diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml index 08e5f42847ae0..92057006c9309 100644 --- a/.cirrus.tasks.yml +++ b/.cirrus.tasks.yml @@ -2,6 +2,12 @@ # # For instructions on how to enable the CI integration in a repository and # further details, see src/tools/ci/README +# +# +# NB: Different tasks intentionally test with different, non-default, +# configurations, to increase the chance of catching problems. Each task with +# non-obvious non-default documents their oddity at the top of the task, +# prefixed by "SPECIAL:". env: @@ -17,10 +23,13 @@ env: CHECK: check-world PROVE_FLAGS=$PROVE_FLAGS CHECKFLAGS: -Otarget PROVE_FLAGS: --timer + # Build test dependencies as part of the build step, to see compiler + # errors/warnings in one place. + MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/src/tools/ci/pg_ci_base.conf - PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance + PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth # What files to preserve in case tests fail @@ -52,6 +61,10 @@ on_failure_meson: &on_failure_meson # To avoid unnecessarily spinning up a lot of VMs / containers for entirely # broken commits, have a minimal task that all others depend on. +# +# SPECIAL: +# - Builds with --auto-features=disabled and thus almost no enabled +# dependencies task: name: SanityCheck @@ -99,7 +112,7 @@ task: EOF build_script: | su postgres <<-EOF - ninja -C build -j${BUILD_JOBS} + ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} EOF upload_caches: ccache @@ -122,20 +135,33 @@ task: src/tools/ci/cores_backtrace.sh linux /tmp/cores +# SPECIAL: +# - Uses postgres specific CPPFLAGS that increase test coverage +# - Specifies configuration options that test reading/writing/copying of node trees +# - Specifies debug_parallel_query=regress, to catch related issues during CI +# - Also runs tests against a running postgres instance, see test_running_script task: - name: FreeBSD - 13 - Meson + name: FreeBSD - Meson env: CPUS: 4 BUILD_JOBS: 4 TEST_JOBS: 8 - IMAGE_FAMILY: pg-ci-freebsd-13 + IMAGE_FAMILY: pg-ci-freebsd DISK_SIZE: 50 CCACHE_DIR: /tmp/ccache_dir - CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DCOPY_PARSE_PLAN_TREES -DWRITE_READ_PARSE_PLAN_TREES -DRAW_EXPRESSION_COVERAGE_TEST -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS + CPPFLAGS: -DRELCACHE_FORCE_RELEASE -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS CFLAGS: -Og -ggdb + # Several buildfarm animals enable these options. Without testing them + # during CI, it would be easy to cause breakage on the buildfarm with CI + # passing. + PG_TEST_INITDB_EXTRA_OPTS: >- + -c debug_copy_parse_plan_trees=on + -c debug_write_read_parse_plan_trees=on + -c debug_raw_expression_coverage_test=on + -c debug_parallel_query=regress PG_TEST_PG_UPGRADE_MODE: --link <<: *freebsd_task_template @@ -151,8 +177,7 @@ task: ccache_cache: folder: $CCACHE_DIR - # Work around performance issues due to 32KB block size - repartition_script: src/tools/ci/gcp_freebsd_repartition.sh + setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh create_user_script: | pw useradd postgres chown -R postgres:postgres . @@ -174,11 +199,10 @@ task: --buildtype=debug \ -Dcassert=true -Dinjection_points=true \ -Duuid=bsd -Dtcl_version=tcl86 -Ddtrace=auto \ - -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \ -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \ build EOF - build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS}' + build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}' upload_caches: ccache test_world_script: | @@ -213,12 +237,120 @@ task: cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores +task: + depends_on: SanityCheck + trigger_type: manual + + env: + # Below are experimentally derived to be a decent choice. + CPUS: 4 + BUILD_JOBS: 8 + TEST_JOBS: 8 + + # Default working directory is /tmp, but its total size (1.2 GB) is not + # enough, so different working and cache directory are set. + CIRRUS_WORKING_DIR: /home/postgres/postgres + CCACHE_DIR: /home/postgres/cache + + PATH: /usr/sbin:$PATH + CORE_DUMP_DIR: /var/crash + + matrix: + - name: NetBSD - Meson + only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*netbsd.*' + env: + OS_NAME: netbsd + IMAGE_FAMILY: pg-ci-netbsd-postgres + PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/pkg/lib/pkgconfig' + # initdb fails with: 'invalid locale settings' error on NetBSD. + # Force 'LANG' and 'LC_*' variables to be 'C'. + # See https://postgr.es/m/2490325.1734471752%40sss.pgh.pa.us + LANG: "C" + LC_ALL: "C" + # -Duuid is not set for the NetBSD, see the comment below, above + # configure_script, for more information. + setup_additional_packages_script: | + #pkgin -y install ... + <<: *netbsd_task_template + + - name: OpenBSD - Meson + only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*openbsd.*' + env: + OS_NAME: openbsd + IMAGE_FAMILY: pg-ci-openbsd-postgres + PKGCONFIG_PATH: '/usr/lib/pkgconfig:/usr/local/lib/pkgconfig' + UUID: -Duuid=e2fs + TCL: -Dtcl_version=tcl86 + setup_additional_packages_script: | + #pkg_add -I ... + # Always core dump to ${CORE_DUMP_DIR} + set_core_dump_script: sysctl -w kern.nosuidcoredump=2 + <<: *openbsd_task_template + + sysinfo_script: | + locale + id + uname -a + ulimit -a -H && ulimit -a -S + env + + ccache_cache: + folder: $CCACHE_DIR + setup_ram_disk_script: src/tools/ci/gcp_ram_disk.sh + create_user_script: | + useradd postgres + chown -R postgres:users /home/postgres + mkdir -p ${CCACHE_DIR} + chown -R postgres:users ${CCACHE_DIR} + setup_core_files_script: | + mkdir -p ${CORE_DUMP_DIR} + chmod -R 770 ${CORE_DUMP_DIR} + chown -R postgres:users ${CORE_DUMP_DIR} + + # -Duuid=bsd is not set since 'bsd' uuid option + # is not working on NetBSD & OpenBSD. See + # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org + # And other uuid options are not available on NetBSD. + configure_script: | + su postgres <<-EOF + meson setup \ + --buildtype=debugoptimized \ + --pkg-config-path ${PKGCONFIG_PATH} \ + -Dcassert=true -Dinjection_points=true \ + -Dssl=openssl ${UUID} ${TCL} \ + -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \ + build + EOF + + build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}' + upload_caches: ccache + + test_world_script: | + su postgres <<-EOF + ulimit -c unlimited + # Otherwise tests will fail on OpenBSD, due to inability to start enough + # processes. + ulimit -p 256 + meson test $MTEST_ARGS --num-processes ${TEST_JOBS} + EOF + + on_failure: + <<: *on_failure_meson + cores_script: | + # Although we try to configure the OS to core dump inside + # ${CORE_DUMP_DIR}, they may not obey this. So, move core files to the + # ${CORE_DUMP_DIR} directory. + find build/ -type f -name '*.core' -exec mv '{}' ${CORE_DUMP_DIR} \; + src/tools/ci/cores_backtrace.sh ${OS_NAME} ${CORE_DUMP_DIR} + + # configure feature flags, shared between the task running the linux tests and # the CompilerWarnings task LINUX_CONFIGURE_FEATURES: &LINUX_CONFIGURE_FEATURES >- --with-gssapi --with-icu --with-ldap + --with-libcurl --with-libxml --with-libxslt --with-llvm @@ -238,6 +370,7 @@ LINUX_MESON_FEATURES: &LINUX_MESON_FEATURES >- -Duuid=e2fs +# Check SPECIAL in the matrix: below task: env: CPUS: 4 @@ -316,10 +449,15 @@ task: #DEBIAN_FRONTEND=noninteractive apt-get -y install ... matrix: + # SPECIAL: + # - Uses address sanitizer, sanitizer failures are typically printed in + # the server log + # - Configures postgres with a small segment size - name: Linux - Debian Bookworm - Autoconf env: SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range # Normally, the "relation segment" code basically has no coverage in our # tests, because we (quite reasonably) don't generate tables large @@ -333,6 +471,8 @@ task: --enable-cassert --enable-injection-points --enable-debug \ --enable-tap-tests --enable-nls \ --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ \ ${LINUX_CONFIGURE_FEATURES} \ \ @@ -350,11 +490,18 @@ task: on_failure: <<: *on_failure_ac + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, sanitizer failures + # are typically printed in the server log + # - Test both 64bit and 32 bit builds + # - uses io_method=io_uring - name: Linux - Debian Bookworm - Meson env: CCACHE_MAXSIZE: "400M" # tests two different builds SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: >- + -c io_method=io_uring configure_script: | su postgres <<-EOF @@ -362,7 +509,6 @@ task: --buildtype=debug \ -Dcassert=true -Dinjection_points=true \ ${LINUX_MESON_FEATURES} \ - -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \ build EOF @@ -378,12 +524,21 @@ task: -Dllvm=disabled \ --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ -DPERL=perl5.36-i386-linux-gnu \ - -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \ + -Dlibnuma=disabled \ build-32 EOF - build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS}' - build_32_script: su postgres -c 'ninja -C build-32 -j${BUILD_JOBS}' + build_script: | + su postgres <<-EOF + ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + ninja -C build -t missingdeps + EOF + + build_32_script: | + su postgres <<-EOF + ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET} + ninja -C build -t missingdeps + EOF upload_caches: ccache @@ -412,6 +567,11 @@ task: cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores +# NB: macOS is by far the most expensive OS to run CI for, therefore no +# expensive additional checks should be added. +# +# SPECIAL: +# - Enables --clone for pg_upgrade and pg_combinebackup task: name: macOS - Sonoma - Meson @@ -428,12 +588,27 @@ task: CCACHE_DIR: ${HOME}/ccache MACPORTS_CACHE: ${HOME}/macports-cache + MACOS_PACKAGE_LIST: >- + ccache + icu + kerberos5 + lz4 + meson + openldap + openssl + p5.34-io-tty + p5.34-ipc-run + python312 + tcl + zstd + CC: ccache cc CXX: ccache c++ CFLAGS: -Og -ggdb CXXFLAGS: -Og -ggdb PG_TEST_PG_UPGRADE_MODE: --clone + PG_TEST_PG_COMBINEBACKUP_MODE: --clone <<: *macos_task_template @@ -463,26 +638,14 @@ task: macports_cache: folder: ${MACPORTS_CACHE} fingerprint_script: | - # Include the OS major version in the cache key. If the OS image changes - # to a different major version, we need to reinstall. + # Reinstall packages if the OS major version, the list of the packages + # to install or the MacPorts install script changes. sw_vers -productVersion | sed 's/\..*//' - # Also start afresh if we change our MacPorts install script. + echo $MACOS_PACKAGE_LIST md5 src/tools/ci/ci_macports_packages.sh reupload_on_changes: true setup_additional_packages_script: | - sh src/tools/ci/ci_macports_packages.sh \ - ccache \ - icu \ - kerberos5 \ - lz4 \ - meson \ - openldap \ - openssl \ - p5.34-io-tty \ - p5.34-ipc-run \ - python312 \ - tcl \ - zstd + sh src/tools/ci/ci_macports_packages.sh $MACOS_PACKAGE_LIST # system python doesn't provide headers sudo /opt/local/bin/port select python3 python312 # Make macports install visible for subsequent steps @@ -499,10 +662,9 @@ task: -Dextra_lib_dirs=/opt/local/lib \ -Dcassert=true -Dinjection_points=true \ -Duuid=e2fs -Ddtrace=auto \ - -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \ build - build_script: ninja -C build -j${BUILD_JOBS} + build_script: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} upload_caches: ccache test_world_script: | @@ -571,11 +733,12 @@ task: # Use /DEBUG:FASTLINK to avoid high memory usage during linking configure_script: | vcvarsall x64 - meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Dinjection_points=true -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build + meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Dinjection_points=true -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% build build_script: | vcvarsall x64 - ninja -C build + ninja -C build %MBUILD_TARGET% + ninja -C build -t missingdeps check_world_script: | vcvarsall x64 @@ -633,7 +796,7 @@ task: %BASH% -c "meson setup -Ddebug=true -Doptimization=g -Dcassert=true -Dinjection_points=true -Db_pch=true -Dnls=disabled -DTAR=%TAR% build" build_script: | - %BASH% -c "ninja -C build" + %BASH% -c "ninja -C build ${MBUILD_TARGET}" upload_caches: ccache diff --git a/.cirrus.yml b/.cirrus.yml index a83129ae46d1e..33c6e481d746a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -52,6 +52,16 @@ default_freebsd_task_template: &freebsd_task_template PLATFORM: freebsd <<: *cirrus_community_vm_template +default_netbsd_task_template: &netbsd_task_template + env: + PLATFORM: netbsd + <<: *cirrus_community_vm_template + +default_openbsd_task_template: &openbsd_task_template + env: + PLATFORM: openbsd + <<: *cirrus_community_vm_template + default_windows_task_template: &windows_task_template env: diff --git a/.editorconfig b/.editorconfig index d69a3d1dc4e0a..e20d15d4533a4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,14 +1,176 @@ root = true -[*.{c,h,l,y,pl,pm}] -indent_style = tab +[*] indent_size = tab + +[*] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = unset +tab_width = unset + +[*.[chly]] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tab +tab_width = 4 + +[*.cpp] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tab +tab_width = 4 + +[*.pl] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tab tab_width = 4 -[*.{sgml,xml}] +[*.pm] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tab +tab_width = 4 + +[*.po] +trim_trailing_whitespace = true +insert_final_newline = unset +indent_style = space +tab_width = unset + +[*.py] +trim_trailing_whitespace = true +insert_final_newline = true indent_style = space +tab_width = unset +indent_size = 4 + +[*.sgml] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +tab_width = unset indent_size = 1 -[*.xsl] +[*.xml] +trim_trailing_whitespace = true +insert_final_newline = true indent_style = space +tab_width = unset indent_size = 2 + +[*.xsl] +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +tab_width = unset +indent_size = 1 + +[*.data] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[contrib/pgcrypto/sql/pgp-armor.sql] +trim_trailing_whitespace = unset +insert_final_newline = true +indent_style = unset +tab_width = unset + +[src/backend/catalog/sql_features.txt] +trim_trailing_whitespace = unset +insert_final_newline = true +indent_style = unset +tab_width = unset + +[*.out] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/interfaces/ecpg/test/expected/*] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[configure] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[ppport.h] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/backend/jit/llvm/SectionMemoryManager.cpp] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/backend/jit/llvm/SectionMemoryManager.LICENSE] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/backend/regex/COPYRIGHT] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/backend/snowball/libstemmer/*.c] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/backend/utils/mb/Unicode/*-std.txt] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/include/jit/SectionMemoryManager.h] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/include/snowball/libstemmer/*] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/timezone/data/*] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/tools/pg_bsd_indent/*] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/tools/pg_bsd_indent/tests/*] +indent_style = unset +indent_size = unset +trim_trailing_whitespace = unset +insert_final_newline = unset + +[src/tools/pg_bsd_indent/*.[ch]] +trim_trailing_whitespace = unset +insert_final_newline = unset +indent_style = unset +tab_width = 8 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 7b701089337c1..8048afd1a80fa 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -14,6 +14,60 @@ # # $ git log --pretty=format:"%H # %cd%n# %s" $PGINDENTGITHASH -1 --date=iso +b27644bade0348d0dafd3036c47880a349fe9332 # 2025-06-15 13:04:24 -0400 +# Sync typedefs.list with the buildfarm. + +4672b6223910687b2aab075bcd2dd54ce90d5171 # 2025-06-01 14:55:24 -0400 +# Run pgindent on the previous commit. + +918e7287ed20eb1fe280ab6c4056ccf94dcd53a8 # 2025-04-30 19:18:30 +1200 +# Fix broken indentation + +e1a8b1ad587112e67fdc5aa7b388631dde4dbdda # 2025-04-04 09:38:22 -0500 +# Re-pgindent pg_largeobject.c after commit 0d6c477664. + +796bdda484c838313959f65e2b700f14ac7c0e66 # 2025-03-18 09:02:36 -0400 +# Fix indentation again. + +203c1b4cc49455364b6bcab8034900d1c016b9cd # 2025-03-17 16:06:17 -0400 +# Fix indentation. + +b955df443405e056fd9047ef819a1465654f9d79 # 2025-03-13 12:41:44 +1300 +# Fix indentation issue + +76aa615943049c04efd36ab4765c06eda89cdfea # 2025-01-31 16:44:24 +0900 +# Fix bad indentation introduced in commit d47cbf474 + +6e826278f1ebd9967c0f8adda29c8960a812e344 # 2025-01-13 11:27:32 +0900 +# Fix pgindent damage + +301de6a6f609cb3ad2d9d31fd8db9ae6c71e6dea # 2024-12-25 17:55:42 +0100 +# Partial pgindent of .l and .y files + +53dcba9be5746cc126bdb949bf81c29ea2cfc24d # 2024-11-21 21:40:17 +0100 +# pgindent run + +a7f2f6adc240a2823c2344b89e90bb630dea8803 # 2024-10-16 12:21:13 -0700 +# Whitespace fixup from generated unicode tables. + +7f7474a8e4002ac9fd4979cc7b16b50b70b70c28 # 2024-09-27 11:14:31 -0400 +# Reindent pg_verifybackup.c. + +7229ebe011dff3f418251a4836f6d098923aa1e1 # 2024-08-26 16:16:12 -0700 +# Fix identation. + +2b03cfeea47834913ff769124f4deba88140f662 # 2024-08-21 09:58:11 -0400 +# Fix pgindent damage + +97add39c038bbdb9082b416ddf04cd20b0d20bf5 # 2024-08-15 11:41:46 -0400 +# Clean up indentation and whitespace inconsistencies in ecpg. + +8de5ca1dc9fa809102acd1983ee19159d0bc469f # 2024-08-12 10:57:03 +0300 +# Fix bad indentation introduced in commit f011e82c2c + +c883453cb29cb40c1e59c3c54d159c5e744da8a9 # 2024-07-26 12:00:04 -0400 +# Fix indentation. + 47ecbfdfcc71e41d7dcc35f0be04f8adbe88397f # 2024-07-15 15:17:04 -0700 # Fix bad indentation introduced in 43cd30bcd1c diff --git a/.gitattributes b/.gitattributes index e9ff4a56bd250..8df6b75e653b8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,15 @@ +# IMPORTANT: After updating this file, also run src/tools/generate_editorconfig.py + * whitespace=space-before-tab,trailing-space *.[chly] whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4 +*.cpp whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4 *.pl whitespace=space-before-tab,trailing-space,tabwidth=4 *.pm whitespace=space-before-tab,trailing-space,tabwidth=4 *.po whitespace=space-before-tab,trailing-space,tab-in-indent,-blank-at-eof +*.py whitespace=space-before-tab,trailing-space,tab-in-indent *.sgml whitespace=space-before-tab,trailing-space,tab-in-indent -*.x[ms]l whitespace=space-before-tab,trailing-space,tab-in-indent +*.xml whitespace=space-before-tab,trailing-space,tab-in-indent +*.xsl whitespace=space-before-tab,trailing-space,tab-in-indent # Avoid confusing ASCII underlines with leftover merge conflict markers README conflict-marker-size=32 @@ -22,10 +27,14 @@ src/interfaces/ecpg/test/expected/* -whitespace # These files are maintained or generated elsewhere. We take them as is. configure -whitespace ppport.h -whitespace +src/backend/jit/llvm/SectionMemoryManager.cpp -whitespace +src/backend/jit/llvm/SectionMemoryManager.LICENSE -whitespace src/backend/regex/COPYRIGHT -whitespace src/backend/snowball/libstemmer/*.c -whitespace src/backend/utils/mb/Unicode/*-std.txt -whitespace +src/include/jit/SectionMemoryManager.h -whitespace src/include/snowball/libstemmer/* -whitespace src/timezone/data/* -whitespace src/tools/pg_bsd_indent/* -whitespace src/tools/pg_bsd_indent/tests/* -whitespace +src/tools/pg_bsd_indent/*.[ch] whitespace=-blank-at-eol,-blank-at-eof,tabwidth=8 diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000000..22d95d34847a7 --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Álvaro Herrera diff --git a/COPYRIGHT b/COPYRIGHT index 16f9b46a3fe1b..3b79b1b4ca0db 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ PostgreSQL Database Management System -(formerly known as Postgres, then as Postgres95) +(also known as Postgres, formerly known as Postgres95) -Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of California diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 10f8c7bd0a9fb..5f3e1d1faf930 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -38,60 +38,6 @@ ac_c_werror_flag=$ac_save_c_werror_flag ])# PGAC_TEST_PRINTF_ARCHETYPE -# PGAC_TYPE_64BIT_INT(TYPE) -# ------------------------- -# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to -# yes or no respectively, and define HAVE_TYPE_64 if yes. -AC_DEFUN([PGAC_TYPE_64BIT_INT], -[define([Ac_define], [translit([have_$1_64], [a-z *], [A-Z_P])])dnl -define([Ac_cachevar], [translit([pgac_cv_type_$1_64], [ *], [_p])])dnl -AC_CACHE_CHECK([whether $1 is 64 bits], [Ac_cachevar], -[AC_RUN_IFELSE([AC_LANG_SOURCE( -[typedef $1 ac_int64; - -/* - * These are globals to discourage the compiler from folding all the - * arithmetic tests down to compile-time constants. - */ -ac_int64 a = 20000001; -ac_int64 b = 40000005; - -int does_int64_work() -{ - ac_int64 c,d; - - if (sizeof(ac_int64) != 8) - return 0; /* definitely not the right size */ - - /* Do perfunctory checks to see if 64-bit arithmetic seems to work */ - c = a * b; - d = (c + b) / b; - if (d != a+1) - return 0; - return 1; -} - -int -main() { - return (! does_int64_work()); -}])], -[Ac_cachevar=yes], -[Ac_cachevar=no], -[# If cross-compiling, check the size reported by the compiler and -# trust that the arithmetic works. -AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([], [sizeof($1) == 8])], - Ac_cachevar=yes, - Ac_cachevar=no)])]) - -Ac_define=$Ac_cachevar -if test x"$Ac_cachevar" = xyes ; then - AC_DEFINE(Ac_define, 1, [Define to 1 if `]$1[' works and is 64 bits.]) -fi -undefine([Ac_define])dnl -undefine([Ac_cachevar])dnl -])# PGAC_TYPE_64BIT_INT - - # PGAC_TYPE_128BIT_INT # -------------------- # Check if __int128 is a working 128 bit integer type, and if so @@ -196,7 +142,7 @@ fi])# PGAC_C_STATIC_ASSERT AC_DEFUN([PGAC_C_TYPEOF], [AC_CACHE_CHECK(for typeof, pgac_cv_c_typeof, [pgac_cv_c_typeof=no -for pgac_kw in typeof __typeof__ decltype; do +for pgac_kw in typeof __typeof__; do AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [int x = 0; $pgac_kw(x) y; @@ -270,9 +216,10 @@ fi])# PGAC_C_BUILTIN_CONSTANT_P AC_DEFUN([PGAC_C_BUILTIN_OP_OVERFLOW], [AC_CACHE_CHECK(for __builtin_mul_overflow, pgac_cv__builtin_op_overflow, [AC_LINK_IFELSE([AC_LANG_PROGRAM([ -PG_INT64_TYPE a = 1; -PG_INT64_TYPE b = 1; -PG_INT64_TYPE result; +#include +int64_t a = 1; +int64_t b = 1; +int64_t result; int oflo; ], [oflo = __builtin_mul_overflow(a, b, &result);])], @@ -557,13 +504,13 @@ fi])# PGAC_HAVE_GCC__SYNC_INT32_CAS # types, and define HAVE_GCC__SYNC_INT64_CAS if so. AC_DEFUN([PGAC_HAVE_GCC__SYNC_INT64_CAS], [AC_CACHE_CHECK(for builtin __sync int64 atomic operations, pgac_cv_gcc_sync_int64_cas, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([], - [PG_INT64_TYPE lock = 0; - __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37);])], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int64_t lock = 0; + __sync_val_compare_and_swap(&lock, 0, (int64_t) 37);])], [pgac_cv_gcc_sync_int64_cas="yes"], [pgac_cv_gcc_sync_int64_cas="no"])]) if test x"$pgac_cv_gcc_sync_int64_cas" = x"yes"; then - AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).]) + AC_DEFINE(HAVE_GCC__SYNC_INT64_CAS, 1, [Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t, int64_t).]) fi])# PGAC_HAVE_GCC__SYNC_INT64_CAS # PGAC_HAVE_GCC__ATOMIC_INT32_CAS @@ -588,9 +535,9 @@ fi])# PGAC_HAVE_GCC__ATOMIC_INT32_CAS # types, and define HAVE_GCC__ATOMIC_INT64_CAS if so. AC_DEFUN([PGAC_HAVE_GCC__ATOMIC_INT64_CAS], [AC_CACHE_CHECK(for builtin __atomic int64 atomic operations, pgac_cv_gcc_atomic_int64_cas, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([], - [PG_INT64_TYPE val = 0; - PG_INT64_TYPE expect = 0; +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int64_t val = 0; + int64_t expect = 0; __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);])], [pgac_cv_gcc_atomic_int64_cas="yes"], [pgac_cv_gcc_atomic_int64_cas="no"])]) @@ -605,29 +552,72 @@ fi])# PGAC_HAVE_GCC__ATOMIC_INT64_CAS # test the 8-byte variant, _mm_crc32_u64, but it is assumed to be present if # the other ones are, on x86-64 platforms) # -# An optional compiler flag can be passed as argument (e.g. -msse4.2). If the -# intrinsics are supported, sets pgac_sse42_crc32_intrinsics, and CFLAGS_CRC. +# If the intrinsics are supported, sets pgac_sse42_crc32_intrinsics. +# +# To detect the case where the compiler knows the function but library support +# is missing, we must link not just compile, and store the results in global +# variables so the compiler doesn't optimize away the call. AC_DEFUN([PGAC_SSE42_CRC32_INTRINSICS], -[define([Ac_cachevar], [AS_TR_SH([pgac_cv_sse42_crc32_intrinsics_$1])])dnl -AC_CACHE_CHECK([for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=$1], [Ac_cachevar], -[pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS $1" -AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [unsigned int crc = 0; - crc = _mm_crc32_u8(crc, 0); - crc = _mm_crc32_u32(crc, 0); - /* return computed value, to prevent the above being optimized away */ - return crc == 0;])], +[define([Ac_cachevar], [AS_TR_SH([pgac_cv_sse42_crc32_intrinsics])])dnl +AC_CACHE_CHECK([for _mm_crc32_u8 and _mm_crc32_u32], [Ac_cachevar], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + unsigned int crc; + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("sse4.2"))) + #endif + static int crc32_sse42_test(void) + { + crc = _mm_crc32_u8(crc, 0); + crc = _mm_crc32_u32(crc, 0); + /* return computed value, to prevent the above being optimized away */ + return crc == 0; + }], + [return crc32_sse42_test();])], [Ac_cachevar=yes], - [Ac_cachevar=no]) -CFLAGS="$pgac_save_CFLAGS"]) + [Ac_cachevar=no])]) if test x"$Ac_cachevar" = x"yes"; then - CFLAGS_CRC="$1" pgac_sse42_crc32_intrinsics=yes fi undefine([Ac_cachevar])dnl ])# PGAC_SSE42_CRC32_INTRINSICS +# PGAC_AVX512_PCLMUL_INTRINSICS +# --------------------------- +# Check if the compiler supports AVX-512 carryless multiplication +# and three-way exclusive-or instructions used for computing CRC. +# AVX-512F is assumed to be supported if the above are. +# +# If the intrinsics are supported, sets pgac_avx512_pclmul_intrinsics. +AC_DEFUN([PGAC_AVX512_PCLMUL_INTRINSICS], +[define([Ac_cachevar], [AS_TR_SH([pgac_cv_avx512_pclmul_intrinsics])])dnl +AC_CACHE_CHECK([for _mm512_clmulepi64_epi128], [Ac_cachevar], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + __m512i x; + __m512i y; + + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("vpclmulqdq,avx512vl"))) + #endif + static int avx512_pclmul_test(void) + { + __m128i z; + + y = _mm512_clmulepi64_epi128(x, y, 0); + z = _mm_ternarylogic_epi64( + _mm512_castsi512_si128(y), + _mm512_extracti32x4_epi32(y, 1), + _mm512_extracti32x4_epi32(y, 2), + 0x96); + return _mm_crc32_u64(0, _mm_extract_epi64(z, 0)); + }], + [return avx512_pclmul_test();])], + [Ac_cachevar=yes], + [Ac_cachevar=no])]) +if test x"$Ac_cachevar" = x"yes"; then + pgac_avx512_pclmul_intrinsics=yes +fi +undefine([Ac_cachevar])dnl +])# PGAC_AVX512_PCLMUL_INTRINSICS # PGAC_ARMV8_CRC32C_INTRINSICS # ---------------------------- @@ -644,9 +634,9 @@ AC_DEFUN([PGAC_ARMV8_CRC32C_INTRINSICS], AC_CACHE_CHECK([for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=$1], [Ac_cachevar], [pgac_save_CFLAGS=$CFLAGS CFLAGS="$pgac_save_CFLAGS $1" -AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [unsigned int crc = 0; - crc = __crc32cb(crc, 0); +AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +unsigned int crc;], + [crc = __crc32cb(crc, 0); crc = __crc32ch(crc, 0); crc = __crc32cw(crc, 0); crc = __crc32cd(crc, 0); @@ -679,9 +669,8 @@ AC_DEFUN([PGAC_LOONGARCH_CRC32C_INTRINSICS], AC_CACHE_CHECK( [for __builtin_loongarch_crcc_w_b_w, __builtin_loongarch_crcc_w_h_w, __builtin_loongarch_crcc_w_w_w and __builtin_loongarch_crcc_w_d_w], [Ac_cachevar], -[AC_LINK_IFELSE([AC_LANG_PROGRAM([], - [unsigned int crc = 0; - crc = __builtin_loongarch_crcc_w_b_w(0, crc); +[AC_LINK_IFELSE([AC_LANG_PROGRAM([unsigned int crc;], + [crc = __builtin_loongarch_crcc_w_b_w(0, crc); crc = __builtin_loongarch_crcc_w_h_w(0, crc); crc = __builtin_loongarch_crcc_w_w_w(0, crc); crc = __builtin_loongarch_crcc_w_d_w(0, crc); @@ -700,20 +689,22 @@ undefine([Ac_cachevar])dnl # Check if the compiler supports the XSAVE instructions using the _xgetbv # intrinsic function. # -# An optional compiler flag can be passed as argument (e.g., -mxsave). If the -# intrinsic is supported, sets pgac_xsave_intrinsics and CFLAGS_XSAVE. +# If the intrinsics are supported, sets pgac_xsave_intrinsics. AC_DEFUN([PGAC_XSAVE_INTRINSICS], -[define([Ac_cachevar], [AS_TR_SH([pgac_cv_xsave_intrinsics_$1])])dnl -AC_CACHE_CHECK([for _xgetbv with CFLAGS=$1], [Ac_cachevar], -[pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS $1" -AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [return _xgetbv(0) & 0xe0;])], +[define([Ac_cachevar], [AS_TR_SH([pgac_cv_xsave_intrinsics])])dnl +AC_CACHE_CHECK([for _xgetbv], [Ac_cachevar], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([#include + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("xsave"))) + #endif + static int xsave_test(void) + { + return _xgetbv(0) & 0xe0; + }], + [return xsave_test();])], [Ac_cachevar=yes], - [Ac_cachevar=no]) -CFLAGS="$pgac_save_CFLAGS"]) + [Ac_cachevar=no])]) if test x"$Ac_cachevar" = x"yes"; then - CFLAGS_XSAVE="$1" pgac_xsave_intrinsics=yes fi undefine([Ac_cachevar])dnl @@ -725,30 +716,84 @@ undefine([Ac_cachevar])dnl # _mm512_setzero_si512, _mm512_maskz_loadu_epi8, _mm512_popcnt_epi64, # _mm512_add_epi64, and _mm512_reduce_add_epi64 intrinsic functions. # -# Optional compiler flags can be passed as argument (e.g., -mavx512vpopcntdq -# -mavx512bw). If the intrinsics are supported, sets -# pgac_avx512_popcnt_intrinsics and CFLAGS_POPCNT. +# If the intrinsics are supported, sets pgac_avx512_popcnt_intrinsics. AC_DEFUN([PGAC_AVX512_POPCNT_INTRINSICS], -[define([Ac_cachevar], [AS_TR_SH([pgac_cv_avx512_popcnt_intrinsics_$1])])dnl -AC_CACHE_CHECK([for _mm512_popcnt_epi64 with CFLAGS=$1], [Ac_cachevar], -[pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS $1" -AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [const char buf@<:@sizeof(__m512i)@:>@; - PG_INT64_TYPE popcnt = 0; - __m512i accum = _mm512_setzero_si512(); - const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); - const __m512i cnt = _mm512_popcnt_epi64(val); - accum = _mm512_add_epi64(accum, cnt); - popcnt = _mm512_reduce_add_epi64(accum); - /* return computed value, to prevent the above being optimized away */ - return popcnt == 0;])], +[define([Ac_cachevar], [AS_TR_SH([pgac_cv_avx512_popcnt_intrinsics])])dnl +AC_CACHE_CHECK([for _mm512_popcnt_epi64], [Ac_cachevar], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include + #include + char buf[sizeof(__m512i)]; + + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("avx512vpopcntdq,avx512bw"))) + #endif + static int popcount_test(void) + { + int64_t popcnt = 0; + __m512i accum = _mm512_setzero_si512(); + __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); + __m512i cnt = _mm512_popcnt_epi64(val); + accum = _mm512_add_epi64(accum, cnt); + popcnt = _mm512_reduce_add_epi64(accum); + return (int) popcnt; + }]], + [return popcount_test();])], [Ac_cachevar=yes], - [Ac_cachevar=no]) -CFLAGS="$pgac_save_CFLAGS"]) + [Ac_cachevar=no])]) if test x"$Ac_cachevar" = x"yes"; then - CFLAGS_POPCNT="$1" pgac_avx512_popcnt_intrinsics=yes fi undefine([Ac_cachevar])dnl ])# PGAC_AVX512_POPCNT_INTRINSICS + +# PGAC_SVE_POPCNT_INTRINSICS +# -------------------------- +# Check if the compiler supports the SVE popcount instructions using the +# svptrue_b64, svdup_u64, svcntb, svld1_u64, svld1_u8, svadd_u64_x, +# svcnt_u64_x, svcnt_u8_x, svaddv_u64, svaddv_u8, svwhilelt_b8_s32, +# svand_n_u64_x, and svand_n_u8_x intrinsic functions. +# +# If the intrinsics are supported, sets pgac_sve_popcnt_intrinsics. +AC_DEFUN([PGAC_SVE_POPCNT_INTRINSICS], +[define([Ac_cachevar], [AS_TR_SH([pgac_cv_sve_popcnt_intrinsics])])dnl +AC_CACHE_CHECK([for svcnt_x], [Ac_cachevar], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include + + char buf[128]; + + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("arch=armv8-a+sve"))) + #endif + static int popcount_test(void) + { + svbool_t pred = svptrue_b64(); + svuint8_t vec8; + svuint64_t accum1 = svdup_u64(0), + accum2 = svdup_u64(0), + vec64; + char *p = buf; + uint64_t popcnt, + mask = 0x5555555555555555; + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + popcnt = svaddv_u64(pred, svadd_u64_x(pred, accum1, accum2)); + + pred = svwhilelt_b8_s32(0, sizeof(buf)); + vec8 = svand_n_u8_x(pred, svld1_u8(pred, (const uint8_t *) p), 0x55); + return (int) (popcnt + svaddv_u8(pred, svcnt_u8_x(pred, vec8))); + }]], + [return popcount_test();])], + [Ac_cachevar=yes], + [Ac_cachevar=no])]) +if test x"$Ac_cachevar" = x"yes"; then + pgac_sve_popcnt_intrinsics=yes +fi +undefine([Ac_cachevar])dnl +])# PGAC_SVE_POPCNT_INTRINSICS diff --git a/config/c-library.m4 b/config/c-library.m4 index aa8223d2ef0e9..421bc612b272a 100644 --- a/config/c-library.m4 +++ b/config/c-library.m4 @@ -81,58 +81,3 @@ AC_DEFUN([PGAC_STRUCT_SOCKADDR_SA_LEN], [#include #include ])])# PGAC_STRUCT_SOCKADDR_MEMBERS - - -# PGAC_TYPE_LOCALE_T -# ------------------ -# Check for the locale_t type and find the right header file. macOS -# needs xlocale.h; standard is locale.h, but glibc <= 2.25 also had an -# xlocale.h file that we should not use, so we check the standard -# header first. -AC_DEFUN([PGAC_TYPE_LOCALE_T], -[AC_CACHE_CHECK([for locale_t], pgac_cv_type_locale_t, -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[#include -locale_t x;], -[])], -[pgac_cv_type_locale_t=yes], -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[#include -locale_t x;], -[])], -[pgac_cv_type_locale_t='yes (in xlocale.h)'], -[pgac_cv_type_locale_t=no])])]) -if test "$pgac_cv_type_locale_t" = 'yes (in xlocale.h)'; then - AC_DEFINE(LOCALE_T_IN_XLOCALE, 1, - [Define to 1 if `locale_t' requires .]) -fi])# PGAC_TYPE_LOCALE_T - - -# PGAC_FUNC_WCSTOMBS_L -# -------------------- -# Try to find a declaration for wcstombs_l(). It might be in stdlib.h -# (following the POSIX requirement for wcstombs()), or in locale.h, or in -# xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE. -# -AC_DEFUN([PGAC_FUNC_WCSTOMBS_L], -[AC_CACHE_CHECK([for wcstombs_l declaration], pgac_cv_func_wcstombs_l, -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[#include -#include ], -[#ifndef wcstombs_l -(void) wcstombs_l; -#endif])], -[pgac_cv_func_wcstombs_l='yes'], -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[#include -#include -#include ], -[#ifndef wcstombs_l -(void) wcstombs_l; -#endif])], -[pgac_cv_func_wcstombs_l='yes (in xlocale.h)'], -[pgac_cv_func_wcstombs_l='no'])])]) -if test "$pgac_cv_func_wcstombs_l" = 'yes (in xlocale.h)'; then - AC_DEFINE(WCSTOMBS_L_IN_XLOCALE, 1, - [Define to 1 if `wcstombs_l' requires .]) -fi])# PGAC_FUNC_WCSTOMBS_L diff --git a/config/check_modules.pl b/config/check_modules.pl index b605634e073b9..f3b48a62347c0 100644 --- a/config/check_modules.pl +++ b/config/check_modules.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # # Verify that required Perl modules are available, diff --git a/config/config.guess b/config/config.guess index f6d217a49f8f4..48a684601bd23 100644 --- a/config/config.guess +++ b/config/config.guess @@ -4,7 +4,7 @@ # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2024-01-01' +timestamp='2024-07-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -123,7 +123,7 @@ set_cc_for_build() { dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" - for driver in cc gcc c89 c99 ; do + for driver in cc gcc c17 c99 c89 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver break @@ -634,7 +634,8 @@ EOF sed 's/^ //' << EOF > "$dummy.c" #include - main() + int + main () { if (!__power_pc()) exit(1); @@ -718,7 +719,8 @@ EOF #include #include - int main () + int + main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); @@ -1621,6 +1623,7 @@ cat > "$dummy.c" <&2 exit 1 ;; - kfreebsd*-gnu*- | kopensolaris*-gnu*-) + kfreebsd*-gnu*- | knetbsd*-gnu*- | netbsd*-gnu*- | kopensolaris*-gnu*-) ;; vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) ;; @@ -1864,6 +2245,8 @@ case $kernel-$os-$obj in ;; os2-emx-) ;; + rtmk-nova-) + ;; *-eabi*- | *-gnueabi*-) ;; none--*) @@ -1890,7 +2273,7 @@ case $vendor in *-riscix*) vendor=acorn ;; - *-sunos*) + *-sunos* | *-solaris*) vendor=sun ;; *-cnk* | *-aix*) diff --git a/config/llvm.m4 b/config/llvm.m4 index c6cf8858f645e..fa4bedd9370fc 100644 --- a/config/llvm.m4 +++ b/config/llvm.m4 @@ -25,8 +25,8 @@ AC_DEFUN([PGAC_LLVM_SUPPORT], AC_MSG_ERROR([$LLVM_CONFIG does not work]) fi # and whether the version is supported - if echo $pgac_llvm_version | $AWK -F '.' '{ if ([$]1 >= 10) exit 1; else exit 0;}';then - AC_MSG_ERROR([$LLVM_CONFIG version is $pgac_llvm_version but at least 10 is required]) + if echo $pgac_llvm_version | $AWK -F '.' '{ if ([$]1 >= 14) exit 1; else exit 0;}';then + AC_MSG_ERROR([$LLVM_CONFIG version is $pgac_llvm_version but at least 14 is required]) fi AC_MSG_NOTICE([using llvm $pgac_llvm_version]) diff --git a/config/programs.m4 b/config/programs.m4 index 490ec9fe9f5d8..0ad1e58b48d6b 100644 --- a/config/programs.m4 +++ b/config/programs.m4 @@ -59,57 +59,16 @@ AC_SUBST(BISONFLAGS) # PGAC_PATH_FLEX # -------------- # Look for Flex, set the output variable FLEX to its path if found. -# Reject versions before 2.5.35 (the earliest version in the buildfarm -# as of 2022). Also find Flex if its installed under `lex', but do not -# accept other Lex programs. AC_DEFUN([PGAC_PATH_FLEX], -[AC_CACHE_CHECK([for flex], pgac_cv_path_flex, -[# Let the user override the test -if test -n "$FLEX"; then - pgac_cv_path_flex=$FLEX -else - pgac_save_IFS=$IFS - IFS=$PATH_SEPARATOR - for pgac_dir in $PATH; do - IFS=$pgac_save_IFS - if test -z "$pgac_dir" || test x"$pgac_dir" = x"."; then - pgac_dir=`pwd` - fi - for pgac_prog in flex lex; do - pgac_candidate="$pgac_dir/$pgac_prog" - if test -f "$pgac_candidate" \ - && $pgac_candidate --version /dev/null 2>&1 - then - echo '%%' > conftest.l - if $pgac_candidate -t conftest.l 2>/dev/null | grep FLEX_SCANNER >/dev/null 2>&1; then - pgac_flex_version=`$pgac_candidate --version 2>/dev/null` - if echo "$pgac_flex_version" | sed ['s/[.a-z]/ /g'] | $AWK '{ if ([$]1 == 2 && ([$]2 > 5 || ([$]2 == 5 && [$]3 >= 35))) exit 0; else exit 1;}' - then - pgac_cv_path_flex=$pgac_candidate - break 2 - else - AC_MSG_ERROR([ -*** The installed version of Flex, $pgac_candidate, is too old to use with PostgreSQL. -*** Flex version 2.5.35 or later is required, but this is $pgac_flex_version.]) - fi - fi - fi - done - done - rm -f conftest.l lex.yy.c - : ${pgac_cv_path_flex=no} -fi -])[]dnl AC_CACHE_CHECK - -if test x"$pgac_cv_path_flex" = x"no"; then +[PGAC_PATH_PROGS(FLEX, flex) +if test -z "$FLEX"; then AC_MSG_ERROR([flex not found]) -else - FLEX=$pgac_cv_path_flex - pgac_flex_version=`$FLEX --version 2>/dev/null` - AC_MSG_NOTICE([using $pgac_flex_version]) fi +pgac_flex_version=`$FLEX --version 2>/dev/null` +AC_MSG_NOTICE([using $pgac_flex_version]) + AC_SUBST(FLEX) AC_SUBST(FLEXFLAGS) ])# PGAC_PATH_FLEX @@ -315,3 +274,83 @@ AC_DEFUN([PGAC_CHECK_STRIP], AC_SUBST(STRIP_STATIC_LIB) AC_SUBST(STRIP_SHARED_LIB) ])# PGAC_CHECK_STRIP + + + +# PGAC_CHECK_LIBCURL +# ------------------ +# Check for required libraries and headers, and test to see whether the current +# installation of libcurl is thread-safe. + +AC_DEFUN([PGAC_CHECK_LIBCURL], +[ + AC_CHECK_HEADER(curl/curl.h, [], + [AC_MSG_ERROR([header file is required for --with-libcurl])]) + AC_CHECK_LIB(curl, curl_multi_init, [ + AC_DEFINE([HAVE_LIBCURL], [1], [Define to 1 if you have the `curl' library (-lcurl).]) + AC_SUBST(LIBCURL_LDLIBS, -lcurl) + ], + [AC_MSG_ERROR([library 'curl' does not provide curl_multi_init])]) + + pgac_save_CPPFLAGS=$CPPFLAGS + pgac_save_LDFLAGS=$LDFLAGS + pgac_save_LIBS=$LIBS + + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + LDFLAGS="$LIBCURL_LDFLAGS $LDFLAGS" + LIBS="$LIBCURL_LDLIBS $LIBS" + + # Check to see whether the current platform supports threadsafe Curl + # initialization. + AC_CACHE_CHECK([for curl_global_init thread safety], [pgac_cv__libcurl_threadsafe_init], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([ +#include +],[ + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); +#ifdef CURL_VERSION_THREADSAFE + if (info->features & CURL_VERSION_THREADSAFE) + return 0; +#endif + + return 1; +])], + [pgac_cv__libcurl_threadsafe_init=yes], + [pgac_cv__libcurl_threadsafe_init=no], + [pgac_cv__libcurl_threadsafe_init=unknown])]) + if test x"$pgac_cv__libcurl_threadsafe_init" = xyes ; then + AC_DEFINE(HAVE_THREADSAFE_CURL_GLOBAL_INIT, 1, + [Define to 1 if curl_global_init() is guaranteed to be thread-safe.]) + fi + + # Fail if a thread-friendly DNS resolver isn't built. + AC_CACHE_CHECK([for curl support for asynchronous DNS], [pgac_cv__libcurl_async_dns], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([ +#include +],[ + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); + return (info->features & CURL_VERSION_ASYNCHDNS) ? 0 : 1; +])], + [pgac_cv__libcurl_async_dns=yes], + [pgac_cv__libcurl_async_dns=no], + [pgac_cv__libcurl_async_dns=unknown])]) + if test x"$pgac_cv__libcurl_async_dns" = xno ; then + AC_MSG_ERROR([ +*** The installed version of libcurl does not support asynchronous DNS +*** lookups. Rebuild libcurl with the AsynchDNS feature enabled in order +*** to use it with libpq.]) + fi + + CPPFLAGS=$pgac_save_CPPFLAGS + LDFLAGS=$pgac_save_LDFLAGS + LIBS=$pgac_save_LIBS +])# PGAC_CHECK_LIBCURL diff --git a/configure b/configure index ea5514fab1a3c..4f15347cc9503 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for PostgreSQL 18devel. +# Generated by GNU Autoconf 2.69 for PostgreSQL 18beta1. # # Report bugs to . # @@ -11,7 +11,7 @@ # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # -# Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Copyright (c) 1996-2025, PostgreSQL Global Development Group ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## @@ -582,8 +582,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='PostgreSQL' PACKAGE_TARNAME='postgresql' -PACKAGE_VERSION='18devel' -PACKAGE_STRING='PostgreSQL 18devel' +PACKAGE_VERSION='18beta1' +PACKAGE_STRING='PostgreSQL 18beta1' PACKAGE_BUGREPORT='pgsql-bugs@lists.postgresql.org' PACKAGE_URL='https://www.postgresql.org/' @@ -647,9 +647,6 @@ MSGFMT_FLAGS MSGFMT PG_CRC32C_OBJS CFLAGS_CRC -PG_POPCNT_OBJS -CFLAGS_POPCNT -CFLAGS_XSAVE LIBOBJS OPENSSL ZSTD @@ -658,6 +655,7 @@ UUID_LIBS LDAP_LIBS_BE LDAP_LIBS_FE with_ssl +LIBCURL_LDLIBS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC @@ -711,7 +709,18 @@ XML2_LIBS XML2_CFLAGS XML2_CONFIG with_libxml +LIBNUMA_LIBS +LIBNUMA_CFLAGS +with_libnuma +LIBCURL_LDFLAGS +LIBCURL_CPPFLAGS +LIBCURL_LIBS +LIBCURL_CFLAGS +with_libcurl with_uuid +LIBURING_LIBS +LIBURING_CFLAGS +with_liburing with_readline with_systemd with_selinux @@ -725,7 +734,6 @@ with_tcl ICU_LIBS ICU_CFLAGS with_icu -INCLUDES autodepend PKG_CONFIG_LIBDIR PKG_CONFIG_PATH @@ -741,6 +749,7 @@ CXXFLAGS_SL_MODULE CFLAGS_SL_MODULE CFLAGS_VECTORIZE CFLAGS_UNROLL_LOOPS +PERMIT_MISSING_VARIABLE_DECLARATIONS PERMIT_DECLARATION_AFTER_STATEMENT LLVM_BINPATH LLVM_CXXFLAGS @@ -763,6 +772,7 @@ LDFLAGS CFLAGS CC enable_injection_points +PG_TEST_EXTRA enable_tap_tests enable_dtrace DTRACEFLAGS @@ -836,8 +846,6 @@ enable_integer_datetimes enable_nls with_pgport enable_rpath -enable_spinlocks -enable_atomics enable_debug enable_profiling enable_coverage @@ -866,8 +874,11 @@ with_selinux with_systemd with_readline with_libedit_preferred +with_liburing with_uuid with_ossp_uuid +with_libcurl +with_libnuma with_libxml with_libxslt with_system_tzdata @@ -881,6 +892,7 @@ enable_largefile ac_precious_vars='build_alias host_alias target_alias +PG_TEST_EXTRA CC CFLAGS LDFLAGS @@ -897,6 +909,12 @@ PKG_CONFIG_PATH PKG_CONFIG_LIBDIR ICU_CFLAGS ICU_LIBS +LIBURING_CFLAGS +LIBURING_LIBS +LIBCURL_CFLAGS +LIBCURL_LIBS +LIBNUMA_CFLAGS +LIBNUMA_LIBS XML2_CONFIG XML2_CFLAGS XML2_LIBS @@ -1450,7 +1468,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures PostgreSQL 18devel to adapt to many kinds of systems. +\`configure' configures PostgreSQL 18beta1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1515,7 +1533,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of PostgreSQL 18devel:";; + short | recursive ) echo "Configuration of PostgreSQL 18beta1:";; esac cat <<\_ACEOF @@ -1529,8 +1547,6 @@ Optional Features: enable Native Language Support --disable-rpath do not embed shared library search path in executables - --disable-spinlocks do not use spinlocks - --disable-atomics do not use atomic operations --enable-debug build with debugging symbols (-g) --enable-profiling build with profiling enabled --enable-coverage build with coverage testing instrumentation @@ -1577,8 +1593,11 @@ Optional Packages: --without-readline do not use GNU Readline nor BSD Libedit for editing --with-libedit-preferred prefer BSD Libedit over GNU Readline + --with-liburing build with io_uring support, for asynchronous I/O --with-uuid=LIB build contrib/uuid-ossp using LIB (bsd,e2fs,ossp) --with-ossp-uuid obsolete spelling of --with-uuid=ossp + --with-libcurl build with libcurl support + --with-libnuma build with libnuma support --with-libxml build with XML support --with-libxslt use XSLT support when building contrib/xml2 --with-system-tzdata=DIR @@ -1590,6 +1609,9 @@ Optional Packages: --with-openssl obsolete spelling of --with-ssl=openssl Some influential environment variables: + PG_TEST_EXTRA + enable selected extra tests (overridden at runtime by + PG_TEST_EXTRA environment variable) CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a @@ -1609,6 +1631,18 @@ Some influential environment variables: path overriding pkg-config's built-in search path ICU_CFLAGS C compiler flags for ICU, overriding pkg-config ICU_LIBS linker flags for ICU, overriding pkg-config + LIBURING_CFLAGS + C compiler flags for LIBURING, overriding pkg-config + LIBURING_LIBS + linker flags for LIBURING, overriding pkg-config + LIBCURL_CFLAGS + C compiler flags for LIBCURL, overriding pkg-config + LIBCURL_LIBS + linker flags for LIBCURL, overriding pkg-config + LIBNUMA_CFLAGS + C compiler flags for LIBNUMA, overriding pkg-config + LIBNUMA_LIBS + linker flags for LIBNUMA, overriding pkg-config XML2_CONFIG path to xml2-config utility XML2_CFLAGS C compiler flags for XML2, overriding pkg-config XML2_LIBS linker flags for XML2, overriding pkg-config @@ -1690,14 +1724,14 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -PostgreSQL configure 18devel +PostgreSQL configure 18beta1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. -Copyright (c) 1996-2024, PostgreSQL Global Development Group +Copyright (c) 1996-2025, PostgreSQL Global Development Group _ACEOF exit fi @@ -2096,116 +2130,116 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else - eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main () { -if (sizeof ($2)) - return 0; +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main () { -if (sizeof (($2))) - return 0; +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - + eval "$4=yes" else - eval "$3=yes" + eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -eval ac_res=\$$3 +eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_type +} # ac_fn_c_check_member -# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES -# ---------------------------------------------------- -# Tries to find if the field MEMBER exists in type AGGR, after including -# INCLUDES, setting cache variable VAR accordingly. -ac_fn_c_check_member () +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 -$as_echo_n "checking for $2.$3... " >&6; } -if eval \${$4+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else + eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main () { -static $2 ac_aggr; -if (ac_aggr.$3) -return 0; +if (sizeof ($2)) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" -else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main () { -static $2 ac_aggr; -if (sizeof ac_aggr.$3) -return 0; +if (sizeof (($2))) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" + else - eval "$4=no" + eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -eval ac_res=\$$4 +eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_member +} # ac_fn_c_check_type # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- @@ -2443,7 +2477,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by PostgreSQL $as_me 18devel, which was +It was created by PostgreSQL $as_me 18beta1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3266,60 +3300,6 @@ fi -# -# Spinlocks -# - - -# Check whether --enable-spinlocks was given. -if test "${enable_spinlocks+set}" = set; then : - enableval=$enable_spinlocks; - case $enableval in - yes) - : - ;; - no) - : - ;; - *) - as_fn_error $? "no argument expected for --enable-spinlocks option" "$LINENO" 5 - ;; - esac - -else - enable_spinlocks=yes - -fi - - - -# -# Atomic operations -# - - -# Check whether --enable-atomics was given. -if test "${enable_atomics+set}" = set; then : - enableval=$enable_atomics; - case $enableval in - yes) - : - ;; - no) - : - ;; - *) - as_fn_error $? "no argument expected for --enable-atomics option" "$LINENO" 5 - ;; - esac - -else - enable_atomics=yes - -fi - - - # # --enable-debug adds -g to compiler flags # @@ -3686,6 +3666,7 @@ fi + # # Injection points # @@ -5129,8 +5110,8 @@ fi as_fn_error $? "$LLVM_CONFIG does not work" "$LINENO" 5 fi # and whether the version is supported - if echo $pgac_llvm_version | $AWK -F '.' '{ if ($1 >= 10) exit 1; else exit 0;}';then - as_fn_error $? "$LLVM_CONFIG version is $pgac_llvm_version but at least 10 is required" "$LINENO" 5 + if echo $pgac_llvm_version | $AWK -F '.' '{ if ($1 >= 14) exit 1; else exit 0;}';then + as_fn_error $? "$LLVM_CONFIG version is $pgac_llvm_version but at least 14 is required" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: using llvm $pgac_llvm_version" >&5 $as_echo "$as_me: using llvm $pgac_llvm_version" >&6;} @@ -6080,6 +6061,54 @@ if test x"$pgac_cv_prog_CXX_cxxflags__Wformat_security" = x"yes"; then fi + # gcc 14+, clang for a while + # (Supported in C++ by clang but not gcc. For consistency, omit in C++.) + save_CFLAGS=$CFLAGS + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -Wmissing-variable-declarations, for CFLAGS" >&5 +$as_echo_n "checking whether ${CC} supports -Wmissing-variable-declarations, for CFLAGS... " >&6; } +if ${pgac_cv_prog_CC_cflags__Wmissing_variable_declarations+:} false; then : + $as_echo_n "(cached) " >&6 +else + pgac_save_CFLAGS=$CFLAGS +pgac_save_CC=$CC +CC=${CC} +CFLAGS="${CFLAGS} -Wmissing-variable-declarations" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + pgac_cv_prog_CC_cflags__Wmissing_variable_declarations=yes +else + pgac_cv_prog_CC_cflags__Wmissing_variable_declarations=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$pgac_save_CFLAGS" +CC="$pgac_save_CC" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CC_cflags__Wmissing_variable_declarations" >&5 +$as_echo "$pgac_cv_prog_CC_cflags__Wmissing_variable_declarations" >&6; } +if test x"$pgac_cv_prog_CC_cflags__Wmissing_variable_declarations" = x"yes"; then + CFLAGS="${CFLAGS} -Wmissing-variable-declarations" +fi + + + PERMIT_MISSING_VARIABLE_DECLARATIONS= + if test x"$save_CFLAGS" != x"$CFLAGS"; then + PERMIT_MISSING_VARIABLE_DECLARATIONS=-Wno-missing-variable-declarations + fi + # Disable strict-aliasing rules; needed for gcc 3.3+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC} supports -fno-strict-aliasing, for CFLAGS" >&5 @@ -7290,17 +7319,27 @@ if test x"$pgac_cv_prog_CLANGXX_cxxflags__fexcess_precision_standard" = x"yes"; fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -Xclang -no-opaque-pointers, for BITCODE_CFLAGS" >&5 -$as_echo_n "checking whether ${CLANG} supports -Xclang -no-opaque-pointers, for BITCODE_CFLAGS... " >&6; } -if ${pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers+:} false; then : + # Ideally bitcode should perhaps match $CC's use, or not, of outline atomic + # functions, but for now we err on the side of suppressing them in bitcode, + # because we can't assume they're available at runtime. This affects aarch64 + # builds using the basic armv8-a ISA without LSE support. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CFLAGS" >&5 +$as_echo_n "checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CFLAGS... " >&6; } +if ${pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics+:} false; then : $as_echo_n "(cached) " >&6 else - pgac_save_CFLAGS=$CFLAGS -pgac_save_CC=$CC -CC=${CLANG} -CFLAGS="${BITCODE_CFLAGS} -Xclang -no-opaque-pointers" -ac_save_c_werror_flag=$ac_c_werror_flag -ac_c_werror_flag=yes + pgac_save_CXXFLAGS=$CXXFLAGS +pgac_save_CXX=$CXX +CXX=${CLANG} +CXXFLAGS="${BITCODE_CFLAGS} -mno-outline-atomics" +ac_save_cxx_werror_flag=$ac_cxx_werror_flag +ac_cxx_werror_flag=yes +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -7312,31 +7351,37 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers=yes +if ac_fn_cxx_try_compile "$LINENO"; then : + pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=yes else - pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers=no + pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_c_werror_flag=$ac_save_c_werror_flag -CFLAGS="$pgac_save_CFLAGS" -CC="$pgac_save_CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_cxx_werror_flag=$ac_save_cxx_werror_flag +CXXFLAGS="$pgac_save_CXXFLAGS" +CXX="$pgac_save_CXX" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers" >&5 -$as_echo "$pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers" >&6; } -if test x"$pgac_cv_prog_CLANG_cflags__Xclang__no_opaque_pointers" = x"yes"; then - BITCODE_CFLAGS="${BITCODE_CFLAGS} -Xclang -no-opaque-pointers" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&5 +$as_echo "$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&6; } +if test x"$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" = x"yes"; then + BITCODE_CFLAGS="${BITCODE_CFLAGS} -mno-outline-atomics" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANGXX} supports -Xclang -no-opaque-pointers, for BITCODE_CXXFLAGS" >&5 -$as_echo_n "checking whether ${CLANGXX} supports -Xclang -no-opaque-pointers, for BITCODE_CXXFLAGS... " >&6; } -if ${pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CXXFLAGS" >&5 +$as_echo_n "checking whether ${CLANG} supports -mno-outline-atomics, for BITCODE_CXXFLAGS... " >&6; } +if ${pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics+:} false; then : $as_echo_n "(cached) " >&6 else pgac_save_CXXFLAGS=$CXXFLAGS pgac_save_CXX=$CXX -CXX=${CLANGXX} -CXXFLAGS="${BITCODE_CXXFLAGS} -Xclang -no-opaque-pointers" +CXX=${CLANG} +CXXFLAGS="${BITCODE_CXXFLAGS} -mno-outline-atomics" ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_ext=cpp @@ -7357,9 +7402,9 @@ main () } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : - pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers=yes + pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=yes else - pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers=no + pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c @@ -7372,10 +7417,10 @@ ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="$pgac_save_CXXFLAGS" CXX="$pgac_save_CXX" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers" >&5 -$as_echo "$pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers" >&6; } -if test x"$pgac_cv_prog_CLANGXX_cxxflags__Xclang__no_opaque_pointers" = x"yes"; then - BITCODE_CXXFLAGS="${BITCODE_CXXFLAGS} -Xclang -no-opaque-pointers" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&5 +$as_echo "$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" >&6; } +if test x"$pgac_cv_prog_CLANG_cxxflags__mno_outline_atomics" = x"yes"; then + BITCODE_CXXFLAGS="${BITCODE_CXXFLAGS} -mno-outline-atomics" fi @@ -7581,10 +7626,10 @@ $as_echo "#define PROFILE_PID_DIR 1" >>confdefs.h fi fi -# On Solaris, we need this #define to get POSIX-conforming versions -# of many interfaces (sigwait, getpwuid_r, ...). +# On Solaris, we need these #defines to get POSIX-conforming versions +# of many interfaces (sigwait, getpwuid_r, shmdt, ...). if test "$PORTNAME" = "solaris"; then - CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS" + CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS" fi # We already have this in Makefile.win32, but configure needs it too @@ -8048,7 +8093,6 @@ done IFS=$ac_save_IFS - # # Library directories # @@ -8162,17 +8206,31 @@ fi # Put the nasty error message in config.log where it belongs echo "$ICU_PKG_ERRORS" >&5 - as_fn_error $? "ICU library not found -If you have ICU already installed, see config.log for details on the -failure. It is possible the compiler isn't looking in the proper directory. -Use --without-icu to disable ICU support." "$LINENO" 5 + as_fn_error $? "Package requirements (icu-uc icu-i18n) were not met: + +$ICU_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables ICU_CFLAGS +and ICU_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "ICU library not found -If you have ICU already installed, see config.log for details on the -failure. It is possible the compiler isn't looking in the proper directory. -Use --without-icu to disable ICU support." "$LINENO" 5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables ICU_CFLAGS +and ICU_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } else ICU_CFLAGS=$pkg_cv_ICU_CFLAGS ICU_LIBS=$pkg_cv_ICU_LIBS @@ -8659,79 +8717,207 @@ fi - -# -# UUID library # -# There are at least three UUID libraries in common use: the FreeBSD/NetBSD -# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP -# UUID library. More than one of these might be present on a given platform, -# so we make the user say which one she wants. +# liburing # +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with liburing support" >&5 +$as_echo_n "checking whether to build with liburing support... " >&6; } -# Check whether --with-uuid was given. -if test "${with_uuid+set}" = set; then : - withval=$with_uuid; +# Check whether --with-liburing was given. +if test "${with_liburing+set}" = set; then : + withval=$with_liburing; case $withval in yes) - as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 - ;; - no) - as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 - ;; - *) - - ;; - esac - -fi - - -if test x"$with_uuid" = x"" ; then - with_uuid=no -fi +$as_echo "#define USE_LIBURING 1" >>confdefs.h - -# Check whether --with-ossp-uuid was given. -if test "${with_ossp_uuid+set}" = set; then : - withval=$with_ossp_uuid; - case $withval in - yes) - : ;; no) : ;; *) - as_fn_error $? "no argument expected for --with-ossp-uuid option" "$LINENO" 5 + as_fn_error $? "no argument expected for --with-liburing option" "$LINENO" 5 ;; esac else - with_ossp_uuid=no - -fi - + with_liburing=no -if test "$with_ossp_uuid" = yes ; then - with_uuid=ossp fi -if test "$with_uuid" != no ; then - if test "$with_uuid" = bsd ; then -$as_echo "#define HAVE_UUID_BSD 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_liburing" >&5 +$as_echo "$with_liburing" >&6; } - elif test "$with_uuid" = e2fs ; then -$as_echo "#define HAVE_UUID_E2FS 1" >>confdefs.h +if test "$with_liburing" = yes; then - elif test "$with_uuid" = ossp ; then +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for liburing" >&5 +$as_echo_n "checking for liburing... " >&6; } -$as_echo "#define HAVE_UUID_OSSP 1" >>confdefs.h +if test -n "$LIBURING_CFLAGS"; then + pkg_cv_LIBURING_CFLAGS="$LIBURING_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liburing\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liburing") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBURING_CFLAGS=`$PKG_CONFIG --cflags "liburing" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBURING_LIBS"; then + pkg_cv_LIBURING_LIBS="$LIBURING_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liburing\""; } >&5 + ($PKG_CONFIG --exists --print-errors "liburing") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBURING_LIBS=`$PKG_CONFIG --libs "liburing" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBURING_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liburing" 2>&1` + else + LIBURING_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liburing" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBURING_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (liburing) were not met: + +$LIBURING_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables LIBURING_CFLAGS +and LIBURING_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables LIBURING_CFLAGS +and LIBURING_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + LIBURING_CFLAGS=$pkg_cv_LIBURING_CFLAGS + LIBURING_LIBS=$pkg_cv_LIBURING_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +fi + +# +# UUID library +# +# There are at least three UUID libraries in common use: the FreeBSD/NetBSD +# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP +# UUID library. More than one of these might be present on a given platform, +# so we make the user say which one she wants. +# + + + +# Check whether --with-uuid was given. +if test "${with_uuid+set}" = set; then : + withval=$with_uuid; + case $withval in + yes) + as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 + ;; + no) + as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 + ;; + *) + + ;; + esac + +fi + + +if test x"$with_uuid" = x"" ; then + with_uuid=no +fi + + + +# Check whether --with-ossp-uuid was given. +if test "${with_ossp_uuid+set}" = set; then : + withval=$with_ossp_uuid; + case $withval in + yes) + : + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --with-ossp-uuid option" "$LINENO" 5 + ;; + esac + +else + with_ossp_uuid=no + +fi + + +if test "$with_ossp_uuid" = yes ; then + with_uuid=ossp +fi + +if test "$with_uuid" != no ; then + if test "$with_uuid" = bsd ; then + +$as_echo "#define HAVE_UUID_BSD 1" >>confdefs.h + + elif test "$with_uuid" = e2fs ; then + +$as_echo "#define HAVE_UUID_E2FS 1" >>confdefs.h + + elif test "$with_uuid" = ossp ; then + +$as_echo "#define HAVE_UUID_OSSP 1" >>confdefs.h else as_fn_error $? "--with-uuid must specify one of bsd, e2fs, or ossp" "$LINENO" 5 @@ -8740,6 +8926,341 @@ fi +# +# libcurl +# +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with libcurl support" >&5 +$as_echo_n "checking whether to build with libcurl support... " >&6; } + + + +# Check whether --with-libcurl was given. +if test "${with_libcurl+set}" = set; then : + withval=$with_libcurl; + case $withval in + yes) + +$as_echo "#define USE_LIBCURL 1" >>confdefs.h + + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --with-libcurl option" "$LINENO" 5 + ;; + esac + +else + with_libcurl=no + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libcurl" >&5 +$as_echo "$with_libcurl" >&6; } + + +if test "$with_libcurl" = yes ; then + # Check for libcurl 7.61.0 or higher (corresponding to RHEL8 and the ability + # to explicitly set TLS 1.3 ciphersuites). + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcurl >= 7.61.0" >&5 +$as_echo_n "checking for libcurl >= 7.61.0... " >&6; } + +if test -n "$LIBCURL_CFLAGS"; then + pkg_cv_LIBCURL_CFLAGS="$LIBCURL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.61.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcurl >= 7.61.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBCURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl >= 7.61.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBCURL_LIBS"; then + pkg_cv_LIBCURL_LIBS="$LIBCURL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.61.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libcurl >= 7.61.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBCURL_LIBS=`$PKG_CONFIG --libs "libcurl >= 7.61.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBCURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl >= 7.61.0" 2>&1` + else + LIBCURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl >= 7.61.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBCURL_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (libcurl >= 7.61.0) were not met: + +$LIBCURL_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables LIBCURL_CFLAGS +and LIBCURL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables LIBCURL_CFLAGS +and LIBCURL_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + LIBCURL_CFLAGS=$pkg_cv_LIBCURL_CFLAGS + LIBCURL_LIBS=$pkg_cv_LIBCURL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + + # Curl's flags are kept separate from the standard CPPFLAGS/LDFLAGS. We use + # them only for libpq-oauth. + LIBCURL_CPPFLAGS= + LIBCURL_LDFLAGS= + + # We only care about -I, -D, and -L switches. Note that -lcurl will be added + # to LIBCURL_LDLIBS by PGAC_CHECK_LIBCURL, below. + for pgac_option in $LIBCURL_CFLAGS; do + case $pgac_option in + -I*|-D*) LIBCURL_CPPFLAGS="$LIBCURL_CPPFLAGS $pgac_option";; + esac + done + for pgac_option in $LIBCURL_LIBS; do + case $pgac_option in + -L*) LIBCURL_LDFLAGS="$LIBCURL_LDFLAGS $pgac_option";; + esac + done + + + + + # OAuth requires python for testing + if test "$with_python" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** OAuth support tests require --with-python to run" >&5 +$as_echo "$as_me: WARNING: *** OAuth support tests require --with-python to run" >&2;} + fi +fi + + +# +# libnuma +# +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with libnuma support" >&5 +$as_echo_n "checking whether to build with libnuma support... " >&6; } + + + +# Check whether --with-libnuma was given. +if test "${with_libnuma+set}" = set; then : + withval=$with_libnuma; + case $withval in + yes) + +$as_echo "#define USE_LIBNUMA 1" >>confdefs.h + + ;; + no) + : + ;; + *) + as_fn_error $? "no argument expected for --with-libnuma option" "$LINENO" 5 + ;; + esac + +else + with_libnuma=no + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libnuma" >&5 +$as_echo "$with_libnuma" >&6; } + + +if test "$with_libnuma" = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for numa_available in -lnuma" >&5 +$as_echo_n "checking for numa_available in -lnuma... " >&6; } +if ${ac_cv_lib_numa_numa_available+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnuma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char numa_available (); +int +main () +{ +return numa_available (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_numa_numa_available=yes +else + ac_cv_lib_numa_numa_available=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_numa_numa_available" >&5 +$as_echo "$ac_cv_lib_numa_numa_available" >&6; } +if test "x$ac_cv_lib_numa_numa_available" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNUMA 1 +_ACEOF + + LIBS="-lnuma $LIBS" + +else + as_fn_error $? "library 'libnuma' is required for NUMA support" "$LINENO" 5 +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for numa" >&5 +$as_echo_n "checking for numa... " >&6; } + +if test -n "$LIBNUMA_CFLAGS"; then + pkg_cv_LIBNUMA_CFLAGS="$LIBNUMA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"numa\""; } >&5 + ($PKG_CONFIG --exists --print-errors "numa") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBNUMA_CFLAGS=`$PKG_CONFIG --cflags "numa" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBNUMA_LIBS"; then + pkg_cv_LIBNUMA_LIBS="$LIBNUMA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"numa\""; } >&5 + ($PKG_CONFIG --exists --print-errors "numa") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBNUMA_LIBS=`$PKG_CONFIG --libs "numa" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBNUMA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "numa" 2>&1` + else + LIBNUMA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "numa" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBNUMA_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (numa) were not met: + +$LIBNUMA_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables LIBNUMA_CFLAGS +and LIBNUMA_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables LIBNUMA_CFLAGS +and LIBNUMA_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + LIBNUMA_CFLAGS=$pkg_cv_LIBNUMA_CFLAGS + LIBNUMA_LIBS=$pkg_cv_LIBNUMA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi +fi + # # XML # @@ -9909,59 +10430,68 @@ if test -z "$BISON"; then fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for flex" >&5 -$as_echo_n "checking for flex... " >&6; } -if ${pgac_cv_path_flex+:} false; then : +if test -z "$FLEX"; then + for ac_prog in flex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_FLEX+:} false; then : $as_echo_n "(cached) " >&6 else - # Let the user override the test -if test -n "$FLEX"; then - pgac_cv_path_flex=$FLEX -else - pgac_save_IFS=$IFS - IFS=$PATH_SEPARATOR - for pgac_dir in $PATH; do - IFS=$pgac_save_IFS - if test -z "$pgac_dir" || test x"$pgac_dir" = x"."; then - pgac_dir=`pwd` - fi - for pgac_prog in flex lex; do - pgac_candidate="$pgac_dir/$pgac_prog" - if test -f "$pgac_candidate" \ - && $pgac_candidate --version /dev/null 2>&1 - then - echo '%%' > conftest.l - if $pgac_candidate -t conftest.l 2>/dev/null | grep FLEX_SCANNER >/dev/null 2>&1; then - pgac_flex_version=`$pgac_candidate --version 2>/dev/null` - if echo "$pgac_flex_version" | sed 's/[.a-z]/ /g' | $AWK '{ if ($1 == 2 && ($2 > 5 || ($2 == 5 && $3 >= 35))) exit 0; else exit 1;}' - then - pgac_cv_path_flex=$pgac_candidate - break 2 - else - as_fn_error $? " -*** The installed version of Flex, $pgac_candidate, is too old to use with PostgreSQL. -*** Flex version 2.5.35 or later is required, but this is $pgac_flex_version." "$LINENO" 5 - fi - fi - fi - done + case $FLEX in + [\\/]* | ?:[\\/]*) + ac_cv_path_FLEX="$FLEX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_FLEX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - rm -f conftest.l lex.yy.c - : ${pgac_cv_path_flex=no} +IFS=$as_save_IFS + + ;; +esac +fi +FLEX=$ac_cv_path_FLEX +if test -n "$FLEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 +$as_echo "$FLEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + + test -n "$FLEX" && break +done + +else + # Report the value of FLEX in configure's output in all cases. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FLEX" >&5 +$as_echo_n "checking for FLEX... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 +$as_echo "$FLEX" >&6; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_path_flex" >&5 -$as_echo "$pgac_cv_path_flex" >&6; } -if test x"$pgac_cv_path_flex" = x"no"; then + +if test -z "$FLEX"; then as_fn_error $? "flex not found" "$LINENO" 5 -else - FLEX=$pgac_cv_path_flex - pgac_flex_version=`$FLEX --version 2>/dev/null` - { $as_echo "$as_me:${as_lineno-$LINENO}: using $pgac_flex_version" >&5 -$as_echo "$as_me: using $pgac_flex_version" >&6;} fi +pgac_flex_version=`$FLEX --version 2>/dev/null` +{ $as_echo "$as_me:${as_lineno-$LINENO}: using $pgac_flex_version" >&5 +$as_echo "$as_me: using $pgac_flex_version" >&6;} + @@ -12185,26 +12715,180 @@ fi fi -if test "$enable_spinlocks" = yes; then +if test "$with_libcurl" = yes ; then -$as_echo "#define HAVE_SPINLOCKS 1" >>confdefs.h + ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default" +if test "x$ac_cv_header_curl_curl_h" = xyes; then : else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -*** Not using spinlocks will cause poor performance." >&5 -$as_echo "$as_me: WARNING: -*** Not using spinlocks will cause poor performance." >&2;} + as_fn_error $? "header file is required for --with-libcurl" "$LINENO" 5 +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_multi_init in -lcurl" >&5 +$as_echo_n "checking for curl_multi_init in -lcurl... " >&6; } +if ${ac_cv_lib_curl_curl_multi_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcurl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char curl_multi_init (); +int +main () +{ +return curl_multi_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_curl_curl_multi_init=yes +else + ac_cv_lib_curl_curl_multi_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_multi_init" >&5 +$as_echo "$ac_cv_lib_curl_curl_multi_init" >&6; } +if test "x$ac_cv_lib_curl_curl_multi_init" = xyes; then : + -if test "$enable_atomics" = yes; then +$as_echo "#define HAVE_LIBCURL 1" >>confdefs.h + + LIBCURL_LDLIBS=-lcurl -$as_echo "#define HAVE_ATOMICS 1" >>confdefs.h else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -*** Not using atomic operations will cause poor performance." >&5 -$as_echo "$as_me: WARNING: -*** Not using atomic operations will cause poor performance." >&2;} + as_fn_error $? "library 'curl' does not provide curl_multi_init" "$LINENO" 5 +fi + + + pgac_save_CPPFLAGS=$CPPFLAGS + pgac_save_LDFLAGS=$LDFLAGS + pgac_save_LIBS=$LIBS + + CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS" + LDFLAGS="$LIBCURL_LDFLAGS $LDFLAGS" + LIBS="$LIBCURL_LDLIBS $LIBS" + + # Check to see whether the current platform supports threadsafe Curl + # initialization. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_global_init thread safety" >&5 +$as_echo_n "checking for curl_global_init thread safety... " >&6; } +if ${pgac_cv__libcurl_threadsafe_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + pgac_cv__libcurl_threadsafe_init=unknown +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); +#ifdef CURL_VERSION_THREADSAFE + if (info->features & CURL_VERSION_THREADSAFE) + return 0; +#endif + + return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + pgac_cv__libcurl_threadsafe_init=yes +else + pgac_cv__libcurl_threadsafe_init=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__libcurl_threadsafe_init" >&5 +$as_echo "$pgac_cv__libcurl_threadsafe_init" >&6; } + if test x"$pgac_cv__libcurl_threadsafe_init" = xyes ; then + +$as_echo "#define HAVE_THREADSAFE_CURL_GLOBAL_INIT 1" >>confdefs.h + + fi + + # Fail if a thread-friendly DNS resolver isn't built. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl support for asynchronous DNS" >&5 +$as_echo_n "checking for curl support for asynchronous DNS... " >&6; } +if ${pgac_cv__libcurl_async_dns+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + pgac_cv__libcurl_async_dns=unknown +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); + return (info->features & CURL_VERSION_ASYNCHDNS) ? 0 : 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + pgac_cv__libcurl_async_dns=yes +else + pgac_cv__libcurl_async_dns=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__libcurl_async_dns" >&5 +$as_echo "$pgac_cv__libcurl_async_dns" >&6; } + if test x"$pgac_cv__libcurl_async_dns" = xno ; then + as_fn_error $? " +*** The installed version of libcurl does not support asynchronous DNS +*** lookups. Rebuild libcurl with the AsynchDNS feature enabled in order +*** to use it with libpq." "$LINENO" 5 + fi + + CPPFLAGS=$pgac_save_CPPFLAGS + LDFLAGS=$pgac_save_LDFLAGS + LIBS=$pgac_save_LIBS + fi if test "$with_gssapi" = yes ; then @@ -12320,122 +13004,27 @@ if test "${with_openssl+set}" = set; then : esac else - with_openssl=no - -fi - - -if test "$with_openssl" = yes ; then - with_ssl=openssl -fi - -if test "$with_ssl" = openssl ; then - # Minimum required OpenSSL version is 1.0.2 - -$as_echo "#define OPENSSL_API_COMPAT 0x10002000L" >>confdefs.h - - if test "$PORTNAME" != "win32"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5 -$as_echo_n "checking for CRYPTO_new_ex_data in -lcrypto... " >&6; } -if ${ac_cv_lib_crypto_CRYPTO_new_ex_data+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcrypto $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char CRYPTO_new_ex_data (); -int -main () -{ -return CRYPTO_new_ex_data (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_crypto_CRYPTO_new_ex_data=yes -else - ac_cv_lib_crypto_CRYPTO_new_ex_data=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CRYPTO_new_ex_data" >&5 -$as_echo "$ac_cv_lib_crypto_CRYPTO_new_ex_data" >&6; } -if test "x$ac_cv_lib_crypto_CRYPTO_new_ex_data" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBCRYPTO 1 -_ACEOF - - LIBS="-lcrypto $LIBS" - -else - as_fn_error $? "library 'crypto' is required for OpenSSL" "$LINENO" 5 -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5 -$as_echo_n "checking for SSL_new in -lssl... " >&6; } -if ${ac_cv_lib_ssl_SSL_new+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lssl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char SSL_new (); -int -main () -{ -return SSL_new (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ssl_SSL_new=yes -else - ac_cv_lib_ssl_SSL_new=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5 -$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; } -if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBSSL 1 -_ACEOF - - LIBS="-lssl $LIBS" - -else - as_fn_error $? "library 'ssl' is required for OpenSSL" "$LINENO" 5 + with_openssl=no + fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing CRYPTO_new_ex_data" >&5 -$as_echo_n "checking for library containing CRYPTO_new_ex_data... " >&6; } -if ${ac_cv_search_CRYPTO_new_ex_data+:} false; then : + +if test "$with_openssl" = yes ; then + with_ssl=openssl +fi + +if test "$with_ssl" = openssl ; then + # Minimum required OpenSSL version is 1.1.1 + +$as_echo "#define OPENSSL_API_COMPAT 0x10101000L" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_new_ex_data in -lcrypto" >&5 +$as_echo_n "checking for CRYPTO_new_ex_data in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_CRYPTO_new_ex_data+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -12454,46 +13043,35 @@ return CRYPTO_new_ex_data (); return 0; } _ACEOF -for ac_lib in '' eay32 crypto; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_CRYPTO_new_ex_data=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_CRYPTO_new_ex_data=yes +else + ac_cv_lib_crypto_CRYPTO_new_ex_data=no fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_CRYPTO_new_ex_data+:} false; then : - break + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -done -if ${ac_cv_search_CRYPTO_new_ex_data+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CRYPTO_new_ex_data" >&5 +$as_echo "$ac_cv_lib_crypto_CRYPTO_new_ex_data" >&6; } +if test "x$ac_cv_lib_crypto_CRYPTO_new_ex_data" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPTO 1 +_ACEOF -else - ac_cv_search_CRYPTO_new_ex_data=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_CRYPTO_new_ex_data" >&5 -$as_echo "$ac_cv_search_CRYPTO_new_ex_data" >&6; } -ac_res=$ac_cv_search_CRYPTO_new_ex_data -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + LIBS="-lcrypto $LIBS" else - as_fn_error $? "library 'eay32' or 'crypto' is required for OpenSSL" "$LINENO" 5 + as_fn_error $? "library 'crypto' is required for OpenSSL" "$LINENO" 5 fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_new" >&5 -$as_echo_n "checking for library containing SSL_new... " >&6; } -if ${ac_cv_search_SSL_new+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5 +$as_echo_n "checking for SSL_new in -lssl... " >&6; } +if ${ac_cv_lib_ssl_SSL_new+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -12512,86 +13090,56 @@ return SSL_new (); return 0; } _ACEOF -for ac_lib in '' ssleay32 ssl; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_SSL_new=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_SSL_new+:} false; then : - break -fi -done -if ${ac_cv_search_SSL_new+:} false; then : - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ssl_SSL_new=yes else - ac_cv_search_SSL_new=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS + ac_cv_lib_ssl_SSL_new=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_new" >&5 -$as_echo "$ac_cv_search_SSL_new" >&6; } -ac_res=$ac_cv_search_SSL_new -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -else - as_fn_error $? "library 'ssleay32' or 'ssl' is required for OpenSSL" "$LINENO" 5 +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi - - fi - # Function introduced in OpenSSL 1.0.2, not in LibreSSL. - for ac_func in SSL_CTX_set_cert_cb -do : - ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb" -if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5 +$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; } +if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_SSL_CTX_SET_CERT_CB 1 +#define HAVE_LIBSSL 1 _ACEOF + LIBS="-lssl $LIBS" + +else + as_fn_error $? "library 'ssl' is required for OpenSSL" "$LINENO" 5 fi -done - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free + # Functions introduced in OpenSSL 1.1.1. + for ac_func in SSL_CTX_set_ciphersuites do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + ac_fn_c_check_func "$LINENO" "SSL_CTX_set_ciphersuites" "ac_cv_func_SSL_CTX_set_ciphersuites" +if test "x$ac_cv_func_SSL_CTX_set_ciphersuites" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define HAVE_SSL_CTX_SET_CIPHERSUITES 1 _ACEOF +else + as_fn_error $? "OpenSSL version >= 1.1.1 is required for SSL support" "$LINENO" 5 fi done - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - for ac_func in CRYPTO_lock + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. + for ac_func in SSL_CTX_set_cert_cb do : - ac_fn_c_check_func "$LINENO" "CRYPTO_lock" "ac_cv_func_CRYPTO_lock" -if test "x$ac_cv_func_CRYPTO_lock" = xyes; then : + ac_fn_c_check_func "$LINENO" "SSL_CTX_set_cert_cb" "ac_cv_func_SSL_CTX_set_cert_cb" +if test "x$ac_cv_func_SSL_CTX_set_cert_cb" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_CRYPTO_LOCK 1 +#define HAVE_SSL_CTX_SET_CERT_CB 1 _ACEOF fi done - # Function introduced in OpenSSL 1.1.1. - for ac_func in X509_get_signature_info SSL_CTX_set_num_tickets + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. + for ac_func in X509_get_signature_info SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -13244,101 +13792,7 @@ fi ## Header files ## -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 -$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } -if ${ac_cv_header_stdbool_h+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - #ifndef bool - "error: bool is not defined" - #endif - #ifndef false - "error: false is not defined" - #endif - #if false - "error: false is not 0" - #endif - #ifndef true - "error: true is not defined" - #endif - #if true != 1 - "error: true is not 1" - #endif - #ifndef __bool_true_false_are_defined - "error: __bool_true_false_are_defined is not defined" - #endif - - struct s { _Bool s: 1; _Bool t; } s; - - char a[true == 1 ? 1 : -1]; - char b[false == 0 ? 1 : -1]; - char c[__bool_true_false_are_defined == 1 ? 1 : -1]; - char d[(bool) 0.5 == true ? 1 : -1]; - /* See body of main program for 'e'. */ - char f[(_Bool) 0.0 == false ? 1 : -1]; - char g[true]; - char h[sizeof (_Bool)]; - char i[sizeof s.t]; - enum { j = false, k = true, l = false * true, m = true * 256 }; - /* The following fails for - HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ - _Bool n[m]; - char o[sizeof n == m * sizeof n[0] ? 1 : -1]; - char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; - /* Catch a bug in an HP-UX C compiler. See - http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html - http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html - */ - _Bool q = true; - _Bool *pq = &q; - -int -main () -{ - - bool e = &s; - *pq |= q; - *pq |= ! q; - /* Refer to every declared value, to avoid compiler optimizations. */ - return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l - + !m + !n + !o + !p + !q + !pq); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdbool_h=yes -else - ac_cv_header_stdbool_h=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 -$as_echo "$ac_cv_header_stdbool_h" >&6; } - ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" -if test "x$ac_cv_type__Bool" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE__BOOL 1 -_ACEOF - - -fi - - -if test $ac_cv_header_stdbool_h = yes; then - -$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h - -fi - - -for ac_header in atomic.h copyfile.h execinfo.h getopt.h ifaddrs.h langinfo.h mbarrier.h sys/epoll.h sys/event.h sys/personality.h sys/prctl.h sys/procctl.h sys/signalfd.h sys/ucred.h termios.h ucred.h +for ac_header in atomic.h copyfile.h execinfo.h getopt.h ifaddrs.h mbarrier.h sys/epoll.h sys/event.h sys/personality.h sys/prctl.h sys/procctl.h sys/signalfd.h sys/ucred.h termios.h ucred.h xlocale.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -14083,6 +14537,13 @@ done fi +if test "$with_libcurl" = yes ; then + # Error out early if this platform can't support libpq-oauth. + if test "$ac_cv_header_sys_event_h" != yes -a "$ac_cv_header_sys_epoll_h" != yes; then + as_fn_error $? "client-side OAuth is not supported on this platform" "$LINENO" 5 + fi +fi + ## ## Types, structures, compiler characteristics ## @@ -14455,7 +14916,7 @@ if ${pgac_cv_c_typeof+:} false; then : $as_echo_n "(cached) " >&6 else pgac_cv_c_typeof=no -for pgac_kw in typeof __typeof__ decltype; do +for pgac_kw in typeof __typeof__; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -14547,6 +15008,43 @@ if test x"$pgac_cv__builtin_constant_p" = xyes ; then $as_echo "#define HAVE__BUILTIN_CONSTANT_P 1" >>confdefs.h +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5 +$as_echo_n "checking for __builtin_mul_overflow... " >&6; } +if ${pgac_cv__builtin_op_overflow+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int64_t a = 1; +int64_t b = 1; +int64_t result; +int oflo; + +int +main () +{ +oflo = __builtin_mul_overflow(a, b, &result); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv__builtin_op_overflow=yes +else + pgac_cv__builtin_op_overflow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5 +$as_echo "$pgac_cv__builtin_op_overflow" >&6; } +if test x"$pgac_cv__builtin_op_overflow" = xyes ; then + +$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_unreachable" >&5 $as_echo_n "checking for __builtin_unreachable... " >&6; } @@ -14666,55 +15164,6 @@ _ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale_t" >&5 -$as_echo_n "checking for locale_t... " >&6; } -if ${pgac_cv_type_locale_t+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -locale_t x; -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_type_locale_t=yes -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -locale_t x; -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_type_locale_t='yes (in xlocale.h)' -else - pgac_cv_type_locale_t=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_locale_t" >&5 -$as_echo "$pgac_cv_type_locale_t" >&6; } -if test "$pgac_cv_type_locale_t" = 'yes (in xlocale.h)'; then - -$as_echo "#define LOCALE_T_IN_XLOCALE 1" >>confdefs.h - -fi - # MSVC doesn't cope well with defining restrict to __restrict, the # spelling it understands, because it conflicts with # __declspec(restrict). Therefore we define pg_restrict to the @@ -15071,94 +15520,51 @@ esac rm -rf conftest* fi - -fi - - -fi - -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5 -$as_echo_n "checking size of off_t... " >&6; } -if ${ac_cv_sizeof_off_t+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_off_t" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (off_t) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_off_t=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5 -$as_echo "$ac_cv_sizeof_off_t" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_OFF_T $ac_cv_sizeof_off_t -_ACEOF - - - -# If we don't have largefile support, can't handle segment size >= 2GB. -if test "$ac_cv_sizeof_off_t" -lt 8; then - if expr $RELSEG_SIZE '*' $blocksize '>=' 2 '*' 1024 '*' 1024; then - as_fn_error $? "Large file support is not enabled. Segment size cannot be larger than 1GB." "$LINENO" 5 - fi + +fi + + fi # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of bool" >&5 -$as_echo_n "checking size of bool... " >&6; } -if ${ac_cv_sizeof_bool+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5 +$as_echo_n "checking size of off_t... " >&6; } +if ${ac_cv_sizeof_off_t+:} false; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (bool))" "ac_cv_sizeof_bool" "#ifdef HAVE_STDBOOL_H -#include -#endif -"; then : + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then : else - if test "$ac_cv_type_bool" = yes; then + if test "$ac_cv_type_off_t" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (bool) +as_fn_error 77 "cannot compute sizeof (off_t) See \`config.log' for more details" "$LINENO" 5; } else - ac_cv_sizeof_bool=0 + ac_cv_sizeof_off_t=0 fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_bool" >&5 -$as_echo "$ac_cv_sizeof_bool" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5 +$as_echo "$ac_cv_sizeof_off_t" >&6; } cat >>confdefs.h <<_ACEOF -#define SIZEOF_BOOL $ac_cv_sizeof_bool +#define SIZEOF_OFF_T $ac_cv_sizeof_off_t _ACEOF -if test "$ac_cv_header_stdbool_h" = yes -a "$ac_cv_sizeof_bool" = 1; then - -$as_echo "#define PG_USE_STDBOOL 1" >>confdefs.h - +# If we don't have largefile support, can't handle segment size >= 2GB. +if test "$ac_cv_sizeof_off_t" -lt 8; then + if expr $RELSEG_SIZE '*' $blocksize '>=' 2 '*' 1024 '*' 1024; then + as_fn_error $? "Large file support is not enabled. Segment size cannot be larger than 1GB." "$LINENO" 5 + fi fi @@ -15201,59 +15607,6 @@ if test x"$pgac_cv_var_int_timezone" = xyes ; then $as_echo "#define HAVE_INT_TIMEZONE 1" >>confdefs.h -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wcstombs_l declaration" >&5 -$as_echo_n "checking for wcstombs_l declaration... " >&6; } -if ${pgac_cv_func_wcstombs_l+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -int -main () -{ -#ifndef wcstombs_l -(void) wcstombs_l; -#endif - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_func_wcstombs_l='yes' -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -int -main () -{ -#ifndef wcstombs_l -(void) wcstombs_l; -#endif - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_func_wcstombs_l='yes (in xlocale.h)' -else - pgac_cv_func_wcstombs_l='no' -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_func_wcstombs_l" >&5 -$as_echo "$pgac_cv_func_wcstombs_l" >&6; } -if test "$pgac_cv_func_wcstombs_l" = 'yes (in xlocale.h)'; then - -$as_echo "#define WCSTOMBS_L_IN_XLOCALE 1" >>confdefs.h - fi # Some versions of libedit contain strlcpy(), setproctitle(), and other @@ -15263,7 +15616,7 @@ fi LIBS_including_readline="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` -for ac_func in backtrace_symbols copyfile copy_file_range getifaddrs getpeerucred inet_pton kqueue mbstowcs_l memset_s posix_fallocate ppoll pthread_is_threaded_np setproctitle setproctitle_fast strchrnul strsignal syncfs sync_file_range uselocale wcstombs_l +for ac_func in backtrace_symbols copyfile copy_file_range elf_aux_info getauxval getifaddrs getpeerucred inet_pton kqueue localeconv_l mbstowcs_l posix_fallocate ppoll pthread_is_threaded_np setproctitle setproctitle_fast strsignal syncfs sync_file_range uselocale wcstombs_l do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15789,6 +16142,16 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRSEP $ac_have_decl _ACEOF +ac_fn_c_check_decl "$LINENO" "timingsafe_bcmp" "ac_cv_have_decl_timingsafe_bcmp" "$ac_includes_default" +if test "x$ac_cv_have_decl_timingsafe_bcmp" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TIMINGSAFE_BCMP $ac_have_decl +_ACEOF # We can't use AC_CHECK_FUNCS to detect these functions, because it @@ -15817,6 +16180,31 @@ cat >>confdefs.h <<_ACEOF #define HAVE_DECL_PWRITEV $ac_have_decl _ACEOF +ac_fn_c_check_decl "$LINENO" "strchrnul" "ac_cv_have_decl_strchrnul" "#include +" +if test "x$ac_cv_have_decl_strchrnul" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRCHRNUL $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "memset_s" "ac_cv_have_decl_memset_s" "#define __STDC_WANT_LIB_EXT1__ 1 +#include +" +if test "x$ac_cv_have_decl_memset_s" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MEMSET_S $ac_have_decl +_ACEOF + # This is probably only present on macOS, but may as well check always ac_fn_c_check_decl "$LINENO" "F_FULLFSYNC" "ac_cv_have_decl_F_FULLFSYNC" "#include @@ -15949,6 +16337,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp" +if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then : + $as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" timingsafe_bcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "pthread_barrier_wait" "ac_cv_func_pthread_barrier_wait" @@ -16036,17 +16437,6 @@ fi # Win32 (really MinGW) support if test "$PORTNAME" = "win32"; then - for ac_func in _configthreadlocale -do : - ac_fn_c_check_func "$LINENO" "_configthreadlocale" "ac_cv_func__configthreadlocale" -if test "x$ac_cv_func__configthreadlocale" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE__CONFIGTHREADLOCALE 1 -_ACEOF - -fi -done - case " $LIBOBJS " in *" dirmod.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS dirmod.$ac_objext" @@ -16456,242 +16846,12 @@ for the exact reason." "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - - -# -------------------- -# Run tests below here -# -------------------- - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long int is 64 bits" >&5 -$as_echo_n "checking whether long int is 64 bits... " >&6; } -if ${pgac_cv_type_long_int_64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - # If cross-compiling, check the size reported by the compiler and -# trust that the arithmetic works. -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -static int test_array [1 - 2 * !(sizeof(long int) == 8)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_type_long_int_64=yes -else - pgac_cv_type_long_int_64=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -typedef long int ac_int64; - -/* - * These are globals to discourage the compiler from folding all the - * arithmetic tests down to compile-time constants. - */ -ac_int64 a = 20000001; -ac_int64 b = 40000005; - -int does_int64_work() -{ - ac_int64 c,d; - - if (sizeof(ac_int64) != 8) - return 0; /* definitely not the right size */ - - /* Do perfunctory checks to see if 64-bit arithmetic seems to work */ - c = a * b; - d = (c + b) / b; - if (d != a+1) - return 0; - return 1; -} - -int -main() { - return (! does_int64_work()); -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - pgac_cv_type_long_int_64=yes -else - pgac_cv_type_long_int_64=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_int_64" >&5 -$as_echo "$pgac_cv_type_long_int_64" >&6; } - -HAVE_LONG_INT_64=$pgac_cv_type_long_int_64 -if test x"$pgac_cv_type_long_int_64" = xyes ; then - -$as_echo "#define HAVE_LONG_INT_64 1" >>confdefs.h - -fi - - -if test x"$HAVE_LONG_INT_64" = x"yes" ; then - pg_int64_type="long int" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether long long int is 64 bits" >&5 -$as_echo_n "checking whether long long int is 64 bits... " >&6; } -if ${pgac_cv_type_long_long_int_64+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - # If cross-compiling, check the size reported by the compiler and -# trust that the arithmetic works. -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -static int test_array [1 - 2 * !(sizeof(long long int) == 8)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - pgac_cv_type_long_long_int_64=yes -else - pgac_cv_type_long_long_int_64=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -typedef long long int ac_int64; - -/* - * These are globals to discourage the compiler from folding all the - * arithmetic tests down to compile-time constants. - */ -ac_int64 a = 20000001; -ac_int64 b = 40000005; - -int does_int64_work() -{ - ac_int64 c,d; - - if (sizeof(ac_int64) != 8) - return 0; /* definitely not the right size */ - - /* Do perfunctory checks to see if 64-bit arithmetic seems to work */ - c = a * b; - d = (c + b) / b; - if (d != a+1) - return 0; - return 1; -} - -int -main() { - return (! does_int64_work()); -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - pgac_cv_type_long_long_int_64=yes -else - pgac_cv_type_long_long_int_64=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_type_long_long_int_64" >&5 -$as_echo "$pgac_cv_type_long_long_int_64" >&6; } - -HAVE_LONG_LONG_INT_64=$pgac_cv_type_long_long_int_64 -if test x"$pgac_cv_type_long_long_int_64" = xyes ; then - -$as_echo "#define HAVE_LONG_LONG_INT_64 1" >>confdefs.h - -fi - - if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then - pg_int64_type="long long int" - else - as_fn_error $? "Cannot find a working 64-bit integer type." "$LINENO" 5 - fi -fi - - -cat >>confdefs.h <<_ACEOF -#define PG_INT64_TYPE $pg_int64_type -_ACEOF - - -# Select the printf length modifier that goes with that, too. -if test x"$pg_int64_type" = x"long long int" ; then - INT64_MODIFIER='"ll"' -else - INT64_MODIFIER='"l"' -fi - - -cat >>confdefs.h <<_ACEOF -#define INT64_MODIFIER $INT64_MODIFIER -_ACEOF - - -# has to be down here, rather than with the other builtins, because -# the test uses PG_INT64_TYPE. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow" >&5 -$as_echo_n "checking for __builtin_mul_overflow... " >&6; } -if ${pgac_cv__builtin_op_overflow+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -PG_INT64_TYPE a = 1; -PG_INT64_TYPE b = 1; -PG_INT64_TYPE result; -int oflo; - -int -main () -{ -oflo = __builtin_mul_overflow(a, b, &result); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - pgac_cv__builtin_op_overflow=yes -else - pgac_cv__builtin_op_overflow=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__builtin_op_overflow" >&5 -$as_echo "$pgac_cv__builtin_op_overflow" >&6; } -if test x"$pgac_cv__builtin_op_overflow" = xyes ; then +fi -$as_echo "#define HAVE__BUILTIN_OP_OVERFLOW 1" >>confdefs.h -fi +# -------------------- +# Run tests below here +# -------------------- # Check size of void *, size_t (enables tweaks for > 32bit address space) # The cast to long int works around a bug in the HP C Compiler @@ -16793,6 +16953,39 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5 +$as_echo_n "checking size of long long... " >&6; } +if ${ac_cv_sizeof_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5 +$as_echo "$ac_cv_sizeof_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + # Determine memory alignment requirements for the basic C data types. @@ -16901,43 +17094,41 @@ cat >>confdefs.h <<_ACEOF _ACEOF -if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then - # The cast to long int works around a bug in the HP C Compiler, +# The cast to long int works around a bug in the HP C Compiler, # see AC_CHECK_SIZEOF for more information. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of long long int" >&5 -$as_echo_n "checking alignment of long long int... " >&6; } -if ${ac_cv_alignof_long_long_int+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of int64_t" >&5 +$as_echo_n "checking alignment of int64_t... " >&6; } +if ${ac_cv_alignof_int64_t+:} false; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_long_long_int" "$ac_includes_default + if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_int64_t" "$ac_includes_default #ifndef offsetof # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0) #endif -typedef struct { char x; long long int y; } ac__type_alignof_;"; then : +typedef struct { char x; int64_t y; } ac__type_alignof_;"; then : else - if test "$ac_cv_type_long_long_int" = yes; then + if test "$ac_cv_type_int64_t" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute alignment of long long int +as_fn_error 77 "cannot compute alignment of int64_t See \`config.log' for more details" "$LINENO" 5; } else - ac_cv_alignof_long_long_int=0 + ac_cv_alignof_int64_t=0 fi fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_long_long_int" >&5 -$as_echo "$ac_cv_alignof_long_long_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_int64_t" >&5 +$as_echo "$ac_cv_alignof_int64_t" >&6; } cat >>confdefs.h <<_ACEOF -#define ALIGNOF_LONG_LONG_INT $ac_cv_alignof_long_long_int +#define ALIGNOF_INT64_T $ac_cv_alignof_int64_t _ACEOF -fi # The cast to long int works around a bug in the HP C Compiler, # see AC_CHECK_SIZEOF for more information. { $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of double" >&5 @@ -16995,8 +17186,8 @@ MAX_ALIGNOF=$ac_cv_alignof_double if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then as_fn_error $? "alignment of 'long' is greater than the alignment of 'double'" "$LINENO" 5 fi -if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then - as_fn_error $? "alignment of 'long long int' is greater than the alignment of 'double'" "$LINENO" 5 +if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then + as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 'double'" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF @@ -17004,51 +17195,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF - -# Some platforms predefine the types int8, int16, etc. Only check -# a (hopefully) representative subset. -ac_fn_c_check_type "$LINENO" "int8" "ac_cv_type_int8" "#include -" -if test "x$ac_cv_type_int8" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_INT8 1 -_ACEOF - - -fi -ac_fn_c_check_type "$LINENO" "uint8" "ac_cv_type_uint8" "#include -" -if test "x$ac_cv_type_uint8" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_UINT8 1 -_ACEOF - - -fi -ac_fn_c_check_type "$LINENO" "int64" "ac_cv_type_int64" "#include -" -if test "x$ac_cv_type_int64" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_INT64 1 -_ACEOF - - -fi -ac_fn_c_check_type "$LINENO" "uint64" "ac_cv_type_uint64" "#include -" -if test "x$ac_cv_type_uint64" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_UINT64 1 -_ACEOF - - -fi - - # Some compilers offer a 128-bit integer scalar type. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5 $as_echo_n "checking for __int128... " >&6; } @@ -17303,12 +17449,12 @@ if ${pgac_cv_gcc_sync_int64_cas+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include int main () { -PG_INT64_TYPE lock = 0; - __sync_val_compare_and_swap(&lock, 0, (PG_INT64_TYPE) 37); +int64_t lock = 0; + __sync_val_compare_and_swap(&lock, 0, (int64_t) 37); ; return 0; } @@ -17368,12 +17514,12 @@ if ${pgac_cv_gcc_atomic_int64_cas+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include int main () { -PG_INT64_TYPE val = 0; - PG_INT64_TYPE expect = 0; +int64_t val = 0; + int64_t expect = 0; __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); ; return 0; @@ -17535,268 +17681,219 @@ fi # Check for XSAVE intrinsics # -CFLAGS_XSAVE="" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _xgetbv with CFLAGS=" >&5 -$as_echo_n "checking for _xgetbv with CFLAGS=... " >&6; } -if ${pgac_cv_xsave_intrinsics_+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _xgetbv" >&5 +$as_echo_n "checking for _xgetbv... " >&6; } +if ${pgac_cv_xsave_intrinsics+:} false; then : $as_echo_n "(cached) " >&6 else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS " -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -return _xgetbv(0) & 0xe0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_xsave_intrinsics_=yes -else - pgac_cv_xsave_intrinsics_=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_xsave_intrinsics_" >&5 -$as_echo "$pgac_cv_xsave_intrinsics_" >&6; } -if test x"$pgac_cv_xsave_intrinsics_" = x"yes"; then - CFLAGS_XSAVE="" - pgac_xsave_intrinsics=yes -fi - -if test x"$pgac_xsave_intrinsics" != x"yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _xgetbv with CFLAGS=-mxsave" >&5 -$as_echo_n "checking for _xgetbv with CFLAGS=-mxsave... " >&6; } -if ${pgac_cv_xsave_intrinsics__mxsave+:} false; then : - $as_echo_n "(cached) " >&6 -else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS -mxsave" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("xsave"))) + #endif + static int xsave_test(void) + { + return _xgetbv(0) & 0xe0; + } int main () { -return _xgetbv(0) & 0xe0; +return xsave_test(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_xsave_intrinsics__mxsave=yes + pgac_cv_xsave_intrinsics=yes else - pgac_cv_xsave_intrinsics__mxsave=no + pgac_cv_xsave_intrinsics=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_xsave_intrinsics__mxsave" >&5 -$as_echo "$pgac_cv_xsave_intrinsics__mxsave" >&6; } -if test x"$pgac_cv_xsave_intrinsics__mxsave" = x"yes"; then - CFLAGS_XSAVE="-mxsave" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_xsave_intrinsics" >&5 +$as_echo "$pgac_cv_xsave_intrinsics" >&6; } +if test x"$pgac_cv_xsave_intrinsics" = x"yes"; then pgac_xsave_intrinsics=yes fi -fi if test x"$pgac_xsave_intrinsics" = x"yes"; then $as_echo "#define HAVE_XSAVE_INTRINSICS 1" >>confdefs.h fi - # Check for AVX-512 popcount intrinsics # -CFLAGS_POPCNT="" -PG_POPCNT_OBJS="" if test x"$host_cpu" = x"x86_64"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm512_popcnt_epi64 with CFLAGS=" >&5 -$as_echo_n "checking for _mm512_popcnt_epi64 with CFLAGS=... " >&6; } -if ${pgac_cv_avx512_popcnt_intrinsics_+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm512_popcnt_epi64" >&5 +$as_echo_n "checking for _mm512_popcnt_epi64... " >&6; } +if ${pgac_cv_avx512_popcnt_intrinsics+:} false; then : $as_echo_n "(cached) " >&6 else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS " -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -int -main () -{ -const char buf[sizeof(__m512i)]; - PG_INT64_TYPE popcnt = 0; - __m512i accum = _mm512_setzero_si512(); - const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); - const __m512i cnt = _mm512_popcnt_epi64(val); - accum = _mm512_add_epi64(accum, cnt); - popcnt = _mm512_reduce_add_epi64(accum); - /* return computed value, to prevent the above being optimized away */ - return popcnt == 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_avx512_popcnt_intrinsics_=yes -else - pgac_cv_avx512_popcnt_intrinsics_=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_avx512_popcnt_intrinsics_" >&5 -$as_echo "$pgac_cv_avx512_popcnt_intrinsics_" >&6; } -if test x"$pgac_cv_avx512_popcnt_intrinsics_" = x"yes"; then - CFLAGS_POPCNT="" - pgac_avx512_popcnt_intrinsics=yes -fi + #include + char buf[sizeof(__m512i)]; - if test x"$pgac_avx512_popcnt_intrinsics" != x"yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm512_popcnt_epi64 with CFLAGS=-mavx512vpopcntdq -mavx512bw" >&5 -$as_echo_n "checking for _mm512_popcnt_epi64 with CFLAGS=-mavx512vpopcntdq -mavx512bw... " >&6; } -if ${pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw+:} false; then : - $as_echo_n "(cached) " >&6 -else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS -mavx512vpopcntdq -mavx512bw" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("avx512vpopcntdq,avx512bw"))) + #endif + static int popcount_test(void) + { + int64_t popcnt = 0; + __m512i accum = _mm512_setzero_si512(); + __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); + __m512i cnt = _mm512_popcnt_epi64(val); + accum = _mm512_add_epi64(accum, cnt); + popcnt = _mm512_reduce_add_epi64(accum); + return (int) popcnt; + } int main () { -const char buf[sizeof(__m512i)]; - PG_INT64_TYPE popcnt = 0; - __m512i accum = _mm512_setzero_si512(); - const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); - const __m512i cnt = _mm512_popcnt_epi64(val); - accum = _mm512_add_epi64(accum, cnt); - popcnt = _mm512_reduce_add_epi64(accum); - /* return computed value, to prevent the above being optimized away */ - return popcnt == 0; +return popcount_test(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw=yes + pgac_cv_avx512_popcnt_intrinsics=yes else - pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw=no + pgac_cv_avx512_popcnt_intrinsics=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw" >&5 -$as_echo "$pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw" >&6; } -if test x"$pgac_cv_avx512_popcnt_intrinsics__mavx512vpopcntdq__mavx512bw" = x"yes"; then - CFLAGS_POPCNT="-mavx512vpopcntdq -mavx512bw" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_avx512_popcnt_intrinsics" >&5 +$as_echo "$pgac_cv_avx512_popcnt_intrinsics" >&6; } +if test x"$pgac_cv_avx512_popcnt_intrinsics" = x"yes"; then pgac_avx512_popcnt_intrinsics=yes fi - fi if test x"$pgac_avx512_popcnt_intrinsics" = x"yes"; then - PG_POPCNT_OBJS="pg_popcount_avx512.o pg_popcount_avx512_choose.o" $as_echo "#define USE_AVX512_POPCNT_WITH_RUNTIME_CHECK 1" >>confdefs.h fi fi - - -# Check for Intel SSE 4.2 intrinsics to do CRC calculations. +# Check for SVE popcount intrinsics # -# First check if the _mm_crc32_u8 and _mm_crc32_u64 intrinsics can be used -# with the default compiler flags. If not, check if adding the -msse4.2 -# flag helps. CFLAGS_CRC is set to -msse4.2 if that's required. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=" >&5 -$as_echo_n "checking for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=... " >&6; } -if ${pgac_cv_sse42_crc32_intrinsics_+:} false; then : +if test x"$host_cpu" = x"aarch64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for svcnt_x" >&5 +$as_echo_n "checking for svcnt_x... " >&6; } +if ${pgac_cv_sve_popcnt_intrinsics+:} false; then : $as_echo_n "(cached) " >&6 else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS " -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#include + + char buf[128]; + + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("arch=armv8-a+sve"))) + #endif + static int popcount_test(void) + { + svbool_t pred = svptrue_b64(); + svuint8_t vec8; + svuint64_t accum1 = svdup_u64(0), + accum2 = svdup_u64(0), + vec64; + char *p = buf; + uint64_t popcnt, + mask = 0x5555555555555555; + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + popcnt = svaddv_u64(pred, svadd_u64_x(pred, accum1, accum2)); + + pred = svwhilelt_b8_s32(0, sizeof(buf)); + vec8 = svand_n_u8_x(pred, svld1_u8(pred, (const uint8_t *) p), 0x55); + return (int) (popcnt + svaddv_u8(pred, svcnt_u8_x(pred, vec8))); + } int main () { -unsigned int crc = 0; - crc = _mm_crc32_u8(crc, 0); - crc = _mm_crc32_u32(crc, 0); - /* return computed value, to prevent the above being optimized away */ - return crc == 0; +return popcount_test(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_sse42_crc32_intrinsics_=yes + pgac_cv_sve_popcnt_intrinsics=yes else - pgac_cv_sse42_crc32_intrinsics_=no + pgac_cv_sve_popcnt_intrinsics=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_sse42_crc32_intrinsics_" >&5 -$as_echo "$pgac_cv_sse42_crc32_intrinsics_" >&6; } -if test x"$pgac_cv_sse42_crc32_intrinsics_" = x"yes"; then - CFLAGS_CRC="" - pgac_sse42_crc32_intrinsics=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_sve_popcnt_intrinsics" >&5 +$as_echo "$pgac_cv_sve_popcnt_intrinsics" >&6; } +if test x"$pgac_cv_sve_popcnt_intrinsics" = x"yes"; then + pgac_sve_popcnt_intrinsics=yes +fi + + if test x"$pgac_sve_popcnt_intrinsics" = x"yes"; then + +$as_echo "#define USE_SVE_POPCNT_WITH_RUNTIME_CHECK 1" >>confdefs.h + + fi fi -if test x"$pgac_sse42_crc32_intrinsics" != x"yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=-msse4.2" >&5 -$as_echo_n "checking for _mm_crc32_u8 and _mm_crc32_u32 with CFLAGS=-msse4.2... " >&6; } -if ${pgac_cv_sse42_crc32_intrinsics__msse4_2+:} false; then : +# Check for Intel SSE 4.2 intrinsics to do CRC calculations. +# +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm_crc32_u8 and _mm_crc32_u32" >&5 +$as_echo_n "checking for _mm_crc32_u8 and _mm_crc32_u32... " >&6; } +if ${pgac_cv_sse42_crc32_intrinsics+:} false; then : $as_echo_n "(cached) " >&6 else - pgac_save_CFLAGS=$CFLAGS -CFLAGS="$pgac_save_CFLAGS -msse4.2" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include + unsigned int crc; + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("sse4.2"))) + #endif + static int crc32_sse42_test(void) + { + crc = _mm_crc32_u8(crc, 0); + crc = _mm_crc32_u32(crc, 0); + /* return computed value, to prevent the above being optimized away */ + return crc == 0; + } int main () { -unsigned int crc = 0; - crc = _mm_crc32_u8(crc, 0); - crc = _mm_crc32_u32(crc, 0); - /* return computed value, to prevent the above being optimized away */ - return crc == 0; +return crc32_sse42_test(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_sse42_crc32_intrinsics__msse4_2=yes + pgac_cv_sse42_crc32_intrinsics=yes else - pgac_cv_sse42_crc32_intrinsics__msse4_2=no + pgac_cv_sse42_crc32_intrinsics=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -CFLAGS="$pgac_save_CFLAGS" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_sse42_crc32_intrinsics__msse4_2" >&5 -$as_echo "$pgac_cv_sse42_crc32_intrinsics__msse4_2" >&6; } -if test x"$pgac_cv_sse42_crc32_intrinsics__msse4_2" = x"yes"; then - CFLAGS_CRC="-msse4.2" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_sse42_crc32_intrinsics" >&5 +$as_echo "$pgac_cv_sse42_crc32_intrinsics" >&6; } +if test x"$pgac_cv_sse42_crc32_intrinsics" = x"yes"; then pgac_sse42_crc32_intrinsics=yes fi -fi # Are we targeting a processor that supports SSE 4.2? gcc, clang and icc all # define __SSE4_2__ in that case. @@ -17823,7 +17920,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for ARMv8 CRC Extension intrinsics to do CRC calculations. # # First check if __crc32c* intrinsics can be used with the default compiler -# flags. If not, check if adding -march=armv8-a+crc flag helps. +# flags. If not, check if adding "-march=armv8-a+crc+simd" flag helps. +# On systems using soft-float ABI, "-march=armv8-a+crc" is required instead. # CFLAGS_CRC is set if the extra flag is required. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=" >&5 $as_echo_n "checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=... " >&6; } @@ -17835,11 +17933,11 @@ CFLAGS="$pgac_save_CFLAGS " cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include +unsigned int crc; int main () { -unsigned int crc = 0; - crc = __crc32cb(crc, 0); +crc = __crc32cb(crc, 0); crc = __crc32ch(crc, 0); crc = __crc32cw(crc, 0); crc = __crc32cd(crc, 0); @@ -17866,7 +17964,48 @@ if test x"$pgac_cv_armv8_crc32c_intrinsics_" = x"yes"; then fi if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=-march=armv8-a+crc" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=-march=armv8-a+crc+simd" >&5 +$as_echo_n "checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=-march=armv8-a+crc+simd... " >&6; } +if ${pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd+:} false; then : + $as_echo_n "(cached) " >&6 +else + pgac_save_CFLAGS=$CFLAGS +CFLAGS="$pgac_save_CFLAGS -march=armv8-a+crc+simd" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +unsigned int crc; +int +main () +{ +crc = __crc32cb(crc, 0); + crc = __crc32ch(crc, 0); + crc = __crc32cw(crc, 0); + crc = __crc32cd(crc, 0); + /* return computed value, to prevent the above being optimized away */ + return crc == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd=yes +else + pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS="$pgac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd" >&5 +$as_echo "$pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd" >&6; } +if test x"$pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrcpsimd" = x"yes"; then + CFLAGS_CRC="-march=armv8-a+crc+simd" + pgac_armv8_crc32c_intrinsics=yes +fi + + if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=-march=armv8-a+crc" >&5 $as_echo_n "checking for __crc32cb, __crc32ch, __crc32cw, and __crc32cd with CFLAGS=-march=armv8-a+crc... " >&6; } if ${pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrc+:} false; then : $as_echo_n "(cached) " >&6 @@ -17876,11 +18015,11 @@ CFLAGS="$pgac_save_CFLAGS -march=armv8-a+crc" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include +unsigned int crc; int main () { -unsigned int crc = 0; - crc = __crc32cb(crc, 0); +crc = __crc32cb(crc, 0); crc = __crc32ch(crc, 0); crc = __crc32cw(crc, 0); crc = __crc32cd(crc, 0); @@ -17906,6 +18045,7 @@ if test x"$pgac_cv_armv8_crc32c_intrinsics__march_armv8_apcrc" = x"yes"; then pgac_armv8_crc32c_intrinsics=yes fi + fi fi # Check for LoongArch CRC intrinsics to do CRC calculations. @@ -17919,12 +18059,11 @@ if ${pgac_cv_loongarch_crc32c_intrinsics+:} false; then : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +unsigned int crc; int main () { -unsigned int crc = 0; - crc = __builtin_loongarch_crcc_w_b_w(0, crc); +crc = __builtin_loongarch_crcc_w_b_w(0, crc); crc = __builtin_loongarch_crcc_w_h_w(0, crc); crc = __builtin_loongarch_crcc_w_w_w(0, crc); crc = __builtin_loongarch_crcc_w_d_w(0, crc); @@ -17953,17 +18092,26 @@ fi # Select CRC-32C implementation. # -# If we are targeting a processor that has Intel SSE 4.2 instructions, we can -# use the special CRC instructions for calculating CRC-32C. If we're not -# targeting such a processor, but we can nevertheless produce code that uses -# the SSE intrinsics, perhaps with some extra CFLAGS, compile both -# implementations and select which one to use at runtime, depending on whether -# SSE 4.2 is supported by the processor we're running on. +# There are three methods of calculating CRC, in order of increasing +# performance: +# +# 1. The fallback using a lookup table, called slicing-by-8 +# 2. CRC-32C instructions (found in e.g. Intel SSE 4.2 and ARMv8 CRC Extension) +# 3. Algorithms using carryless multiplication instructions +# (e.g. Intel PCLMUL and Arm PMULL) # -# Similarly, if we are targeting an ARM processor that has the CRC -# instructions that are part of the ARMv8 CRC Extension, use them. And if -# we're not targeting such a processor, but can nevertheless produce code that -# uses the CRC instructions, compile both, and select at runtime. +# If we can produce code (via function attributes or additional compiler +# flags) that uses #2 (and possibly #3), we compile all implementations +# and select which one to use at runtime, depending on what is supported +# by the processor we're running on. +# +# If we are targeting a processor that has #2, we can use that without +# runtime selection. +# +# Note that we do not use __attribute__((target("..."))) for the ARM CRC +# instructions because until clang 16, using the ARM intrinsics still requires +# special -march flags. Perhaps we can re-evaluate this decision after some +# time has passed. # # You can skip the runtime check by setting the appropriate USE_*_CRC32 flag to 1 # in the template or configure command line. @@ -18009,7 +18157,7 @@ if test x"$USE_SSE42_CRC32C" = x"1"; then $as_echo "#define USE_SSE42_CRC32C 1" >>confdefs.h - PG_CRC32C_OBJS="pg_crc32c_sse42.o" + PG_CRC32C_OBJS="pg_crc32c_sse42.o pg_crc32c_sse42_choose.o" { $as_echo "$as_me:${as_lineno-$LINENO}: result: SSE 4.2" >&5 $as_echo "SSE 4.2" >&6; } else @@ -18058,6 +18206,71 @@ $as_echo "slicing-by-8" >&6; } fi +# Check for carryless multiplication intrinsics to do vectorized CRC calculations. +# +if test x"$host_cpu" = x"x86_64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _mm512_clmulepi64_epi128" >&5 +$as_echo_n "checking for _mm512_clmulepi64_epi128... " >&6; } +if ${pgac_cv_avx512_pclmul_intrinsics+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + __m512i x; + __m512i y; + + #if defined(__has_attribute) && __has_attribute (target) + __attribute__((target("vpclmulqdq,avx512vl"))) + #endif + static int avx512_pclmul_test(void) + { + __m128i z; + + y = _mm512_clmulepi64_epi128(x, y, 0); + z = _mm_ternarylogic_epi64( + _mm512_castsi512_si128(y), + _mm512_extracti32x4_epi32(y, 1), + _mm512_extracti32x4_epi32(y, 2), + 0x96); + return _mm_crc32_u64(0, _mm_extract_epi64(z, 0)); + } +int +main () +{ +return avx512_pclmul_test(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pgac_cv_avx512_pclmul_intrinsics=yes +else + pgac_cv_avx512_pclmul_intrinsics=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_avx512_pclmul_intrinsics" >&5 +$as_echo "$pgac_cv_avx512_pclmul_intrinsics" >&6; } +if test x"$pgac_cv_avx512_pclmul_intrinsics" = x"yes"; then + pgac_avx512_pclmul_intrinsics=yes +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for vectorized CRC-32C" >&5 +$as_echo_n "checking for vectorized CRC-32C... " >&6; } +if test x"$pgac_avx512_pclmul_intrinsics" = x"yes"; then + +$as_echo "#define USE_AVX512_CRC32C_WITH_RUNTIME_CHECK 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: AVX-512 with runtime check" >&5 +$as_echo "AVX-512 with runtime check" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi # Select semaphore implementation type. if test "$PORTNAME" != "win32"; then @@ -19159,6 +19372,9 @@ fi # For linkers that understand --export-dynamic, add that to the LDFLAGS_EX_BE # (backend specific ldflags). One some platforms this will always fail (e.g., # windows), but on others it depends on the choice of linker (e.g., solaris). +# macOS uses -export_dynamic instead. (On macOS, the option is only +# needed when also using -flto, but we add it anyway since it's +# harmless.) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wl,--export-dynamic, for LDFLAGS_EX_BE" >&5 $as_echo_n "checking whether $CC supports -Wl,--export-dynamic, for LDFLAGS_EX_BE... " >&6; } if ${pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl___export_dynamic+:} false; then : @@ -19197,6 +19413,46 @@ if test x"$pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl___export_dynamic" = x"yes"; then LDFLAGS_EX_BE="${LDFLAGS_EX_BE} -Wl,--export-dynamic" fi +if test x"$LDFLAGS_EX_BE" = x""; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wl,-export_dynamic, for LDFLAGS_EX_BE" >&5 +$as_echo_n "checking whether $CC supports -Wl,-export_dynamic, for LDFLAGS_EX_BE... " >&6; } +if ${pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic+:} false; then : + $as_echo_n "(cached) " >&6 +else + pgac_save_LDFLAGS=$LDFLAGS +LDFLAGS="$pgac_save_LDFLAGS -Wl,-export_dynamic" +if test "$cross_compiling" = yes; then : + pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic="assuming no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern void $link_test_func (); void (*fptr) () = $link_test_func; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic=yes +else + pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +LDFLAGS="$pgac_save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic" >&5 +$as_echo "$pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic" >&6; } +if test x"$pgac_cv_prog_cc_LDFLAGS_EX_BE__Wl__export_dynamic" = x"yes"; then + LDFLAGS_EX_BE="${LDFLAGS_EX_BE} -Wl,-export_dynamic" +fi + +fi # Create compiler version string @@ -19296,9 +19552,6 @@ fi ac_config_headers="$ac_config_headers src/include/pg_config.h" -ac_config_headers="$ac_config_headers src/include/pg_config_ext.h" - - ac_config_headers="$ac_config_headers src/interfaces/ecpg/include/ecpg_config.h" @@ -19809,7 +20062,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by PostgreSQL $as_me 18devel, which was +This file was extended by PostgreSQL $as_me 18beta1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19880,7 +20133,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -PostgreSQL config.status 18devel +PostgreSQL config.status 18beta1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -20013,7 +20266,6 @@ do "src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;; "check_win32_symlinks") CONFIG_COMMANDS="$CONFIG_COMMANDS check_win32_symlinks" ;; "src/include/pg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config.h" ;; - "src/include/pg_config_ext.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/pg_config_ext.h" ;; "src/interfaces/ecpg/include/ecpg_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/interfaces/ecpg/include/ecpg_config.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; @@ -20621,10 +20873,6 @@ $as_echo "$as_me: WARNING: *** link for $FILE -- please fix by hand" >&2;} "src/include/pg_config.h":H) # Update timestamp for pg_config.h (see Makefile.global) echo >src/include/stamp-h - ;; - "src/include/pg_config_ext.h":H) -# Update timestamp for pg_config_ext.h (see Makefile.global) -echo >src/include/stamp-ext-h ;; "src/interfaces/ecpg/include/ecpg_config.h":H) echo >src/interfaces/ecpg/include/stamp-h ;; diff --git a/configure.ac b/configure.ac index 0089e78b687ae..4b8335dc6138e 100644 --- a/configure.ac +++ b/configure.ac @@ -17,13 +17,13 @@ dnl Read the Autoconf manual for details. dnl m4_pattern_forbid(^PGAC_)dnl to catch undefined macros -AC_INIT([PostgreSQL], [18devel], [pgsql-bugs@lists.postgresql.org], [], [https://www.postgresql.org/]) +AC_INIT([PostgreSQL], [18beta1], [pgsql-bugs@lists.postgresql.org], [], [https://www.postgresql.org/]) m4_if(m4_defn([m4_PACKAGE_VERSION]), [2.69], [], [m4_fatal([Autoconf version 2.69 is required. Untested combinations of 'autoconf' and PostgreSQL versions are not recommended. You can remove the check from 'configure.ac' but it is then your responsibility whether the result works or not.])]) -AC_COPYRIGHT([Copyright (c) 1996-2024, PostgreSQL Global Development Group]) +AC_COPYRIGHT([Copyright (c) 1996-2025, PostgreSQL Global Development Group]) AC_CONFIG_SRCDIR([src/backend/access/common/heaptuple.c]) AC_CONFIG_AUX_DIR(config) AC_PREFIX_DEFAULT(/usr/local/pgsql) @@ -186,18 +186,6 @@ PGAC_ARG_BOOL(enable, rpath, yes, [do not embed shared library search path in executables]) AC_SUBST(enable_rpath) -# -# Spinlocks -# -PGAC_ARG_BOOL(enable, spinlocks, yes, - [do not use spinlocks]) - -# -# Atomic operations -# -PGAC_ARG_BOOL(enable, atomics, yes, - [do not use atomic operations]) - # # --enable-debug adds -g to compiler flags # @@ -248,6 +236,8 @@ AC_SUBST(enable_dtrace) PGAC_ARG_BOOL(enable, tap-tests, no, [enable TAP tests (requires Perl and IPC::Run)]) AC_SUBST(enable_tap_tests) +AC_ARG_VAR(PG_TEST_EXTRA, + [enable selected extra tests (overridden at runtime by PG_TEST_EXTRA environment variable)]) # # Injection points @@ -530,6 +520,15 @@ if test "$GCC" = yes -a "$ICC" = no; then # This was included in -Wall/-Wformat in older GCC versions PGAC_PROG_CC_CFLAGS_OPT([-Wformat-security]) PGAC_PROG_CXX_CFLAGS_OPT([-Wformat-security]) + # gcc 14+, clang for a while + # (Supported in C++ by clang but not gcc. For consistency, omit in C++.) + save_CFLAGS=$CFLAGS + PGAC_PROG_CC_CFLAGS_OPT([-Wmissing-variable-declarations]) + PERMIT_MISSING_VARIABLE_DECLARATIONS= + if test x"$save_CFLAGS" != x"$CFLAGS"; then + PERMIT_MISSING_VARIABLE_DECLARATIONS=-Wno-missing-variable-declarations + fi + AC_SUBST(PERMIT_MISSING_VARIABLE_DECLARATIONS) # Disable strict-aliasing rules; needed for gcc 3.3+ PGAC_PROG_CC_CFLAGS_OPT([-fno-strict-aliasing]) PGAC_PROG_CXX_CFLAGS_OPT([-fno-strict-aliasing]) @@ -634,8 +633,12 @@ if test "$with_llvm" = yes ; then PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-fexcess-precision=standard]) PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANGXX, BITCODE_CXXFLAGS, [-fexcess-precision=standard]) - PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-Xclang -no-opaque-pointers]) - PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANGXX, BITCODE_CXXFLAGS, [-Xclang -no-opaque-pointers]) + # Ideally bitcode should perhaps match $CC's use, or not, of outline atomic + # functions, but for now we err on the side of suppressing them in bitcode, + # because we can't assume they're available at runtime. This affects aarch64 + # builds using the basic armv8-a ISA without LSE support. + PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANG, BITCODE_CFLAGS, [-mno-outline-atomics]) + PGAC_PROG_VARCXX_VARFLAGS_OPT(CLANG, BITCODE_CXXFLAGS, [-mno-outline-atomics]) NOT_THE_CFLAGS="" PGAC_PROG_VARCC_VARFLAGS_OPT(CLANG, NOT_THE_CFLAGS, [-Wunused-command-line-argument]) @@ -690,10 +693,10 @@ if test "$enable_profiling" = yes && test "$ac_cv_prog_cc_g" = yes; then fi fi -# On Solaris, we need this #define to get POSIX-conforming versions -# of many interfaces (sigwait, getpwuid_r, ...). +# On Solaris, we need these #defines to get POSIX-conforming versions +# of many interfaces (sigwait, getpwuid_r, shmdt, ...). if test "$PORTNAME" = "solaris"; then - CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS" + CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS" fi # We already have this in Makefile.win32, but configure needs it too @@ -804,7 +807,6 @@ for dir in $with_includes $SRCH_INC; do fi done IFS=$ac_save_IFS -AC_SUBST(INCLUDES) # @@ -832,11 +834,7 @@ AC_MSG_RESULT([$with_icu]) AC_SUBST(with_icu) if test "$with_icu" = yes; then - PKG_CHECK_MODULES(ICU, icu-uc icu-i18n, [], - [AC_MSG_ERROR([ICU library not found -If you have ICU already installed, see config.log for details on the -failure. It is possible the compiler isn't looking in the proper directory. -Use --without-icu to disable ICU support.])]) + PKG_CHECK_MODULES(ICU, icu-uc icu-i18n) fi # @@ -977,6 +975,18 @@ AC_SUBST(with_readline) PGAC_ARG_BOOL(with, libedit-preferred, no, [prefer BSD Libedit over GNU Readline]) +# +# liburing +# +AC_MSG_CHECKING([whether to build with liburing support]) +PGAC_ARG_BOOL(with, liburing, no, [build with io_uring support, for asynchronous I/O], + [AC_DEFINE([USE_LIBURING], 1, [Define to build with io_uring support. (--with-liburing)])]) +AC_MSG_RESULT([$with_liburing]) +AC_SUBST(with_liburing) + +if test "$with_liburing" = yes; then + PKG_CHECK_MODULES(LIBURING, liburing) +fi # # UUID library @@ -1009,6 +1019,62 @@ fi AC_SUBST(with_uuid) +# +# libcurl +# +AC_MSG_CHECKING([whether to build with libcurl support]) +PGAC_ARG_BOOL(with, libcurl, no, [build with libcurl support], + [AC_DEFINE([USE_LIBCURL], 1, [Define to 1 to build with libcurl support. (--with-libcurl)])]) +AC_MSG_RESULT([$with_libcurl]) +AC_SUBST(with_libcurl) + +if test "$with_libcurl" = yes ; then + # Check for libcurl 7.61.0 or higher (corresponding to RHEL8 and the ability + # to explicitly set TLS 1.3 ciphersuites). + PKG_CHECK_MODULES(LIBCURL, [libcurl >= 7.61.0]) + + # Curl's flags are kept separate from the standard CPPFLAGS/LDFLAGS. We use + # them only for libpq-oauth. + LIBCURL_CPPFLAGS= + LIBCURL_LDFLAGS= + + # We only care about -I, -D, and -L switches. Note that -lcurl will be added + # to LIBCURL_LDLIBS by PGAC_CHECK_LIBCURL, below. + for pgac_option in $LIBCURL_CFLAGS; do + case $pgac_option in + -I*|-D*) LIBCURL_CPPFLAGS="$LIBCURL_CPPFLAGS $pgac_option";; + esac + done + for pgac_option in $LIBCURL_LIBS; do + case $pgac_option in + -L*) LIBCURL_LDFLAGS="$LIBCURL_LDFLAGS $pgac_option";; + esac + done + + AC_SUBST(LIBCURL_CPPFLAGS) + AC_SUBST(LIBCURL_LDFLAGS) + + # OAuth requires python for testing + if test "$with_python" != yes; then + AC_MSG_WARN([*** OAuth support tests require --with-python to run]) + fi +fi + + +# +# libnuma +# +AC_MSG_CHECKING([whether to build with libnuma support]) +PGAC_ARG_BOOL(with, libnuma, no, [build with libnuma support], + [AC_DEFINE([USE_LIBNUMA], 1, [Define to build with NUMA support. (--with-libnuma)])]) +AC_MSG_RESULT([$with_libnuma]) +AC_SUBST(with_libnuma) + +if test "$with_libnuma" = yes ; then + AC_CHECK_LIB(numa, numa_available, [], [AC_MSG_ERROR([library 'libnuma' is required for NUMA support])]) + PKG_CHECK_MODULES(LIBNUMA, numa) +fi + # # XML # @@ -1296,18 +1362,8 @@ failure. It is possible the compiler isn't looking in the proper directory. Use --without-zlib to disable zlib support.])]) fi -if test "$enable_spinlocks" = yes; then - AC_DEFINE(HAVE_SPINLOCKS, 1, [Define to 1 if you have spinlocks.]) -else - AC_MSG_WARN([ -*** Not using spinlocks will cause poor performance.]) -fi - -if test "$enable_atomics" = yes; then - AC_DEFINE(HAVE_ATOMICS, 1, [Define to 1 if you want to use atomics if available.]) -else - AC_MSG_WARN([ -*** Not using atomic operations will cause poor performance.]) +if test "$with_libcurl" = yes ; then + PGAC_CHECK_LIBCURL fi if test "$with_gssapi" = yes ; then @@ -1335,30 +1391,17 @@ fi if test "$with_ssl" = openssl ; then dnl Order matters! - # Minimum required OpenSSL version is 1.0.2 - AC_DEFINE(OPENSSL_API_COMPAT, [0x10002000L], + # Minimum required OpenSSL version is 1.1.1 + AC_DEFINE(OPENSSL_API_COMPAT, [0x10101000L], [Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.]) - if test "$PORTNAME" != "win32"; then - AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])]) - AC_CHECK_LIB(ssl, SSL_new, [], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])]) - else - AC_SEARCH_LIBS(CRYPTO_new_ex_data, [eay32 crypto], [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])]) - AC_SEARCH_LIBS(SSL_new, [ssleay32 ssl], [], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])]) - fi + AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])]) + AC_CHECK_LIB(ssl, SSL_new, [], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])]) + # Functions introduced in OpenSSL 1.1.1. + AC_CHECK_FUNCS([SSL_CTX_set_ciphersuites], [], [AC_MSG_ERROR([OpenSSL version >= 1.1.1 is required for SSL support])]) # Function introduced in OpenSSL 1.0.2, not in LibreSSL. AC_CHECK_FUNCS([SSL_CTX_set_cert_cb]) - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free]) - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - AC_CHECK_FUNCS([CRYPTO_lock]) - # Function introduced in OpenSSL 1.1.1. - AC_CHECK_FUNCS([X509_get_signature_info SSL_CTX_set_num_tickets]) + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. + AC_CHECK_FUNCS([X509_get_signature_info SSL_CTX_set_num_tickets SSL_CTX_set_keylog_callback]) AC_DEFINE([USE_OPENSSL], 1, [Define to 1 to build with OpenSSL support. (--with-ssl=openssl)]) elif test "$with_ssl" != no ; then AC_MSG_ERROR([--with-ssl must specify openssl]) @@ -1456,15 +1499,12 @@ AC_SUBST(UUID_LIBS) ## Header files ## -AC_HEADER_STDBOOL - AC_CHECK_HEADERS(m4_normalize([ atomic.h copyfile.h execinfo.h getopt.h ifaddrs.h - langinfo.h mbarrier.h sys/epoll.h sys/event.h @@ -1475,6 +1515,7 @@ AC_CHECK_HEADERS(m4_normalize([ sys/ucred.h termios.h ucred.h + xlocale.h ])) if expr x"$pgac_cv_check_readline" : 'x-lreadline' >/dev/null ; then @@ -1618,6 +1659,13 @@ if test "$PORTNAME" = "win32" ; then AC_CHECK_HEADERS(crtdefs.h) fi +if test "$with_libcurl" = yes ; then + # Error out early if this platform can't support libpq-oauth. + if test "$ac_cv_header_sys_event_h" != yes -a "$ac_cv_header_sys_epoll_h" != yes; then + AC_MSG_ERROR([client-side OAuth is not supported on this platform]) + fi +fi + ## ## Types, structures, compiler characteristics ## @@ -1630,6 +1678,7 @@ PGAC_C_STATIC_ASSERT PGAC_C_TYPEOF PGAC_C_TYPES_COMPATIBLE PGAC_C_BUILTIN_CONSTANT_P +PGAC_C_BUILTIN_OP_OVERFLOW PGAC_C_BUILTIN_UNREACHABLE PGAC_C_COMPUTED_GOTO PGAC_STRUCT_TIMEZONE @@ -1637,8 +1686,6 @@ PGAC_UNION_SEMUN AC_CHECK_TYPES(socklen_t, [], [], [#include ]) PGAC_STRUCT_SOCKADDR_SA_LEN -PGAC_TYPE_LOCALE_T - # MSVC doesn't cope well with defining restrict to __restrict, the # spelling it understands, because it conflicts with # __declspec(restrict). Therefore we define pg_restrict to the @@ -1719,25 +1766,12 @@ if test "$ac_cv_sizeof_off_t" -lt 8; then fi fi -AC_CHECK_SIZEOF([bool], [], -[#ifdef HAVE_STDBOOL_H -#include -#endif]) - -dnl We use if we have it and it declares type bool as having -dnl size 1. Otherwise, c.h will fall back to declaring bool as unsigned char. -if test "$ac_cv_header_stdbool_h" = yes -a "$ac_cv_sizeof_bool" = 1; then - AC_DEFINE([PG_USE_STDBOOL], 1, - [Define to 1 to use to define type bool.]) -fi - ## ## Functions, global variables ## PGAC_VAR_INT_TIMEZONE -PGAC_FUNC_WCSTOMBS_L # Some versions of libedit contain strlcpy(), setproctitle(), and other # symbols that that library has no business exposing to the world. Pending @@ -1750,18 +1784,19 @@ AC_CHECK_FUNCS(m4_normalize([ backtrace_symbols copyfile copy_file_range + elf_aux_info + getauxval getifaddrs getpeerucred inet_pton kqueue + localeconv_l mbstowcs_l - memset_s posix_fallocate ppoll pthread_is_threaded_np setproctitle setproctitle_fast - strchrnul strsignal syncfs sync_file_range @@ -1795,12 +1830,15 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include ]) ]) # fi AC_CHECK_DECLS(fdatasync, [], [], [#include ]) -AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep]) +AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep, timingsafe_bcmp]) # We can't use AC_CHECK_FUNCS to detect these functions, because it # won't handle deployment target restrictions on macOS AC_CHECK_DECLS([preadv], [], [], [#include ]) AC_CHECK_DECLS([pwritev], [], [], [#include ]) +AC_CHECK_DECLS([strchrnul], [], [], [#include ]) +AC_CHECK_DECLS([memset_s], [], [], [#define __STDC_WANT_LIB_EXT1__ 1 +#include ]) # This is probably only present on macOS, but may as well check always AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include ]) @@ -1815,6 +1853,7 @@ AC_REPLACE_FUNCS(m4_normalize([ strlcpy strnlen strsep + timingsafe_bcmp ])) AC_REPLACE_FUNCS(pthread_barrier_wait) @@ -1850,7 +1889,6 @@ fi # Win32 (really MinGW) support if test "$PORTNAME" = "win32"; then - AC_CHECK_FUNCS(_configthreadlocale) AC_LIBOBJ(dirmod) AC_LIBOBJ(kill) AC_LIBOBJ(open) @@ -1946,54 +1984,18 @@ for the exact reason.]])], # Run tests below here # -------------------- -dnl Check to see if we have a working 64-bit integer type. -dnl Since Postgres 8.4, we no longer support compilers without a working -dnl 64-bit type; but we have to determine whether that type is called -dnl "long int" or "long long int". - -PGAC_TYPE_64BIT_INT([long int]) - -if test x"$HAVE_LONG_INT_64" = x"yes" ; then - pg_int64_type="long int" -else - PGAC_TYPE_64BIT_INT([long long int]) - if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then - pg_int64_type="long long int" - else - AC_MSG_ERROR([Cannot find a working 64-bit integer type.]) - fi -fi - -AC_DEFINE_UNQUOTED(PG_INT64_TYPE, $pg_int64_type, - [Define to the name of a signed 64-bit integer type.]) - -# Select the printf length modifier that goes with that, too. -if test x"$pg_int64_type" = x"long long int" ; then - INT64_MODIFIER='"ll"' -else - INT64_MODIFIER='"l"' -fi - -AC_DEFINE_UNQUOTED(INT64_MODIFIER, $INT64_MODIFIER, - [Define to the appropriate printf length modifier for 64-bit ints.]) - -# has to be down here, rather than with the other builtins, because -# the test uses PG_INT64_TYPE. -PGAC_C_BUILTIN_OP_OVERFLOW - # Check size of void *, size_t (enables tweaks for > 32bit address space) AC_CHECK_SIZEOF([void *]) AC_CHECK_SIZEOF([size_t]) AC_CHECK_SIZEOF([long]) +AC_CHECK_SIZEOF([long long]) # Determine memory alignment requirements for the basic C data types. AC_CHECK_ALIGNOF(short) AC_CHECK_ALIGNOF(int) AC_CHECK_ALIGNOF(long) -if test x"$HAVE_LONG_LONG_INT_64" = x"yes" ; then - AC_CHECK_ALIGNOF(long long int) -fi +AC_CHECK_ALIGNOF(int64_t) AC_CHECK_ALIGNOF(double) # Compute maximum alignment of any basic type. @@ -2017,17 +2019,11 @@ MAX_ALIGNOF=$ac_cv_alignof_double if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double']) fi -if test x"$HAVE_LONG_LONG_INT_64" = xyes && test $ac_cv_alignof_long_long_int -gt $MAX_ALIGNOF ; then - AC_MSG_ERROR([alignment of 'long long int' is greater than the alignment of 'double']) +if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then + AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 'double']) fi AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum alignment requirement of any C data type.]) - -# Some platforms predefine the types int8, int16, etc. Only check -# a (hopefully) representative subset. -AC_CHECK_TYPES([int8, uint8, int64, uint64], [], [], -[#include ]) - # Some compilers offer a 128-bit integer scalar type. PGAC_TYPE_128BIT_INT @@ -2088,43 +2084,33 @@ fi # Check for XSAVE intrinsics # -CFLAGS_XSAVE="" -PGAC_XSAVE_INTRINSICS([]) -if test x"$pgac_xsave_intrinsics" != x"yes"; then - PGAC_XSAVE_INTRINSICS([-mxsave]) -fi +PGAC_XSAVE_INTRINSICS() if test x"$pgac_xsave_intrinsics" = x"yes"; then AC_DEFINE(HAVE_XSAVE_INTRINSICS, 1, [Define to 1 if you have XSAVE intrinsics.]) fi -AC_SUBST(CFLAGS_XSAVE) # Check for AVX-512 popcount intrinsics # -CFLAGS_POPCNT="" -PG_POPCNT_OBJS="" if test x"$host_cpu" = x"x86_64"; then - PGAC_AVX512_POPCNT_INTRINSICS([]) - if test x"$pgac_avx512_popcnt_intrinsics" != x"yes"; then - PGAC_AVX512_POPCNT_INTRINSICS([-mavx512vpopcntdq -mavx512bw]) - fi + PGAC_AVX512_POPCNT_INTRINSICS() if test x"$pgac_avx512_popcnt_intrinsics" = x"yes"; then - PG_POPCNT_OBJS="pg_popcount_avx512.o pg_popcount_avx512_choose.o" AC_DEFINE(USE_AVX512_POPCNT_WITH_RUNTIME_CHECK, 1, [Define to 1 to use AVX-512 popcount instructions with a runtime check.]) fi fi -AC_SUBST(CFLAGS_POPCNT) -AC_SUBST(PG_POPCNT_OBJS) -# Check for Intel SSE 4.2 intrinsics to do CRC calculations. +# Check for SVE popcount intrinsics # -# First check if the _mm_crc32_u8 and _mm_crc32_u64 intrinsics can be used -# with the default compiler flags. If not, check if adding the -msse4.2 -# flag helps. CFLAGS_CRC is set to -msse4.2 if that's required. -PGAC_SSE42_CRC32_INTRINSICS([]) -if test x"$pgac_sse42_crc32_intrinsics" != x"yes"; then - PGAC_SSE42_CRC32_INTRINSICS([-msse4.2]) +if test x"$host_cpu" = x"aarch64"; then + PGAC_SVE_POPCNT_INTRINSICS() + if test x"$pgac_sve_popcnt_intrinsics" = x"yes"; then + AC_DEFINE(USE_SVE_POPCNT_WITH_RUNTIME_CHECK, 1, [Define to 1 to use SVE popcount instructions with a runtime check.]) + fi fi +# Check for Intel SSE 4.2 intrinsics to do CRC calculations. +# +PGAC_SSE42_CRC32_INTRINSICS() + # Are we targeting a processor that supports SSE 4.2? gcc, clang and icc all # define __SSE4_2__ in that case. AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ @@ -2136,11 +2122,15 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ # Check for ARMv8 CRC Extension intrinsics to do CRC calculations. # # First check if __crc32c* intrinsics can be used with the default compiler -# flags. If not, check if adding -march=armv8-a+crc flag helps. +# flags. If not, check if adding "-march=armv8-a+crc+simd" flag helps. +# On systems using soft-float ABI, "-march=armv8-a+crc" is required instead. # CFLAGS_CRC is set if the extra flag is required. PGAC_ARMV8_CRC32C_INTRINSICS([]) if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then - PGAC_ARMV8_CRC32C_INTRINSICS([-march=armv8-a+crc]) + PGAC_ARMV8_CRC32C_INTRINSICS([-march=armv8-a+crc+simd]) + if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then + PGAC_ARMV8_CRC32C_INTRINSICS([-march=armv8-a+crc]) + fi fi # Check for LoongArch CRC intrinsics to do CRC calculations. @@ -2153,17 +2143,26 @@ AC_SUBST(CFLAGS_CRC) # Select CRC-32C implementation. # -# If we are targeting a processor that has Intel SSE 4.2 instructions, we can -# use the special CRC instructions for calculating CRC-32C. If we're not -# targeting such a processor, but we can nevertheless produce code that uses -# the SSE intrinsics, perhaps with some extra CFLAGS, compile both -# implementations and select which one to use at runtime, depending on whether -# SSE 4.2 is supported by the processor we're running on. +# There are three methods of calculating CRC, in order of increasing +# performance: +# +# 1. The fallback using a lookup table, called slicing-by-8 +# 2. CRC-32C instructions (found in e.g. Intel SSE 4.2 and ARMv8 CRC Extension) +# 3. Algorithms using carryless multiplication instructions +# (e.g. Intel PCLMUL and Arm PMULL) +# +# If we can produce code (via function attributes or additional compiler +# flags) that uses #2 (and possibly #3), we compile all implementations +# and select which one to use at runtime, depending on what is supported +# by the processor we're running on. # -# Similarly, if we are targeting an ARM processor that has the CRC -# instructions that are part of the ARMv8 CRC Extension, use them. And if -# we're not targeting such a processor, but can nevertheless produce code that -# uses the CRC instructions, compile both, and select at runtime. +# If we are targeting a processor that has #2, we can use that without +# runtime selection. +# +# Note that we do not use __attribute__((target("..."))) for the ARM CRC +# instructions because until clang 16, using the ARM intrinsics still requires +# special -march flags. Perhaps we can re-evaluate this decision after some +# time has passed. # # You can skip the runtime check by setting the appropriate USE_*_CRC32 flag to 1 # in the template or configure command line. @@ -2206,7 +2205,7 @@ fi AC_MSG_CHECKING([which CRC-32C implementation to use]) if test x"$USE_SSE42_CRC32C" = x"1"; then AC_DEFINE(USE_SSE42_CRC32C, 1, [Define to 1 use Intel SSE 4.2 CRC instructions.]) - PG_CRC32C_OBJS="pg_crc32c_sse42.o" + PG_CRC32C_OBJS="pg_crc32c_sse42.o pg_crc32c_sse42_choose.o" AC_MSG_RESULT(SSE 4.2) else if test x"$USE_SSE42_CRC32C_WITH_RUNTIME_CHECK" = x"1"; then @@ -2239,6 +2238,19 @@ else fi AC_SUBST(PG_CRC32C_OBJS) +# Check for carryless multiplication intrinsics to do vectorized CRC calculations. +# +if test x"$host_cpu" = x"x86_64"; then + PGAC_AVX512_PCLMUL_INTRINSICS() +fi + +AC_MSG_CHECKING([for vectorized CRC-32C]) +if test x"$pgac_avx512_pclmul_intrinsics" = x"yes"; then + AC_DEFINE(USE_AVX512_CRC32C_WITH_RUNTIME_CHECK, 1, [Define to 1 to use AVX-512 CRC algorithms with a runtime check.]) + AC_MSG_RESULT(AVX-512 with runtime check) +else + AC_MSG_RESULT(none) +fi # Select semaphore implementation type. if test "$PORTNAME" != "win32"; then @@ -2424,7 +2436,13 @@ fi # For linkers that understand --export-dynamic, add that to the LDFLAGS_EX_BE # (backend specific ldflags). One some platforms this will always fail (e.g., # windows), but on others it depends on the choice of linker (e.g., solaris). +# macOS uses -export_dynamic instead. (On macOS, the option is only +# needed when also using -flto, but we add it anyway since it's +# harmless.) PGAC_PROG_CC_LD_VARFLAGS_OPT(LDFLAGS_EX_BE, [-Wl,--export-dynamic], $link_test_func) +if test x"$LDFLAGS_EX_BE" = x""; then + PGAC_PROG_CC_LD_VARFLAGS_OPT(LDFLAGS_EX_BE, [-Wl,-export_dynamic], $link_test_func) +fi AC_SUBST(LDFLAGS_EX_BE) # Create compiler version string @@ -2521,12 +2539,6 @@ AC_CONFIG_HEADERS([src/include/pg_config.h], echo >src/include/stamp-h ]) -AC_CONFIG_HEADERS([src/include/pg_config_ext.h], -[ -# Update timestamp for pg_config_ext.h (see Makefile.global) -echo >src/include/stamp-ext-h -]) - AC_CONFIG_HEADERS([src/interfaces/ecpg/include/ecpg_config.h], [echo >src/interfaces/ecpg/include/stamp-h]) diff --git a/contrib/Makefile b/contrib/Makefile index abd780f277405..2f0a88d3f7744 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -32,6 +32,8 @@ SUBDIRS = \ passwordcheck \ pg_buffercache \ pg_freespacemap \ + pg_logicalinspect \ + pg_overexplain \ pg_prewarm \ pg_stat_statements \ pg_surgery \ diff --git a/contrib/amcheck/Makefile b/contrib/amcheck/Makefile index 5e9002d250181..1b7a63cbaa40c 100644 --- a/contrib/amcheck/Makefile +++ b/contrib/amcheck/Makefile @@ -3,14 +3,17 @@ MODULE_big = amcheck OBJS = \ $(WIN32RES) \ + verify_common.o \ + verify_gin.o \ verify_heapam.o \ verify_nbtree.o EXTENSION = amcheck -DATA = amcheck--1.3--1.4.sql amcheck--1.2--1.3.sql amcheck--1.1--1.2.sql amcheck--1.0--1.1.sql amcheck--1.0.sql +DATA = amcheck--1.2--1.3.sql amcheck--1.1--1.2.sql amcheck--1.0--1.1.sql amcheck--1.0.sql \ + amcheck--1.3--1.4.sql amcheck--1.4--1.5.sql PGFILEDESC = "amcheck - function for verifying relation integrity" -REGRESS = check check_btree check_heap +REGRESS = check check_btree check_gin check_heap EXTRA_INSTALL = contrib/pg_walinspect TAP_TESTS = 1 diff --git a/contrib/amcheck/amcheck--1.4--1.5.sql b/contrib/amcheck/amcheck--1.4--1.5.sql new file mode 100644 index 0000000000000..445c48ccb7d72 --- /dev/null +++ b/contrib/amcheck/amcheck--1.4--1.5.sql @@ -0,0 +1,14 @@ +/* contrib/amcheck/amcheck--1.4--1.5.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION amcheck UPDATE TO '1.5'" to load this file. \quit + + +-- gin_index_check() +-- +CREATE FUNCTION gin_index_check(index regclass) +RETURNS VOID +AS 'MODULE_PATHNAME', 'gin_index_check' +LANGUAGE C STRICT; + +REVOKE ALL ON FUNCTION gin_index_check(regclass) FROM PUBLIC; diff --git a/contrib/amcheck/amcheck.control b/contrib/amcheck/amcheck.control index e67ace01c995f..c8ba6d7c9bc36 100644 --- a/contrib/amcheck/amcheck.control +++ b/contrib/amcheck/amcheck.control @@ -1,5 +1,5 @@ # amcheck extension comment = 'functions for verifying relation integrity' -default_version = '1.4' +default_version = '1.5' module_pathname = '$libdir/amcheck' relocatable = true diff --git a/contrib/amcheck/expected/check_btree.out b/contrib/amcheck/expected/check_btree.out index e7fb5f551574a..c6f4b16c55615 100644 --- a/contrib/amcheck/expected/check_btree.out +++ b/contrib/amcheck/expected/check_btree.out @@ -57,8 +57,8 @@ ERROR: could not open relation with OID 17 BEGIN; CREATE INDEX bttest_a_brin_idx ON bttest_a USING brin(id); SELECT bt_index_parent_check('bttest_a_brin_idx'); -ERROR: only B-Tree indexes are supported as targets for verification -DETAIL: Relation "bttest_a_brin_idx" is not a B-Tree index. +ERROR: expected "btree" index as targets for verification +DETAIL: Relation "bttest_a_brin_idx" is a brin index. ROLLBACK; -- normal check outside of xact SELECT bt_index_check('bttest_a_idx'); diff --git a/contrib/amcheck/expected/check_gin.out b/contrib/amcheck/expected/check_gin.out new file mode 100644 index 0000000000000..8dd01ced8d15f --- /dev/null +++ b/contrib/amcheck/expected/check_gin.out @@ -0,0 +1,90 @@ +-- Test of index bulk load +SELECT setseed(1); + setseed +--------- + +(1 row) + +CREATE TABLE "gin_check"("Column1" int[]); +-- posting trees (frequently used entries) +INSERT INTO gin_check select array_agg(round(random()*255) ) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves (sparse entries) +INSERT INTO gin_check select array_agg(255 + round(random()*100)) from generate_series(1, 100) as i group by i % 100; +CREATE INDEX gin_check_idx on "gin_check" USING GIN("Column1"); +SELECT gin_index_check('gin_check_idx'); + gin_index_check +----------------- + +(1 row) + +-- cleanup +DROP TABLE gin_check; +-- Test index inserts +SELECT setseed(1); + setseed +--------- + +(1 row) + +CREATE TABLE "gin_check"("Column1" int[]); +CREATE INDEX gin_check_idx on "gin_check" USING GIN("Column1"); +ALTER INDEX gin_check_idx SET (fastupdate = false); +-- posting trees +INSERT INTO gin_check select array_agg(round(random()*255) ) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves +INSERT INTO gin_check select array_agg(100 + round(random()*255)) from generate_series(1, 100) as i group by i % 100; +SELECT gin_index_check('gin_check_idx'); + gin_index_check +----------------- + +(1 row) + +-- cleanup +DROP TABLE gin_check; +-- Test GIN over text array +SELECT setseed(1); + setseed +--------- + +(1 row) + +CREATE TABLE "gin_check_text_array"("Column1" text[]); +-- posting trees +INSERT INTO gin_check_text_array select array_agg(sha256(round(random()*300)::text::bytea)::text) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves +INSERT INTO gin_check_text_array select array_agg(sha256(round(random()*300 + 300)::text::bytea)::text) from generate_series(1, 10000) as i group by i % 100; +CREATE INDEX gin_check_text_array_idx on "gin_check_text_array" USING GIN("Column1"); +SELECT gin_index_check('gin_check_text_array_idx'); + gin_index_check +----------------- + +(1 row) + +-- cleanup +DROP TABLE gin_check_text_array; +-- Test GIN over jsonb +CREATE TABLE "gin_check_jsonb"("j" jsonb); +INSERT INTO gin_check_jsonb values ('{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}'); +INSERT INTO gin_check_jsonb values ('[[14,2,3]]'); +INSERT INTO gin_check_jsonb values ('[1,[14,2,3]]'); +CREATE INDEX "gin_check_jsonb_idx" on gin_check_jsonb USING GIN("j" jsonb_path_ops); +SELECT gin_index_check('gin_check_jsonb_idx'); + gin_index_check +----------------- + +(1 row) + +-- cleanup +DROP TABLE gin_check_jsonb; +-- Test GIN multicolumn index +CREATE TABLE "gin_check_multicolumn"(a text[], b text[]); +INSERT INTO gin_check_multicolumn (a,b) values ('{a,c,e}','{b,d,f}'); +CREATE INDEX "gin_check_multicolumn_idx" on gin_check_multicolumn USING GIN(a,b); +SELECT gin_index_check('gin_check_multicolumn_idx'); + gin_index_check +----------------- + +(1 row) + +-- cleanup +DROP TABLE gin_check_multicolumn; diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build index fc08e32539a75..1f0c347ed5413 100644 --- a/contrib/amcheck/meson.build +++ b/contrib/amcheck/meson.build @@ -1,6 +1,8 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group amcheck_sources = files( + 'verify_common.c', + 'verify_gin.c', 'verify_heapam.c', 'verify_nbtree.c', ) @@ -24,6 +26,7 @@ install_data( 'amcheck--1.1--1.2.sql', 'amcheck--1.2--1.3.sql', 'amcheck--1.3--1.4.sql', + 'amcheck--1.4--1.5.sql', kwargs: contrib_data_args, ) @@ -35,6 +38,7 @@ tests += { 'sql': [ 'check', 'check_btree', + 'check_gin', 'check_heap', ], }, @@ -45,6 +49,7 @@ tests += { 't/003_cic_2pc.pl', 't/004_verify_nbtree_unique.pl', 't/005_pitr.pl', + 't/006_verify_gin.pl', ], }, } diff --git a/contrib/amcheck/sql/check_gin.sql b/contrib/amcheck/sql/check_gin.sql new file mode 100644 index 0000000000000..11caed3d6a81b --- /dev/null +++ b/contrib/amcheck/sql/check_gin.sql @@ -0,0 +1,62 @@ +-- Test of index bulk load +SELECT setseed(1); +CREATE TABLE "gin_check"("Column1" int[]); +-- posting trees (frequently used entries) +INSERT INTO gin_check select array_agg(round(random()*255) ) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves (sparse entries) +INSERT INTO gin_check select array_agg(255 + round(random()*100)) from generate_series(1, 100) as i group by i % 100; +CREATE INDEX gin_check_idx on "gin_check" USING GIN("Column1"); +SELECT gin_index_check('gin_check_idx'); + +-- cleanup +DROP TABLE gin_check; + +-- Test index inserts +SELECT setseed(1); +CREATE TABLE "gin_check"("Column1" int[]); +CREATE INDEX gin_check_idx on "gin_check" USING GIN("Column1"); +ALTER INDEX gin_check_idx SET (fastupdate = false); +-- posting trees +INSERT INTO gin_check select array_agg(round(random()*255) ) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves +INSERT INTO gin_check select array_agg(100 + round(random()*255)) from generate_series(1, 100) as i group by i % 100; + +SELECT gin_index_check('gin_check_idx'); + +-- cleanup +DROP TABLE gin_check; + +-- Test GIN over text array +SELECT setseed(1); +CREATE TABLE "gin_check_text_array"("Column1" text[]); +-- posting trees +INSERT INTO gin_check_text_array select array_agg(sha256(round(random()*300)::text::bytea)::text) from generate_series(1, 100000) as i group by i % 10000; +-- posting leaves +INSERT INTO gin_check_text_array select array_agg(sha256(round(random()*300 + 300)::text::bytea)::text) from generate_series(1, 10000) as i group by i % 100; +CREATE INDEX gin_check_text_array_idx on "gin_check_text_array" USING GIN("Column1"); +SELECT gin_index_check('gin_check_text_array_idx'); + +-- cleanup +DROP TABLE gin_check_text_array; + +-- Test GIN over jsonb +CREATE TABLE "gin_check_jsonb"("j" jsonb); +INSERT INTO gin_check_jsonb values ('{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}'); +INSERT INTO gin_check_jsonb values ('[[14,2,3]]'); +INSERT INTO gin_check_jsonb values ('[1,[14,2,3]]'); +CREATE INDEX "gin_check_jsonb_idx" on gin_check_jsonb USING GIN("j" jsonb_path_ops); + +SELECT gin_index_check('gin_check_jsonb_idx'); + +-- cleanup +DROP TABLE gin_check_jsonb; + +-- Test GIN multicolumn index +CREATE TABLE "gin_check_multicolumn"(a text[], b text[]); +INSERT INTO gin_check_multicolumn (a,b) values ('{a,c,e}','{b,d,f}'); +CREATE INDEX "gin_check_multicolumn_idx" on gin_check_multicolumn USING GIN(a,b); + +SELECT gin_index_check('gin_check_multicolumn_idx'); + +-- cleanup +DROP TABLE gin_check_multicolumn; diff --git a/contrib/amcheck/t/001_verify_heapam.pl b/contrib/amcheck/t/001_verify_heapam.pl index 481e4dbe4feae..701e27fc76d3e 100644 --- a/contrib/amcheck/t/001_verify_heapam.pl +++ b/contrib/amcheck/t/001_verify_heapam.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -15,7 +15,7 @@ # Test set-up # $node = PostgreSQL::Test::Cluster->new('test'); -$node->init; +$node->init(no_data_checksums => 1); $node->append_conf('postgresql.conf', 'autovacuum=off'); $node->start; $node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); diff --git a/contrib/amcheck/t/002_cic.pl b/contrib/amcheck/t/002_cic.pl index 0207407ca0e96..6a0c4f611258f 100644 --- a/contrib/amcheck/t/002_cic.pl +++ b/contrib/amcheck/t/002_cic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test CREATE INDEX CONCURRENTLY with concurrent modifications use strict; @@ -21,8 +21,9 @@ 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); $node->start; $node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); -$node->safe_psql('postgres', q(CREATE TABLE tbl(i int))); +$node->safe_psql('postgres', q(CREATE TABLE tbl(i int, j jsonb))); $node->safe_psql('postgres', q(CREATE INDEX idx ON tbl(i))); +$node->safe_psql('postgres', q(CREATE INDEX ginidx ON tbl USING gin(j))); # # Stress CIC with pgbench. @@ -40,13 +41,13 @@ { '002_pgbench_concurrent_transaction' => q( BEGIN; - INSERT INTO tbl VALUES(0); + INSERT INTO tbl VALUES(0, '{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}'); COMMIT; ), '002_pgbench_concurrent_transaction_savepoints' => q( BEGIN; SAVEPOINT s1; - INSERT INTO tbl VALUES(0); + INSERT INTO tbl VALUES(0, '[[14,2,3]]'); COMMIT; ), '002_pgbench_concurrent_cic' => q( @@ -54,7 +55,10 @@ \if :gotlock DROP INDEX CONCURRENTLY idx; CREATE INDEX CONCURRENTLY idx ON tbl(i); + DROP INDEX CONCURRENTLY ginidx; + CREATE INDEX CONCURRENTLY ginidx ON tbl USING gin(j); SELECT bt_index_check('idx',true); + SELECT gin_index_check('ginidx'); SELECT pg_advisory_unlock(42); \endif ) diff --git a/contrib/amcheck/t/003_cic_2pc.pl b/contrib/amcheck/t/003_cic_2pc.pl index fc314b8524e34..00a446a381faf 100644 --- a/contrib/amcheck/t/003_cic_2pc.pl +++ b/contrib/amcheck/t/003_cic_2pc.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test CREATE INDEX CONCURRENTLY with concurrent prepared-xact modifications use strict; @@ -25,7 +25,7 @@ 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); $node->start; $node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); -$node->safe_psql('postgres', q(CREATE TABLE tbl(i int))); +$node->safe_psql('postgres', q(CREATE TABLE tbl(i int, j jsonb))); # @@ -41,7 +41,7 @@ $main_h->query_safe( q( BEGIN; -INSERT INTO tbl VALUES(0); +INSERT INTO tbl VALUES(0, '[[14,2,3]]'); )); my $cic_h = $node->background_psql('postgres'); @@ -50,6 +50,7 @@ qr/start/, q( \echo start CREATE INDEX CONCURRENTLY idx ON tbl(i); +CREATE INDEX CONCURRENTLY ginidx ON tbl USING gin(j); )); $main_h->query_safe( @@ -60,7 +61,7 @@ $main_h->query_safe( q( BEGIN; -INSERT INTO tbl VALUES(0); +INSERT INTO tbl VALUES(0, '[[14,2,3]]'); )); $node->safe_psql('postgres', q(COMMIT PREPARED 'a';)); @@ -69,7 +70,7 @@ q( PREPARE TRANSACTION 'b'; BEGIN; -INSERT INTO tbl VALUES(0); +INSERT INTO tbl VALUES(0, '"mary had a little lamb"'); )); $node->safe_psql('postgres', q(COMMIT PREPARED 'b';)); @@ -86,6 +87,9 @@ $result = $node->psql('postgres', q(SELECT bt_index_check('idx',true))); is($result, '0', 'bt_index_check after overlapping 2PC'); +$result = $node->psql('postgres', q(SELECT gin_index_check('ginidx'))); +is($result, '0', 'gin_index_check after overlapping 2PC'); + # # Server restart shall not change whether prepared xact blocks CIC @@ -94,7 +98,7 @@ $node->safe_psql( 'postgres', q( BEGIN; -INSERT INTO tbl VALUES(0); +INSERT INTO tbl VALUES(0, '{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}'); PREPARE TRANSACTION 'spans_restart'; BEGIN; CREATE TABLE unused (); @@ -108,12 +112,16 @@ \echo start DROP INDEX CONCURRENTLY idx; CREATE INDEX CONCURRENTLY idx ON tbl(i); +DROP INDEX CONCURRENTLY ginidx; +CREATE INDEX CONCURRENTLY ginidx ON tbl USING gin(j); )); $node->safe_psql('postgres', "COMMIT PREPARED 'spans_restart'"); $reindex_h->quit; $result = $node->psql('postgres', q(SELECT bt_index_check('idx',true))); is($result, '0', 'bt_index_check after 2PC and restart'); +$result = $node->psql('postgres', q(SELECT gin_index_check('ginidx'))); +is($result, '0', 'gin_index_check after 2PC and restart'); # @@ -136,14 +144,14 @@ { '003_pgbench_concurrent_2pc' => q( BEGIN; - INSERT INTO tbl VALUES(0); + INSERT INTO tbl VALUES(0,'null'); PREPARE TRANSACTION 'c:client_id'; COMMIT PREPARED 'c:client_id'; ), '003_pgbench_concurrent_2pc_savepoint' => q( BEGIN; SAVEPOINT s1; - INSERT INTO tbl VALUES(0); + INSERT INTO tbl VALUES(0,'[false, "jnvaba", -76, 7, {"_": [1]}, 9]'); PREPARE TRANSACTION 'c:client_id'; COMMIT PREPARED 'c:client_id'; ), @@ -163,7 +171,25 @@ SELECT bt_index_check('idx',true); SELECT pg_advisory_unlock(42); \endif + ), + '005_pgbench_concurrent_cic' => q( + SELECT pg_try_advisory_lock(42)::integer AS gotginlock \gset + \if :gotginlock + DROP INDEX CONCURRENTLY ginidx; + CREATE INDEX CONCURRENTLY ginidx ON tbl USING gin(j); + SELECT gin_index_check('ginidx'); + SELECT pg_advisory_unlock(42); + \endif + ), + '006_pgbench_concurrent_ric' => q( + SELECT pg_try_advisory_lock(42)::integer AS gotginlock \gset + \if :gotginlock + REINDEX INDEX CONCURRENTLY ginidx; + SELECT gin_index_check('ginidx'); + SELECT pg_advisory_unlock(42); + \endif ) + }); $node->stop; diff --git a/contrib/amcheck/t/004_verify_nbtree_unique.pl b/contrib/amcheck/t/004_verify_nbtree_unique.pl index 3b22d56182862..6be08e3f38f79 100644 --- a/contrib/amcheck/t/004_verify_nbtree_unique.pl +++ b/contrib/amcheck/t/004_verify_nbtree_unique.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # This regression test checks the behavior of the btree validation in the # presence of breaking sort order changes. diff --git a/contrib/amcheck/t/005_pitr.pl b/contrib/amcheck/t/005_pitr.pl index a000408360a0e..9da468a72cfc3 100644 --- a/contrib/amcheck/t/005_pitr.pl +++ b/contrib/amcheck/t/005_pitr.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test integrity of intermediate states by PITR to those states use strict; diff --git a/contrib/amcheck/t/006_verify_gin.pl b/contrib/amcheck/t/006_verify_gin.pl new file mode 100644 index 0000000000000..e540cd6606adf --- /dev/null +++ b/contrib/amcheck/t/006_verify_gin.pl @@ -0,0 +1,316 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +my $node; +my $blksize; + +# to get the split fast, we want tuples to be as large as possible, but the same time we don't want them to be toasted. +my $filler_size = 1900; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('test'); +$node->init(no_data_checksums => 1); +$node->append_conf('postgresql.conf', 'autovacuum=off'); +$node->start; +$blksize = int($node->safe_psql('postgres', 'SHOW block_size;')); +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); +$node->safe_psql( + 'postgres', q( + CREATE OR REPLACE FUNCTION random_string( INT ) RETURNS text AS $$ + SELECT string_agg(substring('0123456789abcdefghijklmnopqrstuvwxyz', ceil(random() * 36)::integer, 1), '') from generate_series(1, $1); + $$ LANGUAGE SQL;)); + +# Tests +invalid_entry_order_leaf_page_test(); +invalid_entry_order_inner_page_test(); +invalid_entry_columns_order_test(); +inconsistent_with_parent_key__parent_key_corrupted_test(); +inconsistent_with_parent_key__child_key_corrupted_test(); +inconsistent_with_parent_key__parent_key_corrupted_posting_tree_test(); + +sub invalid_entry_order_leaf_page_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[]); + INSERT INTO $relname (a) VALUES ('{aaaaa,bbbbb}'); + CREATE INDEX $indexname ON $relname USING gin (a); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 1; # root + + # produce wrong order by replacing aaaaa with ccccc + string_replace_block( + $relpath, + 'aaaaa', + 'ccccc', + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\" has wrong tuple order on entry tree page, block 1, offset 2, rightlink 4294967295"; + like($stderr, qr/$expected/); +} + +sub invalid_entry_order_inner_page_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + # to break the order in the inner page we need at least 3 items (rightmost key in the inner level is not checked for the order) + # so fill table until we have 2 splits + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[]); + INSERT INTO $relname (a) VALUES (('{' || 'pppppppppp' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'qqqqqqqqqq' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'rrrrrrrrrr' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'ssssssssss' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'tttttttttt' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'uuuuuuuuuu' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'vvvvvvvvvv' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'wwwwwwwwww' || random_string($filler_size) ||'}')::text[]); + CREATE INDEX $indexname ON $relname USING gin (a); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 1; # root + + # we have rrrrrrrrr... and tttttttttt... as keys in the root, so produce wrong order by replacing rrrrrrrrrr.... + string_replace_block( + $relpath, + 'rrrrrrrrrr', + 'zzzzzzzzzz', + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\" has wrong tuple order on entry tree page, block 1, offset 2, rightlink 4294967295"; + like($stderr, qr/$expected/); +} + +sub invalid_entry_columns_order_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[],b text[]); + INSERT INTO $relname (a,b) VALUES ('{aaa}','{bbb}'); + CREATE INDEX $indexname ON $relname USING gin (a,b); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 1; # root + + # mess column numbers + # root items order before: (1,aaa), (2,bbb) + # root items order after: (2,aaa), (1,bbb) + my $attrno_1 = pack('s', 1); + my $attrno_2 = pack('s', 2); + + my $find = qr/($attrno_1)(.)(aaa)/s; + my $replace = $attrno_2 . '$2$3'; + string_replace_block( + $relpath, + $find, + $replace, + $blkno + ); + + $find = qr/($attrno_2)(.)(bbb)/s; + $replace = $attrno_1 . '$2$3'; + string_replace_block( + $relpath, + $find, + $replace, + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\" has wrong tuple order on entry tree page, block 1, offset 2, rightlink 4294967295"; + like($stderr, qr/$expected/); +} + +sub inconsistent_with_parent_key__parent_key_corrupted_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + # fill the table until we have a split + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[]); + INSERT INTO $relname (a) VALUES (('{' || 'llllllllll' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'mmmmmmmmmm' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'nnnnnnnnnn' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'xxxxxxxxxx' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'yyyyyyyyyy' || random_string($filler_size) ||'}')::text[]); + CREATE INDEX $indexname ON $relname USING gin (a); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 1; # root + + # we have nnnnnnnnnn... as parent key in the root, so replace it with something smaller then child's keys + string_replace_block( + $relpath, + 'nnnnnnnnnn', + 'aaaaaaaaaa', + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\" has inconsistent records on page 3 offset 3"; + like($stderr, qr/$expected/); +} + +sub inconsistent_with_parent_key__child_key_corrupted_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + # fill the table until we have a split + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[]); + INSERT INTO $relname (a) VALUES (('{' || 'llllllllll' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'mmmmmmmmmm' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'nnnnnnnnnn' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'xxxxxxxxxx' || random_string($filler_size) ||'}')::text[]); + INSERT INTO $relname (a) VALUES (('{' || 'yyyyyyyyyy' || random_string($filler_size) ||'}')::text[]); + CREATE INDEX $indexname ON $relname USING gin (a); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 3; # leaf + + # we have nnnnnnnnnn... as parent key in the root, so replace child key with something bigger + string_replace_block( + $relpath, + 'nnnnnnnnnn', + 'pppppppppp', + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\" has inconsistent records on page 3 offset 3"; + like($stderr, qr/$expected/); +} + +sub inconsistent_with_parent_key__parent_key_corrupted_posting_tree_test +{ + my $relname = "test"; + my $indexname = "test_gin_idx"; + + $node->safe_psql( + 'postgres', qq( + DROP TABLE IF EXISTS $relname; + CREATE TABLE $relname (a text[]); + INSERT INTO $relname (a) select ('{aaaaa}') from generate_series(1,10000); + CREATE INDEX $indexname ON $relname USING gin (a); + )); + my $relpath = relation_filepath($indexname); + + $node->stop; + + my $blkno = 2; # posting tree root + + # we have a posting tree for 'aaaaa' key with the root at 2nd block + # and two leaf pages 3 and 4. replace 4th page's high key with (1,1) + # so that there are tid's in leaf page that are larger then the new high key. + my $find = pack('S*', 0, 4, 0) . '....'; + my $replace = pack('S*', 0, 4, 0, 1, 1); + string_replace_block( + $relpath, + $find, + $replace, + $blkno + ); + + $node->start; + + my ($result, $stdout, $stderr) = $node->psql('postgres', qq(SELECT gin_index_check('$indexname'))); + my $expected = "index \"$indexname\": tid exceeds parent's high key in postingTree leaf on block 4"; + like($stderr, qr/$expected/); +} + + +# Returns the filesystem path for the named relation. +sub relation_filepath +{ + my ($relname) = @_; + + my $pgdata = $node->data_dir; + my $rel = $node->safe_psql('postgres', + qq(SELECT pg_relation_filepath('$relname'))); + die "path not found for relation $relname" unless defined $rel; + return "$pgdata/$rel"; +} + +# substitute pattern 'find' with 'replace' within the block with number 'blkno' in the file 'filename' +sub string_replace_block +{ + my ($filename, $find, $replace, $blkno) = @_; + + my $fh; + open($fh, '+<', $filename) or BAIL_OUT("open failed: $!"); + binmode $fh; + + my $offset = $blkno * $blksize; + my $buffer; + + sysseek($fh, $offset, 0) or BAIL_OUT("seek failed: $!"); + sysread($fh, $buffer, $blksize) or BAIL_OUT("read failed: $!"); + + $buffer =~ s/$find/'"' . $replace . '"'/gee; + + sysseek($fh, $offset, 0) or BAIL_OUT("seek failed: $!"); + syswrite($fh, $buffer) or BAIL_OUT("write failed: $!"); + + close($fh) or BAIL_OUT("close failed: $!"); + + return; +} + +done_testing(); diff --git a/contrib/amcheck/verify_common.c b/contrib/amcheck/verify_common.c new file mode 100644 index 0000000000000..d095e62ce551f --- /dev/null +++ b/contrib/amcheck/verify_common.c @@ -0,0 +1,191 @@ +/*------------------------------------------------------------------------- + * + * verify_common.c + * Utility functions common to all access methods. + * + * Copyright (c) 2016-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/amcheck/verify_common.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/genam.h" +#include "access/table.h" +#include "access/tableam.h" +#include "verify_common.h" +#include "catalog/index.h" +#include "catalog/pg_am.h" +#include "commands/tablecmds.h" +#include "utils/guc.h" +#include "utils/syscache.h" + +static bool amcheck_index_mainfork_expected(Relation rel); + + +/* + * Check if index relation should have a file for its main relation fork. + * Verification uses this to skip unlogged indexes when in hot standby mode, + * where there is simply nothing to verify. + * + * NB: Caller should call index_checkable() before calling here. + */ +static bool +amcheck_index_mainfork_expected(Relation rel) +{ + if (rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED || + !RecoveryInProgress()) + return true; + + ereport(NOTICE, + (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), + errmsg("cannot verify unlogged index \"%s\" during recovery, skipping", + RelationGetRelationName(rel)))); + + return false; +} + +/* +* Amcheck main workhorse. +* Given index relation OID, lock relation. +* Next, take a number of standard actions: +* 1) Make sure the index can be checked +* 2) change the context of the user, +* 3) keep track of GUCs modified via index functions +* 4) execute callback function to verify integrity. +*/ +void +amcheck_lock_relation_and_check(Oid indrelid, + Oid am_id, + IndexDoCheckCallback check, + LOCKMODE lockmode, + void *state) +{ + Oid heapid; + Relation indrel; + Relation heaprel; + Oid save_userid; + int save_sec_context; + int save_nestlevel; + + /* + * We must lock table before index to avoid deadlocks. However, if the + * passed indrelid isn't an index then IndexGetRelation() will fail. + * Rather than emitting a not-very-helpful error message, postpone + * complaining, expecting that the is-it-an-index test below will fail. + * + * In hot standby mode this will raise an error when parentcheck is true. + */ + heapid = IndexGetRelation(indrelid, true); + if (OidIsValid(heapid)) + { + heaprel = table_open(heapid, lockmode); + + /* + * Switch to the table owner's userid, so that any index functions are + * run as that user. Also lock down security-restricted operations + * and arrange to make GUC variable changes local to this command. + */ + GetUserIdAndSecContext(&save_userid, &save_sec_context); + SetUserIdAndSecContext(heaprel->rd_rel->relowner, + save_sec_context | SECURITY_RESTRICTED_OPERATION); + save_nestlevel = NewGUCNestLevel(); + } + else + { + heaprel = NULL; + /* Set these just to suppress "uninitialized variable" warnings */ + save_userid = InvalidOid; + save_sec_context = -1; + save_nestlevel = -1; + } + + /* + * Open the target index relations separately (like relation_openrv(), but + * with heap relation locked first to prevent deadlocking). In hot + * standby mode this will raise an error when parentcheck is true. + * + * There is no need for the usual indcheckxmin usability horizon test + * here, even in the heapallindexed case, because index undergoing + * verification only needs to have entries for a new transaction snapshot. + * (If this is a parentcheck verification, there is no question about + * committed or recently dead heap tuples lacking index entries due to + * concurrent activity.) + */ + indrel = index_open(indrelid, lockmode); + + /* + * Since we did the IndexGetRelation call above without any lock, it's + * barely possible that a race against an index drop/recreation could have + * netted us the wrong table. + */ + if (heaprel == NULL || heapid != IndexGetRelation(indrelid, false)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("could not open parent table of index \"%s\"", + RelationGetRelationName(indrel)))); + + /* Check that relation suitable for checking */ + if (index_checkable(indrel, am_id)) + check(indrel, heaprel, state, lockmode == ShareLock); + + /* Roll back any GUC changes executed by index functions */ + AtEOXact_GUC(false, save_nestlevel); + + /* Restore userid and security context */ + SetUserIdAndSecContext(save_userid, save_sec_context); + + /* + * Release locks early. That's ok here because nothing in the called + * routines will trigger shared cache invalidations to be sent, so we can + * relax the usual pattern of only releasing locks after commit. + */ + index_close(indrel, lockmode); + if (heaprel) + table_close(heaprel, lockmode); +} + +/* + * Basic checks about the suitability of a relation for checking as an index. + * + * + * NB: Intentionally not checking permissions, the function is normally not + * callable by non-superusers. If granted, it's useful to be able to check a + * whole cluster. + */ +bool +index_checkable(Relation rel, Oid am_id) +{ + if (rel->rd_rel->relkind != RELKIND_INDEX || + rel->rd_rel->relam != am_id) + { + HeapTuple amtup; + HeapTuple amtuprel; + + amtup = SearchSysCache1(AMOID, ObjectIdGetDatum(am_id)); + amtuprel = SearchSysCache1(AMOID, ObjectIdGetDatum(rel->rd_rel->relam)); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("expected \"%s\" index as targets for verification", NameStr(((Form_pg_am) GETSTRUCT(amtup))->amname)), + errdetail("Relation \"%s\" is a %s index.", + RelationGetRelationName(rel), NameStr(((Form_pg_am) GETSTRUCT(amtuprel))->amname)))); + } + + if (RELATION_IS_OTHER_TEMP(rel)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"), + errdetail("Index \"%s\" is associated with temporary relation.", + RelationGetRelationName(rel)))); + + if (!rel->rd_index->indisvalid) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot check index \"%s\"", + RelationGetRelationName(rel)), + errdetail("Index is not valid."))); + + return amcheck_index_mainfork_expected(rel); +} diff --git a/contrib/amcheck/verify_common.h b/contrib/amcheck/verify_common.h new file mode 100644 index 0000000000000..e78adb68808f0 --- /dev/null +++ b/contrib/amcheck/verify_common.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------- + * + * amcheck.h + * Shared routines for amcheck verifications. + * + * Copyright (c) 2016-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/amcheck/amcheck.h + * + *------------------------------------------------------------------------- + */ +#include "storage/bufpage.h" +#include "storage/lmgr.h" +#include "storage/lockdefs.h" +#include "utils/relcache.h" +#include "miscadmin.h" + +/* Typedefs for callback functions for amcheck_lock_relation_and_check */ +typedef void (*IndexCheckableCallback) (Relation index); +typedef void (*IndexDoCheckCallback) (Relation rel, + Relation heaprel, + void *state, + bool readonly); + +extern void amcheck_lock_relation_and_check(Oid indrelid, + Oid am_id, + IndexDoCheckCallback check, + LOCKMODE lockmode, void *state); + +extern bool index_checkable(Relation rel, Oid am_id); diff --git a/contrib/amcheck/verify_gin.c b/contrib/amcheck/verify_gin.c new file mode 100644 index 0000000000000..c615d950736f6 --- /dev/null +++ b/contrib/amcheck/verify_gin.c @@ -0,0 +1,794 @@ +/*------------------------------------------------------------------------- + * + * verify_gin.c + * Verifies the integrity of GIN indexes based on invariants. + * + * + * GIN index verification checks a number of invariants: + * + * - consistency: Paths in GIN graph have to contain consistent keys: tuples + * on parent pages consistently include tuples from children pages. + * + * - graph invariants: Each internal page must have at least one downlink, and + * can reference either only leaf pages or only internal pages. + * + * + * Copyright (c) 2016-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/amcheck/verify_gin.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/gin_private.h" +#include "access/nbtree.h" +#include "catalog/pg_am.h" +#include "utils/memutils.h" +#include "utils/rel.h" +#include "verify_common.h" +#include "string.h" + +/* + * GinScanItem represents one item of depth-first scan of the index. + */ +typedef struct GinScanItem +{ + int depth; + IndexTuple parenttup; + BlockNumber parentblk; + BlockNumber blkno; + struct GinScanItem *next; +} GinScanItem; + +/* + * GinPostingTreeScanItem represents one item of a depth-first posting tree scan. + */ +typedef struct GinPostingTreeScanItem +{ + int depth; + ItemPointerData parentkey; + BlockNumber parentblk; + BlockNumber blkno; + struct GinPostingTreeScanItem *next; +} GinPostingTreeScanItem; + + +PG_FUNCTION_INFO_V1(gin_index_check); + +static void gin_check_parent_keys_consistency(Relation rel, + Relation heaprel, + void *callback_state, bool readonly); +static void check_index_page(Relation rel, Buffer buffer, BlockNumber blockNo); +static IndexTuple gin_refind_parent(Relation rel, + BlockNumber parentblkno, + BlockNumber childblkno, + BufferAccessStrategy strategy); +static ItemId PageGetItemIdCareful(Relation rel, BlockNumber block, Page page, + OffsetNumber offset); + +/* + * gin_index_check(index regclass) + * + * Verify integrity of GIN index. + * + * Acquires AccessShareLock on heap & index relations. + */ +Datum +gin_index_check(PG_FUNCTION_ARGS) +{ + Oid indrelid = PG_GETARG_OID(0); + + amcheck_lock_relation_and_check(indrelid, + GIN_AM_OID, + gin_check_parent_keys_consistency, + AccessShareLock, + NULL); + + PG_RETURN_VOID(); +} + +/* + * Read item pointers from leaf entry tuple. + * + * Returns a palloc'd array of ItemPointers. The number of items is returned + * in *nitems. + */ +static ItemPointer +ginReadTupleWithoutState(IndexTuple itup, int *nitems) +{ + Pointer ptr = GinGetPosting(itup); + int nipd = GinGetNPosting(itup); + ItemPointer ipd; + int ndecoded; + + if (GinItupIsCompressed(itup)) + { + if (nipd > 0) + { + ipd = ginPostingListDecode((GinPostingList *) ptr, &ndecoded); + if (nipd != ndecoded) + elog(ERROR, "number of items mismatch in GIN entry tuple, %d in tuple header, %d decoded", + nipd, ndecoded); + } + else + ipd = palloc(0); + } + else + { + ipd = (ItemPointer) palloc(sizeof(ItemPointerData) * nipd); + memcpy(ipd, ptr, sizeof(ItemPointerData) * nipd); + } + *nitems = nipd; + return ipd; +} + +/* + * Scans through a posting tree (given by the root), and verifies that the keys + * on a child keys are consistent with the parent. + * + * Allocates a separate memory context and scans through posting tree graph. + */ +static void +gin_check_posting_tree_parent_keys_consistency(Relation rel, BlockNumber posting_tree_root) +{ + BufferAccessStrategy strategy = GetAccessStrategy(BAS_BULKREAD); + GinPostingTreeScanItem *stack; + MemoryContext mctx; + MemoryContext oldcontext; + + int leafdepth; + + mctx = AllocSetContextCreate(CurrentMemoryContext, + "posting tree check context", + ALLOCSET_DEFAULT_SIZES); + oldcontext = MemoryContextSwitchTo(mctx); + + /* + * We don't know the height of the tree yet, but as soon as we encounter a + * leaf page, we will set 'leafdepth' to its depth. + */ + leafdepth = -1; + + /* Start the scan at the root page */ + stack = (GinPostingTreeScanItem *) palloc0(sizeof(GinPostingTreeScanItem)); + stack->depth = 0; + ItemPointerSetInvalid(&stack->parentkey); + stack->parentblk = InvalidBlockNumber; + stack->blkno = posting_tree_root; + + elog(DEBUG3, "processing posting tree at blk %u", posting_tree_root); + + while (stack) + { + GinPostingTreeScanItem *stack_next; + Buffer buffer; + Page page; + OffsetNumber i, + maxoff; + BlockNumber rightlink; + + CHECK_FOR_INTERRUPTS(); + + buffer = ReadBufferExtended(rel, MAIN_FORKNUM, stack->blkno, + RBM_NORMAL, strategy); + LockBuffer(buffer, GIN_SHARE); + page = (Page) BufferGetPage(buffer); + + Assert(GinPageIsData(page)); + + /* Check that the tree has the same height in all branches */ + if (GinPageIsLeaf(page)) + { + ItemPointerData minItem; + int nlist; + ItemPointerData *list; + char tidrange_buf[MAXPGPATH]; + + ItemPointerSetMin(&minItem); + + elog(DEBUG1, "page blk: %u, type leaf", stack->blkno); + + if (leafdepth == -1) + leafdepth = stack->depth; + else if (stack->depth != leafdepth) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": internal pages traversal encountered leaf page unexpectedly on block %u", + RelationGetRelationName(rel), stack->blkno))); + list = GinDataLeafPageGetItems(page, &nlist, minItem); + + if (nlist > 0) + snprintf(tidrange_buf, sizeof(tidrange_buf), + "%d tids (%u, %u) - (%u, %u)", + nlist, + ItemPointerGetBlockNumberNoCheck(&list[0]), + ItemPointerGetOffsetNumberNoCheck(&list[0]), + ItemPointerGetBlockNumberNoCheck(&list[nlist - 1]), + ItemPointerGetOffsetNumberNoCheck(&list[nlist - 1])); + else + snprintf(tidrange_buf, sizeof(tidrange_buf), "0 tids"); + + if (stack->parentblk != InvalidBlockNumber) + elog(DEBUG3, "blk %u: parent %u highkey (%u, %u), %s", + stack->blkno, + stack->parentblk, + ItemPointerGetBlockNumberNoCheck(&stack->parentkey), + ItemPointerGetOffsetNumberNoCheck(&stack->parentkey), + tidrange_buf); + else + elog(DEBUG3, "blk %u: root leaf, %s", + stack->blkno, + tidrange_buf); + + if (stack->parentblk != InvalidBlockNumber && + ItemPointerGetOffsetNumberNoCheck(&stack->parentkey) != InvalidOffsetNumber && + nlist > 0 && ItemPointerCompare(&stack->parentkey, &list[nlist - 1]) < 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": tid exceeds parent's high key in postingTree leaf on block %u", + RelationGetRelationName(rel), stack->blkno))); + } + else + { + LocationIndex pd_lower; + ItemPointerData bound; + int lowersize; + + /* + * Check that tuples in each page are properly ordered and + * consistent with parent high key + */ + maxoff = GinPageGetOpaque(page)->maxoff; + rightlink = GinPageGetOpaque(page)->rightlink; + + elog(DEBUG1, "page blk: %u, type data, maxoff %d", stack->blkno, maxoff); + + if (stack->parentblk != InvalidBlockNumber) + elog(DEBUG3, "blk %u: internal posting tree page with %u items, parent %u highkey (%u, %u)", + stack->blkno, maxoff, stack->parentblk, + ItemPointerGetBlockNumberNoCheck(&stack->parentkey), + ItemPointerGetOffsetNumberNoCheck(&stack->parentkey)); + else + elog(DEBUG3, "blk %u: root internal posting tree page with %u items", + stack->blkno, maxoff); + + /* + * A GIN posting tree internal page stores PostingItems in the + * 'lower' part of the page. The 'upper' part is unused. The + * number of elements is stored in the opaque area (maxoff). Make + * sure the size of the 'lower' part agrees with 'maxoff' + * + * We didn't set pd_lower until PostgreSQL version 9.4, so if this + * check fails, it could also be because the index was + * binary-upgraded from an earlier version. That was a long time + * ago, though, so let's warn if it doesn't match. + */ + pd_lower = ((PageHeader) page)->pd_lower; + lowersize = pd_lower - MAXALIGN(SizeOfPageHeaderData); + if ((lowersize - MAXALIGN(sizeof(ItemPointerData))) / sizeof(PostingItem) != maxoff) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has unexpected pd_lower %u in posting tree block %u with maxoff %u)", + RelationGetRelationName(rel), pd_lower, stack->blkno, maxoff))); + + /* + * Before the PostingItems, there's one ItemPointerData in the + * 'lower' part that stores the page's high key. + */ + bound = *GinDataPageGetRightBound(page); + + /* + * Gin page right bound has a sane value only when not a highkey + * on the rightmost page (at a given level). For the rightmost + * page does not store the highkey explicitly, and the value is + * infinity. + */ + if (ItemPointerIsValid(&stack->parentkey) && + rightlink != InvalidBlockNumber && + !ItemPointerEquals(&stack->parentkey, &bound)) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": posting tree page's high key (%u, %u) doesn't match the downlink on block %u (parent blk %u, key (%u, %u))", + RelationGetRelationName(rel), + ItemPointerGetBlockNumberNoCheck(&bound), + ItemPointerGetOffsetNumberNoCheck(&bound), + stack->blkno, stack->parentblk, + ItemPointerGetBlockNumberNoCheck(&stack->parentkey), + ItemPointerGetOffsetNumberNoCheck(&stack->parentkey)))); + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + GinPostingTreeScanItem *ptr; + PostingItem *posting_item = GinDataPageGetPostingItem(page, i); + + /* ItemPointerGetOffsetNumber expects a valid pointer */ + if (!(i == maxoff && + rightlink == InvalidBlockNumber)) + elog(DEBUG3, "key (%u, %u) -> %u", + ItemPointerGetBlockNumber(&posting_item->key), + ItemPointerGetOffsetNumber(&posting_item->key), + BlockIdGetBlockNumber(&posting_item->child_blkno)); + else + elog(DEBUG3, "key (%u, %u) -> %u", + 0, 0, BlockIdGetBlockNumber(&posting_item->child_blkno)); + + if (i == maxoff && rightlink == InvalidBlockNumber) + { + /* + * The rightmost item in the tree level has (0, 0) as the + * key + */ + if (ItemPointerGetBlockNumberNoCheck(&posting_item->key) != 0 || + ItemPointerGetOffsetNumberNoCheck(&posting_item->key) != 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": rightmost posting tree page (blk %u) has unexpected last key (%u, %u)", + RelationGetRelationName(rel), + stack->blkno, + ItemPointerGetBlockNumberNoCheck(&posting_item->key), + ItemPointerGetOffsetNumberNoCheck(&posting_item->key)))); + } + else if (i != FirstOffsetNumber) + { + PostingItem *previous_posting_item = GinDataPageGetPostingItem(page, i - 1); + + if (ItemPointerCompare(&posting_item->key, &previous_posting_item->key) < 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has wrong tuple order in posting tree, block %u, offset %u", + RelationGetRelationName(rel), stack->blkno, i))); + } + + /* + * Check if this tuple is consistent with the downlink in the + * parent. + */ + if (i == maxoff && ItemPointerIsValid(&stack->parentkey) && + ItemPointerCompare(&stack->parentkey, &posting_item->key) < 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": posting item exceeds parent's high key in postingTree internal page on block %u offset %u", + RelationGetRelationName(rel), + stack->blkno, i))); + + /* This is an internal page, recurse into the child. */ + ptr = (GinPostingTreeScanItem *) palloc(sizeof(GinPostingTreeScanItem)); + ptr->depth = stack->depth + 1; + + /* + * The rightmost parent key is always invalid item pointer. + * Its value is 'Infinity' and not explicitly stored. + */ + ptr->parentkey = posting_item->key; + ptr->parentblk = stack->blkno; + ptr->blkno = BlockIdGetBlockNumber(&posting_item->child_blkno); + ptr->next = stack->next; + stack->next = ptr; + } + } + LockBuffer(buffer, GIN_UNLOCK); + ReleaseBuffer(buffer); + + /* Step to next item in the queue */ + stack_next = stack->next; + pfree(stack); + stack = stack_next; + } + + MemoryContextSwitchTo(oldcontext); + MemoryContextDelete(mctx); +} + +/* + * Main entry point for GIN checks. + * + * Allocates memory context and scans through the whole GIN graph. + */ +static void +gin_check_parent_keys_consistency(Relation rel, + Relation heaprel, + void *callback_state, + bool readonly) +{ + BufferAccessStrategy strategy = GetAccessStrategy(BAS_BULKREAD); + GinScanItem *stack; + MemoryContext mctx; + MemoryContext oldcontext; + GinState state; + int leafdepth; + + mctx = AllocSetContextCreate(CurrentMemoryContext, + "amcheck consistency check context", + ALLOCSET_DEFAULT_SIZES); + oldcontext = MemoryContextSwitchTo(mctx); + initGinState(&state, rel); + + /* + * We don't know the height of the tree yet, but as soon as we encounter a + * leaf page, we will set 'leafdepth' to its depth. + */ + leafdepth = -1; + + /* Start the scan at the root page */ + stack = (GinScanItem *) palloc0(sizeof(GinScanItem)); + stack->depth = 0; + stack->parenttup = NULL; + stack->parentblk = InvalidBlockNumber; + stack->blkno = GIN_ROOT_BLKNO; + + while (stack) + { + GinScanItem *stack_next; + Buffer buffer; + Page page; + OffsetNumber i, + maxoff, + prev_attnum; + IndexTuple prev_tuple; + BlockNumber rightlink; + + CHECK_FOR_INTERRUPTS(); + + buffer = ReadBufferExtended(rel, MAIN_FORKNUM, stack->blkno, + RBM_NORMAL, strategy); + LockBuffer(buffer, GIN_SHARE); + page = (Page) BufferGetPage(buffer); + maxoff = PageGetMaxOffsetNumber(page); + rightlink = GinPageGetOpaque(page)->rightlink; + + /* Do basic sanity checks on the page headers */ + check_index_page(rel, buffer, stack->blkno); + + elog(DEBUG3, "processing entry tree page at blk %u, maxoff: %u", stack->blkno, maxoff); + + /* + * It's possible that the page was split since we looked at the + * parent, so that we didn't missed the downlink of the right sibling + * when we scanned the parent. If so, add the right sibling to the + * stack now. + */ + if (stack->parenttup != NULL) + { + GinNullCategory parent_key_category; + Datum parent_key = gintuple_get_key(&state, + stack->parenttup, + &parent_key_category); + OffsetNumber parent_key_attnum = gintuple_get_attrnum(&state, stack->parenttup); + ItemId iid = PageGetItemIdCareful(rel, stack->blkno, + page, maxoff); + IndexTuple idxtuple = (IndexTuple) PageGetItem(page, iid); + OffsetNumber page_max_key_attnum = gintuple_get_attrnum(&state, idxtuple); + GinNullCategory page_max_key_category; + Datum page_max_key = gintuple_get_key(&state, idxtuple, &page_max_key_category); + + if (rightlink != InvalidBlockNumber && + ginCompareAttEntries(&state, page_max_key_attnum, page_max_key, + page_max_key_category, parent_key_attnum, + parent_key, parent_key_category) < 0) + { + /* split page detected, install right link to the stack */ + GinScanItem *ptr; + + elog(DEBUG3, "split detected for blk: %u, parent blk: %u", stack->blkno, stack->parentblk); + + ptr = (GinScanItem *) palloc(sizeof(GinScanItem)); + ptr->depth = stack->depth; + ptr->parenttup = CopyIndexTuple(stack->parenttup); + ptr->parentblk = stack->parentblk; + ptr->blkno = rightlink; + ptr->next = stack->next; + stack->next = ptr; + } + } + + /* Check that the tree has the same height in all branches */ + if (GinPageIsLeaf(page)) + { + if (leafdepth == -1) + leafdepth = stack->depth; + else if (stack->depth != leafdepth) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": internal pages traversal encountered leaf page unexpectedly on block %u", + RelationGetRelationName(rel), stack->blkno))); + } + + /* + * Check that tuples in each page are properly ordered and consistent + * with parent high key + */ + prev_tuple = NULL; + prev_attnum = InvalidAttrNumber; + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + ItemId iid = PageGetItemIdCareful(rel, stack->blkno, page, i); + IndexTuple idxtuple = (IndexTuple) PageGetItem(page, iid); + OffsetNumber current_attnum = gintuple_get_attrnum(&state, idxtuple); + GinNullCategory current_key_category; + Datum current_key; + + if (MAXALIGN(ItemIdGetLength(iid)) != MAXALIGN(IndexTupleSize(idxtuple))) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has inconsistent tuple sizes, block %u, offset %u", + RelationGetRelationName(rel), stack->blkno, i))); + + current_key = gintuple_get_key(&state, idxtuple, ¤t_key_category); + + /* + * Compare the entry to the preceding one. + * + * Don't check for high key on the rightmost inner page, as this + * key is not really stored explicitly. + * + * The entries may be for different attributes, so make sure to + * use ginCompareAttEntries for comparison. + */ + if ((i != FirstOffsetNumber) && + !(i == maxoff && rightlink == InvalidBlockNumber && !GinPageIsLeaf(page))) + { + Datum prev_key; + GinNullCategory prev_key_category; + + prev_key = gintuple_get_key(&state, prev_tuple, &prev_key_category); + if (ginCompareAttEntries(&state, prev_attnum, prev_key, + prev_key_category, current_attnum, + current_key, current_key_category) >= 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has wrong tuple order on entry tree page, block %u, offset %u, rightlink %u", + RelationGetRelationName(rel), stack->blkno, i, rightlink))); + } + + /* + * Check if this tuple is consistent with the downlink in the + * parent. + */ + if (stack->parenttup && + i == maxoff) + { + GinNullCategory parent_key_category; + OffsetNumber parent_key_attnum = gintuple_get_attrnum(&state, stack->parenttup); + Datum parent_key = gintuple_get_key(&state, + stack->parenttup, + &parent_key_category); + + if (ginCompareAttEntries(&state, current_attnum, current_key, + current_key_category, parent_key_attnum, + parent_key, parent_key_category) > 0) + { + /* + * There was a discrepancy between parent and child + * tuples. We need to verify it is not a result of + * concurrent call of gistplacetopage(). So, lock parent + * and try to find downlink for current page. It may be + * missing due to concurrent page split, this is OK. + */ + pfree(stack->parenttup); + stack->parenttup = gin_refind_parent(rel, stack->parentblk, + stack->blkno, strategy); + + /* We found it - make a final check before failing */ + if (!stack->parenttup) + elog(NOTICE, "Unable to find parent tuple for block %u on block %u due to concurrent split", + stack->blkno, stack->parentblk); + else + { + parent_key_attnum = gintuple_get_attrnum(&state, stack->parenttup); + parent_key = gintuple_get_key(&state, + stack->parenttup, + &parent_key_category); + + /* + * Check if it is properly adjusted. If succeed, + * proceed to the next key. + */ + if (ginCompareAttEntries(&state, current_attnum, current_key, + current_key_category, parent_key_attnum, + parent_key, parent_key_category) > 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has inconsistent records on page %u offset %u", + RelationGetRelationName(rel), stack->blkno, i))); + } + } + } + + /* If this is an internal page, recurse into the child */ + if (!GinPageIsLeaf(page)) + { + GinScanItem *ptr; + + ptr = (GinScanItem *) palloc(sizeof(GinScanItem)); + ptr->depth = stack->depth + 1; + /* last tuple in layer has no high key */ + if (i == maxoff && rightlink == InvalidBlockNumber) + ptr->parenttup = NULL; + else + ptr->parenttup = CopyIndexTuple(idxtuple); + ptr->parentblk = stack->blkno; + ptr->blkno = GinGetDownlink(idxtuple); + ptr->next = stack->next; + stack->next = ptr; + } + /* If this item is a pointer to a posting tree, recurse into it */ + else if (GinIsPostingTree(idxtuple)) + { + BlockNumber rootPostingTree = GinGetPostingTree(idxtuple); + + gin_check_posting_tree_parent_keys_consistency(rel, rootPostingTree); + } + else + { + ItemPointer ipd; + int nipd; + + ipd = ginReadTupleWithoutState(idxtuple, &nipd); + + for (int j = 0; j < nipd; j++) + { + if (!OffsetNumberIsValid(ItemPointerGetOffsetNumber(&ipd[j]))) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\": posting list contains invalid heap pointer on block %u", + RelationGetRelationName(rel), stack->blkno))); + } + pfree(ipd); + } + + prev_tuple = CopyIndexTuple(idxtuple); + prev_attnum = current_attnum; + } + + LockBuffer(buffer, GIN_UNLOCK); + ReleaseBuffer(buffer); + + /* Step to next item in the queue */ + stack_next = stack->next; + if (stack->parenttup) + pfree(stack->parenttup); + pfree(stack); + stack = stack_next; + } + + MemoryContextSwitchTo(oldcontext); + MemoryContextDelete(mctx); +} + +/* + * Verify that a freshly-read page looks sane. + */ +static void +check_index_page(Relation rel, Buffer buffer, BlockNumber blockNo) +{ + Page page = BufferGetPage(buffer); + + /* + * ReadBuffer verifies that every newly-read page passes + * PageHeaderIsValid, which means it either contains a reasonably sane + * page header or is all-zero. We have to defend against the all-zero + * case, however. + */ + if (PageIsNew(page)) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" contains unexpected zero page at block %u", + RelationGetRelationName(rel), + BufferGetBlockNumber(buffer)), + errhint("Please REINDEX it."))); + + /* + * Additionally check that the special area looks sane. + */ + if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData))) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" contains corrupted page at block %u", + RelationGetRelationName(rel), + BufferGetBlockNumber(buffer)), + errhint("Please REINDEX it."))); + + if (GinPageIsDeleted(page)) + { + if (!GinPageIsLeaf(page)) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has deleted internal page %u", + RelationGetRelationName(rel), blockNo))); + if (PageGetMaxOffsetNumber(page) > InvalidOffsetNumber) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has deleted page %u with tuples", + RelationGetRelationName(rel), blockNo))); + } + else if (PageGetMaxOffsetNumber(page) > MaxIndexTuplesPerPage) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" has page %u with exceeding count of tuples", + RelationGetRelationName(rel), blockNo))); +} + +/* + * Try to re-find downlink pointing to 'blkno', in 'parentblkno'. + * + * If found, returns a palloc'd copy of the downlink tuple. Otherwise, + * returns NULL. + */ +static IndexTuple +gin_refind_parent(Relation rel, BlockNumber parentblkno, + BlockNumber childblkno, BufferAccessStrategy strategy) +{ + Buffer parentbuf; + Page parentpage; + OffsetNumber o, + parent_maxoff; + IndexTuple result = NULL; + + parentbuf = ReadBufferExtended(rel, MAIN_FORKNUM, parentblkno, RBM_NORMAL, + strategy); + + LockBuffer(parentbuf, GIN_SHARE); + parentpage = BufferGetPage(parentbuf); + + if (GinPageIsLeaf(parentpage)) + { + UnlockReleaseBuffer(parentbuf); + return result; + } + + parent_maxoff = PageGetMaxOffsetNumber(parentpage); + for (o = FirstOffsetNumber; o <= parent_maxoff; o = OffsetNumberNext(o)) + { + ItemId p_iid = PageGetItemIdCareful(rel, parentblkno, parentpage, o); + IndexTuple itup = (IndexTuple) PageGetItem(parentpage, p_iid); + + if (GinGetDownlink(itup) == childblkno) + { + /* Found it! Make copy and return it */ + result = CopyIndexTuple(itup); + break; + } + } + + UnlockReleaseBuffer(parentbuf); + + return result; +} + +static ItemId +PageGetItemIdCareful(Relation rel, BlockNumber block, Page page, + OffsetNumber offset) +{ + ItemId itemid = PageGetItemId(page, offset); + + if (ItemIdGetOffset(itemid) + ItemIdGetLength(itemid) > + BLCKSZ - MAXALIGN(sizeof(GinPageOpaqueData))) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("line pointer points past end of tuple space in index \"%s\"", + RelationGetRelationName(rel)), + errdetail_internal("Index tid=(%u,%u) lp_off=%u, lp_len=%u lp_flags=%u.", + block, offset, ItemIdGetOffset(itemid), + ItemIdGetLength(itemid), + ItemIdGetFlags(itemid)))); + + /* + * Verify that line pointer isn't LP_REDIRECT or LP_UNUSED or LP_DEAD, + * since GIN never uses all three. Verify that line pointer has storage, + * too. + */ + if (ItemIdIsRedirected(itemid) || !ItemIdIsUsed(itemid) || + ItemIdIsDead(itemid) || ItemIdGetLength(itemid) == 0) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("invalid line pointer storage in index \"%s\"", + RelationGetRelationName(rel)), + errdetail_internal("Index tid=(%u,%u) lp_off=%u, lp_len=%u lp_flags=%u.", + block, offset, ItemIdGetOffset(itemid), + ItemIdGetLength(itemid), + ItemIdGetFlags(itemid)))); + + return itemid; +} diff --git a/contrib/amcheck/verify_heapam.c b/contrib/amcheck/verify_heapam.c index f2526ed63a284..aa9cccd1da4fe 100644 --- a/contrib/amcheck/verify_heapam.c +++ b/contrib/amcheck/verify_heapam.c @@ -3,7 +3,7 @@ * verify_heapam.c * Functions to check postgresql heap relations for corruption * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * contrib/amcheck/verify_heapam.c *------------------------------------------------------------------------- @@ -12,18 +12,23 @@ #include "access/detoast.h" #include "access/genam.h" -#include "access/heapam.h" #include "access/heaptoast.h" #include "access/multixact.h" +#include "access/relation.h" +#include "access/table.h" #include "access/toast_internals.h" #include "access/visibilitymap.h" +#include "access/xact.h" #include "catalog/pg_am.h" +#include "catalog/pg_class.h" #include "funcapi.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/procarray.h" +#include "storage/read_stream.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/rel.h" PG_FUNCTION_INFO_V1(verify_heapam); @@ -114,7 +119,10 @@ typedef struct HeapCheckContext Relation valid_toast_index; int num_toast_indexes; - /* Values for iterating over pages in the relation */ + /* + * Values for iterating over pages in the relation. `blkno` is the most + * recent block in the buffer yielded by the read stream API. + */ BlockNumber blkno; BufferAccessStrategy bstrategy; Buffer buffer; @@ -149,7 +157,32 @@ typedef struct HeapCheckContext Tuplestorestate *tupstore; } HeapCheckContext; +/* + * The per-relation data provided to the read stream API for heap amcheck to + * use in its callback for the SKIP_PAGES_ALL_FROZEN and + * SKIP_PAGES_ALL_VISIBLE options. + */ +typedef struct HeapCheckReadStreamData +{ + /* + * `range` is used by all SkipPages options. SKIP_PAGES_NONE uses the + * default read stream callback, block_range_read_stream_cb(), which takes + * a BlockRangeReadStreamPrivate as its callback_private_data. `range` + * keeps track of the current block number across + * read_stream_next_buffer() invocations. + */ + BlockRangeReadStreamPrivate range; + SkipPages skip_option; + Relation rel; + Buffer *vmbuffer; +} HeapCheckReadStreamData; + + /* Internal implementation */ +static BlockNumber heapcheck_read_stream_next_unskippable(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data); + static void check_tuple(HeapCheckContext *ctx, bool *xmin_commit_status_ok, XidCommitStatus *xmin_commit_status); @@ -227,6 +260,11 @@ verify_heapam(PG_FUNCTION_ARGS) BlockNumber last_block; BlockNumber nblocks; const char *skip; + ReadStream *stream; + int stream_flags; + ReadStreamBlockNumberCB stream_cb; + void *stream_data; + HeapCheckReadStreamData stream_skip_data; /* Check supplied arguments */ if (PG_ARGISNULL(0)) @@ -400,7 +438,46 @@ verify_heapam(PG_FUNCTION_ARGS) if (TransactionIdIsNormal(ctx.relfrozenxid)) ctx.oldest_xid = ctx.relfrozenxid; - for (ctx.blkno = first_block; ctx.blkno <= last_block; ctx.blkno++) + /* Now that `ctx` is set up, set up the read stream */ + stream_skip_data.range.current_blocknum = first_block; + stream_skip_data.range.last_exclusive = last_block + 1; + stream_skip_data.skip_option = skip_option; + stream_skip_data.rel = ctx.rel; + stream_skip_data.vmbuffer = &vmbuffer; + + if (skip_option == SKIP_PAGES_NONE) + { + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream_cb = block_range_read_stream_cb; + stream_flags = READ_STREAM_SEQUENTIAL | + READ_STREAM_FULL | + READ_STREAM_USE_BATCHING; + stream_data = &stream_skip_data.range; + } + else + { + /* + * It would not be safe to naively use batchmode, as + * heapcheck_read_stream_next_unskippable takes locks. It shouldn't be + * too hard to convert though. + */ + stream_cb = heapcheck_read_stream_next_unskippable; + stream_flags = READ_STREAM_DEFAULT; + stream_data = &stream_skip_data; + } + + stream = read_stream_begin_relation(stream_flags, + ctx.bstrategy, + ctx.rel, + MAIN_FORKNUM, + stream_cb, + stream_data, + 0); + + while ((ctx.buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) { OffsetNumber maxoff; OffsetNumber predecessor[MaxOffsetNumber]; @@ -413,30 +490,11 @@ verify_heapam(PG_FUNCTION_ARGS) memset(predecessor, 0, sizeof(OffsetNumber) * MaxOffsetNumber); - /* Optionally skip over all-frozen or all-visible blocks */ - if (skip_option != SKIP_PAGES_NONE) - { - int32 mapbits; - - mapbits = (int32) visibilitymap_get_status(ctx.rel, ctx.blkno, - &vmbuffer); - if (skip_option == SKIP_PAGES_ALL_FROZEN) - { - if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0) - continue; - } - - if (skip_option == SKIP_PAGES_ALL_VISIBLE) - { - if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0) - continue; - } - } - - /* Read and lock the next page. */ - ctx.buffer = ReadBufferExtended(ctx.rel, MAIN_FORKNUM, ctx.blkno, - RBM_NORMAL, ctx.bstrategy); + /* Lock the next page. */ + Assert(BufferIsValid(ctx.buffer)); LockBuffer(ctx.buffer, BUFFER_LOCK_SHARE); + + ctx.blkno = BufferGetBlockNumber(ctx.buffer); ctx.page = BufferGetPage(ctx.buffer); /* Perform tuple checks */ @@ -795,6 +853,8 @@ verify_heapam(PG_FUNCTION_ARGS) break; } + read_stream_end(stream); + if (vmbuffer != InvalidBuffer) ReleaseBuffer(vmbuffer); @@ -811,6 +871,42 @@ verify_heapam(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +/* + * Heap amcheck's read stream callback for getting the next unskippable block. + * This callback is only used when 'all-visible' or 'all-frozen' is provided + * as the skip option to verify_heapam(). With the default 'none', + * block_range_read_stream_cb() is used instead. + */ +static BlockNumber +heapcheck_read_stream_next_unskippable(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) +{ + HeapCheckReadStreamData *p = callback_private_data; + + /* Loops over [current_blocknum, last_exclusive) blocks */ + for (BlockNumber i; (i = p->range.current_blocknum++) < p->range.last_exclusive;) + { + uint8 mapbits = visibilitymap_get_status(p->rel, i, p->vmbuffer); + + if (p->skip_option == SKIP_PAGES_ALL_FROZEN) + { + if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0) + continue; + } + + if (p->skip_option == SKIP_PAGES_ALL_VISIBLE) + { + if ((mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0) + continue; + } + + return i; + } + + return InvalidBlockNumber; +} + /* * Shared internal implementation for report_corruption and * report_toast_corruption. @@ -1567,11 +1663,11 @@ check_tuple_attribute(HeapCheckContext *ctx) struct varlena *attr; char *tp; /* pointer to the tuple data */ uint16 infomask; - Form_pg_attribute thisatt; + CompactAttribute *thisatt; struct varatt_external toast_pointer; infomask = ctx->tuphdr->t_infomask; - thisatt = TupleDescAttr(RelationGetDescr(ctx->rel), ctx->attnum); + thisatt = TupleDescCompactAttr(RelationGetDescr(ctx->rel), ctx->attnum); tp = (char *) ctx->tuphdr + ctx->tuphdr->t_hoff; @@ -1592,7 +1688,7 @@ check_tuple_attribute(HeapCheckContext *ctx) /* Skip non-varlena values, but update offset first */ if (thisatt->attlen != -1) { - ctx->offset = att_align_nominal(ctx->offset, thisatt->attalign); + ctx->offset = att_nominal_alignby(ctx->offset, thisatt->attalignby); ctx->offset = att_addlength_pointer(ctx->offset, thisatt->attlen, tp + ctx->offset); if (ctx->tuphdr->t_hoff + ctx->offset > ctx->lp_len) @@ -1608,8 +1704,8 @@ check_tuple_attribute(HeapCheckContext *ctx) } /* Ok, we're looking at a varlena attribute. */ - ctx->offset = att_align_pointer(ctx->offset, thisatt->attalign, -1, - tp + ctx->offset); + ctx->offset = att_pointer_alignby(ctx->offset, thisatt->attalignby, -1, + tp + ctx->offset); /* Get the (possibly corrupt) varlena datum */ attdatum = fetchatt(thisatt, tp + ctx->offset); @@ -1763,7 +1859,6 @@ check_tuple_attribute(HeapCheckContext *ctx) static void check_toasted_attribute(HeapCheckContext *ctx, ToastedAttribute *ta) { - SnapshotData SnapshotToast; ScanKeyData toastkey; SysScanDesc toastscan; bool found_toasttup; @@ -1787,10 +1882,9 @@ check_toasted_attribute(HeapCheckContext *ctx, ToastedAttribute *ta) * Check if any chunks for this toasted object exist in the toast table, * accessible via the index. */ - init_toast_snapshot(&SnapshotToast); toastscan = systable_beginscan_ordered(ctx->toast_rel, ctx->valid_toast_index, - &SnapshotToast, 1, + get_toast_snapshot(), 1, &toastkey); found_toasttup = false; while ((toasttup = @@ -1875,7 +1969,9 @@ check_tuple(HeapCheckContext *ctx, bool *xmin_commit_status_ok, /* * Convert a TransactionId into a FullTransactionId using our cached values of * the valid transaction ID range. It is the caller's responsibility to have - * already updated the cached values, if necessary. + * already updated the cached values, if necessary. This is akin to + * FullTransactionIdFromAllowableAt(), but it tolerates corruption in the form + * of an xid before epoch 0. */ static FullTransactionId FullTransactionIdFromXidAndCtx(TransactionId xid, const HeapCheckContext *ctx) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 34990c5cea3f3..f11c43a0ed797 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -14,7 +14,7 @@ * that every visible heap tuple has a matching index tuple. * * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/amcheck/verify_nbtree.c @@ -30,21 +30,23 @@ #include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" +#include "verify_common.h" #include "catalog/index.h" #include "catalog/pg_am.h" #include "catalog/pg_opfamily_d.h" -#include "commands/tablecmds.h" #include "common/pg_prng.h" #include "lib/bloomfilter.h" #include "miscadmin.h" -#include "storage/lmgr.h" #include "storage/smgr.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/snapmgr.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "amcheck", + .version = PG_VERSION +); /* * A B-Tree cannot possibly have this many levels, since there must be one @@ -158,14 +160,22 @@ typedef struct BtreeLastVisibleEntry ItemPointer tid; /* Heap tid */ } BtreeLastVisibleEntry; +/* + * arguments for the bt_index_check_callback callback + */ +typedef struct BTCallbackState +{ + bool parentcheck; + bool heapallindexed; + bool rootdescend; + bool checkunique; +} BTCallbackState; + PG_FUNCTION_INFO_V1(bt_index_check); PG_FUNCTION_INFO_V1(bt_index_parent_check); -static void bt_index_check_internal(Oid indrelid, bool parentcheck, - bool heapallindexed, bool rootdescend, - bool checkunique); -static inline void btree_index_checkable(Relation rel); -static inline bool btree_index_mainfork_expected(Relation rel); +static void bt_index_check_callback(Relation indrel, Relation heaprel, + void *state, bool readonly); static void bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace, bool readonly, bool heapallindexed, bool rootdescend, bool checkunique); @@ -240,15 +250,21 @@ Datum bt_index_check(PG_FUNCTION_ARGS) { Oid indrelid = PG_GETARG_OID(0); - bool heapallindexed = false; - bool checkunique = false; + BTCallbackState args; + + args.heapallindexed = false; + args.rootdescend = false; + args.parentcheck = false; + args.checkunique = false; if (PG_NARGS() >= 2) - heapallindexed = PG_GETARG_BOOL(1); - if (PG_NARGS() == 3) - checkunique = PG_GETARG_BOOL(2); + args.heapallindexed = PG_GETARG_BOOL(1); + if (PG_NARGS() >= 3) + args.checkunique = PG_GETARG_BOOL(2); - bt_index_check_internal(indrelid, false, heapallindexed, false, checkunique); + amcheck_lock_relation_and_check(indrelid, BTREE_AM_OID, + bt_index_check_callback, + AccessShareLock, &args); PG_RETURN_VOID(); } @@ -266,18 +282,23 @@ Datum bt_index_parent_check(PG_FUNCTION_ARGS) { Oid indrelid = PG_GETARG_OID(0); - bool heapallindexed = false; - bool rootdescend = false; - bool checkunique = false; + BTCallbackState args; + + args.heapallindexed = false; + args.rootdescend = false; + args.parentcheck = true; + args.checkunique = false; if (PG_NARGS() >= 2) - heapallindexed = PG_GETARG_BOOL(1); + args.heapallindexed = PG_GETARG_BOOL(1); if (PG_NARGS() >= 3) - rootdescend = PG_GETARG_BOOL(2); - if (PG_NARGS() == 4) - checkunique = PG_GETARG_BOOL(3); + args.rootdescend = PG_GETARG_BOOL(2); + if (PG_NARGS() >= 4) + args.checkunique = PG_GETARG_BOOL(3); - bt_index_check_internal(indrelid, true, heapallindexed, rootdescend, checkunique); + amcheck_lock_relation_and_check(indrelid, BTREE_AM_OID, + bt_index_check_callback, + ShareLock, &args); PG_RETURN_VOID(); } @@ -286,193 +307,46 @@ bt_index_parent_check(PG_FUNCTION_ARGS) * Helper for bt_index_[parent_]check, coordinating the bulk of the work. */ static void -bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed, - bool rootdescend, bool checkunique) +bt_index_check_callback(Relation indrel, Relation heaprel, void *state, bool readonly) { - Oid heapid; - Relation indrel; - Relation heaprel; - LOCKMODE lockmode; - Oid save_userid; - int save_sec_context; - int save_nestlevel; + BTCallbackState *args = (BTCallbackState *) state; + bool heapkeyspace, + allequalimage; - if (parentcheck) - lockmode = ShareLock; - else - lockmode = AccessShareLock; - - /* - * We must lock table before index to avoid deadlocks. However, if the - * passed indrelid isn't an index then IndexGetRelation() will fail. - * Rather than emitting a not-very-helpful error message, postpone - * complaining, expecting that the is-it-an-index test below will fail. - * - * In hot standby mode this will raise an error when parentcheck is true. - */ - heapid = IndexGetRelation(indrelid, true); - if (OidIsValid(heapid)) - { - heaprel = table_open(heapid, lockmode); - - /* - * Switch to the table owner's userid, so that any index functions are - * run as that user. Also lock down security-restricted operations - * and arrange to make GUC variable changes local to this command. - */ - GetUserIdAndSecContext(&save_userid, &save_sec_context); - SetUserIdAndSecContext(heaprel->rd_rel->relowner, - save_sec_context | SECURITY_RESTRICTED_OPERATION); - save_nestlevel = NewGUCNestLevel(); - RestrictSearchPath(); - } - else - { - heaprel = NULL; - /* Set these just to suppress "uninitialized variable" warnings */ - save_userid = InvalidOid; - save_sec_context = -1; - save_nestlevel = -1; - } - - /* - * Open the target index relations separately (like relation_openrv(), but - * with heap relation locked first to prevent deadlocking). In hot - * standby mode this will raise an error when parentcheck is true. - * - * There is no need for the usual indcheckxmin usability horizon test - * here, even in the heapallindexed case, because index undergoing - * verification only needs to have entries for a new transaction snapshot. - * (If this is a parentcheck verification, there is no question about - * committed or recently dead heap tuples lacking index entries due to - * concurrent activity.) - */ - indrel = index_open(indrelid, lockmode); - - /* - * Since we did the IndexGetRelation call above without any lock, it's - * barely possible that a race against an index drop/recreation could have - * netted us the wrong table. - */ - if (heaprel == NULL || heapid != IndexGetRelation(indrelid, false)) + if (!smgrexists(RelationGetSmgr(indrel), MAIN_FORKNUM)) ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("could not open parent table of index \"%s\"", + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" lacks a main relation fork", RelationGetRelationName(indrel)))); - /* Relation suitable for checking as B-Tree? */ - btree_index_checkable(indrel); - - if (btree_index_mainfork_expected(indrel)) + /* Extract metadata from metapage, and sanitize it in passing */ + _bt_metaversion(indrel, &heapkeyspace, &allequalimage); + if (allequalimage && !heapkeyspace) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" metapage has equalimage field set on unsupported nbtree version", + RelationGetRelationName(indrel)))); + if (allequalimage && !_bt_allequalimage(indrel, false)) { - bool heapkeyspace, - allequalimage; - - if (!smgrexists(RelationGetSmgr(indrel), MAIN_FORKNUM)) - ereport(ERROR, - (errcode(ERRCODE_INDEX_CORRUPTED), - errmsg("index \"%s\" lacks a main relation fork", - RelationGetRelationName(indrel)))); - - /* Extract metadata from metapage, and sanitize it in passing */ - _bt_metaversion(indrel, &heapkeyspace, &allequalimage); - if (allequalimage && !heapkeyspace) - ereport(ERROR, - (errcode(ERRCODE_INDEX_CORRUPTED), - errmsg("index \"%s\" metapage has equalimage field set on unsupported nbtree version", - RelationGetRelationName(indrel)))); - if (allequalimage && !_bt_allequalimage(indrel, false)) - { - bool has_interval_ops = false; - - for (int i = 0; i < IndexRelationGetNumberOfKeyAttributes(indrel); i++) - if (indrel->rd_opfamily[i] == INTERVAL_BTREE_FAM_OID) - has_interval_ops = true; - ereport(ERROR, - (errcode(ERRCODE_INDEX_CORRUPTED), - errmsg("index \"%s\" metapage incorrectly indicates that deduplication is safe", - RelationGetRelationName(indrel)), - has_interval_ops - ? errhint("This is known of \"interval\" indexes last built on a version predating 2023-11.") - : 0)); - } + bool has_interval_ops = false; - /* Check index, possibly against table it is an index on */ - bt_check_every_level(indrel, heaprel, heapkeyspace, parentcheck, - heapallindexed, rootdescend, checkunique); + for (int i = 0; i < IndexRelationGetNumberOfKeyAttributes(indrel); i++) + if (indrel->rd_opfamily[i] == INTERVAL_BTREE_FAM_OID) + { + has_interval_ops = true; + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("index \"%s\" metapage incorrectly indicates that deduplication is safe", + RelationGetRelationName(indrel)), + has_interval_ops + ? errhint("This is known of \"interval\" indexes last built on a version predating 2023-11.") + : 0)); + } } - /* Roll back any GUC changes executed by index functions */ - AtEOXact_GUC(false, save_nestlevel); - - /* Restore userid and security context */ - SetUserIdAndSecContext(save_userid, save_sec_context); - - /* - * Release locks early. That's ok here because nothing in the called - * routines will trigger shared cache invalidations to be sent, so we can - * relax the usual pattern of only releasing locks after commit. - */ - index_close(indrel, lockmode); - if (heaprel) - table_close(heaprel, lockmode); -} - -/* - * Basic checks about the suitability of a relation for checking as a B-Tree - * index. - * - * NB: Intentionally not checking permissions, the function is normally not - * callable by non-superusers. If granted, it's useful to be able to check a - * whole cluster. - */ -static inline void -btree_index_checkable(Relation rel) -{ - if (rel->rd_rel->relkind != RELKIND_INDEX || - rel->rd_rel->relam != BTREE_AM_OID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("only B-Tree indexes are supported as targets for verification"), - errdetail("Relation \"%s\" is not a B-Tree index.", - RelationGetRelationName(rel)))); - - if (RELATION_IS_OTHER_TEMP(rel)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot access temporary tables of other sessions"), - errdetail("Index \"%s\" is associated with temporary relation.", - RelationGetRelationName(rel)))); - - if (!rel->rd_index->indisvalid) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot check index \"%s\"", - RelationGetRelationName(rel)), - errdetail("Index is not valid."))); -} - -/* - * Check if B-Tree index relation should have a file for its main relation - * fork. Verification uses this to skip unlogged indexes when in hot standby - * mode, where there is simply nothing to verify. We behave as if the - * relation is empty. - * - * NB: Caller should call btree_index_checkable() before calling here. - */ -static inline bool -btree_index_mainfork_expected(Relation rel) -{ - if (rel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED || - !RecoveryInProgress()) - return true; - - ereport(DEBUG1, - (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), - errmsg("cannot verify unlogged index \"%s\" during recovery, skipping", - RelationGetRelationName(rel)))); - - return false; + /* Check index, possibly against table it is an index on */ + bt_check_every_level(indrel, heaprel, heapkeyspace, readonly, + args->heapallindexed, args->rootdescend, args->checkunique); } /* @@ -721,7 +595,7 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace, RelationGetRelationName(state->heaprel)); table_index_build_scan(state->heaprel, state->rel, indexinfo, true, false, - bt_tuple_present_callback, (void *) state, scan); + bt_tuple_present_callback, state, scan); ereport(DEBUG1, (errmsg_internal("finished verifying presence of " INT64_FORMAT " tuples from table \"%s\" with bitset %.2f%% set", @@ -1433,6 +1307,13 @@ bt_target_page_check(BtreeCheckState *state) bool lowersizelimit; ItemPointer scantid; + /* + * True if we already called bt_entry_unique_check() for the current + * item. This helps to avoid visiting the heap for keys, which are + * anyway presented only once and can't comprise a unique violation. + */ + bool unique_checked = false; + CHECK_FOR_INTERRUPTS(); itemid = PageGetItemIdCareful(state, state->targetblock, @@ -1592,8 +1473,7 @@ bt_target_page_check(BtreeCheckState *state) */ lowersizelimit = skey->heapkeyspace && (P_ISLEAF(topaque) || BTreeTupleGetHeapTID(itup) == NULL); - if (tupsize > (lowersizelimit ? BTMaxItemSize(state->target) : - BTMaxItemSizeNoHeapTid(state->target))) + if (tupsize > (lowersizelimit ? BTMaxItemSize : BTMaxItemSizeNoHeapTid)) { ItemPointer tid = BTreeTupleGetPointsToTID(itup); char *itid, @@ -1775,12 +1655,18 @@ bt_target_page_check(BtreeCheckState *state) /* * If the index is unique verify entries uniqueness by checking the - * heap tuples visibility. + * heap tuples visibility. Immediately check posting tuples and + * tuples with repeated keys. Postpone check for keys, which have the + * first appearance. */ if (state->checkunique && state->indexinfo->ii_Unique && - P_ISLEAF(topaque) && !skey->anynullkeys) + P_ISLEAF(topaque) && !skey->anynullkeys && + (BTreeTupleIsPosting(itup) || ItemPointerIsValid(lVis.tid))) + { bt_entry_unique_check(state, itup, state->targetblock, offset, &lVis); + unique_checked = true; + } if (state->checkunique && state->indexinfo->ii_Unique && P_ISLEAF(topaque) && OffsetNumberNext(offset) <= max) @@ -1799,6 +1685,9 @@ bt_target_page_check(BtreeCheckState *state) * data (whole index tuple or last posting in index tuple). Key * containing null value does not violate unique constraint and * treated as different to any other key. + * + * If the next key is the same as the previous one, do the + * bt_entry_unique_check() call if it was postponed. */ if (_bt_compare(state->rel, skey, state->target, OffsetNumberNext(offset)) != 0 || skey->anynullkeys) @@ -1808,6 +1697,11 @@ bt_target_page_check(BtreeCheckState *state) lVis.postingIndex = -1; lVis.tid = NULL; } + else if (!unique_checked) + { + bt_entry_unique_check(state, itup, state->targetblock, offset, + &lVis); + } skey->scantid = scantid; /* Restore saved scan key state */ } @@ -1890,10 +1784,19 @@ bt_target_page_check(BtreeCheckState *state) rightkey->scantid = NULL; /* The first key on the next page is the same */ - if (_bt_compare(state->rel, rightkey, state->target, max) == 0 && !rightkey->anynullkeys) + if (_bt_compare(state->rel, rightkey, state->target, max) == 0 && + !rightkey->anynullkeys) { Page rightpage; + /* + * Do the bt_entry_unique_check() call if it was + * postponed. + */ + if (!unique_checked) + bt_entry_unique_check(state, itup, state->targetblock, + offset, &lVis); + elog(DEBUG2, "cross page equal keys"); rightpage = palloc_btree_page(state, rightblock_number); @@ -2441,7 +2344,7 @@ bt_child_highkey_check(BtreeCheckState *state, * So, now we traverse to the right of that cousin page and * current child level page under consideration still belongs * to the subtree of target's left sibling. Thus, we need to - * match child's high key to it's left uncle page high key. + * match child's high key to its left uncle page high key. * Thankfully we saved it, it's called a "low key" of target * page. */ diff --git a/contrib/auth_delay/auth_delay.c b/contrib/auth_delay/auth_delay.c index ff0e1fd461bb3..8681b54fc3a8e 100644 --- a/contrib/auth_delay/auth_delay.c +++ b/contrib/auth_delay/auth_delay.c @@ -2,7 +2,7 @@ * * auth_delay.c * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/auth_delay/auth_delay.c @@ -14,11 +14,12 @@ #include #include "libpq/auth.h" -#include "port.h" #include "utils/guc.h" -#include "utils/timestamp.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "auth_delay", + .version = PG_VERSION +); /* GUC Variables */ static int auth_delay_milliseconds = 0; diff --git a/contrib/auth_delay/meson.build b/contrib/auth_delay/meson.build index 9ef5a7091eeec..2fecf2359976b 100644 --- a/contrib/auth_delay/meson.build +++ b/contrib/auth_delay/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group auth_delay_sources = files( 'auth_delay.c', diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index 677c135f59bc2..1f4badb492840 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -3,7 +3,7 @@ * auto_explain.c * * - * Copyright (c) 2008-2024, PostgreSQL Global Development Group + * Copyright (c) 2008-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/auto_explain/auto_explain.c @@ -16,13 +16,16 @@ #include "access/parallel.h" #include "commands/explain.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" #include "common/pg_prng.h" #include "executor/instrument.h" -#include "jit/jit.h" -#include "nodes/params.h" #include "utils/guc.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "auto_explain", + .version = PG_VERSION +); /* GUC variables */ static int auto_explain_log_min_duration = -1; /* msec or -1 */ @@ -72,7 +75,7 @@ static bool current_query_sampled = false; (nesting_level == 0 || auto_explain_log_nested_statements) && \ current_query_sampled) -/* Saved hook values in case of unload */ +/* Saved hook values */ static ExecutorStart_hook_type prev_ExecutorStart = NULL; static ExecutorRun_hook_type prev_ExecutorRun = NULL; static ExecutorFinish_hook_type prev_ExecutorFinish = NULL; @@ -81,7 +84,7 @@ static ExecutorEnd_hook_type prev_ExecutorEnd = NULL; static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags); static void explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, - uint64 count, bool execute_once); + uint64 count); static void explain_ExecutorFinish(QueryDesc *queryDesc); static void explain_ExecutorEnd(QueryDesc *queryDesc); @@ -95,7 +98,7 @@ _PG_init(void) /* Define custom GUC variables. */ DefineCustomIntVariable("auto_explain.log_min_duration", "Sets the minimum execution time above which plans will be logged.", - "Zero prints all plans. -1 turns this feature off.", + "-1 disables logging plans. 0 means log all plans.", &auto_explain_log_min_duration, -1, -1, INT_MAX, @@ -106,8 +109,8 @@ _PG_init(void) NULL); DefineCustomIntVariable("auto_explain.log_parameter_max_length", - "Sets the maximum length of query parameters to log.", - "Zero logs no query parameters, -1 logs them in full.", + "Sets the maximum length of query parameter values to log.", + "-1 means log values in full.", &auto_explain_log_parameter_max_length, -1, -1, INT_MAX, @@ -323,15 +326,15 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags) */ static void explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, - uint64 count, bool execute_once) + uint64 count) { nesting_level++; PG_TRY(); { if (prev_ExecutorRun) - prev_ExecutorRun(queryDesc, direction, count, execute_once); + prev_ExecutorRun(queryDesc, direction, count); else - standard_ExecutorRun(queryDesc, direction, count, execute_once); + standard_ExecutorRun(queryDesc, direction, count); } PG_FINALLY(); { diff --git a/contrib/auto_explain/meson.build b/contrib/auto_explain/meson.build index af1a3b8e3250e..92dc9df6f7cac 100644 --- a/contrib/auto_explain/meson.build +++ b/contrib/auto_explain/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group auto_explain_sources = files( 'auto_explain.c', diff --git a/contrib/auto_explain/t/001_auto_explain.pl b/contrib/auto_explain/t/001_auto_explain.pl index 0e5b34afa9456..6af5ac1da1845 100644 --- a/contrib/auto_explain/t/001_auto_explain.pl +++ b/contrib/auto_explain/t/001_auto_explain.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -28,7 +28,7 @@ sub query_log } my $node = PostgreSQL::Test::Cluster->new('main'); -$node->init('auth_extra' => [ '--create-role', 'regress_user1' ]); +$node->init(auth_extra => [ '--create-role' => 'regress_user1' ]); $node->append_conf('postgresql.conf', "session_preload_libraries = 'auto_explain'"); $node->append_conf('postgresql.conf', "auto_explain.log_min_duration = 0"); @@ -212,4 +212,17 @@ sub query_log DROP USER regress_user1; }); +# Test pg_get_loaded_modules() function. This function is particularly +# useful for modules with no SQL presence, such as auto_explain. + +my $res = $node->safe_psql( + "postgres", q{ +SELECT module_name, + version = current_setting('server_version') as version_ok, + regexp_replace(file_name, '\..*', '') as file_name_stripped +FROM pg_get_loaded_modules() +WHERE module_name = 'auto_explain'; +}); +like($res, qr/^auto_explain\|t\|auto_explain$/, "pg_get_loaded_modules() ok"); + done_testing(); diff --git a/contrib/basebackup_to_shell/basebackup_to_shell.c b/contrib/basebackup_to_shell/basebackup_to_shell.c index fe419d90806a7..8720f5a43727d 100644 --- a/contrib/basebackup_to_shell/basebackup_to_shell.c +++ b/contrib/basebackup_to_shell/basebackup_to_shell.c @@ -3,7 +3,7 @@ * basebackup_to_shell.c * target base backup files to a shell command * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * contrib/basebackup_to_shell/basebackup_to_shell.c *------------------------------------------------------------------------- @@ -18,7 +18,10 @@ #include "utils/acl.h" #include "utils/guc.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "basebackup_to_shell", + .version = PG_VERSION +); typedef struct bbsink_shell { diff --git a/contrib/basebackup_to_shell/meson.build b/contrib/basebackup_to_shell/meson.build index 8175c9b5c5bba..8c88242456e80 100644 --- a/contrib/basebackup_to_shell/meson.build +++ b/contrib/basebackup_to_shell/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group basebackup_to_shell_sources = files( 'basebackup_to_shell.c', diff --git a/contrib/basebackup_to_shell/t/001_basic.pl b/contrib/basebackup_to_shell/t/001_basic.pl index 07cb32fdae951..4d540147a6de9 100644 --- a/contrib/basebackup_to_shell/t/001_basic.pl +++ b/contrib/basebackup_to_shell/t/001_basic.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -24,8 +24,8 @@ # Make sure pg_hba.conf is set up to allow connections from backupuser. # This is only needed on Windows machines that don't use UNIX sockets. $node->init( - 'allows_streaming' => 1, - 'auth_extra' => [ '--create-role', 'backupuser' ]); + allows_streaming => 1, + auth_extra => [ '--create-role' => 'backupuser' ]); $node->append_conf('postgresql.conf', "shared_preload_libraries = 'basebackup_to_shell'"); @@ -37,15 +37,19 @@ # to keep test times reasonable. Using @pg_basebackup_defs as the first # element of the array passed to IPC::Run interpolate the array (as it is # not a reference to an array)... -my @pg_basebackup_defs = ('pg_basebackup', '--no-sync', '-cfast'); +my @pg_basebackup_defs = + ('pg_basebackup', '--no-sync', '--checkpoint' => 'fast'); # This particular test module generally wants to run with -Xfetch, because # -Xstream is not supported with a backup target, and with -U backupuser. -my @pg_basebackup_cmd = (@pg_basebackup_defs, '-U', 'backupuser', '-Xfetch'); +my @pg_basebackup_cmd = ( + @pg_basebackup_defs, + '--username' => 'backupuser', + '--wal-method' => 'fetch'); # Can't use this module without setting basebackup_to_shell.command. $node->command_fails_like( - [ @pg_basebackup_cmd, '--target', 'shell' ], + [ @pg_basebackup_cmd, '--target' => 'shell' ], qr/shell command for backup is not configured/, 'fails if basebackup_to_shell.command is not set'); @@ -64,13 +68,13 @@ # Should work now. $node->command_ok( - [ @pg_basebackup_cmd, '--target', 'shell' ], + [ @pg_basebackup_cmd, '--target' => 'shell' ], 'backup with no detail: pg_basebackup'); verify_backup('', $backup_path, "backup with no detail"); # Should fail with a detail. $node->command_fails_like( - [ @pg_basebackup_cmd, '--target', 'shell:foo' ], + [ @pg_basebackup_cmd, '--target' => 'shell:foo' ], qr/a target detail is not permitted because the configured command does not include %d/, 'fails if detail provided without %d'); @@ -87,19 +91,19 @@ # Should fail due to lack of permission. $node->command_fails_like( - [ @pg_basebackup_cmd, '--target', 'shell' ], + [ @pg_basebackup_cmd, '--target' => 'shell' ], qr/permission denied to use basebackup_to_shell/, 'fails if required_role not granted'); # Should fail due to lack of a detail. $node->safe_psql('postgres', 'GRANT trustworthy TO backupuser'); $node->command_fails_like( - [ @pg_basebackup_cmd, '--target', 'shell' ], + [ @pg_basebackup_cmd, '--target' => 'shell' ], qr/a target detail is required because the configured command includes %d/, 'fails if %d is present and detail not given'); # Should work. -$node->command_ok([ @pg_basebackup_cmd, '--target', 'shell:bar' ], +$node->command_ok([ @pg_basebackup_cmd, '--target' => 'shell:bar' ], 'backup with detail: pg_basebackup'); verify_backup('bar.', $backup_path, "backup with detail"); @@ -127,15 +131,19 @@ sub verify_backup # Untar. my $extract_path = PostgreSQL::Test::Utils::tempdir; - system_or_bail($tar, 'xf', $backup_dir . '/' . $prefix . 'base.tar', - '-C', $extract_path); + system_or_bail( + $tar, + 'xf' => $backup_dir . '/' . $prefix . 'base.tar', + '-C' => $extract_path); # Verify. $node->command_ok( [ - 'pg_verifybackup', '-n', - '-m', "${backup_dir}/${prefix}backup_manifest", - '-e', $extract_path + 'pg_verifybackup', + '--no-parse-wal', + '--manifest-path' => "${backup_dir}/${prefix}backup_manifest", + '--exit-on-error', + $extract_path ], "$test_name: backup verifies ok"); } diff --git a/contrib/basic_archive/basic_archive.c b/contrib/basic_archive/basic_archive.c index 028cf51c25d46..4a8b8c7ac29c1 100644 --- a/contrib/basic_archive/basic_archive.c +++ b/contrib/basic_archive/basic_archive.c @@ -17,7 +17,7 @@ * a file is successfully archived and then the system crashes before * a durable record of the success has been made. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/basic_archive/basic_archive.c @@ -36,9 +36,11 @@ #include "storage/copydir.h" #include "storage/fd.h" #include "utils/guc.h" -#include "utils/memutils.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "basic_archive", + .version = PG_VERSION +); static char *archive_directory = NULL; diff --git a/contrib/basic_archive/meson.build b/contrib/basic_archive/meson.build index cc2f62bf36e5a..c2d8a38c7ca32 100644 --- a/contrib/basic_archive/meson.build +++ b/contrib/basic_archive/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group basic_archive_sources = files( 'basic_archive.c', diff --git a/contrib/bloom/blcost.c b/contrib/bloom/blcost.c index 9b629b2c3d57e..a38fcf3c57918 100644 --- a/contrib/bloom/blcost.c +++ b/contrib/bloom/blcost.c @@ -3,7 +3,7 @@ * blcost.c * Cost estimate function for bloom indexes. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/blcost.c @@ -13,7 +13,6 @@ #include "postgres.h" #include "bloom.h" -#include "fmgr.h" #include "utils/selfuncs.h" /* diff --git a/contrib/bloom/blinsert.c b/contrib/bloom/blinsert.c index f8a1061abb9ef..7866438122f58 100644 --- a/contrib/bloom/blinsert.c +++ b/contrib/bloom/blinsert.c @@ -3,7 +3,7 @@ * blinsert.c * Bloom index build and insert functions. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/blinsert.c @@ -16,15 +16,16 @@ #include "access/generic_xlog.h" #include "access/tableam.h" #include "bloom.h" -#include "catalog/index.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "storage/bufmgr.h" -#include "storage/indexfsm.h" -#include "storage/smgr.h" #include "utils/memutils.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "bloom", + .version = PG_VERSION +); /* * State of bloom index build. We accumulate one page data here before @@ -141,7 +142,7 @@ blbuild(Relation heap, Relation index, IndexInfo *indexInfo) /* Do the heap scan */ reltuples = table_index_build_scan(heap, index, indexInfo, true, true, - bloomBuildCallback, (void *) &buildstate, + bloomBuildCallback, &buildstate, NULL); /* Flush last page if needed (it will be, unless heap was empty) */ diff --git a/contrib/bloom/bloom.h b/contrib/bloom/bloom.h index fba3ba77711a4..648167045f4e8 100644 --- a/contrib/bloom/bloom.h +++ b/contrib/bloom/bloom.h @@ -3,7 +3,7 @@ * bloom.h * Header for bloom index. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/bloom.h @@ -110,12 +110,9 @@ typedef struct BloomOptions * FreeBlockNumberArray - array of block numbers sized so that metadata fill * all space in metapage. */ -typedef BlockNumber FreeBlockNumberArray[ - MAXALIGN_DOWN( - BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(BloomPageOpaqueData)) - - MAXALIGN(sizeof(uint16) * 2 + sizeof(uint32) + sizeof(BloomOptions)) - ) / sizeof(BlockNumber) -]; +typedef BlockNumber FreeBlockNumberArray[MAXALIGN_DOWN(BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(BloomPageOpaqueData)) + - MAXALIGN(sizeof(uint16) * 2 + sizeof(uint32) + sizeof(BloomOptions))) + / sizeof(BlockNumber)]; /* Metadata of bloom index */ typedef struct BloomMetaPageData diff --git a/contrib/bloom/blscan.c b/contrib/bloom/blscan.c index 0a303a49b24d8..d072f47fe28b5 100644 --- a/contrib/bloom/blscan.c +++ b/contrib/bloom/blscan.c @@ -3,7 +3,7 @@ * blscan.c * Bloom index scan functions. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/blscan.c @@ -17,9 +17,6 @@ #include "miscadmin.h" #include "pgstat.h" #include "storage/bufmgr.h" -#include "storage/lmgr.h" -#include "utils/memutils.h" -#include "utils/rel.h" /* * Begin scan of bloom index. @@ -55,10 +52,7 @@ blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, so->sign = NULL; if (scankey && scan->numberOfKeys > 0) - { - memmove(scan->keyData, scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); - } + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); } /* @@ -121,6 +115,9 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) */ bas = GetAccessStrategy(BAS_BULKREAD); npages = RelationGetNumberOfBlocks(scan->indexRelation); + pgstat_count_index_scan(scan->indexRelation); + if (scan->instrument) + scan->instrument->nsearches++; for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++) { diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index 6836129c90d8e..2c0e71eedc654 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -3,7 +3,7 @@ * blutils.c * Bloom index utilities. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1990-1993, Regents of the University of California * * IDENTIFICATION @@ -17,14 +17,11 @@ #include "access/generic_xlog.h" #include "access/reloptions.h" #include "bloom.h" -#include "catalog/index.h" #include "commands/vacuum.h" -#include "miscadmin.h" #include "storage/bufmgr.h" -#include "storage/freespace.h" #include "storage/indexfsm.h" -#include "storage/lmgr.h" #include "utils/memutils.h" +#include "varatt.h" /* Signature dealing macros - note i is assumed to be of type int */ #define GETWORD(x,i) ( *( (BloomSignatureWord *)(x) + ( (i) / SIGNWORDBITS ) ) ) @@ -112,6 +109,9 @@ blhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BLOOM_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; @@ -137,6 +137,7 @@ blhandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = blvacuumcleanup; amroutine->amcanreturn = NULL; amroutine->amcostestimate = blcostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = bloptions; amroutine->amproperty = NULL; amroutine->ambuildphasename = NULL; @@ -152,6 +153,8 @@ blhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } @@ -201,7 +204,7 @@ initBloomState(BloomState *state, Relation index) UnlockReleaseBuffer(buffer); - index->rd_amcache = (void *) opts; + index->rd_amcache = opts; } memcpy(&state->opts, index->rd_amcache, sizeof(state->opts)); diff --git a/contrib/bloom/blvacuum.c b/contrib/bloom/blvacuum.c index 0998240feaff5..86b15a75f6fb9 100644 --- a/contrib/bloom/blvacuum.c +++ b/contrib/bloom/blvacuum.c @@ -3,7 +3,7 @@ * blvacuum.c * Bloom VACUUM functions. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/blvacuum.c @@ -14,13 +14,9 @@ #include "access/genam.h" #include "bloom.h" -#include "catalog/storage.h" #include "commands/vacuum.h" -#include "miscadmin.h" -#include "postmaster/autovacuum.h" #include "storage/bufmgr.h" #include "storage/indexfsm.h" -#include "storage/lmgr.h" /* @@ -61,7 +57,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, *itupPtr, *itupEnd; - vacuum_delay_point(); + vacuum_delay_point(false); buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno, RBM_NORMAL, info->strategy); @@ -191,7 +187,7 @@ blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) Buffer buffer; Page page; - vacuum_delay_point(); + vacuum_delay_point(false); buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno, RBM_NORMAL, info->strategy); diff --git a/contrib/bloom/blvalidate.c b/contrib/bloom/blvalidate.c index 88c5a791975c4..001c188aeb712 100644 --- a/contrib/bloom/blvalidate.c +++ b/contrib/bloom/blvalidate.c @@ -3,7 +3,7 @@ * blvalidate.c * Opclass validator for bloom. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/bloom/blvalidate.c @@ -18,9 +18,7 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" -#include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/syscache.h" @@ -38,8 +36,6 @@ blvalidate(Oid opclassoid) Oid opcintype; Oid opckeytype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -62,12 +58,7 @@ blvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -126,7 +117,7 @@ blvalidate(Oid opclassoid) { ereport(INFO, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("gist opfamily %s contains function %s with wrong signature for support number %d", + errmsg("bloom opfamily %s contains function %s with wrong signature for support number %d", opfamilyname, format_procedure(procform->amproc), procform->amprocnum))); @@ -218,7 +209,6 @@ blvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; diff --git a/contrib/bloom/meson.build b/contrib/bloom/meson.build index 422e39e74eab5..695712a455e6d 100644 --- a/contrib/bloom/meson.build +++ b/contrib/bloom/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group bloom_sources = files( 'blcost.c', diff --git a/contrib/bloom/t/001_wal.pl b/contrib/bloom/t/001_wal.pl index 61f5641d9e56e..612920001cd2a 100644 --- a/contrib/bloom/t/001_wal.pl +++ b/contrib/bloom/t/001_wal.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test generic xlog record work for bloom index replication. use strict; diff --git a/contrib/bool_plperl/bool_plperl.c b/contrib/bool_plperl/bool_plperl.c index 0fa1eee8e57eb..7c611bd52a7b4 100644 --- a/contrib/bool_plperl/bool_plperl.c +++ b/contrib/bool_plperl/bool_plperl.c @@ -4,7 +4,10 @@ #include "plperl.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "bool_plperl", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(bool_to_plperl); diff --git a/contrib/bool_plperl/expected/bool_plperl.out b/contrib/bool_plperl/expected/bool_plperl.out index 187df8db96f9e..183dc07b3fbc3 100644 --- a/contrib/bool_plperl/expected/bool_plperl.out +++ b/contrib/bool_plperl/expected/bool_plperl.out @@ -104,9 +104,9 @@ SELECT spi_test(); DROP EXTENSION plperl CASCADE; NOTICE: drop cascades to 6 other objects -DETAIL: drop cascades to function spi_test() -drop cascades to extension bool_plperl +DETAIL: drop cascades to extension bool_plperl drop cascades to function perl2int(integer) drop cascades to function perl2text(text) drop cascades to function perl2undef() drop cascades to function bool2perl(boolean,boolean,boolean) +drop cascades to function spi_test() diff --git a/contrib/bool_plperl/expected/bool_plperlu.out b/contrib/bool_plperl/expected/bool_plperlu.out index 8337d337e992e..1496bbafac8e0 100644 --- a/contrib/bool_plperl/expected/bool_plperlu.out +++ b/contrib/bool_plperl/expected/bool_plperlu.out @@ -104,9 +104,9 @@ SELECT spi_test(); DROP EXTENSION plperlu CASCADE; NOTICE: drop cascades to 6 other objects -DETAIL: drop cascades to function spi_test() -drop cascades to extension bool_plperlu +DETAIL: drop cascades to extension bool_plperlu drop cascades to function perl2int(integer) drop cascades to function perl2text(text) drop cascades to function perl2undef() drop cascades to function bool2perl(boolean,boolean,boolean) +drop cascades to function spi_test() diff --git a/contrib/bool_plperl/meson.build b/contrib/bool_plperl/meson.build index 43eaa9cd77aed..f489d99044ce0 100644 --- a/contrib/bool_plperl/meson.build +++ b/contrib/bool_plperl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not perl_dep.found() subdir_done() diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c index 5e27906f802b0..98663cb86117e 100644 --- a/contrib/btree_gin/btree_gin.c +++ b/contrib/btree_gin/btree_gin.c @@ -7,17 +7,17 @@ #include "access/stratnum.h" #include "utils/builtins.h" -#include "utils/bytea.h" -#include "utils/cash.h" #include "utils/date.h" #include "utils/float.h" #include "utils/inet.h" #include "utils/numeric.h" #include "utils/timestamp.h" #include "utils/uuid.h" -#include "utils/varbit.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "btree_gin", + .version = PG_VERSION +); typedef struct QueryInfo { diff --git a/contrib/btree_gin/meson.build b/contrib/btree_gin/meson.build index 74c1adeebb037..b2749f6e66951 100644 --- a/contrib/btree_gin/meson.build +++ b/contrib/btree_gin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group btree_gin_sources = files( 'btree_gin.c', diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile index 073dcc745c4d3..68190ac5e4687 100644 --- a/contrib/btree_gist/Makefile +++ b/contrib/btree_gist/Makefile @@ -33,12 +33,14 @@ EXTENSION = btree_gist DATA = btree_gist--1.0--1.1.sql \ btree_gist--1.1--1.2.sql btree_gist--1.2.sql btree_gist--1.2--1.3.sql \ btree_gist--1.3--1.4.sql btree_gist--1.4--1.5.sql \ - btree_gist--1.5--1.6.sql btree_gist--1.6--1.7.sql + btree_gist--1.5--1.6.sql btree_gist--1.6--1.7.sql \ + btree_gist--1.7--1.8.sql btree_gist--1.8--1.9.sql PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes" REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \ time timetz date interval macaddr macaddr8 inet cidr text varchar char \ - bytea bit varbit numeric uuid not_equal enum bool partitions + bytea bit varbit numeric uuid not_equal enum bool partitions \ + stratnum without_overlaps SHLIB_LINK += $(filter -lm, $(LIBS)) diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c index 6790f22b4b670..0df2ae20d8b21 100644 --- a/contrib/btree_gist/btree_bit.c +++ b/contrib/btree_gist/btree_bit.c @@ -5,20 +5,19 @@ #include "btree_gist.h" #include "btree_utils_var.h" -#include "utils/builtins.h" -#include "utils/bytea.h" +#include "utils/fmgrprotos.h" +#include "utils/sortsupport.h" #include "utils/varbit.h" - -/* -** Bit ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_bit_compress); PG_FUNCTION_INFO_V1(gbt_bit_union); PG_FUNCTION_INFO_V1(gbt_bit_picksplit); PG_FUNCTION_INFO_V1(gbt_bit_consistent); PG_FUNCTION_INFO_V1(gbt_bit_penalty); PG_FUNCTION_INFO_V1(gbt_bit_same); +PG_FUNCTION_INFO_V1(gbt_bit_sortsupport); +PG_FUNCTION_INFO_V1(gbt_varbit_sortsupport); /* define for comparison */ @@ -122,7 +121,7 @@ static const gbtree_vinfo tinfo = /************************************************** - * Bit ops + * GiST support functions **************************************************/ Datum @@ -137,7 +136,7 @@ Datum gbt_bit_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) DatumGetByteaP(PG_GETARG_DATUM(1)); + void *query = DatumGetByteaP(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ @@ -162,8 +161,6 @@ gbt_bit_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } - - Datum gbt_bit_union(PG_FUNCTION_ARGS) { @@ -174,7 +171,6 @@ gbt_bit_union(PG_FUNCTION_ARGS) &tinfo, fcinfo->flinfo)); } - Datum gbt_bit_picksplit(PG_FUNCTION_ARGS) { @@ -197,7 +193,6 @@ gbt_bit_same(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_bit_penalty(PG_FUNCTION_ARGS) { @@ -208,3 +203,46 @@ gbt_bit_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo)); } + +static int +gbt_bit_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + /* for leaf items we expect lower == upper, so only compare lower */ + result = DirectFunctionCall2(byteacmp, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_bit_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bit_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} + +Datum +gbt_varbit_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bit_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_bool.c b/contrib/btree_gist/btree_bool.c index 8b2af129b52dc..1127597bb6017 100644 --- a/contrib/btree_gist/btree_bool.c +++ b/contrib/btree_gist/btree_bool.c @@ -5,7 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "common/int.h" +#include "utils/sortsupport.h" typedef struct boolkey { @@ -13,9 +13,7 @@ typedef struct boolkey bool upper; } boolKEY; -/* -** bool ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_bool_compress); PG_FUNCTION_INFO_V1(gbt_bool_fetch); PG_FUNCTION_INFO_V1(gbt_bool_union); @@ -23,6 +21,7 @@ PG_FUNCTION_INFO_V1(gbt_bool_picksplit); PG_FUNCTION_INFO_V1(gbt_bool_consistent); PG_FUNCTION_INFO_V1(gbt_bool_penalty); PG_FUNCTION_INFO_V1(gbt_bool_same); +PG_FUNCTION_INFO_V1(gbt_bool_sortsupport); static bool gbt_boolgt(const void *a, const void *b, FmgrInfo *flinfo) @@ -83,10 +82,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * bool ops + * GiST support functions **************************************************/ - Datum gbt_bool_compress(PG_FUNCTION_ARGS) { @@ -121,11 +119,10 @@ gbt_bool_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_bool_union(PG_FUNCTION_ARGS) { @@ -133,10 +130,9 @@ gbt_bool_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(boolKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(boolKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_bool_penalty(PG_FUNCTION_ARGS) { @@ -167,3 +163,24 @@ gbt_bool_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_bool_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + boolKEY *arg1 = (boolKEY *) DatumGetPointer(x); + boolKEY *arg2 = (boolKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return (int32) arg1->lower - (int32) arg2->lower; +} + +Datum +gbt_bool_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bool_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c index 6b005f0157e29..26f8710fad5c6 100644 --- a/contrib/btree_gist/btree_bytea.c +++ b/contrib/btree_gist/btree_bytea.c @@ -5,19 +5,17 @@ #include "btree_gist.h" #include "btree_utils_var.h" -#include "utils/builtins.h" -#include "utils/bytea.h" +#include "utils/fmgrprotos.h" +#include "utils/sortsupport.h" - -/* -** Bytea ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_bytea_compress); PG_FUNCTION_INFO_V1(gbt_bytea_union); PG_FUNCTION_INFO_V1(gbt_bytea_picksplit); PG_FUNCTION_INFO_V1(gbt_bytea_consistent); PG_FUNCTION_INFO_V1(gbt_bytea_penalty); PG_FUNCTION_INFO_V1(gbt_bytea_same); +PG_FUNCTION_INFO_V1(gbt_bytea_sortsupport); /* define for comparison */ @@ -70,7 +68,6 @@ gbt_byteacmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo) PointerGetDatum(b))); } - static const gbtree_vinfo tinfo = { gbt_t_bytea, @@ -87,10 +84,9 @@ static const gbtree_vinfo tinfo = /************************************************** - * Text ops + * GiST support functions **************************************************/ - Datum gbt_bytea_compress(PG_FUNCTION_ARGS) { @@ -99,13 +95,11 @@ gbt_bytea_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); } - - Datum gbt_bytea_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) DatumGetByteaP(PG_GETARG_DATUM(1)); + void *query = DatumGetByteaP(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ @@ -122,8 +116,6 @@ gbt_bytea_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } - - Datum gbt_bytea_union(PG_FUNCTION_ARGS) { @@ -134,7 +126,6 @@ gbt_bytea_union(PG_FUNCTION_ARGS) &tinfo, fcinfo->flinfo)); } - Datum gbt_bytea_picksplit(PG_FUNCTION_ARGS) { @@ -157,7 +148,6 @@ gbt_bytea_same(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_bytea_penalty(PG_FUNCTION_ARGS) { @@ -168,3 +158,35 @@ gbt_bytea_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo)); } + +static int +gbt_bytea_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R xkey = gbt_var_key_readable(key1); + GBT_VARKEY_R ykey = gbt_var_key_readable(key2); + Datum result; + + /* for leaf items we expect lower == upper, so only compare lower */ + result = DirectFunctionCall2(byteacmp, + PointerGetDatum(xkey.lower), + PointerGetDatum(ykey.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_bytea_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bytea_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c index 546b948ea400a..01c8d5a5f4074 100644 --- a/contrib/btree_gist/btree_cash.c +++ b/contrib/btree_gist/btree_cash.c @@ -7,6 +7,7 @@ #include "btree_utils_num.h" #include "common/int.h" #include "utils/cash.h" +#include "utils/sortsupport.h" typedef struct { @@ -14,9 +15,7 @@ typedef struct Cash upper; } cashKEY; -/* -** Cash ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_cash_compress); PG_FUNCTION_INFO_V1(gbt_cash_fetch); PG_FUNCTION_INFO_V1(gbt_cash_union); @@ -25,6 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_cash_consistent); PG_FUNCTION_INFO_V1(gbt_cash_distance); PG_FUNCTION_INFO_V1(gbt_cash_penalty); PG_FUNCTION_INFO_V1(gbt_cash_same); +PG_FUNCTION_INFO_V1(gbt_cash_sortsupport); static bool gbt_cashgt(const void *a, const void *b, FmgrInfo *flinfo) @@ -111,11 +111,11 @@ cash_dist(PG_FUNCTION_ARGS) PG_RETURN_CASH(ra); } + /************************************************** - * Cash ops + * GiST support functions **************************************************/ - Datum gbt_cash_compress(PG_FUNCTION_ARGS) { @@ -150,12 +150,11 @@ gbt_cash_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_cash_distance(PG_FUNCTION_ARGS) { @@ -169,11 +168,10 @@ gbt_cash_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_cash_union(PG_FUNCTION_ARGS) { @@ -181,10 +179,9 @@ gbt_cash_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(cashKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_cash_penalty(PG_FUNCTION_ARGS) { @@ -215,3 +212,29 @@ gbt_cash_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_cash_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + cashKEY *arg1 = (cashKEY *) DatumGetPointer(x); + cashKEY *arg2 = (cashKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (arg1->lower > arg2->lower) + return 1; + else if (arg1->lower < arg2->lower) + return -1; + else + return 0; +} + +Datum +gbt_cash_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_cash_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c index 68a4107dbf085..c008dc61ba5f5 100644 --- a/contrib/btree_gist/btree_date.c +++ b/contrib/btree_gist/btree_date.c @@ -5,8 +5,9 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/date.h" +#include "utils/sortsupport.h" typedef struct { @@ -14,9 +15,7 @@ typedef struct DateADT upper; } dateKEY; -/* -** date ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_date_compress); PG_FUNCTION_INFO_V1(gbt_date_fetch); PG_FUNCTION_INFO_V1(gbt_date_union); @@ -25,6 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_date_consistent); PG_FUNCTION_INFO_V1(gbt_date_distance); PG_FUNCTION_INFO_V1(gbt_date_penalty); PG_FUNCTION_INFO_V1(gbt_date_same); +PG_FUNCTION_INFO_V1(gbt_date_sortsupport); static bool gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo) @@ -128,11 +128,9 @@ date_dist(PG_FUNCTION_ARGS) /************************************************** - * date ops + * GiST support functions **************************************************/ - - Datum gbt_date_compress(PG_FUNCTION_ARGS) { @@ -167,12 +165,11 @@ gbt_date_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_date_distance(PG_FUNCTION_ARGS) { @@ -186,11 +183,10 @@ gbt_date_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_date_union(PG_FUNCTION_ARGS) { @@ -198,10 +194,9 @@ gbt_date_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(dateKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_date_penalty(PG_FUNCTION_ARGS) { @@ -238,7 +233,6 @@ gbt_date_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_date_picksplit(PG_FUNCTION_ARGS) { @@ -257,3 +251,26 @@ gbt_date_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_date_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + dateKEY *akey = (dateKEY *) DatumGetPointer(x); + dateKEY *bkey = (dateKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(date_cmp, + DateADTGetDatum(akey->lower), + DateADTGetDatum(bkey->lower))); +} + +Datum +gbt_date_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_date_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_enum.c b/contrib/btree_gist/btree_enum.c index d4dc38a38e524..83c95c7bb0401 100644 --- a/contrib/btree_gist/btree_enum.c +++ b/contrib/btree_gist/btree_enum.c @@ -6,7 +6,9 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "fmgr.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" +#include "utils/fmgroids.h" +#include "utils/sortsupport.h" /* enums are really Oids, so we just use the same structure */ @@ -16,9 +18,7 @@ typedef struct Oid upper; } oidKEY; -/* -** enum ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_enum_compress); PG_FUNCTION_INFO_V1(gbt_enum_fetch); PG_FUNCTION_INFO_V1(gbt_enum_union); @@ -26,6 +26,7 @@ PG_FUNCTION_INFO_V1(gbt_enum_picksplit); PG_FUNCTION_INFO_V1(gbt_enum_consistent); PG_FUNCTION_INFO_V1(gbt_enum_penalty); PG_FUNCTION_INFO_V1(gbt_enum_same); +PG_FUNCTION_INFO_V1(gbt_enum_sortsupport); static bool @@ -99,10 +100,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * Enum ops + * GiST support functions **************************************************/ - Datum gbt_enum_compress(PG_FUNCTION_ARGS) { @@ -137,7 +137,7 @@ gbt_enum_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -149,10 +149,9 @@ gbt_enum_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(oidKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_enum_penalty(PG_FUNCTION_ARGS) { @@ -183,3 +182,39 @@ gbt_enum_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_enum_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + oidKEY *arg1 = (oidKEY *) DatumGetPointer(x); + oidKEY *arg2 = (oidKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(CallerFInfoFunctionCall2(enum_cmp, + ssup->ssup_extra, + InvalidOid, + arg1->lower, + arg2->lower)); +} + +Datum +gbt_enum_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + FmgrInfo *flinfo; + + ssup->comparator = gbt_enum_ssup_cmp; + + /* + * Since gbt_enum_ssup_cmp() uses enum_cmp() like the rest of the + * comparison functions, it also needs to pass flinfo when calling it. The + * caller to a SortSupport comparison function doesn't provide an FmgrInfo + * struct, so look it up now, save it in ssup_extra and use it in + * gbt_enum_ssup_cmp() later. + */ + flinfo = MemoryContextAlloc(ssup->ssup_cxt, sizeof(FmgrInfo)); + fmgr_info_cxt(F_ENUM_CMP, flinfo, ssup->ssup_cxt); + ssup->ssup_extra = flinfo; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c index 84ca5eee5012c..bec026a923a18 100644 --- a/contrib/btree_gist/btree_float4.c +++ b/contrib/btree_gist/btree_float4.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "utils/float.h" +#include "utils/sortsupport.h" typedef struct float4key { @@ -13,9 +14,7 @@ typedef struct float4key float4 upper; } float4KEY; -/* -** float4 ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_float4_compress); PG_FUNCTION_INFO_V1(gbt_float4_fetch); PG_FUNCTION_INFO_V1(gbt_float4_union); @@ -24,6 +23,7 @@ PG_FUNCTION_INFO_V1(gbt_float4_consistent); PG_FUNCTION_INFO_V1(gbt_float4_distance); PG_FUNCTION_INFO_V1(gbt_float4_penalty); PG_FUNCTION_INFO_V1(gbt_float4_same); +PG_FUNCTION_INFO_V1(gbt_float4_sortsupport); static bool gbt_float4gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -107,10 +107,9 @@ float4_dist(PG_FUNCTION_ARGS) /************************************************** - * float4 ops + * GiST support functions **************************************************/ - Datum gbt_float4_compress(PG_FUNCTION_ARGS) { @@ -145,12 +144,11 @@ gbt_float4_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_float4_distance(PG_FUNCTION_ARGS) { @@ -164,11 +162,10 @@ gbt_float4_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_float4_union(PG_FUNCTION_ARGS) { @@ -176,10 +173,9 @@ gbt_float4_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(float4KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_float4_penalty(PG_FUNCTION_ARGS) { @@ -210,3 +206,24 @@ gbt_float4_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_float4_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + float4KEY *arg1 = (float4KEY *) DatumGetPointer(x); + float4KEY *arg2 = (float4KEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return float4_cmp_internal(arg1->lower, arg2->lower); +} + +Datum +gbt_float4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_float4_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c index 081a719b0061c..43e7cde2b6958 100644 --- a/contrib/btree_gist/btree_float8.c +++ b/contrib/btree_gist/btree_float8.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "utils/float.h" +#include "utils/sortsupport.h" typedef struct float8key { @@ -13,9 +14,7 @@ typedef struct float8key float8 upper; } float8KEY; -/* -** float8 ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_float8_compress); PG_FUNCTION_INFO_V1(gbt_float8_fetch); PG_FUNCTION_INFO_V1(gbt_float8_union); @@ -24,6 +23,7 @@ PG_FUNCTION_INFO_V1(gbt_float8_consistent); PG_FUNCTION_INFO_V1(gbt_float8_distance); PG_FUNCTION_INFO_V1(gbt_float8_penalty); PG_FUNCTION_INFO_V1(gbt_float8_same); +PG_FUNCTION_INFO_V1(gbt_float8_sortsupport); static bool @@ -113,11 +113,11 @@ float8_dist(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(fabs(r)); } + /************************************************** - * float8 ops + * GiST support functions **************************************************/ - Datum gbt_float8_compress(PG_FUNCTION_ARGS) { @@ -152,12 +152,11 @@ gbt_float8_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_float8_distance(PG_FUNCTION_ARGS) { @@ -171,11 +170,10 @@ gbt_float8_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_float8_union(PG_FUNCTION_ARGS) { @@ -183,10 +181,9 @@ gbt_float8_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(float8KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_float8_penalty(PG_FUNCTION_ARGS) { @@ -217,3 +214,24 @@ gbt_float8_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_float8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + float8KEY *arg1 = (float8KEY *) DatumGetPointer(x); + float8KEY *arg2 = (float8KEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return float8_cmp_internal(arg1->lower, arg2->lower); +} + +Datum +gbt_float8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_float8_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_gist--1.7--1.8.sql b/contrib/btree_gist/btree_gist--1.7--1.8.sql new file mode 100644 index 0000000000000..8f79365a461f8 --- /dev/null +++ b/contrib/btree_gist/btree_gist--1.7--1.8.sql @@ -0,0 +1,87 @@ +/* contrib/btree_gist/btree_gist--1.7--1.8.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.8'" to load this file. \quit + +CREATE FUNCTION gist_translate_cmptype_btree(int) +RETURNS smallint +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_time_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_date_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_text_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_uuid_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; + +ALTER OPERATOR FAMILY gist_bool_ops USING gist ADD + FUNCTION 12 ("any", "any") gist_translate_cmptype_btree (int) ; diff --git a/contrib/btree_gist/btree_gist--1.8--1.9.sql b/contrib/btree_gist/btree_gist--1.8--1.9.sql new file mode 100644 index 0000000000000..4b38749bf5f34 --- /dev/null +++ b/contrib/btree_gist/btree_gist--1.8--1.9.sql @@ -0,0 +1,197 @@ +/* contrib/btree_gist/btree_gist--1.7--1.8.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION btree_gist UPDATE TO '1.9'" to load this file. \quit + +CREATE FUNCTION gbt_bit_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_varbit_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_bool_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_bytea_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_cash_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_date_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_enum_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_float4_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_float8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_inet_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_int2_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_int4_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_int8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_intv_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_macaddr_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_macad8_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_numeric_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_oid_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_text_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_bpchar_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_time_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_ts_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +CREATE FUNCTION gbt_uuid_sortsupport(internal) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT; + +ALTER OPERATOR FAMILY gist_bit_ops USING gist ADD + FUNCTION 11 (bit, bit) gbt_bit_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_vbit_ops USING gist ADD + FUNCTION 11 (varbit, varbit) gbt_varbit_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bool_ops USING gist ADD + FUNCTION 11 (bool, bool) gbt_bool_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bytea_ops USING gist ADD + FUNCTION 11 (bytea, bytea) gbt_bytea_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD + FUNCTION 11 (money, money) gbt_cash_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_date_ops USING gist ADD + FUNCTION 11 (date, date) gbt_date_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD + FUNCTION 11 (anyenum, anyenum) gbt_enum_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD + FUNCTION 11 (float4, float4) gbt_float4_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD + FUNCTION 11 (float8, float8) gbt_float8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_inet_ops USING gist ADD + FUNCTION 11 (inet, inet) gbt_inet_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_cidr_ops USING gist ADD + FUNCTION 11 (cidr, cidr) gbt_inet_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD + FUNCTION 11 (int2, int2) gbt_int2_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD + FUNCTION 11 (int4, int4) gbt_int4_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD + FUNCTION 11 (int8, int8) gbt_int8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD + FUNCTION 11 (interval, interval) gbt_intv_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD + FUNCTION 11 (macaddr, macaddr) gbt_macaddr_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD + FUNCTION 11 (macaddr8, macaddr8) gbt_macad8_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_numeric_ops USING gist ADD + FUNCTION 11 (numeric, numeric) gbt_numeric_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD + FUNCTION 11 (oid, oid) gbt_oid_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_text_ops USING gist ADD + FUNCTION 11 (text, text) gbt_text_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_bpchar_ops USING gist ADD + FUNCTION 11 (bpchar, bpchar) gbt_bpchar_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_time_ops USING gist ADD + FUNCTION 11 (time, time) gbt_time_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD + FUNCTION 11 (timetz, timetz) gbt_time_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD + FUNCTION 11 (timestamp, timestamp) gbt_ts_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD + FUNCTION 11 (timestamptz, timestamptz) gbt_ts_sortsupport (internal) ; + +ALTER OPERATOR FAMILY gist_uuid_ops USING gist ADD + FUNCTION 11 (uuid, uuid) gbt_uuid_sortsupport (internal) ; diff --git a/contrib/btree_gist/btree_gist.c b/contrib/btree_gist/btree_gist.c index 92520aedae1c0..39fcbdad334f0 100644 --- a/contrib/btree_gist/btree_gist.c +++ b/contrib/btree_gist/btree_gist.c @@ -3,13 +3,19 @@ */ #include "postgres.h" +#include "access/cmptype.h" +#include "access/stratnum.h" #include "utils/builtins.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "btree_gist", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(gbt_decompress); PG_FUNCTION_INFO_V1(gbtreekey_in); PG_FUNCTION_INFO_V1(gbtreekey_out); +PG_FUNCTION_INFO_V1(gist_translate_cmptype_btree); /************************************************** * In/Out for keys @@ -51,3 +57,28 @@ gbt_decompress(PG_FUNCTION_ARGS) { PG_RETURN_POINTER(PG_GETARG_POINTER(0)); } + +/* + * Returns the btree number for supported operators, otherwise invalid. + */ +Datum +gist_translate_cmptype_btree(PG_FUNCTION_ARGS) +{ + CompareType cmptype = PG_GETARG_INT32(0); + + switch (cmptype) + { + case COMPARE_EQ: + PG_RETURN_UINT16(BTEqualStrategyNumber); + case COMPARE_LT: + PG_RETURN_UINT16(BTLessStrategyNumber); + case COMPARE_LE: + PG_RETURN_UINT16(BTLessEqualStrategyNumber); + case COMPARE_GT: + PG_RETURN_UINT16(BTGreaterStrategyNumber); + case COMPARE_GE: + PG_RETURN_UINT16(BTGreaterEqualStrategyNumber); + default: + PG_RETURN_UINT16(InvalidStrategy); + } +} diff --git a/contrib/btree_gist/btree_gist.control b/contrib/btree_gist/btree_gist.control index fa9171a80a2e3..69d9341a0adea 100644 --- a/contrib/btree_gist/btree_gist.control +++ b/contrib/btree_gist/btree_gist.control @@ -1,6 +1,6 @@ # btree_gist extension comment = 'support for indexing common datatypes in GiST' -default_version = '1.7' +default_version = '1.9' module_pathname = '$libdir/btree_gist' relocatable = true trusted = true diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c index 2fb952dca83fb..8b23853bafbb7 100644 --- a/contrib/btree_gist/btree_inet.c +++ b/contrib/btree_gist/btree_inet.c @@ -7,7 +7,7 @@ #include "btree_utils_num.h" #include "catalog/pg_type.h" #include "utils/builtins.h" -#include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct inetkey { @@ -15,15 +15,14 @@ typedef struct inetkey double upper; } inetKEY; -/* -** inet ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_inet_compress); PG_FUNCTION_INFO_V1(gbt_inet_union); PG_FUNCTION_INFO_V1(gbt_inet_picksplit); PG_FUNCTION_INFO_V1(gbt_inet_consistent); PG_FUNCTION_INFO_V1(gbt_inet_penalty); PG_FUNCTION_INFO_V1(gbt_inet_same); +PG_FUNCTION_INFO_V1(gbt_inet_sortsupport); static bool @@ -86,10 +85,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * inet ops + * GiST support functions **************************************************/ - Datum gbt_inet_compress(PG_FUNCTION_ARGS) { @@ -115,7 +113,6 @@ gbt_inet_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(retval); } - Datum gbt_inet_consistent(PG_FUNCTION_ARGS) { @@ -139,11 +136,10 @@ gbt_inet_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_inet_union(PG_FUNCTION_ARGS) { @@ -151,10 +147,9 @@ gbt_inet_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(inetKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_inet_penalty(PG_FUNCTION_ARGS) { @@ -185,3 +180,29 @@ gbt_inet_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_inet_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + inetKEY *arg1 = (inetKEY *) DatumGetPointer(x); + inetKEY *arg2 = (inetKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (arg1->lower < arg2->lower) + return -1; + else if (arg1->lower > arg2->lower) + return 1; + else + return 0; +} + +Datum +gbt_inet_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_inet_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c index fdbf156586c93..33eccdedd7049 100644 --- a/contrib/btree_gist/btree_int2.c +++ b/contrib/btree_gist/btree_int2.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "common/int.h" +#include "utils/sortsupport.h" typedef struct int16key { @@ -13,9 +14,7 @@ typedef struct int16key int16 upper; } int16KEY; -/* -** int16 ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_int2_compress); PG_FUNCTION_INFO_V1(gbt_int2_fetch); PG_FUNCTION_INFO_V1(gbt_int2_union); @@ -24,6 +23,8 @@ PG_FUNCTION_INFO_V1(gbt_int2_consistent); PG_FUNCTION_INFO_V1(gbt_int2_distance); PG_FUNCTION_INFO_V1(gbt_int2_penalty); PG_FUNCTION_INFO_V1(gbt_int2_same); +PG_FUNCTION_INFO_V1(gbt_int2_sortsupport); + static bool gbt_int2gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -112,10 +113,9 @@ int2_dist(PG_FUNCTION_ARGS) /************************************************** - * int16 ops + * GiST support functions **************************************************/ - Datum gbt_int2_compress(PG_FUNCTION_ARGS) { @@ -150,11 +150,10 @@ gbt_int2_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int2_distance(PG_FUNCTION_ARGS) { @@ -168,11 +167,10 @@ gbt_int2_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int2_union(PG_FUNCTION_ARGS) { @@ -180,10 +178,9 @@ gbt_int2_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(int16KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_int2_penalty(PG_FUNCTION_ARGS) { @@ -214,3 +211,27 @@ gbt_int2_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_int2_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + int16KEY *arg1 = (int16KEY *) DatumGetPointer(x); + int16KEY *arg2 = (int16KEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (arg1->lower < arg2->lower) + return -1; + else if (arg1->lower > arg2->lower) + return 1; + else + return 0; +} + +Datum +gbt_int2_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int2_ssup_cmp; + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c index 8915fb5d08772..a82cee9a58a8c 100644 --- a/contrib/btree_gist/btree_int4.c +++ b/contrib/btree_gist/btree_int4.c @@ -2,10 +2,10 @@ * contrib/btree_gist/btree_int4.c */ #include "postgres.h" - #include "btree_gist.h" #include "btree_utils_num.h" #include "common/int.h" +#include "utils/sortsupport.h" typedef struct int32key { @@ -13,9 +13,7 @@ typedef struct int32key int32 upper; } int32KEY; -/* -** int32 ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_int4_compress); PG_FUNCTION_INFO_V1(gbt_int4_fetch); PG_FUNCTION_INFO_V1(gbt_int4_union); @@ -24,7 +22,7 @@ PG_FUNCTION_INFO_V1(gbt_int4_consistent); PG_FUNCTION_INFO_V1(gbt_int4_distance); PG_FUNCTION_INFO_V1(gbt_int4_penalty); PG_FUNCTION_INFO_V1(gbt_int4_same); - +PG_FUNCTION_INFO_V1(gbt_int4_sortsupport); static bool gbt_int4gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -113,10 +111,9 @@ int4_dist(PG_FUNCTION_ARGS) /************************************************** - * int32 ops + * GiST support functions **************************************************/ - Datum gbt_int4_compress(PG_FUNCTION_ARGS) { @@ -151,11 +148,10 @@ gbt_int4_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int4_distance(PG_FUNCTION_ARGS) { @@ -169,11 +165,10 @@ gbt_int4_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int4_union(PG_FUNCTION_ARGS) { @@ -181,10 +176,9 @@ gbt_int4_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(int32KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_int4_penalty(PG_FUNCTION_ARGS) { @@ -215,3 +209,27 @@ gbt_int4_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_int4_ssup_cmp(Datum a, Datum b, SortSupport ssup) +{ + int32KEY *ia = (int32KEY *) DatumGetPointer(a); + int32KEY *ib = (int32KEY *) DatumGetPointer(b); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (ia->lower < ib->lower) + return -1; + else if (ia->lower > ib->lower) + return 1; + else + return 0; +} + +Datum +gbt_int4_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int4_ssup_cmp; + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c index 7c63a5b6dc1f8..f0c56e017269a 100644 --- a/contrib/btree_gist/btree_int8.c +++ b/contrib/btree_gist/btree_int8.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "common/int.h" +#include "utils/sortsupport.h" typedef struct int64key { @@ -13,9 +14,7 @@ typedef struct int64key int64 upper; } int64KEY; -/* -** int64 ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_int8_compress); PG_FUNCTION_INFO_V1(gbt_int8_fetch); PG_FUNCTION_INFO_V1(gbt_int8_union); @@ -24,6 +23,7 @@ PG_FUNCTION_INFO_V1(gbt_int8_consistent); PG_FUNCTION_INFO_V1(gbt_int8_distance); PG_FUNCTION_INFO_V1(gbt_int8_penalty); PG_FUNCTION_INFO_V1(gbt_int8_same); +PG_FUNCTION_INFO_V1(gbt_int8_sortsupport); static bool @@ -113,10 +113,9 @@ int8_dist(PG_FUNCTION_ARGS) /************************************************** - * int64 ops + * GiST support functions **************************************************/ - Datum gbt_int8_compress(PG_FUNCTION_ARGS) { @@ -151,11 +150,10 @@ gbt_int8_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int8_distance(PG_FUNCTION_ARGS) { @@ -169,11 +167,10 @@ gbt_int8_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_int8_union(PG_FUNCTION_ARGS) { @@ -181,10 +178,9 @@ gbt_int8_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(int64KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_int8_penalty(PG_FUNCTION_ARGS) { @@ -215,3 +211,28 @@ gbt_int8_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_int8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + int64KEY *arg1 = (int64KEY *) DatumGetPointer(x); + int64KEY *arg2 = (int64KEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (arg1->lower < arg2->lower) + return -1; + else if (arg1->lower > arg2->lower) + return 1; + else + return 0; + +} + +Datum +gbt_int8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_int8_ssup_cmp; + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c index b0afdf02bb554..b5e365c6e09b4 100644 --- a/contrib/btree_gist/btree_interval.c +++ b/contrib/btree_gist/btree_interval.c @@ -5,7 +5,8 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" +#include "utils/sortsupport.h" #include "utils/timestamp.h" typedef struct @@ -14,10 +15,7 @@ typedef struct upper; } intvKEY; - -/* -** Interval ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_intv_compress); PG_FUNCTION_INFO_V1(gbt_intv_fetch); PG_FUNCTION_INFO_V1(gbt_intv_decompress); @@ -27,6 +25,7 @@ PG_FUNCTION_INFO_V1(gbt_intv_consistent); PG_FUNCTION_INFO_V1(gbt_intv_distance); PG_FUNCTION_INFO_V1(gbt_intv_penalty); PG_FUNCTION_INFO_V1(gbt_intv_same); +PG_FUNCTION_INFO_V1(gbt_intv_sortsupport); static bool @@ -113,7 +112,7 @@ static const gbtree_ninfo tinfo = Interval * abs_interval(Interval *a) { - static Interval zero = {0, 0, 0}; + static const Interval zero = {0, 0, 0}; if (DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), @@ -137,10 +136,9 @@ interval_dist(PG_FUNCTION_ARGS) /************************************************** - * interval ops + * GiST support functions **************************************************/ - Datum gbt_intv_compress(PG_FUNCTION_ARGS) { @@ -224,7 +222,7 @@ gbt_intv_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -242,7 +240,7 @@ gbt_intv_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -254,7 +252,7 @@ gbt_intv_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(intvKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } @@ -295,3 +293,26 @@ gbt_intv_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_intv_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + intvKEY *arg1 = (intvKEY *) DatumGetPointer(x); + intvKEY *arg2 = (intvKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(interval_cmp, + IntervalPGetDatum(&arg1->lower), + IntervalPGetDatum(&arg2->lower))); +} + +Datum +gbt_intv_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_intv_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c index 17290529c02fb..3b2f26719d5dc 100644 --- a/contrib/btree_gist/btree_macaddr.c +++ b/contrib/btree_gist/btree_macaddr.c @@ -5,8 +5,9 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct { @@ -15,9 +16,7 @@ typedef struct char pad[4]; /* make struct size = sizeof(gbtreekey16) */ } macKEY; -/* -** OID ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_macad_compress); PG_FUNCTION_INFO_V1(gbt_macad_fetch); PG_FUNCTION_INFO_V1(gbt_macad_union); @@ -25,6 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_macad_picksplit); PG_FUNCTION_INFO_V1(gbt_macad_consistent); PG_FUNCTION_INFO_V1(gbt_macad_penalty); PG_FUNCTION_INFO_V1(gbt_macad_same); +PG_FUNCTION_INFO_V1(gbt_macaddr_sortsupport); static bool @@ -88,11 +88,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * macaddr ops + * GiST support functions **************************************************/ - - static uint64 mac_2_uint64(macaddr *m) { @@ -105,8 +103,6 @@ mac_2_uint64(macaddr *m) return res; } - - Datum gbt_macad_compress(PG_FUNCTION_ARGS) { @@ -141,7 +137,7 @@ gbt_macad_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -153,7 +149,7 @@ gbt_macad_union(PG_FUNCTION_ARGS) void *out = palloc0(sizeof(macKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(macKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } @@ -194,3 +190,26 @@ gbt_macad_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_macaddr_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + macKEY *arg1 = (macKEY *) DatumGetPointer(x); + macKEY *arg2 = (macKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(macaddr_cmp, + MacaddrPGetDatum(&arg1->lower), + MacaddrPGetDatum(&arg2->lower))); +} + +Datum +gbt_macaddr_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_macaddr_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c index 796cc4efee323..f2b104617e680 100644 --- a/contrib/btree_gist/btree_macaddr8.c +++ b/contrib/btree_gist/btree_macaddr8.c @@ -5,8 +5,9 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/inet.h" +#include "utils/sortsupport.h" typedef struct { @@ -15,9 +16,7 @@ typedef struct /* make struct size = sizeof(gbtreekey16) */ } mac8KEY; -/* -** OID ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_macad8_compress); PG_FUNCTION_INFO_V1(gbt_macad8_fetch); PG_FUNCTION_INFO_V1(gbt_macad8_union); @@ -25,7 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_macad8_picksplit); PG_FUNCTION_INFO_V1(gbt_macad8_consistent); PG_FUNCTION_INFO_V1(gbt_macad8_penalty); PG_FUNCTION_INFO_V1(gbt_macad8_same); - +PG_FUNCTION_INFO_V1(gbt_macad8_sortsupport); static bool gbt_macad8gt(const void *a, const void *b, FmgrInfo *flinfo) @@ -88,11 +87,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * macaddr ops + * GiST support functions **************************************************/ - - static uint64 mac8_2_uint64(macaddr8 *m) { @@ -105,8 +102,6 @@ mac8_2_uint64(macaddr8 *m) return res; } - - Datum gbt_macad8_compress(PG_FUNCTION_ARGS) { @@ -141,11 +136,10 @@ gbt_macad8_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_macad8_union(PG_FUNCTION_ARGS) { @@ -153,10 +147,9 @@ gbt_macad8_union(PG_FUNCTION_ARGS) void *out = palloc0(sizeof(mac8KEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(mac8KEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_macad8_penalty(PG_FUNCTION_ARGS) { @@ -194,3 +187,26 @@ gbt_macad8_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_macaddr8_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + mac8KEY *arg1 = (mac8KEY *) DatumGetPointer(x); + mac8KEY *arg2 = (mac8KEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(macaddr8_cmp, + Macaddr8PGetDatum(&arg1->lower), + Macaddr8PGetDatum(&arg2->lower))); +} + +Datum +gbt_macad8_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_macaddr8_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c index 35e466cdd9423..a39c05d9da1cf 100644 --- a/contrib/btree_gist/btree_numeric.c +++ b/contrib/btree_gist/btree_numeric.c @@ -11,16 +11,16 @@ #include "utils/builtins.h" #include "utils/numeric.h" #include "utils/rel.h" +#include "utils/sortsupport.h" -/* -** Bytea ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_numeric_compress); PG_FUNCTION_INFO_V1(gbt_numeric_union); PG_FUNCTION_INFO_V1(gbt_numeric_picksplit); PG_FUNCTION_INFO_V1(gbt_numeric_consistent); PG_FUNCTION_INFO_V1(gbt_numeric_penalty); PG_FUNCTION_INFO_V1(gbt_numeric_same); +PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport); /* define for comparison */ @@ -90,10 +90,9 @@ static const gbtree_vinfo tinfo = /************************************************** - * Text ops + * GiST support functions **************************************************/ - Datum gbt_numeric_compress(PG_FUNCTION_ARGS) { @@ -102,13 +101,11 @@ gbt_numeric_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo)); } - - Datum gbt_numeric_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) DatumGetNumeric(PG_GETARG_DATUM(1)); + void *query = DatumGetNumeric(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ @@ -125,8 +122,6 @@ gbt_numeric_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } - - Datum gbt_numeric_union(PG_FUNCTION_ARGS) { @@ -137,7 +132,6 @@ gbt_numeric_union(PG_FUNCTION_ARGS) &tinfo, fcinfo->flinfo)); } - Datum gbt_numeric_same(PG_FUNCTION_ARGS) { @@ -149,7 +143,6 @@ gbt_numeric_same(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_numeric_penalty(PG_FUNCTION_ARGS) { @@ -215,8 +208,6 @@ gbt_numeric_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - - Datum gbt_numeric_picksplit(PG_FUNCTION_ARGS) { @@ -227,3 +218,35 @@ gbt_numeric_picksplit(PG_FUNCTION_ARGS) &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(v); } + +static int +gbt_numeric_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + /* for leaf items we expect lower == upper, so only compare lower */ + result = DirectFunctionCall2(numeric_cmp, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_numeric_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_numeric_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c index 3cc7d4245d42b..ffe0d7983e40f 100644 --- a/contrib/btree_gist/btree_oid.c +++ b/contrib/btree_gist/btree_oid.c @@ -5,6 +5,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/sortsupport.h" typedef struct { @@ -12,9 +13,7 @@ typedef struct Oid upper; } oidKEY; -/* -** OID ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_oid_compress); PG_FUNCTION_INFO_V1(gbt_oid_fetch); PG_FUNCTION_INFO_V1(gbt_oid_union); @@ -23,6 +22,7 @@ PG_FUNCTION_INFO_V1(gbt_oid_consistent); PG_FUNCTION_INFO_V1(gbt_oid_distance); PG_FUNCTION_INFO_V1(gbt_oid_penalty); PG_FUNCTION_INFO_V1(gbt_oid_same); +PG_FUNCTION_INFO_V1(gbt_oid_sortsupport); static bool @@ -113,10 +113,9 @@ oid_dist(PG_FUNCTION_ARGS) /************************************************** - * Oid ops + * GiST support functions **************************************************/ - Datum gbt_oid_compress(PG_FUNCTION_ARGS) { @@ -151,11 +150,10 @@ gbt_oid_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_oid_distance(PG_FUNCTION_ARGS) { @@ -169,11 +167,10 @@ gbt_oid_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_oid_union(PG_FUNCTION_ARGS) { @@ -181,10 +178,9 @@ gbt_oid_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(oidKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_oid_penalty(PG_FUNCTION_ARGS) { @@ -215,3 +211,29 @@ gbt_oid_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_oid_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + oidKEY *arg1 = (oidKEY *) DatumGetPointer(x); + oidKEY *arg2 = (oidKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + if (arg1->lower > arg2->lower) + return 1; + else if (arg1->lower < arg2->lower) + return -1; + else + return 0; +} + +Datum +gbt_oid_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_oid_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c index be0eac7975b46..ddee42504a192 100644 --- a/contrib/btree_gist/btree_text.c +++ b/contrib/btree_gist/btree_text.c @@ -5,11 +5,11 @@ #include "btree_gist.h" #include "btree_utils_var.h" -#include "utils/builtins.h" +#include "mb/pg_wchar.h" +#include "utils/fmgrprotos.h" +#include "utils/sortsupport.h" -/* -** Text ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_text_compress); PG_FUNCTION_INFO_V1(gbt_bpchar_compress); PG_FUNCTION_INFO_V1(gbt_text_union); @@ -18,6 +18,8 @@ PG_FUNCTION_INFO_V1(gbt_text_consistent); PG_FUNCTION_INFO_V1(gbt_bpchar_consistent); PG_FUNCTION_INFO_V1(gbt_text_penalty); PG_FUNCTION_INFO_V1(gbt_text_same); +PG_FUNCTION_INFO_V1(gbt_text_sortsupport); +PG_FUNCTION_INFO_V1(gbt_bpchar_sortsupport); /* define for comparison */ @@ -162,10 +164,9 @@ static gbtree_vinfo bptinfo = /************************************************** - * Text ops + * GiST support functions **************************************************/ - Datum gbt_text_compress(PG_FUNCTION_ARGS) { @@ -186,13 +187,11 @@ gbt_bpchar_compress(PG_FUNCTION_ARGS) return gbt_text_compress(fcinfo); } - - Datum gbt_text_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) DatumGetTextP(PG_GETARG_DATUM(1)); + void *query = DatumGetTextP(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ @@ -215,12 +214,11 @@ gbt_text_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } - Datum gbt_bpchar_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) DatumGetTextP(PG_GETARG_DATUM(1)); + void *query = DatumGetTextP(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ @@ -242,7 +240,6 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(retval); } - Datum gbt_text_union(PG_FUNCTION_ARGS) { @@ -253,7 +250,6 @@ gbt_text_union(PG_FUNCTION_ARGS) &tinfo, fcinfo->flinfo)); } - Datum gbt_text_picksplit(PG_FUNCTION_ARGS) { @@ -276,7 +272,6 @@ gbt_text_same(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_text_penalty(PG_FUNCTION_ARGS) { @@ -287,3 +282,69 @@ gbt_text_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo)); } + +static int +gbt_text_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + /* for leaf items we expect lower == upper, so only compare lower */ + result = DirectFunctionCall2Coll(bttextcmp, + ssup->ssup_collation, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_text_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_text_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} + +static int +gbt_bpchar_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + GBT_VARKEY *key1 = PG_DETOAST_DATUM(x); + GBT_VARKEY *key2 = PG_DETOAST_DATUM(y); + + GBT_VARKEY_R arg1 = gbt_var_key_readable(key1); + GBT_VARKEY_R arg2 = gbt_var_key_readable(key2); + Datum result; + + /* for leaf items we expect lower == upper, so only compare lower */ + result = DirectFunctionCall2Coll(bpcharcmp, + ssup->ssup_collation, + PointerGetDatum(arg1.lower), + PointerGetDatum(arg2.lower)); + + GBT_FREE_IF_COPY(key1, x); + GBT_FREE_IF_COPY(key2, y); + + return DatumGetInt32(result); +} + +Datum +gbt_bpchar_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_bpchar_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c index d89401c0f51e4..1dba95057ba9f 100644 --- a/contrib/btree_gist/btree_time.c +++ b/contrib/btree_gist/btree_time.c @@ -5,8 +5,9 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/date.h" +#include "utils/sortsupport.h" #include "utils/timestamp.h" typedef struct @@ -15,9 +16,7 @@ typedef struct TimeADT upper; } timeKEY; -/* -** time ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_time_compress); PG_FUNCTION_INFO_V1(gbt_timetz_compress); PG_FUNCTION_INFO_V1(gbt_time_fetch); @@ -28,6 +27,8 @@ PG_FUNCTION_INFO_V1(gbt_time_distance); PG_FUNCTION_INFO_V1(gbt_timetz_consistent); PG_FUNCTION_INFO_V1(gbt_time_penalty); PG_FUNCTION_INFO_V1(gbt_time_same); +PG_FUNCTION_INFO_V1(gbt_time_sortsupport); +PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport); #ifdef USE_FLOAT8_BYVAL @@ -92,8 +93,6 @@ gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo) TimeADTGetDatumFast(*bb))); } - - static int gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo) { @@ -150,11 +149,9 @@ time_dist(PG_FUNCTION_ARGS) /************************************************** - * time ops + * GiST support functions **************************************************/ - - Datum gbt_time_compress(PG_FUNCTION_ARGS) { @@ -163,7 +160,6 @@ gbt_time_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo)); } - Datum gbt_timetz_compress(PG_FUNCTION_ARGS) { @@ -216,7 +212,7 @@ gbt_time_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -233,7 +229,7 @@ gbt_time_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -258,11 +254,10 @@ gbt_timetz_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &qqq, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } - Datum gbt_time_union(PG_FUNCTION_ARGS) { @@ -270,10 +265,9 @@ gbt_time_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(timeKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } - Datum gbt_time_penalty(PG_FUNCTION_ARGS) { @@ -313,7 +307,6 @@ gbt_time_penalty(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } - Datum gbt_time_picksplit(PG_FUNCTION_ARGS) { @@ -332,3 +325,26 @@ gbt_time_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + timeKEY *arg1 = (timeKEY *) DatumGetPointer(x); + timeKEY *arg2 = (timeKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(time_cmp, + TimeADTGetDatumFast(arg1->lower), + TimeADTGetDatumFast(arg2->lower))); +} + +Datum +gbt_time_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_timekey_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c index 3f5ba91891d80..eb899c4d21363 100644 --- a/contrib/btree_gist/btree_ts.c +++ b/contrib/btree_gist/btree_ts.c @@ -7,9 +7,10 @@ #include "btree_gist.h" #include "btree_utils_num.h" -#include "utils/builtins.h" -#include "utils/datetime.h" +#include "utils/fmgrprotos.h" +#include "utils/timestamp.h" #include "utils/float.h" +#include "utils/sortsupport.h" typedef struct { @@ -17,9 +18,7 @@ typedef struct Timestamp upper; } tsKEY; -/* -** timestamp ops -*/ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_ts_compress); PG_FUNCTION_INFO_V1(gbt_tstz_compress); PG_FUNCTION_INFO_V1(gbt_ts_fetch); @@ -31,6 +30,7 @@ PG_FUNCTION_INFO_V1(gbt_tstz_consistent); PG_FUNCTION_INFO_V1(gbt_tstz_distance); PG_FUNCTION_INFO_V1(gbt_ts_penalty); PG_FUNCTION_INFO_V1(gbt_ts_same); +PG_FUNCTION_INFO_V1(gbt_ts_sortsupport); #ifdef USE_FLOAT8_BYVAL @@ -40,6 +40,8 @@ PG_FUNCTION_INFO_V1(gbt_ts_same); #endif +/* define for comparison */ + static bool gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo) { @@ -95,7 +97,6 @@ gbt_tslt(const void *a, const void *b, FmgrInfo *flinfo) TimestampGetDatumFast(*bb))); } - static int gbt_tskey_cmp(const void *a, const void *b, FmgrInfo *flinfo) { @@ -126,7 +127,6 @@ gbt_ts_dist(const void *a, const void *b, FmgrInfo *flinfo) return fabs(INTERVAL_TO_SEC(i)); } - static const gbtree_ninfo tinfo = { gbt_t_ts, @@ -190,12 +190,10 @@ tstz_dist(PG_FUNCTION_ARGS) PG_RETURN_INTERVAL_P(abs_interval(r)); } - /************************************************** - * timestamp ops + * GiST support functions **************************************************/ - static inline Timestamp tstz_to_ts_gmt(TimestampTz ts) { @@ -212,7 +210,6 @@ gbt_ts_compress(PG_FUNCTION_ARGS) PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo)); } - Datum gbt_tstz_compress(PG_FUNCTION_ARGS) { @@ -265,7 +262,7 @@ gbt_ts_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -282,7 +279,7 @@ gbt_ts_distance(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -306,7 +303,7 @@ gbt_tstz_consistent(PG_FUNCTION_ARGS) key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)]; qqq = tstz_to_ts_gmt(query); - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &qqq, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -325,7 +322,7 @@ gbt_tstz_distance(PG_FUNCTION_ARGS) key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)]; qqq = tstz_to_ts_gmt(query); - PG_RETURN_FLOAT8(gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), + PG_RETURN_FLOAT8(gbt_num_distance(&key, &qqq, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -337,7 +334,7 @@ gbt_ts_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(tsKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } @@ -398,3 +395,26 @@ gbt_ts_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + tsKEY *arg1 = (tsKEY *) DatumGetPointer(x); + tsKEY *arg2 = (tsKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, + TimestampGetDatumFast(arg1->lower), + TimestampGetDatumFast(arg2->lower))); +} + +Datum +gbt_ts_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_ts_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h index 11e892311eeb3..53e477d8b1e20 100644 --- a/contrib/btree_gist/btree_utils_num.h +++ b/contrib/btree_gist/btree_utils_num.h @@ -9,7 +9,6 @@ #include "access/gist.h" #include "btree_gist.h" -#include "utils/rel.h" typedef char GBT_NUMKEY; diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c index 0c0e952f73621..d9df2356cd1e4 100644 --- a/contrib/btree_gist/btree_utils_var.c +++ b/contrib/btree_gist/btree_utils_var.c @@ -9,8 +9,7 @@ #include "btree_gist.h" #include "btree_utils_var.h" -#include "utils/builtins.h" -#include "utils/pg_locale.h" +#include "mb/pg_wchar.h" #include "utils/rel.h" /* used for key sorting */ diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h index 2f8def655c8d6..75ad33d24fcd1 100644 --- a/contrib/btree_gist/btree_utils_var.h +++ b/contrib/btree_gist/btree_utils_var.h @@ -6,7 +6,6 @@ #include "access/gist.h" #include "btree_gist.h" -#include "mb/pg_wchar.h" /* Variable length key */ typedef bytea GBT_VARKEY; @@ -42,7 +41,17 @@ typedef struct GBT_VARKEY *(*f_l2n) (GBT_VARKEY *, FmgrInfo *flinfo); /* convert leaf to node */ } gbtree_vinfo; - +/* + * Free ptr1 in case its a copy of ptr2. + * + * This is adapted from varlena's PG_FREE_IF_COPY, though doesn't require + * fcinfo access. + */ +#define GBT_FREE_IF_COPY(ptr1, ptr2) \ + do { \ + if ((Pointer) (ptr1) != DatumGetPointer(ptr2)) \ + pfree(ptr1); \ + } while (0) extern GBT_VARKEY_R gbt_var_key_readable(const GBT_VARKEY *k); diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c index fe8c679cbed63..23a307a6a71d5 100644 --- a/contrib/btree_gist/btree_uuid.c +++ b/contrib/btree_gist/btree_uuid.c @@ -6,6 +6,7 @@ #include "btree_gist.h" #include "btree_utils_num.h" #include "port/pg_bswap.h" +#include "utils/sortsupport.h" #include "utils/uuid.h" typedef struct @@ -15,9 +16,7 @@ typedef struct } uuidKEY; -/* - * UUID ops - */ +/* GiST support functions */ PG_FUNCTION_INFO_V1(gbt_uuid_compress); PG_FUNCTION_INFO_V1(gbt_uuid_fetch); PG_FUNCTION_INFO_V1(gbt_uuid_union); @@ -25,6 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_uuid_picksplit); PG_FUNCTION_INFO_V1(gbt_uuid_consistent); PG_FUNCTION_INFO_V1(gbt_uuid_penalty); PG_FUNCTION_INFO_V1(gbt_uuid_same); +PG_FUNCTION_INFO_V1(gbt_uuid_sortsupport); static int @@ -93,10 +93,9 @@ static const gbtree_ninfo tinfo = /************************************************** - * uuid ops + * GiST support functions **************************************************/ - Datum gbt_uuid_compress(PG_FUNCTION_ARGS) { @@ -148,7 +147,7 @@ gbt_uuid_consistent(PG_FUNCTION_ARGS) key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; - PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) query, &strategy, + PG_RETURN_BOOL(gbt_num_consistent(&key, query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)); } @@ -160,7 +159,7 @@ gbt_uuid_union(PG_FUNCTION_ARGS) void *out = palloc(sizeof(uuidKEY)); *(int *) PG_GETARG_POINTER(1) = sizeof(uuidKEY); - PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo)); + PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo)); } /* @@ -233,3 +232,24 @@ gbt_uuid_same(PG_FUNCTION_ARGS) *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo); PG_RETURN_POINTER(result); } + +static int +gbt_uuid_ssup_cmp(Datum x, Datum y, SortSupport ssup) +{ + uuidKEY *arg1 = (uuidKEY *) DatumGetPointer(x); + uuidKEY *arg2 = (uuidKEY *) DatumGetPointer(y); + + /* for leaf items we expect lower == upper, so only compare lower */ + return uuid_internal_cmp(&arg1->lower, &arg2->lower); +} + +Datum +gbt_uuid_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = gbt_uuid_ssup_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} diff --git a/contrib/btree_gist/expected/enum.out b/contrib/btree_gist/expected/enum.out index c4b769dd4b77c..5782f43883859 100644 --- a/contrib/btree_gist/expected/enum.out +++ b/contrib/btree_gist/expected/enum.out @@ -1,5 +1,8 @@ -- enum check -create type rainbow as enum ('r','o','y','g','b','i','v'); +create type rainbow as enum ('r','o','g','b','i','v'); +-- enum values added later take some different codepaths internally, +-- so make sure we have coverage for those too +alter type rainbow add value 'y' before 'g'; CREATE TABLE enumtmp (a rainbow); \copy enumtmp from 'data/enum.data' SET enable_seqscan=on; diff --git a/contrib/btree_gist/expected/stratnum.out b/contrib/btree_gist/expected/stratnum.out new file mode 100644 index 0000000000000..8222b66153833 --- /dev/null +++ b/contrib/btree_gist/expected/stratnum.out @@ -0,0 +1,13 @@ +-- test stratnum translation support func +SELECT gist_translate_cmptype_btree(7); + gist_translate_cmptype_btree +------------------------------ + 0 +(1 row) + +SELECT gist_translate_cmptype_btree(3); + gist_translate_cmptype_btree +------------------------------ + 3 +(1 row) + diff --git a/contrib/btree_gist/expected/without_overlaps.out b/contrib/btree_gist/expected/without_overlaps.out new file mode 100644 index 0000000000000..18856900ded3a --- /dev/null +++ b/contrib/btree_gist/expected/without_overlaps.out @@ -0,0 +1,92 @@ +-- Core must test WITHOUT OVERLAPS +-- with an int4range + daterange, +-- so here we do some simple tests +-- to make sure int + daterange works too, +-- since that is the expected use-case. +CREATE TABLE temporal_rng ( + id integer, + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng + Table "public.temporal_rng" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | integer | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + pg_get_constraintdef +--------------------------------------------- + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + pg_get_indexdef +------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_rng_pk ON temporal_rng USING gist (id, valid_at) +(1 row) + +INSERT INTO temporal_rng VALUES + (1, '[2000-01-01,2001-01-01)'); +-- same key, doesn't overlap: +INSERT INTO temporal_rng VALUES + (1, '[2001-01-01,2002-01-01)'); +-- overlaps but different key: +INSERT INTO temporal_rng VALUES + (2, '[2000-01-01,2001-01-01)'); +-- should fail: +INSERT INTO temporal_rng VALUES + (1, '[2000-06-01,2001-01-01)'); +ERROR: conflicting key value violates exclusion constraint "temporal_rng_pk" +DETAIL: Key (id, valid_at)=(1, [06-01-2000,01-01-2001)) conflicts with existing key (id, valid_at)=(1, [01-01-2000,01-01-2001)). +-- Foreign key +CREATE TABLE temporal_fk_rng2rng ( + id integer, + valid_at daterange, + parent_id integer, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +\d temporal_fk_rng2rng + Table "public.temporal_fk_rng2rng" + Column | Type | Collation | Nullable | Default +-----------+-----------+-----------+----------+--------- + id | integer | | not null | + valid_at | daterange | | not null | + parent_id | integer | | | +Indexes: + "temporal_fk_rng2rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Foreign-key constraints: + "temporal_fk_rng2rng_fk" FOREIGN KEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng(id, PERIOD valid_at) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_rng2rng_fk'; + pg_get_constraintdef +--------------------------------------------------------------------------------------- + FOREIGN KEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng(id, PERIOD valid_at) +(1 row) + +-- okay +INSERT INTO temporal_fk_rng2rng VALUES + (1, '[2000-01-01,2001-01-01)', 1); +-- okay spanning two parent records: +INSERT INTO temporal_fk_rng2rng VALUES + (2, '[2000-01-01,2002-01-01)', 1); +-- key is missing +INSERT INTO temporal_fk_rng2rng VALUES + (3, '[2000-01-01,2001-01-01)', 3); +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=(3, [01-01-2000,01-01-2001)) is not present in table "temporal_rng". +-- key exist but is outside range +INSERT INTO temporal_fk_rng2rng VALUES + (4, '[2001-01-01,2002-01-01)', 2); +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=(2, [01-01-2001,01-01-2002)) is not present in table "temporal_rng". +-- key exist but is partly outside range +INSERT INTO temporal_fk_rng2rng VALUES + (5, '[2000-01-01,2002-01-01)', 2); +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=(2, [01-01-2000,01-01-2002)) is not present in table "temporal_rng". diff --git a/contrib/btree_gist/meson.build b/contrib/btree_gist/meson.build index c88a6ac84aeff..89932dd3844ee 100644 --- a/contrib/btree_gist/meson.build +++ b/contrib/btree_gist/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group btree_gist_sources = files( 'btree_bit.c', @@ -50,6 +50,8 @@ install_data( 'btree_gist--1.4--1.5.sql', 'btree_gist--1.5--1.6.sql', 'btree_gist--1.6--1.7.sql', + 'btree_gist--1.7--1.8.sql', + 'btree_gist--1.8--1.9.sql', kwargs: contrib_data_args, ) @@ -89,6 +91,8 @@ tests += { 'enum', 'bool', 'partitions', + 'stratnum', + 'without_overlaps', ], }, } diff --git a/contrib/btree_gist/sql/enum.sql b/contrib/btree_gist/sql/enum.sql index 476211e97952c..d662cb6322102 100644 --- a/contrib/btree_gist/sql/enum.sql +++ b/contrib/btree_gist/sql/enum.sql @@ -1,6 +1,10 @@ -- enum check -create type rainbow as enum ('r','o','y','g','b','i','v'); +create type rainbow as enum ('r','o','g','b','i','v'); + +-- enum values added later take some different codepaths internally, +-- so make sure we have coverage for those too +alter type rainbow add value 'y' before 'g'; CREATE TABLE enumtmp (a rainbow); diff --git a/contrib/btree_gist/sql/stratnum.sql b/contrib/btree_gist/sql/stratnum.sql new file mode 100644 index 0000000000000..da8bbf883b0cc --- /dev/null +++ b/contrib/btree_gist/sql/stratnum.sql @@ -0,0 +1,3 @@ +-- test stratnum translation support func +SELECT gist_translate_cmptype_btree(7); +SELECT gist_translate_cmptype_btree(3); diff --git a/contrib/btree_gist/sql/without_overlaps.sql b/contrib/btree_gist/sql/without_overlaps.sql new file mode 100644 index 0000000000000..b1b581fcabc2b --- /dev/null +++ b/contrib/btree_gist/sql/without_overlaps.sql @@ -0,0 +1,53 @@ +-- Core must test WITHOUT OVERLAPS +-- with an int4range + daterange, +-- so here we do some simple tests +-- to make sure int + daterange works too, +-- since that is the expected use-case. +CREATE TABLE temporal_rng ( + id integer, + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + +INSERT INTO temporal_rng VALUES + (1, '[2000-01-01,2001-01-01)'); +-- same key, doesn't overlap: +INSERT INTO temporal_rng VALUES + (1, '[2001-01-01,2002-01-01)'); +-- overlaps but different key: +INSERT INTO temporal_rng VALUES + (2, '[2000-01-01,2001-01-01)'); +-- should fail: +INSERT INTO temporal_rng VALUES + (1, '[2000-06-01,2001-01-01)'); + +-- Foreign key +CREATE TABLE temporal_fk_rng2rng ( + id integer, + valid_at daterange, + parent_id integer, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +\d temporal_fk_rng2rng +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_rng2rng_fk'; + +-- okay +INSERT INTO temporal_fk_rng2rng VALUES + (1, '[2000-01-01,2001-01-01)', 1); +-- okay spanning two parent records: +INSERT INTO temporal_fk_rng2rng VALUES + (2, '[2000-01-01,2002-01-01)', 1); +-- key is missing +INSERT INTO temporal_fk_rng2rng VALUES + (3, '[2000-01-01,2001-01-01)', 3); +-- key exist but is outside range +INSERT INTO temporal_fk_rng2rng VALUES + (4, '[2001-01-01,2002-01-01)', 2); +-- key exist but is partly outside range +INSERT INTO temporal_fk_rng2rng VALUES + (5, '[2000-01-01,2002-01-01)', 2); diff --git a/contrib/citext/Makefile b/contrib/citext/Makefile index b9b3713f537c4..fc990607bf2b4 100644 --- a/contrib/citext/Makefile +++ b/contrib/citext/Makefile @@ -4,6 +4,7 @@ MODULES = citext EXTENSION = citext DATA = citext--1.4.sql \ + citext--1.7--1.8.sql \ citext--1.6--1.7.sql \ citext--1.5--1.6.sql \ citext--1.4--1.5.sql \ diff --git a/contrib/citext/citext--1.7--1.8.sql b/contrib/citext/citext--1.7--1.8.sql new file mode 100644 index 0000000000000..a490736a17982 --- /dev/null +++ b/contrib/citext/citext--1.7--1.8.sql @@ -0,0 +1,60 @@ +/* contrib/citext/citext--1.7--1.8.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION citext UPDATE TO '1.8'" to load this file. \quit + +CREATE OR REPLACE FUNCTION regexp_match(string citext, pattern citext) RETURNS TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_match( $1::text, $2::text, 'i' ); + +CREATE OR REPLACE FUNCTION regexp_match(string citext, pattern citext, flags text) RETURNS TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_match( $1::text, $2::text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); + +CREATE OR REPLACE FUNCTION regexp_matches(string citext, pattern citext) RETURNS SETOF TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE ROWS 1 +RETURN pg_catalog.regexp_matches( $1::text, $2::text, 'i' ); + +CREATE OR REPLACE FUNCTION regexp_matches(string citext, pattern citext, flags text) RETURNS SETOF TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE ROWS 10 +RETURN pg_catalog.regexp_matches( $1::text, $2::text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); + +CREATE OR REPLACE FUNCTION regexp_replace(string citext, pattern citext, replacement text) returns TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_replace( $1::text, $2::text, $3, 'i'); + +CREATE OR REPLACE FUNCTION regexp_replace(string citext, pattern citext, replacement text, flags text) returns TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_replace( $1::text, $2::text, $3, CASE WHEN pg_catalog.strpos($4, 'c') = 0 THEN $4 || 'i' ELSE $4 END); + +CREATE OR REPLACE FUNCTION regexp_split_to_array(string citext, pattern citext) RETURNS TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_split_to_array( $1::text, $2::text, 'i' ); + +CREATE OR REPLACE FUNCTION regexp_split_to_array(string citext, pattern citext, flags text) RETURNS TEXT[] +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_split_to_array( $1::text, $2::text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); + +CREATE OR REPLACE FUNCTION regexp_split_to_table(string citext, pattern citext) RETURNS SETOF TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_split_to_table( $1::text, $2::text, 'i' ); + +CREATE OR REPLACE FUNCTION regexp_split_to_table(string citext, pattern citext, flags text) RETURNS SETOF TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_split_to_table( $1::text, $2::text, CASE WHEN pg_catalog.strpos($3, 'c') = 0 THEN $3 || 'i' ELSE $3 END ); + +CREATE OR REPLACE FUNCTION strpos( citext, citext ) RETURNS INT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.strpos( pg_catalog.lower( $1::text ), pg_catalog.lower( $2::text ) ); + +CREATE OR REPLACE FUNCTION replace( citext, citext, citext ) RETURNS TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.regexp_replace( $1::text, pg_catalog.regexp_replace($2::text, '([^a-zA-Z_0-9])', E'\\\\\\1', 'g'), $3::text, 'gi' ); + +CREATE OR REPLACE FUNCTION split_part( citext, citext, int ) RETURNS TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN (pg_catalog.regexp_split_to_array( $1::text, pg_catalog.regexp_replace($2::text, '([^a-zA-Z_0-9])', E'\\\\\\1', 'g'), 'i'))[$3]; + +CREATE OR REPLACE FUNCTION translate( citext, citext, text ) RETURNS TEXT +LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE +RETURN pg_catalog.translate( pg_catalog.translate( $1::text, pg_catalog.lower($2::text), $3), pg_catalog.upper($2::text), $3); diff --git a/contrib/citext/citext.c b/contrib/citext/citext.c index 26af935a70f6f..a15ce5db8295f 100644 --- a/contrib/citext/citext.c +++ b/contrib/citext/citext.c @@ -5,12 +5,15 @@ #include "catalog/pg_collation.h" #include "common/hashfn.h" -#include "utils/builtins.h" +#include "fmgr.h" #include "utils/formatting.h" #include "utils/varlena.h" #include "varatt.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "citext", + .version = PG_VERSION +); /* * ==================== diff --git a/contrib/citext/citext.control b/contrib/citext/citext.control index f82265b3347a8..2b0f3fa84074b 100644 --- a/contrib/citext/citext.control +++ b/contrib/citext/citext.control @@ -1,6 +1,6 @@ # citext extension comment = 'data type for case-insensitive character strings' -default_version = '1.7' +default_version = '1.8' module_pathname = '$libdir/citext' relocatable = true trusted = true diff --git a/contrib/citext/meson.build b/contrib/citext/meson.build index 40cdd0d2f186b..7fff34f236850 100644 --- a/contrib/citext/meson.build +++ b/contrib/citext/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group citext_sources = files( 'citext.c', @@ -26,6 +26,7 @@ install_data( 'citext--1.4--1.5.sql', 'citext--1.5--1.6.sql', 'citext--1.6--1.7.sql', + 'citext--1.7--1.8.sql', kwargs: contrib_data_args, ) diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index 1fc447511a100..8d3654ab7aafe 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -17,7 +17,10 @@ #include "utils/array.h" #include "utils/float.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "cube", + .version = PG_VERSION +); /* * Taken from the intarray contrib header @@ -120,13 +123,14 @@ cube_in(PG_FUNCTION_ARGS) char *str = PG_GETARG_CSTRING(0); NDBOX *result; Size scanbuflen; + yyscan_t scanner; - cube_scanner_init(str, &scanbuflen); + cube_scanner_init(str, &scanbuflen, &scanner); - cube_yyparse(&result, scanbuflen, fcinfo->context); + cube_yyparse(&result, scanbuflen, fcinfo->context, scanner); /* We might as well run this even on failure. */ - cube_scanner_finish(); + cube_scanner_finish(scanner); PG_RETURN_NDBOX_P(result); } diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h index 96fa41a04e710..ad1e2bd699810 100644 --- a/contrib/cube/cubedata.h +++ b/contrib/cube/cubedata.h @@ -59,14 +59,24 @@ typedef struct NDBOX #define CubeKNNDistanceEuclid 17 /* <-> */ #define CubeKNNDistanceChebyshev 18 /* <=> */ +/* for cubescan.l and cubeparse.y */ +/* All grammar constructs return strings */ +#define YYSTYPE char * +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif + /* in cubescan.l */ -extern int cube_yylex(void); +extern int cube_yylex(YYSTYPE *yylval_param, yyscan_t yyscanner); extern void cube_yyerror(NDBOX **result, Size scanbuflen, struct Node *escontext, + yyscan_t yyscanner, const char *message); -extern void cube_scanner_init(const char *str, Size *scanbuflen); -extern void cube_scanner_finish(void); +extern void cube_scanner_init(const char *str, Size *scanbuflen, yyscan_t *yyscannerp); +extern void cube_scanner_finish(yyscan_t yyscanner); /* in cubeparse.y */ extern int cube_yyparse(NDBOX **result, Size scanbuflen, - struct Node *escontext); + struct Node *escontext, + yyscan_t yyscanner); diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y index fd56d0e16280d..c6e657ca939e7 100644 --- a/contrib/cube/cubeparse.y +++ b/contrib/cube/cubeparse.y @@ -7,17 +7,11 @@ #include "postgres.h" #include "cubedata.h" +#include "cubeparse.h" /* must be after cubedata.h for YYSTYPE and NDBOX */ #include "nodes/miscnodes.h" #include "utils/float.h" #include "varatt.h" -/* silence -Wmissing-variable-declarations */ -extern int cube_yychar; -extern int cube_yynerrs; - -/* All grammar constructs return strings */ -#define YYSTYPE char * - /* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents @@ -38,6 +32,9 @@ static bool write_point_as_box(int dim, char *str, %parse-param {NDBOX **result} %parse-param {Size scanbuflen} %parse-param {struct Node *escontext} +%parse-param {yyscan_t yyscanner} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="cube_yy" @@ -73,6 +70,8 @@ box: O_BRACKET paren_list COMMA paren_list C_BRACKET if (!write_box(dim, $2, $4, result, escontext)) YYABORT; + + (void) yynerrs; /* suppress compiler warning */ } | paren_list COMMA paren_list @@ -245,8 +244,8 @@ write_box(int dim, char *str1, char *str2, * The value turned out to be a point, ie. all the upper-right * coordinates were equal to the lower-left coordinates. Resize the * cube we constructed. Note: we don't bother to repalloc() it - * smaller, as it's unlikely that the tiny amount of memory freed - * that way would be useful, and the output is always short-lived. + * smaller, as it's unlikely that the tiny amount of memory freed that + * way would be useful, and the output is always short-lived. */ size = POINT_SIZE(dim); SET_VARSIZE(bp, size); @@ -261,7 +260,7 @@ static bool write_point_as_box(int dim, char *str, NDBOX **result, struct Node *escontext) { - NDBOX *bp; + NDBOX *bp; int i, size; char *s; diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l index a30fbfc3111a2..e2806dc288fe5 100644 --- a/contrib/cube/cubescan.l +++ b/contrib/cube/cubescan.l @@ -6,13 +6,8 @@ #include "postgres.h" -/* - * NB: include cubeparse.h only AFTER defining YYSTYPE (to match cubeparse.y) - * and cubedata.h for NDBOX. - */ #include "cubedata.h" -#define YYSTYPE char * -#include "cubeparse.h" +#include "cubeparse.h" /* must be after cubedata.h for YYSTYPE and NDBOX */ } %{ @@ -30,18 +25,19 @@ fprintf_to_ereport(const char *fmt, const char *msg) { ereport(ERROR, (errmsg_internal("%s", msg))); } - -/* Handles to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; -static char *scanbuf; %} +%option reentrant +%option bison-bridge %option 8bit %option never-interactive %option nodefault %option noinput %option nounput %option noyywrap +%option noyyalloc +%option noyyrealloc +%option noyyfree %option warn %option prefix="cube_yy" @@ -55,14 +51,14 @@ NaN [nN][aA][nN] %% -{float} cube_yylval = yytext; return CUBEFLOAT; -{infinity} cube_yylval = yytext; return CUBEFLOAT; -{NaN} cube_yylval = yytext; return CUBEFLOAT; -\[ cube_yylval = "("; return O_BRACKET; -\] cube_yylval = ")"; return C_BRACKET; -\( cube_yylval = "("; return O_PAREN; -\) cube_yylval = ")"; return C_PAREN; -\, cube_yylval = ","; return COMMA; +{float} *yylval = yytext; return CUBEFLOAT; +{infinity} *yylval = yytext; return CUBEFLOAT; +{NaN} *yylval = yytext; return CUBEFLOAT; +\[ *yylval = "("; return O_BRACKET; +\] *yylval = ")"; return C_BRACKET; +\( *yylval = "("; return O_PAREN; +\) *yylval = ")"; return C_PAREN; +\, *yylval = ","; return COMMA; [ \t\n\r\f\v]+ /* discard spaces */ . return yytext[0]; /* alert parser of the garbage */ @@ -74,14 +70,18 @@ NaN [nN][aA][nN] void cube_yyerror(NDBOX **result, Size scanbuflen, struct Node *escontext, + yyscan_t yyscanner, const char *message) { + struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext + * macro */ + if (*yytext == YY_END_OF_BUFFER_CHAR) { errsave(escontext, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for cube"), - /* translator: %s is typically "syntax error" */ + /* translator: %s is typically "syntax error" */ errdetail("%s at end of input", message))); } else @@ -89,7 +89,7 @@ cube_yyerror(NDBOX **result, Size scanbuflen, errsave(escontext, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for cube"), - /* translator: first %s is typically "syntax error" */ + /* translator: first %s is typically "syntax error" */ errdetail("%s at or near \"%s\"", message, yytext))); } } @@ -99,26 +99,18 @@ cube_yyerror(NDBOX **result, Size scanbuflen, * Called before any actual parsing is done */ void -cube_scanner_init(const char *str, Size *scanbuflen) +cube_scanner_init(const char *str, Size *scanbuflen, yyscan_t *yyscannerp) { Size slen = strlen(str); + yyscan_t yyscanner; - /* - * Might be left over after ereport() - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); + if (yylex_init(yyscannerp) != 0) + elog(ERROR, "yylex_init() failed: %m"); - /* - * Make a scan buffer with special termination needed by flex. - */ - *scanbuflen = slen; - scanbuf = palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + yyscanner = *yyscannerp; - BEGIN(INITIAL); + yy_scan_bytes(str, slen, yyscanner); + *scanbuflen = slen; } @@ -126,8 +118,34 @@ cube_scanner_init(const char *str, Size *scanbuflen) * Called after parsing is done to clean up after cube_scanner_init() */ void -cube_scanner_finish(void) +cube_scanner_finish(yyscan_t yyscanner) +{ + yylex_destroy(yyscanner); +} + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + return palloc(size); +} + +void * +yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, size); + else + return palloc(size); +} + +void +yyfree(void *ptr, yyscan_t yyscanner) { - yy_delete_buffer(scanbufhandle); - pfree(scanbuf); + if (ptr) + pfree(ptr); } diff --git a/contrib/cube/meson.build b/contrib/cube/meson.build index 21b6f9c43ad90..fd3c057f46920 100644 --- a/contrib/cube/meson.build +++ b/contrib/cube/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group cube_sources = files( 'cube.c', diff --git a/contrib/dblink/Makefile b/contrib/dblink/Makefile index d4c7ed625ab6c..fde0b49ddbbd4 100644 --- a/contrib/dblink/Makefile +++ b/contrib/dblink/Makefile @@ -13,6 +13,7 @@ PGFILEDESC = "dblink - connect to other PostgreSQL databases" REGRESS = dblink REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress +TAP_TESTS = 1 ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 755293456fff6..8a0b112a7ff29 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -9,7 +9,7 @@ * Shridhar Daithankar * * contrib/dblink/dblink.c - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * ALL RIGHTS RESERVED; * * Permission to use, copy, modify, and distribute this software and its @@ -43,6 +43,8 @@ #include "catalog/pg_foreign_server.h" #include "catalog/pg_type.h" #include "catalog/pg_user_mapping.h" +#include "commands/defrem.h" +#include "common/base64.h" #include "executor/spi.h" #include "foreign/foreign.h" #include "funcapi.h" @@ -63,7 +65,10 @@ #include "utils/varlena.h" #include "utils/wait_event.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "dblink", + .version = PG_VERSION +); typedef struct remoteConn { @@ -100,7 +105,7 @@ static PGresult *storeQueryResult(volatile storeInfo *sinfo, PGconn *conn, const static void storeRow(volatile storeInfo *sinfo, PGresult *res, bool first); static remoteConn *getConnectionByName(const char *name); static HTAB *createConnHash(void); -static void createNewConnection(const char *name, remoteConn *rconn); +static remoteConn *createNewConnection(const char *name); static void deleteConnection(const char *name); static char **get_pkey_attnames(Relation rel, int16 *indnkeyatts); static char **get_text_array_contents(ArrayType *array, int *numitems); @@ -114,7 +119,8 @@ static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclM static char *generate_relation_name(Relation rel); static void dblink_connstr_check(const char *connstr); static bool dblink_connstr_has_pw(const char *connstr); -static void dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr); +static void dblink_security_check(PGconn *conn, const char *connname, + const char *connstr); static void dblink_res_error(PGconn *conn, const char *conname, PGresult *res, bool fail, const char *fmt,...) pg_attribute_printf(5, 6); static char *get_connect_string(const char *servername); @@ -126,6 +132,11 @@ static bool is_valid_dblink_option(const PQconninfoOption *options, const char *option, Oid context); static int applyRemoteGucs(PGconn *conn); static void restoreLocalGucs(int nestlevel); +static bool UseScramPassthrough(ForeignServer *foreign_server, UserMapping *user); +static void appendSCRAMKeysInfo(StringInfo buf); +static bool is_valid_dblink_fdw_option(const PQconninfoOption *options, const char *option, + Oid context); +static bool dblink_connstr_has_required_scram_options(const char *connstr); /* Global */ static remoteConn *pconn = NULL; @@ -137,16 +148,22 @@ static uint32 dblink_we_get_conn = 0; static uint32 dblink_we_get_result = 0; /* - * Following is list that holds multiple remote connections. + * Following is hash that holds multiple remote connections. * Calling convention of each dblink function changes to accept - * connection name as the first parameter. The connection list is + * connection name as the first parameter. The connection hash is * much like ecpg e.g. a mapping between a name and a PGconn object. + * + * To avoid potentially leaking a PGconn object in case of out-of-memory + * errors, we first create the hash entry, then open the PGconn. + * Hence, a hash entry whose rconn.conn pointer is NULL must be + * understood as a leftover from a failed create; it should be ignored + * by lookup operations, and silently replaced by create operations. */ typedef struct remoteConnHashEnt { char name[NAMEDATALEN]; - remoteConn *rconn; + remoteConn rconn; } remoteConnHashEnt; /* initial number of connection hashes */ @@ -160,8 +177,7 @@ xpstrdup(const char *in) return pstrdup(in); } -static void -pg_attribute_noreturn() +pg_noreturn static void dblink_res_internalerror(PGconn *conn, PGresult *res, const char *p2) { char *msg = pchomp(PQerrorMessage(conn)); @@ -170,8 +186,7 @@ dblink_res_internalerror(PGconn *conn, PGresult *res, const char *p2) elog(ERROR, "%s: %s", p2, msg); } -static void -pg_attribute_noreturn() +pg_noreturn static void dblink_conn_not_avail(const char *conname) { if (conname) @@ -225,7 +240,7 @@ dblink_get_conn(char *conname_or_str, errmsg("could not establish connection"), errdetail_internal("%s", msg))); } - dblink_security_check(conn, rconn, connstr); + dblink_security_check(conn, NULL, connstr); if (PQclientEncoding(conn) != GetDatabaseEncoding()) PQsetClientEncoding(conn, GetDatabaseEncodingName()); freeconn = true; @@ -288,15 +303,6 @@ dblink_connect(PG_FUNCTION_ARGS) else if (PG_NARGS() == 1) conname_or_str = text_to_cstring(PG_GETARG_TEXT_PP(0)); - if (connname) - { - rconn = (remoteConn *) MemoryContextAlloc(TopMemoryContext, - sizeof(remoteConn)); - rconn->conn = NULL; - rconn->openCursorCount = 0; - rconn->newXactForCursor = false; - } - /* first check for valid foreign data server */ connstr = get_connect_string(conname_or_str); if (connstr == NULL) @@ -309,6 +315,13 @@ dblink_connect(PG_FUNCTION_ARGS) if (dblink_we_connect == 0) dblink_we_connect = WaitEventExtensionNew("DblinkConnect"); + /* if we need a hashtable entry, make that first, since it might fail */ + if (connname) + { + rconn = createNewConnection(connname); + Assert(rconn->conn == NULL); + } + /* OK to make connection */ conn = libpqsrv_connect(connstr, dblink_we_connect); @@ -316,8 +329,8 @@ dblink_connect(PG_FUNCTION_ARGS) { msg = pchomp(PQerrorMessage(conn)); libpqsrv_disconnect(conn); - if (rconn) - pfree(rconn); + if (connname) + deleteConnection(connname); ereport(ERROR, (errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION), @@ -326,16 +339,16 @@ dblink_connect(PG_FUNCTION_ARGS) } /* check password actually used if not superuser */ - dblink_security_check(conn, rconn, connstr); + dblink_security_check(conn, connname, connstr); /* attempt to set client encoding to match server encoding, if needed */ if (PQclientEncoding(conn) != GetDatabaseEncoding()) PQsetClientEncoding(conn, GetDatabaseEncodingName()); + /* all OK, save away the conn */ if (connname) { rconn->conn = conn; - createNewConnection(connname, rconn); } else { @@ -375,10 +388,7 @@ dblink_disconnect(PG_FUNCTION_ARGS) libpqsrv_disconnect(conn); if (rconn) - { deleteConnection(conname); - pfree(rconn); - } else pconn->conn = NULL; @@ -1296,6 +1306,9 @@ dblink_get_connections(PG_FUNCTION_ARGS) hash_seq_init(&status, remoteConnHash); while ((hentry = (remoteConnHashEnt *) hash_seq_search(&status)) != NULL) { + /* ignore it if it's not an open connection */ + if (hentry->rconn.conn == NULL) + continue; /* stash away current value */ astate = accumArrayResult(astate, CStringGetTextDatum(hentry->name), @@ -1966,7 +1979,7 @@ dblink_fdw_validator(PG_FUNCTION_ARGS) { DefElem *def = (DefElem *) lfirst(cell); - if (!is_valid_dblink_option(options, def->defname, context)) + if (!is_valid_dblink_fdw_option(options, def->defname, context)) { /* * Unknown option, or invalid option for the context specified, so @@ -2377,9 +2390,7 @@ get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pk /* * Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "SPI connect failure - returned %d", ret); + SPI_connect(); initStringInfo(&buf); @@ -2533,8 +2544,8 @@ getConnectionByName(const char *name) hentry = (remoteConnHashEnt *) hash_search(remoteConnHash, key, HASH_FIND, NULL); - if (hentry) - return hentry->rconn; + if (hentry && hentry->rconn.conn != NULL) + return &hentry->rconn; return NULL; } @@ -2551,8 +2562,8 @@ createConnHash(void) HASH_ELEM | HASH_STRINGS); } -static void -createNewConnection(const char *name, remoteConn *rconn) +static remoteConn * +createNewConnection(const char *name) { remoteConnHashEnt *hentry; bool found; @@ -2566,17 +2577,15 @@ createNewConnection(const char *name, remoteConn *rconn) hentry = (remoteConnHashEnt *) hash_search(remoteConnHash, key, HASH_ENTER, &found); - if (found) - { - libpqsrv_disconnect(rconn->conn); - pfree(rconn); - + if (found && hentry->rconn.conn != NULL) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("duplicate connection name"))); - } - hentry->rconn = rconn; + /* New, or reusable, so initialize the rconn struct to zeroes */ + memset(&hentry->rconn, 0, sizeof(remoteConn)); + + return &hentry->rconn; } static void @@ -2600,13 +2609,77 @@ deleteConnection(const char *name) errmsg("undefined connection name"))); } + /* + * Ensure that require_auth and SCRAM keys are correctly set on connstr. + * SCRAM keys used to pass-through are coming from the initial connection + * from the client with the server. + * + * All required SCRAM options are set by dblink, so we just need to ensure + * that these options are not overwritten by the user. + * + * See appendSCRAMKeysInfo and its usage for more. + */ +bool +dblink_connstr_has_required_scram_options(const char *connstr) +{ + PQconninfoOption *options; + bool has_scram_server_key = false; + bool has_scram_client_key = false; + bool has_require_auth = false; + bool has_scram_keys = false; + + options = PQconninfoParse(connstr, NULL); + if (options) + { + /* + * Continue iterating even if we found the keys that we need to + * validate to make sure that there is no other declaration of these + * keys that can overwrite the first. + */ + for (PQconninfoOption *option = options; option->keyword != NULL; option++) + { + if (strcmp(option->keyword, "require_auth") == 0) + { + if (option->val != NULL && strcmp(option->val, "scram-sha-256") == 0) + has_require_auth = true; + else + has_require_auth = false; + } + + if (strcmp(option->keyword, "scram_client_key") == 0) + { + if (option->val != NULL && option->val[0] != '\0') + has_scram_client_key = true; + else + has_scram_client_key = false; + } + + if (strcmp(option->keyword, "scram_server_key") == 0) + { + if (option->val != NULL && option->val[0] != '\0') + has_scram_server_key = true; + else + has_scram_server_key = false; + } + } + PQconninfoFree(options); + } + + has_scram_keys = has_scram_client_key && has_scram_server_key && MyProcPort->has_scram_keys; + + return (has_scram_keys && has_require_auth); +} + /* * We need to make sure that the connection made used credentials * which were provided by the user, so check what credentials were * used to connect and then make sure that they came from the user. + * + * On failure, we close "conn" and also delete the hashtable entry + * identified by "connname" (if that's not NULL). */ static void -dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr) +dblink_security_check(PGconn *conn, const char *connname, const char *connstr) { /* Superuser bypasses security check */ if (superuser()) @@ -2616,6 +2689,18 @@ dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr) if (PQconnectionUsedPassword(conn) && dblink_connstr_has_pw(connstr)) return; + /* + * Password was not used to connect, check if SCRAM pass-through is in + * use. + * + * If dblink_connstr_has_required_scram_options is true we assume that + * UseScramPassthrough is also true because the required SCRAM keys are + * only added if UseScramPassthrough is set, and the user is not allowed + * to add the SCRAM keys on fdw and user mapping options. + */ + if (MyProcPort->has_scram_keys && dblink_connstr_has_required_scram_options(connstr)) + return; + #ifdef ENABLE_GSS /* If GSSAPI creds used to connect, make sure it was one delegated */ if (PQconnectionUsedGSSAPI(conn) && be_gssapi_get_delegation(MyProcPort)) @@ -2624,8 +2709,8 @@ dblink_security_check(PGconn *conn, remoteConn *rconn, const char *connstr) /* Otherwise, fail out */ libpqsrv_disconnect(conn); - if (rconn) - pfree(rconn); + if (connname) + deleteConnection(connname); ereport(ERROR, (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), @@ -2668,12 +2753,14 @@ dblink_connstr_has_pw(const char *connstr) } /* - * For non-superusers, insist that the connstr specify a password, except - * if GSSAPI credentials have been delegated (and we check that they are used - * for the connection in dblink_security_check later). This prevents a - * password or GSSAPI credentials from being picked up from .pgpass, a - * service file, the environment, etc. We don't want the postgres user's - * passwords or Kerberos credentials to be accessible to non-superusers. + * For non-superusers, insist that the connstr specify a password, except if + * GSSAPI credentials have been delegated (and we check that they are used for + * the connection in dblink_security_check later) or if SCRAM pass-through is + * being used. This prevents a password or GSSAPI credentials from being + * picked up from .pgpass, a service file, the environment, etc. We don't want + * the postgres user's passwords or Kerberos credentials to be accessible to + * non-superusers. In case of SCRAM pass-through insist that the connstr + * has the required SCRAM pass-through options. */ static void dblink_connstr_check(const char *connstr) @@ -2684,6 +2771,9 @@ dblink_connstr_check(const char *connstr) if (dblink_connstr_has_pw(connstr)) return; + if (MyProcPort->has_scram_keys && dblink_connstr_has_required_scram_options(connstr)) + return; + #ifdef ENABLE_GSS if (be_gssapi_get_delegation(MyProcPort)) return; @@ -2836,6 +2926,14 @@ get_connect_string(const char *servername) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, OBJECT_FOREIGN_SERVER, foreign_server->servername); + /* + * First append hardcoded options needed for SCRAM pass-through, so if + * the user overwrites these options we can ereport on + * dblink_connstr_check and dblink_security_check. + */ + if (MyProcPort->has_scram_keys && UseScramPassthrough(foreign_server, user_mapping)) + appendSCRAMKeysInfo(&buf); + foreach(cell, fdw->options) { DefElem *def = lfirst(cell); @@ -3002,6 +3100,13 @@ is_valid_dblink_option(const PQconninfoOption *options, const char *option, if (strcmp(opt->keyword, "client_encoding") == 0) return false; + /* + * Disallow OAuth options for now, since the builtin flow communicates on + * stderr by default and can't cache tokens yet. + */ + if (strncmp(opt->keyword, "oauth_", strlen("oauth_")) == 0) + return false; + /* * If the option is "user" or marked secure, it should be specified only * in USER MAPPING. Others should be specified only in SERVER. @@ -3020,6 +3125,20 @@ is_valid_dblink_option(const PQconninfoOption *options, const char *option, return true; } +/* + * Same as is_valid_dblink_option but also check for only dblink_fdw specific + * options. + */ +static bool +is_valid_dblink_fdw_option(const PQconninfoOption *options, const char *option, + Oid context) +{ + if (strcmp(option, "use_scram_passthrough") == 0) + return true; + + return is_valid_dblink_option(options, option, context); +} + /* * Copy the remote session's values of GUCs that affect datatype I/O * and apply them locally in a new GUC nesting level. Returns the new @@ -3089,3 +3208,66 @@ restoreLocalGucs(int nestlevel) if (nestlevel > 0) AtEOXact_GUC(true, nestlevel); } + +/* + * Append SCRAM client key and server key information from the global + * MyProcPort into the given StringInfo buffer. + */ +static void +appendSCRAMKeysInfo(StringInfo buf) +{ + int len; + int encoded_len; + char *client_key; + char *server_key; + + len = pg_b64_enc_len(sizeof(MyProcPort->scram_ClientKey)); + /* don't forget the zero-terminator */ + client_key = palloc0(len + 1); + encoded_len = pg_b64_encode(MyProcPort->scram_ClientKey, + sizeof(MyProcPort->scram_ClientKey), + client_key, len); + if (encoded_len < 0) + elog(ERROR, "could not encode SCRAM client key"); + + len = pg_b64_enc_len(sizeof(MyProcPort->scram_ServerKey)); + /* don't forget the zero-terminator */ + server_key = palloc0(len + 1); + encoded_len = pg_b64_encode(MyProcPort->scram_ServerKey, + sizeof(MyProcPort->scram_ServerKey), + server_key, len); + if (encoded_len < 0) + elog(ERROR, "could not encode SCRAM server key"); + + appendStringInfo(buf, "scram_client_key='%s' ", client_key); + appendStringInfo(buf, "scram_server_key='%s' ", server_key); + appendStringInfoString(buf, "require_auth='scram-sha-256' "); + + pfree(client_key); + pfree(server_key); +} + + +static bool +UseScramPassthrough(ForeignServer *foreign_server, UserMapping *user) +{ + ListCell *cell; + + foreach(cell, foreign_server->options) + { + DefElem *def = lfirst(cell); + + if (strcmp(def->defname, "use_scram_passthrough") == 0) + return defGetBoolean(def); + } + + foreach(cell, user->options) + { + DefElem *def = (DefElem *) lfirst(cell); + + if (strcmp(def->defname, "use_scram_passthrough") == 0) + return defGetBoolean(def); + } + + return false; +} diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out index 7809f58d96b5f..c70c79574fd1d 100644 --- a/contrib/dblink/expected/dblink.out +++ b/contrib/dblink/expected/dblink.out @@ -898,6 +898,17 @@ CREATE USER MAPPING FOR public SERVER fdtest OPTIONS (server 'localhost'); -- fail, can't specify server here ERROR: invalid option "server" CREATE USER MAPPING FOR public SERVER fdtest OPTIONS (user :'USER'); +-- OAuth options are not allowed in either context +ALTER SERVER fdtest OPTIONS (ADD oauth_issuer 'https://example.com'); +ERROR: invalid option "oauth_issuer" +ALTER SERVER fdtest OPTIONS (ADD oauth_client_id 'myID'); +ERROR: invalid option "oauth_client_id" +ALTER USER MAPPING FOR public SERVER fdtest + OPTIONS (ADD oauth_issuer 'https://example.com'); +ERROR: invalid option "oauth_issuer" +ALTER USER MAPPING FOR public SERVER fdtest + OPTIONS (ADD oauth_client_id 'myID'); +ERROR: invalid option "oauth_client_id" GRANT USAGE ON FOREIGN SERVER fdtest TO regress_dblink_user; GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO regress_dblink_user; SET SESSION AUTHORIZATION regress_dblink_user; diff --git a/contrib/dblink/meson.build b/contrib/dblink/meson.build index 45eeb58c6186b..dfd8eb6877e90 100644 --- a/contrib/dblink/meson.build +++ b/contrib/dblink/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dblink_sources = files( 'dblink.c', @@ -36,4 +36,9 @@ tests += { ], 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], }, + 'tap': { + 'tests': [ + 't/001_auth_scram.pl', + ], + }, } diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql index 7870ce5d5a43d..365b21036e854 100644 --- a/contrib/dblink/sql/dblink.sql +++ b/contrib/dblink/sql/dblink.sql @@ -469,6 +469,14 @@ CREATE USER MAPPING FOR public SERVER fdtest OPTIONS (server 'localhost'); -- fail, can't specify server here CREATE USER MAPPING FOR public SERVER fdtest OPTIONS (user :'USER'); +-- OAuth options are not allowed in either context +ALTER SERVER fdtest OPTIONS (ADD oauth_issuer 'https://example.com'); +ALTER SERVER fdtest OPTIONS (ADD oauth_client_id 'myID'); +ALTER USER MAPPING FOR public SERVER fdtest + OPTIONS (ADD oauth_issuer 'https://example.com'); +ALTER USER MAPPING FOR public SERVER fdtest + OPTIONS (ADD oauth_client_id 'myID'); + GRANT USAGE ON FOREIGN SERVER fdtest TO regress_dblink_user; GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO regress_dblink_user; diff --git a/contrib/dblink/t/001_auth_scram.pl b/contrib/dblink/t/001_auth_scram.pl new file mode 100644 index 0000000000000..ef3dea6c5ad19 --- /dev/null +++ b/contrib/dblink/t/001_auth_scram.pl @@ -0,0 +1,253 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# Test SCRAM authentication when opening a new connection with a foreign +# server. +# +# The test is executed by testing the SCRAM authentifcation on a loopback +# connection on the same server and with different servers. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +if (!$use_unix_sockets) +{ + plan skip_all => "test requires Unix-domain sockets"; +} + +my $user = "user01"; + +my $db0 = "db0"; # For node1 +my $db1 = "db1"; # For node1 +my $db2 = "db2"; # For node2 +my $fdw_server = "db1_fdw"; +my $fdw_server2 = "db2_fdw"; +my $fdw_invalid_server = "db2_fdw_invalid"; # For invalid fdw options +my $fdw_invalid_server2 = + "db2_fdw_invalid2"; # For invalid scram keys fdw options + +my $node1 = PostgreSQL::Test::Cluster->new('node1'); +my $node2 = PostgreSQL::Test::Cluster->new('node2'); + +$node1->init; +$node2->init; + +$node1->start; +$node2->start; + +# Test setup + +$node1->safe_psql('postgres', qq'CREATE USER $user WITH password \'pass\''); +$node2->safe_psql('postgres', qq'CREATE USER $user WITH password \'pass\''); +$ENV{PGPASSWORD} = "pass"; + +$node1->safe_psql('postgres', qq'CREATE DATABASE $db0'); +$node1->safe_psql('postgres', qq'CREATE DATABASE $db1'); +$node2->safe_psql('postgres', qq'CREATE DATABASE $db2'); + +setup_table($node1, $db1, "t"); +setup_table($node2, $db2, "t2"); + +$node1->safe_psql($db0, 'CREATE EXTENSION IF NOT EXISTS dblink'); +setup_fdw_server($node1, $db0, $fdw_server, $node1, $db1); +setup_fdw_server($node1, $db0, $fdw_server2, $node2, $db2); +setup_invalid_fdw_server($node1, $db0, $fdw_invalid_server, $node2, $db2); +setup_fdw_server($node1, $db0, $fdw_invalid_server2, $node2, $db2); + +setup_user_mapping($node1, $db0, $fdw_server); +setup_user_mapping($node1, $db0, $fdw_server2); +setup_user_mapping($node1, $db0, $fdw_invalid_server); + +# Make the user have the same SCRAM key on both servers. Forcing to have the +# same iteration and salt. +my $rolpassword = $node1->safe_psql('postgres', + qq"SELECT rolpassword FROM pg_authid WHERE rolname = '$user';"); +$node2->safe_psql('postgres', qq"ALTER ROLE $user PASSWORD '$rolpassword'"); + +unlink($node1->data_dir . '/pg_hba.conf'); +unlink($node2->data_dir . '/pg_hba.conf'); + +$node1->append_conf( + 'pg_hba.conf', qq{ +local db0 all scram-sha-256 +local db1 all scram-sha-256 +} +); +$node2->append_conf( + 'pg_hba.conf', qq{ +local db2 all scram-sha-256 +} +); + +$node1->restart; +$node2->restart; + +# End of test setup + +test_scram_keys_is_not_overwritten($node1, $db0, $fdw_invalid_server2); + +test_fdw_auth($node1, $db0, "t", $fdw_server, + "SCRAM auth on the same database cluster must succeed"); + +test_fdw_auth($node1, $db0, "t2", $fdw_server2, + "SCRAM auth on a different database cluster must succeed"); + +test_fdw_auth_with_invalid_overwritten_require_auth($fdw_invalid_server); + +# Ensure that trust connections fail without superuser opt-in. +unlink($node1->data_dir . '/pg_hba.conf'); +unlink($node2->data_dir . '/pg_hba.conf'); + +$node1->append_conf( + 'pg_hba.conf', qq{ +local db0 all scram-sha-256 +local db1 all trust +} +); +$node2->append_conf( + 'pg_hba.conf', qq{ +local all all password +} +); + +$node1->restart; +$node2->restart; + +my ($ret, $stdout, $stderr) = $node1->psql( + $db0, + "SELECT * FROM dblink('$fdw_server', 'SELECT * FROM t') AS t(a int, b int)", + connstr => $node1->connstr($db0) . " user=$user"); + +is($ret, 3, 'loopback trust fails on the same cluster'); +like( + $stderr, + qr/failed: authentication method requirement "scram-sha-256" failed: server did not complete authentication/, + 'expected error from loopback trust (same cluster)'); + +($ret, $stdout, $stderr) = $node1->psql( + $db0, + "SELECT * FROM dblink('$fdw_server2', 'SELECT * FROM t2') AS t2(a int, b int)", + connstr => $node1->connstr($db0) . " user=$user"); + +is($ret, 3, 'loopback password fails on a different cluster'); +like( + $stderr, + qr/authentication method requirement "scram-sha-256" failed: server requested a cleartext password/, + 'expected error from loopback password (different cluster)'); + +# Helper functions + +sub test_fdw_auth +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($node, $db, $tbl, $fdw, $testname) = @_; + my $connstr = $node->connstr($db) . qq' user=$user'; + + my $ret = $node->safe_psql( + $db, + qq"SELECT count(1) FROM dblink('$fdw', 'SELECT * FROM $tbl') AS $tbl(a int, b int)", + connstr => $connstr); + + is($ret, '10', $testname); +} + +sub test_fdw_auth_with_invalid_overwritten_require_auth +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($fdw) = @_; + + my ($ret, $stdout, $stderr) = $node1->psql( + $db0, + "select * from dblink('$fdw', 'select * from t') as t(a int, b int)", + connstr => $node1->connstr($db0) . " user=$user"); + + is($ret, 3, 'loopback trust fails when overwriting require_auth'); + like( + $stderr, + qr/password or GSSAPI delegated credentials required/, + 'expected error when connecting to a fdw overwriting the require_auth' + ); +} + +sub test_scram_keys_is_not_overwritten +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($node, $db, $fdw) = @_; + + my ($ret, $stdout, $stderr) = $node->psql( + $db, + qq'CREATE USER MAPPING FOR $user SERVER $fdw OPTIONS (user \'$user\', scram_client_key \'key\');', + connstr => $node->connstr($db) . " user=$user"); + + is($ret, 3, 'user mapping creation fails when using scram_client_key'); + like( + $stderr, + qr/ERROR: invalid option "scram_client_key"/, + 'user mapping creation fails when using scram_client_key'); + + ($ret, $stdout, $stderr) = $node->psql( + $db, + qq'CREATE USER MAPPING FOR $user SERVER $fdw OPTIONS (user \'$user\', scram_server_key \'key\');', + connstr => $node->connstr($db) . " user=$user"); + + is($ret, 3, 'user mapping creation fails when using scram_server_key'); + like( + $stderr, + qr/ERROR: invalid option "scram_server_key"/, + 'user mapping creation fails when using scram_server_key'); +} + +sub setup_user_mapping +{ + my ($node, $db, $fdw) = @_; + + $node->safe_psql($db, + qq'CREATE USER MAPPING FOR $user SERVER $fdw OPTIONS (user \'$user\');' + ); +} + +sub setup_fdw_server +{ + my ($node, $db, $fdw, $fdw_node, $dbname) = @_; + my $host = $fdw_node->host; + my $port = $fdw_node->port; + + $node->safe_psql( + $db, qq'CREATE SERVER $fdw FOREIGN DATA WRAPPER dblink_fdw options ( + host \'$host\', port \'$port\', dbname \'$dbname\', use_scram_passthrough \'true\') ' + ); + $node->safe_psql($db, qq'GRANT USAGE ON FOREIGN SERVER $fdw TO $user;'); + $node->safe_psql($db, qq'GRANT ALL ON SCHEMA public TO $user'); +} + +sub setup_invalid_fdw_server +{ + my ($node, $db, $fdw, $fdw_node, $dbname) = @_; + my $host = $fdw_node->host; + my $port = $fdw_node->port; + + $node->safe_psql( + $db, qq'CREATE SERVER $fdw FOREIGN DATA WRAPPER dblink_fdw options ( + host \'$host\', port \'$port\', dbname \'$dbname\', use_scram_passthrough \'true\', require_auth \'none\') ' + ); + $node->safe_psql($db, qq'GRANT USAGE ON FOREIGN SERVER $fdw TO $user;'); + $node->safe_psql($db, qq'GRANT ALL ON SCHEMA public TO $user'); +} + +sub setup_table +{ + my ($node, $db, $tbl) = @_; + + $node->safe_psql($db, + qq'CREATE TABLE $tbl AS SELECT g as a, g + 1 as b FROM generate_series(1,10) g(g)' + ); + $node->safe_psql($db, qq'GRANT USAGE ON SCHEMA public TO $user'); + $node->safe_psql($db, qq'GRANT SELECT ON $tbl TO $user'); +} + +done_testing(); diff --git a/contrib/dict_int/dict_int.c b/contrib/dict_int/dict_int.c index 82f3c60251251..bdad52d202897 100644 --- a/contrib/dict_int/dict_int.c +++ b/contrib/dict_int/dict_int.c @@ -3,7 +3,7 @@ * dict_int.c * Text search dictionary for integers * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/dict_int/dict_int.c @@ -15,7 +15,10 @@ #include "commands/defrem.h" #include "tsearch/ts_public.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "dict_int", + .version = PG_VERSION +); typedef struct { diff --git a/contrib/dict_int/meson.build b/contrib/dict_int/meson.build index 97bc0aaf1dbe1..ab41588547bc8 100644 --- a/contrib/dict_int/meson.build +++ b/contrib/dict_int/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dict_int_sources = files( 'dict_int.c', diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c index 62d2d841417ca..1ec5285d6d1fc 100644 --- a/contrib/dict_xsyn/dict_xsyn.c +++ b/contrib/dict_xsyn/dict_xsyn.c @@ -3,7 +3,7 @@ * dict_xsyn.c * Extended synonym dictionary * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/dict_xsyn/dict_xsyn.c @@ -14,11 +14,16 @@ #include +#include "catalog/pg_collation_d.h" #include "commands/defrem.h" #include "tsearch/ts_locale.h" -#include "tsearch/ts_utils.h" +#include "tsearch/ts_public.h" +#include "utils/formatting.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "dict_xsyn", + .version = PG_VERSION +); typedef struct { @@ -48,14 +53,14 @@ find_word(char *in, char **end) char *start; *end = NULL; - while (*in && t_isspace(in)) + while (*in && isspace((unsigned char) *in)) in += pg_mblen(in); if (!*in || *in == '#') return NULL; start = in; - while (*in && !t_isspace(in)) + while (*in && !isspace((unsigned char) *in)) in += pg_mblen(in); *end = in; @@ -93,7 +98,7 @@ read_dictionary(DictSyn *d, const char *filename) if (*line == '\0') continue; - value = lowerstr(line); + value = str_tolower(line, strlen(line), DEFAULT_COLLATION_OID); pfree(line); pos = value; @@ -210,7 +215,7 @@ dxsyn_lexize(PG_FUNCTION_ARGS) { char *temp = pnstrdup(in, length); - word.key = lowerstr(temp); + word.key = str_tolower(temp, length, DEFAULT_COLLATION_OID); pfree(temp); word.value = NULL; } diff --git a/contrib/dict_xsyn/meson.build b/contrib/dict_xsyn/meson.build index 12d41d30a7b74..93f41b1f963e0 100644 --- a/contrib/dict_xsyn/meson.build +++ b/contrib/dict_xsyn/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dict_xsyn_sources = files( 'dict_xsyn.c', diff --git a/contrib/earthdistance/Makefile b/contrib/earthdistance/Makefile index f93b7a925a290..0cf3fa379a27d 100644 --- a/contrib/earthdistance/Makefile +++ b/contrib/earthdistance/Makefile @@ -3,7 +3,8 @@ MODULES = earthdistance EXTENSION = earthdistance -DATA = earthdistance--1.1.sql earthdistance--1.0--1.1.sql +DATA = earthdistance--1.1.sql earthdistance--1.0--1.1.sql \ + earthdistance--1.1--1.2.sql PGFILEDESC = "earthdistance - calculate distances on the surface of the Earth" REGRESS = earthdistance diff --git a/contrib/earthdistance/earthdistance--1.1--1.2.sql b/contrib/earthdistance/earthdistance--1.1--1.2.sql new file mode 100644 index 0000000000000..40a0ce233d17c --- /dev/null +++ b/contrib/earthdistance/earthdistance--1.1--1.2.sql @@ -0,0 +1,73 @@ +/* contrib/earthdistance/earthdistance--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION earthdistance UPDATE TO '1.2'" to load this file. \quit + +CREATE OR REPLACE FUNCTION earth() RETURNS float8 +LANGUAGE SQL IMMUTABLE PARALLEL SAFE +RETURN '6378168'::float8; + +CREATE OR REPLACE FUNCTION sec_to_gc(float8) +RETURNS float8 +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN CASE + WHEN $1 < '0'::float8 THEN '0'::float8 + WHEN $1 / ('2'::float8 * earth()) > '1'::float8 THEN pi() * earth() + ELSE '2'::float8 * earth() * asin($1 / ('2'::float8 * earth())) +END; + +CREATE OR REPLACE FUNCTION gc_to_sec(float8) +RETURNS float8 +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN CASE + WHEN $1 < '0'::float8 THEN '0'::float8 + WHEN $1 / earth() > pi() THEN '2'::float8 * earth() + ELSE '2'::float8 * earth() * sin($1 / ('2'::float8 * earth())) +END; + +CREATE OR REPLACE FUNCTION ll_to_earth(float8, float8) +RETURNS earth +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN @extschema:cube@.cube(@extschema:cube@.cube(@extschema:cube@.cube( + earth() * cos(radians($1)) * cos(radians($2))), + earth() * cos(radians($1)) * sin(radians($2))), + earth() * sin(radians($1)))::earth; + +CREATE OR REPLACE FUNCTION latitude(earth) +RETURNS float8 +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN CASE + WHEN @extschema:cube@.cube_ll_coord($1, 3) / earth() < '-1'::float8 THEN '-90'::float8 + WHEN @extschema:cube@.cube_ll_coord($1, 3) / earth() > '1'::float8 THEN '90'::float8 + ELSE degrees(asin(@extschema:cube@.cube_ll_coord($1, 3) / earth())) +END; + +CREATE OR REPLACE FUNCTION longitude(earth) +RETURNS float8 +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN degrees(atan2(@extschema:cube@.cube_ll_coord($1, 2), + @extschema:cube@.cube_ll_coord($1, 1))); + +CREATE OR REPLACE FUNCTION earth_distance(earth, earth) +RETURNS float8 +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN sec_to_gc(@extschema:cube@.cube_distance($1, $2)); + +CREATE OR REPLACE FUNCTION earth_box(earth, float8) +RETURNS @extschema:cube@.cube +LANGUAGE SQL +IMMUTABLE STRICT +PARALLEL SAFE +RETURN @extschema:cube@.cube_enlarge($1, gc_to_sec($2), 3); diff --git a/contrib/earthdistance/earthdistance--1.1.sql b/contrib/earthdistance/earthdistance--1.1.sql index 9ef20ab848c51..4799f03e3ea3d 100644 --- a/contrib/earthdistance/earthdistance--1.1.sql +++ b/contrib/earthdistance/earthdistance--1.1.sql @@ -27,10 +27,10 @@ AS 'SELECT ''6378168''::float8'; -- and that the point must be very near the surface of the sphere -- centered about the origin with the radius of the earth. -CREATE DOMAIN earth AS cube - CONSTRAINT not_point check(cube_is_point(value)) - CONSTRAINT not_3d check(cube_dim(value) <= 3) - CONSTRAINT on_surface check(abs(cube_distance(value, '(0)'::cube) / +CREATE DOMAIN earth AS @extschema:cube@.cube + CONSTRAINT not_point CHECK(@extschema:cube@.cube_is_point(VALUE)) + CONSTRAINT not_3d CHECK(@extschema:cube@.cube_dim(VALUE) <= 3) + CONSTRAINT on_surface CHECK(abs(@extschema:cube@.cube_distance(VALUE, '(0)'::@extschema:cube@.cube) / earth() - '1'::float8) < '10e-7'::float8); CREATE FUNCTION sec_to_gc(float8) diff --git a/contrib/earthdistance/earthdistance.c b/contrib/earthdistance/earthdistance.c index ded048c8ac502..f3011803d0810 100644 --- a/contrib/earthdistance/earthdistance.c +++ b/contrib/earthdistance/earthdistance.c @@ -11,7 +11,10 @@ #define M_PI 3.14159265358979323846 #endif -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "earthdistance", + .version = PG_VERSION +); /* Earth's radius is in statute miles. */ static const double EARTH_RADIUS = 3958.747716; diff --git a/contrib/earthdistance/earthdistance.control b/contrib/earthdistance/earthdistance.control index 5816d22cdd988..de2465d487e2e 100644 --- a/contrib/earthdistance/earthdistance.control +++ b/contrib/earthdistance/earthdistance.control @@ -1,6 +1,6 @@ # earthdistance extension comment = 'calculate great-circle distances on the surface of the Earth' -default_version = '1.1' +default_version = '1.2' module_pathname = '$libdir/earthdistance' relocatable = true requires = 'cube' diff --git a/contrib/earthdistance/meson.build b/contrib/earthdistance/meson.build index 4e3c538f7aaac..a5f8d1a3ffa0d 100644 --- a/contrib/earthdistance/meson.build +++ b/contrib/earthdistance/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group earthdistance_sources = files( 'earthdistance.c', @@ -20,6 +20,7 @@ install_data( 'earthdistance.control', 'earthdistance--1.0--1.1.sql', 'earthdistance--1.1.sql', + 'earthdistance--1.1--1.2.sql', kwargs: contrib_data_args, ) diff --git a/contrib/file_fdw/data/agg.bad b/contrib/file_fdw/data/agg.bad index 3415b15007216..04279ce55b5ec 100644 --- a/contrib/file_fdw/data/agg.bad +++ b/contrib/file_fdw/data/agg.bad @@ -2,3 +2,4 @@ 100;@99.097@ 0;@aaa@ 42;@324.78@ +1;@bbb@ diff --git a/contrib/file_fdw/expected/file_fdw.out b/contrib/file_fdw/expected/file_fdw.out index 86c148a86ba3a..246e3d3e566fc 100644 --- a/contrib/file_fdw/expected/file_fdw.out +++ b/contrib/file_fdw/expected/file_fdw.out @@ -48,6 +48,10 @@ SET ROLE regress_file_fdw_superuser; CREATE USER MAPPING FOR regress_file_fdw_superuser SERVER file_server; CREATE USER MAPPING FOR regress_no_priv_user SERVER file_server; -- validator tests +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (foo 'bar'); -- ERROR +ERROR: invalid option "foo" +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS ("a=b" 'true'); -- ERROR +ERROR: invalid option name "a=b": must not contain "=" CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR ERROR: COPY format "xml" not recognized CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR @@ -90,6 +94,16 @@ ERROR: COPY delimiter cannot be newline or carriage return CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null ' '); -- ERROR ERROR: COPY null representation cannot use newline or carriage return +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (on_error 'unsupported'); -- ERROR +ERROR: COPY ON_ERROR "unsupported" not recognized +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', on_error 'ignore'); -- ERROR +ERROR: only ON_ERROR STOP is allowed in BINARY mode +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (log_verbosity 'unsupported'); -- ERROR +ERROR: COPY LOG_VERBOSITY "unsupported" not recognized +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (reject_limit '1'); -- ERROR +ERROR: COPY REJECT_LIMIT requires ON_ERROR to be set to IGNORE +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (on_error 'ignore', reject_limit '0'); -- ERROR +ERROR: REJECT_LIMIT (0) must be greater than zero CREATE FOREIGN TABLE tbl () SERVER file_server; -- ERROR ERROR: either filename or program is required for file_fdw foreign tables \set filename :abs_srcdir '/data/agg.data' @@ -206,6 +220,37 @@ SELECT * FROM agg_csv c JOIN agg_text t ON (t.a = c.a) ORDER BY c.a; SELECT * FROM agg_bad; -- ERROR ERROR: invalid input syntax for type real: "aaa" CONTEXT: COPY agg_bad, line 3, column b: "aaa" +-- on_error, log_verbosity and reject_limit tests +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD on_error 'ignore'); +SELECT * FROM agg_bad; +NOTICE: 2 rows were skipped due to data type incompatibility + a | b +-----+-------- + 100 | 99.097 + 42 | 324.78 +(2 rows) + +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD log_verbosity 'silent'); +SELECT * FROM agg_bad; + a | b +-----+-------- + 100 | 99.097 + 42 | 324.78 +(2 rows) + +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD reject_limit '1'); -- ERROR +SELECT * FROM agg_bad; +ERROR: skipped more than REJECT_LIMIT (1) rows due to data type incompatibility +CONTEXT: COPY agg_bad, line 5, column b: "bbb" +ALTER FOREIGN TABLE agg_bad OPTIONS (SET reject_limit '2'); +SELECT * FROM agg_bad; + a | b +-----+-------- + 100 | 99.097 + 42 | 324.78 +(2 rows) + +ANALYZE agg_bad; -- misc query tests \t on SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv'); diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index 249d82d3a0593..a9a5671d95a6f 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -3,7 +3,7 @@ * file_fdw.c * foreign-data wrapper for server-side flat files (or programs). * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/file_fdw/file_fdw.c @@ -22,9 +22,12 @@ #include "catalog/pg_authid.h" #include "catalog/pg_foreign_table.h" #include "commands/copy.h" +#include "commands/copyfrom_internal.h" #include "commands/defrem.h" -#include "commands/explain.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" #include "commands/vacuum.h" +#include "executor/executor.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" #include "miscadmin.h" @@ -39,7 +42,10 @@ #include "utils/sampling.h" #include "utils/varlena.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "file_fdw", + .version = PG_VERSION +); /* * Describes the valid options for objects that use this wrapper. @@ -74,6 +80,9 @@ static const struct FileFdwOption valid_options[] = { {"null", ForeignTableRelationId}, {"default", ForeignTableRelationId}, {"encoding", ForeignTableRelationId}, + {"on_error", ForeignTableRelationId}, + {"log_verbosity", ForeignTableRelationId}, + {"reject_limit", ForeignTableRelationId}, {"force_not_null", AttributeRelationId}, {"force_null", AttributeRelationId}, @@ -527,7 +536,7 @@ fileGetForeignRelSize(PlannerInfo *root, &fdw_private->filename, &fdw_private->is_program, &fdw_private->options); - baserel->fdw_private = (void *) fdw_private; + baserel->fdw_private = fdw_private; /* Estimate relation size */ estimate_size(root, baserel, fdw_private); @@ -576,6 +585,7 @@ fileGetForeignPaths(PlannerInfo *root, create_foreignscan_path(root, baserel, NULL, /* default pathtarget */ baserel->rows, + 0, startup_cost, total_cost, NIL, /* no pathkeys */ @@ -708,7 +718,7 @@ fileBeginForeignScan(ForeignScanState *node, int eflags) festate->options = options; festate->cstate = cstate; - node->fdw_state = (void *) festate; + node->fdw_state = festate; } /* @@ -722,38 +732,81 @@ fileIterateForeignScan(ForeignScanState *node) FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state; EState *estate = CreateExecutorState(); ExprContext *econtext; - MemoryContext oldcontext; + MemoryContext oldcontext = CurrentMemoryContext; TupleTableSlot *slot = node->ss.ss_ScanTupleSlot; - bool found; + CopyFromState cstate = festate->cstate; ErrorContextCallback errcallback; /* Set up callback to identify error line number. */ errcallback.callback = CopyFromErrorCallback; - errcallback.arg = (void *) festate->cstate; + errcallback.arg = cstate; errcallback.previous = error_context_stack; error_context_stack = &errcallback; /* - * The protocol for loading a virtual tuple into a slot is first - * ExecClearTuple, then fill the values/isnull arrays, then - * ExecStoreVirtualTuple. If we don't find another row in the file, we - * just skip the last step, leaving the slot empty as required. - * * We pass ExprContext because there might be a use of the DEFAULT option * in COPY FROM, so we may need to evaluate default expressions. */ - ExecClearTuple(slot); econtext = GetPerTupleExprContext(estate); +retry: + /* * DEFAULT expressions need to be evaluated in a per-tuple context, so * switch in case we are doing that. */ - oldcontext = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - found = NextCopyFrom(festate->cstate, econtext, - slot->tts_values, slot->tts_isnull); - if (found) + MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); + + /* + * The protocol for loading a virtual tuple into a slot is first + * ExecClearTuple, then fill the values/isnull arrays, then + * ExecStoreVirtualTuple. If we don't find another row in the file, we + * just skip the last step, leaving the slot empty as required. + * + */ + ExecClearTuple(slot); + + if (NextCopyFrom(cstate, econtext, slot->tts_values, slot->tts_isnull)) + { + if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE && + cstate->escontext->error_occurred) + { + /* + * Soft error occurred, skip this tuple and just make + * ErrorSaveContext ready for the next NextCopyFrom. Since we + * don't set details_wanted and error_data is not to be filled, + * just resetting error_occurred is enough. + */ + cstate->escontext->error_occurred = false; + + /* Switch back to original memory context */ + MemoryContextSwitchTo(oldcontext); + + /* + * Make sure we are interruptible while repeatedly calling + * NextCopyFrom() until no soft error occurs. + */ + CHECK_FOR_INTERRUPTS(); + + /* + * Reset the per-tuple exprcontext, to clean-up after expression + * evaluations etc. + */ + ResetPerTupleExprContext(estate); + + if (cstate->opts.reject_limit > 0 && + cstate->num_errors > cstate->opts.reject_limit) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("skipped more than REJECT_LIMIT (%" PRId64 ") rows due to data type incompatibility", + cstate->opts.reject_limit))); + + /* Repeat NextCopyFrom() until no soft error occurs */ + goto retry; + } + ExecStoreVirtualTuple(slot); + } /* Switch back to original memory context */ MemoryContextSwitchTo(oldcontext); @@ -795,8 +848,19 @@ fileEndForeignScan(ForeignScanState *node) FileFdwExecutionState *festate = (FileFdwExecutionState *) node->fdw_state; /* if festate is NULL, we are in EXPLAIN; nothing to do */ - if (festate) - EndCopyFrom(festate->cstate); + if (!festate) + return; + + if (festate->cstate->opts.on_error == COPY_ON_ERROR_IGNORE && + festate->cstate->num_errors > 0 && + festate->cstate->opts.log_verbosity >= COPY_LOG_VERBOSITY_DEFAULT) + ereport(NOTICE, + errmsg_plural("%" PRIu64 " row was skipped due to data type incompatibility", + "%" PRIu64 " rows were skipped due to data type incompatibility", + festate->cstate->num_errors, + festate->cstate->num_errors)); + + EndCopyFrom(festate->cstate); } /* @@ -1112,7 +1176,8 @@ estimate_costs(PlannerInfo *root, RelOptInfo *baserel, * which must have at least targrows entries. * The actual number of rows selected is returned as the function result. * We also count the total number of rows in the file and return it into - * *totalrows. Note that *totaldeadrows is always set to 0. + * *totalrows. Rows skipped due to on_error = 'ignore' are not included + * in this count. Note that *totaldeadrows is always set to 0. * * Note that the returned list of rows is not always in order by physical * position in the file. Therefore, correlation estimates derived later @@ -1168,7 +1233,7 @@ file_acquire_sample_rows(Relation onerel, int elevel, /* Set up callback to identify error line number. */ errcallback.callback = CopyFromErrorCallback; - errcallback.arg = (void *) cstate; + errcallback.arg = cstate; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1177,7 +1242,7 @@ file_acquire_sample_rows(Relation onerel, int elevel, for (;;) { /* Check for user-requested abort or sleep */ - vacuum_delay_point(); + vacuum_delay_point(true); /* Fetch next row */ MemoryContextReset(tupcontext); @@ -1190,6 +1255,21 @@ file_acquire_sample_rows(Relation onerel, int elevel, if (!found) break; + if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE && + cstate->escontext->error_occurred) + { + /* + * Soft error occurred, skip this tuple and just make + * ErrorSaveContext ready for the next NextCopyFrom. Since we + * don't set details_wanted and error_data is not to be filled, + * just resetting error_occurred is enough. + */ + cstate->escontext->error_occurred = false; + + /* Repeat NextCopyFrom() until no soft error occurs */ + continue; + } + /* * The first targrows sample rows are simply copied into the * reservoir. Then we start replacing tuples in the sample until we @@ -1235,6 +1315,15 @@ file_acquire_sample_rows(Relation onerel, int elevel, /* Clean up. */ MemoryContextDelete(tupcontext); + if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE && + cstate->num_errors > 0 && + cstate->opts.log_verbosity >= COPY_LOG_VERBOSITY_DEFAULT) + ereport(NOTICE, + errmsg_plural("%" PRIu64 " row was skipped due to data type incompatibility", + "%" PRIu64 " rows were skipped due to data type incompatibility", + cstate->num_errors, + cstate->num_errors)); + EndCopyFrom(cstate); pfree(values); diff --git a/contrib/file_fdw/meson.build b/contrib/file_fdw/meson.build index f982196c2b74a..6db493b3dad66 100644 --- a/contrib/file_fdw/meson.build +++ b/contrib/file_fdw/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group file_fdw_sources = files( 'file_fdw.c', diff --git a/contrib/file_fdw/sql/file_fdw.sql b/contrib/file_fdw/sql/file_fdw.sql index f0548e14e1845..1a397ad4bd150 100644 --- a/contrib/file_fdw/sql/file_fdw.sql +++ b/contrib/file_fdw/sql/file_fdw.sql @@ -55,6 +55,8 @@ CREATE USER MAPPING FOR regress_file_fdw_superuser SERVER file_server; CREATE USER MAPPING FOR regress_no_priv_user SERVER file_server; -- validator tests +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (foo 'bar'); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS ("a=b" 'true'); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape ':'); -- ERROR @@ -77,6 +79,11 @@ CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', delimiter '); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'csv', null ' '); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (on_error 'unsupported'); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'binary', on_error 'ignore'); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (log_verbosity 'unsupported'); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (reject_limit '1'); -- ERROR +CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (on_error 'ignore', reject_limit '0'); -- ERROR CREATE FOREIGN TABLE tbl () SERVER file_server; -- ERROR \set filename :abs_srcdir '/data/agg.data' @@ -150,6 +157,17 @@ SELECT * FROM agg_csv c JOIN agg_text t ON (t.a = c.a) ORDER BY c.a; -- error context report tests SELECT * FROM agg_bad; -- ERROR +-- on_error, log_verbosity and reject_limit tests +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD on_error 'ignore'); +SELECT * FROM agg_bad; +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD log_verbosity 'silent'); +SELECT * FROM agg_bad; +ALTER FOREIGN TABLE agg_bad OPTIONS (ADD reject_limit '1'); -- ERROR +SELECT * FROM agg_bad; +ALTER FOREIGN TABLE agg_bad OPTIONS (SET reject_limit '2'); +SELECT * FROM agg_bad; +ANALYZE agg_bad; + -- misc query tests \t on SELECT explain_filter('EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM agg_csv'); diff --git a/contrib/fuzzystrmatch/daitch_mokotoff.c b/contrib/fuzzystrmatch/daitch_mokotoff.c index 8c050c6441b52..07f895ae2bf64 100644 --- a/contrib/fuzzystrmatch/daitch_mokotoff.c +++ b/contrib/fuzzystrmatch/daitch_mokotoff.c @@ -1,7 +1,7 @@ /* * Daitch-Mokotoff Soundex * - * Copyright (c) 2023-2024, PostgreSQL Global Development Group + * Copyright (c) 2023-2025, PostgreSQL Global Development Group * * This module was originally sponsored by Finance Norway / * Trafikkforsikringsforeningen, and implemented by Dag Lem diff --git a/contrib/fuzzystrmatch/daitch_mokotoff_header.pl b/contrib/fuzzystrmatch/daitch_mokotoff_header.pl index bb2827364edeb..ff190a33ee0cb 100755 --- a/contrib/fuzzystrmatch/daitch_mokotoff_header.pl +++ b/contrib/fuzzystrmatch/daitch_mokotoff_header.pl @@ -2,7 +2,7 @@ # # Generation of types and lookup tables for Daitch-Mokotoff soundex. # -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # This module was originally sponsored by Finance Norway / # Trafikkforsikringsforeningen, and implemented by Dag Lem @@ -58,7 +58,7 @@ /* * Constants and lookup tables for Daitch-Mokotoff Soundex * - * Copyright (c) 2023-2024, PostgreSQL Global Development Group + * Copyright (c) 2023-2025, PostgreSQL Global Development Group * * This file is generated by daitch_mokotoff_header.pl */ diff --git a/contrib/fuzzystrmatch/dmetaphone.c b/contrib/fuzzystrmatch/dmetaphone.c index f8f2c2b447d2b..6627b2b89433a 100644 --- a/contrib/fuzzystrmatch/dmetaphone.c +++ b/contrib/fuzzystrmatch/dmetaphone.c @@ -308,13 +308,13 @@ IsVowel(metastring *s, int pos) static int SlavoGermanic(metastring *s) { - if ((char *) strstr(s->str, "W")) + if (strstr(s->str, "W")) return 1; - else if ((char *) strstr(s->str, "K")) + else if (strstr(s->str, "K")) return 1; - else if ((char *) strstr(s->str, "CZ")) + else if (strstr(s->str, "CZ")) return 1; - else if ((char *) strstr(s->str, "WITZ")) + else if (strstr(s->str, "WITZ")) return 1; else return 0; diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c index 72ae2ab91b5a9..e7cc314b763ee 100644 --- a/contrib/fuzzystrmatch/fuzzystrmatch.c +++ b/contrib/fuzzystrmatch/fuzzystrmatch.c @@ -6,7 +6,7 @@ * Joe Conway * * contrib/fuzzystrmatch/fuzzystrmatch.c - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * ALL RIGHTS RESERVED; * * metaphone() @@ -40,12 +40,14 @@ #include -#include "mb/pg_wchar.h" #include "utils/builtins.h" #include "utils/varlena.h" #include "varatt.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "fuzzystrmatch", + .version = PG_VERSION +); /* * Soundex diff --git a/contrib/fuzzystrmatch/meson.build b/contrib/fuzzystrmatch/meson.build index 299b2fa9cb4fd..f52daa4ea1cff 100644 --- a/contrib/fuzzystrmatch/meson.build +++ b/contrib/fuzzystrmatch/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group fuzzystrmatch_sources = files( 'daitch_mokotoff.c', diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index 2125436e40cde..4f867e4bd1f1c 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -21,7 +21,10 @@ #include "utils/memutils.h" #include "utils/typcache.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "hstore", + .version = PG_VERSION +); /* old names for C functions */ HSTORE_POLLUTE(hstore_from_text, tconvert); diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c index 0d4ec16d1e540..5e57eceffc817 100644 --- a/contrib/hstore/hstore_op.c +++ b/contrib/hstore/hstore_op.c @@ -858,7 +858,7 @@ setup_firstcall(FuncCallContext *funcctx, HStore *hs, st = (HStore *) palloc(VARSIZE(hs)); memcpy(st, hs, VARSIZE(hs)); - funcctx->user_fctx = (void *) st; + funcctx->user_fctx = st; if (fcinfo) { diff --git a/contrib/hstore/hstore_subs.c b/contrib/hstore/hstore_subs.c index 1443d8634b299..3d03f66fa0dfb 100644 --- a/contrib/hstore/hstore_subs.c +++ b/contrib/hstore/hstore_subs.c @@ -12,7 +12,7 @@ * check_subscripts function and just let the fetch and assign functions * do everything. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/contrib/hstore/meson.build b/contrib/hstore/meson.build index 544310a2977fc..39622d1024de6 100644 --- a/contrib/hstore/meson.build +++ b/contrib/hstore/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # .. so that includes of hstore/hstore.h work hstore_inc = include_directories('.', '../') diff --git a/contrib/hstore_plperl/hstore_plperl--1.0.sql b/contrib/hstore_plperl/hstore_plperl--1.0.sql index af743c8733508..2837f3719f088 100644 --- a/contrib/hstore_plperl/hstore_plperl--1.0.sql +++ b/contrib/hstore_plperl/hstore_plperl--1.0.sql @@ -7,11 +7,11 @@ CREATE FUNCTION hstore_to_plperl(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME'; -CREATE FUNCTION plperl_to_hstore(val internal) RETURNS hstore +CREATE FUNCTION plperl_to_hstore(val internal) RETURNS @extschema:hstore@.hstore LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME'; -CREATE TRANSFORM FOR hstore LANGUAGE plperl ( +CREATE TRANSFORM FOR @extschema:hstore@.hstore LANGUAGE plperl ( FROM SQL WITH FUNCTION hstore_to_plperl(internal), TO SQL WITH FUNCTION plperl_to_hstore(internal) ); diff --git a/contrib/hstore_plperl/hstore_plperl.c b/contrib/hstore_plperl/hstore_plperl.c index 4a1629cad512e..31393b4fa504d 100644 --- a/contrib/hstore_plperl/hstore_plperl.c +++ b/contrib/hstore_plperl/hstore_plperl.c @@ -4,7 +4,10 @@ #include "hstore/hstore.h" #include "plperl.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "hstore_plperl", + .version = PG_VERSION +); /* Linkage to functions in hstore module */ typedef HStore *(*hstoreUpgrade_t) (Datum orig); diff --git a/contrib/hstore_plperl/hstore_plperlu--1.0.sql b/contrib/hstore_plperl/hstore_plperlu--1.0.sql index 7c3bc86eba965..7f3119a7b2e91 100644 --- a/contrib/hstore_plperl/hstore_plperlu--1.0.sql +++ b/contrib/hstore_plperl/hstore_plperlu--1.0.sql @@ -7,11 +7,11 @@ CREATE FUNCTION hstore_to_plperlu(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME', 'hstore_to_plperl'; -CREATE FUNCTION plperlu_to_hstore(val internal) RETURNS hstore +CREATE FUNCTION plperlu_to_hstore(val internal) RETURNS @extschema:hstore@.hstore LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME', 'plperl_to_hstore'; -CREATE TRANSFORM FOR hstore LANGUAGE plperlu ( +CREATE TRANSFORM FOR @extschema:hstore@.hstore LANGUAGE plperlu ( FROM SQL WITH FUNCTION hstore_to_plperlu(internal), TO SQL WITH FUNCTION plperlu_to_hstore(internal) ); diff --git a/contrib/hstore_plperl/meson.build b/contrib/hstore_plperl/meson.build index 0da6c7dab047d..60b8ad23569b9 100644 --- a/contrib/hstore_plperl/meson.build +++ b/contrib/hstore_plperl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not perl_dep.found() subdir_done() diff --git a/contrib/hstore_plpython/hstore_plpython.c b/contrib/hstore_plpython/hstore_plpython.c index 310f63c30d481..e2bfc6da38e18 100644 --- a/contrib/hstore_plpython/hstore_plpython.c +++ b/contrib/hstore_plpython/hstore_plpython.c @@ -3,9 +3,12 @@ #include "fmgr.h" #include "hstore/hstore.h" #include "plpy_typeio.h" -#include "plpython.h" +#include "plpy_util.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "hstore_plpython", + .version = PG_VERSION +); /* Linkage to functions in plpython module */ typedef char *(*PLyObject_AsString_t) (PyObject *plrv); diff --git a/contrib/hstore_plpython/hstore_plpython3u--1.0.sql b/contrib/hstore_plpython/hstore_plpython3u--1.0.sql index 0b410ab18354c..3508232241684 100644 --- a/contrib/hstore_plpython/hstore_plpython3u--1.0.sql +++ b/contrib/hstore_plpython/hstore_plpython3u--1.0.sql @@ -7,13 +7,13 @@ CREATE FUNCTION hstore_to_plpython3(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME', 'hstore_to_plpython'; -CREATE FUNCTION plpython3_to_hstore(val internal) RETURNS hstore +CREATE FUNCTION plpython3_to_hstore(val internal) RETURNS @extschema:hstore@.hstore LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME', 'plpython_to_hstore'; -CREATE TRANSFORM FOR hstore LANGUAGE plpython3u ( +CREATE TRANSFORM FOR @extschema:hstore@.hstore LANGUAGE plpython3u ( FROM SQL WITH FUNCTION hstore_to_plpython3(internal), TO SQL WITH FUNCTION plpython3_to_hstore(internal) ); -COMMENT ON TRANSFORM FOR hstore LANGUAGE plpython3u IS 'transform between hstore and Python dict'; +COMMENT ON TRANSFORM FOR @extschema:hstore@.hstore LANGUAGE plpython3u IS 'transform between hstore and Python dict'; diff --git a/contrib/hstore_plpython/meson.build b/contrib/hstore_plpython/meson.build index fd6f755e4a3ad..ea8e20a377be4 100644 --- a/contrib/hstore_plpython/meson.build +++ b/contrib/hstore_plpython/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not python3_dep.found() subdir_done() diff --git a/contrib/intagg/meson.build b/contrib/intagg/meson.build index b3cb6217e2636..0978c86dc5bde 100644 --- a/contrib/intagg/meson.build +++ b/contrib/intagg/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group install_data( 'intagg.control', diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h index 0352cbd36826b..ab899a81b4f49 100644 --- a/contrib/intarray/_int.h +++ b/contrib/intarray/_int.h @@ -41,17 +41,17 @@ typedef struct #define SORT(x) \ do { \ int _nelems_ = ARRNELEMS(x); \ - if (_nelems_ > 1) \ - isort(ARRPTR(x), _nelems_); \ + bool _ascending = true; \ + isort(ARRPTR(x), _nelems_, &_ascending); \ } while(0) /* sort the elements of the array and remove duplicates */ #define PREPAREARR(x) \ do { \ int _nelems_ = ARRNELEMS(x); \ - if (_nelems_ > 1) \ - if (isort(ARRPTR(x), _nelems_)) \ - (x) = _int_unique(x); \ + bool _ascending = true; \ + isort(ARRPTR(x), _nelems_, &_ascending); \ + (x) = _int_unique(x); \ } while(0) /* "wish" function */ @@ -109,7 +109,7 @@ typedef struct /* * useful functions */ -bool isort(int32 *a, int len); +void isort(int32 *a, size_t len, void *arg); ArrayType *new_intArrayType(int num); ArrayType *copy_intArrayType(ArrayType *a); ArrayType *resize_intArrayType(ArrayType *a, int num); @@ -176,16 +176,12 @@ bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot); bool gin_bool_consistent(QUERYTYPE *query, bool *check); bool query_has_required_values(QUERYTYPE *query); -int compASC(const void *a, const void *b); -int compDESC(const void *a, const void *b); - /* sort, either ascending or descending */ #define QSORT(a, direction) \ do { \ int _nelems_ = ARRNELEMS(a); \ - if (_nelems_ > 1) \ - qsort((void*) ARRPTR(a), _nelems_, sizeof(int32), \ - (direction) ? compASC : compDESC ); \ + bool _ascending = (direction) ? true : false; \ + isort(ARRPTR(a), _nelems_, &_ascending); \ } while(0) #endif /* ___INT_H__ */ diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c index 8fc6ad87fc754..2b2c3f4029ec5 100644 --- a/contrib/intarray/_int_bool.c +++ b/contrib/intarray/_int_bool.c @@ -5,7 +5,6 @@ #include "_int.h" #include "miscadmin.h" -#include "utils/builtins.h" PG_FUNCTION_INFO_V1(bqarr_in); PG_FUNCTION_INFO_V1(bqarr_out); @@ -299,7 +298,7 @@ bool signconsistent(QUERYTYPE *query, BITVECP sign, int siglen, bool calcnot) { return execute(GETQUERY(query) + query->size - 1, - (void *) sign, (void *) (intptr_t) siglen, calcnot, + sign, (void *) (intptr_t) siglen, calcnot, checkcondition_bit); } @@ -313,7 +312,7 @@ execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot) chkval.arrb = ARRPTR(array); chkval.arre = chkval.arrb + ARRNELEMS(array); return execute(GETQUERY(query) + query->size - 1, - (void *) &chkval, NULL, calcnot, + &chkval, NULL, calcnot, checkcondition_arr); } @@ -355,7 +354,7 @@ gin_bool_consistent(QUERYTYPE *query, bool *check) } return execute(GETQUERY(query) + query->size - 1, - (void *) &gcv, NULL, true, + &gcv, NULL, true, checkcondition_gin); } diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c index 5b164f6788fb4..ba6d0a99995ed 100644 --- a/contrib/intarray/_int_op.c +++ b/contrib/intarray/_int_op.c @@ -5,7 +5,10 @@ #include "_int.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "intarray", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(_int_different); PG_FUNCTION_INFO_V1(_int_same); diff --git a/contrib/intarray/_int_selfuncs.c b/contrib/intarray/_int_selfuncs.c index bc1ad3a80487f..6c3b7ace146aa 100644 --- a/contrib/intarray/_int_selfuncs.c +++ b/contrib/intarray/_int_selfuncs.c @@ -3,7 +3,7 @@ * _int_selfuncs.c * Functions for selectivity estimation of intarray operators * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -20,10 +20,9 @@ #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "miscadmin.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" #include "utils/selfuncs.h" -#include "utils/syscache.h" PG_FUNCTION_INFO_V1(_int_overlap_sel); PG_FUNCTION_INFO_V1(_int_contains_sel); diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c index c85280c8422c4..0d0cdc289cde7 100644 --- a/contrib/intarray/_int_tool.c +++ b/contrib/intarray/_int_tool.c @@ -186,36 +186,38 @@ rt__int_size(ArrayType *a, float *size) *size = (float) ARRNELEMS(a); } -/* qsort_arg comparison function for isort() */ -static int +/* comparison function for isort() and _int_unique() */ +static inline int isort_cmp(const void *a, const void *b, void *arg) { int32 aval = *((const int32 *) a); int32 bval = *((const int32 *) b); - if (aval < bval) - return -1; - if (aval > bval) - return 1; - - /* - * Report if we have any duplicates. If there are equal keys, qsort must - * compare them at some point, else it wouldn't know whether one should go - * before or after the other. - */ - *((bool *) arg) = true; + if (*((bool *) arg)) + { + /* compare for ascending order */ + if (aval < bval) + return -1; + if (aval > bval) + return 1; + } + else + { + if (aval > bval) + return -1; + if (aval < bval) + return 1; + } return 0; } -/* Sort the given data (len >= 2). Return true if any duplicates found */ -bool -isort(int32 *a, int len) -{ - bool r = false; - - qsort_arg(a, len, sizeof(int32), isort_cmp, &r); - return r; -} +#define ST_SORT isort +#define ST_ELEMENT_TYPE int32 +#define ST_COMPARE(a, b, ascending) isort_cmp(a, b, ascending) +#define ST_COMPARE_ARG_TYPE void +#define ST_SCOPE +#define ST_DEFINE +#include "lib/sort_template.h" /* Create a new int array with room for "num" elements */ ArrayType * @@ -311,10 +313,10 @@ ArrayType * _int_unique(ArrayType *r) { int num = ARRNELEMS(r); - bool duplicates_found; /* not used */ + bool ascending = true; num = qunique_arg(ARRPTR(r), num, sizeof(int), isort_cmp, - &duplicates_found); + &ascending); return resize_intArrayType(r, num); } @@ -393,15 +395,3 @@ int_to_intset(int32 elem) aa[0] = elem; return result; } - -int -compASC(const void *a, const void *b) -{ - return pg_cmp_s32(*(const int32 *) a, *(const int32 *) b); -} - -int -compDESC(const void *a, const void *b) -{ - return pg_cmp_s32(*(const int32 *) b, *(const int32 *) a); -} diff --git a/contrib/intarray/bench/bench.pl b/contrib/intarray/bench/bench.pl index 1c728a2762b12..dfad66baea4a1 100755 --- a/contrib/intarray/bench/bench.pl +++ b/contrib/intarray/bench/bench.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/contrib/intarray/bench/create_test.pl b/contrib/intarray/bench/create_test.pl index fc540001fc00b..ed8132b088893 100755 --- a/contrib/intarray/bench/create_test.pl +++ b/contrib/intarray/bench/create_test.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # contrib/intarray/bench/create_test.pl diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out index b39ab82d43d50..d0e68d0447fb7 100644 --- a/contrib/intarray/expected/_int.out +++ b/contrib/intarray/expected/_int.out @@ -492,6 +492,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + SET enable_seqscan = off; -- not all of these would use index by default CREATE INDEX text_idx on test__int using gist ( a gist__int_ops ); SELECT count(*) from test__int WHERE a && '{23,50}'; @@ -566,6 +572,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail ERROR: input array is too big (199 maximum allowed, 1001 current), use gist__intbig_ops opclass instead DROP INDEX text_idx; @@ -648,6 +660,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0)); ERROR: value 0 out of bounds for option "siglen" @@ -728,6 +746,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops ); SELECT count(*) from test__int WHERE a && '{23,50}'; @@ -802,6 +826,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gin ( a gin__int_ops ); SELECT count(*) from test__int WHERE a && '{23,50}'; @@ -876,6 +906,12 @@ SELECT count(*) from test__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + DROP INDEX text_idx; -- Repeat the same queries with an extended data set. The data set is the -- same that we used before, except that each element in the array is @@ -968,4 +1004,10 @@ SELECT count(*) from more__int WHERE a @@ '!20 & !21'; 6344 (1 row) +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; + count +------- + 12 +(1 row) + RESET enable_seqscan; diff --git a/contrib/intarray/meson.build b/contrib/intarray/meson.build index 5d4609ebc6e28..fae9add981dc6 100644 --- a/contrib/intarray/meson.build +++ b/contrib/intarray/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group intarray_sources = files( '_int_bool.c', diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql index 2d4ed1c9ae24f..5668ab4070453 100644 --- a/contrib/intarray/sql/_int.sql +++ b/contrib/intarray/sql/_int.sql @@ -107,6 +107,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; SET enable_seqscan = off; -- not all of these would use index by default @@ -124,6 +125,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; INSERT INTO test__int SELECT array(SELECT x FROM generate_series(1, 1001) x); -- should fail @@ -144,6 +146,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gist (a gist__intbig_ops(siglen = 0)); @@ -162,6 +165,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops ); @@ -178,6 +182,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; DROP INDEX text_idx; CREATE INDEX text_idx on test__int using gin ( a gin__int_ops ); @@ -194,6 +199,7 @@ SELECT count(*) from test__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from test__int WHERE a @@ '20 | !21'; SELECT count(*) from test__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; DROP INDEX text_idx; @@ -229,6 +235,7 @@ SELECT count(*) from more__int WHERE a @> '{20,23}' or a @> '{50,68}'; SELECT count(*) from more__int WHERE a @@ '(20&23)|(50&68)'; SELECT count(*) from more__int WHERE a @@ '20 | !21'; SELECT count(*) from more__int WHERE a @@ '!20 & !21'; +SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)'; RESET enable_seqscan; diff --git a/contrib/isn/Makefile b/contrib/isn/Makefile index 1037506c70564..bfe8977bb648d 100644 --- a/contrib/isn/Makefile +++ b/contrib/isn/Makefile @@ -3,8 +3,8 @@ MODULES = isn EXTENSION = isn -DATA = isn--1.1.sql isn--1.1--1.2.sql \ - isn--1.0--1.1.sql +DATA = isn--1.0--1.1.sql isn--1.1.sql \ + isn--1.1--1.2.sql isn--1.2--1.3.sql PGFILEDESC = "isn - data types for international product numbering standards" # the other .h files are data tables, we don't install those diff --git a/contrib/isn/expected/isn.out b/contrib/isn/expected/isn.out index 2f05b7eb861ac..c533768d926c8 100644 --- a/contrib/isn/expected/isn.out +++ b/contrib/isn/expected/isn.out @@ -279,6 +279,50 @@ FROM (VALUES ('9780123456786', 'UPC'), 9771234567003 | ISSN | t | | | | (3 rows) +-- +-- test weak mode +-- +SELECT '2222222222221'::ean13; -- fail +ERROR: invalid check digit for EAN13 number: "2222222222221", should be 2 +LINE 1: SELECT '2222222222221'::ean13; + ^ +SET isn.weak TO TRUE; +SELECT '2222222222221'::ean13; + ean13 +------------------ + 222-222222222-2! +(1 row) + +SELECT is_valid('2222222222221'::ean13); + is_valid +---------- + f +(1 row) + +SELECT make_valid('2222222222221'::ean13); + make_valid +----------------- + 222-222222222-2 +(1 row) + +SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC + isn_weak +---------- + t +(1 row) + +SELECT isn_weak(false); + isn_weak +---------- + f +(1 row) + +SHOW isn.weak; + isn.weak +---------- + off +(1 row) + -- -- cleanup -- diff --git a/contrib/isn/isn--1.2--1.3.sql b/contrib/isn/isn--1.2--1.3.sql new file mode 100644 index 0000000000000..a8e30ff44fbfd --- /dev/null +++ b/contrib/isn/isn--1.2--1.3.sql @@ -0,0 +1,7 @@ +/* contrib/isn/isn--1.2--1.3.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION isn UPDATE TO '1.3'" to load this file. \quit + +ALTER FUNCTION isn_weak(boolean) VOLATILE PARALLEL UNSAFE; +ALTER FUNCTION isn_weak() STABLE PARALLEL SAFE; diff --git a/contrib/isn/isn.c b/contrib/isn/isn.c index 71a543b9478b6..038c8ed4db7bd 100644 --- a/contrib/isn/isn.c +++ b/contrib/isn/isn.c @@ -4,7 +4,7 @@ * PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC) * * Author: German Mendez Bravo (Kronuz) - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/isn/isn.c @@ -21,9 +21,12 @@ #include "UPC.h" #include "fmgr.h" #include "isn.h" -#include "utils/builtins.h" +#include "utils/guc.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "isn", + .version = PG_VERSION +); #ifdef USE_ASSERT_CHECKING #define ISN_DEBUG 1 @@ -40,6 +43,7 @@ enum isn_type static const char *const isn_names[] = {"EAN13/UPC/ISxN", "EAN13/UPC/ISxN", "EAN13", "ISBN", "ISMN", "ISSN", "UPC"}; +/* GUC value */ static bool g_weak = false; @@ -930,6 +934,20 @@ _PG_init(void) if (!check_table(UPC_range, UPC_index)) elog(ERROR, "UPC failed check"); } + + /* Define a GUC variable for weak mode. */ + DefineCustomBoolVariable("isn.weak", + "Accept input with invalid ISN check digits.", + NULL, + &g_weak, + false, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); + + MarkGUCPrefixReserved("isn"); } /* isn_out @@ -1110,17 +1128,16 @@ make_valid(PG_FUNCTION_ARGS) /* this function temporarily sets weak input flag * (to lose the strictness of check digit acceptance) - * It's a helper function, not intended to be used!! */ PG_FUNCTION_INFO_V1(accept_weak_input); Datum accept_weak_input(PG_FUNCTION_ARGS) { -#ifdef ISN_WEAK_MODE - g_weak = PG_GETARG_BOOL(0); -#else - /* function has no effect */ -#endif /* ISN_WEAK_MODE */ + bool newvalue = PG_GETARG_BOOL(0); + + (void) set_config_option("isn.weak", newvalue ? "on" : "off", + PGC_USERSET, PGC_S_SESSION, + GUC_ACTION_SET, true, 0, false); PG_RETURN_BOOL(g_weak); } diff --git a/contrib/isn/isn.control b/contrib/isn/isn.control index 1cb5e2b234036..e7daea52b8451 100644 --- a/contrib/isn/isn.control +++ b/contrib/isn/isn.control @@ -1,6 +1,6 @@ # isn extension comment = 'data types for international product numbering standards' -default_version = '1.2' +default_version = '1.3' module_pathname = '$libdir/isn' relocatable = true trusted = true diff --git a/contrib/isn/isn.h b/contrib/isn/isn.h index 2b499bcf3389a..399896ad417c0 100644 --- a/contrib/isn/isn.h +++ b/contrib/isn/isn.h @@ -4,7 +4,7 @@ * PostgreSQL type definitions for ISNs (ISBN, ISMN, ISSN, EAN13, UPC) * * Author: German Mendez Bravo (Kronuz) - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/isn/isn.h @@ -18,7 +18,6 @@ #include "fmgr.h" #undef ISN_DEBUG -#define ISN_WEAK_MODE /* * uint64 is the internal storage format for ISNs. diff --git a/contrib/isn/meson.build b/contrib/isn/meson.build index abe83265573ba..39cf781684eee 100644 --- a/contrib/isn/meson.build +++ b/contrib/isn/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group isn_sources = files( 'isn.c', @@ -19,8 +19,9 @@ contrib_targets += isn install_data( 'isn.control', 'isn--1.0--1.1.sql', - 'isn--1.1--1.2.sql', 'isn--1.1.sql', + 'isn--1.1--1.2.sql', + 'isn--1.2--1.3.sql', kwargs: contrib_data_args, ) diff --git a/contrib/isn/sql/isn.sql b/contrib/isn/sql/isn.sql index 2c2ea077d1e14..043e5580b0d36 100644 --- a/contrib/isn/sql/isn.sql +++ b/contrib/isn/sql/isn.sql @@ -120,6 +120,19 @@ FROM (VALUES ('9780123456786', 'UPC'), AS a(str,typ), LATERAL pg_input_error_info(a.str, a.typ) as errinfo; +-- +-- test weak mode +-- +SELECT '2222222222221'::ean13; -- fail +SET isn.weak TO TRUE; +SELECT '2222222222221'::ean13; +SELECT is_valid('2222222222221'::ean13); +SELECT make_valid('2222222222221'::ean13); + +SELECT isn_weak(); -- backwards-compatibility wrappers for accessing the GUC +SELECT isn_weak(false); +SHOW isn.weak; + -- -- cleanup -- diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c index 2af1e0c02afd3..c02e2d41af108 100644 --- a/contrib/jsonb_plperl/jsonb_plperl.c +++ b/contrib/jsonb_plperl/jsonb_plperl.c @@ -7,7 +7,10 @@ #include "utils/fmgrprotos.h" #include "utils/jsonb.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "jsonb_plperl", + .version = PG_VERSION +); static SV *Jsonb_to_SV(JsonbContainer *jsonb); static JsonbValue *SV_to_JsonbValue(SV *obj, JsonbParseState **ps, bool is_elem); diff --git a/contrib/jsonb_plperl/meson.build b/contrib/jsonb_plperl/meson.build index c36de6481c2eb..95a9a7bc08242 100644 --- a/contrib/jsonb_plperl/meson.build +++ b/contrib/jsonb_plperl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not perl_dep.found() subdir_done() diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c index a625727c5e8ca..9383615abbfa3 100644 --- a/contrib/jsonb_plpython/jsonb_plpython.c +++ b/contrib/jsonb_plpython/jsonb_plpython.c @@ -2,12 +2,15 @@ #include "plpy_elog.h" #include "plpy_typeio.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/fmgrprotos.h" #include "utils/jsonb.h" #include "utils/numeric.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "jsonb_plpython", + .version = PG_VERSION +); /* for PLyObject_AsString in plpy_typeio.c */ typedef char *(*PLyObject_AsString_t) (PyObject *plrv); diff --git a/contrib/jsonb_plpython/meson.build b/contrib/jsonb_plpython/meson.build index 0503e952f0e5f..5fe80483e587c 100644 --- a/contrib/jsonb_plpython/meson.build +++ b/contrib/jsonb_plpython/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not python3_dep.found() subdir_done() diff --git a/contrib/lo/Makefile b/contrib/lo/Makefile index 716893859eb51..8cfff63d882a2 100644 --- a/contrib/lo/Makefile +++ b/contrib/lo/Makefile @@ -3,7 +3,7 @@ MODULES = lo EXTENSION = lo -DATA = lo--1.1.sql lo--1.0--1.1.sql +DATA = lo--1.1.sql lo--1.0--1.1.sql lo--1.1--1.2.sql PGFILEDESC = "lo - management for large objects" REGRESS = lo diff --git a/contrib/lo/expected/lo.out b/contrib/lo/expected/lo.out index c63e4b1c704fb..2c9c07f783092 100644 --- a/contrib/lo/expected/lo.out +++ b/contrib/lo/expected/lo.out @@ -47,4 +47,79 @@ SELECT lo_get(43214); DELETE FROM image; SELECT lo_get(43214); ERROR: large object 43214 does not exist +-- Now let's try it with an AFTER trigger +DROP TRIGGER t_raster ON image; +CREATE CONSTRAINT TRIGGER t_raster AFTER UPDATE OR DELETE ON image + DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW EXECUTE PROCEDURE lo_manage(raster); +SELECT lo_create(43223); + lo_create +----------- + 43223 +(1 row) + +SELECT lo_create(43224); + lo_create +----------- + 43224 +(1 row) + +SELECT lo_create(43225); + lo_create +----------- + 43225 +(1 row) + +INSERT INTO image (title, raster) VALUES ('beautiful image', 43223); +SELECT lo_get(43223); + lo_get +-------- + \x +(1 row) + +UPDATE image SET raster = 43224 WHERE title = 'beautiful image'; +SELECT lo_get(43223); -- gone +ERROR: large object 43223 does not exist +SELECT lo_get(43224); + lo_get +-------- + \x +(1 row) + +-- test updating of unrelated column +UPDATE image SET title = 'beautiful picture' WHERE title = 'beautiful image'; +SELECT lo_get(43224); + lo_get +-------- + \x +(1 row) + +-- this case used to be buggy +BEGIN; +UPDATE image SET title = 'beautiful image' WHERE title = 'beautiful picture'; +UPDATE image SET raster = 43225 WHERE title = 'beautiful image'; +SELECT lo_get(43224); + lo_get +-------- + \x +(1 row) + +COMMIT; +SELECT lo_get(43224); -- gone +ERROR: large object 43224 does not exist +SELECT lo_get(43225); + lo_get +-------- + \x +(1 row) + +DELETE FROM image; +SELECT lo_get(43225); -- gone +ERROR: large object 43225 does not exist +SELECT lo_oid(1::lo); + lo_oid +-------- + 1 +(1 row) + DROP TABLE image; diff --git a/contrib/lo/lo--1.1--1.2.sql b/contrib/lo/lo--1.1--1.2.sql new file mode 100644 index 0000000000000..a480923a3a684 --- /dev/null +++ b/contrib/lo/lo--1.1--1.2.sql @@ -0,0 +1,8 @@ +/* contrib/lo/lo--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION lo UPDATE TO '1.2'" to load this file. \quit + +CREATE OR REPLACE FUNCTION lo_oid(lo) RETURNS pg_catalog.oid +LANGUAGE SQL STRICT IMMUTABLE PARALLEL SAFE +RETURN (SELECT $1::pg_catalog.oid); diff --git a/contrib/lo/lo.c b/contrib/lo/lo.c index 457be26c4edfe..f9348a16b6608 100644 --- a/contrib/lo/lo.c +++ b/contrib/lo/lo.c @@ -9,10 +9,13 @@ #include "commands/trigger.h" #include "executor/spi.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "lo", + .version = PG_VERSION +); /* diff --git a/contrib/lo/lo.control b/contrib/lo/lo.control index f73f8b5fae5e7..3acb3665a4e16 100644 --- a/contrib/lo/lo.control +++ b/contrib/lo/lo.control @@ -1,6 +1,6 @@ # lo extension comment = 'Large Object maintenance' -default_version = '1.1' +default_version = '1.2' module_pathname = '$libdir/lo' relocatable = true trusted = true diff --git a/contrib/lo/meson.build b/contrib/lo/meson.build index 4cc72b64578cb..2d78907ba12a8 100644 --- a/contrib/lo/meson.build +++ b/contrib/lo/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group lo_sources = files( 'lo.c', @@ -20,6 +20,7 @@ install_data( 'lo.control', 'lo--1.0--1.1.sql', 'lo--1.1.sql', + 'lo--1.1--1.2.sql', kwargs: contrib_data_args, ) diff --git a/contrib/lo/sql/lo.sql b/contrib/lo/sql/lo.sql index 7703950924508..d1a9d7cf25540 100644 --- a/contrib/lo/sql/lo.sql +++ b/contrib/lo/sql/lo.sql @@ -27,4 +27,47 @@ DELETE FROM image; SELECT lo_get(43214); +-- Now let's try it with an AFTER trigger + +DROP TRIGGER t_raster ON image; + +CREATE CONSTRAINT TRIGGER t_raster AFTER UPDATE OR DELETE ON image + DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW EXECUTE PROCEDURE lo_manage(raster); + +SELECT lo_create(43223); +SELECT lo_create(43224); +SELECT lo_create(43225); + +INSERT INTO image (title, raster) VALUES ('beautiful image', 43223); + +SELECT lo_get(43223); + +UPDATE image SET raster = 43224 WHERE title = 'beautiful image'; + +SELECT lo_get(43223); -- gone +SELECT lo_get(43224); + +-- test updating of unrelated column +UPDATE image SET title = 'beautiful picture' WHERE title = 'beautiful image'; + +SELECT lo_get(43224); + +-- this case used to be buggy +BEGIN; +UPDATE image SET title = 'beautiful image' WHERE title = 'beautiful picture'; +UPDATE image SET raster = 43225 WHERE title = 'beautiful image'; +SELECT lo_get(43224); +COMMIT; + +SELECT lo_get(43224); -- gone +SELECT lo_get(43225); + +DELETE FROM image; + +SELECT lo_get(43225); -- gone + + +SELECT lo_oid(1::lo); + DROP TABLE image; diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c index e89a39a5b5f25..286ad24fbe847 100644 --- a/contrib/ltree/_ltree_gist.c +++ b/contrib/ltree/_ltree_gist.c @@ -506,7 +506,7 @@ Datum _ltree_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - void *query = (void *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + void *query = PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c index 2fdb5ea97bf40..b4a8097328d3a 100644 --- a/contrib/ltree/_ltree_op.c +++ b/contrib/ltree/_ltree_op.c @@ -73,7 +73,7 @@ _ltree_isparent(PG_FUNCTION_ARGS) { ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE_P(1); - bool res = array_iterator(la, ltree_isparent, (void *) query, NULL); + bool res = array_iterator(la, ltree_isparent, query, NULL); PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -94,7 +94,7 @@ _ltree_risparent(PG_FUNCTION_ARGS) { ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltree *query = PG_GETARG_LTREE_P(1); - bool res = array_iterator(la, ltree_risparent, (void *) query, NULL); + bool res = array_iterator(la, ltree_risparent, query, NULL); PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -115,7 +115,7 @@ _ltq_regex(PG_FUNCTION_ARGS) { ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); lquery *query = PG_GETARG_LQUERY_P(1); - bool res = array_iterator(la, ltq_regex, (void *) query, NULL); + bool res = array_iterator(la, ltq_regex, query, NULL); PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -151,7 +151,7 @@ _lt_q_regex(PG_FUNCTION_ARGS) while (num > 0) { - if (array_iterator(_tree, ltq_regex, (void *) query, NULL)) + if (array_iterator(_tree, ltq_regex, query, NULL)) { res = true; break; @@ -180,7 +180,7 @@ _ltxtq_exec(PG_FUNCTION_ARGS) { ArrayType *la = PG_GETARG_ARRAYTYPE_P(0); ltxtquery *query = PG_GETARG_LTXTQUERY_P(1); - bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL); + bool res = array_iterator(la, ltxtq_exec, query, NULL); PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -205,7 +205,7 @@ _ltree_extract_isparent(PG_FUNCTION_ARGS) ltree *found, *item; - if (!array_iterator(la, ltree_isparent, (void *) query, &found)) + if (!array_iterator(la, ltree_isparent, query, &found)) { PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -228,7 +228,7 @@ _ltree_extract_risparent(PG_FUNCTION_ARGS) ltree *found, *item; - if (!array_iterator(la, ltree_risparent, (void *) query, &found)) + if (!array_iterator(la, ltree_risparent, query, &found)) { PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -251,7 +251,7 @@ _ltq_extract_regex(PG_FUNCTION_ARGS) ltree *found, *item; - if (!array_iterator(la, ltq_regex, (void *) query, &found)) + if (!array_iterator(la, ltq_regex, query, &found)) { PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); @@ -274,7 +274,7 @@ _ltxtq_extract_exec(PG_FUNCTION_ARGS) ltree *found, *item; - if (!array_iterator(la, ltxtq_exec, (void *) query, &found)) + if (!array_iterator(la, ltxtq_exec, query, &found)) { PG_FREE_IF_COPY(la, 0); PG_FREE_IF_COPY(query, 1); diff --git a/contrib/ltree/ltree_io.c b/contrib/ltree/ltree_io.c index 0a12c77a621f8..b54a15d6c685e 100644 --- a/contrib/ltree/ltree_io.c +++ b/contrib/ltree/ltree_io.c @@ -10,7 +10,6 @@ #include "crc32.h" #include "libpq/pqformat.h" #include "ltree.h" -#include "utils/memutils.h" #include "varatt.h" @@ -412,7 +411,7 @@ parse_lquery(const char *buf, struct Node *escontext) case LQPRS_WAITFNUM: if (t_iseq(ptr, ',')) state = LQPRS_WAITSNUM; - else if (t_isdigit(ptr)) + else if (isdigit((unsigned char) *ptr)) { int low = atoi(ptr); @@ -430,7 +429,7 @@ parse_lquery(const char *buf, struct Node *escontext) UNCHAR; break; case LQPRS_WAITSNUM: - if (t_isdigit(ptr)) + if (isdigit((unsigned char) *ptr)) { int high = atoi(ptr); @@ -461,7 +460,7 @@ parse_lquery(const char *buf, struct Node *escontext) case LQPRS_WAITCLOSE: if (t_iseq(ptr, '}')) state = LQPRS_WAITEND; - else if (!t_isdigit(ptr)) + else if (!isdigit((unsigned char) *ptr)) UNCHAR; break; case LQPRS_WAITND: @@ -472,7 +471,7 @@ parse_lquery(const char *buf, struct Node *escontext) } else if (t_iseq(ptr, ',')) state = LQPRS_WAITSNUM; - else if (!t_isdigit(ptr)) + else if (!isdigit((unsigned char) *ptr)) UNCHAR; break; case LQPRS_WAITEND: diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c index 24a21d3ea0173..ce9f4caad4feb 100644 --- a/contrib/ltree/ltree_op.c +++ b/contrib/ltree/ltree_op.c @@ -7,15 +7,16 @@ #include -#include "access/htup_details.h" -#include "catalog/pg_statistic.h" #include "common/hashfn.h" #include "ltree.h" #include "utils/builtins.h" -#include "utils/lsyscache.h" #include "utils/selfuncs.h" +#include "varatt.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "ltree", + .version = PG_VERSION +); /* compare functions */ PG_FUNCTION_INFO_V1(ltree_cmp); diff --git a/contrib/ltree/ltxtquery_io.c b/contrib/ltree/ltxtquery_io.c index 121fc55e469ea..ec331607793a7 100644 --- a/contrib/ltree/ltxtquery_io.c +++ b/contrib/ltree/ltxtquery_io.c @@ -88,7 +88,7 @@ gettoken_query(QPRS_STATE *state, int32 *val, int32 *lenval, char **strval, uint *lenval = charlen; *flag = 0; } - else if (!t_isspace(state->buf)) + else if (!isspace((unsigned char) *state->buf)) ereturn(state->escontext, ERR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("operand syntax error"))); @@ -410,7 +410,7 @@ ltxtq_in(PG_FUNCTION_ARGS) { ltxtquery *res; - if ((res = queryin((char *) PG_GETARG_POINTER(0), fcinfo->context)) == NULL) + if ((res = queryin(PG_GETARG_POINTER(0), fcinfo->context)) == NULL) PG_RETURN_NULL(); PG_RETURN_POINTER(res); } diff --git a/contrib/ltree/meson.build b/contrib/ltree/meson.build index 1ea9603d453f1..f9b063028391e 100644 --- a/contrib/ltree/meson.build +++ b/contrib/ltree/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ltree_sources = files( '_ltree_gist.c', diff --git a/contrib/ltree_plpython/ltree_plpython.c b/contrib/ltree_plpython/ltree_plpython.c index ac159ea31415c..0493aeb2423cc 100644 --- a/contrib/ltree_plpython/ltree_plpython.c +++ b/contrib/ltree_plpython/ltree_plpython.c @@ -2,9 +2,12 @@ #include "fmgr.h" #include "ltree/ltree.h" -#include "plpython.h" +#include "plpy_util.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "ltree_plpython", + .version = PG_VERSION +); /* Linkage to functions in plpython module */ typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size); diff --git a/contrib/ltree_plpython/ltree_plpython3u--1.0.sql b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql index 09ada3c7e8b70..14f73518d6ae4 100644 --- a/contrib/ltree_plpython/ltree_plpython3u--1.0.sql +++ b/contrib/ltree_plpython/ltree_plpython3u--1.0.sql @@ -7,6 +7,6 @@ CREATE FUNCTION ltree_to_plpython3(val internal) RETURNS internal LANGUAGE C STRICT IMMUTABLE AS 'MODULE_PATHNAME', 'ltree_to_plpython'; -CREATE TRANSFORM FOR ltree LANGUAGE plpython3u ( +CREATE TRANSFORM FOR @extschema:ltree@.ltree LANGUAGE plpython3u ( FROM SQL WITH FUNCTION ltree_to_plpython3(internal) ); diff --git a/contrib/ltree_plpython/meson.build b/contrib/ltree_plpython/meson.build index 894b99b7a3ab5..a37732c486b9d 100644 --- a/contrib/ltree_plpython/meson.build +++ b/contrib/ltree_plpython/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not python3_dep.found() subdir_done() diff --git a/contrib/meson.build b/contrib/meson.build index 14a8906865063..ed30ee7d639f6 100644 --- a/contrib/meson.build +++ b/contrib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group contrib_mod_args = pg_mod_args @@ -46,6 +46,8 @@ subdir('passwordcheck') subdir('pg_buffercache') subdir('pgcrypto') subdir('pg_freespacemap') +subdir('pg_logicalinspect') +subdir('pg_overexplain') subdir('pg_prewarm') subdir('pgrowlocks') subdir('pg_stat_statements') diff --git a/contrib/oid2name/meson.build b/contrib/oid2name/meson.build index 122979dc43ea2..074f16acd72e9 100644 --- a/contrib/oid2name/meson.build +++ b/contrib/oid2name/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group oid2name_sources = files( 'oid2name.c', diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c index e8c1e2c97bd2f..51802907138ed 100644 --- a/contrib/oid2name/oid2name.c +++ b/contrib/oid2name/oid2name.c @@ -62,7 +62,7 @@ void sql_exec_dumpalltbspc(PGconn *conn, struct options *opts); void get_opts(int argc, char **argv, struct options *my_opts) { - static struct option long_options[] = { + static const struct option long_options[] = { {"dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'}, {"host", required_argument, NULL, 'H'}, /* deprecated */ @@ -353,7 +353,7 @@ sql_conn(struct options *my_opts) res = PQexec(conn, ALWAYS_SECURE_SEARCH_PATH_SQL); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - pg_log_error("could not clear search_path: %s", + pg_log_error("could not clear \"search_path\": %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); diff --git a/contrib/oid2name/t/001_basic.pl b/contrib/oid2name/t/001_basic.pl index ae0e9ee20afce..a0ede3ebf6392 100644 --- a/contrib/oid2name/t/001_basic.pl +++ b/contrib/oid2name/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/contrib/pageinspect/Makefile b/contrib/pageinspect/Makefile index 95e030b396929..9dee765331069 100644 --- a/contrib/pageinspect/Makefile +++ b/contrib/pageinspect/Makefile @@ -13,7 +13,8 @@ OBJS = \ rawpage.o EXTENSION = pageinspect -DATA = pageinspect--1.11--1.12.sql pageinspect--1.10--1.11.sql \ +DATA = pageinspect--1.12--1.13.sql \ + pageinspect--1.11--1.12.sql pageinspect--1.10--1.11.sql \ pageinspect--1.9--1.10.sql pageinspect--1.8--1.9.sql \ pageinspect--1.7--1.8.sql pageinspect--1.6--1.7.sql \ pageinspect--1.5.sql pageinspect--1.5--1.6.sql \ diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c index 5a38d926689d7..990c965aa9241 100644 --- a/contrib/pageinspect/brinfuncs.c +++ b/contrib/pageinspect/brinfuncs.c @@ -2,27 +2,23 @@ * brinfuncs.c * Functions to investigate BRIN indexes * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/brinfuncs.c */ #include "postgres.h" -#include "access/brin.h" #include "access/brin_internal.h" #include "access/brin_page.h" -#include "access/brin_revmap.h" #include "access/brin_tuple.h" #include "access/htup_details.h" -#include "catalog/index.h" #include "catalog/pg_am_d.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "lib/stringinfo.h" #include "miscadmin.h" #include "pageinspect.h" -#include "utils/array.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -121,6 +117,8 @@ verify_brin_page(bytea *raw_page, uint16 type, const char *strtype) return page; } +/* Number of output arguments (columns) for brin_page_items() */ +#define BRIN_PAGE_ITEMS_V1_12 8 /* * Extract all item values from a BRIN index page @@ -149,6 +147,21 @@ brin_page_items(PG_FUNCTION_ARGS) InitMaterializedSRF(fcinfo, 0); + /* + * Version 1.12 added a new output column for the empty range flag. But as + * it was added in the middle, it may cause crashes with function + * definitions from older versions of the extension. + * + * There is no way to reliably avoid the problems created by the old + * function definition at this point, so insist that the user update the + * extension. + */ + if (rsinfo->setDesc->natts < BRIN_PAGE_ITEMS_V1_12) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("function has wrong number of declared columns"), + errhint("To resolve the problem, update the \"pageinspect\" extension to the latest version."))); + indexRel = index_open(indexRelid, AccessShareLock); if (!IS_BRIN(indexRel)) diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c index 9cdc8e182b483..294821231fc3b 100644 --- a/contrib/pageinspect/btreefuncs.c +++ b/contrib/pageinspect/btreefuncs.c @@ -206,14 +206,12 @@ check_relation_block_range(Relation rel, int64 blkno) if (blkno < 0 || blkno > MaxBlockNumber) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid block number %lld", - (long long) blkno))); + errmsg("invalid block number %" PRId64, blkno))); if ((BlockNumber) (blkno) >= RelationGetNumberOfBlocks(rel)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("block number %lld is out of range", - (long long) blkno))); + errmsg("block number %" PRId64 " is out of range", blkno))); } /* ----------------------------------------------- diff --git a/contrib/pageinspect/expected/brin.out b/contrib/pageinspect/expected/brin.out index 3a9d9125e4247..b6a43bbb01b30 100644 --- a/contrib/pageinspect/expected/brin.out +++ b/contrib/pageinspect/expected/brin.out @@ -114,7 +114,7 @@ CREATE TABLE brin_parallel_test (a int, b text, c bigint) WITH (fillfactor=40); -- for the different opclasses we build later). INSERT INTO brin_parallel_test SELECT (CASE WHEN (mod(i,231) = 0) OR (i BETWEEN 3500 AND 4000) THEN NULL ELSE i END), - (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3750 AND 4250) THEN NULL ELSE md5(i::text) END), + (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3750 AND 4250) THEN NULL ELSE encode(sha256(i::text::bytea), 'hex') END), (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3850 AND 4500) THEN NULL ELSE (i/100) + mod(i,8) END) FROM generate_series(1,5000) S(i); -- Build an index with different opclasses - minmax, bloom and minmax-multi. @@ -152,8 +152,8 @@ SELECT relname, relpages ORDER BY relname; relname | relpages ------------------------+---------- - brin_test_parallel_idx | 3 - brin_test_serial_idx | 3 + brin_test_parallel_idx | 4 + brin_test_serial_idx | 4 (2 rows) -- Check that (A except B) and (B except A) is empty, which means the indexes @@ -186,8 +186,8 @@ SELECT relname, relpages ORDER BY relname; relname | relpages ------------------------+---------- - brin_test_parallel_idx | 3 - brin_test_serial_idx | 3 + brin_test_parallel_idx | 4 + brin_test_serial_idx | 4 (2 rows) SELECT * FROM brin_page_items(get_raw_page('brin_test_parallel_idx', 2), 'brin_test_parallel_idx') diff --git a/contrib/pageinspect/expected/oldextversions.out b/contrib/pageinspect/expected/oldextversions.out index f5c4b61bd793f..2910891ece71c 100644 --- a/contrib/pageinspect/expected/oldextversions.out +++ b/contrib/pageinspect/expected/oldextversions.out @@ -52,5 +52,19 @@ SELECT pagesize, version FROM page_header(get_raw_page('test1', 0)); 8192 | 4 (1 row) +-- brin_page_items() added a new "empty" flag in 1.12, make sure we detect +-- an old function definition +ALTER EXTENSION pageinspect UPDATE TO '1.11'; +CREATE INDEX test_1_a_brin_idx ON test1 USING BRIN (a); +SELECT * FROM brin_page_items(get_raw_page('test_1_a_brin_idx', 2), 'test_1_a_brin_idx'); +ERROR: function has wrong number of declared columns +HINT: To resolve the problem, update the "pageinspect" extension to the latest version. +ALTER EXTENSION pageinspect UPDATE TO '1.12'; +SELECT * FROM brin_page_items(get_raw_page('test_1_a_brin_idx', 2), 'test_1_a_brin_idx'); + itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | empty | value +------------+--------+--------+----------+----------+-------------+-------+------------------------------------------ + 1 | 0 | 1 | f | f | f | f | {72057594037927937 .. 72057594037927937} +(1 row) + DROP TABLE test1; DROP EXTENSION pageinspect; diff --git a/contrib/pageinspect/expected/page.out b/contrib/pageinspect/expected/page.out index 80ddb45a60ac0..e42fd9747fd1c 100644 --- a/contrib/pageinspect/expected/page.out +++ b/contrib/pageinspect/expected/page.out @@ -208,6 +208,43 @@ select tuple_data_split('test8'::regclass, t_data, t_infomask, t_infomask2, t_bi (1 row) drop table test8; +-- check storage of generated columns +-- stored +create table test9s (a int not null, b int generated always as (a * 2) stored); +insert into test9s values (131584); +select raw_flags, t_bits, t_data + from heap_page_items(get_raw_page('test9s', 0)), lateral heap_tuple_infomask_flags(t_infomask, t_infomask2); + raw_flags | t_bits | t_data +---------------------+--------+-------------------- + {HEAP_XMAX_INVALID} | | \x0002020000040400 +(1 row) + +select tuple_data_split('test9s'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test9s', 0)); + tuple_data_split +------------------------------- + {"\\x00020200","\\x00040400"} +(1 row) + +drop table test9s; +-- virtual +create table test9v (a int not null, b int generated always as (a * 2) virtual); +insert into test9v values (131584); +select raw_flags, t_bits, t_data + from heap_page_items(get_raw_page('test9v', 0)), lateral heap_tuple_infomask_flags(t_infomask, t_infomask2); + raw_flags | t_bits | t_data +----------------------------------+----------+------------ + {HEAP_HASNULL,HEAP_XMAX_INVALID} | 10000000 | \x00020200 +(1 row) + +select tuple_data_split('test9v'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test9v', 0)); + tuple_data_split +---------------------- + {"\\x00020200",NULL} +(1 row) + +drop table test9v; -- Failure with incorrect page size -- Suppress the DETAIL message, to allow the tests to work across various -- page sizes. @@ -239,3 +276,13 @@ SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1); (1 row) +-- tests for sequences +create sequence test_sequence start 72057594037927937; +select tuple_data_split('test_sequence'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test_sequence', 0)); + tuple_data_split +------------------------------------------------------- + {"\\x0100000000000001","\\x0000000000000000","\\x00"} +(1 row) + +drop sequence test_sequence; diff --git a/contrib/pageinspect/fsmfuncs.c b/contrib/pageinspect/fsmfuncs.c index f8ae08862445b..0ccc3ddfbb8f9 100644 --- a/contrib/pageinspect/fsmfuncs.c +++ b/contrib/pageinspect/fsmfuncs.c @@ -9,7 +9,7 @@ * there's hardly any use case for using these without superuser-rights * anyway. * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/fsmfuncs.c @@ -19,7 +19,7 @@ #include "postgres.h" -#include "funcapi.h" +#include "fmgr.h" #include "lib/stringinfo.h" #include "miscadmin.h" #include "pageinspect.h" diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c index 1dabbdb588972..09a90957081f1 100644 --- a/contrib/pageinspect/ginfuncs.c +++ b/contrib/pageinspect/ginfuncs.c @@ -2,24 +2,21 @@ * ginfuncs.c * Functions to investigate the content of GIN indexes * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/ginfuncs.c */ #include "postgres.h" -#include "access/gin.h" #include "access/gin_private.h" #include "access/htup_details.h" -#include "catalog/namespace.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "miscadmin.h" #include "pageinspect.h" #include "utils/array.h" #include "utils/builtins.h" -#include "utils/rel.h" PG_FUNCTION_INFO_V1(gin_metapage_info); diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c index 1cc3b8c9e909c..7b16e2a1ef33c 100644 --- a/contrib/pageinspect/gistfuncs.c +++ b/contrib/pageinspect/gistfuncs.c @@ -2,7 +2,7 @@ * gistfuncs.c * Functions to investigate the content of GiST indexes * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/gistfuncs.c @@ -10,10 +10,8 @@ #include "postgres.h" #include "access/gist.h" -#include "access/gist_private.h" #include "access/htup.h" #include "access/relation.h" -#include "catalog/namespace.h" #include "catalog/pg_am_d.h" #include "funcapi.h" #include "miscadmin.h" @@ -25,7 +23,6 @@ #include "utils/pg_lsn.h" #include "utils/rel.h" #include "utils/ruleutils.h" -#include "utils/varlena.h" PG_FUNCTION_INFO_V1(gist_page_opaque_info); PG_FUNCTION_INFO_V1(gist_page_items); @@ -245,8 +242,8 @@ gist_page_items(PG_FUNCTION_ARGS) } else { - tupdesc = CreateTupleDescCopy(RelationGetDescr(indexRel)); - tupdesc->natts = IndexRelationGetNumberOfKeyAttributes(indexRel); + tupdesc = CreateTupleDescTruncatedCopy(RelationGetDescr(indexRel), + IndexRelationGetNumberOfKeyAttributes(indexRel)); printflags |= RULE_INDEXDEF_KEYS_ONLY; } diff --git a/contrib/pageinspect/hashfuncs.c b/contrib/pageinspect/hashfuncs.c index d4f827a7e2d91..ca7f1f6e7410d 100644 --- a/contrib/pageinspect/hashfuncs.c +++ b/contrib/pageinspect/hashfuncs.c @@ -2,7 +2,7 @@ * hashfuncs.c * Functions to investigate the content of HASH indexes * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/hashfuncs.c @@ -436,8 +436,8 @@ hash_bitmap_info(PG_FUNCTION_ARGS) if (ovflblkno >= RelationGetNumberOfBlocks(indexRel)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("block number %lld is out of range for relation \"%s\"", - (long long int) ovflblkno, RelationGetRelationName(indexRel)))); + errmsg("block number %" PRId64 " is out of range for relation \"%s\"", + ovflblkno, RelationGetRelationName(indexRel)))); /* Read the metapage so we can determine which bitmap page to use */ metabuf = _hash_getbuf(indexRel, HASH_METAPAGE, HASH_READ, LH_META_PAGE); diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c index 3faeabc7115fb..377ae30d1fa71 100644 --- a/contrib/pageinspect/heapfuncs.c +++ b/contrib/pageinspect/heapfuncs.c @@ -15,7 +15,7 @@ * there's hardly any use case for using these without superuser-rights * anyway. * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/heapfuncs.c @@ -32,7 +32,6 @@ #include "funcapi.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "pageinspect.h" #include "port/pg_bitutils.h" #include "utils/array.h" #include "utils/builtins.h" @@ -43,13 +42,14 @@ * was used to upgrade from an older version, tuples might still have an * oid. Seems worthwhile to display that. */ -#define HeapTupleHeaderGetOidOld(tup) \ -( \ - ((tup)->t_infomask & HEAP_HASOID_OLD) ? \ - *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \ - : \ - InvalidOid \ -) +static inline Oid +HeapTupleHeaderGetOidOld(const HeapTupleHeaderData *tup) +{ + if (tup->t_infomask & HEAP_HASOID_OLD) + return *((Oid *) ((char *) (tup) + (tup)->t_hoff - sizeof(Oid))); + else + return InvalidOid; +} /* @@ -212,11 +212,8 @@ heap_page_items(PG_FUNCTION_ARGS) lp_offset + lp_len <= raw_page_size) { HeapTupleHeader tuphdr; - bytea *tuple_data_bytea; - int tuple_data_len; /* Extract information from the tuple header */ - tuphdr = (HeapTupleHeader) PageGetItem(page, id); values[4] = UInt32GetDatum(HeapTupleHeaderGetRawXmin(tuphdr)); @@ -228,31 +225,32 @@ heap_page_items(PG_FUNCTION_ARGS) values[9] = UInt32GetDatum(tuphdr->t_infomask); values[10] = UInt8GetDatum(tuphdr->t_hoff); - /* Copy raw tuple data into bytea attribute */ - tuple_data_len = lp_len - tuphdr->t_hoff; - tuple_data_bytea = (bytea *) palloc(tuple_data_len + VARHDRSZ); - SET_VARSIZE(tuple_data_bytea, tuple_data_len + VARHDRSZ); - memcpy(VARDATA(tuple_data_bytea), (char *) tuphdr + tuphdr->t_hoff, - tuple_data_len); - values[13] = PointerGetDatum(tuple_data_bytea); - /* * We already checked that the item is completely within the raw * page passed to us, with the length given in the line pointer. - * Let's check that t_hoff doesn't point over lp_len, before using - * it to access t_bits and oid. + * But t_hoff could be out of range, so check it before relying on + * it to fetch additional info. */ if (tuphdr->t_hoff >= SizeofHeapTupleHeader && tuphdr->t_hoff <= lp_len && tuphdr->t_hoff == MAXALIGN(tuphdr->t_hoff)) { + int tuple_data_len; + bytea *tuple_data_bytea; + + /* Copy null bitmask and OID, if present */ if (tuphdr->t_infomask & HEAP_HASNULL) { - int bits_len; - - bits_len = - BITMAPLEN(HeapTupleHeaderGetNatts(tuphdr)) * BITS_PER_BYTE; - values[11] = CStringGetTextDatum(bits_to_text(tuphdr->t_bits, bits_len)); + int bitmaplen; + + bitmaplen = BITMAPLEN(HeapTupleHeaderGetNatts(tuphdr)); + /* better range-check the attribute count, too */ + if (bitmaplen <= tuphdr->t_hoff - SizeofHeapTupleHeader) + values[11] = + CStringGetTextDatum(bits_to_text(tuphdr->t_bits, + bitmaplen * BITS_PER_BYTE)); + else + nulls[11] = true; } else nulls[11] = true; @@ -261,11 +259,22 @@ heap_page_items(PG_FUNCTION_ARGS) values[12] = HeapTupleHeaderGetOidOld(tuphdr); else nulls[12] = true; + + /* Copy raw tuple data into bytea attribute */ + tuple_data_len = lp_len - tuphdr->t_hoff; + tuple_data_bytea = (bytea *) palloc(tuple_data_len + VARHDRSZ); + SET_VARSIZE(tuple_data_bytea, tuple_data_len + VARHDRSZ); + if (tuple_data_len > 0) + memcpy(VARDATA(tuple_data_bytea), + (char *) tuphdr + tuphdr->t_hoff, + tuple_data_len); + values[13] = PointerGetDatum(tuple_data_bytea); } else { nulls[11] = true; nulls[12] = true; + nulls[13] = true; } } else @@ -320,7 +329,11 @@ tuple_data_split_internal(Oid relid, char *tupdata, raw_attrs = initArrayResult(BYTEAOID, CurrentMemoryContext, false); nattrs = tupdesc->natts; - if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) + /* + * Sequences always use heap AM, but they don't show that in the catalogs. + */ + if (rel->rd_rel->relkind != RELKIND_SEQUENCE && + rel->rd_rel->relam != HEAP_TABLE_AM_OID) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("only heap AM is supported"))); @@ -331,11 +344,11 @@ tuple_data_split_internal(Oid relid, char *tupdata, for (i = 0; i < nattrs; i++) { - Form_pg_attribute attr; + CompactAttribute *attr; bool is_null; bytea *attr_data = NULL; - attr = TupleDescAttr(tupdesc, i); + attr = TupleDescCompactAttr(tupdesc, i); /* * Tuple header can specify fewer attributes than tuple descriptor as @@ -354,8 +367,8 @@ tuple_data_split_internal(Oid relid, char *tupdata, if (attr->attlen == -1) { - off = att_align_pointer(off, attr->attalign, -1, - tupdata + off); + off = att_pointer_alignby(off, attr->attalignby, -1, + tupdata + off); /* * As VARSIZE_ANY throws an exception if it can't properly @@ -373,7 +386,7 @@ tuple_data_split_internal(Oid relid, char *tupdata, } else { - off = att_align_nominal(off, attr->attalign); + off = att_nominal_alignby(off, attr->attalignby); len = attr->attlen; } diff --git a/contrib/pageinspect/meson.build b/contrib/pageinspect/meson.build index 27a007c1df3a6..3e2132f1b2d23 100644 --- a/contrib/pageinspect/meson.build +++ b/contrib/pageinspect/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pageinspect_sources = files( 'brinfuncs.c', @@ -37,6 +37,7 @@ install_data( 'pageinspect--1.9--1.10.sql', 'pageinspect--1.10--1.11.sql', 'pageinspect--1.11--1.12.sql', + 'pageinspect--1.12--1.13.sql', 'pageinspect.control', kwargs: contrib_data_args, ) diff --git a/contrib/pageinspect/pageinspect--1.12--1.13.sql b/contrib/pageinspect/pageinspect--1.12--1.13.sql new file mode 100644 index 0000000000000..07ec70a5de39a --- /dev/null +++ b/contrib/pageinspect/pageinspect--1.12--1.13.sql @@ -0,0 +1,74 @@ +/* contrib/pageinspect/pageinspect--1.12--1.13.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pageinspect UPDATE TO '1.13'" to load this file. \quit + +-- Convert SQL functions to new style + +CREATE OR REPLACE FUNCTION heap_page_item_attrs( + IN page bytea, + IN rel_oid regclass, + IN do_detoast bool, + OUT lp smallint, + OUT lp_off smallint, + OUT lp_flags smallint, + OUT lp_len smallint, + OUT t_xmin xid, + OUT t_xmax xid, + OUT t_field3 int4, + OUT t_ctid tid, + OUT t_infomask2 integer, + OUT t_infomask integer, + OUT t_hoff smallint, + OUT t_bits text, + OUT t_oid oid, + OUT t_attrs bytea[] + ) +RETURNS SETOF record +LANGUAGE SQL PARALLEL RESTRICTED +BEGIN ATOMIC +SELECT lp, + lp_off, + lp_flags, + lp_len, + t_xmin, + t_xmax, + t_field3, + t_ctid, + t_infomask2, + t_infomask, + t_hoff, + t_bits, + t_oid, + tuple_data_split( + rel_oid::oid, + t_data, + t_infomask, + t_infomask2, + t_bits, + do_detoast) + AS t_attrs + FROM heap_page_items(page); +END; + +CREATE OR REPLACE FUNCTION heap_page_item_attrs(IN page bytea, IN rel_oid regclass, + OUT lp smallint, + OUT lp_off smallint, + OUT lp_flags smallint, + OUT lp_len smallint, + OUT t_xmin xid, + OUT t_xmax xid, + OUT t_field3 int4, + OUT t_ctid tid, + OUT t_infomask2 integer, + OUT t_infomask integer, + OUT t_hoff smallint, + OUT t_bits text, + OUT t_oid oid, + OUT t_attrs bytea[] + ) +RETURNS SETOF record +LANGUAGE SQL PARALLEL RESTRICTED +BEGIN ATOMIC +SELECT * FROM heap_page_item_attrs(page, rel_oid, false); +END; diff --git a/contrib/pageinspect/pageinspect.control b/contrib/pageinspect/pageinspect.control index b2804e9b1284b..cfc87feac034a 100644 --- a/contrib/pageinspect/pageinspect.control +++ b/contrib/pageinspect/pageinspect.control @@ -1,5 +1,5 @@ # pageinspect extension comment = 'inspect the contents of database pages at a low level' -default_version = '1.12' +default_version = '1.13' module_pathname = '$libdir/pageinspect' relocatable = true diff --git a/contrib/pageinspect/pageinspect.h b/contrib/pageinspect/pageinspect.h index 209163a8c8152..1d0ec67f401f6 100644 --- a/contrib/pageinspect/pageinspect.h +++ b/contrib/pageinspect/pageinspect.h @@ -3,7 +3,7 @@ * pageinspect.h * Common functions for pageinspect. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/pageinspect.h diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index 2800ebd62f5fc..0d57123aa2669 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -5,7 +5,7 @@ * * Access-method specific inspection functions are in separate files. * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pageinspect/rawpage.c @@ -29,7 +29,10 @@ #include "utils/rel.h" #include "utils/varlena.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pageinspect", + .version = PG_VERSION +); static bytea *get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno); @@ -357,7 +360,7 @@ page_checksum_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version) if (PageIsNew(page)) PG_RETURN_NULL(); - PG_RETURN_INT16(pg_checksum_page((char *) page, blkno)); + PG_RETURN_INT16(pg_checksum_page(page, blkno)); } Datum diff --git a/contrib/pageinspect/sql/brin.sql b/contrib/pageinspect/sql/brin.sql index aadbf0529f202..4edf17b5a4510 100644 --- a/contrib/pageinspect/sql/brin.sql +++ b/contrib/pageinspect/sql/brin.sql @@ -62,7 +62,7 @@ CREATE TABLE brin_parallel_test (a int, b text, c bigint) WITH (fillfactor=40); -- for the different opclasses we build later). INSERT INTO brin_parallel_test SELECT (CASE WHEN (mod(i,231) = 0) OR (i BETWEEN 3500 AND 4000) THEN NULL ELSE i END), - (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3750 AND 4250) THEN NULL ELSE md5(i::text) END), + (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3750 AND 4250) THEN NULL ELSE encode(sha256(i::text::bytea), 'hex') END), (CASE WHEN (mod(i,233) = 0) OR (i BETWEEN 3850 AND 4500) THEN NULL ELSE (i/100) + mod(i,8) END) FROM generate_series(1,5000) S(i); diff --git a/contrib/pageinspect/sql/oldextversions.sql b/contrib/pageinspect/sql/oldextversions.sql index 9f953492c23c3..44f564faec960 100644 --- a/contrib/pageinspect/sql/oldextversions.sql +++ b/contrib/pageinspect/sql/oldextversions.sql @@ -22,5 +22,14 @@ ALTER EXTENSION pageinspect UPDATE TO '1.9'; \df page_header SELECT pagesize, version FROM page_header(get_raw_page('test1', 0)); +-- brin_page_items() added a new "empty" flag in 1.12, make sure we detect +-- an old function definition +ALTER EXTENSION pageinspect UPDATE TO '1.11'; +CREATE INDEX test_1_a_brin_idx ON test1 USING BRIN (a); +SELECT * FROM brin_page_items(get_raw_page('test_1_a_brin_idx', 2), 'test_1_a_brin_idx'); + +ALTER EXTENSION pageinspect UPDATE TO '1.12'; +SELECT * FROM brin_page_items(get_raw_page('test_1_a_brin_idx', 2), 'test_1_a_brin_idx'); + DROP TABLE test1; DROP EXTENSION pageinspect; diff --git a/contrib/pageinspect/sql/page.sql b/contrib/pageinspect/sql/page.sql index 5bff568d3b5f8..c75fe1147f69e 100644 --- a/contrib/pageinspect/sql/page.sql +++ b/contrib/pageinspect/sql/page.sql @@ -84,6 +84,25 @@ select tuple_data_split('test8'::regclass, t_data, t_infomask, t_infomask2, t_bi from heap_page_items(get_raw_page('test8', 0)); drop table test8; +-- check storage of generated columns +-- stored +create table test9s (a int not null, b int generated always as (a * 2) stored); +insert into test9s values (131584); +select raw_flags, t_bits, t_data + from heap_page_items(get_raw_page('test9s', 0)), lateral heap_tuple_infomask_flags(t_infomask, t_infomask2); +select tuple_data_split('test9s'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test9s', 0)); +drop table test9s; + +-- virtual +create table test9v (a int not null, b int generated always as (a * 2) virtual); +insert into test9v values (131584); +select raw_flags, t_bits, t_data + from heap_page_items(get_raw_page('test9v', 0)), lateral heap_tuple_infomask_flags(t_infomask, t_infomask2); +select tuple_data_split('test9v'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test9v', 0)); +drop table test9v; + -- Failure with incorrect page size -- Suppress the DETAIL message, to allow the tests to work across various -- page sizes. @@ -98,3 +117,9 @@ SHOW block_size \gset SELECT fsm_page_contents(decode(repeat('00', :block_size), 'hex')); SELECT page_header(decode(repeat('00', :block_size), 'hex')); SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1); + +-- tests for sequences +create sequence test_sequence start 72057594037927937; +select tuple_data_split('test_sequence'::regclass, t_data, t_infomask, t_infomask2, t_bits) + from heap_page_items(get_raw_page('test_sequence', 0)); +drop sequence test_sequence; diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out index 2027681daf664..83472c76d2784 100644 --- a/contrib/passwordcheck/expected/passwordcheck.out +++ b/contrib/passwordcheck/expected/passwordcheck.out @@ -1,3 +1,4 @@ +SET md5_password_warnings = off; LOAD 'passwordcheck'; CREATE USER regress_passwordcheck_user1; -- ok @@ -5,6 +6,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password'; -- error: too short ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt'; ERROR: password is too short +DETAIL: password must be at least "passwordcheck.min_password_length" (8) bytes long +-- ok +SET passwordcheck.min_password_length = 6; +ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt'; -- error: contains user name ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1'; ERROR: password must not contain user name diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out index 5d8d5dcc1c21b..fb12ec45cc4bf 100644 --- a/contrib/passwordcheck/expected/passwordcheck_1.out +++ b/contrib/passwordcheck/expected/passwordcheck_1.out @@ -1,3 +1,4 @@ +SET md5_password_warnings = off; LOAD 'passwordcheck'; CREATE USER regress_passwordcheck_user1; -- ok @@ -5,6 +6,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password'; -- error: too short ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt'; ERROR: password is too short +DETAIL: password must be at least "passwordcheck.min_password_length" (8) bytes long +-- ok +SET passwordcheck.min_password_length = 6; +ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt'; -- error: contains user name ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1'; ERROR: password must not contain user name diff --git a/contrib/passwordcheck/meson.build b/contrib/passwordcheck/meson.build index b15a8b9fd6044..297a24f3e3b30 100644 --- a/contrib/passwordcheck/meson.build +++ b/contrib/passwordcheck/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group passwordcheck_sources = files( 'passwordcheck.c', diff --git a/contrib/passwordcheck/passwordcheck.c b/contrib/passwordcheck/passwordcheck.c index 0785618f2abbe..39ded17afa413 100644 --- a/contrib/passwordcheck/passwordcheck.c +++ b/contrib/passwordcheck/passwordcheck.c @@ -3,7 +3,7 @@ * passwordcheck.c * * - * Copyright (c) 2009-2024, PostgreSQL Global Development Group + * Copyright (c) 2009-2025, PostgreSQL Global Development Group * * Author: Laurenz Albe * @@ -15,6 +15,7 @@ #include "postgres.h" #include +#include #ifdef USE_CRACKLIB #include @@ -24,13 +25,16 @@ #include "fmgr.h" #include "libpq/crypt.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "passwordcheck", + .version = PG_VERSION +); -/* Saved hook value in case of unload */ +/* Saved hook value */ static check_password_hook_type prev_check_password_hook = NULL; -/* passwords shorter than this will be rejected */ -#define MIN_PWD_LENGTH 8 +/* GUC variables */ +static int min_password_length = 8; /* * check_password @@ -93,10 +97,12 @@ check_password(const char *username, #endif /* enforce minimum length */ - if (pwdlen < MIN_PWD_LENGTH) + if (pwdlen < min_password_length) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("password is too short"))); + errmsg("password is too short"), + errdetail("password must be at least \"passwordcheck.min_password_length\" (%d) bytes long", + min_password_length))); /* check if the password contains the username */ if (strstr(password, username)) @@ -142,6 +148,19 @@ check_password(const char *username, void _PG_init(void) { + /* Define custom GUC variables. */ + DefineCustomIntVariable("passwordcheck.min_password_length", + "Minimum allowed password length.", + NULL, + &min_password_length, + 8, + 0, INT_MAX, + PGC_SUSET, + GUC_UNIT_BYTE, + NULL, NULL, NULL); + + MarkGUCPrefixReserved("passwordcheck"); + /* activate password checks when the module is loaded */ prev_check_password_hook = check_password_hook; check_password_hook = check_password; diff --git a/contrib/passwordcheck/sql/passwordcheck.sql b/contrib/passwordcheck/sql/passwordcheck.sql index 1fbd6b0e96e08..21ad8d452b5e4 100644 --- a/contrib/passwordcheck/sql/passwordcheck.sql +++ b/contrib/passwordcheck/sql/passwordcheck.sql @@ -1,3 +1,4 @@ +SET md5_password_warnings = off; LOAD 'passwordcheck'; CREATE USER regress_passwordcheck_user1; @@ -8,6 +9,10 @@ ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password'; -- error: too short ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt'; +-- ok +SET passwordcheck.min_password_length = 6; +ALTER USER regress_passwordcheck_user1 PASSWORD 'v_shrt'; + -- error: contains user name ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1'; diff --git a/contrib/pg_buffercache/Makefile b/contrib/pg_buffercache/Makefile index eae65ead9e502..5f748543e2ea2 100644 --- a/contrib/pg_buffercache/Makefile +++ b/contrib/pg_buffercache/Makefile @@ -8,10 +8,11 @@ OBJS = \ EXTENSION = pg_buffercache DATA = pg_buffercache--1.2.sql pg_buffercache--1.2--1.3.sql \ pg_buffercache--1.1--1.2.sql pg_buffercache--1.0--1.1.sql \ - pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql + pg_buffercache--1.3--1.4.sql pg_buffercache--1.4--1.5.sql \ + pg_buffercache--1.5--1.6.sql PGFILEDESC = "pg_buffercache - monitoring of shared buffer cache in real-time" -REGRESS = pg_buffercache +REGRESS = pg_buffercache pg_buffercache_numa ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/contrib/pg_buffercache/expected/pg_buffercache.out b/contrib/pg_buffercache/expected/pg_buffercache.out index b745dc69eaecf..9a9216dc7b1bf 100644 --- a/contrib/pg_buffercache/expected/pg_buffercache.out +++ b/contrib/pg_buffercache/expected/pg_buffercache.out @@ -55,3 +55,67 @@ SELECT count(*) > 0 FROM pg_buffercache_usage_counts(); t (1 row) +RESET role; +------ +---- Test pg_buffercache_evict* functions +------ +CREATE ROLE regress_buffercache_normal; +SET ROLE regress_buffercache_normal; +-- These should fail because they need to be called as SUPERUSER +SELECT * FROM pg_buffercache_evict(1); +ERROR: must be superuser to use pg_buffercache_evict() +SELECT * FROM pg_buffercache_evict_relation(1); +ERROR: must be superuser to use pg_buffercache_evict_relation() +SELECT * FROM pg_buffercache_evict_all(); +ERROR: must be superuser to use pg_buffercache_evict_all() +RESET ROLE; +-- These should return nothing, because these are STRICT functions +SELECT * FROM pg_buffercache_evict(NULL); + buffer_evicted | buffer_flushed +----------------+---------------- + | +(1 row) + +SELECT * FROM pg_buffercache_evict_relation(NULL); + buffers_evicted | buffers_flushed | buffers_skipped +-----------------+-----------------+----------------- + | | +(1 row) + +-- These should fail because they are not called by valid range of buffers +-- Number of the shared buffers are limited by max integer +SELECT 2147483647 max_buffers \gset +SELECT * FROM pg_buffercache_evict(-1); +ERROR: bad buffer ID: -1 +SELECT * FROM pg_buffercache_evict(0); +ERROR: bad buffer ID: 0 +SELECT * FROM pg_buffercache_evict(:max_buffers); +ERROR: bad buffer ID: 2147483647 +-- This should fail because pg_buffercache_evict_relation() doesn't accept +-- local relations +CREATE TEMP TABLE temp_pg_buffercache(); +SELECT * FROM pg_buffercache_evict_relation('temp_pg_buffercache'); +ERROR: relation uses local buffers, pg_buffercache_evict_relation() is intended to be used for shared buffers only +DROP TABLE temp_pg_buffercache; +-- These shouldn't fail +SELECT buffer_evicted IS NOT NULL FROM pg_buffercache_evict(1); + ?column? +---------- + t +(1 row) + +SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_all(); + ?column? +---------- + t +(1 row) + +CREATE TABLE shared_pg_buffercache(); +SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_relation('shared_pg_buffercache'); + ?column? +---------- + t +(1 row) + +DROP TABLE shared_pg_buffercache; +DROP ROLE regress_buffercache_normal; diff --git a/contrib/pg_buffercache/expected/pg_buffercache_numa.out b/contrib/pg_buffercache/expected/pg_buffercache_numa.out new file mode 100644 index 0000000000000..a10b331a55261 --- /dev/null +++ b/contrib/pg_buffercache/expected/pg_buffercache_numa.out @@ -0,0 +1,29 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +\quit +\endif +-- We expect at least one entry for each buffer +select count(*) >= (select setting::bigint + from pg_settings + where name = 'shared_buffers') +from pg_buffercache_numa; + ?column? +---------- + t +(1 row) + +-- Check that the functions / views can't be accessed by default. To avoid +-- having to create a dedicated user, use the pg_database_owner pseudo-role. +SET ROLE pg_database_owner; +SELECT count(*) > 0 FROM pg_buffercache_numa; +ERROR: permission denied for view pg_buffercache_numa +RESET role; +-- Check that pg_monitor is allowed to query view / function +SET ROLE pg_monitor; +SELECT count(*) > 0 FROM pg_buffercache_numa; + ?column? +---------- + t +(1 row) + +RESET role; diff --git a/contrib/pg_buffercache/expected/pg_buffercache_numa_1.out b/contrib/pg_buffercache/expected/pg_buffercache_numa_1.out new file mode 100644 index 0000000000000..6dd6824b4e4f3 --- /dev/null +++ b/contrib/pg_buffercache/expected/pg_buffercache_numa_1.out @@ -0,0 +1,3 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +\quit diff --git a/contrib/pg_buffercache/meson.build b/contrib/pg_buffercache/meson.build index 1ca3452918bbc..7cd039a1df9cb 100644 --- a/contrib/pg_buffercache/meson.build +++ b/contrib/pg_buffercache/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_buffercache_sources = files( 'pg_buffercache_pages.c', @@ -23,6 +23,7 @@ install_data( 'pg_buffercache--1.2.sql', 'pg_buffercache--1.3--1.4.sql', 'pg_buffercache--1.4--1.5.sql', + 'pg_buffercache--1.5--1.6.sql', 'pg_buffercache.control', kwargs: contrib_data_args, ) @@ -34,6 +35,7 @@ tests += { 'regress': { 'sql': [ 'pg_buffercache', + 'pg_buffercache_numa', ], }, } diff --git a/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql new file mode 100644 index 0000000000000..458f054a69179 --- /dev/null +++ b/contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql @@ -0,0 +1,46 @@ +/* contrib/pg_buffercache/pg_buffercache--1.5--1.6.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION pg_buffercache UPDATE TO '1.6'" to load this file. \quit + +-- Register the new functions. +CREATE OR REPLACE FUNCTION pg_buffercache_numa_pages() +RETURNS SETOF RECORD +AS 'MODULE_PATHNAME', 'pg_buffercache_numa_pages' +LANGUAGE C PARALLEL SAFE; + +-- Create a view for convenient access. +CREATE VIEW pg_buffercache_numa AS + SELECT P.* FROM pg_buffercache_numa_pages() AS P + (bufferid integer, os_page_num bigint, numa_node integer); + +-- Don't want these to be available to public. +REVOKE ALL ON FUNCTION pg_buffercache_numa_pages() FROM PUBLIC; +REVOKE ALL ON pg_buffercache_numa FROM PUBLIC; + +GRANT EXECUTE ON FUNCTION pg_buffercache_numa_pages() TO pg_monitor; +GRANT SELECT ON pg_buffercache_numa TO pg_monitor; + + +DROP FUNCTION pg_buffercache_evict(integer); +CREATE FUNCTION pg_buffercache_evict( + IN int, + OUT buffer_evicted boolean, + OUT buffer_flushed boolean) +AS 'MODULE_PATHNAME', 'pg_buffercache_evict' +LANGUAGE C PARALLEL SAFE VOLATILE STRICT; + +CREATE FUNCTION pg_buffercache_evict_relation( + IN regclass, + OUT buffers_evicted int4, + OUT buffers_flushed int4, + OUT buffers_skipped int4) +AS 'MODULE_PATHNAME', 'pg_buffercache_evict_relation' +LANGUAGE C PARALLEL SAFE VOLATILE STRICT; + +CREATE FUNCTION pg_buffercache_evict_all( + OUT buffers_evicted int4, + OUT buffers_flushed int4, + OUT buffers_skipped int4) +AS 'MODULE_PATHNAME', 'pg_buffercache_evict_all' +LANGUAGE C PARALLEL SAFE VOLATILE; diff --git a/contrib/pg_buffercache/pg_buffercache.control b/contrib/pg_buffercache/pg_buffercache.control index 5ee875f77dd90..b030ba3a6faba 100644 --- a/contrib/pg_buffercache/pg_buffercache.control +++ b/contrib/pg_buffercache/pg_buffercache.control @@ -1,5 +1,5 @@ # pg_buffercache extension comment = 'examine the shared buffer cache' -default_version = '1.5' +default_version = '1.6' module_pathname = '$libdir/pg_buffercache' relocatable = true diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c index 3ae0a018e103c..4b007f6e1b06a 100644 --- a/contrib/pg_buffercache/pg_buffercache_pages.c +++ b/contrib/pg_buffercache/pg_buffercache_pages.c @@ -9,18 +9,29 @@ #include "postgres.h" #include "access/htup_details.h" +#include "access/relation.h" #include "catalog/pg_type.h" #include "funcapi.h" +#include "port/pg_numa.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" +#include "utils/rel.h" #define NUM_BUFFERCACHE_PAGES_MIN_ELEM 8 #define NUM_BUFFERCACHE_PAGES_ELEM 9 #define NUM_BUFFERCACHE_SUMMARY_ELEM 5 #define NUM_BUFFERCACHE_USAGE_COUNTS_ELEM 4 +#define NUM_BUFFERCACHE_EVICT_ELEM 2 +#define NUM_BUFFERCACHE_EVICT_RELATION_ELEM 3 +#define NUM_BUFFERCACHE_EVICT_ALL_ELEM 3 -PG_MODULE_MAGIC; +#define NUM_BUFFERCACHE_NUMA_ELEM 3 + +PG_MODULE_MAGIC_EXT( + .name = "pg_buffercache", + .version = PG_VERSION +); /* * Record structure holding the to be exposed cache data. @@ -55,15 +66,45 @@ typedef struct BufferCachePagesRec *record; } BufferCachePagesContext; +/* + * Record structure holding the to be exposed cache data. + */ +typedef struct +{ + uint32 bufferid; + int64 page_num; + int32 numa_node; +} BufferCacheNumaRec; + +/* + * Function context for data persisting over repeated calls. + */ +typedef struct +{ + TupleDesc tupdesc; + int buffers_per_page; + int pages_per_buffer; + int os_page_size; + BufferCacheNumaRec *record; +} BufferCacheNumaContext; + /* * Function returning data from the shared buffer cache - buffer number, * relation node/tablespace/database/blocknum and dirty indicator. */ PG_FUNCTION_INFO_V1(pg_buffercache_pages); +PG_FUNCTION_INFO_V1(pg_buffercache_numa_pages); PG_FUNCTION_INFO_V1(pg_buffercache_summary); PG_FUNCTION_INFO_V1(pg_buffercache_usage_counts); PG_FUNCTION_INFO_V1(pg_buffercache_evict); +PG_FUNCTION_INFO_V1(pg_buffercache_evict_relation); +PG_FUNCTION_INFO_V1(pg_buffercache_evict_all); + + +/* Only need to touch memory once per backend process lifetime */ +static bool firstNumaTouch = true; + Datum pg_buffercache_pages(PG_FUNCTION_ARGS) @@ -243,6 +284,260 @@ pg_buffercache_pages(PG_FUNCTION_ARGS) SRF_RETURN_DONE(funcctx); } +/* + * Inquire about NUMA memory mappings for shared buffers. + * + * Returns NUMA node ID for each memory page used by the buffer. Buffers may + * be smaller or larger than OS memory pages. For each buffer we return one + * entry for each memory page used by the buffer (if the buffer is smaller, + * it only uses a part of one memory page). + * + * We expect both sizes (for buffers and memory pages) to be a power-of-2, so + * one is always a multiple of the other. + * + * In order to get reliable results we also need to touch memory pages, so + * that the inquiry about NUMA memory node doesn't return -2 (which indicates + * unmapped/unallocated pages). + */ +Datum +pg_buffercache_numa_pages(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + MemoryContext oldcontext; + BufferCacheNumaContext *fctx; /* User function context. */ + TupleDesc tupledesc; + TupleDesc expected_tupledesc; + HeapTuple tuple; + Datum result; + + if (SRF_IS_FIRSTCALL()) + { + int i, + idx; + Size os_page_size; + void **os_page_ptrs; + int *os_page_status; + uint64 os_page_count; + int pages_per_buffer; + int max_entries; + volatile uint64 touch pg_attribute_unused(); + char *startptr, + *endptr; + + if (pg_numa_init() == -1) + elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform"); + + /* + * The database block size and OS memory page size are unlikely to be + * the same. The block size is 1-32KB, the memory page size depends on + * platform. On x86 it's usually 4KB, on ARM it's 4KB or 64KB, but + * there are also features like THP etc. Moreover, we don't quite know + * how the pages and buffers "align" in memory - the buffers may be + * shifted in some way, using more memory pages than necessary. + * + * So we need to be careful about mapping buffers to memory pages. We + * calculate the maximum number of pages a buffer might use, so that + * we allocate enough space for the entries. And then we count the + * actual number of entries as we scan the buffers. + * + * This information is needed before calling move_pages() for NUMA + * node id inquiry. + */ + os_page_size = pg_get_shmem_pagesize(); + + /* + * The pages and block size is expected to be 2^k, so one divides the + * other (we don't know in which direction). This does not say + * anything about relative alignment of pages/buffers. + */ + Assert((os_page_size % BLCKSZ == 0) || (BLCKSZ % os_page_size == 0)); + + /* + * How many addresses we are going to query? Simply get the page for + * the first buffer, and first page after the last buffer, and count + * the pages from that. + */ + startptr = (char *) TYPEALIGN_DOWN(os_page_size, + BufferGetBlock(1)); + endptr = (char *) TYPEALIGN(os_page_size, + (char *) BufferGetBlock(NBuffers) + BLCKSZ); + os_page_count = (endptr - startptr) / os_page_size; + + /* Used to determine the NUMA node for all OS pages at once */ + os_page_ptrs = palloc0(sizeof(void *) * os_page_count); + os_page_status = palloc(sizeof(uint64) * os_page_count); + + /* Fill pointers for all the memory pages. */ + idx = 0; + for (char *ptr = startptr; ptr < endptr; ptr += os_page_size) + { + os_page_ptrs[idx++] = ptr; + + /* Only need to touch memory once per backend process lifetime */ + if (firstNumaTouch) + pg_numa_touch_mem_if_required(touch, ptr); + } + + Assert(idx == os_page_count); + + elog(DEBUG1, "NUMA: NBuffers=%d os_page_count=" UINT64_FORMAT " " + "os_page_size=%zu", NBuffers, os_page_count, os_page_size); + + /* + * If we ever get 0xff back from kernel inquiry, then we probably have + * bug in our buffers to OS page mapping code here. + */ + memset(os_page_status, 0xff, sizeof(int) * os_page_count); + + /* Query NUMA status for all the pointers */ + if (pg_numa_query_pages(0, os_page_count, os_page_ptrs, os_page_status) == -1) + elog(ERROR, "failed NUMA pages inquiry: %m"); + + /* Initialize the multi-call context, load entries about buffers */ + + funcctx = SRF_FIRSTCALL_INIT(); + + /* Switch context when allocating stuff to be used in later calls */ + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /* Create a user function context for cross-call persistence */ + fctx = (BufferCacheNumaContext *) palloc(sizeof(BufferCacheNumaContext)); + + if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + if (expected_tupledesc->natts != NUM_BUFFERCACHE_NUMA_ELEM) + elog(ERROR, "incorrect number of output arguments"); + + /* Construct a tuple descriptor for the result rows. */ + tupledesc = CreateTemplateTupleDesc(expected_tupledesc->natts); + TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid", + INT4OID, -1, 0); + TupleDescInitEntry(tupledesc, (AttrNumber) 2, "os_page_num", + INT8OID, -1, 0); + TupleDescInitEntry(tupledesc, (AttrNumber) 3, "numa_node", + INT4OID, -1, 0); + + fctx->tupdesc = BlessTupleDesc(tupledesc); + + /* + * Each buffer needs at least one entry, but it might be offset in + * some way, and use one extra entry. So we allocate space for the + * maximum number of entries we might need, and then count the exact + * number as we're walking buffers. That way we can do it in one pass, + * without reallocating memory. + */ + pages_per_buffer = Max(1, BLCKSZ / os_page_size) + 1; + max_entries = NBuffers * pages_per_buffer; + + /* Allocate entries for BufferCachePagesRec records. */ + fctx->record = (BufferCacheNumaRec *) + MemoryContextAllocHuge(CurrentMemoryContext, + sizeof(BufferCacheNumaRec) * max_entries); + + /* Return to original context when allocating transient memory */ + MemoryContextSwitchTo(oldcontext); + + if (firstNumaTouch) + elog(DEBUG1, "NUMA: page-faulting the buffercache for proper NUMA readouts"); + + /* + * Scan through all the buffers, saving the relevant fields in the + * fctx->record structure. + * + * We don't hold the partition locks, so we don't get a consistent + * snapshot across all buffers, but we do grab the buffer header + * locks, so the information of each buffer is self-consistent. + * + * This loop touches and stores addresses into os_page_ptrs[] as input + * to one big move_pages(2) inquiry system call. Basically we ask for + * all memory pages for NBuffers. + */ + startptr = (char *) TYPEALIGN_DOWN(os_page_size, (char *) BufferGetBlock(1)); + idx = 0; + for (i = 0; i < NBuffers; i++) + { + char *buffptr = (char *) BufferGetBlock(i + 1); + BufferDesc *bufHdr; + uint32 buf_state; + uint32 bufferid; + int32 page_num; + char *startptr_buff, + *endptr_buff; + + CHECK_FOR_INTERRUPTS(); + + bufHdr = GetBufferDescriptor(i); + + /* Lock each buffer header before inspecting. */ + buf_state = LockBufHdr(bufHdr); + bufferid = BufferDescriptorGetBuffer(bufHdr); + UnlockBufHdr(bufHdr, buf_state); + + /* start of the first page of this buffer */ + startptr_buff = (char *) TYPEALIGN_DOWN(os_page_size, buffptr); + + /* end of the buffer (no need to align to memory page) */ + endptr_buff = buffptr + BLCKSZ; + + Assert(startptr_buff < endptr_buff); + + /* calculate ID of the first page for this buffer */ + page_num = (startptr_buff - startptr) / os_page_size; + + /* Add an entry for each OS page overlapping with this buffer. */ + for (char *ptr = startptr_buff; ptr < endptr_buff; ptr += os_page_size) + { + fctx->record[idx].bufferid = bufferid; + fctx->record[idx].page_num = page_num; + fctx->record[idx].numa_node = os_page_status[page_num]; + + /* advance to the next entry/page */ + ++idx; + ++page_num; + } + } + + Assert((idx >= os_page_count) && (idx <= max_entries)); + + /* Set max calls and remember the user function context. */ + funcctx->max_calls = idx; + funcctx->user_fctx = fctx; + + /* Remember this backend touched the pages */ + firstNumaTouch = false; + } + + funcctx = SRF_PERCALL_SETUP(); + + /* Get the saved state */ + fctx = funcctx->user_fctx; + + if (funcctx->call_cntr < funcctx->max_calls) + { + uint32 i = funcctx->call_cntr; + Datum values[NUM_BUFFERCACHE_NUMA_ELEM]; + bool nulls[NUM_BUFFERCACHE_NUMA_ELEM]; + + values[0] = Int32GetDatum(fctx->record[i].bufferid); + nulls[0] = false; + + values[1] = Int64GetDatum(fctx->record[i].page_num); + nulls[1] = false; + + values[2] = Int32GetDatum(fctx->record[i].numa_node); + nulls[2] = false; + + /* Build and return the tuple. */ + tuple = heap_form_tuple(fctx->tupdesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + SRF_RETURN_NEXT(funcctx, result); + } + else + SRF_RETURN_DONE(funcctx); +} + Datum pg_buffercache_summary(PG_FUNCTION_ARGS) { @@ -349,21 +644,131 @@ pg_buffercache_usage_counts(PG_FUNCTION_ARGS) return (Datum) 0; } +/* + * Helper function to check if the user has superuser privileges. + */ +static void +pg_buffercache_superuser_check(char *func_name) +{ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to use %s()", + func_name))); +} + /* * Try to evict a shared buffer. */ Datum pg_buffercache_evict(PG_FUNCTION_ARGS) { + Datum result; + TupleDesc tupledesc; + HeapTuple tuple; + Datum values[NUM_BUFFERCACHE_EVICT_ELEM]; + bool nulls[NUM_BUFFERCACHE_EVICT_ELEM] = {0}; + Buffer buf = PG_GETARG_INT32(0); + bool buffer_flushed; - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to use pg_buffercache_evict function"))); + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + pg_buffercache_superuser_check("pg_buffercache_evict"); if (buf < 1 || buf > NBuffers) elog(ERROR, "bad buffer ID: %d", buf); - PG_RETURN_BOOL(EvictUnpinnedBuffer(buf)); + values[0] = BoolGetDatum(EvictUnpinnedBuffer(buf, &buffer_flushed)); + values[1] = BoolGetDatum(buffer_flushed); + + tuple = heap_form_tuple(tupledesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +} + +/* + * Try to evict specified relation. + */ +Datum +pg_buffercache_evict_relation(PG_FUNCTION_ARGS) +{ + Datum result; + TupleDesc tupledesc; + HeapTuple tuple; + Datum values[NUM_BUFFERCACHE_EVICT_RELATION_ELEM]; + bool nulls[NUM_BUFFERCACHE_EVICT_RELATION_ELEM] = {0}; + + Oid relOid; + Relation rel; + + int32 buffers_evicted = 0; + int32 buffers_flushed = 0; + int32 buffers_skipped = 0; + + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + pg_buffercache_superuser_check("pg_buffercache_evict_relation"); + + relOid = PG_GETARG_OID(0); + + rel = relation_open(relOid, AccessShareLock); + + if (RelationUsesLocalBuffers(rel)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("relation uses local buffers, %s() is intended to be used for shared buffers only", + "pg_buffercache_evict_relation"))); + + EvictRelUnpinnedBuffers(rel, &buffers_evicted, &buffers_flushed, + &buffers_skipped); + + relation_close(rel, AccessShareLock); + + values[0] = Int32GetDatum(buffers_evicted); + values[1] = Int32GetDatum(buffers_flushed); + values[2] = Int32GetDatum(buffers_skipped); + + tuple = heap_form_tuple(tupledesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +} + + +/* + * Try to evict all shared buffers. + */ +Datum +pg_buffercache_evict_all(PG_FUNCTION_ARGS) +{ + Datum result; + TupleDesc tupledesc; + HeapTuple tuple; + Datum values[NUM_BUFFERCACHE_EVICT_ALL_ELEM]; + bool nulls[NUM_BUFFERCACHE_EVICT_ALL_ELEM] = {0}; + + int32 buffers_evicted = 0; + int32 buffers_flushed = 0; + int32 buffers_skipped = 0; + + if (get_call_result_type(fcinfo, NULL, &tupledesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + pg_buffercache_superuser_check("pg_buffercache_evict_all"); + + EvictAllUnpinnedBuffers(&buffers_evicted, &buffers_flushed, + &buffers_skipped); + + values[0] = Int32GetDatum(buffers_evicted); + values[1] = Int32GetDatum(buffers_flushed); + values[2] = Int32GetDatum(buffers_skipped); + + tuple = heap_form_tuple(tupledesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); } diff --git a/contrib/pg_buffercache/sql/pg_buffercache.sql b/contrib/pg_buffercache/sql/pg_buffercache.sql index 944fbb1beaef0..47cca1907c74b 100644 --- a/contrib/pg_buffercache/sql/pg_buffercache.sql +++ b/contrib/pg_buffercache/sql/pg_buffercache.sql @@ -26,3 +26,45 @@ SET ROLE pg_monitor; SELECT count(*) > 0 FROM pg_buffercache; SELECT buffers_used + buffers_unused > 0 FROM pg_buffercache_summary(); SELECT count(*) > 0 FROM pg_buffercache_usage_counts(); +RESET role; + + +------ +---- Test pg_buffercache_evict* functions +------ + +CREATE ROLE regress_buffercache_normal; +SET ROLE regress_buffercache_normal; + +-- These should fail because they need to be called as SUPERUSER +SELECT * FROM pg_buffercache_evict(1); +SELECT * FROM pg_buffercache_evict_relation(1); +SELECT * FROM pg_buffercache_evict_all(); + +RESET ROLE; + +-- These should return nothing, because these are STRICT functions +SELECT * FROM pg_buffercache_evict(NULL); +SELECT * FROM pg_buffercache_evict_relation(NULL); + +-- These should fail because they are not called by valid range of buffers +-- Number of the shared buffers are limited by max integer +SELECT 2147483647 max_buffers \gset +SELECT * FROM pg_buffercache_evict(-1); +SELECT * FROM pg_buffercache_evict(0); +SELECT * FROM pg_buffercache_evict(:max_buffers); + +-- This should fail because pg_buffercache_evict_relation() doesn't accept +-- local relations +CREATE TEMP TABLE temp_pg_buffercache(); +SELECT * FROM pg_buffercache_evict_relation('temp_pg_buffercache'); +DROP TABLE temp_pg_buffercache; + +-- These shouldn't fail +SELECT buffer_evicted IS NOT NULL FROM pg_buffercache_evict(1); +SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_all(); +CREATE TABLE shared_pg_buffercache(); +SELECT buffers_evicted IS NOT NULL FROM pg_buffercache_evict_relation('shared_pg_buffercache'); +DROP TABLE shared_pg_buffercache; + +DROP ROLE regress_buffercache_normal; diff --git a/contrib/pg_buffercache/sql/pg_buffercache_numa.sql b/contrib/pg_buffercache/sql/pg_buffercache_numa.sql new file mode 100644 index 0000000000000..837f3d64e21bc --- /dev/null +++ b/contrib/pg_buffercache/sql/pg_buffercache_numa.sql @@ -0,0 +1,21 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +\quit +\endif + +-- We expect at least one entry for each buffer +select count(*) >= (select setting::bigint + from pg_settings + where name = 'shared_buffers') +from pg_buffercache_numa; + +-- Check that the functions / views can't be accessed by default. To avoid +-- having to create a dedicated user, use the pg_database_owner pseudo-role. +SET ROLE pg_database_owner; +SELECT count(*) > 0 FROM pg_buffercache_numa; +RESET role; + +-- Check that pg_monitor is allowed to query view / function +SET ROLE pg_monitor; +SELECT count(*) > 0 FROM pg_buffercache_numa; +RESET role; diff --git a/contrib/pg_freespacemap/Makefile b/contrib/pg_freespacemap/Makefile index b48e4b255bcfd..a986ae73d69cc 100644 --- a/contrib/pg_freespacemap/Makefile +++ b/contrib/pg_freespacemap/Makefile @@ -6,7 +6,9 @@ OBJS = \ pg_freespacemap.o EXTENSION = pg_freespacemap -DATA = pg_freespacemap--1.1.sql pg_freespacemap--1.1--1.2.sql \ +DATA = pg_freespacemap--1.1.sql \ + pg_freespacemap--1.2--1.3.sql \ + pg_freespacemap--1.1--1.2.sql \ pg_freespacemap--1.0--1.1.sql PGFILEDESC = "pg_freespacemap - monitoring of free space map" diff --git a/contrib/pg_freespacemap/meson.build b/contrib/pg_freespacemap/meson.build index af5d2b8c27c88..ff8eda3580e5a 100644 --- a/contrib/pg_freespacemap/meson.build +++ b/contrib/pg_freespacemap/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_freespacemap_sources = files( 'pg_freespacemap.c', @@ -20,6 +20,7 @@ install_data( 'pg_freespacemap--1.0--1.1.sql', 'pg_freespacemap--1.1--1.2.sql', 'pg_freespacemap--1.1.sql', + 'pg_freespacemap--1.2--1.3.sql', 'pg_freespacemap.control', kwargs: contrib_data_args, ) diff --git a/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql b/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql new file mode 100644 index 0000000000000..4986109bdafda --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql @@ -0,0 +1,13 @@ +/* contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_freespacemap UPDATE TO '1.3'" to load this file. \quit + +CREATE OR REPLACE FUNCTION + pg_freespace(rel regclass, blkno OUT bigint, avail OUT int2) +RETURNS SETOF RECORD +LANGUAGE SQL PARALLEL SAFE +BEGIN ATOMIC + SELECT blkno, pg_freespace($1, blkno) AS avail + FROM generate_series('0'::bigint, pg_relation_size($1) / current_setting('block_size'::text)::bigint - '1'::bigint) AS blkno; +END; diff --git a/contrib/pg_freespacemap/pg_freespacemap.c b/contrib/pg_freespacemap/pg_freespacemap.c index b82cab2d97ef4..610fc90b5ba57 100644 --- a/contrib/pg_freespacemap/pg_freespacemap.c +++ b/contrib/pg_freespacemap/pg_freespacemap.c @@ -9,10 +9,14 @@ #include "postgres.h" #include "access/relation.h" -#include "funcapi.h" +#include "fmgr.h" #include "storage/freespace.h" +#include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_freespacemap", + .version = PG_VERSION +); /* * Returns the amount of free space on a given page, according to the @@ -30,6 +34,13 @@ pg_freespace(PG_FUNCTION_ARGS) rel = relation_open(relid, AccessShareLock); + if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" does not have storage", + RelationGetRelationName(rel)), + errdetail_relkind_not_supported(rel->rd_rel->relkind))); + if (blkno < 0 || blkno > MaxBlockNumber) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), diff --git a/contrib/pg_freespacemap/pg_freespacemap.control b/contrib/pg_freespacemap/pg_freespacemap.control index ac8fc5050a917..1992320691b27 100644 --- a/contrib/pg_freespacemap/pg_freespacemap.control +++ b/contrib/pg_freespacemap/pg_freespacemap.control @@ -1,5 +1,5 @@ # pg_freespacemap extension comment = 'examine the free space map (FSM)' -default_version = '1.2' +default_version = '1.3' module_pathname = '$libdir/pg_freespacemap' relocatable = true diff --git a/contrib/pg_logicalinspect/.gitignore b/contrib/pg_logicalinspect/.gitignore new file mode 100644 index 0000000000000..b4903eba657fa --- /dev/null +++ b/contrib/pg_logicalinspect/.gitignore @@ -0,0 +1,6 @@ +# Generated subdirectories +/log/ +/results/ +/output_iso/ +/tmp_check/ +/tmp_check_iso/ diff --git a/contrib/pg_logicalinspect/Makefile b/contrib/pg_logicalinspect/Makefile new file mode 100644 index 0000000000000..17cee50d5c882 --- /dev/null +++ b/contrib/pg_logicalinspect/Makefile @@ -0,0 +1,32 @@ +# contrib/pg_logicalinspect/Makefile + +MODULE_big = pg_logicalinspect +OBJS = \ + $(WIN32RES) \ + pg_logicalinspect.o +PGFILEDESC = "pg_logicalinspect - functions to inspect logical decoding components" + +EXTENSION = pg_logicalinspect +DATA = pg_logicalinspect--1.0.sql + +EXTRA_INSTALL = contrib/test_decoding + +REGRESS = pg_logicalinspect +ISOLATION = logical_inspect + +ISOLATION_OPTS = --temp-config $(top_srcdir)/contrib/pg_logicalinspect/logicalinspect.conf + +# Disabled because these tests require "wal_level=logical", which +# some installcheck users do not have (e.g. buildfarm clients). +NO_INSTALLCHECK = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/pg_logicalinspect +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/pg_logicalinspect/expected/logical_inspect.out b/contrib/pg_logicalinspect/expected/logical_inspect.out new file mode 100644 index 0000000000000..b343d3ad73388 --- /dev/null +++ b/contrib/pg_logicalinspect/expected/logical_inspect.out @@ -0,0 +1,32 @@ +Parsed test spec with 2 sessions + +starting permutation: s0_init s0_begin s0_savepoint s0_truncate s1_create_table s1_checkpoint s1_get_changes s1_check_snapshot_info s1_check_snapshot_meta s0_commit +step s0_init: SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); +?column? +-------- +init +(1 row) + +step s0_begin: BEGIN; +step s0_savepoint: SAVEPOINT sp1; +step s0_truncate: TRUNCATE tbl1; +step s1_create_table: CREATE TABLE tbl2 (val1 integer, val2 integer); +step s1_checkpoint: CHECKPOINT; +step s1_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0'); +data +---- +(0 rows) + +step s1_check_snapshot_info: SELECT count(*) > 0 as has_info FROM pg_ls_logicalsnapdir(), pg_get_logical_snapshot_info(name) AS info where info.catchange_count >= 2 and array_length(info.catchange_xip,1) >= 2 and info.committed_count >= 1 and array_length(info.committed_xip,1) >= 1; +has_info +-------- +t +(1 row) + +step s1_check_snapshot_meta: SELECT count(meta.*) > 0 AS has_meta from pg_ls_logicalsnapdir(), pg_get_logical_snapshot_meta(name) as meta; +has_meta +-------- +t +(1 row) + +step s0_commit: COMMIT; diff --git a/contrib/pg_logicalinspect/expected/pg_logicalinspect.out b/contrib/pg_logicalinspect/expected/pg_logicalinspect.out new file mode 100644 index 0000000000000..f6c9b625d6b42 --- /dev/null +++ b/contrib/pg_logicalinspect/expected/pg_logicalinspect.out @@ -0,0 +1,81 @@ +CREATE EXTENSION pg_logicalinspect; +-- =================================================================== +-- Tests for input validation +-- =================================================================== +SELECT pg_get_logical_snapshot_info('0-40796E18.foo'); +ERROR: invalid snapshot file name "0-40796E18.foo" +SELECT pg_get_logical_snapshot_info('0--40796E18.snap'); +ERROR: invalid snapshot file name "0--40796E18.snap" +SELECT pg_get_logical_snapshot_info('-1--40796E18.snap'); +ERROR: invalid snapshot file name "-1--40796E18.snap" +SELECT pg_get_logical_snapshot_info('0/40796E18.foo.snap'); +ERROR: invalid snapshot file name "0/40796E18.foo.snap" +SELECT pg_get_logical_snapshot_info('0/40796E18.snap'); +ERROR: invalid snapshot file name "0/40796E18.snap" +SELECT pg_get_logical_snapshot_info(''); +ERROR: invalid snapshot file name "" +SELECT pg_get_logical_snapshot_info(NULL); + pg_get_logical_snapshot_info +------------------------------ + +(1 row) + +SELECT pg_get_logical_snapshot_info('../snapshots'); +ERROR: invalid snapshot file name "../snapshots" +SELECT pg_get_logical_snapshot_info('../snapshots/0-40796E18.snap'); +ERROR: invalid snapshot file name "../snapshots/0-40796E18.snap" +SELECT pg_get_logical_snapshot_meta('0-40796E18.foo'); +ERROR: invalid snapshot file name "0-40796E18.foo" +SELECT pg_get_logical_snapshot_meta('0-40796E18.foo.snap'); +ERROR: invalid snapshot file name "0-40796E18.foo.snap" +SELECT pg_get_logical_snapshot_meta('0/40796E18.snap'); +ERROR: invalid snapshot file name "0/40796E18.snap" +SELECT pg_get_logical_snapshot_meta(''); +ERROR: invalid snapshot file name "" +SELECT pg_get_logical_snapshot_meta(NULL); + pg_get_logical_snapshot_meta +------------------------------ + +(1 row) + +SELECT pg_get_logical_snapshot_meta('../snapshots'); +ERROR: invalid snapshot file name "../snapshots" +-- =================================================================== +-- Tests for permissions +-- =================================================================== +CREATE ROLE regress_pg_logicalinspect; +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_info(text)', 'EXECUTE'); -- no + has_function_privilege +------------------------ + f +(1 row) + +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_meta(text)', 'EXECUTE'); -- no + has_function_privilege +------------------------ + f +(1 row) + +-- Functions accessible by users with role pg_read_server_files. +GRANT pg_read_server_files TO regress_pg_logicalinspect; +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_info(text)', 'EXECUTE'); -- yes + has_function_privilege +------------------------ + t +(1 row) + +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_meta(text)', 'EXECUTE'); -- yes + has_function_privilege +------------------------ + t +(1 row) + +-- =================================================================== +-- Clean up +-- =================================================================== +DROP ROLE regress_pg_logicalinspect; +DROP EXTENSION pg_logicalinspect; diff --git a/contrib/pg_logicalinspect/logicalinspect.conf b/contrib/pg_logicalinspect/logicalinspect.conf new file mode 100644 index 0000000000000..e3d257315fa58 --- /dev/null +++ b/contrib/pg_logicalinspect/logicalinspect.conf @@ -0,0 +1 @@ +wal_level = logical diff --git a/contrib/pg_logicalinspect/meson.build b/contrib/pg_logicalinspect/meson.build new file mode 100644 index 0000000000000..5c0528a8c63ed --- /dev/null +++ b/contrib/pg_logicalinspect/meson.build @@ -0,0 +1,39 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +pg_logicalinspect_sources = files('pg_logicalinspect.c') + +if host_system == 'windows' + pg_logicalinspect_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_logicalinspect', + '--FILEDESC', 'pg_logicalinspect - functions to inspect logical decoding components',]) +endif + +pg_logicalinspect = shared_module('pg_logicalinspect', + pg_logicalinspect_sources, + kwargs: contrib_mod_args + { + 'dependencies': contrib_mod_args['dependencies'], + }, +) +contrib_targets += pg_logicalinspect + +install_data( + 'pg_logicalinspect.control', + 'pg_logicalinspect--1.0.sql', + kwargs: contrib_data_args, +) + +tests += { + 'name': 'pg_logicalinspect', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'isolation': { + 'specs': [ + 'logical_inspect', + ], + 'regress_args': [ + '--temp-config', files('logicalinspect.conf'), + ], + # see above + 'runningcheck': false, + }, +} diff --git a/contrib/pg_logicalinspect/pg_logicalinspect--1.0.sql b/contrib/pg_logicalinspect/pg_logicalinspect--1.0.sql new file mode 100644 index 0000000000000..8f7f947cbb39b --- /dev/null +++ b/contrib/pg_logicalinspect/pg_logicalinspect--1.0.sql @@ -0,0 +1,43 @@ +/* contrib/pg_logicalinspect/pg_logicalinspect--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION pg_logicalinspect" to load this file. \quit + +-- +-- pg_get_logical_snapshot_meta() +-- +CREATE FUNCTION pg_get_logical_snapshot_meta(IN filename text, + OUT magic int4, + OUT checksum int8, + OUT version int4 +) +AS 'MODULE_PATHNAME', 'pg_get_logical_snapshot_meta' +LANGUAGE C STRICT PARALLEL SAFE; + +REVOKE EXECUTE ON FUNCTION pg_get_logical_snapshot_meta(text) FROM PUBLIC; +GRANT EXECUTE ON FUNCTION pg_get_logical_snapshot_meta(text) TO pg_read_server_files; + +-- +-- pg_get_logical_snapshot_info() +-- +CREATE FUNCTION pg_get_logical_snapshot_info(IN filename text, + OUT state text, + OUT xmin xid, + OUT xmax xid, + OUT start_decoding_at pg_lsn, + OUT two_phase_at pg_lsn, + OUT initial_xmin_horizon xid, + OUT building_full_snapshot boolean, + OUT in_slot_creation boolean, + OUT last_serialized_snapshot pg_lsn, + OUT next_phase_at xid, + OUT committed_count int4, + OUT committed_xip xid[], + OUT catchange_count int4, + OUT catchange_xip xid[] +) +AS 'MODULE_PATHNAME', 'pg_get_logical_snapshot_info' +LANGUAGE C STRICT PARALLEL SAFE; + +REVOKE EXECUTE ON FUNCTION pg_get_logical_snapshot_info(text) FROM PUBLIC; +GRANT EXECUTE ON FUNCTION pg_get_logical_snapshot_info(text) TO pg_read_server_files; diff --git a/contrib/pg_logicalinspect/pg_logicalinspect.c b/contrib/pg_logicalinspect/pg_logicalinspect.c new file mode 100644 index 0000000000000..50e805d3195e0 --- /dev/null +++ b/contrib/pg_logicalinspect/pg_logicalinspect.c @@ -0,0 +1,207 @@ +/*------------------------------------------------------------------------- + * + * pg_logicalinspect.c + * Functions to inspect contents of PostgreSQL logical snapshots + * + * Copyright (c) 2024-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * contrib/pg_logicalinspect/pg_logicalinspect.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "funcapi.h" +#include "replication/snapbuild_internal.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/pg_lsn.h" + +PG_MODULE_MAGIC_EXT( + .name = "pg_logicalinspect", + .version = PG_VERSION +); + +PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_meta); +PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_info); + +/* Return the description of SnapBuildState */ +static const char * +get_snapbuild_state_desc(SnapBuildState state) +{ + const char *stateDesc = "unknown state"; + + switch (state) + { + case SNAPBUILD_START: + stateDesc = "start"; + break; + case SNAPBUILD_BUILDING_SNAPSHOT: + stateDesc = "building"; + break; + case SNAPBUILD_FULL_SNAPSHOT: + stateDesc = "full"; + break; + case SNAPBUILD_CONSISTENT: + stateDesc = "consistent"; + break; + } + + return stateDesc; +} + +/* + * Extract the LSN from the given serialized snapshot file name. + */ +static XLogRecPtr +parse_snapshot_filename(const char *filename) +{ + uint32 hi; + uint32 lo; + XLogRecPtr lsn; + char tmpfname[MAXPGPATH]; + + /* + * Extract the values to build the LSN. + * + * Note: Including ".snap" doesn't mean that sscanf() also does the format + * check including the suffix. The subsequent check validates if the given + * filename has the expected suffix. + */ + if (sscanf(filename, "%X-%X.snap", &hi, &lo) != 2) + goto parse_error; + + /* + * Bring back the extracted LSN to the snapshot file format and compare it + * to the given filename. This check strictly checks if the given filename + * follows the format of the snapshot filename. + */ + sprintf(tmpfname, "%X-%X.snap", hi, lo); + if (strcmp(tmpfname, filename) != 0) + goto parse_error; + + lsn = ((uint64) hi) << 32 | lo; + + return lsn; + +parse_error: + ereport(ERROR, + errmsg("invalid snapshot file name \"%s\"", filename)); + + return InvalidXLogRecPtr; /* keep compiler quiet */ +} + +/* + * Retrieve the logical snapshot file metadata. + */ +Datum +pg_get_logical_snapshot_meta(PG_FUNCTION_ARGS) +{ +#define PG_GET_LOGICAL_SNAPSHOT_META_COLS 3 + SnapBuildOnDisk ondisk; + HeapTuple tuple; + Datum values[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0}; + bool nulls[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0}; + TupleDesc tupdesc; + XLogRecPtr lsn; + int i = 0; + text *filename_t = PG_GETARG_TEXT_PP(0); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + lsn = parse_snapshot_filename(text_to_cstring(filename_t)); + + /* Validate and restore the snapshot to 'ondisk' */ + SnapBuildRestoreSnapshot(&ondisk, lsn, CurrentMemoryContext, false); + + values[i++] = UInt32GetDatum(ondisk.magic); + values[i++] = Int64GetDatum((int64) ondisk.checksum); + values[i++] = UInt32GetDatum(ondisk.version); + + Assert(i == PG_GET_LOGICAL_SNAPSHOT_META_COLS); + + tuple = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + +#undef PG_GET_LOGICAL_SNAPSHOT_META_COLS +} + +Datum +pg_get_logical_snapshot_info(PG_FUNCTION_ARGS) +{ +#define PG_GET_LOGICAL_SNAPSHOT_INFO_COLS 14 + SnapBuildOnDisk ondisk; + HeapTuple tuple; + Datum values[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0}; + bool nulls[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0}; + TupleDesc tupdesc; + XLogRecPtr lsn; + int i = 0; + text *filename_t = PG_GETARG_TEXT_PP(0); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + lsn = parse_snapshot_filename(text_to_cstring(filename_t)); + + /* Validate and restore the snapshot to 'ondisk' */ + SnapBuildRestoreSnapshot(&ondisk, lsn, CurrentMemoryContext, false); + + values[i++] = CStringGetTextDatum(get_snapbuild_state_desc(ondisk.builder.state)); + values[i++] = TransactionIdGetDatum(ondisk.builder.xmin); + values[i++] = TransactionIdGetDatum(ondisk.builder.xmax); + values[i++] = LSNGetDatum(ondisk.builder.start_decoding_at); + values[i++] = LSNGetDatum(ondisk.builder.two_phase_at); + values[i++] = TransactionIdGetDatum(ondisk.builder.initial_xmin_horizon); + values[i++] = BoolGetDatum(ondisk.builder.building_full_snapshot); + values[i++] = BoolGetDatum(ondisk.builder.in_slot_creation); + values[i++] = LSNGetDatum(ondisk.builder.last_serialized_snapshot); + values[i++] = TransactionIdGetDatum(ondisk.builder.next_phase_at); + + values[i++] = UInt32GetDatum(ondisk.builder.committed.xcnt); + if (ondisk.builder.committed.xcnt > 0) + { + Datum *arrayelems; + + arrayelems = (Datum *) palloc(ondisk.builder.committed.xcnt * sizeof(Datum)); + + for (int j = 0; j < ondisk.builder.committed.xcnt; j++) + arrayelems[j] = TransactionIdGetDatum(ondisk.builder.committed.xip[j]); + + values[i++] = PointerGetDatum(construct_array_builtin(arrayelems, + ondisk.builder.committed.xcnt, + XIDOID)); + } + else + nulls[i++] = true; + + values[i++] = UInt32GetDatum(ondisk.builder.catchange.xcnt); + if (ondisk.builder.catchange.xcnt > 0) + { + Datum *arrayelems; + + arrayelems = (Datum *) palloc(ondisk.builder.catchange.xcnt * sizeof(Datum)); + + for (int j = 0; j < ondisk.builder.catchange.xcnt; j++) + arrayelems[j] = TransactionIdGetDatum(ondisk.builder.catchange.xip[j]); + + values[i++] = PointerGetDatum(construct_array_builtin(arrayelems, + ondisk.builder.catchange.xcnt, + XIDOID)); + } + else + nulls[i++] = true; + + Assert(i == PG_GET_LOGICAL_SNAPSHOT_INFO_COLS); + + tuple = heap_form_tuple(tupdesc, values, nulls); + + PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); + +#undef PG_GET_LOGICAL_SNAPSHOT_INFO_COLS +} diff --git a/contrib/pg_logicalinspect/pg_logicalinspect.control b/contrib/pg_logicalinspect/pg_logicalinspect.control new file mode 100644 index 0000000000000..b4a70e57ba250 --- /dev/null +++ b/contrib/pg_logicalinspect/pg_logicalinspect.control @@ -0,0 +1,5 @@ +# pg_logicalinspect extension +comment = 'functions to inspect logical decoding components' +default_version = '1.0' +module_pathname = '$libdir/pg_logicalinspect' +relocatable = true diff --git a/contrib/pg_logicalinspect/specs/logical_inspect.spec b/contrib/pg_logicalinspect/specs/logical_inspect.spec new file mode 100644 index 0000000000000..26b2db10f3ea8 --- /dev/null +++ b/contrib/pg_logicalinspect/specs/logical_inspect.spec @@ -0,0 +1,46 @@ +# Test the pg_logicalinspect functions: that needs some permutation to +# ensure that we are creating at least one snapshot that contains ongoing and +# committed catalogs changes. +setup +{ + DROP TABLE IF EXISTS tbl1; + DROP TABLE IF EXISTS tbl2; + CREATE TABLE tbl1 (val1 integer, val2 integer); + CREATE EXTENSION pg_logicalinspect; +} + +teardown +{ + DROP TABLE tbl1; + DROP TABLE tbl2; + SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot'); + DROP EXTENSION pg_logicalinspect; +} + +session "s0" +setup { SET synchronous_commit=on; } +step "s0_init" { SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); } +step "s0_begin" { BEGIN; } +step "s0_savepoint" { SAVEPOINT sp1; } +step "s0_truncate" { TRUNCATE tbl1; } +step "s0_commit" { COMMIT; } + +session "s1" +setup { SET synchronous_commit=on; } +step "s1_checkpoint" { CHECKPOINT; } +step "s1_create_table" { CREATE TABLE tbl2 (val1 integer, val2 integer); } +step "s1_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'skip-empty-xacts', '1', 'include-xids', '0'); } +step "s1_check_snapshot_meta" { SELECT count(meta.*) > 0 AS has_meta from pg_ls_logicalsnapdir(), pg_get_logical_snapshot_meta(name) as meta; } +step "s1_check_snapshot_info" { SELECT count(*) > 0 as has_info FROM pg_ls_logicalsnapdir(), pg_get_logical_snapshot_info(name) AS info where info.catchange_count >= 2 and array_length(info.catchange_xip,1) >= 2 and info.committed_count >= 1 and array_length(info.committed_xip,1) >= 1; } + + +# Both s0 and s1 execute catalog-change transactions. When "s1_get_changes" is +# executed, s0's transaction is still in progress, while s1's transaction has +# already completed. Consequently, the logical decoding produces a snapshot at +# the point where a RUNNING_XACTS record is generated by "s1_checkpoint". +# This snapshot contains both two ongoing catalog-change transactions (from s0's +# top-level and sub transactions) and one completed transaction (from s1). +# "s1_check_snapshot_info" verifies whether the logical snapshot contains at +# least the expected number of transactions, accounting for potential +# additional catalog changes that may occur due to concurrent autoanalyze. +permutation "s0_init" "s0_begin" "s0_savepoint" "s0_truncate" "s1_create_table" "s1_checkpoint" "s1_get_changes" "s1_check_snapshot_info" "s1_check_snapshot_meta" "s0_commit" diff --git a/contrib/pg_logicalinspect/sql/pg_logicalinspect.sql b/contrib/pg_logicalinspect/sql/pg_logicalinspect.sql new file mode 100644 index 0000000000000..143cf45dc12b8 --- /dev/null +++ b/contrib/pg_logicalinspect/sql/pg_logicalinspect.sql @@ -0,0 +1,48 @@ +CREATE EXTENSION pg_logicalinspect; + +-- =================================================================== +-- Tests for input validation +-- =================================================================== + +SELECT pg_get_logical_snapshot_info('0-40796E18.foo'); +SELECT pg_get_logical_snapshot_info('0--40796E18.snap'); +SELECT pg_get_logical_snapshot_info('-1--40796E18.snap'); +SELECT pg_get_logical_snapshot_info('0/40796E18.foo.snap'); +SELECT pg_get_logical_snapshot_info('0/40796E18.snap'); +SELECT pg_get_logical_snapshot_info(''); +SELECT pg_get_logical_snapshot_info(NULL); +SELECT pg_get_logical_snapshot_info('../snapshots'); +SELECT pg_get_logical_snapshot_info('../snapshots/0-40796E18.snap'); + +SELECT pg_get_logical_snapshot_meta('0-40796E18.foo'); +SELECT pg_get_logical_snapshot_meta('0-40796E18.foo.snap'); +SELECT pg_get_logical_snapshot_meta('0/40796E18.snap'); +SELECT pg_get_logical_snapshot_meta(''); +SELECT pg_get_logical_snapshot_meta(NULL); +SELECT pg_get_logical_snapshot_meta('../snapshots'); + +-- =================================================================== +-- Tests for permissions +-- =================================================================== +CREATE ROLE regress_pg_logicalinspect; + +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_info(text)', 'EXECUTE'); -- no +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_meta(text)', 'EXECUTE'); -- no + +-- Functions accessible by users with role pg_read_server_files. +GRANT pg_read_server_files TO regress_pg_logicalinspect; + +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_info(text)', 'EXECUTE'); -- yes +SELECT has_function_privilege('regress_pg_logicalinspect', + 'pg_get_logical_snapshot_meta(text)', 'EXECUTE'); -- yes + +-- =================================================================== +-- Clean up +-- =================================================================== + +DROP ROLE regress_pg_logicalinspect; + +DROP EXTENSION pg_logicalinspect; diff --git a/contrib/pg_overexplain/.gitignore b/contrib/pg_overexplain/.gitignore new file mode 100644 index 0000000000000..5dcb3ff972350 --- /dev/null +++ b/contrib/pg_overexplain/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/pg_overexplain/Makefile b/contrib/pg_overexplain/Makefile new file mode 100644 index 0000000000000..f1c39ecebc11d --- /dev/null +++ b/contrib/pg_overexplain/Makefile @@ -0,0 +1,21 @@ +# contrib/pg_overexplain/Makefile + +MODULE_big = pg_overexplain +OBJS = \ + $(WIN32RES) \ + pg_overexplain.o + +PGFILEDESC = "pg_overexplain - allow EXPLAIN to dump even more details" + +REGRESS = pg_overexplain + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/pg_overexplain +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/pg_overexplain/expected/pg_overexplain.out b/contrib/pg_overexplain/expected/pg_overexplain.out new file mode 100644 index 0000000000000..6de02323d7cfc --- /dev/null +++ b/contrib/pg_overexplain/expected/pg_overexplain.out @@ -0,0 +1,489 @@ +-- These tests display internal details that would not be stable under +-- debug_parallel_query, so make sure that option is disabled. +SET debug_parallel_query = off; +-- Make sure that we don't print any JIT-related information, as that +-- would also make results unstable. +SET jit = off; +-- These options do not exist, so these queries should all fail. +EXPLAIN (DEBUFF) SELECT 1; +ERROR: unrecognized EXPLAIN option "debuff" +LINE 1: EXPLAIN (DEBUFF) SELECT 1; + ^ +EXPLAIN (DEBUG) SELECT 1; +ERROR: unrecognized EXPLAIN option "debug" +LINE 1: EXPLAIN (DEBUG) SELECT 1; + ^ +EXPLAIN (RANGE_TABLE) SELECT 1; +ERROR: unrecognized EXPLAIN option "range_table" +LINE 1: EXPLAIN (RANGE_TABLE) SELECT 1; + ^ +-- Load the module that creates the options. +LOAD 'pg_overexplain'; +-- The first option still does not exist, but the others do. +EXPLAIN (DEBUFF) SELECT 1; +ERROR: unrecognized EXPLAIN option "debuff" +LINE 1: EXPLAIN (DEBUFF) SELECT 1; + ^ +EXPLAIN (DEBUG) SELECT 1; + QUERY PLAN +------------------------------------------ + Result (cost=0.00..0.01 rows=1 width=4) + Disabled Nodes: 0 + Parallel Safe: false + Plan Node ID: 0 + PlannedStmt: + Command Type: select + Flags: canSetTag + Subplans Needing Rewind: none + Relation OIDs: none + Executor Parameter Types: none + Parse Location: 0 to end +(11 rows) + +EXPLAIN (RANGE_TABLE) SELECT 1; + QUERY PLAN +------------------------------------------ + Result (cost=0.00..0.01 rows=1 width=4) + RTI 1 (result): + Eref: "*RESULT*" () +(3 rows) + +-- Create a partitioned table. +CREATE TABLE vegetables (id serial, name text, genus text) +PARTITION BY LIST (genus); +CREATE TABLE daucus PARTITION OF vegetables FOR VALUES IN ('daucus'); +CREATE TABLE brassica PARTITION OF vegetables FOR VALUES IN ('brassica'); +INSERT INTO vegetables (name, genus) + VALUES ('carrot', 'daucus'), ('bok choy', 'brassica'), + ('brocooli', 'brassica'), ('cauliflower', 'brassica'), + ('cabbage', 'brassica'), ('kohlrabi', 'brassica'), + ('rutabaga', 'brassica'), ('turnip', 'brassica'); +VACUUM ANALYZE vegetables; +-- We filter relation OIDs out of the test output in order to avoid +-- test instability. This is currently only needed for EXPLAIN (DEBUG), not +-- EXPLAIN (RANGE_TABLE). Also suppress actual row counts, which are not +-- stable (e.g. 1/8 is 0.12 on some buildfarm machines and 0.13 on others). +CREATE FUNCTION explain_filter(text) RETURNS SETOF text +LANGUAGE plpgsql AS +$$ +DECLARE + ln text; +BEGIN + FOR ln IN EXECUTE $1 + LOOP + ln := regexp_replace(ln, 'Relation OIDs:( \m\d+\M)+', + 'Relation OIDs: NNN...', 'g'); + ln := regexp_replace(ln, '( ?\m\d+\M)+', + 'NNN...', 'g'); + ln := regexp_replace(ln, 'actual rows=\d+\.\d+', + 'actual rows=N.NN', 'g'); + RETURN NEXT ln; + END LOOP; +END; +$$; +-- Test with both options together and an aggregate. +SELECT explain_filter($$ +EXPLAIN (DEBUG, RANGE_TABLE, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + explain_filter +----------------------------------------------------- + GroupAggregate + Group Key: vegetables.genus + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 0 + -> Sort + Sort Key: vegetables.genus, vegetables.name + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 1 + -> Append + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 2 + Append RTIs: 1 + -> Seq Scan on brassica vegetables_1 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 3 + Scan RTI: 3 + -> Seq Scan on daucus vegetables_2 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 4 + Scan RTI: 4 + PlannedStmt: + Command Type: select + Flags: canSetTag + Subplans Needing Rewind: none + Relation OIDs: NNN... + Executor Parameter Types: none + Parse Location: 0 to end + RTI 1 (relation, inherited, in-from-clause): + Eref: vegetables (id, name, genus) + Relation: vegetables + Relation Kind: partitioned_table + Relation Lock Mode: AccessShareLock + Permission Info Index: 1 + RTI 2 (group): + Eref: "*GROUP*" (genus) + RTI 3 (relation, in-from-clause): + Alias: vegetables (id, name, genus) + Eref: vegetables (id, name, genus) + Relation: brassica + Relation Kind: relation + Relation Lock Mode: AccessShareLock + RTI 4 (relation, in-from-clause): + Alias: vegetables (id, name, genus) + Eref: vegetables (id, name, genus) + Relation: daucus + Relation Kind: relation + Relation Lock Mode: AccessShareLock + Unprunable RTIs: 1 3 4 +(53 rows) + +-- Test a different output format. +SELECT explain_filter($$ +EXPLAIN (DEBUG, RANGE_TABLE, FORMAT XML, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + explain_filter +--------------------------------------------------------------------- + + + + + + + Aggregate + + Sorted + + Simple + + false + + false + + false + + + + vegetables.genus + + + + 0 + + true + + 0 + + none + + none + + + + + + Sort + + Outer + + false + + false + + false + + + + vegetables.genus + + vegetables.name + + + + 0 + + true + + 1 + + none + + none + + + + + + Append + + Outer + + false + + false + + false + + 0 + + true + + 2 + + none + + none + + 1 + + 0 + + + + + + Seq Scan + + Member+ + false + + false + + brassica + + vegetables_1 + + false + + 0 + + true + + 3 + + none + + none + + 3 + + + + + + Seq Scan + + Member+ + false + + false + + daucus + + vegetables_2 + + false + + 0 + + true + + 4 + + none + + none + + 4 + + + + + + + + + + + + + + + + + + select + + canSetTag + + none + + NNN... + + none + + 0 to end + + + + + + + + 1 + + relation + + true + + true + + vegetables (id, name, genus) + + vegetables + + partitioned_table + + AccessShareLock + + 1 + + false + + false + + + + + + 2 + + group + + false + + false + + "*GROUP*" (genus) + + false + + false + + + + + + 3 + + relation + + false + + true + + vegetables (id, name, genus) + + vegetables (id, name, genus) + + brassica + + relation + + AccessShareLock + + false + + false + + + + + + 4 + + relation + + false + + true + + vegetables (id, name, genus) + + vegetables (id, name, genus) + + daucus + + relation + + AccessShareLock + + false + + false + + + + 1 3 4 + + none + + + + + + +(1 row) + +-- Test just the DEBUG option. Verify that it shows information about +-- disabled nodes, parallel safety, and the parallelModeNeeded flag. +SET enable_seqscan = false; +SET debug_parallel_query = true; +SELECT explain_filter($$ +EXPLAIN (DEBUG, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + explain_filter +----------------------------------------------------------- + Gather + Workers Planned: 1 + Single Copy: true + Disabled Nodes: 0 + Parallel Safe: false + Plan Node ID: 0 + -> GroupAggregate + Group Key: vegetables.genus + Disabled Nodes: 2 + Parallel Safe: true + Plan Node ID: 1 + -> Sort + Sort Key: vegetables.genus, vegetables.name + Disabled Nodes: 2 + Parallel Safe: true + Plan Node ID: 2 + -> Append + Disabled Nodes: 2 + Parallel Safe: true + Plan Node ID: 3 + -> Seq Scan on brassica vegetables_1 + Disabled: true + Disabled Nodes: 1 + Parallel Safe: true + Plan Node ID: 4 + -> Seq Scan on daucus vegetables_2 + Disabled: true + Disabled Nodes: 1 + Parallel Safe: true + Plan Node ID: 5 + PlannedStmt: + Command Type: select + Flags: canSetTag, parallelModeNeeded + Subplans Needing Rewind: none + Relation OIDs: NNN... + Executor Parameter Types: none + Parse Location: 0 to end +(37 rows) + +SET debug_parallel_query = false; +RESET enable_seqscan; +-- Test the DEBUG option with a non-SELECT query, and also verify that the +-- hasReturning flag is shown. +SELECT explain_filter($$ +EXPLAIN (DEBUG, COSTS OFF) +INSERT INTO vegetables (name, genus) + VALUES ('Brotero''s carrot', 'brassica') RETURNING id +$$); + explain_filter +---------------------------------- + Insert on vegetables + Disabled Nodes: 0 + Parallel Safe: false + Plan Node ID: 0 + -> Result + Disabled Nodes: 0 + Parallel Safe: false + Plan Node ID: 1 + PlannedStmt: + Command Type: insert + Flags: hasReturning, canSetTag + Subplans Needing Rewind: none + Relation OIDs: NNN... + Executor Parameter Types: 0 + Parse Location: 0 to end +(15 rows) + +-- Create an index, and then attempt to force a nested loop with inner index +-- scan so that we can see parameter-related information. Also, let's try +-- actually running the query, but try to suppress potentially variable output. +CREATE INDEX ON vegetables (id); +ANALYZE vegetables; +SET enable_hashjoin = false; +SET enable_material = false; +SET enable_mergejoin = false; +SET enable_seqscan = false; +SELECT explain_filter($$ +EXPLAIN (BUFFERS OFF, COSTS OFF, SUMMARY OFF, TIMING OFF, ANALYZE, DEBUG) +SELECT * FROM vegetables v1, vegetables v2 WHERE v1.id = v2.id; +$$); + explain_filter +------------------------------------------------------------------------------------------ + Nested Loop (actual rows=N.NN loops=1) + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 0 + -> Append (actual rows=N.NN loops=1) + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 1 + -> Index Scan using brassica_id_idx on brassica v1_1 (actual rows=N.NN loops=1) + Index Searches: 1 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 2 + -> Index Scan using daucus_id_idx on daucus v1_2 (actual rows=N.NN loops=1) + Index Searches: 1 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 3 + -> Append (actual rows=N.NN loops=8) + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 4 + extParam: 0 + allParam: 0 + -> Index Scan using brassica_id_idx on brassica v2_1 (actual rows=N.NN loops=8) + Index Cond: (id = v1.id) + Index Searches: 8 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 5 + extParam: 0 + allParam: 0 + -> Index Scan using daucus_id_idx on daucus v2_2 (actual rows=N.NN loops=8) + Index Cond: (id = v1.id) + Index Searches: 8 + Disabled Nodes: 0 + Parallel Safe: true + Plan Node ID: 6 + extParam: 0 + allParam: 0 + PlannedStmt: + Command Type: select + Flags: canSetTag + Subplans Needing Rewind: none + Relation OIDs: NNN... + Executor Parameter Types: 23 + Parse Location: 0 to end +(47 rows) + +RESET enable_hashjoin; +RESET enable_material; +RESET enable_mergejoin; +RESET enable_seqscan; +-- Test the RANGE_TABLE option with a case that allows partition pruning. +EXPLAIN (RANGE_TABLE, COSTS OFF) +SELECT * FROM vegetables WHERE genus = 'daucus'; + QUERY PLAN +---------------------------------------------- + Seq Scan on daucus vegetables + Filter: (genus = 'daucus'::text) + Scan RTI: 2 + RTI 1 (relation, inherited, in-from-clause): + Eref: vegetables (id, name, genus) + Relation: vegetables + Relation Kind: partitioned_table + Relation Lock Mode: AccessShareLock + Permission Info Index: 1 + RTI 2 (relation, in-from-clause): + Alias: vegetables (id, name, genus) + Eref: vegetables (id, name, genus) + Relation: daucus + Relation Kind: relation + Relation Lock Mode: AccessShareLock + Unprunable RTIs: 1 2 +(16 rows) + +-- Also test a case that involves a write. +EXPLAIN (RANGE_TABLE, COSTS OFF) +INSERT INTO vegetables (name, genus) VALUES ('broccoflower', 'brassica'); + QUERY PLAN +---------------------------------------- + Insert on vegetables + Nominal RTI: 1 + Exclude Relation RTI: 0 + -> Result + RTI 1 (relation): + Eref: vegetables (id, name, genus) + Relation: vegetables + Relation Kind: partitioned_table + Relation Lock Mode: RowExclusiveLock + Permission Info Index: 1 + RTI 2 (result): + Eref: "*RESULT*" () + Unprunable RTIs: 1 + Result RTIs: 1 +(14 rows) + diff --git a/contrib/pg_overexplain/meson.build b/contrib/pg_overexplain/meson.build new file mode 100644 index 0000000000000..6f52d1e51bc7e --- /dev/null +++ b/contrib/pg_overexplain/meson.build @@ -0,0 +1,28 @@ +# Copyright (c) 2022-2025, PostgreSQL Global Development Group + +pg_overexplain_sources = files( + 'pg_overexplain.c', +) + +if host_system == 'windows' + pg_overexplain_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_overexplain', + '--FILEDESC', 'pg_overexplain - allow EXPLAIN to dump even more details',]) +endif + +pg_overexplain = shared_module('pg_overexplain', + pg_overexplain_sources, + kwargs: contrib_mod_args, +) +contrib_targets += pg_overexplain + +tests += { + 'name': 'pg_overexplain', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'pg_overexplain', + ], + }, +} diff --git a/contrib/pg_overexplain/pg_overexplain.c b/contrib/pg_overexplain/pg_overexplain.c new file mode 100644 index 0000000000000..de824566f8c90 --- /dev/null +++ b/contrib/pg_overexplain/pg_overexplain.c @@ -0,0 +1,774 @@ +/*------------------------------------------------------------------------- + * + * pg_overexplain.c + * allow EXPLAIN to dump even more details + * + * Copyright (c) 2016-2025, PostgreSQL Global Development Group + * + * contrib/pg_overexplain/pg_overexplain.c + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "catalog/pg_class.h" +#include "commands/defrem.h" +#include "commands/explain.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" +#include "fmgr.h" +#include "parser/parsetree.h" +#include "storage/lock.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" + +PG_MODULE_MAGIC_EXT( + .name = "pg_overexplain", + .version = PG_VERSION +); + +typedef struct +{ + bool debug; + bool range_table; +} overexplain_options; + +static overexplain_options *overexplain_ensure_options(ExplainState *es); +static void overexplain_debug_handler(ExplainState *es, DefElem *opt, + ParseState *pstate); +static void overexplain_range_table_handler(ExplainState *es, DefElem *opt, + ParseState *pstate); +static void overexplain_per_node_hook(PlanState *planstate, List *ancestors, + const char *relationship, + const char *plan_name, + ExplainState *es); +static void overexplain_per_plan_hook(PlannedStmt *plannedstmt, + IntoClause *into, + ExplainState *es, + const char *queryString, + ParamListInfo params, + QueryEnvironment *queryEnv); +static void overexplain_debug(PlannedStmt *plannedstmt, ExplainState *es); +static void overexplain_range_table(PlannedStmt *plannedstmt, + ExplainState *es); +static void overexplain_alias(const char *qlabel, Alias *alias, + ExplainState *es); +static void overexplain_bitmapset(const char *qlabel, Bitmapset *bms, + ExplainState *es); +static void overexplain_intlist(const char *qlabel, List *list, + ExplainState *es); + +static int es_extension_id; +static explain_per_node_hook_type prev_explain_per_node_hook; +static explain_per_plan_hook_type prev_explain_per_plan_hook; + +/* + * Initialization we do when this module is loaded. + */ +void +_PG_init(void) +{ + /* Get an ID that we can use to cache data in an ExplainState. */ + es_extension_id = GetExplainExtensionId("pg_overexplain"); + + /* Register the new EXPLAIN options implemented by this module. */ + RegisterExtensionExplainOption("debug", overexplain_debug_handler); + RegisterExtensionExplainOption("range_table", + overexplain_range_table_handler); + + /* Use the per-node and per-plan hooks to make our options do something. */ + prev_explain_per_node_hook = explain_per_node_hook; + explain_per_node_hook = overexplain_per_node_hook; + prev_explain_per_plan_hook = explain_per_plan_hook; + explain_per_plan_hook = overexplain_per_plan_hook; +} + +/* + * Get the overexplain_options structure from an ExplainState; if there is + * none, create one, attach it to the ExplainState, and return it. + */ +static overexplain_options * +overexplain_ensure_options(ExplainState *es) +{ + overexplain_options *options; + + options = GetExplainExtensionState(es, es_extension_id); + + if (options == NULL) + { + options = palloc0(sizeof(overexplain_options)); + SetExplainExtensionState(es, es_extension_id, options); + } + + return options; +} + +/* + * Parse handler for EXPLAIN (DEBUG). + */ +static void +overexplain_debug_handler(ExplainState *es, DefElem *opt, ParseState *pstate) +{ + overexplain_options *options = overexplain_ensure_options(es); + + options->debug = defGetBoolean(opt); +} + +/* + * Parse handler for EXPLAIN (RANGE_TABLE). + */ +static void +overexplain_range_table_handler(ExplainState *es, DefElem *opt, + ParseState *pstate) +{ + overexplain_options *options = overexplain_ensure_options(es); + + options->range_table = defGetBoolean(opt); +} + +/* + * Print out additional per-node information as appropriate. If the user didn't + * specify any of the options we support, do nothing; else, print whatever is + * relevant to the specified options. + */ +static void +overexplain_per_node_hook(PlanState *planstate, List *ancestors, + const char *relationship, const char *plan_name, + ExplainState *es) +{ + overexplain_options *options; + Plan *plan = planstate->plan; + + if (prev_explain_per_node_hook) + (*prev_explain_per_node_hook) (planstate, ancestors, relationship, + plan_name, es); + + options = GetExplainExtensionState(es, es_extension_id); + if (options == NULL) + return; + + /* + * If the "debug" option was given, display miscellaneous fields from the + * "Plan" node that would not otherwise be displayed. + */ + if (options->debug) + { + /* + * Normal EXPLAIN will display "Disabled: true" if the node is + * disabled; but that is based on noticing that plan->disabled_nodes + * is higher than the sum of its children; here, we display the raw + * value, for debugging purposes. + */ + ExplainPropertyInteger("Disabled Nodes", NULL, plan->disabled_nodes, + es); + + /* + * Normal EXPLAIN will display the parallel_aware flag; here, we show + * the parallel_safe flag as well. + */ + ExplainPropertyBool("Parallel Safe", plan->parallel_safe, es); + + /* + * The plan node ID isn't normally displayed, since it is only useful + * for debugging. + */ + ExplainPropertyInteger("Plan Node ID", NULL, plan->plan_node_id, es); + + /* + * It is difficult to explain what extParam and allParam mean in plain + * language, so we simply display these fields labelled with the + * structure member name. For compactness, the text format omits the + * display of this information when the bitmapset is empty. + */ + if (es->format != EXPLAIN_FORMAT_TEXT || !bms_is_empty(plan->extParam)) + overexplain_bitmapset("extParam", plan->extParam, es); + if (es->format != EXPLAIN_FORMAT_TEXT || !bms_is_empty(plan->allParam)) + overexplain_bitmapset("allParam", plan->allParam, es); + } + + /* + * If the "range_table" option was specified, display information about + * the range table indexes for this node. + */ + if (options->range_table) + { + switch (nodeTag(plan)) + { + case T_SeqScan: + case T_SampleScan: + case T_IndexScan: + case T_IndexOnlyScan: + case T_BitmapHeapScan: + case T_TidScan: + case T_TidRangeScan: + case T_SubqueryScan: + case T_FunctionScan: + case T_TableFuncScan: + case T_ValuesScan: + case T_CteScan: + case T_NamedTuplestoreScan: + case T_WorkTableScan: + ExplainPropertyInteger("Scan RTI", NULL, + ((Scan *) plan)->scanrelid, es); + break; + case T_ForeignScan: + overexplain_bitmapset("Scan RTIs", + ((ForeignScan *) plan)->fs_base_relids, + es); + break; + case T_CustomScan: + overexplain_bitmapset("Scan RTIs", + ((CustomScan *) plan)->custom_relids, + es); + break; + case T_ModifyTable: + ExplainPropertyInteger("Nominal RTI", NULL, + ((ModifyTable *) plan)->nominalRelation, es); + ExplainPropertyInteger("Exclude Relation RTI", NULL, + ((ModifyTable *) plan)->exclRelRTI, es); + break; + case T_Append: + overexplain_bitmapset("Append RTIs", + ((Append *) plan)->apprelids, + es); + break; + case T_MergeAppend: + overexplain_bitmapset("Append RTIs", + ((MergeAppend *) plan)->apprelids, + es); + break; + default: + break; + } + } +} + +/* + * Print out additional per-query information as appropriate. Here again, if + * the user didn't specify any of the options implemented by this module, do + * nothing; otherwise, call the appropriate function for each specified + * option. + */ +static void +overexplain_per_plan_hook(PlannedStmt *plannedstmt, + IntoClause *into, + ExplainState *es, + const char *queryString, + ParamListInfo params, + QueryEnvironment *queryEnv) +{ + overexplain_options *options; + + if (prev_explain_per_plan_hook) + (*prev_explain_per_plan_hook) (plannedstmt, into, es, queryString, + params, queryEnv); + + options = GetExplainExtensionState(es, es_extension_id); + if (options == NULL) + return; + + if (options->debug) + overexplain_debug(plannedstmt, es); + + if (options->range_table) + overexplain_range_table(plannedstmt, es); +} + +/* + * Print out various details from the PlannedStmt that wouldn't otherwise + * be displayed. + * + * We don't try to print everything here. Information that would be displayed + * anyway doesn't need to be printed again here, and things with lots of + * substructure probably should be printed via separate options, or not at all. + */ +static void +overexplain_debug(PlannedStmt *plannedstmt, ExplainState *es) +{ + char *commandType = NULL; + StringInfoData flags; + + /* Even in text mode, we want to set this output apart as its own group. */ + ExplainOpenGroup("PlannedStmt", "PlannedStmt", true, es); + if (es->format == EXPLAIN_FORMAT_TEXT) + { + ExplainIndentText(es); + appendStringInfoString(es->str, "PlannedStmt:\n"); + es->indent++; + } + + /* Print the command type. */ + switch (plannedstmt->commandType) + { + case CMD_UNKNOWN: + commandType = "unknown"; + break; + case CMD_SELECT: + commandType = "select"; + break; + case CMD_UPDATE: + commandType = "update"; + break; + case CMD_INSERT: + commandType = "insert"; + break; + case CMD_DELETE: + commandType = "delete"; + break; + case CMD_MERGE: + commandType = "merge"; + break; + case CMD_UTILITY: + commandType = "utility"; + break; + case CMD_NOTHING: + commandType = "nothing"; + break; + } + ExplainPropertyText("Command Type", commandType, es); + + /* Print various properties as a comma-separated list of flags. */ + initStringInfo(&flags); + if (plannedstmt->hasReturning) + appendStringInfoString(&flags, ", hasReturning"); + if (plannedstmt->hasModifyingCTE) + appendStringInfoString(&flags, ", hasModifyingCTE"); + if (plannedstmt->canSetTag) + appendStringInfoString(&flags, ", canSetTag"); + if (plannedstmt->transientPlan) + appendStringInfoString(&flags, ", transientPlan"); + if (plannedstmt->dependsOnRole) + appendStringInfoString(&flags, ", dependsOnRole"); + if (plannedstmt->parallelModeNeeded) + appendStringInfoString(&flags, ", parallelModeNeeded"); + if (flags.len == 0) + appendStringInfoString(&flags, ", none"); + ExplainPropertyText("Flags", flags.data + 2, es); + + /* Various lists of integers. */ + overexplain_bitmapset("Subplans Needing Rewind", + plannedstmt->rewindPlanIDs, es); + overexplain_intlist("Relation OIDs", + plannedstmt->relationOids, es); + overexplain_intlist("Executor Parameter Types", + plannedstmt->paramExecTypes, es); + + /* + * Print the statement location. (If desired, we could alternatively print + * stmt_location and stmt_len as two separate fields.) + */ + if (plannedstmt->stmt_location == -1) + ExplainPropertyText("Parse Location", "Unknown", es); + else if (plannedstmt->stmt_len == 0) + ExplainPropertyText("Parse Location", + psprintf("%d to end", plannedstmt->stmt_location), + es); + else + ExplainPropertyText("Parse Location", + psprintf("%d for %d bytes", + plannedstmt->stmt_location, + plannedstmt->stmt_len), + es); + + /* Done with this group. */ + if (es->format == EXPLAIN_FORMAT_TEXT) + es->indent--; + ExplainCloseGroup("PlannedStmt", "PlannedStmt", true, es); +} + +/* + * Provide detailed information about the contents of the PlannedStmt's + * range table. + */ +static void +overexplain_range_table(PlannedStmt *plannedstmt, ExplainState *es) +{ + Index rti; + + /* Open group, one entry per RangeTblEntry */ + ExplainOpenGroup("Range Table", "Range Table", false, es); + + /* Iterate over the range table */ + for (rti = 1; rti <= list_length(plannedstmt->rtable); ++rti) + { + RangeTblEntry *rte = rt_fetch(rti, plannedstmt->rtable); + char *kind = NULL; + char *relkind; + + /* NULL entries are possible; skip them */ + if (rte == NULL) + continue; + + /* Translate rtekind to a string */ + switch (rte->rtekind) + { + case RTE_RELATION: + kind = "relation"; + break; + case RTE_SUBQUERY: + kind = "subquery"; + break; + case RTE_JOIN: + kind = "join"; + break; + case RTE_FUNCTION: + kind = "function"; + break; + case RTE_TABLEFUNC: + kind = "tablefunc"; + break; + case RTE_VALUES: + kind = "values"; + break; + case RTE_CTE: + kind = "cte"; + break; + case RTE_NAMEDTUPLESTORE: + kind = "namedtuplestore"; + break; + case RTE_RESULT: + kind = "result"; + break; + case RTE_GROUP: + kind = "group"; + break; + } + + /* Begin group for this specific RTE */ + ExplainOpenGroup("Range Table Entry", NULL, true, es); + + /* + * In text format, the summary line displays the range table index and + * rtekind, plus indications if rte->inh and/or rte->inFromCl are set. + * In other formats, we display those as separate properties. + */ + if (es->format == EXPLAIN_FORMAT_TEXT) + { + ExplainIndentText(es); + appendStringInfo(es->str, "RTI %u (%s%s%s):\n", rti, kind, + rte->inh ? ", inherited" : "", + rte->inFromCl ? ", in-from-clause" : ""); + es->indent++; + } + else + { + ExplainPropertyUInteger("RTI", NULL, rti, es); + ExplainPropertyText("Kind", kind, es); + ExplainPropertyBool("Inherited", rte->inh, es); + ExplainPropertyBool("In From Clause", rte->inFromCl, es); + } + + /* rte->alias is optional; rte->eref is requested */ + if (rte->alias != NULL) + overexplain_alias("Alias", rte->alias, es); + overexplain_alias("Eref", rte->eref, es); + + /* + * We adhere to the usual EXPLAIN convention that schema names are + * displayed only in verbose mode, and we emit nothing if there is no + * relation OID. + */ + if (rte->relid != 0) + { + const char *relname; + const char *qualname; + + relname = quote_identifier(get_rel_name(rte->relid)); + + if (es->verbose) + { + Oid nspoid = get_rel_namespace(rte->relid); + char *nspname; + + nspname = get_namespace_name_or_temp(nspoid); + qualname = psprintf("%s.%s", quote_identifier(nspname), + relname); + } + else + qualname = relname; + + ExplainPropertyText("Relation", qualname, es); + } + + /* Translate relkind, if any, to a string */ + switch (rte->relkind) + { + case RELKIND_RELATION: + relkind = "relation"; + break; + case RELKIND_INDEX: + relkind = "index"; + break; + case RELKIND_SEQUENCE: + relkind = "sequence"; + break; + case RELKIND_TOASTVALUE: + relkind = "toastvalue"; + break; + case RELKIND_VIEW: + relkind = "view"; + break; + case RELKIND_MATVIEW: + relkind = "matview"; + break; + case RELKIND_COMPOSITE_TYPE: + relkind = "composite_type"; + break; + case RELKIND_FOREIGN_TABLE: + relkind = "foreign_table"; + break; + case RELKIND_PARTITIONED_TABLE: + relkind = "partitioned_table"; + break; + case RELKIND_PARTITIONED_INDEX: + relkind = "partitioned_index"; + break; + case '\0': + relkind = NULL; + break; + default: + relkind = psprintf("%c", rte->relkind); + break; + } + + /* If there is a relkind, show it */ + if (relkind != NULL) + ExplainPropertyText("Relation Kind", relkind, es); + + /* If there is a lock mode, show it */ + if (rte->rellockmode != 0) + ExplainPropertyText("Relation Lock Mode", + GetLockmodeName(DEFAULT_LOCKMETHOD, + rte->rellockmode), es); + + /* + * If there is a perminfoindex, show it. We don't try to display + * information from the RTEPermissionInfo node here because they are + * just indexes plannedstmt->permInfos which could be separately + * dumped if someone wants to add EXPLAIN (PERMISSIONS) or similar. + */ + if (rte->perminfoindex != 0) + ExplainPropertyInteger("Permission Info Index", NULL, + rte->perminfoindex, es); + + /* + * add_rte_to_flat_rtable will clear rte->tablesample and + * rte->subquery in the finished plan, so skip those fields. + * + * However, the security_barrier flag is not shown by the core code, + * so let's print it here. + */ + if (es->format != EXPLAIN_FORMAT_TEXT || rte->security_barrier) + ExplainPropertyBool("Security Barrier", rte->security_barrier, es); + + /* + * If this is a join, print out the fields that are specifically valid + * for joins. + */ + if (rte->rtekind == RTE_JOIN) + { + char *jointype; + + switch (rte->jointype) + { + case JOIN_INNER: + jointype = "Inner"; + break; + case JOIN_LEFT: + jointype = "Left"; + break; + case JOIN_FULL: + jointype = "Full"; + break; + case JOIN_RIGHT: + jointype = "Right"; + break; + case JOIN_SEMI: + jointype = "Semi"; + break; + case JOIN_ANTI: + jointype = "Anti"; + break; + case JOIN_RIGHT_SEMI: + jointype = "Right Semi"; + break; + case JOIN_RIGHT_ANTI: + jointype = "Right Anti"; + break; + default: + jointype = "???"; + break; + } + + /* Join type */ + ExplainPropertyText("Join Type", jointype, es); + + /* # of JOIN USING columns */ + if (es->format != EXPLAIN_FORMAT_TEXT || rte->joinmergedcols != 0) + ExplainPropertyInteger("JOIN USING Columns", NULL, + rte->joinmergedcols, es); + + /* + * add_rte_to_flat_rtable will clear joinaliasvars, joinleftcols, + * joinrightcols, and join_using_alias here, so skip those fields. + */ + } + + /* + * add_rte_to_flat_rtable will clear functions, tablefunc, and + * values_lists, but we can display funcordinality. + */ + if (rte->rtekind == RTE_FUNCTION) + ExplainPropertyBool("WITH ORDINALITY", rte->funcordinality, es); + + /* + * If this is a CTE, print out CTE-related properties. + */ + if (rte->rtekind == RTE_CTE) + { + ExplainPropertyText("CTE Name", rte->ctename, es); + ExplainPropertyUInteger("CTE Levels Up", NULL, rte->ctelevelsup, + es); + ExplainPropertyBool("CTE Self-Reference", rte->self_reference, es); + } + + /* + * add_rte_to_flat_rtable will clear coltypes, coltypmods, and + * colcollations, so skip those fields. + * + * If this is an ephemeral named relation, print out ENR-related + * properties. + */ + if (rte->rtekind == RTE_NAMEDTUPLESTORE) + { + ExplainPropertyText("ENR Name", rte->enrname, es); + ExplainPropertyFloat("ENR Tuples", NULL, rte->enrtuples, 0, es); + } + + /* + * add_rte_to_flat_rtable will clear groupexprs and securityQuals, so + * skip that field. We have handled inFromCl above, so the only thing + * left to handle here is rte->lateral. + */ + if (es->format != EXPLAIN_FORMAT_TEXT || rte->lateral) + ExplainPropertyBool("Lateral", rte->lateral, es); + + /* Done with this RTE */ + if (es->format == EXPLAIN_FORMAT_TEXT) + es->indent--; + ExplainCloseGroup("Range Table Entry", NULL, true, es); + } + + /* Print PlannedStmt fields that contain RTIs. */ + if (es->format != EXPLAIN_FORMAT_TEXT || + !bms_is_empty(plannedstmt->unprunableRelids)) + overexplain_bitmapset("Unprunable RTIs", plannedstmt->unprunableRelids, + es); + if (es->format != EXPLAIN_FORMAT_TEXT || + plannedstmt->resultRelations != NIL) + overexplain_intlist("Result RTIs", plannedstmt->resultRelations, es); + + /* Close group, we're all done */ + ExplainCloseGroup("Range Table", "Range Table", false, es); +} + +/* + * Emit a text property describing the contents of an Alias. + * + * Column lists can be quite long here, so perhaps we should have an option + * to limit the display length by # of column or # of characters, but for + * now, just display everything. + */ +static void +overexplain_alias(const char *qlabel, Alias *alias, ExplainState *es) +{ + StringInfoData buf; + bool first = true; + + Assert(alias != NULL); + + initStringInfo(&buf); + appendStringInfo(&buf, "%s (", quote_identifier(alias->aliasname)); + + foreach_node(String, cn, alias->colnames) + { + appendStringInfo(&buf, "%s%s", + first ? "" : ", ", + quote_identifier(cn->sval)); + first = false; + } + + appendStringInfoChar(&buf, ')'); + ExplainPropertyText(qlabel, buf.data, es); + pfree(buf.data); +} + +/* + * Emit a text property describing the contents of a bitmapset -- either a + * space-separated list of integer members, or the word "none" if the bitmapset + * is empty. + */ +static void +overexplain_bitmapset(const char *qlabel, Bitmapset *bms, ExplainState *es) +{ + int x = -1; + + StringInfoData buf; + + if (bms_is_empty(bms)) + { + ExplainPropertyText(qlabel, "none", es); + return; + } + + initStringInfo(&buf); + while ((x = bms_next_member(bms, x)) >= 0) + appendStringInfo(&buf, " %d", x); + Assert(buf.data[0] == ' '); + ExplainPropertyText(qlabel, buf.data + 1, es); + pfree(buf.data); +} + +/* + * Emit a text property describing the contents of a list of integers, OIDs, + * or XIDs -- either a space-separated list of integer members, or the word + * "none" if the list is empty. + */ +static void +overexplain_intlist(const char *qlabel, List *list, ExplainState *es) +{ + StringInfoData buf; + + initStringInfo(&buf); + + if (list == NIL) + { + ExplainPropertyText(qlabel, "none", es); + return; + } + + if (IsA(list, IntList)) + { + foreach_int(i, list) + appendStringInfo(&buf, " %d", i); + } + else if (IsA(list, OidList)) + { + foreach_oid(o, list) + appendStringInfo(&buf, " %u", o); + } + else if (IsA(list, XidList)) + { + foreach_xid(x, list) + appendStringInfo(&buf, " %u", x); + } + else + { + appendStringInfoString(&buf, " not an integer list"); + Assert(false); + } + + if (buf.len > 0) + ExplainPropertyText(qlabel, buf.data + 1, es); + + pfree(buf.data); +} diff --git a/contrib/pg_overexplain/sql/pg_overexplain.sql b/contrib/pg_overexplain/sql/pg_overexplain.sql new file mode 100644 index 0000000000000..42e275ac2f906 --- /dev/null +++ b/contrib/pg_overexplain/sql/pg_overexplain.sql @@ -0,0 +1,112 @@ +-- These tests display internal details that would not be stable under +-- debug_parallel_query, so make sure that option is disabled. +SET debug_parallel_query = off; + +-- Make sure that we don't print any JIT-related information, as that +-- would also make results unstable. +SET jit = off; + +-- These options do not exist, so these queries should all fail. +EXPLAIN (DEBUFF) SELECT 1; +EXPLAIN (DEBUG) SELECT 1; +EXPLAIN (RANGE_TABLE) SELECT 1; + +-- Load the module that creates the options. +LOAD 'pg_overexplain'; + +-- The first option still does not exist, but the others do. +EXPLAIN (DEBUFF) SELECT 1; +EXPLAIN (DEBUG) SELECT 1; +EXPLAIN (RANGE_TABLE) SELECT 1; + +-- Create a partitioned table. +CREATE TABLE vegetables (id serial, name text, genus text) +PARTITION BY LIST (genus); +CREATE TABLE daucus PARTITION OF vegetables FOR VALUES IN ('daucus'); +CREATE TABLE brassica PARTITION OF vegetables FOR VALUES IN ('brassica'); +INSERT INTO vegetables (name, genus) + VALUES ('carrot', 'daucus'), ('bok choy', 'brassica'), + ('brocooli', 'brassica'), ('cauliflower', 'brassica'), + ('cabbage', 'brassica'), ('kohlrabi', 'brassica'), + ('rutabaga', 'brassica'), ('turnip', 'brassica'); +VACUUM ANALYZE vegetables; + +-- We filter relation OIDs out of the test output in order to avoid +-- test instability. This is currently only needed for EXPLAIN (DEBUG), not +-- EXPLAIN (RANGE_TABLE). Also suppress actual row counts, which are not +-- stable (e.g. 1/8 is 0.12 on some buildfarm machines and 0.13 on others). +CREATE FUNCTION explain_filter(text) RETURNS SETOF text +LANGUAGE plpgsql AS +$$ +DECLARE + ln text; +BEGIN + FOR ln IN EXECUTE $1 + LOOP + ln := regexp_replace(ln, 'Relation OIDs:( \m\d+\M)+', + 'Relation OIDs: NNN...', 'g'); + ln := regexp_replace(ln, '( ?\m\d+\M)+', + 'NNN...', 'g'); + ln := regexp_replace(ln, 'actual rows=\d+\.\d+', + 'actual rows=N.NN', 'g'); + RETURN NEXT ln; + END LOOP; +END; +$$; + +-- Test with both options together and an aggregate. +SELECT explain_filter($$ +EXPLAIN (DEBUG, RANGE_TABLE, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + +-- Test a different output format. +SELECT explain_filter($$ +EXPLAIN (DEBUG, RANGE_TABLE, FORMAT XML, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); + +-- Test just the DEBUG option. Verify that it shows information about +-- disabled nodes, parallel safety, and the parallelModeNeeded flag. +SET enable_seqscan = false; +SET debug_parallel_query = true; +SELECT explain_filter($$ +EXPLAIN (DEBUG, COSTS OFF) +SELECT genus, array_agg(name ORDER BY name) FROM vegetables GROUP BY genus +$$); +SET debug_parallel_query = false; +RESET enable_seqscan; + +-- Test the DEBUG option with a non-SELECT query, and also verify that the +-- hasReturning flag is shown. +SELECT explain_filter($$ +EXPLAIN (DEBUG, COSTS OFF) +INSERT INTO vegetables (name, genus) + VALUES ('Brotero''s carrot', 'brassica') RETURNING id +$$); + +-- Create an index, and then attempt to force a nested loop with inner index +-- scan so that we can see parameter-related information. Also, let's try +-- actually running the query, but try to suppress potentially variable output. +CREATE INDEX ON vegetables (id); +ANALYZE vegetables; +SET enable_hashjoin = false; +SET enable_material = false; +SET enable_mergejoin = false; +SET enable_seqscan = false; +SELECT explain_filter($$ +EXPLAIN (BUFFERS OFF, COSTS OFF, SUMMARY OFF, TIMING OFF, ANALYZE, DEBUG) +SELECT * FROM vegetables v1, vegetables v2 WHERE v1.id = v2.id; +$$); +RESET enable_hashjoin; +RESET enable_material; +RESET enable_mergejoin; +RESET enable_seqscan; + +-- Test the RANGE_TABLE option with a case that allows partition pruning. +EXPLAIN (RANGE_TABLE, COSTS OFF) +SELECT * FROM vegetables WHERE genus = 'daucus'; + +-- Also test a case that involves a write. +EXPLAIN (RANGE_TABLE, COSTS OFF) +INSERT INTO vegetables (name, genus) VALUES ('broccoflower', 'brassica'); diff --git a/contrib/pg_prewarm/Makefile b/contrib/pg_prewarm/Makefile index 9cfde8c4e4fad..617ac8e09b2d8 100644 --- a/contrib/pg_prewarm/Makefile +++ b/contrib/pg_prewarm/Makefile @@ -10,6 +10,8 @@ EXTENSION = pg_prewarm DATA = pg_prewarm--1.1--1.2.sql pg_prewarm--1.1.sql pg_prewarm--1.0--1.1.sql PGFILEDESC = "pg_prewarm - preload relation data into system buffer cache" +REGRESS = pg_prewarm + TAP_TESTS = 1 ifdef USE_PGXS diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index d061731706ac0..c01b9c7e6a4d6 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -16,7 +16,7 @@ * relevant database in turn. The former keeps running after the * initial prewarm is complete to update the dump file periodically. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pg_prewarm/autoprewarm.c @@ -30,8 +30,6 @@ #include "access/relation.h" #include "access/xact.h" -#include "catalog/pg_class.h" -#include "catalog/pg_type.h" #include "pgstat.h" #include "postmaster/bgworker.h" #include "postmaster/interrupt.h" @@ -42,18 +40,14 @@ #include "storage/ipc.h" #include "storage/latch.h" #include "storage/lwlock.h" -#include "storage/proc.h" #include "storage/procsignal.h" -#include "storage/shmem.h" +#include "storage/read_stream.h" #include "storage/smgr.h" #include "tcop/tcopprot.h" -#include "utils/acl.h" -#include "utils/datetime.h" #include "utils/guc.h" -#include "utils/memutils.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" -#include "utils/resowner.h" +#include "utils/timestamp.h" #define AUTOPREWARM_FILE "autoprewarm.blocks" @@ -82,6 +76,28 @@ typedef struct AutoPrewarmSharedState int prewarmed_blocks; } AutoPrewarmSharedState; +/* + * Private data passed through the read stream API for our use in the + * callback. + */ +typedef struct AutoPrewarmReadStreamData +{ + /* The array of records containing the blocks we should prewarm. */ + BlockInfoRecord *block_info; + + /* + * pos is the read stream callback's index into block_info. Because the + * read stream may read ahead, pos is likely to be ahead of the index in + * the main loop in autoprewarm_database_main(). + */ + int pos; + Oid tablespace; + RelFileNumber filenumber; + ForkNumber forknum; + BlockNumber nblocks; +} AutoPrewarmReadStreamData; + + PGDLLEXPORT void autoprewarm_main(Datum main_arg); PGDLLEXPORT void autoprewarm_database_main(Datum main_arg); @@ -429,6 +445,54 @@ apw_load_buffers(void) apw_state->prewarmed_blocks, num_elements))); } +/* + * Return the next block number of a specific relation and fork to read + * according to the array of BlockInfoRecord. + */ +static BlockNumber +apw_read_stream_next_block(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) +{ + AutoPrewarmReadStreamData *p = callback_private_data; + + CHECK_FOR_INTERRUPTS(); + + while (p->pos < apw_state->prewarm_stop_idx) + { + BlockInfoRecord blk = p->block_info[p->pos]; + + if (!have_free_buffer()) + { + p->pos = apw_state->prewarm_stop_idx; + return InvalidBlockNumber; + } + + if (blk.tablespace != p->tablespace) + return InvalidBlockNumber; + + if (blk.filenumber != p->filenumber) + return InvalidBlockNumber; + + if (blk.forknum != p->forknum) + return InvalidBlockNumber; + + p->pos++; + + /* + * Check whether blocknum is valid and within fork file size. + * Fast-forward through any invalid blocks. We want p->pos to reflect + * the location of the next relation or fork before ending the stream. + */ + if (blk.blocknum >= p->nblocks) + continue; + + return blk.blocknum; + } + + return InvalidBlockNumber; +} + /* * Prewarm all blocks for one database (and possibly also global objects, if * those got grouped with this database). @@ -436,11 +500,9 @@ apw_load_buffers(void) void autoprewarm_database_main(Datum main_arg) { - int pos; BlockInfoRecord *block_info; - Relation rel = NULL; - BlockNumber nblocks = 0; - BlockInfoRecord *old_blk = NULL; + int i; + BlockInfoRecord blk; dsm_segment *seg; /* Establish signal handlers; once that's done, unblock signals. */ @@ -456,108 +518,142 @@ autoprewarm_database_main(Datum main_arg) errmsg("could not map dynamic shared memory segment"))); BackgroundWorkerInitializeConnectionByOid(apw_state->database, InvalidOid, 0); block_info = (BlockInfoRecord *) dsm_segment_address(seg); - pos = apw_state->prewarm_start_idx; + + i = apw_state->prewarm_start_idx; + blk = block_info[i]; /* * Loop until we run out of blocks to prewarm or until we run out of free * buffers. */ - while (pos < apw_state->prewarm_stop_idx && have_free_buffer()) + while (i < apw_state->prewarm_stop_idx && have_free_buffer()) { - BlockInfoRecord *blk = &block_info[pos++]; - Buffer buf; - - CHECK_FOR_INTERRUPTS(); + Oid tablespace = blk.tablespace; + RelFileNumber filenumber = blk.filenumber; + Oid reloid; + Relation rel; /* - * Quit if we've reached records for another database. If previous - * blocks are of some global objects, then continue pre-warming. + * All blocks between prewarm_start_idx and prewarm_stop_idx should + * belong either to global objects or the same database. */ - if (old_blk != NULL && old_blk->database != blk->database && - old_blk->database != 0) - break; + Assert(blk.database == apw_state->database || blk.database == 0); - /* - * As soon as we encounter a block of a new relation, close the old - * relation. Note that rel will be NULL if try_relation_open failed - * previously; in that case, there is nothing to close. - */ - if (old_blk != NULL && old_blk->filenumber != blk->filenumber && - rel != NULL) - { - relation_close(rel, AccessShareLock); - rel = NULL; - CommitTransactionCommand(); - } + StartTransactionCommand(); - /* - * Try to open each new relation, but only once, when we first - * encounter it. If it's been dropped, skip the associated blocks. - */ - if (old_blk == NULL || old_blk->filenumber != blk->filenumber) + reloid = RelidByRelfilenumber(blk.tablespace, blk.filenumber); + if (!OidIsValid(reloid) || + (rel = try_relation_open(reloid, AccessShareLock)) == NULL) { - Oid reloid; + /* We failed to open the relation, so there is nothing to close. */ + CommitTransactionCommand(); - Assert(rel == NULL); - StartTransactionCommand(); - reloid = RelidByRelfilenumber(blk->tablespace, blk->filenumber); - if (OidIsValid(reloid)) - rel = try_relation_open(reloid, AccessShareLock); + /* + * Fast-forward to the next relation. We want to skip all of the + * other records referencing this relation since we know we can't + * open it. That way, we avoid repeatedly trying and failing to + * open the same relation. + */ + for (; i < apw_state->prewarm_stop_idx; i++) + { + blk = block_info[i]; + if (blk.tablespace != tablespace || + blk.filenumber != filenumber) + break; + } - if (!rel) - CommitTransactionCommand(); - } - if (!rel) - { - old_blk = blk; + /* Time to try and open our newfound relation */ continue; } - /* Once per fork, check for fork existence and size. */ - if (old_blk == NULL || - old_blk->filenumber != blk->filenumber || - old_blk->forknum != blk->forknum) + /* + * We have a relation; now let's loop until we find a valid fork of + * the relation or we run out of free buffers. Once we've read from + * all valid forks or run out of options, we'll close the relation and + * move on. + */ + while (i < apw_state->prewarm_stop_idx && + blk.tablespace == tablespace && + blk.filenumber == filenumber && + have_free_buffer()) { + ForkNumber forknum = blk.forknum; + BlockNumber nblocks; + struct AutoPrewarmReadStreamData p; + ReadStream *stream; + Buffer buf; + /* * smgrexists is not safe for illegal forknum, hence check whether * the passed forknum is valid before using it in smgrexists. */ - if (blk->forknum > InvalidForkNumber && - blk->forknum <= MAX_FORKNUM && - smgrexists(RelationGetSmgr(rel), blk->forknum)) - nblocks = RelationGetNumberOfBlocksInFork(rel, blk->forknum); - else - nblocks = 0; - } + if (blk.forknum <= InvalidForkNumber || + blk.forknum > MAX_FORKNUM || + !smgrexists(RelationGetSmgr(rel), blk.forknum)) + { + /* + * Fast-forward to the next fork. We want to skip all of the + * other records referencing this fork since we already know + * it's not valid. + */ + for (; i < apw_state->prewarm_stop_idx; i++) + { + blk = block_info[i]; + if (blk.tablespace != tablespace || + blk.filenumber != filenumber || + blk.forknum != forknum) + break; + } + + /* Time to check if this newfound fork is valid */ + continue; + } - /* Check whether blocknum is valid and within fork file size. */ - if (blk->blocknum >= nblocks) - { - /* Move to next forknum. */ - old_blk = blk; - continue; - } + nblocks = RelationGetNumberOfBlocksInFork(rel, blk.forknum); - /* Prewarm buffer. */ - buf = ReadBufferExtended(rel, blk->forknum, blk->blocknum, RBM_NORMAL, - NULL); - if (BufferIsValid(buf)) - { - apw_state->prewarmed_blocks++; - ReleaseBuffer(buf); - } + p = (struct AutoPrewarmReadStreamData) + { + .block_info = block_info, + .pos = i, + .tablespace = tablespace, + .filenumber = filenumber, + .forknum = forknum, + .nblocks = nblocks, + }; + + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_DEFAULT | + READ_STREAM_USE_BATCHING, + NULL, + rel, + p.forknum, + apw_read_stream_next_block, + &p, + 0); - old_blk = blk; - } + /* + * Loop until we've prewarmed all the blocks from this fork. The + * read stream callback will check that we still have free buffers + * before requesting each block from the read stream API. + */ + while ((buf = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) + { + apw_state->prewarmed_blocks++; + ReleaseBuffer(buf); + } - dsm_detach(seg); + read_stream_end(stream); + + /* Advance i past all the blocks just prewarmed. */ + i = p.pos; + blk = block_info[i]; + } - /* Release lock on previous relation. */ - if (rel) - { relation_close(rel, AccessShareLock); CommitTransactionCommand(); } + + dsm_detach(seg); } /* @@ -597,8 +693,15 @@ apw_dump_now(bool is_bgworker, bool dump_unlogged) return 0; } - block_info_array = - (BlockInfoRecord *) palloc(sizeof(BlockInfoRecord) * NBuffers); + /* + * With sufficiently large shared_buffers, allocation will exceed 1GB, so + * allow for a huge allocation to prevent outright failure. + * + * (In the future, it might be a good idea to redesign this to use a more + * memory-efficient data structure.) + */ + block_info_array = (BlockInfoRecord *) + palloc_extended((sizeof(BlockInfoRecord) * NBuffers), MCXT_ALLOC_HUGE); for (num_blocks = 0, i = 0; i < NBuffers; i++) { @@ -805,12 +908,11 @@ apw_detach_shmem(int code, Datum arg) static void apw_start_leader_worker(void) { - BackgroundWorker worker; + BackgroundWorker worker = {0}; BackgroundWorkerHandle *handle; BgwHandleStatus status; pid_t pid; - MemSet(&worker, 0, sizeof(BackgroundWorker)); worker.bgw_flags = BGWORKER_SHMEM_ACCESS; worker.bgw_start_time = BgWorkerStart_ConsistentState; strcpy(worker.bgw_library_name, "pg_prewarm"); @@ -847,10 +949,9 @@ apw_start_leader_worker(void) static void apw_start_database_worker(void) { - BackgroundWorker worker; + BackgroundWorker worker = {0}; BackgroundWorkerHandle *handle; - MemSet(&worker, 0, sizeof(BackgroundWorker)); worker.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION; worker.bgw_start_time = BgWorkerStart_ConsistentState; diff --git a/contrib/pg_prewarm/expected/pg_prewarm.out b/contrib/pg_prewarm/expected/pg_prewarm.out new file mode 100644 index 0000000000000..94e4fa1a9d237 --- /dev/null +++ b/contrib/pg_prewarm/expected/pg_prewarm.out @@ -0,0 +1,10 @@ +-- Test pg_prewarm extension +CREATE EXTENSION pg_prewarm; +-- pg_prewarm() should fail if the target relation has no storage. +CREATE TABLE test (c1 int) PARTITION BY RANGE (c1); +SELECT pg_prewarm('test', 'buffer'); +ERROR: relation "test" does not have storage +DETAIL: This operation is not supported for partitioned tables. +-- Cleanup +DROP TABLE test; +DROP EXTENSION pg_prewarm; diff --git a/contrib/pg_prewarm/meson.build b/contrib/pg_prewarm/meson.build index da58f70a9f82c..f24c47ef6a533 100644 --- a/contrib/pg_prewarm/meson.build +++ b/contrib/pg_prewarm/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_prewarm_sources = files( 'autoprewarm.c', @@ -29,6 +29,11 @@ tests += { 'name': 'pg_prewarm', 'sd': meson.current_source_dir(), 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'pg_prewarm', + ], + }, 'tap': { 'tests': [ 't/001_basic.pl', diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c index 5c859e983c5ca..b968933ea8b6c 100644 --- a/contrib/pg_prewarm/pg_prewarm.c +++ b/contrib/pg_prewarm/pg_prewarm.c @@ -3,7 +3,7 @@ * pg_prewarm.c * prewarming utilities * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pg_prewarm/pg_prewarm.c @@ -26,7 +26,10 @@ #include "utils/lsyscache.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_prewarm", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(pg_prewarm); @@ -39,25 +42,6 @@ typedef enum static PGIOAlignedBlock blockbuffer; -struct pg_prewarm_read_stream_private -{ - BlockNumber blocknum; - int64 last_block; -}; - -static BlockNumber -pg_prewarm_read_stream_next_block(ReadStream *stream, - void *callback_private_data, - void *per_buffer_data) -{ - struct pg_prewarm_read_stream_private *p = callback_private_data; - - if (p->blocknum <= p->last_block) - return p->blocknum++; - - return InvalidBlockNumber; -} - /* * pg_prewarm(regclass, mode text, fork text, * first_block int8, last_block int8) @@ -128,6 +112,14 @@ pg_prewarm(PG_FUNCTION_ARGS) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind), get_rel_name(relOid)); + /* Check that the relation has storage. */ + if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" does not have storage", + RelationGetRelationName(rel)), + errdetail_relkind_not_supported(rel->rd_rel->relkind))); + /* Check that the fork exists. */ if (!smgrexists(RelationGetSmgr(rel), forkNumber)) ereport(ERROR, @@ -145,8 +137,8 @@ pg_prewarm(PG_FUNCTION_ARGS) if (first_block < 0 || first_block >= nblocks) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("starting block number must be between 0 and %lld", - (long long) (nblocks - 1)))); + errmsg("starting block number must be between 0 and %" PRId64, + (nblocks - 1)))); } if (PG_ARGISNULL(4)) last_block = nblocks - 1; @@ -156,8 +148,8 @@ pg_prewarm(PG_FUNCTION_ARGS) if (last_block < 0 || last_block >= nblocks) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("ending block number must be between 0 and %lld", - (long long) (nblocks - 1)))); + errmsg("ending block number must be between 0 and %" PRId64, + (nblocks - 1)))); } /* Now we're ready to do the real work. */ @@ -203,7 +195,7 @@ pg_prewarm(PG_FUNCTION_ARGS) } else if (ptype == PREWARM_BUFFER) { - struct pg_prewarm_read_stream_private p; + BlockRangeReadStreamPrivate p; ReadStream *stream; /* @@ -211,14 +203,20 @@ pg_prewarm(PG_FUNCTION_ARGS) */ /* Set up the private state for our streaming buffer read callback. */ - p.blocknum = first_block; - p.last_block = last_block; + p.current_blocknum = first_block; + p.last_exclusive = last_block + 1; - stream = read_stream_begin_relation(READ_STREAM_FULL, + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, NULL, rel, forkNumber, - pg_prewarm_read_stream_next_block, + block_range_read_stream_cb, &p, 0); diff --git a/contrib/pg_prewarm/sql/pg_prewarm.sql b/contrib/pg_prewarm/sql/pg_prewarm.sql new file mode 100644 index 0000000000000..c76f2c7916436 --- /dev/null +++ b/contrib/pg_prewarm/sql/pg_prewarm.sql @@ -0,0 +1,10 @@ +-- Test pg_prewarm extension +CREATE EXTENSION pg_prewarm; + +-- pg_prewarm() should fail if the target relation has no storage. +CREATE TABLE test (c1 int) PARTITION BY RANGE (c1); +SELECT pg_prewarm('test', 'buffer'); + +-- Cleanup +DROP TABLE test; +DROP EXTENSION pg_prewarm; diff --git a/contrib/pg_prewarm/t/001_basic.pl b/contrib/pg_prewarm/t/001_basic.pl index 825d3448ee562..0a8259d367854 100644 --- a/contrib/pg_prewarm/t/001_basic.pl +++ b/contrib/pg_prewarm/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/contrib/pg_stat_statements/Makefile b/contrib/pg_stat_statements/Makefile index c19ccad77ed4e..b2bd8794d2a14 100644 --- a/contrib/pg_stat_statements/Makefile +++ b/contrib/pg_stat_statements/Makefile @@ -7,7 +7,7 @@ OBJS = \ EXTENSION = pg_stat_statements DATA = pg_stat_statements--1.4.sql \ - pg_stat_statements--1.10--1.11.sql \ + pg_stat_statements--1.11--1.12.sql pg_stat_statements--1.10--1.11.sql \ pg_stat_statements--1.9--1.10.sql pg_stat_statements--1.8--1.9.sql \ pg_stat_statements--1.7--1.8.sql pg_stat_statements--1.6--1.7.sql \ pg_stat_statements--1.5--1.6.sql pg_stat_statements--1.4--1.5.sql \ @@ -19,8 +19,8 @@ LDFLAGS_SL += $(filter -lm, $(LIBS)) REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_statements/pg_stat_statements.conf REGRESS = select dml cursors utility level_tracking planning \ - user_activity wal entry_timestamp privileges cleanup \ - oldextversions + user_activity wal entry_timestamp privileges extended \ + parallel cleanup oldextversions squashing # Disabled because these tests require "shared_preload_libraries=pg_stat_statements", # which typical installcheck users do not have (e.g. buildfarm clients). NO_INSTALLCHECK = 1 diff --git a/contrib/pg_stat_statements/expected/dml.out b/contrib/pg_stat_statements/expected/dml.out index f6ac8da5ca221..347cb8699e432 100644 --- a/contrib/pg_stat_statements/expected/dml.out +++ b/contrib/pg_stat_statements/expected/dml.out @@ -80,9 +80,9 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; 1 | 10 | INSERT INTO pgss_dml_tab VALUES(generate_series($1, $2), $3) 1 | 12 | SELECT * FROM pgss_dml_tab ORDER BY a 2 | 4 | SELECT * FROM pgss_dml_tab WHERE a > $1 ORDER BY a - 1 | 8 | SELECT * FROM pgss_dml_tab WHERE a IN ($1, $2, $3, $4, $5) + 1 | 8 | SELECT * FROM pgss_dml_tab WHERE a IN ($1 /*, ... */) 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t - 1 | 0 | SET pg_stat_statements.track_utility = FALSE + 1 | 0 | SET pg_stat_statements.track_utility = $1 6 | 6 | UPDATE pgss_dml_tab SET b = $1 WHERE a = $2 1 | 3 | UPDATE pgss_dml_tab SET b = $1 WHERE a > $2 (10 rows) diff --git a/contrib/pg_stat_statements/expected/extended.out b/contrib/pg_stat_statements/expected/extended.out new file mode 100644 index 0000000000000..7da308ba84f4f --- /dev/null +++ b/contrib/pg_stat_statements/expected/extended.out @@ -0,0 +1,128 @@ +-- Tests with extended query protocol +SET pg_stat_statements.track_utility = FALSE; +-- This test checks that an execute message sets a query ID. +SELECT query_id IS NOT NULL AS query_id_set + FROM pg_stat_activity WHERE pid = pg_backend_pid() \bind \g + query_id_set +-------------- + t +(1 row) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT $1 \parse stmt1 +SELECT $1, $2 \parse stmt2 +SELECT $1, $2, $3 \parse stmt3 +SELECT $1 \bind 'unnamed_val1' \g + ?column? +-------------- + unnamed_val1 +(1 row) + +\bind_named stmt1 'stmt1_val1' \g + ?column? +------------ + stmt1_val1 +(1 row) + +\bind_named stmt2 'stmt2_val1' 'stmt2_val2' \g + ?column? | ?column? +------------+------------ + stmt2_val1 | stmt2_val2 +(1 row) + +\bind_named stmt3 'stmt3_val1' 'stmt3_val2' 'stmt3_val3' \g + ?column? | ?column? | ?column? +------------+------------+------------ + stmt3_val1 | stmt3_val2 | stmt3_val3 +(1 row) + +\bind_named stmt3 'stmt3_val4' 'stmt3_val5' 'stmt3_val6' \g + ?column? | ?column? | ?column? +------------+------------+------------ + stmt3_val4 | stmt3_val5 | stmt3_val6 +(1 row) + +\bind_named stmt2 'stmt2_val3' 'stmt2_val4' \g + ?column? | ?column? +------------+------------ + stmt2_val3 | stmt2_val4 +(1 row) + +\bind_named stmt1 'stmt1_val1' \g + ?column? +------------ + stmt1_val1 +(1 row) + +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | rows | query +-------+------+---------------------------------------------------- + 3 | 3 | SELECT $1 + 2 | 2 | SELECT $1, $2 + 2 | 2 | SELECT $1, $2, $3 + 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(4 rows) + +-- Various parameter numbering patterns +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- Unique query IDs with parameter numbers switched. +SELECT WHERE ($1::int, 7) IN ((8, $2::int), ($3::int, 9)) \bind '1' '2' '3' \g +-- +(0 rows) + +SELECT WHERE ($2::int, 10) IN ((11, $3::int), ($1::int, 12)) \bind '1' '2' '3' \g +-- +(0 rows) + +SELECT WHERE $1::int IN ($2::int, $3::int) \bind '1' '2' '3' \g +-- +(0 rows) + +SELECT WHERE $2::int IN ($3::int, $1::int) \bind '1' '2' '3' \g +-- +(0 rows) + +SELECT WHERE $3::int IN ($1::int, $2::int) \bind '1' '2' '3' \g +-- +(0 rows) + +-- Two groups of two queries with the same query ID. +SELECT WHERE '1'::int IN ($1::int, '2'::int) \bind '1' \g +-- +(1 row) + +SELECT WHERE '4'::int IN ($1::int, '5'::int) \bind '2' \g +-- +(0 rows) + +SELECT WHERE $2::int IN ($1::int, '1'::int) \bind '1' '2' \g +-- +(0 rows) + +SELECT WHERE $2::int IN ($1::int, '2'::int) \bind '3' '4' \g +-- +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +--------------------------------------------------------------+------- + SELECT WHERE $1::int IN ($2::int, $3::int) | 1 + SELECT WHERE $2::int IN ($1::int, $3::int) | 2 + SELECT WHERE $2::int IN ($1::int, $3::int) | 2 + SELECT WHERE $2::int IN ($3::int, $1::int) | 1 + SELECT WHERE $3::int IN ($1::int, $2::int) | 1 + SELECT WHERE ($1::int, $4) IN (($5, $2::int), ($3::int, $6)) | 1 + SELECT WHERE ($2::int, $4) IN (($5, $3::int), ($1::int, $6)) | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(8 rows) + diff --git a/contrib/pg_stat_statements/expected/level_tracking.out b/contrib/pg_stat_statements/expected/level_tracking.out index d8dd8a2deea08..8213fcd2e612c 100644 --- a/contrib/pg_stat_statements/expected/level_tracking.out +++ b/contrib/pg_stat_statements/expected/level_tracking.out @@ -64,7 +64,7 @@ SELECT toplevel, calls, query FROM pg_stat_statements | | END; $$ f | 1 | SELECT $1::TEXT t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t - t | 1 | SET pg_stat_statements.track = 'all' + t | 1 | SET pg_stat_statements.track = $1 (7 rows) -- Procedure with multiple utility statements. @@ -112,6 +112,1162 @@ SELECT toplevel, calls, query FROM pg_stat_statements t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t (2 rows) +-- EXPLAIN - all-level tracking. +CREATE TABLE test_table (x int); +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (SELECT 1, 2); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) TABLE stats_track_tab; + QUERY PLAN +----------------------------- + Seq Scan on stats_track_tab +(1 row) + +EXPLAIN (COSTS OFF) (TABLE test_table); + QUERY PLAN +------------------------ + Seq Scan on test_table +(1 row) + +EXPLAIN (COSTS OFF) VALUES (1); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (VALUES (1, 2)); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1)); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + +EXPLAIN (COSTS OFF) SELECT 1 UNION SELECT 2; + QUERY PLAN +-------------------------- + Unique + -> Sort + Sort Key: (1) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+--------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2) + f | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2); + t | 1 | EXPLAIN (COSTS OFF) (TABLE test_table) + f | 1 | EXPLAIN (COSTS OFF) (TABLE test_table); + t | 1 | EXPLAIN (COSTS OFF) (VALUES ($1, $2)) + f | 1 | EXPLAIN (COSTS OFF) (VALUES ($1, $2)); + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab + f | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; + t | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)) + f | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)); + t | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($1, $2) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + f | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($1, $2) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 UNION SELECT $2 + f | 1 | EXPLAIN (COSTS OFF) SELECT $1 UNION SELECT $2; + f | 1 | EXPLAIN (COSTS OFF) SELECT $1; + t | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab + f | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab; + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2 + f | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2; + t | 1 | EXPLAIN (COSTS OFF) VALUES ($1) + f | 1 | EXPLAIN (COSTS OFF) VALUES ($1); + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(23 rows) + +-- EXPLAIN - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (SELECT 1, 2); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) TABLE stats_track_tab; + QUERY PLAN +----------------------------- + Seq Scan on stats_track_tab +(1 row) + +EXPLAIN (COSTS OFF) (TABLE test_table); + QUERY PLAN +------------------------ + Seq Scan on test_table +(1 row) + +EXPLAIN (COSTS OFF) VALUES (1); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (VALUES (1, 2)); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1)); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + +EXPLAIN (COSTS OFF) SELECT 1 UNION SELECT 2; + QUERY PLAN +-------------------------- + Unique + -> Sort + Sort Key: (1) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+-------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2) + t | 1 | EXPLAIN (COSTS OFF) (TABLE test_table) + t | 1 | EXPLAIN (COSTS OFF) (VALUES ($1, $2)) + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)) + t | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($1, $2) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 UNION SELECT $2 + t | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2 + t | 1 | EXPLAIN (COSTS OFF) VALUES ($1) + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(12 rows) + +-- EXPLAIN - all-level tracking with multi-statement strings. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- SELECT queries +EXPLAIN (COSTS OFF) SELECT 1\; EXPLAIN (COSTS OFF) SELECT 1, 2; + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (SELECT 1, 2, 3)\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3, 4); + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) SELECT 1, 2 UNION SELECT 3, 4\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3) UNION SELECT 3, 4, 5; + QUERY PLAN +---------------------------- + Unique + -> Sort + Sort Key: (1), (2) + -> Append + -> Result + -> Result +(6 rows) + + QUERY PLAN +--------------------------------- + Unique + -> Sort + Sort Key: (1), (2), (3) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+--------------------------------------------------------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3) + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3) UNION SELECT $4, $5, $6 + f | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3); EXPLAIN (COSTS OFF) (SELECT 1, 2, 3, 4); + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3, $4) + f | 1 | EXPLAIN (COSTS OFF) (SELECT 1, 2, 3); EXPLAIN (COSTS OFF) (SELECT $1, $2, $3, $4); + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2 UNION SELECT $3, $4 + f | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2 UNION SELECT $3, $4; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3) UNION SELECT 3, 4, 5; + f | 1 | EXPLAIN (COSTS OFF) SELECT $1; EXPLAIN (COSTS OFF) SELECT 1, 2; + f | 1 | EXPLAIN (COSTS OFF) SELECT 1, 2 UNION SELECT 3, 4; EXPLAIN (COSTS OFF) (SELECT $1, $2, $3) UNION SELECT $4, $5, $6; + f | 1 | EXPLAIN (COSTS OFF) SELECT 1; EXPLAIN (COSTS OFF) SELECT $1, $2; + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(13 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- Most DMLs +EXPLAIN (COSTS OFF) TABLE stats_track_tab\; EXPLAIN (COSTS OFF) (TABLE test_table); + QUERY PLAN +----------------------------- + Seq Scan on stats_track_tab +(1 row) + + QUERY PLAN +------------------------ + Seq Scan on test_table +(1 row) + +EXPLAIN (COSTS OFF) VALUES (1)\; EXPLAIN (COSTS OFF) (VALUES (1, 2)); + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1\; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab\; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = 1; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1))\; EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (1), (2); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + + QUERY PLAN +--------------------------------- + Insert on stats_track_tab + -> Values Scan on "*VALUES*" +(2 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------------------------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) (TABLE test_table) + t | 1 | EXPLAIN (COSTS OFF) (VALUES ($1, $2)) + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = $1 + f | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = $1; + f | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = 1; + t | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ($1), ($2) + t | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)) + f | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)); EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (1), (2); + f | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1)); EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ($1), ($2); + t | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab + f | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab; EXPLAIN (COSTS OFF) (TABLE test_table); + f | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab; EXPLAIN (COSTS OFF) (TABLE test_table); + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2 + f | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1; + f | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1; + t | 1 | EXPLAIN (COSTS OFF) VALUES ($1) + f | 1 | EXPLAIN (COSTS OFF) VALUES ($1); EXPLAIN (COSTS OFF) (VALUES (1, 2)); + f | 1 | EXPLAIN (COSTS OFF) VALUES (1); EXPLAIN (COSTS OFF) (VALUES ($1, $2)); + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(21 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- MERGE, worth its own. +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id)\; EXPLAIN (COSTS OFF) SELECT 1, 2, 3, 4, 5; + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + + QUERY PLAN +------------ + Result +(1 row) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------------------------ + t | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($1, $2) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + f | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($1, $2) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id); EXPLAIN (COSTS OFF) SELECT 1, 2, 3, 4, 5; + f | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series(1, 10) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id); EXPLAIN (COSTS OFF) SELECT $1, $2, $3, $4, $5; + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2, $3, $4, $5 + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- EXPLAIN - top-level tracking with multi-statement strings. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) SELECT 1\; EXPLAIN (COSTS OFF) SELECT 1, 2; + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (SELECT 1, 2, 3)\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3, 4); + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) TABLE stats_track_tab\; EXPLAIN (COSTS OFF) (TABLE test_table); + QUERY PLAN +----------------------------- + Seq Scan on stats_track_tab +(1 row) + + QUERY PLAN +------------------------ + Seq Scan on test_table +(1 row) + +EXPLAIN (COSTS OFF) VALUES (1)\; EXPLAIN (COSTS OFF) (VALUES (1, 2)); + QUERY PLAN +------------ + Result +(1 row) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1\; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab\; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = 1; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1))\; EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1), (2)); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + +ERROR: INSERT has more expressions than target columns +LINE 1: ...N (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1), (2)); + ^ +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id)\; EXPLAIN (COSTS OFF) SELECT 1, 2, 3, 4, 5; + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) SELECT 1, 2 UNION SELECT 3, 4\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3) UNION SELECT 3, 4, 5; + QUERY PLAN +---------------------------- + Unique + -> Sort + Sort Key: (1), (2) + -> Append + -> Result + -> Result +(6 rows) + + QUERY PLAN +--------------------------------- + Unique + -> Sort + Sort Key: (1), (2), (3) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------------------------------------ + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3) + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3) UNION SELECT $4, $5, $6 + t | 1 | EXPLAIN (COSTS OFF) (SELECT $1, $2, $3, $4) + t | 1 | EXPLAIN (COSTS OFF) (TABLE test_table) + t | 1 | EXPLAIN (COSTS OFF) (VALUES ($1, $2)) + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = $1 + t | 1 | EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (($1)) + t | 1 | EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab USING (SELECT id FROM generate_series($1, $2) id) ON x = id+ + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + t | 1 | EXPLAIN (COSTS OFF) SELECT $1 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2 UNION SELECT $3, $4 + t | 1 | EXPLAIN (COSTS OFF) SELECT $1, $2, $3, $4, $5 + t | 1 | EXPLAIN (COSTS OFF) TABLE stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 + t | 1 | EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = $1 WHERE x = $2 + t | 1 | EXPLAIN (COSTS OFF) VALUES ($1) + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(18 rows) + +-- EXPLAIN with CTEs - all-level tracking +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (WITH a AS (SELECT 4) (SELECT 1, 2)); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) UPDATE stats_track_tab SET x = 1 WHERE x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) DELETE FROM stats_track_tab; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) INSERT INTO stats_track_tab VALUES ((1)); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + +EXPLAIN (COSTS OFF) WITH a AS (select 4) SELECT 1 UNION SELECT 2; + QUERY PLAN +-------------------------- + Unique + -> Sort + Sort Key: (1) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) (WITH a AS (SELECT $1) (SELECT $2, $3)) + f | 1 | EXPLAIN (COSTS OFF) (WITH a AS (SELECT $1) (SELECT $2, $3)); + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) DELETE FROM stats_track_tab + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) DELETE FROM stats_track_tab; + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) INSERT INTO stats_track_tab VALUES (($2)) + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) INSERT INTO stats_track_tab VALUES (($2)); + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($2, $3) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($2, $3) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) SELECT $2 + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) SELECT $2; + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) UPDATE stats_track_tab SET x = $2 WHERE x = $3 + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) UPDATE stats_track_tab SET x = $2 WHERE x = $3; + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (select $1) SELECT $2 UNION SELECT $3 + f | 1 | EXPLAIN (COSTS OFF) WITH a AS (select $1) SELECT $2 UNION SELECT $3; + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(15 rows) + +-- EXPLAIN with CTEs - top-level tracking +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) (WITH a AS (SELECT 4) (SELECT 1, 2)); + QUERY PLAN +------------ + Result +(1 row) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) UPDATE stats_track_tab SET x = 1 WHERE x = 1; + QUERY PLAN +----------------------------------- + Update on stats_track_tab + -> Seq Scan on stats_track_tab + Filter: (x = 1) +(3 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) DELETE FROM stats_track_tab; + QUERY PLAN +----------------------------------- + Delete on stats_track_tab + -> Seq Scan on stats_track_tab +(2 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) INSERT INTO stats_track_tab VALUES ((1)); + QUERY PLAN +--------------------------- + Insert on stats_track_tab + -> Result +(2 rows) + +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); + QUERY PLAN +------------------------------------------------------- + Merge on stats_track_tab + -> Hash Right Join + Hash Cond: (stats_track_tab.x = id.id) + -> Seq Scan on stats_track_tab + -> Hash + -> Function Scan on generate_series id +(6 rows) + +EXPLAIN (COSTS OFF) WITH a AS (select 4) SELECT 1 UNION SELECT 2; + QUERY PLAN +-------------------------- + Unique + -> Sort + Sort Key: (1) + -> Append + -> Result + -> Result +(6 rows) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------------------ + t | 1 | EXPLAIN (COSTS OFF) (WITH a AS (SELECT $1) (SELECT $2, $3)) + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) DELETE FROM stats_track_tab + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) INSERT INTO stats_track_tab VALUES (($2)) + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) MERGE INTO stats_track_tab + + | | USING (SELECT id FROM generate_series($2, $3) id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) SELECT $2 + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (SELECT $1) UPDATE stats_track_tab SET x = $2 WHERE x = $3 + t | 1 | EXPLAIN (COSTS OFF) WITH a AS (select $1) SELECT $2 UNION SELECT $3 + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(8 rows) + +-- Explain analyze, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100; + QUERY PLAN +----------------------------------- + Result (actual rows=1.00 loops=1) +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab; + QUERY PLAN +-------------------------------------------------------- + Seq Scan on stats_track_tab (actual rows=0.00 loops=1) +(1 row) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------- + t | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + + | | DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab + f | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + + | | DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab; + t | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT $1 + f | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT $1; + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- Explain analyze, top tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100; + QUERY PLAN +----------------------------------- + Result (actual rows=1.00 loops=1) +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab; + QUERY PLAN +-------------------------------------------------------- + Seq Scan on stats_track_tab (actual rows=0.00 loops=1) +(1 row) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------------------------------ + t | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + + | | DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab + t | 1 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT $1 + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(3 rows) + +-- Create Materialized View, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +CREATE MATERIALIZED VIEW pgss_materialized_view AS + SELECT * FROM generate_series(1, 5) as id; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------- + t | 1 | CREATE MATERIALIZED VIEW pgss_materialized_view AS+ + | | SELECT * FROM generate_series($1, $2) as id + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- CREATE MATERIALIZED VIEW, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +CREATE MATERIALIZED VIEW pgss_materialized_view_2 AS + SELECT * FROM generate_series(1, 5) as id; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+------------------------------------------------------ + t | 1 | CREATE MATERIALIZED VIEW pgss_materialized_view_2 AS+ + | | SELECT * FROM generate_series($1, $2) as id + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- REFRESH MATERIALIZED VIEW, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +REFRESH MATERIALIZED VIEW pgss_materialized_view; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------- + t | 1 | REFRESH MATERIALIZED VIEW pgss_materialized_view + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- REFRESH MATERIALIZED VIEW, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +REFRESH MATERIALIZED VIEW pgss_materialized_view; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------- + t | 1 | REFRESH MATERIALIZED VIEW pgss_materialized_view + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- CREATE TABLE AS, all-level tracking. +SET pg_stat_statements.track = 'all'; +PREPARE test_prepare_pgss AS select generate_series(1, 10); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +CREATE TEMPORARY TABLE pgss_ctas_1 AS SELECT 1; +CREATE TEMPORARY TABLE pgss_ctas_2 AS EXECUTE test_prepare_pgss; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+----------------------------------------------------------------- + t | 1 | CREATE TEMPORARY TABLE pgss_ctas_1 AS SELECT $1 + f | 1 | CREATE TEMPORARY TABLE pgss_ctas_1 AS SELECT $1; + t | 1 | CREATE TEMPORARY TABLE pgss_ctas_2 AS EXECUTE test_prepare_pgss + f | 1 | PREPARE test_prepare_pgss AS select generate_series($1, $2) + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- CREATE TABLE AS, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +CREATE TEMPORARY TABLE pgss_ctas_3 AS SELECT 1; +CREATE TEMPORARY TABLE pgss_ctas_4 AS EXECUTE test_prepare_pgss; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+----------------------------------------------------------------- + t | 1 | CREATE TEMPORARY TABLE pgss_ctas_3 AS SELECT $1 + t | 1 | CREATE TEMPORARY TABLE pgss_ctas_4 AS EXECUTE test_prepare_pgss + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(3 rows) + +-- EXPLAIN with CREATE TABLE AS - all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT $1 + f | 1 | EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT $1; + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(3 rows) + +-- EXPLAIN with CREATE TABLE AS - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT 1; + QUERY PLAN +------------ + Result +(1 row) + +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+--------------------------------------------------------------------------- + t | 1 | EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT $1 + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- DECLARE CURSOR, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +BEGIN; +DECLARE FOOCUR CURSOR FOR SELECT * from stats_track_tab; +FETCH FORWARD 1 FROM foocur; + x +--- +(0 rows) + +CLOSE foocur; +COMMIT; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+---------------------------------------------------------- + t | 1 | BEGIN + t | 1 | CLOSE foocur + t | 1 | COMMIT + t | 1 | DECLARE FOOCUR CURSOR FOR SELECT * from stats_track_tab + f | 1 | DECLARE FOOCUR CURSOR FOR SELECT * from stats_track_tab; + t | 1 | FETCH FORWARD 1 FROM foocur + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(7 rows) + +-- DECLARE CURSOR, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +BEGIN; +DECLARE FOOCUR CURSOR FOR SELECT * FROM stats_track_tab; +FETCH FORWARD 1 FROM foocur; + x +--- +(0 rows) + +CLOSE foocur; +COMMIT; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+--------------------------------------------------------- + t | 1 | BEGIN + t | 1 | CLOSE foocur + t | 1 | COMMIT + t | 1 | DECLARE FOOCUR CURSOR FOR SELECT * FROM stats_track_tab + t | 1 | FETCH FORWARD 1 FROM foocur + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(6 rows) + +-- COPY - all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +COPY (SELECT 1) TO stdout; +1 +COPY (SELECT 1 UNION SELECT 2) TO stdout; +1 +2 +COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout; +1 +COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout; +1 +COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout; +2 +2 +COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout; +2 +2 +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+----------------------------------------------------------------------------- + f | 1 | COPY (DELETE FROM stats_track_tab WHERE x = $1 RETURNING x) TO stdout + t | 1 | COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout + f | 1 | COPY (INSERT INTO stats_track_tab (x) VALUES ($1) RETURNING x) TO stdout + t | 1 | COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout + f | 1 | COPY (MERGE INTO stats_track_tab USING (SELECT $1 id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout + t | 1 | COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout + f | 1 | COPY (SELECT $1 UNION SELECT $2) TO stdout + f | 1 | COPY (SELECT $1) TO stdout + t | 1 | COPY (SELECT 1 UNION SELECT 2) TO stdout + t | 1 | COPY (SELECT 1) TO stdout + f | 1 | COPY (UPDATE stats_track_tab SET x = $1 WHERE x = $2 RETURNING x) TO stdout + t | 1 | COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(13 rows) + +-- COPY - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +COPY (SELECT 1) TO stdout; +1 +COPY (SELECT 1 UNION SELECT 2) TO stdout; +1 +2 +COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout; +1 +COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout; +1 +COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout; +2 +2 +COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout; +2 +2 +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + toplevel | calls | query +----------+-------+--------------------------------------------------------------------------- + t | 1 | COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout + t | 1 | COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout + t | 1 | COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + + | | WHEN MATCHED THEN UPDATE SET x = id + + | | WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout + t | 1 | COPY (SELECT 1 UNION SELECT 2) TO stdout + t | 1 | COPY (SELECT 1) TO stdout + t | 1 | COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout + t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(7 rows) + -- DO block - top-level tracking without utility. SET pg_stat_statements.track = 'top'; SET pg_stat_statements.track_utility = FALSE; @@ -167,6 +1323,57 @@ SELECT toplevel, calls, query FROM pg_stat_statements t | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t (4 rows) +-- DO block --- multiple inner queries with separators +SET pg_stat_statements.track = 'all'; +SET pg_stat_statements.track_utility = TRUE; +CREATE TABLE pgss_do_util_tab_1 (a int); +CREATE TABLE pgss_do_util_tab_2 (a int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +DO $$ +DECLARE BEGIN + EXECUTE 'CREATE TABLE pgss_do_table (id INT); DROP TABLE pgss_do_table'; + EXECUTE 'SELECT a FROM pgss_do_util_tab_1; SELECT a FROM pgss_do_util_tab_2'; +END $$; +SELECT toplevel, calls, rows, query FROM pg_stat_statements + WHERE toplevel IS FALSE + ORDER BY query COLLATE "C"; + toplevel | calls | rows | query +----------+-------+------+------------------------------------- + f | 1 | 0 | CREATE TABLE pgss_do_table (id INT) + f | 1 | 0 | DROP TABLE pgss_do_table + f | 1 | 0 | SELECT a FROM pgss_do_util_tab_1 + f | 1 | 0 | SELECT a FROM pgss_do_util_tab_2 +(4 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- Note the extra semicolon at the end of the query. +DO $$ +DECLARE BEGIN + EXECUTE 'CREATE TABLE pgss_do_table (id INT); DROP TABLE pgss_do_table;'; + EXECUTE 'SELECT a FROM pgss_do_util_tab_1; SELECT a FROM pgss_do_util_tab_2;'; +END $$; +SELECT toplevel, calls, rows, query FROM pg_stat_statements + WHERE toplevel IS FALSE + ORDER BY query COLLATE "C"; + toplevel | calls | rows | query +----------+-------+------+------------------------------------- + f | 1 | 0 | CREATE TABLE pgss_do_table (id INT) + f | 1 | 0 | DROP TABLE pgss_do_table + f | 1 | 0 | SELECT a FROM pgss_do_util_tab_1 + f | 1 | 0 | SELECT a FROM pgss_do_util_tab_2 +(4 rows) + +DROP TABLE pgss_do_util_tab_1, pgss_do_util_tab_2; -- PL/pgSQL function - top-level tracking. SET pg_stat_statements.track = 'top'; SET pg_stat_statements.track_utility = FALSE; diff --git a/contrib/pg_stat_statements/expected/oldextversions.out b/contrib/pg_stat_statements/expected/oldextversions.out index 5842c930e50ff..de679b19711ab 100644 --- a/contrib/pg_stat_statements/expected/oldextversions.out +++ b/contrib/pg_stat_statements/expected/oldextversions.out @@ -342,4 +342,69 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; t (1 row) +-- New functions and views for pg_stat_statements in 1.12 +AlTER EXTENSION pg_stat_statements UPDATE TO '1.12'; +\d pg_stat_statements + View "public.pg_stat_statements" + Column | Type | Collation | Nullable | Default +----------------------------+--------------------------+-----------+----------+--------- + userid | oid | | | + dbid | oid | | | + toplevel | boolean | | | + queryid | bigint | | | + query | text | | | + plans | bigint | | | + total_plan_time | double precision | | | + min_plan_time | double precision | | | + max_plan_time | double precision | | | + mean_plan_time | double precision | | | + stddev_plan_time | double precision | | | + calls | bigint | | | + total_exec_time | double precision | | | + min_exec_time | double precision | | | + max_exec_time | double precision | | | + mean_exec_time | double precision | | | + stddev_exec_time | double precision | | | + rows | bigint | | | + shared_blks_hit | bigint | | | + shared_blks_read | bigint | | | + shared_blks_dirtied | bigint | | | + shared_blks_written | bigint | | | + local_blks_hit | bigint | | | + local_blks_read | bigint | | | + local_blks_dirtied | bigint | | | + local_blks_written | bigint | | | + temp_blks_read | bigint | | | + temp_blks_written | bigint | | | + shared_blk_read_time | double precision | | | + shared_blk_write_time | double precision | | | + local_blk_read_time | double precision | | | + local_blk_write_time | double precision | | | + temp_blk_read_time | double precision | | | + temp_blk_write_time | double precision | | | + wal_records | bigint | | | + wal_fpi | bigint | | | + wal_bytes | numeric | | | + wal_buffers_full | bigint | | | + jit_functions | bigint | | | + jit_generation_time | double precision | | | + jit_inlining_count | bigint | | | + jit_inlining_time | double precision | | | + jit_optimization_count | bigint | | | + jit_optimization_time | double precision | | | + jit_emission_count | bigint | | | + jit_emission_time | double precision | | | + jit_deform_count | bigint | | | + jit_deform_time | double precision | | | + parallel_workers_to_launch | bigint | | | + parallel_workers_launched | bigint | | | + stats_since | timestamp with time zone | | | + minmax_stats_since | timestamp with time zone | | | + +SELECT count(*) > 0 AS has_data FROM pg_stat_statements; + has_data +---------- + t +(1 row) + DROP EXTENSION pg_stat_statements; diff --git a/contrib/pg_stat_statements/expected/parallel.out b/contrib/pg_stat_statements/expected/parallel.out new file mode 100644 index 0000000000000..8af3bd2c91588 --- /dev/null +++ b/contrib/pg_stat_statements/expected/parallel.out @@ -0,0 +1,34 @@ +-- +-- Tests for parallel statistics +-- +SET pg_stat_statements.track_utility = FALSE; +-- encourage use of parallel plans +SET parallel_setup_cost = 0; +SET parallel_tuple_cost = 0; +SET min_parallel_table_scan_size = 0; +SET max_parallel_workers_per_gather = 2; +CREATE TABLE pgss_parallel_tab (a int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT count(*) FROM pgss_parallel_tab; + count +------- + 0 +(1 row) + +SELECT query, + parallel_workers_to_launch > 0 AS has_workers_to_launch, + parallel_workers_launched > 0 AS has_workers_launched + FROM pg_stat_statements + WHERE query ~ 'SELECT count' + ORDER BY query COLLATE "C"; + query | has_workers_to_launch | has_workers_launched +----------------------------------------+-----------------------+---------------------- + SELECT count(*) FROM pgss_parallel_tab | t | t +(1 row) + +DROP TABLE pgss_parallel_tab; diff --git a/contrib/pg_stat_statements/expected/select.out b/contrib/pg_stat_statements/expected/select.out index dd6c756f67d5b..75c896f388512 100644 --- a/contrib/pg_stat_statements/expected/select.out +++ b/contrib/pg_stat_statements/expected/select.out @@ -19,8 +19,89 @@ SELECT 1 AS "int"; 1 (1 row) +-- LIMIT and OFFSET patterns +-- Try some query permutations which once produced identical query IDs +SELECT 1 AS "int" LIMIT 1; + int +----- + 1 +(1 row) + +SELECT 1 AS "int" LIMIT 2; + int +----- + 1 +(1 row) + +SELECT 1 AS "int" OFFSET 1; + int +----- +(0 rows) + +SELECT 1 AS "int" OFFSET 2; + int +----- +(0 rows) + +SELECT 1 AS "int" OFFSET 1 LIMIT 1; + int +----- +(0 rows) + +SELECT 1 AS "int" OFFSET 2 LIMIT 2; + int +----- +(0 rows) + +SELECT 1 AS "int" LIMIT 1 OFFSET 1; + int +----- +(0 rows) + +SELECT 1 AS "int" LIMIT 3 OFFSET 3; + int +----- +(0 rows) + +SELECT 1 AS "int" OFFSET 1 FETCH FIRST 2 ROW ONLY; + int +----- +(0 rows) + +SELECT 1 AS "int" OFFSET 2 FETCH FIRST 3 ROW ONLY; + int +----- +(0 rows) + +-- DISTINCT and ORDER BY patterns +-- Try some query permutations which once produced identical query IDs +SELECT DISTINCT 1 AS "int"; + int +----- + 1 +(1 row) + +SELECT DISTINCT 2 AS "int"; + int +----- + 2 +(1 row) + +SELECT 1 AS "int" ORDER BY 1; + int +----- + 1 +(1 row) + +SELECT 2 AS "int" ORDER BY 1; + int +----- + 2 +(1 row) + +/* this comment should not appear in the output */ SELECT 'hello' - -- multiline + -- but this one will appear AS "text"; text ------- @@ -129,14 +210,19 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; -------+------+------------------------------------------------------------------------------ 1 | 1 | PREPARE pgss_test (int) AS SELECT $1, $2 LIMIT $3 4 | 4 | SELECT $1 + - | | -- multiline + + | | -- but this one will appear + | | AS "text" 2 | 2 | SELECT $1 + $2 3 | 3 | SELECT $1 + $2 + $3 AS "add" 1 | 1 | SELECT $1 AS "float" 2 | 2 | SELECT $1 AS "int" + 2 | 2 | SELECT $1 AS "int" LIMIT $2 + 2 | 0 | SELECT $1 AS "int" OFFSET $2 + 6 | 0 | SELECT $1 AS "int" OFFSET $2 LIMIT $3 + 2 | 2 | SELECT $1 AS "int" ORDER BY 1 1 | 2 | SELECT $1 AS i UNION SELECT $2 ORDER BY i 1 | 1 | SELECT $1 || $2 + 2 | 2 | SELECT DISTINCT $1 AS "int" 0 | 0 | SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C" 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t 1 | 2 | WITH t(f) AS ( + @@ -144,14 +230,73 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; | | ) + | | SELECT f FROM t ORDER BY f 1 | 1 | select $1::jsonb ? $2 -(12 rows) +(17 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) +-- normalization of constants and parameters, with constant locations +-- recorded one or more times. SELECT pg_stat_statements_reset() IS NOT NULL AS t; t --- t (1 row) +SELECT WHERE '1' IN ('1'::int, '3'::int::text); +-- +(1 row) + +SELECT WHERE (1, 2) IN ((1, 2), (2, 3)); +-- +(1 row) + +SELECT WHERE (3, 4) IN ((5, 6), (8, 7)); +-- +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +------------------------------------------------------------------------+------- + SELECT WHERE $1 IN ($2::int, $3::int::text) | 1 + SELECT WHERE ($1, $2) IN (($3, $4), ($5, $6)) | 2 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 + SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C" | 0 +(4 rows) + +-- with the last element being an explicit function call with an argument, ensure +-- the normalization of the squashing interval is correct. +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT WHERE 1 IN (1, int4(1), int4(2)); +-- +(1 row) + +SELECT WHERE 1 = ANY (ARRAY[1, int4(1), int4(2)]); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +------------------------------------------------------------------------+------- + SELECT WHERE $1 IN ($2 /*, ... */) | 2 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 + SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C" | 0 +(3 rows) + -- -- queries with locking clauses -- @@ -412,3 +557,239 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; t (1 row) +-- Temporary table with same name, re-created. +BEGIN; + CREATE TEMP TABLE temp_t (id int) ON COMMIT DROP; + SELECT * FROM temp_t; + id +---- +(0 rows) + +COMMIT; +BEGIN; + CREATE TEMP TABLE temp_t (id int) ON COMMIT DROP; + SELECT * FROM temp_t; + id +---- +(0 rows) + +COMMIT; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+------------------------------------------------------------------------ + 2 | SELECT * FROM temp_t + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(3 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- search_path with various schemas and temporary tables +CREATE SCHEMA pgss_schema_1; +CREATE SCHEMA pgss_schema_2; +-- Same attributes. +CREATE TABLE pgss_schema_1.tab_search_same (a int, b int); +CREATE TABLE pgss_schema_2.tab_search_same (a int, b int); +CREATE TEMP TABLE tab_search_same (a int, b int); +-- Different number of attributes, mapping types +CREATE TABLE pgss_schema_1.tab_search_diff_1 (a int); +CREATE TABLE pgss_schema_2.tab_search_diff_1 (a int, b int); +CREATE TEMP TABLE tab_search_diff_1 (a int, b int, c int); +-- Same number of attributes, different types +CREATE TABLE pgss_schema_1.tab_search_diff_2 (a int); +CREATE TABLE pgss_schema_2.tab_search_diff_2 (a text); +CREATE TEMP TABLE tab_search_diff_2 (a bigint); +-- First permanent schema +SET search_path = 'pgss_schema_1'; +SELECT count(*) FROM tab_search_same; + count +------- + 0 +(1 row) + +SELECT a, b FROM tab_search_same; + a | b +---+--- +(0 rows) + +SELECT count(*) FROM tab_search_diff_1; + count +------- + 0 +(1 row) + +SELECT count(*) FROM tab_search_diff_2; + count +------- + 0 +(1 row) + +SELECT a FROM tab_search_diff_2 AS t1; + a +--- +(0 rows) + +SELECT a FROM tab_search_diff_2; + a +--- +(0 rows) + +SELECT a AS a1 FROM tab_search_diff_2; + a1 +---- +(0 rows) + +-- Second permanent schema +SET search_path = 'pgss_schema_2'; +SELECT count(*) FROM tab_search_same; + count +------- + 0 +(1 row) + +SELECT a, b FROM tab_search_same; + a | b +---+--- +(0 rows) + +SELECT count(*) FROM tab_search_diff_1; + count +------- + 0 +(1 row) + +SELECT count(*) FROM tab_search_diff_2; + count +------- + 0 +(1 row) + +SELECT a FROM tab_search_diff_2 AS t1; + a +--- +(0 rows) + +SELECT a FROM tab_search_diff_2; + a +--- +(0 rows) + +SELECT a AS a1 FROM tab_search_diff_2; + a1 +---- +(0 rows) + +-- Temporary schema +SET search_path = 'pg_temp'; +SELECT count(*) FROM tab_search_same; + count +------- + 0 +(1 row) + +SELECT a, b FROM tab_search_same; + a | b +---+--- +(0 rows) + +SELECT count(*) FROM tab_search_diff_1; + count +------- + 0 +(1 row) + +SELECT count(*) FROM tab_search_diff_2; + count +------- + 0 +(1 row) + +SELECT a FROM tab_search_diff_2 AS t1; + a +--- +(0 rows) + +SELECT a FROM tab_search_diff_2; + a +--- +(0 rows) + +SELECT a AS a1 FROM tab_search_diff_2; + a1 +---- +(0 rows) + +RESET search_path; +-- Schema qualifications +SELECT count(*) FROM pgss_schema_1.tab_search_same; + count +------- + 0 +(1 row) + +SELECT a, b FROM pgss_schema_1.tab_search_same; + a | b +---+--- +(0 rows) + +SELECT count(*) FROM pgss_schema_2.tab_search_diff_1; + count +------- + 0 +(1 row) + +SELECT count(*) FROM pg_temp.tab_search_diff_2; + count +------- + 0 +(1 row) + +SELECT a FROM pgss_schema_2.tab_search_diff_2 AS t1; + a +--- +(0 rows) + +SELECT a FROM pgss_schema_2.tab_search_diff_2; + a +--- +(0 rows) + +SELECT a AS a1 FROM pgss_schema_2.tab_search_diff_2; + a1 +---- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+------------------------------------------------------------------------ + 8 | SELECT a FROM tab_search_diff_2 + 4 | SELECT a FROM tab_search_diff_2 AS t1 + 4 | SELECT a, b FROM tab_search_same + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 4 | SELECT count(*) FROM tab_search_diff_1 + 4 | SELECT count(*) FROM tab_search_diff_2 + 4 | SELECT count(*) FROM tab_search_same + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(8 rows) + +DROP SCHEMA pgss_schema_1 CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table pgss_schema_1.tab_search_same +drop cascades to table pgss_schema_1.tab_search_diff_1 +drop cascades to table pgss_schema_1.tab_search_diff_2 +DROP SCHEMA pgss_schema_2 CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table pgss_schema_2.tab_search_same +drop cascades to table pgss_schema_2.tab_search_diff_1 +drop cascades to table pgss_schema_2.tab_search_diff_2 +DROP TABLE tab_search_same, tab_search_diff_1, tab_search_diff_2; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/expected/squashing.out b/contrib/pg_stat_statements/expected/squashing.out new file mode 100644 index 0000000000000..7b935d464ecff --- /dev/null +++ b/contrib/pg_stat_statements/expected/squashing.out @@ -0,0 +1,812 @@ +-- +-- Const squashing functionality +-- +CREATE EXTENSION pg_stat_statements; +-- +-- Simple Lists +-- +CREATE TABLE test_squash (id int, data int); +-- single element will not be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN (1); + id | data +----+------ +(0 rows) + +SELECT ARRAY[1]; + array +------- + {1} +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN ($1) | 1 + SELECT ARRAY[$1] | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- more than 1 element in a list will be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5); + id | data +----+------ +(0 rows) + +SELECT ARRAY[1, 2, 3]; + array +--------- + {1,2,3} +(1 row) + +SELECT ARRAY[1, 2, 3, 4]; + array +----------- + {1,2,3,4} +(1 row) + +SELECT ARRAY[1, 2, 3, 4, 5]; + array +------------- + {1,2,3,4,5} +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +-------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN ($1 /*, ... */) | 3 + SELECT ARRAY[$1 /*, ... */] | 3 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- built-in functions will be squashed +-- the IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT WHERE 1 IN (1, int4(1), int4(2), 2); +-- +(1 row) + +SELECT WHERE 1 = ANY (ARRAY[1, int4(1), int4(2), 2]); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT WHERE $1 IN ($2 /*, ... */) | 2 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- external parameters will not be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5) \bind 1 2 3 4 5 +; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id::text = ANY(ARRAY[$1, $2, $3, $4, $5]) \bind 1 2 3 4 5 +; + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +---------------------------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5) | 1 + SELECT * FROM test_squash WHERE id::text = ANY(ARRAY[$1, $2, $3, $4, $5]) | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- neither are prepared statements +-- the IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +PREPARE p1(int, int, int, int, int) AS +SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5); +EXECUTE p1(1, 2, 3, 4, 5); + id | data +----+------ +(0 rows) + +DEALLOCATE p1; +PREPARE p1(int, int, int, int, int) AS +SELECT * FROM test_squash WHERE id = ANY(ARRAY[$1, $2, $3, $4, $5]); +EXECUTE p1(1, 2, 3, 4, 5); + id | data +----+------ +(0 rows) + +DEALLOCATE p1; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +------------------------------------------------------------+------- + DEALLOCATE $1 | 2 + PREPARE p1(int, int, int, int, int) AS +| 2 + SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- More conditions in the query +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) AND data = 2; + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +---------------------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN ($1 /*, ... */) AND data = $2 | 6 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Multiple squashed intervals +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +-------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN ($1 /*, ... */)+| 6 + AND data IN ($2 /*, ... */) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- No constants squashing for OpExpr +-- The IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash WHERE id IN + (1 + 1, 2 + 2, 3 + 3, 4 + 4, 5 + 5, 6 + 6, 7 + 7, 8 + 8, 9 + 9); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id IN + (@ '-1', @ '-2', @ '-3', @ '-4', @ '-5', @ '-6', @ '-7', @ '-8', @ '-9'); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY(ARRAY + [1 + 1, 2 + 2, 3 + 3, 4 + 4, 5 + 5, 6 + 6, 7 + 7, 8 + 8, 9 + 9]); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY(ARRAY + [@ '-1', @ '-2', @ '-3', @ '-4', @ '-5', @ '-6', @ '-7', @ '-8', @ '-9']); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN +| 2 + ($1 + $2, $3 + $4, $5 + $6, $7 + $8, $9 + $10, $11 + $12, $13 + $14, $15 + $16, $17 + $18) | + SELECT * FROM test_squash WHERE id IN +| 2 + (@ $1, @ $2, @ $3, @ $4, @ $5, @ $6, @ $7, @ $8, @ $9) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- +-- FuncExpr +-- +-- Verify multiple type representation end up with the same query_id +CREATE TABLE test_float (data float); +-- The casted ARRAY expressions will have the same queryId as the IN clause +-- form of the query +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT data FROM test_float WHERE data IN (1, 2); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data IN (1, '2'); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data IN ('1', 2); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data IN ('1', '2'); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data IN (1.0, 1.0); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data = ANY(ARRAY['1'::double precision, '2'::double precision]); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data = ANY(ARRAY[1.0::double precision, 1.0::double precision]); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data = ANY(ARRAY[1, 2]); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data = ANY(ARRAY[1, '2']); + data +------ +(0 rows) + +SELECT data FROM test_float WHERE data = ANY(ARRAY['1', 2]); + data +------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +--------------------------------------------------------------------+------- + SELECT data FROM test_float WHERE data = ANY(ARRAY[$1 /*, ... */]) | 3 + SELECT data FROM test_float WHERE data IN ($1 /*, ... */) | 7 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- Numeric type, implicit cast is squashed +CREATE TABLE test_squash_numeric (id int, data numeric(5, 2)); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_numeric WHERE data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_numeric WHERE data = ANY(ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +--------------------------------------------------------------------------+------- + SELECT * FROM test_squash_numeric WHERE data = ANY(ARRAY[$1 /*, ... */]) | 1 + SELECT * FROM test_squash_numeric WHERE data IN ($1 /*, ... */) | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- Bigint, implicit cast is squashed +CREATE TABLE test_squash_bigint (id int, data bigint); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_bigint WHERE data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +-------------------------------------------------------------------------+------- + SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[$1 /*, ... */]) | 1 + SELECT * FROM test_squash_bigint WHERE data IN ($1 /*, ... */) | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(3 rows) + +-- Bigint, explicit cast is squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_bigint WHERE data IN + (1::bigint, 2::bigint, 3::bigint, 4::bigint, 5::bigint, 6::bigint, + 7::bigint, 8::bigint, 9::bigint, 10::bigint, 11::bigint); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[ + 1::bigint, 2::bigint, 3::bigint, 4::bigint, 5::bigint, 6::bigint, + 7::bigint, 8::bigint, 9::bigint, 10::bigint, 11::bigint]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT * FROM test_squash_bigint WHERE data IN +| 2 + ($1 /*, ... */) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Bigint, long tokens with parenthesis, will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_bigint WHERE id IN + (abs(100), abs(200), abs(300), abs(400), abs(500), abs(600), abs(700), + abs(800), abs(900), abs(1000), ((abs(1100)))); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_bigint WHERE id = ANY(ARRAY[ + abs(100), abs(200), abs(300), abs(400), abs(500), abs(600), abs(700), + abs(800), abs(900), abs(1000), ((abs(1100)))]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +-------------------------------------------------------------------------+------- + SELECT * FROM test_squash_bigint WHERE id IN +| 2 + (abs($1), abs($2), abs($3), abs($4), abs($5), abs($6), abs($7),+| + abs($8), abs($9), abs($10), ((abs($11)))) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Multiple FuncExpr's. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT WHERE 1 IN (1::int::bigint::int, 2::int::bigint::int); +-- +(1 row) + +SELECT WHERE 1 = ANY(ARRAY[1::int::bigint::int, 2::int::bigint::int]); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT WHERE $1 IN ($2 /*, ... */) | 2 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- +-- CoerceViaIO +-- +-- Create some dummy type to force CoerceViaIO +CREATE TYPE casttesttype; +CREATE FUNCTION casttesttype_in(cstring) + RETURNS casttesttype + AS 'textin' + LANGUAGE internal STRICT IMMUTABLE; +NOTICE: return type casttesttype is only a shell +CREATE FUNCTION casttesttype_out(casttesttype) + RETURNS cstring + AS 'textout' + LANGUAGE internal STRICT IMMUTABLE; +NOTICE: argument type casttesttype is only a shell +LINE 1: CREATE FUNCTION casttesttype_out(casttesttype) + ^ +CREATE TYPE casttesttype ( + internallength = variable, + input = casttesttype_in, + output = casttesttype_out, + alignment = int4 +); +CREATE CAST (int4 AS casttesttype) WITH INOUT; +CREATE FUNCTION casttesttype_eq(casttesttype, casttesttype) +returns boolean language sql immutable as $$ + SELECT true +$$; +CREATE OPERATOR = ( + leftarg = casttesttype, + rightarg = casttesttype, + procedure = casttesttype_eq, + commutator = =); +CREATE TABLE test_squash_cast (id int, data casttesttype); +-- Use the introduced type to construct a list of CoerceViaIO around Const +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_cast WHERE data IN + (1::int4::casttesttype, 2::int4::casttesttype, 3::int4::casttesttype, + 4::int4::casttesttype, 5::int4::casttesttype, 6::int4::casttesttype, + 7::int4::casttesttype, 8::int4::casttesttype, 9::int4::casttesttype, + 10::int4::casttesttype, 11::int4::casttesttype); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_cast WHERE data = ANY (ARRAY + [1::int4::casttesttype, 2::int4::casttesttype, 3::int4::casttesttype, + 4::int4::casttesttype, 5::int4::casttesttype, 6::int4::casttesttype, + 7::int4::casttesttype, 8::int4::casttesttype, 9::int4::casttesttype, + 10::int4::casttesttype, 11::int4::casttesttype]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT * FROM test_squash_cast WHERE data IN +| 2 + ($1 /*, ... */) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Some casting expression are simplified to Const +CREATE TABLE test_squash_jsonb (id int, data jsonb); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_jsonb WHERE data IN + (('"1"')::jsonb, ('"2"')::jsonb, ('"3"')::jsonb, ('"4"')::jsonb, + ('"5"')::jsonb, ('"6"')::jsonb, ('"7"')::jsonb, ('"8"')::jsonb, + ('"9"')::jsonb, ('"10"')::jsonb); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_jsonb WHERE data = ANY (ARRAY + [('"1"')::jsonb, ('"2"')::jsonb, ('"3"')::jsonb, ('"4"')::jsonb, + ('"5"')::jsonb, ('"6"')::jsonb, ('"7"')::jsonb, ('"8"')::jsonb, + ('"9"')::jsonb, ('"10"')::jsonb]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT * FROM test_squash_jsonb WHERE data IN +| 2 + ($1 /*, ... */) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- CoerceViaIO, SubLink instead of a Const. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM test_squash_jsonb WHERE data IN + ((SELECT '"1"')::jsonb, (SELECT '"2"')::jsonb, (SELECT '"3"')::jsonb, + (SELECT '"4"')::jsonb, (SELECT '"5"')::jsonb, (SELECT '"6"')::jsonb, + (SELECT '"7"')::jsonb, (SELECT '"8"')::jsonb, (SELECT '"9"')::jsonb, + (SELECT '"10"')::jsonb); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash_jsonb WHERE data = ANY(ARRAY + [(SELECT '"1"')::jsonb, (SELECT '"2"')::jsonb, (SELECT '"3"')::jsonb, + (SELECT '"4"')::jsonb, (SELECT '"5"')::jsonb, (SELECT '"6"')::jsonb, + (SELECT '"7"')::jsonb, (SELECT '"8"')::jsonb, (SELECT '"9"')::jsonb, + (SELECT '"10"')::jsonb]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------------------------+------- + SELECT * FROM test_squash_jsonb WHERE data IN +| 2 + ((SELECT $1)::jsonb, (SELECT $2)::jsonb, (SELECT $3)::jsonb,+| + (SELECT $4)::jsonb, (SELECT $5)::jsonb, (SELECT $6)::jsonb,+| + (SELECT $7)::jsonb, (SELECT $8)::jsonb, (SELECT $9)::jsonb,+| + (SELECT $10)::jsonb) | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Multiple CoerceViaIO wrapping a constant. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT WHERE 1 IN (1::text::int::text::int, 1::text::int::text::int); +-- +(1 row) + +SELECT WHERE 1 = ANY(ARRAY[1::text::int::text::int, 1::text::int::text::int]); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +-------------------------------------------------------------------------+------- + SELECT WHERE $1 IN ($2::text::int::text::int, $3::text::int::text::int) | 2 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- +-- RelabelType +-- +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- if there is only one level of RelabelType, the list will be squashable +SELECT * FROM test_squash WHERE id IN + (1::oid, 2::oid, 3::oid, 4::oid, 5::oid, 6::oid, 7::oid, 8::oid, 9::oid); + id | data +----+------ +(0 rows) + +SELECT ARRAY[1::oid, 2::oid, 3::oid, 4::oid, 5::oid, 6::oid, 7::oid, 8::oid, 9::oid]; + array +--------------------- + {1,2,3,4,5,6,7,8,9} +(1 row) + +-- if there is at least one element with multiple levels of RelabelType, +-- the list will not be squashable +SELECT * FROM test_squash WHERE id IN (1::oid, 2::oid::int::oid); + id | data +----+------ +(0 rows) + +SELECT * FROM test_squash WHERE id = ANY(ARRAY[1::oid, 2::oid::int::oid]); + id | data +----+------ +(0 rows) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +--------------------------------------------------------------------+------- + SELECT * FROM test_squash WHERE id IN +| 1 + ($1 /*, ... */) | + SELECT * FROM test_squash WHERE id IN ($1::oid, $2::oid::int::oid) | 2 + SELECT ARRAY[$1 /*, ... */] | 1 + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(4 rows) + +-- +-- edge cases +-- +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- for nested arrays, only constants are squashed +SELECT ARRAY[ + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + ]; + array +----------------------------------------------------------------------------------------------- + {{1,2,3,4,5,6,7,8,9,10},{1,2,3,4,5,6,7,8,9,10},{1,2,3,4,5,6,7,8,9,10},{1,2,3,4,5,6,7,8,9,10}} +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT ARRAY[ +| 1 + ARRAY[$1 /*, ... */], +| + ARRAY[$2 /*, ... */], +| + ARRAY[$3 /*, ... */], +| + ARRAY[$4 /*, ... */] +| + ] | + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 +(2 rows) + +-- Test constants evaluation in a CTE, which was causing issues in the past +WITH cte AS ( + SELECT 'const' as const FROM test_squash +) +SELECT ARRAY['a', 'b', 'c', const::varchar] AS result +FROM cte; + result +-------- +(0 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- Rewritten as an OpExpr, so it will not be squashed +select where '1' IN ('1'::int, '2'::int::text); +-- +(1 row) + +-- Rewritten as an ArrayExpr, so it will be squashed +select where '1' IN ('1'::int, '2'::int); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 + select where $1 IN ($2 /*, ... */) | 1 + select where $1 IN ($2::int, $3::int::text) | 1 +(3 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- Both of these queries will be rewritten as an ArrayExpr, so they +-- will be squashed, and have a similar queryId +select where '1' IN ('1'::int::text, '2'::int::text); +-- +(1 row) + +select where '1' = ANY (array['1'::int::text, '2'::int::text]); +-- +(1 row) + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + query | calls +----------------------------------------------------+------- + SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 + select where $1 IN ($2 /*, ... */) | 2 +(2 rows) + +-- +-- cleanup +-- +DROP TABLE test_squash; +DROP TABLE test_float; +DROP TABLE test_squash_numeric; +DROP TABLE test_squash_bigint; +DROP TABLE test_squash_cast CASCADE; +DROP TABLE test_squash_jsonb; diff --git a/contrib/pg_stat_statements/expected/utility.out b/contrib/pg_stat_statements/expected/utility.out index fa738b5c00d41..060d4416dd749 100644 --- a/contrib/pg_stat_statements/expected/utility.out +++ b/contrib/pg_stat_statements/expected/utility.out @@ -66,7 +66,8 @@ DROP SERVER server_stats; DROP FOREIGN DATA WRAPPER wrapper_stats; -- Functions CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data')) - RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL; + RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + SET work_mem = '256kB'; DROP FUNCTION func_stats; -- Rules CREATE TABLE tab_rule_stats (a int, b int); @@ -106,7 +107,8 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; 1 | 0 | CREATE FOREIGN DATA WRAPPER wrapper_stats 1 | 0 | CREATE FOREIGN TABLE foreign_stats (a int) SERVER server_stats 1 | 0 | CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data'))+ - | | RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + | | RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + + | | SET work_mem = $1 1 | 0 | CREATE FUNCTION trigger_func_stats () RETURNS trigger LANGUAGE plpgsql + | | AS $$ BEGIN return OLD; end; $$ 1 | 0 | CREATE INDEX pt_stats2_index ON ONLY pt_stats2 (a) @@ -551,12 +553,26 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- SET statements. -- These use two different strings, still they count as one entry. +CREATE ROLE regress_stat_set_1; +CREATE ROLE regress_stat_set_2; SET work_mem = '1MB'; Set work_mem = '1MB'; SET work_mem = '2MB'; +SET work_mem = DEFAULT; +SET work_mem TO DEFAULT; +SET work_mem FROM CURRENT; +BEGIN; +SET LOCAL work_mem = '128kB'; +SET LOCAL work_mem = '256kB'; +SET LOCAL work_mem = DEFAULT; +SET LOCAL work_mem TO DEFAULT; +SET LOCAL work_mem FROM CURRENT; +COMMIT; RESET work_mem; SET enable_seqscan = off; SET enable_seqscan = on; +SET SESSION work_mem = '300kB'; +SET SESSION work_mem = '400kB'; RESET enable_seqscan; -- SET TRANSACTION ISOLATION BEGIN; @@ -564,33 +580,72 @@ SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; COMMIT; --- SET SESSION CHARACTERISTICS +-- SET SESSION AUTHORIZATION SET SESSION SESSION AUTHORIZATION DEFAULT; +SET SESSION AUTHORIZATION 'regress_stat_set_1'; +SET SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; BEGIN; SET LOCAL SESSION AUTHORIZATION DEFAULT; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1'; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; COMMIT; +-- SET SESSION CHARACTERISTICS +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE; +-- SET XML OPTION +SET XML OPTION DOCUMENT; +SET XML OPTION CONTENT; +-- SET TIME ZONE +SET TIME ZONE 'America/New_York'; +SET TIME ZONE 'Asia/Tokyo'; +SET TIME ZONE DEFAULT; +SET TIME ZONE LOCAL; +SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0'; +RESET TIME ZONE; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; - calls | rows | query --------+------+---------------------------------------------------- - 2 | 0 | BEGIN - 2 | 0 | COMMIT + calls | rows | query +-------+------+------------------------------------------------------------------ + 3 | 0 | BEGIN + 3 | 0 | COMMIT + 1 | 0 | CREATE ROLE regress_stat_set_1 + 1 | 0 | CREATE ROLE regress_stat_set_2 2 | 0 | RESET SESSION AUTHORIZATION + 1 | 0 | RESET TIME ZONE 1 | 0 | RESET enable_seqscan 1 | 0 | RESET work_mem 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 1 | 0 | SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1' + 1 | 0 | SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2' 1 | 0 | SET LOCAL SESSION AUTHORIZATION DEFAULT + 2 | 0 | SET LOCAL work_mem = $1 + 2 | 0 | SET LOCAL work_mem = DEFAULT + 1 | 0 | SET LOCAL work_mem FROM CURRENT + 1 | 0 | SET SESSION AUTHORIZATION 'regress_stat_set_1' + 1 | 0 | SET SESSION AUTHORIZATION 'regress_stat_set_2' + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY + 1 | 0 | SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE 1 | 0 | SET SESSION SESSION AUTHORIZATION DEFAULT + 1 | 0 | SET TIME ZONE 'America/New_York' + 1 | 0 | SET TIME ZONE 'Asia/Tokyo' + 1 | 0 | SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0' + 2 | 0 | SET TIME ZONE DEFAULT 1 | 0 | SET TRANSACTION ISOLATION LEVEL READ COMMITTED 1 | 0 | SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 1 | 0 | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - 1 | 0 | SET enable_seqscan = off - 1 | 0 | SET enable_seqscan = on - 2 | 0 | SET work_mem = '1MB' - 1 | 0 | SET work_mem = '2MB' -(15 rows) - + 1 | 0 | SET XML OPTION CONTENT + 1 | 0 | SET XML OPTION DOCUMENT + 2 | 0 | SET enable_seqscan = $1 + 5 | 0 | SET work_mem = $1 + 2 | 0 | SET work_mem = DEFAULT + 1 | 0 | SET work_mem FROM CURRENT +(34 rows) + +DROP ROLE regress_stat_set_1; +DROP ROLE regress_stat_set_2; SELECT pg_stat_statements_reset() IS NOT NULL AS t; t --- @@ -664,3 +719,21 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; t (1 row) +-- Special cases. Keep these ones at the end to avoid conflicts. +SET SCHEMA 'foo'; +SET SCHEMA 'public'; +RESET ALL; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | rows | query +-------+------+---------------------------------------------------- + 1 | 0 | RESET ALL + 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 2 | 0 | SET SCHEMA $1 +(3 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/expected/wal.out b/contrib/pg_stat_statements/expected/wal.out index 34a2bf5b033c1..977e382d84894 100644 --- a/contrib/pg_stat_statements/expected/wal.out +++ b/contrib/pg_stat_statements/expected/wal.out @@ -18,7 +18,7 @@ FROM pg_stat_statements ORDER BY query COLLATE "C"; DELETE FROM pgss_wal_tab WHERE a > $1 | 1 | 1 | t | t | t INSERT INTO pgss_wal_tab VALUES(generate_series($1, $2), $3) | 1 | 10 | t | t | t SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1 | 1 | f | f | f - SET pg_stat_statements.track_utility = FALSE | 1 | 0 | f | f | t + SET pg_stat_statements.track_utility = $1 | 1 | 0 | f | f | t UPDATE pgss_wal_tab SET b = $1 WHERE a > $2 | 1 | 3 | t | t | t (5 rows) diff --git a/contrib/pg_stat_statements/meson.build b/contrib/pg_stat_statements/meson.build index 5cf926d1f85b6..01a6cbdcf6139 100644 --- a/contrib/pg_stat_statements/meson.build +++ b/contrib/pg_stat_statements/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_stat_statements_sources = files( 'pg_stat_statements.c', @@ -21,6 +21,7 @@ contrib_targets += pg_stat_statements install_data( 'pg_stat_statements.control', 'pg_stat_statements--1.4.sql', + 'pg_stat_statements--1.11--1.12.sql', 'pg_stat_statements--1.10--1.11.sql', 'pg_stat_statements--1.9--1.10.sql', 'pg_stat_statements--1.8--1.9.sql', @@ -51,8 +52,11 @@ tests += { 'wal', 'entry_timestamp', 'privileges', + 'extended', + 'parallel', 'cleanup', 'oldextversions', + 'squashing', ], 'regress_args': ['--temp-config', files('pg_stat_statements.conf')], # Disabled because these tests require diff --git a/contrib/pg_stat_statements/pg_stat_statements--1.11--1.12.sql b/contrib/pg_stat_statements/pg_stat_statements--1.11--1.12.sql new file mode 100644 index 0000000000000..4343d83f0b8cb --- /dev/null +++ b/contrib/pg_stat_statements/pg_stat_statements--1.11--1.12.sql @@ -0,0 +1,76 @@ +/* contrib/pg_stat_statements/pg_stat_statements--1.11--1.12.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_stat_statements UPDATE TO '1.12'" to load this file. \quit + +/* First we have to remove them from the extension */ +ALTER EXTENSION pg_stat_statements DROP VIEW pg_stat_statements; +ALTER EXTENSION pg_stat_statements DROP FUNCTION pg_stat_statements(boolean); + +/* Then we can drop them */ +DROP VIEW pg_stat_statements; +DROP FUNCTION pg_stat_statements(boolean); + +/* Now redefine */ +CREATE FUNCTION pg_stat_statements(IN showtext boolean, + OUT userid oid, + OUT dbid oid, + OUT toplevel bool, + OUT queryid bigint, + OUT query text, + OUT plans int8, + OUT total_plan_time float8, + OUT min_plan_time float8, + OUT max_plan_time float8, + OUT mean_plan_time float8, + OUT stddev_plan_time float8, + OUT calls int8, + OUT total_exec_time float8, + OUT min_exec_time float8, + OUT max_exec_time float8, + OUT mean_exec_time float8, + OUT stddev_exec_time float8, + OUT rows int8, + OUT shared_blks_hit int8, + OUT shared_blks_read int8, + OUT shared_blks_dirtied int8, + OUT shared_blks_written int8, + OUT local_blks_hit int8, + OUT local_blks_read int8, + OUT local_blks_dirtied int8, + OUT local_blks_written int8, + OUT temp_blks_read int8, + OUT temp_blks_written int8, + OUT shared_blk_read_time float8, + OUT shared_blk_write_time float8, + OUT local_blk_read_time float8, + OUT local_blk_write_time float8, + OUT temp_blk_read_time float8, + OUT temp_blk_write_time float8, + OUT wal_records int8, + OUT wal_fpi int8, + OUT wal_bytes numeric, + OUT wal_buffers_full int8, + OUT jit_functions int8, + OUT jit_generation_time float8, + OUT jit_inlining_count int8, + OUT jit_inlining_time float8, + OUT jit_optimization_count int8, + OUT jit_optimization_time float8, + OUT jit_emission_count int8, + OUT jit_emission_time float8, + OUT jit_deform_count int8, + OUT jit_deform_time float8, + OUT parallel_workers_to_launch int8, + OUT parallel_workers_launched int8, + OUT stats_since timestamp with time zone, + OUT minmax_stats_since timestamp with time zone +) +RETURNS SETOF record +AS 'MODULE_PATHNAME', 'pg_stat_statements_1_12' +LANGUAGE C STRICT VOLATILE PARALLEL SAFE; + +CREATE VIEW pg_stat_statements AS + SELECT * FROM pg_stat_statements(true); + +GRANT SELECT ON pg_stat_statements TO PUBLIC; diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index d4197ae0f7ebe..ecc7f2fb2663f 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -34,7 +34,7 @@ * in the file to be read or written while holding only shared lock. * * - * Copyright (c) 2008-2024, PostgreSQL Global Development Group + * Copyright (c) 2008-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pg_stat_statements/pg_stat_statements.c @@ -49,7 +49,6 @@ #include "access/parallel.h" #include "catalog/pg_authid.h" -#include "common/hashfn.h" #include "common/int.h" #include "executor/instrument.h" #include "funcapi.h" @@ -59,9 +58,7 @@ #include "nodes/queryjumble.h" #include "optimizer/planner.h" #include "parser/analyze.h" -#include "parser/parsetree.h" #include "parser/scanner.h" -#include "parser/scansup.h" #include "pgstat.h" #include "storage/fd.h" #include "storage/ipc.h" @@ -74,7 +71,10 @@ #include "utils/memutils.h" #include "utils/timestamp.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_stat_statements", + .version = PG_VERSION +); /* Location of permanent stats file (valid when database is shut down) */ #define PGSS_DUMP_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "/pg_stat_statements.stat" @@ -113,6 +113,7 @@ typedef enum pgssVersion PGSS_V1_9, PGSS_V1_10, PGSS_V1_11, + PGSS_V1_12, } pgssVersion; typedef enum pgssStoreKind @@ -126,10 +127,10 @@ typedef enum pgssStoreKind */ PGSS_PLAN = 0, PGSS_EXEC, - - PGSS_NUMKIND /* Must be last value of this enum */ } pgssStoreKind; +#define PGSS_NUMKIND (PGSS_EXEC + 1) + /* * Hashtable key that defines the identity of a hashtable entry. We separate * queries by user and by database even if they are otherwise identical. @@ -143,7 +144,7 @@ typedef struct pgssHashKey { Oid userid; /* user OID */ Oid dbid; /* database OID */ - uint64 queryid; /* query identifier */ + int64 queryid; /* query identifier */ bool toplevel; /* query executed at top level */ } pgssHashKey; @@ -189,6 +190,7 @@ typedef struct Counters int64 wal_records; /* # of WAL records generated */ int64 wal_fpi; /* # of WAL full page images generated */ uint64 wal_bytes; /* total amount of WAL generated in bytes */ + int64 wal_buffers_full; /* # of times the WAL buffers became full */ int64 jit_functions; /* total number of JIT functions emitted */ double jit_generation_time; /* total time to generate jit code */ int64 jit_inlining_count; /* number of times inlining time has been @@ -204,6 +206,10 @@ typedef struct Counters int64 jit_emission_count; /* number of times emission time has been * > 0 */ double jit_emission_time; /* total time to emit jit code */ + int64 parallel_workers_to_launch; /* # of parallel workers planned + * to be launched */ + int64 parallel_workers_launched; /* # of parallel workers actually + * launched */ } Counters; /* @@ -254,7 +260,7 @@ typedef struct pgssSharedState /* Current nesting depth of planner/ExecutorRun/ProcessUtility calls */ static int nesting_level = 0; -/* Saved hook values in case of unload */ +/* Saved hook values */ static shmem_request_hook_type prev_shmem_request_hook = NULL; static shmem_startup_hook_type prev_shmem_startup_hook = NULL; static post_parse_analyze_hook_type prev_post_parse_analyze_hook = NULL; @@ -293,7 +299,6 @@ static bool pgss_track_planning = false; /* whether to track planning * duration */ static bool pgss_save = true; /* whether to save stats across shutdown */ - #define pgss_enabled(level) \ (!IsParallelWorker() && \ (pgss_track == PGSS_TRACK_ALL || \ @@ -301,10 +306,9 @@ static bool pgss_save = true; /* whether to save stats across shutdown */ #define record_gc_qtexts() \ do { \ - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; \ - SpinLockAcquire(&s->mutex); \ - s->gc_count++; \ - SpinLockRelease(&s->mutex); \ + SpinLockAcquire(&pgss->mutex); \ + pgss->gc_count++; \ + SpinLockRelease(&pgss->mutex); \ } while(0) /*---- Function declarations ----*/ @@ -318,6 +322,7 @@ PG_FUNCTION_INFO_V1(pg_stat_statements_1_8); PG_FUNCTION_INFO_V1(pg_stat_statements_1_9); PG_FUNCTION_INFO_V1(pg_stat_statements_1_10); PG_FUNCTION_INFO_V1(pg_stat_statements_1_11); +PG_FUNCTION_INFO_V1(pg_stat_statements_1_12); PG_FUNCTION_INFO_V1(pg_stat_statements); PG_FUNCTION_INFO_V1(pg_stat_statements_info); @@ -333,7 +338,7 @@ static PlannedStmt *pgss_planner(Query *parse, static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags); static void pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, - uint64 count, bool execute_once); + uint64 count); static void pgss_ExecutorFinish(QueryDesc *queryDesc); static void pgss_ExecutorEnd(QueryDesc *queryDesc); static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, @@ -341,14 +346,16 @@ static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc); -static void pgss_store(const char *query, uint64 queryId, +static void pgss_store(const char *query, int64 queryId, int query_location, int query_len, pgssStoreKind kind, double total_time, uint64 rows, const BufferUsage *bufusage, const WalUsage *walusage, const struct JitInstrumentation *jitusage, - JumbleState *jstate); + JumbleState *jstate, + int parallel_workers_to_launch, + int parallel_workers_launched); static void pg_stat_statements_internal(FunctionCallInfo fcinfo, pgssVersion api_version, bool showtext); @@ -363,7 +370,7 @@ static char *qtext_fetch(Size query_offset, int query_len, char *buffer, Size buffer_size); static bool need_gc_qtexts(void); static void gc_qtexts(void); -static TimestampTz entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only); +static TimestampTz entry_reset(Oid userid, Oid dbid, int64 queryid, bool minmax_only); static char *generate_normalized_query(JumbleState *jstate, const char *query, int query_loc, int *query_len_p); static void fill_in_constant_lengths(JumbleState *jstate, const char *query, @@ -845,7 +852,7 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate) { if (pgss_track_utility && IsA(query->utilityStmt, ExecuteStmt)) { - query->queryId = UINT64CONST(0); + query->queryId = INT64CONST(0); return; } } @@ -868,7 +875,9 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate) NULL, NULL, NULL, - jstate); + jstate, + 0, + 0); } /* @@ -887,17 +896,10 @@ pgss_planner(Query *parse, * We can't process the query if no query_string is provided, as * pgss_store needs it. We also ignore query without queryid, as it would * be treated as a utility statement, which may not be the case. - * - * Note that planner_hook can be called from the planner itself, so we - * have a specific nesting level for the planner. However, utility - * commands containing optimizable statements can also call the planner, - * same for regular DML (for instance for underlying foreign key queries). - * So testing the planner nesting level only is not enough to detect real - * top level planner call. */ if (pgss_enabled(nesting_level) && pgss_track_planning && query_string - && parse->queryId != UINT64CONST(0)) + && parse->queryId != INT64CONST(0)) { instr_time start; instr_time duration; @@ -953,7 +955,9 @@ pgss_planner(Query *parse, &bufusage, &walusage, NULL, - NULL); + NULL, + 0, + 0); } else { @@ -998,7 +1002,7 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) * counting of optimizable statements that are directly contained in * utility statements. */ - if (pgss_enabled(nesting_level) && queryDesc->plannedstmt->queryId != UINT64CONST(0)) + if (pgss_enabled(nesting_level) && queryDesc->plannedstmt->queryId != INT64CONST(0)) { /* * Set up to track total elapsed time in ExecutorRun. Make sure the @@ -1020,16 +1024,15 @@ pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) * ExecutorRun hook: all we need do is track nesting depth */ static void -pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, - bool execute_once) +pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count) { nesting_level++; PG_TRY(); { if (prev_ExecutorRun) - prev_ExecutorRun(queryDesc, direction, count, execute_once); + prev_ExecutorRun(queryDesc, direction, count); else - standard_ExecutorRun(queryDesc, direction, count, execute_once); + standard_ExecutorRun(queryDesc, direction, count); } PG_FINALLY(); { @@ -1065,9 +1068,9 @@ pgss_ExecutorFinish(QueryDesc *queryDesc) static void pgss_ExecutorEnd(QueryDesc *queryDesc) { - uint64 queryId = queryDesc->plannedstmt->queryId; + int64 queryId = queryDesc->plannedstmt->queryId; - if (queryId != UINT64CONST(0) && queryDesc->totaltime && + if (queryId != INT64CONST(0) && queryDesc->totaltime && pgss_enabled(nesting_level)) { /* @@ -1086,7 +1089,9 @@ pgss_ExecutorEnd(QueryDesc *queryDesc) &queryDesc->totaltime->bufusage, &queryDesc->totaltime->walusage, queryDesc->estate->es_jit ? &queryDesc->estate->es_jit->instr : NULL, - NULL); + NULL, + queryDesc->estate->es_parallel_workers_to_launch, + queryDesc->estate->es_parallel_workers_launched); } if (prev_ExecutorEnd) @@ -1106,7 +1111,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, DestReceiver *dest, QueryCompletion *qc) { Node *parsetree = pstmt->utilityStmt; - uint64 saved_queryId = pstmt->queryId; + int64 saved_queryId = pstmt->queryId; int saved_stmt_location = pstmt->stmt_location; int saved_stmt_len = pstmt->stmt_len; bool enabled = pgss_track_utility && pgss_enabled(nesting_level); @@ -1126,7 +1131,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, * only. */ if (enabled) - pstmt->queryId = UINT64CONST(0); + pstmt->queryId = INT64CONST(0); /* * If it's an EXECUTE statement, we don't track it and don't increment the @@ -1217,7 +1222,9 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, &bufusage, &walusage, NULL, - NULL); + NULL, + 0, + 0); } else { @@ -1271,14 +1278,16 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, * for the arrays in the Counters field. */ static void -pgss_store(const char *query, uint64 queryId, +pgss_store(const char *query, int64 queryId, int query_location, int query_len, pgssStoreKind kind, double total_time, uint64 rows, const BufferUsage *bufusage, const WalUsage *walusage, const struct JitInstrumentation *jitusage, - JumbleState *jstate) + JumbleState *jstate, + int parallel_workers_to_launch, + int parallel_workers_launched) { pgssHashKey key; pgssEntry *entry; @@ -1295,7 +1304,7 @@ pgss_store(const char *query, uint64 queryId, * Nothing to do if compute_query_id isn't enabled and no other module * computed a query identifier. */ - if (queryId == UINT64CONST(0)) + if (queryId == INT64CONST(0)) return; /* @@ -1386,28 +1395,26 @@ pgss_store(const char *query, uint64 queryId, /* Increment the counts, except when jstate is not NULL */ if (!jstate) { + Assert(kind == PGSS_PLAN || kind == PGSS_EXEC); + /* * Grab the spinlock while updating the counters (see comment about * locking rules at the head of the file) */ - volatile pgssEntry *e = (volatile pgssEntry *) entry; - - Assert(kind == PGSS_PLAN || kind == PGSS_EXEC); - - SpinLockAcquire(&e->mutex); + SpinLockAcquire(&entry->mutex); /* "Unstick" entry if it was previously sticky */ - if (IS_STICKY(e->counters)) - e->counters.usage = USAGE_INIT; + if (IS_STICKY(entry->counters)) + entry->counters.usage = USAGE_INIT; - e->counters.calls[kind] += 1; - e->counters.total_time[kind] += total_time; + entry->counters.calls[kind] += 1; + entry->counters.total_time[kind] += total_time; - if (e->counters.calls[kind] == 1) + if (entry->counters.calls[kind] == 1) { - e->counters.min_time[kind] = total_time; - e->counters.max_time[kind] = total_time; - e->counters.mean_time[kind] = total_time; + entry->counters.min_time[kind] = total_time; + entry->counters.max_time[kind] = total_time; + entry->counters.mean_time[kind] = total_time; } else { @@ -1415,75 +1422,80 @@ pgss_store(const char *query, uint64 queryId, * Welford's method for accurately computing variance. See * */ - double old_mean = e->counters.mean_time[kind]; + double old_mean = entry->counters.mean_time[kind]; - e->counters.mean_time[kind] += - (total_time - old_mean) / e->counters.calls[kind]; - e->counters.sum_var_time[kind] += - (total_time - old_mean) * (total_time - e->counters.mean_time[kind]); + entry->counters.mean_time[kind] += + (total_time - old_mean) / entry->counters.calls[kind]; + entry->counters.sum_var_time[kind] += + (total_time - old_mean) * (total_time - entry->counters.mean_time[kind]); /* * Calculate min and max time. min = 0 and max = 0 means that the * min/max statistics were reset */ - if (e->counters.min_time[kind] == 0 - && e->counters.max_time[kind] == 0) + if (entry->counters.min_time[kind] == 0 + && entry->counters.max_time[kind] == 0) { - e->counters.min_time[kind] = total_time; - e->counters.max_time[kind] = total_time; + entry->counters.min_time[kind] = total_time; + entry->counters.max_time[kind] = total_time; } else { - if (e->counters.min_time[kind] > total_time) - e->counters.min_time[kind] = total_time; - if (e->counters.max_time[kind] < total_time) - e->counters.max_time[kind] = total_time; + if (entry->counters.min_time[kind] > total_time) + entry->counters.min_time[kind] = total_time; + if (entry->counters.max_time[kind] < total_time) + entry->counters.max_time[kind] = total_time; } } - e->counters.rows += rows; - e->counters.shared_blks_hit += bufusage->shared_blks_hit; - e->counters.shared_blks_read += bufusage->shared_blks_read; - e->counters.shared_blks_dirtied += bufusage->shared_blks_dirtied; - e->counters.shared_blks_written += bufusage->shared_blks_written; - e->counters.local_blks_hit += bufusage->local_blks_hit; - e->counters.local_blks_read += bufusage->local_blks_read; - e->counters.local_blks_dirtied += bufusage->local_blks_dirtied; - e->counters.local_blks_written += bufusage->local_blks_written; - e->counters.temp_blks_read += bufusage->temp_blks_read; - e->counters.temp_blks_written += bufusage->temp_blks_written; - e->counters.shared_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_read_time); - e->counters.shared_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_write_time); - e->counters.local_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_read_time); - e->counters.local_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_write_time); - e->counters.temp_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_read_time); - e->counters.temp_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_write_time); - e->counters.usage += USAGE_EXEC(total_time); - e->counters.wal_records += walusage->wal_records; - e->counters.wal_fpi += walusage->wal_fpi; - e->counters.wal_bytes += walusage->wal_bytes; + entry->counters.rows += rows; + entry->counters.shared_blks_hit += bufusage->shared_blks_hit; + entry->counters.shared_blks_read += bufusage->shared_blks_read; + entry->counters.shared_blks_dirtied += bufusage->shared_blks_dirtied; + entry->counters.shared_blks_written += bufusage->shared_blks_written; + entry->counters.local_blks_hit += bufusage->local_blks_hit; + entry->counters.local_blks_read += bufusage->local_blks_read; + entry->counters.local_blks_dirtied += bufusage->local_blks_dirtied; + entry->counters.local_blks_written += bufusage->local_blks_written; + entry->counters.temp_blks_read += bufusage->temp_blks_read; + entry->counters.temp_blks_written += bufusage->temp_blks_written; + entry->counters.shared_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_read_time); + entry->counters.shared_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->shared_blk_write_time); + entry->counters.local_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_read_time); + entry->counters.local_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->local_blk_write_time); + entry->counters.temp_blk_read_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_read_time); + entry->counters.temp_blk_write_time += INSTR_TIME_GET_MILLISEC(bufusage->temp_blk_write_time); + entry->counters.usage += USAGE_EXEC(total_time); + entry->counters.wal_records += walusage->wal_records; + entry->counters.wal_fpi += walusage->wal_fpi; + entry->counters.wal_bytes += walusage->wal_bytes; + entry->counters.wal_buffers_full += walusage->wal_buffers_full; if (jitusage) { - e->counters.jit_functions += jitusage->created_functions; - e->counters.jit_generation_time += INSTR_TIME_GET_MILLISEC(jitusage->generation_counter); + entry->counters.jit_functions += jitusage->created_functions; + entry->counters.jit_generation_time += INSTR_TIME_GET_MILLISEC(jitusage->generation_counter); if (INSTR_TIME_GET_MILLISEC(jitusage->deform_counter)) - e->counters.jit_deform_count++; - e->counters.jit_deform_time += INSTR_TIME_GET_MILLISEC(jitusage->deform_counter); + entry->counters.jit_deform_count++; + entry->counters.jit_deform_time += INSTR_TIME_GET_MILLISEC(jitusage->deform_counter); if (INSTR_TIME_GET_MILLISEC(jitusage->inlining_counter)) - e->counters.jit_inlining_count++; - e->counters.jit_inlining_time += INSTR_TIME_GET_MILLISEC(jitusage->inlining_counter); + entry->counters.jit_inlining_count++; + entry->counters.jit_inlining_time += INSTR_TIME_GET_MILLISEC(jitusage->inlining_counter); if (INSTR_TIME_GET_MILLISEC(jitusage->optimization_counter)) - e->counters.jit_optimization_count++; - e->counters.jit_optimization_time += INSTR_TIME_GET_MILLISEC(jitusage->optimization_counter); + entry->counters.jit_optimization_count++; + entry->counters.jit_optimization_time += INSTR_TIME_GET_MILLISEC(jitusage->optimization_counter); if (INSTR_TIME_GET_MILLISEC(jitusage->emission_counter)) - e->counters.jit_emission_count++; - e->counters.jit_emission_time += INSTR_TIME_GET_MILLISEC(jitusage->emission_counter); + entry->counters.jit_emission_count++; + entry->counters.jit_emission_time += INSTR_TIME_GET_MILLISEC(jitusage->emission_counter); } - SpinLockRelease(&e->mutex); + /* parallel worker counters */ + entry->counters.parallel_workers_to_launch += parallel_workers_to_launch; + entry->counters.parallel_workers_launched += parallel_workers_launched; + + SpinLockRelease(&entry->mutex); } done: @@ -1502,11 +1514,11 @@ pg_stat_statements_reset_1_7(PG_FUNCTION_ARGS) { Oid userid; Oid dbid; - uint64 queryid; + int64 queryid; userid = PG_GETARG_OID(0); dbid = PG_GETARG_OID(1); - queryid = (uint64) PG_GETARG_INT64(2); + queryid = PG_GETARG_INT64(2); entry_reset(userid, dbid, queryid, false); @@ -1518,12 +1530,12 @@ pg_stat_statements_reset_1_11(PG_FUNCTION_ARGS) { Oid userid; Oid dbid; - uint64 queryid; + int64 queryid; bool minmax_only; userid = PG_GETARG_OID(0); dbid = PG_GETARG_OID(1); - queryid = (uint64) PG_GETARG_INT64(2); + queryid = PG_GETARG_INT64(2); minmax_only = PG_GETARG_BOOL(3); PG_RETURN_TIMESTAMPTZ(entry_reset(userid, dbid, queryid, minmax_only)); @@ -1549,7 +1561,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS) #define PG_STAT_STATEMENTS_COLS_V1_9 33 #define PG_STAT_STATEMENTS_COLS_V1_10 43 #define PG_STAT_STATEMENTS_COLS_V1_11 49 -#define PG_STAT_STATEMENTS_COLS 49 /* maximum of above */ +#define PG_STAT_STATEMENTS_COLS_V1_12 52 +#define PG_STAT_STATEMENTS_COLS 52 /* maximum of above */ /* * Retrieve statement statistics. @@ -1561,6 +1574,16 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS) * expected API version is identified by embedding it in the C name of the * function. Unfortunately we weren't bright enough to do that for 1.1. */ +Datum +pg_stat_statements_1_12(PG_FUNCTION_ARGS) +{ + bool showtext = PG_GETARG_BOOL(0); + + pg_stat_statements_internal(fcinfo, PGSS_V1_12, showtext); + + return (Datum) 0; +} + Datum pg_stat_statements_1_11(PG_FUNCTION_ARGS) { @@ -1705,6 +1728,10 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, if (api_version != PGSS_V1_11) elog(ERROR, "incorrect number of output arguments"); break; + case PG_STAT_STATEMENTS_COLS_V1_12: + if (api_version != PGSS_V1_12) + elog(ERROR, "incorrect number of output arguments"); + break; default: elog(ERROR, "incorrect number of output arguments"); } @@ -1724,15 +1751,11 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, int n_writers; /* Take the mutex so we can examine variables */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - extent = s->extent; - n_writers = s->n_writers; - gc_count = s->gc_count; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + extent = pgss->extent; + n_writers = pgss->n_writers; + gc_count = pgss->gc_count; + SpinLockRelease(&pgss->mutex); /* No point in loading file now if there are active writers */ if (n_writers == 0) @@ -1847,15 +1870,16 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, } /* copy counters to a local variable to keep locking time short */ - { - volatile pgssEntry *e = (volatile pgssEntry *) entry; + SpinLockAcquire(&entry->mutex); + tmp = entry->counters; + SpinLockRelease(&entry->mutex); - SpinLockAcquire(&e->mutex); - tmp = e->counters; - stats_since = e->stats_since; - minmax_stats_since = e->minmax_stats_since; - SpinLockRelease(&e->mutex); - } + /* + * The spinlock is not required when reading these two as they are + * always updated when holding pgss->lock exclusively. + */ + stats_since = entry->stats_since; + minmax_stats_since = entry->minmax_stats_since; /* Skip entry if unexecuted (ie, it's a pending "sticky" entry) */ if (IS_STICKY(tmp)) @@ -1935,6 +1959,10 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, Int32GetDatum(-1)); values[i++] = wal_bytes; } + if (api_version >= PGSS_V1_12) + { + values[i++] = Int64GetDatumFast(tmp.wal_buffers_full); + } if (api_version >= PGSS_V1_10) { values[i++] = Int64GetDatumFast(tmp.jit_functions); @@ -1950,6 +1978,14 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, { values[i++] = Int64GetDatumFast(tmp.jit_deform_count); values[i++] = Float8GetDatumFast(tmp.jit_deform_time); + } + if (api_version >= PGSS_V1_12) + { + values[i++] = Int64GetDatumFast(tmp.parallel_workers_to_launch); + values[i++] = Int64GetDatumFast(tmp.parallel_workers_launched); + } + if (api_version >= PGSS_V1_11) + { values[i++] = TimestampTzGetDatum(stats_since); values[i++] = TimestampTzGetDatum(minmax_stats_since); } @@ -1962,6 +1998,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo, api_version == PGSS_V1_9 ? PG_STAT_STATEMENTS_COLS_V1_9 : api_version == PGSS_V1_10 ? PG_STAT_STATEMENTS_COLS_V1_10 : api_version == PGSS_V1_11 ? PG_STAT_STATEMENTS_COLS_V1_11 : + api_version == PGSS_V1_12 ? PG_STAT_STATEMENTS_COLS_V1_12 : -1 /* fail if you forget to update this assert */ )); tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); @@ -1996,13 +2033,9 @@ pg_stat_statements_info(PG_FUNCTION_ARGS) elog(ERROR, "return type must be a row type"); /* Read global statistics for pg_stat_statements */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - stats = s->stats; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + stats = pgss->stats; + SpinLockRelease(&pgss->mutex); values[0] = Int64GetDatum(stats.dealloc); values[1] = TimestampTzGetDatum(stats.stats_reset); @@ -2169,13 +2202,9 @@ entry_dealloc(void) pfree(entries); /* Increment the number of times entries are deallocated */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - s->stats.dealloc += 1; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + pgss->stats.dealloc += 1; + SpinLockRelease(&pgss->mutex); } /* @@ -2205,17 +2234,13 @@ qtext_store(const char *query, int query_len, * We use a spinlock to protect extent/n_writers/gc_count, so that * multiple processes may execute this function concurrently. */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - off = s->extent; - s->extent += query_len + 1; - s->n_writers++; - if (gc_count) - *gc_count = s->gc_count; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + off = pgss->extent; + pgss->extent += query_len + 1; + pgss->n_writers++; + if (gc_count) + *gc_count = pgss->gc_count; + SpinLockRelease(&pgss->mutex); *query_offset = off; @@ -2244,13 +2269,9 @@ qtext_store(const char *query, int query_len, CloseTransientFile(fd); /* Mark our write complete */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - s->n_writers--; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + pgss->n_writers--; + SpinLockRelease(&pgss->mutex); return true; @@ -2264,13 +2285,9 @@ qtext_store(const char *query, int query_len, CloseTransientFile(fd); /* Mark our write complete */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - s->n_writers--; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + pgss->n_writers--; + SpinLockRelease(&pgss->mutex); return false; } @@ -2408,13 +2425,9 @@ need_gc_qtexts(void) Size extent; /* Read shared extent pointer */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - extent = s->extent; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + extent = pgss->extent; + SpinLockRelease(&pgss->mutex); /* * Don't proceed if file does not exceed 512 bytes per possible entry. @@ -2658,7 +2671,7 @@ if (e) { \ * Reset entries corresponding to parameters passed. */ static TimestampTz -entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only) +entry_reset(Oid userid, Oid dbid, int64 queryid, bool minmax_only) { HASH_SEQ_STATUS hash_seq; pgssEntry *entry; @@ -2678,7 +2691,7 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only) stats_reset = GetCurrentTimestamp(); - if (userid != 0 && dbid != 0 && queryid != UINT64CONST(0)) + if (userid != 0 && dbid != 0 && queryid != INT64CONST(0)) { /* If all the parameters are available, use the fast path. */ memset(&key, 0, sizeof(pgssHashKey)); @@ -2701,7 +2714,7 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only) SINGLE_ENTRY_RESET(entry); } - else if (userid != 0 || dbid != 0 || queryid != UINT64CONST(0)) + else if (userid != 0 || dbid != 0 || queryid != INT64CONST(0)) { /* Reset entries corresponding to valid parameters. */ hash_seq_init(&hash_seq, pgss_hash); @@ -2733,14 +2746,10 @@ entry_reset(Oid userid, Oid dbid, uint64 queryid, bool minmax_only) * Reset global statistics for pg_stat_statements since all entries are * removed. */ - { - volatile pgssSharedState *s = (volatile pgssSharedState *) pgss; - - SpinLockAcquire(&s->mutex); - s->stats.dealloc = 0; - s->stats.stats_reset = stats_reset; - SpinLockRelease(&s->mutex); - } + SpinLockAcquire(&pgss->mutex); + pgss->stats.dealloc = 0; + pgss->stats.stats_reset = stats_reset; + SpinLockRelease(&pgss->mutex); /* * Write new empty query file, perhaps even creating a new one to recover @@ -2801,13 +2810,13 @@ generate_normalized_query(JumbleState *jstate, const char *query, { char *norm_query; int query_len = *query_len_p; - int i, - norm_query_buflen, /* Space allowed for norm_query */ + int norm_query_buflen, /* Space allowed for norm_query */ len_to_wrt, /* Length (in bytes) to write */ quer_loc = 0, /* Source query byte location */ n_quer_loc = 0, /* Normalized query byte location */ last_off = 0, /* Offset from start for previous tok */ last_tok_len = 0; /* Length (in bytes) of that tok */ + int num_constants_replaced = 0; /* * Get constants' lengths (core system only gives us locations). Note @@ -2827,12 +2836,13 @@ generate_normalized_query(JumbleState *jstate, const char *query, /* Allocate result buffer */ norm_query = palloc(norm_query_buflen + 1); - for (i = 0; i < jstate->clocations_count; i++) + for (int i = 0; i < jstate->clocations_count; i++) { int off, /* Offset from start for cur tok */ tok_len; /* Length (in bytes) of that tok */ off = jstate->clocations[i].location; + /* Adjust recorded location if we're dealing with partial string */ off -= query_loc; @@ -2844,15 +2854,21 @@ generate_normalized_query(JumbleState *jstate, const char *query, /* Copy next chunk (what precedes the next constant) */ len_to_wrt = off - last_off; len_to_wrt -= last_tok_len; - Assert(len_to_wrt >= 0); memcpy(norm_query + n_quer_loc, query + quer_loc, len_to_wrt); n_quer_loc += len_to_wrt; - /* And insert a param symbol in place of the constant token */ - n_quer_loc += sprintf(norm_query + n_quer_loc, "$%d", - i + 1 + jstate->highest_extern_param_id); + /* + * And insert a param symbol in place of the constant token; and, if + * we have a squashable list, insert a placeholder comment starting + * from the list's second value. + */ + n_quer_loc += sprintf(norm_query + n_quer_loc, "$%d%s", + num_constants_replaced + 1 + jstate->highest_extern_param_id, + jstate->clocations[i].squashed ? " /*, ... */" : ""); + num_constants_replaced++; + /* move forward */ quer_loc = off + tok_len; last_off = off; last_tok_len = tok_len; @@ -2943,6 +2959,9 @@ fill_in_constant_lengths(JumbleState *jstate, const char *query, Assert(loc >= 0); + if (locs[i].squashed) + continue; /* squashable list, ignore */ + if (loc <= last_loc) continue; /* Duplicate constant, ignore */ diff --git a/contrib/pg_stat_statements/pg_stat_statements.control b/contrib/pg_stat_statements/pg_stat_statements.control index 8a76106ec6763..d45ebc12e3605 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.control +++ b/contrib/pg_stat_statements/pg_stat_statements.control @@ -1,5 +1,5 @@ # pg_stat_statements extension comment = 'track planning and execution statistics of all SQL statements executed' -default_version = '1.11' +default_version = '1.12' module_pathname = '$libdir/pg_stat_statements' relocatable = true diff --git a/contrib/pg_stat_statements/sql/extended.sql b/contrib/pg_stat_statements/sql/extended.sql new file mode 100644 index 0000000000000..a366658a53a72 --- /dev/null +++ b/contrib/pg_stat_statements/sql/extended.sql @@ -0,0 +1,37 @@ +-- Tests with extended query protocol + +SET pg_stat_statements.track_utility = FALSE; + +-- This test checks that an execute message sets a query ID. +SELECT query_id IS NOT NULL AS query_id_set + FROM pg_stat_activity WHERE pid = pg_backend_pid() \bind \g + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT $1 \parse stmt1 +SELECT $1, $2 \parse stmt2 +SELECT $1, $2, $3 \parse stmt3 +SELECT $1 \bind 'unnamed_val1' \g +\bind_named stmt1 'stmt1_val1' \g +\bind_named stmt2 'stmt2_val1' 'stmt2_val2' \g +\bind_named stmt3 'stmt3_val1' 'stmt3_val2' 'stmt3_val3' \g +\bind_named stmt3 'stmt3_val4' 'stmt3_val5' 'stmt3_val6' \g +\bind_named stmt2 'stmt2_val3' 'stmt2_val4' \g +\bind_named stmt1 'stmt1_val1' \g + +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Various parameter numbering patterns +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- Unique query IDs with parameter numbers switched. +SELECT WHERE ($1::int, 7) IN ((8, $2::int), ($3::int, 9)) \bind '1' '2' '3' \g +SELECT WHERE ($2::int, 10) IN ((11, $3::int), ($1::int, 12)) \bind '1' '2' '3' \g +SELECT WHERE $1::int IN ($2::int, $3::int) \bind '1' '2' '3' \g +SELECT WHERE $2::int IN ($3::int, $1::int) \bind '1' '2' '3' \g +SELECT WHERE $3::int IN ($1::int, $2::int) \bind '1' '2' '3' \g +-- Two groups of two queries with the same query ID. +SELECT WHERE '1'::int IN ($1::int, '2'::int) \bind '1' \g +SELECT WHERE '4'::int IN ($1::int, '5'::int) \bind '2' \g +SELECT WHERE $2::int IN ($1::int, '1'::int) \bind '1' '2' \g +SELECT WHERE $2::int IN ($1::int, '2'::int) \bind '3' '4' \g + +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; diff --git a/contrib/pg_stat_statements/sql/level_tracking.sql b/contrib/pg_stat_statements/sql/level_tracking.sql index 65a17147a5a96..86f007e85524a 100644 --- a/contrib/pg_stat_statements/sql/level_tracking.sql +++ b/contrib/pg_stat_statements/sql/level_tracking.sql @@ -55,6 +55,252 @@ CALL proc_with_utility_stmt(); SELECT toplevel, calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", toplevel; +-- EXPLAIN - all-level tracking. +CREATE TABLE test_table (x int); +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) SELECT 1; +EXPLAIN (COSTS OFF) (SELECT 1, 2); +EXPLAIN (COSTS OFF) TABLE stats_track_tab; +EXPLAIN (COSTS OFF) (TABLE test_table); +EXPLAIN (COSTS OFF) VALUES (1); +EXPLAIN (COSTS OFF) (VALUES (1, 2)); +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1; +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1)); +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); +EXPLAIN (COSTS OFF) SELECT 1 UNION SELECT 2; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) SELECT 1; +EXPLAIN (COSTS OFF) (SELECT 1, 2); +EXPLAIN (COSTS OFF) TABLE stats_track_tab; +EXPLAIN (COSTS OFF) (TABLE test_table); +EXPLAIN (COSTS OFF) VALUES (1); +EXPLAIN (COSTS OFF) (VALUES (1, 2)); +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1; +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab; +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1)); +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); +EXPLAIN (COSTS OFF) SELECT 1 UNION SELECT 2; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN - all-level tracking with multi-statement strings. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- SELECT queries +EXPLAIN (COSTS OFF) SELECT 1\; EXPLAIN (COSTS OFF) SELECT 1, 2; +EXPLAIN (COSTS OFF) (SELECT 1, 2, 3)\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3, 4); +EXPLAIN (COSTS OFF) SELECT 1, 2 UNION SELECT 3, 4\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3) UNION SELECT 3, 4, 5; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- Most DMLs +EXPLAIN (COSTS OFF) TABLE stats_track_tab\; EXPLAIN (COSTS OFF) (TABLE test_table); +EXPLAIN (COSTS OFF) VALUES (1)\; EXPLAIN (COSTS OFF) (VALUES (1, 2)); +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1\; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1; +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab\; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = 1; +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1))\; EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES (1), (2); +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- MERGE, worth its own. +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id)\; EXPLAIN (COSTS OFF) SELECT 1, 2, 3, 4, 5; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN - top-level tracking with multi-statement strings. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) SELECT 1\; EXPLAIN (COSTS OFF) SELECT 1, 2; +EXPLAIN (COSTS OFF) (SELECT 1, 2, 3)\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3, 4); +EXPLAIN (COSTS OFF) TABLE stats_track_tab\; EXPLAIN (COSTS OFF) (TABLE test_table); +EXPLAIN (COSTS OFF) VALUES (1)\; EXPLAIN (COSTS OFF) (VALUES (1, 2)); +EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1 WHERE x = 1\; EXPLAIN (COSTS OFF) UPDATE stats_track_tab SET x = 1; +EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab\; EXPLAIN (COSTS OFF) DELETE FROM stats_track_tab WHERE x = 1; +EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1))\; EXPLAIN (COSTS OFF) INSERT INTO stats_track_tab VALUES ((1), (2)); +EXPLAIN (COSTS OFF) MERGE INTO stats_track_tab USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id)\; EXPLAIN (COSTS OFF) SELECT 1, 2, 3, 4, 5; +EXPLAIN (COSTS OFF) SELECT 1, 2 UNION SELECT 3, 4\; EXPLAIN (COSTS OFF) (SELECT 1, 2, 3) UNION SELECT 3, 4, 5; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN with CTEs - all-level tracking +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) SELECT 1; +EXPLAIN (COSTS OFF) (WITH a AS (SELECT 4) (SELECT 1, 2)); +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) UPDATE stats_track_tab SET x = 1 WHERE x = 1; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) DELETE FROM stats_track_tab; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) INSERT INTO stats_track_tab VALUES ((1)); +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); +EXPLAIN (COSTS OFF) WITH a AS (select 4) SELECT 1 UNION SELECT 2; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN with CTEs - top-level tracking +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) SELECT 1; +EXPLAIN (COSTS OFF) (WITH a AS (SELECT 4) (SELECT 1, 2)); +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) UPDATE stats_track_tab SET x = 1 WHERE x = 1; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) DELETE FROM stats_track_tab; +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) INSERT INTO stats_track_tab VALUES ((1)); +EXPLAIN (COSTS OFF) WITH a AS (SELECT 4) MERGE INTO stats_track_tab + USING (SELECT id FROM generate_series(1, 10) id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id); +EXPLAIN (COSTS OFF) WITH a AS (select 4) SELECT 1 UNION SELECT 2; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- Explain analyze, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100; +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- Explain analyze, top tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT 100; +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) + DECLARE foocur CURSOR FOR SELECT * FROM stats_track_tab; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- Create Materialized View, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +CREATE MATERIALIZED VIEW pgss_materialized_view AS + SELECT * FROM generate_series(1, 5) as id; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- CREATE MATERIALIZED VIEW, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +CREATE MATERIALIZED VIEW pgss_materialized_view_2 AS + SELECT * FROM generate_series(1, 5) as id; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- REFRESH MATERIALIZED VIEW, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +REFRESH MATERIALIZED VIEW pgss_materialized_view; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- REFRESH MATERIALIZED VIEW, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +REFRESH MATERIALIZED VIEW pgss_materialized_view; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- CREATE TABLE AS, all-level tracking. +SET pg_stat_statements.track = 'all'; +PREPARE test_prepare_pgss AS select generate_series(1, 10); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +CREATE TEMPORARY TABLE pgss_ctas_1 AS SELECT 1; +CREATE TEMPORARY TABLE pgss_ctas_2 AS EXECUTE test_prepare_pgss; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- CREATE TABLE AS, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +CREATE TEMPORARY TABLE pgss_ctas_3 AS SELECT 1; +CREATE TEMPORARY TABLE pgss_ctas_4 AS EXECUTE test_prepare_pgss; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN with CREATE TABLE AS - all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT 1; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- EXPLAIN with CREATE TABLE AS - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +EXPLAIN (COSTS OFF) CREATE TEMPORARY TABLE pgss_explain_ctas AS SELECT 1; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- DECLARE CURSOR, all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +BEGIN; +DECLARE FOOCUR CURSOR FOR SELECT * from stats_track_tab; +FETCH FORWARD 1 FROM foocur; +CLOSE foocur; +COMMIT; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- DECLARE CURSOR, top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +BEGIN; +DECLARE FOOCUR CURSOR FOR SELECT * FROM stats_track_tab; +FETCH FORWARD 1 FROM foocur; +CLOSE foocur; +COMMIT; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- COPY - all-level tracking. +SET pg_stat_statements.track = 'all'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +COPY (SELECT 1) TO stdout; +COPY (SELECT 1 UNION SELECT 2) TO stdout; +COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout; +COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout; +COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout; +COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + +-- COPY - top-level tracking. +SET pg_stat_statements.track = 'top'; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +COPY (SELECT 1) TO stdout; +COPY (SELECT 1 UNION SELECT 2) TO stdout; +COPY (MERGE INTO stats_track_tab USING (SELECT 1 id) ON x = id + WHEN MATCHED THEN UPDATE SET x = id + WHEN NOT MATCHED THEN INSERT (x) VALUES (id) RETURNING x) TO stdout; +COPY (INSERT INTO stats_track_tab (x) VALUES (1) RETURNING x) TO stdout; +COPY (UPDATE stats_track_tab SET x = 2 WHERE x = 1 RETURNING x) TO stdout; +COPY (DELETE FROM stats_track_tab WHERE x = 2 RETURNING x) TO stdout; +SELECT toplevel, calls, query FROM pg_stat_statements + ORDER BY query COLLATE "C"; + -- DO block - top-level tracking without utility. SET pg_stat_statements.track = 'top'; SET pg_stat_statements.track_utility = FALSE; @@ -88,6 +334,32 @@ END; $$; SELECT toplevel, calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", toplevel; +-- DO block --- multiple inner queries with separators +SET pg_stat_statements.track = 'all'; +SET pg_stat_statements.track_utility = TRUE; +CREATE TABLE pgss_do_util_tab_1 (a int); +CREATE TABLE pgss_do_util_tab_2 (a int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +DO $$ +DECLARE BEGIN + EXECUTE 'CREATE TABLE pgss_do_table (id INT); DROP TABLE pgss_do_table'; + EXECUTE 'SELECT a FROM pgss_do_util_tab_1; SELECT a FROM pgss_do_util_tab_2'; +END $$; +SELECT toplevel, calls, rows, query FROM pg_stat_statements + WHERE toplevel IS FALSE + ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- Note the extra semicolon at the end of the query. +DO $$ +DECLARE BEGIN + EXECUTE 'CREATE TABLE pgss_do_table (id INT); DROP TABLE pgss_do_table;'; + EXECUTE 'SELECT a FROM pgss_do_util_tab_1; SELECT a FROM pgss_do_util_tab_2;'; +END $$; +SELECT toplevel, calls, rows, query FROM pg_stat_statements + WHERE toplevel IS FALSE + ORDER BY query COLLATE "C"; +DROP TABLE pgss_do_util_tab_1, pgss_do_util_tab_2; + -- PL/pgSQL function - top-level tracking. SET pg_stat_statements.track = 'top'; SET pg_stat_statements.track_utility = FALSE; diff --git a/contrib/pg_stat_statements/sql/oldextversions.sql b/contrib/pg_stat_statements/sql/oldextversions.sql index 38d5505d0db7d..13b8ca28586d1 100644 --- a/contrib/pg_stat_statements/sql/oldextversions.sql +++ b/contrib/pg_stat_statements/sql/oldextversions.sql @@ -58,4 +58,9 @@ SELECT count(*) > 0 AS has_data FROM pg_stat_statements; SELECT pg_get_functiondef('pg_stat_statements_reset'::regproc); SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- New functions and views for pg_stat_statements in 1.12 +AlTER EXTENSION pg_stat_statements UPDATE TO '1.12'; +\d pg_stat_statements +SELECT count(*) > 0 AS has_data FROM pg_stat_statements; + DROP EXTENSION pg_stat_statements; diff --git a/contrib/pg_stat_statements/sql/parallel.sql b/contrib/pg_stat_statements/sql/parallel.sql new file mode 100644 index 0000000000000..4ce1573d132b0 --- /dev/null +++ b/contrib/pg_stat_statements/sql/parallel.sql @@ -0,0 +1,26 @@ +-- +-- Tests for parallel statistics +-- + +SET pg_stat_statements.track_utility = FALSE; + +-- encourage use of parallel plans +SET parallel_setup_cost = 0; +SET parallel_tuple_cost = 0; +SET min_parallel_table_scan_size = 0; +SET max_parallel_workers_per_gather = 2; + +CREATE TABLE pgss_parallel_tab (a int); + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +SELECT count(*) FROM pgss_parallel_tab; + +SELECT query, + parallel_workers_to_launch > 0 AS has_workers_to_launch, + parallel_workers_launched > 0 AS has_workers_launched + FROM pg_stat_statements + WHERE query ~ 'SELECT count' + ORDER BY query COLLATE "C"; + +DROP TABLE pgss_parallel_tab; diff --git a/contrib/pg_stat_statements/sql/select.sql b/contrib/pg_stat_statements/sql/select.sql index eb45cb81ad23f..11662cde08c92 100644 --- a/contrib/pg_stat_statements/sql/select.sql +++ b/contrib/pg_stat_statements/sql/select.sql @@ -12,8 +12,29 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- SELECT 1 AS "int"; +-- LIMIT and OFFSET patterns +-- Try some query permutations which once produced identical query IDs +SELECT 1 AS "int" LIMIT 1; +SELECT 1 AS "int" LIMIT 2; +SELECT 1 AS "int" OFFSET 1; +SELECT 1 AS "int" OFFSET 2; +SELECT 1 AS "int" OFFSET 1 LIMIT 1; +SELECT 1 AS "int" OFFSET 2 LIMIT 2; +SELECT 1 AS "int" LIMIT 1 OFFSET 1; +SELECT 1 AS "int" LIMIT 3 OFFSET 3; +SELECT 1 AS "int" OFFSET 1 FETCH FIRST 2 ROW ONLY; +SELECT 1 AS "int" OFFSET 2 FETCH FIRST 3 ROW ONLY; + +-- DISTINCT and ORDER BY patterns +-- Try some query permutations which once produced identical query IDs +SELECT DISTINCT 1 AS "int"; +SELECT DISTINCT 2 AS "int"; +SELECT 1 AS "int" ORDER BY 1; +SELECT 2 AS "int" ORDER BY 1; + +/* this comment should not appear in the output */ SELECT 'hello' - -- multiline + -- but this one will appear AS "text"; SELECT 'world' AS "text"; @@ -58,6 +79,22 @@ DEALLOCATE pgss_test; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- normalization of constants and parameters, with constant locations +-- recorded one or more times. +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT WHERE '1' IN ('1'::int, '3'::int::text); +SELECT WHERE (1, 2) IN ((1, 2), (2, 3)); +SELECT WHERE (3, 4) IN ((5, 6), (8, 7)); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- with the last element being an explicit function call with an argument, ensure +-- the normalization of the squashing interval is correct. +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT WHERE 1 IN (1, int4(1), int4(2)); +SELECT WHERE 1 = ANY (ARRAY[1, int4(1), int4(2)]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + -- -- queries with locking clauses -- @@ -147,3 +184,72 @@ SELECT ( SELECT COUNT(*) FROM pg_stat_statements WHERE query LIKE '%SELECT GROUPING%'; SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- Temporary table with same name, re-created. +BEGIN; + CREATE TEMP TABLE temp_t (id int) ON COMMIT DROP; + SELECT * FROM temp_t; +COMMIT; +BEGIN; + CREATE TEMP TABLE temp_t (id int) ON COMMIT DROP; + SELECT * FROM temp_t; +COMMIT; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- search_path with various schemas and temporary tables +CREATE SCHEMA pgss_schema_1; +CREATE SCHEMA pgss_schema_2; +-- Same attributes. +CREATE TABLE pgss_schema_1.tab_search_same (a int, b int); +CREATE TABLE pgss_schema_2.tab_search_same (a int, b int); +CREATE TEMP TABLE tab_search_same (a int, b int); +-- Different number of attributes, mapping types +CREATE TABLE pgss_schema_1.tab_search_diff_1 (a int); +CREATE TABLE pgss_schema_2.tab_search_diff_1 (a int, b int); +CREATE TEMP TABLE tab_search_diff_1 (a int, b int, c int); +-- Same number of attributes, different types +CREATE TABLE pgss_schema_1.tab_search_diff_2 (a int); +CREATE TABLE pgss_schema_2.tab_search_diff_2 (a text); +CREATE TEMP TABLE tab_search_diff_2 (a bigint); +-- First permanent schema +SET search_path = 'pgss_schema_1'; +SELECT count(*) FROM tab_search_same; +SELECT a, b FROM tab_search_same; +SELECT count(*) FROM tab_search_diff_1; +SELECT count(*) FROM tab_search_diff_2; +SELECT a FROM tab_search_diff_2 AS t1; +SELECT a FROM tab_search_diff_2; +SELECT a AS a1 FROM tab_search_diff_2; +-- Second permanent schema +SET search_path = 'pgss_schema_2'; +SELECT count(*) FROM tab_search_same; +SELECT a, b FROM tab_search_same; +SELECT count(*) FROM tab_search_diff_1; +SELECT count(*) FROM tab_search_diff_2; +SELECT a FROM tab_search_diff_2 AS t1; +SELECT a FROM tab_search_diff_2; +SELECT a AS a1 FROM tab_search_diff_2; +-- Temporary schema +SET search_path = 'pg_temp'; +SELECT count(*) FROM tab_search_same; +SELECT a, b FROM tab_search_same; +SELECT count(*) FROM tab_search_diff_1; +SELECT count(*) FROM tab_search_diff_2; +SELECT a FROM tab_search_diff_2 AS t1; +SELECT a FROM tab_search_diff_2; +SELECT a AS a1 FROM tab_search_diff_2; +RESET search_path; +-- Schema qualifications +SELECT count(*) FROM pgss_schema_1.tab_search_same; +SELECT a, b FROM pgss_schema_1.tab_search_same; +SELECT count(*) FROM pgss_schema_2.tab_search_diff_1; +SELECT count(*) FROM pg_temp.tab_search_diff_2; +SELECT a FROM pgss_schema_2.tab_search_diff_2 AS t1; +SELECT a FROM pgss_schema_2.tab_search_diff_2; +SELECT a AS a1 FROM pgss_schema_2.tab_search_diff_2; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +DROP SCHEMA pgss_schema_1 CASCADE; +DROP SCHEMA pgss_schema_2 CASCADE; +DROP TABLE tab_search_same, tab_search_diff_1, tab_search_diff_2; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; diff --git a/contrib/pg_stat_statements/sql/squashing.sql b/contrib/pg_stat_statements/sql/squashing.sql new file mode 100644 index 0000000000000..bd3243ec9cd85 --- /dev/null +++ b/contrib/pg_stat_statements/sql/squashing.sql @@ -0,0 +1,301 @@ +-- +-- Const squashing functionality +-- +CREATE EXTENSION pg_stat_statements; + +-- +-- Simple Lists +-- + +CREATE TABLE test_squash (id int, data int); + +-- single element will not be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN (1); +SELECT ARRAY[1]; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- more than 1 element in a list will be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN (1, 2, 3); +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4); +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5); +SELECT ARRAY[1, 2, 3]; +SELECT ARRAY[1, 2, 3, 4]; +SELECT ARRAY[1, 2, 3, 4, 5]; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- built-in functions will be squashed +-- the IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT WHERE 1 IN (1, int4(1), int4(2), 2); +SELECT WHERE 1 = ANY (ARRAY[1, int4(1), int4(2), 2]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- external parameters will not be squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5) \bind 1 2 3 4 5 +; +SELECT * FROM test_squash WHERE id::text = ANY(ARRAY[$1, $2, $3, $4, $5]) \bind 1 2 3 4 5 +; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- neither are prepared statements +-- the IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +PREPARE p1(int, int, int, int, int) AS +SELECT * FROM test_squash WHERE id IN ($1, $2, $3, $4, $5); +EXECUTE p1(1, 2, 3, 4, 5); +DEALLOCATE p1; +PREPARE p1(int, int, int, int, int) AS +SELECT * FROM test_squash WHERE id = ANY(ARRAY[$1, $2, $3, $4, $5]); +EXECUTE p1(1, 2, 3, 4, 5); +DEALLOCATE p1; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- More conditions in the query +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9) AND data = 2; +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) AND data = 2; +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) AND data = 2; +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND data = 2; +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) AND data = 2; +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) AND data = 2; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Multiple squashed intervals +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9); +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +SELECT * FROM test_squash WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) + AND data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]); +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +SELECT * FROM test_squash WHERE id = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + AND data = ANY (ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- No constants squashing for OpExpr +-- The IN and ARRAY forms of this statement will have the same queryId +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash WHERE id IN + (1 + 1, 2 + 2, 3 + 3, 4 + 4, 5 + 5, 6 + 6, 7 + 7, 8 + 8, 9 + 9); +SELECT * FROM test_squash WHERE id IN + (@ '-1', @ '-2', @ '-3', @ '-4', @ '-5', @ '-6', @ '-7', @ '-8', @ '-9'); +SELECT * FROM test_squash WHERE id = ANY(ARRAY + [1 + 1, 2 + 2, 3 + 3, 4 + 4, 5 + 5, 6 + 6, 7 + 7, 8 + 8, 9 + 9]); +SELECT * FROM test_squash WHERE id = ANY(ARRAY + [@ '-1', @ '-2', @ '-3', @ '-4', @ '-5', @ '-6', @ '-7', @ '-8', @ '-9']); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- +-- FuncExpr +-- + +-- Verify multiple type representation end up with the same query_id +CREATE TABLE test_float (data float); +-- The casted ARRAY expressions will have the same queryId as the IN clause +-- form of the query +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT data FROM test_float WHERE data IN (1, 2); +SELECT data FROM test_float WHERE data IN (1, '2'); +SELECT data FROM test_float WHERE data IN ('1', 2); +SELECT data FROM test_float WHERE data IN ('1', '2'); +SELECT data FROM test_float WHERE data IN (1.0, 1.0); +SELECT data FROM test_float WHERE data = ANY(ARRAY['1'::double precision, '2'::double precision]); +SELECT data FROM test_float WHERE data = ANY(ARRAY[1.0::double precision, 1.0::double precision]); +SELECT data FROM test_float WHERE data = ANY(ARRAY[1, 2]); +SELECT data FROM test_float WHERE data = ANY(ARRAY[1, '2']); +SELECT data FROM test_float WHERE data = ANY(ARRAY['1', 2]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Numeric type, implicit cast is squashed +CREATE TABLE test_squash_numeric (id int, data numeric(5, 2)); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_numeric WHERE data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); +SELECT * FROM test_squash_numeric WHERE data = ANY(ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Bigint, implicit cast is squashed +CREATE TABLE test_squash_bigint (id int, data bigint); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_bigint WHERE data IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); +SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Bigint, explicit cast is squashed +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_bigint WHERE data IN + (1::bigint, 2::bigint, 3::bigint, 4::bigint, 5::bigint, 6::bigint, + 7::bigint, 8::bigint, 9::bigint, 10::bigint, 11::bigint); +SELECT * FROM test_squash_bigint WHERE data = ANY(ARRAY[ + 1::bigint, 2::bigint, 3::bigint, 4::bigint, 5::bigint, 6::bigint, + 7::bigint, 8::bigint, 9::bigint, 10::bigint, 11::bigint]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Bigint, long tokens with parenthesis, will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_bigint WHERE id IN + (abs(100), abs(200), abs(300), abs(400), abs(500), abs(600), abs(700), + abs(800), abs(900), abs(1000), ((abs(1100)))); +SELECT * FROM test_squash_bigint WHERE id = ANY(ARRAY[ + abs(100), abs(200), abs(300), abs(400), abs(500), abs(600), abs(700), + abs(800), abs(900), abs(1000), ((abs(1100)))]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Multiple FuncExpr's. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT WHERE 1 IN (1::int::bigint::int, 2::int::bigint::int); +SELECT WHERE 1 = ANY(ARRAY[1::int::bigint::int, 2::int::bigint::int]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- +-- CoerceViaIO +-- + +-- Create some dummy type to force CoerceViaIO +CREATE TYPE casttesttype; + +CREATE FUNCTION casttesttype_in(cstring) + RETURNS casttesttype + AS 'textin' + LANGUAGE internal STRICT IMMUTABLE; + +CREATE FUNCTION casttesttype_out(casttesttype) + RETURNS cstring + AS 'textout' + LANGUAGE internal STRICT IMMUTABLE; + +CREATE TYPE casttesttype ( + internallength = variable, + input = casttesttype_in, + output = casttesttype_out, + alignment = int4 +); + +CREATE CAST (int4 AS casttesttype) WITH INOUT; + +CREATE FUNCTION casttesttype_eq(casttesttype, casttesttype) +returns boolean language sql immutable as $$ + SELECT true +$$; + +CREATE OPERATOR = ( + leftarg = casttesttype, + rightarg = casttesttype, + procedure = casttesttype_eq, + commutator = =); + +CREATE TABLE test_squash_cast (id int, data casttesttype); + +-- Use the introduced type to construct a list of CoerceViaIO around Const +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_cast WHERE data IN + (1::int4::casttesttype, 2::int4::casttesttype, 3::int4::casttesttype, + 4::int4::casttesttype, 5::int4::casttesttype, 6::int4::casttesttype, + 7::int4::casttesttype, 8::int4::casttesttype, 9::int4::casttesttype, + 10::int4::casttesttype, 11::int4::casttesttype); +SELECT * FROM test_squash_cast WHERE data = ANY (ARRAY + [1::int4::casttesttype, 2::int4::casttesttype, 3::int4::casttesttype, + 4::int4::casttesttype, 5::int4::casttesttype, 6::int4::casttesttype, + 7::int4::casttesttype, 8::int4::casttesttype, 9::int4::casttesttype, + 10::int4::casttesttype, 11::int4::casttesttype]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Some casting expression are simplified to Const +CREATE TABLE test_squash_jsonb (id int, data jsonb); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_jsonb WHERE data IN + (('"1"')::jsonb, ('"2"')::jsonb, ('"3"')::jsonb, ('"4"')::jsonb, + ('"5"')::jsonb, ('"6"')::jsonb, ('"7"')::jsonb, ('"8"')::jsonb, + ('"9"')::jsonb, ('"10"')::jsonb); +SELECT * FROM test_squash_jsonb WHERE data = ANY (ARRAY + [('"1"')::jsonb, ('"2"')::jsonb, ('"3"')::jsonb, ('"4"')::jsonb, + ('"5"')::jsonb, ('"6"')::jsonb, ('"7"')::jsonb, ('"8"')::jsonb, + ('"9"')::jsonb, ('"10"')::jsonb]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- CoerceViaIO, SubLink instead of a Const. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM test_squash_jsonb WHERE data IN + ((SELECT '"1"')::jsonb, (SELECT '"2"')::jsonb, (SELECT '"3"')::jsonb, + (SELECT '"4"')::jsonb, (SELECT '"5"')::jsonb, (SELECT '"6"')::jsonb, + (SELECT '"7"')::jsonb, (SELECT '"8"')::jsonb, (SELECT '"9"')::jsonb, + (SELECT '"10"')::jsonb); +SELECT * FROM test_squash_jsonb WHERE data = ANY(ARRAY + [(SELECT '"1"')::jsonb, (SELECT '"2"')::jsonb, (SELECT '"3"')::jsonb, + (SELECT '"4"')::jsonb, (SELECT '"5"')::jsonb, (SELECT '"6"')::jsonb, + (SELECT '"7"')::jsonb, (SELECT '"8"')::jsonb, (SELECT '"9"')::jsonb, + (SELECT '"10"')::jsonb]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Multiple CoerceViaIO wrapping a constant. Will not squash +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT WHERE 1 IN (1::text::int::text::int, 1::text::int::text::int); +SELECT WHERE 1 = ANY(ARRAY[1::text::int::text::int, 1::text::int::text::int]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- +-- RelabelType +-- + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- if there is only one level of RelabelType, the list will be squashable +SELECT * FROM test_squash WHERE id IN + (1::oid, 2::oid, 3::oid, 4::oid, 5::oid, 6::oid, 7::oid, 8::oid, 9::oid); +SELECT ARRAY[1::oid, 2::oid, 3::oid, 4::oid, 5::oid, 6::oid, 7::oid, 8::oid, 9::oid]; +-- if there is at least one element with multiple levels of RelabelType, +-- the list will not be squashable +SELECT * FROM test_squash WHERE id IN (1::oid, 2::oid::int::oid); +SELECT * FROM test_squash WHERE id = ANY(ARRAY[1::oid, 2::oid::int::oid]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- +-- edge cases +-- + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- for nested arrays, only constants are squashed +SELECT ARRAY[ + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + ]; +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- Test constants evaluation in a CTE, which was causing issues in the past +WITH cte AS ( + SELECT 'const' as const FROM test_squash +) +SELECT ARRAY['a', 'b', 'c', const::varchar] AS result +FROM cte; + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- Rewritten as an OpExpr, so it will not be squashed +select where '1' IN ('1'::int, '2'::int::text); +-- Rewritten as an ArrayExpr, so it will be squashed +select where '1' IN ('1'::int, '2'::int); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +-- Both of these queries will be rewritten as an ArrayExpr, so they +-- will be squashed, and have a similar queryId +select where '1' IN ('1'::int::text, '2'::int::text); +select where '1' = ANY (array['1'::int::text, '2'::int::text]); +SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- +-- cleanup +-- +DROP TABLE test_squash; +DROP TABLE test_float; +DROP TABLE test_squash_numeric; +DROP TABLE test_squash_bigint; +DROP TABLE test_squash_cast CASCADE; +DROP TABLE test_squash_jsonb; diff --git a/contrib/pg_stat_statements/sql/utility.sql b/contrib/pg_stat_statements/sql/utility.sql index 4f7afece1decc..dd97203c21025 100644 --- a/contrib/pg_stat_statements/sql/utility.sql +++ b/contrib/pg_stat_statements/sql/utility.sql @@ -47,7 +47,8 @@ DROP FOREIGN DATA WRAPPER wrapper_stats; -- Functions CREATE FUNCTION func_stats(a text DEFAULT 'a_data', b text DEFAULT lower('b_data')) - RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL; + RETURNS text AS $$ SELECT $1::text || '_' || $2::text; $$ LANGUAGE SQL + SET work_mem = '256kB'; DROP FUNCTION func_stats; -- Rules @@ -277,12 +278,26 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- SET statements. -- These use two different strings, still they count as one entry. +CREATE ROLE regress_stat_set_1; +CREATE ROLE regress_stat_set_2; SET work_mem = '1MB'; Set work_mem = '1MB'; SET work_mem = '2MB'; +SET work_mem = DEFAULT; +SET work_mem TO DEFAULT; +SET work_mem FROM CURRENT; +BEGIN; +SET LOCAL work_mem = '128kB'; +SET LOCAL work_mem = '256kB'; +SET LOCAL work_mem = DEFAULT; +SET LOCAL work_mem TO DEFAULT; +SET LOCAL work_mem FROM CURRENT; +COMMIT; RESET work_mem; SET enable_seqscan = off; SET enable_seqscan = on; +SET SESSION work_mem = '300kB'; +SET SESSION work_mem = '400kB'; RESET enable_seqscan; -- SET TRANSACTION ISOLATION BEGIN; @@ -290,15 +305,35 @@ SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; COMMIT; --- SET SESSION CHARACTERISTICS +-- SET SESSION AUTHORIZATION SET SESSION SESSION AUTHORIZATION DEFAULT; +SET SESSION AUTHORIZATION 'regress_stat_set_1'; +SET SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; BEGIN; SET LOCAL SESSION AUTHORIZATION DEFAULT; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_1'; +SET LOCAL SESSION AUTHORIZATION 'regress_stat_set_2'; RESET SESSION AUTHORIZATION; COMMIT; +-- SET SESSION CHARACTERISTICS +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ ONLY; +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE; +-- SET XML OPTION +SET XML OPTION DOCUMENT; +SET XML OPTION CONTENT; +-- SET TIME ZONE +SET TIME ZONE 'America/New_York'; +SET TIME ZONE 'Asia/Tokyo'; +SET TIME ZONE DEFAULT; +SET TIME ZONE LOCAL; +SET TIME ZONE 'CST7CDT,M4.1.0,M10.5.0'; +RESET TIME ZONE; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +DROP ROLE regress_stat_set_1; +DROP ROLE regress_stat_set_2; SELECT pg_stat_statements_reset() IS NOT NULL AS t; -- @@ -329,3 +364,11 @@ DROP TABLE pgss_ctas; DROP TABLE pgss_select_into; SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- Special cases. Keep these ones at the end to avoid conflicts. +SET SCHEMA 'foo'; +SET SCHEMA 'public'; +RESET ALL; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; diff --git a/contrib/pg_stat_statements/t/010_restart.pl b/contrib/pg_stat_statements/t/010_restart.pl index 207d54714bed1..066345ab8215a 100644 --- a/contrib/pg_stat_statements/t/010_restart.pl +++ b/contrib/pg_stat_statements/t/010_restart.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Tests for checking that pg_stat_statements contents are preserved # across restarts. diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c index 37dffe3f7d57a..3e86283beb7cf 100644 --- a/contrib/pg_surgery/heap_surgery.c +++ b/contrib/pg_surgery/heap_surgery.c @@ -3,7 +3,7 @@ * heap_surgery.c * Functions to perform surgery on the damaged heap table. * - * Copyright (c) 2020-2024, PostgreSQL Global Development Group + * Copyright (c) 2020-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pg_surgery/heap_surgery.c @@ -12,18 +12,21 @@ */ #include "postgres.h" -#include "access/heapam.h" +#include "access/htup_details.h" +#include "access/relation.h" #include "access/visibilitymap.h" #include "access/xloginsert.h" #include "catalog/pg_am_d.h" -#include "catalog/pg_proc_d.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/acl.h" #include "utils/array.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_surgery", + .version = PG_VERSION +); /* Options to forcefully change the state of a heap tuple. */ typedef enum HeapTupleForceOption diff --git a/contrib/pg_surgery/meson.build b/contrib/pg_surgery/meson.build index effc4ada34b73..c6cfa9c4694a3 100644 --- a/contrib/pg_surgery/meson.build +++ b/contrib/pg_surgery/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_surgery_sources = files( 'heap_surgery.c', diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out index ce4bf1d4e51bf..0b70d9de25624 100644 --- a/contrib/pg_trgm/expected/pg_trgm.out +++ b/contrib/pg_trgm/expected/pg_trgm.out @@ -2372,6 +2372,9 @@ ERROR: value 2025 out of bounds for option "siglen" DETAIL: Valid values are between "1" and "2024". create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024)); set enable_seqscan=off; +-- check index compatibility handling when opclass option is specified +alter table test_trgm alter column t type varchar(768); +alter table test_trgm alter column t type text; select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t; t | sml -------------+---------- diff --git a/contrib/pg_trgm/meson.build b/contrib/pg_trgm/meson.build index dac92135530cd..a31aa5c574d34 100644 --- a/contrib/pg_trgm/meson.build +++ b/contrib/pg_trgm/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_trgm_sources = files( 'trgm_gin.c', diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql index 6a9da24d5a72b..340c9891899f0 100644 --- a/contrib/pg_trgm/sql/pg_trgm.sql +++ b/contrib/pg_trgm/sql/pg_trgm.sql @@ -52,6 +52,10 @@ create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2025)); create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024)); set enable_seqscan=off; +-- check index compatibility handling when opclass option is specified +alter table test_trgm alter column t type varchar(768); +alter table test_trgm alter column t type text; + select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t; select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t; select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t; diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h index afb0adb222b91..ca017585369ad 100644 --- a/contrib/pg_trgm/trgm.h +++ b/contrib/pg_trgm/trgm.h @@ -15,7 +15,6 @@ */ #define LPADDING 2 #define RPADDING 1 -#define KEEPONLYALNUM /* * Caution: IGNORECASE macro means that trigrams are case-insensitive. * If this macro is disabled, the ~* and ~~* operators must be removed from @@ -41,23 +40,15 @@ typedef char trgm[3]; -#define CMPCHAR(a,b) ( ((a)==(b)) ? 0 : ( ((a)<(b)) ? -1 : 1 ) ) -#define CMPPCHAR(a,b,i) CMPCHAR( *(((const char*)(a))+i), *(((const char*)(b))+i) ) -#define CMPTRGM(a,b) ( CMPPCHAR(a,b,0) ? CMPPCHAR(a,b,0) : ( CMPPCHAR(a,b,1) ? CMPPCHAR(a,b,1) : CMPPCHAR(a,b,2) ) ) - #define CPTRGM(a,b) do { \ *(((char*)(a))+0) = *(((char*)(b))+0); \ *(((char*)(a))+1) = *(((char*)(b))+1); \ *(((char*)(a))+2) = *(((char*)(b))+2); \ } while(0) +extern int (*CMPTRGM) (const void *a, const void *b); -#ifdef KEEPONLYALNUM #define ISWORDCHR(c) (t_isalnum(c)) #define ISPRINTABLECHAR(a) ( isascii( *(unsigned char*)(a) ) && (isalnum( *(unsigned char*)(a) ) || *(unsigned char*)(a)==' ') ) -#else -#define ISWORDCHR(c) (!t_isspace(c)) -#define ISPRINTABLECHAR(a) ( isascii( *(unsigned char*)(a) ) && isprint( *(unsigned char*)(a) ) ) -#endif #define ISPRINTABLETRGM(t) ( ISPRINTABLECHAR( ((char*)(t)) ) && ISPRINTABLECHAR( ((char*)(t))+1 ) && ISPRINTABLECHAR( ((char*)(t))+2 ) ) #define ISESCAPECHAR(x) (*(x) == '\\') /* Wildcard escape character */ diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c index 9ef2e38560a2b..5ba895217b0a9 100644 --- a/contrib/pg_trgm/trgm_gist.c +++ b/contrib/pg_trgm/trgm_gist.c @@ -106,7 +106,7 @@ makesign(BITVECP sign, TRGM *a, int siglen) SETBIT(sign, SIGLENBIT(siglen)); /* set last unused bit */ for (k = 0; k < len; k++) { - CPTRGM(((char *) &tmp), ptr + k); + CPTRGM(&tmp, ptr + k); HASH(sign, tmp, siglen); } } @@ -186,7 +186,7 @@ cnt_sml_sign_common(TRGM *qtrg, BITVECP sign, int siglen) for (k = 0; k < len; k++) { - CPTRGM(((char *) &tmp), ptr + k); + CPTRGM(&tmp, ptr + k); count += GETBIT(sign, HASHVAL(tmp, siglen)); } @@ -228,7 +228,7 @@ gtrgm_consistent(PG_FUNCTION_ARGS) if (cache == NULL || cache->strategy != strategy || VARSIZE(cache->query) != querysize || - memcmp((char *) cache->query, (char *) query, querysize) != 0) + memcmp(cache->query, query, querysize) != 0) { gtrgm_consistent_cache *newcache; TrgmPackedGraph *graph = NULL; @@ -284,12 +284,12 @@ gtrgm_consistent(PG_FUNCTION_ARGS) newcache->strategy = strategy; newcache->query = (text *) ((char *) newcache + MAXALIGN(sizeof(gtrgm_consistent_cache))); - memcpy((char *) newcache->query, (char *) query, querysize); + memcpy(newcache->query, query, querysize); if (qtrg) { newcache->trigrams = (TRGM *) ((char *) newcache->query + MAXALIGN(querysize)); - memcpy((char *) newcache->trigrams, (char *) qtrg, qtrgsize); + memcpy((char *) newcache->trigrams, qtrg, qtrgsize); /* release qtrg in case it was made in fn_mcxt */ pfree(qtrg); } @@ -299,7 +299,7 @@ gtrgm_consistent(PG_FUNCTION_ARGS) if (cache) pfree(cache); - fcinfo->flinfo->fn_extra = (void *) newcache; + fcinfo->flinfo->fn_extra = newcache; cache = newcache; } @@ -373,7 +373,7 @@ gtrgm_consistent(PG_FUNCTION_ARGS) res = true; for (k = 0; k < len; k++) { - CPTRGM(((char *) &tmp), ptr + k); + CPTRGM(&tmp, ptr + k); if (!GETBIT(sign, HASHVAL(tmp, siglen))) { res = false; @@ -426,7 +426,7 @@ gtrgm_consistent(PG_FUNCTION_ARGS) check = (bool *) palloc(len * sizeof(bool)); for (k = 0; k < len; k++) { - CPTRGM(((char *) &tmp), ptr + k); + CPTRGM(&tmp, ptr + k); check[k] = GETBIT(sign, HASHVAL(tmp, siglen)); } res = trigramsMatchGraph(cache->graph, check); @@ -552,7 +552,7 @@ unionkey(BITVECP sbase, TRGM *add, int siglen) for (i = 0; i < ARRNELEM(add); i++) { - CPTRGM(((char *) &tmp), ptr + i); + CPTRGM(&tmp, ptr + i); HASH(sbase, tmp, siglen); } } diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c index c509d15ee402f..29b39ec8a4c25 100644 --- a/contrib/pg_trgm/trgm_op.c +++ b/contrib/pg_trgm/trgm_op.c @@ -5,18 +5,23 @@ #include +#include "catalog/pg_collation_d.h" #include "catalog/pg_type.h" #include "common/int.h" #include "lib/qunique.h" #include "miscadmin.h" #include "trgm.h" #include "tsearch/ts_locale.h" +#include "utils/formatting.h" #include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_crc.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_trgm", + .version = PG_VERSION +); /* GUC variables */ double similarity_threshold = 0.3f; @@ -40,6 +45,9 @@ PG_FUNCTION_INFO_V1(strict_word_similarity_commutator_op); PG_FUNCTION_INFO_V1(strict_word_similarity_dist_op); PG_FUNCTION_INFO_V1(strict_word_similarity_dist_commutator_op); +static int CMPTRGM_CHOOSE(const void *a, const void *b); +int (*CMPTRGM) (const void *a, const void *b) = CMPTRGM_CHOOSE; + /* Trigram with position */ typedef struct { @@ -105,6 +113,47 @@ _PG_init(void) MarkGUCPrefixReserved("pg_trgm"); } +#define CMPCHAR(a,b) ( ((a)==(b)) ? 0 : ( ((a)<(b)) ? -1 : 1 ) ) + +/* + * Functions for comparing two trgms while treating each char as "signed char" or + * "unsigned char". + */ +static inline int +CMPTRGM_SIGNED(const void *a, const void *b) +{ +#define CMPPCHAR_S(a,b,i) CMPCHAR( *(((const signed char*)(a))+i), *(((const signed char*)(b))+i) ) + + return CMPPCHAR_S(a, b, 0) ? CMPPCHAR_S(a, b, 0) + : (CMPPCHAR_S(a, b, 1) ? CMPPCHAR_S(a, b, 1) + : CMPPCHAR_S(a, b, 2)); +} + +static inline int +CMPTRGM_UNSIGNED(const void *a, const void *b) +{ +#define CMPPCHAR_UNS(a,b,i) CMPCHAR( *(((const unsigned char*)(a))+i), *(((const unsigned char*)(b))+i) ) + + return CMPPCHAR_UNS(a, b, 0) ? CMPPCHAR_UNS(a, b, 0) + : (CMPPCHAR_UNS(a, b, 1) ? CMPPCHAR_UNS(a, b, 1) + : CMPPCHAR_UNS(a, b, 2)); +} + +/* + * This gets called on the first call. It replaces the function pointer so + * that subsequent calls are routed directly to the chosen implementation. + */ +static int +CMPTRGM_CHOOSE(const void *a, const void *b) +{ + if (GetDefaultCharSignedness()) + CMPTRGM = CMPTRGM_SIGNED; + else + CMPTRGM = CMPTRGM_UNSIGNED; + + return CMPTRGM(a, b); +} + /* * Deprecated function. * Use "pg_trgm.similarity_threshold" GUC variable instead of this function. @@ -303,7 +352,7 @@ generate_trgm_only(trgm *trg, char *str, int slen, TrgmBound *bounds) while ((bword = find_word(eword, slen - (eword - str), &eword, &charlen)) != NULL) { #ifdef IGNORECASE - bword = lowerstr_with_len(bword, eword - bword); + bword = str_tolower(bword, eword - bword, DEFAULT_COLLATION_OID); bytelen = strlen(bword); #else bytelen = eword - bword; @@ -899,7 +948,7 @@ generate_wildcard_trgm(const char *str, int slen) buf, &bytelen, &charlen)) != NULL) { #ifdef IGNORECASE - buf2 = lowerstr_with_len(buf, bytelen); + buf2 = str_tolower(buf, bytelen, DEFAULT_COLLATION_OID); bytelen = strlen(buf2); #else buf2 = buf; diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c index 75d6d1d4a8dd3..149f9eb259c01 100644 --- a/contrib/pg_trgm/trgm_regexp.c +++ b/contrib/pg_trgm/trgm_regexp.c @@ -181,7 +181,7 @@ * 7) Mark state 3 final because state 5 of source NFA is marked as final. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -191,9 +191,11 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" #include "regex/regexport.h" #include "trgm.h" #include "tsearch/ts_locale.h" +#include "utils/formatting.h" #include "utils/hsearch.h" #include "utils/memutils.h" #include "varatt.h" @@ -847,16 +849,16 @@ convertPgWchar(pg_wchar c, trgm_mb_char *result) * within each color, since we used the REG_ICASE option; so there's no * need to process the uppercase version. * - * XXX this code is dependent on the assumption that lowerstr() works the - * same as the regex engine's internal case folding machinery. Might be - * wiser to expose pg_wc_tolower and test whether c == pg_wc_tolower(c). - * On the other hand, the trigrams in the index were created using - * lowerstr(), so we're probably screwed if there's any incompatibility - * anyway. + * XXX this code is dependent on the assumption that str_tolower() works + * the same as the regex engine's internal case folding machinery. Might + * be wiser to expose pg_wc_tolower and test whether c == + * pg_wc_tolower(c). On the other hand, the trigrams in the index were + * created using str_tolower(), so we're probably screwed if there's any + * incompatibility anyway. */ #ifdef IGNORECASE { - char *lowerCased = lowerstr(s); + char *lowerCased = str_tolower(s, strlen(s), DEFAULT_COLLATION_OID); if (strcmp(lowerCased, s) != 0) { diff --git a/contrib/pg_visibility/meson.build b/contrib/pg_visibility/meson.build index f3c1263313a25..1b14cf037c3f1 100644 --- a/contrib/pg_visibility/meson.build +++ b/contrib/pg_visibility/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_visibility_sources = files( 'pg_visibility.c', @@ -36,6 +36,7 @@ tests += { 'tap': { 'tests': [ 't/001_concurrent_transaction.pl', + 't/002_corrupt_vm.pl', ], }, } diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index 1a1a4ff7be702..d79ef35006bfa 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -3,7 +3,7 @@ * pg_visibility.c * display visibility map information and page-level visibility bits * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * contrib/pg_visibility/pg_visibility.c *------------------------------------------------------------------------- @@ -21,11 +21,14 @@ #include "storage/bufmgr.h" #include "storage/proc.h" #include "storage/procarray.h" +#include "storage/read_stream.h" #include "storage/smgr.h" #include "utils/rel.h" -#include "utils/snapmgr.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_visibility", + .version = PG_VERSION +); typedef struct vbits { @@ -41,6 +44,17 @@ typedef struct corrupt_items ItemPointer tids; } corrupt_items; +/* for collect_corrupt_items_read_stream_next_block */ +struct collect_corrupt_items_read_stream_private +{ + bool all_frozen; + bool all_visible; + BlockNumber current_blocknum; + BlockNumber last_exclusive; + Relation rel; + Buffer vmbuffer; +}; + PG_FUNCTION_INFO_V1(pg_visibility_map); PG_FUNCTION_INFO_V1(pg_visibility_map_rel); PG_FUNCTION_INFO_V1(pg_visibility); @@ -380,6 +394,7 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS) Relation rel; ForkNumber fork; BlockNumber block; + BlockNumber old_block; rel = relation_open(relid, AccessExclusiveLock); @@ -389,15 +404,22 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS) /* Forcibly reset cached file size */ RelationGetSmgr(rel)->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber; + /* Compute new and old size before entering critical section. */ + fork = VISIBILITYMAP_FORKNUM; block = visibilitymap_prepare_truncate(rel, 0); - if (BlockNumberIsValid(block)) - { - fork = VISIBILITYMAP_FORKNUM; - smgrtruncate(RelationGetSmgr(rel), &fork, 1, &block); - } + old_block = BlockNumberIsValid(block) ? smgrnblocks(RelationGetSmgr(rel), fork) : 0; + + /* + * WAL-logging, buffer dropping, file truncation must be atomic and all on + * one side of a checkpoint. See RelationTruncate() for discussion. + */ + Assert((MyProc->delayChkptFlags & (DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE)) == 0); + MyProc->delayChkptFlags |= DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE; + START_CRIT_SECTION(); if (RelationNeedsWAL(rel)) { + XLogRecPtr lsn; xl_smgr_truncate xlrec; xlrec.blkno = 0; @@ -405,11 +427,19 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS) xlrec.flags = SMGR_TRUNCATE_VM; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); - XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE); + lsn = XLogInsert(RM_SMGR_ID, + XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE); + XLogFlush(lsn); } + if (BlockNumberIsValid(block)) + smgrtruncate(RelationGetSmgr(rel), &fork, 1, &old_block, &block); + + END_CRIT_SECTION(); + MyProc->delayChkptFlags &= ~(DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE); + /* * Release the lock right away, not at commit time. * @@ -478,6 +508,8 @@ collect_visibility_data(Oid relid, bool include_pd) BlockNumber blkno; Buffer vmbuffer = InvalidBuffer; BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD); + BlockRangeReadStreamPrivate p; + ReadStream *stream = NULL; rel = relation_open(relid, AccessShareLock); @@ -489,6 +521,26 @@ collect_visibility_data(Oid relid, bool include_pd) info->next = 0; info->count = nblocks; + /* Create a stream if reading main fork. */ + if (include_pd) + { + p.current_blocknum = 0; + p.last_exclusive = nblocks; + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, + bstrategy, + rel, + MAIN_FORKNUM, + block_range_read_stream_cb, + &p, + 0); + } + for (blkno = 0; blkno < nblocks; ++blkno) { int32 mapbits; @@ -513,8 +565,7 @@ collect_visibility_data(Oid relid, bool include_pd) Buffer buffer; Page page; - buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - bstrategy); + buffer = read_stream_next_buffer(stream, NULL); LockBuffer(buffer, BUFFER_LOCK_SHARE); page = BufferGetPage(buffer); @@ -525,6 +576,12 @@ collect_visibility_data(Oid relid, bool include_pd) } } + if (include_pd) + { + Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer); + read_stream_end(stream); + } + /* Clean up. */ if (vmbuffer != InvalidBuffer) ReleaseBuffer(vmbuffer); @@ -546,11 +603,21 @@ collect_visibility_data(Oid relid, bool include_pd) * * 1. Ignore processes xmin's, because they consider connection to other * databases that were ignored before. - * 2. Ignore KnownAssignedXids, because they are not database-aware. At the - * same time, the primary could compute its horizons database-aware. + * 2. Ignore KnownAssignedXids, as they are not database-aware. Although we + * now perform minimal checking on a standby by always using nextXid, this + * approach is better than nothing and will at least catch extremely broken + * cases where a xid is in the future. * 3. Ignore walsender xmin, because it could go backward if some replication * connections don't use replication slots. * + * While it might seem like we could use KnownAssignedXids for shared + * catalogs, since shared catalogs rely on a global horizon rather than a + * database-specific one - there are potential edge cases. For example, a + * transaction may crash on the primary without writing a commit/abort record. + * This would lead to a situation where it appears to still be running on the + * standby, even though it has already ended on the primary. For this reason, + * it's safer to ignore KnownAssignedXids, even for shared catalogs. + * * As a result, we're using only currently running xids to compute the horizon. * Surely these would significantly sacrifice accuracy. But we have to do so * to avoid reporting false errors. @@ -560,7 +627,17 @@ GetStrictOldestNonRemovableTransactionId(Relation rel) { RunningTransactions runningTransactions; - if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress()) + if (RecoveryInProgress()) + { + TransactionId result; + + /* As we ignore KnownAssignedXids on standby, just pick nextXid */ + LWLockAcquire(XidGenLock, LW_SHARED); + result = XidFromFullTransactionId(TransamVariables->nextXid); + LWLockRelease(XidGenLock); + return result; + } + else if (rel == NULL || rel->rd_rel->relisshared) { /* Shared relation: take into account all running xids */ runningTransactions = GetRunningTransactionData(); @@ -590,6 +667,38 @@ GetStrictOldestNonRemovableTransactionId(Relation rel) } } +/* + * Callback function to get next block for read stream object used in + * collect_corrupt_items() function. + */ +static BlockNumber +collect_corrupt_items_read_stream_next_block(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) +{ + struct collect_corrupt_items_read_stream_private *p = callback_private_data; + + for (; p->current_blocknum < p->last_exclusive; p->current_blocknum++) + { + bool check_frozen = false; + bool check_visible = false; + + /* Make sure we are interruptible. */ + CHECK_FOR_INTERRUPTS(); + + if (p->all_frozen && VM_ALL_FROZEN(p->rel, p->current_blocknum, &p->vmbuffer)) + check_frozen = true; + if (p->all_visible && VM_ALL_VISIBLE(p->rel, p->current_blocknum, &p->vmbuffer)) + check_visible = true; + if (!check_visible && !check_frozen) + continue; + + return p->current_blocknum++; + } + + return InvalidBlockNumber; +} + /* * Returns a list of items whose visibility map information does not match * the status of the tuples on the page. @@ -608,12 +717,13 @@ static corrupt_items * collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) { Relation rel; - BlockNumber nblocks; corrupt_items *items; - BlockNumber blkno; Buffer vmbuffer = InvalidBuffer; BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD); TransactionId OldestXmin = InvalidTransactionId; + struct collect_corrupt_items_read_stream_private p; + ReadStream *stream; + Buffer buffer; rel = relation_open(relid, AccessShareLock); @@ -623,8 +733,6 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) if (all_visible) OldestXmin = GetStrictOldestNonRemovableTransactionId(rel); - nblocks = RelationGetNumberOfBlocks(rel); - /* * Guess an initial array size. We don't expect many corrupted tuples, so * start with a small array. This function uses the "next" field to track @@ -638,34 +746,38 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) items->count = 64; items->tids = palloc(items->count * sizeof(ItemPointerData)); + p.current_blocknum = 0; + p.last_exclusive = RelationGetNumberOfBlocks(rel); + p.rel = rel; + p.vmbuffer = InvalidBuffer; + p.all_frozen = all_frozen; + p.all_visible = all_visible; + stream = read_stream_begin_relation(READ_STREAM_FULL, + bstrategy, + rel, + MAIN_FORKNUM, + collect_corrupt_items_read_stream_next_block, + &p, + 0); + /* Loop over every block in the relation. */ - for (blkno = 0; blkno < nblocks; ++blkno) + while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) { - bool check_frozen = false; - bool check_visible = false; - Buffer buffer; + bool check_frozen = all_frozen; + bool check_visible = all_visible; Page page; OffsetNumber offnum, maxoff; + BlockNumber blkno; /* Make sure we are interruptible. */ CHECK_FOR_INTERRUPTS(); - /* Use the visibility map to decide whether to check this page. */ - if (all_frozen && VM_ALL_FROZEN(rel, blkno, &vmbuffer)) - check_frozen = true; - if (all_visible && VM_ALL_VISIBLE(rel, blkno, &vmbuffer)) - check_visible = true; - if (!check_visible && !check_frozen) - continue; - - /* Read and lock the page. */ - buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - bstrategy); LockBuffer(buffer, BUFFER_LOCK_SHARE); page = BufferGetPage(buffer); maxoff = PageGetMaxOffsetNumber(page); + blkno = BufferGetBlockNumber(buffer); /* * The visibility map bits might have changed while we were acquiring @@ -758,10 +870,13 @@ collect_corrupt_items(Oid relid, bool all_visible, bool all_frozen) UnlockReleaseBuffer(buffer); } + read_stream_end(stream); /* Clean up. */ if (vmbuffer != InvalidBuffer) ReleaseBuffer(vmbuffer); + if (p.vmbuffer != InvalidBuffer) + ReleaseBuffer(p.vmbuffer); relation_close(rel, AccessShareLock); /* diff --git a/contrib/pg_visibility/t/001_concurrent_transaction.pl b/contrib/pg_visibility/t/001_concurrent_transaction.pl index c31d041757d0c..9911720984e3b 100644 --- a/contrib/pg_visibility/t/001_concurrent_transaction.pl +++ b/contrib/pg_visibility/t/001_concurrent_transaction.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Check that a concurrent transaction doesn't cause false negatives in # pg_check_visible() function @@ -10,11 +10,18 @@ use Test::More; +# Initialize the primary node my $node = PostgreSQL::Test::Cluster->new('main'); - -$node->init; +$node->init(allows_streaming => 1); $node->start; +# Initialize the streaming standby +my $backup_name = 'my_backup'; +$node->backup($backup_name); +my $standby = PostgreSQL::Test::Cluster->new('standby'); +$standby->init_from_backup($node, $backup_name, has_streaming => 1); +$standby->start; + # Setup another database $node->safe_psql("postgres", "CREATE DATABASE other_database;\n"); my $bsession = $node->background_psql('other_database'); @@ -39,9 +46,18 @@ # There should be no false negatives ok($result eq "", "pg_check_visible() detects no errors"); +# Run pg_check_visible() on standby +$node->wait_for_catchup($standby); +$result = $standby->safe_psql("postgres", + "SELECT * FROM pg_check_visible('vacuum_test');"); + +# There should be no false negatives either +ok($result eq "", "pg_check_visible() detects no errors"); + # Shutdown $bsession->query_safe("COMMIT;"); $bsession->quit; $node->stop; +$standby->stop; done_testing(); diff --git a/contrib/pg_visibility/t/002_corrupt_vm.pl b/contrib/pg_visibility/t/002_corrupt_vm.pl new file mode 100644 index 0000000000000..b9b319564669b --- /dev/null +++ b/contrib/pg_visibility/t/002_corrupt_vm.pl @@ -0,0 +1,109 @@ +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Check that pg_check_visible() and pg_check_frozen() report correct TIDs for +# corruption. +use strict; +use warnings FATAL => 'all'; +use File::Copy; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('main'); +$node->init; +# Anything holding a snapshot, including auto-analyze of pg_proc, could stop +# VACUUM from updating the visibility map. +$node->append_conf('postgresql.conf', 'autovacuum=off'); +$node->start; + +my $blck_size = $node->safe_psql("postgres", "SHOW block_size;"); + +# Create a sample table with at least 10 pages and then run VACUUM. 10 is +# selected manually as it is big enough to select 5 random tuples from the +# relation. +$node->safe_psql( + 'postgres', qq( + CREATE EXTENSION pg_visibility; + CREATE TABLE corruption_test + WITH (autovacuum_enabled = false) AS + SELECT + i, + repeat('a', 10) AS data + FROM + generate_series(1, $blck_size) i; + VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) corruption_test; +)); + +# VACUUM is run, it is safe to get the number of pages. +my $npages = $node->safe_psql( + "postgres", + "SELECT relpages FROM pg_class + WHERE relname = 'corruption_test';" +); +ok($npages >= 10, 'table has at least 10 pages'); + +my $file = $node->safe_psql("postgres", + "SELECT pg_relation_filepath('corruption_test');"); + +# Delete the first block to make sure that it will be skipped as it is +# not visible nor frozen. +$node->safe_psql( + "postgres", + "DELETE FROM corruption_test + WHERE (ctid::text::point)[0] = 0;" +); + +# Copy visibility map. +$node->stop; +my $vm_file = $node->data_dir . '/' . $file . '_vm'; +copy("$vm_file", "${vm_file}_temp"); +$node->start; + +# Select 5 random tuples that are starting from the second block of the +# relation. The first block is skipped because it is deleted above. +my $tuples = $node->safe_psql( + "postgres", + "SELECT ctid FROM ( + SELECT ctid FROM corruption_test + WHERE (ctid::text::point)[0] != 0 + ORDER BY random() LIMIT 5) + ORDER BY ctid ASC;" +); + +# Do the changes below to use tuples in the query. +# "\n" -> "," +# "(" -> "'(" +# ")" -> ")'" +(my $tuples_query = $tuples) =~ s/\n/,/g; +$tuples_query =~ s/\(/\'\(/g; +$tuples_query =~ s/\)/\)\'/g; + +$node->safe_psql( + "postgres", + "DELETE FROM corruption_test + WHERE ctid in ($tuples_query);" +); + +# Overwrite visibility map with the old one. +$node->stop; +move("${vm_file}_temp", "$vm_file"); +$node->start; + +my $result = $node->safe_psql( + "postgres", + "SELECT DISTINCT t_ctid + FROM pg_check_visible('corruption_test') + ORDER BY t_ctid ASC;" +); +is($result, $tuples, 'pg_check_visible must report tuples as corrupted'); + +$result = $node->safe_psql( + "postgres", + "SELECT DISTINCT t_ctid + FROM pg_check_frozen('corruption_test') + ORDER BY t_ctid ASC;" +); +is($result, $tuples, 'pg_check_frozen must report tuples as corrupted'); + +$node->stop; +done_testing(); diff --git a/contrib/pg_walinspect/meson.build b/contrib/pg_walinspect/meson.build index bd959a2070f69..3a82ce09fcf9b 100644 --- a/contrib/pg_walinspect/meson.build +++ b/contrib/pg_walinspect/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_walinspect_sources = files('pg_walinspect.c') diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c index 9e3e05e398ac0..64745564cc249 100644 --- a/contrib/pg_walinspect/pg_walinspect.c +++ b/contrib/pg_walinspect/pg_walinspect.c @@ -3,7 +3,7 @@ * pg_walinspect.c * Functions to inspect contents of PostgreSQL Write-Ahead Log * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pg_walinspect/pg_walinspect.c @@ -29,7 +29,10 @@ * give a thought about doing the same in pg_waldump tool as well. */ -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pg_walinspect", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(pg_get_wal_block_info); PG_FUNCTION_INFO_V1(pg_get_wal_record_info); diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile index 85f1c94681356..69afa3750116c 100644 --- a/contrib/pgcrypto/Makefile +++ b/contrib/pgcrypto/Makefile @@ -11,6 +11,7 @@ OBJS = \ crypt-des.o \ crypt-gensalt.o \ crypt-md5.o \ + crypt-sha.o \ mbuf.o \ openssl.o \ pgcrypto.o \ @@ -36,14 +37,14 @@ MODULE_big = pgcrypto EXTENSION = pgcrypto DATA = pgcrypto--1.3.sql pgcrypto--1.2--1.3.sql pgcrypto--1.1--1.2.sql \ - pgcrypto--1.0--1.1.sql + pgcrypto--1.0--1.1.sql pgcrypto--1.3--1.4.sql PGFILEDESC = "pgcrypto - cryptographic functions" REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \ sha2 des 3des cast5 \ crypt-des crypt-md5 crypt-blowfish crypt-xdes \ pgp-armor pgp-decrypt pgp-encrypt pgp-encrypt-md5 $(CF_PGP_TESTS) \ - pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info + pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info crypt-shacrypt ifdef USE_PGXS PG_CONFIG = pg_config @@ -61,7 +62,6 @@ endif # matter.) SHLIB_LINK += $(filter -lcrypto -lz, $(LIBS)) ifeq ($(PORTNAME), win32) -SHLIB_LINK += $(filter -leay32, $(LIBS)) # those must be at the end SHLIB_LINK += -lws2_32 endif diff --git a/contrib/pgcrypto/crypt-gensalt.c b/contrib/pgcrypto/crypt-gensalt.c index 740f3612532b0..7149dce02d5fe 100644 --- a/contrib/pgcrypto/crypt-gensalt.c +++ b/contrib/pgcrypto/crypt-gensalt.c @@ -185,3 +185,85 @@ _crypt_gensalt_blowfish_rn(unsigned long count, return output; } + +/* + * Helper for _crypt_gensalt_sha256_rn and _crypt_gensalt_sha512_rn + */ +static char * +_crypt_gensalt_sha(unsigned long count, + const char *input, int size, char *output, int output_size) +{ + char *s_ptr = output; + unsigned int result_bufsize = PX_SHACRYPT_SALT_BUF_LEN; + int rc; + + /* output buffer must be allocated with PX_MAX_SALT_LEN bytes */ + if (PX_MAX_SALT_LEN < result_bufsize) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid size of salt")); + + /* + * Care must be taken to not exceed the buffer size allocated for the + * input character buffer. + */ + if ((PX_SHACRYPT_SALT_MAX_LEN != size) || (output_size < size)) + ereport(ERROR, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("invalid length of salt buffer")); + + /* Skip magic bytes, set by callers */ + s_ptr += 3; + if ((rc = pg_snprintf(s_ptr, 18, "rounds=%lu$", count)) <= 0) + ereport(ERROR, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("cannot format salt string")); + + /* s_ptr should now be positioned at the start of the salt string */ + s_ptr += rc; + + /* + * Normalize salt string + * + * size of input buffer was checked above to not exceed + * PX_SHACRYPT_SALT_LEN_MAX. + */ + for (int i = 0; i < size; i++) + { + *s_ptr = _crypt_itoa64[input[i] & 0x3f]; + s_ptr++; + } + + /* We're done */ + return output; +} + +/* gen_list->gen function for sha512 */ +char * +_crypt_gensalt_sha512_rn(unsigned long count, + char const *input, int size, + char *output, int output_size) +{ + memset(output, 0, output_size); + /* set magic byte for sha512crypt */ + output[0] = '$'; + output[1] = '6'; + output[2] = '$'; + + return _crypt_gensalt_sha(count, input, size, output, output_size); +} + +/* gen_list->gen function for sha256 */ +char * +_crypt_gensalt_sha256_rn(unsigned long count, + const char *input, int size, + char *output, int output_size) +{ + memset(output, 0, output_size); + /* set magic byte for sha256crypt */ + output[0] = '$'; + output[1] = '5'; + output[2] = '$'; + + return _crypt_gensalt_sha(count, input, size, output, output_size); +} diff --git a/contrib/pgcrypto/crypt-md5.c b/contrib/pgcrypto/crypt-md5.c index d38721a1010a4..33f93847a4273 100644 --- a/contrib/pgcrypto/crypt-md5.c +++ b/contrib/pgcrypto/crypt-md5.c @@ -33,11 +33,11 @@ _crypt_to64(char *s, unsigned long v, int n) char * px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen) { - static char *magic = "$1$"; /* This string is magic for this algorithm. - * Having it this way, we can get better later - * on */ - static char *p; - static const char *sp, + static const char *magic = "$1$"; /* This string is magic for this + * algorithm. Having it this way, we + * can get better later on */ + char *p; + const char *sp, *ep; unsigned char final[MD5_SIZE]; int sl, @@ -81,7 +81,7 @@ px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen) px_md_update(ctx, (const uint8 *) pw, strlen(pw)); /* Then our magic string */ - px_md_update(ctx, (uint8 *) magic, strlen(magic)); + px_md_update(ctx, (const uint8 *) magic, strlen(magic)); /* Then the raw salt */ px_md_update(ctx, (const uint8 *) sp, sl); diff --git a/contrib/pgcrypto/crypt-sha.c b/contrib/pgcrypto/crypt-sha.c new file mode 100644 index 0000000000000..7ec21771a83b7 --- /dev/null +++ b/contrib/pgcrypto/crypt-sha.c @@ -0,0 +1,642 @@ +/* + * contrib/pgcrypto/crypt-sha.c + * + * This implements shacrypt password hash functions and follows the + * public available reference implementation from + * + * https://www.akkadia.org/drepper/SHA-crypt.txt + * + * This code is public domain. + * + * Please see the inline comments for details about the algorithm. + * + * Basically the following code implements password hashing with sha256 and + * sha512 digest via OpenSSL. Additionally, an extended salt generation (see + * crypt-gensalt.c for details) is provided, which generates a salt suitable + * for either sha256crypt and sha512crypt password hash generation. + * + * Official identifiers for suitable password hashes used in salts are + * 5 : sha256crypt and + * 6 : sha512crypt + * + * The hashing code below supports and uses salt length up to 16 bytes. Longer + * input is possible, but any additional byte of the input is disregarded. + * gen_salt(), when called with a sha256crypt or sha512crypt identifier will + * always generate a 16 byte long salt string. + * + * Output is compatible with any sha256crypt and sha512crypt output + * generated by e.g. OpenSSL or libc crypt(). + * + * The described algorithm uses default computing rounds of 5000. Currently, + * even when no specific rounds specification is used, we always explicitly + * print out the rounds option flag with the final hash password string. + * + * The length of the specific password hash (without magic bytes and salt + * string) is: + * + * sha256crypt: 43 bytes and + * sha512crypt: 86 bytes. + * + * Overall hashed password length is: + * + * sha256crypt: 80 bytes and + * sha512crypt: 123 bytes + * + */ +#include "postgres.h" + +#include "common/string.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" + +#include "px-crypt.h" +#include "px.h" + +typedef enum +{ + PGCRYPTO_SHA256CRYPT = 0, + PGCRYPTO_SHA512CRYPT = 1, + PGCRYPTO_SHA_UNKOWN +} PGCRYPTO_SHA_t; + +static const char _crypt_itoa64[64 + 1] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +/* + * Modern UNIX password, based on SHA crypt hashes + */ +char * +px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstlen) +{ + static const char rounds_prefix[] = "rounds="; + static const char *magic_bytes[2] = {"$5$", "$6$"}; + + /* Used to create the password hash string */ + StringInfo out_buf = NULL; + + PGCRYPTO_SHA_t type = PGCRYPTO_SHA_UNKOWN; + PX_MD *digestA = NULL; + PX_MD *digestB = NULL; + int err; + + const char *dec_salt_binary; /* pointer into the real salt string */ + StringInfo decoded_salt = NULL; /* decoded salt string */ + unsigned char sha_buf[PX_SHACRYPT_DIGEST_MAX_LEN]; + + /* temporary buffer for digests */ + unsigned char sha_buf_tmp[PX_SHACRYPT_DIGEST_MAX_LEN]; + char rounds_custom = 0; + char *p_bytes = NULL; + char *s_bytes = NULL; + char *cp = NULL; + const char *fp = NULL; /* intermediate pointer within salt string */ + const char *ep = NULL; /* holds pointer to the end of the salt string */ + size_t buf_size = 0; /* buffer size for sha256crypt/sha512crypt */ + unsigned int block; /* number of bytes processed */ + uint32 rounds = PX_SHACRYPT_ROUNDS_DEFAULT; + unsigned int len, + salt_len = 0; + + /* Sanity checks */ + if (!passwd) + return NULL; + + if (pw == NULL) + elog(ERROR, "null value for password rejected"); + + if (salt == NULL) + elog(ERROR, "null value for salt rejected"); + + /* + * Make sure result buffers are large enough. + */ + if (dstlen < PX_SHACRYPT_BUF_LEN) + elog(ERROR, "insufficient result buffer size to encrypt password"); + + /* Init result buffer */ + out_buf = makeStringInfoExt(PX_SHACRYPT_BUF_LEN); + decoded_salt = makeStringInfoExt(PX_SHACRYPT_SALT_MAX_LEN); + + /* Init contents of buffers properly */ + memset(&sha_buf, '\0', sizeof(sha_buf)); + memset(&sha_buf_tmp, '\0', sizeof(sha_buf_tmp)); + + /* + * Decode the salt string. We need to know how many rounds and which + * digest we have to use to hash the password. + */ + len = strlen(pw); + dec_salt_binary = salt; + + /* + * Analyze and prepare the salt string + * + * The magic string should be specified in the first three bytes of the + * salt string. Do some sanity checks first. + */ + if (strlen(dec_salt_binary) < 3) + ereport(ERROR, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid salt")); + + /* + * Check format of magic bytes. These should define either 5=sha256crypt + * or 6=sha512crypt in the second byte, enclosed by ascii dollar signs. + */ + if ((dec_salt_binary[0] != '$') || (dec_salt_binary[2] != '$')) + ereport(ERROR, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid format of salt"), + errhint("magic byte format for shacrypt is either \"$5$\" or \"$6$\"")); + + /* + * Check magic byte for supported shacrypt digest. + * + * We're just interested in the very first 3 bytes of the salt string, + * since this defines the digest length to use. + */ + if (strncmp(dec_salt_binary, magic_bytes[0], strlen(magic_bytes[0])) == 0) + { + type = PGCRYPTO_SHA256CRYPT; + dec_salt_binary += strlen(magic_bytes[0]); + } + else if (strncmp(dec_salt_binary, magic_bytes[1], strlen(magic_bytes[1])) == 0) + { + type = PGCRYPTO_SHA512CRYPT; + dec_salt_binary += strlen(magic_bytes[1]); + } + + /* + * dec_salt_binary pointer is positioned after the magic bytes now + * + * We extract any options in the following code branch. The only optional + * setting we need to take care of is the "rounds" option. Note that the + * salt generator already checked for invalid settings before, but we need + * to do it here again to protect against injection of wrong values when + * called without the generator. + * + * If there is any garbage added after the magic byte and the options/salt + * string, we don't treat this special: This is just absorbed as part of + * the salt with up to PX_SHACRYPT_SALT_LEN_MAX. + * + * Unknown magic byte is handled further below. + */ + if (strncmp(dec_salt_binary, + rounds_prefix, sizeof(rounds_prefix) - 1) == 0) + { + const char *num = dec_salt_binary + sizeof(rounds_prefix) - 1; + char *endp; + int srounds = strtoint(num, &endp, 10); + + if (*endp != '$') + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("could not parse salt options")); + + dec_salt_binary = endp + 1; + + /* + * We violate supported lower or upper bound of rounds, but in this + * case we change this value to the supported lower or upper value. We + * don't do this silently and print a NOTICE in such a case. + * + * Note that a salt string generated with gen_salt() would never + * generated such a salt string, since it would error out. + * + * But Drepper's upstream reference implementation supports this when + * passing the salt string directly, so we maintain compatibility. + */ + if (srounds > PX_SHACRYPT_ROUNDS_MAX) + { + ereport(NOTICE, + errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("rounds=%d exceeds maximum supported value (%d), using %d instead", + srounds, PX_SHACRYPT_ROUNDS_MAX, + PX_SHACRYPT_ROUNDS_MAX)); + srounds = PX_SHACRYPT_ROUNDS_MAX; + } + else if (srounds < PX_SHACRYPT_ROUNDS_MIN) + { + ereport(NOTICE, + errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("rounds=%d is below supported value (%d), using %d instead", + srounds, PX_SHACRYPT_ROUNDS_MIN, + PX_SHACRYPT_ROUNDS_MIN)); + srounds = PX_SHACRYPT_ROUNDS_MIN; + } + + rounds = (uint32) srounds; + rounds_custom = 1; + } + + /* + * Choose the correct digest length and add the magic bytes to the result + * buffer. Also handle possible invalid magic byte we've extracted above. + */ + switch (type) + { + case PGCRYPTO_SHA256CRYPT: + { + /* Two PX_MD objects required */ + err = px_find_digest("sha256", &digestA); + if (err) + goto error; + + err = px_find_digest("sha256", &digestB); + if (err) + goto error; + + /* digest buffer length is 32 for sha256 */ + buf_size = 32; + + appendStringInfoString(out_buf, magic_bytes[0]); + break; + } + + case PGCRYPTO_SHA512CRYPT: + { + /* Two PX_MD objects required */ + err = px_find_digest("sha512", &digestA); + if (err) + goto error; + + err = px_find_digest("sha512", &digestB); + if (err) + goto error; + + buf_size = PX_SHACRYPT_DIGEST_MAX_LEN; + + appendStringInfoString(out_buf, magic_bytes[1]); + break; + } + + case PGCRYPTO_SHA_UNKOWN: + elog(ERROR, "unknown crypt identifier \"%c\"", salt[1]); + } + + if (rounds_custom > 0) + appendStringInfo(out_buf, "rounds=%u$", rounds); + + /* + * We need the real decoded salt string from salt input, this is every + * character before the last '$' in the preamble. Append every compatible + * character up to PX_SHACRYPT_SALT_MAX_LEN to the result buffer. Note + * that depending on the input, there might be no '$' marker after the + * salt, when there is no password hash attached at the end. + * + * We try hard to recognize mistakes, but since we might get an input + * string which might also have the password hash after the salt string + * section we give up as soon we reach the end of the input or if there + * are any bytes consumed for the salt string until we reach the first '$' + * marker thereafter. + */ + for (ep = dec_salt_binary; + *ep && ep < (dec_salt_binary + PX_SHACRYPT_SALT_MAX_LEN); + ep++) + { + /* + * Filter out any string which shouldn't be here. + * + * First check for accidentally embedded magic strings here. We don't + * support '$' in salt strings anyways and seeing a magic byte trying + * to identify shacrypt hashes might indicate that something went + * wrong when generating this salt string. Note that we later check + * for non-supported literals anyways, but any '$' here confuses us at + * this point. + */ + fp = strstr(dec_salt_binary, magic_bytes[0]); + if (fp != NULL) + elog(ERROR, "bogus magic byte found in salt string"); + + fp = strstr(dec_salt_binary, magic_bytes[1]); + if (fp != NULL) + elog(ERROR, "bogus magic byte found in salt string"); + + /* + * This looks very strict, but we assume the caller did something + * wrong when we see a "rounds=" option here. + */ + fp = strstr(dec_salt_binary, rounds_prefix); + if (fp != NULL) + elog(ERROR, "invalid rounds option specified in salt string"); + + if (*ep != '$') + { + if (strchr(_crypt_itoa64, *ep) != NULL) + appendStringInfoCharMacro(decoded_salt, *ep); + else + ereport(ERROR, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid character in salt string: \"%.*s\"", + pg_mblen(ep), ep)); + } + else + { + /* + * We encountered a '$' marker. Check if we already absorbed some + * bytes from input. If true, we are optimistic and terminate at + * this stage. If not, we try further. + * + * If we already consumed enough bytes for the salt string, + * everything that is after this marker is considered to be part + * of an optionally specified password hash and ignored. + */ + if (decoded_salt->len > 0) + break; + } + } + + salt_len = decoded_salt->len; + appendStringInfoString(out_buf, decoded_salt->data); + elog(DEBUG1, "using salt \"%s\", salt len = %d, rounds = %u", + decoded_salt->data, decoded_salt->len, rounds); + + /* + * Sanity check: at this point the salt string buffer must not exceed + * expected size. + */ + if (out_buf->len > (3 + 17 * rounds_custom + salt_len)) + elog(ERROR, "unexpected length of salt string"); + + /*- + * 1. Start digest A + * 2. Add the password string to digest A + * 3. Add the salt to digest A + */ + px_md_update(digestA, (const unsigned char *) pw, len); + px_md_update(digestA, (const unsigned char *) decoded_salt->data, salt_len); + + /*- + * 4. Create digest B + * 5. Add password to digest B + * 6. Add the salt string to digest B + * 7. Add the password again to digest B + * 8. Finalize digest B + */ + px_md_update(digestB, (const unsigned char *) pw, len); + px_md_update(digestB, (const unsigned char *) dec_salt_binary, salt_len); + px_md_update(digestB, (const unsigned char *) pw, len); + px_md_finish(digestB, sha_buf); + + /* + * 9. For each block (excluding the NULL byte), add digest B to digest A. + */ + for (block = len; block > buf_size; block -= buf_size) + px_md_update(digestA, sha_buf, buf_size); + + /*- + * 10. For the remaining N bytes of the password string, add the first N + * bytes of digest B to A. + */ + px_md_update(digestA, sha_buf, block); + + /*- + * 11. For each bit of the binary representation of the length of the + * password string up to and including the highest 1-digit, starting from + * to lowest bit position (numeric value 1) + * + * a) for a 1-digit add digest B (sha_buf) to digest A + * b) for a 0-digit add the password string + */ + block = len; + while (block) + { + px_md_update(digestA, + (block & 1) ? sha_buf : (const unsigned char *) pw, + (block & 1) ? buf_size : len); + + /* right shift to next byte */ + block >>= 1; + } + + /* 12. Finalize digest A */ + px_md_finish(digestA, sha_buf); + + /* 13. Start digest DP */ + px_md_reset(digestB); + + /*- + * 14 Add every byte of the password string (excluding trailing NULL) + * to the digest DP + */ + for (block = len; block > 0; block--) + px_md_update(digestB, (const unsigned char *) pw, len); + + /* 15. Finalize digest DP */ + px_md_finish(digestB, sha_buf_tmp); + + /*- + * 16. produce byte sequence P with same length as password. + * a) for each block of 32 or 64 bytes of length of the password + * string the entire digest DP is used + * b) for the remaining N (up to 31 or 63) bytes use the + * first N bytes of digest DP + */ + if ((p_bytes = palloc0(len)) == NULL) + { + goto error; + } + + /* N step of 16, copy over the bytes from password */ + for (cp = p_bytes, block = len; block > buf_size; block -= buf_size, cp += buf_size) + memcpy(cp, sha_buf_tmp, buf_size); + memcpy(cp, sha_buf_tmp, block); + + /* + * 17. Start digest DS + */ + px_md_reset(digestB); + + /*- + * 18. Repeat the following 16+A[0] times, where A[0] represents the first + * byte in digest A interpreted as an 8-bit unsigned value + * add the salt to digest DS + */ + for (block = 16 + sha_buf[0]; block > 0; block--) + px_md_update(digestB, (const unsigned char *) dec_salt_binary, salt_len); + + /* + * 19. Finalize digest DS + */ + px_md_finish(digestB, sha_buf_tmp); + + /*- + * 20. Produce byte sequence S of the same length as the salt string where + * + * a) for each block of 32 or 64 bytes of length of the salt string the + * entire digest DS is used + * + * b) for the remaining N (up to 31 or 63) bytes use the first N + * bytes of digest DS + */ + if ((s_bytes = palloc0(salt_len)) == NULL) + goto error; + + for (cp = s_bytes, block = salt_len; block > buf_size; block -= buf_size, cp += buf_size) + memcpy(cp, sha_buf_tmp, buf_size); + memcpy(cp, sha_buf_tmp, block); + + /* Make sure we don't leave something important behind */ + px_memset(&sha_buf_tmp, 0, sizeof sha_buf); + + /*- + * 21. Repeat a loop according to the number specified in the rounds= + * specification in the salt (or the default value if none is + * present). Each round is numbered, starting with 0 and up to N-1. + * + * The loop uses a digest as input. In the first round it is the + * digest produced in step 12. In the latter steps it is the digest + * produced in step 21.h of the previous round. The following text + * uses the notation "digest A/B" to describe this behavior. + */ + for (block = 0; block < rounds; block++) + { + /* + * Make it possible to abort in case large values for "rounds" are + * specified. + */ + CHECK_FOR_INTERRUPTS(); + + /* a) start digest B */ + px_md_reset(digestB); + + /*- + * b) for odd round numbers add the byte sequence P to digest B + * c) for even round numbers add digest A/B + */ + px_md_update(digestB, + (block & 1) ? (const unsigned char *) p_bytes : sha_buf, + (block & 1) ? len : buf_size); + + /* d) for all round numbers not divisible by 3 add the byte sequence S */ + if ((block % 3) != 0) + px_md_update(digestB, (const unsigned char *) s_bytes, salt_len); + + /* e) for all round numbers not divisible by 7 add the byte sequence P */ + if ((block % 7) != 0) + px_md_update(digestB, (const unsigned char *) p_bytes, len); + + /*- + * f) for odd round numbers add digest A/C + * g) for even round numbers add the byte sequence P + */ + px_md_update(digestB, + (block & 1) ? sha_buf : (const unsigned char *) p_bytes, + (block & 1) ? buf_size : len); + + /* h) finish digest C. */ + px_md_finish(digestB, sha_buf); + } + + px_md_free(digestA); + px_md_free(digestB); + + digestA = NULL; + digestB = NULL; + + pfree(s_bytes); + pfree(p_bytes); + + s_bytes = NULL; + p_bytes = NULL; + + /* prepare final result buffer */ + appendStringInfoCharMacro(out_buf, '$'); + +#define b64_from_24bit(B2, B1, B0, N) \ + do { \ + unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ + int i = (N); \ + while (i-- > 0) \ + { \ + appendStringInfoCharMacro(out_buf, _crypt_itoa64[w & 0x3f]); \ + w >>= 6; \ + } \ + } while (0) + + switch (type) + { + case PGCRYPTO_SHA256CRYPT: + { + b64_from_24bit(sha_buf[0], sha_buf[10], sha_buf[20], 4); + b64_from_24bit(sha_buf[21], sha_buf[1], sha_buf[11], 4); + b64_from_24bit(sha_buf[12], sha_buf[22], sha_buf[2], 4); + b64_from_24bit(sha_buf[3], sha_buf[13], sha_buf[23], 4); + b64_from_24bit(sha_buf[24], sha_buf[4], sha_buf[14], 4); + b64_from_24bit(sha_buf[15], sha_buf[25], sha_buf[5], 4); + b64_from_24bit(sha_buf[6], sha_buf[16], sha_buf[26], 4); + b64_from_24bit(sha_buf[27], sha_buf[7], sha_buf[17], 4); + b64_from_24bit(sha_buf[18], sha_buf[28], sha_buf[8], 4); + b64_from_24bit(sha_buf[9], sha_buf[19], sha_buf[29], 4); + b64_from_24bit(0, sha_buf[31], sha_buf[30], 3); + + break; + } + + case PGCRYPTO_SHA512CRYPT: + { + b64_from_24bit(sha_buf[0], sha_buf[21], sha_buf[42], 4); + b64_from_24bit(sha_buf[22], sha_buf[43], sha_buf[1], 4); + b64_from_24bit(sha_buf[44], sha_buf[2], sha_buf[23], 4); + b64_from_24bit(sha_buf[3], sha_buf[24], sha_buf[45], 4); + b64_from_24bit(sha_buf[25], sha_buf[46], sha_buf[4], 4); + b64_from_24bit(sha_buf[47], sha_buf[5], sha_buf[26], 4); + b64_from_24bit(sha_buf[6], sha_buf[27], sha_buf[48], 4); + b64_from_24bit(sha_buf[28], sha_buf[49], sha_buf[7], 4); + b64_from_24bit(sha_buf[50], sha_buf[8], sha_buf[29], 4); + b64_from_24bit(sha_buf[9], sha_buf[30], sha_buf[51], 4); + b64_from_24bit(sha_buf[31], sha_buf[52], sha_buf[10], 4); + b64_from_24bit(sha_buf[53], sha_buf[11], sha_buf[32], 4); + b64_from_24bit(sha_buf[12], sha_buf[33], sha_buf[54], 4); + b64_from_24bit(sha_buf[34], sha_buf[55], sha_buf[13], 4); + b64_from_24bit(sha_buf[56], sha_buf[14], sha_buf[35], 4); + b64_from_24bit(sha_buf[15], sha_buf[36], sha_buf[57], 4); + b64_from_24bit(sha_buf[37], sha_buf[58], sha_buf[16], 4); + b64_from_24bit(sha_buf[59], sha_buf[17], sha_buf[38], 4); + b64_from_24bit(sha_buf[18], sha_buf[39], sha_buf[60], 4); + b64_from_24bit(sha_buf[40], sha_buf[61], sha_buf[19], 4); + b64_from_24bit(sha_buf[62], sha_buf[20], sha_buf[41], 4); + b64_from_24bit(0, 0, sha_buf[63], 2); + + break; + } + + case PGCRYPTO_SHA_UNKOWN: + /* we shouldn't land here ... */ + elog(ERROR, "unsupported digest length"); + } + + /* + * Copy over result to specified buffer. + * + * The passwd character buffer should have at least PX_SHACRYPT_BUF_LEN + * allocated, since we checked above if dstlen is smaller than + * PX_SHACRYPT_BUF_LEN (which also includes the NULL byte). + * + * In that case we would have failed above already. + */ + memcpy(passwd, out_buf->data, out_buf->len); + + /* make sure nothing important is left behind */ + px_memset(&sha_buf, 0, sizeof sha_buf); + destroyStringInfo(out_buf); + destroyStringInfo(decoded_salt); + + /* ...and we're done */ + return passwd; + +error: + if (digestA != NULL) + px_md_free(digestA); + + if (digestB != NULL) + px_md_free(digestB); + + destroyStringInfo(out_buf); + destroyStringInfo(decoded_salt); + + ereport(ERROR, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("cannot create encrypted password")); + return NULL; /* keep compiler quiet */ +} diff --git a/contrib/pgcrypto/expected/crypt-des.out b/contrib/pgcrypto/expected/crypt-des.out index a462dcd580a89..70ca7b357b216 100644 --- a/contrib/pgcrypto/expected/crypt-des.out +++ b/contrib/pgcrypto/expected/crypt-des.out @@ -28,4 +28,11 @@ FROM ctest; t (1 row) +-- check disabling of built in crypto functions +SET pgcrypto.builtin_crypto_enabled = off; +UPDATE ctest SET salt = gen_salt('des'); +ERROR: use of built-in crypto functions is disabled +UPDATE ctest SET res = crypt(data, salt); +ERROR: use of built-in crypto functions is disabled +RESET pgcrypto.builtin_crypto_enabled; DROP TABLE ctest; diff --git a/contrib/pgcrypto/expected/crypt-shacrypt.out b/contrib/pgcrypto/expected/crypt-shacrypt.out new file mode 100644 index 0000000000000..f3b76d5e9136c --- /dev/null +++ b/contrib/pgcrypto/expected/crypt-shacrypt.out @@ -0,0 +1,196 @@ +-- +-- crypt() and gensalt: sha256crypt, sha512crypt +-- +-- $5$ is sha256crypt +SELECT crypt('', '$5$Szzz0yzz'); + crypt +--------------------------------------------------------- + $5$Szzz0yzz$cA.ZFZKqblRYjdsbrWtVTYa/qSwPQnt2uh0LBtyYAAD +(1 row) + +SELECT crypt('foox', '$5$Szzz0yzz'); + crypt +--------------------------------------------------------- + $5$Szzz0yzz$7hI0rUWkO2QdBkzamh.vP.MIPlbZiwSvu2smhSi6064 +(1 row) + +CREATE TABLE ctest (data text, res text, salt text); +INSERT INTO ctest VALUES ('password', '', ''); +-- generate a salt for sha256crypt, default rounds +UPDATE ctest SET salt = gen_salt('sha256crypt'); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + worked +-------- + t +(1 row) + +-- generate a salt for sha256crypt, rounds 9999 +UPDATE ctest SET salt = gen_salt('sha256crypt', 9999); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + worked +-------- + t +(1 row) + +-- should fail, below supported minimum rounds value +UPDATE ctest SET salt = gen_salt('sha256crypt', 10); +ERROR: gen_salt: Incorrect number of rounds +-- should fail, exceeds supported maximum rounds value +UPDATE ctest SET salt = gen_salt('sha256crypt', 1000000000); +ERROR: gen_salt: Incorrect number of rounds +TRUNCATE ctest; +-- $6$ is sha512crypt +SELECT crypt('', '$6$Szzz0yzz'); + crypt +---------------------------------------------------------------------------------------------------- + $6$Szzz0yzz$EGj.JLAovFyAtCJx3YD1DXD1yTXoO9gv4qgLyHBsJJ1lkpnLB8ZPHekm1qXjJCOBc/8thCuHpxNN8Y5xzRYU5. +(1 row) + +SELECT crypt('foox', '$6$Szzz0yzz'); + crypt +---------------------------------------------------------------------------------------------------- + $6$Szzz0yzz$KqDw1Y8kze.VFapkvTc9Y5fbqzltjeRz1aPGC/pkHRhFQZ2aM6PmZpXQjcD7AOH88Bq0CSD.VlmymQzcBMEUl0 +(1 row) + +INSERT INTO ctest VALUES ('password', '', ''); +-- generate a salt for sha512crypt, default rounds +UPDATE ctest SET salt = gen_salt('sha512crypt'); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + worked +-------- + t +(1 row) + +-- generate a salt for sha512crypt, rounds 9999 +UPDATE ctest SET salt = gen_salt('sha512crypt', 9999); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + worked +-------- + t +(1 row) + +-- should fail, below supported minimum rounds value +UPDATE ctest SET salt = gen_salt('sha512crypt', 10); +ERROR: gen_salt: Incorrect number of rounds +-- should fail, exceeds supported maximum rounds value +UPDATE ctest SET salt = gen_salt('sha512crypt', 1000000000); +ERROR: gen_salt: Incorrect number of rounds +-- Extended tests taken from public domain code at +-- https://www.akkadia.org/drepper/SHA-crypt.txt +-- +-- We adapt the tests defined there to make sure we are compatible with the reference +-- implementation. +-- This tests sha256crypt (magic byte $5$ with salt and rounds) +SELECT crypt('Hello world!', '$5$saltstring') + = '$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5' AS result; + result +-------- + t +(1 row) + +SELECT crypt('Hello world!', '$5$rounds=10000$saltstringsaltstring') + = '$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2.opqey6IcA' AS result; + result +-------- + t +(1 row) + +SELECT crypt('This is just a test', '$5$rounds=5000$toolongsaltstring') + = '$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8mGRcvxa5' AS result; + result +-------- + t +(1 row) + + SELECT crypt('a very much longer text to encrypt. This one even stretches over more' + 'than one line.', '$5$rounds=1400$anotherlongsaltstring') + = '$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12oP84Bnq1' AS result; + result +-------- + t +(1 row) + +SELECT crypt('we have a short salt string but not a short password', '$5$rounds=77777$short') + = '$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/' AS result; + result +-------- + t +(1 row) + +SELECT crypt('a short string', '$5$rounds=123456$asaltof16chars..') + = '$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/cZKmF/wJvD' AS result; + result +-------- + t +(1 row) + +SELECT crypt('the minimum number is still observed', '$5$rounds=10$roundstoolow') + = '$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL972bIC' AS result; +NOTICE: rounds=10 is below supported value (1000), using 1000 instead + result +-------- + t +(1 row) + +-- The following tests sha512crypt (magic byte $6$ with salt and rounds) +SELECT crypt('Hello world!', '$6$saltstring') + = '$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1' AS result; + result +-------- + t +(1 row) + +SELECT crypt('Hello world!', '$6$rounds=10000$saltstringsaltstring') + = '$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sbHbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v.' AS result; + result +-------- + t +(1 row) + +SELECT crypt('This is just a test', '$6$rounds=5000$toolongsaltstring') + = '$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQzQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0' AS result; + result +-------- + t +(1 row) + +SELECT crypt('a very much longer text to encrypt. This one even stretches over more' + 'than one line.', '$6$rounds=1400$anotherlongsaltstring') + = '$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wPvMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1' AS result; + result +-------- + t +(1 row) + +SELECT crypt('we have a short salt string but not a short password', '$6$rounds=77777$short') + = '$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0gge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0' AS result; + result +-------- + t +(1 row) + +SELECT crypt('a short string', '$6$rounds=123456$asaltof16chars..') + = '$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwcelCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1' AS result; + result +-------- + t +(1 row) + +SELECT crypt('the minimum number is still observed', '$6$rounds=10$roundstoolow') + = '$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX.' AS result; +NOTICE: rounds=10 is below supported value (1000), using 1000 instead + result +-------- + t +(1 row) + +-- cleanup +DROP TABLE ctest; diff --git a/contrib/pgcrypto/expected/rijndael.out b/contrib/pgcrypto/expected/rijndael.out index 015ba4430d962..28e28b989fd95 100644 --- a/contrib/pgcrypto/expected/rijndael.out +++ b/contrib/pgcrypto/expected/rijndael.out @@ -135,3 +135,121 @@ select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes') Lets try a longer message. (1 row) +-- cfb +SELECT encrypt( +'\x00112233445566778899aabbccddeeff', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', +'aes-cfb/pad:none'); + encrypt +------------------------------------ + \xf28122856e1cf9a7216a30d111f3997f +(1 row) + +-- without padding, input not multiple of block size +SELECT encrypt( +'\x00112233445566778899aabbccddeeff00', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', +'aes-cfb/pad:none'); + encrypt +-------------------------------------- + \xf28122856e1cf9a7216a30d111f3997fcb +(1 row) + +-- key padding +SELECT encrypt( +'\x0011223344', +'\x000102030405', +'aes-cfb'); + encrypt +-------------- + \x8145d1a0ef +(1 row) + +SELECT encrypt( +'\x0011223344', +'\x000102030405060708090a0b0c0d0e0f10111213', +'aes-cfb'); + encrypt +-------------- + \x52642c3b9c +(1 row) + +SELECT encrypt( +'\x0011223344', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b', +'aes-cfb'); + encrypt +-------------- + \xc93b4468a4 +(1 row) + +-- empty data +select encrypt('', 'foo', 'aes-cfb'); + encrypt +--------- + \x +(1 row) + +-- 10 bytes key +select encrypt('foo', '0123456789', 'aes-cfb'); + encrypt +---------- + \x6f8ced +(1 row) + +-- 22 bytes key +select encrypt('foo', '0123456789012345678901', 'aes-cfb'); + encrypt +---------- + \xfb47d2 +(1 row) + +-- decrypt +select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb'), '0123456', 'aes-cfb'), 'escape'); + encode +-------- + foo +(1 row) + +-- data not multiple of block size +select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb') || '\x00'::bytea, '0123456', 'aes-cfb'), 'escape'); + encode +--------- + foo\337 +(1 row) + +-- bad padding +-- (The input value is the result of encrypt_iv('abcdefghijklmnopqrstuvwxyz', '0123456', 'abcd', 'aes-cfb') +-- with the 16th byte changed (s/c5/d5/) to corrupt the padding of the last block.) +select encode(decrypt_iv('\xf9ad6817cb58d31dd9ba6571fbc4f55d56f65b631f0f437cb828', '0123456', 'abcd', 'aes-cfb'), 'escape'); + encode +------------------------------------------------- + abcdefghijklmnoq\243:\205o\x7F\x05z\276\x07\332 +(1 row) + +-- iv +select encrypt_iv('foo', '0123456', 'abcd', 'aes-cfb'); + encrypt_iv +------------ + \xfea064 +(1 row) + +select encode(decrypt_iv('\xfea064', '0123456', 'abcd', 'aes-cfb'), 'escape'); + encode +-------- + foo +(1 row) + +-- long message +select encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'); + encrypt +-------------------------------------------------------- + \x4586f6c6351055051f723b1b0aad52c877eaf0c421d18fd73a28 +(1 row) + +select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'), '0123456789', 'aes-cfb'), 'escape'); + encode +---------------------------- + Lets try a longer message. +(1 row) + diff --git a/contrib/pgcrypto/meson.build b/contrib/pgcrypto/meson.build index 85948915482c3..7d5ef9b6d3231 100644 --- a/contrib/pgcrypto/meson.build +++ b/contrib/pgcrypto/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not ssl.found() subdir_done() @@ -9,6 +9,7 @@ pgcrypto_sources = files( 'crypt-des.c', 'crypt-gensalt.c', 'crypt-md5.c', + 'crypt-sha.c', 'mbuf.c', 'pgcrypto.c', 'pgp-armor.c', @@ -52,6 +53,7 @@ pgcrypto_regress = [ 'pgp-pubkey-decrypt', 'pgp-pubkey-encrypt', 'pgp-info', + 'crypt-shacrypt' ] pgcrypto_openssl_sources = files( @@ -93,6 +95,7 @@ install_data( 'pgcrypto--1.1--1.2.sql', 'pgcrypto--1.2--1.3.sql', 'pgcrypto--1.3.sql', + 'pgcrypto--1.3--1.4.sql', 'pgcrypto.control', kwargs: contrib_data_args, ) diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index 8259de5e393d9..f179e80c8429e 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.c @@ -31,6 +31,7 @@ #include "postgres.h" +#include #include #include #include @@ -154,8 +155,6 @@ digest_free(PX_MD *h) pfree(h); } -static int px_openssl_initialized = 0; - /* PUBLIC functions */ int @@ -166,12 +165,6 @@ px_find_digest(const char *name, PX_MD **res) PX_MD *h; OSSLDigest *digest; - if (!px_openssl_initialized) - { - px_openssl_initialized = 1; - OpenSSL_add_all_algorithms(); - } - md = EVP_get_digestbyname(name); if (md == NULL) return PXE_NO_HASH; @@ -211,7 +204,7 @@ px_find_digest(const char *name, PX_MD **res) h->update = digest_update; h->finish = digest_finish; h->free = digest_free; - h->p.ptr = (void *) digest; + h->p.ptr = digest; *res = h; return 0; @@ -624,6 +617,36 @@ ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv return err; } +static int +ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv) +{ + OSSLCipher *od = c->ptr; + int err; + + err = ossl_aes_init(c, key, klen, iv); + if (err) + return err; + + switch (od->klen) + { + case 128 / 8: + od->evp_ciph = EVP_aes_128_cfb(); + break; + case 192 / 8: + od->evp_ciph = EVP_aes_192_cfb(); + break; + case 256 / 8: + od->evp_ciph = EVP_aes_256_cfb(); + break; + default: + /* shouldn't happen */ + err = PXE_CIPHER_INIT; + break; + } + + return err; +} + /* * aliases */ @@ -643,6 +666,7 @@ static PX_Alias ossl_aliases[] = { {"rijndael", "aes-cbc"}, {"rijndael-cbc", "aes-cbc"}, {"rijndael-ecb", "aes-ecb"}, + {"rijndael-cfb", "aes-cfb"}, {NULL} }; @@ -714,6 +738,13 @@ static const struct ossl_cipher ossl_aes_cbc = { 128 / 8, 256 / 8 }; +static const struct ossl_cipher ossl_aes_cfb = { + ossl_aes_cfb_init, + NULL, /* EVP_aes_XXX_cfb(), determined in init + * function */ + 128 / 8, 256 / 8 +}; + /* * Special handlers */ @@ -735,6 +766,7 @@ static const struct ossl_cipher_lookup ossl_cipher_types[] = { {"cast5-cbc", &ossl_cast_cbc}, {"aes-ecb", &ossl_aes_ecb}, {"aes-cbc", &ossl_aes_cbc}, + {"aes-cfb", &ossl_aes_cfb}, {NULL} }; @@ -802,3 +834,55 @@ ResOwnerReleaseOSSLCipher(Datum res) { free_openssl_cipher((OSSLCipher *) DatumGetPointer(res)); } + +/* + * CheckFIPSMode + * + * Returns the FIPS mode of the underlying OpenSSL installation. + */ +bool +CheckFIPSMode(void) +{ + int fips_enabled = 0; + + /* + * EVP_default_properties_is_fips_enabled was added in OpenSSL 3.0, before + * that FIPS_mode() was used to test for FIPS being enabled. The last + * upstream OpenSSL version before 3.0 which supported FIPS was 1.0.2, but + * there are forks of 1.1.1 which are FIPS validated so we still need to + * test with FIPS_mode() even though we don't support 1.0.2. + */ + fips_enabled = +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_default_properties_is_fips_enabled(NULL); +#else + FIPS_mode(); +#endif + + return (fips_enabled == 1); +} + +/* + * CheckBuiltinCryptoMode + * + * Function for erroring out in case built-in crypto is executed when the user + * has disabled it. If builtin_crypto_enabled is set to BC_OFF or BC_FIPS and + * OpenSSL is operating in FIPS mode the function will error out, else the + * query executing built-in crypto can proceed. + */ +void +CheckBuiltinCryptoMode(void) +{ + if (builtin_crypto_enabled == BC_ON) + return; + + if (builtin_crypto_enabled == BC_OFF) + ereport(ERROR, + errmsg("use of built-in crypto functions is disabled")); + + Assert(builtin_crypto_enabled == BC_FIPS); + + if (CheckFIPSMode() == true) + ereport(ERROR, + errmsg("use of non-FIPS validated crypto not allowed when OpenSSL is in FIPS mode")); +} diff --git a/contrib/pgcrypto/pgcrypto--1.3--1.4.sql b/contrib/pgcrypto/pgcrypto--1.3--1.4.sql new file mode 100644 index 0000000000000..b942bde842789 --- /dev/null +++ b/contrib/pgcrypto/pgcrypto--1.3--1.4.sql @@ -0,0 +1,9 @@ +/* contrib/pgcrypto/pgcrypto--1.3--1.4.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pgcrypto UPDATE TO '1.4'" to load this file. \quit + +CREATE FUNCTION fips_mode() +RETURNS bool +AS 'MODULE_PATHNAME', 'pg_check_fipsmode' +LANGUAGE C VOLATILE STRICT PARALLEL SAFE; diff --git a/contrib/pgcrypto/pgcrypto.c b/contrib/pgcrypto/pgcrypto.c index 96447c5757761..9ecbbd2e2f869 100644 --- a/contrib/pgcrypto/pgcrypto.c +++ b/contrib/pgcrypto/pgcrypto.c @@ -38,17 +38,50 @@ #include "px-crypt.h" #include "px.h" #include "utils/builtins.h" -#include "utils/uuid.h" +#include "utils/guc.h" #include "varatt.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pgcrypto", + .version = PG_VERSION +); /* private stuff */ +static const struct config_enum_entry builtin_crypto_options[] = { + {"on", BC_ON, false}, + {"off", BC_OFF, false}, + {"fips", BC_FIPS, false}, + {NULL, 0, false} +}; + typedef int (*PFN) (const char *name, void **res); static void *find_provider(text *name, PFN provider_lookup, const char *desc, int silent); +int builtin_crypto_enabled = BC_ON; + +/* + * Entrypoint of this module. + */ +void +_PG_init(void) +{ + DefineCustomEnumVariable("pgcrypto.builtin_crypto_enabled", + "Sets if builtin crypto functions are enabled.", + "\"on\" enables builtin crypto, \"off\" unconditionally disables and \"fips\" " + "will disable builtin crypto if OpenSSL is in FIPS mode", + &builtin_crypto_enabled, + BC_ON, + builtin_crypto_options, + PGC_SUSET, + 0, + NULL, + NULL, + NULL); + MarkGUCPrefixReserved("pgcrypto"); +} + /* SQL function: hash(bytea, text) returns bytea */ PG_FUNCTION_INFO_V1(pg_digest); @@ -451,6 +484,14 @@ pg_random_uuid(PG_FUNCTION_ARGS) return gen_random_uuid(fcinfo); } +PG_FUNCTION_INFO_V1(pg_check_fipsmode); + +Datum +pg_check_fipsmode(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(CheckFIPSMode()); +} + static void * find_provider(text *name, PFN provider_lookup, diff --git a/contrib/pgcrypto/pgcrypto.control b/contrib/pgcrypto/pgcrypto.control index d2151d3bc4be5..fcdd0b46f5b2d 100644 --- a/contrib/pgcrypto/pgcrypto.control +++ b/contrib/pgcrypto/pgcrypto.control @@ -1,6 +1,6 @@ # pgcrypto extension comment = 'cryptographic functions' -default_version = '1.3' +default_version = '1.4' module_pathname = '$libdir/pgcrypto' relocatable = true trusted = true diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c index 0913ff2c1bc2e..d7729eec9bcae 100644 --- a/contrib/pgcrypto/px-crypt.c +++ b/contrib/pgcrypto/px-crypt.c @@ -67,6 +67,16 @@ run_crypt_bf(const char *psw, const char *salt, return res; } +static char * +run_crypt_sha(const char *psw, const char *salt, + char *buf, unsigned len) +{ + char *res; + + res = px_crypt_shacrypt(psw, salt, buf, len); + return res; +} + struct px_crypt_algo { char *id; @@ -81,6 +91,8 @@ static const struct px_crypt_algo {"$2x$", 4, run_crypt_bf}, {"$2$", 3, NULL}, /* N/A */ {"$1$", 3, run_crypt_md5}, + {"$5$", 3, run_crypt_sha}, + {"$6$", 3, run_crypt_sha}, {"_", 1, run_crypt_des}, {"", 0, run_crypt_des}, {NULL, 0, NULL} @@ -91,6 +103,8 @@ px_crypt(const char *psw, const char *salt, char *buf, unsigned len) { const struct px_crypt_algo *c; + CheckBuiltinCryptoMode(); + for (c = px_crypt_list; c->id; c++) { if (!c->id_len) @@ -125,6 +139,16 @@ static struct generator gen_list[] = { {"md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0}, {"xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF}, {"bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31}, + { + "sha256crypt", _crypt_gensalt_sha256_rn, + PX_SHACRYPT_SALT_MAX_LEN, PX_SHACRYPT_ROUNDS_DEFAULT, + PX_SHACRYPT_ROUNDS_MIN, PX_SHACRYPT_ROUNDS_MAX + }, + { + "sha512crypt", _crypt_gensalt_sha512_rn, + PX_SHACRYPT_SALT_MAX_LEN, PX_SHACRYPT_ROUNDS_DEFAULT, + PX_SHACRYPT_ROUNDS_MIN, PX_SHACRYPT_ROUNDS_MAX + }, {NULL, NULL, 0, 0, 0, 0} }; @@ -135,6 +159,8 @@ px_gen_salt(const char *salt_type, char *buf, int rounds) char *p; char rbuf[16]; + CheckBuiltinCryptoMode(); + for (g = gen_list; g->name; g++) if (pg_strcasecmp(g->name, salt_type) == 0) break; diff --git a/contrib/pgcrypto/px-crypt.h b/contrib/pgcrypto/px-crypt.h index 54de806965530..bb03cf5592ad0 100644 --- a/contrib/pgcrypto/px-crypt.h +++ b/contrib/pgcrypto/px-crypt.h @@ -45,6 +45,30 @@ /* default for blowfish salt */ #define PX_BF_ROUNDS 6 +/* Maximum salt string length of shacrypt. */ +#define PX_SHACRYPT_SALT_MAX_LEN 16 + +/* SHA buffer length */ +#define PX_SHACRYPT_DIGEST_MAX_LEN 64 + +/* calculated buffer size of a buffer to store a shacrypt salt string */ +#define PX_SHACRYPT_SALT_BUF_LEN (3 + 7 + 10 + PX_SHACRYPT_SALT_MAX_LEN + 1) + +/* + * calculated buffer size of a buffer to store complete result of a shacrypt + * digest including salt + */ +#define PX_SHACRYPT_BUF_LEN (PX_SHACRYPT_SALT_BUF_LEN + 86 + 1) + +/* Default number of rounds of shacrypt if not explicitly specified. */ +#define PX_SHACRYPT_ROUNDS_DEFAULT 5000 + +/* Minimum number of rounds of shacrypt. */ +#define PX_SHACRYPT_ROUNDS_MIN 1000 + +/* Maximum number of rounds of shacrypt. */ +#define PX_SHACRYPT_ROUNDS_MAX 999999999 + /* * main interface */ @@ -64,6 +88,10 @@ char *_crypt_gensalt_md5_rn(unsigned long count, const char *input, int size, char *output, int output_size); char *_crypt_gensalt_blowfish_rn(unsigned long count, const char *input, int size, char *output, int output_size); +char *_crypt_gensalt_sha256_rn(unsigned long count, + const char *input, int size, char *output, int output_size); +char *_crypt_gensalt_sha512_rn(unsigned long count, + const char *input, int size, char *output, int output_size); /* disable 'extended DES crypt' */ /* #define DISABLE_XDES */ @@ -79,4 +107,7 @@ char *px_crypt_des(const char *key, const char *setting); char *px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen); +/* crypt-sha.c */ +char *px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstlen); + #endif /* _PX_CRYPT_H */ diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h index 471bb4ec7274c..4b81fceab8ec2 100644 --- a/contrib/pgcrypto/px.h +++ b/contrib/pgcrypto/px.h @@ -89,6 +89,12 @@ #define PXE_PGP_UNSUPPORTED_PUBALGO -122 #define PXE_PGP_MULTIPLE_SUBKEYS -123 +typedef enum BuiltinCryptoOptions +{ + BC_ON, + BC_OFF, + BC_FIPS, +} BuiltinCryptoOptions; typedef struct px_digest PX_MD; typedef struct px_alias PX_Alias; @@ -96,6 +102,8 @@ typedef struct px_hmac PX_HMAC; typedef struct px_cipher PX_Cipher; typedef struct px_combo PX_Combo; +extern int builtin_crypto_enabled; + struct px_digest { unsigned (*result_size) (PX_MD *h); @@ -173,7 +181,7 @@ int px_find_hmac(const char *name, PX_HMAC **res); int px_find_cipher(const char *name, PX_Cipher **res); int px_find_combo(const char *name, PX_Combo **res); -void px_THROW_ERROR(int err) pg_attribute_noreturn(); +pg_noreturn void px_THROW_ERROR(int err); const char *px_strerror(int err); const char *px_resolve_alias(const PX_Alias *list, const char *name); @@ -182,6 +190,9 @@ void px_set_debug_handler(void (*handler) (const char *)); void px_memset(void *ptr, int c, size_t len); +bool CheckFIPSMode(void); +void CheckBuiltinCryptoMode(void); + #ifdef PX_DEBUG void px_debug(const char *fmt,...) pg_attribute_printf(1, 2); #else diff --git a/contrib/pgcrypto/sql/crypt-des.sql b/contrib/pgcrypto/sql/crypt-des.sql index a85ec1e655510..58cc9d2720a1c 100644 --- a/contrib/pgcrypto/sql/crypt-des.sql +++ b/contrib/pgcrypto/sql/crypt-des.sql @@ -18,4 +18,10 @@ UPDATE ctest SET res = crypt(data, salt); SELECT res = crypt(data, res) AS "worked" FROM ctest; +-- check disabling of built in crypto functions +SET pgcrypto.builtin_crypto_enabled = off; +UPDATE ctest SET salt = gen_salt('des'); +UPDATE ctest SET res = crypt(data, salt); +RESET pgcrypto.builtin_crypto_enabled; + DROP TABLE ctest; diff --git a/contrib/pgcrypto/sql/crypt-shacrypt.sql b/contrib/pgcrypto/sql/crypt-shacrypt.sql new file mode 100644 index 0000000000000..3ee826f61aa6c --- /dev/null +++ b/contrib/pgcrypto/sql/crypt-shacrypt.sql @@ -0,0 +1,99 @@ +-- +-- crypt() and gensalt: sha256crypt, sha512crypt +-- + +-- $5$ is sha256crypt +SELECT crypt('', '$5$Szzz0yzz'); + +SELECT crypt('foox', '$5$Szzz0yzz'); + +CREATE TABLE ctest (data text, res text, salt text); +INSERT INTO ctest VALUES ('password', '', ''); + +-- generate a salt for sha256crypt, default rounds +UPDATE ctest SET salt = gen_salt('sha256crypt'); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + +-- generate a salt for sha256crypt, rounds 9999 +UPDATE ctest SET salt = gen_salt('sha256crypt', 9999); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + +-- should fail, below supported minimum rounds value +UPDATE ctest SET salt = gen_salt('sha256crypt', 10); + +-- should fail, exceeds supported maximum rounds value +UPDATE ctest SET salt = gen_salt('sha256crypt', 1000000000); + +TRUNCATE ctest; + +-- $6$ is sha512crypt +SELECT crypt('', '$6$Szzz0yzz'); + +SELECT crypt('foox', '$6$Szzz0yzz'); + +INSERT INTO ctest VALUES ('password', '', ''); + +-- generate a salt for sha512crypt, default rounds +UPDATE ctest SET salt = gen_salt('sha512crypt'); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + +-- generate a salt for sha512crypt, rounds 9999 +UPDATE ctest SET salt = gen_salt('sha512crypt', 9999); +UPDATE ctest SET res = crypt(data, salt); +SELECT res = crypt(data, res) AS "worked" +FROM ctest; + +-- should fail, below supported minimum rounds value +UPDATE ctest SET salt = gen_salt('sha512crypt', 10); + +-- should fail, exceeds supported maximum rounds value +UPDATE ctest SET salt = gen_salt('sha512crypt', 1000000000); + +-- Extended tests taken from public domain code at +-- https://www.akkadia.org/drepper/SHA-crypt.txt +-- +-- We adapt the tests defined there to make sure we are compatible with the reference +-- implementation. + +-- This tests sha256crypt (magic byte $5$ with salt and rounds) +SELECT crypt('Hello world!', '$5$saltstring') + = '$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5' AS result; +SELECT crypt('Hello world!', '$5$rounds=10000$saltstringsaltstring') + = '$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2.opqey6IcA' AS result; +SELECT crypt('This is just a test', '$5$rounds=5000$toolongsaltstring') + = '$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8mGRcvxa5' AS result; + SELECT crypt('a very much longer text to encrypt. This one even stretches over more' + 'than one line.', '$5$rounds=1400$anotherlongsaltstring') + = '$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12oP84Bnq1' AS result; +SELECT crypt('we have a short salt string but not a short password', '$5$rounds=77777$short') + = '$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/' AS result; +SELECT crypt('a short string', '$5$rounds=123456$asaltof16chars..') + = '$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/cZKmF/wJvD' AS result; +SELECT crypt('the minimum number is still observed', '$5$rounds=10$roundstoolow') + = '$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL972bIC' AS result; + +-- The following tests sha512crypt (magic byte $6$ with salt and rounds) +SELECT crypt('Hello world!', '$6$saltstring') + = '$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1' AS result; +SELECT crypt('Hello world!', '$6$rounds=10000$saltstringsaltstring') + = '$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sbHbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v.' AS result; +SELECT crypt('This is just a test', '$6$rounds=5000$toolongsaltstring') + = '$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQzQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0' AS result; +SELECT crypt('a very much longer text to encrypt. This one even stretches over more' + 'than one line.', '$6$rounds=1400$anotherlongsaltstring') + = '$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wPvMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1' AS result; +SELECT crypt('we have a short salt string but not a short password', '$6$rounds=77777$short') + = '$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0gge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0' AS result; +SELECT crypt('a short string', '$6$rounds=123456$asaltof16chars..') + = '$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwcelCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1' AS result; +SELECT crypt('the minimum number is still observed', '$6$rounds=10$roundstoolow') + = '$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1xhLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX.' AS result; + +-- cleanup +DROP TABLE ctest; diff --git a/contrib/pgcrypto/sql/rijndael.sql b/contrib/pgcrypto/sql/rijndael.sql index a27664199804e..de4e4da5e29ee 100644 --- a/contrib/pgcrypto/sql/rijndael.sql +++ b/contrib/pgcrypto/sql/rijndael.sql @@ -70,3 +70,56 @@ select encode(decrypt_iv('\x2c24cb7da91d6d5699801268b0f5adad', '0123456', 'abcd' -- long message select encrypt('Lets try a longer message.', '0123456789', 'aes'); select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes'), '0123456789', 'aes'), 'escape'); + +-- cfb +SELECT encrypt( +'\x00112233445566778899aabbccddeeff', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', +'aes-cfb/pad:none'); + +-- without padding, input not multiple of block size +SELECT encrypt( +'\x00112233445566778899aabbccddeeff00', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', +'aes-cfb/pad:none'); + +-- key padding + +SELECT encrypt( +'\x0011223344', +'\x000102030405', +'aes-cfb'); + +SELECT encrypt( +'\x0011223344', +'\x000102030405060708090a0b0c0d0e0f10111213', +'aes-cfb'); + +SELECT encrypt( +'\x0011223344', +'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b', +'aes-cfb'); + +-- empty data +select encrypt('', 'foo', 'aes-cfb'); +-- 10 bytes key +select encrypt('foo', '0123456789', 'aes-cfb'); +-- 22 bytes key +select encrypt('foo', '0123456789012345678901', 'aes-cfb'); + +-- decrypt +select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb'), '0123456', 'aes-cfb'), 'escape'); +-- data not multiple of block size +select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb') || '\x00'::bytea, '0123456', 'aes-cfb'), 'escape'); +-- bad padding +-- (The input value is the result of encrypt_iv('abcdefghijklmnopqrstuvwxyz', '0123456', 'abcd', 'aes-cfb') +-- with the 16th byte changed (s/c5/d5/) to corrupt the padding of the last block.) +select encode(decrypt_iv('\xf9ad6817cb58d31dd9ba6571fbc4f55d56f65b631f0f437cb828', '0123456', 'abcd', 'aes-cfb'), 'escape'); + +-- iv +select encrypt_iv('foo', '0123456', 'abcd', 'aes-cfb'); +select encode(decrypt_iv('\xfea064', '0123456', 'abcd', 'aes-cfb'), 'escape'); + +-- long message +select encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'); +select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'), '0123456789', 'aes-cfb'), 'escape'); diff --git a/contrib/pgrowlocks/meson.build b/contrib/pgrowlocks/meson.build index d1e73dc617ec1..6007a76ae754c 100644 --- a/contrib/pgrowlocks/meson.build +++ b/contrib/pgrowlocks/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgrowlocks_sources = files( 'pgrowlocks.c', diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c index adbc8279c3fdb..b75d80fa7a9c2 100644 --- a/contrib/pgrowlocks/pgrowlocks.c +++ b/contrib/pgrowlocks/pgrowlocks.c @@ -37,12 +37,15 @@ #include "storage/bufmgr.h" #include "storage/procarray.h" #include "utils/acl.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/varlena.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pgrowlocks", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(pgrowlocks); diff --git a/contrib/pgstattuple/expected/pgstattuple.out b/contrib/pgstattuple/expected/pgstattuple.out index 283856e109e64..9176dc98b6a9e 100644 --- a/contrib/pgstattuple/expected/pgstattuple.out +++ b/contrib/pgstattuple/expected/pgstattuple.out @@ -273,6 +273,31 @@ select pgstathashindex('test_partition_hash_idx'); (4,8,0,1,0,0,0,100) (1 row) +-- these should work for sequences +create sequence test_sequence; +select count(*) from pgstattuple('test_sequence'); + count +------- + 1 +(1 row) + +select pg_relpages('test_sequence'); + pg_relpages +------------- + 1 +(1 row) + +-- these should fail for sequences +select pgstatindex('test_sequence'); +ERROR: relation "test_sequence" is not a btree index +select pgstatginindex('test_sequence'); +ERROR: relation "test_sequence" is not a GIN index +select pgstathashindex('test_sequence'); +ERROR: relation "test_sequence" is not a hash index +select pgstattuple_approx('test_sequence'); +ERROR: relation "test_sequence" is of wrong relation kind +DETAIL: This operation is not supported for sequences. +drop sequence test_sequence; drop table test_partitioned; drop view test_view; drop foreign table test_foreign_table; diff --git a/contrib/pgstattuple/meson.build b/contrib/pgstattuple/meson.build index 72e8902e4410f..654245809e5d3 100644 --- a/contrib/pgstattuple/meson.build +++ b/contrib/pgstattuple/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgstattuple_sources = files( 'pgstatapprox.c', diff --git a/contrib/pgstattuple/pgstatapprox.c b/contrib/pgstattuple/pgstatapprox.c index c84c6423555e2..a59ff4e9d4fac 100644 --- a/contrib/pgstattuple/pgstatapprox.c +++ b/contrib/pgstattuple/pgstatapprox.c @@ -3,7 +3,7 @@ * pgstatapprox.c * Bloat estimation functions * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/pgstattuple/pgstatapprox.c @@ -14,21 +14,15 @@ #include "access/heapam.h" #include "access/htup_details.h" -#include "access/multixact.h" #include "access/relation.h" -#include "access/transam.h" #include "access/visibilitymap.h" -#include "access/xact.h" -#include "catalog/namespace.h" #include "catalog/pg_am_d.h" #include "commands/vacuum.h" #include "funcapi.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/freespace.h" -#include "storage/lmgr.h" #include "storage/procarray.h" -#include "utils/builtins.h" PG_FUNCTION_INFO_V1(pgstattuple_approx); PG_FUNCTION_INFO_V1(pgstattuple_approx_v1_5); @@ -106,14 +100,7 @@ statapprox_heap(Relation rel, output_type *stat) page = BufferGetPage(buf); - /* - * It's not safe to call PageGetHeapFreeSpace() on new pages, so we - * treat them as being free space for our purposes. - */ - if (!PageIsNew(page)) - stat->free_space += PageGetHeapFreeSpace(page); - else - stat->free_space += BLCKSZ - SizeOfPageHeaderData; + stat->free_space += PageGetExactFreeSpace(page); /* We may count the page as scanned even if it's new/empty */ scanned++; diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 5c06ba6db438e..4b9d76ec4e4df 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -32,14 +32,11 @@ #include "access/htup_details.h" #include "access/nbtree.h" #include "access/relation.h" -#include "access/table.h" #include "catalog/namespace.h" #include "catalog/pg_am.h" #include "funcapi.h" #include "miscadmin.h" #include "storage/bufmgr.h" -#include "storage/lmgr.h" -#include "utils/builtins.h" #include "utils/rel.h" #include "utils/varlena.h" @@ -311,7 +308,7 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo) max_avail = BLCKSZ - (BLCKSZ - ((PageHeader) page)->pd_special + SizeOfPageHeaderData); indexStat.max_avail += max_avail; - indexStat.free_space += PageGetFreeSpace(page); + indexStat.free_space += PageGetExactFreeSpace(page); indexStat.leaf_pages++; diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 3bd8b96197f86..0d9c2b0b65369 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -36,10 +36,12 @@ #include "miscadmin.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" -#include "utils/builtins.h" #include "utils/varlena.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pgstattuple", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(pgstattuple); PG_FUNCTION_INFO_V1(pgstattuple_v1_5); @@ -323,7 +325,11 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) pgstattuple_type stat = {0}; SnapshotData SnapshotDirty; - if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) + /* + * Sequences always use heap AM, but they don't show that in the catalogs. + */ + if (rel->rd_rel->relkind != RELKIND_SEQUENCE && + rel->rd_rel->relam != HEAP_TABLE_AM_OID) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("only heap AM is supported"))); @@ -372,7 +378,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, hscan->rs_strategy); LockBuffer(buffer, BUFFER_LOCK_SHARE); - stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer)); + stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer)); UnlockReleaseBuffer(buffer); block++; } @@ -385,7 +391,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo) buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, hscan->rs_strategy); LockBuffer(buffer, BUFFER_LOCK_SHARE); - stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer)); + stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer)); UnlockReleaseBuffer(buffer); block++; } @@ -565,7 +571,7 @@ pgstat_index_page(pgstattuple_type *stat, Page page, { OffsetNumber i; - stat->free_space += PageGetFreeSpace(page); + stat->free_space += PageGetExactFreeSpace(page); for (i = minoff; i <= maxoff; i = OffsetNumberNext(i)) { diff --git a/contrib/pgstattuple/sql/pgstattuple.sql b/contrib/pgstattuple/sql/pgstattuple.sql index b08c31c21b7ea..7e72c567a0641 100644 --- a/contrib/pgstattuple/sql/pgstattuple.sql +++ b/contrib/pgstattuple/sql/pgstattuple.sql @@ -119,6 +119,18 @@ create index test_partition_hash_idx on test_partition using hash (a); select pgstatindex('test_partition_idx'); select pgstathashindex('test_partition_hash_idx'); +-- these should work for sequences +create sequence test_sequence; +select count(*) from pgstattuple('test_sequence'); +select pg_relpages('test_sequence'); + +-- these should fail for sequences +select pgstatindex('test_sequence'); +select pgstatginindex('test_sequence'); +select pgstathashindex('test_sequence'); +select pgstattuple_approx('test_sequence'); + +drop sequence test_sequence; drop table test_partitioned; drop view test_view; drop foreign table test_foreign_table; diff --git a/contrib/postgres_fdw/Makefile b/contrib/postgres_fdw/Makefile index 88fdce40d6a3a..adfbd2ef758e0 100644 --- a/contrib/postgres_fdw/Makefile +++ b/contrib/postgres_fdw/Makefile @@ -17,6 +17,7 @@ EXTENSION = postgres_fdw DATA = postgres_fdw--1.0.sql postgres_fdw--1.0--1.1.sql postgres_fdw--1.1--1.2.sql REGRESS = postgres_fdw query_cancel +TAP_TESTS = 1 ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 12d1fec0e82d7..304f3c20f8356 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -3,7 +3,7 @@ * connection.c * Connection management functions for postgres_fdw * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/connection.c @@ -16,10 +16,10 @@ #include #endif -#include "access/htup_details.h" #include "access/xact.h" #include "catalog/pg_user_mapping.h" #include "commands/defrem.h" +#include "common/base64.h" #include "funcapi.h" #include "libpq/libpq-be.h" #include "libpq/libpq-be-fe-helpers.h" @@ -27,13 +27,10 @@ #include "miscadmin.h" #include "pgstat.h" #include "postgres_fdw.h" -#include "storage/fd.h" #include "storage/latch.h" #include "utils/builtins.h" -#include "utils/datetime.h" #include "utils/hsearch.h" #include "utils/inval.h" -#include "utils/memutils.h" #include "utils/syscache.h" /* @@ -99,6 +96,13 @@ static uint32 pgfdw_we_get_result = 0; */ #define CONNECTION_CLEANUP_TIMEOUT 30000 +/* + * Milliseconds to wait before issuing another cancel request. This covers + * the race condition where the remote session ignored our cancel request + * because it arrived while idle. + */ +#define RETRY_CANCEL_TIMEOUT 1000 + /* Macro for constructing abort command to be sent */ #define CONSTRUCT_ABORT_COMMAND(sql, entry, toplevel) \ do { \ @@ -149,6 +153,7 @@ static void pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel); static bool pgfdw_cancel_query(PGconn *conn); static bool pgfdw_cancel_query_begin(PGconn *conn, TimestampTz endtime); static bool pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, + TimestampTz retrycanceltime, bool consume_input); static bool pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors); @@ -158,6 +163,7 @@ static bool pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query, bool consume_input, bool ignore_errors); static bool pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, + TimestampTz retrycanceltime, PGresult **result, bool *timed_out); static void pgfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel); static bool pgfdw_abort_cleanup_begin(ConnCacheEntry *entry, bool toplevel, @@ -172,11 +178,13 @@ static void pgfdw_finish_abort_cleanup(List *pending_entries, static void pgfdw_security_check(const char **keywords, const char **values, UserMapping *user, PGconn *conn); static bool UserMappingPasswordRequired(UserMapping *user); +static bool UseScramPassthrough(ForeignServer *server, UserMapping *user); static bool disconnect_cached_connections(Oid serverid); static void postgres_fdw_get_connections_internal(FunctionCallInfo fcinfo, enum pgfdwVersion api_version); static int pgfdw_conn_check(PGconn *conn); static bool pgfdw_conn_checkable(void); +static bool pgfdw_has_required_scram_options(const char **keywords, const char **values); /* * Get a PGconn which can be used to execute queries on the remote PostgreSQL @@ -448,6 +456,15 @@ pgfdw_security_check(const char **keywords, const char **values, UserMapping *us } } + /* + * Ok if SCRAM pass-through is being used and all required SCRAM options + * are set correctly. If pgfdw_has_required_scram_options returns true we + * assume that UseScramPassthrough is also true since SCRAM options are + * only set when UseScramPassthrough is enabled. + */ + if (MyProcPort->has_scram_keys && pgfdw_has_required_scram_options(keywords, values)) + return; + ereport(ERROR, (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), errmsg("password or GSSAPI delegated credentials required"), @@ -478,9 +495,10 @@ connect_pg_server(ForeignServer *server, UserMapping *user) * and UserMapping. (Some of them might not be libpq options, in * which case we'll just waste a few array slots.) Add 4 extra slots * for application_name, fallback_application_name, client_encoding, - * end marker. + * end marker, and 3 extra slots for scram keys and required scram + * pass-through options. */ - n = list_length(server->options) + list_length(user->options) + 4; + n = list_length(server->options) + list_length(user->options) + 4 + 3; keywords = (const char **) palloc(n * sizeof(char *)); values = (const char **) palloc(n * sizeof(char *)); @@ -549,9 +567,46 @@ connect_pg_server(ForeignServer *server, UserMapping *user) values[n] = GetDatabaseEncodingName(); n++; + /* Add required SCRAM pass-through connection options if it's enabled. */ + if (MyProcPort->has_scram_keys && UseScramPassthrough(server, user)) + { + int len; + int encoded_len; + + keywords[n] = "scram_client_key"; + len = pg_b64_enc_len(sizeof(MyProcPort->scram_ClientKey)); + /* don't forget the zero-terminator */ + values[n] = palloc0(len + 1); + encoded_len = pg_b64_encode(MyProcPort->scram_ClientKey, + sizeof(MyProcPort->scram_ClientKey), + (char *) values[n], len); + if (encoded_len < 0) + elog(ERROR, "could not encode SCRAM client key"); + n++; + + keywords[n] = "scram_server_key"; + len = pg_b64_enc_len(sizeof(MyProcPort->scram_ServerKey)); + /* don't forget the zero-terminator */ + values[n] = palloc0(len + 1); + encoded_len = pg_b64_encode(MyProcPort->scram_ServerKey, + sizeof(MyProcPort->scram_ServerKey), + (char *) values[n], len); + if (encoded_len < 0) + elog(ERROR, "could not encode SCRAM server key"); + n++; + + /* + * Require scram-sha-256 to ensure that no other auth method is + * used when connecting with foreign server. + */ + keywords[n] = "require_auth"; + values[n] = "scram-sha-256"; + n++; + } + keywords[n] = values[n] = NULL; - /* verify the set of connection parameters */ + /* Verify the set of connection parameters. */ check_conn_params(keywords, values, user); /* first time, allocate or get the custom wait event */ @@ -570,7 +625,7 @@ connect_pg_server(ForeignServer *server, UserMapping *user) server->servername), errdetail_internal("%s", pchomp(PQerrorMessage(conn))))); - /* Perform post-connection security checks */ + /* Perform post-connection security checks. */ pgfdw_security_check(keywords, values, user, conn); /* Prepare new session for use */ @@ -624,6 +679,30 @@ UserMappingPasswordRequired(UserMapping *user) return true; } +static bool +UseScramPassthrough(ForeignServer *server, UserMapping *user) +{ + ListCell *cell; + + foreach(cell, server->options) + { + DefElem *def = (DefElem *) lfirst(cell); + + if (strcmp(def->defname, "use_scram_passthrough") == 0) + return defGetBoolean(def); + } + + foreach(cell, user->options) + { + DefElem *def = (DefElem *) lfirst(cell); + + if (strcmp(def->defname, "use_scram_passthrough") == 0) + return defGetBoolean(def); + } + + return false; +} + /* * For non-superusers, insist that the connstr specify a password or that the * user provided their own GSSAPI delegated credentials. This @@ -658,10 +737,19 @@ check_conn_params(const char **keywords, const char **values, UserMapping *user) if (!UserMappingPasswordRequired(user)) return; + /* + * Ok if SCRAM pass-through is being used and all required scram options + * are set correctly. If pgfdw_has_required_scram_options returns true we + * assume that UseScramPassthrough is also true since SCRAM options are + * only set when UseScramPassthrough is enabled. + */ + if (MyProcPort->has_scram_keys && pgfdw_has_required_scram_options(keywords, values)) + return; + ereport(ERROR, (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED), errmsg("password or GSSAPI delegated credentials required"), - errdetail("Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping."))); + errdetail("Non-superusers must delegate GSSAPI credentials, provide a password, or enable SCRAM pass-through in user mapping."))); } /* @@ -1326,18 +1414,25 @@ pgfdw_reset_xact_state(ConnCacheEntry *entry, bool toplevel) static bool pgfdw_cancel_query(PGconn *conn) { + TimestampTz now = GetCurrentTimestamp(); TimestampTz endtime; + TimestampTz retrycanceltime; /* * If it takes too long to cancel the query and discard the result, assume * the connection is dead. */ - endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), - CONNECTION_CLEANUP_TIMEOUT); + endtime = TimestampTzPlusMilliseconds(now, CONNECTION_CLEANUP_TIMEOUT); + + /* + * Also, lose patience and re-issue the cancel request after a little bit. + * (This serves to close some race conditions.) + */ + retrycanceltime = TimestampTzPlusMilliseconds(now, RETRY_CANCEL_TIMEOUT); if (!pgfdw_cancel_query_begin(conn, endtime)) return false; - return pgfdw_cancel_query_end(conn, endtime, false); + return pgfdw_cancel_query_end(conn, endtime, retrycanceltime, false); } /* @@ -1363,9 +1458,10 @@ pgfdw_cancel_query_begin(PGconn *conn, TimestampTz endtime) } static bool -pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, bool consume_input) +pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, + TimestampTz retrycanceltime, bool consume_input) { - PGresult *result = NULL; + PGresult *result; bool timed_out; /* @@ -1384,7 +1480,8 @@ pgfdw_cancel_query_end(PGconn *conn, TimestampTz endtime, bool consume_input) } /* Get and discard the result of the query. */ - if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out)) + if (pgfdw_get_cleanup_result(conn, endtime, retrycanceltime, + &result, &timed_out)) { if (timed_out) ereport(WARNING, @@ -1457,7 +1554,7 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query, TimestampTz endtime, bool consume_input, bool ignore_errors) { - PGresult *result = NULL; + PGresult *result; bool timed_out; Assert(query != NULL); @@ -1475,7 +1572,7 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query, } /* Get the result of the query. */ - if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out)) + if (pgfdw_get_cleanup_result(conn, endtime, endtime, &result, &timed_out)) { if (timed_out) ereport(WARNING, @@ -1499,28 +1596,36 @@ pgfdw_exec_cleanup_query_end(PGconn *conn, const char *query, } /* - * Get, during abort cleanup, the result of a query that is in progress. This - * might be a query that is being interrupted by transaction abort, or it might - * be a query that was initiated as part of transaction abort to get the remote - * side back to the appropriate state. + * Get, during abort cleanup, the result of a query that is in progress. + * This might be a query that is being interrupted by a cancel request or by + * transaction abort, or it might be a query that was initiated as part of + * transaction abort to get the remote side back to the appropriate state. + * + * endtime is the time at which we should give up and assume the remote side + * is dead. retrycanceltime is the time at which we should issue a fresh + * cancel request (pass the same value as endtime if this is not wanted). * - * endtime is the time at which we should give up and assume the remote - * side is dead. Returns true if the timeout expired or connection trouble - * occurred, false otherwise. Sets *result except in case of a timeout. - * Sets timed_out to true only when the timeout expired. + * Returns true if the timeout expired or connection trouble occurred, + * false otherwise. Sets *result except in case of a true result. + * Sets *timed_out to true only when the timeout expired. */ static bool -pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result, +pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, + TimestampTz retrycanceltime, + PGresult **result, bool *timed_out) { volatile bool failed = false; PGresult *volatile last_res = NULL; + *result = NULL; *timed_out = false; /* In what follows, do not leak any PGresults on an error. */ PG_TRY(); { + int canceldelta = RETRY_CANCEL_TIMEOUT * 2; + for (;;) { PGresult *res; @@ -1531,8 +1636,33 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result, TimestampTz now = GetCurrentTimestamp(); long cur_timeout; + /* If timeout has expired, give up. */ + if (now >= endtime) + { + *timed_out = true; + failed = true; + goto exit; + } + + /* If we need to re-issue the cancel request, do that. */ + if (now >= retrycanceltime) + { + /* We ignore failure to issue the repeated request. */ + (void) libpqsrv_cancel(conn, endtime); + + /* Recompute "now" in case that took measurable time. */ + now = GetCurrentTimestamp(); + + /* Adjust re-cancel timeout in increasing steps. */ + retrycanceltime = TimestampTzPlusMilliseconds(now, + canceldelta); + canceldelta += canceldelta; + } + /* If timeout has expired, give up, else get sleep time. */ - cur_timeout = TimestampDifferenceMilliseconds(now, endtime); + cur_timeout = TimestampDifferenceMilliseconds(now, + Min(endtime, + retrycanceltime)); if (cur_timeout <= 0) { *timed_out = true; @@ -1853,7 +1983,9 @@ pgfdw_finish_abort_cleanup(List *pending_entries, List *cancel_requested, foreach(lc, cancel_requested) { ConnCacheEntry *entry = (ConnCacheEntry *) lfirst(lc); + TimestampTz now = GetCurrentTimestamp(); TimestampTz endtime; + TimestampTz retrycanceltime; char sql[100]; Assert(entry->changing_xact_state); @@ -1867,10 +1999,13 @@ pgfdw_finish_abort_cleanup(List *pending_entries, List *cancel_requested, * remaining entries in the list, leading to slamming that entry's * connection shut. */ - endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), + endtime = TimestampTzPlusMilliseconds(now, CONNECTION_CLEANUP_TIMEOUT); + retrycanceltime = TimestampTzPlusMilliseconds(now, + RETRY_CANCEL_TIMEOUT); - if (!pgfdw_cancel_query_end(entry->conn, endtime, true)) + if (!pgfdw_cancel_query_end(entry->conn, endtime, + retrycanceltime, true)) { /* Unable to cancel running query */ pgfdw_reset_xact_state(entry, toplevel); @@ -1997,8 +2132,8 @@ pgfdw_finish_abort_cleanup(List *pending_entries, List *cancel_requested, /* Number of output arguments (columns) for various API versions */ #define POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_1 2 -#define POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_2 4 -#define POSTGRES_FDW_GET_CONNECTIONS_COLS 4 /* maximum of above */ +#define POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_2 6 +#define POSTGRES_FDW_GET_CONNECTIONS_COLS 6 /* maximum of above */ /* * Internal function used by postgres_fdw_get_connections variants. @@ -2014,10 +2149,15 @@ pgfdw_finish_abort_cleanup(List *pending_entries, List *cancel_requested, * * For API version 1.2 and later, this function takes an input parameter * to check a connection status and returns the following - * additional values along with the two values from version 1.1: + * additional values along with the four values from version 1.1: * + * - user_name - the local user name of the active connection. In case the + * user mapping is dropped but the connection is still active, then the + * user name will be NULL in the output. * - used_in_xact - true if the connection is used in the current transaction. - * - closed: true if the connection is closed. + * - closed - true if the connection is closed. + * - remote_backend_pid - process ID of the remote backend, on the foreign + * server, handling the connection. * * No records are returned when there are no cached connections at all. */ @@ -2056,6 +2196,7 @@ postgres_fdw_get_connections_internal(FunctionCallInfo fcinfo, ForeignServer *server; Datum values[POSTGRES_FDW_GET_CONNECTIONS_COLS] = {0}; bool nulls[POSTGRES_FDW_GET_CONNECTIONS_COLS] = {0}; + int i = 0; /* We only look for open remote connections */ if (!entry->conn) @@ -2100,28 +2241,64 @@ postgres_fdw_get_connections_internal(FunctionCallInfo fcinfo, Assert(entry->conn && entry->xact_depth > 0 && entry->invalidated); /* Show null, if no server name was found */ - nulls[0] = true; + nulls[i++] = true; } else - values[0] = CStringGetTextDatum(server->servername); + values[i++] = CStringGetTextDatum(server->servername); + + if (api_version >= PGFDW_V1_2) + { + HeapTuple tp; + + /* Use the system cache to obtain the user mapping */ + tp = SearchSysCache1(USERMAPPINGOID, ObjectIdGetDatum(entry->key)); + + /* + * Just like in the foreign server case, user mappings can also be + * dropped in the current explicit transaction. Therefore, the + * similar check as in the server case is required. + */ + if (!HeapTupleIsValid(tp)) + { + /* + * If we reach here, this entry must have been invalidated in + * pgfdw_inval_callback, same as in the server case. + */ + Assert(entry->conn && entry->xact_depth > 0 && + entry->invalidated); - values[1] = BoolGetDatum(!entry->invalidated); + nulls[i++] = true; + } + else + { + Oid userid; + + userid = ((Form_pg_user_mapping) GETSTRUCT(tp))->umuser; + values[i++] = CStringGetTextDatum(MappingUserName(userid)); + ReleaseSysCache(tp); + } + } + + values[i++] = BoolGetDatum(!entry->invalidated); if (api_version >= PGFDW_V1_2) { bool check_conn = PG_GETARG_BOOL(0); /* Is this connection used in the current transaction? */ - values[2] = BoolGetDatum(entry->xact_depth > 0); + values[i++] = BoolGetDatum(entry->xact_depth > 0); /* * If a connection status check is requested and supported, return * whether the connection is closed. Otherwise, return NULL. */ if (check_conn && pgfdw_conn_checkable()) - values[3] = BoolGetDatum(pgfdw_conn_check(entry->conn) != 0); + values[i++] = BoolGetDatum(pgfdw_conn_check(entry->conn) != 0); else - nulls[3] = true; + nulls[i++] = true; + + /* Return process ID of remote backend */ + values[i++] = Int32GetDatum(PQbackendPID(entry->conn)); } tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); @@ -2331,3 +2508,56 @@ pgfdw_conn_checkable(void) return false; #endif } + +/* + * Ensure that require_auth and SCRAM keys are correctly set on values. SCRAM + * keys used to pass-through are coming from the initial connection from the + * client with the server. + * + * All required SCRAM options are set by postgres_fdw, so we just need to + * ensure that these options are not overwritten by the user. + */ +static bool +pgfdw_has_required_scram_options(const char **keywords, const char **values) +{ + bool has_scram_server_key = false; + bool has_scram_client_key = false; + bool has_require_auth = false; + bool has_scram_keys = false; + + /* + * Continue iterating even if we found the keys that we need to validate + * to make sure that there is no other declaration of these keys that can + * overwrite the first. + */ + for (int i = 0; keywords[i] != NULL; i++) + { + if (strcmp(keywords[i], "scram_client_key") == 0) + { + if (values[i] != NULL && values[i][0] != '\0') + has_scram_client_key = true; + else + has_scram_client_key = false; + } + + if (strcmp(keywords[i], "scram_server_key") == 0) + { + if (values[i] != NULL && values[i][0] != '\0') + has_scram_server_key = true; + else + has_scram_server_key = false; + } + + if (strcmp(keywords[i], "require_auth") == 0) + { + if (values[i] != NULL && strcmp(values[i], "scram-sha-256") == 0) + has_require_auth = true; + else + has_require_auth = false; + } + } + + has_scram_keys = has_scram_client_key && has_scram_server_key && MyProcPort->has_scram_keys; + + return (has_scram_keys && has_require_auth); +} diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index fb590c87e67ba..d9970dd675336 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -24,7 +24,7 @@ * with collations that match the remote table's columns, which we can * consider to be user error. * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/deparse.c @@ -47,8 +47,6 @@ #include "catalog/pg_ts_dict.h" #include "catalog/pg_type.h" #include "commands/defrem.h" -#include "commands/tablecmds.h" -#include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "nodes/plannodes.h" #include "optimizer/optimizer.h" @@ -3971,17 +3969,17 @@ appendOrderByClause(List *pathkeys, bool has_final_sort, appendStringInfoString(buf, ", "); /* - * Lookup the operator corresponding to the strategy in the opclass. - * The datatype used by the opfamily is not necessarily the same as - * the expression type (for array types for example). + * Lookup the operator corresponding to the compare type in the + * opclass. The datatype used by the opfamily is not necessarily the + * same as the expression type (for array types for example). */ - oprid = get_opfamily_member(pathkey->pk_opfamily, - em->em_datatype, - em->em_datatype, - pathkey->pk_strategy); + oprid = get_opfamily_member_for_cmptype(pathkey->pk_opfamily, + em->em_datatype, + em->em_datatype, + pathkey->pk_cmptype); if (!OidIsValid(oprid)) elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - pathkey->pk_strategy, em->em_datatype, em->em_datatype, + pathkey->pk_cmptype, em->em_datatype, em->em_datatype, pathkey->pk_opfamily); deparseExpr(em_expr, context); diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 212434711e32a..2185b42bb4f79 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -196,6 +196,17 @@ ALTER USER MAPPING FOR public SERVER testserver1 -- permitted to check validation. ALTER USER MAPPING FOR public SERVER testserver1 OPTIONS (ADD sslkey 'value', ADD sslcert 'value'); +-- OAuth options are not allowed in either context +ALTER SERVER testserver1 OPTIONS (ADD oauth_issuer 'https://example.com'); +ERROR: invalid option "oauth_issuer" +ALTER SERVER testserver1 OPTIONS (ADD oauth_client_id 'myID'); +ERROR: invalid option "oauth_client_id" +ALTER USER MAPPING FOR public SERVER testserver1 + OPTIONS (ADD oauth_issuer 'https://example.com'); +ERROR: invalid option "oauth_issuer" +ALTER USER MAPPING FOR public SERVER testserver1 + OPTIONS (ADD oauth_client_id 'myID'); +ERROR: invalid option "oauth_client_id" ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1'); ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1'); ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); @@ -637,6 +648,17 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1; Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST (3 rows) +-- test restriction on non-system foreign tables. +SET restrict_nonsystem_relation_kind TO 'foreign-table'; +SELECT * from ft1 where c1 < 1; -- ERROR +ERROR: access to non-system foreign table is restricted +INSERT INTO ft1 (c1) VALUES (1); -- ERROR +ERROR: access to non-system foreign table is restricted +DELETE FROM ft1 WHERE c1 = 1; -- ERROR +ERROR: access to non-system foreign table is restricted +TRUNCATE ft1; -- ERROR +ERROR: access to non-system foreign table is restricted +RESET restrict_nonsystem_relation_kind; -- =================================================================== -- WHERE with remotely-executable conditions -- =================================================================== @@ -2543,6 +2565,70 @@ SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = f 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 (10 rows) +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1, ft4, ft5, local_tbl WHERE ft1.c1 = ft4.c1 AND ft1.c1 = ft5.c1 + AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft5.c1 < 100 FOR UPDATE; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + LockRows + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft4.*, ft5.*, local_tbl.ctid + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft4.*, ft5.*, local_tbl.ctid + Merge Cond: (local_tbl.c1 = ft1.c2) + -> Index Scan using local_tbl_pkey on public.local_tbl + Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + Sort Key: ft1.c2 + -> Foreign Scan + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + Relations: ((public.ft1) INNER JOIN (public.ft4)) INNER JOIN (public.ft5) + Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2.c1, r2.c2, r2.c3, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, r3.c1, r3.c2, r3.c3, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1."C 1" = r2.c1)) AND ((r1."C 1" < 100)))) INNER JOIN "S 1"."T 4" r3 ON (((r1."C 1" = r3.c1)) AND ((r3.c1 < 100)))) FOR UPDATE OF r1 FOR UPDATE OF r2 FOR UPDATE OF r3 + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* + Merge Cond: (ft1.c1 = ft5.c1) + -> Merge Join + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft4.c1, ft4.c2, ft4.c3, ft4.* + Merge Cond: (ft1.c1 = ft4.c1) + -> Sort + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + Sort Key: ft1.c1 + -> Foreign Scan on public.ft1 + Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* + Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) FOR UPDATE + -> Sort + Output: ft4.c1, ft4.c2, ft4.c3, ft4.* + Sort Key: ft4.c1 + -> Foreign Scan on public.ft4 + Output: ft4.c1, ft4.c2, ft4.c3, ft4.* + Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" FOR UPDATE + -> Sort + Output: ft5.c1, ft5.c2, ft5.c3, ft5.* + Sort Key: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1, ft5.c2, ft5.c3, ft5.* + Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" WHERE ((c1 < 100)) FOR UPDATE +(38 rows) + +SELECT * FROM ft1, ft4, ft5, local_tbl WHERE ft1.c1 = ft4.c1 AND ft1.c1 = ft5.c1 + AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft5.c1 < 100 FOR UPDATE; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 | c1 | c2 | c3 +----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------ + 12 | 2 | 00012 | Tue Jan 13 00:00:00 1970 PST | Tue Jan 13 00:00:00 1970 | 2 | 2 | foo | 12 | 13 | AAA012 | 12 | 13 | AAA012 | 2 | 2 | 0002 + 42 | 2 | 00042 | Thu Feb 12 00:00:00 1970 PST | Thu Feb 12 00:00:00 1970 | 2 | 2 | foo | 42 | 43 | AAA042 | 42 | 43 | AAA042 | 2 | 2 | 0002 + 72 | 2 | 00072 | Sat Mar 14 00:00:00 1970 PST | Sat Mar 14 00:00:00 1970 | 2 | 2 | foo | 72 | 73 | AAA072 | 72 | 73 | | 2 | 2 | 0002 + 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST | Sun Jan 25 00:00:00 1970 | 4 | 4 | foo | 24 | 25 | AAA024 | 24 | 25 | AAA024 | 4 | 4 | 0004 + 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST | Tue Feb 24 00:00:00 1970 | 4 | 4 | foo | 54 | 55 | AAA054 | 54 | 55 | | 4 | 4 | 0004 + 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST | Thu Mar 26 00:00:00 1970 | 4 | 4 | foo | 84 | 85 | AAA084 | 84 | 85 | AAA084 | 4 | 4 | 0004 + 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 97 | AAA096 | 96 | 97 | AAA096 | 6 | 6 | 0006 + 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 37 | AAA036 | 36 | 37 | | 6 | 6 | 0006 + 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 67 | AAA066 | 66 | 67 | AAA066 | 6 | 6 | 0006 + 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 + 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo | 48 | 49 | AAA048 | 48 | 49 | AAA048 | 8 | 8 | 0008 + 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo | 18 | 19 | AAA018 | 18 | 19 | | 8 | 8 | 0008 + 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo | 78 | 79 | AAA078 | 78 | 79 | AAA078 | 8 | 8 | 0008 +(13 rows) + RESET enable_nestloop; RESET enable_hashjoin; -- test that add_paths_with_pathkeys_for_rel() arranges for the epq_path to @@ -3957,10 +4043,11 @@ select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 gr QUERY PLAN ------------------------------------------------------------------------------------------------------------ Sort - Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2)) + Output: c2, (sum(c2)), (count(c2) OVER w1), ((c2 % 2)) Sort Key: ft2.c2 -> WindowAgg - Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2)) + Output: c2, (sum(c2)), count(c2) OVER w1, ((c2 % 2)) + Window: w1 AS (PARTITION BY ((ft2.c2 % 2))) -> Sort Output: c2, ((c2 % 2)), (sum(c2)) Sort Key: ((ft2.c2 % 2)) @@ -3968,7 +4055,7 @@ select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 gr Output: c2, ((c2 % 2)), (sum(c2)) Relations: Aggregate on (public.ft2) Remote SQL: SELECT c2, (c2 % 2), sum(c2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1 -(12 rows) +(13 rows) select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; c2 | sum | count @@ -3990,10 +4077,11 @@ select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 wher QUERY PLAN --------------------------------------------------------------------------------------------------- Sort - Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) + Output: c2, (array_agg(c2) OVER w1), ((c2 % 2)) Sort Key: ft1.c2 -> WindowAgg - Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) + Output: c2, array_agg(c2) OVER w1, ((c2 % 2)) + Window: w1 AS (PARTITION BY ((ft1.c2 % 2)) ORDER BY ft1.c2) -> Sort Output: c2, ((c2 % 2)) Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC @@ -4001,7 +4089,7 @@ select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 wher Output: c2, ((c2 % 2)) Relations: Aggregate on (public.ft1) Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1 -(12 rows) +(13 rows) select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; c2 | array_agg @@ -4020,13 +4108,14 @@ select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 wher explain (verbose, costs off) select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; - QUERY PLAN ---------------------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- Sort - Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) + Output: c2, (array_agg(c2) OVER w1), ((c2 % 2)) Sort Key: ft1.c2 -> WindowAgg - Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) + Output: c2, array_agg(c2) OVER w1, ((c2 % 2)) + Window: w1 AS (PARTITION BY ((ft1.c2 % 2)) ORDER BY ft1.c2 RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) -> Sort Output: c2, ((c2 % 2)) Sort Key: ((ft1.c2 % 2)), ft1.c2 @@ -4034,7 +4123,7 @@ select c2, array_agg(c2) over (partition by c2%2 order by c2 range between curre Output: c2, ((c2 % 2)) Relations: Aggregate on (public.ft1) Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1 -(12 rows) +(13 rows) select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; c2 | array_agg @@ -4262,13 +4351,13 @@ EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft1 Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) Batch Size: 1 -> Result - Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum + Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying(10), 'ft1 '::character(10), NULL::user_enum (5 rows) ALTER TABLE "S 1"."T 1" RENAME TO "T 0"; @@ -4296,13 +4385,13 @@ EXECUTE st6; (9 rows) EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft1 Remote SQL: INSERT INTO "S 1"."T 0"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) Batch Size: 1 -> Result - Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum + Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying(10), 'ft1 '::character(10), NULL::user_enum (5 rows) ALTER TABLE "S 1"."T 0" RENAME TO "T 1"; @@ -4922,6 +5011,44 @@ SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ----+----+----+----+----+----+----+----+----+----+---- (0 rows) +-- Semi-join conditions shouldn't pop up as left/right join clauses. +SET enable_material TO off; +EXPLAIN (verbose, costs off) +SELECT x1.c1 FROM + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x1 + RIGHT JOIN + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x2 + ON (x1.c1 = x2.c1) +ORDER BY x1.c1 LIMIT 10; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: ft2.c1 + Relations: ((public.ft2 ft2_1) LEFT JOIN ((public.ft2) SEMI JOIN (public.ft4))) SEMI JOIN (public.ft4 ft4_1) + Remote SQL: SELECT s9.c1 FROM ("S 1"."T 1" r6 LEFT JOIN (SELECT r4."C 1" FROM "S 1"."T 1" r4 WHERE ((r4.c2 < 10)) AND EXISTS (SELECT NULL FROM "S 1"."T 3" r5 WHERE ((r4."C 1" = r5.c1)))) s9(c1) ON (((s9.c1 = r6."C 1")))) WHERE ((r6.c2 < 10)) AND EXISTS (SELECT NULL FROM "S 1"."T 3" r7 WHERE ((r6."C 1" = r7.c1))) ORDER BY s9.c1 ASC NULLS LAST LIMIT 10::bigint +(4 rows) + +SELECT x1.c1 FROM + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x1 + RIGHT JOIN + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x2 + ON (x1.c1 = x2.c1) +ORDER BY x1.c1 LIMIT 10; + c1 +---- + 2 + 4 + 6 + 8 + 10 + 12 + 14 + 16 + 18 + 20 +(10 rows) + +RESET enable_material; -- Can't push down semi-join with inner rel vars in targetlist EXPLAIN (verbose, costs off) SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE @@ -4950,13 +5077,13 @@ SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE -- =================================================================== EXPLAIN (verbose, costs off) INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Insert on public.ft2 Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) Batch Size: 1 -> Subquery Scan on "*SELECT*" - Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::user_enum + Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying(10), 'ft2 '::character(10), NULL::user_enum -> Foreign Scan on public.ft2 ft2_1 Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3) Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1" LIMIT 20::bigint @@ -4964,12 +5091,12 @@ INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; INSERT INTO ft2 (c1,c2,c3) - VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *; - c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -------+-----+-----+----+----+----+------------+---- - 1101 | 201 | aaa | | | | ft2 | - 1102 | 202 | bbb | | | | ft2 | - 1103 | 203 | ccc | | | | ft2 | + VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING old, new, old.*, new.*; + old | new | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +-----+---------------------------------+----+----+----+----+----+----+----+----+------+-----+-----+----+----+----+------------+---- + | (1101,201,aaa,,,,"ft2 ",) | | | | | | | | | 1101 | 201 | aaa | | | | ft2 | + | (1102,202,bbb,,,,"ft2 ",) | | | | | | | | | 1102 | 202 | bbb | | | | ft2 | + | (1103,203,ccc,,,,"ft2 ",) | | | | | | | | | 1103 | 203 | ccc | | | | ft2 | (3 rows) INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); @@ -5100,6 +5227,31 @@ UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING 1017 | 507 | 0001700017_update7 | | | | ft2 | (102 rows) +BEGIN; + EXPLAIN (verbose, costs off) + UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40 + RETURNING old.*, new.*; -- can't be pushed down + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.ft2 + Output: old.c1, old.c2, old.c3, old.c4, old.c5, old.c6, old.c7, old.c8, new.c1, new.c2, new.c3, new.c4, new.c5, new.c6, new.c7, new.c8 + Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8 + -> Foreign Scan on public.ft2 + Output: (c2 + 400), (c3 || '_update7b'::text), ctid, ft2.* + Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" < 40)) AND ((("C 1" % 10) = 7)) FOR UPDATE +(6 rows) + + UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40 + RETURNING old.*, new.*; + c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 +----+-----+---------------+------------------------------+--------------------------+----+------------+-----+----+-----+------------------------+------------------------------+--------------------------+----+------------+----- + 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo | 7 | 807 | 00007_update7_update7b | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo + 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo | 17 | 807 | 00017_update7_update7b | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo + 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo | 27 | 807 | 00027_update7_update7b | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo + 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo | 37 | 807 | 00037_update7_update7b | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo +(4 rows) + +ROLLBACK; EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down @@ -5230,6 +5382,29 @@ DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; 1105 | (103 rows) +BEGIN; + EXPLAIN (verbose, costs off) + DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; -- can't be pushed down + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Delete on public.ft2 + Output: old.c1, c4 + Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1 RETURNING "C 1", c4 + -> Foreign Scan on public.ft2 + Output: ctid + Remote SQL: SELECT ctid FROM "S 1"."T 1" WHERE (("C 1" < 40)) AND ((("C 1" % 10) = 6)) FOR UPDATE +(6 rows) + + DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; + c1 | c4 +----+------------------------------ + 6 | Wed Jan 07 00:00:00 1970 PST + 16 | Sat Jan 17 00:00:00 1970 PST + 26 | Tue Jan 27 00:00:00 1970 PST + 36 | Fri Feb 06 00:00:00 1970 PST +(4 rows) + +ROLLBACK; EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down QUERY PLAN @@ -6066,14 +6241,14 @@ SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; EXPLAIN (verbose, costs off) INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft2 Output: (ft2.tableoid)::regclass Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) Batch Size: 1 -> Result - Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::user_enum + Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying(10), 'ft2 '::character(10), NULL::user_enum (6 rows) INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass; @@ -6154,6 +6329,70 @@ UPDATE ft2 SET c3 = 'foo' (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096 (16 rows) +BEGIN; + EXPLAIN (verbose, costs off) + UPDATE ft2 SET c3 = 'bar' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1 + RETURNING old, new, ft2, ft2.*, ft4, ft4.*; -- can't be pushed down + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Update on public.ft2 + Output: old.*, new.*, ft2.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1, ft4.c2, ft4.c3 + Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8 + -> Foreign Scan + Output: 'bar'::text, ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3 + Relations: ((public.ft2) INNER JOIN (public.ft4)) INNER JOIN (public.ft5) + Remote SQL: SELECT r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r2.c1, r2.c2, r2.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)))) INNER JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1)))) FOR UPDATE OF r1 + -> Nested Loop + Output: ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3 + Join Filter: (ft4.c1 = ft5.c1) + -> Sort + Output: ft2.ctid, ft2.*, ft2.c2, ft4.*, ft4.c1, ft4.c2, ft4.c3 + Sort Key: ft2.c2 + -> Hash Join + Output: ft2.ctid, ft2.*, ft2.c2, ft4.*, ft4.c1, ft4.c2, ft4.c3 + Hash Cond: (ft2.c2 = ft4.c1) + -> Foreign Scan on public.ft2 + Output: ft2.ctid, ft2.*, ft2.c2 + Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1200)) FOR UPDATE + -> Hash + Output: ft4.*, ft4.c1, ft4.c2, ft4.c3 + -> Foreign Scan on public.ft4 + Output: ft4.*, ft4.c1, ft4.c2, ft4.c3 + Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" + -> Materialize + Output: ft5.*, ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.*, ft5.c1 + Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" +(29 rows) + + UPDATE ft2 SET c3 = 'bar' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1 + RETURNING old, new, ft2, ft2.*, ft4, ft4.*; + old | new | ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3 +--------------------------------+--------------------------------+--------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+-------- + (1206,6,foo,,,,"ft2 ",) | (1206,6,bar,,,,"ft2 ",) | (1206,6,bar,,,,"ft2 ",) | 1206 | 6 | bar | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006 + (1212,12,foo,,,,"ft2 ",) | (1212,12,bar,,,,"ft2 ",) | (1212,12,bar,,,,"ft2 ",) | 1212 | 12 | bar | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012 + (1224,24,foo,,,,"ft2 ",) | (1224,24,bar,,,,"ft2 ",) | (1224,24,bar,,,,"ft2 ",) | 1224 | 24 | bar | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024 + (1230,30,foo,,,,"ft2 ",) | (1230,30,bar,,,,"ft2 ",) | (1230,30,bar,,,,"ft2 ",) | 1230 | 30 | bar | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030 + (1242,42,foo,,,,"ft2 ",) | (1242,42,bar,,,,"ft2 ",) | (1242,42,bar,,,,"ft2 ",) | 1242 | 42 | bar | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042 + (1248,48,foo,,,,"ft2 ",) | (1248,48,bar,,,,"ft2 ",) | (1248,48,bar,,,,"ft2 ",) | 1248 | 48 | bar | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048 + (1260,60,foo,,,,"ft2 ",) | (1260,60,bar,,,,"ft2 ",) | (1260,60,bar,,,,"ft2 ",) | 1260 | 60 | bar | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060 + (1266,66,foo,,,,"ft2 ",) | (1266,66,bar,,,,"ft2 ",) | (1266,66,bar,,,,"ft2 ",) | 1266 | 66 | bar | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066 + (1278,78,foo,,,,"ft2 ",) | (1278,78,bar,,,,"ft2 ",) | (1278,78,bar,,,,"ft2 ",) | 1278 | 78 | bar | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078 + (1284,84,foo,,,,"ft2 ",) | (1284,84,bar,,,,"ft2 ",) | (1284,84,bar,,,,"ft2 ",) | 1284 | 84 | bar | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084 + (1296,96,foo,,,,"ft2 ",) | (1296,96,bar,,,,"ft2 ",) | (1296,96,bar,,,,"ft2 ",) | 1296 | 96 | bar | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096 + (1218,18,foo,,,,"ft2 ",) | (1218,18,bar,,,,"ft2 ",) | (1218,18,bar,,,,"ft2 ",) | 1218 | 18 | bar | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018 + (1236,36,foo,,,,"ft2 ",) | (1236,36,bar,,,,"ft2 ",) | (1236,36,bar,,,,"ft2 ",) | 1236 | 36 | bar | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036 + (1254,54,foo,,,,"ft2 ",) | (1254,54,bar,,,,"ft2 ",) | (1254,54,bar,,,,"ft2 ",) | 1254 | 54 | bar | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054 + (1272,72,foo,,,,"ft2 ",) | (1272,72,bar,,,,"ft2 ",) | (1272,72,bar,,,,"ft2 ",) | 1272 | 72 | bar | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072 + (1290,90,foo,,,,"ft2 ",) | (1290,90,bar,,,,"ft2 ",) | (1290,90,bar,,,,"ft2 ",) | 1290 | 90 | bar | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090 +(16 rows) + +ROLLBACK; EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) @@ -7272,65 +7511,68 @@ select * from rem1; -- =================================================================== create table gloc1 ( a int, - b int generated always as (a * 2) stored); + b int generated always as (a * 2) stored, + c int +); alter table gloc1 set (autovacuum_enabled = 'false'); create foreign table grem1 ( a int, - b int generated always as (a * 2) stored) - server loopback options(table_name 'gloc1'); + b int generated always as (a * 2) stored, + c int generated always as (a * 3) virtual +) server loopback options(table_name 'gloc1'); explain (verbose, costs off) insert into grem1 (a) values (1), (2); - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------- Insert on public.grem1 - Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT) + Remote SQL: INSERT INTO public.gloc1(a, b, c) VALUES ($1, DEFAULT, DEFAULT) Batch Size: 1 -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, NULL::integer + Output: "*VALUES*".column1, NULL::integer, NULL::integer (5 rows) insert into grem1 (a) values (1), (2); explain (verbose, costs off) update grem1 set a = 22 where a = 2; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------- Update on public.grem1 - Remote SQL: UPDATE public.gloc1 SET a = $2, b = DEFAULT WHERE ctid = $1 + Remote SQL: UPDATE public.gloc1 SET a = $2, b = DEFAULT, c = DEFAULT WHERE ctid = $1 -> Foreign Scan on public.grem1 Output: 22, ctid, grem1.* - Remote SQL: SELECT a, b, ctid FROM public.gloc1 WHERE ((a = 2)) FOR UPDATE + Remote SQL: SELECT a, b, c, ctid FROM public.gloc1 WHERE ((a = 2)) FOR UPDATE (5 rows) update grem1 set a = 22 where a = 2; select * from gloc1; - a | b -----+---- - 1 | 2 - 22 | 44 + a | b | c +----+----+--- + 1 | 2 | + 22 | 44 | (2 rows) select * from grem1; - a | b -----+---- - 1 | 2 - 22 | 44 + a | b | c +----+----+---- + 1 | 2 | 3 + 22 | 44 | 66 (2 rows) delete from grem1; -- test copy from copy grem1 from stdin; select * from gloc1; - a | b ----+--- - 1 | 2 - 2 | 4 + a | b | c +---+---+--- + 1 | 2 | + 2 | 4 | (2 rows) select * from grem1; - a | b ----+--- - 1 | 2 - 2 | 4 + a | b | c +---+---+--- + 1 | 2 | 3 + 2 | 4 | 6 (2 rows) delete from grem1; @@ -7338,28 +7580,28 @@ delete from grem1; alter server loopback options (add batch_size '10'); explain (verbose, costs off) insert into grem1 (a) values (1), (2); - QUERY PLAN -------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------- Insert on public.grem1 - Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT) + Remote SQL: INSERT INTO public.gloc1(a, b, c) VALUES ($1, DEFAULT, DEFAULT) Batch Size: 10 -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, NULL::integer + Output: "*VALUES*".column1, NULL::integer, NULL::integer (5 rows) insert into grem1 (a) values (1), (2); select * from gloc1; - a | b ----+--- - 1 | 2 - 2 | 4 + a | b | c +---+---+--- + 1 | 2 | + 2 | 4 | (2 rows) select * from grem1; - a | b ----+--- - 1 | 2 - 2 | 4 + a | b | c +---+---+--- + 1 | 2 | 3 + 2 | 4 | 6 (2 rows) delete from grem1; @@ -10290,7 +10532,7 @@ CREATE FOREIGN TABLE pg_temp.ft1_nopw ( ) SERVER loopback_nopw OPTIONS (schema_name 'public', table_name 'ft1'); SELECT 1 FROM ft1_nopw LIMIT 1; ERROR: password or GSSAPI delegated credentials required -DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping. +DETAIL: Non-superusers must delegate GSSAPI credentials, provide a password, or enable SCRAM pass-through in user mapping. -- If we add a password to the connstr it'll fail, because we don't allow passwords -- in connstrs only in user mappings. ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw'); @@ -10340,7 +10582,7 @@ DROP USER MAPPING FOR CURRENT_USER SERVER loopback_nopw; -- lacks password_required=false SELECT 1 FROM ft1_nopw LIMIT 1; ERROR: password or GSSAPI delegated credentials required -DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping. +DETAIL: Non-superusers must delegate GSSAPI credentials, provide a password, or enable SCRAM pass-through in user mapping. RESET ROLE; -- The user mapping for public is passwordless and lacks the password_required=false -- mapping option, but will work because the current user is a superuser. @@ -10461,13 +10703,20 @@ NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to user mapping for public on server loopback3 drop cascades to foreign table ft7 -- List all the existing cached connections. loopback and loopback3 --- should be output as invalid connections. Also the server name for --- loopback3 should be NULL because the server was dropped. -SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; - server_name | valid | used_in_xact | closed --------------+-------+--------------+-------- - loopback | f | t | - | f | t | +-- should be output as invalid connections. Also the server name and user name +-- for loopback3 should be NULL because both server and user mapping were +-- dropped. In this test, the PIDs of remote backends can be gathered from +-- pg_stat_activity, and remote_backend_pid should match one of those PIDs. +SELECT server_name, user_name = CURRENT_USER as "user_name = CURRENT_USER", + valid, used_in_xact, closed, + remote_backend_pid = ANY(SELECT pid FROM pg_stat_activity + WHERE backend_type = 'client backend' AND pid <> pg_backend_pid()) + as remote_backend_pid + FROM postgres_fdw_get_connections() ORDER BY 1; + server_name | user_name = CURRENT_USER | valid | used_in_xact | closed | remote_backend_pid +-------------+--------------------------+-------+--------------+--------+-------------------- + loopback | t | f | t | | t + | | f | t | | t (2 rows) -- The invalid connections get closed in pgfdw_xact_callback during commit. @@ -11540,17 +11789,17 @@ SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c Filter: (async_pt_3.a = local_tbl.a) (15 rows) -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; - QUERY PLAN -------------------------------------------------------------------------------- - Nested Loop (actual rows=1 loops=1) - -> Seq Scan on local_tbl (actual rows=1 loops=1) + QUERY PLAN +---------------------------------------------------------------------------------- + Nested Loop (actual rows=1.00 loops=1) + -> Seq Scan on local_tbl (actual rows=1.00 loops=1) Filter: (c = 'bar'::text) Rows Removed by Filter: 1 - -> Append (actual rows=1 loops=1) + -> Append (actual rows=1.00 loops=1) -> Async Foreign Scan on async_p1 async_pt_1 (never executed) - -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1 loops=1) + -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1.00 loops=1) -> Seq Scan on async_p3 async_pt_3 (never executed) Filter: (a = local_tbl.a) (9 rows) @@ -11786,22 +12035,22 @@ SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt W Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000)) (20 rows) -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; - QUERY PLAN ------------------------------------------------------------------------------------------ - Nested Loop Left Join (actual rows=1 loops=1) + QUERY PLAN +-------------------------------------------------------------------------------------------- + Nested Loop Left Join (actual rows=1.00 loops=1) Join Filter: (t1.a = async_pt.a) Rows Removed by Join Filter: 399 InitPlan 1 - -> Aggregate (actual rows=1 loops=1) - -> Append (actual rows=400 loops=1) - -> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1) - -> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200 loops=1) - -> Seq Scan on local_tbl t1 (actual rows=1 loops=1) - -> Append (actual rows=400 loops=1) - -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200 loops=1) - -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200 loops=1) + -> Aggregate (actual rows=1.00 loops=1) + -> Append (actual rows=400.00 loops=1) + -> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200.00 loops=1) + -> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200.00 loops=1) + -> Seq Scan on local_tbl t1 (actual rows=1.00 loops=1) + -> Append (actual rows=400.00 loops=1) + -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200.00 loops=1) + -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200.00 loops=1) (12 rows) SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; @@ -11830,17 +12079,17 @@ SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; Filter: (t1_3.b === 505) (14 rows) -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; - QUERY PLAN -------------------------------------------------------------------------- - Limit (actual rows=1 loops=1) - -> Append (actual rows=1 loops=1) - -> Async Foreign Scan on async_p1 t1_1 (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Limit (actual rows=1.00 loops=1) + -> Append (actual rows=1.00 loops=1) + -> Async Foreign Scan on async_p1 t1_1 (actual rows=0.00 loops=1) Filter: (b === 505) - -> Async Foreign Scan on async_p2 t1_2 (actual rows=0 loops=1) + -> Async Foreign Scan on async_p2 t1_2 (actual rows=0.00 loops=1) Filter: (b === 505) - -> Seq Scan on async_p3 t1_3 (actual rows=1 loops=1) + -> Seq Scan on async_p3 t1_3 (actual rows=1.00 loops=1) Filter: (b === 505) Rows Removed by Filter: 101 (9 rows) @@ -11990,14 +12239,14 @@ DELETE FROM async_pt WHERE b = 0 RETURNING *; DELETE FROM async_p1; DELETE FROM async_p2; DELETE FROM async_p3; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM async_pt; - QUERY PLAN -------------------------------------------------------------------------- - Append (actual rows=0 loops=1) - -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0 loops=1) - -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0 loops=1) - -> Seq Scan on async_p3 async_pt_3 (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) + -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0.00 loops=1) + -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0.00 loops=1) + -> Seq Scan on async_p3 async_pt_3 (actual rows=0.00 loops=1) (4 rows) -- Clean up @@ -12308,25 +12557,34 @@ SELECT 1 FROM ft1 LIMIT 1; -- Since the remote server is still connected, "closed" should be FALSE, -- or NULL if the connection status check is not available. -SELECT CASE WHEN closed IS NOT true THEN 1 ELSE 0 END +-- In this test, the remote backend handling this connection should have +-- application_name set to "fdw_conn_check", so remote_backend_pid should +-- match the PID from the pg_stat_activity entry with that application_name. +SELECT server_name, + CASE WHEN closed IS NOT true THEN false ELSE true END AS closed, + remote_backend_pid = (SELECT pid FROM pg_stat_activity + WHERE application_name = 'fdw_conn_check') AS remote_backend_pid FROM postgres_fdw_get_connections(true); - case ------- - 1 + server_name | closed | remote_backend_pid +-------------+--------+-------------------- + loopback | f | t (1 row) -- After terminating the remote backend, since the connection is closed, -- "closed" should be TRUE, or NULL if the connection status check --- is not available. +-- is not available. Despite the termination, remote_backend_pid should +-- still show the non-zero PID of the terminated remote backend. DO $$ BEGIN PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity WHERE application_name = 'fdw_conn_check'; END $$; -SELECT CASE WHEN closed IS NOT false THEN 1 ELSE 0 END +SELECT server_name, + CASE WHEN closed IS NOT false THEN true ELSE false END AS closed, + remote_backend_pid <> 0 AS remote_backend_pid FROM postgres_fdw_get_connections(true); - case ------- - 1 + server_name | closed | remote_backend_pid +-------------+--------+-------------------- + loopback | t | t (1 row) -- Clean up diff --git a/contrib/postgres_fdw/expected/query_cancel.out b/contrib/postgres_fdw/expected/query_cancel.out index afef67aa8deee..c3fc585d49f81 100644 --- a/contrib/postgres_fdw/expected/query_cancel.out +++ b/contrib/postgres_fdw/expected/query_cancel.out @@ -2,19 +2,33 @@ SELECT version() ~ 'cygwin' AS skip_test \gset \if :skip_test \quit \endif --- Make sure this big CROSS JOIN query is pushed down -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; +-- Let's test canceling a remote query. Use a table that does not have +-- remote_estimate enabled, else there will be multiple queries to the +-- remote and we might unluckily send the cancel in between two of them. +-- First let's confirm that the query is actually pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: (count(*)) - Relations: Aggregate on ((((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)) - Remote SQL: SELECT count(*) FROM ((("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (TRUE)) INNER JOIN "S 1"."T 3" r4 ON (TRUE)) INNER JOIN "S 1"."T 4" r6 ON (TRUE)) + Relations: Aggregate on ((((public.ft1 a) INNER JOIN (public.ft1 b)) INNER JOIN (public.ft1 c)) INNER JOIN (public.ft1 d)) + Remote SQL: SELECT count(*) FROM ((("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (TRUE)) INNER JOIN "S 1"."T 1" r4 ON (TRUE)) INNER JOIN "S 1"."T 1" r6 ON (TRUE)) (4 rows) --- Make sure query cancellation works BEGIN; +-- Make sure that connection is open and set up. +SELECT count(*) FROM ft1 a; + count +------- + 822 +(1 row) + +-- On most machines, 10ms will be enough to be sure that we've sent the slow +-- query. We may sometimes exercise the race condition where we send cancel +-- before the remote side starts the query, but that's fine too. SET LOCAL statement_timeout = '10ms'; -select count(*) from ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; -- this takes very long +-- This would take very long if not canceled: +SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; ERROR: canceling statement due to statement timeout COMMIT; diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build index 3014086ba641f..8b29be24deeb7 100644 --- a/contrib/postgres_fdw/meson.build +++ b/contrib/postgres_fdw/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group postgres_fdw_sources = files( 'connection.c', @@ -41,4 +41,9 @@ tests += { ], 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], }, + 'tap': { + 'tests': [ + 't/001_auth_scram.pl', + ], + }, } diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c index 630b304338ada..c2f936640bca8 100644 --- a/contrib/postgres_fdw/option.c +++ b/contrib/postgres_fdw/option.c @@ -3,7 +3,7 @@ * option.c * FDW and GUC option handling for postgres_fdw * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/option.c @@ -20,7 +20,6 @@ #include "commands/extension.h" #include "libpq/libpq-be.h" #include "postgres_fdw.h" -#include "utils/builtins.h" #include "utils/guc.h" #include "utils/varlena.h" @@ -280,6 +279,9 @@ InitPgFdwOptions(void) {"analyze_sampling", ForeignServerRelationId, false}, {"analyze_sampling", ForeignTableRelationId, false}, + {"use_scram_passthrough", ForeignServerRelationId, false}, + {"use_scram_passthrough", UserMappingRelationId, false}, + /* * sslcert and sslkey are in fact libpq options, but we repeat them * here to allow them to appear in both foreign server context (when @@ -346,6 +348,13 @@ InitPgFdwOptions(void) strcmp(lopt->keyword, "client_encoding") == 0) continue; + /* + * Disallow OAuth options for now, since the builtin flow communicates + * on stderr by default and can't cache tokens yet. + */ + if (strncmp(lopt->keyword, "oauth_", strlen("oauth_")) == 0) + continue; + /* We don't have to copy keyword string, as described above. */ popt->keyword = lopt->keyword; @@ -522,7 +531,7 @@ process_pgfdw_appname(const char *appname) appendStringInfoString(&buf, application_name); break; case 'c': - appendStringInfo(&buf, "%lx.%x", (long) (MyStartTime), MyProcPid); + appendStringInfo(&buf, INT64_HEX_FORMAT ".%x", MyStartTime, MyProcPid); break; case 'C': appendStringInfoString(&buf, cluster_name); diff --git a/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql b/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql index 0d406c6028af4..511a3e5c2ef71 100644 --- a/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql +++ b/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql @@ -11,7 +11,8 @@ DROP FUNCTION postgres_fdw_get_connections (); CREATE FUNCTION postgres_fdw_get_connections ( IN check_conn boolean DEFAULT false, OUT server_name text, - OUT valid boolean, OUT used_in_xact boolean, OUT closed boolean) + OUT user_name text, OUT valid boolean, OUT used_in_xact boolean, + OUT closed boolean, OUT remote_backend_pid int4) RETURNS SETOF record AS 'MODULE_PATHNAME', 'postgres_fdw_get_connections_1_2' LANGUAGE C STRICT PARALLEL RESTRICTED; diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index fc65d81e2177a..4283ce9f96252 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -3,7 +3,7 @@ * postgres_fdw.c * Foreign-data wrapper for remote PostgreSQL servers * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/postgres_fdw.c @@ -17,11 +17,10 @@ #include "access/htup_details.h" #include "access/sysattr.h" #include "access/table.h" -#include "catalog/pg_class.h" #include "catalog/pg_opfamily.h" #include "commands/defrem.h" -#include "commands/explain.h" -#include "commands/vacuum.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" #include "executor/execAsync.h" #include "foreign/fdwapi.h" #include "funcapi.h" @@ -29,7 +28,6 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/appendinfo.h" -#include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/inherit.h" #include "optimizer/optimizer.h" @@ -51,7 +49,10 @@ #include "utils/sampling.h" #include "utils/selfuncs.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "postgres_fdw", + .version = PG_VERSION +); /* Default CPU cost to start up a foreign query. */ #define DEFAULT_FDW_STARTUP_COST 100.0 @@ -239,6 +240,7 @@ typedef struct PgFdwDirectModifyState PGresult *result; /* result for query */ int num_tuples; /* # of result tuples */ int next_tuple; /* index of next one to return */ + MemoryContextCallback result_cb; /* ensures result will get freed */ Relation resultRel; /* relcache entry for the target relation */ AttrNumber *attnoMap; /* array of attnums of input user columns */ AttrNumber ctidAttno; /* attnum of input ctid column */ @@ -430,6 +432,7 @@ static void estimate_path_cost_size(PlannerInfo *root, List *pathkeys, PgFdwPathExtraData *fpextra, double *p_rows, int *p_width, + int *p_disabled_nodes, Cost *p_startup_cost, Cost *p_total_cost); static void get_remote_estimate(const char *sql, PGconn *conn, @@ -442,6 +445,7 @@ static void adjust_foreign_grouping_path_cost(PlannerInfo *root, double retrieved_rows, double width, double limit_tuples, + int *p_disabled_nodes, Cost *p_startup_cost, Cost *p_run_cost); static bool ec_member_matches_foreign(PlannerInfo *root, RelOptInfo *rel, @@ -631,7 +635,7 @@ postgresGetForeignRelSize(PlannerInfo *root, * functions. */ fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo)); - baserel->fdw_private = (void *) fpinfo; + baserel->fdw_private = fpinfo; /* Base foreign tables need to be pushed down always. */ fpinfo->pushdown_safe = true; @@ -735,6 +739,7 @@ postgresGetForeignRelSize(PlannerInfo *root, */ estimate_path_cost_size(root, baserel, NIL, NIL, NULL, &fpinfo->rows, &fpinfo->width, + &fpinfo->disabled_nodes, &fpinfo->startup_cost, &fpinfo->total_cost); /* Report estimated baserel size to planner. */ @@ -765,6 +770,7 @@ postgresGetForeignRelSize(PlannerInfo *root, /* Fill in basically-bogus cost estimates for use later. */ estimate_path_cost_size(root, baserel, NIL, NIL, NULL, &fpinfo->rows, &fpinfo->width, + &fpinfo->disabled_nodes, &fpinfo->startup_cost, &fpinfo->total_cost); } @@ -994,7 +1000,7 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel) /* Looks like we can generate a pathkey, so let's do it. */ pathkey = make_canonical_pathkey(root, cur_ec, linitial_oid(cur_ec->ec_opfamilies), - BTLessStrategyNumber, + COMPARE_LT, false); useful_pathkeys_list = lappend(useful_pathkeys_list, list_make1(pathkey)); @@ -1030,6 +1036,7 @@ postgresGetForeignPaths(PlannerInfo *root, path = create_foreignscan_path(root, baserel, NULL, /* default pathtarget */ fpinfo->rows, + fpinfo->disabled_nodes, fpinfo->startup_cost, fpinfo->total_cost, NIL, /* no pathkeys */ @@ -1130,7 +1137,7 @@ postgresGetForeignPaths(PlannerInfo *root, clauses = generate_implied_equalities_for_column(root, baserel, ec_member_matches_foreign, - (void *) &arg, + &arg, baserel->lateral_referencers); /* Done if there are no more expressions in the foreign rel */ @@ -1184,13 +1191,14 @@ postgresGetForeignPaths(PlannerInfo *root, ParamPathInfo *param_info = (ParamPathInfo *) lfirst(lc); double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; /* Get a cost estimate from the remote */ estimate_path_cost_size(root, baserel, param_info->ppi_clauses, NIL, NULL, - &rows, &width, + &rows, &width, &disabled_nodes, &startup_cost, &total_cost); /* @@ -1203,6 +1211,7 @@ postgresGetForeignPaths(PlannerInfo *root, path = create_foreignscan_path(root, baserel, NULL, /* default pathtarget */ rows, + disabled_nodes, startup_cost, total_cost, NIL, /* no pathkeys */ @@ -1510,7 +1519,7 @@ postgresBeginForeignScan(ForeignScanState *node, int eflags) * We'll save private state in node->fdw_state. */ fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState)); - node->fdw_state = (void *) fsstate; + node->fdw_state = fsstate; /* * Identify which user to do the remote access as. This should match what @@ -1814,7 +1823,7 @@ postgresPlanForeignModify(PlannerInfo *root, for (attnum = 1; attnum <= tupdesc->natts; attnum++) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1); if (!attr->attisdropped) targetAttrs = lappend_int(targetAttrs, attnum); @@ -2187,7 +2196,7 @@ postgresBeginForeignInsert(ModifyTableState *mtstate, /* We transmit all columns that are defined in the foreign table. */ for (attnum = 1; attnum <= tupdesc->natts; attnum++) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1); if (!attr->attisdropped) targetAttrs = lappend_int(targetAttrs, attnum); @@ -2660,7 +2669,18 @@ postgresBeginDirectModify(ForeignScanState *node, int eflags) * We'll save private state in node->fdw_state. */ dmstate = (PgFdwDirectModifyState *) palloc0(sizeof(PgFdwDirectModifyState)); - node->fdw_state = (void *) dmstate; + node->fdw_state = dmstate; + + /* + * We use a memory context callback to ensure that the dmstate's PGresult + * (if any) will be released, even if the query fails somewhere that's + * outside our control. The callback is always armed for the duration of + * the query; this relies on PQclear(NULL) being a no-op. + */ + dmstate->result_cb.func = (MemoryContextCallbackFunction) PQclear; + dmstate->result_cb.arg = NULL; + MemoryContextRegisterResetCallback(CurrentMemoryContext, + &dmstate->result_cb); /* * Identify which user to do the remote access as. This should match what @@ -2809,7 +2829,13 @@ postgresEndDirectModify(ForeignScanState *node) return; /* Release PGresult */ - PQclear(dmstate->result); + if (dmstate->result) + { + PQclear(dmstate->result); + dmstate->result = NULL; + /* ... and don't forget to disable the callback */ + dmstate->result_cb.arg = NULL; + } /* Release remote connection */ ReleaseConnection(dmstate->conn); @@ -3079,7 +3105,7 @@ postgresExecForeignTruncate(List *rels, * final sort and the LIMIT restriction. * * The function returns the cost and size estimates in p_rows, p_width, - * p_startup_cost and p_total_cost variables. + * p_disabled_nodes, p_startup_cost and p_total_cost variables. */ static void estimate_path_cost_size(PlannerInfo *root, @@ -3088,12 +3114,14 @@ estimate_path_cost_size(PlannerInfo *root, List *pathkeys, PgFdwPathExtraData *fpextra, double *p_rows, int *p_width, + int *p_disabled_nodes, Cost *p_startup_cost, Cost *p_total_cost) { PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private; double rows; double retrieved_rows; int width; + int disabled_nodes = 0; Cost startup_cost; Cost total_cost; @@ -3326,7 +3354,7 @@ estimate_path_cost_size(PlannerInfo *root, { RelOptInfo *outerrel = fpinfo->outerrel; PgFdwRelationInfo *ofpinfo; - AggClauseCosts aggcosts; + AggClauseCosts aggcosts = {0}; double input_rows; int numGroupCols; double numGroups = 1; @@ -3350,7 +3378,6 @@ estimate_path_cost_size(PlannerInfo *root, input_rows = ofpinfo->rows; /* Collect statistics about aggregates for estimating costs. */ - MemSet(&aggcosts, 0, sizeof(AggClauseCosts)); if (root->parse->hasAggs) { get_agg_clause_costs(root, AGGSPLIT_SIMPLE, &aggcosts); @@ -3483,6 +3510,7 @@ estimate_path_cost_size(PlannerInfo *root, adjust_foreign_grouping_path_cost(root, pathkeys, retrieved_rows, width, fpextra->limit_tuples, + &disabled_nodes, &startup_cost, &run_cost); } else @@ -3577,6 +3605,7 @@ estimate_path_cost_size(PlannerInfo *root, /* Return results. */ *p_rows = rows; *p_width = width; + *p_disabled_nodes = disabled_nodes; *p_startup_cost = startup_cost; *p_total_cost = total_cost; } @@ -3637,6 +3666,7 @@ adjust_foreign_grouping_path_cost(PlannerInfo *root, double retrieved_rows, double width, double limit_tuples, + int *p_disabled_nodes, Cost *p_startup_cost, Cost *p_run_cost) { @@ -3656,6 +3686,7 @@ adjust_foreign_grouping_path_cost(PlannerInfo *root, cost_sort(&sort_path, root, pathkeys, + 0, *p_startup_cost + *p_run_cost, retrieved_rows, width, @@ -4301,7 +4332,7 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate, foreach(lc, fmstate->target_attrs) { int attnum = lfirst_int(lc); - Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, attnum - 1); Datum value; bool isnull; @@ -4578,13 +4609,17 @@ execute_dml_stmt(ForeignScanState *node) /* * Get the result, and check for success. * - * We don't use a PG_TRY block here, so be careful not to throw error - * without releasing the PGresult. + * We use a memory context callback to ensure that the PGresult will be + * released, even if the query fails somewhere that's outside our control. + * The callback is already registered, just need to fill in its arg. */ + Assert(dmstate->result == NULL); dmstate->result = pgfdw_get_result(dmstate->conn); + dmstate->result_cb.arg = dmstate->result; + if (PQresultStatus(dmstate->result) != (dmstate->has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK)) - pgfdw_report_error(ERROR, dmstate->result, dmstate->conn, true, + pgfdw_report_error(ERROR, dmstate->result, dmstate->conn, false, dmstate->query); /* Get the number of rows affected. */ @@ -4628,30 +4663,16 @@ get_returning_data(ForeignScanState *node) } else { - /* - * On error, be sure to release the PGresult on the way out. Callers - * do not have PG_TRY blocks to ensure this happens. - */ - PG_TRY(); - { - HeapTuple newtup; - - newtup = make_tuple_from_result_row(dmstate->result, - dmstate->next_tuple, - dmstate->rel, - dmstate->attinmeta, - dmstate->retrieved_attrs, - node, - dmstate->temp_cxt); - ExecStoreHeapTuple(newtup, slot, false); - } - PG_CATCH(); - { - PQclear(dmstate->result); - PG_RE_THROW(); - } - PG_END_TRY(); + HeapTuple newtup; + newtup = make_tuple_from_result_row(dmstate->result, + dmstate->next_tuple, + dmstate->rel, + dmstate->attinmeta, + dmstate->retrieved_attrs, + node, + dmstate->temp_cxt); + ExecStoreHeapTuple(newtup, slot, false); /* Get the updated/deleted tuple. */ if (dmstate->rel) resultSlot = slot; @@ -5650,13 +5671,13 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) attname = PQgetvalue(res, i, 1); typename = PQgetvalue(res, i, 2); attnotnull = PQgetvalue(res, i, 3); - attdefault = PQgetisnull(res, i, 4) ? (char *) NULL : + attdefault = PQgetisnull(res, i, 4) ? NULL : PQgetvalue(res, i, 4); - attgenerated = PQgetisnull(res, i, 5) ? (char *) NULL : + attgenerated = PQgetisnull(res, i, 5) ? NULL : PQgetvalue(res, i, 5); - collname = PQgetisnull(res, i, 6) ? (char *) NULL : + collname = PQgetisnull(res, i, 6) ? NULL : PQgetvalue(res, i, 6); - collnamespace = PQgetisnull(res, i, 7) ? (char *) NULL : + collnamespace = PQgetisnull(res, i, 7) ? NULL : PQgetvalue(res, i, 7); if (first_item) @@ -5758,8 +5779,7 @@ semijoin_target_ok(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, if (!IsA(var, Var)) continue; - if (bms_is_member(var->varno, innerrel->relids) && - !bms_is_member(var->varno, outerrel->relids)) + if (bms_is_member(var->varno, innerrel->relids)) { /* * The planner can create semi-join, which refers to inner rel @@ -5767,6 +5787,7 @@ semijoin_target_ok(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, * exists() subquery, so can't handle references to inner rel in * the target list. */ + Assert(!bms_is_member(var->varno, outerrel->relids)); ok = false; break; } @@ -5953,17 +5974,33 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, break; case JOIN_LEFT: - fpinfo->joinclauses = list_concat(fpinfo->joinclauses, - fpinfo_i->remote_conds); - fpinfo->remote_conds = list_concat(fpinfo->remote_conds, - fpinfo_o->remote_conds); + + /* + * When semi-join is involved in the inner or outer part of the + * left join, it's deparsed as a subquery, and we can't refer to + * its vars on the upper level. + */ + if (bms_is_empty(fpinfo_i->hidden_subquery_rels)) + fpinfo->joinclauses = list_concat(fpinfo->joinclauses, + fpinfo_i->remote_conds); + if (bms_is_empty(fpinfo_o->hidden_subquery_rels)) + fpinfo->remote_conds = list_concat(fpinfo->remote_conds, + fpinfo_o->remote_conds); break; case JOIN_RIGHT: - fpinfo->joinclauses = list_concat(fpinfo->joinclauses, - fpinfo_o->remote_conds); - fpinfo->remote_conds = list_concat(fpinfo->remote_conds, - fpinfo_i->remote_conds); + + /* + * When semi-join is involved in the inner or outer part of the + * right join, it's deparsed as a subquery, and we can't refer to + * its vars on the upper level. + */ + if (bms_is_empty(fpinfo_o->hidden_subquery_rels)) + fpinfo->joinclauses = list_concat(fpinfo->joinclauses, + fpinfo_o->remote_conds); + if (bms_is_empty(fpinfo_i->hidden_subquery_rels)) + fpinfo->remote_conds = list_concat(fpinfo->remote_conds, + fpinfo_i->remote_conds); break; case JOIN_SEMI: @@ -6147,13 +6184,15 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, { double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; List *useful_pathkeys = lfirst(lc); Path *sorted_epq_path; estimate_path_cost_size(root, rel, NIL, useful_pathkeys, NULL, - &rows, &width, &startup_cost, &total_cost); + &rows, &width, &disabled_nodes, + &startup_cost, &total_cost); /* * The EPQ path must be at least as well sorted as the path itself, in @@ -6175,6 +6214,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, create_foreignscan_path(root, rel, NULL, rows, + disabled_nodes, startup_cost, total_cost, useful_pathkeys, @@ -6188,6 +6228,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel, create_foreign_join_path(root, rel, NULL, rows, + disabled_nodes, startup_cost, total_cost, useful_pathkeys, @@ -6335,6 +6376,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root, ForeignPath *joinpath; double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; Path *epq_path; /* Path to create plan to be executed when @@ -6424,12 +6466,14 @@ postgresGetForeignJoinPaths(PlannerInfo *root, /* Estimate costs for bare join relation */ estimate_path_cost_size(root, joinrel, NIL, NIL, NULL, - &rows, &width, &startup_cost, &total_cost); + &rows, &width, &disabled_nodes, + &startup_cost, &total_cost); /* Now update this information in the joinrel */ joinrel->rows = rows; joinrel->reltarget->width = width; fpinfo->rows = rows; fpinfo->width = width; + fpinfo->disabled_nodes = disabled_nodes; fpinfo->startup_cost = startup_cost; fpinfo->total_cost = total_cost; @@ -6441,6 +6485,7 @@ postgresGetForeignJoinPaths(PlannerInfo *root, joinrel, NULL, /* default pathtarget */ rows, + disabled_nodes, startup_cost, total_cost, NIL, /* no pathkeys */ @@ -6768,6 +6813,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, ForeignPath *grouppath; double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; @@ -6818,11 +6864,13 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, /* Estimate the cost of push down */ estimate_path_cost_size(root, grouped_rel, NIL, NIL, NULL, - &rows, &width, &startup_cost, &total_cost); + &rows, &width, &disabled_nodes, + &startup_cost, &total_cost); /* Now update this information in the fpinfo */ fpinfo->rows = rows; fpinfo->width = width; + fpinfo->disabled_nodes = disabled_nodes; fpinfo->startup_cost = startup_cost; fpinfo->total_cost = total_cost; @@ -6831,6 +6879,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, grouped_rel, grouped_rel->reltarget, rows, + disabled_nodes, startup_cost, total_cost, NIL, /* no pathkeys */ @@ -6859,6 +6908,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, PgFdwPathExtraData *fpextra; double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; List *fdw_private; @@ -6952,7 +7002,8 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, /* Estimate the costs of performing the final sort remotely */ estimate_path_cost_size(root, input_rel, NIL, root->sort_pathkeys, fpextra, - &rows, &width, &startup_cost, &total_cost); + &rows, &width, &disabled_nodes, + &startup_cost, &total_cost); /* * Build the fdw_private list that will be used by postgresGetForeignPlan. @@ -6965,6 +7016,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, input_rel, root->upper_targets[UPPERREL_ORDERED], rows, + disabled_nodes, startup_cost, total_cost, root->sort_pathkeys, @@ -6998,6 +7050,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, bool save_use_remote_estimate = false; double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; List *fdw_private; @@ -7082,6 +7135,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, path->parent, path->pathtarget, path->rows, + path->disabled_nodes, path->startup_cost, path->total_cost, path->pathkeys, @@ -7199,7 +7253,8 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, ifpinfo->use_remote_estimate = false; } estimate_path_cost_size(root, input_rel, NIL, pathkeys, fpextra, - &rows, &width, &startup_cost, &total_cost); + &rows, &width, &disabled_nodes, + &startup_cost, &total_cost); if (!fpextra->has_final_sort) ifpinfo->use_remote_estimate = save_use_remote_estimate; @@ -7218,6 +7273,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, input_rel, root->upper_targets[UPPERREL_FINAL], rows, + disabled_nodes, startup_cost, total_cost, pathkeys, @@ -7589,7 +7645,7 @@ make_tuple_from_result_row(PGresult *res, errpos.rel = rel; errpos.fsstate = fsstate; errcallback.callback = conversion_error_callback; - errcallback.arg = (void *) &errpos; + errcallback.arg = &errpos; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -7799,14 +7855,13 @@ conversion_error_callback(void *arg) EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel) { - ListCell *lc; - PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private; + EquivalenceMemberIterator it; + EquivalenceMember *em; - foreach(lc, ec->ec_members) + setup_eclass_member_iterator(&it, ec, rel->relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *em = (EquivalenceMember *) lfirst(lc); - /* * Note we require !bms_is_empty, else we'd accept constant * expressions which are not suitable for the purpose. @@ -7860,7 +7915,10 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, while (expr && IsA(expr, RelabelType)) expr = ((RelabelType *) expr)->arg; - /* Locate an EquivalenceClass member matching this expr, if any */ + /* + * Locate an EquivalenceClass member matching this expr, if any. + * Ignore child members. + */ foreach(lc2, ec->ec_members) { EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); @@ -7870,9 +7928,8 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, if (em->em_is_const) continue; - /* Ignore child members */ - if (em->em_is_child) - continue; + /* Child members should not exist in ec_members */ + Assert(!em->em_is_child); /* Match if same expression (after stripping relabel) */ em_expr = em->em_expr; diff --git a/contrib/postgres_fdw/postgres_fdw.h b/contrib/postgres_fdw/postgres_fdw.h index 37c1575af6c21..81358f3bde7df 100644 --- a/contrib/postgres_fdw/postgres_fdw.h +++ b/contrib/postgres_fdw/postgres_fdw.h @@ -3,7 +3,7 @@ * postgres_fdw.h * Foreign-data wrapper for remote PostgreSQL servers * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/postgres_fdw.h @@ -62,6 +62,7 @@ typedef struct PgFdwRelationInfo /* Estimated size and cost for a scan, join, or grouping/aggregation. */ double rows; int width; + int disabled_nodes; Cost startup_cost; Cost total_cost; diff --git a/contrib/postgres_fdw/shippable.c b/contrib/postgres_fdw/shippable.c index ad91660696803..da3b13b207d17 100644 --- a/contrib/postgres_fdw/shippable.c +++ b/contrib/postgres_fdw/shippable.c @@ -13,7 +13,7 @@ * functions or functions using nonportable collations. Those considerations * need not be accounted for here. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/postgres_fdw/shippable.c diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 371e1319338a6..e534b40de3c76 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -213,6 +213,14 @@ ALTER USER MAPPING FOR public SERVER testserver1 ALTER USER MAPPING FOR public SERVER testserver1 OPTIONS (ADD sslkey 'value', ADD sslcert 'value'); +-- OAuth options are not allowed in either context +ALTER SERVER testserver1 OPTIONS (ADD oauth_issuer 'https://example.com'); +ALTER SERVER testserver1 OPTIONS (ADD oauth_client_id 'myID'); +ALTER USER MAPPING FOR public SERVER testserver1 + OPTIONS (ADD oauth_issuer 'https://example.com'); +ALTER USER MAPPING FOR public SERVER testserver1 + OPTIONS (ADD oauth_client_id 'myID'); + ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1'); ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1'); ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); @@ -327,6 +335,14 @@ DELETE FROM loct_empty; ANALYZE ft_empty; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1; +-- test restriction on non-system foreign tables. +SET restrict_nonsystem_relation_kind TO 'foreign-table'; +SELECT * from ft1 where c1 < 1; -- ERROR +INSERT INTO ft1 (c1) VALUES (1); -- ERROR +DELETE FROM ft1 WHERE c1 = 1; -- ERROR +TRUNCATE ft1; -- ERROR +RESET restrict_nonsystem_relation_kind; + -- =================================================================== -- WHERE with remotely-executable conditions -- =================================================================== @@ -699,6 +715,11 @@ SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = f AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM ft1, ft4, ft5, local_tbl WHERE ft1.c1 = ft4.c1 AND ft1.c1 = ft5.c1 + AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft5.c1 < 100 FOR UPDATE; +SELECT * FROM ft1, ft4, ft5, local_tbl WHERE ft1.c1 = ft4.c1 AND ft1.c1 = ft5.c1 + AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft5.c1 < 100 FOR UPDATE; RESET enable_nestloop; RESET enable_hashjoin; @@ -1447,6 +1468,23 @@ SELECT ft2.*, ft4.* FROM ft2 INNER JOIN WHERE ft2.c1 > 900 ORDER BY ft2.c1 LIMIT 10; +-- Semi-join conditions shouldn't pop up as left/right join clauses. +SET enable_material TO off; +EXPLAIN (verbose, costs off) +SELECT x1.c1 FROM + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x1 + RIGHT JOIN + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x2 + ON (x1.c1 = x2.c1) +ORDER BY x1.c1 LIMIT 10; +SELECT x1.c1 FROM + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x1 + RIGHT JOIN + (SELECT * FROM ft2 WHERE EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft2.c1 AND ft2.c2 < 10)) x2 + ON (x1.c1 = x2.c1) +ORDER BY x1.c1 LIMIT 10; +RESET enable_material; + -- Can't push down semi-join with inner rel vars in targetlist EXPLAIN (verbose, costs off) SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE @@ -1461,7 +1499,7 @@ EXPLAIN (verbose, costs off) INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; INSERT INTO ft2 (c1,c2,c3) - VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *; + VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING old, new, old.*, new.*; INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down @@ -1469,6 +1507,13 @@ UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *; -- can be pushed down UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *; +BEGIN; + EXPLAIN (verbose, costs off) + UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40 + RETURNING old.*, new.*; -- can't be pushed down + UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7b' WHERE c1 % 10 = 7 AND c1 < 40 + RETURNING old.*, new.*; +ROLLBACK; EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down @@ -1477,6 +1522,11 @@ UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT EXPLAIN (verbose, costs off) DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; -- can be pushed down DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; +BEGIN; + EXPLAIN (verbose, costs off) + DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; -- can't be pushed down + DELETE FROM ft2 WHERE c1 % 10 = 6 AND c1 < 40 RETURNING old.c1, c4; +ROLLBACK; EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; @@ -1503,6 +1553,17 @@ UPDATE ft2 SET c3 = 'foo' FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1 RETURNING ft2, ft2.*, ft4, ft4.*; +BEGIN; + EXPLAIN (verbose, costs off) + UPDATE ft2 SET c3 = 'bar' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1 + RETURNING old, new, ft2, ft2.*, ft4, ft4.*; -- can't be pushed down + UPDATE ft2 SET c3 = 'bar' + FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) + WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1 + RETURNING old, new, ft2, ft2.*, ft4, ft4.*; +ROLLBACK; EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) @@ -1828,12 +1889,15 @@ select * from rem1; -- =================================================================== create table gloc1 ( a int, - b int generated always as (a * 2) stored); + b int generated always as (a * 2) stored, + c int +); alter table gloc1 set (autovacuum_enabled = 'false'); create foreign table grem1 ( a int, - b int generated always as (a * 2) stored) - server loopback options(table_name 'gloc1'); + b int generated always as (a * 2) stored, + c int generated always as (a * 3) virtual +) server loopback options(table_name 'gloc1'); explain (verbose, costs off) insert into grem1 (a) values (1), (2); insert into grem1 (a) values (1), (2); @@ -3374,9 +3438,16 @@ SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1; ALTER SERVER loopback OPTIONS (ADD use_remote_estimate 'off'); DROP SERVER loopback3 CASCADE; -- List all the existing cached connections. loopback and loopback3 --- should be output as invalid connections. Also the server name for --- loopback3 should be NULL because the server was dropped. -SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; +-- should be output as invalid connections. Also the server name and user name +-- for loopback3 should be NULL because both server and user mapping were +-- dropped. In this test, the PIDs of remote backends can be gathered from +-- pg_stat_activity, and remote_backend_pid should match one of those PIDs. +SELECT server_name, user_name = CURRENT_USER as "user_name = CURRENT_USER", + valid, used_in_xact, closed, + remote_backend_pid = ANY(SELECT pid FROM pg_stat_activity + WHERE backend_type = 'client backend' AND pid <> pg_backend_pid()) + as remote_backend_pid + FROM postgres_fdw_get_connections() ORDER BY 1; -- The invalid connections get closed in pgfdw_xact_callback during commit. COMMIT; -- All cached connections were closed while committing above xact, so no @@ -3894,7 +3965,7 @@ ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true'); EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; @@ -3969,13 +4040,13 @@ ANALYZE local_tbl; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; @@ -4027,7 +4098,7 @@ DELETE FROM async_p1; DELETE FROM async_p2; DELETE FROM async_p3; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) SELECT * FROM async_pt; -- Clean up @@ -4252,17 +4323,26 @@ SELECT 1 FROM ft1 LIMIT 1; -- Since the remote server is still connected, "closed" should be FALSE, -- or NULL if the connection status check is not available. -SELECT CASE WHEN closed IS NOT true THEN 1 ELSE 0 END +-- In this test, the remote backend handling this connection should have +-- application_name set to "fdw_conn_check", so remote_backend_pid should +-- match the PID from the pg_stat_activity entry with that application_name. +SELECT server_name, + CASE WHEN closed IS NOT true THEN false ELSE true END AS closed, + remote_backend_pid = (SELECT pid FROM pg_stat_activity + WHERE application_name = 'fdw_conn_check') AS remote_backend_pid FROM postgres_fdw_get_connections(true); -- After terminating the remote backend, since the connection is closed, -- "closed" should be TRUE, or NULL if the connection status check --- is not available. +-- is not available. Despite the termination, remote_backend_pid should +-- still show the non-zero PID of the terminated remote backend. DO $$ BEGIN PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity WHERE application_name = 'fdw_conn_check'; END $$; -SELECT CASE WHEN closed IS NOT false THEN 1 ELSE 0 END +SELECT server_name, + CASE WHEN closed IS NOT false THEN true ELSE false END AS closed, + remote_backend_pid <> 0 AS remote_backend_pid FROM postgres_fdw_get_connections(true); -- Clean up diff --git a/contrib/postgres_fdw/sql/query_cancel.sql b/contrib/postgres_fdw/sql/query_cancel.sql index 8f11f3f9a6a2c..a68307058436b 100644 --- a/contrib/postgres_fdw/sql/query_cancel.sql +++ b/contrib/postgres_fdw/sql/query_cancel.sql @@ -3,10 +3,20 @@ SELECT version() ~ 'cygwin' AS skip_test \gset \quit \endif --- Make sure this big CROSS JOIN query is pushed down -EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; --- Make sure query cancellation works +-- Let's test canceling a remote query. Use a table that does not have +-- remote_estimate enabled, else there will be multiple queries to the +-- remote and we might unluckily send the cancel in between two of them. +-- First let's confirm that the query is actually pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; + BEGIN; +-- Make sure that connection is open and set up. +SELECT count(*) FROM ft1 a; +-- On most machines, 10ms will be enough to be sure that we've sent the slow +-- query. We may sometimes exercise the race condition where we send cancel +-- before the remote side starts the query, but that's fine too. SET LOCAL statement_timeout = '10ms'; -select count(*) from ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; -- this takes very long +-- This would take very long if not canceled: +SELECT count(*) FROM ft1 a CROSS JOIN ft1 b CROSS JOIN ft1 c CROSS JOIN ft1 d; COMMIT; diff --git a/contrib/postgres_fdw/t/001_auth_scram.pl b/contrib/postgres_fdw/t/001_auth_scram.pl new file mode 100644 index 0000000000000..b94a6a6293bad --- /dev/null +++ b/contrib/postgres_fdw/t/001_auth_scram.pl @@ -0,0 +1,197 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# Test SCRAM authentication when opening a new connection with a foreign +# server. +# +# The test is executed by testing the SCRAM authentifcation on a loopback +# connection on the same server and with different servers. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +my $hostaddr = '127.0.0.1'; +my $user = "user01"; + +my $db0 = "db0"; # For node1 +my $db1 = "db1"; # For node1 +my $db2 = "db2"; # For node2 +my $fdw_server = "db1_fdw"; +my $fdw_server2 = "db2_fdw"; + +my $node1 = PostgreSQL::Test::Cluster->new('node1'); +my $node2 = PostgreSQL::Test::Cluster->new('node2'); + +$node1->init; +$node2->init; + +$node1->start; +$node2->start; + +# Test setup + +$node1->safe_psql('postgres', qq'CREATE USER $user WITH password \'pass\''); +$node2->safe_psql('postgres', qq'CREATE USER $user WITH password \'pass\''); +$ENV{PGPASSWORD} = "pass"; + +$node1->safe_psql('postgres', qq'CREATE DATABASE $db0'); +$node1->safe_psql('postgres', qq'CREATE DATABASE $db1'); +$node2->safe_psql('postgres', qq'CREATE DATABASE $db2'); + +setup_table($node1, $db1, "t"); +setup_table($node2, $db2, "t2"); + +$node1->safe_psql($db0, 'CREATE EXTENSION IF NOT EXISTS postgres_fdw'); +setup_fdw_server($node1, $db0, $fdw_server, $node1, $db1); +setup_fdw_server($node1, $db0, $fdw_server2, $node2, $db2); + +setup_user_mapping($node1, $db0, $fdw_server); +setup_user_mapping($node1, $db0, $fdw_server2); + +# Make the user have the same SCRAM key on both servers. Forcing to have the +# same iteration and salt. +my $rolpassword = $node1->safe_psql('postgres', + qq"SELECT rolpassword FROM pg_authid WHERE rolname = '$user';"); +$node2->safe_psql('postgres', qq"ALTER ROLE $user PASSWORD '$rolpassword'"); + +setup_pghba($node1); +setup_pghba($node2); + +# End of test setup + +test_fdw_auth($node1, $db0, "t", $fdw_server, + "SCRAM auth on the same database cluster must succeed"); +test_fdw_auth($node1, $db0, "t2", $fdw_server2, + "SCRAM auth on a different database cluster must succeed"); +test_auth($node2, $db2, "t2", + "SCRAM auth directly on foreign server should still succeed"); + +SKIP: +{ + skip "test requires Unix-domain sockets", 4 if !$use_unix_sockets; + + # Ensure that trust connections fail without superuser opt-in. + unlink($node1->data_dir . '/pg_hba.conf'); + unlink($node2->data_dir . '/pg_hba.conf'); + + $node1->append_conf( + 'pg_hba.conf', qq{ +local db0 all scram-sha-256 +local db1 all trust +} + ); + $node2->append_conf( + 'pg_hba.conf', qq{ +local all all password +} + ); + + $node1->restart; + $node2->restart; + + my ($ret, $stdout, $stderr) = $node1->psql( + $db0, + qq'select count(1) from t', + connstr => $node1->connstr($db0) . " user=$user"); + + is($ret, 3, 'loopback trust fails on the same cluster'); + like( + $stderr, + qr/failed: authentication method requirement "scram-sha-256"/, + 'expected error from loopback trust (same cluster)'); + + ($ret, $stdout, $stderr) = $node1->psql( + $db0, + qq'select count(1) from t2', + connstr => $node1->connstr($db0) . " user=$user"); + + is($ret, 3, 'loopback password fails on a different cluster'); + like( + $stderr, + qr/failed: authentication method requirement "scram-sha-256"/, + 'expected error from loopback password (different cluster)'); +} + +# Helper functions + +sub test_auth +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($node, $db, $tbl, $testname) = @_; + my $connstr = $node->connstr($db) . qq' user=$user'; + + my $ret = $node->safe_psql( + $db, + qq'SELECT count(1) FROM $tbl', + connstr => $connstr); + + is($ret, '10', $testname); +} + +sub test_fdw_auth +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($node, $db, $tbl, $fdw, $testname) = @_; + my $connstr = $node->connstr($db) . qq' user=$user'; + + $node->safe_psql( + $db, + qq'IMPORT FOREIGN SCHEMA public LIMIT TO ($tbl) FROM SERVER $fdw INTO public;', + connstr => $connstr); + + test_auth($node, $db, $tbl, $testname); +} + +sub setup_pghba +{ + my ($node) = @_; + + unlink($node->data_dir . '/pg_hba.conf'); + $node->append_conf( + 'pg_hba.conf', qq{ + local all all scram-sha-256 + host all all $hostaddr/32 scram-sha-256 + }); + + $node->restart; +} + +sub setup_user_mapping +{ + my ($node, $db, $fdw) = @_; + + $node->safe_psql($db, + qq'CREATE USER MAPPING FOR $user SERVER $fdw OPTIONS (user \'$user\');' + ); + $node->safe_psql($db, qq'GRANT USAGE ON FOREIGN SERVER $fdw TO $user;'); + $node->safe_psql($db, qq'GRANT ALL ON SCHEMA public TO $user'); +} + +sub setup_fdw_server +{ + my ($node, $db, $fdw, $fdw_node, $dbname) = @_; + my $host = $fdw_node->host; + my $port = $fdw_node->port; + + $node->safe_psql( + $db, qq'CREATE SERVER $fdw FOREIGN DATA WRAPPER postgres_fdw options ( + host \'$host\', port \'$port\', dbname \'$dbname\', use_scram_passthrough \'true\') ' + ); +} + +sub setup_table +{ + my ($node, $db, $tbl) = @_; + + $node->safe_psql($db, + qq'CREATE TABLE $tbl AS SELECT g, g + 1 FROM generate_series(1,10) g(g)' + ); + $node->safe_psql($db, qq'GRANT USAGE ON SCHEMA public TO $user'); + $node->safe_psql($db, qq'GRANT SELECT ON $tbl TO $user'); +} + +done_testing(); diff --git a/contrib/seg/Makefile b/contrib/seg/Makefile index 132ec8dbfeaab..b408f4049cbd7 100644 --- a/contrib/seg/Makefile +++ b/contrib/seg/Makefile @@ -14,7 +14,7 @@ PGFILEDESC = "seg - line segment data type" HEADERS = segdata.h -REGRESS = security seg +REGRESS = security seg partition EXTRA_CLEAN = segparse.h segparse.c segscan.c diff --git a/contrib/seg/expected/partition.out b/contrib/seg/expected/partition.out new file mode 100644 index 0000000000000..90d8397d5d461 --- /dev/null +++ b/contrib/seg/expected/partition.out @@ -0,0 +1,54 @@ +-- +-- Test that partitioned-index operations cope with objects that are +-- not in the secure search path. (This has little to do with seg, +-- but we need an opclass that isn't in pg_catalog, and the base system +-- has no such opclass.) Note that we need to test propagation of the +-- partitioned index's properties both to partitions that pre-date it +-- and to partitions created later. +-- +create function mydouble(int) returns int strict immutable parallel safe +begin atomic select $1 * 2; end; +create collation mycollation from "POSIX"; +create table pt (category int, sdata seg, tdata text) + partition by list (category); +-- pre-existing partition +create table pt12 partition of pt for values in (1,2); +insert into pt values(1, '0 .. 1'::seg, 'zed'); +-- expression references object in public schema +create index pti1 on pt ((mydouble(category) + 1)); +-- opclass in public schema +create index pti2 on pt (sdata seg_ops); +-- collation in public schema +create index pti3 on pt (tdata collate mycollation); +-- new partition +create table pt34 partition of pt for values in (3,4); +insert into pt values(4, '-1 .. 1'::seg, 'foo'); +\d+ pt + Partitioned table "public.pt" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +----------+---------+-----------+----------+---------+----------+--------------+------------- + category | integer | | | | plain | | + sdata | seg | | | | plain | | + tdata | text | | | | extended | | +Partition key: LIST (category) +Indexes: + "pti1" btree ((mydouble(category) + 1)) + "pti2" btree (sdata) + "pti3" btree (tdata COLLATE mycollation) +Partitions: pt12 FOR VALUES IN (1, 2), + pt34 FOR VALUES IN (3, 4) + +\d+ pt12 + Table "public.pt12" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +----------+---------+-----------+----------+---------+----------+--------------+------------- + category | integer | | | | plain | | + sdata | seg | | | | plain | | + tdata | text | | | | extended | | +Partition of: pt FOR VALUES IN (1, 2) +Partition constraint: ((category IS NOT NULL) AND (category = ANY (ARRAY[1, 2]))) +Indexes: + "pt12_expr_idx" btree ((mydouble(category) + 1)) + "pt12_sdata_idx" btree (sdata) + "pt12_tdata_idx" btree (tdata COLLATE mycollation) + diff --git a/contrib/seg/meson.build b/contrib/seg/meson.build index abeaf08eff161..e331e0972306a 100644 --- a/contrib/seg/meson.build +++ b/contrib/seg/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group seg_sources = files( 'seg.c', @@ -55,6 +55,7 @@ tests += { 'sql': [ 'security', 'seg', + 'partition', ], }, } diff --git a/contrib/seg/seg-validate.pl b/contrib/seg/seg-validate.pl index 22cbca966d6e0..bf8e47f8c1f2c 100755 --- a/contrib/seg/seg-validate.pl +++ b/contrib/seg/seg-validate.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c index 7f9fc24eb4b60..151cbb954b9a1 100644 --- a/contrib/seg/seg.c +++ b/contrib/seg/seg.c @@ -28,7 +28,10 @@ #define GIST_QUERY_DEBUG */ -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "seg", + .version = PG_VERSION +); /* * Auxiliary data structure for picksplit method. @@ -105,13 +108,14 @@ seg_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); SEG *result = palloc(sizeof(SEG)); + yyscan_t scanner; - seg_scanner_init(str); + seg_scanner_init(str, &scanner); - if (seg_yyparse(result, fcinfo->context) != 0) - seg_yyerror(result, fcinfo->context, "bogus input"); + if (seg_yyparse(result, fcinfo->context, scanner) != 0) + seg_yyerror(result, fcinfo->context, scanner, "bogus input"); - seg_scanner_finish(); + seg_scanner_finish(scanner); PG_RETURN_POINTER(result); } diff --git a/contrib/seg/segdata.h b/contrib/seg/segdata.h index 3d6e3e3f24506..4347c31c28e94 100644 --- a/contrib/seg/segdata.h +++ b/contrib/seg/segdata.h @@ -14,12 +14,20 @@ typedef struct SEG /* in seg.c */ extern int significant_digits(const char *s); +/* for segscan.l and segparse.y */ +union YYSTYPE; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif + /* in segscan.l */ -extern int seg_yylex(void); +extern int seg_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner); extern void seg_yyerror(SEG *result, struct Node *escontext, + yyscan_t yyscanner, const char *message); -extern void seg_scanner_init(const char *str); -extern void seg_scanner_finish(void); +extern void seg_scanner_init(const char *str, yyscan_t *yyscannerp); +extern void seg_scanner_finish(yyscan_t yyscanner); /* in segparse.y */ -extern int seg_yyparse(SEG *result, struct Node *escontext); +extern int seg_yyparse(SEG *result, struct Node *escontext, yyscan_t yyscanner); diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y index 729d4b6390b0a..0358ddb182cb5 100644 --- a/contrib/seg/segparse.y +++ b/contrib/seg/segparse.y @@ -12,10 +12,7 @@ #include "utils/float.h" #include "segdata.h" - -/* silence -Wmissing-variable-declarations */ -extern int seg_yychar; -extern int seg_yynerrs; +#include "segparse.h" /* * Bison doesn't allocate anything that needs to live across parser calls, @@ -29,19 +26,14 @@ static bool seg_atof(char *value, float *result, struct Node *escontext); static int sig_digits(const char *value); -static char strbuf[25] = { - '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', - '0', '0', '0', '0', '0', - '0', '0', '0', '0', '\0' -}; - %} /* BISON Declarations */ %parse-param {SEG *result} %parse-param {struct Node *escontext} +%parse-param {yyscan_t yyscanner} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="seg_yy" @@ -69,14 +61,18 @@ static char strbuf[25] = { range: boundary PLUMIN deviation { + char strbuf[25]; + result->lower = $1.val - $3.val; result->upper = $1.val + $3.val; - sprintf(strbuf, "%g", result->lower); + snprintf(strbuf, sizeof(strbuf), "%g", result->lower); result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); - sprintf(strbuf, "%g", result->upper); + snprintf(strbuf, sizeof(strbuf), "%g", result->upper); result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); result->l_ext = '\0'; result->u_ext = '\0'; + + (void) yynerrs; /* suppress compiler warning */ } | boundary RANGE boundary diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l index 4ad529eccc468..3a0cd7ed506c0 100644 --- a/contrib/seg/segscan.l +++ b/contrib/seg/segscan.l @@ -6,12 +6,8 @@ #include "nodes/miscnodes.h" -/* - * NB: include segparse.h only AFTER including segdata.h, because segdata.h - * contains the definition for SEG. - */ #include "segdata.h" -#include "segparse.h" +#include "segparse.h" /* must be after segdata.h for SEG */ } %{ @@ -29,18 +25,19 @@ fprintf_to_ereport(const char *fmt, const char *msg) { ereport(ERROR, (errmsg_internal("%s", msg))); } - -/* Handles to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; -static char *scanbuf; %} +%option reentrant +%option bison-bridge %option 8bit %option never-interactive %option nodefault %option noinput %option nounput %option noyywrap +%option noyyalloc +%option noyyrealloc +%option noyyfree %option warn %option prefix="seg_yy" @@ -53,12 +50,12 @@ float ({integer}|{real})([eE]{integer})? %% -{range} seg_yylval.text = yytext; return RANGE; -{plumin} seg_yylval.text = yytext; return PLUMIN; -{float} seg_yylval.text = yytext; return SEGFLOAT; -\< seg_yylval.text = "<"; return EXTENSION; -\> seg_yylval.text = ">"; return EXTENSION; -\~ seg_yylval.text = "~"; return EXTENSION; +{range} yylval->text = yytext; return RANGE; +{plumin} yylval->text = yytext; return PLUMIN; +{float} yylval->text = yytext; return SEGFLOAT; +\< yylval->text = "<"; return EXTENSION; +\> yylval->text = ">"; return EXTENSION; +\~ yylval->text = "~"; return EXTENSION; [ \t\n\r\f\v]+ /* discard spaces */ . return yytext[0]; /* alert parser of the garbage */ @@ -67,8 +64,11 @@ float ({integer}|{real})([eE]{integer})? /* LCOV_EXCL_STOP */ void -seg_yyerror(SEG *result, struct Node *escontext, const char *message) +seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char *message) { + struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext + * macro */ + /* if we already reported an error, don't overwrite it */ if (SOFT_ERROR_OCCURRED(escontext)) return; @@ -78,7 +78,7 @@ seg_yyerror(SEG *result, struct Node *escontext, const char *message) errsave(escontext, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("bad seg representation"), - /* translator: %s is typically "syntax error" */ + /* translator: %s is typically "syntax error" */ errdetail("%s at end of input", message))); } else @@ -86,7 +86,7 @@ seg_yyerror(SEG *result, struct Node *escontext, const char *message) errsave(escontext, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("bad seg representation"), - /* translator: first %s is typically "syntax error" */ + /* translator: first %s is typically "syntax error" */ errdetail("%s at or near \"%s\"", message, yytext))); } } @@ -96,25 +96,16 @@ seg_yyerror(SEG *result, struct Node *escontext, const char *message) * Called before any actual parsing is done */ void -seg_scanner_init(const char *str) +seg_scanner_init(const char *str, yyscan_t *yyscannerp) { - Size slen = strlen(str); - - /* - * Might be left over after ereport() - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); - - /* - * Make a scan buffer with special termination needed by flex. - */ - scanbuf = palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); - - BEGIN(INITIAL); + yyscan_t yyscanner; + + if (yylex_init(yyscannerp) != 0) + elog(ERROR, "yylex_init() failed: %m"); + + yyscanner = *yyscannerp; + + yy_scan_string(str, yyscanner); } @@ -122,8 +113,34 @@ seg_scanner_init(const char *str) * Called after parsing is done to clean up after seg_scanner_init() */ void -seg_scanner_finish(void) +seg_scanner_finish(yyscan_t yyscanner) +{ + yylex_destroy(yyscanner); +} + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + return palloc(size); +} + +void * +yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, size); + else + return palloc(size); +} + +void +yyfree(void *ptr, yyscan_t yyscanner) { - yy_delete_buffer(scanbufhandle); - pfree(scanbuf); + if (ptr) + pfree(ptr); } diff --git a/contrib/seg/sort-segments.pl b/contrib/seg/sort-segments.pl index 44f203a9a9fef..ec94402f302e2 100755 --- a/contrib/seg/sort-segments.pl +++ b/contrib/seg/sort-segments.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # this script will sort any table with the segment data type in its last column diff --git a/contrib/seg/sql/partition.sql b/contrib/seg/sql/partition.sql new file mode 100644 index 0000000000000..e1febdea87370 --- /dev/null +++ b/contrib/seg/sql/partition.sql @@ -0,0 +1,36 @@ +-- +-- Test that partitioned-index operations cope with objects that are +-- not in the secure search path. (This has little to do with seg, +-- but we need an opclass that isn't in pg_catalog, and the base system +-- has no such opclass.) Note that we need to test propagation of the +-- partitioned index's properties both to partitions that pre-date it +-- and to partitions created later. +-- + +create function mydouble(int) returns int strict immutable parallel safe +begin atomic select $1 * 2; end; + +create collation mycollation from "POSIX"; + +create table pt (category int, sdata seg, tdata text) + partition by list (category); + +-- pre-existing partition +create table pt12 partition of pt for values in (1,2); + +insert into pt values(1, '0 .. 1'::seg, 'zed'); + +-- expression references object in public schema +create index pti1 on pt ((mydouble(category) + 1)); +-- opclass in public schema +create index pti2 on pt (sdata seg_ops); +-- collation in public schema +create index pti3 on pt (tdata collate mycollation); + +-- new partition +create table pt34 partition of pt for values in (3,4); + +insert into pt values(4, '-1 .. 1'::seg, 'foo'); + +\d+ pt +\d+ pt12 diff --git a/contrib/sepgsql/.gitignore b/contrib/sepgsql/.gitignore index 31613e011f511..b1778d05bbd0b 100644 --- a/contrib/sepgsql/.gitignore +++ b/contrib/sepgsql/.gitignore @@ -3,5 +3,5 @@ /sepgsql-regtest.if /sepgsql-regtest.pp /tmp -# Generated subdirectories -/results/ +# Generated by test suite +/tmp_check/ diff --git a/contrib/sepgsql/Makefile b/contrib/sepgsql/Makefile index afca75b693ffa..90b4585a9e2c2 100644 --- a/contrib/sepgsql/Makefile +++ b/contrib/sepgsql/Makefile @@ -15,6 +15,8 @@ OBJS = \ DATA_built = sepgsql.sql PGFILEDESC = "sepgsql - SELinux integration" +TAP_TESTS = 1 + # Note: because we don't tell the Makefile there are any regression tests, # we have to clean those result files explicitly EXTRA_CLEAN = -r $(pg_regress_clean_files) tmp/ *.pp sepgsql-regtest.if sepgsql-regtest.fc diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c index eaeb4101bca18..6eeb429a28c08 100644 --- a/contrib/sepgsql/database.c +++ b/contrib/sepgsql/database.c @@ -4,7 +4,7 @@ * * Routines corresponding to database objects * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c index 57e4a84bb0b7d..b437007d67197 100644 --- a/contrib/sepgsql/dml.c +++ b/contrib/sepgsql/dml.c @@ -4,7 +4,7 @@ * * Routines to handle DML permission checks * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/expected/alter.out b/contrib/sepgsql/expected/alter.out index ae43537505296..1462cfa3cbcc7 100644 --- a/contrib/sepgsql/expected/alter.out +++ b/contrib/sepgsql/expected/alter.out @@ -164,7 +164,6 @@ LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_re LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema.regtest_table_2.b" permissive=0 ALTER TABLE regtest_table ALTER b DROP NOT NULL; LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_table.b" permissive=0 -LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema.regtest_table_2.b" permissive=0 ALTER TABLE regtest_table ALTER b SET STATISTICS -1; LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_table.b" permissive=0 LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema.regtest_table_2.b" permissive=0 @@ -249,8 +248,6 @@ LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_re LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema.regtest_ptable_1_tens.p" permissive=0 ALTER TABLE regtest_ptable ALTER p DROP NOT NULL; LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_ptable.p" permissive=0 -LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_table_part.p" permissive=0 -LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema.regtest_ptable_1_tens.p" permissive=0 ALTER TABLE regtest_ptable ALTER p SET STATISTICS -1; LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_ptable.p" permissive=0 LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="regtest_schema_2.regtest_table_part.p" permissive=0 diff --git a/contrib/sepgsql/expected/ddl.out b/contrib/sepgsql/expected/ddl.out index 93c677e5463f6..7e8deae4f9320 100644 --- a/contrib/sepgsql/expected/ddl.out +++ b/contrib/sepgsql/expected/ddl.out @@ -154,6 +154,8 @@ LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:sepgsql_r CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END'; LOG: SELinux: allowed { search } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=system_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="pg_catalog" permissive=0 +LINE 1: CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUA... + ^ LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="regtest_schema" permissive=0 LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="regtest_schema.regtest_func(pg_catalog.text,integer[])" permissive=0 CREATE AGGREGATE regtest_agg ( @@ -247,6 +249,8 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:sepgsql_reg CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE plpgsql AS 'BEGIN RETURN $1 * $1 < 100; END'; LOG: SELinux: allowed { search } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=system_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="pg_catalog" permissive=0 +LINE 1: CREATE FUNCTION regtest_func_2(int) RETURNS bool LANGUAGE pl... + ^ LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="regtest_schema" permissive=0 LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:sepgsql_regtest_superuser_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="regtest_schema.regtest_func_2(integer)" permissive=0 RESET SESSION AUTHORIZATION; diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c index 0f206b1093d81..7aff15c6aec21 100644 --- a/contrib/sepgsql/hooks.c +++ b/contrib/sepgsql/hooks.c @@ -4,7 +4,7 @@ * * Entrypoints of the hooks in PostgreSQL, and dispatches the callbacks. * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ @@ -25,7 +25,10 @@ #include "utils/guc.h" #include "utils/queryenvironment.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "sepgsql", + .version = PG_VERSION +); /* * Declarations @@ -394,7 +397,7 @@ sepgsql_utility_command(PlannedStmt *pstmt, } /* - * Module load/unload callback + * Module load callback */ void _PG_init(void) diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c index c790bc6b10004..996ce174454dc 100644 --- a/contrib/sepgsql/label.c +++ b/contrib/sepgsql/label.c @@ -4,7 +4,7 @@ * * Routines to support SELinux labels (security context) * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/launcher b/contrib/sepgsql/launcher index 85f60fd84f324..911e082fdeead 100755 --- a/contrib/sepgsql/launcher +++ b/contrib/sepgsql/launcher @@ -2,7 +2,7 @@ # # A wrapper script to launch psql command in regression test # -# Copyright (c) 2010-2024, PostgreSQL Global Development Group +# Copyright (c) 2010-2025, PostgreSQL Global Development Group # # ------------------------------------------------------------------------- diff --git a/contrib/sepgsql/meson.build b/contrib/sepgsql/meson.build index 9544efe02870b..6bf69783729a7 100644 --- a/contrib/sepgsql/meson.build +++ b/contrib/sepgsql/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not selinux.found() subdir_done() @@ -37,7 +37,16 @@ contrib_targets += custom_target('sepgsql.sql', command: [sed, '-e', 's,MODULE_PATHNAME,$libdir/sepgsql,g', '@INPUT@'], capture: true, install: true, - install_dir: contrib_data_args['install_dir'], + install_dir: dir_data / 'contrib', ) -# TODO: implement sepgsql tests +tests += { + 'name': 'sepgsql', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_sepgsql.pl', + ], + }, +} diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c index 4899bc2a3e322..0d2723d44596d 100644 --- a/contrib/sepgsql/proc.c +++ b/contrib/sepgsql/proc.c @@ -4,7 +4,7 @@ * * Routines corresponding to procedure objects * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c index 92867d41e4088..528a529d4561a 100644 --- a/contrib/sepgsql/relation.c +++ b/contrib/sepgsql/relation.c @@ -4,7 +4,7 @@ * * Routines corresponding to relation/attribute objects * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c index 96e34b90e7596..f85e544bef467 100644 --- a/contrib/sepgsql/schema.c +++ b/contrib/sepgsql/schema.c @@ -4,7 +4,7 @@ * * Routines corresponding to schema objects * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/selinux.c b/contrib/sepgsql/selinux.c index d3b67b1304cb8..fcdcf8072d48c 100644 --- a/contrib/sepgsql/selinux.c +++ b/contrib/sepgsql/selinux.c @@ -5,7 +5,7 @@ * Interactions between userspace and selinux in kernelspace, * using libselinux api. * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h index a42d288e96e5b..678d1ffab451e 100644 --- a/contrib/sepgsql/sepgsql.h +++ b/contrib/sepgsql/sepgsql.h @@ -4,7 +4,7 @@ * * Definitions corresponding to SE-PostgreSQL * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/sepgsql/t/001_sepgsql.pl b/contrib/sepgsql/t/001_sepgsql.pl new file mode 100644 index 0000000000000..f5e4645e4e6d0 --- /dev/null +++ b/contrib/sepgsql/t/001_sepgsql.pl @@ -0,0 +1,248 @@ + +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bsepgsql\b/) +{ + plan skip_all => + 'Potentially unsafe test sepgsql not enabled in PG_TEST_EXTRA'; +} + +note "checking selinux environment"; + +# matchpathcon must be present to assess whether the installation environment +# is OK. +note "checking for matchpathcon"; +if (system('matchpathcon -n . >/dev/null 2>&1') != 0) +{ + diag </dev/null 2>&1') != 0) +{ + diag </dev/null 2>&1') != 0) +{ + diag </dev/null`)[2]; +note "current user domain is '$DOMAIN'"; +if ($DOMAIN ne 'unconfined_t') +{ + diag <<'EOS'; + +The regression tests must be launched from the unconfined_t domain. + +The unconfined_t domain is typically the default domain for user +shell processes. If the default has been changed on your system, +you can revert the changes like this: + + $ sudo semanage login -d `whoami` + +Or, you can add a setting to log in using the unconfined_t domain: + + $ sudo semanage login -a -s unconfined_u -r s0-s0:c0.c255 `whoami` + +EOS + die; +} + +# SELinux must be configured in enforcing mode +note "checking selinux operating mode"; +my $CURRENT_MODE = + (split /: */, `LANG=C sestatus | grep '^Current mode:'`)[1]; +chomp $CURRENT_MODE; +note "current operating mode is '$CURRENT_MODE'"; +if ($CURRENT_MODE eq 'enforcing') +{ + # OK +} +elsif ($CURRENT_MODE eq 'permissive' || $CURRENT_MODE eq 'disabled') +{ + diag <<'EOS'; + +Before running the regression tests, SELinux must be enabled and +must be running in enforcing mode. + +If SELinux is currently running in permissive mode, you can +switch to enforcing mode using the 'setenforce' command. + + $ sudo setenforce 1 + +The system default setting is configured in /etc/selinux/config, +or using a kernel boot parameter. +EOS + die; +} +else +{ + diag <new('test'); +$node->init; +$node->append_conf('postgresql.conf', 'log_statement=none'); + +{ + local %ENV = $node->_get_env(); + + my $result = run_log( + [ + 'postgres', '--single', '-F', + '-c' => 'exit_on_error=true', + '-D' => $node->data_dir, + 'template0' + ], + '<' => $ENV{share_contrib_dir} . '/sepgsql.sql'); + ok($result, 'sepgsql installation script'); +} + +$node->append_conf('postgresql.conf', 'shared_preload_libraries=sepgsql'); +$node->start; + +my @tests = qw(label dml ddl alter misc); + +# Check if the truncate permission exists in the loaded policy, and if so, +# run the truncate test +# +# Testing the TRUNCATE regression test can be done by manually adding +# the permission with CIL if necessary: +# sudo semodule -cE base +# sudo sed -i -E 's/(class db_table.*?) \)/\1 truncate\)/' base.cil +# sudo semodule -i base.cil +push @tests, 'truncate' if -f '/sys/fs/selinux/class/db_table/perms/truncate'; + +$node->command_ok( + [ + $ENV{PG_REGRESS}, + '--bindir' => '', + '--inputdir' => '.', + '--launcher' => './launcher', + @tests + ], + 'sepgsql tests'); + +done_testing(); diff --git a/contrib/sepgsql/test_sepgsql b/contrib/sepgsql/test_sepgsql index 3a29556d1ffc7..23dae1bf03742 100755 --- a/contrib/sepgsql/test_sepgsql +++ b/contrib/sepgsql/test_sepgsql @@ -4,10 +4,10 @@ # to try to ensure that the SELinux environment is set up appropriately and # the database is configured correctly. # -# Note that this must be run against an installed Postgres database. -# There's no equivalent of "make check", and that wouldn't be terribly useful -# since much of the value is in checking that you installed sepgsql into -# your database correctly. +# This must be run against an installed Postgres database. The +# purpose of this script is in checking that you installed sepgsql +# into your database correctly. For testing sepgsql during +# development, "make check", "meson test", etc. are also available. # # This must be run in the contrib/sepgsql directory of a Postgres build tree. # @@ -302,5 +302,5 @@ if [ -f /sys/fs/selinux/class/db_table/perms/truncate ]; then tests+=" truncate" fi -make REGRESS="$tests" REGRESS_OPTS="--launcher ./launcher" installcheck -# exit with the exit code provided by "make" +PGXS=`pg_config --pgxs` +"$(dirname $PGXS)/../../src/test/regress/pg_regress" --inputdir=. --bindir="$PG_BINDIR" --launcher=./launcher $tests diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c index 7defbc961e1b6..65ea8e7946a6e 100644 --- a/contrib/sepgsql/uavc.c +++ b/contrib/sepgsql/uavc.c @@ -6,7 +6,7 @@ * access control decisions recently used, and reduce number of kernel * invocations to avoid unnecessary performance hit. * - * Copyright (c) 2011-2024, PostgreSQL Global Development Group + * Copyright (c) 2011-2025, PostgreSQL Global Development Group * * ------------------------------------------------------------------------- */ diff --git a/contrib/spi/.gitignore b/contrib/spi/.gitignore new file mode 100644 index 0000000000000..5dcb3ff972350 --- /dev/null +++ b/contrib/spi/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/spi/Makefile b/contrib/spi/Makefile index c9c34ff38895b..7ccbef8c9265e 100644 --- a/contrib/spi/Makefile +++ b/contrib/spi/Makefile @@ -10,6 +10,8 @@ DATA = autoinc--1.0.sql \ refint--1.0.sql PGFILEDESC = "spi - examples of using SPI and triggers" +REGRESS = autoinc refint + DOCS = $(addsuffix .example, $(MODULES)) # this is needed for the regression tests; diff --git a/contrib/spi/autoinc.c b/contrib/spi/autoinc.c index 8bf742230e057..b5609f2025193 100644 --- a/contrib/spi/autoinc.c +++ b/contrib/spi/autoinc.c @@ -11,7 +11,10 @@ #include "utils/builtins.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "autoinc", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(autoinc); diff --git a/contrib/spi/expected/autoinc.out b/contrib/spi/expected/autoinc.out new file mode 100644 index 0000000000000..07ae8ad1f2b65 --- /dev/null +++ b/contrib/spi/expected/autoinc.out @@ -0,0 +1,50 @@ +CREATE EXTENSION autoinc; +create sequence aitest_seq increment 10 start 0 minvalue 0; +create table aitest ( + price_id int4, + price_val int4, + price_on int4 +); +create trigger aiserial + before insert or update on aitest + for each row + execute procedure + autoinc (price_on, aitest_seq); +insert into aitest values (1, 1, null); +insert into aitest values (2, 2, 0); +insert into aitest values (3, 3, 1); +select * from aitest; + price_id | price_val | price_on +----------+-----------+---------- + 1 | 1 | 10 + 2 | 2 | 20 + 3 | 3 | 1 +(3 rows) + +update aitest set price_on = 11; +select * from aitest; + price_id | price_val | price_on +----------+-----------+---------- + 1 | 1 | 11 + 2 | 2 | 11 + 3 | 3 | 11 +(3 rows) + +update aitest set price_on = 0; +select * from aitest; + price_id | price_val | price_on +----------+-----------+---------- + 1 | 1 | 30 + 2 | 2 | 40 + 3 | 3 | 50 +(3 rows) + +update aitest set price_on = null; +select * from aitest; + price_id | price_val | price_on +----------+-----------+---------- + 1 | 1 | 60 + 2 | 2 | 70 + 3 | 3 | 80 +(3 rows) + diff --git a/contrib/spi/expected/refint.out b/contrib/spi/expected/refint.out new file mode 100644 index 0000000000000..796336032174e --- /dev/null +++ b/contrib/spi/expected/refint.out @@ -0,0 +1,113 @@ +CREATE EXTENSION refint; +create table pkeys (pkey1 int4 not null, pkey2 text not null); +create table fkeys (fkey1 int4, fkey2 text, fkey3 int); +create table fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); +create index fkeys_i on fkeys (fkey1, fkey2); +create index fkeys2_i on fkeys2 (fkey21, fkey22); +create index fkeys2p_i on fkeys2 (pkey23); +insert into pkeys values (10, '1'); +insert into pkeys values (20, '2'); +insert into pkeys values (30, '3'); +insert into pkeys values (40, '4'); +insert into pkeys values (50, '5'); +insert into pkeys values (60, '6'); +create unique index pkeys_i on pkeys (pkey1, pkey2); +-- +-- For fkeys: +-- (fkey1, fkey2) --> pkeys (pkey1, pkey2) +-- (fkey3) --> fkeys2 (pkey23) +-- +create trigger check_fkeys_pkey_exist + after insert or update on fkeys + for each row + execute function + check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); +create trigger check_fkeys_pkey2_exist + after insert or update on fkeys + for each row + execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); +-- +-- For fkeys2: +-- (fkey21, fkey22) --> pkeys (pkey1, pkey2) +-- +create trigger check_fkeys2_pkey_exist + after insert or update on fkeys2 + for each row + execute procedure + check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2'); +-- +-- For pkeys: +-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: +-- fkeys (fkey1, fkey2) and fkeys2 (fkey21, fkey22) +-- +create trigger check_pkeys_fkey_cascade + after delete or update on pkeys + for each row + execute procedure + check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', + 'fkeys', 'fkey1', 'fkey2', 'fkeys2', 'fkey21', 'fkey22'); +-- +-- For fkeys2: +-- ON DELETE/UPDATE (pkey23) RESTRICT: +-- fkeys (fkey3) +-- +create trigger check_fkeys2_fkey_restrict + after delete or update on fkeys2 + for each row + execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'fkeys', 'fkey3'); +insert into fkeys2 values (10, '1', 1); +insert into fkeys2 values (30, '3', 2); +insert into fkeys2 values (40, '4', 5); +insert into fkeys2 values (50, '5', 3); +-- no key in pkeys +insert into fkeys2 values (70, '5', 3); +ERROR: tuple references non-existent key +DETAIL: Trigger "check_fkeys2_pkey_exist" found tuple referencing non-existent key in "pkeys". +insert into fkeys values (10, '1', 2); +insert into fkeys values (30, '3', 3); +insert into fkeys values (40, '4', 2); +insert into fkeys values (50, '5', 2); +-- no key in pkeys +insert into fkeys values (70, '5', 1); +ERROR: tuple references non-existent key +DETAIL: Trigger "check_fkeys_pkey_exist" found tuple referencing non-existent key in "pkeys". +-- no key in fkeys2 +insert into fkeys values (60, '6', 4); +ERROR: tuple references non-existent key +DETAIL: Trigger "check_fkeys_pkey2_exist" found tuple referencing non-existent key in "fkeys2". +delete from pkeys where pkey1 = 30 and pkey2 = '3'; +NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted +ERROR: "check_fkeys2_fkey_restrict": tuple is referenced in "fkeys" +CONTEXT: SQL statement "delete from fkeys2 where fkey21 = $1 and fkey22 = $2 " +delete from pkeys where pkey1 = 40 and pkey2 = '4'; +NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted +NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys2 are deleted +update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; +NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are updated +NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys2 are updated +update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; +ERROR: duplicate key value violates unique constraint "pkeys_i" +DETAIL: Key (pkey1, pkey2)=(7, 70) already exists. +SELECT trigger_name, event_manipulation, event_object_schema, event_object_table, + action_order, action_condition, action_orientation, action_timing, + action_reference_old_table, action_reference_new_table + FROM information_schema.triggers + WHERE event_object_table in ('pkeys', 'fkeys', 'fkeys2') + ORDER BY trigger_name COLLATE "C", 2; + trigger_name | event_manipulation | event_object_schema | event_object_table | action_order | action_condition | action_orientation | action_timing | action_reference_old_table | action_reference_new_table +----------------------------+--------------------+---------------------+--------------------+--------------+------------------+--------------------+---------------+----------------------------+---------------------------- + check_fkeys2_fkey_restrict | DELETE | public | fkeys2 | 1 | | ROW | AFTER | | + check_fkeys2_fkey_restrict | UPDATE | public | fkeys2 | 1 | | ROW | AFTER | | + check_fkeys2_pkey_exist | INSERT | public | fkeys2 | 1 | | ROW | AFTER | | + check_fkeys2_pkey_exist | UPDATE | public | fkeys2 | 2 | | ROW | AFTER | | + check_fkeys_pkey2_exist | INSERT | public | fkeys | 1 | | ROW | AFTER | | + check_fkeys_pkey2_exist | UPDATE | public | fkeys | 1 | | ROW | AFTER | | + check_fkeys_pkey_exist | INSERT | public | fkeys | 2 | | ROW | AFTER | | + check_fkeys_pkey_exist | UPDATE | public | fkeys | 2 | | ROW | AFTER | | + check_pkeys_fkey_cascade | DELETE | public | pkeys | 1 | | ROW | AFTER | | + check_pkeys_fkey_cascade | UPDATE | public | pkeys | 1 | | ROW | AFTER | | +(10 rows) + +DROP TABLE pkeys; +DROP TABLE fkeys; +DROP TABLE fkeys2; diff --git a/contrib/spi/insert_username.c b/contrib/spi/insert_username.c index a2e1747ff74c7..e44241f9d6cba 100644 --- a/contrib/spi/insert_username.c +++ b/contrib/spi/insert_username.c @@ -14,7 +14,10 @@ #include "utils/builtins.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "insert_username", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(insert_username); diff --git a/contrib/spi/meson.build b/contrib/spi/meson.build index 7f623dceb6c3b..3832a91019a43 100644 --- a/contrib/spi/meson.build +++ b/contrib/spi/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group autoinc_sources = files( 'autoinc.c', @@ -107,3 +107,15 @@ install_data('refint.control', 'refint--1.0.sql', install_data('refint.example', kwargs: contrib_doc_args, ) + +tests += { + 'name': 'spi', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'autoinc', + 'refint', + ], + }, +} diff --git a/contrib/spi/moddatetime.c b/contrib/spi/moddatetime.c index 3eb7004de97d7..5013eee433e47 100644 --- a/contrib/spi/moddatetime.c +++ b/contrib/spi/moddatetime.c @@ -19,10 +19,13 @@ OH, me, I'm Terry Mackintosh #include "catalog/pg_type.h" #include "commands/trigger.h" #include "executor/spi.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "moddatetime", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(moddatetime); diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c index 18062eb1cffbd..d5e25e07ae9e2 100644 --- a/contrib/spi/refint.c +++ b/contrib/spi/refint.c @@ -15,7 +15,10 @@ #include "utils/memutils.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "refint", + .version = PG_VERSION +); typedef struct { @@ -81,6 +84,10 @@ check_primary_key(PG_FUNCTION_ARGS) /* internal error */ elog(ERROR, "check_primary_key: must be fired for row"); + if (!TRIGGER_FIRED_AFTER(trigdata->tg_event)) + /* internal error */ + elog(ERROR, "check_primary_key: must be fired by AFTER trigger"); + /* If INSERTion then must check Tuple to being inserted */ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) tuple = trigdata->tg_trigtuple; @@ -108,9 +115,7 @@ check_primary_key(PG_FUNCTION_ARGS) tupdesc = rel->rd_att; /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "check_primary_key: SPI_connect returned %d", ret); + SPI_connect(); /* * We use SPI plan preparation feature, so allocate space to place key @@ -286,6 +291,10 @@ check_foreign_key(PG_FUNCTION_ARGS) /* internal error */ elog(ERROR, "check_foreign_key: cannot process INSERT events"); + if (!TRIGGER_FIRED_AFTER(trigdata->tg_event)) + /* internal error */ + elog(ERROR, "check_foreign_key: must be fired by AFTER trigger"); + /* Have to check tg_trigtuple - tuple being deleted */ trigtuple = trigdata->tg_trigtuple; @@ -328,9 +337,7 @@ check_foreign_key(PG_FUNCTION_ARGS) tupdesc = rel->rd_att; /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "check_foreign_key: SPI_connect returned %d", ret); + SPI_connect(); /* * We use SPI plan preparation feature, so allocate space to place key @@ -339,10 +346,10 @@ check_foreign_key(PG_FUNCTION_ARGS) kvals = (Datum *) palloc(nkeys * sizeof(Datum)); /* - * Construct ident string as TriggerName $ TriggeredRelationId and try to - * find prepared execution plan(s). + * Construct ident string as TriggerName $ TriggeredRelationId $ + * OperationType and try to find prepared execution plan(s). */ - snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id); + snprintf(ident, sizeof(ident), "%s$%u$%c", trigger->tgname, rel->rd_id, is_update ? 'U' : 'D'); plan = find_plan(ident, &FPlans, &nFPlans); /* if there is no plan(s) then allocate argtypes for preparation */ @@ -574,8 +581,6 @@ check_foreign_key(PG_FUNCTION_ARGS) relname = args[0]; - snprintf(ident, sizeof(ident), "%s$%u", trigger->tgname, rel->rd_id); - plan = find_plan(ident, &FPlans, &nFPlans); ret = SPI_execp(plan->splan[r], kvals, NULL, tcount); /* we have no NULLs - so we pass ^^^^ here */ @@ -597,9 +602,15 @@ check_foreign_key(PG_FUNCTION_ARGS) else { #ifdef REFINT_VERBOSE + const char *operation; + + if (action == 'c') + operation = is_update ? "updated" : "deleted"; + else + operation = "set to null"; + elog(NOTICE, "%s: " UINT64_FORMAT " tuple(s) of %s are %s", - trigger->tgname, SPI_processed, relname, - (action == 'c') ? "deleted" : "set to null"); + trigger->tgname, SPI_processed, relname, operation); #endif } args += nkeys + 1; /* to the next relation */ diff --git a/contrib/spi/sql/autoinc.sql b/contrib/spi/sql/autoinc.sql new file mode 100644 index 0000000000000..b240dcdc082f7 --- /dev/null +++ b/contrib/spi/sql/autoinc.sql @@ -0,0 +1,33 @@ +CREATE EXTENSION autoinc; + +create sequence aitest_seq increment 10 start 0 minvalue 0; + +create table aitest ( + price_id int4, + price_val int4, + price_on int4 +); + +create trigger aiserial + before insert or update on aitest + for each row + execute procedure + autoinc (price_on, aitest_seq); + +insert into aitest values (1, 1, null); +insert into aitest values (2, 2, 0); +insert into aitest values (3, 3, 1); + +select * from aitest; + +update aitest set price_on = 11; + +select * from aitest; + +update aitest set price_on = 0; + +select * from aitest; + +update aitest set price_on = null; + +select * from aitest; diff --git a/contrib/spi/sql/refint.sql b/contrib/spi/sql/refint.sql new file mode 100644 index 0000000000000..63458127917ba --- /dev/null +++ b/contrib/spi/sql/refint.sql @@ -0,0 +1,97 @@ +CREATE EXTENSION refint; + +create table pkeys (pkey1 int4 not null, pkey2 text not null); +create table fkeys (fkey1 int4, fkey2 text, fkey3 int); +create table fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); + +create index fkeys_i on fkeys (fkey1, fkey2); +create index fkeys2_i on fkeys2 (fkey21, fkey22); +create index fkeys2p_i on fkeys2 (pkey23); + +insert into pkeys values (10, '1'); +insert into pkeys values (20, '2'); +insert into pkeys values (30, '3'); +insert into pkeys values (40, '4'); +insert into pkeys values (50, '5'); +insert into pkeys values (60, '6'); +create unique index pkeys_i on pkeys (pkey1, pkey2); + +-- +-- For fkeys: +-- (fkey1, fkey2) --> pkeys (pkey1, pkey2) +-- (fkey3) --> fkeys2 (pkey23) +-- +create trigger check_fkeys_pkey_exist + after insert or update on fkeys + for each row + execute function + check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); + +create trigger check_fkeys_pkey2_exist + after insert or update on fkeys + for each row + execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); + +-- +-- For fkeys2: +-- (fkey21, fkey22) --> pkeys (pkey1, pkey2) +-- +create trigger check_fkeys2_pkey_exist + after insert or update on fkeys2 + for each row + execute procedure + check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2'); + +-- +-- For pkeys: +-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: +-- fkeys (fkey1, fkey2) and fkeys2 (fkey21, fkey22) +-- +create trigger check_pkeys_fkey_cascade + after delete or update on pkeys + for each row + execute procedure + check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', + 'fkeys', 'fkey1', 'fkey2', 'fkeys2', 'fkey21', 'fkey22'); + +-- +-- For fkeys2: +-- ON DELETE/UPDATE (pkey23) RESTRICT: +-- fkeys (fkey3) +-- +create trigger check_fkeys2_fkey_restrict + after delete or update on fkeys2 + for each row + execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'fkeys', 'fkey3'); + +insert into fkeys2 values (10, '1', 1); +insert into fkeys2 values (30, '3', 2); +insert into fkeys2 values (40, '4', 5); +insert into fkeys2 values (50, '5', 3); +-- no key in pkeys +insert into fkeys2 values (70, '5', 3); + +insert into fkeys values (10, '1', 2); +insert into fkeys values (30, '3', 3); +insert into fkeys values (40, '4', 2); +insert into fkeys values (50, '5', 2); +-- no key in pkeys +insert into fkeys values (70, '5', 1); +-- no key in fkeys2 +insert into fkeys values (60, '6', 4); + +delete from pkeys where pkey1 = 30 and pkey2 = '3'; +delete from pkeys where pkey1 = 40 and pkey2 = '4'; +update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; +update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; + +SELECT trigger_name, event_manipulation, event_object_schema, event_object_table, + action_order, action_condition, action_orientation, action_timing, + action_reference_old_table, action_reference_new_table + FROM information_schema.triggers + WHERE event_object_table in ('pkeys', 'fkeys', 'fkeys2') + ORDER BY trigger_name COLLATE "C", 2; + +DROP TABLE pkeys; +DROP TABLE fkeys; +DROP TABLE fkeys2; diff --git a/contrib/sslinfo/Makefile b/contrib/sslinfo/Makefile index dd1ff83b16d19..14305594e2db8 100644 --- a/contrib/sslinfo/Makefile +++ b/contrib/sslinfo/Makefile @@ -20,4 +20,4 @@ include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif -SHLIB_LINK += $(filter -lssl -lcrypto -lssleay32 -leay32, $(LIBS)) +SHLIB_LINK += $(filter -lssl -lcrypto, $(LIBS)) diff --git a/contrib/sslinfo/meson.build b/contrib/sslinfo/meson.build index 39d49a1736c15..4c513759200e0 100644 --- a/contrib/sslinfo/meson.build +++ b/contrib/sslinfo/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not ssl.found() subdir_done() diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c index 5fd46b9874138..da70201119317 100644 --- a/contrib/sslinfo/sslinfo.c +++ b/contrib/sslinfo/sslinfo.c @@ -19,18 +19,10 @@ #include "miscadmin.h" #include "utils/builtins.h" -/* - * On Windows, includes a #define for X509_NAME, which breaks our - * ability to use OpenSSL's version of that symbol if is pulled - * in after ... and, at least on some builds, it is. We - * can't reliably fix that by re-ordering #includes, because libpq/libpq-be.h - * #includes . Instead, just zap the #define again here. - */ -#ifdef X509_NAME -#undef X509_NAME -#endif - -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "sslinfo", + .version = PG_VERSION +); static Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName); static Datum ASN1_STRING_to_text(ASN1_STRING *str); diff --git a/contrib/tablefunc/meson.build b/contrib/tablefunc/meson.build index dccf3b375821b..ee67272ec0ac3 100644 --- a/contrib/tablefunc/meson.build +++ b/contrib/tablefunc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tablefunc_sources = files( 'tablefunc.c', diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c index 7d1b5f514390c..74afdc0977f47 100644 --- a/contrib/tablefunc/tablefunc.c +++ b/contrib/tablefunc/tablefunc.c @@ -10,7 +10,7 @@ * And contributors: * Nabil Sayegh * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without a written agreement @@ -38,13 +38,16 @@ #include "catalog/pg_type.h" #include "common/pg_prng.h" #include "executor/spi.h" +#include "fmgr.h" #include "funcapi.h" #include "lib/stringinfo.h" #include "miscadmin.h" -#include "tablefunc.h" #include "utils/builtins.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "tablefunc", + .version = PG_VERSION +); static HTAB *load_categories_hash(char *cats_sql, MemoryContext per_query_ctx); static Tuplestorestate *get_crosstab_tuplestore(char *sql, @@ -385,9 +388,7 @@ crosstab(PG_FUNCTION_ARGS) per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "crosstab: SPI_connect returned %d", ret); + SPI_connect(); /* Retrieve the desired rows */ ret = SPI_execute(sql, true, 0); @@ -724,9 +725,7 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx) HASH_ELEM | HASH_STRINGS | HASH_CONTEXT); /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "load_categories_hash: SPI_connect returned %d", ret); + SPI_connect(); /* Retrieve the category name rows */ ret = SPI_execute(cats_sql, true, 0); @@ -806,9 +805,7 @@ get_crosstab_tuplestore(char *sql, tupstore = tuplestore_begin_heap(randomAccess, false, work_mem); /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "get_crosstab_tuplestore: SPI_connect returned %d", ret); + SPI_connect(); /* Now retrieve the crosstab source rows */ ret = SPI_execute(sql, true, 0); @@ -1151,15 +1148,11 @@ connectby(char *relname, AttInMetadata *attinmeta) { Tuplestorestate *tupstore = NULL; - int ret; MemoryContext oldcontext; - int serial = 1; /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "connectby: SPI_connect returned %d", ret); + SPI_connect(); /* switch to longer term context to create the tuple store */ oldcontext = MemoryContextSwitchTo(per_query_ctx); diff --git a/contrib/tablefunc/tablefunc.h b/contrib/tablefunc/tablefunc.h deleted file mode 100644 index 2009382ce7df8..0000000000000 --- a/contrib/tablefunc/tablefunc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * contrib/tablefunc/tablefunc.h - * - * - * tablefunc - * - * Sample to demonstrate C functions which return setof scalar - * and setof composite. - * Joe Conway - * And contributors: - * Nabil Sayegh - * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without a written agreement - * is hereby granted, provided that the above copyright notice and this - * paragraph and the following two paragraphs appear in all copies. - * - * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING - * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS - * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - */ - -#ifndef TABLEFUNC_H -#define TABLEFUNC_H - -#include "fmgr.h" - -#endif /* TABLEFUNC_H */ diff --git a/contrib/tcn/meson.build b/contrib/tcn/meson.build index 9650a234d8fd6..6ffb136af904d 100644 --- a/contrib/tcn/meson.build +++ b/contrib/tcn/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tcn_sources = files( 'tcn.c', diff --git a/contrib/tcn/tcn.c b/contrib/tcn/tcn.c index 8d23c824c1b04..3158dee0f26a9 100644 --- a/contrib/tcn/tcn.c +++ b/contrib/tcn/tcn.c @@ -3,7 +3,7 @@ * tcn.c * triggered change notification support for PostgreSQL * - * Portions Copyright (c) 2011-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2011-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -23,7 +23,10 @@ #include "utils/rel.h" #include "utils/syscache.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "tcn", + .version = PG_VERSION +); /* * Copy from s (for source) to r (for result), wrapping with q (quote) diff --git a/contrib/test_decoding/Makefile b/contrib/test_decoding/Makefile index a4ba1a509aec2..02e961f4d3144 100644 --- a/contrib/test_decoding/Makefile +++ b/contrib/test_decoding/Makefile @@ -9,7 +9,7 @@ REGRESS = ddl xact rewrite toast permissions decoding_in_xact \ ISOLATION = mxact delayed_startup ondisk_startup concurrent_ddl_dml \ oldest_xmin snapshot_transfer subxact_without_top concurrent_stream \ twophase_snapshot slot_creation_error catalog_change_snapshot \ - skip_snapshot_restore + skip_snapshot_restore invalidation_distribution REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf ISOLATION_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out index 5713b8ab1c375..bcd1f74b2bc53 100644 --- a/contrib/test_decoding/expected/ddl.out +++ b/contrib/test_decoding/expected/ddl.out @@ -492,6 +492,9 @@ WITH (user_catalog_table = true) options | text[] | | | | extended | | Indexes: "replication_metadata_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "replication_metadata_id_not_null" NOT NULL "id" + "replication_metadata_relation_not_null" NOT NULL "relation" Options: user_catalog_table=true INSERT INTO replication_metadata(relation, options) @@ -506,6 +509,9 @@ ALTER TABLE replication_metadata RESET (user_catalog_table); options | text[] | | | | extended | | Indexes: "replication_metadata_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "replication_metadata_id_not_null" NOT NULL "id" + "replication_metadata_relation_not_null" NOT NULL "relation" INSERT INTO replication_metadata(relation, options) VALUES ('bar', ARRAY['a', 'b']); @@ -519,6 +525,9 @@ ALTER TABLE replication_metadata SET (user_catalog_table = true); options | text[] | | | | extended | | Indexes: "replication_metadata_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "replication_metadata_id_not_null" NOT NULL "id" + "replication_metadata_relation_not_null" NOT NULL "relation" Options: user_catalog_table=true INSERT INTO replication_metadata(relation, options) @@ -538,6 +547,9 @@ ALTER TABLE replication_metadata SET (user_catalog_table = false); rewritemeornot | integer | | | | plain | | Indexes: "replication_metadata_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "replication_metadata_id_not_null" NOT NULL "id" + "replication_metadata_relation_not_null" NOT NULL "relation" Options: user_catalog_table=false INSERT INTO replication_metadata(relation, options) diff --git a/contrib/test_decoding/expected/invalidation_distribution.out b/contrib/test_decoding/expected/invalidation_distribution.out new file mode 100644 index 0000000000000..ae53b1e61de3e --- /dev/null +++ b/contrib/test_decoding/expected/invalidation_distribution.out @@ -0,0 +1,41 @@ +Parsed test spec with 3 sessions + +starting permutation: s1_insert_tbl1 s1_begin s1_insert_tbl1 s2_alter_pub_add_tbl s1_commit s1_insert_tbl1 s2_get_binary_changes +step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1); +step s1_begin: BEGIN; +step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1); +step s2_alter_pub_add_tbl: ALTER PUBLICATION pub ADD TABLE tbl1; +step s1_commit: COMMIT; +step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1); +step s2_get_binary_changes: SELECT count(data) FROM pg_logical_slot_get_binary_changes('isolation_slot', NULL, NULL, 'proto_version', '4', 'publication_names', 'pub') WHERE get_byte(data, 0) = 73; +count +----- + 1 +(1 row) + +?column? +-------- +stop +(1 row) + + +starting permutation: s1_begin s1_insert_tbl1 s3_begin s3_insert_tbl1 s2_alter_pub_add_tbl s1_insert_tbl1 s1_commit s3_commit s2_get_binary_changes +step s1_begin: BEGIN; +step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1); +step s3_begin: BEGIN; +step s3_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (2, 2); +step s2_alter_pub_add_tbl: ALTER PUBLICATION pub ADD TABLE tbl1; +step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1); +step s1_commit: COMMIT; +step s3_commit: COMMIT; +step s2_get_binary_changes: SELECT count(data) FROM pg_logical_slot_get_binary_changes('isolation_slot', NULL, NULL, 'proto_version', '4', 'publication_names', 'pub') WHERE get_byte(data, 0) = 73; +count +----- + 1 +(1 row) + +?column? +-------- +stop +(1 row) + diff --git a/contrib/test_decoding/expected/oldest_xmin.out b/contrib/test_decoding/expected/oldest_xmin.out index dd6053f9c1f4b..57268b38d3322 100644 --- a/contrib/test_decoding/expected/oldest_xmin.out +++ b/contrib/test_decoding/expected/oldest_xmin.out @@ -38,3 +38,44 @@ COMMIT stop (1 row) + +starting permutation: s0_begin s0_getxid s1_begin s1_insert s0_alter s0_commit s0_checkpoint s0_advance_slot s0_advance_slot s1_commit s0_vacuum s0_get_changes +step s0_begin: BEGIN; +step s0_getxid: SELECT pg_current_xact_id() IS NULL; +?column? +-------- +f +(1 row) + +step s1_begin: BEGIN; +step s1_insert: INSERT INTO harvest VALUES ((1, 2, 3)); +step s0_alter: ALTER TYPE basket DROP ATTRIBUTE mangos; +step s0_commit: COMMIT; +step s0_checkpoint: CHECKPOINT; +step s0_advance_slot: SELECT slot_name FROM pg_replication_slot_advance('isolation_slot', pg_current_wal_lsn()); +slot_name +-------------- +isolation_slot +(1 row) + +step s0_advance_slot: SELECT slot_name FROM pg_replication_slot_advance('isolation_slot', pg_current_wal_lsn()); +slot_name +-------------- +isolation_slot +(1 row) + +step s1_commit: COMMIT; +step s0_vacuum: VACUUM pg_attribute; +step s0_get_changes: SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); +data +------------------------------------------------------ +BEGIN +table public.harvest: INSERT: fruits[basket]:'(1,2,3)' +COMMIT +(3 rows) + +?column? +-------- +stop +(1 row) + diff --git a/contrib/test_decoding/expected/stats.out b/contrib/test_decoding/expected/stats.out index 78d36429c8ad0..de6dc416130a0 100644 --- a/contrib/test_decoding/expected/stats.out +++ b/contrib/test_decoding/expected/stats.out @@ -138,12 +138,46 @@ SELECT slot_name FROM pg_stat_replication_slots; (3 rows) COMMIT; +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_stats4_twophase', 'test_decoding', false, true) s4; + ?column? +---------- + init +(1 row) + +-- The INSERT changes are large enough to be spilled but will not be, because +-- the transaction is aborted. The logical decoding skips collecting further +-- changes too. The transaction is prepared to make sure the decoding processes +-- the aborted transaction. +BEGIN; +INSERT INTO stats_test SELECT 'serialize-toobig--1:'||g.i FROM generate_series(1, 5000) g(i); +PREPARE TRANSACTION 'test1_abort'; +ROLLBACK PREPARED 'test1_abort'; +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats4_twophase', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); + count +------- + 1 +(1 row) + +-- Verify that the decoding doesn't spill already-aborted transaction's changes. +SELECT pg_stat_force_next_flush(); + pg_stat_force_next_flush +-------------------------- + +(1 row) + +SELECT slot_name, spill_txns, spill_count FROM pg_stat_replication_slots WHERE slot_name = 'regression_slot_stats4_twophase'; + slot_name | spill_txns | spill_count +---------------------------------+------------+------------- + regression_slot_stats4_twophase | 0 | 0 +(1 row) + DROP TABLE stats_test; SELECT pg_drop_replication_slot('regression_slot_stats1'), pg_drop_replication_slot('regression_slot_stats2'), - pg_drop_replication_slot('regression_slot_stats3'); - pg_drop_replication_slot | pg_drop_replication_slot | pg_drop_replication_slot ---------------------------+--------------------------+-------------------------- - | | + pg_drop_replication_slot('regression_slot_stats3'), + pg_drop_replication_slot('regression_slot_stats4_twophase'); + pg_drop_replication_slot | pg_drop_replication_slot | pg_drop_replication_slot | pg_drop_replication_slot +--------------------------+--------------------------+--------------------------+-------------------------- + | | | (1 row) diff --git a/contrib/test_decoding/expected/stream.out b/contrib/test_decoding/expected/stream.out index 4ab2d47bf8d3c..9879e02ca8409 100644 --- a/contrib/test_decoding/expected/stream.out +++ b/contrib/test_decoding/expected/stream.out @@ -109,6 +109,31 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,NULL, 'incl committing streamed transaction (17 rows) +/* + * Test concurrent abort with toast data. When streaming the second insertion, we + * detect that the subtransaction was aborted, and reset the transaction while having + * the TOAST changes in memory, resulting in deallocating both decoded changes and + * TOAST reconstruction data. Memory usage counters must be updated correctly. + * + * Set debug_logical_replication_streaming to 'immediate' to disable the transaction + * status check happening before streaming the second insertion, so we can detect a + * concurrent abort while streaming. + */ +SET debug_logical_replication_streaming = immediate; +BEGIN; +INSERT INTO stream_test SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i); +ALTER TABLE stream_test ADD COLUMN i INT; +SAVEPOINT s1; +INSERT INTO stream_test(data, i) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50), 1 FROM generate_series(1, 500) g(i); +ROLLBACK TO s1; +COMMIT; +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); + count +------- + 5 +(1 row) + +RESET debug_logical_replication_streaming; DROP TABLE stream_test; SELECT pg_drop_replication_slot('regression_slot'); pg_drop_replication_slot diff --git a/contrib/test_decoding/expected/twophase.out b/contrib/test_decoding/expected/twophase.out index 517f20bc37e7a..08a7c56b5dfb5 100644 --- a/contrib/test_decoding/expected/twophase.out +++ b/contrib/test_decoding/expected/twophase.out @@ -205,11 +205,34 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc COMMIT (3 rows) +-- Test that accessing a TOAST table is permitted during the decoding of a +-- prepared transaction. +-- Create a table with a column that uses a TOASTed default value. +-- (temporarily hide query, to avoid the long CREATE TABLE stmt) +\set ECHO none +BEGIN; +INSERT INTO test_tab VALUES('test'); +PREPARE TRANSACTION 'test_toast_table_access'; +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); + count +------- + 3 +(1 row) + +COMMIT PREPARED 'test_toast_table_access'; +-- consume commit prepared +SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); + data +------------------------------------------- + COMMIT PREPARED 'test_toast_table_access' +(1 row) + -- Test 8: -- cleanup and make sure results are also empty DROP TABLE test_prepared1; DROP TABLE test_prepared2; DROP TABLE test_prepared_savepoint; +DROP TABLE test_tab; -- show results. There should be nothing to show SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); data diff --git a/contrib/test_decoding/meson.build b/contrib/test_decoding/meson.build index f643dc81a2c84..25f6b8a90826b 100644 --- a/contrib/test_decoding/meson.build +++ b/contrib/test_decoding/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_decoding_sources = files( 'test_decoding.c', @@ -63,6 +63,7 @@ tests += { 'twophase_snapshot', 'slot_creation_error', 'skip_snapshot_restore', + 'invalidation_distribution', ], 'regress_args': [ '--temp-config', files('logical.conf'), diff --git a/contrib/test_decoding/specs/invalidation_distribution.spec b/contrib/test_decoding/specs/invalidation_distribution.spec new file mode 100644 index 0000000000000..67d41969ac1d6 --- /dev/null +++ b/contrib/test_decoding/specs/invalidation_distribution.spec @@ -0,0 +1,43 @@ +# Test that catalog cache invalidation messages are distributed to ongoing +# transactions, ensuring they can access the updated catalog content after +# processing these messages. +setup +{ + SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'pgoutput'); + CREATE TABLE tbl1(val1 integer, val2 integer); + CREATE PUBLICATION pub; +} + +teardown +{ + DROP TABLE tbl1; + DROP PUBLICATION pub; + SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot'); +} + +session "s1" +setup { SET synchronous_commit=on; } + +step "s1_begin" { BEGIN; } +step "s1_insert_tbl1" { INSERT INTO tbl1 (val1, val2) VALUES (1, 1); } +step "s1_commit" { COMMIT; } + +session "s2" +setup { SET synchronous_commit=on; } + +step "s2_alter_pub_add_tbl" { ALTER PUBLICATION pub ADD TABLE tbl1; } +step "s2_get_binary_changes" { SELECT count(data) FROM pg_logical_slot_get_binary_changes('isolation_slot', NULL, NULL, 'proto_version', '4', 'publication_names', 'pub') WHERE get_byte(data, 0) = 73; } + +session "s3" +setup { SET synchronous_commit=on; } +step "s3_begin" { BEGIN; } +step "s3_insert_tbl1" { INSERT INTO tbl1 (val1, val2) VALUES (2, 2); } +step "s3_commit" { COMMIT; } + +# Expect to get one insert change. LOGICAL_REP_MSG_INSERT = 'I' +permutation "s1_insert_tbl1" "s1_begin" "s1_insert_tbl1" "s2_alter_pub_add_tbl" "s1_commit" "s1_insert_tbl1" "s2_get_binary_changes" + +# Expect to get one insert change with LOGICAL_REP_MSG_INSERT = 'I' from +# the second "s1_insert_tbl1" executed after adding the table tbl1 to the +# publication in "s2_alter_pub_add_tbl". +permutation "s1_begin" "s1_insert_tbl1" "s3_begin" "s3_insert_tbl1" "s2_alter_pub_add_tbl" "s1_insert_tbl1" "s1_commit" "s3_commit" "s2_get_binary_changes" diff --git a/contrib/test_decoding/specs/oldest_xmin.spec b/contrib/test_decoding/specs/oldest_xmin.spec index 88bd30f5ff76c..7f2fe3d7ed776 100644 --- a/contrib/test_decoding/specs/oldest_xmin.spec +++ b/contrib/test_decoding/specs/oldest_xmin.spec @@ -25,6 +25,7 @@ step "s0_commit" { COMMIT; } step "s0_checkpoint" { CHECKPOINT; } step "s0_vacuum" { VACUUM pg_attribute; } step "s0_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); } +step "s0_advance_slot" { SELECT slot_name FROM pg_replication_slot_advance('isolation_slot', pg_current_wal_lsn()); } session "s1" setup { SET synchronous_commit=on; } @@ -40,3 +41,7 @@ step "s1_commit" { COMMIT; } # will be removed (xmax set) before T1 commits. That is, interlocking doesn't # forbid modifying catalog after someone read it (and didn't commit yet). permutation "s0_begin" "s0_getxid" "s1_begin" "s1_insert" "s0_alter" "s0_commit" "s0_checkpoint" "s0_get_changes" "s0_get_changes" "s1_commit" "s0_vacuum" "s0_get_changes" + +# Perform the same testing process as described above, but use advance_slot to +# forces xmin advancement during fast forward decoding. +permutation "s0_begin" "s0_getxid" "s1_begin" "s1_insert" "s0_alter" "s0_commit" "s0_checkpoint" "s0_advance_slot" "s0_advance_slot" "s1_commit" "s0_vacuum" "s0_get_changes" diff --git a/contrib/test_decoding/specs/skip_snapshot_restore.spec b/contrib/test_decoding/specs/skip_snapshot_restore.spec index 3f1fb6f02c778..7b35dbcc9f3f2 100644 --- a/contrib/test_decoding/specs/skip_snapshot_restore.spec +++ b/contrib/test_decoding/specs/skip_snapshot_restore.spec @@ -39,7 +39,7 @@ step "s2_get_changes_slot0" { SELECT data FROM pg_logical_slot_get_changes('slot # serializes consistent snapshots to the disk at LSNs where are before # s0-transaction's commit. After s0-transaction commits, "s1_init" resumes but # must not restore any serialized snapshots and will reach the consistent state -# when decoding a RUNNING_XACT record generated after s0-transaction's commit. +# when decoding a RUNNING_XACTS record generated after s0-transaction's commit. # We check if the get_changes on 'slot1' will not return any s0-transaction's # changes as its confirmed_flush_lsn will be after the s0-transaction's commit # record. diff --git a/contrib/test_decoding/sql/stats.sql b/contrib/test_decoding/sql/stats.sql index 630371f147ab7..a022fe1bf0750 100644 --- a/contrib/test_decoding/sql/stats.sql +++ b/contrib/test_decoding/sql/stats.sql @@ -50,7 +50,25 @@ SELECT slot_name FROM pg_stat_replication_slots; SELECT slot_name FROM pg_stat_replication_slots; COMMIT; + +SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot_stats4_twophase', 'test_decoding', false, true) s4; + +-- The INSERT changes are large enough to be spilled but will not be, because +-- the transaction is aborted. The logical decoding skips collecting further +-- changes too. The transaction is prepared to make sure the decoding processes +-- the aborted transaction. +BEGIN; +INSERT INTO stats_test SELECT 'serialize-toobig--1:'||g.i FROM generate_series(1, 5000) g(i); +PREPARE TRANSACTION 'test1_abort'; +ROLLBACK PREPARED 'test1_abort'; +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats4_twophase', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); + +-- Verify that the decoding doesn't spill already-aborted transaction's changes. +SELECT pg_stat_force_next_flush(); +SELECT slot_name, spill_txns, spill_count FROM pg_stat_replication_slots WHERE slot_name = 'regression_slot_stats4_twophase'; + DROP TABLE stats_test; SELECT pg_drop_replication_slot('regression_slot_stats1'), pg_drop_replication_slot('regression_slot_stats2'), - pg_drop_replication_slot('regression_slot_stats3'); + pg_drop_replication_slot('regression_slot_stats3'), + pg_drop_replication_slot('regression_slot_stats4_twophase'); diff --git a/contrib/test_decoding/sql/stream.sql b/contrib/test_decoding/sql/stream.sql index 4feec62972a5e..f1269403e0a24 100644 --- a/contrib/test_decoding/sql/stream.sql +++ b/contrib/test_decoding/sql/stream.sql @@ -44,5 +44,26 @@ toasted-123456789012345678901234567890123456789012345678901234567890123456789012 SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); +/* + * Test concurrent abort with toast data. When streaming the second insertion, we + * detect that the subtransaction was aborted, and reset the transaction while having + * the TOAST changes in memory, resulting in deallocating both decoded changes and + * TOAST reconstruction data. Memory usage counters must be updated correctly. + * + * Set debug_logical_replication_streaming to 'immediate' to disable the transaction + * status check happening before streaming the second insertion, so we can detect a + * concurrent abort while streaming. + */ +SET debug_logical_replication_streaming = immediate; +BEGIN; +INSERT INTO stream_test SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i); +ALTER TABLE stream_test ADD COLUMN i INT; +SAVEPOINT s1; +INSERT INTO stream_test(data, i) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50), 1 FROM generate_series(1, 500) g(i); +ROLLBACK TO s1; +COMMIT; +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); +RESET debug_logical_replication_streaming; + DROP TABLE stream_test; SELECT pg_drop_replication_slot('regression_slot'); diff --git a/contrib/test_decoding/sql/twophase.sql b/contrib/test_decoding/sql/twophase.sql index 0244795f3d9e1..4b9ef0c0c4499 100644 --- a/contrib/test_decoding/sql/twophase.sql +++ b/contrib/test_decoding/sql/twophase.sql @@ -104,11 +104,33 @@ COMMIT PREPARED 'test_prepared_nodecode'; -- should be decoded now SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); +-- Test that accessing a TOAST table is permitted during the decoding of a +-- prepared transaction. + +-- Create a table with a column that uses a TOASTed default value. +-- (temporarily hide query, to avoid the long CREATE TABLE stmt) +\set ECHO none +SELECT 'CREATE TABLE test_tab (a text DEFAULT ''' || string_agg('toast value', '') || ''');' FROM generate_series(1, 4000) +\gexec +\set ECHO all + +BEGIN; +INSERT INTO test_tab VALUES('test'); +PREPARE TRANSACTION 'test_toast_table_access'; + +SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); + +COMMIT PREPARED 'test_toast_table_access'; + +-- consume commit prepared +SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1'); + -- Test 8: -- cleanup and make sure results are also empty DROP TABLE test_prepared1; DROP TABLE test_prepared2; DROP TABLE test_prepared_savepoint; +DROP TABLE test_tab; -- show results. There should be nothing to show SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); diff --git a/contrib/test_decoding/t/001_repl_stats.pl b/contrib/test_decoding/t/001_repl_stats.pl index eac0e974d7fec..0de62edb7d84c 100644 --- a/contrib/test_decoding/t/001_repl_stats.pl +++ b/contrib/test_decoding/t/001_repl_stats.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test replication statistics data in pg_stat_replication_slots is sane after # drop replication slot and restart. @@ -118,4 +118,64 @@ sub test_slot_stats # shutdown $node->stop; +# Test replication slot stats persistence in a single session. The slot +# is dropped and created concurrently of a session peeking at its data +# repeatedly, hence holding in its local cache a reference to the stats. +$node->start; + +my $slot_name_restart = 'regression_slot5'; +$node->safe_psql('postgres', + "SELECT pg_create_logical_replication_slot('$slot_name_restart', 'test_decoding');" +); + +# Look at slot data, with a persistent connection. +my $bpgsql = $node->background_psql('postgres', on_error_stop => 1); + +# Launch query and look at slot data, incrementing the refcount of the +# stats entry. +$bpgsql->query_safe( + "SELECT pg_logical_slot_peek_binary_changes('$slot_name_restart', NULL, NULL)" +); + +# Drop the slot entry. The stats entry is not dropped yet as the previous +# session still holds a reference to it. +$node->safe_psql('postgres', + "SELECT pg_drop_replication_slot('$slot_name_restart')"); + +# Create again the same slot. The stats entry is reinitialized, not marked +# as dropped anymore. +$node->safe_psql('postgres', + "SELECT pg_create_logical_replication_slot('$slot_name_restart', 'test_decoding');" +); + +# Look again at the slot data. The local stats reference should be refreshed +# to the reinitialized entry. +$bpgsql->query_safe( + "SELECT pg_logical_slot_peek_binary_changes('$slot_name_restart', NULL, NULL)" +); +# Drop again the slot, the entry is not dropped yet as the previous session +# still has a refcount on it. +$node->safe_psql('postgres', + "SELECT pg_drop_replication_slot('$slot_name_restart')"); + +# Shutdown the node, which should happen cleanly with the stats file written +# to disk. Note that the background session created previously needs to be +# hold *while* the node is shutting down to check that it drops the stats +# entry of the slot before writing the stats file. +$node->stop; + +# Make sure that the node is correctly shut down. Checking the control file +# is not enough, as the node may detect that something is incorrect after the +# control file has been updated and the shutdown checkpoint is finished, so +# also check that the stats file has been written out. +command_like( + [ 'pg_controldata', $node->data_dir ], + qr/Database cluster state:\s+shut down\n/, + 'node shut down ok'); + +my $stats_file = "$datadir/pg_stat/pgstat.stat"; +ok(-f "$stats_file", "stats file must exist after shutdown"); + +$bpgsql->quit; + done_testing(); diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c index 7c50d13969841..bb495563200c3 100644 --- a/contrib/test_decoding/test_decoding.c +++ b/contrib/test_decoding/test_decoding.c @@ -3,7 +3,7 @@ * test_decoding.c * example logical decoding output plugin * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/test_decoding/test_decoding.c @@ -22,7 +22,10 @@ #include "utils/memutils.h" #include "utils/rel.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "test_decoding", + .version = PG_VERSION +); typedef struct { diff --git a/contrib/tsm_system_rows/meson.build b/contrib/tsm_system_rows/meson.build index 534eca7f2aeb3..b8cece3d80f59 100644 --- a/contrib/tsm_system_rows/meson.build +++ b/contrib/tsm_system_rows/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tsm_system_rows_sources = files( 'tsm_system_rows.c', diff --git a/contrib/tsm_system_rows/tsm_system_rows.c b/contrib/tsm_system_rows/tsm_system_rows.c index a9f5d657d1ce6..f401efa2131fc 100644 --- a/contrib/tsm_system_rows/tsm_system_rows.c +++ b/contrib/tsm_system_rows/tsm_system_rows.c @@ -17,7 +17,7 @@ * won't visit blocks added after the first scan, but that is fine since * such blocks shouldn't contain any visible tuples anyway. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -28,14 +28,16 @@ #include "postgres.h" -#include "access/relscan.h" #include "access/tsmapi.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "optimizer/optimizer.h" #include "utils/sampling.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "tsm_system_rows", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(tsm_system_rows_handler); diff --git a/contrib/tsm_system_time/meson.build b/contrib/tsm_system_time/meson.build index 5e0480b4187f2..8a143a8f8e6f4 100644 --- a/contrib/tsm_system_time/meson.build +++ b/contrib/tsm_system_time/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tsm_system_time_sources = files( 'tsm_system_time.c', diff --git a/contrib/tsm_system_time/tsm_system_time.c b/contrib/tsm_system_time/tsm_system_time.c index f187fd77655a3..c9c71d8c3af39 100644 --- a/contrib/tsm_system_time/tsm_system_time.c +++ b/contrib/tsm_system_time/tsm_system_time.c @@ -13,7 +13,7 @@ * However, we do what we can to reduce surprising behavior by selecting * the sampling pattern just once per query, much as in tsm_system_rows. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -26,7 +26,6 @@ #include -#include "access/relscan.h" #include "access/tsmapi.h" #include "catalog/pg_type.h" #include "miscadmin.h" @@ -34,7 +33,10 @@ #include "utils/sampling.h" #include "utils/spccache.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "tsm_system_time", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(tsm_system_time_handler); diff --git a/contrib/unaccent/meson.build b/contrib/unaccent/meson.build index 2fe44fde70964..33d4649bae15d 100644 --- a/contrib/unaccent/meson.build +++ b/contrib/unaccent/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group unaccent_sources = files( 'unaccent.c', diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c index 707962305f83b..336ba31047a4a 100644 --- a/contrib/unaccent/unaccent.c +++ b/contrib/unaccent/unaccent.c @@ -3,7 +3,7 @@ * unaccent.c * Text search unaccent dictionary * - * Copyright (c) 2009-2024, PostgreSQL Global Development Group + * Copyright (c) 2009-2025, PostgreSQL Global Development Group * * IDENTIFICATION * contrib/unaccent/unaccent.c @@ -13,7 +13,6 @@ #include "postgres.h" -#include "catalog/namespace.h" #include "catalog/pg_ts_dict.h" #include "commands/defrem.h" #include "lib/stringinfo.h" @@ -22,10 +21,12 @@ #include "tsearch/ts_public.h" #include "utils/builtins.h" #include "utils/lsyscache.h" -#include "utils/regproc.h" #include "utils/syscache.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "unaccent", + .version = PG_VERSION +); /* * An unaccent dictionary uses a trie to find a string to replace. Each node @@ -157,7 +158,7 @@ initTrie(const char *filename) { ptrlen = pg_mblen(ptr); /* ignore whitespace, but end src or trg */ - if (t_isspace(ptr)) + if (isspace((unsigned char) *ptr)) { if (state == 1) state = 2; diff --git a/contrib/uuid-ossp/meson.build b/contrib/uuid-ossp/meson.build index 56732d1d14763..982f27c085fc9 100644 --- a/contrib/uuid-ossp/meson.build +++ b/contrib/uuid-ossp/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not uuid.found() subdir_done() diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c index 3172714eb6ac4..58e312a068279 100644 --- a/contrib/uuid-ossp/uuid-ossp.c +++ b/contrib/uuid-ossp/uuid-ossp.c @@ -2,7 +2,7 @@ * * UUID generation functions using the BSD, E2FS or OSSP UUID library * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * Portions Copyright (c) 2009 Andrew Gierth * @@ -102,7 +102,10 @@ do { \ #endif /* !HAVE_UUID_OSSP */ -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "uuid-ossp", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(uuid_nil); PG_FUNCTION_INFO_V1(uuid_ns_dns); diff --git a/contrib/vacuumlo/meson.build b/contrib/vacuumlo/meson.build index b5f4ee0851969..deee1d2832d6a 100644 --- a/contrib/vacuumlo/meson.build +++ b/contrib/vacuumlo/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group vacuumlo_sources = files( 'vacuumlo.c', diff --git a/contrib/vacuumlo/t/001_basic.pl b/contrib/vacuumlo/t/001_basic.pl index 57a9cda6f6b57..8b2ad24eff1ab 100644 --- a/contrib/vacuumlo/t/001_basic.pl +++ b/contrib/vacuumlo/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c index 0d99428dec666..16a450c4386af 100644 --- a/contrib/vacuumlo/vacuumlo.c +++ b/contrib/vacuumlo/vacuumlo.c @@ -3,7 +3,7 @@ * vacuumlo.c * This removes orphaned large objects from a database. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -139,7 +139,7 @@ vacuumlo(const char *database, const struct _param *param) res = PQexec(conn, ALWAYS_SECURE_SEARCH_PATH_SQL); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - pg_log_error("failed to set search_path: %s", PQerrorMessage(conn)); + pg_log_error("failed to set \"search_path\": %s", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return -1; diff --git a/contrib/xml2/Makefile b/contrib/xml2/Makefile index 0d703fe0e8f94..8597e9aa9c599 100644 --- a/contrib/xml2/Makefile +++ b/contrib/xml2/Makefile @@ -7,7 +7,9 @@ OBJS = \ xslt_proc.o EXTENSION = xml2 -DATA = xml2--1.1.sql xml2--1.0--1.1.sql +DATA = xml2--1.1.sql \ + xml2--1.1--1.2.sql \ + xml2--1.0--1.1.sql PGFILEDESC = "xml2 - XPath querying and XSLT" REGRESS = xml2 diff --git a/contrib/xml2/expected/xml2.out b/contrib/xml2/expected/xml2.out index eba6ae6036498..3d97b14c3a1e4 100644 --- a/contrib/xml2/expected/xml2.out +++ b/contrib/xml2/expected/xml2.out @@ -207,6 +207,45 @@ SELECT xslt_process('cim30400test37 +(1 row) + +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'item_without_toptag') + FROM articles; + xpath_nodeset +------------------------------------------------------------------------------------------------------------------------------ + test37 +(1 row) + +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'result', 'item') + FROM articles; + xpath_nodeset +----------------------------------------------------------------------------------- + test37 +(1 row) + +-- xpath_list() +SELECT xpath_list(article_xml::text, '/article/author|/article/pages') + FROM articles; + xpath_list +------------ + test,37 +(1 row) + +SELECT xpath_list(article_xml::text, '/article/author|/article/pages', '|') + FROM articles; + xpath_list +------------ + test|37 +(1 row) + -- possible security exploit SELECT xslt_process('Hello from XML', $$cim30400 $$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text); ERROR: xslt_process() is not available without libxslt +-- xpath_nodeset() +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages') + FROM articles; + xpath_nodeset +---------------------------------------- + test37 +(1 row) + +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'item_without_toptag') + FROM articles; + xpath_nodeset +------------------------------------------------------------------------------------------------------------------------------ + test37 +(1 row) + +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'result', 'item') + FROM articles; + xpath_nodeset +----------------------------------------------------------------------------------- + test37 +(1 row) + +-- xpath_list() +SELECT xpath_list(article_xml::text, '/article/author|/article/pages') + FROM articles; + xpath_list +------------ + test,37 +(1 row) + +SELECT xpath_list(article_xml::text, '/article/author|/article/pages', '|') + FROM articles; + xpath_list +------------ + test|37 +(1 row) + -- possible security exploit SELECT xslt_process('Hello from XML', $$cim30400 $$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text); +-- xpath_nodeset() +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages') + FROM articles; +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'item_without_toptag') + FROM articles; +SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages', + 'result', 'item') + FROM articles; + +-- xpath_list() +SELECT xpath_list(article_xml::text, '/article/author|/article/pages') + FROM articles; +SELECT xpath_list(article_xml::text, '/article/author|/article/pages', '|') + FROM articles; + -- possible security exploit SELECT xslt_process('Hello from XML', $$ #include -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "xml2", + .version = PG_VERSION +); /* exported for use by xslt_proc.c */ @@ -279,8 +281,8 @@ xpath_string(PG_FUNCTION_ARGS) /* We could try casting to string using the libxml function? */ xpath = (xmlChar *) palloc(pathsize + 9); - memcpy((char *) xpath, "string(", 7); - memcpy((char *) (xpath + 7), VARDATA_ANY(xpathsupp), pathsize); + memcpy(xpath, "string(", 7); + memcpy(xpath + 7, VARDATA_ANY(xpathsupp), pathsize); xpath[pathsize + 7] = ')'; xpath[pathsize + 8] = '\0'; @@ -386,9 +388,9 @@ pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace) workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); /* compile the path */ - comppath = xmlXPathCompile(xpath); + comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath); if (comppath == NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "XPath Syntax Error"); /* Now evaluate the path expression. */ @@ -560,8 +562,7 @@ xpath_table(PG_FUNCTION_ARGS) relname, condition); - if ((ret = SPI_connect()) < 0) - elog(ERROR, "xpath_table: SPI_connect returned %d", ret); + SPI_connect(); if ((ret = SPI_exec(query_buf.data, 0)) != SPI_OK_SELECT) elog(ERROR, "xpath_table: SPI execution failed for query %s", @@ -650,10 +651,10 @@ xpath_table(PG_FUNCTION_ARGS) ctxt->node = xmlDocGetRootElement(doctree); /* compile the path */ - comppath = xmlXPathCompile(xpaths[j]); + comppath = xmlXPathCtxtCompile(ctxt, xpaths[j]); if (comppath == NULL) xml_ereport(xmlerrcxt, ERROR, - ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "XPath Syntax Error"); /* Now evaluate the path expression. */ diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c index f30a3a42c03e9..b720d89f754ae 100644 --- a/contrib/xml2/xslt_proc.c +++ b/contrib/xml2/xslt_proc.c @@ -7,10 +7,7 @@ */ #include "postgres.h" -#include "executor/spi.h" #include "fmgr.h" -#include "funcapi.h" -#include "miscadmin.h" #include "utils/builtins.h" #include "utils/xml.h" @@ -90,7 +87,7 @@ xslt_process(PG_FUNCTION_ARGS) XML_PARSE_NOENT); if (doctree == NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT, "error parsing XML document"); /* Same for stylesheet */ @@ -99,14 +96,14 @@ xslt_process(PG_FUNCTION_ARGS) XML_PARSE_NOENT); if (ssdoc == NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT, "error parsing stylesheet as XML document"); /* After this call we need not free ssdoc separately */ stylesheet = xsltParseStylesheetDoc(ssdoc); if (stylesheet == NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "failed to parse stylesheet"); xslt_ctxt = xsltNewTransformContext(stylesheet, doctree); @@ -141,7 +138,7 @@ xslt_process(PG_FUNCTION_ARGS) NULL, NULL, xslt_ctxt); if (restree == NULL) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "failed to apply stylesheet"); resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet); diff --git a/doc/src/sgml/Makefile b/doc/src/sgml/Makefile index 9c9bbfe375d84..11aac91381258 100644 --- a/doc/src/sgml/Makefile +++ b/doc/src/sgml/Makefile @@ -59,7 +59,7 @@ GENERATED_SGML = version.sgml \ features-supported.sgml features-unsupported.sgml errcodes-table.sgml \ keywords-table.sgml targets-meson.sgml wait_event_types.sgml -ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML) +ALL_SGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML) ALL_IMAGES := $(wildcard $(srcdir)/images/*.svg) @@ -68,7 +68,7 @@ ALL_IMAGES := $(wildcard $(srcdir)/images/*.svg) # we're at it, also resolve all entities (that is, copy all included # files into one big file). This helps tools that don't understand # vpath builds (such as dbtoepub). -postgres-full.xml: postgres.sgml $(ALLSGML) +postgres-full.xml: postgres.sgml $(ALL_SGML) $(XMLLINT) $(XMLINCLUDE) --output $@ --noent --valid $< @@ -143,19 +143,25 @@ postgres.txt: postgres.html ## Print ## -postgres.pdf: +postgres.pdf pdf: $(error Invalid target; use postgres-A4.pdf or postgres-US.pdf as targets) XSLTPROC_FO_FLAGS += --stringparam img.src.path '$(srcdir)/' +# XSL Formatting Objects (FO), https://en.wikipedia.org/wiki/XSL_Formatting_Objects %-A4.fo: stylesheet-fo.xsl %-full.xml $(XSLTPROC) $(XMLINCLUDE) $(XSLTPROCFLAGS) $(XSLTPROC_FO_FLAGS) --stringparam paper.type A4 -o $@ $^ %-US.fo: stylesheet-fo.xsl %-full.xml $(XSLTPROC) $(XMLINCLUDE) $(XSLTPROCFLAGS) $(XSLTPROC_FO_FLAGS) --stringparam paper.type USletter -o $@ $^ +# There is no easy way to pipe output and capture its return code, +# so add a final line to report the return code. %.pdf: %.fo $(ALL_IMAGES) - $(FOP) -fo $< -pdf $@ + @ { LANG=C $(FOP) -fo $< -pdf $@ 2>&1; echo "FOP_RETURN $$?"; } | \ + $(AWK) 'BEGIN { warn = 0 } $$1 != "FOP_RETURN" { print } /not available in font/ { warn = 1 } \ + END { if (warn != 0) print("\nWarning: found characters that cannot be output in the PDF document; see README.non-ASCII"); \ + if ($$2 != 0) { exit $$2} }' 1>&2 ## @@ -194,7 +200,7 @@ MAKEINFO = makeinfo ## # Quick syntax check without style processing -check: postgres.sgml $(ALLSGML) check-tabs +check: postgres.sgml $(ALL_SGML) check-tabs check-nbsp $(XMLLINT) $(XMLINCLUDE) --noout --valid $< @@ -257,7 +263,15 @@ endif # sqlmansectnum != 7 # tabs are harmless, but it is best to avoid them in SGML files check-tabs: - @( ! grep ' ' $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml $(srcdir)/*.xsl) ) || (echo "Tabs appear in SGML/XML files" 1>&2; exit 1) + @( ! grep ' ' $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml $(srcdir)/*.xsl) ) || \ + (echo "Tabs appear in SGML/XML files" 1>&2; exit 1) + +# Non-breaking spaces are harmless, but it is best to avoid them in SGML files. +# Use perl command because non-GNU grep or sed could not have hex escape sequence. +check-nbsp: + @ ( $(PERL) -ne '/\xC2\xA0/ and print("$$ARGV:$$_"),$$n++; END {exit($$n>0)}' \ + $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml $(srcdir)/*.xsl $(srcdir)/images/*.xsl) ) || \ + (echo "Non-breaking spaces appear in SGML/XML files" 1>&2; exit 1) ## ## Clean diff --git a/doc/src/sgml/README.non-ASCII b/doc/src/sgml/README.non-ASCII new file mode 100644 index 0000000000000..e9065a33ad6f2 --- /dev/null +++ b/doc/src/sgml/README.non-ASCII @@ -0,0 +1,38 @@ + + +Representation of non-ASCII characters +-------------------------------------- + +Find non-ASCII characters using: + + grep --recursive --color='auto' -P '[\x80-\xFF]' . + +Convert to HTML4 named entity (&) escapes +----------------------------------------- + +We support several output formats: + +* html (supports all Unicode characters) +* man (supports all Unicode characters) +* pdf (supports only Latin-1 characters) +* info + +While some output formatting tools support all Unicode characters, +others only support Latin-1 characters. Specifically, the PDF rendering +engine can only display Latin-1 characters; non-Latin-1 Unicode +characters are displayed as "###". + +Therefore, in the SGML files, we can only use Latin-1 characters. We +can use UTF8 representations of Latin-1 characters, or HTML entities of +Latin-1 characters, e.g., Álvaro. + +Do not use UTF numeric character escapes (&#nnn;). + +When building the PDF docs, problem characters will appear as warnings. + +HTML entities + official: http://www.w3.org/TR/html4/sgml/entities.html + one page: http://www.zipcon.net/~swhite/docs/computers/browsers/entities_page.html + other lists: http://www.zipcon.net/~swhite/docs/computers/browsers/entities.html + http://www.zipcon.net/~swhite/docs/computers/browsers/entities_page.html + https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references diff --git a/doc/src/sgml/acronyms.sgml b/doc/src/sgml/acronyms.sgml index 58d0d90fece02..2f906e9f018d9 100644 --- a/doc/src/sgml/acronyms.sgml +++ b/doc/src/sgml/acronyms.sgml @@ -9,6 +9,15 @@ + + AIO + + + Asynchronous I/O + + + + ACL @@ -354,6 +363,15 @@ + + I/O + + + Input/Output + + + + ISO diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml index 755c9f1485084..e15a3323dfbfd 100644 --- a/doc/src/sgml/advanced.sgml +++ b/doc/src/sgml/advanced.sgml @@ -389,30 +389,32 @@ SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) FROM emps SELECT depname, empno, salary, - rank() OVER (PARTITION BY depname ORDER BY salary DESC) + row_number() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary; - depname | empno | salary | rank ------------+-------+--------+------ - develop | 8 | 6000 | 1 - develop | 10 | 5200 | 2 - develop | 11 | 5200 | 2 - develop | 9 | 4500 | 4 - develop | 7 | 4200 | 5 - personnel | 2 | 3900 | 1 - personnel | 5 | 3500 | 2 - sales | 1 | 5000 | 1 - sales | 4 | 4800 | 2 - sales | 3 | 4800 | 2 + depname | empno | salary | row_number +-----------+-------+--------+------------ + develop | 8 | 6000 | 1 + develop | 10 | 5200 | 2 + develop | 11 | 5200 | 3 + develop | 9 | 4500 | 4 + develop | 7 | 4200 | 5 + personnel | 2 | 3900 | 1 + personnel | 5 | 3500 | 2 + sales | 1 | 5000 | 1 + sales | 4 | 4800 | 2 + sales | 3 | 4800 | 3 (10 rows) - As shown here, the rank function produces a numerical rank - for each distinct ORDER BY value in the current row's - partition, using the order defined by the ORDER BY clause. - rank needs no explicit parameter, because its behavior + As shown here, the row_number window function + assigns sequential numbers to the rows within each partition, + in the order defined by the ORDER BY clause + (with tied rows numbered in an unspecified order). + row_number needs no explicit parameter, + because its behavior is entirely determined by the OVER clause. @@ -527,14 +529,15 @@ SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary; SELECT depname, empno, salary, enroll_date FROM (SELECT depname, empno, salary, enroll_date, - rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos + row_number() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos FROM empsalary ) AS ss WHERE pos < 3; The above query only shows the rows from the inner query having - rank less than 3. + row_number less than 3 (that is, the first + two rows for each department). diff --git a/doc/src/sgml/amcheck.sgml b/doc/src/sgml/amcheck.sgml index 3af065615bc0d..211a0ae1945bb 100644 --- a/doc/src/sgml/amcheck.sgml +++ b/doc/src/sgml/amcheck.sgml @@ -188,6 +188,26 @@ ORDER BY c.relpages DESC LIMIT 10; + + + + gin_index_check(index regclass) returns void + + gin_index_check + + + + + + gin_index_check tests that its target GIN index + has consistent parent-child tuples relations (no parent tuples + require tuple adjustment) and page graph respects balanced-tree + invariants (internal pages reference only leaf page or only internal + pages). + + + + @@ -466,8 +486,8 @@ SET client_min_messages = DEBUG1; - File system or storage subsystem faults where checksums happen to - simply not be enabled. + File system or storage subsystem faults when data checksums are + disabled. Note that amcheck examines a page as represented in some diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index 0c4656ee3027a..15c868021e673 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -337,13 +337,13 @@ LOG: duration: 3.651 ms plan: Query Text: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; - Aggregate (cost=16.79..16.80 rows=1 width=0) (actual time=3.626..3.627 rows=1 loops=1) - -> Hash Join (cost=4.17..16.55 rows=92 width=0) (actual time=3.349..3.594 rows=92 loops=1) + Aggregate (cost=16.79..16.80 rows=1 width=0) (actual time=3.626..3.627 rows=1.00 loops=1) + -> Hash Join (cost=4.17..16.55 rows=92 width=0) (actual time=3.349..3.594 rows=92.00 loops=1) Hash Cond: (pg_class.oid = pg_index.indrelid) - -> Seq Scan on pg_class (cost=0.00..9.55 rows=255 width=4) (actual time=0.016..0.140 rows=255 loops=1) - -> Hash (cost=3.02..3.02 rows=92 width=4) (actual time=3.238..3.238 rows=92 loops=1) + -> Seq Scan on pg_class (cost=0.00..9.55 rows=255 width=4) (actual time=0.016..0.140 rows=255.00 loops=1) + -> Hash (cost=3.02..3.02 rows=92 width=4) (actual time=3.238..3.238 rows=92.00 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 4kB - -> Seq Scan on pg_index (cost=0.00..3.02 rows=92 width=4) (actual time=0.008..3.187 rows=92 loops=1) + -> Seq Scan on pg_index (cost=0.00..3.02 rows=92 width=4) (actual time=0.008..3.187 rows=92.00 loops=1) Filter: indisunique ]]> diff --git a/doc/src/sgml/backup-manifest.sgml b/doc/src/sgml/backup-manifest.sgml index d5ec244834ec1..594e216bcba1f 100644 --- a/doc/src/sgml/backup-manifest.sgml +++ b/doc/src/sgml/backup-manifest.sgml @@ -87,10 +87,10 @@ This key is always present on the last line of the backup manifest file. - The associated value is a SHA256 checksum of all the preceding lines. + The associated value is a SHA-256 checksum of all the preceding lines. We use a fixed checksum method here to make it possible for clients - to do incremental parsing of the manifest. While a SHA256 checksum - is significantly more expensive than a CRC32C checksum, the manifest + to do incremental parsing of the manifest. While a SHA-256 checksum + is significantly more expensive than a CRC-32C checksum, the manifest should normally be small enough that the extra computation won't matter very much. diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index e4e4c56cf1403..25b8904baf7cd 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -106,10 +106,10 @@ pg_dump dbname > Text files created by pg_dump are intended to - be read in by the psql program. The - general command form to restore a dump is + be read by the psql program using its default + settings. The general command form to restore a text dump is -psql dbname < dumpfile +psql -X dbname < dumpfile where dumpfile is the file output by the pg_dump command. The database dbname < template0 before executing psql (e.g., with createdb -T template0 dbname). psql + class="parameter">dbname). + To ensure psql runs with its default settings, + use the () option. + psql supports options similar to pg_dump for specifying the database server to connect to and the user name to use. See the reference page for more information. - Non-text file dumps are restored using the + + + Non-text file dumps should be restored using the utility. @@ -141,7 +147,7 @@ psql dbname < psql exit with an exit status of 3 if an SQL error occurs: -psql --set ON_ERROR_STOP=on dbname < dumpfile +psql -X --set ON_ERROR_STOP=on dbname < dumpfile Either way, you will only have a partially restored database. Alternatively, you can specify that the whole dump should be @@ -160,7 +166,7 @@ psql --set ON_ERROR_STOP=on dbname < write to or read from pipes makes it possible to dump a database directly from one server to another, for example: -pg_dump -h host1 dbname | psql -h host2 dbname +pg_dump -h host1 dbname | psql -X -h host2 dbname @@ -205,7 +211,7 @@ pg_dumpall > dumpfile The resulting dump can be restored with psql: -psql -f dumpfile postgres +psql -X -f dumpfile postgres (Actually, you can specify any existing database name to start from, but if you are loading into an empty cluster then postgres diff --git a/doc/src/sgml/biblio.sgml b/doc/src/sgml/biblio.sgml index 443e2d6fac7be..cfcadabe08c1c 100644 --- a/doc/src/sgml/biblio.sgml +++ b/doc/src/sgml/biblio.sgml @@ -286,7 +286,7 @@ ssimkovi@ag.or.at - Partial indexing in POSTGRES: research project + <ulink url="https://search.library.berkeley.edu/permalink/01UCS_BER/iqob43/alma991082339239706532">Partial indexing in POSTGRES: research project</ulink> Nels @@ -303,7 +303,7 @@ ssimkovi@ag.or.at - A Unified Framework for Version Modeling Using Production Rules in a Database System + <ulink url="https://www2.eecs.berkeley.edu/Pubs/TechRpts/1990/1466.html">A Unified Framework for Version Modeling Using Production Rules in a Database System</ulink> L. @@ -564,5 +564,23 @@ ssimkovi@ag.or.at + + + <ulink url="https://dsf.berkeley.edu/papers/S2K-91-05.pdf"> + An overview of the Sequoia 2000 project + </ulink> + + + M. + Stonebraker + + + + + Digest of Papers COMPCON Spring 1992 + 1992 + 383–388 + + diff --git a/doc/src/sgml/bloom.sgml b/doc/src/sgml/bloom.sgml index 19f2b172cc4fb..ec5d077679b14 100644 --- a/doc/src/sgml/bloom.sgml +++ b/doc/src/sgml/bloom.sgml @@ -118,12 +118,13 @@ SELECT 10000000 =# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN -------------------------------------------------------------------&zwsp;----------------------------------- - Seq Scan on tbloom (cost=0.00..2137.14 rows=3 width=24) (actual time=16.971..16.971 rows=0 loops=1) + Seq Scan on tbloom (cost=0.00..213744.00 rows=250 width=24) (actual time=357.059..357.059 rows=0.00 loops=1) Filter: ((i2 = 898732) AND (i5 = 123451)) - Rows Removed by Filter: 100000 + Rows Removed by Filter: 10000000 + Buffers: shared hit=63744 Planning Time: 0.346 ms - Execution Time: 16.988 ms -(5 rows) + Execution Time: 357.076 ms +(6 rows) @@ -136,17 +137,18 @@ CREATE INDEX =# SELECT pg_size_pretty(pg_relation_size('btreeidx')); pg_size_pretty ---------------- - 3976 kB + 386 MB (1 row) =# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN -------------------------------------------------------------------&zwsp;----------------------------------- - Seq Scan on tbloom (cost=0.00..2137.00 rows=2 width=24) (actual time=12.805..12.805 rows=0 loops=1) + Seq Scan on tbloom (cost=0.00..213744.00 rows=2 width=24) (actual time=351.016..351.017 rows=0.00 loops=1) Filter: ((i2 = 898732) AND (i5 = 123451)) - Rows Removed by Filter: 100000 + Rows Removed by Filter: 10000000 + Buffers: shared hit=63744 Planning Time: 0.138 ms - Execution Time: 12.817 ms -(5 rows) + Execution Time: 351.035 ms +(6 rows) @@ -159,20 +161,23 @@ CREATE INDEX =# SELECT pg_size_pretty(pg_relation_size('bloomidx')); pg_size_pretty ---------------- - 1584 kB + 153 MB (1 row) =# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------------------- - Bitmap Heap Scan on tbloom (cost=1792.00..1799.69 rows=2 width=24) (actual time=0.388..0.388 rows=0 loops=1) + Bitmap Heap Scan on tbloom (cost=1792.00..1799.69 rows=2 width=24) (actual time=22.605..22.606 rows=0.00 loops=1) Recheck Cond: ((i2 = 898732) AND (i5 = 123451)) - Rows Removed by Index Recheck: 29 - Heap Blocks: exact=28 - -> Bitmap Index Scan on bloomidx (cost=0.00..1792.00 rows=2 width=0) (actual time=0.356..0.356 rows=29 loops=1) + Rows Removed by Index Recheck: 2300 + Heap Blocks: exact=2256 + Buffers: shared hit=21864 + -> Bitmap Index Scan on bloomidx (cost=0.00..178436.00 rows=1 width=0) (actual time=20.005..20.005 rows=2300.00 loops=1) Index Cond: ((i2 = 898732) AND (i5 = 123451)) + Index Searches: 1 + Buffers: shared hit=19608 Planning Time: 0.099 ms - Execution Time: 0.408 ms -(8 rows) + Execution Time: 22.632 ms +(11 rows) @@ -197,21 +202,27 @@ CREATE INDEX =# EXPLAIN ANALYZE SELECT * FROM tbloom WHERE i2 = 898732 AND i5 = 123451; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------------------------- - Bitmap Heap Scan on tbloom (cost=24.34..32.03 rows=2 width=24) (actual time=0.028..0.029 rows=0 loops=1) + Bitmap Heap Scan on tbloom (cost=9.29..13.30 rows=1 width=24) (actual time=0.032..0.033 rows=0.00 loops=1) Recheck Cond: ((i5 = 123451) AND (i2 = 898732)) - -> BitmapAnd (cost=24.34..24.34 rows=2 width=0) (actual time=0.027..0.027 rows=0 loops=1) - -> Bitmap Index Scan on btreeidx5 (cost=0.00..12.04 rows=500 width=0) (actual time=0.026..0.026 rows=0 loops=1) + Buffers: shared read=6 + -> BitmapAnd (cost=9.29..9.29 rows=1 width=0) (actual time=0.047..0.047 rows=0.00 loops=1) + Buffers: shared hit=6 + -> Bitmap Index Scan on btreeidx5 (cost=0.00..4.52 rows=11 width=0) (actual time=0.026..0.026 rows=7.00 loops=1) Index Cond: (i5 = 123451) - -> Bitmap Index Scan on btreeidx2 (cost=0.00..12.04 rows=500 width=0) (never executed) + Index Searches: 1 + Buffers: shared hit=3 + -> Bitmap Index Scan on btreeidx2 (cost=0.00..4.52 rows=11 width=0) (actual time=0.007..0.007 rows=8.00 loops=1) Index Cond: (i2 = 898732) - Planning Time: 0.491 ms - Execution Time: 0.055 ms -(9 rows) + Index Searches: 1 + Buffers: shared hit=3 + Planning Time: 0.264 ms + Execution Time: 0.047 ms +(15 rows) Although this query runs much faster than with either of the single indexes, we pay a penalty in index size. Each of the single-column - btree indexes occupies 2 MB, so the total space needed is 12 MB, - eight times the space used by the bloom index. + btree indexes occupies 88.5 MB, so the total space needed is 531 MB, + over three times the space used by the bloom index. diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml index 31e7c78aaef49..a4c1b99be1faf 100644 --- a/doc/src/sgml/btree-gist.sgml +++ b/doc/src/sgml/btree-gist.sgml @@ -52,6 +52,13 @@ oid, and money. + + By default btree_gist builds GiST index with + sortsupport in sorted mode. This usually results in + much faster index built speed. It is still possible to revert to buffered built strategy + by using the buffering parameter when creating the index. + + This module is considered trusted, that is, it can be installed by non-superusers who have CREATE privilege diff --git a/doc/src/sgml/btree.sgml b/doc/src/sgml/btree.sgml index 2b3997988cff0..027361f20bbed 100644 --- a/doc/src/sgml/btree.sgml +++ b/doc/src/sgml/btree.sgml @@ -207,7 +207,7 @@ As shown in , btree defines - one required and four optional support functions. The five + one required and five optional support functions. The six user-defined methods are: @@ -583,6 +583,35 @@ options(relopts local_relopts *) returns + + skipsupport + + + Optionally, a btree operator family may provide a skip + support function, registered under support function number 6. + These functions give the B-tree code a way to iterate through every + possible value that can be represented by an operator class's underlying + input type, in key space order. This is used by the core code when it + applies the skip scan optimization. The APIs involved in this are + defined in src/include/utils/skipsupport.h. + + + Operator classes that do not provide a skip support function are still + eligible to use skip scan. The core code can still use its fallback + strategy, though that might be suboptimal for some discrete types. It + usually doesn't make sense (and may not even be feasible) for operator + classes on continuous types to provide a skip support function. + + + It is not sensible for an operator family to register a cross-type + skipsupport function, and attempting to do so will + result in an error. This is because determining the next indexable value + must happen by incrementing a value copied from an index tuple. The + values generated must all be of the same underlying data type (the + skipped index column's opclass input type). + + + diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index b654fae1b2f60..fa86c569dc497 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1186,17 +1186,6 @@ - - - attcacheoff int4 - - - Always -1 in storage, but when loaded into a row descriptor - in memory this might be updated to cache the offset of the attribute - within the row - - - atttypmod int4 @@ -1271,7 +1260,7 @@ attnotnull bool - This represents a not-null constraint. + This column has a (possibly invalid) not-null constraint. @@ -1318,8 +1307,10 @@ If a zero byte (''), then not a generated column. - Otherwise, s = stored. (Other values might be added - in the future.) + Otherwise, s = stored, v = + virtual. A stored generated column is physically stored like a normal + column. A virtual generated column is physically stored as a null + value, with the actual value being computed at run time. @@ -1591,7 +1582,7 @@ rolpassword text - Password (possibly encrypted); null if none. The format depends + Encrypted password; null if none. The format depends on the form of encryption used. @@ -1618,6 +1609,15 @@ will store the md5 hash of xyzzyjoe. + + + Support for MD5-encrypted passwords is deprecated and will be removed in a + future release of PostgreSQL. Refer to + for details about migrating to another + password type. + + + If the password is encrypted with SCRAM-SHA-256, it has the format: @@ -1627,11 +1627,6 @@ SCRAM-SHA-256$<iteration count>:&l ServerKey are in Base64 encoded format. This format is the same as that specified by RFC 5803. - - - A password that does not follow either of those formats is assumed to be - unencrypted. - @@ -2066,6 +2061,27 @@ SCRAM-SHA-256$<iteration count>:&l + + + relallfrozen int4 + + + Number of pages that are marked all-frozen in the table's visibility + map. This is only an estimate used for triggering autovacuums. It can + also be used along with relallvisible for + scheduling manual vacuums and tuning vacuum's freezing + behavior. + + It is updated by + VACUUM, + ANALYZE, + and a few DDL commands such as + CREATE INDEX. + + + + reltoastrelid oid @@ -2502,14 +2518,10 @@ SCRAM-SHA-256$<iteration count>:&l - The catalog pg_constraint stores check, primary - key, unique, foreign key, and exclusion constraints on tables, as well as - not-null constraints on domains. + The catalog pg_constraint stores check, not-null, + primary key, unique, foreign key, and exclusion constraints on tables. (Column constraints are not treated specially. Every column constraint is equivalent to some table constraint.) - Not-null constraints on relations are represented in the - pg_attribute - catalog, not here. @@ -2571,7 +2583,7 @@ SCRAM-SHA-256$<iteration count>:&l c = check constraint, f = foreign key constraint, - n = not-null constraint (domains only), + n = not-null constraint, p = primary key constraint, u = unique constraint, t = constraint trigger, @@ -2597,13 +2609,21 @@ SCRAM-SHA-256$<iteration count>:&l + + + conenforced bool + + + Is the constraint enforced? + + + convalidated bool Has the constraint been validated? - Currently, can be false only for foreign keys and CHECK constraints @@ -2730,6 +2750,17 @@ SCRAM-SHA-256$<iteration count>:&l + + + conperiod bool + + + This constraint is defined with WITHOUT OVERLAPS + (for primary keys and unique constraints) or PERIOD + (for foreign keys). + + + conkey int2[] @@ -2799,7 +2830,8 @@ SCRAM-SHA-256$<iteration count>:&l (references pg_operator.oid) - If an exclusion constraint, list of the per-column exclusion operators + If an exclusion constraint or WITHOUT OVERLAPS + primary key/unique constraint, list of the per-column exclusion operators. @@ -3322,7 +3354,8 @@ SCRAM-SHA-256$<iteration count>:&l S = sequence, f = function, T = type, - n = schema + n = schema, + L = large object @@ -6024,7 +6057,7 @@ SCRAM-SHA-256$<iteration count>:&l The function has no side effects. No information about the arguments is conveyed except via the return value. Any function that might throw an error depending on the values of its arguments - is not leak-proof. + is not leakproof. @@ -6388,6 +6421,20 @@ SCRAM-SHA-256$<iteration count>:&l publication instead of its own. + + + + pubgencols char + + + Controls how to handle generated column replication when there is no + publication column list: + n = generated columns in the tables associated with + the publication should not be replicated, + s = stored generated columns in the tables associated + with the publication should be replicated. + + @@ -8030,7 +8077,7 @@ SCRAM-SHA-256$<iteration count>:&l If true, the associated replication slots (i.e. the main slot and the - table sync slots) in the upstream database are enabled to be + table synchronization slots) in the upstream database are enabled to be synchronized to the standbys diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml index 834cb30c85a19..5a0e97f6f3158 100644 --- a/doc/src/sgml/charset.sgml +++ b/doc/src/sgml/charset.sgml @@ -377,8 +377,9 @@ initdb --locale-provider=icu --icu-locale=en The builtin provider uses built-in operations. Only - the C and C.UTF-8 locales are - supported for this provider. + the C, C.UTF-8, and + PG_UNICODE_FAST locales are supported for this + provider. The C locale behavior is identical to the @@ -392,6 +393,13 @@ initdb --locale-provider=icu --icu-locale=en regular expression character classes are based on the "POSIX Compatible" semantics, and the case mapping is the "simple" variant. + + The PG_UNICODE_FAST locale is available only when + the database encoding is UTF-8, and the behavior is + based on Unicode. The collation uses the code point values only. The + regular expression character classes are based on the "Standard" + semantics, and the case mapping is the "full" variant. + @@ -862,7 +870,7 @@ SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR"; This SQL standard collation sorts using the Unicode Collation Algorithm with the Default Unicode Collation Element Table. It is available in all encodings. ICU support is required to use this - collation, and behavior may change if Postgres is built with a + collation, and behavior may change if PostgreSQL is built with a different version of ICU. (This collation has the same behavior as the ICU root locale; see .) @@ -886,6 +894,23 @@ SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR"; + + pg_unicode_fast + + + This collation sorts by Unicode code point values rather than natural + language order. For the functions lower, + initcap, and upper it uses + Unicode full case mapping. For pattern matching (including regular + expressions), it uses the Standard variant of Unicode Compatibility + Properties. Behavior is efficient and stable within a + Postgres major version. It is only + available for encoding UTF8. + + + + pg_c_utf8 @@ -897,7 +922,7 @@ SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR"; expressions), it uses the POSIX Compatible variant of Unicode Compatibility Properties. Behavior is efficient and stable within a - Postgres major version. This collation is + PostgreSQL major version. This collation is only available for encoding UTF8. @@ -1197,7 +1222,7 @@ CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-tr to a performance penalty. Note, in particular, that B-tree cannot use deduplication with indexes that use a nondeterministic collation. Also, certain operations are not possible with nondeterministic collations, - such as pattern matching operations. Therefore, they should be used + such as some pattern matching operations. Therefore, they should be used only in cases where they are specifically wanted. @@ -1846,7 +1871,7 @@ ORDER BY c COLLATE ebcdic; Traditional Chinese, Taiwanese Yes Yes - 1–3 + 1–4 diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 51343de7cadbe..832b616a7bbff 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -531,6 +531,15 @@ include_dir directory user's password. See for details. + + + Support for MD5-encrypted passwords is deprecated and will be + removed in a future release of + PostgreSQL. Refer to + for details about migrating to + another password type. + + @@ -647,6 +656,16 @@ include_dir directory + + + oauth + + + Authorize and optionally authenticate using a third-party OAuth 2.0 + identity provider. See for details. + + + @@ -1134,6 +1153,12 @@ omicron bryanh guest1 only on OpenBSD). + + + OAuth authorization/authentication, + which relies on an external OAuth 2.0 identity provider. + + @@ -1260,6 +1285,14 @@ omicron bryanh guest1 server is encrypted for SCRAM (see below), then SCRAM-based authentication will automatically be chosen instead. + + + + Support for MD5-encrypted passwords is deprecated and will be removed + in a future release of PostgreSQL. Refer to + the text below for details about migrating to another password type. + + @@ -2312,6 +2345,242 @@ host ... radius radiusservers="server1,server2" radiussecrets="""secret one"","" + + OAuth Authorization/Authentication + + + OAuth Authorization/Authentication + + + + OAuth 2.0 is an industry-standard framework, defined in + RFC 6749, + to enable third-party applications to obtain limited access to a protected + resource. + + OAuth client support has to be enabled when PostgreSQL + is built, see for more information. + + + + This documentation uses the following terminology when discussing the OAuth + ecosystem: + + + + + Resource Owner (or End User) + + + The user or system who owns protected resources and can grant access to + them. This documentation also uses the term end user + when the resource owner is a person. When you use + psql to connect to the database using OAuth, + you are the resource owner/end user. + + + + + + Client + + + The system which accesses the protected resources using access + tokens. Applications using libpq, such as psql, + are the OAuth clients when connecting to a + PostgreSQL cluster. + + + + + + Resource Server + + + The system hosting the protected resources which are + accessed by the client. The PostgreSQL + cluster being connected to is the resource server. + + + + + + Provider + + + The organization, product vendor, or other entity which develops and/or + administers the OAuth authorization servers and clients for a given application. + Different providers typically choose different implementation details + for their OAuth systems; a client of one provider is not generally + guaranteed to have access to the servers of another. + + + This use of the term "provider" is not standard, but it seems to be in + wide use colloquially. (It should not be confused with OpenID's similar + term "Identity Provider". While the implementation of OAuth in + PostgreSQL is intended to be interoperable + and compatible with OpenID Connect/OIDC, it is not itself an OIDC client + and does not require its use.) + + + + + + Authorization Server + + + The system which receives requests from, and issues access tokens to, + the client after the authenticated resource owner has given approval. + PostgreSQL does not provide an authorization + server; it is the responsibility of the OAuth provider. + + + + + + Issuer + + + An identifier for an authorization server, printed as an + https:// URL, which provides a trusted "namespace" + for OAuth clients and applications. The issuer identifier allows a + single authorization server to talk to the clients of mutually + untrusting entities, as long as they maintain separate issuers. + + + + + + + + + For small deployments, there may not be a meaningful distinction between + the "provider", "authorization server", and "issuer". However, for more + complicated setups, there may be a one-to-many (or many-to-many) + relationship: a provider may rent out multiple issuer identifiers to + separate tenants, then provide multiple authorization servers, possibly + with different supported feature sets, to interact with their clients. + + + + + + PostgreSQL supports bearer tokens, defined in + RFC 6750, + which are a type of access token used with OAuth 2.0 where the token is an + opaque string. The format of the access token is implementation specific + and is chosen by each authorization server. + + + + The following configuration options are supported for OAuth: + + + issuer + + + An HTTPS URL which is either the exact + issuer identifier of the + authorization server, as defined by its discovery document, or a + well-known URI that points directly to that discovery document. This + parameter is required. + + + When an OAuth client connects to the server, a URL for the discovery + document will be constructed using the issuer identifier. By default, + this URL uses the conventions of OpenID Connect Discovery: the path + /.well-known/openid-configuration will be appended + to the end of the issuer identifier. Alternatively, if the + issuer contains a /.well-known/ + path segment, that URL will be provided to the client as-is. + + + + The OAuth client in libpq requires the server's issuer setting to + exactly match the issuer identifier which is provided in the discovery + document, which must in turn match the client's + setting. No variations in + case or formatting are permitted. + + + + + + + scope + + + A space-separated list of the OAuth scopes needed for the server to + both authorize the client and authenticate the user. Appropriate values + are determined by the authorization server and the OAuth validation + module used (see for more + information on validators). This parameter is required. + + + + + + validator + + + The library to use for validating bearer tokens. If given, the name must + exactly match one of the libraries listed in + . This parameter is + optional unless oauth_validator_libraries contains + more than one library, in which case it is required. + + + + + + map + + + Allows for mapping between OAuth identity provider and database user + names. See for details. If a + map is not specified, the user name associated with the token (as + determined by the OAuth validator) must exactly match the role name + being requested. This parameter is optional. + + + + + + + delegate_ident_mapping + + + + An advanced option which is not intended for common use. + + + When set to 1, standard user mapping with + pg_ident.conf is skipped, and the OAuth validator + takes full responsibility for mapping end user identities to database + roles. If the validator authorizes the token, the server trusts that + the user is allowed to connect under the requested role, and the + connection is allowed to proceed regardless of the authentication + status of the user. + + + This parameter is incompatible with map. + + + + delegate_ident_mapping provides additional + flexibility in the design of the authentication system, but it also + requires careful implementation of the OAuth validator, which must + determine whether the provided token carries sufficient end-user + privileges in addition to the standard + checks required of all validators. Use with caution. + + + + + + + + Authentication Problems diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 57cd7bb972711..7e0e5400ee128 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -140,7 +140,7 @@ An example of what this file might look like is: # This is a comment -log_connections = yes +log_connections = all log_destination = 'syslog' search_path = '"$user", public' shared_buffers = 128MB @@ -337,7 +337,7 @@ UPDATE pg_settings SET setting = reset_val WHERE name = 'configuration_parameter command-line parameter, or its equivalent variation. For example, -postgres -c log_connections=yes --log-destination='syslog' +postgres -c log_connections=all --log-destination='syslog' Settings provided in this way override those set via postgresql.conf or ALTER SYSTEM, @@ -708,7 +708,7 @@ include_dir 'conf.d' - PostgreSQL sizes certain resources based directly on the value of + PostgreSQL sizes certain resources based directly on the value of max_connections. Increasing its value leads to higher allocation of those resources, including shared memory. @@ -1124,6 +1124,14 @@ include_dir 'conf.d' mechanism, and hence not work with passwords encrypted with SCRAM-SHA-256. See for more details. + + + Support for MD5-encrypted passwords is deprecated and will be removed + in a future release of PostgreSQL. Refer + to for details about migrating to + another password type. + + @@ -1147,6 +1155,22 @@ include_dir 'conf.d' + + md5_password_warnings (boolean) + + md5_password_warnings configuration parameter + + + + + Controls whether a WARNING about MD5 password + deprecation is produced when a CREATE ROLE or + ALTER ROLE statement sets an MD5-encrypted password. + The default value is on. + + + + krb_server_keyfile (string) @@ -1201,6 +1225,32 @@ include_dir 'conf.d' + + + oauth_validator_libraries (string) + + oauth_validator_libraries configuration parameter + + + + + The library/libraries to use for validating OAuth connection tokens. If + only one validator library is provided, it will be used by default for + any OAuth connections; otherwise, all + oauth HBA entries + must explicitly set a validator chosen from this + list. If set to an empty string (the default), OAuth connections will be + refused. This parameter can only be set in the + postgresql.conf file. + + + Validator modules must be implemented/obtained separately; + PostgreSQL does not ship with any default + implementations. For more information on implementing OAuth validators, + see . + + + @@ -1340,6 +1390,28 @@ include_dir 'conf.d' + + ssl_tls13_ciphers (string) + + ssl_tls13_ciphers configuration parameter + + + + + Specifies a list of cipher suites that are allowed by connections using + TLS version 1.3. Multiple cipher suites can be + specified by using a colon separated list. If left blank, the default + set of cipher suites in OpenSSL will be used. + + + + This parameter can only be set in the + postgresql.conf file or on the server command + line. + + + + ssl_ciphers (string) @@ -1348,15 +1420,13 @@ include_dir 'conf.d' - Specifies a list of SSL cipher suites that are - allowed to be used by SSL connections. See the - ciphers + Specifies a list of SSL ciphers that are allowed by + connections using TLS version 1.2 and lower, see + for TLS version 1.3 connections. See + the ciphers manual page in the OpenSSL package for the - syntax of this setting and a list of supported values. Only - connections using TLS version 1.2 and lower are affected. There is - currently no setting that controls the cipher choices used by TLS - version 1.3 connections. The default value is - HIGH:MEDIUM:+3DES:!aNULL. The default is usually a + syntax of this setting and a list of supported values. The default value + is HIGH:MEDIUM:+3DES:!aNULL. The default is usually a reasonable choice unless you have specific security requirements. @@ -1452,21 +1522,21 @@ include_dir 'conf.d' - - ssl_ecdh_curve (string) + + ssl_groups (string) - ssl_ecdh_curve configuration parameter + ssl_groups configuration parameter Specifies the name of the curve to use in ECDH key exchange. It needs to be supported by all clients that connect. + Multiple curves can be specified by using a colon-separated list. It does not need to be the same curve used by the server's Elliptic - Curve key. - This parameter can only be set in the postgresql.conf - file or on the server command line. - The default is prime256v1. + Curve key. This parameter can only be set in the + postgresql.conf file or on the server command line. + The default is X25519:prime256v1. @@ -1475,9 +1545,16 @@ include_dir 'conf.d' prime256v1 (NIST P-256), secp384r1 (NIST P-384), secp521r1 (NIST P-521). - The full list of available curves can be shown with the command - openssl ecparam -list_curves. Not all of them - are usable in TLS though. + An incomplete list of available groups can be shown with the command + openssl ecparam -list_curves. Not all of them are + usable with TLS though, and many supported group + names and aliases are omitted. + + + + In PostgreSQL versions before 18.0 this + setting was named ssl_ecdh_curve and only accepted + a single value. @@ -2286,6 +2363,44 @@ include_dir 'conf.d' + + file_copy_method (enum) + + file_copy_method configuration parameter + + + + + Specifies the method used to copy files. + Possible values are COPY (default) and + CLONE (if operating support is available). + + + + This parameter affects: + + + + + CREATE DATABASE ... STRATEGY=FILE_COPY + + + + + ALTER DATABASE ... SET TABLESPACE ... + + + + + + CLONE uses the copy_file_range() + (Linux, FreeBSD) or copyfile + (macOS) system calls, giving the kernel the opportunity to share disk + blocks or push work down to lower layers on some file systems. + + + + max_notify_queue_pages (integer) @@ -2317,8 +2432,13 @@ include_dir 'conf.d' - Sets the maximum number of simultaneously open files allowed to each - server subprocess. The default is one thousand files. If the kernel is enforcing + Sets the maximum number of open files each server subprocess is + allowed to open simultaneously; files already opened in the + postmaster are not counted toward this limit. The default is one + thousand files. + + + If the kernel is enforcing a safe per-process limit, you don't need to worry about this setting. But on some platforms (notably, most BSD systems), the kernel will allow individual processes to open many more files than the system @@ -2332,149 +2452,6 @@ include_dir 'conf.d' - - Cost-based Vacuum Delay - - - During the execution of - and - commands, the system maintains an - internal counter that keeps track of the estimated cost of the - various I/O operations that are performed. When the accumulated - cost reaches a limit (specified by - vacuum_cost_limit), the process performing - the operation will sleep for a short period of time, as specified by - vacuum_cost_delay. Then it will reset the - counter and continue execution. - - - - The intent of this feature is to allow administrators to reduce - the I/O impact of these commands on concurrent database - activity. There are many situations where it is not - important that maintenance commands like - VACUUM and ANALYZE finish - quickly; however, it is usually very important that these - commands do not significantly interfere with the ability of the - system to perform other database operations. Cost-based vacuum - delay provides a way for administrators to achieve this. - - - - This feature is disabled by default for manually issued - VACUUM commands. To enable it, set the - vacuum_cost_delay variable to a nonzero - value. - - - - - vacuum_cost_delay (floating point) - - vacuum_cost_delay configuration parameter - - - - - The amount of time that the process will sleep - when the cost limit has been exceeded. - If this value is specified without units, it is taken as milliseconds. - The default value is zero, which disables the cost-based vacuum - delay feature. Positive values enable cost-based vacuuming. - - - - When using cost-based vacuuming, appropriate values for - vacuum_cost_delay are usually quite small, perhaps - less than 1 millisecond. While vacuum_cost_delay - can be set to fractional-millisecond values, such delays may not be - measured accurately on older platforms. On such platforms, - increasing VACUUM's throttled resource consumption - above what you get at 1ms will require changing the other vacuum cost - parameters. You should, nonetheless, - keep vacuum_cost_delay as small as your platform - will consistently measure; large delays are not helpful. - - - - - - vacuum_cost_page_hit (integer) - - vacuum_cost_page_hit configuration parameter - - - - - The estimated cost for vacuuming a buffer found in the shared buffer - cache. It represents the cost to lock the buffer pool, lookup - the shared hash table and scan the content of the page. The - default value is one. - - - - - - vacuum_cost_page_miss (integer) - - vacuum_cost_page_miss configuration parameter - - - - - The estimated cost for vacuuming a buffer that has to be read from - disk. This represents the effort to lock the buffer pool, - lookup the shared hash table, read the desired block in from - the disk and scan its content. The default value is 2. - - - - - - vacuum_cost_page_dirty (integer) - - vacuum_cost_page_dirty configuration parameter - - - - - The estimated cost charged when vacuum modifies a block that was - previously clean. It represents the extra I/O required to - flush the dirty block out to disk again. The default value is - 20. - - - - - - vacuum_cost_limit (integer) - - vacuum_cost_limit configuration parameter - - - - - This is the accumulated cost that will cause the vacuuming process to sleep - for vacuum_cost_delay. The default is 200. - - - - - - - - There are certain operations that hold critical locks and should - therefore complete as quickly as possible. Cost-based vacuum - delays do not occur during such operations. Therefore it is - possible that the cost accumulates far higher than the specified - limit. To avoid uselessly long delays in such cases, the actual - delay is calculated as vacuum_cost_delay * - accumulated_balance / - vacuum_cost_limit with a maximum of - vacuum_cost_delay * 4. - - - Background Writer @@ -2614,8 +2591,8 @@ include_dir 'conf.d' - - Asynchronous Behavior + + I/O @@ -2656,41 +2633,33 @@ include_dir 'conf.d' - Sets the number of concurrent disk I/O operations that + Sets the number of concurrent storage I/O operations that PostgreSQL expects can be executed simultaneously. Raising this value will increase the number of I/O - operations that any individual PostgreSQL session - attempts to initiate in parallel. The allowed range is 1 to 1000, - or zero to disable issuance of asynchronous I/O requests. Currently, - this setting only affects bitmap heap scans. + operations that any individual PostgreSQL + session attempts to initiate in parallel. The allowed range is + 1 to 1000, or + 0 to disable issuance of asynchronous I/O requests. + The default is 16. - For magnetic drives, a good starting point for this setting is the - number of separate - drives comprising a RAID 0 stripe or RAID 1 mirror being used for the - database. (For RAID 5 the parity drive should not be counted.) - However, if the database is often busy with multiple queries issued in - concurrent sessions, lower values may be sufficient to keep the disk - array busy. A value higher than needed to keep the disks busy will - only result in extra CPU overhead. - SSDs and other memory-based storage can often process many - concurrent requests, so the best value might be in the hundreds. + Higher values will have the most impact on higher latency storage + where queries otherwise experience noticeable I/O stalls and on + devices with high IOPs. Unnecessarily high values may increase I/O + latency for all queries on the system - Asynchronous I/O depends on an effective posix_fadvise - function, which some operating systems lack. If the function is not - present then setting this parameter to anything but zero will result - in an error. On some operating systems (e.g., Solaris), the function - is present but does not actually do anything. + On systems with prefetch advice support, + effective_io_concurrency also controls the + prefetch distance. - The default is 1 on supported systems, otherwise 0. This value can - be overridden for tables in a particular tablespace by setting the - tablespace parameter of the same name (see - ). + This value can be overridden for tables in a particular tablespace by + setting the tablespace parameter of the same name (see ). @@ -2707,10 +2676,30 @@ include_dir 'conf.d' for maintenance work that is done on behalf of many client sessions. - The default is 10 on supported systems, otherwise 0. This value can - be overridden for tables in a particular tablespace by setting the - tablespace parameter of the same name (see - ). + The default is 16. This value can be overridden + for tables in a particular tablespace by setting the tablespace + parameter of the same name (see ). + + + + + + io_max_combine_limit (integer) + + io_max_combine_limit configuration parameter + + + + + Controls the largest I/O size in operations that combine I/O, and silently + limits the user-settable parameter io_combine_limit. + This parameter can only be set in + the postgresql.conf file or on the server + command line. + The maximum possible size depends on the operating system and block + size, but is typically 1MB on Unix and 128kB on Windows. + The default is 128kB. @@ -2723,63 +2712,158 @@ include_dir 'conf.d' - Controls the largest I/O size in operations that combine I/O. + Controls the largest I/O size in operations that combine I/O. If set + higher than the io_max_combine_limit parameter, the + lower value will silently be used instead, so both may need to be raised + to increase the I/O size. + The maximum possible size depends on the operating system and block + size, but is typically 1MB on Unix and 128kB on Windows. The default is 128kB. - - max_worker_processes (integer) + + io_max_concurrency (integer) - max_worker_processes configuration parameter + io_max_concurrency configuration parameter - Sets the maximum number of background processes that the cluster - can support. This parameter can only be set at server start. The - default is 8. + Controls the maximum number of I/O operations that one process can + execute simultaneously. - - When running a standby server, you must set this parameter to the - same or higher value than on the primary server. Otherwise, queries - will not be allowed in the standby server. + The default setting of -1 selects a number based + on and the maximum number of + processes (, , and ), but not more than + 64. - - When changing this value, consider also adjusting - , - , and - . + This parameter can only be set at server start. - - max_parallel_workers_per_gather (integer) + + io_method (enum) - max_parallel_workers_per_gather configuration parameter + io_method configuration parameter - Sets the maximum number of workers that can be started by a single - Gather or Gather Merge node. - Parallel workers are taken from the pool of processes established by - , limited by - . Note that the requested - number of workers may not actually be available at run time. If this - occurs, the plan will run with fewer workers than expected, which may - be inefficient. The default value is 2. Setting this value to 0 - disables parallel query execution. + Selects the method for executing asynchronous I/O. + Possible values are: + + + + worker (execute asynchronous I/O using worker processes) + + + + + io_uring (execute asynchronous I/O using + io_uring, requires a build with + / + ) + + + + + sync (execute asynchronous-eligible I/O synchronously) + + + + The default is worker. - - Note that parallel queries may consume very substantially more - resources than non-parallel queries, because each worker process is - a completely separate process which has roughly the same impact on the + This parameter can only be set at server start. + + + + + + io_workers (int) + + io_workers configuration parameter + + + + + Selects the number of I/O worker processes to use. The default is + 3. This parameter can only be set in the + postgresql.conf file or on the server command + line. + + + Only has an effect if is set to + worker. + + + + + + + + Worker Processes + + + + max_worker_processes (integer) + + max_worker_processes configuration parameter + + + + + Sets the maximum number of background processes that the cluster + can support. This parameter can only be set at server start. The + default is 8. + + + + When running a standby server, you must set this parameter to the + same or higher value than on the primary server. Otherwise, queries + will not be allowed in the standby server. + + + + When changing this value, consider also adjusting + , + , and + . + + + + + + max_parallel_workers_per_gather (integer) + + max_parallel_workers_per_gather configuration parameter + + + + + Sets the maximum number of workers that can be started by a single + Gather or Gather Merge node. + Parallel workers are taken from the pool of processes established by + , limited by + . Note that the requested + number of workers may not actually be available at run time. If this + occurs, the plan will run with fewer workers than expected, which may + be inefficient. The default value is 2. Setting this value to 0 + disables parallel query execution. + + + + Note that parallel queries may consume very substantially more + resources than non-parallel queries, because each worker process is + a completely separate process which has roughly the same impact on the system as an additional user session. This should be taken into account when choosing a value for this setting, as well as when configuring other settings that control resource utilization, such @@ -2810,7 +2894,7 @@ include_dir 'conf.d' Sets the maximum number of parallel workers that can be started by a single utility command. Currently, the parallel utility commands that support the use of parallel workers are - CREATE INDEX only when building a B-tree index, + CREATE INDEX when building a B-tree or BRIN index, and VACUUM without FULL option. Parallel workers are taken from the pool of processes established by , limited @@ -3852,10 +3936,8 @@ include_dir 'conf.d' off, on and try (the default). The setting try enables - prefetching only if the operating system provides the - posix_fadvise function, which is currently used - to implement prefetching. Note that some operating systems provide the - function, but it doesn't do anything. + prefetching only if the operating system provides support for issuing + read-ahead advice. Prefetching blocks that will soon be needed can reduce I/O wait times @@ -4447,7 +4529,6 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows max_replication_slots (integer) max_replication_slots configuration parameter - in a sending server @@ -4462,11 +4543,6 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows to replica or higher to allow replication slots to be used. - - - Note that this parameter also applies on the subscriber side, but with - a different meaning. - @@ -4533,6 +4609,46 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows + + idle_replication_slot_timeout (integer) + + idle_replication_slot_timeout configuration parameter + + + + + Invalidate replication slots that have remained idle longer than this + duration. If this value is specified without units, it is taken as + minutes. A value of zero (the default) disables the idle timeout + invalidation mechanism. This parameter can only be set in the + postgresql.conf file or on the server command + line. + + + + Slot invalidation due to idle timeout occurs during checkpoint. + Because checkpoints happen at checkpoint_timeout + intervals, there can be some lag between when the + idle_replication_slot_timeout was exceeded and when + the slot invalidation is triggered at the next checkpoint. + To avoid such lags, users can force a checkpoint to promptly invalidate + inactive slots. The duration of slot inactivity is calculated using the + slot's pg_replication_slots.inactive_since + value. + + + + Note that the idle timeout invalidation mechanism is not applicable + for slots that do not reserve WAL or for slots on the standby server + that are being synced from the primary server (i.e., standby slots + having pg_replication_slots.synced + value true). Synced slots are always considered to + be inactive because they don't perform logical decoding to produce + changes. + + + + wal_sender_timeout (integer) @@ -4682,6 +4798,8 @@ ANY num_sync ( standby_name is the name of a standby server. + num_sync + must be an integer value greater than zero. FIRST and ANY specify the method to choose synchronous standbys from the listed servers. @@ -5005,6 +5123,13 @@ ANY num_sync ( ( num_sync ( - max_replication_slots (integer) + + max_active_replication_origins (integer) - max_replication_slots configuration parameter - in a subscriber + max_active_replication_origins configuration parameter @@ -5184,16 +5309,13 @@ ANY num_sync ( pg_replication_origin_status) - will prevent the server from starting. - max_replication_slots must be set to at least the + will prevent the server from starting. It defaults to 10. This parameter + can only be set at server start. + + max_active_replication_origins must be set to at least the number of subscriptions that will be added to the subscriber, plus some reserve for table synchronization. - - - Note that this parameter also applies on a sending server, but with - a different meaning. - @@ -5333,6 +5455,20 @@ ANY num_sync ( + enable_distinct_reordering (boolean) + + enable_distinct_reordering configuration parameter + + + + + Enables or disables the query planner's ability to reorder DISTINCT + keys to match the input path's pathkeys. The default is on. + + + + enable_gathermerge (boolean) @@ -5419,8 +5555,9 @@ ANY num_sync ( . @@ -5435,7 +5572,9 @@ ANY num_sync ( ). - The default is on. + The default is on. The + setting must also be + enabled to have the query planner consider index-only-scans. @@ -5567,9 +5706,13 @@ ANY num_sync ( num_sync ( num_sync ( + enable_self_join_elimination (boolean) + + enable_self_join_elimination configuration parameter + + + + + Enables or disables the query planner's optimization which analyses + the query tree and replaces self joins with semantically equivalent + single scans. Takes into consideration only plain tables. + The default is on. + + + + enable_seqscan (boolean) @@ -6418,7 +6581,7 @@ SELECT * FROM parent WHERE key = 2400; If csvlog is included in log_destination, - log entries are output in comma separated + log entries are output in comma-separated value (CSV) format, which is convenient for loading logs into programs. See for details. @@ -7307,20 +7470,105 @@ local0.* /var/log/postgresql - log_connections (boolean) + log_connections (string) log_connections configuration parameter - Causes each attempted connection to the server to be logged, - as well as successful completion of both client authentication (if - necessary) and authorization. + Causes aspects of each connection to the server to be logged. + The default is the empty string, '', which + disables all connection logging. The following options may be + specified alone or in a comma-separated list: + + + + Log Connection Options + + + + + + Name + Description + + + + + receipt + Logs receipt of a connection. + + + + authentication + + Logs the original identity used by an authentication method + to identify a user. In most cases, the identity string + matches the PostgreSQL username, + but some third-party authentication methods may alter the + original user identifier before the server stores it. Failed + authentication is always logged regardless of the value of + this setting. + + + + + authorization + + Logs successful completion of authorization. At this point + the connection has been established but the backend is not + yet fully set up. The log message includes the authorized + username as well as the database name and application name, + if applicable. + + + + + setup_durations + + Logs the time spent establishing the connection and setting up the + backend until the connection is ready to execute its first + query. The log message includes three durations: the total + setup duration (starting from the postmaster accepting the + incoming connection and ending when the connection is ready + for query), the time it took to fork the new backend, and + the time it took to authenticate the user. + + + + + all + + A convenience alias equivalent to specifying all options. If + all is specified in a list of other + options, all connection aspects will be logged. + + + + + +
+ + + Disconnection logging is separately controlled by . + + + + For the purposes of backwards compatibility, on, + off, true, + false, yes, + no, 1, and 0 + are still supported. The positive values are equivalent to specifying + the receipt, authentication, and + authorization options. + + + Only superusers and users with the appropriate SET privilege can change this parameter at session start, and it cannot be changed at all within a session. - The default is off. @@ -7495,6 +7743,12 @@ local0.* /var/log/postgresql Remote host name or IP address yes + + %L + Local address (the IP address on the server that the + client connected to) + yes + %b Backend type @@ -7670,6 +7924,26 @@ log_line_prefix = '%m [%p] %q%u@%d/%a '
+ + log_lock_failures (boolean) + + log_lock_failures configuration parameter + + + + + Controls whether a detailed log message is produced + when a lock acquisition fails. This is useful for analyzing + the causes of lock failures. Currently, only lock failures + due to SELECT NOWAIT is supported. + The default is off. Only superusers and + users with the appropriate SET privilege + can change this setting. + + + + + log_recovery_conflict_waits (boolean) @@ -8198,7 +8472,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; various purposes. The cluster name appears in the process title for all server processes in this cluster. Moreover, it is the default application name for a standby connection (see .) + linkend="guc-synchronous-standby-names"/>). @@ -8310,6 +8584,33 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + track_cost_delay_timing (boolean) + + track_cost_delay_timing configuration parameter + + + + + Enables timing of cost-based vacuum delay (see + ). This parameter + is off by default, as it will repeatedly query the operating system for + the current time, which may cause significant overhead on some + platforms. You can use the tool to + measure the overhead of timing on your system. Cost-based vacuum delay + timing information is displayed in + pg_stat_progress_vacuum, + pg_stat_progress_analyze, + in the output of when the + VERBOSE option is used, and by autovacuum for + auto-vacuums and auto-analyzes when + is set. + Only superusers and users with the appropriate SET + privilege can change this setting. + + + + track_io_timing (boolean) @@ -8318,7 +8619,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - Enables timing of database I/O calls. This parameter is off by + Enables timing of database I/O waits. This parameter is off by default, as it will repeatedly query the operating system for the current time, which may cause significant overhead on some platforms. You can use the tool to @@ -8327,9 +8628,13 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; displayed in pg_stat_database, - pg_stat_io, in the output of - when the BUFFERS option - is used, in the output of when + pg_stat_io (if object + is not wal), in the output of the + + pg_stat_get_backend_io() function (if + object is not wal), in the + output of when the BUFFERS + option is used, in the output of when the VERBOSE option is used, by autovacuum for auto-vacuums and auto-analyzes, when is set and by @@ -8348,14 +8653,18 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - Enables timing of WAL I/O calls. This parameter is off by default, + Enables timing of WAL I/O waits. This parameter is off by default, as it will repeatedly query the operating system for the current time, which may cause significant overhead on some platforms. You can use the pg_test_timing tool to measure the overhead of timing on your system. - I/O timing information is - displayed in - pg_stat_wal. + I/O timing information is displayed in + + pg_stat_io for the + object wal and in the output of + the + pg_stat_get_backend_io() function for the + object wal. Only superusers and users with the appropriate SET privilege can change this setting. @@ -8510,14 +8819,22 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
- - Automatic Vacuuming + + Vacuuming - autovacuum + vacuum configuration parameters + + These parameters control vacuuming behavior. For more information on the + purpose and responsibilities of vacuum, see . + + + + Automatic Vacuuming + These settings control the behavior of the autovacuum feature. Refer to for more information. @@ -8525,298 +8842,745 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; basis; see . - + - - autovacuum (boolean) - - autovacuum configuration parameter - - - - - Controls whether the server should run the - autovacuum launcher daemon. This is on by default; however, - must also be enabled for - autovacuum to work. - This parameter can only be set in the postgresql.conf - file or on the server command line; however, autovacuuming can be - disabled for individual tables by changing table storage parameters. - - - Note that even when this parameter is disabled, the system - will launch autovacuum processes if necessary to - prevent transaction ID wraparound. See for more information. - - - + + autovacuum (boolean) + + autovacuum configuration parameter + + + + + Controls whether the server should run the + autovacuum launcher daemon. This is on by default; however, + must also be enabled for + autovacuum to work. + This parameter can only be set in the postgresql.conf + file or on the server command line; however, autovacuuming can be + disabled for individual tables by changing table storage parameters. + + + Note that even when this parameter is disabled, the system + will launch autovacuum processes if necessary to + prevent transaction ID wraparound. See for more information. + + + - - autovacuum_max_workers (integer) - - autovacuum_max_workers configuration parameter - - - - - Specifies the maximum number of autovacuum processes (other than the - autovacuum launcher) that may be running at any one time. The default - is three. This parameter can only be set at server start. - - - + + autovacuum_worker_slots (integer) + + autovacuum_worker_slots configuration parameter + + + + + Specifies the number of backend slots to reserve for autovacuum worker + processes. The default is typically 16 slots, but might be less if + your kernel settings will not support it (as determined during initdb). + This parameter can only be set at server start. + + + When changing this value, consider also adjusting + . + + + - - autovacuum_naptime (integer) - - autovacuum_naptime configuration parameter - - - - - Specifies the minimum delay between autovacuum runs on any given - database. In each round the daemon examines the - database and issues VACUUM and ANALYZE commands - as needed for tables in that database. - If this value is specified without units, it is taken as seconds. - The default is one minute (1min). - This parameter can only be set in the postgresql.conf - file or on the server command line. - - - + + autovacuum_max_workers (integer) + + autovacuum_max_workers configuration parameter + + + + + Specifies the maximum number of autovacuum processes (other than the + autovacuum launcher) that may be running at any one time. The default + is 3. This parameter can only be set in the + postgresql.conf file or on the server command line. + + + Note that a setting for this value which is higher than + will have no effect, + since autovacuum workers are taken from the pool of slots established + by that setting. + + + - - autovacuum_vacuum_threshold (integer) - - autovacuum_vacuum_threshold - configuration parameter - - - - - Specifies the minimum number of updated or deleted tuples needed - to trigger a VACUUM in any one table. - The default is 50 tuples. - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + autovacuum_naptime (integer) + + autovacuum_naptime configuration parameter + + + + + Specifies the minimum delay between autovacuum runs on any given + database. In each round the daemon examines the + database and issues VACUUM and ANALYZE commands + as needed for tables in that database. + If this value is specified without units, it is taken as seconds. + The default is one minute (1min). + This parameter can only be set in the postgresql.conf + file or on the server command line. + + + - - autovacuum_vacuum_insert_threshold (integer) - - autovacuum_vacuum_insert_threshold - configuration parameter - - - - - Specifies the number of inserted tuples needed to trigger a - VACUUM in any one table. - The default is 1000 tuples. If -1 is specified, autovacuum will not - trigger a VACUUM operation on any tables based on - the number of inserts. - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + autovacuum_vacuum_threshold (integer) + + autovacuum_vacuum_threshold + configuration parameter + + + + + Specifies the minimum number of updated or deleted tuples needed + to trigger a VACUUM in any one table. + The default is 50 tuples. + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + - - autovacuum_analyze_threshold (integer) - - autovacuum_analyze_threshold - configuration parameter - - - - - Specifies the minimum number of inserted, updated or deleted tuples - needed to trigger an ANALYZE in any one table. - The default is 50 tuples. - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + autovacuum_vacuum_insert_threshold (integer) + + autovacuum_vacuum_insert_threshold + configuration parameter + + + + + Specifies the number of inserted tuples needed to trigger a + VACUUM in any one table. + The default is 1000 tuples. If -1 is specified, autovacuum will not + trigger a VACUUM operation on any tables based on + the number of inserts. + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + - - autovacuum_vacuum_scale_factor (floating point) - - autovacuum_vacuum_scale_factor - configuration parameter - - - - - Specifies a fraction of the table size to add to - autovacuum_vacuum_threshold - when deciding whether to trigger a VACUUM. - The default is 0.2 (20% of table size). - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + autovacuum_analyze_threshold (integer) + + autovacuum_analyze_threshold + configuration parameter + + + + + Specifies the minimum number of inserted, updated or deleted tuples + needed to trigger an ANALYZE in any one table. + The default is 50 tuples. + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + + + + autovacuum_vacuum_scale_factor (floating point) + + autovacuum_vacuum_scale_factor + configuration parameter + + + + + Specifies a fraction of the table size to add to + autovacuum_vacuum_threshold + when deciding whether to trigger a VACUUM. + The default is 0.2 (20% of table size). + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + + + + autovacuum_vacuum_insert_scale_factor (floating point) + + autovacuum_vacuum_insert_scale_factor + configuration parameter + + + + + Specifies a fraction of the unfrozen pages in the table to add to + autovacuum_vacuum_insert_threshold when deciding + whether to trigger a VACUUM. The default is + 0.2 (20% of unfrozen pages in table). This + parameter can only be set in the postgresql.conf + file or on the server command line; but the setting can be overridden + for individual tables by changing table storage parameters. + + + + + + autovacuum_analyze_scale_factor (floating point) + + autovacuum_analyze_scale_factor + configuration parameter + + + + + Specifies a fraction of the table size to add to + autovacuum_analyze_threshold + when deciding whether to trigger an ANALYZE. + The default is 0.1 (10% of table size). + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + + + + autovacuum_vacuum_max_threshold (integer) + + autovacuum_vacuum_max_threshold + configuration parameter + + + + + Specifies the maximum number of updated or deleted tuples needed to + trigger a VACUUM in any one table, i.e., a limit on + the value calculated with + autovacuum_vacuum_threshold and + autovacuum_vacuum_scale_factor. The default is + 100,000,000 tuples. If -1 is specified, autovacuum will not enforce a + maximum number of updated or deleted tuples that will trigger a + VACUUM operation. This parameter can only be set + in the postgresql.conf file or on the server + command line; but the setting can be overridden for individual tables + by changing storage parameters. + + + + + + autovacuum_freeze_max_age (integer) + + autovacuum_freeze_max_age + configuration parameter + + + + + Specifies the maximum age (in transactions) that a table's + pg_class.relfrozenxid field can + attain before a VACUUM operation is forced + to prevent transaction ID wraparound within the table. + Note that the system will launch autovacuum processes to + prevent wraparound even when autovacuum is otherwise disabled. + + + + Vacuum also allows removal of old files from the + pg_xact subdirectory, which is why the default + is a relatively low 200 million transactions. + This parameter can only be set at server start, but the setting + can be reduced for individual tables by + changing table storage parameters. + For more information see . + + + + + + autovacuum_multixact_freeze_max_age (integer) + + autovacuum_multixact_freeze_max_age + configuration parameter + + + + + Specifies the maximum age (in multixacts) that a table's + pg_class.relminmxid field can + attain before a VACUUM operation is forced to + prevent multixact ID wraparound within the table. + Note that the system will launch autovacuum processes to + prevent wraparound even when autovacuum is otherwise disabled. + + + + Vacuuming multixacts also allows removal of old files from the + pg_multixact/members and pg_multixact/offsets + subdirectories, which is why the default is a relatively low + 400 million multixacts. + This parameter can only be set at server start, but the setting can + be reduced for individual tables by changing table storage parameters. + For more information see . + + + + + + autovacuum_vacuum_cost_delay (floating point) + + autovacuum_vacuum_cost_delay + configuration parameter + + + + + Specifies the cost delay value that will be used in automatic + VACUUM operations. If -1 is specified, the regular + value will be used. + If this value is specified without units, it is taken as milliseconds. + The default value is 2 milliseconds. + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + + + + autovacuum_vacuum_cost_limit (integer) + + autovacuum_vacuum_cost_limit + configuration parameter + + + + + Specifies the cost limit value that will be used in automatic + VACUUM operations. If -1 + is specified (which is the default), the regular + value will be used. Note that + the value is distributed proportionally among the running autovacuum + workers, if there is more than one, so that the sum of the limits for + each worker does not exceed the value of this variable. + This parameter can only be set in the postgresql.conf + file or on the server command line; + but the setting can be overridden for individual tables by + changing table storage parameters. + + + + + + + + + Cost-based Vacuum Delay + + + During the execution of + and + commands, the system maintains an + internal counter that keeps track of the estimated cost of the + various I/O operations that are performed. When the accumulated + cost reaches a limit (specified by + vacuum_cost_limit), the process performing + the operation will sleep for a short period of time, as specified by + vacuum_cost_delay. Then it will reset the + counter and continue execution. + + + + The intent of this feature is to allow administrators to reduce + the I/O impact of these commands on concurrent database + activity. There are many situations where it is not + important that maintenance commands like + VACUUM and ANALYZE finish + quickly; however, it is usually very important that these + commands do not significantly interfere with the ability of the + system to perform other database operations. Cost-based vacuum + delay provides a way for administrators to achieve this. + + + + This feature is disabled by default for manually issued + VACUUM commands. To enable it, set the + vacuum_cost_delay variable to a nonzero + value. + + + + + vacuum_cost_delay (floating point) + + vacuum_cost_delay configuration parameter + + + + + The amount of time that the process will sleep when the cost + limit has been exceeded. If this value is specified without + units, it is taken as milliseconds. The default value is + 0, which disables the cost-based vacuum delay + feature. Positive values enable cost-based vacuuming. + + + + When using cost-based vacuuming, appropriate values for + vacuum_cost_delay are usually quite small, perhaps + less than 1 millisecond. While vacuum_cost_delay + can be set to fractional-millisecond values, such delays may not be + measured accurately on older platforms. On such platforms, + increasing VACUUM's throttled resource consumption + above what you get at 1ms will require changing the other vacuum cost + parameters. You should, nonetheless, + keep vacuum_cost_delay as small as your platform + will consistently measure; large delays are not helpful. + + + + + + vacuum_cost_page_hit (integer) + + vacuum_cost_page_hit configuration parameter + + + + + The estimated cost for vacuuming a buffer found in the shared + buffer cache. It represents the cost to lock the buffer pool, + lookup the shared hash table and scan the content of the page. + The default value is 1. + + + + + + vacuum_cost_page_miss (integer) + + vacuum_cost_page_miss configuration parameter + + + + + The estimated cost for vacuuming a buffer that has to be read from + disk. This represents the effort to lock the buffer pool, + lookup the shared hash table, read the desired block in from + the disk and scan its content. The default value is + 2. + + + + + + vacuum_cost_page_dirty (integer) + + vacuum_cost_page_dirty configuration parameter + + + + + The estimated cost charged when vacuum modifies a block that was + previously clean. It represents the extra I/O required to + flush the dirty block out to disk again. The default value is + 20. + + + + + + vacuum_cost_limit (integer) + + vacuum_cost_limit configuration parameter + + + + + This is the accumulated cost that will cause the vacuuming + process to sleep for vacuum_cost_delay. The + default is 200. + + + + + + + + There are certain operations that hold critical locks and should + therefore complete as quickly as possible. Cost-based vacuum + delays do not occur during such operations. Therefore it is + possible that the cost accumulates far higher than the specified + limit. To avoid uselessly long delays in such cases, the actual + delay is calculated as vacuum_cost_delay * + accumulated_balance / + vacuum_cost_limit with a maximum of + vacuum_cost_delay * 4. + + + + + + Default Behavior + + + + vacuum_truncate (boolean) + + vacuum_truncate configuration parameter + + + + + Enables or disables vacuum to try to truncate off any empty pages at + the end of the table. The default value is true. + If true, VACUUM and autovacuum + do the truncation and the disk space for the truncated pages is + returned to the operating system. Note that the truncation requires + an ACCESS EXCLUSIVE lock on the table. The + TRUNCATE parameter of + VACUUM, if + specified, overrides the value of this parameter. The setting can + also be overridden for individual tables by changing table storage + parameters. + + + + + + + + Freezing + + + To maintain correctness even after transaction IDs wrap around, + PostgreSQL marks rows that are sufficiently + old as frozen. These rows are visible to everyone; + other transactions do not need to examine their inserting XID to + determine visibility. VACUUM is responsible for + marking rows as frozen. The following settings control + VACUUM's freezing behavior and should be tuned based + on the XID consumption rate of the system and data access patterns of the + dominant workloads. See for more + information on transaction ID wraparound and tuning these parameters. + + + + + vacuum_freeze_table_age (integer) + + vacuum_freeze_table_age configuration parameter + + + + + VACUUM performs an aggressive scan if the table's + pg_class.relfrozenxid field has reached + the age specified by this setting. An aggressive scan differs from + a regular VACUUM in that it visits every page that might + contain unfrozen XIDs or MXIDs, not just those that might contain dead + tuples. The default is 150 million transactions. Although users can + set this value anywhere from zero to two billion, VACUUM + will silently limit the effective value to 95% of + , so that a + periodic manual VACUUM has a chance to run before an + anti-wraparound autovacuum is launched for the table. For more + information see + . + + + + + + vacuum_freeze_min_age (integer) + + vacuum_freeze_min_age configuration parameter + + + + + Specifies the cutoff age (in transactions) that + VACUUM should use to decide whether to + trigger freezing of pages that have an older XID. + The default is 50 million transactions. Although + users can set this value anywhere from zero to one billion, + VACUUM will silently limit the effective value to half + the value of , so + that there is not an unreasonably short time between forced + autovacuums. For more information see . + + + - - autovacuum_vacuum_insert_scale_factor (floating point) - - autovacuum_vacuum_insert_scale_factor - configuration parameter - - - - - Specifies a fraction of the table size to add to - autovacuum_vacuum_insert_threshold - when deciding whether to trigger a VACUUM. - The default is 0.2 (20% of table size). - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + vacuum_failsafe_age (integer) + + vacuum_failsafe_age configuration parameter + + + + + Specifies the maximum age (in transactions) that a table's + pg_class.relfrozenxid + field can attain before VACUUM takes + extraordinary measures to avoid system-wide transaction ID + wraparound failure. This is VACUUM's + strategy of last resort. The failsafe typically triggers + when an autovacuum to prevent transaction ID wraparound has + already been running for some time, though it's possible for + the failsafe to trigger during any VACUUM. + + + When the failsafe is triggered, any cost-based delay that is + in effect will no longer be applied, further non-essential + maintenance tasks (such as index vacuuming) are bypassed, and any + Buffer Access Strategy + in use will be disabled resulting in VACUUM being + free to make use of all of + shared buffers. + + + The default is 1.6 billion transactions. Although users can + set this value anywhere from zero to 2.1 billion, + VACUUM will silently adjust the effective + value to no less than 105% of . + + + - - autovacuum_analyze_scale_factor (floating point) - - autovacuum_analyze_scale_factor - configuration parameter - - - - - Specifies a fraction of the table size to add to - autovacuum_analyze_threshold - when deciding whether to trigger an ANALYZE. - The default is 0.1 (10% of table size). - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. - - - + + vacuum_multixact_freeze_table_age (integer) + + vacuum_multixact_freeze_table_age configuration parameter + + + + + VACUUM performs an aggressive scan if the table's + pg_class.relminmxid field has reached + the age specified by this setting. An aggressive scan differs from + a regular VACUUM in that it visits every page that might + contain unfrozen XIDs or MXIDs, not just those that might contain dead + tuples. The default is 150 million multixacts. + Although users can set this value anywhere from zero to two billion, + VACUUM will silently limit the effective value to 95% of + , so that a + periodic manual VACUUM has a chance to run before an + anti-wraparound is launched for the table. + For more information see . + + + - - autovacuum_freeze_max_age (integer) - - autovacuum_freeze_max_age - configuration parameter - - - - - Specifies the maximum age (in transactions) that a table's - pg_class.relfrozenxid field can - attain before a VACUUM operation is forced - to prevent transaction ID wraparound within the table. - Note that the system will launch autovacuum processes to - prevent wraparound even when autovacuum is otherwise disabled. - + + vacuum_multixact_freeze_min_age (integer) + + vacuum_multixact_freeze_min_age configuration parameter + + + + + Specifies the cutoff age (in multixacts) that VACUUM + should use to decide whether to trigger freezing of pages with + an older multixact ID. The default is 5 million multixacts. + Although users can set this value anywhere from zero to one billion, + VACUUM will silently limit the effective value to half + the value of , + so that there is not an unreasonably short time between forced + autovacuums. + For more information see . + + + - - Vacuum also allows removal of old files from the - pg_xact subdirectory, which is why the default - is a relatively low 200 million transactions. - This parameter can only be set at server start, but the setting - can be reduced for individual tables by - changing table storage parameters. - For more information see . - - - + + vacuum_multixact_failsafe_age (integer) + + vacuum_multixact_failsafe_age configuration parameter + + + + + Specifies the maximum age (in multixacts) that a table's + pg_class.relminmxid + field can attain before VACUUM takes + extraordinary measures to avoid system-wide multixact ID + wraparound failure. This is VACUUM's + strategy of last resort. The failsafe typically triggers when + an autovacuum to prevent transaction ID wraparound has already + been running for some time, though it's possible for the + failsafe to trigger during any VACUUM. + + + When the failsafe is triggered, any cost-based delay that is + in effect will no longer be applied, and further non-essential + maintenance tasks (such as index vacuuming) are bypassed. + + + The default is 1.6 billion multixacts. Although users can set + this value anywhere from zero to 2.1 billion, + VACUUM will silently adjust the effective + value to no less than 105% of . + + + - - autovacuum_multixact_freeze_max_age (integer) + + vacuum_max_eager_freeze_failure_rate (floating point) - autovacuum_multixact_freeze_max_age - configuration parameter + vacuum_max_eager_freeze_failure_rate configuration parameter - Specifies the maximum age (in multixacts) that a table's - pg_class.relminmxid field can - attain before a VACUUM operation is forced to - prevent multixact ID wraparound within the table. - Note that the system will launch autovacuum processes to - prevent wraparound even when autovacuum is otherwise disabled. - - - - Vacuuming multixacts also allows removal of old files from the - pg_multixact/members and pg_multixact/offsets - subdirectories, which is why the default is a relatively low - 400 million multixacts. - This parameter can only be set at server start, but the setting can - be reduced for individual tables by changing table storage parameters. - For more information see . + Specifies the maximum number of pages (as a fraction of total pages in + the relation) that VACUUM may scan and + fail to set all-frozen in the visibility map + before disabling eager scanning. A value of 0 + disables eager scanning altogether. The default is + 0.03 (3%). - - - - autovacuum_vacuum_cost_delay (floating point) - - autovacuum_vacuum_cost_delay - configuration parameter - - - - Specifies the cost delay value that will be used in automatic - VACUUM operations. If -1 is specified, the regular - value will be used. - If this value is specified without units, it is taken as milliseconds. - The default value is 2 milliseconds. - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. + Note that when eager scanning is enabled, only freeze failures + count against the cap, not successful freezing. Successful page + freezes are capped internally at 20% of the all-visible but not + all-frozen pages in the relation. Capping successful page freezes helps + amortize the overhead across multiple normal vacuums and limits the + potential downside of wasted eager freezes of pages that are modified + again before the next aggressive vacuum. - - - - autovacuum_vacuum_cost_limit (integer) - - autovacuum_vacuum_cost_limit - configuration parameter - - - - Specifies the cost limit value that will be used in automatic - VACUUM operations. If -1 is specified (which is the - default), the regular - value will be used. Note that - the value is distributed proportionally among the running autovacuum - workers, if there is more than one, so that the sum of the limits for - each worker does not exceed the value of this variable. - This parameter can only be set in the postgresql.conf - file or on the server command line; - but the setting can be overridden for individual tables by - changing table storage parameters. + This parameter can only be set in the + postgresql.conf file or on the server command + line; but the setting can be overridden for individual tables by + changing the + + corresponding table storage parameter. + For more information on tuning vacuum's freezing behavior, + see . - + + @@ -9376,7 +10140,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; If transaction_timeout is shorter or equal to idle_in_transaction_session_timeout or statement_timeout - then the longer timeout is ignored. + then the longer timeout is ignored. @@ -9488,168 +10252,6 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; - - vacuum_freeze_table_age (integer) - - vacuum_freeze_table_age configuration parameter - - - - - VACUUM performs an aggressive scan if the table's - pg_class.relfrozenxid field has reached - the age specified by this setting. An aggressive scan differs from - a regular VACUUM in that it visits every page that might - contain unfrozen XIDs or MXIDs, not just those that might contain dead - tuples. The default is 150 million transactions. Although users can - set this value anywhere from zero to two billion, VACUUM - will silently limit the effective value to 95% of - , so that a - periodic manual VACUUM has a chance to run before an - anti-wraparound autovacuum is launched for the table. For more - information see - . - - - - - - vacuum_freeze_min_age (integer) - - vacuum_freeze_min_age configuration parameter - - - - - Specifies the cutoff age (in transactions) that - VACUUM should use to decide whether to - trigger freezing of pages that have an older XID. - The default is 50 million transactions. Although - users can set this value anywhere from zero to one billion, - VACUUM will silently limit the effective value to half - the value of , so - that there is not an unreasonably short time between forced - autovacuums. For more information see . - - - - - - vacuum_failsafe_age (integer) - - vacuum_failsafe_age configuration parameter - - - - - Specifies the maximum age (in transactions) that a table's - pg_class.relfrozenxid - field can attain before VACUUM takes - extraordinary measures to avoid system-wide transaction ID - wraparound failure. This is VACUUM's - strategy of last resort. The failsafe typically triggers - when an autovacuum to prevent transaction ID wraparound has - already been running for some time, though it's possible for - the failsafe to trigger during any VACUUM. - - - When the failsafe is triggered, any cost-based delay that is - in effect will no longer be applied, further non-essential - maintenance tasks (such as index vacuuming) are bypassed, and any - Buffer Access Strategy - in use will be disabled resulting in VACUUM being - free to make use of all of - shared buffers. - - - The default is 1.6 billion transactions. Although users can - set this value anywhere from zero to 2.1 billion, - VACUUM will silently adjust the effective - value to no less than 105% of . - - - - - - vacuum_multixact_freeze_table_age (integer) - - vacuum_multixact_freeze_table_age configuration parameter - - - - - VACUUM performs an aggressive scan if the table's - pg_class.relminmxid field has reached - the age specified by this setting. An aggressive scan differs from - a regular VACUUM in that it visits every page that might - contain unfrozen XIDs or MXIDs, not just those that might contain dead - tuples. The default is 150 million multixacts. - Although users can set this value anywhere from zero to two billion, - VACUUM will silently limit the effective value to 95% of - , so that a - periodic manual VACUUM has a chance to run before an - anti-wraparound is launched for the table. - For more information see . - - - - - - vacuum_multixact_freeze_min_age (integer) - - vacuum_multixact_freeze_min_age configuration parameter - - - - - Specifies the cutoff age (in multixacts) that VACUUM - should use to decide whether to trigger freezing of pages with - an older multixact ID. The default is 5 million multixacts. - Although users can set this value anywhere from zero to one billion, - VACUUM will silently limit the effective value to half - the value of , - so that there is not an unreasonably short time between forced - autovacuums. - For more information see . - - - - - - vacuum_multixact_failsafe_age (integer) - - vacuum_multixact_failsafe_age configuration parameter - - - - - Specifies the maximum age (in multixacts) that a table's - pg_class.relminmxid - field can attain before VACUUM takes - extraordinary measures to avoid system-wide multixact ID - wraparound failure. This is VACUUM's - strategy of last resort. The failsafe typically triggers when - an autovacuum to prevent transaction ID wraparound has already - been running for some time, though it's possible for the - failsafe to trigger during any VACUUM. - - - When the failsafe is triggered, any cost-based delay that is - in effect will no longer be applied, and further non-essential - maintenance tasks (such as index vacuuming) are bypassed. - - - The default is 1.6 billion multixacts. Although users can set - this value anywhere from zero to 2.1 billion, - VACUUM will silently adjust the effective - value to no less than 105% of . - - - - bytea_output (enum) @@ -9805,6 +10407,23 @@ SET XML OPTION { DOCUMENT | CONTENT }; + + restrict_nonsystem_relation_kind (string) + + restrict_nonsystem_relation_kind + configuration parameter + + + + + Set relation kinds for which access to non-system relations is prohibited. + The value takes the form of a comma-separated list of relation kinds. + Currently, the supported relation kinds are view and + foreign-table. + + + + @@ -9898,8 +10517,10 @@ SET XML OPTION { DOCUMENT | CONTENT }; - Sets the collection of time zone abbreviations that will be accepted - by the server for datetime input. The default is 'Default', + Sets the collection of additional time zone abbreviations that + will be accepted by the server for datetime input (beyond any + abbreviations defined by the current TimeZone + setting). The default is 'Default', which is a collection that works in most of the world; there are also 'Australia' and 'India', and other collections can be defined for a particular installation. @@ -10383,6 +11004,75 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + extension_control_path (string) + + extension_control_path configuration parameter + + + + + A path to search for extensions, specifically extension control files + (name.control). The + remaining extension script and secondary control files are then loaded + from the same directory where the primary control file was found. + See for details. + + + + The value for extension_control_path must be a + list of absolute directory paths separated by colons (or semi-colons + on Windows). If a list element starts + with the special string $system, the + compiled-in PostgreSQL extension + directory is substituted for $system; this + is where the extensions provided by the standard + PostgreSQL distribution are installed. + (Use pg_config --sharedir to find out the name of + this directory.) For example: + +extension_control_path = '/usr/local/share/postgresql:/home/my_project/share:$system' + + or, in a Windows environment: + +extension_control_path = 'C:\tools\postgresql;H:\my_project\share;$system' + + Note that the specified paths elements are expected to have a + subdirectory extension which will contain the + .control and .sql files; the + extension suffix is automatically appended to + each path element. + + + + The default value for this parameter is + '$system'. If the value is set to an empty + string, the default '$system' is also assumed. + + + + This parameter can be changed at run time by superusers and users + with the appropriate SET privilege, but a + setting done that way will only persist until the end of the + client connection, so this method should be reserved for + development purposes. The recommended way to set this parameter + is in the postgresql.conf configuration + file. + + + + Note that if you set this parameter to be able to load extensions from + nonstandard locations, you will most likely also need to set to a correspondent location, for + example, + +extension_control_path = '/usr/local/share/postgresql:$system' +dynamic_library_path = '/usr/local/lib/postgresql:$libdir' + + + + + gin_fuzzy_search_limit (integer) @@ -10817,7 +11507,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' Turning this setting off is intended for environments where the configuration of PostgreSQL is managed by some external tool. - In such environments, a well intentioned superuser might + In such environments, a well-intentioned superuser might mistakenly use ALTER SYSTEM to change the configuration instead of using the external tool. This might result in unintended behavior, such as the external tool @@ -11021,7 +11711,9 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' had at server startup. (On Microsoft Windows this parameter will always display 0700.) See - for more information. + the + initdb option + for more information. @@ -11417,6 +12109,29 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + debug_copy_parse_plan_trees (boolean) + + debug_copy_parse_plan_trees configuration parameter + + + + + Enabling this forces all parse and plan trees to be passed through + copyObject(), to facilitate catching errors and + omissions in copyObject(). The default is off. + + + + This parameter is only available when + DEBUG_NODE_TESTS_ENABLED was defined at compile time + (which happens automatically when using the + configure option + ). + + + + debug_discard_caches (integer) @@ -11532,6 +12247,54 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + debug_raw_expression_coverage_test (boolean) + + debug_raw_expression_coverage_test configuration parameter + + + + + Enabling this forces all raw parse trees for DML statements to be + scanned by raw_expression_tree_walker(), to + facilitate catching errors and omissions in that function. The + default is off. + + + + This parameter is only available when + DEBUG_NODE_TESTS_ENABLED was defined at compile time + (which happens automatically when using the + configure option + ). + + + + + + debug_write_read_parse_plan_trees (boolean) + + debug_write_read_parse_plan_trees configuration parameter + + + + + Enabling this forces all parse and plan trees to be passed through + outfuncs.c/readfuncs.c, to + facilitate catching errors and omissions in those modules. The + default is off. + + + + This parameter is only available when + DEBUG_NODE_TESTS_ENABLED was defined at compile time + (which happens automatically when using the + configure option + ). + + + + ignore_system_indexes (boolean) @@ -11615,9 +12378,6 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' If on, emit information about resource usage during sort operations. - This parameter is only available if the TRACE_SORT macro - was defined when PostgreSQL was compiled. - (However, TRACE_SORT is currently defined by default.) diff --git a/doc/src/sgml/contrib-spi.sgml b/doc/src/sgml/contrib-spi.sgml index e7cae4e38dcce..6fa9479d1b992 100644 --- a/doc/src/sgml/contrib-spi.sgml +++ b/doc/src/sgml/contrib-spi.sgml @@ -36,7 +36,7 @@ check_primary_key() checks the referencing table. - To use, create a BEFORE INSERT OR UPDATE trigger using this + To use, create an AFTER INSERT OR UPDATE trigger using this function on a table referencing another table. Specify as the trigger arguments: the referencing table's column name(s) which form the foreign key, the referenced table name, and the column names in the referenced table @@ -46,7 +46,7 @@ check_foreign_key() checks the referenced table. - To use, create a BEFORE DELETE OR UPDATE trigger using this + To use, create an AFTER DELETE OR UPDATE trigger using this function on a table referenced by other table(s). Specify as the trigger arguments: the number of referencing tables for which the function has to perform checking, the action if a referencing key is found @@ -60,6 +60,16 @@ unique index. + + Note that if these triggers are executed from + another BEFORE trigger, they can fail unexpectedly. For + example, if a user inserts row1 and then the BEFORE + trigger inserts row2 and calls a trigger with the + check_foreign_key(), + the check_foreign_key() + function will not see row1 and will fail. + + There are examples in refint.example. @@ -71,10 +81,12 @@ autoinc() is a trigger that stores the next value of a sequence into an integer field. This has some overlap with the - built-in serial column feature, but it is not the same: - autoinc() will override attempts to substitute a - different field value during inserts, and optionally it can be - used to increment the field during updates, too. + built-in serial column feature, but it is not the same. + The trigger will replace the field's value only if that value is + initially zero or null (after the action of the SQL statement that + inserted or updated the row). Also, if the sequence's next value is + zero, nextval() will be called a second time in + order to obtain a non-zero value. diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index 44639a8dcab90..24b706b29adc3 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -154,6 +154,8 @@ CREATE EXTENSION extension_name; &pgbuffercache; &pgcrypto; &pgfreespacemap; + &pglogicalinspect; + &pgoverexplain; &pgprewarm; &pgrowlocks; &pgstatstatements; diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index e0d33f12e1c50..09309ba0390b7 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -2245,24 +2245,27 @@ TIMESTAMP '2004-10-19 10:23:54+02' TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02' + - In a literal that has been determined to be timestamp without time + + In a value that has been determined to be timestamp without time zone, PostgreSQL will silently ignore any time zone indication. That is, the resulting value is derived from the date/time - fields in the input value, and is not adjusted for time zone. + fields in the input string, and is not adjusted for time zone. - For timestamp with time zone, the internally stored - value is always in UTC (Universal - Coordinated Time, traditionally known as Greenwich Mean Time, - GMT). An input value that has an explicit - time zone specified is converted to UTC using the appropriate offset + For timestamp with time zone values, an input string + that includes an explicit time zone will be converted to UTC + (Universal Coordinated + Time) using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's parameter, and is converted to UTC using the offset for the timezone zone. + In either case, the value is stored internally as UTC, and the + originally stated or assumed time zone is not retained. @@ -2534,6 +2537,10 @@ TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02' abbreviation if one is in common use in the current zone. Otherwise it appears as a signed numeric offset in ISO 8601 basic format (hh or hhmm). + The alphabetic abbreviations shown in these styles are taken from the + IANA time zone database entry currently selected by the + run-time parameter; they are not + affected by the setting. @@ -2675,6 +2682,14 @@ TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02' savings was nominally in effect on that date. + + + The sign in POSIX-style time zone specifications has the opposite meaning + of the sign in ISO-8601 datetime values. For example, the POSIX time zone + for 2014-06-04 12:00+04 would be UTC-4. + + + To complicate matters, some jurisdictions have used the same timezone abbreviation to mean different UTC offsets at different times; for @@ -4380,7 +4395,7 @@ SELECT to_tsvector( 'postgraduate' ), to_tsquery( 'postgres:*' ); The data type uuid stores Universally Unique Identifiers - (UUID) as defined by RFC 4122, + (UUID) as defined by RFC 9562, ISO/IEC 9834-8:2005, and related standards. (Some systems refer to this data type as a globally unique identifier, or GUID,GUID instead.) This @@ -4392,6 +4407,15 @@ SELECT to_tsvector( 'postgraduate' ), to_tsquery( 'postgres:*' ); are only unique within a single database. + + RFC 9562 defines 8 different UUID versions. Each version has specific requirements + for generating new UUID values, and each version provides distinct benefits and drawbacks. + PostgreSQL provides native support for generating UUIDs + using the UUIDv4 and UUIDv7 algorithms. Alternatively, UUID values can be generated + outside of the database using any algorithm. The data type uuid can be used + to store any UUID, regardless of the origin and the UUID version. + + A UUID is written as a sequence of lower-case hexadecimal digits, in several groups separated by hyphens, specifically a group of 8 diff --git a/doc/src/sgml/datetime.sgml b/doc/src/sgml/datetime.sgml index e7035c7806538..3e24170acbfcc 100644 --- a/doc/src/sgml/datetime.sgml +++ b/doc/src/sgml/datetime.sgml @@ -80,7 +80,7 @@ See if the token matches any known time zone abbreviation. - These abbreviations are supplied by the configuration file + These abbreviations are determined by the configuration settings described in . @@ -424,9 +424,43 @@ Since timezone abbreviations are not well standardized, PostgreSQL provides a means to customize - the set of abbreviations accepted by the server. The - run-time parameter - determines the active set of abbreviations. While this parameter + the set of abbreviations accepted in datetime input. + There are two sources for these abbreviations: + + + + + The run-time parameter is usually + set to the name of an entry in the IANA time zone database. + If that zone has widely-used zone abbreviations, they will appear + in the IANA data, and PostgreSQL will + preferentially recognize those abbreviations with the meanings + given in the IANA data. + For example, if timezone is set + to America/New_York then EST + will be understood as UTC-5 and EDT will be + understood as UTC-4. (These IANA abbreviations will also be used + in datetime output, if is set to a + style that prefers non-numeric zone abbreviations.) + + + + + + If an abbreviation is not found in the current IANA time zone, + it is sought in the list specified by the + run-time parameter. + The timezone_abbreviations list is primarily + useful for allowing datetime input to recognize abbreviations for + time zones other than the current zone. (These abbreviations will + not be used in datetime output.) + + + + + + + While the timezone_abbreviations parameter can be altered by any database user, the possible values for it are under the control of the database administrator — they are in fact names of configuration files stored in diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml index 81f35986c8820..808c690985b73 100644 --- a/doc/src/sgml/dblink.sgml +++ b/doc/src/sgml/dblink.sgml @@ -150,9 +150,23 @@ dblink_connect(text connname, text connstr) returns text executing arbitrary SQL commands. + + The foreign-data wrapper dblink_fdw has an additional + Boolean option use_scram_passthrough that controls + whether dblink will use the SCRAM pass-through + authentication to connect to the remote database. With SCRAM pass-through + authentication, dblink uses SCRAM-hashed secrets + instead of plain-text user passwords to connect to the remote server. This + avoids storing plain-text user passwords in PostgreSQL system catalogs. + See the documentation of the equivalent use_scram_passthrough + option of postgres_fdw for further details and restrictions. + + Only superusers may use dblink_connect to create - non-password-authenticated and non-GSSAPI-authenticated connections. + connections that use neither password authentication, SCRAM pass-through, + nor GSSAPI-authentication. If non-superusers need this capability, use dblink_connect_u instead. @@ -181,8 +195,9 @@ SELECT dblink_connect('myconn', 'dbname=postgres options=-csearch_path='); (1 row) -- FOREIGN DATA WRAPPER functionality --- Note: local connection must require password authentication for this to work properly --- Otherwise, you will receive the following error from dblink_connect(): +-- Note: local connections that don't use SCRAM pass-through require password +-- authentication for this to work properly. Otherwise, you will receive +-- the following error from dblink_connect(): -- ERROR: password is required -- DETAIL: Non-superuser cannot connect if the server does not request a password. -- HINT: Target server's authentication method must be changed. diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 626d35514cc39..96936bcd3ae3e 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -271,8 +271,8 @@ CREATE TABLE people ( example, with the above definitions and assuming additional appropriate columns, writing -INSERT INTO people (name, address) VALUE ('A', 'foo'); -INSERT INTO people (name, address) VALUE ('B', 'bar'); +INSERT INTO people (name, address) VALUES ('A', 'foo'); +INSERT INTO people (name, address) VALUES ('B', 'bar'); would generate values for the id column starting at 1 and result in the following table data: @@ -285,7 +285,7 @@ INSERT INTO people (name, address) VALUE ('B', 'bar'); Alternatively, the keyword DEFAULT can be specified in place of a value to explicitly request the sequence-generated value, like -INSERT INTO people (id, name, address) VALUE (DEFAULT, 'C', 'baz'); +INSERT INTO people (id, name, address) VALUES (DEFAULT, 'C', 'baz'); Similarly, the keyword DEFAULT can be used in UPDATE commands. @@ -361,7 +361,6 @@ INSERT INTO people (id, name, address) VALUE (DEFAULT, 'C', storage and is computed when it is read. Thus, a virtual generated column is similar to a view and a stored generated column is similar to a materialized view (except that it is always updated automatically). - PostgreSQL currently implements only stored generated columns. @@ -371,12 +370,12 @@ INSERT INTO people (id, name, address) VALUE (DEFAULT, 'C', CREATE TABLE people ( ..., height_cm numeric, - height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) STORED + height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) ); - The keyword STORED must be specified to choose the - stored kind of generated column. See for - more details. + A generated column is by default of the virtual kind. Use the keywords + VIRTUAL or STORED to make the choice + explicit. See for more details. @@ -442,12 +441,18 @@ CREATE TABLE people ( If a parent column is a generated column, its child column must also - be a generated column; however, the child column can have a - different generation expression. The generation expression that is + be a generated column of the same kind (stored or virtual); however, + the child column can have a different generation expression. + + + + For stored generated columns, the generation expression that is actually applied during insert or update of a row is the one - associated with the table that the row is physically in. - (This is unlike the behavior for column defaults: for those, the - default value associated with the table named in the query applies.) + associated with the table that the row is physically in. (This is + unlike the behavior for column defaults: for those, the default value + associated with the table named in the query applies.) For virtual + generated columns, the generation expression of the table named in the + query applies when a table is read. @@ -502,6 +507,26 @@ CREATE TABLE people ( particular role can read from a generated column but not from the underlying base columns. + + + For virtual generated columns, this is only fully secure if the + generation expression uses only leakproof functions (see ), but this is not enforced by the system. + + + + + Privileges of functions used in generation expressions are checked when + the expression is actually executed, on write or read respectively, as + if the generation expression had been called directly from the query + using the generated column. The user of a generated column must have + permissions to call all functions used by the generation expression. + Functions in the generation expression are executed with the privileges + of the user executing the query or the function owner, depending on + whether the functions are defined as SECURITY INVOKER + or SECURITY DEFINER. + + @@ -514,8 +539,13 @@ CREATE TABLE people ( - Generated columns are skipped for logical replication and cannot be - specified in a CREATE PUBLICATION column list. + Generated columns are allowed to be replicated during logical replication + according to the CREATE PUBLICATION parameter + + publish_generated_columns or by including them + in the column list of the CREATE PUBLICATION command. + This is currently only supported for stored generated columns. + See for details. @@ -769,17 +799,38 @@ CREATE TABLE products ( price numeric ); + An explicit constraint name can also be specified, for example: + +CREATE TABLE products ( + product_no integer NOT NULL, + name text CONSTRAINT products_name_not_null NOT NULL, + price numeric +); + + + + + A not-null constraint is usually written as a column constraint. The + syntax for writing it as a table constraint is + +CREATE TABLE products ( + product_no integer, + name text, + price numeric, + NOT NULL product_no, + NOT NULL name +); + + But this syntax is not standard and mainly intended for use by + pg_dump. - A not-null constraint is always written as a column constraint. A - not-null constraint is functionally equivalent to creating a check + A not-null constraint is functionally equivalent to creating a check constraint CHECK (column_name IS NOT NULL), but in PostgreSQL creating an explicit - not-null constraint is more efficient. The drawback is that you - cannot give explicit names to not-null constraints created this - way. + not-null constraint is more efficient. @@ -796,6 +847,10 @@ CREATE TABLE products ( order the constraints are checked. + + However, a column can have at most one explicit not-null constraint. + + The NOT NULL constraint has an inverse: the NULL constraint. This does not mean that the @@ -989,7 +1044,7 @@ CREATE TABLE example ( A table can have at most one primary key. (There can be any number - of unique and not-null constraints, which are functionally almost the + of unique constraints, which combined with not-null constraints are functionally almost the same thing, but only one can be identified as the primary key.) Relational database theory dictates that every table must have a primary key. This rule is @@ -1205,16 +1260,32 @@ CREATE TABLE order_items ( - Restricting and cascading deletes are the two most common options. - RESTRICT prevents deletion of a - referenced row. NO ACTION means that if any - referencing rows still exist when the constraint is checked, an error - is raised; this is the default behavior if you do not specify anything. - (The essential difference between these two choices is that - NO ACTION allows the check to be deferred until - later in the transaction, whereas RESTRICT does not.) + The default ON DELETE action is ON DELETE NO + ACTION; this does not need to be specified. This means that the + deletion in the referenced table is allowed to proceed. But the + foreign-key constraint is still required to be satisfied, so this + operation will usually result in an error. But checking of foreign-key + constraints can also be deferred to later in the transaction (not covered + in this chapter). In that case, the NO ACTION setting + would allow other commands to fix the situation before the + constraint is checked, for example by inserting another suitable row into + the referenced table or by deleting the now-dangling rows from the + referencing table. + + + + RESTRICT is a stricter setting than NO + ACTION. It prevents deletion of a referenced row. + RESTRICT does not allow the check to be deferred until + later in the transaction. + + + CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well. + + + There are two other options: SET NULL and SET DEFAULT. These cause the referencing column(s) in the referencing row(s) @@ -1284,6 +1355,15 @@ CREATE TABLE posts ( NULL and SET DEFAULT. In this case, CASCADE means that the updated values of the referenced column(s) should be copied into the referencing row(s). + There is also a noticeable difference between ON UPDATE NO + ACTION (the default) and ON UPDATE RESTRICT. + The former will allow the update to proceed and the foreign-key constraint + will be checked against the state after the update. The latter will + prevent the update to run even if the state after the update would still + satisfy the constraint. This prevents updating a referenced row to a + value that is distinct but compares as equal (for example, a character + string with a different case variant, if a character string type with a + case-insensitive collation is used). @@ -1570,17 +1650,15 @@ ALTER TABLE products ADD COLUMN description text; - From PostgreSQL 11, adding a column with - a constant default value no longer means that each row of the table - needs to be updated when the ALTER TABLE statement + Adding a column with a constant default value does not require each row of + the table to be updated when the ALTER TABLE statement is executed. Instead, the default value will be returned the next time the row is accessed, and applied when the table is rewritten, making the ALTER TABLE very fast even on large tables. - However, if the default value is volatile (e.g., - clock_timestamp()) + If the default value is volatile (e.g., clock_timestamp()) each row will need to be updated with the value calculated at the time ALTER TABLE is executed. To avoid a potentially lengthy update operation, particularly if you intend to fill the column @@ -1649,11 +1727,16 @@ ALTER TABLE products ADD CHECK (name <> ''); ALTER TABLE products ADD CONSTRAINT some_name UNIQUE (product_no); ALTER TABLE products ADD FOREIGN KEY (product_group_id) REFERENCES product_groups; - To add a not-null constraint, which cannot be written as a table - constraint, use this syntax: + + + + To add a not-null constraint, which is normally not written as a table + constraint, this special syntax is available: ALTER TABLE products ALTER COLUMN product_no SET NOT NULL; + This command silently does nothing if the column already has a + not-null constraint. @@ -1681,9 +1764,6 @@ ALTER TABLE products ALTER COLUMN product_no SET NOT NULL; ALTER TABLE products DROP CONSTRAINT some_name; - (If you are dealing with a generated constraint name like $2, - don't forget that you'll need to double-quote it to make it a valid - identifier.) @@ -1694,12 +1774,15 @@ ALTER TABLE products DROP CONSTRAINT some_name; - This works the same for all constraint types except not-null - constraints. To drop a not-null constraint use: + Simplified syntax is available to drop a not-null constraint: ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL; - (Recall that not-null constraints do not have names.) + This mirrors the SET NOT NULL syntax for adding a + not-null constraint. This command will silently do nothing if the column + does not have a not-null constraint. (Recall that a column can have at + most one not-null constraint, so it is never ambiguous which constraint + this command acts on.) @@ -2140,8 +2223,9 @@ REVOKE ALL ON accounts FROM PUBLIC; Allows VACUUM, ANALYZE, CLUSTER, REFRESH MATERIALIZED VIEW, - REINDEX, and LOCK TABLE on a - relation. + REINDEX, LOCK TABLE, + and database object statistics manipulation functions + (see ) on a relation. @@ -2592,7 +2676,8 @@ GRANT SELECT (col1), UPDATE (col1) ON mytable TO miriam_rw; When multiple policies apply to a given query, they are combined using either OR (for permissive policies, which are the default) or using AND (for restrictive policies). - This is similar to the rule that a given role has the privileges + The OR behavior is similar to the rule that a given + role has the privileges of all roles that they are a member of. Permissive vs. restrictive policies are discussed further below. @@ -3778,12 +3863,14 @@ VALUES ('Albany', NULL, NULL, 'NY'); not INSERT or ALTER TABLE ... RENAME) typically default to including child tables and support the ONLY notation to exclude them. - Commands that do database maintenance and tuning - (e.g., REINDEX, VACUUM) - typically only work on individual, physical tables and do not - support recursing over inheritance hierarchies. The respective - behavior of each individual command is documented in its reference - page (). + The majority of commands that do database maintenance and tuning + (e.g., REINDEX) only work on individual, physical + tables and do not support recursing over inheritance hierarchies. + However, both VACUUM and ANALYZE + commands default to including child tables and the ONLY + notation is supported to allow them to be excluded. The respective + behavior of each individual command is documented in its reference page + (). @@ -4355,44 +4442,6 @@ ALTER INDEX measurement_city_id_logdate_key ... - - - There is also an option for merging multiple table partitions into - a single partition using the - ALTER TABLE ... MERGE PARTITIONS. - This feature simplifies the management of partitioned tables by allowing - users to combine partitions that are no longer needed as - separate entities. It's important to note that this operation is not - supported for hash-partitioned tables and acquires an - ACCESS EXCLUSIVE lock, which could impact high-load - systems due to the lock's restrictive nature. For example, we can - merge three monthly partitions into one quarter partition: - -ALTER TABLE measurement - MERGE PARTITIONS (measurement_y2006m01, - measurement_y2006m02, - measurement_y2006m03) INTO measurement_y2006q1; - - - - - Similarly to merging multiple table partitions, there is an option for - splitting a single partition into multiple using the - ALTER TABLE ... SPLIT PARTITION. - This feature could come in handy when one partition grows too big - and needs to be split into multiple. It's important to note that - this operation is not supported for hash-partitioned tables and acquires - an ACCESS EXCLUSIVE lock, which could impact high-load - systems due to the lock's restrictive nature. For example, we can split - the quarter partition back to monthly partitions: - -ALTER TABLE measurement SPLIT PARTITION measurement_y2006q1 INTO - (PARTITION measurement_y2006m01 FOR VALUES FROM ('2006-01-01') TO ('2006-02-01'), - PARTITION measurement_y2006m02 FOR VALUES FROM ('2006-02-01') TO ('2006-03-01'), - PARTITION measurement_y2006m03 FOR VALUES FROM ('2006-03-01') TO ('2006-04-01')); - - - @@ -4479,12 +4528,10 @@ ALTER TABLE measurement SPLIT PARTITION measurement_y2006q1 INTO Both CHECK and NOT NULL constraints of a partitioned table are always inherited by all its - partitions. CHECK constraints that are marked - NO INHERIT are not allowed to be created on - partitioned tables. - You cannot drop a NOT NULL constraint on a - partition's column if the same constraint is present in the parent - table. + partitions; it is not allowed to create NO INHERIT + constraints of those types. + You cannot drop a constraint of those types if the same constraint + is present in the parent table. @@ -4892,11 +4939,12 @@ ALTER TABLE measurement_y2008m02 INHERIT measurement; - If you are using manual VACUUM or - ANALYZE commands, don't forget that - you need to run them on each child table individually. A command like: + Manual VACUUM and ANALYZE + commands will automatically process all inheritance child tables. If + this is undesirable, you can use the ONLY keyword. + A command like: -ANALYZE measurement; +ANALYZE ONLY measurement; will only process the root table. @@ -5025,7 +5073,13 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01'; It is possible to determine the number of partitions which were removed during this phase by observing the Subplans Removed property in the - EXPLAIN output. + EXPLAIN output. The query planner obtains locks for + all partitions which are part of the plan. However, when the executor + uses a cached plan, locks are only obtained on the partitions which + remain after partition pruning done during the initialization phase of + execution, i.e., the ones shown in the EXPLAIN + output and not the ones referred to by the + Subplans Removed property. diff --git a/doc/src/sgml/dml.sgml b/doc/src/sgml/dml.sgml index 3d95bdb94e79d..458aee788b7fb 100644 --- a/doc/src/sgml/dml.sgml +++ b/doc/src/sgml/dml.sgml @@ -308,7 +308,8 @@ DELETE FROM products; - In an INSERT, the data available to RETURNING is + In an INSERT, the default data available to + RETURNING is the row as it was inserted. This is not so useful in trivial inserts, since it would just repeat the data provided by the client. But it can be very handy when relying on computed default values. For example, @@ -325,7 +326,8 @@ INSERT INTO users (firstname, lastname) VALUES ('Joe', 'Cool') RETURNING id; - In an UPDATE, the data available to RETURNING is + In an UPDATE, the default data available to + RETURNING is the new content of the modified row. For example: UPDATE products SET price = price * 1.10 @@ -335,7 +337,8 @@ UPDATE products SET price = price * 1.10 - In a DELETE, the data available to RETURNING is + In a DELETE, the default data available to + RETURNING is the content of the deleted row. For example: DELETE FROM products @@ -345,7 +348,8 @@ DELETE FROM products - In a MERGE, the data available to RETURNING is + In a MERGE, the default data available to + RETURNING is the content of the source row plus the content of the inserted, updated, or deleted target row. Since it is quite common for the source and target to have many of the same columns, specifying RETURNING * @@ -359,6 +363,35 @@ MERGE INTO products p USING new_products n ON p.product_no = n.product_no + + In each of these commands, it is also possible to explicitly return the + old and new content of the modified row. For example: + +UPDATE products SET price = price * 1.10 + WHERE price <= 99.99 + RETURNING name, old.price AS old_price, new.price AS new_price, + new.price - old.price AS price_change; + + In this example, writing new.price is the same as + just writing price, but it makes the meaning clearer. + + + + This syntax for returning old and new values is available in + INSERT, UPDATE, + DELETE, and MERGE commands, but + typically old values will be NULL for an + INSERT, and new values will be NULL + for a DELETE. However, there are situations where it + can still be useful for those commands. For example, in an + INSERT with an + ON CONFLICT DO UPDATE + clause, the old values will be non-NULL for conflicting + rows. Similarly, if a DELETE is turned into an + UPDATE by a rewrite rule, + the new values may be non-NULL. + + If there are triggers () on the target table, the data available to RETURNING is the row as modified by diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml index 8e009cca050f2..1bd9abb667650 100644 --- a/doc/src/sgml/event-trigger.sgml +++ b/doc/src/sgml/event-trigger.sgml @@ -26,7 +26,7 @@ An event trigger fires whenever the event with which it is associated - occurs in the database in which it is defined. Currently, the only + occurs in the database in which it is defined. Currently, the supported events are login, ddl_command_start, @@ -36,6 +36,9 @@ Support for additional events may be added in future releases. + + login + The login event occurs when an authenticated user logs into the system. Any bug in a trigger procedure for this event may @@ -54,25 +57,62 @@ the in-progress login trigger. + + For an example on how to use the login event trigger, + see . + + + + + ddl_command_start + The ddl_command_start event occurs just before the - execution of a CREATE, ALTER, DROP, - SECURITY LABEL, - COMMENT, GRANT or REVOKE - command. No check whether the affected object exists or doesn't exist is - performed before the event trigger fires. - As an exception, however, this event does not occur for - DDL commands targeting shared objects — databases, roles, and tablespaces - — or for commands targeting event triggers themselves. The event trigger - mechanism does not support these object types. - ddl_command_start also occurs just before the execution of a - SELECT INTO command, since this is equivalent to - CREATE TABLE AS. + execution of a DDL command. DDL commands in this context are: + + CREATE + ALTER + DROP + COMMENT + GRANT + IMPORT FOREIGN SCHEMA + REINDEX + REFRESH MATERIALIZED VIEW + REVOKE + SECURITY LABEL + + ddl_command_start also occurs just before the + execution of a SELECT INTO command, since this is + equivalent to CREATE TABLE AS. + + As an exception, this event does not occur for DDL commands targeting + shared objects: + + databases + roles (role definitions and role memberships) + tablespaces + parameter privileges + ALTER SYSTEM + + This event also does not occur for commands targeting event triggers + themselves. + + + + No check whether the affected object exists or doesn't exist is performed + before the event trigger fires. + + + + + ddl_command_end + The ddl_command_end event occurs just after the execution of - this same set of commands. To obtain more details on the DDL + the same set of commands as ddl_command_start. To + obtain more details on the DDL operations that took place, use the set-returning function pg_event_trigger_ddl_commands() from the ddl_command_end event trigger code (see @@ -80,17 +120,31 @@ after the actions have taken place (but before the transaction commits), and thus the system catalogs can be read as already changed. + + + + sql_drop The sql_drop event occurs just before the ddl_command_end event trigger for any operation that drops - database objects. To list the objects that have been dropped, use the + database objects. Note that besides the obvious DROP + commands, some ALTER commands can also trigger an + sql_drop event. + + + + To list the objects that have been dropped, use the set-returning function pg_event_trigger_dropped_objects() from the sql_drop event trigger code (see ). Note that the trigger is executed after the objects have been deleted from the system catalogs, so it's not possible to look them up anymore. + + + + table_rewrite The table_rewrite event occurs just before a table is @@ -99,7 +153,16 @@ control statements are available to rewrite a table, like CLUSTER and VACUUM, the table_rewrite event is not triggered by them. + To find the OID of the table that was rewritten, use the function + pg_event_trigger_table_rewrite_oid(), to discover the + reason(s) for the rewrite, use the function + pg_event_trigger_table_rewrite_reason() (see ). + + + + Event Triggers in Aborted Transactions Event triggers (like other functions) cannot be executed in an aborted @@ -112,11 +175,10 @@ back, just as they would be in any other case where the containing transaction aborts. + - - For a complete list of commands supported by the event trigger mechanism, - see . - + + Creating Event Triggers Event triggers are created using the command . @@ -138,935 +200,7 @@ to intercept. A common use of such triggers is to restrict the range of DDL operations which users may perform. - - - - Event Trigger Firing Matrix - - - lists all commands - for which event triggers are supported. - - - - Event Trigger Support by Command Tag - - - - - - - - - - Command Tag - ddl_&zwsp;command_&zwsp;start - ddl_&zwsp;command_&zwsp;end - sql_&zwsp;drop - table_&zwsp;rewrite - Notes - - - - - ALTER AGGREGATE - X - X - - - - - - - - ALTER COLLATION - X - X - - - - - - - - ALTER CONVERSION - X - X - - - - - - - - ALTER DOMAIN - X - X - - - - - - - - ALTER DEFAULT PRIVILEGES - X - X - - - - - - - - ALTER EXTENSION - X - X - - - - - - - - ALTER FOREIGN DATA WRAPPER - X - X - - - - - - - - ALTER FOREIGN TABLE - X - X - X - - - - - - ALTER FUNCTION - X - X - - - - - - - - ALTER LANGUAGE - X - X - - - - - - - - ALTER LARGE OBJECT - X - X - - - - - - - - ALTER MATERIALIZED VIEW - X - X - - - X - - - - ALTER OPERATOR - X - X - - - - - - - - ALTER OPERATOR CLASS - X - X - - - - - - - - ALTER OPERATOR FAMILY - X - X - - - - - - - - ALTER POLICY - X - X - - - - - - - - ALTER PROCEDURE - X - X - - - - - - - - ALTER PUBLICATION - X - X - - - - - - - - ALTER ROUTINE - X - X - - - - - - - - ALTER SCHEMA - X - X - - - - - - - - ALTER SEQUENCE - X - X - - - - - - - - ALTER SERVER - X - X - - - - - - - - ALTER STATISTICS - X - X - - - - - - - - ALTER SUBSCRIPTION - X - X - - - - - - - - ALTER TABLE - X - X - X - X - - - - ALTER TEXT SEARCH CONFIGURATION - X - X - - - - - - - - ALTER TEXT SEARCH DICTIONARY - X - X - - - - - - - - ALTER TEXT SEARCH PARSER - X - X - - - - - - - - ALTER TEXT SEARCH TEMPLATE - X - X - - - - - - - - ALTER TRIGGER - X - X - - - - - - - - ALTER TYPE - X - X - - - X - - - - ALTER USER MAPPING - X - X - - - - - - - - ALTER VIEW - X - X - - - - - - - - COMMENT - X - X - - - - - Only for local objects - - - CREATE ACCESS METHOD - X - X - - - - - - - - CREATE AGGREGATE - X - X - - - - - - - - CREATE CAST - X - X - - - - - - - - CREATE COLLATION - X - X - - - - - - - - CREATE CONVERSION - X - X - - - - - - - - CREATE DOMAIN - X - X - - - - - - - - CREATE EXTENSION - X - X - - - - - - - - CREATE FOREIGN DATA WRAPPER - X - X - - - - - - - - CREATE FOREIGN TABLE - X - X - - - - - - - - CREATE FUNCTION - X - X - - - - - - - - CREATE INDEX - X - X - - - - - - - - CREATE LANGUAGE - X - X - - - - - - - - CREATE MATERIALIZED VIEW - X - X - - - - - - - - CREATE OPERATOR - X - X - - - - - - - - CREATE OPERATOR CLASS - X - X - - - - - - - - CREATE OPERATOR FAMILY - X - X - - - - - - - - CREATE POLICY - X - X - - - - - - - - CREATE PROCEDURE - X - X - - - - - - - - CREATE PUBLICATION - X - X - - - - - - - - CREATE RULE - X - X - - - - - - - - CREATE SCHEMA - X - X - - - - - - - - CREATE SEQUENCE - X - X - - - - - - - - CREATE SERVER - X - X - - - - - - - - CREATE STATISTICS - X - X - - - - - - - - CREATE SUBSCRIPTION - X - X - - - - - - - - CREATE TABLE - X - X - - - - - - - - CREATE TABLE AS - X - X - - - - - - - - CREATE TEXT SEARCH CONFIGURATION - X - X - - - - - - - - CREATE TEXT SEARCH DICTIONARY - X - X - - - - - - - - CREATE TEXT SEARCH PARSER - X - X - - - - - - - - CREATE TEXT SEARCH TEMPLATE - X - X - - - - - - - - CREATE TRIGGER - X - X - - - - - - - - CREATE TYPE - X - X - - - - - - - - CREATE USER MAPPING - X - X - - - - - - - - CREATE VIEW - X - X - - - - - - - - DROP ACCESS METHOD - X - X - X - - - - - - DROP AGGREGATE - X - X - X - - - - - - DROP CAST - X - X - X - - - - - - DROP COLLATION - X - X - X - - - - - - DROP CONVERSION - X - X - X - - - - - - DROP DOMAIN - X - X - X - - - - - - DROP EXTENSION - X - X - X - - - - - - DROP FOREIGN DATA WRAPPER - X - X - X - - - - - - DROP FOREIGN TABLE - X - X - X - - - - - - DROP FUNCTION - X - X - X - - - - - - DROP INDEX - X - X - X - - - - - - DROP LANGUAGE - X - X - X - - - - - - DROP MATERIALIZED VIEW - X - X - X - - - - - - DROP OPERATOR - X - X - X - - - - - - DROP OPERATOR CLASS - X - X - X - - - - - - DROP OPERATOR FAMILY - X - X - X - - - - - - DROP OWNED - X - X - X - - - - - - DROP POLICY - X - X - X - - - - - - DROP PROCEDURE - X - X - X - - - - - - DROP PUBLICATION - X - X - X - - - - - - DROP ROUTINE - X - X - X - - - - - - DROP RULE - X - X - X - - - - - - DROP SCHEMA - X - X - X - - - - - - DROP SEQUENCE - X - X - X - - - - - - DROP SERVER - X - X - X - - - - - - DROP STATISTICS - X - X - X - - - - - - DROP SUBSCRIPTION - X - X - X - - - - - - DROP TABLE - X - X - X - - - - - - DROP TEXT SEARCH CONFIGURATION - X - X - X - - - - - - DROP TEXT SEARCH DICTIONARY - X - X - X - - - - - - DROP TEXT SEARCH PARSER - X - X - X - - - - - - DROP TEXT SEARCH TEMPLATE - X - X - X - - - - - - DROP TRIGGER - X - X - X - - - - - - DROP TYPE - X - X - X - - - - - - DROP USER MAPPING - X - X - X - - - - - - DROP VIEW - X - X - X - - - - - - GRANT - X - X - - - - - Only for local objects - - - IMPORT FOREIGN SCHEMA - X - X - - - - - - - - REFRESH MATERIALIZED VIEW - X - X - - - - - - - - REINDEX - X - X - - - - - - - - REVOKE - X - X - - - - - Only for local objects - - - SECURITY LABEL - X - X - - - - - Only for local objects - - - SELECT INTO - X - X - - - - - - - - -
+
diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index 218940ee5ce19..63c5ec6d1eb99 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -649,6 +649,11 @@ RETURNS anycompatible AS ... control file can specify a different directory for the script file(s). + + Additional locations for extension control files can be configured using + the parameter . + + The file format for an extension control file is the same as for the postgresql.conf file, namely a list of @@ -669,9 +674,9 @@ RETURNS anycompatible AS ... The directory containing the extension's SQL script file(s). Unless an absolute path is given, the name is relative to - the installation's SHAREDIR directory. The - default behavior is equivalent to specifying - directory = 'extension'. + the directory where the control file was found. By default, + the script files are looked for in the same directory where the + control file was found. @@ -719,8 +724,8 @@ RETURNS anycompatible AS ... The value of this parameter will be substituted for each occurrence of MODULE_PATHNAME in the script file(s). If it is not - set, no substitution is made. Typically, this is set to - $libdir/shared_library_name and + set, no substitution is made. Typically, this is set to just + shared_library_name and then MODULE_PATHNAME is used in CREATE FUNCTION commands for C-language functions, so that the script files do not need to hard-wire the name of the shared library. @@ -1339,8 +1344,8 @@ SELECT * FROM pg_extension_update_paths('extension_namesearch_path; do not trust the path provided by CREATE/ALTER EXTENSION to be secure. Best practice is to temporarily - set search_path to 'pg_catalog, - pg_temp' and insert references to the extension's + set search_path to pg_catalog, + pg_temp and insert references to the extension's installation schema explicitly where needed. (This practice might also be helpful for creating views.) Examples can be found in the contrib modules in @@ -1348,15 +1353,11 @@ SELECT * FROM pg_extension_update_paths('extension_name - Cross-extension references are extremely difficult to make fully - secure, partially because of uncertainty about which schema the other - extension is in. The hazards are reduced if both extensions are - installed in the same schema, because then a hostile object cannot be - placed ahead of the referenced extension in the installation-time - search_path. However, no mechanism currently exists - to require that. For now, best practice is to not mark an extension - trusted if it depends on another one, unless that other one is always - installed in pg_catalog. + Secure cross-extension references typically require schema-qualification + of the names of the other extension's objects, using the + @extschema:name@ + syntax, in addition to careful matching of argument types for functions + and operators. @@ -1810,6 +1811,36 @@ include $(PGXS) or on the make command line. + + You can select a separate directory prefix in which to install your + extension's files, by setting the make variable + prefix when executing make install + like so: + +make install prefix=/usr/local/postgresql + + This will install the extension control and SQL files into + /usr/local/postgresql/share and the shared modules into + /usr/local/postgresql/lib. If the prefix does not + include the strings postgres or + pgsql, such as + +make install prefix=/usr/local/extras + + then postgresql will be appended to the directory + names, installing the control and SQL files into + /usr/local/extras/share/postgresql/extension and the + shared modules into /usr/local/extras/lib/postgresql. + Either way, you'll need to set and to enable the + PostgreSQL server to find the files: + +extension_control_path = '/usr/local/extras/share/postgresql:$system' +dynamic_library_path = '/usr/local/extras/lib/postgresql:$libdir' + + + You can also run make in a directory outside the source tree of your extension, if you want to keep the build directory separate. diff --git a/doc/src/sgml/file-fdw.sgml b/doc/src/sgml/file-fdw.sgml index f2f2af9a5962f..882d9a76d2169 100644 --- a/doc/src/sgml/file-fdw.sgml +++ b/doc/src/sgml/file-fdw.sgml @@ -126,6 +126,41 @@ + + on_error + + + + Specifies how to behave when encountering an error converting a column's + input value into its data type, + the same as COPY's ON_ERROR option. + + + + + + reject_limit + + + + Specifies the maximum number of errors tolerated while converting a column's + input value to its data type, the same as COPY's + REJECT_LIMIT option. + + + + + + log_verbosity + + + + Specifies the amount of messages emitted by file_fdw, + the same as COPY's LOG_VERBOSITY option. + + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index a7ff5f8264266..fef9584f908ec 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -111,6 +111,7 @@ + @@ -143,6 +144,8 @@ + + diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index b669ab7f97765..c67688cbf5f98 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1396,6 +1396,27 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in + + + + gamma + + gamma ( double precision ) + double precision + + + Gamma function + + + gamma(0.5) + 1.772453850905516 + + + gamma(6) + 120 + + + @@ -1436,6 +1457,23 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in + + + + lgamma + + lgamma ( double precision ) + double precision + + + Natural logarithm of the absolute value of the gamma function + + + lgamma(1000) + 5905.220423209181 + + + @@ -2596,7 +2634,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in - + lower lower ( text ) @@ -2657,7 +2695,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in - + normalize @@ -2910,7 +2948,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in unicode_assigned unicode_assigned ( text ) - text + boolean Returns true if all characters in the string are @@ -3036,7 +3074,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in concat concat ( val1 "any" - [, val2 "any" [, ...] ] ) + , val2 "any" , ... ) text @@ -3056,7 +3094,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in concat_ws ( sep text, val1 "any" - [, val2 "any" [, ...] ] ) + , val2 "any" , ... ) text @@ -3076,7 +3114,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in format format ( formatstr text - [, formatarg "any" [, ...] ] ) + , formatarg "any" , ... ) text @@ -3109,6 +3147,44 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in + + + + casefold + + casefold ( text ) + text + + + Performs case folding of the input string according to the collation. + Case folding is similar to case conversion, but the purpose of case + folding is to facilitate case-insensitive matching of strings, + whereas the purpose of case conversion is to convert to a particular + cased form. This function can only be used when the server encoding + is UTF8. + + + Ordinarily, case folding simply converts to lowercase, but there may + be exceptions depending on the collation. For instance, some + characters have more than two lowercase variants, or fold to uppercase. + + + Case folding may change the length of the string. For instance, in + the PG_UNICODE_FAST collation, ß + (U+00DF) folds to ss. + + + casefold can be used for Unicode Default Caseless + Matching. It does not always preserve the normalized form of the + input string (see ). + + + The libc provider doesn't support case folding, so + casefold is identical to . + + + @@ -3170,7 +3246,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in parse_ident parse_ident ( qualified_identifier text - [, strict_mode boolean DEFAULT true ] ) + , strict_mode boolean DEFAULT true ) text[] @@ -3309,8 +3385,8 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_count regexp_count ( string text, pattern text - [, start integer - [, flags text ] ] ) + , start integer + , flags text ) integer @@ -3331,11 +3407,11 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_instr regexp_instr ( string text, pattern text - [, start integer - [, N integer - [, endoption integer - [, flags text - [, subexpr integer ] ] ] ] ] ) + , start integer + , N integer + , endoption integer + , flags text + , subexpr integer ) integer @@ -3360,7 +3436,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_like regexp_like ( string text, pattern text - [, flags text ] ) + , flags text ) boolean @@ -3380,7 +3456,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_match - regexp_match ( string text, pattern text [, flags text ] ) + regexp_match ( string text, pattern text , flags text ) text[] @@ -3400,7 +3476,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_matches - regexp_matches ( string text, pattern text [, flags text ] ) + regexp_matches ( string text, pattern text , flags text ) setof text[] @@ -3426,7 +3502,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_replace regexp_replace ( string text, pattern text, replacement text - [, flags text ] ) + , flags text ) text @@ -3445,8 +3521,8 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_replace ( string text, pattern text, replacement text, start integer - [, N integer - [, flags text ] ] ) + , N integer + , flags text ) text @@ -3473,7 +3549,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_split_to_array - regexp_split_to_array ( string text, pattern text [, flags text ] ) + regexp_split_to_array ( string text, pattern text , flags text ) text[] @@ -3492,7 +3568,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_split_to_table - regexp_split_to_table ( string text, pattern text [, flags text ] ) + regexp_split_to_table ( string text, pattern text , flags text ) setof text @@ -3516,10 +3592,10 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in regexp_substr regexp_substr ( string text, pattern text - [, start integer - [, N integer - [, flags text - [, subexpr integer ] ] ] ] ) + , start integer + , N integer + , flags text + , subexpr integer ) text @@ -3986,7 +4062,7 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in -format(formatstr text [, formatarg "any" [, ...] ]) +format(formatstr text , formatarg "any" , ... ) formatstr is a format string that specifies how the result should be formatted. Text in the format string is copied @@ -4490,6 +4566,40 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); + + + + crc32 + + crc32 ( bytea ) + bigint + + + Computes the CRC-32 value of the binary string. + + + crc32('abc'::bytea) + 891568578 + + + + + + + crc32c + + crc32c ( bytea ) + bigint + + + Computes the CRC-32C value of the binary string. + + + crc32c('abc'::bytea) + 910901175 + + + @@ -4588,6 +4698,23 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); + + + + reverse + + reverse ( bytea ) + bytea + + + Reverses the order of the bytes in the binary string. + + + reverse('\xabcd'::bytea) + \xcdab + + + @@ -4963,6 +5090,23 @@ SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three'); + + In addition, it is possible to cast integral values to and from type + bytea. Casting an integer to bytea produces + 2, 4, or 8 bytes, depending on the width of the integer type. The result + is the two's complement representation of the integer, with the most + significant byte first. Some examples: + +1234::smallint::bytea \x04d2 +cast(1234 as bytea) \x000004d2 +cast(-1234 as bytea) \xfffffb2e +'\x8000'::bytea::smallint -32768 +'\x8000'::bytea::integer 32768 + + Casting a bytea to an integer will raise an error if the + length of the bytea exceeds the width of the integer type. + + See also the aggregate function string_agg in and the large object functions @@ -5380,9 +5524,10 @@ cast(-44 as bit(12)) 111111010100 - The pattern matching operators of all three kinds do not support - nondeterministic collations. If required, apply a different collation to - the expression to work around this limitation. + SIMILAR TO and POSIX-style regular + expressions do not support nondeterministic collations. If required, use + LIKE or apply a different collation to the expression + to work around this limitation. @@ -5428,6 +5573,46 @@ cast(-44 as bit(12)) 111111010100 + + LIKE pattern matching supports nondeterministic + collations (see ), such as + case-insensitive collations or collations that, say, ignore punctuation. + So with a case-insensitive collation, one could have: + +'AbC' LIKE 'abc' COLLATE case_insensitive true +'AbC' LIKE 'a%' COLLATE case_insensitive true + + With collations that ignore certain characters or in general that consider + strings of different lengths equal, the semantics can become a bit more + complicated. Consider these examples: + +'.foo.' LIKE 'foo' COLLATE ign_punct true +'.foo.' LIKE 'f_o' COLLATE ign_punct true +'.foo.' LIKE '_oo' COLLATE ign_punct false + + The way the matching works is that the pattern is partitioned into + sequences of wildcards and non-wildcard strings (wildcards being + _ and %). For example, the pattern + f_o is partitioned into f, _, o, the + pattern _oo is partitioned into _, + oo. The input string matches the pattern if it can be + partitioned in such a way that the wildcards match one character or any + number of characters respectively and the non-wildcard partitions are + equal under the applicable collation. So for example, '.foo.' + LIKE 'f_o' COLLATE ign_punct is true because one can partition + .foo. into .f, o, o., and then + '.f' = 'f' COLLATE ign_punct, 'o' + matches the _ wildcard, and 'o.' = 'o' COLLATE + ign_punct. But '.foo.' LIKE '_oo' COLLATE + ign_punct is false because .foo. cannot be + partitioned in a way that the first character is any character and the + rest of the string compares equal to oo. (Note that + the single-character wildcard always matches exactly one character, + independent of the collation. So in this example, the + _ would match ., but then the rest + of the input string won't match the rest of the pattern.) + + LIKE pattern matching always covers the entire string. Therefore, if it's desired to match a sequence anywhere within @@ -5469,8 +5654,9 @@ cast(-44 as bit(12)) 111111010100 The key word ILIKE can be used instead of - LIKE to make the match case-insensitive according - to the active locale. This is not in the SQL standard but is a + LIKE to make the match case-insensitive according to the + active locale. (But this does not support nondeterministic collations.) + This is not in the SQL standard but is a PostgreSQL extension. @@ -6117,13 +6303,13 @@ SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab; It has the syntax regexp_replace(string, pattern, replacement - , start + , flags ) + or + regexp_replace(string, + pattern, replacement, + start , N - - , flags ). - (Notice that N cannot be specified - unless start is, - but flags can be given in any case.) + , flags ). The source string is returned unchanged if there is no match to the pattern. If there is a match, the string is returned with the @@ -8593,8 +8779,8 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); plus/minus sign in specified position - RN - Roman numeral (input between 1 and 3999) + RN or rn + Roman numeral (values between 1 and 3999) TH or th @@ -8705,6 +8891,8 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); n is the number of digits following V. V with to_number divides in a similar manner. + The V can be thought of as marking the position + of an implicit decimal point in the input or output string. to_char and to_number do not support the use of V combined with a decimal point @@ -8720,6 +8908,19 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}'); (e.g., 9.99EEEE is a valid pattern). + + + + In to_number(), the RN + pattern converts Roman numerals (in standard form) to numbers. + Input is case-insensitive, so RN + and rn are equivalent. RN + cannot be used in combination with any other formatting patterns or + modifiers except FM, which is applicable only + in to_char() and is ignored + in to_number(). + + @@ -10398,12 +10599,16 @@ SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); quarter - The quarter of the year (1–4) that the date is in + The quarter of the year (1–4) that the date is in; + for interval values, the month field divided by 3 + plus 1 SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 1 +SELECT EXTRACT(QUARTER FROM INTERVAL '1 year 6 months'); +Result: 3 @@ -10474,9 +10679,16 @@ SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); week to get consistent results. + + For interval values, the week field is simply the number + of integral days divided by 7. + + SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 7 +SELECT EXTRACT(WEEK FROM INTERVAL '13 days 24 hours'); +Result: 1 @@ -10574,7 +10786,7 @@ SELECT date_part('hour', INTERVAL '4 hours 3 minutes'); -date_trunc(field, source [, time_zone ]) +date_trunc(field, source , time_zone ) source is a value expression of type timestamp, timestamp with time zone, @@ -10693,7 +10905,7 @@ SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-0 - <literal>AT TIME ZONE and AT LOCAL</literal> + <literal>AT TIME ZONE</literal> and <literal>AT LOCAL</literal> time zone @@ -10866,6 +11078,8 @@ SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'A Result: 2001-02-16 05:38:40 SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT LOCAL; Result: 2001-02-16 17:38:40 +SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE '+05'; +Result: 2001-02-16 20:38:40 SELECT TIME WITH TIME ZONE '20:38:40-05' AT LOCAL; Result: 17:38:40 @@ -10878,11 +11092,14 @@ SELECT TIME WITH TIME ZONE '20:38:40-05' AT LOCAL; Tokyo time to Chicago time. The fourth example shifts the time stamp with time zone value to the time zone currently specified by the TimeZone setting and returns the value without a - time zone. + time zone. The fifth example demonstrates that the sign in a POSIX-style + time zone specification has the opposite meaning of the sign in an + ISO-8601 datetime literal, as described in + and . - The fifth example is a cautionary tale. Due to the fact that there is no + The sixth example is a cautionary tale. Due to the fact that there is no date associated with the input value, the conversion is made using the current date of the session. Therefore, this static example may show a wrong result depending on the time of the year it is viewed because @@ -14166,6 +14383,14 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple gen_random_uuid + + uuidv4 + + + + uuidv7 + + uuid_extract_timestamp @@ -14175,46 +14400,164 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple - PostgreSQL includes one function to generate a UUID: - -gen_random_uuid () uuid - - This function returns a version 4 (random) UUID. This is the most commonly - used type of UUID and is appropriate for most applications. + shows the PostgreSQL + functions that can be used to generate UUIDs. - - The module provides additional functions that - implement other standard algorithms for generating UUIDs. - + + <acronym>UUID</acronym> Generation Functions + + + + + + Function + + + Description + + + Example(s) + + + + - - There are also functions to extract data from UUIDs: - -uuid_extract_timestamp (uuid) timestamp with time zone - - This function extracts a timestamp with time zone from UUID - version 1. For other versions, this function returns null. Note that the - extracted timestamp is not necessarily exactly equal to the time the UUID - was generated; this depends on the implementation that generated the UUID. - + + + + + gen_random_uuid + uuid + + + uuidv4 + uuid + + + Generate a version 4 (random) UUID. + + + gen_random_uuid() + 5b30857f-0bfa-48b5-ac0b-5c64e28078d1 + + + uuidv4() + b42410ee-132f-42ee-9e4f-09a6485c95b8 + + + + + + + uuidv7 + ( shift interval ) + uuid + + + Generate a version 7 (time-ordered) UUID. The timestamp is computed using UNIX timestamp + with millisecond precision + sub-millisecond timestamp + random. The optional parameter + shift will shift the computed timestamp by the given interval. + + + uuidv7() + 019535d9-3df7-79fb-b466-fa907fa17f9e + + + + + +
+ + + + The module provides additional functions that + implement other standard algorithms for generating UUIDs. + + - -uuid_extract_version (uuid) smallint - - This function extracts the version from a UUID of the variant described by - RFC 4122. For - other variants, this function returns null. For example, for a UUID - generated by gen_random_uuid, this function will - return 4. + shows the PostgreSQL + functions that can be used to extract information from UUIDs. + + <acronym>UUID</acronym> Extraction Functions + + + + + + Function + + + Description + + + Example(s) + + + + + + + + + + uuid_extract_timestamp + ( uuid ) + timestamp with time zone + + + Extracts a timestamp with time zone from UUID + version 1 and 7. For other versions, this function returns null. Note that + the extracted timestamp is not necessarily exactly equal to the time the + UUID was generated; this depends on the implementation that generated the + UUID. + + + uuid_extract_timestamp('019535d9-3df7-79fb-b466-&zwsp;fa907fa17f9e'::uuid) + 2025-02-23 21:46:24.503-05 + + + + + + + uuid_extract_version + ( uuid ) + smallint + + + Extracts the version from a UUID of the variant described by + RFC 9562. For + other variants, this function returns null. For example, for a UUID + generated by gen_random_uuid, this function will + return 4. + + + uuid_extract_version('41db1265-8bc1-4ab3-992f-&zwsp;885799a4af1d'::uuid) + 4 + + + uuid_extract_version('019535d9-3df7-79fb-b466-&zwsp;fa907fa17f9e'::uuid) + 7 + + + + + +
+ PostgreSQL also provides the usual comparison operators shown in for UUIDs. + + See for details on the data type + uuid in PostgreSQL. +
@@ -16011,7 +16354,7 @@ table2-mapping which specifies the data type returned. It must be one of json, jsonb, bytea, a character string type (text, char, or varchar), or a type - for which there is a cast from json to that type. + that can be cast to json. By default, the json type is returned. @@ -17074,25 +17417,32 @@ ERROR: value too long for type character(2) json_strip_nulls - json_strip_nulls ( json ) + json_strip_nulls ( target json ,strip_in_arrays boolean ) json jsonb_strip_nulls - jsonb_strip_nulls ( jsonb ) + jsonb_strip_nulls ( target jsonb ,strip_in_arrays boolean ) jsonb Deletes all object fields that have null values from the given JSON - value, recursively. Null values that are not object fields are - untouched. + value, recursively. + If strip_in_arrays is true (the default is false), + null array elements are also stripped. + Otherwise they are not stripped. Bare null values are never stripped. json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]') [{"f1":1},2,null,3] - + + + jsonb_strip_nulls('[1,2,null,3,4]', true); + [1,2,3,4] + + @@ -17131,8 +17481,8 @@ ERROR: value too long for type character(2) boolean - Returns the result of a JSON path predicate check for the specified - JSON value. + Returns the SQL boolean result of a JSON path predicate check + for the specified JSON value. (This is useful only with predicate check expressions, not SQL-standard JSON path expressions, @@ -17599,9 +17949,9 @@ SELECT '{ Boolean predicate, whereas the SQL standard allows predicates only within filters. While SQL-standard path expressions return the relevant element(s) of the queried JSON value, predicate check expressions - return the single three-valued result of the + return the single three-valued jsonb result of the predicate: true, - false, or unknown. + false, or null. For example, we could write this SQL-standard filter expression: => select jsonb_path_query(:'json', '$.track.segments ?(@[*].HR > 130)'); @@ -17971,15 +18321,16 @@ ERROR: jsonpath member accessor can only be applied to an object string - String value converted from a JSON boolean, number, string, or datetime + String value converted from a JSON boolean, number, string, or + datetime jsonb_path_query_array('[1.23, "xyz", false]', '$[*].string()') ["1.23", "xyz", "false"] - jsonb_path_query('"2023-08-15"', '$.datetime().string()') - "2023-08-15" + jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()') + "2023-08-15T12:34:56" @@ -18060,7 +18411,9 @@ ERROR: jsonpath member accessor can only be applied to an object decimal - Rounded decimal value converted from a JSON number or string. precision and scale must be integer values. + Rounded decimal value converted from a JSON number or string + (precision and scale must be + integer values) jsonb_path_query('1234.5678', '$.decimal(6, 2)') @@ -18162,7 +18515,7 @@ ERROR: jsonpath member accessor can only be applied to an object Time without time zone value converted from a string, with fractional - seconds adjusted to the given precision. + seconds adjusted to the given precision jsonb_path_query('"12:34:56.789"', '$.time(2)') @@ -18191,7 +18544,7 @@ ERROR: jsonpath member accessor can only be applied to an object Time with time zone value converted from a string, with fractional - seconds adjusted to the given precision. + seconds adjusted to the given precision jsonb_path_query('"12:34:56.789 +05:30"', '$.time_tz(2)') @@ -18220,7 +18573,7 @@ ERROR: jsonpath member accessor can only be applied to an object Timestamp without time zone value converted from a string, with - fractional seconds adjusted to the given precision. + fractional seconds adjusted to the given precision jsonb_path_query('"2023-08-15 12:34:56.789"', '$.timestamp(2)') @@ -18249,7 +18602,7 @@ ERROR: jsonpath member accessor can only be applied to an object Timestamp with time zone value converted from a string, with fractional - seconds adjusted to the given precision. + seconds adjusted to the given precision jsonb_path_query('"2023-08-15 12:34:56.789 +05:30"', '$.timestamp_tz(2)') @@ -18835,7 +19188,7 @@ ERROR: jsonpath array subscript is out of bounds JSON_QUERY(jsonb '[1,[2,3],null]', 'lax $[*][$off]' PASSING 1 AS off WITH CONDITIONAL WRAPPER) - [3] + 3 JSON_QUERY(jsonb '{"a": "[1, 2]"}', 'lax $.a' OMIT QUOTES) @@ -19311,7 +19664,7 @@ SELECT jt.* FROM SELECT jt.* FROM my_films, JSON_TABLE (js, '$.favorites[*] ? (@.films[*].director == $filter)' - PASSING 'Alfred Hitchcock' AS filter, 'Vertigo' AS filter2 + PASSING 'Alfred Hitchcock' AS filter COLUMNS ( id FOR ORDINALITY, kind text PATH '$.kind', @@ -19398,13 +19751,13 @@ SELECT jt.* FROM SELECT * FROM JSON_TABLE ( '{"favorites": - {"movies": + [{"movies": [{"name": "One", "director": "John Doe"}, {"name": "Two", "director": "Don Joe"}], "books": [{"name": "Mystery", "authors": [{"name": "Brown Dan"}]}, {"name": "Wonder", "authors": [{"name": "Jun Murakami"}, {"name":"Craig Doe"}]}] -}}'::json, '$.favorites[*]' +}]}'::json, '$.favorites[*]' COLUMNS ( user_id FOR ORDINALITY, NESTED '$.movies[*]' @@ -20329,6 +20682,23 @@ SELECT NULLIF(value, '(none)') ... + + + + array_reverse + + array_reverse ( anyarray ) + anyarray + + + Reverses the first dimension of the array. + + + array_reverse(ARRAY[[1,2],[3,4],[5,6]]) + {{5,6},{3,4},{1,2}} + + + @@ -20373,14 +20743,50 @@ SELECT NULLIF(value, '(none)') ... - - array_to_string + + array_sort - array_to_string ( array anyarray, delimiter text , null_string text ) - text + array_sort ( + array anyarray + , descending boolean + , nulls_first boolean + ) + anyarray - Converts each array element to its text representation, and + Sorts the first dimension of the array. + The sort order is determined by the default sort ordering of the + array's element type; however, if the element type is collatable, + the collation to use can be specified by adding + a COLLATE clause to + the array argument. + + + If descending is true then sort in + descending order, otherwise ascending order. If omitted, the + default is ascending order. + If nulls_first is true then nulls appear + before non-null values, otherwise nulls appear after non-null + values. + If omitted, nulls_first is taken to have + the same value as descending. + + + array_sort(ARRAY[[2,4],[2,1],[6,5]]) + {{2,1},{2,4},{6,5}} + + + + + + + array_to_string + + array_to_string ( array anyarray, delimiter text , null_string text ) + text + + + Converts each array element to its text representation, and concatenates those separated by the delimiter string. If null_string is given and is @@ -21387,7 +21793,7 @@ SELECT NULLIF(value, '(none)') ... Extracts the lower bound of the multirange (NULL if the - multirange is empty has no lower bound). + multirange is empty or has no lower bound). lower('{[1.1,2.2)}'::nummultirange) @@ -21876,6 +22282,54 @@ SELECT NULLIF(value, '(none)') ... No + + + + json_agg_strict + + json_agg_strict ( anyelement ) + json + + + + jsonb_agg_strict + + jsonb_agg_strict ( anyelement ) + jsonb + + + Collects all the input values, skipping nulls, into a JSON array. + Values are converted to JSON as per to_json + or to_jsonb. + + No + + + + + json_arrayagg + json_arrayagg ( + value_expression + ORDER BY sort_expression + { NULL | ABSENT } ON NULL + RETURNING data_type FORMAT JSON ENCODING UTF8 ) + + + Behaves in the same way as json_array + but as an aggregate function so it only takes one + value_expression parameter. + If ABSENT ON NULL is specified, any NULL + values are omitted. + If ORDER BY is specified, the elements will + appear in the array in that order rather than in the input order. + + + SELECT json_arrayagg(v) FROM (VALUES(2),(1)) t(v) + [2, 1] + + No + + json_objectagg @@ -21986,31 +22440,6 @@ SELECT NULLIF(value, '(none)') ... No - - - json_arrayagg - json_arrayagg ( - value_expression - ORDER BY sort_expression - { NULL | ABSENT } ON NULL - RETURNING data_type FORMAT JSON ENCODING UTF8 ) - - - Behaves in the same way as json_array - but as an aggregate function so it only takes one - value_expression parameter. - If ABSENT ON NULL is specified, any NULL - values are omitted. - If ORDER BY is specified, the elements will - appear in the array in that order rather than in the input order. - - - SELECT json_arrayagg(v) FROM (VALUES(2),(1)) t(v) - [2, 1] - - No - - @@ -22052,7 +22481,7 @@ SELECT NULLIF(value, '(none)') ... Computes the maximum of the non-null input values. Available for any numeric, string, date/time, or enum type, - as well as inet, interval, + as well as bytea, inet, interval, money, oid, pg_lsn, tid, xid8, and also arrays and composite types containing sortable data types. @@ -22071,7 +22500,7 @@ SELECT NULLIF(value, '(none)') ... Computes the minimum of the non-null input values. Available for any numeric, string, date/time, or enum type, - as well as inet, interval, + as well as bytea, inet, interval, money, oid, pg_lsn, tid, xid8, and also arrays and composite types containing sortable data types. @@ -22119,29 +22548,6 @@ SELECT NULLIF(value, '(none)') ... No - - - - json_agg_strict - - json_agg_strict ( anyelement ) - json - - - - jsonb_agg_strict - - jsonb_agg_strict ( anyelement ) - jsonb - - - Collects all the input values, skipping nulls, into a JSON array. - Values are converted to JSON as per to_json - or to_jsonb. - - No - - @@ -24670,6 +25076,28 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n); + + + + pg_get_loaded_modules + + pg_get_loaded_modules () + setof record + ( module_name text, + version text, + file_name text ) + + + Returns a list of the loadable modules that are loaded into the + current server session. The module_name + and version fields are NULL unless the + module author supplied values for them using + the PG_MODULE_MAGIC_EXT macro. + The file_name field gives the file + name of the module (shared library). + + + @@ -24715,6 +25143,19 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n); + + + + pg_numa_available + + pg_numa_available () + boolean + + + Returns true if the server has been compiled with NUMA support. + + + @@ -25068,6 +25509,24 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); + + + + has_largeobject_privilege + + has_largeobject_privilege ( + user name or oid, + largeobject oid, + privilege text ) + boolean + + + Does user have privilege for large object? + Allowable privilege types are + SELECT and UPDATE. + + + @@ -25223,6 +25682,10 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); are immediately available without doing SET ROLE, while SET denotes whether it is possible to change to the role using the SET ROLE command. + WITH ADMIN OPTION or WITH GRANT + OPTION can be added to any of these privilege types to + test whether the ADMIN privilege is held (all + six spellings test the same thing). This function does not allow the special case of setting user to public, because the PUBLIC pseudo-role can never be a member of real roles. @@ -27049,6 +27512,34 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} + + + + age + + age ( xid ) + integer + + + Returns the number of transactions between the supplied + transaction id and the current transaction counter. + + + + + + + mxid_age + + mxid_age ( xid ) + integer + + + Returns the number of multixacts IDs between the supplied + multixact ID and the current multixacts counter. + + + @@ -27193,7 +27684,8 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} The internal transaction ID type xid is 32 bits wide and wraps around every 4 billion transactions. However, - the functions shown in use a + the functions shown in , except + age and mxid_age, use a 64-bit type xid8 that does not wrap around during the life of an installation and can be converted to xid by casting if required; see for details. @@ -27275,33 +27767,6 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} - - - - age - - age ( xid ) - integer - - - Returns the number of transactions between the supplied - transaction id and the current transaction counter. - - - - - - - mxid_age - - mxid_age ( xid ) - integer - - - Returns the number of multixacts IDs between the supplied - multixact ID and the current multixacts counter. - - @@ -27786,6 +28251,11 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} integer + + default_char_signedness + boolean + + @@ -28119,6 +28589,11 @@ acl | {postgres=arwdDxtm/postgres,foo=r/postgres} use false instead. This function corresponds to the SQL command . + + set_config accepts the NULL value for + new_value, but as settings cannot be null, it + is interpreted as a request to reset the setting to its default value. + set_config('log_statement_stats', 'off', false) off @@ -28309,16 +28784,16 @@ One message for each memory context will be logged. For example: LOG: logging memory contexts of PID 10377 STATEMENT: SELECT pg_log_backend_memory_contexts(pg_backend_pid()); -LOG: level: 0; TopMemoryContext: 80800 total in 6 blocks; 14432 free (5 chunks); 66368 used -LOG: level: 1; pgstat TabStatusArray lookup hash table: 8192 total in 1 blocks; 1408 free (0 chunks); 6784 used -LOG: level: 1; TopTransactionContext: 8192 total in 1 blocks; 7720 free (1 chunks); 472 used -LOG: level: 1; RowDescriptionContext: 8192 total in 1 blocks; 6880 free (0 chunks); 1312 used -LOG: level: 1; MessageContext: 16384 total in 2 blocks; 5152 free (0 chunks); 11232 used -LOG: level: 1; Operator class cache: 8192 total in 1 blocks; 512 free (0 chunks); 7680 used -LOG: level: 1; smgr relation table: 16384 total in 2 blocks; 4544 free (3 chunks); 11840 used -LOG: level: 1; TransactionAbortContext: 32768 total in 1 blocks; 32504 free (0 chunks); 264 used +LOG: level: 1; TopMemoryContext: 80800 total in 6 blocks; 14432 free (5 chunks); 66368 used +LOG: level: 2; pgstat TabStatusArray lookup hash table: 8192 total in 1 blocks; 1408 free (0 chunks); 6784 used +LOG: level: 2; TopTransactionContext: 8192 total in 1 blocks; 7720 free (1 chunks); 472 used +LOG: level: 2; RowDescriptionContext: 8192 total in 1 blocks; 6880 free (0 chunks); 1312 used +LOG: level: 2; MessageContext: 16384 total in 2 blocks; 5152 free (0 chunks); 11232 used +LOG: level: 2; Operator class cache: 8192 total in 1 blocks; 512 free (0 chunks); 7680 used +LOG: level: 2; smgr relation table: 16384 total in 2 blocks; 4544 free (3 chunks); 11840 used +LOG: level: 2; TransactionAbortContext: 32768 total in 1 blocks; 32504 free (0 chunks); 264 used ... -LOG: level: 1; ErrorContext: 8192 total in 1 blocks; 7928 free (3 chunks); 264 used +LOG: level: 2; ErrorContext: 8192 total in 1 blocks; 7928 free (3 chunks); 264 used LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560 used If there are more than 100 child contexts under the same parent, the first @@ -29091,8 +29566,7 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset Drops the physical or logical replication slot named slot_name. Same as replication protocol - command DROP_REPLICATION_SLOT. For logical slots, this must - be called while connected to the same database the slot was created on. + command DROP_REPLICATION_SLOT. @@ -29142,7 +29616,8 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset The copied physical slot starts to reserve WAL from the same LSN as the source slot. temporary is optional. If temporary - is omitted, the same value as the source slot is used. + is omitted, the same value as the source slot is used. Copy of an + invalidated slot is not allowed. @@ -29164,6 +29639,11 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset from the same LSN as the source logical slot. Both temporary and plugin are optional; if they are omitted, the values of the source slot are used. + The failover option of the source logical slot + is not copied and is set to false by default. This + is to avoid the risk of being unable to continue logical replication + after failover to standby where the slot is being synchronized. Copy of + an invalidated slot is not allowed. @@ -29289,6 +29769,7 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset Creates a replication origin with the given external name, and returns the internal ID assigned to it. + The name must be no longer than 512 bytes. @@ -29449,11 +29930,11 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset pg_logical_emit_message - pg_logical_emit_message ( transactional boolean, prefix text, content text [, flush boolean DEFAULT false] ) + pg_logical_emit_message ( transactional boolean, prefix text, content text , flush boolean DEFAULT false ) pg_lsn - pg_logical_emit_message ( transactional boolean, prefix text, content bytea [, flush boolean DEFAULT false] ) + pg_logical_emit_message ( transactional boolean, prefix text, content bytea , flush boolean DEFAULT false ) pg_lsn @@ -29937,6 +30418,229 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset + + lists functions used to + manipulate statistics. + These functions cannot be executed during recovery. + + + Changes made by these statistics manipulation functions are likely to be + overwritten by autovacuum (or manual + VACUUM or ANALYZE) and should be + considered temporary. + + + + + + Database Object Statistics Manipulation Functions + + + + + Function + + + Description + + + + + + + + + pg_restore_relation_stats + + pg_restore_relation_stats ( + VARIADIC kwargs "any" ) + boolean + + + Updates table-level statistics. Ordinarily, these statistics are + collected automatically or updated as a part of or , so it's not + necessary to call this function. However, it is useful after a + restore to enable the optimizer to choose better plans if + ANALYZE has not been run yet. + + + The tracked statistics may change from version to version, so + arguments are passed as pairs of argname + and argvalue in the form: + +SELECT pg_restore_relation_stats( + 'arg1name', 'arg1value'::arg1type, + 'arg2name', 'arg2value'::arg2type, + 'arg3name', 'arg3value'::arg3type); + + + + For example, to set the relpages and + reltuples values for the table + mytable: + +SELECT pg_restore_relation_stats( + 'schemaname', 'myschema', + 'relname', 'mytable', + 'relpages', 173::integer, + 'reltuples', 10000::real); + + + + The arguments schemaname and + relname are required, and specify the table. Other + arguments are the names and values of statistics corresponding to + certain columns in pg_class. + The currently-supported relation statistics are + relpages with a value of type + integer, reltuples with a value of + type real, relallvisible with a value + of type integer, and relallfrozen + with a value of type integer. + + + Additionally, this function accepts argument name + version of type integer, which + specifies the server version from which the statistics originated. + This is anticipated to be helpful in porting statistics from older + versions of PostgreSQL. + + + Minor errors are reported as a WARNING and + ignored, and remaining statistics will still be restored. If all + specified statistics are successfully restored, returns + true, otherwise false. + + + The caller must have the MAINTAIN privilege on the + table or be the owner of the database. + + + + + + + + + pg_clear_relation_stats + + pg_clear_relation_stats ( schemaname text, relname text ) + void + + + Clears table-level statistics for the given relation, as though the + table was newly created. + + + The caller must have the MAINTAIN privilege on the + table or be the owner of the database. + + + + + + + + pg_restore_attribute_stats + + pg_restore_attribute_stats ( + VARIADIC kwargs "any" ) + boolean + + + Creates or updates column-level statistics. Ordinarily, these + statistics are collected automatically or updated as a part of or , so it's not + necessary to call this function. However, it is useful after a + restore to enable the optimizer to choose better plans if + ANALYZE has not been run yet. + + + The tracked statistics may change from version to version, so + arguments are passed as pairs of argname + and argvalue in the form: + +SELECT pg_restore_attribute_stats( + 'arg1name', 'arg1value'::arg1type, + 'arg2name', 'arg2value'::arg2type, + 'arg3name', 'arg3value'::arg3type); + + + + For example, to set the avg_width and + null_frac values for the attribute + col1 of the table + mytable: + +SELECT pg_restore_attribute_stats( + 'schemaname', 'myschema', + 'relname', 'mytable', + 'attname', 'col1', + 'inherited', false, + 'avg_width', 125::integer, + 'null_frac', 0.5::real); + + + + The required arguments are schemaname and + relname with a value of type text + which specify the table; either attname with a + value of type text or attnum with a + value of type smallint, which specifies the column; and + inherited, which specifies whether the statistics + include values from child tables. Other arguments are the names and + values of statistics corresponding to columns in pg_stats. + + + Additionally, this function accepts argument name + version of type integer, which + specifies the server version from which the statistics originated. + This is anticipated to be helpful in porting statistics from older + versions of PostgreSQL. + + + Minor errors are reported as a WARNING and + ignored, and remaining statistics will still be restored. If all + specified statistics are successfully restored, returns + true, otherwise false. + + + The caller must have the MAINTAIN privilege on the + table or be the owner of the database. + + + + + + + + + pg_clear_attribute_stats + + pg_clear_attribute_stats ( + schemaname text, + relname text, + attname text, + inherited boolean ) + void + + + Clears column-level statistics for the given relation and + attribute, as though the table was newly created. + + + The caller must have the MAINTAIN privilege on + the table or be the owner of the database. + + + + + +
+ lists functions that provide information about the structure of partitioned tables. @@ -30332,6 +31036,30 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size + + + + pg_ls_summariesdir + + pg_ls_summariesdir () + setof record + ( name text, + size bigint, + modification timestamp with time zone ) + + + Returns the name, size, and last modification time (mtime) of each + ordinary file in the server's WAL summaries directory + (pg_wal/summaries). Filenames beginning + with a dot, directories, and other special files are excluded. + + + This function is restricted to superusers and members of + the pg_monitor role by default, but other users can + be granted EXECUTE to run the function. + + + @@ -31158,8 +31886,12 @@ CREATE EVENT TRIGGER test_event_trigger_for_drops integer - Returns a code explaining the reason(s) for rewriting. The exact - meaning of the codes is release dependent. + Returns a code explaining the reason(s) for rewriting. The value is + a bitmap built from the following values: 1 + (the table has changed its persistence), 2 + (default value of a column has changed), 4 + (a column has a new data type) and 8 + (the table access method has changed). diff --git a/doc/src/sgml/generate-errcodes-table.pl b/doc/src/sgml/generate-errcodes-table.pl index dd87aee948397..d939eec3f4a8e 100644 --- a/doc/src/sgml/generate-errcodes-table.pl +++ b/doc/src/sgml/generate-errcodes-table.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the errcodes-table.sgml file from errcodes.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/doc/src/sgml/generate-keywords-table.pl b/doc/src/sgml/generate-keywords-table.pl index 891d7811a866c..76c4689872fab 100644 --- a/doc/src/sgml/generate-keywords-table.pl +++ b/doc/src/sgml/generate-keywords-table.pl @@ -2,7 +2,7 @@ # # Generate the keywords table for the documentation's SQL Key Words appendix # -# Copyright (c) 2019-2024, PostgreSQL Global Development Group +# Copyright (c) 2019-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/doc/src/sgml/generate-targets-meson.pl b/doc/src/sgml/generate-targets-meson.pl index 62823b46bef84..d127429c98181 100644 --- a/doc/src/sgml/generate-targets-meson.pl +++ b/doc/src/sgml/generate-targets-meson.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the targets-meson.sgml file from targets-meson.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index 39c7bf370d67b..ee86e17005520 100644 --- a/doc/src/sgml/gist.sgml +++ b/doc/src/sgml/gist.sgml @@ -266,7 +266,7 @@ CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops); There are five methods that an index operator class for - GiST must provide, and six that are optional. + GiST must provide, and seven that are optional. Correctness of the index is ensured by proper implementation of the same, consistent and union methods, while efficiency (size and speed) of the @@ -289,6 +289,11 @@ CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops); user-specified parameters. The optional eleventh method sortsupport is used to speed up building a GiST index. + The optional twelfth method stratnum is used to + translate compare types (from + src/include/nodes/primnodes.h) into strategy numbers + used by the operator class. This lets the core code look up operators for + temporal constraint indexes. @@ -1022,7 +1027,7 @@ fill_my_string_relopt(const char *value, void *ptr) int len = strlen(tmp); if (ptr) - strcpy((char *) ptr, tmp); + strcpy(ptr, tmp); pfree(tmp); return len + 1; @@ -1163,6 +1168,90 @@ my_sortsupport(PG_FUNCTION_ARGS)
+ + + translate_cmptype + + + Given a CompareType value from + src/include/nodes/primnodes.h, returns a strategy + number used by this operator class for matching functionality. The + function should return InvalidStrategy if the + operator class has no matching strategy. + + + + This is used for temporal index constraints (i.e., PRIMARY + KEY and UNIQUE). If the operator class + provides this function and it returns results for + COMPARE_EQ, it can be used in the + non-WITHOUT OVERLAPS part(s) of an index constraint. + + + + This support function corresponds to the index access method callback + function amtranslatecmptype (see ). The + amtranslatecmptype callback function for + GiST indexes merely calls down to the + translate_cmptype support function of the + respective operator family, since the GiST index access method has no + fixed strategy numbers itself. + + + + The SQL declaration of the function must look like + this: + + +CREATE OR REPLACE FUNCTION my_translate_cmptype(integer) +RETURNS smallint +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + + + And the operator family registration must look like this: + +ALTER OPERATOR FAMILY my_opfamily USING gist ADD + FUNCTION 12 ("any", "any") my_translate_cmptype(int); + + + + + The matching code in the C module could then follow this skeleton: + + +PG_FUNCTION_INFO_V1(my_translate_cmptype); + +Datum +my_translate_cmptype(PG_FUNCTION_ARGS) +{ + CompareType cmptype = PG_GETARG_INT32(0); + StrategyNumber ret = InvalidStrategy; + + switch (cmptype) + { + case COMPARE_EQ: + ret = BTEqualStrategyNumber; + } + + PG_RETURN_UINT16(ret); +} + + + + + One translation function is provided by + PostgreSQL: + gist_translate_cmptype_common is for operator classes that + use the RT*StrategyNumber constants. + The btree_gist + extension defines a second translation function, + gist_translate_cmptype_btree, for operator classes that use + the BT*StrategyNumber constants. + + + diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml index 405fe6dc8b953..b88cac598e901 100644 --- a/doc/src/sgml/glossary.sgml +++ b/doc/src/sgml/glossary.sgml @@ -81,6 +81,31 @@ + + Asynchronous I/O + AIO + + Asynchronous I/O + + + + Asynchronous I/O (AIO) describes + performing I/O in a non-blocking way (asynchronously), + in contrast to synchronous I/O, which blocks for the + entire duration of the I/O. + + + With AIO, starting an I/O operation + is separated from waiting for the result of the operation, allowing + multiple I/O operations to be initiated concurrently, + as well as performing CPU heavy operations + concurrently with I/O. The price for that increased + concurrency is increased complexity. + + + + + Atomic @@ -851,6 +876,11 @@ + + GMT + + + Grant @@ -933,6 +963,20 @@ + + Input/Output + I/O + + + Input/Output (I/O) describes the communication between + a program and peripheral devices. In the context of database systems, + I/O commonly, but not exclusively, refers to + interaction with storage devices or the network. + + + + + Insert @@ -1069,6 +1113,16 @@ + + Logical replication cluster + + + A set of publisher and subscriber instances with the publisher instance + replicating changes to the subscriber instance. + + + + Log record @@ -2037,6 +2091,17 @@ + + UTC + + + Universal Coordinated Time, the primary global time reference, + approximately the time prevailing at the zero meridian of longitude. + Often but inaccurately referred to as GMT (Greenwich Mean Time). + + + + Vacuum diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml index acf3ac0601d23..b47d8b4106efb 100644 --- a/doc/src/sgml/high-availability.sgml +++ b/doc/src/sgml/high-availability.sgml @@ -1535,7 +1535,8 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)' When the parameter is set to true on a standby server, it will begin accepting connections once the recovery has - brought the system to a consistent state. All such connections are + brought the system to a consistent state and be ready for hot standby. + All such connections are strictly read-only; not even temporary tables may be written. @@ -1974,9 +1975,12 @@ LOG: database system is ready to accept read-only connections Consistency information is recorded once per checkpoint on the primary. It is not possible to enable hot standby when reading WAL written during a period when wal_level was not set to - replica or logical on the primary. Reaching - a consistent state can also be delayed in the presence of both of these - conditions: + replica or logical on the primary. + Even after reaching a consistent state, the recovery snapshot may not + be ready for hot standby if both of the following conditions are met, + delaying accepting read-only connections. To enable hot standby, + long-lived write transactions with more than 64 subtransactions + need to be closed on the primary. diff --git a/doc/src/sgml/history.sgml b/doc/src/sgml/history.sgml index e7d134e53ad5a..8bfa1db670d7a 100644 --- a/doc/src/sgml/history.sgml +++ b/doc/src/sgml/history.sgml @@ -75,9 +75,8 @@ url="https://www.ibm.com/">IBM) picked up the code and commercialized it. In late 1992, POSTGRES became the primary data manager - for the - - Sequoia 2000 scientific computing project. + for the Sequoia 2000 scientific computing project described in + . @@ -204,11 +203,10 @@ - Many people continue to refer to - PostgreSQL as Postgres - (now rarely in all capital letters) because of tradition or because - it is easier to pronounce. This usage is widely accepted as a - nickname or alias. + Postgres is still considered an official + project name, both because of tradition and because people find it + easier to pronounce Postgres than + PostgreSQL. diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml index 7d93e49e91309..44325e0bba0c4 100644 --- a/doc/src/sgml/hstore.sgml +++ b/doc/src/sgml/hstore.sgml @@ -946,15 +946,6 @@ ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; extension for PL/Python is called hstore_plpython3u. If you use it, hstore values are mapped to Python dictionaries. - - - - It is strongly recommended that the transform extensions be installed in - the same schema as hstore. Otherwise there are - installation-time security hazards if a transform extension's schema - contains objects defined by a hostile user. - - diff --git a/doc/src/sgml/images/genetic-algorithm.gv b/doc/src/sgml/images/genetic-algorithm.gv index 80c354c2c8be8..7912e165deac0 100644 --- a/doc/src/sgml/images/genetic-algorithm.gv +++ b/doc/src/sgml/images/genetic-algorithm.gv @@ -36,6 +36,7 @@ digraph { // edges a1 -> a2 -> a3 -> a4; + // these trailing spaces output as "nbsp" (UTF8 NO-BREAK SPACE) a4 -> a5[xlabel="false ", fontsize=10]; a4 -> end[xlabel="true ", fontsize=10]; a5 -> a6 -> a7 -> a8 -> a9; diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index e3c1539a1e3bc..1aa4741a8eaee 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -103,6 +103,12 @@ typedef struct IndexAmRoutine bool amcanorder; /* does AM support ORDER BY result of an operator on indexed column? */ bool amcanorderbyop; + /* does AM support hashing using API consistent with the hash AM? */ + bool amcanhash; + /* do operators within an opfamily have consistent equality semantics? */ + bool amconsistentequality; + /* do operators within an opfamily have consistent ordering semantics? */ + bool amconsistentordering; /* does AM support backward scanning? */ bool amcanbackward; /* does AM support UNIQUE indexes? */ @@ -146,6 +152,7 @@ typedef struct IndexAmRoutine amvacuumcleanup_function amvacuumcleanup; amcanreturn_function amcanreturn; /* can be NULL */ amcostestimate_function amcostestimate; + amgettreeheight_function amgettreeheight; /* can be NULL */ amoptions_function amoptions; amproperty_function amproperty; /* can be NULL */ ambuildphasename_function ambuildphasename; /* can be NULL */ @@ -163,6 +170,10 @@ typedef struct IndexAmRoutine amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ + + /* interface functions to support planning */ + amtranslate_strategy_function amtranslatestrategy; /* can be NULL */ + amtranslate_cmptype_function amtranslatecmptype; /* can be NULL */ } IndexAmRoutine; @@ -480,6 +491,21 @@ amcostestimate (PlannerInfo *root, +int +amgettreeheight (Relation rel); + + Compute the height of a tree-shaped index. This information is supplied to + the amcostestimate function in + path->indexinfo->tree_height and can be used to support + the cost estimation. The result is not used anywhere else, so this + function can actually be used to compute any kind of data (that fits into + an integer) about the index that the cost estimation function might want to + know. If the computation is expensive, it could be useful to cache the + result as part of RelationData.rd_amcache. + + + + bytea * amoptions (ArrayType *reloptions, bool validate); @@ -809,7 +835,8 @@ amrestrpos (IndexScanDesc scan); Size -amestimateparallelscan (int nkeys, +amestimateparallelscan (Relation indexRelation, + int nkeys, int norderbys); Estimate and return the number of bytes of dynamic shared memory which @@ -860,6 +887,28 @@ amparallelrescan (IndexScanDesc scan); the beginning. + + +CompareType +amtranslatestrategy (StrategyNumber strategy, Oid opfamily, Oid opcintype); + +StrategyNumber +amtranslatecmptype (CompareType cmptype, Oid opfamily, Oid opcintype); + + These functions, if implemented, will be called by the planner and executor + to convert between fixed CompareType values and the specific + strategy numbers used by the access method. These functions can be + implemented by access methods that implement functionality similar to the + built-in btree or hash access methods, and by implementing these + translations, the system can learn about the semantics of the access + method's operations and can use them in place of btree or hash indexes in + various places. If the functionality of the access method is not similar + to those built-in access methods, these functions do not need to be + implemented. If the functions are not implemented, the access method will + be ignored for certain planner and executor decisions, but is otherwise + fully functional. + +
diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 6d731e0701fdd..9c4f76abf0dcd 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -460,20 +460,56 @@ CREATE INDEX test2_mm_idx ON test2 (major, minor); efficient when there are constraints on the leading (leftmost) columns. The exact rule is that equality constraints on leading columns, plus any inequality constraints on the first column that does not have an - equality constraint, will be used to limit the portion of the index + equality constraint, will always be used to limit the portion of the index that is scanned. Constraints on columns to the right of these columns - are checked in the index, so they save visits to the table proper, but - they do not reduce the portion of the index that has to be scanned. + are checked in the index, so they'll always save visits to the table + proper, but they do not necessarily reduce the portion of the index that + has to be scanned. If a B-tree index scan can apply the skip scan + optimization effectively, it will apply every column constraint when + navigating through the index via repeated index searches. This can reduce + the portion of the index that has to be read, even though one or more + columns (prior to the least significant index column from the query + predicate) lacks a conventional equality constraint. Skip scan works by + generating a dynamic equality constraint internally, that matches every + possible value in an index column (though only given a column that lacks + an equality constraint that comes from the query predicate, and only when + the generated constraint can be used in conjunction with a later column + constraint from the query predicate). + + + + For example, given an index on (x, y), and a query + condition WHERE y = 7700, a B-tree index scan might be + able to apply the skip scan optimization. This generally happens when the + query planner expects that repeated WHERE x = N AND y = 7700 + searches for every possible value of N (or for every + x value that is actually stored in the index) is the + fastest possible approach, given the available indexes on the table. This + approach is generally only taken when there are so few distinct + x values that the planner expects the scan to skip over + most of the index (because most of its leaf pages cannot possibly contain + relevant tuples). If there are many distinct x values, + then the entire index will have to be scanned, so in most cases the planner + will prefer a sequential table scan over using the index. + + + + The skip scan optimization can also be applied selectively, during B-tree + scans that have at least some useful constraints from the query predicate. For example, given an index on (a, b, c) and a query condition WHERE a = 5 AND b >= 42 AND c < 77, - the index would have to be scanned from the first entry with - a = 5 and b = 42 up through the last entry with - a = 5. Index entries with c >= 77 would be - skipped, but they'd still have to be scanned through. - This index could in principle be used for queries that have constraints - on b and/or c with no constraint on a - — but the entire index would have to be scanned, so in most cases - the planner would prefer a sequential table scan over using the index. + the index might have to be scanned from the first entry with + a = 5 and b = 42 up through the last + entry with a = 5. Index entries with + c >= 77 will never need to be filtered at the table + level, but it may or may not be profitable to skip over them within the + index. When skipping takes place, the scan starts a new index search to + reposition itself from the end of the current a = 5 and + b = N grouping (i.e. from the position in the index + where the first tuple a = 5 AND b = N AND c >= 77 + appears), to the start of the next such grouping (i.e. the position in the + index where the first tuple a = 5 AND b = N + 1 + appears). @@ -669,9 +705,13 @@ CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST); multicolumn index on (x, y). This index would typically be more efficient than index combination for queries involving both columns, but as discussed in , it - would be almost useless for queries involving only y, so it - should not be the only index. A combination of the multicolumn index - and a separate index on y would serve reasonably well. For + would be less useful for queries involving only y. Just + how useful will depend on how effective the B-tree index skip scan + optimization is; if x has no more than several hundred + distinct values, skip scan will make searches for specific + y values execute reasonably efficiently. A combination + of a multicolumn index on (x, y) and a separate index on + y might also serve reasonably well. For queries involving only x, the multicolumn index could be used, though it would be larger and hence slower than an index on x alone. The last alternative is to create all three diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml index 9442b0718c094..19dffe7be6aa7 100644 --- a/doc/src/sgml/information_schema.sgml +++ b/doc/src/sgml/information_schema.sgml @@ -6896,9 +6896,7 @@ ORDER BY c.ordinal_position; enforced yes_or_no - Applies to a feature not available in - PostgreSQL (currently always - YES) + YES if the constraint is enforced, NO if not diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 4784834ab9fd4..de19f3ad92952 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -55,9 +55,11 @@ Alternatively, PostgreSQL can be built using - Meson. This is currently - experimental. If you choose to use - Meson, then you don't need + Meson. This is the only + option for building PostgreSQL on Windows + using Visual Studio. For other platforms, + using Meson is currently experimental. If + you choose to use Meson, then you don't need GNU make, but the other requirements below still apply. @@ -100,10 +102,10 @@ yacc - Flex 2.5.35 or later and - Bison 2.3 or later are required. Other - lex and yacc - programs cannot be used. + Flex and Bison are + required. Other lex and + yacc programs cannot be used. + Bison needs to be at least version 2.3. @@ -239,7 +241,7 @@ language, you need a Python installation with the header files and the sysconfig module. The minimum - required version is Python 3.2. + supported version is Python 3.6.8. @@ -293,7 +295,13 @@ encrypted client connections. OpenSSL is also required for random number generation on platforms that do not have /dev/urandom (except Windows). The minimum - required version is 1.0.2. + required version is 1.1.1. + + + Additionally, LibreSSL is supported using the + OpenSSL compatibility layer. The minimum + required version is 3.4 (from OpenBSD + version 7.0). @@ -305,6 +313,14 @@ + + + You need Curl to build an optional module + which implements the OAuth Device + Authorization flow for client applications. + + + You need LZ4, if you want to support @@ -936,17 +952,15 @@ build-postgresql: JIT compilation (see ). This requires the LLVM library to be installed. The minimum required version of LLVM is - currently 10. + currently 14. llvm-configllvm-config will be used to find the required compilation options. - llvm-config, and then - llvm-config-$major-$minor for all supported - versions, will be searched for in your PATH. If - that would not yield the desired program, - use LLVM_CONFIG to specify a path to the - correct llvm-config. For example + llvm-config will be searched for in your + PATH. If that would not yield the desired program, + use LLVM_CONFIG to specify a path to the correct + llvm-config. For example ./configure ... --with-llvm LLVM_CONFIG='/path/to/llvm/bin/llvm-config' @@ -991,7 +1005,9 @@ build-postgresql: Build with support for SSL (encrypted) connections. The only LIBRARY - supported is . This requires the + supported is , which is used for both + OpenSSL + and LibreSSL. This requires the OpenSSL package to be installed. configure will check for the required header files and libraries to make sure that your @@ -1135,6 +1151,48 @@ build-postgresql: + + + + + Build with libcurl support for OAuth 2.0 client flows. + Libcurl version 7.61.0 or later is required for this feature. + Building with this will check for the required header files + and libraries to make sure that your curl + installation is sufficient before proceeding. + + + + + + + + + Build with libnuma support for basic NUMA support. + Only supported on platforms for which the libnuma + library is implemented. + + + + + + + + + Build with liburing, enabling io_uring support for asynchronous I/O. + + + To detect the required compiler and linker options, PostgreSQL will + query pkg-config. + + + To use a liburing installation that is in an unusual location, you + can set pkg-config-related environment + variables (see its documentation). + + + + @@ -1258,34 +1316,6 @@ build-postgresql: - - - - - Allow the build to succeed even if PostgreSQL - has no CPU spinlock support for the platform. The lack of - spinlock support will result in very poor performance; therefore, - this option should only be used if the build aborts and - informs you that the platform lacks spinlock support. If this - option is required to build PostgreSQL on - your platform, please report the problem to the - PostgreSQL developers. - - - - - - - - - Disable use of CPU atomic operations. This option does nothing on - platforms that lack such operations. On platforms that do have - them, this will result in poor performance. This option is only - useful for debugging or making performance comparisons. - - - - @@ -2424,7 +2454,7 @@ ninja install JIT compilation (see ). This requires the LLVM library to be installed. The minimum required version of - LLVM is currently 10. Disabled by + LLVM is currently 14. Disabled by default. @@ -2604,6 +2634,47 @@ ninja install + + + + + Build with libcurl support for OAuth 2.0 client flows. + Libcurl version 7.61.0 or later is required for this feature. + Building with this will check for the required header files + and libraries to make sure that your Curl + installation is sufficient before proceeding. The default for this + option is auto. + + + + + + + + + Build with liburing, enabling io_uring support for asynchronous I/O. + Defaults to auto. + + + + To use a liburing installation that is in an unusual location, you + can set pkg-config-related environment + variables (see its documentation). + + + + + + + + + Build with libnuma support for basic NUMA support. + Only supported on platforms for which the libnuma + library is implemented. The default for this option is auto. + + + + @@ -2690,35 +2761,6 @@ ninja install - - - - - This option is set to true by default; setting it to false will - allow the build to succeed even if PostgreSQL - has no CPU spinlock support for the platform. The lack of - spinlock support will result in very poor performance; therefore, - this option should only be changed if the build aborts and - informs you that the platform lacks spinlock support. If setting this - option to false is required to build PostgreSQL on - your platform, please report the problem to the - PostgreSQL developers. - - - - - - - - - This option is set to true by default; setting it to false will - disable use of CPU atomic operations. The option does nothing on - platforms that lack such operations. On platforms that do have - them, disabling atomics will result in poor performance. Changing - this option is only useful for debugging or making performance comparisons. - - - @@ -2727,7 +2769,7 @@ ninja install - + Setting this option allows you to override the value of all @@ -3131,9 +3173,13 @@ ninja install - Enable test suites which require special software to run. This option - accepts arguments via a whitespace-separated list. See for details. + Enable additional test suites, which are not run by default because + they are not secure to run on a multiuser system, require special + software to run, or are resource intensive. The argument is a + whitespace-separated list of tests to enable. See + for details. If the + PG_TEST_EXTRA environment variable is set when the + tests are run, it overrides this setup-time option. @@ -3393,9 +3439,6 @@ export MANPATH these CPU architectures: x86, PowerPC, S/390, SPARC, ARM, MIPS, and RISC-V, including big-endian, little-endian, 32-bit, and 64-bit variants where applicable. - It is often - possible to build on an unsupported CPU type by configuring with - , but performance will be poor. @@ -3632,33 +3675,9 @@ xcrun --show-sdk-path PostgreSQL for Windows can be built using MinGW, a Unix-like build - environment for Microsoft operating systems. - The MinGW build procedure uses the normal build system described in - this chapter. - - - - MinGW, the Unix-like build tools, and MSYS, a collection - of Unix tools required to run shell scripts - like configure, can be downloaded - from . Neither is - required to run the resulting binaries; they are needed only for - creating the binaries. - - - - To build 64 bit binaries using MinGW, install the 64 bit tool set - from , put its bin - directory in the PATH, and run - configure with the - --host=x86_64-w64-mingw32 option. - - - - After you have everything installed, it is suggested that you - run psql - under CMD.EXE, as the MSYS console has - buffering issues. + environment for Windows. It is recommended to use the MSYS2 environment for this and also + to install any prerequisite packages. @@ -3782,11 +3801,11 @@ make: *** [postgres] Error 1 - - Visual + + Visual Studio - - Visual + + Visual Studio installation on @@ -3800,8 +3819,8 @@ make: *** [postgres] Error 1 - PostgreSQL for Windows with Visual can be built using meson, as described - in . + PostgreSQL for Windows with Visual Studio can be built using Meson, as + described in . The native Windows port requires a 32 or 64-bit version of Windows 10 or later. @@ -3871,14 +3890,12 @@ make: *** [postgres] Error 1 - ActiveState Perl + Strawberry Perl - ActiveState Perl is required to run the build generation scripts. MinGW + Strawberry Perl is required to run the build generation scripts. MinGW or Cygwin Perl will not work. It must also be present in the PATH. Binaries can be downloaded from - - (Note: version 5.14 or later is required, - the free Standard Distribution is sufficient). + . @@ -3887,38 +3904,10 @@ make: *** [postgres] Error 1 Flex - Bison and Flex are - required. Only Bison versions 2.3 and later - will work. Flex must be version 2.5.35 or later. - - - - Both Bison and Flex - are included in the msys tool suite, available - from as part of the - MinGW compiler suite. - - - - You will need to add the directory containing - flex.exe and bison.exe to the - PATH environment variable. In the case of MinGW, the directory is the - \msys\1.0\bin subdirectory of your MinGW - installation directory. + Binaries for Bison and + Flex can be downloaded from . - - - - The Bison distribution from GnuWin32 appears to have a bug that - causes Bison to malfunction when installed in a directory with - spaces in the name, such as the default location on English - installations C:\Program Files\GnuWin32. - Consider installing into C:\GnuWin32 or use the - NTFS short name path to GnuWin32 in your PATH environment setting - (e.g., C:\PROGRA~1\GnuWin32). - - - @@ -3930,10 +3919,11 @@ make: *** [postgres] Error 1 - ActiveState Tcl + Magicsplat Tcl - Required for building PL/Tcl (Note: version - 8.4 is required, the free Standard Distribution is sufficient). + Required for building PL/Tcl. + Binaries can be downloaded from + . diff --git a/doc/src/sgml/isn.sgml b/doc/src/sgml/isn.sgml index bd7a221f73112..1f08ada621846 100644 --- a/doc/src/sgml/isn.sgml +++ b/doc/src/sgml/isn.sgml @@ -230,7 +230,7 @@ The isn module provides the standard comparison operators, plus B-tree and hash indexing support for all these data types. In - addition there are several specialized functions; shown in . + addition, there are several specialized functions, shown in . In this table, isn means any one of the module's data types. @@ -252,55 +252,78 @@ - isn_weak - isn_weak ( boolean ) - boolean + make_valid + make_valid ( isn ) + isn - Sets the weak input mode, and returns new setting. + Clears the invalid-check-digit flag of the value. - isn_weak () + is_valid + is_valid ( isn ) boolean - Returns the current status of the weak mode. + Checks for the presence of the invalid-check-digit flag. - make_valid - make_valid ( isn ) - isn + isn_weak + isn_weak ( boolean ) + boolean - Validates an invalid number (clears the invalid flag). + Sets the weak input mode, and returns the new setting. + This function is retained for backward compatibility. + The recommended way to set weak mode is via + the isn.weak configuration parameter. - is_valid - is_valid ( isn ) + isn_weak () boolean - Checks for the presence of the invalid flag. + Returns the current status of the weak mode. + This function is retained for backward compatibility. + The recommended way to check weak mode is via + the isn.weak configuration parameter. + - - Weak mode is used to be able to insert invalid data - into a table. Invalid means the check digit is wrong, not that there are - missing numbers. - + + Configuration Parameters + + + + + isn.weak (boolean) + + isn.weak configuration parameter + + + + + isn.weak enables the weak input mode, which allows + ISN input values to be accepted even when their check digit is wrong. + The default is false, which rejects invalid check + digits. + + + + Why would you want to use the weak mode? Well, it could be that @@ -325,9 +348,9 @@ - You can also force the insertion of invalid numbers even when not in the - weak mode, by appending the ! character at the end of the - number. + You can also force the insertion of marked-as-invalid numbers even when not + in the weak mode, by appending the ! character at the + end of the number. @@ -366,11 +389,11 @@ SELECT issn('3251231?'); SELECT ismn('979047213542?'); --Using the weak mode: -SELECT isn_weak(true); +SET isn.weak TO true; INSERT INTO test VALUES('978-0-11-000533-4'); INSERT INTO test VALUES('9780141219307'); INSERT INTO test VALUES('2-205-00876-X'); -SELECT isn_weak(false); +SET isn.weak TO false; SELECT id FROM test WHERE NOT is_valid(id); UPDATE test SET id = make_valid(id) WHERE id = '2-205-00876-X!'; @@ -398,9 +421,9 @@ SELECT isbn13(id) FROM test; - + - + Care was taken during the creation of the algorithms and they diff --git a/doc/src/sgml/jit.sgml b/doc/src/sgml/jit.sgml index 1921557cb826d..44e18bf1a6f04 100644 --- a/doc/src/sgml/jit.sgml +++ b/doc/src/sgml/jit.sgml @@ -148,11 +148,12 @@ =# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------ - Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=0.303..0.303 rows=1 loops=1) - -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.017..0.111 rows=356 loops=1) + Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=0.303..0.303 rows=1.00 loops=1) + Buffers: shared hit=14 + -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.017..0.111 rows=356.00 loops=1) + Buffers: shared hit=14 Planning Time: 0.116 ms Execution Time: 0.365 ms -(4 rows) Given the cost of the plan, it is entirely reasonable that no JIT was used; the cost of JIT would @@ -164,8 +165,10 @@ SET =# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------ - Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=6.049..6.049 rows=1 loops=1) - -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.019..0.052 rows=356 loops=1) + Aggregate (cost=16.27..16.29 rows=1 width=8) (actual time=6.049..6.049 rows=1.00 loops=1) + Buffers: shared hit=14 + -> Seq Scan on pg_class (cost=0.00..15.42 rows=342 width=4) (actual time=0.019..0.052 rows=356.00 loops=1) + Buffers: shared hit=14 Planning Time: 0.133 ms JIT: Functions: 3 diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml index 54648c459c127..206eadb8f7baf 100644 --- a/doc/src/sgml/json.sgml +++ b/doc/src/sgml/json.sgml @@ -584,12 +584,13 @@ SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"'; The btree ordering for jsonb datums is seldom of great interest, but for completeness it is: -Object > Array > Boolean > Number > String > Null +Object > Array > Boolean > Number > String > null Object with n pairs > object with n - 1 pairs Array with n elements > array with n - 1 elements + with the exception that (for historical reasons) an empty top level array sorts less than null. Objects with equal numbers of pairs are compared in the order: key-1, value-1, key-2 ... diff --git a/doc/src/sgml/legal.sgml b/doc/src/sgml/legal.sgml index d6c77f3516b7e..75c1309cf7326 100644 --- a/doc/src/sgml/legal.sgml +++ b/doc/src/sgml/legal.sgml @@ -1,9 +1,9 @@ -2024 +2025 - 1996–2024 + 1996–2025 The PostgreSQL Global Development Group @@ -11,13 +11,15 @@ Legal Notice - PostgreSQL is Copyright © 1996–2024 - by the PostgreSQL Global Development Group. + PostgreSQL Database Management System + (also known as Postgres, formerly known as Postgres95) - Postgres95 is Copyright © 1994–5 - by the Regents of the University of California. + Portions Copyright © 1996-2025, PostgreSQL Global Development Group + + + Portions Copyright © 1994, The Regents of the University of California diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 068ee60771cbf..08bd51219262d 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -378,7 +378,7 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn); At any time during connection, the status of the connection can be checked by calling . If this call returns CONNECTION_BAD, then the - connection procedure has failed; if the call returns CONNECTION_OK, then the + connection procedure has failed; if the call returns CONNECTION_OK, then the connection is ready. Both of these states are equally detectable from the return value of PQconnectPoll, described above. Other states might also occur during (and only during) an asynchronous connection procedure. These @@ -522,7 +522,7 @@ switch(PQstatus(conn)) sequence described in the documentation of . -typedef pg_int64 pg_usec_time_t; +typedef int64_t pg_usec_time_t; int PQsocketPoll(int sock, int forRead, int forWrite, pg_usec_time_t end_time); @@ -545,9 +545,9 @@ int PQsocketPoll(int sock, int forRead, int forWrite, the Unix epoch (that is, time_t times 1 million). Timeout is infinite if end_time is -1. Timeout is immediate (no blocking) if - end_time is 0 (or indeed, any time before now). - Timeout values can be calculated conveniently by adding the desired - number of microseconds to the result of + end_time is 0 (or indeed, any + time before now). Timeout values can be calculated conveniently by + adding the desired number of microseconds to the result of . Note that the underlying system calls may have less than microsecond precision, so that the actual delay may be imprecise. @@ -1341,6 +1341,15 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname The server must request MD5 hashed password authentication. + + + Support for MD5-encrypted passwords is deprecated and will be + removed in a future release of + PostgreSQL. Refer to + for details about migrating to + another password type. + + @@ -1376,6 +1385,15 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname + + oauth + + + The server must request an OAuth bearer token from the client. + + + + none @@ -1830,11 +1848,12 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname direct - start SSL handshake directly after establishing the TCP/IP - connection. This is only allowed with sslmode=require or higher, - because the weaker settings could lead to unintended fallback to - plaintext authentication when the server does not support direct - SSL handshake. + start SSL handshake directly after establishing the TCP/IP + connection. This is only allowed with + sslmode=require or higher, because the weaker + settings could lead to unintended fallback to plaintext + authentication when the server does not support direct SSL + handshake. @@ -1899,6 +1918,30 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname + + sslkeylogfile + + + This parameter specifies the location where libpq + will log keys used in this SSL context. This is useful for debugging + PostgreSQL protocol interactions or client + connections using network inspection tools like + Wireshark. This parameter is ignored if an + SSL connection is not made, or if LibreSSL + is used (LibreSSL does not support key + logging). Keys are logged using the NSS + format. + + + Key logging will expose potentially sensitive information in the + keylog file. Keylog files should be handled with the same care as + files. + + + + + + sslpassword @@ -1913,7 +1956,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname Enter PEM pass phrase: prompt that OpenSSL will emit by default when an encrypted client certificate key is provided to - libpq. + libpq. If the key is not encrypted this parameter is ignored. The parameter @@ -1999,7 +2042,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname The special value system may be specified instead, in - which case the system's trusted CA roots will be loaded. The exact + which case the trusted CA roots from the SSL implementation will be loaded. The exact locations of these root certificates differ by SSL implementation and platform. For OpenSSL in particular, the locations may be further modified by the SSL_CERT_DIR @@ -2143,6 +2186,54 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname + + min_protocol_version + + + Specifies the minimum protocol version to allow for the connection. + The default is to allow any version of the + PostgreSQL protocol supported by libpq, + which currently means 3.0. If the server + does not support at least this protocol version the connection will be + closed. + + + + The current supported values are + 3.0, 3.2, + and latest. The latest value is + equivalent to the latest protocol version supported by the libpq + version being used, which is currently 3.2. + + + + + + max_protocol_version + + + Specifies the protocol version to request from the server. + The default is to use version 3.0 of the + PostgreSQL protocol, unless the connection + string specifies a feature that relies on a higher protocol version, + in which case the latest version supported by libpq is used. If the + server does not support the protocol version requested by the client, + the connection is automatically downgraded to a lower minor protocol + version that the server supports. After the connection attempt has + completed you can use to + find out which exact protocol version was negotiated. + + + + The current supported values are + 3.0, 3.2, + and latest. The latest value is + equivalent to the latest protocol version supported by the libpq + version being used, which is currently 3.2. + + + + krbsrvname @@ -2189,6 +2280,34 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname + + scram_client_key + + + The base64-encoded SCRAM client key. This can be used by foreign-data + wrappers or similar middleware to enable pass-through SCRAM + authentication. See for one such + implementation. It is not meant to be specified directly by users or + client applications. + + + + + + scram_server_key + + + The base64-encoded SCRAM server key. This can be used by foreign-data + wrappers or similar middleware to enable pass-through SCRAM + authentication. See for one such + implementation. It is not meant to be specified directly by users or + client applications. + + + + service @@ -2335,6 +2454,107 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname + + + oauth_issuer + + + The HTTPS URL of a trusted issuer to contact if the server requests an + OAuth token for the connection. This parameter is required for all OAuth + connections; it should exactly match the issuer + setting in the server's HBA configuration. + + + As part of the standard authentication handshake, libpq + will ask the server for a discovery document: a URL + providing a set of OAuth configuration parameters. The server must + provide a URL that is directly constructed from the components of the + oauth_issuer, and this value must exactly match the + issuer identifier that is declared in the discovery document itself, or + the connection will fail. This is required to prevent a class of + + "mix-up attacks" on OAuth clients. + + + You may also explicitly set oauth_issuer to the + /.well-known/ URI used for OAuth discovery. In this + case, if the server asks for a different URL, the connection will fail, + but a custom OAuth flow + may be able to speed up the standard handshake by using previously + cached tokens. (In this case, it is recommended that + be set as well, since the + client will not have a chance to ask the server for a correct scope + setting, and the default scopes for a token may not be sufficient to + connect.) libpq currently supports the + following well-known endpoints: + + /.well-known/openid-configuration + /.well-known/oauth-authorization-server + + + + + Issuers are highly privileged during the OAuth connection handshake. As + a rule of thumb, if you would not trust the operator of a URL to handle + access to your servers, or to impersonate you directly, that URL should + not be trusted as an oauth_issuer. + + + + + + + oauth_client_id + + + An OAuth 2.0 client identifier, as issued by the authorization server. + If the PostgreSQL server + requests an OAuth token for the + connection (and if no custom + OAuth hook is installed to provide one), then this parameter must + be set; otherwise, the connection will fail. + + + + + + oauth_client_secret + + + The client password, if any, to use when contacting the OAuth + authorization server. Whether this parameter is required or not is + determined by the OAuth provider; "public" clients generally do not use + a secret, whereas "confidential" clients generally do. + + + + + + oauth_scope + + + The scope of the access request sent to the authorization server, + specified as a (possibly empty) space-separated list of OAuth scope + identifiers. This parameter is optional and intended for advanced usage. + + + Usually the client will obtain appropriate scope settings from the + PostgreSQL server. If this parameter is used, + the server's requested scope list will be ignored. This can prevent a + less-trusted server from requesting inappropriate access scopes from the + end user. However, if the client's scope setting does not contain the + server's required scopes, the server is likely to reject the issued + token, and the connection will fail. + + + The meaning of an empty scope list is provider-dependent. An OAuth + authorization server may choose to issue a token with "default scope", + whatever that happens to be, or it may reject the token request + entirely. + + + + @@ -2520,6 +2740,26 @@ char *PQport(const PGconn *conn); + + PQservicePQservice + + + + Returns the service of the active connection. + + +char *PQservice(const PGconn *conn); + + + + + returns NULL if the + conn argument is NULL. + Otherwise, if there was no service provided, it returns an empty string. + + + + PQttyPQtty @@ -2571,14 +2811,14 @@ ConnStatusType PQstatus(const PGconn *conn); The status can be one of a number of values. However, only two of these are seen outside of an asynchronous connection procedure: - CONNECTION_OK and - CONNECTION_BAD. A good connection to the database - has the status CONNECTION_OK. A failed + CONNECTION_OK and + CONNECTION_BAD. A good connection to the database + has the status CONNECTION_OK. A failed connection attempt is signaled by status - CONNECTION_BAD. Ordinarily, an OK status will + CONNECTION_BAD. Ordinarily, an OK status will remain so until , but a communications failure might result in the status changing to - CONNECTION_BAD prematurely. In that case the + CONNECTION_BAD prematurely. In that case the application could try to recover by calling . @@ -2643,6 +2883,7 @@ const char *PQparameterStatus(const PGconn *conn, const char *paramName); IntervalStyle is_superuser scram_iterations + search_path server_encoding server_version session_authorization @@ -2652,7 +2893,8 @@ const char *PQparameterStatus(const PGconn *conn, const char *paramName); (default_transaction_read_only and in_hot_standby were not reported by releases before 14; scram_iterations was not reported by releases - before 16.) + before 16; search_path was not reported by releases + before 18.) Note that server_version, server_encoding and @@ -2676,22 +2918,44 @@ const char *PQparameterStatus(const PGconn *conn, const char *paramName); + + PQfullProtocolVersionPQfullProtocolVersion + + + + Interrogates the frontend/backend protocol being used. + +int PQfullProtocolVersion(const PGconn *conn); + + Applications might wish to use this function to determine whether certain + features are supported. The result is formed by multiplying the server's + major version number by 10000 and adding the minor version number. For + example, version 3.2 would be returned as 30002, and version 4.0 would + be returned as 40000. Zero is returned if the connection is bad. The 3.0 + protocol is supported by PostgreSQL server + versions 7.4 and above. + + + The protocol version will not change after connection startup is + complete, but it could theoretically change during a connection reset. + + + + PQprotocolVersionPQprotocolVersion - Interrogates the frontend/backend protocol being used. + Interrogates the frontend/backend protocol major version. int PQprotocolVersion(const PGconn *conn); - Applications might wish to use this function to determine whether certain - features are supported. Currently, the possible values are 3 - (3.0 protocol), or zero (connection bad). The protocol version will - not change after connection startup is complete, but it could - theoretically change during a connection reset. The 3.0 protocol is - supported by PostgreSQL server versions 7.4 - and above. + Unlike , this returns only + the major protocol version in use, but it is supported by a wider range + of libpq releases back to version 7.4. Currently, the possible values are + 3 (3.0 protocol), or zero (connection bad). Prior to release version + 14.0, libpq could additionally return 2 (2.0 protocol). @@ -5070,7 +5334,7 @@ unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length); , , , - + , , and respectively. @@ -5310,7 +5574,7 @@ PGresult *PQgetResult(PGconn *conn); PGRES_PIPELINE_SYNC will be returned. The result of the next query after the synchronization point follows immediately (that is, no null pointer is returned after - the synchronization point.) + the synchronization point). @@ -6364,7 +6628,7 @@ PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn); checked by calling . If this call returns CONNECTION_BAD, then the cancel procedure has failed; if the call returns - CONNECTION_OK, then cancel request was + CONNECTION_OK, then cancel request was successfully dispatched. Both of these states are equally detectable from the return value of PQcancelPoll, described above. @@ -6486,15 +6750,15 @@ ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn); The status can be one of a number of values. However, only three of these are seen outside of an asynchronous cancel procedure: - CONNECTION_ALLOCATED, - CONNECTION_OK and - CONNECTION_BAD. The initial state of a + CONNECTION_ALLOCATED, + CONNECTION_OK and + CONNECTION_BAD. The initial state of a PGcancelConn that's successfully created using - is CONNECTION_ALLOCATED. + is CONNECTION_ALLOCATED. A cancel request that was successfully dispatched - has the status CONNECTION_OK. A failed + has the status CONNECTION_OK. A failed cancel attempt is signaled by status - CONNECTION_BAD. An OK status will + CONNECTION_BAD. An OK status will remain so until or is called. @@ -7357,8 +7621,9 @@ int PQputline(PGconn *conn, \. as a final line to indicate to the server that it had finished sending COPY data. While this still works, it is deprecated and the special meaning of \. can be expected to be removed in a - future release. It is sufficient to call after - having sent the actual data. + future release. (It already will misbehave in CSV + mode.) It is sufficient to call + after having sent the actual data. @@ -8018,7 +8283,7 @@ size_t PQresultMemorySize(const PGresult *res); - Return the version of libpq that is being used. + Return the version of libpq that is being used. int PQlibVersion(void); @@ -8269,7 +8534,7 @@ typedef struct evtInfo pointer should be cast to a PGEventRegister *. This structure contains a PGconn that should be in the - CONNECTION_OK status; guaranteed if one calls + CONNECTION_OK status; guaranteed if one calls right after obtaining a good PGconn. When returning a failure code, all cleanup must be performed as no PGEVT_CONNDESTROY @@ -9136,6 +9401,26 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) linkend="libpq-connect-load-balance-hosts"/> connection parameter. + + + + + PGMINPROTOCOLVERSION + + PGMINPROTOCOLVERSION behaves the same as the connection parameter. + + + + + + + PGMAXPROTOCOLVERSION + + PGMAXPROTOCOLVERSION behaves the same as the connection parameter. + + @@ -9230,7 +9515,9 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) The file .pgpass in a user's home directory can contain passwords to be used if the connection requires a password (and no password has been - specified otherwise). On Microsoft Windows the file is named + specified otherwise). On Unix systems, the directory can be specified by + the HOME environment variable, or if undefined, the home + directory of the effective user. On Microsoft Windows the file is named %APPDATA%\postgresql\pgpass.conf (where %APPDATA% refers to the Application Data subdirectory in the user's profile). @@ -9293,7 +9580,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) The connection service file allows libpq connection parameters to be associated with a single service name. That service name can then be - specified in a libpq connection string, and the associated settings will be + specified using the service key word + in a libpq connection string, and the associated settings will be used. This allows connection parameters to be modified without requiring a recompile of the libpq-using application. The service name can also be specified using the PGSERVICE environment variable. @@ -9556,7 +9844,7 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) For backwards compatibility with earlier versions of PostgreSQL, if a root CA file exists, the behavior of - sslmode=require will be the same + sslmode=require will be the same as that of verify-ca, meaning the server certificate is validated against the CA. Relying on this behavior is discouraged, and applications that need certificate validation should always use @@ -9863,9 +10151,11 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) SSL Library Initialization - If your application initializes libssl and/or - libcrypto libraries and libpq - is built with SSL support, you should call + Applications which need to be compatible with older versions of + PostgreSQL, using OpenSSL + version 1.0.2 or older, need to initialize the SSL library before using it. + Applications which initialize libssl and/or + libcrypto libraries should call to tell libpq that the libssl and/or libcrypto libraries have been initialized by your application, so that @@ -9873,6 +10163,10 @@ ldap://ldap.acme.com/cn=dbserver,cn=hosts?pgconnectinfo?base?(objectclass=*) However, this is unnecessary when using OpenSSL version 1.1.0 or later, as duplicate initializations are no longer problematic. + + Refer to the documentation for the version of PostgreSQL + that you are targeting for details on their use. + @@ -9888,21 +10182,8 @@ void PQinitOpenSSL(int do_ssl, int do_crypto); - When do_ssl is non-zero, libpq - will initialize the OpenSSL library before first - opening a database connection. When do_crypto is - non-zero, the libcrypto library will be initialized. By - default (if is not called), both libraries - are initialized. When SSL support is not compiled in, this function is - present but does nothing. - - - - If your application uses and initializes either OpenSSL - or its underlying libcrypto library, you must - call this function with zeroes for the appropriate parameter(s) - before first opening a database connection. Also be sure that you - have done that initialization before opening a database connection. + This function is deprecated and only present for backwards compatibility, + it does nothing. @@ -9919,11 +10200,14 @@ void PQinitSSL(int do_ssl); This function is equivalent to PQinitOpenSSL(do_ssl, do_ssl). - It is sufficient for applications that initialize both or neither - of OpenSSL and libcrypto. + This function is deprecated and only present for backwards compatibility, + it does nothing. + and + are maintained for backwards compatibility, but are no longer required + since PostgreSQL 18. has been present since PostgreSQL 8.0, while was added in PostgreSQL 8.4, so @@ -9938,6 +10222,343 @@ void PQinitSSL(int do_ssl); + + OAuth Support + + + libpq implements support for the OAuth v2 Device Authorization client flow, + documented in + RFC 8628, + as an optional module. See the + installation documentation for information on how to enable support + for Device Authorization as a builtin flow. + + + When support is enabled and the optional module installed, libpq + will use the builtin flow by default if the server + requests a bearer token during + authentication. This flow can be utilized even if the system running the + client application does not have a usable web browser, for example when + running a client via SSH. + + + The builtin flow will, by default, print a URL to visit and a user code to + enter there: + +$ psql 'dbname=postgres oauth_issuer=https://example.com oauth_client_id=...' +Visit https://example.com/device and enter the code: ABCD-EFGH + + (This prompt may be + customized.) + The user will then log into their OAuth provider, which will ask whether + to allow libpq and the server to perform actions on their behalf. It is always + a good idea to carefully review the URL and permissions displayed, to ensure + they match expectations, before continuing. Permissions should not be given + to untrusted third parties. + + + Client applications may implement their own flows to customize interaction + and integration with applications. See + for more information on how add a custom flow to libpq. + + + For an OAuth client flow to be usable, the connection string must at minimum + contain and + . (These settings are + determined by your organization's OAuth provider.) The builtin flow + additionally requires the OAuth authorization server to publish a device + authorization endpoint. + + + + + The builtin Device Authorization flow is not currently supported on Windows. + Custom client flows may still be implemented. + + + + + Authdata Hooks + + + The behavior of the OAuth flow may be modified or replaced by a client using + the following hook API: + + + + PQsetAuthDataHookPQsetAuthDataHook + + + + Sets the PGauthDataHook, overriding + libpq's handling of one or more aspects of + its OAuth client flow. + +void PQsetAuthDataHook(PQauthDataHook_type hook); + + If hook is NULL, the + default handler will be reinstalled. Otherwise, the application passes + a pointer to a callback function with the signature: + +int hook_fn(PGauthData type, PGconn *conn, void *data); + + which libpq will call when an action is + required of the application. type describes + the request being made, conn is the + connection handle being authenticated, and data + points to request-specific metadata. The contents of this pointer are + determined by type; see + for the supported + list. + + + Hooks can be chained together to allow cooperative and/or fallback + behavior. In general, a hook implementation should examine the incoming + type (and, potentially, the request metadata + and/or the settings for the particular conn + in use) to decide whether or not to handle a specific piece of authdata. + If not, it should delegate to the previous hook in the chain + (retrievable via PQgetAuthDataHook). + + + Success is indicated by returning an integer greater than zero. + Returning a negative integer signals an error condition and abandons the + connection attempt. (A zero value is reserved for the default + implementation.) + + + + + + PQgetAuthDataHookPQgetAuthDataHook + + + + Retrieves the current value of PGauthDataHook. + +PQauthDataHook_type PQgetAuthDataHook(void); + + At initialization time (before the first call to + PQsetAuthDataHook), this function will return + PQdefaultAuthDataHook. + + + + + + + + Hook Types + + The following PGauthData types and their corresponding + data structures are defined: + + + + + PQAUTHDATA_PROMPT_OAUTH_DEVICE + PQAUTHDATA_PROMPT_OAUTH_DEVICE + + + + Replaces the default user prompt during the builtin device + authorization client flow. data points to + an instance of PGpromptOAuthDevice: + +typedef struct _PGpromptOAuthDevice +{ + const char *verification_uri; /* verification URI to visit */ + const char *user_code; /* user code to enter */ + const char *verification_uri_complete; /* optional combination of URI and + * code, or NULL */ + int expires_in; /* seconds until user code expires */ +} PGpromptOAuthDevice; + + + + The OAuth Device Authorization flow which + can be included + in libpq + requires the end user to visit a URL with a browser, then enter a code + which permits libpq to connect to the server + on their behalf. The default prompt simply prints the + verification_uri and user_code + on standard error. Replacement implementations may display this + information using any preferred method, for example with a GUI. + + + This callback is only invoked during the builtin device + authorization flow. If the application installs a + custom OAuth + flow, or libpq was not built with + support for the builtin flow, this authdata type will not be used. + + + If a non-NULL verification_uri_complete is + provided, it may optionally be used for non-textual verification (for + example, by displaying a QR code). The URL and user code should still + be displayed to the end user in this case, because the code will be + manually confirmed by the provider, and the URL lets users continue + even if they can't use the non-textual method. For more information, + see section 3.3.1 in + RFC 8628. + + + + + + + PQAUTHDATA_OAUTH_BEARER_TOKEN + PQAUTHDATA_OAUTH_BEARER_TOKEN + + + + Adds a custom implementation of a flow, replacing the builtin flow if + it is installed. + The hook should either directly return a Bearer token for the current + user/issuer/scope combination, if one is available without blocking, or + else set up an asynchronous callback to retrieve one. + + + data points to an instance + of PGoauthBearerRequest, which should be filled in + by the implementation: + +typedef struct PGoauthBearerRequest +{ + /* Hook inputs (constant across all calls) */ + const char *openid_configuration; /* OIDC discovery URL */ + const char *scope; /* required scope(s), or NULL */ + + /* Hook outputs */ + + /* Callback implementing a custom asynchronous OAuth flow. */ + PostgresPollingStatusType (*async) (PGconn *conn, + struct PGoauthBearerRequest *request, + SOCKTYPE *altsock); + + /* Callback to clean up custom allocations. */ + void (*cleanup) (PGconn *conn, struct PGoauthBearerRequest *request); + + char *token; /* acquired Bearer token */ + void *user; /* hook-defined allocated data */ +} PGoauthBearerRequest; + + + + Two pieces of information are provided to the hook by + libpq: + openid_configuration contains the URL of an + OAuth discovery document describing the authorization server's + supported flows, and scope contains a + (possibly empty) space-separated list of OAuth scopes which are + required to access the server. Either or both may be + NULL to indicate that the information was not + discoverable. (In this case, implementations may be able to establish + the requirements using some other preconfigured knowledge, or they may + choose to fail.) + + + The final output of the hook is token, which + must point to a valid Bearer token for use on the connection. (This + token should be issued by the + and hold the requested + scopes, or the connection will be rejected by the server's validator + module.) The allocated token string must remain valid until + libpq is finished connecting; the hook + should set a cleanup callback which will be + called when libpq no longer requires it. + + + If an implementation cannot immediately produce a + token during the initial call to the hook, + it should set the async callback to handle + nonblocking communication with the authorization server. + + + Performing blocking operations during the + PQAUTHDATA_OAUTH_BEARER_TOKEN hook callback will + interfere with nonblocking connection APIs such as + PQconnectPoll and prevent concurrent connections + from making progress. Applications which only ever use the + synchronous connection primitives, such as + PQconnectdb, may synchronously retrieve a token + during the hook instead of implementing the + async callback, but they will necessarily + be limited to one connection at a time. + + + This will be called to begin the flow immediately upon return from the + hook. When the callback cannot make further progress without blocking, + it should return either PGRES_POLLING_READING or + PGRES_POLLING_WRITING after setting + *pgsocket to the file descriptor that will be marked + ready to read/write when progress can be made again. (This descriptor + is then provided to the top-level polling loop via + PQsocket().) Return PGRES_POLLING_OK + after setting token when the flow is + complete, or PGRES_POLLING_FAILED to indicate failure. + + + Implementations may wish to store additional data for bookkeeping + across calls to the async and + cleanup callbacks. The + user pointer is provided for this purpose; + libpq will not touch its contents and the + application may use it at its convenience. (Remember to free any + allocations during token cleanup.) + + + + + + + + + + Debugging and Developer Settings + + + A "dangerous debugging mode" may be enabled by setting the environment + variable PGOAUTHDEBUG=UNSAFE. This functionality is provided + for ease of local development and testing only. It does several things that + you will not want a production system to do: + + + + + permits the use of unencrypted HTTP during the OAuth provider exchange + + + + + allows the system's trusted CA list to be completely replaced using the + PGOAUTHCAFILE environment variable + + + + + prints HTTP traffic (containing several critical secrets) to standard + error during the OAuth flow + + + + + permits the use of zero-second retry intervals, which can cause the + client to busy-loop and pointlessly consume CPU + + + + + + + Do not share the output of the OAuth flow traffic with third parties. It + contains secrets that can be used to attack your clients and servers. + + + + + Behavior in Threaded Programs @@ -10010,6 +10631,18 @@ int PQisthreadsafe(); libpq source code for a way to do cooperative locking between libpq and your application. + + + Similarly, if you are using Curl inside your application, + and you do not already + initialize + libcurl globally before starting new threads, you will need to + cooperatively lock (again via PQregisterThreadLock) + around any code that may initialize libcurl. This restriction is lifted for + more recent versions of Curl that are built to support thread-safe + initialization; those builds can be identified by the advertisement of a + threadsafe feature in their version metadata. + diff --git a/doc/src/sgml/limits.sgml b/doc/src/sgml/limits.sgml index c549447013fd5..f26f4466719a5 100644 --- a/doc/src/sgml/limits.sgml +++ b/doc/src/sgml/limits.sgml @@ -135,4 +135,15 @@ created tuples are internally marked as null in the tuple's null bitmap, the null bitmap also occupies space. + + + Each table can store a theoretical maximum of 2^32 out-of-line values; see + for a detailed discussion of out-of-line + storage. This limit arises from the use of a 32-bit OID to identify each + such value. The practical limit is significantly less than the theoretical + limit, because as the OID space fills up, finding an OID that is still free + can become expensive, in turn slowing down INSERT/UPDATE statements. + Typically, this is only an issue for tables containing many terabytes + of data; partitioning is a possible workaround. + diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml index 2b725c3c18240..79731c6553f31 100644 --- a/doc/src/sgml/lobj.sgml +++ b/doc/src/sgml/lobj.sgml @@ -398,7 +398,7 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence); When dealing with large objects that might exceed 2GB in size, instead use -pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence); +int64_t lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence); This function has the same behavior as lo_lseek, but it can accept an @@ -434,7 +434,7 @@ int lo_tell(PGconn *conn, int fd); When dealing with large objects that might exceed 2GB in size, instead use -pg_int64 lo_tell64(PGconn *conn, int fd); +int64_t lo_tell64(PGconn *conn, int fd); This function has the same behavior as lo_tell, but it can deliver a result larger @@ -485,7 +485,7 @@ int lo_truncate(PGconn *conn, int fd, size_t len); When dealing with large objects that might exceed 2GB in size, instead use -int lo_truncate64(PGconn *conn, int fd, pg_int64 len); +int lo_truncate64(PGconn *conn, int fd, int64_t len); This function has the same behavior as lo_truncate, but it can accept a @@ -725,7 +725,7 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image * testlo.c * test using large objects with libpq * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml index a23a3d57e2b47..c32e6bc000d4d 100644 --- a/doc/src/sgml/logical-replication.sgml +++ b/doc/src/sgml/logical-replication.sgml @@ -24,10 +24,11 @@ - Logical replication of a table typically starts with taking a snapshot - of the data on the publisher database and copying that to the subscriber. - Once that is done, the changes on the publisher are sent to the subscriber - as they occur in real-time. The subscriber applies the data in the same + When logical replication of a table typically starts, PostgreSQL takes + a snapshot of the table's data on the publisher database and copies it + to the subscriber. Once complete, changes on the publisher since the + initial copy are sent continually to the subscriber. The subscriber + applies the data in the same order as the publisher so that transactional consistency is guaranteed for publications within a single subscription. This method of data replication is sometimes referred to as transactional replication. @@ -123,35 +124,6 @@ TRUNCATE. See ). - - A published table must have a replica identity configured in - order to be able to replicate UPDATE - and DELETE operations, so that appropriate rows to - update or delete can be identified on the subscriber side. By default, - this is the primary key, if there is one. Another unique index (with - certain additional requirements) can also be set to be the replica - identity. If the table does not have any suitable key, then it can be set - to replica identity FULL, which means the entire row becomes - the key. When replica identity FULL is specified, - indexes can be used on the subscriber side for searching the rows. Candidate - indexes must be btree or hash, non-partial, and the leftmost index field must - be a column (not an expression) that references the published table column. - These restrictions on the non-unique index properties adhere to some of the - restrictions that are enforced for primary keys. If there are no such - suitable indexes, the search on the subscriber side can be very inefficient, - therefore replica identity FULL should only be used as a - fallback if no other solution is possible. If a replica identity other - than FULL is set on the publisher side, a replica identity - comprising the same or fewer columns must also be set on the subscriber - side. See for details on - how to set the replica identity. If a table without a replica identity is - added to a publication that replicates UPDATE - or DELETE operations then - subsequent UPDATE or DELETE - operations will cause an error on the publisher. INSERT - operations can proceed regardless of any replica identity. - - Every publication can have multiple subscribers. @@ -165,9 +137,62 @@ The individual tables can be added and removed dynamically using ALTER PUBLICATION. Both the ADD TABLE and DROP TABLE operations are - transactional; so the table will start or stop replicating at the correct + transactional, so the table will start or stop replicating at the correct snapshot once the transaction has committed. + + + Replica Identity + + + A published table must have a replica identity + configured in order to be able to replicate UPDATE + and DELETE operations, so that appropriate rows to + update or delete can be identified on the subscriber side. + + + + By default, this is the primary key, if there is one. Another unique index + (with certain additional requirements) can also be set to be the replica + identity. If the table does not have any suitable key, then it can be set + to replica identity FULL, which means the entire row + becomes the key. When replica identity FULL is + specified, indexes can be used on the subscriber side for searching the + rows. Candidate indexes must be btree or hash, non-partial, and the + leftmost index field must be a column (not an expression) that references + the published table column. These restrictions on the non-unique index + properties adhere to some of the restrictions that are enforced for + primary keys. If there are no such suitable indexes, the search on the + subscriber side can be very inefficient, therefore replica identity + FULL should only be used as a fallback if no other + solution is possible. + + + + If a replica identity other than FULL is set on the + publisher side, a replica identity comprising the same or fewer columns + must also be set on the subscriber side. + + + + Tables with a replica identity defined as NOTHING, + DEFAULT without a primary key, or USING + INDEX with a dropped index, cannot support + UPDATE or DELETE operations when + included in a publication replicating these actions. Attempting such + operations will result in an error on the publisher. + + + + INSERT operations can proceed regardless of any replica identity. + + + + See ALTER TABLE...REPLICA IDENTITY + for details on how to set the replica identity. + + +
@@ -338,34 +363,25 @@ Create some test tables on the publisher. -test_pub=# CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); -CREATE TABLE -test_pub=# CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); -CREATE TABLE -test_pub=# CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); -CREATE TABLE +/* pub # */ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); +/* pub # */ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); +/* pub # */ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Create the same tables on the subscriber. -test_sub=# CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); -CREATE TABLE -test_sub=# CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); -CREATE TABLE -test_sub=# CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); -CREATE TABLE +/* sub # */ CREATE TABLE t1(a int, b text, PRIMARY KEY(a)); +/* sub # */ CREATE TABLE t2(c int, d text, PRIMARY KEY(c)); +/* sub # */ CREATE TABLE t3(e int, f text, PRIMARY KEY(e)); Insert data to the tables at the publisher side. -test_pub=# INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); -INSERT 0 3 -test_pub=# INSERT INTO t2 VALUES (1, 'A'), (2, 'B'), (3, 'C'); -INSERT 0 3 -test_pub=# INSERT INTO t3 VALUES (1, 'i'), (2, 'ii'), (3, 'iii'); -INSERT 0 3 +/* pub # */ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); +/* pub # */ INSERT INTO t2 VALUES (1, 'A'), (2, 'B'), (3, 'C'); +/* pub # */ INSERT INTO t3 VALUES (1, 'i'), (2, 'ii'), (3, 'iii'); @@ -374,41 +390,34 @@ INSERT 0 3 publish operations. The publication pub3b has a row filter (see ). - -test_pub=# CREATE PUBLICATION pub1 FOR TABLE t1; -CREATE PUBLICATION -test_pub=# CREATE PUBLICATION pub2 FOR TABLE t2 WITH (publish = 'truncate'); -CREATE PUBLICATION -test_pub=# CREATE PUBLICATION pub3a FOR TABLE t3 WITH (publish = 'truncate'); -CREATE PUBLICATION -test_pub=# CREATE PUBLICATION pub3b FOR TABLE t3 WHERE (e > 5); -CREATE PUBLICATION - + 5); +]]> Create subscriptions for the publications. The subscription sub3 subscribes to both pub3a and pub3b. All subscriptions will copy initial data by default. -test_sub=# CREATE SUBSCRIPTION sub1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub1' -test_sub-# PUBLICATION pub1; -CREATE SUBSCRIPTION -test_sub=# CREATE SUBSCRIPTION sub2 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub2' -test_sub-# PUBLICATION pub2; -CREATE SUBSCRIPTION -test_sub=# CREATE SUBSCRIPTION sub3 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=sub3' -test_sub-# PUBLICATION pub3a, pub3b; -CREATE SUBSCRIPTION +/* sub # */ CREATE SUBSCRIPTION sub1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=sub1' +/* sub - */ PUBLICATION pub1; +/* sub # */ CREATE SUBSCRIPTION sub2 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=sub2' +/* sub - */ PUBLICATION pub2; +/* sub # */ CREATE SUBSCRIPTION sub3 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=sub3' +/* sub - */ PUBLICATION pub3a, pub3b; Observe that initial table data is copied, regardless of the publish operation of the publication. -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b ---+------- 1 | one @@ -416,7 +425,7 @@ test_sub=# SELECT * FROM t1; 3 | three (3 rows) -test_sub=# SELECT * FROM t2; +/* sub # */ SELECT * FROM t2; c | d ---+--- 1 | A @@ -431,7 +440,7 @@ test_sub=# SELECT * FROM t2; it means the copied table t3 contains all rows even when they do not match the row filter of publication pub3b. -test_sub=# SELECT * FROM t3; +/* sub # */ SELECT * FROM t3; e | f ---+----- 1 | i @@ -443,18 +452,15 @@ test_sub=# SELECT * FROM t3; Insert more data to the tables at the publisher side. -test_pub=# INSERT INTO t1 VALUES (4, 'four'), (5, 'five'), (6, 'six'); -INSERT 0 3 -test_pub=# INSERT INTO t2 VALUES (4, 'D'), (5, 'E'), (6, 'F'); -INSERT 0 3 -test_pub=# INSERT INTO t3 VALUES (4, 'iv'), (5, 'v'), (6, 'vi'); -INSERT 0 3 +/* pub # */ INSERT INTO t1 VALUES (4, 'four'), (5, 'five'), (6, 'six'); +/* pub # */ INSERT INTO t2 VALUES (4, 'D'), (5, 'E'), (6, 'F'); +/* pub # */ INSERT INTO t3 VALUES (4, 'iv'), (5, 'v'), (6, 'vi'); Now the publisher side data looks like: -test_pub=# SELECT * FROM t1; +/* pub # */ SELECT * FROM t1; a | b ---+------- 1 | one @@ -465,7 +471,7 @@ test_pub=# SELECT * FROM t1; 6 | six (6 rows) -test_pub=# SELECT * FROM t2; +/* pub # */ SELECT * FROM t2; c | d ---+--- 1 | A @@ -476,7 +482,7 @@ test_pub=# SELECT * FROM t2; 6 | F (6 rows) -test_pub=# SELECT * FROM t3; +/* pub # */ SELECT * FROM t3; e | f ---+----- 1 | i @@ -496,7 +502,7 @@ test_pub=# SELECT * FROM t3; only replicate data that matches the row filter of pub3b. Now the subscriber side data looks like: -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b ---+------- 1 | one @@ -507,7 +513,7 @@ test_sub=# SELECT * FROM t1; 6 | six (6 rows) -test_sub=# SELECT * FROM t2; +/* sub # */ SELECT * FROM t2; c | d ---+--- 1 | A @@ -515,7 +521,7 @@ test_sub=# SELECT * FROM t2; 3 | C (3 rows) -test_sub=# SELECT * FROM t3; +/* sub # */ SELECT * FROM t3; e | f ---+----- 1 | i @@ -542,8 +548,7 @@ test_sub=# SELECT * FROM t3; First, create a publication for the examples to use. -test_pub=# CREATE PUBLICATION pub1 FOR ALL TABLES; -CREATE PUBLICATION +/* pub # */ CREATE PUBLICATION pub1 FOR ALL TABLES; Example 1: Where the subscription says connect = false @@ -554,13 +559,12 @@ CREATE PUBLICATION Create the subscription. -test_sub=# CREATE SUBSCRIPTION sub1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub' -test_sub-# PUBLICATION pub1 -test_sub-# WITH (connect=false); +/* sub # */ CREATE SUBSCRIPTION sub1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub' +/* sub - */ PUBLICATION pub1 +/* sub - */ WITH (connect=false); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. -CREATE SUBSCRIPTION @@ -569,7 +573,7 @@ CREATE SUBSCRIPTION specified during CREATE SUBSCRIPTION, the name of the slot to create is same as the subscription name, e.g. "sub1". -test_pub=# SELECT * FROM pg_create_logical_replication_slot('sub1', 'pgoutput'); +/* pub # */ SELECT * FROM pg_create_logical_replication_slot('sub1', 'pgoutput'); slot_name | lsn -----------+----------- sub1 | 0/19404D0 @@ -581,10 +585,8 @@ test_pub=# SELECT * FROM pg_create_logical_replication_slot('sub1', 'pgoutput'); On the subscriber, complete the activation of the subscription. After this the tables of pub1 will start replicating. -test_sub=# ALTER SUBSCRIPTION sub1 ENABLE; -ALTER SUBSCRIPTION -test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; -ALTER SUBSCRIPTION +/* sub # */ ALTER SUBSCRIPTION sub1 ENABLE; +/* sub # */ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; @@ -600,13 +602,12 @@ ALTER SUBSCRIPTION Create the subscription. -test_sub=# CREATE SUBSCRIPTION sub1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub' -test_sub-# PUBLICATION pub1 -test_sub-# WITH (connect=false, slot_name='myslot'); +/* sub # */ CREATE SUBSCRIPTION sub1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub' +/* sub - */ PUBLICATION pub1 +/* sub - */ WITH (connect=false, slot_name='myslot'); WARNING: subscription was created, but is not connected HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription. -CREATE SUBSCRIPTION @@ -614,7 +615,7 @@ CREATE SUBSCRIPTION On the publisher, manually create a slot using the same name that was specified during CREATE SUBSCRIPTION, e.g. "myslot". -test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput'); +/* pub # */ SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput'); slot_name | lsn -----------+----------- myslot | 0/19059A0 @@ -626,10 +627,8 @@ test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput' On the subscriber, the remaining subscription activation steps are the same as before. -test_sub=# ALTER SUBSCRIPTION sub1 ENABLE; -ALTER SUBSCRIPTION -test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; -ALTER SUBSCRIPTION +/* sub # */ ALTER SUBSCRIPTION sub1 ENABLE; +/* sub # */ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; @@ -644,18 +643,17 @@ ALTER SUBSCRIPTION enabled = false, and create_slot = false are also needed. -test_sub=# CREATE SUBSCRIPTION sub1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub' -test_sub-# PUBLICATION pub1 -test_sub-# WITH (slot_name=NONE, enabled=false, create_slot=false); -CREATE SUBSCRIPTION +/* sub # */ CREATE SUBSCRIPTION sub1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub' +/* sub - */ PUBLICATION pub1 +/* sub - */ WITH (slot_name=NONE, enabled=false, create_slot=false); On the publisher, manually create a slot using any name, e.g. "myslot". -test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput'); +/* pub # */ SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput'); slot_name | lsn -----------+----------- myslot | 0/1905930 @@ -667,18 +665,15 @@ test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput' On the subscriber, associate the subscription with the slot name just created. -test_sub=# ALTER SUBSCRIPTION sub1 SET (slot_name='myslot'); -ALTER SUBSCRIPTION +/* sub # */ ALTER SUBSCRIPTION sub1 SET (slot_name='myslot'); The remaining subscription activation steps are same as before. -test_sub=# ALTER SUBSCRIPTION sub1 ENABLE; -ALTER SUBSCRIPTION -test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; -ALTER SUBSCRIPTION +/* sub # */ ALTER SUBSCRIPTION sub1 ENABLE; +/* sub # */ ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION; @@ -701,10 +696,7 @@ ALTER SUBSCRIPTION failover parameter ensures a seamless transition of those subscriptions after the standby is promoted. They can continue subscribing to publications on the - new primary server without losing data. Note that in the case of - asynchronous replication, there remains a risk of data loss for transactions - committed on the former primary server but have yet to be replicated to the new - primary server. + new primary server. @@ -730,7 +722,7 @@ ALTER SUBSCRIPTION will return the relevant replication slots associated with the failover-enabled subscriptions. -test_sub=# SELECT +/* sub # */ SELECT array_agg(quote_literal(s.subslotname)) AS slots FROM pg_subscription s WHERE s.subfailover AND @@ -753,7 +745,7 @@ test_sub=# SELECT as they will either be dropped or re-created on the new primary server in those cases. -test_sub=# SELECT +/* sub # */ SELECT array_agg(quote_literal(slot_name)) AS slots FROM ( @@ -772,7 +764,7 @@ test_sub=# SELECT Check that the logical replication slots identified above exist on the standby server and are ready for failover. -test_standby=# SELECT slot_name, (synced AND NOT temporary AND NOT conflicting) AS failover_ready +/* standby # */ SELECT slot_name, (synced AND NOT temporary AND NOT conflicting) AS failover_ready FROM pg_replication_slots WHERE slot_name IN ('sub1','sub2','sub3', 'pg_16394_sync_16385_7394666715149055164'); @@ -791,7 +783,7 @@ test_standby=# SELECT slot_name, (synced AND NOT temporary AND NOT conflicting) If all the slots are present on the standby server and the result (failover_ready) of the above SQL query is true, then existing subscriptions can continue subscribing to publications now on the - new primary server without losing data. + new primary server. @@ -1002,12 +994,9 @@ test_standby=# SELECT slot_name, (synced AND NOT temporary AND NOT conflicting) Create some tables to be used in the following examples. -test_pub=# CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c)); -CREATE TABLE -test_pub=# CREATE TABLE t2(d int, e int, f int, PRIMARY KEY(d)); -CREATE TABLE -test_pub=# CREATE TABLE t3(g int, h int, i int, PRIMARY KEY(g)); -CREATE TABLE +/* pub # */ CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c)); +/* pub # */ CREATE TABLE t2(d int, e int, f int, PRIMARY KEY(d)); +/* pub # */ CREATE TABLE t3(g int, h int, i int, PRIMARY KEY(g)); @@ -1016,43 +1005,40 @@ CREATE TABLE p2 has two tables. Table t1 has no row filter, and table t2 has a row filter. Publication p3 has two tables, and both of them have a row filter. - -test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 WHERE (a > 5 AND c = 'NSW'); -CREATE PUBLICATION -test_pub=# CREATE PUBLICATION p2 FOR TABLE t1, t2 WHERE (e = 99); -CREATE PUBLICATION -test_pub=# CREATE PUBLICATION p3 FOR TABLE t2 WHERE (d = 10), t3 WHERE (g = 10); -CREATE PUBLICATION - + 5 AND c = 'NSW'); +/* pub # */ CREATE PUBLICATION p2 FOR TABLE t1, t2 WHERE (e = 99); +/* pub # */ CREATE PUBLICATION p3 FOR TABLE t2 WHERE (d = 10), t3 WHERE (g = 10); +]]> psql can be used to show the row filter expressions (if defined) for each publication. - -test_pub=# \dRp+ - Publication p1 + 5) AND (c = 'NSW'::text)) + "public.t1" WHERE ((a > 5) AND (c = 'NSW'::text)) - Publication p2 + Publication p2 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- postgres | f | t | t | t | t | f Tables: - "public.t1" - "public.t2" WHERE (e = 99) + "public.t1" + "public.t2" WHERE (e = 99) - Publication p3 + Publication p3 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- postgres | f | t | t | t | t | f Tables: - "public.t2" WHERE (d = 10) - "public.t3" WHERE (g = 10) - + "public.t2" WHERE (d = 10) + "public.t3" WHERE (g = 10) +]]> psql can be used to show the row filter expressions (if @@ -1060,8 +1046,8 @@ Tables: of two publications, but has a row filter only in p1. See that table t2 is a member of two publications, and has a different row filter in each of them. - -test_pub=# \d t1 + 5) AND (c = 'NSW'::text)) "p2" -test_pub=# \d t2 +/* pub # */ \d t2 Table "public.t2" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- @@ -1087,7 +1073,7 @@ Publications: "p2" WHERE (e = 99) "p3" WHERE (d = 10) -test_pub=# \d t3 +/* pub # */ \d t3 Table "public.t3" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- @@ -1098,43 +1084,33 @@ Indexes: "t3_pkey" PRIMARY KEY, btree (g) Publications: "p3" WHERE (g = 10) - +]]> On the subscriber node, create a table t1 with the same definition as the one on the publisher, and also create the subscription s1 that subscribes to the publication p1. -test_sub=# CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c)); -CREATE TABLE -test_sub=# CREATE SUBSCRIPTION s1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1' -test_sub-# PUBLICATION p1; -CREATE SUBSCRIPTION +/* sub # */ CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c)); +/* sub # */ CREATE SUBSCRIPTION s1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=s1' +/* sub - */ PUBLICATION p1; Insert some rows. Only the rows satisfying the t1 WHERE clause of publication p1 are replicated. -test_pub=# INSERT INTO t1 VALUES (2, 102, 'NSW'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (3, 103, 'QLD'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (4, 104, 'VIC'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (5, 105, 'ACT'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (6, 106, 'NSW'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (7, 107, 'NT'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (8, 108, 'QLD'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES (9, 109, 'NSW'); -INSERT 0 1 - -test_pub=# SELECT * FROM t1; +/* pub # */ INSERT INTO t1 VALUES (2, 102, 'NSW'); +/* pub # */ INSERT INTO t1 VALUES (3, 103, 'QLD'); +/* pub # */ INSERT INTO t1 VALUES (4, 104, 'VIC'); +/* pub # */ INSERT INTO t1 VALUES (5, 105, 'ACT'); +/* pub # */ INSERT INTO t1 VALUES (6, 106, 'NSW'); +/* pub # */ INSERT INTO t1 VALUES (7, 107, 'NT'); +/* pub # */ INSERT INTO t1 VALUES (8, 108, 'QLD'); +/* pub # */ INSERT INTO t1 VALUES (9, 109, 'NSW'); + +/* pub # */ SELECT * FROM t1; a | b | c ---+-----+----- 2 | 102 | NSW @@ -1148,7 +1124,7 @@ test_pub=# SELECT * FROM t1; (8 rows) -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b | c ---+-----+----- 6 | 106 | NSW @@ -1162,10 +1138,9 @@ test_sub=# SELECT * FROM t1; p1. The UPDATE replicates the change as normal. -test_pub=# UPDATE t1 SET b = 999 WHERE a = 6; -UPDATE 1 +/* pub # */ UPDATE t1 SET b = 999 WHERE a = 6; -test_pub=# SELECT * FROM t1; +/* pub # */ SELECT * FROM t1; a | b | c ---+-----+----- 2 | 102 | NSW @@ -1179,7 +1154,7 @@ test_pub=# SELECT * FROM t1; (8 rows) -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b | c ---+-----+----- 9 | 109 | NSW @@ -1194,10 +1169,9 @@ test_sub=# SELECT * FROM t1; transformed into an INSERT and the change is replicated. See the new row on the subscriber. -test_pub=# UPDATE t1 SET a = 555 WHERE a = 2; -UPDATE 1 +/* pub # */ UPDATE t1 SET a = 555 WHERE a = 2; -test_pub=# SELECT * FROM t1; +/* pub # */ SELECT * FROM t1; a | b | c -----+-----+----- 3 | 103 | QLD @@ -1211,7 +1185,7 @@ test_pub=# SELECT * FROM t1; (8 rows) -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b | c -----+-----+----- 9 | 109 | NSW @@ -1227,10 +1201,9 @@ test_sub=# SELECT * FROM t1; transformed into a DELETE and the change is replicated. See that the row is removed from the subscriber. -test_pub=# UPDATE t1 SET c = 'VIC' WHERE a = 9; -UPDATE 1 +/* pub # */ UPDATE t1 SET c = 'VIC' WHERE a = 9; -test_pub=# SELECT * FROM t1; +/* pub # */ SELECT * FROM t1; a | b | c -----+-----+----- 3 | 103 | QLD @@ -1244,7 +1217,7 @@ test_pub=# SELECT * FROM t1; (8 rows) -test_sub=# SELECT * FROM t1; +/* sub # */ SELECT * FROM t1; a | b | c -----+-----+----- 6 | 999 | NSW @@ -1262,17 +1235,13 @@ test_sub=# SELECT * FROM t1; Create a partitioned table on the publisher. -test_pub=# CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a); -CREATE TABLE -test_pub=# CREATE TABLE child PARTITION OF parent DEFAULT; -CREATE TABLE +/* pub # */ CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a); +/* pub # */ CREATE TABLE child PARTITION OF parent DEFAULT; Create the same tables on the subscriber. -test_sub=# CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a); -CREATE TABLE -test_sub=# CREATE TABLE child PARTITION OF parent DEFAULT; -CREATE TABLE +/* sub # */ CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a); +/* sub # */ CREATE TABLE child PARTITION OF parent DEFAULT; @@ -1280,16 +1249,14 @@ CREATE TABLE publication parameter publish_via_partition_root is set as true. There are row filters defined on both the partitioned table (parent), and on the partition (child). += 5) +/* pub - */ WITH (publish_via_partition_root=true); +]]> -test_pub=# CREATE PUBLICATION p4 FOR TABLE parent WHERE (a < 5), child WHERE (a >= 5) -test_pub-# WITH (publish_via_partition_root=true); -CREATE PUBLICATION - - -test_sub=# CREATE SUBSCRIPTION s4 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s4' -test_sub-# PUBLICATION p4; -CREATE SUBSCRIPTION +/* sub # */ CREATE SUBSCRIPTION s4 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=s4' +/* sub - */ PUBLICATION p4; @@ -1298,12 +1265,10 @@ CREATE SUBSCRIPTION parent (because publish_via_partition_root is true). -test_pub=# INSERT INTO parent VALUES (2), (4), (6); -INSERT 0 3 -test_pub=# INSERT INTO child VALUES (3), (5), (7); -INSERT 0 3 +/* pub # */ INSERT INTO parent VALUES (2), (4), (6); +/* pub # */ INSERT INTO child VALUES (3), (5), (7); -test_pub=# SELECT * FROM parent ORDER BY a; +/* pub # */ SELECT * FROM parent ORDER BY a; a --- 2 @@ -1315,7 +1280,7 @@ test_pub=# SELECT * FROM parent ORDER BY a; (6 rows) -test_sub=# SELECT * FROM parent ORDER BY a; +/* sub # */ SELECT * FROM parent ORDER BY a; a --- 2 @@ -1328,16 +1293,13 @@ test_sub=# SELECT * FROM parent ORDER BY a; Repeat the same test, but with a different value for publish_via_partition_root. The publication parameter publish_via_partition_root is set as false. A row filter is defined on the partition (child). += 5) +/* pub - */ WITH (publish_via_partition_root=false); +]]> -test_pub=# DROP PUBLICATION p4; -DROP PUBLICATION -test_pub=# CREATE PUBLICATION p4 FOR TABLE parent, child WHERE (a >= 5) -test_pub-# WITH (publish_via_partition_root=false); -CREATE PUBLICATION - - -test_sub=# ALTER SUBSCRIPTION s4 REFRESH PUBLICATION; -ALTER SUBSCRIPTION +/* sub # */ ALTER SUBSCRIPTION s4 REFRESH PUBLICATION; @@ -1345,14 +1307,11 @@ ALTER SUBSCRIPTION row filter of child (because publish_via_partition_root is false). -test_pub=# TRUNCATE parent; -TRUNCATE TABLE -test_pub=# INSERT INTO parent VALUES (2), (4), (6); -INSERT 0 3 -test_pub=# INSERT INTO child VALUES (3), (5), (7); -INSERT 0 3 +/* pub # */ TRUNCATE parent; +/* pub # */ INSERT INTO parent VALUES (2), (4), (6); +/* pub # */ INSERT INTO child VALUES (3), (5), (7); -test_pub=# SELECT * FROM parent ORDER BY a; +/* pub # */ SELECT * FROM parent ORDER BY a; a --- 2 @@ -1364,7 +1323,7 @@ test_pub=# SELECT * FROM parent ORDER BY a; (6 rows) -test_sub=# SELECT * FROM child ORDER BY a; +/* sub # */ SELECT * FROM child ORDER BY a; a --- 5 @@ -1407,6 +1366,14 @@ test_sub=# SELECT * FROM child ORDER BY a; of columns in the list is not preserved. + + Generated columns can also be specified in a column list. This allows + generated columns to be published, regardless of the publication parameter + + publish_generated_columns. See + for details. + + Specifying a column list when the publication also publishes FOR TABLES IN SCHEMA @@ -1439,7 +1406,9 @@ test_sub=# SELECT * FROM child ORDER BY a; During initial data synchronization, only the published columns are copied. However, if the subscriber is from a release prior to 15, then all the columns in the table are copied during initial data synchronization, - ignoring any column lists. + ignoring any column lists. If the subscriber is from a release prior to 18, + then initial table synchronization won't copy generated columns even if they + are defined in the publisher. @@ -1473,8 +1442,7 @@ test_sub=# SELECT * FROM child ORDER BY a; Create a table t1 to be used in the following example. -test_pub=# CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); -CREATE TABLE +/* pub # */ CREATE TABLE t1(id int, a text, b text, c text, d text, e text, PRIMARY KEY(id)); @@ -1483,15 +1451,14 @@ CREATE TABLE replicated. Notice that the order of column names in the column list does not matter. -test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d); -CREATE PUBLICATION +/* pub # */ CREATE PUBLICATION p1 FOR TABLE t1 (id, b, a, d); psql can be used to show the column lists (if defined) for each publication. -test_pub=# \dRp+ +/* pub # */ \dRp+ Publication p1 Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ----------+------------+---------+---------+---------+-----------+---------- @@ -1504,7 +1471,7 @@ Tables: psql can be used to show the column lists (if defined) for each table. -test_pub=# \d t1 +/* pub # */ \d t1 Table "public.t1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- @@ -1527,24 +1494,19 @@ Publications: s1 that subscribes to the publication p1. -test_sub=# CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id)); -CREATE TABLE -test_sub=# CREATE SUBSCRIPTION s1 -test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1' -test_sub-# PUBLICATION p1; -CREATE SUBSCRIPTION +/* sub # */ CREATE TABLE t1(id int, b text, a text, d text, PRIMARY KEY(id)); +/* sub # */ CREATE SUBSCRIPTION s1 +/* sub - */ CONNECTION 'host=localhost dbname=test_pub application_name=s1' +/* sub - */ PUBLICATION p1; On the publisher node, insert some rows to table t1. -test_pub=# INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2'); -INSERT 0 1 -test_pub=# INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3'); -INSERT 0 1 -test_pub=# SELECT * FROM t1 ORDER BY id; +/* pub # */ INSERT INTO t1 VALUES(1, 'a-1', 'b-1', 'c-1', 'd-1', 'e-1'); +/* pub # */ INSERT INTO t1 VALUES(2, 'a-2', 'b-2', 'c-2', 'd-2', 'e-2'); +/* pub # */ INSERT INTO t1 VALUES(3, 'a-3', 'b-3', 'c-3', 'd-3', 'e-3'); +/* pub # */ SELECT * FROM t1 ORDER BY id; id | a | b | c | d | e ----+-----+-----+-----+-----+----- 1 | a-1 | b-1 | c-1 | d-1 | e-1 @@ -1557,7 +1519,7 @@ test_pub=# SELECT * FROM t1 ORDER BY id; Only data from the column list of publication p1 is replicated. -test_sub=# SELECT * FROM t1 ORDER BY id; +/* sub # */ SELECT * FROM t1 ORDER BY id; id | b | a | d ----+-----+-----+----- 1 | b-1 | a-1 | d-1 @@ -1570,6 +1532,185 @@ test_sub=# SELECT * FROM t1 ORDER BY id; + + Generated Column Replication + + + Typically, a table at the subscriber will be defined the same as the + publisher table, so if the publisher table has a + GENERATED column then the subscriber table will + have a matching generated column. In this case, it is always the subscriber + table generated column value that is used. + + + + For example, note below that subscriber table generated column value comes from the + subscriber column's calculation. + +/* pub # */ CREATE TABLE tab_gen_to_gen (a int, b int GENERATED ALWAYS AS (a + 1) STORED); +/* pub # */ INSERT INTO tab_gen_to_gen VALUES (1),(2),(3); +/* pub # */ CREATE PUBLICATION pub1 FOR TABLE tab_gen_to_gen; +/* pub # */ SELECT * FROM tab_gen_to_gen; + a | b +---+--- + 1 | 2 + 2 | 3 + 3 | 4 +(3 rows) + +/* sub # */ CREATE TABLE tab_gen_to_gen (a int, b int GENERATED ALWAYS AS (a * 100) STORED); +/* sub # */ CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub' PUBLICATION pub1; +/* sub # */ SELECT * from tab_gen_to_gen; + a | b +---+---- + 1 | 100 + 2 | 200 + 3 | 300 +(3 rows) + + + + + In fact, prior to version 18.0, logical replication does not publish + GENERATED columns at all. + + + + But, replicating a generated column to a regular column can sometimes be + desirable. + + + This feature may be useful when replicating data to a + non-PostgreSQL database via output plugin, especially if the target database + does not support generated columns. + + + + + + Generated columns are not published by default, but users can opt to + publish stored generated columns just like regular ones. + + + + There are two ways to do this: + + + + Set the PUBLICATION parameter + + publish_generated_columns to stored. + This instructs PostgreSQL logical replication to publish current and + future stored generated columns of the publication's tables. + + + + + + Specify a table column list + to explicitly nominate which stored generated columns will be published. + + + + + When determining which table columns will be published, a column list + takes precedence, overriding the effect of the + publish_generated_columns parameter. + + + + + + + + The following table summarizes behavior when there are generated columns + involved in the logical replication. Results are shown for when + publishing generated columns is not enabled, and for when it is + enabled. + + + + Replication Result Summary + + + + + Publish generated columns? + Publisher table column + Subscriber table column + Result + + + + + + No + GENERATED + GENERATED + Publisher table column is not replicated. Use the subscriber table generated column value. + + + + No + GENERATED + regular + Publisher table column is not replicated. Use the subscriber table regular column default value. + + + + No + GENERATED + --missing-- + Publisher table column is not replicated. Nothing happens. + + + + Yes + GENERATED + GENERATED + ERROR. Not supported. + + + + Yes + GENERATED + regular + Publisher table column value is replicated to the subscriber table column. + + + + Yes + GENERATED + --missing-- + ERROR. The column is reported as missing from the subscriber table. + + + +
+ + + + There's currently no support for subscriptions comprising several + publications where the same table has been published with different column + lists. See . + + + + This same situation can occur if one publication is publishing generated + columns, while another publication in the same subscription is not + publishing generated columns for the same table. + + + + + + If the subscriber is from a release prior to 18, then initial table + synchronization won't copy generated columns even if they are defined in + the publisher. + + +
+ Conflicts @@ -1579,8 +1720,220 @@ test_sub=# SELECT * FROM t1 ORDER BY id; node. If incoming data violates any constraints the replication will stop. This is referred to as a conflict. When replicating UPDATE or DELETE - operations, missing data will not produce a conflict and such operations - will simply be skipped. + operations, missing data is also considered as a + conflict, but does not result in an error and such + operations will simply be skipped. +
+ + + Additional logging is triggered, and the conflict statistics are collected (displayed in the + pg_stat_subscription_stats view) + in the following conflict cases: + + + insert_exists + + + Inserting a row that violates a NOT DEFERRABLE + unique constraint. Note that to log the origin and commit + timestamp details of the conflicting key, + track_commit_timestamp + should be enabled on the subscriber. In this case, an error will be + raised until the conflict is resolved manually. + + + + + update_origin_differs + + + Updating a row that was previously modified by another origin. + Note that this conflict can only be detected when + track_commit_timestamp + is enabled on the subscriber. Currently, the update is always applied + regardless of the origin of the local row. + + + + + update_exists + + + The updated value of a row violates a NOT DEFERRABLE + unique constraint. Note that to log the origin and commit + timestamp details of the conflicting key, + track_commit_timestamp + should be enabled on the subscriber. In this case, an error will be + raised until the conflict is resolved manually. Note that when updating a + partitioned table, if the updated row value satisfies another partition + constraint resulting in the row being inserted into a new partition, the + insert_exists conflict may arise if the new row + violates a NOT DEFERRABLE unique constraint. + + + + + update_missing + + + The tuple to be updated was not found. The update will simply be + skipped in this scenario. + + + + + delete_origin_differs + + + Deleting a row that was previously modified by another origin. Note that + this conflict can only be detected when + track_commit_timestamp + is enabled on the subscriber. Currently, the delete is always applied + regardless of the origin of the local row. + + + + + delete_missing + + + The tuple to be deleted was not found. The delete will simply be + skipped in this scenario. + + + + + multiple_unique_conflicts + + + Inserting or updating a row violates multiple + NOT DEFERRABLE unique constraints. Note that to log + the origin and commit timestamp details of conflicting keys, ensure + that track_commit_timestamp + is enabled on the subscriber. In this case, an error will be raised until + the conflict is resolved manually. + + + + + Note that there are other conflict scenarios, such as exclusion constraint + violations. Currently, we do not provide additional details for them in the + log. + + + + The log format for logical replication conflicts is as follows: + +LOG: conflict detected on relation "schemaname.tablename": conflict=conflict_type +DETAIL: detailed_explanation. +{detail_values [; ... ]}. + +where detail_values is one of: + + Key (column_name , ...)=(column_value , ...) + existing local tuple (column_name , ...)=(column_value , ...) + remote tuple (column_name , ...)=(column_value , ...) + replica identity {(column_name , ...)=(column_value , ...) | full (column_name , ...)=(column_value , ...)} + + + The log provides the following information: + + + LOG + + + + + schemaname.tablename + identifies the local relation involved in the conflict. + + + + + conflict_type is the type of conflict that occurred + (e.g., insert_exists, update_exists). + + + + + + + + DETAIL + + + + + detailed_explanation includes + the origin, transaction ID, and commit timestamp of the transaction that + modified the existing local tuple, if available. + + + + + The Key section includes the key values of the local + tuple that violated a unique constraint for + insert_exists, update_exists or + multiple_unique_conflicts conflicts. + + + + + The existing local tuple section includes the local + tuple if its origin differs from the remote tuple for + update_origin_differs or delete_origin_differs + conflicts, or if the key value conflicts with the remote tuple for + insert_exists, update_exists or + multiple_unique_conflicts conflicts. + + + + + The remote tuple section includes the new tuple from + the remote insert or update operation that caused the conflict. Note that + for an update operation, the column value of the new tuple will be null + if the value is unchanged and toasted. + + + + + The replica identity section includes the replica + identity key values that were used to search for the existing local + tuple to be updated or deleted. This may include the full tuple value + if the local relation is marked with + REPLICA IDENTITY FULL. + + + + + column_name is the column name. + For existing local tuple, remote tuple, + and replica identity full cases, column names are + logged only if the user lacks the privilege to access all columns of + the table. If column names are present, they appear in the same order + as the corresponding column values. + + + + + column_value is the column value. + The large column values are truncated to 64 bytes. + + + + + Note that in case of multiple_unique_conflicts conflict, + multiple detailed_explanation + and detail_values lines + will be generated, each detailing the conflict information associated + with distinct unique + constraints. + + + + + + @@ -1597,7 +1950,7 @@ test_sub=# SELECT * FROM t1 ORDER BY id; - A conflict will produce an error and will stop the replication; it must be + A conflict that produces an error will stop the replication; it must be resolved manually by the user. Details about the conflict can be found in the subscriber's server log. @@ -1609,8 +1962,9 @@ test_sub=# SELECT * FROM t1 ORDER BY id; an error, the replication won't proceed, and the logical replication worker will emit the following kind of message to the subscriber's server log: -ERROR: duplicate key value violates unique constraint "test_pkey" -DETAIL: Key (c)=(1) already exists. +ERROR: conflict detected on relation "public.test": conflict=insert_exists +DETAIL: Key already exists in unique index "t_pkey", which was modified locally in transaction 740 at 2024-06-26 10:47:04.727375+08. +Key (c)=(1); existing local tuple (1, 'local'); remote tuple (1, 'remote'). CONTEXT: processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378 The LSN of the transaction that contains the change violating the constraint and @@ -1636,6 +1990,15 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Please note that skipping the whole transaction includes skipping changes that might not violate any constraint. This can easily make the subscriber inconsistent. + The additional details regarding conflicting rows, such as their origin and + commit timestamp can be seen in the DETAIL line of the + log. But note that this information is only available when + track_commit_timestamp + is enabled on the subscriber. Users can use this information to decide + whether to retain the local change or adopt the remote alteration. For + instance, the DETAIL line in the above log indicates that + the existing row was modified locally. Users can manually perform a + remote-change-win.
@@ -1756,15 +2119,6 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Architecture - - Logical replication starts by copying a snapshot of the data on the - publisher database. Once that is done, changes on the publisher are sent - to the subscriber as they occur in real time. The subscriber applies data - in the order in which commits were made on the publisher so that - transactional consistency is guaranteed for the publications within any - single subscription. - - Logical replication is built with an architecture similar to physical streaming replication (see ). It is @@ -1803,18 +2157,20 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Initial Snapshot The initial data in existing subscribed tables are snapshotted and - copied in a parallel instance of a special kind of apply process. - This process will create its own replication slot and copy the existing - data. As soon as the copy is finished the table contents will become - visible to other backends. Once existing data is copied, the worker - enters synchronization mode, which ensures that the table is brought - up to a synchronized state with the main apply process by streaming - any changes that happened during the initial data copy using standard - logical replication. During this synchronization phase, the changes - are applied and committed in the same order as they happened on the - publisher. Once synchronization is done, control of the - replication of the table is given back to the main apply process where - replication continues as normal. + copied in parallel instances of a special kind of apply process. + These special apply processes are dedicated table synchronization + workers, spawned for each table to be synchronized. Each table + synchronization process will create its own replication slot and + copy the existing data. As soon as the copy is finished the table + contents will become visible to other backends. Once existing data + is copied, the worker enters synchronization mode, which ensures + that the table is brought up to a synchronized state with the main + apply process by streaming any changes that happened during the + initial data copy using standard logical replication. During this + synchronization phase, the changes are applied and committed in the same + order as they happened on the publisher. Once synchronization is done, + control of the replication of the table is given back to the main apply + process where replication continues as normal. @@ -1825,6 +2181,15 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER when copying the existing table data. + + + If a table synchronization worker fails during copy, the apply worker + detects the failure and respawns the table synchronization worker to + continue the synchronization process. This behaviour ensures that + transient errors do not permanently disrupt the replication setup. See + also wal_retrieve_retry_interval. + + @@ -1953,10 +2318,8 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Configuration Settings - Logical replication requires several configuration options to be set. Most - options are relevant only on one side of the replication. However, - max_replication_slots is used on both the publisher and - the subscriber, but it has a different meaning for each. + Logical replication requires several configuration options to be set. These + options are relevant only on one side of the replication. @@ -1973,6 +2336,11 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER plus some reserve for table synchronization. + + Logical replication slots are also affected by + idle_replication_slot_timeout. + + max_wal_senders should be set to at least the same as @@ -1991,7 +2359,7 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER Subscribers - max_replication_slots + max_active_replication_origins must be set to at least the number of subscriptions that will be added to the subscriber, plus some reserve for table synchronization. @@ -2035,6 +2403,769 @@ CONTEXT: processing remote data for replication origin "pg_16395" during "INSER + + Upgrade + + + Migration of logical replication clusters + is possible only when all the members of the old logical replication + clusters are version 17.0 or later. + + + + Prepare for Publisher Upgrades + + + pg_upgrade attempts to migrate logical + slots. This helps avoid the need for manually defining the same + logical slots on the new publisher. Migration of logical slots is + only supported when the old cluster is version 17.0 or later. + Logical slots on clusters before version 17.0 will silently be + ignored. + + + + Before you start upgrading the publisher cluster, ensure that the + subscription is temporarily disabled, by executing + ALTER SUBSCRIPTION ... DISABLE. + Re-enable the subscription after the upgrade. + + + + There are some prerequisites for pg_upgrade to + be able to upgrade the logical slots. If these are not met an error + will be reported. + + + + + + The new cluster must have + wal_level as + logical. + + + + + The new cluster must have + max_replication_slots + configured to a value greater than or equal to the number of slots + present in the old cluster. + + + + + The output plugins referenced by the slots on the old cluster must be + installed in the new PostgreSQL executable directory. + + + + + The old cluster has replicated all the transactions and logical decoding + messages to subscribers. + + + + + All slots on the old cluster must be usable, i.e., there are no slots + whose + pg_replication_slots.conflicting + is not true. + + + + + The new cluster must not have permanent logical slots, i.e., + there must be no slots where + pg_replication_slots.temporary + is false. + + + + + + + Prepare for Subscriber Upgrades + + + Setup the + subscriber configurations in the new subscriber. + pg_upgrade attempts to migrate subscription + dependencies which includes the subscription's table information present in + pg_subscription_rel + system catalog and also the subscription's replication origin. This allows + logical replication on the new subscriber to continue from where the + old subscriber was up to. Migration of subscription dependencies is only + supported when the old cluster is version 17.0 or later. Subscription + dependencies on clusters before version 17.0 will silently be ignored. + + + + There are some prerequisites for pg_upgrade to + be able to upgrade the subscriptions. If these are not met an error + will be reported. + + + + + + All the subscription tables in the old subscriber should be in state + i (initialize) or r (ready). This + can be verified by checking pg_subscription_rel.srsubstate. + + + + + The replication origin entry corresponding to each of the subscriptions + should exist in the old cluster. This can be found by checking + pg_subscription and + pg_replication_origin + system tables. + + + + + The new cluster must have + max_active_replication_origins + configured to a value greater than or equal to the number of + subscriptions present in the old cluster. + + + + + + + Upgrading Logical Replication Clusters + + + While upgrading a subscriber, write operations can be performed in the + publisher. These changes will be replicated to the subscriber once the + subscriber upgrade is completed. + + + + + The logical replication restrictions apply to logical replication cluster + upgrades also. See for + details. + + + The prerequisites of publisher upgrade apply to logical replication + cluster upgrades also. See + for details. + + + The prerequisites of subscriber upgrade apply to logical replication + cluster upgrades also. See + for details. + + + + + + Upgrading logical replication cluster requires multiple steps to be + performed on various nodes. Because not all operations are + transactional, the user is advised to take backups as described in + . + + + + + The steps to upgrade the following logical replication clusters are + detailed below: + + + + Follow the steps specified in + to upgrade + a two-node logical replication cluster. + + + + + Follow the steps specified in + to upgrade + a cascaded logical replication cluster. + + + + + Follow the steps specified in + + to upgrade a two-node circular logical replication cluster. + + + + + + + Steps to Upgrade a Two-node Logical Replication Cluster + + Let's say publisher is in node1 and subscriber is + in node2. The subscriber node2 has + a subscription sub1_node1_node2 which is subscribing + the changes from node1. + + + + + + Disable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... DISABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE; + + + + + + Stop the publisher server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1 stop + + + + + + + Initialize data1_upgraded instance by using the + required newer version. + + + + + + Upgrade the publisher node1's server to the + required newer version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data1" + --new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded publisher server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile + + + + + + + Stop the subscriber server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2 stop + + + + + + + Initialize data2_upgraded instance by using the + required newer version. + + + + + + Upgrade the subscriber node2's server to + the required new version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data2" + --new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded subscriber server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile + + + + + + + On node2, create any tables that were created in + the upgraded publisher node1 server between + + and now, e.g.: + +/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); + + + + + + + Enable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... ENABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE; + + + + + + + Refresh the node2 subscription's publications using + ALTER SUBSCRIPTION ... REFRESH PUBLICATION, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION; + + + + + + + + In the steps described above, the publisher is upgraded first, followed + by the subscriber. Alternatively, the user can use similar steps to + upgrade the subscriber first, followed by the publisher. + + + + + + Steps to Upgrade a Cascaded Logical Replication Cluster + + Let's say we have a cascaded logical replication setup + node1->node2->node3. + Here node2 is subscribing the changes from + node1 and node3 is subscribing + the changes from node2. The node2 + has a subscription sub1_node1_node2 which is + subscribing the changes from node1. The + node3 has a subscription + sub1_node2_node3 which is subscribing the changes from + node2. + + + + + + Disable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... DISABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE; + + + + + + + Stop the server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1 stop + + + + + + + Initialize data1_upgraded instance by using the + required newer version. + + + + + + Upgrade the node1's server to the required newer + version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data1" + --new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile + + + + + + + Disable all the subscriptions on node3 that are + subscribing the changes from node2 by using + ALTER SUBSCRIPTION ... DISABLE, + e.g.: + +/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 DISABLE; + + + + + + + Stop the server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2 stop + + + + + + + Initialize data2_upgraded instance by using the + required newer version. + + + + + + Upgrade the node2's server to the required + new version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data2" + --new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile + + + + + + + On node2, create any tables that were created in + the upgraded publisher node1 server between + + and now, e.g.: + +/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); + + + + + + + Enable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... ENABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE; + + + + + + + Refresh the node2 subscription's publications using + ALTER SUBSCRIPTION ... REFRESH PUBLICATION, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION; + + + + + + + Stop the server in node3, e.g.: + +pg_ctl -D /opt/PostgreSQL/data3 stop + + + + + + + Initialize data3_upgraded instance by using the + required newer version. + + + + + + Upgrade the node3's server to the required + new version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data3" + --new-datadir "/opt/PostgreSQL/postgres/18/data3_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded server in node3, e.g.: + +pg_ctl -D /opt/PostgreSQL/data3_upgraded start -l logfile + + + + + + + On node3, create any tables that were created in + the upgraded node2 between + and now, + e.g.: + +/* node3 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); + + + + + + + Enable all the subscriptions on node3 that are + subscribing the changes from node2 by using + ALTER SUBSCRIPTION ... ENABLE, + e.g.: + +/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 ENABLE; + + + + + + + Refresh the node3 subscription's publications using + ALTER SUBSCRIPTION ... REFRESH PUBLICATION, + e.g.: + +/* node3 # */ ALTER SUBSCRIPTION sub1_node2_node3 REFRESH PUBLICATION; + + + + + + + + Steps to Upgrade a Two-node Circular Logical Replication Cluster + + Let's say we have a circular logical replication setup + node1->node2 and + node2->node1. Here + node2 is subscribing the changes from + node1 and node1 is subscribing + the changes from node2. The node1 + has a subscription sub1_node2_node1 which is + subscribing the changes from node2. The + node2 has a subscription + sub1_node1_node2 which is subscribing the changes from + node1. + + + + + + Disable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... DISABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 DISABLE; + + + + + + + Stop the server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1 stop + + + + + + + Initialize data1_upgraded instance by using the + required newer version. + + + + + + Upgrade the node1's server to the required + newer version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data1" + --new-datadir "/opt/PostgreSQL/postgres/18/data1_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded server in node1, e.g.: + +pg_ctl -D /opt/PostgreSQL/data1_upgraded start -l logfile + + + + + + + Enable all the subscriptions on node2 that are + subscribing the changes from node1 by using + ALTER SUBSCRIPTION ... ENABLE, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 ENABLE; + + + + + + + On node1, create any tables that were created in + node2 between + and now, e.g.: + +/* node1 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); + + + + + + + + Refresh the node1 subscription's publications to + copy initial table data from node2 using + ALTER SUBSCRIPTION ... REFRESH PUBLICATION, + e.g.: + +/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 REFRESH PUBLICATION; + + + + + + + Disable all the subscriptions on node1 that are + subscribing the changes from node2 by using + ALTER SUBSCRIPTION ... DISABLE, + e.g.: + +/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 DISABLE; + + + + + + + Stop the server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2 stop + + + + + + + Initialize data2_upgraded instance by using the + required newer version. + + + + + + Upgrade the node2's server to the required + new version, e.g.: + +pg_upgrade + --old-datadir "/opt/PostgreSQL/postgres/17/data2" + --new-datadir "/opt/PostgreSQL/postgres/18/data2_upgraded" + --old-bindir "/opt/PostgreSQL/postgres/17/bin" + --new-bindir "/opt/PostgreSQL/postgres/18/bin" + + + + + + + Start the upgraded server in node2, e.g.: + +pg_ctl -D /opt/PostgreSQL/data2_upgraded start -l logfile + + + + + + + Enable all the subscriptions on node1 that are + subscribing the changes from node2 by using + ALTER SUBSCRIPTION ... ENABLE, + e.g.: + +/* node1 # */ ALTER SUBSCRIPTION sub1_node2_node1 ENABLE; + + + + + + + On node2, create any tables that were created in + the upgraded node1 between + and now, e.g.: + +/* node2 # */ CREATE TABLE distributors (did integer PRIMARY KEY, name varchar(40)); + + + + + + + Refresh the node2 subscription's publications to + copy initial table data from node1 using + ALTER SUBSCRIPTION ... REFRESH PUBLICATION, + e.g.: + +/* node2 # */ ALTER SUBSCRIPTION sub1_node1_node2 REFRESH PUBLICATION; + + + + + + + + + Quick Setup diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml index 1c4ae38f1b992..dd9e83b08eaf1 100644 --- a/doc/src/sgml/logicaldecoding.sgml +++ b/doc/src/sgml/logicaldecoding.sgml @@ -455,9 +455,8 @@ postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NU using the slot's contents without losing any changes. - Creation of a snapshot is not always possible. In particular, it will - fail when connected to a hot standby. Applications that do not require - snapshot export may suppress it with the NOEXPORT_SNAPSHOT + Applications that do not require + snapshot export may suppress it with the SNAPSHOT 'nothing' option. @@ -898,7 +897,6 @@ typedef void (*LogicalDecodeMessageCB) (struct LogicalDecodingContext *ctx, callback might also error out due to simultaneous rollback of this very same transaction. In that case, the logical decoding of this aborted transaction is stopped gracefully. - The prefix is arbitrary null-terminated prefix which can be used for identifying interesting messages for the current plugin. And finally the message parameter holds diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml index 9584105b03b39..1c3543303f0ab 100644 --- a/doc/src/sgml/ltree.sgml +++ b/doc/src/sgml/ltree.sgml @@ -841,15 +841,6 @@ ltreetest=> SELECT ins_label(path,2,'Space') FROM test WHERE path <@ 'Top. creating a function, ltree values are mapped to Python lists. (The reverse is currently not supported, however.) - - - - It is strongly recommended that the transform extension be installed in - the same schema as ltree. Otherwise there are - installation-time security hazards if a transform extension's schema - contains objects defined by a hostile user. - - diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 0be90bdc7efe1..600e4b3f2f3b8 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -496,9 +496,25 @@ When that happens, VACUUM will eventually need to perform an aggressive vacuum, which will freeze all eligible unfrozen XID and MXID values, including those from all-visible but not all-frozen pages. - In practice most tables require periodic aggressive vacuuming. + + + + If a table is building up a backlog of all-visible but not all-frozen + pages, a normal vacuum may choose to scan skippable pages in an effort to + freeze them. Doing so decreases the number of pages the next aggressive + vacuum must scan. These are referred to as eagerly + scanned pages. Eager scanning can be tuned to attempt to freeze + more all-visible pages by increasing . Even if eager + scanning has kept the number of all-visible but not all-frozen pages to a + minimum, most tables still require periodic aggressive vacuuming. However, + any pages successfully eager frozen may be skipped during an aggressive + vacuum, so eager freezing may minimize the overhead of aggressive vacuums. + + + - controls when VACUUM does that: all-visible but not all-frozen + controls when a table is aggressively vacuumed. All all-visible but not all-frozen pages are scanned if the number of transactions that have passed since the last such scan is greater than vacuum_freeze_table_age minus vacuum_freeze_min_age. Setting @@ -626,10 +642,12 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
- VACUUM normally only scans pages that have been modified - since the last vacuum, but relfrozenxid can only be - advanced when every page of the table - that might contain unfrozen XIDs is scanned. This happens when + While VACUUM scans mostly pages that have been + modified since the last vacuum, it may also eagerly scan some + all-visible but not all-frozen pages in an attempt to freeze them, but + the relfrozenxid will only be advanced when + every page of the table that might contain unfrozen XIDs is scanned. + This happens when relfrozenxid is more than vacuum_freeze_table_age transactions old, when VACUUM's FREEZE option is used, or when all @@ -793,10 +811,11 @@ HINT: Execute a database-wide VACUUM in that database. As a safety device, an aggressive vacuum scan will occur for any table whose multixact-age is greater than . Also, if the - storage occupied by multixacts members exceeds 2GB, aggressive vacuum + storage occupied by multixacts members exceeds about 10GB, aggressive vacuum scans will occur more often for all tables, starting with those that have the oldest multixact-age. Both of these kinds of aggressive - scans will occur even if autovacuum is nominally disabled. + scans will occur even if autovacuum is nominally disabled. The members storage + area can grow up to about 20GB before reaching wraparound. @@ -895,9 +914,11 @@ HINT: Execute a database-wide VACUUM in that database. VACUUM exceeds the vacuum threshold, the table is vacuumed. The vacuum threshold is defined as: -vacuum threshold = vacuum base threshold + vacuum scale factor * number of tuples +vacuum threshold = Minimum(vacuum max threshold, vacuum base threshold + vacuum scale factor * number of tuples) - where the vacuum base threshold is + where the vacuum max threshold is + , + the vacuum base threshold is , the vacuum scale factor is , @@ -929,8 +950,7 @@ vacuum insert threshold = vacuum base insert threshold + vacuum insert scale fac If the relfrozenxid value of the table is more than vacuum_freeze_table_age transactions old, an aggressive vacuum is performed to freeze old tuples and advance - relfrozenxid; otherwise, only pages that have been modified - since the last vacuum are scanned. + relfrozenxid. diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml index a8a70a1fc4242..fe4cb4410cd51 100644 --- a/doc/src/sgml/manage-ag.sgml +++ b/doc/src/sgml/manage-ag.sgml @@ -530,9 +530,11 @@ CREATE TABLE foo(i int); pg_tablespace system catalog, for example -SELECT spcname FROM pg_tablespace; +SELECT spcname, spcowner::regrole, pg_tablespace_location(oid) FROM pg_tablespace; - The program's \db meta-command + It is possible to find which databases use which tablespaces; + see . The program's \db meta-command is also useful for listing the existing tablespaces. @@ -541,10 +543,7 @@ SELECT spcname FROM pg_tablespace; point to each of the non-built-in tablespaces defined in the cluster. Although not recommended, it is possible to adjust the tablespace layout by hand by redefining these links. Under no circumstances perform - this operation while the server is running. Note that in PostgreSQL 9.1 - and earlier you will also need to update the pg_tablespace - catalog with the new locations. (If you do not, pg_dump will - continue to output the old tablespace locations.) + this operation while the server is running. diff --git a/doc/src/sgml/meson.build b/doc/src/sgml/meson.build index e418de83a76e1..6ae192eac68a4 100644 --- a/doc/src/sgml/meson.build +++ b/doc/src/sgml/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group docs = [] installdocs = [] diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 55417a6fa9d19..4265a22d4de35 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -168,6 +168,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser of the current command being executed by any server process. + + The parameter enables + monitoring of cost-based vacuum delay. + + The parameter controls whether cumulative statistics are collected about table and index accesses. @@ -185,7 +190,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser The parameter enables monitoring - of WAL write and fsync times. + of WAL read, write and fsync times. @@ -507,7 +512,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser pg_stat_subscription_statspg_stat_subscription_stats - One row per subscription, showing statistics about errors. + One row per subscription, showing statistics about errors and conflicts. See pg_stat_subscription_stats for details. @@ -899,6 +904,12 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser Current overall state of this backend. Possible values are: + + + starting: The backend is in initial startup. Client + authentication is performed during this phase. + + active: The backend is executing a query. @@ -1016,7 +1027,9 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser it may or may not be waiting on some event. If the state is active and wait_event is non-null, it means that a query is being executed, but is being blocked somewhere - in the system. + in the system. To keep the reporting overhead low, the system does not + attempt to synchronize different aspects of activity data for a backend. + As a result, ephemeral discrepancies may exist between the view's columns. @@ -1148,7 +1161,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage Extensions can add Extension, - InjectionPoint. and LWLock events + InjectionPoint, and LWLock events to the lists shown in and . In some cases, the name of an LWLock assigned by an extension will not be @@ -2157,7 +2170,10 @@ description | Waiting for a newly initialized WAL file to reach durable storage apply_error_count bigint - Number of times an error occurred while applying changes + Number of times an error occurred while applying changes. Note that any + conflict resulting in an apply error will be counted in both + apply_error_count and the corresponding conflict + count (e.g., confl_*). @@ -2171,6 +2187,88 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + confl_insert_exists bigint + + + Number of times a row insertion violated a + NOT DEFERRABLE unique constraint during the + application of changes. See + for details about this conflict. + + + + + + confl_update_origin_differs bigint + + + Number of times an update was applied to a row that had been previously + modified by another source during the application of changes. See + for details about this + conflict. + + + + + + confl_update_exists bigint + + + Number of times that an updated row value violated a + NOT DEFERRABLE unique constraint during the + application of changes. See + for details about this conflict. + + + + + + confl_update_missing bigint + + + Number of times the tuple to be updated was not found during the + application of changes. See + for details about this conflict. + + + + + + confl_delete_origin_differs bigint + + + Number of times a delete operation was applied to row that had been + previously modified by another source during the application of changes. + See for details about + this conflict. + + + + + + confl_delete_missing bigint + + + Number of times the tuple to be deleted was not found during the application + of changes. See for details + about this conflict. + + + + + + confl_multiple_unique_conflicts bigint + + + Number of times a row insertion or an updated row values violated multiple + NOT DEFERRABLE unique constraints during the + application of changes. See + for details about this conflict. + + + stats_reset timestamp with time zone @@ -2508,9 +2606,10 @@ description | Waiting for a newly initialized WAL file to reach durable storage - Currently, I/O on relations (e.g. tables, indexes) is tracked. However, - relation I/O which bypasses shared buffers (e.g. when moving a table from one - tablespace to another) is currently not tracked. + Currently, I/O on relations (e.g. tables, indexes) and WAL activity are + tracked. However, relation I/O which bypasses shared buffers + (e.g. when moving a table from one tablespace to another) is currently + not tracked. @@ -2563,6 +2662,11 @@ description | Waiting for a newly initialized WAL file to reach durable storage temp relation: Temporary relations. + + + wal: Write Ahead Logs. + + @@ -2587,6 +2691,13 @@ description | Waiting for a newly initialized WAL file to reach durable storage normal. + + + init: I/O operations performed while creating the + WAL segments are tracked in context + init. + + vacuum: I/O operations performed outside of shared @@ -2619,8 +2730,18 @@ description | Waiting for a newly initialized WAL file to reach durable storage reads bigint - Number of read operations, each of the size specified in - op_bytes. + Number of read operations. + + + + + + + + read_bytes numeric + + + The total size of read operations in bytes. @@ -2631,8 +2752,12 @@ description | Waiting for a newly initialized WAL file to reach durable storage read_time double precision - Time spent in read operations in milliseconds (if - is enabled, otherwise zero) + Time spent waiting for read operations in milliseconds (if + is enabled and + object is not wal, + or if is enabled + and object is wal, + otherwise zero) @@ -2643,8 +2768,18 @@ description | Waiting for a newly initialized WAL file to reach durable storage writes bigint - Number of write operations, each of the size specified in - op_bytes. + Number of write operations. + + + + + + + + write_bytes numeric + + + The total size of write operations in bytes. @@ -2655,8 +2790,12 @@ description | Waiting for a newly initialized WAL file to reach durable storage write_time double precision - Time spent in write operations in milliseconds (if - is enabled, otherwise zero) + Time spent waiting for write operations in milliseconds (if + is enabled and + object is not wal, + or if is enabled + and object is wal, + otherwise zero) @@ -2667,8 +2806,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage writebacks bigint - Number of units of size op_bytes which the process - requested the kernel write out to permanent storage. + Number of units of size BLCKSZ (typically 8kB) which + the process requested the kernel write out to permanent storage. @@ -2679,7 +2818,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage writeback_time double precision - Time spent in writeback operations in milliseconds (if + Time spent waiting for writeback operations in milliseconds (if is enabled, otherwise zero). This includes the time spent queueing write-out requests and, potentially, the time spent to write out the dirty data. @@ -2693,8 +2832,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage extends bigint - Number of relation extend operations, each of the size specified in - op_bytes. + Number of relation extend operations. @@ -2702,11 +2840,10 @@ description | Waiting for a newly initialized WAL file to reach durable storage - extend_time double precision + extend_bytes numeric - Time spent in extend operations in milliseconds (if - is enabled, otherwise zero) + The total size of relation extend operations in bytes. @@ -2714,16 +2851,15 @@ description | Waiting for a newly initialized WAL file to reach durable storage - op_bytes bigint - - - The number of bytes per unit of I/O read, written, or extended. + extend_time double precision - Relation data reads, writes, and extends are done in - block_size units, derived from the build-time - parameter BLCKSZ, which is 8192 by - default. + Time spent waiting for extend operations in milliseconds. (if + is enabled and + object is not wal, + or if is enabled + and object is wal, + otherwise zero) @@ -2792,8 +2928,12 @@ description | Waiting for a newly initialized WAL file to reach durable storage fsync_time double precision - Time spent in fsync operations in milliseconds (if - is enabled, otherwise zero) + Time spent waiting for fsync operations in milliseconds (if + is enabled and + object is not wal, + or if is enabled + and object is wal, + otherwise zero) @@ -2831,6 +2971,16 @@ description | Waiting for a newly initialized WAL file to reach durable storage writer. + + For the object wal, + fsyncs and fsync_time track the + fsync activity of WAL files done in issue_xlog_fsync. + writes and write_time + track the write activity of WAL files done in + XLogWrite. + See for more information. + + pg_stat_io can be used to inform database tuning. For example: @@ -2865,7 +3015,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage - Columns tracking I/O time will only be non-zero when + Columns tracking I/O wait time will only be non-zero when is enabled. The user should be careful when referencing these columns in combination with their corresponding I/O operations in case track_io_timing @@ -2978,7 +3128,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage num_timed bigint - Number of scheduled checkpoints that have been performed + Number of scheduled checkpoints due to timeout @@ -2987,7 +3137,16 @@ description | Waiting for a newly initialized WAL file to reach durable storage num_requested bigint - Number of requested checkpoints that have been performed + Number of requested checkpoints + + + + + + num_done bigint + + + Number of checkpoints that have been performed @@ -3045,7 +3204,16 @@ description | Waiting for a newly initialized WAL file to reach durable storage buffers_written bigint - Number of buffers written during checkpoints and restartpoints + Number of shared buffers written during checkpoints and restartpoints + + + + + + slru_written bigint + + + Number of SLRU buffers written during checkpoints and restartpoints @@ -3061,6 +3229,18 @@ description | Waiting for a newly initialized WAL file to reach durable storage
+ + Checkpoints may be skipped if the server has been idle since the last one. + num_timed and + num_requested count both completed and skipped + checkpoints, while num_done tracks only + the completed ones. Similarly, restartpoints may be skipped + if the last replayed checkpoint record is already the last restartpoint. + restartpoints_timed and + restartpoints_req count both completed and + skipped restartpoints, while restartpoints_done + tracks only the completed ones. + @@ -3126,63 +3306,6 @@ description | Waiting for a newly initialized WAL file to reach durable storage
- - - wal_write bigint - - - Number of times WAL buffers were written out to disk via - XLogWrite request. - See for more information about - the internal WAL function XLogWrite. - - - - - - wal_sync bigint - - - Number of times WAL files were synced to disk via - issue_xlog_fsync request - (if is on and - is either - fdatasync, fsync or - fsync_writethrough, otherwise zero). - See for more information about - the internal WAL function issue_xlog_fsync. - - - - - - wal_write_time double precision - - - Total amount of time spent writing WAL buffers to disk via - XLogWrite request, in milliseconds - (if is enabled, - otherwise zero). This includes the sync time when - wal_sync_method is either - open_datasync or open_sync. - - - - - - wal_sync_time double precision - - - Total amount of time spent syncing WAL files to disk via - issue_xlog_fsync request, in milliseconds - (if track_wal_io_timing is enabled, - fsync is on, and - wal_sync_method is either - fdatasync, fsync or - fsync_writethrough, otherwise zero). - - - stats_reset timestamp with time zone @@ -3393,8 +3516,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage Number of data page checksum failures detected in this - database (or on a shared object), or NULL if data checksums are not - enabled. + database (or on a shared object), or NULL if data checksums are + disabled. @@ -3404,8 +3527,8 @@ description | Waiting for a newly initialized WAL file to reach durable storage Time at which the last data page checksum failure was detected in - this database (or on a shared object), or NULL if data checksums are not - enabled. + this database (or on a shared object), or NULL if data checksums are + disabled. @@ -3508,6 +3631,24 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + parallel_workers_to_launch bigint + + + Number of parallel workers planned to be launched by queries on this database + + + + + + parallel_workers_launched bigint + + + Number of parallel workers launched by queries on this database + + + stats_reset timestamp with time zone @@ -3919,6 +4060,48 @@ description | Waiting for a newly initialized WAL file to reach durable storage daemon + + + + total_vacuum_time double precision + + + Total time this table has been manually vacuumed, in milliseconds. + (This includes the time spent sleeping due to cost-based delays.) + + + + + + total_autovacuum_time double precision + + + Total time this table has been vacuumed by the autovacuum daemon, + in milliseconds. (This includes the time spent sleeping due to + cost-based delays.) + + + + + + total_analyze_time double precision + + + Total time this table has been manually analyzed, in milliseconds. + (This includes the time spent sleeping due to cost-based delays.) + + + + + + total_autoanalyze_time double precision + + + Total time this table has been analyzed by the autovacuum daemon, + in milliseconds. (This includes the time spent sleeping due to + cost-based delays.) + + @@ -4074,16 +4257,35 @@ description | Waiting for a newly initialized WAL file to reach durable storage - Queries that use certain SQL constructs to search for - rows matching any value out of a list or array of multiple scalar values - (see ) perform multiple - primitive index scans (up to one primitive scan per scalar - value) during query execution. Each internal primitive index scan - increments pg_stat_all_indexes.idx_scan, + Index scans may sometimes perform multiple index searches per execution. + Each index search increments pg_stat_all_indexes.idx_scan, so it's possible for the count of index scans to significantly exceed the total number of index scan executor node executions. + + This can happen with queries that use certain SQL + constructs to search for rows matching any value out of a list or array of + multiple scalar values (see ). It + can also happen to queries with a + column_name = + value1 OR + column_name = + value2 ... construct, though only + when the optimizer transforms the construct into an equivalent + multi-valued array representation. Similarly, when B-tree index scans use + the skip scan optimization, an index search is performed each time the + scan is repositioned to the next index leaf page that might have matching + tuples (see ). + + + + EXPLAIN ANALYZE outputs the total number of index + searches performed by each index scan node. See + for an example demonstrating how + this works. + + @@ -4669,6 +4871,27 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + + pg_stat_get_backend_io + + pg_stat_get_backend_io ( integer ) + setof record + + + Returns I/O statistics about the backend with the specified + process ID. The output fields are exactly the same as the ones in the + pg_stat_io view. + + + The function does not return I/O statistics for the checkpointer, + the background writer, the startup process and the autovacuum launcher + as they are already visible in the pg_stat_io + view and there is only one of each. + + + @@ -4685,6 +4908,25 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + + pg_stat_get_backend_wal + + pg_stat_get_backend_wal ( integer ) + record + + + Returns WAL statistics about the backend with the specified + process ID. The output fields are exactly the same as the ones in the + pg_stat_wal view. + + + The function does not return WAL statistics for the checkpointer, + the background writer, the startup process and the autovacuum launcher. + + + @@ -4850,6 +5092,24 @@ description | Waiting for a newly initialized WAL file to reach durable storage + + + + pg_stat_reset_backend_stats + + pg_stat_reset_backend_stats ( integer ) + void + + + Resets statistics for a single backend with the specified process ID + to zero. + + + This function is restricted to superusers by default, but other users + can be granted EXECUTE to run the function. + + + @@ -5382,6 +5642,18 @@ FROM pg_stat_get_backend_idset() AS backendid; acquiring inherited sample rows. + + + + delay_time double precision + + + Total time spent sleeping due to cost-based delay (see + , in milliseconds + (if is enabled, otherwise + zero). + + @@ -5449,9 +5721,9 @@ FROM pg_stat_get_backend_idset() AS backendid; - Note that when ANALYZE is run on a partitioned table, - all of its partitions are also recursively analyzed. - In that case, ANALYZE + Note that when ANALYZE is run on a partitioned table + without the ONLY keyword, all of its partitions are + also recursively analyzed. In that case, ANALYZE progress is reported first for the parent table, whereby its inheritance statistics are collected, followed by that for each partition. @@ -6307,6 +6579,21 @@ FROM pg_stat_get_backend_idset() AS backendid; cleaning up indexes. + + + + delay_time double precision + + + Total time spent sleeping due to cost-based delay (see + ), in milliseconds + (if is enabled, otherwise + zero). This includes the time that any associated parallel workers have + slept. However, parallel workers report their sleep time no more + frequently than once per second, so the reported value may be slightly + stale. + + diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index 380d0c9e8051e..049ee75a4ba3b 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -417,8 +417,8 @@ does not see effects of those commands on other rows in the database. This behavior makes Read Committed mode unsuitable for commands that involve complex search conditions; however, it is just right for simpler - cases. For example, consider updating bank balances with transactions - like: + cases. For example, consider transferring $100 from one account + to another: BEGIN; @@ -427,8 +427,8 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 7534; COMMIT; - If two such transactions concurrently try to change the balance of account - 12345, we clearly want the second transaction to start with the updated + If another transaction concurrently tries to change the balance of account + 7534, we clearly want the second statement to start with the updated version of the account's row. Because each command is affecting only a predetermined row, letting it see the updated version of the row does not create any troublesome inconsistency. diff --git a/doc/src/sgml/oauth-validators.sgml b/doc/src/sgml/oauth-validators.sgml new file mode 100644 index 0000000000000..704089dd7b3cb --- /dev/null +++ b/doc/src/sgml/oauth-validators.sgml @@ -0,0 +1,416 @@ + + + + OAuth Validator Modules + + OAuth Validators + + + PostgreSQL provides infrastructure for creating + custom modules to perform server-side validation of OAuth bearer tokens. + Because OAuth implementations vary so wildly, and bearer token validation is + heavily dependent on the issuing party, the server cannot check the token + itself; validator modules provide the integration layer between the server + and the OAuth provider in use. + + + OAuth validator modules must at least consist of an initialization function + (see ) and the required callback for + performing validation (see ). + + + + Since a misbehaving validator might let unauthorized users into the database, + correct implementation is crucial for server safety. See + for design considerations. + + + + + Safely Designing a Validator Module + + + Read and understand the entirety of this section before implementing a + validator module. A malfunctioning validator is potentially worse than no + authentication at all, both because of the false sense of security it + provides, and because it may contribute to attacks against other pieces of + an OAuth ecosystem. + + + + + Validator Responsibilities + + Although different modules may take very different approaches to token + validation, implementations generally need to perform three separate + actions: + + + + Validate the Token + + + The validator must first ensure that the presented token is in fact a + valid Bearer token for use in client authentication. The correct way to + do this depends on the provider, but it generally involves either + cryptographic operations to prove that the token was created by a trusted + party (offline validation), or the presentation of the token to that + trusted party so that it can perform validation for you (online + validation). + + + Online validation, usually implemented via + OAuth Token + Introspection, requires fewer steps of a validator module and + allows central revocation of a token in the event that it is stolen + or misissued. However, it does require the module to make at least one + network call per authentication attempt (all of which must complete + within the configured ). + Additionally, your provider may not provide introspection endpoints for + use by external resource servers. + + + Offline validation is much more involved, typically requiring a validator + to maintain a list of trusted signing keys for a provider and then + check the token's cryptographic signature along with its contents. + Implementations must follow the provider's instructions to the letter, + including any verification of issuer ("where is this token from?"), + audience ("who is this token for?"), and validity period ("when can this + token be used?"). Since there is no communication between the module and + the provider, tokens cannot be centrally revoked using this method; + offline validator implementations may wish to place restrictions on the + maximum length of a token's validity period. + + + If the token cannot be validated, the module should immediately fail. + Further authentication/authorization is pointless if the bearer token + wasn't issued by a trusted party. + + + + + Authorize the Client + + + Next the validator must ensure that the end user has given the client + permission to access the server on their behalf. This generally involves + checking the scopes that have been assigned to the token, to make sure + that they cover database access for the current HBA parameters. + + + The purpose of this step is to prevent an OAuth client from obtaining a + token under false pretenses. If the validator requires all tokens to + carry scopes that cover database access, the provider should then loudly + prompt the user to grant that access during the flow. This gives them the + opportunity to reject the request if the client isn't supposed to be + using their credentials to connect to databases. + + + While it is possible to establish client authorization without explicit + scopes by using out-of-band knowledge of the deployed architecture, doing + so removes the user from the loop, which prevents them from catching + deployment mistakes and allows any such mistakes to be exploited + silently. Access to the database must be tightly restricted to only + trusted clients + + + That is, "trusted" in the sense that the OAuth client and the + PostgreSQL server are controlled by the same + entity. Notably, the Device Authorization client flow supported by + libpq does not usually meet this bar, since it's designed for use by + public/untrusted clients. + + + if users are not prompted for additional scopes. + + + Even if authorization fails, a module may choose to continue to pull + authentication information from the token for use in auditing and + debugging. + + + + + Authenticate the End User + + + Finally, the validator should determine a user identifier for the token, + either by asking the provider for this information or by extracting it + from the token itself, and return that identifier to the server (which + will then make a final authorization decision using the HBA + configuration). This identifier will be available within the session via + system_user + and recorded in the server logs if + is enabled. + + + Different providers may record a variety of different authentication + information for an end user, typically referred to as + claims. Providers usually document which of these + claims are trustworthy enough to use for authorization decisions and + which are not. (For instance, it would probably not be wise to use an + end user's full name as the identifier for authentication, since many + providers allow users to change their display names arbitrarily.) + Ultimately, the choice of which claim (or combination of claims) to use + comes down to the provider implementation and application requirements. + + + Note that anonymous/pseudonymous login is possible as well, by enabling + usermap delegation; see + . + + + + + + + + General Coding Guidelines + + Developers should keep the following in mind when implementing token + validation: + + + + Token Confidentiality + + + Modules should not write tokens, or pieces of tokens, into the server + log. This is true even if the module considers the token invalid; an + attacker who confuses a client into communicating with the wrong provider + should not be able to retrieve that (otherwise valid) token from the + disk. + + + Implementations that send tokens over the network (for example, to + perform online token validation with a provider) must authenticate the + peer and ensure that strong transport security is in use. + + + + + Logging + + + Modules may use the same logging + facilities as standard extensions; however, the rules for emitting + log entries to the client are subtly different during the authentication + phase of the connection. Generally speaking, modules should log + verification problems at the COMMERROR level and return + normally, instead of using ERROR/FATAL + to unwind the stack, to avoid leaking information to unauthenticated + clients. + + + + + Interruptibility + + + Modules must remain interruptible by signals so that the server can + correctly handle authentication timeouts and shutdown signals from + pg_ctl. For example, blocking calls on sockets + should generally be replaced with code that handles both socket events + and interrupts without races (see WaitLatchOrSocket(), + WaitEventSetWait(), et al), and long-running loops + should periodically call CHECK_FOR_INTERRUPTS(). + Failure to follow this guidance may result in unresponsive backend + sessions. + + + + + Testing + + + The breadth of testing an OAuth system is well beyond the scope of this + documentation, but at minimum, negative testing should be considered + mandatory. It's trivial to design a module that lets authorized users in; + the whole point of the system is to keep unauthorized users out. + + + + + Documentation + + + Validator implementations should document the contents and format of the + authenticated ID that is reported to the server for each end user, since + DBAs may need to use this information to construct pg_ident maps. (For + instance, is it an email address? an organizational ID number? a UUID?) + They should also document whether or not it is safe to use the module in + delegate_ident_mapping=1 mode, and what additional + configuration is required in order to do so. + + + + + + + + Authorizing Users (Usermap Delegation) + + The standard deliverable of a validation module is the user identifier, + which the server will then compare to any configured + pg_ident.conf + mappings and determine whether the end user is authorized to connect. + However, OAuth is itself an authorization framework, and tokens may carry + information about user privileges. For example, a token may be associated + with the organizational groups that a user belongs to, or list the roles + that a user may assume, and duplicating that knowledge into local usermaps + for every server may not be desirable. + + + To bypass username mapping entirely, and have the validator module assume + the additional responsibility of authorizing user connections, the HBA may + be configured with . + The module may then use token scopes or an equivalent method to decide + whether the user is allowed to connect under their desired role. The user + identifier will still be recorded by the server, but it plays no part in + determining whether to continue the connection. + + + Using this scheme, authentication itself is optional. As long as the module + reports that the connection is authorized, login will continue even if there + is no recorded user identifier at all. This makes it possible to implement + anonymous or pseudonymous access to the database, where the third-party + provider performs all necessary authentication but does not provide any + user-identifying information to the server. (Some providers may create an + anonymized ID number that can be recorded instead, for later auditing.) + + + Usermap delegation provides the most architectural flexibility, but it turns + the validator module into a single point of failure for connection + authorization. Use with caution. + + + + + + Initialization Functions + + _PG_oauth_validator_module_init + + + OAuth validator modules are dynamically loaded from the shared + libraries listed in . + Modules are loaded on demand when requested from a login in progress. + The normal library search path is used to locate the library. To + provide the validator callbacks and to indicate that the library is an OAuth + validator module a function named + _PG_oauth_validator_module_init must be provided. The + return value of the function must be a pointer to a struct of type + OAuthValidatorCallbacks, which contains a magic + number and pointers to the module's token validation functions. The returned + pointer must be of server lifetime, which is typically achieved by defining + it as a static const variable in global scope. + +typedef struct OAuthValidatorCallbacks +{ + uint32 magic; /* must be set to PG_OAUTH_VALIDATOR_MAGIC */ + + ValidatorStartupCB startup_cb; + ValidatorShutdownCB shutdown_cb; + ValidatorValidateCB validate_cb; +} OAuthValidatorCallbacks; + +typedef const OAuthValidatorCallbacks *(*OAuthValidatorModuleInit) (void); + + + Only the validate_cb callback is required, the others + are optional. + + + + + OAuth Validator Callbacks + + OAuth validator modules implement their functionality by defining a set of + callbacks. The server will call them as required to process the + authentication request from the user. + + + + Startup Callback + + The startup_cb callback is executed directly after + loading the module. This callback can be used to set up local state and + perform additional initialization if required. If the validator module + has state it can use state->private_data to + store it. + + +typedef void (*ValidatorStartupCB) (ValidatorModuleState *state); + + + + + + Validate Callback + + The validate_cb callback is executed during the OAuth + exchange when a user attempts to authenticate using OAuth. Any state set in + previous calls will be available in state->private_data. + + +typedef bool (*ValidatorValidateCB) (const ValidatorModuleState *state, + const char *token, const char *role, + ValidatorModuleResult *result); + + + token will contain the bearer token to validate. + PostgreSQL has ensured that the token is well-formed syntactically, but no + other validation has been performed. role will + contain the role the user has requested to log in as. The callback must + set output parameters in the result struct, which is + defined as below: + + +typedef struct ValidatorModuleResult +{ + bool authorized; + char *authn_id; +} ValidatorModuleResult; + + + The connection will only proceed if the module sets + result->authorized to true. To + authenticate the user, the authenticated user name (as determined using the + token) shall be palloc'd and returned in the result->authn_id + field. Alternatively, result->authn_id may be set to + NULL if the token is valid but the associated user identity cannot be + determined. + + + A validator may return false to signal an internal error, + in which case any result parameters are ignored and the connection fails. + Otherwise the validator should return true to indicate + that it has processed the token and made an authorization decision. + + + The behavior after validate_cb returns depends on the + specific HBA setup. Normally, the result->authn_id user + name must exactly match the role that the user is logging in as. (This + behavior may be modified with a usermap.) But when authenticating against + an HBA rule with delegate_ident_mapping turned on, + PostgreSQL will not perform any checks on the value of + result->authn_id at all; in this case it is up to the + validator to ensure that the token carries enough privileges for the user to + log in under the indicated role. + + + + + Shutdown Callback + + The shutdown_cb callback is executed when the backend + process associated with the connection exits. If the validator module has + any allocated state, this callback should free it to avoid resource leaks. + +typedef void (*ValidatorShutdownCB) (ValidatorModuleState *state); + + + + + + diff --git a/doc/src/sgml/pageinspect.sgml b/doc/src/sgml/pageinspect.sgml index 27e0598f74c01..487c5d758ffbf 100644 --- a/doc/src/sgml/pageinspect.sgml +++ b/doc/src/sgml/pageinspect.sgml @@ -85,7 +85,7 @@ test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); The checksum field is the checksum stored in the page, which might be incorrect if the page is somehow corrupted. If - data checksums are not enabled for this instance, then the value stored + data checksums are disabled for this instance, then the value stored is meaningless. diff --git a/doc/src/sgml/parallel.sgml b/doc/src/sgml/parallel.sgml index 590cb385ddfcf..1ce9abf86f525 100644 --- a/doc/src/sgml/parallel.sgml +++ b/doc/src/sgml/parallel.sgml @@ -423,7 +423,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%'; Append node can have both partial and non-partial child plans. Non-partial children will be scanned by only a single process, since scanning them more than once would produce duplicate results. Plans that - involve appending multiple results sets can therefore achieve + involve appending multiple result sets can therefore achieve coarse-grained parallelism even when efficient partial plans are not available. For example, consider a query against a partitioned table that can only be implemented efficiently by using an index that does @@ -510,12 +510,6 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%'; - - - Plan nodes to which an InitPlan is attached. - - - Plan nodes that reference a correlated SubPlan. diff --git a/doc/src/sgml/passwordcheck.sgml b/doc/src/sgml/passwordcheck.sgml index 601f489227223..7ea32410463b6 100644 --- a/doc/src/sgml/passwordcheck.sgml +++ b/doc/src/sgml/passwordcheck.sgml @@ -59,4 +59,41 @@ + + Configuration Parameters + + + + + passwordcheck.min_password_length (integer) + + passwordcheck.min_password_length configuration parameter + + + + + The minimum acceptable password length in bytes. The default is 8. Only + superusers can change this setting. + + + + This parameter has no effect if a user supplies a pre-encrypted + password. + + + + + + + + In ordinary usage, this parameter is set in + postgresql.conf, but superusers can alter it on-the-fly + within their own sessions. Typical usage might be: + + + +# postgresql.conf +passwordcheck.min_password_length = 12 + + diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index ff689b65245fc..106583fb2965d 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -39,7 +39,7 @@ Examples in this section are drawn from the regression test database - after doing a VACUUM ANALYZE, using v17 development sources. + after doing a VACUUM ANALYZE, using v18 development sources. You should be able to get similar results if you try the examples yourself, but your estimated costs and row counts might vary slightly because ANALYZE's statistics are random samples rather @@ -578,6 +578,31 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2; discussed below. + + When using the enable/disable flags to disable plan node types, many of + the flags only discourage the use of the corresponding plan node and don't + outright disallow the planner's ability to use the plan node type. This + is by design so that the planner still maintains the ability to form a + plan for a given query. When the resulting plan contains a disabled node, + the EXPLAIN output will indicate this fact. + + +SET enable_seqscan = off; +EXPLAIN SELECT * FROM unit; + + QUERY PLAN +--------------------------------------------------------- + Seq Scan on unit (cost=0.00..21.30 rows=1130 width=44) + Disabled: true + + + + + Because the unit table has no indexes, there is no + other means to read the table data, so the sequential scan is the only + option available to the query planner. + + subplan @@ -696,14 +721,22 @@ WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------------------------------- - Nested Loop (cost=4.65..118.50 rows=10 width=488) (actual time=0.017..0.051 rows=10 loops=1) - -> Bitmap Heap Scan on tenk1 t1 (cost=4.36..39.38 rows=10 width=244) (actual time=0.009..0.017 rows=10 loops=1) + Nested Loop (cost=4.65..118.50 rows=10 width=488) (actual time=0.017..0.051 rows=10.00 loops=1) + Buffers: shared hit=36 read=6 + -> Bitmap Heap Scan on tenk1 t1 (cost=4.36..39.38 rows=10 width=244) (actual time=0.009..0.017 rows=10.00 loops=1) Recheck Cond: (unique1 < 10) Heap Blocks: exact=10 - -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..4.36 rows=10 width=0) (actual time=0.004..0.004 rows=10 loops=1) + Buffers: shared hit=3 read=5 written=4 + -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..4.36 rows=10 width=0) (actual time=0.004..0.004 rows=10.00 loops=1) Index Cond: (unique1 < 10) - -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.29..7.90 rows=1 width=244) (actual time=0.003..0.003 rows=1 loops=10) + Index Searches: 1 + Buffers: shared hit=2 + -> Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.29..7.90 rows=1 width=244) (actual time=0.003..0.003 rows=1.00 loops=10) Index Cond: (unique2 = t1.unique2) + Index Searches: 10 + Buffers: shared hit=24 read=6 + Planning: + Buffers: shared hit=15 dirtied=9 Planning Time: 0.485 ms Execution Time: 0.073 ms @@ -741,19 +774,28 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------------------------------------&zwsp;------ - Sort (cost=713.05..713.30 rows=100 width=488) (actual time=2.995..3.002 rows=100 loops=1) + Sort (cost=713.05..713.30 rows=100 width=488) (actual time=2.995..3.002 rows=100.00 loops=1) Sort Key: t1.fivethous Sort Method: quicksort Memory: 74kB - -> Hash Join (cost=226.23..709.73 rows=100 width=488) (actual time=0.515..2.920 rows=100 loops=1) + Buffers: shared hit=440 + -> Hash Join (cost=226.23..709.73 rows=100 width=488) (actual time=0.515..2.920 rows=100.00 loops=1) Hash Cond: (t2.unique2 = t1.unique2) - -> Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.026..1.790 rows=10000 loops=1) - -> Hash (cost=224.98..224.98 rows=100 width=244) (actual time=0.476..0.477 rows=100 loops=1) + Buffers: shared hit=437 + -> Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.026..1.790 rows=10000.00 loops=1) + Buffers: shared hit=345 + -> Hash (cost=224.98..224.98 rows=100 width=244) (actual time=0.476..0.477 rows=100.00 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 35kB - -> Bitmap Heap Scan on tenk1 t1 (cost=5.06..224.98 rows=100 width=244) (actual time=0.030..0.450 rows=100 loops=1) + Buffers: shared hit=92 + -> Bitmap Heap Scan on tenk1 t1 (cost=5.06..224.98 rows=100 width=244) (actual time=0.030..0.450 rows=100.00 loops=1) Recheck Cond: (unique1 < 100) Heap Blocks: exact=90 - -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.013..0.013 rows=100 loops=1) + Buffers: shared hit=92 + -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.013..0.013 rows=100.00 loops=1) Index Cond: (unique1 < 100) + Index Searches: 1 + Buffers: shared hit=2 + Planning: + Buffers: shared hit=12 Planning Time: 0.187 ms Execution Time: 3.036 ms @@ -766,6 +808,90 @@ WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous; shown.) + + Index Scan nodes (as well as Bitmap Index Scan and Index-Only Scan nodes) + show an Index Searches line that reports the total number + of searches across all node + executions/loops: + + +EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE thousand IN (1, 500, 700, 999); + QUERY PLAN +-------------------------------------------------------------------&zwsp;--------------------------------------------------------------- + Bitmap Heap Scan on tenk1 (cost=9.45..73.44 rows=40 width=244) (actual time=0.012..0.028 rows=40.00 loops=1) + Recheck Cond: (thousand = ANY ('{1,500,700,999}'::integer[])) + Heap Blocks: exact=39 + Buffers: shared hit=47 + -> Bitmap Index Scan on tenk1_thous_tenthous (cost=0.00..9.44 rows=40 width=0) (actual time=0.009..0.009 rows=40.00 loops=1) + Index Cond: (thousand = ANY ('{1,500,700,999}'::integer[])) + Index Searches: 4 + Buffers: shared hit=8 + Planning Time: 0.029 ms + Execution Time: 0.034 ms + + + Here we see a Bitmap Index Scan node that needed 4 separate index + searches. The scan had to search the index from the + tenk1_thous_tenthous index root page once per + integer value from the predicate's IN + construct. However, the number of index searches often won't have such a + simple correspondence to the query predicate: + + +EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE thousand IN (1, 2, 3, 4); + QUERY PLAN +-------------------------------------------------------------------&zwsp;--------------------------------------------------------------- + Bitmap Heap Scan on tenk1 (cost=9.45..73.44 rows=40 width=244) (actual time=0.009..0.019 rows=40.00 loops=1) + Recheck Cond: (thousand = ANY ('{1,2,3,4}'::integer[])) + Heap Blocks: exact=38 + Buffers: shared hit=40 + -> Bitmap Index Scan on tenk1_thous_tenthous (cost=0.00..9.44 rows=40 width=0) (actual time=0.005..0.005 rows=40.00 loops=1) + Index Cond: (thousand = ANY ('{1,2,3,4}'::integer[])) + Index Searches: 1 + Buffers: shared hit=2 + Planning Time: 0.029 ms + Execution Time: 0.026 ms + + + This variant of our IN query performed only 1 index + search. It spent less time traversing the index (compared to the original + query) because its IN construct uses values matching + index tuples stored next to each other, on the same + tenk1_thous_tenthous index leaf page. + + + + The Index Searches line is also useful with B-tree index + scans that apply the skip scan optimization to + more efficiently traverse through an index: + +EXPLAIN ANALYZE SELECT four, unique1 FROM tenk1 WHERE four BETWEEN 1 AND 3 AND unique1 = 42; + QUERY PLAN +-------------------------------------------------------------------&zwsp;--------------------------------------------------------------- + Index Only Scan using tenk1_four_unique1_idx on tenk1 (cost=0.29..6.90 rows=1 width=8) (actual time=0.006..0.007 rows=1.00 loops=1) + Index Cond: ((four >= 1) AND (four <= 3) AND (unique1 = 42)) + Heap Fetches: 0 + Index Searches: 3 + Buffers: shared hit=7 + Planning Time: 0.029 ms + Execution Time: 0.012 ms + + + Here we see an Index-Only Scan node using + tenk1_four_unique1_idx, a multi-column index on the + tenk1 table's four and + unique1 columns. The scan performs 3 searches + that each read a single index leaf page: + four = 1 AND unique1 = 42, + four = 2 AND unique1 = 42, and + four = 3 AND unique1 = 42. This index + is generally a good target for skip scan, since, as discussed in + , its leading column (the + four column) contains only 4 distinct values, + while its second/final column (the unique1 + column) contains many distinct values. + + Another type of extra information is the number of rows removed by a filter condition: @@ -775,9 +901,10 @@ EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE ten < 7; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------- - Seq Scan on tenk1 (cost=0.00..470.00 rows=7000 width=244) (actual time=0.030..1.995 rows=7000 loops=1) + Seq Scan on tenk1 (cost=0.00..470.00 rows=7000 width=244) (actual time=0.030..1.995 rows=7000.00 loops=1) Filter: (ten < 7) Rows Removed by Filter: 3000 + Buffers: shared hit=345 Planning Time: 0.102 ms Execution Time: 2.145 ms @@ -798,9 +925,10 @@ EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; QUERY PLAN -------------------------------------------------------------------&zwsp;----------------------------------- - Seq Scan on polygon_tbl (cost=0.00..1.09 rows=1 width=85) (actual time=0.023..0.023 rows=0 loops=1) + Seq Scan on polygon_tbl (cost=0.00..1.09 rows=1 width=85) (actual time=0.023..0.023 rows=0.00 loops=1) Filter: (f1 @> '((0.5,2))'::polygon) Rows Removed by Filter: 7 + Buffers: shared hit=1 Planning Time: 0.039 ms Execution Time: 0.033 ms @@ -817,9 +945,11 @@ EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------------------- - Index Scan using gpolygonind on polygon_tbl (cost=0.13..8.15 rows=1 width=85) (actual time=0.074..0.074 rows=0 loops=1) + Index Scan using gpolygonind on polygon_tbl (cost=0.13..8.15 rows=1 width=85) (actual time=0.074..0.074 rows=0.00 loops=1) Index Cond: (f1 @> '((0.5,2))'::polygon) Rows Removed by Index Recheck: 1 + Index Searches: 1 + Buffers: shared hit=1 Planning Time: 0.039 ms Execution Time: 0.098 ms @@ -832,34 +962,33 @@ EXPLAIN ANALYZE SELECT * FROM polygon_tbl WHERE f1 @> polygon '(0.5,2.0)'; - EXPLAIN has a BUFFERS option that can be used with - ANALYZE to get even more run time statistics: + EXPLAIN has a BUFFERS option which + provides additional detail about I/O operations performed during the + planning and execution of the given query. The buffer numbers displayed + show the count of the non-distinct buffers hit, read, dirtied, and written + for the given node and all of its child nodes. The + ANALYZE option implicitly enables the + BUFFERS option. If this + is undesired, BUFFERS may be explicitly disabled: -EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000; +EXPLAIN (ANALYZE, BUFFERS OFF) SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000; QUERY PLAN -------------------------------------------------------------------&zwsp;-------------------------------------------------------------- - Bitmap Heap Scan on tenk1 (cost=25.07..60.11 rows=10 width=244) (actual time=0.105..0.114 rows=10 loops=1) + Bitmap Heap Scan on tenk1 (cost=25.07..60.11 rows=10 width=244) (actual time=0.105..0.114 rows=10.00 loops=1) Recheck Cond: ((unique1 < 100) AND (unique2 > 9000)) Heap Blocks: exact=10 - Buffers: shared hit=14 read=3 - -> BitmapAnd (cost=25.07..25.07 rows=10 width=0) (actual time=0.100..0.101 rows=0 loops=1) - Buffers: shared hit=4 read=3 - -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.027..0.027 rows=100 loops=1) + -> BitmapAnd (cost=25.07..25.07 rows=10 width=0) (actual time=0.100..0.101 rows=0.00 loops=1) + -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.027..0.027 rows=100.00 loops=1) Index Cond: (unique1 < 100) - Buffers: shared hit=2 - -> Bitmap Index Scan on tenk1_unique2 (cost=0.00..19.78 rows=999 width=0) (actual time=0.070..0.070 rows=999 loops=1) + Index Searches: 1 + -> Bitmap Index Scan on tenk1_unique2 (cost=0.00..19.78 rows=999 width=0) (actual time=0.070..0.070 rows=999.00 loops=1) Index Cond: (unique2 > 9000) - Buffers: shared hit=2 read=3 - Planning: - Buffers: shared hit=3 + Index Searches: 1 Planning Time: 0.162 ms Execution Time: 0.143 ms - - The numbers provided by BUFFERS help to identify which parts - of the query are the most I/O-intensive. @@ -877,12 +1006,15 @@ EXPLAIN ANALYZE UPDATE tenk1 SET hundred = hundred + 1 WHERE unique1 < 100; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------------------------- - Update on tenk1 (cost=5.06..225.23 rows=0 width=0) (actual time=1.634..1.635 rows=0 loops=1) - -> Bitmap Heap Scan on tenk1 (cost=5.06..225.23 rows=100 width=10) (actual time=0.065..0.141 rows=100 loops=1) + Update on tenk1 (cost=5.06..225.23 rows=0 width=0) (actual time=1.634..1.635 rows=0.00 loops=1) + -> Bitmap Heap Scan on tenk1 (cost=5.06..225.23 rows=100 width=10) (actual time=0.065..0.141 rows=100.00 loops=1) Recheck Cond: (unique1 < 100) Heap Blocks: exact=90 - -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.031..0.031 rows=100 loops=1) + Buffers: shared hit=4 read=2 + -> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=100 width=0) (actual time=0.031..0.031 rows=100.00 loops=1) Index Cond: (unique1 < 100) + Index Searches: 1 + Buffers: shared read=2 Planning Time: 0.151 ms Execution Time: 1.856 ms @@ -1014,11 +1146,14 @@ EXPLAIN ANALYZE SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------------------------ - Limit (cost=0.29..14.33 rows=2 width=244) (actual time=0.051..0.071 rows=2 loops=1) - -> Index Scan using tenk1_unique2 on tenk1 (cost=0.29..70.50 rows=10 width=244) (actual time=0.051..0.070 rows=2 loops=1) + Limit (cost=0.29..14.33 rows=2 width=244) (actual time=0.051..0.071 rows=2.00 loops=1) + Buffers: shared hit=16 + -> Index Scan using tenk1_unique2 on tenk1 (cost=0.29..70.50 rows=10 width=244) (actual time=0.051..0.070 rows=2.00 loops=1) Index Cond: (unique2 > 9000) Filter: (unique1 < 100) Rows Removed by Filter: 287 + Index Searches: 1 + Buffers: shared hit=16 Planning Time: 0.077 ms Execution Time: 0.086 ms diff --git a/doc/src/sgml/pgbuffercache.sgml b/doc/src/sgml/pgbuffercache.sgml index 4b90eefc0b078..537d601494242 100644 --- a/doc/src/sgml/pgbuffercache.sgml +++ b/doc/src/sgml/pgbuffercache.sgml @@ -27,12 +27,24 @@ pg_buffercache_evict + + pg_buffercache_evict_relation + + + + pg_buffercache_evict_all + + This module provides the pg_buffercache_pages() function (wrapped in the pg_buffercache view), - the pg_buffercache_summary() function, the - pg_buffercache_usage_counts() function and - the pg_buffercache_evict() function. + pg_buffercache_numa_pages() function (wrapped in the + pg_buffercache_numa view), the + pg_buffercache_summary() function, the + pg_buffercache_usage_counts() function, the + pg_buffercache_evict(), the + pg_buffercache_evict_relation() function and the + pg_buffercache_evict_all() function. @@ -42,6 +54,15 @@ convenient use. + + The pg_buffercache_numa_pages() provides + NUMA node mappings for shared buffer entries. This + information is not part of pg_buffercache_pages() + itself, as it is much slower to retrieve. + The pg_buffercache_numa view wraps the function for + convenient use. + + The pg_buffercache_summary() function returns a single row summarizing the state of the shared buffer cache. @@ -65,6 +86,19 @@ function is restricted to superusers only. + + The pg_buffercache_evict_relation() function allows all + unpinned shared buffers in the relation to be evicted from the buffer pool + given a relation identifier. Use of this function is restricted to + superusers only. + + + + The pg_buffercache_evict_all() function allows all + unpinned shared buffers to be evicted in the buffer pool. Use of this + function is restricted to superusers only. + + The <structname>pg_buffercache</structname> View @@ -200,6 +234,78 @@ + + The <structname>pg_buffercache_numa</structname> View + + + The definitions of the columns exposed by the view are shown in . + + + + <structname>pg_buffercache_numa</structname> Columns + + + + + Column Type + + + Description + + + + + + + + bufferid integer + + + ID, in the range 1..shared_buffers + + + + + + os_page_num bigint + + + number of OS memory page for this buffer + + + + + + numa_node int + + + ID of NUMA node + + + + + +
+ + + As NUMA node ID inquiry for each page requires memory pages + to be paged-in, the first execution of this function can take a noticeable + amount of time. In all the cases (first execution or not), retrieving this + information is costly and querying the view at a high frequency is not recommended. + + + + + When determining the NUMA node, the view touches + all memory pages for the shared memory segment. This will force + allocation of the shared memory, if it wasn't allocated already, + and the memory may get allocated in a single NUMA + node (depending on system configuration). + + + +
+ The <function>pg_buffercache_summary()</function> Function @@ -365,15 +471,53 @@ - The <structname>pg_buffercache_evict</structname> Function + The <function>pg_buffercache_evict()</function> Function The pg_buffercache_evict() function takes a buffer identifier, as shown in the bufferid column of - the pg_buffercache view. It returns true on success, - and false if the buffer wasn't valid, if it couldn't be evicted because it - was pinned, or if it became dirty again after an attempt to write it out. - The result is immediately out of date upon return, as the buffer might - become valid again at any time due to concurrent activity. The function is + the pg_buffercache view. It returns information + about whether the buffer was evicted and flushed. The buffer_evicted + column is true on success, and false if the buffer wasn't valid, if it + couldn't be evicted because it was pinned, or if it became dirty again + after an attempt to write it out. The buffer_flushed column is true if the + buffer was flushed. This does not necessarily mean that buffer was flushed + by us, it might be flushed by someone else. The result is immediately out + of date upon return, as the buffer might become valid again at any time due + to concurrent activity. The function is intended for developer testing + only. + + + + + The <structname>pg_buffercache_evict_relation</structname> Function + + The pg_buffercache_evict_relation() function is very + similar to the pg_buffercache_evict() function. The + difference is that the pg_buffercache_evict_relation() + takes a relation identifier instead of buffer identifier. It tries to + evict all buffers for all forks in that relation. + + It returns the number of evicted buffers, flushed buffers and the number of + buffers that could not be evicted. Flushed buffers haven't necessarily + been flushed by us, they might have been flushed by someone else. The + result is immediately out of date upon return, as buffers might immediately + be read back in due to concurrent activity. The function is intended for + developer testing only. + + + + + The <structname>pg_buffercache_evict_all</structname> Function + + The pg_buffercache_evict_all() function is very + similar to the pg_buffercache_evict() function. The + difference is, the pg_buffercache_evict_all() function + does not take an argument; instead it tries to evict all buffers in the + buffer pool. It returns the number of evicted buffers, flushed buffers and + the number of buffers that could not be evicted. Flushed buffers haven't + necessarily been flushed by us, they might have been flushed by someone + else. The result is immediately out of date upon return, as buffers might + immediately be read back in due to concurrent activity. The function is intended for developer testing only. diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml index b8b89696e7f68..bc5c74ad017fa 100644 --- a/doc/src/sgml/pgcrypto.sgml +++ b/doc/src/sgml/pgcrypto.sgml @@ -106,7 +106,7 @@ hmac(data bytea, key bytea, type text) returns bytea The algorithms in crypt() differ from the usual - MD5 or SHA1 hashing algorithms in the following respects: + MD5 or SHA-1 hashing algorithms in the following respects: @@ -146,6 +146,12 @@ hmac(data bytea, key bytea, type text) returns bytea Supported Algorithms for <function>crypt()</function> + + + + + + Algorithm @@ -189,6 +195,29 @@ hmac(data bytea, key bytea, type text) returns bytea 13 Original UNIX crypt + + sha256crypt + unlimited + yes + up to 32 + 80 + Adapted from publicly available reference implementation + Unix crypt using SHA-256 and SHA-512 + + + + + sha512crypt + unlimited + yes + up to 32 + 123 + Adapted from publicly available reference implementation + Unix crypt using SHA-256 and SHA-512 + + + +
@@ -245,7 +274,9 @@ gen_salt(type text [, iter_count integer ]) returns text The type parameter specifies the hashing algorithm. The accepted types are: des, xdes, - md5 and bf. + md5, bf, sha256crypt and + sha512crypt. The last two, sha256crypt and + sha512crypt are modern SHA-2 based password hashes. @@ -284,6 +315,12 @@ gen_salt(type text [, iter_count integer ]) returns text 4 31 + + sha256crypt, sha512crypt + 5000 + 1000 + 999999999 + @@ -313,6 +350,14 @@ gen_salt(type text [, iter_count integer ]) returns text gen_salt. + + The default iter_count for sha256crypt and + sha512crypt of 5000 is considered too low for modern + hardware, but can be adjusted to generate stronger password hashes. + Otherwise both hashes, sha256crypt and sha512crypt are + considered safe. + + Hash Algorithm Speeds @@ -525,7 +570,7 @@ gen_salt(type text [, iter_count integer ]) returns text - A SHA1 hash of the random prefix and data is appended. + A SHA-1 hash of the random prefix and data is appended. @@ -1082,6 +1127,11 @@ decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea cbc — next block depends on previous (default) + + + cfb — next block depends on previous encrypted block + + ecb — each block is encrypted separately (for @@ -1112,7 +1162,8 @@ encrypt(data, 'fooz', 'bf-cbc/pad:pkcs') In encrypt_iv and decrypt_iv, the - iv parameter is the initial value for the CBC mode; + iv parameter is the initial value for the CBC and + CFB mode; it is ignored for ECB. It is clipped or padded with zeroes if not exactly block size. It defaults to all zeroes in the functions without this parameter. @@ -1149,6 +1200,60 @@ gen_random_uuid() returns uuid + + OpenSSL Support Functions + + + fips_mode + + + +fips_mode() returns boolean + + + Returns true if OpenSSL is + running with FIPS mode enabled, otherwise false. + + + + + Configuration Parameters + + + There is one configuration parameter that controls the behavior of + pgcrypto. + + + + + + pgcrypto.builtin_crypto_enabled (enum) + + pgcrypto.builtin_crypto_enabled configuration + parameter + + + + + pgcrypto.builtin_crypto_enabled determines if the + built in crypto functions gen_salt(), and + crypt() are available for use. Setting this to + off disables these functions. on + (the default) enables these functions to work normally. + fips disables these functions if + OpenSSL is detected to operate in FIPS mode. + + + + + + + In ordinary usage, this parameter is set + in postgresql.conf, although superusers can alter it + on-the-fly within their own sessions. + + + Notes diff --git a/doc/src/sgml/pgfreespacemap.sgml b/doc/src/sgml/pgfreespacemap.sgml index 829ad60f32fdc..3774a9f8c6b29 100644 --- a/doc/src/sgml/pgfreespacemap.sgml +++ b/doc/src/sgml/pgfreespacemap.sgml @@ -67,7 +67,7 @@ For indexes, what is tracked is entirely-unused pages, rather than free space within pages. Therefore, the values are not meaningful, just - whether a page is full or empty. + whether a page is in-use or empty. diff --git a/doc/src/sgml/pglogicalinspect.sgml b/doc/src/sgml/pglogicalinspect.sgml new file mode 100644 index 0000000000000..4b111f961133b --- /dev/null +++ b/doc/src/sgml/pglogicalinspect.sgml @@ -0,0 +1,143 @@ + + + + pg_logicalinspect — logical decoding components inspection + + + pg_logicalinspect + + + + The pg_logicalinspect module provides SQL functions + that allow you to inspect the contents of logical decoding components. It + allows the inspection of serialized logical snapshots of a running + PostgreSQL database cluster, which is useful + for debugging or educational purposes. + + + + By default, use of these functions is restricted to superusers and members of + the pg_read_server_files role. Access may be granted by + superusers to others using GRANT. + + + + Functions + + + + + pg_get_logical_snapshot_meta(filename text) returns record + + + + + Gets logical snapshot metadata about a snapshot file that is located in + the server's pg_logical/snapshots directory. + The filename argument represents the snapshot + file name. + For example: + +postgres=# SELECT * FROM pg_ls_logicalsnapdir(); +-[ RECORD 1 ]+----------------------- +name | 0-40796E18.snap +size | 152 +modification | 2024-08-14 16:36:32+00 + +postgres=# SELECT * FROM pg_get_logical_snapshot_meta('0-40796E18.snap'); +-[ RECORD 1 ]-------- +magic | 1369563137 +checksum | 1028045905 +version | 6 + +postgres=# SELECT ss.name, meta.* FROM pg_ls_logicalsnapdir() AS ss, +pg_get_logical_snapshot_meta(ss.name) AS meta; +-[ RECORD 1 ]------------- +name | 0-40796E18.snap +magic | 1369563137 +checksum | 1028045905 +version | 6 + + + + If filename does not match a snapshot file, the + function raises an error. + + + + + + + pg_get_logical_snapshot_info(filename text) returns record + + + + + Gets logical snapshot information about a snapshot file that is located in + the server's pg_logical/snapshots directory. + The filename argument represents the snapshot + file name. + For example: + +postgres=# SELECT * FROM pg_ls_logicalsnapdir(); +-[ RECORD 1 ]+----------------------- +name | 0-40796E18.snap +size | 152 +modification | 2024-08-14 16:36:32+00 + +postgres=# SELECT * FROM pg_get_logical_snapshot_info('0-40796E18.snap'); +-[ RECORD 1 ]------------+----------- +state | consistent +xmin | 751 +xmax | 751 +start_decoding_at | 0/40796AF8 +two_phase_at | 0/40796AF8 +initial_xmin_horizon | 0 +building_full_snapshot | f +in_slot_creation | f +last_serialized_snapshot | 0/0 +next_phase_at | 0 +committed_count | 0 +committed_xip | +catchange_count | 2 +catchange_xip | {751,752} + +postgres=# SELECT ss.name, info.* FROM pg_ls_logicalsnapdir() AS ss, +pg_get_logical_snapshot_info(ss.name) AS info; +-[ RECORD 1 ]------------+---------------- +name | 0-40796E18.snap +state | consistent +xmin | 751 +xmax | 751 +start_decoding_at | 0/40796AF8 +two_phase_at | 0/40796AF8 +initial_xmin_horizon | 0 +building_full_snapshot | f +in_slot_creation | f +last_serialized_snapshot | 0/0 +next_phase_at | 0 +committed_count | 0 +committed_xip | +catchange_count | 2 +catchange_xip | {751,752} + + + + If filename does not match a snapshot file, the + function raises an error. + + + + + + + + + Author + + + Bertrand Drouvot bertranddrouvot.pg@gmail.com + + + + diff --git a/doc/src/sgml/pgoverexplain.sgml b/doc/src/sgml/pgoverexplain.sgml new file mode 100644 index 0000000000000..21930fbd3bd76 --- /dev/null +++ b/doc/src/sgml/pgoverexplain.sgml @@ -0,0 +1,186 @@ + + + + pg_overexplain — allow EXPLAIN to dump even more details + + + pg_overexplain + + + + The pg_overexplain extends EXPLAIN + with new options that provide additional output. It is mostly intended to + assist with debugging of and development of the planner, rather than for + general use. Since this module displays internal details of planner data + structures, it may be necessary to refer to the source code to make sense + of the output. Furthermore, the output is likely to change whenever (and as + often as) those data structures change. + + + + EXPLAIN (DEBUG) + + + The DEBUG option displays miscellaneous information from + the plan tree that is not normally shown because it is not expected to be + of general interest. For each individual plan node, it will display the + following fields. See Plan in + nodes/plannodes.h for additional documentation of these + fields. + + + + + + Disabled Nodes. Normal EXPLAIN + determines whether a node is disabled by checking whether the node's + count of disabled nodes is larger than the sum of the counts for the + underlying nodes. This option shows the raw counter value. + + + + + + Parallel Safe. Indicates whether it would be safe for + a plan tree node to appear beneath a Gather or + Gather Merge node, regardless of whether it is + actually below such a node. + + + + + + Plan Node ID. An internal ID number that should be + unique for every node in the plan tree. It is used to coordinate parallel + query activity. + + + + + + extParam and allParam. Information + about which numbered parameters affect this plan node or its children. In + text mode, these fields are only displayed if they are non-empty sets. + + + + + + Once per query, the DEBUG option will display the + following fields. See PlannedStmt in + nodes/plannodes.h for additional detail. + + + + + + Command Type. For example, select + or update. + + + + + + Flags. A comma-separated list of Boolean structure + member names from the PlannedStmt that are set to + true. It covers the following structure members: + hasReturning, hasModifyingCTE, + canSetTag, transientPlan, + dependsOnRole, parallelModeNeeded. + + + + + + Subplans Needing Rewind. Integer IDs of subplans that + may need to be rewound by the executor. + + + + + + Relation OIDs. OIDs of relations upon which this plan + depends. + + + + + + Executor Parameter Types. Type OID for each executor parameter + (e.g. when a nested loop is chosen and a parameter is used to pass a value down + to an inner index scan). Does not include parameters supplied to a prepared + statement by the user. + + + + + + Parse Location. Location within the query string + supplied to the planner where this query's text can be found. May be + Unknown in some contexts. Otherwise, may be + NNN to end for some integer NNN or + NNN for MMM bytes for some integers + NNN and MMM. + + + + + + + EXPLAIN (RANGE_TABLE) + + + The RANGE_TABLE option displays information from the + plan tree specifically concerning the query's range table. Range table + entries correspond roughly to items appearing in the query's + FROM clause, but with numerous exceptions. For example, + subqueries that are proved unnecessary may be deleted from the range table + entirely, while inheritance expansion adds range table entries for child + tables that are not named directly in the query. + + + + Range table entries are generally referenced within the query plan by a + range table index, or RTI. Plan nodes that reference one or more RTIs will + be labelled accordingly, using one of the following fields: Scan + RTI, Nominal RTI, Exclude Relation + RTI, Append RTIs. + + + + In addition, the query as a whole may maintain lists of range table indexes + that are needed for various purposes. These lists will be displayed once + per query, labelled as appropriate as Unprunable RTIs or + Result RTIs. In text mode, these fields are only + displayed if they are non-empty sets. + + + + Finally, but most importantly, the RANGE_TABLE option + will display a dump of the query's entire range table. Each range table + entry is labelled with the appropriate range table index, the kind of range + table entry (e.g. relation, + subquery, or join), followed by the + contents of various range table entry fields that are not normally part of + EXPLAIN output. Some of these fields are only displayed + for certain kinds of range table entries. For example, + Eref is displayed for all types of range table entries, + but CTE Name is displayed only for range table entries + of type cte. + + + + For more information about range table entries, see the definition of + RangeTblEntry in nodes/plannodes.h. + + + + + Author + + + Robert Haas rhaas@postgresql.org + + + + diff --git a/doc/src/sgml/pgstatstatements.sgml b/doc/src/sgml/pgstatstatements.sgml index 9b0aff73b1efe..7baa07dcdbf7f 100644 --- a/doc/src/sgml/pgstatstatements.sgml +++ b/doc/src/sgml/pgstatstatements.sgml @@ -436,6 +436,15 @@ + + + wal_buffers_full bigint + + + Number of times the WAL buffers became full + + + jit_functions bigint @@ -527,6 +536,24 @@ + + + parallel_workers_to_launch bigint + + + Number of parallel workers planned to be launched + + + + + + parallel_workers_launched bigint + + + Number of parallel workers actually launched + + + stats_since timestamp with time zone @@ -603,9 +630,25 @@ In some cases, queries with visibly different texts might get merged into a - single pg_stat_statements entry. Normally this will happen - only for semantically equivalent queries, but there is a small chance of - hash collisions causing unrelated queries to be merged into one entry. + single pg_stat_statements entry; as explained above, + this is expected to happen for semantically equivalent queries. + In addition, if the only difference between queries is the number of elements + in a list of constants, the list will get squashed down to a single element but shown + with a commented-out list indicator: + + +=# SELECT pg_stat_statements_reset(); +=# SELECT * FROM test WHERE a IN (1, 2, 3, 4, 5, 6, 7); +=# SELECT * FROM test WHERE a IN (1, 2, 3, 4, 5, 6, 7, 8); +=# SELECT query, calls FROM pg_stat_statements + WHERE query LIKE 'SELECT%'; +-[ RECORD 1 ]------------------------------ +query | SELECT * FROM test WHERE a IN ($1 /*, ... */) +calls | 2 + + + In addition to these cases, there is a small chance of hash collisions + causing unrelated queries to be merged into one entry. (This cannot happen for queries belonging to different users or databases, however.) @@ -630,8 +673,13 @@ things, the internal object identifiers appearing in this representation. This has some counterintuitive implications. For example, pg_stat_statements will consider two apparently-identical - queries to be distinct, if they reference a table that was dropped - and recreated between the executions of the two queries. + queries to be distinct, if they reference for example a function that was + dropped and recreated between the executions of the two queries. + Conversely, if a table is dropped and recreated between the + executions of queries, two apparently-identical queries may be + considered the same. However, if the alias for a table is different + for otherwise-similar queries, these queries will be considered + distinct. The hashing process is also sensitive to differences in machine architecture and other facets of the platform. Furthermore, it is not safe to assume that queryid diff --git a/doc/src/sgml/planstats.sgml b/doc/src/sgml/planstats.sgml index c7ec749d0a601..068b804a18d70 100644 --- a/doc/src/sgml/planstats.sgml +++ b/doc/src/sgml/planstats.sgml @@ -489,10 +489,10 @@ SELECT relpages, reltuples FROM pg_class WHERE relname = 't'; condition on the a column: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a = 1; QUERY PLAN -------------------------------------------------------------------&zwsp;------------ - Seq Scan on t (cost=0.00..170.00 rows=100 width=8) (actual rows=100 loops=1) + Seq Scan on t (cost=0.00..170.00 rows=100 width=8) (actual rows=100.00 loops=1) Filter: (a = 1) Rows Removed by Filter: 9900 @@ -506,10 +506,10 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1; condition on both columns, combining them with AND: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN -------------------------------------------------------------------&zwsp;---------- - Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=100 loops=1) + Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=100.00 loops=1) Filter: ((a = 1) AND (b = 1)) Rows Removed by Filter: 9900 @@ -530,10 +530,10 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; CREATE STATISTICS stts (dependencies) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN -------------------------------------------------------------------&zwsp;------------ - Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1) + Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100.00 loops=1) Filter: ((a = 1) AND (b = 1)) Rows Removed by Filter: 9900 @@ -551,23 +551,23 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; estimated number of rows returned by the HashAggregate node) is very accurate: -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT COUNT(*) FROM t GROUP BY a; QUERY PLAN -------------------------------------------------------------------&zwsp;---------------------- - HashAggregate (cost=195.00..196.00 rows=100 width=12) (actual rows=100 loops=1) + HashAggregate (cost=195.00..196.00 rows=100 width=12) (actual rows=100.00 loops=1) Group Key: a - -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=4) (actual rows=10000 loops=1) + -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=4) (actual rows=10000.00 loops=1) But without multivariate statistics, the estimate for the number of groups in a query with two columns in GROUP BY, as in the following example, is off by an order of magnitude: -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT COUNT(*) FROM t GROUP BY a, b; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------- - HashAggregate (cost=220.00..230.00 rows=1000 width=16) (actual rows=100 loops=1) + HashAggregate (cost=220.00..230.00 rows=1000 width=16) (actual rows=100.00 loops=1) Group Key: a, b - -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000 loops=1) + -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000.00 loops=1) By redefining the statistics object to include n-distinct counts for the two columns, the estimate is much improved: @@ -575,12 +575,12 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; DROP STATISTICS stts; CREATE STATISTICS stts (dependencies, ndistinct) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT COUNT(*) FROM t GROUP BY a, b; QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------- - HashAggregate (cost=220.00..221.00 rows=100 width=16) (actual rows=100 loops=1) + HashAggregate (cost=220.00..221.00 rows=100 width=16) (actual rows=100.00 loops=1) Group Key: a, b - -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000 loops=1) + -> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000.00 loops=1) @@ -615,10 +615,10 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; DROP STATISTICS stts; CREATE STATISTICS stts2 (mcv) ON a, b FROM t; ANALYZE t; -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN -------------------------------------------------------------------&zwsp;------------ - Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1) + Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100.00 loops=1) Filter: ((a = 1) AND (b = 1)) Rows Removed by Filter: 9900 @@ -672,10 +672,10 @@ SELECT m.* FROM pg_statistic_ext join pg_statistic_ext_data on (oid = stxoid), to decide which combinations are compatible. -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a = 1 AND b = 10; QUERY PLAN -------------------------------------------------------------------&zwsp;-------- - Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1) + Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0.00 loops=1) Filter: ((a = 1) AND (b = 10)) Rows Removed by Filter: 10000 @@ -685,10 +685,10 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10; consider the following range query for the same table: -EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; +EXPLAIN (ANALYZE, TIMING OFF, BUFFERS OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; QUERY PLAN -------------------------------------------------------------------&zwsp;-------- - Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1) + Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0.00 loops=1) Filter: ((a <= 49) AND (b > 49)) Rows Removed by Filter: 10000 @@ -729,6 +729,9 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; accurately, the function that the operator is based on). If not, then the selectivity estimator will behave as if no statistics are available, and the planner will proceed with default or fall-back assumptions. + The program's + \do+ + meta-command is useful to determine which operators are marked as leakproof. @@ -737,7 +740,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49; error, in which case this mechanism is invisible in practice. But if the user is reading from a security-barrier view, then the planner might wish to check the statistics of an underlying table that is otherwise - inaccessible to the user. In that case, the operator should be leak-proof + inaccessible to the user. In that case, the operator should be leakproof or the statistics will not be used. There is no direct feedback about that, except that the plan might be suboptimal. If one suspects that this is the case, one could try running the query as a more privileged user, diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 25b1077ad7382..8007261d0224c 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1093,6 +1093,19 @@ $$ LANGUAGE plperl; be permitted to use this language. + + + Trusted PL/Perl relies on the Perl Opcode module to + preserve security. + Perl + documents + that the module is not effective for the trusted PL/Perl use case. If + your security needs are incompatible with the uncertainty in that warning, + consider executing REVOKE USAGE ON LANGUAGE plperl FROM + PUBLIC. + + + Here is an example of a function that will not work because file system operations are not allowed for security reasons: diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index a675923867205..e937491e6b89e 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1295,7 +1295,7 @@ $$ LANGUAGE plpgsql; On failure, this function might produce an error message such as ERROR: query returned no rows -DETAIL: parameters: $1 = 'nosuchuser' +DETAIL: parameters: username = 'nosuchuser' CONTEXT: PL/pgSQL function get_userid(text) line 6 at SQL statement @@ -3317,7 +3317,7 @@ OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING Opening a Bound Cursor -OPEN bound_cursorvar ( argument_name := argument_value , ... ) ; +OPEN bound_cursorvar ( argument_name { := | => } argument_value , ... ) ; @@ -3340,7 +3340,8 @@ OPEN bound_cursorvar ( positional or named notation. In positional notation, all arguments are specified in order. In named notation, - each argument's name is specified using := to + each argument's name is specified using := + or => to separate it from the argument expression. Similar to calling functions, described in , it is also allowed to mix positional and named notation. @@ -3352,6 +3353,7 @@ OPEN bound_cursorvar ( @@ -3672,7 +3674,7 @@ COMMIT; <<label>> -FOR recordvar IN bound_cursorvar ( argument_name := argument_value , ... ) LOOP +FOR recordvar IN bound_cursorvar ( argument_name { := | => } argument_value , ... ) LOOP statements END LOOP label ; diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index e5d51d6e9f5a4..bee817ea822a2 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -553,7 +553,7 @@ $$ LANGUAGE plpython3u; Iterator (any object providing __iter__ and - next methods) + __next__ methods) @@ -569,7 +569,7 @@ AS $$ def __iter__ (self): return self - def next (self): + def __next__(self): self.ndx += 1 if self.ndx == len(self.who): raise StopIteration diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml index 90969f63ca7c9..781a01067f7d6 100644 --- a/doc/src/sgml/postgres-fdw.sgml +++ b/doc/src/sgml/postgres-fdw.sgml @@ -194,7 +194,9 @@ OPTIONS (ADD password_required 'false'); user can potentially use any client certificates, .pgpass, .pg_service.conf etc. in the unix home directory of the - system user the postgres server runs as. They can also use any trust + system user the postgres server runs as. (For details on how home + directories are found, see .) They can + also use any trust relationship granted by authentication modes like peer or ident authentication. @@ -754,7 +756,7 @@ OPTIONS (ADD password_required 'false'); - + keep_connections (boolean) @@ -768,6 +770,73 @@ OPTIONS (ADD password_required 'false'); + + use_scram_passthrough (boolean) + + + This option controls whether postgres_fdw will + use the SCRAM pass-through authentication to connect to the foreign + server. With SCRAM pass-through authentication, + postgres_fdw uses SCRAM-hashed secrets instead of + plain-text user passwords to connect to the remote server. This + avoids storing plain-text user passwords in PostgreSQL system + catalogs. + + + + To use SCRAM pass-through authentication: + + + + The remote server must request the scram-sha-256 + authentication method; otherwise, the connection will fail. + + + + + + The remote server can be of any PostgreSQL version that supports + SCRAM. Support for use_scram_passthrough is + only required on the client side (FDW side). + + + + + + The user mapping password is not used. + + + + + + The server running postgres_fdw and the remote + server must have identical SCRAM secrets (encrypted passwords) for + the user being used on postgres_fdw to + authenticate on the foreign server (same salt and iterations, not + merely the same password). + + + + As a corollary, if FDW connections to multiple hosts are to be + made, for example for partitioned foreign tables/sharding, then all + hosts must have identical SCRAM secrets for the users involved. + + + + + + The current session on the PostgreSQL instance that makes the + outgoing FDW connections also must also use SCRAM authentication + for its incoming client connection. (Hence + pass-through: SCRAM must be used going in and out.) + This is a technical requirement of the SCRAM protocol. + + + + + + + @@ -779,7 +848,8 @@ OPTIONS (ADD password_required 'false'); postgres_fdw_get_connections( IN check_conn boolean DEFAULT false, OUT server_name text, - OUT valid boolean, OUT used_in_xact boolean, OUT closed boolean) + OUT user_name text, OUT valid boolean, OUT used_in_xact boolean, + OUT closed boolean, OUT remote_backend_pid int4) returns setof record @@ -806,10 +876,12 @@ OPTIONS (ADD password_required 'false'); Example usage of the function: - server_name | valid | used_in_xact | closed --------------+-------+--------------+-------- - loopback1 | t | t | - loopback2 | f | t | +postgres=# SELECT * FROM postgres_fdw_get_connections(true); + server_name | user_name | valid | used_in_xact | closed | remote_backend_pid +-------------+-----------+-------+--------------+----------------------------- + loopback1 | postgres | t | t | f | 1353340 + loopback2 | public | t | t | f | 1353120 + loopback3 | | f | t | f | 1353156 The output columns are described in . @@ -836,6 +908,16 @@ OPTIONS (ADD password_required 'false'); invalid), this will be NULL. + + user_name + text + + Name of the local user mapped to the foreign server of this + connection, or public if a public mapping is used. + If the user mapping is dropped but the connection remains open + (i.e., marked as invalid), this will be NULL. + + valid boolean @@ -864,6 +946,17 @@ OPTIONS (ADD password_required 'false'); is not available on this platform. + + remote_backend_pid + int4 + + Process ID of the remote backend, on the foreign server, + handling the connection. If the remote backend is terminated and + the connection is closed (with closed set to + true), this still shows the process ID of + the terminated backend. + +
@@ -1096,7 +1189,10 @@ postgres=# SELECT postgres_fdw_disconnect_all(); postgres_fdw can be used with remote servers dating back to PostgreSQL 8.3. Read-only capability is available - back to 8.1. A limitation however is that postgres_fdw + back to 8.1. + + + A limitation however is that postgres_fdw generally assumes that immutable built-in functions and operators are safe to send to the remote server for execution, if they appear in a WHERE clause for a foreign table. Thus, a built-in @@ -1108,6 +1204,13 @@ postgres=# SELECT postgres_fdw_disconnect_all(); optimization fence, and placing the problematic function or operator outside the sub-SELECT. + + Another limitation is that when executing INSERT + statements with an ON CONFLICT DO NOTHING clause on + a foreign table, the remote server must be running + PostgreSQL 9.5 or later, + as earlier versions do not support this feature. + diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index ec9f90e283e5f..af476c82fcc1e 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -9,6 +9,7 @@ %filelist; + If the client has not issued an explicit BEGIN, - then each Sync ordinarily causes an implicit COMMIT - if the preceding step(s) succeeded, or an - implicit ROLLBACK if they failed. However, there - are a few DDL commands (such as CREATE DATABASE) - that cannot be executed inside a transaction block. If one of - these is executed in a pipeline, it will fail unless it is the first - command in the pipeline. Furthermore, upon success it will force an - immediate commit to preserve database consistency. Thus a Sync - immediately following one of these commands has no effect except to - respond with ReadyForQuery. + then an implicit transaction block is started and each Sync ordinarily + causes an implicit COMMIT if the preceding step(s) + succeeded, or an implicit ROLLBACK if they failed. + This implicit transaction block will only be detected by the server + when the first command ends without a sync. There are a few DDL + commands (such as CREATE DATABASE) that cannot be + executed inside a transaction block. If one of these is executed in a + pipeline, it will fail unless it is the first command after a Sync. + Furthermore, upon success it will force an immediate commit to preserve + database consistency. Thus a Sync immediately following one of these + commands has no effect except to respond with ReadyForQuery. @@ -1325,6 +1412,7 @@ SELCT 1/0; IntervalStyle is_superuser scram_iterations + search_path server_encoding server_version session_authorization @@ -1334,7 +1422,8 @@ SELCT 1/0; (default_transaction_read_only and in_hot_standby were not reported by releases before 14; scram_iterations was not reported by releases - before 16.) + before 16; search_path was not reported by releases + before 18.) Note that server_version, server_encoding and @@ -1506,10 +1595,10 @@ SELCT 1/0; The frontend should also be prepared to handle an ErrorMessage - response to SSLRequest from the server. This would only occur if - the server predates the addition of SSL support - to PostgreSQL. (Such servers are now very ancient, - and likely do not exist in the wild anymore.) + response to SSLRequest from the server. The frontend should not display + this error message to the user/application, since the server has not been + authenticated + (CVE-2024-10977). In this case the connection must be closed, but the frontend might choose to open a fresh connection and proceed without requesting SSL. @@ -1619,12 +1708,13 @@ SELCT 1/0; The frontend should also be prepared to handle an ErrorMessage - response to GSSENCRequest from the server. This would only occur if - the server predates the addition of GSSAPI encryption - support to PostgreSQL. In this case the - connection must be closed, but the frontend might choose to open a fresh - connection and proceed without requesting GSSAPI - encryption. + response to GSSENCRequest from the server. The frontend should not display + this error message to the user/application, since the server has not been + authenticated + (CVE-2024-10977). + In this case the connection must be closed, but the frontend might choose + to open a fresh connection and proceed without requesting + GSSAPI encryption. @@ -1676,11 +1766,11 @@ SELCT 1/0; SASL is a framework for authentication in connection-oriented - protocols. At the moment, PostgreSQL implements two SASL - authentication mechanisms, SCRAM-SHA-256 and SCRAM-SHA-256-PLUS. More - might be added in the future. The below steps illustrate how SASL - authentication is performed in general, while the next subsection gives - more details on SCRAM-SHA-256 and SCRAM-SHA-256-PLUS. + protocols. At the moment, PostgreSQL implements three + SASL authentication mechanisms: SCRAM-SHA-256, SCRAM-SHA-256-PLUS, and + OAUTHBEARER. More might be added in the future. The below steps illustrate how SASL + authentication is performed in general, while the next subsections give + more details on particular mechanisms. @@ -1715,7 +1805,7 @@ SELCT 1/0; Finally, when the authentication exchange is completed successfully, the - server sends an AuthenticationSASLFinal message, followed + server sends an optional AuthenticationSASLFinal message, followed immediately by an AuthenticationOk message. The AuthenticationSASLFinal contains additional server-to-client data, whose content is particular to the selected authentication mechanism. If the authentication mechanism doesn't @@ -1734,9 +1824,9 @@ SELCT 1/0; SCRAM-SHA-256 Authentication - The implemented SASL mechanisms at the moment - are SCRAM-SHA-256 and its variant with channel - binding SCRAM-SHA-256-PLUS. They are described in + SCRAM-SHA-256, and its variant with channel + binding SCRAM-SHA-256-PLUS, are password-based + authentication mechanisms. They are described in detail in RFC 7677 and RFC 5802. @@ -1838,6 +1928,121 @@ SELCT 1/0; + + + OAUTHBEARER Authentication + + + OAUTHBEARER is a token-based mechanism for federated + authentication. It is described in detail in + RFC 7628. + + + + A typical exchange differs depending on whether or not the client already + has a bearer token cached for the current user. If it does not, the exchange + will take place over two connections: the first "discovery" connection to + obtain OAuth metadata from the server, and the second connection to send + the token after the client has obtained it. (libpq does not currently + implement a caching method as part of its builtin flow, so it uses the + two-connection exchange.) + + + + This mechanism is client-initiated, like SCRAM. The client initial response + consists of the standard "GS2" header used by SCRAM, followed by a list of + key=value pairs. The only key currently supported by + the server is auth, which contains the bearer token. + OAUTHBEARER additionally specifies three optional + components of the client initial response (the authzid of + the GS2 header, and the host and + port keys) which are currently ignored by the + server. + + + + OAUTHBEARER does not support channel binding, and there + is no "OAUTHBEARER-PLUS" mechanism. This mechanism does not make use of + server data during a successful authentication, so the + AuthenticationSASLFinal message is not used in the exchange. + + + + Example + + + During the first exchange, the server sends an AuthenticationSASL message + with the OAUTHBEARER mechanism advertised. + + + + + + The client responds by sending a SASLInitialResponse message which + indicates the OAUTHBEARER mechanism. Assuming the + client does not already have a valid bearer token for the current user, + the auth field is empty, indicating a discovery + connection. + + + + + + Server sends an AuthenticationSASLContinue message containing an error + status alongside a well-known URI and scopes that the + client should use to conduct an OAuth flow. + + + + + + Client sends a SASLResponse message containing the empty set (a single + 0x01 byte) to finish its half of the discovery + exchange. + + + + + + Server sends an ErrorMessage to fail the first exchange. + + + At this point, the client conducts one of many possible OAuth flows to + obtain a bearer token, using any metadata that it has been configured with + in addition to that provided by the server. (This description is left + deliberately vague; OAUTHBEARER does not specify or + mandate any particular method for obtaining a token.) + + + Once it has a token, the client reconnects to the server for the final + exchange: + + + + + + The server once again sends an AuthenticationSASL message with the + OAUTHBEARER mechanism advertised. + + + + + + The client responds by sending a SASLInitialResponse message, but this + time the auth field in the message contains the + bearer token that was obtained during the client flow. + + + + + + The server validates the token according to the instructions of the + token provider. If the client is authorized to connect, it sends an + AuthenticationOk message to end the SASL exchange. + + + + @@ -2675,8 +2880,6 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" Drops a replication slot, freeing any reserved server-side resources. - If the slot is a logical slot that was created in a database other than - the database the walsender is connected to, this command fails. @@ -3263,7 +3466,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Comma separated list of publication names for which to subscribe + Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required. @@ -3328,8 +3531,9 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Option to send changes by their origin. Possible values are "none" - to only send the changes that have no origin associated, or "any" + Option to send changes by their origin. Possible values are + none to only send the changes that have no origin + associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes. @@ -3498,10 +3702,10 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" indicate that it can be sent by a frontend (F), a backend (B), or both (F & B). Notice that although each message includes a byte count at the beginning, - the message format is defined so that the message end can be found without - reference to the byte count. This aids validity checking. (The CopyData - message is an exception, because it forms part of a data stream; the contents - of any individual CopyData message cannot be interpretable on their own.) + most messages are defined so that the message end can be found without + reference to the byte count. This is for historical reasons, as the + original, now-obsolete protocol version 2 did not have an explicit length + field. It also aids validity checking though. @@ -3917,7 +4121,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Int32(12) + Int32 Length of message contents in bytes, including self. @@ -3935,14 +4139,29 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Int32 + Byten - The secret key of this backend. + The secret key of this backend. This field extends to the end of the + message, indicated by the length field. + + + The maximum key length is 256 bytes. The + PostgreSQL server only sends keys up to + 32 bytes, but the larger maximum size allows for future server + versions, as well as connection poolers and other middleware, to use + longer keys. One possible use case is augmenting the server's key + with extra information. Middleware is therefore also encouraged to + not use up all of the bytes, in case multiple middleware + applications are layered on top of each other, each of which may + wrap the key with extra data. + + Before protocol version 3.2, the secret key was always 4 bytes long. + @@ -4148,14 +4367,18 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Int32 + Byten - The secret key for the target backend. + The secret key for the target backend. This field extends to the end of the + message, indicated by the length field. The maximum key length is 256 bytes. + + Before protocol version 3.2, the secret key was always 4 bytes long. + @@ -6541,7 +6764,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" Next, the following message part appears for each column included in - the publication (except generated columns): + the publication: @@ -7474,7 +7697,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" - Next, one of the following submessages appears for each column (except generated columns): + Next, one of the following submessages appears for each published column: @@ -7604,8 +7827,9 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" is a well-defined way to recover from errors during COPY. The special \. last line is not needed anymore, and is not sent during COPY OUT. - (It is still recognized as a terminator during COPY IN, but its use is - deprecated and will eventually be removed.) Binary COPY is supported. + (It is still recognized as a terminator during text-mode COPY + IN, but not in CSV mode. The text-mode behavior is + deprecated and may eventually be removed.) Binary COPY is supported. The CopyInResponse and CopyOutResponse messages include fields indicating the number of columns and the format of each column. diff --git a/doc/src/sgml/queries.sgml b/doc/src/sgml/queries.sgml index 372cce1a487e3..a326960ff4dfb 100644 --- a/doc/src/sgml/queries.sgml +++ b/doc/src/sgml/queries.sgml @@ -1461,10 +1461,10 @@ GROUP BY GROUPING SETS ( When multiple window functions are used, all the window functions having - syntactically equivalent PARTITION BY and ORDER BY - clauses in their window definitions are guaranteed to be evaluated in a - single pass over the data. Therefore they will see the same sort ordering, - even if the ORDER BY does not uniquely determine an ordering. + equivalent PARTITION BY and ORDER BY + clauses in their window definitions are guaranteed to see the same + ordering of the input rows, even if the ORDER BY does + not uniquely determine the ordering. However, no guarantees are made about the evaluation of functions having different PARTITION BY or ORDER BY specifications. (In such cases a sort step is typically required between the passes of diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml index 59962d6e85633..727a0cb185fb2 100644 --- a/doc/src/sgml/query.sgml +++ b/doc/src/sgml/query.sgml @@ -671,7 +671,7 @@ SELECT max(temp_lo) FROM weather; we might try: -SELECT city FROM weather WHERE temp_lo = max(temp_lo); WRONG +SELECT city FROM weather WHERE temp_lo = max(temp_lo); -- WRONG but this will not work since the aggregate diff --git a/doc/src/sgml/ref/alter_database.sgml b/doc/src/sgml/ref/alter_database.sgml index 2479c41e8d635..9da8920e12eff 100644 --- a/doc/src/sgml/ref/alter_database.sgml +++ b/doc/src/sgml/ref/alter_database.sgml @@ -82,7 +82,8 @@ ALTER DATABASE name RESET ALL default tablespace to the new tablespace. The new default tablespace must be empty for this database, and no one can be connected to the database. Tables and indexes in non-default tablespaces are - unaffected. + unaffected. The method used to copy files to the new tablespace + is affected by the setting. diff --git a/doc/src/sgml/ref/alter_default_privileges.sgml b/doc/src/sgml/ref/alter_default_privileges.sgml index 89aacec4fab84..6acd0f1df914c 100644 --- a/doc/src/sgml/ref/alter_default_privileges.sgml +++ b/doc/src/sgml/ref/alter_default_privileges.sgml @@ -51,6 +51,11 @@ GRANT { { USAGE | CREATE } ON SCHEMAS TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] +GRANT { { SELECT | UPDATE } + [, ...] | ALL [ PRIVILEGES ] } + ON LARGE OBJECTS + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN } [, ...] | ALL [ PRIVILEGES ] } @@ -83,6 +88,13 @@ REVOKE [ GRANT OPTION FOR ] ON SCHEMAS FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] + +REVOKE [ GRANT OPTION FOR ] + { { SELECT | UPDATE } + [, ...] | ALL [ PRIVILEGES ] } + ON LARGE OBJECTS + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] @@ -117,8 +129,8 @@ REVOKE [ GRANT OPTION FOR ] Currently, only the privileges for schemas, tables (including views and foreign - tables), sequences, functions, and types (including domains) can be - altered. For this command, functions include aggregates and procedures. + tables), sequences, functions, types (including domains), and large objects + can be altered. For this command, functions include aggregates and procedures. The words FUNCTIONS and ROUTINES are equivalent in this command. (ROUTINES is preferred going forward as the standard term for functions and procedures taken @@ -161,7 +173,8 @@ REVOKE [ GRANT OPTION FOR ] If IN SCHEMA is omitted, the global default privileges are altered. IN SCHEMA is not allowed when setting privileges - for schemas, since schemas can't be nested. + for schemas and large objects, since schemas can't be nested and + large objects don't belong to a schema.
diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml index f6704d7557a81..74855172222ec 100644 --- a/doc/src/sgml/ref/alter_domain.sgml +++ b/doc/src/sgml/ref/alter_domain.sgml @@ -41,6 +41,11 @@ ALTER DOMAIN name RENAME TO new_name ALTER DOMAIN name SET SCHEMA new_schema + +where domain_constraint is: + +[ CONSTRAINT constraint_name ] +{ NOT NULL | CHECK (expression) } @@ -79,8 +84,7 @@ ALTER DOMAIN name ADD domain_constraint [ NOT VALID ] - This form adds a new constraint to a domain using the same syntax as - CREATE DOMAIN. + This form adds a new constraint to a domain. When a new constraint is added to a domain, all columns using that domain will be checked against the newly added constraint. These checks can be suppressed by adding the new constraint using the diff --git a/doc/src/sgml/ref/alter_foreign_table.sgml b/doc/src/sgml/ref/alter_foreign_table.sgml index 3cb6f08fcf2a9..e2da3cc719f90 100644 --- a/doc/src/sgml/ref/alter_foreign_table.sgml +++ b/doc/src/sgml/ref/alter_foreign_table.sgml @@ -173,7 +173,8 @@ ALTER FOREIGN TABLE [ IF EXISTS ] name This form adds a new constraint to a foreign table, using the same syntax as CREATE FOREIGN TABLE. - Currently only CHECK constraints are supported. + Currently only CHECK and NOT NULL + constraints are supported. @@ -182,7 +183,8 @@ ALTER FOREIGN TABLE [ IF EXISTS ] nameCREATE FOREIGN TABLE.) - If the constraint is marked NOT VALID, then it isn't + If the constraint is marked NOT VALID (allowed only for + the CHECK case), then it isn't assumed to hold, but is only recorded for possible future use. diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index e26efec064bee..1d42d05d85816 100644 --- a/doc/src/sgml/ref/alter_index.sgml +++ b/doc/src/sgml/ref/alter_index.sgml @@ -87,10 +87,11 @@ ALTER INDEX ALL IN TABLESPACE name - ATTACH PARTITION + ATTACH PARTITION index_name - Causes the named index to become attached to the altered index. + Causes the named index (possibly schema-qualified) to become attached + to the altered index. The named index must be on a partition of the table containing the index being altered, and have an equivalent definition. An attached index cannot be dropped by itself, and will automatically be dropped diff --git a/doc/src/sgml/ref/alter_opfamily.sgml b/doc/src/sgml/ref/alter_opfamily.sgml index b2e5b9b72ec8b..5c4c2e579f570 100644 --- a/doc/src/sgml/ref/alter_opfamily.sgml +++ b/doc/src/sgml/ref/alter_opfamily.sgml @@ -273,14 +273,6 @@ ALTER OPERATOR FAMILY name USING name RENAME TO . See there for more information. + + + Altering the publish_via_partition_root parameter can + lead to data loss or duplication at the subscriber because it changes + the identity and schema of the published tables. Note this happens only + when a partition root table is specified as the replication target. + + + This problem can be avoided by refraining from modifying partition leaf + tables after the ALTER PUBLICATION ... SET until the + ALTER SUBSCRIPTION ... REFRESH PUBLICATION + is executed and by only refreshing using the copy_data = off + option. + + diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml index 7be36cf466d2c..a998ccc7ead2f 100644 --- a/doc/src/sgml/ref/alter_sequence.sgml +++ b/doc/src/sgml/ref/alter_sequence.sgml @@ -27,9 +27,10 @@ ALTER SEQUENCE [ IF EXISTS ] name [ AS data_type ] [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] + [ [ NO ] CYCLE ] [ START [ WITH ] start ] [ RESTART [ [ WITH ] restart ] ] - [ CACHE cache ] [ [ NO ] CYCLE ] + [ CACHE cache ] [ OWNED BY { table_name.column_name | NONE } ] ALTER SEQUENCE [ IF EXISTS ] name SET { LOGGED | UNLOGGED } ALTER SEQUENCE [ IF EXISTS ] name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } @@ -154,6 +155,38 @@ ALTER SEQUENCE [ IF EXISTS ] name S + + CYCLE + + + The optional CYCLE key word can be used to enable + the sequence to wrap around when the + maxvalue or + minvalue has been + reached by + an ascending or descending sequence respectively. If the limit is + reached, the next number generated will be the + minvalue or + maxvalue, + respectively. + + + + + + NO CYCLE + + + If the optional NO CYCLE key word is + specified, any calls to nextval after the + sequence has reached its maximum value will return an error. + If neither CYCLE or NO + CYCLE are specified, the old cycle behavior will be + maintained. + + + + start @@ -207,38 +240,6 @@ ALTER SEQUENCE [ IF EXISTS ] name S - - CYCLE - - - The optional CYCLE key word can be used to enable - the sequence to wrap around when the - maxvalue or - minvalue has been - reached by - an ascending or descending sequence respectively. If the limit is - reached, the next number generated will be the - minvalue or - maxvalue, - respectively. - - - - - - NO CYCLE - - - If the optional NO CYCLE key word is - specified, any calls to nextval after the - sequence has reached its maximum value will return an error. - If neither CYCLE or NO - CYCLE are specified, the old cycle behavior will be - maintained. - - - - SET { LOGGED | UNLOGGED } diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 6a2822adad739..d63f3a621acc6 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -37,13 +37,6 @@ ALTER TABLE [ IF EXISTS ] name ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } ALTER TABLE [ IF EXISTS ] name DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ] -ALTER TABLE [ IF EXISTS ] name - SPLIT PARTITION partition_name INTO - (PARTITION partition_name1 { FOR VALUES partition_bound_spec | DEFAULT }, - PARTITION partition_name2 { FOR VALUES partition_bound_spec | DEFAULT } [, ...]) -ALTER TABLE [ IF EXISTS ] name - MERGE PARTITIONS (partition_name1, partition_name2 [, ...]) - INTO partition_name where action is one of: @@ -65,7 +58,8 @@ ALTER TABLE [ IF EXISTS ] name ALTER [ COLUMN ] column_name SET COMPRESSION compression_method ADD table_constraint [ NOT VALID ] ADD table_constraint_using_index - ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] + ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] + ALTER CONSTRAINT constraint_name [ INHERIT | NO INHERIT ] VALIDATE CONSTRAINT constraint_name DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] DISABLE TRIGGER [ trigger_name | ALL | USER ] @@ -105,28 +99,29 @@ WITH ( MODULUS numeric_literal, REM and column_constraint is: [ CONSTRAINT constraint_name ] -{ NOT NULL | +{ NOT NULL [ NO INHERIT ] | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | - GENERATED ALWAYS AS ( generation_expr ) STORED | + GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } -[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] +[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | - UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters | - PRIMARY KEY ( column_name [, ... ] ) index_parameters | + NOT NULL column_name [ NO INHERIT ] | + UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters | + PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | - FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] + FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } -[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] +[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] and table_constraint_using_index is: @@ -248,6 +243,8 @@ WITH ( MODULUS numeric_literal, REM entire table; however, if a valid CHECK constraint is found which proves no NULL can exist, then the table scan is skipped. + If a column has an invalid not-null constraint, + SET NOT NULL validates it. @@ -258,7 +255,9 @@ WITH ( MODULUS numeric_literal, REM table. Even if there is no NOT NULL constraint on the parent, such a constraint can still be added to individual partitions, if desired; that is, the children can disallow nulls even if the parent - allows them, but not the other way around. + allows them, but not the other way around. It is also possible to drop + the NOT NULL constraint from ONLY + the parent table, which does not remove it from the children. @@ -268,8 +267,8 @@ WITH ( MODULUS numeric_literal, REM This form replaces the expression of a generated column. Existing data - in the column is rewritten and all the future changes will apply the new - generation expression. + in a stored generated column is rewritten and all the future changes + will apply the new generation expression. @@ -283,10 +282,15 @@ WITH ( MODULUS numeric_literal, REM longer apply the generation expression. + + This form is currently only supported for stored generated columns (not + virtual ones). + + If DROP EXPRESSION IF EXISTS is specified and the - column is not a stored generated column, no error is thrown. In this - case a notice is issued instead. + column is not a generated column, no error is thrown. In this case a + notice is issued instead. @@ -456,8 +460,8 @@ WITH ( MODULUS numeric_literal, REM This form adds a new constraint to a table using the same constraint syntax as CREATE TABLE, plus the option NOT - VALID, which is currently only allowed for foreign key - and CHECK constraints. + VALID, which is currently only allowed for foreign key, + CHECK constraints and not-null constraints. @@ -490,8 +494,6 @@ WITH ( MODULUS numeric_literal, REM Additional restrictions apply when unique or primary key constraints are added to partitioned tables; see CREATE TABLE. - Also, foreign key constraints on partitioned - tables may not be declared NOT VALID at present. @@ -557,19 +559,40 @@ WITH ( MODULUS numeric_literal, REM This form alters the attributes of a constraint that was previously - created. Currently only foreign key constraints may be altered. + created. Currently only foreign key constraints may be altered in + this fashion, but see below. + + ALTER CONSTRAINT ... INHERIT + ALTER CONSTRAINT ... NO INHERIT + + + These forms modify a inheritable constraint so that it becomes not + inheritable, or vice-versa. Only not-null constraints may be altered + in this fashion at present. + In addition to changing the inheritability status of the constraint, + in the case where a non-inheritable constraint is being marked + inheritable, if the table has children, an equivalent constraint + will be added to them. If marking an inheritable constraint as + non-inheritable on a table with children, then the corresponding + constraint on children will be marked as no longer inherited, + but not removed. + + + + VALIDATE CONSTRAINT - This form validates a foreign key or check constraint that was + This form validates a foreign key, check, or not-null constraint that was previously created as NOT VALID, by scanning the table to ensure there are no rows for which the constraint is not - satisfied. Nothing happens if the constraint is already marked valid. + satisfied. If the constraint is not enforced, an error is thrown. + Nothing happens if the constraint is already marked valid. (See below for an explanation of the usefulness of this command.) @@ -802,6 +825,10 @@ WITH ( MODULUS numeric_literal, REM (for identity or serial columns). However, it is also possible to change the persistence of such sequences separately. + + + This form is not supported for partitioned tables. + @@ -850,19 +877,16 @@ WITH ( MODULUS numeric_literal, REM table. Subsequently, queries against the parent will include records of the target table. To be added as a child, the target table must already contain all the same columns as the parent (it could have - additional columns, too). The columns must have matching data types, - and if they have NOT NULL constraints in the parent - then they must also have NOT NULL constraints in the - child. + additional columns, too). The columns must have matching data types. - There must also be matching child-table constraints for all - CHECK constraints of the parent, except those - marked non-inheritable (that is, created with ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT) - in the parent, which are ignored; all child-table constraints matched - must not be marked non-inheritable. - Currently + In addition, all CHECK and NOT NULL + constraints on the parent must also exist on the child, except those + marked non-inheritable (that is, created with + ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT), which + are ignored. All child-table constraints matched must not be marked + non-inheritable. Currently UNIQUE, PRIMARY KEY, and FOREIGN KEY constraints are not considered, but this might change in the future. @@ -930,8 +954,9 @@ WITH ( MODULUS numeric_literal, REM DEFAULT - Records the old values of the columns of the primary key, if any. + Records the old values of the columns of the primary key. This is the default for non-system tables. + When there is no primary key, the behavior is the same as NOTHING. @@ -1017,20 +1042,18 @@ WITH ( MODULUS numeric_literal, REM A partition using FOR VALUES uses same syntax for partition_bound_spec as - CREATE TABLE. The partition bound specification + CREATE TABLE. + The partition bound specification must correspond to the partitioning strategy and partition key of the target table. The table to be attached must have all the same columns as the target table and no more; moreover, the column types must also match. Also, it must have all the NOT NULL and - CHECK constraints of the target table. Currently + CHECK constraints of the target table, not marked + NO INHERIT. Currently FOREIGN KEY constraints are not considered. UNIQUE and PRIMARY KEY constraints from the parent table will be created in the partition, if they don't already exist. - If any of the CHECK constraints of the table being - attached are marked NO INHERIT, the command will fail; - such constraints must be recreated without the - NO INHERIT clause. @@ -1124,140 +1147,14 @@ WITH ( MODULUS numeric_literal, REM - - SPLIT PARTITION partition_name INTO (PARTITION partition_name1 { FOR VALUES partition_bound_spec | DEFAULT }, PARTITION partition_name2 { FOR VALUES partition_bound_spec | DEFAULT } [, ...]) - - - - This form splits a single partition of the target table. Hash-partitioning - is not supported. Bounds of new partitions should not overlap with new and - existing partitions (except partition_name). - If the split partition is a DEFAULT partition, one of the new partitions must be DEFAULT. - In case one of the new partitions or one of existing partitions is DEFAULT, - new partitions partition_name1, - partition_name2, ... can have spaces - between partitions bounds. If the partitioned table does not have a DEFAULT - partition, the DEFAULT partition can be defined as one of the new partitions. - - - In case new partitions do not contain a DEFAULT partition and the partitioned table - does not have a DEFAULT partition, the following must be true: sum bounds of - new partitions partition_name1, - partition_name2, ... should be - equal to bound of split partition partition_name. - One of the new partitions partition_name1, - partition_name2, ... can have - the same name as split partition partition_name - (this is suitable in case of splitting a DEFAULT partition: we split it, but after - splitting we have a partition with the same name). - Only simple, non-partitioned partition can be split. - - - The new partitions will be created the same as tables created with the - SQL command CREATE TABLE partition_nameN (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS). - The indexes and identity are created later, after moving the data - into the new partitions. - Extended statistics aren't copied from the parent table, for consistency with - CREATE TABLE PARTITION OF. - - New partitions will have the same table access method as the parent. - If the parent table is persistent then new partitions are created - persistent. If the parent table is temporary then new partitions - are also created temporary. New partitions will also be created in - the same tablespace as the parent. - - - - This command acquires an ACCESS EXCLUSIVE lock. - This is a significant limitation, which limits the usage of this - command with large partitioned tables under a high load. - - - - - - - MERGE PARTITIONS (partition_name1, partition_name2 [, ...]) INTO partition_name - - - - This form merges several partitions into the one partition of the target table. - Hash-partitioning is not supported. If DEFAULT partition is not in the - list of partitions partition_name1, - partition_name2 [, ...]: - - - - For range-partitioned tables it is necessary that the ranges - of the partitions partition_name1, - partition_name2 [, ...] can - be merged into one range without spaces and overlaps (otherwise an error - will be generated). The combined range will be the range for the partition - partition_name. - - - - - For list-partitioned tables the value lists of all partitions - partition_name1, - partition_name2 [, ...] are - combined and form the list of values of partition - partition_name. - - - - If DEFAULT partition is in the list of partitions partition_name1, - partition_name2 [, ...]: - - - - The partition partition_name - will be the DEFAULT partition. - - - - - For range- and list-partitioned tables the ranges and lists of values - of the merged partitions can be any. - - - - The new partition partition_name - can have the same name as one of the merged partitions. Only simple, - non-partitioned partitions can be merged. - - - The new partition will be created the same as a table created with the - SQL command CREATE TABLE partition_name (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS). - The indexes and identity are created later, after moving the data - into the new partition. - Extended statistics aren't copied from the parent table, for consistency with - CREATE TABLE PARTITION OF. - The new partition will have the same table access method as the parent. - If the parent table is persistent then the new partition is created - persistent. If the parent table is temporary then the new partition - is also created temporary. The new partition will also be created in - the same tablespace as the parent. - - - - This command acquires an ACCESS EXCLUSIVE lock. - This is a significant limitation, which limits the usage of this - command with large partitioned tables under a high load. - - - - - - All the forms of ALTER TABLE that act on a single table, except - RENAME, SET SCHEMA, - ATTACH PARTITION, DETACH PARTITION, - SPLIT PARTITION, and MERGE PARTITIONS - can be combined into + All the forms of ALTER TABLE that act on a single table, + except RENAME, SET SCHEMA, + ATTACH PARTITION, and + DETACH PARTITION can be combined into a list of multiple alterations to be applied together. For example, it is possible to add several columns and/or alter the type of several columns in a single command. This is particularly useful with large @@ -1500,8 +1397,7 @@ WITH ( MODULUS numeric_literal, REM partition_name - The name of the table to attach as a new partition or to detach from this table, - or the name of split partition, or the name of the new merged partition. + The name of the table to attach as a new partition or to detach from this table. @@ -1528,36 +1424,53 @@ WITH ( MODULUS numeric_literal, REM When a column is added with ADD COLUMN and a - non-volatile DEFAULT is specified, the default is + non-volatile DEFAULT is specified, the default value is evaluated at the time of the statement and the result stored in the - table's metadata. That value will be used for the column for all existing - rows. If no DEFAULT is specified, NULL is used. In - neither case is a rewrite of the table required. + table's metadata, where it will be returned when any existing rows are + accessed. The value will be only applied when the table is rewritten, + making the ALTER TABLE very fast even on large tables. + If no column constraints are specified, NULL is used as the + DEFAULT. In neither case is a rewrite of the table + required. + + + + Adding a column with a volatile DEFAULT + (e.g., clock_timestamp()), a stored generated column, + an identity column, or a column with a domain data type that has + constraints will cause the entire table and its indexes to be rewritten. + Adding a virtual generated column never requires a rewrite. + + + + Changing the type of an existing column will normally cause the entire table + and its indexes to be rewritten. + As an exception, when changing the type of an existing column, + if the USING clause does not change the column + contents and the old type is either binary coercible to the new type + or an unconstrained domain over the new type, a table rewrite is not + needed. However, indexes will still be rebuilt unless the system + can verify that the new index would be logically equivalent to the + existing one. For example, if the collation for a column has been + changed, an index rebuild is required because the new sort + order might be different. However, in the absence of a collation + change, a column can be changed from text to + varchar (or vice versa) without rebuilding the indexes + because these data types sort identically. - Adding a column with a volatile DEFAULT or - changing the type of an existing column will require the entire table and - its indexes to be rewritten. As an exception, when changing the type of an - existing column, if the USING clause does not change - the column contents and the old type is either binary coercible to the new - type or an unconstrained domain over the new type, a table rewrite is not - needed. However, indexes must always be rebuilt unless the system can - verify that the new index would be logically equivalent to the existing - one. For example, if the collation for a column has been changed, an index - rebuild is always required because the new sort order might be different. - However, in the absence of a collation change, a column can be changed - from text to varchar (or vice versa) without - rebuilding the indexes because these data types sort identically. - Table and/or index rebuilds may take a - significant amount of time for a large table; and will temporarily require - as much as double the disk space. + Table and/or index + rebuilds may take a significant amount of time for a large table, + and will temporarily require as much as double the disk space. - Adding a CHECK or NOT NULL constraint requires - scanning the table to verify that existing rows meet the constraint, - but does not require a table rewrite. + Adding an enforced CHECK or NOT NULL + constraint requires scanning the table to verify that existing rows meet the + constraint, but does not require a table rewrite. If a CHECK + constraint is added as NOT ENFORCED, the validation will + not be performed. @@ -1917,42 +1830,23 @@ ALTER TABLE measurement DETACH PARTITION measurement_y2015m12; - - To split a single partition of the range-partitioned table: - -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2023 INTO - (PARTITION sales_feb2023 FOR VALUES FROM ('2023-02-01') TO ('2023-03-01'), - PARTITION sales_mar2023 FOR VALUES FROM ('2023-03-01') TO ('2023-04-01'), - PARTITION sales_apr2023 FOR VALUES FROM ('2023-04-01') TO ('2023-05-01')); - - - - To split a single partition of the list-partitioned table: - -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); - - - - To merge several partitions into one partition of the target table: - -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_central) - INTO sales_all; - - Compatibility - The forms ADD (without USING INDEX), + The forms ADD [COLUMN], DROP [COLUMN], DROP IDENTITY, RESTART, SET DEFAULT, SET DATA TYPE (without USING), SET GENERATED, and SET sequence_option - conform with the SQL standard. The other forms are + conform with the SQL standard. + The form ADD table_constraint + conforms with the SQL standard when the USING INDEX and + NOT VALID clauses are omitted and the constraint type is + one of CHECK, UNIQUE, PRIMARY KEY, + or REFERENCES. + The other forms are PostgreSQL extensions of the SQL standard. Also, the ability to specify more than one manipulation in a single ALTER TABLE command is an extension. diff --git a/doc/src/sgml/ref/alter_tablespace.sgml b/doc/src/sgml/ref/alter_tablespace.sgml index 6ec863400d17b..d0e08089ddb96 100644 --- a/doc/src/sgml/ref/alter_tablespace.sgml +++ b/doc/src/sgml/ref/alter_tablespace.sgml @@ -88,7 +88,7 @@ ALTER TABLESPACE name RESET ( , , diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index 2b94b378e9f31..ec81f00fecf87 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -31,7 +31,7 @@ ANALYZE [ ( option [, ...] ) ] [ and table_and_columns is: - table_name [ ( column_name [, ...] ) ] + [ ONLY ] table_name [ * ] [ ( column_name [, ...] ) ] @@ -65,7 +65,7 @@ ANALYZE [ ( option [, ...] ) ] [ VERBOSE - Enables display of progress messages. + Enables display of progress messages at INFO level. @@ -142,9 +142,12 @@ ANALYZE [ ( option [, ...] ) ] [ ONLY is specified before + the table name, only that table is analyzed. If ONLY + is not specified, the table and all its inheritance child tables or + partitions (if any) are analyzed. Optionally, * + can be specified after the table name to explicitly indicate that + inheritance child tables (or partitions) are to be analyzed. @@ -284,22 +287,23 @@ ANALYZE [ ( option [, ...] ) ] [ ANALYZE gathers two sets of statistics: one on the rows of the parent table only, and a second including rows of both the parent table and all of its children. This second set of statistics is needed when - planning queries that process the inheritance tree as a whole. The child - tables themselves are not individually analyzed in this case. - The autovacuum daemon, however, will only consider inserts or - updates on the parent table itself when deciding whether to trigger an - automatic analyze for that table. If that table is rarely inserted into - or updated, the inheritance statistics will not be up to date unless you - run ANALYZE manually. + planning queries that process the inheritance tree as a whole. The + autovacuum daemon, however, will only consider inserts or updates on the + parent table itself when deciding whether to trigger an automatic analyze + for that table. If that table is rarely inserted into or updated, the + inheritance statistics will not be up to date unless you run + ANALYZE manually. By default, + ANALYZE will also recursively collect and update the + statistics for each inheritance child table. The ONLY + keyword may be used to disable this. For partitioned tables, ANALYZE gathers statistics by - sampling rows from all partitions; in addition, it will recurse into each - partition and update its statistics. Each leaf partition is analyzed only - once, even with multi-level partitioning. No statistics are collected for - only the parent table (without data from its partitions), because with - partitioning it's guaranteed to be empty. + sampling rows from all partitions. By default, + ANALYZE will also recursively collect and update the + statistics for each partition. The ONLY keyword may be + used to disable this. diff --git a/doc/src/sgml/ref/cluster.sgml b/doc/src/sgml/ref/cluster.sgml index c5760244e67e2..8811f169ea0b1 100644 --- a/doc/src/sgml/ref/cluster.sgml +++ b/doc/src/sgml/ref/cluster.sgml @@ -106,7 +106,8 @@ CLUSTER [ ( option [, ...] ) ] [ VERBOSE - Prints a progress report as each table is clustered. + Prints a progress report as each table is clustered + at INFO level. diff --git a/doc/src/sgml/ref/clusterdb.sgml b/doc/src/sgml/ref/clusterdb.sgml index d3145318b361f..0d2051bf6f188 100644 --- a/doc/src/sgml/ref/clusterdb.sgml +++ b/doc/src/sgml/ref/clusterdb.sgml @@ -248,9 +248,8 @@ PostgreSQL documentation - Specifies the name of the database to connect to to discover which - databases should be clustered, - when / is used. + When the / is used, connect + to this database to gather the list of databases to cluster. If not specified, the postgres database will be used, or if that does not exist, template1 will be used. This can be a connection diff --git a/doc/src/sgml/ref/copy.sgml b/doc/src/sgml/ref/copy.sgml index 1518af8a0450c..8433344e5b6f5 100644 --- a/doc/src/sgml/ref/copy.sgml +++ b/doc/src/sgml/ref/copy.sgml @@ -44,6 +44,7 @@ COPY { table_name [ ( column_name [, ...] ) | * } FORCE_NULL { ( column_name [, ...] ) | * } ON_ERROR error_action + REJECT_LIMIT maxerror ENCODING 'encoding_name' LOG_VERBOSITY verbosity @@ -220,6 +221,7 @@ COPY { table_name [ ( csv (Comma Separated Values), or binary. The default is text. + See below for details. @@ -235,7 +237,7 @@ COPY { table_name [ ( COPY FREEZE on - a partitioned table. + a partitioned table or foreign table. This option is only allowed in COPY FROM. @@ -407,6 +409,26 @@ COPY { table_name [ ( verbose, a NOTICE message containing the line of the input file and the column name whose input conversion has failed is emitted for each discarded row. + When it is set to silent, no message is emitted + regarding ignored rows. + + + + + + REJECT_LIMIT + + + Specifies the maximum number of errors tolerated while converting a + column's input value to its data type, when ON_ERROR is + set to ignore. + If the input causes more errors than the specified value, the COPY + command fails, even with ON_ERROR set to ignore. + This clause must be used with ON_ERROR=ignore + and maxerror must be positive bigint. + If not specified, ON_ERROR=ignore + allows an unlimited number of errors, meaning COPY will + skip all erroneous data. @@ -427,10 +449,12 @@ COPY { table_name [ ( LOG_VERBOSITY - Specify the amount of messages emitted by a COPY - command: default or verbose. If - verbose is specified, additional messages are emitted - during processing. + Specifies the amount of messages emitted by a COPY + command: default, verbose, or + silent. + If verbose is specified, additional messages are + emitted during processing. + silent suppresses both verbose and default messages. This is currently used in COPY FROM command when @@ -496,16 +520,16 @@ COPY count Notes - COPY TO can be used only with plain - tables, not views, and does not copy rows from child tables - or child partitions. For example, COPY table TO copies - the same rows as SELECT * FROM ONLY table. - The syntax COPY (SELECT * FROM table) TO ... can be used to - dump all of the rows in an inheritance hierarchy, partitioned table, - or view. + COPY TO can be used with plain + tables and populated materialized views. + For example, + COPY table + TO copies the same rows as + SELECT * FROM ONLY table. + However it doesn't directly support other relation types, + such as partitioned tables, inheritance child tables, or views. + To copy all rows from such relations, use COPY (SELECT * FROM + table) TO. @@ -627,10 +651,10 @@ COPY count - + File Formats - + Text Format @@ -646,11 +670,16 @@ COPY count - End of data can be represented by a single line containing just + End of data can be represented by a line containing just backslash-period (\.). An end-of-data marker is not necessary when reading from a file, since the end of file - serves perfectly well; it is needed only when copying data to or from - client applications using pre-3.0 client protocol. + serves perfectly well; in that context this provision exists only for + backward compatibility. However, psql + uses \. to terminate a COPY FROM + STDIN operation (that is, reading + in-line COPY data in an SQL script). In that + context the rule is needed to be able to end the operation before the + end of the script. @@ -770,11 +799,11 @@ COPY count - + CSV Format - This format option is used for importing and exporting the Comma + This format option is used for importing and exporting the Comma- Separated Value (CSV) file format used by many other programs, such as spreadsheets. Instead of the escaping rules used by PostgreSQL's standard text format, it @@ -811,16 +840,25 @@ COPY count Because backslash is not a special character in the CSV - format, \., the end-of-data marker, could also appear - as a data value. To avoid any misinterpretation, a \. - data value appearing as a lone entry on a line is automatically - quoted on output, and on input, if quoted, is not interpreted as the - end-of-data marker. If you are loading a file created by another - application that has a single unquoted column and might have a - value of \., you might need to quote that value in the - input file. + format, the end-of-data marker used in text mode (\.) + is not normally treated as special when reading CSV + data. An exception is that psql will terminate + a COPY FROM STDIN operation (that is, reading + in-line COPY data in an SQL script) at a line containing + only \., whether it is text or CSV + mode. + + + PostgreSQL versions before v18 always + recognized unquoted \. as an end-of-data marker, + even when reading from a separate file. For compatibility with older + versions, COPY TO will quote \. + when it's alone on a line, even though this is no longer necessary. + + + In CSV format, all characters are significant. A quoted value @@ -855,7 +893,7 @@ COPY count - + Binary Format diff --git a/doc/src/sgml/ref/create_collation.sgml b/doc/src/sgml/ref/create_collation.sgml index e34bfc97c3da2..4af1836ae30e4 100644 --- a/doc/src/sgml/ref/create_collation.sgml +++ b/doc/src/sgml/ref/create_collation.sgml @@ -99,7 +99,8 @@ CREATE COLLATION [ IF NOT EXISTS ] name FROM If provider is builtin, then locale must be specified and set to - either C or C.UTF-8. + either C, C.UTF-8 or + PG_UNICODE_FAST. diff --git a/doc/src/sgml/ref/create_database.sgml b/doc/src/sgml/ref/create_database.sgml index 7653cb902eebe..640c0425faec5 100644 --- a/doc/src/sgml/ref/create_database.sgml +++ b/doc/src/sgml/ref/create_database.sgml @@ -138,7 +138,9 @@ CREATE DATABASE name log volume substantially, especially if the template database is large, it also forces the system to perform a checkpoint both before and after the creation of the new database. In some situations, this may - have a noticeable negative impact on overall system performance. + have a noticeable negative impact on overall system performance. The + FILE_COPY strategy is affected by the setting. @@ -168,7 +170,8 @@ CREATE DATABASE name If is builtin, then locale or builtin_locale must be specified and set to - either C or C.UTF-8. + either C, C.UTF-8, or + PG_UNICODE_FAST. @@ -233,7 +236,8 @@ CREATE DATABASE name The locales available for the builtin provider are - C and C.UTF-8. + C, C.UTF-8 and + PG_UNICODE_FAST. diff --git a/doc/src/sgml/ref/create_domain.sgml b/doc/src/sgml/ref/create_domain.sgml index ce55520348620..c111285a69c6d 100644 --- a/doc/src/sgml/ref/create_domain.sgml +++ b/doc/src/sgml/ref/create_domain.sgml @@ -283,7 +283,8 @@ CREATE TABLE us_snail_addy ( The syntax NOT NULL in this command is a PostgreSQL extension. (A standard-conforming - way to write the same would be CHECK (VALUE IS NOT + way to write the same for non-composite data types would be + CHECK (VALUE IS NOT NULL). However, per , such constraints are best avoided in practice anyway.) The NULL constraint is a diff --git a/doc/src/sgml/ref/create_extension.sgml b/doc/src/sgml/ref/create_extension.sgml index ca2b80d669c5e..713abd9c49447 100644 --- a/doc/src/sgml/ref/create_extension.sgml +++ b/doc/src/sgml/ref/create_extension.sgml @@ -90,8 +90,10 @@ CREATE EXTENSION [ IF NOT EXISTS ] extension_name The name of the extension to be installed. PostgreSQL will create the - extension using details from the file - SHAREDIR/extension/extension_name.control. + extension using details from the file extension_name.control, + found via the server's extension control path (set by .) diff --git a/doc/src/sgml/ref/create_foreign_table.sgml b/doc/src/sgml/ref/create_foreign_table.sgml index dc4b90759901b..d08834ac9d291 100644 --- a/doc/src/sgml/ref/create_foreign_table.sgml +++ b/doc/src/sgml/ref/create_foreign_table.sgml @@ -23,7 +23,8 @@ PostgreSQL documentation CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ OPTIONS ( option 'value' [, ... ] ) ] [ COLLATE collation ] [ column_constraint [ ... ] ] - | table_constraint } + | table_constraint + | LIKE source_table [ like_option ... ] } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] @@ -43,16 +44,23 @@ CREATE FOREIGN TABLE [ IF NOT EXISTS ] table_name where column_constraint is: [ CONSTRAINT constraint_name ] -{ NOT NULL | +{ NOT NULL [ NO INHERIT ] | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | - GENERATED ALWAYS AS ( generation_expr ) STORED } + GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] } +[ ENFORCED | NOT ENFORCED ] and table_constraint is: [ CONSTRAINT constraint_name ] -CHECK ( expression ) [ NO INHERIT ] +{ NOT NULL column_name [ NO INHERIT ] | + CHECK ( expression ) [ NO INHERIT ] } +[ ENFORCED | NOT ENFORCED ] + +and like_option is: + +{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | STATISTICS | ALL } and partition_bound_spec is: @@ -188,6 +196,111 @@ WITH ( MODULUS numeric_literal, REM + + LIKE source_table [ like_option ... ] + + + The LIKE clause specifies a table from which + the new table automatically copies all column names, their data types, + and their not-null constraints. + + + Unlike INHERITS, the new table and original table + are completely decoupled after creation is complete. Changes to the + original table will not be applied to the new table, and it is not + possible to include data of the new table in scans of the original + table. + + + Also unlike INHERITS, columns and + constraints copied by LIKE are not merged with similarly + named columns and constraints. + If the same name is specified explicitly or in another + LIKE clause, an error is signaled. + + + The optional like_option clauses specify + which additional properties of the original table to copy. Specifying + INCLUDING copies the property, specifying + EXCLUDING omits the property. + EXCLUDING is the default. If multiple specifications + are made for the same kind of object, the last one is used. The + available options are: + + + + INCLUDING COMMENTS + + + Comments for the copied columns, constraints, and indexes will be + copied. The default behavior is to exclude comments, resulting in + the copied columns and constraints in the new table having no + comments. + + + + + + INCLUDING CONSTRAINTS + + + CHECK constraints will be copied. No distinction + is made between column constraints and table constraints. Not-null + constraints are always copied to the new table. + + + + + + INCLUDING DEFAULTS + + + Default expressions for the copied column definitions will be + copied. Otherwise, default expressions are not copied, resulting in + the copied columns in the new table having null defaults. Note that + copying defaults that call database-modification functions, such as + nextval, may create a functional linkage + between the original and new tables. + + + + + + INCLUDING GENERATED + + + Any generation expressions of copied column definitions will be + copied. By default, new columns will be regular base columns. + + + + + + INCLUDING STATISTICS + + + Extended statistics are copied to the new table. + + + + + + INCLUDING ALL + + + INCLUDING ALL is an abbreviated form selecting + all the available individual options. (It could be useful to write + individual EXCLUDING clauses after + INCLUDING ALL to select all but some specific + options.) + + + + + + + + CONSTRAINT constraint_name @@ -203,11 +316,16 @@ WITH ( MODULUS numeric_literal, REM - NOT NULL + NOT NULL [ NO INHERIT ] The column is not allowed to contain null values. + + + A constraint marked with NO INHERIT will not propagate to + child tables. + @@ -275,7 +393,7 @@ WITH ( MODULUS numeric_literal, REM - GENERATED ALWAYS AS ( generation_expr ) STOREDgenerated column + GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ]generated column This clause creates the column as a generated @@ -284,10 +402,13 @@ WITH ( MODULUS numeric_literal, REM - The keyword STORED is required to signify that the + When VIRTUAL is specified, the column will be + computed when it is read. (The foreign-data wrapper will see it as a + null value in new rows and may choose to store it as a null value or + ignore it altogether.) When STORED is specified, the column will be computed on write. (The computed value will be presented to the foreign-data wrapper for storage and must be returned on - reading.) + reading.) VIRTUAL is the default. @@ -437,6 +558,8 @@ CREATE FOREIGN TABLE measurement_y2016m07 The ability to specify column default values is also a PostgreSQL extension. Table inheritance, in the form defined by PostgreSQL, is nonstandard. + The LIKE clause, as supported in this command, is + nonstandard. diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index 621bc0e253ceb..147a8f7587c71 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -387,9 +387,13 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] The optional WITH clause specifies storage - parameters for the index. Each index method has its own set of allowed - storage parameters. The B-tree, hash, GiST and SP-GiST index methods all - accept this parameter: + parameters for the index. Each index method has its own set + of allowed storage parameters. + + + + The B-tree, hash, GiST and SP-GiST index methods all accept this + parameter: @@ -401,7 +405,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - The fillfactor for an index is a percentage that determines how full + Controls how full the index method will try to pack index pages. For B-trees, leaf pages are filled to this percentage during initial index builds, and also when extending the index at the right (adding new largest key values). @@ -488,7 +492,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - Determines whether the buffered build technique described in + Controls whether the buffered build technique described in is used to build the index. With OFF buffering is disabled, with ON it is enabled, and with AUTO it is initially disabled, @@ -503,7 +507,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - GIN indexes accept different parameters: + GIN indexes accept these parameters: @@ -515,8 +519,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - This setting controls usage of the fast update technique described in - . It is a Boolean parameter: + Controls usage of the fast update technique described in + . ON enables fast update, OFF disables it. The default is ON. @@ -525,8 +529,9 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] Turning fastupdate off via ALTER INDEX prevents future insertions from going into the list of pending index entries, - but does not in itself flush previous entries. You might want to - VACUUM the table or call gin_clean_pending_list + but does not in itself flush existing entries. You might want to + VACUUM the table or call + the gin_clean_pending_list function afterward to ensure the pending list is emptied.
@@ -544,7 +549,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - Custom parameter. + Overrides the global setting of + for this index. This value is specified in kilobytes. @@ -552,7 +558,7 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] - BRIN indexes accept different parameters: + BRIN indexes accept these parameters: @@ -580,8 +586,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] Defines whether a summarization run is queued for the previous page - range whenever an insertion is detected on the next one. - See for more details. + range whenever an insertion is detected on the next one + (see for more details). The default is off. @@ -808,7 +814,7 @@ Indexes: leveraging multiple CPUs in order to process the table rows faster. This feature is known as parallel index build. For index methods that support building indexes - in parallel (currently, only B-tree), + in parallel (currently, B-tree and BRIN), maintenance_work_mem specifies the maximum amount of memory that can be used by each index build operation as a whole, regardless of how many worker processes were started. diff --git a/doc/src/sgml/ref/create_materialized_view.sgml b/doc/src/sgml/ref/create_materialized_view.sgml index 0d2fea2b97f0d..62d897931c314 100644 --- a/doc/src/sgml/ref/create_materialized_view.sgml +++ b/doc/src/sgml/ref/create_materialized_view.sgml @@ -143,7 +143,9 @@ CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] table_name A SELECT, TABLE, or VALUES command. This query will run within a security-restricted operation; in particular, calls to functions that - themselves create temporary tables will fail. + themselves create temporary tables will fail. Also, while the query is + running, the is temporarily changed to + pg_catalog, pg_temp. diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml index f1d6a4cbbe286..2d560b68658cf 100644 --- a/doc/src/sgml/ref/create_opclass.sgml +++ b/doc/src/sgml/ref/create_opclass.sgml @@ -269,14 +269,6 @@ CREATE OPERATOR CLASS name [ DEFAUL is likely to be inlined into the calling query, which will prevent the optimizer from recognizing that the query matches an index. - - - Before PostgreSQL 8.4, the OPERATOR - clause could include a RECHECK option. This is no longer - supported because whether an index operator is lossy is now - determined on-the-fly at run time. This allows efficient handling of - cases where an operator might or might not be lossy. - diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml index fd9c5deac95dc..802630f2df116 100644 --- a/doc/src/sgml/ref/create_publication.sgml +++ b/doc/src/sgml/ref/create_publication.sgml @@ -89,8 +89,11 @@ CREATE PUBLICATION name When a column list is specified, only the named columns are replicated. - If no column list is specified, all columns of the table are replicated - through this publication, including any columns added later. It has no + The column list can contain stored generated columns as well. If the + column list is omitted, the publication will replicate all non-generated + columns (including any added in the future) by default. Stored generated + columns can also be replicated if publish_generated_columns + is set to stored. Specifying a column list has no effect on TRUNCATE commands. See for details about column lists. @@ -188,6 +191,42 @@ CREATE PUBLICATION name + + publish_generated_columns (enum) + + + Specifies whether the generated columns present in the tables + associated with the publication should be replicated. Possible values + are none and stored. + + + + The default is none meaning the generated + columns present in the tables associated with publication will not be + replicated. + + + + If set to stored, the stored generated columns + present in the tables associated with publication will be replicated. + + + + + If the subscriber is from a release prior to 18, then initial table + synchronization won't copy generated columns even if parameter + publish_generated_columns is stored + in the publisher. + + + + + See for more details about + logical replication of generated columns. + + + + publish_via_partition_root (boolean) @@ -290,6 +329,14 @@ CREATE PUBLICATION name system columns. + + The generated columns that are part of REPLICA IDENTITY + must be published explicitly either by listing them in the column list or + by enabling the publish_generated_columns option, in + order for UPDATE and DELETE operations + to be published. + + The row filter on a table becomes redundant if FOR TABLES IN SCHEMA is specified and the table diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml index f72ba9affc2d1..cee23b1ea6b4d 100644 --- a/doc/src/sgml/ref/create_role.sgml +++ b/doc/src/sgml/ref/create_role.sgml @@ -273,6 +273,14 @@ in sync when changing the above synopsis! different format). This allows reloading of encrypted passwords during dump/restore. + + + Support for MD5-encrypted passwords is deprecated and will be removed + in a future release of PostgreSQL. Refer + to for details about migrating to + another password type. + + diff --git a/doc/src/sgml/ref/create_sequence.sgml b/doc/src/sgml/ref/create_sequence.sgml index 34e9084b5ccbf..1e283f13d15c6 100644 --- a/doc/src/sgml/ref/create_sequence.sgml +++ b/doc/src/sgml/ref/create_sequence.sgml @@ -25,7 +25,9 @@ CREATE [ { TEMPORARY | TEMP } | UNLOGGED ] SEQUENCE [ IF NOT EXISTS ] data_type ] [ INCREMENT [ BY ] increment ] [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] - [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ] + [ [ NO ] CYCLE ] + [ START [ WITH ] start ] + [ CACHE cache ] [ OWNED BY { table_name.column_name | NONE } ] @@ -193,6 +195,31 @@ SELECT * FROM name; + + CYCLE + NO CYCLE + + + The CYCLE option allows the sequence to wrap + around when the maxvalue or minvalue has been reached by an + ascending or descending sequence respectively. If the limit is + reached, the next number generated will be the minvalue or maxvalue, respectively. + + + + If NO CYCLE is specified, any calls to + nextval after the sequence has reached its + maximum value will return an error. If neither + CYCLE or NO CYCLE are + specified, NO CYCLE is the default. + + + + start @@ -221,31 +248,6 @@ SELECT * FROM name; - - CYCLE - NO CYCLE - - - The CYCLE option allows the sequence to wrap - around when the maxvalue or minvalue has been reached by an - ascending or descending sequence respectively. If the limit is - reached, the next number generated will be the minvalue or maxvalue, respectively. - - - - If NO CYCLE is specified, any calls to - nextval after the sequence has reached its - maximum value will return an error. If neither - CYCLE or NO CYCLE are - specified, NO CYCLE is the default. - - - - OWNED BY table_name.column_name OWNED BY NONE diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml index 740b7d9421041..57dec28a5df64 100644 --- a/doc/src/sgml/ref/create_subscription.sgml +++ b/doc/src/sgml/ref/create_subscription.sgml @@ -185,7 +185,7 @@ CREATE SUBSCRIPTION subscription_name When setting slot_name to a valid name and - create_slot to false, the + create_slot to false, the failover property value of the named slot may differ from the counterpart failover parameter specified in the subscription. Always ensure the slot property @@ -271,11 +271,23 @@ CREATE SUBSCRIPTION subscription_name Specifies whether to enable streaming of in-progress transactions - for this subscription. The default value is off, - meaning all transactions are fully decoded on the publisher and only - then sent to the subscriber as a whole. + for this subscription. The default value is parallel, + meaning incoming changes are directly applied via one of the parallel + apply workers, if available. If no parallel apply worker is free to + handle streaming transactions then the changes are written to + temporary files and applied after the transaction is committed. Note + that if an error happens in a parallel apply worker, the finish LSN + of the remote transaction might not be reported in the server log. + + + There is a risk of deadlock when the schemas of the publisher and + subscriber differ, although such cases are rare. The apply worker + is equipped to retry these transactions automatically. + + + If set to on, the incoming changes are written to temporary files and then applied only after the transaction is @@ -283,13 +295,8 @@ CREATE SUBSCRIPTION subscription_name - If set to parallel, incoming changes are directly - applied via one of the parallel apply workers, if available. If no - parallel apply worker is free to handle streaming transactions then - the changes are written to temporary files and applied after the - transaction is committed. Note that if an error happens in a - parallel apply worker, the finish LSN of the remote transaction - might not be reported in the server log. + If set to off, all transactions are fully decoded + on the publisher and only then sent to the subscriber as a whole. @@ -474,7 +481,8 @@ CREATE SUBSCRIPTION subscription_name If any table in the publication has a WHERE clause, rows for which the expression - evaluates to false or null will not be published. If the subscription has + evaluates to false or NULL will not be + published. If the subscription has several publications in which the same table has been published with different WHERE clauses, a row will be published if any of the expressions (referring to that publish operation) are satisfied. In @@ -526,12 +534,14 @@ CREATE SUBSCRIPTION subscription_name # substitute <pub-names> below with your publication name(s) to be queried SELECT DISTINCT PT.schemaname, PT.tablename -FROM pg_publication_tables PT, +FROM pg_publication_tables PT + JOIN pg_class C ON (C.relname = PT.tablename) + JOIN pg_namespace N ON (N.nspname = PT.schemaname), pg_subscription_rel PS - JOIN pg_class C ON (C.oid = PS.srrelid) - JOIN pg_namespace N ON (N.oid = C.relnamespace) -WHERE N.nspname = PT.schemaname AND - C.relname = PT.tablename AND +WHERE C.relnamespace = N.oid AND + (PS.srrelid = C.oid OR + C.oid IN (SELECT relid FROM pg_partition_ancestors(PS.srrelid) UNION + SELECT relid FROM pg_partition_tree(PS.srrelid))) AND PT.pubname IN (<pub-names>); diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 93b3f664f2112..4a41b2f553007 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -61,29 +61,30 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI where column_constraint is: [ CONSTRAINT constraint_name ] -{ NOT NULL | +{ NOT NULL [ NO INHERIT ] | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | - GENERATED ALWAYS AS ( generation_expr ) STORED | + GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } -[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] +[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | - UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters | - PRIMARY KEY ( column_name [, ... ] ) index_parameters | + NOT NULL column_name [ NO INHERIT ] | + UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters | + PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | - FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] + FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } -[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] +[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ] and like_option is: @@ -220,6 +221,10 @@ WITH ( MODULUS numeric_literal, REM If this is specified, any sequences created together with the unlogged table (for identity or serial columns) are also created as unlogged. + + + This form is not supported for partitioned tables. + @@ -720,8 +725,9 @@ WITH ( MODULUS numeric_literal, REM INCLUDING GENERATED - Any generation expressions of copied column definitions will be - copied. By default, new columns will be regular base columns. + Any generation expressions as well as the stored/virtual choice of + copied column definitions will be copied. By default, new columns + will be regular base columns. @@ -814,11 +820,16 @@ WITH ( MODULUS numeric_literal, REM - NOT NULL + NOT NULL [ NO INHERIT ] The column is not allowed to contain null values. + + + A constraint marked with NO INHERIT will not propagate to + child tables. + @@ -897,7 +908,7 @@ WITH ( MODULUS numeric_literal, REM - GENERATED ALWAYS AS ( generation_expr ) STOREDgenerated column + GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ]generated column This clause creates the column as a generated @@ -906,8 +917,11 @@ WITH ( MODULUS numeric_literal, REM - The keyword STORED is required to signify that the - column will be computed on write and will be stored on disk. + When VIRTUAL is specified, the column will be + computed when it is read, and it will not occupy any storage. When + STORED is specified, the column will be computed on + write and will be stored on disk. VIRTUAL is the + default. @@ -924,8 +938,8 @@ WITH ( MODULUS numeric_literal, REM This clause creates the column as an identity column. It will have an implicit sequence attached to it - and the column in new rows will automatically have values from the - sequence assigned to it. + and in newly-inserted rows the column will automatically have values + from the sequence assigned to it. Such a column is implicitly NOT NULL. @@ -955,16 +969,23 @@ WITH ( MODULUS numeric_literal, REM - The optional sequence_options clause can be - used to override the options of the sequence. - See for details. + The optional sequence_options clause can + be used to override the parameters of the sequence. The available + options include those shown for , + plus SEQUENCE NAME name, + LOGGED, and UNLOGGED, which + allow selection of the name and persistence level of the + sequence. Without SEQUENCE NAME, the system + chooses an unused name for the sequence. + Without LOGGED or UNLOGGED, + the sequence will have the same persistence level as the table. UNIQUE [ NULLS [ NOT ] DISTINCT ] (column constraint) - UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) + UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) INCLUDE ( column_name [, ...]) (table constraint) @@ -978,6 +999,27 @@ WITH ( MODULUS numeric_literal, REM of these columns. + + If the WITHOUT OVERLAPS option is specified for the + last column, then that column is checked for overlaps instead of + equality. In that case, the other columns of the constraint will allow + duplicates so long as the duplicates don't overlap in the + WITHOUT OVERLAPS column. (This is sometimes called a + temporal key, if the column is a range of dates or timestamps, but + PostgreSQL allows ranges over any base type.) + In effect, such a constraint is enforced with an EXCLUDE + constraint rather than a UNIQUE constraint. So for + example UNIQUE (id, valid_at WITHOUT OVERLAPS) behaves + like EXCLUDE USING GIST (id WITH =, valid_at WITH + &&). The WITHOUT OVERLAPS column + must have a range or multirange type. Empty ranges/multiranges are + not permitted. The non-WITHOUT OVERLAPS columns of + the constraint can be any type that can be compared for equality in a + GiST index. By default, only range types are supported, but you can use + other types by adding the extension (which + is the expected way to use this feature). + + For the purpose of a unique constraint, null values are not considered equal, unless NULLS NOT DISTINCT is @@ -1000,8 +1042,10 @@ WITH ( MODULUS numeric_literal, REM Adding a unique constraint will automatically create a unique btree - index on the column or group of columns used in the constraint. The - created index has the same name as the unique constraint. + index on the column or group of columns used in the constraint. But if + the constraint includes a WITHOUT OVERLAPS clause, it + will use a GiST index. The created index has the same name as the + unique constraint. @@ -1019,7 +1063,7 @@ WITH ( MODULUS numeric_literal, REM PRIMARY KEY (column constraint) - PRIMARY KEY ( column_name [, ... ] ) + PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) INCLUDE ( column_name [, ...]) (table constraint) @@ -1054,8 +1098,8 @@ WITH ( MODULUS numeric_literal, REM Adding a PRIMARY KEY constraint will automatically create a unique btree index on the column or group of columns used in - the constraint. That index has the same name as the primary key - constraint. + the constraint, or GiST if WITHOUT OVERLAPS was + specified. @@ -1124,8 +1168,8 @@ WITH ( MODULUS numeric_literal, REM REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] (column constraint) - FOREIGN KEY ( column_name [, ... ] ) - REFERENCES reftable [ ( refcolumn [, ... ] ) ] + FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) + REFERENCES reftable [ ( refcolumn [, ... ] [, PERIOD refcolumn ] ) ] [ MATCH matchtype ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] @@ -1141,7 +1185,39 @@ WITH ( MODULUS numeric_literal, REM primary key of the reftable is used. Otherwise, the refcolumn list must refer to the columns of a non-deferrable unique or primary key - constraint or be the columns of a non-partial unique index. The user + constraint or be the columns of a non-partial unique index. + + + + If the last column is marked with PERIOD, it is + treated in a special way. While the non-PERIOD + columns are compared for equality (and there must be at least one of + them), the PERIOD column is not. Instead, the + constraint is considered satisfied if the referenced table has matching + records (based on the non-PERIOD parts of the key) + whose combined PERIOD values completely cover the + referencing record's. In other words, the reference must have a + referent for its entire duration. This column must be a range or + multirange type. In addition, the referenced table must have a primary + key or unique constraint declared with WITHOUT + OVERLAPS. Finally, if the foreign key has a PERIOD + column_name specification + the corresponding refcolumn, + if present, must also be marked PERIOD. If the + refcolumn clause is omitted, + and thus the reftable's primary key constraint chosen, the primary key + must have its final column marked WITHOUT OVERLAPS. + + + + For each pair of referencing and referenced column, if they are of a + collatable data type, then the collations must either be both + deterministic or else both the same. This ensures that both columns + have a consistent notion of equality. + + + + The user must have REFERENCES permission on the referenced table (either the whole table, or the specific referenced columns). The addition of a foreign key constraint requires a @@ -1176,17 +1252,16 @@ WITH ( MODULUS numeric_literal, REM clause specifies the action to perform when a referenced column in the referenced table is being updated to a new value. If the row is updated, but the referenced column is not actually - changed, no action is done. Referential actions other than the - NO ACTION check cannot be deferred, even if - the constraint is declared deferrable. There are the following possible - actions for each clause: + changed, no action is done. Referential actions are executed as part of + the data changing command, even if the constraint is deferred. There + are the following possible actions for each clause: NO ACTION - Produce an error indicating that the deletion or update + Produce an error if the deletion or update would create a foreign key constraint violation. If the constraint is deferred, this error will be produced at constraint check time if there still @@ -1199,10 +1274,17 @@ WITH ( MODULUS numeric_literal, REM RESTRICT - Produce an error indicating that the deletion or update - would create a foreign key constraint violation. - This is the same as NO ACTION except that - the check is not deferrable. + Produce an error if a row to be deleted or updated matches a row in + the referencing table. This prevents the action even if the state + after the action would not violate the foreign key constraint. In + particular, it prevents updates of referenced rows to values that + are distinct but compare as equal. (But it does not prevent + no-op updates that update a column to the same + value.) + + + + In a temporal foreign key, this option is not supported. @@ -1215,6 +1297,10 @@ WITH ( MODULUS numeric_literal, REM values of the referencing column(s) to the new values of the referenced columns, respectively. + + + In a temporal foreign key, this option is not supported. + @@ -1226,6 +1312,10 @@ WITH ( MODULUS numeric_literal, REM referencing columns, to null. A subset of columns can only be specified for ON DELETE actions. + + + In a temporal foreign key, this option is not supported. + @@ -1239,6 +1329,10 @@ WITH ( MODULUS numeric_literal, REM (There must be a row in the referenced table matching the default values, if they are not null, or the operation will fail.) + + + In a temporal foreign key, this option is not supported. + @@ -1291,6 +1385,36 @@ WITH ( MODULUS numeric_literal, REM + + ENFORCED + NOT ENFORCED + + + When the constraint is ENFORCED, then the database + system will ensure that the constraint is satisfied, by checking the + constraint at appropriate times (after each statement or at the end of + the transaction, as appropriate). That is the default. If the + constraint is NOT ENFORCED, the database system will + not check the constraint. It is then up to the application code to + ensure that the constraints are satisfied. The database system might + still assume that the data actually satisfies the constraint for + optimization decisions where this does not affect the correctness of the + result. + + + + NOT ENFORCED constraints can be useful as + documentation if the actual checking of the constraint at run time is + too expensive. + + + + This is currently only supported for foreign key and CHECK + constraints. + + + + USING method @@ -1568,15 +1692,10 @@ WITH ( MODULUS numeric_literal, REM - Enables or disables vacuum to try to truncate off any empty pages - at the end of this table. The default value is true. - If true, VACUUM and - autovacuum do the truncation and the disk space for - the truncated pages is returned to the operating system. - Note that the truncation requires ACCESS EXCLUSIVE - lock on the table. The TRUNCATE parameter - of VACUUM, if specified, overrides the value - of this option. + Per-table value for parameter. The + TRUNCATE parameter of + VACUUM, if + specified, overrides the value of this option. @@ -1596,6 +1715,21 @@ WITH ( MODULUS numeric_literal, REM + + autovacuum_vacuum_max_threshold, toast.autovacuum_vacuum_max_threshold (integer) + + autovacuum_vacuum_max_threshold + storage parameter + + + + + Per-table value for + parameter. + + + + autovacuum_vacuum_scale_factor, toast.autovacuum_vacuum_scale_factor (floating point) @@ -1815,6 +1949,21 @@ WITH ( MODULUS numeric_literal, REM + + vacuum_max_eager_freeze_failure_rate, toast.vacuum_max_eager_freeze_failure_rate (floating point) + + vacuum_max_eager_freeze_failure_rate + storage parameter + + + + + Per-table value for + parameter. + + + + user_catalog_table (boolean) @@ -2327,13 +2476,6 @@ CREATE TABLE cities_partdef constraint, and index names must be unique across all relations within the same schema. - - - Currently, PostgreSQL does not record names - for not-null constraints at all, so they are not - subject to the uniqueness restriction. This might change in a future - release. - @@ -2380,9 +2522,9 @@ CREATE TABLE cities_partdef Generated Columns - The option STORED is not standard but is also used by - other SQL implementations. The SQL standard does not specify the storage - of generated columns. + The options STORED and VIRTUAL are + not standard but are also used by other SQL implementations. The SQL + standard does not specify the storage of generated columns. diff --git a/doc/src/sgml/ref/create_tablespace.sgml b/doc/src/sgml/ref/create_tablespace.sgml index 9d5ab025261da..b77e774c53f92 100644 --- a/doc/src/sgml/ref/create_tablespace.sgml +++ b/doc/src/sgml/ref/create_tablespace.sgml @@ -110,7 +110,7 @@ CREATE TABLESPACE tablespace_name and maintenance_io_concurrency. Setting these values for a particular tablespace will override the planner's usual estimate of the cost of reading pages from tables in - that tablespace, and the executor's prefetching behavior, as established + that tablespace, and how many concurrent I/Os are issued, as established by the configuration parameters of the same name (see , , diff --git a/doc/src/sgml/ref/delete.sgml b/doc/src/sgml/ref/delete.sgml index 7717855bc9ef4..29649f6afd65c 100644 --- a/doc/src/sgml/ref/delete.sgml +++ b/doc/src/sgml/ref/delete.sgml @@ -25,7 +25,8 @@ PostgreSQL documentation DELETE FROM [ ONLY ] table_name [ * ] [ [ AS ] alias ] [ USING from_item [, ...] ] [ WHERE condition | WHERE CURRENT OF cursor_name ] - [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ] + [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ] + { * | output_expression [ [ AS ] output_name ] } [, ...] ] @@ -160,6 +161,26 @@ DELETE FROM [ ONLY ] table_name [ * + + output_alias + + + An optional substitute name for OLD or + NEW rows in the RETURNING list. + + + + By default, old values from the target table can be returned by writing + OLD.column_name + or OLD.*, and new values can be returned by writing + NEW.column_name + or NEW.*. When an alias is provided, these names are + hidden and the old or new rows must be referred to using the alias. + For example RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*. + + + + output_expression @@ -170,6 +191,23 @@ DELETE FROM [ ONLY ] table_name [ * or table(s) listed in USING. Write * to return all columns. + + + A column name or * may be qualified using + OLD or NEW, or the corresponding + output_alias for + OLD or NEW, to cause old or new + values to be returned. An unqualified column name, or + *, or a column name or * qualified + using the target table name or alias will return old values. + + + + For a simple DELETE, all new values will be + NULL. However, if an ON DELETE + rule causes an INSERT or UPDATE + to be executed instead, the new values may be non-NULL. + diff --git a/doc/src/sgml/ref/drop_extension.sgml b/doc/src/sgml/ref/drop_extension.sgml index 484e5d9b11a15..4266c6d1ceb31 100644 --- a/doc/src/sgml/ref/drop_extension.sgml +++ b/doc/src/sgml/ref/drop_extension.sgml @@ -82,7 +82,7 @@ DROP EXTENSION [ IF EXISTS ] name [ This option prevents the specified extensions from being dropped if other objects, besides these extensions, their members, and their - explicitly dependent routines, depend on them.  This is the default. + explicitly dependent routines, depend on them. This is the default. diff --git a/doc/src/sgml/ref/drop_owned.sgml b/doc/src/sgml/ref/drop_owned.sgml index efda01a39e88b..46e1c229ec0fb 100644 --- a/doc/src/sgml/ref/drop_owned.sgml +++ b/doc/src/sgml/ref/drop_owned.sgml @@ -33,7 +33,7 @@ DROP OWNED BY { name | CURRENT_ROLE database that are owned by one of the specified roles. Any privileges granted to the given roles on objects in the current database or on shared objects (databases, tablespaces, configuration - parameters) will also be revoked. + parameters, or other roles) will also be revoked. diff --git a/doc/src/sgml/ref/explain.sgml b/doc/src/sgml/ref/explain.sgml index db9d3a8549add..6dda680aa0de8 100644 --- a/doc/src/sgml/ref/explain.sgml +++ b/doc/src/sgml/ref/explain.sgml @@ -201,8 +201,8 @@ ROLLBACK; query processing. The number of blocks shown for an upper-level node includes those used by all its child nodes. In text - format, only non-zero values are printed. This parameter defaults to - FALSE. + format, only non-zero values are printed. Buffers information is + automatically included when ANALYZE is used. @@ -240,8 +240,9 @@ ROLLBACK; Include information on WAL record generation. Specifically, include the - number of records, number of full page images (fpi) and the amount of WAL - generated in bytes. In text format, only non-zero values are printed. + number of records, number of full page images (fpi), the amount of WAL + generated in bytes and the number of times the WAL buffers became full. + In text format, only non-zero values are printed. This parameter may only be used when ANALYZE is also enabled. It defaults to FALSE. @@ -497,14 +498,17 @@ EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN -------------------------------------------------------------------&zwsp;------------------------------------------------------ - HashAggregate (cost=10.77..10.87 rows=10 width=12) (actual time=0.043..0.044 rows=10 loops=1) + HashAggregate (cost=10.77..10.87 rows=10 width=12) (actual time=0.043..0.044 rows=10.00 loops=1) Group Key: foo Batches: 1 Memory Usage: 24kB - -> Index Scan using test_pkey on test (cost=0.29..10.27 rows=99 width=8) (actual time=0.009..0.025 rows=99 loops=1) + Buffers: shared hit=4 + -> Index Scan using test_pkey on test (cost=0.29..10.27 rows=99 width=8) (actual time=0.009..0.025 rows=99.00 loops=1) Index Cond: ((id > 100) AND (id < 200)) + Index Searches: 1 + Buffers: shared hit=4 Planning Time: 0.244 ms Execution Time: 0.073 ms -(7 rows) +(10 rows) diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index bdd613e77ffdd..7613174c18b56 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -227,7 +227,7 @@ PostgreSQL documentation - + @@ -260,14 +260,20 @@ PostgreSQL documentation - + - Use checksums on data pages to help detect corruption by the - I/O system that would otherwise be silent. Enabling checksums - may incur a noticeable performance penalty. If set, checksums + Use checksums on data pages to help detect corruption by the I/O + system that would otherwise be silent. This is enabled by default; + use to disable + checksums. + + + + Enabling checksums + might incur a small performance penalty. If set, checksums are calculated for all objects, in all databases. All checksum failures will be reported in the @@ -289,8 +295,8 @@ PostgreSQL documentation If is builtin, or must be - specified and set to C or - C.UTF-8. + specified and set to C, C.UTF-8 + or PG_UNICODE_FAST. @@ -343,6 +349,15 @@ PostgreSQL documentation + + + + + Do not enable data checksums. + + + + @@ -512,6 +527,33 @@ PostgreSQL documentation + + + + + By default, initdb safely writes all database files + to disk. This option instructs initdb to skip + synchronizing all files in the individual database directories, the + database directories themselves, and the tablespace directories, i.e., + everything in the base subdirectory and any other + tablespace directories. Other files, such as those in + pg_wal and pg_xact, will still be + synchronized unless the option is also + specified. + + + Note that if is used in + conjunction with , some or all of + the aforementioned files and directories will be synchronized because + syncfs processes entire file systems. + + + This option is primarily intended for internal use by tools that + separately ensure the skipped files are synchronized to disk. + + + + diff --git a/doc/src/sgml/ref/insert.sgml b/doc/src/sgml/ref/insert.sgml index 6f0adee1a124a..3f13991779050 100644 --- a/doc/src/sgml/ref/insert.sgml +++ b/doc/src/sgml/ref/insert.sgml @@ -26,7 +26,8 @@ INSERT INTO table_name [ AS expression | DEFAULT } [, ...] ) [, ...] | query } [ ON CONFLICT [ conflict_target ] conflict_action ] - [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ] + [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ] + { * | output_expression [ [ AS ] output_name ] } [, ...] ] where conflict_target can be one of: @@ -293,6 +294,26 @@ INSERT INTO table_name [ AS + + output_alias + + + An optional substitute name for OLD or + NEW rows in the RETURNING list. + + + + By default, old values from the target table can be returned by writing + OLD.column_name + or OLD.*, and new values can be returned by writing + NEW.column_name + or NEW.*. When an alias is provided, these names are + hidden and the old or new rows must be referred to using the alias. + For example RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*. + + + + output_expression @@ -305,6 +326,23 @@ INSERT INTO table_name [ AS * to return all columns of the inserted or updated row(s). + + + A column name or * may be qualified using + OLD or NEW, or the corresponding + output_alias for + OLD or NEW, to cause old or new + values to be returned. An unqualified column name, or + *, or a column name or * + qualified using the target table name or alias will return new values. + + + + For a simple INSERT, all old values will be + NULL. However, for an INSERT + with an ON CONFLICT DO UPDATE clause, the old + values may be non-NULL. + @@ -711,6 +749,20 @@ INSERT INTO employees_log SELECT *, current_timestamp FROM upd; INSERT INTO distributors (did, dname) VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname; + + + + Insert or update new distributors as above, returning information + about any existing values that were updated, together with the new data + inserted. Note that the returned values for old_did + and old_dname will be NULL for + non-conflicting rows: + +INSERT INTO distributors (did, dname) + VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') + ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname + RETURNING old.did AS old_did, old.dname AS old_dname, + new.did AS new_did, new.dname AS new_dname; diff --git a/doc/src/sgml/ref/merge.sgml b/doc/src/sgml/ref/merge.sgml index 97b34b9fcaf7a..ecbcd8345d874 100644 --- a/doc/src/sgml/ref/merge.sgml +++ b/doc/src/sgml/ref/merge.sgml @@ -25,7 +25,8 @@ PostgreSQL documentation MERGE INTO [ ONLY ] target_table_name [ * ] [ [ AS ] target_alias ] USING data_source ON join_condition when_clause [...] -[ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ] +[ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ] + { * | output_expression [ [ AS ] output_name ] } [, ...] ] where data_source is: @@ -499,6 +500,25 @@ DELETE + + output_alias + + + An optional substitute name for OLD or + NEW rows in the RETURNING list. + + + By default, old values from the target table can be returned by writing + OLD.column_name + or OLD.*, and new values can be returned by writing + NEW.column_name + or NEW.*. When an alias is provided, these names are + hidden and the old or new rows must be referred to using the alias. + For example RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*. + + + + output_expression @@ -517,6 +537,17 @@ DELETE qualifying the * with the name or alias of the source or target table. + + A column name or * may also be qualified using + OLD or NEW, or the corresponding + output_alias for + OLD or NEW, to cause old or new + values from the target table to be returned. An unqualified column + name from the target table, or a column name or * + qualified using the target table name or alias will return new values + for INSERT and UPDATE actions, and + old values for DELETE actions. + @@ -707,23 +738,6 @@ WHEN NOT MATCHED THEN - - Notice that this would be exactly equivalent to the following - statement because the MATCHED result does not change - during execution. - - -MERGE INTO customer_account ca -USING (SELECT customer_id, transaction_value FROM recent_transactions) AS t -ON t.customer_id = ca.customer_id -WHEN MATCHED THEN - UPDATE SET balance = balance + transaction_value -WHEN NOT MATCHED THEN - INSERT (customer_id, balance) - VALUES (t.customer_id, t.transaction_value); - - - Attempt to insert a new stock item along with the quantity of stock. If the item already exists, instead update the stock count of the existing @@ -739,7 +753,7 @@ WHEN MATCHED AND w.stock + s.stock_delta > 0 THEN UPDATE SET stock = w.stock + s.stock_delta WHEN MATCHED THEN DELETE -RETURNING merge_action(), w.*; +RETURNING merge_action(), w.winename, old.stock AS old_stock, new.stock AS new_stock; The wine_stock_changes table might be, for example, a diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml index 82d0c8e0088d2..9659f76042c5b 100644 --- a/doc/src/sgml/ref/pg_basebackup.sgml +++ b/doc/src/sgml/ref/pg_basebackup.sgml @@ -687,7 +687,7 @@ PostgreSQL documentation Using a SHA hash function provides a cryptographically secure digest of each file for users who wish to verify that the backup has not been - tampered with, while the CRC32C algorithm provides a checksum that is + tampered with, while the CRC-32C algorithm provides a checksum that is much faster to calculate; it is good at catching errors due to accidental changes but is not resistant to malicious modifications. Note that, to be useful against an adversary who has access to the backup, the backup @@ -807,14 +807,18 @@ PostgreSQL documentation will override any conflicting command line options. - The option is called --dbname for consistency with other + This option is called --dbname for consistency with other client applications, but because pg_basebackup doesn't connect to any particular database in the cluster, any database - name in the connection string will be ignored - by PostgreSQL. Middleware, or proxies, used in - connecting to PostgreSQL might however - utilize the value. The database name specified in connection string can - also be used by + name included in the connection string will be ignored by the server. + However, a database name supplied that way overrides the default + database name (replication) for purposes of + looking up the replication connection's password + in ~/.pgpass. Similarly, middleware or proxies + used in connecting to PostgreSQL might + utilize the name for purposes such as connection routing. The + database name can also be used + by logical replication slot synchronization. @@ -1001,10 +1005,11 @@ PostgreSQL documentation pg_basebackup works with servers of the same - or an older major version, down to 9.1. However, WAL streaming mode (-X - stream) only works with server version 9.3 and later, and tar format + or older major version, down to 9.1. However, WAL streaming mode (-X + stream) only works with server version 9.3 and later, the tar format (--format=tar) only works with server version 9.5 - and later. + and later, and incremental backup (--incremental) only works + with server version 17 and later. diff --git a/doc/src/sgml/ref/pg_combinebackup.sgml b/doc/src/sgml/ref/pg_combinebackup.sgml index 091982f62ad56..330a598f7013e 100644 --- a/doc/src/sgml/ref/pg_combinebackup.sgml +++ b/doc/src/sgml/ref/pg_combinebackup.sgml @@ -81,6 +81,35 @@ PostgreSQL documentation + + + + + + Use hard links instead of copying files to the synthetic backup. + Reconstruction of the synthetic backup might be faster (no file copying) + and use less disk space, but care must be taken when using the output + directory, because any modifications to that directory (for example, + starting the server) can also affect the input directories. Likewise, + changes to the input directories (for example, starting the server on + the full backup) could affect the output directory. Thus, this option + is best used when the input directories are only copies that will be + removed after pg_combinebackup has completed. + + + + Requires that the input backups and the output directory are in the + same file system. + + + + If a backup manifest is not available or does not contain checksum of + the right type, hard links will still be created, but the file will be + also read block-by-block for the checksum calculation. + + + + @@ -167,7 +196,8 @@ PostgreSQL documentation Perform regular file copy. This is the default. (See also - and .) + , , and + /.) diff --git a/doc/src/sgml/ref/pg_createsubscriber.sgml b/doc/src/sgml/ref/pg_createsubscriber.sgml index 87a9d3db28e5d..4b1d08d5f16da 100644 --- a/doc/src/sgml/ref/pg_createsubscriber.sgml +++ b/doc/src/sgml/ref/pg_createsubscriber.sgml @@ -49,7 +49,8 @@ PostgreSQL documentation pg_createsubscriber creates a new logical replica from a physical standby server. All tables in the specified - database are included in the logical replication setup. A pair of + database are included in the logical + replication setup. A pair of publication and subscription objects are created for each database. It must be run at the target server. @@ -57,20 +58,24 @@ PostgreSQL documentation After a successful run, the state of the target server is analogous to a fresh logical replication setup. The main difference between the logical - replication setup and pg_createsubscriber is the - initial data copy. It does only the synchronization phase, which ensures - each table is brought up to a synchronized state. + replication setup and pg_createsubscriber is how + the data synchronization is done. pg_createsubscriber + does not copy the initial table data. It does only the synchronization phase, + which ensures each table is brought up to a synchronized state. - The pg_createsubscriber targets large database + pg_createsubscriber targets large database systems because in logical replication setup, most of the time is spent doing the initial data copy. Furthermore, a side effect of this long time spent synchronizing data is usually a large amount of changes to be applied (that were produced during the initial data copy), which increases even more the time when the logical replica will be available. For smaller - databases, - initial data synchronization is recommended. + databases, it is recommended to set up logical replication with initial data + synchronization. For details, see the CREATE SUBSCRIPTION + + copy_data option. + @@ -82,13 +87,40 @@ PostgreSQL documentation command-line arguments: + + + + + + Create one subscription per database on the target server. Exceptions + are template databases and databases that don't allow connections. + To discover the list of all databases, connect to the source server + using the database name specified in the + connection string, or if not specified, the postgres + database will be used, or if that does not exist, template1 + will be used. + Automatically generated names for subscriptions, publications, and + replication slots are used when this option is specified. + This option cannot be used along with , + , , or + . + + + + - The database name to create the subscription. Multiple databases can - be selected by writing multiple switches. + The name of the database in which to create a subscription. Multiple + databases can be selected by writing multiple + switches. This option cannot be used together with . + If option is not provided, the database name will be + obtained from option. If the database name is not + specified in either the option, or the + option, and option is not + specified, an error will be reported. @@ -137,9 +169,39 @@ PostgreSQL documentation + + + + + + Remove all objects of the specified type from specified databases on the + target server. + + + + + + publications: + The FOR ALL TABLES publications established for this + subscriber are always removed; specifying this object type causes all + other publications replicated from the source server to be dropped as + well. + + + + + + The objects selected to be dropped are individually logged, including during + a . There is no opportunity to affect or stop the + dropping of the selected objects, so consider taking a backup of them + using pg_dump. + + + + - + The directory to use for postmaster sockets on target server. The @@ -159,6 +221,19 @@ PostgreSQL documentation + + + + + + Enables two_phase + commit for the subscription. When multiple databases are specified, this + option applies uniformly to all subscriptions created on those databases. + The default is false. + + + + @@ -189,8 +264,8 @@ PostgreSQL documentation Use the specified main server configuration file for the target data - directory. The pg_createsubscriber uses - internally the pg_ctl command to start and + directory. pg_createsubscriber internally uses + the pg_ctl command to start and stop the target server. It allows you to specify the actual postgresql.conf configuration file if it is stored outside the data directory. @@ -208,7 +283,8 @@ PostgreSQL documentation names must match the number of specified databases, otherwise an error is reported. The order of the multiple publication name switches must match the order of database switches. If this option is not specified, - a generated name is assigned to the publication name. + a generated name is assigned to the publication name. This option cannot + be used together with . @@ -224,7 +300,8 @@ PostgreSQL documentation otherwise an error is reported. The order of the multiple replication slot name switches must match the order of database switches. If this option is not specified, the subscription name is assigned to the - replication slot name. + replication slot name. This option cannot be used together with + . @@ -239,7 +316,8 @@ PostgreSQL documentation names must match the number of specified databases, otherwise an error is reported. The order of the multiple subscription name switches must match the order of database switches. If this option is not specified, - a generated name is assigned to the subscription name. + a generated name is assigned to the subscription name. This option cannot + be used together with . @@ -289,12 +367,14 @@ PostgreSQL documentation The target server must be used as a physical standby. The target server - must have and and configured to a value greater than or equal to the number of specified databases. The target server must have configured to a value greater than the number of specified databases. The target server - must accept local connections. + must accept local connections. If you are planning to use the + switch then you will also need to set + the appropriately. @@ -354,6 +434,7 @@ PostgreSQL documentation + Unless the switch is specified, pg_createsubscriber sets up logical replication with two-phase commit disabled. This means that any prepared transactions will be replicated at the time @@ -371,6 +452,13 @@ PostgreSQL documentation server. If the target server has a standby, replication will break and a fresh standby should be created. + + + Replication failures can occur if required WAL files are missing. To prevent + this, the source server must set + to -1 to + ensure that required WAL files are not prematurely removed. + @@ -405,11 +493,11 @@ PostgreSQL documentation Create a publication and replication slot for each specified database on the source server. Each publication is created using FOR ALL - TABLES. If option is - not specified, it has the following name pattern: + TABLES. If the option + is not specified, the publication has the following name pattern: pg_createsubscriber_%u_%x (parameter: database oid, random int). - If is not specified, the + If the option is not specified, the replication slot has the following name pattern: pg_createsubscriber_%u_%x (parameters: database oid, random int). @@ -444,8 +532,8 @@ PostgreSQL documentation Create a subscription for each specified database on the target server. - If is not specified, the subscription - has the following name pattern: + If the option is not specified, the + subscription has the following name pattern: pg_createsubscriber_%u_%x (parameters: database oid, random int). It does not copy existing data from the source server. It does not diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index b95ed875176f7..1e06bd33bdcd1 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -36,16 +36,20 @@ PostgreSQL documentation Description - pg_dump is a utility for backing up a + pg_dump is a utility for exporting a PostgreSQL database. It makes consistent - backups even if the database is being used concurrently. + exports even if the database is being used concurrently. pg_dump does not block other users accessing the database (readers or writers). + Note, however, that except in simple cases, + pg_dump is generally not the right choice for + taking regular backups of production databases. See for further discussion. pg_dump only dumps a single database. - To back up an entire cluster, or to back up global objects that are + To export an entire cluster, or to export global objects that are common to all databases in a cluster (such as roles and tablespaces), use . @@ -76,7 +80,7 @@ PostgreSQL documentation pg_restore, pg_dump provides a flexible archival and transfer mechanism. pg_dump can be used to - backup an entire database, then pg_restore + export an entire database, then pg_restore can be used to examine the archive and/or select which parts of the database are to be restored. The most flexible output file formats are the custom format () and the @@ -119,7 +123,7 @@ PostgreSQL documentation - Dump only the data, not the schema (data definitions). + Dump only the data, not the schema (data definitions) or statistics. Table data, large objects, and sequence values are dumped. @@ -137,13 +141,15 @@ PostgreSQL documentation Include large objects in the dump. This is the default behavior - except when , , or - is specified. The - switch is therefore only useful to add large objects to dumps - where a specific schema or table has been requested. Note that - large objects are considered data and therefore will be included when - is used, but not - when is. + except when , , + , , or + is specified. The + switch is therefore only useful to add large objects to dumps where a + specific schema or table has been requested. Note that large objects + are considered data and therefore will be included when + is used, but not when + or + is. @@ -512,10 +518,11 @@ PostgreSQL documentation - Dump only the object definitions (schema), not data. + Dump only the object definitions (schema), not data or statistics. - This option is the inverse of . + This option cannot be used with + or . It is similar to, but for historical reasons not identical to, specifying . @@ -737,7 +744,8 @@ PostgreSQL documentation - This option is relevant only when creating a data-only dump. + This option is relevant only when creating a dump that includes data + but does not include schema. It instructs pg_dump to include commands to temporarily disable triggers on the target tables while the data is restored. Use this if you have referential @@ -829,7 +837,8 @@ PostgreSQL documentation though you do not need the data in it. - To exclude data for all tables in the database, see . + To exclude data for all tables in the database, see + or . @@ -997,6 +1006,14 @@ PostgreSQL documentation The only exception is that an empty pattern is disallowed. + + + Using wildcards in may result + in access to unexpected foreign servers. Also, to use this option securely, + make sure that the named server must have a trusted owner. + + + When is specified, @@ -1063,7 +1080,25 @@ PostgreSQL documentation - Do not dump comments. + Do not dump COMMENT commands. + + + + + + + + + Do not dump data. + + + + + + + + + Do not dump row security policies. @@ -1077,6 +1112,15 @@ PostgreSQL documentation + + + + + Do not dump schema (data definitions). + + + + @@ -1086,6 +1130,15 @@ PostgreSQL documentation + + + + + Do not dump statistics. This is the default. + + + + @@ -1224,14 +1277,27 @@ PostgreSQL documentation The data section contains actual table data, large-object - contents, and sequence values. + contents, sequence values, and statistics for tables, + materialized views, and foriegn tables. Post-data items include definitions of indexes, triggers, rules, - and constraints other than validated check constraints. + statistics for indexes, and constraints other than validated check + constraints. Pre-data items include all other data definition items. + + + + + Include sequence data in the dump. This is the default behavior except + when , , or + is specified. + + + + @@ -1288,6 +1354,17 @@ PostgreSQL documentation + + + + + Dump only the statistics, not the schema (data definitions) or data. + Statistics for tables, materialized views, foreign tables, + and indexes are dumped. + + + + @@ -1363,6 +1440,33 @@ PostgreSQL documentation + + + + + Dump data. This is the default. + + + + + + + + + Dump schema (data definitions). This is the default. + + + + + + + + + Dump statistics. + + + + @@ -1569,7 +1673,7 @@ CREATE DATABASE foo WITH TEMPLATE template0; - When a data-only dump is chosen and the option + When a dump without schema is chosen and the option is used, pg_dump emits commands to disable triggers on user tables before inserting the data, and then commands to re-enable them after the data has been @@ -1578,12 +1682,14 @@ CREATE DATABASE foo WITH TEMPLATE template0; - The dump file produced by pg_dump - does not contain the statistics used by the optimizer to make - query planning decisions. Therefore, it is wise to run - ANALYZE after restoring from a dump file - to ensure optimal performance; see - and for more information. + If is specified, + pg_dump will include most optimizer statistics in the + resulting dump file. However, some statistics may not be included, such as + those created explicitly with or + custom statistics added by an extension. Therefore, it may be useful to + run ANALYZE after restoring from a dump file to ensure + optimal performance; see and for more information. @@ -1624,6 +1730,14 @@ CREATE DATABASE foo WITH TEMPLATE template0; option will be automatically enabled by the subscriber if the subscription had been originally created with two_phase = true option. + + + It is generally recommended to use the + () option when restoring a database from a + plain-text pg_dump script to ensure a clean + restore process and prevent potential conflicts with + non-default psql configurations. + @@ -1641,7 +1755,7 @@ CREATE DATABASE foo WITH TEMPLATE template0; newdb: -$ psql -d newdb -f db.sql +$ psql -X -d newdb -f db.sql diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index 4d7c0464687ef..43f384ed16a9c 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -16,7 +16,7 @@ PostgreSQL documentation pg_dumpall - extract a PostgreSQL database cluster into a script file + extract a PostgreSQL database cluster using a specified dump format @@ -33,7 +33,7 @@ PostgreSQL documentation pg_dumpall is a utility for writing out (dumping) all PostgreSQL databases - of a cluster into one script file. The script file contains + of a cluster into an archive. The archive contains SQL commands that can be used as input to to restore the databases. It does this by calling for each database in the cluster. @@ -52,11 +52,16 @@ PostgreSQL documentation - The SQL script will be written to the standard output. Use the + Plain text SQL scripts will be written to the standard output. Use the / option or shell operators to redirect it into a file. + + Archives in other formats will be placed in a directory named using the + /, which is required in this case. + + pg_dumpall needs to connect several times to the PostgreSQL server (once per @@ -81,7 +86,7 @@ PostgreSQL documentation - Dump only the data, not the schema (data definitions). + Dump only the data, not the schema (data definitions) or statistics. @@ -121,38 +126,82 @@ PostgreSQL documentation Send output to the specified file. If this is omitted, the standard output is used. + Note: This option can only be omitted when is plain - + + - Specify a filename from which to read patterns for databases excluded - from the dump. The patterns are interpreted according to the same rules - as . - To read from STDIN, use - as the - filename. The option can be specified in - conjunction with for excluding - databases, and can also be specified more than once for multiple filter - files. - - - - The file lists one database pattern per row, with the following format: - -exclude database PATTERN - - - - - Lines starting with # are considered comments and - ignored. Comments can be placed after an object pattern row as well. - Blank lines are also ignored. See - for how to perform quoting in patterns. - - + Specify the format of dump files. In plain format, all the dump data is + sent in a single text stream. This is the default. + + In all other modes, pg_dumpall first creates two files: + global.dat and map.dat, in the directory + specified by . + The first file contains global data, such as roles and tablespaces. The second + contains a mapping between database oids and names. These files are used by + pg_restore. Data for individual databases is placed in + databases subdirectory, named using the database's oid. + + + + d + directory + + + Output directory-format archives for each database, + suitable for input into pg_restore. The directory + will have database oid as its name. + + + + + + p + plain + + + Output a plain-text SQL script file (the default). + + + + + + c + custom + + + Output a custom-format archive for each database, + suitable for input into pg_restore. The archive + will be named dboid.dmp where dboid is the + oid of the database. + + + + + + t + tar + + + Output a tar-format archive for each database, + suitable for input into pg_restore. The archive + will be named dboid.tar where dboid is the + oid of the database. + + + + + + + Note: see for details + of how the various non plain text archives work. + + @@ -307,7 +356,7 @@ exclude database PATTERN - This option is relevant only when creating a data-only dump. + This option is relevant only when creating a dump with data and without schema. It instructs pg_dumpall to include commands to temporarily disable triggers on the target tables while the data is restored. Use this if you have referential @@ -354,6 +403,37 @@ exclude database PATTERN + + + + + Specify a filename from which to read patterns for databases excluded + from the dump. The patterns are interpreted according to the same rules + as . + To read from STDIN, use - as the + filename. The option can be specified in + conjunction with for excluding + databases, and can also be specified more than once for multiple filter + files. + + + + The file lists one database pattern per row, with the following format: + +exclude database PATTERN + + + + + Lines starting with # are considered comments and + ignored. Comments can be placed after an object pattern row as well. + Blank lines are also ignored. See + for how to perform quoting in patterns. + + + + + @@ -417,7 +497,25 @@ exclude database PATTERN - Do not dump comments. + Do not dump COMMENT commands. + + + + + + + + + Do not dump data. + + + + + + + + + Do not dump row security policies. @@ -447,6 +545,15 @@ exclude database PATTERN + + + + + Do not dump schema (data definitions). + + + + @@ -456,6 +563,15 @@ exclude database PATTERN + + + + + Do not dump statistics. This is the default. + + + + @@ -569,6 +685,28 @@ exclude database PATTERN + + + + + Dump only the statistics, not the schema (data definitions) or data. + Statistics for tables, materialized views, foreign tables, + and indexes are dumped. + + + + + + + + + Include sequence data in the dump. This is the default behavior except + when , , or + is specified. + + + + @@ -582,6 +720,33 @@ exclude database PATTERN + + + + + Dump data. This is the default. + + + + + + + + + Dump schema (data definitions). This is the default. + + + + + + + + + Dump statistics. + + + + @@ -793,10 +958,14 @@ exclude database PATTERN - Once restored, it is wise to run ANALYZE on each - database so the optimizer has useful statistics. You - can also run vacuumdb -a -z to analyze all - databases. + If is specified, + pg_dumpall will include most optimizer statistics in the + resulting dump file. However, some statistics may not be included, such as + those created explicitly with or + custom statistics added by an extension. Therefore, it may be useful to + run ANALYZE on each database after restoring from a dump + file to ensure optimal performance. You can also run vacuumdb -a + -z to analyze all databases. @@ -817,6 +986,17 @@ exclude database PATTERN database creation will fail for databases in non-default locations. + + + It is generally recommended to use the + () option when restoring a database from a + pg_dumpall script to ensure a clean restore + process and prevent potential conflicts with non-default + psql configurations. Additionally, because + the pg_dumpall script may + include psql meta-commands, it may be + incompatible with clients other than psql. + @@ -833,9 +1013,9 @@ exclude database PATTERN To restore database(s) from this file, you can use: -$ psql -f db.out postgres +$ psql -X -f db.out -d postgres - It is not important to which database you connect here since the + It is not important which database you connect to here since the script file created by pg_dumpall will contain the appropriate commands to create and connect to the saved databases. An exception is that if you specified , diff --git a/doc/src/sgml/ref/pg_receivewal.sgml b/doc/src/sgml/ref/pg_receivewal.sgml index 8944eee2a3649..9e353a068e5a3 100644 --- a/doc/src/sgml/ref/pg_receivewal.sgml +++ b/doc/src/sgml/ref/pg_receivewal.sgml @@ -315,13 +315,16 @@ PostgreSQL documentation will override any conflicting command line options. - The option is called --dbname for consistency with other + This option is called --dbname for consistency with other client applications, but because pg_receivewal doesn't connect to any particular database in the cluster, any database - name in the connection string will be ignored by - PostgreSQL. Middleware, or proxies, used in - connecting to PostgreSQL might however - utilize the value. + name included in the connection string will be ignored by the server. + However, a database name supplied that way overrides the default + database name (replication) for purposes of + looking up the replication connection's password + in ~/.pgpass. Similarly, middleware or proxies + used in connecting to PostgreSQL might + utilize the name for purposes such as connection routing. diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml index 95eb14b6352e2..63a45c7018a45 100644 --- a/doc/src/sgml/ref/pg_recvlogical.sgml +++ b/doc/src/sgml/ref/pg_recvlogical.sgml @@ -74,8 +74,13 @@ PostgreSQL documentation - The can be specified with - to enable decoding of prepared transactions. + The and are required + for this action. + + + + The and options + can be specified with . @@ -87,6 +92,10 @@ PostgreSQL documentation Drop the replication slot with the name specified by , then exit. + + + The is required for this action. + @@ -101,6 +110,11 @@ PostgreSQL documentation is specified. + + The and , + are required for this action. + + The stream format is determined by the output plugin specified when the slot was created. @@ -151,6 +165,16 @@ PostgreSQL documentation + + + + + Enables the slot to be synchronized to the standbys. This option may + only be specified with . + + + + @@ -159,6 +183,9 @@ PostgreSQL documentation Write received and decoded transaction data into this file. Use - for stdout. + + This parameter is required for . + @@ -265,6 +292,9 @@ PostgreSQL documentation mode, create the slot with this name. In mode, delete the slot with this name. + + This parameter is required for any of actions. + @@ -305,7 +335,11 @@ PostgreSQL documentation The dbname can be a connection string. If so, connection string parameters will override any conflicting - command line options. Defaults to the user name. + command line options. + + + This parameter is required for + and . diff --git a/doc/src/sgml/ref/pg_resetwal.sgml b/doc/src/sgml/ref/pg_resetwal.sgml index cf9c7e70f2712..2c019c2aac6eb 100644 --- a/doc/src/sgml/ref/pg_resetwal.sgml +++ b/doc/src/sgml/ref/pg_resetwal.sgml @@ -313,34 +313,6 @@ PostgreSQL documentation - - - - - Set the new WAL segment size, in megabytes. The value must be set to a - power of 2 between 1 and 1024 (megabytes). See the same option of for more information. - - - - This option can also be used to change the WAL segment size of an - existing database cluster, avoiding the need to - re-initdb. - - - - - While pg_resetwal will set the WAL starting address - beyond the latest existing WAL segment file, some segment size changes - can cause previous WAL file names to be reused. It is recommended to - use together with this option to manually set the - WAL starting address if WAL file name overlap will cause problems with - your archiving strategy. - - - - - @@ -383,6 +355,53 @@ PostgreSQL documentation + + + + + + Manually set the default char signedness. Possible values are + signed and unsigned. + + + For a database cluster that pg_upgrade upgraded from + a PostgreSQL version before 18, the safe + value would be the default char signedness of the platform + that ran the cluster before that upgrade. For all other + clusters, signed would be the safe value. However, + this option is exclusively for use with pg_upgrade + and should not normally be used manually. + + + + + + + + + Set the new WAL segment size, in megabytes. The value must be set to a + power of 2 between 1 and 1024 (megabytes). See the same option of for more information. + + + + This option can also be used to change the WAL segment size of an + existing database cluster, avoiding the need to + re-initdb. + + + + + While pg_resetwal will set the WAL starting address + beyond the latest existing WAL segment file, some segment size changes + can cause previous WAL file names to be reused. It is recommended to + use together with this option to manually set the + WAL starting address if WAL file name overlap will cause problems with + your archiving strategy. + + + + diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 2e3ba80258177..8c88b07dcc865 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -18,8 +18,9 @@ PostgreSQL documentation pg_restore - restore a PostgreSQL database from an - archive file created by pg_dump + restore a PostgreSQL database or cluster + from an archive created by pg_dump or + pg_dumpall @@ -38,13 +39,14 @@ PostgreSQL documentation pg_restore is a utility for restoring a - PostgreSQL database from an archive - created by in one of the non-plain-text + PostgreSQL database or cluster from an archive + created by or + in one of the non-plain-text formats. It will issue the commands necessary to reconstruct the - database to the state it was in at the time it was saved. The - archive files also allow pg_restore to + database or cluster to the state it was in at the time it was saved. The + archives also allow pg_restore to be selective about what is restored, or even to reorder the items - prior to being restored. The archive files are designed to be + prior to being restored. The archive formats are designed to be portable across architectures. @@ -52,10 +54,17 @@ PostgreSQL documentation pg_restore can operate in two modes. If a database name is specified, pg_restore connects to that database and restores archive contents directly into - the database. Otherwise, a script containing the SQL - commands necessary to rebuild the database is created and written + the database. + When restoring from a dump made by pg_dumpall, + each database will be created and then the restoration will be run in that + database. + + Otherwise, when a database name is not specified, a script containing the SQL + commands necessary to rebuild the database or cluster is created and written to a file or standard output. This script output is equivalent to - the plain text output format of pg_dump. + the plain text output format of pg_dump or + pg_dumpall. + Some of the options controlling the output are therefore analogous to pg_dump options. @@ -94,7 +103,7 @@ PostgreSQL documentation - Restore only the data, not the schema (data definitions). + Restore only the data, not the schema (data definitions) or statistics. Table data, large objects, and sequence values are restored, if present in the archive. @@ -140,6 +149,8 @@ PostgreSQL documentation commands that mention this database. Access privileges for the database itself are also restored, unless is specified. + is required when restoring multiple databases + from an archive created by pg_dumpall. @@ -190,86 +201,6 @@ PostgreSQL documentation - - - - - Specify a filename from which to read patterns for objects excluded - or included from restore. The patterns are interpreted according to the - same rules as - / for including objects in schemas, - /for excluding objects in schemas, - / for restoring named functions, - / for restoring named indexes, - / for restoring named tables - or / for restoring triggers. - To read from STDIN, use - as the - filename. The option can be specified in - conjunction with the above listed options for including or excluding - objects, and can also be specified more than once for multiple filter - files. - - - - The file lists one database pattern per row, with the following format: - -{ include | exclude } { function | index | schema | table | trigger } PATTERN - - - - - The first keyword specifies whether the objects matched by the pattern - are to be included or excluded. The second keyword specifies the type - of object to be filtered using the pattern: - - - - function: functions, works like the - / option. This keyword - can only be used with the include keyword. - - - - - index: indexes, works like the - / option. This keyword - can only be used with the include keyword. - - - - - schema: schemas, works like the - / and - / options. - - - - - table: tables, works like the - / option. This keyword - can only be used with the include keyword. - - - - - trigger: triggers, works like the - / option. This keyword - can only be used with the include keyword. - - - - - - - Lines starting with # are considered comments and - ignored. Comments can be placed after an object pattern row as well. - Blank lines are also ignored. See - for how to perform quoting in patterns. - - - - - @@ -315,6 +246,19 @@ PostgreSQL documentation + + + + + + Restore only global objects (roles and tablespaces), no databases. + + + This option is only relevant when restoring from an archive made using pg_dumpall. + + + + @@ -483,10 +427,11 @@ PostgreSQL documentation to the extent that schema entries are present in the archive. - This option is the inverse of . + This option cannot be used with + or . It is similar to, but for historical reasons not identical to, specifying - . + . (Do not confuse this with the option, which @@ -617,7 +562,7 @@ PostgreSQL documentation - This option is relevant only when performing a data-only restore. + This option is relevant only when performing a restore without schema. It instructs pg_restore to execute commands to temporarily disable triggers on the target tables while the data is restored. Use this if you have referential @@ -658,6 +603,108 @@ PostgreSQL documentation + + + + + Do not restore databases whose name matches + pattern. + Multiple patterns can be excluded by writing multiple + switches. The + pattern parameter is + interpreted as a pattern according to the same rules used by + psql's \d + commands (see ), + so multiple databases can also be excluded by writing wildcard + characters in the pattern. When using wildcards, be careful to + quote the pattern if needed to prevent shell wildcard expansion. + + + This option is only relevant when restoring from an archive made using pg_dumpall. + + + + + + + + + Specify a filename from which to read patterns for objects excluded + or included from restore. The patterns are interpreted according to the + same rules as + / for including objects in schemas, + / for excluding objects in schemas, + / for restoring named functions, + / for restoring named indexes, + / for restoring named tables + or / for restoring triggers. + To read from STDIN, use - as the + filename. The option can be specified in + conjunction with the above listed options for including or excluding + objects, and can also be specified more than once for multiple filter + files. + + + + The file lists one database pattern per row, with the following format: + +{ include | exclude } { function | index | schema | table | trigger } PATTERN + + + + + The first keyword specifies whether the objects matched by the pattern + are to be included or excluded. The second keyword specifies the type + of object to be filtered using the pattern: + + + + function: functions, works like the + / option. This keyword + can only be used with the include keyword. + + + + + index: indexes, works like the + / option. This keyword + can only be used with the include keyword. + + + + + schema: schemas, works like the + / and + / options. + + + + + table: tables, works like the + / option. This keyword + can only be used with the include keyword. + + + + + trigger: triggers, works like the + / option. This keyword + can only be used with the include keyword. + + + + + + + Lines starting with # are considered comments and + ignored. Comments can be placed after an object pattern row as well. + Blank lines are also ignored. See + for how to perform quoting in patterns. + + + + + @@ -681,6 +728,16 @@ PostgreSQL documentation + + + + + Do not output commands to restore data, even if the archive + contains them. + + + + @@ -703,6 +760,16 @@ PostgreSQL documentation + + + + + Do not output commands to restore row security policies, even if + the archive contains them. + + + + @@ -713,6 +780,16 @@ PostgreSQL documentation + + + + + Do not output commands to restore schema (data definitions), even if + the archive contains them. + + + + @@ -723,6 +800,16 @@ PostgreSQL documentation + + + + + Do not output commands to restore statistics, even if the archive + contains them. + + + + @@ -774,6 +861,15 @@ PostgreSQL documentation + + + + + Restore only the statistics, not schema (data definitions) or data. + + + + @@ -781,7 +877,7 @@ PostgreSQL documentation Require that each schema (/) and table (/) qualifier match at - least one schema/table in the backup file. + least one schema/table in the file to be restored. @@ -823,6 +919,36 @@ PostgreSQL documentation + + + + + Output commands to restore data, if the archive contains them. + This is the default. + + + + + + + + + Output commands to restore schema (data definitions), if the archive + contains them. This is the default. + + + + + + + + + Output commands to restore statistics, if the archive contains them. + This is the default. + + + + @@ -1040,10 +1166,12 @@ CREATE DATABASE foo WITH TEMPLATE template0; - Once restored, it is wise to run ANALYZE on each - restored table so the optimizer has useful statistics; see - and - for more information. + By default, pg_restore will restore optimizer statistics + if included in the dump file. If not all statistics were restored, it may + be useful to run ANALYZE on each restored table so the + optimizer has useful statistics; see and for more + information. diff --git a/doc/src/sgml/ref/pg_rewind.sgml b/doc/src/sgml/ref/pg_rewind.sgml index dc039d875665a..5485033ed8c7c 100644 --- a/doc/src/sgml/ref/pg_rewind.sgml +++ b/doc/src/sgml/ref/pg_rewind.sgml @@ -186,8 +186,10 @@ PostgreSQL documentation Create standby.signal and append connection settings to postgresql.auto.conf in the output - directory. --source-server is mandatory with - this option. + directory. The dbname will be recorded only if the dbname was + specified explicitly in the connection string or + environment variable. --source-server is + mandatory with this option. diff --git a/doc/src/sgml/ref/pg_verifybackup.sgml b/doc/src/sgml/ref/pg_verifybackup.sgml index a3f167f9f6e01..61c12975e4ad5 100644 --- a/doc/src/sgml/ref/pg_verifybackup.sgml +++ b/doc/src/sgml/ref/pg_verifybackup.sgml @@ -34,8 +34,12 @@ PostgreSQL documentation integrity of a database cluster backup taken using pg_basebackup against a backup_manifest generated by the server at the time - of the backup. The backup must be stored in the "plain" - format; a "tar" format backup can be checked after extracting it. + of the backup. The backup may be stored either in the "plain" or the "tar" + format; this includes tar-format backups compressed with any algorithm + supported by pg_basebackup. However, at present, + WAL verification is supported only for plain-format + backups. Therefore, if the backup is stored in tar-format, the + -n, --no-parse-wal option should be used. @@ -139,6 +143,45 @@ PostgreSQL documentation + + + + + + Specifies the format of the backup. format + can be one of the following: + + + + p + plain + + + Backup consists of plain files with the same layout as the + source server's data directory and tablespaces. + + + + + + t + tar + + + Backup consists of tar files, which may be compressed. A valid + backup includes the main data directory in a file named + base.tar, the WAL files in + pg_wal.tar, and separate tar files for + each tablespace, named after the tablespace's OID. If the backup + is compressed, the relevant compression extension is added to the + end of each file name. + + + + + + + diff --git a/doc/src/sgml/ref/pg_waldump.sgml b/doc/src/sgml/ref/pg_waldump.sgml index a9371e037bde5..ce23add5577ed 100644 --- a/doc/src/sgml/ref/pg_waldump.sgml +++ b/doc/src/sgml/ref/pg_waldump.sgml @@ -284,7 +284,7 @@ PostgreSQL documentation The full page images are saved with the following file name format: - TIMELINE-LSN.RELTABLESPACE.DATOID.RELNODE.BLKNOFORK + TIMELINE-LSN.RELTABLESPACE.DATOID.RELNODE.BLKNO_FORK The file names are composed of the following parts: @@ -335,8 +335,8 @@ PostgreSQL documentation FORK The name of the fork the full page image came from, such as - _main, _fsm, - _vm, or _init. + main, fsm, + vm, or init. diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index 46240e3f72599..ab252d9fc74f9 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -231,11 +231,10 @@ pgbench options d sent to the server. This uses the client/server bandwidth extensively through a COPY. pgbench uses the option - with version 14 or later - of PostgreSQL to speed up - subsequent VACUUM, except on the - pgbench_accounts table if partitions are - enabled. Using g causes logging to + to load data into ordinary (non-partition) tables with version 14 + or later of PostgreSQL to speed up + subsequent VACUUM. + Using g causes logging to print one message every 100,000 rows while generating data for all tables. @@ -909,7 +908,7 @@ pgbench options d Print messages about all errors and failures (errors without retrying) including which limit for retries was exceeded and how far it was exceeded for the serialization/deadlock failures. (Note that in this - case the output can be significantly increased.). + case the output can be significantly increased.) See for more information. diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml index 9877f2f01c691..aeeed297437e6 100644 --- a/doc/src/sgml/ref/pgupgrade.sgml +++ b/doc/src/sgml/ref/pgupgrade.sgml @@ -67,7 +67,7 @@ PostgreSQL documentation - pg_upgrade supports upgrades from 9.2.X and later to the current + pg_upgrade supports upgrades from 9.2.X and later to the current major release of PostgreSQL, including snapshot and beta releases. @@ -118,7 +118,7 @@ PostgreSQL documentation - number of simultaneous processes or threads to use + number of simultaneous connections and processes/threads to use @@ -235,7 +235,8 @@ PostgreSQL documentation Copy files to the new cluster. This is the default. (See also - and .) + , , + , and .) @@ -253,6 +254,94 @@ PostgreSQL documentation + + + + + Do not restore statistics from the old cluster into the new cluster. + + + + + + option + + + Manually set the default char signedness of new clusters. Possible values + are signed and unsigned. + + + In the C language, the default signedness of the char type + (when not explicitly specified) varies across platforms. For example, + char defaults to signed char on x86 CPUs but + to unsigned char on ARM CPUs. + + + Starting from PostgreSQL 18, database clusters + maintain their own default char signedness setting, which can be used to + ensure consistent behavior across platforms with different default char + signedness. By default, pg_upgrade preserves + the char signedness setting when upgrading from an existing cluster. + However, when upgrading from PostgreSQL 17 or + earlier, pg_upgrade adopts the char signedness + of the platform on which it was built. + + + This option allows you to explicitly set the default char signedness for + the new cluster, overriding any inherited values. There are two specific + scenarios where this option is relevant: + + + + If you are planning to migrate to a different platform after the upgrade, + you should not use this option. The default behavior is right in this case. + Instead, perform the upgrade on the original platform without this flag, + and then migrate the cluster afterward. This is the recommended and safest + approach. + + + + + If you have already migrated the cluster to a platform with different + char signedness (for example, from an x86-based system to an ARM-based + system), you should use this option to specify the signedness matching + the original platform's default char signedness. Additionally, it's + essential not to modify any data files between migrating data files and + running pg_upgrade. pg_upgrade + should be the first operation that starts the cluster on the new platform. + + + + + + + + + + + + Move the data directories from the old cluster to the new cluster. + Then, replace the catalog files with those generated for the new + cluster. This mode can outperform , + , , and + , especially on clusters with many + relations. + + + However, this mode creates many garbage files in the old cluster, which + can prolong the file synchronization step if + is used. Therefore, it is + recommended to use with + . + + + Additionally, once the file transfer step begins, the old cluster will + be destructively modified and therefore will no longer be safe to + start. See for details. + + + + method @@ -295,6 +384,14 @@ PostgreSQL documentation with pg_upgrade: + + + The steps to upgrade logical replication clusters + are not covered here; + refer to for details. + + + Optionally move the old cluster @@ -396,129 +493,6 @@ make prefix=/usr/local/pgsql.new install - - Prepare for publisher upgrades - - - pg_upgrade attempts to migrate logical - slots. This helps avoid the need for manually defining the same - logical slots on the new publisher. Migration of logical slots is - only supported when the old cluster is version 17.0 or later. - Logical slots on clusters before version 17.0 will silently be - ignored. - - - - Before you start upgrading the publisher cluster, ensure that the - subscription is temporarily disabled, by executing - ALTER SUBSCRIPTION ... DISABLE. - Re-enable the subscription after the upgrade. - - - - There are some prerequisites for pg_upgrade to - be able to upgrade the logical slots. If these are not met an error - will be reported. - - - - - - The new cluster must have - wal_level as - logical. - - - - - The new cluster must have - max_replication_slots - configured to a value greater than or equal to the number of slots - present in the old cluster. - - - - - The output plugins referenced by the slots on the old cluster must be - installed in the new PostgreSQL executable directory. - - - - - The old cluster has replicated all the transactions and logical decoding - messages to subscribers. - - - - - All slots on the old cluster must be usable, i.e., there are no slots - whose - pg_replication_slots.conflicting - is not true. - - - - - The new cluster must not have permanent logical slots, i.e., - there must be no slots where - pg_replication_slots.temporary - is false. - - - - - - - - Prepare for subscriber upgrades - - - Setup the - subscriber configurations in the new subscriber. - pg_upgrade attempts to migrate subscription - dependencies which includes the subscription's table information present in - pg_subscription_rel - system catalog and also the subscription's replication origin. This allows - logical replication on the new subscriber to continue from where the - old subscriber was up to. Migration of subscription dependencies is only - supported when the old cluster is version 17.0 or later. Subscription - dependencies on clusters before version 17.0 will silently be ignored. - - - - There are some prerequisites for pg_upgrade to - be able to upgrade the subscriptions. If these are not met an error - will be reported. - - - - - - All the subscription tables in the old subscriber should be in state - i (initialize) or r (ready). This - can be verified by checking pg_subscription_rel.srsubstate. - - - - - The replication origin entry corresponding to each of the subscriptions - should exist in the old cluster. This can be found by checking - pg_subscription and - pg_replication_origin - system tables. - - - - - The new cluster must have - max_replication_slots - configured to a value greater than or equal to the number of - subscriptions present in the old cluster. - - - - - Stop both servers @@ -566,7 +540,7 @@ NET STOP postgresql-&majorversion; Always run the pg_upgrade binary of the new server, not the old one. pg_upgrade requires the specification of the old and new cluster's data and executable (bin) directories. You can also specify - user and port values, and whether you want the data files linked or cloned + user and port values, and whether you want the data files linked, cloned, or swapped instead of the default copy behavior. @@ -583,15 +557,18 @@ NET STOP postgresql-&majorversion; is started. Clone mode also requires that the old and new data directories be in the same file system. This mode is only available on certain operating systems and file systems. + Swap mode may be the fastest if there are many relations, but you will not + be able to access your old cluster once the file transfer step begins. + Swap mode also requires that the old and new cluster data directories be + in the same file system. - The option allows multiple CPU cores to be used - for copying/linking of files and to dump and restore database schemas - in parallel; a good place to start is the maximum of the number of - CPU cores and tablespaces. This option can dramatically reduce the - time to upgrade a multi-database server running on a multiprocessor - machine. + Setting to 2 or higher allows pg_upgrade to + process multiple databases and tablespaces in parallel. A good starting + point is the number of CPU cores on the machine. This option can + substantially reduce the upgrade time for multi-database and + multi-tablespace servers. @@ -612,8 +589,9 @@ pg_upgrade.exe to perform only the checks, even if the old server is still running. pg_upgrade --check will also outline any manual adjustments you will need to make after the upgrade. If you - are going to be using link or clone mode, you should use the option - or with + are going to be using link, clone, copy-file-range, or swap mode, you + should use the option , , + , or with to enable mode-specific checks. pg_upgrade requires write permission in the current directory. @@ -845,17 +823,29 @@ psql --username=postgres --file=script.sql postgres Statistics - Because optimizer statistics are not transferred by pg_upgrade, you will - be instructed to run a command to regenerate that information at the end - of the upgrade. You might need to set connection parameters to - match your new cluster. + Unless the option is specified, + pg_upgrade will transfer most optimizer statistics + from the old cluster to the new cluster. However, some statistics may + not be transferred, such as those created explicitly with or custom statistics added by an + extension. - Using vacuumdb --all --analyze-only can efficiently - generate such statistics, and the use of - can speed it up. Option - can be used to generate minimal statistics quickly. + Because not all statistics are transferred by + pg_upgrade, you will be instructed to run commands to + regenerate that information at the end of the upgrade. You might need to + set connection parameters to match your new cluster. + + + + First, use + vacuumdb --all --analyze-in-stages --missing-stats-only + to quickly generate minimal optimizer statistics for relations without + any. Then, use vacuumdb --all --analyze-only to ensure + all relations have updated cumulative statistics for triggering vacuum and + analyze. For both commands, the use of can speed + it up. If vacuum_cost_delay is set to a non-zero value, this can be overridden to speed up statistics generation using PGOPTIONS, e.g., PGOPTIONS='-c @@ -893,7 +883,7 @@ psql --username=postgres --file=script.sql postgres - If the option was not + If neither nor was used, the old cluster was unmodified; it can be restarted. @@ -933,6 +923,32 @@ psql --username=postgres --file=script.sql postgres + + + + If the option was used, the old cluster might + be destructively modified: + + + + + If pg_upgrade aborts before reporting that the + old cluster is no longer safe to start, the old cluster was + unmodified; it can be restarted. + + + + + + If pg_upgrade has reported that the old cluster + is no longer safe to start, the old cluster was destructively + modified. The old cluster will need to be restored from backup in + this case. + + + + + diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 07419a3b92e4e..570ef21d1fce3 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -864,6 +864,13 @@ testdb=> same line. + + Many of the meta-commands also allow x to be appended + as an option. This will cause the results to be displayed in expanded + mode, as if \x or \pset expanded + had been used. + + The following meta-commands are defined: @@ -917,6 +924,36 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g + + \bind_named statement_name [ parameter ] ... + + + + \bind_named is equivalent to \bind, + except that it takes the name of an existing prepared statement as + first parameter. An empty string denotes the unnamed prepared + statement. + + + + Example: + +INSERT INTO tbls1 VALUES ($1, $2) \parse stmt1 +\bind_named stmt1 'first value' 'second value' \g + + + + + This command causes the extended query protocol (see + ) to be used, unlike normal + psql operation, which uses the simple + query protocol. So this command can be useful to test the extended + query protocol from psql. + + + + + \c or \connect [ -reuse-previous=on|off ] [ dbname [ username ] [ host ] [ port ] | conninfo ] @@ -1018,7 +1055,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g Changes the current working directory to directory. Without argument, changes - to the current user's home directory. + to the current user's home directory. For details on how home + directories are found, see . @@ -1029,12 +1067,51 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g + + \close prepared_statement_name + + + + Closes the specified prepared statement. An empty string denotes the + unnamed prepared statement. If no prepared statement exists with this + name, the operation is a no-op. + + + + Example: + +SELECT $1 \parse stmt1 +\close stmt1 + + + + + This command causes the extended query protocol to be used, + unlike normal psql operation, which + uses the simple query protocol. So this command can be useful + to test the extended query protocol from + psql. + + + + + \conninfo - - Outputs information about the current database connection. - + + Outputs information about the current database connection, + including SSL-related information if SSL is in use. + + + Note that the Client User field shows + the user at the time of connection, while the + Superuser field indicates whether + the current user (in the current execution context) has + superuser privileges. These users are usually the same, but they can + differ, for example, if the current user was changed with the + SET ROLE command. + @@ -1076,7 +1153,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g For \copy ... from stdin, data rows are read from the same - source that issued the command, continuing until \. + source that issued the command, continuing until a line containing + only \. is read or the stream reaches EOF. This option is useful for populating tables in-line within an SQL script file. For \copy ... to stdout, output is sent to the same place @@ -1120,10 +1198,6 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g destination, because all data must pass through the client/server connection. For large amounts of data the SQL command might be preferable. - Also, because of this pass-through method, \copy - ... from in CSV mode will erroneously - treat a \. data value alone on a line as an - end-of-input marker. @@ -1215,7 +1289,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \d[S+] [ pattern ] + \d[Sx+] [ pattern ] @@ -1264,12 +1338,24 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g foreign tables. This is purely a convenience measure. + + As with many other commands, if x is appended to + the command name, the results are displayed in expanded mode, but note + that this only applies when \d is used without a + pattern argument, and + the x modifier cannot appear immediately after the + \d (because \dx is a different + command); the x modifier may only appear after an + S or + modifier. For example, + \d+x is equivalent to \dtvmsE+x + and will show a list of all relations in expanded mode. + - \da[S] [ pattern ] + \da[Sx] [ pattern ] @@ -1280,19 +1366,23 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. - \dA[+] [ pattern ] + \dA[x+] [ pattern ] Lists access methods. If pattern is specified, only access - methods whose names match the pattern are shown. If - + is appended to the command name, each access + methods whose names match the pattern are shown. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, each access method is listed with its associated handler function and description. @@ -1300,7 +1390,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dAc[+] + \dAc[x+] [access-method-pattern [input-type-pattern]] @@ -1315,6 +1405,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g If input-type-pattern is specified, only operator classes associated with input types whose names match that pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each operator class is listed with its associated operator family and owner. @@ -1323,7 +1415,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dAf[+] + \dAf[x+] [access-method-pattern [input-type-pattern]] @@ -1338,6 +1430,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g If input-type-pattern is specified, only operator families associated with input types whose names match that pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each operator family is listed with its owner. @@ -1346,7 +1440,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dAo[+] + \dAo[x+] [access-method-pattern [operator-family-pattern]] @@ -1362,15 +1456,18 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g If operator-family-pattern is specified, only members of operator families whose names match that pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each operator - is listed with its sort operator family (if it is an ordering operator). + is listed with its sort operator family (if it is an ordering operator), + and whether its underlying function is leakproof. - \dAp[+] + \dAp[x+] [access-method-pattern [operator-family-pattern]] @@ -1385,6 +1482,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g If operator-family-pattern is specified, only functions of operator families whose names match that pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, functions are displayed verbosely, with their actual parameter lists. @@ -1392,13 +1491,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \db[+] [ pattern ] + \db[x+] [ pattern ] Lists tablespaces. If pattern is specified, only tablespaces whose names match the pattern are shown. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each tablespace is listed with its associated options, on-disk size, permissions and description. @@ -1408,7 +1509,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dc[S+] [ pattern ] + \dc[Sx+] [ pattern ] Lists conversions between character-set encodings. @@ -1418,6 +1519,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each object is listed with its associated description. @@ -1426,7 +1529,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dconfig[+] [ pattern ] + \dconfig[x+] [ pattern ] Lists server configuration parameters and their values. @@ -1435,6 +1538,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g a pattern, only parameters that are set to non-default values are listed. (Use \dconfig * to see all parameters.) + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each parameter is listed with its data type, context in which the parameter can be set, and access privileges (if non-default access @@ -1445,22 +1550,25 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dC[+] [ pattern ] + \dC[x+] [ pattern ] Lists type casts. If pattern is specified, only casts whose source or target types match the pattern are listed. - If + is appended to the command name, each object - is listed with its associated description. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional + information about each cast is shown, including whether its underlying + function is leakproof, and the cast's description. - \dd[S] [ pattern ] + \dd[Sx] [ pattern ] Shows the descriptions of objects of type constraint, @@ -1477,6 +1585,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -1489,7 +1599,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dD[S+] [ pattern ] + \dD[Sx+] [ pattern ] Lists domains. If S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each object is listed with its associated permissions and description. @@ -1506,7 +1618,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \ddp [ pattern ] + \ddp[x] [ pattern ] Lists default access privilege settings. An entry is shown for @@ -1515,6 +1627,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g If pattern is specified, only entries whose role name or schema name matches the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -1528,12 +1642,12 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dE[S+] [ pattern ] - \di[S+] [ pattern ] - \dm[S+] [ pattern ] - \ds[S+] [ pattern ] - \dt[S+] [ pattern ] - \dv[S+] [ pattern ] + \dE[Sx+] [ pattern ] + \di[Sx+] [ pattern ] + \dm[Sx+] [ pattern ] + \ds[Sx+] [ pattern ] + \dt[Sx+] [ pattern ] + \dv[Sx+] [ pattern ] @@ -1546,7 +1660,10 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g You can specify any or all of these letters, in any order, to obtain a listing of objects of these types. For example, \dti lists - tables and indexes. If + is + tables and indexes. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, each object is listed with its persistence status (permanent, temporary, or unlogged), physical size on disk, and associated description if any. @@ -1561,14 +1678,17 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \des[+] [ pattern ] + \des[x+] [ pattern ] Lists foreign servers (mnemonic: external servers). If pattern is specified, only those servers whose name matches the pattern - are listed. If the form \des+ is used, a + are listed. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, a full description of each server is shown, including the server's access privileges, type, version, options, and description. @@ -1577,14 +1697,17 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \det[+] [ pattern ] + \det[x+] [ pattern ] Lists foreign tables (mnemonic: external tables). If pattern is specified, only entries whose table name or schema name matches - the pattern are listed. If the form \det+ - is used, generic options and the foreign table description + the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, + generic options and the foreign table description are also displayed. @@ -1592,15 +1715,18 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \deu[+] [ pattern ] + \deu[x+] [ pattern ] Lists user mappings (mnemonic: external users). If pattern is specified, only those mappings whose user names match the - pattern are listed. If the form \deu+ is - used, additional information about each mapping is shown. + pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, + additional information about each mapping is shown. @@ -1615,15 +1741,18 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dew[+] [ pattern ] + \dew[x+] [ pattern ] Lists foreign-data wrappers (mnemonic: external wrappers). If pattern is specified, only those foreign-data wrappers whose name matches - the pattern are listed. If the form \dew+ - is used, the access privileges, options, and description of the + the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, + the access privileges, options, and description of the foreign-data wrapper are also shown. @@ -1631,7 +1760,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \df[anptwS+] [ pattern [ arg_pattern ... ] ] + \df[anptwSx+] [ pattern [ arg_pattern ... ] ] @@ -1652,11 +1781,13 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. - If the form \df+ is used, additional information + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional information about each function is shown, including volatility, - parallel safety, owner, security classification, access privileges, - language, internal name (for C and internal functions only), - and description. + parallel safety, owner, security classification, whether it is + leakproof, access privileges, language, internal name (for C and + internal functions only), and description. Source code for a specific function can be seen using \sf. @@ -1665,13 +1796,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dF[+] [ pattern ] + \dF[x+] [ pattern ] Lists text search configurations. If pattern is specified, only configurations whose names match the pattern are shown. - If the form \dF+ is used, a full description of + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, a full description of each configuration is shown, including the underlying text search parser and the dictionary list for each parser token type. @@ -1679,13 +1812,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dFd[+] [ pattern ] + \dFd[x+] [ pattern ] Lists text search dictionaries. If pattern is specified, only dictionaries whose names match the pattern are shown. - If the form \dFd+ is used, additional information + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional information is shown about each selected dictionary, including the underlying text search template and the option values. @@ -1693,13 +1828,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dFp[+] [ pattern ] + \dFp[x+] [ pattern ] Lists text search parsers. If pattern is specified, only parsers whose names match the pattern are shown. - If the form \dFp+ is used, a full description of + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, a full description of each parser is shown, including the underlying functions and the list of recognized token types. @@ -1707,13 +1844,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dFt[+] [ pattern ] + \dFt[x+] [ pattern ] Lists text search templates. If pattern is specified, only templates whose names match the pattern are shown. - If the form \dFt+ is used, additional information + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional information is shown about each template, including the underlying function names. @@ -1721,7 +1860,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dg[S+] [ pattern ] + \dg[Sx+] [ pattern ] Lists database roles. @@ -1732,7 +1871,9 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g S modifier to include system roles. If pattern is specified, only those roles whose names match the pattern are listed. - If the form \dg+ is used, additional information + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional information is shown about each role; currently this adds the comment for each role. @@ -1741,11 +1882,13 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dl[+] + \dl[x+] This is an alias for \lo_list, which shows a list of large objects. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each large object is listed with its associated permissions, if any. @@ -1754,7 +1897,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dL[S+] [ pattern ] + \dL[Sx+] [ pattern ] Lists procedural languages. If S modifier to include system - objects. If + is appended to the command name, each + objects. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, each language is listed with its call handler, validator, access privileges, and whether it is a system object. @@ -1771,7 +1917,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dn[S+] [ pattern ] + \dn[Sx+] [ pattern ] @@ -1780,6 +1926,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g is specified, only schemas whose names match the pattern are listed. By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each object is listed with its associated permissions and description, if any. @@ -1788,7 +1936,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \do[S+] [ pattern [ arg_pattern [ arg_pattern ] ] ] + \do[Sx+] [ pattern [ arg_pattern [ arg_pattern ] ] ] Lists operators with their operand and result types. @@ -1804,16 +1952,18 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, - additional information about each operator is shown, currently just - the name of the underlying function. + additional information about each operator is shown, including + the name of the underlying function, and whether it is leakproof. - \dO[S+] [ pattern ] + \dO[Sx+] [ pattern ] Lists collations. @@ -1821,7 +1971,10 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g specified, only collations whose names match the pattern are listed. By default, only user-created objects are shown; supply a pattern or the S modifier to - include system objects. If + is appended + include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, each collation is listed with its associated description, if any. Note that only collations usable with the current database's encoding @@ -1833,7 +1986,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dp[S] [ pattern ] + \dp[Sx] [ pattern ] Lists tables, views and sequences with their @@ -1843,6 +1996,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g pattern are listed. By default only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -1857,7 +2012,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dP[itn+] [ pattern ] + \dP[itnx+] [ pattern ] Lists partitioned relations. @@ -1877,6 +2032,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, the sum of the sizes of each relation's partitions is also displayed, along with the relation's description. @@ -1890,7 +2047,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \drds [ role-pattern [ database-pattern ] ] + \drds[x] [ role-pattern [ database-pattern ] ] Lists defined configuration settings. These settings can be @@ -1900,6 +2057,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g specific roles and databases to list, respectively. If omitted, or if * is specified, all settings are listed, including those not role-specific or database-specific, respectively. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -1913,7 +2072,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \drg[S] [ pattern ] + \drg[Sx] [ pattern ] Lists information about each granted role membership, including @@ -1927,19 +2086,23 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g S modifier to include system roles. If pattern is specified, only grants to those roles whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. - \dRp[+] [ pattern ] + \dRp[x+] [ pattern ] Lists replication publications. If pattern is specified, only those publications whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, the tables and schemas associated with each publication are shown as well. @@ -1947,13 +2110,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dRs[+] [ pattern ] + \dRs[x+] [ pattern ] Lists replication subscriptions. If pattern is specified, only those subscriptions whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, additional properties of the subscriptions are shown. @@ -1961,12 +2126,14 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dT[S+] [ pattern ] + \dT[Sx+] [ pattern ] Lists data types. If pattern is specified, only types whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each type is listed with its internal name and size, its allowed values if it is an enum type, and its associated permissions. @@ -1978,7 +2145,7 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \du[S+] [ pattern ] + \du[Sx+] [ pattern ] Lists database roles. @@ -1989,7 +2156,9 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g S modifier to include system roles. If pattern is specified, only those roles whose names match the pattern are listed. - If the form \du+ is used, additional information + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, additional information is shown about each role; currently this adds the comment for each role. @@ -1997,27 +2166,31 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dx[+] [ pattern ] + \dx[x+] [ pattern ] Lists installed extensions. If pattern is specified, only those extensions whose names match the pattern are listed. - If the form \dx+ is used, all the objects belonging + If x is appended to the command name, the results + are displayed in expanded mode. + If + is appended to the command name, all the objects belonging to each matching extension are listed. - \dX [ pattern ] + \dX[x] [ pattern ] Lists extended statistics. If pattern is specified, only those extended statistics whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -2033,13 +2206,15 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g - \dy[+] [ pattern ] + \dy[x+] [ pattern ] Lists event triggers. If pattern is specified, only those event triggers whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each object is listed with its associated description. @@ -2627,13 +2802,15 @@ SELECT - \l[+] or \list[+] [ pattern ] + \l[x+] or \list[x+] [ pattern ] List the databases in the server and show their names, owners, character set encodings, and access privileges. If pattern is specified, only databases whose names match the pattern are listed. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, database sizes, default tablespaces, and descriptions are also displayed. (Size information is only available for databases that the current @@ -2697,12 +2874,14 @@ lo_import 152801 - \lo_list[+] + \lo_list[x+] Shows a list of all PostgreSQL large objects currently stored in the database, along with any comments provided for them. + If x is appended to the command name, the results + are displayed in expanded mode. If + is appended to the command name, each large object is listed with its associated permissions, if any. @@ -2780,6 +2959,37 @@ lo_import 152801 + + \parse statement_name + + + Creates a prepared statement from the current query buffer, based on + the name of a destination prepared-statement object. An empty string + denotes the unnamed prepared statement. + + + + Example: + +SELECT $1 \parse stmt1 + + + + + This command causes the extended query protocol to be used, unlike + normal psql operation, which uses the + simple query protocol. A + + message will be issued by this command so it can be useful to + test the extended query protocol from + psql. This command affects only the next + query executed; all subsequent queries will use the simple query + protocol by default. + + + + + \password [ username ] @@ -3474,6 +3684,83 @@ testdb=> \setenv LESS -imx4F + + \startpipeline + \sendpipeline + \syncpipeline + \endpipeline + \flushrequest + \flush + \getresults [ number_results ] + + + + This group of commands implements pipelining of SQL statements. + A pipeline must begin with a \startpipeline + and end with an \endpipeline. In between there + may be any number of \syncpipeline commands, + which sends a sync message + without ending the ongoing pipeline and flushing the send buffer. + In pipeline mode, statements are sent to the server without waiting + for the results of previous statements. + See for more details. + + + + All queries executed while a pipeline is ongoing use the extended + query protocol. Queries are appended to the pipeline when ending with + a semicolon. The meta-commands \bind, + \bind_named, \close or + \parse can be used in an ongoing pipeline. While + a pipeline is ongoing, \sendpipeline will append + the current query buffer to the pipeline. Other meta-commands like + \g, \gx or + \gdesc are not allowed in pipeline mode. + + + + \flushrequest appends a flush command to the + pipeline, allowing to read results with + \getresults without issuing a sync or ending the + pipeline. \getresults will automatically push + unsent data to the server. \flush can be used to + manually push unsent data. + + + + \getresults accepts an optional + number_results parameter. + If provided, only the first + number_results pending + results will be read. If not provided or 0, all + pending results are read. + + + + When pipeline mode is active, a dedicated prompt variable is available + to report the pipeline status. + See for more details + + + + COPY is not supported while in pipeline mode. + + + + Example: + +\startpipeline +SELECT * FROM pg_class; +SELECT 1 \bind \sendpipeline +\flushrequest +\getresults +\endpipeline + + + + + + \t @@ -3578,6 +3865,8 @@ testdb=> \setenv LESS -imx4F until interrupted, or the query fails, or the execution count limit (if given) is reached, or the query no longer returns the minimum number of rows. Wait the specified number of seconds (default 2) between executions. + The default wait can be changed with the variable + . For backwards compatibility, seconds can be specified with or without an interval= prefix. @@ -3605,7 +3894,7 @@ testdb=> \setenv LESS -imx4F - \z[S] [ pattern ] + \z[Sx] [ pattern ] Lists tables, views and sequences with their @@ -3615,6 +3904,8 @@ testdb=> \setenv LESS -imx4F pattern are listed. By default only user-created objects are shown; supply a pattern or the S modifier to include system objects. + If x is appended to the command name, the results + are displayed in expanded mode. @@ -4232,6 +4523,37 @@ bar + + PIPELINE_COMMAND_COUNT + + + The number of commands queued in an ongoing pipeline. + + + + + + PIPELINE_RESULT_COUNT + + + The number of commands of an ongoing pipeline that were followed + by either a \flushrequest or a + \syncpipeline, forcing the server to send the + results. These results can be retrieved with + \getresults. + + + + + + PIPELINE_SYNC_COUNT + + + The number of sync messages queued in an ongoing pipeline. + + + + PORT @@ -4292,6 +4614,15 @@ bar + + SERVICE + + + The service name, if applicable. + + + + SHELL_ERROR @@ -4430,6 +4761,18 @@ bar + + WATCH_INTERVAL + + + This variable sets the default interval, in seconds, which + \watch waits between executing the query. The + default is 2 seconds. Specifying an interval in the command overrides + this variable. + + + + @@ -4586,6 +4929,11 @@ testdb=> INSERT INTO my_table VALUES (:'content'); + + %s + The name of the service. + + %/ The name of the current database. @@ -4617,6 +4965,17 @@ testdb=> INSERT INTO my_table VALUES (:'content'); + + %P + + + Pipeline status: off when not in a pipeline, + on when in an ongoing pipeline or + abort when in an aborted pipeline. + + + + %R @@ -5284,6 +5643,31 @@ testdb=> \df int*pl * bigint + + Here, the + option is used to display additional + information about one of these functions, and x is used + to display the results in expanded mode: + +testdb=> \df+x int*pl integer bigint +List of functions +-[ RECORD 1 ]-------+----------------------------- +Schema | pg_catalog +Name | int48pl +Result data type | bigint +Argument data types | integer, bigint +Type | func +Volatility | immutable +Parallel | safe +Owner | postgres +Security | invoker +Leakproof? | no +Access privileges | +Language | internal +Internal name | int48pl +Description | implementation of + operator + + + When suitable, query results can be shown in a crosstab representation with the \crosstabview command: diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index dcf70d14bc360..c405539714695 100644 --- a/doc/src/sgml/ref/reindex.sgml +++ b/doc/src/sgml/ref/reindex.sgml @@ -194,7 +194,8 @@ REINDEX [ ( option [, ...] ) ] { DA VERBOSE - Prints a progress report as each index is reindexed. + Prints a progress report as each index is reindexed + at INFO level. @@ -464,14 +465,17 @@ Indexes: If the index marked INVALID is suffixed - ccnew, then it corresponds to the transient + _ccnew, then it corresponds to the transient index created during the concurrent operation, and the recommended recovery method is to drop it using DROP INDEX, then attempt REINDEX CONCURRENTLY again. - If the invalid index is instead suffixed ccold, + If the invalid index is instead suffixed _ccold, it corresponds to the original index which could not be dropped; the recommended recovery method is to just drop said index, since the rebuild proper has been successful. + A nonzero number may be appended to the suffix of the invalid index + names to keep them unique, like _ccnew1, + _ccold2, etc. diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml index 98c3333228fb9..abcb041179bb9 100644 --- a/doc/src/sgml/ref/reindexdb.sgml +++ b/doc/src/sgml/ref/reindexdb.sgml @@ -352,9 +352,8 @@ PostgreSQL documentation - Specifies the name of the database to connect to to discover which - databases should be reindexed, - when / is used. + When the / is used, connect + to this database to gather the list of databases to reindex. If not specified, the postgres database will be used, or if that does not exist, template1 will be used. This can be a connection diff --git a/doc/src/sgml/ref/security_label.sgml b/doc/src/sgml/ref/security_label.sgml index e5e5fb483e94e..aa45c0af2487b 100644 --- a/doc/src/sgml/ref/security_label.sgml +++ b/doc/src/sgml/ref/security_label.sgml @@ -84,6 +84,10 @@ SECURITY LABEL [ FOR provider ] ON based on object labels, rather than traditional discretionary access control (DAC) concepts such as users and groups. + + + You must own the database object to use SECURITY LABEL. + diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml index 5459b29525969..2218f54682ec3 100644 --- a/doc/src/sgml/ref/set.sgml +++ b/doc/src/sgml/ref/set.sgml @@ -165,7 +165,7 @@ SET [ SESSION | LOCAL ] TIME ZONE { value NAMES - SET NAMES value is an alias for + SET NAMES 'value' is an alias for SET client_encoding TO value. @@ -200,7 +200,7 @@ SELECT setseed(value); - 'PST8PDT' + 'America/Los_Angeles' The time zone for Berkeley, California. @@ -298,7 +298,7 @@ SET datestyle TO postgres, dmy; Set the time zone for Berkeley, California: -SET TIME ZONE 'PST8PDT'; +SET TIME ZONE 'America/Los_Angeles'; diff --git a/doc/src/sgml/ref/show.sgml b/doc/src/sgml/ref/show.sgml index b3747b119f9d2..5fbb5bbe013e3 100644 --- a/doc/src/sgml/ref/show.sgml +++ b/doc/src/sgml/ref/show.sgml @@ -77,30 +77,6 @@ SHOW ALL - - LC_COLLATE - - - Shows the database's locale setting for collation (text - ordering). At present, this parameter can be shown but not - set, because the setting is determined at database creation - time. - - - - - - LC_CTYPE - - - Shows the database's locale setting for character - classification. At present, this parameter can be shown but - not set, because the setting is determined at database creation - time. - - - - IS_SUPERUSER diff --git a/doc/src/sgml/ref/update.sgml b/doc/src/sgml/ref/update.sgml index 1c433bec2bb8e..12ec5ba070939 100644 --- a/doc/src/sgml/ref/update.sgml +++ b/doc/src/sgml/ref/update.sgml @@ -29,7 +29,8 @@ UPDATE [ ONLY ] table_name [ * ] [ } [, ...] [ FROM from_item [, ...] ] [ WHERE condition | WHERE CURRENT OF cursor_name ] - [ RETURNING { * | output_expression [ [ AS ] output_name ] } [, ...] ] + [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ] + { * | output_expression [ [ AS ] output_name ] } [, ...] ] @@ -211,6 +212,26 @@ UPDATE [ ONLY ] table_name [ * ] [ + + output_alias + + + An optional substitute name for OLD or + NEW rows in the RETURNING list. + + + + By default, old values from the target table can be returned by writing + OLD.column_name + or OLD.*, and new values can be returned by writing + NEW.column_name + or NEW.*. When an alias is provided, these names are + hidden and the old or new rows must be referred to using the alias. + For example RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*. + + + + output_expression @@ -221,6 +242,16 @@ UPDATE [ ONLY ] table_name [ * ] [ or table(s) listed in FROM. Write * to return all columns. + + + A column name or * may be qualified using + OLD or NEW, or the corresponding + output_alias for + OLD or NEW, to cause old or new + values to be returned. An unqualified column name, or + *, or a column name or * qualified + using the target table name or alias will return new values. + @@ -348,12 +379,13 @@ UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT - Perform the same operation and return the updated entries: + Perform the same operation and return the updated entries, and the old + precipitation value: UPDATE weather SET temp_lo = temp_lo+1, temp_hi = temp_lo+15, prcp = DEFAULT WHERE city = 'San Francisco' AND date = '2003-07-03' - RETURNING temp_lo, temp_hi, prcp; + RETURNING temp_lo, temp_hi, prcp, old.prcp AS old_prcp; diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 9857b35627b3e..bd5dcaf86a5cc 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -42,7 +42,7 @@ VACUUM [ ( option [, ...] ) ] [ and table_and_columns is: - table_name [ ( column_name [, ...] ) ] + [ ONLY ] table_name [ * ] [ ( column_name [, ...] ) ] @@ -129,7 +129,8 @@ VACUUM [ ( option [, ...] ) ] [ VERBOSE - Prints a detailed vacuum activity report for each table. + Prints a detailed vacuum activity report for each table + at INFO level. @@ -264,7 +265,8 @@ VACUUM [ ( option [, ...] ) ] [ vacuum_truncate + and is the default unless + is set to false or the vacuum_truncate option has been set to false for the table to be vacuumed. Setting this option to false may be useful to avoid ACCESS EXCLUSIVE lock on the table that @@ -401,8 +403,13 @@ VACUUM [ ( option [, ...] ) ] [ The name (optionally schema-qualified) of a specific table or - materialized view to vacuum. If the specified table is a partitioned - table, all of its leaf partitions are vacuumed. + materialized view to vacuum. If ONLY is specified + before the table name, only that table is vacuumed. If + ONLY is not specified, the table and all its + inheritance child tables or partitions (if any) are also vacuumed. + Optionally, * can be specified after the table name + to explicitly indicate that inheritance child tables (or partitions) are + to be vacuumed. diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml index 66fccb30a2d26..b0680a61814cc 100644 --- a/doc/src/sgml/ref/vacuumdb.sgml +++ b/doc/src/sgml/ref/vacuumdb.sgml @@ -277,6 +277,22 @@ PostgreSQL documentation + + + + + Only analyze relations that are missing statistics for a column, index + expression, or extended statistics object. This option prevents + vacuumdb from deleting existing statistics + so that the query optimizer's choices do not become transiently worse. + + + This option can only be used in conjunction with + or . + + + + @@ -544,9 +560,8 @@ PostgreSQL documentation - Specifies the name of the database to connect to to discover which - databases should be vacuumed, - when / is used. + When the / is used, connect + to this database to gather the list of databases to vacuum. If not specified, the postgres database will be used, or if that does not exist, template1 will be used. This can be a connection diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml index d1042e022280d..bf4ffb3057636 100644 --- a/doc/src/sgml/regress.sgml +++ b/doc/src/sgml/regress.sgml @@ -284,6 +284,17 @@ make check-world PG_TEST_EXTRA='kerberos ldap ssl load_balance libpq_encryption' + + sepgsql + + + Runs the test suite under contrib/sepgsql. This + requires an SELinux environment that is set up in a specific way; see + . + + + + ssl @@ -336,6 +347,16 @@ make check-world PG_TEST_EXTRA='kerberos ldap ssl load_balance libpq_encryption' + + + oauth + + + Runs the test suite under src/test/modules/oauth_validator. + This opens TCP/IP listen sockets for a test server running HTTPS. + + + Tests for features that are not supported by the current build @@ -576,11 +597,11 @@ make check NO_LOCALE=1 Most of the date and time results are dependent on the time zone environment. The reference files are generated for time zone - PST8PDT (Berkeley, California), and there will be + America/Los_Angeles, and there will be apparent failures if the tests are not run with that time zone setting. The regression test driver sets environment variable - PGTZ to PST8PDT, which normally - ensures proper results. + PGTZ to America/Los_Angeles, + which normally ensures proper results. diff --git a/doc/src/sgml/release-18.sgml b/doc/src/sgml/release-18.sgml index 4f027a07d1ce9..ab83b1554001e 100644 --- a/doc/src/sgml/release-18.sgml +++ b/doc/src/sgml/release-18.sgml @@ -1,16 +1,3601 @@ - - Release 18 + + Release 18 - - Release date: - 2025-??-?? - + + Release date: + 2025-??-??, CURRENT AS OF 2025-05-23 + - - This is just a placeholder for now. - + + Overview - + + PostgreSQL 18 contains many new features + and enhancements, including: + + + + + + + (to be completed) + + + + + + The above items and other new features of + PostgreSQL 18 are explained in more detail + in the sections below. + + + + + + + Migration to Version 18 + + + A dump/restore using or use of + or logical replication is required for + those wishing to migrate data from any previous release. See for general information on migrating to new + major releases. + + + + Version 18 contains a number of changes that may affect compatibility + with previous releases. Observe the following incompatibilities: + + + + + + + + +Change initdb default to enable data checksums (Greg Sabino Mullane) +§ + + + +Checksums can be disabled with the new initdb option . +pg_upgrade requires matching cluster checksum settings, so this new +option can be useful to upgrade non-checksum old clusters. + + + + + + + +Change time zone abbreviation handling (Tom Lane) +§ + + + +The system will now favor the current session's time zone abbreviations before checking the server variable timezone_abbreviations. Previously timezone_abbreviations was +checked first. + + + + + + + +Deprecate MD5 password authentication (Nathan Bossart) +§ + + + +Support for MD5 passwords will be removed in a future major version release. CREATE ROLE and ALTER ROLE now emit deprecation warnings when setting MD5 passwords. +These warnings can be disabled by setting the md5_password_warnings parameter to off. + + + + + + + +Change VACUUM and ANALYZE to process the inheritance children of a parent (Michael Harris) +§ + + + +The previous behavior can be performed by using the new ONLY option. + + + + + + + +Prevent COPY FROM from treating \. as an end-of-file marker when reading CSV files (Daniel Vérité, Tom Lane) +§ +§ + + + +psql will still treat \. as an end-of-file marker when reading CSV files from STDIN. Older psql clients connecting to PostgreSQL 18 servers might +experience \copy problems. This +release also enforces that \. must appear alone on a line. + + + + + + + +Disallow unlogged partitioned tables (Michael Paquier) +§ + + + +Previously ALTER TABLE SET [UN]LOGGED did nothing, and the creation of an unlogged partitioned table did not cause its children to be unlogged. + + + + + + + +Execute AFTER triggers as the role that was active when trigger events were queued (Laurenz Albe) +§ + + + +Previously such triggers were run as the role that was active at trigger execution time (e.g., at COMMIT). This is significant for cases where the role is changed between queue time and +transaction commit. + + + + + + + +Remove non-functional support for rule privileges in GRANT/REVOKE (Fujii Masao) +§ + + + +These have been non-functional since PostgreSQL 8.2. + + + + + + + +Remove column pg_backend_memory_contexts.parent (Melih Mutlu) +§ + + + +This is no longer needed since pg_backend_memory_contexts.path was added. + + + + + + + +Change pg_backend_memory_contexts.level and pg_log_backend_memory_contexts() to be one-based (Melih Mutlu, Atsushi Torikoshi, David Rowley, Fujii Masao) +§ +§ +§ + + + +These were previously zero-based. + + + + + + + + + Changes + + + Below you will find a detailed account of the changes between + PostgreSQL 18 and the previous major + release. + + + + Server + + + Optimizer + + + + + + + +Automatically remove some unnecessary table self-joins (Andrey Lepikhov, Alexander Kuzmenkov, Alexander Korotkov, Alena Rybakina) +§ + + + +This optimization can be disabled using server variable enable_self_join_elimination. + + + + + + + +Convert some IN (VALUES ...) to x = ANY ... for better optimizer statistics (Alena Rybakina, Andrei Lepikhov) +§ + + + + + + + +Allow transforming OR-clauses to arrays for faster index processing (Alexander Korotkov, Andrey Lepikhov) +§ + + + + + + + +Speed up the processing of INTERSECT, EXCEPT, window aggregates, and view column aliases (Tom Lane, David Rowley) +§ +§ +§ +§ + + + + + + + +Allow the keys of SELECT DISTINCT to be internally reordered to avoid sorting (Richard Guo) +§ + + + +This optimization can be disabled using enable_distinct_reordering. + + + + + + + +Ignore GROUP BY columns that are functionally dependent on other columns (Zhang Mingli, Jian He, David Rowley) +§ + + + +If a GROUP BY clause includes all columns of a unique index, as well as other columns of the same table, those other columns are redundant and can be dropped +from the grouping. This was already true for non-deferred primary keys. + + + + + + + +Allow some HAVING clauses on GROUPING SETS to be pushed to WHERE clauses (Richard Guo) +§ +§ +§ +§ + + + +This allows earlier row filtering. This release also fixes some GROUPING SETS queries that used to return incorrect results. + + + + + + + +Improve row estimates for generate_series() using numeric and timestamp values (David Rowley, Song Jinzhou) +§ +§ + + + + + + + +Allow the optimizer to use Right Semi Join plans (Richard Guo) +§ + + + +Semi-joins are used when needing to find if there is at least one match. + + + + + + + +Allow merge joins to use incremental sorts (Richard Guo) +§ + + + + + + + +Improve the efficiency of planning queries accessing many partitions (Ashutosh Bapat, Yuya Watari, David Rowley) +§ +§ + + + + + + + +Allow partitionwise joins in more cases, and reduce its memory usage (Richard Guo, Tom Lane, Ashutosh Bapat) +§ +§ + + + + + + + +Improve cost estimates of partition queries (Nikita Malakhov, Andrei Lepikhov) +§ + + + + + + + +Improve SQL-language function plan caching (Alexander Pyhalov, Tom Lane) +§ +§ + + + + + + + +Improve handling of disabled optimizer features (Robert Haas) +§ + + + + + + + + + Indexes + + + + + + + +Allow skip scans of btree indexes (Peter Geoghegan) +§ +§ + + + +This allows multi-column btree indexes to be used by queries that only +equality-reference the second or later indexed columns. + + + + + + + +Allow non-btree unique indexes to be used as partition keys and in materialized views (Mark Dilger) +§ +§ + + + +The index type must still support equality. + + + + + + + +Allow GIN indexes to be created in parallel (Tomas Vondra, Matthias van de Meent) +§ + + + + + + + +Allow values to be sorted to speed range-type GiST and btree index builds (Bernd Helmle) +§ + + + + + + + + + General Performance + + + + + + + +Add an asynchronous I/O subsystem (Andres Freund, Thomas Munro, Nazir Bilal Yavuz, Melanie Plageman) +§ +§ +§ +§ +§ +§ +§ +§ +§ +§ +§ + + + +This feature allows backends to queue multiple read requests, which allows for more efficient sequential scans, bitmap heap scans, vacuums, etc. +This is enabled by server variable io_method, with server variables io_combine_limit and io_max_combine_limit added to control it. This also enables +effective_io_concurrency and maintenance_io_concurrency values greater than zero for systems without fadvise() support. The new system view pg_aios shows the file handles being used +for asynchronous I/O. + + + + + + + +Improve the locking performance of queries that access many relations (Tomas Vondra) +§ + + + + + + + +Improve the performance and reduce memory usage of hash joins and GROUP BY (David Rowley, Jeff Davis) +§ +§ +§ +§ +§ + + + +This also improves hash set operations used by EXCEPT, and hash lookups of subplan values. + + + + + + + +Allow normal vacuums to freeze some pages, even though they are all-visible (Melanie Plageman) +§ +§ + + + +This reduces the overhead of later full-relation freezing. The aggressiveness of this can be controlled by server variable and per-table setting vacuum_max_eager_freeze_failure_rate. +Previously vacuum never processed all-visible pages until freezing was required. + + + + + + + +Add server variable vacuum_truncate to control file truncation during VACUUM (Nathan Bossart, Gurjeet Singh) +§ + + + +A storage-level parameter with the same name and behavior already existed. + + + + + + + +Increase server variables effective_io_concurrency's and maintenance_io_concurrency's default values to 16 (Melanie Plageman) +§ +§ + + + +This more accurately reflects modern hardware. + + + + + + + + + Monitoring + + + + + + + +Increase the logging granularity of server variable log_connections (Melanie Plageman) +§ + + + +This server variable was previously only boolean; these options are still supported. + + + + + + + +Add log_connections option to report the duration of connection stages (Melanie Plageman) +§ + + + + + + + +Add log_line_prefix escape %L to output the client IP address (Greg Sabino Mullane) +§ + + + + + + + +Add server variable log_lock_failures to log lock acquisition failures (Yuki Seino) +§ + + + +Specifically it reports SELECT ... NOWAIT lock failures. + + + + + + + +Modify pg_stat_all_tables and its variants to report the time spent in VACUUM, ANALYZE, and their automatic variants (Sami Imseih) +§ + + + +The new columns are total_vacuum_time, total_autovacuum_time, total_analyze_time, and total_autoanalyze_time. + + + + + + + +Add delay time reporting to VACUUM and ANALYZE (Bertrand Drouvot, Nathan Bossart) +§ +§ + + + +This information appears in the autovacuum logs, the system views pg_stat_progress_vacuum and pg_stat_progress_analyze, and the output of VACUUM and ANALYZE when in VERBOSE +mode; tracking must be enabled with the server variable track_cost_delay_timing. + + + + + + + +Add WAL, CPU, and average read statistics output to ANALYZE VERBOSE (Anthonin Bonnefoy) +§ +§ + + + + + + + +Add full WAL buffer count to VACUUM/ANALYZE (VERBOSE) and autovacuum log output (Bertrand Drouvot) +§ + + + + + + + +Add per-backend I/O statistics reporting (Bertrand Drouvot) +§ +§ + + + +The statistics are accessed via pg_stat_get_backend_io(). Per-backend I/O statistics can be cleared via pg_stat_reset_backend_stats(). + + + + + + + +Add pg_stat_io columns to report I/O activity in bytes (Nazir Bilal Yavuz) +§ + + + +The new columns are read_bytes, write_bytes, and extend_bytes. The op_bytes column, which always equaled BLCKSZ, has been removed. + + + + + + + +Add WAL I/O activity rows to pg_stat_io (Nazir Bilal Yavuz, Bertrand Drouvot, Michael Paquier) +§ +§ +§ + + + +This includes WAL receiver activity and a wait event for such writes. + + + + + + + + +Change server variable track_wal_io_timing to control tracking WAL timing in pg_stat_io instead of pg_stat_wal (Bertrand Drouvot) +§ + + + + + + + +Remove read/sync columns from pg_stat_wal (Bertrand Drouvot) +§ +§ + + + +This removes columns wal_write, wal_sync, wal_write_time, and wal_sync_time. + + + + + + + +Add function pg_stat_get_backend_wal() to return per-backend WAL statistics (Bertrand Drouvot) +§ + + + +Per-backend WAL statistics can be cleared via pg_stat_reset_backend_stats(). + + + + + + + +Add function pg_ls_summariesdir() to specifically list the contents of PGDATA/pg_wal/summaries (Yushi Ogiwara) +§ + + + + + + + +Add column pg_stat_checkpointer.num_done to report the number of completed checkpoints (Anton A. Melnikov) +§ + + + +Columns num_timed and num_requested count both completed and skipped checkpoints. + + + + + + + +Add column pg_stat_checkpointer.slru_written to report SLRU buffers written (Nitin Jadhav) +§ + + + +Also, modify the checkpoint server log message to report separate shared buffer and SLRU buffer values. + + + + + + + +Add columns to pg_stat_database to report parallel workers activity (Benoit Lobréau) +§ + + + +The new columns are parallel_workers_to_launch and parallel_workers_launched. + + + + + + + +Have query jumbling of arrays consider only the first and last array elements (Dmitry Dolgov, Sami Imseih) +§ +§ + + + +Jumbling is used by pg_stat_statements. + + + + + + + +Adjust query jumbling to group together queries using the same relation name (Michael Paquier, Sami Imseih) +§ + + + +This is true even if the tables in different schemas have different column names. + + + + + + + +Add column pg_backend_memory_contexts.type to report the type of memory context (David Rowley) +§ + + + + + + + +Add column pg_backend_memory_contexts.path to show memory context parents (Melih Mutlu) +§ + + + + + + + + + Privileges + + + + + + + +Add function pg_get_acl() to retrieve database access control details (Joel Jacobson) +§ +§ + + + + + + + +Add function has_largeobject_privilege() to check large object privileges (Yugo Nagata) +§ + + + + + + + +Allow ALTER DEFAULT PRIVILEGES to define large object default privileges (Takatsuka Haruka, Yugo Nagata, Laurenz Albe) +§ + + + + + + + +Add predefined role pg_signal_autovacuum_worker (Kirill Reshke) +§ + + + +This allows sending signals to autovacuum workers. + + + + + + + + + Server Configuration + + + + + + + +Add support for the OAuth authentication method (Jacob Champion, Daniel Gustafsson, Thomas Munro) +§ + + + +This adds an oauth authentication method to pg_hba.conf, libpq OAuth options, a server variable oauth_validator_libraries to load token validation libraries, and +a configure flag to add the required compile-time libraries. + + + + + + + +Add server variable ssl_tls13_ciphers to allow specification of multiple colon-separated TLSv1.3 cipher suites (Erica Zhang, Daniel Gustafsson) +§ + + + + + + + +Change server variable ssl_groups's default to include elliptic curve X25519 (Daniel Gustafsson, Jacob Champion) +§ + + + + + + + +Rename server variable ssl_ecdh_curve to ssl_groups and allow multiple colon-separated ECDH curves to be specified (Erica Zhang, Daniel Gustafsson) +§ + + +The previous name still works. + + + + + + + +Add function pg_check_fipsmode() to report the server's FIPS mode (Daniel Gustafsson) +§ + + + + + + + +Make cancel request keys 256 bits (Heikki Linnakangas, Jelte Fennema-Nio) +§ +§ + + + +This is only possible when the server and client support wire protocol version 3.2, introduced in this release. + + + + + + + +Add server variable autovacuum_worker_slots to specify the maximum number of background workers (Nathan Bossart) +§ + + + +With this variable set, autovacuum_max_workers can be adjusted at runtime up to this maximum without a server restart. + + + + + + + +Allow specification of the fixed number of dead tuples that will trigger an autovacuum (Nathan Bossart, Frédéric Yhuel) +§ + + + +The server variable is autovacuum_vacuum_max_threshold. Percentages are still used for triggering. + + + + + + + +Change server variable max_files_per_process to limit only files opened by a backend (Andres Freund) +§ + + + +Previously files opened by the postmaster were also counted toward this limit. + + + + + + + +Add server variable num_os_semaphores to report the required number of semaphores (Nathan Bossart) +§ + + + +This is useful for operating system configuration. + + + + + + + +Add server variable extension_control_path to specify the location of extension control files (Peter Eisentraut, Matheus Alcantara) +§ +§ + + + + + + + + + Streaming Replication and Recovery + + + + + + + +Allow inactive replication slots to be automatically invalided using server variable idle_replication_slot_timeout (Nisha Moond, Bharath Rupireddy) +§ + + + + + + + +Add server variable max_active_replication_origins to control the maximum active replication origins (Euler Taveira) +§ + + + +This was previously controlled by max_replication_slots, but this new setting allows a higher origin count in cases where fewer slots are required. + + + + + + + + + <link linkend="logical-replication">Logical Replication</link> + + + + + + + +Allow the values of generated columns to be logically replicated (Shubham Khanna, Vignesh C, Zhijie Hou, Shlok Kyal, Peter Smith) +§ +§ +§ +§ + + + +If the publication specifies a column list, all specified columns, generated and non-generated, are published. Without a specified column list, publication option publish_generated_columns +controls whether generated columns are published. Previously generated columns were not replicated and the subscriber had to compute the values if possible; this is particularly +useful for non-PostgreSQL subscribers which lack such a capability. + + + + + + + +Change the default CREATE SUBSCRIPTION streaming option from off to parallel (Vignesh C) +§ + + + + + + + +Allow ALTER SUBSCRIPTION to change the replication slot's two-phase commit behavior (Hayato Kuroda, Ajin Cherian, Amit Kapila, Zhijie Hou) +§ +§ + + + + + + + +Log conflicts while applying logical replication changes (Zhijie Hou, Nisha Moond) +§ +§ +§ +§ +§ + + + +Also report in new columns of pg_stat_subscription_stats. + + + + + + + + + + + Utility Commands + + + + + + + +Allow generated columns to be virtual, and make them the default (Peter Eisentraut, Jian He, Richard Guo, Dean Rasheed) +§ +§ +§ + + + +Virtual generated columns generate their values when the columns are read, not written. The write behavior can still be specified via the STORED option. + + + + + + + +Add OLD/NEW support to RETURNING in DML queries (Dean Rasheed) +§ + + + +Previously RETURNING only returned new values for INSERT and UPDATE, and old values for DELETE; MERGE would return the appropriate value for the internal query executed. This new syntax +allows the RETURNING list of INSERT/UPDATE/DELETE/MERGE to explicitly return old and new values by using the special aliases old and new. These aliases can be renamed to +avoid identifier conflicts. + + + + + + + +Allow foreign tables to be created like existing local tables (Zhang Mingli) +§ + + + +The syntax is CREATE FOREIGN TABLE ... LIKE. + + + + + + + +Allow LIKE with nondeterministic collations (Peter Eisentraut) +§ + + + + + + + +Allow text position search functions with nondeterministic collations (Peter Eisentraut) +§ + + + +These used to generate an error. + + + + + + + +Add builtin collation provider PG_UNICODE_FAST (Jeff Davis) +§ + + + +This locale supports case mapping, but sorts in code point order, not natural language order. + + + + + + + +Allow VACUUM and ANALYZE to process partitioned tables without processing their children (Michael Harris) +§ + + + +This is enabled with the new ONLY option. This is useful since autovacuum does not process partitioned tables, just its children. + + + + + + + +Add functions to modify per-relation and per-column optimizer statistics (Corey Huinker) +§ +§ +§ + + + +The functions are pg_restore_relation_stats(), pg_restore_attribute_stats(), pg_clear_relation_stats(), and pg_clear_attribute_stats(). + + + + + + + + +Add server variable file_copy_method to control the file copying method (Nazir Bilal Yavuz) +§ + + + +This controls whether CREATE DATABASE ... STRATEGY=FILE_COPY and ALTER DATABASE ... SET TABLESPACE uses file copy or clone. + + + + + + + <link linkend="ddl-constraints">Constraints</link> + + + + + + + +Allow the specification of non-overlapping PRIMARY KEY and UNIQUE constraints (Paul A. Jungwirth) +§ + + + +This is specified by WITHOUT OVERLAPS on the last column. + + + + + + + +Allow CHECK and foreign key constraints to be specified as NOT ENFORCED (Amul Sul) +§ +§ + + + +This also adds column pg_constraint.conenforced. + + + + + + +Require primary/foreign key relationships to use either deterministic collations or the the same nondeterministic collations (Peter Eisentraut) +§ + + + +The restore of a pg_dump, also used by pg_upgrade, will fail if these requirements are not met; schema changes must be made for these upgrade methods to succeed. + + + + + + + +Store column NOT NULL specifications in pg_constraint (Álvaro Herrera, Bernd Helmle) +§ + + + +This allows names to be specified for NOT NULL constraint. This also adds NOT NULL constraints to foreign tables and NOT NULL inheritance control to local tables. + + + + + + + +Allow ALTER TABLE to set the NOT VALID attribute of NOT NULL constraints (Rushabh Lathia, Jian He) +§ + + + + + + + +Allow modification of the inheritability of NOT NULL constraints (Suraj Kharage, Álvaro Herrera) +§ +§ + + + +The syntax is ALTER TABLE ... ALTER CONSTRAINT ... [NO] INHERIT. + + + + + + + +Allow NOT VALID foreign key constraints on partitioned tables (Amul Sul) +§ + + + + + + + +Allow dropping of constraints ONLY on partitioned tables (Álvaro Herrera) +§ + + + +This was previously erroneously prohibited. + + + + + + + + <link linkend="sql-copy"><command>COPY</command></link> + + + + + + + +Add REJECT_LIMIT to control the number of invalid rows COPY FROM can ignore (Atsushi Torikoshi) +§ + + + +This is available when ON_ERROR = 'ignore'. + + + + + + + +Allow COPY TO to copy rows from populated materialized views (Jian He) +§ + + + + + + + +Add COPY LOG_VERBOSITY level silent to suppress log output of ignored rows (Atsushi Torikoshi) +§ + + + +This new level suppresses output for discarded input rows when on_error = 'ignore'. + + + + + + + +Disallow COPY FREEZE on foreign tables (Nathan Bossart) +§ + + + +Previously, the COPY worked but the FREEZE was ignored, so disallow this command. + + + + + + + + <link linkend="sql-explain"><command>EXPLAIN</command></link> + + + + + + + +Automatically include BUFFERS output in EXPLAIN ANALYZE (Guillaume Lelarge, David Rowley) +§ + + + + + + + +Add full WAL buffer count to EXPLAIN (WAL) output (Bertrand Drouvot) +§ + + + + + + + +In EXPLAIN ANALYZE, report the number of index lookups used per index scan node (Peter Geoghegan) +§ + + + + + + + +Modify EXPLAIN to output fractional row counts (Ibrar Ahmed, Ilia Evdokimov, Robert Haas) +§ +§ + + + + + + + +Add memory and disk usage details to Material, Window Aggregate, and common table expression nodes to EXPLAIN +output (David Rowley, Tatsuo Ishii) +§ +§ +§ +§ + + + + + + + + +Add details about window function arguments to EXPLAIN output (Tom Lane) +§ + + + + + + + +Add Parallel Bitmap Heap Scan worker cache statistics to EXPLAIN ANALYZE (David Geier, Heikki Linnakangas, Donghang Lin, Alena Rybakina, David Rowley) +§ + + + + + + + +Indicate disabled nodes in EXPLAIN ANALYZE output (Robert Haas, David Rowley, Laurenz Albe) +§ +§ +§ + + + + + + + + + + + Data Types + + + + + + + +Improve Unicode full case mapping and conversion (Jeff Davis) +§ +§ + + + +This adds the ability to do conditional and title case mapping, and case map single characters to multiple characters. + + + + + + + +Allow jsonb null values to be cast to scalar types as NULL (Tom Lane) +§ + + + +Previously such casts generated an error. + + + + + + + +Add optional parameter to json{b}_strip_nulls to allow removal of null array elements (Florents Tselai) +§ + + + + + + + +Add function array_sort() which sorts an array's first dimension (Junwang Zhao, Jian He) +§ + + + + + + + +Add function array_reverse() which reverses an array's first dimension (Aleksander Alekseev) +§ + + + + + + + +Add function reverse() to reverse bytea bytes (Aleksander Alekseev) +§ + + + + + + + +Allow casting between integer types and bytea (Aleksander Alekseev) +§ + + + +The integer values are stored as bytea two's complement values. + + + + + + + +Update Unicode data to Unicode 16.0.0 (Peter Eisentraut) +§ + + + + + + + +Add full text search stemming for Estonian (Tom Lane) +§ + + + + + + + +Improve the XML error codes to more closely match the SQL standard (Tom Lane) +§ + + + +These errors are reported via SQLSTATE. + + + + + + + + + Functions + + + + + + + +Add function CASEFOLD() to allow for more sophisticated case-insensitive matching (Jeff Davis) +§ + + + +This allows more accurate comparisons, i.e., a character can have multiple upper or lower case equivalents, or upper or lower case conversion changes the number of characters. + + + + + + + +Allow MIN()/MAX() aggregates on arrays and composite types (Aleksander Alekseev, Marat Buharov) +§ +§ + + + + + + + +Add a WEEK option to EXTRACT() (Tom Lane) +§ + + + + + + + +Improve the output EXTRACT(QUARTER ...) for negative values (Tom Lane) +§ + + + + + + + +Add roman numeral support to to_number() (Hunaid Sohail) +§ + + + +This is accessed via the RN pattern. + + + + + + + +Add UUID version 7 generation function uuidv7() (Andrey Borodin) +§ + + + +This UUID value is temporally sortable. Function alias uuidv4() has been added to explicitly generate version 4 UUIDs. + + + + + + + +Add functions crc32() and crc32c() to compute CRC values (Aleksander Alekseev) +§ + + + + + + + +Add math functions gamma() and lgamma() (Dean Rasheed) +§ + + + + + + + +Allow => syntax for named cursor arguments in plpgsql (Pavel Stehule) +§ + + + +We previously only accepted :=. + + + + + + + +Allow regexp_match[es]()/regexp_like()/regexp_replace()/regexp_count()/regexp_instr()/regexp_substr()/regexp_split_to_table()/regexp_split_to_array() to use named arguments (Jian He) +§ + + + + + + + + + <link linkend="libpq">libpq</link> + + + + + + + +Add function PQfullProtocolVersion() to report the full, including minor, protocol version number (Jacob Champion, Jelte Fennema-Nio) +§ + + + + + + + +Add libpq connection parameters and environment variables to specify the minimum and maximum acceptable protocol version for connections (Jelte Fennema-Nio) +§ +§ + + + + + + + +Add libpq function PQservice() to return the connection service name (Michael Banck) +§ + + + + + + + +Report search_path changes to the client (Alexander Kukushkin, Jelte Fennema-Nio, Tomas Vondra) +§ +§ + + + + + + + +Add PQtrace() output for all message types, including authentication (Jelte Fennema-Nio) +§ +§ +§ +§ +§ + + + + + + + +Add libpq connection parameter sslkeylogfile which dumps out SSL key material (Abhishek Chanda, Daniel Gustafsson) +§ + + + +This is useful for debugging. + + + + + + + +Modify some libpq function signatures to use int64_t (Thomas Munro) +§ + + + +These previously used pg_int64, which is now deprecated. + + + + + + + + + <xref linkend="app-psql"/> + + + + + + + +Allow psql to parse, bind, and close named prepared statements (Anthonin Bonnefoy, Michael Paquier) +§ + + + +This is accomplished with new commands \parse, \bind_named, and \close. + + + + + + + +Add psql backslash commands to allowing issuance of pipeline queries (Anthonin Bonnefoy) +§ +§ +§ + + + +The new commands are \startpipeline, \syncpipeline, \sendpipeline, \endpipeline, \flushrequest, \flush, and \getresults. + + + + + + + +Allow adding pipeline status to the psql prompt and add related state variables (Anthonin Bonnefoy) +§ + + + +The new prompt character is %P and the new psql variables are PIPELINE_SYNC_COUNT, PIPELINE_COMMAND_COUNT, and PIPELINE_RESULT_COUNT. + + + + + + + +Allow adding the connection service name to the psql prompt or access it via psql variable (Michael Banck) +§ + + + + + + + +Add psql option to use expanded mode on all list commands (Dean Rasheed) +§ + + + +Adding backslash suffix x enables this. + + + + + + + +Change psql's \conninfo to use tabular format and include more information (Álvaro Herrera, Maiquel Grassi, Hunaid Sohail) +§ + + + + + + + +Add function's leakproof indicator to psql's \df+, \do+, \dAo+, and \dC+ outputs (Yugo Nagata) +§ + + + + + + + +Add access method details for partitioned relations in \dP+ (Justin Pryzby) +§ + + + + + + + +Add default_version to the psql \dx extension output (Magnus Hagander) +§ + + + + + + + +Add psql variable WATCH_INTERVAL to set the default \watch wait time (Daniel Gustafsson) +§ + + + + + + + + + Server Applications + + + + + + + +Change initdb to default to enabling checksums (Greg Sabino Mullane) +§ +§ + + + +The new initdb option disables checksums. + + + + + + + +Add initdb option to avoid syncing heap/index files (Nathan Bossart) +§ + + + +initdb option is still available to avoid syncing any files. + + + + + + + +Add vacuumdb option to compute only missing optimizer statistics (Corey Huinker, Nathan Bossart) +§ +§ + + + +This option can only be used by and . + + + + + + + +Add pg_combinebackup option / to enable hard linking (Israel Barth Rubio, Robert Haas) +§ + + + +Only some files can be hard linked. This should not be used if the backups will be used independently. + + + + + + + +Allow pg_verifybackup to verify tar-format backups (Amul Sul) +§ + + + + + + + +If pg_rewind's specifies a database name, use it in output (Masahiko Sawada) +§ + + + + + + + +Add pg_resetwal option to change the default char signedness (Masahiko Sawada) +§ + + + + + + + + <link + linkend="app-pgdump"><application>pg_dump</application></link>/<link + linkend="app-pg-dumpall"><application>pg_dumpall</application></link>/<link + linkend="app-pgrestore"><application>pg_restore</application></link> + + + + + + + +Allow pg_dumpall to dump in the same output formats as pg_dump supports (Mahendra Singh Thalor, Andrew Dunstan) +§ + + + +Also modify pg_restore to handle such dumps. Previously pg_dumpall only supported text format. + + + + + + + +Add pg_dump options , , and (Jeff Davis) +§ + + + + + + + +Add pg_dump and pg_dumpall option to dump sequence data that would normally be excluded (Nathan Bossart) +§ +§ + + + + + + + +Add pg_dump, pg_dumpall, and pg_restore options , , , and (Corey Huinker, Jeff Davis) +§ + + + + + + + +Add option to disable row level security policy processing in pg_dump, pg_dumpall, pg_restore (Nikolay Samokhvalov) +§ + + + +This is useful for migrating to systems with different policies. + + + + + + + + + <link linkend="pgupgrade"><application>pg_upgrade</application></link> + + + + + + + +Allow pg_upgrade to preserve optimizer statistics (Corey Huinker, Jeff Davis, Nathan Bossart) +§ +§ +§ +§ + + + +Extended statistics are not preserved. Also add pg_upgrade option to disable statistics preservation. + + + + + + + +Allow pg_upgrade to process database checks in parallel (Nathan Bossart) +§ +§ +§ +§ +§ +§ +§ +§ +§ +§ +§ + + + +This is controlled by the existing option. + + + + + + + +Add pg_upgrade option to swap directories rather than copy, clone, or link files (Nathan Bossart) +§ + + + +This mode is potentially the fastest. + + + + + + + +Add pg_upgrade option to set the default char signedness of new cluster (Masahiko Sawada) +§ +§ + + + +This is to handle cases where a pre-PostgreSQL 18 cluster's default CPU signedness does not match the new cluster. + + + + + + + + + Logical Replication Applications + + + + + + + +Add pg_createsubscriber option to create logical replicas for all databases (Shubham Khanna) +§ + + + + + + + +Add pg_createsubscriber option to remove publications (Shubham Khanna) +§ + + + + + + + +Add pg_createsubscriber option to enable prepared transactions (Shubham Khanna) +§ + + + + + + + +Add pg_recvlogical option to specify failover slots (Hayato Kuroda) +§ + + + + + + + +Allow pg_recvlogical to work without (Hayato Kuroda) +§ + + + + + + + + + + + Source Code + + + + + + + +Separate the loading and running of injection points (Michael Paquier, Heikki Linnakangas) +§ +§ + + + +Injection points can now be created, but not run, via INJECTION_POINT_LOAD(), and such injection points can be run via INJECTION_POINT_CACHED(). + + + + + + + +Support runtime arguments in injection points (Michael Paquier) +§ + + + + + + + +Allow inline injection point test code with IS_INJECTION_POINT_ATTACHED() (Heikki Linnakangas) +§ + + + + + + + +Improve the performance of processing long JSON strings using SIMD instructions (David Rowley) +§ + + + + + + + +Speed up CRC32C calculations using x86 AVX-512 instructions (Raghuveer Devulapalli, Paul Amonson) +§ + + + + + + + +Add ARM Neon and SVE CPU intrinsics for popcount (integer bit counting) (Chiranmoy Bhattacharya, Devanga Susmitha, Rama Malladi) +§ +§ + + + + + + + +Improve the speed of numeric multiplication and division (Joel Jacobson, Dean Rasheed) +§ +§ +§ +§ + + + + + + + +Add configure option to enable NUMA awareness (Jakub Wartak, Bertrand Drouvot) +§ +§ +§ + + + +The function pg_numa_available() reports on NUMA awareness, and system views pg_shmem_allocations_numa and pg_buffercache_numa which report on shared memory distribution across +NUMA nodes. + + + + + + + +Add TOAST table to pg_index to allow for very large expression indexes (Nathan Bossart) +§ + + + + + + + +Remove column +pg_attribute.attcacheoff (David Rowley) +§ + + + + + + + +Add column pg_class.relallfrozen (Melanie Plageman) +§ + + + + + + + +Add amgettreeheight, amconsistentequality, and amconsistentordering to the index access method API (Mark Dilger) +§ +§ + + + + + + + +Add GiST support function stratnum() (Paul A. Jungwirth) +§ + + + + + + + +Record the default CPU signedness of char in pg_controldata (Masahiko Sawada) +§ + + + + + + + +Add support for Python "Limited API" in PL/Python (Peter Eisentraut) +§ +§ + + + +This helps prevent problems caused by Python 3.x version mismatches. + + + + + + + +Change the minimum supported Python version to 3.6.8 (Jacob Champion) +§ + + + + + + + +Remove support for OpenSSL versions older than 1.1.1 (Daniel Gustafsson) +§ +§ + + + + + + + +If LLVM is enabled, require version 14 or later (Thomas Munro) +§ + + + + + + + +Add macro PG_MODULE_MAGIC_EXT to allow extensions to report their name and version (Andrei Lepikhov) +§ + + + +This information can be access via the new function pg_get_loaded_modules(). + + + + + + + +Document that SPI_connect()/SPI_connect_ext() always returns success (SPI_OK_CONNECT) (Stepan Neretin) +§ + + + +Errors are always reported via ereport(). + + + + + + + +Remove the experimental designation of Meson builds on Windows (Aleksander Alekseev) +§ + + + + + + + +Add documentation section about API and ABI compatibility (David Wheeler, Peter Eisentraut) +§ + + + + + + + +Remove configure options and (Thomas Munro) +§ +§ + + + +Thirty-two-bit atomic operations are now required. + + + + + + + +Remove support for the HPPA/PA-RISC architecture (Tom Lane) +§ + + + + + + + + + Additional Modules + + + + + + + +Add extension pg_logicalinspect to inspect logical snapshots (Bertrand Drouvot) +§ + + + + + + + +Add extension pg_overexplain which adds debug details to EXPLAIN output (Robert Haas) +§ + + + + + + + +Add output columns to postgres_fdw_get_connections() (Hayato Kuroda, Sagar Dilip Shedge) +§ +§ +§ +§ + + + +New output column used_in_xact indicates if the foreign data wrapper is being used by a current transaction, closed indicates if it is closed, user_name indicates the +user name, and remote_backend_pid indicates the remote backend process identifier. + + + + + + + +Allow SCRAM authentication from the client to be passed to postgres_fdw servers (Matheus Alcantara, Peter Eisentraut) +§ + + + +This avoids storing postgres_fdw authentication information in the database, and is enabled with the +postgres_fdw use_scram_passthrough connection option. libpq uses new connection +parameters scram_client_key and scram_server_key. + + + + + + + +Allow SCRAM authentication from the client to be passed to dblink servers (Matheus Alcantara) +§ + + + + + + + +Add on_error and log_verbosity options to file_fdw (Atsushi Torikoshi) +§ + + + +These control how file_fdw handles and reports invalid file rows. + + + + + + + +Add reject_limit to control the number of invalid rows file_fdw can ignore (Atsushi Torikoshi) +§ + + + +This is active when ON_ERROR = 'ignore'. + + + + + + + +Add configurable variable min_password_length to passwordcheck (Emanuele Musella, Maurizio Boriani) +§ + + + +This controls the minimum password length. + + + + + + + +Have pgbench report the number of failed, retried, or skipped transactions in per-script reports (Yugo Nagata) +§ + + + + + + + +Add isn server variable weak to control invalid check digit acceptance (Viktor Holmberg) +§ + + + +This was previously only controlled by function isn_weak(). + + + + + + + +Allow values to be sorted to speed btree_gist index builds (Bernd Helmle, Andrey Borodin) +§ + + + + + + + +Add amcheck function gin_index_check() to verify GIN indexes (Grigory Kryachko, Heikki Linnakangas, Andrey Borodin) +§ + + + + + + + +Add functions pg_buffercache_evict_relation() and pg_buffercache_evict_all() to evict unpinned shared buffers (Nazir Bilal Yavuz) +§ + + + +The existing function pg_buffercache_evict() now returns the buffer flush status. + + + + + + + +Allow extensions to install custom EXPLAIN options (Robert Haas, Sami Imseih) +§ +§ +§ + + + + + + + +Allow extensions to use the server's cumulative statistics API (Michael Paquier) +§ +§ + + + + + + + <link linkend="pgstatstatements"><application>pg_stat_statements</application></link> + + + + + + + +Allow the queries of CREATE TABLE AS and DECLARE to be tracked by pg_stat_statements (Anthonin Bonnefoy) +§ + + + +They are also now assigned query ids. + + + + + + + +Allow the parameterization of SET values in pg_stat_statements (Greg Sabino Mullane, Michael Paquier) +§ + + + +This reduces the bloat caused by SET statements with differing constants. + + + + + + + +Add pg_stat_statements columns to report parallel activity (Guillaume Lelarge) +§ + + + +The new columns are parallel_workers_to_launch and parallel_workers_launched. + + + + + + + +Add pg_stat_statements.wal_buffers_full to report full WAL buffers (Bertrand Drouvot) +§ + + + + + + + + + <link linkend="pgcrypto"><application>pgcrypto</application></link> + + + + + + + +Add pgcrypto functions sha256crypt() and sha512crypt() (Bernd Helmle) +§ + + + + + + + +Add CFB mode to pgcrypto encryption and decryption (Umar Hayat) +§ + + + + + + + +Add pgcrypto server variable builtin_crypto_enabled to allow disabling builtin non-FIPS mode cryptographic functions (Daniel Gustafsson, Joe Conway) +§ + + + +This is useful for guaranteeing FIPS mode behavior. + + + + + + + + + + + + Acknowledgments + + + The following individuals (in alphabetical order) have contributed + to this release as patch authors, committers, reviewers, testers, + or reporters of issues. + + + + (to be completed) + + + + diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index cf6ba54087664..cee577ff8d353 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -16,24 +16,6 @@ pg_[A-Za-z0-9_]+ , \<[a-z]+_[a-z_]+\> , -non-ASCII characters find using grep -P '[\x80-\xFF]' or - (remove 'X') grep -X-color='auto' -P -n "[\x80-\xFF]" - convert to HTML4 named entity (&) escapes - - official: http://www.w3.org/TR/html4/sgml/entities.html - one page: http://www.zipcon.net/~swhite/docs/computers/browsers/entities_page.html - other lists: http://www.zipcon.net/~swhite/docs/computers/browsers/entities.html - http://www.zipcon.net/~swhite/docs/computers/browsers/entities_page.html - https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references - - We cannot use UTF8 because rendering engines have to - support the referenced characters. - - Do not use numeric _UTF_ numeric character escapes (&#nnn;), - we can only use Latin1. - - Example: Alvaro Herrera is Álvaro Herrera - wrap long lines For new features, add links to the documentation sections. @@ -69,6 +51,15 @@ For new features, add links to the documentation sections. review, so each item is truly a community effort. + + Section markers (§) in the release notes link to gitweb + pages which show the primary git commit + messages and source tree changes responsible for the release note item. + There might be additional git commits which + are not shown. + + + + + + + + + + + 1.5em diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml index 4dfbbd0862614..916189a7d68ce 100644 --- a/doc/src/sgml/syntax.sgml +++ b/doc/src/sgml/syntax.sgml @@ -2496,7 +2496,7 @@ SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype)); linkend="functions-comparison"/>, to compare one row against another as described in , and to use them in connection with subqueries, as discussed in , + linkend="functions-subquery"/>. diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml index a0b692bf1e934..986ae1f543dbd 100644 --- a/doc/src/sgml/system-views.sgml +++ b/doc/src/sgml/system-views.sgml @@ -51,6 +51,11 @@ + + pg_aios + In-use asynchronous IO handles + + pg_available_extensions available extensions @@ -176,6 +181,11 @@ shared memory allocations + + pg_shmem_allocations_numa + NUMA node mappings for shared memory allocations + + pg_stats planner statistics @@ -231,6 +241,295 @@ + + <structname>pg_aios</structname> + + + pg_aios + + + + The pg_aios view lists all handles that are currently in-use. An I/O handle + is used to reference an I/O operation that is being prepared, executed or + is in the process of completing. pg_aios contains + one row for each I/O handle. + + + + This view is mainly useful for developers of + PostgreSQL, but may also be useful when tuning + PostgreSQL. + + + + <structname>pg_aios</structname> Columns + + + + + Column Type + + + Description + + + + + + + + pid int4 + + + Process ID of the server process that is issuing this I/O. + + + + + + io_id int4 + + + Identifier of the I/O handle. Handles are reused once the I/O + completed (or if the handle is released before I/O is started). On reuse + + pg_aios.io_generation + + is incremented. + + + + + + io_generation int8 + + + Generation of the I/O handle. + + + + + + state text + + + State of the I/O handle: + + + + HANDED_OUT, referenced by code but not yet used + + + + + DEFINED, information necessary for execution is known + + + + + STAGED, ready for execution + + + + + SUBMITTED, submitted for execution + + + + + COMPLETED_IO, finished, but result has not yet been processed + + + + + COMPLETED_SHARED, shared completion processing completed + + + + + COMPLETED_LOCAL, backend local completion processing completed + + + + + + + + + operation text + + + Operation performed using the I/O handle: + + + + invalid, not yet known + + + + + readv, a vectored read + + + + + writev, a vectored write + + + + + + + + + off int8 + + + Offset of the I/O operation. + + + + + + length int8 + + + Length of the I/O operation. + + + + + + target text + + + What kind of object is the I/O targeting: + + + + smgr, I/O on relations + + + + + + + + + handle_data_len int2 + + + Length of the data associated with the I/O operation. For I/O to/from + and , this indicates the number of buffers the + I/O is operating on. + + + + + + raw_result int4 + + + Low-level result of the I/O operation, or NULL if the operation has not + yet completed. + + + + + + result text + + + High-level result of the I/O operation: + + + + UNKNOWN means that the result of the + operation is not yet known. + + + + + OK means the I/O completed successfully. + + + + + PARTIAL means that the I/O completed without + error, but did not process all data. Commonly callers will need to + retry and perform the remainder of the work in a separate I/O. + + + + + WARNING means that the I/O completed without + error, but that execution of the IO triggered a warning. E.g. when + encountering a corrupted buffer with enabled. + + + + + ERROR means the I/O failed with an error. + + + + + + + + + target_desc text + + + Description of what the I/O operation is targeting. + + + + + + f_sync bool + + + Flag indicating whether the I/O is executed synchronously. + + + + + + f_localmem bool + + + Flag indicating whether the I/O references process local memory. + + + + + + f_buffered bool + + + Flag indicating whether the I/O is buffered I/O. + + + + + +
+ + + The pg_aios view is read-only. + + + + By default, the pg_aios view can be read only by + superusers or roles with privileges of the + pg_read_all_stats role. + +
+ <structname>pg_available_extensions</structname> @@ -481,15 +780,6 @@
- - - parent text - - - Name of the parent of this memory context - - - type text @@ -2444,7 +2734,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx active bool - True if this slot is currently actively being used + True if this slot is currently being streamed @@ -2453,9 +2743,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx active_pid int4 - The process ID of the session using this slot if the slot - is currently actively being used. NULL if - inactive. + The process ID of the session streaming data for this slot. + NULL if inactive. @@ -2570,20 +2859,33 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + + two_phase_at pg_lsn + + + The address (LSN) from which the decoding of prepared + transactions is enabled. NULL for logical slots + where two_phase is false and for physical slots. + + + inactive_since timestamptz - The time since the slot has become inactive. - NULL if the slot is currently being used. - Note that for slots on the standby that are being synced from a + The time when the slot became inactive. NULL if the + slot is currently being streamed. If the slot becomes invalid, + this value will never be updated. + For standby slots that are being synced from a primary server (whose synced field is - true), the - inactive_since indicates the last - synchronization (see - ) - time. + true), the inactive_since + indicates the time when slot synchronization (see ) + was most recently stopped. NULL if the slot + has always been synchronized. This helps standby slots track when + synchronization was interrupted. @@ -2595,7 +2897,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx True if this logical slot conflicted with recovery (and so is now invalidated). When this column is true, check invalidation_reason column for the conflict - reason. Always NULL for physical slots. + reason. Always NULL for physical slots. @@ -2627,6 +2929,13 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx perform logical decoding. It is set only for logical slots. + + + idle_timeout means that the slot has remained + idle longer than the configured + duration. + + @@ -3623,7 +3932,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx passwd text - Password (possibly encrypted); null if none. See + Encrypted password; null if none. See pg_authid for details of how encrypted passwords are stored. @@ -3747,6 +4056,96 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx + + <structname>pg_shmem_allocations_numa</structname> + + + pg_shmem_allocations_numa + + + + The pg_shmem_allocations_numa shows how shared + memory allocations in the server's main shared memory segment are distributed + across NUMA nodes. This includes both memory allocated by + PostgreSQL itself and memory allocated + by extensions using the mechanisms detailed in + . This view will output multiple rows + for each of the shared memory segments provided that they are spread across + multiple NUMA nodes. This view should not be queried by monitoring systems + as it is very slow and may end up allocating shared memory in case it was not + used earlier. + Current limitation for this view is that won't show anonymous shared memory + allocations. + + + + Note that this view does not include memory allocated using the dynamic + shared memory infrastructure. + + + + + When determining the NUMA node, the view touches + all memory pages for the shared memory segment. This will force + allocation of the shared memory, if it wasn't allocated already, + and the memory may get allocated in a single NUMA + node (depending on system configuration). + + + + + <structname>pg_shmem_allocations_numa</structname> Columns + + + + + Column Type + + + Description + + + + + + + + name text + + + The name of the shared memory allocation. + + + + + + numa_node int4 + + + ID of NUMA node + + + + + + size int8 + + + Size of the allocation on this particular NUMA memory node in bytes + + + + + +
+ + + By default, the pg_shmem_allocations_numa view can be + read only by superusers or roles with privileges of the + pg_read_all_stats role. + +
+ <structname>pg_stats</structname> @@ -3954,7 +4353,7 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx range type column. (Null for non-range types.) - This histogram is calculated using the subtype_diff + This histogram is calculated using the subtype_diff range function regardless of whether range bounds are inclusive. @@ -4573,7 +4972,9 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx The view pg_timezone_abbrevs provides a list of time zone abbreviations that are currently recognized by the datetime input routines. The contents of this view change when the - run-time parameter is modified. + or + run-time parameters are + modified. diff --git a/doc/src/sgml/tableam.sgml b/doc/src/sgml/tableam.sgml index 4b37f2e5a601c..9ccf5b739ed60 100644 --- a/doc/src/sgml/tableam.sgml +++ b/doc/src/sgml/tableam.sgml @@ -35,13 +35,60 @@ argument of type internal and to return the pseudo-type table_am_handler. The argument is a dummy value that simply serves to prevent handler functions from being called directly from SQL commands. + + + + Here is how an extension SQL script file might create a table access + method handler: + + + +CREATE OR REPLACE FUNCTION my_tableam_handler(internal) + RETURNS table_am_handler AS 'my_extension', 'my_tableam_handler' + LANGUAGE C STRICT; +CREATE ACCESS METHOD myam TYPE TABLE HANDLER my_tableam_handler; + + + The result of the function must be a pointer to a struct of type TableAmRoutine, which contains everything that the core code needs to know to make use of the table access method. The return value needs to be of server lifetime, which is typically achieved by - defining it as a static const variable in global - scope. The TableAmRoutine struct, also called the + defining it as a static const variable in global scope. + + + + Here is how a source file with the table access method handler might + look like: + + + + + + + The TableAmRoutine struct, also called the access method's API struct, defines the behavior of the access method using callbacks. These callbacks are pointers to plain C functions and are not visible or callable at the SQL level. All the diff --git a/doc/src/sgml/targets-meson.txt b/doc/src/sgml/targets-meson.txt index bd470c87a7090..d0021a5eb10d2 100644 --- a/doc/src/sgml/targets-meson.txt +++ b/doc/src/sgml/targets-meson.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # Description of important meson targets, used for the 'help' target and # installation.sgml (via generate-targets-meson.pl). Right now the parsers are diff --git a/doc/src/sgml/textsearch.sgml b/doc/src/sgml/textsearch.sgml index bde5f391e5c06..89928ed182913 100644 --- a/doc/src/sgml/textsearch.sgml +++ b/doc/src/sgml/textsearch.sgml @@ -1342,7 +1342,7 @@ ts_headline( config <b> and </b>, which can be suitable - for HTML output. + for HTML output (but see the warning below). @@ -1354,6 +1354,21 @@ ts_headline( config + + Warning: Cross-site Scripting (XSS) Safety + + The output from ts_headline is not guaranteed to + be safe for direct inclusion in web pages. When + HighlightAll is false (the + default), some simple XML tags are removed from the document, but this + is not guaranteed to remove all HTML markup. Therefore, this does not + provide an effective defense against attacks such as cross-site + scripting (XSS) attacks, when working with untrusted input. To guard + against such attacks, all HTML markup should be removed from the input + document, or an HTML sanitizer should be used on the output. + + + These option names are recognized case-insensitively. You must double-quote string values if they contain spaces or commas. @@ -2225,6 +2240,18 @@ LIMIT 10; Specifically, the only non-alphanumeric characters supported for email user names are period, dash, and underscore. + + + tag does not support all valid tag names as defined by + W3C Recommendation, XML. + Specifically, the only tag names supported are those starting with an + ASCII letter, underscore, or colon, and containing only letters, digits, + hyphens, underscores, periods, and colons. tag also + includes XML comments starting with <!-- and ending + with -->, and XML declarations (but note that this + includes anything starting with <?x and ending with + >). + @@ -3852,6 +3879,7 @@ Parser: "pg_catalog.default" pg_catalog | danish_stem | snowball stemmer for danish language pg_catalog | dutch_stem | snowball stemmer for dutch language pg_catalog | english_stem | snowball stemmer for english language + pg_catalog | estonian_stem | snowball stemmer for estonian language pg_catalog | finnish_stem | snowball stemmer for finnish language pg_catalog | french_stem | snowball stemmer for french language pg_catalog | german_stem | snowball stemmer for german language diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index 31626536a2e29..bb1b5faf34e31 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -129,6 +129,9 @@ In all cases, a trigger is executed as part of the same transaction as the statement that triggered it, so if either the statement or the trigger causes an error, the effects of both will be rolled back. + Also, the trigger will always run as the role that queued the trigger + event, unless the trigger function is marked as SECURITY + DEFINER, in which case it will run as the function owner. @@ -289,6 +292,10 @@ BEFORE trigger. Changes to the value of a generated column in a BEFORE trigger are ignored and will be overwritten. + Virtual generated columns are never computed when triggers fire. In the C + language interface, their content is undefined in a trigger function. + Higher-level programming languages should prevent access to virtual + generated columns in triggers. @@ -357,7 +364,8 @@ If a foreign key constraint specifies referential actions (that is, cascading updates or deletes), those actions are performed via - ordinary SQL update or delete commands on the referencing table. + ordinary SQL UPDATE or DELETE + commands on the referencing table. In particular, any triggers that exist on the referencing table will be fired for those changes. If such a trigger modifies or blocks the effect of one of these commands, the end result could @@ -915,8 +923,7 @@ trigf(PG_FUNCTION_ARGS) tupdesc = trigdata->tg_relation->rd_att; /* connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - elog(ERROR, "trigf (fired %s): SPI_connect returned %d", when, ret); + SPI_connect(); /* get number of rows in table */ ret = SPI_exec("SELECT count(*) FROM ttest", 0); diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 0a005481d1bf2..ed18704a9c2ab 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -407,7 +407,7 @@ REVOKE group_role FROM role1become the group role. In this state, the database session has access to the privileges of the group role rather than the original login role, and any database objects created are - considered owned by the group role not the login role. Second, member + considered owned by the group role, not the login role. Second, member roles that have been granted membership with the INHERIT option automatically have use of the privileges of those directly or indirectly a member of, though the diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 05e2a8f8be959..f3b86b26be905 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -186,7 +186,7 @@ - Each individual record in a WAL file is protected by a CRC-32 (32-bit) check + Each individual record in a WAL file is protected by a CRC-32C (32-bit) check that allows us to tell if record contents are correct. The CRC value is set when we write each WAL record and checked during crash recovery, archive recovery and replication. @@ -194,10 +194,8 @@ - Data pages are not currently checksummed by default, though full page images - recorded in WAL records will be protected; see initdb - for details about enabling data checksums. + Data pages are checksummed by default, and full page images + recorded in WAL records are always checksum protected. @@ -212,7 +210,7 @@ - Individual state files in pg_twophase are protected by CRC-32. + Individual state files in pg_twophase are protected by CRC-32C. @@ -238,15 +236,15 @@ - By default, data pages are not protected by checksums, but this can - optionally be enabled for a cluster. When enabled, each data page includes + By default, data pages are protected by checksums, but this can + optionally be disabled for a cluster. When enabled, each data page includes a checksum that is updated when the page is written and verified each time the page is read. Only data pages are protected by checksums; internal data structures and temporary files are not. - Checksums are normally enabled when the cluster is initialized using initdb. They can also be enabled or disabled at a later time as an offline operation. Data checksums are enabled or disabled at the full cluster @@ -643,6 +641,9 @@ until the situation is resolved. A slow or failed standby server that uses a replication slot will have the same effect (see ). + Similarly, if + WAL summarization is enabled, old segments are kept + until they are summarized. @@ -679,11 +680,11 @@ In some cases, when the WAL size on the primary increases quickly, - for instance during massive INSERT, + for instance during massive INSERT, the restartpoints_req counter on the standby may demonstrate a peak growth. This occurs because requests to create a new restartpoint due to increased - XLOG consumption cannot be performed because the safe checkpoint record + WAL consumption cannot be performed because the safe checkpoint record since the last restartpoint has not yet been replayed on the standby. This behavior is normal and does not lead to an increase in system resource consumption. @@ -810,8 +811,9 @@ When is enabled, the total amounts of time XLogWrite writes and issue_xlog_fsync syncs WAL data to disk are counted as - wal_write_time and wal_sync_time in - , respectively. + write_time and fsync_time in + for the object + wal, respectively. XLogWrite is normally called by XLogInsertRecord (when there is no space for the new record in WAL buffers), XLogFlush and the WAL writer, @@ -829,8 +831,9 @@ of the setting of track_wal_io_timing, the number of times XLogWrite writes and issue_xlog_fsync syncs WAL data to disk are also - counted as wal_write and wal_sync - in pg_stat_wal, respectively. + counted as writes and fsyncs + in pg_stat_io for the object + wal, respectively. @@ -841,8 +844,8 @@ The and settings limit prefetching concurrency and distance, respectively. By default, it is set to - try, which enables the feature on systems where - posix_fadvise is available. + try, which enables the feature on systems that support + issuing read-ahead advice. diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 5b584a4f14446..2d81afce8cb9b 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -234,21 +234,6 @@ CALL clean_emp(); whereas returning void is a PostgreSQL extension. - - - The entire body of an SQL function is parsed before any of it is - executed. While an SQL function can contain commands that alter - the system catalogs (e.g., CREATE TABLE), the effects - of such commands will not be visible during parse analysis of - later commands in the function. Thus, for example, - CREATE TABLE foo (...); INSERT INTO foo VALUES(...); - will not work as desired if packaged up into a single SQL function, - since foo won't exist yet when the INSERT - command is parsed. It's recommended to use PL/pgSQL - instead of an SQL function in this type of situation. - - - The syntax of the CREATE FUNCTION command requires the function body to be written as a string constant. It is usually @@ -1954,6 +1939,9 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision magic block + + PG_MODULE_MAGIC + To ensure that a dynamically loaded object file is not loaded into an @@ -1968,6 +1956,30 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision PG_MODULE_MAGIC; +or + +PG_MODULE_MAGIC_EXT(parameters); + + + + + The PG_MODULE_MAGIC_EXT variant allows the specification + of additional information about the module; currently, a name and/or a + version string can be added. (More fields might be allowed in future.) + Write something like this: + + +PG_MODULE_MAGIC_EXT( + .name = "my_module_name", + .version = "1.2.3" +); + + + Subsequently the name and version can be examined via + the pg_get_loaded_modules() function. + The meaning of the version string is not restricted + by PostgreSQL, but use of semantic versioning + rules is recommended. @@ -2384,6 +2396,56 @@ PG_FUNCTION_INFO_V1(funcname); takes as its argument the actual value to return. + + To call another version-1 function, you can use + DirectFunctionCalln(func, + arg1, ..., argn). This is particularly useful when you want + to call functions defined in the standard internal library, by using an + interface similar to their SQL signature. + + + + These convenience functions and similar ones can be found + in fmgr.h. + The DirectFunctionCalln + family expect a C function name as their first argument. There are also + OidFunctionCalln which + take the OID of the target function, and some other variants. All of + these expect the function's arguments to be supplied + as Datums, and likewise they return Datum. + Note that neither arguments nor result are allowed to be NULL when + using these convenience functions. + + + + For example, to call the starts_with(text, text) + function from C, you can search through the catalog and find out that + its C implementation is the + Datum text_starts_with(PG_FUNCTION_ARGS) + function. Typically you would + use DirectFunctionCall2(text_starts_with, ...) to + call such a function. However, starts_with(text, + text) requires collation information, so it will fail + with could not determine which collation to use for string + comparison if called that way. Instead you must + use DirectFunctionCall2Coll(text_starts_with, ...) + and provide the desired collation, which typically is just passed + through from PG_GET_COLLATION(), as shown in the + example below. + + + + fmgr.h also supplies macros that facilitate + conversions between C types and Datum. For example to + turn Datum into text*, you can + use DatumGetTextPP(X). While some types have macros + named like TypeGetDatum(X) for the reverse + conversion, text* does not; it's sufficient to use the + generic macro PointerGetDatum(X) for that. + If your extension defines additional types, it is usually convenient to + define similar macros for your types too. + + Here are some examples using the version-1 calling convention: @@ -2482,6 +2544,25 @@ concat_text(PG_FUNCTION_ARGS) memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size); PG_RETURN_TEXT_P(new_text); } + +/* A wrapper around starts_with(text, text) */ + +PG_FUNCTION_INFO_V1(t_starts_with); + +Datum +t_starts_with(PG_FUNCTION_ARGS) +{ + text *t1 = PG_GETARG_TEXT_PP(0); + text *t2 = PG_GETARG_TEXT_PP(1); + Oid collid = PG_GET_COLLATION(); + bool result; + + result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with, + collid, + PointerGetDatum(t1), + PointerGetDatum(t2))); + PG_RETURN_BOOL(result); +} ]]> @@ -2513,6 +2594,10 @@ CREATE FUNCTION copytext(text) RETURNS text CREATE FUNCTION concat_text(text, text) RETURNS text AS 'DIRECTORY/funcs', 'concat_text' LANGUAGE C STRICT; + +CREATE FUNCTION t_starts_with(text, text) RETURNS boolean + AS 'DIRECTORY/funcs', 't_starts_with' + LANGUAGE C STRICT; @@ -2704,6 +2789,142 @@ CREATE FUNCTION concat_text(text, text) RETURNS text &dfunc; + + Server API and ABI Stability Guidance + + + This section contains guidance to authors of extensions and other server + plugins about API and ABI stability in the + PostgreSQL server. + + + + General + + + The PostgreSQL server contains several + well-demarcated APIs for server plugins, such as the function manager + (fmgr, described in this chapter), + SPI (), and various hooks + specifically designed for extensions. These interfaces are carefully + managed for long-term stability and compatibility. However, the entire + set of global functions and variables in the server effectively + constitutes the publicly usable API, and most of it was not designed + with extensibility and long-term stability in mind. + + + + Therefore, while taking advantage of these interfaces is valid, the + further one strays from the well-trodden path, the likelier it will be + that one might encounter API or ABI compatibility issues at some point. + Extension authors are encouraged to provide feedback about their + requirements, so that over time, as new use patterns arise, certain + interfaces can be considered more stabilized or new, better-designed + interfaces can be added. + + + + + API Compatibility + + The API, or application programming interface, is the + interface used at compile time. + + + + Major Versions + + There is no promise of API compatibility between + PostgreSQL major versions. Extension code + therefore might require source code changes to work with multiple major + versions. These can usually be managed with preprocessor conditions + such as #if PG_VERSION_NUM >= 160000. + Sophisticated extensions that use interfaces beyond the well-demarcated + ones usually require a few such changes for each major server version. + + + + + Minor Versions + + PostgreSQL makes an effort to avoid server + API breaks in minor releases. In general, extension code that compiles + and works with a minor release should also compile and work with any + other minor release of the same major version, past or future. + + + + When a change is required, it will be carefully + managed, taking the requirements of extensions into account. Such + changes will be communicated in the release notes (). + + + + + + ABI Compatibility + + The ABI, or application binary interface, is the + interface used at run time. + + + + Major Versions + + Servers of different major versions have intentionally incompatible + ABIs. Extensions that use server APIs must therefore be re-compiled for + each major release. The inclusion of PG_MODULE_MAGIC + (see ) ensures that code compiled for + one major version will be rejected by other major versions. + + + + + Minor Versions + + PostgreSQL makes an effort to avoid server + ABI breaks in minor releases. In general, an extension compiled against + any minor release should work with any other minor release of the same + major version, past or future. + + + + When a change is required, + PostgreSQL will choose the least invasive + change possible, for example by squeezing a new field into padding + space or appending it to the end of a struct. These sorts of changes + should not impact extensions unless they use very unusual code + patterns. + + + + In rare cases, however, even such non-invasive changes may be + impractical or impossible. In such an event, the change will be + carefully managed, taking the requirements of extensions into account. + Such changes will also be documented in the release notes (). + + + + Note, however, that many parts of the server are not designed or + maintained as publicly-consumable APIs (and that, in most cases, the + actual boundary is also not well-defined). If urgent needs arise, + changes in those parts will naturally be made with less consideration + for extension code than changes in well-defined and widely used + interfaces. + + + + Also, in the absence of automated detection of such changes, this is + not a guarantee, but historically such breaking changes have been + extremely rare. + + + + + + Composite-Type Arguments @@ -3608,14 +3829,17 @@ uint32 WaitEventExtensionNew(const char *wait_event_name) An injection point with a given name is declared using macro: -INJECTION_POINT(name); +INJECTION_POINT(name, arg); There are a few injection points already declared at strategic points within the server code. After adding a new injection point the code needs to be compiled in order for that injection point to be available in the binary. Add-ins written in C-language can declare injection points in - their own code using the same macro. + their own code using the same macro. The injection point names should use + lower-case characters, with terms separated by + dashes. arg is an optional argument value given to the + callback at run-time. @@ -3625,7 +3849,7 @@ INJECTION_POINT(name); a two-step approach with the following macros: INJECTION_POINT_LOAD(name); -INJECTION_POINT_CACHED(name); +INJECTION_POINT_CACHED(name, arg); Before entering the critical section, @@ -3658,7 +3882,9 @@ extern void InjectionPointAttach(const char *name, InjectionPointCallback: static void -custom_injection_callback(const char *name, const void *private_data) +custom_injection_callback(const char *name, + const void *private_data, + void *arg) { uint32 wait_event_info = WaitEventInjectionPointNew(name); @@ -3687,7 +3913,7 @@ if (IS_INJECTION_POINT_ATTACHED("before-foobar")) local_var = 123; /* also execute the callback */ - INJECTION_POINT_CACHED("before-foobar"); + INJECTION_POINT_CACHED("before-foobar", NULL); } #endif @@ -3728,6 +3954,68 @@ extern bool InjectionPointDetach(const char *name); + + Custom Cumulative Statistics + + + It is possible for add-ins written in C-language to use custom types + of cumulative statistics registered in the + Cumulative Statistics System. + + + + First, define a PgStat_KindInfo that includes all + the information related to the custom type registered. For example: + +static const PgStat_KindInfo custom_stats = { + .name = "custom_stats", + .fixed_amount = false, + .shared_size = sizeof(PgStatShared_Custom), + .shared_data_off = offsetof(PgStatShared_Custom, stats), + .shared_data_len = sizeof(((PgStatShared_Custom *) 0)->stats), + .pending_size = sizeof(PgStat_StatCustomEntry), +} + + + Then, each backend that needs to use this custom type needs to register + it with pgstat_register_kind and a unique ID used to + store the entries related to this type of statistics: + +extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind, + const PgStat_KindInfo *kind_info); + + While developing a new extension, use + PGSTAT_KIND_EXPERIMENTAL for + kind. When you are ready to release the extension + to users, reserve a kind ID at the + + Custom Cumulative Statistics page. + + + + The details of the API for PgStat_KindInfo can + be found in src/include/utils/pgstat_internal.h. + + + + The type of statistics registered is associated with a name and a unique + ID shared across the server in shared memory. Each backend using a + custom type of statistics maintains a local cache storing the information + of each custom PgStat_KindInfo. + + + + Place the extension module implementing the custom cumulative statistics + type in so that it will + be loaded early during PostgreSQL startup. + + + + An example describing how to register and use custom statistics can be + found in src/test/modules/injection_points. + + + Using C++ for Extensibility diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 22d8ad1aac43b..3d315df2f9803 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -461,6 +461,13 @@ 5 + + + Return the addresses of C-callable skip support function(s) + (optional) + + 6 +
@@ -508,7 +515,7 @@ - GiST indexes have eleven support functions, six of which are optional, + GiST indexes have twelve support functions, seven of which are optional, as shown in . (For more information see .) @@ -590,6 +597,12 @@ (optional) 11 + + translate_cmptype + translate compare types to strategy numbers + used by the operator class (optional) + 12 + @@ -1056,7 +1069,8 @@ DEFAULT FOR TYPE int8 USING btree FAMILY integer_ops AS FUNCTION 1 btint8cmp(int8, int8) , FUNCTION 2 btint8sortsupport(internal) , FUNCTION 3 in_range(int8, int8, int8, boolean, boolean) , - FUNCTION 4 btequalimage(oid) ; + FUNCTION 4 btequalimage(oid) , + FUNCTION 6 btint8skipsupport(internal) ; CREATE OPERATOR CLASS int4_ops DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS @@ -1069,7 +1083,8 @@ DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS FUNCTION 1 btint4cmp(int4, int4) , FUNCTION 2 btint4sortsupport(internal) , FUNCTION 3 in_range(int4, int4, int4, boolean, boolean) , - FUNCTION 4 btequalimage(oid) ; + FUNCTION 4 btequalimage(oid) , + FUNCTION 6 btint4skipsupport(internal) ; CREATE OPERATOR CLASS int2_ops DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS @@ -1082,7 +1097,8 @@ DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS FUNCTION 1 btint2cmp(int2, int2) , FUNCTION 2 btint2sortsupport(internal) , FUNCTION 3 in_range(int2, int2, int2, boolean, boolean) , - FUNCTION 4 btequalimage(oid) ; + FUNCTION 4 btequalimage(oid) , + FUNCTION 6 btint2skipsupport(internal) ; ALTER OPERATOR FAMILY integer_ops USING btree ADD -- cross-type comparisons int8 vs int2 diff --git a/meson.build b/meson.build index 27805b9bcc951..d142e3e408b38 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Entry point for building PostgreSQL with meson # @@ -8,7 +8,7 @@ project('postgresql', ['c'], - version: '18devel', + version: '18beta1', license: 'PostgreSQL', # We want < 0.56 for python 3.5 compatibility on old platforms. EPEL for @@ -107,6 +107,7 @@ os_deps = [] backend_both_deps = [] backend_deps = [] libpq_deps = [] +libpq_oauth_deps = [] pg_sysroot = '' @@ -261,13 +262,23 @@ elif host_system == 'openbsd' elif host_system == 'sunos' portname = 'solaris' export_fmt = '-Wl,-M@0@' - cppflags += '-D_POSIX_PTHREAD_SEMANTICS' + # We need these #defines to get POSIX-conforming versions + # of many interfaces (sigwait, getpwuid_r, shmdt, ...). + cppflags += [ + '-D_POSIX_C_SOURCE=200112L', + '-D__EXTENSIONS__', + '-D_POSIX_PTHREAD_SEMANTICS', + ] elif host_system == 'windows' portname = 'win32' exesuffix = '.exe' dlsuffix = '.dll' library_path_var = '' + if cc.get_id() != 'msvc' + # define before including for getting localtime_r() etc. on MinGW + cppflags += '-D_POSIX_C_SOURCE' + endif export_file_format = 'win' export_file_suffix = 'def' @@ -324,7 +335,7 @@ endif # External programs perl = find_program(get_option('PERL'), required: true, native: true) python = find_program(get_option('PYTHON'), required: true, native: true) -flex = find_program(get_option('FLEX'), native: true, version: '>= 2.5.35') +flex = find_program(get_option('FLEX'), native: true) bison = find_program(get_option('BISON'), native: true, version: '>= 2.3') sed = find_program(get_option('SED'), 'sed', native: true, required: false) prove = find_program(get_option('PROVE'), native: true, required: false) @@ -547,7 +558,8 @@ test_c_args = cppflags + cflags bsd_authopt = get_option('bsd_auth') bsd_auth = not_found_dep if cc.check_header('bsd_auth.h', required: bsd_authopt, - args: test_c_args, include_directories: postgres_inc) + args: test_c_args, prefix: '#include ', + include_directories: postgres_inc) cdata.set('USE_BSD_AUTH', 1) bsd_auth = declare_dependency() endif @@ -788,7 +800,7 @@ endif llvmopt = get_option('llvm') llvm = not_found_dep if add_languages('cpp', required: llvmopt, native: false) - llvm = dependency('llvm', version: '>=10', method: 'config-tool', required: llvmopt) + llvm = dependency('llvm', version: '>=14', method: 'config-tool', required: llvmopt) if llvm.found() @@ -844,6 +856,144 @@ endif +############################################################### +# Library: libcurl +############################################################### + +libcurlopt = get_option('libcurl') +oauth_flow_supported = false + +if not libcurlopt.disabled() + # Check for libcurl 7.61.0 or higher (corresponding to RHEL8 and the ability + # to explicitly set TLS 1.3 ciphersuites). + libcurl = dependency('libcurl', version: '>= 7.61.0', required: libcurlopt) + if libcurl.found() + # Check to see whether the current platform supports thread-safe Curl + # initialization. + libcurl_threadsafe_init = false + + if not meson.is_cross_build() + r = cc.run(''' + #include + + int main(void) + { + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); + #ifdef CURL_VERSION_THREADSAFE + if (info->features & CURL_VERSION_THREADSAFE) + return 0; + #endif + + return 1; + }''', + name: 'test for curl_global_init thread safety', + dependencies: libcurl, + ) + + assert(r.compiled()) + if r.returncode() == 0 + libcurl_threadsafe_init = true + message('curl_global_init is thread-safe') + elif r.returncode() == 1 + message('curl_global_init is not thread-safe') + else + message('curl_global_init failed; assuming not thread-safe') + endif + endif + + if libcurl_threadsafe_init + cdata.set('HAVE_THREADSAFE_CURL_GLOBAL_INIT', 1) + endif + + # Fail if a thread-friendly DNS resolver isn't built. + if not meson.is_cross_build() + r = cc.run(''' + #include + + int main(void) + { + curl_version_info_data *info; + + if (curl_global_init(CURL_GLOBAL_ALL)) + return -1; + + info = curl_version_info(CURLVERSION_NOW); + return (info->features & CURL_VERSION_ASYNCHDNS) ? 0 : 1; + }''', + name: 'test for curl support for asynchronous DNS', + dependencies: libcurl, + ) + + assert(r.compiled()) + if r.returncode() != 0 + error(''' +*** The installed version of libcurl does not support asynchronous DNS +*** lookups. Rebuild libcurl with the AsynchDNS feature enabled in order +*** to use it with libpq.''') + endif + endif + endif + + # Check that the current platform supports our builtin flow. This requires + # libcurl and one of either epoll or kqueue. + oauth_flow_supported = ( + libcurl.found() + and (cc.check_header('sys/event.h', required: false, + args: test_c_args, include_directories: postgres_inc) + or cc.check_header('sys/epoll.h', required: false, + args: test_c_args, include_directories: postgres_inc)) + ) + + if oauth_flow_supported + cdata.set('USE_LIBCURL', 1) + elif libcurlopt.enabled() + error('client-side OAuth is not supported on this platform') + endif + +else + libcurl = not_found_dep +endif + + +############################################################### +# Library: libnuma +############################################################### + +libnumaopt = get_option('libnuma') +if not libnumaopt.disabled() + # via pkg-config + libnuma = dependency('numa', required: false) + if not libnuma.found() + libnuma = cc.find_library('numa', required: libnumaopt) + endif + if not cc.has_header('numa.h', dependencies: libnuma, required: libnumaopt) + libnuma = not_found_dep + endif + if libnuma.found() + cdata.set('USE_LIBNUMA', 1) + endif +else + libnuma = not_found_dep +endif + + +############################################################### +# Library: liburing +############################################################### + +liburingopt = get_option('liburing') +liburing = dependency('liburing', required: liburingopt) +if liburing.found() + cdata.set('USE_LIBURING', 1) +endif + + + ############################################################### # Library: libxml ############################################################### @@ -986,6 +1136,7 @@ endif perlopt = get_option('plperl') perl_dep = not_found_dep +perlversion = '' if not perlopt.disabled() perl_may_work = true @@ -1003,7 +1154,7 @@ if not perlopt.disabled() # Then inquire perl about its configuration if perl_may_work perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}'] - perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout() + perlversion = run_command(perl_conf_cmd, 'version', check: true).stdout() archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout() privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout() useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout() @@ -1054,7 +1205,10 @@ if not perlopt.disabled() if cc.get_id() == 'msvc' # prevent binary mismatch between MSVC built plperl and Strawberry or # msys ucrt perl libraries - perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE'] + perl_v = run_command(perl, '-V').stdout() + if not perl_v.contains('USE_THREAD_SAFE_LOCALE') + perl_ccflags += ['-DNO_THREAD_SAFE_LOCALE'] + endif endif endif @@ -1065,20 +1219,19 @@ if not perlopt.disabled() # Config's ccdlflags and ldflags. (Those are the choices of those who # built the Perl installation, which are not necessarily appropriate # for building PostgreSQL.) - ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip() - undesired = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().split() - undesired += run_command(perl_conf_cmd, 'ldflags', check: true).stdout().split() - - perl_ldopts = [] - foreach ldopt : ldopts.split(' ') - if ldopt == '' or ldopt in undesired - continue - endif - - perl_ldopts += ldopt.strip('"') - endforeach + perl_ldopts = run_command(perl, '-e', ''' +use ExtUtils::Embed; +use Text::ParseWords; +# tell perl to suppress including these in ldopts +*ExtUtils::Embed::_ldflags =*ExtUtils::Embed::_ccdlflags = sub { return ""; }; +# adding an argument to ldopts makes it return a value instead of printing +# print one of these per line so splitting will preserve spaces in file names. +# shellwords eats backslashes, so we need to escape them. +(my $opts = ldopts(undef)) =~ s!\\!\\\\!g; +print "$_\n" foreach shellwords($opts); +''', + check: true).stdout().strip().split('\n') - message('LDFLAGS recommended by perl: "@0@"'.format(ldopts)) message('LDFLAGS for embedding perl: "@0@"'.format(' '.join(perl_ldopts))) perl_dep_int = declare_dependency( @@ -1355,28 +1508,16 @@ if sslopt in ['auto', 'openssl'] ['CRYPTO_new_ex_data', {'required': true}], ['SSL_new', {'required': true}], + # Functions introduced in OpenSSL 1.1.1. + ['SSL_CTX_set_ciphersuites', {'required': true}], + # Function introduced in OpenSSL 1.0.2, not in LibreSSL. ['SSL_CTX_set_cert_cb'], - # Functions introduced in OpenSSL 1.1.0. We used to check for - # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL - # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it - # doesn't have these OpenSSL 1.1.0 functions. So check for individual - # functions. - ['OPENSSL_init_ssl'], - ['BIO_meth_new'], - ['ASN1_STRING_get0_data'], - ['HMAC_CTX_new'], - ['HMAC_CTX_free'], - - # OpenSSL versions before 1.1.0 required setting callback functions, for - # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() - # function was removed. - ['CRYPTO_lock'], - - # Function introduced in OpenSSL 1.1.1 + # Function introduced in OpenSSL 1.1.1, not in LibreSSL. ['X509_get_signature_info'], ['SSL_CTX_set_num_tickets'], + ['SSL_CTX_set_keylog_callback'], ] are_openssl_funcs_complete = true @@ -1398,7 +1539,7 @@ if sslopt in ['auto', 'openssl'] if are_openssl_funcs_complete cdata.set('USE_OPENSSL', 1, description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)') - cdata.set('OPENSSL_API_COMPAT', '0x10002000L', + cdata.set('OPENSSL_API_COMPAT', '0x10101000L', description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.') ssl_library = 'openssl' else @@ -1595,21 +1736,6 @@ if not cc.compiles(c99_test, name: 'c99', args: test_c_args) endif endif -sizeof_long = cc.sizeof('long', args: test_c_args) -cdata.set('SIZEOF_LONG', sizeof_long) -if sizeof_long == 8 - cdata.set('HAVE_LONG_INT_64', 1) - pg_int64_type = 'long int' - cdata.set_quoted('INT64_MODIFIER', 'l') -elif sizeof_long == 4 and cc.sizeof('long long', args: test_c_args) == 8 - cdata.set('HAVE_LONG_LONG_INT_64', 1) - pg_int64_type = 'long long int' - cdata.set_quoted('INT64_MODIFIER', 'll') -else - error('do not know how to get a 64bit int') -endif -cdata.set('PG_INT64_TYPE', pg_int64_type) - if host_machine.endian() == 'big' cdata.set('WORDS_BIGENDIAN', 1) endif @@ -1633,16 +1759,18 @@ endforeach # of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms # where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF. # -# We assume without checking that int64's alignment is at least as strong +# We assume without checking that int64_t's alignment is at least as strong # as long, char, short, or int. Note that we intentionally do not consider # any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 # would be too much of a penalty for disk and memory space. alignof_double = cdata.get('ALIGNOF_DOUBLE') -if cc.alignment(pg_int64_type, args: test_c_args) > alignof_double - error('alignment of int64 is greater than the alignment of double') +if cc.alignment('int64_t', args: test_c_args, prefix: '#include ') > alignof_double + error('alignment of int64_t is greater than the alignment of double') endif cdata.set('MAXIMUM_ALIGNOF', alignof_double) +cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args)) +cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args)) cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args)) cdata.set('SIZEOF_SIZE_T', cc.sizeof('size_t', args: test_c_args)) @@ -1741,6 +1869,7 @@ if cc.compiles(''' my_label: return 1; }''', + name: 'computed goto', args: test_c_args) cdata.set('HAVE_COMPUTED_GOTO', 1) endif @@ -1757,21 +1886,12 @@ if cc.compiles(''' ({ _Static_assert(1, "foo"); }); } ''', + name: '_Static_assert', args: test_c_args) cdata.set('HAVE__STATIC_ASSERT', 1) endif -# We use if we have it and it declares type bool as having -# size 1. Otherwise, c.h will fall back to declaring bool as unsigned char. -if cc.has_type('_Bool', args: test_c_args) \ - and cc.has_type('bool', prefix: '#include ', args: test_c_args) \ - and cc.sizeof('bool', prefix: '#include ', args: test_c_args) == 1 - cdata.set('HAVE__BOOL', 1) - cdata.set('PG_USE_STDBOOL', 1) -endif - - # Need to check a call with %m because netbsd supports gnu_printf but emits a # warning for each use of %m. printf_attributes = ['gnu_printf', '__syslog__', 'printf'] @@ -1851,17 +1971,17 @@ endif # compile, and store the results in global variables so the compiler doesn't # optimize away the call. if cc.links(''' - INT64 a = 1; - INT64 b = 1; - INT64 result; + #include + int64_t a = 1; + int64_t b = 1; + int64_t result; int main(void) { return __builtin_mul_overflow(a, b, &result); }''', name: '__builtin_mul_overflow', - args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))], - ) + args: test_c_args) cdata.set('HAVE__BUILTIN_OP_OVERFLOW', 1) endif @@ -1986,6 +2106,16 @@ if cc.has_argument('-Wdeclaration-after-statement') cflags_no_decl_after_statement += '-Wno-declaration-after-statement' endif +# Some code is not clean for -Wmissing-variable-declarations, so we +# make the "no" option available. Also, while clang supports this +# option for C++, gcc does not, so for consistency, leave it off for +# C++. +cflags_no_missing_var_decls = [] +if cc.has_argument('-Wmissing-variable-declarations') + cflags_warn += '-Wmissing-variable-declarations' + cflags_no_missing_var_decls += '-Wno-missing-variable-declarations' +endif + # The following tests want to suppress various unhelpful warnings by adding # -Wno-foo switches. But gcc won't complain about unrecognized -Wno-foo @@ -2089,101 +2219,84 @@ endif # Atomics ############################################################### -if not get_option('spinlocks') - warning('Not using spinlocks will cause poor performance') -else - cdata.set('HAVE_SPINLOCKS', 1) -endif - -if not get_option('atomics') - warning('Not using atomics will cause poor performance') -else - # XXX: perhaps we should require some atomics support in this case these - # days? - cdata.set('HAVE_ATOMICS', 1) - - atomic_checks = [ - {'name': 'HAVE_GCC__SYNC_CHAR_TAS', - 'desc': '__sync_lock_test_and_set(char)', - 'test': ''' +atomic_checks = [ + {'name': 'HAVE_GCC__SYNC_CHAR_TAS', + 'desc': '__sync_lock_test_and_set(char)', + 'test': ''' char lock = 0; __sync_lock_test_and_set(&lock, 1); __sync_lock_release(&lock);'''}, - {'name': 'HAVE_GCC__SYNC_INT32_TAS', - 'desc': '__sync_lock_test_and_set(int32)', - 'test': ''' + {'name': 'HAVE_GCC__SYNC_INT32_TAS', + 'desc': '__sync_lock_test_and_set(int32)', + 'test': ''' int lock = 0; __sync_lock_test_and_set(&lock, 1); __sync_lock_release(&lock);'''}, - {'name': 'HAVE_GCC__SYNC_INT32_CAS', - 'desc': '__sync_val_compare_and_swap(int32)', - 'test': ''' + {'name': 'HAVE_GCC__SYNC_INT32_CAS', + 'desc': '__sync_val_compare_and_swap(int32)', + 'test': ''' int val = 0; __sync_val_compare_and_swap(&val, 0, 37);'''}, - {'name': 'HAVE_GCC__SYNC_INT64_CAS', - 'desc': '__sync_val_compare_and_swap(int64)', - 'test': ''' -INT64 val = 0; + {'name': 'HAVE_GCC__SYNC_INT64_CAS', + 'desc': '__sync_val_compare_and_swap(int64)', + 'test': ''' +int64_t val = 0; __sync_val_compare_and_swap(&val, 0, 37);'''}, - {'name': 'HAVE_GCC__ATOMIC_INT32_CAS', - 'desc': ' __atomic_compare_exchange_n(int32)', - 'test': ''' + {'name': 'HAVE_GCC__ATOMIC_INT32_CAS', + 'desc': ' __atomic_compare_exchange_n(int32)', + 'test': ''' int val = 0; int expect = 0; __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''}, - {'name': 'HAVE_GCC__ATOMIC_INT64_CAS', - 'desc': ' __atomic_compare_exchange_n(int64)', - 'test': ''' -INT64 val = 0; -INT64 expect = 0; + {'name': 'HAVE_GCC__ATOMIC_INT64_CAS', + 'desc': ' __atomic_compare_exchange_n(int64)', + 'test': ''' +int64_t val = 0; +int64_t expect = 0; __atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''}, - ] +] - foreach check : atomic_checks - test = ''' +foreach check : atomic_checks + test = ''' +#include int main(void) { @0@ }'''.format(check['test']) - cdata.set(check['name'], - cc.links(test, - name: check['desc'], - args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) ? 1 : false - ) - endforeach - -endif + cdata.set(check['name'], + cc.links(test, + name: check['desc'], + args: test_c_args) ? 1 : false + ) +endforeach ############################################################### # Check for the availability of XSAVE intrinsics. ############################################################### -cflags_xsave = [] if host_cpu == 'x86' or host_cpu == 'x86_64' prog = ''' #include +#if defined(__has_attribute) && __has_attribute (target) +__attribute__((target("xsave"))) +#endif int main(void) { return _xgetbv(0) & 0xe0; } ''' - if cc.links(prog, name: 'XSAVE intrinsics without -mxsave', - args: test_c_args) - cdata.set('HAVE_XSAVE_INTRINSICS', 1) - elif cc.links(prog, name: 'XSAVE intrinsics with -mxsave', - args: test_c_args + ['-mxsave']) + if cc.links(prog, name: 'XSAVE intrinsics', args: test_c_args) cdata.set('HAVE_XSAVE_INTRINSICS', 1) - cflags_xsave += '-mxsave' endif endif @@ -2193,19 +2306,22 @@ endif # Check for the availability of AVX-512 popcount intrinsics. ############################################################### -cflags_popcnt = [] if host_cpu == 'x86_64' prog = ''' #include +#include +char buf[sizeof(__m512i)]; +#if defined(__has_attribute) && __has_attribute (target) +__attribute__((target("avx512vpopcntdq,avx512bw"))) +#endif int main(void) { - const char buf[sizeof(__m512i)]; - INT64 popcnt = 0; + int64_t popcnt = 0; __m512i accum = _mm512_setzero_si512(); - const __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); - const __m512i cnt = _mm512_popcnt_epi64(val); + __m512i val = _mm512_maskz_loadu_epi8((__mmask64) 0xf0f0f0f0f0f0f0f0, (const __m512i *) buf); + __m512i cnt = _mm512_popcnt_epi64(val); accum = _mm512_add_epi64(accum, cnt); popcnt = _mm512_reduce_add_epi64(accum); /* return computed value, to prevent the above being optimized away */ @@ -2213,13 +2329,56 @@ int main(void) } ''' - if cc.links(prog, name: 'AVX-512 popcount without -mavx512vpopcntdq -mavx512bw', - args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))]) + if cc.links(prog, name: 'AVX-512 popcount', args: test_c_args) cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1) - elif cc.links(prog, name: 'AVX-512 popcount with -mavx512vpopcntdq -mavx512bw', - args: test_c_args + ['-DINT64=@0@'.format(cdata.get('PG_INT64_TYPE'))] + ['-mavx512vpopcntdq'] + ['-mavx512bw']) - cdata.set('USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 1) - cflags_popcnt += ['-mavx512vpopcntdq'] + ['-mavx512bw'] + endif + +endif + + +############################################################### +# Check for the availability of SVE popcount intrinsics. +############################################################### + +if host_cpu == 'aarch64' + + prog = ''' +#include + +char buf[128]; + +#if defined(__has_attribute) && __has_attribute (target) +__attribute__((target("arch=armv8-a+sve"))) +#endif +int main(void) +{ + svbool_t pred = svptrue_b64(); + svuint8_t vec8; + svuint64_t accum1 = svdup_u64(0), + accum2 = svdup_u64(0), + vec64; + char *p = buf; + uint64_t popcnt, + mask = 0x5555555555555555; + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + vec64 = svand_n_u64_x(pred, svld1_u64(pred, (const uint64_t *) p), mask); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec64)); + p += svcntb(); + + popcnt = svaddv_u64(pred, svadd_u64_x(pred, accum1, accum2)); + + pred = svwhilelt_b8_s32(0, sizeof(buf)); + vec8 = svand_n_u8_x(pred, svld1_u8(pred, (const uint8_t *) p), 0x55); + return (int) (popcnt + svaddv_u8(pred, svcnt_u8_x(pred, vec8))); +} +''' + + if cc.links(prog, name: 'SVE popcount', args: test_c_args) + cdata.set('USE_SVE_POPCNT_WITH_RUNTIME_CHECK', 1) endif endif @@ -2228,17 +2387,26 @@ endif ############################################################### # Select CRC-32C implementation. # -# If we are targeting a processor that has Intel SSE 4.2 instructions, we can -# use the special CRC instructions for calculating CRC-32C. If we're not -# targeting such a processor, but we can nevertheless produce code that uses -# the SSE intrinsics, perhaps with some extra CFLAGS, compile both -# implementations and select which one to use at runtime, depending on whether -# SSE 4.2 is supported by the processor we're running on. +# There are three methods of calculating CRC, in order of increasing +# performance: +# +# 1. The fallback using a lookup table, called slicing-by-8 +# 2. CRC-32C instructions (found in e.g. Intel SSE 4.2 and ARMv8 CRC Extension) +# 3. Algorithms using carryless multiplication instructions +# (e.g. Intel PCLMUL and Arm PMULL) +# +# If we can produce code (via function attributes or additional compiler +# flags) that uses #2 (and possibly #3), we compile all implementations +# and select which one to use at runtime, depending on what is supported +# by the processor we're running on. # -# Similarly, if we are targeting an ARM processor that has the CRC -# instructions that are part of the ARMv8 CRC Extension, use them. And if -# we're not targeting such a processor, but can nevertheless produce code that -# uses the CRC instructions, compile both, and select at runtime. +# If we are targeting a processor that has #2, we can use that without +# runtime selection. +# +# Note that we do not use __attribute__((target("..."))) for the ARM CRC +# instructions because until clang 16, using the ARM intrinsics still requires +# special -march flags. Perhaps we can re-evaluate this decision after some +# time has passed. ############################################################### have_optimized_crc = false @@ -2253,10 +2421,13 @@ if host_cpu == 'x86' or host_cpu == 'x86_64' prog = ''' #include +unsigned int crc; +#if defined(__has_attribute) && __has_attribute (target) +__attribute__((target("sse4.2"))) +#endif int main(void) { - unsigned int crc = 0; crc = _mm_crc32_u8(crc, 0); crc = _mm_crc32_u32(crc, 0); /* return computed value, to prevent the above being optimized away */ @@ -2264,31 +2435,63 @@ int main(void) } ''' - if cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 without -msse4.2', + if not cc.links(prog, name: 'SSE 4.2 CRC32C', args: test_c_args) + # Do not use Intel SSE 4.2 + elif (cc.get_define('__SSE4_2__') != '') # Use Intel SSE 4.2 unconditionally. cdata.set('USE_SSE42_CRC32C', 1) have_optimized_crc = true - elif cc.links(prog, name: '_mm_crc32_u8 and _mm_crc32_u32 with -msse4.2', - args: test_c_args + ['-msse4.2']) + else # Use Intel SSE 4.2, with runtime check. The CPUID instruction is needed for # the runtime check. - cflags_crc += '-msse4.2' cdata.set('USE_SSE42_CRC32C', false) cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1) have_optimized_crc = true endif + # Check if the compiler supports AVX-512 carryless multiplication + # and three-way exclusive-or instructions used for computing CRC. + # AVX-512F is assumed to be supported if the above are. + prog = ''' +#include +__m512i x; +__m512i y; + +#if defined(__has_attribute) && __has_attribute (target) +__attribute__((target("vpclmulqdq,avx512vl"))) +#endif +int main(void) +{ + __m128i z; + + y = _mm512_clmulepi64_epi128(x, y, 0); + z = _mm_ternarylogic_epi64( + _mm512_castsi512_si128(y), + _mm512_extracti32x4_epi32(y, 1), + _mm512_extracti32x4_epi32(y, 2), + 0x96); + /* return computed value, to prevent the above being optimized away */ + return _mm_crc32_u64(0, _mm_extract_epi64(z, 0)); +} +''' + + if cc.links(prog, + name: 'AVX-512 CRC32C', + args: test_c_args) + cdata.set('USE_AVX512_CRC32C_WITH_RUNTIME_CHECK', 1) + endif + endif elif host_cpu == 'arm' or host_cpu == 'aarch64' prog = ''' #include +unsigned int crc; int main(void) { - unsigned int crc = 0; crc = __crc32cb(crc, 0); crc = __crc32ch(crc, 0); crc = __crc32cw(crc, 0); @@ -2304,6 +2507,13 @@ int main(void) # Use ARM CRC Extension unconditionally cdata.set('USE_ARMV8_CRC32C', 1) have_optimized_crc = true + elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc+simd', + args: test_c_args + ['-march=armv8-a+crc+simd']) + # Use ARM CRC Extension, with runtime check + cflags_crc += '-march=armv8-a+crc+simd' + cdata.set('USE_ARMV8_CRC32C', false) + cdata.set('USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK', 1) + have_optimized_crc = true elif cc.links(prog, name: '__crc32cb, __crc32ch, __crc32cw, and __crc32cd with -march=armv8-a+crc', args: test_c_args + ['-march=armv8-a+crc']) # Use ARM CRC Extension, with runtime check @@ -2316,9 +2526,10 @@ int main(void) elif host_cpu == 'loongarch64' prog = ''' +unsigned int crc; + int main(void) { - unsigned int crc = 0; crc = __builtin_loongarch_crcc_w_b_w(0, crc); crc = __builtin_loongarch_crcc_w_h_w(0, crc); crc = __builtin_loongarch_crcc_w_w_w(0, crc); @@ -2378,6 +2589,7 @@ elif host_cpu == 'ppc' or host_cpu == 'ppc64' } int test_adds(int x) { return addi(3, x) + addi(x, 5); } ''', + name: '@0@: "i"(x) when __builtin_constant_p(x)'.format(host_cpu), args: test_c_args) cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1) endif @@ -2399,9 +2611,7 @@ header_checks = [ 'execinfo.h', 'getopt.h', 'ifaddrs.h', - 'langinfo.h', 'mbarrier.h', - 'stdbool.h', 'strings.h', 'sys/epoll.h', 'sys/event.h', @@ -2412,6 +2622,7 @@ header_checks = [ 'sys/ucred.h', 'termios.h', 'ucred.h', + 'xlocale.h', ] foreach header : header_checks @@ -2433,6 +2644,7 @@ decl_checks = [ ['strlcpy', 'string.h'], ['strnlen', 'string.h'], ['strsep', 'string.h'], + ['timingsafe_bcmp', 'string.h'], ] # Need to check for function declarations for these functions, because @@ -2441,6 +2653,8 @@ decl_checks = [ decl_checks += [ ['preadv', 'sys/uio.h'], ['pwritev', 'sys/uio.h'], + ['strchrnul', 'string.h'], + ['memset_s', 'string.h', '#define __STDC_WANT_LIB_EXT1__ 1'], ] # Check presence of some optional LLVM functions. @@ -2454,11 +2668,28 @@ endif foreach c : decl_checks func = c.get(0) header = c.get(1) - args = c.get(2, {}) + prologue = c.get(2, '') + args = c.get(3, {}) varname = 'HAVE_DECL_' + func.underscorify().to_upper() - found = cc.has_header_symbol(header, func, - args: test_c_args, include_directories: postgres_inc, + found = cc.compiles(''' +@0@ +#include <@1@> + +int main() +{ +#ifndef @2@ + (void) @2@; +#endif + +return 0; +} +'''.format(prologue, header, func), + name: 'test whether @0@ is declared'.format(func), + # need to add cflags_warn to get at least + # -Werror=unguarded-availability-new if applicable + args: test_c_args + cflags_warn, + include_directories: postgres_inc, kwargs: args) cdata.set10(varname, found, description: '''Define to 1 if you have the declaration of `@0@', and to 0 if you @@ -2555,18 +2786,9 @@ else cdata.set('STRERROR_R_INT', false) endif -# Find the right header file for the locale_t type. macOS needs xlocale.h; -# standard is locale.h, but glibc <= 2.25 also had an xlocale.h file that -# we should not use so we check the standard header first. MSVC has a -# replacement defined in src/include/port/win32_port.h. -if not cc.has_type('locale_t', prefix: '#include ') and \ - cc.has_type('locale_t', prefix: '#include ') - cdata.set('LOCALE_T_IN_XLOCALE', 1) -endif - # Check if the C compiler understands typeof or a variant. Define # HAVE_TYPEOF if so, and define 'typeof' to the actual key word. -foreach kw : ['typeof', '__typeof__', 'decltype'] +foreach kw : ['typeof', '__typeof__'] if cc.compiles(''' int main(void) { @@ -2576,7 +2798,7 @@ int main(void) return y; } '''.format(kw), - name: 'typeof()', + name: kw, args: test_c_args, include_directories: postgres_inc) cdata.set('HAVE_TYPEOF', 1) @@ -2589,29 +2811,6 @@ int main(void) endforeach -# Try to find a declaration for wcstombs_l(). It might be in stdlib.h -# (following the POSIX requirement for wcstombs()), or in locale.h, or in -# xlocale.h. If it's in the latter, define WCSTOMBS_L_IN_XLOCALE. -wcstombs_l_test = ''' -#include -#include -@0@ - -void main(void) -{ -#ifndef wcstombs_l - (void) wcstombs_l; -#endif -} -''' -if (not cc.compiles(wcstombs_l_test.format(''), - name: 'wcstombs_l') and - cc.compiles(wcstombs_l_test.format('#include '), - name: 'wcstombs_l in xlocale.h')) - cdata.set('WCSTOMBS_L_IN_XLOCALE', 1) -endif - - # MSVC doesn't cope well with defining restrict to __restrict, the spelling it # understands, because it conflicts with __declspec(restrict). Therefore we # define pg_restrict to the appropriate definition, which presumably won't @@ -2663,7 +2862,6 @@ endif # XXX: Might be worth conditioning some checks on the OS, to avoid doing # unnecessary checks over and over, particularly on windows. func_checks = [ - ['_configthreadlocale', {'skip': host_system != 'windows'}], ['backtrace_symbols', {'dependencies': [execinfo_dep]}], ['clock_gettime', {'dependencies': [rt_dep], 'define': false}], ['copyfile'], @@ -2672,7 +2870,9 @@ func_checks = [ # when enabling asan the dlopen check doesn't notice that -ldl is actually # required. Just checking for dlsym() ought to suffice. ['dlsym', {'dependencies': [dl_dep], 'define': false}], + ['elf_aux_info'], ['explicit_bzero'], + ['getauxval'], ['getifaddrs'], ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt}], ['getopt_long', {'dependencies': [getopt_dep, gnugetopt_dep], 'skip': always_replace_getopt_long}], @@ -2681,8 +2881,8 @@ func_checks = [ ['inet_aton'], ['inet_pton'], ['kqueue'], + ['localeconv_l'], ['mbstowcs_l'], - ['memset_s'], ['mkdtemp'], ['posix_fadvise'], ['posix_fallocate'], @@ -2696,7 +2896,6 @@ func_checks = [ ['shm_unlink', {'dependencies': [rt_dep], 'define': false}], ['shmget', {'dependencies': [cygipc_dep], 'define': false}], ['socket', {'dependencies': [socket_dep], 'define': false}], - ['strchrnul'], ['strerror_r', {'dependencies': [thread_dep]}], ['strlcat'], ['strlcpy'], @@ -2705,6 +2904,7 @@ func_checks = [ ['strsignal'], ['sync_file_range'], ['syncfs'], + ['timingsafe_bcmp'], ['uselocale'], ['wcstombs_l'], ] @@ -3042,7 +3242,7 @@ frontend_common_code = declare_dependency( compile_args: ['-DFRONTEND'], include_directories: [postgres_inc], sources: generated_headers, - dependencies: [os_deps, zlib, zstd], + dependencies: [os_deps, zlib, zstd, lz4], ) backend_common_code = declare_dependency( @@ -3075,6 +3275,16 @@ frontend_shlib_code = declare_dependency( dependencies: [shlib_code, os_deps, libintl], ) +# For frontend code that doesn't use fe_utils - this mainly exists for libpq's +# tests, which are defined before fe_utils is defined, as fe_utils depends on +# libpq. +frontend_no_fe_utils_code = declare_dependency( + include_directories: [postgres_inc], + link_with: [common_static, pgport_static], + sources: generated_headers, + dependencies: [os_deps, libintl], +) + # Dependencies both for static and shared libpq libpq_deps += [ thread_dep, @@ -3085,9 +3295,14 @@ libpq_deps += [ ssl, ] +libpq_oauth_deps += [ + libcurl, +] + subdir('src/interfaces/libpq') -# fe_utils depends on libpq +# fe_utils and libpq-oauth depends on libpq subdir('src/fe_utils') +subdir('src/interfaces/libpq-oauth') # for frontend binaries frontend_code = declare_dependency( @@ -3105,6 +3320,8 @@ backend_both_deps += [ icu_i18n, ldap, libintl, + libnuma, + liburing, libxml, lz4, pam, @@ -3142,7 +3359,6 @@ subdir('src') subdir('contrib') subdir('src/test') -subdir('src/interfaces/libpq/test') subdir('src/interfaces/ecpg/test') subdir('doc/src/sgml') @@ -3236,24 +3452,30 @@ if libintl.found() and meson.version().version_compare('>=0.60') endif -all_built = [ +# all targets that 'meson install' needs +installed_targets = [ backend_targets, bin_targets, libpq_st, pl_targets, contrib_targets, nls_mo_targets, - testprep_targets, ecpg_targets, ] +# all targets that require building code +all_built = [ + installed_targets, + testprep_targets, +] + # Meson's default install target is quite verbose. Provide one that is quiet. install_quiet = custom_target('install-quiet', output: 'install-quiet', build_always_stale: true, build_by_default: false, command: [meson_bin, meson_args, 'install', '--quiet', '--no-rebuild'], - depends: all_built, + depends: installed_targets, ) # Target to install files used for tests, which aren't installed by default @@ -3308,6 +3530,7 @@ test('tmp_install', priority: setup_tests_priority, timeout: 300, is_parallel: false, + depends: installed_targets, suite: ['setup']) test('install_test_files', @@ -3332,11 +3555,8 @@ test_initdb_template = meson.build_root() / 'tmp_install' / 'initdb-template' test_env.set('PG_REGRESS', pg_regress.full_path()) test_env.set('REGRESS_SHLIB', regress_module.full_path()) test_env.set('INITDB_TEMPLATE', test_initdb_template) - -# Test suites that are not safe by default but can be run if selected -# by the user via the whitespace-separated list in variable PG_TEST_EXTRA. -# Export PG_TEST_EXTRA so it can be checked in individual tap tests. -test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA')) +# for Cluster.pm's portlock logic +test_env.set('top_builddir', meson.build_root()) # Add the temporary installation to the library search path on platforms where # that works (everything but windows, basically). On windows everything @@ -3401,6 +3621,11 @@ foreach test_dir : tests testwrap, '--basedir', meson.build_root(), '--srcdir', test_dir['sd'], + # Some test suites are not run by default but can be run if selected by the + # user via variable PG_TEST_EXTRA. Pass configuration time value of + # PG_TEST_EXTRA as an argument to testwrap so that it can be overridden by + # run time value, if any. + '--pg-test-extra', get_option('PG_TEST_EXTRA'), ] foreach kind, v : test_dir @@ -3520,6 +3745,8 @@ foreach test_dir : tests # also test/ for non-installed test binaries built separately. env = test_env env.prepend('PATH', temp_install_bindir, test_dir['bd'], test_dir['bd'] / 'test') + temp_install_datadir = '@0@@1@'.format(test_install_destdir, dir_prefix / dir_data) + env.set('share_contrib_dir', temp_install_datadir / 'contrib') foreach name, value : t.get('env', {}) env.set(name, value) @@ -3749,6 +3976,9 @@ if meson.version().version_compare('>=0.57') 'gss': gssapi, 'icu': icu, 'ldap': ldap, + 'libcurl': libcurl, + 'libnuma': libnuma, + 'liburing': liburing, 'libxml': libxml, 'libxslt': libxslt, 'llvm': llvm, @@ -3756,7 +3986,7 @@ if meson.version().version_compare('>=0.57') 'nls': libintl, 'openssl': ssl, 'pam': pam, - 'plperl': perl_dep, + 'plperl': [perl_dep, perlversion], 'plpython': python3_dep, 'pltcl': tcl_dep, 'readline': readline, @@ -3767,6 +3997,7 @@ if meson.version().version_compare('>=0.57') 'zstd': zstd, }, section: 'External libraries', + list_sep: ' ', ) endif diff --git a/meson_options.txt b/meson_options.txt index 246cecf382712..06bf5627d3c03 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Data layout influencing options @@ -47,13 +47,7 @@ option('injection_points', type: 'boolean', value: false, description: 'Enable injection points') option('PG_TEST_EXTRA', type: 'string', value: '', - description: 'Enable selected extra tests') - -option('atomics', type: 'boolean', value: true, - description: 'Use atomic operations') - -option('spinlocks', type: 'boolean', value: true, - description: 'Use spinlocks') + description: 'Enable selected extra tests. Overridden by PG_TEST_EXTRA environment variable.') option('PG_GIT_REVISION', type: 'string', value: 'HEAD', description: 'git revision to be packaged by pgdist target') @@ -106,9 +100,18 @@ option('icu', type: 'feature', value: 'auto', option('ldap', type: 'feature', value: 'auto', description: 'LDAP support') +option('libcurl', type : 'feature', value: 'auto', + description: 'libcurl support') + option('libedit_preferred', type: 'boolean', value: false, description: 'Prefer BSD Libedit over GNU Readline') +option('libnuma', type: 'feature', value: 'auto', + description: 'NUMA support') + +option('liburing', type : 'feature', value: 'auto', + description: 'io_uring support, for asynchronous I/O') + option('libxml', type: 'feature', value: 'auto', description: 'XML support') diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 83b91fe916738..04952b533ded9 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -87,9 +87,19 @@ endif # not PGXS # # In a PGXS build, we cannot use the values inserted into Makefile.global # by configure, since the installation tree may have been relocated. -# Instead get the path values from pg_config. +# Instead get the path values from pg_config. But users can specify +# prefix explicitly, if they want to select their own installation +# location. -ifndef PGXS +ifdef PGXS +# Extension makefiles should set PG_CONFIG, but older ones might not +ifndef PG_CONFIG +PG_CONFIG = pg_config +endif +endif + +# This means: if ((not PGXS) or prefix) +ifneq (,$(if $(PGXS),,1)$(prefix)) # Note that prefix, exec_prefix, and datarootdir aren't defined in a PGXS build; # makefiles may only use the derived variables such as bindir. @@ -147,11 +157,6 @@ localedir := @localedir@ else # PGXS case -# Extension makefiles should set PG_CONFIG, but older ones might not -ifndef PG_CONFIG -PG_CONFIG = pg_config -endif - bindir := $(shell $(PG_CONFIG) --bindir) datadir := $(shell $(PG_CONFIG) --sharedir) sysconfdir := $(shell $(PG_CONFIG) --sysconfdir) @@ -190,6 +195,9 @@ with_systemd = @with_systemd@ with_gssapi = @with_gssapi@ with_krb_srvnam = @with_krb_srvnam@ with_ldap = @with_ldap@ +with_libcurl = @with_libcurl@ +with_libnuma = @with_libnuma@ +with_liburing = @with_liburing@ with_libxml = @with_libxml@ with_libxslt = @with_libxslt@ with_llvm = @with_llvm@ @@ -216,6 +224,12 @@ krb_srvtab = @krb_srvtab@ ICU_CFLAGS = @ICU_CFLAGS@ ICU_LIBS = @ICU_LIBS@ +LIBNUMA_CFLAGS = @LIBNUMA_CFLAGS@ +LIBNUMA_LIBS = @LIBNUMA_LIBS@ + +LIBURING_CFLAGS = @LIBURING_CFLAGS@ +LIBURING_LIBS = @LIBURING_LIBS@ + TCLSH = @TCLSH@ TCL_LIBS = @TCL_LIBS@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ @@ -240,7 +254,7 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ PG_SYSROOT = @PG_SYSROOT@ -override CPPFLAGS := $(ICU_CFLAGS) $(CPPFLAGS) +override CPPFLAGS := $(ICU_CFLAGS) $(LIBNUMA_CFLAGS) $(LIBURING_CFLAGS) $(CPPFLAGS) ifdef PGXS override CPPFLAGS := -I$(includedir_server) -I$(includedir_internal) $(CPPFLAGS) @@ -262,10 +276,9 @@ CFLAGS_SL_MODULE = @CFLAGS_SL_MODULE@ CXXFLAGS_SL_MODULE = @CXXFLAGS_SL_MODULE@ CFLAGS_UNROLL_LOOPS = @CFLAGS_UNROLL_LOOPS@ CFLAGS_VECTORIZE = @CFLAGS_VECTORIZE@ -CFLAGS_POPCNT = @CFLAGS_POPCNT@ CFLAGS_CRC = @CFLAGS_CRC@ -CFLAGS_XSAVE = @CFLAGS_XSAVE@ PERMIT_DECLARATION_AFTER_STATEMENT = @PERMIT_DECLARATION_AFTER_STATEMENT@ +PERMIT_MISSING_VARIABLE_DECLARATIONS = @PERMIT_MISSING_VARIABLE_DECLARATIONS@ CXXFLAGS = @CXXFLAGS@ LLVM_CPPFLAGS = @LLVM_CPPFLAGS@ @@ -334,6 +347,9 @@ perl_embed_ldflags = @perl_embed_ldflags@ AWK = @AWK@ LN_S = @LN_S@ +LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ +LIBCURL_LDFLAGS = @LIBCURL_LDFLAGS@ +LIBCURL_LDLIBS = @LIBCURL_LDLIBS@ MSGFMT = @MSGFMT@ MSGFMT_FLAGS = @MSGFMT_FLAGS@ MSGMERGE = @MSGMERGE@ @@ -358,10 +374,10 @@ DOWNLOAD = wget -O $@ --no-use-server-timestamps # Pick a release from here: . Note # that the most recent release listed there is often a pre-release; # don't pick that one, except for testing. -UNICODE_VERSION = 15.1.0 +UNICODE_VERSION = 16.0.0 # Pick a release from here: -CLDR_VERSION = 45 +CLDR_VERSION = 47 # Tree-wide build support @@ -455,6 +471,7 @@ cd $(srcdir) && \ PATH="$(bindir):$(CURDIR):$$PATH" \ PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' \ PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' \ + share_contrib_dir='$(DESTDIR)$(datadir)/$(datamoduledir)' \ $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl) endef else # PGXS case @@ -482,6 +499,7 @@ cd $(srcdir) && \ $(with_temp_install) \ PGPORT='6$(DEF_PGPORT)' top_builddir='$(CURDIR)/$(top_builddir)' \ PG_REGRESS='$(CURDIR)/$(top_builddir)/src/test/regress/pg_regress' \ + share_contrib_dir='$(abs_top_builddir)/tmp_install$(datadir)/$(datamoduledir)' \ $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl) endef @@ -641,6 +659,16 @@ submake-libpgfeutils: | submake-generated-headers # # Testing support +# Store any configure-time setting for PG_TEST_EXTRA, but let environment +# variables override it to maintain the historical behavior of the tests. +# (Standard `=` assignment would require devs to use a commandline option.) +# This is skipped in PGXS mode to keep the setting from escaping into other +# projects' builds. +ifndef PGXS +PG_TEST_EXTRA ?= @PG_TEST_EXTRA@ +export PG_TEST_EXTRA +endif + ifneq ($(USE_MODULE_DB),) PL_TESTDB = pl_regression_$(NAME) ifneq ($(MODULE_big),) @@ -761,9 +789,6 @@ LIBOBJS = @LIBOBJS@ # files needed for the chosen CRC-32C implementation PG_CRC32C_OBJS = @PG_CRC32C_OBJS@ -# files needed for the chosen popcount implementation -PG_POPCNT_OBJS = @PG_POPCNT_OBJS@ - LIBS := -lpgcommon -lpgport $(LIBS) # to make ws2_32.lib the last library @@ -782,7 +807,6 @@ TAS = @TAS@ %.c: %.l $(FLEX) $(if $(FLEX_NO_BACKUP),-b) $(FLEXFLAGS) -o'$@' $< @$(if $(FLEX_NO_BACKUP),if [ `wc -l &2; exit 1; fi) - $(if $(FLEX_FIX_WARNING),$(PERL) $(top_srcdir)/src/tools/fix-old-flex-code.pl '$@') %.c: %.y $(if $(BISON_CHECK_CMD),$(BISON_CHECK_CMD)) @@ -834,12 +858,6 @@ $(top_builddir)/src/include/pg_config.h: $(top_builddir)/src/include/stamp-h ; $(top_builddir)/src/include/stamp-h: $(top_srcdir)/src/include/pg_config.h.in $(top_builddir)/config.status cd $(top_builddir) && ./config.status src/include/pg_config.h -# Also remake pg_config_ext.h from pg_config_ext.h.in, same logic as above. -$(top_builddir)/src/include/pg_config_ext.h: $(top_builddir)/src/include/stamp-ext-h ; - -$(top_builddir)/src/include/stamp-ext-h: $(top_srcdir)/src/include/pg_config_ext.h.in $(top_builddir)/config.status - cd $(top_builddir) && ./config.status src/include/pg_config_ext.h - # Also remake ecpg_config.h from ecpg_config.h.in if the latter changed, same # logic as above. $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h: $(top_builddir)/src/interfaces/ecpg/include/stamp-h ; diff --git a/src/Makefile.shlib b/src/Makefile.shlib index fa81f6ffdd6d9..3825af5b22872 100644 --- a/src/Makefile.shlib +++ b/src/Makefile.shlib @@ -112,7 +112,7 @@ ifeq ($(PORTNAME), darwin) ifneq ($(SO_MAJOR_VERSION), 0) version_link = -compatibility_version $(SO_MAJOR_VERSION) -current_version $(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) endif - LINK.shared = $(COMPILER) -dynamiclib -install_name '$(libdir)/lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX)' $(version_link) $(exported_symbols_list) + LINK.shared = $(COMPILER) -dynamiclib -install_name '$(libdir)/lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX)' $(version_link) shlib = lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX) shlib_major = lib$(NAME).$(SO_MAJOR_VERSION)$(DLSUFFIX) else @@ -122,7 +122,7 @@ ifeq ($(PORTNAME), darwin) BUILD.exports = $(AWK) '/^[^\#]/ {printf "_%s\n",$$1}' $< >$@ exports_file = $(SHLIB_EXPORTS:%.txt=%.list) ifneq (,$(exports_file)) - exported_symbols_list = -exported_symbols_list $(exports_file) + LINK.shared += -exported_symbols_list $(exports_file) endif endif diff --git a/src/backend/Makefile b/src/backend/Makefile index 84302cc6dab7b..7344c8c7f5c65 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -2,7 +2,7 @@ # # Makefile for the postgres backend # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/Makefile @@ -43,9 +43,10 @@ OBJS = \ $(top_builddir)/src/common/libpgcommon_srv.a \ $(top_builddir)/src/port/libpgport_srv.a -# We put libpgport and libpgcommon into OBJS, so remove it from LIBS; also add -# libldap and ICU -LIBS := $(filter-out -lpgport -lpgcommon, $(LIBS)) $(LDAP_LIBS_BE) $(ICU_LIBS) +# We put libpgport and libpgcommon into OBJS, so remove it from LIBS. +LIBS := $(filter-out -lpgport -lpgcommon, $(LIBS)) +# The backend conditionally needs libraries that most executables don't need. +LIBS += $(LDAP_LIBS_BE) $(ICU_LIBS) $(LIBURING_LIBS) # The backend doesn't need everything that's in LIBS, however LIBS := $(filter-out -lreadline -ledit -ltermcap -lncurses -lcurses, $(LIBS)) diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 6467bed604a05..4204088fa0d7d 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -4,7 +4,7 @@ * * See src/backend/access/brin/README for details. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -33,7 +33,7 @@ #include "postmaster/autovacuum.h" #include "storage/bufmgr.h" #include "storage/freespace.h" -#include "tcop/tcopprot.h" /* pgrminclude ignore */ +#include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/datum.h" #include "utils/fmgrprotos.h" @@ -67,6 +67,9 @@ typedef struct BrinShared BlockNumber pagesPerRange; int scantuplesortstates; + /* Query ID, for report in worker processes */ + int64 queryid; + /* * workersdonecv is used to monitor the progress of workers. All parallel * participants must indicate that they are done before leader can use @@ -253,6 +256,9 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BRIN_PROCNUM_OPTIONS; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; @@ -279,6 +285,7 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = brinvacuumcleanup; amroutine->amcanreturn = NULL; amroutine->amcostestimate = brincostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = brinoptions; amroutine->amproperty = NULL; amroutine->ambuildphasename = NULL; @@ -294,6 +301,8 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } @@ -505,16 +514,18 @@ brininsertcleanup(Relation index, IndexInfo *indexInfo) BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache; /* bail out if cache not initialized */ - if (indexInfo->ii_AmCache == NULL) + if (bistate == NULL) return; + /* do this first to avoid dangling pointer if we fail partway through */ + indexInfo->ii_AmCache = NULL; + /* * Clean up the revmap. Note that the brinDesc has already been cleaned up * as part of its own memory context. */ brinRevmapTerminate(bistate->bis_rmAccess); - bistate->bis_rmAccess = NULL; - bistate->bis_desc = NULL; + pfree(bistate); } /* @@ -563,7 +574,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) BrinOpaque *opaque; BlockNumber nblocks; BlockNumber heapBlk; - int totalpages = 0; + int64 totalpages = 0; FmgrInfo *consistentFn; MemoryContext oldcxt; MemoryContext perRangeCxt; @@ -581,6 +592,8 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) opaque = (BrinOpaque *) scan->opaque; bdesc = opaque->bo_bdesc; pgstat_count_index_scan(idxRel); + if (scan->instrument) + scan->instrument->nsearches++; /* * We need to know the size of the table so that we know how long to @@ -955,8 +968,7 @@ brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, */ if (scankey && scan->numberOfKeys > 0) - memmove(scan->keyData, scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); } /* @@ -1130,7 +1142,7 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo) xlrec.pagesPerRange = BrinGetPagesPerRange(index); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBrinCreateIdx); + XLogRegisterData(&xlrec, SizeOfBrinCreateIdx); XLogRegisterBuffer(0, meta, REGBUF_WILL_INIT | REGBUF_STANDARD); recptr = XLogInsert(RM_BRIN_ID, XLOG_BRIN_CREATE_INDEX); @@ -1219,7 +1231,7 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo) * generate summary for the same range twice). */ reltuples = table_index_build_scan(heap, index, indexInfo, false, true, - brinbuildCallback, (void *) state, NULL); + brinbuildCallback, state, NULL); /* * process the final batch @@ -1388,8 +1400,7 @@ brin_summarize_range(PG_FUNCTION_ARGS) if (heapBlk64 > BRIN_ALL_BLOCKRANGES || heapBlk64 < 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("block number out of range: %lld", - (long long) heapBlk64))); + errmsg("block number out of range: %" PRId64, heapBlk64))); heapBlk = (BlockNumber) heapBlk64; /* @@ -1496,8 +1507,8 @@ brin_desummarize_range(PG_FUNCTION_ARGS) if (heapBlk64 > MaxBlockNumber || heapBlk64 < 0) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("block number out of range: %lld", - (long long) heapBlk64))); + errmsg("block number out of range: %" PRId64, + heapBlk64))); heapBlk = (BlockNumber) heapBlk64; /* @@ -1805,7 +1816,7 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel, state->bs_currRangeStart = heapBlk; table_index_build_range_scan(heapRel, state->bs_irel, indexInfo, false, true, false, heapBlk, scanNumBlks, - brinbuildCallback, (void *) state, NULL); + brinbuildCallback, state, NULL); /* * Now we update the values obtained by the scan with the placeholder @@ -2448,6 +2459,7 @@ _brin_begin_parallel(BrinBuildState *buildstate, Relation heap, Relation index, brinshared->isconcurrent = isconcurrent; brinshared->scantuplesortstates = scantuplesortstates; brinshared->pagesPerRange = buildstate->bs_pagesPerRange; + brinshared->queryid = pgstat_get_my_query_id(); ConditionVariableInit(&brinshared->workersdonecv); SpinLockInit(&brinshared->mutex); @@ -2891,6 +2903,9 @@ _brin_parallel_build_main(dsm_segment *seg, shm_toc *toc) indexLockmode = RowExclusiveLock; } + /* Track query ID */ + pgstat_report_query_id(brinshared->queryid, false); + /* Open relations within worker */ heapRel = table_open(brinshared->heaprelid, heapLockmode); indexRel = index_open(brinshared->indexrelid, indexLockmode); diff --git a/src/backend/access/brin/brin_bloom.c b/src/backend/access/brin/brin_bloom.c index f94e2b0bfbd95..82b425ce37daa 100644 --- a/src/backend/access/brin/brin_bloom.c +++ b/src/backend/access/brin/brin_bloom.c @@ -2,7 +2,7 @@ * brin_bloom.c * Implementation of Bloom opclass for BRIN * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -124,7 +124,6 @@ #include "access/htup_details.h" #include "access/reloptions.h" #include "catalog/pg_am.h" -#include "catalog/pg_amop.h" #include "catalog/pg_type.h" #include "common/hashfn.h" #include "utils/fmgrprotos.h" @@ -439,7 +438,6 @@ typedef struct BloomOpaque * consistency. We may need additional procs in the future. */ FmgrInfo extra_procinfos[BLOOM_MAX_PROCNUMS]; - bool extra_proc_missing[BLOOM_MAX_PROCNUMS]; } BloomOpaque; static FmgrInfo *bloom_get_procinfo(BrinDesc *bdesc, uint16 attno, @@ -694,6 +692,17 @@ brin_bloom_union(PG_FUNCTION_ARGS) /* update the number of bits set in the filter */ filter_a->nbits_set = pg_popcount((const char *) filter_a->data, nbytes); + /* if we decompressed filter_a, update the summary */ + if (PointerGetDatum(filter_a) != col_a->bv_values[0]) + { + pfree(DatumGetPointer(col_a->bv_values[0])); + col_a->bv_values[0] = PointerGetDatum(filter_a); + } + + /* also free filter_b, if it was decompressed */ + if (PointerGetDatum(filter_b) != col_b->bv_values[0]) + pfree(filter_b); + PG_RETURN_VOID(); } @@ -715,27 +724,19 @@ bloom_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum) */ opaque = (BloomOpaque *) bdesc->bd_info[attno - 1]->oi_opaque; - /* - * If we already searched for this proc and didn't find it, don't bother - * searching again. - */ - if (opaque->extra_proc_missing[basenum]) - return NULL; - if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid) { if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno, procnum))) - { fmgr_info_copy(&opaque->extra_procinfos[basenum], index_getprocinfo(bdesc->bd_index, attno, procnum), bdesc->bd_context); - } else - { - opaque->extra_proc_missing[basenum] = true; - return NULL; - } + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg_internal("invalid opclass definition"), + errdetail_internal("The operator class is missing support function %d for column %d.", + procnum, attno)); } return &opaque->extra_procinfos[basenum]; diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 750276998c5a1..b86ca5744a348 100644 --- a/src/backend/access/brin/brin_inclusion.c +++ b/src/backend/access/brin/brin_inclusion.c @@ -16,7 +16,7 @@ * writing is the INET type, where IPv6 values cannot be merged with IPv4 * values. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -82,7 +82,7 @@ typedef struct InclusionOpaque } InclusionOpaque; static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, - uint16 procnum); + uint16 procnum, bool missing_ok); static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, uint16 strategynum); @@ -146,12 +146,12 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) Datum result; bool new = false; AttrNumber attno; - Form_pg_attribute attr; + CompactAttribute *attr; Assert(!isnull); attno = column->bv_attno; - attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); + attr = TupleDescCompactAttr(bdesc->bd_tupdesc, attno - 1); /* * If the recorded value is null, copy the new value (which we know to be @@ -179,7 +179,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) * new value for emptiness; if it returns true, we need to set the * "contains empty" flag in the element (unless already set). */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_EMPTY, true); if (finfo != NULL && DatumGetBool(FunctionCall1Coll(finfo, colloid, newval))) { if (!DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY])) @@ -195,7 +195,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) PG_RETURN_BOOL(true); /* Check if the new value is already contained. */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_CONTAINS, true); if (finfo != NULL && DatumGetBool(FunctionCall2Coll(finfo, colloid, column->bv_values[INCLUSION_UNION], @@ -210,7 +210,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) * it's not going to be used any longer. However, the BRIN framework * doesn't allow for the value not being present. Improve someday. */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE, true); if (finfo != NULL && !DatumGetBool(FunctionCall2Coll(finfo, colloid, column->bv_values[INCLUSION_UNION], @@ -221,8 +221,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) } /* Finally, merge the new value to the existing union. */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE); - Assert(finfo != NULL); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE, false); result = FunctionCall2Coll(finfo, colloid, column->bv_values[INCLUSION_UNION], newval); if (!attr->attbyval && @@ -479,7 +478,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS) BrinValues *col_b = (BrinValues *) PG_GETARG_POINTER(2); Oid colloid = PG_GET_COLLATION(); AttrNumber attno; - Form_pg_attribute attr; + CompactAttribute *attr; FmgrInfo *finfo; Datum result; @@ -487,7 +486,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS) Assert(!col_a->bv_allnulls && !col_b->bv_allnulls); attno = col_a->bv_attno; - attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); + attr = TupleDescCompactAttr(bdesc->bd_tupdesc, attno - 1); /* If B includes empty elements, mark A similarly, if needed. */ if (!DatumGetBool(col_a->bv_values[INCLUSION_CONTAINS_EMPTY]) && @@ -506,7 +505,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS) } /* Check if A and B are mergeable; if not, mark A unmergeable. */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGEABLE, true); if (finfo != NULL && !DatumGetBool(FunctionCall2Coll(finfo, colloid, col_a->bv_values[INCLUSION_UNION], @@ -517,8 +516,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS) } /* Finally, merge B to A. */ - finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE); - Assert(finfo != NULL); + finfo = inclusion_get_procinfo(bdesc, attno, PROCNUM_MERGE, false); result = FunctionCall2Coll(finfo, colloid, col_a->bv_values[INCLUSION_UNION], col_b->bv_values[INCLUSION_UNION]); @@ -539,10 +537,12 @@ brin_inclusion_union(PG_FUNCTION_ARGS) * Cache and return inclusion opclass support procedure * * Return the procedure corresponding to the given function support number - * or null if it is not exists. + * or null if it is not exists. If missing_ok is true and the procedure + * isn't set up for this opclass, return NULL instead of raising an error. */ static FmgrInfo * -inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum) +inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum, + bool missing_ok) { InclusionOpaque *opaque; uint16 basenum = procnum - PROCNUM_BASE; @@ -564,13 +564,18 @@ inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum) { if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno, procnum))) - { fmgr_info_copy(&opaque->extra_procinfos[basenum], index_getprocinfo(bdesc->bd_index, attno, procnum), bdesc->bd_context); - } else { + if (!missing_ok) + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg_internal("invalid opclass definition"), + errdetail_internal("The operator class is missing support function %d for column %d.", + procnum, attno)); + opaque->extra_proc_missing[basenum] = true; return NULL; } diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index caf6991eb1b01..d21ab3a668cce 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -2,7 +2,7 @@ * brin_minmax.c * Implementation of Min/Max opclass for BRIN * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c index e5d95de5d84a7..0d1507a2a3624 100644 --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -2,7 +2,7 @@ * brin_minmax_multi.c * Implementation of Multi Min/Max opclass for BRIN * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -111,7 +111,6 @@ typedef struct MinmaxMultiOpaque { FmgrInfo extra_procinfos[MINMAX_MAX_PROCNUMS]; - bool extra_proc_missing[MINMAX_MAX_PROCNUMS]; Oid cached_subtype; FmgrInfo strategy_procinfos[BTMaxStrategyNumber]; } MinmaxMultiOpaque; @@ -413,7 +412,7 @@ AssertCheckRanges(Ranges *ranges, FmgrInfo *cmpFn, Oid colloid) Assert(bsearch_arg(&value, &ranges->values[2 * ranges->nranges], ranges->nsorted, sizeof(Datum), - compare_values, (void *) &cxt) == NULL); + compare_values, &cxt) == NULL); } } #endif @@ -550,7 +549,7 @@ range_deduplicate_values(Ranges *range) /* same as preceding value, so store it */ if (compare_values(&range->values[start + i - 1], &range->values[start + i], - (void *) &cxt) == 0) + &cxt) == 0) continue; range->values[start + n] = range->values[start + i]; @@ -1085,7 +1084,7 @@ range_contains_value(BrinDesc *bdesc, Oid colloid, if (bsearch_arg(&newval, &ranges->values[2 * ranges->nranges], ranges->nsorted, sizeof(Datum), - compare_values, (void *) &cxt) != NULL) + compare_values, &cxt) != NULL) return true; } else @@ -1206,7 +1205,7 @@ sort_expanded_ranges(FmgrInfo *cmp, Oid colloid, for (i = 1; i < neranges; i++) { /* if the current range is equal to the preceding one, do nothing */ - if (!compare_expanded_ranges(&eranges[i - 1], &eranges[i], (void *) &cxt)) + if (!compare_expanded_ranges(&eranges[i - 1], &eranges[i], &cxt)) continue; /* otherwise, copy it to n-th place (if not already there) */ @@ -2872,27 +2871,19 @@ minmax_multi_get_procinfo(BrinDesc *bdesc, uint16 attno, uint16 procnum) */ opaque = (MinmaxMultiOpaque *) bdesc->bd_info[attno - 1]->oi_opaque; - /* - * If we already searched for this proc and didn't find it, don't bother - * searching again. - */ - if (opaque->extra_proc_missing[basenum]) - return NULL; - if (opaque->extra_procinfos[basenum].fn_oid == InvalidOid) { if (RegProcedureIsValid(index_getprocid(bdesc->bd_index, attno, procnum))) - { fmgr_info_copy(&opaque->extra_procinfos[basenum], index_getprocinfo(bdesc->bd_index, attno, procnum), bdesc->bd_context); - } else - { - opaque->extra_proc_missing[basenum] = true; - return NULL; - } + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg_internal("invalid opclass definition"), + errdetail_internal("The operator class is missing support function %d for column %d.", + procnum, attno)); } return &opaque->extra_procinfos[basenum]; diff --git a/src/backend/access/brin/brin_pageops.c b/src/backend/access/brin/brin_pageops.c index b69217c1ec6d5..6d8dd1512d6a7 100644 --- a/src/backend/access/brin/brin_pageops.c +++ b/src/backend/access/brin/brin_pageops.c @@ -2,7 +2,7 @@ * brin_pageops.c * Page-handling routines for BRIN indexes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -190,10 +190,10 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange, xlrec.offnum = oldoff; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBrinSamepageUpdate); + XLogRegisterData(&xlrec, SizeOfBrinSamepageUpdate); XLogRegisterBuffer(0, oldbuf, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) unconstify(BrinTuple *, newtup), newsz); + XLogRegisterBufData(0, newtup, newsz); recptr = XLogInsert(RM_BRIN_ID, info); @@ -282,10 +282,10 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange, XLogBeginInsert(); /* new page */ - XLogRegisterData((char *) &xlrec, SizeOfBrinUpdate); + XLogRegisterData(&xlrec, SizeOfBrinUpdate); XLogRegisterBuffer(0, newbuf, REGBUF_STANDARD | (extended ? REGBUF_WILL_INIT : 0)); - XLogRegisterBufData(0, (char *) unconstify(BrinTuple *, newtup), newsz); + XLogRegisterBufData(0, newtup, newsz); /* revmap page */ XLogRegisterBuffer(1, revmapbuf, 0); @@ -435,10 +435,10 @@ brin_doinsert(Relation idxrel, BlockNumber pagesPerRange, xlrec.offnum = off; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBrinInsert); + XLogRegisterData(&xlrec, SizeOfBrinInsert); XLogRegisterBuffer(0, *buffer, REGBUF_STANDARD | (extended ? REGBUF_WILL_INIT : 0)); - XLogRegisterBufData(0, (char *) tup, itemsz); + XLogRegisterBufData(0, tup, itemsz); XLogRegisterBuffer(1, revmapbuf, 0); diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c index 5a9ed40ab64a2..4e380ecc71097 100644 --- a/src/backend/access/brin/brin_revmap.c +++ b/src/backend/access/brin/brin_revmap.c @@ -12,7 +12,7 @@ * the metapage. When the revmap needs to be expanded, all tuples on the * regular BRIN page at that block (if any) are moved out of the way. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -416,7 +416,7 @@ brinRevmapDesummarizeRange(Relation idxrel, BlockNumber heapBlk) xlrec.regOffset = regOffset; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBrinDesummarize); + XLogRegisterData(&xlrec, SizeOfBrinDesummarize); XLogRegisterBuffer(0, revmapBuf, 0); XLogRegisterBuffer(1, regBuf, REGBUF_STANDARD); recptr = XLogInsert(RM_BRIN_ID, XLOG_BRIN_DESUMMARIZE); @@ -627,7 +627,7 @@ revmap_physical_extend(BrinRevmap *revmap) xlrec.targetBlk = mapBlk; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBrinRevmapExtend); + XLogRegisterData(&xlrec, SizeOfBrinRevmapExtend); XLogRegisterBuffer(0, revmap->rm_metaBuf, REGBUF_STANDARD); XLogRegisterBuffer(1, buf, REGBUF_WILL_INIT); diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index 997eb6d822cd6..861f397e6db58 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -23,7 +23,7 @@ * Note the size of the null bitmask may not be the same as that of the * datum array. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -699,17 +699,19 @@ brin_deconstruct_tuple(BrinDesc *brdesc, datumno < brdesc->bd_info[attnum]->oi_nstored; datumno++) { - Form_pg_attribute thisatt = TupleDescAttr(diskdsc, stored); + CompactAttribute *thisatt = TupleDescCompactAttr(diskdsc, stored); if (thisatt->attlen == -1) { - off = att_align_pointer(off, thisatt->attalign, -1, - tp + off); + off = att_pointer_alignby(off, + thisatt->attalignby, + -1, + tp + off); } else { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, thisatt->attalign); + /* not varlena, so safe to use att_nominal_alignby */ + off = att_nominal_alignby(off, thisatt->attalignby); } values[stored++] = fetchatt(thisatt, tp + off); diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c index 539ac9cb0645f..915b8628b460e 100644 --- a/src/backend/access/brin/brin_validate.c +++ b/src/backend/access/brin/brin_validate.c @@ -3,7 +3,7 @@ * brin_validate.c * Opclass validator for BRIN. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,9 +19,9 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/syscache.h" @@ -42,8 +42,6 @@ brinvalidate(Oid opclassoid) Oid opfamilyoid; Oid opcintype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -65,12 +63,7 @@ brinvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -274,7 +267,6 @@ brinvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; diff --git a/src/backend/access/brin/brin_xlog.c b/src/backend/access/brin/brin_xlog.c index eb48d5e90da0b..85db2f0fd5ace 100644 --- a/src/backend/access/brin/brin_xlog.c +++ b/src/backend/access/brin/brin_xlog.c @@ -2,7 +2,7 @@ * brin_xlog.c * XLog replay routines for BRIN indexes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/brin/meson.build b/src/backend/access/brin/meson.build index 1c784cadbe094..4aa1439721d11 100644 --- a/src/backend/access/brin/meson.build +++ b/src/backend/access/brin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'brin.c', diff --git a/src/backend/access/common/attmap.c b/src/backend/access/common/attmap.c index b0fe27ef57da4..4901ebecef73f 100644 --- a/src/backend/access/common/attmap.c +++ b/src/backend/access/common/attmap.c @@ -10,7 +10,7 @@ * columns in a different order, taking into account dropped columns. * They are also used by the tuple conversion routines in tupconvert.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -96,33 +96,31 @@ build_attrmap_by_position(TupleDesc indesc, same = true; for (i = 0; i < n; i++) { - Form_pg_attribute att = TupleDescAttr(outdesc, i); - Oid atttypid; - int32 atttypmod; + Form_pg_attribute outatt = TupleDescAttr(outdesc, i); - if (att->attisdropped) + if (outatt->attisdropped) continue; /* attrMap->attnums[i] is already 0 */ noutcols++; - atttypid = att->atttypid; - atttypmod = att->atttypmod; for (; j < indesc->natts; j++) { - att = TupleDescAttr(indesc, j); - if (att->attisdropped) + Form_pg_attribute inatt = TupleDescAttr(indesc, j); + + if (inatt->attisdropped) continue; nincols++; /* Found matching column, now check type */ - if (atttypid != att->atttypid || - (atttypmod != att->atttypmod && atttypmod >= 0)) + if (outatt->atttypid != inatt->atttypid || + (outatt->atttypmod != inatt->atttypmod && outatt->atttypmod >= 0)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), - errdetail("Returned type %s does not match expected type %s in column %d.", - format_type_with_typemod(att->atttypid, - att->atttypmod), - format_type_with_typemod(atttypid, - atttypmod), + errdetail("Returned type %s does not match expected type %s in column \"%s\" (position %d).", + format_type_with_typemod(inatt->atttypid, + inatt->atttypmod), + format_type_with_typemod(outatt->atttypid, + outatt->atttypmod), + NameStr(outatt->attname), noutcols))); attrMap->attnums[i] = (AttrNumber) (j + 1); j++; @@ -135,7 +133,7 @@ build_attrmap_by_position(TupleDesc indesc, /* Check for unused input columns */ for (; j < indesc->natts; j++) { - if (TupleDescAttr(indesc, j)->attisdropped) + if (TupleDescCompactAttr(indesc, j)->attisdropped) continue; nincols++; same = false; /* we'll complain below */ @@ -299,8 +297,8 @@ check_attrmap_match(TupleDesc indesc, for (i = 0; i < attrMap->maplen; i++) { - Form_pg_attribute inatt = TupleDescAttr(indesc, i); - Form_pg_attribute outatt = TupleDescAttr(outdesc, i); + CompactAttribute *inatt = TupleDescCompactAttr(indesc, i); + CompactAttribute *outatt; /* * If the input column has a missing attribute, we need a conversion. @@ -311,15 +309,17 @@ check_attrmap_match(TupleDesc indesc, if (attrMap->attnums[i] == (i + 1)) continue; + outatt = TupleDescCompactAttr(outdesc, i); + /* * If it's a dropped column and the corresponding input column is also - * dropped, we don't need a conversion. However, attlen and attalign - * must agree. + * dropped, we don't need a conversion. However, attlen and + * attalignby must agree. */ if (attrMap->attnums[i] == 0 && inatt->attisdropped && inatt->attlen == outatt->attlen && - inatt->attalign == outatt->attalign) + inatt->attalignby == outatt->attalignby) continue; return false; diff --git a/src/backend/access/common/bufmask.c b/src/backend/access/common/bufmask.c index 10a1e4d7c6c64..bb260cffa6828 100644 --- a/src/backend/access/common/bufmask.c +++ b/src/backend/access/common/bufmask.c @@ -5,7 +5,7 @@ * in a page which can be different when the WAL is generated * and when the WAL is applied. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * Contains common routines required for masking a page. * diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c index 3547cdba56eae..6265178774221 100644 --- a/src/backend/access/common/detoast.c +++ b/src/backend/access/common/detoast.c @@ -3,7 +3,7 @@ * detoast.c * Retrieve compressed or external variable size attributes. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/common/detoast.c @@ -88,7 +88,7 @@ detoast_external_attr(struct varlena *attr) eoh = DatumGetEOHP(PointerGetDatum(attr)); resultsize = EOH_get_flat_size(eoh); result = (struct varlena *) palloc(resultsize); - EOH_flatten_into(eoh, (void *) result, resultsize); + EOH_flatten_into(eoh, result, resultsize); } else { diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 9e3407bf987aa..969d1028cae89 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -45,7 +45,7 @@ * and we'd like to still refer to them via C struct offsets. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -83,6 +83,10 @@ #define VARLENA_ATT_IS_PACKABLE(att) \ ((att)->attstorage != TYPSTORAGE_PLAIN) +/* FormData_pg_attribute.attstorage != TYPSTORAGE_PLAIN and an attlen of -1 */ +#define COMPACT_ATTR_IS_PACKABLE(att) \ + ((att)->attlen == -1 && (att)->attispackable) + /* * Setup for caching pass-by-ref missing attributes in a way that survives * tupleDesc destruction. @@ -147,12 +151,12 @@ Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull) { - Form_pg_attribute att; + CompactAttribute *att; Assert(attnum <= tupleDesc->natts); Assert(attnum > 0); - att = TupleDescAttr(tupleDesc, attnum - 1); + att = TupleDescCompactAttr(tupleDesc, attnum - 1); if (att->atthasmissing) { @@ -223,15 +227,15 @@ heap_compute_data_size(TupleDesc tupleDesc, for (i = 0; i < numberOfAttributes; i++) { Datum val; - Form_pg_attribute atti; + CompactAttribute *atti; if (isnull[i]) continue; val = values[i]; - atti = TupleDescAttr(tupleDesc, i); + atti = TupleDescCompactAttr(tupleDesc, i); - if (ATT_IS_PACKABLE(atti) && + if (COMPACT_ATTR_IS_PACKABLE(atti) && VARATT_CAN_MAKE_SHORT(DatumGetPointer(val))) { /* @@ -247,13 +251,13 @@ heap_compute_data_size(TupleDesc tupleDesc, * we want to flatten the expanded value so that the constructed * tuple doesn't depend on it */ - data_length = att_align_nominal(data_length, atti->attalign); + data_length = att_nominal_alignby(data_length, atti->attalignby); data_length += EOH_get_flat_size(DatumGetEOHP(val)); } else { - data_length = att_align_datum(data_length, atti->attalign, - atti->attlen, val); + data_length = att_datum_alignby(data_length, atti->attalignby, + atti->attlen, val); data_length = att_addlength_datum(data_length, atti->attlen, val); } @@ -268,7 +272,7 @@ heap_compute_data_size(TupleDesc tupleDesc, * Fill in either a data value or a bit in the null bitmask */ static inline void -fill_val(Form_pg_attribute att, +fill_val(CompactAttribute *att, bits8 **bit, int *bitmask, char **dataP, @@ -304,13 +308,13 @@ fill_val(Form_pg_attribute att, } /* - * XXX we use the att_align macros on the pointer value itself, not on an - * offset. This is a bit of a hack. + * XXX we use the att_nominal_alignby macro on the pointer value itself, + * not on an offset. This is a bit of a hack. */ if (att->attbyval) { /* pass-by-value */ - data = (char *) att_align_nominal(data, att->attalign); + data = (char *) att_nominal_alignby(data, att->attalignby); store_att_byval(data, datum, att->attlen); data_length = att->attlen; } @@ -330,8 +334,7 @@ fill_val(Form_pg_attribute att, */ ExpandedObjectHeader *eoh = DatumGetEOHP(datum); - data = (char *) att_align_nominal(data, - att->attalign); + data = (char *) att_nominal_alignby(data, att->attalignby); data_length = EOH_get_flat_size(eoh); EOH_flatten_into(eoh, data, data_length); } @@ -349,8 +352,7 @@ fill_val(Form_pg_attribute att, data_length = VARSIZE_SHORT(val); memcpy(data, val, data_length); } - else if (VARLENA_ATT_IS_PACKABLE(att) && - VARATT_CAN_MAKE_SHORT(val)) + else if (att->attispackable && VARATT_CAN_MAKE_SHORT(val)) { /* convert to short varlena -- no alignment */ data_length = VARATT_CONVERTED_SHORT_SIZE(val); @@ -360,8 +362,7 @@ fill_val(Form_pg_attribute att, else { /* full 4-byte header varlena */ - data = (char *) att_align_nominal(data, - att->attalign); + data = (char *) att_nominal_alignby(data, att->attalignby); data_length = VARSIZE(val); memcpy(data, val, data_length); } @@ -370,14 +371,14 @@ fill_val(Form_pg_attribute att, { /* cstring ... never needs alignment */ *infomask |= HEAP_HASVARWIDTH; - Assert(att->attalign == TYPALIGN_CHAR); + Assert(att->attalignby == sizeof(char)); data_length = strlen(DatumGetCString(datum)) + 1; memcpy(data, DatumGetPointer(datum), data_length); } else { /* fixed-length pass-by-reference */ - data = (char *) att_align_nominal(data, att->attalign); + data = (char *) att_nominal_alignby(data, att->attalignby); Assert(att->attlen > 0); data_length = att->attlen; memcpy(data, DatumGetPointer(datum), data_length); @@ -427,7 +428,7 @@ heap_fill_tuple(TupleDesc tupleDesc, for (i = 0; i < numberOfAttributes; i++) { - Form_pg_attribute attr = TupleDescAttr(tupleDesc, i); + CompactAttribute *attr = TupleDescCompactAttr(tupleDesc, i); fill_val(attr, bitP ? &bitP : NULL, @@ -461,7 +462,8 @@ heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc) Assert(!tupleDesc || attnum <= tupleDesc->natts); if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data)) { - if (tupleDesc && TupleDescAttr(tupleDesc, attnum - 1)->atthasmissing) + if (tupleDesc && + TupleDescCompactAttr(tupleDesc, attnum - 1)->atthasmissing) return false; else return true; @@ -570,13 +572,13 @@ nocachegetattr(HeapTuple tup, if (!slow) { - Form_pg_attribute att; + CompactAttribute *att; /* * If we get here, there are no nulls up to and including the target * attribute. If we have a cached offset, we can use it. */ - att = TupleDescAttr(tupleDesc, attnum); + att = TupleDescCompactAttr(tupleDesc, attnum); if (att->attcacheoff >= 0) return fetchatt(att, tp + att->attcacheoff); @@ -591,7 +593,7 @@ nocachegetattr(HeapTuple tup, for (j = 0; j <= attnum; j++) { - if (TupleDescAttr(tupleDesc, j)->attlen <= 0) + if (TupleDescCompactAttr(tupleDesc, j)->attlen <= 0) { slow = true; break; @@ -614,23 +616,23 @@ nocachegetattr(HeapTuple tup, * fixed-width columns, in hope of avoiding future visits to this * routine. */ - TupleDescAttr(tupleDesc, 0)->attcacheoff = 0; + TupleDescCompactAttr(tupleDesc, 0)->attcacheoff = 0; /* we might have set some offsets in the slow path previously */ - while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0) + while (j < natts && TupleDescCompactAttr(tupleDesc, j)->attcacheoff > 0) j++; - off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff + - TupleDescAttr(tupleDesc, j - 1)->attlen; + off = TupleDescCompactAttr(tupleDesc, j - 1)->attcacheoff + + TupleDescCompactAttr(tupleDesc, j - 1)->attlen; for (; j < natts; j++) { - Form_pg_attribute att = TupleDescAttr(tupleDesc, j); + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, j); if (att->attlen <= 0) break; - off = att_align_nominal(off, att->attalign); + off = att_nominal_alignby(off, att->attalignby); att->attcacheoff = off; @@ -639,7 +641,7 @@ nocachegetattr(HeapTuple tup, Assert(j > attnum); - off = TupleDescAttr(tupleDesc, attnum)->attcacheoff; + off = TupleDescCompactAttr(tupleDesc, attnum)->attcacheoff; } else { @@ -659,7 +661,7 @@ nocachegetattr(HeapTuple tup, off = 0; for (i = 0;; i++) /* loop exit is at "break" */ { - Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, i); if (HeapTupleHasNulls(tup) && att_isnull(i, bp)) { @@ -679,19 +681,19 @@ nocachegetattr(HeapTuple tup, * either an aligned or unaligned value. */ if (usecache && - off == att_align_nominal(off, att->attalign)) + off == att_nominal_alignby(off, att->attalignby)) att->attcacheoff = off; else { - off = att_align_pointer(off, att->attalign, -1, - tp + off); + off = att_pointer_alignby(off, att->attalignby, -1, + tp + off); usecache = false; } } else { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, att->attalign); + /* not varlena, so safe to use att_nominal_alignby */ + off = att_nominal_alignby(off, att->attalignby); if (usecache) att->attcacheoff = off; @@ -707,7 +709,7 @@ nocachegetattr(HeapTuple tup, } } - return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off); + return fetchatt(TupleDescCompactAttr(tupleDesc, attnum), tp + off); } /* ---------------- @@ -785,7 +787,7 @@ heap_copytuple(HeapTuple tuple) newTuple->t_self = tuple->t_self; newTuple->t_tableOid = tuple->t_tableOid; newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE); - memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len); + memcpy(newTuple->t_data, tuple->t_data, tuple->t_len); return newTuple; } @@ -811,7 +813,7 @@ heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest) dest->t_self = src->t_self; dest->t_tableOid = src->t_tableOid; dest->t_data = (HeapTupleHeader) palloc(src->t_len); - memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len); + memcpy(dest->t_data, src->t_data, src->t_len); } /* @@ -892,12 +894,12 @@ expand_tuple(HeapTuple *targetHeapTuple, { if (attrmiss[attnum].am_present) { - Form_pg_attribute att = TupleDescAttr(tupleDesc, attnum); + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, attnum); - targetDataLen = att_align_datum(targetDataLen, - att->attalign, - att->attlen, - attrmiss[attnum].am_value); + targetDataLen = att_datum_alignby(targetDataLen, + att->attalignby, + att->attlen, + attrmiss[attnum].am_value); targetDataLen = att_addlength_pointer(targetDataLen, att->attlen, @@ -1020,8 +1022,7 @@ expand_tuple(HeapTuple *targetHeapTuple, /* Now fill in the missing values */ for (attnum = sourceNatts; attnum < natts; attnum++) { - - Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum); + CompactAttribute *attr = TupleDescCompactAttr(tupleDesc, attnum); if (attrmiss && attrmiss[attnum].am_present) { @@ -1096,7 +1097,7 @@ heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc) * the given tuple came from disk, rather than from heap_form_tuple). */ td = (HeapTupleHeader) palloc(tuple->t_len); - memcpy((char *) td, (char *) tuple->t_data, tuple->t_len); + memcpy(td, tuple->t_data, tuple->t_len); HeapTupleHeaderSetDatumLength(td, tuple->t_len); HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid); @@ -1370,7 +1371,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, for (attnum = 0; attnum < natts; attnum++) { - Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum); + CompactAttribute *thisatt = TupleDescCompactAttr(tupleDesc, attnum); if (hasnulls && att_isnull(attnum, bp)) { @@ -1393,19 +1394,19 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, * an aligned or unaligned value. */ if (!slow && - off == att_align_nominal(off, thisatt->attalign)) + off == att_nominal_alignby(off, thisatt->attalignby)) thisatt->attcacheoff = off; else { - off = att_align_pointer(off, thisatt->attalign, -1, - tp + off); + off = att_pointer_alignby(off, thisatt->attalignby, -1, + tp + off); slow = true; } } else { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, thisatt->attalign); + /* not varlena, so safe to use att_nominal_alignby */ + off = att_nominal_alignby(off, thisatt->attalignby); if (!slow) thisatt->attcacheoff = off; @@ -1451,9 +1452,11 @@ heap_freetuple(HeapTuple htup) MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, - const bool *isnull) + const bool *isnull, + Size extra) { MinimalTuple tuple; /* return tuple */ + char *mem; Size len, data_len; int hoff; @@ -1461,6 +1464,8 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor, int numberOfAttributes = tupleDescriptor->natts; int i; + Assert(extra == MAXALIGN(extra)); + if (numberOfAttributes > MaxTupleAttributeNumber) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_COLUMNS), @@ -1496,7 +1501,9 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor, /* * Allocate and zero the space needed. */ - tuple = (MinimalTuple) palloc0(len); + mem = palloc0(len + extra); + memset(mem, 0, extra); + tuple = (MinimalTuple) (mem + extra); /* * And fill in the information. @@ -1532,11 +1539,15 @@ heap_free_minimal_tuple(MinimalTuple mtup) * The result is allocated in the current memory context. */ MinimalTuple -heap_copy_minimal_tuple(MinimalTuple mtup) +heap_copy_minimal_tuple(MinimalTuple mtup, Size extra) { MinimalTuple result; + char *mem; - result = (MinimalTuple) palloc(mtup->t_len); + Assert(extra == MAXALIGN(extra)); + mem = palloc(mtup->t_len + extra); + memset(mem, 0, extra); + result = (MinimalTuple) (mem + extra); memcpy(result, mtup, mtup->t_len); return result; } @@ -1573,15 +1584,20 @@ heap_tuple_from_minimal_tuple(MinimalTuple mtup) * The result is allocated in the current memory context. */ MinimalTuple -minimal_tuple_from_heap_tuple(HeapTuple htup) +minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra) { MinimalTuple result; + char *mem; uint32 len; + Assert(extra == MAXALIGN(extra)); Assert(htup->t_len > MINIMAL_TUPLE_OFFSET); len = htup->t_len - MINIMAL_TUPLE_OFFSET; - result = (MinimalTuple) palloc(len); + mem = palloc(len + extra); + memset(mem, 0, extra); + result = (MinimalTuple) (mem + extra); memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len); + result->t_len = len; return result; } diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index bb2c6a2bcc15d..1986b943a28be 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -4,7 +4,7 @@ * This file contains index tuple accessor and mutator routines, * as well as various tuple utilities. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -303,13 +303,13 @@ nocache_index_getattr(IndexTuple tup, if (!slow) { - Form_pg_attribute att; + CompactAttribute *att; /* * If we get here, there are no nulls up to and including the target * attribute. If we have a cached offset, we can use it. */ - att = TupleDescAttr(tupleDesc, attnum); + att = TupleDescCompactAttr(tupleDesc, attnum); if (att->attcacheoff >= 0) return fetchatt(att, tp + att->attcacheoff); @@ -324,7 +324,7 @@ nocache_index_getattr(IndexTuple tup, for (j = 0; j <= attnum; j++) { - if (TupleDescAttr(tupleDesc, j)->attlen <= 0) + if (TupleDescCompactAttr(tupleDesc, j)->attlen <= 0) { slow = true; break; @@ -347,23 +347,23 @@ nocache_index_getattr(IndexTuple tup, * fixed-width columns, in hope of avoiding future visits to this * routine. */ - TupleDescAttr(tupleDesc, 0)->attcacheoff = 0; + TupleDescCompactAttr(tupleDesc, 0)->attcacheoff = 0; /* we might have set some offsets in the slow path previously */ - while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0) + while (j < natts && TupleDescCompactAttr(tupleDesc, j)->attcacheoff > 0) j++; - off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff + - TupleDescAttr(tupleDesc, j - 1)->attlen; + off = TupleDescCompactAttr(tupleDesc, j - 1)->attcacheoff + + TupleDescCompactAttr(tupleDesc, j - 1)->attlen; for (; j < natts; j++) { - Form_pg_attribute att = TupleDescAttr(tupleDesc, j); + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, j); if (att->attlen <= 0) break; - off = att_align_nominal(off, att->attalign); + off = att_nominal_alignby(off, att->attalignby); att->attcacheoff = off; @@ -372,7 +372,7 @@ nocache_index_getattr(IndexTuple tup, Assert(j > attnum); - off = TupleDescAttr(tupleDesc, attnum)->attcacheoff; + off = TupleDescCompactAttr(tupleDesc, attnum)->attcacheoff; } else { @@ -392,7 +392,7 @@ nocache_index_getattr(IndexTuple tup, off = 0; for (i = 0;; i++) /* loop exit is at "break" */ { - Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + CompactAttribute *att = TupleDescCompactAttr(tupleDesc, i); if (IndexTupleHasNulls(tup) && att_isnull(i, bp)) { @@ -412,19 +412,19 @@ nocache_index_getattr(IndexTuple tup, * either an aligned or unaligned value. */ if (usecache && - off == att_align_nominal(off, att->attalign)) + off == att_nominal_alignby(off, att->attalignby)) att->attcacheoff = off; else { - off = att_align_pointer(off, att->attalign, -1, - tp + off); + off = att_pointer_alignby(off, att->attalignby, -1, + tp + off); usecache = false; } } else { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, att->attalign); + /* not varlena, so safe to use att_nominal_alignby */ + off = att_nominal_alignby(off, att->attalignby); if (usecache) att->attcacheoff = off; @@ -440,7 +440,7 @@ nocache_index_getattr(IndexTuple tup, } } - return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off); + return fetchatt(TupleDescCompactAttr(tupleDesc, attnum), tp + off); } /* @@ -490,7 +490,7 @@ index_deform_tuple_internal(TupleDesc tupleDescriptor, for (attnum = 0; attnum < natts; attnum++) { - Form_pg_attribute thisatt = TupleDescAttr(tupleDescriptor, attnum); + CompactAttribute *thisatt = TupleDescCompactAttr(tupleDescriptor, attnum); if (hasnulls && att_isnull(attnum, bp)) { @@ -513,19 +513,19 @@ index_deform_tuple_internal(TupleDesc tupleDescriptor, * an aligned or unaligned value. */ if (!slow && - off == att_align_nominal(off, thisatt->attalign)) + off == att_nominal_alignby(off, thisatt->attalignby)) thisatt->attcacheoff = off; else { - off = att_align_pointer(off, thisatt->attalign, -1, - tp + off); + off = att_pointer_alignby(off, thisatt->attalignby, -1, + tp + off); slow = true; } } else { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, thisatt->attalign); + /* not varlena, so safe to use att_nominal_alignby */ + off = att_nominal_alignby(off, thisatt->attalignby); if (!slow) thisatt->attcacheoff = off; @@ -587,10 +587,8 @@ index_truncate_tuple(TupleDesc sourceDescriptor, IndexTuple source, if (leavenatts == sourceDescriptor->natts) return CopyIndexTuple(source); - /* Create temporary descriptor to scribble on */ - truncdesc = palloc(TupleDescSize(sourceDescriptor)); - TupleDescCopy(truncdesc, sourceDescriptor); - truncdesc->natts = leavenatts; + /* Create temporary truncated tuple descriptor */ + truncdesc = CreateTupleDescTruncatedCopy(sourceDescriptor, leavenatts); /* Deform, form copy of tuple with fewer attributes */ index_deform_tuple(source, truncdesc, values, isnull); diff --git a/src/backend/access/common/meson.build b/src/backend/access/common/meson.build index 14090c728fb3a..e3cdbe7a22e1a 100644 --- a/src/backend/access/common/meson.build +++ b/src/backend/access/common/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'attmap.c', diff --git a/src/backend/access/common/printsimple.c b/src/backend/access/common/printsimple.c index 4c5eedcdc1795..f346ab3e8125b 100644 --- a/src/backend/access/common/printsimple.c +++ b/src/backend/access/common/printsimple.c @@ -8,7 +8,7 @@ * doesn't handle standalone backends or protocol versions other than * 3.0, because we don't need such handling for current applications. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index c78cc3930873a..830a3d883aa2e 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -5,7 +5,7 @@ * clients and standalone backends are supported here). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c index d8a313a2c906f..22c4cd5a25658 100644 --- a/src/backend/access/common/relation.c +++ b/src/backend/access/common/relation.c @@ -3,7 +3,7 @@ * relation.c * Generic relation related routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index d6eb5d8559939..50747c1639612 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -3,7 +3,7 @@ * reloptions.c * Core support for relation options (pg_class.reloptions) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -231,6 +231,15 @@ static relopt_int intRelOpts[] = }, -1, 0, INT_MAX }, + { + { + "autovacuum_vacuum_max_threshold", + "Maximum number of tuple updates or deletes prior to vacuum", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -2, -1, INT_MAX + }, { { "autovacuum_vacuum_insert_threshold", @@ -352,11 +361,7 @@ static relopt_int intRelOpts[] = RELOPT_KIND_TABLESPACE, ShareUpdateExclusiveLock }, -#ifdef USE_PREFETCH -1, 0, MAX_IO_CONCURRENCY -#else - 0, 0, 0 -#endif }, { { @@ -365,11 +370,7 @@ static relopt_int intRelOpts[] = RELOPT_KIND_TABLESPACE, ShareUpdateExclusiveLock }, -#ifdef USE_PREFETCH -1, 0, MAX_IO_CONCURRENCY -#else - 0, 0, 0 -#endif }, { { @@ -423,6 +424,16 @@ static relopt_real realRelOpts[] = }, -1, 0.0, 100.0 }, + { + { + "vacuum_max_eager_freeze_failure_rate", + "Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning.", + RELOPT_KIND_HEAP | RELOPT_KIND_TOAST, + ShareUpdateExclusiveLock + }, + -1, 0.0, 1.0 + }, + { { "seq_page_cost", @@ -1154,7 +1165,7 @@ add_local_string_reloption(local_relopts *relopts, const char *name, */ Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, - char *validnsps[], bool acceptOidsOff, bool isReset) + const char *const validnsps[], bool acceptOidsOff, bool isReset) { Datum result; ArrayBuildState *astate; @@ -1232,8 +1243,9 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace, } else { - text *t; + const char *name; const char *value; + text *t; Size len; /* @@ -1280,11 +1292,19 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace, * have just "name", assume "name=true" is meant. Note: the * namespace is not output. */ + name = def->defname; if (def->arg != NULL) value = defGetString(def); else value = "true"; + /* Insist that name not contain "=", else "a=b=c" is ambiguous */ + if (strchr(name, '=') != NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid option name \"%s\": must not contain \"=\"", + name))); + /* * This is not a great place for this test, but there's no other * convenient place to filter the option out. As WITH (oids = @@ -1292,7 +1312,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace, * amount of ugly. */ if (acceptOidsOff && def->defnamespace == NULL && - strcmp(def->defname, "oids") == 0) + strcmp(name, "oids") == 0) { if (defGetBoolean(def)) ereport(ERROR, @@ -1302,11 +1322,11 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace, continue; } - len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value); + len = VARHDRSZ + strlen(name) + 1 + strlen(value); /* +1 leaves room for sprintf's trailing null */ t = (text *) palloc(len + 1); SET_VARSIZE(t, len); - sprintf(VARDATA(t), "%s=%s", def->defname, value); + sprintf(VARDATA(t), "%s=%s", name, value); astate = accumArrayResult(astate, PointerGetDatum(t), false, TEXTOID, @@ -1760,6 +1780,17 @@ fillRelOptions(void *rdopts, Size basesize, char *itempos = ((char *) rdopts) + elems[j].offset; char *string_val; + /* + * If isset_offset is provided, store whether the reloption is + * set there. + */ + if (elems[j].isset_offset > 0) + { + char *setpos = ((char *) rdopts) + elems[j].isset_offset; + + *(bool *) setpos = options[i].isset; + } + switch (options[i].gen->type) { case RELOPT_TYPE_BOOL: @@ -1843,6 +1874,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)}, {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)}, + {"autovacuum_vacuum_max_threshold", RELOPT_TYPE_INT, + offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_max_threshold)}, {"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)}, {"autovacuum_analyze_threshold", RELOPT_TYPE_INT, @@ -1880,7 +1913,9 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"vacuum_index_cleanup", RELOPT_TYPE_ENUM, offsetof(StdRdOptions, vacuum_index_cleanup)}, {"vacuum_truncate", RELOPT_TYPE_BOOL, - offsetof(StdRdOptions, vacuum_truncate)} + offsetof(StdRdOptions, vacuum_truncate), offsetof(StdRdOptions, vacuum_truncate_set)}, + {"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL, + offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)} }; return (bytea *) build_reloptions(reloptions, validate, kind, @@ -1958,6 +1993,7 @@ build_local_reloptions(local_relopts *relopts, Datum options, bool validate) elems[i].optname = opt->option->name; elems[i].opttype = opt->option->type; elems[i].offset = opt->offset; + elems[i].isset_offset = 0; /* not supported for local relopts yet */ i++; } diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c index 704363af3f54d..2d65ab02dd38e 100644 --- a/src/backend/access/common/scankey.c +++ b/src/backend/access/common/scankey.c @@ -3,7 +3,7 @@ * scankey.c * scan key support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/common/session.c b/src/backend/access/common/session.c index 3f2256f491525..8836f73c90bf1 100644 --- a/src/backend/access/common/session.c +++ b/src/backend/access/common/session.c @@ -12,7 +12,7 @@ * Currently this infrastructure is used to share: * - typemod registry for ephemeral row-types, i.e. BlessTupleDesc etc. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/backend/access/common/session.c * diff --git a/src/backend/access/common/syncscan.c b/src/backend/access/common/syncscan.c index 8d78d28a6fced..4e2cfc1f7c91c 100644 --- a/src/backend/access/common/syncscan.c +++ b/src/backend/access/common/syncscan.c @@ -36,7 +36,7 @@ * ss_report_location - update current scan location * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/common/tidstore.c b/src/backend/access/common/tidstore.c index a7179759d67d2..5bd75fb499cef 100644 --- a/src/backend/access/common/tidstore.c +++ b/src/backend/access/common/tidstore.c @@ -11,7 +11,7 @@ * TidStoreCreateShared(). Other backends can attach to the shared TidStore * by TidStoreAttach(). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -113,10 +113,10 @@ typedef struct BlocktableEntry /* Per-backend state for a TidStore */ struct TidStore { - /* MemoryContext where the TidStore is allocated */ - MemoryContext context; - - /* MemoryContext that the radix tree uses */ + /* + * MemoryContext for the radix tree when using local memory, NULL for + * shared memory + */ MemoryContext rt_context; /* Storage for TIDs. Use either one depending on TidStoreIsShared() */ @@ -167,7 +167,6 @@ TidStoreCreateLocal(size_t max_bytes, bool insert_only) size_t maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE; ts = palloc0(sizeof(TidStore)); - ts->context = CurrentMemoryContext; /* choose the maxBlockSize to be no larger than 1/16 of max_bytes */ while (16 * maxBlockSize > max_bytes) @@ -201,8 +200,7 @@ TidStoreCreateLocal(size_t max_bytes, bool insert_only) /* * Similar to TidStoreCreateLocal() but create a shared TidStore on a - * DSA area. The TID storage will live in the DSA area, and the memory - * context rt_context will have only meta data of the radix tree. + * DSA area. * * The returned object is allocated in backend-local memory. */ @@ -215,11 +213,6 @@ TidStoreCreateShared(size_t max_bytes, int tranche_id) size_t dsa_max_size = DSA_MAX_SEGMENT_SIZE; ts = palloc0(sizeof(TidStore)); - ts->context = CurrentMemoryContext; - - ts->rt_context = AllocSetContextCreate(CurrentMemoryContext, - "TID storage meta data", - ALLOCSET_SMALL_SIZES); /* * Choose the initial and maximum DSA segment sizes to be no longer than @@ -235,8 +228,7 @@ TidStoreCreateShared(size_t max_bytes, int tranche_id) dsa_init_size = dsa_max_size; area = dsa_create_ext(tranche_id, dsa_init_size, dsa_max_size); - ts->tree.shared = shared_ts_create(ts->rt_context, area, - tranche_id); + ts->tree.shared = shared_ts_create(area, tranche_id); ts->area = area; return ts; @@ -328,13 +320,13 @@ TidStoreDestroy(TidStore *ts) if (TidStoreIsShared(ts)) { shared_ts_free(ts->tree.shared); - dsa_detach(ts->area); } else + { local_ts_free(ts->tree.local); - - MemoryContextDelete(ts->rt_context); + MemoryContextDelete(ts->rt_context); + } pfree(ts); } diff --git a/src/backend/access/common/toast_compression.c b/src/backend/access/common/toast_compression.c index 52230f31c6821..21f2f4af97e3f 100644 --- a/src/backend/access/common/toast_compression.c +++ b/src/backend/access/common/toast_compression.c @@ -3,7 +3,7 @@ * toast_compression.c * Functions for toast compression. * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c index 90d0654e6298b..7d8be8346ce52 100644 --- a/src/backend/access/common/toast_internals.c +++ b/src/backend/access/common/toast_internals.c @@ -3,7 +3,7 @@ * toast_internals.c * Functions for internal use by the TOAST system. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/common/toast_internals.c @@ -393,7 +393,6 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative) HeapTuple toasttup; int num_indexes; int validIndex; - SnapshotData SnapshotToast; if (!VARATT_IS_EXTERNAL_ONDISK(attr)) return; @@ -425,9 +424,8 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative) * sequence or not, but since we've already locked the index we might as * well use systable_beginscan_ordered.) */ - init_toast_snapshot(&SnapshotToast); toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex], - &SnapshotToast, 1, &toastkey); + get_toast_snapshot(), 1, &toastkey); while ((toasttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL) { /* @@ -631,41 +629,28 @@ toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock) } /* ---------- - * init_toast_snapshot + * get_toast_snapshot * - * Initialize an appropriate TOAST snapshot. We must use an MVCC snapshot - * to initialize the TOAST snapshot; since we don't know which one to use, - * just use the oldest one. + * Return the TOAST snapshot. Detoasting *must* happen in the same + * transaction that originally fetched the toast pointer. */ -void -init_toast_snapshot(Snapshot toast_snapshot) +Snapshot +get_toast_snapshot(void) { - Snapshot snapshot = GetOldestSnapshot(); - /* - * GetOldestSnapshot returns NULL if the session has no active snapshots. - * We can get that if, for example, a procedure fetches a toasted value - * into a local variable, commits, and then tries to detoast the value. - * Such coding is unsafe, because once we commit there is nothing to - * prevent the toast data from being deleted. Detoasting *must* happen in - * the same transaction that originally fetched the toast pointer. Hence, - * rather than trying to band-aid over the problem, throw an error. (This - * is not very much protection, because in many scenarios the procedure - * would have already created a new transaction snapshot, preventing us - * from detecting the problem. But it's better than nothing, and for sure - * we shouldn't expend code on masking the problem more.) + * We cannot directly check that detoasting happens in the same + * transaction that originally fetched the toast pointer, but at least + * check that the session has some active snapshots. It might not if, for + * example, a procedure fetches a toasted value into a local variable, + * commits, and then tries to detoast the value. Such coding is unsafe, + * because once we commit there is nothing to prevent the toast data from + * being deleted. (This is not very much protection, because in many + * scenarios the procedure would have already created a new transaction + * snapshot, preventing us from detecting the problem. But it's better + * than nothing.) */ - if (snapshot == NULL) + if (!HaveRegisteredOrActiveSnapshot()) elog(ERROR, "cannot fetch toast data without an active snapshot"); - /* - * Catalog snapshots can be returned by GetOldestSnapshot() even if not - * registered or active. That easily hides bugs around not having a - * snapshot set up - most of the time there is a valid catalog snapshot. - * So additionally insist that the current snapshot is registered or - * active. - */ - Assert(HaveRegisteredOrActiveSnapshot()); - - InitToastSnapshot(*toast_snapshot, snapshot->lsn, snapshot->whenTaken); + return &SnapshotToastData; } diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c index 4d596c4bef60a..54dc2f4ab80ab 100644 --- a/src/backend/access/common/tupconvert.c +++ b/src/backend/access/common/tupconvert.c @@ -7,7 +7,7 @@ * equivalent but might have columns in a different order or different sets of * dropped columns. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 47379fef220b7..020d00cd01ce7 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -3,7 +3,7 @@ * tupdesc.c * POSTGRES tuple descriptor support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,6 +22,7 @@ #include "access/htup_details.h" #include "access/toast_compression.h" #include "access/tupdesc_details.h" +#include "catalog/catalog.h" #include "catalog/pg_collation.h" #include "catalog/pg_type.h" #include "common/hashfn.h" @@ -56,6 +57,120 @@ ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc) ResourceOwnerForget(owner, PointerGetDatum(tupdesc), &tupdesc_resowner_desc); } +/* + * populate_compact_attribute_internal + * Helper function for populate_compact_attribute() + */ +static inline void +populate_compact_attribute_internal(Form_pg_attribute src, + CompactAttribute *dst) +{ + memset(dst, 0, sizeof(CompactAttribute)); + + dst->attcacheoff = -1; + dst->attlen = src->attlen; + + dst->attbyval = src->attbyval; + dst->attispackable = (src->attstorage != TYPSTORAGE_PLAIN); + dst->atthasmissing = src->atthasmissing; + dst->attisdropped = src->attisdropped; + dst->attgenerated = (src->attgenerated != '\0'); + + /* + * Assign nullability status for this column. Assuming that a constraint + * exists, at this point we don't know if a not-null constraint is valid, + * so we assign UNKNOWN unless the table is a catalog, in which case we + * know it's valid. + */ + dst->attnullability = !src->attnotnull ? ATTNULLABLE_UNRESTRICTED : + IsCatalogRelationOid(src->attrelid) ? ATTNULLABLE_VALID : + ATTNULLABLE_UNKNOWN; + + switch (src->attalign) + { + case TYPALIGN_INT: + dst->attalignby = ALIGNOF_INT; + break; + case TYPALIGN_CHAR: + dst->attalignby = sizeof(char); + break; + case TYPALIGN_DOUBLE: + dst->attalignby = ALIGNOF_DOUBLE; + break; + case TYPALIGN_SHORT: + dst->attalignby = ALIGNOF_SHORT; + break; + default: + dst->attalignby = 0; + elog(ERROR, "invalid attalign value: %c", src->attalign); + break; + } +} + +/* + * populate_compact_attribute + * Fill in the corresponding CompactAttribute element from the + * Form_pg_attribute for the given attribute number. This must be called + * whenever a change is made to a Form_pg_attribute in the TupleDesc. + */ +void +populate_compact_attribute(TupleDesc tupdesc, int attnum) +{ + Form_pg_attribute src = TupleDescAttr(tupdesc, attnum); + CompactAttribute *dst; + + /* + * Don't use TupleDescCompactAttr to prevent infinite recursion in assert + * builds. + */ + dst = &tupdesc->compact_attrs[attnum]; + + populate_compact_attribute_internal(src, dst); +} + +/* + * verify_compact_attribute + * In Assert enabled builds, we verify that the CompactAttribute is + * populated correctly. This helps find bugs in places such as ALTER + * TABLE where code makes changes to the FormData_pg_attribute but + * forgets to call populate_compact_attribute(). + * + * This is used in TupleDescCompactAttr(), but declared here to allow access + * to populate_compact_attribute_internal(). + */ +void +verify_compact_attribute(TupleDesc tupdesc, int attnum) +{ +#ifdef USE_ASSERT_CHECKING + CompactAttribute cattr; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum); + CompactAttribute tmp; + + /* + * Make a temp copy of the TupleDesc's CompactAttribute. This may be a + * shared TupleDesc and the attcacheoff might get changed by another + * backend. + */ + memcpy(&cattr, &tupdesc->compact_attrs[attnum], sizeof(CompactAttribute)); + + /* + * Populate the temporary CompactAttribute from the corresponding + * Form_pg_attribute + */ + populate_compact_attribute_internal(attr, &tmp); + + /* + * Make the attcacheoff match since it's been reset to -1 by + * populate_compact_attribute_internal. Same with attnullability. + */ + tmp.attcacheoff = cattr.attcacheoff; + tmp.attnullability = cattr.attnullability; + + /* Check the freshly populated CompactAttribute matches the TupleDesc's */ + Assert(memcmp(&tmp, &cattr, sizeof(CompactAttribute)) == 0); +#endif +} + /* * CreateTemplateTupleDesc * This function allocates an empty tuple descriptor structure. @@ -74,18 +189,20 @@ CreateTemplateTupleDesc(int natts) Assert(natts >= 0); /* - * Allocate enough memory for the tuple descriptor, including the - * attribute rows. + * Allocate enough memory for the tuple descriptor, the CompactAttribute + * array and also an array of FormData_pg_attribute. * - * Note: the attribute array stride is sizeof(FormData_pg_attribute), - * since we declare the array elements as FormData_pg_attribute for - * notational convenience. However, we only guarantee that the first - * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that - * copies tupdesc entries around copies just that much. In principle that - * could be less due to trailing padding, although with the current - * definition of pg_attribute there probably isn't any padding. + * Note: the FormData_pg_attribute array stride is + * sizeof(FormData_pg_attribute), since we declare the array elements as + * FormData_pg_attribute for notational convenience. However, we only + * guarantee that the first ATTRIBUTE_FIXED_PART_SIZE bytes of each entry + * are valid; most code that copies tupdesc entries around copies just + * that much. In principle that could be less due to trailing padding, + * although with the current definition of pg_attribute there probably + * isn't any padding. */ - desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) + + desc = (TupleDesc) palloc(offsetof(struct TupleDescData, compact_attrs) + + natts * sizeof(CompactAttribute) + natts * sizeof(FormData_pg_attribute)); /* @@ -117,8 +234,10 @@ CreateTupleDesc(int natts, Form_pg_attribute *attrs) desc = CreateTemplateTupleDesc(natts); for (i = 0; i < natts; ++i) + { memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE); - + populate_compact_attribute(desc, i); + } return desc; } @@ -155,6 +274,54 @@ CreateTupleDescCopy(TupleDesc tupdesc) att->atthasmissing = false; att->attidentity = '\0'; att->attgenerated = '\0'; + + populate_compact_attribute(desc, i); + } + + /* We can copy the tuple type identification, too */ + desc->tdtypeid = tupdesc->tdtypeid; + desc->tdtypmod = tupdesc->tdtypmod; + + return desc; +} + +/* + * CreateTupleDescTruncatedCopy + * This function creates a new TupleDesc with only the first 'natts' + * attributes from an existing TupleDesc + * + * !!! Constraints and defaults are not copied !!! + */ +TupleDesc +CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts) +{ + TupleDesc desc; + int i; + + Assert(natts <= tupdesc->natts); + + desc = CreateTemplateTupleDesc(natts); + + /* Flat-copy the attribute array */ + memcpy(TupleDescAttr(desc, 0), + TupleDescAttr(tupdesc, 0), + desc->natts * sizeof(FormData_pg_attribute)); + + /* + * Since we're not copying constraints and defaults, clear fields + * associated with them. + */ + for (i = 0; i < desc->natts; i++) + { + Form_pg_attribute att = TupleDescAttr(desc, i); + + att->attnotnull = false; + att->atthasdef = false; + att->atthasmissing = false; + att->attidentity = '\0'; + att->attgenerated = '\0'; + + populate_compact_attribute(desc, i); } /* We can copy the tuple type identification, too */ @@ -183,6 +350,14 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) TupleDescAttr(tupdesc, 0), desc->natts * sizeof(FormData_pg_attribute)); + for (i = 0; i < desc->natts; i++) + { + populate_compact_attribute(desc, i); + + TupleDescCompactAttr(desc, i)->attnullability = + TupleDescCompactAttr(tupdesc, i)->attnullability; + } + /* Copy the TupleConstr data structure, if any */ if (constr) { @@ -190,6 +365,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) cpy->has_not_null = constr->has_not_null; cpy->has_generated_stored = constr->has_generated_stored; + cpy->has_generated_virtual = constr->has_generated_virtual; if ((cpy->num_defval = constr->num_defval) > 0) { @@ -207,7 +383,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) { if (constr->missing[i].am_present) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, i); cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value, attr->attbyval, @@ -224,6 +400,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) { cpy->check[i].ccname = pstrdup(constr->check[i].ccname); cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin); + cpy->check[i].ccenforced = constr->check[i].ccenforced; cpy->check[i].ccvalid = constr->check[i].ccvalid; cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit; } @@ -252,7 +429,7 @@ TupleDescCopy(TupleDesc dst, TupleDesc src) { int i; - /* Flat-copy the header and attribute array */ + /* Flat-copy the header and attribute arrays */ memcpy(dst, src, TupleDescSize(src)); /* @@ -268,6 +445,8 @@ TupleDescCopy(TupleDesc dst, TupleDesc src) att->atthasmissing = false; att->attidentity = '\0'; att->attgenerated = '\0'; + + populate_compact_attribute(dst, i); } dst->constr = NULL; @@ -304,17 +483,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE); - /* - * Aside from updating the attno, we'd better reset attcacheoff. - * - * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of - * all following columns in dst as well. Current usage scenarios don't - * require that though, because all following columns will get initialized - * by other uses of this function or TupleDescInitEntry. So we cheat a - * bit to avoid a useless O(N^2) penalty. - */ dstAtt->attnum = dstAttno; - dstAtt->attcacheoff = -1; /* since we're not copying constraints or defaults, clear these */ dstAtt->attnotnull = false; @@ -322,6 +491,8 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, dstAtt->atthasmissing = false; dstAtt->attidentity = '\0'; dstAtt->attgenerated = '\0'; + + populate_compact_attribute(dst, dstAttno - 1); } /* @@ -442,9 +613,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) * them (since atttypid will be zero for all dropped columns) and in * general it seems safer to check them always. * - * attcacheoff must NOT be checked since it's possibly not set in both - * copies. We also intentionally ignore atthasmissing, since that's - * not very relevant in tupdescs, which lack the attmissingval field. + * We intentionally ignore atthasmissing, since that's not very + * relevant in tupdescs, which lack the attmissingval field. */ if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) return false; @@ -466,6 +636,24 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) return false; if (attr1->attnotnull != attr2->attnotnull) return false; + + /* + * When the column has a not-null constraint, we also need to consider + * its validity aspect, which only manifests in CompactAttribute-> + * attnullability, so verify that. + */ + if (attr1->attnotnull) + { + CompactAttribute *cattr1 = TupleDescCompactAttr(tupdesc1, i); + CompactAttribute *cattr2 = TupleDescCompactAttr(tupdesc2, i); + + Assert(cattr1->attnullability != ATTNULLABLE_UNKNOWN); + Assert((cattr1->attnullability == ATTNULLABLE_UNKNOWN) == + (cattr2->attnullability == ATTNULLABLE_UNKNOWN)); + + if (cattr1->attnullability != cattr2->attnullability) + return false; + } if (attr1->atthasdef != attr2->atthasdef) return false; if (attr1->attidentity != attr2->attidentity) @@ -494,6 +682,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) return false; if (constr1->has_generated_stored != constr2->has_generated_stored) return false; + if (constr1->has_generated_virtual != constr2->has_generated_virtual) + return false; n = constr1->num_defval; if (n != (int) constr2->num_defval) return false; @@ -521,7 +711,7 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) return false; if (missval1->am_present) { - Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i); + CompactAttribute *missatt1 = TupleDescCompactAttr(tupdesc1, i); if (!datumIsEqual(missval1->am_value, missval2->am_value, missatt1->attbyval, missatt1->attlen)) @@ -547,6 +737,7 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) if (!(strcmp(check1->ccname, check2->ccname) == 0 && strcmp(check1->ccbin, check2->ccbin) == 0 && + check1->ccenforced == check2->ccenforced && check1->ccvalid == check2->ccvalid && check1->ccnoinherit == check2->ccnoinherit)) return false; @@ -685,7 +876,6 @@ TupleDescInitEntry(TupleDesc desc, else if (attributeName != NameStr(att->attname)) namestrcpy(&(att->attname), attributeName); - att->attcacheoff = -1; att->atttypmod = typmod; att->attnum = attributeNumber; @@ -714,6 +904,8 @@ TupleDescInitEntry(TupleDesc desc, att->attcompression = InvalidCompressionMethod; att->attcollation = typeForm->typcollation; + populate_compact_attribute(desc, attributeNumber - 1); + ReleaseSysCache(tuple); } @@ -747,7 +939,6 @@ TupleDescInitBuiltinEntry(TupleDesc desc, Assert(attributeName != NULL); namestrcpy(&(att->attname), attributeName); - att->attcacheoff = -1; att->atttypmod = typmod; att->attnum = attributeNumber; @@ -821,6 +1012,8 @@ TupleDescInitBuiltinEntry(TupleDesc desc, default: elog(ERROR, "unsupported type %u", oidtypeid); } + + populate_compact_attribute(desc, attributeNumber - 1); } /* diff --git a/src/backend/access/gin/README b/src/backend/access/gin/README index b08073162128a..742bcbad499fa 100644 --- a/src/backend/access/gin/README +++ b/src/backend/access/gin/README @@ -237,10 +237,10 @@ GIN packs keys and downlinks into tuples in a different way. P_i is grouped with K_{i+1}. -Inf key is not needed. -There are couple of additional notes regarding K_{n+1} key. -1) In entry tree rightmost page, a key coupled with P_n doesn't really matter. +There are a couple of additional notes regarding K_{n+1} key. +1) In the entry tree on the rightmost page, a key coupled with P_n doesn't really matter. Highkey is assumed to be infinity. -2) In posting tree, a key coupled with P_n always doesn't matter. Highkey for +2) In the posting tree, a key coupled with P_n always doesn't matter. Highkey for non-rightmost pages is stored separately and accessed via GinDataPageGetRightBound(). diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c index 2373e76f77e4f..1f821323eb0a0 100644 --- a/src/backend/access/gin/ginarrayproc.c +++ b/src/backend/access/gin/ginarrayproc.c @@ -4,7 +4,7 @@ * support functions for GIN's indexing of any array * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gin/ginbtree.c b/src/backend/access/gin/ginbtree.c index b7a5013896adb..644d484ea53c6 100644 --- a/src/backend/access/gin/ginbtree.c +++ b/src/backend/access/gin/ginbtree.c @@ -4,7 +4,7 @@ * page utilities routines for the postgres inverted index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -423,7 +423,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack, xlrec.flags = xlflags; - XLogRegisterData((char *) &xlrec, sizeof(ginxlogInsert)); + XLogRegisterData(&xlrec, sizeof(ginxlogInsert)); /* * Log information about child if this was an insertion of a @@ -433,7 +433,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack, { BlockIdSet(&childblknos[0], BufferGetBlockNumber(childbuf)); BlockIdSet(&childblknos[1], GinPageGetOpaque(childpage)->rightlink); - XLogRegisterData((char *) childblknos, + XLogRegisterData(childblknos, sizeof(BlockIdData) * 2); } @@ -617,7 +617,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack, if (BufferIsValid(childbuf)) XLogRegisterBuffer(3, childbuf, REGBUF_STANDARD); - XLogRegisterData((char *) &data, sizeof(ginxlogSplit)); + XLogRegisterData(&data, sizeof(ginxlogSplit)); recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_SPLIT); @@ -685,9 +685,9 @@ ginFinishSplit(GinBtree btree, GinBtreeStack *stack, bool freestack, #ifdef USE_INJECTION_POINTS if (GinPageIsLeaf(BufferGetPage(stack->buffer))) - INJECTION_POINT("gin-leave-leaf-split-incomplete"); + INJECTION_POINT("gin-leave-leaf-split-incomplete", NULL); else - INJECTION_POINT("gin-leave-internal-split-incomplete"); + INJECTION_POINT("gin-leave-internal-split-incomplete", NULL); #endif /* search parent to lock */ @@ -778,7 +778,7 @@ ginFinishSplit(GinBtree btree, GinBtreeStack *stack, bool freestack, static void ginFinishOldSplit(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats, int access) { - INJECTION_POINT("gin-finish-incomplete-split"); + INJECTION_POINT("gin-finish-incomplete-split", NULL); elog(DEBUG1, "finishing incomplete split of block %u in gin index \"%s\"", stack->blkno, RelationGetRelationName(btree->index)); diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c index 7f89cd5e8261e..302cb2092a9a8 100644 --- a/src/backend/access/gin/ginbulk.c +++ b/src/backend/access/gin/ginbulk.c @@ -4,7 +4,7 @@ * routines for fast build of inverted index * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -117,7 +117,7 @@ ginInitBA(BuildAccumulator *accum) ginCombineData, ginAllocEntryAccumulator, NULL, /* no freefunc needed */ - (void *) accum); + accum); } /* @@ -127,10 +127,10 @@ ginInitBA(BuildAccumulator *accum) static Datum getDatumCopy(BuildAccumulator *accum, OffsetNumber attnum, Datum value) { - Form_pg_attribute att; + CompactAttribute *att; Datum res; - att = TupleDescAttr(accum->ginstate->origTupdesc, attnum - 1); + att = TupleDescCompactAttr(accum->ginstate->origTupdesc, attnum - 1); if (att->attbyval) res = value; else diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 126c4dd4504e8..6c2c61947204a 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -4,7 +4,7 @@ * routines for handling GIN posting tree pages. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -63,7 +63,7 @@ typedef struct * If we need WAL data representing the reconstructed leaf page, it's * stored here by computeLeafRecompressWALData. */ - char *walinfo; /* buffer start */ + void *walinfo; /* buffer start */ int walinfolen; /* and length */ } disassembledLeaf; @@ -1173,7 +1173,7 @@ dataExecPlaceToPageInternal(GinBtree btree, Buffer buf, GinBtreeStack *stack, data.newitem = *pitem; XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) &data, + XLogRegisterBufData(0, &data, sizeof(ginxlogInsertDataInternal)); } } @@ -1844,9 +1844,9 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, data.size = rootsize; XLogBeginInsert(); - XLogRegisterData((char *) &data, sizeof(ginxlogCreatePostingTree)); + XLogRegisterData(&data, sizeof(ginxlogCreatePostingTree)); - XLogRegisterData((char *) GinDataLeafPageGetPostingList(page), + XLogRegisterData(GinDataLeafPageGetPostingList(page), rootsize); XLogRegisterBuffer(0, buffer, REGBUF_WILL_INIT); diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index 94ef951e14fda..ba6bbd562df0c 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -4,7 +4,7 @@ * routines for handling GIN entry tree pages. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -585,9 +585,9 @@ entryExecPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, data.offset = off; XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) &data, + XLogRegisterBufData(0, &data, offsetof(ginxlogInsertEntry, tuple)); - XLogRegisterBufData(0, (char *) insertData->entry, + XLogRegisterBufData(0, insertData->entry, IndexTupleSize(insertData->entry)); } } diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index eeca3ed318f4c..a6d88572cc29b 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -7,7 +7,7 @@ * transfer pending entries into the regular index structure. This * wins because bulk insertion is much more efficient than retail. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -39,7 +39,7 @@ int gin_pending_list_limit = 0; #define GIN_PAGE_FREESIZE \ - ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) ) + ( (Size) BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) ) typedef struct KeyArray { @@ -122,7 +122,7 @@ writeListPage(Relation index, Buffer buffer, data.ntuples = ntuples; XLogBeginInsert(); - XLogRegisterData((char *) &data, sizeof(ginxlogInsertListPage)); + XLogRegisterData(&data, sizeof(ginxlogInsertListPage)); XLogRegisterBuffer(0, buffer, REGBUF_WILL_INIT); XLogRegisterBufData(0, workspace.data, size); @@ -431,7 +431,7 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector) memcpy(&data.metadata, metadata, sizeof(GinMetaPageData)); XLogRegisterBuffer(0, metabuffer, REGBUF_WILL_INIT | REGBUF_STANDARD); - XLogRegisterData((char *) &data, sizeof(ginxlogUpdateMeta)); + XLogRegisterData(&data, sizeof(ginxlogUpdateMeta)); recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_UPDATE_META_PAGE); PageSetLSN(metapage, recptr); @@ -456,7 +456,7 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector) * ginInsertCleanup() should not be called inside our CRIT_SECTION. */ cleanupSize = GinGetPendingListCleanupSize(index); - if (metadata->nPendingPages * GIN_PAGE_FREESIZE > cleanupSize * 1024L) + if (metadata->nPendingPages * GIN_PAGE_FREESIZE > cleanupSize * (Size) 1024) needCleanup = true; UnlockReleaseBuffer(metabuffer); @@ -646,7 +646,7 @@ shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, memcpy(&data.metadata, metadata, sizeof(GinMetaPageData)); - XLogRegisterData((char *) &data, + XLogRegisterData(&data, sizeof(ginxlogDeleteListPages)); recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_DELETE_LISTPAGE); @@ -795,7 +795,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean, blknoFinish; bool cleanupFinish = false; bool fsm_vac = false; - Size workMemory; + int workMemory; /* * We would like to prevent concurrent cleanup process. For that we will @@ -892,7 +892,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean, */ processPendingPage(&accum, &datums, page, FirstOffsetNumber); - vacuum_delay_point(); + vacuum_delay_point(false); /* * Is it time to flush memory to disk? Flush if we are at the end of @@ -901,7 +901,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean, */ if (GinPageGetOpaque(page)->rightlink == InvalidBlockNumber || (GinPageHasFullRow(page) && - (accum.allocatedMemory >= workMemory * 1024L))) + accum.allocatedMemory >= workMemory * (Size) 1024)) { ItemPointerData *list; uint32 nlist; @@ -929,7 +929,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean, { ginEntryInsert(ginstate, attnum, key, category, list, nlist, NULL); - vacuum_delay_point(); + vacuum_delay_point(false); } /* @@ -1002,7 +1002,7 @@ ginInsertCleanup(GinState *ginstate, bool full_clean, /* * Read next page in pending list */ - vacuum_delay_point(); + vacuum_delay_point(false); buffer = ReadBuffer(index, blkno); LockBuffer(buffer, GIN_SHARE); page = BufferGetPage(buffer); diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 0b4f2ebadb6c8..f29ccd3c2d1ff 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -4,7 +4,7 @@ * fetch tuples from a GIN scan. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -122,10 +122,10 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, GinScanEntry scanEntry, Snapshot snapshot) { OffsetNumber attnum; - Form_pg_attribute attr; + CompactAttribute *attr; /* Initialize empty bitmap result */ - scanEntry->matchBitmap = tbm_create(work_mem * 1024L, NULL); + scanEntry->matchBitmap = tbm_create(work_mem * (Size) 1024, NULL); /* Null query cannot partial-match anything */ if (scanEntry->isPartialMatch && @@ -134,7 +134,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, /* Locate tupdesc entry for key column (for attbyval/attlen data) */ attnum = scanEntry->attnum; - attr = TupleDescAttr(btree->ginstate->origTupdesc, attnum - 1); + attr = TupleDescCompactAttr(btree->ginstate->origTupdesc, attnum - 1); /* * Predicate lock entry leaf page, following pages will be locked by @@ -332,7 +332,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot) entry->list = NULL; entry->nlist = 0; entry->matchBitmap = NULL; - entry->matchResult = NULL; + entry->matchNtuples = -1; + entry->matchResult.blockno = InvalidBlockNumber; entry->reduceResult = false; entry->predictNumberResult = 0; @@ -373,7 +374,7 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot) if (entry->matchBitmap) { if (entry->matchIterator) - tbm_end_iterate(entry->matchIterator); + tbm_end_private_iterate(entry->matchIterator); entry->matchIterator = NULL; tbm_free(entry->matchBitmap); entry->matchBitmap = NULL; @@ -385,7 +386,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry, Snapshot snapshot) if (entry->matchBitmap && !tbm_is_empty(entry->matchBitmap)) { - entry->matchIterator = tbm_begin_iterate(entry->matchBitmap); + entry->matchIterator = + tbm_begin_private_iterate(entry->matchBitmap); entry->isFinished = false; } } @@ -556,16 +558,18 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key) qsort_arg(entryIndexes, key->nentries, sizeof(int), entryIndexByFrequencyCmp, key); + for (i = 1; i < key->nentries; i++) + key->entryRes[entryIndexes[i]] = GIN_MAYBE; for (i = 0; i < key->nentries - 1; i++) { /* Pass all entries <= i as FALSE, and the rest as MAYBE */ - for (j = 0; j <= i; j++) - key->entryRes[entryIndexes[j]] = GIN_FALSE; - for (j = i + 1; j < key->nentries; j++) - key->entryRes[entryIndexes[j]] = GIN_MAYBE; + key->entryRes[entryIndexes[i]] = GIN_FALSE; if (key->triConsistentFn(key) == GIN_FALSE) break; + + /* Make this loop interruptible in case there are many keys */ + CHECK_FOR_INTERRUPTS(); } /* i is now the last required entry. */ @@ -823,29 +827,35 @@ entryGetItem(GinState *ginstate, GinScanEntry entry, { /* * If we've exhausted all items on this block, move to next block - * in the bitmap. + * in the bitmap. tbm_private_iterate() sets matchResult.blockno + * to InvalidBlockNumber when the bitmap is exhausted. */ - while (entry->matchResult == NULL || - (entry->matchResult->ntuples >= 0 && - entry->offset >= entry->matchResult->ntuples) || - entry->matchResult->blockno < advancePastBlk || + while ((!BlockNumberIsValid(entry->matchResult.blockno)) || + (!entry->matchResult.lossy && + entry->offset >= entry->matchNtuples) || + entry->matchResult.blockno < advancePastBlk || (ItemPointerIsLossyPage(&advancePast) && - entry->matchResult->blockno == advancePastBlk)) + entry->matchResult.blockno == advancePastBlk)) { - entry->matchResult = tbm_iterate(entry->matchIterator); - - if (entry->matchResult == NULL) + if (!tbm_private_iterate(entry->matchIterator, &entry->matchResult)) { + Assert(!BlockNumberIsValid(entry->matchResult.blockno)); ItemPointerSetInvalid(&entry->curItem); - tbm_end_iterate(entry->matchIterator); + tbm_end_private_iterate(entry->matchIterator); entry->matchIterator = NULL; entry->isFinished = true; break; } + /* Exact pages need their tuple offsets extracted. */ + if (!entry->matchResult.lossy) + entry->matchNtuples = tbm_extract_page_tuple(&entry->matchResult, + entry->matchOffsets, + TBM_MAX_TUPLES_PER_PAGE); + /* * Reset counter to the beginning of entry->matchResult. Note: - * entry->offset is still greater than matchResult->ntuples if + * entry->offset is still greater than matchResult.ntuples if * matchResult is lossy. So, on next call we will get next * result from TIDBitmap. */ @@ -858,10 +868,10 @@ entryGetItem(GinState *ginstate, GinScanEntry entry, * We're now on the first page after advancePast which has any * items on it. If it's a lossy result, return that. */ - if (entry->matchResult->ntuples < 0) + if (entry->matchResult.lossy) { ItemPointerSetLossyPage(&entry->curItem, - entry->matchResult->blockno); + entry->matchResult.blockno); /* * We might as well fall out of the loop; we could not @@ -872,30 +882,35 @@ entryGetItem(GinState *ginstate, GinScanEntry entry, } /* - * Not a lossy page. Skip over any offsets <= advancePast, and - * return that. + * Not a lossy page. If tuple offsets were extracted, + * entry->matchNtuples must be > -1 */ - if (entry->matchResult->blockno == advancePastBlk) + Assert(entry->matchNtuples > -1); + + /* Skip over any offsets <= advancePast, and return that. */ + if (entry->matchResult.blockno == advancePastBlk) { + Assert(entry->matchNtuples > 0); + /* * First, do a quick check against the last offset on the * page. If that's > advancePast, so are all the other * offsets, so just go back to the top to get the next page. */ - if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff) + if (entry->matchOffsets[entry->matchNtuples - 1] <= advancePastOff) { - entry->offset = entry->matchResult->ntuples; + entry->offset = entry->matchNtuples; continue; } /* Otherwise scan to find the first item > advancePast */ - while (entry->matchResult->offsets[entry->offset] <= advancePastOff) + while (entry->matchOffsets[entry->offset] <= advancePastOff) entry->offset++; } ItemPointerSet(&entry->curItem, - entry->matchResult->blockno, - entry->matchResult->offsets[entry->offset]); + entry->matchResult.blockno, + entry->matchOffsets[entry->offset]); entry->offset++; /* Done unless we need to reduce the result */ diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index 71f38be90c3b1..a65acd8910493 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -4,7 +4,7 @@ * insert routines for the postgres inverted index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,14 +15,126 @@ #include "postgres.h" #include "access/gin_private.h" +#include "access/gin_tuple.h" +#include "access/parallel.h" +#include "access/table.h" #include "access/tableam.h" #include "access/xloginsert.h" +#include "catalog/index.h" +#include "catalog/pg_collation.h" +#include "commands/progress.h" #include "miscadmin.h" #include "nodes/execnodes.h" +#include "pgstat.h" #include "storage/bufmgr.h" #include "storage/predicate.h" +#include "tcop/tcopprot.h" +#include "utils/datum.h" #include "utils/memutils.h" #include "utils/rel.h" +#include "utils/builtins.h" + + +/* Magic numbers for parallel state sharing */ +#define PARALLEL_KEY_GIN_SHARED UINT64CONST(0xB000000000000001) +#define PARALLEL_KEY_TUPLESORT UINT64CONST(0xB000000000000002) +#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xB000000000000003) +#define PARALLEL_KEY_WAL_USAGE UINT64CONST(0xB000000000000004) +#define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xB000000000000005) + +/* + * Status for index builds performed in parallel. This is allocated in a + * dynamic shared memory segment. + */ +typedef struct GinBuildShared +{ + /* + * These fields are not modified during the build. They primarily exist + * for the benefit of worker processes that need to create state + * corresponding to that used by the leader. + */ + Oid heaprelid; + Oid indexrelid; + bool isconcurrent; + int scantuplesortstates; + + /* + * workersdonecv is used to monitor the progress of workers. All parallel + * participants must indicate that they are done before leader can use + * results built by the workers (and before leader can write the data into + * the index). + */ + ConditionVariable workersdonecv; + + /* + * mutex protects all following fields + * + * These fields contain status information of interest to GIN index builds + * that must work just the same when an index is built in parallel. + */ + slock_t mutex; + + /* + * Mutable state that is maintained by workers, and reported back to + * leader at end of the scans. + * + * nparticipantsdone is number of worker processes finished. + * + * reltuples is the total number of input heap tuples. + * + * indtuples is the total number of tuples that made it into the index. + */ + int nparticipantsdone; + double reltuples; + double indtuples; + + /* + * ParallelTableScanDescData data follows. Can't directly embed here, as + * implementations of the parallel table scan desc interface might need + * stronger alignment. + */ +} GinBuildShared; + +/* + * Return pointer to a GinBuildShared's parallel table scan. + * + * c.f. shm_toc_allocate as to why BUFFERALIGN is used, rather than just + * MAXALIGN. + */ +#define ParallelTableScanFromGinBuildShared(shared) \ + (ParallelTableScanDesc) ((char *) (shared) + BUFFERALIGN(sizeof(GinBuildShared))) + +/* + * Status for leader in parallel index build. + */ +typedef struct GinLeader +{ + /* parallel context itself */ + ParallelContext *pcxt; + + /* + * nparticipanttuplesorts is the exact number of worker processes + * successfully launched, plus one leader process if it participates as a + * worker (only DISABLE_LEADER_PARTICIPATION builds avoid leader + * participating as a worker). + */ + int nparticipanttuplesorts; + + /* + * Leader process convenience pointers to shared state (leader avoids TOC + * lookups). + * + * GinBuildShared is the shared state for entire build. sharedsort is the + * shared, tuplesort-managed state passed to each process tuplesort. + * snapshot is the snapshot used by the scan iff an MVCC snapshot is + * required. + */ + GinBuildShared *ginshared; + Sharedsort *sharedsort; + Snapshot snapshot; + WalUsage *walusage; + BufferUsage *bufferusage; +} GinLeader; typedef struct { @@ -32,9 +144,60 @@ typedef struct MemoryContext tmpCtx; MemoryContext funcCtx; BuildAccumulator accum; + ItemPointerData tid; + int work_mem; + + /* + * bs_leader is only present when a parallel index build is performed, and + * only in the leader process. + */ + GinLeader *bs_leader; + int bs_worker_id; + + /* used to pass information from workers to leader */ + double bs_numtuples; + double bs_reltuples; + + /* + * The sortstate is used by workers (including the leader). It has to be + * part of the build state, because that's the only thing passed to the + * build callback etc. + */ + Tuplesortstate *bs_sortstate; + + /* + * The sortstate used only within a single worker for the first merge pass + * happening there. In principle it doesn't need to be part of the build + * state and we could pass it around directly, but it's more convenient + * this way. And it's part of the build state, after all. + */ + Tuplesortstate *bs_worker_sort; } GinBuildState; +/* parallel index builds */ +static void _gin_begin_parallel(GinBuildState *buildstate, Relation heap, Relation index, + bool isconcurrent, int request); +static void _gin_end_parallel(GinLeader *ginleader, GinBuildState *state); +static Size _gin_parallel_estimate_shared(Relation heap, Snapshot snapshot); +static double _gin_parallel_heapscan(GinBuildState *state); +static double _gin_parallel_merge(GinBuildState *state); +static void _gin_leader_participate_as_worker(GinBuildState *buildstate, + Relation heap, Relation index); +static void _gin_parallel_scan_and_build(GinBuildState *state, + GinBuildShared *ginshared, + Sharedsort *sharedsort, + Relation heap, Relation index, + int sortmem, bool progress); + +static ItemPointer _gin_parse_tuple_items(GinTuple *a); +static Datum _gin_parse_tuple_key(GinTuple *a); + +static GinTuple *_gin_build_tuple(OffsetNumber attrnum, unsigned char category, + Datum key, int16 typlen, bool typbyval, + ItemPointerData *items, uint32 nitems, + Size *len); + /* * Adds array of item pointers to tuple's posting list, or * creates posting tree and tuple pointing to tree in case @@ -288,7 +451,7 @@ ginBuildCallback(Relation index, ItemPointer tid, Datum *values, values[i], isnull[i], tid); /* If we've maxed out our available memory, dump everything to the index */ - if (buildstate->accum.allocatedMemory >= (Size) maintenance_work_mem * 1024L) + if (buildstate->accum.allocatedMemory >= maintenance_work_mem * (Size) 1024) { ItemPointerData *list; Datum key; @@ -313,12 +476,114 @@ ginBuildCallback(Relation index, ItemPointer tid, Datum *values, MemoryContextSwitchTo(oldCtx); } +/* + * ginFlushBuildState + * Write all data from BuildAccumulator into the tuplesort. + */ +static void +ginFlushBuildState(GinBuildState *buildstate, Relation index) +{ + ItemPointerData *list; + Datum key; + GinNullCategory category; + uint32 nlist; + OffsetNumber attnum; + TupleDesc tdesc = RelationGetDescr(index); + + ginBeginBAScan(&buildstate->accum); + while ((list = ginGetBAEntry(&buildstate->accum, + &attnum, &key, &category, &nlist)) != NULL) + { + /* information about the key */ + Form_pg_attribute attr = TupleDescAttr(tdesc, (attnum - 1)); + + /* GIN tuple and tuple length */ + GinTuple *tup; + Size tuplen; + + /* there could be many entries, so be willing to abort here */ + CHECK_FOR_INTERRUPTS(); + + tup = _gin_build_tuple(attnum, category, + key, attr->attlen, attr->attbyval, + list, nlist, &tuplen); + + tuplesort_putgintuple(buildstate->bs_worker_sort, tup, tuplen); + + pfree(tup); + } + + MemoryContextReset(buildstate->tmpCtx); + ginInitBA(&buildstate->accum); +} + +/* + * ginBuildCallbackParallel + * Callback for the parallel index build. + * + * This is similar to the serial build callback ginBuildCallback, but + * instead of writing the accumulated entries into the index, each worker + * writes them into a (local) tuplesort. + * + * The worker then sorts and combines these entries, before writing them + * into a shared tuplesort for the leader (see _gin_parallel_scan_and_build + * for the whole process). + */ +static void +ginBuildCallbackParallel(Relation index, ItemPointer tid, Datum *values, + bool *isnull, bool tupleIsAlive, void *state) +{ + GinBuildState *buildstate = (GinBuildState *) state; + MemoryContext oldCtx; + int i; + + oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx); + + /* + * if scan wrapped around - flush accumulated entries and start anew + * + * With parallel scans, we don't have a guarantee the scan does not start + * half-way through the relation (serial builds disable sync scans and + * always start from block 0, parallel scans require allow_sync=true). + * + * Building the posting lists assumes the TIDs are monotonic and never go + * back, and the wrap around would break that. We handle that by detecting + * the wraparound, and flushing all entries. This means we'll later see + * two separate entries with non-overlapping TID lists (which can be + * combined by merge sort). + * + * To detect a wraparound, we remember the last TID seen by each worker + * (for any key). If the next TID seen by the worker is lower, the scan + * must have wrapped around. + */ + if (ItemPointerCompare(tid, &buildstate->tid) < 0) + ginFlushBuildState(buildstate, index); + + /* remember the TID we're about to process */ + buildstate->tid = *tid; + + for (i = 0; i < buildstate->ginstate.origTupdesc->natts; i++) + ginHeapTupleBulkInsert(buildstate, (OffsetNumber) (i + 1), + values[i], isnull[i], tid); + + /* + * If we've maxed out our available memory, dump everything to the + * tuplesort. We use half the per-worker fraction of maintenance_work_mem, + * the other half is used for the tuplesort. + */ + if (buildstate->accum.allocatedMemory >= buildstate->work_mem * (Size) 1024) + ginFlushBuildState(buildstate, index); + + MemoryContextSwitchTo(oldCtx); +} + IndexBuildResult * ginbuild(Relation heap, Relation index, IndexInfo *indexInfo) { IndexBuildResult *result; double reltuples; GinBuildState buildstate; + GinBuildState *state = &buildstate; Buffer RootBuffer, MetaBuffer; ItemPointerData *list; @@ -336,6 +601,12 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo) buildstate.indtuples = 0; memset(&buildstate.buildStats, 0, sizeof(GinStatsData)); + /* Initialize fields for parallel build too. */ + buildstate.bs_numtuples = 0; + buildstate.bs_reltuples = 0; + buildstate.bs_leader = NULL; + memset(&buildstate.tid, 0, sizeof(ItemPointerData)); + /* initialize the meta page */ MetaBuffer = GinNewBuffer(index); @@ -375,26 +646,96 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo) buildstate.accum.ginstate = &buildstate.ginstate; ginInitBA(&buildstate.accum); + /* Report table scan phase started */ + pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE, + PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN); + /* - * Do the heap scan. We disallow sync scan here because dataPlaceToPage - * prefers to receive tuples in TID order. + * Attempt to launch parallel worker scan when required + * + * XXX plan_create_index_workers makes the number of workers dependent on + * maintenance_work_mem, requiring 32MB for each worker. For GIN that's + * reasonable too, because we sort the data just like btree. It does + * ignore the memory used to accumulate data in memory (set by work_mem), + * but there is no way to communicate that to plan_create_index_workers. */ - reltuples = table_index_build_scan(heap, index, indexInfo, false, true, - ginBuildCallback, (void *) &buildstate, - NULL); + if (indexInfo->ii_ParallelWorkers > 0) + _gin_begin_parallel(state, heap, index, indexInfo->ii_Concurrent, + indexInfo->ii_ParallelWorkers); - /* dump remaining entries to the index */ - oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx); - ginBeginBAScan(&buildstate.accum); - while ((list = ginGetBAEntry(&buildstate.accum, - &attnum, &key, &category, &nlist)) != NULL) + /* + * If parallel build requested and at least one worker process was + * successfully launched, set up coordination state, wait for workers to + * complete. Then read all tuples from the shared tuplesort and insert + * them into the index. + * + * In serial mode, simply scan the table and build the index one index + * tuple at a time. + */ + if (state->bs_leader) { - /* there could be many entries, so be willing to abort here */ - CHECK_FOR_INTERRUPTS(); - ginEntryInsert(&buildstate.ginstate, attnum, key, category, - list, nlist, &buildstate.buildStats); + SortCoordinate coordinate; + + coordinate = (SortCoordinate) palloc0(sizeof(SortCoordinateData)); + coordinate->isWorker = false; + coordinate->nParticipants = + state->bs_leader->nparticipanttuplesorts; + coordinate->sharedsort = state->bs_leader->sharedsort; + + /* + * Begin leader tuplesort. + * + * In cases where parallelism is involved, the leader receives the + * same share of maintenance_work_mem as a serial sort (it is + * generally treated in the same way as a serial sort once we return). + * Parallel worker Tuplesortstates will have received only a fraction + * of maintenance_work_mem, though. + * + * We rely on the lifetime of the Leader Tuplesortstate almost not + * overlapping with any worker Tuplesortstate's lifetime. There may + * be some small overlap, but that's okay because we rely on leader + * Tuplesortstate only allocating a small, fixed amount of memory + * here. When its tuplesort_performsort() is called (by our caller), + * and significant amounts of memory are likely to be used, all + * workers must have already freed almost all memory held by their + * Tuplesortstates (they are about to go away completely, too). The + * overall effect is that maintenance_work_mem always represents an + * absolute high watermark on the amount of memory used by a CREATE + * INDEX operation, regardless of the use of parallelism or any other + * factor. + */ + state->bs_sortstate = + tuplesort_begin_index_gin(heap, index, + maintenance_work_mem, coordinate, + TUPLESORT_NONE); + + /* scan the relation in parallel and merge per-worker results */ + reltuples = _gin_parallel_merge(state); + + _gin_end_parallel(state->bs_leader, state); + } + else /* no parallel index build */ + { + /* + * Do the heap scan. We disallow sync scan here because + * dataPlaceToPage prefers to receive tuples in TID order. + */ + reltuples = table_index_build_scan(heap, index, indexInfo, false, true, + ginBuildCallback, &buildstate, NULL); + + /* dump remaining entries to the index */ + oldCtx = MemoryContextSwitchTo(buildstate.tmpCtx); + ginBeginBAScan(&buildstate.accum); + while ((list = ginGetBAEntry(&buildstate.accum, + &attnum, &key, &category, &nlist)) != NULL) + { + /* there could be many entries, so be willing to abort here */ + CHECK_FOR_INTERRUPTS(); + ginEntryInsert(&buildstate.ginstate, attnum, key, category, + list, nlist, &buildstate.buildStats); + } + MemoryContextSwitchTo(oldCtx); } - MemoryContextSwitchTo(oldCtx); MemoryContextDelete(buildstate.funcCtx); MemoryContextDelete(buildstate.tmpCtx); @@ -497,7 +838,7 @@ gininsert(Relation index, Datum *values, bool *isnull, oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context); ginstate = (GinState *) palloc(sizeof(GinState)); initGinState(ginstate, index); - indexInfo->ii_AmCache = (void *) ginstate; + indexInfo->ii_AmCache = ginstate; MemoryContextSwitchTo(oldCtx); } @@ -534,3 +875,1562 @@ gininsert(Relation index, Datum *values, bool *isnull, return false; } + +/* + * Create parallel context, and launch workers for leader. + * + * buildstate argument should be initialized (with the exception of the + * tuplesort states, which may later be created based on shared + * state initially set up here). + * + * isconcurrent indicates if operation is CREATE INDEX CONCURRENTLY. + * + * request is the target number of parallel worker processes to launch. + * + * Sets buildstate's GinLeader, which caller must use to shut down parallel + * mode by passing it to _gin_end_parallel() at the very end of its index + * build. If not even a single worker process can be launched, this is + * never set, and caller should proceed with a serial index build. + */ +static void +_gin_begin_parallel(GinBuildState *buildstate, Relation heap, Relation index, + bool isconcurrent, int request) +{ + ParallelContext *pcxt; + int scantuplesortstates; + Snapshot snapshot; + Size estginshared; + Size estsort; + GinBuildShared *ginshared; + Sharedsort *sharedsort; + GinLeader *ginleader = (GinLeader *) palloc0(sizeof(GinLeader)); + WalUsage *walusage; + BufferUsage *bufferusage; + bool leaderparticipates = true; + int querylen; + +#ifdef DISABLE_LEADER_PARTICIPATION + leaderparticipates = false; +#endif + + /* + * Enter parallel mode, and create context for parallel build of gin index + */ + EnterParallelMode(); + Assert(request > 0); + pcxt = CreateParallelContext("postgres", "_gin_parallel_build_main", + request); + + scantuplesortstates = leaderparticipates ? request + 1 : request; + + /* + * Prepare for scan of the base relation. In a normal index build, we use + * SnapshotAny because we must retrieve all tuples and do our own time + * qual checks (because we have to index RECENTLY_DEAD tuples). In a + * concurrent build, we take a regular MVCC snapshot and index whatever's + * live according to that. + */ + if (!isconcurrent) + snapshot = SnapshotAny; + else + snapshot = RegisterSnapshot(GetTransactionSnapshot()); + + /* + * Estimate size for our own PARALLEL_KEY_GIN_SHARED workspace. + */ + estginshared = _gin_parallel_estimate_shared(heap, snapshot); + shm_toc_estimate_chunk(&pcxt->estimator, estginshared); + estsort = tuplesort_estimate_shared(scantuplesortstates); + shm_toc_estimate_chunk(&pcxt->estimator, estsort); + + shm_toc_estimate_keys(&pcxt->estimator, 2); + + /* + * Estimate space for WalUsage and BufferUsage -- PARALLEL_KEY_WAL_USAGE + * and PARALLEL_KEY_BUFFER_USAGE. + * + * If there are no extensions loaded that care, we could skip this. We + * have no way of knowing whether anyone's looking at pgWalUsage or + * pgBufferUsage, so do it unconditionally. + */ + shm_toc_estimate_chunk(&pcxt->estimator, + mul_size(sizeof(WalUsage), pcxt->nworkers)); + shm_toc_estimate_keys(&pcxt->estimator, 1); + shm_toc_estimate_chunk(&pcxt->estimator, + mul_size(sizeof(BufferUsage), pcxt->nworkers)); + shm_toc_estimate_keys(&pcxt->estimator, 1); + + /* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */ + if (debug_query_string) + { + querylen = strlen(debug_query_string); + shm_toc_estimate_chunk(&pcxt->estimator, querylen + 1); + shm_toc_estimate_keys(&pcxt->estimator, 1); + } + else + querylen = 0; /* keep compiler quiet */ + + /* Everyone's had a chance to ask for space, so now create the DSM */ + InitializeParallelDSM(pcxt); + + /* If no DSM segment was available, back out (do serial build) */ + if (pcxt->seg == NULL) + { + if (IsMVCCSnapshot(snapshot)) + UnregisterSnapshot(snapshot); + DestroyParallelContext(pcxt); + ExitParallelMode(); + return; + } + + /* Store shared build state, for which we reserved space */ + ginshared = (GinBuildShared *) shm_toc_allocate(pcxt->toc, estginshared); + /* Initialize immutable state */ + ginshared->heaprelid = RelationGetRelid(heap); + ginshared->indexrelid = RelationGetRelid(index); + ginshared->isconcurrent = isconcurrent; + ginshared->scantuplesortstates = scantuplesortstates; + + ConditionVariableInit(&ginshared->workersdonecv); + SpinLockInit(&ginshared->mutex); + + /* Initialize mutable state */ + ginshared->nparticipantsdone = 0; + ginshared->reltuples = 0.0; + ginshared->indtuples = 0.0; + + table_parallelscan_initialize(heap, + ParallelTableScanFromGinBuildShared(ginshared), + snapshot); + + /* + * Store shared tuplesort-private state, for which we reserved space. + * Then, initialize opaque state using tuplesort routine. + */ + sharedsort = (Sharedsort *) shm_toc_allocate(pcxt->toc, estsort); + tuplesort_initialize_shared(sharedsort, scantuplesortstates, + pcxt->seg); + + shm_toc_insert(pcxt->toc, PARALLEL_KEY_GIN_SHARED, ginshared); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_TUPLESORT, sharedsort); + + /* Store query string for workers */ + if (debug_query_string) + { + char *sharedquery; + + sharedquery = (char *) shm_toc_allocate(pcxt->toc, querylen + 1); + memcpy(sharedquery, debug_query_string, querylen + 1); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_QUERY_TEXT, sharedquery); + } + + /* + * Allocate space for each worker's WalUsage and BufferUsage; no need to + * initialize. + */ + walusage = shm_toc_allocate(pcxt->toc, + mul_size(sizeof(WalUsage), pcxt->nworkers)); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_WAL_USAGE, walusage); + bufferusage = shm_toc_allocate(pcxt->toc, + mul_size(sizeof(BufferUsage), pcxt->nworkers)); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_BUFFER_USAGE, bufferusage); + + /* Launch workers, saving status for leader/caller */ + LaunchParallelWorkers(pcxt); + ginleader->pcxt = pcxt; + ginleader->nparticipanttuplesorts = pcxt->nworkers_launched; + if (leaderparticipates) + ginleader->nparticipanttuplesorts++; + ginleader->ginshared = ginshared; + ginleader->sharedsort = sharedsort; + ginleader->snapshot = snapshot; + ginleader->walusage = walusage; + ginleader->bufferusage = bufferusage; + + /* If no workers were successfully launched, back out (do serial build) */ + if (pcxt->nworkers_launched == 0) + { + _gin_end_parallel(ginleader, NULL); + return; + } + + /* Save leader state now that it's clear build will be parallel */ + buildstate->bs_leader = ginleader; + + /* Join heap scan ourselves */ + if (leaderparticipates) + _gin_leader_participate_as_worker(buildstate, heap, index); + + /* + * Caller needs to wait for all launched workers when we return. Make + * sure that the failure-to-start case will not hang forever. + */ + WaitForParallelWorkersToAttach(pcxt); +} + +/* + * Shut down workers, destroy parallel context, and end parallel mode. + */ +static void +_gin_end_parallel(GinLeader *ginleader, GinBuildState *state) +{ + int i; + + /* Shutdown worker processes */ + WaitForParallelWorkersToFinish(ginleader->pcxt); + + /* + * Next, accumulate WAL usage. (This must wait for the workers to finish, + * or we might get incomplete data.) + */ + for (i = 0; i < ginleader->pcxt->nworkers_launched; i++) + InstrAccumParallelQuery(&ginleader->bufferusage[i], &ginleader->walusage[i]); + + /* Free last reference to MVCC snapshot, if one was used */ + if (IsMVCCSnapshot(ginleader->snapshot)) + UnregisterSnapshot(ginleader->snapshot); + DestroyParallelContext(ginleader->pcxt); + ExitParallelMode(); +} + +/* + * Within leader, wait for end of heap scan. + * + * When called, parallel heap scan started by _gin_begin_parallel() will + * already be underway within worker processes (when leader participates + * as a worker, we should end up here just as workers are finishing). + * + * Returns the total number of heap tuples scanned. + */ +static double +_gin_parallel_heapscan(GinBuildState *state) +{ + GinBuildShared *ginshared = state->bs_leader->ginshared; + int nparticipanttuplesorts; + + nparticipanttuplesorts = state->bs_leader->nparticipanttuplesorts; + for (;;) + { + SpinLockAcquire(&ginshared->mutex); + if (ginshared->nparticipantsdone == nparticipanttuplesorts) + { + /* copy the data into leader state */ + state->bs_reltuples = ginshared->reltuples; + state->bs_numtuples = ginshared->indtuples; + + SpinLockRelease(&ginshared->mutex); + break; + } + SpinLockRelease(&ginshared->mutex); + + ConditionVariableSleep(&ginshared->workersdonecv, + WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN); + } + + ConditionVariableCancelSleep(); + + return state->bs_reltuples; +} + +/* + * Buffer used to accumulate TIDs from multiple GinTuples for the same key + * (we read these from the tuplesort, sorted by the key). + * + * This is similar to BuildAccumulator in that it's used to collect TIDs + * in memory before inserting them into the index, but it's much simpler + * as it only deals with a single index key at a time. + * + * When adding TIDs to the buffer, we make sure to keep them sorted, both + * during the initial table scan (and detecting when the scan wraps around), + * and during merging (where we do mergesort). + */ +typedef struct GinBuffer +{ + OffsetNumber attnum; + GinNullCategory category; + Datum key; /* 0 if no key (and keylen == 0) */ + Size keylen; /* number of bytes (not typlen) */ + + /* type info */ + int16 typlen; + bool typbyval; + + /* Number of TIDs to collect before attempt to write some out. */ + int maxitems; + + /* array of TID values */ + int nitems; + int nfrozen; + SortSupport ssup; /* for sorting/comparing keys */ + ItemPointerData *items; +} GinBuffer; + +/* + * Check that TID array contains valid values, and that it's sorted (if we + * expect it to be). + */ +static void +AssertCheckItemPointers(GinBuffer *buffer) +{ +#ifdef USE_ASSERT_CHECKING + /* we should not have a buffer with no TIDs to sort */ + Assert(buffer->items != NULL); + Assert(buffer->nitems > 0); + + for (int i = 0; i < buffer->nitems; i++) + { + Assert(ItemPointerIsValid(&buffer->items[i])); + + /* don't check ordering for the first TID item */ + if (i == 0) + continue; + + Assert(ItemPointerCompare(&buffer->items[i - 1], &buffer->items[i]) < 0); + } +#endif +} + +/* + * GinBuffer checks + * + * Make sure the nitems/items fields are consistent (either the array is empty + * or not empty, the fields need to agree). If there are items, check ordering. + */ +static void +AssertCheckGinBuffer(GinBuffer *buffer) +{ +#ifdef USE_ASSERT_CHECKING + /* if we have any items, the array must exist */ + Assert(!((buffer->nitems > 0) && (buffer->items == NULL))); + + /* + * The buffer may be empty, in which case we must not call the check of + * item pointers, because that assumes non-emptiness. + */ + if (buffer->nitems == 0) + return; + + /* Make sure the item pointers are valid and sorted. */ + AssertCheckItemPointers(buffer); +#endif +} + +/* + * GinBufferInit + * Initialize buffer to store tuples for a GIN index. + * + * Initialize the buffer used to accumulate TID for a single key at a time + * (we process the data sorted), so we know when we received all data for + * a given key. + * + * Initializes sort support procedures for all index attributes. + */ +static GinBuffer * +GinBufferInit(Relation index) +{ + GinBuffer *buffer = palloc0(sizeof(GinBuffer)); + int i, + nKeys; + TupleDesc desc = RelationGetDescr(index); + + /* + * How many items can we fit into the memory limit? We don't want to end + * with too many TIDs. and 64kB seems more than enough. But maybe this + * should be tied to maintenance_work_mem or something like that? + */ + buffer->maxitems = (64 * 1024L) / sizeof(ItemPointerData); + + nKeys = IndexRelationGetNumberOfKeyAttributes(index); + + buffer->ssup = palloc0(sizeof(SortSupportData) * nKeys); + + /* + * Lookup ordering operator for the index key data type, and initialize + * the sort support function. + */ + for (i = 0; i < nKeys; i++) + { + Oid cmpFunc; + SortSupport sortKey = &buffer->ssup[i]; + Form_pg_attribute att = TupleDescAttr(desc, i); + + sortKey->ssup_cxt = CurrentMemoryContext; + sortKey->ssup_collation = index->rd_indcollation[i]; + + if (!OidIsValid(sortKey->ssup_collation)) + sortKey->ssup_collation = DEFAULT_COLLATION_OID; + + sortKey->ssup_nulls_first = false; + sortKey->ssup_attno = i + 1; + sortKey->abbreviate = false; + + Assert(sortKey->ssup_attno != 0); + + /* + * If the compare proc isn't specified in the opclass definition, look + * up the index key type's default btree comparator. + */ + cmpFunc = index_getprocid(index, i + 1, GIN_COMPARE_PROC); + if (cmpFunc == InvalidOid) + { + TypeCacheEntry *typentry; + + typentry = lookup_type_cache(att->atttypid, + TYPECACHE_CMP_PROC_FINFO); + if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify a comparison function for type %s", + format_type_be(att->atttypid)))); + + cmpFunc = typentry->cmp_proc_finfo.fn_oid; + } + + PrepareSortSupportComparisonShim(cmpFunc, sortKey); + } + + return buffer; +} + +/* Is the buffer empty, i.e. has no TID values in the array? */ +static bool +GinBufferIsEmpty(GinBuffer *buffer) +{ + return (buffer->nitems == 0); +} + +/* + * GinBufferKeyEquals + * Can the buffer store TIDs for the provided GIN tuple (same key)? + * + * Compare if the tuple matches the already accumulated data in the GIN + * buffer. Compare scalar fields first, before the actual key. + * + * Returns true if the key matches, and the TID belongs to the buffer, or + * false if the key does not match. + */ +static bool +GinBufferKeyEquals(GinBuffer *buffer, GinTuple *tup) +{ + int r; + Datum tupkey; + + AssertCheckGinBuffer(buffer); + + if (tup->attrnum != buffer->attnum) + return false; + + /* same attribute should have the same type info */ + Assert(tup->typbyval == buffer->typbyval); + Assert(tup->typlen == buffer->typlen); + + if (tup->category != buffer->category) + return false; + + /* + * For NULL/empty keys, this means equality, for normal keys we need to + * compare the actual key value. + */ + if (buffer->category != GIN_CAT_NORM_KEY) + return true; + + /* + * For the tuple, get either the first sizeof(Datum) bytes for byval + * types, or a pointer to the beginning of the data array. + */ + tupkey = (buffer->typbyval) ? *(Datum *) tup->data : PointerGetDatum(tup->data); + + r = ApplySortComparator(buffer->key, false, + tupkey, false, + &buffer->ssup[buffer->attnum - 1]); + + return (r == 0); +} + +/* + * GinBufferShouldTrim + * Should we trim the list of item pointers? + * + * By trimming we understand writing out and removing the tuple IDs that + * we know can't change by future merges. We can deduce the TID up to which + * this is guaranteed from the "first" TID in each GIN tuple, which provides + * a "horizon" (for a given key) thanks to the sort. + * + * We don't want to do this too often - compressing longer TID lists is more + * efficient. But we also don't want to accumulate too many TIDs, for two + * reasons. First, it consumes memory and we might exceed maintenance_work_mem + * (or whatever limit applies), even if that's unlikely because TIDs are very + * small so we can fit a lot of them. Second, and more importantly, long TID + * lists are an issue if the scan wraps around, because a key may get a very + * wide list (with min/max TID for that key), forcing "full" mergesorts for + * every list merged into it (instead of the efficient append). + * + * So we look at two things when deciding if to trim - if the resulting list + * (after adding TIDs from the new tuple) would be too long, and if there is + * enough TIDs to trim (with values less than "first" TID from the new tuple), + * we do the trim. By enough we mean at least 128 TIDs (mostly an arbitrary + * number). + */ +static bool +GinBufferShouldTrim(GinBuffer *buffer, GinTuple *tup) +{ + /* not enough TIDs to trim (1024 is somewhat arbitrary number) */ + if (buffer->nfrozen < 1024) + return false; + + /* no need to trim if we have not hit the memory limit yet */ + if ((buffer->nitems + tup->nitems) < buffer->maxitems) + return false; + + /* + * OK, we have enough frozen TIDs to flush, and we have hit the memory + * limit, so it's time to write it out. + */ + return true; +} + +/* + * GinBufferStoreTuple + * Add data (especially TID list) from a GIN tuple to the buffer. + * + * The buffer is expected to be empty (in which case it's initialized), or + * having the same key. The TID values from the tuple are combined with the + * stored values using a merge sort. + * + * The tuples (for the same key) are expected to be sorted by first TID. But + * this does not guarantee the lists do not overlap, especially in the leader, + * because the workers process interleaving data. There should be no overlaps + * in a single worker - it could happen when the parallel scan wraps around, + * but we detect that and flush the data (see ginBuildCallbackParallel). + * + * By sorting the GinTuple not only by key, but also by the first TID, we make + * it more less likely the lists will overlap during merge. We merge them using + * mergesort, but it's cheaper to just append one list to the other. + * + * How often can the lists overlap? There should be no overlaps in workers, + * and in the leader we can see overlaps between lists built by different + * workers. But the workers merge the items as much as possible, so there + * should not be too many. + */ +static void +GinBufferStoreTuple(GinBuffer *buffer, GinTuple *tup) +{ + ItemPointerData *items; + Datum key; + + AssertCheckGinBuffer(buffer); + + key = _gin_parse_tuple_key(tup); + items = _gin_parse_tuple_items(tup); + + /* if the buffer is empty, set the fields (and copy the key) */ + if (GinBufferIsEmpty(buffer)) + { + buffer->category = tup->category; + buffer->keylen = tup->keylen; + buffer->attnum = tup->attrnum; + + buffer->typlen = tup->typlen; + buffer->typbyval = tup->typbyval; + + if (tup->category == GIN_CAT_NORM_KEY) + buffer->key = datumCopy(key, buffer->typbyval, buffer->typlen); + else + buffer->key = (Datum) 0; + } + + /* + * Try freeze TIDs at the beginning of the list, i.e. exclude them from + * the mergesort. We can do that with TIDs before the first TID in the new + * tuple we're about to add into the buffer. + * + * We do this incrementally when adding data into the in-memory buffer, + * and not later (e.g. when hitting a memory limit), because it allows us + * to skip the frozen data during the mergesort, making it cheaper. + */ + + /* + * Check if the last TID in the current list is frozen. This is the case + * when merging non-overlapping lists, e.g. in each parallel worker. + */ + if ((buffer->nitems > 0) && + (ItemPointerCompare(&buffer->items[buffer->nitems - 1], + GinTupleGetFirst(tup)) == 0)) + buffer->nfrozen = buffer->nitems; + + /* + * Now find the last TID we know to be frozen, i.e. the last TID right + * before the new GIN tuple. + * + * Start with the first not-yet-frozen tuple, and walk until we find the + * first TID that's higher. If we already know the whole list is frozen + * (i.e. nfrozen == nitems), this does nothing. + * + * XXX This might do a binary search for sufficiently long lists, but it + * does not seem worth the complexity. Overlapping lists should be rare + * common, TID comparisons are cheap, and we should quickly freeze most of + * the list. + */ + for (int i = buffer->nfrozen; i < buffer->nitems; i++) + { + /* Is the TID after the first TID of the new tuple? Can't freeze. */ + if (ItemPointerCompare(&buffer->items[i], + GinTupleGetFirst(tup)) > 0) + break; + + buffer->nfrozen++; + } + + /* add the new TIDs into the buffer, combine using merge-sort */ + { + int nnew; + ItemPointer new; + + /* + * Resize the array - we do this first, because we'll dereference the + * first unfrozen TID, which would fail if the array is NULL. We'll + * still pass 0 as number of elements in that array though. + */ + if (buffer->items == NULL) + buffer->items = palloc((buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); + else + buffer->items = repalloc(buffer->items, + (buffer->nitems + tup->nitems) * sizeof(ItemPointerData)); + + new = ginMergeItemPointers(&buffer->items[buffer->nfrozen], /* first unfrozen */ + (buffer->nitems - buffer->nfrozen), /* num of unfrozen */ + items, tup->nitems, &nnew); + + Assert(nnew == (tup->nitems + (buffer->nitems - buffer->nfrozen))); + + memcpy(&buffer->items[buffer->nfrozen], new, + nnew * sizeof(ItemPointerData)); + + pfree(new); + + buffer->nitems += tup->nitems; + + AssertCheckItemPointers(buffer); + } + + /* free the decompressed TID list */ + pfree(items); +} + +/* + * GinBufferReset + * Reset the buffer into a state as if it contains no data. + */ +static void +GinBufferReset(GinBuffer *buffer) +{ + Assert(!GinBufferIsEmpty(buffer)); + + /* release byref values, do nothing for by-val ones */ + if ((buffer->category == GIN_CAT_NORM_KEY) && !buffer->typbyval) + pfree(DatumGetPointer(buffer->key)); + + /* + * Not required, but makes it more likely to trigger NULL dereference if + * using the value incorrectly, etc. + */ + buffer->key = (Datum) 0; + + buffer->attnum = 0; + buffer->category = 0; + buffer->keylen = 0; + buffer->nitems = 0; + buffer->nfrozen = 0; + + buffer->typlen = 0; + buffer->typbyval = 0; +} + +/* + * GinBufferTrim + * Discard the "frozen" part of the TID list (which should have been + * written to disk/index before this call). + */ +static void +GinBufferTrim(GinBuffer *buffer) +{ + Assert((buffer->nfrozen > 0) && (buffer->nfrozen <= buffer->nitems)); + + memmove(&buffer->items[0], &buffer->items[buffer->nfrozen], + sizeof(ItemPointerData) * (buffer->nitems - buffer->nfrozen)); + + buffer->nitems -= buffer->nfrozen; + buffer->nfrozen = 0; +} + +/* + * GinBufferFree + * Release memory associated with the GinBuffer (including TID array). + */ +static void +GinBufferFree(GinBuffer *buffer) +{ + if (buffer->items) + pfree(buffer->items); + + /* release byref values, do nothing for by-val ones */ + if (!GinBufferIsEmpty(buffer) && + (buffer->category == GIN_CAT_NORM_KEY) && !buffer->typbyval) + pfree(DatumGetPointer(buffer->key)); + + pfree(buffer); +} + +/* + * GinBufferCanAddKey + * Check if a given GIN tuple can be added to the current buffer. + * + * Returns true if the buffer is either empty or for the same index key. + */ +static bool +GinBufferCanAddKey(GinBuffer *buffer, GinTuple *tup) +{ + /* empty buffer can accept data for any key */ + if (GinBufferIsEmpty(buffer)) + return true; + + /* otherwise just data for the same key */ + return GinBufferKeyEquals(buffer, tup); +} + +/* + * Within leader, wait for end of heap scan and merge per-worker results. + * + * After waiting for all workers to finish, merge the per-worker results into + * the complete index. The results from each worker are sorted by block number + * (start of the page range). While combining the per-worker results we merge + * summaries for the same page range, and also fill-in empty summaries for + * ranges without any tuples. + * + * Returns the total number of heap tuples scanned. + */ +static double +_gin_parallel_merge(GinBuildState *state) +{ + GinTuple *tup; + Size tuplen; + double reltuples = 0; + GinBuffer *buffer; + + /* GIN tuples from workers, merged by leader */ + double numtuples = 0; + + /* wait for workers to scan table and produce partial results */ + reltuples = _gin_parallel_heapscan(state); + + /* Execute the sort */ + pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE, + PROGRESS_GIN_PHASE_PERFORMSORT_2); + + /* do the actual sort in the leader */ + tuplesort_performsort(state->bs_sortstate); + + /* + * Initialize buffer to combine entries for the same key. + * + * The leader is allowed to use the whole maintenance_work_mem buffer to + * combine data. The parallel workers already completed. + */ + buffer = GinBufferInit(state->ginstate.index); + + /* + * Set the progress target for the next phase. Reset the block number + * values set by table_index_build_scan + */ + { + const int progress_index[] = { + PROGRESS_CREATEIDX_SUBPHASE, + PROGRESS_CREATEIDX_TUPLES_TOTAL, + PROGRESS_SCAN_BLOCKS_TOTAL, + PROGRESS_SCAN_BLOCKS_DONE + }; + const int64 progress_vals[] = { + PROGRESS_GIN_PHASE_MERGE_2, + state->bs_numtuples, + 0, 0 + }; + + pgstat_progress_update_multi_param(4, progress_index, progress_vals); + } + + /* + * Read the GIN tuples from the shared tuplesort, sorted by category and + * key. That probably gives us order matching how data is organized in the + * index. + * + * We don't insert the GIN tuples right away, but instead accumulate as + * many TIDs for the same key as possible, and then insert that at once. + * This way we don't need to decompress/recompress the posting lists, etc. + */ + while ((tup = tuplesort_getgintuple(state->bs_sortstate, &tuplen, true)) != NULL) + { + MemoryContext oldCtx; + + CHECK_FOR_INTERRUPTS(); + + /* + * If the buffer can accept the new GIN tuple, just store it there and + * we're done. If it's a different key (or maybe too much data) flush + * the current contents into the index first. + */ + if (!GinBufferCanAddKey(buffer, tup)) + { + /* + * Buffer is not empty and it's storing a different key - flush + * the data into the insert, and start a new entry for current + * GinTuple. + */ + AssertCheckItemPointers(buffer); + + oldCtx = MemoryContextSwitchTo(state->tmpCtx); + + ginEntryInsert(&state->ginstate, + buffer->attnum, buffer->key, buffer->category, + buffer->items, buffer->nitems, &state->buildStats); + + MemoryContextSwitchTo(oldCtx); + MemoryContextReset(state->tmpCtx); + + /* discard the existing data */ + GinBufferReset(buffer); + } + + /* + * We're about to add a GIN tuple to the buffer - check the memory + * limit first, and maybe write out some of the data into the index + * first, if needed (and possible). We only flush the part of the TID + * list that we know won't change, and only if there's enough data for + * compression to work well. + */ + if (GinBufferShouldTrim(buffer, tup)) + { + Assert(buffer->nfrozen > 0); + + /* + * Buffer is not empty and it's storing a different key - flush + * the data into the insert, and start a new entry for current + * GinTuple. + */ + AssertCheckItemPointers(buffer); + + oldCtx = MemoryContextSwitchTo(state->tmpCtx); + + ginEntryInsert(&state->ginstate, + buffer->attnum, buffer->key, buffer->category, + buffer->items, buffer->nfrozen, &state->buildStats); + + MemoryContextSwitchTo(oldCtx); + MemoryContextReset(state->tmpCtx); + + /* truncate the data we've just discarded */ + GinBufferTrim(buffer); + } + + /* + * Remember data for the current tuple (either remember the new key, + * or append if to the existing data). + */ + GinBufferStoreTuple(buffer, tup); + + /* Report progress */ + pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE, + ++numtuples); + } + + /* flush data remaining in the buffer (for the last key) */ + if (!GinBufferIsEmpty(buffer)) + { + AssertCheckItemPointers(buffer); + + ginEntryInsert(&state->ginstate, + buffer->attnum, buffer->key, buffer->category, + buffer->items, buffer->nitems, &state->buildStats); + + /* discard the existing data */ + GinBufferReset(buffer); + + /* Report progress */ + pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE, + ++numtuples); + } + + /* relase all the memory */ + GinBufferFree(buffer); + + tuplesort_end(state->bs_sortstate); + + return reltuples; +} + +/* + * Returns size of shared memory required to store state for a parallel + * gin index build based on the snapshot its parallel scan will use. + */ +static Size +_gin_parallel_estimate_shared(Relation heap, Snapshot snapshot) +{ + /* c.f. shm_toc_allocate as to why BUFFERALIGN is used */ + return add_size(BUFFERALIGN(sizeof(GinBuildShared)), + table_parallelscan_estimate(heap, snapshot)); +} + +/* + * Within leader, participate as a parallel worker. + */ +static void +_gin_leader_participate_as_worker(GinBuildState *buildstate, Relation heap, Relation index) +{ + GinLeader *ginleader = buildstate->bs_leader; + int sortmem; + + /* + * Might as well use reliable figure when doling out maintenance_work_mem + * (when requested number of workers were not launched, this will be + * somewhat higher than it is for other workers). + */ + sortmem = maintenance_work_mem / ginleader->nparticipanttuplesorts; + + /* Perform work common to all participants */ + _gin_parallel_scan_and_build(buildstate, ginleader->ginshared, + ginleader->sharedsort, heap, index, + sortmem, true); +} + +/* + * _gin_process_worker_data + * First phase of the key merging, happening in the worker. + * + * Depending on the number of distinct keys, the TID lists produced by the + * callback may be very short (due to frequent evictions in the callback). + * But combining many tiny lists is expensive, so we try to do as much as + * possible in the workers and only then pass the results to the leader. + * + * We read the tuples sorted by the key, and merge them into larger lists. + * At the moment there's no memory limit, so this will just produce one + * huge (sorted) list per key in each worker. Which means the leader will + * do a very limited number of mergesorts, which is good. + */ +static void +_gin_process_worker_data(GinBuildState *state, Tuplesortstate *worker_sort, + bool progress) +{ + GinTuple *tup; + Size tuplen; + + GinBuffer *buffer; + + /* + * Initialize buffer to combine entries for the same key. + * + * The workers are limited to the same amount of memory as during the sort + * in ginBuildCallbackParallel. But this probably should be the 32MB used + * during planning, just like there. + */ + buffer = GinBufferInit(state->ginstate.index); + + /* sort the raw per-worker data */ + if (progress) + pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE, + PROGRESS_GIN_PHASE_PERFORMSORT_1); + + tuplesort_performsort(state->bs_worker_sort); + + /* reset the number of GIN tuples produced by this worker */ + state->bs_numtuples = 0; + + if (progress) + pgstat_progress_update_param(PROGRESS_CREATEIDX_SUBPHASE, + PROGRESS_GIN_PHASE_MERGE_1); + + /* + * Read the GIN tuples from the shared tuplesort, sorted by the key, and + * merge them into larger chunks for the leader to combine. + */ + while ((tup = tuplesort_getgintuple(worker_sort, &tuplen, true)) != NULL) + { + + CHECK_FOR_INTERRUPTS(); + + /* + * If the buffer can accept the new GIN tuple, just store it there and + * we're done. If it's a different key (or maybe too much data) flush + * the current contents into the index first. + */ + if (!GinBufferCanAddKey(buffer, tup)) + { + GinTuple *ntup; + Size ntuplen; + + /* + * Buffer is not empty and it's storing a different key - flush + * the data into the insert, and start a new entry for current + * GinTuple. + */ + AssertCheckItemPointers(buffer); + + ntup = _gin_build_tuple(buffer->attnum, buffer->category, + buffer->key, buffer->typlen, buffer->typbyval, + buffer->items, buffer->nitems, &ntuplen); + + tuplesort_putgintuple(state->bs_sortstate, ntup, ntuplen); + state->bs_numtuples++; + + pfree(ntup); + + /* discard the existing data */ + GinBufferReset(buffer); + } + + /* + * We're about to add a GIN tuple to the buffer - check the memory + * limit first, and maybe write out some of the data into the index + * first, if needed (and possible). We only flush the part of the TID + * list that we know won't change, and only if there's enough data for + * compression to work well. + */ + if (GinBufferShouldTrim(buffer, tup)) + { + GinTuple *ntup; + Size ntuplen; + + Assert(buffer->nfrozen > 0); + + /* + * Buffer is not empty and it's storing a different key - flush + * the data into the insert, and start a new entry for current + * GinTuple. + */ + AssertCheckItemPointers(buffer); + + ntup = _gin_build_tuple(buffer->attnum, buffer->category, + buffer->key, buffer->typlen, buffer->typbyval, + buffer->items, buffer->nfrozen, &ntuplen); + + tuplesort_putgintuple(state->bs_sortstate, ntup, ntuplen); + + pfree(ntup); + + /* truncate the data we've just discarded */ + GinBufferTrim(buffer); + } + + /* + * Remember data for the current tuple (either remember the new key, + * or append if to the existing data). + */ + GinBufferStoreTuple(buffer, tup); + } + + /* flush data remaining in the buffer (for the last key) */ + if (!GinBufferIsEmpty(buffer)) + { + GinTuple *ntup; + Size ntuplen; + + AssertCheckItemPointers(buffer); + + ntup = _gin_build_tuple(buffer->attnum, buffer->category, + buffer->key, buffer->typlen, buffer->typbyval, + buffer->items, buffer->nitems, &ntuplen); + + tuplesort_putgintuple(state->bs_sortstate, ntup, ntuplen); + state->bs_numtuples++; + + pfree(ntup); + + /* discard the existing data */ + GinBufferReset(buffer); + } + + /* relase all the memory */ + GinBufferFree(buffer); + + tuplesort_end(worker_sort); +} + +/* + * Perform a worker's portion of a parallel GIN index build sort. + * + * This generates a tuplesort for the worker portion of the table. + * + * sortmem is the amount of working memory to use within each worker, + * expressed in KBs. + * + * When this returns, workers are done, and need only release resources. + * + * Before feeding data into a shared tuplesort (for the leader process), + * the workers process data in two phases. + * + * 1) A worker reads a portion of rows from the table, accumulates entries + * in memory, and flushes them into a private tuplesort (e.g. because of + * using too much memory). + * + * 2) The private tuplesort gets sorted (by key and TID), the worker reads + * the data again, and combines the entries as much as possible. This has + * to happen eventually, and this way it's done in workers in parallel. + * + * Finally, the combined entries are written into the shared tuplesort, so + * that the leader can process them. + * + * How well this works (compared to just writing entries into the shared + * tuplesort) depends on the data set. For large tables with many distinct + * keys this helps a lot. With many distinct keys it's likely the buffers has + * to be flushed often, generating many entries with the same key and short + * TID lists. These entries need to be sorted and merged at some point, + * before writing them to the index. The merging is quite expensive, it can + * easily be ~50% of a serial build, and doing as much of it in the workers + * means it's parallelized. The leader still has to merge results from the + * workers, but it's much more efficient to merge few large entries than + * many tiny ones. + * + * This also reduces the amount of data the workers pass to the leader through + * the shared tuplesort. OTOH the workers need more space for the private sort, + * possibly up to 2x of the data, if no entries be merged in a worker. But this + * is very unlikely, and the only consequence is inefficiency, so we ignore it. + */ +static void +_gin_parallel_scan_and_build(GinBuildState *state, + GinBuildShared *ginshared, Sharedsort *sharedsort, + Relation heap, Relation index, + int sortmem, bool progress) +{ + SortCoordinate coordinate; + TableScanDesc scan; + double reltuples; + IndexInfo *indexInfo; + + /* Initialize local tuplesort coordination state */ + coordinate = palloc0(sizeof(SortCoordinateData)); + coordinate->isWorker = true; + coordinate->nParticipants = -1; + coordinate->sharedsort = sharedsort; + + /* remember how much space is allowed for the accumulated entries */ + state->work_mem = (sortmem / 2); + + /* Begin "partial" tuplesort */ + state->bs_sortstate = tuplesort_begin_index_gin(heap, index, + state->work_mem, + coordinate, + TUPLESORT_NONE); + + /* Local per-worker sort of raw-data */ + state->bs_worker_sort = tuplesort_begin_index_gin(heap, index, + state->work_mem, + NULL, + TUPLESORT_NONE); + + /* Join parallel scan */ + indexInfo = BuildIndexInfo(index); + indexInfo->ii_Concurrent = ginshared->isconcurrent; + + scan = table_beginscan_parallel(heap, + ParallelTableScanFromGinBuildShared(ginshared)); + + reltuples = table_index_build_scan(heap, index, indexInfo, true, progress, + ginBuildCallbackParallel, state, scan); + + /* write remaining accumulated entries */ + ginFlushBuildState(state, index); + + /* + * Do the first phase of in-worker processing - sort the data produced by + * the callback, and combine them into much larger chunks and place that + * into the shared tuplestore for leader to process. + */ + _gin_process_worker_data(state, state->bs_worker_sort, progress); + + /* sort the GIN tuples built by this worker */ + tuplesort_performsort(state->bs_sortstate); + + state->bs_reltuples += reltuples; + + /* + * Done. Record ambuild statistics. + */ + SpinLockAcquire(&ginshared->mutex); + ginshared->nparticipantsdone++; + ginshared->reltuples += state->bs_reltuples; + ginshared->indtuples += state->bs_numtuples; + SpinLockRelease(&ginshared->mutex); + + /* Notify leader */ + ConditionVariableSignal(&ginshared->workersdonecv); + + tuplesort_end(state->bs_sortstate); +} + +/* + * Perform work within a launched parallel process. + */ +void +_gin_parallel_build_main(dsm_segment *seg, shm_toc *toc) +{ + char *sharedquery; + GinBuildShared *ginshared; + Sharedsort *sharedsort; + GinBuildState buildstate; + Relation heapRel; + Relation indexRel; + LOCKMODE heapLockmode; + LOCKMODE indexLockmode; + WalUsage *walusage; + BufferUsage *bufferusage; + int sortmem; + + /* + * The only possible status flag that can be set to the parallel worker is + * PROC_IN_SAFE_IC. + */ + Assert((MyProc->statusFlags == 0) || + (MyProc->statusFlags == PROC_IN_SAFE_IC)); + + /* Set debug_query_string for individual workers first */ + sharedquery = shm_toc_lookup(toc, PARALLEL_KEY_QUERY_TEXT, true); + debug_query_string = sharedquery; + + /* Report the query string from leader */ + pgstat_report_activity(STATE_RUNNING, debug_query_string); + + /* Look up gin shared state */ + ginshared = shm_toc_lookup(toc, PARALLEL_KEY_GIN_SHARED, false); + + /* Open relations using lock modes known to be obtained by index.c */ + if (!ginshared->isconcurrent) + { + heapLockmode = ShareLock; + indexLockmode = AccessExclusiveLock; + } + else + { + heapLockmode = ShareUpdateExclusiveLock; + indexLockmode = RowExclusiveLock; + } + + /* Open relations within worker */ + heapRel = table_open(ginshared->heaprelid, heapLockmode); + indexRel = index_open(ginshared->indexrelid, indexLockmode); + + /* initialize the GIN build state */ + initGinState(&buildstate.ginstate, indexRel); + buildstate.indtuples = 0; + memset(&buildstate.buildStats, 0, sizeof(GinStatsData)); + memset(&buildstate.tid, 0, sizeof(ItemPointerData)); + + /* + * create a temporary memory context that is used to hold data not yet + * dumped out to the index + */ + buildstate.tmpCtx = AllocSetContextCreate(CurrentMemoryContext, + "Gin build temporary context", + ALLOCSET_DEFAULT_SIZES); + + /* + * create a temporary memory context that is used for calling + * ginExtractEntries(), and can be reset after each tuple + */ + buildstate.funcCtx = AllocSetContextCreate(CurrentMemoryContext, + "Gin build temporary context for user-defined function", + ALLOCSET_DEFAULT_SIZES); + + buildstate.accum.ginstate = &buildstate.ginstate; + ginInitBA(&buildstate.accum); + + + /* Look up shared state private to tuplesort.c */ + sharedsort = shm_toc_lookup(toc, PARALLEL_KEY_TUPLESORT, false); + tuplesort_attach_shared(sharedsort, seg); + + /* Prepare to track buffer usage during parallel execution */ + InstrStartParallelQuery(); + + /* + * Might as well use reliable figure when doling out maintenance_work_mem + * (when requested number of workers were not launched, this will be + * somewhat higher than it is for other workers). + */ + sortmem = maintenance_work_mem / ginshared->scantuplesortstates; + + _gin_parallel_scan_and_build(&buildstate, ginshared, sharedsort, + heapRel, indexRel, sortmem, false); + + /* Report WAL/buffer usage during parallel execution */ + bufferusage = shm_toc_lookup(toc, PARALLEL_KEY_BUFFER_USAGE, false); + walusage = shm_toc_lookup(toc, PARALLEL_KEY_WAL_USAGE, false); + InstrEndParallelQuery(&bufferusage[ParallelWorkerNumber], + &walusage[ParallelWorkerNumber]); + + index_close(indexRel, indexLockmode); + table_close(heapRel, heapLockmode); +} + +/* + * Used to keep track of compressed TID lists when building a GIN tuple. + */ +typedef struct +{ + dlist_node node; /* linked list pointers */ + GinPostingList *seg; +} GinSegmentInfo; + +/* + * _gin_build_tuple + * Serialize the state for an index key into a tuple for tuplesort. + * + * The tuple has a number of scalar fields (mostly matching the build state), + * and then a data array that stores the key first, and then the TID list. + * + * For by-reference data types, we store the actual data. For by-val types + * we simply copy the whole Datum, so that we don't have to care about stuff + * like endianess etc. We could make it a little bit smaller, but it's not + * worth it - it's a tiny fraction of the data, and we need to MAXALIGN the + * start of the TID list anyway. So we wouldn't save anything. + * + * The TID list is serialized as compressed - it's highly compressible, and + * we already have ginCompressPostingList for this purpose. The list may be + * pretty long, so we compress it into multiple segments and then copy all + * of that into the GIN tuple. + */ +static GinTuple * +_gin_build_tuple(OffsetNumber attrnum, unsigned char category, + Datum key, int16 typlen, bool typbyval, + ItemPointerData *items, uint32 nitems, + Size *len) +{ + GinTuple *tuple; + char *ptr; + + Size tuplen; + int keylen; + + dlist_mutable_iter iter; + dlist_head segments; + int ncompressed; + Size compresslen; + + /* + * Calculate how long is the key value. Only keys with GIN_CAT_NORM_KEY + * have actual non-empty key. We include varlena headers and \0 bytes for + * strings, to make it easier to access the data in-line. + * + * For byval types we simply copy the whole Datum. We could store just the + * necessary bytes, but this is simpler to work with and not worth the + * extra complexity. Moreover we still need to do the MAXALIGN to allow + * direct access to items pointers. + * + * XXX Note that for byval types we store the whole datum, no matter what + * the typlen value is. + */ + if (category != GIN_CAT_NORM_KEY) + keylen = 0; + else if (typbyval) + keylen = sizeof(Datum); + else if (typlen > 0) + keylen = typlen; + else if (typlen == -1) + keylen = VARSIZE_ANY(key); + else if (typlen == -2) + keylen = strlen(DatumGetPointer(key)) + 1; + else + elog(ERROR, "unexpected typlen value (%d)", typlen); + + /* compress the item pointers */ + ncompressed = 0; + compresslen = 0; + dlist_init(&segments); + + /* generate compressed segments of TID list chunks */ + while (ncompressed < nitems) + { + int cnt; + GinSegmentInfo *seginfo = palloc(sizeof(GinSegmentInfo)); + + seginfo->seg = ginCompressPostingList(&items[ncompressed], + (nitems - ncompressed), + UINT16_MAX, + &cnt); + + ncompressed += cnt; + compresslen += SizeOfGinPostingList(seginfo->seg); + + dlist_push_tail(&segments, &seginfo->node); + } + + /* + * Determine GIN tuple length with all the data included. Be careful about + * alignment, to allow direct access to compressed segments (those require + * only SHORTALIGN). + */ + tuplen = SHORTALIGN(offsetof(GinTuple, data) + keylen) + compresslen; + + *len = tuplen; + + /* + * Allocate space for the whole GIN tuple. + * + * The palloc0 is needed - writetup_index_gin will write the whole tuple + * to disk, so we need to make sure the padding bytes are defined + * (otherwise valgrind would report this). + */ + tuple = palloc0(tuplen); + + tuple->tuplen = tuplen; + tuple->attrnum = attrnum; + tuple->category = category; + tuple->keylen = keylen; + tuple->nitems = nitems; + + /* key type info */ + tuple->typlen = typlen; + tuple->typbyval = typbyval; + + /* + * Copy the key and items into the tuple. First the key value, which we + * can simply copy right at the beginning of the data array. + */ + if (category == GIN_CAT_NORM_KEY) + { + if (typbyval) + { + memcpy(tuple->data, &key, sizeof(Datum)); + } + else if (typlen > 0) /* byref, fixed length */ + { + memcpy(tuple->data, DatumGetPointer(key), typlen); + } + else if (typlen == -1) + { + memcpy(tuple->data, DatumGetPointer(key), keylen); + } + else if (typlen == -2) + { + memcpy(tuple->data, DatumGetPointer(key), keylen); + } + } + + /* finally, copy the TIDs into the array */ + ptr = (char *) tuple + SHORTALIGN(offsetof(GinTuple, data) + keylen); + + /* copy in the compressed data, and free the segments */ + dlist_foreach_modify(iter, &segments) + { + GinSegmentInfo *seginfo = dlist_container(GinSegmentInfo, node, iter.cur); + + memcpy(ptr, seginfo->seg, SizeOfGinPostingList(seginfo->seg)); + + ptr += SizeOfGinPostingList(seginfo->seg); + + dlist_delete(&seginfo->node); + + pfree(seginfo->seg); + pfree(seginfo); + } + + return tuple; +} + +/* + * _gin_parse_tuple_key + * Return a Datum representing the key stored in the tuple. + * + * Most of the tuple fields are directly accessible, the only thing that + * needs more care is the key and the TID list. + * + * For the key, this returns a regular Datum representing it. It's either the + * actual key value, or a pointer to the beginning of the data array (which is + * where the data was copied by _gin_build_tuple). + */ +static Datum +_gin_parse_tuple_key(GinTuple *a) +{ + Datum key; + + if (a->category != GIN_CAT_NORM_KEY) + return (Datum) 0; + + if (a->typbyval) + { + memcpy(&key, a->data, a->keylen); + return key; + } + + return PointerGetDatum(a->data); +} + +/* +* _gin_parse_tuple_items + * Return a pointer to a palloc'd array of decompressed TID array. + */ +static ItemPointer +_gin_parse_tuple_items(GinTuple *a) +{ + int len; + char *ptr; + int ndecoded; + ItemPointer items; + + len = a->tuplen - SHORTALIGN(offsetof(GinTuple, data) + a->keylen); + ptr = (char *) a + SHORTALIGN(offsetof(GinTuple, data) + a->keylen); + + items = ginPostingListDecodeAllSegments((GinPostingList *) ptr, len, &ndecoded); + + Assert(ndecoded == a->nitems); + + return (ItemPointer) items; +} + +/* + * _gin_compare_tuples + * Compare GIN tuples, used by tuplesort during parallel index build. + * + * The scalar fields (attrnum, category) are compared first, the key value is + * compared last. The comparisons are done using type-specific sort support + * functions. + * + * If the key value matches, we compare the first TID value in the TID list, + * which means the tuples are merged in an order in which they are most + * likely to be simply concatenated. (This "first" TID will also allow us + * to determine a point up to which the list is fully determined and can be + * written into the index to enforce a memory limit etc.) + */ +int +_gin_compare_tuples(GinTuple *a, GinTuple *b, SortSupport ssup) +{ + int r; + Datum keya, + keyb; + + if (a->attrnum < b->attrnum) + return -1; + + if (a->attrnum > b->attrnum) + return 1; + + if (a->category < b->category) + return -1; + + if (a->category > b->category) + return 1; + + if (a->category == GIN_CAT_NORM_KEY) + { + keya = _gin_parse_tuple_key(a); + keyb = _gin_parse_tuple_key(b); + + r = ApplySortComparator(keya, false, + keyb, false, + &ssup[a->attrnum - 1]); + + /* if the key is the same, consider the first TID in the array */ + return (r != 0) ? r : ItemPointerCompare(GinTupleGetFirst(a), + GinTupleGetFirst(b)); + } + + return ItemPointerCompare(GinTupleGetFirst(a), + GinTupleGetFirst(b)); +} diff --git a/src/backend/access/gin/ginlogic.c b/src/backend/access/gin/ginlogic.c index 28caf91f85736..ff456247cefac 100644 --- a/src/backend/access/gin/ginlogic.c +++ b/src/backend/access/gin/ginlogic.c @@ -24,7 +24,7 @@ * is used for.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -140,7 +140,9 @@ shimBoolConsistentFn(GinScanKey key) * every combination is O(n^2), so this is only feasible for a small number of * MAYBE inputs. * - * NB: This function modifies the key->entryRes array! + * NB: This function modifies the key->entryRes array. For now that's okay + * so long as we restore the entry-time contents before returning. This may + * need revisiting if we ever invent multithreaded GIN scans, though. */ static GinTernaryValue shimTriConsistentFn(GinScanKey key) @@ -149,7 +151,7 @@ shimTriConsistentFn(GinScanKey key) int maybeEntries[MAX_MAYBE_ENTRIES]; int i; bool boolResult; - bool recheck = false; + bool recheck; GinTernaryValue curResult; /* @@ -169,8 +171,8 @@ shimTriConsistentFn(GinScanKey key) } /* - * If none of the inputs were MAYBE, so we can just call consistent - * function as is. + * If none of the inputs were MAYBE, we can just call the consistent + * function as-is. */ if (nmaybe == 0) return directBoolConsistentFn(key); @@ -179,6 +181,7 @@ shimTriConsistentFn(GinScanKey key) for (i = 0; i < nmaybe; i++) key->entryRes[maybeEntries[i]] = GIN_FALSE; curResult = directBoolConsistentFn(key); + recheck = key->recheckCurItem; for (;;) { @@ -200,13 +203,20 @@ shimTriConsistentFn(GinScanKey key) recheck |= key->recheckCurItem; if (curResult != boolResult) - return GIN_MAYBE; + { + curResult = GIN_MAYBE; + break; + } } /* TRUE with recheck is taken to mean MAYBE */ if (curResult == GIN_TRUE && recheck) curResult = GIN_MAYBE; + /* We must restore the original state of the entryRes array */ + for (i = 0; i < nmaybe; i++) + key->entryRes[maybeEntries[i]] = GIN_MAYBE; + return curResult; } diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c index 708f9f49ec162..48eadec87b0b1 100644 --- a/src/backend/access/gin/ginpostinglist.c +++ b/src/backend/access/gin/ginpostinglist.c @@ -4,7 +4,7 @@ * routines for dealing with posting lists. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c index af24d38544eb9..c2d1771bd77b5 100644 --- a/src/backend/access/gin/ginscan.c +++ b/src/backend/access/gin/ginscan.c @@ -4,7 +4,7 @@ * routines to manage scans of inverted index relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -68,8 +68,13 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, * * Entries with non-null extra_data are never considered identical, since * we can't know exactly what the opclass might be doing with that. + * + * Also, give up de-duplication once we have 100 entries. That avoids + * spending O(N^2) time on probably-fruitless de-duplication of large + * search-key sets. The threshold of 100 is arbitrary but matches + * predtest.c's threshold for what's a large array. */ - if (extra_data == NULL) + if (extra_data == NULL && so->totalentries < 100) { for (i = 0; i < so->totalentries; i++) { @@ -106,7 +111,8 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum, ItemPointerSetMin(&scanEntry->curItem); scanEntry->matchBitmap = NULL; scanEntry->matchIterator = NULL; - scanEntry->matchResult = NULL; + scanEntry->matchResult.blockno = InvalidBlockNumber; + scanEntry->matchNtuples = -1; scanEntry->list = NULL; scanEntry->nlist = 0; scanEntry->offset = InvalidOffsetNumber; @@ -246,7 +252,7 @@ ginFreeScanKeys(GinScanOpaque so) if (entry->list) pfree(entry->list); if (entry->matchIterator) - tbm_end_iterate(entry->matchIterator); + tbm_end_private_iterate(entry->matchIterator); if (entry->matchBitmap) tbm_free(entry->matchBitmap); } @@ -436,6 +442,8 @@ ginNewScanKey(IndexScanDesc scan) MemoryContextSwitchTo(oldCtx); pgstat_count_index_scan(scan->indexRelation); + if (scan->instrument) + scan->instrument->nsearches++; } void @@ -447,10 +455,7 @@ ginrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ginFreeScanKeys(so); if (scankey && scan->numberOfKeys > 0) - { - memmove(scan->keyData, scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); - } + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); } diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 5747ae6a4cabe..78f7b7a2495cf 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -4,7 +4,7 @@ * Utility routines for the Postgres inverted index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -20,6 +20,7 @@ #include "access/xloginsert.h" #include "catalog/pg_collation.h" #include "catalog/pg_type.h" +#include "commands/progress.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "storage/indexfsm.h" @@ -43,6 +44,9 @@ ginhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = GIN_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; @@ -53,7 +57,7 @@ ginhandler(PG_FUNCTION_ARGS) amroutine->amclusterable = false; amroutine->ampredlocks = true; amroutine->amcanparallel = false; - amroutine->amcanbuildparallel = false; + amroutine->amcanbuildparallel = true; amroutine->amcaninclude = false; amroutine->amusemaintenanceworkmem = true; amroutine->amsummarizing = false; @@ -69,9 +73,10 @@ ginhandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = ginvacuumcleanup; amroutine->amcanreturn = NULL; amroutine->amcostestimate = gincostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = ginoptions; amroutine->amproperty = NULL; - amroutine->ambuildphasename = NULL; + amroutine->ambuildphasename = ginbuildphasename; amroutine->amvalidate = ginvalidate; amroutine->amadjustmembers = ginadjustmembers; amroutine->ambeginscan = ginbeginscan; @@ -688,7 +693,7 @@ ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build) memcpy(&data.metadata, metadata, sizeof(GinMetaPageData)); XLogBeginInsert(); - XLogRegisterData((char *) &data, sizeof(ginxlogUpdateMeta)); + XLogRegisterData(&data, sizeof(ginxlogUpdateMeta)); XLogRegisterBuffer(0, metabuffer, REGBUF_WILL_INIT | REGBUF_STANDARD); recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_UPDATE_META_PAGE); @@ -699,3 +704,28 @@ ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build) END_CRIT_SECTION(); } + +/* + * ginbuildphasename() -- Return name of index build phase. + */ +char * +ginbuildphasename(int64 phasenum) +{ + switch (phasenum) + { + case PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE: + return "initializing"; + case PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN: + return "scanning table"; + case PROGRESS_GIN_PHASE_PERFORMSORT_1: + return "sorting tuples (workers)"; + case PROGRESS_GIN_PHASE_MERGE_1: + return "merging tuples (workers)"; + case PROGRESS_GIN_PHASE_PERFORMSORT_2: + return "sorting tuples"; + case PROGRESS_GIN_PHASE_MERGE_2: + return "merging tuples"; + default: + return NULL; + } +} diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index b3f415e2849a0..fbbe3a6dd7046 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -4,7 +4,7 @@ * delete & vacuum routines for the postgres GIN * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,7 +19,6 @@ #include "access/xloginsert.h" #include "commands/vacuum.h" #include "miscadmin.h" -#include "postmaster/autovacuum.h" #include "storage/indexfsm.h" #include "storage/lmgr.h" #include "storage/predicate.h" @@ -217,7 +216,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn data.rightLink = GinPageGetOpaque(page)->rightlink; data.deleteXid = GinPageGetDeleteXid(page); - XLogRegisterData((char *) &data, sizeof(ginxlogDeletePage)); + XLogRegisterData(&data, sizeof(ginxlogDeletePage)); recptr = XLogInsert(RM_GIN_ID, XLOG_GIN_DELETE_PAGE); PageSetLSN(page, recptr); @@ -663,12 +662,12 @@ ginbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, UnlockReleaseBuffer(buffer); } - vacuum_delay_point(); + vacuum_delay_point(false); for (i = 0; i < nRoot; i++) { ginVacuumPostingTree(&gvs, rootOfPostingTree[i]); - vacuum_delay_point(); + vacuum_delay_point(false); } if (blkno == InvalidBlockNumber) /* rightmost page */ @@ -749,7 +748,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats) Buffer buffer; Page page; - vacuum_delay_point(); + vacuum_delay_point(false); buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno, RBM_NORMAL, info->strategy); diff --git a/src/backend/access/gin/ginvalidate.c b/src/backend/access/gin/ginvalidate.c index 74420a129aa48..5b0bfe8cc1dbc 100644 --- a/src/backend/access/gin/ginvalidate.c +++ b/src/backend/access/gin/ginvalidate.c @@ -3,7 +3,7 @@ * ginvalidate.c * Opclass validator for GIN. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,8 +19,8 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" +#include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/syscache.h" @@ -37,8 +37,6 @@ ginvalidate(Oid opclassoid) Oid opcintype; Oid opckeytype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -61,12 +59,7 @@ ginvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -264,7 +257,6 @@ ginvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c index 07ba0b559eaea..55a1ec09776ba 100644 --- a/src/backend/access/gin/ginxlog.c +++ b/src/backend/access/gin/ginxlog.c @@ -4,7 +4,7 @@ * WAL replay logic for inverted index. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gin/meson.build b/src/backend/access/gin/meson.build index bd52c98f14f56..6472831476d64 100644 --- a/src/backend/access/gin/meson.build +++ b/src/backend/access/gin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'ginarrayproc.c', diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index ed4ffa63a7720..7b24380c97801 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -4,7 +4,7 @@ * interface routines for the postgres GiST index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -43,7 +43,7 @@ static void gistprunepage(Relation rel, Page page, Buffer buffer, #define ROTATEDIST(d) do { \ - SplitPageLayout *tmp=(SplitPageLayout*)palloc0(sizeof(SplitPageLayout)); \ + SplitPageLayout *tmp = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout)); \ tmp->block.blkno = InvalidBlockNumber; \ tmp->buffer = InvalidBuffer; \ tmp->next = (d); \ @@ -65,6 +65,9 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = GIST_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = true; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; @@ -91,6 +94,7 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = gistvacuumcleanup; amroutine->amcanreturn = gistcanreturn; amroutine->amcostestimate = gistcostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = gistoptions; amroutine->amproperty = gistproperty; amroutine->ambuildphasename = NULL; @@ -106,6 +110,8 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = gisttranslatecmptype; PG_RETURN_POINTER(amroutine); } @@ -172,14 +178,13 @@ gistinsert(Relation r, Datum *values, bool *isnull, oldCxt = MemoryContextSwitchTo(indexInfo->ii_Context); giststate = initGISTstate(r); giststate->tempCxt = createTempGistContext(); - indexInfo->ii_AmCache = (void *) giststate; + indexInfo->ii_AmCache = giststate; MemoryContextSwitchTo(oldCxt); } oldCxt = MemoryContextSwitchTo(giststate->tempCxt); - itup = gistFormTuple(giststate, r, - values, isnull, true /* size is currently bogus */ ); + itup = gistFormTuple(giststate, r, values, isnull, true); itup->t_tid = *ht_ctid; gistdoinsert(r, itup, 0, giststate, heapRel, false); @@ -626,7 +631,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate, } /* - * Workhouse routine for doing insertion into a GiST index. Note that + * Workhorse routine for doing insertion into a GiST index. Note that * this routine assumes it is invoked in a short-lived memory context, * so it does not bother releasing palloc'd allocations. */ @@ -1043,12 +1048,19 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child, bool is_build) /* * The page has changed since we looked. During normal operation, every * update of a page changes its LSN, so the LSN we memorized should have - * changed too. During index build, however, we don't WAL-log the changes - * until we have built the index, so the LSN doesn't change. There is no - * concurrent activity during index build, but we might have changed the - * parent ourselves. + * changed too. + * + * During index build, however, we don't WAL-log the changes until we have + * built the index, so the LSN doesn't change. There is no concurrent + * activity during index build, but we might have changed the parent + * ourselves. + * + * We will also get here if child->downlinkoffnum is invalid. That happens + * if 'parent' had been updated by an earlier call to this function on its + * grandchild, which had to move right. */ - Assert(parent->lsn != PageGetLSN(parent->page) || is_build); + Assert(parent->lsn != PageGetLSN(parent->page) || is_build || + child->downlinkoffnum == InvalidOffsetNumber); /* * Scan the page to re-find the downlink. If the page was split, it might @@ -1557,9 +1569,8 @@ initGISTstate(Relation index) * tuples during page split. Also, B-tree is not adjusting tuples on * internal pages the way GiST does. */ - giststate->nonLeafTupdesc = CreateTupleDescCopyConstr(index->rd_att); - giststate->nonLeafTupdesc->natts = - IndexRelationGetNumberOfKeyAttributes(index); + giststate->nonLeafTupdesc = CreateTupleDescTruncatedCopy(index->rd_att, + IndexRelationGetNumberOfKeyAttributes(index)); for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(index); i++) { diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index ba06df30fafeb..9e707167d984b 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -22,7 +22,7 @@ * tuples (unless buffering mode is disabled). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -273,7 +273,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo) /* Scan the table, adding all tuples to the tuplesort */ reltuples = table_index_build_scan(heap, index, indexInfo, true, true, gistSortedBuildCallback, - (void *) &buildstate, NULL); + &buildstate, NULL); /* * Perform the sort and build index pages. @@ -312,7 +312,7 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo) /* Scan the table, inserting all the tuples to the index. */ reltuples = table_index_build_scan(heap, index, indexInfo, true, true, gistBuildCallback, - (void *) &buildstate, NULL); + &buildstate, NULL); /* * If buffering was used, flush out all the tuples that are still in @@ -657,10 +657,12 @@ gistInitBuffering(GISTBuildState *buildstate) itupMinSize = (Size) MAXALIGN(sizeof(IndexTupleData)); for (i = 0; i < index->rd_att->natts; i++) { - if (TupleDescAttr(index->rd_att, i)->attlen < 0) + CompactAttribute *attr = TupleDescCompactAttr(index->rd_att, i); + + if (attr->attlen < 0) itupMinSize += VARHDRSZ; else - itupMinSize += TupleDescAttr(index->rd_att, i)->attlen; + itupMinSize += attr->attlen; } /* Calculate average and maximal number of index tuples which fit to page */ diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c index 4c2301da00500..0707254d18ea1 100644 --- a/src/backend/access/gist/gistbuildbuffers.c +++ b/src/backend/access/gist/gistbuildbuffers.c @@ -4,7 +4,7 @@ * node buffer management functions for GiST buffering build algorithm. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index b35b8a9757752..387d997234537 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -4,7 +4,7 @@ * fetch tuples from a GiST scan. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -625,6 +625,8 @@ gistgettuple(IndexScanDesc scan, ScanDirection dir) GISTSearchItem fakeItem; pgstat_count_index_scan(scan->indexRelation); + if (scan->instrument) + scan->instrument->nsearches++; so->firstCall = false; so->curPageData = so->nPageData = 0; @@ -750,6 +752,8 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) return 0; pgstat_count_index_scan(scan->indexRelation); + if (scan->instrument) + scan->instrument->nsearches++; /* Begin the scan by processing the root page */ so->curPageData = so->nPageData = 0; diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c index 781c2f7358814..392163cb22900 100644 --- a/src/backend/access/gist/gistproc.c +++ b/src/backend/access/gist/gistproc.c @@ -7,7 +7,7 @@ * This gives R-tree behavior, with Guttman's poly-time split algorithm. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index e05801e2f5bf1..700fa959d03d8 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -4,7 +4,7 @@ * routines to manage scans on GiST index relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -233,8 +233,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys, fn_extras[i] = scan->keyData[i].sk_func.fn_extra; } - memmove(scan->keyData, key, - scan->numberOfKeys * sizeof(ScanKeyData)); + memcpy(scan->keyData, key, scan->numberOfKeys * sizeof(ScanKeyData)); /* * Modify the scan key so that the Consistent method is called for all @@ -289,8 +288,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys, fn_extras[i] = scan->orderByData[i].sk_func.fn_extra; } - memmove(scan->orderByData, orderbys, - scan->numberOfOrderBys * sizeof(ScanKeyData)); + memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData)); so->orderByTypes = (Oid *) palloc(scan->numberOfOrderBys * sizeof(Oid)); diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c index f56b92c31361b..49838ceb07b19 100644 --- a/src/backend/access/gist/gistsplit.c +++ b/src/backend/access/gist/gistsplit.c @@ -15,7 +15,7 @@ * gistSplitByKey() is the entry point to this file. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index 78e98d68b1518..c0aa7d0222f39 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -4,7 +4,7 @@ * utilities routines for the postgres GiST index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -21,6 +21,7 @@ #include "common/pg_prng.h" #include "storage/indexfsm.h" #include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/snapmgr.h" @@ -1055,3 +1056,56 @@ gistGetFakeLSN(Relation rel) return GetFakeLSNForUnloggedRel(); } } + +/* + * This is a stratnum translation support function for GiST opclasses that use + * the RT*StrategyNumber constants. + */ +Datum +gist_translate_cmptype_common(PG_FUNCTION_ARGS) +{ + CompareType cmptype = PG_GETARG_INT32(0); + + switch (cmptype) + { + case COMPARE_EQ: + PG_RETURN_UINT16(RTEqualStrategyNumber); + case COMPARE_LT: + PG_RETURN_UINT16(RTLessStrategyNumber); + case COMPARE_LE: + PG_RETURN_UINT16(RTLessEqualStrategyNumber); + case COMPARE_GT: + PG_RETURN_UINT16(RTGreaterStrategyNumber); + case COMPARE_GE: + PG_RETURN_UINT16(RTGreaterEqualStrategyNumber); + case COMPARE_OVERLAP: + PG_RETURN_UINT16(RTOverlapStrategyNumber); + case COMPARE_CONTAINED_BY: + PG_RETURN_UINT16(RTContainedByStrategyNumber); + default: + PG_RETURN_UINT16(InvalidStrategy); + } +} + +/* + * Returns the opclass's private stratnum used for the given compare type. + * + * Calls the opclass's GIST_TRANSLATE_CMPTYPE_PROC support function, if any, + * and returns the result. Returns InvalidStrategy if the function is not + * defined. + */ +StrategyNumber +gisttranslatecmptype(CompareType cmptype, Oid opfamily) +{ + Oid funcid; + Datum result; + + /* Check whether the function is provided. */ + funcid = get_opfamily_proc(opfamily, ANYOID, ANYOID, GIST_TRANSLATE_CMPTYPE_PROC); + if (!OidIsValid(funcid)) + return InvalidStrategy; + + /* Ask the translation function */ + result = OidFunctionCall1Coll(funcid, InvalidOid, Int32GetDatum(cmptype)); + return DatumGetUInt16(result); +} diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c index 24fb94f473ecb..dca236b6e5735 100644 --- a/src/backend/access/gist/gistvacuum.c +++ b/src/backend/access/gist/gistvacuum.c @@ -4,7 +4,7 @@ * vacuuming routines for the postgres GiST index access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -22,6 +22,7 @@ #include "miscadmin.h" #include "storage/indexfsm.h" #include "storage/lmgr.h" +#include "storage/read_stream.h" #include "utils/memutils.h" /* Working state needed by gistbulkdelete */ @@ -44,8 +45,7 @@ typedef struct static void gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state); -static void gistvacuumpage(GistVacState *vstate, BlockNumber blkno, - BlockNumber orig_blkno); +static void gistvacuumpage(GistVacState *vstate, Buffer buffer); static void gistvacuum_delete_empty_pages(IndexVacuumInfo *info, GistVacState *vstate); static bool gistdeletepage(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, @@ -129,8 +129,9 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, GistVacState vstate; BlockNumber num_pages; bool needLock; - BlockNumber blkno; MemoryContext oldctx; + BlockRangeReadStreamPrivate p; + ReadStream *stream = NULL; /* * Reset fields that track information about the entire index now. This @@ -208,7 +209,21 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, */ needLock = !RELATION_IS_LOCAL(rel); - blkno = GIST_ROOT_BLKNO; + p.current_blocknum = GIST_ROOT_BLKNO; + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, + info->strategy, + rel, + MAIN_FORKNUM, + block_range_read_stream_cb, + &p, + 0); for (;;) { /* Get the current relation length */ @@ -219,13 +234,37 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, UnlockRelationForExtension(rel, ExclusiveLock); /* Quit if we've scanned the whole relation */ - if (blkno >= num_pages) + if (p.current_blocknum >= num_pages) break; - /* Iterate over pages, then loop back to recheck length */ - for (; blkno < num_pages; blkno++) - gistvacuumpage(&vstate, blkno, blkno); + + p.last_exclusive = num_pages; + + /* Iterate over pages, then loop back to recheck relation length */ + while (true) + { + Buffer buf; + + /* call vacuum_delay_point while not holding any buffer lock */ + vacuum_delay_point(false); + + buf = read_stream_next_buffer(stream, NULL); + + if (!BufferIsValid(buf)) + break; + + gistvacuumpage(&vstate, buf); + } + + /* + * We have to reset the read stream to use it again. After returning + * InvalidBuffer, the read stream API won't invoke our callback again + * until the stream has been reset. + */ + read_stream_reset(stream); } + read_stream_end(stream); + /* * If we found any recyclable pages (and recorded them in the FSM), then * forcibly update the upper-level FSM pages to ensure that searchers can @@ -260,34 +299,32 @@ gistvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, /* * gistvacuumpage --- VACUUM one page * - * This processes a single page for gistbulkdelete(). In some cases we - * must go back and re-examine previously-scanned pages; this routine - * recurses when necessary to handle that case. - * - * blkno is the page to process. orig_blkno is the highest block number - * reached by the outer gistvacuumscan loop (the same as blkno, unless we - * are recursing to re-examine a previous page). + * This processes a single page for gistbulkdelete(). `buffer` contains the + * page to process. In some cases we must go back and reexamine + * previously-scanned pages; this routine recurses when necessary to handle + * that case. */ static void -gistvacuumpage(GistVacState *vstate, BlockNumber blkno, BlockNumber orig_blkno) +gistvacuumpage(GistVacState *vstate, Buffer buffer) { IndexVacuumInfo *info = vstate->info; IndexBulkDeleteCallback callback = vstate->callback; void *callback_state = vstate->callback_state; Relation rel = info->index; - Buffer buffer; + BlockNumber orig_blkno = BufferGetBlockNumber(buffer); Page page; BlockNumber recurse_to; + /* + * orig_blkno is the highest block number reached by the outer + * gistvacuumscan() loop. This will be the same as blkno unless we are + * recursing to reexamine a previous page. + */ + BlockNumber blkno = orig_blkno; + restart: recurse_to = InvalidBlockNumber; - /* call vacuum_delay_point while not holding any buffer lock */ - vacuum_delay_point(); - - buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - info->strategy); - /* * We are not going to stay here for a long time, aggressively grab an * exclusive lock. @@ -450,6 +487,12 @@ gistvacuumpage(GistVacState *vstate, BlockNumber blkno, BlockNumber orig_blkno) if (recurse_to != InvalidBlockNumber) { blkno = recurse_to; + + /* check for vacuum delay while not holding any buffer lock */ + vacuum_delay_point(false); + + buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, + info->strategy); goto restart; } } diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c index 36b5a85cf31a7..2ed6f74fce97b 100644 --- a/src/backend/access/gist/gistvalidate.c +++ b/src/backend/access/gist/gistvalidate.c @@ -3,7 +3,7 @@ * gistvalidate.c * Opclass validator for GiST. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,7 +19,6 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "utils/lsyscache.h" #include "utils/regproc.h" @@ -39,8 +38,6 @@ gistvalidate(Oid opclassoid) Oid opcintype; Oid opckeytype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -63,12 +60,7 @@ gistvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -146,6 +138,12 @@ gistvalidate(Oid opclassoid) ok = check_amproc_signature(procform->amproc, VOIDOID, true, 1, 1, INTERNALOID); break; + case GIST_TRANSLATE_CMPTYPE_PROC: + ok = check_amproc_signature(procform->amproc, INT2OID, true, + 1, 1, INT4OID) && + procform->amproclefttype == ANYOID && + procform->amprocrighttype == ANYOID; + break; default: ereport(INFO, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -266,7 +264,8 @@ gistvalidate(Oid opclassoid) continue; /* got it */ if (i == GIST_DISTANCE_PROC || i == GIST_FETCH_PROC || i == GIST_COMPRESS_PROC || i == GIST_DECOMPRESS_PROC || - i == GIST_OPTIONS_PROC || i == GIST_SORTSUPPORT_PROC) + i == GIST_OPTIONS_PROC || i == GIST_SORTSUPPORT_PROC || + i == GIST_TRANSLATE_CMPTYPE_PROC) continue; /* optional methods */ ereport(INFO, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -277,7 +276,6 @@ gistvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; @@ -338,6 +336,7 @@ gistadjustmembers(Oid opfamilyoid, case GIST_FETCH_PROC: case GIST_OPTIONS_PROC: case GIST_SORTSUPPORT_PROC: + case GIST_TRANSLATE_CMPTYPE_PROC: /* Optional, so force it to be a soft family dependency */ op->ref_is_hard = false; op->ref_is_family = true; diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c index 451e8d8d98e63..b354e4ba5d1b7 100644 --- a/src/backend/access/gist/gistxlog.c +++ b/src/backend/access/gist/gistxlog.c @@ -4,7 +4,7 @@ * WAL replay logic for GiST. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -528,14 +528,14 @@ gistXLogSplit(bool page_is_leaf, * of buffer or data registrations here, make sure you modify the * XLogEnsureRecordSpace() calls accordingly! */ - XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageSplit)); + XLogRegisterData(&xlrec, sizeof(gistxlogPageSplit)); i = 1; for (ptr = dist; ptr; ptr = ptr->next) { XLogRegisterBuffer(i, ptr->buffer, REGBUF_WILL_INIT); - XLogRegisterBufData(i, (char *) &(ptr->block.num), sizeof(int)); - XLogRegisterBufData(i, (char *) ptr->list, ptr->lenlist); + XLogRegisterBufData(i, &(ptr->block.num), sizeof(int)); + XLogRegisterBufData(i, ptr->list, ptr->lenlist); i++; } @@ -559,7 +559,7 @@ gistXLogPageDelete(Buffer buffer, FullTransactionId xid, xlrec.downlinkOffset = downlinkOffset; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfGistxlogPageDelete); + XLogRegisterData(&xlrec, SizeOfGistxlogPageDelete); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); XLogRegisterBuffer(1, parentBuffer, REGBUF_STANDARD); @@ -583,7 +583,7 @@ gistXLogAssignLSN(void) */ XLogBeginInsert(); XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT); - XLogRegisterData((char *) &dummy, sizeof(dummy)); + XLogRegisterData(&dummy, sizeof(dummy)); return XLogInsert(RM_GIST_ID, XLOG_GIST_ASSIGN_LSN); } @@ -609,7 +609,7 @@ gistXLogPageReuse(Relation rel, Relation heaprel, xlrec_reuse.snapshotConflictHorizon = deleteXid; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec_reuse, SizeOfGistxlogPageReuse); + XLogRegisterData(&xlrec_reuse, SizeOfGistxlogPageReuse); XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_REUSE); } @@ -639,14 +639,14 @@ gistXLogUpdate(Buffer buffer, xlrec.ntoinsert = ituplen; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageUpdate)); + XLogRegisterData(&xlrec, sizeof(gistxlogPageUpdate)); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) todelete, sizeof(OffsetNumber) * ntodelete); + XLogRegisterBufData(0, todelete, sizeof(OffsetNumber) * ntodelete); /* new tuples */ for (i = 0; i < ituplen; i++) - XLogRegisterBufData(0, (char *) (itup[i]), IndexTupleSize(itup[i])); + XLogRegisterBufData(0, itup[i], IndexTupleSize(itup[i])); /* * Include a full page image of the child buf. (only necessary if a @@ -678,14 +678,14 @@ gistXLogDelete(Buffer buffer, OffsetNumber *todelete, int ntodelete, xlrec.ntodelete = ntodelete; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfGistxlogDelete); + XLogRegisterData(&xlrec, SizeOfGistxlogDelete); /* * We need the target-offsets array whether or not we store the whole * buffer, to allow us to find the snapshotConflictHorizon on a standby * server. */ - XLogRegisterData((char *) todelete, ntodelete * sizeof(OffsetNumber)); + XLogRegisterData(todelete, ntodelete * sizeof(OffsetNumber)); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); diff --git a/src/backend/access/gist/meson.build b/src/backend/access/gist/meson.build index 1f67512192484..14c37c5eb1b9b 100644 --- a/src/backend/access/gist/meson.build +++ b/src/backend/access/gist/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'gist.c', diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 01d06b7c3289e..53061c819fbf0 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -3,7 +3,7 @@ * hash.c * Implementation of Margo Seltzer's Hashing package for postgres. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -21,6 +21,7 @@ #include "access/hash.h" #include "access/hash_xlog.h" #include "access/relscan.h" +#include "access/stratnum.h" #include "access/tableam.h" #include "access/xloginsert.h" #include "commands/progress.h" @@ -63,6 +64,9 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = HASHOPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amcanhash = true; + amroutine->amconsistentequality = true; + amroutine->amconsistentordering = false; amroutine->amcanbackward = true; amroutine->amcanunique = false; amroutine->amcanmulticol = false; @@ -89,6 +93,7 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = hashvacuumcleanup; amroutine->amcanreturn = NULL; amroutine->amcostestimate = hashcostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = hashoptions; amroutine->amproperty = NULL; amroutine->ambuildphasename = NULL; @@ -104,6 +109,8 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = hashtranslatestrategy; + amroutine->amtranslatecmptype = hashtranslatecmptype; PG_RETURN_POINTER(amroutine); } @@ -119,7 +126,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) double reltuples; double allvisfrac; uint32 num_buckets; - long sort_threshold; + Size sort_threshold; HashBuildState buildstate; /* @@ -154,13 +161,13 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) * one page. Also, "initial index size" accounting does not include the * metapage, nor the first bitmap page. */ - sort_threshold = (maintenance_work_mem * 1024L) / BLCKSZ; + sort_threshold = (maintenance_work_mem * (Size) 1024) / BLCKSZ; if (index->rd_rel->relpersistence != RELPERSISTENCE_TEMP) sort_threshold = Min(sort_threshold, NBuffers); else sort_threshold = Min(sort_threshold, NLocBuffer); - if (num_buckets >= (uint32) sort_threshold) + if (num_buckets >= sort_threshold) buildstate.spool = _h_spoolinit(heap, index, num_buckets); else buildstate.spool = NULL; @@ -172,7 +179,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo) /* do the heap scan */ reltuples = table_index_build_scan(heap, index, indexInfo, true, true, hashbuildCallback, - (void *) &buildstate, NULL); + &buildstate, NULL); pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_TOTAL, buildstate.indtuples); @@ -414,11 +421,7 @@ hashrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, /* Update scan key, if a new one is given */ if (scankey && scan->numberOfKeys > 0) - { - memmove(scan->keyData, - scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); - } + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); so->hashso_buc_populated = false; so->hashso_buc_split = false; @@ -616,7 +619,7 @@ hashbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, xlrec.ntuples = metap->hashm_ntuples; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashUpdateMetaPage); + XLogRegisterData(&xlrec, SizeOfHashUpdateMetaPage); XLogRegisterBuffer(0, metabuf, REGBUF_STANDARD); @@ -716,7 +719,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, bool retain_pin = false; bool clear_dead_marking = false; - vacuum_delay_point(); + vacuum_delay_point(false); page = BufferGetPage(buf); opaque = HashPageGetOpaque(page); @@ -823,7 +826,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, xlrec.is_primary_bucket_page = (buf == bucket_buf); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashDelete); + XLogRegisterData(&xlrec, SizeOfHashDelete); /* * bucket buffer was not changed, but still needs to be @@ -838,7 +841,7 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, } XLogRegisterBuffer(1, buf, REGBUF_STANDARD); - XLogRegisterBufData(1, (char *) deletable, + XLogRegisterBufData(1, deletable, ndeletable * sizeof(OffsetNumber)); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_DELETE); @@ -925,3 +928,19 @@ hashbucketcleanup(Relation rel, Bucket cur_bucket, Buffer bucket_buf, else LockBuffer(bucket_buf, BUFFER_LOCK_UNLOCK); } + +CompareType +hashtranslatestrategy(StrategyNumber strategy, Oid opfamily) +{ + if (strategy == HTEqualStrategyNumber) + return COMPARE_EQ; + return COMPARE_INVALID; +} + +StrategyNumber +hashtranslatecmptype(CompareType cmptype, Oid opfamily) +{ + if (cmptype == COMPARE_EQ) + return HTEqualStrategyNumber; + return InvalidStrategy; +} diff --git a/src/backend/access/hash/hash_xlog.c b/src/backend/access/hash/hash_xlog.c index 4e1ec468569e1..8d97067fe5403 100644 --- a/src/backend/access/hash/hash_xlog.c +++ b/src/backend/access/hash/hash_xlog.c @@ -4,7 +4,7 @@ * WAL replay logic for hash index. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c index ce8ee0ea2efdb..ec96348942ee7 100644 --- a/src/backend/access/hash/hashfunc.c +++ b/src/backend/access/hash/hashfunc.c @@ -3,7 +3,7 @@ * hashfunc.c * Support functions for hash access method. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -268,7 +268,7 @@ hashtext(PG_FUNCTION_ARGS) { text *key = PG_GETARG_TEXT_PP(0); Oid collid = PG_GET_COLLATION(); - pg_locale_t mylocale = 0; + pg_locale_t mylocale; Datum result; if (!collid) @@ -277,10 +277,9 @@ hashtext(PG_FUNCTION_ARGS) errmsg("could not determine which collation to use for string hashing"), errhint("Use the COLLATE clause to set the collation explicitly."))); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { result = hash_any((unsigned char *) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); @@ -298,7 +297,9 @@ hashtext(PG_FUNCTION_ARGS) buf = palloc(bsize + 1); rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale); - if (rsize != bsize) + + /* the second call may return a smaller value than the first */ + if (rsize > bsize) elog(ERROR, "pg_strnxfrm() returned unexpected result"); /* @@ -322,7 +323,7 @@ hashtextextended(PG_FUNCTION_ARGS) { text *key = PG_GETARG_TEXT_PP(0); Oid collid = PG_GET_COLLATION(); - pg_locale_t mylocale = 0; + pg_locale_t mylocale; Datum result; if (!collid) @@ -331,10 +332,9 @@ hashtextextended(PG_FUNCTION_ARGS) errmsg("could not determine which collation to use for string hashing"), errhint("Use the COLLATE clause to set the collation explicitly."))); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { result = hash_any_extended((unsigned char *) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key), @@ -352,7 +352,9 @@ hashtextextended(PG_FUNCTION_ARGS) buf = palloc(bsize + 1); rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale); - if (rsize != bsize) + + /* the second call may return a smaller value than the first */ + if (rsize > bsize) elog(ERROR, "pg_strnxfrm() returned unexpected result"); /* @@ -374,6 +376,11 @@ hashtextextended(PG_FUNCTION_ARGS) /* * hashvarlena() can be used for any varlena datatype in which there are * no non-significant bits, ie, distinct bitpatterns never compare as equal. + * + * (However, you need to define an SQL-level wrapper function around it with + * the concrete input data type; otherwise hashvalidate() won't accept it. + * Moreover, at least for built-in types, a C-level wrapper function is also + * recommended; otherwise, the opr_sanity test will get upset.) */ Datum hashvarlena(PG_FUNCTION_ARGS) @@ -404,3 +411,15 @@ hashvarlenaextended(PG_FUNCTION_ARGS) return result; } + +Datum +hashbytea(PG_FUNCTION_ARGS) +{ + return hashvarlena(fcinfo); +} + +Datum +hashbyteaextended(PG_FUNCTION_ARGS) +{ + return hashvarlenaextended(fcinfo); +} diff --git a/src/backend/access/hash/hashinsert.c b/src/backend/access/hash/hashinsert.c index 9ac162041183e..10de1580dc211 100644 --- a/src/backend/access/hash/hashinsert.c +++ b/src/backend/access/hash/hashinsert.c @@ -3,7 +3,7 @@ * hashinsert.c * Item insertion in hash tables for Postgres. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -221,12 +221,12 @@ _hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel, bool sorted) xlrec.offnum = itup_off; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashInsert); + XLogRegisterData(&xlrec, SizeOfHashInsert); XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) itup, IndexTupleSize(itup)); + XLogRegisterBufData(0, itup, IndexTupleSize(itup)); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INSERT); @@ -436,14 +436,14 @@ _hash_vacuum_one_page(Relation rel, Relation hrel, Buffer metabuf, Buffer buf) XLogBeginInsert(); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec, SizeOfHashVacuumOnePage); + XLogRegisterData(&xlrec, SizeOfHashVacuumOnePage); /* * We need the target-offsets array whether or not we store the * whole buffer, to allow us to find the snapshotConflictHorizon * on a standby server. */ - XLogRegisterData((char *) deletable, + XLogRegisterData(deletable, ndeletable * sizeof(OffsetNumber)); XLogRegisterBuffer(1, metabuf, REGBUF_STANDARD); diff --git a/src/backend/access/hash/hashovfl.c b/src/backend/access/hash/hashovfl.c index c280ae885e37a..4f5fd3b28372a 100644 --- a/src/backend/access/hash/hashovfl.c +++ b/src/backend/access/hash/hashovfl.c @@ -3,7 +3,7 @@ * hashovfl.c * Overflow page management code for the Postgres hash access method * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -388,24 +388,24 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin) xlrec.bmsize = metap->hashm_bmsize; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashAddOvflPage); + XLogRegisterData(&xlrec, SizeOfHashAddOvflPage); XLogRegisterBuffer(0, ovflbuf, REGBUF_WILL_INIT); - XLogRegisterBufData(0, (char *) &pageopaque->hasho_bucket, sizeof(Bucket)); + XLogRegisterBufData(0, &pageopaque->hasho_bucket, sizeof(Bucket)); XLogRegisterBuffer(1, buf, REGBUF_STANDARD); if (BufferIsValid(mapbuf)) { XLogRegisterBuffer(2, mapbuf, REGBUF_STANDARD); - XLogRegisterBufData(2, (char *) &bitmap_page_bit, sizeof(uint32)); + XLogRegisterBufData(2, &bitmap_page_bit, sizeof(uint32)); } if (BufferIsValid(newmapbuf)) XLogRegisterBuffer(3, newmapbuf, REGBUF_WILL_INIT); XLogRegisterBuffer(4, metabuf, REGBUF_STANDARD); - XLogRegisterBufData(4, (char *) &metap->hashm_firstfree, sizeof(uint32)); + XLogRegisterBufData(4, &metap->hashm_firstfree, sizeof(uint32)); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_ADD_OVFL_PAGE); @@ -656,7 +656,7 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, xlrec.is_prev_bucket_same_wrt = (wbuf == prevbuf); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashSqueezePage); + XLogRegisterData(&xlrec, SizeOfHashSqueezePage); /* * bucket buffer was not changed, but still needs to be registered to @@ -676,10 +676,10 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, /* Remember that wbuf is modified. */ mod_wbuf = true; - XLogRegisterBufData(1, (char *) itup_offsets, + XLogRegisterBufData(1, itup_offsets, nitups * sizeof(OffsetNumber)); for (i = 0; i < nitups; i++) - XLogRegisterBufData(1, (char *) itups[i], tups_size[i]); + XLogRegisterBufData(1, itups[i], tups_size[i]); } else if (xlrec.is_prim_bucket_same_wrt || xlrec.is_prev_bucket_same_wrt) { @@ -721,12 +721,12 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf, XLogRegisterBuffer(4, nextbuf, REGBUF_STANDARD); XLogRegisterBuffer(5, mapbuf, REGBUF_STANDARD); - XLogRegisterBufData(5, (char *) &bitmapbit, sizeof(uint32)); + XLogRegisterBufData(5, &bitmapbit, sizeof(uint32)); if (update_metap) { XLogRegisterBuffer(6, metabuf, REGBUF_STANDARD); - XLogRegisterBufData(6, (char *) &metap->hashm_firstfree, sizeof(uint32)); + XLogRegisterBufData(6, &metap->hashm_firstfree, sizeof(uint32)); } recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SQUEEZE_PAGE); @@ -993,7 +993,7 @@ _hash_squeezebucket(Relation rel, xlrec.is_prim_bucket_same_wrt = (wbuf == bucket_buf); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashMovePageContents); + XLogRegisterData(&xlrec, SizeOfHashMovePageContents); /* * bucket buffer was not changed, but still needs to @@ -1008,13 +1008,13 @@ _hash_squeezebucket(Relation rel, } XLogRegisterBuffer(1, wbuf, REGBUF_STANDARD); - XLogRegisterBufData(1, (char *) itup_offsets, + XLogRegisterBufData(1, itup_offsets, nitups * sizeof(OffsetNumber)); for (i = 0; i < nitups; i++) - XLogRegisterBufData(1, (char *) itups[i], tups_size[i]); + XLogRegisterBufData(1, itups[i], tups_size[i]); XLogRegisterBuffer(2, rbuf, REGBUF_STANDARD); - XLogRegisterBufData(2, (char *) deletable, + XLogRegisterBufData(2, deletable, ndeletable * sizeof(OffsetNumber)); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_MOVE_PAGE_CONTENTS); diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index d09c349e28f99..b8e5bd005e59a 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -3,7 +3,7 @@ * hashpage.c * Hash table page management code for the Postgres hash access method * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -394,7 +394,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum) xlrec.ffactor = metap->hashm_ffactor; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashInitMetaPage); + XLogRegisterData(&xlrec, SizeOfHashInitMetaPage); XLogRegisterBuffer(0, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_INIT_META_PAGE); @@ -468,7 +468,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum) xlrec.bmsize = metap->hashm_bmsize; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashInitBitmapPage); + XLogRegisterData(&xlrec, SizeOfHashInitBitmapPage); XLogRegisterBuffer(0, bitmapbuf, REGBUF_WILL_INIT); /* @@ -916,21 +916,21 @@ _hash_expandtable(Relation rel, Buffer metabuf) if (metap_update_masks) { xlrec.flags |= XLH_SPLIT_META_UPDATE_MASKS; - XLogRegisterBufData(2, (char *) &metap->hashm_lowmask, sizeof(uint32)); - XLogRegisterBufData(2, (char *) &metap->hashm_highmask, sizeof(uint32)); + XLogRegisterBufData(2, &metap->hashm_lowmask, sizeof(uint32)); + XLogRegisterBufData(2, &metap->hashm_highmask, sizeof(uint32)); } if (metap_update_splitpoint) { xlrec.flags |= XLH_SPLIT_META_UPDATE_SPLITPOINT; - XLogRegisterBufData(2, (char *) &metap->hashm_ovflpoint, + XLogRegisterBufData(2, &metap->hashm_ovflpoint, sizeof(uint32)); XLogRegisterBufData(2, - (char *) &metap->hashm_spares[metap->hashm_ovflpoint], + &metap->hashm_spares[metap->hashm_ovflpoint], sizeof(uint32)); } - XLogRegisterData((char *) &xlrec, SizeOfHashSplitAllocPage); + XLogRegisterData(&xlrec, SizeOfHashSplitAllocPage); recptr = XLogInsert(RM_HASH_ID, XLOG_HASH_SPLIT_ALLOCATE_PAGE); @@ -1304,7 +1304,7 @@ _hash_splitbucket(Relation rel, XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHashSplitComplete); + XLogRegisterData(&xlrec, SizeOfHashSplitComplete); XLogRegisterBuffer(0, bucket_obuf, REGBUF_STANDARD); XLogRegisterBuffer(1, bucket_nbuf, REGBUF_STANDARD); diff --git a/src/backend/access/hash/hashsearch.c b/src/backend/access/hash/hashsearch.c index 0d99d6abc8669..92c15a65be29a 100644 --- a/src/backend/access/hash/hashsearch.c +++ b/src/backend/access/hash/hashsearch.c @@ -3,7 +3,7 @@ * hashsearch.c * search code for postgres hash tables * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -298,6 +298,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir) HashScanPosItem *currItem; pgstat_count_index_scan(rel); + if (scan->instrument) + scan->instrument->nsearches++; /* * We do not support hash scans with no index qualification, because we diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c index 149cd9fc05628..6e8c0e68a92c8 100644 --- a/src/backend/access/hash/hashsort.c +++ b/src/backend/access/hash/hashsort.c @@ -14,7 +14,7 @@ * plenty of locality of access. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -148,6 +148,9 @@ _h_indexbuild(HSpool *hspool, Relation heapRel) /* the tuples are sorted by hashkey, so pass 'sorted' as true */ _hash_doinsert(hspool->index, itup, heapRel, true); + /* allow insertion phase to be interrupted, and track progress */ + CHECK_FOR_INTERRUPTS(); + pgstat_progress_update_param(PROGRESS_CREATEIDX_TUPLES_DONE, ++tups_done); } diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 20028f5cd14e1..66c39f606540b 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -3,7 +3,7 @@ * hashutil.c * Utility code for Postgres hash implementation. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/hash/hashvalidate.c b/src/backend/access/hash/hashvalidate.c index 40164e2ea2bb8..06ac832ba10f8 100644 --- a/src/backend/access/hash/hashvalidate.c +++ b/src/backend/access/hash/hashvalidate.c @@ -3,7 +3,7 @@ * hashvalidate.c * Opclass validator for hash. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -21,20 +21,13 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" -#include "catalog/pg_proc.h" #include "catalog/pg_type.h" -#include "parser/parse_coerce.h" #include "utils/builtins.h" -#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/syscache.h" -static bool check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype); - - /* * Validator for a hash opclass. * @@ -52,8 +45,6 @@ hashvalidate(Oid opclassoid) Oid opfamilyoid; Oid opcintype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -74,12 +65,7 @@ hashvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -90,6 +76,7 @@ hashvalidate(Oid opclassoid) { HeapTuple proctup = &proclist->members[i]->tuple; Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup); + bool ok; /* * All hash functions should be registered with matching left/right @@ -109,29 +96,15 @@ hashvalidate(Oid opclassoid) switch (procform->amprocnum) { case HASHSTANDARD_PROC: + ok = check_amproc_signature(procform->amproc, INT4OID, true, + 1, 1, procform->amproclefttype); + break; case HASHEXTENDED_PROC: - if (!check_hash_func_signature(procform->amproc, procform->amprocnum, - procform->amproclefttype)) - { - ereport(INFO, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d", - opfamilyname, "hash", - format_procedure(procform->amproc), - procform->amprocnum))); - result = false; - } - else - { - /* Remember which types we can hash */ - hashabletypes = - list_append_unique_oid(hashabletypes, - procform->amproclefttype); - } + ok = check_amproc_signature(procform->amproc, INT8OID, true, + 2, 2, procform->amproclefttype, INT8OID); break; case HASHOPTIONS_PROC: - if (!check_amoptsproc_signature(procform->amproc)) - result = false; + ok = check_amoptsproc_signature(procform->amproc); break; default: ereport(INFO, @@ -141,7 +114,24 @@ hashvalidate(Oid opclassoid) format_procedure(procform->amproc), procform->amprocnum))); result = false; - break; + continue; /* don't want additional message */ + } + + if (!ok) + { + ereport(INFO, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d", + opfamilyname, "hash", + format_procedure(procform->amproc), + procform->amprocnum))); + result = false; + } + + /* Remember which types we can hash */ + if (ok && (procform->amprocnum == HASHSTANDARD_PROC || procform->amprocnum == HASHEXTENDED_PROC)) + { + hashabletypes = list_append_unique_oid(hashabletypes, procform->amproclefttype); } } @@ -260,91 +250,12 @@ hashvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; } -/* - * We need a custom version of check_amproc_signature because of assorted - * hacks in the core hash opclass definitions. - */ -static bool -check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype) -{ - bool result = true; - Oid restype; - int16 nargs; - HeapTuple tp; - Form_pg_proc procform; - - switch (amprocnum) - { - case HASHSTANDARD_PROC: - restype = INT4OID; - nargs = 1; - break; - - case HASHEXTENDED_PROC: - restype = INT8OID; - nargs = 2; - break; - - default: - elog(ERROR, "invalid amprocnum"); - } - - tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for function %u", funcid); - procform = (Form_pg_proc) GETSTRUCT(tp); - - if (procform->prorettype != restype || procform->proretset || - procform->pronargs != nargs) - result = false; - - if (!IsBinaryCoercible(argtype, procform->proargtypes.values[0])) - { - /* - * Some of the built-in hash opclasses cheat by using hash functions - * that are different from but physically compatible with the opclass - * datatype. In some of these cases, even a "binary coercible" check - * fails because there's no relevant cast. For the moment, fix it by - * having a list of allowed cases. Test the specific function - * identity, not just its input type, because hashvarlena() takes - * INTERNAL and allowing any such function seems too scary. - */ - if ((funcid == F_HASHINT4 || funcid == F_HASHINT4EXTENDED) && - (argtype == DATEOID || - argtype == XIDOID || argtype == CIDOID)) - /* okay, allowed use of hashint4() */ ; - else if ((funcid == F_HASHINT8 || funcid == F_HASHINT8EXTENDED) && - (argtype == XID8OID)) - /* okay, allowed use of hashint8() */ ; - else if ((funcid == F_TIMESTAMP_HASH || - funcid == F_TIMESTAMP_HASH_EXTENDED) && - argtype == TIMESTAMPTZOID) - /* okay, allowed use of timestamp_hash() */ ; - else if ((funcid == F_HASHCHAR || funcid == F_HASHCHAREXTENDED) && - argtype == BOOLOID) - /* okay, allowed use of hashchar() */ ; - else if ((funcid == F_HASHVARLENA || funcid == F_HASHVARLENAEXTENDED) && - argtype == BYTEAOID) - /* okay, allowed use of hashvarlena() */ ; - else - result = false; - } - - /* If function takes a second argument, it must be for a 64-bit salt. */ - if (nargs == 2 && procform->proargtypes.values[1] != INT8OID) - result = false; - - ReleaseSysCache(tp); - return result; -} - /* * Prechecking function for adding operators/functions to a hash opfamily. */ diff --git a/src/backend/access/hash/meson.build b/src/backend/access/hash/meson.build index 390e2795e784a..5f933faa6c9fe 100644 --- a/src/backend/access/hash/meson.build +++ b/src/backend/access/hash/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'hash.c', diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile index af0bd1888e53f..394534172fa1a 100644 --- a/src/backend/access/heap/Makefile +++ b/src/backend/access/heap/Makefile @@ -16,6 +16,7 @@ OBJS = \ heapam.o \ heapam_handler.o \ heapam_visibility.o \ + heapam_xlog.o \ heaptoast.o \ hio.o \ pruneheap.o \ diff --git a/src/backend/access/heap/README.tuplock b/src/backend/access/heap/README.tuplock index 6441e8baf0e4a..843c2e58f929d 100644 --- a/src/backend/access/heap/README.tuplock +++ b/src/backend/access/heap/README.tuplock @@ -70,13 +70,8 @@ KEY SHARE conflict When there is a single locker in a tuple, we can just store the locking info in the tuple itself. We do this by storing the locker's Xid in XMAX, and -setting infomask bits specifying the locking strength. There is one exception -here: since infomask space is limited, we do not provide a separate bit -for SELECT FOR SHARE, so we have to use the extended info in a MultiXact in -that case. (The other cases, SELECT FOR UPDATE and SELECT FOR KEY SHARE, are -presumably more commonly used due to being the standards-mandated locking -mechanism, or heavily used by the RI code, so we want to provide fast paths -for those.) +setting infomask bits specifying the locking strength. See "Infomask Bits" +below for details on the bit patterns we use. MultiXacts ---------- @@ -153,3 +148,54 @@ The following infomask bits are applicable: We currently never set the HEAP_XMAX_COMMITTED when the HEAP_XMAX_IS_MULTI bit is set. + +Locking to write inplace-updated tables +--------------------------------------- + +If IsInplaceUpdateRelation() returns true for a table, the table is a system +catalog that receives systable_inplace_update_begin() calls. Preparing a +heap_update() of these tables follows additional locking rules, to ensure we +don't lose the effects of an inplace update. In particular, consider a moment +when a backend has fetched the old tuple to modify, not yet having called +heap_update(). Another backend's inplace update starting then can't conclude +until the heap_update() places its new tuple in a buffer. We enforce that +using locktags as follows. While DDL code is the main audience, the executor +follows these rules to make e.g. "MERGE INTO pg_class" safer. Locking rules +are per-catalog: + + pg_class systable_inplace_update_begin() callers: before the call, acquire a + lock on the relation in mode ShareUpdateExclusiveLock or stricter. If the + update targets a row of RELKIND_INDEX (but not RELKIND_PARTITIONED_INDEX), + that lock must be on the table. Locking the index rel is not necessary. + (This allows VACUUM to overwrite per-index pg_class while holding a lock on + the table alone.) systable_inplace_update_begin() acquires and releases + LOCKTAG_TUPLE in InplaceUpdateTupleLock, an alias for ExclusiveLock, on each + tuple it overwrites. + + pg_class heap_update() callers: before copying the tuple to modify, take a + lock on the tuple, a ShareUpdateExclusiveLock on the relation, or a + ShareRowExclusiveLock or stricter on the relation. + + SearchSysCacheLocked1() is one convenient way to acquire the tuple lock. + Most heap_update() callers already hold a suitable lock on the relation for + other reasons and can skip the tuple lock. If you do acquire the tuple + lock, release it immediately after the update. + + + pg_database: before copying the tuple to modify, all updaters of pg_database + rows acquire LOCKTAG_TUPLE. (Few updaters acquire LOCKTAG_OBJECT on the + database OID, so it wasn't worth extending that as a second option.) + +Ideally, DDL might want to perform permissions checks before LockTuple(), as +we do with RangeVarGetRelidExtended() callbacks. We typically don't bother. +LOCKTAG_TUPLE acquirers release it after each row, so the potential +inconvenience is lower. + +Reading inplace-updated columns +------------------------------- + +Inplace updates create an exception to the rule that tuple data won't change +under a reader holding a pin. A reader of a heap_fetch() result tuple may +witness a torn read. Current inplace-updated fields are aligned and are no +wider than four bytes, and current readers don't need consistency across +fields. Hence, they get by with just fetching each field once. diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 91b20147a0047..0dcd6ee817e04 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -3,7 +3,7 @@ * heapam.c * heap access method code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -31,43 +31,28 @@ */ #include "postgres.h" -#include "access/bufmask.h" #include "access/heapam.h" -#include "access/heapam_xlog.h" #include "access/heaptoast.h" #include "access/hio.h" #include "access/multixact.h" -#include "access/parallel.h" -#include "access/relscan.h" #include "access/subtrans.h" #include "access/syncscan.h" -#include "access/sysattr.h" -#include "access/tableam.h" -#include "access/transam.h" #include "access/valid.h" #include "access/visibilitymap.h" -#include "access/xact.h" -#include "access/xlog.h" #include "access/xloginsert.h" -#include "access/xlogutils.h" -#include "catalog/catalog.h" +#include "catalog/pg_database.h" +#include "catalog/pg_database_d.h" #include "commands/vacuum.h" -#include "miscadmin.h" #include "pgstat.h" -#include "port/atomics.h" #include "port/pg_bitutils.h" -#include "storage/bufmgr.h" -#include "storage/freespace.h" #include "storage/lmgr.h" #include "storage/predicate.h" #include "storage/procarray.h" -#include "storage/standby.h" #include "utils/datum.h" #include "utils/injection_point.h" #include "utils/inval.h" -#include "utils/relcache.h" -#include "utils/snapmgr.h" #include "utils/spccache.h" +#include "utils/syscache.h" static HeapTuple heap_prepare_insert(Relation relation, HeapTuple tup, @@ -76,6 +61,12 @@ static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf, Buffer newbuf, HeapTuple oldtup, HeapTuple newtup, HeapTuple old_key_tuple, bool all_visible_cleared, bool new_all_visible_cleared); +#ifdef USE_ASSERT_CHECKING +static void check_lock_if_inplace_updateable_rel(Relation relation, + ItemPointer otid, + HeapTuple newtup); +static void check_inplace_rel_lock(HeapTuple oldtup); +#endif static Bitmapset *HeapDetermineColumnsInfo(Relation relation, Bitmapset *interesting_cols, Bitmapset *external_cols, @@ -107,7 +98,8 @@ static void MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 in Relation rel, ItemPointer ctid, XLTW_Oper oper, int *remaining); static bool ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status, - uint16 infomask, Relation rel, int *remaining); + uint16 infomask, Relation rel, int *remaining, + bool logLockFailure); static void index_delete_sort(TM_IndexDeleteOp *delstate); static int bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate); static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup); @@ -122,6 +114,8 @@ static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool ke * heavyweight lock mode and MultiXactStatus values to use for any particular * tuple lock strength. * + * These interact with InplaceUpdateTupleLock, an alias for ExclusiveLock. + * * Don't look at lockstatus/updstatus directly! Use get_mxact_status_for_lock * instead. */ @@ -169,8 +163,8 @@ static const struct LockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock) #define UnlockTupleTuplock(rel, tup, mode) \ UnlockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock) -#define ConditionalLockTupleTuplock(rel, tup, mode) \ - ConditionalLockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock) +#define ConditionalLockTupleTuplock(rel, tup, mode, log) \ + ConditionalLockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock, (log)) #ifdef USE_PREFETCH /* @@ -219,6 +213,27 @@ static const int MultiXactStatusLock[MaxMultiXactStatus + 1] = #define TUPLOCK_from_mxstatus(status) \ (MultiXactStatusLock[(status)]) +/* + * Check that we have a valid snapshot if we might need TOAST access. + */ +static inline void +AssertHasSnapshotForToast(Relation rel) +{ +#ifdef USE_ASSERT_CHECKING + + /* bootstrap mode in particular breaks this rule */ + if (!IsNormalProcessingMode()) + return; + + /* if the relation doesn't have a TOAST table, we are good */ + if (!OidIsValid(rel->rd_rel->reltoastrelid)) + return; + + Assert(HaveRegisteredOrActiveSnapshot()); + +#endif /* USE_ASSERT_CHECKING */ +} + /* ---------------------------------------------------------------- * heap support routines * ---------------------------------------------------------------- @@ -286,6 +301,47 @@ heap_scan_stream_read_next_serial(ReadStream *stream, return scan->rs_prefetch_block; } +/* + * Read stream API callback for bitmap heap scans. + * Returns the next block the caller wants from the read stream or + * InvalidBlockNumber when done. + */ +static BlockNumber +bitmapheap_stream_read_next(ReadStream *pgsr, void *private_data, + void *per_buffer_data) +{ + TBMIterateResult *tbmres = per_buffer_data; + BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) private_data; + HeapScanDesc hscan = (HeapScanDesc) bscan; + TableScanDesc sscan = &hscan->rs_base; + + for (;;) + { + CHECK_FOR_INTERRUPTS(); + + /* no more entries in the bitmap */ + if (!tbm_iterate(&sscan->st.rs_tbmiterator, tbmres)) + return InvalidBlockNumber; + + /* + * Ignore any claimed entries past what we think is the end of the + * relation. It may have been extended after the start of our scan (we + * only hold an AccessShareLock, and it could be inserts from this + * backend). We don't take this optimization in SERIALIZABLE + * isolation though, as we need to examine all invisible tuples + * reachable by the index. + */ + if (!IsolationIsSerializable() && + tbmres->blockno >= hscan->rs_nblocks) + continue; + + return tbmres->blockno; + } + + /* not reachable */ + Assert(false); +} + /* ---------------- * initscan - scan code common to heap_beginscan and heap_rescan * ---------------- @@ -387,6 +443,8 @@ initscan(HeapScanDesc scan, ScanKey key, bool keep_startblock) ItemPointerSetInvalid(&scan->rs_ctup.t_self); scan->rs_cbuf = InvalidBuffer; scan->rs_cblock = InvalidBlockNumber; + scan->rs_ntuples = 0; + scan->rs_cindex = 0; /* * Initialize to ForwardScanDirection because it is most common and @@ -952,8 +1010,8 @@ heapgettup_pagemode(HeapScanDesc scan, { HeapTuple tuple = &(scan->rs_ctup); Page page; - int lineindex; - int linesleft; + uint32 lineindex; + uint32 linesleft; if (likely(scan->rs_inited)) { @@ -990,6 +1048,9 @@ heapgettup_pagemode(HeapScanDesc scan, linesleft = scan->rs_ntuples; lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1; + /* block is the same for all tuples, set it once outside the loop */ + ItemPointerSetBlockNumber(&tuple->t_self, scan->rs_cblock); + /* lineindex now references the next or previous visible tid */ continue_page: @@ -998,13 +1059,14 @@ heapgettup_pagemode(HeapScanDesc scan, ItemId lpp; OffsetNumber lineoff; + Assert(lineindex <= scan->rs_ntuples); lineoff = scan->rs_vistuples[lineindex]; lpp = PageGetItemId(page, lineoff); Assert(ItemIdIsNormal(lpp)); tuple->t_data = (HeapTupleHeader) PageGetItem(page, lpp); tuple->t_len = ItemIdGetLength(lpp); - ItemPointerSet(&(tuple->t_self), scan->rs_cblock, lineoff); + ItemPointerSetOffsetNumber(&tuple->t_self, lineoff); /* skip any tuples that don't match the scan key */ if (key != NULL && @@ -1054,7 +1116,18 @@ heap_beginscan(Relation relation, Snapshot snapshot, /* * allocate and initialize scan descriptor */ - scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData)); + if (flags & SO_TYPE_BITMAPSCAN) + { + BitmapHeapScanDesc bscan = palloc(sizeof(BitmapHeapScanDescData)); + + /* + * Bitmap Heap scans do not have any fields that a normal Heap Scan + * does not have, so no special initializations required here. + */ + scan = (HeapScanDesc) bscan; + } + else + scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData)); scan->rs_base.rs_rd = relation; scan->rs_base.rs_snapshot = snapshot; @@ -1062,8 +1135,7 @@ heap_beginscan(Relation relation, Snapshot snapshot, scan->rs_base.rs_flags = flags; scan->rs_base.rs_parallel = parallel_scan; scan->rs_strategy = NULL; /* set in initscan */ - scan->rs_vmbuffer = InvalidBuffer; - scan->rs_empty_tuples_pending = 0; + scan->rs_cbuf = InvalidBuffer; /* * Disable page-at-a-time mode if it's not a MVCC-safe snapshot. @@ -1135,7 +1207,15 @@ heap_beginscan(Relation relation, Snapshot snapshot, else cb = heap_scan_stream_read_next_serial; - scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_SEQUENTIAL, + /* --- + * It is safe to use batchmode as the only locks taken by `cb` + * are never taken while waiting for IO: + * - SyncScanLock is used in the non-parallel case + * - in the parallel case, only spinlocks and atomics are used + * --- + */ + scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_SEQUENTIAL | + READ_STREAM_USE_BATCHING, scan->rs_strategy, scan->rs_base.rs_rd, MAIN_FORKNUM, @@ -1143,6 +1223,17 @@ heap_beginscan(Relation relation, Snapshot snapshot, scan, 0); } + else if (scan->rs_base.rs_flags & SO_TYPE_BITMAPSCAN) + { + scan->rs_read_stream = read_stream_begin_relation(READ_STREAM_DEFAULT | + READ_STREAM_USE_BATCHING, + scan->rs_strategy, + scan->rs_base.rs_rd, + MAIN_FORKNUM, + bitmapheap_stream_read_next, + scan, + sizeof(TBMIterateResult)); + } return (TableScanDesc) scan; @@ -1177,20 +1268,15 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params, * unpin scan buffers */ if (BufferIsValid(scan->rs_cbuf)) - ReleaseBuffer(scan->rs_cbuf); - - if (BufferIsValid(scan->rs_vmbuffer)) { - ReleaseBuffer(scan->rs_vmbuffer); - scan->rs_vmbuffer = InvalidBuffer; + ReleaseBuffer(scan->rs_cbuf); + scan->rs_cbuf = InvalidBuffer; } /* - * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan, - * to avoid incorrectly emitting NULL-filled tuples from a previous scan - * on rescan. + * SO_TYPE_BITMAPSCAN would be cleaned up here, but it does not hold any + * additional data vs a normal HeapScan */ - scan->rs_empty_tuples_pending = 0; /* * The read stream is reset on rescan. This must be done before @@ -1219,9 +1305,6 @@ heap_endscan(TableScanDesc sscan) if (BufferIsValid(scan->rs_cbuf)) ReleaseBuffer(scan->rs_cbuf); - if (BufferIsValid(scan->rs_vmbuffer)) - ReleaseBuffer(scan->rs_vmbuffer); - /* * Must free the read stream before freeing the BufferAccessStrategy. */ @@ -1396,8 +1479,8 @@ heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid, heap_setscanlimits(sscan, startBlk, numBlks); /* Finally, set the TID range in sscan */ - ItemPointerCopy(&lowestItem, &sscan->rs_mintid); - ItemPointerCopy(&highestItem, &sscan->rs_maxtid); + ItemPointerCopy(&lowestItem, &sscan->st.tidrange.rs_mintid); + ItemPointerCopy(&highestItem, &sscan->st.tidrange.rs_maxtid); } bool @@ -1405,8 +1488,8 @@ heap_getnextslot_tidrange(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot) { HeapScanDesc scan = (HeapScanDesc) sscan; - ItemPointer mintid = &sscan->rs_mintid; - ItemPointer maxtid = &sscan->rs_maxtid; + ItemPointer mintid = &sscan->st.tidrange.rs_mintid; + ItemPointer maxtid = &sscan->st.tidrange.rs_maxtid; /* Note: no locking manipulations needed */ for (;;) @@ -2004,6 +2087,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, Assert(HeapTupleHeaderGetNatts(tup->t_data) <= RelationGetNumberOfAttributes(relation)); + AssertHasSnapshotForToast(relation); + /* * Fill in tuple header fields and toast the tuple if necessary. * @@ -2119,7 +2204,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, } XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapInsert); + XLogRegisterData(&xlrec, SizeOfHeapInsert); xlhdr.t_infomask2 = heaptup->t_data->t_infomask2; xlhdr.t_infomask = heaptup->t_data->t_infomask; @@ -2131,7 +2216,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, * xl_heap_header in the xlog. */ XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags); - XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader); + XLogRegisterBufData(0, &xlhdr, SizeOfHeapHeader); /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ XLogRegisterBufData(0, (char *) heaptup->t_data + SizeofHeapTupleHeader, @@ -2281,6 +2366,8 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, /* currently not needed (thus unsupported) for heap_multi_insert() */ Assert(!(options & HEAP_INSERT_NO_LOGICAL)); + AssertHasSnapshotForToast(relation); + needwal = RelationNeedsWAL(relation); saveFreeSpace = RelationGetTargetPageFreeSpace(relation, HEAP_DEFAULT_FILLFACTOR); @@ -2528,7 +2615,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, bufflags |= REGBUF_KEEP_DATA; XLogBeginInsert(); - XLogRegisterData((char *) xlrec, tupledata - scratch.data); + XLogRegisterData(xlrec, tupledata - scratch.data); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD | bufflags); XLogRegisterBufData(0, tupledata, totaldatalen); @@ -2703,6 +2790,8 @@ heap_delete(Relation relation, ItemPointer tid, Assert(ItemPointerIsValid(tid)); + AssertHasSnapshotForToast(relation); + /* * Forbid this during a parallel operation, lest it allocate a combo CID. * Other workers might need that combo CID for visibility checks, and we @@ -3018,7 +3107,7 @@ heap_delete(Relation relation, ItemPointer tid, } XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapDelete); + XLogRegisterData(&xlrec, SizeOfHeapDelete); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); @@ -3031,7 +3120,7 @@ heap_delete(Relation relation, ItemPointer tid, xlhdr.t_infomask = old_key_tuple->t_data->t_infomask; xlhdr.t_hoff = old_key_tuple->t_data->t_hoff; - XLogRegisterData((char *) &xlhdr, SizeOfHeapHeader); + XLogRegisterData(&xlhdr, SizeOfHeapHeader); XLogRegisterData((char *) old_key_tuple->t_data + SizeofHeapTupleHeader, old_key_tuple->t_len @@ -3198,6 +3287,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, Assert(HeapTupleHeaderGetNatts(newtup->t_data) <= RelationGetNumberOfAttributes(relation)); + AssertHasSnapshotForToast(relation); + /* * Forbid this during a parallel operation, lest it allocate a combo CID. * Other workers might need that combo CID for visibility checks, and we @@ -3208,6 +3299,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), errmsg("cannot update tuples during a parallel operation"))); +#ifdef USE_ASSERT_CHECKING + check_lock_if_inplace_updateable_rel(relation, otid, newtup); +#endif + /* * Fetch the list of attributes to be checked for various operations. * @@ -3238,6 +3333,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, interesting_attrs = bms_add_members(interesting_attrs, id_attrs); block = ItemPointerGetBlockNumber(otid); + INJECTION_POINT("heap_update-before-pin", NULL); buffer = ReadBuffer(relation, block); page = BufferGetPage(buffer); @@ -3253,7 +3349,51 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid)); - Assert(ItemIdIsNormal(lp)); + + /* + * Usually, a buffer pin and/or snapshot blocks pruning of otid, ensuring + * we see LP_NORMAL here. When the otid origin is a syscache, we may have + * neither a pin nor a snapshot. Hence, we may see other LP_ states, each + * of which indicates concurrent pruning. + * + * Failing with TM_Updated would be most accurate. However, unlike other + * TM_Updated scenarios, we don't know the successor ctid in LP_UNUSED and + * LP_DEAD cases. While the distinction between TM_Updated and TM_Deleted + * does matter to SQL statements UPDATE and MERGE, those SQL statements + * hold a snapshot that ensures LP_NORMAL. Hence, the choice between + * TM_Updated and TM_Deleted affects only the wording of error messages. + * Settle on TM_Deleted, for two reasons. First, it avoids complicating + * the specification of when tmfd->ctid is valid. Second, it creates + * error log evidence that we took this branch. + * + * Since it's possible to see LP_UNUSED at otid, it's also possible to see + * LP_NORMAL for a tuple that replaced LP_UNUSED. If it's a tuple for an + * unrelated row, we'll fail with "duplicate key value violates unique". + * XXX if otid is the live, newer version of the newtup row, we'll discard + * changes originating in versions of this catalog row after the version + * the caller got from syscache. See syscache-update-pruned.spec. + */ + if (!ItemIdIsNormal(lp)) + { + Assert(RelationSupportsSysCache(RelationGetRelid(relation))); + + UnlockReleaseBuffer(buffer); + Assert(!have_tuple_lock); + if (vmbuffer != InvalidBuffer) + ReleaseBuffer(vmbuffer); + tmfd->ctid = *otid; + tmfd->xmax = InvalidTransactionId; + tmfd->cmax = InvalidCommandId; + *update_indexes = TU_None; + + bms_free(hot_attrs); + bms_free(sum_attrs); + bms_free(key_attrs); + bms_free(id_attrs); + /* modified_attrs not yet initialized */ + bms_free(interesting_attrs); + return TM_Deleted; + } /* * Fill in enough data in oldtup for HeapDetermineColumnsInfo to work @@ -3748,7 +3888,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, oldtup.t_data->t_infomask2); xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; - XLogRegisterData((char *) &xlrec, SizeOfHeapLock); + XLogRegisterData(&xlrec, SizeOfHeapLock); recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_LOCK); PageSetLSN(page, recptr); } @@ -4072,6 +4212,128 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, return TM_Ok; } +#ifdef USE_ASSERT_CHECKING +/* + * Confirm adequate lock held during heap_update(), per rules from + * README.tuplock section "Locking to write inplace-updated tables". + */ +static void +check_lock_if_inplace_updateable_rel(Relation relation, + ItemPointer otid, + HeapTuple newtup) +{ + /* LOCKTAG_TUPLE acceptable for any catalog */ + switch (RelationGetRelid(relation)) + { + case RelationRelationId: + case DatabaseRelationId: + { + LOCKTAG tuptag; + + SET_LOCKTAG_TUPLE(tuptag, + relation->rd_lockInfo.lockRelId.dbId, + relation->rd_lockInfo.lockRelId.relId, + ItemPointerGetBlockNumber(otid), + ItemPointerGetOffsetNumber(otid)); + if (LockHeldByMe(&tuptag, InplaceUpdateTupleLock, false)) + return; + } + break; + default: + Assert(!IsInplaceUpdateRelation(relation)); + return; + } + + switch (RelationGetRelid(relation)) + { + case RelationRelationId: + { + /* LOCKTAG_TUPLE or LOCKTAG_RELATION ok */ + Form_pg_class classForm = (Form_pg_class) GETSTRUCT(newtup); + Oid relid = classForm->oid; + Oid dbid; + LOCKTAG tag; + + if (IsSharedRelation(relid)) + dbid = InvalidOid; + else + dbid = MyDatabaseId; + + if (classForm->relkind == RELKIND_INDEX) + { + Relation irel = index_open(relid, AccessShareLock); + + SET_LOCKTAG_RELATION(tag, dbid, irel->rd_index->indrelid); + index_close(irel, AccessShareLock); + } + else + SET_LOCKTAG_RELATION(tag, dbid, relid); + + if (!LockHeldByMe(&tag, ShareUpdateExclusiveLock, false) && + !LockHeldByMe(&tag, ShareRowExclusiveLock, true)) + elog(WARNING, + "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)", + NameStr(classForm->relname), + relid, + classForm->relkind, + ItemPointerGetBlockNumber(otid), + ItemPointerGetOffsetNumber(otid)); + } + break; + case DatabaseRelationId: + { + /* LOCKTAG_TUPLE required */ + Form_pg_database dbForm = (Form_pg_database) GETSTRUCT(newtup); + + elog(WARNING, + "missing lock on database \"%s\" (OID %u) @ TID (%u,%u)", + NameStr(dbForm->datname), + dbForm->oid, + ItemPointerGetBlockNumber(otid), + ItemPointerGetOffsetNumber(otid)); + } + break; + } +} + +/* + * Confirm adequate relation lock held, per rules from README.tuplock section + * "Locking to write inplace-updated tables". + */ +static void +check_inplace_rel_lock(HeapTuple oldtup) +{ + Form_pg_class classForm = (Form_pg_class) GETSTRUCT(oldtup); + Oid relid = classForm->oid; + Oid dbid; + LOCKTAG tag; + + if (IsSharedRelation(relid)) + dbid = InvalidOid; + else + dbid = MyDatabaseId; + + if (classForm->relkind == RELKIND_INDEX) + { + Relation irel = index_open(relid, AccessShareLock); + + SET_LOCKTAG_RELATION(tag, dbid, irel->rd_index->indrelid); + index_close(irel, AccessShareLock); + } + else + SET_LOCKTAG_RELATION(tag, dbid, relid); + + if (!LockHeldByMe(&tag, ShareUpdateExclusiveLock, true)) + elog(WARNING, + "missing lock for relation \"%s\" (OID %u, relkind %c) @ TID (%u,%u)", + NameStr(classForm->relname), + relid, + classForm->relkind, + ItemPointerGetBlockNumber(&oldtup->t_self), + ItemPointerGetOffsetNumber(&oldtup->t_self)); +} +#endif + /* * Check if the specified attribute's values are the same. Subroutine for * HeapDetermineColumnsInfo. @@ -4080,8 +4342,6 @@ static bool heap_attr_equals(TupleDesc tupdesc, int attrnum, Datum value1, Datum value2, bool isnull1, bool isnull2) { - Form_pg_attribute att; - /* * If one value is NULL and other is not, then they are certainly not * equal @@ -4111,8 +4371,10 @@ heap_attr_equals(TupleDesc tupdesc, int attrnum, Datum value1, Datum value2, } else { + CompactAttribute *att; + Assert(attrnum <= tupdesc->natts); - att = TupleDescAttr(tupdesc, attrnum - 1); + att = TupleDescCompactAttr(tupdesc, attrnum - 1); return datumIsEqual(value1, value2, att->attbyval, att->attlen); } } @@ -4194,7 +4456,7 @@ HeapDetermineColumnsInfo(Relation relation, * that system attributes can't be stored externally. */ if (attrnum < 0 || isnull1 || - TupleDescAttr(tupdesc, attrnum - 1)->attlen != -1) + TupleDescCompactAttr(tupdesc, attrnum - 1)->attlen != -1) continue; /* @@ -4709,7 +4971,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, case LockWaitSkip: if (!ConditionalMultiXactIdWait((MultiXactId) xwait, status, infomask, relation, - NULL)) + NULL, false)) { result = TM_WouldBlock; /* recovery code expects to have buffer lock held */ @@ -4720,7 +4982,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, case LockWaitError: if (!ConditionalMultiXactIdWait((MultiXactId) xwait, status, infomask, relation, - NULL)) + NULL, log_lock_failures)) ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on row in relation \"%s\"", @@ -4749,7 +5011,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, XLTW_Lock); break; case LockWaitSkip: - if (!ConditionalXactLockTableWait(xwait)) + if (!ConditionalXactLockTableWait(xwait, false)) { result = TM_WouldBlock; /* recovery code expects to have buffer lock held */ @@ -4758,7 +5020,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, } break; case LockWaitError: - if (!ConditionalXactLockTableWait(xwait)) + if (!ConditionalXactLockTableWait(xwait, log_lock_failures)) ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on row in relation \"%s\"", @@ -4957,7 +5219,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, xlrec.infobits_set = compute_infobits(new_infomask, tuple->t_data->t_infomask2); xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; - XLogRegisterData((char *) &xlrec, SizeOfHeapLock); + XLogRegisterData(&xlrec, SizeOfHeapLock); /* we don't decode row locks atm, so no need to log the origin */ @@ -5018,12 +5280,12 @@ heap_acquire_tuplock(Relation relation, ItemPointer tid, LockTupleMode mode, break; case LockWaitSkip: - if (!ConditionalLockTupleTuplock(relation, tid, mode)) + if (!ConditionalLockTupleTuplock(relation, tid, mode, false)) return false; break; case LockWaitError: - if (!ConditionalLockTupleTuplock(relation, tid, mode)) + if (!ConditionalLockTupleTuplock(relation, tid, mode, log_lock_failures)) ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on row in relation \"%s\"", @@ -5710,7 +5972,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, xlrec.flags = cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0; - XLogRegisterData((char *) &xlrec, SizeOfHeapLockUpdated); + XLogRegisterData(&xlrec, SizeOfHeapLockUpdated); recptr = XLogInsert(RM_HEAP2_ID, XLOG_HEAP2_LOCK_UPDATED); @@ -5863,7 +6125,7 @@ heap_finish_speculative(Relation relation, ItemPointer tid) /* We want the same filtering on this as on a plain insert */ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); - XLogRegisterData((char *) &xlrec, SizeOfHeapConfirm); + XLogRegisterData(&xlrec, SizeOfHeapConfirm); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CONFIRM); @@ -6008,7 +6270,7 @@ heap_abort_speculative(Relation relation, ItemPointer tid) xlrec.xmax = xid; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapDelete); + XLogRegisterData(&xlrec, SizeOfHeapDelete); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); /* No replica identity & replication origin logged */ @@ -6041,87 +6303,292 @@ heap_abort_speculative(Relation relation, ItemPointer tid) } /* - * heap_inplace_update - update a tuple "in place" (ie, overwrite it) - * - * Overwriting violates both MVCC and transactional safety, so the uses - * of this function in Postgres are extremely limited. Nonetheless we - * find some places to use it. - * - * The tuple cannot change size, and therefore it's reasonable to assume - * that its null bitmap (if any) doesn't change either. So we just - * overwrite the data portion of the tuple without touching the null - * bitmap or any of the header fields. - * - * tuple is an in-memory tuple structure containing the data to be written - * over the target tuple. Also, tuple->t_self identifies the target tuple. - * - * Note that the tuple updated here had better not come directly from the - * syscache if the relation has a toast relation as this tuple could - * include toast values that have been expanded, causing a failure here. + * heap_inplace_lock - protect inplace update from concurrent heap_update() + * + * Evaluate whether the tuple's state is compatible with a no-key update. + * Current transaction rowmarks are fine, as is KEY SHARE from any + * transaction. If compatible, return true with the buffer exclusive-locked, + * and the caller must release that by calling + * heap_inplace_update_and_unlock(), calling heap_inplace_unlock(), or raising + * an error. Otherwise, call release_callback(arg), wait for blocking + * transactions to end, and return false. + * + * Since this is intended for system catalogs and SERIALIZABLE doesn't cover + * DDL, this doesn't guarantee any particular predicate locking. + * + * One could modify this to return true for tuples with delete in progress, + * All inplace updaters take a lock that conflicts with DROP. If explicit + * "DELETE FROM pg_class" is in progress, we'll wait for it like we would an + * update. + * + * Readers of inplace-updated fields expect changes to those fields are + * durable. For example, vac_truncate_clog() reads datfrozenxid from + * pg_database tuples via catalog snapshots. A future snapshot must not + * return a lower datfrozenxid for the same database OID (lower in the + * FullTransactionIdPrecedes() sense). We achieve that since no update of a + * tuple can start while we hold a lock on its buffer. In cases like + * BEGIN;GRANT;CREATE INDEX;COMMIT we're inplace-updating a tuple visible only + * to this transaction. ROLLBACK then is one case where it's okay to lose + * inplace updates. (Restoring relhasindex=false on ROLLBACK is fine, since + * any concurrent CREATE INDEX would have blocked, then inplace-updated the + * committed tuple.) + * + * In principle, we could avoid waiting by overwriting every tuple in the + * updated tuple chain. Reader expectations permit updating a tuple only if + * it's aborted, is the tail of the chain, or we already updated the tuple + * referenced in its t_ctid. Hence, we would need to overwrite the tuples in + * order from tail to head. That would imply either (a) mutating all tuples + * in one critical section or (b) accepting a chance of partial completion. + * Partial completion of a relfrozenxid update would have the weird + * consequence that the table's next VACUUM could see the table's relfrozenxid + * move forward between vacuum_get_cutoffs() and finishing. */ -void -heap_inplace_update(Relation relation, HeapTuple tuple) +bool +heap_inplace_lock(Relation relation, + HeapTuple oldtup_ptr, Buffer buffer, + void (*release_callback) (void *), void *arg) { - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - uint32 oldlen; - uint32 newlen; + HeapTupleData oldtup = *oldtup_ptr; /* minimize diff vs. heap_update() */ + TM_Result result; + bool ret; + +#ifdef USE_ASSERT_CHECKING + if (RelationGetRelid(relation) == RelationRelationId) + check_inplace_rel_lock(oldtup_ptr); +#endif + + Assert(BufferIsValid(buffer)); /* - * For now, we don't allow parallel updates. Unlike a regular update, - * this should never create a combo CID, so it might be possible to relax - * this restriction, but not without more thought and testing. It's not - * clear that it would be useful, anyway. + * Construct shared cache inval if necessary. Because we pass a tuple + * version without our own inplace changes or inplace changes other + * sessions complete while we wait for locks, inplace update mustn't + * change catcache lookup keys. But we aren't bothering with index + * updates either, so that's true a fortiori. After LockBuffer(), it + * would be too late, because this might reach a + * CatalogCacheInitializeCache() that locks "buffer". */ - if (IsInParallelMode()) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("cannot update tuples during a parallel operation"))); + CacheInvalidateHeapTupleInplace(relation, oldtup_ptr, NULL); - INJECTION_POINT("inplace-before-pin"); - buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(&(tuple->t_self))); + LockTuple(relation, &oldtup.t_self, InplaceUpdateTupleLock); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); - page = (Page) BufferGetPage(buffer); - offnum = ItemPointerGetOffsetNumber(&(tuple->t_self)); - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); + /*---------- + * Interpret HeapTupleSatisfiesUpdate() like heap_update() does, except: + * + * - wait unconditionally + * - already locked tuple above, since inplace needs that unconditionally + * - don't recheck header after wait: simpler to defer to next iteration + * - don't try to continue even if the updater aborts: likewise + * - no crosscheck + */ + result = HeapTupleSatisfiesUpdate(&oldtup, GetCurrentCommandId(false), + buffer); - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(ERROR, "invalid lp"); + if (result == TM_Invisible) + { + /* no known way this can happen */ + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg_internal("attempted to overwrite invisible tuple"))); + } + else if (result == TM_SelfModified) + { + /* + * CREATE INDEX might reach this if an expression is silly enough to + * call e.g. SELECT ... FROM pg_class FOR SHARE. C code of other SQL + * statements might get here after a heap_update() of the same row, in + * the absence of an intervening CommandCounterIncrement(). + */ + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("tuple to be updated was already modified by an operation triggered by the current command"))); + } + else if (result == TM_BeingModified) + { + TransactionId xwait; + uint16 infomask; - htup = (HeapTupleHeader) PageGetItem(page, lp); + xwait = HeapTupleHeaderGetRawXmax(oldtup.t_data); + infomask = oldtup.t_data->t_infomask; + + if (infomask & HEAP_XMAX_IS_MULTI) + { + LockTupleMode lockmode = LockTupleNoKeyExclusive; + MultiXactStatus mxact_status = MultiXactStatusNoKeyUpdate; + int remain; + + if (DoesMultiXactIdConflict((MultiXactId) xwait, infomask, + lockmode, NULL)) + { + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + release_callback(arg); + ret = false; + MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask, + relation, &oldtup.t_self, XLTW_Update, + &remain); + } + else + ret = true; + } + else if (TransactionIdIsCurrentTransactionId(xwait)) + ret = true; + else if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask)) + ret = true; + else + { + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + release_callback(arg); + ret = false; + XactLockTableWait(xwait, relation, &oldtup.t_self, + XLTW_Update); + } + } + else + { + ret = (result == TM_Ok); + if (!ret) + { + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + release_callback(arg); + } + } + + /* + * GetCatalogSnapshot() relies on invalidation messages to know when to + * take a new snapshot. COMMIT of xwait is responsible for sending the + * invalidation. We're not acquiring heavyweight locks sufficient to + * block if not yet sent, so we must take a new snapshot to ensure a later + * attempt has a fair chance. While we don't need this if xwait aborted, + * don't bother optimizing that. + */ + if (!ret) + { + UnlockTuple(relation, &oldtup.t_self, InplaceUpdateTupleLock); + ForgetInplace_Inval(); + InvalidateCatalogSnapshot(); + } + return ret; +} - oldlen = ItemIdGetLength(lp) - htup->t_hoff; +/* + * heap_inplace_update_and_unlock - core of systable_inplace_update_finish + * + * The tuple cannot change size, and therefore its header fields and null + * bitmap (if any) don't change either. + * + * Since we hold LOCKTAG_TUPLE, no updater has a local copy of this tuple. + */ +void +heap_inplace_update_and_unlock(Relation relation, + HeapTuple oldtup, HeapTuple tuple, + Buffer buffer) +{ + HeapTupleHeader htup = oldtup->t_data; + uint32 oldlen; + uint32 newlen; + char *dst; + char *src; + int nmsgs = 0; + SharedInvalidationMessage *invalMessages = NULL; + bool RelcacheInitFileInval = false; + + Assert(ItemPointerEquals(&oldtup->t_self, &tuple->t_self)); + oldlen = oldtup->t_len - htup->t_hoff; newlen = tuple->t_len - tuple->t_data->t_hoff; if (oldlen != newlen || htup->t_hoff != tuple->t_data->t_hoff) elog(ERROR, "wrong tuple length"); - /* NO EREPORT(ERROR) from here till changes are logged */ - START_CRIT_SECTION(); + dst = (char *) htup + htup->t_hoff; + src = (char *) tuple->t_data + tuple->t_data->t_hoff; - memcpy((char *) htup + htup->t_hoff, - (char *) tuple->t_data + tuple->t_data->t_hoff, - newlen); + /* Like RecordTransactionCommit(), log only if needed */ + if (XLogStandbyInfoActive()) + nmsgs = inplaceGetInvalidationMessages(&invalMessages, + &RelcacheInitFileInval); - MarkBufferDirty(buffer); + /* + * Unlink relcache init files as needed. If unlinking, acquire + * RelCacheInitLock until after associated invalidations. By doing this + * in advance, if we checkpoint and then crash between inplace + * XLogInsert() and inval, we don't rely on StartupXLOG() -> + * RelationCacheInitFileRemove(). That uses elevel==LOG, so replay would + * neglect to PANIC on EIO. + */ + PreInplace_Inval(); + + /*---------- + * NO EREPORT(ERROR) from here till changes are complete + * + * Our buffer lock won't stop a reader having already pinned and checked + * visibility for this tuple. Hence, we write WAL first, then mutate the + * buffer. Like in MarkBufferDirtyHint() or RecordTransactionCommit(), + * checkpoint delay makes that acceptable. With the usual order of + * changes, a crash after memcpy() and before XLogInsert() could allow + * datfrozenxid to overtake relfrozenxid: + * + * ["D" is a VACUUM (ONLY_DATABASE_STATS)] + * ["R" is a VACUUM tbl] + * D: vac_update_datfrozenxid() -> systable_beginscan(pg_class) + * D: systable_getnext() returns pg_class tuple of tbl + * R: memcpy() into pg_class tuple of tbl + * D: raise pg_database.datfrozenxid, XLogInsert(), finish + * [crash] + * [recovery restores datfrozenxid w/o relfrozenxid] + * + * Mimic MarkBufferDirtyHint() subroutine XLogSaveBufferForHint(). + * Specifically, use DELAY_CHKPT_START, and copy the buffer to the stack. + * The stack copy facilitates a FPI of the post-mutation block before we + * accept other sessions seeing it. DELAY_CHKPT_START allows us to + * XLogInsert() before MarkBufferDirty(). Since XLogSaveBufferForHint() + * can operate under BUFFER_LOCK_SHARED, it can't avoid DELAY_CHKPT_START. + * This function, however, likely could avoid it with the following order + * of operations: MarkBufferDirty(), XLogInsert(), memcpy(). Opt to use + * DELAY_CHKPT_START here, too, as a way to have fewer distinct code + * patterns to analyze. Inplace update isn't so frequent that it should + * pursue the small optimization of skipping DELAY_CHKPT_START. + */ + Assert((MyProc->delayChkptFlags & DELAY_CHKPT_START) == 0); + START_CRIT_SECTION(); + MyProc->delayChkptFlags |= DELAY_CHKPT_START; /* XLOG stuff */ if (RelationNeedsWAL(relation)) { xl_heap_inplace xlrec; + PGAlignedBlock copied_buffer; + char *origdata = (char *) BufferGetBlock(buffer); + Page page = BufferGetPage(buffer); + uint16 lower = ((PageHeader) page)->pd_lower; + uint16 upper = ((PageHeader) page)->pd_upper; + uintptr_t dst_offset_in_block; + RelFileLocator rlocator; + ForkNumber forkno; + BlockNumber blkno; XLogRecPtr recptr; xlrec.offnum = ItemPointerGetOffsetNumber(&tuple->t_self); + xlrec.dbId = MyDatabaseId; + xlrec.tsId = MyDatabaseTableSpace; + xlrec.relcacheInitFileInval = RelcacheInitFileInval; + xlrec.nmsgs = nmsgs; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapInplace); - - XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); - XLogRegisterBufData(0, (char *) htup + htup->t_hoff, newlen); + XLogRegisterData(&xlrec, MinSizeOfHeapInplace); + if (nmsgs != 0) + XLogRegisterData(invalMessages, + nmsgs * sizeof(SharedInvalidationMessage)); + + /* register block matching what buffer will look like after changes */ + memcpy(copied_buffer.data, origdata, lower); + memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper); + dst_offset_in_block = dst - origdata; + memcpy(copied_buffer.data + dst_offset_in_block, src, newlen); + BufferGetTag(buffer, &rlocator, &forkno, &blkno); + Assert(forkno == MAIN_FORKNUM); + XLogRegisterBlock(0, &rlocator, forkno, blkno, copied_buffer.data, + REGBUF_STANDARD); + XLogRegisterBufData(0, src, newlen); /* inplace updates aren't decoded atm, don't log the origin */ @@ -6130,20 +6597,50 @@ heap_inplace_update(Relation relation, HeapTuple tuple) PageSetLSN(page, recptr); } + memcpy(dst, src, newlen); + + MarkBufferDirty(buffer); + + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + + /* + * Send invalidations to shared queue. SearchSysCacheLocked1() assumes we + * do this before UnlockTuple(). + * + * If we're mutating a tuple visible only to this transaction, there's an + * equivalent transactional inval from the action that created the tuple, + * and this inval is superfluous. + */ + AtInplace_Inval(); + + MyProc->delayChkptFlags &= ~DELAY_CHKPT_START; END_CRIT_SECTION(); + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); - UnlockReleaseBuffer(buffer); + AcceptInvalidationMessages(); /* local processing of just-sent inval */ /* - * Send out shared cache inval if necessary. Note that because we only - * pass the new version of the tuple, this mustn't be used for any - * operations that could change catcache lookup keys. But we aren't - * bothering with index updates either, so that's true a fortiori. + * Queue a transactional inval. The immediate invalidation we just sent + * is the only one known to be necessary. To reduce risk from the + * transition to immediate invalidation, continue sending a transactional + * invalidation like we've long done. Third-party code might rely on it. */ if (!IsBootstrapProcessingMode()) CacheInvalidateHeapTuple(relation, tuple, NULL); } +/* + * heap_inplace_unlock - reverse of heap_inplace_lock + */ +void +heap_inplace_unlock(Relation relation, + HeapTuple oldtup, Buffer buffer) +{ + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + UnlockTuple(relation, &oldtup->t_self, InplaceUpdateTupleLock); + ForgetInplace_Inval(); +} + #define FRM_NOOP 0x0001 #define FRM_INVALIDATE_XMAX 0x0002 #define FRM_RETURN_IS_XID 0x0004 @@ -6811,30 +7308,6 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, return freeze_xmin || replace_xvac || replace_xmax || freeze_xmax; } -/* - * heap_execute_freeze_tuple - * Execute the prepared freezing of a tuple with caller's freeze plan. - * - * Caller is responsible for ensuring that no other backend can access the - * storage underlying this tuple, either by holding an exclusive lock on the - * buffer containing it (which is what lazy VACUUM does), or by having it be - * in private storage (which is what CLUSTER and friends do). - */ -static inline void -heap_execute_freeze_tuple(HeapTupleHeader tuple, HeapTupleFreeze *frz) -{ - HeapTupleHeaderSetXmax(tuple, frz->xmax); - - if (frz->frzflags & XLH_FREEZE_XVAC) - HeapTupleHeaderSetXvac(tuple, FrozenTransactionId); - - if (frz->frzflags & XLH_INVALID_XVAC) - HeapTupleHeaderSetXvac(tuple, InvalidTransactionId); - - tuple->t_infomask = frz->t_infomask; - tuple->t_infomask2 = frz->t_infomask2; -} - /* * Perform xmin/xmax XID status sanity checks before actually executing freeze * plans. @@ -7096,10 +7569,10 @@ MultiXactIdGetUpdateXid(TransactionId xmax, uint16 t_infomask) * checking the hint bits. */ TransactionId -HeapTupleGetUpdateXid(HeapTupleHeader tuple) +HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup) { - return MultiXactIdGetUpdateXid(HeapTupleHeaderGetRawXmax(tuple), - tuple->t_infomask); + return MultiXactIdGetUpdateXid(HeapTupleHeaderGetRawXmax(tup), + tup->t_infomask); } /* @@ -7193,7 +7666,8 @@ DoesMultiXactIdConflict(MultiXactId multi, uint16 infomask, * fail if lock is unavailable. 'rel', 'ctid' and 'oper' are used to set up * context information for error messages. 'remaining', if not NULL, receives * the number of members that are still running, including any (non-aborted) - * subtransactions of our own transaction. + * subtransactions of our own transaction. 'logLockFailure' indicates whether + * to log details when a lock acquisition fails with 'nowait' enabled. * * We do this by sleeping on each member using XactLockTableWait. Any * members that belong to the current backend are *not* waited for, however; @@ -7214,7 +7688,7 @@ static bool Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, bool nowait, Relation rel, ItemPointer ctid, XLTW_Oper oper, - int *remaining) + int *remaining, bool logLockFailure) { bool result = true; MultiXactMember *members; @@ -7261,7 +7735,7 @@ Do_MultiXactIdWait(MultiXactId multi, MultiXactStatus status, */ if (nowait) { - result = ConditionalXactLockTableWait(memxid); + result = ConditionalXactLockTableWait(memxid, logLockFailure); if (!result) break; } @@ -7294,7 +7768,7 @@ MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, int *remaining) { (void) Do_MultiXactIdWait(multi, status, infomask, false, - rel, ctid, oper, remaining); + rel, ctid, oper, remaining, false); } /* @@ -7312,10 +7786,11 @@ MultiXactIdWait(MultiXactId multi, MultiXactStatus status, uint16 infomask, */ static bool ConditionalMultiXactIdWait(MultiXactId multi, MultiXactStatus status, - uint16 infomask, Relation rel, int *remaining) + uint16 infomask, Relation rel, int *remaining, + bool logLockFailure) { return Do_MultiXactIdWait(multi, status, infomask, true, - rel, NULL, XLTW_None, remaining); + rel, NULL, XLTW_None, remaining, logLockFailure); } /* @@ -7982,7 +8457,6 @@ index_delete_sort(TM_IndexDeleteOp *delstate) { TM_IndexDelete *deltids = delstate->deltids; int ndeltids = delstate->ndeltids; - int low = 0; /* * Shellsort gap sequence (taken from Sedgewick-Incerpi paper). @@ -7998,7 +8472,7 @@ index_delete_sort(TM_IndexDeleteOp *delstate) for (int g = 0; g < lengthof(gaps); g++) { - for (int hi = gaps[g], i = low + hi; i < ndeltids; i++) + for (int hi = gaps[g], i = hi; i < ndeltids; i++) { TM_IndexDelete d = deltids[i]; int j = i; @@ -8335,7 +8809,7 @@ log_heap_visible(Relation rel, Buffer heap_buffer, Buffer vm_buffer, if (RelationIsAccessibleInLogicalDecoding(rel)) xlrec.flags |= VISIBILITYMAP_XLOG_CATALOG_REL; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapVisible); + XLogRegisterData(&xlrec, SizeOfHeapVisible); XLogRegisterBuffer(0, vm_buffer, 0); @@ -8486,7 +8960,7 @@ log_heap_update(Relation reln, Buffer oldbuf, if (oldbuf != newbuf) XLogRegisterBuffer(1, oldbuf, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec, SizeOfHeapUpdate); + XLogRegisterData(&xlrec, SizeOfHeapUpdate); /* * Prepare WAL data for the new tuple. @@ -8497,15 +8971,15 @@ log_heap_update(Relation reln, Buffer oldbuf, { prefix_suffix[0] = prefixlen; prefix_suffix[1] = suffixlen; - XLogRegisterBufData(0, (char *) &prefix_suffix, sizeof(uint16) * 2); + XLogRegisterBufData(0, &prefix_suffix, sizeof(uint16) * 2); } else if (prefixlen > 0) { - XLogRegisterBufData(0, (char *) &prefixlen, sizeof(uint16)); + XLogRegisterBufData(0, &prefixlen, sizeof(uint16)); } else { - XLogRegisterBufData(0, (char *) &suffixlen, sizeof(uint16)); + XLogRegisterBufData(0, &suffixlen, sizeof(uint16)); } } @@ -8519,11 +8993,11 @@ log_heap_update(Relation reln, Buffer oldbuf, * * The 'data' doesn't include the common prefix or suffix. */ - XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader); + XLogRegisterBufData(0, &xlhdr, SizeOfHeapHeader); if (prefixlen == 0) { XLogRegisterBufData(0, - ((char *) newtup->t_data) + SizeofHeapTupleHeader, + (char *) newtup->t_data + SizeofHeapTupleHeader, newtup->t_len - SizeofHeapTupleHeader - suffixlen); } else @@ -8536,13 +9010,13 @@ log_heap_update(Relation reln, Buffer oldbuf, if (newtup->t_data->t_hoff - SizeofHeapTupleHeader > 0) { XLogRegisterBufData(0, - ((char *) newtup->t_data) + SizeofHeapTupleHeader, + (char *) newtup->t_data + SizeofHeapTupleHeader, newtup->t_data->t_hoff - SizeofHeapTupleHeader); } /* data after common prefix */ XLogRegisterBufData(0, - ((char *) newtup->t_data) + newtup->t_data->t_hoff + prefixlen, + (char *) newtup->t_data + newtup->t_data->t_hoff + prefixlen, newtup->t_len - newtup->t_data->t_hoff - prefixlen - suffixlen); } @@ -8554,7 +9028,7 @@ log_heap_update(Relation reln, Buffer oldbuf, xlhdr_idx.t_infomask = old_key_tuple->t_data->t_infomask; xlhdr_idx.t_hoff = old_key_tuple->t_data->t_hoff; - XLogRegisterData((char *) &xlhdr_idx, SizeOfHeapHeader); + XLogRegisterData(&xlhdr_idx, SizeOfHeapHeader); /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ XLogRegisterData((char *) old_key_tuple->t_data + SizeofHeapTupleHeader, @@ -8634,7 +9108,7 @@ log_heap_new_cid(Relation relation, HeapTuple tup) * called us certainly did, but that's WAL-logged separately. */ XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapNewCid); + XLogRegisterData(&xlrec, SizeOfHeapNewCid); /* will be looked at irrespective of origin */ @@ -8745,1303 +9219,6 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required, return key_tuple; } -/* - * Replay XLOG_HEAP2_PRUNE_* records. - */ -static void -heap_xlog_prune_freeze(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - char *maindataptr = XLogRecGetData(record); - xl_heap_prune xlrec; - Buffer buffer; - RelFileLocator rlocator; - BlockNumber blkno; - XLogRedoAction action; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); - memcpy(&xlrec, maindataptr, SizeOfHeapPrune); - maindataptr += SizeOfHeapPrune; - - /* - * We will take an ordinary exclusive lock or a cleanup lock depending on - * whether the XLHP_CLEANUP_LOCK flag is set. With an ordinary exclusive - * lock, we better not be doing anything that requires moving existing - * tuple data. - */ - Assert((xlrec.flags & XLHP_CLEANUP_LOCK) != 0 || - (xlrec.flags & (XLHP_HAS_REDIRECTIONS | XLHP_HAS_DEAD_ITEMS)) == 0); - - /* - * We are about to remove and/or freeze tuples. In Hot Standby mode, - * ensure that there are no queries running for which the removed tuples - * are still visible or which still consider the frozen xids as running. - * The conflict horizon XID comes after xl_heap_prune. - */ - if ((xlrec.flags & XLHP_HAS_CONFLICT_HORIZON) != 0) - { - TransactionId snapshot_conflict_horizon; - - /* memcpy() because snapshot_conflict_horizon is stored unaligned */ - memcpy(&snapshot_conflict_horizon, maindataptr, sizeof(TransactionId)); - maindataptr += sizeof(TransactionId); - - if (InHotStandby) - ResolveRecoveryConflictWithSnapshot(snapshot_conflict_horizon, - (xlrec.flags & XLHP_IS_CATALOG_REL) != 0, - rlocator); - } - - /* - * If we have a full-page image, restore it and we're done. - */ - action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, - (xlrec.flags & XLHP_CLEANUP_LOCK) != 0, - &buffer); - if (action == BLK_NEEDS_REDO) - { - Page page = (Page) BufferGetPage(buffer); - OffsetNumber *redirected; - OffsetNumber *nowdead; - OffsetNumber *nowunused; - int nredirected; - int ndead; - int nunused; - int nplans; - Size datalen; - xlhp_freeze_plan *plans; - OffsetNumber *frz_offsets; - char *dataptr = XLogRecGetBlockData(record, 0, &datalen); - - heap_xlog_deserialize_prune_and_freeze(dataptr, xlrec.flags, - &nplans, &plans, &frz_offsets, - &nredirected, &redirected, - &ndead, &nowdead, - &nunused, &nowunused); - - /* - * Update all line pointers per the record, and repair fragmentation - * if needed. - */ - if (nredirected > 0 || ndead > 0 || nunused > 0) - heap_page_prune_execute(buffer, - (xlrec.flags & XLHP_CLEANUP_LOCK) == 0, - redirected, nredirected, - nowdead, ndead, - nowunused, nunused); - - /* Freeze tuples */ - for (int p = 0; p < nplans; p++) - { - HeapTupleFreeze frz; - - /* - * Convert freeze plan representation from WAL record into - * per-tuple format used by heap_execute_freeze_tuple - */ - frz.xmax = plans[p].xmax; - frz.t_infomask2 = plans[p].t_infomask2; - frz.t_infomask = plans[p].t_infomask; - frz.frzflags = plans[p].frzflags; - frz.offset = InvalidOffsetNumber; /* unused, but be tidy */ - - for (int i = 0; i < plans[p].ntuples; i++) - { - OffsetNumber offset = *(frz_offsets++); - ItemId lp; - HeapTupleHeader tuple; - - lp = PageGetItemId(page, offset); - tuple = (HeapTupleHeader) PageGetItem(page, lp); - heap_execute_freeze_tuple(tuple, &frz); - } - } - - /* There should be no more data */ - Assert((char *) frz_offsets == dataptr + datalen); - - /* - * Note: we don't worry about updating the page's prunability hints. - * At worst this will cause an extra prune cycle to occur soon. - */ - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - - /* - * If we released any space or line pointers, update the free space map. - * - * Do this regardless of a full-page image being applied, since the FSM - * data is not in the page anyway. - */ - if (BufferIsValid(buffer)) - { - if (xlrec.flags & (XLHP_HAS_REDIRECTIONS | - XLHP_HAS_DEAD_ITEMS | - XLHP_HAS_NOW_UNUSED_ITEMS)) - { - Size freespace = PageGetHeapFreeSpace(BufferGetPage(buffer)); - - UnlockReleaseBuffer(buffer); - - XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); - } - else - UnlockReleaseBuffer(buffer); - } -} - -/* - * Replay XLOG_HEAP2_VISIBLE record. - * - * The critical integrity requirement here is that we must never end up with - * a situation where the visibility map bit is set, and the page-level - * PD_ALL_VISIBLE bit is clear. If that were to occur, then a subsequent - * page modification would fail to clear the visibility map bit. - */ -static void -heap_xlog_visible(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_visible *xlrec = (xl_heap_visible *) XLogRecGetData(record); - Buffer vmbuffer = InvalidBuffer; - Buffer buffer; - Page page; - RelFileLocator rlocator; - BlockNumber blkno; - XLogRedoAction action; - - Assert((xlrec->flags & VISIBILITYMAP_XLOG_VALID_BITS) == xlrec->flags); - - XLogRecGetBlockTag(record, 1, &rlocator, NULL, &blkno); - - /* - * If there are any Hot Standby transactions running that have an xmin - * horizon old enough that this page isn't all-visible for them, they - * might incorrectly decide that an index-only scan can skip a heap fetch. - * - * NB: It might be better to throw some kind of "soft" conflict here that - * forces any index-only scan that is in flight to perform heap fetches, - * rather than killing the transaction outright. - */ - if (InHotStandby) - ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon, - xlrec->flags & VISIBILITYMAP_XLOG_CATALOG_REL, - rlocator); - - /* - * Read the heap page, if it still exists. If the heap file has dropped or - * truncated later in recovery, we don't need to update the page, but we'd - * better still update the visibility map. - */ - action = XLogReadBufferForRedo(record, 1, &buffer); - if (action == BLK_NEEDS_REDO) - { - /* - * We don't bump the LSN of the heap page when setting the visibility - * map bit (unless checksums or wal_hint_bits is enabled, in which - * case we must). This exposes us to torn page hazards, but since - * we're not inspecting the existing page contents in any way, we - * don't care. - */ - page = BufferGetPage(buffer); - - PageSetAllVisible(page); - - if (XLogHintBitIsNeeded()) - PageSetLSN(page, lsn); - - MarkBufferDirty(buffer); - } - else if (action == BLK_RESTORED) - { - /* - * If heap block was backed up, we already restored it and there's - * nothing more to do. (This can only happen with checksums or - * wal_log_hints enabled.) - */ - } - - if (BufferIsValid(buffer)) - { - Size space = PageGetFreeSpace(BufferGetPage(buffer)); - - UnlockReleaseBuffer(buffer); - - /* - * Since FSM is not WAL-logged and only updated heuristically, it - * easily becomes stale in standbys. If the standby is later promoted - * and runs VACUUM, it will skip updating individual free space - * figures for pages that became all-visible (or all-frozen, depending - * on the vacuum mode,) which is troublesome when FreeSpaceMapVacuum - * propagates too optimistic free space values to upper FSM layers; - * later inserters try to use such pages only to find out that they - * are unusable. This can cause long stalls when there are many such - * pages. - * - * Forestall those problems by updating FSM's idea about a page that - * is becoming all-visible or all-frozen. - * - * Do this regardless of a full-page image being applied, since the - * FSM data is not in the page anyway. - */ - if (xlrec->flags & VISIBILITYMAP_VALID_BITS) - XLogRecordPageWithFreeSpace(rlocator, blkno, space); - } - - /* - * Even if we skipped the heap page update due to the LSN interlock, it's - * still safe to update the visibility map. Any WAL record that clears - * the visibility map bit does so before checking the page LSN, so any - * bits that need to be cleared will still be cleared. - */ - if (XLogReadBufferForRedoExtended(record, 0, RBM_ZERO_ON_ERROR, false, - &vmbuffer) == BLK_NEEDS_REDO) - { - Page vmpage = BufferGetPage(vmbuffer); - Relation reln; - uint8 vmbits; - - /* initialize the page if it was read as zeros */ - if (PageIsNew(vmpage)) - PageInit(vmpage, BLCKSZ, 0); - - /* remove VISIBILITYMAP_XLOG_* */ - vmbits = xlrec->flags & VISIBILITYMAP_VALID_BITS; - - /* - * XLogReadBufferForRedoExtended locked the buffer. But - * visibilitymap_set will handle locking itself. - */ - LockBuffer(vmbuffer, BUFFER_LOCK_UNLOCK); - - reln = CreateFakeRelcacheEntry(rlocator); - visibilitymap_pin(reln, blkno, &vmbuffer); - - visibilitymap_set(reln, blkno, InvalidBuffer, lsn, vmbuffer, - xlrec->snapshotConflictHorizon, vmbits); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - else if (BufferIsValid(vmbuffer)) - UnlockReleaseBuffer(vmbuffer); -} - -/* - * Given an "infobits" field from an XLog record, set the correct bits in the - * given infomask and infomask2 for the tuple touched by the record. - * - * (This is the reverse of compute_infobits). - */ -static void -fix_infomask_from_infobits(uint8 infobits, uint16 *infomask, uint16 *infomask2) -{ - *infomask &= ~(HEAP_XMAX_IS_MULTI | HEAP_XMAX_LOCK_ONLY | - HEAP_XMAX_KEYSHR_LOCK | HEAP_XMAX_EXCL_LOCK); - *infomask2 &= ~HEAP_KEYS_UPDATED; - - if (infobits & XLHL_XMAX_IS_MULTI) - *infomask |= HEAP_XMAX_IS_MULTI; - if (infobits & XLHL_XMAX_LOCK_ONLY) - *infomask |= HEAP_XMAX_LOCK_ONLY; - if (infobits & XLHL_XMAX_EXCL_LOCK) - *infomask |= HEAP_XMAX_EXCL_LOCK; - /* note HEAP_XMAX_SHR_LOCK isn't considered here */ - if (infobits & XLHL_XMAX_KEYSHR_LOCK) - *infomask |= HEAP_XMAX_KEYSHR_LOCK; - - if (infobits & XLHL_KEYS_UPDATED) - *infomask2 |= HEAP_KEYS_UPDATED; -} - -static void -heap_xlog_delete(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); - Buffer buffer; - Page page; - ItemId lp = NULL; - HeapTupleHeader htup; - BlockNumber blkno; - RelFileLocator target_locator; - ItemPointerData target_tid; - - XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); - ItemPointerSetBlockNumber(&target_tid, blkno); - ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(target_locator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - if (PageGetMaxOffsetNumber(page) >= xlrec->offnum) - lp = PageGetItemId(page, xlrec->offnum); - - if (PageGetMaxOffsetNumber(page) < xlrec->offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - HeapTupleHeaderClearHotUpdated(htup); - fix_infomask_from_infobits(xlrec->infobits_set, - &htup->t_infomask, &htup->t_infomask2); - if (!(xlrec->flags & XLH_DELETE_IS_SUPER)) - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - else - HeapTupleHeaderSetXmin(htup, InvalidTransactionId); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - - /* Mark the page as a candidate for pruning */ - PageSetPrunable(page, XLogRecGetXid(record)); - - if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* Make sure t_ctid is set correctly */ - if (xlrec->flags & XLH_DELETE_IS_PARTITION_MOVE) - HeapTupleHeaderSetMovedPartitions(htup); - else - htup->t_ctid = target_tid; - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_insert(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); - Buffer buffer; - Page page; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - HeapTupleHeader htup; - xl_heap_header xlhdr; - uint32 newlen; - Size freespace = 0; - RelFileLocator target_locator; - BlockNumber blkno; - ItemPointerData target_tid; - XLogRedoAction action; - - XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); - ItemPointerSetBlockNumber(&target_tid, blkno); - ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(target_locator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* - * If we inserted the first and only tuple on the page, re-initialize the - * page from scratch. - */ - if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) - { - buffer = XLogInitBufferForRedo(record, 0); - page = BufferGetPage(buffer); - PageInit(page, BufferGetPageSize(buffer), 0); - action = BLK_NEEDS_REDO; - } - else - action = XLogReadBufferForRedo(record, 0, &buffer); - if (action == BLK_NEEDS_REDO) - { - Size datalen; - char *data; - - page = BufferGetPage(buffer); - - if (PageGetMaxOffsetNumber(page) + 1 < xlrec->offnum) - elog(PANIC, "invalid max offset number"); - - data = XLogRecGetBlockData(record, 0, &datalen); - - newlen = datalen - SizeOfHeapHeader; - Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); - memcpy((char *) &xlhdr, data, SizeOfHeapHeader); - data += SizeOfHeapHeader; - - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ - memcpy((char *) htup + SizeofHeapTupleHeader, - data, - newlen); - newlen += SizeofHeapTupleHeader; - htup->t_infomask2 = xlhdr.t_infomask2; - htup->t_infomask = xlhdr.t_infomask; - htup->t_hoff = xlhdr.t_hoff; - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - htup->t_ctid = target_tid; - - if (PageAddItem(page, (Item) htup, newlen, xlrec->offnum, - true, true) == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ - if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) - PageSetAllVisible(page); - - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); - - /* - * If the page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(target_locator, blkno, freespace); -} - -/* - * Handles MULTI_INSERT record type. - */ -static void -heap_xlog_multi_insert(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_multi_insert *xlrec; - RelFileLocator rlocator; - BlockNumber blkno; - Buffer buffer; - Page page; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - HeapTupleHeader htup; - uint32 newlen; - Size freespace = 0; - int i; - bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0; - XLogRedoAction action; - - /* - * Insertion doesn't overwrite MVCC data, so no conflict processing is - * required. - */ - xlrec = (xl_heap_multi_insert *) XLogRecGetData(record); - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); - - /* check that the mutually exclusive flags are not both set */ - Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) && - (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET))); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, blkno, &vmbuffer); - visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (isinit) - { - buffer = XLogInitBufferForRedo(record, 0); - page = BufferGetPage(buffer); - PageInit(page, BufferGetPageSize(buffer), 0); - action = BLK_NEEDS_REDO; - } - else - action = XLogReadBufferForRedo(record, 0, &buffer); - if (action == BLK_NEEDS_REDO) - { - char *tupdata; - char *endptr; - Size len; - - /* Tuples are stored as block data */ - tupdata = XLogRecGetBlockData(record, 0, &len); - endptr = tupdata + len; - - page = (Page) BufferGetPage(buffer); - - for (i = 0; i < xlrec->ntuples; i++) - { - OffsetNumber offnum; - xl_multi_insert_tuple *xlhdr; - - /* - * If we're reinitializing the page, the tuples are stored in - * order from FirstOffsetNumber. Otherwise there's an array of - * offsets in the WAL record, and the tuples come after that. - */ - if (isinit) - offnum = FirstOffsetNumber + i; - else - offnum = xlrec->offsets[i]; - if (PageGetMaxOffsetNumber(page) + 1 < offnum) - elog(PANIC, "invalid max offset number"); - - xlhdr = (xl_multi_insert_tuple *) SHORTALIGN(tupdata); - tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; - - newlen = xlhdr->datalen; - Assert(newlen <= MaxHeapTupleSize); - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ - memcpy((char *) htup + SizeofHeapTupleHeader, - (char *) tupdata, - newlen); - tupdata += newlen; - - newlen += SizeofHeapTupleHeader; - htup->t_infomask2 = xlhdr->t_infomask2; - htup->t_infomask = xlhdr->t_infomask; - htup->t_hoff = xlhdr->t_hoff; - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - ItemPointerSetBlockNumber(&htup->t_ctid, blkno); - ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); - - offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); - if (offnum == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - } - if (tupdata != endptr) - elog(PANIC, "total tuple length mismatch"); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - - if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ - if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) - PageSetAllVisible(page); - - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); - - /* - * If the page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); -} - -/* - * Handles UPDATE and HOT_UPDATE - */ -static void -heap_xlog_update(XLogReaderState *record, bool hot_update) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); - RelFileLocator rlocator; - BlockNumber oldblk; - BlockNumber newblk; - ItemPointerData newtid; - Buffer obuffer, - nbuffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleData oldtup; - HeapTupleHeader htup; - uint16 prefixlen = 0, - suffixlen = 0; - char *newp; - union - { - HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; - } tbuf; - xl_heap_header xlhdr; - uint32 newlen; - Size freespace = 0; - XLogRedoAction oldaction; - XLogRedoAction newaction; - - /* initialize to keep the compiler quiet */ - oldtup.t_data = NULL; - oldtup.t_len = 0; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &newblk); - if (XLogRecGetBlockTagExtended(record, 1, NULL, NULL, &oldblk, NULL)) - { - /* HOT updates are never done across pages */ - Assert(!hot_update); - } - else - oldblk = newblk; - - ItemPointerSet(&newtid, newblk, xlrec->new_offnum); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, oldblk, &vmbuffer); - visibilitymap_clear(reln, oldblk, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* - * In normal operation, it is important to lock the two pages in - * page-number order, to avoid possible deadlocks against other update - * operations going the other way. However, during WAL replay there can - * be no other update happening, so we don't need to worry about that. But - * we *do* need to worry that we don't expose an inconsistent state to Hot - * Standby queries --- so the original page can't be unlocked before we've - * added the new tuple to the new page. - */ - - /* Deal with old tuple version */ - oldaction = XLogReadBufferForRedo(record, (oldblk == newblk) ? 0 : 1, - &obuffer); - if (oldaction == BLK_NEEDS_REDO) - { - page = BufferGetPage(obuffer); - offnum = xlrec->old_offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - oldtup.t_data = htup; - oldtup.t_len = ItemIdGetLength(lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - if (hot_update) - HeapTupleHeaderSetHotUpdated(htup); - else - HeapTupleHeaderClearHotUpdated(htup); - fix_infomask_from_infobits(xlrec->old_infobits_set, &htup->t_infomask, - &htup->t_infomask2); - HeapTupleHeaderSetXmax(htup, xlrec->old_xmax); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - /* Set forward chain link in t_ctid */ - htup->t_ctid = newtid; - - /* Mark the page as a candidate for pruning */ - PageSetPrunable(page, XLogRecGetXid(record)); - - if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - PageSetLSN(page, lsn); - MarkBufferDirty(obuffer); - } - - /* - * Read the page the new tuple goes into, if different from old. - */ - if (oldblk == newblk) - { - nbuffer = obuffer; - newaction = oldaction; - } - else if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) - { - nbuffer = XLogInitBufferForRedo(record, 0); - page = (Page) BufferGetPage(nbuffer); - PageInit(page, BufferGetPageSize(nbuffer), 0); - newaction = BLK_NEEDS_REDO; - } - else - newaction = XLogReadBufferForRedo(record, 0, &nbuffer); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) - { - Relation reln = CreateFakeRelcacheEntry(rlocator); - Buffer vmbuffer = InvalidBuffer; - - visibilitymap_pin(reln, newblk, &vmbuffer); - visibilitymap_clear(reln, newblk, vmbuffer, VISIBILITYMAP_VALID_BITS); - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - /* Deal with new tuple */ - if (newaction == BLK_NEEDS_REDO) - { - char *recdata; - char *recdata_end; - Size datalen; - Size tuplen; - - recdata = XLogRecGetBlockData(record, 0, &datalen); - recdata_end = recdata + datalen; - - page = BufferGetPage(nbuffer); - - offnum = xlrec->new_offnum; - if (PageGetMaxOffsetNumber(page) + 1 < offnum) - elog(PANIC, "invalid max offset number"); - - if (xlrec->flags & XLH_UPDATE_PREFIX_FROM_OLD) - { - Assert(newblk == oldblk); - memcpy(&prefixlen, recdata, sizeof(uint16)); - recdata += sizeof(uint16); - } - if (xlrec->flags & XLH_UPDATE_SUFFIX_FROM_OLD) - { - Assert(newblk == oldblk); - memcpy(&suffixlen, recdata, sizeof(uint16)); - recdata += sizeof(uint16); - } - - memcpy((char *) &xlhdr, recdata, SizeOfHeapHeader); - recdata += SizeOfHeapHeader; - - tuplen = recdata_end - recdata; - Assert(tuplen <= MaxHeapTupleSize); - - htup = &tbuf.hdr; - MemSet((char *) htup, 0, SizeofHeapTupleHeader); - - /* - * Reconstruct the new tuple using the prefix and/or suffix from the - * old tuple, and the data stored in the WAL record. - */ - newp = (char *) htup + SizeofHeapTupleHeader; - if (prefixlen > 0) - { - int len; - - /* copy bitmap [+ padding] [+ oid] from WAL record */ - len = xlhdr.t_hoff - SizeofHeapTupleHeader; - memcpy(newp, recdata, len); - recdata += len; - newp += len; - - /* copy prefix from old tuple */ - memcpy(newp, (char *) oldtup.t_data + oldtup.t_data->t_hoff, prefixlen); - newp += prefixlen; - - /* copy new tuple data from WAL record */ - len = tuplen - (xlhdr.t_hoff - SizeofHeapTupleHeader); - memcpy(newp, recdata, len); - recdata += len; - newp += len; - } - else - { - /* - * copy bitmap [+ padding] [+ oid] + data from record, all in one - * go - */ - memcpy(newp, recdata, tuplen); - recdata += tuplen; - newp += tuplen; - } - Assert(recdata == recdata_end); - - /* copy suffix from old tuple */ - if (suffixlen > 0) - memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen); - - newlen = SizeofHeapTupleHeader + tuplen + prefixlen + suffixlen; - htup->t_infomask2 = xlhdr.t_infomask2; - htup->t_infomask = xlhdr.t_infomask; - htup->t_hoff = xlhdr.t_hoff; - - HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); - HeapTupleHeaderSetCmin(htup, FirstCommandId); - HeapTupleHeaderSetXmax(htup, xlrec->new_xmax); - /* Make sure there is no forward chain link in t_ctid */ - htup->t_ctid = newtid; - - offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); - if (offnum == InvalidOffsetNumber) - elog(PANIC, "failed to add tuple"); - - if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) - PageClearAllVisible(page); - - freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ - - PageSetLSN(page, lsn); - MarkBufferDirty(nbuffer); - } - - if (BufferIsValid(nbuffer) && nbuffer != obuffer) - UnlockReleaseBuffer(nbuffer); - if (BufferIsValid(obuffer)) - UnlockReleaseBuffer(obuffer); - - /* - * If the new page is running low on free space, update the FSM as well. - * Arbitrarily, our definition of "low" is less than 20%. We can't do much - * better than that without knowing the fill-factor for the table. - * - * However, don't update the FSM on HOT updates, because after crash - * recovery, either the old or the new tuple will certainly be dead and - * prunable. After pruning, the page will have roughly as much free space - * as it did before the update, assuming the new tuple is about the same - * size as the old one. - * - * XXX: Don't do this if the page was restored from full page image. We - * don't bother to update the FSM in that case, it doesn't need to be - * totally accurate anyway. - */ - if (newaction == BLK_NEEDS_REDO && !hot_update && freespace < BLCKSZ / 5) - XLogRecordPageWithFreeSpace(rlocator, newblk, freespace); -} - -static void -heap_xlog_confirm(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_confirm *xlrec = (xl_heap_confirm *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - /* - * Confirm tuple as actually inserted - */ - ItemPointerSet(&htup->t_ctid, BufferGetBlockNumber(buffer), offnum); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_lock(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) - { - RelFileLocator rlocator; - Buffer vmbuffer = InvalidBuffer; - BlockNumber block; - Relation reln; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); - reln = CreateFakeRelcacheEntry(rlocator); - - visibilitymap_pin(reln, block, &vmbuffer); - visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = (Page) BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, - &htup->t_infomask2); - - /* - * Clear relevant update flags, but only if the modified infomask says - * there's no update. - */ - if (HEAP_XMAX_IS_LOCKED_ONLY(htup->t_infomask)) - { - HeapTupleHeaderClearHotUpdated(htup); - /* Make sure there is no forward chain link in t_ctid */ - ItemPointerSet(&htup->t_ctid, - BufferGetBlockNumber(buffer), - offnum); - } - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - HeapTupleHeaderSetCmax(htup, FirstCommandId, false); - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_lock_updated(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_lock_updated *xlrec; - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - - xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); - - /* - * The visibility map may need to be fixed even if the heap page is - * already up-to-date. - */ - if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) - { - RelFileLocator rlocator; - Buffer vmbuffer = InvalidBuffer; - BlockNumber block; - Relation reln; - - XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); - reln = CreateFakeRelcacheEntry(rlocator); - - visibilitymap_pin(reln, block, &vmbuffer); - visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); - - ReleaseBuffer(vmbuffer); - FreeFakeRelcacheEntry(reln); - } - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); - htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; - fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, - &htup->t_infomask2); - HeapTupleHeaderSetXmax(htup, xlrec->xmax); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -static void -heap_xlog_inplace(XLogReaderState *record) -{ - XLogRecPtr lsn = record->EndRecPtr; - xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); - Buffer buffer; - Page page; - OffsetNumber offnum; - ItemId lp = NULL; - HeapTupleHeader htup; - uint32 oldlen; - Size newlen; - - if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) - { - char *newtup = XLogRecGetBlockData(record, 0, &newlen); - - page = BufferGetPage(buffer); - - offnum = xlrec->offnum; - if (PageGetMaxOffsetNumber(page) >= offnum) - lp = PageGetItemId(page, offnum); - - if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) - elog(PANIC, "invalid lp"); - - htup = (HeapTupleHeader) PageGetItem(page, lp); - - oldlen = ItemIdGetLength(lp) - htup->t_hoff; - if (oldlen != newlen) - elog(PANIC, "wrong tuple length"); - - memcpy((char *) htup + htup->t_hoff, newtup, newlen); - - PageSetLSN(page, lsn); - MarkBufferDirty(buffer); - } - if (BufferIsValid(buffer)) - UnlockReleaseBuffer(buffer); -} - -void -heap_redo(XLogReaderState *record) -{ - uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; - - /* - * These operations don't overwrite MVCC data so no conflict processing is - * required. The ones in heap2 rmgr do. - */ - - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP_INSERT: - heap_xlog_insert(record); - break; - case XLOG_HEAP_DELETE: - heap_xlog_delete(record); - break; - case XLOG_HEAP_UPDATE: - heap_xlog_update(record, false); - break; - case XLOG_HEAP_TRUNCATE: - - /* - * TRUNCATE is a no-op because the actions are already logged as - * SMGR WAL records. TRUNCATE WAL record only exists for logical - * decoding. - */ - break; - case XLOG_HEAP_HOT_UPDATE: - heap_xlog_update(record, true); - break; - case XLOG_HEAP_CONFIRM: - heap_xlog_confirm(record); - break; - case XLOG_HEAP_LOCK: - heap_xlog_lock(record); - break; - case XLOG_HEAP_INPLACE: - heap_xlog_inplace(record); - break; - default: - elog(PANIC, "heap_redo: unknown op code %u", info); - } -} - -void -heap2_redo(XLogReaderState *record) -{ - uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; - - switch (info & XLOG_HEAP_OPMASK) - { - case XLOG_HEAP2_PRUNE_ON_ACCESS: - case XLOG_HEAP2_PRUNE_VACUUM_SCAN: - case XLOG_HEAP2_PRUNE_VACUUM_CLEANUP: - heap_xlog_prune_freeze(record); - break; - case XLOG_HEAP2_VISIBLE: - heap_xlog_visible(record); - break; - case XLOG_HEAP2_MULTI_INSERT: - heap_xlog_multi_insert(record); - break; - case XLOG_HEAP2_LOCK_UPDATED: - heap_xlog_lock_updated(record); - break; - case XLOG_HEAP2_NEW_CID: - - /* - * Nothing to do on a real replay, only used during logical - * decoding. - */ - break; - case XLOG_HEAP2_REWRITE: - heap_xlog_logical_rewrite(record); - break; - default: - elog(PANIC, "heap2_redo: unknown op code %u", info); - } -} - -/* - * Mask a heap page before performing consistency checks on it. - */ -void -heap_mask(char *pagedata, BlockNumber blkno) -{ - Page page = (Page) pagedata; - OffsetNumber off; - - mask_page_lsn_and_checksum(page); - - mask_page_hint_bits(page); - mask_unused_space(page); - - for (off = 1; off <= PageGetMaxOffsetNumber(page); off++) - { - ItemId iid = PageGetItemId(page, off); - char *page_item; - - page_item = (char *) (page + ItemIdGetOffset(iid)); - - if (ItemIdIsNormal(iid)) - { - HeapTupleHeader page_htup = (HeapTupleHeader) page_item; - - /* - * If xmin of a tuple is not yet frozen, we should ignore - * differences in hint bits, since they can be set without - * emitting WAL. - */ - if (!HeapTupleHeaderXminFrozen(page_htup)) - page_htup->t_infomask &= ~HEAP_XACT_MASK; - else - { - /* Still we need to mask xmax hint bits. */ - page_htup->t_infomask &= ~HEAP_XMAX_INVALID; - page_htup->t_infomask &= ~HEAP_XMAX_COMMITTED; - } - - /* - * During replay, we set Command Id to FirstCommandId. Hence, mask - * it. See heap_xlog_insert() for details. - */ - page_htup->t_choice.t_heap.t_field3.t_cid = MASK_MARKER; - - /* - * For a speculative tuple, heap_insert() does not set ctid in the - * caller-passed heap tuple itself, leaving the ctid field to - * contain a speculative token value - a per-backend monotonically - * increasing identifier. Besides, it does not WAL-log ctid under - * any circumstances. - * - * During redo, heap_xlog_insert() sets t_ctid to current block - * number and self offset number. It doesn't care about any - * speculative insertions on the primary. Hence, we set t_ctid to - * current block number and self offset number to ignore any - * inconsistency. - */ - if (HeapTupleHeaderIsSpeculative(page_htup)) - ItemPointerSet(&page_htup->t_ctid, blkno, off); - - /* - * NB: Not ignoring ctid changes due to the tuple having moved - * (i.e. HeapTupleHeaderIndicatesMovedPartitions), because that's - * important information that needs to be in-sync between primary - * and standby, and thus is WAL logged. - */ - } - - /* - * Ignore any padding bytes after the tuple, when the length of the - * item is not MAXALIGNed. - */ - if (ItemIdHasStorage(iid)) - { - int len = ItemIdGetLength(iid); - int padlen = MAXALIGN(len) - len; - - if (padlen > 0) - memset(page_item + len, MASK_MARKER, padlen); - } - } -} - /* * HeapCheckForSerializableConflictOut * We are reading a tuple. If it's not visible, there may be a diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 6f8b1b79298f3..cb4bc35c93ed4 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -3,7 +3,7 @@ * heapam_handler.c * heap table access method code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -56,7 +56,9 @@ static bool SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer, static BlockNumber heapam_scan_get_blocks_done(HeapScanDesc hscan); -static const TableAmRoutine heapam_methods; +static bool BitmapHeapScanNextBlock(TableScanDesc scan, + bool *recheck, + uint64 *lossy_pages, uint64 *exact_pages); /* ------------------------------------------------------------------------ @@ -457,12 +459,12 @@ heapam_tuple_lock(Relation relation, ItemPointer tid, Snapshot snapshot, XLTW_FetchUpdated); break; case LockWaitSkip: - if (!ConditionalXactLockTableWait(SnapshotDirty.xmax)) + if (!ConditionalXactLockTableWait(SnapshotDirty.xmax, false)) /* skip instead of waiting */ return TM_WouldBlock; break; case LockWaitError: - if (!ConditionalXactLockTableWait(SnapshotDirty.xmax)) + if (!ConditionalXactLockTableWait(SnapshotDirty.xmax, log_lock_failures)) ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on row in relation \"%s\"", @@ -607,14 +609,11 @@ heapam_relation_set_new_filelocator(Relation rel, /* * If required, set up an init fork for an unlogged table so that it can - * be correctly reinitialized on restart. Recovery may remove it while - * replaying, for example, an XLOG_DBASE_CREATE* or XLOG_TBLSPC_CREATE - * record. Therefore, logging is necessary even if wal_level=minimal. + * be correctly reinitialized on restart. */ if (persistence == RELPERSISTENCE_UNLOGGED) { Assert(rel->rd_rel->relkind == RELKIND_RELATION || - rel->rd_rel->relkind == RELKIND_MATVIEW || rel->rd_rel->relkind == RELKIND_TOASTVALUE); smgrcreate(srel, INIT_FORKNUM, false); log_smgrcreate(newrlocator, INIT_FORKNUM); @@ -754,7 +753,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap, tableScan = NULL; heapScan = NULL; - indexScan = index_beginscan(OldHeap, OldIndex, SnapshotAny, 0, 0); + indexScan = index_beginscan(OldHeap, OldIndex, SnapshotAny, NULL, 0, 0); index_rescan(indexScan, NULL, 0, NULL, 0); } else @@ -2052,6 +2051,8 @@ heapam_relation_needs_toast_table(Relation rel) if (att->attisdropped) continue; + if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + continue; data_length = att_align_nominal(data_length, att->attalign); if (att->attlen > 0) { @@ -2118,165 +2119,32 @@ heapam_estimate_rel_size(Relation rel, int32 *attr_widths, * ------------------------------------------------------------------------ */ -static bool -heapam_scan_bitmap_next_block(TableScanDesc scan, - TBMIterateResult *tbmres) -{ - HeapScanDesc hscan = (HeapScanDesc) scan; - BlockNumber block = tbmres->blockno; - Buffer buffer; - Snapshot snapshot; - int ntup; - - hscan->rs_cindex = 0; - hscan->rs_ntuples = 0; - - /* - * We can skip fetching the heap page if we don't need any fields from the - * heap, the bitmap entries don't need rechecking, and all tuples on the - * page are visible to our transaction. - */ - if (!(scan->rs_flags & SO_NEED_TUPLES) && - !tbmres->recheck && - VM_ALL_VISIBLE(scan->rs_rd, tbmres->blockno, &hscan->rs_vmbuffer)) - { - /* can't be lossy in the skip_fetch case */ - Assert(tbmres->ntuples >= 0); - Assert(hscan->rs_empty_tuples_pending >= 0); - - hscan->rs_empty_tuples_pending += tbmres->ntuples; - - return true; - } - - /* - * Ignore any claimed entries past what we think is the end of the - * relation. It may have been extended after the start of our scan (we - * only hold an AccessShareLock, and it could be inserts from this - * backend). We don't take this optimization in SERIALIZABLE isolation - * though, as we need to examine all invisible tuples reachable by the - * index. - */ - if (!IsolationIsSerializable() && block >= hscan->rs_nblocks) - return false; - - /* - * Acquire pin on the target heap page, trading in any pin we held before. - */ - hscan->rs_cbuf = ReleaseAndReadBuffer(hscan->rs_cbuf, - scan->rs_rd, - block); - hscan->rs_cblock = block; - buffer = hscan->rs_cbuf; - snapshot = scan->rs_snapshot; - - ntup = 0; - - /* - * Prune and repair fragmentation for the whole page, if possible. - */ - heap_page_prune_opt(scan->rs_rd, buffer); - - /* - * We must hold share lock on the buffer content while examining tuple - * visibility. Afterwards, however, the tuples we have found to be - * visible are guaranteed good as long as we hold the buffer pin. - */ - LockBuffer(buffer, BUFFER_LOCK_SHARE); - - /* - * We need two separate strategies for lossy and non-lossy cases. - */ - if (tbmres->ntuples >= 0) - { - /* - * Bitmap is non-lossy, so we just look through the offsets listed in - * tbmres; but we have to follow any HOT chain starting at each such - * offset. - */ - int curslot; - - for (curslot = 0; curslot < tbmres->ntuples; curslot++) - { - OffsetNumber offnum = tbmres->offsets[curslot]; - ItemPointerData tid; - HeapTupleData heapTuple; - - ItemPointerSet(&tid, block, offnum); - if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot, - &heapTuple, NULL, true)) - hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid); - } - } - else - { - /* - * Bitmap is lossy, so we must examine each line pointer on the page. - * But we can ignore HOT chains, since we'll check each tuple anyway. - */ - Page page = BufferGetPage(buffer); - OffsetNumber maxoff = PageGetMaxOffsetNumber(page); - OffsetNumber offnum; - - for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum)) - { - ItemId lp; - HeapTupleData loctup; - bool valid; - - lp = PageGetItemId(page, offnum); - if (!ItemIdIsNormal(lp)) - continue; - loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp); - loctup.t_len = ItemIdGetLength(lp); - loctup.t_tableOid = scan->rs_rd->rd_id; - ItemPointerSet(&loctup.t_self, block, offnum); - valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer); - if (valid) - { - hscan->rs_vistuples[ntup++] = offnum; - PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot, - HeapTupleHeaderGetXmin(loctup.t_data)); - } - HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup, - buffer, snapshot); - } - } - - LockBuffer(buffer, BUFFER_LOCK_UNLOCK); - - Assert(ntup <= MaxHeapTuplesPerPage); - hscan->rs_ntuples = ntup; - - return ntup > 0; -} - static bool heapam_scan_bitmap_next_tuple(TableScanDesc scan, - TBMIterateResult *tbmres, - TupleTableSlot *slot) + TupleTableSlot *slot, + bool *recheck, + uint64 *lossy_pages, + uint64 *exact_pages) { - HeapScanDesc hscan = (HeapScanDesc) scan; + BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan; + HeapScanDesc hscan = (HeapScanDesc) bscan; OffsetNumber targoffset; Page page; ItemId lp; - if (hscan->rs_empty_tuples_pending > 0) + /* + * Out of range? If so, nothing more to look at on this page + */ + while (hscan->rs_cindex >= hscan->rs_ntuples) { /* - * If we don't have to fetch the tuple, just return nulls. + * Returns false if the bitmap is exhausted and there are no further + * blocks we need to scan. */ - ExecStoreAllNullTuple(slot); - hscan->rs_empty_tuples_pending--; - return true; + if (!BitmapHeapScanNextBlock(scan, recheck, lossy_pages, exact_pages)) + return false; } - /* - * Out of range? If so, nothing more to look at on this page - */ - if (hscan->rs_cindex < 0 || hscan->rs_cindex >= hscan->rs_ntuples) - return false; - targoffset = hscan->rs_vistuples[hscan->rs_cindex]; page = BufferGetPage(hscan->rs_cbuf); lp = PageGetItemId(page, targoffset); @@ -2524,7 +2392,7 @@ reform_and_rewrite_tuple(HeapTuple tuple, /* Be sure to null out any dropped columns */ for (i = 0; i < newTupDesc->natts; i++) { - if (TupleDescAttr(newTupDesc, i)->attisdropped) + if (TupleDescCompactAttr(newTupDesc, i)->attisdropped) isnull[i] = true; } @@ -2548,6 +2416,9 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer, if (scan->rs_flags & SO_ALLOW_PAGEMODE) { + uint32 start = 0, + end = hscan->rs_ntuples; + /* * In pageatatime mode, heap_prepare_pagescan() already did visibility * checks, so just look at the info it left in rs_vistuples[]. @@ -2557,18 +2428,15 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer, * in increasing order, but it's not clear that there would be enough * gain to justify the restriction. */ - int start = 0, - end = hscan->rs_ntuples - 1; - - while (start <= end) + while (start < end) { - int mid = (start + end) / 2; + uint32 mid = start + (end - start) / 2; OffsetNumber curoffset = hscan->rs_vistuples[mid]; if (tupoffset == curoffset) return true; else if (tupoffset < curoffset) - end = mid - 1; + end = mid; else start = mid + 1; } @@ -2583,6 +2451,162 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer, } } +/* + * Helper function get the next block of a bitmap heap scan. Returns true when + * it got the next block and saved it in the scan descriptor and false when + * the bitmap and or relation are exhausted. + */ +static bool +BitmapHeapScanNextBlock(TableScanDesc scan, + bool *recheck, + uint64 *lossy_pages, uint64 *exact_pages) +{ + BitmapHeapScanDesc bscan = (BitmapHeapScanDesc) scan; + HeapScanDesc hscan = (HeapScanDesc) bscan; + BlockNumber block; + void *per_buffer_data; + Buffer buffer; + Snapshot snapshot; + int ntup; + TBMIterateResult *tbmres; + OffsetNumber offsets[TBM_MAX_TUPLES_PER_PAGE]; + int noffsets = -1; + + Assert(scan->rs_flags & SO_TYPE_BITMAPSCAN); + Assert(hscan->rs_read_stream); + + hscan->rs_cindex = 0; + hscan->rs_ntuples = 0; + + /* Release buffer containing previous block. */ + if (BufferIsValid(hscan->rs_cbuf)) + { + ReleaseBuffer(hscan->rs_cbuf); + hscan->rs_cbuf = InvalidBuffer; + } + + hscan->rs_cbuf = read_stream_next_buffer(hscan->rs_read_stream, + &per_buffer_data); + + if (BufferIsInvalid(hscan->rs_cbuf)) + { + /* the bitmap is exhausted */ + return false; + } + + Assert(per_buffer_data); + + tbmres = per_buffer_data; + + Assert(BlockNumberIsValid(tbmres->blockno)); + Assert(BufferGetBlockNumber(hscan->rs_cbuf) == tbmres->blockno); + + /* Exact pages need their tuple offsets extracted. */ + if (!tbmres->lossy) + noffsets = tbm_extract_page_tuple(tbmres, offsets, + TBM_MAX_TUPLES_PER_PAGE); + + *recheck = tbmres->recheck; + + block = hscan->rs_cblock = tbmres->blockno; + buffer = hscan->rs_cbuf; + snapshot = scan->rs_snapshot; + + ntup = 0; + + /* + * Prune and repair fragmentation for the whole page, if possible. + */ + heap_page_prune_opt(scan->rs_rd, buffer); + + /* + * We must hold share lock on the buffer content while examining tuple + * visibility. Afterwards, however, the tuples we have found to be + * visible are guaranteed good as long as we hold the buffer pin. + */ + LockBuffer(buffer, BUFFER_LOCK_SHARE); + + /* + * We need two separate strategies for lossy and non-lossy cases. + */ + if (!tbmres->lossy) + { + /* + * Bitmap is non-lossy, so we just look through the offsets listed in + * tbmres; but we have to follow any HOT chain starting at each such + * offset. + */ + int curslot; + + /* We must have extracted the tuple offsets by now */ + Assert(noffsets > -1); + + for (curslot = 0; curslot < noffsets; curslot++) + { + OffsetNumber offnum = offsets[curslot]; + ItemPointerData tid; + HeapTupleData heapTuple; + + ItemPointerSet(&tid, block, offnum); + if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot, + &heapTuple, NULL, true)) + hscan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid); + } + } + else + { + /* + * Bitmap is lossy, so we must examine each line pointer on the page. + * But we can ignore HOT chains, since we'll check each tuple anyway. + */ + Page page = BufferGetPage(buffer); + OffsetNumber maxoff = PageGetMaxOffsetNumber(page); + OffsetNumber offnum; + + for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum)) + { + ItemId lp; + HeapTupleData loctup; + bool valid; + + lp = PageGetItemId(page, offnum); + if (!ItemIdIsNormal(lp)) + continue; + loctup.t_data = (HeapTupleHeader) PageGetItem(page, lp); + loctup.t_len = ItemIdGetLength(lp); + loctup.t_tableOid = scan->rs_rd->rd_id; + ItemPointerSet(&loctup.t_self, block, offnum); + valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer); + if (valid) + { + hscan->rs_vistuples[ntup++] = offnum; + PredicateLockTID(scan->rs_rd, &loctup.t_self, snapshot, + HeapTupleHeaderGetXmin(loctup.t_data)); + } + HeapCheckForSerializableConflictOut(valid, scan->rs_rd, &loctup, + buffer, snapshot); + } + } + + LockBuffer(buffer, BUFFER_LOCK_UNLOCK); + + Assert(ntup <= MaxHeapTuplesPerPage); + hscan->rs_ntuples = ntup; + + if (tbmres->lossy) + (*lossy_pages)++; + else + (*exact_pages)++; + + /* + * Return true to indicate that a valid block was found and the bitmap is + * not exhausted. If there are no visible tuples on this page, + * hscan->rs_ntuples will be 0 and heapam_scan_bitmap_next_tuple() will + * return false returning control to this function to advance to the next + * block in the bitmap. + */ + return true; +} /* ------------------------------------------------------------------------ * Definition of the heap table access method. @@ -2642,7 +2666,6 @@ static const TableAmRoutine heapam_methods = { .relation_estimate_size = heapam_estimate_rel_size, - .scan_bitmap_next_block = heapam_scan_bitmap_next_block, .scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple, .scan_sample_next_block = heapam_scan_sample_next_block, .scan_sample_next_tuple = heapam_scan_sample_next_tuple diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c index 9243feed01f9b..05f6946fe60d2 100644 --- a/src/backend/access/heap/heapam_visibility.c +++ b/src/backend/access/heap/heapam_visibility.c @@ -55,7 +55,7 @@ * HeapTupleSatisfiesAny() * all tuples are visible * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -962,6 +962,15 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, { HeapTupleHeader tuple = htup->t_data; + /* + * Assert that the caller has registered the snapshot. This function + * doesn't care about the registration as such, but in general you + * shouldn't try to use a snapshot without registration because it might + * get invalidated while it's still in use, and this is a convenient place + * to check for that. + */ + Assert(snapshot->regd_count > 0 || snapshot->active_count > 0); + Assert(ItemPointerIsValid(&htup->t_self)); Assert(htup->t_tableOid != InvalidOid); diff --git a/src/backend/access/heap/heapam_xlog.c b/src/backend/access/heap/heapam_xlog.c new file mode 100644 index 0000000000000..30f4c2d3c6719 --- /dev/null +++ b/src/backend/access/heap/heapam_xlog.c @@ -0,0 +1,1345 @@ +/*------------------------------------------------------------------------- + * + * heapam_xlog.c + * WAL replay logic for heap access method. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/access/heap/heapam_xlog.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/bufmask.h" +#include "access/heapam.h" +#include "access/visibilitymap.h" +#include "access/xlog.h" +#include "access/xlogutils.h" +#include "storage/freespace.h" +#include "storage/standby.h" + + +/* + * Replay XLOG_HEAP2_PRUNE_* records. + */ +static void +heap_xlog_prune_freeze(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + char *maindataptr = XLogRecGetData(record); + xl_heap_prune xlrec; + Buffer buffer; + RelFileLocator rlocator; + BlockNumber blkno; + XLogRedoAction action; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); + memcpy(&xlrec, maindataptr, SizeOfHeapPrune); + maindataptr += SizeOfHeapPrune; + + /* + * We will take an ordinary exclusive lock or a cleanup lock depending on + * whether the XLHP_CLEANUP_LOCK flag is set. With an ordinary exclusive + * lock, we better not be doing anything that requires moving existing + * tuple data. + */ + Assert((xlrec.flags & XLHP_CLEANUP_LOCK) != 0 || + (xlrec.flags & (XLHP_HAS_REDIRECTIONS | XLHP_HAS_DEAD_ITEMS)) == 0); + + /* + * We are about to remove and/or freeze tuples. In Hot Standby mode, + * ensure that there are no queries running for which the removed tuples + * are still visible or which still consider the frozen xids as running. + * The conflict horizon XID comes after xl_heap_prune. + */ + if ((xlrec.flags & XLHP_HAS_CONFLICT_HORIZON) != 0) + { + TransactionId snapshot_conflict_horizon; + + /* memcpy() because snapshot_conflict_horizon is stored unaligned */ + memcpy(&snapshot_conflict_horizon, maindataptr, sizeof(TransactionId)); + maindataptr += sizeof(TransactionId); + + if (InHotStandby) + ResolveRecoveryConflictWithSnapshot(snapshot_conflict_horizon, + (xlrec.flags & XLHP_IS_CATALOG_REL) != 0, + rlocator); + } + + /* + * If we have a full-page image, restore it and we're done. + */ + action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, + (xlrec.flags & XLHP_CLEANUP_LOCK) != 0, + &buffer); + if (action == BLK_NEEDS_REDO) + { + Page page = (Page) BufferGetPage(buffer); + OffsetNumber *redirected; + OffsetNumber *nowdead; + OffsetNumber *nowunused; + int nredirected; + int ndead; + int nunused; + int nplans; + Size datalen; + xlhp_freeze_plan *plans; + OffsetNumber *frz_offsets; + char *dataptr = XLogRecGetBlockData(record, 0, &datalen); + + heap_xlog_deserialize_prune_and_freeze(dataptr, xlrec.flags, + &nplans, &plans, &frz_offsets, + &nredirected, &redirected, + &ndead, &nowdead, + &nunused, &nowunused); + + /* + * Update all line pointers per the record, and repair fragmentation + * if needed. + */ + if (nredirected > 0 || ndead > 0 || nunused > 0) + heap_page_prune_execute(buffer, + (xlrec.flags & XLHP_CLEANUP_LOCK) == 0, + redirected, nredirected, + nowdead, ndead, + nowunused, nunused); + + /* Freeze tuples */ + for (int p = 0; p < nplans; p++) + { + HeapTupleFreeze frz; + + /* + * Convert freeze plan representation from WAL record into + * per-tuple format used by heap_execute_freeze_tuple + */ + frz.xmax = plans[p].xmax; + frz.t_infomask2 = plans[p].t_infomask2; + frz.t_infomask = plans[p].t_infomask; + frz.frzflags = plans[p].frzflags; + frz.offset = InvalidOffsetNumber; /* unused, but be tidy */ + + for (int i = 0; i < plans[p].ntuples; i++) + { + OffsetNumber offset = *(frz_offsets++); + ItemId lp; + HeapTupleHeader tuple; + + lp = PageGetItemId(page, offset); + tuple = (HeapTupleHeader) PageGetItem(page, lp); + heap_execute_freeze_tuple(tuple, &frz); + } + } + + /* There should be no more data */ + Assert((char *) frz_offsets == dataptr + datalen); + + /* + * Note: we don't worry about updating the page's prunability hints. + * At worst this will cause an extra prune cycle to occur soon. + */ + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + + /* + * If we released any space or line pointers, update the free space map. + * + * Do this regardless of a full-page image being applied, since the FSM + * data is not in the page anyway. + */ + if (BufferIsValid(buffer)) + { + if (xlrec.flags & (XLHP_HAS_REDIRECTIONS | + XLHP_HAS_DEAD_ITEMS | + XLHP_HAS_NOW_UNUSED_ITEMS)) + { + Size freespace = PageGetHeapFreeSpace(BufferGetPage(buffer)); + + UnlockReleaseBuffer(buffer); + + XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); + } + else + UnlockReleaseBuffer(buffer); + } +} + +/* + * Replay XLOG_HEAP2_VISIBLE records. + * + * The critical integrity requirement here is that we must never end up with + * a situation where the visibility map bit is set, and the page-level + * PD_ALL_VISIBLE bit is clear. If that were to occur, then a subsequent + * page modification would fail to clear the visibility map bit. + */ +static void +heap_xlog_visible(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_visible *xlrec = (xl_heap_visible *) XLogRecGetData(record); + Buffer vmbuffer = InvalidBuffer; + Buffer buffer; + Page page; + RelFileLocator rlocator; + BlockNumber blkno; + XLogRedoAction action; + + Assert((xlrec->flags & VISIBILITYMAP_XLOG_VALID_BITS) == xlrec->flags); + + XLogRecGetBlockTag(record, 1, &rlocator, NULL, &blkno); + + /* + * If there are any Hot Standby transactions running that have an xmin + * horizon old enough that this page isn't all-visible for them, they + * might incorrectly decide that an index-only scan can skip a heap fetch. + * + * NB: It might be better to throw some kind of "soft" conflict here that + * forces any index-only scan that is in flight to perform heap fetches, + * rather than killing the transaction outright. + */ + if (InHotStandby) + ResolveRecoveryConflictWithSnapshot(xlrec->snapshotConflictHorizon, + xlrec->flags & VISIBILITYMAP_XLOG_CATALOG_REL, + rlocator); + + /* + * Read the heap page, if it still exists. If the heap file has dropped or + * truncated later in recovery, we don't need to update the page, but we'd + * better still update the visibility map. + */ + action = XLogReadBufferForRedo(record, 1, &buffer); + if (action == BLK_NEEDS_REDO) + { + /* + * We don't bump the LSN of the heap page when setting the visibility + * map bit (unless checksums or wal_hint_bits is enabled, in which + * case we must). This exposes us to torn page hazards, but since + * we're not inspecting the existing page contents in any way, we + * don't care. + */ + page = BufferGetPage(buffer); + + PageSetAllVisible(page); + + if (XLogHintBitIsNeeded()) + PageSetLSN(page, lsn); + + MarkBufferDirty(buffer); + } + else if (action == BLK_RESTORED) + { + /* + * If heap block was backed up, we already restored it and there's + * nothing more to do. (This can only happen with checksums or + * wal_log_hints enabled.) + */ + } + + if (BufferIsValid(buffer)) + { + Size space = PageGetFreeSpace(BufferGetPage(buffer)); + + UnlockReleaseBuffer(buffer); + + /* + * Since FSM is not WAL-logged and only updated heuristically, it + * easily becomes stale in standbys. If the standby is later promoted + * and runs VACUUM, it will skip updating individual free space + * figures for pages that became all-visible (or all-frozen, depending + * on the vacuum mode,) which is troublesome when FreeSpaceMapVacuum + * propagates too optimistic free space values to upper FSM layers; + * later inserters try to use such pages only to find out that they + * are unusable. This can cause long stalls when there are many such + * pages. + * + * Forestall those problems by updating FSM's idea about a page that + * is becoming all-visible or all-frozen. + * + * Do this regardless of a full-page image being applied, since the + * FSM data is not in the page anyway. + */ + if (xlrec->flags & VISIBILITYMAP_VALID_BITS) + XLogRecordPageWithFreeSpace(rlocator, blkno, space); + } + + /* + * Even if we skipped the heap page update due to the LSN interlock, it's + * still safe to update the visibility map. Any WAL record that clears + * the visibility map bit does so before checking the page LSN, so any + * bits that need to be cleared will still be cleared. + */ + if (XLogReadBufferForRedoExtended(record, 0, RBM_ZERO_ON_ERROR, false, + &vmbuffer) == BLK_NEEDS_REDO) + { + Page vmpage = BufferGetPage(vmbuffer); + Relation reln; + uint8 vmbits; + + /* initialize the page if it was read as zeros */ + if (PageIsNew(vmpage)) + PageInit(vmpage, BLCKSZ, 0); + + /* remove VISIBILITYMAP_XLOG_* */ + vmbits = xlrec->flags & VISIBILITYMAP_VALID_BITS; + + /* + * XLogReadBufferForRedoExtended locked the buffer. But + * visibilitymap_set will handle locking itself. + */ + LockBuffer(vmbuffer, BUFFER_LOCK_UNLOCK); + + reln = CreateFakeRelcacheEntry(rlocator); + visibilitymap_pin(reln, blkno, &vmbuffer); + + visibilitymap_set(reln, blkno, InvalidBuffer, lsn, vmbuffer, + xlrec->snapshotConflictHorizon, vmbits); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + else if (BufferIsValid(vmbuffer)) + UnlockReleaseBuffer(vmbuffer); +} + +/* + * Given an "infobits" field from an XLog record, set the correct bits in the + * given infomask and infomask2 for the tuple touched by the record. + * + * (This is the reverse of compute_infobits). + */ +static void +fix_infomask_from_infobits(uint8 infobits, uint16 *infomask, uint16 *infomask2) +{ + *infomask &= ~(HEAP_XMAX_IS_MULTI | HEAP_XMAX_LOCK_ONLY | + HEAP_XMAX_KEYSHR_LOCK | HEAP_XMAX_EXCL_LOCK); + *infomask2 &= ~HEAP_KEYS_UPDATED; + + if (infobits & XLHL_XMAX_IS_MULTI) + *infomask |= HEAP_XMAX_IS_MULTI; + if (infobits & XLHL_XMAX_LOCK_ONLY) + *infomask |= HEAP_XMAX_LOCK_ONLY; + if (infobits & XLHL_XMAX_EXCL_LOCK) + *infomask |= HEAP_XMAX_EXCL_LOCK; + /* note HEAP_XMAX_SHR_LOCK isn't considered here */ + if (infobits & XLHL_XMAX_KEYSHR_LOCK) + *infomask |= HEAP_XMAX_KEYSHR_LOCK; + + if (infobits & XLHL_KEYS_UPDATED) + *infomask2 |= HEAP_KEYS_UPDATED; +} + +/* + * Replay XLOG_HEAP_DELETE records. + */ +static void +heap_xlog_delete(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); + Buffer buffer; + Page page; + ItemId lp = NULL; + HeapTupleHeader htup; + BlockNumber blkno; + RelFileLocator target_locator; + ItemPointerData target_tid; + + XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); + ItemPointerSetBlockNumber(&target_tid, blkno); + ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(target_locator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + if (PageGetMaxOffsetNumber(page) >= xlrec->offnum) + lp = PageGetItemId(page, xlrec->offnum); + + if (PageGetMaxOffsetNumber(page) < xlrec->offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + HeapTupleHeaderClearHotUpdated(htup); + fix_infomask_from_infobits(xlrec->infobits_set, + &htup->t_infomask, &htup->t_infomask2); + if (!(xlrec->flags & XLH_DELETE_IS_SUPER)) + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + else + HeapTupleHeaderSetXmin(htup, InvalidTransactionId); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + + /* Mark the page as a candidate for pruning */ + PageSetPrunable(page, XLogRecGetXid(record)); + + if (xlrec->flags & XLH_DELETE_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* Make sure t_ctid is set correctly */ + if (xlrec->flags & XLH_DELETE_IS_PARTITION_MOVE) + HeapTupleHeaderSetMovedPartitions(htup); + else + htup->t_ctid = target_tid; + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +/* + * Replay XLOG_HEAP_INSERT records. + */ +static void +heap_xlog_insert(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record); + Buffer buffer; + Page page; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + HeapTupleHeader htup; + xl_heap_header xlhdr; + uint32 newlen; + Size freespace = 0; + RelFileLocator target_locator; + BlockNumber blkno; + ItemPointerData target_tid; + XLogRedoAction action; + + XLogRecGetBlockTag(record, 0, &target_locator, NULL, &blkno); + ItemPointerSetBlockNumber(&target_tid, blkno); + ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(target_locator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* + * If we inserted the first and only tuple on the page, re-initialize the + * page from scratch. + */ + if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) + { + buffer = XLogInitBufferForRedo(record, 0); + page = BufferGetPage(buffer); + PageInit(page, BufferGetPageSize(buffer), 0); + action = BLK_NEEDS_REDO; + } + else + action = XLogReadBufferForRedo(record, 0, &buffer); + if (action == BLK_NEEDS_REDO) + { + Size datalen; + char *data; + + page = BufferGetPage(buffer); + + if (PageGetMaxOffsetNumber(page) + 1 < xlrec->offnum) + elog(PANIC, "invalid max offset number"); + + data = XLogRecGetBlockData(record, 0, &datalen); + + newlen = datalen - SizeOfHeapHeader; + Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); + memcpy(&xlhdr, data, SizeOfHeapHeader); + data += SizeOfHeapHeader; + + htup = &tbuf.hdr; + MemSet(htup, 0, SizeofHeapTupleHeader); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ + memcpy((char *) htup + SizeofHeapTupleHeader, + data, + newlen); + newlen += SizeofHeapTupleHeader; + htup->t_infomask2 = xlhdr.t_infomask2; + htup->t_infomask = xlhdr.t_infomask; + htup->t_hoff = xlhdr.t_hoff; + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + htup->t_ctid = target_tid; + + if (PageAddItem(page, (Item) htup, newlen, xlrec->offnum, + true, true) == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ + if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) + PageSetAllVisible(page); + + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); + + /* + * If the page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(target_locator, blkno, freespace); +} + +/* + * Replay XLOG_HEAP2_MULTI_INSERT records. + */ +static void +heap_xlog_multi_insert(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_multi_insert *xlrec; + RelFileLocator rlocator; + BlockNumber blkno; + Buffer buffer; + Page page; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + HeapTupleHeader htup; + uint32 newlen; + Size freespace = 0; + int i; + bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0; + XLogRedoAction action; + + /* + * Insertion doesn't overwrite MVCC data, so no conflict processing is + * required. + */ + xlrec = (xl_heap_multi_insert *) XLogRecGetData(record); + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &blkno); + + /* check that the mutually exclusive flags are not both set */ + Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) && + (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET))); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, blkno, &vmbuffer); + visibilitymap_clear(reln, blkno, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (isinit) + { + buffer = XLogInitBufferForRedo(record, 0); + page = BufferGetPage(buffer); + PageInit(page, BufferGetPageSize(buffer), 0); + action = BLK_NEEDS_REDO; + } + else + action = XLogReadBufferForRedo(record, 0, &buffer); + if (action == BLK_NEEDS_REDO) + { + char *tupdata; + char *endptr; + Size len; + + /* Tuples are stored as block data */ + tupdata = XLogRecGetBlockData(record, 0, &len); + endptr = tupdata + len; + + page = (Page) BufferGetPage(buffer); + + for (i = 0; i < xlrec->ntuples; i++) + { + OffsetNumber offnum; + xl_multi_insert_tuple *xlhdr; + + /* + * If we're reinitializing the page, the tuples are stored in + * order from FirstOffsetNumber. Otherwise there's an array of + * offsets in the WAL record, and the tuples come after that. + */ + if (isinit) + offnum = FirstOffsetNumber + i; + else + offnum = xlrec->offsets[i]; + if (PageGetMaxOffsetNumber(page) + 1 < offnum) + elog(PANIC, "invalid max offset number"); + + xlhdr = (xl_multi_insert_tuple *) SHORTALIGN(tupdata); + tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; + + newlen = xlhdr->datalen; + Assert(newlen <= MaxHeapTupleSize); + htup = &tbuf.hdr; + MemSet(htup, 0, SizeofHeapTupleHeader); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ + memcpy((char *) htup + SizeofHeapTupleHeader, + tupdata, + newlen); + tupdata += newlen; + + newlen += SizeofHeapTupleHeader; + htup->t_infomask2 = xlhdr->t_infomask2; + htup->t_infomask = xlhdr->t_infomask; + htup->t_hoff = xlhdr->t_hoff; + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + ItemPointerSetBlockNumber(&htup->t_ctid, blkno); + ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); + + offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); + if (offnum == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + } + if (tupdata != endptr) + elog(PANIC, "total tuple length mismatch"); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + + if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + /* XLH_INSERT_ALL_FROZEN_SET implies that all tuples are visible */ + if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) + PageSetAllVisible(page); + + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); + + /* + * If the page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(rlocator, blkno, freespace); +} + +/* + * Replay XLOG_HEAP_UPDATE and XLOG_HEAP_HOT_UPDATE records. + */ +static void +heap_xlog_update(XLogReaderState *record, bool hot_update) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record); + RelFileLocator rlocator; + BlockNumber oldblk; + BlockNumber newblk; + ItemPointerData newtid; + Buffer obuffer, + nbuffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleData oldtup; + HeapTupleHeader htup; + uint16 prefixlen = 0, + suffixlen = 0; + char *newp; + union + { + HeapTupleHeaderData hdr; + char data[MaxHeapTupleSize]; + } tbuf; + xl_heap_header xlhdr; + uint32 newlen; + Size freespace = 0; + XLogRedoAction oldaction; + XLogRedoAction newaction; + + /* initialize to keep the compiler quiet */ + oldtup.t_data = NULL; + oldtup.t_len = 0; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &newblk); + if (XLogRecGetBlockTagExtended(record, 1, NULL, NULL, &oldblk, NULL)) + { + /* HOT updates are never done across pages */ + Assert(!hot_update); + } + else + oldblk = newblk; + + ItemPointerSet(&newtid, newblk, xlrec->new_offnum); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, oldblk, &vmbuffer); + visibilitymap_clear(reln, oldblk, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* + * In normal operation, it is important to lock the two pages in + * page-number order, to avoid possible deadlocks against other update + * operations going the other way. However, during WAL replay there can + * be no other update happening, so we don't need to worry about that. But + * we *do* need to worry that we don't expose an inconsistent state to Hot + * Standby queries --- so the original page can't be unlocked before we've + * added the new tuple to the new page. + */ + + /* Deal with old tuple version */ + oldaction = XLogReadBufferForRedo(record, (oldblk == newblk) ? 0 : 1, + &obuffer); + if (oldaction == BLK_NEEDS_REDO) + { + page = BufferGetPage(obuffer); + offnum = xlrec->old_offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + oldtup.t_data = htup; + oldtup.t_len = ItemIdGetLength(lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + if (hot_update) + HeapTupleHeaderSetHotUpdated(htup); + else + HeapTupleHeaderClearHotUpdated(htup); + fix_infomask_from_infobits(xlrec->old_infobits_set, &htup->t_infomask, + &htup->t_infomask2); + HeapTupleHeaderSetXmax(htup, xlrec->old_xmax); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + /* Set forward chain link in t_ctid */ + htup->t_ctid = newtid; + + /* Mark the page as a candidate for pruning */ + PageSetPrunable(page, XLogRecGetXid(record)); + + if (xlrec->flags & XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + PageSetLSN(page, lsn); + MarkBufferDirty(obuffer); + } + + /* + * Read the page the new tuple goes into, if different from old. + */ + if (oldblk == newblk) + { + nbuffer = obuffer; + newaction = oldaction; + } + else if (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) + { + nbuffer = XLogInitBufferForRedo(record, 0); + page = (Page) BufferGetPage(nbuffer); + PageInit(page, BufferGetPageSize(nbuffer), 0); + newaction = BLK_NEEDS_REDO; + } + else + newaction = XLogReadBufferForRedo(record, 0, &nbuffer); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) + { + Relation reln = CreateFakeRelcacheEntry(rlocator); + Buffer vmbuffer = InvalidBuffer; + + visibilitymap_pin(reln, newblk, &vmbuffer); + visibilitymap_clear(reln, newblk, vmbuffer, VISIBILITYMAP_VALID_BITS); + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + /* Deal with new tuple */ + if (newaction == BLK_NEEDS_REDO) + { + char *recdata; + char *recdata_end; + Size datalen; + Size tuplen; + + recdata = XLogRecGetBlockData(record, 0, &datalen); + recdata_end = recdata + datalen; + + page = BufferGetPage(nbuffer); + + offnum = xlrec->new_offnum; + if (PageGetMaxOffsetNumber(page) + 1 < offnum) + elog(PANIC, "invalid max offset number"); + + if (xlrec->flags & XLH_UPDATE_PREFIX_FROM_OLD) + { + Assert(newblk == oldblk); + memcpy(&prefixlen, recdata, sizeof(uint16)); + recdata += sizeof(uint16); + } + if (xlrec->flags & XLH_UPDATE_SUFFIX_FROM_OLD) + { + Assert(newblk == oldblk); + memcpy(&suffixlen, recdata, sizeof(uint16)); + recdata += sizeof(uint16); + } + + memcpy(&xlhdr, recdata, SizeOfHeapHeader); + recdata += SizeOfHeapHeader; + + tuplen = recdata_end - recdata; + Assert(tuplen <= MaxHeapTupleSize); + + htup = &tbuf.hdr; + MemSet(htup, 0, SizeofHeapTupleHeader); + + /* + * Reconstruct the new tuple using the prefix and/or suffix from the + * old tuple, and the data stored in the WAL record. + */ + newp = (char *) htup + SizeofHeapTupleHeader; + if (prefixlen > 0) + { + int len; + + /* copy bitmap [+ padding] [+ oid] from WAL record */ + len = xlhdr.t_hoff - SizeofHeapTupleHeader; + memcpy(newp, recdata, len); + recdata += len; + newp += len; + + /* copy prefix from old tuple */ + memcpy(newp, (char *) oldtup.t_data + oldtup.t_data->t_hoff, prefixlen); + newp += prefixlen; + + /* copy new tuple data from WAL record */ + len = tuplen - (xlhdr.t_hoff - SizeofHeapTupleHeader); + memcpy(newp, recdata, len); + recdata += len; + newp += len; + } + else + { + /* + * copy bitmap [+ padding] [+ oid] + data from record, all in one + * go + */ + memcpy(newp, recdata, tuplen); + recdata += tuplen; + newp += tuplen; + } + Assert(recdata == recdata_end); + + /* copy suffix from old tuple */ + if (suffixlen > 0) + memcpy(newp, (char *) oldtup.t_data + oldtup.t_len - suffixlen, suffixlen); + + newlen = SizeofHeapTupleHeader + tuplen + prefixlen + suffixlen; + htup->t_infomask2 = xlhdr.t_infomask2; + htup->t_infomask = xlhdr.t_infomask; + htup->t_hoff = xlhdr.t_hoff; + + HeapTupleHeaderSetXmin(htup, XLogRecGetXid(record)); + HeapTupleHeaderSetCmin(htup, FirstCommandId); + HeapTupleHeaderSetXmax(htup, xlrec->new_xmax); + /* Make sure there is no forward chain link in t_ctid */ + htup->t_ctid = newtid; + + offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true); + if (offnum == InvalidOffsetNumber) + elog(PANIC, "failed to add tuple"); + + if (xlrec->flags & XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED) + PageClearAllVisible(page); + + freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ + + PageSetLSN(page, lsn); + MarkBufferDirty(nbuffer); + } + + if (BufferIsValid(nbuffer) && nbuffer != obuffer) + UnlockReleaseBuffer(nbuffer); + if (BufferIsValid(obuffer)) + UnlockReleaseBuffer(obuffer); + + /* + * If the new page is running low on free space, update the FSM as well. + * Arbitrarily, our definition of "low" is less than 20%. We can't do much + * better than that without knowing the fill-factor for the table. + * + * However, don't update the FSM on HOT updates, because after crash + * recovery, either the old or the new tuple will certainly be dead and + * prunable. After pruning, the page will have roughly as much free space + * as it did before the update, assuming the new tuple is about the same + * size as the old one. + * + * XXX: Don't do this if the page was restored from full page image. We + * don't bother to update the FSM in that case, it doesn't need to be + * totally accurate anyway. + */ + if (newaction == BLK_NEEDS_REDO && !hot_update && freespace < BLCKSZ / 5) + XLogRecordPageWithFreeSpace(rlocator, newblk, freespace); +} + +/* + * Replay XLOG_HEAP_CONFIRM records. + */ +static void +heap_xlog_confirm(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_confirm *xlrec = (xl_heap_confirm *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + /* + * Confirm tuple as actually inserted + */ + ItemPointerSet(&htup->t_ctid, BufferGetBlockNumber(buffer), offnum); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +/* + * Replay XLOG_HEAP_LOCK records. + */ +static void +heap_xlog_lock(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_lock *xlrec = (xl_heap_lock *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileLocator rlocator; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); + reln = CreateFakeRelcacheEntry(rlocator); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = (Page) BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, + &htup->t_infomask2); + + /* + * Clear relevant update flags, but only if the modified infomask says + * there's no update. + */ + if (HEAP_XMAX_IS_LOCKED_ONLY(htup->t_infomask)) + { + HeapTupleHeaderClearHotUpdated(htup); + /* Make sure there is no forward chain link in t_ctid */ + ItemPointerSet(&htup->t_ctid, + BufferGetBlockNumber(buffer), + offnum); + } + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + HeapTupleHeaderSetCmax(htup, FirstCommandId, false); + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +/* + * Replay XLOG_HEAP2_LOCK_UPDATED records. + */ +static void +heap_xlog_lock_updated(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_lock_updated *xlrec; + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + + xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); + + /* + * The visibility map may need to be fixed even if the heap page is + * already up-to-date. + */ + if (xlrec->flags & XLH_LOCK_ALL_FROZEN_CLEARED) + { + RelFileLocator rlocator; + Buffer vmbuffer = InvalidBuffer; + BlockNumber block; + Relation reln; + + XLogRecGetBlockTag(record, 0, &rlocator, NULL, &block); + reln = CreateFakeRelcacheEntry(rlocator); + + visibilitymap_pin(reln, block, &vmbuffer); + visibilitymap_clear(reln, block, vmbuffer, VISIBILITYMAP_ALL_FROZEN); + + ReleaseBuffer(vmbuffer); + FreeFakeRelcacheEntry(reln); + } + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + htup->t_infomask &= ~(HEAP_XMAX_BITS | HEAP_MOVED); + htup->t_infomask2 &= ~HEAP_KEYS_UPDATED; + fix_infomask_from_infobits(xlrec->infobits_set, &htup->t_infomask, + &htup->t_infomask2); + HeapTupleHeaderSetXmax(htup, xlrec->xmax); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); +} + +/* + * Replay XLOG_HEAP_INPLACE records. + */ +static void +heap_xlog_inplace(XLogReaderState *record) +{ + XLogRecPtr lsn = record->EndRecPtr; + xl_heap_inplace *xlrec = (xl_heap_inplace *) XLogRecGetData(record); + Buffer buffer; + Page page; + OffsetNumber offnum; + ItemId lp = NULL; + HeapTupleHeader htup; + uint32 oldlen; + Size newlen; + + if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) + { + char *newtup = XLogRecGetBlockData(record, 0, &newlen); + + page = BufferGetPage(buffer); + + offnum = xlrec->offnum; + if (PageGetMaxOffsetNumber(page) >= offnum) + lp = PageGetItemId(page, offnum); + + if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp)) + elog(PANIC, "invalid lp"); + + htup = (HeapTupleHeader) PageGetItem(page, lp); + + oldlen = ItemIdGetLength(lp) - htup->t_hoff; + if (oldlen != newlen) + elog(PANIC, "wrong tuple length"); + + memcpy((char *) htup + htup->t_hoff, newtup, newlen); + + PageSetLSN(page, lsn); + MarkBufferDirty(buffer); + } + if (BufferIsValid(buffer)) + UnlockReleaseBuffer(buffer); + + ProcessCommittedInvalidationMessages(xlrec->msgs, + xlrec->nmsgs, + xlrec->relcacheInitFileInval, + xlrec->dbId, + xlrec->tsId); +} + +void +heap_redo(XLogReaderState *record) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + + /* + * These operations don't overwrite MVCC data so no conflict processing is + * required. The ones in heap2 rmgr do. + */ + + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP_INSERT: + heap_xlog_insert(record); + break; + case XLOG_HEAP_DELETE: + heap_xlog_delete(record); + break; + case XLOG_HEAP_UPDATE: + heap_xlog_update(record, false); + break; + case XLOG_HEAP_TRUNCATE: + + /* + * TRUNCATE is a no-op because the actions are already logged as + * SMGR WAL records. TRUNCATE WAL record only exists for logical + * decoding. + */ + break; + case XLOG_HEAP_HOT_UPDATE: + heap_xlog_update(record, true); + break; + case XLOG_HEAP_CONFIRM: + heap_xlog_confirm(record); + break; + case XLOG_HEAP_LOCK: + heap_xlog_lock(record); + break; + case XLOG_HEAP_INPLACE: + heap_xlog_inplace(record); + break; + default: + elog(PANIC, "heap_redo: unknown op code %u", info); + } +} + +void +heap2_redo(XLogReaderState *record) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + + switch (info & XLOG_HEAP_OPMASK) + { + case XLOG_HEAP2_PRUNE_ON_ACCESS: + case XLOG_HEAP2_PRUNE_VACUUM_SCAN: + case XLOG_HEAP2_PRUNE_VACUUM_CLEANUP: + heap_xlog_prune_freeze(record); + break; + case XLOG_HEAP2_VISIBLE: + heap_xlog_visible(record); + break; + case XLOG_HEAP2_MULTI_INSERT: + heap_xlog_multi_insert(record); + break; + case XLOG_HEAP2_LOCK_UPDATED: + heap_xlog_lock_updated(record); + break; + case XLOG_HEAP2_NEW_CID: + + /* + * Nothing to do on a real replay, only used during logical + * decoding. + */ + break; + case XLOG_HEAP2_REWRITE: + heap_xlog_logical_rewrite(record); + break; + default: + elog(PANIC, "heap2_redo: unknown op code %u", info); + } +} + +/* + * Mask a heap page before performing consistency checks on it. + */ +void +heap_mask(char *pagedata, BlockNumber blkno) +{ + Page page = (Page) pagedata; + OffsetNumber off; + + mask_page_lsn_and_checksum(page); + + mask_page_hint_bits(page); + mask_unused_space(page); + + for (off = 1; off <= PageGetMaxOffsetNumber(page); off++) + { + ItemId iid = PageGetItemId(page, off); + char *page_item; + + page_item = (char *) (page + ItemIdGetOffset(iid)); + + if (ItemIdIsNormal(iid)) + { + HeapTupleHeader page_htup = (HeapTupleHeader) page_item; + + /* + * If xmin of a tuple is not yet frozen, we should ignore + * differences in hint bits, since they can be set without + * emitting WAL. + */ + if (!HeapTupleHeaderXminFrozen(page_htup)) + page_htup->t_infomask &= ~HEAP_XACT_MASK; + else + { + /* Still we need to mask xmax hint bits. */ + page_htup->t_infomask &= ~HEAP_XMAX_INVALID; + page_htup->t_infomask &= ~HEAP_XMAX_COMMITTED; + } + + /* + * During replay, we set Command Id to FirstCommandId. Hence, mask + * it. See heap_xlog_insert() for details. + */ + page_htup->t_choice.t_heap.t_field3.t_cid = MASK_MARKER; + + /* + * For a speculative tuple, heap_insert() does not set ctid in the + * caller-passed heap tuple itself, leaving the ctid field to + * contain a speculative token value - a per-backend monotonically + * increasing identifier. Besides, it does not WAL-log ctid under + * any circumstances. + * + * During redo, heap_xlog_insert() sets t_ctid to current block + * number and self offset number. It doesn't care about any + * speculative insertions on the primary. Hence, we set t_ctid to + * current block number and self offset number to ignore any + * inconsistency. + */ + if (HeapTupleHeaderIsSpeculative(page_htup)) + ItemPointerSet(&page_htup->t_ctid, blkno, off); + + /* + * NB: Not ignoring ctid changes due to the tuple having moved + * (i.e. HeapTupleHeaderIndicatesMovedPartitions), because that's + * important information that needs to be in-sync between primary + * and standby, and thus is WAL logged. + */ + } + + /* + * Ignore any padding bytes after the tuple, when the length of the + * item is not MAXALIGNed. + */ + if (ItemIdHasStorage(iid)) + { + int len = ItemIdGetLength(iid); + int padlen = MAXALIGN(len) - len; + + if (padlen > 0) + memset(page_item + len, MASK_MARKER, padlen); + } + } +} diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c index a420e1653046c..cb1e57030f64c 100644 --- a/src/backend/access/heap/heaptoast.c +++ b/src/backend/access/heap/heaptoast.c @@ -4,7 +4,7 @@ * Heap-specific definitions for external and compressed storage * of variable size attributes. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -369,7 +369,7 @@ toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc) /* * Look at non-null varlena attributes */ - if (!toast_isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1) + if (!toast_isnull[i] && TupleDescCompactAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; @@ -483,7 +483,7 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup, */ if (toast_isnull[i]) has_nulls = true; - else if (TupleDescAttr(tupleDesc, i)->attlen == -1) + else if (TupleDescCompactAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; @@ -584,7 +584,7 @@ toast_build_flattened_tuple(TupleDesc tupleDesc, /* * Look at non-null varlena attributes */ - if (!isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1) + if (!isnull[i] && TupleDescCompactAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; @@ -639,7 +639,6 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, int endchunk; int num_indexes; int validIndex; - SnapshotData SnapshotToast; /* Look for the valid index of toast relation */ validIndex = toast_open_indexes(toastrel, @@ -685,9 +684,8 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, } /* Prepare for scan */ - init_toast_snapshot(&SnapshotToast); toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex], - &SnapshotToast, nscankeys, toastkey); + get_toast_snapshot(), nscankeys, toastkey); /* * Read the chunks by index diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index 7c662cdf46ecf..c482c9d61b265 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -3,7 +3,7 @@ * hio.c * POSTGRES heap access method input/output code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/heap/meson.build b/src/backend/access/heap/meson.build index e00d5b4f0de2d..2637b24112fba 100644 --- a/src/backend/access/heap/meson.build +++ b/src/backend/access/heap/meson.build @@ -1,9 +1,10 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'heapam.c', 'heapam_handler.c', 'heapam_visibility.c', + 'heapam_xlog.c', 'heaptoast.c', 'hio.c', 'pruneheap.c', diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 869d82ad66724..a8025889be088 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -3,7 +3,7 @@ * pruneheap.c * heap page pruning and HOT-chain management code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -1906,7 +1906,7 @@ heap_log_freeze_eq(xlhp_freeze_plan *plan, HeapTupleFreeze *frz) } /* - * Comparator used to deduplicate XLOG_HEAP2_FREEZE_PAGE freeze plans + * Comparator used to deduplicate the freeze plans used in WAL records. */ static int heap_log_freeze_cmp(const void *arg1, const void *arg2) @@ -1966,7 +1966,7 @@ heap_log_freeze_new_plan(xlhp_freeze_plan *plan, HeapTupleFreeze *frz) /* * Deduplicate tuple-based freeze plans so that each distinct set of - * processing steps is only stored once in XLOG_HEAP2_FREEZE_PAGE records. + * processing steps is only stored once in the WAL record. * Called during original execution of freezing (for logged relations). * * Return value is number of plans set in *plans_out for caller. Also writes @@ -2093,9 +2093,9 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer, nplans = heap_log_freeze_plan(frozen, nfrozen, plans, frz_offsets); freeze_plans.nplans = nplans; - XLogRegisterBufData(0, (char *) &freeze_plans, + XLogRegisterBufData(0, &freeze_plans, offsetof(xlhp_freeze_plans, plans)); - XLogRegisterBufData(0, (char *) plans, + XLogRegisterBufData(0, plans, sizeof(xlhp_freeze_plan) * nplans); } if (nredirected > 0) @@ -2103,9 +2103,9 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer, xlrec.flags |= XLHP_HAS_REDIRECTIONS; redirect_items.ntargets = nredirected; - XLogRegisterBufData(0, (char *) &redirect_items, + XLogRegisterBufData(0, &redirect_items, offsetof(xlhp_prune_items, data)); - XLogRegisterBufData(0, (char *) redirected, + XLogRegisterBufData(0, redirected, sizeof(OffsetNumber[2]) * nredirected); } if (ndead > 0) @@ -2113,9 +2113,9 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer, xlrec.flags |= XLHP_HAS_DEAD_ITEMS; dead_items.ntargets = ndead; - XLogRegisterBufData(0, (char *) &dead_items, + XLogRegisterBufData(0, &dead_items, offsetof(xlhp_prune_items, data)); - XLogRegisterBufData(0, (char *) dead, + XLogRegisterBufData(0, dead, sizeof(OffsetNumber) * ndead); } if (nunused > 0) @@ -2123,17 +2123,17 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer, xlrec.flags |= XLHP_HAS_NOW_UNUSED_ITEMS; unused_items.ntargets = nunused; - XLogRegisterBufData(0, (char *) &unused_items, + XLogRegisterBufData(0, &unused_items, offsetof(xlhp_prune_items, data)); - XLogRegisterBufData(0, (char *) unused, + XLogRegisterBufData(0, unused, sizeof(OffsetNumber) * nunused); } if (nfrozen > 0) - XLogRegisterBufData(0, (char *) frz_offsets, + XLogRegisterBufData(0, frz_offsets, sizeof(OffsetNumber) * nfrozen); /* - * Prepare the main xl_heap_prune record. We already set the XLPH_HAS_* + * Prepare the main xl_heap_prune record. We already set the XLHP_HAS_* * flag above. */ if (RelationIsAccessibleInLogicalDecoding(relation)) @@ -2147,9 +2147,9 @@ log_heap_prune_and_freeze(Relation relation, Buffer buffer, Assert(nredirected == 0 && ndead == 0); /* also, any items in 'unused' must've been LP_DEAD previously */ } - XLogRegisterData((char *) &xlrec, SizeOfHeapPrune); + XLogRegisterData(&xlrec, SizeOfHeapPrune); if (TransactionIdIsValid(conflict_xid)) - XLogRegisterData((char *) &conflict_xid, sizeof(TransactionId)); + XLogRegisterData(&conflict_xid, sizeof(TransactionId)); switch (reason) { diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 473f3aa9bef9e..e6d2b5fced198 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -92,7 +92,7 @@ * heap's TOAST table will go through the normal bufmgr. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * IDENTIFICATION @@ -887,7 +887,7 @@ logical_heap_rewrite_flush_mappings(RewriteState state) src->off += len; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); XLogRegisterData(waldata_start, len); /* write xlog record */ @@ -961,8 +961,8 @@ logical_rewrite_log_mapping(RewriteState state, TransactionId xid, dboid = MyDatabaseId; snprintf(path, MAXPGPATH, - "pg_logical/mappings/" LOGICAL_REWRITE_FORMAT, - dboid, relid, + "%s/" LOGICAL_REWRITE_FORMAT, + PG_LOGICAL_MAPPINGS_DIR, dboid, relid, LSN_FORMAT_ARGS(state->rs_begin_lsn), xid, GetCurrentTransactionId()); @@ -1081,8 +1081,8 @@ heap_xlog_logical_rewrite(XLogReaderState *r) xlrec = (xl_heap_rewrite_mapping *) XLogRecGetData(r); snprintf(path, MAXPGPATH, - "pg_logical/mappings/" LOGICAL_REWRITE_FORMAT, - xlrec->mapped_db, xlrec->mapped_rel, + "%s/" LOGICAL_REWRITE_FORMAT, + PG_LOGICAL_MAPPINGS_DIR, xlrec->mapped_db, xlrec->mapped_rel, LSN_FORMAT_ARGS(xlrec->start_lsn), xlrec->mapped_xid, XLogRecGetXid(r)); @@ -1158,7 +1158,7 @@ CheckPointLogicalRewriteHeap(void) XLogRecPtr redo; DIR *mappings_dir; struct dirent *mapping_de; - char path[MAXPGPATH + 20]; + char path[MAXPGPATH + sizeof(PG_LOGICAL_MAPPINGS_DIR)]; /* * We start of with a minimum of the last redo pointer. No new decoding @@ -1173,8 +1173,8 @@ CheckPointLogicalRewriteHeap(void) if (cutoff != InvalidXLogRecPtr && redo < cutoff) cutoff = redo; - mappings_dir = AllocateDir("pg_logical/mappings"); - while ((mapping_de = ReadDir(mappings_dir, "pg_logical/mappings")) != NULL) + mappings_dir = AllocateDir(PG_LOGICAL_MAPPINGS_DIR); + while ((mapping_de = ReadDir(mappings_dir, PG_LOGICAL_MAPPINGS_DIR)) != NULL) { Oid dboid; Oid relid; @@ -1189,7 +1189,7 @@ CheckPointLogicalRewriteHeap(void) strcmp(mapping_de->d_name, "..") == 0) continue; - snprintf(path, sizeof(path), "pg_logical/mappings/%s", mapping_de->d_name); + snprintf(path, sizeof(path), "%s/%s", PG_LOGICAL_MAPPINGS_DIR, mapping_de->d_name); de_type = get_dirent_type(path, mapping_de, false, DEBUG1); if (de_type != PGFILETYPE_ERROR && de_type != PGFILETYPE_REG) @@ -1249,5 +1249,5 @@ CheckPointLogicalRewriteHeap(void) FreeDir(mappings_dir); /* persist directory entries to disk */ - fsync_fname("pg_logical/mappings", true); + fsync_fname(PG_LOGICAL_MAPPINGS_DIR, true); } diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 835b53415d0b7..09416450af962 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -3,6 +3,104 @@ * vacuumlazy.c * Concurrent ("lazy") vacuuming. * + * Heap relations are vacuumed in three main phases. In phase I, vacuum scans + * relation pages, pruning and freezing tuples and saving dead tuples' TIDs in + * a TID store. If that TID store fills up or vacuum finishes scanning the + * relation, it progresses to phase II: index vacuuming. Index vacuuming + * deletes the dead index entries referenced in the TID store. In phase III, + * vacuum scans the blocks of the relation referred to by the TIDs in the TID + * store and reaps the corresponding dead items, freeing that space for future + * tuples. + * + * If there are no indexes or index scanning is disabled, phase II may be + * skipped. If phase I identified very few dead index entries or if vacuum's + * failsafe mechanism has triggered (to avoid transaction ID wraparound), + * vacuum may skip phases II and III. + * + * If the TID store fills up in phase I, vacuum suspends phase I and proceeds + * to phases II and III, cleaning up the dead tuples referenced in the current + * TID store. This empties the TID store, allowing vacuum to resume phase I. + * + * In a way, the phases are more like states in a state machine, but they have + * been referred to colloquially as phases for so long that they are referred + * to as such here. + * + * Manually invoked VACUUMs may scan indexes during phase II in parallel. For + * more information on this, see the comment at the top of vacuumparallel.c. + * + * In between phases, vacuum updates the freespace map (every + * VACUUM_FSM_EVERY_PAGES). + * + * After completing all three phases, vacuum may truncate the relation if it + * has emptied pages at the end. Finally, vacuum updates relation statistics + * in pg_class and the cumulative statistics subsystem. + * + * Relation Scanning: + * + * Vacuum scans the heap relation, starting at the beginning and progressing + * to the end, skipping pages as permitted by their visibility status, vacuum + * options, and various other requirements. + * + * Vacuums are either aggressive or normal. Aggressive vacuums must scan every + * unfrozen tuple in order to advance relfrozenxid and avoid transaction ID + * wraparound. Normal vacuums may scan otherwise skippable pages for one of + * two reasons: + * + * When page skipping is not disabled, a normal vacuum may scan pages that are + * marked all-visible (and even all-frozen) in the visibility map if the range + * of skippable pages is below SKIP_PAGES_THRESHOLD. This is primarily for the + * benefit of kernel readahead (see comment in heap_vac_scan_next_block()). + * + * A normal vacuum may also scan skippable pages in an effort to freeze them + * and decrease the backlog of all-visible but not all-frozen pages that have + * to be processed by the next aggressive vacuum. These are referred to as + * eagerly scanned pages. Pages scanned due to SKIP_PAGES_THRESHOLD do not + * count as eagerly scanned pages. + * + * Eagerly scanned pages that are set all-frozen in the VM are successful + * eager freezes and those not set all-frozen in the VM are failed eager + * freezes. + * + * Because we want to amortize the overhead of freezing pages over multiple + * vacuums, normal vacuums cap the number of successful eager freezes to + * MAX_EAGER_FREEZE_SUCCESS_RATE of the number of all-visible but not + * all-frozen pages at the beginning of the vacuum. Since eagerly frozen pages + * may be unfrozen before the next aggressive vacuum, capping the number of + * successful eager freezes also caps the downside of eager freezing: + * potentially wasted work. + * + * Once the success cap has been hit, eager scanning is disabled for the + * remainder of the vacuum of the relation. + * + * Success is capped globally because we don't want to limit our successes if + * old data happens to be concentrated in a particular part of the table. This + * is especially likely to happen for append-mostly workloads where the oldest + * data is at the beginning of the unfrozen portion of the relation. + * + * On the assumption that different regions of the table are likely to contain + * similarly aged data, normal vacuums use a localized eager freeze failure + * cap. The failure count is reset for each region of the table -- comprised + * of EAGER_SCAN_REGION_SIZE blocks. In each region, we tolerate + * vacuum_max_eager_freeze_failure_rate of EAGER_SCAN_REGION_SIZE failures + * before suspending eager scanning until the end of the region. + * vacuum_max_eager_freeze_failure_rate is configurable both globally and per + * table. + * + * Aggressive vacuums must examine every unfrozen tuple and thus are not + * subject to any of the limits imposed by the eager scanning algorithm. + * + * Once vacuum has decided to scan a given block, it must read the block and + * obtain a cleanup lock to prune tuples on the page. A non-aggressive vacuum + * may choose to skip pruning and freezing if it cannot acquire a cleanup lock + * on the buffer right away. In this case, it may miss cleaning up dead tuples + * and their associated index entries (though it is free to reap any existing + * dead items on the page). + * + * After pruning and freezing, pages that are newly all-visible and all-frozen + * are marked as such in the visibility map. + * + * Dead TID Storage: + * * The major space usage for vacuuming is storage for the dead tuple IDs that * are to be removed from indexes. We want to ensure we can vacuum even the * very largest relations with finite memory space usage. To do that, we set @@ -20,7 +118,7 @@ * that there only needs to be one call to lazy_vacuum, after the initial pass * completes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -35,7 +133,6 @@ #include "access/genam.h" #include "access/heapam.h" -#include "access/heapam_xlog.h" #include "access/htup_details.h" #include "access/multixact.h" #include "access/tidstore.h" @@ -47,6 +144,7 @@ #include "commands/progress.h" #include "commands/vacuum.h" #include "common/int.h" +#include "common/pg_prng.h" #include "executor/instrument.h" #include "miscadmin.h" #include "pgstat.h" @@ -55,8 +153,8 @@ #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/lmgr.h" +#include "storage/read_stream.h" #include "utils/lsyscache.h" -#include "utils/memutils.h" #include "utils/pg_rusage.h" #include "utils/timestamp.h" @@ -133,6 +231,31 @@ typedef enum VACUUM_ERRCB_PHASE_TRUNCATE, } VacErrPhase; +/* + * An eager scan of a page that is set all-frozen in the VM is considered + * "successful". To spread out freezing overhead across multiple normal + * vacuums, we limit the number of successful eager page freezes. The maximum + * number of eager page freezes is calculated as a ratio of the all-visible + * but not all-frozen pages at the beginning of the vacuum. + */ +#define MAX_EAGER_FREEZE_SUCCESS_RATE 0.2 + +/* + * On the assumption that different regions of the table tend to have + * similarly aged data, once vacuum fails to freeze + * vacuum_max_eager_freeze_failure_rate of the blocks in a region of size + * EAGER_SCAN_REGION_SIZE, it suspends eager scanning until it has progressed + * to another region of the table with potentially older data. + */ +#define EAGER_SCAN_REGION_SIZE 4096 + +/* + * heap_vac_scan_next_block() sets these flags to communicate information + * about the block it read to the caller. + */ +#define VAC_BLK_WAS_EAGER_SCANNED (1 << 0) +#define VAC_BLK_ALL_VISIBLE_ACCORDING_TO_VM (1 << 1) + typedef struct LVRelState { /* Target heap relation and its indexes */ @@ -189,8 +312,30 @@ typedef struct LVRelState BlockNumber rel_pages; /* total number of pages */ BlockNumber scanned_pages; /* # pages examined (not skipped via VM) */ + + /* + * Count of all-visible blocks eagerly scanned (for logging only). This + * does not include skippable blocks scanned due to SKIP_PAGES_THRESHOLD. + */ + BlockNumber eager_scanned_pages; + BlockNumber removed_pages; /* # pages removed by relation truncation */ - BlockNumber frozen_pages; /* # pages with newly frozen tuples */ + BlockNumber new_frozen_tuple_pages; /* # pages with newly frozen tuples */ + + /* # pages newly set all-visible in the VM */ + BlockNumber vm_new_visible_pages; + + /* + * # pages newly set all-visible and all-frozen in the VM. This is a + * subset of vm_new_visible_pages. That is, vm_new_visible_pages includes + * all pages set all-visible, but vm_new_visible_frozen_pages includes + * only those which were also set all-frozen. + */ + BlockNumber vm_new_visible_frozen_pages; + + /* # all-visible pages newly set all-frozen in the VM */ + BlockNumber vm_new_frozen_pages; + BlockNumber lpdead_item_pages; /* # pages with LP_DEAD items */ BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ @@ -215,9 +360,57 @@ typedef struct LVRelState BlockNumber current_block; /* last block returned */ BlockNumber next_unskippable_block; /* next unskippable block */ bool next_unskippable_allvis; /* its visibility status */ + bool next_unskippable_eager_scanned; /* if it was eagerly scanned */ Buffer next_unskippable_vmbuffer; /* buffer containing its VM bit */ + + /* State related to managing eager scanning of all-visible pages */ + + /* + * A normal vacuum that has failed to freeze too many eagerly scanned + * blocks in a region suspends eager scanning. + * next_eager_scan_region_start is the block number of the first block + * eligible for resumed eager scanning. + * + * When eager scanning is permanently disabled, either initially + * (including for aggressive vacuum) or due to hitting the success cap, + * this is set to InvalidBlockNumber. + */ + BlockNumber next_eager_scan_region_start; + + /* + * The remaining number of blocks a normal vacuum will consider eager + * scanning when it is successful. When eager scanning is enabled, this is + * initialized to MAX_EAGER_FREEZE_SUCCESS_RATE of the total number of + * all-visible but not all-frozen pages. For each eager freeze success, + * this is decremented. Once it hits 0, eager scanning is permanently + * disabled. It is initialized to 0 if eager scanning starts out disabled + * (including for aggressive vacuum). + */ + BlockNumber eager_scan_remaining_successes; + + /* + * The maximum number of blocks which may be eagerly scanned and not + * frozen before eager scanning is temporarily suspended. This is + * configurable both globally, via the + * vacuum_max_eager_freeze_failure_rate GUC, and per table, with a table + * storage parameter of the same name. It is calculated as + * vacuum_max_eager_freeze_failure_rate of EAGER_SCAN_REGION_SIZE blocks. + * It is 0 when eager scanning is disabled. + */ + BlockNumber eager_scan_max_fails_per_region; + + /* + * The number of eagerly scanned blocks vacuum failed to freeze (due to + * age) in the current eager scan region. Vacuum resets it to + * eager_scan_max_fails_per_region each time it enters a new region of the + * relation. If eager_scan_remaining_fails hits 0, eager scanning is + * suspended until the next region. It is also 0 if eager scanning has + * been permanently disabled. + */ + BlockNumber eager_scan_remaining_fails; } LVRelState; + /* Struct for saving and restoring vacuum error information. */ typedef struct LVSavedErrInfo { @@ -229,8 +422,11 @@ typedef struct LVSavedErrInfo /* non-export function prototypes */ static void lazy_scan_heap(LVRelState *vacrel); -static bool heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno, - bool *all_visible_according_to_vm); +static void heap_vacuum_eager_scan_setup(LVRelState *vacrel, + VacuumParams *params); +static BlockNumber heap_vac_scan_next_block(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data); static void find_next_unskippable_block(LVRelState *vacrel, bool *skipsallvis); static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, @@ -238,7 +434,7 @@ static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, static void lazy_scan_prune(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, Buffer vmbuffer, bool all_visible_according_to_vm, - bool *has_lpdead_items); + bool *has_lpdead_items, bool *vm_page_frozen); static bool lazy_scan_noprune(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, bool *has_lpdead_items); @@ -280,6 +476,130 @@ static void restore_vacuum_error_info(LVRelState *vacrel, const LVSavedErrInfo *saved_vacrel); + +/* + * Helper to set up the eager scanning state for vacuuming a single relation. + * Initializes the eager scan management related members of the LVRelState. + * + * Caller provides whether or not an aggressive vacuum is required due to + * vacuum options or for relfrozenxid/relminmxid advancement. + */ +static void +heap_vacuum_eager_scan_setup(LVRelState *vacrel, VacuumParams *params) +{ + uint32 randseed; + BlockNumber allvisible; + BlockNumber allfrozen; + float first_region_ratio; + bool oldest_unfrozen_before_cutoff = false; + + /* + * Initialize eager scan management fields to their disabled values. + * Aggressive vacuums, normal vacuums of small tables, and normal vacuums + * of tables without sufficiently old tuples disable eager scanning. + */ + vacrel->next_eager_scan_region_start = InvalidBlockNumber; + vacrel->eager_scan_max_fails_per_region = 0; + vacrel->eager_scan_remaining_fails = 0; + vacrel->eager_scan_remaining_successes = 0; + + /* If eager scanning is explicitly disabled, just return. */ + if (params->max_eager_freeze_failure_rate == 0) + return; + + /* + * The caller will have determined whether or not an aggressive vacuum is + * required by either the vacuum parameters or the relative age of the + * oldest unfrozen transaction IDs. An aggressive vacuum must scan every + * all-visible page to safely advance the relfrozenxid and/or relminmxid, + * so scans of all-visible pages are not considered eager. + */ + if (vacrel->aggressive) + return; + + /* + * Aggressively vacuuming a small relation shouldn't take long, so it + * isn't worth amortizing. We use two times the region size as the size + * cutoff because the eager scan start block is a random spot somewhere in + * the first region, making the second region the first to be eager + * scanned normally. + */ + if (vacrel->rel_pages < 2 * EAGER_SCAN_REGION_SIZE) + return; + + /* + * We only want to enable eager scanning if we are likely to be able to + * freeze some of the pages in the relation. + * + * Tuples with XIDs older than OldestXmin or MXIDs older than OldestMxact + * are technically freezable, but we won't freeze them unless the criteria + * for opportunistic freezing is met. Only tuples with XIDs/MXIDs older + * than the FreezeLimit/MultiXactCutoff are frozen in the common case. + * + * So, as a heuristic, we wait until the FreezeLimit has advanced past the + * relfrozenxid or the MultiXactCutoff has advanced past the relminmxid to + * enable eager scanning. + */ + if (TransactionIdIsNormal(vacrel->cutoffs.relfrozenxid) && + TransactionIdPrecedes(vacrel->cutoffs.relfrozenxid, + vacrel->cutoffs.FreezeLimit)) + oldest_unfrozen_before_cutoff = true; + + if (!oldest_unfrozen_before_cutoff && + MultiXactIdIsValid(vacrel->cutoffs.relminmxid) && + MultiXactIdPrecedes(vacrel->cutoffs.relminmxid, + vacrel->cutoffs.MultiXactCutoff)) + oldest_unfrozen_before_cutoff = true; + + if (!oldest_unfrozen_before_cutoff) + return; + + /* We have met the criteria to eagerly scan some pages. */ + + /* + * Our success cap is MAX_EAGER_FREEZE_SUCCESS_RATE of the number of + * all-visible but not all-frozen blocks in the relation. + */ + visibilitymap_count(vacrel->rel, &allvisible, &allfrozen); + + vacrel->eager_scan_remaining_successes = + (BlockNumber) (MAX_EAGER_FREEZE_SUCCESS_RATE * + (allvisible - allfrozen)); + + /* If every all-visible page is frozen, eager scanning is disabled. */ + if (vacrel->eager_scan_remaining_successes == 0) + return; + + /* + * Now calculate the bounds of the first eager scan region. Its end block + * will be a random spot somewhere in the first EAGER_SCAN_REGION_SIZE + * blocks. This affects the bounds of all subsequent regions and avoids + * eager scanning and failing to freeze the same blocks each vacuum of the + * relation. + */ + randseed = pg_prng_uint32(&pg_global_prng_state); + + vacrel->next_eager_scan_region_start = randseed % EAGER_SCAN_REGION_SIZE; + + Assert(params->max_eager_freeze_failure_rate > 0 && + params->max_eager_freeze_failure_rate <= 1); + + vacrel->eager_scan_max_fails_per_region = + params->max_eager_freeze_failure_rate * + EAGER_SCAN_REGION_SIZE; + + /* + * The first region will be smaller than subsequent regions. As such, + * adjust the eager freeze failures tolerated for this region. + */ + first_region_ratio = 1 - (float) vacrel->next_eager_scan_region_start / + EAGER_SCAN_REGION_SIZE; + + vacrel->eager_scan_remaining_fails = + vacrel->eager_scan_max_fails_per_region * + first_region_ratio; +} + /* * heap_vacuum_rel() -- perform VACUUM for one heap relation * @@ -303,7 +623,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, minmulti_updated; BlockNumber orig_rel_pages, new_rel_pages, - new_rel_allvisible; + new_rel_allvisible, + new_rel_allfrozen; PGRUsage ru0; TimestampTz starttime = 0; PgStat_Counter startreadtime = 0, @@ -319,7 +640,6 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, if (instrument) { pg_rusage_init(&ru0); - starttime = GetCurrentTimestamp(); if (track_io_timing) { startreadtime = pgStatBlockReadTime; @@ -327,6 +647,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } } + /* Used for instrumentation and stats report */ + starttime = GetCurrentTimestamp(); + pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM, RelationGetRelid(rel)); @@ -408,8 +731,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, /* Initialize page counters explicitly (be tidy) */ vacrel->scanned_pages = 0; + vacrel->eager_scanned_pages = 0; vacrel->removed_pages = 0; - vacrel->frozen_pages = 0; + vacrel->new_frozen_tuple_pages = 0; vacrel->lpdead_item_pages = 0; vacrel->missed_dead_pages = 0; vacrel->nonempty_pages = 0; @@ -430,6 +754,10 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->recently_dead_tuples = 0; vacrel->missed_dead_tuples = 0; + vacrel->vm_new_visible_pages = 0; + vacrel->vm_new_visible_frozen_pages = 0; + vacrel->vm_new_frozen_pages = 0; + /* * Get cutoffs that determine which deleted tuples are considered DEAD, * not just RECENTLY_DEAD, and which XIDs/MXIDs to freeze. Then determine @@ -449,9 +777,16 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->aggressive = vacuum_get_cutoffs(rel, params, &vacrel->cutoffs); vacrel->rel_pages = orig_rel_pages = RelationGetNumberOfBlocks(rel); vacrel->vistest = GlobalVisTestFor(rel); + /* Initialize state used to track oldest extant XID/MXID */ vacrel->NewRelfrozenXid = vacrel->cutoffs.OldestXmin; vacrel->NewRelminMxid = vacrel->cutoffs.OldestMxact; + + /* + * Initialize state related to tracking all-visible page skipping. This is + * very important to determine whether or not it is safe to advance the + * relfrozenxid/relminmxid. + */ vacrel->skippedallvis = false; skipwithvm = true; if (params->options & VACOPT_DISABLE_PAGE_SKIPPING) @@ -466,6 +801,13 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->skipwithvm = skipwithvm; + /* + * Set up eager scan tracking state. This must happen after determining + * whether or not the vacuum must be aggressive, because only normal + * vacuums use the eager scan algorithm. + */ + heap_vacuum_eager_scan_setup(vacrel, params); + if (verbose) { if (vacrel->aggressive) @@ -558,10 +900,18 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * pg_class.relpages to */ new_rel_pages = vacrel->rel_pages; /* After possible rel truncation */ - visibilitymap_count(rel, &new_rel_allvisible, NULL); + visibilitymap_count(rel, &new_rel_allvisible, &new_rel_allfrozen); if (new_rel_allvisible > new_rel_pages) new_rel_allvisible = new_rel_pages; + /* + * An all-frozen block _must_ be all-visible. As such, clamp the count of + * all-frozen blocks to the count of all-visible blocks. This matches the + * clamping of relallvisible above. + */ + if (new_rel_allfrozen > new_rel_allvisible) + new_rel_allfrozen = new_rel_allvisible; + /* * Now actually update rel's pg_class entry. * @@ -570,7 +920,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, * scan every page that isn't skipped using the visibility map. */ vac_update_relstats(rel, new_rel_pages, vacrel->new_live_tuples, - new_rel_allvisible, vacrel->nindexes > 0, + new_rel_allvisible, new_rel_allfrozen, + vacrel->nindexes > 0, vacrel->NewRelfrozenXid, vacrel->NewRelminMxid, &frozenxid_updated, &minmulti_updated, false); @@ -588,7 +939,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, rel->rd_rel->relisshared, Max(vacrel->new_live_tuples, 0), vacrel->recently_dead_tuples + - vacrel->missed_dead_tuples); + vacrel->missed_dead_tuples, + starttime); pgstat_progress_end_command(); if (instrument) @@ -608,6 +960,9 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, int32 diff; double read_rate = 0, write_rate = 0; + int64 total_blks_hit; + int64 total_blks_read; + int64 total_blks_dirtied; TimestampDifference(starttime, endtime, &secs_dur, &usecs_dur); memset(&walusage, 0, sizeof(WalUsage)); @@ -615,6 +970,13 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, memset(&bufferusage, 0, sizeof(BufferUsage)); BufferUsageAccumDiff(&bufferusage, &pgBufferUsage, &startbufferusage); + total_blks_hit = bufferusage.shared_blks_hit + + bufferusage.local_blks_hit; + total_blks_read = bufferusage.shared_blks_read + + bufferusage.local_blks_read; + total_blks_dirtied = bufferusage.shared_blks_dirtied + + bufferusage.local_blks_dirtied; + initStringInfo(&buf); if (verbose) { @@ -650,21 +1012,23 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->relnamespace, vacrel->relname, vacrel->num_index_scans); - appendStringInfo(&buf, _("pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n"), + appendStringInfo(&buf, _("pages: %u removed, %u remain, %u scanned (%.2f%% of total), %u eagerly scanned\n"), vacrel->removed_pages, new_rel_pages, vacrel->scanned_pages, orig_rel_pages == 0 ? 100.0 : - 100.0 * vacrel->scanned_pages / orig_rel_pages); + 100.0 * vacrel->scanned_pages / + orig_rel_pages, + vacrel->eager_scanned_pages); appendStringInfo(&buf, - _("tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n"), - (long long) vacrel->tuples_deleted, - (long long) vacrel->new_rel_tuples, - (long long) vacrel->recently_dead_tuples); + _("tuples: %" PRId64 " removed, %" PRId64 " remain, %" PRId64 " are dead but not yet removable\n"), + vacrel->tuples_deleted, + (int64) vacrel->new_rel_tuples, + vacrel->recently_dead_tuples); if (vacrel->missed_dead_tuples > 0) appendStringInfo(&buf, - _("tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n"), - (long long) vacrel->missed_dead_tuples, + _("tuples missed: %" PRId64 " dead from %u pages not removed due to cleanup lock contention\n"), + vacrel->missed_dead_tuples, vacrel->missed_dead_pages); diff = (int32) (ReadNextTransactionId() - vacrel->cutoffs.OldestXmin); @@ -687,11 +1051,19 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, _("new relminmxid: %u, which is %d MXIDs ahead of previous value\n"), vacrel->NewRelminMxid, diff); } - appendStringInfo(&buf, _("frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n"), - vacrel->frozen_pages, + appendStringInfo(&buf, _("frozen: %u pages from table (%.2f%% of total) had %" PRId64 " tuples frozen\n"), + vacrel->new_frozen_tuple_pages, orig_rel_pages == 0 ? 100.0 : - 100.0 * vacrel->frozen_pages / orig_rel_pages, - (long long) vacrel->tuples_frozen); + 100.0 * vacrel->new_frozen_tuple_pages / + orig_rel_pages, + vacrel->tuples_frozen); + + appendStringInfo(&buf, + _("visibility map: %u pages set all-visible, %u pages set all-frozen (%u were all-visible)\n"), + vacrel->vm_new_visible_pages, + vacrel->vm_new_visible_frozen_pages + + vacrel->vm_new_frozen_pages, + vacrel->vm_new_frozen_pages); if (vacrel->do_index_vacuuming) { if (vacrel->nindexes == 0 || vacrel->num_index_scans == 0) @@ -699,7 +1071,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, else appendStringInfoString(&buf, _("index scan needed: ")); - msgfmt = _("%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n"); + msgfmt = _("%u pages from table (%.2f%% of total) had %" PRId64 " dead item identifiers removed\n"); } else { @@ -708,13 +1080,13 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, else appendStringInfoString(&buf, _("index scan bypassed by failsafe: ")); - msgfmt = _("%u pages from table (%.2f%% of total) have %lld dead item identifiers\n"); + msgfmt = _("%u pages from table (%.2f%% of total) have %" PRId64 " dead item identifiers\n"); } appendStringInfo(&buf, msgfmt, vacrel->lpdead_item_pages, orig_rel_pages == 0 ? 100.0 : 100.0 * vacrel->lpdead_item_pages / orig_rel_pages, - (long long) vacrel->lpdead_items); + vacrel->lpdead_items); for (int i = 0; i < vacrel->nindexes; i++) { IndexBulkDeleteResult *istat = vacrel->indstats[i]; @@ -730,6 +1102,17 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, istat->pages_deleted, istat->pages_free); } + if (track_cost_delay_timing) + { + /* + * We bypass the changecount mechanism because this value is + * only updated by the calling process. We also rely on the + * above call to pgstat_progress_end_command() to not clear + * the st_progress_param array. + */ + appendStringInfo(&buf, _("delay time: %.3f ms\n"), + (double) MyBEEntry->st_progress_param[PROGRESS_VACUUM_DELAY_TIME] / 1000000.0); + } if (track_io_timing) { double read_ms = (double) (pgStatBlockReadTime - startreadtime) / 1000; @@ -740,23 +1123,24 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, } if (secs_dur > 0 || usecs_dur > 0) { - read_rate = (double) BLCKSZ * (bufferusage.shared_blks_read + bufferusage.local_blks_read) / + read_rate = (double) BLCKSZ * total_blks_read / (1024 * 1024) / (secs_dur + usecs_dur / 1000000.0); - write_rate = (double) BLCKSZ * (bufferusage.shared_blks_dirtied + bufferusage.local_blks_dirtied) / + write_rate = (double) BLCKSZ * total_blks_dirtied / (1024 * 1024) / (secs_dur + usecs_dur / 1000000.0); } appendStringInfo(&buf, _("avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"), read_rate, write_rate); appendStringInfo(&buf, - _("buffer usage: %lld hits, %lld misses, %lld dirtied\n"), - (long long) (bufferusage.shared_blks_hit + bufferusage.local_blks_hit), - (long long) (bufferusage.shared_blks_read + bufferusage.local_blks_read), - (long long) (bufferusage.shared_blks_dirtied + bufferusage.local_blks_dirtied)); + _("buffer usage: %" PRId64 " hits, %" PRId64 " reads, %" PRId64 " dirtied\n"), + total_blks_hit, + total_blks_read, + total_blks_dirtied); appendStringInfo(&buf, - _("WAL usage: %lld records, %lld full page images, %llu bytes\n"), - (long long) walusage.wal_records, - (long long) walusage.wal_fpi, - (unsigned long long) walusage.wal_bytes); + _("WAL usage: %" PRId64 " records, %" PRId64 " full page images, %" PRIu64 " bytes, %" PRId64 " buffers full\n"), + walusage.wal_records, + walusage.wal_fpi, + walusage.wal_bytes, + walusage.wal_buffers_full); appendStringInfo(&buf, _("system usage: %s"), pg_rusage_show(&ru0)); ereport(verbose ? INFO : LOG, @@ -815,13 +1199,12 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, static void lazy_scan_heap(LVRelState *vacrel) { + ReadStream *stream; BlockNumber rel_pages = vacrel->rel_pages, - blkno, + blkno = 0, next_fsm_block_to_vacuum = 0; - bool all_visible_according_to_vm; - - TidStore *dead_items = vacrel->dead_items; - VacDeadItemsInfo *dead_items_info = vacrel->dead_items_info; + BlockNumber orig_eager_scan_success_limit = + vacrel->eager_scan_remaining_successes; /* for logging */ Buffer vmbuffer = InvalidBuffer; const int initprog_index[] = { PROGRESS_VACUUM_PHASE, @@ -833,30 +1216,41 @@ lazy_scan_heap(LVRelState *vacrel) /* Report that we're scanning the heap, advertising total # of blocks */ initprog_val[0] = PROGRESS_VACUUM_PHASE_SCAN_HEAP; initprog_val[1] = rel_pages; - initprog_val[2] = dead_items_info->max_bytes; + initprog_val[2] = vacrel->dead_items_info->max_bytes; pgstat_progress_update_multi_param(3, initprog_index, initprog_val); /* Initialize for the first heap_vac_scan_next_block() call */ vacrel->current_block = InvalidBlockNumber; vacrel->next_unskippable_block = InvalidBlockNumber; vacrel->next_unskippable_allvis = false; + vacrel->next_unskippable_eager_scanned = false; vacrel->next_unskippable_vmbuffer = InvalidBuffer; - while (heap_vac_scan_next_block(vacrel, &blkno, &all_visible_according_to_vm)) + /* + * Set up the read stream for vacuum's first pass through the heap. + * + * This could be made safe for READ_STREAM_USE_BATCHING, but only with + * explicit work in heap_vac_scan_next_block. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE, + vacrel->bstrategy, + vacrel->rel, + MAIN_FORKNUM, + heap_vac_scan_next_block, + vacrel, + sizeof(uint8)); + + while (true) { Buffer buf; Page page; + uint8 blk_info = 0; bool has_lpdead_items; + void *per_buffer_data = NULL; + bool vm_page_frozen = false; bool got_cleanup_lock = false; - vacrel->scanned_pages++; - - /* Report as block scanned, update error traceback information */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); - update_vacuum_error_info(vacrel, NULL, VACUUM_ERRCB_PHASE_SCAN_HEAP, - blkno, InvalidOffsetNumber); - - vacuum_delay_point(); + vacuum_delay_point(false); /* * Regularly check if wraparound failsafe should trigger. @@ -867,16 +1261,20 @@ lazy_scan_heap(LVRelState *vacrel) * one-pass strategy, and the two-pass strategy with the index_cleanup * param set to 'off'. */ - if (vacrel->scanned_pages % FAILSAFE_EVERY_PAGES == 0) + if (vacrel->scanned_pages > 0 && + vacrel->scanned_pages % FAILSAFE_EVERY_PAGES == 0) lazy_check_wraparound_failsafe(vacrel); /* * Consider if we definitely have enough space to process TIDs on page * already. If we are close to overrunning the available space for * dead_items TIDs, pause and do a cycle of vacuuming before we tackle - * this page. + * this page. However, let's force at least one page-worth of tuples + * to be stored as to ensure we do at least some work when the memory + * configured is so low that we run out before storing anything. */ - if (TidStoreMemoryUsage(dead_items) > dead_items_info->max_bytes) + if (vacrel->dead_items_info->num_items > 0 && + TidStoreMemoryUsage(vacrel->dead_items) > vacrel->dead_items_info->max_bytes) { /* * Before beginning index vacuuming, we release any pin we may @@ -896,10 +1294,11 @@ lazy_scan_heap(LVRelState *vacrel) /* * Vacuum the Free Space Map to make newly-freed space visible on - * upper-level FSM pages. Note we have not yet processed blkno. + * upper-level FSM pages. Note that blkno is the previously + * processed block. */ FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, - blkno); + blkno + 1); next_fsm_block_to_vacuum = blkno; /* Report that we are once again scanning the heap */ @@ -907,6 +1306,26 @@ lazy_scan_heap(LVRelState *vacrel) PROGRESS_VACUUM_PHASE_SCAN_HEAP); } + buf = read_stream_next_buffer(stream, &per_buffer_data); + + /* The relation is exhausted. */ + if (!BufferIsValid(buf)) + break; + + blk_info = *((uint8 *) per_buffer_data); + CheckBufferIsPinnedOnce(buf); + page = BufferGetPage(buf); + blkno = BufferGetBlockNumber(buf); + + vacrel->scanned_pages++; + if (blk_info & VAC_BLK_WAS_EAGER_SCANNED) + vacrel->eager_scanned_pages++; + + /* Report as block scanned, update error traceback information */ + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + update_vacuum_error_info(vacrel, NULL, VACUUM_ERRCB_PHASE_SCAN_HEAP, + blkno, InvalidOffsetNumber); + /* * Pin the visibility map page in case we need to mark the page * all-visible. In most cases this will be very cheap, because we'll @@ -914,10 +1333,6 @@ lazy_scan_heap(LVRelState *vacrel) */ visibilitymap_pin(vacrel->rel, blkno, &vmbuffer); - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); - page = BufferGetPage(buf); - /* * We need a buffer cleanup lock to prune HOT chains and defragment * the page in lazy_scan_prune. But when it's not possible to acquire @@ -973,8 +1388,64 @@ lazy_scan_heap(LVRelState *vacrel) */ if (got_cleanup_lock) lazy_scan_prune(vacrel, buf, blkno, page, - vmbuffer, all_visible_according_to_vm, - &has_lpdead_items); + vmbuffer, + blk_info & VAC_BLK_ALL_VISIBLE_ACCORDING_TO_VM, + &has_lpdead_items, &vm_page_frozen); + + /* + * Count an eagerly scanned page as a failure or a success. + * + * Only lazy_scan_prune() freezes pages, so if we didn't get the + * cleanup lock, we won't have frozen the page. However, we only count + * pages that were too new to require freezing as eager freeze + * failures. + * + * We could gather more information from lazy_scan_noprune() about + * whether or not there were tuples with XIDs or MXIDs older than the + * FreezeLimit or MultiXactCutoff. However, for simplicity, we simply + * exclude pages skipped due to cleanup lock contention from eager + * freeze algorithm caps. + */ + if (got_cleanup_lock && + (blk_info & VAC_BLK_WAS_EAGER_SCANNED)) + { + /* Aggressive vacuums do not eager scan. */ + Assert(!vacrel->aggressive); + + if (vm_page_frozen) + { + if (vacrel->eager_scan_remaining_successes > 0) + vacrel->eager_scan_remaining_successes--; + + if (vacrel->eager_scan_remaining_successes == 0) + { + /* + * Report only once that we disabled eager scanning. We + * may eagerly read ahead blocks in excess of the success + * or failure caps before attempting to freeze them, so we + * could reach here even after disabling additional eager + * scanning. + */ + if (vacrel->eager_scan_max_fails_per_region > 0) + ereport(vacrel->verbose ? INFO : DEBUG2, + (errmsg("disabling eager scanning after freezing %u eagerly scanned blocks of \"%s.%s.%s\"", + orig_eager_scan_success_limit, + vacrel->dbname, vacrel->relnamespace, + vacrel->relname))); + + /* + * If we hit our success cap, permanently disable eager + * scanning by setting the other eager scan management + * fields to their disabled values. + */ + vacrel->eager_scan_remaining_fails = 0; + vacrel->next_eager_scan_region_start = InvalidBlockNumber; + vacrel->eager_scan_max_fails_per_region = 0; + } + } + else if (vacrel->eager_scan_remaining_fails > 0) + vacrel->eager_scan_remaining_fails--; + } /* * Now drop the buffer lock and, potentially, update the FSM. @@ -1026,8 +1497,12 @@ lazy_scan_heap(LVRelState *vacrel) if (BufferIsValid(vmbuffer)) ReleaseBuffer(vmbuffer); - /* report that everything is now scanned */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno); + /* + * Report that everything is now scanned. We never skip scanning the last + * block in the relation, so we can pass rel_pages here. + */ + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, + rel_pages); /* now we can compute the new value for pg_class.reltuples */ vacrel->new_live_tuples = vac_estimate_reltuples(vacrel->rel, rel_pages, @@ -1042,22 +1517,26 @@ lazy_scan_heap(LVRelState *vacrel) Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + vacrel->missed_dead_tuples; + read_stream_end(stream); + /* * Do index vacuuming (call each index's ambulkdelete routine), then do * related heap vacuuming */ - if (dead_items_info->num_items > 0) + if (vacrel->dead_items_info->num_items > 0) lazy_vacuum(vacrel); /* * Vacuum the remainder of the Free Space Map. We must do this whether or * not there were indexes, and whether or not we bypassed index vacuuming. + * We can pass rel_pages here because we never skip scanning the last + * block of the relation. */ - if (blkno > next_fsm_block_to_vacuum) - FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); + if (rel_pages > next_fsm_block_to_vacuum) + FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, rel_pages); /* report all blocks vacuumed */ - pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, blkno); + pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_VACUUMED, rel_pages); /* Do final index cleanup (call each index's amvacuumcleanup routine) */ if (vacrel->nindexes > 0 && vacrel->do_index_cleanup) @@ -1065,28 +1544,37 @@ lazy_scan_heap(LVRelState *vacrel) } /* - * heap_vac_scan_next_block() -- get next block for vacuum to process - * - * lazy_scan_heap() calls here every time it needs to get the next block to - * prune and vacuum. The function uses the visibility map, vacuum options, - * and various thresholds to skip blocks which do not need to be processed and - * sets blkno to the next block to process. - * - * The block number and visibility status of the next block to process are set - * in *blkno and *all_visible_according_to_vm. The return value is false if - * there are no further blocks to process. - * - * vacrel is an in/out parameter here. Vacuum options and information about - * the relation are read. vacrel->skippedallvis is set if we skip a block - * that's all-visible but not all-frozen, to ensure that we don't update - * relfrozenxid in that case. vacrel also holds information about the next - * unskippable block, as bookkeeping for this function. + * heap_vac_scan_next_block() -- read stream callback to get the next block + * for vacuum to process + * + * Every time lazy_scan_heap() needs a new block to process during its first + * phase, it invokes read_stream_next_buffer() with a stream set up to call + * heap_vac_scan_next_block() to get the next block. + * + * heap_vac_scan_next_block() uses the visibility map, vacuum options, and + * various thresholds to skip blocks which do not need to be processed and + * returns the next block to process or InvalidBlockNumber if there are no + * remaining blocks. + * + * The visibility status of the next block to process and whether or not it + * was eager scanned is set in the per_buffer_data. + * + * callback_private_data contains a reference to the LVRelState, passed to the + * read stream API during stream setup. The LVRelState is an in/out parameter + * here (locally named `vacrel`). Vacuum options and information about the + * relation are read from it. vacrel->skippedallvis is set if we skip a block + * that's all-visible but not all-frozen (to ensure that we don't update + * relfrozenxid in that case). vacrel also holds information about the next + * unskippable block -- as bookkeeping for this function. */ -static bool -heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno, - bool *all_visible_according_to_vm) +static BlockNumber +heap_vac_scan_next_block(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) { BlockNumber next_block; + LVRelState *vacrel = callback_private_data; + uint8 blk_info = 0; /* relies on InvalidBlockNumber + 1 overflowing to 0 on first call */ next_block = vacrel->current_block + 1; @@ -1099,8 +1587,7 @@ heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno, ReleaseBuffer(vacrel->next_unskippable_vmbuffer); vacrel->next_unskippable_vmbuffer = InvalidBuffer; } - *blkno = vacrel->rel_pages; - return false; + return InvalidBlockNumber; } /* @@ -1149,9 +1636,10 @@ heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno, * but chose not to. We know that they are all-visible in the VM, * otherwise they would've been unskippable. */ - *blkno = vacrel->current_block = next_block; - *all_visible_according_to_vm = true; - return true; + vacrel->current_block = next_block; + blk_info |= VAC_BLK_ALL_VISIBLE_ACCORDING_TO_VM; + *((uint8 *) per_buffer_data) = blk_info; + return vacrel->current_block; } else { @@ -1161,9 +1649,13 @@ heap_vac_scan_next_block(LVRelState *vacrel, BlockNumber *blkno, */ Assert(next_block == vacrel->next_unskippable_block); - *blkno = vacrel->current_block = next_block; - *all_visible_according_to_vm = vacrel->next_unskippable_allvis; - return true; + vacrel->current_block = next_block; + if (vacrel->next_unskippable_allvis) + blk_info |= VAC_BLK_ALL_VISIBLE_ACCORDING_TO_VM; + if (vacrel->next_unskippable_eager_scanned) + blk_info |= VAC_BLK_WAS_EAGER_SCANNED; + *((uint8 *) per_buffer_data) = blk_info; + return vacrel->current_block; } } @@ -1186,11 +1678,12 @@ find_next_unskippable_block(LVRelState *vacrel, bool *skipsallvis) BlockNumber rel_pages = vacrel->rel_pages; BlockNumber next_unskippable_block = vacrel->next_unskippable_block + 1; Buffer next_unskippable_vmbuffer = vacrel->next_unskippable_vmbuffer; + bool next_unskippable_eager_scanned = false; bool next_unskippable_allvis; *skipsallvis = false; - for (;;) + for (;; next_unskippable_block++) { uint8 mapbits = visibilitymap_get_status(vacrel->rel, next_unskippable_block, @@ -1198,6 +1691,19 @@ find_next_unskippable_block(LVRelState *vacrel, bool *skipsallvis) next_unskippable_allvis = (mapbits & VISIBILITYMAP_ALL_VISIBLE) != 0; + /* + * At the start of each eager scan region, normal vacuums with eager + * scanning enabled reset the failure counter, allowing vacuum to + * resume eager scanning if it had been suspended in the previous + * region. + */ + if (next_unskippable_block >= vacrel->next_eager_scan_region_start) + { + vacrel->eager_scan_remaining_fails = + vacrel->eager_scan_max_fails_per_region; + vacrel->next_eager_scan_region_start += EAGER_SCAN_REGION_SIZE; + } + /* * A block is unskippable if it is not all visible according to the * visibility map. @@ -1226,28 +1732,41 @@ find_next_unskippable_block(LVRelState *vacrel, bool *skipsallvis) break; /* - * Aggressive VACUUM caller can't skip pages just because they are - * all-visible. They may still skip all-frozen pages, which can't - * contain XIDs < OldestXmin (XIDs that aren't already frozen by now). + * All-frozen pages cannot contain XIDs < OldestXmin (XIDs that aren't + * already frozen by now), so this page can be skipped. */ - if ((mapbits & VISIBILITYMAP_ALL_FROZEN) == 0) - { - if (vacrel->aggressive) - break; + if ((mapbits & VISIBILITYMAP_ALL_FROZEN) != 0) + continue; - /* - * All-visible block is safe to skip in non-aggressive case. But - * remember that the final range contains such a block for later. - */ - *skipsallvis = true; + /* + * Aggressive vacuums cannot skip any all-visible pages that are not + * also all-frozen. + */ + if (vacrel->aggressive) + break; + + /* + * Normal vacuums with eager scanning enabled only skip all-visible + * but not all-frozen pages if they have hit the failure limit for the + * current eager scan region. + */ + if (vacrel->eager_scan_remaining_fails > 0) + { + next_unskippable_eager_scanned = true; + break; } - next_unskippable_block++; + /* + * All-visible blocks are safe to skip in a normal vacuum. But + * remember that the final range contains such a block for later. + */ + *skipsallvis = true; } /* write the local variables back to vacrel */ vacrel->next_unskippable_block = next_unskippable_block; vacrel->next_unskippable_allvis = next_unskippable_allvis; + vacrel->next_unskippable_eager_scanned = next_unskippable_eager_scanned; vacrel->next_unskippable_vmbuffer = next_unskippable_vmbuffer; } @@ -1278,6 +1797,12 @@ find_next_unskippable_block(LVRelState *vacrel, bool *skipsallvis) * lazy_scan_prune (or lazy_scan_noprune). Otherwise returns true, indicating * that lazy_scan_heap is done processing the page, releasing lock on caller's * behalf. + * + * No vm_page_frozen output parameter (like that passed to lazy_scan_prune()) + * is passed here because neither empty nor new pages can be eagerly frozen. + * New pages are never frozen. Empty pages are always set frozen in the VM at + * the same time that they are set all-visible, and we don't eagerly scan + * frozen pages. */ static bool lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, @@ -1347,6 +1872,8 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, */ if (!PageIsAllVisible(page)) { + uint8 old_vmbits; + START_CRIT_SECTION(); /* mark buffer dirty before writing a WAL record */ @@ -1366,10 +1893,24 @@ lazy_scan_new_or_empty(LVRelState *vacrel, Buffer buf, BlockNumber blkno, log_newpage_buffer(buf, true); PageSetAllVisible(page); - visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr, - vmbuffer, InvalidTransactionId, - VISIBILITYMAP_ALL_VISIBLE | VISIBILITYMAP_ALL_FROZEN); + old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf, + InvalidXLogRecPtr, + vmbuffer, InvalidTransactionId, + VISIBILITYMAP_ALL_VISIBLE | + VISIBILITYMAP_ALL_FROZEN); END_CRIT_SECTION(); + + /* + * If the page wasn't already set all-visible and/or all-frozen in + * the VM, count it as newly set for logging. + */ + if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0) + { + vacrel->vm_new_visible_pages++; + vacrel->vm_new_visible_frozen_pages++; + } + else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0) + vacrel->vm_new_frozen_pages++; } freespace = PageGetHeapFreeSpace(page); @@ -1401,6 +1942,10 @@ cmpOffsetNumbers(const void *a, const void *b) * * *has_lpdead_items is set to true or false depending on whether, upon return * from this function, any LP_DEAD items are still present on the page. + * + * *vm_page_frozen is set to true if the page is newly set all-frozen in the + * VM. The caller currently only uses this for determining whether an eagerly + * scanned page was successfully set all-frozen. */ static void lazy_scan_prune(LVRelState *vacrel, @@ -1409,7 +1954,8 @@ lazy_scan_prune(LVRelState *vacrel, Page page, Buffer vmbuffer, bool all_visible_according_to_vm, - bool *has_lpdead_items) + bool *has_lpdead_items, + bool *vm_page_frozen) { Relation rel = vacrel->rel; PruneFreezeResult presult; @@ -1447,11 +1993,12 @@ lazy_scan_prune(LVRelState *vacrel, if (presult.nfrozen > 0) { /* - * We don't increment the frozen_pages instrumentation counter when - * nfrozen == 0, since it only counts pages with newly frozen tuples - * (don't confuse that with pages newly set all-frozen in VM). + * We don't increment the new_frozen_tuple_pages instrumentation + * counter when nfrozen == 0, since it only counts pages with newly + * frozen tuples (don't confuse that with pages newly set all-frozen + * in VM). */ - vacrel->frozen_pages++; + vacrel->new_frozen_tuple_pages++; } /* @@ -1523,6 +2070,7 @@ lazy_scan_prune(LVRelState *vacrel, */ if (!all_visible_according_to_vm && presult.all_visible) { + uint8 old_vmbits; uint8 flags = VISIBILITYMAP_ALL_VISIBLE; if (presult.all_frozen) @@ -1546,9 +2094,30 @@ lazy_scan_prune(LVRelState *vacrel, */ PageSetAllVisible(page); MarkBufferDirty(buf); - visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr, - vmbuffer, presult.vm_conflict_horizon, - flags); + old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf, + InvalidXLogRecPtr, + vmbuffer, presult.vm_conflict_horizon, + flags); + + /* + * If the page wasn't already set all-visible and/or all-frozen in the + * VM, count it as newly set for logging. + */ + if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0) + { + vacrel->vm_new_visible_pages++; + if (presult.all_frozen) + { + vacrel->vm_new_visible_frozen_pages++; + *vm_page_frozen = true; + } + } + else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0 && + presult.all_frozen) + { + vacrel->vm_new_frozen_pages++; + *vm_page_frozen = true; + } } /* @@ -1598,6 +2167,8 @@ lazy_scan_prune(LVRelState *vacrel, else if (all_visible_according_to_vm && presult.all_visible && presult.all_frozen && !VM_ALL_FROZEN(vacrel->rel, blkno, &vmbuffer)) { + uint8 old_vmbits; + /* * Avoid relying on all_visible_according_to_vm as a proxy for the * page-level PD_ALL_VISIBLE bit being set, since it might have become @@ -1617,10 +2188,35 @@ lazy_scan_prune(LVRelState *vacrel, * was logged when the page's tuples were frozen. */ Assert(!TransactionIdIsValid(presult.vm_conflict_horizon)); - visibilitymap_set(vacrel->rel, blkno, buf, InvalidXLogRecPtr, - vmbuffer, InvalidTransactionId, - VISIBILITYMAP_ALL_VISIBLE | - VISIBILITYMAP_ALL_FROZEN); + old_vmbits = visibilitymap_set(vacrel->rel, blkno, buf, + InvalidXLogRecPtr, + vmbuffer, InvalidTransactionId, + VISIBILITYMAP_ALL_VISIBLE | + VISIBILITYMAP_ALL_FROZEN); + + /* + * The page was likely already set all-visible in the VM. However, + * there is a small chance that it was modified sometime between + * setting all_visible_according_to_vm and checking the visibility + * during pruning. Check the return value of old_vmbits anyway to + * ensure the visibility map counters used for logging are accurate. + */ + if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0) + { + vacrel->vm_new_visible_pages++; + vacrel->vm_new_visible_frozen_pages++; + *vm_page_frozen = true; + } + + /* + * We already checked that the page was not set all-frozen in the VM + * above, so we don't need to test the value of old_vmbits. + */ + else + { + vacrel->vm_new_frozen_pages++; + *vm_page_frozen = true; + } } } @@ -1924,7 +2520,7 @@ lazy_vacuum(LVRelState *vacrel) */ threshold = (double) vacrel->rel_pages * BYPASS_THRESHOLD_PAGES; bypass = (vacrel->lpdead_item_pages < threshold && - (TidStoreMemoryUsage(vacrel->dead_items) < (32L * 1024L * 1024L))); + TidStoreMemoryUsage(vacrel->dead_items) < 32 * 1024 * 1024); } if (bypass) @@ -2080,6 +2676,34 @@ lazy_vacuum_all_indexes(LVRelState *vacrel) return allindexes; } +/* + * Read stream callback for vacuum's third phase (second pass over the heap). + * Gets the next block from the TID store and returns it or InvalidBlockNumber + * if there are no further blocks to vacuum. + * + * NB: Assumed to be safe to use with READ_STREAM_USE_BATCHING. + */ +static BlockNumber +vacuum_reap_lp_read_stream_next(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) +{ + TidStoreIter *iter = callback_private_data; + TidStoreIterResult *iter_result; + + iter_result = TidStoreIterateNext(iter); + if (iter_result == NULL) + return InvalidBlockNumber; + + /* + * Save the TidStoreIterResult for later, so we can extract the offsets. + * It is safe to copy the result, according to TidStoreIterateNext(). + */ + memcpy(per_buffer_data, iter_result, sizeof(*iter_result)); + + return iter_result->blkno; +} + /* * lazy_vacuum_heap_rel() -- second pass over the heap for two pass strategy * @@ -2100,11 +2724,11 @@ lazy_vacuum_all_indexes(LVRelState *vacrel) static void lazy_vacuum_heap_rel(LVRelState *vacrel) { + ReadStream *stream; BlockNumber vacuumed_pages = 0; Buffer vmbuffer = InvalidBuffer; LVSavedErrInfo saved_err_info; TidStoreIter *iter; - TidStoreIterResult *iter_result; Assert(vacrel->do_index_vacuuming); Assert(vacrel->do_index_cleanup); @@ -2120,20 +2744,45 @@ lazy_vacuum_heap_rel(LVRelState *vacrel) InvalidBlockNumber, InvalidOffsetNumber); iter = TidStoreBeginIterate(vacrel->dead_items); - while ((iter_result = TidStoreIterateNext(iter)) != NULL) + + /* + * Set up the read stream for vacuum's second pass through the heap. + * + * It is safe to use batchmode, as vacuum_reap_lp_read_stream_next() does + * not need to wait for IO and does not perform locking. Once we support + * parallelism it should still be fine, as presumably the holder of locks + * would never be blocked by IO while holding the lock. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_USE_BATCHING, + vacrel->bstrategy, + vacrel->rel, + MAIN_FORKNUM, + vacuum_reap_lp_read_stream_next, + iter, + sizeof(TidStoreIterResult)); + + while (true) { BlockNumber blkno; Buffer buf; Page page; + TidStoreIterResult *iter_result; Size freespace; OffsetNumber offsets[MaxOffsetNumber]; int num_offsets; - vacuum_delay_point(); + vacuum_delay_point(false); + + buf = read_stream_next_buffer(stream, (void **) &iter_result); - blkno = iter_result->blkno; - vacrel->blkno = blkno; + /* The relation is exhausted */ + if (!BufferIsValid(buf)) + break; + + vacrel->blkno = blkno = BufferGetBlockNumber(buf); + Assert(iter_result); num_offsets = TidStoreGetBlockOffsets(iter_result, offsets, lengthof(offsets)); Assert(num_offsets <= lengthof(offsets)); @@ -2145,8 +2794,6 @@ lazy_vacuum_heap_rel(LVRelState *vacrel) visibilitymap_pin(vacrel->rel, blkno, &vmbuffer); /* We need a non-cleanup exclusive lock to mark dead_items unused */ - buf = ReadBufferExtended(vacrel->rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - vacrel->bstrategy); LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); lazy_vacuum_heap_page(vacrel, blkno, buf, offsets, num_offsets, vmbuffer); @@ -2159,6 +2806,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel) RecordPageWithFreeSpace(vacrel->rel, blkno, freespace); vacuumed_pages++; } + + read_stream_end(stream); TidStoreEndIterate(iter); vacrel->blkno = InvalidBlockNumber; @@ -2174,8 +2823,8 @@ lazy_vacuum_heap_rel(LVRelState *vacrel) vacuumed_pages == vacrel->lpdead_item_pages)); ereport(DEBUG2, - (errmsg("table \"%s\": removed %lld dead item identifiers in %u pages", - vacrel->relname, (long long) vacrel->dead_items_info->num_items, + (errmsg("table \"%s\": removed %" PRId64 " dead item identifiers in %u pages", + vacrel->relname, vacrel->dead_items_info->num_items, vacuumed_pages))); /* Revert to the previous phase information for error traceback */ @@ -2266,6 +2915,7 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer, if (heap_page_is_all_visible(vacrel, buffer, &visibility_cutoff_xid, &all_frozen)) { + uint8 old_vmbits; uint8 flags = VISIBILITYMAP_ALL_VISIBLE; if (all_frozen) @@ -2275,8 +2925,25 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer, } PageSetAllVisible(page); - visibilitymap_set(vacrel->rel, blkno, buffer, InvalidXLogRecPtr, - vmbuffer, visibility_cutoff_xid, flags); + old_vmbits = visibilitymap_set(vacrel->rel, blkno, buffer, + InvalidXLogRecPtr, + vmbuffer, visibility_cutoff_xid, + flags); + + /* + * If the page wasn't already set all-visible and/or all-frozen in the + * VM, count it as newly set for logging. + */ + if ((old_vmbits & VISIBILITYMAP_ALL_VISIBLE) == 0) + { + vacrel->vm_new_visible_pages++; + if (all_frozen) + vacrel->vm_new_visible_frozen_pages++; + } + + else if ((old_vmbits & VISIBILITYMAP_ALL_FROZEN) == 0 && + all_frozen) + vacrel->vm_new_frozen_pages++; } /* Revert to the previous phase information for error traceback */ @@ -2445,7 +3112,7 @@ lazy_vacuum_one_index(Relation indrel, IndexBulkDeleteResult *istat, InvalidBlockNumber, InvalidOffsetNumber); /* Do bulk deletion */ - istat = vac_bulkdel_one_index(&ivinfo, istat, (void *) vacrel->dead_items, + istat = vac_bulkdel_one_index(&ivinfo, istat, vacrel->dead_items, vacrel->dead_items_info); /* Revert to the previous phase information for error traceback */ @@ -2873,7 +3540,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers) */ dead_items_info = (VacDeadItemsInfo *) palloc(sizeof(VacDeadItemsInfo)); - dead_items_info->max_bytes = vac_work_mem * 1024L; + dead_items_info->max_bytes = vac_work_mem * (Size) 1024; dead_items_info->num_items = 0; vacrel->dead_items_info = dead_items_info; @@ -2887,19 +3554,18 @@ static void dead_items_add(LVRelState *vacrel, BlockNumber blkno, OffsetNumber *offsets, int num_offsets) { - TidStore *dead_items = vacrel->dead_items; const int prog_index[2] = { PROGRESS_VACUUM_NUM_DEAD_ITEM_IDS, PROGRESS_VACUUM_DEAD_TUPLE_BYTES }; int64 prog_val[2]; - TidStoreSetBlockOffsets(dead_items, blkno, offsets, num_offsets); + TidStoreSetBlockOffsets(vacrel->dead_items, blkno, offsets, num_offsets); vacrel->dead_items_info->num_items += num_offsets; /* update the progress information */ prog_val[0] = vacrel->dead_items_info->num_items; - prog_val[1] = TidStoreMemoryUsage(dead_items); + prog_val[1] = TidStoreMemoryUsage(vacrel->dead_items); pgstat_progress_update_multi_param(2, prog_index, prog_val); } @@ -2909,8 +3575,6 @@ dead_items_add(LVRelState *vacrel, BlockNumber blkno, OffsetNumber *offsets, static void dead_items_reset(LVRelState *vacrel) { - TidStore *dead_items = vacrel->dead_items; - if (ParallelVacuumIsActive(vacrel)) { parallel_vacuum_reset_dead_items(vacrel->pvs); @@ -2918,7 +3582,7 @@ dead_items_reset(LVRelState *vacrel) } /* Recreate the tidstore with the same max_bytes limitation */ - TidStoreDestroy(dead_items); + TidStoreDestroy(vacrel->dead_items); vacrel->dead_items = TidStoreCreateLocal(vacrel->dead_items_info->max_bytes, true); /* Reset the counter */ @@ -3090,7 +3754,7 @@ update_relstats_all_indexes(LVRelState *vacrel) vac_update_relstats(indrel, istat->num_pages, istat->num_index_tuples, - 0, + 0, 0, false, InvalidTransactionId, InvalidMultiXactId, diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c index 8b24e7bc33cf6..745a04ef26e29 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -3,7 +3,7 @@ * visibilitymap.c * bitmap for tracking visibility of heap tuples * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -239,8 +239,10 @@ visibilitymap_pin_ok(BlockNumber heapBlk, Buffer vmbuf) * You must pass a buffer containing the correct map page to this function. * Call visibilitymap_pin first to pin the right one. This function doesn't do * any I/O. + * + * Returns the state of the page's VM bits before setting flags. */ -void +uint8 visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, XLogRecPtr recptr, Buffer vmBuf, TransactionId cutoff_xid, uint8 flags) @@ -250,6 +252,7 @@ visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, uint8 mapOffset = HEAPBLK_TO_OFFSET(heapBlk); Page page; uint8 *map; + uint8 status; #ifdef TRACE_VISIBILITYMAP elog(DEBUG1, "vm_set %s %d", RelationGetRelationName(rel), heapBlk); @@ -274,7 +277,8 @@ visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, map = (uint8 *) PageGetContents(page); LockBuffer(vmBuf, BUFFER_LOCK_EXCLUSIVE); - if (flags != (map[mapByte] >> mapOffset & VISIBILITYMAP_VALID_BITS)) + status = (map[mapByte] >> mapOffset) & VISIBILITYMAP_VALID_BITS; + if (flags != status) { START_CRIT_SECTION(); @@ -311,6 +315,7 @@ visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, } LockBuffer(vmBuf, BUFFER_LOCK_UNLOCK); + return status; } /* diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c index 079fb7cba65ef..f0f4f974bcedb 100644 --- a/src/backend/access/index/amapi.c +++ b/src/backend/access/index/amapi.c @@ -3,7 +3,7 @@ * amapi.c * Support routines for API for Postgres index access methods. * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -107,6 +107,66 @@ GetIndexAmRoutineByAmId(Oid amoid, bool noerror) } +/* + * IndexAmTranslateStrategy - given an access method and strategy, get the + * corresponding compare type. + * + * If missing_ok is false, throw an error if no compare type is found. If + * true, just return COMPARE_INVALID. + */ +CompareType +IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok) +{ + CompareType result; + IndexAmRoutine *amroutine; + + /* shortcut for common case */ + if (amoid == BTREE_AM_OID && + (strategy > InvalidStrategy && strategy <= BTMaxStrategyNumber)) + return (CompareType) strategy; + + amroutine = GetIndexAmRoutineByAmId(amoid, false); + if (amroutine->amtranslatestrategy) + result = amroutine->amtranslatestrategy(strategy, opfamily); + else + result = COMPARE_INVALID; + + if (!missing_ok && result == COMPARE_INVALID) + elog(ERROR, "could not translate strategy number %d for index AM %u", strategy, amoid); + + return result; +} + +/* + * IndexAmTranslateCompareType - given an access method and compare type, get + * the corresponding strategy number. + * + * If missing_ok is false, throw an error if no strategy is found correlating + * to the given cmptype. If true, just return InvalidStrategy. + */ +StrategyNumber +IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok) +{ + StrategyNumber result; + IndexAmRoutine *amroutine; + + /* shortcut for common case */ + if (amoid == BTREE_AM_OID && + (cmptype > COMPARE_INVALID && cmptype <= COMPARE_GT)) + return (StrategyNumber) cmptype; + + amroutine = GetIndexAmRoutineByAmId(amoid, false); + if (amroutine->amtranslatecmptype) + result = amroutine->amtranslatecmptype(cmptype, opfamily); + else + result = InvalidStrategy; + + if (!missing_ok && result == InvalidStrategy) + elog(ERROR, "could not translate compare type %u for index AM %u", cmptype, amoid); + + return result; +} + /* * Ask appropriate access method to validate the specified opclass. */ diff --git a/src/backend/access/index/amvalidate.c b/src/backend/access/index/amvalidate.c index 32bb477f3283c..4cf237019adaf 100644 --- a/src/backend/access/index/amvalidate.c +++ b/src/backend/access/index/amvalidate.c @@ -4,7 +4,7 @@ * Support routines for index access methods' amvalidate and * amadjustmembers functions. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index de751e8e4a30a..0cb27af131095 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -3,7 +3,7 @@ * genam.c * general index access method routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -20,6 +20,7 @@ #include "postgres.h" #include "access/genam.h" +#include "access/heapam.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/transam.h" @@ -29,6 +30,7 @@ #include "storage/bufmgr.h" #include "storage/procarray.h" #include "utils/acl.h" +#include "utils/injection_point.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/rls.h" @@ -117,6 +119,7 @@ RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys) scan->ignore_killed_tuples = !scan->xactStartedInRecovery; scan->opaque = NULL; + scan->instrument = NULL; scan->xs_itup = NULL; scan->xs_itupdesc = NULL; @@ -154,8 +157,9 @@ IndexScanEnd(IndexScanDesc scan) * * Construct a string describing the contents of an index entry, in the * form "(key_name, ...)=(key_value, ...)". This is currently used - * for building unique-constraint and exclusion-constraint error messages, - * so only key columns of the index are checked and printed. + * for building unique-constraint, exclusion-constraint error messages, and + * logical replication conflict error messages so only key columns of the index + * are checked and printed. * * Note that if the user does not have permissions to view all of the * columns involved then a NULL is returned. Returning a partial key seems @@ -371,7 +375,7 @@ index_compute_xid_horizon_for_tuples(Relation irel, * nkeys, key: scan keys * * The attribute numbers in the scan key should be set for the heap case. - * If we choose to index, we reset them to 1..n to reference the index + * If we choose to index, we convert them to 1..n to reference the index * columns. Note this means there must be one scankey qualification per * index column! This is checked by the Asserts in the normal, index-using * case, but won't be checked if the heapscan path is taken. @@ -419,17 +423,22 @@ systable_beginscan(Relation heapRelation, if (irel) { int i; + ScanKey idxkey; - /* Change attribute numbers to be index column numbers. */ + idxkey = palloc_array(ScanKeyData, nkeys); + + /* Convert attribute numbers to be index column numbers. */ for (i = 0; i < nkeys; i++) { int j; + memcpy(&idxkey[i], &key[i], sizeof(ScanKeyData)); + for (j = 0; j < IndexRelationGetNumberOfAttributes(irel); j++) { if (key[i].sk_attno == irel->rd_index->indkey.values[j]) { - key[i].sk_attno = j + 1; + idxkey[i].sk_attno = j + 1; break; } } @@ -438,9 +447,11 @@ systable_beginscan(Relation heapRelation, } sysscan->iscan = index_beginscan(heapRelation, irel, - snapshot, nkeys, 0); - index_rescan(sysscan->iscan, key, nkeys, NULL, 0); + snapshot, NULL, nkeys, 0); + index_rescan(sysscan->iscan, idxkey, nkeys, NULL, 0); sysscan->scan = NULL; + + pfree(idxkey); } else { @@ -566,17 +577,13 @@ systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup) Assert(tup == ExecFetchSlotHeapTuple(sysscan->slot, false, NULL)); - /* - * Trust that table_tuple_satisfies_snapshot() and its subsidiaries - * (commonly LockBuffer() and HeapTupleSatisfiesMVCC()) do not themselves - * acquire snapshots, so we need not register the snapshot. Those - * facilities are too low-level to have any business scanning tables. - */ freshsnap = GetCatalogSnapshot(RelationGetRelid(sysscan->heap_rel)); + freshsnap = RegisterSnapshot(freshsnap); result = table_tuple_satisfies_snapshot(sysscan->heap_rel, sysscan->slot, freshsnap); + UnregisterSnapshot(freshsnap); /* * Handle the concurrent abort while fetching the catalog tuple during @@ -647,6 +654,7 @@ systable_beginscan_ordered(Relation heapRelation, { SysScanDesc sysscan; int i; + ScanKey idxkey; /* REINDEX can probably be a hard error here ... */ if (ReindexIsProcessingIndex(RelationGetRelid(indexRelation))) @@ -678,16 +686,20 @@ systable_beginscan_ordered(Relation heapRelation, sysscan->snapshot = NULL; } - /* Change attribute numbers to be index column numbers. */ + idxkey = palloc_array(ScanKeyData, nkeys); + + /* Convert attribute numbers to be index column numbers. */ for (i = 0; i < nkeys; i++) { int j; + memcpy(&idxkey[i], &key[i], sizeof(ScanKeyData)); + for (j = 0; j < IndexRelationGetNumberOfAttributes(indexRelation); j++) { if (key[i].sk_attno == indexRelation->rd_index->indkey.values[j]) { - key[i].sk_attno = j + 1; + idxkey[i].sk_attno = j + 1; break; } } @@ -696,10 +708,20 @@ systable_beginscan_ordered(Relation heapRelation, } sysscan->iscan = index_beginscan(heapRelation, indexRelation, - snapshot, nkeys, 0); - index_rescan(sysscan->iscan, key, nkeys, NULL, 0); + snapshot, NULL, nkeys, 0); + index_rescan(sysscan->iscan, idxkey, nkeys, NULL, 0); sysscan->scan = NULL; + pfree(idxkey); + + /* + * If CheckXidAlive is set then set a flag to indicate that system table + * scan is in-progress. See detailed comments in xact.c where these + * variables are declared. + */ + if (TransactionIdIsValid(CheckXidAlive)) + bsysscan = true; + return sysscan; } @@ -744,5 +766,148 @@ systable_endscan_ordered(SysScanDesc sysscan) index_endscan(sysscan->iscan); if (sysscan->snapshot) UnregisterSnapshot(sysscan->snapshot); + + /* + * Reset the bsysscan flag at the end of the systable scan. See detailed + * comments in xact.c where these variables are declared. + */ + if (TransactionIdIsValid(CheckXidAlive)) + bsysscan = false; + pfree(sysscan); } + +/* + * systable_inplace_update_begin --- update a row "in place" (overwrite it) + * + * Overwriting violates both MVCC and transactional safety, so the uses of + * this function in Postgres are extremely limited. Nonetheless we find some + * places to use it. See README.tuplock section "Locking to write + * inplace-updated tables" and later sections for expectations of readers and + * writers of a table that gets inplace updates. Standard flow: + * + * ... [any slow preparation not requiring oldtup] ... + * systable_inplace_update_begin([...], &tup, &inplace_state); + * if (!HeapTupleIsValid(tup)) + * elog(ERROR, [...]); + * ... [buffer is exclusive-locked; mutate "tup"] ... + * if (dirty) + * systable_inplace_update_finish(inplace_state, tup); + * else + * systable_inplace_update_cancel(inplace_state); + * + * The first several params duplicate the systable_beginscan() param list. + * "oldtupcopy" is an output parameter, assigned NULL if the key ceases to + * find a live tuple. (In PROC_IN_VACUUM, that is a low-probability transient + * condition.) If "oldtupcopy" gets non-NULL, you must pass output parameter + * "state" to systable_inplace_update_finish() or + * systable_inplace_update_cancel(). + */ +void +systable_inplace_update_begin(Relation relation, + Oid indexId, + bool indexOK, + Snapshot snapshot, + int nkeys, const ScanKeyData *key, + HeapTuple *oldtupcopy, + void **state) +{ + int retries = 0; + SysScanDesc scan; + HeapTuple oldtup; + BufferHeapTupleTableSlot *bslot; + + /* + * For now, we don't allow parallel updates. Unlike a regular update, + * this should never create a combo CID, so it might be possible to relax + * this restriction, but not without more thought and testing. It's not + * clear that it would be useful, anyway. + */ + if (IsInParallelMode()) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TRANSACTION_STATE), + errmsg("cannot update tuples during a parallel operation"))); + + /* + * Accept a snapshot argument, for symmetry, but this function advances + * its snapshot as needed to reach the tail of the updated tuple chain. + */ + Assert(snapshot == NULL); + + Assert(IsInplaceUpdateRelation(relation) || !IsSystemRelation(relation)); + + /* Loop for an exclusive-locked buffer of a non-updated tuple. */ + do + { + TupleTableSlot *slot; + + CHECK_FOR_INTERRUPTS(); + + /* + * Processes issuing heap_update (e.g. GRANT) at maximum speed could + * drive us to this error. A hostile table owner has stronger ways to + * damage their own table, so that's minor. + */ + if (retries++ > 10000) + elog(ERROR, "giving up after too many tries to overwrite row"); + + INJECTION_POINT("inplace-before-pin", NULL); + scan = systable_beginscan(relation, indexId, indexOK, snapshot, + nkeys, unconstify(ScanKeyData *, key)); + oldtup = systable_getnext(scan); + if (!HeapTupleIsValid(oldtup)) + { + systable_endscan(scan); + *oldtupcopy = NULL; + return; + } + + slot = scan->slot; + Assert(TTS_IS_BUFFERTUPLE(slot)); + bslot = (BufferHeapTupleTableSlot *) slot; + } while (!heap_inplace_lock(scan->heap_rel, + bslot->base.tuple, bslot->buffer, + (void (*) (void *)) systable_endscan, scan)); + + *oldtupcopy = heap_copytuple(oldtup); + *state = scan; +} + +/* + * systable_inplace_update_finish --- second phase of inplace update + * + * The tuple cannot change size, and therefore its header fields and null + * bitmap (if any) don't change either. + */ +void +systable_inplace_update_finish(void *state, HeapTuple tuple) +{ + SysScanDesc scan = (SysScanDesc) state; + Relation relation = scan->heap_rel; + TupleTableSlot *slot = scan->slot; + BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; + HeapTuple oldtup = bslot->base.tuple; + Buffer buffer = bslot->buffer; + + heap_inplace_update_and_unlock(relation, oldtup, tuple, buffer); + systable_endscan(scan); +} + +/* + * systable_inplace_update_cancel --- abandon inplace update + * + * This is an alternative to making a no-op update. + */ +void +systable_inplace_update_cancel(void *state) +{ + SysScanDesc scan = (SysScanDesc) state; + Relation relation = scan->heap_rel; + TupleTableSlot *slot = scan->slot; + BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; + HeapTuple oldtup = bslot->base.tuple; + Buffer buffer = bslot->buffer; + + heap_inplace_unlock(relation, oldtup, buffer); + systable_endscan(scan); +} diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index dcd04b813d8d9..219df1971da66 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -3,7 +3,7 @@ * indexam.c * general index access method routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -256,6 +256,7 @@ IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, + IndexScanInstrumentation *instrument, int nkeys, int norderbys) { IndexScanDesc scan; @@ -270,6 +271,7 @@ index_beginscan(Relation heapRelation, */ scan->heapRelation = heapRelation; scan->xs_snapshot = snapshot; + scan->instrument = instrument; /* prepare to fetch index matches from table */ scan->xs_heapfetch = table_index_fetch_begin(heapRelation); @@ -286,6 +288,7 @@ index_beginscan(Relation heapRelation, IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, + IndexScanInstrumentation *instrument, int nkeys) { IndexScanDesc scan; @@ -299,6 +302,7 @@ index_beginscan_bitmap(Relation indexRelation, * up by RelationGetIndexScan. */ scan->xs_snapshot = snapshot; + scan->instrument = instrument; return scan; } @@ -448,14 +452,19 @@ index_restrpos(IndexScanDesc scan) /* * index_parallelscan_estimate - estimate shared memory for parallel scan + * + * When instrument=true, estimate includes SharedIndexScanInstrumentation + * space. When parallel_aware=true, estimate includes whatever space the + * index AM's amestimateparallelscan routine requested when called. */ Size index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys, - Snapshot snapshot) + Snapshot snapshot, bool instrument, + bool parallel_aware, int nworkers) { Size nbytes; - Assert(snapshot != InvalidSnapshot); + Assert(instrument || parallel_aware); RELATION_CHECKS; @@ -463,14 +472,25 @@ index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys, nbytes = add_size(nbytes, EstimateSnapshotSpace(snapshot)); nbytes = MAXALIGN(nbytes); + if (instrument) + { + Size sharedinfosz; + + sharedinfosz = offsetof(SharedIndexScanInstrumentation, winstrument) + + nworkers * sizeof(IndexScanInstrumentation); + nbytes = add_size(nbytes, sharedinfosz); + nbytes = MAXALIGN(nbytes); + } + /* - * If amestimateparallelscan is not provided, assume there is no - * AM-specific data needed. (It's hard to believe that could work, but - * it's easy enough to cater to it here.) + * If parallel scan index AM interface can't be used (or index AM provides + * no such interface), assume there is no AM-specific data needed */ - if (indexRelation->rd_indam->amestimateparallelscan != NULL) + if (parallel_aware && + indexRelation->rd_indam->amestimateparallelscan != NULL) nbytes = add_size(nbytes, - indexRelation->rd_indam->amestimateparallelscan(nkeys, + indexRelation->rd_indam->amestimateparallelscan(indexRelation, + nkeys, norderbys)); return nbytes; @@ -488,11 +508,14 @@ index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys, */ void index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, - Snapshot snapshot, ParallelIndexScanDesc target) + Snapshot snapshot, bool instrument, + bool parallel_aware, int nworkers, + SharedIndexScanInstrumentation **sharedinfo, + ParallelIndexScanDesc target) { Size offset; - Assert(snapshot != InvalidSnapshot); + Assert(instrument || parallel_aware); RELATION_CHECKS; @@ -500,17 +523,36 @@ index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, EstimateSnapshotSpace(snapshot)); offset = MAXALIGN(offset); - target->ps_relid = RelationGetRelid(heapRelation); - target->ps_indexid = RelationGetRelid(indexRelation); - target->ps_offset = offset; + target->ps_locator = heapRelation->rd_locator; + target->ps_indexlocator = indexRelation->rd_locator; + target->ps_offset_ins = 0; + target->ps_offset_am = 0; SerializeSnapshot(snapshot, target->ps_snapshot_data); + if (instrument) + { + Size sharedinfosz; + + target->ps_offset_ins = offset; + sharedinfosz = offsetof(SharedIndexScanInstrumentation, winstrument) + + nworkers * sizeof(IndexScanInstrumentation); + offset = add_size(offset, sharedinfosz); + offset = MAXALIGN(offset); + + /* Set leader's *sharedinfo pointer, and initialize stats */ + *sharedinfo = (SharedIndexScanInstrumentation *) + OffsetToPointer(target, target->ps_offset_ins); + memset(*sharedinfo, 0, sharedinfosz); + (*sharedinfo)->num_workers = nworkers; + } + /* aminitparallelscan is optional; assume no-op if not provided by AM */ - if (indexRelation->rd_indam->aminitparallelscan != NULL) + if (parallel_aware && indexRelation->rd_indam->aminitparallelscan != NULL) { void *amtarget; - amtarget = OffsetToPointer(target, offset); + target->ps_offset_am = offset; + amtarget = OffsetToPointer(target, target->ps_offset_am); indexRelation->rd_indam->aminitparallelscan(amtarget); } } @@ -538,13 +580,17 @@ index_parallelrescan(IndexScanDesc scan) * Caller must be holding suitable locks on the heap and the index. */ IndexScanDesc -index_beginscan_parallel(Relation heaprel, Relation indexrel, int nkeys, - int norderbys, ParallelIndexScanDesc pscan) +index_beginscan_parallel(Relation heaprel, Relation indexrel, + IndexScanInstrumentation *instrument, + int nkeys, int norderbys, + ParallelIndexScanDesc pscan) { Snapshot snapshot; IndexScanDesc scan; - Assert(RelationGetRelid(heaprel) == pscan->ps_relid); + Assert(RelFileLocatorEquals(heaprel->rd_locator, pscan->ps_locator)); + Assert(RelFileLocatorEquals(indexrel->rd_locator, pscan->ps_indexlocator)); + snapshot = RestoreSnapshot(pscan->ps_snapshot_data); RegisterSnapshot(snapshot); scan = index_beginscan_internal(indexrel, nkeys, norderbys, snapshot, @@ -556,6 +602,7 @@ index_beginscan_parallel(Relation heaprel, Relation indexrel, int nkeys, */ scan->heapRelation = heaprel; scan->xs_snapshot = snapshot; + scan->instrument = instrument; /* prepare to fetch index matches from table */ scan->xs_heapfetch = table_index_fetch_begin(heaprel); diff --git a/src/backend/access/index/meson.build b/src/backend/access/index/meson.build index 641b5bd0c272e..e29c03089fd6d 100644 --- a/src/backend/access/index/meson.build +++ b/src/backend/access/index/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'amapi.c', diff --git a/src/backend/access/meson.build b/src/backend/access/meson.build index 62a371db7f75c..7a2d0ddb68942 100644 --- a/src/backend/access/meson.build +++ b/src/backend/access/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('brin') subdir('common') diff --git a/src/backend/access/nbtree/Makefile b/src/backend/access/nbtree/Makefile index d69808e78c61e..c5cd4e0177fa5 100644 --- a/src/backend/access/nbtree/Makefile +++ b/src/backend/access/nbtree/Makefile @@ -17,6 +17,7 @@ OBJS = \ nbtdedup.o \ nbtinsert.o \ nbtpage.o \ + nbtpreprocesskeys.o \ nbtree.o \ nbtsearch.o \ nbtsort.o \ diff --git a/src/backend/access/nbtree/README b/src/backend/access/nbtree/README index 52e646c7f759a..53d4a61dc3f19 100644 --- a/src/backend/access/nbtree/README +++ b/src/backend/access/nbtree/README @@ -99,9 +99,9 @@ cannot miss any items it should have seen, nor accidentally return the same item twice. The scan must remember the page's right-link at the time it was scanned, since that is the page to move right to; if we move right to the current right-link then we'd re-scan any items moved by a page split. -We don't similarly remember the left-link, since it's best to use the most -up-to-date left-link when trying to move left (see detailed move-left -algorithm below). +We also remember the left-link, and follow it when the scan moves backwards +(though this requires extra handling to account for concurrent splits of +the left sibling; see detailed move-left algorithm below). In most cases we release our lock and pin on a page before attempting to acquire pin and lock on the page we are moving to. In a few places diff --git a/src/backend/access/nbtree/meson.build b/src/backend/access/nbtree/meson.build index 232f64b9447d8..80962de6e6ed9 100644 --- a/src/backend/access/nbtree/meson.build +++ b/src/backend/access/nbtree/meson.build @@ -1,10 +1,11 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'nbtcompare.c', 'nbtdedup.c', 'nbtinsert.c', 'nbtpage.c', + 'nbtpreprocesskeys.c', 'nbtree.c', 'nbtsearch.c', 'nbtsort.c', diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c index 1c72867c84e5e..4da5a3c1d161d 100644 --- a/src/backend/access/nbtree/nbtcompare.c +++ b/src/backend/access/nbtree/nbtcompare.c @@ -3,7 +3,7 @@ * nbtcompare.c * Comparison functions for btree access method. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -58,6 +58,7 @@ #include #include "utils/fmgrprotos.h" +#include "utils/skipsupport.h" #include "utils/sortsupport.h" #ifdef STRESS_SORT_INT_MIN @@ -78,6 +79,51 @@ btboolcmp(PG_FUNCTION_ARGS) PG_RETURN_INT32((int32) a - (int32) b); } +static Datum +bool_decrement(Relation rel, Datum existing, bool *underflow) +{ + bool bexisting = DatumGetBool(existing); + + if (bexisting == false) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return BoolGetDatum(bexisting - 1); +} + +static Datum +bool_increment(Relation rel, Datum existing, bool *overflow) +{ + bool bexisting = DatumGetBool(existing); + + if (bexisting == true) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return BoolGetDatum(bexisting + 1); +} + +Datum +btboolskipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = bool_decrement; + sksup->increment = bool_increment; + sksup->low_elem = BoolGetDatum(false); + sksup->high_elem = BoolGetDatum(true); + + PG_RETURN_VOID(); +} + Datum btint2cmp(PG_FUNCTION_ARGS) { @@ -105,6 +151,51 @@ btint2sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +static Datum +int2_decrement(Relation rel, Datum existing, bool *underflow) +{ + int16 iexisting = DatumGetInt16(existing); + + if (iexisting == PG_INT16_MIN) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return Int16GetDatum(iexisting - 1); +} + +static Datum +int2_increment(Relation rel, Datum existing, bool *overflow) +{ + int16 iexisting = DatumGetInt16(existing); + + if (iexisting == PG_INT16_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return Int16GetDatum(iexisting + 1); +} + +Datum +btint2skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = int2_decrement; + sksup->increment = int2_increment; + sksup->low_elem = Int16GetDatum(PG_INT16_MIN); + sksup->high_elem = Int16GetDatum(PG_INT16_MAX); + + PG_RETURN_VOID(); +} + Datum btint4cmp(PG_FUNCTION_ARGS) { @@ -128,6 +219,51 @@ btint4sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +static Datum +int4_decrement(Relation rel, Datum existing, bool *underflow) +{ + int32 iexisting = DatumGetInt32(existing); + + if (iexisting == PG_INT32_MIN) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return Int32GetDatum(iexisting - 1); +} + +static Datum +int4_increment(Relation rel, Datum existing, bool *overflow) +{ + int32 iexisting = DatumGetInt32(existing); + + if (iexisting == PG_INT32_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return Int32GetDatum(iexisting + 1); +} + +Datum +btint4skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = int4_decrement; + sksup->increment = int4_increment; + sksup->low_elem = Int32GetDatum(PG_INT32_MIN); + sksup->high_elem = Int32GetDatum(PG_INT32_MAX); + + PG_RETURN_VOID(); +} + Datum btint8cmp(PG_FUNCTION_ARGS) { @@ -171,6 +307,51 @@ btint8sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +static Datum +int8_decrement(Relation rel, Datum existing, bool *underflow) +{ + int64 iexisting = DatumGetInt64(existing); + + if (iexisting == PG_INT64_MIN) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return Int64GetDatum(iexisting - 1); +} + +static Datum +int8_increment(Relation rel, Datum existing, bool *overflow) +{ + int64 iexisting = DatumGetInt64(existing); + + if (iexisting == PG_INT64_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return Int64GetDatum(iexisting + 1); +} + +Datum +btint8skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = int8_decrement; + sksup->increment = int8_increment; + sksup->low_elem = Int64GetDatum(PG_INT64_MIN); + sksup->high_elem = Int64GetDatum(PG_INT64_MAX); + + PG_RETURN_VOID(); +} + Datum btint48cmp(PG_FUNCTION_ARGS) { @@ -292,6 +473,51 @@ btoidsortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +static Datum +oid_decrement(Relation rel, Datum existing, bool *underflow) +{ + Oid oexisting = DatumGetObjectId(existing); + + if (oexisting == InvalidOid) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return ObjectIdGetDatum(oexisting - 1); +} + +static Datum +oid_increment(Relation rel, Datum existing, bool *overflow) +{ + Oid oexisting = DatumGetObjectId(existing); + + if (oexisting == OID_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return ObjectIdGetDatum(oexisting + 1); +} + +Datum +btoidskipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = oid_decrement; + sksup->increment = oid_increment; + sksup->low_elem = ObjectIdGetDatum(InvalidOid); + sksup->high_elem = ObjectIdGetDatum(OID_MAX); + + PG_RETURN_VOID(); +} + Datum btoidvectorcmp(PG_FUNCTION_ARGS) { @@ -325,3 +551,50 @@ btcharcmp(PG_FUNCTION_ARGS) /* Be careful to compare chars as unsigned */ PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b)); } + +static Datum +char_decrement(Relation rel, Datum existing, bool *underflow) +{ + uint8 cexisting = UInt8GetDatum(existing); + + if (cexisting == 0) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return CharGetDatum((uint8) cexisting - 1); +} + +static Datum +char_increment(Relation rel, Datum existing, bool *overflow) +{ + uint8 cexisting = UInt8GetDatum(existing); + + if (cexisting == UCHAR_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return CharGetDatum((uint8) cexisting + 1); +} + +Datum +btcharskipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = char_decrement; + sksup->increment = char_increment; + + /* btcharcmp compares chars as unsigned */ + sksup->low_elem = UInt8GetDatum(0); + sksup->high_elem = UInt8GetDatum(UCHAR_MAX); + + PG_RETURN_VOID(); +} diff --git a/src/backend/access/nbtree/nbtdedup.c b/src/backend/access/nbtree/nbtdedup.c index 456d86b51c95d..08884116aecbe 100644 --- a/src/backend/access/nbtree/nbtdedup.c +++ b/src/backend/access/nbtree/nbtdedup.c @@ -3,7 +3,7 @@ * nbtdedup.c * Deduplicate or bottom-up delete items in Postgres btrees. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -84,7 +84,7 @@ _bt_dedup_pass(Relation rel, Buffer buf, IndexTuple newitem, Size newitemsz, state = (BTDedupState) palloc(sizeof(BTDedupStateData)); state->deduplicate = true; state->nmaxitems = 0; - state->maxpostingsize = Min(BTMaxItemSize(page) / 2, INDEX_SIZE_MASK); + state->maxpostingsize = Min(BTMaxItemSize / 2, INDEX_SIZE_MASK); /* Metadata about base tuple of current pending posting list */ state->base = NULL; state->baseoff = InvalidOffsetNumber; @@ -252,14 +252,14 @@ _bt_dedup_pass(Relation rel, Buffer buf, IndexTuple newitem, Size newitemsz, XLogBeginInsert(); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec_dedup, SizeOfBtreeDedup); + XLogRegisterData(&xlrec_dedup, SizeOfBtreeDedup); /* * The intervals array is not in the buffer, but pretend that it is. * When XLogInsert stores the whole buffer, the array need not be * stored too. */ - XLogRegisterBufData(0, (char *) state->intervals, + XLogRegisterBufData(0, state->intervals, state->nintervals * sizeof(BTDedupInterval)); recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_DEDUP); @@ -568,7 +568,7 @@ _bt_dedup_finish_pending(Page newpage, BTDedupState state) /* Use original, unchanged base tuple */ tuplesz = IndexTupleSize(state->base); Assert(tuplesz == MAXALIGN(IndexTupleSize(state->base))); - Assert(tuplesz <= BTMaxItemSize(newpage)); + Assert(tuplesz <= BTMaxItemSize); if (PageAddItem(newpage, (Item) state->base, tuplesz, tupoff, false, false) == InvalidOffsetNumber) elog(ERROR, "deduplication failed to add tuple to page"); @@ -588,7 +588,7 @@ _bt_dedup_finish_pending(Page newpage, BTDedupState state) state->intervals[state->nintervals].nitems = state->nitems; Assert(tuplesz == MAXALIGN(IndexTupleSize(final))); - Assert(tuplesz <= BTMaxItemSize(newpage)); + Assert(tuplesz <= BTMaxItemSize); if (PageAddItem(newpage, (Item) final, tuplesz, tupoff, false, false) == InvalidOffsetNumber) elog(ERROR, "deduplication failed to add tuple to page"); diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 7e8902e48cde7..aa82cede30aa4 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -3,7 +3,7 @@ * nbtinsert.c * Item insertion in Lehman and Yao btrees for Postgres. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -827,7 +827,7 @@ _bt_findinsertloc(Relation rel, opaque = BTPageGetOpaque(page); /* Check 1/3 of a page restriction */ - if (unlikely(insertstate->itemsz > BTMaxItemSize(page))) + if (unlikely(insertstate->itemsz > BTMaxItemSize)) _bt_check_third_page(rel, heapRel, itup_key->heapkeyspace, page, insertstate->itup); @@ -1320,7 +1320,7 @@ _bt_insertonpg(Relation rel, xlrec.offnum = newitemoff; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBtreeInsert); + XLogRegisterData(&xlrec, SizeOfBtreeInsert); if (isleaf && postingoff == 0) { @@ -1358,7 +1358,7 @@ _bt_insertonpg(Relation rel, XLogRegisterBuffer(2, metabuf, REGBUF_WILL_INIT | REGBUF_STANDARD); - XLogRegisterBufData(2, (char *) &xlmeta, + XLogRegisterBufData(2, &xlmeta, sizeof(xl_btree_metadata)); } } @@ -1367,7 +1367,7 @@ _bt_insertonpg(Relation rel, if (postingoff == 0) { /* Just log itup from caller */ - XLogRegisterBufData(0, (char *) itup, IndexTupleSize(itup)); + XLogRegisterBufData(0, itup, IndexTupleSize(itup)); } else { @@ -1381,8 +1381,8 @@ _bt_insertonpg(Relation rel, */ upostingoff = postingoff; - XLogRegisterBufData(0, (char *) &upostingoff, sizeof(uint16)); - XLogRegisterBufData(0, (char *) origitup, + XLogRegisterBufData(0, &upostingoff, sizeof(uint16)); + XLogRegisterBufData(0, origitup, IndexTupleSize(origitup)); } @@ -1720,7 +1720,7 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf, rbuf = _bt_allocbuf(rel, heaprel); rightpage = BufferGetPage(rbuf); rightpagenumber = BufferGetBlockNumber(rbuf); - /* rightpage was initialized by _bt_getbuf */ + /* rightpage was initialized by _bt_allocbuf */ ropaque = BTPageGetOpaque(rightpage); /* @@ -1979,7 +1979,7 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf, xlrec.postingoff = postingoff; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBtreeSplit); + XLogRegisterData(&xlrec, SizeOfBtreeSplit); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); XLogRegisterBuffer(1, rbuf, REGBUF_WILL_INIT); @@ -2017,13 +2017,13 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf, * newitem-logged case). */ if (newitemonleft && xlrec.postingoff == 0) - XLogRegisterBufData(0, (char *) newitem, newitemsz); + XLogRegisterBufData(0, newitem, newitemsz); else if (xlrec.postingoff != 0) { Assert(isleaf); Assert(newitemonleft || firstrightoff == newitemoff); Assert(newitemsz == IndexTupleSize(orignewitem)); - XLogRegisterBufData(0, (char *) orignewitem, newitemsz); + XLogRegisterBufData(0, orignewitem, newitemsz); } /* Log the left page's new high key */ @@ -2033,7 +2033,7 @@ _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf, itemid = PageGetItemId(origpage, P_HIKEY); lefthighkey = (IndexTuple) PageGetItem(origpage, itemid); } - XLogRegisterBufData(0, (char *) lefthighkey, + XLogRegisterBufData(0, lefthighkey, MAXALIGN(IndexTupleSize(lefthighkey))); /* @@ -2564,7 +2564,7 @@ _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf) xlrec.level = metad->btm_level; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfBtreeNewroot); + XLogRegisterData(&xlrec, SizeOfBtreeNewroot); XLogRegisterBuffer(0, rootbuf, REGBUF_WILL_INIT); XLogRegisterBuffer(1, lbuf, REGBUF_STANDARD); @@ -2579,7 +2579,7 @@ _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf) md.last_cleanup_num_delpages = metad->btm_last_cleanup_num_delpages; md.allequalimage = metad->btm_allequalimage; - XLogRegisterBufData(2, (char *) &md, sizeof(xl_btree_metadata)); + XLogRegisterBufData(2, &md, sizeof(xl_btree_metadata)); /* * Direct access to page is not good but faster - we should implement diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c index 01bbece6bfd9d..c79dd38ee18f3 100644 --- a/src/backend/access/nbtree/nbtpage.c +++ b/src/backend/access/nbtree/nbtpage.c @@ -4,7 +4,7 @@ * BTree-specific page management code for the Postgres btree access * method. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -299,7 +299,7 @@ _bt_set_cleanup_info(Relation rel, BlockNumber num_delpages) md.last_cleanup_num_delpages = num_delpages; md.allequalimage = metad->btm_allequalimage; - XLogRegisterBufData(0, (char *) &md, sizeof(xl_btree_metadata)); + XLogRegisterBufData(0, &md, sizeof(xl_btree_metadata)); recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_META_CLEANUP); @@ -488,12 +488,12 @@ _bt_getroot(Relation rel, Relation heaprel, int access) md.last_cleanup_num_delpages = 0; md.allequalimage = metad->btm_allequalimage; - XLogRegisterBufData(2, (char *) &md, sizeof(xl_btree_metadata)); + XLogRegisterBufData(2, &md, sizeof(xl_btree_metadata)); xlrec.rootblk = rootblkno; xlrec.level = 0; - XLogRegisterData((char *) &xlrec, SizeOfBtreeNewroot); + XLogRegisterData(&xlrec, SizeOfBtreeNewroot); recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_NEWROOT); @@ -948,7 +948,7 @@ _bt_allocbuf(Relation rel, Relation heaprel) RelationIsAccessibleInLogicalDecoding(heaprel); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec_reuse, SizeOfBtreeReusePage); + XLogRegisterData(&xlrec_reuse, SizeOfBtreeReusePage); XLogInsert(RM_BTREE_ID, XLOG_BTREE_REUSE_PAGE); } @@ -1234,15 +1234,15 @@ _bt_delitems_vacuum(Relation rel, Buffer buf, XLogBeginInsert(); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec_vacuum, SizeOfBtreeVacuum); + XLogRegisterData(&xlrec_vacuum, SizeOfBtreeVacuum); if (ndeletable > 0) - XLogRegisterBufData(0, (char *) deletable, + XLogRegisterBufData(0, deletable, ndeletable * sizeof(OffsetNumber)); if (nupdatable > 0) { - XLogRegisterBufData(0, (char *) updatedoffsets, + XLogRegisterBufData(0, updatedoffsets, nupdatable * sizeof(OffsetNumber)); XLogRegisterBufData(0, updatedbuf, updatedbuflen); } @@ -1353,15 +1353,15 @@ _bt_delitems_delete(Relation rel, Buffer buf, XLogBeginInsert(); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec_delete, SizeOfBtreeDelete); + XLogRegisterData(&xlrec_delete, SizeOfBtreeDelete); if (ndeletable > 0) - XLogRegisterBufData(0, (char *) deletable, + XLogRegisterBufData(0, deletable, ndeletable * sizeof(OffsetNumber)); if (nupdatable > 0) { - XLogRegisterBufData(0, (char *) updatedoffsets, + XLogRegisterBufData(0, updatedoffsets, nupdatable * sizeof(OffsetNumber)); XLogRegisterBufData(0, updatedbuf, updatedbuflen); } @@ -2269,7 +2269,7 @@ _bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf, xlrec.leftblk = opaque->btpo_prev; xlrec.rightblk = opaque->btpo_next; - XLogRegisterData((char *) &xlrec, SizeOfBtreeMarkPageHalfDead); + XLogRegisterData(&xlrec, SizeOfBtreeMarkPageHalfDead); recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_MARK_PAGE_HALFDEAD); @@ -2694,7 +2694,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno, xlrec.leafrightsib = leafrightsib; xlrec.leaftopparent = leaftopparent; - XLogRegisterData((char *) &xlrec, SizeOfBtreeUnlinkPage); + XLogRegisterData(&xlrec, SizeOfBtreeUnlinkPage); if (BufferIsValid(metabuf)) { @@ -2709,7 +2709,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno, xlmeta.last_cleanup_num_delpages = metad->btm_last_cleanup_num_delpages; xlmeta.allequalimage = metad->btm_allequalimage; - XLogRegisterBufData(4, (char *) &xlmeta, sizeof(xl_btree_metadata)); + XLogRegisterBufData(4, &xlmeta, sizeof(xl_btree_metadata)); xlinfo = XLOG_BTREE_UNLINK_PAGE_META; } else @@ -2953,7 +2953,7 @@ _bt_lock_subtree_parent(Relation rel, Relation heaprel, BlockNumber child, void _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly) { - int64 maxbufsize; + Size maxbufsize; /* * Don't bother with optimization in cleanup-only case -- we don't expect @@ -2969,12 +2969,13 @@ _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly) * int overflow here. */ vstate->bufsize = 256; - maxbufsize = (work_mem * 1024L) / sizeof(BTPendingFSM); - maxbufsize = Min(maxbufsize, INT_MAX); + maxbufsize = (work_mem * (Size) 1024) / sizeof(BTPendingFSM); maxbufsize = Min(maxbufsize, MaxAllocSize / sizeof(BTPendingFSM)); + /* BTVacState.maxbufsize has type int */ + maxbufsize = Min(maxbufsize, INT_MAX); /* Stay sane with small work_mem */ maxbufsize = Max(maxbufsize, vstate->bufsize); - vstate->maxbufsize = maxbufsize; + vstate->maxbufsize = (int) maxbufsize; /* Allocate buffer, indicate that there are currently 0 pending pages */ vstate->pendingpages = palloc(sizeof(BTPendingFSM) * vstate->bufsize); diff --git a/src/backend/access/nbtree/nbtpreprocesskeys.c b/src/backend/access/nbtree/nbtpreprocesskeys.c new file mode 100644 index 0000000000000..a136e4bbfdfb5 --- /dev/null +++ b/src/backend/access/nbtree/nbtpreprocesskeys.c @@ -0,0 +1,2526 @@ +/*------------------------------------------------------------------------- + * + * nbtpreprocesskeys.c + * Preprocessing for Postgres btree scan keys. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/access/nbtree/nbtpreprocesskeys.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/nbtree.h" +#include "lib/qunique.h" +#include "utils/array.h" +#include "utils/lsyscache.h" +#include "utils/memutils.h" + +typedef struct BTScanKeyPreproc +{ + ScanKey inkey; + int inkeyi; + int arrayidx; +} BTScanKeyPreproc; + +typedef struct BTSortArrayContext +{ + FmgrInfo *sortproc; + Oid collation; + bool reverse; +} BTSortArrayContext; + +static bool _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption); +static void _bt_mark_scankey_required(ScanKey skey); +static bool _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op, + ScanKey leftarg, ScanKey rightarg, + BTArrayKeyInfo *array, FmgrInfo *orderproc, + bool *result); +static bool _bt_compare_array_scankey_args(IndexScanDesc scan, + ScanKey arraysk, ScanKey skey, + FmgrInfo *orderproc, BTArrayKeyInfo *array, + bool *qual_ok); +static bool _bt_saoparray_shrink(IndexScanDesc scan, ScanKey arraysk, + ScanKey skey, FmgrInfo *orderproc, + BTArrayKeyInfo *array, bool *qual_ok); +static bool _bt_skiparray_shrink(IndexScanDesc scan, ScanKey skey, + BTArrayKeyInfo *array, bool *qual_ok); +static void _bt_skiparray_strat_adjust(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array); +static void _bt_skiparray_strat_decrement(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array); +static void _bt_skiparray_strat_increment(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array); +static ScanKey _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys); +static void _bt_preprocess_array_keys_final(IndexScanDesc scan, int *keyDataMap); +static int _bt_num_array_keys(IndexScanDesc scan, Oid *skip_eq_ops_out, + int *numSkipArrayKeys_out); +static Datum _bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, + Oid elemtype, StrategyNumber strat, + Datum *elems, int nelems); +static void _bt_setup_array_cmp(IndexScanDesc scan, ScanKey skey, Oid elemtype, + FmgrInfo *orderproc, FmgrInfo **sortprocp); +static int _bt_sort_array_elements(ScanKey skey, FmgrInfo *sortproc, + bool reverse, Datum *elems, int nelems); +static bool _bt_merge_arrays(IndexScanDesc scan, ScanKey skey, + FmgrInfo *sortproc, bool reverse, + Oid origelemtype, Oid nextelemtype, + Datum *elems_orig, int *nelems_orig, + Datum *elems_next, int nelems_next); +static int _bt_compare_array_elements(const void *a, const void *b, void *arg); + + +/* + * _bt_preprocess_keys() -- Preprocess scan keys + * + * The given search-type keys (taken from scan->keyData[]) + * are copied to so->keyData[] with possible transformation. + * scan->numberOfKeys is the number of input keys, so->numberOfKeys gets + * the number of output keys. Calling here a second or subsequent time + * (during the same btrescan) is a no-op. + * + * The output keys are marked with additional sk_flags bits beyond the + * system-standard bits supplied by the caller. The DESC and NULLS_FIRST + * indoption bits for the relevant index attribute are copied into the flags. + * Also, for a DESC column, we commute (flip) all the sk_strategy numbers + * so that the index sorts in the desired direction. + * + * One key purpose of this routine is to discover which scan keys must be + * satisfied to continue the scan. It also attempts to eliminate redundant + * keys and detect contradictory keys. (If the index opfamily provides + * incomplete sets of cross-type operators, we may fail to detect redundant + * or contradictory keys, but we can survive that.) + * + * The output keys must be sorted by index attribute. Presently we expect + * (but verify) that the input keys are already so sorted --- this is done + * by match_clauses_to_index() in indxpath.c. Some reordering of the keys + * within each attribute may be done as a byproduct of the processing here. + * That process must leave array scan keys (within an attribute) in the same + * order as corresponding entries from the scan's BTArrayKeyInfo array info. + * We might also construct skip array scan keys that weren't present in the + * original input keys; these are also output in standard attribute order. + * + * The output keys are marked with flags SK_BT_REQFWD and/or SK_BT_REQBKWD + * if they must be satisfied in order to continue the scan forward or backward + * respectively. _bt_checkkeys uses these flags. For example, if the quals + * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple + * (1,2,7), but we must continue the scan in case there are tuples (1,3,z). + * But once we reach tuples like (1,4,z) we can stop scanning because no + * later tuples could match. This is reflected by marking the x and y keys, + * but not the z key, with SK_BT_REQFWD. In general, the keys for leading + * attributes with "=" keys are marked both SK_BT_REQFWD and SK_BT_REQBKWD. + * For the first attribute without an "=" key, any "<" and "<=" keys are + * marked SK_BT_REQFWD while any ">" and ">=" keys are marked SK_BT_REQBKWD. + * This can be seen to be correct by considering the above example. + * + * If we never generated skip array scan keys, it would be possible for "gaps" + * to appear that make it unsafe to mark any subsequent input scan keys + * (copied from scan->keyData[]) as required to continue the scan. Prior to + * Postgres 18, a qual like "WHERE y = 4" always resulted in a full scan. + * This qual now becomes "WHERE x = ANY('{every possible x value}') and y = 4" + * on output. In other words, preprocessing now adds a skip array on "x". + * This has the potential to be much more efficient than a full index scan + * (though it behaves like a full scan when there's many distinct "x" values). + * + * If possible, redundant keys are eliminated: we keep only the tightest + * >/>= bound and the tightest />= or both + * 4::int AND x > 10::bigint", and we are unable to determine + * which key is more restrictive for lack of a suitable cross-type operator. + * _bt_first will arbitrarily pick one of the keys to do the initial + * positioning with. If it picks x > 4, then the x > 10 condition will fail + * until we reach index entries > 10; but we can't stop the scan just because + * x > 10 is failing. On the other hand, if we are scanning backwards, then + * failure of either key is indeed enough to stop the scan. (In general, when + * inequality keys are present, the initial-positioning code only promises to + * position before the first possible match, not exactly at the first match, + * for a forward scan; or after the last match for a backward scan.) + * + * As a byproduct of this work, we can detect contradictory quals such + * as "x = 1 AND x > 2". If we see that, we return so->qual_ok = false, + * indicating the scan need not be run at all since no tuples can match. + * (In this case we do not bother completing the output key array!) + * Again, missing cross-type operators might cause us to fail to prove the + * quals contradictory when they really are, but the scan will work correctly. + * + * Skip array = keys will even be generated in the presence of "contradictory" + * inequality quals when it'll enable marking later input quals as required. + * We'll merge any such inequalities into the generated skip array by setting + * its array.low_compare or array.high_compare key field. The resulting skip + * array will generate its array elements from a range that's constrained by + * any merged input inequalities (which won't get output in so->keyData[]). + * + * Row comparison keys currently have a couple of notable limitations. + * Right now we just transfer them into the preprocessed array without any + * editorialization. We can treat them the same as an ordinary inequality + * comparison on the row's first index column, for the purposes of the logic + * about required keys. Also, we are unable to merge a row comparison key + * into a skip array (only ordinary inequalities are merged). A key that + * comes after a Row comparison key is therefore never marked as required. + * + * Note: the reason we have to copy the preprocessed scan keys into private + * storage is that we are modifying the array based on comparisons of the + * key argument values, which could change on a rescan. Therefore we can't + * overwrite the source data. + */ +void +_bt_preprocess_keys(IndexScanDesc scan) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + int numberOfKeys = scan->numberOfKeys; + int16 *indoption = scan->indexRelation->rd_indoption; + int new_numberOfKeys; + int numberOfEqualCols; + ScanKey inkeys; + BTScanKeyPreproc xform[BTMaxStrategyNumber]; + bool test_result; + AttrNumber attno; + ScanKey arrayKeyData; + int *keyDataMap = NULL; + int arrayidx = 0; + + if (so->numberOfKeys > 0) + { + /* + * Only need to do preprocessing once per btrescan, at most. All + * calls after the first are handled as no-ops. + */ + return; + } + + /* initialize result variables */ + so->qual_ok = true; + so->numberOfKeys = 0; + + if (numberOfKeys < 1) + return; /* done if qual-less scan */ + + /* If any keys are SK_SEARCHARRAY type, set up array-key info */ + arrayKeyData = _bt_preprocess_array_keys(scan, &numberOfKeys); + if (!so->qual_ok) + { + /* unmatchable array, so give up */ + return; + } + + /* + * Treat arrayKeyData[] (a partially preprocessed copy of scan->keyData[]) + * as our input if _bt_preprocess_array_keys just allocated it, else just + * use scan->keyData[] + */ + if (arrayKeyData) + { + inkeys = arrayKeyData; + + /* Also maintain keyDataMap for remapping so->orderProcs[] later */ + keyDataMap = MemoryContextAlloc(so->arrayContext, + numberOfKeys * sizeof(int)); + + /* + * Also enlarge output array when it might otherwise not have room for + * a skip array's scan key + */ + if (numberOfKeys > scan->numberOfKeys) + so->keyData = repalloc(so->keyData, + numberOfKeys * sizeof(ScanKeyData)); + } + else + inkeys = scan->keyData; + + /* we check that input keys are correctly ordered */ + if (inkeys[0].sk_attno < 1) + elog(ERROR, "btree index keys must be ordered by attribute"); + + /* We can short-circuit most of the work if there's just one key */ + if (numberOfKeys == 1) + { + /* Apply indoption to scankey (might change sk_strategy!) */ + if (!_bt_fix_scankey_strategy(&inkeys[0], indoption)) + so->qual_ok = false; + memcpy(&so->keyData[0], &inkeys[0], sizeof(ScanKeyData)); + so->numberOfKeys = 1; + /* We can mark the qual as required if it's for first index col */ + if (inkeys[0].sk_attno == 1) + _bt_mark_scankey_required(&so->keyData[0]); + if (arrayKeyData) + { + /* + * Don't call _bt_preprocess_array_keys_final in this fast path + * (we'll miss out on the single value array transformation, but + * that's not nearly as important when there's only one scan key) + */ + Assert(so->keyData[0].sk_flags & SK_SEARCHARRAY); + Assert(so->keyData[0].sk_strategy != BTEqualStrategyNumber || + (so->arrayKeys[0].scan_key == 0 && + !(so->keyData[0].sk_flags & SK_BT_SKIP) && + OidIsValid(so->orderProcs[0].fn_oid))); + } + + return; + } + + /* + * Otherwise, do the full set of pushups. + */ + new_numberOfKeys = 0; + numberOfEqualCols = 0; + + /* + * Initialize for processing of keys for attr 1. + * + * xform[i] points to the currently best scan key of strategy type i+1; it + * is NULL if we haven't yet found such a key for this attr. + */ + attno = 1; + memset(xform, 0, sizeof(xform)); + + /* + * Loop iterates from 0 to numberOfKeys inclusive; we use the last pass to + * handle after-last-key processing. Actual exit from the loop is at the + * "break" statement below. + */ + for (int i = 0;; i++) + { + ScanKey inkey = inkeys + i; + int j; + + if (i < numberOfKeys) + { + /* Apply indoption to scankey (might change sk_strategy!) */ + if (!_bt_fix_scankey_strategy(inkey, indoption)) + { + /* NULL can't be matched, so give up */ + so->qual_ok = false; + return; + } + } + + /* + * If we are at the end of the keys for a particular attr, finish up + * processing and emit the cleaned-up keys. + */ + if (i == numberOfKeys || inkey->sk_attno != attno) + { + int priorNumberOfEqualCols = numberOfEqualCols; + + /* check input keys are correctly ordered */ + if (i < numberOfKeys && inkey->sk_attno < attno) + elog(ERROR, "btree index keys must be ordered by attribute"); + + /* + * If = has been specified, all other keys can be eliminated as + * redundant. Note that this is no less true if the = key is + * SEARCHARRAY; the only real difference is that the inequality + * key _becomes_ redundant by making _bt_compare_scankey_args + * eliminate the subset of elements that won't need to be matched + * (with SAOP arrays and skip arrays alike). + * + * If we have a case like "key = 1 AND key > 2", we set qual_ok to + * false and abandon further processing. We'll do the same thing + * given a case like "key IN (0, 1) AND key > 2". + * + * We also have to deal with the case of "key IS NULL", which is + * unsatisfiable in combination with any other index condition. By + * the time we get here, that's been classified as an equality + * check, and we've rejected any combination of it with a regular + * equality condition; but not with other types of conditions. + */ + if (xform[BTEqualStrategyNumber - 1].inkey) + { + ScanKey eq = xform[BTEqualStrategyNumber - 1].inkey; + BTArrayKeyInfo *array = NULL; + FmgrInfo *orderproc = NULL; + + if (arrayKeyData && (eq->sk_flags & SK_SEARCHARRAY)) + { + int eq_in_ikey, + eq_arrayidx; + + eq_in_ikey = xform[BTEqualStrategyNumber - 1].inkeyi; + eq_arrayidx = xform[BTEqualStrategyNumber - 1].arrayidx; + array = &so->arrayKeys[eq_arrayidx - 1]; + orderproc = so->orderProcs + eq_in_ikey; + + Assert(array->scan_key == eq_in_ikey); + Assert(OidIsValid(orderproc->fn_oid)); + } + + for (j = BTMaxStrategyNumber; --j >= 0;) + { + ScanKey chk = xform[j].inkey; + + if (!chk || j == (BTEqualStrategyNumber - 1)) + continue; + + if (eq->sk_flags & SK_SEARCHNULL) + { + /* IS NULL is contradictory to anything else */ + so->qual_ok = false; + return; + } + + if (_bt_compare_scankey_args(scan, chk, eq, chk, + array, orderproc, + &test_result)) + { + if (!test_result) + { + /* keys proven mutually contradictory */ + so->qual_ok = false; + return; + } + /* else discard the redundant non-equality key */ + xform[j].inkey = NULL; + xform[j].inkeyi = -1; + } + /* else, cannot determine redundancy, keep both keys */ + } + /* track number of attrs for which we have "=" keys */ + numberOfEqualCols++; + } + + /* try to keep only one of <, <= */ + if (xform[BTLessStrategyNumber - 1].inkey && + xform[BTLessEqualStrategyNumber - 1].inkey) + { + ScanKey lt = xform[BTLessStrategyNumber - 1].inkey; + ScanKey le = xform[BTLessEqualStrategyNumber - 1].inkey; + + if (_bt_compare_scankey_args(scan, le, lt, le, NULL, NULL, + &test_result)) + { + if (test_result) + xform[BTLessEqualStrategyNumber - 1].inkey = NULL; + else + xform[BTLessStrategyNumber - 1].inkey = NULL; + } + } + + /* try to keep only one of >, >= */ + if (xform[BTGreaterStrategyNumber - 1].inkey && + xform[BTGreaterEqualStrategyNumber - 1].inkey) + { + ScanKey gt = xform[BTGreaterStrategyNumber - 1].inkey; + ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1].inkey; + + if (_bt_compare_scankey_args(scan, ge, gt, ge, NULL, NULL, + &test_result)) + { + if (test_result) + xform[BTGreaterEqualStrategyNumber - 1].inkey = NULL; + else + xform[BTGreaterStrategyNumber - 1].inkey = NULL; + } + } + + /* + * Emit the cleaned-up keys into the so->keyData[] array, and then + * mark them if they are required. They are required (possibly + * only in one direction) if all attrs before this one had "=". + * + * In practice we'll rarely output non-required scan keys here; + * typically, _bt_preprocess_array_keys has already added "=" keys + * sufficient to form an unbroken series of "=" constraints on all + * attrs prior to the attr from the final scan->keyData[] key. + */ + for (j = BTMaxStrategyNumber; --j >= 0;) + { + if (xform[j].inkey) + { + ScanKey outkey = &so->keyData[new_numberOfKeys++]; + + memcpy(outkey, xform[j].inkey, sizeof(ScanKeyData)); + if (arrayKeyData) + keyDataMap[new_numberOfKeys - 1] = xform[j].inkeyi; + if (priorNumberOfEqualCols == attno - 1) + _bt_mark_scankey_required(outkey); + } + } + + /* + * Exit loop here if done. + */ + if (i == numberOfKeys) + break; + + /* Re-initialize for new attno */ + attno = inkey->sk_attno; + memset(xform, 0, sizeof(xform)); + } + + /* check strategy this key's operator corresponds to */ + j = inkey->sk_strategy - 1; + + /* if row comparison, push it directly to the output array */ + if (inkey->sk_flags & SK_ROW_HEADER) + { + ScanKey outkey = &so->keyData[new_numberOfKeys++]; + + memcpy(outkey, inkey, sizeof(ScanKeyData)); + if (arrayKeyData) + keyDataMap[new_numberOfKeys - 1] = i; + if (numberOfEqualCols == attno - 1) + _bt_mark_scankey_required(outkey); + + /* + * We don't support RowCompare using equality; such a qual would + * mess up the numberOfEqualCols tracking. + */ + Assert(j != (BTEqualStrategyNumber - 1)); + continue; + } + + if (inkey->sk_strategy == BTEqualStrategyNumber && + (inkey->sk_flags & SK_SEARCHARRAY)) + { + /* must track how input scan keys map to arrays */ + Assert(arrayKeyData); + arrayidx++; + } + + /* + * have we seen a scan key for this same attribute and using this same + * operator strategy before now? + */ + if (xform[j].inkey == NULL) + { + /* nope, so this scan key wins by default (at least for now) */ + xform[j].inkey = inkey; + xform[j].inkeyi = i; + xform[j].arrayidx = arrayidx; + } + else + { + FmgrInfo *orderproc = NULL; + BTArrayKeyInfo *array = NULL; + + /* + * Seen one of these before, so keep only the more restrictive key + * if possible + */ + if (j == (BTEqualStrategyNumber - 1) && arrayKeyData) + { + /* + * Have to set up array keys + */ + if (inkey->sk_flags & SK_SEARCHARRAY) + { + array = &so->arrayKeys[arrayidx - 1]; + orderproc = so->orderProcs + i; + + Assert(array->scan_key == i); + Assert(OidIsValid(orderproc->fn_oid)); + Assert(!(inkey->sk_flags & SK_BT_SKIP)); + } + else if (xform[j].inkey->sk_flags & SK_SEARCHARRAY) + { + array = &so->arrayKeys[xform[j].arrayidx - 1]; + orderproc = so->orderProcs + xform[j].inkeyi; + + Assert(array->scan_key == xform[j].inkeyi); + Assert(OidIsValid(orderproc->fn_oid)); + Assert(!(xform[j].inkey->sk_flags & SK_BT_SKIP)); + } + + /* + * Both scan keys might have arrays, in which case we'll + * arbitrarily pass only one of the arrays. That won't + * matter, since _bt_compare_scankey_args is aware that two + * SEARCHARRAY scan keys mean that _bt_preprocess_array_keys + * failed to eliminate redundant arrays through array merging. + * _bt_compare_scankey_args just returns false when it sees + * this; it won't even try to examine either array. + */ + } + + if (_bt_compare_scankey_args(scan, inkey, inkey, xform[j].inkey, + array, orderproc, &test_result)) + { + /* Have all we need to determine redundancy */ + if (test_result) + { + /* + * New key is more restrictive, and so replaces old key... + */ + if (j != (BTEqualStrategyNumber - 1) || + !(xform[j].inkey->sk_flags & SK_SEARCHARRAY)) + { + xform[j].inkey = inkey; + xform[j].inkeyi = i; + xform[j].arrayidx = arrayidx; + } + else + { + /* + * ...unless we have to keep the old key because it's + * an array that rendered the new key redundant. We + * need to make sure that we don't throw away an array + * scan key. _bt_preprocess_array_keys_final expects + * us to keep all of the arrays that weren't already + * eliminated by _bt_preprocess_array_keys earlier on. + */ + Assert(!(inkey->sk_flags & SK_SEARCHARRAY)); + } + } + else if (j == (BTEqualStrategyNumber - 1)) + { + /* key == a && key == b, but a != b */ + so->qual_ok = false; + return; + } + /* else old key is more restrictive, keep it */ + } + else + { + /* + * We can't determine which key is more restrictive. Push + * xform[j] directly to the output array, then set xform[j] to + * the new scan key. + * + * Note: We do things this way around so that our arrays are + * always in the same order as their corresponding scan keys, + * even with incomplete opfamilies. _bt_advance_array_keys + * depends on this. + */ + ScanKey outkey = &so->keyData[new_numberOfKeys++]; + + memcpy(outkey, xform[j].inkey, sizeof(ScanKeyData)); + if (arrayKeyData) + keyDataMap[new_numberOfKeys - 1] = xform[j].inkeyi; + if (numberOfEqualCols == attno - 1) + _bt_mark_scankey_required(outkey); + xform[j].inkey = inkey; + xform[j].inkeyi = i; + xform[j].arrayidx = arrayidx; + } + } + } + + so->numberOfKeys = new_numberOfKeys; + + /* + * Now that we've built a temporary mapping from so->keyData[] (output + * scan keys) to arrayKeyData[] (our input scan keys), fix array->scan_key + * references. Also consolidate the so->orderProcs[] array such that it + * can be subscripted using so->keyData[]-wise offsets. + */ + if (arrayKeyData) + _bt_preprocess_array_keys_final(scan, keyDataMap); + + /* Could pfree arrayKeyData/keyDataMap now, but not worth the cycles */ +} + +/* + * Adjust a scankey's strategy and flags setting as needed for indoptions. + * + * We copy the appropriate indoption value into the scankey sk_flags + * (shifting to avoid clobbering system-defined flag bits). Also, if + * the DESC option is set, commute (flip) the operator strategy number. + * + * A secondary purpose is to check for IS NULL/NOT NULL scankeys and set up + * the strategy field correctly for them. + * + * Lastly, for ordinary scankeys (not IS NULL/NOT NULL), we check for a + * NULL comparison value. Since all btree operators are assumed strict, + * a NULL means that the qual cannot be satisfied. We return true if the + * comparison value isn't NULL, or false if the scan should be abandoned. + * + * This function is applied to the *input* scankey structure; therefore + * on a rescan we will be looking at already-processed scankeys. Hence + * we have to be careful not to re-commute the strategy if we already did it. + * It's a bit ugly to modify the caller's copy of the scankey but in practice + * there shouldn't be any problem, since the index's indoptions are certainly + * not going to change while the scankey survives. + */ +static bool +_bt_fix_scankey_strategy(ScanKey skey, int16 *indoption) +{ + int addflags; + + addflags = indoption[skey->sk_attno - 1] << SK_BT_INDOPTION_SHIFT; + + /* + * We treat all btree operators as strict (even if they're not so marked + * in pg_proc). This means that it is impossible for an operator condition + * with a NULL comparison constant to succeed, and we can reject it right + * away. + * + * However, we now also support "x IS NULL" clauses as search conditions, + * so in that case keep going. The planner has not filled in any + * particular strategy in this case, so set it to BTEqualStrategyNumber + * --- we can treat IS NULL as an equality operator for purposes of search + * strategy. + * + * Likewise, "x IS NOT NULL" is supported. We treat that as either "less + * than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS + * FIRST index. + * + * Note: someday we might have to fill in sk_collation from the index + * column's collation. At the moment this is a non-issue because we'll + * never actually call the comparison operator on a NULL. + */ + if (skey->sk_flags & SK_ISNULL) + { + /* SK_ISNULL shouldn't be set in a row header scankey */ + Assert(!(skey->sk_flags & SK_ROW_HEADER)); + + /* Set indoption flags in scankey (might be done already) */ + skey->sk_flags |= addflags; + + /* Set correct strategy for IS NULL or NOT NULL search */ + if (skey->sk_flags & SK_SEARCHNULL) + { + skey->sk_strategy = BTEqualStrategyNumber; + skey->sk_subtype = InvalidOid; + skey->sk_collation = InvalidOid; + } + else if (skey->sk_flags & SK_SEARCHNOTNULL) + { + if (skey->sk_flags & SK_BT_NULLS_FIRST) + skey->sk_strategy = BTGreaterStrategyNumber; + else + skey->sk_strategy = BTLessStrategyNumber; + skey->sk_subtype = InvalidOid; + skey->sk_collation = InvalidOid; + } + else + { + /* regular qual, so it cannot be satisfied */ + return false; + } + + /* Needn't do the rest */ + return true; + } + + /* Adjust strategy for DESC, if we didn't already */ + if ((addflags & SK_BT_DESC) && !(skey->sk_flags & SK_BT_DESC)) + skey->sk_strategy = BTCommuteStrategyNumber(skey->sk_strategy); + skey->sk_flags |= addflags; + + /* If it's a row header, fix row member flags and strategies similarly */ + if (skey->sk_flags & SK_ROW_HEADER) + { + ScanKey subkey = (ScanKey) DatumGetPointer(skey->sk_argument); + + if (subkey->sk_flags & SK_ISNULL) + { + /* First row member is NULL, so RowCompare is unsatisfiable */ + Assert(subkey->sk_flags & SK_ROW_MEMBER); + return false; + } + + for (;;) + { + Assert(subkey->sk_flags & SK_ROW_MEMBER); + addflags = indoption[subkey->sk_attno - 1] << SK_BT_INDOPTION_SHIFT; + if ((addflags & SK_BT_DESC) && !(subkey->sk_flags & SK_BT_DESC)) + subkey->sk_strategy = BTCommuteStrategyNumber(subkey->sk_strategy); + subkey->sk_flags |= addflags; + if (subkey->sk_flags & SK_ROW_END) + break; + subkey++; + } + } + + return true; +} + +/* + * Mark a scankey as "required to continue the scan". + * + * Depending on the operator type, the key may be required for both scan + * directions or just one. Also, if the key is a row comparison header, + * we have to mark its first subsidiary ScanKey as required. (Subsequent + * subsidiary ScanKeys are normally for lower-order columns, and thus + * cannot be required, since they're after the first non-equality scankey.) + * + * Note: when we set required-key flag bits in a subsidiary scankey, we are + * scribbling on a data structure belonging to the index AM's caller, not on + * our private copy. This should be OK because the marking will not change + * from scan to scan within a query, and so we'd just re-mark the same way + * anyway on a rescan. Something to keep an eye on though. + */ +static void +_bt_mark_scankey_required(ScanKey skey) +{ + int addflags; + + switch (skey->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + addflags = SK_BT_REQFWD; + break; + case BTEqualStrategyNumber: + addflags = SK_BT_REQFWD | SK_BT_REQBKWD; + break; + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + addflags = SK_BT_REQBKWD; + break; + default: + elog(ERROR, "unrecognized StrategyNumber: %d", + (int) skey->sk_strategy); + addflags = 0; /* keep compiler quiet */ + break; + } + + skey->sk_flags |= addflags; + + if (skey->sk_flags & SK_ROW_HEADER) + { + ScanKey subkey = (ScanKey) DatumGetPointer(skey->sk_argument); + + /* First subkey should be same column/operator as the header */ + Assert(subkey->sk_flags & SK_ROW_MEMBER); + Assert(subkey->sk_attno == skey->sk_attno); + Assert(subkey->sk_strategy == skey->sk_strategy); + subkey->sk_flags |= addflags; + } +} + +/* + * Compare two scankey values using a specified operator. + * + * The test we want to perform is logically "leftarg op rightarg", where + * leftarg and rightarg are the sk_argument values in those ScanKeys, and + * the comparison operator is the one in the op ScanKey. However, in + * cross-data-type situations we may need to look up the correct operator in + * the index's opfamily: it is the one having amopstrategy = op->sk_strategy + * and amoplefttype/amoprighttype equal to the two argument datatypes. + * + * If the opfamily doesn't supply a complete set of cross-type operators we + * may not be able to make the comparison. If we can make the comparison + * we store the operator result in *result and return true. We return false + * if the comparison could not be made. + * + * If either leftarg or rightarg are an array, we'll apply array-specific + * rules to determine which array elements are redundant on behalf of caller. + * It is up to our caller to save whichever of the two scan keys is the array, + * and discard the non-array scan key (the non-array scan key is guaranteed to + * be redundant with any complete opfamily). Caller isn't expected to call + * here with a pair of array scan keys provided we're dealing with a complete + * opfamily (_bt_preprocess_array_keys will merge array keys together to make + * sure of that). + * + * Note: we'll also shrink caller's array as needed to eliminate redundant + * array elements. One reason why caller should prefer to discard non-array + * scan keys is so that we'll have the opportunity to shrink the array + * multiple times, in multiple calls (for each of several other scan keys on + * the same index attribute). + * + * Note: op always points at the same ScanKey as either leftarg or rightarg. + * Since we don't scribble on the scankeys themselves, this aliasing should + * cause no trouble. + * + * Note: this routine needs to be insensitive to any DESC option applied + * to the index column. For example, "x < 4" is a tighter constraint than + * "x < 5" regardless of which way the index is sorted. + */ +static bool +_bt_compare_scankey_args(IndexScanDesc scan, ScanKey op, + ScanKey leftarg, ScanKey rightarg, + BTArrayKeyInfo *array, FmgrInfo *orderproc, + bool *result) +{ + Relation rel = scan->indexRelation; + Oid lefttype, + righttype, + optype, + opcintype, + cmp_op; + StrategyNumber strat; + + Assert(!((leftarg->sk_flags | rightarg->sk_flags) & + (SK_ROW_HEADER | SK_ROW_MEMBER))); + + /* + * First, deal with cases where one or both args are NULL. This should + * only happen when the scankeys represent IS NULL/NOT NULL conditions. + */ + if ((leftarg->sk_flags | rightarg->sk_flags) & SK_ISNULL) + { + bool leftnull, + rightnull; + + /* Handle skip array comparison with IS NOT NULL scan key */ + if ((leftarg->sk_flags | rightarg->sk_flags) & SK_BT_SKIP) + { + /* Shouldn't generate skip array in presence of IS NULL key */ + Assert(!((leftarg->sk_flags | rightarg->sk_flags) & SK_SEARCHNULL)); + Assert((leftarg->sk_flags | rightarg->sk_flags) & SK_SEARCHNOTNULL); + + /* Skip array will have no NULL element/IS NULL scan key */ + Assert(array->num_elems == -1); + array->null_elem = false; + + /* IS NOT NULL key (could be leftarg or rightarg) now redundant */ + *result = true; + return true; + } + + if (leftarg->sk_flags & SK_ISNULL) + { + Assert(leftarg->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)); + leftnull = true; + } + else + leftnull = false; + if (rightarg->sk_flags & SK_ISNULL) + { + Assert(rightarg->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)); + rightnull = true; + } + else + rightnull = false; + + /* + * We treat NULL as either greater than or less than all other values. + * Since true > false, the tests below work correctly for NULLS LAST + * logic. If the index is NULLS FIRST, we need to flip the strategy. + */ + strat = op->sk_strategy; + if (op->sk_flags & SK_BT_NULLS_FIRST) + strat = BTCommuteStrategyNumber(strat); + + switch (strat) + { + case BTLessStrategyNumber: + *result = (leftnull < rightnull); + break; + case BTLessEqualStrategyNumber: + *result = (leftnull <= rightnull); + break; + case BTEqualStrategyNumber: + *result = (leftnull == rightnull); + break; + case BTGreaterEqualStrategyNumber: + *result = (leftnull >= rightnull); + break; + case BTGreaterStrategyNumber: + *result = (leftnull > rightnull); + break; + default: + elog(ERROR, "unrecognized StrategyNumber: %d", (int) strat); + *result = false; /* keep compiler quiet */ + break; + } + return true; + } + + /* + * If either leftarg or rightarg are equality-type array scankeys, we need + * specialized handling (since by now we know that IS NULL wasn't used) + */ + if (array) + { + bool leftarray, + rightarray; + + leftarray = ((leftarg->sk_flags & SK_SEARCHARRAY) && + leftarg->sk_strategy == BTEqualStrategyNumber); + rightarray = ((rightarg->sk_flags & SK_SEARCHARRAY) && + rightarg->sk_strategy == BTEqualStrategyNumber); + + /* + * _bt_preprocess_array_keys is responsible for merging together array + * scan keys, and will do so whenever the opfamily has the required + * cross-type support. If it failed to do that, we handle it just + * like the case where we can't make the comparison ourselves. + */ + if (leftarray && rightarray) + { + /* Can't make the comparison */ + *result = false; /* suppress compiler warnings */ + Assert(!((leftarg->sk_flags | rightarg->sk_flags) & SK_BT_SKIP)); + return false; + } + + /* + * Otherwise we need to determine if either one of leftarg or rightarg + * uses an array, then pass this through to a dedicated helper + * function. + */ + if (leftarray) + return _bt_compare_array_scankey_args(scan, leftarg, rightarg, + orderproc, array, result); + else if (rightarray) + return _bt_compare_array_scankey_args(scan, rightarg, leftarg, + orderproc, array, result); + + /* FALL THRU */ + } + + /* + * The opfamily we need to worry about is identified by the index column. + */ + Assert(leftarg->sk_attno == rightarg->sk_attno); + + opcintype = rel->rd_opcintype[leftarg->sk_attno - 1]; + + /* + * Determine the actual datatypes of the ScanKey arguments. We have to + * support the convention that sk_subtype == InvalidOid means the opclass + * input type; this is a hack to simplify life for ScanKeyInit(). + */ + lefttype = leftarg->sk_subtype; + if (lefttype == InvalidOid) + lefttype = opcintype; + righttype = rightarg->sk_subtype; + if (righttype == InvalidOid) + righttype = opcintype; + optype = op->sk_subtype; + if (optype == InvalidOid) + optype = opcintype; + + /* + * If leftarg and rightarg match the types expected for the "op" scankey, + * we can use its already-looked-up comparison function. + */ + if (lefttype == opcintype && righttype == optype) + { + *result = DatumGetBool(FunctionCall2Coll(&op->sk_func, + op->sk_collation, + leftarg->sk_argument, + rightarg->sk_argument)); + return true; + } + + /* + * Otherwise, we need to go to the syscache to find the appropriate + * operator. (This cannot result in infinite recursion, since no + * indexscan initiated by syscache lookup will use cross-data-type + * operators.) + * + * If the sk_strategy was flipped by _bt_fix_scankey_strategy, we have to + * un-flip it to get the correct opfamily member. + */ + strat = op->sk_strategy; + if (op->sk_flags & SK_BT_DESC) + strat = BTCommuteStrategyNumber(strat); + + cmp_op = get_opfamily_member(rel->rd_opfamily[leftarg->sk_attno - 1], + lefttype, + righttype, + strat); + if (OidIsValid(cmp_op)) + { + RegProcedure cmp_proc = get_opcode(cmp_op); + + if (RegProcedureIsValid(cmp_proc)) + { + *result = DatumGetBool(OidFunctionCall2Coll(cmp_proc, + op->sk_collation, + leftarg->sk_argument, + rightarg->sk_argument)); + return true; + } + } + + /* Can't make the comparison */ + *result = false; /* suppress compiler warnings */ + return false; +} + +/* + * Compare an array scan key to a scalar scan key, eliminating contradictory + * array elements such that the scalar scan key becomes redundant. + * + * If the opfamily is incomplete we may not be able to determine which + * elements are contradictory. When we return true we'll have validly set + * *qual_ok, guaranteeing that at least the scalar scan key can be considered + * redundant. We return false if the comparison could not be made (caller + * must keep both scan keys when this happens). + * + * Note: it's up to caller to deal with IS [NOT] NULL scan keys, as well as + * row comparison scan keys. We only deal with scalar scan keys. + */ +static bool +_bt_compare_array_scankey_args(IndexScanDesc scan, ScanKey arraysk, ScanKey skey, + FmgrInfo *orderproc, BTArrayKeyInfo *array, + bool *qual_ok) +{ + Assert(arraysk->sk_attno == skey->sk_attno); + Assert(!(arraysk->sk_flags & (SK_ISNULL | SK_ROW_HEADER | SK_ROW_MEMBER))); + Assert((arraysk->sk_flags & SK_SEARCHARRAY) && + arraysk->sk_strategy == BTEqualStrategyNumber); + /* don't expect to have to deal with NULLs/row comparison scan keys */ + Assert(!(skey->sk_flags & (SK_ISNULL | SK_ROW_HEADER | SK_ROW_MEMBER))); + Assert(!(skey->sk_flags & SK_SEARCHARRAY) || + skey->sk_strategy != BTEqualStrategyNumber); + + /* + * Just call the appropriate helper function based on whether it's a SAOP + * array or a skip array. Both helpers will set *qual_ok in passing. + */ + if (array->num_elems != -1) + return _bt_saoparray_shrink(scan, arraysk, skey, orderproc, array, + qual_ok); + else + return _bt_skiparray_shrink(scan, skey, array, qual_ok); +} + +/* + * Preprocessing of SAOP array scan key, used to determine which array + * elements are eliminated as contradictory by a non-array scalar key. + * + * _bt_compare_array_scankey_args helper function. + * + * Array elements can be eliminated as contradictory when excluded by some + * other operator on the same attribute. For example, with an index scan qual + * "WHERE a IN (1, 2, 3) AND a < 2", all array elements except the value "1" + * are eliminated, and the < scan key is eliminated as redundant. Cases where + * every array element is eliminated by a redundant scalar scan key have an + * unsatisfiable qual, which we handle by setting *qual_ok=false for caller. + */ +static bool +_bt_saoparray_shrink(IndexScanDesc scan, ScanKey arraysk, ScanKey skey, + FmgrInfo *orderproc, BTArrayKeyInfo *array, bool *qual_ok) +{ + Relation rel = scan->indexRelation; + Oid opcintype = rel->rd_opcintype[arraysk->sk_attno - 1]; + int cmpresult = 0, + cmpexact = 0, + matchelem, + new_nelems = 0; + FmgrInfo crosstypeproc; + FmgrInfo *orderprocp = orderproc; + + Assert(array->num_elems > 0); + Assert(!(arraysk->sk_flags & SK_BT_SKIP)); + + /* + * _bt_binsrch_array_skey searches an array for the entry best matching a + * datum of opclass input type for the index's attribute (on-disk type). + * We can reuse the array's ORDER proc whenever the non-array scan key's + * type is a match for the corresponding attribute's input opclass type. + * Otherwise, we have to do another ORDER proc lookup so that our call to + * _bt_binsrch_array_skey applies the correct comparator. + * + * Note: we have to support the convention that sk_subtype == InvalidOid + * means the opclass input type; this is a hack to simplify life for + * ScanKeyInit(). + */ + if (skey->sk_subtype != opcintype && skey->sk_subtype != InvalidOid) + { + RegProcedure cmp_proc; + Oid arraysk_elemtype; + + /* + * Need an ORDER proc lookup to detect redundancy/contradictoriness + * with this pair of scankeys. + * + * Scalar scan key's argument will be passed to _bt_compare_array_skey + * as its tupdatum/lefthand argument (rhs arg is for array elements). + */ + arraysk_elemtype = arraysk->sk_subtype; + if (arraysk_elemtype == InvalidOid) + arraysk_elemtype = rel->rd_opcintype[arraysk->sk_attno - 1]; + cmp_proc = get_opfamily_proc(rel->rd_opfamily[arraysk->sk_attno - 1], + skey->sk_subtype, arraysk_elemtype, + BTORDER_PROC); + if (!RegProcedureIsValid(cmp_proc)) + { + /* Can't make the comparison */ + *qual_ok = false; /* suppress compiler warnings */ + return false; + } + + /* We have all we need to determine redundancy/contradictoriness */ + orderprocp = &crosstypeproc; + fmgr_info(cmp_proc, orderprocp); + } + + matchelem = _bt_binsrch_array_skey(orderprocp, false, + NoMovementScanDirection, + skey->sk_argument, false, array, + arraysk, &cmpresult); + + switch (skey->sk_strategy) + { + case BTLessStrategyNumber: + cmpexact = 1; /* exclude exact match, if any */ + /* FALL THRU */ + case BTLessEqualStrategyNumber: + if (cmpresult >= cmpexact) + matchelem++; + /* Resize, keeping elements from the start of the array */ + new_nelems = matchelem; + break; + case BTEqualStrategyNumber: + if (cmpresult != 0) + { + /* qual is unsatisfiable */ + new_nelems = 0; + } + else + { + /* Shift matching element to the start of the array, resize */ + array->elem_values[0] = array->elem_values[matchelem]; + new_nelems = 1; + } + break; + case BTGreaterEqualStrategyNumber: + cmpexact = 1; /* include exact match, if any */ + /* FALL THRU */ + case BTGreaterStrategyNumber: + if (cmpresult >= cmpexact) + matchelem++; + /* Shift matching elements to the start of the array, resize */ + new_nelems = array->num_elems - matchelem; + memmove(array->elem_values, array->elem_values + matchelem, + sizeof(Datum) * new_nelems); + break; + default: + elog(ERROR, "unrecognized StrategyNumber: %d", + (int) skey->sk_strategy); + break; + } + + Assert(new_nelems >= 0); + Assert(new_nelems <= array->num_elems); + + array->num_elems = new_nelems; + *qual_ok = new_nelems > 0; + + return true; +} + +/* + * Preprocessing of skip array scan key, used to determine redundancy against + * a non-array scalar scan key (must be an inequality). + * + * _bt_compare_array_scankey_args helper function. + * + * Skip arrays work by procedurally generating their elements as needed, so we + * just store the inequality as the skip array's low_compare or high_compare + * (except when there's already a more restrictive low_compare/high_compare). + * The array's final elements are the range of values that still satisfy the + * array's final low_compare and high_compare. + */ +static bool +_bt_skiparray_shrink(IndexScanDesc scan, ScanKey skey, BTArrayKeyInfo *array, + bool *qual_ok) +{ + bool test_result; + + Assert(array->num_elems == -1); + + /* + * Array's index attribute will be constrained by a strict operator/key. + * Array must not "contain a NULL element" (i.e. the scan must not apply + * "IS NULL" qual when it reaches the end of the index that stores NULLs). + */ + array->null_elem = false; + *qual_ok = true; + + /* + * Consider if we should treat caller's scalar scan key as the skip + * array's high_compare or low_compare. + * + * In general the current array element must either be a copy of a value + * taken from an index tuple, or a derivative value generated by opclass's + * skip support function. That way the scan can always safely assume that + * it's okay to use the only-input-opclass-type proc from so->orderProcs[] + * (they can be cross-type with SAOP arrays, but never with skip arrays). + * + * This approach is enabled by MINVAL/MAXVAL sentinel key markings, which + * can be thought of as representing either the lowest or highest matching + * array element (excluding the NULL element, where applicable, though as + * just discussed it isn't applicable to this range skip array anyway). + * Array keys marked MINVAL/MAXVAL never have a valid datum in their + * sk_argument field. The scan directly applies the array's low_compare + * key when it encounters MINVAL in the array key proper (just as it + * applies high_compare when it sees MAXVAL set in the array key proper). + * The scan must never use the array's so->orderProcs[] proc against + * low_compare's/high_compare's sk_argument, either (so->orderProcs[] is + * only intended to be used with rhs datums from the array proper/index). + */ + switch (skey->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + if (array->high_compare) + { + /* replace existing high_compare with caller's key? */ + if (!_bt_compare_scankey_args(scan, array->high_compare, skey, + array->high_compare, NULL, NULL, + &test_result)) + return false; /* can't determine more restrictive key */ + + if (!test_result) + return true; /* no, just discard caller's key */ + + /* yes, replace existing high_compare with caller's key */ + } + + /* caller's key becomes skip array's high_compare */ + array->high_compare = skey; + break; + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + if (array->low_compare) + { + /* replace existing low_compare with caller's key? */ + if (!_bt_compare_scankey_args(scan, array->low_compare, skey, + array->low_compare, NULL, NULL, + &test_result)) + return false; /* can't determine more restrictive key */ + + if (!test_result) + return true; /* no, just discard caller's key */ + + /* yes, replace existing low_compare with caller's key */ + } + + /* caller's key becomes skip array's low_compare */ + array->low_compare = skey; + break; + case BTEqualStrategyNumber: + default: + elog(ERROR, "unrecognized StrategyNumber: %d", + (int) skey->sk_strategy); + break; + } + + return true; +} + +/* + * Applies the opfamily's skip support routine to convert the skip array's > + * low_compare key (if any) into a >= key, and to convert its < high_compare + * key (if any) into a <= key. Decrements the high_compare key's sk_argument, + * and/or increments the low_compare key's sk_argument (also adjusts their + * operator strategies, while changing the operator as appropriate). + * + * This optional optimization reduces the number of descents required within + * _bt_first. Whenever _bt_first is called with a skip array whose current + * array element is the sentinel value MINVAL, using a transformed >= key + * instead of using the original > key makes it safe to include lower-order + * scan keys in the insertion scan key (there must be lower-order scan keys + * after the skip array). We will avoid an extra _bt_first to find the first + * value in the index > sk_argument -- at least when the first real matching + * value in the index happens to be an exact match for the sk_argument value + * that we produced here by incrementing the original input key's sk_argument. + * (Backwards scans derive the same benefit when they encounter the sentinel + * value MAXVAL, by converting the high_compare key from < to <=.) + * + * Note: The transformation is only correct when it cannot allow the scan to + * overlook matching tuples, but we don't have enough semantic information to + * safely make sure that can't happen during scans with cross-type operators. + * That's why we'll never apply the transformation in cross-type scenarios. + * For example, if we attempted to convert "sales_ts > '2024-01-01'::date" + * into "sales_ts >= '2024-01-02'::date" given a "sales_ts" attribute whose + * input opclass is timestamp_ops, the scan would overlook almost all (or all) + * tuples for sales that fell on '2024-01-01'. + * + * Note: We can safely modify array->low_compare/array->high_compare in place + * because they just point to copies of our scan->keyData[] input scan keys + * (namely the copies returned by _bt_preprocess_array_keys to be used as + * input into the standard preprocessing steps in _bt_preprocess_keys). + * Everything will be reset if there's a rescan. + */ +static void +_bt_skiparray_strat_adjust(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + MemoryContext oldContext; + + /* + * Called last among all preprocessing steps, when the skip array's final + * low_compare and high_compare have both been chosen + */ + Assert(arraysk->sk_flags & SK_BT_SKIP); + Assert(array->num_elems == -1 && !array->null_elem && array->sksup); + + oldContext = MemoryContextSwitchTo(so->arrayContext); + + if (array->high_compare && + array->high_compare->sk_strategy == BTLessStrategyNumber) + _bt_skiparray_strat_decrement(scan, arraysk, array); + + if (array->low_compare && + array->low_compare->sk_strategy == BTGreaterStrategyNumber) + _bt_skiparray_strat_increment(scan, arraysk, array); + + MemoryContextSwitchTo(oldContext); +} + +/* + * Convert skip array's > low_compare key into a >= key + */ +static void +_bt_skiparray_strat_decrement(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array) +{ + Relation rel = scan->indexRelation; + Oid opfamily = rel->rd_opfamily[arraysk->sk_attno - 1], + opcintype = rel->rd_opcintype[arraysk->sk_attno - 1], + leop; + RegProcedure cmp_proc; + ScanKey high_compare = array->high_compare; + Datum orig_sk_argument = high_compare->sk_argument, + new_sk_argument; + bool uflow; + + Assert(high_compare->sk_strategy == BTLessStrategyNumber); + + /* + * Only perform the transformation when the operator type matches the + * index attribute's input opclass type + */ + if (high_compare->sk_subtype != opcintype && + high_compare->sk_subtype != InvalidOid) + return; + + /* Decrement, handling underflow by marking the qual unsatisfiable */ + new_sk_argument = array->sksup->decrement(rel, orig_sk_argument, &uflow); + if (uflow) + { + BTScanOpaque so = (BTScanOpaque) scan->opaque; + + so->qual_ok = false; + return; + } + + /* Look up <= operator (might fail) */ + leop = get_opfamily_member(opfamily, opcintype, opcintype, + BTLessEqualStrategyNumber); + if (!OidIsValid(leop)) + return; + cmp_proc = get_opcode(leop); + if (RegProcedureIsValid(cmp_proc)) + { + /* Transform < high_compare key into <= key */ + fmgr_info(cmp_proc, &high_compare->sk_func); + high_compare->sk_argument = new_sk_argument; + high_compare->sk_strategy = BTLessEqualStrategyNumber; + } +} + +/* + * Convert skip array's < low_compare key into a <= key + */ +static void +_bt_skiparray_strat_increment(IndexScanDesc scan, ScanKey arraysk, + BTArrayKeyInfo *array) +{ + Relation rel = scan->indexRelation; + Oid opfamily = rel->rd_opfamily[arraysk->sk_attno - 1], + opcintype = rel->rd_opcintype[arraysk->sk_attno - 1], + geop; + RegProcedure cmp_proc; + ScanKey low_compare = array->low_compare; + Datum orig_sk_argument = low_compare->sk_argument, + new_sk_argument; + bool oflow; + + Assert(low_compare->sk_strategy == BTGreaterStrategyNumber); + + /* + * Only perform the transformation when the operator type matches the + * index attribute's input opclass type + */ + if (low_compare->sk_subtype != opcintype && + low_compare->sk_subtype != InvalidOid) + return; + + /* Increment, handling overflow by marking the qual unsatisfiable */ + new_sk_argument = array->sksup->increment(rel, orig_sk_argument, &oflow); + if (oflow) + { + BTScanOpaque so = (BTScanOpaque) scan->opaque; + + so->qual_ok = false; + return; + } + + /* Look up >= operator (might fail) */ + geop = get_opfamily_member(opfamily, opcintype, opcintype, + BTGreaterEqualStrategyNumber); + if (!OidIsValid(geop)) + return; + cmp_proc = get_opcode(geop); + if (RegProcedureIsValid(cmp_proc)) + { + /* Transform > low_compare key into >= key */ + fmgr_info(cmp_proc, &low_compare->sk_func); + low_compare->sk_argument = new_sk_argument; + low_compare->sk_strategy = BTGreaterEqualStrategyNumber; + } +} + +/* + * _bt_preprocess_array_keys() -- Preprocess SK_SEARCHARRAY scan keys + * + * If there are any SK_SEARCHARRAY scan keys, deconstruct the array(s) and + * set up BTArrayKeyInfo info for each one that is an equality-type key. + * Returns modified scan keys as input for further, standard preprocessing. + * + * Currently we perform two kinds of preprocessing to deal with redundancies. + * For inequality array keys, it's sufficient to find the extreme element + * value and replace the whole array with that scalar value. This eliminates + * all but one array element as redundant. Similarly, we are capable of + * "merging together" multiple equality array keys (from two or more input + * scan keys) into a single output scan key containing only the intersecting + * array elements. This can eliminate many redundant array elements, as well + * as eliminating whole array scan keys as redundant. It can also allow us to + * detect contradictory quals. + * + * Caller must pass *new_numberOfKeys to give us a way to change the number of + * scan keys that caller treats as input to standard preprocessing steps. The + * returned array is smaller than scan->keyData[] when we could eliminate a + * redundant array scan key (redundant with another array scan key). It is + * convenient for _bt_preprocess_keys caller to have to deal with no more than + * one equality strategy array scan key per index attribute. We'll always be + * able to set things up that way when complete opfamilies are used. + * + * We're also responsible for generating skip arrays (and their associated + * scan keys) here. This enables skip scan. We do this for index attributes + * that initially lacked an equality condition within scan->keyData[], iff + * doing so allows a later scan key (that was passed to us in scan->keyData[]) + * to be marked required by our _bt_preprocess_keys caller. + * + * We set the scan key references from the scan's BTArrayKeyInfo info array to + * offsets into the temp modified input array returned to caller. Scans that + * have array keys should call _bt_preprocess_array_keys_final when standard + * preprocessing steps are complete. This will convert the scan key offset + * references into references to the scan's so->keyData[] output scan keys. + * + * Note: the reason we need to return a temp scan key array, rather than just + * modifying scan->keyData[], is that callers are permitted to call btrescan + * without supplying a new set of scankey data. Certain other preprocessing + * routines (e.g., _bt_fix_scankey_strategy) _can_ modify scan->keyData[], but + * we can't make that work here because our modifications are non-idempotent. + */ +static ScanKey +_bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; + int16 *indoption = rel->rd_indoption; + Oid skip_eq_ops[INDEX_MAX_KEYS]; + int numArrayKeys, + numSkipArrayKeys, + numArrayKeyData; + AttrNumber attno_skip = 1; + int origarrayatt = InvalidAttrNumber, + origarraykey = -1; + Oid origelemtype = InvalidOid; + MemoryContext oldContext; + ScanKey arrayKeyData; /* modified copy of scan->keyData */ + + /* + * Check the number of input array keys within scan->keyData[] input keys + * (also checks if we should add extra skip arrays based on input keys) + */ + numArrayKeys = _bt_num_array_keys(scan, skip_eq_ops, &numSkipArrayKeys); + + /* Quit if nothing to do. */ + if (numArrayKeys == 0) + return NULL; + + /* + * Estimated final size of arrayKeyData[] array we'll return to our caller + * is the size of the original scan->keyData[] input array, plus space for + * any additional skip array scan keys we'll need to generate below + */ + numArrayKeyData = scan->numberOfKeys + numSkipArrayKeys; + + /* + * Make a scan-lifespan context to hold array-associated data, or reset it + * if we already have one from a previous rescan cycle. + */ + if (so->arrayContext == NULL) + so->arrayContext = AllocSetContextCreate(CurrentMemoryContext, + "BTree array context", + ALLOCSET_SMALL_SIZES); + else + MemoryContextReset(so->arrayContext); + + oldContext = MemoryContextSwitchTo(so->arrayContext); + + /* Create output scan keys in the workspace context */ + arrayKeyData = (ScanKey) palloc(numArrayKeyData * sizeof(ScanKeyData)); + + /* Allocate space for per-array data in the workspace context */ + so->skipScan = (numSkipArrayKeys > 0); + so->arrayKeys = (BTArrayKeyInfo *) palloc(numArrayKeys * sizeof(BTArrayKeyInfo)); + + /* Allocate space for ORDER procs used to help _bt_checkkeys */ + so->orderProcs = (FmgrInfo *) palloc(numArrayKeyData * sizeof(FmgrInfo)); + + numArrayKeys = 0; + numArrayKeyData = 0; + for (int input_ikey = 0; input_ikey < scan->numberOfKeys; input_ikey++) + { + ScanKey inkey = scan->keyData + input_ikey, + cur; + FmgrInfo sortproc; + FmgrInfo *sortprocp = &sortproc; + Oid elemtype; + bool reverse; + ArrayType *arrayval; + int16 elmlen; + bool elmbyval; + char elmalign; + int num_elems; + Datum *elem_values; + bool *elem_nulls; + int num_nonnulls; + + /* set up next output scan key */ + cur = &arrayKeyData[numArrayKeyData]; + + /* Backfill skip arrays for attrs < or <= input key's attr? */ + while (numSkipArrayKeys && attno_skip <= inkey->sk_attno) + { + Oid opfamily = rel->rd_opfamily[attno_skip - 1]; + Oid opcintype = rel->rd_opcintype[attno_skip - 1]; + Oid collation = rel->rd_indcollation[attno_skip - 1]; + Oid eq_op = skip_eq_ops[attno_skip - 1]; + CompactAttribute *attr; + RegProcedure cmp_proc; + + if (!OidIsValid(eq_op)) + { + /* + * Attribute already has an = input key, so don't output a + * skip array for attno_skip. Just copy attribute's = input + * key into arrayKeyData[] once outside this inner loop. + * + * Note: When we get here there must be a later attribute that + * lacks an equality input key, and still needs a skip array + * (if there wasn't then numSkipArrayKeys would be 0 by now). + */ + Assert(attno_skip == inkey->sk_attno); + /* inkey can't be last input key to be marked required: */ + Assert(input_ikey < scan->numberOfKeys - 1); +#if 0 + /* Could be a redundant input scan key, so can't do this: */ + Assert(inkey->sk_strategy == BTEqualStrategyNumber || + (inkey->sk_flags & SK_SEARCHNULL)); +#endif + + attno_skip++; + break; + } + + cmp_proc = get_opcode(eq_op); + if (!RegProcedureIsValid(cmp_proc)) + elog(ERROR, "missing oprcode for skipping equals operator %u", eq_op); + + ScanKeyEntryInitialize(cur, + SK_SEARCHARRAY | SK_BT_SKIP, /* flags */ + attno_skip, /* skipped att number */ + BTEqualStrategyNumber, /* equality strategy */ + InvalidOid, /* opclass input subtype */ + collation, /* index column's collation */ + cmp_proc, /* equality operator's proc */ + (Datum) 0); /* constant */ + + /* Initialize generic BTArrayKeyInfo fields */ + so->arrayKeys[numArrayKeys].scan_key = numArrayKeyData; + so->arrayKeys[numArrayKeys].num_elems = -1; + + /* Initialize skip array specific BTArrayKeyInfo fields */ + attr = TupleDescCompactAttr(RelationGetDescr(rel), attno_skip - 1); + reverse = (indoption[attno_skip - 1] & INDOPTION_DESC) != 0; + so->arrayKeys[numArrayKeys].attlen = attr->attlen; + so->arrayKeys[numArrayKeys].attbyval = attr->attbyval; + so->arrayKeys[numArrayKeys].null_elem = true; /* for now */ + so->arrayKeys[numArrayKeys].sksup = + PrepareSkipSupportFromOpclass(opfamily, opcintype, reverse); + so->arrayKeys[numArrayKeys].low_compare = NULL; /* for now */ + so->arrayKeys[numArrayKeys].high_compare = NULL; /* for now */ + + /* + * We'll need a 3-way ORDER proc. Set that up now. + */ + _bt_setup_array_cmp(scan, cur, opcintype, + &so->orderProcs[numArrayKeyData], NULL); + + numArrayKeys++; + numArrayKeyData++; /* keep this scan key/array */ + + /* set up next output scan key */ + cur = &arrayKeyData[numArrayKeyData]; + + /* remember having output this skip array and scan key */ + numSkipArrayKeys--; + attno_skip++; + } + + /* + * Provisionally copy scan key into arrayKeyData[] array we'll return + * to _bt_preprocess_keys caller + */ + *cur = *inkey; + + if (!(cur->sk_flags & SK_SEARCHARRAY)) + { + numArrayKeyData++; /* keep this non-array scan key */ + continue; + } + + /* + * Process SAOP array scan key + */ + Assert(!(cur->sk_flags & (SK_ROW_HEADER | SK_SEARCHNULL | SK_SEARCHNOTNULL))); + + /* If array is null as a whole, the scan qual is unsatisfiable */ + if (cur->sk_flags & SK_ISNULL) + { + so->qual_ok = false; + break; + } + + /* + * Deconstruct the array into elements + */ + arrayval = DatumGetArrayTypeP(cur->sk_argument); + /* We could cache this data, but not clear it's worth it */ + get_typlenbyvalalign(ARR_ELEMTYPE(arrayval), + &elmlen, &elmbyval, &elmalign); + deconstruct_array(arrayval, + ARR_ELEMTYPE(arrayval), + elmlen, elmbyval, elmalign, + &elem_values, &elem_nulls, &num_elems); + + /* + * Compress out any null elements. We can ignore them since we assume + * all btree operators are strict. + */ + num_nonnulls = 0; + for (int j = 0; j < num_elems; j++) + { + if (!elem_nulls[j]) + elem_values[num_nonnulls++] = elem_values[j]; + } + + /* We could pfree(elem_nulls) now, but not worth the cycles */ + + /* If there's no non-nulls, the scan qual is unsatisfiable */ + if (num_nonnulls == 0) + { + so->qual_ok = false; + break; + } + + /* + * Determine the nominal datatype of the array elements. We have to + * support the convention that sk_subtype == InvalidOid means the + * opclass input type; this is a hack to simplify life for + * ScanKeyInit(). + */ + elemtype = cur->sk_subtype; + if (elemtype == InvalidOid) + elemtype = rel->rd_opcintype[cur->sk_attno - 1]; + + /* + * If the comparison operator is not equality, then the array qual + * degenerates to a simple comparison against the smallest or largest + * non-null array element, as appropriate. + */ + switch (cur->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + cur->sk_argument = + _bt_find_extreme_element(scan, cur, elemtype, + BTGreaterStrategyNumber, + elem_values, num_nonnulls); + numArrayKeyData++; /* keep this transformed scan key */ + continue; + case BTEqualStrategyNumber: + /* proceed with rest of loop */ + break; + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + cur->sk_argument = + _bt_find_extreme_element(scan, cur, elemtype, + BTLessStrategyNumber, + elem_values, num_nonnulls); + numArrayKeyData++; /* keep this transformed scan key */ + continue; + default: + elog(ERROR, "unrecognized StrategyNumber: %d", + (int) cur->sk_strategy); + break; + } + + /* + * We'll need a 3-way ORDER proc to perform binary searches for the + * next matching array element. Set that up now. + * + * Array scan keys with cross-type equality operators will require a + * separate same-type ORDER proc for sorting their array. Otherwise, + * sortproc just points to the same proc used during binary searches. + */ + _bt_setup_array_cmp(scan, cur, elemtype, + &so->orderProcs[numArrayKeyData], &sortprocp); + + /* + * Sort the non-null elements and eliminate any duplicates. We must + * sort in the same ordering used by the index column, so that the + * arrays can be advanced in lockstep with the scan's progress through + * the index's key space. + */ + reverse = (indoption[cur->sk_attno - 1] & INDOPTION_DESC) != 0; + num_elems = _bt_sort_array_elements(cur, sortprocp, reverse, + elem_values, num_nonnulls); + + if (origarrayatt == cur->sk_attno) + { + BTArrayKeyInfo *orig = &so->arrayKeys[origarraykey]; + + /* + * This array scan key is redundant with a previous equality + * operator array scan key. Merge the two arrays together to + * eliminate contradictory non-intersecting elements (or try to). + * + * We merge this next array back into attribute's original array. + */ + Assert(arrayKeyData[orig->scan_key].sk_attno == cur->sk_attno); + Assert(arrayKeyData[orig->scan_key].sk_collation == + cur->sk_collation); + if (_bt_merge_arrays(scan, cur, sortprocp, reverse, + origelemtype, elemtype, + orig->elem_values, &orig->num_elems, + elem_values, num_elems)) + { + /* Successfully eliminated this array */ + pfree(elem_values); + + /* + * If no intersecting elements remain in the original array, + * the scan qual is unsatisfiable + */ + if (orig->num_elems == 0) + { + so->qual_ok = false; + break; + } + + /* Throw away this scan key/array */ + continue; + } + + /* + * Unable to merge this array with previous array due to a lack of + * suitable cross-type opfamily support. Will need to keep both + * scan keys/arrays. + */ + } + else + { + /* + * This array is the first for current index attribute. + * + * If it turns out to not be the last array (that is, if the next + * array is redundantly applied to this same index attribute), + * we'll then treat this array as the attribute's "original" array + * when merging. + */ + origarrayatt = cur->sk_attno; + origarraykey = numArrayKeys; + origelemtype = elemtype; + } + + /* Initialize generic BTArrayKeyInfo fields */ + so->arrayKeys[numArrayKeys].scan_key = numArrayKeyData; + so->arrayKeys[numArrayKeys].num_elems = num_elems; + + /* Initialize SAOP array specific BTArrayKeyInfo fields */ + so->arrayKeys[numArrayKeys].elem_values = elem_values; + so->arrayKeys[numArrayKeys].cur_elem = -1; /* i.e. invalid */ + + numArrayKeys++; + numArrayKeyData++; /* keep this scan key/array */ + } + + Assert(numSkipArrayKeys == 0 || !so->qual_ok); + + /* Set final number of equality-type array keys */ + so->numArrayKeys = numArrayKeys; + /* Set number of scan keys in arrayKeyData[] */ + *new_numberOfKeys = numArrayKeyData; + + MemoryContextSwitchTo(oldContext); + + return arrayKeyData; +} + +/* + * _bt_preprocess_array_keys_final() -- fix up array scan key references + * + * When _bt_preprocess_array_keys performed initial array preprocessing, it + * set each array's array->scan_key to its scankey's arrayKeyData[] offset. + * This function handles translation of the scan key references from the + * BTArrayKeyInfo info array, from input scan key references (to the keys in + * arrayKeyData[]), into output references (to the keys in so->keyData[]). + * Caller's keyDataMap[] array tells us how to perform this remapping. + * + * Also finalizes so->orderProcs[] for the scan. Arrays already have an ORDER + * proc, which might need to be repositioned to its so->keyData[]-wise offset + * (very much like the remapping that we apply to array->scan_key references). + * Non-array equality strategy scan keys (that survived preprocessing) don't + * yet have an so->orderProcs[] entry, so we set one for them here. + * + * Also converts single-element array scan keys into equivalent non-array + * equality scan keys, which decrements so->numArrayKeys. It's possible that + * this will leave this new btrescan without any arrays at all. This isn't + * necessary for correctness; it's just an optimization. Non-array equality + * scan keys are slightly faster than equivalent array scan keys at runtime. + */ +static void +_bt_preprocess_array_keys_final(IndexScanDesc scan, int *keyDataMap) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; + int arrayidx = 0; + int last_equal_output_ikey PG_USED_FOR_ASSERTS_ONLY = -1; + + Assert(so->qual_ok); + + /* + * Nothing for us to do when _bt_preprocess_array_keys only had to deal + * with array inequalities + */ + if (so->numArrayKeys == 0) + return; + + for (int output_ikey = 0; output_ikey < so->numberOfKeys; output_ikey++) + { + ScanKey outkey = so->keyData + output_ikey; + int input_ikey; + bool found PG_USED_FOR_ASSERTS_ONLY = false; + + Assert(outkey->sk_strategy != InvalidStrategy); + + if (outkey->sk_strategy != BTEqualStrategyNumber) + continue; + + input_ikey = keyDataMap[output_ikey]; + + Assert(last_equal_output_ikey < output_ikey); + Assert(last_equal_output_ikey < input_ikey); + last_equal_output_ikey = output_ikey; + + /* + * We're lazy about looking up ORDER procs for non-array keys, since + * not all input keys become output keys. Take care of it now. + */ + if (!(outkey->sk_flags & SK_SEARCHARRAY)) + { + Oid elemtype; + + /* No need for an ORDER proc given an IS NULL scan key */ + if (outkey->sk_flags & SK_SEARCHNULL) + continue; + + /* + * A non-required scan key doesn't need an ORDER proc, either + * (unless it's associated with an array, which this one isn't) + */ + if (!(outkey->sk_flags & SK_BT_REQFWD)) + continue; + + elemtype = outkey->sk_subtype; + if (elemtype == InvalidOid) + elemtype = rel->rd_opcintype[outkey->sk_attno - 1]; + + _bt_setup_array_cmp(scan, outkey, elemtype, + &so->orderProcs[output_ikey], NULL); + continue; + } + + /* + * Reorder existing array scan key so->orderProcs[] entries. + * + * Doing this in-place is safe because preprocessing is required to + * output all equality strategy scan keys in original input order + * (among each group of entries against the same index attribute). + * This is also the order that the arrays themselves appear in. + */ + so->orderProcs[output_ikey] = so->orderProcs[input_ikey]; + + /* Fix-up array->scan_key references for arrays */ + for (; arrayidx < so->numArrayKeys; arrayidx++) + { + BTArrayKeyInfo *array = &so->arrayKeys[arrayidx]; + + /* + * All skip arrays must be marked required, and final column can + * never have a skip array + */ + Assert(array->num_elems > 0 || array->num_elems == -1); + Assert(array->num_elems != -1 || outkey->sk_flags & SK_BT_REQFWD); + Assert(array->num_elems != -1 || + outkey->sk_attno < IndexRelationGetNumberOfKeyAttributes(rel)); + + if (array->scan_key == input_ikey) + { + /* found it */ + array->scan_key = output_ikey; + found = true; + + /* + * Transform array scan keys that have exactly 1 element + * remaining (following all prior preprocessing) into + * equivalent non-array scan keys. + */ + if (array->num_elems == 1) + { + outkey->sk_flags &= ~SK_SEARCHARRAY; + outkey->sk_argument = array->elem_values[0]; + so->numArrayKeys--; + + /* If we're out of array keys, we can quit right away */ + if (so->numArrayKeys == 0) + return; + + /* Shift other arrays forward */ + memmove(array, array + 1, + sizeof(BTArrayKeyInfo) * + (so->numArrayKeys - arrayidx)); + + /* + * Don't increment arrayidx (there was an entry that was + * just shifted forward to the offset at arrayidx, which + * will still need to be matched) + */ + } + else + { + /* + * Any skip array low_compare and high_compare scan keys + * are now final. Transform the array's > low_compare key + * into a >= key (and < high_compare keys into a <= key). + */ + if (array->num_elems == -1 && array->sksup && + !array->null_elem) + _bt_skiparray_strat_adjust(scan, outkey, array); + + /* Match found, so done with this array */ + arrayidx++; + } + + break; + } + } + + Assert(found); + } + + /* + * Parallel index scans require space in shared memory to store the + * current array elements (for arrays kept by preprocessing) to schedule + * the next primitive index scan. The underlying structure is protected + * using an LWLock, so defensively limit its size. In practice this can + * only affect parallel scans that use an incomplete opfamily. + */ + if (scan->parallel_scan && so->numArrayKeys > INDEX_MAX_KEYS) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg_internal("number of array scan keys left by preprocessing (%d) exceeds the maximum allowed by parallel btree index scans (%d)", + so->numArrayKeys, INDEX_MAX_KEYS))); +} + +/* + * _bt_num_array_keys() -- determine # of BTArrayKeyInfo entries + * + * _bt_preprocess_array_keys helper function. Returns the estimated size of + * the scan's BTArrayKeyInfo array, which is guaranteed to be large enough to + * fit every so->arrayKeys[] entry. + * + * Also sets *numSkipArrayKeys_out to the number of skip arrays caller must + * add to the scan keys it'll output. Caller must add this many skip arrays: + * one array for each of the most significant attributes that lack a = input + * key (IS NULL keys count as = input keys here). The specific attributes + * that need skip arrays are indicated by initializing skip_eq_ops_out[] arg + * 0-based attribute offset to a valid = op strategy Oid. We'll only ever set + * skip_eq_ops_out[] entries to InvalidOid for attributes that already have an + * equality key in scan->keyData[] input keys -- and only when there's some + * later "attribute gap" for us to "fill-in" with a skip array. + * + * We're optimistic about skipping working out: we always add exactly the skip + * arrays needed to maximize the number of input scan keys that can ultimately + * be marked as required to continue the scan (but no more). Given a + * multi-column index on (a, b, c, d), we add skip arrays as follows: + * + * Input keys Output keys (after all preprocessing) + * ---------- ------------------------------------- + * a = 1 a = 1 (no skip arrays) + * b = 42 skip a AND b = 42 + * a = 1 AND b = 42 a = 1 AND b = 42 (no skip arrays) + * a >= 1 AND b = 42 range skip a AND b = 42 + * a = 1 AND b > 42 a = 1 AND b > 42 (no skip arrays) + * a >= 1 AND a <= 3 AND b = 42 range skip a AND b = 42 + * a = 1 AND c <= 27 a = 1 AND skip b AND c <= 27 + * a = 1 AND d >= 1 a = 1 AND skip b AND skip c AND d >= 1 + * a = 1 AND b >= 42 AND d > 1 a = 1 AND range skip b AND skip c AND d > 1 + */ +static int +_bt_num_array_keys(IndexScanDesc scan, Oid *skip_eq_ops_out, + int *numSkipArrayKeys_out) +{ + Relation rel = scan->indexRelation; + AttrNumber attno_skip = 1, + attno_inkey = 1; + bool attno_has_equal = false, + attno_has_rowcompare = false; + int numSAOPArrayKeys, + numSkipArrayKeys, + prev_numSkipArrayKeys; + + Assert(scan->numberOfKeys); + + /* Initial pass over input scan keys counts the number of SAOP arrays */ + numSAOPArrayKeys = 0; + *numSkipArrayKeys_out = prev_numSkipArrayKeys = numSkipArrayKeys = 0; + for (int i = 0; i < scan->numberOfKeys; i++) + { + ScanKey inkey = scan->keyData + i; + + if (inkey->sk_flags & SK_SEARCHARRAY) + numSAOPArrayKeys++; + } + +#ifdef DEBUG_DISABLE_SKIP_SCAN + /* don't attempt to add skip arrays */ + return numSAOPArrayKeys; +#endif + + for (int i = 0;; i++) + { + ScanKey inkey = scan->keyData + i; + + /* + * Backfill skip arrays for any wholly omitted attributes prior to + * attno_inkey + */ + while (attno_skip < attno_inkey) + { + Oid opfamily = rel->rd_opfamily[attno_skip - 1]; + Oid opcintype = rel->rd_opcintype[attno_skip - 1]; + + /* Look up input opclass's equality operator (might fail) */ + skip_eq_ops_out[attno_skip - 1] = + get_opfamily_member(opfamily, opcintype, opcintype, + BTEqualStrategyNumber); + if (!OidIsValid(skip_eq_ops_out[attno_skip - 1])) + { + /* + * Cannot generate a skip array for this or later attributes + * (input opclass lacks an equality strategy operator) + */ + *numSkipArrayKeys_out = prev_numSkipArrayKeys; + return numSAOPArrayKeys + prev_numSkipArrayKeys; + } + + /* plan on adding a backfill skip array for this attribute */ + numSkipArrayKeys++; + attno_skip++; + } + + prev_numSkipArrayKeys = numSkipArrayKeys; + + /* + * Stop once past the final input scan key. We deliberately never add + * a skip array for the last input scan key's attribute -- even when + * there are only inequality keys on that attribute. + */ + if (i == scan->numberOfKeys) + break; + + /* + * Later preprocessing steps cannot merge a RowCompare into a skip + * array, so stop adding skip arrays once we see one. (Note that we + * can backfill skip arrays before a RowCompare, which will allow keys + * up to and including the RowCompare to be marked required.) + * + * Skip arrays work by maintaining a current array element value, + * which anchors lower-order keys via an implied equality constraint. + * This is incompatible with the current nbtree row comparison design, + * which compares all columns together, as an indivisible group. + * Alternative designs that can be used alongside skip arrays are + * possible, but it's not clear that they're really worth pursuing. + * + * A RowCompare qual "(a, b, c) > (10, 'foo', 42)" is equivalent to + * "(a=10 AND b='foo' AND c>42) OR (a=10 AND b>'foo') OR (a>10)". + * Decomposing this RowCompare into these 3 disjuncts allows each + * disjunct to be executed as a separate "single value" index scan. + * That'll give all 3 scans the ability to add skip arrays in the + * usual way (when there are any scalar keys after the RowCompare). + * Under this scheme, a qual "(a, b, c) > (10, 'foo', 42) AND d = 99" + * performs 3 separate scans, each of which can mark keys up to and + * including its "d = 99" key as required to continue the scan. + */ + if (attno_has_rowcompare) + break; + + /* + * Now consider next attno_inkey (or keep going if this is an + * additional scan key against the same attribute) + */ + if (attno_inkey < inkey->sk_attno) + { + /* + * Now add skip array for previous scan key's attribute, though + * only if the attribute has no equality strategy scan keys + */ + if (attno_has_equal) + { + /* Attributes with an = key must have InvalidOid eq_op set */ + skip_eq_ops_out[attno_skip - 1] = InvalidOid; + } + else + { + Oid opfamily = rel->rd_opfamily[attno_skip - 1]; + Oid opcintype = rel->rd_opcintype[attno_skip - 1]; + + /* Look up input opclass's equality operator (might fail) */ + skip_eq_ops_out[attno_skip - 1] = + get_opfamily_member(opfamily, opcintype, opcintype, + BTEqualStrategyNumber); + + if (!OidIsValid(skip_eq_ops_out[attno_skip - 1])) + { + /* + * Input opclass lacks an equality strategy operator, so + * don't generate a skip array that definitely won't work + */ + break; + } + + /* plan on adding a backfill skip array for this attribute */ + numSkipArrayKeys++; + } + + /* Set things up for this new attribute */ + attno_skip++; + attno_inkey = inkey->sk_attno; + attno_has_equal = false; + } + + /* + * Track if this attribute's scan keys include any equality strategy + * scan keys (IS NULL keys count as equality keys here). Also track + * if it has any RowCompare keys. + */ + if (inkey->sk_strategy == BTEqualStrategyNumber || + (inkey->sk_flags & SK_SEARCHNULL)) + attno_has_equal = true; + if (inkey->sk_flags & SK_ROW_HEADER) + attno_has_rowcompare = true; + } + + *numSkipArrayKeys_out = numSkipArrayKeys; + return numSAOPArrayKeys + numSkipArrayKeys; +} + +/* + * _bt_find_extreme_element() -- get least or greatest array element + * + * scan and skey identify the index column, whose opfamily determines the + * comparison semantics. strat should be BTLessStrategyNumber to get the + * least element, or BTGreaterStrategyNumber to get the greatest. + */ +static Datum +_bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, Oid elemtype, + StrategyNumber strat, + Datum *elems, int nelems) +{ + Relation rel = scan->indexRelation; + Oid cmp_op; + RegProcedure cmp_proc; + FmgrInfo flinfo; + Datum result; + int i; + + /* + * Look up the appropriate comparison operator in the opfamily. + * + * Note: it's possible that this would fail, if the opfamily is + * incomplete, but it seems quite unlikely that an opfamily would omit + * non-cross-type comparison operators for any datatype that it supports + * at all. + */ + Assert(skey->sk_strategy != BTEqualStrategyNumber); + Assert(OidIsValid(elemtype)); + cmp_op = get_opfamily_member(rel->rd_opfamily[skey->sk_attno - 1], + elemtype, + elemtype, + strat); + if (!OidIsValid(cmp_op)) + elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", + strat, elemtype, elemtype, + rel->rd_opfamily[skey->sk_attno - 1]); + cmp_proc = get_opcode(cmp_op); + if (!RegProcedureIsValid(cmp_proc)) + elog(ERROR, "missing oprcode for operator %u", cmp_op); + + fmgr_info(cmp_proc, &flinfo); + + Assert(nelems > 0); + result = elems[0]; + for (i = 1; i < nelems; i++) + { + if (DatumGetBool(FunctionCall2Coll(&flinfo, + skey->sk_collation, + elems[i], + result))) + result = elems[i]; + } + + return result; +} + +/* + * _bt_setup_array_cmp() -- Set up array comparison functions + * + * Sets ORDER proc in caller's orderproc argument, which is used during binary + * searches of arrays during the index scan. Also sets a same-type ORDER proc + * in caller's *sortprocp argument, which is used when sorting the array. + * + * Preprocessing calls here with all equality strategy scan keys (when scan + * uses equality array keys), including those not associated with any array. + * See _bt_advance_array_keys for an explanation of why it'll need to treat + * simple scalar equality scan keys as degenerate single element arrays. + * + * Caller should pass an orderproc pointing to space that'll store the ORDER + * proc for the scan, and a *sortprocp pointing to its own separate space. + * When calling here for a non-array scan key, sortprocp arg should be NULL. + * + * In the common case where we don't need to deal with cross-type operators, + * only one ORDER proc is actually required by caller. We'll set *sortprocp + * to point to the same memory that caller's orderproc continues to point to. + * Otherwise, *sortprocp will continue to point to caller's own space. Either + * way, *sortprocp will point to a same-type ORDER proc (since that's the only + * safe way to sort/deduplicate the array associated with caller's scan key). + */ +static void +_bt_setup_array_cmp(IndexScanDesc scan, ScanKey skey, Oid elemtype, + FmgrInfo *orderproc, FmgrInfo **sortprocp) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; + RegProcedure cmp_proc; + Oid opcintype = rel->rd_opcintype[skey->sk_attno - 1]; + + Assert(skey->sk_strategy == BTEqualStrategyNumber); + Assert(OidIsValid(elemtype)); + + /* + * If scankey operator is not a cross-type comparison, we can use the + * cached comparison function; otherwise gotta look it up in the catalogs + */ + if (elemtype == opcintype) + { + /* Set same-type ORDER procs for caller */ + *orderproc = *index_getprocinfo(rel, skey->sk_attno, BTORDER_PROC); + if (sortprocp) + *sortprocp = orderproc; + + return; + } + + /* + * Look up the appropriate cross-type comparison function in the opfamily. + * + * Use the opclass input type as the left hand arg type, and the array + * element type as the right hand arg type (since binary searches use an + * index tuple's attribute value to search for a matching array element). + * + * Note: it's possible that this would fail, if the opfamily is + * incomplete, but only in cases where it's quite likely that _bt_first + * would fail in just the same way (had we not failed before it could). + */ + cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], + opcintype, elemtype, BTORDER_PROC); + if (!RegProcedureIsValid(cmp_proc)) + elog(ERROR, "missing support function %d(%u,%u) for attribute %d of index \"%s\"", + BTORDER_PROC, opcintype, elemtype, skey->sk_attno, + RelationGetRelationName(rel)); + + /* Set cross-type ORDER proc for caller */ + fmgr_info_cxt(cmp_proc, orderproc, so->arrayContext); + + /* Done if caller doesn't actually have an array they'll need to sort */ + if (!sortprocp) + return; + + /* + * Look up the appropriate same-type comparison function in the opfamily. + * + * Note: it's possible that this would fail, if the opfamily is + * incomplete, but it seems quite unlikely that an opfamily would omit + * non-cross-type comparison procs for any datatype that it supports at + * all. + */ + cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], + elemtype, elemtype, BTORDER_PROC); + if (!RegProcedureIsValid(cmp_proc)) + elog(ERROR, "missing support function %d(%u,%u) for attribute %d of index \"%s\"", + BTORDER_PROC, elemtype, elemtype, + skey->sk_attno, RelationGetRelationName(rel)); + + /* Set same-type ORDER proc for caller */ + fmgr_info_cxt(cmp_proc, *sortprocp, so->arrayContext); +} + +/* + * _bt_sort_array_elements() -- sort and de-dup array elements + * + * The array elements are sorted in-place, and the new number of elements + * after duplicate removal is returned. + * + * skey identifies the index column whose opfamily determines the comparison + * semantics, and sortproc is a corresponding ORDER proc. If reverse is true, + * we sort in descending order. + */ +static int +_bt_sort_array_elements(ScanKey skey, FmgrInfo *sortproc, bool reverse, + Datum *elems, int nelems) +{ + BTSortArrayContext cxt; + + if (nelems <= 1) + return nelems; /* no work to do */ + + /* Sort the array elements */ + cxt.sortproc = sortproc; + cxt.collation = skey->sk_collation; + cxt.reverse = reverse; + qsort_arg(elems, nelems, sizeof(Datum), + _bt_compare_array_elements, &cxt); + + /* Now scan the sorted elements and remove duplicates */ + return qunique_arg(elems, nelems, sizeof(Datum), + _bt_compare_array_elements, &cxt); +} + +/* + * _bt_merge_arrays() -- merge next array's elements into an original array + * + * Called when preprocessing encounters a pair of array equality scan keys, + * both against the same index attribute (during initial array preprocessing). + * Merging reorganizes caller's original array (the left hand arg) in-place, + * without ever copying elements from one array into the other. (Mixing the + * elements together like this would be wrong, since they don't necessarily + * use the same underlying element type, despite all the other similarities.) + * + * Both arrays must have already been sorted and deduplicated by calling + * _bt_sort_array_elements. sortproc is the same-type ORDER proc that was + * just used to sort and deduplicate caller's "next" array. We'll usually be + * able to reuse that order PROC to merge the arrays together now. If not, + * then we'll perform a separate ORDER proc lookup. + * + * If the opfamily doesn't supply a complete set of cross-type ORDER procs we + * may not be able to determine which elements are contradictory. If we have + * the required ORDER proc then we return true (and validly set *nelems_orig), + * guaranteeing that at least the next array can be considered redundant. We + * return false if the required comparisons cannot be made (caller must keep + * both arrays when this happens). + */ +static bool +_bt_merge_arrays(IndexScanDesc scan, ScanKey skey, FmgrInfo *sortproc, + bool reverse, Oid origelemtype, Oid nextelemtype, + Datum *elems_orig, int *nelems_orig, + Datum *elems_next, int nelems_next) +{ + Relation rel = scan->indexRelation; + BTScanOpaque so = (BTScanOpaque) scan->opaque; + BTSortArrayContext cxt; + int nelems_orig_start = *nelems_orig, + nelems_orig_merged = 0; + FmgrInfo *mergeproc = sortproc; + FmgrInfo crosstypeproc; + + Assert(skey->sk_strategy == BTEqualStrategyNumber); + Assert(OidIsValid(origelemtype) && OidIsValid(nextelemtype)); + + if (origelemtype != nextelemtype) + { + RegProcedure cmp_proc; + + /* + * Cross-array-element-type merging is required, so can't just reuse + * sortproc when merging + */ + cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], + origelemtype, nextelemtype, BTORDER_PROC); + if (!RegProcedureIsValid(cmp_proc)) + { + /* Can't make the required comparisons */ + return false; + } + + /* We have all we need to determine redundancy/contradictoriness */ + mergeproc = &crosstypeproc; + fmgr_info_cxt(cmp_proc, mergeproc, so->arrayContext); + } + + cxt.sortproc = mergeproc; + cxt.collation = skey->sk_collation; + cxt.reverse = reverse; + + for (int i = 0, j = 0; i < nelems_orig_start && j < nelems_next;) + { + Datum *oelem = elems_orig + i, + *nelem = elems_next + j; + int res = _bt_compare_array_elements(oelem, nelem, &cxt); + + if (res == 0) + { + elems_orig[nelems_orig_merged++] = *oelem; + i++; + j++; + } + else if (res < 0) + i++; + else /* res > 0 */ + j++; + } + + *nelems_orig = nelems_orig_merged; + + return true; +} + +/* + * qsort_arg comparator for sorting array elements + */ +static int +_bt_compare_array_elements(const void *a, const void *b, void *arg) +{ + Datum da = *((const Datum *) a); + Datum db = *((const Datum *) b); + BTSortArrayContext *cxt = (BTSortArrayContext *) arg; + int32 compare; + + compare = DatumGetInt32(FunctionCall2Coll(cxt->sortproc, + cxt->collation, + da, db)); + if (cxt->reverse) + INVERT_COMPARE_RESULT(compare); + return compare; +} diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 686a3206f726b..fdff960c13022 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -8,7 +8,7 @@ * This file contains only the public interface routines. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -20,10 +20,9 @@ #include "access/nbtree.h" #include "access/relscan.h" -#include "access/xloginsert.h" +#include "access/stratnum.h" #include "commands/progress.h" #include "commands/vacuum.h" -#include "miscadmin.h" #include "nodes/execnodes.h" #include "pgstat.h" #include "storage/bulk_write.h" @@ -31,7 +30,8 @@ #include "storage/indexfsm.h" #include "storage/ipc.h" #include "storage/lmgr.h" -#include "storage/smgr.h" +#include "storage/read_stream.h" +#include "utils/datum.h" #include "utils/fmgrprotos.h" #include "utils/index_selfuncs.h" #include "utils/memutils.h" @@ -66,27 +66,41 @@ typedef enum */ typedef struct BTParallelScanDescData { - BlockNumber btps_scanPage; /* latest or next page to be scanned */ + BlockNumber btps_nextScanPage; /* next page to be scanned */ + BlockNumber btps_lastCurrPage; /* page whose sibling link was copied into + * btps_nextScanPage */ BTPS_State btps_pageStatus; /* indicates whether next page is * available for scan. see above for * possible states of parallel scan. */ - slock_t btps_mutex; /* protects above variables, btps_arrElems */ + LWLock btps_lock; /* protects shared parallel state */ ConditionVariable btps_cv; /* used to synchronize parallel scan */ /* * btps_arrElems is used when scans need to schedule another primitive - * index scan. Holds BTArrayKeyInfo.cur_elem offsets for scan keys. + * index scan with one or more SAOP arrays. Holds BTArrayKeyInfo.cur_elem + * offsets for each = scan key associated with a ScalarArrayOp array. */ int btps_arrElems[FLEXIBLE_ARRAY_MEMBER]; + + /* + * Additional space (at the end of the struct) is used when scans need to + * schedule another primitive index scan with one or more skip arrays. + * Holds a flattened datum representation for each = scan key associated + * with a skip array. + */ } BTParallelScanDescData; typedef struct BTParallelScanDescData *BTParallelScanDesc; +static void _bt_parallel_serialize_arrays(Relation rel, BTParallelScanDesc btscan, + BTScanOpaque so); +static void _bt_parallel_restore_arrays(Relation rel, BTParallelScanDesc btscan, + BTScanOpaque so); static void btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state, BTCycleId cycleid); -static void btvacuumpage(BTVacState *vstate, BlockNumber scanblkno); +static BlockNumber btvacuumpage(BTVacState *vstate, Buffer buf); static BTVacuumPosting btreevacuumposting(BTVacState *vstate, IndexTuple posting, OffsetNumber updatedoffset, @@ -107,6 +121,9 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BTOPTIONS_PROC; amroutine->amcanorder = true; amroutine->amcanorderbyop = false; + amroutine->amcanhash = false; + amroutine->amconsistentequality = true; + amroutine->amconsistentordering = true; amroutine->amcanbackward = true; amroutine->amcanunique = true; amroutine->amcanmulticol = true; @@ -133,6 +150,7 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = btvacuumcleanup; amroutine->amcanreturn = btcanreturn; amroutine->amcostestimate = btcostestimate; + amroutine->amgettreeheight = btgettreeheight; amroutine->amoptions = btoptions; amroutine->amproperty = btproperty; amroutine->ambuildphasename = btbuildphasename; @@ -148,6 +166,8 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = btestimateparallelscan; amroutine->aminitparallelscan = btinitparallelscan; amroutine->amparallelrescan = btparallelrescan; + amroutine->amtranslatestrategy = bttranslatestrategy; + amroutine->amtranslatecmptype = bttranslatecmptype; PG_RETURN_POINTER(amroutine); } @@ -208,6 +228,8 @@ btgettuple(IndexScanDesc scan, ScanDirection dir) BTScanOpaque so = (BTScanOpaque) scan->opaque; bool res; + Assert(scan->heapRelation != NULL); + /* btree indexes are never lossy */ scan->xs_recheck = false; @@ -269,6 +291,8 @@ btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) int64 ntids = 0; ItemPointer heapTid; + Assert(scan->heapRelation == NULL); + /* Each loop iteration performs another primitive index scan */ do { @@ -329,8 +353,10 @@ btbeginscan(Relation rel, int nkeys, int norderbys) else so->keyData = NULL; + so->skipScan = false; so->needPrimScan = false; so->scanBehind = false; + so->oppositeDirCheck = false; so->arrayKeys = NULL; so->orderProcs = NULL; so->arrayContext = NULL; @@ -371,9 +397,38 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, BTScanPosInvalidate(so->currPos); } + /* + * We prefer to eagerly drop leaf page pins before btgettuple returns. + * This avoids making VACUUM wait to acquire a cleanup lock on the page. + * + * We cannot safely drop leaf page pins during index-only scans due to a + * race condition involving VACUUM setting pages all-visible in the VM. + * It's also unsafe for plain index scans that use a non-MVCC snapshot. + * + * When we drop pins eagerly, the mechanism that marks so->killedItems[] + * index tuples LP_DEAD has to deal with concurrent TID recycling races. + * The scheme used to detect unsafe TID recycling won't work when scanning + * unlogged relations (since it involves saving an affected page's LSN). + * Opt out of eager pin dropping during unlogged relation scans for now + * (this is preferable to opting out of kill_prior_tuple LP_DEAD setting). + * + * Also opt out of dropping leaf page pins eagerly during bitmap scans. + * Pins cannot be held for more than an instant during bitmap scans either + * way, so we might as well avoid wasting cycles on acquiring page LSNs. + * + * See nbtree/README section on making concurrent TID recycling safe. + * + * Note: so->dropPin should never change across rescans. + */ + so->dropPin = (!scan->xs_want_itup && + IsMVCCSnapshot(scan->xs_snapshot) && + RelationNeedsWAL(scan->indexRelation) && + scan->heapRelation != NULL); + so->markItemIndex = -1; so->needPrimScan = false; so->scanBehind = false; + so->oppositeDirCheck = false; BTScanPosUnpinIfPinned(so->markPos); BTScanPosInvalidate(so->markPos); @@ -403,9 +458,7 @@ btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, * Reset the scan keys */ if (scankey && scan->numberOfKeys > 0) - memmove(scan->keyData, - scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); so->numberOfKeys = 0; /* until _bt_preprocess_keys sets it */ so->numArrayKeys = 0; /* ditto */ } @@ -534,10 +587,167 @@ btrestrpos(IndexScanDesc scan) * btestimateparallelscan -- estimate storage for BTParallelScanDescData */ Size -btestimateparallelscan(int nkeys, int norderbys) +btestimateparallelscan(Relation rel, int nkeys, int norderbys) { - /* Pessimistically assume all input scankeys will be output with arrays */ - return offsetof(BTParallelScanDescData, btps_arrElems) + sizeof(int) * nkeys; + int16 nkeyatts = IndexRelationGetNumberOfKeyAttributes(rel); + Size estnbtreeshared, + genericattrspace; + + /* + * Pessimistically assume that every input scan key will be output with + * its own SAOP array + */ + estnbtreeshared = offsetof(BTParallelScanDescData, btps_arrElems) + + sizeof(int) * nkeys; + + /* Single column indexes cannot possibly use a skip array */ + if (nkeyatts == 1) + return estnbtreeshared; + + /* + * Pessimistically assume that all attributes prior to the least + * significant attribute require a skip array (and an associated key) + */ + genericattrspace = datumEstimateSpace((Datum) 0, false, true, + sizeof(Datum)); + for (int attnum = 1; attnum < nkeyatts; attnum++) + { + CompactAttribute *attr; + + /* + * We make the conservative assumption that every index column will + * also require a skip array. + * + * Every skip array must have space to store its scan key's sk_flags. + */ + estnbtreeshared = add_size(estnbtreeshared, sizeof(int)); + + /* Consider space required to store a datum of opclass input type */ + attr = TupleDescCompactAttr(rel->rd_att, attnum - 1); + if (attr->attbyval) + { + /* This index attribute stores pass-by-value datums */ + Size estfixed = datumEstimateSpace((Datum) 0, false, + true, attr->attlen); + + estnbtreeshared = add_size(estnbtreeshared, estfixed); + continue; + } + + /* + * This index attribute stores pass-by-reference datums. + * + * Assume that serializing this array will use just as much space as a + * pass-by-value datum, in addition to space for the largest possible + * whole index tuple (this is not just a per-datum portion of the + * largest possible tuple because that'd be almost as large anyway). + * + * This is quite conservative, but it's not clear how we could do much + * better. The executor requires an up-front storage request size + * that reliably covers the scan's high watermark memory usage. We + * can't be sure of the real high watermark until the scan is over. + */ + estnbtreeshared = add_size(estnbtreeshared, genericattrspace); + estnbtreeshared = add_size(estnbtreeshared, BTMaxItemSize); + } + + return estnbtreeshared; +} + +/* + * _bt_parallel_serialize_arrays() -- Serialize parallel array state. + * + * Caller must have exclusively locked btscan->btps_lock when called. + */ +static void +_bt_parallel_serialize_arrays(Relation rel, BTParallelScanDesc btscan, + BTScanOpaque so) +{ + char *datumshared; + + /* Space for serialized datums begins immediately after btps_arrElems[] */ + datumshared = ((char *) &btscan->btps_arrElems[so->numArrayKeys]); + for (int i = 0; i < so->numArrayKeys; i++) + { + BTArrayKeyInfo *array = &so->arrayKeys[i]; + ScanKey skey = &so->keyData[array->scan_key]; + + if (array->num_elems != -1) + { + /* Save SAOP array's cur_elem (no need to copy key/datum) */ + Assert(!(skey->sk_flags & SK_BT_SKIP)); + btscan->btps_arrElems[i] = array->cur_elem; + continue; + } + + /* Save all mutable state associated with skip array's key */ + Assert(skey->sk_flags & SK_BT_SKIP); + memcpy(datumshared, &skey->sk_flags, sizeof(int)); + datumshared += sizeof(int); + + if (skey->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL)) + { + /* No sk_argument datum to serialize */ + Assert(skey->sk_argument == 0); + continue; + } + + datumSerialize(skey->sk_argument, (skey->sk_flags & SK_ISNULL) != 0, + array->attbyval, array->attlen, &datumshared); + } +} + +/* + * _bt_parallel_restore_arrays() -- Restore serialized parallel array state. + * + * Caller must have exclusively locked btscan->btps_lock when called. + */ +static void +_bt_parallel_restore_arrays(Relation rel, BTParallelScanDesc btscan, + BTScanOpaque so) +{ + char *datumshared; + + /* Space for serialized datums begins immediately after btps_arrElems[] */ + datumshared = ((char *) &btscan->btps_arrElems[so->numArrayKeys]); + for (int i = 0; i < so->numArrayKeys; i++) + { + BTArrayKeyInfo *array = &so->arrayKeys[i]; + ScanKey skey = &so->keyData[array->scan_key]; + bool isnull; + + if (array->num_elems != -1) + { + /* Restore SAOP array using its saved cur_elem */ + Assert(!(skey->sk_flags & SK_BT_SKIP)); + array->cur_elem = btscan->btps_arrElems[i]; + skey->sk_argument = array->elem_values[array->cur_elem]; + continue; + } + + /* Restore skip array by restoring its key directly */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + skey->sk_argument = (Datum) 0; + memcpy(&skey->sk_flags, datumshared, sizeof(int)); + datumshared += sizeof(int); + + Assert(skey->sk_flags & SK_BT_SKIP); + + if (skey->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL)) + { + /* No sk_argument datum to restore */ + continue; + } + + skey->sk_argument = datumRestore(&datumshared, &isnull); + if (isnull) + { + Assert(skey->sk_argument == 0); + Assert(skey->sk_flags & SK_SEARCHNULL); + Assert(skey->sk_flags & SK_ISNULL); + } + } } /* @@ -548,8 +758,10 @@ btinitparallelscan(void *target) { BTParallelScanDesc bt_target = (BTParallelScanDesc) target; - SpinLockInit(&bt_target->btps_mutex); - bt_target->btps_scanPage = InvalidBlockNumber; + LWLockInitialize(&bt_target->btps_lock, + LWTRANCHE_PARALLEL_BTREE_SCAN); + bt_target->btps_nextScanPage = InvalidBlockNumber; + bt_target->btps_lastCurrPage = InvalidBlockNumber; bt_target->btps_pageStatus = BTPARALLEL_NOT_INITIALIZED; ConditionVariableInit(&bt_target->btps_cv); } @@ -565,18 +777,19 @@ btparallelrescan(IndexScanDesc scan) Assert(parallel_scan); - btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, - parallel_scan->ps_offset); + btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan, + parallel_scan->ps_offset_am); /* - * In theory, we don't need to acquire the spinlock here, because there + * In theory, we don't need to acquire the LWLock here, because there * shouldn't be any other workers running at this point, but we do so for * consistency. */ - SpinLockAcquire(&btscan->btps_mutex); - btscan->btps_scanPage = InvalidBlockNumber; + LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE); + btscan->btps_nextScanPage = InvalidBlockNumber; + btscan->btps_lastCurrPage = InvalidBlockNumber; btscan->btps_pageStatus = BTPARALLEL_NOT_INITIALIZED; - SpinLockRelease(&btscan->btps_mutex); + LWLockRelease(&btscan->btps_lock); } /* @@ -585,94 +798,113 @@ btparallelrescan(IndexScanDesc scan) * or _bt_parallel_done(). * * The return value is true if we successfully seized the scan and false - * if we did not. The latter case occurs if no pages remain. - * - * If the return value is true, *pageno returns the next or current page - * of the scan (depending on the scan direction). An invalid block number - * means the scan hasn't yet started, or that caller needs to start the next - * primitive index scan (if it's the latter case we'll set so.needPrimScan). - * The first time a participating process reaches the last page, it will return - * true and set *pageno to P_NONE; after that, further attempts to seize the - * scan will return false. + * if we did not. The latter case occurs when no pages remain, or when + * another primitive index scan is scheduled that caller's backend cannot + * start just yet (only backends that call from _bt_first are capable of + * starting primitive index scans, which they indicate by passing first=true). * - * Callers should ignore the value of pageno if the return value is false. + * If the return value is true, *next_scan_page returns the next page of the + * scan, and *last_curr_page returns the page that *next_scan_page came from. + * An invalid *next_scan_page means the scan hasn't yet started, or that + * caller needs to start the next primitive index scan (if it's the latter + * case we'll set so.needPrimScan). * - * Callers that are in a position to start a new primitive index scan must - * pass first=true (all other callers pass first=false). We just return false - * for first=false callers that require another primitive index scan. + * Callers should ignore the value of *next_scan_page and *last_curr_page if + * the return value is false. */ bool -_bt_parallel_seize(IndexScanDesc scan, BlockNumber *pageno, bool first) +_bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, + BlockNumber *last_curr_page, bool first) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; - bool exit_loop = false; - bool status = true; + bool exit_loop = false, + status = true, + endscan = false; ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; - *pageno = P_NONE; + *next_scan_page = InvalidBlockNumber; + *last_curr_page = InvalidBlockNumber; + + /* + * Reset so->currPos, and initialize moreLeft/moreRight such that the next + * call to _bt_readnextpage treats this backend similarly to a serial + * backend that steps from *last_curr_page to *next_scan_page (unless this + * backend's so->currPos is initialized by _bt_readfirstpage before then). + */ + BTScanPosInvalidate(so->currPos); + so->currPos.moreLeft = so->currPos.moreRight = true; if (first) { /* * Initialize array related state when called from _bt_first, assuming - * that this will either be the first primitive index scan for the - * scan, or a previous explicitly scheduled primitive scan. - * - * Note: so->needPrimScan is only set when a scheduled primitive index - * scan is set to be performed in caller's worker process. It should - * not be set here by us for the first primitive scan, nor should we - * ever set it for a parallel scan that has no array keys. + * that this will be the first primitive index scan for the scan */ so->needPrimScan = false; so->scanBehind = false; + so->oppositeDirCheck = false; } else { /* - * Don't attempt to seize the scan when backend requires another - * primitive index scan unless we're in a position to start it now + * Don't attempt to seize the scan when it requires another primitive + * index scan, since caller's backend cannot start it right now */ if (so->needPrimScan) return false; } - btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, - parallel_scan->ps_offset); + btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan, + parallel_scan->ps_offset_am); while (1) { - SpinLockAcquire(&btscan->btps_mutex); + LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE); if (btscan->btps_pageStatus == BTPARALLEL_DONE) { /* We're done with this parallel index scan */ status = false; } + else if (btscan->btps_pageStatus == BTPARALLEL_IDLE && + btscan->btps_nextScanPage == P_NONE) + { + /* End this parallel index scan */ + status = false; + endscan = true; + } else if (btscan->btps_pageStatus == BTPARALLEL_NEED_PRIMSCAN) { Assert(so->numArrayKeys); - /* - * If we can start another primitive scan right away, do so. - * Otherwise just wait. - */ if (first) { + /* Can start scheduled primitive scan right away, so do so */ btscan->btps_pageStatus = BTPARALLEL_ADVANCING; - for (int i = 0; i < so->numArrayKeys; i++) - { - BTArrayKeyInfo *array = &so->arrayKeys[i]; - ScanKey skey = &so->keyData[array->scan_key]; - array->cur_elem = btscan->btps_arrElems[i]; - skey->sk_argument = array->elem_values[array->cur_elem]; - } - so->needPrimScan = true; - so->scanBehind = false; - *pageno = InvalidBlockNumber; + /* Restore scan's array keys from serialized values */ + _bt_parallel_restore_arrays(rel, btscan, so); exit_loop = true; } + else + { + /* + * Don't attempt to seize the scan when it requires another + * primitive index scan, since caller's backend cannot start + * it right now + */ + status = false; + } + + /* + * Either way, update backend local state to indicate that a + * pending primitive scan is required + */ + so->needPrimScan = true; + so->scanBehind = false; + so->oppositeDirCheck = false; } else if (btscan->btps_pageStatus != BTPARALLEL_ADVANCING) { @@ -681,43 +913,60 @@ _bt_parallel_seize(IndexScanDesc scan, BlockNumber *pageno, bool first) * of advancing it to a new page! */ btscan->btps_pageStatus = BTPARALLEL_ADVANCING; - *pageno = btscan->btps_scanPage; + Assert(btscan->btps_nextScanPage != P_NONE); + *next_scan_page = btscan->btps_nextScanPage; + *last_curr_page = btscan->btps_lastCurrPage; exit_loop = true; } - SpinLockRelease(&btscan->btps_mutex); + LWLockRelease(&btscan->btps_lock); if (exit_loop || !status) break; ConditionVariableSleep(&btscan->btps_cv, WAIT_EVENT_BTREE_PAGE); } ConditionVariableCancelSleep(); + /* When the scan has reached the rightmost (or leftmost) page, end it */ + if (endscan) + _bt_parallel_done(scan); + return status; } /* * _bt_parallel_release() -- Complete the process of advancing the scan to a - * new page. We now have the new value btps_scanPage; some other backend + * new page. We now have the new value btps_nextScanPage; another backend * can now begin advancing the scan. * - * Callers whose scan uses array keys must save their scan_page argument so + * Callers whose scan uses array keys must save their curr_page argument so * that it can be passed to _bt_parallel_primscan_schedule, should caller - * determine that another primitive index scan is required. If that happens, - * scan_page won't be scanned by any backend (unless the next primitive index - * scan lands on scan_page). + * determine that another primitive index scan is required. + * + * If caller's next_scan_page is P_NONE, the scan has reached the index's + * rightmost/leftmost page. This is treated as reaching the end of the scan + * within _bt_parallel_seize. + * + * Note: unlike the serial case, parallel scans don't need to remember both + * sibling links. next_scan_page is whichever link is next given the scan's + * direction. That's all we'll ever need, since the direction of a parallel + * scan can never change. */ void -_bt_parallel_release(IndexScanDesc scan, BlockNumber scan_page) +_bt_parallel_release(IndexScanDesc scan, BlockNumber next_scan_page, + BlockNumber curr_page) { ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; - btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, - parallel_scan->ps_offset); + Assert(BlockNumberIsValid(next_scan_page)); - SpinLockAcquire(&btscan->btps_mutex); - btscan->btps_scanPage = scan_page; + btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan, + parallel_scan->ps_offset_am); + + LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE); + btscan->btps_nextScanPage = next_scan_page; + btscan->btps_lastCurrPage = curr_page; btscan->btps_pageStatus = BTPARALLEL_IDLE; - SpinLockRelease(&btscan->btps_mutex); + LWLockRelease(&btscan->btps_lock); ConditionVariableSignal(&btscan->btps_cv); } @@ -731,28 +980,39 @@ _bt_parallel_release(IndexScanDesc scan, BlockNumber scan_page) void _bt_parallel_done(IndexScanDesc scan) { + BTScanOpaque so = (BTScanOpaque) scan->opaque; ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; bool status_changed = false; + Assert(!BTScanPosIsValid(so->currPos)); + /* Do nothing, for non-parallel scans */ if (parallel_scan == NULL) return; - btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, - parallel_scan->ps_offset); + /* + * Should not mark parallel scan done when there's still a pending + * primitive index scan + */ + if (so->needPrimScan) + return; + + btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan, + parallel_scan->ps_offset_am); /* * Mark the parallel scan as done, unless some other process did so * already */ - SpinLockAcquire(&btscan->btps_mutex); + LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE); + Assert(btscan->btps_pageStatus != BTPARALLEL_NEED_PRIMSCAN); if (btscan->btps_pageStatus != BTPARALLEL_DONE) { btscan->btps_pageStatus = BTPARALLEL_DONE; status_changed = true; } - SpinLockRelease(&btscan->btps_mutex); + LWLockRelease(&btscan->btps_lock); /* wake up all the workers associated with this parallel scan */ if (status_changed) @@ -762,39 +1022,36 @@ _bt_parallel_done(IndexScanDesc scan) /* * _bt_parallel_primscan_schedule() -- Schedule another primitive index scan. * - * Caller passes the block number most recently passed to _bt_parallel_release + * Caller passes the curr_page most recently passed to _bt_parallel_release * by its backend. Caller successfully schedules the next primitive index scan * if the shared parallel state hasn't been seized since caller's backend last * advanced the scan. */ void -_bt_parallel_primscan_schedule(IndexScanDesc scan, BlockNumber prev_scan_page) +_bt_parallel_primscan_schedule(IndexScanDesc scan, BlockNumber curr_page) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; ParallelIndexScanDesc parallel_scan = scan->parallel_scan; BTParallelScanDesc btscan; Assert(so->numArrayKeys); - btscan = (BTParallelScanDesc) OffsetToPointer((void *) parallel_scan, - parallel_scan->ps_offset); + btscan = (BTParallelScanDesc) OffsetToPointer(parallel_scan, + parallel_scan->ps_offset_am); - SpinLockAcquire(&btscan->btps_mutex); - if (btscan->btps_scanPage == prev_scan_page && + LWLockAcquire(&btscan->btps_lock, LW_EXCLUSIVE); + if (btscan->btps_lastCurrPage == curr_page && btscan->btps_pageStatus == BTPARALLEL_IDLE) { - btscan->btps_scanPage = InvalidBlockNumber; + btscan->btps_nextScanPage = InvalidBlockNumber; + btscan->btps_lastCurrPage = InvalidBlockNumber; btscan->btps_pageStatus = BTPARALLEL_NEED_PRIMSCAN; /* Serialize scan's current array keys */ - for (int i = 0; i < so->numArrayKeys; i++) - { - BTArrayKeyInfo *array = &so->arrayKeys[i]; - - btscan->btps_arrElems[i] = array->cur_elem; - } + _bt_parallel_serialize_arrays(rel, btscan, so); } - SpinLockRelease(&btscan->btps_mutex); + LWLockRelease(&btscan->btps_lock); } /* @@ -930,8 +1187,9 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, Relation rel = info->index; BTVacState vstate; BlockNumber num_pages; - BlockNumber scanblkno; bool needLock; + BlockRangeReadStreamPrivate p; + ReadStream *stream = NULL; /* * Reset fields that track information about the entire index now. This @@ -1000,7 +1258,21 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, */ needLock = !RELATION_IS_LOCAL(rel); - scanblkno = BTREE_METAPAGE + 1; + p.current_blocknum = BTREE_METAPAGE + 1; + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, + info->strategy, + rel, + MAIN_FORKNUM, + block_range_read_stream_cb, + &p, + 0); for (;;) { /* Get the current relation length */ @@ -1015,18 +1287,42 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, num_pages); /* Quit if we've scanned the whole relation */ - if (scanblkno >= num_pages) + if (p.current_blocknum >= num_pages) break; - /* Iterate over pages, then loop back to recheck length */ - for (; scanblkno < num_pages; scanblkno++) + + p.last_exclusive = num_pages; + + /* Iterate over pages, then loop back to recheck relation length */ + while (true) { - btvacuumpage(&vstate, scanblkno); + BlockNumber current_block; + Buffer buf; + + /* call vacuum_delay_point while not holding any buffer lock */ + vacuum_delay_point(false); + + buf = read_stream_next_buffer(stream, NULL); + + if (!BufferIsValid(buf)) + break; + + current_block = btvacuumpage(&vstate, buf); + if (info->report_progress) pgstat_progress_update_param(PROGRESS_SCAN_BLOCKS_DONE, - scanblkno); + current_block); } + + /* + * We have to reset the read stream to use it again. After returning + * InvalidBuffer, the read stream API won't invoke our callback again + * until the stream has been reset. + */ + read_stream_reset(stream); } + read_stream_end(stream); + /* Set statistics num_pages field to final size of index */ stats->num_pages = num_pages; @@ -1050,14 +1346,16 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, * btvacuumpage --- VACUUM one page * * This processes a single page for btvacuumscan(). In some cases we must - * backtrack to re-examine and VACUUM pages that were the scanblkno during + * backtrack to re-examine and VACUUM pages that were on buf's page during * a previous call here. This is how we handle page splits (that happened * after our cycleid was acquired) whose right half page happened to reuse * a block that we might have processed at some point before it was * recycled (i.e. before the page split). + * + * Returns BlockNumber of a scanned page (not backtracked). */ -static void -btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) +static BlockNumber +btvacuumpage(BTVacState *vstate, Buffer buf) { IndexVacuumInfo *info = vstate->info; IndexBulkDeleteResult *stats = vstate->stats; @@ -1068,7 +1366,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) bool attempt_pagedel; BlockNumber blkno, backtrack_to; - Buffer buf; + BlockNumber scanblkno = BufferGetBlockNumber(buf); Page page; BTPageOpaque opaque; @@ -1079,17 +1377,6 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) attempt_pagedel = false; backtrack_to = P_NONE; - /* call vacuum_delay_point while not holding any buffer lock */ - vacuum_delay_point(); - - /* - * We can't use _bt_getbuf() here because it always applies - * _bt_checkpage(), which will barf on an all-zero page. We want to - * recycle all-zero pages, not fail. Also, we want to use a nondefault - * buffer access strategy. - */ - buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, - info->strategy); _bt_lockbuf(rel, buf, BT_READ); page = BufferGetPage(buf); opaque = NULL; @@ -1125,7 +1412,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) errmsg_internal("right sibling %u of scanblkno %u unexpectedly in an inconsistent state in index \"%s\"", blkno, scanblkno, RelationGetRelationName(rel)))); _bt_relbuf(rel, buf); - return; + return scanblkno; } /* @@ -1145,7 +1432,7 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) { /* Done with current scanblkno (and all lower split pages) */ _bt_relbuf(rel, buf); - return; + return scanblkno; } } @@ -1376,8 +1663,22 @@ btvacuumpage(BTVacState *vstate, BlockNumber scanblkno) if (backtrack_to != P_NONE) { blkno = backtrack_to; + + /* check for vacuum delay while not holding any buffer lock */ + vacuum_delay_point(false); + + /* + * We can't use _bt_getbuf() here because it always applies + * _bt_checkpage(), which will barf on an all-zero page. We want to + * recycle all-zero pages, not fail. Also, we want to use a + * nondefault buffer access strategy. + */ + buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, + info->strategy); goto backtrack; } + + return scanblkno; } /* @@ -1445,3 +1746,52 @@ btcanreturn(Relation index, int attno) { return true; } + +/* + * btgettreeheight() -- Compute tree height for use by btcostestimate(). + */ +int +btgettreeheight(Relation rel) +{ + return _bt_getrootheight(rel); +} + +CompareType +bttranslatestrategy(StrategyNumber strategy, Oid opfamily) +{ + switch (strategy) + { + case BTLessStrategyNumber: + return COMPARE_LT; + case BTLessEqualStrategyNumber: + return COMPARE_LE; + case BTEqualStrategyNumber: + return COMPARE_EQ; + case BTGreaterEqualStrategyNumber: + return COMPARE_GE; + case BTGreaterStrategyNumber: + return COMPARE_GT; + default: + return COMPARE_INVALID; + } +} + +StrategyNumber +bttranslatecmptype(CompareType cmptype, Oid opfamily) +{ + switch (cmptype) + { + case COMPARE_LT: + return BTLessStrategyNumber; + case COMPARE_LE: + return BTLessEqualStrategyNumber; + case COMPARE_EQ: + return BTEqualStrategyNumber; + case COMPARE_GE: + return BTGreaterEqualStrategyNumber; + case COMPARE_GT: + return BTGreaterStrategyNumber; + default: + return InvalidStrategy; + } +} diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 57bcfc7e4c642..36544ecfd5878 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -4,7 +4,7 @@ * Search code for postgres btrees. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -25,12 +25,15 @@ #include "utils/rel.h" -static void _bt_drop_lock_and_maybe_pin(IndexScanDesc scan, BTScanPos sp); +static inline void _bt_drop_lock_and_maybe_pin(Relation rel, BTScanOpaque so); +static Buffer _bt_moveright(Relation rel, Relation heaprel, BTScanInsert key, + Buffer buf, bool forupdate, BTStack stack, + int access); static OffsetNumber _bt_binsrch(Relation rel, BTScanInsert key, Buffer buf); static int _bt_binsrch_posting(BTScanInsert key, Page page, OffsetNumber offnum); static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir, - OffsetNumber offnum, bool firstPage); + OffsetNumber offnum, bool firstpage); static void _bt_saveitem(BTScanOpaque so, int itemIndex, OffsetNumber offnum, IndexTuple itup); static int _bt_setuppostingitems(BTScanOpaque so, int itemIndex, @@ -39,36 +42,44 @@ static int _bt_setuppostingitems(BTScanOpaque so, int itemIndex, static inline void _bt_savepostingitem(BTScanOpaque so, int itemIndex, OffsetNumber offnum, ItemPointer heapTid, int tupleOffset); +static inline void _bt_returnitem(IndexScanDesc scan, BTScanOpaque so); static bool _bt_steppage(IndexScanDesc scan, ScanDirection dir); -static bool _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir); -static bool _bt_parallel_readpage(IndexScanDesc scan, BlockNumber blkno, - ScanDirection dir); -static Buffer _bt_walk_left(Relation rel, Buffer buf); +static bool _bt_readfirstpage(IndexScanDesc scan, OffsetNumber offnum, + ScanDirection dir); +static bool _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, + BlockNumber lastcurrblkno, ScanDirection dir, + bool seized); +static Buffer _bt_lock_and_validate_left(Relation rel, BlockNumber *blkno, + BlockNumber lastcurrblkno); static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir); -static inline void _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir); /* * _bt_drop_lock_and_maybe_pin() * - * Unlock the buffer; and if it is safe to release the pin, do that, too. - * This will prevent vacuum from stalling in a blocked state trying to read a - * page when a cursor is sitting on it. - * - * See nbtree/README section on making concurrent TID recycling safe. + * Unlock so->currPos.buf. If scan is so->dropPin, drop the pin, too. + * Dropping the pin prevents VACUUM from blocking on acquiring a cleanup lock. */ -static void -_bt_drop_lock_and_maybe_pin(IndexScanDesc scan, BTScanPos sp) +static inline void +_bt_drop_lock_and_maybe_pin(Relation rel, BTScanOpaque so) { - _bt_unlockbuf(scan->indexRelation, sp->buf); - - if (IsMVCCSnapshot(scan->xs_snapshot) && - RelationNeedsWAL(scan->indexRelation) && - !scan->xs_want_itup) + if (!so->dropPin) { - ReleaseBuffer(sp->buf); - sp->buf = InvalidBuffer; + /* Just drop the lock (not the pin) */ + _bt_unlockbuf(rel, so->currPos.buf); + return; } + + /* + * Drop both the lock and the pin. + * + * Have to set so->currPos.lsn so that _bt_killitems has a way to detect + * when concurrent heap TID recycling by VACUUM might have taken place. + */ + Assert(RelationNeedsWAL(rel)); + so->currPos.lsn = BufferGetLSNAtomic(so->currPos.buf); + _bt_relbuf(rel, so->currPos.buf); + so->currPos.buf = InvalidBuffer; } /* @@ -231,7 +242,7 @@ _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP, * 'access'. If we move right, we release the buffer and lock and acquire * the same on the right sibling. Return value is the buffer we stop at. */ -Buffer +static Buffer _bt_moveright(Relation rel, Relation heaprel, BTScanInsert key, @@ -858,14 +869,14 @@ _bt_compare(Relation rel, * We need to be clever about the direction of scan, the search * conditions, and the tree ordering. We find the first item (or, * if backwards scan, the last item) in the tree that satisfies the - * qualifications in the scan key. On success exit, the page containing - * the current index tuple is pinned but not locked, and data about - * the matching tuple(s) on the page has been loaded into so->currPos. - * scan->xs_heaptid is set to the heap TID of the current tuple, and if - * requested, scan->xs_itup points to a copy of the index tuple. + * qualifications in the scan key. On success exit, data about the + * matching tuple(s) on the page has been loaded into so->currPos. We'll + * drop all locks and hold onto a pin on page's buffer, except during + * so->dropPin scans, when we drop both the lock and the pin. + * _bt_returnitem sets the next item to return to scan on success exit. * * If there are no matching items in the index, we return false, with no - * pins or locks held. + * pins or locks held. so->currPos will remain invalid. * * Note that scan->keyData[], and the so->keyData[] scankey built from it, * are both search-type scankeys (see nbtree/README for more about this). @@ -877,24 +888,18 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) { Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; - Buffer buf; BTStack stack; OffsetNumber offnum; - StrategyNumber strat; BTScanInsertData inskey; ScanKey startKeys[INDEX_MAX_KEYS]; ScanKeyData notnullkeys[INDEX_MAX_KEYS]; int keysz = 0; - int i; - bool status; StrategyNumber strat_total; - BTScanPosItem *currItem; - BlockNumber blkno; + BlockNumber blkno = InvalidBlockNumber, + lastcurrblkno; Assert(!BTScanPosIsValid(so->currPos)); - pgstat_count_index_scan(rel); - /* * Examine the scan keys and eliminate any redundant keys; also mark the * keys that must be matched to continue the scan. @@ -907,56 +912,52 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) */ if (!so->qual_ok) { + Assert(!so->needPrimScan); _bt_parallel_done(scan); return false; } /* - * For parallel scans, get the starting page from shared state. If the - * scan has not started, proceed to find out first leaf page in the usual - * way while keeping other participating processes waiting. If the scan - * has already begun, use the page number from the shared structure. - * - * When a parallel scan has another primitive index scan scheduled, a - * parallel worker will seize the scan for that purpose now. This is - * similar to the case where the top-level scan hasn't started. + * If this is a parallel scan, we must seize the scan. _bt_readfirstpage + * will likely release the parallel scan later on. */ - if (scan->parallel_scan != NULL) - { - status = _bt_parallel_seize(scan, &blkno, true); + if (scan->parallel_scan != NULL && + !_bt_parallel_seize(scan, &blkno, &lastcurrblkno, true)) + return false; - /* - * Initialize arrays (when _bt_parallel_seize didn't already set up - * the next primitive index scan) - */ - if (so->numArrayKeys && !so->needPrimScan) - _bt_start_array_keys(scan, dir); + /* + * Initialize the scan's arrays (if any) for the current scan direction + * (except when they were already set to later values as part of + * scheduling the primitive index scan that is now underway) + */ + if (so->numArrayKeys && !so->needPrimScan) + _bt_start_array_keys(scan, dir); - if (!status) - return false; - else if (blkno == P_NONE) - { - _bt_parallel_done(scan); - return false; - } - else if (blkno != InvalidBlockNumber) - { - if (!_bt_parallel_readpage(scan, blkno, dir)) - return false; - goto readcomplete; - } - } - else if (so->numArrayKeys && !so->needPrimScan) + if (blkno != InvalidBlockNumber) { /* - * First _bt_first call (for current btrescan) without parallelism. - * - * Initialize arrays, and the corresponding scan keys that were just - * output by _bt_preprocess_keys. + * We anticipated calling _bt_search, but another worker bet us to it. + * _bt_readnextpage releases the scan for us (not _bt_readfirstpage). */ - _bt_start_array_keys(scan, dir); + Assert(scan->parallel_scan != NULL); + Assert(!so->needPrimScan); + Assert(blkno != P_NONE); + + if (!_bt_readnextpage(scan, blkno, lastcurrblkno, dir, true)) + return false; + + _bt_returnitem(scan, so); + return true; } + /* + * Count an indexscan for stats, now that we know that we'll call + * _bt_search/_bt_endpoint below + */ + pgstat_count_index_scan(rel); + if (scan->instrument) + scan->instrument->nsearches++; + /*---------- * Examine the scan keys to discover where we need to start the scan. * @@ -987,7 +988,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * one we use --- by definition, they are either redundant or * contradictory. * - * Any regular (not SK_SEARCHNULL) key implies a NOT NULL qualifier. + * In practice we rarely see any "attribute boundary key gaps" here. + * Preprocessing can usually backfill skip array keys for any attributes + * that were omitted from the original scan->keyData[] input keys. All + * array keys are always considered = keys, but we'll sometimes need to + * treat the current key value as if we were using an inequality strategy. + * This happens with range skip arrays, which store inequality keys in the + * array's low_compare/high_compare fields (used to find the first/last + * set of matches, when = key will lack a usable sk_argument value). + * These are always preferred over any redundant "standard" inequality + * keys on the same column (per the usual rule about preferring = keys). + * Note also that any column with an = skip array key can never have an + * additional, contradictory = key. + * + * All keys (with the exception of SK_SEARCHNULL keys and SK_BT_SKIP + * array keys whose array is "null_elem=true") imply a NOT NULL qualifier. * If the index stores nulls at the end of the index we'll be starting * from, and we have no boundary key for the column (which means the key * we deduced NOT NULL from is an inequality key that constrains the other @@ -1028,6 +1043,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * We don't cast the decision in stone until we reach keys for the * next attribute. */ + cur = so->keyData; curattr = 1; chosen = NULL; /* Also remember any scankey that implies a NOT NULL constraint */ @@ -1038,13 +1054,59 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * pass to handle after-last-key processing. Actual exit from the * loop is at one of the "break" statements below. */ - for (cur = so->keyData, i = 0;; cur++, i++) + for (int i = 0;; cur++, i++) { if (i >= so->numberOfKeys || cur->sk_attno != curattr) { /* - * Done looking at keys for curattr. If we didn't find a - * usable boundary key, see if we can deduce a NOT NULL key. + * Done looking at keys for curattr. + * + * If this is a scan key for a skip array whose current + * element is MINVAL, choose low_compare (when scanning + * backwards it'll be MAXVAL, and we'll choose high_compare). + * + * Note: if the array's low_compare key makes 'chosen' NULL, + * then we behave as if the array's first element is -inf, + * except when !array->null_elem implies a usable NOT NULL + * constraint. + */ + if (chosen != NULL && + (chosen->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL))) + { + int ikey = chosen - so->keyData; + ScanKey skipequalitykey = chosen; + BTArrayKeyInfo *array = NULL; + + for (int arridx = 0; arridx < so->numArrayKeys; arridx++) + { + array = &so->arrayKeys[arridx]; + if (array->scan_key == ikey) + break; + } + + if (ScanDirectionIsForward(dir)) + { + Assert(!(skipequalitykey->sk_flags & SK_BT_MAXVAL)); + chosen = array->low_compare; + } + else + { + Assert(!(skipequalitykey->sk_flags & SK_BT_MINVAL)); + chosen = array->high_compare; + } + + Assert(chosen == NULL || + chosen->sk_attno == skipequalitykey->sk_attno); + + if (!array->null_elem) + impliesNN = skipequalitykey; + else + Assert(chosen == NULL && impliesNN == NULL); + } + + /* + * If we didn't find a usable boundary key, see if we can + * deduce a NOT NULL key */ if (chosen == NULL && impliesNN != NULL && ((impliesNN->sk_flags & SK_BT_NULLS_FIRST) ? @@ -1076,22 +1138,51 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) startKeys[keysz++] = chosen; /* - * Adjust strat_total, and quit if we have stored a > or < - * key. + * We can only consider adding more boundary keys when the one + * that we just chose to add uses either the = or >= strategy + * (during backwards scans we can only do so when the key that + * we just added to startKeys[] uses the = or <= strategy) */ - strat = chosen->sk_strategy; - if (strat != BTEqualStrategyNumber) + strat_total = chosen->sk_strategy; + if (strat_total == BTGreaterStrategyNumber || + strat_total == BTLessStrategyNumber) + break; + + /* + * If the key that we just added to startKeys[] is a skip + * array = key whose current element is marked NEXT or PRIOR, + * make strat_total > or < (and stop adding boundary keys). + * This can only happen with opclasses that lack skip support. + */ + if (chosen->sk_flags & (SK_BT_NEXT | SK_BT_PRIOR)) { - strat_total = strat; - if (strat == BTGreaterStrategyNumber || - strat == BTLessStrategyNumber) - break; + Assert(chosen->sk_flags & SK_BT_SKIP); + Assert(strat_total == BTEqualStrategyNumber); + + if (ScanDirectionIsForward(dir)) + { + Assert(!(chosen->sk_flags & SK_BT_PRIOR)); + strat_total = BTGreaterStrategyNumber; + } + else + { + Assert(!(chosen->sk_flags & SK_BT_NEXT)); + strat_total = BTLessStrategyNumber; + } + + /* + * We're done. We'll never find an exact = match for a + * NEXT or PRIOR sentinel sk_argument value. There's no + * sense in trying to add more keys to startKeys[]. + */ + break; } /* - * Done if that was the last attribute, or if next key is not - * in sequence (implying no boundary key is available for the - * next attribute). + * Done if that was the last scan key output by preprocessing. + * Also done if there is a gap index attribute that lacks a + * usable key (only possible when preprocessing was unable to + * generate a skip array key to "fill in the gap"). */ if (i >= so->numberOfKeys || cur->sk_attno != curattr + 1) @@ -1146,31 +1237,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * If we found no usable boundary keys, we have to start from one end of * the tree. Walk down that edge to the first or last key, and scan from * there. + * + * Note: calls _bt_readfirstpage for us, which releases the parallel scan. */ if (keysz == 0) - { - bool match; - - match = _bt_endpoint(scan, dir); - - if (!match) - { - /* No match, so mark (parallel) scan finished */ - _bt_parallel_done(scan); - } - - return match; - } + return _bt_endpoint(scan, dir); /* * We want to start the scan somewhere within the index. Set up an * insertion scankey we can use to search for the boundary point we * identified above. The insertion scankey is built using the keys * identified by startKeys[]. (Remaining insertion scankey fields are - * initialized after initial-positioning strategy is finalized.) + * initialized after initial-positioning scan keys are finalized.) */ Assert(keysz <= INDEX_MAX_KEYS); - for (i = 0; i < keysz; i++) + for (int i = 0; i < keysz; i++) { ScanKey cur = startKeys[i]; @@ -1179,22 +1260,23 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) if (cur->sk_flags & SK_ROW_HEADER) { /* - * Row comparison header: look to the first row member instead. - * - * The member scankeys are already in insertion format (ie, they - * have sk_func = 3-way-comparison function), but we have to watch - * out for nulls, which _bt_preprocess_keys didn't check. A null - * in the first row member makes the condition unmatchable, just - * like qual_ok = false. + * Row comparison header: look to the first row member instead */ ScanKey subkey = (ScanKey) DatumGetPointer(cur->sk_argument); + /* + * Cannot be a NULL in the first row member: _bt_preprocess_keys + * would've marked the qual as unsatisfiable, preventing us from + * ever getting this far + */ Assert(subkey->sk_flags & SK_ROW_MEMBER); - if (subkey->sk_flags & SK_ISNULL) - { - _bt_parallel_done(scan); - return false; - } + Assert(subkey->sk_attno == cur->sk_attno); + Assert(!(subkey->sk_flags & SK_ISNULL)); + + /* + * The member scankeys are already in insertion format (ie, they + * have sk_func = 3-way-comparison function) + */ memcpy(inskey.scankeys + i, subkey, sizeof(ScanKeyData)); /* @@ -1385,12 +1467,12 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * position ourselves on the target leaf page. */ Assert(ScanDirectionIsBackward(dir) == inskey.backward); - stack = _bt_search(rel, NULL, &inskey, &buf, BT_READ); + stack = _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ); /* don't need to keep the stack around... */ _bt_freestack(stack); - if (!BufferIsValid(buf)) + if (!BufferIsValid(so->currPos.buf)) { /* * We only get here if the index is completely empty. Lock relation @@ -1404,33 +1486,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) if (IsolationIsSerializable()) { PredicateLockRelation(rel, scan->xs_snapshot); - stack = _bt_search(rel, NULL, &inskey, &buf, BT_READ); + stack = _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ); _bt_freestack(stack); } - if (!BufferIsValid(buf)) + if (!BufferIsValid(so->currPos.buf)) { - /* - * Mark parallel scan as done, so that all the workers can finish - * their scan. - */ + Assert(!so->needPrimScan); _bt_parallel_done(scan); - BTScanPosInvalidate(so->currPos); return false; } } - PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot); - - _bt_initialize_more_data(so, dir); - /* position to the precise item on the page */ - offnum = _bt_binsrch(rel, &inskey, buf); - Assert(!BTScanPosIsValid(so->currPos)); - so->currPos.buf = buf; + offnum = _bt_binsrch(rel, &inskey, so->currPos.buf); /* - * Now load data from the first page of the scan. + * Now load data from the first page of the scan (usually the page + * currently in so->currPos.buf). * * If inskey.nextkey = false and inskey.backward = false, offnum is * positioned at the first non-pivot tuple >= inskey.scankeys. @@ -1448,29 +1521,10 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * for the page. For example, when inskey is both < the leaf page's high * key and > all of its non-pivot tuples, offnum will be "maxoff + 1". */ - if (!_bt_readpage(scan, dir, offnum, true)) - { - /* - * There's no actually-matching data on this page. Try to advance to - * the next page. Return false if there's no matching data at all. - */ - _bt_unlockbuf(scan->indexRelation, so->currPos.buf); - if (!_bt_steppage(scan, dir)) - return false; - } - else - { - /* We have at least one item to return as scan's first item */ - _bt_drop_lock_and_maybe_pin(scan, &so->currPos); - } - -readcomplete: - /* OK, itemIndex says what to return */ - currItem = &so->currPos.items[so->currPos.itemIndex]; - scan->xs_heaptid = currItem->heapTid; - if (scan->xs_want_itup) - scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); + if (!_bt_readfirstpage(scan, offnum, dir)) + return false; + _bt_returnitem(scan, so); return true; } @@ -1481,18 +1535,19 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * but is not locked, and so->currPos.itemIndex identifies which item was * previously returned. * - * On successful exit, scan->xs_heaptid is set to the TID of the next - * heap tuple, and if requested, scan->xs_itup points to a copy of the - * index tuple. so->currPos is updated as needed. + * On success exit, so->currPos is updated as needed, and _bt_returnitem + * sets the next item to return to the scan. so->currPos remains valid. * - * On failure exit (no more tuples), we release pin and set - * so->currPos.buf to InvalidBuffer. + * On failure exit (no more tuples), we invalidate so->currPos. It'll + * still be possible for the scan to return tuples by changing direction, + * though we'll need to call _bt_first anew in that other direction. */ bool _bt_next(IndexScanDesc scan, ScanDirection dir) { BTScanOpaque so = (BTScanOpaque) scan->opaque; - BTScanPosItem *currItem; + + Assert(BTScanPosIsValid(so->currPos)); /* * Advance to next tuple on current page; or if there's no more, try to @@ -1515,12 +1570,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) } } - /* OK, itemIndex says what to return */ - currItem = &so->currPos.items[so->currPos.itemIndex]; - scan->xs_heaptid = currItem->heapTid; - if (scan->xs_want_itup) - scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); - + _bt_returnitem(scan, so); return true; } @@ -1538,14 +1588,6 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) * that there can be no more matching tuples in the current scan direction * (could just be for the current primitive index scan when scan has arrays). * - * _bt_first caller passes us an offnum returned by _bt_binsrch, which might - * be an out of bounds offnum such as "maxoff + 1" in certain corner cases. - * _bt_checkkeys will stop the scan as soon as an equality qual fails (when - * its scan key was marked required), so _bt_first _must_ pass us an offnum - * exactly at the beginning of where equal tuples are to be found. When we're - * passed an offnum past the end of the page, we might still manage to stop - * the scan on this page by calling _bt_checkkeys against the high key. - * * In the case of a parallel scan, caller must have called _bt_parallel_seize * prior to calling this function; this function will invoke * _bt_parallel_release before returning. @@ -1554,8 +1596,9 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) */ static bool _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, - bool firstPage) + bool firstpage) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; Page page; BTPageOpaque opaque; @@ -1566,138 +1609,91 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, int itemIndex, indnatts; - /* - * We must have the buffer pinned and locked, but the usual macro can't be - * used here; this function is what makes it good for currPos. - */ - Assert(BufferIsValid(so->currPos.buf)); - + /* save the page/buffer block number, along with its sibling links */ page = BufferGetPage(so->currPos.buf); opaque = BTPageGetOpaque(page); + so->currPos.currPage = BufferGetBlockNumber(so->currPos.buf); + so->currPos.prevPage = opaque->btpo_prev; + so->currPos.nextPage = opaque->btpo_next; + /* delay setting so->currPos.lsn until _bt_drop_lock_and_maybe_pin */ + so->currPos.dir = dir; + so->currPos.nextTupleOffset = 0; + + /* either moreRight or moreLeft should be set now (may be unset later) */ + Assert(ScanDirectionIsForward(dir) ? so->currPos.moreRight : + so->currPos.moreLeft); + Assert(!P_IGNORE(opaque)); + Assert(BTScanPosIsPinned(so->currPos)); + Assert(!so->needPrimScan); - /* allow next page be processed by parallel worker */ if (scan->parallel_scan) { + /* allow next/prev page to be read by other worker without delay */ if (ScanDirectionIsForward(dir)) - pstate.prev_scan_page = opaque->btpo_next; + _bt_parallel_release(scan, so->currPos.nextPage, + so->currPos.currPage); else - pstate.prev_scan_page = BufferGetBlockNumber(so->currPos.buf); - - _bt_parallel_release(scan, pstate.prev_scan_page); + _bt_parallel_release(scan, so->currPos.prevPage, + so->currPos.currPage); } - indnatts = IndexRelationGetNumberOfAttributes(scan->indexRelation); + PredicateLockPage(rel, so->currPos.currPage, scan->xs_snapshot); + + /* initialize local variables */ + indnatts = IndexRelationGetNumberOfAttributes(rel); arrayKeys = so->numArrayKeys != 0; minoff = P_FIRSTDATAKEY(opaque); maxoff = PageGetMaxOffsetNumber(page); /* initialize page-level state that we'll pass to _bt_checkkeys */ - pstate.dir = dir; pstate.minoff = minoff; pstate.maxoff = maxoff; pstate.finaltup = NULL; pstate.page = page; + pstate.firstpage = firstpage; + pstate.forcenonrequired = false; + pstate.startikey = 0; pstate.offnum = InvalidOffsetNumber; pstate.skip = InvalidOffsetNumber; pstate.continuescan = true; /* default assumption */ - pstate.prechecked = false; - pstate.firstmatch = false; pstate.rechecks = 0; pstate.targetdistance = 0; - - /* - * We note the buffer's block number so that we can release the pin later. - * This allows us to re-read the buffer if it is needed again for hinting. - */ - so->currPos.currPage = BufferGetBlockNumber(so->currPos.buf); - - /* - * We save the LSN of the page as we read it, so that we know whether it - * safe to apply LP_DEAD hints to the page later. This allows us to drop - * the pin for MVCC scans, which allows vacuum to avoid blocking. - */ - so->currPos.lsn = BufferGetLSNAtomic(so->currPos.buf); - - /* - * we must save the page's right-link while scanning it; this tells us - * where to step right to after we're done with these items. There is no - * corresponding need for the left-link, since splits always go right. - */ - so->currPos.nextPage = opaque->btpo_next; - - /* initialize tuple workspace to empty */ - so->currPos.nextTupleOffset = 0; - - /* - * Now that the current page has been made consistent, the macro should be - * good. - */ - Assert(BTScanPosIsPinned(so->currPos)); - - /* - * Prechecking the value of the continuescan flag for the last item on the - * page (for backwards scan it will be the first item on a page). If we - * observe it to be true, then it should be true for all other items. This - * allows us to do significant optimizations in the _bt_checkkeys() - * function for all the items on the page. - * - * With the forward scan, we do this check for the last item on the page - * instead of the high key. It's relatively likely that the most - * significant column in the high key will be different from the - * corresponding value from the last item on the page. So checking with - * the last item on the page would give a more precise answer. - * - * We skip this for the first page read by each (primitive) scan, to avoid - * slowing down point queries. They typically don't stand to gain much - * when the optimization can be applied, and are more likely to notice the - * overhead of the precheck. - * - * The optimization is unsafe and must be avoided whenever _bt_checkkeys - * just set a low-order required array's key to the best available match - * for a truncated -inf attribute value from the prior page's high key - * (array element 0 is always the best available match in this scenario). - * It's quite likely that matches for array element 0 begin on this page, - * but the start of matches won't necessarily align with page boundaries. - * When the start of matches is somewhere in the middle of this page, it - * would be wrong to treat page's final non-pivot tuple as representative. - * Doing so might lead us to treat some of the page's earlier tuples as - * being part of a group of tuples thought to satisfy the required keys. - * - * Note: Conversely, in the case where the scan's arrays just advanced - * using the prior page's HIKEY _without_ advancement setting scanBehind, - * the start of matches must be aligned with page boundaries, which makes - * it safe to attempt the optimization here now. It's also safe when the - * prior page's HIKEY simply didn't need to advance any required array. In - * both cases we can safely assume that the _first_ tuple from this page - * must be >= the current set of array keys/equality constraints. And so - * if the final tuple is == those same keys (and also satisfies any - * required < or <= strategy scan keys) during the precheck, we can safely - * assume that this must also be true of all earlier tuples from the page. - */ - if (!firstPage && !so->scanBehind && minoff < maxoff) - { - ItemId iid; - IndexTuple itup; - - iid = PageGetItemId(page, ScanDirectionIsForward(dir) ? maxoff : minoff); - itup = (IndexTuple) PageGetItem(page, iid); - - /* Call with arrayKeys=false to avoid undesirable side-effects */ - _bt_checkkeys(scan, &pstate, false, itup, indnatts); - pstate.prechecked = pstate.continuescan; - pstate.continuescan = true; /* reset */ - } + pstate.nskipadvances = 0; if (ScanDirectionIsForward(dir)) { /* SK_SEARCHARRAY forward scans must provide high key up front */ - if (arrayKeys && !P_RIGHTMOST(opaque)) + if (arrayKeys) { - ItemId iid = PageGetItemId(page, P_HIKEY); + if (!P_RIGHTMOST(opaque)) + { + ItemId iid = PageGetItemId(page, P_HIKEY); - pstate.finaltup = (IndexTuple) PageGetItem(page, iid); + pstate.finaltup = (IndexTuple) PageGetItem(page, iid); + + if (so->scanBehind && + !_bt_scanbehind_checkkeys(scan, dir, pstate.finaltup)) + { + /* Schedule another primitive index scan after all */ + so->currPos.moreRight = false; + so->needPrimScan = true; + if (scan->parallel_scan) + _bt_parallel_primscan_schedule(scan, + so->currPos.currPage); + return false; + } + } + + so->scanBehind = so->oppositeDirCheck = false; /* reset */ } + /* + * Consider pstate.startikey optimization once the ongoing primitive + * index scan has already read at least one page + */ + if (!pstate.firstpage && minoff < maxoff) + _bt_set_startikey(scan, &pstate); + /* load items[] in ascending order */ itemIndex = 0; @@ -1734,6 +1730,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, { Assert(!passes_quals && pstate.continuescan); Assert(offnum < pstate.skip); + Assert(!pstate.forcenonrequired); offnum = pstate.skip; pstate.skip = InvalidOffsetNumber; @@ -1743,7 +1740,6 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, if (passes_quals) { /* tuple passes all scan key conditions */ - pstate.firstmatch = true; if (!BTreeTupleIsPosting(itup)) { /* Remember it */ @@ -1791,14 +1787,19 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, * only appear on non-pivot tuples on the right sibling page are * common. */ - if (pstate.continuescan && !P_RIGHTMOST(opaque)) + if (pstate.continuescan && !so->scanBehind && !P_RIGHTMOST(opaque)) { ItemId iid = PageGetItemId(page, P_HIKEY); IndexTuple itup = (IndexTuple) PageGetItem(page, iid); int truncatt; - truncatt = BTreeTupleGetNAtts(itup, scan->indexRelation); - pstate.prechecked = false; /* precheck didn't cover HIKEY */ + /* Reset arrays, per _bt_set_startikey contract */ + if (pstate.forcenonrequired) + _bt_start_array_keys(scan, dir); + pstate.forcenonrequired = false; + pstate.startikey = 0; /* _bt_set_startikey ignores P_HIKEY */ + + truncatt = BTreeTupleGetNAtts(itup, rel); _bt_checkkeys(scan, &pstate, arrayKeys, itup, truncatt); } @@ -1813,13 +1814,37 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, else { /* SK_SEARCHARRAY backward scans must provide final tuple up front */ - if (arrayKeys && minoff <= maxoff && !P_LEFTMOST(opaque)) + if (arrayKeys) { - ItemId iid = PageGetItemId(page, minoff); + if (minoff <= maxoff && !P_LEFTMOST(opaque)) + { + ItemId iid = PageGetItemId(page, minoff); + + pstate.finaltup = (IndexTuple) PageGetItem(page, iid); - pstate.finaltup = (IndexTuple) PageGetItem(page, iid); + if (so->scanBehind && + !_bt_scanbehind_checkkeys(scan, dir, pstate.finaltup)) + { + /* Schedule another primitive index scan after all */ + so->currPos.moreLeft = false; + so->needPrimScan = true; + if (scan->parallel_scan) + _bt_parallel_primscan_schedule(scan, + so->currPos.currPage); + return false; + } + } + + so->scanBehind = so->oppositeDirCheck = false; /* reset */ } + /* + * Consider pstate.startikey optimization once the ongoing primitive + * index scan has already read at least one page + */ + if (!pstate.firstpage && minoff < maxoff) + _bt_set_startikey(scan, &pstate); + /* load items[] in descending order */ itemIndex = MaxTIDsPerBTreePage; @@ -1844,8 +1869,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, */ if (scan->ignore_killed_tuples && ItemIdIsDead(iid)) { - Assert(offnum >= P_FIRSTDATAKEY(opaque)); - if (offnum > P_FIRSTDATAKEY(opaque)) + if (offnum > minoff) { offnum = OffsetNumberPrev(offnum); continue; @@ -1860,9 +1884,31 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, Assert(!BTreeTupleIsPivot(itup)); pstate.offnum = offnum; + if (arrayKeys && offnum == minoff && pstate.forcenonrequired) + { + /* Reset arrays, per _bt_set_startikey contract */ + pstate.forcenonrequired = false; + pstate.startikey = 0; + _bt_start_array_keys(scan, dir); + } passes_quals = _bt_checkkeys(scan, &pstate, arrayKeys, itup, indnatts); + if (arrayKeys && so->scanBehind) + { + /* + * Done scanning this page, but not done with the current + * primscan. + * + * Note: Forward scans don't check this explicitly, since they + * prefer to reuse pstate.skip for this instead. + */ + Assert(!passes_quals && pstate.continuescan); + Assert(!pstate.forcenonrequired); + + break; + } + /* * Check if we need to skip ahead to a later tuple (only possible * when the scan uses array keys) @@ -1871,6 +1917,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, { Assert(!passes_quals && pstate.continuescan); Assert(offnum > pstate.skip); + Assert(!pstate.forcenonrequired); offnum = pstate.skip; pstate.skip = InvalidOffsetNumber; @@ -1880,7 +1927,6 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, if (passes_quals && tuple_alive) { /* tuple passes all scan key conditions */ - pstate.firstmatch = true; if (!BTreeTupleIsPosting(itup)) { /* Remember it */ @@ -1916,22 +1962,40 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum, } } } + /* When !continuescan, there can't be any more matches, so stop */ if (!pstate.continuescan) - { - /* there can't be any more matches, so stop */ - so->currPos.moreLeft = false; break; - } offnum = OffsetNumberPrev(offnum); } + /* + * We don't need to visit page to the left when no more matches will + * be found there + */ + if (!pstate.continuescan) + so->currPos.moreLeft = false; + Assert(itemIndex >= 0); so->currPos.firstItem = itemIndex; so->currPos.lastItem = MaxTIDsPerBTreePage - 1; so->currPos.itemIndex = MaxTIDsPerBTreePage - 1; } + /* + * If _bt_set_startikey told us to temporarily treat the scan's keys as + * nonrequired (possible only during scans with array keys), there must be + * no lasting consequences for the scan's array keys. The scan's arrays + * should now have exactly the same elements as they would have had if the + * nonrequired behavior had never been used. (In general, a scan's arrays + * are expected to track its progress through the index's key space.) + * + * We are required (by _bt_set_startikey) to call _bt_checkkeys against + * pstate.finaltup with pstate.forcenonrequired=false to allow the scan's + * arrays to recover. Assert that that step hasn't been missed. + */ + Assert(!pstate.forcenonrequired); + return (so->currPos.firstItem <= so->currPos.lastItem); } @@ -2021,23 +2085,41 @@ _bt_savepostingitem(BTScanOpaque so, int itemIndex, OffsetNumber offnum, currItem->tupleOffset = tupleOffset; } +/* + * Return the index item from so->currPos.items[so->currPos.itemIndex] to the + * index scan by setting the relevant fields in caller's index scan descriptor + */ +static inline void +_bt_returnitem(IndexScanDesc scan, BTScanOpaque so) +{ + BTScanPosItem *currItem = &so->currPos.items[so->currPos.itemIndex]; + + /* Most recent _bt_readpage must have succeeded */ + Assert(BTScanPosIsValid(so->currPos)); + Assert(so->currPos.itemIndex >= so->currPos.firstItem); + Assert(so->currPos.itemIndex <= so->currPos.lastItem); + + /* Return next item, per amgettuple contract */ + scan->xs_heaptid = currItem->heapTid; + if (so->currTuples) + scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); +} + /* * _bt_steppage() -- Step to next page containing valid data for scan * - * On entry, if so->currPos.buf is valid the buffer is pinned but not locked; - * if pinned, we'll drop the pin before moving to next page. The buffer is - * not locked on entry. + * Wrapper on _bt_readnextpage that performs final steps for the current page. * - * For success on a scan using a non-MVCC snapshot we hold a pin, but not a - * read lock, on that page. If we do not hold the pin, we set so->currPos.buf - * to InvalidBuffer. We return true to indicate success. + * On entry, so->currPos must be valid. Its buffer will be pinned, though + * never locked. (Actually, when so->dropPin there won't even be a pin held, + * though so->currPos.currPage must still be set to a valid block number.) */ static bool _bt_steppage(IndexScanDesc scan, ScanDirection dir) { BTScanOpaque so = (BTScanOpaque) scan->opaque; - BlockNumber blkno = InvalidBlockNumber; - bool status; + BlockNumber blkno, + lastcurrblkno; Assert(BTScanPosIsValid(so->currPos)); @@ -2075,322 +2157,310 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir) * markPos state. But depending on the current array state like this * would add complexity. Instead, we just unset markPos's copy of * moreRight or moreLeft (whichever might be affected), while making - * btrestpos reset the scan's arrays to their initial scan positions. - * In effect, btrestpos leaves advancing the arrays up to the first + * btrestrpos reset the scan's arrays to their initial scan positions. + * In effect, btrestrpos leaves advancing the arrays up to the first * _bt_readpage call (that takes place after it has restored markPos). */ - Assert(so->markPos.dir == dir); if (so->needPrimScan) { - if (ScanDirectionIsForward(dir)) + if (ScanDirectionIsForward(so->currPos.dir)) so->markPos.moreRight = true; else so->markPos.moreLeft = true; } + + /* mark/restore not supported by parallel scans */ + Assert(!scan->parallel_scan); } + BTScanPosUnpinIfPinned(so->currPos); + + /* Walk to the next page with data */ if (ScanDirectionIsForward(dir)) + blkno = so->currPos.nextPage; + else + blkno = so->currPos.prevPage; + lastcurrblkno = so->currPos.currPage; + + /* + * Cancel primitive index scans that were scheduled when the call to + * _bt_readpage for currPos happened to use the opposite direction to the + * one that we're stepping in now. (It's okay to leave the scan's array + * keys as-is, since the next _bt_readpage will advance them.) + */ + if (so->currPos.dir != dir) + so->needPrimScan = false; + + return _bt_readnextpage(scan, blkno, lastcurrblkno, dir, false); +} + +/* + * _bt_readfirstpage() -- Read first page containing valid data for _bt_first + * + * _bt_first caller passes us an offnum returned by _bt_binsrch, which might + * be an out of bounds offnum such as "maxoff + 1" in certain corner cases. + * _bt_checkkeys will stop the scan as soon as an equality qual fails (when + * its scan key was marked required), so _bt_first _must_ pass us an offnum + * exactly at the beginning of where equal tuples are to be found. When we're + * passed an offnum past the end of the page, we might still manage to stop + * the scan on this page by calling _bt_checkkeys against the high key. See + * _bt_readpage for full details. + * + * On entry, so->currPos must be pinned and locked (so offnum stays valid). + * Parallel scan callers must have seized the scan before calling here. + * + * On exit, we'll have updated so->currPos and retained locks and pins + * according to the same rules as those laid out for _bt_readnextpage exit. + * Like _bt_readnextpage, our return value indicates if there are any matching + * records in the given direction. + * + * We always release the scan for a parallel scan caller, regardless of + * success or failure; we'll call _bt_parallel_release as soon as possible. + */ +static bool +_bt_readfirstpage(IndexScanDesc scan, OffsetNumber offnum, ScanDirection dir) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + + so->numKilled = 0; /* just paranoia */ + so->markItemIndex = -1; /* ditto */ + + /* Initialize so->currPos for the first page (page in so->currPos.buf) */ + if (so->needPrimScan) { - /* Walk right to the next page with data */ - if (scan->parallel_scan != NULL) - { - /* - * Seize the scan to get the next block number; if the scan has - * ended already, bail out. - */ - status = _bt_parallel_seize(scan, &blkno, false); - if (!status) - { - /* release the previous buffer, if pinned */ - BTScanPosUnpinIfPinned(so->currPos); - BTScanPosInvalidate(so->currPos); - return false; - } - } - else - { - /* Not parallel, so use the previously-saved nextPage link. */ - blkno = so->currPos.nextPage; - } + Assert(so->numArrayKeys); - /* Remember we left a page with data */ so->currPos.moreLeft = true; - - /* release the previous buffer, if pinned */ - BTScanPosUnpinIfPinned(so->currPos); + so->currPos.moreRight = true; + so->needPrimScan = false; } - else + else if (ScanDirectionIsForward(dir)) { - /* Remember we left a page with data */ + so->currPos.moreLeft = false; so->currPos.moreRight = true; + } + else + { + so->currPos.moreLeft = true; + so->currPos.moreRight = false; + } - if (scan->parallel_scan != NULL) - { - /* - * Seize the scan to get the current block number; if the scan has - * ended already, bail out. - */ - status = _bt_parallel_seize(scan, &blkno, false); - BTScanPosUnpinIfPinned(so->currPos); - if (!status) - { - BTScanPosInvalidate(so->currPos); - return false; - } - } - else - { - /* Not parallel, so just use our own notion of the current page */ - blkno = so->currPos.currPage; - } + /* + * Attempt to load matching tuples from the first page. + * + * Note that _bt_readpage will finish initializing the so->currPos fields. + * _bt_readpage also releases parallel scan (even when it returns false). + */ + if (_bt_readpage(scan, dir, offnum, true)) + { + Relation rel = scan->indexRelation; + + /* + * _bt_readpage succeeded. Drop the lock (and maybe the pin) on + * so->currPos.buf in preparation for btgettuple returning tuples. + */ + Assert(BTScanPosIsPinned(so->currPos)); + _bt_drop_lock_and_maybe_pin(rel, so); + return true; } - if (!_bt_readnextpage(scan, blkno, dir)) - return false; + /* There's no actually-matching data on the page in so->currPos.buf */ + _bt_unlockbuf(scan->indexRelation, so->currPos.buf); - /* We have at least one item to return as scan's next item */ - _bt_drop_lock_and_maybe_pin(scan, &so->currPos); + /* Call _bt_readnextpage using its _bt_steppage wrapper function */ + if (!_bt_steppage(scan, dir)) + return false; + /* _bt_readpage for a later page (now in so->currPos) succeeded */ return true; } /* - * _bt_readnextpage() -- Read next page containing valid data for scan + * _bt_readnextpage() -- Read next page containing valid data for _bt_next + * + * Caller's blkno is the next interesting page's link, taken from either the + * previously-saved right link or left link. lastcurrblkno is the page that + * was current at the point where the blkno link was saved, which we use to + * reason about concurrent page splits/page deletions during backwards scans. + * In the common case where seized=false, blkno is either so->currPos.nextPage + * or so->currPos.prevPage, and lastcurrblkno is so->currPos.currPage. + * + * On entry, so->currPos shouldn't be locked by caller. so->currPos.buf must + * be InvalidBuffer/unpinned as needed by caller (note that lastcurrblkno + * won't need to be read again in almost all cases). Parallel scan callers + * that seized the scan before calling here should pass seized=true; such a + * caller's blkno and lastcurrblkno arguments come from the seized scan. + * seized=false callers just pass us the blkno/lastcurrblkno taken from their + * so->currPos, which (along with so->currPos itself) can be used to end the + * scan. A seized=false caller's blkno can never be assumed to be the page + * that must be read next during a parallel scan, though. We must figure that + * part out for ourselves by seizing the scan (the correct page to read might + * already be beyond the seized=false caller's blkno during a parallel scan, + * unless blkno/so->currPos.nextPage/so->currPos.prevPage is already P_NONE, + * or unless so->currPos.moreRight/so->currPos.moreLeft is already unset). * * On success exit, so->currPos is updated to contain data from the next - * interesting page, and we return true. Caller must release the lock (and - * maybe the pin) on the buffer on success exit. + * interesting page, and we return true. We hold a pin on the buffer on + * success exit (except during so->dropPin index scans, when we drop the pin + * eagerly to avoid blocking VACUUM). + * + * If there are no more matching records in the given direction, we invalidate + * so->currPos (while ensuring it retains no locks or pins), and return false. * - * If there are no more matching records in the given direction, we drop all - * locks and pins, set so->currPos.buf to InvalidBuffer, and return false. + * We always release the scan for a parallel scan caller, regardless of + * success or failure; we'll call _bt_parallel_release as soon as possible. */ static bool -_bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir) +_bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, + BlockNumber lastcurrblkno, ScanDirection dir, bool seized) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; - Relation rel; - Page page; - BTPageOpaque opaque; - bool status; - rel = scan->indexRelation; + Assert(so->currPos.currPage == lastcurrblkno || seized); + Assert(!(blkno == P_NONE && seized)); + Assert(!BTScanPosIsPinned(so->currPos)); + /* + * Remember that the scan already read lastcurrblkno, a page to the left + * of blkno (or remember reading a page to the right, for backwards scans) + */ if (ScanDirectionIsForward(dir)) - { - for (;;) - { - /* - * if we're at end of scan, give up and mark parallel scan as - * done, so that all the workers can finish their scan - */ - if (blkno == P_NONE || !so->currPos.moreRight) - { - _bt_parallel_done(scan); - BTScanPosInvalidate(so->currPos); - return false; - } - /* check for interrupts while we're not holding any buffer lock */ - CHECK_FOR_INTERRUPTS(); - /* step right one page */ - so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ); - page = BufferGetPage(so->currPos.buf); - opaque = BTPageGetOpaque(page); - /* check for deleted page */ - if (!P_IGNORE(opaque)) - { - PredicateLockPage(rel, blkno, scan->xs_snapshot); - /* see if there are any matches on this page */ - /* note that this will clear moreRight if we can stop */ - if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque), false)) - break; - } - else if (scan->parallel_scan != NULL) - { - /* allow next page be processed by parallel worker */ - _bt_parallel_release(scan, opaque->btpo_next); - } - - /* nope, keep going */ - if (scan->parallel_scan != NULL) - { - _bt_relbuf(rel, so->currPos.buf); - status = _bt_parallel_seize(scan, &blkno, false); - if (!status) - { - BTScanPosInvalidate(so->currPos); - return false; - } - } - else - { - blkno = opaque->btpo_next; - _bt_relbuf(rel, so->currPos.buf); - } - } - } + so->currPos.moreLeft = true; else + so->currPos.moreRight = true; + + for (;;) { - /* - * Should only happen in parallel cases, when some other backend - * advanced the scan. - */ - if (so->currPos.currPage != blkno) + Page page; + BTPageOpaque opaque; + + if (blkno == P_NONE || + (ScanDirectionIsForward(dir) ? + !so->currPos.moreRight : !so->currPos.moreLeft)) { - BTScanPosUnpinIfPinned(so->currPos); - so->currPos.currPage = blkno; + /* most recent _bt_readpage call (for lastcurrblkno) ended scan */ + Assert(so->currPos.currPage == lastcurrblkno && !seized); + BTScanPosInvalidate(so->currPos); + _bt_parallel_done(scan); /* iff !so->needPrimScan */ + return false; } - /* - * Walk left to the next page with data. This is much more complex - * than the walk-right case because of the possibility that the page - * to our left splits while we are in flight to it, plus the - * possibility that the page we were on gets deleted after we leave - * it. See nbtree/README for details. - * - * It might be possible to rearrange this code to have less overhead - * in pinning and locking, but that would require capturing the left - * sibling block number when the page is initially read, and then - * optimistically starting there (rather than pinning the page twice). - * It is not clear that this would be worth the complexity. - */ - if (BTScanPosIsPinned(so->currPos)) - _bt_lockbuf(rel, so->currPos.buf, BT_READ); - else - so->currPos.buf = _bt_getbuf(rel, so->currPos.currPage, BT_READ); + Assert(!so->needPrimScan); - for (;;) + /* parallel scan must never actually visit so->currPos blkno */ + if (!seized && scan->parallel_scan != NULL && + !_bt_parallel_seize(scan, &blkno, &lastcurrblkno, false)) { - /* Done if we know there are no matching keys to the left */ - if (!so->currPos.moreLeft) - { - _bt_relbuf(rel, so->currPos.buf); - _bt_parallel_done(scan); - BTScanPosInvalidate(so->currPos); - return false; - } - - /* Step to next physical page */ - so->currPos.buf = _bt_walk_left(rel, so->currPos.buf); + /* whole scan is now done (or another primitive scan required) */ + BTScanPosInvalidate(so->currPos); + return false; + } - /* if we're physically at end of index, return failure */ + if (ScanDirectionIsForward(dir)) + { + /* read blkno, but check for interrupts first */ + CHECK_FOR_INTERRUPTS(); + so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ); + } + else + { + /* read blkno, avoiding race (also checks for interrupts) */ + so->currPos.buf = _bt_lock_and_validate_left(rel, &blkno, + lastcurrblkno); if (so->currPos.buf == InvalidBuffer) { - _bt_parallel_done(scan); + /* must have been a concurrent deletion of leftmost page */ BTScanPosInvalidate(so->currPos); + _bt_parallel_done(scan); return false; } + } - /* - * Okay, we managed to move left to a non-deleted page. Done if - * it's not half-dead and contains matching tuples. Else loop back - * and do it all again. - */ - page = BufferGetPage(so->currPos.buf); - opaque = BTPageGetOpaque(page); - if (!P_IGNORE(opaque)) + page = BufferGetPage(so->currPos.buf); + opaque = BTPageGetOpaque(page); + lastcurrblkno = blkno; + if (likely(!P_IGNORE(opaque))) + { + /* see if there are any matches on this page */ + if (ScanDirectionIsForward(dir)) { - PredicateLockPage(rel, BufferGetBlockNumber(so->currPos.buf), scan->xs_snapshot); - /* see if there are any matches on this page */ - /* note that this will clear moreLeft if we can stop */ - if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page), false)) + /* note that this will clear moreRight if we can stop */ + if (_bt_readpage(scan, dir, P_FIRSTDATAKEY(opaque), seized)) break; + blkno = so->currPos.nextPage; } - else if (scan->parallel_scan != NULL) + else { - /* allow next page be processed by parallel worker */ - _bt_parallel_release(scan, BufferGetBlockNumber(so->currPos.buf)); + /* note that this will clear moreLeft if we can stop */ + if (_bt_readpage(scan, dir, PageGetMaxOffsetNumber(page), seized)) + break; + blkno = so->currPos.prevPage; } - - /* - * For parallel scans, get the last page scanned as it is quite - * possible that by the time we try to seize the scan, some other - * worker has already advanced the scan to a different page. We - * must continue based on the latest page scanned by any worker. - */ + } + else + { + /* _bt_readpage not called, so do all this for ourselves */ + if (ScanDirectionIsForward(dir)) + blkno = opaque->btpo_next; + else + blkno = opaque->btpo_prev; if (scan->parallel_scan != NULL) - { - _bt_relbuf(rel, so->currPos.buf); - status = _bt_parallel_seize(scan, &blkno, false); - if (!status) - { - BTScanPosInvalidate(so->currPos); - return false; - } - so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ); - } + _bt_parallel_release(scan, blkno, lastcurrblkno); } - } - - return true; -} -/* - * _bt_parallel_readpage() -- Read current page containing valid data for scan - * - * On success, release lock and maybe pin on buffer. We return true to - * indicate success. - */ -static bool -_bt_parallel_readpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir) -{ - BTScanOpaque so = (BTScanOpaque) scan->opaque; - - Assert(!so->needPrimScan); - - _bt_initialize_more_data(so, dir); - - if (!_bt_readnextpage(scan, blkno, dir)) - return false; + /* no matching tuples on this page */ + _bt_relbuf(rel, so->currPos.buf); + seized = false; /* released by _bt_readpage (or by us) */ + } - /* We have at least one item to return as scan's next item */ - _bt_drop_lock_and_maybe_pin(scan, &so->currPos); + /* + * _bt_readpage succeeded. Drop the lock (and maybe the pin) on + * so->currPos.buf in preparation for btgettuple returning tuples. + */ + Assert(so->currPos.currPage == blkno); + Assert(BTScanPosIsPinned(so->currPos)); + _bt_drop_lock_and_maybe_pin(rel, so); return true; } /* - * _bt_walk_left() -- step left one page, if possible + * _bt_lock_and_validate_left() -- lock caller's left sibling blkno, + * recovering from concurrent page splits/page deletions when necessary + * + * Called during backwards scans, to deal with their unique concurrency rules. * - * The given buffer must be pinned and read-locked. This will be dropped - * before stepping left. On return, we have pin and read lock on the - * returned page, instead. + * blkno points to the block number of the page that we expect to move the + * scan to. We'll successfully move the scan there when we find that its + * right sibling link still points to lastcurrblkno (the page we just read). + * Otherwise, we have to figure out which page is the correct one for the scan + * to now read the hard way, reasoning about concurrent splits and deletions. + * See nbtree/README. * - * Returns InvalidBuffer if there is no page to the left (no lock is held - * in that case). + * On return, we have both a pin and a read lock on the returned page, whose + * block number will be set in *blkno. Returns InvalidBuffer if there is no + * page to the left (no lock or pin is held in that case). * * It is possible for the returned leaf page to be half-dead; caller must * check that condition and step left again when required. */ static Buffer -_bt_walk_left(Relation rel, Buffer buf) +_bt_lock_and_validate_left(Relation rel, BlockNumber *blkno, + BlockNumber lastcurrblkno) { - Page page; - BTPageOpaque opaque; - - page = BufferGetPage(buf); - opaque = BTPageGetOpaque(page); + BlockNumber origblkno = *blkno; /* detects circular links */ for (;;) { - BlockNumber obknum; - BlockNumber lblkno; - BlockNumber blkno; + Buffer buf; + Page page; + BTPageOpaque opaque; int tries; - /* if we're at end of tree, release buf and return failure */ - if (P_LEFTMOST(opaque)) - { - _bt_relbuf(rel, buf); - break; - } - /* remember original page we are stepping left from */ - obknum = BufferGetBlockNumber(buf); - /* step left */ - blkno = lblkno = opaque->btpo_prev; - _bt_relbuf(rel, buf); /* check for interrupts while we're not holding any buffer lock */ CHECK_FOR_INTERRUPTS(); - buf = _bt_getbuf(rel, blkno, BT_READ); + buf = _bt_getbuf(rel, *blkno, BT_READ); page = BufferGetPage(buf); opaque = BTPageGetOpaque(page); @@ -2398,7 +2468,7 @@ _bt_walk_left(Relation rel, Buffer buf) * If this isn't the page we want, walk right till we find what we * want --- but go no more than four hops (an arbitrary limit). If we * don't find the correct page by then, the most likely bet is that - * the original page got deleted and isn't in the sibling chain at all + * lastcurrblkno got deleted and isn't in the sibling chain at all * anymore, not that its left sibling got split more than four times. * * Note that it is correct to test P_ISDELETED not P_IGNORE here, @@ -2407,21 +2477,27 @@ _bt_walk_left(Relation rel, Buffer buf) tries = 0; for (;;) { - if (!P_ISDELETED(opaque) && opaque->btpo_next == obknum) + if (likely(!P_ISDELETED(opaque) && + opaque->btpo_next == lastcurrblkno)) { /* Found desired page, return it */ return buf; } if (P_RIGHTMOST(opaque) || ++tries > 4) break; - blkno = opaque->btpo_next; - buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ); + /* step right */ + *blkno = opaque->btpo_next; + buf = _bt_relandgetbuf(rel, buf, *blkno, BT_READ); page = BufferGetPage(buf); opaque = BTPageGetOpaque(page); } - /* Return to the original page to see what's up */ - buf = _bt_relandgetbuf(rel, buf, obknum, BT_READ); + /* + * Return to the original page (usually the page most recently read by + * _bt_readpage, which is passed by caller as lastcurrblkno) to see + * what's up with its prev sibling link + */ + buf = _bt_relandgetbuf(rel, buf, lastcurrblkno, BT_READ); page = BufferGetPage(buf); opaque = BTPageGetOpaque(page); if (P_ISDELETED(opaque)) @@ -2437,31 +2513,42 @@ _bt_walk_left(Relation rel, Buffer buf) if (P_RIGHTMOST(opaque)) elog(ERROR, "fell off the end of index \"%s\"", RelationGetRelationName(rel)); - blkno = opaque->btpo_next; - buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ); + lastcurrblkno = opaque->btpo_next; + buf = _bt_relandgetbuf(rel, buf, lastcurrblkno, BT_READ); page = BufferGetPage(buf); opaque = BTPageGetOpaque(page); if (!P_ISDELETED(opaque)) break; } - - /* - * Now return to top of loop, resetting obknum to point to this - * nondeleted page, and try again. - */ } else { /* - * It wasn't deleted; the explanation had better be that the page - * to the left got split or deleted. Without this check, we'd go - * into an infinite loop if there's anything wrong. + * Original lastcurrblkno wasn't deleted; the explanation had + * better be that the page to the left got split or deleted. + * Without this check, we risk going into an infinite loop. */ - if (opaque->btpo_prev == lblkno) + if (opaque->btpo_prev == origblkno) elog(ERROR, "could not find left sibling of block %u in index \"%s\"", - obknum, RelationGetRelationName(rel)); - /* Okay to try again with new lblkno value */ + lastcurrblkno, RelationGetRelationName(rel)); + /* Okay to try again, since left sibling link changed */ + } + + /* + * Original lastcurrblkno from caller was concurrently deleted (could + * also have been a great many concurrent left sibling page splits). + * Found a non-deleted page that should now act as our lastcurrblkno. + */ + if (P_LEFTMOST(opaque)) + { + /* New lastcurrblkno has no left sibling (concurrently deleted) */ + _bt_relbuf(rel, buf); + break; } + + /* Start from scratch with new lastcurrblkno's blkno/prev link */ + *blkno = origblkno = opaque->btpo_prev; + _bt_relbuf(rel, buf); } return InvalidBuffer; @@ -2553,40 +2640,41 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost) * * This is used by _bt_first() to set up a scan when we've determined * that the scan must start at the beginning or end of the index (for - * a forward or backward scan respectively). Exit conditions are the - * same as for _bt_first(). + * a forward or backward scan respectively). + * + * Parallel scan callers must have seized the scan before calling here. + * Exit conditions are the same as for _bt_first(). */ static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir) { Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; - Buffer buf; Page page; BTPageOpaque opaque; OffsetNumber start; - BTScanPosItem *currItem; + + Assert(!BTScanPosIsValid(so->currPos)); + Assert(!so->needPrimScan); /* * Scan down to the leftmost or rightmost leaf page. This is a simplified - * version of _bt_search(). We don't maintain a stack since we know we - * won't need it. + * version of _bt_search(). */ - buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir)); + so->currPos.buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir)); - if (!BufferIsValid(buf)) + if (!BufferIsValid(so->currPos.buf)) { /* * Empty index. Lock the whole relation, as nothing finer to lock * exists. */ PredicateLockRelation(rel, scan->xs_snapshot); - BTScanPosInvalidate(so->currPos); + _bt_parallel_done(scan); return false; } - PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot); - page = BufferGetPage(buf); + page = BufferGetPage(so->currPos.buf); opaque = BTPageGetOpaque(page); Assert(P_ISLEAF(opaque)); @@ -2609,65 +2697,12 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) start = 0; /* keep compiler quiet */ } - /* remember which buffer we have pinned */ - so->currPos.buf = buf; - - _bt_initialize_more_data(so, dir); - /* * Now load data from the first page of the scan. */ - if (!_bt_readpage(scan, dir, start, true)) - { - /* - * There's no actually-matching data on this page. Try to advance to - * the next page. Return false if there's no matching data at all. - */ - _bt_unlockbuf(scan->indexRelation, so->currPos.buf); - if (!_bt_steppage(scan, dir)) - return false; - } - else - { - /* We have at least one item to return as scan's first item */ - _bt_drop_lock_and_maybe_pin(scan, &so->currPos); - } - - /* OK, itemIndex says what to return */ - currItem = &so->currPos.items[so->currPos.itemIndex]; - scan->xs_heaptid = currItem->heapTid; - if (scan->xs_want_itup) - scan->xs_itup = (IndexTuple) (so->currTuples + currItem->tupleOffset); + if (!_bt_readfirstpage(scan, start, dir)) + return false; + _bt_returnitem(scan, so); return true; } - -/* - * _bt_initialize_more_data() -- initialize moreLeft, moreRight and scan dir - * from currPos - */ -static inline void -_bt_initialize_more_data(BTScanOpaque so, ScanDirection dir) -{ - so->currPos.dir = dir; - if (so->needPrimScan) - { - Assert(so->numArrayKeys); - - so->currPos.moreLeft = true; - so->currPos.moreRight = true; - so->needPrimScan = false; - } - else if (ScanDirectionIsForward(dir)) - { - so->currPos.moreLeft = false; - so->currPos.moreRight = true; - } - else - { - so->currPos.moreLeft = true; - so->currPos.moreRight = false; - } - so->numKilled = 0; /* just paranoia */ - so->markItemIndex = -1; /* ditto */ -} diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index f5d7b3b0c3014..9d70e89c1f3ce 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -29,7 +29,7 @@ * This code isn't concerned about the FSM at all. The caller is responsible * for initializing that. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -45,14 +45,13 @@ #include "access/relscan.h" #include "access/table.h" #include "access/xact.h" -#include "access/xloginsert.h" #include "catalog/index.h" #include "commands/progress.h" #include "executor/instrument.h" #include "miscadmin.h" #include "pgstat.h" #include "storage/bulk_write.h" -#include "tcop/tcopprot.h" /* pgrminclude ignore */ +#include "tcop/tcopprot.h" #include "utils/rel.h" #include "utils/sortsupport.h" #include "utils/tuplesort.h" @@ -105,6 +104,9 @@ typedef struct BTShared bool isconcurrent; int scantuplesortstates; + /* Query ID, for report in worker processes */ + int64 queryid; + /* * workersdonecv is used to monitor the progress of workers. All parallel * participants must indicate that they are done before leader can use @@ -473,7 +475,7 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate, /* Fill spool using either serial or parallel heap scan */ if (!buildstate->btleader) reltuples = table_index_build_scan(heap, index, indexInfo, true, true, - _bt_build_callback, (void *) buildstate, + _bt_build_callback, buildstate, NULL); else reltuples = _bt_parallel_heapscan(buildstate, @@ -827,7 +829,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup, * make use of the reserved space. This should never fail on internal * pages. */ - if (unlikely(itupsz > BTMaxItemSize(npage))) + if (unlikely(itupsz > BTMaxItemSize)) _bt_check_third_page(wstate->index, wstate->heap, isleaf, npage, itup); @@ -1169,7 +1171,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) { SortSupport sortKey = sortKeys + i; ScanKey scanKey = wstate->inskey->scankeys + i; - int16 strategy; + bool reverse; sortKey->ssup_cxt = CurrentMemoryContext; sortKey->ssup_collation = scanKey->sk_collation; @@ -1181,10 +1183,9 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) Assert(sortKey->ssup_attno != 0); - strategy = (scanKey->sk_flags & SK_BT_DESC) != 0 ? - BTGreaterStrategyNumber : BTLessStrategyNumber; + reverse = (scanKey->sk_flags & SK_BT_DESC) != 0; - PrepareSortSupportFromIndexRel(wstate->index, strategy, sortKey); + PrepareSortSupportFromIndexRel(wstate->index, reverse, sortKey); } for (;;) @@ -1303,7 +1304,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2) */ dstate->maxpostingsize = MAXALIGN_DOWN((BLCKSZ * 10 / 100)) - sizeof(ItemIdData); - Assert(dstate->maxpostingsize <= BTMaxItemSize((Page) state->btps_buf) && + Assert(dstate->maxpostingsize <= BTMaxItemSize && dstate->maxpostingsize <= INDEX_SIZE_MASK); dstate->htids = palloc(dstate->maxpostingsize); @@ -1505,6 +1506,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request) btshared->nulls_not_distinct = btspool->nulls_not_distinct; btshared->isconcurrent = isconcurrent; btshared->scantuplesortstates = scantuplesortstates; + btshared->queryid = pgstat_get_my_query_id(); ConditionVariableInit(&btshared->workersdonecv); SpinLockInit(&btshared->mutex); /* Initialize mutable state */ @@ -1787,6 +1789,9 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc) indexLockmode = RowExclusiveLock; } + /* Track query ID */ + pgstat_report_query_id(btshared->queryid, false); + /* Open relations within worker */ heapRel = table_open(btshared->heaprelid, heapLockmode); indexRel = index_open(btshared->indexrelid, indexLockmode); @@ -1924,7 +1929,7 @@ _bt_parallel_scan_and_sort(BTSpool *btspool, BTSpool *btspool2, ParallelTableScanFromBTShared(btshared)); reltuples = table_index_build_scan(btspool->heap, btspool->index, indexInfo, true, progress, _bt_build_callback, - (void *) &buildstate, scan); + &buildstate, scan); /* Execute this worker's part of the sort */ if (progress) diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c index 1f40d40263e93..e6c9aaa0454dd 100644 --- a/src/backend/access/nbtree/nbtsplitloc.c +++ b/src/backend/access/nbtree/nbtsplitloc.c @@ -3,7 +3,7 @@ * nbtsplitloc.c * Choose split point code for Postgres btree implementation. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index d6de2072d4057..c71d1b6f2e1e0 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -3,7 +3,7 @@ * nbtutils.c * Utility code for Postgres btree implementation. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,61 +19,31 @@ #include "access/nbtree.h" #include "access/reloptions.h" -#include "access/relscan.h" #include "commands/progress.h" -#include "lib/qunique.h" #include "miscadmin.h" -#include "utils/array.h" #include "utils/datum.h" #include "utils/lsyscache.h" -#include "utils/memutils.h" -#include "utils/rel.h" #define LOOK_AHEAD_REQUIRED_RECHECKS 3 #define LOOK_AHEAD_DEFAULT_DISTANCE 5 +#define NSKIPADVANCES_THRESHOLD 3 -typedef struct BTSortArrayContext -{ - FmgrInfo *sortproc; - Oid collation; - bool reverse; -} BTSortArrayContext; - -typedef struct BTScanKeyPreproc -{ - ScanKey skey; - int ikey; - int arrayidx; -} BTScanKeyPreproc; - -static void _bt_setup_array_cmp(IndexScanDesc scan, ScanKey skey, Oid elemtype, - FmgrInfo *orderproc, FmgrInfo **sortprocp); -static Datum _bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, - Oid elemtype, StrategyNumber strat, - Datum *elems, int nelems); -static int _bt_sort_array_elements(ScanKey skey, FmgrInfo *sortproc, - bool reverse, Datum *elems, int nelems); -static bool _bt_merge_arrays(IndexScanDesc scan, ScanKey skey, - FmgrInfo *sortproc, bool reverse, - Oid origelemtype, Oid nextelemtype, - Datum *elems_orig, int *nelems_orig, - Datum *elems_next, int nelems_next); -static bool _bt_compare_array_scankey_args(IndexScanDesc scan, - ScanKey arraysk, ScanKey skey, - FmgrInfo *orderproc, BTArrayKeyInfo *array, - bool *qual_ok); -static ScanKey _bt_preprocess_array_keys(IndexScanDesc scan); -static void _bt_preprocess_array_keys_final(IndexScanDesc scan, int *keyDataMap); -static int _bt_compare_array_elements(const void *a, const void *b, void *arg); static inline int32 _bt_compare_array_skey(FmgrInfo *orderproc, Datum tupdatum, bool tupnull, Datum arrdatum, ScanKey cur); -static int _bt_binsrch_array_skey(FmgrInfo *orderproc, - bool cur_elem_trig, ScanDirection dir, - Datum tupdatum, bool tupnull, - BTArrayKeyInfo *array, ScanKey cur, - int32 *set_elem_result); -static bool _bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir); +static void _bt_binsrch_skiparray_skey(bool cur_elem_trig, ScanDirection dir, + Datum tupdatum, bool tupnull, + BTArrayKeyInfo *array, ScanKey cur, + int32 *set_elem_result); +static void _bt_skiparray_set_element(Relation rel, ScanKey skey, BTArrayKeyInfo *array, + int32 set_elem_result, Datum tupdatum, bool tupnull); +static void _bt_skiparray_set_isnull(Relation rel, ScanKey skey, BTArrayKeyInfo *array); +static void _bt_array_set_low_or_high(Relation rel, ScanKey skey, + BTArrayKeyInfo *array, bool low_not_high); +static bool _bt_array_decrement(Relation rel, ScanKey skey, BTArrayKeyInfo *array); +static bool _bt_array_increment(Relation rel, ScanKey skey, BTArrayKeyInfo *array); +static bool _bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir, + bool *skip_array_set); static void _bt_rewind_nonrequired_arrays(IndexScanDesc scan, ScanDirection dir); static bool _bt_tuple_before_array_skeys(IndexScanDesc scan, ScanDirection dir, IndexTuple tuple, TupleDesc tupdesc, int tupnatts, @@ -85,19 +55,15 @@ static bool _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, static bool _bt_verify_arrays_bt_first(IndexScanDesc scan, ScanDirection dir); static bool _bt_verify_keys_with_arraykeys(IndexScanDesc scan); #endif -static bool _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op, - ScanKey leftarg, ScanKey rightarg, - BTArrayKeyInfo *array, FmgrInfo *orderproc, - bool *result); -static bool _bt_fix_scankey_strategy(ScanKey skey, int16 *indoption); -static void _bt_mark_scankey_required(ScanKey skey); +static bool _bt_oppodir_checkkeys(IndexScanDesc scan, ScanDirection dir, + IndexTuple finaltup); static bool _bt_check_compare(IndexScanDesc scan, ScanDirection dir, IndexTuple tuple, int tupnatts, TupleDesc tupdesc, - bool advancenonrequired, bool prechecked, bool firstmatch, + bool advancenonrequired, bool forcenonrequired, bool *continuescan, int *ikey); static bool _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, int tupnatts, TupleDesc tupdesc, - ScanDirection dir, bool *continuescan); + ScanDirection dir, bool forcenonrequired, bool *continuescan); static void _bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate, int tupnatts, TupleDesc tupdesc); static int _bt_keep_natts(Relation rel, IndexTuple lastleft, @@ -230,1156 +196,786 @@ _bt_freestack(BTStack stack) } } - /* - * _bt_preprocess_array_keys() -- Preprocess SK_SEARCHARRAY scan keys - * - * If there are any SK_SEARCHARRAY scan keys, deconstruct the array(s) and - * set up BTArrayKeyInfo info for each one that is an equality-type key. - * Returns modified scan keys as input for further, standard preprocessing. - * - * Currently we perform two kinds of preprocessing to deal with redundancies. - * For inequality array keys, it's sufficient to find the extreme element - * value and replace the whole array with that scalar value. This eliminates - * all but one array element as redundant. Similarly, we are capable of - * "merging together" multiple equality array keys (from two or more input - * scan keys) into a single output scan key containing only the intersecting - * array elements. This can eliminate many redundant array elements, as well - * as eliminating whole array scan keys as redundant. It can also allow us to - * detect contradictory quals. + * _bt_compare_array_skey() -- apply array comparison function * - * It is convenient for _bt_preprocess_keys caller to have to deal with no - * more than one equality strategy array scan key per index attribute. We'll - * always be able to set things up that way when complete opfamilies are used. - * Eliminated array scan keys can be recognized as those that have had their - * sk_strategy field set to InvalidStrategy here by us. Caller should avoid - * including these in the scan's so->keyData[] output array. + * Compares caller's tuple attribute value to a scan key/array element. + * Helper function used during binary searches of SK_SEARCHARRAY arrays. * - * We set the scan key references from the scan's BTArrayKeyInfo info array to - * offsets into the temp modified input array returned to caller. Scans that - * have array keys should call _bt_preprocess_array_keys_final when standard - * preprocessing steps are complete. This will convert the scan key offset - * references into references to the scan's so->keyData[] output scan keys. + * This routine returns: + * <0 if tupdatum < arrdatum; + * 0 if tupdatum == arrdatum; + * >0 if tupdatum > arrdatum. * - * Note: the reason we need to return a temp scan key array, rather than just - * scribbling on scan->keyData, is that callers are permitted to call btrescan - * without supplying a new set of scankey data. - */ -static ScanKey -_bt_preprocess_array_keys(IndexScanDesc scan) + * This is essentially the same interface as _bt_compare: both functions + * compare the value that they're searching for to a binary search pivot. + * However, unlike _bt_compare, this function's "tuple argument" comes first, + * while its "array/scankey argument" comes second. +*/ +static inline int32 +_bt_compare_array_skey(FmgrInfo *orderproc, + Datum tupdatum, bool tupnull, + Datum arrdatum, ScanKey cur) { - BTScanOpaque so = (BTScanOpaque) scan->opaque; - Relation rel = scan->indexRelation; - int numberOfKeys = scan->numberOfKeys; - int16 *indoption = rel->rd_indoption; - int numArrayKeys; - int origarrayatt = InvalidAttrNumber, - origarraykey = -1; - Oid origelemtype = InvalidOid; - ScanKey cur; - MemoryContext oldContext; - ScanKey arrayKeyData; /* modified copy of scan->keyData */ - - Assert(numberOfKeys); - - /* Quick check to see if there are any array keys */ - numArrayKeys = 0; - for (int i = 0; i < numberOfKeys; i++) - { - cur = &scan->keyData[i]; - if (cur->sk_flags & SK_SEARCHARRAY) - { - numArrayKeys++; - Assert(!(cur->sk_flags & (SK_ROW_HEADER | SK_SEARCHNULL | SK_SEARCHNOTNULL))); - /* If any arrays are null as a whole, we can quit right now. */ - if (cur->sk_flags & SK_ISNULL) - { - so->qual_ok = false; - return NULL; - } - } - } + int32 result = 0; - /* Quit if nothing to do. */ - if (numArrayKeys == 0) - return NULL; + Assert(cur->sk_strategy == BTEqualStrategyNumber); + Assert(!(cur->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL))); - /* - * Make a scan-lifespan context to hold array-associated data, or reset it - * if we already have one from a previous rescan cycle. - */ - if (so->arrayContext == NULL) - so->arrayContext = AllocSetContextCreate(CurrentMemoryContext, - "BTree array context", - ALLOCSET_SMALL_SIZES); + if (tupnull) /* NULL tupdatum */ + { + if (cur->sk_flags & SK_ISNULL) + result = 0; /* NULL "=" NULL */ + else if (cur->sk_flags & SK_BT_NULLS_FIRST) + result = -1; /* NULL "<" NOT_NULL */ + else + result = 1; /* NULL ">" NOT_NULL */ + } + else if (cur->sk_flags & SK_ISNULL) /* NOT_NULL tupdatum, NULL arrdatum */ + { + if (cur->sk_flags & SK_BT_NULLS_FIRST) + result = 1; /* NOT_NULL ">" NULL */ + else + result = -1; /* NOT_NULL "<" NULL */ + } else - MemoryContextReset(so->arrayContext); - - oldContext = MemoryContextSwitchTo(so->arrayContext); - - /* Create modifiable copy of scan->keyData in the workspace context */ - arrayKeyData = (ScanKey) palloc(numberOfKeys * sizeof(ScanKeyData)); - memcpy(arrayKeyData, scan->keyData, numberOfKeys * sizeof(ScanKeyData)); - - /* Allocate space for per-array data in the workspace context */ - so->arrayKeys = (BTArrayKeyInfo *) palloc(numArrayKeys * sizeof(BTArrayKeyInfo)); - - /* Allocate space for ORDER procs used to help _bt_checkkeys */ - so->orderProcs = (FmgrInfo *) palloc(numberOfKeys * sizeof(FmgrInfo)); - - /* Now process each array key */ - numArrayKeys = 0; - for (int i = 0; i < numberOfKeys; i++) { - FmgrInfo sortproc; - FmgrInfo *sortprocp = &sortproc; - Oid elemtype; - bool reverse; - ArrayType *arrayval; - int16 elmlen; - bool elmbyval; - char elmalign; - int num_elems; - Datum *elem_values; - bool *elem_nulls; - int num_nonnulls; - int j; - - cur = &arrayKeyData[i]; - if (!(cur->sk_flags & SK_SEARCHARRAY)) - continue; - /* - * First, deconstruct the array into elements. Anything allocated - * here (including a possibly detoasted array value) is in the - * workspace context. + * Like _bt_compare, we need to be careful of cross-type comparisons, + * so the left value has to be the value that came from an index tuple */ - arrayval = DatumGetArrayTypeP(cur->sk_argument); - /* We could cache this data, but not clear it's worth it */ - get_typlenbyvalalign(ARR_ELEMTYPE(arrayval), - &elmlen, &elmbyval, &elmalign); - deconstruct_array(arrayval, - ARR_ELEMTYPE(arrayval), - elmlen, elmbyval, elmalign, - &elem_values, &elem_nulls, &num_elems); + result = DatumGetInt32(FunctionCall2Coll(orderproc, cur->sk_collation, + tupdatum, arrdatum)); /* - * Compress out any null elements. We can ignore them since we assume - * all btree operators are strict. + * We flip the sign by following the obvious rule: flip whenever the + * column is a DESC column. + * + * _bt_compare does it the wrong way around (flip when *ASC*) in order + * to compensate for passing its orderproc arguments backwards. We + * don't need to play these games because we find it natural to pass + * tupdatum as the left value (and arrdatum as the right value). */ - num_nonnulls = 0; - for (j = 0; j < num_elems; j++) - { - if (!elem_nulls[j]) - elem_values[num_nonnulls++] = elem_values[j]; - } + if (cur->sk_flags & SK_BT_DESC) + INVERT_COMPARE_RESULT(result); + } - /* We could pfree(elem_nulls) now, but not worth the cycles */ + return result; +} - /* If there's no non-nulls, the scan qual is unsatisfiable */ - if (num_nonnulls == 0) - { - so->qual_ok = false; - break; - } +/* + * _bt_binsrch_array_skey() -- Binary search for next matching array key + * + * Returns an index to the first array element >= caller's tupdatum argument. + * This convention is more natural for forwards scan callers, but that can't + * really matter to backwards scan callers. Both callers require handling for + * the case where the match we return is < tupdatum, and symmetric handling + * for the case where our best match is > tupdatum. + * + * Also sets *set_elem_result to the result _bt_compare_array_skey returned + * when we used it to compare the matching array element to tupdatum/tupnull. + * + * cur_elem_trig indicates if array advancement was triggered by this array's + * scan key, and that the array is for a required scan key. We can apply this + * information to find the next matching array element in the current scan + * direction using far fewer comparisons (fewer on average, compared to naive + * binary search). This scheme takes advantage of an important property of + * required arrays: required arrays always advance in lockstep with the index + * scan's progress through the index's key space. + */ +int +_bt_binsrch_array_skey(FmgrInfo *orderproc, + bool cur_elem_trig, ScanDirection dir, + Datum tupdatum, bool tupnull, + BTArrayKeyInfo *array, ScanKey cur, + int32 *set_elem_result) +{ + int low_elem = 0, + mid_elem = -1, + high_elem = array->num_elems - 1, + result = 0; + Datum arrdatum; - /* - * Determine the nominal datatype of the array elements. We have to - * support the convention that sk_subtype == InvalidOid means the - * opclass input type; this is a hack to simplify life for - * ScanKeyInit(). - */ - elemtype = cur->sk_subtype; - if (elemtype == InvalidOid) - elemtype = rel->rd_opcintype[cur->sk_attno - 1]; + Assert(cur->sk_flags & SK_SEARCHARRAY); + Assert(!(cur->sk_flags & SK_BT_SKIP)); + Assert(!(cur->sk_flags & SK_ISNULL)); /* SAOP arrays never have NULLs */ + Assert(cur->sk_strategy == BTEqualStrategyNumber); - /* - * If the comparison operator is not equality, then the array qual - * degenerates to a simple comparison against the smallest or largest - * non-null array element, as appropriate. - */ - switch (cur->sk_strategy) - { - case BTLessStrategyNumber: - case BTLessEqualStrategyNumber: - cur->sk_argument = - _bt_find_extreme_element(scan, cur, elemtype, - BTGreaterStrategyNumber, - elem_values, num_nonnulls); - continue; - case BTEqualStrategyNumber: - /* proceed with rest of loop */ - break; - case BTGreaterEqualStrategyNumber: - case BTGreaterStrategyNumber: - cur->sk_argument = - _bt_find_extreme_element(scan, cur, elemtype, - BTLessStrategyNumber, - elem_values, num_nonnulls); - continue; - default: - elog(ERROR, "unrecognized StrategyNumber: %d", - (int) cur->sk_strategy); - break; - } + if (cur_elem_trig) + { + Assert(!ScanDirectionIsNoMovement(dir)); + Assert(cur->sk_flags & SK_BT_REQFWD); /* - * We'll need a 3-way ORDER proc to perform binary searches for the - * next matching array element. Set that up now. + * When the scan key that triggered array advancement is a required + * array scan key, it is now certain that the current array element + * (plus all prior elements relative to the current scan direction) + * cannot possibly be at or ahead of the corresponding tuple value. + * (_bt_checkkeys must have called _bt_tuple_before_array_skeys, which + * makes sure this is true as a condition of advancing the arrays.) + * + * This makes it safe to exclude array elements up to and including + * the former-current array element from our search. * - * Array scan keys with cross-type equality operators will require a - * separate same-type ORDER proc for sorting their array. Otherwise, - * sortproc just points to the same proc used during binary searches. + * Separately, when array advancement was triggered by a required scan + * key, the array element immediately after the former-current element + * is often either an exact tupdatum match, or a "close by" near-match + * (a near-match tupdatum is one whose key space falls _between_ the + * former-current and new-current array elements). We'll detect both + * cases via an optimistic comparison of the new search lower bound + * (or new search upper bound in the case of backwards scans). */ - _bt_setup_array_cmp(scan, cur, elemtype, - &so->orderProcs[i], &sortprocp); + if (ScanDirectionIsForward(dir)) + { + low_elem = array->cur_elem + 1; /* old cur_elem exhausted */ - /* - * Sort the non-null elements and eliminate any duplicates. We must - * sort in the same ordering used by the index column, so that the - * arrays can be advanced in lockstep with the scan's progress through - * the index's key space. - */ - reverse = (indoption[cur->sk_attno - 1] & INDOPTION_DESC) != 0; - num_elems = _bt_sort_array_elements(cur, sortprocp, reverse, - elem_values, num_nonnulls); + /* Compare prospective new cur_elem (also the new lower bound) */ + if (high_elem >= low_elem) + { + arrdatum = array->elem_values[low_elem]; + result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, + arrdatum, cur); + + if (result <= 0) + { + /* Optimistic comparison optimization worked out */ + *set_elem_result = result; + return low_elem; + } + mid_elem = low_elem; + low_elem++; /* this cur_elem exhausted, too */ + } - if (origarrayatt == cur->sk_attno) + if (high_elem < low_elem) + { + /* Caller needs to perform "beyond end" array advancement */ + *set_elem_result = 1; + return high_elem; + } + } + else { - BTArrayKeyInfo *orig = &so->arrayKeys[origarraykey]; + high_elem = array->cur_elem - 1; /* old cur_elem exhausted */ - /* - * This array scan key is redundant with a previous equality - * operator array scan key. Merge the two arrays together to - * eliminate contradictory non-intersecting elements (or try to). - * - * We merge this next array back into attribute's original array. - */ - Assert(arrayKeyData[orig->scan_key].sk_attno == cur->sk_attno); - Assert(arrayKeyData[orig->scan_key].sk_collation == - cur->sk_collation); - if (_bt_merge_arrays(scan, cur, sortprocp, reverse, - origelemtype, elemtype, - orig->elem_values, &orig->num_elems, - elem_values, num_elems)) + /* Compare prospective new cur_elem (also the new upper bound) */ + if (high_elem >= low_elem) { - /* Successfully eliminated this array */ - pfree(elem_values); + arrdatum = array->elem_values[high_elem]; + result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, + arrdatum, cur); - /* - * If no intersecting elements remain in the original array, - * the scan qual is unsatisfiable - */ - if (orig->num_elems == 0) + if (result >= 0) { - so->qual_ok = false; - break; + /* Optimistic comparison optimization worked out */ + *set_elem_result = result; + return high_elem; } - - /* - * Indicate to _bt_preprocess_keys caller that it must ignore - * this scan key - */ - cur->sk_strategy = InvalidStrategy; - continue; + mid_elem = high_elem; + high_elem--; /* this cur_elem exhausted, too */ } - /* - * Unable to merge this array with previous array due to a lack of - * suitable cross-type opfamily support. Will need to keep both - * scan keys/arrays. - */ + if (high_elem < low_elem) + { + /* Caller needs to perform "beyond end" array advancement */ + *set_elem_result = -1; + return low_elem; + } } - else + } + + while (high_elem > low_elem) + { + mid_elem = low_elem + ((high_elem - low_elem) / 2); + arrdatum = array->elem_values[mid_elem]; + + result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, + arrdatum, cur); + + if (result == 0) { /* - * This array is the first for current index attribute. - * - * If it turns out to not be the last array (that is, if the next - * array is redundantly applied to this same index attribute), - * we'll then treat this array as the attribute's "original" array - * when merging. + * It's safe to quit as soon as we see an equal array element. + * This often saves an extra comparison or two... */ - origarrayatt = cur->sk_attno; - origarraykey = numArrayKeys; - origelemtype = elemtype; + low_elem = mid_elem; + break; } - /* - * And set up the BTArrayKeyInfo data. - * - * Note: _bt_preprocess_array_keys_final will fix-up each array's - * scan_key field later on, after so->keyData[] has been finalized. - */ - so->arrayKeys[numArrayKeys].scan_key = i; - so->arrayKeys[numArrayKeys].num_elems = num_elems; - so->arrayKeys[numArrayKeys].elem_values = elem_values; - numArrayKeys++; + if (result > 0) + low_elem = mid_elem + 1; + else + high_elem = mid_elem; } - so->numArrayKeys = numArrayKeys; + /* + * ...but our caller also cares about how its searched-for tuple datum + * compares to the low_elem datum. Must always set *set_elem_result with + * the result of that comparison specifically. + */ + if (low_elem != mid_elem) + result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, + array->elem_values[low_elem], cur); - MemoryContextSwitchTo(oldContext); + *set_elem_result = result; - return arrayKeyData; + return low_elem; } /* - * _bt_preprocess_array_keys_final() -- fix up array scan key references + * _bt_binsrch_skiparray_skey() -- "Binary search" within a skip array * - * When _bt_preprocess_array_keys performed initial array preprocessing, it - * set each array's array->scan_key to the array's arrayKeys[] entry offset - * (that also work as references into the original scan->keyData[] array). - * This function handles translation of the scan key references from the - * BTArrayKeyInfo info array, from input scan key references (to the keys in - * scan->keyData[]), into output references (to the keys in so->keyData[]). - * Caller's keyDataMap[] array tells us how to perform this remapping. + * Does not return an index into the array, since skip arrays don't really + * contain elements (they generate their array elements procedurally instead). + * Our interface matches that of _bt_binsrch_array_skey in every other way. * - * Also finalizes so->orderProcs[] for the scan. Arrays already have an ORDER - * proc, which might need to be repositioned to its so->keyData[]-wise offset - * (very much like the remapping that we apply to array->scan_key references). - * Non-array equality strategy scan keys (that survived preprocessing) don't - * yet have an so->orderProcs[] entry, so we set one for them here. + * Sets *set_elem_result just like _bt_binsrch_array_skey would with a true + * array. The value 0 indicates that tupdatum/tupnull is within the range of + * the skip array. We return -1 when tupdatum/tupnull is lower that any value + * within the range of the array, and 1 when it is higher than every value. + * Caller should pass *set_elem_result to _bt_skiparray_set_element to advance + * the array. * - * Also converts single-element array scan keys into equivalent non-array - * equality scan keys, which decrements so->numArrayKeys. It's possible that - * this will leave this new btrescan without any arrays at all. This isn't - * necessary for correctness; it's just an optimization. Non-array equality - * scan keys are slightly faster than equivalent array scan keys at runtime. + * cur_elem_trig indicates if array advancement was triggered by this array's + * scan key. We use this to optimize-away comparisons that are known by our + * caller to be unnecessary from context, just like _bt_binsrch_array_skey. */ static void -_bt_preprocess_array_keys_final(IndexScanDesc scan, int *keyDataMap) +_bt_binsrch_skiparray_skey(bool cur_elem_trig, ScanDirection dir, + Datum tupdatum, bool tupnull, + BTArrayKeyInfo *array, ScanKey cur, + int32 *set_elem_result) { - BTScanOpaque so = (BTScanOpaque) scan->opaque; - Relation rel = scan->indexRelation; - int arrayidx = 0; - int last_equal_output_ikey PG_USED_FOR_ASSERTS_ONLY = -1; + Assert(cur->sk_flags & SK_BT_SKIP); + Assert(cur->sk_flags & SK_SEARCHARRAY); + Assert(cur->sk_flags & SK_BT_REQFWD); + Assert(array->num_elems == -1); + Assert(!ScanDirectionIsNoMovement(dir)); - Assert(so->qual_ok); + if (array->null_elem) + { + Assert(!array->low_compare && !array->high_compare); - /* - * Nothing for us to do when _bt_preprocess_array_keys only had to deal - * with array inequalities - */ - if (so->numArrayKeys == 0) + *set_elem_result = 0; return; + } - for (int output_ikey = 0; output_ikey < so->numberOfKeys; output_ikey++) + if (tupnull) /* NULL tupdatum */ { - ScanKey outkey = so->keyData + output_ikey; - int input_ikey; - bool found PG_USED_FOR_ASSERTS_ONLY = false; - - Assert(outkey->sk_strategy != InvalidStrategy); - - if (outkey->sk_strategy != BTEqualStrategyNumber) - continue; - - input_ikey = keyDataMap[output_ikey]; - - Assert(last_equal_output_ikey < output_ikey); - Assert(last_equal_output_ikey < input_ikey); - last_equal_output_ikey = output_ikey; + if (cur->sk_flags & SK_BT_NULLS_FIRST) + *set_elem_result = -1; /* NULL "<" NOT_NULL */ + else + *set_elem_result = 1; /* NULL ">" NOT_NULL */ + return; + } + /* + * Array inequalities determine whether tupdatum is within the range of + * caller's skip array + */ + *set_elem_result = 0; + if (ScanDirectionIsForward(dir)) + { /* - * We're lazy about looking up ORDER procs for non-array keys, since - * not all input keys become output keys. Take care of it now. + * Evaluate low_compare first (unless cur_elem_trig tells us that it + * cannot possibly fail to be satisfied), then evaluate high_compare */ - if (!(outkey->sk_flags & SK_SEARCHARRAY)) - { - Oid elemtype; - - /* No need for an ORDER proc given an IS NULL scan key */ - if (outkey->sk_flags & SK_SEARCHNULL) - continue; - - /* - * A non-required scan key doesn't need an ORDER proc, either - * (unless it's associated with an array, which this one isn't) - */ - if (!(outkey->sk_flags & SK_BT_REQFWD)) - continue; - - elemtype = outkey->sk_subtype; - if (elemtype == InvalidOid) - elemtype = rel->rd_opcintype[outkey->sk_attno - 1]; - - _bt_setup_array_cmp(scan, outkey, elemtype, - &so->orderProcs[output_ikey], NULL); - continue; - } - + if (!cur_elem_trig && array->low_compare && + !DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func, + array->low_compare->sk_collation, + tupdatum, + array->low_compare->sk_argument))) + *set_elem_result = -1; + else if (array->high_compare && + !DatumGetBool(FunctionCall2Coll(&array->high_compare->sk_func, + array->high_compare->sk_collation, + tupdatum, + array->high_compare->sk_argument))) + *set_elem_result = 1; + } + else + { /* - * Reorder existing array scan key so->orderProcs[] entries. - * - * Doing this in-place is safe because preprocessing is required to - * output all equality strategy scan keys in original input order - * (among each group of entries against the same index attribute). - * This is also the order that the arrays themselves appear in. + * Evaluate high_compare first (unless cur_elem_trig tells us that it + * cannot possibly fail to be satisfied), then evaluate low_compare */ - so->orderProcs[output_ikey] = so->orderProcs[input_ikey]; - - /* Fix-up array->scan_key references for arrays */ - for (; arrayidx < so->numArrayKeys; arrayidx++) - { - BTArrayKeyInfo *array = &so->arrayKeys[arrayidx]; - - Assert(array->num_elems > 0); - - if (array->scan_key == input_ikey) - { - /* found it */ - array->scan_key = output_ikey; - found = true; - - /* - * Transform array scan keys that have exactly 1 element - * remaining (following all prior preprocessing) into - * equivalent non-array scan keys. - */ - if (array->num_elems == 1) - { - outkey->sk_flags &= ~SK_SEARCHARRAY; - outkey->sk_argument = array->elem_values[0]; - so->numArrayKeys--; - - /* If we're out of array keys, we can quit right away */ - if (so->numArrayKeys == 0) - return; - - /* Shift other arrays forward */ - memmove(array, array + 1, - sizeof(BTArrayKeyInfo) * - (so->numArrayKeys - arrayidx)); - - /* - * Don't increment arrayidx (there was an entry that was - * just shifted forward to the offset at arrayidx, which - * will still need to be matched) - */ - } - else - { - /* Match found, so done with this array */ - arrayidx++; - } - - break; - } - } - - Assert(found); + if (!cur_elem_trig && array->high_compare && + !DatumGetBool(FunctionCall2Coll(&array->high_compare->sk_func, + array->high_compare->sk_collation, + tupdatum, + array->high_compare->sk_argument))) + *set_elem_result = 1; + else if (array->low_compare && + !DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func, + array->low_compare->sk_collation, + tupdatum, + array->low_compare->sk_argument))) + *set_elem_result = -1; } /* - * Parallel index scans require space in shared memory to store the - * current array elements (for arrays kept by preprocessing) to schedule - * the next primitive index scan. The underlying structure is protected - * using a spinlock, so defensively limit its size. In practice this can - * only affect parallel scans that use an incomplete opfamily. + * Assert that any keys that were assumed to be satisfied already (due to + * caller passing cur_elem_trig=true) really are satisfied as expected */ - if (scan->parallel_scan && so->numArrayKeys > INDEX_MAX_KEYS) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg_internal("number of array scan keys left by preprocessing (%d) exceeds the maximum allowed by parallel btree index scans (%d)", - so->numArrayKeys, INDEX_MAX_KEYS))); +#ifdef USE_ASSERT_CHECKING + if (cur_elem_trig) + { + if (ScanDirectionIsForward(dir) && array->low_compare) + Assert(DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func, + array->low_compare->sk_collation, + tupdatum, + array->low_compare->sk_argument))); + + if (ScanDirectionIsBackward(dir) && array->high_compare) + Assert(DatumGetBool(FunctionCall2Coll(&array->high_compare->sk_func, + array->high_compare->sk_collation, + tupdatum, + array->high_compare->sk_argument))); + } +#endif } /* - * _bt_setup_array_cmp() -- Set up array comparison functions - * - * Sets ORDER proc in caller's orderproc argument, which is used during binary - * searches of arrays during the index scan. Also sets a same-type ORDER proc - * in caller's *sortprocp argument, which is used when sorting the array. + * _bt_skiparray_set_element() -- Set skip array scan key's sk_argument * - * Preprocessing calls here with all equality strategy scan keys (when scan - * uses equality array keys), including those not associated with any array. - * See _bt_advance_array_keys for an explanation of why it'll need to treat - * simple scalar equality scan keys as degenerate single element arrays. + * Caller passes set_elem_result returned by _bt_binsrch_skiparray_skey for + * caller's tupdatum/tupnull. * - * Caller should pass an orderproc pointing to space that'll store the ORDER - * proc for the scan, and a *sortprocp pointing to its own separate space. - * When calling here for a non-array scan key, sortprocp arg should be NULL. - * - * In the common case where we don't need to deal with cross-type operators, - * only one ORDER proc is actually required by caller. We'll set *sortprocp - * to point to the same memory that caller's orderproc continues to point to. - * Otherwise, *sortprocp will continue to point to caller's own space. Either - * way, *sortprocp will point to a same-type ORDER proc (since that's the only - * safe way to sort/deduplicate the array associated with caller's scan key). + * We copy tupdatum/tupnull into skey's sk_argument iff set_elem_result == 0. + * Otherwise, we set skey to either the lowest or highest value that's within + * the range of caller's skip array (whichever is the best available match to + * tupdatum/tupnull that is still within the range of the skip array according + * to _bt_binsrch_skiparray_skey/set_elem_result). */ static void -_bt_setup_array_cmp(IndexScanDesc scan, ScanKey skey, Oid elemtype, - FmgrInfo *orderproc, FmgrInfo **sortprocp) +_bt_skiparray_set_element(Relation rel, ScanKey skey, BTArrayKeyInfo *array, + int32 set_elem_result, Datum tupdatum, bool tupnull) { - BTScanOpaque so = (BTScanOpaque) scan->opaque; - Relation rel = scan->indexRelation; - RegProcedure cmp_proc; - Oid opcintype = rel->rd_opcintype[skey->sk_attno - 1]; - - Assert(skey->sk_strategy == BTEqualStrategyNumber); - Assert(OidIsValid(elemtype)); + Assert(skey->sk_flags & SK_BT_SKIP); + Assert(skey->sk_flags & SK_SEARCHARRAY); - /* - * If scankey operator is not a cross-type comparison, we can use the - * cached comparison function; otherwise gotta look it up in the catalogs - */ - if (elemtype == opcintype) + if (set_elem_result) { - /* Set same-type ORDER procs for caller */ - *orderproc = *index_getprocinfo(rel, skey->sk_attno, BTORDER_PROC); - if (sortprocp) - *sortprocp = orderproc; + /* tupdatum/tupnull is out of the range of the skip array */ + Assert(!array->null_elem); + _bt_array_set_low_or_high(rel, skey, array, set_elem_result < 0); return; } - /* - * Look up the appropriate cross-type comparison function in the opfamily. - * - * Use the opclass input type as the left hand arg type, and the array - * element type as the right hand arg type (since binary searches use an - * index tuple's attribute value to search for a matching array element). - * - * Note: it's possible that this would fail, if the opfamily is - * incomplete, but only in cases where it's quite likely that _bt_first - * would fail in just the same way (had we not failed before it could). - */ - cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], - opcintype, elemtype, BTORDER_PROC); - if (!RegProcedureIsValid(cmp_proc)) - elog(ERROR, "missing support function %d(%u,%u) for attribute %d of index \"%s\"", - BTORDER_PROC, opcintype, elemtype, skey->sk_attno, - RelationGetRelationName(rel)); - - /* Set cross-type ORDER proc for caller */ - fmgr_info_cxt(cmp_proc, orderproc, so->arrayContext); - - /* Done if caller doesn't actually have an array they'll need to sort */ - if (!sortprocp) + /* Advance skip array to tupdatum (or tupnull) value */ + if (unlikely(tupnull)) + { + _bt_skiparray_set_isnull(rel, skey, array); return; + } - /* - * Look up the appropriate same-type comparison function in the opfamily. - * - * Note: it's possible that this would fail, if the opfamily is - * incomplete, but it seems quite unlikely that an opfamily would omit - * non-cross-type comparison procs for any datatype that it supports at - * all. - */ - cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], - elemtype, elemtype, BTORDER_PROC); - if (!RegProcedureIsValid(cmp_proc)) - elog(ERROR, "missing support function %d(%u,%u) for attribute %d of index \"%s\"", - BTORDER_PROC, elemtype, elemtype, - skey->sk_attno, RelationGetRelationName(rel)); - - /* Set same-type ORDER proc for caller */ - fmgr_info_cxt(cmp_proc, *sortprocp, so->arrayContext); + /* Free memory previously allocated for sk_argument if needed */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + + /* tupdatum becomes new sk_argument/new current element */ + skey->sk_flags &= ~(SK_SEARCHNULL | SK_ISNULL | + SK_BT_MINVAL | SK_BT_MAXVAL | + SK_BT_NEXT | SK_BT_PRIOR); + skey->sk_argument = datumCopy(tupdatum, array->attbyval, array->attlen); +} + +/* + * _bt_skiparray_set_isnull() -- set skip array scan key to NULL + */ +static void +_bt_skiparray_set_isnull(Relation rel, ScanKey skey, BTArrayKeyInfo *array) +{ + Assert(skey->sk_flags & SK_BT_SKIP); + Assert(skey->sk_flags & SK_SEARCHARRAY); + Assert(array->null_elem && !array->low_compare && !array->high_compare); + + /* Free memory previously allocated for sk_argument if needed */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + + /* NULL becomes new sk_argument/new current element */ + skey->sk_argument = (Datum) 0; + skey->sk_flags &= ~(SK_BT_MINVAL | SK_BT_MAXVAL | + SK_BT_NEXT | SK_BT_PRIOR); + skey->sk_flags |= (SK_SEARCHNULL | SK_ISNULL); } /* - * _bt_find_extreme_element() -- get least or greatest array element + * _bt_start_array_keys() -- Initialize array keys at start of a scan * - * scan and skey identify the index column, whose opfamily determines the - * comparison semantics. strat should be BTLessStrategyNumber to get the - * least element, or BTGreaterStrategyNumber to get the greatest. + * Set up the cur_elem counters and fill in the first sk_argument value for + * each array scankey. */ -static Datum -_bt_find_extreme_element(IndexScanDesc scan, ScanKey skey, Oid elemtype, - StrategyNumber strat, - Datum *elems, int nelems) +void +_bt_start_array_keys(IndexScanDesc scan, ScanDirection dir) { Relation rel = scan->indexRelation; - Oid cmp_op; - RegProcedure cmp_proc; - FmgrInfo flinfo; - Datum result; - int i; + BTScanOpaque so = (BTScanOpaque) scan->opaque; - /* - * Look up the appropriate comparison operator in the opfamily. - * - * Note: it's possible that this would fail, if the opfamily is - * incomplete, but it seems quite unlikely that an opfamily would omit - * non-cross-type comparison operators for any datatype that it supports - * at all. - */ - Assert(skey->sk_strategy != BTEqualStrategyNumber); - Assert(OidIsValid(elemtype)); - cmp_op = get_opfamily_member(rel->rd_opfamily[skey->sk_attno - 1], - elemtype, - elemtype, - strat); - if (!OidIsValid(cmp_op)) - elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - strat, elemtype, elemtype, - rel->rd_opfamily[skey->sk_attno - 1]); - cmp_proc = get_opcode(cmp_op); - if (!RegProcedureIsValid(cmp_proc)) - elog(ERROR, "missing oprcode for operator %u", cmp_op); - - fmgr_info(cmp_proc, &flinfo); - - Assert(nelems > 0); - result = elems[0]; - for (i = 1; i < nelems; i++) + Assert(so->numArrayKeys); + Assert(so->qual_ok); + + for (int i = 0; i < so->numArrayKeys; i++) { - if (DatumGetBool(FunctionCall2Coll(&flinfo, - skey->sk_collation, - elems[i], - result))) - result = elems[i]; - } + BTArrayKeyInfo *array = &so->arrayKeys[i]; + ScanKey skey = &so->keyData[array->scan_key]; - return result; + Assert(skey->sk_flags & SK_SEARCHARRAY); + + _bt_array_set_low_or_high(rel, skey, array, + ScanDirectionIsForward(dir)); + } + so->scanBehind = so->oppositeDirCheck = false; /* reset */ } /* - * _bt_sort_array_elements() -- sort and de-dup array elements + * _bt_array_set_low_or_high() -- Set array scan key to lowest/highest element * - * The array elements are sorted in-place, and the new number of elements - * after duplicate removal is returned. - * - * skey identifies the index column whose opfamily determines the comparison - * semantics, and sortproc is a corresponding ORDER proc. If reverse is true, - * we sort in descending order. + * Caller also passes associated scan key, which will have its argument set to + * the lowest/highest array value in passing. */ -static int -_bt_sort_array_elements(ScanKey skey, FmgrInfo *sortproc, bool reverse, - Datum *elems, int nelems) +static void +_bt_array_set_low_or_high(Relation rel, ScanKey skey, BTArrayKeyInfo *array, + bool low_not_high) { - BTSortArrayContext cxt; + Assert(skey->sk_flags & SK_SEARCHARRAY); + + if (array->num_elems != -1) + { + /* set low or high element for SAOP array */ + int set_elem = 0; - if (nelems <= 1) - return nelems; /* no work to do */ + Assert(!(skey->sk_flags & SK_BT_SKIP)); - /* Sort the array elements */ - cxt.sortproc = sortproc; - cxt.collation = skey->sk_collation; - cxt.reverse = reverse; - qsort_arg(elems, nelems, sizeof(Datum), - _bt_compare_array_elements, &cxt); + if (!low_not_high) + set_elem = array->num_elems - 1; - /* Now scan the sorted elements and remove duplicates */ - return qunique_arg(elems, nelems, sizeof(Datum), - _bt_compare_array_elements, &cxt); + /* + * Just copy over array datum (only skip arrays require freeing and + * allocating memory for sk_argument) + */ + array->cur_elem = set_elem; + skey->sk_argument = array->elem_values[set_elem]; + + return; + } + + /* set low or high element for skip array */ + Assert(skey->sk_flags & SK_BT_SKIP); + Assert(array->num_elems == -1); + + /* Free memory previously allocated for sk_argument if needed */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + + /* Reset flags */ + skey->sk_argument = (Datum) 0; + skey->sk_flags &= ~(SK_SEARCHNULL | SK_ISNULL | + SK_BT_MINVAL | SK_BT_MAXVAL | + SK_BT_NEXT | SK_BT_PRIOR); + + if (array->null_elem && + (low_not_high == ((skey->sk_flags & SK_BT_NULLS_FIRST) != 0))) + { + /* Requested element (either lowest or highest) has the value NULL */ + skey->sk_flags |= (SK_SEARCHNULL | SK_ISNULL); + } + else if (low_not_high) + { + /* Setting array to lowest element (according to low_compare) */ + skey->sk_flags |= SK_BT_MINVAL; + } + else + { + /* Setting array to highest element (according to high_compare) */ + skey->sk_flags |= SK_BT_MAXVAL; + } } /* - * _bt_merge_arrays() -- merge next array's elements into an original array + * _bt_array_decrement() -- decrement array scan key's sk_argument * - * Called when preprocessing encounters a pair of array equality scan keys, - * both against the same index attribute (during initial array preprocessing). - * Merging reorganizes caller's original array (the left hand arg) in-place, - * without ever copying elements from one array into the other. (Mixing the - * elements together like this would be wrong, since they don't necessarily - * use the same underlying element type, despite all the other similarities.) - * - * Both arrays must have already been sorted and deduplicated by calling - * _bt_sort_array_elements. sortproc is the same-type ORDER proc that was - * just used to sort and deduplicate caller's "next" array. We'll usually be - * able to reuse that order PROC to merge the arrays together now. If not, - * then we'll perform a separate ORDER proc lookup. - * - * If the opfamily doesn't supply a complete set of cross-type ORDER procs we - * may not be able to determine which elements are contradictory. If we have - * the required ORDER proc then we return true (and validly set *nelems_orig), - * guaranteeing that at least the next array can be considered redundant. We - * return false if the required comparisons cannot not be made (caller must - * keep both arrays when this happens). + * Return value indicates whether caller's array was successfully decremented. + * Cannot decrement an array whose current element is already the first one. */ static bool -_bt_merge_arrays(IndexScanDesc scan, ScanKey skey, FmgrInfo *sortproc, - bool reverse, Oid origelemtype, Oid nextelemtype, - Datum *elems_orig, int *nelems_orig, - Datum *elems_next, int nelems_next) +_bt_array_decrement(Relation rel, ScanKey skey, BTArrayKeyInfo *array) { - Relation rel = scan->indexRelation; - BTScanOpaque so = (BTScanOpaque) scan->opaque; - BTSortArrayContext cxt; - int nelems_orig_start = *nelems_orig, - nelems_orig_merged = 0; - FmgrInfo *mergeproc = sortproc; - FmgrInfo crosstypeproc; + bool uflow = false; + Datum dec_sk_argument; - Assert(skey->sk_strategy == BTEqualStrategyNumber); - Assert(OidIsValid(origelemtype) && OidIsValid(nextelemtype)); + Assert(skey->sk_flags & SK_SEARCHARRAY); + Assert(!(skey->sk_flags & (SK_BT_MAXVAL | SK_BT_NEXT | SK_BT_PRIOR))); - if (origelemtype != nextelemtype) + /* SAOP array? */ + if (array->num_elems != -1) { - RegProcedure cmp_proc; - - /* - * Cross-array-element-type merging is required, so can't just reuse - * sortproc when merging - */ - cmp_proc = get_opfamily_proc(rel->rd_opfamily[skey->sk_attno - 1], - origelemtype, nextelemtype, BTORDER_PROC); - if (!RegProcedureIsValid(cmp_proc)) + Assert(!(skey->sk_flags & (SK_BT_SKIP | SK_BT_MINVAL | SK_BT_MAXVAL))); + if (array->cur_elem > 0) { - /* Can't make the required comparisons */ - return false; + /* + * Just decrement current element, and assign its datum to skey + * (only skip arrays need us to free existing sk_argument memory) + */ + array->cur_elem--; + skey->sk_argument = array->elem_values[array->cur_elem]; + + /* Successfully decremented array */ + return true; } - /* We have all we need to determine redundancy/contradictoriness */ - mergeproc = &crosstypeproc; - fmgr_info_cxt(cmp_proc, mergeproc, so->arrayContext); + /* Cannot decrement to before first array element */ + return false; } - cxt.sortproc = mergeproc; - cxt.collation = skey->sk_collation; - cxt.reverse = reverse; + /* Nope, this is a skip array */ + Assert(skey->sk_flags & SK_BT_SKIP); + + /* + * The sentinel value that represents the minimum value within the range + * of a skip array (often just -inf) is never decrementable + */ + if (skey->sk_flags & SK_BT_MINVAL) + return false; + + /* + * When the current array element is NULL, and the lowest sorting value in + * the index is also NULL, we cannot decrement before first array element + */ + if ((skey->sk_flags & SK_ISNULL) && (skey->sk_flags & SK_BT_NULLS_FIRST)) + return false; + + /* + * Opclasses without skip support "decrement" the scan key's current + * element by setting the PRIOR flag. The true prior value is determined + * by repositioning to the last index tuple < existing sk_argument/current + * array element. Note that this works in the usual way when the scan key + * is already marked ISNULL (i.e. when the current element is NULL). + */ + if (!array->sksup) + { + /* Successfully "decremented" array */ + skey->sk_flags |= SK_BT_PRIOR; + return true; + } - for (int i = 0, j = 0; i < nelems_orig_start && j < nelems_next;) + /* + * Opclasses with skip support directly decrement sk_argument + */ + if (skey->sk_flags & SK_ISNULL) { - Datum *oelem = elems_orig + i, - *nelem = elems_next + j; - int res = _bt_compare_array_elements(oelem, nelem, &cxt); + Assert(!(skey->sk_flags & SK_BT_NULLS_FIRST)); + + /* + * Existing sk_argument/array element is NULL (for an IS NULL qual). + * + * "Decrement" from NULL to the high_elem value provided by opclass + * skip support routine. + */ + skey->sk_flags &= ~(SK_SEARCHNULL | SK_ISNULL); + skey->sk_argument = datumCopy(array->sksup->high_elem, + array->attbyval, array->attlen); + return true; + } - if (res == 0) + /* + * Ask opclass support routine to provide decremented copy of existing + * non-NULL sk_argument + */ + dec_sk_argument = array->sksup->decrement(rel, skey->sk_argument, &uflow); + if (unlikely(uflow)) + { + /* dec_sk_argument has undefined value (so no pfree) */ + if (array->null_elem && (skey->sk_flags & SK_BT_NULLS_FIRST)) { - elems_orig[nelems_orig_merged++] = *oelem; - i++; - j++; + _bt_skiparray_set_isnull(rel, skey, array); + + /* Successfully "decremented" array to NULL */ + return true; } - else if (res < 0) - i++; - else /* res > 0 */ - j++; + + /* Cannot decrement to before first array element */ + return false; + } + + /* + * Successfully decremented sk_argument to a non-NULL value. Make sure + * that the decremented value is still within the range of the array. + */ + if (array->low_compare && + !DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func, + array->low_compare->sk_collation, + dec_sk_argument, + array->low_compare->sk_argument))) + { + /* Keep existing sk_argument after all */ + if (!array->attbyval) + pfree(DatumGetPointer(dec_sk_argument)); + + /* Cannot decrement to before first array element */ + return false; } - *nelems_orig = nelems_orig_merged; + /* Accept value returned by opclass decrement callback */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + skey->sk_argument = dec_sk_argument; + /* Successfully decremented array */ return true; } /* - * Compare an array scan key to a scalar scan key, eliminating contradictory - * array elements such that the scalar scan key becomes redundant. + * _bt_array_increment() -- increment array scan key's sk_argument * - * Array elements can be eliminated as contradictory when excluded by some - * other operator on the same attribute. For example, with an index scan qual - * "WHERE a IN (1, 2, 3) AND a < 2", all array elements except the value "1" - * are eliminated, and the < scan key is eliminated as redundant. Cases where - * every array element is eliminated by a redundant scalar scan key have an - * unsatisfiable qual, which we handle by setting *qual_ok=false for caller. - * - * If the opfamily doesn't supply a complete set of cross-type ORDER procs we - * may not be able to determine which elements are contradictory. If we have - * the required ORDER proc then we return true (and validly set *qual_ok), - * guaranteeing that at least the scalar scan key can be considered redundant. - * We return false if the comparison could not be made (caller must keep both - * scan keys when this happens). + * Return value indicates whether caller's array was successfully incremented. + * Cannot increment an array whose current element is already the final one. */ static bool -_bt_compare_array_scankey_args(IndexScanDesc scan, ScanKey arraysk, ScanKey skey, - FmgrInfo *orderproc, BTArrayKeyInfo *array, - bool *qual_ok) +_bt_array_increment(Relation rel, ScanKey skey, BTArrayKeyInfo *array) { - Relation rel = scan->indexRelation; - Oid opcintype = rel->rd_opcintype[arraysk->sk_attno - 1]; - int cmpresult = 0, - cmpexact = 0, - matchelem, - new_nelems = 0; - FmgrInfo crosstypeproc; - FmgrInfo *orderprocp = orderproc; - - Assert(arraysk->sk_attno == skey->sk_attno); - Assert(array->num_elems > 0); - Assert(!(arraysk->sk_flags & (SK_ISNULL | SK_ROW_HEADER | SK_ROW_MEMBER))); - Assert((arraysk->sk_flags & SK_SEARCHARRAY) && - arraysk->sk_strategy == BTEqualStrategyNumber); - Assert(!(skey->sk_flags & (SK_ISNULL | SK_ROW_HEADER | SK_ROW_MEMBER))); - Assert(!(skey->sk_flags & SK_SEARCHARRAY) || - skey->sk_strategy != BTEqualStrategyNumber); + bool oflow = false; + Datum inc_sk_argument; + + Assert(skey->sk_flags & SK_SEARCHARRAY); + Assert(!(skey->sk_flags & (SK_BT_MINVAL | SK_BT_NEXT | SK_BT_PRIOR))); + + /* SAOP array? */ + if (array->num_elems != -1) + { + Assert(!(skey->sk_flags & (SK_BT_SKIP | SK_BT_MINVAL | SK_BT_MAXVAL))); + if (array->cur_elem < array->num_elems - 1) + { + /* + * Just increment current element, and assign its datum to skey + * (only skip arrays need us to free existing sk_argument memory) + */ + array->cur_elem++; + skey->sk_argument = array->elem_values[array->cur_elem]; + + /* Successfully incremented array */ + return true; + } + + /* Cannot increment past final array element */ + return false; + } + + /* Nope, this is a skip array */ + Assert(skey->sk_flags & SK_BT_SKIP); /* - * _bt_binsrch_array_skey searches an array for the entry best matching a - * datum of opclass input type for the index's attribute (on-disk type). - * We can reuse the array's ORDER proc whenever the non-array scan key's - * type is a match for the corresponding attribute's input opclass type. - * Otherwise, we have to do another ORDER proc lookup so that our call to - * _bt_binsrch_array_skey applies the correct comparator. - * - * Note: we have to support the convention that sk_subtype == InvalidOid - * means the opclass input type; this is a hack to simplify life for - * ScanKeyInit(). + * The sentinel value that represents the maximum value within the range + * of a skip array (often just +inf) is never incrementable + */ + if (skey->sk_flags & SK_BT_MAXVAL) + return false; + + /* + * When the current array element is NULL, and the highest sorting value + * in the index is also NULL, we cannot increment past the final element + */ + if ((skey->sk_flags & SK_ISNULL) && !(skey->sk_flags & SK_BT_NULLS_FIRST)) + return false; + + /* + * Opclasses without skip support "increment" the scan key's current + * element by setting the NEXT flag. The true next value is determined by + * repositioning to the first index tuple > existing sk_argument/current + * array element. Note that this works in the usual way when the scan key + * is already marked ISNULL (i.e. when the current element is NULL). + */ + if (!array->sksup) + { + /* Successfully "incremented" array */ + skey->sk_flags |= SK_BT_NEXT; + return true; + } + + /* + * Opclasses with skip support directly increment sk_argument */ - if (skey->sk_subtype != opcintype && skey->sk_subtype != InvalidOid) + if (skey->sk_flags & SK_ISNULL) { - RegProcedure cmp_proc; - Oid arraysk_elemtype; + Assert(skey->sk_flags & SK_BT_NULLS_FIRST); /* - * Need an ORDER proc lookup to detect redundancy/contradictoriness - * with this pair of scankeys. + * Existing sk_argument/array element is NULL (for an IS NULL qual). * - * Scalar scan key's argument will be passed to _bt_compare_array_skey - * as its tupdatum/lefthand argument (rhs arg is for array elements). + * "Increment" from NULL to the low_elem value provided by opclass + * skip support routine. */ - arraysk_elemtype = arraysk->sk_subtype; - if (arraysk_elemtype == InvalidOid) - arraysk_elemtype = rel->rd_opcintype[arraysk->sk_attno - 1]; - cmp_proc = get_opfamily_proc(rel->rd_opfamily[arraysk->sk_attno - 1], - skey->sk_subtype, arraysk_elemtype, - BTORDER_PROC); - if (!RegProcedureIsValid(cmp_proc)) + skey->sk_flags &= ~(SK_SEARCHNULL | SK_ISNULL); + skey->sk_argument = datumCopy(array->sksup->low_elem, + array->attbyval, array->attlen); + return true; + } + + /* + * Ask opclass support routine to provide incremented copy of existing + * non-NULL sk_argument + */ + inc_sk_argument = array->sksup->increment(rel, skey->sk_argument, &oflow); + if (unlikely(oflow)) + { + /* inc_sk_argument has undefined value (so no pfree) */ + if (array->null_elem && !(skey->sk_flags & SK_BT_NULLS_FIRST)) { - /* Can't make the comparison */ - *qual_ok = false; /* suppress compiler warnings */ - return false; + _bt_skiparray_set_isnull(rel, skey, array); + + /* Successfully "incremented" array to NULL */ + return true; } - /* We have all we need to determine redundancy/contradictoriness */ - orderprocp = &crosstypeproc; - fmgr_info(cmp_proc, orderprocp); + /* Cannot increment past final array element */ + return false; } - matchelem = _bt_binsrch_array_skey(orderprocp, false, - NoMovementScanDirection, - skey->sk_argument, false, array, - arraysk, &cmpresult); - - switch (skey->sk_strategy) + /* + * Successfully incremented sk_argument to a non-NULL value. Make sure + * that the incremented value is still within the range of the array. + */ + if (array->high_compare && + !DatumGetBool(FunctionCall2Coll(&array->high_compare->sk_func, + array->high_compare->sk_collation, + inc_sk_argument, + array->high_compare->sk_argument))) { - case BTLessStrategyNumber: - cmpexact = 1; /* exclude exact match, if any */ - /* FALL THRU */ - case BTLessEqualStrategyNumber: - if (cmpresult >= cmpexact) - matchelem++; - /* Resize, keeping elements from the start of the array */ - new_nelems = matchelem; - break; - case BTEqualStrategyNumber: - if (cmpresult != 0) - { - /* qual is unsatisfiable */ - new_nelems = 0; - } - else - { - /* Shift matching element to the start of the array, resize */ - array->elem_values[0] = array->elem_values[matchelem]; - new_nelems = 1; - } - break; - case BTGreaterEqualStrategyNumber: - cmpexact = 1; /* include exact match, if any */ - /* FALL THRU */ - case BTGreaterStrategyNumber: - if (cmpresult >= cmpexact) - matchelem++; - /* Shift matching elements to the start of the array, resize */ - new_nelems = array->num_elems - matchelem; - memmove(array->elem_values, array->elem_values + matchelem, - sizeof(Datum) * new_nelems); - break; - default: - elog(ERROR, "unrecognized StrategyNumber: %d", - (int) skey->sk_strategy); - break; - } + /* Keep existing sk_argument after all */ + if (!array->attbyval) + pfree(DatumGetPointer(inc_sk_argument)); - Assert(new_nelems >= 0); - Assert(new_nelems <= array->num_elems); + /* Cannot increment past final array element */ + return false; + } - array->num_elems = new_nelems; - *qual_ok = new_nelems > 0; + /* Accept value returned by opclass increment callback */ + if (!array->attbyval && skey->sk_argument) + pfree(DatumGetPointer(skey->sk_argument)); + skey->sk_argument = inc_sk_argument; + /* Successfully incremented array */ return true; } /* - * qsort_arg comparator for sorting array elements - */ -static int -_bt_compare_array_elements(const void *a, const void *b, void *arg) -{ - Datum da = *((const Datum *) a); - Datum db = *((const Datum *) b); - BTSortArrayContext *cxt = (BTSortArrayContext *) arg; - int32 compare; - - compare = DatumGetInt32(FunctionCall2Coll(cxt->sortproc, - cxt->collation, - da, db)); - if (cxt->reverse) - INVERT_COMPARE_RESULT(compare); - return compare; -} - -/* - * _bt_compare_array_skey() -- apply array comparison function - * - * Compares caller's tuple attribute value to a scan key/array element. - * Helper function used during binary searches of SK_SEARCHARRAY arrays. + * _bt_advance_array_keys_increment() -- Advance to next set of array elements * - * This routine returns: - * <0 if tupdatum < arrdatum; - * 0 if tupdatum == arrdatum; - * >0 if tupdatum > arrdatum. + * Advances the array keys by a single increment in the current scan + * direction. When there are multiple array keys this can roll over from the + * lowest order array to higher order arrays. * - * This is essentially the same interface as _bt_compare: both functions - * compare the value that they're searching for to a binary search pivot. - * However, unlike _bt_compare, this function's "tuple argument" comes first, - * while its "array/scankey argument" comes second. -*/ -static inline int32 -_bt_compare_array_skey(FmgrInfo *orderproc, - Datum tupdatum, bool tupnull, - Datum arrdatum, ScanKey cur) -{ - int32 result = 0; - - Assert(cur->sk_strategy == BTEqualStrategyNumber); - - if (tupnull) /* NULL tupdatum */ - { - if (cur->sk_flags & SK_ISNULL) - result = 0; /* NULL "=" NULL */ - else if (cur->sk_flags & SK_BT_NULLS_FIRST) - result = -1; /* NULL "<" NOT_NULL */ - else - result = 1; /* NULL ">" NOT_NULL */ - } - else if (cur->sk_flags & SK_ISNULL) /* NOT_NULL tupdatum, NULL arrdatum */ - { - if (cur->sk_flags & SK_BT_NULLS_FIRST) - result = 1; /* NOT_NULL ">" NULL */ - else - result = -1; /* NOT_NULL "<" NULL */ - } - else - { - /* - * Like _bt_compare, we need to be careful of cross-type comparisons, - * so the left value has to be the value that came from an index tuple - */ - result = DatumGetInt32(FunctionCall2Coll(orderproc, cur->sk_collation, - tupdatum, arrdatum)); - - /* - * We flip the sign by following the obvious rule: flip whenever the - * column is a DESC column. - * - * _bt_compare does it the wrong way around (flip when *ASC*) in order - * to compensate for passing its orderproc arguments backwards. We - * don't need to play these games because we find it natural to pass - * tupdatum as the left value (and arrdatum as the right value). - */ - if (cur->sk_flags & SK_BT_DESC) - INVERT_COMPARE_RESULT(result); - } - - return result; -} - -/* - * _bt_binsrch_array_skey() -- Binary search for next matching array key - * - * Returns an index to the first array element >= caller's tupdatum argument. - * This convention is more natural for forwards scan callers, but that can't - * really matter to backwards scan callers. Both callers require handling for - * the case where the match we return is < tupdatum, and symmetric handling - * for the case where our best match is > tupdatum. - * - * Also sets *set_elem_result to the result _bt_compare_array_skey returned - * when we used it to compare the matching array element to tupdatum/tupnull. - * - * cur_elem_trig indicates if array advancement was triggered by this array's - * scan key, and that the array is for a required scan key. We can apply this - * information to find the next matching array element in the current scan - * direction using far fewer comparisons (fewer on average, compared to naive - * binary search). This scheme takes advantage of an important property of - * required arrays: required arrays always advance in lockstep with the index - * scan's progress through the index's key space. - */ -static int -_bt_binsrch_array_skey(FmgrInfo *orderproc, - bool cur_elem_trig, ScanDirection dir, - Datum tupdatum, bool tupnull, - BTArrayKeyInfo *array, ScanKey cur, - int32 *set_elem_result) -{ - int low_elem = 0, - mid_elem = -1, - high_elem = array->num_elems - 1, - result = 0; - Datum arrdatum; - - Assert(cur->sk_flags & SK_SEARCHARRAY); - Assert(cur->sk_strategy == BTEqualStrategyNumber); - - if (cur_elem_trig) - { - Assert(!ScanDirectionIsNoMovement(dir)); - Assert(cur->sk_flags & SK_BT_REQFWD); - - /* - * When the scan key that triggered array advancement is a required - * array scan key, it is now certain that the current array element - * (plus all prior elements relative to the current scan direction) - * cannot possibly be at or ahead of the corresponding tuple value. - * (_bt_checkkeys must have called _bt_tuple_before_array_skeys, which - * makes sure this is true as a condition of advancing the arrays.) - * - * This makes it safe to exclude array elements up to and including - * the former-current array element from our search. - * - * Separately, when array advancement was triggered by a required scan - * key, the array element immediately after the former-current element - * is often either an exact tupdatum match, or a "close by" near-match - * (a near-match tupdatum is one whose key space falls _between_ the - * former-current and new-current array elements). We'll detect both - * cases via an optimistic comparison of the new search lower bound - * (or new search upper bound in the case of backwards scans). - */ - if (ScanDirectionIsForward(dir)) - { - low_elem = array->cur_elem + 1; /* old cur_elem exhausted */ - - /* Compare prospective new cur_elem (also the new lower bound) */ - if (high_elem >= low_elem) - { - arrdatum = array->elem_values[low_elem]; - result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, - arrdatum, cur); - - if (result <= 0) - { - /* Optimistic comparison optimization worked out */ - *set_elem_result = result; - return low_elem; - } - mid_elem = low_elem; - low_elem++; /* this cur_elem exhausted, too */ - } - - if (high_elem < low_elem) - { - /* Caller needs to perform "beyond end" array advancement */ - *set_elem_result = 1; - return high_elem; - } - } - else - { - high_elem = array->cur_elem - 1; /* old cur_elem exhausted */ - - /* Compare prospective new cur_elem (also the new upper bound) */ - if (high_elem >= low_elem) - { - arrdatum = array->elem_values[high_elem]; - result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, - arrdatum, cur); - - if (result >= 0) - { - /* Optimistic comparison optimization worked out */ - *set_elem_result = result; - return high_elem; - } - mid_elem = high_elem; - high_elem--; /* this cur_elem exhausted, too */ - } - - if (high_elem < low_elem) - { - /* Caller needs to perform "beyond end" array advancement */ - *set_elem_result = -1; - return low_elem; - } - } - } - - while (high_elem > low_elem) - { - mid_elem = low_elem + ((high_elem - low_elem) / 2); - arrdatum = array->elem_values[mid_elem]; - - result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, - arrdatum, cur); - - if (result == 0) - { - /* - * It's safe to quit as soon as we see an equal array element. - * This often saves an extra comparison or two... - */ - low_elem = mid_elem; - break; - } - - if (result > 0) - low_elem = mid_elem + 1; - else - high_elem = mid_elem; - } - - /* - * ...but our caller also cares about how its searched-for tuple datum - * compares to the low_elem datum. Must always set *set_elem_result with - * the result of that comparison specifically. - */ - if (low_elem != mid_elem) - result = _bt_compare_array_skey(orderproc, tupdatum, tupnull, - array->elem_values[low_elem], cur); - - *set_elem_result = result; - - return low_elem; -} - -/* - * _bt_start_array_keys() -- Initialize array keys at start of a scan - * - * Set up the cur_elem counters and fill in the first sk_argument value for - * each array scankey. - */ -void -_bt_start_array_keys(IndexScanDesc scan, ScanDirection dir) -{ - BTScanOpaque so = (BTScanOpaque) scan->opaque; - int i; - - Assert(so->numArrayKeys); - Assert(so->qual_ok); - - for (i = 0; i < so->numArrayKeys; i++) - { - BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i]; - ScanKey skey = &so->keyData[curArrayKey->scan_key]; - - Assert(curArrayKey->num_elems > 0); - Assert(skey->sk_flags & SK_SEARCHARRAY); - - if (ScanDirectionIsBackward(dir)) - curArrayKey->cur_elem = curArrayKey->num_elems - 1; - else - curArrayKey->cur_elem = 0; - skey->sk_argument = curArrayKey->elem_values[curArrayKey->cur_elem]; - } - so->scanBehind = false; -} - -/* - * _bt_advance_array_keys_increment() -- Advance to next set of array elements - * - * Advances the array keys by a single increment in the current scan - * direction. When there are multiple array keys this can roll over from the - * lowest order array to higher order arrays. - * - * Returns true if there is another set of values to consider, false if not. - * On true result, the scankeys are initialized with the next set of values. - * On false result, the scankeys stay the same, and the array keys are not - * advanced (every array remains at its final element for scan direction). - */ -static bool -_bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir) + * Returns true if there is another set of values to consider, false if not. + * On true result, the scankeys are initialized with the next set of values. + * On false result, the scankeys stay the same, and the array keys are not + * advanced (every array remains at its final element for scan direction). + */ +static bool +_bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir, + bool *skip_array_set) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; /* @@ -1389,40 +985,49 @@ _bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir) */ for (int i = so->numArrayKeys - 1; i >= 0; i--) { - BTArrayKeyInfo *curArrayKey = &so->arrayKeys[i]; - ScanKey skey = &so->keyData[curArrayKey->scan_key]; - int cur_elem = curArrayKey->cur_elem; - int num_elems = curArrayKey->num_elems; - bool rolled = false; + BTArrayKeyInfo *array = &so->arrayKeys[i]; + ScanKey skey = &so->keyData[array->scan_key]; + + if (array->num_elems == -1) + *skip_array_set = true; - if (ScanDirectionIsForward(dir) && ++cur_elem >= num_elems) + if (ScanDirectionIsForward(dir)) { - cur_elem = 0; - rolled = true; + if (_bt_array_increment(rel, skey, array)) + return true; } - else if (ScanDirectionIsBackward(dir) && --cur_elem < 0) + else { - cur_elem = num_elems - 1; - rolled = true; + if (_bt_array_decrement(rel, skey, array)) + return true; } - curArrayKey->cur_elem = cur_elem; - skey->sk_argument = curArrayKey->elem_values[cur_elem]; - if (!rolled) - return true; + /* + * Couldn't increment (or decrement) array. Handle array roll over. + * + * Start over at the array's lowest sorting value (or its highest + * value, for backward scans)... + */ + _bt_array_set_low_or_high(rel, skey, array, + ScanDirectionIsForward(dir)); - /* Need to advance next array key, if any */ + /* ...then increment (or decrement) next most significant array */ } /* - * The array keys are now exhausted. (There isn't actually a distinct - * state that represents array exhaustion, since index scans don't always - * end after btgettuple returns "false".) + * The array keys are now exhausted. * * Restore the array keys to the state they were in immediately before we * were called. This ensures that the arrays only ever ratchet in the - * current scan direction. Without this, scans would overlook matching - * tuples if and when the scan's direction was subsequently reversed. + * current scan direction. + * + * Without this, scans could overlook matching tuples when the scan + * direction gets reversed just before btgettuple runs out of items to + * return, but just after _bt_readpage prepares all the items from the + * scan's final page in so->currPos. When we're on the final page it is + * typical for so->currPos to get invalidated once btgettuple finally + * returns false, which'll effectively invalidate the scan's array keys. + * That hasn't happened yet, though -- and in general it may never happen. */ _bt_start_array_keys(scan, -dir); @@ -1430,7 +1035,7 @@ _bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir) } /* - * _bt_rewind_nonrequired_arrays() -- Rewind non-required arrays + * _bt_rewind_nonrequired_arrays() -- Rewind SAOP arrays not marked required * * Called when _bt_advance_array_keys decides to start a new primitive index * scan on the basis of the current scan position being before the position @@ -1462,10 +1067,15 @@ _bt_advance_array_keys_increment(IndexScanDesc scan, ScanDirection dir) * * Note: _bt_verify_arrays_bt_first is called by an assertion to enforce that * everybody got this right. + * + * Note: In practice almost all SAOP arrays are marked required during + * preprocessing (if necessary by generating skip arrays). It is hardly ever + * truly necessary to call here, but consistently doing so is simpler. */ static void _bt_rewind_nonrequired_arrays(IndexScanDesc scan, ScanDirection dir) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; int arrayidx = 0; @@ -1473,7 +1083,6 @@ _bt_rewind_nonrequired_arrays(IndexScanDesc scan, ScanDirection dir) { ScanKey cur = so->keyData + ikey; BTArrayKeyInfo *array = NULL; - int first_elem_dir; if (!(cur->sk_flags & SK_SEARCHARRAY) || cur->sk_strategy != BTEqualStrategyNumber) @@ -1485,16 +1094,10 @@ _bt_rewind_nonrequired_arrays(IndexScanDesc scan, ScanDirection dir) if ((cur->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD))) continue; - if (ScanDirectionIsForward(dir)) - first_elem_dir = 0; - else - first_elem_dir = array->num_elems - 1; + Assert(array->num_elems != -1); /* No non-required skip arrays */ - if (array->cur_elem != first_elem_dir) - { - array->cur_elem = first_elem_dir; - cur->sk_argument = array->elem_values[first_elem_dir]; - } + _bt_array_set_low_or_high(rel, cur, array, + ScanDirectionIsForward(dir)); } } @@ -1507,7 +1110,7 @@ _bt_rewind_nonrequired_arrays(IndexScanDesc scan, ScanDirection dir) * * readpagetup callers must only call here when _bt_check_compare already set * continuescan=false. We help these callers deal with _bt_check_compare's - * inability to distinguishing between the < and > cases (it uses equality + * inability to distinguish between the < and > cases (it uses equality * operator scan keys, whereas we use 3-way ORDER procs). These callers pass * a _bt_check_compare-set sktrig value that indicates which scan key * triggered the call (!readpagetup callers just pass us sktrig=0 instead). @@ -1619,9 +1222,77 @@ _bt_tuple_before_array_skeys(IndexScanDesc scan, ScanDirection dir, tupdatum = index_getattr(tuple, cur->sk_attno, tupdesc, &tupnull); - result = _bt_compare_array_skey(&so->orderProcs[ikey], - tupdatum, tupnull, - cur->sk_argument, cur); + if (likely(!(cur->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL)))) + { + /* Scankey has a valid/comparable sk_argument value */ + result = _bt_compare_array_skey(&so->orderProcs[ikey], + tupdatum, tupnull, + cur->sk_argument, cur); + + if (result == 0) + { + /* + * Interpret result in a way that takes NEXT/PRIOR into + * account + */ + if (cur->sk_flags & SK_BT_NEXT) + result = -1; + else if (cur->sk_flags & SK_BT_PRIOR) + result = 1; + + Assert(result == 0 || (cur->sk_flags & SK_BT_SKIP)); + } + } + else + { + BTArrayKeyInfo *array = NULL; + + /* + * Current array element/array = scan key value is a sentinel + * value that represents the lowest (or highest) possible value + * that's still within the range of the array. + * + * Like _bt_first, we only see MINVAL keys during forwards scans + * (and similarly only see MAXVAL keys during backwards scans). + * Even if the scan's direction changes, we'll stop at some higher + * order key before we can ever reach any MAXVAL (or MINVAL) keys. + * (However, unlike _bt_first we _can_ get to keys marked either + * NEXT or PRIOR, regardless of the scan's current direction.) + */ + Assert(ScanDirectionIsForward(dir) ? + !(cur->sk_flags & SK_BT_MAXVAL) : + !(cur->sk_flags & SK_BT_MINVAL)); + + /* + * There are no valid sk_argument values in MINVAL/MAXVAL keys. + * Check if tupdatum is within the range of skip array instead. + */ + for (int arrayidx = 0; arrayidx < so->numArrayKeys; arrayidx++) + { + array = &so->arrayKeys[arrayidx]; + if (array->scan_key == ikey) + break; + } + + _bt_binsrch_skiparray_skey(false, dir, tupdatum, tupnull, + array, cur, &result); + + if (result == 0) + { + /* + * tupdatum satisfies both low_compare and high_compare, so + * it's time to advance the array keys. + * + * Note: It's possible that the skip array will "advance" from + * its MINVAL (or MAXVAL) representation to an alternative, + * logically equivalent representation of the same value: a + * representation where the = key gets a valid datum in its + * sk_argument. This is only possible when low_compare uses + * the >= strategy (or high_compare uses the <= strategy). + */ + return false; + } + } /* * Does this comparison indicate that caller must _not_ advance the @@ -1671,8 +1342,7 @@ _bt_start_prim_scan(IndexScanDesc scan, ScanDirection dir) Assert(so->numArrayKeys); - /* scanBehind flag doesn't persist across primitive index scans - reset */ - so->scanBehind = false; + so->scanBehind = so->oppositeDirCheck = false; /* reset */ /* * Array keys are advanced within _bt_checkkeys when the scan reaches the @@ -1758,9 +1428,10 @@ _bt_start_prim_scan(IndexScanDesc scan, ScanDirection dir) * postcondition's <= operator with a >=. In other words, just swap the * precondition with the postcondition.) * - * We also deal with "advancing" non-required arrays here. Callers whose - * sktrig scan key is non-required specify sktrig_required=false. These calls - * are the only exception to the general rule about always advancing the + * We also deal with "advancing" non-required arrays here (or arrays that are + * treated as non-required for the duration of a _bt_readpage call). Callers + * whose sktrig scan key is non-required specify sktrig_required=false. These + * calls are the only exception to the general rule about always advancing the * required array keys (the scan may not even have a required array). These * callers should just pass a NULL pstate (since there is never any question * of stopping the scan). No call to _bt_tuple_before_array_skeys is required @@ -1792,14 +1463,17 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, { BTScanOpaque so = (BTScanOpaque) scan->opaque; Relation rel = scan->indexRelation; - ScanDirection dir = pstate ? pstate->dir : ForwardScanDirection; + ScanDirection dir = so->currPos.dir; int arrayidx = 0; bool beyond_end_advance = false, + skip_array_advanced = false, has_required_opposite_direction_only = false, - oppodir_inequality_sktrig = false, all_required_satisfied = true, all_satisfied = true; + Assert(!so->needPrimScan && !so->scanBehind && !so->oppositeDirCheck); + Assert(_bt_verify_keys_with_arraykeys(scan)); + if (sktrig_required) { /* @@ -1808,19 +1482,6 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, Assert(!_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, tupnatts, false, 0, NULL)); - so->scanBehind = false; /* reset */ - - /* - * Required scan key wasn't satisfied, so required arrays will have to - * advance. Invalidate page-level state that tracks whether the - * scan's required-in-opposite-direction-only keys are known to be - * satisfied by page's remaining tuples. - */ - pstate->firstmatch = false; - - /* Shouldn't have to invalidate 'prechecked', though */ - Assert(!pstate->prechecked); - /* * Once we return we'll have a new set of required array keys, so * reset state used by "look ahead" optimization @@ -1828,8 +1489,26 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, pstate->rechecks = 0; pstate->targetdistance = 0; } + else if (sktrig < so->numberOfKeys - 1 && + !(so->keyData[so->numberOfKeys - 1].sk_flags & SK_SEARCHARRAY)) + { + int least_sign_ikey = so->numberOfKeys - 1; + bool continuescan; - Assert(_bt_verify_keys_with_arraykeys(scan)); + /* + * Optimization: perform a precheck of the least significant key + * during !sktrig_required calls when it isn't already our sktrig + * (provided the precheck key is not itself an array). + * + * When the precheck works out we'll avoid an expensive binary search + * of sktrig's array (plus any other arrays before least_sign_ikey). + */ + Assert(so->keyData[sktrig].sk_flags & SK_SEARCHARRAY); + if (!_bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, false, + false, &continuescan, + &least_sign_ikey)) + return false; + } for (int ikey = 0; ikey < so->numberOfKeys; ikey++) { @@ -1871,8 +1550,6 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, if (cur->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD)) { - Assert(sktrig_required); - required = true; if (cur->sk_attno > tupnatts) @@ -1912,18 +1589,6 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, beyond_end_advance = true; all_satisfied = all_required_satisfied = false; - /* - * Set a flag that remembers that this was an inequality required - * in the opposite scan direction only, that nevertheless - * triggered the call here. - * - * This only happens when an inequality operator (which must be - * strict) encounters a group of NULLs that indicate the end of - * non-NULL values for tuples in the current scan direction. - */ - if (unlikely(required_opposite_direction_only)) - oppodir_inequality_sktrig = true; - continue; } @@ -1954,18 +1619,9 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, */ if (beyond_end_advance) { - int final_elem_dir; - - if (ScanDirectionIsBackward(dir) || !array) - final_elem_dir = 0; - else - final_elem_dir = array->num_elems - 1; - - if (array && array->cur_elem != final_elem_dir) - { - array->cur_elem = final_elem_dir; - cur->sk_argument = array->elem_values[final_elem_dir]; - } + if (array) + _bt_array_set_low_or_high(rel, cur, array, + ScanDirectionIsBackward(dir)); continue; } @@ -1990,18 +1646,9 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, */ if (!all_required_satisfied || cur->sk_attno > tupnatts) { - int first_elem_dir; - - if (ScanDirectionIsForward(dir) || !array) - first_elem_dir = 0; - else - first_elem_dir = array->num_elems - 1; - - if (array && array->cur_elem != first_elem_dir) - { - array->cur_elem = first_elem_dir; - cur->sk_argument = array->elem_values[first_elem_dir]; - } + if (array) + _bt_array_set_low_or_high(rel, cur, array, + ScanDirectionIsForward(dir)); continue; } @@ -2017,18 +1664,26 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, bool cur_elem_trig = (sktrig_required && ikey == sktrig); /* - * Binary search for closest match that's available from the array + * "Binary search" by checking if tupdatum/tupnull are within the + * range of the skip array */ - set_elem = _bt_binsrch_array_skey(&so->orderProcs[ikey], - cur_elem_trig, dir, - tupdatum, tupnull, array, cur, - &result); + if (array->num_elems == -1) + _bt_binsrch_skiparray_skey(cur_elem_trig, dir, + tupdatum, tupnull, array, cur, + &result); - Assert(set_elem >= 0 && set_elem < array->num_elems); + /* + * Binary search for the closest match from the SAOP array + */ + else + set_elem = _bt_binsrch_array_skey(&so->orderProcs[ikey], + cur_elem_trig, dir, + tupdatum, tupnull, array, cur, + &result); } else { - Assert(sktrig_required && required); + Assert(required); /* * This is a required non-array equality strategy scan key, which @@ -2070,7 +1725,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * be eliminated by _bt_preprocess_keys. It won't matter if some of * our "true" array scan keys (or even all of them) are non-required. */ - if (required && + if (sktrig_required && required && ((ScanDirectionIsForward(dir) && result > 0) || (ScanDirectionIsBackward(dir) && result < 0))) beyond_end_advance = true; @@ -2085,7 +1740,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * array scan keys are considered interesting.) */ all_satisfied = false; - if (required) + if (sktrig_required && required) all_required_satisfied = false; else { @@ -2100,11 +1755,22 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, } } - /* Advance array keys, even when set_elem isn't an exact match */ - if (array && array->cur_elem != set_elem) + /* Advance array keys, even when we don't have an exact match */ + if (array) { - array->cur_elem = set_elem; - cur->sk_argument = array->elem_values[set_elem]; + if (array->num_elems == -1) + { + /* Skip array's new element is tupdatum (or MINVAL/MAXVAL) */ + _bt_skiparray_set_element(rel, cur, array, result, + tupdatum, tupnull); + skip_array_advanced = true; + } + else if (array->cur_elem != set_elem) + { + /* SAOP array's new element is set_elem datum */ + array->cur_elem = set_elem; + cur->sk_argument = array->elem_values[set_elem]; + } } } @@ -2114,11 +1780,19 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * higher-order arrays (might exhaust all the scan's arrays instead, which * ends the top-level scan). */ - if (beyond_end_advance && !_bt_advance_array_keys_increment(scan, dir)) + if (beyond_end_advance && + !_bt_advance_array_keys_increment(scan, dir, &skip_array_advanced)) goto end_toplevel_scan; Assert(_bt_verify_keys_with_arraykeys(scan)); + /* + * Maintain a page-level count of the number of times the scan's array + * keys advanced in a way that affected at least one skip array + */ + if (sktrig_required && skip_array_advanced) + pstate->nskipadvances++; + /* * Does tuple now satisfy our new qual? Recheck with _bt_check_compare. * @@ -2135,6 +1809,12 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * of any required scan key). All that matters is whether caller's tuple * satisfies the new qual, so it's safe to just skip the _bt_check_compare * recheck when we've already determined that it can only return 'false'. + * + * Note: In practice most scan keys are marked required by preprocessing, + * if necessary by generating a preceding skip array. We nevertheless + * often handle array keys marked required as if they were nonrequired. + * This behavior is requested by our _bt_check_compare caller, though only + * when it is passed "forcenonrequired=true" by _bt_checkkeys. */ if ((sktrig_required && all_required_satisfied) || (!sktrig_required && all_satisfied)) @@ -2145,9 +1825,9 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, Assert(all_required_satisfied); /* Recheck _bt_check_compare on behalf of caller */ - if (_bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, - false, false, false, - &continuescan, &nsktrig) && + if (_bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, false, + !sktrig_required, &continuescan, + &nsktrig) && !so->scanBehind) { /* This tuple satisfies the new qual */ @@ -2228,10 +1908,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * Note: we don't just quit at this point when all required scan keys were * found to be satisfied because we need to consider edge-cases involving * scan keys required in the opposite direction only; those aren't tracked - * by all_required_satisfied. (Actually, oppodir_inequality_sktrig trigger - * scan keys are tracked by all_required_satisfied, since it's convenient - * for _bt_check_compare to behave as if they are required in the current - * scan direction to deal with NULLs. We'll account for that separately.) + * by all_required_satisfied. */ Assert(_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, tupnatts, false, 0, NULL) == @@ -2265,7 +1942,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, /* * When we encounter a truncated finaltup high key attribute, we're * optimistic about the chances of its corresponding required scan key - * being satisfied when we go on to check it against tuples from this + * being satisfied when we go on to recheck it against tuples from this * page's right sibling leaf page. We consider truncated attributes to be * satisfied by required scan keys, which allows the primitive index scan * to continue to the next leaf page. We must set so->scanBehind to true @@ -2273,7 +1950,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * keys for one or more truncated attribute values (scan keys required in * _either_ scan direction). * - * There is a chance that _bt_checkkeys (which checks so->scanBehind) will + * There is a chance that _bt_readpage (which checks so->scanBehind) will * find that even the sibling leaf page's finaltup is < the new array * keys. When that happens, our optimistic policy will have incurred a * single extra leaf page access that could have been avoided. @@ -2285,27 +1962,12 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * Being pessimistic would also give some scans with non-required arrays a * perverse advantage over similar scans that use required arrays instead. * - * You can think of this as a speculative bet on what the scan is likely - * to find on the next page. It's not much of a gamble, though, since the - * untruncated prefix of attributes must strictly satisfy the new qual - * (though it's okay if any non-required scan keys fail to be satisfied). + * This is similar to our scan-level heuristics, below. They also set + * scanBehind to speculatively continue the primscan onto the next page. */ - if (so->scanBehind && has_required_opposite_direction_only) + if (so->scanBehind) { - /* - * However, we avoid this behavior whenever the scan involves a scan - * key required in the opposite direction to the scan only, along with - * a finaltup with at least one truncated attribute that's associated - * with a scan key marked required (required in either direction). - * - * _bt_check_compare simply won't stop the scan for a scan key that's - * marked required in the opposite scan direction only. That leaves - * us without any reliable way of reconsidering any opposite-direction - * inequalities if it turns out that starting a new primitive index - * scan will allow _bt_first to skip ahead by a great many leaf pages - * (see next section for details of how that works). - */ - goto new_prim_scan; + /* Truncated high key -- _bt_scanbehind_checkkeys recheck scheduled */ } /* @@ -2330,69 +1992,32 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * (primitive) scan. If this happens at the start of a large group of * NULL values, then we shouldn't expect to be called again until after * the scan has already read indefinitely-many leaf pages full of tuples - * with NULL suffix values. We need a separate test for this case so that - * we don't miss our only opportunity to skip over such a group of pages. - * (_bt_first is expected to skip over the group of NULLs by applying a - * similar "deduce NOT NULL" rule, where it finishes its insertion scan - * key by consing up an explicit SK_SEARCHNOTNULL key.) + * with NULL suffix values. (_bt_first is expected to skip over the group + * of NULLs by applying a similar "deduce NOT NULL" rule of its own, which + * involves consing up an explicit SK_SEARCHNOTNULL key.) * - * Apply a test against finaltup to detect and recover from these problem: + * Apply a test against finaltup to detect and recover from the problem: * if even finaltup doesn't satisfy such an inequality, we just skip by * starting a new primitive index scan. When we skip, we know for sure * that all of the tuples on the current page following caller's tuple are * also before the _bt_first-wise start of tuples for our new qual. That * at least suggests many more skippable pages beyond the current page. + * (when so->scanBehind and so->oppositeDirCheck are set, this'll happen + * when we test the next page's finaltup/high key instead.) */ - if (has_required_opposite_direction_only && pstate->finaltup && - (all_required_satisfied || oppodir_inequality_sktrig)) + else if (has_required_opposite_direction_only && pstate->finaltup && + unlikely(!_bt_oppodir_checkkeys(scan, dir, pstate->finaltup))) { - int nfinaltupatts = BTreeTupleGetNAtts(pstate->finaltup, rel); - ScanDirection flipped; - bool continuescanflip; - int opsktrig; - /* - * We're checking finaltup (which is usually not caller's tuple), so - * cannot reuse work from caller's earlier _bt_check_compare call. - * - * Flip the scan direction when calling _bt_check_compare this time, - * so that it will set continuescanflip=false when it encounters an - * inequality required in the opposite scan direction. + * Make sure that any SAOP arrays that were not marked required by + * preprocessing are reset to their first element for this direction */ - Assert(!so->scanBehind); - opsktrig = 0; - flipped = -dir; - _bt_check_compare(scan, flipped, - pstate->finaltup, nfinaltupatts, tupdesc, - false, false, false, - &continuescanflip, &opsktrig); - - /* - * Only start a new primitive index scan when finaltup has a required - * unsatisfied inequality (unsatisfied in the opposite direction) - */ - Assert(all_required_satisfied != oppodir_inequality_sktrig); - if (unlikely(!continuescanflip && - so->keyData[opsktrig].sk_strategy != BTEqualStrategyNumber)) - { - /* - * It's possible for the same inequality to be unsatisfied by both - * caller's tuple (in scan's direction) and finaltup (in the - * opposite direction) due to _bt_check_compare's behavior with - * NULLs - */ - Assert(opsktrig >= sktrig); /* not opsktrig > sktrig due to NULLs */ - - /* - * Make sure that any non-required arrays are set to the first - * array element for the current scan direction - */ - _bt_rewind_nonrequired_arrays(scan, dir); - - goto new_prim_scan; - } + _bt_rewind_nonrequired_arrays(scan, dir); + goto new_prim_scan; } +continue_scan: + /* * Stick with the ongoing primitive index scan for now. * @@ -2413,9 +2038,21 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, if (so->scanBehind) { - /* Optimization: skip by setting "look ahead" mechanism's offnum */ - Assert(ScanDirectionIsForward(dir)); - pstate->skip = pstate->maxoff + 1; + /* + * Remember if recheck needs to call _bt_oppodir_checkkeys for next + * page's finaltup (see above comments about "Handle inequalities + * marked required in the opposite scan direction" for why). + */ + so->oppositeDirCheck = has_required_opposite_direction_only; + + _bt_rewind_nonrequired_arrays(scan, dir); + + /* + * skip by setting "look ahead" mechanism's offnum for forwards scans + * (backwards scans check scanBehind flag directly instead) + */ + if (ScanDirectionIsForward(dir)) + pstate->skip = pstate->maxoff + 1; } /* Caller's tuple doesn't match the new qual */ @@ -2423,17 +2060,64 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, new_prim_scan: + Assert(pstate->finaltup); /* not on rightmost/leftmost page */ + + /* + * Looks like another primitive index scan is required. But consider + * continuing the current primscan based on scan-level heuristics. + * + * Continue the ongoing primitive scan (and schedule a recheck for when + * the scan arrives on the next sibling leaf page) when it has already + * read at least one leaf page before the one we're reading now. This + * makes primscan scheduling more efficient when scanning subsets of an + * index with many distinct attribute values matching many array elements. + * It encourages fewer, larger primitive scans where that makes sense. + * This will in turn encourage _bt_readpage to apply the pstate.startikey + * optimization more often. + * + * Also continue the ongoing primitive index scan when it is still on the + * first page if there have been more than NSKIPADVANCES_THRESHOLD calls + * here that each advanced at least one of the scan's skip arrays + * (deliberately ignore advancements that only affected SAOP arrays here). + * A page that cycles through this many skip array elements is quite + * likely to neighbor similar pages, that we'll also need to read. + * + * Note: These heuristics aren't as aggressive as you might think. We're + * conservative about allowing a primitive scan to step from the first + * leaf page it reads to the page's sibling page (we only allow it on + * first pages whose finaltup strongly suggests that it'll work out, as + * well as first pages that have a large number of skip array advances). + * Clearing this first page finaltup hurdle is a strong signal in itself. + * + * Note: The NSKIPADVANCES_THRESHOLD heuristic exists only to avoid + * pathological cases. Specifically, cases where a skip scan should just + * behave like a traditional full index scan, but ends up "skipping" again + * and again, descending to the prior leaf page's direct sibling leaf page + * each time. This misbehavior would otherwise be possible during scans + * that never quite manage to "clear the first page finaltup hurdle". + */ + if (!pstate->firstpage || pstate->nskipadvances > NSKIPADVANCES_THRESHOLD) + { + /* Schedule a recheck once on the next (or previous) page */ + so->scanBehind = true; + + /* Continue the current primitive scan after all */ + goto continue_scan; + } + /* * End this primitive index scan, but schedule another. * - * Note: If the scan direction happens to change, this scheduled primitive - * index scan won't go ahead after all. + * Note: We make a soft assumption that the current scan direction will + * also be used within _bt_next, when it is asked to step off this page. + * It is up to _bt_next to cancel this scheduled primitive index scan + * whenever it steps to a page in the direction opposite currPos.dir. */ pstate->continuescan = false; /* Tell _bt_readpage we're done... */ so->needPrimScan = true; /* ...but call _bt_first again */ if (scan->parallel_scan) - _bt_parallel_primscan_schedule(scan, pstate->prev_scan_page); + _bt_parallel_primscan_schedule(scan, so->currPos.currPage); /* Caller's tuple doesn't match the new qual */ return false; @@ -2451,542 +2135,12 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate, * first positions for what will then be the current scan direction. */ pstate->continuescan = false; /* Tell _bt_readpage we're done... */ - so->needPrimScan = false; /* ...don't call _bt_first again, though */ + so->needPrimScan = false; /* ...and don't call _bt_first again */ /* Caller's tuple doesn't match any qual */ return false; } -/* - * _bt_preprocess_keys() -- Preprocess scan keys - * - * The given search-type keys (taken from scan->keyData[]) - * are copied to so->keyData[] with possible transformation. - * scan->numberOfKeys is the number of input keys, so->numberOfKeys gets - * the number of output keys (possibly less, never greater). - * - * The output keys are marked with additional sk_flags bits beyond the - * system-standard bits supplied by the caller. The DESC and NULLS_FIRST - * indoption bits for the relevant index attribute are copied into the flags. - * Also, for a DESC column, we commute (flip) all the sk_strategy numbers - * so that the index sorts in the desired direction. - * - * One key purpose of this routine is to discover which scan keys must be - * satisfied to continue the scan. It also attempts to eliminate redundant - * keys and detect contradictory keys. (If the index opfamily provides - * incomplete sets of cross-type operators, we may fail to detect redundant - * or contradictory keys, but we can survive that.) - * - * The output keys must be sorted by index attribute. Presently we expect - * (but verify) that the input keys are already so sorted --- this is done - * by match_clauses_to_index() in indxpath.c. Some reordering of the keys - * within each attribute may be done as a byproduct of the processing here. - * That process must leave array scan keys (within an attribute) in the same - * order as corresponding entries from the scan's BTArrayKeyInfo array info. - * - * The output keys are marked with flags SK_BT_REQFWD and/or SK_BT_REQBKWD - * if they must be satisfied in order to continue the scan forward or backward - * respectively. _bt_checkkeys uses these flags. For example, if the quals - * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple - * (1,2,7), but we must continue the scan in case there are tuples (1,3,z). - * But once we reach tuples like (1,4,z) we can stop scanning because no - * later tuples could match. This is reflected by marking the x and y keys, - * but not the z key, with SK_BT_REQFWD. In general, the keys for leading - * attributes with "=" keys are marked both SK_BT_REQFWD and SK_BT_REQBKWD. - * For the first attribute without an "=" key, any "<" and "<=" keys are - * marked SK_BT_REQFWD while any ">" and ">=" keys are marked SK_BT_REQBKWD. - * This can be seen to be correct by considering the above example. Note - * in particular that if there are no keys for a given attribute, the keys for - * subsequent attributes can never be required; for instance "WHERE y = 4" - * requires a full-index scan. - * - * If possible, redundant keys are eliminated: we keep only the tightest - * >/>= bound and the tightest />= or both - * 4::int AND x > 10::bigint", and we are unable to determine - * which key is more restrictive for lack of a suitable cross-type operator. - * _bt_first will arbitrarily pick one of the keys to do the initial - * positioning with. If it picks x > 4, then the x > 10 condition will fail - * until we reach index entries > 10; but we can't stop the scan just because - * x > 10 is failing. On the other hand, if we are scanning backwards, then - * failure of either key is indeed enough to stop the scan. (In general, when - * inequality keys are present, the initial-positioning code only promises to - * position before the first possible match, not exactly at the first match, - * for a forward scan; or after the last match for a backward scan.) - * - * As a byproduct of this work, we can detect contradictory quals such - * as "x = 1 AND x > 2". If we see that, we return so->qual_ok = false, - * indicating the scan need not be run at all since no tuples can match. - * (In this case we do not bother completing the output key array!) - * Again, missing cross-type operators might cause us to fail to prove the - * quals contradictory when they really are, but the scan will work correctly. - * - * Row comparison keys are currently also treated without any smarts: - * we just transfer them into the preprocessed array without any - * editorialization. We can treat them the same as an ordinary inequality - * comparison on the row's first index column, for the purposes of the logic - * about required keys. - * - * Note: the reason we have to copy the preprocessed scan keys into private - * storage is that we are modifying the array based on comparisons of the - * key argument values, which could change on a rescan. Therefore we can't - * overwrite the source data. - */ -void -_bt_preprocess_keys(IndexScanDesc scan) -{ - BTScanOpaque so = (BTScanOpaque) scan->opaque; - int numberOfKeys = scan->numberOfKeys; - int16 *indoption = scan->indexRelation->rd_indoption; - int new_numberOfKeys; - int numberOfEqualCols; - ScanKey inkeys; - ScanKey outkeys; - ScanKey cur; - BTScanKeyPreproc xform[BTMaxStrategyNumber]; - bool test_result; - int i, - j; - AttrNumber attno; - ScanKey arrayKeyData; - int *keyDataMap = NULL; - int arrayidx = 0; - - if (so->numberOfKeys > 0) - { - /* - * Only need to do preprocessing once per btrescan, at most. All - * calls after the first are handled as no-ops. - * - * If there are array scan keys in so->keyData[], then the now-current - * array elements must already be present in each array's scan key. - * Verify that that happened using an assertion. - */ - Assert(_bt_verify_keys_with_arraykeys(scan)); - return; - } - - /* initialize result variables */ - so->qual_ok = true; - so->numberOfKeys = 0; - - if (numberOfKeys < 1) - return; /* done if qual-less scan */ - - /* If any keys are SK_SEARCHARRAY type, set up array-key info */ - arrayKeyData = _bt_preprocess_array_keys(scan); - if (!so->qual_ok) - { - /* unmatchable array, so give up */ - return; - } - - /* - * Treat arrayKeyData[] (a partially preprocessed copy of scan->keyData[]) - * as our input if _bt_preprocess_array_keys just allocated it, else just - * use scan->keyData[] - */ - if (arrayKeyData) - { - inkeys = arrayKeyData; - - /* Also maintain keyDataMap for remapping so->orderProc[] later */ - keyDataMap = MemoryContextAlloc(so->arrayContext, - numberOfKeys * sizeof(int)); - } - else - inkeys = scan->keyData; - - outkeys = so->keyData; - cur = &inkeys[0]; - /* we check that input keys are correctly ordered */ - if (cur->sk_attno < 1) - elog(ERROR, "btree index keys must be ordered by attribute"); - - /* We can short-circuit most of the work if there's just one key */ - if (numberOfKeys == 1) - { - /* Apply indoption to scankey (might change sk_strategy!) */ - if (!_bt_fix_scankey_strategy(cur, indoption)) - so->qual_ok = false; - memcpy(outkeys, cur, sizeof(ScanKeyData)); - so->numberOfKeys = 1; - /* We can mark the qual as required if it's for first index col */ - if (cur->sk_attno == 1) - _bt_mark_scankey_required(outkeys); - if (arrayKeyData) - { - /* - * Don't call _bt_preprocess_array_keys_final in this fast path - * (we'll miss out on the single value array transformation, but - * that's not nearly as important when there's only one scan key) - */ - Assert(cur->sk_flags & SK_SEARCHARRAY); - Assert(cur->sk_strategy != BTEqualStrategyNumber || - (so->arrayKeys[0].scan_key == 0 && - OidIsValid(so->orderProcs[0].fn_oid))); - } - - return; - } - - /* - * Otherwise, do the full set of pushups. - */ - new_numberOfKeys = 0; - numberOfEqualCols = 0; - - /* - * Initialize for processing of keys for attr 1. - * - * xform[i] points to the currently best scan key of strategy type i+1; it - * is NULL if we haven't yet found such a key for this attr. - */ - attno = 1; - memset(xform, 0, sizeof(xform)); - - /* - * Loop iterates from 0 to numberOfKeys inclusive; we use the last pass to - * handle after-last-key processing. Actual exit from the loop is at the - * "break" statement below. - */ - for (i = 0;; cur++, i++) - { - if (i < numberOfKeys) - { - /* Apply indoption to scankey (might change sk_strategy!) */ - if (!_bt_fix_scankey_strategy(cur, indoption)) - { - /* NULL can't be matched, so give up */ - so->qual_ok = false; - return; - } - } - - /* - * If we are at the end of the keys for a particular attr, finish up - * processing and emit the cleaned-up keys. - */ - if (i == numberOfKeys || cur->sk_attno != attno) - { - int priorNumberOfEqualCols = numberOfEqualCols; - - /* check input keys are correctly ordered */ - if (i < numberOfKeys && cur->sk_attno < attno) - elog(ERROR, "btree index keys must be ordered by attribute"); - - /* - * If = has been specified, all other keys can be eliminated as - * redundant. If we have a case like key = 1 AND key > 2, we can - * set qual_ok to false and abandon further processing. - * - * We also have to deal with the case of "key IS NULL", which is - * unsatisfiable in combination with any other index condition. By - * the time we get here, that's been classified as an equality - * check, and we've rejected any combination of it with a regular - * equality condition; but not with other types of conditions. - */ - if (xform[BTEqualStrategyNumber - 1].skey) - { - ScanKey eq = xform[BTEqualStrategyNumber - 1].skey; - BTArrayKeyInfo *array = NULL; - FmgrInfo *orderproc = NULL; - - if (arrayKeyData && (eq->sk_flags & SK_SEARCHARRAY)) - { - int eq_in_ikey, - eq_arrayidx; - - eq_in_ikey = xform[BTEqualStrategyNumber - 1].ikey; - eq_arrayidx = xform[BTEqualStrategyNumber - 1].arrayidx; - array = &so->arrayKeys[eq_arrayidx - 1]; - orderproc = so->orderProcs + eq_in_ikey; - - Assert(array->scan_key == eq_in_ikey); - Assert(OidIsValid(orderproc->fn_oid)); - } - - for (j = BTMaxStrategyNumber; --j >= 0;) - { - ScanKey chk = xform[j].skey; - - if (!chk || j == (BTEqualStrategyNumber - 1)) - continue; - - if (eq->sk_flags & SK_SEARCHNULL) - { - /* IS NULL is contradictory to anything else */ - so->qual_ok = false; - return; - } - - if (_bt_compare_scankey_args(scan, chk, eq, chk, - array, orderproc, - &test_result)) - { - if (!test_result) - { - /* keys proven mutually contradictory */ - so->qual_ok = false; - return; - } - /* else discard the redundant non-equality key */ - Assert(!array || array->num_elems > 0); - xform[j].skey = NULL; - xform[j].ikey = -1; - } - /* else, cannot determine redundancy, keep both keys */ - } - /* track number of attrs for which we have "=" keys */ - numberOfEqualCols++; - } - - /* try to keep only one of <, <= */ - if (xform[BTLessStrategyNumber - 1].skey - && xform[BTLessEqualStrategyNumber - 1].skey) - { - ScanKey lt = xform[BTLessStrategyNumber - 1].skey; - ScanKey le = xform[BTLessEqualStrategyNumber - 1].skey; - - if (_bt_compare_scankey_args(scan, le, lt, le, NULL, NULL, - &test_result)) - { - if (test_result) - xform[BTLessEqualStrategyNumber - 1].skey = NULL; - else - xform[BTLessStrategyNumber - 1].skey = NULL; - } - } - - /* try to keep only one of >, >= */ - if (xform[BTGreaterStrategyNumber - 1].skey - && xform[BTGreaterEqualStrategyNumber - 1].skey) - { - ScanKey gt = xform[BTGreaterStrategyNumber - 1].skey; - ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1].skey; - - if (_bt_compare_scankey_args(scan, ge, gt, ge, NULL, NULL, - &test_result)) - { - if (test_result) - xform[BTGreaterEqualStrategyNumber - 1].skey = NULL; - else - xform[BTGreaterStrategyNumber - 1].skey = NULL; - } - } - - /* - * Emit the cleaned-up keys into the outkeys[] array, and then - * mark them if they are required. They are required (possibly - * only in one direction) if all attrs before this one had "=". - */ - for (j = BTMaxStrategyNumber; --j >= 0;) - { - if (xform[j].skey) - { - ScanKey outkey = &outkeys[new_numberOfKeys++]; - - memcpy(outkey, xform[j].skey, sizeof(ScanKeyData)); - if (arrayKeyData) - keyDataMap[new_numberOfKeys - 1] = xform[j].ikey; - if (priorNumberOfEqualCols == attno - 1) - _bt_mark_scankey_required(outkey); - } - } - - /* - * Exit loop here if done. - */ - if (i == numberOfKeys) - break; - - /* Re-initialize for new attno */ - attno = cur->sk_attno; - memset(xform, 0, sizeof(xform)); - } - - /* check strategy this key's operator corresponds to */ - j = cur->sk_strategy - 1; - - /* if row comparison, push it directly to the output array */ - if (cur->sk_flags & SK_ROW_HEADER) - { - ScanKey outkey = &outkeys[new_numberOfKeys++]; - - memcpy(outkey, cur, sizeof(ScanKeyData)); - if (arrayKeyData) - keyDataMap[new_numberOfKeys - 1] = i; - if (numberOfEqualCols == attno - 1) - _bt_mark_scankey_required(outkey); - - /* - * We don't support RowCompare using equality; such a qual would - * mess up the numberOfEqualCols tracking. - */ - Assert(j != (BTEqualStrategyNumber - 1)); - continue; - } - - /* - * Does this input scan key require further processing as an array? - */ - if (cur->sk_strategy == InvalidStrategy) - { - /* _bt_preprocess_array_keys marked this array key redundant */ - Assert(arrayKeyData); - Assert(cur->sk_flags & SK_SEARCHARRAY); - continue; - } - - if (cur->sk_strategy == BTEqualStrategyNumber && - (cur->sk_flags & SK_SEARCHARRAY)) - { - /* _bt_preprocess_array_keys kept this array key */ - Assert(arrayKeyData); - arrayidx++; - } - - /* - * have we seen a scan key for this same attribute and using this same - * operator strategy before now? - */ - if (xform[j].skey == NULL) - { - /* nope, so this scan key wins by default (at least for now) */ - xform[j].skey = cur; - xform[j].ikey = i; - xform[j].arrayidx = arrayidx; - } - else - { - FmgrInfo *orderproc = NULL; - BTArrayKeyInfo *array = NULL; - - /* - * Seen one of these before, so keep only the more restrictive key - * if possible - */ - if (j == (BTEqualStrategyNumber - 1) && arrayKeyData) - { - /* - * Have to set up array keys - */ - if ((cur->sk_flags & SK_SEARCHARRAY)) - { - array = &so->arrayKeys[arrayidx - 1]; - orderproc = so->orderProcs + i; - - Assert(array->scan_key == i); - Assert(OidIsValid(orderproc->fn_oid)); - } - else if ((xform[j].skey->sk_flags & SK_SEARCHARRAY)) - { - array = &so->arrayKeys[xform[j].arrayidx - 1]; - orderproc = so->orderProcs + xform[j].ikey; - - Assert(array->scan_key == xform[j].ikey); - Assert(OidIsValid(orderproc->fn_oid)); - } - - /* - * Both scan keys might have arrays, in which case we'll - * arbitrarily pass only one of the arrays. That won't - * matter, since _bt_compare_scankey_args is aware that two - * SEARCHARRAY scan keys mean that _bt_preprocess_array_keys - * failed to eliminate redundant arrays through array merging. - * _bt_compare_scankey_args just returns false when it sees - * this; it won't even try to examine either array. - */ - } - - if (_bt_compare_scankey_args(scan, cur, cur, xform[j].skey, - array, orderproc, &test_result)) - { - /* Have all we need to determine redundancy */ - if (test_result) - { - Assert(!array || array->num_elems > 0); - - /* - * New key is more restrictive, and so replaces old key... - */ - if (j != (BTEqualStrategyNumber - 1) || - !(xform[j].skey->sk_flags & SK_SEARCHARRAY)) - { - xform[j].skey = cur; - xform[j].ikey = i; - xform[j].arrayidx = arrayidx; - } - else - { - /* - * ...unless we have to keep the old key because it's - * an array that rendered the new key redundant. We - * need to make sure that we don't throw away an array - * scan key. _bt_compare_scankey_args expects us to - * always keep arrays (and discard non-arrays). - */ - Assert(!(cur->sk_flags & SK_SEARCHARRAY)); - } - } - else if (j == (BTEqualStrategyNumber - 1)) - { - /* key == a && key == b, but a != b */ - so->qual_ok = false; - return; - } - /* else old key is more restrictive, keep it */ - } - else - { - /* - * We can't determine which key is more restrictive. Push - * xform[j] directly to the output array, then set xform[j] to - * the new scan key. - * - * Note: We do things this way around so that our arrays are - * always in the same order as their corresponding scan keys, - * even with incomplete opfamilies. _bt_advance_array_keys - * depends on this. - */ - ScanKey outkey = &outkeys[new_numberOfKeys++]; - - memcpy(outkey, xform[j].skey, sizeof(ScanKeyData)); - if (arrayKeyData) - keyDataMap[new_numberOfKeys - 1] = xform[j].ikey; - if (numberOfEqualCols == attno - 1) - _bt_mark_scankey_required(outkey); - xform[j].skey = cur; - xform[j].ikey = i; - xform[j].arrayidx = arrayidx; - } - } - } - - so->numberOfKeys = new_numberOfKeys; - - /* - * Now that we've built a temporary mapping from so->keyData[] (output - * scan keys) to scan->keyData[] (input scan keys), fix array->scan_key - * references. Also consolidate the so->orderProc[] array such that it - * can be subscripted using so->keyData[]-wise offsets. - */ - if (arrayKeyData) - _bt_preprocess_array_keys_final(scan, keyDataMap); - - /* Could pfree arrayKeyData/keyDataMap now, but not worth the cycles */ -} - #ifdef USE_ASSERT_CHECKING /* * Verify that the scan's qual state matches what we expect at the point that @@ -3039,433 +2193,41 @@ _bt_verify_keys_with_arraykeys(IndexScanDesc scan) { BTScanOpaque so = (BTScanOpaque) scan->opaque; int last_sk_attno = InvalidAttrNumber, - arrayidx = 0; - - if (!so->qual_ok) - return false; - - for (int ikey = 0; ikey < so->numberOfKeys; ikey++) - { - ScanKey cur = so->keyData + ikey; - BTArrayKeyInfo *array; - - if (cur->sk_strategy != BTEqualStrategyNumber || - !(cur->sk_flags & SK_SEARCHARRAY)) - continue; - - array = &so->arrayKeys[arrayidx++]; - if (array->scan_key != ikey) - return false; - - if (array->num_elems <= 0) - return false; - - if (cur->sk_argument != array->elem_values[array->cur_elem]) - return false; - if (last_sk_attno > cur->sk_attno) - return false; - last_sk_attno = cur->sk_attno; - } - - if (arrayidx != so->numArrayKeys) - return false; - - return true; -} -#endif - -/* - * Compare two scankey values using a specified operator. - * - * The test we want to perform is logically "leftarg op rightarg", where - * leftarg and rightarg are the sk_argument values in those ScanKeys, and - * the comparison operator is the one in the op ScanKey. However, in - * cross-data-type situations we may need to look up the correct operator in - * the index's opfamily: it is the one having amopstrategy = op->sk_strategy - * and amoplefttype/amoprighttype equal to the two argument datatypes. - * - * If the opfamily doesn't supply a complete set of cross-type operators we - * may not be able to make the comparison. If we can make the comparison - * we store the operator result in *result and return true. We return false - * if the comparison could not be made. - * - * If either leftarg or rightarg are an array, we'll apply array-specific - * rules to determine which array elements are redundant on behalf of caller. - * It is up to our caller to save whichever of the two scan keys is the array, - * and discard the non-array scan key (the non-array scan key is guaranteed to - * be redundant with any complete opfamily). Caller isn't expected to call - * here with a pair of array scan keys provided we're dealing with a complete - * opfamily (_bt_preprocess_array_keys will merge array keys together to make - * sure of that). - * - * Note: we'll also shrink caller's array as needed to eliminate redundant - * array elements. One reason why caller should prefer to discard non-array - * scan keys is so that we'll have the opportunity to shrink the array - * multiple times, in multiple calls (for each of several other scan keys on - * the same index attribute). - * - * Note: op always points at the same ScanKey as either leftarg or rightarg. - * Since we don't scribble on the scankeys themselves, this aliasing should - * cause no trouble. - * - * Note: this routine needs to be insensitive to any DESC option applied - * to the index column. For example, "x < 4" is a tighter constraint than - * "x < 5" regardless of which way the index is sorted. - */ -static bool -_bt_compare_scankey_args(IndexScanDesc scan, ScanKey op, - ScanKey leftarg, ScanKey rightarg, - BTArrayKeyInfo *array, FmgrInfo *orderproc, - bool *result) -{ - Relation rel = scan->indexRelation; - Oid lefttype, - righttype, - optype, - opcintype, - cmp_op; - StrategyNumber strat; - - /* - * First, deal with cases where one or both args are NULL. This should - * only happen when the scankeys represent IS NULL/NOT NULL conditions. - */ - if ((leftarg->sk_flags | rightarg->sk_flags) & SK_ISNULL) - { - bool leftnull, - rightnull; - - if (leftarg->sk_flags & SK_ISNULL) - { - Assert(leftarg->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)); - leftnull = true; - } - else - leftnull = false; - if (rightarg->sk_flags & SK_ISNULL) - { - Assert(rightarg->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)); - rightnull = true; - } - else - rightnull = false; - - /* - * We treat NULL as either greater than or less than all other values. - * Since true > false, the tests below work correctly for NULLS LAST - * logic. If the index is NULLS FIRST, we need to flip the strategy. - */ - strat = op->sk_strategy; - if (op->sk_flags & SK_BT_NULLS_FIRST) - strat = BTCommuteStrategyNumber(strat); - - switch (strat) - { - case BTLessStrategyNumber: - *result = (leftnull < rightnull); - break; - case BTLessEqualStrategyNumber: - *result = (leftnull <= rightnull); - break; - case BTEqualStrategyNumber: - *result = (leftnull == rightnull); - break; - case BTGreaterEqualStrategyNumber: - *result = (leftnull >= rightnull); - break; - case BTGreaterStrategyNumber: - *result = (leftnull > rightnull); - break; - default: - elog(ERROR, "unrecognized StrategyNumber: %d", (int) strat); - *result = false; /* keep compiler quiet */ - break; - } - return true; - } - - /* - * If either leftarg or rightarg are equality-type array scankeys, we need - * specialized handling (since by now we know that IS NULL wasn't used) - */ - if (array) - { - bool leftarray, - rightarray; - - leftarray = ((leftarg->sk_flags & SK_SEARCHARRAY) && - leftarg->sk_strategy == BTEqualStrategyNumber); - rightarray = ((rightarg->sk_flags & SK_SEARCHARRAY) && - rightarg->sk_strategy == BTEqualStrategyNumber); - - /* - * _bt_preprocess_array_keys is responsible for merging together array - * scan keys, and will do so whenever the opfamily has the required - * cross-type support. If it failed to do that, we handle it just - * like the case where we can't make the comparison ourselves. - */ - if (leftarray && rightarray) - { - /* Can't make the comparison */ - *result = false; /* suppress compiler warnings */ - return false; - } - - /* - * Otherwise we need to determine if either one of leftarg or rightarg - * uses an array, then pass this through to a dedicated helper - * function. - */ - if (leftarray) - return _bt_compare_array_scankey_args(scan, leftarg, rightarg, - orderproc, array, result); - else if (rightarray) - return _bt_compare_array_scankey_args(scan, rightarg, leftarg, - orderproc, array, result); - - /* FALL THRU */ - } - - /* - * The opfamily we need to worry about is identified by the index column. - */ - Assert(leftarg->sk_attno == rightarg->sk_attno); - - opcintype = rel->rd_opcintype[leftarg->sk_attno - 1]; - - /* - * Determine the actual datatypes of the ScanKey arguments. We have to - * support the convention that sk_subtype == InvalidOid means the opclass - * input type; this is a hack to simplify life for ScanKeyInit(). - */ - lefttype = leftarg->sk_subtype; - if (lefttype == InvalidOid) - lefttype = opcintype; - righttype = rightarg->sk_subtype; - if (righttype == InvalidOid) - righttype = opcintype; - optype = op->sk_subtype; - if (optype == InvalidOid) - optype = opcintype; - - /* - * If leftarg and rightarg match the types expected for the "op" scankey, - * we can use its already-looked-up comparison function. - */ - if (lefttype == opcintype && righttype == optype) - { - *result = DatumGetBool(FunctionCall2Coll(&op->sk_func, - op->sk_collation, - leftarg->sk_argument, - rightarg->sk_argument)); - return true; - } - - /* - * Otherwise, we need to go to the syscache to find the appropriate - * operator. (This cannot result in infinite recursion, since no - * indexscan initiated by syscache lookup will use cross-data-type - * operators.) - * - * If the sk_strategy was flipped by _bt_fix_scankey_strategy, we have to - * un-flip it to get the correct opfamily member. - */ - strat = op->sk_strategy; - if (op->sk_flags & SK_BT_DESC) - strat = BTCommuteStrategyNumber(strat); - - cmp_op = get_opfamily_member(rel->rd_opfamily[leftarg->sk_attno - 1], - lefttype, - righttype, - strat); - if (OidIsValid(cmp_op)) - { - RegProcedure cmp_proc = get_opcode(cmp_op); - - if (RegProcedureIsValid(cmp_proc)) - { - *result = DatumGetBool(OidFunctionCall2Coll(cmp_proc, - op->sk_collation, - leftarg->sk_argument, - rightarg->sk_argument)); - return true; - } - } - - /* Can't make the comparison */ - *result = false; /* suppress compiler warnings */ - return false; -} - -/* - * Adjust a scankey's strategy and flags setting as needed for indoptions. - * - * We copy the appropriate indoption value into the scankey sk_flags - * (shifting to avoid clobbering system-defined flag bits). Also, if - * the DESC option is set, commute (flip) the operator strategy number. - * - * A secondary purpose is to check for IS NULL/NOT NULL scankeys and set up - * the strategy field correctly for them. - * - * Lastly, for ordinary scankeys (not IS NULL/NOT NULL), we check for a - * NULL comparison value. Since all btree operators are assumed strict, - * a NULL means that the qual cannot be satisfied. We return true if the - * comparison value isn't NULL, or false if the scan should be abandoned. - * - * This function is applied to the *input* scankey structure; therefore - * on a rescan we will be looking at already-processed scankeys. Hence - * we have to be careful not to re-commute the strategy if we already did it. - * It's a bit ugly to modify the caller's copy of the scankey but in practice - * there shouldn't be any problem, since the index's indoptions are certainly - * not going to change while the scankey survives. - */ -static bool -_bt_fix_scankey_strategy(ScanKey skey, int16 *indoption) -{ - int addflags; - - addflags = indoption[skey->sk_attno - 1] << SK_BT_INDOPTION_SHIFT; - - /* - * We treat all btree operators as strict (even if they're not so marked - * in pg_proc). This means that it is impossible for an operator condition - * with a NULL comparison constant to succeed, and we can reject it right - * away. - * - * However, we now also support "x IS NULL" clauses as search conditions, - * so in that case keep going. The planner has not filled in any - * particular strategy in this case, so set it to BTEqualStrategyNumber - * --- we can treat IS NULL as an equality operator for purposes of search - * strategy. - * - * Likewise, "x IS NOT NULL" is supported. We treat that as either "less - * than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS - * FIRST index. - * - * Note: someday we might have to fill in sk_collation from the index - * column's collation. At the moment this is a non-issue because we'll - * never actually call the comparison operator on a NULL. - */ - if (skey->sk_flags & SK_ISNULL) - { - /* SK_ISNULL shouldn't be set in a row header scankey */ - Assert(!(skey->sk_flags & SK_ROW_HEADER)); - - /* Set indoption flags in scankey (might be done already) */ - skey->sk_flags |= addflags; - - /* Set correct strategy for IS NULL or NOT NULL search */ - if (skey->sk_flags & SK_SEARCHNULL) - { - skey->sk_strategy = BTEqualStrategyNumber; - skey->sk_subtype = InvalidOid; - skey->sk_collation = InvalidOid; - } - else if (skey->sk_flags & SK_SEARCHNOTNULL) - { - if (skey->sk_flags & SK_BT_NULLS_FIRST) - skey->sk_strategy = BTGreaterStrategyNumber; - else - skey->sk_strategy = BTLessStrategyNumber; - skey->sk_subtype = InvalidOid; - skey->sk_collation = InvalidOid; - } - else - { - /* regular qual, so it cannot be satisfied */ - return false; - } - - /* Needn't do the rest */ - return true; - } - - if (skey->sk_strategy == InvalidStrategy) - { - /* Already-eliminated array scan key; don't need to fix anything */ - Assert(skey->sk_flags & SK_SEARCHARRAY); - return true; - } - - /* Adjust strategy for DESC, if we didn't already */ - if ((addflags & SK_BT_DESC) && !(skey->sk_flags & SK_BT_DESC)) - skey->sk_strategy = BTCommuteStrategyNumber(skey->sk_strategy); - skey->sk_flags |= addflags; - - /* If it's a row header, fix row member flags and strategies similarly */ - if (skey->sk_flags & SK_ROW_HEADER) - { - ScanKey subkey = (ScanKey) DatumGetPointer(skey->sk_argument); - - for (;;) - { - Assert(subkey->sk_flags & SK_ROW_MEMBER); - addflags = indoption[subkey->sk_attno - 1] << SK_BT_INDOPTION_SHIFT; - if ((addflags & SK_BT_DESC) && !(subkey->sk_flags & SK_BT_DESC)) - subkey->sk_strategy = BTCommuteStrategyNumber(subkey->sk_strategy); - subkey->sk_flags |= addflags; - if (subkey->sk_flags & SK_ROW_END) - break; - subkey++; - } - } - - return true; -} - -/* - * Mark a scankey as "required to continue the scan". - * - * Depending on the operator type, the key may be required for both scan - * directions or just one. Also, if the key is a row comparison header, - * we have to mark its first subsidiary ScanKey as required. (Subsequent - * subsidiary ScanKeys are normally for lower-order columns, and thus - * cannot be required, since they're after the first non-equality scankey.) - * - * Note: when we set required-key flag bits in a subsidiary scankey, we are - * scribbling on a data structure belonging to the index AM's caller, not on - * our private copy. This should be OK because the marking will not change - * from scan to scan within a query, and so we'd just re-mark the same way - * anyway on a rescan. Something to keep an eye on though. - */ -static void -_bt_mark_scankey_required(ScanKey skey) -{ - int addflags; - - switch (skey->sk_strategy) - { - case BTLessStrategyNumber: - case BTLessEqualStrategyNumber: - addflags = SK_BT_REQFWD; - break; - case BTEqualStrategyNumber: - addflags = SK_BT_REQFWD | SK_BT_REQBKWD; - break; - case BTGreaterEqualStrategyNumber: - case BTGreaterStrategyNumber: - addflags = SK_BT_REQBKWD; - break; - default: - elog(ERROR, "unrecognized StrategyNumber: %d", - (int) skey->sk_strategy); - addflags = 0; /* keep compiler quiet */ - break; - } + arrayidx = 0; - skey->sk_flags |= addflags; + if (!so->qual_ok) + return false; - if (skey->sk_flags & SK_ROW_HEADER) + for (int ikey = 0; ikey < so->numberOfKeys; ikey++) { - ScanKey subkey = (ScanKey) DatumGetPointer(skey->sk_argument); + ScanKey cur = so->keyData + ikey; + BTArrayKeyInfo *array; - /* First subkey should be same column/operator as the header */ - Assert(subkey->sk_flags & SK_ROW_MEMBER); - Assert(subkey->sk_attno == skey->sk_attno); - Assert(subkey->sk_strategy == skey->sk_strategy); - subkey->sk_flags |= addflags; + if (cur->sk_strategy != BTEqualStrategyNumber || + !(cur->sk_flags & SK_SEARCHARRAY)) + continue; + + array = &so->arrayKeys[arrayidx++]; + if (array->scan_key != ikey) + return false; + + if (array->num_elems == 0 || array->num_elems < -1) + return false; + + if (array->num_elems != -1 && + cur->sk_argument != array->elem_values[array->cur_elem]) + return false; + if (last_sk_attno > cur->sk_attno) + return false; + last_sk_attno = cur->sk_attno; } + + if (arrayidx != so->numArrayKeys) + return false; + + return true; } +#endif /* * Test whether an indextuple satisfies all the scankey conditions. @@ -3473,24 +2235,21 @@ _bt_mark_scankey_required(ScanKey skey) * Return true if so, false if not. If the tuple fails to pass the qual, * we also determine whether there's any need to continue the scan beyond * this tuple, and set pstate.continuescan accordingly. See comments for - * _bt_preprocess_keys(), above, about how this is done. + * _bt_preprocess_keys() about how this is done. * * Forward scan callers can pass a high key tuple in the hopes of having * us set *continuescan to false, and avoiding an unnecessary visit to * the page to the right. * * Advances the scan's array keys when necessary for arrayKeys=true callers. - * Caller can avoid all array related side-effects when calling just to do a - * page continuescan precheck -- pass arrayKeys=false for that. Scans without - * any arrays keys must always pass arrayKeys=false. + * Scans without any array keys must always pass arrayKeys=false. * * Also stops and starts primitive index scans for arrayKeys=true callers. * Scans with array keys are required to set up page state that helps us with * this. The page's finaltup tuple (the page high key for a forward scan, or * the page's first non-pivot tuple for a backward scan) must be set in - * pstate.finaltup ahead of the first call here for the page (or possibly the - * first call after an initial continuescan-setting page precheck call). Set - * this to NULL for rightmost page (or the leftmost page for backwards scans). + * pstate.finaltup ahead of the first call here for the page. Set this to + * NULL for rightmost page (or the leftmost page for backwards scans). * * scan: index scan descriptor (containing a search-type scankey) * pstate: page level input and output parameters @@ -3504,41 +2263,47 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys, { TupleDesc tupdesc = RelationGetDescr(scan->indexRelation); BTScanOpaque so = (BTScanOpaque) scan->opaque; - ScanDirection dir = pstate->dir; - int ikey = 0; + ScanDirection dir = so->currPos.dir; + int ikey = pstate->startikey; bool res; Assert(BTreeTupleGetNAtts(tuple, scan->indexRelation) == tupnatts); + Assert(!so->needPrimScan && !so->scanBehind && !so->oppositeDirCheck); + Assert(arrayKeys || so->numArrayKeys == 0); - res = _bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, - arrayKeys, pstate->prechecked, pstate->firstmatch, - &pstate->continuescan, &ikey); + res = _bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, arrayKeys, + pstate->forcenonrequired, &pstate->continuescan, + &ikey); + /* + * If _bt_check_compare relied on the pstate.startikey optimization, call + * again (in assert-enabled builds) to verify it didn't affect our answer. + * + * Note: we can't do this when !pstate.forcenonrequired, since any arrays + * before pstate.startikey won't have advanced on this page at all. + */ + Assert(!pstate->forcenonrequired || arrayKeys); #ifdef USE_ASSERT_CHECKING - if (!arrayKeys && so->numArrayKeys) - { - /* - * This is a continuescan precheck call for a scan with array keys. - * - * Assert that the scan isn't in danger of becoming confused. - */ - Assert(!so->scanBehind && !pstate->prechecked && !pstate->firstmatch); - Assert(!_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, - tupnatts, false, 0, NULL)); - } - if (pstate->prechecked || pstate->firstmatch) + if (pstate->startikey > 0 && !pstate->forcenonrequired) { - bool dcontinuescan; + bool dres, + dcontinuescan; int dikey = 0; + /* Pass arrayKeys=false to avoid array side-effects */ + dres = _bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, false, + pstate->forcenonrequired, &dcontinuescan, + &dikey); + Assert(res == dres); + Assert(pstate->continuescan == dcontinuescan); + /* - * Call relied on continuescan/firstmatch prechecks -- assert that we - * get the same answer without those optimizations + * Should also get the same ikey result. We need a slightly weaker + * assertion during arrayKeys calls, since they might be using an + * array that couldn't be marked required during preprocessing. */ - Assert(res == _bt_check_compare(scan, dir, tuple, tupnatts, tupdesc, - false, false, false, - &dcontinuescan, &dikey)); - Assert(pstate->continuescan == dcontinuescan); + Assert(arrayKeys || ikey == dikey); + Assert(ikey <= dikey); } #endif @@ -3559,65 +2324,40 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys, * It's also possible that the scan is still _before_ the _start_ of * tuples matching the current set of array keys. Check for that first. */ + Assert(!pstate->forcenonrequired); if (_bt_tuple_before_array_skeys(scan, dir, tuple, tupdesc, tupnatts, true, ikey, NULL)) { + /* Override _bt_check_compare, continue primitive scan */ + pstate->continuescan = true; + /* - * Tuple is still before the start of matches according to the scan's - * required array keys (according to _all_ of its required equality - * strategy keys, actually). + * We will end up here repeatedly given a group of tuples > the + * previous array keys and < the now-current keys (for a backwards + * scan it's just the same, though the operators swap positions). * - * _bt_advance_array_keys occasionally sets so->scanBehind to signal - * that the scan's current position/tuples might be significantly - * behind (multiple pages behind) its current array keys. When this - * happens, we need to be prepared to recover by starting a new - * primitive index scan here, on our own. + * We must avoid allowing this linear search process to scan very many + * tuples from well before the start of tuples matching the current + * array keys (or from well before the point where we'll once again + * have to advance the scan's array keys). + * + * We keep the overhead under control by speculatively "looking ahead" + * to later still-unscanned items from this same leaf page. We'll + * only attempt this once the number of tuples that the linear search + * process has examined starts to get out of hand. */ - Assert(!so->scanBehind || - so->keyData[ikey].sk_strategy == BTEqualStrategyNumber); - if (unlikely(so->scanBehind) && pstate->finaltup && - _bt_tuple_before_array_skeys(scan, dir, pstate->finaltup, tupdesc, - BTreeTupleGetNAtts(pstate->finaltup, - scan->indexRelation), - false, 0, NULL)) - { - /* Cut our losses -- start a new primitive index scan now */ - pstate->continuescan = false; - so->needPrimScan = true; - } - else + pstate->rechecks++; + if (pstate->rechecks >= LOOK_AHEAD_REQUIRED_RECHECKS) { - /* Override _bt_check_compare, continue primitive scan */ - pstate->continuescan = true; + /* See if we should skip ahead within the current leaf page */ + _bt_checkkeys_look_ahead(scan, pstate, tupnatts, tupdesc); /* - * We will end up here repeatedly given a group of tuples > the - * previous array keys and < the now-current keys (for a backwards - * scan it's just the same, though the operators swap positions). - * - * We must avoid allowing this linear search process to scan very - * many tuples from well before the start of tuples matching the - * current array keys (or from well before the point where we'll - * once again have to advance the scan's array keys). - * - * We keep the overhead under control by speculatively "looking - * ahead" to later still-unscanned items from this same leaf page. - * We'll only attempt this once the number of tuples that the - * linear search process has examined starts to get out of hand. + * Might have set pstate.skip to a later page offset. When that + * happens then _bt_readpage caller will inexpensively skip ahead + * to a later tuple from the same page (the one just after the + * tuple we successfully "looked ahead" to). */ - pstate->rechecks++; - if (pstate->rechecks >= LOOK_AHEAD_REQUIRED_RECHECKS) - { - /* See if we should skip ahead within the current leaf page */ - _bt_checkkeys_look_ahead(scan, pstate, tupnatts, tupdesc); - - /* - * Might have set pstate.skip to a later page offset. When - * that happens then _bt_readpage caller will inexpensively - * skip ahead to a later tuple from the same page (the one - * just after the tuple we successfully "looked ahead" to). - */ - } } /* This indextuple doesn't match the current qual, in any case */ @@ -3634,6 +2374,415 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys, ikey, true); } +/* + * Test whether caller's finaltup tuple is still before the start of matches + * for the current array keys. + * + * Called at the start of reading a page during a scan with array keys, though + * only when the so->scanBehind flag was set on the scan's prior page. + * + * Returns false if the tuple is still before the start of matches. When that + * happens, caller should cut its losses and start a new primitive index scan. + * Otherwise returns true. + */ +bool +_bt_scanbehind_checkkeys(IndexScanDesc scan, ScanDirection dir, + IndexTuple finaltup) +{ + Relation rel = scan->indexRelation; + TupleDesc tupdesc = RelationGetDescr(rel); + BTScanOpaque so = (BTScanOpaque) scan->opaque; + int nfinaltupatts = BTreeTupleGetNAtts(finaltup, rel); + bool scanBehind; + + Assert(so->numArrayKeys); + + if (_bt_tuple_before_array_skeys(scan, dir, finaltup, tupdesc, + nfinaltupatts, false, 0, &scanBehind)) + return false; + + /* + * If scanBehind was set, all of the untruncated attribute values from + * finaltup that correspond to an array match the array's current element, + * but there are other keys associated with truncated suffix attributes. + * Array advancement must have incremented the scan's arrays on the + * previous page, resulting in a set of array keys that happen to be an + * exact match for the current page high key's untruncated prefix values. + * + * This page definitely doesn't contain tuples that the scan will need to + * return. The next page may or may not contain relevant tuples. Handle + * this by cutting our losses and starting a new primscan. + */ + if (scanBehind) + return false; + + if (!so->oppositeDirCheck) + return true; + + return _bt_oppodir_checkkeys(scan, dir, finaltup); +} + +/* + * Test whether an indextuple fails to satisfy an inequality required in the + * opposite direction only. + * + * Caller's finaltup tuple is the page high key (for forwards scans), or the + * first non-pivot tuple (for backwards scans). Called during scans with + * required array keys and required opposite-direction inequalities. + * + * Returns false if an inequality scan key required in the opposite direction + * only isn't satisfied (and any earlier required scan keys are satisfied). + * Otherwise returns true. + * + * An unsatisfied inequality required in the opposite direction only might + * well enable skipping over many leaf pages, provided another _bt_first call + * takes place. This type of unsatisfied inequality won't usually cause + * _bt_checkkeys to stop the scan to consider array advancement/starting a new + * primitive index scan. + */ +static bool +_bt_oppodir_checkkeys(IndexScanDesc scan, ScanDirection dir, + IndexTuple finaltup) +{ + Relation rel = scan->indexRelation; + TupleDesc tupdesc = RelationGetDescr(rel); + BTScanOpaque so = (BTScanOpaque) scan->opaque; + int nfinaltupatts = BTreeTupleGetNAtts(finaltup, rel); + bool continuescan; + ScanDirection flipped = -dir; + int ikey = 0; + + Assert(so->numArrayKeys); + + _bt_check_compare(scan, flipped, finaltup, nfinaltupatts, tupdesc, false, + false, &continuescan, + &ikey); + + if (!continuescan && so->keyData[ikey].sk_strategy != BTEqualStrategyNumber) + return false; + + return true; +} + +/* + * Determines an offset to the first scan key (an so->keyData[]-wise offset) + * that is _not_ guaranteed to be satisfied by every tuple from pstate.page, + * which is set in pstate.startikey for _bt_checkkeys calls for the page. + * This allows caller to save cycles on comparisons of a prefix of keys while + * reading pstate.page. + * + * Also determines if later calls to _bt_checkkeys (for pstate.page) should be + * forced to treat all required scan keys >= pstate.startikey as nonrequired + * (that is, if they're to be treated as if any SK_BT_REQFWD/SK_BT_REQBKWD + * markings that were set by preprocessing were not set at all, for the + * duration of _bt_checkkeys calls prior to the call for pstate.finaltup). + * This is indicated to caller by setting pstate.forcenonrequired. + * + * Call here at the start of reading a leaf page beyond the first one for the + * primitive index scan. We consider all non-pivot tuples, so it doesn't make + * sense to call here when only a subset of those tuples can ever be read. + * This is also a good idea on performance grounds; not calling here when on + * the first page (first for the current primitive scan) avoids wasting cycles + * during selective point queries. They typically don't stand to gain as much + * when we can set pstate.startikey, and are likely to notice the overhead of + * calling here. (Also, allowing pstate.forcenonrequired to be set on a + * primscan's first page would mislead _bt_advance_array_keys, which expects + * pstate.nskipadvances to be representative of every first page's key space.) + * + * Caller must call _bt_start_array_keys and reset startikey/forcenonrequired + * ahead of the finaltup _bt_checkkeys call when we set forcenonrequired=true. + * This will give _bt_checkkeys the opportunity to call _bt_advance_array_keys + * with sktrig_required=true, restoring the invariant that the scan's required + * arrays always track the scan's progress through the index's key space. + * Caller won't need to do this on the rightmost/leftmost page in the index + * (where pstate.finaltup isn't ever set), since forcenonrequired will never + * be set here in the first place. + */ +void +_bt_set_startikey(IndexScanDesc scan, BTReadPageState *pstate) +{ + BTScanOpaque so = (BTScanOpaque) scan->opaque; + Relation rel = scan->indexRelation; + TupleDesc tupdesc = RelationGetDescr(rel); + ItemId iid; + IndexTuple firsttup, + lasttup; + int startikey = 0, + arrayidx = 0, + firstchangingattnum; + bool start_past_saop_eq = false; + + Assert(!so->scanBehind); + Assert(pstate->minoff < pstate->maxoff); + Assert(!pstate->firstpage); + Assert(pstate->startikey == 0); + Assert(!so->numArrayKeys || pstate->finaltup || + P_RIGHTMOST(BTPageGetOpaque(pstate->page)) || + P_LEFTMOST(BTPageGetOpaque(pstate->page))); + + if (so->numberOfKeys == 0) + return; + + /* minoff is an offset to the lowest non-pivot tuple on the page */ + iid = PageGetItemId(pstate->page, pstate->minoff); + firsttup = (IndexTuple) PageGetItem(pstate->page, iid); + + /* maxoff is an offset to the highest non-pivot tuple on the page */ + iid = PageGetItemId(pstate->page, pstate->maxoff); + lasttup = (IndexTuple) PageGetItem(pstate->page, iid); + + /* Determine the first attribute whose values change on caller's page */ + firstchangingattnum = _bt_keep_natts_fast(rel, firsttup, lasttup); + + for (; startikey < so->numberOfKeys; startikey++) + { + ScanKey key = so->keyData + startikey; + BTArrayKeyInfo *array; + Datum firstdatum, + lastdatum; + bool firstnull, + lastnull; + int32 result; + + /* + * Determine if it's safe to set pstate.startikey to an offset to a + * key that comes after this key, by examining this key + */ + if (!(key->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD))) + { + /* Scan key isn't marked required (corner case) */ + Assert(!(key->sk_flags & SK_ROW_HEADER)); + break; /* unsafe */ + } + if (key->sk_flags & SK_ROW_HEADER) + { + /* + * RowCompare inequality. + * + * Only the first subkey from a RowCompare can ever be marked + * required (that happens when the row header is marked required). + * There is no simple, general way for us to transitively deduce + * whether or not every tuple on the page satisfies a RowCompare + * key based only on firsttup and lasttup -- so we just give up. + */ + if (!start_past_saop_eq && !so->skipScan) + break; /* unsafe to go further */ + + /* + * We have to be even more careful with RowCompares that come + * after an array: we assume it's unsafe to even bypass the array. + * Calling _bt_start_array_keys to recover the scan's arrays + * following use of forcenonrequired mode isn't compatible with + * _bt_check_rowcompare's continuescan=false behavior with NULL + * row compare members. _bt_advance_array_keys must not make a + * decision on the basis of a key not being satisfied in the + * opposite-to-scan direction until the scan reaches a leaf page + * where the same key begins to be satisfied in scan direction. + * The _bt_first !used_all_subkeys behavior makes this limitation + * hard to work around some other way. + */ + return; /* completely unsafe to set pstate.startikey */ + } + if (key->sk_strategy != BTEqualStrategyNumber) + { + /* + * Scalar inequality key. + * + * It's definitely safe for _bt_checkkeys to avoid assessing this + * inequality when the page's first and last non-pivot tuples both + * satisfy the inequality (since the same must also be true of all + * the tuples in between these two). + * + * Unlike the "=" case, it doesn't matter if this attribute has + * more than one distinct value (though it _is_ necessary for any + * and all _prior_ attributes to contain no more than one distinct + * value amongst all of the tuples from pstate.page). + */ + if (key->sk_attno > firstchangingattnum) /* >, not >= */ + break; /* unsafe, preceding attr has multiple + * distinct values */ + + firstdatum = index_getattr(firsttup, key->sk_attno, tupdesc, &firstnull); + lastdatum = index_getattr(lasttup, key->sk_attno, tupdesc, &lastnull); + + if (key->sk_flags & SK_ISNULL) + { + /* IS NOT NULL key */ + Assert(key->sk_flags & SK_SEARCHNOTNULL); + + if (firstnull || lastnull) + break; /* unsafe */ + + /* Safe, IS NOT NULL key satisfied by every tuple */ + continue; + } + + /* Test firsttup */ + if (firstnull || + !DatumGetBool(FunctionCall2Coll(&key->sk_func, + key->sk_collation, firstdatum, + key->sk_argument))) + break; /* unsafe */ + + /* Test lasttup */ + if (lastnull || + !DatumGetBool(FunctionCall2Coll(&key->sk_func, + key->sk_collation, lastdatum, + key->sk_argument))) + break; /* unsafe */ + + /* Safe, scalar inequality satisfied by every tuple */ + continue; + } + + /* Some = key (could be a scalar = key, could be an array = key) */ + Assert(key->sk_strategy == BTEqualStrategyNumber); + + if (!(key->sk_flags & SK_SEARCHARRAY)) + { + /* + * Scalar = key (possibly an IS NULL key). + * + * It is unsafe to set pstate.startikey to an ikey beyond this + * key, unless the = key is satisfied by every possible tuple on + * the page (possible only when attribute has just one distinct + * value among all tuples on the page). + */ + if (key->sk_attno >= firstchangingattnum) + break; /* unsafe, multiple distinct attr values */ + + firstdatum = index_getattr(firsttup, key->sk_attno, tupdesc, + &firstnull); + if (key->sk_flags & SK_ISNULL) + { + /* IS NULL key */ + Assert(key->sk_flags & SK_SEARCHNULL); + + if (!firstnull) + break; /* unsafe */ + + /* Safe, IS NULL key satisfied by every tuple */ + continue; + } + if (firstnull || + !DatumGetBool(FunctionCall2Coll(&key->sk_func, + key->sk_collation, firstdatum, + key->sk_argument))) + break; /* unsafe */ + + /* Safe, scalar = key satisfied by every tuple */ + continue; + } + + /* = array key (could be a SAOP array, could be a skip array) */ + array = &so->arrayKeys[arrayidx++]; + Assert(array->scan_key == startikey); + if (array->num_elems != -1) + { + /* + * SAOP array = key. + * + * Handle this like we handle scalar = keys (though binary search + * for a matching element, to avoid relying on key's sk_argument). + */ + if (key->sk_attno >= firstchangingattnum) + break; /* unsafe, multiple distinct attr values */ + + firstdatum = index_getattr(firsttup, key->sk_attno, tupdesc, + &firstnull); + _bt_binsrch_array_skey(&so->orderProcs[startikey], + false, NoMovementScanDirection, + firstdatum, firstnull, array, key, + &result); + if (result != 0) + break; /* unsafe */ + + /* Safe, SAOP = key satisfied by every tuple */ + start_past_saop_eq = true; + continue; + } + + /* + * Skip array = key + */ + Assert(key->sk_flags & SK_BT_SKIP); + if (array->null_elem) + { + /* + * Non-range skip array = key. + * + * Safe, non-range skip array "satisfied" by every tuple on page + * (safe even when "key->sk_attno > firstchangingattnum"). + */ + continue; + } + + /* + * Range skip array = key. + * + * Handle this like we handle scalar inequality keys (but avoid using + * key's sk_argument directly, as in the SAOP array case). + */ + if (key->sk_attno > firstchangingattnum) /* >, not >= */ + break; /* unsafe, preceding attr has multiple + * distinct values */ + + firstdatum = index_getattr(firsttup, key->sk_attno, tupdesc, &firstnull); + lastdatum = index_getattr(lasttup, key->sk_attno, tupdesc, &lastnull); + + /* Test firsttup */ + _bt_binsrch_skiparray_skey(false, ForwardScanDirection, + firstdatum, firstnull, array, key, + &result); + if (result != 0) + break; /* unsafe */ + + /* Test lasttup */ + _bt_binsrch_skiparray_skey(false, ForwardScanDirection, + lastdatum, lastnull, array, key, + &result); + if (result != 0) + break; /* unsafe */ + + /* Safe, range skip array satisfied by every tuple on page */ + } + + /* + * Use of forcenonrequired is typically undesirable, since it'll force + * _bt_readpage caller to read every tuple on the page -- even though, in + * general, it might well be possible to end the scan on an earlier tuple. + * However, caller must use forcenonrequired when start_past_saop_eq=true, + * since the usual required array behavior might fail to roll over to the + * SAOP array. + * + * We always prefer forcenonrequired=true during scans with skip arrays + * (except on the first page of each primitive index scan), though -- even + * when "startikey == 0". That way, _bt_advance_array_keys's low-order + * key precheck optimization can always be used (unless on the first page + * of the scan). It seems slightly preferable to check more tuples when + * that allows us to do significantly less skip array maintenance. + */ + pstate->forcenonrequired = (start_past_saop_eq || so->skipScan); + pstate->startikey = startikey; + + /* + * _bt_readpage caller is required to call _bt_checkkeys against page's + * finaltup with forcenonrequired=false whenever we initially set + * forcenonrequired=true. That way the scan's arrays will reliably track + * its progress through the index's key space. + * + * We don't expect this when _bt_readpage caller has no finaltup due to + * its page being the rightmost (or the leftmost, during backwards scans). + * When we see that _bt_readpage has no finaltup, back out of everything. + */ + Assert(!pstate->forcenonrequired || so->numArrayKeys); + if (pstate->forcenonrequired && !pstate->finaltup) + { + pstate->forcenonrequired = false; + pstate->startikey = 0; + } +} + /* * Test whether an indextuple satisfies current scan condition. * @@ -3663,19 +2812,27 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys, * by the current array key, or if they're truly unsatisfied (that is, if * they're unsatisfied by every possible array key). * - * Though we advance non-required array keys on our own, that shouldn't have - * any lasting consequences for the scan. By definition, non-required arrays - * have no fixed relationship with the scan's progress. (There are delicate - * considerations for non-required arrays when the arrays need to be advanced - * following our setting continuescan to false, but that doesn't concern us.) - * * Pass advancenonrequired=false to avoid all array related side effects. * This allows _bt_advance_array_keys caller to avoid infinite recursion. + * + * Pass forcenonrequired=true to instruct us to treat all keys as nonrequired. + * This is used to make it safe to temporarily stop properly maintaining the + * scan's required arrays. _bt_checkkeys caller (_bt_readpage, actually) + * determines a prefix of keys that must satisfy every possible corresponding + * index attribute value from its page, which is passed to us via *ikey arg + * (this is the first key that might be unsatisfied by tuples on the page). + * Obviously, we won't maintain any array keys from before *ikey, so it's + * quite possible for such arrays to "fall behind" the index's keyspace. + * Caller will need to "catch up" by passing forcenonrequired=true (alongside + * an *ikey=0) once the page's finaltup is reached. + * + * Note: it's safe to pass an *ikey > 0 with forcenonrequired=false, but only + * when caller determines that it won't affect array maintenance. */ static bool _bt_check_compare(IndexScanDesc scan, ScanDirection dir, IndexTuple tuple, int tupnatts, TupleDesc tupdesc, - bool advancenonrequired, bool prechecked, bool firstmatch, + bool advancenonrequired, bool forcenonrequired, bool *continuescan, int *ikey) { BTScanOpaque so = (BTScanOpaque) scan->opaque; @@ -3692,36 +2849,20 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, /* * Check if the key is required in the current scan direction, in the - * opposite scan direction _only_, or in neither direction + * opposite scan direction _only_, or in neither direction (except + * when we're forced to treat all scan keys as nonrequired) */ - if (((key->sk_flags & SK_BT_REQFWD) && ScanDirectionIsForward(dir)) || - ((key->sk_flags & SK_BT_REQBKWD) && ScanDirectionIsBackward(dir))) + if (forcenonrequired) + { + /* treating scan's keys as non-required */ + } + else if (((key->sk_flags & SK_BT_REQFWD) && ScanDirectionIsForward(dir)) || + ((key->sk_flags & SK_BT_REQBKWD) && ScanDirectionIsBackward(dir))) requiredSameDir = true; else if (((key->sk_flags & SK_BT_REQFWD) && ScanDirectionIsBackward(dir)) || ((key->sk_flags & SK_BT_REQBKWD) && ScanDirectionIsForward(dir))) requiredOppositeDirOnly = true; - /* - * If the caller told us the *continuescan flag is known to be true - * for the last item on the page, then we know the keys required for - * the current direction scan should be matched. Otherwise, the - * *continuescan flag would be set for the current item and - * subsequently the last item on the page accordingly. - * - * If the key is required for the opposite direction scan, we can skip - * the check if the caller tells us there was already at least one - * matching item on the page. Also, we require the *continuescan flag - * to be true for the last item on the page to know there are no - * NULLs. - * - * Both cases above work except for the row keys, where NULLs could be - * found in the middle of matching values. - */ - if (prechecked && - (requiredSameDir || (requiredOppositeDirOnly && firstmatch)) && - !(key->sk_flags & SK_ROW_HEADER)) - continue; - if (key->sk_attno > tupnatts) { /* @@ -3734,11 +2875,35 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, continue; } + /* + * A skip array scan key uses one of several sentinel values. We just + * fall back on _bt_tuple_before_array_skeys when we see such a value. + */ + if (key->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL | + SK_BT_NEXT | SK_BT_PRIOR)) + { + Assert(key->sk_flags & SK_SEARCHARRAY); + Assert(key->sk_flags & SK_BT_SKIP); + Assert(requiredSameDir || forcenonrequired); + + /* + * Cannot fall back on _bt_tuple_before_array_skeys when we're + * treating the scan's keys as nonrequired, though. Just handle + * this like any other non-required equality-type array key. + */ + if (forcenonrequired) + return _bt_advance_array_keys(scan, NULL, tuple, tupnatts, + tupdesc, *ikey, false); + + *continuescan = false; + return false; + } + /* row-comparison keys need special processing */ if (key->sk_flags & SK_ROW_HEADER) { if (_bt_check_rowcompare(key, tuple, tupnatts, tupdesc, dir, - continuescan)) + forcenonrequired, continuescan)) continue; return false; } @@ -3759,6 +2924,7 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, else { Assert(key->sk_flags & SK_SEARCHNOTNULL); + Assert(!(key->sk_flags & SK_BT_SKIP)); if (!isNull) continue; /* tuple satisfies this qual */ } @@ -3770,15 +2936,37 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, */ if (requiredSameDir) *continuescan = false; + else if (unlikely(key->sk_flags & SK_BT_SKIP)) + { + /* + * If we're treating scan keys as nonrequired, and encounter a + * skip array scan key whose current element is NULL, then it + * must be a non-range skip array. It must be satisfied, so + * there's no need to call _bt_advance_array_keys to check. + */ + Assert(forcenonrequired && *ikey > 0); + continue; + } /* - * In any case, this indextuple doesn't match the qual. + * This indextuple doesn't match the qual. */ return false; } if (isNull) { + /* + * Scalar scan key isn't satisfied by NULL tuple value. + * + * If we're treating scan keys as nonrequired, and key is for a + * skip array, then we must attempt to advance the array to NULL + * (if we're successful then the tuple might match the qual). + */ + if (unlikely(forcenonrequired && key->sk_flags & SK_BT_SKIP)) + return _bt_advance_array_keys(scan, NULL, tuple, tupnatts, + tupdesc, *ikey, false); + if (key->sk_flags & SK_BT_NULLS_FIRST) { /* @@ -3793,7 +2981,7 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, * (_bt_advance_array_keys also relies on this behavior during * forward scans.) */ - if ((key->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD)) && + if ((requiredSameDir || requiredOppositeDirOnly) && ScanDirectionIsBackward(dir)) *continuescan = false; } @@ -3811,26 +2999,18 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, * (_bt_advance_array_keys also relies on this behavior during * backward scans.) */ - if ((key->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD)) && + if ((requiredSameDir || requiredOppositeDirOnly) && ScanDirectionIsForward(dir)) *continuescan = false; } /* - * In any case, this indextuple doesn't match the qual. + * This indextuple doesn't match the qual. */ return false; } - /* - * Apply the key-checking function, though only if we must. - * - * When a key is required in the opposite-of-scan direction _only_, - * then it must already be satisfied if firstmatch=true indicates that - * an earlier tuple from this same page satisfied it earlier on. - */ - if (!(requiredOppositeDirOnly && firstmatch) && - !DatumGetBool(FunctionCall2Coll(&key->sk_func, key->sk_collation, + if (!DatumGetBool(FunctionCall2Coll(&key->sk_func, key->sk_collation, datum, key->sk_argument))) { /* @@ -3880,7 +3060,8 @@ _bt_check_compare(IndexScanDesc scan, ScanDirection dir, */ static bool _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, int tupnatts, - TupleDesc tupdesc, ScanDirection dir, bool *continuescan) + TupleDesc tupdesc, ScanDirection dir, + bool forcenonrequired, bool *continuescan) { ScanKey subkey = (ScanKey) DatumGetPointer(skey->sk_argument); int32 cmpresult = 0; @@ -3920,7 +3101,11 @@ _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, int tupnatts, if (isNull) { - if (subkey->sk_flags & SK_BT_NULLS_FIRST) + if (forcenonrequired) + { + /* treating scan's keys as non-required */ + } + else if (subkey->sk_flags & SK_BT_NULLS_FIRST) { /* * Since NULLs are sorted before non-NULLs, we know we have @@ -3966,15 +3151,20 @@ _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, int tupnatts, if (subkey->sk_flags & SK_ISNULL) { /* - * Unlike the simple-scankey case, this isn't a disallowed case. + * Unlike the simple-scankey case, this isn't a disallowed case + * (except when it's the first row element that has the NULL arg). * But it can never match. If all the earlier row comparison * columns are required for the scan direction, we can stop the * scan, because there can't be another tuple that will succeed. */ - if (subkey != (ScanKey) DatumGetPointer(skey->sk_argument)) - subkey--; - if ((subkey->sk_flags & SK_BT_REQFWD) && - ScanDirectionIsForward(dir)) + Assert(subkey != (ScanKey) DatumGetPointer(skey->sk_argument)); + subkey--; + if (forcenonrequired) + { + /* treating scan's keys as non-required */ + } + else if ((subkey->sk_flags & SK_BT_REQFWD) && + ScanDirectionIsForward(dir)) *continuescan = false; else if ((subkey->sk_flags & SK_BT_REQBKWD) && ScanDirectionIsBackward(dir)) @@ -4021,13 +3211,12 @@ _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, int tupnatts, result = (cmpresult > 0); break; default: - elog(ERROR, "unrecognized RowCompareType: %d", - (int) subkey->sk_strategy); + elog(ERROR, "unexpected strategy number %d", subkey->sk_strategy); result = 0; /* keep compiler quiet */ break; } - if (!result) + if (!result && !forcenonrequired) { /* * Tuple fails this qual. If it's a required qual for the current @@ -4066,10 +3255,13 @@ static void _bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate, int tupnatts, TupleDesc tupdesc) { - ScanDirection dir = pstate->dir; + BTScanOpaque so = (BTScanOpaque) scan->opaque; + ScanDirection dir = so->currPos.dir; OffsetNumber aheadoffnum; IndexTuple ahead; + Assert(!pstate->forcenonrequired); + /* Avoid looking ahead when comparing the page high key */ if (pstate->offnum < pstate->minoff) return; @@ -4091,7 +3283,7 @@ _bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate, */ if (!pstate->targetdistance) pstate->targetdistance = LOOK_AHEAD_DEFAULT_DISTANCE; - else + else if (pstate->targetdistance < MaxIndexTuplesPerPage / 2) pstate->targetdistance *= 2; /* Don't read past the end (or before the start) of the page, though */ @@ -4138,87 +3330,85 @@ _bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate, * current page and killed tuples thereon (generally, this should only be * called if so->numKilled > 0). * - * The caller does not have a lock on the page and may or may not have the - * page pinned in a buffer. Note that read-lock is sufficient for setting - * LP_DEAD status (which is only a hint). - * - * We match items by heap TID before assuming they are the right ones to - * delete. We cope with cases where items have moved right due to insertions. - * If an item has moved off the current page due to a split, we'll fail to - * find it and do nothing (this is not an error case --- we assume the item - * will eventually get marked in a future indexscan). + * Caller should not have a lock on the so->currPos page, but must hold a + * buffer pin when !so->dropPin. When we return, it still won't be locked. + * It'll continue to hold whatever pins were held before calling here. * - * Note that if we hold a pin on the target page continuously from initially - * reading the items until applying this function, VACUUM cannot have deleted - * any items from the page, and so there is no need to search left from the - * recorded offset. (This observation also guarantees that the item is still - * the right one to delete, which might otherwise be questionable since heap - * TIDs can get recycled.) This holds true even if the page has been modified - * by inserts and page splits, so there is no need to consult the LSN. + * We match items by heap TID before assuming they are the right ones to set + * LP_DEAD. If the scan is one that holds a buffer pin on the target page + * continuously from initially reading the items until applying this function + * (if it is a !so->dropPin scan), VACUUM cannot have deleted any items on the + * page, so the page's TIDs can't have been recycled by now. There's no risk + * that we'll confuse a new index tuple that happens to use a recycled TID + * with a now-removed tuple with the same TID (that used to be on this same + * page). We can't rely on that during scans that drop buffer pins eagerly + * (so->dropPin scans), though, so we must condition setting LP_DEAD bits on + * the page LSN having not changed since back when _bt_readpage saw the page. + * We totally give up on setting LP_DEAD bits when the page LSN changed. * - * If the pin was released after reading the page, then we re-read it. If it - * has been modified since we read it (as determined by the LSN), we dare not - * flag any entries because it is possible that the old entry was vacuumed - * away and the TID was re-used by a completely different heap tuple. + * We give up much less often during !so->dropPin scans, but it still happens. + * We cope with cases where items have moved right due to insertions. If an + * item has moved off the current page due to a split, we'll fail to find it + * and just give up on it. */ void _bt_killitems(IndexScanDesc scan) { + Relation rel = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; Page page; BTPageOpaque opaque; OffsetNumber minoff; OffsetNumber maxoff; - int i; int numKilled = so->numKilled; bool killedsomething = false; - bool droppedpin PG_USED_FOR_ASSERTS_ONLY; + Buffer buf; + Assert(numKilled > 0); Assert(BTScanPosIsValid(so->currPos)); + Assert(scan->heapRelation != NULL); /* can't be a bitmap index scan */ - /* - * Always reset the scan state, so we don't look for same items on other - * pages. - */ + /* Always invalidate so->killedItems[] before leaving so->currPos */ so->numKilled = 0; - if (BTScanPosIsPinned(so->currPos)) + if (!so->dropPin) { /* * We have held the pin on this page since we read the index tuples, * so all we need to do is lock it. The pin will have prevented - * re-use of any TID on the page, so there is no need to check the - * LSN. + * concurrent VACUUMs from recycling any of the TIDs on the page. */ - droppedpin = false; - _bt_lockbuf(scan->indexRelation, so->currPos.buf, BT_READ); - - page = BufferGetPage(so->currPos.buf); + Assert(BTScanPosIsPinned(so->currPos)); + buf = so->currPos.buf; + _bt_lockbuf(rel, buf, BT_READ); } else { - Buffer buf; + XLogRecPtr latestlsn; - droppedpin = true; - /* Attempt to re-read the buffer, getting pin and lock. */ - buf = _bt_getbuf(scan->indexRelation, so->currPos.currPage, BT_READ); + Assert(!BTScanPosIsPinned(so->currPos)); + Assert(RelationNeedsWAL(rel)); + buf = _bt_getbuf(rel, so->currPos.currPage, BT_READ); - page = BufferGetPage(buf); - if (BufferGetLSNAtomic(buf) == so->currPos.lsn) - so->currPos.buf = buf; - else + latestlsn = BufferGetLSNAtomic(buf); + Assert(!XLogRecPtrIsInvalid(so->currPos.lsn)); + Assert(so->currPos.lsn <= latestlsn); + if (so->currPos.lsn != latestlsn) { - /* Modified while not pinned means hinting is not safe. */ - _bt_relbuf(scan->indexRelation, buf); + /* Modified, give up on hinting */ + _bt_relbuf(rel, buf); return; } + + /* Unmodified, hinting is safe */ } + page = BufferGetPage(buf); opaque = BTPageGetOpaque(page); minoff = P_FIRSTDATAKEY(opaque); maxoff = PageGetMaxOffsetNumber(page); - for (i = 0; i < numKilled; i++) + for (int i = 0; i < numKilled; i++) { int itemIndex = so->killedItems[i]; BTScanPosItem *kitem = &so->currPos.items[itemIndex]; @@ -4250,7 +3440,7 @@ _bt_killitems(IndexScanDesc scan) * correctness. * * Note that the page may have been modified in almost any way - * since we first read it (in the !droppedpin case), so it's + * since we first read it (in the !so->dropPin case), so it's * possible that this posting list tuple wasn't a posting list * tuple when we first encountered its heap TIDs. */ @@ -4266,7 +3456,7 @@ _bt_killitems(IndexScanDesc scan) * though only in the common case where the page can't * have been concurrently modified */ - Assert(kitem->indexOffset == offnum || !droppedpin); + Assert(kitem->indexOffset == offnum || !so->dropPin); /* * Read-ahead to later kitems here. @@ -4330,10 +3520,13 @@ _bt_killitems(IndexScanDesc scan) if (killedsomething) { opaque->btpo_flags |= BTP_HAS_GARBAGE; - MarkBufferDirtyHint(so->currPos.buf, true); + MarkBufferDirtyHint(buf, true); } - _bt_unlockbuf(scan->indexRelation, so->currPos.buf); + if (!so->dropPin) + _bt_unlockbuf(rel, buf); + else + _bt_relbuf(rel, buf); } @@ -4874,11 +4067,11 @@ _bt_keep_natts_fast(Relation rel, IndexTuple lastleft, IndexTuple firstright) datum2; bool isNull1, isNull2; - Form_pg_attribute att; + CompactAttribute *att; datum1 = index_getattr(lastleft, attnum, itupdesc, &isNull1); datum2 = index_getattr(firstright, attnum, itupdesc, &isNull2); - att = TupleDescAttr(itupdesc, attnum - 1); + att = TupleDescCompactAttr(itupdesc, attnum - 1); if (isNull1 != isNull2) break; @@ -5077,7 +4270,7 @@ _bt_check_third_page(Relation rel, Relation heap, bool needheaptidspace, itemsz = MAXALIGN(IndexTupleSize(newtup)); /* Double check item size against limit */ - if (itemsz <= BTMaxItemSize(page)) + if (itemsz <= BTMaxItemSize) return; /* @@ -5085,7 +4278,7 @@ _bt_check_third_page(Relation rel, Relation heap, bool needheaptidspace, * index uses version 2 or version 3, or that page is an internal page, in * which case a slightly higher limit applies. */ - if (!needheaptidspace && itemsz <= BTMaxItemSizeNoHeapTid(page)) + if (!needheaptidspace && itemsz <= BTMaxItemSizeNoHeapTid) return; /* @@ -5102,8 +4295,7 @@ _bt_check_third_page(Relation rel, Relation heap, bool needheaptidspace, errmsg("index row size %zu exceeds btree version %u maximum %zu for index \"%s\"", itemsz, needheaptidspace ? BTREE_VERSION : BTREE_NOVAC_VERSION, - needheaptidspace ? BTMaxItemSize(page) : - BTMaxItemSizeNoHeapTid(page), + needheaptidspace ? BTMaxItemSize : BTMaxItemSizeNoHeapTid, RelationGetRelationName(rel)), errdetail("Index row references tuple (%u,%u) in relation \"%s\".", ItemPointerGetBlockNumber(BTreeTupleGetHeapTID(newtup)), diff --git a/src/backend/access/nbtree/nbtvalidate.c b/src/backend/access/nbtree/nbtvalidate.c index e9d4cd60de3c2..817ad358f0caa 100644 --- a/src/backend/access/nbtree/nbtvalidate.c +++ b/src/backend/access/nbtree/nbtvalidate.c @@ -3,7 +3,7 @@ * nbtvalidate.c * Opclass validator for btree. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -21,7 +21,6 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -46,8 +45,6 @@ btvalidate(Oid opclassoid) Oid opfamilyoid; Oid opcintype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -69,12 +66,7 @@ btvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -114,6 +106,10 @@ btvalidate(Oid opclassoid) case BTOPTIONS_PROC: ok = check_amoptsproc_signature(procform->amproc); break; + case BTSKIPSUPPORT_PROC: + ok = check_amproc_signature(procform->amproc, VOIDOID, true, + 1, 1, INTERNALOID); + break; default: ereport(INFO, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -280,7 +276,6 @@ btvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; diff --git a/src/backend/access/nbtree/nbtxlog.c b/src/backend/access/nbtree/nbtxlog.c index b5b0e22447e4b..d31dd56732d2f 100644 --- a/src/backend/access/nbtree/nbtxlog.c +++ b/src/backend/access/nbtree/nbtxlog.c @@ -4,7 +4,7 @@ * WAL replay logic for btrees. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -483,7 +483,7 @@ btree_xlog_dedup(XLogReaderState *record) state->deduplicate = true; /* unused */ state->nmaxitems = 0; /* unused */ /* Conservatively use larger maxpostingsize than primary */ - state->maxpostingsize = BTMaxItemSize(page); + state->maxpostingsize = BTMaxItemSize; state->base = NULL; state->baseoff = InvalidOffsetNumber; state->basetupsize = 0; @@ -634,10 +634,11 @@ btree_xlog_vacuum(XLogReaderState *record) PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted); /* - * Mark the page as not containing any LP_DEAD items --- see comments - * in _bt_delitems_vacuum(). + * Clear the vacuum cycle ID, and mark the page as not containing any + * LP_DEAD items */ opaque = BTPageGetOpaque(page); + opaque->btpo_cycleid = 0; opaque->btpo_flags &= ~BTP_HAS_GARBAGE; PageSetLSN(page, lsn); @@ -698,7 +699,10 @@ btree_xlog_delete(XLogReaderState *record) if (xlrec->ndeleted > 0) PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted); - /* Mark the page as not containing any LP_DEAD items */ + /* + * Do *not* clear the vacuum cycle ID, but do mark the page as not + * containing any LP_DEAD items + */ opaque = BTPageGetOpaque(page); opaque->btpo_flags &= ~BTP_HAS_GARBAGE; @@ -982,9 +986,9 @@ btree_xlog_newroot(XLogReaderState *record) * As far as any backend operating during original execution is concerned, the * FSM is a cache of recycle-safe pages; the mere presence of the page in the * FSM indicates that the page must already be safe to recycle (actually, - * _bt_getbuf() verifies it's safe using BTPageIsRecyclable(), but that's just - * because it would be unwise to completely trust the FSM, given its current - * limitations). + * _bt_allocbuf() verifies it's safe using BTPageIsRecyclable(), but that's + * just because it would be unwise to completely trust the FSM, given its + * current limitations). * * This isn't sufficient to prevent similar concurrent recycling race * conditions during Hot Standby, though. For that we need to log a diff --git a/src/backend/access/rmgrdesc/brindesc.c b/src/backend/access/rmgrdesc/brindesc.c index 3f55022a3e000..9fc0bfe2a523a 100644 --- a/src/backend/access/rmgrdesc/brindesc.c +++ b/src/backend/access/rmgrdesc/brindesc.c @@ -3,7 +3,7 @@ * brindesc.c * rmgr descriptor routines for BRIN indexes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/clogdesc.c b/src/backend/access/rmgrdesc/clogdesc.c index c1d47c219f9d2..41bf28dcfd05c 100644 --- a/src/backend/access/rmgrdesc/clogdesc.c +++ b/src/backend/access/rmgrdesc/clogdesc.c @@ -3,7 +3,7 @@ * clogdesc.c * rmgr descriptor routines for access/transam/clog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,15 +28,15 @@ clog_desc(StringInfo buf, XLogReaderState *record) int64 pageno; memcpy(&pageno, rec, sizeof(pageno)); - appendStringInfo(buf, "page %lld", (long long) pageno); + appendStringInfo(buf, "page %" PRId64, pageno); } else if (info == CLOG_TRUNCATE) { xl_clog_truncate xlrec; memcpy(&xlrec, rec, sizeof(xl_clog_truncate)); - appendStringInfo(buf, "page %lld; oldestXact %u", - (long long) xlrec.pageno, xlrec.oldestXact); + appendStringInfo(buf, "page %" PRId64 "; oldestXact %u", + xlrec.pageno, xlrec.oldestXact); } } diff --git a/src/backend/access/rmgrdesc/committsdesc.c b/src/backend/access/rmgrdesc/committsdesc.c index f5f09a1bc7968..a6ab9dd78de17 100644 --- a/src/backend/access/rmgrdesc/committsdesc.c +++ b/src/backend/access/rmgrdesc/committsdesc.c @@ -3,7 +3,7 @@ * committsdesc.c * rmgr descriptor routines for access/transam/commit_ts.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,14 +28,14 @@ commit_ts_desc(StringInfo buf, XLogReaderState *record) int64 pageno; memcpy(&pageno, rec, sizeof(pageno)); - appendStringInfo(buf, "%lld", (long long) pageno); + appendStringInfo(buf, "%" PRId64, pageno); } else if (info == COMMIT_TS_TRUNCATE) { xl_commit_ts_truncate *trunc = (xl_commit_ts_truncate *) rec; - appendStringInfo(buf, "pageno %lld, oldestXid %u", - (long long) trunc->pageno, trunc->oldestXid); + appendStringInfo(buf, "pageno %" PRId64 ", oldestXid %u", + trunc->pageno, trunc->oldestXid); } } diff --git a/src/backend/access/rmgrdesc/dbasedesc.c b/src/backend/access/rmgrdesc/dbasedesc.c index 731dac826cccd..4224c5673ff87 100644 --- a/src/backend/access/rmgrdesc/dbasedesc.c +++ b/src/backend/access/rmgrdesc/dbasedesc.c @@ -3,7 +3,7 @@ * dbasedesc.c * rmgr descriptor routines for commands/dbcommands.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/genericdesc.c b/src/backend/access/rmgrdesc/genericdesc.c index c35641483b8f9..75dc4108b9aa2 100644 --- a/src/backend/access/rmgrdesc/genericdesc.c +++ b/src/backend/access/rmgrdesc/genericdesc.c @@ -4,7 +4,7 @@ * rmgr descriptor routines for access/transam/generic_xlog.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/rmgrdesc/genericdesc.c diff --git a/src/backend/access/rmgrdesc/gindesc.c b/src/backend/access/rmgrdesc/gindesc.c index 4746f246ff1f9..723ff9499cf46 100644 --- a/src/backend/access/rmgrdesc/gindesc.c +++ b/src/backend/access/rmgrdesc/gindesc.c @@ -3,7 +3,7 @@ * gindesc.c * rmgr descriptor routines for access/transam/gin/ginxlog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/gistdesc.c b/src/backend/access/rmgrdesc/gistdesc.c index 5efbbf72e5781..a2b84e898f959 100644 --- a/src/backend/access/rmgrdesc/gistdesc.c +++ b/src/backend/access/rmgrdesc/gistdesc.c @@ -3,7 +3,7 @@ * gistdesc.c * rmgr descriptor routines for access/gist/gistxlog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/hashdesc.c b/src/backend/access/rmgrdesc/hashdesc.c index dd0bfff8cbc25..75f43a9152071 100644 --- a/src/backend/access/rmgrdesc/hashdesc.c +++ b/src/backend/access/rmgrdesc/hashdesc.c @@ -3,7 +3,7 @@ * hashdesc.c * rmgr descriptor routines for access/hash/hash.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c index 5f5673e088b01..82b62c95de574 100644 --- a/src/backend/access/rmgrdesc/heapdesc.c +++ b/src/backend/access/rmgrdesc/heapdesc.c @@ -3,7 +3,7 @@ * heapdesc.c * rmgr descriptor routines for access/heap/heapam.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -16,6 +16,7 @@ #include "access/heapam_xlog.h" #include "access/rmgrdesc_utils.h" +#include "storage/standbydefs.h" /* * NOTE: "keyname" argument cannot have trailing spaces or punctuation @@ -253,6 +254,9 @@ heap_desc(StringInfo buf, XLogReaderState *record) xl_heap_inplace *xlrec = (xl_heap_inplace *) rec; appendStringInfo(buf, "off: %u", xlrec->offnum); + standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs, + xlrec->dbId, xlrec->tsId, + xlrec->relcacheInitFileInval); } } diff --git a/src/backend/access/rmgrdesc/logicalmsgdesc.c b/src/backend/access/rmgrdesc/logicalmsgdesc.c index 430d7668c0c2e..1c8c99f19f836 100644 --- a/src/backend/access/rmgrdesc/logicalmsgdesc.c +++ b/src/backend/access/rmgrdesc/logicalmsgdesc.c @@ -3,7 +3,7 @@ * logicalmsgdesc.c * rmgr descriptor routines for replication/logical/message.c * - * Portions Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2015-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/access/rmgrdesc/meson.build b/src/backend/access/rmgrdesc/meson.build index e8b7a65fc76c2..96c98e800c22d 100644 --- a/src/backend/access/rmgrdesc/meson.build +++ b/src/backend/access/rmgrdesc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # used by frontend programs like pg_waldump rmgr_desc_sources = files( diff --git a/src/backend/access/rmgrdesc/mxactdesc.c b/src/backend/access/rmgrdesc/mxactdesc.c index 3e8ad4d5ef82b..3ca0582db3647 100644 --- a/src/backend/access/rmgrdesc/mxactdesc.c +++ b/src/backend/access/rmgrdesc/mxactdesc.c @@ -3,7 +3,7 @@ * mxactdesc.c * rmgr descriptor routines for access/transam/multixact.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -58,7 +58,7 @@ multixact_desc(StringInfo buf, XLogReaderState *record) int64 pageno; memcpy(&pageno, rec, sizeof(pageno)); - appendStringInfo(buf, "%lld", (long long) pageno); + appendStringInfo(buf, "%" PRId64, pageno); } else if (info == XLOG_MULTIXACT_CREATE_ID) { diff --git a/src/backend/access/rmgrdesc/nbtdesc.c b/src/backend/access/rmgrdesc/nbtdesc.c index 0f201ca2237c8..c05d19ab00753 100644 --- a/src/backend/access/rmgrdesc/nbtdesc.c +++ b/src/backend/access/rmgrdesc/nbtdesc.c @@ -3,7 +3,7 @@ * nbtdesc.c * rmgr descriptor routines for access/nbtree/nbtxlog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/relmapdesc.c b/src/backend/access/rmgrdesc/relmapdesc.c index 46d39cdca0eed..caf1846032167 100644 --- a/src/backend/access/rmgrdesc/relmapdesc.c +++ b/src/backend/access/rmgrdesc/relmapdesc.c @@ -3,7 +3,7 @@ * relmapdesc.c * rmgr descriptor routines for utils/cache/relmapper.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/replorigindesc.c b/src/backend/access/rmgrdesc/replorigindesc.c index c369ca01171ff..5dd742339969a 100644 --- a/src/backend/access/rmgrdesc/replorigindesc.c +++ b/src/backend/access/rmgrdesc/replorigindesc.c @@ -3,7 +3,7 @@ * replorigindesc.c * rmgr descriptor routines for replication/logical/origin.c * - * Portions Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2015-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/access/rmgrdesc/rmgrdesc_utils.c b/src/backend/access/rmgrdesc/rmgrdesc_utils.c index 2665c45873a64..25cf167f17524 100644 --- a/src/backend/access/rmgrdesc/rmgrdesc_utils.c +++ b/src/backend/access/rmgrdesc/rmgrdesc_utils.c @@ -3,7 +3,7 @@ * rmgrdesc_utils.c * Support functions for rmgrdesc routines * - * Copyright (c) 2023-2024, PostgreSQL Global Development Group + * Copyright (c) 2023-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/access/rmgrdesc/seqdesc.c b/src/backend/access/rmgrdesc/seqdesc.c index cf0e02ded592e..0d289d77fcf7a 100644 --- a/src/backend/access/rmgrdesc/seqdesc.c +++ b/src/backend/access/rmgrdesc/seqdesc.c @@ -3,7 +3,7 @@ * seqdesc.c * rmgr descriptor routines for commands/sequence.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/smgrdesc.c b/src/backend/access/rmgrdesc/smgrdesc.c index 71410e0a2d358..4bb7fc79bced6 100644 --- a/src/backend/access/rmgrdesc/smgrdesc.c +++ b/src/backend/access/rmgrdesc/smgrdesc.c @@ -3,7 +3,7 @@ * smgrdesc.c * rmgr descriptor routines for catalog/storage.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,19 +26,17 @@ smgr_desc(StringInfo buf, XLogReaderState *record) if (info == XLOG_SMGR_CREATE) { xl_smgr_create *xlrec = (xl_smgr_create *) rec; - char *path = relpathperm(xlrec->rlocator, xlrec->forkNum); - appendStringInfoString(buf, path); - pfree(path); + appendStringInfoString(buf, + relpathperm(xlrec->rlocator, xlrec->forkNum).str); } else if (info == XLOG_SMGR_TRUNCATE) { xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec; - char *path = relpathperm(xlrec->rlocator, MAIN_FORKNUM); - appendStringInfo(buf, "%s to %u blocks flags %d", path, + appendStringInfo(buf, "%s to %u blocks flags %d", + relpathperm(xlrec->rlocator, MAIN_FORKNUM).str, xlrec->blkno, xlrec->flags); - pfree(path); } } diff --git a/src/backend/access/rmgrdesc/spgdesc.c b/src/backend/access/rmgrdesc/spgdesc.c index e75971100c9c8..72efedc5b40d3 100644 --- a/src/backend/access/rmgrdesc/spgdesc.c +++ b/src/backend/access/rmgrdesc/spgdesc.c @@ -3,7 +3,7 @@ * spgdesc.c * rmgr descriptor routines for access/spgist/spgxlog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c index 25f870b187e8e..81eff5f31c4f6 100644 --- a/src/backend/access/rmgrdesc/standbydesc.c +++ b/src/backend/access/rmgrdesc/standbydesc.c @@ -3,7 +3,7 @@ * standbydesc.c * rmgr descriptor routines for storage/ipc/standby.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -96,11 +96,7 @@ standby_identify(uint8 info) return id; } -/* - * This routine is used by both standby_desc and xact_desc, because - * transaction commits and XLOG_INVALIDATIONS messages contain invalidations; - * it seems pointless to duplicate the code. - */ +/* also used by non-standby records having analogous invalidation fields */ void standby_desc_invalidations(StringInfo buf, int nmsgs, SharedInvalidationMessage *msgs, @@ -136,6 +132,8 @@ standby_desc_invalidations(StringInfo buf, appendStringInfo(buf, " relmap db %u", msg->rm.dbId); else if (msg->id == SHAREDINVALSNAPSHOT_ID) appendStringInfo(buf, " snapshot %u", msg->sn.relId); + else if (msg->id == SHAREDINVALRELSYNC_ID) + appendStringInfo(buf, " relsync %u", msg->rs.relid); else appendStringInfo(buf, " unrecognized id %d", msg->id); } diff --git a/src/backend/access/rmgrdesc/tblspcdesc.c b/src/backend/access/rmgrdesc/tblspcdesc.c index 56396ca946fef..5d612b4232e26 100644 --- a/src/backend/access/rmgrdesc/tblspcdesc.c +++ b/src/backend/access/rmgrdesc/tblspcdesc.c @@ -3,7 +3,7 @@ * tblspcdesc.c * rmgr descriptor routines for commands/tablespace.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c index dccca201e05c0..305598e2865c8 100644 --- a/src/backend/access/rmgrdesc/xactdesc.c +++ b/src/backend/access/rmgrdesc/xactdesc.c @@ -3,7 +3,7 @@ * xactdesc.c * rmgr descriptor routines for access/transam/xact.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -252,6 +252,8 @@ ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *p parsed->nsubxacts = xlrec->nsubxacts; parsed->nrels = xlrec->ncommitrels; parsed->nabortrels = xlrec->nabortrels; + parsed->nstats = xlrec->ncommitstats; + parsed->nabortstats = xlrec->nabortstats; parsed->nmsgs = xlrec->ninvalmsgs; strncpy(parsed->twophase_gid, bufptr, xlrec->gidlen); @@ -287,10 +289,8 @@ xact_desc_relations(StringInfo buf, char *label, int nrels, appendStringInfo(buf, "; %s:", label); for (i = 0; i < nrels; i++) { - char *path = relpathperm(xlocators[i], MAIN_FORKNUM); - - appendStringInfo(buf, " %s", path); - pfree(path); + appendStringInfo(buf, " %s", + relpathperm(xlocators[i], MAIN_FORKNUM).str); } } } @@ -319,10 +319,13 @@ xact_desc_stats(StringInfo buf, const char *label, appendStringInfo(buf, "; %sdropped stats:", label); for (i = 0; i < ndropped; i++) { - appendStringInfo(buf, " %d/%u/%u", + uint64 objid = + ((uint64) dropped_stats[i].objid_hi) << 32 | dropped_stats[i].objid_lo; + + appendStringInfo(buf, " %d/%u/%" PRIu64, dropped_stats[i].kind, dropped_stats[i].dboid, - dropped_stats[i].objoid); + objid); } } } diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c index 363294d6234a9..58040f28656fc 100644 --- a/src/backend/access/rmgrdesc/xlogdesc.c +++ b/src/backend/access/rmgrdesc/xlogdesc.c @@ -3,7 +3,7 @@ * xlogdesc.c * rmgr descriptor routines for access/transam/xlog.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/sequence/meson.build b/src/backend/access/sequence/meson.build index 1843aed38db23..ec9ab9b7e9dbd 100644 --- a/src/backend/access/sequence/meson.build +++ b/src/backend/access/sequence/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'sequence.c', diff --git a/src/backend/access/sequence/sequence.c b/src/backend/access/sequence/sequence.c index 8d6b7bb5dc25b..8b53035537022 100644 --- a/src/backend/access/sequence/sequence.c +++ b/src/backend/access/sequence/sequence.c @@ -3,7 +3,7 @@ * sequence.c * Generic routines for sequence-related code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,7 +22,7 @@ #include "access/relation.h" #include "access/sequence.h" -#include "storage/lmgr.h" +#include "utils/rel.h" static inline void validate_relation_kind(Relation r); diff --git a/src/backend/access/spgist/meson.build b/src/backend/access/spgist/meson.build index a6f4f3182bbed..e763f05304f73 100644 --- a/src/backend/access/spgist/meson.build +++ b/src/backend/access/spgist/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'spgdoinsert.c', diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c index a4995c168b44d..af6b27b2135ac 100644 --- a/src/backend/access/spgist/spgdoinsert.c +++ b/src/backend/access/spgist/spgdoinsert.c @@ -4,7 +4,7 @@ * implementation of insert algorithm * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -295,8 +295,8 @@ addLeafTuple(Relation index, SpGistState *state, SpGistLeafTuple leafTuple, int flags; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); - XLogRegisterData((char *) leafTuple, leafTuple->size); + XLogRegisterData(&xlrec, sizeof(xlrec)); + XLogRegisterData(leafTuple, leafTuple->size); flags = REGBUF_STANDARD; if (xlrec.newPage) @@ -532,12 +532,12 @@ moveLeafs(Relation index, SpGistState *state, xlrec.nodeI = parent->node; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfSpgxlogMoveLeafs); - XLogRegisterData((char *) toDelete, + XLogRegisterData(&xlrec, SizeOfSpgxlogMoveLeafs); + XLogRegisterData(toDelete, sizeof(OffsetNumber) * nDelete); - XLogRegisterData((char *) toInsert, + XLogRegisterData(toInsert, sizeof(OffsetNumber) * nInsert); - XLogRegisterData((char *) leafdata, leafptr - leafdata); + XLogRegisterData(leafdata, leafptr - leafdata); XLogRegisterBuffer(0, current->buffer, REGBUF_STANDARD); XLogRegisterBuffer(1, nbuf, REGBUF_STANDARD | (xlrec.newPage ? REGBUF_WILL_INIT : 0)); @@ -1365,15 +1365,15 @@ doPickSplit(Relation index, SpGistState *state, XLogBeginInsert(); xlrec.nInsert = nToInsert; - XLogRegisterData((char *) &xlrec, SizeOfSpgxlogPickSplit); + XLogRegisterData(&xlrec, SizeOfSpgxlogPickSplit); - XLogRegisterData((char *) toDelete, + XLogRegisterData(toDelete, sizeof(OffsetNumber) * xlrec.nDelete); - XLogRegisterData((char *) toInsert, + XLogRegisterData(toInsert, sizeof(OffsetNumber) * xlrec.nInsert); - XLogRegisterData((char *) leafPageSelect, + XLogRegisterData(leafPageSelect, sizeof(uint8) * xlrec.nInsert); - XLogRegisterData((char *) innerTuple, innerTuple->size); + XLogRegisterData(innerTuple, innerTuple->size); XLogRegisterData(leafdata, leafptr - leafdata); /* Old leaf page */ @@ -1559,8 +1559,8 @@ spgAddNodeAction(Relation index, SpGistState *state, XLogRecPtr recptr; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); - XLogRegisterData((char *) newInnerTuple, newInnerTuple->size); + XLogRegisterData(&xlrec, sizeof(xlrec)); + XLogRegisterData(newInnerTuple, newInnerTuple->size); XLogRegisterBuffer(0, current->buffer, REGBUF_STANDARD); @@ -1685,8 +1685,8 @@ spgAddNodeAction(Relation index, SpGistState *state, if (xlrec.parentBlk == 2) XLogRegisterBuffer(2, parent->buffer, REGBUF_STANDARD); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); - XLogRegisterData((char *) newInnerTuple, newInnerTuple->size); + XLogRegisterData(&xlrec, sizeof(xlrec)); + XLogRegisterData(newInnerTuple, newInnerTuple->size); recptr = XLogInsert(RM_SPGIST_ID, XLOG_SPGIST_ADD_NODE); @@ -1868,9 +1868,9 @@ spgSplitNodeAction(Relation index, SpGistState *state, XLogRecPtr recptr; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); - XLogRegisterData((char *) prefixTuple, prefixTuple->size); - XLogRegisterData((char *) postfixTuple, postfixTuple->size); + XLogRegisterData(&xlrec, sizeof(xlrec)); + XLogRegisterData(prefixTuple, prefixTuple->size); + XLogRegisterData(postfixTuple, postfixTuple->size); XLogRegisterBuffer(0, current->buffer, REGBUF_STANDARD); if (newBuffer != InvalidBuffer) @@ -1974,7 +1974,7 @@ spgdoinsert(Relation index, SpGistState *state, { if (!isnulls[i]) { - if (TupleDescAttr(leafDescriptor, i)->attlen == -1) + if (TupleDescCompactAttr(leafDescriptor, i)->attlen == -1) leafDatums[i] = PointerGetDatum(PG_DETOAST_DATUM(datums[i])); else leafDatums[i] = datums[i]; diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c index 1bec19c2b88f7..6a61e093fa05a 100644 --- a/src/backend/access/spgist/spginsert.c +++ b/src/backend/access/spgist/spginsert.c @@ -5,7 +5,7 @@ * * All the actual insertion logic is in spgdoinsert.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -122,7 +122,7 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo) ALLOCSET_DEFAULT_SIZES); reltuples = table_index_build_scan(heap, index, indexInfo, true, true, - spgistBuildCallback, (void *) &buildstate, + spgistBuildCallback, &buildstate, NULL); MemoryContextDelete(buildstate.tmpCtx); diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c index 44d054525202a..d6989759e5fd7 100644 --- a/src/backend/access/spgist/spgkdtreeproc.c +++ b/src/backend/access/spgist/spgkdtreeproc.c @@ -4,7 +4,7 @@ * implementation of k-d tree over points for SP-GiST * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/spgist/spgproc.c b/src/backend/access/spgist/spgproc.c index 89699e7e7ffc6..660009291da4d 100644 --- a/src/backend/access/spgist/spgproc.c +++ b/src/backend/access/spgist/spgproc.c @@ -4,7 +4,7 @@ * Common supporting procedures for SP-GiST opclasses. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/spgist/spgquadtreeproc.c b/src/backend/access/spgist/spgquadtreeproc.c index 791db1d42e002..3e8cfa1709af3 100644 --- a/src/backend/access/spgist/spgquadtreeproc.c +++ b/src/backend/access/spgist/spgquadtreeproc.c @@ -4,7 +4,7 @@ * implementation of quad tree over points for SP-GiST * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c index 03293a7816e6f..25893050c5876 100644 --- a/src/backend/access/spgist/spgscan.c +++ b/src/backend/access/spgist/spgscan.c @@ -4,7 +4,7 @@ * routines for scanning SP-GiST indexes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -384,16 +384,14 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, /* copy scankeys into local storage */ if (scankey && scan->numberOfKeys > 0) - memmove(scan->keyData, scankey, - scan->numberOfKeys * sizeof(ScanKeyData)); + memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); /* initialize order-by data if needed */ if (orderbys && scan->numberOfOrderBys > 0) { int i; - memmove(scan->orderByData, orderbys, - scan->numberOfOrderBys * sizeof(ScanKeyData)); + memcpy(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData)); for (i = 0; i < scan->numberOfOrderBys; i++) { @@ -423,6 +421,8 @@ spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, /* count an indexscan for stats */ pgstat_count_index_scan(scan->indexRelation); + if (scan->instrument) + scan->instrument->nsearches++; } void @@ -867,7 +867,7 @@ spgWalk(Relation index, SpGistScanOpaque so, bool scanWholeIndex, if (SpGistPageIsLeaf(page)) { - /* Page is a leaf - that is, all it's tuples are heap items */ + /* Page is a leaf - that is, all its tuples are heap items */ OffsetNumber max = PageGetMaxOffsetNumber(page); if (SpGistBlockIsRoot(blkno)) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index 3f08d330b6113..73842655f086c 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -29,7 +29,7 @@ * No new entries ever get pushed into a -2-labeled child, either. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -427,7 +427,7 @@ spg_text_inner_consistent(PG_FUNCTION_ARGS) { spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0); spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1); - bool collate_is_c = lc_collate_is_c(PG_GET_COLLATION()); + bool collate_is_c = pg_newlocale_from_collation(PG_GET_COLLATION())->collate_is_c; text *reconstructedValue; text *reconstrText; int maxReconstrLen; diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 76b80146ff01b..95fea74e296f8 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -4,7 +4,7 @@ * various support functions for SP-GiST * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -50,6 +50,9 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = SPGIST_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = true; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = false; @@ -76,6 +79,7 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = spgvacuumcleanup; amroutine->amcanreturn = spgcanreturn; amroutine->amcostestimate = spgcostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = spgoptions; amroutine->amproperty = spgproperty; amroutine->ambuildphasename = NULL; @@ -91,6 +95,8 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amestimateparallelscan = NULL; amroutine->aminitparallelscan = NULL; amroutine->amparallelrescan = NULL; + amroutine->amtranslatestrategy = NULL; + amroutine->amtranslatecmptype = NULL; PG_RETURN_POINTER(amroutine); } @@ -278,7 +284,7 @@ spgGetCache(Relation index) UnlockReleaseBuffer(metabuffer); } - index->rd_amcache = (void *) cache; + index->rd_amcache = cache; } else { @@ -330,7 +336,9 @@ getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType) att->attcollation = InvalidOid; /* In case we changed typlen, we'd better reset following offsets */ for (int i = spgFirstIncludeColumn; i < outTupDesc->natts; i++) - TupleDescAttr(outTupDesc, i)->attcacheoff = -1; + TupleDescCompactAttr(outTupDesc, i)->attcacheoff = -1; + + populate_compact_attribute(outTupDesc, spgKeyColumn); } return outTupDesc; } diff --git a/src/backend/access/spgist/spgvacuum.c b/src/backend/access/spgist/spgvacuum.c index 0da069fd4d722..2678f7ab7829a 100644 --- a/src/backend/access/spgist/spgvacuum.c +++ b/src/backend/access/spgist/spgvacuum.c @@ -4,7 +4,7 @@ * vacuum for SP-GiST * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -25,6 +25,7 @@ #include "storage/bufmgr.h" #include "storage/indexfsm.h" #include "storage/lmgr.h" +#include "storage/read_stream.h" #include "utils/snapmgr.h" @@ -380,14 +381,14 @@ vacuumLeafPage(spgBulkDeleteState *bds, Relation index, Buffer buffer, STORE_STATE(&bds->spgstate, xlrec.stateSrc); - XLogRegisterData((char *) &xlrec, SizeOfSpgxlogVacuumLeaf); + XLogRegisterData(&xlrec, SizeOfSpgxlogVacuumLeaf); /* sizeof(xlrec) should be a multiple of sizeof(OffsetNumber) */ - XLogRegisterData((char *) toDead, sizeof(OffsetNumber) * xlrec.nDead); - XLogRegisterData((char *) toPlaceholder, sizeof(OffsetNumber) * xlrec.nPlaceholder); - XLogRegisterData((char *) moveSrc, sizeof(OffsetNumber) * xlrec.nMove); - XLogRegisterData((char *) moveDest, sizeof(OffsetNumber) * xlrec.nMove); - XLogRegisterData((char *) chainSrc, sizeof(OffsetNumber) * xlrec.nChain); - XLogRegisterData((char *) chainDest, sizeof(OffsetNumber) * xlrec.nChain); + XLogRegisterData(toDead, sizeof(OffsetNumber) * xlrec.nDead); + XLogRegisterData(toPlaceholder, sizeof(OffsetNumber) * xlrec.nPlaceholder); + XLogRegisterData(moveSrc, sizeof(OffsetNumber) * xlrec.nMove); + XLogRegisterData(moveDest, sizeof(OffsetNumber) * xlrec.nMove); + XLogRegisterData(chainSrc, sizeof(OffsetNumber) * xlrec.nChain); + XLogRegisterData(chainDest, sizeof(OffsetNumber) * xlrec.nChain); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); @@ -465,9 +466,9 @@ vacuumLeafRoot(spgBulkDeleteState *bds, Relation index, Buffer buffer) /* Prepare WAL record */ STORE_STATE(&bds->spgstate, xlrec.stateSrc); - XLogRegisterData((char *) &xlrec, SizeOfSpgxlogVacuumRoot); + XLogRegisterData(&xlrec, SizeOfSpgxlogVacuumRoot); /* sizeof(xlrec) should be a multiple of sizeof(OffsetNumber) */ - XLogRegisterData((char *) toDelete, + XLogRegisterData(toDelete, sizeof(OffsetNumber) * xlrec.nDelete); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); @@ -600,8 +601,8 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer) XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfSpgxlogVacuumRedirect); - XLogRegisterData((char *) itemToPlaceholder, + XLogRegisterData(&xlrec, SizeOfSpgxlogVacuumRedirect); + XLogRegisterData(itemToPlaceholder, sizeof(OffsetNumber) * xlrec.nToPlaceholder); XLogRegisterBuffer(0, buffer, REGBUF_STANDARD); @@ -618,17 +619,12 @@ vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer) * Process one page during a bulkdelete scan */ static void -spgvacuumpage(spgBulkDeleteState *bds, BlockNumber blkno) +spgvacuumpage(spgBulkDeleteState *bds, Buffer buffer) { Relation index = bds->info->index; - Buffer buffer; + BlockNumber blkno = BufferGetBlockNumber(buffer); Page page; - /* call vacuum_delay_point while not holding any buffer lock */ - vacuum_delay_point(); - - buffer = ReadBufferExtended(index, MAIN_FORKNUM, blkno, - RBM_NORMAL, bds->info->strategy); LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE); page = (Page) BufferGetPage(buffer); @@ -704,7 +700,7 @@ spgprocesspending(spgBulkDeleteState *bds) continue; /* ignore already-done items */ /* call vacuum_delay_point while not holding any buffer lock */ - vacuum_delay_point(); + vacuum_delay_point(false); /* examine the referenced page */ blkno = ItemPointerGetBlockNumber(&pitem->tid); @@ -805,8 +801,9 @@ spgvacuumscan(spgBulkDeleteState *bds) { Relation index = bds->info->index; bool needLock; - BlockNumber num_pages, - blkno; + BlockNumber num_pages; + BlockRangeReadStreamPrivate p; + ReadStream *stream = NULL; /* Finish setting up spgBulkDeleteState */ initSpGistState(&bds->spgstate, index); @@ -824,6 +821,21 @@ spgvacuumscan(spgBulkDeleteState *bds) /* We can skip locking for new or temp relations */ needLock = !RELATION_IS_LOCAL(index); + p.current_blocknum = SPGIST_METAPAGE_BLKNO + 1; + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, + bds->info->strategy, + index, + MAIN_FORKNUM, + block_range_read_stream_cb, + &p, + 0); /* * The outer loop iterates over all index pages except the metapage, in @@ -833,7 +845,6 @@ spgvacuumscan(spgBulkDeleteState *bds) * delete some deletable tuples. See more extensive comments about this * in btvacuumscan(). */ - blkno = SPGIST_METAPAGE_BLKNO + 1; for (;;) { /* Get the current relation length */ @@ -844,18 +855,41 @@ spgvacuumscan(spgBulkDeleteState *bds) UnlockRelationForExtension(index, ExclusiveLock); /* Quit if we've scanned the whole relation */ - if (blkno >= num_pages) + if (p.current_blocknum >= num_pages) break; + + p.last_exclusive = num_pages; + /* Iterate over pages, then loop back to recheck length */ - for (; blkno < num_pages; blkno++) + while (true) { - spgvacuumpage(bds, blkno); + Buffer buf; + + /* call vacuum_delay_point while not holding any buffer lock */ + vacuum_delay_point(false); + + buf = read_stream_next_buffer(stream, NULL); + + if (!BufferIsValid(buf)) + break; + + spgvacuumpage(bds, buf); + /* empty the pending-list after each page */ if (bds->pendingList != NULL) spgprocesspending(bds); } + + /* + * We have to reset the read stream to use it again. After returning + * InvalidBuffer, the read stream API won't invoke our callback again + * until the stream has been reset. + */ + read_stream_reset(stream); } + read_stream_end(stream); + /* Propagate local lastUsedPages cache to metablock */ SpGistUpdateMetaPage(index); diff --git a/src/backend/access/spgist/spgvalidate.c b/src/backend/access/spgist/spgvalidate.c index 850c3b675d63c..e9964fab4f41a 100644 --- a/src/backend/access/spgist/spgvalidate.c +++ b/src/backend/access/spgist/spgvalidate.c @@ -3,7 +3,7 @@ * spgvalidate.c * Opclass validator for SP-GiST. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,7 +19,6 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -45,8 +44,6 @@ spgvalidate(Oid opclassoid) Oid opcintype; Oid opckeytype; char *opclassname; - HeapTuple familytup; - Form_pg_opfamily familyform; char *opfamilyname; CatCList *proclist, *oprlist; @@ -72,12 +69,7 @@ spgvalidate(Oid opclassoid) opclassname = NameStr(classform->opcname); /* Fetch opfamily information */ - familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid)); - if (!HeapTupleIsValid(familytup)) - elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid); - familyform = (Form_pg_opfamily) GETSTRUCT(familytup); - - opfamilyname = NameStr(familyform->opfname); + opfamilyname = get_opfamily_name(opfamilyoid, false); /* Fetch all operators and support functions of the opfamily */ oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid)); @@ -319,7 +311,6 @@ spgvalidate(Oid opclassoid) ReleaseCatCacheList(proclist); ReleaseCatCacheList(oprlist); - ReleaseSysCache(familytup); ReleaseSysCache(classtup); return result; diff --git a/src/backend/access/spgist/spgxlog.c b/src/backend/access/spgist/spgxlog.c index 4e31d33e70949..b7986e6f7131e 100644 --- a/src/backend/access/spgist/spgxlog.c +++ b/src/backend/access/spgist/spgxlog.c @@ -4,7 +4,7 @@ * WAL replay logic for SP-GiST * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/table/meson.build b/src/backend/access/table/meson.build index 8ed1335a55d68..36ad5fb835ad1 100644 --- a/src/backend/access/table/meson.build +++ b/src/backend/access/table/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'table.c', diff --git a/src/backend/access/table/table.c b/src/backend/access/table/table.c index e589730ca0842..be698bba0ed1b 100644 --- a/src/backend/access/table/table.c +++ b/src/backend/access/table/table.c @@ -3,7 +3,7 @@ * table.c * Generic routines for table related code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c index e57a0b7ea310b..a56c5eceb14ad 100644 --- a/src/backend/access/table/tableam.c +++ b/src/backend/access/table/tableam.c @@ -3,7 +3,7 @@ * tableam.c * Table access method routines too big to be inline functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -24,6 +24,7 @@ #include "access/syncscan.h" #include "access/tableam.h" #include "access/xact.h" +#include "optimizer/optimizer.h" #include "optimizer/plancat.h" #include "port/pg_bitutils.h" #include "storage/bufmgr.h" @@ -168,7 +169,7 @@ table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan) uint32 flags = SO_TYPE_SEQSCAN | SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE; - Assert(RelationGetRelid(relation) == pscan->phs_relid); + Assert(RelFileLocatorEquals(relation->rd_locator, pscan->phs_locator)); if (!pscan->phs_snapshot_any) { @@ -389,7 +390,7 @@ table_block_parallelscan_initialize(Relation rel, ParallelTableScanDesc pscan) { ParallelBlockTableScanDesc bpscan = (ParallelBlockTableScanDesc) pscan; - bpscan->base.phs_relid = RelationGetRelid(rel); + bpscan->base.phs_locator = rel->rd_locator; bpscan->phs_nblocks = RelationGetNumberOfBlocks(rel); /* compare phs_syncscan initialization to similar logic in initscan */ bpscan->base.phs_syncscan = synchronize_seqscans && @@ -740,6 +741,8 @@ table_block_relation_estimate_size(Relation rel, int32 *attr_widths, tuple_width += overhead_bytes_per_tuple; /* note: integer division is intentional here */ density = (usable_bytes_per_page * fillfactor / 100) / tuple_width; + /* There's at least one row on the page, even with low fillfactor. */ + density = clamp_row_est(density); } *tuples = rint(density * (double) curpages); diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c index e9b598256fbe0..476663b66aada 100644 --- a/src/backend/access/table/tableamapi.c +++ b/src/backend/access/table/tableamapi.c @@ -3,7 +3,7 @@ * tableamapi.c * Support routines for API for Postgres table access methods * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/table/tableamapi.c @@ -91,9 +91,6 @@ GetTableAmRoutine(Oid amhandler) Assert(routine->relation_estimate_size != NULL); - /* optional, but one callback implies presence of the other */ - Assert((routine->scan_bitmap_next_block == NULL) == - (routine->scan_bitmap_next_tuple == NULL)); Assert(routine->scan_sample_next_block != NULL); Assert(routine->scan_sample_next_tuple != NULL); diff --git a/src/backend/access/table/toast_helper.c b/src/backend/access/table/toast_helper.c index 53224932f0db4..b60fab0a4d294 100644 --- a/src/backend/access/table/toast_helper.c +++ b/src/backend/access/table/toast_helper.c @@ -4,7 +4,7 @@ * Helper functions for table AMs implementing compressed or * out-of-line storage of varlena attributes. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/table/toast_helper.c @@ -75,7 +75,7 @@ toast_tuple_init(ToastTupleContext *ttc) { if (ttc->ttc_isnull[i] || !VARATT_IS_EXTERNAL_ONDISK(new_value) || - memcmp((char *) old_value, (char *) new_value, + memcmp(old_value, new_value, VARSIZE_EXTERNAL(old_value)) != 0) { /* @@ -324,7 +324,7 @@ toast_delete_external(Relation rel, const Datum *values, const bool *isnull, for (i = 0; i < numAttrs; i++) { - if (TupleDescAttr(tupleDesc, i)->attlen == -1) + if (TupleDescCompactAttr(tupleDesc, i)->attlen == -1) { Datum value = values[i]; diff --git a/src/backend/access/tablesample/bernoulli.c b/src/backend/access/tablesample/bernoulli.c index c8ac308ff8c55..5e1c5d2b7231a 100644 --- a/src/backend/access/tablesample/bernoulli.c +++ b/src/backend/access/tablesample/bernoulli.c @@ -13,7 +13,7 @@ * cutoff value computed from the selection probability by BeginSampleScan. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/tablesample/meson.build b/src/backend/access/tablesample/meson.build index 6f3112fb758b5..b0124cde63a01 100644 --- a/src/backend/access/tablesample/meson.build +++ b/src/backend/access/tablesample/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bernoulli.c', diff --git a/src/backend/access/tablesample/system.c b/src/backend/access/tablesample/system.c index fe483ab859725..8db813b89fc64 100644 --- a/src/backend/access/tablesample/system.c +++ b/src/backend/access/tablesample/system.c @@ -13,7 +13,7 @@ * cutoff value computed from the selection probability by BeginSampleScan. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/tablesample/tablesample.c b/src/backend/access/tablesample/tablesample.c index e9a495e4cc879..5ad424cf8491f 100644 --- a/src/backend/access/tablesample/tablesample.c +++ b/src/backend/access/tablesample/tablesample.c @@ -3,7 +3,7 @@ * tablesample.c * Support functions for TABLESAMPLE feature * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/transam/README b/src/backend/access/transam/README index 28d196cf62b33..231106270fd40 100644 --- a/src/backend/access/transam/README +++ b/src/backend/access/transam/README @@ -586,13 +586,13 @@ void XLogRegisterBuffer(uint8 block_id, Buffer buf, uint8 flags); XLogRegisterBufData() is included in the WAL record even if a full-page image is taken. -void XLogRegisterData(char *data, int len); +void XLogRegisterData(const void *data, int len); XLogRegisterData is used to include arbitrary data in the WAL record. If XLogRegisterData() is called multiple times, the data are appended, and will be made available to the redo routine as one contiguous chunk. -void XLogRegisterBufData(uint8 block_id, char *data, int len); +void XLogRegisterBufData(uint8 block_id, const void *data, int len); XLogRegisterBufData is used to include data associated with a particular buffer that was registered earlier with XLogRegisterBuffer(). If diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index e6f79320e9425..48f10bec91e12 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -24,7 +24,7 @@ * for aborts (whether sync or async), since the post-crash assumption would * be that such transactions failed anyway. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/clog.c @@ -984,8 +984,8 @@ ExtendCLOG(TransactionId newestXact) /* * Remove all CLOG segments before the one holding the passed transaction ID * - * Before removing any CLOG data, we must flush XLOG to disk, to ensure - * that any recently-emitted FREEZE_PAGE records have reached disk; otherwise + * Before removing any CLOG data, we must flush XLOG to disk, to ensure that + * any recently-emitted records with freeze plans have reached disk; otherwise * a crash and restart might leave us with some unfrozen tuples referencing * removed CLOG data. We choose to emit a special TRUNCATE XLOG record too. * Replaying the deletion from XLOG is not critical, since the files could @@ -1074,7 +1074,7 @@ static void WriteZeroPageXlogRec(int64 pageno) { XLogBeginInsert(); - XLogRegisterData((char *) (&pageno), sizeof(pageno)); + XLogRegisterData(&pageno, sizeof(pageno)); (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE); } @@ -1095,7 +1095,7 @@ WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact, Oid oldestXactDb) xlrec.oldestXactDb = oldestXactDb; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate)); + XLogRegisterData(&xlrec, sizeof(xl_clog_truncate)); recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE); XLogFlush(recptr); } diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index 77e1899d7ad21..113fae1437ad8 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -12,7 +12,7 @@ * XLOG records for these events and will re-perform the status update on * redo; so we need make no additional XLOG entry here. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/commit_ts.c @@ -989,7 +989,7 @@ static void WriteZeroPageXlogRec(int64 pageno) { XLogBeginInsert(); - XLogRegisterData((char *) (&pageno), sizeof(pageno)); + XLogRegisterData(&pageno, sizeof(pageno)); (void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE); } @@ -1005,7 +1005,7 @@ WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid) xlrec.oldestXid = oldestXid; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), SizeOfCommitTsTruncate); + XLogRegisterData(&xlrec, SizeOfCommitTsTruncate); (void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_TRUNCATE); } diff --git a/src/backend/access/transam/generic_xlog.c b/src/backend/access/transam/generic_xlog.c index e8522781631df..2ce11e96af0dd 100644 --- a/src/backend/access/transam/generic_xlog.c +++ b/src/backend/access/transam/generic_xlog.c @@ -4,7 +4,7 @@ * Implementation of generic xlog records. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/generic_xlog.c @@ -55,7 +55,7 @@ typedef struct char *image; /* copy of page image for modification, do not * do it in-place to have aligned memory chunk */ char delta[MAX_DELTA_SIZE]; /* delta between page images */ -} PageData; +} GenericXLogPageData; /* * State of generic xlog record construction. Must be allocated at an I/O @@ -66,17 +66,17 @@ struct GenericXLogState /* Page images (properly aligned, must be first) */ PGIOAlignedBlock images[MAX_GENERIC_XLOG_PAGES]; /* Info about each page, see above */ - PageData pages[MAX_GENERIC_XLOG_PAGES]; + GenericXLogPageData pages[MAX_GENERIC_XLOG_PAGES]; bool isLogged; }; -static void writeFragment(PageData *pageData, OffsetNumber offset, +static void writeFragment(GenericXLogPageData *pageData, OffsetNumber offset, OffsetNumber length, const char *data); -static void computeRegionDelta(PageData *pageData, +static void computeRegionDelta(GenericXLogPageData *pageData, const char *curpage, const char *targetpage, int targetStart, int targetEnd, int validStart, int validEnd); -static void computeDelta(PageData *pageData, Page curpage, Page targetpage); +static void computeDelta(GenericXLogPageData *pageData, Page curpage, Page targetpage); static void applyPageRedo(Page page, const char *delta, Size deltaSize); @@ -87,7 +87,7 @@ static void applyPageRedo(Page page, const char *delta, Size deltaSize); * actual data (of length length). */ static void -writeFragment(PageData *pageData, OffsetNumber offset, OffsetNumber length, +writeFragment(GenericXLogPageData *pageData, OffsetNumber offset, OffsetNumber length, const char *data) { char *ptr = pageData->delta + pageData->deltaLen; @@ -118,7 +118,7 @@ writeFragment(PageData *pageData, OffsetNumber offset, OffsetNumber length, * about the data-matching loops. */ static void -computeRegionDelta(PageData *pageData, +computeRegionDelta(GenericXLogPageData *pageData, const char *curpage, const char *targetpage, int targetStart, int targetEnd, int validStart, int validEnd) @@ -225,7 +225,7 @@ computeRegionDelta(PageData *pageData, * and store it in pageData's delta field. */ static void -computeDelta(PageData *pageData, Page curpage, Page targetpage) +computeDelta(GenericXLogPageData *pageData, Page curpage, Page targetpage) { int targetLower = ((PageHeader) targetpage)->pd_lower, targetUpper = ((PageHeader) targetpage)->pd_upper, @@ -303,7 +303,7 @@ GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags) /* Search array for existing entry or first unused slot */ for (block_id = 0; block_id < MAX_GENERIC_XLOG_PAGES; block_id++) { - PageData *page = &state->pages[block_id]; + GenericXLogPageData *page = &state->pages[block_id]; if (BufferIsInvalid(page->buffer)) { @@ -352,7 +352,7 @@ GenericXLogFinish(GenericXLogState *state) */ for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++) { - PageData *pageData = &state->pages[i]; + GenericXLogPageData *pageData = &state->pages[i]; Page page; PageHeader pageHeader; @@ -401,7 +401,7 @@ GenericXLogFinish(GenericXLogState *state) /* Set LSN */ for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++) { - PageData *pageData = &state->pages[i]; + GenericXLogPageData *pageData = &state->pages[i]; if (BufferIsInvalid(pageData->buffer)) continue; @@ -415,7 +415,7 @@ GenericXLogFinish(GenericXLogState *state) START_CRIT_SECTION(); for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++) { - PageData *pageData = &state->pages[i]; + GenericXLogPageData *pageData = &state->pages[i]; if (BufferIsInvalid(pageData->buffer)) continue; diff --git a/src/backend/access/transam/meson.build b/src/backend/access/transam/meson.build index 8a3522557cd90..e8ae9b13c8e49 100644 --- a/src/backend/access/transam/meson.build +++ b/src/backend/access/transam/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'clog.c', diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index c601ff98a14d5..3c06ac45532f8 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -59,7 +59,7 @@ * counter does not fall within the wraparound horizon considering the global * minimum value. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/multixact.c @@ -89,6 +89,7 @@ #include "storage/procarray.h" #include "utils/fmgrprotos.h" #include "utils/guc_hooks.h" +#include "utils/injection_point.h" #include "utils/memutils.h" @@ -120,7 +121,7 @@ MultiXactIdToOffsetEntry(MultiXactId multi) return multi % MULTIXACT_OFFSETS_PER_PAGE; } -static inline int +static inline int64 MultiXactIdToOffsetSegment(MultiXactId multi) { return MultiXactIdToOffsetPage(multi) / SLRU_PAGES_PER_SEGMENT; @@ -174,7 +175,7 @@ MXOffsetToMemberPage(MultiXactOffset offset) return offset / MULTIXACT_MEMBERS_PER_PAGE; } -static inline int +static inline int64 MXOffsetToMemberSegment(MultiXactOffset offset) { return MXOffsetToMemberPage(offset) / SLRU_PAGES_PER_SEGMENT; @@ -854,6 +855,9 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) } } + /* Load the injection point before entering the critical section */ + INJECTION_POINT_LOAD("multixact-create-from-members"); + /* * Assign the MXID and offsets range to use, and make sure there is space * in the OFFSETs and MEMBERs files. NB: this routine does @@ -868,6 +872,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) */ multi = GetNewMultiXactId(nmembers, &offset); + INJECTION_POINT_CACHED("multixact-create-from-members", NULL); + /* Make an XLOG entry describing the new MXID. */ xlrec.mid = multi; xlrec.moff = offset; @@ -880,8 +886,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) * Not clear that it's worth the trouble though. */ XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), SizeOfMultiXactCreate); - XLogRegisterData((char *) members, nmembers * sizeof(MultiXactMember)); + XLogRegisterData(&xlrec, SizeOfMultiXactCreate); + XLogRegisterData(members, nmembers * sizeof(MultiXactMember)); (void) XLogInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_CREATE_ID); @@ -1281,7 +1287,7 @@ GetNewMultiXactId(int nmembers, MultiXactOffset *offset) * range, in which case an error would be raised. * * In all other cases, the passed multixact must be within the known valid - * range, that is, greater to or equal than oldestMultiXactId, and less than + * range, that is, greater than or equal to oldestMultiXactId, and less than * nextMXact. Otherwise, an error is raised. * * isLockOnly must be set to true if caller is certain that the given multi @@ -1480,6 +1486,8 @@ GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, LWLockRelease(lock); CHECK_FOR_INTERRUPTS(); + INJECTION_POINT("multixact-get-members-cv-sleep", NULL); + ConditionVariableSleep(&MultiXactState->nextoff_cv, WAIT_EVENT_MULTIXACT_CREATION); slept = true; @@ -2009,7 +2017,7 @@ check_multixact_offset_buffers(int *newval, void **extra, GucSource source) } /* - * GUC check_hook for multixact_member_buffer + * GUC check_hook for multixact_member_buffers */ bool check_multixact_member_buffers(int *newval, void **extra, GucSource source) @@ -3039,10 +3047,10 @@ SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int64 segpage, void *data static void PerformMembersTruncation(MultiXactOffset oldestOffset, MultiXactOffset newOldestOffset) { - const int maxsegment = MXOffsetToMemberSegment(MaxMultiXactOffset); - int startsegment = MXOffsetToMemberSegment(oldestOffset); - int endsegment = MXOffsetToMemberSegment(newOldestOffset); - int segment = startsegment; + const int64 maxsegment = MXOffsetToMemberSegment(MaxMultiXactOffset); + int64 startsegment = MXOffsetToMemberSegment(oldestOffset); + int64 endsegment = MXOffsetToMemberSegment(newOldestOffset); + int64 segment = startsegment; /* * Delete all the segments but the last one. The last segment can still @@ -3050,8 +3058,8 @@ PerformMembersTruncation(MultiXactOffset oldestOffset, MultiXactOffset newOldest */ while (segment != endsegment) { - elog(DEBUG2, "truncating multixact members segment %llx", - (unsigned long long) segment); + elog(DEBUG2, "truncating multixact members segment %" PRIx64, + segment); SlruDeleteSegment(MultiXactMemberCtl, segment); /* move to next segment, handling wraparound correctly */ @@ -3202,14 +3210,14 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB) } elog(DEBUG1, "performing multixact truncation: " - "offsets [%u, %u), offsets segments [%llx, %llx), " - "members [%u, %u), members segments [%llx, %llx)", + "offsets [%u, %u), offsets segments [%" PRIx64 ", %" PRIx64 "), " + "members [%u, %u), members segments [%" PRIx64 ", %" PRIx64 ")", oldestMulti, newOldestMulti, - (unsigned long long) MultiXactIdToOffsetSegment(oldestMulti), - (unsigned long long) MultiXactIdToOffsetSegment(newOldestMulti), + MultiXactIdToOffsetSegment(oldestMulti), + MultiXactIdToOffsetSegment(newOldestMulti), oldestOffset, newOldestOffset, - (unsigned long long) MXOffsetToMemberSegment(oldestOffset), - (unsigned long long) MXOffsetToMemberSegment(newOldestOffset)); + MXOffsetToMemberSegment(oldestOffset), + MXOffsetToMemberSegment(newOldestOffset)); /* * Do truncation, and the WAL logging of the truncation, in a critical @@ -3347,7 +3355,7 @@ static void WriteMZeroPageXlogRec(int64 pageno, uint8 info) { XLogBeginInsert(); - XLogRegisterData((char *) (&pageno), sizeof(pageno)); + XLogRegisterData(&pageno, sizeof(pageno)); (void) XLogInsert(RM_MULTIXACT_ID, info); } @@ -3374,7 +3382,7 @@ WriteMTruncateXlogRec(Oid oldestMultiDB, xlrec.endTruncMemb = endTruncMemb; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), SizeOfMultiXactTruncate); + XLogRegisterData(&xlrec, SizeOfMultiXactTruncate); recptr = XLogInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_TRUNCATE_ID); XLogFlush(recptr); } @@ -3462,14 +3470,14 @@ multixact_redo(XLogReaderState *record) SizeOfMultiXactTruncate); elog(DEBUG1, "replaying multixact truncation: " - "offsets [%u, %u), offsets segments [%llx, %llx), " - "members [%u, %u), members segments [%llx, %llx)", + "offsets [%u, %u), offsets segments [%" PRIx64 ", %" PRIx64 "), " + "members [%u, %u), members segments [%" PRIx64 ", %" PRIx64 ")", xlrec.startTruncOff, xlrec.endTruncOff, - (unsigned long long) MultiXactIdToOffsetSegment(xlrec.startTruncOff), - (unsigned long long) MultiXactIdToOffsetSegment(xlrec.endTruncOff), + MultiXactIdToOffsetSegment(xlrec.startTruncOff), + MultiXactIdToOffsetSegment(xlrec.endTruncOff), xlrec.startTruncMemb, xlrec.endTruncMemb, - (unsigned long long) MXOffsetToMemberSegment(xlrec.startTruncMemb), - (unsigned long long) MXOffsetToMemberSegment(xlrec.endTruncMemb)); + MXOffsetToMemberSegment(xlrec.startTruncMemb), + MXOffsetToMemberSegment(xlrec.endTruncMemb)); /* should not be required, but more than cheap enough */ LWLockAcquire(MultiXactTruncationLock, LW_EXCLUSIVE); diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index 8613fc6fb547c..94db1ec30126a 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -3,7 +3,7 @@ * parallel.c * Infrastructure for launching parallel workers * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/brin.h" +#include "access/gin.h" #include "access/nbtree.h" #include "access/parallel.h" #include "access/session.h" @@ -83,12 +84,14 @@ typedef struct FixedParallelState /* Fixed-size state that workers must restore. */ Oid database_id; Oid authenticated_user_id; - Oid current_user_id; + Oid session_user_id; Oid outer_user_id; + Oid current_user_id; Oid temp_namespace_id; Oid temp_toast_namespace_id; int sec_context; - bool is_superuser; + bool session_user_is_superuser; + bool role_is_superuser; PGPROC *parallel_leader_pgproc; pid_t parallel_leader_pid; ProcNumber parallel_leader_proc_number; @@ -146,13 +149,16 @@ static const struct { "_brin_parallel_build_main", _brin_parallel_build_main }, + { + "_gin_parallel_build_main", _gin_parallel_build_main + }, { "parallel_vacuum_main", parallel_vacuum_main } }; /* Private functions. */ -static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg); +static void ProcessParallelMessage(ParallelContext *pcxt, int i, StringInfo msg); static void WaitForParallelWorkersToExit(ParallelContext *pcxt); static parallel_worker_main_type LookupParallelWorkerFunction(const char *libraryname, const char *funcname); static void ParallelWorkerShutdown(int code, Datum arg); @@ -230,6 +236,15 @@ InitializeParallelDSM(ParallelContext *pcxt) shm_toc_estimate_chunk(&pcxt->estimator, sizeof(FixedParallelState)); shm_toc_estimate_keys(&pcxt->estimator, 1); + /* + * If we manage to reach here while non-interruptible, it's unsafe to + * launch any workers: we would fail to process interrupts sent by them. + * We can deal with that edge case by pretending no workers were + * requested. + */ + if (!INTERRUPTS_CAN_BE_PROCESSED()) + pcxt->nworkers = 0; + /* * Normally, the user will have requested at least one worker process, but * if by chance they have not, we can skip a bunch of things here. @@ -327,9 +342,11 @@ InitializeParallelDSM(ParallelContext *pcxt) shm_toc_allocate(pcxt->toc, sizeof(FixedParallelState)); fps->database_id = MyDatabaseId; fps->authenticated_user_id = GetAuthenticatedUserId(); + fps->session_user_id = GetSessionUserId(); fps->outer_user_id = GetCurrentRoleId(); - fps->is_superuser = current_role_is_superuser; GetUserIdAndSecContext(&fps->current_user_id, &fps->sec_context); + fps->session_user_is_superuser = GetSessionUserIsSuperuser(); + fps->role_is_superuser = current_role_is_superuser; GetTempNamespaceState(&fps->temp_namespace_id, &fps->temp_toast_namespace_id); fps->parallel_leader_pgproc = MyProc; @@ -476,6 +493,9 @@ InitializeParallelDSM(ParallelContext *pcxt) shm_toc_insert(pcxt->toc, PARALLEL_KEY_ENTRYPOINT, entrypointstate); } + /* Update nworkers_to_launch, in case we changed nworkers above. */ + pcxt->nworkers_to_launch = pcxt->nworkers; + /* Restore previous memory context. */ MemoryContextSwitchTo(oldcontext); } @@ -539,10 +559,11 @@ ReinitializeParallelWorkers(ParallelContext *pcxt, int nworkers_to_launch) { /* * The number of workers that need to be launched must be less than the - * number of workers with which the parallel context is initialized. + * number of workers with which the parallel context is initialized. But + * the caller might not know that InitializeParallelDSM reduced nworkers, + * so just silently trim the request. */ - Assert(pcxt->nworkers >= nworkers_to_launch); - pcxt->nworkers_to_launch = nworkers_to_launch; + pcxt->nworkers_to_launch = Min(pcxt->nworkers, nworkers_to_launch); } /* @@ -1010,7 +1031,7 @@ ParallelContextActive(void) * * Note: this is called within a signal handler! All we can do is set * a flag that will cause the next CHECK_FOR_INTERRUPTS() to invoke - * HandleParallelMessages(). + * ProcessParallelMessages(). */ void HandleParallelMessageInterrupt(void) @@ -1021,10 +1042,10 @@ HandleParallelMessageInterrupt(void) } /* - * Handle any queued protocol messages received from parallel workers. + * Process any queued protocol messages received from parallel workers. */ void -HandleParallelMessages(void) +ProcessParallelMessages(void) { dlist_iter iter; MemoryContext oldcontext; @@ -1047,7 +1068,7 @@ HandleParallelMessages(void) */ if (hpm_context == NULL) /* first time through? */ hpm_context = AllocSetContextCreate(TopMemoryContext, - "HandleParallelMessages", + "ProcessParallelMessages", ALLOCSET_DEFAULT_SIZES); else MemoryContextReset(hpm_context); @@ -1090,7 +1111,7 @@ HandleParallelMessages(void) initStringInfo(&msg); appendBinaryStringInfo(&msg, data, nbytes); - HandleParallelMessage(pcxt, i, &msg); + ProcessParallelMessage(pcxt, i, &msg); pfree(msg.data); } else @@ -1110,10 +1131,10 @@ HandleParallelMessages(void) } /* - * Handle a single protocol message received from a single parallel worker. + * Process a single protocol message received from a single parallel worker. */ static void -HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg) +ProcessParallelMessage(ParallelContext *pcxt, int i, StringInfo msg) { char msgtype; @@ -1191,7 +1212,7 @@ HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg) break; } - case 'P': /* Parallel progress reporting */ + case PqMsg_Progress: { /* * Only incremental progress reporting is currently supported. @@ -1391,16 +1412,37 @@ ParallelWorkerMain(Datum main_arg) entrypt = LookupParallelWorkerFunction(library_name, function_name); - /* Restore database connection. */ + /* + * Restore current session authorization and role id. No verification + * happens here, we just blindly adopt the leader's state. Note that this + * has to happen before InitPostgres, since InitializeSessionUserId will + * not set these variables. + */ + SetAuthenticatedUserId(fps->authenticated_user_id); + SetSessionAuthorization(fps->session_user_id, + fps->session_user_is_superuser); + SetCurrentRoleId(fps->outer_user_id, fps->role_is_superuser); + + /* + * Restore database connection. We skip connection authorization checks, + * reasoning that (a) the leader checked these things when it started, and + * (b) we do not want parallel mode to cause these failures, because that + * would make use of parallel query plans not transparent to applications. + */ BackgroundWorkerInitializeConnectionByOid(fps->database_id, fps->authenticated_user_id, - 0); + BGWORKER_BYPASS_ALLOWCONN | + BGWORKER_BYPASS_ROLELOGINCHECK); /* * Set the client encoding to the database encoding, since that is what - * the leader will expect. + * the leader will expect. (We're cheating a bit by not calling + * PrepareClientEncoding first. It's okay because this call will always + * result in installing a no-op conversion. No error should be possible, + * but check anyway.) */ - SetClientEncoding(GetDatabaseEncoding()); + if (SetClientEncoding(GetDatabaseEncoding()) < 0) + elog(ERROR, "SetClientEncoding(%d) failed", GetDatabaseEncoding()); /* * Load libraries that were loaded by original backend. We want to do @@ -1410,17 +1452,25 @@ ParallelWorkerMain(Datum main_arg) libraryspace = shm_toc_lookup(toc, PARALLEL_KEY_LIBRARY, false); StartTransactionCommand(); RestoreLibraryState(libraryspace); - - /* Restore GUC values from launching backend. */ - gucspace = shm_toc_lookup(toc, PARALLEL_KEY_GUC, false); - RestoreGUCState(gucspace); CommitTransactionCommand(); /* Crank up a transaction state appropriate to a parallel worker. */ tstatespace = shm_toc_lookup(toc, PARALLEL_KEY_TRANSACTION_STATE, false); StartParallelWorkerTransaction(tstatespace); - /* Restore combo CID state. */ + /* + * Restore state that affects catalog access. Ideally we'd do this even + * before calling InitPostgres, but that has order-of-initialization + * problems, and also the relmapper would get confused during the + * CommitTransactionCommand call above. + */ + pendingsyncsspace = shm_toc_lookup(toc, PARALLEL_KEY_PENDING_SYNCS, + false); + RestorePendingSyncs(pendingsyncsspace); + relmapperspace = shm_toc_lookup(toc, PARALLEL_KEY_RELMAPPER_STATE, false); + RestoreRelationMap(relmapperspace); + reindexspace = shm_toc_lookup(toc, PARALLEL_KEY_REINDEX_STATE, false); + RestoreReindexState(reindexspace); combocidspace = shm_toc_lookup(toc, PARALLEL_KEY_COMBO_CID, false); RestoreComboCIDState(combocidspace); @@ -1456,32 +1506,29 @@ ParallelWorkerMain(Datum main_arg) InvalidateSystemCaches(); /* - * Restore current role id. Skip verifying whether session user is - * allowed to become this role and blindly restore the leader's state for - * current role. + * Restore GUC values from launching backend. We can't do this earlier, + * because GUC check hooks that do catalog lookups need to see the same + * database state as the leader. Also, the check hooks for + * session_authorization and role assume we already set the correct role + * OIDs. */ - SetCurrentRoleId(fps->outer_user_id, fps->is_superuser); + gucspace = shm_toc_lookup(toc, PARALLEL_KEY_GUC, false); + RestoreGUCState(gucspace); - /* Restore user ID and security context. */ + /* + * Restore current user ID and security context. No verification happens + * here, we just blindly adopt the leader's state. We can't do this till + * after restoring GUCs, else we'll get complaints about restoring + * session_authorization and role. (In effect, we're assuming that all + * the restored values are okay to set, even if we are now inside a + * restricted context.) + */ SetUserIdAndSecContext(fps->current_user_id, fps->sec_context); /* Restore temp-namespace state to ensure search path matches leader's. */ SetTempNamespaceState(fps->temp_namespace_id, fps->temp_toast_namespace_id); - /* Restore pending syncs. */ - pendingsyncsspace = shm_toc_lookup(toc, PARALLEL_KEY_PENDING_SYNCS, - false); - RestorePendingSyncs(pendingsyncsspace); - - /* Restore reindex state. */ - reindexspace = shm_toc_lookup(toc, PARALLEL_KEY_REINDEX_STATE, false); - RestoreReindexState(reindexspace); - - /* Restore relmapper state. */ - relmapperspace = shm_toc_lookup(toc, PARALLEL_KEY_RELMAPPER_STATE, false); - RestoreRelationMap(relmapperspace); - /* Restore uncommitted enums. */ uncommittedenumsspace = shm_toc_lookup(toc, PARALLEL_KEY_UNCOMMITTEDENUMS, false); diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index 248aa1a6553b6..fe56286d9a972 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -49,7 +49,7 @@ * by re-setting the page's page_dirty flag. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/slru.c @@ -70,7 +70,7 @@ #include "pgstat.h" #include "storage/fd.h" #include "storage/shmem.h" -#include "utils/guc_hooks.h" +#include "utils/guc.h" /* * Converts segment number to the filename of the segment. @@ -100,8 +100,7 @@ SlruFileName(SlruCtl ctl, char *path, int64 segno) * that in the future we can't decrease SLRU_PAGES_PER_SEGMENT easily. */ Assert(segno >= 0 && segno <= INT64CONST(0xFFFFFFFFFFFFFFF)); - return snprintf(path, MAXPGPATH, "%s/%015llX", ctl->Dir, - (long long) segno); + return snprintf(path, MAXPGPATH, "%s/%015" PRIX64, ctl->Dir, segno); } else { @@ -343,7 +342,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, ctl->shared = shared; ctl->sync_handler = sync_handler; ctl->long_segment_names = long_segment_names; - ctl->bank_mask = (nslots / SLRU_BANK_SIZE) - 1; + ctl->nbanks = nbanks; strlcpy(ctl->Dir, subdir, sizeof(ctl->Dir)); } @@ -358,7 +357,7 @@ check_slru_buffers(const char *name, int *newval) if (*newval % SLRU_BANK_SIZE == 0) return true; - GUC_check_errdetail("\"%s\" must be a multiple of %d", name, + GUC_check_errdetail("\"%s\" must be a multiple of %d.", name, SLRU_BANK_SIZE); return false; } @@ -606,7 +605,7 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid) { SlruShared shared = ctl->shared; LWLock *banklock = SimpleLruGetBankLock(ctl, pageno); - int bankno = pageno & ctl->bank_mask; + int bankno = pageno % ctl->nbanks; int bankstart = bankno * SLRU_BANK_SIZE; int bankend = bankstart + SLRU_BANK_SIZE; @@ -716,9 +715,12 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruWriteAll fdata) if (!ok) SlruReportIOError(ctl, pageno, InvalidTransactionId); - /* If part of a checkpoint, count this as a buffer written. */ + /* If part of a checkpoint, count this as a SLRU buffer written. */ if (fdata) - CheckpointStats.ckpt_bufs_written++; + { + CheckpointStats.ckpt_slru_written++; + PendingCheckpointerStats.slru_written++; + } } /* @@ -1177,14 +1179,14 @@ SlruSelectLRUPage(SlruCtl ctl, int64 pageno) int bestinvalidslot = 0; /* keep compiler quiet */ int best_invalid_delta = -1; int64 best_invalid_page_number = 0; /* keep compiler quiet */ - int bankno = pageno & ctl->bank_mask; + int bankno = pageno % ctl->nbanks; int bankstart = bankno * SLRU_BANK_SIZE; int bankend = bankstart + SLRU_BANK_SIZE; Assert(LWLockHeldByMe(SimpleLruGetBankLock(ctl, pageno))); /* See if page already has a buffer assigned */ - for (int slotno = 0; slotno < shared->num_slots; slotno++) + for (int slotno = bankstart; slotno < bankend; slotno++) { if (shared->page_status[slotno] != SLRU_PAGE_EMPTY && shared->page_number[slotno] == pageno) @@ -1532,7 +1534,7 @@ SlruDeleteSegment(SlruCtl ctl, int64 segno) did_write = false; for (int slotno = 0; slotno < shared->num_slots; slotno++) { - int pagesegno; + int64 pagesegno; int curbank = SlotGetBankNumber(slotno); /* diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c index 50bb1d8cfc5f0..15153618fad16 100644 --- a/src/backend/access/transam/subtrans.c +++ b/src/backend/access/transam/subtrans.c @@ -19,7 +19,7 @@ * data across crashes. During database startup, we simply force the * currently-active page of SUBTRANS to zeroes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/subtrans.c diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c index 146751ae37526..a27f27cc037d1 100644 --- a/src/backend/access/transam/timeline.c +++ b/src/backend/access/transam/timeline.c @@ -21,7 +21,7 @@ * The fields are separated by tabs. Lines beginning with # are comments, and * are ignored. Empty lines are also ignored. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/timeline.c diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c index 75b5325df8b28..9a39451a29a96 100644 --- a/src/backend/access/transam/transam.c +++ b/src/backend/access/transam/transam.c @@ -3,7 +3,7 @@ * transam.c * postgres transaction (commit) log interface routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index e98286d768b07..73a80559194e7 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -3,7 +3,7 @@ * twophase.c * Two-phase commit support functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -466,7 +466,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid, proc->databaseId = databaseid; proc->roleId = owner; proc->tempNamespaceId = InvalidOid; - proc->isBackgroundWorker = false; + proc->isRegularBackend = false; proc->lwWaiting = LW_WS_NOT_WAITING; proc->lwWaitMode = 0; proc->waitLock = NULL; @@ -747,7 +747,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS) * out as a result set. */ status = (Working_State *) palloc(sizeof(Working_State)); - funcctx->user_fctx = (void *) status; + funcctx->user_fctx = status; status->ngxacts = GetPreparedTransactionList(&status->array); status->currIdx = 0; @@ -929,32 +929,16 @@ TwoPhaseGetDummyProc(TransactionId xid, bool lock_held) /* * Compute the FullTransactionId for the given TransactionId. * - * The wrap logic is safe here because the span of active xids cannot exceed one - * epoch at any given time. + * This is safe if the xid has not yet reached COMMIT PREPARED or ROLLBACK + * PREPARED. After those commands, concurrent vac_truncate_clog() may make + * the xid cease to qualify as allowable. XXX Not all callers limit their + * calls accordingly. */ static inline FullTransactionId AdjustToFullTransactionId(TransactionId xid) { - FullTransactionId nextFullXid; - TransactionId nextXid; - uint32 epoch; - Assert(TransactionIdIsValid(xid)); - - LWLockAcquire(XidGenLock, LW_SHARED); - nextFullXid = TransamVariables->nextXid; - LWLockRelease(XidGenLock); - - nextXid = XidFromFullTransactionId(nextFullXid); - epoch = EpochFromFullTransactionId(nextFullXid); - if (unlikely(xid > nextXid)) - { - /* Wraparound occurred, must be from a prev epoch. */ - Assert(epoch > 0); - epoch--; - } - - return FullTransactionIdFromEpochAndXid(epoch, xid); + return FullTransactionIdFromAllowableAt(ReadNextFullTransactionId(), xid); } static inline int @@ -1505,6 +1489,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit) GlobalTransaction gxact; PGPROC *proc; TransactionId xid; + bool ondisk; char *buf; char *bufptr; TwoPhaseFileHeader *hdr; @@ -1657,6 +1642,12 @@ FinishPreparedTransaction(const char *gid, bool isCommit) PredicateLockTwoPhaseFinish(xid, isCommit); + /* + * Read this value while holding the two-phase lock, as the on-disk 2PC + * file is physically removed after the lock is released. + */ + ondisk = gxact->ondisk; + /* Clear shared memory state */ RemoveGXact(gxact); @@ -1672,7 +1663,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit) /* * And now we can clean up any files we may have left. */ - if (gxact->ondisk) + if (ondisk) RemoveTwoPhaseFile(xid, true); MyLockedGxact = NULL; @@ -1700,8 +1691,7 @@ ProcessRecords(char *bufptr, TransactionId xid, bufptr += MAXALIGN(sizeof(TwoPhaseRecordOnDisk)); if (callbacks[record->rmid] != NULL) - callbacks[record->rmid] (xid, record->info, - (void *) bufptr, record->len); + callbacks[record->rmid] (xid, record->info, bufptr, record->len); bufptr += MAXALIGN(record->len); } diff --git a/src/backend/access/transam/twophase_rmgr.c b/src/backend/access/transam/twophase_rmgr.c index 15b797f34b3af..b638e0949e77e 100644 --- a/src/backend/access/transam/twophase_rmgr.c +++ b/src/backend/access/transam/twophase_rmgr.c @@ -3,7 +3,7 @@ * twophase_rmgr.c * Two-phase-commit resource managers tables * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index fb6a86afcb134..fe895787cb72d 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -3,7 +3,7 @@ * varsup.c * postgres OID & XID variables support routines * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/transam/varsup.c @@ -153,14 +153,14 @@ GetNewTransactionId(bool isSubXact) if (oldest_datname) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("database is not accepting commands that assign new XIDs to avoid wraparound data loss in database \"%s\"", + errmsg("database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"", oldest_datname), errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("database is not accepting commands that assign new XIDs to avoid wraparound data loss in database with OID %u", + errmsg("database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u", oldest_datoid), errhint("Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); @@ -175,7 +175,7 @@ GetNewTransactionId(bool isSubXact) (errmsg("database \"%s\" must be vacuumed within %u transactions", oldest_datname, xidWrapLimit - xid), - errhint("To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" + errhint("To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots."))); else ereport(WARNING, diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index d119ab909dc6d..b885513f76541 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -5,7 +5,7 @@ * * See src/backend/access/transam/README for more information. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -51,6 +51,7 @@ #include "replication/origin.h" #include "replication/snapbuild.h" #include "replication/syncrep.h" +#include "storage/aio_subsys.h" #include "storage/condition_variable.h" #include "storage/fd.h" #include "storage/lmgr.h" @@ -69,6 +70,7 @@ #include "utils/snapmgr.h" #include "utils/timeout.h" #include "utils/timestamp.h" +#include "utils/typcache.h" /* * User-tweakable parameters @@ -647,7 +649,7 @@ AssignTransactionId(TransactionState s) if (IsInParallelMode() || IsParallelWorker()) ereport(ERROR, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("cannot assign XIDs during a parallel operation"))); + errmsg("cannot assign transaction IDs during a parallel operation"))); /* * Ensure parent(s) have XIDs, so that a child always has an XID later @@ -769,8 +771,8 @@ AssignTransactionId(TransactionState s) xlrec.nsubxacts = nUnreportedXids; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment); - XLogRegisterData((char *) unreportedXids, + XLogRegisterData(&xlrec, MinSizeOfXactAssignment); + XLogRegisterData(unreportedXids, nUnreportedXids * sizeof(TransactionId)); (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT); @@ -1367,14 +1369,24 @@ RecordTransactionCommit(void) /* * Transactions without an assigned xid can contain invalidation - * messages (e.g. explicit relcache invalidations or catcache - * invalidations for inplace updates); standbys need to process those. - * We can't emit a commit record without an xid, and we don't want to - * force assigning an xid, because that'd be problematic for e.g. - * vacuum. Hence we emit a bespoke record for the invalidations. We - * don't want to use that in case a commit record is emitted, so they - * happen synchronously with commits (besides not wanting to emit more - * WAL records). + * messages. While inplace updates do this, this is not known to be + * necessary; see comment at inplace CacheInvalidateHeapTuple(). + * Extensions might still rely on this capability, and standbys may + * need to process those invals. We can't emit a commit record + * without an xid, and we don't want to force assigning an xid, + * because that'd be problematic for e.g. vacuum. Hence we emit a + * bespoke record for the invalidations. We don't want to use that in + * case a commit record is emitted, so they happen synchronously with + * commits (besides not wanting to emit more WAL records). + * + * XXX Every known use of this capability is a defect. Since an XID + * isn't controlling visibility of the change that prompted invals, + * other sessions need the inval even if this transactions aborts. + * + * ON COMMIT DELETE ROWS does a nontransactional index_build(), which + * queues a relcache inval, including in transactions without an xid + * that had read the (empty) table. Standbys don't need any ON COMMIT + * DELETE ROWS invals, but we've not done the work to withhold them. */ if (nmsgs != 0) { @@ -2400,12 +2412,17 @@ CommitTransaction(void) RESOURCE_RELEASE_BEFORE_LOCKS, true, true); + AtEOXact_Aio(true); + /* Check we've released all buffer pins */ AtEOXact_Buffers(true); /* Clean up the relation cache */ AtEOXact_RelationCache(true); + /* Clean up the type cache */ + AtEOXact_TypeCache(); + /* * Make catalog changes visible to all backends. This has to happen after * relcache references are dropped (see comments for @@ -2702,12 +2719,17 @@ PrepareTransaction(void) RESOURCE_RELEASE_BEFORE_LOCKS, true, true); + AtEOXact_Aio(true); + /* Check we've released all buffer pins */ AtEOXact_Buffers(true); /* Clean up the relation cache */ AtEOXact_RelationCache(true); + /* Clean up the type cache */ + AtEOXact_TypeCache(); + /* notify doesn't need a postprepare call */ PostPrepare_PgStat(); @@ -2813,7 +2835,9 @@ AbortTransaction(void) pgstat_report_wait_end(); pgstat_progress_end_command(); - /* Clean up buffer context locks, too */ + pgaio_error_cleanup(); + + /* Clean up buffer content locks, too */ UnlockBuffers(); /* Reset WAL record construction state */ @@ -2943,8 +2967,10 @@ AbortTransaction(void) ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); + AtEOXact_Aio(false); AtEOXact_Buffers(false); AtEOXact_RelationCache(false); + AtEOXact_TypeCache(); AtEOXact_Inval(false); AtEOXact_MultiXact(); ResourceOwnerRelease(TopTransactionResourceOwner, @@ -3641,16 +3667,6 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType) errmsg("%s cannot run inside a subtransaction", stmtType))); - /* - * inside a pipeline that has started an implicit transaction? - */ - if (MyXactFlags & XACT_FLAGS_PIPELINING) - ereport(ERROR, - (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), - /* translator: %s represents an SQL statement name */ - errmsg("%s cannot be executed within a pipeline", - stmtType))); - /* * inside a function call? */ @@ -3762,9 +3778,6 @@ IsInTransactionBlock(bool isTopLevel) if (IsSubTransaction()) return true; - if (MyXactFlags & XACT_FLAGS_PIPELINING) - return true; - if (!isTopLevel) return true; @@ -5147,6 +5160,7 @@ CommitSubTransaction(void) true, false); AtEOSubXact_RelationCache(true, s->subTransactionId, s->parent->subTransactionId); + AtEOSubXact_TypeCache(); AtEOSubXact_Inval(true); AtSubCommit_smgr(); @@ -5226,6 +5240,9 @@ AbortSubTransaction(void) pgstat_report_wait_end(); pgstat_progress_end_command(); + + pgaio_error_cleanup(); + UnlockBuffers(); /* Reset WAL record construction state */ @@ -5320,8 +5337,10 @@ AbortSubTransaction(void) RESOURCE_RELEASE_BEFORE_LOCKS, false, false); + AtEOXact_Aio(false); AtEOSubXact_RelationCache(false, s->subTransactionId, s->parent->subTransactionId); + AtEOSubXact_TypeCache(); AtEOSubXact_Inval(false); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_LOCKS, @@ -5902,54 +5921,54 @@ XactLogCommitRecord(TimestampTz commit_time, XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), sizeof(xl_xact_commit)); + XLogRegisterData(&xlrec, sizeof(xl_xact_commit)); if (xl_xinfo.xinfo != 0) - XLogRegisterData((char *) (&xl_xinfo.xinfo), sizeof(xl_xinfo.xinfo)); + XLogRegisterData(&xl_xinfo.xinfo, sizeof(xl_xinfo.xinfo)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO) - XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo)); + XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS) { - XLogRegisterData((char *) (&xl_subxacts), + XLogRegisterData(&xl_subxacts, MinSizeOfXactSubxacts); - XLogRegisterData((char *) subxacts, + XLogRegisterData(subxacts, nsubxacts * sizeof(TransactionId)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS) { - XLogRegisterData((char *) (&xl_relfilelocators), + XLogRegisterData(&xl_relfilelocators, MinSizeOfXactRelfileLocators); - XLogRegisterData((char *) rels, + XLogRegisterData(rels, nrels * sizeof(RelFileLocator)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS) { - XLogRegisterData((char *) (&xl_dropped_stats), + XLogRegisterData(&xl_dropped_stats, MinSizeOfXactStatsItems); - XLogRegisterData((char *) droppedstats, + XLogRegisterData(droppedstats, ndroppedstats * sizeof(xl_xact_stats_item)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS) { - XLogRegisterData((char *) (&xl_invals), MinSizeOfXactInvals); - XLogRegisterData((char *) msgs, + XLogRegisterData(&xl_invals, MinSizeOfXactInvals); + XLogRegisterData(msgs, nmsgs * sizeof(SharedInvalidationMessage)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE) { - XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase)); + XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID) - XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1); + XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN) - XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin)); + XLogRegisterData(&xl_origin, sizeof(xl_xact_origin)); /* we allow filtering by xacts */ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); @@ -6055,47 +6074,47 @@ XactLogAbortRecord(TimestampTz abort_time, XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), MinSizeOfXactAbort); + XLogRegisterData(&xlrec, MinSizeOfXactAbort); if (xl_xinfo.xinfo != 0) - XLogRegisterData((char *) (&xl_xinfo), sizeof(xl_xinfo)); + XLogRegisterData(&xl_xinfo, sizeof(xl_xinfo)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO) - XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo)); + XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS) { - XLogRegisterData((char *) (&xl_subxacts), + XLogRegisterData(&xl_subxacts, MinSizeOfXactSubxacts); - XLogRegisterData((char *) subxacts, + XLogRegisterData(subxacts, nsubxacts * sizeof(TransactionId)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS) { - XLogRegisterData((char *) (&xl_relfilelocators), + XLogRegisterData(&xl_relfilelocators, MinSizeOfXactRelfileLocators); - XLogRegisterData((char *) rels, + XLogRegisterData(rels, nrels * sizeof(RelFileLocator)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS) { - XLogRegisterData((char *) (&xl_dropped_stats), + XLogRegisterData(&xl_dropped_stats, MinSizeOfXactStatsItems); - XLogRegisterData((char *) droppedstats, + XLogRegisterData(droppedstats, ndroppedstats * sizeof(xl_xact_stats_item)); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE) { - XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase)); + XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase)); if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID) - XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1); + XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1); } if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN) - XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin)); + XLogRegisterData(&xl_origin, sizeof(xl_xact_origin)); /* Include the replication origin */ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f86f4b5c4b73b..47ffc0a230772 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -28,7 +28,7 @@ * the current system state, and for starting/stopping backups. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlog.c @@ -73,7 +73,6 @@ #include "pg_trace.h" #include "pgstat.h" #include "port/atomics.h" -#include "port/pg_iovec.h" #include "postmaster/bgwriter.h" #include "postmaster/startup.h" #include "postmaster/walsummarizer.h" @@ -97,7 +96,6 @@ #include "utils/guc_hooks.h" #include "utils/guc_tables.h" #include "utils/injection_point.h" -#include "utils/memutils.h" #include "utils/ps_status.h" #include "utils/relmapper.h" #include "utils/snapmgr.h" @@ -105,6 +103,10 @@ #include "utils/timestamp.h" #include "utils/varlena.h" +#ifdef WAL_DEBUG +#include "utils/memutils.h" +#endif + /* timeline ID to be used when bootstrapping */ #define BootstrapTimeLineID 1 @@ -300,11 +302,6 @@ static bool doPageWrites; * so it's a plain spinlock. The other locks are held longer (potentially * over I/O operations), so we use LWLocks for them. These locks are: * - * WALBufMappingLock: must be held to replace a page in the WAL buffer cache. - * It is only held while initializing and changing the mapping. If the - * contents of the buffer being replaced haven't been written yet, the mapping - * lock is released while the write is done, and reacquired afterwards. - * * WALWriteLock: must be held to write WAL buffers to disk (XLogWrite or * XLogFlush). * @@ -471,21 +468,37 @@ typedef struct XLogCtlData pg_atomic_uint64 logFlushResult; /* last byte + 1 flushed */ /* - * Latest initialized page in the cache (last byte position + 1). + * First initialized page in the cache (first byte position). + */ + XLogRecPtr InitializedFrom; + + /* + * Latest reserved for initialization page in the cache (last byte + * position + 1). * - * To change the identity of a buffer (and InitializedUpTo), you need to - * hold WALBufMappingLock. To change the identity of a buffer that's + * To change the identity of a buffer, you need to advance + * InitializeReserved first. To change the identity of a buffer that's * still dirty, the old page needs to be written out first, and for that * you need WALWriteLock, and you need to ensure that there are no * in-progress insertions to the page by calling * WaitXLogInsertionsToFinish(). */ - XLogRecPtr InitializedUpTo; + pg_atomic_uint64 InitializeReserved; + + /* + * Latest initialized page in the cache (last byte position + 1). + * + * InitializedUpTo is updated after the buffer initialization. After + * update, waiters got notification using InitializedUpToCondVar. + */ + pg_atomic_uint64 InitializedUpTo; + ConditionVariable InitializedUpToCondVar; /* * These values do not change after startup, although the pointed-to pages - * and xlblocks values certainly do. xlblocks values are protected by - * WALBufMappingLock. + * and xlblocks values certainly do. xlblocks values are changed + * lock-free according to the check for the xlog write position and are + * accompanied by changes of InitializeReserved and InitializedUpTo. */ char *pages; /* buffers for unwritten XLOG pages */ pg_atomic_uint64 *xlblocks; /* 1st byte ptr-s + XLOG_BLCKSZ */ @@ -552,7 +565,7 @@ typedef struct XLogCtlData } XLogCtlData; /* - * Classification of XLogRecordInsert operations. + * Classification of XLogInsertRecord operations. */ typedef enum { @@ -808,9 +821,9 @@ XLogInsertRecord(XLogRecData *rdata, * fullPageWrites from changing until the insertion is finished. * * Step 2 can usually be done completely in parallel. If the required WAL - * page is not initialized yet, you have to grab WALBufMappingLock to - * initialize it, but the WAL writer tries to do that ahead of insertions - * to avoid that from happening in the critical path. + * page is not initialized yet, you have to go through AdvanceXLInsertBuffer, + * which will ensure it is initialized. But the WAL writer tries to do that + * ahead of insertions to avoid that from happening in the critical path. * *---------- */ @@ -1247,7 +1260,7 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata, written = 0; while (rdata != NULL) { - char *rdata_data = rdata->data; + const char *rdata_data = rdata->data; int rdata_len = rdata->len; while (rdata_len > freespace) @@ -1989,32 +2002,79 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) XLogRecPtr NewPageEndPtr = InvalidXLogRecPtr; XLogRecPtr NewPageBeginPtr; XLogPageHeader NewPage; + XLogRecPtr ReservedPtr; int npages pg_attribute_unused() = 0; - LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE); - /* - * Now that we have the lock, check if someone initialized the page - * already. + * We must run the loop below inside the critical section as we expect + * XLogCtl->InitializedUpTo to eventually keep up. The most of callers + * already run inside the critical section. Except for WAL writer, which + * passed 'opportunistic == true', and therefore we don't perform + * operations that could error out. + * + * Start an explicit critical section anyway though. + */ + Assert(CritSectionCount > 0 || opportunistic); + START_CRIT_SECTION(); + + /*-- + * Loop till we get all the pages in WAL buffer before 'upto' reserved for + * initialization. Multiple process can initialize different buffers with + * this loop in parallel as following. + * + * 1. Reserve page for initialization using XLogCtl->InitializeReserved. + * 2. Initialize the reserved page. + * 3. Attempt to advance XLogCtl->InitializedUpTo, */ - while (upto >= XLogCtl->InitializedUpTo || opportunistic) + ReservedPtr = pg_atomic_read_u64(&XLogCtl->InitializeReserved); + while (upto >= ReservedPtr || opportunistic) { - nextidx = XLogRecPtrToBufIdx(XLogCtl->InitializedUpTo); + Assert(ReservedPtr % XLOG_BLCKSZ == 0); /* - * Get ending-offset of the buffer page we need to replace (this may - * be zero if the buffer hasn't been used yet). Fall through if it's - * already written out. + * Get ending-offset of the buffer page we need to replace. + * + * We don't lookup into xlblocks, but rather calculate position we + * must wait to be written. If it was written, xlblocks will have this + * position (or uninitialized) */ - OldPageRqstPtr = pg_atomic_read_u64(&XLogCtl->xlblocks[nextidx]); - if (LogwrtResult.Write < OldPageRqstPtr) + if (ReservedPtr + XLOG_BLCKSZ > XLogCtl->InitializedFrom + XLOG_BLCKSZ * XLOGbuffers) + OldPageRqstPtr = ReservedPtr + XLOG_BLCKSZ - (XLogRecPtr) XLOG_BLCKSZ * XLOGbuffers; + else + OldPageRqstPtr = InvalidXLogRecPtr; + + if (LogwrtResult.Write < OldPageRqstPtr && opportunistic) { /* - * Nope, got work to do. If we just want to pre-initialize as much - * as we can without flushing, give up now. + * If we just want to pre-initialize as much as we can without + * flushing, give up now. */ - if (opportunistic) - break; + upto = ReservedPtr - 1; + break; + } + + /* + * Attempt to reserve the page for initialization. Failure means that + * this page got reserved by another process. + */ + if (!pg_atomic_compare_exchange_u64(&XLogCtl->InitializeReserved, + &ReservedPtr, + ReservedPtr + XLOG_BLCKSZ)) + continue; + + /* + * Wait till page gets correctly initialized up to OldPageRqstPtr. + */ + nextidx = XLogRecPtrToBufIdx(ReservedPtr); + while (pg_atomic_read_u64(&XLogCtl->InitializedUpTo) < OldPageRqstPtr) + ConditionVariableSleep(&XLogCtl->InitializedUpToCondVar, WAIT_EVENT_WAL_BUFFER_INIT); + ConditionVariableCancelSleep(); + Assert(pg_atomic_read_u64(&XLogCtl->xlblocks[nextidx]) == OldPageRqstPtr); + + /* Fall through if it's already written out. */ + if (LogwrtResult.Write < OldPageRqstPtr) + { + /* Nope, got work to do. */ /* Advance shared memory write request position */ SpinLockAcquire(&XLogCtl->info_lck); @@ -2029,14 +2089,6 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) RefreshXLogWriteResult(LogwrtResult); if (LogwrtResult.Write < OldPageRqstPtr) { - /* - * Must acquire write lock. Release WALBufMappingLock first, - * to make sure that all insertions that we need to wait for - * can finish (up to this same position). Otherwise we risk - * deadlock. - */ - LWLockRelease(WALBufMappingLock); - WaitXLogInsertionsToFinish(OldPageRqstPtr); LWLockAcquire(WALWriteLock, LW_EXCLUSIVE); @@ -2055,12 +2107,9 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) WriteRqst.Flush = 0; XLogWrite(WriteRqst, tli, false); LWLockRelease(WALWriteLock); - PendingWalStats.wal_buffers_full++; + pgWalUsage.wal_buffers_full++; TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE(); } - /* Re-acquire WALBufMappingLock and retry */ - LWLockAcquire(WALBufMappingLock, LW_EXCLUSIVE); - continue; } } @@ -2068,11 +2117,9 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) * Now the next buffer slot is free and we can set it up to be the * next output page. */ - NewPageBeginPtr = XLogCtl->InitializedUpTo; + NewPageBeginPtr = ReservedPtr; NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ; - Assert(XLogRecPtrToBufIdx(NewPageBeginPtr) == nextidx); - NewPage = (XLogPageHeader) (XLogCtl->pages + nextidx * (Size) XLOG_BLCKSZ); /* @@ -2087,7 +2134,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) * Be sure to re-zero the buffer so that bytes beyond what we've * written will look like zeroes and not valid XLOG records... */ - MemSet((char *) NewPage, 0, XLOG_BLCKSZ); + MemSet(NewPage, 0, XLOG_BLCKSZ); /* * Fill the new page's header @@ -2136,12 +2183,100 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic) */ pg_write_barrier(); + /*----- + * Update the value of XLogCtl->xlblocks[nextidx] and try to advance + * XLogCtl->InitializedUpTo in a lock-less manner. + * + * First, let's provide a formal proof of the algorithm. Let it be 'n' + * process with the following variables in shared memory: + * f - an array of 'n' boolean flags, + * v - atomic integer variable. + * + * Also, let + * i - a number of a process, + * j - local integer variable, + * CAS(var, oldval, newval) - compare-and-swap atomic operation + * returning true on success, + * write_barrier()/read_barrier() - memory barriers. + * + * The pseudocode for each process is the following. + * + * j := i + * f[i] := true + * write_barrier() + * while CAS(v, j, j + 1): + * j := j + 1 + * read_barrier() + * if not f[j]: + * break + * + * Let's prove that v eventually reaches the value of n. + * 1. Prove by contradiction. Assume v doesn't reach n and stucks + * on k, where k < n. + * 2. Process k attempts CAS(v, k, k + 1). 1). If, as we assumed, v + * gets stuck at k, then this CAS operation must fail. Therefore, + * v < k when process k attempts CAS(v, k, k + 1). + * 3. If, as we assumed, v gets stuck at k, then the value k of v + * must be achieved by some process m, where m < k. The process + * m must observe f[k] == false. Otherwise, it will later attempt + * CAS(v, k, k + 1) with success. + * 4. Therefore, corresponding read_barrier() (while j == k) on + * process m reached before write_barrier() of process k. But then + * process k attempts CAS(v, k, k + 1) after process m successfully + * incremented v to k, and that CAS operation must succeed. + * That leads to a contradiction. So, there is no such k (k < n) + * where v gets stuck. Q.E.D. + * + * To apply this proof to the code below, we assume + * XLogCtl->InitializedUpTo will play the role of v with XLOG_BLCKSZ + * granularity. We also assume setting XLogCtl->xlblocks[nextidx] to + * NewPageEndPtr to play the role of setting f[i] to true. Also, note + * that processes can't concurrently map different xlog locations to + * the same nextidx because we previously requested that + * XLogCtl->InitializedUpTo >= OldPageRqstPtr. So, a xlog buffer can + * be taken for initialization only once the previous initialization + * takes effect on XLogCtl->InitializedUpTo. + */ + pg_atomic_write_u64(&XLogCtl->xlblocks[nextidx], NewPageEndPtr); - XLogCtl->InitializedUpTo = NewPageEndPtr; + + pg_write_barrier(); + + while (pg_atomic_compare_exchange_u64(&XLogCtl->InitializedUpTo, &NewPageBeginPtr, NewPageEndPtr)) + { + NewPageBeginPtr = NewPageEndPtr; + NewPageEndPtr = NewPageBeginPtr + XLOG_BLCKSZ; + nextidx = XLogRecPtrToBufIdx(NewPageBeginPtr); + + pg_read_barrier(); + + if (pg_atomic_read_u64(&XLogCtl->xlblocks[nextidx]) != NewPageEndPtr) + { + /* + * Page at nextidx wasn't initialized yet, so we can't move + * InitializedUpto further. It will be moved by backend which + * will initialize nextidx. + */ + ConditionVariableBroadcast(&XLogCtl->InitializedUpToCondVar); + break; + } + } npages++; } - LWLockRelease(WALBufMappingLock); + + END_CRIT_SECTION(); + + /* + * All the pages in WAL buffer before 'upto' were reserved for + * initialization. However, some pages might be reserved by concurrent + * processes. Wait till they finish initialization. + */ + while (upto >= pg_atomic_read_u64(&XLogCtl->InitializedUpTo)) + ConditionVariableSleep(&XLogCtl->InitializedUpToCondVar, WAIT_EVENT_WAL_BUFFER_INIT); + ConditionVariableCancelSleep(); + + pg_read_barrier(); #ifdef WAL_DEBUG if (XLOG_DEBUG && npages > 0) @@ -2433,29 +2568,17 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible) { errno = 0; - /* Measure I/O timing to write WAL data */ - if (track_wal_io_timing) - INSTR_TIME_SET_CURRENT(start); - else - INSTR_TIME_SET_ZERO(start); + /* + * Measure I/O timing to write WAL data, for pg_stat_io. + */ + start = pgstat_prepare_io_time(track_wal_io_timing); pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE); written = pg_pwrite(openLogFile, from, nleft, startoffset); pgstat_report_wait_end(); - /* - * Increment the I/O timing and the number of times WAL data - * were written out to disk. - */ - if (track_wal_io_timing) - { - instr_time end; - - INSTR_TIME_SET_CURRENT(end); - INSTR_TIME_ACCUM_DIFF(PendingWalStats.wal_write_time, end, start); - } - - PendingWalStats.wal_write++; + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, + IOOP_WRITE, start, 1, written); if (written <= 0) { @@ -2668,8 +2791,14 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN) wakeup = true; } - if (wakeup && ProcGlobal->walwriterLatch) - SetLatch(ProcGlobal->walwriterLatch); + if (wakeup) + { + volatile PROC_HDR *procglobal = ProcGlobal; + ProcNumber walwriterProc = procglobal->walwriterProc; + + if (walwriterProc != INVALID_PROC_NUMBER) + SetLatch(&GetPGProcByNumber(walwriterProc)->procLatch); + } } /* @@ -3208,6 +3337,7 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, int fd; int save_errno; int open_flags = O_RDWR | O_CREAT | O_EXCL | PG_BINARY; + instr_time io_start; Assert(logtli != 0); @@ -3251,6 +3381,9 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, (errcode_for_file_access(), errmsg("could not create file \"%s\": %m", tmppath))); + /* Measure I/O timing when initializing segment */ + io_start = pgstat_prepare_io_time(track_wal_io_timing); + pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE); save_errno = 0; if (wal_init_zero) @@ -3286,6 +3419,14 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, } pgstat_report_wait_end(); + /* + * A full segment worth of data is written when using wal_init_zero. One + * byte is written when not using it. + */ + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_INIT, IOOP_WRITE, + io_start, 1, + wal_init_zero ? wal_segment_size : 1); + if (save_errno) { /* @@ -3302,6 +3443,9 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, errmsg("could not write to file \"%s\": %m", tmppath))); } + /* Measure I/O timing when flushing segment */ + io_start = pgstat_prepare_io_time(track_wal_io_timing); + pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC); if (pg_fsync(fd) != 0) { @@ -3314,6 +3458,9 @@ XLogFileInitInternal(XLogSegNo logsegno, TimeLineID logtli, } pgstat_report_wait_end(); + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_INIT, + IOOP_FSYNC, io_start, 1, 0); + if (close(fd) != 0) ereport(ERROR, (errcode_for_file_access(), @@ -4255,10 +4402,37 @@ WriteControlFile(void) ControlFile->float8ByVal = FLOAT8PASSBYVAL; + /* + * Initialize the default 'char' signedness. + * + * The signedness of the char type is implementation-defined. For instance + * on x86 architecture CPUs, the char data type is typically treated as + * signed by default, whereas on aarch architecture CPUs, it is typically + * treated as unsigned by default. In v17 or earlier, we accidentally let + * C implementation signedness affect persistent data. This led to + * inconsistent results when comparing char data across different + * platforms. + * + * This flag can be used as a hint to ensure consistent behavior for + * pre-v18 data files that store data sorted by the 'char' type on disk, + * especially in cross-platform replication scenarios. + * + * Newly created database clusters unconditionally set the default char + * signedness to true. pg_upgrade changes this flag for clusters that were + * initialized on signedness=false platforms. As a result, + * signedness=false setting will become rare over time. If we had known + * about this problem during the last development cycle that forced initdb + * (v8.3), we would have made all clusters signed or all clusters + * unsigned. Making pg_upgrade the only source of signedness=false will + * cause the population of database clusters to converge toward that + * retrospective ideal. + */ + ControlFile->default_char_signedness = true; + /* Contents are protected with a CRC */ INIT_CRC32C(ControlFile->crc); COMP_CRC32C(ControlFile->crc, - (char *) ControlFile, + ControlFile, offsetof(ControlFileData, crc)); FIN_CRC32C(ControlFile->crc); @@ -4314,7 +4488,7 @@ ReadControlFile(void) { pg_crc32c crc; int fd; - static char wal_segsz_str[20]; + char wal_segsz_str[20]; int r; /* @@ -4376,7 +4550,7 @@ ReadControlFile(void) /* Now check the CRC. */ INIT_CRC32C(crc); COMP_CRC32C(crc, - (char *) ControlFile, + ControlFile, offsetof(ControlFileData, crc)); FIN_CRC32C(crc); @@ -4394,17 +4568,21 @@ ReadControlFile(void) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with CATALOG_VERSION_NO %d," - " but the server was compiled with CATALOG_VERSION_NO %d.", - ControlFile->catalog_version_no, CATALOG_VERSION_NO), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "CATALOG_VERSION_NO", ControlFile->catalog_version_no, + "CATALOG_VERSION_NO", CATALOG_VERSION_NO), errhint("It looks like you need to initdb."))); if (ControlFile->maxAlign != MAXIMUM_ALIGNOF) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with MAXALIGN %d," - " but the server was compiled with MAXALIGN %d.", - ControlFile->maxAlign, MAXIMUM_ALIGNOF), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "MAXALIGN", ControlFile->maxAlign, + "MAXALIGN", MAXIMUM_ALIGNOF), errhint("It looks like you need to initdb."))); if (ControlFile->floatFormat != FLOATFORMAT_VALUE) ereport(FATAL, @@ -4416,57 +4594,71 @@ ReadControlFile(void) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with BLCKSZ %d," - " but the server was compiled with BLCKSZ %d.", - ControlFile->blcksz, BLCKSZ), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "BLCKSZ", ControlFile->blcksz, + "BLCKSZ", BLCKSZ), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->relseg_size != RELSEG_SIZE) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with RELSEG_SIZE %d," - " but the server was compiled with RELSEG_SIZE %d.", - ControlFile->relseg_size, RELSEG_SIZE), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "RELSEG_SIZE", ControlFile->relseg_size, + "RELSEG_SIZE", RELSEG_SIZE), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->xlog_blcksz != XLOG_BLCKSZ) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with XLOG_BLCKSZ %d," - " but the server was compiled with XLOG_BLCKSZ %d.", - ControlFile->xlog_blcksz, XLOG_BLCKSZ), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "XLOG_BLCKSZ", ControlFile->xlog_blcksz, + "XLOG_BLCKSZ", XLOG_BLCKSZ), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->nameDataLen != NAMEDATALEN) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with NAMEDATALEN %d," - " but the server was compiled with NAMEDATALEN %d.", - ControlFile->nameDataLen, NAMEDATALEN), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "NAMEDATALEN", ControlFile->nameDataLen, + "NAMEDATALEN", NAMEDATALEN), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->indexMaxKeys != INDEX_MAX_KEYS) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with INDEX_MAX_KEYS %d," - " but the server was compiled with INDEX_MAX_KEYS %d.", - ControlFile->indexMaxKeys, INDEX_MAX_KEYS), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "INDEX_MAX_KEYS", ControlFile->indexMaxKeys, + "INDEX_MAX_KEYS", INDEX_MAX_KEYS), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->toast_max_chunk_size != TOAST_MAX_CHUNK_SIZE) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d," - " but the server was compiled with TOAST_MAX_CHUNK_SIZE %d.", - ControlFile->toast_max_chunk_size, (int) TOAST_MAX_CHUNK_SIZE), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "TOAST_MAX_CHUNK_SIZE", ControlFile->toast_max_chunk_size, + "TOAST_MAX_CHUNK_SIZE", (int) TOAST_MAX_CHUNK_SIZE), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->loblksize != LOBLKSIZE) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database files are incompatible with server"), - errdetail("The database cluster was initialized with LOBLKSIZE %d," - " but the server was compiled with LOBLKSIZE %d.", - ControlFile->loblksize, (int) LOBLKSIZE), + /* translator: %s is a variable name and %d is its value */ + errdetail("The database cluster was initialized with %s %d," + " but the server was compiled with %s %d.", + "LOBLKSIZE", ControlFile->loblksize, + "LOBLKSIZE", (int) LOBLKSIZE), errhint("It looks like you need to recompile or initdb."))); #ifdef USE_FLOAT8_BYVAL @@ -4504,11 +4696,15 @@ ReadControlFile(void) /* check and update variables dependent on wal_segment_size */ if (ConvertToXSegs(min_wal_size_mb, wal_segment_size) < 2) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("\"min_wal_size\" must be at least twice \"wal_segment_size\""))); + /* translator: both %s are GUC names */ + errmsg("\"%s\" must be at least twice \"%s\"", + "min_wal_size", "wal_segment_size"))); if (ConvertToXSegs(max_wal_size_mb, wal_segment_size) < 2) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("\"max_wal_size\" must be at least twice \"wal_segment_size\""))); + /* translator: both %s are GUC names */ + errmsg("\"%s\" must be at least twice \"%s\"", + "max_wal_size", "wal_segment_size"))); UsableBytesInSegment = (wal_segment_size / XLOG_BLCKSZ * UsableBytesInPage) - @@ -4561,6 +4757,19 @@ DataChecksumsEnabled(void) return (ControlFile->data_checksum_version > 0); } +/* + * Return true if the cluster was initialized on a platform where the + * default signedness of char is "signed". This function exists for code + * that deals with pre-v18 data files that store data sorted by the 'char' + * type on disk (e.g., GIN and GiST indexes). See the comments in + * WriteControlFile() for details. + */ +bool +GetDefaultCharSignedness(void) +{ + return ControlFile->default_char_signedness; +} + /* * Returns a fake LSN for unlogged relations. * @@ -4715,7 +4924,9 @@ check_wal_consistency_checking(char **newval, void **extra, GucSource source) list_free(elemlist); /* assign new value */ - *extra = guc_malloc(ERROR, (RM_MAX_ID + 1) * sizeof(bool)); + *extra = guc_malloc(LOG, (RM_MAX_ID + 1) * sizeof(bool)); + if (!*extra) + return false; memcpy(*extra, newwalconsistency, (RM_MAX_ID + 1) * sizeof(bool)); return true; } @@ -4993,6 +5204,10 @@ XLOGShmemInit(void) pg_atomic_init_u64(&XLogCtl->logWriteResult, InvalidXLogRecPtr); pg_atomic_init_u64(&XLogCtl->logFlushResult, InvalidXLogRecPtr); pg_atomic_init_u64(&XLogCtl->unloggedLSN, InvalidXLogRecPtr); + + pg_atomic_init_u64(&XLogCtl->InitializeReserved, InvalidXLogRecPtr); + pg_atomic_init_u64(&XLogCtl->InitializedUpTo, InvalidXLogRecPtr); + ConditionVariableInit(&XLogCtl->InitializedUpToCondVar); } /* @@ -5168,9 +5383,9 @@ BootStrapXLOG(uint32 data_checksum_version) static char * str_time(pg_time_t tnow) { - static char buf[128]; + char *buf = palloc(128); - pg_strftime(buf, sizeof(buf), + pg_strftime(buf, 128, "%Y-%m-%d %H:%M:%S %Z", pg_localtime(&tnow, log_timezone)); @@ -5373,7 +5588,7 @@ CheckRequiredParameterValues(void) */ if (ArchiveRecoveryRequested && EnableHotStandby) { - /* We ignore autovacuum_max_workers when we make this test. */ + /* We ignore autovacuum_worker_slots when we make this test. */ RecoveryRequiresIntParameter("max_connections", MaxConnections, ControlFile->MaxConnections); @@ -6012,7 +6227,8 @@ StartupXLOG(void) memset(page + len, 0, XLOG_BLCKSZ - len); pg_atomic_write_u64(&XLogCtl->xlblocks[firstIdx], endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ); - XLogCtl->InitializedUpTo = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ; + pg_atomic_write_u64(&XLogCtl->InitializedUpTo, endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ); + XLogCtl->InitializedFrom = endOfRecoveryInfo->lastPageBeginPtr; } else { @@ -6021,8 +6237,10 @@ StartupXLOG(void) * let the first attempt to insert a log record to initialize the next * buffer. */ - XLogCtl->InitializedUpTo = EndOfLog; + pg_atomic_write_u64(&XLogCtl->InitializedUpTo, EndOfLog); + XLogCtl->InitializedFrom = EndOfLog; } + pg_atomic_write_u64(&XLogCtl->InitializeReserved, pg_atomic_read_u64(&XLogCtl->InitializedUpTo)); /* * Update local and shared status. This is OK to do without any locks @@ -6071,7 +6289,7 @@ StartupXLOG(void) /* * Reload shared-memory state for prepared transactions. This needs to * happen before renaming the last partial segment of the old timeline as - * it may be possible that we have to recovery some transactions from it. + * it may be possible that we have to recover some transactions from it. */ RecoverPreparedTransactions(); @@ -6698,14 +6916,15 @@ LogCheckpointEnd(bool restartpoint) */ if (restartpoint) ereport(LOG, - (errmsg("restartpoint complete: wrote %d buffers (%.1f%%); " - "%d WAL file(s) added, %d removed, %d recycled; " - "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; " - "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; " - "distance=%d kB, estimate=%d kB; " - "lsn=%X/%X, redo lsn=%X/%X", + (errmsg("restartpoint complete: wrote %d buffers (%.1f%%), " + "wrote %d SLRU buffers; %d WAL file(s) added, " + "%d removed, %d recycled; write=%ld.%03d s, " + "sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, " + "longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, " + "estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X", CheckpointStats.ckpt_bufs_written, (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers, + CheckpointStats.ckpt_slru_written, CheckpointStats.ckpt_segs_added, CheckpointStats.ckpt_segs_removed, CheckpointStats.ckpt_segs_recycled, @@ -6721,14 +6940,15 @@ LogCheckpointEnd(bool restartpoint) LSN_FORMAT_ARGS(ControlFile->checkPointCopy.redo)))); else ereport(LOG, - (errmsg("checkpoint complete: wrote %d buffers (%.1f%%); " - "%d WAL file(s) added, %d removed, %d recycled; " - "write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; " - "sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; " - "distance=%d kB, estimate=%d kB; " - "lsn=%X/%X, redo lsn=%X/%X", + (errmsg("checkpoint complete: wrote %d buffers (%.1f%%), " + "wrote %d SLRU buffers; %d WAL file(s) added, " + "%d removed, %d recycled; write=%ld.%03d s, " + "sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, " + "longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, " + "estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X", CheckpointStats.ckpt_bufs_written, (double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers, + CheckpointStats.ckpt_slru_written, CheckpointStats.ckpt_segs_added, CheckpointStats.ckpt_segs_removed, CheckpointStats.ckpt_segs_recycled, @@ -6849,8 +7069,11 @@ update_checkpoint_display(int flags, bool restartpoint, bool reset) * In this case, we only insert an XLOG_CHECKPOINT_SHUTDOWN record, and it's * both the record marking the completion of the checkpoint and the location * from which WAL replay would begin if needed. + * + * Returns true if a new checkpoint was performed, or false if it was skipped + * because the system was idle. */ -void +bool CreateCheckPoint(int flags) { bool shutdown; @@ -6942,7 +7165,7 @@ CreateCheckPoint(int flags) END_CRIT_SECTION(); ereport(DEBUG1, (errmsg_internal("checkpoint skipped because system is idle"))); - return; + return false; } } @@ -7022,7 +7245,7 @@ CreateCheckPoint(int flags) { /* Include WAL level in record for WAL summarizer's benefit. */ XLogBeginInsert(); - XLogRegisterData((char *) &wal_level, sizeof(wal_level)); + XLogRegisterData(&wal_level, sizeof(wal_level)); (void) XLogInsert(RM_XLOG_ID, XLOG_CHECKPOINT_REDO); /* @@ -7175,7 +7398,7 @@ CreateCheckPoint(int flags) * Now insert the checkpoint record into XLOG. */ XLogBeginInsert(); - XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint)); + XLogRegisterData(&checkPoint, sizeof(checkPoint)); recptr = XLogInsert(RM_XLOG_ID, shutdown ? XLOG_CHECKPOINT_SHUTDOWN : XLOG_CHECKPOINT_ONLINE); @@ -7261,7 +7484,7 @@ CreateCheckPoint(int flags) * until after the above call that flushes the XLOG_CHECKPOINT_ONLINE * record. */ - SetWalSummarizerLatch(); + WakeupWalSummarizer(); /* * Let smgr do post-checkpoint cleanup (eg, deleting old files). @@ -7275,13 +7498,17 @@ CreateCheckPoint(int flags) if (PriorRedoPtr != InvalidXLogRecPtr) UpdateCheckPointDistanceEstimate(RedoRecPtr - PriorRedoPtr); +#ifdef USE_INJECTION_POINTS + INJECTION_POINT("checkpoint-before-old-wal-removal", NULL); +#endif + /* * Delete old log files, those no longer needed for last checkpoint to * prevent the disk holding the xlog from growing full. */ XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size); KeepLogSeg(recptr, &_logSegNo); - if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED, + if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED | RS_INVAL_IDLE_TIMEOUT, _logSegNo, InvalidOid, InvalidTransactionId)) { @@ -7324,6 +7551,8 @@ CreateCheckPoint(int flags) CheckpointStats.ckpt_segs_added, CheckpointStats.ckpt_segs_removed, CheckpointStats.ckpt_segs_recycled); + + return true; } /* @@ -7355,7 +7584,7 @@ CreateEndOfRecoveryRecord(void) START_CRIT_SECTION(); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xl_end_of_recovery)); + XLogRegisterData(&xlrec, sizeof(xl_end_of_recovery)); recptr = XLogInsert(RM_XLOG_ID, XLOG_END_OF_RECOVERY); XLogFlush(recptr); @@ -7448,7 +7677,7 @@ CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr, XLogBeginInsert(); xlrec.overwritten_lsn = aborted_lsn; xlrec.overwrite_time = GetCurrentTimestamp(); - XLogRegisterData((char *) &xlrec, sizeof(xl_overwrite_contrecord)); + XLogRegisterData(&xlrec, sizeof(xl_overwrite_contrecord)); recptr = XLogInsert(RM_XLOG_ID, XLOG_OVERWRITE_CONTRECORD); /* check that the record was inserted to the right place */ @@ -7657,7 +7886,7 @@ CreateRestartPoint(int flags) * This location needs to be after CheckPointGuts() to ensure that some * work has already happened during this checkpoint. */ - INJECTION_POINT("create-restart-point"); + INJECTION_POINT("create-restart-point", NULL); /* * Remember the prior checkpoint's redo ptr for @@ -7734,7 +7963,7 @@ CreateRestartPoint(int flags) replayPtr = GetXLogReplayRecPtr(&replayTLI); endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr; KeepLogSeg(endptr, &_logSegNo); - if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED, + if (InvalidateObsoleteReplicationSlots(RS_INVAL_WAL_REMOVED | RS_INVAL_IDLE_TIMEOUT, _logSegNo, InvalidOid, InvalidTransactionId)) { @@ -7986,7 +8215,7 @@ void XLogPutNextOid(Oid nextOid) { XLogBeginInsert(); - XLogRegisterData((char *) (&nextOid), sizeof(Oid)); + XLogRegisterData(&nextOid, sizeof(Oid)); (void) XLogInsert(RM_XLOG_ID, XLOG_NEXTOID); /* @@ -8047,7 +8276,7 @@ XLogRestorePoint(const char *rpName) strlcpy(xlrec.rp_name, rpName, MAXFNAMELEN); XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xl_restore_point)); + XLogRegisterData(&xlrec, sizeof(xl_restore_point)); RecPtr = XLogInsert(RM_XLOG_ID, XLOG_RESTORE_POINT); @@ -8096,7 +8325,7 @@ XLogReportParameters(void) xlrec.track_commit_timestamp = track_commit_timestamp; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); recptr = XLogInsert(RM_XLOG_ID, XLOG_PARAMETER_CHANGE); XLogFlush(recptr); @@ -8171,7 +8400,7 @@ UpdateFullPageWrites(void) if (XLogStandbyInfoActive() && !recoveryInProgress) { XLogBeginInsert(); - XLogRegisterData((char *) (&fullPageWrites), sizeof(bool)); + XLogRegisterData(&fullPageWrites, sizeof(bool)); XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE); } @@ -8659,11 +8888,10 @@ issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli) wal_sync_method == WAL_SYNC_METHOD_OPEN_DSYNC) return; - /* Measure I/O timing to sync the WAL file */ - if (track_wal_io_timing) - INSTR_TIME_SET_CURRENT(start); - else - INSTR_TIME_SET_ZERO(start); + /* + * Measure I/O timing to sync the WAL file for pg_stat_io. + */ + start = pgstat_prepare_io_time(track_wal_io_timing); pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC); switch (wal_sync_method) @@ -8709,18 +8937,8 @@ issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli) pgstat_report_wait_end(); - /* - * Increment the I/O timing and the number of times WAL files were synced. - */ - if (track_wal_io_timing) - { - instr_time end; - - INSTR_TIME_SET_CURRENT(end); - INSTR_TIME_ACCUM_DIFF(PendingWalStats.wal_sync_time, end, start); - } - - PendingWalStats.wal_sync++; + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_FSYNC, + start, 1, 0); } /* @@ -8937,10 +9155,10 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, datadirpathlen = strlen(DataDir); /* Collect information about all tablespaces */ - tblspcdir = AllocateDir("pg_tblspc"); - while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL) + tblspcdir = AllocateDir(PG_TBLSPC_DIR); + while ((de = ReadDir(tblspcdir, PG_TBLSPC_DIR)) != NULL) { - char fullpath[MAXPGPATH + 10]; + char fullpath[MAXPGPATH + sizeof(PG_TBLSPC_DIR)]; char linkpath[MAXPGPATH]; char *relpath = NULL; char *s; @@ -8963,7 +9181,7 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, if (*badp != '\0' || errno == EINVAL || errno == ERANGE) continue; - snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name); + snprintf(fullpath, sizeof(fullpath), "%s/%s", PG_TBLSPC_DIR, de->d_name); de_type = get_dirent_type(fullpath, de, false, ERROR); @@ -9024,8 +9242,8 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces, * In this case, we store a relative path rather than an * absolute path into the tablespaceinfo. */ - snprintf(linkpath, sizeof(linkpath), "pg_tblspc/%s", - de->d_name); + snprintf(linkpath, sizeof(linkpath), "%s/%s", + PG_TBLSPC_DIR, de->d_name); relpath = pstrdup(linkpath); } else @@ -9104,7 +9322,7 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("WAL level not sufficient for making an online backup"), - errhint("wal_level must be set to \"replica\" or \"logical\" at server start."))); + errhint("\"wal_level\" must be set to \"replica\" or \"logical\" at server start."))); /* * OK to update backup counter and session-level lock. @@ -9211,7 +9429,7 @@ do_pg_backup_stop(BackupState *state, bool waitforarchive) * Write the backup-end xlog record */ XLogBeginInsert(); - XLogRegisterData((char *) (&state->startpoint), + XLogRegisterData(&state->startpoint, sizeof(state->startpoint)); state->stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END); diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index 81999b48200be..1ef1713c91a49 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -4,7 +4,7 @@ * Functions for archiving WAL files and restoring from the archive. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlogarchive.c diff --git a/src/backend/access/transam/xlogbackup.c b/src/backend/access/transam/xlogbackup.c index 5171668cddc17..342590e0a46d3 100644 --- a/src/backend/access/transam/xlogbackup.c +++ b/src/backend/access/transam/xlogbackup.c @@ -3,7 +3,7 @@ * xlogbackup.c * Internal routines for base backups. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index 4e46baaebdf7a..8c3090165f001 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -7,7 +7,7 @@ * This file contains WAL control and information functions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlogfuncs.c @@ -28,6 +28,7 @@ #include "pgstat.h" #include "replication/walreceiver.h" #include "storage/fd.h" +#include "storage/latch.h" #include "storage/standby.h" #include "utils/builtins.h" #include "utils/memutils.h" diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c index 90476015347ad..5ee9d0b028eae 100644 --- a/src/backend/access/transam/xloginsert.c +++ b/src/backend/access/transam/xloginsert.c @@ -9,7 +9,7 @@ * of XLogRecData structs by a call to XLogRecordAssemble(). See * access/transam/README for details. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xloginsert.c @@ -72,7 +72,7 @@ typedef struct RelFileLocator rlocator; /* identifies the relation and block */ ForkNumber forkno; BlockNumber block; - Page page; /* page content */ + const PageData *page; /* page content */ uint32 rdata_len; /* total length of data in rdata chain */ XLogRecData *rdata_head; /* head of the chain of data registered with * this block */ @@ -138,8 +138,8 @@ static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included); -static bool XLogCompressBackupBlock(char *page, uint16 hole_offset, - uint16 hole_length, char *dest, uint16 *dlen); +static bool XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, + uint16 hole_length, void *dest, uint16 *dlen); /* * Begin constructing a WAL record. This must be called before the @@ -307,7 +307,7 @@ XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags) */ void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, - BlockNumber blknum, Page page, uint8 flags) + BlockNumber blknum, const PageData *page, uint8 flags) { registered_buffer *regbuf; @@ -361,7 +361,7 @@ XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, * XLogRecGetData(). */ void -XLogRegisterData(char *data, uint32 len) +XLogRegisterData(const void *data, uint32 len) { XLogRecData *rdata; @@ -402,7 +402,7 @@ XLogRegisterData(char *data, uint32 len) * limited) */ void -XLogRegisterBufData(uint8 block_id, char *data, uint32 len) +XLogRegisterBufData(uint8 block_id, const void *data, uint32 len) { registered_buffer *regbuf; XLogRecData *rdata; @@ -648,7 +648,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, if (include_image) { - Page page = regbuf->page; + const PageData *page = regbuf->page; uint16 compressed_len = 0; /* @@ -869,8 +869,8 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, if (mainrdata_len > PG_UINT32_MAX) ereport(ERROR, (errmsg_internal("too much WAL data"), - errdetail_internal("Main data length is %llu bytes for a maximum of %u bytes.", - (unsigned long long) mainrdata_len, + errdetail_internal("Main data length is %" PRIu64 " bytes for a maximum of %u bytes.", + mainrdata_len, PG_UINT32_MAX))); mainrdata_len_4b = (uint32) mainrdata_len; @@ -915,8 +915,8 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, if (total_len > XLogRecordMaxSize) ereport(ERROR, (errmsg_internal("oversized WAL record"), - errdetail_internal("WAL record would be %llu bytes (of maximum %u bytes); rmid %u flags %u.", - (unsigned long long) total_len, XLogRecordMaxSize, rmid, info))); + errdetail_internal("WAL record would be %" PRIu64 " bytes (of maximum %u bytes); rmid %u flags %u.", + total_len, XLogRecordMaxSize, rmid, info))); /* * Fill in the fields in the record header. Prev-link is filled in later, @@ -941,23 +941,23 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, * the length of compressed block image. */ static bool -XLogCompressBackupBlock(char *page, uint16 hole_offset, uint16 hole_length, - char *dest, uint16 *dlen) +XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, uint16 hole_length, + void *dest, uint16 *dlen) { int32 orig_len = BLCKSZ - hole_length; int32 len = -1; int32 extra_bytes = 0; - char *source; + const void *source; PGAlignedBlock tmp; if (hole_length != 0) { /* must skip the hole */ - source = tmp.data; - memcpy(source, page, hole_offset); - memcpy(source + hole_offset, + memcpy(tmp.data, page, hole_offset); + memcpy(tmp.data + hole_offset, page + (hole_offset + hole_length), BLCKSZ - (hole_length + hole_offset)); + source = tmp.data; /* * Extra data needs to be stored in WAL record for the compressed diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c index 84023d61baf30..7735562db01d1 100644 --- a/src/backend/access/transam/xlogprefetcher.c +++ b/src/backend/access/transam/xlogprefetcher.c @@ -3,7 +3,7 @@ * xlogprefetcher.c * Prefetching support for recovery. * - * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2022-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -362,17 +362,15 @@ XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader) { XLogPrefetcher *prefetcher; - static HASHCTL hash_table_ctl = { - .keysize = sizeof(RelFileLocator), - .entrysize = sizeof(XLogPrefetcherFilter) - }; + HASHCTL ctl; prefetcher = palloc0(sizeof(XLogPrefetcher)); - prefetcher->reader = reader; + + ctl.keysize = sizeof(RelFileLocator); + ctl.entrysize = sizeof(XLogPrefetcherFilter); prefetcher->filter_table = hash_create("XLogPrefetcherFilterTable", 1024, - &hash_table_ctl, - HASH_ELEM | HASH_BLOBS); + &ctl, HASH_ELEM | HASH_BLOBS); dlist_init(&prefetcher->filter_queue); SharedStats->wal_distance = 0; @@ -1085,7 +1083,7 @@ check_recovery_prefetch(int *new_value, void **extra, GucSource source) #ifndef USE_PREFETCH if (*new_value == RECOVERY_PREFETCH_ON) { - GUC_check_errdetail("\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()."); + GUC_check_errdetail("\"recovery_prefetch\" is not supported on platforms that lack support for issuing read-ahead advice."); return false; } #endif diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index 37d2a57961d0d..2790ade1f91e8 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -3,7 +3,7 @@ * xlogreader.c * Generic XLog reading facility * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/transam/xlogreader.c @@ -35,6 +35,7 @@ #ifndef FRONTEND #include "pgstat.h" +#include "storage/bufmgr.h" #else #include "common/logging.h" #endif @@ -793,7 +794,7 @@ XLogDecodeNextRecord(XLogReaderState *state, bool nonblocking) readOff = ReadPageInternal(state, targetPagePtr, pageHeaderSize + len); - memcpy(buffer, (char *) contdata, len); + memcpy(buffer, contdata, len); buffer += len; gotlen += len; @@ -946,9 +947,9 @@ XLogDecodeNextRecord(XLogReaderState *state, bool nonblocking) XLogReaderInvalReadState(state); /* - * If an error was written to errmsg_buf, it'll be returned to the caller - * of XLogReadRecord() after all successfully decoded records from the - * read queue. + * If an error was written to errormsg_buf, it'll be returned to the + * caller of XLogReadRecord() after all successfully decoded records from + * the read queue. */ return XLREAD_FAIL; @@ -1271,9 +1272,9 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, longhdr->xlp_sysid != state->system_identifier) { report_invalid_record(state, - "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu", - (unsigned long long) longhdr->xlp_sysid, - (unsigned long long) state->system_identifier); + "WAL file is from different database system: WAL file database system identifier is %" PRIu64 ", pg_control database system identifier is %" PRIu64, + longhdr->xlp_sysid, + state->system_identifier); return false; } else if (longhdr->xlp_seg_size != state->segcxt.ws_segsize) @@ -1507,6 +1508,9 @@ WALRead(XLogReaderState *state, char *p; XLogRecPtr recptr; Size nbytes; +#ifndef FRONTEND + instr_time io_start; +#endif p = buf; recptr = startptr; @@ -1552,6 +1556,9 @@ WALRead(XLogReaderState *state, segbytes = nbytes; #ifndef FRONTEND + /* Measure I/O timing when reading segment */ + io_start = pgstat_prepare_io_time(track_wal_io_timing); + pgstat_report_wait_start(WAIT_EVENT_WAL_READ); #endif @@ -1561,6 +1568,9 @@ WALRead(XLogReaderState *state, #ifndef FRONTEND pgstat_report_wait_end(); + + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_READ, + io_start, 1, readbytes); #endif if (readbytes <= 0) @@ -2166,28 +2176,14 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page) FullTransactionId XLogRecGetFullXid(XLogReaderState *record) { - TransactionId xid, - next_xid; - uint32 epoch; - /* * This function is only safe during replay, because it depends on the * replay state. See AdvanceNextFullTransactionIdPastXid() for more. */ Assert(AmStartupProcess() || !IsUnderPostmaster); - xid = XLogRecGetXid(record); - next_xid = XidFromFullTransactionId(TransamVariables->nextXid); - epoch = EpochFromFullTransactionId(TransamVariables->nextXid); - - /* - * If xid is numerically greater than next_xid, it has to be from the last - * epoch. - */ - if (unlikely(xid > next_xid)) - --epoch; - - return FullTransactionIdFromEpochAndXid(epoch, xid); + return FullTransactionIdFromAllowableAt(TransamVariables->nextXid, + XLogRecGetXid(record)); } #endif diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c index 2ed3ea2b45bcb..6ce979f2d8bc4 100644 --- a/src/backend/access/transam/xlogrecovery.c +++ b/src/backend/access/transam/xlogrecovery.c @@ -14,7 +14,7 @@ * for interrogating recovery state and controlling the recovery process. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlogrecovery.c @@ -60,6 +60,7 @@ #include "utils/datetime.h" #include "utils/fmgrprotos.h" #include "utils/guc_hooks.h" +#include "utils/pgstat_internal.h" #include "utils/pg_lsn.h" #include "utils/ps_status.h" #include "utils/pg_rusage.h" @@ -290,6 +291,11 @@ static bool backupEndRequired = false; * Consistent state means that the system is internally consistent, all * the WAL has been replayed up to a certain point, and importantly, there * is no trace of later actions on disk. + * + * This flag is used only by the startup process and postmaster. When + * minRecoveryPoint is reached, the startup process sets it to true and + * sends a PMSIGNAL_RECOVERY_CONSISTENT signal to the postmaster, + * which then sets it to true upon receiving the signal. */ bool reachedConsistency = false; @@ -429,9 +435,9 @@ static int emode_for_corrupt_record(int emode, XLogRecPtr RecPtr); static XLogRecord *ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI); static bool rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN); -static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli, +static int XLogFileRead(XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk); -static int XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source); +static int XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source); static bool CheckForStandbyTrigger(void); static void SetPromoteIsTriggered(void); @@ -676,7 +682,7 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, tablespaceinfo *ti = lfirst(lc); char *linkloc; - linkloc = psprintf("pg_tblspc/%u", ti->oid); + linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid); /* * Remove the existing symlink if any and Create the symlink @@ -844,13 +850,15 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, * tliSwitchPoint will throw an error if the checkpoint's timeline is * not in expectedTLEs at all. */ - switchpoint = tliSwitchPoint(ControlFile->checkPointCopy.ThisTimeLineID, expectedTLEs, NULL); + switchpoint = tliSwitchPoint(CheckPointTLI, expectedTLEs, NULL); ereport(FATAL, (errmsg("requested timeline %u is not a child of this server's history", recoveryTargetTLI), - errdetail("Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.", - LSN_FORMAT_ARGS(ControlFile->checkPoint), - ControlFile->checkPointCopy.ThisTimeLineID, + /* translator: %s is a backup_label file or a pg_control file */ + errdetail("Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.", + haveBackupLabel ? "backup_label" : "pg_control", + LSN_FORMAT_ARGS(CheckPointLoc), + CheckPointTLI, LSN_FORMAT_ARGS(switchpoint)))); } @@ -1771,7 +1779,7 @@ PerformWalRecovery(void) #endif /* Handle interrupt signals of startup process */ - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); /* * Pause WAL replay, if requested by a hot-standby session via @@ -1913,7 +1921,7 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl /* Setup error traceback support for ereport() */ errcallback.callback = rm_redo_error_callback; - errcallback.arg = (void *) xlogreader; + errcallback.arg = xlogreader; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -2146,23 +2154,24 @@ CheckTablespaceDirectory(void) DIR *dir; struct dirent *de; - dir = AllocateDir("pg_tblspc"); - while ((de = ReadDir(dir, "pg_tblspc")) != NULL) + dir = AllocateDir(PG_TBLSPC_DIR); + while ((de = ReadDir(dir, PG_TBLSPC_DIR)) != NULL) { - char path[MAXPGPATH + 10]; + char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR)]; /* Skip entries of non-oid names */ if (strspn(de->d_name, "0123456789") != strlen(de->d_name)) continue; - snprintf(path, sizeof(path), "pg_tblspc/%s", de->d_name); + snprintf(path, sizeof(path), "%s/%s", PG_TBLSPC_DIR, de->d_name); if (get_dirent_type(path, de, false, ERROR) != PGFILETYPE_LNK) ereport(allow_in_place_tablespaces ? WARNING : PANIC, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("unexpected directory entry \"%s\" found in %s", - de->d_name, "pg_tblspc/"), - errdetail("All directory entries in pg_tblspc/ should be symbolic links."), + de->d_name, PG_TBLSPC_DIR), + errdetail("All directory entries in %s/ should be symbolic links.", + PG_TBLSPC_DIR), errhint("Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete."))); } } @@ -2244,6 +2253,7 @@ CheckRecoveryConsistency(void) CheckTablespaceDirectory(); reachedConsistency = true; + SendPostmasterSignal(PMSIGNAL_RECOVERY_CONSISTENT); ereport(LOG, (errmsg("consistent recovery state reached at %X/%X", LSN_FORMAT_ARGS(lastReplayedEndRecPtr)))); @@ -2945,7 +2955,7 @@ recoveryPausesHere(bool endOfRecovery) /* loop until recoveryPauseState is set to RECOVERY_NOT_PAUSED */ while (GetRecoveryPauseState() != RECOVERY_NOT_PAUSED) { - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); if (CheckForStandbyTrigger()) return; @@ -3034,7 +3044,7 @@ recoveryApplyDelay(XLogReaderState *record) ResetLatch(&XLogRecoveryCtl->recoveryWakeupLatch); /* This might change recovery_min_apply_delay. */ - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); if (CheckForStandbyTrigger()) break; @@ -3305,6 +3315,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, uint32 targetPageOff; XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY; int r; + instr_time io_start; XLByteToSeg(targetPagePtr, targetSegNo, wal_segment_size); targetPageOff = XLogSegmentOffset(targetPagePtr, wal_segment_size); @@ -3397,6 +3408,9 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, /* Read the requested page */ readOff = targetPageOff; + /* Measure I/O timing when reading segment */ + io_start = pgstat_prepare_io_time(track_wal_io_timing); + pgstat_report_wait_start(WAIT_EVENT_WAL_READ); r = pg_pread(readFile, readBuf, XLOG_BLCKSZ, (off_t) readOff); if (r != XLOG_BLCKSZ) @@ -3405,6 +3419,10 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, int save_errno = errno; pgstat_report_wait_end(); + + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_READ, + io_start, 1, r); + XLogFileName(fname, curFileTLI, readSegNo, wal_segment_size); if (r < 0) { @@ -3425,6 +3443,9 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, } pgstat_report_wait_end(); + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_READ, + io_start, 1, r); + Assert(targetSegNo == readSegNo); Assert(targetPageOff == readOff); Assert(reqLen <= readLen); @@ -3437,12 +3458,12 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, * validates the page header anyway, and would propagate the failure up to * ReadRecord(), which would retry. However, there's a corner case with * continuation records, if a record is split across two pages such that - * we would need to read the two pages from different sources. For - * example, imagine a scenario where a streaming replica is started up, - * and replay reaches a record that's split across two WAL segments. The - * first page is only available locally, in pg_wal, because it's already - * been recycled on the primary. The second page, however, is not present - * in pg_wal, and we should stream it from the primary. There is a + * we would need to read the two pages from different sources across two + * WAL segments. + * + * The first page is only available locally, in pg_wal, because it's + * already been recycled on the primary. The second page, however, is not + * present in pg_wal, and we should stream it from the primary. There is a * recycled WAL segment present in pg_wal, with garbage contents, however. * We would read the first page from the local WAL segment, but when * reading the second page, we would read the bogus, recycled, WAL @@ -3464,6 +3485,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, * responsible for the validation. */ if (StandbyMode && + (targetPagePtr % wal_segment_size) == 0 && !XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf)) { /* @@ -3711,7 +3733,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, now = GetCurrentTimestamp(); /* Handle interrupt signals of startup process */ - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); } last_fail_time = now; currentSource = XLOG_FROM_ARCHIVE; @@ -3768,7 +3790,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, * Try to restore the file from archive, or read an existing * file from pg_wal. */ - readFile = XLogFileReadAnyTLI(readSegNo, DEBUG2, + readFile = XLogFileReadAnyTLI(readSegNo, currentSource == XLOG_FROM_ARCHIVE ? XLOG_FROM_ANY : currentSource); if (readFile >= 0) @@ -3917,8 +3939,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, { if (!expectedTLEs) expectedTLEs = readTimeLineHistory(recoveryTargetTLI); - readFile = XLogFileRead(readSegNo, PANIC, - receiveTLI, + readFile = XLogFileRead(readSegNo, receiveTLI, XLOG_FROM_STREAM, false); Assert(readFile >= 0); } @@ -4002,7 +4023,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess, * This possibly-long loop needs to handle interrupts of startup * process. */ - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); } return XLREAD_FAIL; /* not reached */ @@ -4189,7 +4210,7 @@ rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN) * Otherwise, it's assumed to be already available in pg_wal. */ static int -XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli, +XLogFileRead(XLogSegNo segno, TimeLineID tli, XLogSource source, bool notfoundOk) { char xlogfname[MAXFNAMELEN]; @@ -4271,7 +4292,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli, * This version searches for the segment with any TLI listed in expectedTLEs. */ static int -XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source) +XLogFileReadAnyTLI(XLogSegNo segno, XLogSource source) { char path[MAXPGPATH]; ListCell *cell; @@ -4335,8 +4356,7 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source) if (source == XLOG_FROM_ANY || source == XLOG_FROM_ARCHIVE) { - fd = XLogFileRead(segno, emode, tli, - XLOG_FROM_ARCHIVE, true); + fd = XLogFileRead(segno, tli, XLOG_FROM_ARCHIVE, true); if (fd != -1) { elog(DEBUG1, "got WAL segment from archive"); @@ -4348,8 +4368,7 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source) if (source == XLOG_FROM_ANY || source == XLOG_FROM_PG_WAL) { - fd = XLogFileRead(segno, emode, tli, - XLOG_FROM_PG_WAL, true); + fd = XLogFileRead(segno, tli, XLOG_FROM_PG_WAL, true); if (fd != -1) { if (!expectedTLEs) @@ -4362,7 +4381,7 @@ XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source) /* Couldn't find it. For simplicity, complain about front timeline */ XLogFilePath(path, recoveryTargetTLI, segno, wal_segment_size); errno = ENOENT; - ereport(emode, + ereport(DEBUG2, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", path))); return -1; @@ -4682,7 +4701,7 @@ RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue while (GetRecoveryPauseState() != RECOVERY_NOT_PAUSED) { - HandleStartupProcInterrupts(); + ProcessStartupProcInterrupts(); if (CheckForStandbyTrigger()) { @@ -4765,8 +4784,7 @@ check_primary_slot_name(char **newval, void **extra, GucSource source) * that we have odd behaviors such as unexpected GUC ordering dependencies. */ -static void -pg_attribute_noreturn() +pg_noreturn static void error_multiple_recovery_targets(void) { ereport(ERROR, @@ -4821,9 +4839,11 @@ check_recovery_target_lsn(char **newval, void **extra, GucSource source) if (have_error) return false; - myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr)); + myextra = (XLogRecPtr *) guc_malloc(LOG, sizeof(XLogRecPtr)); + if (!myextra) + return false; *myextra = lsn; - *extra = (void *) myextra; + *extra = myextra; } return true; } @@ -4935,7 +4955,7 @@ check_recovery_target_time(char **newval, void **extra, GucSource source) if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0) { - GUC_check_errdetail("timestamp out of range: \"%s\"", str); + GUC_check_errdetail("Timestamp out of range: \"%s\".", str); return false; } } @@ -4985,9 +5005,11 @@ check_recovery_target_timeline(char **newval, void **extra, GucSource source) } } - myextra = (RecoveryTargetTimeLineGoal *) guc_malloc(ERROR, sizeof(RecoveryTargetTimeLineGoal)); + myextra = (RecoveryTargetTimeLineGoal *) guc_malloc(LOG, sizeof(RecoveryTargetTimeLineGoal)); + if (!myextra) + return false; *myextra = rttg; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -5021,9 +5043,11 @@ check_recovery_target_xid(char **newval, void **extra, GucSource source) if (errno == EINVAL || errno == ERANGE) return false; - myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId)); + myextra = (TransactionId *) guc_malloc(LOG, sizeof(TransactionId)); + if (!myextra) + return false; *myextra = xid; - *extra = (void *) myextra; + *extra = myextra; } return true; } diff --git a/src/backend/access/transam/xlogstats.c b/src/backend/access/transam/xlogstats.c index 2b33decd5a19b..f92d9e13b174e 100644 --- a/src/backend/access/transam/xlogstats.c +++ b/src/backend/access/transam/xlogstats.c @@ -3,7 +3,7 @@ * xlogstats.c * Functions for WAL Statitstics * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/transam/xlogstats.c diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 5295b85fe078c..c389b27f77d47 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -8,7 +8,7 @@ * None of this code is used during normal system operation. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlogutils.c @@ -86,15 +86,14 @@ static void report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno, BlockNumber blkno, bool present) { - char *path = relpathperm(locator, forkno); + RelPathStr path = relpathperm(locator, forkno); if (present) elog(elevel, "page %u of relation %s is uninitialized", - blkno, path); + blkno, path.str); else elog(elevel, "page %u of relation %s does not exist", - blkno, path); - pfree(path); + blkno, path.str); } /* Log a reference to an invalid page */ @@ -180,14 +179,9 @@ forget_invalid_pages(RelFileLocator locator, ForkNumber forkno, hentry->key.forkno == forkno && hentry->key.blkno >= minblkno) { - if (message_level_is_interesting(DEBUG2)) - { - char *path = relpathperm(hentry->key.locator, forkno); - - elog(DEBUG2, "page %u of relation %s has been dropped", - hentry->key.blkno, path); - pfree(path); - } + elog(DEBUG2, "page %u of relation %s has been dropped", + hentry->key.blkno, + relpathperm(hentry->key.locator, forkno).str); if (hash_search(invalid_page_tab, &hentry->key, @@ -213,14 +207,9 @@ forget_invalid_pages_db(Oid dbid) { if (hentry->key.locator.dbOid == dbid) { - if (message_level_is_interesting(DEBUG2)) - { - char *path = relpathperm(hentry->key.locator, hentry->key.forkno); - - elog(DEBUG2, "page %u of relation %s has been dropped", - hentry->key.blkno, path); - pfree(path); - } + elog(DEBUG2, "page %u of relation %s has been dropped", + hentry->key.blkno, + relpathperm(hentry->key.locator, hentry->key.forkno).str); if (hash_search(invalid_page_tab, &hentry->key, @@ -851,11 +840,6 @@ wal_segment_close(XLogReaderState *state) * * Public because it would likely be very helpful for someone writing another * output method outside walsender, e.g. in a bgworker. - * - * TODO: The walsender has its own version of this, but it relies on the - * walsender's latch being set whenever WAL is flushed. No such infrastructure - * exists for normal backends, so we have to do a check/sleep/repeat style of - * loop for now. */ int read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, @@ -895,7 +879,14 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr, loc = targetPagePtr + reqLen; - /* Loop waiting for xlog to be available if necessary */ + /* + * Loop waiting for xlog to be available if necessary + * + * TODO: The walsender has its own version of this function, which uses a + * condition variable to wake up whenever WAL is flushed. We could use the + * same infrastructure here, instead of the check/sleep/repeat style of + * loop. + */ while (1) { /* diff --git a/src/backend/archive/meson.build b/src/backend/archive/meson.build index 51a71673e65f4..2c3ad10199457 100644 --- a/src/backend/archive/meson.build +++ b/src/backend/archive/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group backend_sources += files( 'shell_archive.c' diff --git a/src/backend/archive/shell_archive.c b/src/backend/archive/shell_archive.c index 506c5a30ad209..828723afe4769 100644 --- a/src/backend/archive/shell_archive.c +++ b/src/backend/archive/shell_archive.c @@ -6,7 +6,7 @@ * archive_command GUC) to copy write-ahead log files. It is used as the * default, but other modules may define their own custom archiving logic. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/archive/shell_archive.c @@ -48,7 +48,7 @@ shell_archive_configured(ArchiveModuleState *state) if (XLogArchiveCommand[0] != '\0') return true; - arch_module_check_errdetail("%s is not set.", + arch_module_check_errdetail("\"%s\" is not set.", "archive_command"); return false; } diff --git a/src/backend/backup/backup_manifest.c b/src/backend/backup/backup_manifest.c index 4357cfa31de66..22e2be37c95c3 100644 --- a/src/backend/backup/backup_manifest.c +++ b/src/backend/backup/backup_manifest.c @@ -3,7 +3,7 @@ * backup_manifest.c * code for generating and sending a backup manifest * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/backup_manifest.c @@ -16,6 +16,7 @@ #include "access/xlog.h" #include "backup/backup_manifest.h" #include "backup/basebackup_sink.h" +#include "common/relpath.h" #include "mb/pg_wchar.h" #include "utils/builtins.h" #include "utils/json.h" @@ -117,7 +118,7 @@ AddFileToBackupManifest(backup_manifest_info *manifest, Oid spcoid, */ if (OidIsValid(spcoid)) { - snprintf(pathbuf, sizeof(pathbuf), "pg_tblspc/%u/%s", spcoid, + snprintf(pathbuf, sizeof(pathbuf), "%s/%u/%s", PG_TBLSPC_DIR, spcoid, pathname); pathname = pathbuf; } diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c index 01b35e26bda08..f0f88838dc21a 100644 --- a/src/backend/backup/basebackup.c +++ b/src/backend/backup/basebackup.c @@ -3,7 +3,7 @@ * basebackup.c * code for taking a base backup and streaming it to a standby * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup.c @@ -33,9 +33,9 @@ #include "nodes/pg_list.h" #include "pgstat.h" #include "pgtar.h" -#include "port.h" #include "postmaster/syslogger.h" #include "postmaster/walsummarizer.h" +#include "replication/slot.h" #include "replication/walsender.h" #include "replication/walsender_private.h" #include "storage/bufpage.h" @@ -161,7 +161,7 @@ static const char *const excludeDirContents[] = * even if the intention is to restore to another primary. See backup.sgml * for a more detailed description. */ - "pg_replslot", + PG_REPLSLOT_DIR, /* Contents removed on startup, see dsm_cleanup_for_mmap(). */ PG_DYNSHMEM_DIR, @@ -249,8 +249,10 @@ perform_base_backup(basebackup_options *opt, bbsink *sink, state.bytes_total_is_valid = false; /* we're going to use a BufFile, so we need a ResourceOwner */ - Assert(CurrentResourceOwner == NULL); - CurrentResourceOwner = ResourceOwnerCreate(NULL, "base backup"); + Assert(AuxProcessResourceOwner != NULL); + Assert(CurrentResourceOwner == AuxProcessResourceOwner || + CurrentResourceOwner == NULL); + CurrentResourceOwner = AuxProcessResourceOwner; backup_started_in_recovery = RecoveryInProgress(); @@ -671,7 +673,7 @@ perform_base_backup(basebackup_options *opt, bbsink *sink, FreeBackupManifest(&manifest); /* clean up the resource owner we created */ - WalSndResourceCleanup(true); + ReleaseAuxProcessResources(true); basebackup_progress_done(); } @@ -1347,7 +1349,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name); /* Skip pg_control here to back up it last */ - if (strcmp(pathbuf, "./global/pg_control") == 0) + if (strcmp(pathbuf, "./" XLOG_CONTROL_FILE) == 0) continue; if (lstat(pathbuf, &statbuf) != 0) @@ -1487,7 +1489,7 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly, if (OidIsValid(spcoid)) { relspcoid = spcoid; - lookup_path = psprintf("pg_tblspc/%u/%s", spcoid, + lookup_path = psprintf("%s/%u/%s", PG_TBLSPC_DIR, spcoid, tarfilename); } else @@ -1815,6 +1817,7 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, checksum_failures, readfilename, checksum_failures))); + pgstat_prepare_report_checksum_failure(dboid); pgstat_report_checksum_failures_in_db(dboid, checksum_failures); } diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c index 0b4ee5f2a29f6..a284ce318ff7d 100644 --- a/src/backend/backup/basebackup_copy.c +++ b/src/backend/backup/basebackup_copy.c @@ -16,7 +16,7 @@ * An older method that sent each archive using a separate COPY OUT * operation is no longer supported. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_copy.c diff --git a/src/backend/backup/basebackup_gzip.c b/src/backend/backup/basebackup_gzip.c index 2b6dc656f9384..c4cbb5f527644 100644 --- a/src/backend/backup/basebackup_gzip.c +++ b/src/backend/backup/basebackup_gzip.c @@ -3,7 +3,7 @@ * basebackup_gzip.c * Basebackup sink implementing gzip compression. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_gzip.c diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c index 86fa6821ad2be..28491b1e0ab08 100644 --- a/src/backend/backup/basebackup_incremental.c +++ b/src/backend/backup/basebackup_incremental.c @@ -10,7 +10,7 @@ * backup manifest supplied by the user taking the incremental backup * and extract the required information from it. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_incremental.c @@ -27,9 +27,7 @@ #include "common/hashfn.h" #include "common/int.h" #include "common/parse_manifest.h" -#include "datatype/timestamp.h" #include "postmaster/walsummarizer.h" -#include "utils/timestamp.h" #define BLOCKS_PER_READ 512 @@ -58,7 +56,7 @@ typedef struct { uint32 status; const char *path; - size_t size; + uint64 size; } backup_file_entry; static uint32 hash_string_pointer(const char *s); @@ -133,7 +131,7 @@ static void manifest_process_system_identifier(JsonManifestParseContext *context uint64 manifest_system_identifier); static void manifest_process_file(JsonManifestParseContext *context, const char *pathname, - size_t size, + uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload); @@ -141,9 +139,9 @@ static void manifest_process_wal_range(JsonManifestParseContext *context, TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn); -static void manifest_report_error(JsonManifestParseContext *context, - const char *fmt,...) - pg_attribute_printf(2, 3) pg_attribute_noreturn(); +pg_noreturn static void manifest_report_error(JsonManifestParseContext *context, + const char *fmt,...) + pg_attribute_printf(2, 3); static int compare_block_numbers(const void *a, const void *b); /* @@ -207,8 +205,8 @@ AppendIncrementalManifestData(IncrementalBackupInfo *ib, const char *data, * time for an incremental parse. We'll do all but the last MIN_CHUNK * so that we have enough left for the final piece. */ - json_parse_manifest_incremental_chunk( - ib->inc_state, ib->buf.data, ib->buf.len - MIN_CHUNK, false); + json_parse_manifest_incremental_chunk(ib->inc_state, ib->buf.data, + ib->buf.len - MIN_CHUNK, false); /* now remove what we just parsed */ memmove(ib->buf.data, ib->buf.data + (ib->buf.len - MIN_CHUNK), MIN_CHUNK + 1); @@ -234,8 +232,8 @@ FinalizeIncrementalManifest(IncrementalBackupInfo *ib) oldcontext = MemoryContextSwitchTo(ib->mcxt); /* Parse the last chunk of the manifest */ - json_parse_manifest_incremental_chunk( - ib->inc_state, ib->buf.data, ib->buf.len, true); + json_parse_manifest_incremental_chunk(ib->inc_state, ib->buf.data, + ib->buf.len, true); /* Done with the buffer, so release memory. */ pfree(ib->buf.data); @@ -627,23 +625,21 @@ char * GetIncrementalFilePath(Oid dboid, Oid spcoid, RelFileNumber relfilenumber, ForkNumber forknum, unsigned segno) { - char *path; + RelPathStr path; char *lastslash; char *ipath; path = GetRelationPath(dboid, spcoid, relfilenumber, INVALID_PROC_NUMBER, forknum); - lastslash = strrchr(path, '/'); + lastslash = strrchr(path.str, '/'); Assert(lastslash != NULL); *lastslash = '\0'; if (segno > 0) - ipath = psprintf("%s/INCREMENTAL.%s.%u", path, lastslash + 1, segno); + ipath = psprintf("%s/INCREMENTAL.%s.%u", path.str, lastslash + 1, segno); else - ipath = psprintf("%s/INCREMENTAL.%s", path, lastslash + 1); - - pfree(path); + ipath = psprintf("%s/INCREMENTAL.%s", path.str, lastslash + 1); return ipath; } @@ -953,9 +949,9 @@ manifest_process_system_identifier(JsonManifestParseContext *context, if (manifest_system_identifier != system_identifier) context->error_cb(context, - "manifest system identifier is %llu, but database system identifier is %llu", - (unsigned long long) manifest_system_identifier, - (unsigned long long) system_identifier); + "system identifier in backup manifest is %" PRIu64 ", but database system identifier is %" PRIu64, + manifest_system_identifier, + system_identifier); } /* @@ -966,7 +962,7 @@ manifest_process_system_identifier(JsonManifestParseContext *context, */ static void manifest_process_file(JsonManifestParseContext *context, - const char *pathname, size_t size, + const char *pathname, uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload) diff --git a/src/backend/backup/basebackup_lz4.c b/src/backend/backup/basebackup_lz4.c index aa440aa55dc6f..c5ceccb846f57 100644 --- a/src/backend/backup/basebackup_lz4.c +++ b/src/backend/backup/basebackup_lz4.c @@ -3,7 +3,7 @@ * basebackup_lz4.c * Basebackup sink implementing lz4 compression. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_lz4.c diff --git a/src/backend/backup/basebackup_progress.c b/src/backend/backup/basebackup_progress.c index 8ff6c6073336a..1d22b541f89af 100644 --- a/src/backend/backup/basebackup_progress.c +++ b/src/backend/backup/basebackup_progress.c @@ -22,7 +22,7 @@ * the logic directly into that file as it's fairly simple, but it seems * cleaner to have everything related to progress reporting in one place.) * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_progress.c diff --git a/src/backend/backup/basebackup_sink.c b/src/backend/backup/basebackup_sink.c index 3c51619075865..e962f8f0b8d62 100644 --- a/src/backend/backup/basebackup_sink.c +++ b/src/backend/backup/basebackup_sink.c @@ -3,7 +3,7 @@ * basebackup_sink.c * Default implementations for bbsink (basebackup sink) callbacks. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/backend/backup/basebackup_sink.c * diff --git a/src/backend/backup/basebackup_target.c b/src/backend/backup/basebackup_target.c index bb50bdfe1d7a1..84b1309d3bdc8 100644 --- a/src/backend/backup/basebackup_target.c +++ b/src/backend/backup/basebackup_target.c @@ -6,7 +6,7 @@ * Furthermore, new targets can be defined by extensions. This file * contains code to support that functionality. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_target.c diff --git a/src/backend/backup/basebackup_throttle.c b/src/backend/backup/basebackup_throttle.c index 4477945e61334..b2b743238f9d0 100644 --- a/src/backend/backup/basebackup_throttle.c +++ b/src/backend/backup/basebackup_throttle.c @@ -5,7 +5,7 @@ * next base backup sink in the chain at a rate no greater than the * configured maximum. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_throttle.c diff --git a/src/backend/backup/basebackup_zstd.c b/src/backend/backup/basebackup_zstd.c index 0989e92e3c24f..18b2e8fb0b3b6 100644 --- a/src/backend/backup/basebackup_zstd.c +++ b/src/backend/backup/basebackup_zstd.c @@ -3,7 +3,7 @@ * basebackup_zstd.c * Basebackup sink implementing zstd compression. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/backup/basebackup_zstd.c diff --git a/src/backend/backup/meson.build b/src/backend/backup/meson.build index 79e1f83f8fb03..460025a3046ba 100644 --- a/src/backend/backup/meson.build +++ b/src/backend/backup/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'backup_manifest.c', diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c index 322ae3c3ad115..c7a2c65cc6a7a 100644 --- a/src/backend/backup/walsummary.c +++ b/src/backend/backup/walsummary.c @@ -3,7 +3,7 @@ * walsummary.c * Functions for accessing and managing WAL summary data. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/backend/backup/walsummary.c * diff --git a/src/backend/backup/walsummaryfuncs.c b/src/backend/backup/walsummaryfuncs.c index bb6a3a4a36677..d6dd131da145b 100644 --- a/src/backend/backup/walsummaryfuncs.c +++ b/src/backend/backup/walsummaryfuncs.c @@ -3,7 +3,7 @@ * walsummaryfuncs.c * SQL-callable functions for accessing WAL summary data. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/backend/backup/walsummaryfuncs.c * @@ -92,7 +92,7 @@ pg_wal_summary_contents(PG_FUNCTION_ARGS) if (raw_tli < 1 || raw_tli > PG_INT32_MAX) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid timeline %lld", (long long) raw_tli)); + errmsg("invalid timeline %" PRId64, raw_tli)); /* Prepare to read the specified WAL summary file. */ ws.tli = (TimeLineID) raw_tli; diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 58e0878dc8dd3..9833f52c1bed6 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -4,7 +4,7 @@ * bootparse.y * yacc grammar for the "bootstrap" mode (BKI file format) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,10 +32,7 @@ #include "nodes/makefuncs.h" #include "utils/memutils.h" - -/* silence -Wmissing-variable-declarations */ -extern int boot_yychar; -extern int boot_yynerrs; +#include "bootparse.h" /* @@ -80,6 +77,9 @@ static int num_columns_read = 0; %} +%parse-param {yyscan_t yyscanner} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="boot_yy" @@ -140,6 +140,8 @@ Boot_OpenStmt: do_start(); boot_openrel($2); do_end(); + + (void) yynerrs; /* suppress compiler warning */ } ; diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l index 31d63ff301596..50713912fb149 100644 --- a/src/backend/bootstrap/bootscanner.l +++ b/src/backend/bootstrap/bootscanner.l @@ -4,7 +4,7 @@ * bootscanner.l * a lexical scanner for the bootstrap parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -39,17 +39,19 @@ fprintf_to_ereport(const char *fmt, const char *msg) ereport(ERROR, (errmsg_internal("%s", msg))); } - -static int yyline = 1; /* line number for error reporting */ - %} +%option reentrant +%option bison-bridge %option 8bit %option never-interactive %option nodefault %option noinput %option nounput %option noyywrap +%option noyyalloc +%option noyyrealloc +%option noyyfree %option warn %option prefix="boot_yy" @@ -58,7 +60,7 @@ id [-A-Za-z0-9_]+ sid \'([^']|\'\')*\' /* - * Keyword tokens return the keyword text (as a constant string) in boot_yylval.kw, + * Keyword tokens return the keyword text (as a constant string) in yylval->kw, * just in case that's needed because we want to treat the keyword as an * unreserved identifier. Note that _null_ is not treated as a keyword * for this purpose; it's the one "reserved word" in the bootstrap syntax. @@ -66,23 +68,23 @@ sid \'([^']|\'\')*\' * Notice that all the keywords are case-sensitive, and for historical * reasons some must be upper case. * - * String tokens return a palloc'd string in boot_yylval.str. + * String tokens return a palloc'd string in yylval->str. */ %% -open { boot_yylval.kw = "open"; return OPEN; } +open { yylval->kw = "open"; return OPEN; } -close { boot_yylval.kw = "close"; return XCLOSE; } +close { yylval->kw = "close"; return XCLOSE; } -create { boot_yylval.kw = "create"; return XCREATE; } +create { yylval->kw = "create"; return XCREATE; } -OID { boot_yylval.kw = "OID"; return OBJ_ID; } -bootstrap { boot_yylval.kw = "bootstrap"; return XBOOTSTRAP; } -shared_relation { boot_yylval.kw = "shared_relation"; return XSHARED_RELATION; } -rowtype_oid { boot_yylval.kw = "rowtype_oid"; return XROWTYPE_OID; } +OID { yylval->kw = "OID"; return OBJ_ID; } +bootstrap { yylval->kw = "bootstrap"; return XBOOTSTRAP; } +shared_relation { yylval->kw = "shared_relation"; return XSHARED_RELATION; } +rowtype_oid { yylval->kw = "rowtype_oid"; return XROWTYPE_OID; } -insert { boot_yylval.kw = "insert"; return INSERT_TUPLE; } +insert { yylval->kw = "insert"; return INSERT_TUPLE; } _null_ { return NULLVAL; } @@ -91,35 +93,35 @@ _null_ { return NULLVAL; } "(" { return LPAREN; } ")" { return RPAREN; } -[\n] { yyline++; } +[\n] { yylineno++; } [\r\t ] ; ^\#[^\n]* ; /* drop everything after "#" for comments */ -declare { boot_yylval.kw = "declare"; return XDECLARE; } -build { boot_yylval.kw = "build"; return XBUILD; } -indices { boot_yylval.kw = "indices"; return INDICES; } -unique { boot_yylval.kw = "unique"; return UNIQUE; } -index { boot_yylval.kw = "index"; return INDEX; } -on { boot_yylval.kw = "on"; return ON; } -using { boot_yylval.kw = "using"; return USING; } -toast { boot_yylval.kw = "toast"; return XTOAST; } -FORCE { boot_yylval.kw = "FORCE"; return XFORCE; } -NOT { boot_yylval.kw = "NOT"; return XNOT; } -NULL { boot_yylval.kw = "NULL"; return XNULL; } +declare { yylval->kw = "declare"; return XDECLARE; } +build { yylval->kw = "build"; return XBUILD; } +indices { yylval->kw = "indices"; return INDICES; } +unique { yylval->kw = "unique"; return UNIQUE; } +index { yylval->kw = "index"; return INDEX; } +on { yylval->kw = "on"; return ON; } +using { yylval->kw = "using"; return USING; } +toast { yylval->kw = "toast"; return XTOAST; } +FORCE { yylval->kw = "FORCE"; return XFORCE; } +NOT { yylval->kw = "NOT"; return XNOT; } +NULL { yylval->kw = "NULL"; return XNULL; } {id} { - boot_yylval.str = pstrdup(yytext); + yylval->str = pstrdup(yytext); return ID; } {sid} { /* strip quotes and escapes */ - boot_yylval.str = DeescapeQuotedString(yytext); + yylval->str = DeescapeQuotedString(yytext); return ID; } . { - elog(ERROR, "syntax error at line %d: unexpected character \"%s\"", yyline, yytext); + elog(ERROR, "syntax error at line %d: unexpected character \"%s\"", yylineno, yytext); } %% @@ -127,7 +129,37 @@ NULL { boot_yylval.kw = "NULL"; return XNULL; } /* LCOV_EXCL_STOP */ void -boot_yyerror(const char *message) +boot_yyerror(yyscan_t yyscanner, const char *message) +{ + struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yylineno + * macro */ + + elog(ERROR, "%s at line %d", message, yylineno); +} + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + return palloc(size); +} + +void * +yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, size); + else + return palloc(size); +} + +void +yyfree(void *ptr, yyscan_t yyscanner) { - elog(ERROR, "%s at line %d", message, yyline); + if (ptr) + pfree(ptr); } diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 7637581a1845f..6db864892d0dd 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -4,7 +4,7 @@ * routines to support running postgres in 'bootstrap' mode * bootstrap mode is used to create the initial template database * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -31,6 +31,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "pg_getopt.h" +#include "postmaster/postmaster.h" #include "storage/bufpage.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -201,6 +202,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) int flag; char *userDoption = NULL; uint32 bootstrap_data_checksum_version = 0; /* No checksum */ + yyscan_t scanner; Assert(!IsUnderPostmaster); @@ -223,8 +225,21 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) case 'B': SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; - case 'c': case '-': + + /* + * Error if the user misplaced a special must-be-first option + * for dispatching to a subprogram. parse_dispatch_option() + * returns DISPATCH_POSTMASTER if it doesn't find a match, so + * error for anything else. + */ + if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("--%s must be first argument", optarg))); + + /* FALLTHROUGH */ + case 'c': { char *name, *value; @@ -309,8 +324,23 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) InitializeMaxBackends(); + /* + * Even though bootstrapping runs in single-process mode, initialize + * postmaster child slots array so that --check can detect running out of + * shared memory or other resources if max_connections is set too high. + */ + InitPostmasterChildSlots(); + + InitializeFastPathLocks(); + CreateSharedMemoryAndSemaphores(); + /* + * Estimate number of openable files. This is essential too in --check + * mode, because on some platforms semaphores count as open files. + */ + set_max_safe_fds(); + /* * XXX: It might make sense to move this into its own function at some * point. Right now it seems like it'd cause more code duplication than @@ -349,11 +379,14 @@ BootstrapModeMain(int argc, char *argv[], bool check_only) Nulls[i] = false; } + if (boot_yylex_init(&scanner) != 0) + elog(ERROR, "yylex_init() failed: %m"); + /* * Process bootstrap input. */ StartTransactionCommand(); - boot_yyparse(); + boot_yyparse(scanner); CommitTransactionCommand(); /* @@ -430,8 +463,8 @@ boot_openrel(char *relname) { if (attrtypes[i] == NULL) attrtypes[i] = AllocateAttribute(); - memmove((char *) attrtypes[i], - (char *) TupleDescAttr(boot_reldesc->rd_att, i), + memmove(attrtypes[i], + TupleDescAttr(boot_reldesc->rd_att, i), ATTRIBUTE_FIXED_PART_SIZE); { @@ -547,7 +580,6 @@ DefineAttr(char *name, char *type, int attnum, int nullness) if (OidIsValid(attrtypes[attnum]->attcollation)) attrtypes[attnum]->attcollation = C_COLLATION_OID; - attrtypes[attnum]->attcacheoff = -1; attrtypes[attnum]->atttypmod = -1; attrtypes[attnum]->attislocal = true; diff --git a/src/backend/bootstrap/meson.build b/src/backend/bootstrap/meson.build index a8f821e98b445..29726c1ab4ff1 100644 --- a/src/backend/bootstrap/meson.build +++ b/src/backend/bootstrap/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bootstrap.c') diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm index 8e709524cba65..5a912549b82c0 100644 --- a/src/backend/catalog/Catalog.pm +++ b/src/backend/catalog/Catalog.pm @@ -4,7 +4,7 @@ # Perl module that extracts info from catalog files into Perl # data structures # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/catalog/Catalog.pm diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile index 1589a75fd5332..c090094ed08d5 100644 --- a/src/backend/catalog/Makefile +++ b/src/backend/catalog/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/catalog # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/catalog/Makefile diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index a44ccee3b681f..9ca8a88dc9104 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -3,7 +3,7 @@ * aclchk.c * Routines to check access control permissions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -75,6 +75,7 @@ #include "nodes/makefuncs.h" #include "parser/parse_func.h" #include "parser/parse_type.h" +#include "storage/lmgr.h" #include "utils/acl.h" #include "utils/aclchk_internal.h" #include "utils/builtins.h" @@ -658,147 +659,77 @@ ExecGrantStmt_oids(InternalGrant *istmt) * objectNamesToOids * * Turn a list of object names of a given type into an Oid list. - * - * XXX: This function doesn't take any sort of locks on the objects whose - * names it looks up. In the face of concurrent DDL, we might easily latch - * onto an old version of an object, causing the GRANT or REVOKE statement - * to fail. */ static List * objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant) { List *objects = NIL; ListCell *cell; + const LOCKMODE lockmode = AccessShareLock; Assert(objnames != NIL); switch (objtype) { - case OBJECT_TABLE: - case OBJECT_SEQUENCE: - foreach(cell, objnames) - { - RangeVar *relvar = (RangeVar *) lfirst(cell); - Oid relOid; - - relOid = RangeVarGetRelid(relvar, NoLock, false); - objects = lappend_oid(objects, relOid); - } - break; - case OBJECT_DATABASE: - foreach(cell, objnames) - { - char *dbname = strVal(lfirst(cell)); - Oid dbid; - - dbid = get_database_oid(dbname, false); - objects = lappend_oid(objects, dbid); - } - break; - case OBJECT_DOMAIN: - case OBJECT_TYPE: - foreach(cell, objnames) - { - List *typname = (List *) lfirst(cell); - Oid oid; - - oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname)); - objects = lappend_oid(objects, oid); - } - break; - case OBJECT_FUNCTION: - foreach(cell, objnames) - { - ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell); - Oid funcid; + default: - funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false); - objects = lappend_oid(objects, funcid); - } - break; - case OBJECT_LANGUAGE: + /* + * For most object types, we use get_object_address() directly. + */ foreach(cell, objnames) { - char *langname = strVal(lfirst(cell)); - Oid oid; + ObjectAddress address; - oid = get_language_oid(langname, false); - objects = lappend_oid(objects, oid); + address = get_object_address(objtype, lfirst(cell), NULL, lockmode, false); + objects = lappend_oid(objects, address.objectId); } break; - case OBJECT_LARGEOBJECT: - foreach(cell, objnames) - { - Oid lobjOid = oidparse(lfirst(cell)); - - if (!LargeObjectExists(lobjOid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("large object %u does not exist", - lobjOid))); - objects = lappend_oid(objects, lobjOid); - } - break; - case OBJECT_SCHEMA: - foreach(cell, objnames) - { - char *nspname = strVal(lfirst(cell)); - Oid oid; + case OBJECT_TABLE: + case OBJECT_SEQUENCE: - oid = get_namespace_oid(nspname, false); - objects = lappend_oid(objects, oid); - } - break; - case OBJECT_PROCEDURE: + /* + * Here, we don't use get_object_address(). It requires that the + * specified object type match the actual type of the object, but + * in GRANT/REVOKE, all table-like things are addressed as TABLE. + */ foreach(cell, objnames) { - ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell); - Oid procid; + RangeVar *relvar = (RangeVar *) lfirst(cell); + Oid relOid; - procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false); - objects = lappend_oid(objects, procid); + relOid = RangeVarGetRelid(relvar, lockmode, false); + objects = lappend_oid(objects, relOid); } break; - case OBJECT_ROUTINE: - foreach(cell, objnames) - { - ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell); - Oid routid; - routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false); - objects = lappend_oid(objects, routid); - } - break; - case OBJECT_TABLESPACE: - foreach(cell, objnames) - { - char *spcname = strVal(lfirst(cell)); - Oid spcoid; + case OBJECT_DOMAIN: + case OBJECT_TYPE: - spcoid = get_tablespace_oid(spcname, false); - objects = lappend_oid(objects, spcoid); - } - break; - case OBJECT_FDW: + /* + * The parse representation of types and domains in privilege + * targets is different from that expected by get_object_address() + * (for parse conflict reasons), so we have to do a bit of + * conversion here. + */ foreach(cell, objnames) { - char *fdwname = strVal(lfirst(cell)); - Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false); + List *typname = (List *) lfirst(cell); + TypeName *tn = makeTypeNameFromNameList(typname); + ObjectAddress address; + Relation relation; - objects = lappend_oid(objects, fdwid); + address = get_object_address(objtype, (Node *) tn, &relation, lockmode, false); + Assert(relation == NULL); + objects = lappend_oid(objects, address.objectId); } break; - case OBJECT_FOREIGN_SERVER: - foreach(cell, objnames) - { - char *srvname = strVal(lfirst(cell)); - Oid srvid = get_foreign_server_oid(srvname, false); - objects = lappend_oid(objects, srvid); - } - break; case OBJECT_PARAMETER_ACL: + + /* + * Parameters are handled completely differently. + */ foreach(cell, objnames) { /* @@ -829,9 +760,6 @@ objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant) objects = lappend_oid(objects, parameterId); } break; - default: - elog(ERROR, "unrecognized GrantStmt.objtype: %d", - (int) objtype); } return objects; @@ -1077,6 +1005,10 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s all_privileges = ACL_ALL_RIGHTS_SCHEMA; errormsg = gettext_noop("invalid privilege type %s for schema"); break; + case OBJECT_LARGEOBJECT: + all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT; + errormsg = gettext_noop("invalid privilege type %s for large object"); + break; default: elog(ERROR, "unrecognized GrantStmt.objtype: %d", (int) action->objtype); @@ -1268,6 +1200,16 @@ SetDefaultACL(InternalDefaultACL *iacls) this_privileges = ACL_ALL_RIGHTS_SCHEMA; break; + case OBJECT_LARGEOBJECT: + if (OidIsValid(iacls->nspid)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_GRANT_OPERATION), + errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON LARGE OBJECTS"))); + objtype = DEFACLOBJ_LARGEOBJECT; + if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS) + this_privileges = ACL_ALL_RIGHTS_LARGEOBJECT; + break; + default: elog(ERROR, "unrecognized object type: %d", (int) iacls->objtype); @@ -1511,6 +1453,9 @@ RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid) case DEFACLOBJ_NAMESPACE: iacls.objtype = OBJECT_SCHEMA; break; + case DEFACLOBJ_LARGEOBJECT: + iacls.objtype = OBJECT_LARGEOBJECT; + break; default: /* Shouldn't get here */ elog(ERROR, "unexpected default ACL type: %d", @@ -1848,7 +1793,7 @@ ExecGrant_Relation(InternalGrant *istmt) HeapTuple tuple; ListCell *cell_colprivs; - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid)); + tuple = SearchSysCacheLocked1(RELOID, ObjectIdGetDatum(relOid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relOid); pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); @@ -2060,6 +2005,7 @@ ExecGrant_Relation(InternalGrant *istmt) values, nulls, replaces); CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl); @@ -2072,6 +2018,8 @@ ExecGrant_Relation(InternalGrant *istmt) pfree(new_acl); } + else + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* * Handle column-level privileges, if any were specified or implied. @@ -2185,7 +2133,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, Oid *oldmembers; Oid *newmembers; - tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid)); + tuple = SearchSysCacheLocked1(cacheid, ObjectIdGetDatum(objectid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for %s %u", get_object_class_descr(classid), objectid); @@ -2261,6 +2209,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, nulls, replaces); CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ recordExtensionInitPriv(objectid, classid, 0, new_acl); @@ -2453,14 +2402,6 @@ ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple) (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("cannot set privileges of multirange types"), errhint("Set the privileges of the range type instead."))); - - /* Used GRANT DOMAIN on a non-domain? */ - if (istmt->objtype == OBJECT_DOMAIN && - pg_type_tuple->typtype != TYPTYPE_DOMAIN) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a domain", - NameStr(pg_type_tuple->typname)))); } static void @@ -2641,8 +2582,6 @@ string_to_privilege(const char *privname) return ACL_ALTER_SYSTEM; if (strcmp(privname, "maintain") == 0) return ACL_MAINTAIN; - if (strcmp(privname, "rule") == 0) - return 0; /* ignore old RULE privileges */ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("unrecognized privilege type \"%s\"", privname))); @@ -3082,10 +3021,6 @@ pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid, * Exported routines for examining a user's privileges for various objects * * See aclmask() for a description of the common API for these functions. - * - * Note: we give lookup failure the full ereport treatment because the - * has_xxx_privilege() family of functions allow users to pass any random - * OID to these functions. * **************************************************************** */ @@ -3152,10 +3087,8 @@ object_aclmask_ext(Oid classid, Oid objectid, Oid roleid, return 0; } else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("%s with OID %u does not exist", - get_object_class_descr(classid), objectid))); + elog(ERROR, "cache lookup failed for %s %u", + get_object_class_descr(classid), objectid); } ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid, @@ -3446,7 +3379,7 @@ pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, * Check if ACL_MAINTAIN is being checked and, if so, and not already set * as part of the result, then check if the user is a member of the * pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH - * MATERIALIZED VIEW, and REINDEX on all relations. + * MATERIALIZED VIEW, REINDEX, and LOCK TABLE on all relations. */ if (mask & ACL_MAINTAIN && !(result & ACL_MAINTAIN) && @@ -4160,9 +4093,8 @@ object_ownercheck(Oid classid, Oid objectid, Oid roleid) tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid)); if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid))); + elog(ERROR, "cache lookup failed for %s %u", + get_object_class_descr(classid), objectid); ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid, tuple, @@ -4191,9 +4123,8 @@ object_ownercheck(Oid classid, Oid objectid, Oid roleid) tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid))); + elog(ERROR, "could not find tuple for %s %u", + get_object_class_descr(classid), objectid); ownerId = DatumGetObjectId(heap_getattr(tuple, get_object_attnum_owner(classid), @@ -4336,6 +4267,10 @@ get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid) defaclobjtype = DEFACLOBJ_NAMESPACE; break; + case OBJECT_LARGEOBJECT: + defaclobjtype = DEFACLOBJ_LARGEOBJECT; + break; + default: return NULL; } diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index 6c39434a30667..59caae8f1bc23 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -5,7 +5,7 @@ * bits of hard-wired knowledge * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -34,6 +34,7 @@ #include "catalog/pg_namespace.h" #include "catalog/pg_parameter_acl.h" #include "catalog/pg_replication_origin.h" +#include "catalog/pg_seclabel.h" #include "catalog/pg_shdepend.h" #include "catalog/pg_shdescription.h" #include "catalog/pg_shseclabel.h" @@ -135,9 +136,48 @@ IsCatalogRelationOid(Oid relid) return (relid < (Oid) FirstUnpinnedObjectId); } +/* + * IsCatalogTextUniqueIndexOid + * True iff the relation identified by this OID is a catalog UNIQUE index + * having a column of type "text". + * + * The relcache must not use these indexes. Inserting into any UNIQUE + * index compares index keys while holding BUFFER_LOCK_EXCLUSIVE. + * bttextcmp() can search the COLLOID catcache. Depending on concurrent + * invalidation traffic, catcache can reach relcache builds. A backend + * would self-deadlock on LWLocks if the relcache build read the + * exclusive-locked buffer. + * + * To avoid being itself the cause of self-deadlock, this doesn't read + * catalogs. Instead, it uses a hard-coded list with a supporting + * regression test. + */ +bool +IsCatalogTextUniqueIndexOid(Oid relid) +{ + switch (relid) + { + case ParameterAclParnameIndexId: + case ReplicationOriginNameIndex: + case SecLabelObjectIndexId: + case SharedSecLabelObjectIndexId: + return true; + } + return false; +} + /* * IsInplaceUpdateRelation * True iff core code performs inplace updates on the relation. + * + * This is used for assertions and for making the executor follow the + * locking protocol described at README.tuplock section "Locking to write + * inplace-updated tables". Extensions may inplace-update other heap + * tables, but concurrent SQL UPDATE on the same table may overwrite + * those modifications. + * + * The executor can assume these are not partitions or partitioned and + * have no triggers. */ bool IsInplaceUpdateRelation(Relation relation) @@ -300,16 +340,12 @@ IsSharedRelation(Oid relationId) relationId == TablespaceOidIndexId) return true; /* These are their toast tables and toast indexes */ - if (relationId == PgAuthidToastTable || - relationId == PgAuthidToastIndex || - relationId == PgDatabaseToastTable || + if (relationId == PgDatabaseToastTable || relationId == PgDatabaseToastIndex || relationId == PgDbRoleSettingToastTable || relationId == PgDbRoleSettingToastIndex || relationId == PgParameterAclToastTable || relationId == PgParameterAclToastIndex || - relationId == PgReplicationOriginToastTable || - relationId == PgReplicationOriginToastIndex || relationId == PgShdescriptionToastTable || relationId == PgShdescriptionToastIndex || relationId == PgShseclabelToastTable || @@ -467,10 +503,10 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn) ereport(LOG, (errmsg("still searching for an unused OID in relation \"%s\"", RelationGetRelationName(relation)), - errdetail_plural("OID candidates have been checked %llu time, but no unused OID has been found yet.", - "OID candidates have been checked %llu times, but no unused OID has been found yet.", + errdetail_plural("OID candidates have been checked %" PRIu64 " time, but no unused OID has been found yet.", + "OID candidates have been checked %" PRIu64 " times, but no unused OID has been found yet.", retries, - (unsigned long long) retries))); + retries))); /* * Double the number of retries to do before logging next until it @@ -492,10 +528,10 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn) if (retries > GETNEWOID_LOG_THRESHOLD) { ereport(LOG, - (errmsg_plural("new OID has been assigned in relation \"%s\" after %llu retry", - "new OID has been assigned in relation \"%s\" after %llu retries", + (errmsg_plural("new OID has been assigned in relation \"%s\" after %" PRIu64 " retry", + "new OID has been assigned in relation \"%s\" after %" PRIu64 " retries", retries, - RelationGetRelationName(relation), (unsigned long long) retries))); + RelationGetRelationName(relation), retries))); } return newOid; @@ -521,7 +557,7 @@ RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence) { RelFileLocatorBackend rlocator; - char *rpath; + RelPathStr rpath; bool collides; ProcNumber procNumber; @@ -573,7 +609,7 @@ GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence) /* Check for existing file of same name */ rpath = relpath(rlocator, MAIN_FORKNUM); - if (access(rpath, F_OK) == 0) + if (access(rpath.str, F_OK) == 0) { /* definite collision */ collides = true; @@ -589,8 +625,6 @@ GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence) */ collides = false; } - - pfree(rpath); } while (collides); return rlocator.locator.relNumber; diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 0489cbabcb8a9..18316a3968bcf 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -4,7 +4,7 @@ * Routines to support inter-object dependencies. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -2191,7 +2191,22 @@ find_expr_references_walker(Node *node, } context->rtables = list_delete_first(context->rtables); break; + case RTE_NAMEDTUPLESTORE: + + /* + * Cataloged objects cannot depend on tuplestores, because + * those have no cataloged representation. For now we can + * call the tuplestore a "transition table" because that's + * the only kind exposed to SQL, but someday we might have + * to work harder. + */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("transition table \"%s\" cannot be referenced in a persistent object", + rte->eref->aliasname))); + break; default: + /* Other RTE types can be ignored here */ break; } } @@ -2240,7 +2255,7 @@ find_expr_references_walker(Node *node, context->rtables = lcons(query->rtable, context->rtables); result = query_tree_walker(query, find_expr_references_walker, - (void *) context, + context, QTW_IGNORE_JOINALIASES | QTW_EXAMINE_SORTGROUP); context->rtables = list_delete_first(context->rtables); @@ -2310,7 +2325,7 @@ find_expr_references_walker(Node *node, } return expression_tree_walker(node, find_expr_references_walker, - (void *) context); + context); } /* diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl index 94afdc5491dd8..df3231fcd41c2 100644 --- a/src/backend/catalog/genbki.pl +++ b/src/backend/catalog/genbki.pl @@ -6,7 +6,7 @@ # headers from specially formatted header files and data files. # postgres.bki is used to initialize the postgres template database. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/catalog/genbki.pl @@ -480,6 +480,8 @@ EOM + printf $def "/* Macros related to the structure of $catname */\n\n"; + # Emit OID macros for catalog's OID and rowtype OID, if wanted printf $def "#define %s %s\n", $catalog->{relation_oid_macro}, $catalog->{relation_oid} @@ -561,6 +563,7 @@ print $def "\n#define Natts_$catname $attnum\n\n"; # Emit client code copied from source header + printf $def "/* Definitions copied from ${catname}.h */\n\n"; foreach my $line (@{ $catalog->{client_code} }) { print $def $line; @@ -573,6 +576,9 @@ print $bki "open $catname\n"; } + printf $def + "\n/* OID symbols for objects defined in ${catname}.dat */\n\n"; + # For pg_attribute.h, we generate data entries ourselves. if ($catname eq 'pg_attribute') { @@ -1156,7 +1162,7 @@ sub print_boilerplate * %s * %s * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 01b43cc6a8442..10f43c51c5af0 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -3,7 +3,7 @@ * heap.c * code to create and destroy POSTGRES heap relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -69,6 +69,7 @@ #include "pgstat.h" #include "storage/lmgr.h" #include "storage/predicate.h" +#include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/inval.h" @@ -102,12 +103,13 @@ static ObjectAddress AddNewRelationType(const char *typeName, Oid new_array_type); static void RelationRemoveInheritance(Oid relid); static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, - bool is_validated, bool is_local, int inhcount, - bool is_no_inherit, bool is_internal); + bool is_enforced, bool is_validated, bool is_local, + int16 inhcount, bool is_no_inherit, bool is_internal); static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal); static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, + bool is_enforced, bool is_initially_valid, bool is_no_inherit); static void SetRelationNumChecks(Relation rel, int numchecks); @@ -144,7 +146,6 @@ static const FormData_pg_attribute a1 = { .atttypid = TIDOID, .attlen = sizeof(ItemPointerData), .attnum = SelfItemPointerAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = false, .attalign = TYPALIGN_SHORT, @@ -158,7 +159,6 @@ static const FormData_pg_attribute a2 = { .atttypid = XIDOID, .attlen = sizeof(TransactionId), .attnum = MinTransactionIdAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = true, .attalign = TYPALIGN_INT, @@ -172,7 +172,6 @@ static const FormData_pg_attribute a3 = { .atttypid = CIDOID, .attlen = sizeof(CommandId), .attnum = MinCommandIdAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = true, .attalign = TYPALIGN_INT, @@ -186,7 +185,6 @@ static const FormData_pg_attribute a4 = { .atttypid = XIDOID, .attlen = sizeof(TransactionId), .attnum = MaxTransactionIdAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = true, .attalign = TYPALIGN_INT, @@ -200,7 +198,6 @@ static const FormData_pg_attribute a5 = { .atttypid = CIDOID, .attlen = sizeof(CommandId), .attnum = MaxCommandIdAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = true, .attalign = TYPALIGN_INT, @@ -220,7 +217,6 @@ static const FormData_pg_attribute a6 = { .atttypid = OIDOID, .attlen = sizeof(Oid), .attnum = TableOidAttributeNumber, - .attcacheoff = -1, .atttypmod = -1, .attbyval = true, .attalign = TYPALIGN_INT, @@ -433,7 +429,7 @@ heap_create(const char *relname, * 6) AddNewAttributeTuples() is called to register the * new relation's schema in pg_attribute. * - * 7) StoreConstraints is called () - vadim 08/22/97 + * 7) StoreConstraints() is called - vadim 08/22/97 * * 8) the relations are closed and the new relation's oid * is returned. @@ -512,7 +508,7 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, TupleDescAttr(tupdesc, i)->atttypid, TupleDescAttr(tupdesc, i)->attcollation, NIL, /* assume we're creating a new rowtype */ - flags); + flags | (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL ? CHKATYPE_IS_VIRTUAL : 0)); } } @@ -587,6 +583,17 @@ CheckAttributeType(const char *attname, } else if (att_typtype == TYPTYPE_DOMAIN) { + /* + * Prevent virtual generated columns from having a domain type. We + * would have to enforce domain constraints when columns underlying + * the generated column change. This could possibly be implemented, + * but it's not. + */ + if (flags & CHKATYPE_IS_VIRTUAL) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("virtual generated column \"%s\" cannot have a domain type", attname)); + /* * If it's a domain, recurse to check its base type. */ @@ -684,11 +691,10 @@ CheckAttributeType(const char *attname, * Construct and insert a set of tuples in pg_attribute. * * Caller has already opened and locked pg_attribute. tupdesc contains the - * attributes to insert. attcacheoff is always initialized to -1. - * tupdesc_extra supplies the values for certain variable-length/nullable - * pg_attribute fields and must contain the same number of elements as tupdesc - * or be NULL. The other variable-length fields of pg_attribute are always - * initialized to null values. + * attributes to insert. tupdesc_extra supplies the values for certain + * variable-length/nullable pg_attribute fields and must contain the same + * number of elements as tupdesc or be NULL. The other variable-length fields + * of pg_attribute are always initialized to null values. * * indstate is the index state for CatalogTupleInsertWithInfo. It can be * passed as NULL, in which case we'll fetch the necessary info. (Don't do @@ -740,7 +746,6 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid); slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen); slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum); - slot[slotCount]->tts_values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1); slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod); slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int16GetDatum(attrs->attndims); slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval); @@ -920,6 +925,7 @@ InsertPgClassTuple(Relation pg_class_desc, values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages); values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples); values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible); + values[Anum_pg_class_relallfrozen - 1] = Int32GetDatum(rd_rel->relallfrozen); values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid); values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex); values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared); @@ -990,6 +996,7 @@ AddNewRelationTuple(Relation pg_class_desc, new_rel_reltup->relpages = 0; new_rel_reltup->reltuples = -1; new_rel_reltup->relallvisible = 0; + new_rel_reltup->relallfrozen = 0; /* Sequences always have a known size */ if (relkind == RELKIND_SEQUENCE) @@ -1093,6 +1100,7 @@ AddNewRelationType(const char *typeName, * if false, relacl is always set NULL * allow_system_table_mods: true to allow creation in system namespaces * is_internal: is this a system-generated catalog? + * relrewrite: link to original relation during a table rewrite * * Output parameters: * typaddress: if not null, gets the object address of the new pg_type entry @@ -1471,9 +1479,11 @@ heap_create_with_catalog(const char *relname, * access method is. * * No need to add an explicit dependency for the toast table, as the - * main table depends on it. + * main table depends on it. Partitioned tables may not have an + * access method set. */ - if (RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE) + if ((RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE) || + (relkind == RELKIND_PARTITIONED_TABLE && OidIsValid(accessmtd))) { ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd); add_exact_object_address(&referenced, addrs); @@ -1487,7 +1497,7 @@ heap_create_with_catalog(const char *relname, InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal); /* - * Store any supplied constraints and defaults. + * Store any supplied CHECK constraints and defaults. * * NB: this may do a CommandCounterIncrement and rebuild the relcache * entry, so the relation must be valid and self-consistent at this point. @@ -2002,6 +2012,60 @@ RelationClearMissing(Relation rel) table_close(attr_rel, RowExclusiveLock); } +/* + * StoreAttrMissingVal + * + * Set the missing value of a single attribute. + */ +void +StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) +{ + Datum valuesAtt[Natts_pg_attribute] = {0}; + bool nullsAtt[Natts_pg_attribute] = {0}; + bool replacesAtt[Natts_pg_attribute] = {0}; + Relation attrrel; + Form_pg_attribute attStruct; + HeapTuple atttup, + newtup; + + /* This is only supported for plain tables */ + Assert(rel->rd_rel->relkind == RELKIND_RELATION); + + /* Fetch the pg_attribute row */ + attrrel = table_open(AttributeRelationId, RowExclusiveLock); + + atttup = SearchSysCache2(ATTNUM, + ObjectIdGetDatum(RelationGetRelid(rel)), + Int16GetDatum(attnum)); + if (!HeapTupleIsValid(atttup)) /* shouldn't happen */ + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, RelationGetRelid(rel)); + attStruct = (Form_pg_attribute) GETSTRUCT(atttup); + + /* Make a one-element array containing the value */ + missingval = PointerGetDatum(construct_array(&missingval, + 1, + attStruct->atttypid, + attStruct->attlen, + attStruct->attbyval, + attStruct->attalign)); + + /* Update the pg_attribute row */ + valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true); + replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true; + + valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval; + replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; + + newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), + valuesAtt, nullsAtt, replacesAtt); + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); + + /* clean up */ + ReleaseSysCache(atttup); + table_close(attrrel, RowExclusiveLock); +} + /* * SetAttrMissing * @@ -2072,8 +2136,8 @@ SetAttrMissing(Oid relid, char *attname, char *value) */ static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, - bool is_validated, bool is_local, int inhcount, - bool is_no_inherit, bool is_internal) + bool is_enforced, bool is_validated, bool is_local, + int16 inhcount, bool is_no_inherit, bool is_internal) { char *ccbin; List *varList; @@ -2138,6 +2202,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr, CONSTRAINT_CHECK, /* Constraint Type */ false, /* Is Deferrable */ false, /* Is Deferred */ + is_enforced, /* Is Enforced */ is_validated, InvalidOid, /* no parent constraint */ RelationGetRelid(rel), /* relation */ @@ -2163,6 +2228,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr, is_local, /* conislocal */ inhcount, /* coninhcount */ is_no_inherit, /* connoinherit */ + false, /* conperiod */ is_internal); /* internally constructed? */ pfree(ccbin); @@ -2171,7 +2237,58 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr, } /* - * Store defaults and constraints (passed as a list of CookedConstraint). + * Store a not-null constraint for the given relation + * + * The OID of the new constraint is returned. + */ +static Oid +StoreRelNotNull(Relation rel, const char *nnname, AttrNumber attnum, + bool is_validated, bool is_local, int inhcount, + bool is_no_inherit) +{ + Oid constrOid; + + Assert(attnum > InvalidAttrNumber); + + constrOid = + CreateConstraintEntry(nnname, + RelationGetNamespace(rel), + CONSTRAINT_NOTNULL, + false, + false, + true, /* Is Enforced */ + is_validated, + InvalidOid, + RelationGetRelid(rel), + &attnum, + 1, + 1, + InvalidOid, /* not a domain constraint */ + InvalidOid, /* no associated index */ + InvalidOid, /* Foreign key fields */ + NULL, + NULL, + NULL, + NULL, + 0, + ' ', + ' ', + NULL, + 0, + ' ', + NULL, /* not an exclusion constraint */ + NULL, + NULL, + is_local, + inhcount, + is_no_inherit, + false, + false); + return constrOid; +} + +/* + * Store defaults and CHECK constraints (passed as a list of CookedConstraint). * * Each CookedConstraint struct is modified to store the new catalog tuple OID. * @@ -2204,16 +2321,17 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal) { case CONSTR_DEFAULT: con->conoid = StoreAttrDefault(rel, con->attnum, con->expr, - is_internal, false); + is_internal); break; case CONSTR_CHECK: con->conoid = StoreRelCheck(rel, con->name, con->expr, - !con->skip_validation, con->is_local, - con->inhcount, con->is_no_inherit, - is_internal); + con->is_enforced, !con->skip_validation, + con->is_local, con->inhcount, + con->is_no_inherit, is_internal); numchecks++; break; + default: elog(ERROR, "unrecognized constraint type: %d", (int) con->contype); @@ -2242,7 +2360,7 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal) * cooked CHECK constraints * * All entries in newColDefaults will be processed. Entries in newConstraints - * will be processed only if they are CONSTR_CHECK type. + * will be processed only if they are CONSTR_CHECK or CONSTR_NOTNULL types. * * Returns a list of CookedConstraint nodes that shows the cooked form of * the default and constraint expressions added to the relation. @@ -2271,6 +2389,7 @@ AddRelationNewConstraints(Relation rel, ParseNamespaceItem *nsitem; int numchecks; List *checknames; + List *nnnames; Node *expr; CookedConstraint *cooked; @@ -2329,13 +2448,7 @@ AddRelationNewConstraints(Relation rel, castNode(Const, expr)->constisnull)) continue; - /* If the DEFAULT is volatile we cannot use a missing value */ - if (colDef->missingMode && - contain_volatile_functions_after_planning((Expr *) expr)) - colDef->missingMode = false; - - defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal, - colDef->missingMode); + defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); cooked->contype = CONSTR_DEFAULT; @@ -2343,6 +2456,7 @@ AddRelationNewConstraints(Relation rel, cooked->name = NULL; cooked->attnum = colDef->attnum; cooked->expr = expr; + cooked->is_enforced = true; cooked->skip_validation = false; cooked->is_local = is_local; cooked->inhcount = is_local ? 0 : 1; @@ -2355,6 +2469,7 @@ AddRelationNewConstraints(Relation rel, */ numchecks = numoldchecks; checknames = NIL; + nnnames = NIL; foreach_node(Constraint, cdef, newConstraints) { Oid constrOid; @@ -2409,10 +2524,11 @@ AddRelationNewConstraints(Relation rel, * Check against pre-existing constraints. If we are allowed * to merge with an existing constraint, there's no more to do * here. (We omit the duplicate constraint from the result, - * which is what ATAddCheckConstraint wants.) + * which is what ATAddCheckNNConstraint wants.) */ if (MergeWithExistingConstraint(rel, ccname, expr, allow_merge, is_local, + cdef->is_enforced, cdef->initially_valid, cdef->is_no_inherit)) continue; @@ -2461,8 +2577,10 @@ AddRelationNewConstraints(Relation rel, * OK, store it. */ constrOid = - StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local, - is_local ? 0 : 1, cdef->is_no_inherit, is_internal); + StoreRelCheck(rel, ccname, expr, cdef->is_enforced, + cdef->initially_valid, is_local, + is_local ? 0 : 1, cdef->is_no_inherit, + is_internal); numchecks++; @@ -2472,12 +2590,90 @@ AddRelationNewConstraints(Relation rel, cooked->name = ccname; cooked->attnum = 0; cooked->expr = expr; + cooked->is_enforced = cdef->is_enforced; cooked->skip_validation = cdef->skip_validation; cooked->is_local = is_local; cooked->inhcount = is_local ? 0 : 1; cooked->is_no_inherit = cdef->is_no_inherit; cookedConstraints = lappend(cookedConstraints, cooked); } + else if (cdef->contype == CONSTR_NOTNULL) + { + CookedConstraint *nncooked; + AttrNumber colnum; + int16 inhcount = is_local ? 0 : 1; + char *nnname; + + /* Determine which column to modify */ + colnum = get_attnum(RelationGetRelid(rel), strVal(linitial(cdef->keys))); + if (colnum == InvalidAttrNumber) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + strVal(linitial(cdef->keys)), RelationGetRelationName(rel))); + if (colnum < InvalidAttrNumber) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot add not-null constraint on system column \"%s\"", + strVal(linitial(cdef->keys)))); + + Assert(cdef->initially_valid != cdef->skip_validation); + + /* + * If the column already has a not-null constraint, we don't want + * to add another one; adjust inheritance status as needed. This + * also checks whether the existing constraint matches the + * requested validity. + */ + if (AdjustNotNullInheritance(RelationGetRelid(rel), colnum, + is_local, cdef->is_no_inherit, + cdef->skip_validation)) + continue; + + /* + * If a constraint name is specified, check that it isn't already + * used. Otherwise, choose a non-conflicting one ourselves. + */ + if (cdef->conname) + { + if (ConstraintNameIsUsed(CONSTRAINT_RELATION, + RelationGetRelid(rel), + cdef->conname)) + ereport(ERROR, + errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("constraint \"%s\" for relation \"%s\" already exists", + cdef->conname, RelationGetRelationName(rel))); + nnname = cdef->conname; + } + else + nnname = ChooseConstraintName(RelationGetRelationName(rel), + strVal(linitial(cdef->keys)), + "not_null", + RelationGetNamespace(rel), + nnnames); + nnnames = lappend(nnnames, nnname); + + constrOid = + StoreRelNotNull(rel, nnname, colnum, + cdef->initially_valid, + is_local, + inhcount, + cdef->is_no_inherit); + + nncooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); + nncooked->contype = CONSTR_NOTNULL; + nncooked->conoid = constrOid; + nncooked->name = nnname; + nncooked->attnum = colnum; + nncooked->expr = NULL; + nncooked->is_enforced = true; + nncooked->skip_validation = cdef->skip_validation; + nncooked->is_local = is_local; + nncooked->inhcount = inhcount; + nncooked->is_no_inherit = cdef->is_no_inherit; + + cookedConstraints = lappend(cookedConstraints, nncooked); + } } /* @@ -2505,6 +2701,7 @@ AddRelationNewConstraints(Relation rel, static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, + bool is_enforced, bool is_initially_valid, bool is_no_inherit) { @@ -2595,12 +2792,24 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, * If the child constraint is "not valid" then cannot merge with a * valid parent constraint. */ - if (is_initially_valid && !con->convalidated) + if (is_initially_valid && con->conenforced && !con->convalidated) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"", ccname, RelationGetRelationName(rel)))); + /* + * A non-enforced child constraint cannot be merged with an enforced + * parent constraint. However, the reverse is allowed, where the child + * constraint is enforced. + */ + if ((!is_local && is_enforced && !con->conenforced) || + (is_local && !is_enforced && con->conenforced)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"", + ccname, RelationGetRelationName(rel)))); + /* OK to update the tuple */ ereport(NOTICE, (errmsg("merging constraint \"%s\" with inherited definition", @@ -2623,10 +2832,8 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, { if (is_local) con->conislocal = true; - else - con->coninhcount++; - - if (con->coninhcount < 0) + else if (pg_add_s16_overflow(con->coninhcount, 1, + &con->coninhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); @@ -2638,6 +2845,19 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, con->connoinherit = true; } + /* + * If the child constraint is required to be enforced while the parent + * constraint is not, this should be allowed by marking the child + * constraint as enforced. In the reverse case, an error would have + * already been thrown before reaching this point. + */ + if (is_enforced && !con->conenforced) + { + Assert(is_local); + con->conenforced = true; + con->convalidated = true; + } + CatalogTupleUpdate(conDesc, &tup->t_self, tup); } @@ -2647,6 +2867,262 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, return found; } +/* + * Create the not-null constraints when creating a new relation + * + * These come from two sources: the 'constraints' list (of Constraint) is + * specified directly by the user; the 'old_notnulls' list (of + * CookedConstraint) comes from inheritance. We create one constraint + * for each column, giving priority to user-specified ones, and setting + * inhcount according to how many parents cause each column to get a + * not-null constraint. If a user-specified name clashes with another + * user-specified name, an error is raised. + * + * Returns a list of AttrNumber for columns that need to have the attnotnull + * flag set. + */ +List * +AddRelationNotNullConstraints(Relation rel, List *constraints, + List *old_notnulls) +{ + List *givennames; + List *nnnames; + List *nncols = NIL; + + /* + * We track two lists of names: nnnames keeps all the constraint names, + * givennames tracks user-generated names. The distinction is important, + * because we must raise error for user-generated name conflicts, but for + * system-generated name conflicts we just generate another. + */ + nnnames = NIL; + givennames = NIL; + + /* + * First, create all not-null constraints that are directly specified by + * the user. Note that inheritance might have given us another source for + * each, so we must scan the old_notnulls list and increment inhcount for + * each element with identical attnum. We delete from there any element + * that we process. + * + * We don't use foreach() here because we have two nested loops over the + * constraint list, with possible element deletions in the inner one. If + * we used foreach_delete_current() it could only fix up the state of one + * of the loops, so it seems cleaner to use looping over list indexes for + * both loops. Note that any deletion will happen beyond where the outer + * loop is, so its index never needs adjustment. + */ + for (int outerpos = 0; outerpos < list_length(constraints); outerpos++) + { + Constraint *constr; + AttrNumber attnum; + char *conname; + int inhcount = 0; + + constr = list_nth_node(Constraint, constraints, outerpos); + + Assert(constr->contype == CONSTR_NOTNULL); + + attnum = get_attnum(RelationGetRelid(rel), + strVal(linitial(constr->keys))); + if (attnum == InvalidAttrNumber) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + strVal(linitial(constr->keys)), + RelationGetRelationName(rel))); + if (attnum < InvalidAttrNumber) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot add not-null constraint on system column \"%s\"", + strVal(linitial(constr->keys)))); + + /* + * A column can only have one not-null constraint, so discard any + * additional ones that appear for columns we already saw; but check + * that the NO INHERIT flags match. + */ + for (int restpos = outerpos + 1; restpos < list_length(constraints);) + { + Constraint *other; + + other = list_nth_node(Constraint, constraints, restpos); + if (strcmp(strVal(linitial(constr->keys)), + strVal(linitial(other->keys))) == 0) + { + if (other->is_no_inherit != constr->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NO INHERIT declaration for not-null constraint on column \"%s\"", + strVal(linitial(constr->keys)))); + + /* + * Preserve constraint name if one is specified, but raise an + * error if conflicting ones are specified. + */ + if (other->conname) + { + if (!constr->conname) + constr->conname = pstrdup(other->conname); + else if (strcmp(constr->conname, other->conname) != 0) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting not-null constraint names \"%s\" and \"%s\"", + constr->conname, other->conname)); + } + + /* XXX do we need to verify any other fields? */ + constraints = list_delete_nth_cell(constraints, restpos); + } + else + restpos++; + } + + /* + * Search in the list of inherited constraints for any entries on the + * same column; determine an inheritance count from that. Also, if at + * least one parent has a constraint for this column, then we must not + * accept a user specification for a NO INHERIT one. Any constraint + * from parents that we process here is deleted from the list: we no + * longer need to process it in the loop below. + */ + foreach_ptr(CookedConstraint, old, old_notnulls) + { + if (old->attnum == attnum) + { + /* + * If we get a constraint from the parent, having a local NO + * INHERIT one doesn't work. + */ + if (constr->is_no_inherit) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("cannot define not-null constraint on column \"%s\" with NO INHERIT", + strVal(linitial(constr->keys))), + errdetail("The column has an inherited not-null constraint."))); + + inhcount++; + old_notnulls = foreach_delete_current(old_notnulls, old); + } + } + + /* + * Determine a constraint name, which may have been specified by the + * user, or raise an error if a conflict exists with another + * user-specified name. + */ + if (constr->conname) + { + foreach_ptr(char, thisname, givennames) + { + if (strcmp(thisname, constr->conname) == 0) + ereport(ERROR, + errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("constraint \"%s\" for relation \"%s\" already exists", + constr->conname, + RelationGetRelationName(rel))); + } + + conname = constr->conname; + givennames = lappend(givennames, conname); + } + else + conname = ChooseConstraintName(RelationGetRelationName(rel), + get_attname(RelationGetRelid(rel), + attnum, false), + "not_null", + RelationGetNamespace(rel), + nnnames); + nnnames = lappend(nnnames, conname); + + StoreRelNotNull(rel, conname, + attnum, true, true, + inhcount, constr->is_no_inherit); + + nncols = lappend_int(nncols, attnum); + } + + /* + * If any column remains in the old_notnulls list, we must create a not- + * null constraint marked not-local for that column. Because multiple + * parents could specify a not-null constraint for the same column, we + * must count how many there are and set an appropriate inhcount + * accordingly, deleting elements we've already processed. + * + * We don't use foreach() here because we have two nested loops over the + * constraint list, with possible element deletions in the inner one. If + * we used foreach_delete_current() it could only fix up the state of one + * of the loops, so it seems cleaner to use looping over list indexes for + * both loops. Note that any deletion will happen beyond where the outer + * loop is, so its index never needs adjustment. + */ + for (int outerpos = 0; outerpos < list_length(old_notnulls); outerpos++) + { + CookedConstraint *cooked; + char *conname = NULL; + int inhcount = 1; + + cooked = (CookedConstraint *) list_nth(old_notnulls, outerpos); + Assert(cooked->contype == CONSTR_NOTNULL); + Assert(cooked->name); + + /* + * Preserve the first non-conflicting constraint name we come across. + */ + if (conname == NULL) + conname = cooked->name; + + for (int restpos = outerpos + 1; restpos < list_length(old_notnulls);) + { + CookedConstraint *other; + + other = (CookedConstraint *) list_nth(old_notnulls, restpos); + Assert(other->name); + if (other->attnum == cooked->attnum) + { + if (conname == NULL) + conname = other->name; + + inhcount++; + old_notnulls = list_delete_nth_cell(old_notnulls, restpos); + } + else + restpos++; + } + + /* If we got a name, make sure it isn't one we've already used */ + if (conname != NULL) + { + foreach_ptr(char, thisname, nnnames) + { + if (strcmp(thisname, conname) == 0) + { + conname = NULL; + break; + } + } + } + + /* and choose a name, if needed */ + if (conname == NULL) + conname = ChooseConstraintName(RelationGetRelationName(rel), + get_attname(RelationGetRelid(rel), + cooked->attnum, false), + "not_null", + RelationGetNamespace(rel), + nnnames); + nnnames = lappend(nnnames, conname); + + /* ignore the origin constraint's is_local and inhcount */ + StoreRelNotNull(rel, conname, cooked->attnum, true, + false, inhcount, false); + + nncols = lappend_int(nncols, cooked->attnum); + } + + return nncols; +} + /* * Update the count of constraints in the relation's pg_class tuple. * @@ -2730,7 +3206,7 @@ check_nested_generated_walker(Node *node, void *context) } else return expression_tree_walker(node, check_nested_generated_walker, - (void *) context); + context); } static void diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index a819b4197cee7..739a92bdcc1ca 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3,7 +3,7 @@ * index.c * code to create and destroy POSTGRES index relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -63,6 +63,7 @@ #include "optimizer/optimizer.h" #include "parser/parser.h" #include "pgstat.h" +#include "postmaster/autovacuum.h" #include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" @@ -320,7 +321,6 @@ ConstructTupleDescriptor(Relation heapRelation, MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE); to->attnum = i + 1; - to->attcacheoff = -1; to->attislocal = true; to->attcollation = (i < numkeyatts) ? collationIds[i] : InvalidOid; @@ -477,6 +477,8 @@ ConstructTupleDescriptor(Relation heapRelation, ReleaseSysCache(tuple); } + + populate_compact_attribute(indexTupDesc, i); } pfree(amroutine); @@ -1394,7 +1396,8 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, oldInfo->ii_NullsNotDistinct, false, /* not ready for inserts */ true, - indexRelation->rd_indam->amsummarizing); + indexRelation->rd_indam->amsummarizing, + oldInfo->ii_WithoutOverlaps); /* * Extract the list of column names and the column numbers for the new @@ -1874,6 +1877,7 @@ index_concurrently_set_dead(Oid heapId, Oid indexId) * INDEX_CONSTR_CREATE_UPDATE_INDEX: update the pg_index row * INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS: remove existing dependencies * of index on table's columns + * INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS: constraint uses WITHOUT OVERLAPS * allow_system_table_mods: allow table to be a system catalog * is_internal: index is constructed due to internal process */ @@ -1897,11 +1901,13 @@ index_constraint_create(Relation heapRelation, bool mark_as_primary; bool islocal; bool noinherit; - int inhcount; + bool is_without_overlaps; + int16 inhcount; deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0; initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0; mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0; + is_without_overlaps = (constr_flags & INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS) != 0; /* constraint creation support doesn't work while bootstrapping */ Assert(!IsBootstrapProcessingMode()); @@ -1953,6 +1959,7 @@ index_constraint_create(Relation heapRelation, constraintType, deferrable, initdeferred, + true, /* Is Enforced */ true, parentConstraintId, RelationGetRelid(heapRelation), @@ -1978,6 +1985,7 @@ index_constraint_create(Relation heapRelation, islocal, inhcount, noinherit, + is_without_overlaps, is_internal); /* @@ -2271,9 +2279,17 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode) */ WaitForLockers(heaplocktag, AccessExclusiveLock, true); + /* + * Updating pg_index might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* Finish invalidation of index and mark it as dead */ index_concurrently_set_dead(heapId, indexId); + PopActiveSnapshot(); + /* * Again, commit the transaction to make the pg_index update visible * to other sessions. @@ -2321,6 +2337,12 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode) RelationForgetRelation(indexId); + /* + * Updating pg_index might involve TOAST table access, so ensure we have a + * valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* * fix INDEX relation, and check for expressional index */ @@ -2338,6 +2360,8 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode) ReleaseSysCache(tuple); table_close(indexRelation, RowExclusiveLock); + PopActiveSnapshot(); + /* * if it has any expression columns, we might have stored statistics about * them. @@ -2427,7 +2451,8 @@ BuildIndexInfo(Relation index) indexStruct->indnullsnotdistinct, indexStruct->indisready, false, - index->rd_indam->amsummarizing); + index->rd_indam->amsummarizing, + indexStruct->indisexclusion && indexStruct->indisunique); /* fill in attribute numbers */ for (i = 0; i < numAtts; i++) @@ -2486,7 +2511,8 @@ BuildDummyIndexInfo(Relation index) indexStruct->indnullsnotdistinct, indexStruct->indisready, false, - index->rd_indam->amsummarizing); + index->rd_indam->amsummarizing, + indexStruct->indisexclusion && indexStruct->indisunique); /* fill in attribute numbers */ for (i = 0; i < numAtts; i++) @@ -2631,8 +2657,9 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2, * Add extra state to IndexInfo record * * For unique indexes, we usually don't want to add info to the IndexInfo for - * checking uniqueness, since the B-Tree AM handles that directly. However, - * in the case of speculative insertion, additional support is required. + * checking uniqueness, since the B-Tree AM handles that directly. However, in + * the case of speculative insertion and conflict detection in logical + * replication, additional support is required. * * Do this processing here rather than in BuildIndexInfo() to not incur the * overhead in the common non-speculative cases. @@ -2651,9 +2678,6 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii) */ Assert(ii->ii_Unique); - if (index->rd_rel->relam != BTREE_AM_OID) - elog(ERROR, "unexpected non-btree speculative unique index"); - ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts); ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts); ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts); @@ -2665,7 +2689,11 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii) /* We need the func OIDs and strategy numbers too */ for (i = 0; i < indnkeyatts; i++) { - ii->ii_UniqueStrats[i] = BTEqualStrategyNumber; + ii->ii_UniqueStrats[i] = + IndexAmTranslateCompareType(COMPARE_EQ, + index->rd_rel->relam, + index->rd_opfamily[i], + false); ii->ii_UniqueOps[i] = get_opfamily_member(index->rd_opfamily[i], index->rd_opcintype[i], @@ -2766,8 +2794,8 @@ FormIndexDatum(IndexInfo *indexInfo, * hasindex: set relhasindex to this value * reltuples: if >= 0, set reltuples to this value; else no change * - * If reltuples >= 0, relpages and relallvisible are also updated (using - * RelationGetNumberOfBlocks() and visibilitymap_count()). + * If reltuples >= 0, relpages, relallvisible, and relallfrozen are also + * updated (using RelationGetNumberOfBlocks() and visibilitymap_count()). * * NOTE: an important side-effect of this operation is that an SI invalidation * message is sent out to all backends --- including me --- causing relcache @@ -2782,12 +2810,73 @@ index_update_stats(Relation rel, bool hasindex, double reltuples) { + bool update_stats; + BlockNumber relpages = 0; /* keep compiler quiet */ + BlockNumber relallvisible = 0; + BlockNumber relallfrozen = 0; Oid relid = RelationGetRelid(rel); Relation pg_class; + ScanKeyData key[1]; HeapTuple tuple; + void *state; Form_pg_class rd_rel; bool dirty; + /* + * As a special hack, if we are dealing with an empty table and the + * existing reltuples is -1, we leave that alone. This ensures that + * creating an index as part of CREATE TABLE doesn't cause the table to + * prematurely look like it's been vacuumed. The rd_rel we modify may + * differ from rel->rd_rel due to e.g. commit of concurrent GRANT, but the + * commands that change reltuples take locks conflicting with ours. (Even + * if a command changed reltuples under a weaker lock, this affects only + * statistics for an empty table.) + */ + if (reltuples == 0 && rel->rd_rel->reltuples < 0) + reltuples = -1; + + /* + * Don't update statistics during binary upgrade, because the indexes are + * created before the data is moved into place. + */ + update_stats = reltuples >= 0 && !IsBinaryUpgrade; + + /* + * If autovacuum is off, user may not be expecting table relstats to + * change. This can be important when restoring a dump that includes + * statistics, as the table statistics may be restored before the index is + * created, and we want to preserve the restored table statistics. + */ + if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_TOASTVALUE || + rel->rd_rel->relkind == RELKIND_MATVIEW) + { + if (AutoVacuumingActive()) + { + StdRdOptions *options = (StdRdOptions *) rel->rd_options; + + if (options != NULL && !options->autovacuum.enabled) + update_stats = false; + } + else + update_stats = false; + } + + /* + * Finish I/O and visibility map buffer locks before + * systable_inplace_update_begin() locks the pg_class buffer. The rd_rel + * we modify may differ from rel->rd_rel due to e.g. commit of concurrent + * GRANT, but no command changes a relkind from non-index to index. (Even + * if one did, relallvisible doesn't break functionality.) + */ + if (update_stats) + { + relpages = RelationGetNumberOfBlocks(rel); + + if (rel->rd_rel->relkind != RELKIND_INDEX) + visibilitymap_count(rel, &relallvisible, &relallfrozen); + } + /* * We always update the pg_class row using a non-transactional, * overwrite-in-place update. There are several reasons for this: @@ -2818,33 +2907,12 @@ index_update_stats(Relation rel, pg_class = table_open(RelationRelationId, RowExclusiveLock); - /* - * Make a copy of the tuple to update. Normally we use the syscache, but - * we can't rely on that during bootstrap or while reindexing pg_class - * itself. - */ - if (IsBootstrapProcessingMode() || - ReindexIsProcessingHeap(RelationRelationId)) - { - /* don't assume syscache will work */ - TableScanDesc pg_class_scan; - ScanKeyData key[1]; - - ScanKeyInit(&key[0], - Anum_pg_class_oid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid)); - - pg_class_scan = table_beginscan_catalog(pg_class, 1, key); - tuple = heap_getnext(pg_class_scan, ForwardScanDirection); - tuple = heap_copytuple(tuple); - table_endscan(pg_class_scan); - } - else - { - /* normal case, use syscache */ - tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); - } + ScanKeyInit(&key[0], + Anum_pg_class_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + systable_inplace_update_begin(pg_class, ClassOidIndexId, true, NULL, + 1, key, &tuple, &state); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for relation %u", relid); @@ -2853,15 +2921,6 @@ index_update_stats(Relation rel, /* Should this be a more comprehensive test? */ Assert(rd_rel->relkind != RELKIND_PARTITIONED_INDEX); - /* - * As a special hack, if we are dealing with an empty table and the - * existing reltuples is -1, we leave that alone. This ensures that - * creating an index as part of CREATE TABLE doesn't cause the table to - * prematurely look like it's been vacuumed. - */ - if (reltuples == 0 && rd_rel->reltuples < 0) - reltuples = -1; - /* Apply required updates, if any, to copied tuple */ dirty = false; @@ -2871,20 +2930,8 @@ index_update_stats(Relation rel, dirty = true; } - /* - * Avoid updating statistics during binary upgrade, because the indexes - * are created before the data is moved into place. - */ - if (reltuples >= 0 && !IsBinaryUpgrade) + if (update_stats) { - BlockNumber relpages = RelationGetNumberOfBlocks(rel); - BlockNumber relallvisible; - - if (rd_rel->relkind != RELKIND_INDEX) - visibilitymap_count(rel, &relallvisible, NULL); - else /* don't bother for indexes */ - relallvisible = 0; - if (rd_rel->relpages != (int32) relpages) { rd_rel->relpages = (int32) relpages; @@ -2900,6 +2947,11 @@ index_update_stats(Relation rel, rd_rel->relallvisible = (int32) relallvisible; dirty = true; } + if (rd_rel->relallfrozen != (int32) relallfrozen) + { + rd_rel->relallfrozen = (int32) relallfrozen; + dirty = true; + } } /* @@ -2907,12 +2959,20 @@ index_update_stats(Relation rel, */ if (dirty) { - heap_inplace_update(pg_class, tuple); - /* the above sends a cache inval message */ + systable_inplace_update_finish(state, tuple); + /* the above sends transactional and immediate cache inval messages */ } else { - /* no need to change tuple, but force relcache inval anyway */ + systable_inplace_update_cancel(state); + + /* + * While we didn't change relhasindex, CREATE INDEX needs a + * transactional inval for when the new index's catalog rows become + * visible. Other CREATE INDEX and REINDEX code happens to also queue + * this inval, but keep this in case rare callers rely on this part of + * our API contract. + */ CacheInvalidateRelcacheByTuple(tuple); } @@ -2960,7 +3020,7 @@ index_build(Relation heapRelation, /* * Determine worker process details for parallel CREATE INDEX. Currently, - * only btree has support for parallel builds. + * only btree and BRIN have support for parallel builds. * * Note that planner considers parallel safety for us. */ @@ -3223,7 +3283,6 @@ IndexCheckExclusion(Relation heapRelation, indexInfo->ii_PredicateState = NULL; } - /* * validate_index - support code for concurrent index builds * @@ -3367,7 +3426,7 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot) /* ambulkdelete updates progress metrics */ (void) index_bulk_delete(&ivinfo, NULL, - validate_index_callback, (void *) &state); + validate_index_callback, &state); /* Execute the sort */ { @@ -4000,6 +4059,14 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping", get_namespace_name(indexNamespaceId), get_rel_name(indexOid)))); + + /* + * Remove this invalid toast index from the reindex pending list, + * as it is skipped here due to the hard failure that would happen + * in reindex_index(), should we try to process it. + */ + if (flags & REINDEX_REL_SUPPRESS_INDEX_USE) + RemoveReindexPending(indexOid); continue; } diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index d0d1abda58af3..25c4b6bdc87f0 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -4,7 +4,7 @@ * This file contains routines to support indexes defined on system * catalogs. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index c4145131ce413..a7bffca93d1da 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -2,7 +2,7 @@ * SQL Information Schema * as defined in ISO/IEC 9075-11:2023 * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/backend/catalog/information_schema.sql * @@ -440,9 +440,8 @@ CREATE VIEW check_constraints AS WHERE pg_has_role(coalesce(c.relowner, t.typowner), 'USAGE') AND con.contype = 'c' - UNION - -- not-null constraints on domains - + UNION ALL + -- not-null constraints SELECT current_database()::information_schema.sql_identifier AS constraint_catalog, rs.nspname::information_schema.sql_identifier AS constraint_schema, con.conname::information_schema.sql_identifier AS constraint_name, @@ -453,24 +452,7 @@ CREATE VIEW check_constraints AS LEFT JOIN pg_type t ON t.oid = con.contypid LEFT JOIN pg_attribute at ON (con.conrelid = at.attrelid AND con.conkey[1] = at.attnum) WHERE pg_has_role(coalesce(c.relowner, t.typowner), 'USAGE'::text) - AND con.contype = 'n' - - UNION - -- not-null constraints on relations - - SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog, - CAST(n.nspname AS sql_identifier) AS constraint_schema, - CAST(CAST(n.oid AS text) || '_' || CAST(r.oid AS text) || '_' || CAST(a.attnum AS text) || '_not_null' AS sql_identifier) AS constraint_name, -- XXX - CAST(a.attname || ' IS NOT NULL' AS character_data) - AS check_clause - FROM pg_namespace n, pg_class r, pg_attribute a - WHERE n.oid = r.relnamespace - AND r.oid = a.attrelid - AND a.attnum > 0 - AND NOT a.attisdropped - AND a.attnotnull - AND r.relkind IN ('r', 'p') - AND pg_has_role(r.relowner, 'USAGE'); + AND con.contype = 'n'; GRANT SELECT ON check_constraints TO PUBLIC; @@ -839,6 +821,20 @@ CREATE VIEW constraint_column_usage AS UNION ALL + /* not-null constraints */ + SELECT DISTINCT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname + FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc, pg_constraint c + WHERE nr.oid = r.relnamespace + AND r.oid = a.attrelid + AND r.oid = c.conrelid + AND a.attnum = c.conkey[1] + AND c.connamespace = nc.oid + AND c.contype = 'n' + AND r.relkind in ('r', 'p') + AND not a.attisdropped + + UNION ALL + /* unique/primary key/foreign key constraints */ SELECT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc, @@ -1839,6 +1835,7 @@ CREATE VIEW table_constraints AS CAST(r.relname AS sql_identifier) AS table_name, CAST( CASE c.contype WHEN 'c' THEN 'CHECK' + WHEN 'n' THEN 'CHECK' WHEN 'f' THEN 'FOREIGN KEY' WHEN 'p' THEN 'PRIMARY KEY' WHEN 'u' THEN 'UNIQUE' END @@ -1847,7 +1844,7 @@ CREATE VIEW table_constraints AS AS is_deferrable, CAST(CASE WHEN c.condeferred THEN 'YES' ELSE 'NO' END AS yes_or_no) AS initially_deferred, - CAST('YES' AS yes_or_no) AS enforced, + CAST(CASE WHEN c.conenforced THEN 'YES' ELSE 'NO' END AS yes_or_no) AS enforced, CAST(CASE WHEN c.contype = 'u' THEN CASE WHEN (SELECT NOT indnullsnotdistinct FROM pg_index WHERE indexrelid = conindid) THEN 'YES' ELSE 'NO' END END @@ -1863,38 +1860,6 @@ CREATE VIEW table_constraints AS AND c.contype NOT IN ('t', 'x') -- ignore nonstandard constraints AND r.relkind IN ('r', 'p') AND (NOT pg_is_other_temp_schema(nr.oid)) - AND (pg_has_role(r.relowner, 'USAGE') - -- SELECT privilege omitted, per SQL standard - OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') - OR has_any_column_privilege(r.oid, 'INSERT, UPDATE, REFERENCES') ) - - UNION ALL - - -- not-null constraints - - SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog, - CAST(nr.nspname AS sql_identifier) AS constraint_schema, - CAST(CAST(nr.oid AS text) || '_' || CAST(r.oid AS text) || '_' || CAST(a.attnum AS text) || '_not_null' AS sql_identifier) AS constraint_name, -- XXX - CAST(current_database() AS sql_identifier) AS table_catalog, - CAST(nr.nspname AS sql_identifier) AS table_schema, - CAST(r.relname AS sql_identifier) AS table_name, - CAST('CHECK' AS character_data) AS constraint_type, - CAST('NO' AS yes_or_no) AS is_deferrable, - CAST('NO' AS yes_or_no) AS initially_deferred, - CAST('YES' AS yes_or_no) AS enforced, - CAST(NULL AS yes_or_no) AS nulls_distinct - - FROM pg_namespace nr, - pg_class r, - pg_attribute a - - WHERE nr.oid = r.relnamespace - AND r.oid = a.attrelid - AND a.attnotnull - AND a.attnum > 0 - AND NOT a.attisdropped - AND r.relkind IN ('r', 'p') - AND (NOT pg_is_other_temp_schema(nr.oid)) AND (pg_has_role(r.relowner, 'USAGE') -- SELECT privilege omitted, per SQL standard OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') diff --git a/src/backend/catalog/meson.build b/src/backend/catalog/meson.build index 2f3ded8a0e7c4..1958ea9238a76 100644 --- a/src/backend/catalog/meson.build +++ b/src/backend/catalog/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'aclchk.c', diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 43b707699d72f..d97d632a7ef55 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -9,7 +9,7 @@ * and implementing search-path-controlled searches. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -305,17 +305,32 @@ static SearchPathCacheEntry *LastSearchPathCacheEntry = NULL; static void spcache_init(void) { - Assert(SearchPathCacheContext); - if (SearchPathCache && searchPathCacheValid && SearchPathCache->members < SPCACHE_RESET_THRESHOLD) return; - /* make sure we don't leave dangling pointers if nsphash_create fails */ + searchPathCacheValid = false; + baseSearchPathValid = false; + + /* + * Make sure we don't leave dangling pointers if a failure happens during + * initialization. + */ SearchPathCache = NULL; LastSearchPathCacheEntry = NULL; - MemoryContextReset(SearchPathCacheContext); + if (SearchPathCacheContext == NULL) + { + /* Make the context we'll keep search path cache hashtable in */ + SearchPathCacheContext = AllocSetContextCreate(TopMemoryContext, + "search_path processing cache", + ALLOCSET_DEFAULT_SIZES); + } + else + { + MemoryContextReset(SearchPathCacheContext); + } + /* arbitrary initial starting size of 16 elements */ SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL); searchPathCacheValid = true; @@ -4742,11 +4757,6 @@ InitializeSearchPath(void) } else { - /* Make the context we'll keep search path cache hashtable in */ - SearchPathCacheContext = AllocSetContextCreate(TopMemoryContext, - "search_path processing cache", - ALLOCSET_DEFAULT_SIZES); - /* * In normal mode, arrange for a callback on any syscache invalidation * that will affect the search_path cache. diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c index 0e606ddd895f3..0853983f5e165 100644 --- a/src/backend/catalog/objectaccess.c +++ b/src/backend/catalog/objectaccess.c @@ -3,7 +3,7 @@ * objectaccess.c * functions for object_access_hook on various events * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * ------------------------------------------------------------------------- @@ -42,7 +42,7 @@ RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, (*object_access_hook) (OAT_POST_CREATE, classId, objectId, subId, - (void *) &pc_arg); + &pc_arg); } /* @@ -64,7 +64,7 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId, (*object_access_hook) (OAT_DROP, classId, objectId, subId, - (void *) &drop_arg); + &drop_arg); } /* @@ -103,7 +103,7 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, (*object_access_hook) (OAT_POST_ALTER, classId, objectId, subId, - (void *) &pa_arg); + &pa_arg); } /* @@ -125,7 +125,7 @@ RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation) (*object_access_hook) (OAT_NAMESPACE_SEARCH, NamespaceRelationId, objectId, 0, - (void *) &ns_arg); + &ns_arg); return ns_arg.result; } @@ -168,7 +168,7 @@ RunObjectPostCreateHookStr(Oid classId, const char *objectName, int subId, (*object_access_hook_str) (OAT_POST_CREATE, classId, objectName, subId, - (void *) &pc_arg); + &pc_arg); } /* @@ -190,7 +190,7 @@ RunObjectDropHookStr(Oid classId, const char *objectName, int subId, (*object_access_hook_str) (OAT_DROP, classId, objectName, subId, - (void *) &drop_arg); + &drop_arg); } /* @@ -229,7 +229,7 @@ RunObjectPostAlterHookStr(Oid classId, const char *objectName, int subId, (*object_access_hook_str) (OAT_POST_ALTER, classId, objectName, subId, - (void *) &pa_arg); + &pa_arg); } /* @@ -251,7 +251,7 @@ RunNamespaceSearchHookStr(const char *objectName, bool ereport_on_violation) (*object_access_hook_str) (OAT_NAMESPACE_SEARCH, NamespaceRelationId, objectName, 0, - (void *) &ns_arg); + &ns_arg); return ns_arg.result; } diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 85a7b7e641a02..b63fd57dc04bb 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -3,7 +3,7 @@ * objectaddress.c * functions for working with ObjectAddresses * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -896,7 +896,8 @@ static void getRelationIdentity(StringInfo buffer, Oid relid, List **object, * * If the object is a relation or a child object of a relation (e.g. an * attribute or constraint), the relation is also opened and *relp receives - * the open relcache entry pointer; otherwise, *relp is set to NULL. This + * the open relcache entry pointer; otherwise, *relp is set to NULL. + * (relp can be NULL if the caller never passes a relation-related object.) This * is a bit grotty but it makes life simpler, since the caller will * typically need the relcache entry too. Caller must close the relcache * entry when done with it. The relation is locked with the specified lockmode @@ -1204,8 +1205,12 @@ get_object_address(ObjectType objtype, Node *object, old_address = address; } + /* relp must be given if it's a relation */ + Assert(!relation || relp); + /* Return the object address and the relation. */ - *relp = relation; + if (relp) + *relp = relation; return address; } @@ -2000,16 +2005,20 @@ get_object_address_defacl(List *object, bool missing_ok) case DEFACLOBJ_NAMESPACE: objtype_str = "schemas"; break; + case DEFACLOBJ_LARGEOBJECT: + objtype_str = "large objects"; + break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized default ACL object type \"%c\"", objtype), - errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".", + errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".", DEFACLOBJ_RELATION, DEFACLOBJ_SEQUENCE, DEFACLOBJ_FUNCTION, DEFACLOBJ_TYPE, - DEFACLOBJ_NAMESPACE))); + DEFACLOBJ_NAMESPACE, + DEFACLOBJ_LARGEOBJECT))); } /* @@ -2779,6 +2788,22 @@ get_object_property_data(Oid class_id) */ HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId) +{ + return + get_catalog_object_by_oid_extended(catalog, oidcol, objectId, false); +} + +/* + * Same as get_catalog_object_by_oid(), but with an additional "locktup" + * argument controlling whether to acquire a LOCKTAG_TUPLE at mode + * InplaceUpdateTupleLock. See README.tuplock section "Locking to write + * inplace-updated tables". + */ +HeapTuple +get_catalog_object_by_oid_extended(Relation catalog, + AttrNumber oidcol, + Oid objectId, + bool locktup) { HeapTuple tuple; Oid classId = RelationGetRelid(catalog); @@ -2786,7 +2811,12 @@ get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId) if (oidCacheId > 0) { - tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId)); + if (locktup) + tuple = SearchSysCacheLockedCopy1(oidCacheId, + ObjectIdGetDatum(objectId)); + else + tuple = SearchSysCacheCopy1(oidCacheId, + ObjectIdGetDatum(objectId)); if (!HeapTupleIsValid(tuple)) /* should not happen */ return NULL; } @@ -2811,6 +2841,10 @@ get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId) systable_endscan(scan); return NULL; } + + if (locktup) + LockTuple(catalog, &tuple->t_self, InplaceUpdateTupleLock); + tuple = heap_copytuple(tuple); systable_endscan(scan); @@ -3230,6 +3264,12 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) initStringInfo(&opfam); getOpFamilyDescription(&opfam, amopForm->amopfamily, false); + /* + * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail + * completely if the type links are dangling, which is a form + * of catalog corruption that could occur due to old bugs. + */ + /*------ translator: %d is the operator strategy (a number), the first two %s's are data type names, the third %s is the @@ -3237,8 +3277,10 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) textual form of the operator with arguments. */ appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"), amopForm->amopstrategy, - format_type_be(amopForm->amoplefttype), - format_type_be(amopForm->amoprighttype), + format_type_extended(amopForm->amoplefttype, + -1, FORMAT_TYPE_ALLOW_INVALID), + format_type_extended(amopForm->amoprighttype, + -1, FORMAT_TYPE_ALLOW_INVALID), opfam.data, format_operator(amopForm->amopopr)); @@ -3287,6 +3329,12 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) initStringInfo(&opfam); getOpFamilyDescription(&opfam, amprocForm->amprocfamily, false); + /* + * We use FORMAT_TYPE_ALLOW_INVALID here so as not to fail + * completely if the type links are dangling, which is a form + * of catalog corruption that could occur due to old bugs. + */ + /*------ translator: %d is the function number, the first two %s's are data type names, the third %s is the description of the @@ -3294,8 +3342,10 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) function with arguments. */ appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"), amprocForm->amprocnum, - format_type_be(amprocForm->amproclefttype), - format_type_be(amprocForm->amprocrighttype), + format_type_extended(amprocForm->amproclefttype, + -1, FORMAT_TYPE_ALLOW_INVALID), + format_type_extended(amprocForm->amprocrighttype, + -1, FORMAT_TYPE_ALLOW_INVALID), opfam.data, format_procedure(amprocForm->amproc)); @@ -3798,6 +3848,12 @@ getObjectDescription(const ObjectAddress *object, bool missing_ok) _("default privileges on new schemas belonging to role %s"), rolename); break; + case DEFACLOBJ_LARGEOBJECT: + Assert(!nspname); + appendStringInfo(&buffer, + _("default privileges on new large objects belonging to role %s"), + rolename); + break; default: /* shouldn't get here */ if (nspname) @@ -5720,6 +5776,10 @@ getObjectIdentityParts(const ObjectAddress *object, appendStringInfoString(&buffer, " on schemas"); break; + case DEFACLOBJ_LARGEOBJECT: + appendStringInfoString(&buffer, + " on large objects"); + break; } if (objname) diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 018aad445d174..93d72157a46ae 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -3,7 +3,7 @@ * partition.c * Partitioning related data structures and functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 90fc7db949f5c..a05f8a87c1f83 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -3,7 +3,7 @@ * pg_aggregate.c * routines to support manipulation of the pg_aggregate relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -637,6 +637,7 @@ AggregateCreate(const char *aggName, parameterNames, /* parameterNames */ parameterDefaults, /* parameterDefaults */ PointerGetDatum(NULL), /* trftypes */ + NIL, /* trfoids */ PointerGetDatum(NULL), /* proconfig */ InvalidOid, /* no prosupport */ 1, /* procost */ diff --git a/src/backend/catalog/pg_attrdef.c b/src/backend/catalog/pg_attrdef.c index 003ae70b4d255..1b6270b121324 100644 --- a/src/backend/catalog/pg_attrdef.c +++ b/src/backend/catalog/pg_attrdef.c @@ -3,7 +3,7 @@ * pg_attrdef.c * routines to support manipulation of the pg_attrdef relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,17 +14,12 @@ */ #include "postgres.h" -#include "access/genam.h" #include "access/relation.h" #include "access/table.h" -#include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" #include "catalog/pg_attrdef.h" -#include "executor/executor.h" -#include "optimizer/optimizer.h" -#include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/rel.h" @@ -35,25 +30,22 @@ * Store a default expression for column attnum of relation rel. * * Returns the OID of the new pg_attrdef tuple. - * - * add_column_mode must be true if we are storing the default for a new - * attribute, and false if it's for an already existing attribute. The reason - * for this is that the missing value must never be updated after it is set, - * which can only be when a column is added to the table. Otherwise we would - * in effect be changing existing tuples. */ Oid StoreAttrDefault(Relation rel, AttrNumber attnum, - Node *expr, bool is_internal, bool add_column_mode) + Node *expr, bool is_internal) { char *adbin; Relation adrel; HeapTuple tuple; - Datum values[4]; - static bool nulls[4] = {false, false, false, false}; + Datum values[Natts_pg_attrdef]; + static bool nulls[Natts_pg_attrdef] = {false, false, false, false}; Relation attrrel; HeapTuple atttup; Form_pg_attribute attStruct; + Datum valuesAtt[Natts_pg_attribute] = {0}; + bool nullsAtt[Natts_pg_attribute] = {0}; + bool replacesAtt[Natts_pg_attribute] = {0}; char attgenerated; Oid attrdefOid; ObjectAddress colobject, @@ -72,8 +64,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId, Anum_pg_attrdef_oid); values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid); - values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel); - values[Anum_pg_attrdef_adnum - 1] = attnum; + values[Anum_pg_attrdef_adrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); + values[Anum_pg_attrdef_adnum - 1] = Int16GetDatum(attnum); values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin); tuple = heap_form_tuple(adrel->rd_att, values, nulls); @@ -103,68 +95,15 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, attnum, RelationGetRelid(rel)); attStruct = (Form_pg_attribute) GETSTRUCT(atttup); attgenerated = attStruct->attgenerated; - if (!attStruct->atthasdef) - { - Form_pg_attribute defAttStruct; - - ExprState *exprState; - Expr *expr2 = (Expr *) expr; - EState *estate = NULL; - ExprContext *econtext; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; - Datum missingval = (Datum) 0; - bool missingIsNull = true; - - valuesAtt[Anum_pg_attribute_atthasdef - 1] = true; - replacesAtt[Anum_pg_attribute_atthasdef - 1] = true; - - if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode && - !attgenerated) - { - expr2 = expression_planner(expr2); - estate = CreateExecutorState(); - exprState = ExecPrepareExpr(expr2, estate); - econtext = GetPerTupleExprContext(estate); - - missingval = ExecEvalExpr(exprState, econtext, - &missingIsNull); - - FreeExecutorState(estate); - - defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1); - - if (missingIsNull) - { - /* if the default evaluates to NULL, just store a NULL array */ - missingval = (Datum) 0; - } - else - { - /* otherwise make a one-element array of the value */ - missingval = PointerGetDatum(construct_array(&missingval, - 1, - defAttStruct->atttypid, - defAttStruct->attlen, - defAttStruct->attbyval, - defAttStruct->attalign)); - } - - valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull; - replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true; - valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval; - replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; - nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull; - } - atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - - CatalogTupleUpdate(attrrel, &atttup->t_self, atttup); - - if (!missingIsNull) - pfree(DatumGetPointer(missingval)); - } + + valuesAtt[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(true); + replacesAtt[Anum_pg_attribute_atthasdef - 1] = true; + + atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), + valuesAtt, nullsAtt, replacesAtt); + + CatalogTupleUpdate(attrrel, &atttup->t_self, atttup); + table_close(attrrel, RowExclusiveLock); heap_freetuple(atttup); diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c index 5a5b855d51415..1773c9c549160 100644 --- a/src/backend/catalog/pg_cast.c +++ b/src/backend/catalog/pg_cast.c @@ -3,7 +3,7 @@ * pg_cast.c * routines to support manipulation of the pg_cast relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_class.c b/src/backend/catalog/pg_class.c index e05b0bbb2e025..18eecbdfc0648 100644 --- a/src/backend/catalog/pg_class.c +++ b/src/backend/catalog/pg_class.c @@ -3,7 +3,7 @@ * pg_class.c * routines to support manipulation of the pg_class relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c index 7f2f7012299df..469635b35808d 100644 --- a/src/backend/catalog/pg_collation.c +++ b/src/backend/catalog/pg_collation.c @@ -3,7 +3,7 @@ * pg_collation.c * routines to support manipulation of the pg_collation relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 3baf9231ed0c8..2d5ac1ea8138b 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -3,7 +3,7 @@ * pg_constraint.c * routines to support manipulation of the pg_constraint relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -15,17 +15,20 @@ #include "postgres.h" #include "access/genam.h" +#include "access/gist.h" #include "access/htup_details.h" #include "access/sysattr.h" #include "access/table.h" #include "catalog/catalog.h" #include "catalog/dependency.h" +#include "catalog/heap.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "commands/defrem.h" +#include "common/int.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -50,6 +53,7 @@ CreateConstraintEntry(const char *constraintName, char constraintType, bool isDeferrable, bool isDeferred, + bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, @@ -73,8 +77,9 @@ CreateConstraintEntry(const char *constraintName, Node *conExpr, const char *conBin, bool conIsLocal, - int conInhCount, + int16 conInhCount, bool conNoInherit, + bool conPeriod, bool is_internal) { Relation conDesc; @@ -95,6 +100,12 @@ CreateConstraintEntry(const char *constraintName, ObjectAddresses *addrs_auto; ObjectAddresses *addrs_normal; + /* Only CHECK or FOREIGN KEY constraint can be not enforced */ + Assert(isEnforced || constraintType == CONSTRAINT_CHECK || + constraintType == CONSTRAINT_FOREIGN); + /* NOT ENFORCED constraint must be NOT VALID */ + Assert(isEnforced || !isValidated); + conDesc = table_open(ConstraintRelationId, RowExclusiveLock); Assert(constraintName); @@ -118,8 +129,9 @@ CreateConstraintEntry(const char *constraintName, if (foreignNKeys > 0) { Datum *fkdatums; + int nkeys = Max(foreignNKeys, numFkDeleteSetCols); - fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum)); + fkdatums = (Datum *) palloc(nkeys * sizeof(Datum)); for (i = 0; i < foreignNKeys; i++) fkdatums[i] = Int16GetDatum(foreignKey[i]); confkeyArray = construct_array_builtin(fkdatums, foreignNKeys, INT2OID); @@ -178,6 +190,7 @@ CreateConstraintEntry(const char *constraintName, values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType); values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable); values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred); + values[Anum_pg_constraint_conenforced - 1] = BoolGetDatum(isEnforced); values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated); values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId); values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId); @@ -190,6 +203,7 @@ CreateConstraintEntry(const char *constraintName, values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal); values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount); values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit); + values[Anum_pg_constraint_conperiod - 1] = BoolGetDatum(conPeriod); if (conkeyArray) values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray); @@ -481,6 +495,8 @@ ConstraintNameExists(const char *conname, Oid namespaceid) * name1, name2, and label are used the same way as for makeObjectName(), * except that the label can't be NULL; digits will be appended to the label * if needed to create a name that is unique within the specified namespace. + * If the given label is empty, we only consider names that include at least + * one added digit. * * 'others' can be a list of string names already chosen within the current * command (but not yet reflected into the catalogs); we will not choose @@ -509,8 +525,11 @@ ChooseConstraintName(const char *name1, const char *name2, conDesc = table_open(ConstraintRelationId, AccessShareLock); - /* try the unmodified label first */ - strlcpy(modlabel, label, sizeof(modlabel)); + /* try the unmodified label first, unless it's empty */ + if (label[0] != '\0') + strlcpy(modlabel, label, sizeof(modlabel)); + else + snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass); for (;;) { @@ -560,6 +579,77 @@ ChooseConstraintName(const char *name1, const char *name2, return conname; } +/* + * Find and return a copy of the pg_constraint tuple that implements a + * (possibly not valid) not-null constraint for the given column of the + * given relation. If no such constraint exists, return NULL. + * + * XXX This would be easier if we had pg_attribute.notnullconstr with the OID + * of the constraint that implements the not-null constraint for that column. + * I'm not sure it's worth the catalog bloat and de-normalization, however. + */ +HeapTuple +findNotNullConstraintAttnum(Oid relid, AttrNumber attnum) +{ + Relation pg_constraint; + HeapTuple conTup, + retval = NULL; + SysScanDesc scan; + ScanKeyData key; + + pg_constraint = table_open(ConstraintRelationId, AccessShareLock); + ScanKeyInit(&key, + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, + true, NULL, 1, &key); + + while (HeapTupleIsValid(conTup = systable_getnext(scan))) + { + Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(conTup); + AttrNumber conkey; + + /* + * We're looking for a NOTNULL constraint with the column we're + * looking for as the sole element in conkey. + */ + if (con->contype != CONSTRAINT_NOTNULL) + continue; + + conkey = extractNotNullColumn(conTup); + if (conkey != attnum) + continue; + + /* Found it */ + retval = heap_copytuple(conTup); + break; + } + + systable_endscan(scan); + table_close(pg_constraint, AccessShareLock); + + return retval; +} + +/* + * Find and return a copy of the pg_constraint tuple that implements a + * (possibly not valid) not-null constraint for the given column of the + * given relation. + * If no such column or no such constraint exists, return NULL. + */ +HeapTuple +findNotNullConstraint(Oid relid, const char *colname) +{ + AttrNumber attnum; + + attnum = get_attnum(relid, colname); + if (attnum <= InvalidAttrNumber) + return NULL; + + return findNotNullConstraintAttnum(relid, attnum); +} + /* * Find and return the pg_constraint tuple that implements a validated * not-null constraint for the given domain. @@ -604,6 +694,200 @@ findDomainNotNullConstraint(Oid typid) return retval; } +/* + * Given a pg_constraint tuple for a not-null constraint, return the column + * number it is for. + */ +AttrNumber +extractNotNullColumn(HeapTuple constrTup) +{ + Datum adatum; + ArrayType *arr; + + /* only tuples for not-null constraints should be given */ + Assert(((Form_pg_constraint) GETSTRUCT(constrTup))->contype == CONSTRAINT_NOTNULL); + + adatum = SysCacheGetAttrNotNull(CONSTROID, constrTup, + Anum_pg_constraint_conkey); + arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */ + if (ARR_NDIM(arr) != 1 || + ARR_HASNULL(arr) || + ARR_ELEMTYPE(arr) != INT2OID || + ARR_DIMS(arr)[0] != 1) + elog(ERROR, "conkey is not a 1-D smallint array"); + + /* We leak the detoasted datum, but we don't care */ + + return ((AttrNumber *) ARR_DATA_PTR(arr))[0]; +} + +/* + * AdjustNotNullInheritance + * Adjust inheritance status for a single not-null constraint + * + * If no not-null constraint is found for the column, return false. + * Caller can create one. + * + * If a constraint exists but the connoinherit flag is not what the caller + * wants, throw an error about the incompatibility. If the desired + * constraint is valid but the existing constraint is not valid, also + * throw an error about that (the opposite case is acceptable). + * + * If everything checks out, we adjust conislocal/coninhcount and return + * true. If is_local is true we flip conislocal true, or do nothing if + * it's already true; otherwise we increment coninhcount by 1. + */ +bool +AdjustNotNullInheritance(Oid relid, AttrNumber attnum, + bool is_local, bool is_no_inherit, bool is_notvalid) +{ + HeapTuple tup; + + tup = findNotNullConstraintAttnum(relid, attnum); + if (HeapTupleIsValid(tup)) + { + Relation pg_constraint; + Form_pg_constraint conform; + bool changed = false; + + pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock); + conform = (Form_pg_constraint) GETSTRUCT(tup); + + /* + * If the NO INHERIT flag we're asked for doesn't match what the + * existing constraint has, throw an error. + */ + if (is_no_inherit != conform->connoinherit) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"", + NameStr(conform->conname), get_rel_name(relid)), + errhint("You might need to make the existing constraint inheritable using %s.", + "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT")); + + /* + * Throw an error if the existing constraint is NOT VALID and caller + * wants a valid one. + */ + if (!is_notvalid && !conform->convalidated) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"", + NameStr(conform->conname), get_rel_name(relid)), + errhint("You might need to validate it using %s.", + "ALTER TABLE ... VALIDATE CONSTRAINT")); + + if (!is_local) + { + if (pg_add_s16_overflow(conform->coninhcount, 1, + &conform->coninhcount)) + ereport(ERROR, + errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("too many inheritance parents")); + changed = true; + } + else if (!conform->conislocal) + { + conform->conislocal = true; + changed = true; + } + + if (changed) + CatalogTupleUpdate(pg_constraint, &tup->t_self, tup); + + table_close(pg_constraint, RowExclusiveLock); + + return true; + } + + return false; +} + +/* + * RelationGetNotNullConstraints + * Return the list of not-null constraints for the given rel + * + * Caller can request cooked constraints, or raw. + * + * This is seldom needed, so we just scan pg_constraint each time. + * + * 'include_noinh' determines whether to include NO INHERIT constraints or not. + */ +List * +RelationGetNotNullConstraints(Oid relid, bool cooked, bool include_noinh) +{ + List *notnulls = NIL; + Relation constrRel; + HeapTuple htup; + SysScanDesc conscan; + ScanKeyData skey; + + constrRel = table_open(ConstraintRelationId, AccessShareLock); + ScanKeyInit(&skey, + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + conscan = systable_beginscan(constrRel, ConstraintRelidTypidNameIndexId, true, + NULL, 1, &skey); + + while (HeapTupleIsValid(htup = systable_getnext(conscan))) + { + Form_pg_constraint conForm = (Form_pg_constraint) GETSTRUCT(htup); + AttrNumber colnum; + + if (conForm->contype != CONSTRAINT_NOTNULL) + continue; + if (conForm->connoinherit && !include_noinh) + continue; + + colnum = extractNotNullColumn(htup); + + if (cooked) + { + CookedConstraint *cooked; + + cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); + + cooked->contype = CONSTR_NOTNULL; + cooked->conoid = conForm->oid; + cooked->name = pstrdup(NameStr(conForm->conname)); + cooked->attnum = colnum; + cooked->expr = NULL; + cooked->is_enforced = true; + cooked->skip_validation = !conForm->convalidated; + cooked->is_local = true; + cooked->inhcount = 0; + cooked->is_no_inherit = conForm->connoinherit; + + notnulls = lappend(notnulls, cooked); + } + else + { + Constraint *constr; + + constr = makeNode(Constraint); + constr->contype = CONSTR_NOTNULL; + constr->conname = pstrdup(NameStr(conForm->conname)); + constr->deferrable = false; + constr->initdeferred = false; + constr->location = -1; + constr->keys = list_make1(makeString(get_attname(relid, colnum, + false))); + constr->is_enforced = true; + constr->skip_validation = !conForm->convalidated; + constr->initially_valid = true; + constr->is_no_inherit = conForm->connoinherit; + notnulls = lappend(notnulls, constr); + } + } + + systable_endscan(conscan); + table_close(constrRel, AccessShareLock); + + return notnulls; +} + + /* * Delete a single constraint record. */ @@ -846,11 +1130,12 @@ ConstraintSetParentConstraint(Oid childConstrId, childConstrId); constrForm->conislocal = false; - constrForm->coninhcount++; - if (constrForm->coninhcount < 0) + if (pg_add_s16_overflow(constrForm->coninhcount, 1, + &constrForm->coninhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + constrForm->conparentid = parentConstrId; CatalogTupleUpdate(constrRel, &tuple->t_self, newtup); @@ -1347,6 +1632,78 @@ DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, *numfks = numkeys; } +/* + * FindFKPeriodOpers - + * + * Looks up the operator oids used for the PERIOD part of a temporal foreign key. + * The opclass should be the opclass of that PERIOD element. + * Everything else is an output: containedbyoperoid is the ContainedBy operator for + * types matching the PERIOD element. + * aggedcontainedbyoperoid is also a ContainedBy operator, + * but one whose rhs is a multirange. + * That way foreign keys can compare fkattr <@ range_agg(pkattr). + * intersectoperoid is used by NO ACTION constraints to trim the range being considered + * to just what was updated/deleted. + */ +void +FindFKPeriodOpers(Oid opclass, + Oid *containedbyoperoid, + Oid *aggedcontainedbyoperoid, + Oid *intersectoperoid) +{ + Oid opfamily = InvalidOid; + Oid opcintype = InvalidOid; + StrategyNumber strat; + + /* Make sure we have a range or multirange. */ + if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype)) + { + if (opcintype != ANYRANGEOID && opcintype != ANYMULTIRANGEOID) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("invalid type for PERIOD part of foreign key"), + errdetail("Only range and multirange are supported.")); + + } + else + elog(ERROR, "cache lookup failed for opclass %u", opclass); + + /* + * Look up the ContainedBy operator whose lhs and rhs are the opclass's + * type. We use this to optimize RI checks: if the new value includes all + * of the old value, then we can treat the attribute as if it didn't + * change, and skip the RI check. + */ + GetOperatorFromCompareType(opclass, + InvalidOid, + COMPARE_CONTAINED_BY, + containedbyoperoid, + &strat); + + /* + * Now look up the ContainedBy operator. Its left arg must be the type of + * the column (or rather of the opclass). Its right arg must match the + * return type of the support proc. + */ + GetOperatorFromCompareType(opclass, + ANYMULTIRANGEOID, + COMPARE_CONTAINED_BY, + aggedcontainedbyoperoid, + &strat); + + switch (opcintype) + { + case ANYRANGEOID: + *intersectoperoid = OID_RANGE_INTERSECT_RANGE_OP; + break; + case ANYMULTIRANGEOID: + *intersectoperoid = OID_MULTIRANGE_INTERSECT_MULTIRANGE_OP; + break; + default: + elog(ERROR, "unexpected opcintype: %u", opcintype); + } +} + /* * Determine whether a relation can be proven functionally dependent on * a set of grouping columns. If so, return true and add the pg_constraint diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 0770878eac582..04cc375caea8c 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -3,7 +3,7 @@ * pg_conversion.c * routines to support manipulation of the pg_conversion relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c index 8c20f519fc05e..090fc07c28acb 100644 --- a/src/backend/catalog/pg_db_role_setting.c +++ b/src/backend/catalog/pg_db_role_setting.c @@ -2,7 +2,7 @@ * pg_db_role_setting.c * Routines to support manipulation of the pg_db_role_setting relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index cfd7ef51dfa29..c8b11f887e274 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -3,7 +3,7 @@ * pg_depend.c * routines to support manipulation of the pg_depend relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,7 +28,6 @@ #include "miscadmin.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" -#include "utils/syscache.h" #include "utils/rel.h" @@ -36,7 +35,7 @@ static bool isObjectPinned(const ObjectAddress *object); /* - * Record a dependency between 2 objects via their respective objectAddress. + * Record a dependency between 2 objects via their respective ObjectAddress. * The first argument is the dependent object, the second the one it * references. * diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index 54cededac1bf3..a1634e58eecdd 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -3,7 +3,7 @@ * pg_enum.c * routines to support manipulation of the pg_enum relation * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 836b4bfd894b8..929bb53b620fe 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -8,7 +8,7 @@ * Perhaps someday that code should be moved here, but it'd have to be * disentangled from other stuff such as pg_depend updates. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index e235f7c5e680e..89fc810215099 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -3,7 +3,7 @@ * pg_largeobject.c * routines to support manipulation of the pg_largeobject relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,14 +14,13 @@ */ #include "postgres.h" -#include "access/genam.h" -#include "access/htup_details.h" #include "access/table.h" #include "catalog/catalog.h" #include "catalog/indexing.h" #include "catalog/pg_largeobject.h" #include "catalog/pg_largeobject_metadata.h" #include "miscadmin.h" +#include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/rel.h" @@ -41,6 +40,8 @@ LargeObjectCreate(Oid loid) Oid loid_new; Datum values[Natts_pg_largeobject_metadata]; bool nulls[Natts_pg_largeobject_metadata]; + Oid ownerId; + Acl *lomacl; pg_lo_meta = table_open(LargeObjectMetadataRelationId, RowExclusiveLock); @@ -57,11 +58,18 @@ LargeObjectCreate(Oid loid) loid_new = GetNewOidWithIndex(pg_lo_meta, LargeObjectMetadataOidIndexId, Anum_pg_largeobject_metadata_oid); + ownerId = GetUserId(); + lomacl = get_user_default_acl(OBJECT_LARGEOBJECT, ownerId, InvalidOid); values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new); values[Anum_pg_largeobject_metadata_lomowner - 1] - = ObjectIdGetDatum(GetUserId()); - nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true; + = ObjectIdGetDatum(ownerId); + + if (lomacl != NULL) + values[Anum_pg_largeobject_metadata_lomacl - 1] + = PointerGetDatum(lomacl); + else + nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true; ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), values, nulls); @@ -72,6 +80,10 @@ LargeObjectCreate(Oid loid) table_close(pg_lo_meta, RowExclusiveLock); + /* dependencies on roles mentioned in default ACL */ + recordDependencyOnNewAcl(LargeObjectRelationId, loid_new, 0, + ownerId, lomacl); + return loid_new; } @@ -153,6 +165,15 @@ LargeObjectDrop(Oid loid) */ bool LargeObjectExists(Oid loid) +{ + return LargeObjectExistsWithSnapshot(loid, NULL); +} + +/* + * Same as LargeObjectExists(), except snapshot to read with can be specified. + */ +bool +LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot) { Relation pg_lo_meta; ScanKeyData skey[1]; @@ -170,7 +191,7 @@ LargeObjectExists(Oid loid) sd = systable_beginscan(pg_lo_meta, LargeObjectMetadataOidIndexId, true, - NULL, 1, skey); + snapshot, 1, skey); tuple = systable_getnext(sd); if (HeapTupleIsValid(tuple)) diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index 3ce6e3800919e..6f5634a4de69b 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -3,7 +3,7 @@ * pg_namespace.c * routines to support manipulation of the pg_namespace relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 65b45a424a276..bfcfa643464ac 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -3,7 +3,7 @@ * pg_operator.c * routines to support manipulation of the pg_operator relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_parameter_acl.c b/src/backend/catalog/pg_parameter_acl.c index e50f2666643e4..62a05783eb333 100644 --- a/src/backend/catalog/pg_parameter_acl.c +++ b/src/backend/catalog/pg_parameter_acl.c @@ -3,7 +3,7 @@ * pg_parameter_acl.c * routines to support manipulation of the pg_parameter_acl relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 528c17cd7f676..5fdcf24d5f8de 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -3,7 +3,7 @@ * pg_proc.c * routines to support manipulation of the pg_proc relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,7 +26,6 @@ #include "catalog/pg_proc.h" #include "catalog/pg_transform.h" #include "catalog/pg_type.h" -#include "commands/defrem.h" #include "executor/functions.h" #include "funcapi.h" #include "mb/pg_wchar.h" @@ -61,6 +60,35 @@ static bool match_prosrc_to_literal(const char *prosrc, const char *literal, /* ---------------------------------------------------------------- * ProcedureCreate * + * procedureName: string name of routine (proname) + * procNamespace: OID of namespace (pronamespace) + * replace: true to allow replacement of an existing pg_proc entry + * returnsSet: returns set? (proretset) + * returnType: OID of result type (prorettype) + * proowner: OID of owner role (proowner) + * languageObjectId: OID of function language (prolang) + * languageValidator: OID of validator function to apply, if any + * prosrc: string form of function definition (prosrc) + * probin: string form of binary reference, or NULL (probin) + * prosqlbody: Node tree of pre-parsed SQL body, or NULL (prosqlbody) + * prokind: function/aggregate/procedure/etc code (prokind) + * security_definer: security definer? (prosecdef) + * isLeakProof: leak proof? (proleakproof) + * isStrict: strict? (proisstrict) + * volatility: volatility code (provolatile) + * parallel: parallel safety code (proparallel) + * parameterTypes: input parameter types, as an oidvector (proargtypes) + * allParameterTypes: all parameter types, as an OID array (proallargtypes) + * parameterModes: parameter modes, as a "char" array (proargmodes) + * parameterNames: parameter names, as a text array (proargnames) + * parameterDefaults: defaults, as a List of Node trees (proargdefaults) + * trftypes: transformable type OIDs, as an OID array (protrftypes) + * trfoids: List of transform OIDs that routine should depend on + * proconfig: GUC set clauses, as a text array (proconfig) + * prosupport: OID of support function, if any (prosupport) + * procost: cost factor (procost) + * prorows: estimated output rows for a SRF (prorows) + * * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig * are either arrays of the proper types or NULL. We declare them Datum, * not "ArrayType *", to avoid importing array.h into pg_proc.h. @@ -90,6 +118,7 @@ ProcedureCreate(const char *procedureName, Datum parameterNames, List *parameterDefaults, Datum trftypes, + List *trfoids, Datum proconfig, Oid prosupport, float4 procost, @@ -115,7 +144,6 @@ ProcedureCreate(const char *procedureName, referenced; char *detailmsg; int i; - Oid trfid; ObjectAddresses *addrs; /* @@ -609,25 +637,18 @@ ProcedureCreate(const char *procedureName, ObjectAddressSet(referenced, TypeRelationId, returnType); add_exact_object_address(&referenced, addrs); - /* dependency on transform used by return type, if any */ - if ((trfid = get_transform_oid(returnType, languageObjectId, true))) - { - ObjectAddressSet(referenced, TransformRelationId, trfid); - add_exact_object_address(&referenced, addrs); - } - /* dependency on parameter types */ for (i = 0; i < allParamCount; i++) { ObjectAddressSet(referenced, TypeRelationId, allParams[i]); add_exact_object_address(&referenced, addrs); + } - /* dependency on transform used by parameter type, if any */ - if ((trfid = get_transform_oid(allParams[i], languageObjectId, true))) - { - ObjectAddressSet(referenced, TransformRelationId, trfid); - add_exact_object_address(&referenced, addrs); - } + /* dependency on transforms, if any */ + foreach_oid(transformid, trfoids) + { + ObjectAddressSet(referenced, TransformRelationId, transformid); + add_exact_object_address(&referenced, addrs); } /* dependency on support function, if any */ @@ -873,7 +894,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) callback_arg.prosrc = prosrc; sqlerrcontext.callback = sql_function_parse_error_callback; - sqlerrcontext.arg = (void *) &callback_arg; + sqlerrcontext.arg = &callback_arg; sqlerrcontext.previous = error_context_stack; error_context_stack = &sqlerrcontext; @@ -960,7 +981,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) (void) check_sql_fn_retval(querytree_list, rettype, rettupdesc, proc->prokind, - false, NULL); + false); } error_context_stack = sqlerrcontext.previous; diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index 0602398a54546..d6f94db5d999b 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -3,7 +3,7 @@ * pg_publication.c * publication C API manipulation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -48,9 +48,6 @@ typedef struct * table. */ } published_rel; -static void publication_translate_columns(Relation targetrel, List *columns, - int *natts, AttrNumber **attrs); - /* * Check if relation can be in given publication and throws appropriate * error if not. @@ -259,6 +256,52 @@ is_schema_publication(Oid pubid) return result; } +/* + * Returns true if the relation has column list associated with the + * publication, false otherwise. + * + * If a column list is found, the corresponding bitmap is returned through the + * cols parameter, if provided. The bitmap is constructed within the given + * memory context (mcxt). + */ +bool +check_and_fetch_column_list(Publication *pub, Oid relid, MemoryContext mcxt, + Bitmapset **cols) +{ + HeapTuple cftuple; + bool found = false; + + if (pub->alltables) + return false; + + cftuple = SearchSysCache2(PUBLICATIONRELMAP, + ObjectIdGetDatum(relid), + ObjectIdGetDatum(pub->oid)); + if (HeapTupleIsValid(cftuple)) + { + Datum cfdatum; + bool isnull; + + /* Lookup the column list attribute. */ + cfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, cftuple, + Anum_pg_publication_rel_prattrs, &isnull); + + /* Was a column list found? */ + if (!isnull) + { + /* Build the column list bitmap in the given memory context. */ + if (cols) + *cols = pub_collist_to_bitmapset(*cols, cfdatum, mcxt); + + found = true; + } + + ReleaseSysCache(cftuple); + } + + return found; +} + /* * Gets the relations based on the publication partition option for a specified * relation. @@ -351,6 +394,33 @@ GetTopMostAncestorInPublication(Oid puboid, List *ancestors, int *ancestor_level return topmost_relid; } +/* + * attnumstoint2vector + * Convert a Bitmapset of AttrNumbers into an int2vector. + * + * AttrNumber numbers are 0-based, i.e., not offset by + * FirstLowInvalidHeapAttributeNumber. + */ +static int2vector * +attnumstoint2vector(Bitmapset *attrs) +{ + int2vector *result; + int n = bms_num_members(attrs); + int i = -1; + int j = 0; + + result = buildint2vector(NULL, n); + + while ((i = bms_next_member(attrs, i)) >= 0) + { + Assert(i <= PG_INT16_MAX); + + result->values[j++] = (int16) i; + } + + return result; +} + /* * Insert new publication / relation mapping. */ @@ -365,12 +435,12 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, Relation targetrel = pri->relation; Oid relid = RelationGetRelid(targetrel); Oid pubreloid; + Bitmapset *attnums; Publication *pub = GetPublication(pubid); - AttrNumber *attarray = NULL; - int natts = 0; ObjectAddress myself, referenced; List *relids = NIL; + int i; rel = table_open(PublicationRelRelationId, RowExclusiveLock); @@ -395,13 +465,8 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, check_publication_add_relation(targetrel); - /* - * Translate column names to attnums and make sure the column list - * contains only allowed elements (no system or generated columns etc.). - * Also build an array of attnums, for storing in the catalog. - */ - publication_translate_columns(pri->relation, pri->columns, - &natts, &attarray); + /* Validate and translate column names into a Bitmapset of attnums. */ + attnums = pub_collist_validate(pri->relation, pri->columns); /* Form a tuple. */ memset(values, 0, sizeof(values)); @@ -423,7 +488,7 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, /* Add column list, if available */ if (pri->columns) - values[Anum_pg_publication_rel_prattrs - 1] = PointerGetDatum(buildint2vector(attarray, natts)); + values[Anum_pg_publication_rel_prattrs - 1] = PointerGetDatum(attnumstoint2vector(attnums)); else nulls[Anum_pg_publication_rel_prattrs - 1] = true; @@ -451,9 +516,10 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, false); /* Add dependency on the columns, if any are listed */ - for (int i = 0; i < natts; i++) + i = -1; + while ((i = bms_next_member(attnums, i)) >= 0) { - ObjectAddressSubSet(referenced, RelationRelationId, relid, attarray[i]); + ObjectAddressSubSet(referenced, RelationRelationId, relid, i); recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } @@ -476,47 +542,23 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, return myself; } -/* qsort comparator for attnums */ -static int -compare_int16(const void *a, const void *b) -{ - int av = *(const int16 *) a; - int bv = *(const int16 *) b; - - /* this can't overflow if int is wider than int16 */ - return (av - bv); -} - /* - * Translate a list of column names to an array of attribute numbers - * and a Bitmapset with them; verify that each attribute is appropriate - * to have in a publication column list (no system or generated attributes, - * no duplicates). Additional checks with replica identity are done later; - * see pub_collist_contains_invalid_column. + * pub_collist_validate + * Process and validate the 'columns' list and ensure the columns are all + * valid to use for a publication. Checks for and raises an ERROR for + * any unknown columns, system columns, duplicate columns, or virtual + * generated columns. * - * Note that the attribute numbers are *not* offset by - * FirstLowInvalidHeapAttributeNumber; system columns are forbidden so this - * is okay. + * Looks up each column's attnum and returns a 0-based Bitmapset of the + * corresponding attnums. */ -static void -publication_translate_columns(Relation targetrel, List *columns, - int *natts, AttrNumber **attrs) +Bitmapset * +pub_collist_validate(Relation targetrel, List *columns) { - AttrNumber *attarray = NULL; Bitmapset *set = NULL; ListCell *lc; - int n = 0; TupleDesc tupdesc = RelationGetDescr(targetrel); - /* Bail out when no column list defined. */ - if (!columns) - return; - - /* - * Translate list of columns to attnums. We prohibit system attributes and - * make sure there are no duplicate columns. - */ - attarray = palloc(sizeof(AttrNumber) * list_length(columns)); foreach(lc, columns) { char *colname = strVal(lfirst(lc)); @@ -534,10 +576,10 @@ publication_translate_columns(Relation targetrel, List *columns, errmsg("cannot use system column \"%s\" in publication column list", colname)); - if (TupleDescAttr(tupdesc, attnum - 1)->attgenerated) + if (TupleDescAttr(tupdesc, attnum - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) ereport(ERROR, errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("cannot use generated column \"%s\" in publication column list", + errmsg("cannot use virtual generated column \"%s\" in publication column list", colname)); if (bms_is_member(attnum, set)) @@ -547,16 +589,9 @@ publication_translate_columns(Relation targetrel, List *columns, colname)); set = bms_add_member(set, attnum); - attarray[n++] = attnum; } - /* Be tidy, so that the catalog representation is always sorted */ - qsort(attarray, n, sizeof(AttrNumber), compare_int16); - - *natts = n; - *attrs = attarray; - - bms_free(set); + return set; } /* @@ -569,19 +604,12 @@ publication_translate_columns(Relation targetrel, List *columns, Bitmapset * pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols, MemoryContext mcxt) { - Bitmapset *result = NULL; + Bitmapset *result = columns; ArrayType *arr; int nelems; int16 *elems; MemoryContext oldcxt = NULL; - /* - * If an existing bitmap was provided, use it. Otherwise just use NULL and - * build a new bitmap. - */ - if (columns) - result = columns; - arr = DatumGetArrayTypeP(pubcols); nelems = ARR_DIMS(arr)[0]; elems = (int16 *) ARR_DATA_PTR(arr); @@ -599,6 +627,42 @@ pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols, MemoryContext mcxt) return result; } +/* + * Returns a bitmap representing the columns of the specified table. + * + * Generated columns are included if include_gencols_type is + * PUBLISH_GENCOLS_STORED. + */ +Bitmapset * +pub_form_cols_map(Relation relation, PublishGencolsType include_gencols_type) +{ + Bitmapset *result = NULL; + TupleDesc desc = RelationGetDescr(relation); + + for (int i = 0; i < desc->natts; i++) + { + Form_pg_attribute att = TupleDescAttr(desc, i); + + if (att->attisdropped) + continue; + + if (att->attgenerated) + { + /* We only support replication of STORED generated cols. */ + if (att->attgenerated != ATTRIBUTE_GENERATED_STORED) + continue; + + /* User hasn't requested to replicate STORED generated cols. */ + if (include_gencols_type != PUBLISH_GENCOLS_STORED) + continue; + } + + result = bms_add_member(result, att->attnum); + } + + return result; +} + /* * Insert new publication / schema mapping. */ @@ -1024,6 +1088,7 @@ GetPublication(Oid pubid) pub->pubactions.pubdelete = pubform->pubdelete; pub->pubactions.pubtruncate = pubform->pubtruncate; pub->pubviaroot = pubform->pubviaroot; + pub->pubgencols_type = pubform->pubgencols; ReleaseSysCache(tup); @@ -1077,8 +1142,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS) * publication name. */ arr = PG_GETARG_ARRAYTYPE_P(0); - deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT, - &elems, NULL, &nelems); + deconstruct_array_builtin(arr, TEXTOID, &elems, NULL, &nelems); /* Get Oids of tables from each publication. */ for (i = 0; i < nelems; i++) @@ -1158,7 +1222,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS) PG_NODE_TREEOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); - funcctx->user_fctx = (void *) table_infos; + funcctx->user_fctx = table_infos; MemoryContextSwitchTo(oldcontext); } @@ -1232,9 +1296,23 @@ pg_get_publication_tables(PG_FUNCTION_ARGS) { Form_pg_attribute att = TupleDescAttr(desc, i); - if (att->attisdropped || att->attgenerated) + if (att->attisdropped) continue; + if (att->attgenerated) + { + /* We only support replication of STORED generated cols. */ + if (att->attgenerated != ATTRIBUTE_GENERATED_STORED) + continue; + + /* + * User hasn't requested to replicate STORED generated + * cols. + */ + if (pub->pubgencols_type != PUBLISH_GENCOLS_STORED) + continue; + } + attnums[nattnums++] = att->attnum; } diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c index 501a6ba41060b..8df73e7ab71b4 100644 --- a/src/backend/catalog/pg_range.c +++ b/src/backend/catalog/pg_range.c @@ -3,7 +3,7 @@ * pg_range.c * routines to support manipulation of the pg_range relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 753afb88453dc..536191284e803 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -3,7 +3,7 @@ * pg_shdepend.c * routines to support manipulation of the pg_shdepend relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 9efc9159f2c22..1395032413e3d 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -3,7 +3,7 @@ * pg_subscription.c * replication subscriptions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -34,6 +34,37 @@ static List *textarray_to_stringlist(ArrayType *textarray); +/* + * Add a comma-separated list of publication names to the 'dest' string. + */ +void +GetPublicationsStr(List *publications, StringInfo dest, bool quote_literal) +{ + ListCell *lc; + bool first = true; + + Assert(publications != NIL); + + foreach(lc, publications) + { + char *pubname = strVal(lfirst(lc)); + + if (first) + first = false; + else + appendStringInfoString(dest, ", "); + + if (quote_literal) + appendStringInfoString(dest, quote_literal_cstr(pubname)); + else + { + appendStringInfoChar(dest, '"'); + appendStringInfoString(dest, pubname); + appendStringInfoChar(dest, '"'); + } + } +} + /* * Fetch the subscription from the syscache. */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 395dec8ed88e8..b36f81afb9d3f 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -3,7 +3,7 @@ * pg_type.c * routines to support manipulation of the pg_type relation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt index c002f37202f58..ebe85337c2877 100644 --- a/src/backend/catalog/sql_features.txt +++ b/src/backend/catalog/sql_features.txt @@ -281,7 +281,7 @@ F461 Named character sets NO F471 Scalar subquery values YES F481 Expanded NULL predicate YES F491 Constraint management YES -F492 Optional table constraint enforcement NO +F492 Optional table constraint enforcement YES except not-null constraints F501 Features and conformance views YES F501 Features and conformance views 01 SQL_FEATURES view YES F501 Features and conformance views 02 SQL_SIZING view YES diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index f56b3cc0f231b..227df90f89c97 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -3,7 +3,7 @@ * storage.c * code to create and destroy physical storage for relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -27,6 +27,7 @@ #include "catalog/storage.h" #include "catalog/storage_xlog.h" #include "miscadmin.h" +#include "pgstat.h" #include "storage/bulk_write.h" #include "storage/freespace.h" #include "storage/proc.h" @@ -194,7 +195,7 @@ log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum) xlrec.forkNum = forkNum; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLR_SPECIAL_REL_UPDATE); } @@ -291,6 +292,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) bool vm; bool need_fsm_vacuum = false; ForkNumber forks[MAX_FORKNUM]; + BlockNumber old_blocks[MAX_FORKNUM]; BlockNumber blocks[MAX_FORKNUM]; int nforks = 0; SMgrRelation reln; @@ -306,6 +308,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) /* Prepare for truncation of MAIN fork of the relation */ forks[nforks] = MAIN_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, MAIN_FORKNUM); blocks[nforks] = nblocks; nforks++; @@ -317,6 +320,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) if (BlockNumberIsValid(blocks[nforks])) { forks[nforks] = FSM_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, FSM_FORKNUM); nforks++; need_fsm_vacuum = true; } @@ -330,6 +334,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) if (BlockNumberIsValid(blocks[nforks])) { forks[nforks] = VISIBILITYMAP_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, VISIBILITYMAP_FORKNUM); nforks++; } } @@ -337,30 +342,49 @@ RelationTruncate(Relation rel, BlockNumber nblocks) RelationPreTruncate(rel); /* - * Make sure that a concurrent checkpoint can't complete while truncation - * is in progress. + * The code which follows can interact with concurrent checkpoints in two + * separate ways. * - * The truncation operation might drop buffers that the checkpoint + * First, the truncation operation might drop buffers that the checkpoint * otherwise would have flushed. If it does, then it's essential that the * files actually get truncated on disk before the checkpoint record is * written. Otherwise, if reply begins from that checkpoint, the * to-be-truncated blocks might still exist on disk but have older * contents than expected, which can cause replay to fail. It's OK for the * blocks to not exist on disk at all, but not for them to have the wrong - * contents. + * contents. For this reason, we need to set DELAY_CHKPT_COMPLETE while + * this code executes. + * + * Second, the call to smgrtruncate() below will in turn call + * RegisterSyncRequest(). We need the sync request created by that call to + * be processed before the checkpoint completes. CheckPointGuts() will + * call ProcessSyncRequests(), but if we register our sync request after + * that happens, then the WAL record for the truncation could end up + * preceding the checkpoint record, while the actual sync doesn't happen + * until the next checkpoint. To prevent that, we need to set + * DELAY_CHKPT_START here. That way, if the XLOG_SMGR_TRUNCATE precedes + * the redo pointer of a concurrent checkpoint, we're guaranteed that the + * corresponding sync request will be processed before the checkpoint + * completes. */ - Assert((MyProc->delayChkptFlags & DELAY_CHKPT_COMPLETE) == 0); - MyProc->delayChkptFlags |= DELAY_CHKPT_COMPLETE; + Assert((MyProc->delayChkptFlags & (DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE)) == 0); + MyProc->delayChkptFlags |= DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE; /* - * We WAL-log the truncation before actually truncating, which means - * trouble if the truncation fails. If we then crash, the WAL replay - * likely isn't going to succeed in the truncation either, and cause a - * PANIC. It's tempting to put a critical section here, but that cure - * would be worse than the disease. It would turn a usually harmless - * failure to truncate, that might spell trouble at WAL replay, into a - * certain PANIC. + * We WAL-log the truncation first and then truncate in a critical + * section. Truncation drops buffers, even if dirty, and then truncates + * disk files. All of that work needs to complete before the lock is + * released, or else old versions of pages on disk that are missing recent + * changes would become accessible again. We'll try the whole operation + * again in crash recovery if we panic, but even then we can't give up + * because we don't want standbys' relation sizes to diverge and break + * replay or visibility invariants downstream. The critical section also + * suppresses interrupts. + * + * (See also visibilitymap.c if changing this code.) */ + START_CRIT_SECTION(); + if (RelationNeedsWAL(rel)) { /* @@ -374,7 +398,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) xlrec.flags = SMGR_TRUNCATE_ALL; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE); @@ -384,10 +408,10 @@ RelationTruncate(Relation rel, BlockNumber nblocks) * hit the disk before the WAL record, and the truncation of the FSM * or visibility map. If we crashed during that window, we'd be left * with a truncated heap, but the FSM or visibility map would still - * contain entries for the non-existent heap pages. + * contain entries for the non-existent heap pages, and standbys would + * also never replay the truncation. */ - if (fsm || vm) - XLogFlush(lsn); + XLogFlush(lsn); } /* @@ -395,10 +419,12 @@ RelationTruncate(Relation rel, BlockNumber nblocks) * longer exist after truncation is complete, and then truncate the * corresponding files on disk. */ - smgrtruncate(RelationGetSmgr(rel), forks, nforks, blocks); + smgrtruncate(RelationGetSmgr(rel), forks, nforks, old_blocks, blocks); + + END_CRIT_SECTION(); /* We've done all the critical work, so checkpoints are OK now. */ - MyProc->delayChkptFlags &= ~DELAY_CHKPT_COMPLETE; + MyProc->delayChkptFlags &= ~(DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE); /* * Update upper-level FSM pages to account for the truncation. This is @@ -482,6 +508,9 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, for (blkno = 0; blkno < nblocks; blkno++) { BulkWriteBuffer buf; + int piv_flags; + bool checksum_failure; + bool verified; /* If we got a cancel signal during the copy of the data, quit */ CHECK_FOR_INTERRUPTS(); @@ -489,8 +518,20 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, buf = smgr_bulk_get_buf(bulkstate); smgrread(src, forkNum, blkno, (Page) buf); - if (!PageIsVerifiedExtended((Page) buf, blkno, - PIV_LOG_WARNING | PIV_REPORT_STAT)) + piv_flags = PIV_LOG_WARNING; + if (ignore_checksum_failure) + piv_flags |= PIV_IGNORE_CHECKSUM_FAILURE; + verified = PageIsVerified((Page) buf, blkno, piv_flags, + &checksum_failure); + if (checksum_failure) + { + RelFileLocatorBackend rloc = src->smgr_rlocator; + + pgstat_prepare_report_checksum_failure(rloc.locator.dbOid); + pgstat_report_checksum_failures_in_db(rloc.locator.dbOid, 1); + } + + if (!verified) { /* * For paranoia's sake, capture the file path before invoking the @@ -499,14 +540,14 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, * (errcontext callbacks shouldn't be risking any such thing, but * people have been known to forget that rule.) */ - char *relpath = relpathbackend(src->smgr_rlocator.locator, + RelPathStr relpath = relpathbackend(src->smgr_rlocator.locator, src->smgr_rlocator.backend, forkNum); ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("invalid page in block %u of relation %s", - blkno, relpath))); + blkno, relpath.str))); } /* @@ -738,7 +779,7 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker) { ForkNumber fork; BlockNumber nblocks[MAX_FORKNUM + 1]; - BlockNumber total_blocks = 0; + uint64 total_blocks = 0; SMgrRelation srel; srel = smgropen(pendingsync->rlocator, INVALID_PROC_NUMBER); @@ -782,7 +823,7 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker) * main fork is longer than ever but FSM fork gets shorter. */ if (pendingsync->is_truncated || - total_blocks * BLCKSZ / 1024 >= wal_skip_threshold) + total_blocks >= wal_skip_threshold * (uint64) 1024 / BLCKSZ) { /* allocate the initial array, or extend it, if needed */ if (maxrels == 0) @@ -960,6 +1001,7 @@ smgr_redo(XLogReaderState *record) Relation rel; ForkNumber forks[MAX_FORKNUM]; BlockNumber blocks[MAX_FORKNUM]; + BlockNumber old_blocks[MAX_FORKNUM]; int nforks = 0; bool need_fsm_vacuum = false; @@ -994,6 +1036,7 @@ smgr_redo(XLogReaderState *record) if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0) { forks[nforks] = MAIN_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, MAIN_FORKNUM); blocks[nforks] = xlrec->blkno; nforks++; @@ -1011,6 +1054,7 @@ smgr_redo(XLogReaderState *record) if (BlockNumberIsValid(blocks[nforks])) { forks[nforks] = FSM_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, FSM_FORKNUM); nforks++; need_fsm_vacuum = true; } @@ -1022,13 +1066,18 @@ smgr_redo(XLogReaderState *record) if (BlockNumberIsValid(blocks[nforks])) { forks[nforks] = VISIBILITYMAP_FORKNUM; + old_blocks[nforks] = smgrnblocks(reln, VISIBILITYMAP_FORKNUM); nforks++; } } /* Do the real work to truncate relation forks */ if (nforks > 0) - smgrtruncate(reln, forks, nforks, blocks); + { + START_CRIT_SECTION(); + smgrtruncate(reln, forks, nforks, old_blocks, blocks); + END_CRIT_SECTION(); + } /* * Update upper-level FSM pages to account for the truncation. This is diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index ae099e328c245..566f308e4439d 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -1,7 +1,7 @@ /* * PostgreSQL System Functions * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/backend/catalog/system_functions.sql * @@ -607,6 +607,20 @@ LANGUAGE INTERNAL STRICT STABLE PARALLEL SAFE AS 'jsonb_path_query_first_tz'; +CREATE OR REPLACE FUNCTION + jsonb_strip_nulls(target jsonb, strip_in_arrays boolean DEFAULT false) +RETURNS jsonb +LANGUAGE INTERNAL +STRICT STABLE PARALLEL SAFE +AS 'jsonb_strip_nulls'; + +CREATE OR REPLACE FUNCTION + json_strip_nulls(target json, strip_in_arrays boolean DEFAULT false) +RETURNS json +LANGUAGE INTERNAL +STRICT STABLE PARALLEL SAFE +AS 'json_strip_nulls'; + -- default normalization form is NFC, per SQL standard CREATE OR REPLACE FUNCTION "normalize"(text, text DEFAULT 'NFC') @@ -679,9 +693,11 @@ REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_table_counters(oid) FROM public; REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM public; +REVOKE EXECUTE ON FUNCTION pg_stat_reset_backend_stats(integer) FROM public; + REVOKE EXECUTE ON FUNCTION pg_stat_reset_replication_slot(text) FROM public; -REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, oid) FROM public; +REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, int8) FROM public; REVOKE EXECUTE ON FUNCTION pg_stat_reset_subscription_stats(oid) FROM public; @@ -697,6 +713,8 @@ REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public; REVOKE EXECUTE ON FUNCTION pg_ls_archive_statusdir() FROM public; +REVOKE EXECUTE ON FUNCTION pg_ls_summariesdir() FROM public; + REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public; REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public; @@ -767,6 +785,8 @@ GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor; GRANT EXECUTE ON FUNCTION pg_ls_archive_statusdir() TO pg_monitor; +GRANT EXECUTE ON FUNCTION pg_ls_summariesdir() TO pg_monitor; + GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor; GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor; diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 19cabc9a47fa0..08f780a2e6382 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1,7 +1,7 @@ /* * PostgreSQL System Views * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/backend/catalog/system_views.sql * @@ -634,7 +634,12 @@ REVOKE ALL ON pg_ident_file_mappings FROM PUBLIC; REVOKE EXECUTE ON FUNCTION pg_ident_file_mappings() FROM PUBLIC; CREATE VIEW pg_timezone_abbrevs AS - SELECT * FROM pg_timezone_abbrevs(); + SELECT * FROM pg_timezone_abbrevs_zone() z + UNION ALL + (SELECT * FROM pg_timezone_abbrevs_abbrevs() a + WHERE NOT EXISTS (SELECT 1 FROM pg_timezone_abbrevs_zone() z2 + WHERE z2.abbrev = a.abbrev)) + ORDER BY abbrev; CREATE VIEW pg_timezone_names AS SELECT * FROM pg_timezone_names(); @@ -653,6 +658,14 @@ GRANT SELECT ON pg_shmem_allocations TO pg_read_all_stats; REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations() FROM PUBLIC; GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations() TO pg_read_all_stats; +CREATE VIEW pg_shmem_allocations_numa AS + SELECT * FROM pg_get_shmem_allocations_numa(); + +REVOKE ALL ON pg_shmem_allocations_numa FROM PUBLIC; +GRANT SELECT ON pg_shmem_allocations_numa TO pg_read_all_stats; +REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() FROM PUBLIC; +GRANT EXECUTE ON FUNCTION pg_get_shmem_allocations_numa() TO pg_read_all_stats; + CREATE VIEW pg_backend_memory_contexts AS SELECT * FROM pg_get_backend_memory_contexts(); @@ -691,7 +704,11 @@ CREATE VIEW pg_stat_all_tables AS pg_stat_get_vacuum_count(C.oid) AS vacuum_count, pg_stat_get_autovacuum_count(C.oid) AS autovacuum_count, pg_stat_get_analyze_count(C.oid) AS analyze_count, - pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count + pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count, + pg_stat_get_total_vacuum_time(C.oid) AS total_vacuum_time, + pg_stat_get_total_autovacuum_time(C.oid) AS total_autovacuum_time, + pg_stat_get_total_analyze_time(C.oid) AS total_analyze_time, + pg_stat_get_total_autoanalyze_time(C.oid) AS total_autoanalyze_time FROM pg_class C LEFT JOIN pg_index I ON C.oid = I.indrelid LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) @@ -1016,6 +1033,7 @@ CREATE VIEW pg_replication_slots AS L.wal_status, L.safe_wal_size, L.two_phase, + L.two_phase_at, L.inactive_since, L.conflicting, L.invalidation_reason, @@ -1073,6 +1091,8 @@ CREATE VIEW pg_stat_database AS pg_stat_get_db_sessions_abandoned(D.oid) AS sessions_abandoned, pg_stat_get_db_sessions_fatal(D.oid) AS sessions_fatal, pg_stat_get_db_sessions_killed(D.oid) AS sessions_killed, + pg_stat_get_db_parallel_workers_to_launch(D.oid) as parallel_workers_to_launch, + pg_stat_get_db_parallel_workers_launched(D.oid) as parallel_workers_launched, pg_stat_get_db_stat_reset_time(D.oid) AS stats_reset FROM ( SELECT 0 AS oid, NULL::name AS datname @@ -1138,12 +1158,14 @@ CREATE VIEW pg_stat_checkpointer AS SELECT pg_stat_get_checkpointer_num_timed() AS num_timed, pg_stat_get_checkpointer_num_requested() AS num_requested, + pg_stat_get_checkpointer_num_performed() AS num_done, pg_stat_get_checkpointer_restartpoints_timed() AS restartpoints_timed, pg_stat_get_checkpointer_restartpoints_requested() AS restartpoints_req, pg_stat_get_checkpointer_restartpoints_performed() AS restartpoints_done, pg_stat_get_checkpointer_write_time() AS write_time, pg_stat_get_checkpointer_sync_time() AS sync_time, pg_stat_get_checkpointer_buffers_written() AS buffers_written, + pg_stat_get_checkpointer_slru_written() AS slru_written, pg_stat_get_checkpointer_stat_reset_time() AS stats_reset; CREATE VIEW pg_stat_io AS @@ -1152,14 +1174,16 @@ SELECT b.object, b.context, b.reads, + b.read_bytes, b.read_time, b.writes, + b.write_bytes, b.write_time, b.writebacks, b.writeback_time, b.extends, + b.extend_bytes, b.extend_time, - b.op_bytes, b.hits, b.evictions, b.reuses, @@ -1174,10 +1198,6 @@ CREATE VIEW pg_stat_wal AS w.wal_fpi, w.wal_bytes, w.wal_buffers_full, - w.wal_write, - w.wal_sync, - w.wal_write_time, - w.wal_sync_time, w.stats_reset FROM pg_stat_get_wal() w; @@ -1198,7 +1218,8 @@ CREATE VIEW pg_stat_progress_analyze AS S.param5 AS ext_stats_computed, S.param6 AS child_tables_total, S.param7 AS child_tables_done, - CAST(S.param8 AS oid) AS current_child_table_relid + CAST(S.param8 AS oid) AS current_child_table_relid, + S.param9 / 1000000::double precision AS delay_time FROM pg_stat_get_progress_info('ANALYZE') AS S LEFT JOIN pg_database D ON S.datid = D.oid; @@ -1218,7 +1239,8 @@ CREATE VIEW pg_stat_progress_vacuum AS S.param4 AS heap_blks_vacuumed, S.param5 AS index_vacuum_count, S.param6 AS max_dead_tuple_bytes, S.param7 AS dead_tuple_bytes, S.param8 AS num_dead_item_ids, S.param9 AS indexes_total, - S.param10 AS indexes_processed + S.param10 AS indexes_processed, + S.param11 / 1000000::double precision AS delay_time FROM pg_stat_get_progress_info('VACUUM') AS S LEFT JOIN pg_database D ON S.datid = D.oid; @@ -1365,9 +1387,23 @@ CREATE VIEW pg_stat_subscription_stats AS s.subname, ss.apply_error_count, ss.sync_error_count, + ss.confl_insert_exists, + ss.confl_update_origin_differs, + ss.confl_update_exists, + ss.confl_update_missing, + ss.confl_delete_origin_differs, + ss.confl_delete_missing, + ss.confl_multiple_unique_conflicts, ss.stats_reset FROM pg_subscription as s, pg_stat_get_subscription_stats(s.oid) as ss; CREATE VIEW pg_wait_events AS SELECT * FROM pg_get_wait_events(); + +CREATE VIEW pg_aios AS + SELECT * FROM pg_get_aios(); +REVOKE ALL ON pg_aios FROM PUBLIC; +GRANT SELECT ON pg_aios TO pg_read_all_stats; +REVOKE EXECUTE ON FUNCTION pg_get_aios() FROM PUBLIC; +GRANT EXECUTE ON FUNCTION pg_get_aios() TO pg_read_all_stats; diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 738bc46ae8293..874a8fc89adb3 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -4,7 +4,7 @@ * This file contains routines to support creation of toast tables * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -29,6 +29,7 @@ #include "catalog/toasting.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "utils/fmgroids.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -333,21 +334,36 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, */ class_rel = table_open(RelationRelationId, RowExclusiveLock); - reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid)); - if (!HeapTupleIsValid(reltup)) - elog(ERROR, "cache lookup failed for relation %u", relOid); - - ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; - if (!IsBootstrapProcessingMode()) { /* normal case, use a transactional update */ + reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid)); + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "cache lookup failed for relation %u", relOid); + + ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; + CatalogTupleUpdate(class_rel, &reltup->t_self, reltup); } else { /* While bootstrapping, we cannot UPDATE, so overwrite in-place */ - heap_inplace_update(class_rel, reltup); + + ScanKeyData key[1]; + void *state; + + ScanKeyInit(&key[0], + Anum_pg_class_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relOid)); + systable_inplace_update_begin(class_rel, ClassOidIndexId, true, + NULL, 1, key, &reltup, &state); + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "cache lookup failed for relation %u", relOid); + + ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; + + systable_inplace_update_finish(state, reltup); } heap_freetuple(reltup); diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile index 48f7348f91c72..cb2fbdc7c6018 100644 --- a/src/backend/commands/Makefile +++ b/src/backend/commands/Makefile @@ -34,6 +34,9 @@ OBJS = \ dropcmds.o \ event_trigger.o \ explain.o \ + explain_dr.o \ + explain_format.o \ + explain_state.o \ extension.o \ foreigncmds.o \ functioncmds.o \ diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index fde5a2a0e0496..4268adfe78729 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -4,7 +4,7 @@ * * Routines for aggregate-manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -12,11 +12,11 @@ * src/backend/commands/aggregatecmds.c * * DESCRIPTION - * The "DefineFoo" routines take the parse tree and pick out the + * The "DefineAggregate" routine takes the parse tree and picks out the * appropriate arguments/flags, passing the results to the - * corresponding "FooDefine" routines (in src/catalog) that do - * the actual catalog-munging. These routines also verify permission - * of the user to execute the command. + * "AggregateCreate" routine (in src/backend/catalog), which does the + * actual catalog-munging. DefineAggregate also verifies the permission of + * the user to execute the command. * *------------------------------------------------------------------------- */ diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 4f99ebb4470a6..c801c869c1cfc 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -3,7 +3,7 @@ * alter.c * Drivers for generic alter commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -59,6 +59,7 @@ #include "miscadmin.h" #include "replication/logicalworker.h" #include "rewrite/rewriteDefine.h" +#include "storage/lmgr.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -337,6 +338,22 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name) InvokeObjectPostAlterHook(classId, objectId, 0); + /* Do post catalog-update tasks */ + if (classId == PublicationRelationId) + { + Form_pg_publication pub = (Form_pg_publication) GETSTRUCT(oldtup); + + /* + * Invalidate relsynccache entries. + * + * Unlike ALTER PUBLICATION ADD/SET/DROP commands, renaming a + * publication does not impact the publication status of tables. So, + * we don't need to invalidate relcache to rebuild the rd_pubdesc. + * Instead, we invalidate only the relsyncache. + */ + InvalidatePubRelSyncCache(pub->oid, pub->puballtables); + } + /* Release memory */ pfree(values); pfree(nulls); @@ -421,13 +438,11 @@ ExecRenameStmt(RenameStmt *stmt) { ObjectAddress address; Relation catalog; - Relation relation; address = get_object_address(stmt->renameType, stmt->object, - &relation, + NULL, AccessExclusiveLock, false); - Assert(relation == NULL); catalog = table_open(address.classId, RowExclusiveLock); AlterObjectRename_internal(catalog, @@ -482,8 +497,7 @@ ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddre table_close(rel, NoLock); refAddr = get_object_address(OBJECT_EXTENSION, (Node *) stmt->extname, - &rel, AccessExclusiveLock, false); - Assert(rel == NULL); + NULL, AccessExclusiveLock, false); if (refAddress) *refAddress = refAddr; @@ -563,16 +577,14 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, case OBJECT_TSTEMPLATE: { Relation catalog; - Relation relation; Oid classId; Oid nspOid; address = get_object_address(stmt->objectType, stmt->object, - &relation, + NULL, AccessExclusiveLock, false); - Assert(relation == NULL); classId = address.classId; catalog = table_open(classId, RowExclusiveLock); nspOid = LookupCreationNamespace(stmt->newschema); @@ -876,15 +888,13 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) case OBJECT_TSDICTIONARY: case OBJECT_TSCONFIGURATION: { - Relation relation; ObjectAddress address; address = get_object_address(stmt->objectType, stmt->object, - &relation, + NULL, AccessExclusiveLock, false); - Assert(relation == NULL); AlterObjectOwner_internal(address.classId, address.objectId, newowner); @@ -931,7 +941,9 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) rel = table_open(catalogId, RowExclusiveLock); - oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId); + /* Search tuple and lock it. */ + oldtup = + get_catalog_object_by_oid_extended(rel, Anum_oid, objectId, true); if (oldtup == NULL) elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", objectId, RelationGetRelationName(rel)); @@ -1031,6 +1043,8 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) /* Perform actual update */ CatalogTupleUpdate(rel, &newtup->t_self, newtup); + UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); + /* Update owner dependency reference */ changeDependencyOnOwner(classId, objectId, new_ownerId); @@ -1039,6 +1053,8 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) pfree(nulls); pfree(replaces); } + else + UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); /* Note the post-alter hook gets classId not catalogId */ InvokeObjectPostAlterHook(classId, objectId, 0); diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c index aaa0f9a1dc8c9..58ed9d216cc01 100644 --- a/src/backend/commands/amcmds.c +++ b/src/backend/commands/amcmds.c @@ -3,7 +3,7 @@ * amcmds.c * Routines for SQL commands that manipulate access methods. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index c590a2adc35c0..4fffb76e55735 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -3,7 +3,7 @@ * analyze.c * the Postgres statistics generator * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -41,7 +41,6 @@ #include "parser/parse_oper.h" #include "parser/parse_relation.h" #include "pgstat.h" -#include "postmaster/autovacuum.h" #include "statistics/extended_stats_internal.h" #include "statistics/statistics.h" #include "storage/bufmgr.h" @@ -54,7 +53,6 @@ #include "utils/pg_rusage.h" #include "utils/sampling.h" #include "utils/sortsupport.h" -#include "utils/spccache.h" #include "utils/syscache.h" #include "utils/timestamp.h" @@ -288,7 +286,9 @@ do_analyze_rel(Relation onerel, VacuumParams *params, ind; Relation *Irel; int nindexes; - bool hasindex; + bool verbose, + instrument, + hasindex; VacAttrStats **vacattrstats; AnlIndexData *indexdata; int targrows, @@ -303,12 +303,15 @@ do_analyze_rel(Relation onerel, VacuumParams *params, Oid save_userid; int save_sec_context; int save_nestlevel; - int64 AnalyzePageHit = VacuumPageHit; - int64 AnalyzePageMiss = VacuumPageMiss; - int64 AnalyzePageDirty = VacuumPageDirty; + WalUsage startwalusage = pgWalUsage; + BufferUsage startbufferusage = pgBufferUsage; + BufferUsage bufferusage; PgStat_Counter startreadtime = 0; PgStat_Counter startwritetime = 0; + verbose = (params->options & VACOPT_VERBOSE) != 0; + instrument = (verbose || (AmAutoVacuumWorkerProcess() && + params->log_min_duration >= 0)); if (inh) ereport(elevel, (errmsg("analyzing \"%s.%s\" inheritance tree", @@ -340,8 +343,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params, save_nestlevel = NewGUCNestLevel(); RestrictSearchPath(); - /* measure elapsed time iff autovacuum logging requires it */ - if (AmAutoVacuumWorkerProcess() && params->log_min_duration >= 0) + /* + * When verbose or autovacuum logging is used, initialize a resource usage + * snapshot and optionally track I/O timing. + */ + if (instrument) { if (track_io_timing) { @@ -350,9 +356,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params, } pg_rusage_init(&ru0); - starttime = GetCurrentTimestamp(); } + /* Used for instrumentation and stats report */ + starttime = GetCurrentTimestamp(); + /* * Determine which columns to analyze * @@ -622,12 +630,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params, */ if (!inh) { - BlockNumber relallvisible; + BlockNumber relallvisible = 0; + BlockNumber relallfrozen = 0; if (RELKIND_HAS_STORAGE(onerel->rd_rel->relkind)) - visibilitymap_count(onerel, &relallvisible, NULL); - else - relallvisible = 0; + visibilitymap_count(onerel, &relallvisible, &relallfrozen); /* * Update pg_class for table relation. CCI first, in case acquirefunc @@ -638,6 +645,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, relpages, totalrows, relallvisible, + relallfrozen, hasindex, InvalidTransactionId, InvalidMultiXactId, @@ -654,7 +662,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, vac_update_relstats(Irel[ind], RelationGetNumberOfBlocks(Irel[ind]), totalindexrows, - 0, + 0, 0, false, InvalidTransactionId, InvalidMultiXactId, @@ -670,7 +678,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, */ CommandCounterIncrement(); vac_update_relstats(onerel, -1, totalrows, - 0, hasindex, InvalidTransactionId, + 0, 0, hasindex, InvalidTransactionId, InvalidMultiXactId, NULL, NULL, in_outer_xact); @@ -687,9 +695,9 @@ do_analyze_rel(Relation onerel, VacuumParams *params, */ if (!inh) pgstat_report_analyze(onerel, totalrows, totaldeadrows, - (va_cols == NIL)); + (va_cols == NIL), starttime); else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - pgstat_report_analyze(onerel, 0, 0, (va_cols == NIL)); + pgstat_report_analyze(onerel, 0, 0, (va_cols == NIL), starttime); /* * If this isn't part of VACUUM ANALYZE, let index AMs do cleanup. @@ -724,27 +732,35 @@ do_analyze_rel(Relation onerel, VacuumParams *params, vac_close_indexes(nindexes, Irel, NoLock); /* Log the action if appropriate */ - if (AmAutoVacuumWorkerProcess() && params->log_min_duration >= 0) + if (instrument) { TimestampTz endtime = GetCurrentTimestamp(); - if (params->log_min_duration == 0 || + if (verbose || params->log_min_duration == 0 || TimestampDifferenceExceeds(starttime, endtime, params->log_min_duration)) { long delay_in_ms; + WalUsage walusage; double read_rate = 0; double write_rate = 0; + char *msgfmt; StringInfoData buf; - - /* - * Calculate the difference in the Page Hit/Miss/Dirty that - * happened as part of the analyze by subtracting out the - * pre-analyze values which we saved above. - */ - AnalyzePageHit = VacuumPageHit - AnalyzePageHit; - AnalyzePageMiss = VacuumPageMiss - AnalyzePageMiss; - AnalyzePageDirty = VacuumPageDirty - AnalyzePageDirty; + int64 total_blks_hit; + int64 total_blks_read; + int64 total_blks_dirtied; + + memset(&bufferusage, 0, sizeof(BufferUsage)); + BufferUsageAccumDiff(&bufferusage, &pgBufferUsage, &startbufferusage); + memset(&walusage, 0, sizeof(WalUsage)); + WalUsageAccumDiff(&walusage, &pgWalUsage, &startwalusage); + + total_blks_hit = bufferusage.shared_blks_hit + + bufferusage.local_blks_hit; + total_blks_read = bufferusage.shared_blks_read + + bufferusage.local_blks_read; + total_blks_dirtied = bufferusage.shared_blks_dirtied + + bufferusage.local_blks_dirtied; /* * We do not expect an analyze to take > 25 days and it simplifies @@ -770,10 +786,10 @@ do_analyze_rel(Relation onerel, VacuumParams *params, if (delay_in_ms > 0) { - read_rate = (double) BLCKSZ * AnalyzePageMiss / (1024 * 1024) / - (delay_in_ms / 1000.0); - write_rate = (double) BLCKSZ * AnalyzePageDirty / (1024 * 1024) / - (delay_in_ms / 1000.0); + read_rate = (double) BLCKSZ * total_blks_read / + (1024 * 1024) / (delay_in_ms / 1000.0); + write_rate = (double) BLCKSZ * total_blks_dirtied / + (1024 * 1024) / (delay_in_ms / 1000.0); } /* @@ -782,10 +798,25 @@ do_analyze_rel(Relation onerel, VacuumParams *params, */ initStringInfo(&buf); - appendStringInfo(&buf, _("automatic analyze of table \"%s.%s.%s\"\n"), + + if (AmAutoVacuumWorkerProcess()) + msgfmt = _("automatic analyze of table \"%s.%s.%s\"\n"); + else + msgfmt = _("finished analyzing table \"%s.%s.%s\"\n"); + + appendStringInfo(&buf, msgfmt, get_database_name(MyDatabaseId), get_namespace_name(RelationGetNamespace(onerel)), RelationGetRelationName(onerel)); + if (track_cost_delay_timing) + { + /* + * We bypass the changecount mechanism because this value is + * only updated by the calling process. + */ + appendStringInfo(&buf, _("delay time: %.3f ms\n"), + (double) MyBEEntry->st_progress_param[PROGRESS_ANALYZE_DELAY_TIME] / 1000000.0); + } if (track_io_timing) { double read_ms = (double) (pgStatBlockReadTime - startreadtime) / 1000; @@ -796,13 +827,19 @@ do_analyze_rel(Relation onerel, VacuumParams *params, } appendStringInfo(&buf, _("avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"), read_rate, write_rate); - appendStringInfo(&buf, _("buffer usage: %lld hits, %lld misses, %lld dirtied\n"), - (long long) AnalyzePageHit, - (long long) AnalyzePageMiss, - (long long) AnalyzePageDirty); + appendStringInfo(&buf, _("buffer usage: %" PRId64 " hits, %" PRId64 " reads, %" PRId64 " dirtied\n"), + total_blks_hit, + total_blks_read, + total_blks_dirtied); + appendStringInfo(&buf, + _("WAL usage: %" PRId64 " records, %" PRId64 " full page images, %" PRIu64 " bytes, %" PRId64 " buffers full\n"), + walusage.wal_records, + walusage.wal_fpi, + walusage.wal_bytes, + walusage.wal_buffers_full); appendStringInfo(&buf, _("system usage: %s"), pg_rusage_show(&ru0)); - ereport(LOG, + ereport(verbose ? INFO : LOG, (errmsg_internal("%s", buf.data))); pfree(buf.data); @@ -888,7 +925,7 @@ compute_index_stats(Relation onerel, double totalrows, { HeapTuple heapTuple = rows[rowno]; - vacuum_delay_point(); + vacuum_delay_point(true); /* * Reset the per-tuple context each time, to reclaim any cruft @@ -1012,6 +1049,10 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr) if (attr->attisdropped) return NULL; + /* Don't analyze virtual generated columns */ + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + return NULL; + /* * Get attstattarget value. Set to -1 if null. (Analyze functions expect * -1 to mean use default_statistics_target; see for example @@ -1196,7 +1237,12 @@ acquire_sample_rows(Relation onerel, int elevel, scan = table_beginscan_analyze(onerel); slot = table_slot_create(onerel, NULL); - stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE, + /* + * It is safe to use batching, as block_sampling_read_stream_next never + * blocks. + */ + stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE | + READ_STREAM_USE_BATCHING, vac_strategy, scan->rs_rd, MAIN_FORKNUM, @@ -1207,7 +1253,7 @@ acquire_sample_rows(Relation onerel, int elevel, /* Outer loop over blocks to sample */ while (table_scan_analyze_next_block(scan, stream)) { - vacuum_delay_point(); + vacuum_delay_point(true); while (table_scan_analyze_next_tuple(scan, OldestXmin, &liverows, &deadrows, slot)) { @@ -1939,7 +1985,7 @@ compute_trivial_stats(VacAttrStatsP stats, Datum value; bool isnull; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, i, &isnull); @@ -2055,7 +2101,7 @@ compute_distinct_stats(VacAttrStatsP stats, int firstcount1, j; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, i, &isnull); @@ -2402,7 +2448,7 @@ compute_scalar_stats(VacAttrStatsP stats, Datum value; bool isnull; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, i, &isnull); diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 8ed503e1c1bd9..4bd37d5beb559 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -3,7 +3,7 @@ * async.c * Asynchronous notification: NOTIFY, LISTEN, UNLISTEN * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 78f96789b0e84..54a08e4102e14 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -6,7 +6,7 @@ * There is hardly anything left of Paul Brown's original implementation... * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * @@ -32,7 +32,6 @@ #include "catalog/namespace.h" #include "catalog/objectaccess.h" #include "catalog/pg_am.h" -#include "catalog/pg_database.h" #include "catalog/pg_inherits.h" #include "catalog/toasting.h" #include "commands/cluster.h" @@ -70,8 +69,8 @@ typedef struct static void cluster_multiple_rels(List *rtcs, ClusterParams *params); -static void rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose); -static void copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, +static void rebuild_relation(Relation OldHeap, Relation index, bool verbose); +static void copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verbose, bool *pSwapToastByContent, TransactionId *pFreezeXid, MultiXactId *pCutoffMulti); static List *get_tables_to_cluster(MemoryContext cluster_context); @@ -192,13 +191,11 @@ cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel) stmt->indexname, stmt->relation->relname))); } + /* For non-partitioned tables, do what we came here to do. */ if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) { - /* close relation, keep lock till commit */ - table_close(rel, NoLock); - - /* Do the job. */ - cluster_rel(tableOid, indexOid, ¶ms); + cluster_rel(rel, indexOid, ¶ms); + /* cluster_rel closes the relation, but keeps lock */ return; } @@ -275,6 +272,7 @@ cluster_multiple_rels(List *rtcs, ClusterParams *params) foreach(lc, rtcs) { RelToCluster *rtc = (RelToCluster *) lfirst(lc); + Relation rel; /* Start a new transaction for each relation. */ StartTransactionCommand(); @@ -282,8 +280,11 @@ cluster_multiple_rels(List *rtcs, ClusterParams *params) /* functions in indexes may want a snapshot set */ PushActiveSnapshot(GetTransactionSnapshot()); - /* Do the job. */ - cluster_rel(rtc->tableOid, rtc->indexOid, params); + rel = table_open(rtc->tableOid, AccessExclusiveLock); + + /* Process this table */ + cluster_rel(rel, rtc->indexOid, params); + /* cluster_rel closes the relation, but keeps lock */ PopActiveSnapshot(); CommitTransactionCommand(); @@ -296,8 +297,7 @@ cluster_multiple_rels(List *rtcs, ClusterParams *params) * This clusters the table by creating a new, clustered table and * swapping the relfilenumbers of the new table and the old table, so * the OID of the original table is preserved. Thus we do not lose - * GRANT, inheritance nor references to this table (this was a bug - * in releases through 7.3). + * GRANT, inheritance nor references to this table. * * Indexes are rebuilt too, via REINDEX. Since we are effectively bulk-loading * the new table, it's better to create the indexes afterwards than to fill @@ -308,14 +308,17 @@ cluster_multiple_rels(List *rtcs, ClusterParams *params) * and error messages should refer to the operation as VACUUM not CLUSTER. */ void -cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params) +cluster_rel(Relation OldHeap, Oid indexOid, ClusterParams *params) { - Relation OldHeap; + Oid tableOid = RelationGetRelid(OldHeap); Oid save_userid; int save_sec_context; int save_nestlevel; bool verbose = ((params->options & CLUOPT_VERBOSE) != 0); bool recheck = ((params->options & CLUOPT_RECHECK) != 0); + Relation index; + + Assert(CheckRelationLockedByMe(OldHeap, AccessExclusiveLock, false)); /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); @@ -328,21 +331,6 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params) pgstat_progress_update_param(PROGRESS_CLUSTER_COMMAND, PROGRESS_CLUSTER_COMMAND_VACUUM_FULL); - /* - * We grab exclusive access to the target rel and index for the duration - * of the transaction. (This is redundant for the single-transaction - * case, since cluster() already did it.) The index lock is taken inside - * check_index_is_clusterable. - */ - OldHeap = try_relation_open(tableOid, AccessExclusiveLock); - - /* If the table has gone away, we can skip processing it */ - if (!OldHeap) - { - pgstat_progress_end_command(); - return; - } - /* * Switch to the table owner's userid, so that any index functions are run * as that user. Also lock down security-restricted operations and @@ -445,7 +433,14 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params) /* Check heap and index are valid to cluster on */ if (OidIsValid(indexOid)) + { + /* verify the index is good and lock it */ check_index_is_clusterable(OldHeap, indexOid, AccessExclusiveLock); + /* also open it */ + index = index_open(indexOid, NoLock); + } + else + index = NULL; /* * Quietly ignore the request if this is a materialized view which has not @@ -474,9 +469,8 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params) TransferPredicateLocksToHeapRelation(OldHeap); /* rebuild_relation does all the dirty work */ - rebuild_relation(OldHeap, indexOid, verbose); - - /* NB: rebuild_relation does table_close() on OldHeap */ + rebuild_relation(OldHeap, index, verbose); + /* rebuild_relation closes OldHeap, and index if valid */ out: /* Roll back any GUC changes executed by index functions */ @@ -624,45 +618,68 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) /* * rebuild_relation: rebuild an existing relation in index or physical order * - * OldHeap: table to rebuild --- must be opened and exclusive-locked! - * indexOid: index to cluster by, or InvalidOid to rewrite in physical order. + * OldHeap: table to rebuild. + * index: index to cluster by, or NULL to rewrite in physical order. * - * NB: this routine closes OldHeap at the right time; caller should not. + * On entry, heap and index (if one is given) must be open, and + * AccessExclusiveLock held on them. + * On exit, they are closed, but locks on them are not released. */ static void -rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose) +rebuild_relation(Relation OldHeap, Relation index, bool verbose) { Oid tableOid = RelationGetRelid(OldHeap); Oid accessMethod = OldHeap->rd_rel->relam; Oid tableSpace = OldHeap->rd_rel->reltablespace; Oid OIDNewHeap; + Relation NewHeap; char relpersistence; bool is_system_catalog; bool swap_toast_by_content; TransactionId frozenXid; MultiXactId cutoffMulti; - if (OidIsValid(indexOid)) + Assert(CheckRelationLockedByMe(OldHeap, AccessExclusiveLock, false) && + (index == NULL || CheckRelationLockedByMe(index, AccessExclusiveLock, false))); + + if (index) /* Mark the correct index as clustered */ - mark_index_clustered(OldHeap, indexOid, true); + mark_index_clustered(OldHeap, RelationGetRelid(index), true); /* Remember info about rel before closing OldHeap */ relpersistence = OldHeap->rd_rel->relpersistence; is_system_catalog = IsSystemRelation(OldHeap); - /* Close relcache entry, but keep lock until transaction commit */ - table_close(OldHeap, NoLock); - - /* Create the transient table that will receive the re-ordered data */ + /* + * Create the transient table that will receive the re-ordered data. + * + * OldHeap is already locked, so no need to lock it again. make_new_heap + * obtains AccessExclusiveLock on the new heap and its toast table. + */ OIDNewHeap = make_new_heap(tableOid, tableSpace, accessMethod, relpersistence, - AccessExclusiveLock); + NoLock); + Assert(CheckRelationOidLockedByMe(OIDNewHeap, AccessExclusiveLock, false)); + NewHeap = table_open(OIDNewHeap, NoLock); /* Copy the heap data into the new table in the desired order */ - copy_table_data(OIDNewHeap, tableOid, indexOid, verbose, + copy_table_data(NewHeap, OldHeap, index, verbose, &swap_toast_by_content, &frozenXid, &cutoffMulti); + + /* Close relcache entries, but keep lock until transaction commit */ + table_close(OldHeap, NoLock); + if (index) + index_close(index, NoLock); + + /* + * Close the new relation so it can be dropped as soon as the storage is + * swapped. The relation is not visible to others, so no need to unlock it + * explicitly. + */ + table_close(NewHeap, NoLock); + /* * Swap the physical files of the target and transient tables, then * rebuild the target's indexes and throw away the transient table. @@ -811,13 +828,10 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod, * *pCutoffMulti receives the MultiXactId used as a cutoff point. */ static void -copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, +copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verbose, bool *pSwapToastByContent, TransactionId *pFreezeXid, MultiXactId *pCutoffMulti) { - Relation NewHeap, - OldHeap, - OldIndex; Relation relRelation; HeapTuple reltup; Form_pg_class relform; @@ -836,16 +850,6 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, pg_rusage_init(&ru0); - /* - * Open the relations we need. - */ - NewHeap = table_open(OIDNewHeap, AccessExclusiveLock); - OldHeap = table_open(OIDOldHeap, AccessExclusiveLock); - if (OidIsValid(OIDOldIndex)) - OldIndex = index_open(OIDOldIndex, AccessExclusiveLock); - else - OldIndex = NULL; - /* Store a copy of the namespace name for logging purposes */ nspname = get_namespace_name(RelationGetNamespace(OldHeap)); @@ -946,7 +950,8 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, * provided, else plain seqscan. */ if (OldIndex != NULL && OldIndex->rd_rel->relam == BTREE_AM_OID) - use_sort = plan_cluster_use_sort(OIDOldHeap, OIDOldIndex); + use_sort = plan_cluster_use_sort(RelationGetRelid(OldHeap), + RelationGetRelid(OldIndex)); else use_sort = false; @@ -1001,24 +1006,21 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose, tups_recently_dead, pg_rusage_show(&ru0)))); - if (OldIndex != NULL) - index_close(OldIndex, NoLock); - table_close(OldHeap, NoLock); - table_close(NewHeap, NoLock); - /* Update pg_class to reflect the correct values of pages and tuples. */ relRelation = table_open(RelationRelationId, RowExclusiveLock); - reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(OIDNewHeap)); + reltup = SearchSysCacheCopy1(RELOID, + ObjectIdGetDatum(RelationGetRelid(NewHeap))); if (!HeapTupleIsValid(reltup)) - elog(ERROR, "cache lookup failed for relation %u", OIDNewHeap); + elog(ERROR, "cache lookup failed for relation %u", + RelationGetRelid(NewHeap)); relform = (Form_pg_class) GETSTRUCT(reltup); relform->relpages = num_pages; relform->reltuples = num_tuples; /* Don't update the stats for pg_class. See swap_relation_files. */ - if (OIDOldHeap != RelationRelationId) + if (RelationGetRelid(OldHeap) != RelationRelationId) CatalogTupleUpdate(relRelation, &reltup->t_self, reltup); else CacheInvalidateRelcacheByTuple(reltup); @@ -1224,6 +1226,7 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, int32 swap_pages; float4 swap_tuples; int32 swap_allvisible; + int32 swap_allfrozen; swap_pages = relform1->relpages; relform1->relpages = relform2->relpages; @@ -1236,6 +1239,10 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, swap_allvisible = relform1->relallvisible; relform1->relallvisible = relform2->relallvisible; relform2->relallvisible = swap_allvisible; + + swap_allfrozen = relform1->relallfrozen; + relform1->relallfrozen = relform2->relallfrozen; + relform2->relallfrozen = swap_allfrozen; } /* diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 63ef9a08411b0..8acbfbbeda041 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -3,7 +3,7 @@ * collationcmds.c * collation-related commands support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -377,13 +377,9 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e if (!OidIsValid(newoid)) return InvalidObjectAddress; - /* - * Check that the locales can be loaded. NB: pg_newlocale_from_collation - * is only supposed to be called on non-C-equivalent locales. - */ + /* Check that the locales can be loaded. */ CommandCounterIncrement(); - if (!lc_collate_is_c(newoid) || !lc_ctype_is_c(newoid)) - (void) pg_newlocale_from_collation(newoid); + (void) pg_newlocale_from_collation(newoid); ObjectAddressSet(address, CollationRelationId, newoid); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index e9d50fc7d876f..f67a8b95d29de 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -4,7 +4,7 @@ * * PostgreSQL object comments utility code. * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/commands/comment.c diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c index f7dc42f7452c7..3497a8221f29a 100644 --- a/src/backend/commands/constraint.c +++ b/src/backend/commands/constraint.c @@ -3,7 +3,7 @@ * constraint.c * PostgreSQL CONSTRAINT support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index ddd5d1d1c54a2..d3ecc76d97b14 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -3,7 +3,7 @@ * conversioncmds.c * conversion creation command support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index df7a4a21c9458..74ae42b19a710 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -3,7 +3,7 @@ * copy.c * Implements the COPY utility command * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -397,7 +397,9 @@ defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from) if (!is_from) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY ON_ERROR cannot be used with COPY TO"), + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "ON_ERROR", "COPY TO"), parser_errposition(pstate, def->location))); /* @@ -410,11 +412,43 @@ defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY ON_ERROR \"%s\" not recognized", sval), + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s \"%s\" not recognized", "ON_ERROR", sval), parser_errposition(pstate, def->location))); return COPY_ON_ERROR_STOP; /* keep compiler quiet */ } +/* + * Extract REJECT_LIMIT value from a DefElem. + * + * REJECT_LIMIT can be specified in two ways: as an int64 for the COPY command + * option or as a single-quoted string for the foreign table option using + * file_fdw. Therefore this function needs to handle both formats. + */ +static int64 +defGetCopyRejectLimitOption(DefElem *def) +{ + int64 reject_limit; + + if (def->arg == NULL) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s requires a numeric value", + def->defname))); + else if (nodeTag(def->arg) == T_String) + reject_limit = pg_strtoint64(strVal(def->arg)); + else + reject_limit = defGetInt64(def); + + if (reject_limit <= 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("REJECT_LIMIT (%" PRId64 ") must be greater than zero", + reject_limit))); + + return reject_limit; +} + /* * Extract a CopyLogVerbosityChoice value from a DefElem. */ @@ -424,9 +458,11 @@ defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate) char *sval; /* - * Allow "default", or "verbose" values. + * Allow "silent", "default", or "verbose" values. */ sval = defGetString(def); + if (pg_strcasecmp(sval, "silent") == 0) + return COPY_LOG_VERBOSITY_SILENT; if (pg_strcasecmp(sval, "default") == 0) return COPY_LOG_VERBOSITY_DEFAULT; if (pg_strcasecmp(sval, "verbose") == 0) @@ -434,7 +470,8 @@ defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY LOG_VERBOSITY \"%s\" not recognized", sval), + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s \"%s\" not recognized", "LOG_VERBOSITY", sval), parser_errposition(pstate, def->location))); return COPY_LOG_VERBOSITY_DEFAULT; /* keep compiler quiet */ } @@ -466,6 +503,7 @@ ProcessCopyOptions(ParseState *pstate, bool header_specified = false; bool on_error_specified = false; bool log_verbosity_specified = false; + bool reject_limit_specified = false; ListCell *option; /* Support external use for option sanity checking */ @@ -632,6 +670,13 @@ ProcessCopyOptions(ParseState *pstate, log_verbosity_specified = true; opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate); } + else if (strcmp(defel->defname, "reject_limit") == 0) + { + if (reject_limit_specified) + errorConflictingDefElem(defel, pstate); + reject_limit_specified = true; + opts_out->reject_limit = defGetCopyRejectLimitOption(defel); + } else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -641,28 +686,24 @@ ProcessCopyOptions(ParseState *pstate, } /* - * Check for incompatible options (must do these two before inserting + * Check for incompatible options (must do these three before inserting * defaults) */ if (opts_out->binary && opts_out->delim) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot specify DELIMITER in BINARY mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("cannot specify %s in BINARY mode", "DELIMITER"))); if (opts_out->binary && opts_out->null_print) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot specify NULL in BINARY mode"))); + errmsg("cannot specify %s in BINARY mode", "NULL"))); if (opts_out->binary && opts_out->default_print) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot specify DEFAULT in BINARY mode"))); - - if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("only ON_ERROR STOP is allowed in BINARY mode"))); + errmsg("cannot specify %s in BINARY mode", "DEFAULT"))); /* Set defaults for omitted options */ if (!opts_out->delim) @@ -731,13 +772,15 @@ ProcessCopyOptions(ParseState *pstate, if (opts_out->binary && opts_out->header_line) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot specify HEADER in BINARY mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("cannot specify %s in BINARY mode", "HEADER"))); /* Check quote */ if (!opts_out->csv_mode && opts_out->quote != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY QUOTE requires CSV mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s requires CSV mode", "QUOTE"))); if (opts_out->csv_mode && strlen(opts_out->quote) != 1) ereport(ERROR, @@ -753,7 +796,8 @@ ProcessCopyOptions(ParseState *pstate, if (!opts_out->csv_mode && opts_out->escape != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY ESCAPE requires CSV mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s requires CSV mode", "ESCAPE"))); if (opts_out->csv_mode && strlen(opts_out->escape) != 1) ereport(ERROR, @@ -764,71 +808,101 @@ ProcessCopyOptions(ParseState *pstate, if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY FORCE_QUOTE requires CSV mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s requires CSV mode", "FORCE_QUOTE"))); if ((opts_out->force_quote || opts_out->force_quote_all) && is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY FORCE_QUOTE cannot be used with COPY FROM"))); + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "FORCE_QUOTE", + "COPY FROM"))); /* Check force_notnull */ - if (!opts_out->csv_mode && opts_out->force_notnull != NIL) + if (!opts_out->csv_mode && (opts_out->force_notnull != NIL || + opts_out->force_notnull_all)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY FORCE_NOT_NULL requires CSV mode"))); - if (opts_out->force_notnull != NIL && !is_from) + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL"))); + if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) && + !is_from) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY FORCE_NOT_NULL cannot be used with COPY TO"))); + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "FORCE_NOT_NULL", + "COPY TO"))); /* Check force_null */ - if (!opts_out->csv_mode && opts_out->force_null != NIL) + if (!opts_out->csv_mode && (opts_out->force_null != NIL || + opts_out->force_null_all)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY FORCE_NULL requires CSV mode"))); + /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */ + errmsg("COPY %s requires CSV mode", "FORCE_NULL"))); - if (opts_out->force_null != NIL && !is_from) + if ((opts_out->force_null != NIL || opts_out->force_null_all) && + !is_from) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY FORCE_NULL cannot be used with COPY TO"))); + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "FORCE_NULL", + "COPY TO"))); /* Don't allow the delimiter to appear in the null string. */ if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY delimiter character must not appear in the NULL specification"))); + /*- translator: %s is the name of a COPY option, e.g. NULL */ + errmsg("COPY delimiter character must not appear in the %s specification", + "NULL"))); /* Don't allow the CSV quote char to appear in the null string. */ if (opts_out->csv_mode && strchr(opts_out->null_print, opts_out->quote[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("CSV quote character must not appear in the NULL specification"))); + /*- translator: %s is the name of a COPY option, e.g. NULL */ + errmsg("CSV quote character must not appear in the %s specification", + "NULL"))); /* Check freeze */ if (opts_out->freeze && !is_from) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("COPY FREEZE cannot be used with COPY TO"))); + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "FREEZE", + "COPY TO"))); if (opts_out->default_print) { if (!is_from) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY DEFAULT only available using COPY FROM"))); + /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR, + second %s is a COPY with direction, e.g. COPY TO */ + errmsg("COPY %s cannot be used with %s", "DEFAULT", + "COPY TO"))); /* Don't allow the delimiter to appear in the default string. */ if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("COPY delimiter must not appear in the DEFAULT specification"))); + /*- translator: %s is the name of a COPY option, e.g. NULL */ + errmsg("COPY delimiter character must not appear in the %s specification", + "DEFAULT"))); /* Don't allow the CSV quote char to appear in the default string. */ if (opts_out->csv_mode && strchr(opts_out->default_print, opts_out->quote[0]) != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CSV quote character must not appear in the DEFAULT specification"))); + /*- translator: %s is the name of a COPY option, e.g. NULL */ + errmsg("CSV quote character must not appear in the %s specification", + "DEFAULT"))); /* Don't allow the NULL and DEFAULT string to be the same */ if (opts_out->null_print_len == opts_out->default_print_len && @@ -838,6 +912,19 @@ ProcessCopyOptions(ParseState *pstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("NULL specification and DEFAULT specification cannot be the same"))); } + /* Check on_error */ + if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("only ON_ERROR STOP is allowed in BINARY mode"))); + + if (opts_out->reject_limit && !opts_out->on_error) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + /*- translator: first and second %s are the names of COPY option, e.g. + * ON_ERROR, third is the value of the COPY option, e.g. IGNORE */ + errmsg("COPY %s requires %s to be set to %s", + "REJECT_LIMIT", "ON_ERROR", "IGNORE"))); } /* @@ -867,9 +954,9 @@ CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist) for (i = 0; i < attr_count; i++) { - if (TupleDescAttr(tupDesc, i)->attisdropped) - continue; - if (TupleDescAttr(tupDesc, i)->attgenerated) + CompactAttribute *attr = TupleDescCompactAttr(tupDesc, i); + + if (attr->attisdropped || attr->attgenerated) continue; attnums = lappend_int(attnums, i + 1); } diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index ce4d62e707c95..fbbbc09a97b17 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -9,7 +9,7 @@ * Reading data from the input file or client and parsing it into Datums * is handled in copyfromparse.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,7 +28,7 @@ #include "access/tableam.h" #include "access/xact.h" #include "catalog/namespace.h" -#include "commands/copy.h" +#include "commands/copyapi.h" #include "commands/copyfrom_internal.h" #include "commands/progress.h" #include "commands/trigger.h" @@ -68,7 +68,10 @@ */ #define MAX_BUFFERED_BYTES 65535 -/* Trim the list of buffers back down to this number after flushing */ +/* + * Trim the list of buffers back down to this number after flushing. This + * must be >= 2. + */ #define MAX_PARTITION_BUFFERS 32 /* Stores multi-insert data related to a single relation in CopyFrom. */ @@ -103,6 +106,145 @@ typedef struct CopyMultiInsertInfo /* non-export function prototypes */ static void ClosePipeFromProgram(CopyFromState cstate); +/* + * Built-in format-specific routines. One-row callbacks are defined in + * copyfromparse.c. + */ +static void CopyFromTextLikeInFunc(CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, + Oid *typioparam); +static void CopyFromTextLikeStart(CopyFromState cstate, TupleDesc tupDesc); +static void CopyFromTextLikeEnd(CopyFromState cstate); +static void CopyFromBinaryInFunc(CopyFromState cstate, Oid atttypid, + FmgrInfo *finfo, Oid *typioparam); +static void CopyFromBinaryStart(CopyFromState cstate, TupleDesc tupDesc); +static void CopyFromBinaryEnd(CopyFromState cstate); + + +/* + * COPY FROM routines for built-in formats. + * + * CSV and text formats share the same TextLike routines except for the + * one-row callback. + */ + +/* text format */ +static const CopyFromRoutine CopyFromRoutineText = { + .CopyFromInFunc = CopyFromTextLikeInFunc, + .CopyFromStart = CopyFromTextLikeStart, + .CopyFromOneRow = CopyFromTextOneRow, + .CopyFromEnd = CopyFromTextLikeEnd, +}; + +/* CSV format */ +static const CopyFromRoutine CopyFromRoutineCSV = { + .CopyFromInFunc = CopyFromTextLikeInFunc, + .CopyFromStart = CopyFromTextLikeStart, + .CopyFromOneRow = CopyFromCSVOneRow, + .CopyFromEnd = CopyFromTextLikeEnd, +}; + +/* binary format */ +static const CopyFromRoutine CopyFromRoutineBinary = { + .CopyFromInFunc = CopyFromBinaryInFunc, + .CopyFromStart = CopyFromBinaryStart, + .CopyFromOneRow = CopyFromBinaryOneRow, + .CopyFromEnd = CopyFromBinaryEnd, +}; + +/* Return a COPY FROM routine for the given options */ +static const CopyFromRoutine * +CopyFromGetRoutine(const CopyFormatOptions *opts) +{ + if (opts->csv_mode) + return &CopyFromRoutineCSV; + else if (opts->binary) + return &CopyFromRoutineBinary; + + /* default is text */ + return &CopyFromRoutineText; +} + +/* Implementation of the start callback for text and CSV formats */ +static void +CopyFromTextLikeStart(CopyFromState cstate, TupleDesc tupDesc) +{ + AttrNumber attr_count; + + /* + * If encoding conversion is needed, we need another buffer to hold the + * converted input data. Otherwise, we can just point input_buf to the + * same buffer as raw_buf. + */ + if (cstate->need_transcoding) + { + cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1); + cstate->input_buf_index = cstate->input_buf_len = 0; + } + else + cstate->input_buf = cstate->raw_buf; + cstate->input_reached_eof = false; + + initStringInfo(&cstate->line_buf); + + /* + * Create workspace for CopyReadAttributes results; used by CSV and text + * format. + */ + attr_count = list_length(cstate->attnumlist); + cstate->max_fields = attr_count; + cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *)); +} + +/* + * Implementation of the infunc callback for text and CSV formats. Assign + * the input function data to the given *finfo. + */ +static void +CopyFromTextLikeInFunc(CopyFromState cstate, Oid atttypid, FmgrInfo *finfo, + Oid *typioparam) +{ + Oid func_oid; + + getTypeInputInfo(atttypid, &func_oid, typioparam); + fmgr_info(func_oid, finfo); +} + +/* Implementation of the end callback for text and CSV formats */ +static void +CopyFromTextLikeEnd(CopyFromState cstate) +{ + /* nothing to do */ +} + +/* Implementation of the start callback for binary format */ +static void +CopyFromBinaryStart(CopyFromState cstate, TupleDesc tupDesc) +{ + /* Read and verify binary header */ + ReceiveCopyBinaryHeader(cstate); +} + +/* + * Implementation of the infunc callback for binary format. Assign + * the binary input function to the given *finfo. + */ +static void +CopyFromBinaryInFunc(CopyFromState cstate, Oid atttypid, + FmgrInfo *finfo, Oid *typioparam) +{ + Oid func_oid; + + getTypeBinaryInputInfo(atttypid, &func_oid, typioparam); + fmgr_info(func_oid, finfo); +} + +/* Implementation of the end callback for binary format */ +static void +CopyFromBinaryEnd(CopyFromState cstate) +{ + /* nothing to do */ +} + /* * error context callback for COPY FROM * @@ -123,14 +265,14 @@ CopyFromErrorCallback(void *arg) { /* can't usefully display the data */ if (cstate->cur_attname) - errcontext("COPY %s, line %llu, column %s", + errcontext("COPY %s, line %" PRIu64 ", column %s", cstate->cur_relname, - (unsigned long long) cstate->cur_lineno, + cstate->cur_lineno, cstate->cur_attname); else - errcontext("COPY %s, line %llu", + errcontext("COPY %s, line %" PRIu64, cstate->cur_relname, - (unsigned long long) cstate->cur_lineno); + cstate->cur_lineno); } else { @@ -140,9 +282,9 @@ CopyFromErrorCallback(void *arg) char *attval; attval = CopyLimitPrintoutLength(cstate->cur_attval); - errcontext("COPY %s, line %llu, column %s: \"%s\"", + errcontext("COPY %s, line %" PRIu64 ", column %s: \"%s\"", cstate->cur_relname, - (unsigned long long) cstate->cur_lineno, + cstate->cur_lineno, cstate->cur_attname, attval); pfree(attval); @@ -150,9 +292,9 @@ CopyFromErrorCallback(void *arg) else if (cstate->cur_attname) { /* error is relevant to a particular column, value is NULL */ - errcontext("COPY %s, line %llu, column %s: null input", + errcontext("COPY %s, line %" PRIu64 ", column %s: null input", cstate->cur_relname, - (unsigned long long) cstate->cur_lineno, + cstate->cur_lineno, cstate->cur_attname); } else @@ -167,16 +309,16 @@ CopyFromErrorCallback(void *arg) char *lineval; lineval = CopyLimitPrintoutLength(cstate->line_buf.data); - errcontext("COPY %s, line %llu: \"%s\"", + errcontext("COPY %s, line %" PRIu64 ": \"%s\"", cstate->cur_relname, - (unsigned long long) cstate->cur_lineno, lineval); + cstate->cur_lineno, lineval); pfree(lineval); } else { - errcontext("COPY %s, line %llu", + errcontext("COPY %s, line %" PRIu64, cstate->cur_relname, - (unsigned long long) cstate->cur_lineno); + cstate->cur_lineno); } } } @@ -550,6 +692,13 @@ CopyMultiInsertInfoFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *curr_rri, */ if (buffer->resultRelInfo == curr_rri) { + /* + * The code below would misbehave if we were trying to reduce the + * list to less than two items. + */ + StaticAssertDecl(MAX_PARTITION_BUFFERS >= 2, + "MAX_PARTITION_BUFFERS must be >= 2"); + miinfo->multiInsertBuffers = list_delete_first(miinfo->multiInsertBuffers); miinfo->multiInsertBuffers = lappend(miinfo->multiInsertBuffers, buffer); buffer = (CopyMultiInsertBuffer *) linitial(miinfo->multiInsertBuffers); @@ -587,10 +736,12 @@ CopyMultiInsertInfoNextFreeSlot(CopyMultiInsertInfo *miinfo, ResultRelInfo *rri) { CopyMultiInsertBuffer *buffer = rri->ri_CopyMultiInsertBuffer; - int nused = buffer->nused; + int nused; Assert(buffer != NULL); - Assert(nused < MAX_BUFFERED_TUPLES); + Assert(buffer->nused < MAX_BUFFERED_TUPLES); + + nused = buffer->nused; if (buffer->slots[nused] == NULL) buffer->slots[nused] = table_slot_create(rri->ri_RelationDesc, NULL); @@ -645,7 +796,6 @@ CopyFrom(CopyFromState cstate) CopyMultiInsertInfo multiInsertInfo = {0}; /* pacify compiler */ int64 processed = 0; int64 excluded = 0; - int64 skipped = 0; bool has_before_insert_row_trig; bool has_instead_insert_row_trig; bool leafpart_use_multi_insert = false; @@ -729,6 +879,12 @@ CopyFrom(CopyFromState cstate) errmsg("cannot perform COPY FREEZE on a partitioned table"))); } + /* There's currently no support for COPY FREEZE on foreign tables. */ + if (cstate->rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform COPY FREEZE on a foreign table"))); + /* * Tolerate one registration for the benefit of FirstXactSnapshot. * Scan-bearing queries generally create at least two registrations, @@ -757,7 +913,8 @@ CopyFrom(CopyFromState cstate) * index-entry-making machinery. (There used to be a huge amount of code * here that basically duplicated execUtils.c ...) */ - ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos); + ExecInitRangeTable(estate, cstate->range_table, cstate->rteperminfos, + bms_make_singleton(1)); resultRelInfo = target_resultRelInfo = makeNode(ResultRelInfo); ExecInitResultRelation(estate, resultRelInfo, 1); @@ -948,7 +1105,7 @@ CopyFrom(CopyFromState cstate) /* Set up callback to identify error line number */ errcallback.callback = CopyFromErrorCallback; - errcallback.arg = (void *) cstate; + errcallback.arg = cstate; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -992,26 +1149,29 @@ CopyFrom(CopyFromState cstate) if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull)) break; - if (cstate->opts.on_error != COPY_ON_ERROR_STOP && + if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE && cstate->escontext->error_occurred) { /* - * Soft error occurred, skip this tuple and deal with error - * information according to ON_ERROR. + * Soft error occurred, skip this tuple and just make + * ErrorSaveContext ready for the next NextCopyFrom. Since we + * don't set details_wanted and error_data is not to be filled, + * just resetting error_occurred is enough. */ - if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE) - - /* - * Just make ErrorSaveContext ready for the next NextCopyFrom. - * Since we don't set details_wanted and error_data is not to - * be filled, just resetting error_occurred is enough. - */ - cstate->escontext->error_occurred = false; + cstate->escontext->error_occurred = false; /* Report that this tuple was skipped by the ON_ERROR clause */ pgstat_progress_update_param(PROGRESS_COPY_TUPLES_SKIPPED, - ++skipped); + cstate->num_errors); + if (cstate->opts.reject_limit > 0 && + cstate->num_errors > cstate->opts.reject_limit) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("skipped more than REJECT_LIMIT (%" PRId64 ") rows due to data type incompatibility", + cstate->opts.reject_limit))); + + /* Repeat NextCopyFrom() until no soft error occurs */ continue; } @@ -1308,12 +1468,13 @@ CopyFrom(CopyFromState cstate) error_context_stack = errcallback.previous; if (cstate->opts.on_error != COPY_ON_ERROR_STOP && - cstate->num_errors > 0) + cstate->num_errors > 0 && + cstate->opts.log_verbosity >= COPY_LOG_VERBOSITY_DEFAULT) ereport(NOTICE, - errmsg_plural("%llu row was skipped due to data type incompatibility", - "%llu rows were skipped due to data type incompatibility", - (unsigned long long) cstate->num_errors, - (unsigned long long) cstate->num_errors)); + errmsg_plural("%" PRIu64 " row was skipped due to data type incompatibility", + "%" PRIu64 " rows were skipped due to data type incompatibility", + cstate->num_errors, + cstate->num_errors)); if (bistate != NULL) FreeBulkInsertState(bistate); @@ -1381,7 +1542,6 @@ BeginCopyFrom(ParseState *pstate, num_defaults; FmgrInfo *in_functions; Oid *typioparams; - Oid in_func_oid; int *defmap; ExprState **defexprs; MemoryContext oldcontext; @@ -1413,6 +1573,9 @@ BeginCopyFrom(ParseState *pstate, /* Extract options from the statement node tree */ ProcessCopyOptions(pstate, &cstate->opts, true /* is_from */ , options); + /* Set the format routine */ + cstate->routine = CopyFromGetRoutine(&cstate->opts); + /* Process the target relation */ cstate->rel = rel; @@ -1444,8 +1607,9 @@ BeginCopyFrom(ParseState *pstate, if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY", - NameStr(attr->attname)))); + /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */ + errmsg("%s column \"%s\" not referenced by COPY", + "FORCE_NOT_NULL", NameStr(attr->attname)))); cstate->opts.force_notnull_flags[attnum - 1] = true; } } @@ -1486,8 +1650,9 @@ BeginCopyFrom(ParseState *pstate, if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE_NULL column \"%s\" not referenced by COPY", - NameStr(attr->attname)))); + /*- translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL */ + errmsg("%s column \"%s\" not referenced by COPY", + "FORCE_NULL", NameStr(attr->attname)))); cstate->opts.force_null_flags[attnum - 1] = true; } } @@ -1566,25 +1731,6 @@ BeginCopyFrom(ParseState *pstate, cstate->raw_buf_index = cstate->raw_buf_len = 0; cstate->raw_reached_eof = false; - if (!cstate->opts.binary) - { - /* - * If encoding conversion is needed, we need another buffer to hold - * the converted input data. Otherwise, we can just point input_buf - * to the same buffer as raw_buf. - */ - if (cstate->need_transcoding) - { - cstate->input_buf = (char *) palloc(INPUT_BUF_SIZE + 1); - cstate->input_buf_index = cstate->input_buf_len = 0; - } - else - cstate->input_buf = cstate->raw_buf; - cstate->input_reached_eof = false; - - initStringInfo(&cstate->line_buf); - } - initStringInfo(&cstate->attribute_buf); /* Assign range table and rteperminfos, we'll need them in CopyFrom. */ @@ -1617,13 +1763,9 @@ BeginCopyFrom(ParseState *pstate, continue; /* Fetch the input function and typioparam info */ - if (cstate->opts.binary) - getTypeBinaryInputInfo(att->atttypid, - &in_func_oid, &typioparams[attnum - 1]); - else - getTypeInputInfo(att->atttypid, - &in_func_oid, &typioparams[attnum - 1]); - fmgr_info(in_func_oid, &in_functions[attnum - 1]); + cstate->routine->CopyFromInFunc(cstate, att->atttypid, + &in_functions[attnum - 1], + &typioparams[attnum - 1]); /* Get default info if available */ defexprs[attnum - 1] = NULL; @@ -1758,20 +1900,7 @@ BeginCopyFrom(ParseState *pstate, pgstat_progress_update_multi_param(3, progress_cols, progress_vals); - if (cstate->opts.binary) - { - /* Read and verify binary header */ - ReceiveCopyBinaryHeader(cstate); - } - - /* create workspace for CopyReadAttributes results */ - if (!cstate->opts.binary) - { - AttrNumber attr_count = list_length(cstate->attnumlist); - - cstate->max_fields = attr_count; - cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *)); - } + cstate->routine->CopyFromStart(cstate, tupDesc); MemoryContextSwitchTo(oldcontext); @@ -1784,6 +1913,9 @@ BeginCopyFrom(ParseState *pstate, void EndCopyFrom(CopyFromState cstate) { + /* Invoke the end callback */ + cstate->routine->CopyFromEnd(cstate); + /* No COPY FROM related resources except memory. */ if (cstate->is_program) { diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c index 7efcb891598f0..f5fc346e2013b 100644 --- a/src/backend/commands/copyfromparse.c +++ b/src/backend/commands/copyfromparse.c @@ -47,7 +47,7 @@ * and 'attribute_buf' are expanded on demand, to hold the longest line * encountered so far. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -62,7 +62,7 @@ #include #include -#include "commands/copy.h" +#include "commands/copyapi.h" #include "commands/copyfrom_internal.h" #include "commands/progress.h" #include "executor/executor.h" @@ -70,7 +70,6 @@ #include "libpq/pqformat.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "nodes/miscnodes.h" #include "pgstat.h" #include "port/pg_bswap.h" #include "utils/builtins.h" @@ -136,26 +135,27 @@ if (1) \ } \ } else ((void) 0) -/* Undo any read-ahead and jump out of the block. */ -#define NO_END_OF_COPY_GOTO \ -if (1) \ -{ \ - input_buf_ptr = prev_raw_ptr + 1; \ - goto not_end_of_copy; \ -} else ((void) 0) - /* NOTE: there's a copy of this in copyto.c */ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0"; /* non-export function prototypes */ -static bool CopyReadLine(CopyFromState cstate); -static bool CopyReadLineText(CopyFromState cstate); +static bool CopyReadLine(CopyFromState cstate, bool is_csv); +static bool CopyReadLineText(CopyFromState cstate, bool is_csv); static int CopyReadAttributesText(CopyFromState cstate); static int CopyReadAttributesCSV(CopyFromState cstate); static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull); +static pg_attribute_always_inline bool CopyFromTextLikeOneRow(CopyFromState cstate, + ExprContext *econtext, + Datum *values, + bool *nulls, + bool is_csv); +static pg_attribute_always_inline bool NextCopyFromRawFieldsInternal(CopyFromState cstate, + char ***fields, + int *nfields, + bool is_csv); /* Low-level communications functions */ @@ -740,8 +740,21 @@ CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes) } /* - * Read raw fields in the next line for COPY FROM in text or csv mode. - * Return false if no more lines. + * This function is exposed for use by extensions that read raw fields in the + * next line. See NextCopyFromRawFieldsInternal() for details. + */ +bool +NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) +{ + return NextCopyFromRawFieldsInternal(cstate, fields, nfields, + cstate->opts.csv_mode); +} + +/* + * Workhorse for NextCopyFromRawFields(). + * + * Read raw fields in the next line for COPY FROM in text or csv mode. Return + * false if no more lines. * * An internal temporary buffer is returned via 'fields'. It is valid until * the next call of the function. Since the function returns all raw fields @@ -749,9 +762,13 @@ CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes) * in the relation. * * NOTE: force_not_null option are not applied to the returned fields. + * + * We use pg_attribute_always_inline to reduce function call overhead + * and to help compilers to optimize away the 'is_csv' condition when called + * by internal functions such as CopyFromTextLikeOneRow(). */ -bool -NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) +static pg_attribute_always_inline bool +NextCopyFromRawFieldsInternal(CopyFromState cstate, char ***fields, int *nfields, bool is_csv) { int fldct; bool done; @@ -768,13 +785,13 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) tupDesc = RelationGetDescr(cstate->rel); cstate->cur_lineno++; - done = CopyReadLine(cstate); + done = CopyReadLine(cstate, is_csv); if (cstate->opts.header_line == COPY_HEADER_MATCH) { int fldnum; - if (cstate->opts.csv_mode) + if (is_csv) fldct = CopyReadAttributesCSV(cstate); else fldct = CopyReadAttributesText(cstate); @@ -818,7 +835,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) cstate->cur_lineno++; /* Actually read the line into memory here */ - done = CopyReadLine(cstate); + done = CopyReadLine(cstate, is_csv); /* * EOF at start of line means we're done. If we see EOF after some @@ -829,7 +846,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) return false; /* Parse the line into de-escaped field values */ - if (cstate->opts.csv_mode) + if (is_csv) fldct = CopyReadAttributesCSV(cstate); else fldct = CopyReadAttributesText(cstate); @@ -856,233 +873,275 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext, { TupleDesc tupDesc; AttrNumber num_phys_attrs, - attr_count, num_defaults = cstate->num_defaults; - FmgrInfo *in_functions = cstate->in_functions; - Oid *typioparams = cstate->typioparams; int i; int *defmap = cstate->defmap; ExprState **defexprs = cstate->defexprs; tupDesc = RelationGetDescr(cstate->rel); num_phys_attrs = tupDesc->natts; - attr_count = list_length(cstate->attnumlist); /* Initialize all values for row to NULL */ MemSet(values, 0, num_phys_attrs * sizeof(Datum)); MemSet(nulls, true, num_phys_attrs * sizeof(bool)); MemSet(cstate->defaults, false, num_phys_attrs * sizeof(bool)); - if (!cstate->opts.binary) + /* Get one row from source */ + if (!cstate->routine->CopyFromOneRow(cstate, econtext, values, nulls)) + return false; + + /* + * Now compute and insert any defaults available for the columns not + * provided by the input data. Anything not processed here or above will + * remain NULL. + */ + for (i = 0; i < num_defaults; i++) { - char **field_strings; - ListCell *cur; - int fldct; - int fieldno; - char *string; + /* + * The caller must supply econtext and have switched into the + * per-tuple memory context in it. + */ + Assert(econtext != NULL); + Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory); - /* read raw fields in the next line */ - if (!NextCopyFromRawFields(cstate, &field_strings, &fldct)) - return false; + values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext, + &nulls[defmap[i]]); + } + + return true; +} + +/* Implementation of the per-row callback for text format */ +bool +CopyFromTextOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, + bool *nulls) +{ + return CopyFromTextLikeOneRow(cstate, econtext, values, nulls, false); +} + +/* Implementation of the per-row callback for CSV format */ +bool +CopyFromCSVOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, + bool *nulls) +{ + return CopyFromTextLikeOneRow(cstate, econtext, values, nulls, true); +} + +/* + * Workhorse for CopyFromTextOneRow() and CopyFromCSVOneRow(). + * + * We use pg_attribute_always_inline to reduce function call overhead + * and to help compilers to optimize away the 'is_csv' condition. + */ +static pg_attribute_always_inline bool +CopyFromTextLikeOneRow(CopyFromState cstate, ExprContext *econtext, + Datum *values, bool *nulls, bool is_csv) +{ + TupleDesc tupDesc; + AttrNumber attr_count; + FmgrInfo *in_functions = cstate->in_functions; + Oid *typioparams = cstate->typioparams; + ExprState **defexprs = cstate->defexprs; + char **field_strings; + ListCell *cur; + int fldct; + int fieldno; + char *string; + + tupDesc = RelationGetDescr(cstate->rel); + attr_count = list_length(cstate->attnumlist); - /* check for overflowing fields */ - if (attr_count > 0 && fldct > attr_count) + /* read raw fields in the next line */ + if (!NextCopyFromRawFieldsInternal(cstate, &field_strings, &fldct, is_csv)) + return false; + + /* check for overflowing fields */ + if (attr_count > 0 && fldct > attr_count) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("extra data after last expected column"))); + + fieldno = 0; + + /* Loop to read the user attributes on the line. */ + foreach(cur, cstate->attnumlist) + { + int attnum = lfirst_int(cur); + int m = attnum - 1; + Form_pg_attribute att = TupleDescAttr(tupDesc, m); + + if (fieldno >= fldct) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("extra data after last expected column"))); + errmsg("missing data for column \"%s\"", + NameStr(att->attname)))); + string = field_strings[fieldno++]; - fieldno = 0; - - /* Loop to read the user attributes on the line. */ - foreach(cur, cstate->attnumlist) + if (cstate->convert_select_flags && + !cstate->convert_select_flags[m]) { - int attnum = lfirst_int(cur); - int m = attnum - 1; - Form_pg_attribute att = TupleDescAttr(tupDesc, m); - - if (fieldno >= fldct) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("missing data for column \"%s\"", - NameStr(att->attname)))); - string = field_strings[fieldno++]; + /* ignore input field, leaving column as NULL */ + continue; + } - if (cstate->convert_select_flags && - !cstate->convert_select_flags[m]) + if (is_csv) + { + if (string == NULL && + cstate->opts.force_notnull_flags[m]) { - /* ignore input field, leaving column as NULL */ - continue; + /* + * FORCE_NOT_NULL option is set and column is NULL - convert + * it to the NULL string. + */ + string = cstate->opts.null_print; } - - if (cstate->opts.csv_mode) + else if (string != NULL && cstate->opts.force_null_flags[m] + && strcmp(string, cstate->opts.null_print) == 0) { - if (string == NULL && - cstate->opts.force_notnull_flags[m]) - { - /* - * FORCE_NOT_NULL option is set and column is NULL - - * convert it to the NULL string. - */ - string = cstate->opts.null_print; - } - else if (string != NULL && cstate->opts.force_null_flags[m] - && strcmp(string, cstate->opts.null_print) == 0) - { - /* - * FORCE_NULL option is set and column matches the NULL - * string. It must have been quoted, or otherwise the - * string would already have been set to NULL. Convert it - * to NULL as specified. - */ - string = NULL; - } + /* + * FORCE_NULL option is set and column matches the NULL + * string. It must have been quoted, or otherwise the string + * would already have been set to NULL. Convert it to NULL as + * specified. + */ + string = NULL; } + } - cstate->cur_attname = NameStr(att->attname); - cstate->cur_attval = string; + cstate->cur_attname = NameStr(att->attname); + cstate->cur_attval = string; - if (string != NULL) - nulls[m] = false; + if (string != NULL) + nulls[m] = false; - if (cstate->defaults[m]) - { - /* - * The caller must supply econtext and have switched into the - * per-tuple memory context in it. - */ - Assert(econtext != NULL); - Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory); + if (cstate->defaults[m]) + { + /* We must have switched into the per-tuple memory context */ + Assert(econtext != NULL); + Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory); - values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]); - } + values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]); + } - /* - * If ON_ERROR is specified with IGNORE, skip rows with soft - * errors - */ - else if (!InputFunctionCallSafe(&in_functions[m], - string, - typioparams[m], - att->atttypmod, - (Node *) cstate->escontext, - &values[m])) - { - Assert(cstate->opts.on_error != COPY_ON_ERROR_STOP); + /* + * If ON_ERROR is specified with IGNORE, skip rows with soft errors + */ + else if (!InputFunctionCallSafe(&in_functions[m], + string, + typioparams[m], + att->atttypmod, + (Node *) cstate->escontext, + &values[m])) + { + Assert(cstate->opts.on_error != COPY_ON_ERROR_STOP); - cstate->num_errors++; + cstate->num_errors++; - if (cstate->opts.log_verbosity == COPY_LOG_VERBOSITY_VERBOSE) - { - /* - * Since we emit line number and column info in the below - * notice message, we suppress error context information - * other than the relation name. - */ - Assert(!cstate->relname_only); - cstate->relname_only = true; + if (cstate->opts.log_verbosity == COPY_LOG_VERBOSITY_VERBOSE) + { + /* + * Since we emit line number and column info in the below + * notice message, we suppress error context information other + * than the relation name. + */ + Assert(!cstate->relname_only); + cstate->relname_only = true; - if (cstate->cur_attval) - { - char *attval; - - attval = CopyLimitPrintoutLength(cstate->cur_attval); - ereport(NOTICE, - errmsg("skipping row due to data type incompatibility at line %llu for column %s: \"%s\"", - (unsigned long long) cstate->cur_lineno, - cstate->cur_attname, - attval)); - pfree(attval); - } - else - ereport(NOTICE, - errmsg("skipping row due to data type incompatibility at line %llu for column %s: null input", - (unsigned long long) cstate->cur_lineno, - cstate->cur_attname)); - - /* reset relname_only */ - cstate->relname_only = false; + if (cstate->cur_attval) + { + char *attval; + + attval = CopyLimitPrintoutLength(cstate->cur_attval); + ereport(NOTICE, + errmsg("skipping row due to data type incompatibility at line %" PRIu64 " for column \"%s\": \"%s\"", + cstate->cur_lineno, + cstate->cur_attname, + attval)); + pfree(attval); } + else + ereport(NOTICE, + errmsg("skipping row due to data type incompatibility at line %" PRIu64 " for column \"%s\": null input", + cstate->cur_lineno, + cstate->cur_attname)); - return true; + /* reset relname_only */ + cstate->relname_only = false; } - cstate->cur_attname = NULL; - cstate->cur_attval = NULL; + return true; } - Assert(fieldno == attr_count); + cstate->cur_attname = NULL; + cstate->cur_attval = NULL; } - else - { - /* binary */ - int16 fld_count; - ListCell *cur; - cstate->cur_lineno++; + Assert(fieldno == attr_count); - if (!CopyGetInt16(cstate, &fld_count)) - { - /* EOF detected (end of file, or protocol-level EOF) */ - return false; - } + return true; +} - if (fld_count == -1) - { - /* - * Received EOF marker. Wait for the protocol-level EOF, and - * complain if it doesn't come immediately. In COPY FROM STDIN, - * this ensures that we correctly handle CopyFail, if client - * chooses to send that now. When copying from file, we could - * ignore the rest of the file like in text mode, but we choose to - * be consistent with the COPY FROM STDIN case. - */ - char dummy; +/* Implementation of the per-row callback for binary format */ +bool +CopyFromBinaryOneRow(CopyFromState cstate, ExprContext *econtext, Datum *values, + bool *nulls) +{ + TupleDesc tupDesc; + AttrNumber attr_count; + FmgrInfo *in_functions = cstate->in_functions; + Oid *typioparams = cstate->typioparams; + int16 fld_count; + ListCell *cur; - if (CopyReadBinaryData(cstate, &dummy, 1) > 0) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("received copy data after EOF marker"))); - return false; - } + tupDesc = RelationGetDescr(cstate->rel); + attr_count = list_length(cstate->attnumlist); - if (fld_count != attr_count) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("row field count is %d, expected %d", - (int) fld_count, attr_count))); + cstate->cur_lineno++; - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); - int m = attnum - 1; - Form_pg_attribute att = TupleDescAttr(tupDesc, m); - - cstate->cur_attname = NameStr(att->attname); - values[m] = CopyReadBinaryAttribute(cstate, - &in_functions[m], - typioparams[m], - att->atttypmod, - &nulls[m]); - cstate->cur_attname = NULL; - } + if (!CopyGetInt16(cstate, &fld_count)) + { + /* EOF detected (end of file, or protocol-level EOF) */ + return false; } - /* - * Now compute and insert any defaults available for the columns not - * provided by the input data. Anything not processed here or above will - * remain NULL. - */ - for (i = 0; i < num_defaults; i++) + if (fld_count == -1) { /* - * The caller must supply econtext and have switched into the - * per-tuple memory context in it. + * Received EOF marker. Wait for the protocol-level EOF, and complain + * if it doesn't come immediately. In COPY FROM STDIN, this ensures + * that we correctly handle CopyFail, if client chooses to send that + * now. When copying from file, we could ignore the rest of the file + * like in text mode, but we choose to be consistent with the COPY + * FROM STDIN case. */ - Assert(econtext != NULL); - Assert(CurrentMemoryContext == econtext->ecxt_per_tuple_memory); + char dummy; - values[defmap[i]] = ExecEvalExpr(defexprs[defmap[i]], econtext, - &nulls[defmap[i]]); + if (CopyReadBinaryData(cstate, &dummy, 1) > 0) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("received copy data after EOF marker"))); + return false; + } + + if (fld_count != attr_count) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("row field count is %d, expected %d", + (int) fld_count, attr_count))); + + foreach(cur, cstate->attnumlist) + { + int attnum = lfirst_int(cur); + int m = attnum - 1; + Form_pg_attribute att = TupleDescAttr(tupDesc, m); + + cstate->cur_attname = NameStr(att->attname); + values[m] = CopyReadBinaryAttribute(cstate, + &in_functions[m], + typioparams[m], + att->atttypmod, + &nulls[m]); + cstate->cur_attname = NULL; } return true; @@ -1096,7 +1155,7 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext, * in the final value of line_buf. */ static bool -CopyReadLine(CopyFromState cstate) +CopyReadLine(CopyFromState cstate, bool is_csv) { bool result; @@ -1104,7 +1163,7 @@ CopyReadLine(CopyFromState cstate) cstate->line_buf_valid = false; /* Parse data and transfer into line_buf */ - result = CopyReadLineText(cstate); + result = CopyReadLineText(cstate, is_csv); if (result) { @@ -1172,7 +1231,7 @@ CopyReadLine(CopyFromState cstate) * CopyReadLineText - inner loop of CopyReadLine for text mode */ static bool -CopyReadLineText(CopyFromState cstate) +CopyReadLineText(CopyFromState cstate, bool is_csv) { char *copy_input_buf; int input_buf_ptr; @@ -1182,13 +1241,12 @@ CopyReadLineText(CopyFromState cstate) bool result = false; /* CSV variables */ - bool first_char_in_line = true; bool in_quote = false, last_was_esc = false; char quotec = '\0'; char escapec = '\0'; - if (cstate->opts.csv_mode) + if (is_csv) { quotec = cstate->opts.quote[0]; escapec = cstate->opts.escape[0]; @@ -1265,15 +1323,15 @@ CopyReadLineText(CopyFromState cstate) prev_raw_ptr = input_buf_ptr; c = copy_input_buf[input_buf_ptr++]; - if (cstate->opts.csv_mode) + if (is_csv) { /* - * If character is '\\' or '\r', we may need to look ahead below. - * Force fetch of the next character if we don't already have it. - * We need to do this before changing CSV state, in case one of - * these characters is also the quote or escape character. + * If character is '\r', we may need to look ahead below. Force + * fetch of the next character if we don't already have it. We + * need to do this before changing CSV state, in case '\r' is also + * the quote or escape character. */ - if (c == '\\' || c == '\r') + if (c == '\r') { IF_NEED_REFILL_AND_NOT_EOF_CONTINUE(0); } @@ -1304,7 +1362,7 @@ CopyReadLineText(CopyFromState cstate) } /* Process \r */ - if (c == '\r' && (!cstate->opts.csv_mode || !in_quote)) + if (c == '\r' && (!is_csv || !in_quote)) { /* Check for \r\n on first line, _and_ handle \r\n. */ if (cstate->eol_type == EOL_UNKNOWN || @@ -1332,10 +1390,10 @@ CopyReadLineText(CopyFromState cstate) if (cstate->eol_type == EOL_CRNL) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - !cstate->opts.csv_mode ? + !is_csv ? errmsg("literal carriage return found in data") : errmsg("unquoted carriage return found in data"), - !cstate->opts.csv_mode ? + !is_csv ? errhint("Use \"\\r\" to represent carriage return.") : errhint("Use quoted CSV field to represent carriage return."))); @@ -1349,10 +1407,10 @@ CopyReadLineText(CopyFromState cstate) else if (cstate->eol_type == EOL_NL) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - !cstate->opts.csv_mode ? + !is_csv ? errmsg("literal carriage return found in data") : errmsg("unquoted carriage return found in data"), - !cstate->opts.csv_mode ? + !is_csv ? errhint("Use \"\\r\" to represent carriage return.") : errhint("Use quoted CSV field to represent carriage return."))); /* If reach here, we have found the line terminator */ @@ -1360,15 +1418,15 @@ CopyReadLineText(CopyFromState cstate) } /* Process \n */ - if (c == '\n' && (!cstate->opts.csv_mode || !in_quote)) + if (c == '\n' && (!is_csv || !in_quote)) { if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - !cstate->opts.csv_mode ? + !is_csv ? errmsg("literal newline found in data") : errmsg("unquoted newline found in data"), - !cstate->opts.csv_mode ? + !is_csv ? errhint("Use \"\\n\" to represent newline.") : errhint("Use quoted CSV field to represent newline."))); cstate->eol_type = EOL_NL; /* in case not set yet */ @@ -1377,10 +1435,10 @@ CopyReadLineText(CopyFromState cstate) } /* - * In CSV mode, we only recognize \. alone on a line. This is because - * \. is a valid CSV data value. + * Process backslash, except in CSV mode where backslash is a normal + * character. */ - if (c == '\\' && (!cstate->opts.csv_mode || first_char_in_line)) + if (c == '\\' && !is_csv) { char c2; @@ -1398,12 +1456,6 @@ CopyReadLineText(CopyFromState cstate) if (c2 == '.') { input_buf_ptr++; /* consume the '.' */ - - /* - * Note: if we loop back for more data here, it does not - * matter that the CSV state change checks are re-executed; we - * will come back here with no important state changed. - */ if (cstate->eol_type == EOL_CRNL) { /* Get the next character */ @@ -1412,23 +1464,13 @@ CopyReadLineText(CopyFromState cstate) c2 = copy_input_buf[input_buf_ptr++]; if (c2 == '\n') - { - if (!cstate->opts.csv_mode) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("end-of-copy marker does not match previous newline style"))); - else - NO_END_OF_COPY_GOTO; - } + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("end-of-copy marker does not match previous newline style"))); else if (c2 != '\r') - { - if (!cstate->opts.csv_mode) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("end-of-copy marker corrupt"))); - else - NO_END_OF_COPY_GOTO; - } + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("end-of-copy marker is not alone on its line"))); } /* Get the next character */ @@ -1437,37 +1479,34 @@ CopyReadLineText(CopyFromState cstate) c2 = copy_input_buf[input_buf_ptr++]; if (c2 != '\r' && c2 != '\n') - { - if (!cstate->opts.csv_mode) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("end-of-copy marker corrupt"))); - else - NO_END_OF_COPY_GOTO; - } + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("end-of-copy marker is not alone on its line"))); if ((cstate->eol_type == EOL_NL && c2 != '\n') || (cstate->eol_type == EOL_CRNL && c2 != '\n') || (cstate->eol_type == EOL_CR && c2 != '\r')) - { ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("end-of-copy marker does not match previous newline style"))); - } /* - * Transfer only the data before the \. into line_buf, then - * discard the data and the \. sequence. + * If there is any data on this line before the \., complain. + */ + if (cstate->line_buf.len > 0 || + prev_raw_ptr > cstate->input_buf_index) + ereport(ERROR, + (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + errmsg("end-of-copy marker is not alone on its line"))); + + /* + * Discard the \. and newline, then report EOF. */ - if (prev_raw_ptr > cstate->input_buf_index) - appendBinaryStringInfo(&cstate->line_buf, - cstate->input_buf + cstate->input_buf_index, - prev_raw_ptr - cstate->input_buf_index); cstate->input_buf_index = input_buf_ptr; result = true; /* report EOF */ break; } - else if (!cstate->opts.csv_mode) + else { /* * If we are here, it means we found a backslash followed by @@ -1475,23 +1514,11 @@ CopyReadLineText(CopyFromState cstate) * after a backslash is special, so we skip over that second * character too. If we didn't do that \\. would be * considered an eof-of copy, while in non-CSV mode it is a - * literal backslash followed by a period. In CSV mode, - * backslashes are not special, so we want to process the - * character after the backslash just like a normal character, - * so we don't increment in those cases. + * literal backslash followed by a period. */ input_buf_ptr++; } } - - /* - * This label is for CSV cases where \. appears at the start of a - * line, but there is more text after it, meaning it was a data value. - * We are more strict for \. in CSV mode because \. could be a data - * value, while in non-CSV mode, \. cannot be a data value. - */ -not_end_of_copy: - first_char_in_line = false; } /* end of outer loop */ /* diff --git a/src/backend/commands/copyto.c b/src/backend/commands/copyto.c index ae8b2e36d72db..ea6f18f2c8008 100644 --- a/src/backend/commands/copyto.c +++ b/src/backend/commands/copyto.c @@ -3,7 +3,7 @@ * copyto.c * COPY TO file/program/client * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,7 +19,7 @@ #include #include "access/tableam.h" -#include "commands/copy.h" +#include "commands/copyapi.h" #include "commands/progress.h" #include "executor/execdesc.h" #include "executor/executor.h" @@ -64,6 +64,9 @@ typedef enum CopyDest */ typedef struct CopyToStateData { + /* format-specific routines */ + const CopyToRoutine *routine; + /* low-level state data */ CopyDest copy_dest; /* type of copy source/destination */ FILE *copy_file; /* used if copy_dest == COPY_FILE */ @@ -114,6 +117,19 @@ static void CopyAttributeOutText(CopyToState cstate, const char *string); static void CopyAttributeOutCSV(CopyToState cstate, const char *string, bool use_quote); +/* built-in format-specific routines */ +static void CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc); +static void CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo); +static void CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot); +static void CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot); +static void CopyToTextLikeOneRow(CopyToState cstate, TupleTableSlot *slot, + bool is_csv); +static void CopyToTextLikeEnd(CopyToState cstate); +static void CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc); +static void CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo); +static void CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot); +static void CopyToBinaryEnd(CopyToState cstate); + /* Low-level communications functions */ static void SendCopyBegin(CopyToState cstate); static void SendCopyEnd(CopyToState cstate); @@ -121,9 +137,251 @@ static void CopySendData(CopyToState cstate, const void *databuf, int datasize); static void CopySendString(CopyToState cstate, const char *str); static void CopySendChar(CopyToState cstate, char c); static void CopySendEndOfRow(CopyToState cstate); +static void CopySendTextLikeEndOfRow(CopyToState cstate); static void CopySendInt32(CopyToState cstate, int32 val); static void CopySendInt16(CopyToState cstate, int16 val); +/* + * COPY TO routines for built-in formats. + * + * CSV and text formats share the same TextLike routines except for the + * one-row callback. + */ + +/* text format */ +static const CopyToRoutine CopyToRoutineText = { + .CopyToStart = CopyToTextLikeStart, + .CopyToOutFunc = CopyToTextLikeOutFunc, + .CopyToOneRow = CopyToTextOneRow, + .CopyToEnd = CopyToTextLikeEnd, +}; + +/* CSV format */ +static const CopyToRoutine CopyToRoutineCSV = { + .CopyToStart = CopyToTextLikeStart, + .CopyToOutFunc = CopyToTextLikeOutFunc, + .CopyToOneRow = CopyToCSVOneRow, + .CopyToEnd = CopyToTextLikeEnd, +}; + +/* binary format */ +static const CopyToRoutine CopyToRoutineBinary = { + .CopyToStart = CopyToBinaryStart, + .CopyToOutFunc = CopyToBinaryOutFunc, + .CopyToOneRow = CopyToBinaryOneRow, + .CopyToEnd = CopyToBinaryEnd, +}; + +/* Return a COPY TO routine for the given options */ +static const CopyToRoutine * +CopyToGetRoutine(const CopyFormatOptions *opts) +{ + if (opts->csv_mode) + return &CopyToRoutineCSV; + else if (opts->binary) + return &CopyToRoutineBinary; + + /* default is text */ + return &CopyToRoutineText; +} + +/* Implementation of the start callback for text and CSV formats */ +static void +CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc) +{ + /* + * For non-binary copy, we need to convert null_print to file encoding, + * because it will be sent directly with CopySendString. + */ + if (cstate->need_transcoding) + cstate->opts.null_print_client = pg_server_to_any(cstate->opts.null_print, + cstate->opts.null_print_len, + cstate->file_encoding); + + /* if a header has been requested send the line */ + if (cstate->opts.header_line) + { + ListCell *cur; + bool hdr_delim = false; + + foreach(cur, cstate->attnumlist) + { + int attnum = lfirst_int(cur); + char *colname; + + if (hdr_delim) + CopySendChar(cstate, cstate->opts.delim[0]); + hdr_delim = true; + + colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname); + + if (cstate->opts.csv_mode) + CopyAttributeOutCSV(cstate, colname, false); + else + CopyAttributeOutText(cstate, colname); + } + + CopySendTextLikeEndOfRow(cstate); + } +} + +/* + * Implementation of the outfunc callback for text and CSV formats. Assign + * the output function data to the given *finfo. + */ +static void +CopyToTextLikeOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo) +{ + Oid func_oid; + bool is_varlena; + + /* Set output function for an attribute */ + getTypeOutputInfo(atttypid, &func_oid, &is_varlena); + fmgr_info(func_oid, finfo); +} + +/* Implementation of the per-row callback for text format */ +static void +CopyToTextOneRow(CopyToState cstate, TupleTableSlot *slot) +{ + CopyToTextLikeOneRow(cstate, slot, false); +} + +/* Implementation of the per-row callback for CSV format */ +static void +CopyToCSVOneRow(CopyToState cstate, TupleTableSlot *slot) +{ + CopyToTextLikeOneRow(cstate, slot, true); +} + +/* + * Workhorse for CopyToTextOneRow() and CopyToCSVOneRow(). + * + * We use pg_attribute_always_inline to reduce function call overhead + * and to help compilers to optimize away the 'is_csv' condition. + */ +static pg_attribute_always_inline void +CopyToTextLikeOneRow(CopyToState cstate, + TupleTableSlot *slot, + bool is_csv) +{ + bool need_delim = false; + FmgrInfo *out_functions = cstate->out_functions; + + foreach_int(attnum, cstate->attnumlist) + { + Datum value = slot->tts_values[attnum - 1]; + bool isnull = slot->tts_isnull[attnum - 1]; + + if (need_delim) + CopySendChar(cstate, cstate->opts.delim[0]); + need_delim = true; + + if (isnull) + { + CopySendString(cstate, cstate->opts.null_print_client); + } + else + { + char *string; + + string = OutputFunctionCall(&out_functions[attnum - 1], + value); + + if (is_csv) + CopyAttributeOutCSV(cstate, string, + cstate->opts.force_quote_flags[attnum - 1]); + else + CopyAttributeOutText(cstate, string); + } + } + + CopySendTextLikeEndOfRow(cstate); +} + +/* Implementation of the end callback for text and CSV formats */ +static void +CopyToTextLikeEnd(CopyToState cstate) +{ + /* Nothing to do here */ +} + +/* + * Implementation of the start callback for binary format. Send a header + * for a binary copy. + */ +static void +CopyToBinaryStart(CopyToState cstate, TupleDesc tupDesc) +{ + int32 tmp; + + /* Signature */ + CopySendData(cstate, BinarySignature, 11); + /* Flags field */ + tmp = 0; + CopySendInt32(cstate, tmp); + /* No header extension */ + tmp = 0; + CopySendInt32(cstate, tmp); +} + +/* + * Implementation of the outfunc callback for binary format. Assign + * the binary output function to the given *finfo. + */ +static void +CopyToBinaryOutFunc(CopyToState cstate, Oid atttypid, FmgrInfo *finfo) +{ + Oid func_oid; + bool is_varlena; + + /* Set output function for an attribute */ + getTypeBinaryOutputInfo(atttypid, &func_oid, &is_varlena); + fmgr_info(func_oid, finfo); +} + +/* Implementation of the per-row callback for binary format */ +static void +CopyToBinaryOneRow(CopyToState cstate, TupleTableSlot *slot) +{ + FmgrInfo *out_functions = cstate->out_functions; + + /* Binary per-tuple header */ + CopySendInt16(cstate, list_length(cstate->attnumlist)); + + foreach_int(attnum, cstate->attnumlist) + { + Datum value = slot->tts_values[attnum - 1]; + bool isnull = slot->tts_isnull[attnum - 1]; + + if (isnull) + { + CopySendInt32(cstate, -1); + } + else + { + bytea *outputbytes; + + outputbytes = SendFunctionCall(&out_functions[attnum - 1], + value); + CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ); + CopySendData(cstate, VARDATA(outputbytes), + VARSIZE(outputbytes) - VARHDRSZ); + } + } + + CopySendEndOfRow(cstate); +} + +/* Implementation of the end callback for binary format */ +static void +CopyToBinaryEnd(CopyToState cstate) +{ + /* Generate trailer for a binary copy */ + CopySendInt16(cstate, -1); + /* Need to flush out the trailer */ + CopySendEndOfRow(cstate); +} /* * Send copy start/stop messages for frontend copies. These have changed @@ -191,16 +449,6 @@ CopySendEndOfRow(CopyToState cstate) switch (cstate->copy_dest) { case COPY_FILE: - if (!cstate->opts.binary) - { - /* Default line termination depends on platform */ -#ifndef WIN32 - CopySendChar(cstate, '\n'); -#else - CopySendString(cstate, "\r\n"); -#endif - } - if (fwrite(fe_msgbuf->data, fe_msgbuf->len, 1, cstate->copy_file) != 1 || ferror(cstate->copy_file)) @@ -235,10 +483,6 @@ CopySendEndOfRow(CopyToState cstate) } break; case COPY_FRONTEND: - /* The FE/BE protocol uses \n as newline for all platforms */ - if (!cstate->opts.binary) - CopySendChar(cstate, '\n'); - /* Dump the accumulated row as one CopyData message */ (void) pq_putmessage(PqMsg_CopyData, fe_msgbuf->data, fe_msgbuf->len); break; @@ -254,6 +498,35 @@ CopySendEndOfRow(CopyToState cstate) resetStringInfo(fe_msgbuf); } +/* + * Wrapper function of CopySendEndOfRow for text and CSV formats. Sends the + * line termination and do common appropriate things for the end of row. + */ +static inline void +CopySendTextLikeEndOfRow(CopyToState cstate) +{ + switch (cstate->copy_dest) + { + case COPY_FILE: + /* Default line termination depends on platform */ +#ifndef WIN32 + CopySendChar(cstate, '\n'); +#else + CopySendString(cstate, "\r\n"); +#endif + break; + case COPY_FRONTEND: + /* The FE/BE protocol uses \n as newline for all platforms */ + CopySendChar(cstate, '\n'); + break; + default: + break; + } + + /* Now take the actions related to the end of a row */ + CopySendEndOfRow(cstate); +} + /* * These functions do apply some data conversion */ @@ -380,11 +653,14 @@ BeginCopyTo(ParseState *pstate, RelationGetRelationName(rel)), errhint("Try the COPY (SELECT ...) TO variant."))); else if (rel->rd_rel->relkind == RELKIND_MATVIEW) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot copy from materialized view \"%s\"", - RelationGetRelationName(rel)), - errhint("Try the COPY (SELECT ...) TO variant."))); + { + if (!RelationIsPopulated(rel)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot copy from unpopulated materialized view \"%s\"", + RelationGetRelationName(rel)), + errhint("Use the REFRESH MATERIALIZED VIEW command.")); + } else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -426,6 +702,9 @@ BeginCopyTo(ParseState *pstate, /* Extract options from the statement node tree */ ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options); + /* Set format routine */ + cstate->routine = CopyToGetRoutine(&cstate->opts); + /* Process the source/target relation or query */ if (rel) { @@ -475,7 +754,7 @@ BeginCopyTo(ParseState *pstate, if (q->querySource == QSRC_NON_INSTEAD_RULE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("DO ALSO rules are not supported for the COPY"))); + errmsg("DO ALSO rules are not supported for COPY"))); } ereport(ERROR, @@ -492,7 +771,11 @@ BeginCopyTo(ParseState *pstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("COPY (SELECT INTO) is not supported"))); - Assert(query->utilityStmt == NULL); + /* The only other utility command we could see is NOTIFY */ + if (query->utilityStmt != NULL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("COPY query must not be a utility command"))); /* * Similarly the grammar doesn't enforce the presence of a RETURNING @@ -593,8 +876,9 @@ BeginCopyTo(ParseState *pstate, if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE_QUOTE column \"%s\" not referenced by COPY", - NameStr(attr->attname)))); + /*- translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL */ + errmsg("%s column \"%s\" not referenced by COPY", + "FORCE_QUOTE", NameStr(attr->attname)))); cstate->opts.force_quote_flags[attnum - 1] = true; } } @@ -766,19 +1050,10 @@ DoCopyTo(CopyToState cstate) foreach(cur, cstate->attnumlist) { int attnum = lfirst_int(cur); - Oid out_func_oid; - bool isvarlena; Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); - if (cstate->opts.binary) - getTypeBinaryOutputInfo(attr->atttypid, - &out_func_oid, - &isvarlena); - else - getTypeOutputInfo(attr->atttypid, - &out_func_oid, - &isvarlena); - fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); + cstate->routine->CopyToOutFunc(cstate, attr->atttypid, + &cstate->out_functions[attnum - 1]); } /* @@ -791,56 +1066,7 @@ DoCopyTo(CopyToState cstate) "COPY TO", ALLOCSET_DEFAULT_SIZES); - if (cstate->opts.binary) - { - /* Generate header for a binary copy */ - int32 tmp; - - /* Signature */ - CopySendData(cstate, BinarySignature, 11); - /* Flags field */ - tmp = 0; - CopySendInt32(cstate, tmp); - /* No header extension */ - tmp = 0; - CopySendInt32(cstate, tmp); - } - else - { - /* - * For non-binary copy, we need to convert null_print to file - * encoding, because it will be sent directly with CopySendString. - */ - if (cstate->need_transcoding) - cstate->opts.null_print_client = pg_server_to_any(cstate->opts.null_print, - cstate->opts.null_print_len, - cstate->file_encoding); - - /* if a header has been requested send the line */ - if (cstate->opts.header_line) - { - bool hdr_delim = false; - - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); - char *colname; - - if (hdr_delim) - CopySendChar(cstate, cstate->opts.delim[0]); - hdr_delim = true; - - colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname); - - if (cstate->opts.csv_mode) - CopyAttributeOutCSV(cstate, colname, false); - else - CopyAttributeOutText(cstate, colname); - } - - CopySendEndOfRow(cstate); - } - } + cstate->routine->CopyToStart(cstate, tupDesc); if (cstate->rel) { @@ -875,17 +1101,11 @@ DoCopyTo(CopyToState cstate) else { /* run the plan --- the dest receiver will send tuples */ - ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0, true); + ExecutorRun(cstate->queryDesc, ForwardScanDirection, 0); processed = ((DR_copy *) cstate->queryDesc->dest)->processed; } - if (cstate->opts.binary) - { - /* Generate trailer for a binary copy */ - CopySendInt16(cstate, -1); - /* Need to flush out the trailer */ - CopySendEndOfRow(cstate); - } + cstate->routine->CopyToEnd(cstate); MemoryContextDelete(cstate->rowcontext); @@ -898,73 +1118,18 @@ DoCopyTo(CopyToState cstate) /* * Emit one row during DoCopyTo(). */ -static void +static inline void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot) { - bool need_delim = false; - FmgrInfo *out_functions = cstate->out_functions; MemoryContext oldcontext; - ListCell *cur; - char *string; MemoryContextReset(cstate->rowcontext); oldcontext = MemoryContextSwitchTo(cstate->rowcontext); - if (cstate->opts.binary) - { - /* Binary per-tuple header */ - CopySendInt16(cstate, list_length(cstate->attnumlist)); - } - /* Make sure the tuple is fully deconstructed */ slot_getallattrs(slot); - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); - Datum value = slot->tts_values[attnum - 1]; - bool isnull = slot->tts_isnull[attnum - 1]; - - if (!cstate->opts.binary) - { - if (need_delim) - CopySendChar(cstate, cstate->opts.delim[0]); - need_delim = true; - } - - if (isnull) - { - if (!cstate->opts.binary) - CopySendString(cstate, cstate->opts.null_print_client); - else - CopySendInt32(cstate, -1); - } - else - { - if (!cstate->opts.binary) - { - string = OutputFunctionCall(&out_functions[attnum - 1], - value); - if (cstate->opts.csv_mode) - CopyAttributeOutCSV(cstate, string, - cstate->opts.force_quote_flags[attnum - 1]); - else - CopyAttributeOutText(cstate, string); - } - else - { - bytea *outputbytes; - - outputbytes = SendFunctionCall(&out_functions[attnum - 1], - value); - CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ); - CopySendData(cstate, VARDATA(outputbytes), - VARSIZE(outputbytes) - VARHDRSZ); - } - } - } - - CopySendEndOfRow(cstate); + cstate->routine->CopyToOneRow(cstate, slot); MemoryContextSwitchTo(oldcontext); } @@ -1158,8 +1323,11 @@ CopyAttributeOutCSV(CopyToState cstate, const char *string, if (!use_quote) { /* - * Because '\.' can be a data value, quote it if it appears alone on a - * line so it is not interpreted as the end-of-data marker. + * Quote '\.' if it appears alone on a line, so that it will not be + * interpreted as an end-of-data marker. (PG 18 and up will not + * interpret '\.' in CSV that way, except in embedded-in-SQL data; but + * we want the data to be loadable by older versions too. Also, this + * avoids breaking clients that are still using PQgetline().) */ if (single_attr && strcmp(ptr, "\\.") == 0) use_quote = true; diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 2c8a93b6e56f8..dfd2ab8e8628c 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -13,7 +13,7 @@ * we must return a tuples-processed count in the QueryCompletion. (We no * longer do that for CTAS ... WITH NO DATA, however.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -35,14 +35,16 @@ #include "commands/prepare.h" #include "commands/tablecmds.h" #include "commands/view.h" -#include "miscadmin.h" +#include "executor/execdesc.h" +#include "executor/executor.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" +#include "nodes/queryjumble.h" +#include "parser/analyze.h" #include "rewrite/rewriteHandler.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/lsyscache.h" -#include "utils/rel.h" #include "utils/rls.h" #include "utils/snapmgr.h" @@ -83,7 +85,7 @@ create_ctas_internal(List *attrList, IntoClause *into) bool is_matview; char relkind; Datum toast_options; - static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; ObjectAddress intoRelationAddr; /* This code supports both CREATE TABLE AS and CREATE MATERIALIZED VIEW */ @@ -133,7 +135,7 @@ create_ctas_internal(List *attrList, IntoClause *into) if (is_matview) { /* StoreViewQuery scribbles on tree, so make a copy */ - Query *query = (Query *) copyObject(into->viewQuery); + Query *query = copyObject(into->viewQuery); StoreViewQuery(intoRelationAddr.objectId, query, false); CommandCounterIncrement(); @@ -224,13 +226,11 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, { Query *query = castNode(Query, stmt->query); IntoClause *into = stmt->into; + JumbleState *jstate = NULL; bool is_matview = (into->viewQuery != NULL); bool do_refresh = false; DestReceiver *dest; ObjectAddress address; - List *rewritten; - PlannedStmt *plan; - QueryDesc *queryDesc; /* Check if the relation exists or not */ if (CreateTableAsRelExists(stmt)) @@ -241,6 +241,13 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, */ dest = CreateIntoRelDestReceiver(into); + /* Query contained by CTAS needs to be jumbled if requested */ + if (IsQueryIdEnabled()) + jstate = JumbleQuery(query); + + if (post_parse_analyze_hook) + (*post_parse_analyze_hook) (pstate, query, jstate); + /* * The contained Query could be a SELECT, or an EXECUTE utility command. * If the latter, we just pass it off to ExecuteQuery. @@ -279,9 +286,25 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, * from running the planner before all dependencies are set up. */ address = create_ctas_nodata(query->targetList, into); + + /* + * For materialized views, reuse the REFRESH logic, which locks down + * security-restricted operations and restricts the search_path. This + * reduces the chance that a subsequent refresh will fail. + */ + if (do_refresh) + RefreshMatViewByOid(address.objectId, true, false, false, + pstate->p_sourcetext, qc); + } else { + List *rewritten; + PlannedStmt *plan; + QueryDesc *queryDesc; + + Assert(!is_matview); + /* * Parse analysis was done already, but we still have to run the rule * rewriter. We do not do AcquireRewriteLocks: we assume the query @@ -292,9 +315,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) - elog(ERROR, "unexpected rewrite result for %s", - is_matview ? "CREATE MATERIALIZED VIEW" : - "CREATE TABLE AS SELECT"); + elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT"); query = linitial_node(Query, rewritten); Assert(query->commandType == CMD_SELECT); @@ -321,7 +342,7 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ExecutorStart(queryDesc, GetIntoRelEFlags(into)); /* run the plan to completion */ - ExecutorRun(queryDesc, ForwardScanDirection, 0, true); + ExecutorRun(queryDesc, ForwardScanDirection, 0); /* save the rowcount if we're given a qc to fill */ if (qc) @@ -339,20 +360,6 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, PopActiveSnapshot(); } - /* - * For materialized views, reuse the REFRESH logic, which locks down - * security-restricted operations and restricts the search_path. This - * reduces the chance that a subsequent refresh will fail. - */ - if (do_refresh) - { - RefreshMatViewByOid(address.objectId, false, false, - pstate->p_sourcetext, NULL, qc); - - if (qc) - qc->commandTag = CMDTAG_SELECT; - } - return address; } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 7026352bc99e7..c95eb94501671 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -8,7 +8,7 @@ * stepping on each others' toes. Formerly we used table-level locks * on pg_database, but that's too coarse-grained. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -288,7 +288,7 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath) * snapshot - or the active snapshot - might not be new enough for that, * but the return value of GetLatestSnapshot() should work fine. */ - snapshot = GetLatestSnapshot(); + snapshot = RegisterSnapshot(GetLatestSnapshot()); /* Process the relation block by block. */ for (blkno = 0; blkno < nblocks; blkno++) @@ -313,6 +313,7 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath) UnlockReleaseBuffer(buf); } + UnregisterSnapshot(snapshot); /* Release relation lock. */ UnlockRelationId(&relid, AccessShareLock); @@ -529,7 +530,7 @@ CreateDirAndVersionFile(char *dbpath, Oid dbid, Oid tsid, bool isRedo) xlrec.tablespace_id = tsid; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), + XLogRegisterData(&xlrec, sizeof(xl_dbase_create_wal_log_rec)); (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE_WAL_LOG); @@ -625,7 +626,7 @@ CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid, xlrec.src_tablespace_id = srctablespace; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, + XLogRegisterData(&xlrec, sizeof(xl_dbase_create_file_copy_rec)); (void) XLogInsert(RM_DBASE_ID, @@ -644,9 +645,10 @@ CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid, * make the XLOG entry for the benefit of PITR operations). This avoids * two nasty scenarios: * - * #1: When PITR is off, we don't XLOG the contents of newly created - * indexes; therefore the drop-and-recreate-whole-directory behavior of - * DBASE_CREATE replay would lose such indexes. + * #1: At wal_level=minimal, we don't XLOG the contents of newly created + * relfilenodes; therefore the drop-and-recreate-whole-directory behavior + * of DBASE_CREATE replay would lose such files created in the new + * database between our commit and the next checkpoint. * * #2: Since we have to recopy the source database during DBASE_CREATE * replay, we run the risk of copying changes in it that were committed @@ -704,22 +706,22 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) Oid dboid = InvalidOid; Oid datdba; ListCell *option; - DefElem *dtablespacename = NULL; - DefElem *downer = NULL; - DefElem *dtemplate = NULL; - DefElem *dencoding = NULL; - DefElem *dlocale = NULL; - DefElem *dbuiltinlocale = NULL; - DefElem *dcollate = NULL; - DefElem *dctype = NULL; - DefElem *diculocale = NULL; - DefElem *dicurules = NULL; - DefElem *dlocprovider = NULL; - DefElem *distemplate = NULL; - DefElem *dallowconnections = NULL; - DefElem *dconnlimit = NULL; - DefElem *dcollversion = NULL; - DefElem *dstrategy = NULL; + DefElem *tablespacenameEl = NULL; + DefElem *ownerEl = NULL; + DefElem *templateEl = NULL; + DefElem *encodingEl = NULL; + DefElem *localeEl = NULL; + DefElem *builtinlocaleEl = NULL; + DefElem *collateEl = NULL; + DefElem *ctypeEl = NULL; + DefElem *iculocaleEl = NULL; + DefElem *icurulesEl = NULL; + DefElem *locproviderEl = NULL; + DefElem *istemplateEl = NULL; + DefElem *allowconnectionsEl = NULL; + DefElem *connlimitEl = NULL; + DefElem *collversionEl = NULL; + DefElem *strategyEl = NULL; char *dbname = stmt->dbname; char *dbowner = NULL; const char *dbtemplate = NULL; @@ -746,93 +748,93 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) if (strcmp(defel->defname, "tablespace") == 0) { - if (dtablespacename) + if (tablespacenameEl) errorConflictingDefElem(defel, pstate); - dtablespacename = defel; + tablespacenameEl = defel; } else if (strcmp(defel->defname, "owner") == 0) { - if (downer) + if (ownerEl) errorConflictingDefElem(defel, pstate); - downer = defel; + ownerEl = defel; } else if (strcmp(defel->defname, "template") == 0) { - if (dtemplate) + if (templateEl) errorConflictingDefElem(defel, pstate); - dtemplate = defel; + templateEl = defel; } else if (strcmp(defel->defname, "encoding") == 0) { - if (dencoding) + if (encodingEl) errorConflictingDefElem(defel, pstate); - dencoding = defel; + encodingEl = defel; } else if (strcmp(defel->defname, "locale") == 0) { - if (dlocale) + if (localeEl) errorConflictingDefElem(defel, pstate); - dlocale = defel; + localeEl = defel; } else if (strcmp(defel->defname, "builtin_locale") == 0) { - if (dbuiltinlocale) + if (builtinlocaleEl) errorConflictingDefElem(defel, pstate); - dbuiltinlocale = defel; + builtinlocaleEl = defel; } else if (strcmp(defel->defname, "lc_collate") == 0) { - if (dcollate) + if (collateEl) errorConflictingDefElem(defel, pstate); - dcollate = defel; + collateEl = defel; } else if (strcmp(defel->defname, "lc_ctype") == 0) { - if (dctype) + if (ctypeEl) errorConflictingDefElem(defel, pstate); - dctype = defel; + ctypeEl = defel; } else if (strcmp(defel->defname, "icu_locale") == 0) { - if (diculocale) + if (iculocaleEl) errorConflictingDefElem(defel, pstate); - diculocale = defel; + iculocaleEl = defel; } else if (strcmp(defel->defname, "icu_rules") == 0) { - if (dicurules) + if (icurulesEl) errorConflictingDefElem(defel, pstate); - dicurules = defel; + icurulesEl = defel; } else if (strcmp(defel->defname, "locale_provider") == 0) { - if (dlocprovider) + if (locproviderEl) errorConflictingDefElem(defel, pstate); - dlocprovider = defel; + locproviderEl = defel; } else if (strcmp(defel->defname, "is_template") == 0) { - if (distemplate) + if (istemplateEl) errorConflictingDefElem(defel, pstate); - distemplate = defel; + istemplateEl = defel; } else if (strcmp(defel->defname, "allow_connections") == 0) { - if (dallowconnections) + if (allowconnectionsEl) errorConflictingDefElem(defel, pstate); - dallowconnections = defel; + allowconnectionsEl = defel; } else if (strcmp(defel->defname, "connection_limit") == 0) { - if (dconnlimit) + if (connlimitEl) errorConflictingDefElem(defel, pstate); - dconnlimit = defel; + connlimitEl = defel; } else if (strcmp(defel->defname, "collation_version") == 0) { - if (dcollversion) + if (collversionEl) errorConflictingDefElem(defel, pstate); - dcollversion = defel; + collversionEl = defel; } else if (strcmp(defel->defname, "location") == 0) { @@ -868,9 +870,9 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) } else if (strcmp(defel->defname, "strategy") == 0) { - if (dstrategy) + if (strategyEl) errorConflictingDefElem(defel, pstate); - dstrategy = defel; + strategyEl = defel; } else ereport(ERROR, @@ -879,17 +881,17 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) parser_errposition(pstate, defel->location))); } - if (downer && downer->arg) - dbowner = defGetString(downer); - if (dtemplate && dtemplate->arg) - dbtemplate = defGetString(dtemplate); - if (dencoding && dencoding->arg) + if (ownerEl && ownerEl->arg) + dbowner = defGetString(ownerEl); + if (templateEl && templateEl->arg) + dbtemplate = defGetString(templateEl); + if (encodingEl && encodingEl->arg) { const char *encoding_name; - if (IsA(dencoding->arg, Integer)) + if (IsA(encodingEl->arg, Integer)) { - encoding = defGetInt32(dencoding); + encoding = defGetInt32(encodingEl); encoding_name = pg_encoding_to_char(encoding); if (strcmp(encoding_name, "") == 0 || pg_valid_server_encoding(encoding_name) < 0) @@ -897,39 +899,39 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("%d is not a valid encoding code", encoding), - parser_errposition(pstate, dencoding->location))); + parser_errposition(pstate, encodingEl->location))); } else { - encoding_name = defGetString(dencoding); + encoding_name = defGetString(encodingEl); encoding = pg_valid_server_encoding(encoding_name); if (encoding < 0) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("%s is not a valid encoding name", encoding_name), - parser_errposition(pstate, dencoding->location))); + parser_errposition(pstate, encodingEl->location))); } } - if (dlocale && dlocale->arg) + if (localeEl && localeEl->arg) { - dbcollate = defGetString(dlocale); - dbctype = defGetString(dlocale); - dblocale = defGetString(dlocale); + dbcollate = defGetString(localeEl); + dbctype = defGetString(localeEl); + dblocale = defGetString(localeEl); } - if (dbuiltinlocale && dbuiltinlocale->arg) - dblocale = defGetString(dbuiltinlocale); - if (dcollate && dcollate->arg) - dbcollate = defGetString(dcollate); - if (dctype && dctype->arg) - dbctype = defGetString(dctype); - if (diculocale && diculocale->arg) - dblocale = defGetString(diculocale); - if (dicurules && dicurules->arg) - dbicurules = defGetString(dicurules); - if (dlocprovider && dlocprovider->arg) + if (builtinlocaleEl && builtinlocaleEl->arg) + dblocale = defGetString(builtinlocaleEl); + if (collateEl && collateEl->arg) + dbcollate = defGetString(collateEl); + if (ctypeEl && ctypeEl->arg) + dbctype = defGetString(ctypeEl); + if (iculocaleEl && iculocaleEl->arg) + dblocale = defGetString(iculocaleEl); + if (icurulesEl && icurulesEl->arg) + dbicurules = defGetString(icurulesEl); + if (locproviderEl && locproviderEl->arg) { - char *locproviderstr = defGetString(dlocprovider); + char *locproviderstr = defGetString(locproviderEl); if (pg_strcasecmp(locproviderstr, "builtin") == 0) dblocprovider = COLLPROVIDER_BUILTIN; @@ -943,20 +945,20 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) errmsg("unrecognized locale provider: %s", locproviderstr))); } - if (distemplate && distemplate->arg) - dbistemplate = defGetBoolean(distemplate); - if (dallowconnections && dallowconnections->arg) - dballowconnections = defGetBoolean(dallowconnections); - if (dconnlimit && dconnlimit->arg) + if (istemplateEl && istemplateEl->arg) + dbistemplate = defGetBoolean(istemplateEl); + if (allowconnectionsEl && allowconnectionsEl->arg) + dballowconnections = defGetBoolean(allowconnectionsEl); + if (connlimitEl && connlimitEl->arg) { - dbconnlimit = defGetInt32(dconnlimit); + dbconnlimit = defGetInt32(connlimitEl); if (dbconnlimit < DATCONNLIMIT_UNLIMITED) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid connection limit: %d", dbconnlimit))); } - if (dcollversion) - dbcollversion = defGetString(dcollversion); + if (collversionEl) + dbcollversion = defGetString(collversionEl); /* obtain OID of proposed owner */ if (dbowner) @@ -1025,11 +1027,11 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) } /* Validate the database creation strategy. */ - if (dstrategy && dstrategy->arg) + if (strategyEl && strategyEl->arg) { char *strategy; - strategy = defGetString(dstrategy); + strategy = defGetString(strategyEl); if (pg_strcasecmp(strategy, "wal_log") == 0) dbstrategy = CREATEDB_WAL_LOG; else if (pg_strcasecmp(strategy, "file_copy") == 0) @@ -1063,16 +1065,41 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) /* Check that the chosen locales are valid, and get canonical spellings */ if (!check_locale(LC_COLLATE, dbcollate, &canonname)) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("invalid LC_COLLATE locale name: \"%s\"", dbcollate), - errhint("If the locale name is specific to ICU, use ICU_LOCALE."))); + { + if (dblocprovider == COLLPROVIDER_BUILTIN) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_COLLATE locale name: \"%s\"", dbcollate), + errhint("If the locale name is specific to the builtin provider, use BUILTIN_LOCALE."))); + else if (dblocprovider == COLLPROVIDER_ICU) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_COLLATE locale name: \"%s\"", dbcollate), + errhint("If the locale name is specific to the ICU provider, use ICU_LOCALE."))); + else + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_COLLATE locale name: \"%s\"", dbcollate))); + } dbcollate = canonname; if (!check_locale(LC_CTYPE, dbctype, &canonname)) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("invalid LC_CTYPE locale name: \"%s\"", dbctype), - errhint("If the locale name is specific to ICU, use ICU_LOCALE."))); + { + if (dblocprovider == COLLPROVIDER_BUILTIN) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_CTYPE locale name: \"%s\"", dbctype), + errhint("If the locale name is specific to the builtin provider, use BUILTIN_LOCALE."))); + else if (dblocprovider == COLLPROVIDER_ICU) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_CTYPE locale name: \"%s\"", dbctype), + errhint("If the locale name is specific to the ICU provider, use ICU_LOCALE."))); + else + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid LC_CTYPE locale name: \"%s\"", dbctype))); + } + dbctype = canonname; check_encoding_locale_matches(encoding, dbcollate, dbctype); @@ -1080,7 +1107,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) /* validate provider-specific parameters */ if (dblocprovider != COLLPROVIDER_BUILTIN) { - if (dbuiltinlocale) + if (builtinlocaleEl) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("BUILTIN_LOCALE cannot be specified unless locale provider is builtin"))); @@ -1088,7 +1115,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) if (dblocprovider != COLLPROVIDER_ICU) { - if (diculocale) + if (iculocaleEl) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("ICU locale cannot be specified unless locale provider is ICU"))); @@ -1239,7 +1266,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) * template0, for which we stipulate that it does not contain * collation-using objects.) */ - if (src_collversion && !dcollversion) + if (src_collversion && !collversionEl) { char *actual_versionstr; const char *locale; @@ -1289,12 +1316,12 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) } /* Resolve default tablespace for new database */ - if (dtablespacename && dtablespacename->arg) + if (tablespacenameEl && tablespacenameEl->arg) { char *tablespacename; AclResult aclresult; - tablespacename = defGetString(dtablespacename); + tablespacename = defGetString(tablespacenameEl); dst_deftablespace = get_tablespace_oid(tablespacename, false); /* check permissions */ aclresult = object_aclcheck(TableSpaceRelationId, dst_deftablespace, GetUserId(), @@ -1649,6 +1676,8 @@ dropdb(const char *dbname, bool missing_ok, bool force) bool db_istemplate; Relation pgdbrel; HeapTuple tup; + ScanKeyData scankey; + void *inplace_state; Form_pg_database datform; int notherbackends; int npreparedxacts; @@ -1786,11 +1815,6 @@ dropdb(const char *dbname, bool missing_ok, bool force) */ pgstat_drop_database(db_id); - tup = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(db_id)); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "cache lookup failed for database %u", db_id); - datform = (Form_pg_database) GETSTRUCT(tup); - /* * Except for the deletion of the catalog row, subsequent actions are not * transactional (consider DropDatabaseBuffers() discarding modified @@ -1802,8 +1826,17 @@ dropdb(const char *dbname, bool missing_ok, bool force) * modification is durable before performing irreversible filesystem * operations. */ + ScanKeyInit(&scankey, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(dbname)); + systable_inplace_update_begin(pgdbrel, DatabaseNameIndexId, true, + NULL, 1, &scankey, &tup, &inplace_state); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for database %u", db_id); + datform = (Form_pg_database) GETSTRUCT(tup); datform->datconnlimit = DATCONNLIMIT_INVALID_DB; - heap_inplace_update(pgdbrel, tup); + systable_inplace_update_finish(inplace_state, tup); XLogFlush(XactLastRecEnd); /* @@ -1811,6 +1844,7 @@ dropdb(const char *dbname, bool missing_ok, bool force) * the row will be gone, but if we fail, dropdb() can be invoked again. */ CatalogTupleDelete(pgdbrel, &tup->t_self); + heap_freetuple(tup); /* * Drop db-specific replication slots. @@ -1869,6 +1903,7 @@ RenameDatabase(const char *oldname, const char *newname) { Oid db_id; HeapTuple newtup; + ItemPointerData otid; Relation rel; int notherbackends; int npreparedxacts; @@ -1940,11 +1975,13 @@ RenameDatabase(const char *oldname, const char *newname) errdetail_busy_db(notherbackends, npreparedxacts))); /* rename */ - newtup = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(db_id)); + newtup = SearchSysCacheLockedCopy1(DATABASEOID, ObjectIdGetDatum(db_id)); if (!HeapTupleIsValid(newtup)) elog(ERROR, "cache lookup failed for database %u", db_id); + otid = newtup->t_self; namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname); - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &otid, newtup); + UnlockTuple(rel, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -2172,7 +2209,7 @@ movedb(const char *dbname, const char *tblspcname) xlrec.src_tablespace_id = src_tblspcoid; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, + XLogRegisterData(&xlrec, sizeof(xl_dbase_create_file_copy_rec)); (void) XLogInsert(RM_DBASE_ID, @@ -2193,6 +2230,7 @@ movedb(const char *dbname, const char *tblspcname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", dbname))); + LockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock); new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_tblspcoid); new_record_repl[Anum_pg_database_dattablespace - 1] = true; @@ -2201,6 +2239,7 @@ movedb(const char *dbname, const char *tblspcname) new_record, new_record_nulls, new_record_repl); CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple); + UnlockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -2266,8 +2305,8 @@ movedb(const char *dbname, const char *tblspcname) xlrec.ntablespaces = 1; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xl_dbase_drop_rec)); - XLogRegisterData((char *) &src_tblspcoid, sizeof(Oid)); + XLogRegisterData(&xlrec, sizeof(xl_dbase_drop_rec)); + XLogRegisterData(&src_tblspcoid, sizeof(Oid)); (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP | XLR_SPECIAL_REL_UPDATE); @@ -2431,6 +2470,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", stmt->dbname))); + LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); datform = (Form_pg_database) GETSTRUCT(tuple); dboid = datform->oid; @@ -2480,6 +2520,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record, new_record_nulls, new_record_repl); CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0); @@ -2529,6 +2570,7 @@ AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt) if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE, stmt->dbname); + LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); datum = heap_getattr(tuple, Anum_pg_database_datcollversion, RelationGetDescr(rel), &isnull); oldversion = isnull ? NULL : TextDatumGetCString(datum); @@ -2557,6 +2599,7 @@ AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt) bool nulls[Natts_pg_database] = {0}; bool replaces[Natts_pg_database] = {0}; Datum values[Natts_pg_database] = {0}; + HeapTuple newtuple; ereport(NOTICE, (errmsg("changing version from %s to %s", @@ -2565,14 +2608,15 @@ AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt) values[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(newversion); replaces[Anum_pg_database_datcollversion - 1] = true; - tuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &tuple->t_self, tuple); - heap_freetuple(tuple); + newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), + values, nulls, replaces); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + heap_freetuple(newtuple); } else ereport(NOTICE, (errmsg("version has not changed"))); + UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -2684,6 +2728,8 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to change owner of database"))); + LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); + repl_repl[Anum_pg_database_datdba - 1] = true; repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId); @@ -2705,6 +2751,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl); CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); heap_freetuple(newtuple); @@ -3016,8 +3063,8 @@ remove_dbtablespaces(Oid db_id) xlrec.ntablespaces = ntblspc; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, MinSizeOfDbaseDropRec); - XLogRegisterData((char *) tablespace_ids, ntblspc * sizeof(Oid)); + XLogRegisterData(&xlrec, MinSizeOfDbaseDropRec); + XLogRegisterData(tablespace_ids, ntblspc * sizeof(Oid)); (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP | XLR_SPECIAL_REL_UPDATE); @@ -3239,7 +3286,7 @@ recovery_create_dbdir(char *path, bool only_tblspc) if (stat(path, &st) == 0) return; - if (only_tblspc && strstr(path, "pg_tblspc/") == NULL) + if (only_tblspc && strstr(path, PG_TBLSPC_DIR_SLASH) == NULL) elog(PANIC, "requested to created invalid directory: %s", path); if (reachedConsistency && !allow_in_place_tablespaces) diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 43f50066ea061..5e1b867e6f733 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -4,7 +4,7 @@ * Support routines for various kinds of object creation. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -12,20 +12,7 @@ * src/backend/commands/define.c * * DESCRIPTION - * The "DefineFoo" routines take the parse tree and pick out the - * appropriate arguments/flags, passing the results to the - * corresponding "FooDefine" routines (in src/catalog) that do - * the actual catalog-munging. These routines also verify permission - * of the user to execute the command. - * - * NOTES - * These things must be defined and committed in the following order: - * "create function": - * input/output, recv/send procedures - * "create type": - * type - * "create operator": - * operators + * Support routines for dealing with DefElem nodes. * * *------------------------------------------------------------------------- diff --git a/src/backend/commands/discard.c b/src/backend/commands/discard.c index 92d983ac74817..81339a75a5286 100644 --- a/src/backend/commands/discard.c +++ b/src/backend/commands/discard.c @@ -3,7 +3,7 @@ * discard.c * The implementation of the DISCARD command * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index 85eec7e394779..ceb9a229b63b2 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -3,7 +3,7 @@ * dropcmds.c * handle various "DROP" operations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 7a5ed6b9850e9..edc2c988e2934 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -3,7 +3,7 @@ * event_trigger.c * PostgreSQL EVENT TRIGGER support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -276,8 +276,8 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO Relation tgrel; Oid trigoid; HeapTuple tuple; - Datum values[Natts_pg_trigger]; - bool nulls[Natts_pg_trigger]; + Datum values[Natts_pg_event_trigger]; + bool nulls[Natts_pg_event_trigger]; NameData evtnamedata, evteventdata; ObjectAddress myself, @@ -388,6 +388,7 @@ SetDatabaseHasLoginEventTriggers(void) /* Set dathasloginevt flag in pg_database */ Form_pg_database db; Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock); + ItemPointerData otid; HeapTuple tuple; /* @@ -399,16 +400,18 @@ SetDatabaseHasLoginEventTriggers(void) */ LockSharedObject(DatabaseRelationId, MyDatabaseId, 0, AccessExclusiveLock); - tuple = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); + tuple = SearchSysCacheLockedCopy1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + otid = tuple->t_self; db = (Form_pg_database) GETSTRUCT(tuple); if (!db->dathasloginevt) { db->dathasloginevt = true; - CatalogTupleUpdate(pg_db, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_db, &otid, tuple); CommandCounterIncrement(); } + UnlockTuple(pg_db, &otid, InplaceUpdateTupleLock); table_close(pg_db, RowExclusiveLock); heap_freetuple(tuple); } @@ -946,25 +949,18 @@ EventTriggerOnLogin(void) { Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock); HeapTuple tuple; + void *state; Form_pg_database db; ScanKeyData key[1]; - SysScanDesc scan; - /* - * Get the pg_database tuple to scribble on. Note that this does - * not directly rely on the syscache to avoid issues with - * flattened toast values for the in-place update. - */ + /* Fetch a copy of the tuple to scribble on */ ScanKeyInit(&key[0], Anum_pg_database_oid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(MyDatabaseId)); - scan = systable_beginscan(pg_db, DatabaseOidIndexId, true, - NULL, 1, key); - tuple = systable_getnext(scan); - tuple = heap_copytuple(tuple); - systable_endscan(scan); + systable_inplace_update_begin(pg_db, DatabaseOidIndexId, true, + NULL, 1, key, &tuple, &state); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for database %u", MyDatabaseId); @@ -979,14 +975,11 @@ EventTriggerOnLogin(void) * this instead of regular updates serves two purposes. First, * that avoids possible waiting on the row-level lock. Second, * that avoids dealing with TOAST. - * - * It's known that changes made by heap_inplace_update() may - * be lost due to concurrent normal updates. However, we are - * OK with that. The subsequent connections will still have a - * chance to set "dathasloginevt" to false. */ - heap_inplace_update(pg_db, tuple); + systable_inplace_update_finish(state, tuple); } + else + systable_inplace_update_cancel(state); table_close(pg_db, RowExclusiveLock); heap_freetuple(tuple); } @@ -1130,7 +1123,7 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata) /* * Do event triggers support this object type? * - * See also event trigger support matrix in event-trigger.sgml. + * See also event trigger documentation in event-trigger.sgml. */ bool EventTriggerSupportsObjectType(ObjectType obtype) @@ -1154,7 +1147,7 @@ EventTriggerSupportsObjectType(ObjectType obtype) /* * Do event triggers support this object class? * - * See also event trigger support matrix in event-trigger.sgml. + * See also event trigger documentation in event-trigger.sgml. */ bool EventTriggerSupportsObject(const ObjectAddress *object) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 5771aabf40a79..7e2792ead715b 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -3,7 +3,7 @@ * explain.c * Explain query execution plans * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * IDENTIFICATION @@ -17,6 +17,10 @@ #include "catalog/pg_type.h" #include "commands/createas.h" #include "commands/defrem.h" +#include "commands/explain.h" +#include "commands/explain_dr.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" #include "commands/prepare.h" #include "foreign/fdwapi.h" #include "jit/jit.h" @@ -48,20 +52,9 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; /* Hook for plugins to get control in explain_get_index_name() */ explain_get_index_name_hook_type explain_get_index_name_hook = NULL; - -/* Instrumentation data for SERIALIZE option */ -typedef struct SerializeMetrics -{ - uint64 bytesSent; /* # of bytes serialized */ - instr_time timeSpent; /* time spent serializing */ - BufferUsage bufferUsage; /* buffers accessed during serialization */ -} SerializeMetrics; - -/* OR-able flags for ExplainXMLTag() */ -#define X_OPENING 0 -#define X_CLOSING 1 -#define X_CLOSE_IMMEDIATE 2 -#define X_NOWHITESPACE 4 +/* per-plan and per-node hooks for plugins to print additional info */ +explain_per_plan_hook_type explain_per_plan_hook = NULL; +explain_per_node_hook_type explain_per_node_hook = NULL; /* * Various places within need to convert bytes to kilobytes. Round these up @@ -71,8 +64,7 @@ typedef struct SerializeMetrics static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, - const char *queryString, ParamListInfo params, - QueryEnvironment *queryEnv); + ParseState *pstate, ParamListInfo params); static void ExplainPrintJIT(ExplainState *es, int jit_flags, JitInstrumentation *ji); static void ExplainPrintSerialize(ExplainState *es, @@ -120,6 +112,13 @@ static void show_sort_group_keys(PlanState *planstate, const char *qlabel, List *ancestors, ExplainState *es); static void show_sortorder_options(StringInfo buf, Node *sortexpr, Oid sortOperator, Oid collation, bool nullsFirst); +static void show_window_def(WindowAggState *planstate, + List *ancestors, ExplainState *es); +static void show_window_keys(StringInfo buf, PlanState *planstate, + int nkeys, AttrNumber *keycols, + List *ancestors, ExplainState *es); +static void show_storage_info(char *maxStorageType, int64 maxSpaceUsed, + ExplainState *es); static void show_tablesample(TableSampleClause *tsc, PlanState *planstate, List *ancestors, ExplainState *es); static void show_sort_info(SortState *sortstate, ExplainState *es); @@ -127,9 +126,16 @@ static void show_incremental_sort_info(IncrementalSortState *incrsortstate, ExplainState *es); static void show_hash_info(HashState *hashstate, ExplainState *es); static void show_material_info(MaterialState *mstate, ExplainState *es); +static void show_windowagg_info(WindowAggState *winstate, ExplainState *es); +static void show_ctescan_info(CteScanState *ctescanstate, ExplainState *es); +static void show_table_func_scan_info(TableFuncScanState *tscanstate, + ExplainState *es); +static void show_recursive_union_info(RecursiveUnionState *rstate, + ExplainState *es); static void show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es); static void show_hashagg_info(AggState *aggstate, ExplainState *es); +static void show_indexsearches_info(PlanState *planstate, ExplainState *es); static void show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es); static void show_instrumentation_count(const char *qlabel, int which, @@ -159,20 +165,6 @@ static ExplainWorkersState *ExplainCreateWorkersState(int num_workers); static void ExplainOpenWorker(int n, ExplainState *es); static void ExplainCloseWorker(int n, ExplainState *es); static void ExplainFlushWorkersState(ExplainState *es); -static void ExplainProperty(const char *qlabel, const char *unit, - const char *value, bool numeric, ExplainState *es); -static void ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, - bool labeled, int depth, ExplainState *es); -static void ExplainSaveGroup(ExplainState *es, int depth, int *state_save); -static void ExplainRestoreGroup(ExplainState *es, int depth, int *state_save); -static void ExplainDummyGroup(const char *objtype, const char *labelname, - ExplainState *es); -static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es); -static void ExplainIndentText(ExplainState *es); -static void ExplainJSONLineEnding(ExplainState *es); -static void ExplainYAMLLineStarting(ExplainState *es); -static void escape_yaml(StringInfo buf, const char *str); -static SerializeMetrics GetSerializationMetrics(DestReceiver *dest); @@ -189,123 +181,11 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, JumbleState *jstate = NULL; Query *query; List *rewritten; - ListCell *lc; - bool timing_set = false; - bool summary_set = false; - - /* Parse options list. */ - foreach(lc, stmt->options) - { - DefElem *opt = (DefElem *) lfirst(lc); - - if (strcmp(opt->defname, "analyze") == 0) - es->analyze = defGetBoolean(opt); - else if (strcmp(opt->defname, "verbose") == 0) - es->verbose = defGetBoolean(opt); - else if (strcmp(opt->defname, "costs") == 0) - es->costs = defGetBoolean(opt); - else if (strcmp(opt->defname, "buffers") == 0) - es->buffers = defGetBoolean(opt); - else if (strcmp(opt->defname, "wal") == 0) - es->wal = defGetBoolean(opt); - else if (strcmp(opt->defname, "settings") == 0) - es->settings = defGetBoolean(opt); - else if (strcmp(opt->defname, "generic_plan") == 0) - es->generic = defGetBoolean(opt); - else if (strcmp(opt->defname, "timing") == 0) - { - timing_set = true; - es->timing = defGetBoolean(opt); - } - else if (strcmp(opt->defname, "summary") == 0) - { - summary_set = true; - es->summary = defGetBoolean(opt); - } - else if (strcmp(opt->defname, "memory") == 0) - es->memory = defGetBoolean(opt); - else if (strcmp(opt->defname, "serialize") == 0) - { - if (opt->arg) - { - char *p = defGetString(opt); - - if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0) - es->serialize = EXPLAIN_SERIALIZE_NONE; - else if (strcmp(p, "text") == 0) - es->serialize = EXPLAIN_SERIALIZE_TEXT; - else if (strcmp(p, "binary") == 0) - es->serialize = EXPLAIN_SERIALIZE_BINARY; - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"", - opt->defname, p), - parser_errposition(pstate, opt->location))); - } - else - { - /* SERIALIZE without an argument is taken as 'text' */ - es->serialize = EXPLAIN_SERIALIZE_TEXT; - } - } - else if (strcmp(opt->defname, "format") == 0) - { - char *p = defGetString(opt); - - if (strcmp(p, "text") == 0) - es->format = EXPLAIN_FORMAT_TEXT; - else if (strcmp(p, "xml") == 0) - es->format = EXPLAIN_FORMAT_XML; - else if (strcmp(p, "json") == 0) - es->format = EXPLAIN_FORMAT_JSON; - else if (strcmp(p, "yaml") == 0) - es->format = EXPLAIN_FORMAT_YAML; - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"", - opt->defname, p), - parser_errposition(pstate, opt->location))); - } - else - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unrecognized EXPLAIN option \"%s\"", - opt->defname), - parser_errposition(pstate, opt->location))); - } - /* check that WAL is used with EXPLAIN ANALYZE */ - if (es->wal && !es->analyze) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN option WAL requires ANALYZE"))); - - /* if the timing was not set explicitly, set default value */ - es->timing = (timing_set) ? es->timing : es->analyze; - - /* check that timing is used with EXPLAIN ANALYZE */ - if (es->timing && !es->analyze) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN option TIMING requires ANALYZE"))); - - /* check that serialize is used with EXPLAIN ANALYZE */ - if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN option SERIALIZE requires ANALYZE"))); - - /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */ - if (es->generic && es->analyze) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together"))); - - /* if the summary was not set explicitly, set default value */ - es->summary = (summary_set) ? es->summary : es->analyze; + /* Configure the ExplainState based on the provided options */ + ParseExplainOptionList(es, stmt->options, pstate); + /* Extract the query and, if enabled, jumble it */ query = castNode(Query, stmt->query); if (IsQueryIdEnabled()) jstate = JumbleQuery(query); @@ -342,7 +222,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, { ExplainOneQuery(lfirst_node(Query, l), CURSOR_OPT_PARALLEL_OK, NULL, es, - pstate->p_sourcetext, params, pstate->p_queryEnv); + pstate, params); /* Separate plans with an appropriate separator */ if (lnext(rewritten, l) != NULL) @@ -366,22 +246,6 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, pfree(es->str->data); } -/* - * Create a new ExplainState struct initialized with default options. - */ -ExplainState * -NewExplainState(void) -{ - ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState)); - - /* Set default options (most fields can be left as zeroes). */ - es->costs = true; - /* Prepare output buffer. */ - es->str = makeStringInfo(); - - return es; -} - /* * ExplainResultDesc - * construct the result tupledesc for an EXPLAIN @@ -428,24 +292,22 @@ ExplainResultDesc(ExplainStmt *stmt) static void ExplainOneQuery(Query *query, int cursorOptions, IntoClause *into, ExplainState *es, - const char *queryString, ParamListInfo params, - QueryEnvironment *queryEnv) + ParseState *pstate, ParamListInfo params) { /* planner will not cope with utility statements */ if (query->commandType == CMD_UTILITY) { - ExplainOneUtility(query->utilityStmt, into, es, queryString, params, - queryEnv); + ExplainOneUtility(query->utilityStmt, into, es, pstate, params); return; } /* if an advisor plugin is present, let it manage things */ if (ExplainOneQuery_hook) (*ExplainOneQuery_hook) (query, cursorOptions, into, es, - queryString, params, queryEnv); + pstate->p_sourcetext, params, pstate->p_queryEnv); else standard_ExplainOneQuery(query, cursorOptions, into, es, - queryString, params, queryEnv); + pstate->p_sourcetext, params, pstate->p_queryEnv); } /* @@ -526,8 +388,7 @@ standard_ExplainOneQuery(Query *query, int cursorOptions, */ void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, - const char *queryString, ParamListInfo params, - QueryEnvironment *queryEnv) + ParseState *pstate, ParamListInfo params) { if (utilityStmt == NULL) return; @@ -539,7 +400,9 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, * ExplainOneQuery. Copy to be safe in the EXPLAIN EXECUTE case. */ CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt; + Query *ctas_query; List *rewritten; + JumbleState *jstate = NULL; /* * Check if the relation exists or not. This is done at this stage to @@ -557,11 +420,16 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, return; } - rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query))); + ctas_query = castNode(Query, copyObject(ctas->query)); + if (IsQueryIdEnabled()) + jstate = JumbleQuery(ctas_query); + if (post_parse_analyze_hook) + (*post_parse_analyze_hook) (pstate, ctas_query, jstate); + rewritten = QueryRewrite(ctas_query); Assert(list_length(rewritten) == 1); ExplainOneQuery(linitial_node(Query, rewritten), CURSOR_OPT_PARALLEL_OK, ctas->into, es, - queryString, params, queryEnv); + pstate, params); } else if (IsA(utilityStmt, DeclareCursorStmt)) { @@ -574,17 +442,25 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, * be created, however. */ DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt; + Query *dcs_query; List *rewritten; + JumbleState *jstate = NULL; - rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query))); + dcs_query = castNode(Query, copyObject(dcs->query)); + if (IsQueryIdEnabled()) + jstate = JumbleQuery(dcs_query); + if (post_parse_analyze_hook) + (*post_parse_analyze_hook) (pstate, dcs_query, jstate); + + rewritten = QueryRewrite(dcs_query); Assert(list_length(rewritten) == 1); ExplainOneQuery(linitial_node(Query, rewritten), dcs->options, NULL, es, - queryString, params, queryEnv); + pstate, params); } else if (IsA(utilityStmt, ExecuteStmt)) ExplainExecuteQuery((ExecuteStmt *) utilityStmt, into, es, - queryString, params, queryEnv); + pstate, params); else if (IsA(utilityStmt, NotifyStmt)) { if (es->format == EXPLAIN_FORMAT_TEXT) @@ -700,7 +576,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, dir = ForwardScanDirection; /* run the plan */ - ExecutorRun(queryDesc, dir, 0, true); + ExecutorRun(queryDesc, dir, 0); /* run cleanup too */ ExecutorFinish(queryDesc); @@ -769,6 +645,11 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, if (es->serialize != EXPLAIN_SERIALIZE_NONE) ExplainPrintSerialize(es, &serializeMetrics); + /* Allow plugins to print additional information */ + if (explain_per_plan_hook) + (*explain_per_plan_hook) (plannedstmt, into, es, queryString, + params, queryEnv); + /* * Close down the query and free resources. Include time for this in the * total execution time (although it should be pretty minimal). @@ -879,6 +760,7 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc) { Bitmapset *rels_used = NULL; PlanState *ps; + ListCell *lc; /* Set up ExplainState fields associated with this plan tree */ Assert(queryDesc->plannedstmt != NULL); @@ -889,6 +771,17 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc) es->deparse_cxt = deparse_context_for_plan_tree(queryDesc->plannedstmt, es->rtable_names); es->printed_subplans = NULL; + es->rtable_size = list_length(es->rtable); + foreach(lc, es->rtable) + { + RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); + + if (rte->rtekind == RTE_GROUP) + { + es->rtable_size--; + break; + } + } /* * Sometimes we mark a Gather node as "invisible", which means that it's @@ -918,14 +811,10 @@ ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc) * the queryid in any of the EXPLAIN plans to keep stable the results * generated by regression test suites. */ - if (es->verbose && queryDesc->plannedstmt->queryId != UINT64CONST(0) && + if (es->verbose && queryDesc->plannedstmt->queryId != INT64CONST(0) && compute_query_id != COMPUTE_QUERY_ID_REGRESS) { - /* - * Output the queryid as an int64 rather than a uint64 so we match - * what would be seen in the BIGINT pg_stat_statements.queryid column. - */ - ExplainPropertyInteger("Query Identifier", NULL, (int64) + ExplainPropertyInteger("Query Identifier", NULL, queryDesc->plannedstmt->queryId, es); } } @@ -1327,6 +1216,10 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) if (((ModifyTable *) plan)->exclRelRTI) *rels_used = bms_add_member(*rels_used, ((ModifyTable *) plan)->exclRelRTI); + /* Ensure Vars used in RETURNING will have refnames */ + if (plan->targetlist) + *rels_used = bms_add_member(*rels_used, + linitial_int(((ModifyTable *) plan)->resultRelations)); break; case T_Append: *rels_used = bms_add_members(*rels_used, @@ -1343,6 +1236,96 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used); } +/* + * plan_is_disabled + * Checks if the given plan node type was disabled during query planning. + * This is evident by the disabled_nodes field being higher than the sum of + * the disabled_nodes field from the plan's children. + */ +static bool +plan_is_disabled(Plan *plan) +{ + int child_disabled_nodes; + + /* The node is certainly not disabled if this is zero */ + if (plan->disabled_nodes == 0) + return false; + + child_disabled_nodes = 0; + + /* + * Handle special nodes first. Children of BitmapOrs and BitmapAnds can't + * be disabled, so no need to handle those specifically. + */ + if (IsA(plan, Append)) + { + ListCell *lc; + Append *aplan = (Append *) plan; + + /* + * Sum the Append childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, aplan->appendplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, MergeAppend)) + { + ListCell *lc; + MergeAppend *maplan = (MergeAppend *) plan; + + /* + * Sum the MergeAppend childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, maplan->mergeplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, SubqueryScan)) + child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes; + else if (IsA(plan, CustomScan)) + { + ListCell *lc; + CustomScan *cplan = (CustomScan *) plan; + + foreach(lc, cplan->custom_plans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else + { + /* + * Else, sum up disabled_nodes from the plan's inner and outer side. + */ + if (outerPlan(plan)) + child_disabled_nodes += outerPlan(plan)->disabled_nodes; + if (innerPlan(plan)) + child_disabled_nodes += innerPlan(plan)->disabled_nodes; + } + + /* + * It's disabled if the plan's disabled_nodes is higher than the sum of + * its child's plan disabled_nodes. + */ + if (plan->disabled_nodes > child_disabled_nodes) + return true; + + return false; +} + /* * ExplainNode - * Appends a description of a plan tree to es->str @@ -1379,6 +1362,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainWorkersState *save_workers_state = es->workers_state; int save_indent = es->indent; bool haschildren; + bool isdisabled; /* * Prepare per-worker output buffers, if needed. We'll append the data in @@ -1852,14 +1836,12 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) { + appendStringInfoString(es->str, " (actual "); + if (es->timing) - appendStringInfo(es->str, - " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)", - startup_ms, total_ms, rows, nloops); - else - appendStringInfo(es->str, - " (actual rows=%.0f loops=%.0f)", - rows, nloops); + appendStringInfo(es->str, "time=%.3f..%.3f ", startup_ms, total_ms); + + appendStringInfo(es->str, "rows=%.2f loops=%.0f)", rows, nloops); } else { @@ -1870,7 +1852,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyFloat("Actual Total Time", "ms", total_ms, 3, es); } - ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es); + ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es); ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es); } } @@ -1894,6 +1876,11 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) appendStringInfoChar(es->str, '\n'); + + isdisabled = plan_is_disabled(plan); + if (es->format != EXPLAIN_FORMAT_TEXT || isdisabled) + ExplainPropertyBool("Disabled", isdisabled, es); + /* prepare per-worker general execution details */ if (es->workers_state && es->verbose) { @@ -1918,14 +1905,11 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) { ExplainIndentText(es); + appendStringInfoString(es->str, "actual "); if (es->timing) - appendStringInfo(es->str, - "actual time=%.3f..%.3f rows=%.0f loops=%.0f\n", - startup_ms, total_ms, rows, nloops); - else - appendStringInfo(es->str, - "actual rows=%.0f loops=%.0f\n", - rows, nloops); + appendStringInfo(es->str, "time=%.3f..%.3f ", startup_ms, total_ms); + + appendStringInfo(es->str, "rows=%.2f loops=%.0f\n", rows, nloops); } else { @@ -1936,7 +1920,8 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyFloat("Actual Total Time", "ms", total_ms, 3, es); } - ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es); + + ExplainPropertyFloat("Actual Rows", NULL, rows, 2, es); ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es); } @@ -1980,6 +1965,7 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); + show_indexsearches_info(planstate, es); break; case T_IndexOnlyScan: show_scan_qual(((IndexOnlyScan *) plan)->indexqual, @@ -1996,10 +1982,12 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->analyze) ExplainPropertyFloat("Heap Fetches", NULL, planstate->instrument->ntuples2, 0, es); + show_indexsearches_info(planstate, es); break; case T_BitmapIndexScan: show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig, "Index Cond", planstate, ancestors, es); + show_indexsearches_info(planstate, es); break; case T_BitmapHeapScan: show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig, @@ -2028,6 +2016,8 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); + if (IsA(plan, CteScan)) + show_ctescan_info(castNode(CteScanState, planstate), es); break; case T_Gather: { @@ -2109,6 +2099,8 @@ ExplainNode(PlanState *planstate, List *ancestors, if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); + show_table_func_scan_info(castNode(TableFuncScanState, + planstate), es); break; case T_TidScan: { @@ -2209,12 +2201,14 @@ ExplainNode(PlanState *planstate, List *ancestors, planstate, es); break; case T_WindowAgg: + show_window_def(castNode(WindowAggState, planstate), ancestors, es); + show_upper_qual(((WindowAgg *) plan)->runConditionOrig, + "Run Condition", planstate, ancestors, es); show_upper_qual(plan->qual, "Filter", planstate, ancestors, es); if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); - show_upper_qual(((WindowAgg *) plan)->runConditionOrig, - "Run Condition", planstate, ancestors, es); + show_windowagg_info(castNode(WindowAggState, planstate), es); break; case T_Group: show_group_keys(castNode(GroupState, planstate), ancestors, es); @@ -2259,6 +2253,10 @@ ExplainNode(PlanState *planstate, List *ancestors, show_memoize_info(castNode(MemoizeState, planstate), ancestors, es); break; + case T_RecursiveUnion: + show_recursive_union_info(castNode(RecursiveUnionState, + planstate), es); + break; default: break; } @@ -2316,6 +2314,11 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainFlushWorkersState(es); es->workers_state = save_workers_state; + /* Allow plugins to print additional information */ + if (explain_per_node_hook) + (*explain_per_node_hook) (planstate, ancestors, relationship, + plan_name, es); + /* * If partition pruning was done during executor initialization, the * number of child plans we'll display below will be less than the number @@ -2470,7 +2473,7 @@ show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es) context = set_deparse_context_plan(es->deparse_cxt, plan, ancestors); - useprefix = list_length(es->rtable) > 1; + useprefix = es->rtable_size > 1; /* Deparse each result column (we now include resjunk ones) */ foreach(lc, plan->targetlist) @@ -2554,7 +2557,7 @@ show_upper_qual(List *qual, const char *qlabel, { bool useprefix; - useprefix = (list_length(es->rtable) > 1 || es->verbose); + useprefix = (es->rtable_size > 1 || es->verbose); show_qual(qual, qlabel, planstate, ancestors, useprefix, es); } @@ -2644,7 +2647,7 @@ show_grouping_sets(PlanState *planstate, Agg *agg, context = set_deparse_context_plan(es->deparse_cxt, planstate->plan, ancestors); - useprefix = (list_length(es->rtable) > 1 || es->verbose); + useprefix = (es->rtable_size > 1 || es->verbose); ExplainOpenGroup("Grouping Sets", "Grouping Sets", false, es); @@ -2784,7 +2787,7 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel, context = set_deparse_context_plan(es->deparse_cxt, plan, ancestors); - useprefix = (list_length(es->rtable) > 1 || es->verbose); + useprefix = (es->rtable_size > 1 || es->verbose); for (keyno = 0; keyno < nkeys; keyno++) { @@ -2878,6 +2881,136 @@ show_sortorder_options(StringInfo buf, Node *sortexpr, } } +/* + * Show the window definition for a WindowAgg node. + */ +static void +show_window_def(WindowAggState *planstate, List *ancestors, ExplainState *es) +{ + WindowAgg *wagg = (WindowAgg *) planstate->ss.ps.plan; + StringInfoData wbuf; + bool needspace = false; + + initStringInfo(&wbuf); + appendStringInfo(&wbuf, "%s AS (", quote_identifier(wagg->winname)); + + /* The key columns refer to the tlist of the child plan */ + ancestors = lcons(wagg, ancestors); + if (wagg->partNumCols > 0) + { + appendStringInfoString(&wbuf, "PARTITION BY "); + show_window_keys(&wbuf, outerPlanState(planstate), + wagg->partNumCols, wagg->partColIdx, + ancestors, es); + needspace = true; + } + if (wagg->ordNumCols > 0) + { + if (needspace) + appendStringInfoChar(&wbuf, ' '); + appendStringInfoString(&wbuf, "ORDER BY "); + show_window_keys(&wbuf, outerPlanState(planstate), + wagg->ordNumCols, wagg->ordColIdx, + ancestors, es); + needspace = true; + } + ancestors = list_delete_first(ancestors); + if (wagg->frameOptions & FRAMEOPTION_NONDEFAULT) + { + List *context; + bool useprefix; + char *framestr; + + /* Set up deparsing context for possible frame expressions */ + context = set_deparse_context_plan(es->deparse_cxt, + (Plan *) wagg, + ancestors); + useprefix = (es->rtable_size > 1 || es->verbose); + framestr = get_window_frame_options_for_explain(wagg->frameOptions, + wagg->startOffset, + wagg->endOffset, + context, + useprefix); + if (needspace) + appendStringInfoChar(&wbuf, ' '); + appendStringInfoString(&wbuf, framestr); + pfree(framestr); + } + appendStringInfoChar(&wbuf, ')'); + ExplainPropertyText("Window", wbuf.data, es); + pfree(wbuf.data); +} + +/* + * Append the keys of a window's PARTITION BY or ORDER BY clause to buf. + * We can't use show_sort_group_keys for this because that's too opinionated + * about how the result will be displayed. + * Note that the "planstate" node should be the WindowAgg's child. + */ +static void +show_window_keys(StringInfo buf, PlanState *planstate, + int nkeys, AttrNumber *keycols, + List *ancestors, ExplainState *es) +{ + Plan *plan = planstate->plan; + List *context; + bool useprefix; + + /* Set up deparsing context */ + context = set_deparse_context_plan(es->deparse_cxt, + plan, + ancestors); + useprefix = (es->rtable_size > 1 || es->verbose); + + for (int keyno = 0; keyno < nkeys; keyno++) + { + /* find key expression in tlist */ + AttrNumber keyresno = keycols[keyno]; + TargetEntry *target = get_tle_by_resno(plan->targetlist, + keyresno); + char *exprstr; + + if (!target) + elog(ERROR, "no tlist entry for key %d", keyresno); + /* Deparse the expression, showing any top-level cast */ + exprstr = deparse_expression((Node *) target->expr, context, + useprefix, true); + if (keyno > 0) + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, exprstr); + pfree(exprstr); + + /* + * We don't attempt to provide sort order information because + * WindowAgg carries equality operators not comparison operators; + * compare show_agg_keys. + */ + } +} + +/* + * Show information on storage method and maximum memory/disk space used. + */ +static void +show_storage_info(char *maxStorageType, int64 maxSpaceUsed, ExplainState *es) +{ + int64 maxSpaceUsedKB = BYTES_TO_KILOBYTES(maxSpaceUsed); + + if (es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyText("Storage", maxStorageType, es); + ExplainPropertyInteger("Maximum Storage", "kB", maxSpaceUsedKB, es); + } + else + { + ExplainIndentText(es); + appendStringInfo(es->str, + "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", + maxStorageType, + maxSpaceUsedKB); + } +} + /* * Show TABLESAMPLE properties */ @@ -2896,7 +3029,7 @@ show_tablesample(TableSampleClause *tsc, PlanState *planstate, context = set_deparse_context_plan(es->deparse_cxt, planstate->plan, ancestors); - useprefix = list_length(es->rtable) > 1; + useprefix = es->rtable_size > 1; /* Get the tablesample method name */ method_name = get_func_name(tsc->tsmhandler); @@ -3333,9 +3466,10 @@ show_hash_info(HashState *hashstate, ExplainState *es) static void show_material_info(MaterialState *mstate, ExplainState *es) { + char *maxStorageType; + int64 maxSpaceUsed; + Tuplestorestate *tupstore = mstate->tuplestorestate; - const char *storageType; - int64 spaceUsedKB; /* * Nothing to show if ANALYZE option wasn't used or if execution didn't @@ -3344,22 +3478,101 @@ show_material_info(MaterialState *mstate, ExplainState *es) if (!es->analyze || tupstore == NULL) return; - storageType = tuplestore_storage_type_name(tupstore); - spaceUsedKB = BYTES_TO_KILOBYTES(tuplestore_space_used(tupstore)); + tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed); + show_storage_info(maxStorageType, maxSpaceUsed, es); +} - if (es->format != EXPLAIN_FORMAT_TEXT) - { - ExplainPropertyText("Storage", storageType, es); - ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es); - } - else - { - ExplainIndentText(es); - appendStringInfo(es->str, - "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", - storageType, - spaceUsedKB); - } +/* + * Show information on WindowAgg node, storage method and maximum memory/disk + * space used. + */ +static void +show_windowagg_info(WindowAggState *winstate, ExplainState *es) +{ + char *maxStorageType; + int64 maxSpaceUsed; + + Tuplestorestate *tupstore = winstate->buffer; + + /* + * Nothing to show if ANALYZE option wasn't used or if execution didn't + * get as far as creating the tuplestore. + */ + if (!es->analyze || tupstore == NULL) + return; + + tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed); + show_storage_info(maxStorageType, maxSpaceUsed, es); +} + +/* + * Show information on CTE Scan node, storage method and maximum memory/disk + * space used. + */ +static void +show_ctescan_info(CteScanState *ctescanstate, ExplainState *es) +{ + char *maxStorageType; + int64 maxSpaceUsed; + + Tuplestorestate *tupstore = ctescanstate->leader->cte_table; + + if (!es->analyze || tupstore == NULL) + return; + + tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed); + show_storage_info(maxStorageType, maxSpaceUsed, es); +} + +/* + * Show information on Table Function Scan node, storage method and maximum + * memory/disk space used. + */ +static void +show_table_func_scan_info(TableFuncScanState *tscanstate, ExplainState *es) +{ + char *maxStorageType; + int64 maxSpaceUsed; + + Tuplestorestate *tupstore = tscanstate->tupstore; + + if (!es->analyze || tupstore == NULL) + return; + + tuplestore_get_stats(tupstore, &maxStorageType, &maxSpaceUsed); + show_storage_info(maxStorageType, maxSpaceUsed, es); +} + +/* + * Show information on Recursive Union node, storage method and maximum + * memory/disk space used. + */ +static void +show_recursive_union_info(RecursiveUnionState *rstate, ExplainState *es) +{ + char *maxStorageType, + *tempStorageType; + int64 maxSpaceUsed, + tempSpaceUsed; + + if (!es->analyze) + return; + + /* + * Recursive union node uses two tuplestores. We employ the storage type + * from one of them which consumed more memory/disk than the other. The + * storage size is sum of the two. + */ + tuplestore_get_stats(rstate->working_table, &tempStorageType, + &tempSpaceUsed); + tuplestore_get_stats(rstate->intermediate_table, &maxStorageType, + &maxSpaceUsed); + + if (tempSpaceUsed > maxSpaceUsed) + maxStorageType = tempStorageType; + + maxSpaceUsed += tempSpaceUsed; + show_storage_info(maxStorageType, maxSpaceUsed, es); } /* @@ -3382,7 +3595,7 @@ show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es) * It's hard to imagine having a memoize node with fewer than 2 RTEs, but * let's just keep the same useprefix logic as elsewhere in this file. */ - useprefix = list_length(es->rtable) > 1 || es->verbose; + useprefix = es->rtable_size > 1 || es->verbose; /* Set up deparsing context */ context = set_deparse_context_plan(es->deparse_cxt, @@ -3400,18 +3613,8 @@ show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es) separator = ", "; } - if (es->format != EXPLAIN_FORMAT_TEXT) - { - ExplainPropertyText("Cache Key", keystr.data, es); - ExplainPropertyText("Cache Mode", mstate->binary_mode ? "binary" : "logical", es); - } - else - { - ExplainIndentText(es); - appendStringInfo(es->str, "Cache Key: %s\n", keystr.data); - ExplainIndentText(es); - appendStringInfo(es->str, "Cache Mode: %s\n", mstate->binary_mode ? "binary" : "logical"); - } + ExplainPropertyText("Cache Key", keystr.data, es); + ExplainPropertyText("Cache Mode", mstate->binary_mode ? "binary" : "logical", es); pfree(keystr.data); @@ -3628,10 +3831,69 @@ show_hashagg_info(AggState *aggstate, ExplainState *es) } /* - * Show exact/lossy pages for a BitmapHeapScan node + * Show the total number of index searches for a + * IndexScan/IndexOnlyScan/BitmapIndexScan node */ static void -show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) +show_indexsearches_info(PlanState *planstate, ExplainState *es) +{ + Plan *plan = planstate->plan; + SharedIndexScanInstrumentation *SharedInfo = NULL; + uint64 nsearches = 0; + + if (!es->analyze) + return; + + /* Initialize counters with stats from the local process first */ + switch (nodeTag(plan)) + { + case T_IndexScan: + { + IndexScanState *indexstate = ((IndexScanState *) planstate); + + nsearches = indexstate->iss_Instrument.nsearches; + SharedInfo = indexstate->iss_SharedInfo; + break; + } + case T_IndexOnlyScan: + { + IndexOnlyScanState *indexstate = ((IndexOnlyScanState *) planstate); + + nsearches = indexstate->ioss_Instrument.nsearches; + SharedInfo = indexstate->ioss_SharedInfo; + break; + } + case T_BitmapIndexScan: + { + BitmapIndexScanState *indexstate = ((BitmapIndexScanState *) planstate); + + nsearches = indexstate->biss_Instrument.nsearches; + SharedInfo = indexstate->biss_SharedInfo; + break; + } + default: + break; + } + + /* Next get the sum of the counters set within each and every process */ + if (SharedInfo) + { + for (int i = 0; i < SharedInfo->num_workers; ++i) + { + IndexScanInstrumentation *winstrument = &SharedInfo->winstrument[i]; + + nsearches += winstrument->nsearches; + } + } + + ExplainPropertyUInteger("Index Searches", NULL, nsearches, es); +} + +/* + * Show exact/lossy pages for a BitmapHeapScan node + */ +static void +show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) { if (!es->analyze) return; @@ -3852,17 +4114,17 @@ show_buffer_usage(ExplainState *es, const BufferUsage *usage) { appendStringInfoString(es->str, " shared"); if (usage->shared_blks_hit > 0) - appendStringInfo(es->str, " hit=%lld", - (long long) usage->shared_blks_hit); + appendStringInfo(es->str, " hit=%" PRId64, + usage->shared_blks_hit); if (usage->shared_blks_read > 0) - appendStringInfo(es->str, " read=%lld", - (long long) usage->shared_blks_read); + appendStringInfo(es->str, " read=%" PRId64, + usage->shared_blks_read); if (usage->shared_blks_dirtied > 0) - appendStringInfo(es->str, " dirtied=%lld", - (long long) usage->shared_blks_dirtied); + appendStringInfo(es->str, " dirtied=%" PRId64, + usage->shared_blks_dirtied); if (usage->shared_blks_written > 0) - appendStringInfo(es->str, " written=%lld", - (long long) usage->shared_blks_written); + appendStringInfo(es->str, " written=%" PRId64, + usage->shared_blks_written); if (has_local || has_temp) appendStringInfoChar(es->str, ','); } @@ -3870,17 +4132,17 @@ show_buffer_usage(ExplainState *es, const BufferUsage *usage) { appendStringInfoString(es->str, " local"); if (usage->local_blks_hit > 0) - appendStringInfo(es->str, " hit=%lld", - (long long) usage->local_blks_hit); + appendStringInfo(es->str, " hit=%" PRId64, + usage->local_blks_hit); if (usage->local_blks_read > 0) - appendStringInfo(es->str, " read=%lld", - (long long) usage->local_blks_read); + appendStringInfo(es->str, " read=%" PRId64, + usage->local_blks_read); if (usage->local_blks_dirtied > 0) - appendStringInfo(es->str, " dirtied=%lld", - (long long) usage->local_blks_dirtied); + appendStringInfo(es->str, " dirtied=%" PRId64, + usage->local_blks_dirtied); if (usage->local_blks_written > 0) - appendStringInfo(es->str, " written=%lld", - (long long) usage->local_blks_written); + appendStringInfo(es->str, " written=%" PRId64, + usage->local_blks_written); if (has_temp) appendStringInfoChar(es->str, ','); } @@ -3888,11 +4150,11 @@ show_buffer_usage(ExplainState *es, const BufferUsage *usage) { appendStringInfoString(es->str, " temp"); if (usage->temp_blks_read > 0) - appendStringInfo(es->str, " read=%lld", - (long long) usage->temp_blks_read); + appendStringInfo(es->str, " read=%" PRId64, + usage->temp_blks_read); if (usage->temp_blks_written > 0) - appendStringInfo(es->str, " written=%lld", - (long long) usage->temp_blks_written); + appendStringInfo(es->str, " written=%" PRId64, + usage->temp_blks_written); } appendStringInfoChar(es->str, '\n'); } @@ -3996,20 +4258,23 @@ show_wal_usage(ExplainState *es, const WalUsage *usage) { /* Show only positive counter values. */ if ((usage->wal_records > 0) || (usage->wal_fpi > 0) || - (usage->wal_bytes > 0)) + (usage->wal_bytes > 0) || (usage->wal_buffers_full > 0)) { ExplainIndentText(es); appendStringInfoString(es->str, "WAL:"); if (usage->wal_records > 0) - appendStringInfo(es->str, " records=%lld", - (long long) usage->wal_records); + appendStringInfo(es->str, " records=%" PRId64, + usage->wal_records); if (usage->wal_fpi > 0) - appendStringInfo(es->str, " fpi=%lld", - (long long) usage->wal_fpi); + appendStringInfo(es->str, " fpi=%" PRId64, + usage->wal_fpi); if (usage->wal_bytes > 0) - appendStringInfo(es->str, " bytes=" UINT64_FORMAT, + appendStringInfo(es->str, " bytes=%" PRIu64, usage->wal_bytes); + if (usage->wal_buffers_full > 0) + appendStringInfo(es->str, " buffers full=%" PRId64, + usage->wal_buffers_full); appendStringInfoChar(es->str, '\n'); } } @@ -4021,6 +4286,8 @@ show_wal_usage(ExplainState *es, const WalUsage *usage) usage->wal_fpi, es); ExplainPropertyUInteger("WAL Bytes", NULL, usage->wal_bytes, es); + ExplainPropertyInteger("WAL Buffers Full", NULL, + usage->wal_buffers_full, es); } } @@ -4286,10 +4553,20 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, break; } - /* Should we explicitly label target relations? */ + /* + * Should we explicitly label target relations? + * + * If there's only one target relation, do not list it if it's the + * relation named in the query, or if it has been pruned. (Normally + * mtstate->resultRelInfo doesn't include pruned relations, but a single + * pruned target relation may be present, if all other target relations + * have been pruned. See ExecInitModifyTable().) + */ labeltargets = (mtstate->mt_nrels > 1 || (mtstate->mt_nrels == 1 && - mtstate->resultRelInfo[0].ri_RangeTableIndex != node->nominalRelation)); + mtstate->resultRelInfo[0].ri_RangeTableIndex != node->nominalRelation && + bms_is_member(mtstate->resultRelInfo[0].ri_RangeTableIndex, + mtstate->ps.state->es_unpruned_relids))); if (labeltargets) ExplainOpenGroup("Target Tables", "Target Tables", false, es); @@ -4698,976 +4975,3 @@ ExplainFlushWorkersState(ExplainState *es) pfree(wstate->worker_state_save); pfree(wstate); } - -/* - * Explain a property, such as sort keys or targets, that takes the form of - * a list of unlabeled items. "data" is a list of C strings. - */ -void -ExplainPropertyList(const char *qlabel, List *data, ExplainState *es) -{ - ListCell *lc; - bool first = true; - - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - ExplainIndentText(es); - appendStringInfo(es->str, "%s: ", qlabel); - foreach(lc, data) - { - if (!first) - appendStringInfoString(es->str, ", "); - appendStringInfoString(es->str, (const char *) lfirst(lc)); - first = false; - } - appendStringInfoChar(es->str, '\n'); - break; - - case EXPLAIN_FORMAT_XML: - ExplainXMLTag(qlabel, X_OPENING, es); - foreach(lc, data) - { - char *str; - - appendStringInfoSpaces(es->str, es->indent * 2 + 2); - appendStringInfoString(es->str, ""); - str = escape_xml((const char *) lfirst(lc)); - appendStringInfoString(es->str, str); - pfree(str); - appendStringInfoString(es->str, "\n"); - } - ExplainXMLTag(qlabel, X_CLOSING, es); - break; - - case EXPLAIN_FORMAT_JSON: - ExplainJSONLineEnding(es); - appendStringInfoSpaces(es->str, es->indent * 2); - escape_json(es->str, qlabel); - appendStringInfoString(es->str, ": ["); - foreach(lc, data) - { - if (!first) - appendStringInfoString(es->str, ", "); - escape_json(es->str, (const char *) lfirst(lc)); - first = false; - } - appendStringInfoChar(es->str, ']'); - break; - - case EXPLAIN_FORMAT_YAML: - ExplainYAMLLineStarting(es); - appendStringInfo(es->str, "%s: ", qlabel); - foreach(lc, data) - { - appendStringInfoChar(es->str, '\n'); - appendStringInfoSpaces(es->str, es->indent * 2 + 2); - appendStringInfoString(es->str, "- "); - escape_yaml(es->str, (const char *) lfirst(lc)); - } - break; - } -} - -/* - * Explain a property that takes the form of a list of unlabeled items within - * another list. "data" is a list of C strings. - */ -void -ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es) -{ - ListCell *lc; - bool first = true; - - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - case EXPLAIN_FORMAT_XML: - ExplainPropertyList(qlabel, data, es); - return; - - case EXPLAIN_FORMAT_JSON: - ExplainJSONLineEnding(es); - appendStringInfoSpaces(es->str, es->indent * 2); - appendStringInfoChar(es->str, '['); - foreach(lc, data) - { - if (!first) - appendStringInfoString(es->str, ", "); - escape_json(es->str, (const char *) lfirst(lc)); - first = false; - } - appendStringInfoChar(es->str, ']'); - break; - - case EXPLAIN_FORMAT_YAML: - ExplainYAMLLineStarting(es); - appendStringInfoString(es->str, "- ["); - foreach(lc, data) - { - if (!first) - appendStringInfoString(es->str, ", "); - escape_yaml(es->str, (const char *) lfirst(lc)); - first = false; - } - appendStringInfoChar(es->str, ']'); - break; - } -} - -/* - * Explain a simple property. - * - * If "numeric" is true, the value is a number (or other value that - * doesn't need quoting in JSON). - * - * If unit is non-NULL the text format will display it after the value. - * - * This usually should not be invoked directly, but via one of the datatype - * specific routines ExplainPropertyText, ExplainPropertyInteger, etc. - */ -static void -ExplainProperty(const char *qlabel, const char *unit, const char *value, - bool numeric, ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - ExplainIndentText(es); - if (unit) - appendStringInfo(es->str, "%s: %s %s\n", qlabel, value, unit); - else - appendStringInfo(es->str, "%s: %s\n", qlabel, value); - break; - - case EXPLAIN_FORMAT_XML: - { - char *str; - - appendStringInfoSpaces(es->str, es->indent * 2); - ExplainXMLTag(qlabel, X_OPENING | X_NOWHITESPACE, es); - str = escape_xml(value); - appendStringInfoString(es->str, str); - pfree(str); - ExplainXMLTag(qlabel, X_CLOSING | X_NOWHITESPACE, es); - appendStringInfoChar(es->str, '\n'); - } - break; - - case EXPLAIN_FORMAT_JSON: - ExplainJSONLineEnding(es); - appendStringInfoSpaces(es->str, es->indent * 2); - escape_json(es->str, qlabel); - appendStringInfoString(es->str, ": "); - if (numeric) - appendStringInfoString(es->str, value); - else - escape_json(es->str, value); - break; - - case EXPLAIN_FORMAT_YAML: - ExplainYAMLLineStarting(es); - appendStringInfo(es->str, "%s: ", qlabel); - if (numeric) - appendStringInfoString(es->str, value); - else - escape_yaml(es->str, value); - break; - } -} - -/* - * Explain a string-valued property. - */ -void -ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es) -{ - ExplainProperty(qlabel, NULL, value, false, es); -} - -/* - * Explain an integer-valued property. - */ -void -ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, - ExplainState *es) -{ - char buf[32]; - - snprintf(buf, sizeof(buf), INT64_FORMAT, value); - ExplainProperty(qlabel, unit, buf, true, es); -} - -/* - * Explain an unsigned integer-valued property. - */ -void -ExplainPropertyUInteger(const char *qlabel, const char *unit, uint64 value, - ExplainState *es) -{ - char buf[32]; - - snprintf(buf, sizeof(buf), UINT64_FORMAT, value); - ExplainProperty(qlabel, unit, buf, true, es); -} - -/* - * Explain a float-valued property, using the specified number of - * fractional digits. - */ -void -ExplainPropertyFloat(const char *qlabel, const char *unit, double value, - int ndigits, ExplainState *es) -{ - char *buf; - - buf = psprintf("%.*f", ndigits, value); - ExplainProperty(qlabel, unit, buf, true, es); - pfree(buf); -} - -/* - * Explain a bool-valued property. - */ -void -ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es) -{ - ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es); -} - -/* - * Open a group of related objects. - * - * objtype is the type of the group object, labelname is its label within - * a containing object (if any). - * - * If labeled is true, the group members will be labeled properties, - * while if it's false, they'll be unlabeled objects. - */ -void -ExplainOpenGroup(const char *objtype, const char *labelname, - bool labeled, ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - ExplainXMLTag(objtype, X_OPENING, es); - es->indent++; - break; - - case EXPLAIN_FORMAT_JSON: - ExplainJSONLineEnding(es); - appendStringInfoSpaces(es->str, 2 * es->indent); - if (labelname) - { - escape_json(es->str, labelname); - appendStringInfoString(es->str, ": "); - } - appendStringInfoChar(es->str, labeled ? '{' : '['); - - /* - * In JSON format, the grouping_stack is an integer list. 0 means - * we've emitted nothing at this grouping level, 1 means we've - * emitted something (and so the next item needs a comma). See - * ExplainJSONLineEnding(). - */ - es->grouping_stack = lcons_int(0, es->grouping_stack); - es->indent++; - break; - - case EXPLAIN_FORMAT_YAML: - - /* - * In YAML format, the grouping stack is an integer list. 0 means - * we've emitted nothing at this grouping level AND this grouping - * level is unlabeled and must be marked with "- ". See - * ExplainYAMLLineStarting(). - */ - ExplainYAMLLineStarting(es); - if (labelname) - { - appendStringInfo(es->str, "%s: ", labelname); - es->grouping_stack = lcons_int(1, es->grouping_stack); - } - else - { - appendStringInfoString(es->str, "- "); - es->grouping_stack = lcons_int(0, es->grouping_stack); - } - es->indent++; - break; - } -} - -/* - * Close a group of related objects. - * Parameters must match the corresponding ExplainOpenGroup call. - */ -void -ExplainCloseGroup(const char *objtype, const char *labelname, - bool labeled, ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - es->indent--; - ExplainXMLTag(objtype, X_CLOSING, es); - break; - - case EXPLAIN_FORMAT_JSON: - es->indent--; - appendStringInfoChar(es->str, '\n'); - appendStringInfoSpaces(es->str, 2 * es->indent); - appendStringInfoChar(es->str, labeled ? '}' : ']'); - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - - case EXPLAIN_FORMAT_YAML: - es->indent--; - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - } -} - -/* - * Open a group of related objects, without emitting actual data. - * - * Prepare the formatting state as though we were beginning a group with - * the identified properties, but don't actually emit anything. Output - * subsequent to this call can be redirected into a separate output buffer, - * and then eventually appended to the main output buffer after doing a - * regular ExplainOpenGroup call (with the same parameters). - * - * The extra "depth" parameter is the new group's depth compared to current. - * It could be more than one, in case the eventual output will be enclosed - * in additional nesting group levels. We assume we don't need to track - * formatting state for those levels while preparing this group's output. - * - * There is no ExplainCloseSetAsideGroup --- in current usage, we always - * pop this state with ExplainSaveGroup. - */ -static void -ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, - bool labeled, int depth, ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - es->indent += depth; - break; - - case EXPLAIN_FORMAT_JSON: - es->grouping_stack = lcons_int(0, es->grouping_stack); - es->indent += depth; - break; - - case EXPLAIN_FORMAT_YAML: - if (labelname) - es->grouping_stack = lcons_int(1, es->grouping_stack); - else - es->grouping_stack = lcons_int(0, es->grouping_stack); - es->indent += depth; - break; - } -} - -/* - * Pop one level of grouping state, allowing for a re-push later. - * - * This is typically used after ExplainOpenSetAsideGroup; pass the - * same "depth" used for that. - * - * This should not emit any output. If state needs to be saved, - * save it at *state_save. Currently, an integer save area is sufficient - * for all formats, but we might need to revisit that someday. - */ -static void -ExplainSaveGroup(ExplainState *es, int depth, int *state_save) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - es->indent -= depth; - break; - - case EXPLAIN_FORMAT_JSON: - es->indent -= depth; - *state_save = linitial_int(es->grouping_stack); - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - - case EXPLAIN_FORMAT_YAML: - es->indent -= depth; - *state_save = linitial_int(es->grouping_stack); - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - } -} - -/* - * Re-push one level of grouping state, undoing the effects of ExplainSaveGroup. - */ -static void -ExplainRestoreGroup(ExplainState *es, int depth, int *state_save) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - es->indent += depth; - break; - - case EXPLAIN_FORMAT_JSON: - es->grouping_stack = lcons_int(*state_save, es->grouping_stack); - es->indent += depth; - break; - - case EXPLAIN_FORMAT_YAML: - es->grouping_stack = lcons_int(*state_save, es->grouping_stack); - es->indent += depth; - break; - } -} - -/* - * Emit a "dummy" group that never has any members. - * - * objtype is the type of the group object, labelname is its label within - * a containing object (if any). - */ -static void -ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - ExplainXMLTag(objtype, X_CLOSE_IMMEDIATE, es); - break; - - case EXPLAIN_FORMAT_JSON: - ExplainJSONLineEnding(es); - appendStringInfoSpaces(es->str, 2 * es->indent); - if (labelname) - { - escape_json(es->str, labelname); - appendStringInfoString(es->str, ": "); - } - escape_json(es->str, objtype); - break; - - case EXPLAIN_FORMAT_YAML: - ExplainYAMLLineStarting(es); - if (labelname) - { - escape_yaml(es->str, labelname); - appendStringInfoString(es->str, ": "); - } - else - { - appendStringInfoString(es->str, "- "); - } - escape_yaml(es->str, objtype); - break; - } -} - -/* - * Emit the start-of-output boilerplate. - * - * This is just enough different from processing a subgroup that we need - * a separate pair of subroutines. - */ -void -ExplainBeginOutput(ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - appendStringInfoString(es->str, - "\n"); - es->indent++; - break; - - case EXPLAIN_FORMAT_JSON: - /* top-level structure is an array of plans */ - appendStringInfoChar(es->str, '['); - es->grouping_stack = lcons_int(0, es->grouping_stack); - es->indent++; - break; - - case EXPLAIN_FORMAT_YAML: - es->grouping_stack = lcons_int(0, es->grouping_stack); - break; - } -} - -/* - * Emit the end-of-output boilerplate. - */ -void -ExplainEndOutput(ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* nothing to do */ - break; - - case EXPLAIN_FORMAT_XML: - es->indent--; - appendStringInfoString(es->str, ""); - break; - - case EXPLAIN_FORMAT_JSON: - es->indent--; - appendStringInfoString(es->str, "\n]"); - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - - case EXPLAIN_FORMAT_YAML: - es->grouping_stack = list_delete_first(es->grouping_stack); - break; - } -} - -/* - * Put an appropriate separator between multiple plans - */ -void -ExplainSeparatePlans(ExplainState *es) -{ - switch (es->format) - { - case EXPLAIN_FORMAT_TEXT: - /* add a blank line */ - appendStringInfoChar(es->str, '\n'); - break; - - case EXPLAIN_FORMAT_XML: - case EXPLAIN_FORMAT_JSON: - case EXPLAIN_FORMAT_YAML: - /* nothing to do */ - break; - } -} - -/* - * Emit opening or closing XML tag. - * - * "flags" must contain X_OPENING, X_CLOSING, or X_CLOSE_IMMEDIATE. - * Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally - * add. - * - * XML restricts tag names more than our other output formats, eg they can't - * contain white space or slashes. Replace invalid characters with dashes, - * so that for example "I/O Read Time" becomes "I-O-Read-Time". - */ -static void -ExplainXMLTag(const char *tagname, int flags, ExplainState *es) -{ - const char *s; - const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."; - - if ((flags & X_NOWHITESPACE) == 0) - appendStringInfoSpaces(es->str, 2 * es->indent); - appendStringInfoCharMacro(es->str, '<'); - if ((flags & X_CLOSING) != 0) - appendStringInfoCharMacro(es->str, '/'); - for (s = tagname; *s; s++) - appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-'); - if ((flags & X_CLOSE_IMMEDIATE) != 0) - appendStringInfoString(es->str, " /"); - appendStringInfoCharMacro(es->str, '>'); - if ((flags & X_NOWHITESPACE) == 0) - appendStringInfoCharMacro(es->str, '\n'); -} - -/* - * Indent a text-format line. - * - * We indent by two spaces per indentation level. However, when emitting - * data for a parallel worker there might already be data on the current line - * (cf. ExplainOpenWorker); in that case, don't indent any more. - */ -static void -ExplainIndentText(ExplainState *es) -{ - Assert(es->format == EXPLAIN_FORMAT_TEXT); - if (es->str->len == 0 || es->str->data[es->str->len - 1] == '\n') - appendStringInfoSpaces(es->str, es->indent * 2); -} - -/* - * Emit a JSON line ending. - * - * JSON requires a comma after each property but the last. To facilitate this, - * in JSON format, the text emitted for each property begins just prior to the - * preceding line-break (and comma, if applicable). - */ -static void -ExplainJSONLineEnding(ExplainState *es) -{ - Assert(es->format == EXPLAIN_FORMAT_JSON); - if (linitial_int(es->grouping_stack) != 0) - appendStringInfoChar(es->str, ','); - else - linitial_int(es->grouping_stack) = 1; - appendStringInfoChar(es->str, '\n'); -} - -/* - * Indent a YAML line. - * - * YAML lines are ordinarily indented by two spaces per indentation level. - * The text emitted for each property begins just prior to the preceding - * line-break, except for the first property in an unlabeled group, for which - * it begins immediately after the "- " that introduces the group. The first - * property of the group appears on the same line as the opening "- ". - */ -static void -ExplainYAMLLineStarting(ExplainState *es) -{ - Assert(es->format == EXPLAIN_FORMAT_YAML); - if (linitial_int(es->grouping_stack) == 0) - { - linitial_int(es->grouping_stack) = 1; - } - else - { - appendStringInfoChar(es->str, '\n'); - appendStringInfoSpaces(es->str, es->indent * 2); - } -} - -/* - * YAML is a superset of JSON; unfortunately, the YAML quoting rules are - * ridiculously complicated -- as documented in sections 5.3 and 7.3.3 of - * http://yaml.org/spec/1.2/spec.html -- so we chose to just quote everything. - * Empty strings, strings with leading or trailing whitespace, and strings - * containing a variety of special characters must certainly be quoted or the - * output is invalid; and other seemingly harmless strings like "0xa" or - * "true" must be quoted, lest they be interpreted as a hexadecimal or Boolean - * constant rather than a string. - */ -static void -escape_yaml(StringInfo buf, const char *str) -{ - escape_json(buf, str); -} - - -/* - * DestReceiver functions for SERIALIZE option - * - * A DestReceiver for query tuples, that serializes passed rows into RowData - * messages while measuring the resources expended and total serialized size, - * while never sending the data to the client. This allows measuring the - * overhead of deTOASTing and datatype out/sendfuncs, which are not otherwise - * exercisable without actually hitting the network. - */ -typedef struct SerializeDestReceiver -{ - DestReceiver pub; - ExplainState *es; /* this EXPLAIN statement's ExplainState */ - int8 format; /* text or binary, like pq wire protocol */ - TupleDesc attrinfo; /* the output tuple desc */ - int nattrs; /* current number of columns */ - FmgrInfo *finfos; /* precomputed call info for output fns */ - MemoryContext tmpcontext; /* per-row temporary memory context */ - StringInfoData buf; /* buffer to hold the constructed message */ - SerializeMetrics metrics; /* collected metrics */ -} SerializeDestReceiver; - -/* - * Get the function lookup info that we'll need for output. - * - * This is a subset of what printtup_prepare_info() does. We don't need to - * cope with format choices varying across columns, so it's slightly simpler. - */ -static void -serialize_prepare_info(SerializeDestReceiver *receiver, - TupleDesc typeinfo, int nattrs) -{ - /* get rid of any old data */ - if (receiver->finfos) - pfree(receiver->finfos); - receiver->finfos = NULL; - - receiver->attrinfo = typeinfo; - receiver->nattrs = nattrs; - if (nattrs <= 0) - return; - - receiver->finfos = (FmgrInfo *) palloc0(nattrs * sizeof(FmgrInfo)); - - for (int i = 0; i < nattrs; i++) - { - FmgrInfo *finfo = receiver->finfos + i; - Form_pg_attribute attr = TupleDescAttr(typeinfo, i); - Oid typoutput; - Oid typsend; - bool typisvarlena; - - if (receiver->format == 0) - { - /* wire protocol format text */ - getTypeOutputInfo(attr->atttypid, - &typoutput, - &typisvarlena); - fmgr_info(typoutput, finfo); - } - else if (receiver->format == 1) - { - /* wire protocol format binary */ - getTypeBinaryOutputInfo(attr->atttypid, - &typsend, - &typisvarlena); - fmgr_info(typsend, finfo); - } - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unsupported format code: %d", receiver->format))); - } -} - -/* - * serializeAnalyzeReceive - collect tuples for EXPLAIN (SERIALIZE) - * - * This should match printtup() in printtup.c as closely as possible, - * except for the addition of measurement code. - */ -static bool -serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self) -{ - TupleDesc typeinfo = slot->tts_tupleDescriptor; - SerializeDestReceiver *myState = (SerializeDestReceiver *) self; - MemoryContext oldcontext; - StringInfo buf = &myState->buf; - int natts = typeinfo->natts; - instr_time start, - end; - BufferUsage instr_start; - - /* only measure time, buffers if requested */ - if (myState->es->timing) - INSTR_TIME_SET_CURRENT(start); - if (myState->es->buffers) - instr_start = pgBufferUsage; - - /* Set or update my derived attribute info, if needed */ - if (myState->attrinfo != typeinfo || myState->nattrs != natts) - serialize_prepare_info(myState, typeinfo, natts); - - /* Make sure the tuple is fully deconstructed */ - slot_getallattrs(slot); - - /* Switch into per-row context so we can recover memory below */ - oldcontext = MemoryContextSwitchTo(myState->tmpcontext); - - /* - * Prepare a DataRow message (note buffer is in per-query context) - * - * Note that we fill a StringInfo buffer the same as printtup() does, so - * as to capture the costs of manipulating the strings accurately. - */ - pq_beginmessage_reuse(buf, PqMsg_DataRow); - - pq_sendint16(buf, natts); - - /* - * send the attributes of this tuple - */ - for (int i = 0; i < natts; i++) - { - FmgrInfo *finfo = myState->finfos + i; - Datum attr = slot->tts_values[i]; - - if (slot->tts_isnull[i]) - { - pq_sendint32(buf, -1); - continue; - } - - if (myState->format == 0) - { - /* Text output */ - char *outputstr; - - outputstr = OutputFunctionCall(finfo, attr); - pq_sendcountedtext(buf, outputstr, strlen(outputstr)); - } - else - { - /* Binary output */ - bytea *outputbytes; - - outputbytes = SendFunctionCall(finfo, attr); - pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ); - pq_sendbytes(buf, VARDATA(outputbytes), - VARSIZE(outputbytes) - VARHDRSZ); - } - } - - /* - * We mustn't call pq_endmessage_reuse(), since that would actually send - * the data to the client. Just count the data, instead. We can leave - * the buffer alone; it'll be reset on the next iteration (as would also - * happen in printtup()). - */ - myState->metrics.bytesSent += buf->len; - - /* Return to caller's context, and flush row's temporary memory */ - MemoryContextSwitchTo(oldcontext); - MemoryContextReset(myState->tmpcontext); - - /* Update timing data */ - if (myState->es->timing) - { - INSTR_TIME_SET_CURRENT(end); - INSTR_TIME_ACCUM_DIFF(myState->metrics.timeSpent, end, start); - } - - /* Update buffer metrics */ - if (myState->es->buffers) - BufferUsageAccumDiff(&myState->metrics.bufferUsage, - &pgBufferUsage, - &instr_start); - - return true; -} - -/* - * serializeAnalyzeStartup - start up the serializeAnalyze receiver - */ -static void -serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo) -{ - SerializeDestReceiver *receiver = (SerializeDestReceiver *) self; - - Assert(receiver->es != NULL); - - switch (receiver->es->serialize) - { - case EXPLAIN_SERIALIZE_NONE: - Assert(false); - break; - case EXPLAIN_SERIALIZE_TEXT: - receiver->format = 0; /* wire protocol format text */ - break; - case EXPLAIN_SERIALIZE_BINARY: - receiver->format = 1; /* wire protocol format binary */ - break; - } - - /* Create per-row temporary memory context */ - receiver->tmpcontext = AllocSetContextCreate(CurrentMemoryContext, - "SerializeTupleReceive", - ALLOCSET_DEFAULT_SIZES); - - /* The output buffer is re-used across rows, as in printtup.c */ - initStringInfo(&receiver->buf); - - /* Initialize results counters */ - memset(&receiver->metrics, 0, sizeof(SerializeMetrics)); - INSTR_TIME_SET_ZERO(receiver->metrics.timeSpent); -} - -/* - * serializeAnalyzeShutdown - shut down the serializeAnalyze receiver - */ -static void -serializeAnalyzeShutdown(DestReceiver *self) -{ - SerializeDestReceiver *receiver = (SerializeDestReceiver *) self; - - if (receiver->finfos) - pfree(receiver->finfos); - receiver->finfos = NULL; - - if (receiver->buf.data) - pfree(receiver->buf.data); - receiver->buf.data = NULL; - - if (receiver->tmpcontext) - MemoryContextDelete(receiver->tmpcontext); - receiver->tmpcontext = NULL; -} - -/* - * serializeAnalyzeDestroy - destroy the serializeAnalyze receiver - */ -static void -serializeAnalyzeDestroy(DestReceiver *self) -{ - pfree(self); -} - -/* - * Build a DestReceiver for EXPLAIN (SERIALIZE) instrumentation. - */ -DestReceiver * -CreateExplainSerializeDestReceiver(ExplainState *es) -{ - SerializeDestReceiver *self; - - self = (SerializeDestReceiver *) palloc0(sizeof(SerializeDestReceiver)); - - self->pub.receiveSlot = serializeAnalyzeReceive; - self->pub.rStartup = serializeAnalyzeStartup; - self->pub.rShutdown = serializeAnalyzeShutdown; - self->pub.rDestroy = serializeAnalyzeDestroy; - self->pub.mydest = DestExplainSerialize; - - self->es = es; - - return (DestReceiver *) self; -} - -/* - * GetSerializationMetrics - collect metrics - * - * We have to be careful here since the receiver could be an IntoRel - * receiver if the subject statement is CREATE TABLE AS. In that - * case, return all-zeroes stats. - */ -static SerializeMetrics -GetSerializationMetrics(DestReceiver *dest) -{ - SerializeMetrics empty; - - if (dest->mydest == DestExplainSerialize) - return ((SerializeDestReceiver *) dest)->metrics; - - memset(&empty, 0, sizeof(SerializeMetrics)); - INSTR_TIME_SET_ZERO(empty.timeSpent); - - return empty; -} diff --git a/src/backend/commands/explain_dr.c b/src/backend/commands/explain_dr.c new file mode 100644 index 0000000000000..5715546cf437b --- /dev/null +++ b/src/backend/commands/explain_dr.c @@ -0,0 +1,310 @@ +/*------------------------------------------------------------------------- + * + * explain_dr.c + * Explain DestReceiver to measure serialization overhead + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * IDENTIFICATION + * src/backend/commands/explain.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "commands/explain.h" +#include "commands/explain_dr.h" +#include "commands/explain_state.h" +#include "libpq/pqformat.h" +#include "libpq/protocol.h" +#include "utils/lsyscache.h" + +/* + * DestReceiver functions for SERIALIZE option + * + * A DestReceiver for query tuples, that serializes passed rows into RowData + * messages while measuring the resources expended and total serialized size, + * while never sending the data to the client. This allows measuring the + * overhead of deTOASTing and datatype out/sendfuncs, which are not otherwise + * exercisable without actually hitting the network. + */ +typedef struct SerializeDestReceiver +{ + DestReceiver pub; + ExplainState *es; /* this EXPLAIN statement's ExplainState */ + int8 format; /* text or binary, like pq wire protocol */ + TupleDesc attrinfo; /* the output tuple desc */ + int nattrs; /* current number of columns */ + FmgrInfo *finfos; /* precomputed call info for output fns */ + MemoryContext tmpcontext; /* per-row temporary memory context */ + StringInfoData buf; /* buffer to hold the constructed message */ + SerializeMetrics metrics; /* collected metrics */ +} SerializeDestReceiver; + +/* + * Get the function lookup info that we'll need for output. + * + * This is a subset of what printtup_prepare_info() does. We don't need to + * cope with format choices varying across columns, so it's slightly simpler. + */ +static void +serialize_prepare_info(SerializeDestReceiver *receiver, + TupleDesc typeinfo, int nattrs) +{ + /* get rid of any old data */ + if (receiver->finfos) + pfree(receiver->finfos); + receiver->finfos = NULL; + + receiver->attrinfo = typeinfo; + receiver->nattrs = nattrs; + if (nattrs <= 0) + return; + + receiver->finfos = (FmgrInfo *) palloc0(nattrs * sizeof(FmgrInfo)); + + for (int i = 0; i < nattrs; i++) + { + FmgrInfo *finfo = receiver->finfos + i; + Form_pg_attribute attr = TupleDescAttr(typeinfo, i); + Oid typoutput; + Oid typsend; + bool typisvarlena; + + if (receiver->format == 0) + { + /* wire protocol format text */ + getTypeOutputInfo(attr->atttypid, + &typoutput, + &typisvarlena); + fmgr_info(typoutput, finfo); + } + else if (receiver->format == 1) + { + /* wire protocol format binary */ + getTypeBinaryOutputInfo(attr->atttypid, + &typsend, + &typisvarlena); + fmgr_info(typsend, finfo); + } + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unsupported format code: %d", receiver->format))); + } +} + +/* + * serializeAnalyzeReceive - collect tuples for EXPLAIN (SERIALIZE) + * + * This should match printtup() in printtup.c as closely as possible, + * except for the addition of measurement code. + */ +static bool +serializeAnalyzeReceive(TupleTableSlot *slot, DestReceiver *self) +{ + TupleDesc typeinfo = slot->tts_tupleDescriptor; + SerializeDestReceiver *myState = (SerializeDestReceiver *) self; + MemoryContext oldcontext; + StringInfo buf = &myState->buf; + int natts = typeinfo->natts; + instr_time start, + end; + BufferUsage instr_start; + + /* only measure time, buffers if requested */ + if (myState->es->timing) + INSTR_TIME_SET_CURRENT(start); + if (myState->es->buffers) + instr_start = pgBufferUsage; + + /* Set or update my derived attribute info, if needed */ + if (myState->attrinfo != typeinfo || myState->nattrs != natts) + serialize_prepare_info(myState, typeinfo, natts); + + /* Make sure the tuple is fully deconstructed */ + slot_getallattrs(slot); + + /* Switch into per-row context so we can recover memory below */ + oldcontext = MemoryContextSwitchTo(myState->tmpcontext); + + /* + * Prepare a DataRow message (note buffer is in per-query context) + * + * Note that we fill a StringInfo buffer the same as printtup() does, so + * as to capture the costs of manipulating the strings accurately. + */ + pq_beginmessage_reuse(buf, PqMsg_DataRow); + + pq_sendint16(buf, natts); + + /* + * send the attributes of this tuple + */ + for (int i = 0; i < natts; i++) + { + FmgrInfo *finfo = myState->finfos + i; + Datum attr = slot->tts_values[i]; + + if (slot->tts_isnull[i]) + { + pq_sendint32(buf, -1); + continue; + } + + if (myState->format == 0) + { + /* Text output */ + char *outputstr; + + outputstr = OutputFunctionCall(finfo, attr); + pq_sendcountedtext(buf, outputstr, strlen(outputstr)); + } + else + { + /* Binary output */ + bytea *outputbytes; + + outputbytes = SendFunctionCall(finfo, attr); + pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ); + pq_sendbytes(buf, VARDATA(outputbytes), + VARSIZE(outputbytes) - VARHDRSZ); + } + } + + /* + * We mustn't call pq_endmessage_reuse(), since that would actually send + * the data to the client. Just count the data, instead. We can leave + * the buffer alone; it'll be reset on the next iteration (as would also + * happen in printtup()). + */ + myState->metrics.bytesSent += buf->len; + + /* Return to caller's context, and flush row's temporary memory */ + MemoryContextSwitchTo(oldcontext); + MemoryContextReset(myState->tmpcontext); + + /* Update timing data */ + if (myState->es->timing) + { + INSTR_TIME_SET_CURRENT(end); + INSTR_TIME_ACCUM_DIFF(myState->metrics.timeSpent, end, start); + } + + /* Update buffer metrics */ + if (myState->es->buffers) + BufferUsageAccumDiff(&myState->metrics.bufferUsage, + &pgBufferUsage, + &instr_start); + + return true; +} + +/* + * serializeAnalyzeStartup - start up the serializeAnalyze receiver + */ +static void +serializeAnalyzeStartup(DestReceiver *self, int operation, TupleDesc typeinfo) +{ + SerializeDestReceiver *receiver = (SerializeDestReceiver *) self; + + Assert(receiver->es != NULL); + + switch (receiver->es->serialize) + { + case EXPLAIN_SERIALIZE_NONE: + Assert(false); + break; + case EXPLAIN_SERIALIZE_TEXT: + receiver->format = 0; /* wire protocol format text */ + break; + case EXPLAIN_SERIALIZE_BINARY: + receiver->format = 1; /* wire protocol format binary */ + break; + } + + /* Create per-row temporary memory context */ + receiver->tmpcontext = AllocSetContextCreate(CurrentMemoryContext, + "SerializeTupleReceive", + ALLOCSET_DEFAULT_SIZES); + + /* The output buffer is re-used across rows, as in printtup.c */ + initStringInfo(&receiver->buf); + + /* Initialize results counters */ + memset(&receiver->metrics, 0, sizeof(SerializeMetrics)); + INSTR_TIME_SET_ZERO(receiver->metrics.timeSpent); +} + +/* + * serializeAnalyzeShutdown - shut down the serializeAnalyze receiver + */ +static void +serializeAnalyzeShutdown(DestReceiver *self) +{ + SerializeDestReceiver *receiver = (SerializeDestReceiver *) self; + + if (receiver->finfos) + pfree(receiver->finfos); + receiver->finfos = NULL; + + if (receiver->buf.data) + pfree(receiver->buf.data); + receiver->buf.data = NULL; + + if (receiver->tmpcontext) + MemoryContextDelete(receiver->tmpcontext); + receiver->tmpcontext = NULL; +} + +/* + * serializeAnalyzeDestroy - destroy the serializeAnalyze receiver + */ +static void +serializeAnalyzeDestroy(DestReceiver *self) +{ + pfree(self); +} + +/* + * Build a DestReceiver for EXPLAIN (SERIALIZE) instrumentation. + */ +DestReceiver * +CreateExplainSerializeDestReceiver(ExplainState *es) +{ + SerializeDestReceiver *self; + + self = (SerializeDestReceiver *) palloc0(sizeof(SerializeDestReceiver)); + + self->pub.receiveSlot = serializeAnalyzeReceive; + self->pub.rStartup = serializeAnalyzeStartup; + self->pub.rShutdown = serializeAnalyzeShutdown; + self->pub.rDestroy = serializeAnalyzeDestroy; + self->pub.mydest = DestExplainSerialize; + + self->es = es; + + return (DestReceiver *) self; +} + +/* + * GetSerializationMetrics - collect metrics + * + * We have to be careful here since the receiver could be an IntoRel + * receiver if the subject statement is CREATE TABLE AS. In that + * case, return all-zeroes stats. + */ +SerializeMetrics +GetSerializationMetrics(DestReceiver *dest) +{ + SerializeMetrics empty; + + if (dest->mydest == DestExplainSerialize) + return ((SerializeDestReceiver *) dest)->metrics; + + memset(&empty, 0, sizeof(SerializeMetrics)); + INSTR_TIME_SET_ZERO(empty.timeSpent); + + return empty; +} diff --git a/src/backend/commands/explain_format.c b/src/backend/commands/explain_format.c new file mode 100644 index 0000000000000..752691d56dbc7 --- /dev/null +++ b/src/backend/commands/explain_format.c @@ -0,0 +1,714 @@ +/*------------------------------------------------------------------------- + * + * explain_format.c + * Format routines for explaining query execution plans + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * IDENTIFICATION + * src/backend/commands/explain_format.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "commands/explain.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" +#include "utils/json.h" +#include "utils/xml.h" + +/* OR-able flags for ExplainXMLTag() */ +#define X_OPENING 0 +#define X_CLOSING 1 +#define X_CLOSE_IMMEDIATE 2 +#define X_NOWHITESPACE 4 + +static void ExplainJSONLineEnding(ExplainState *es); +static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es); +static void ExplainYAMLLineStarting(ExplainState *es); +static void escape_yaml(StringInfo buf, const char *str); + +/* + * Explain a property, such as sort keys or targets, that takes the form of + * a list of unlabeled items. "data" is a list of C strings. + */ +void +ExplainPropertyList(const char *qlabel, List *data, ExplainState *es) +{ + ListCell *lc; + bool first = true; + + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + ExplainIndentText(es); + appendStringInfo(es->str, "%s: ", qlabel); + foreach(lc, data) + { + if (!first) + appendStringInfoString(es->str, ", "); + appendStringInfoString(es->str, (const char *) lfirst(lc)); + first = false; + } + appendStringInfoChar(es->str, '\n'); + break; + + case EXPLAIN_FORMAT_XML: + ExplainXMLTag(qlabel, X_OPENING, es); + foreach(lc, data) + { + char *str; + + appendStringInfoSpaces(es->str, es->indent * 2 + 2); + appendStringInfoString(es->str, ""); + str = escape_xml((const char *) lfirst(lc)); + appendStringInfoString(es->str, str); + pfree(str); + appendStringInfoString(es->str, "\n"); + } + ExplainXMLTag(qlabel, X_CLOSING, es); + break; + + case EXPLAIN_FORMAT_JSON: + ExplainJSONLineEnding(es); + appendStringInfoSpaces(es->str, es->indent * 2); + escape_json(es->str, qlabel); + appendStringInfoString(es->str, ": ["); + foreach(lc, data) + { + if (!first) + appendStringInfoString(es->str, ", "); + escape_json(es->str, (const char *) lfirst(lc)); + first = false; + } + appendStringInfoChar(es->str, ']'); + break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + appendStringInfo(es->str, "%s: ", qlabel); + foreach(lc, data) + { + appendStringInfoChar(es->str, '\n'); + appendStringInfoSpaces(es->str, es->indent * 2 + 2); + appendStringInfoString(es->str, "- "); + escape_yaml(es->str, (const char *) lfirst(lc)); + } + break; + } +} + +/* + * Explain a property that takes the form of a list of unlabeled items within + * another list. "data" is a list of C strings. + */ +void +ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es) +{ + ListCell *lc; + bool first = true; + + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + case EXPLAIN_FORMAT_XML: + ExplainPropertyList(qlabel, data, es); + return; + + case EXPLAIN_FORMAT_JSON: + ExplainJSONLineEnding(es); + appendStringInfoSpaces(es->str, es->indent * 2); + appendStringInfoChar(es->str, '['); + foreach(lc, data) + { + if (!first) + appendStringInfoString(es->str, ", "); + escape_json(es->str, (const char *) lfirst(lc)); + first = false; + } + appendStringInfoChar(es->str, ']'); + break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + appendStringInfoString(es->str, "- ["); + foreach(lc, data) + { + if (!first) + appendStringInfoString(es->str, ", "); + escape_yaml(es->str, (const char *) lfirst(lc)); + first = false; + } + appendStringInfoChar(es->str, ']'); + break; + } +} + +/* + * Explain a simple property. + * + * If "numeric" is true, the value is a number (or other value that + * doesn't need quoting in JSON). + * + * If unit is non-NULL the text format will display it after the value. + * + * This usually should not be invoked directly, but via one of the datatype + * specific routines ExplainPropertyText, ExplainPropertyInteger, etc. + */ +static void +ExplainProperty(const char *qlabel, const char *unit, const char *value, + bool numeric, ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + ExplainIndentText(es); + if (unit) + appendStringInfo(es->str, "%s: %s %s\n", qlabel, value, unit); + else + appendStringInfo(es->str, "%s: %s\n", qlabel, value); + break; + + case EXPLAIN_FORMAT_XML: + { + char *str; + + appendStringInfoSpaces(es->str, es->indent * 2); + ExplainXMLTag(qlabel, X_OPENING | X_NOWHITESPACE, es); + str = escape_xml(value); + appendStringInfoString(es->str, str); + pfree(str); + ExplainXMLTag(qlabel, X_CLOSING | X_NOWHITESPACE, es); + appendStringInfoChar(es->str, '\n'); + } + break; + + case EXPLAIN_FORMAT_JSON: + ExplainJSONLineEnding(es); + appendStringInfoSpaces(es->str, es->indent * 2); + escape_json(es->str, qlabel); + appendStringInfoString(es->str, ": "); + if (numeric) + appendStringInfoString(es->str, value); + else + escape_json(es->str, value); + break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + appendStringInfo(es->str, "%s: ", qlabel); + if (numeric) + appendStringInfoString(es->str, value); + else + escape_yaml(es->str, value); + break; + } +} + +/* + * Explain a string-valued property. + */ +void +ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es) +{ + ExplainProperty(qlabel, NULL, value, false, es); +} + +/* + * Explain an integer-valued property. + */ +void +ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value, + ExplainState *es) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), INT64_FORMAT, value); + ExplainProperty(qlabel, unit, buf, true, es); +} + +/* + * Explain an unsigned integer-valued property. + */ +void +ExplainPropertyUInteger(const char *qlabel, const char *unit, uint64 value, + ExplainState *es) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), UINT64_FORMAT, value); + ExplainProperty(qlabel, unit, buf, true, es); +} + +/* + * Explain a float-valued property, using the specified number of + * fractional digits. + */ +void +ExplainPropertyFloat(const char *qlabel, const char *unit, double value, + int ndigits, ExplainState *es) +{ + char *buf; + + buf = psprintf("%.*f", ndigits, value); + ExplainProperty(qlabel, unit, buf, true, es); + pfree(buf); +} + +/* + * Explain a bool-valued property. + */ +void +ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es) +{ + ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es); +} + +/* + * Open a group of related objects. + * + * objtype is the type of the group object, labelname is its label within + * a containing object (if any). + * + * If labeled is true, the group members will be labeled properties, + * while if it's false, they'll be unlabeled objects. + */ +void +ExplainOpenGroup(const char *objtype, const char *labelname, + bool labeled, ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + ExplainXMLTag(objtype, X_OPENING, es); + es->indent++; + break; + + case EXPLAIN_FORMAT_JSON: + ExplainJSONLineEnding(es); + appendStringInfoSpaces(es->str, 2 * es->indent); + if (labelname) + { + escape_json(es->str, labelname); + appendStringInfoString(es->str, ": "); + } + appendStringInfoChar(es->str, labeled ? '{' : '['); + + /* + * In JSON format, the grouping_stack is an integer list. 0 means + * we've emitted nothing at this grouping level, 1 means we've + * emitted something (and so the next item needs a comma). See + * ExplainJSONLineEnding(). + */ + es->grouping_stack = lcons_int(0, es->grouping_stack); + es->indent++; + break; + + case EXPLAIN_FORMAT_YAML: + + /* + * In YAML format, the grouping stack is an integer list. 0 means + * we've emitted nothing at this grouping level AND this grouping + * level is unlabeled and must be marked with "- ". See + * ExplainYAMLLineStarting(). + */ + ExplainYAMLLineStarting(es); + if (labelname) + { + appendStringInfo(es->str, "%s: ", labelname); + es->grouping_stack = lcons_int(1, es->grouping_stack); + } + else + { + appendStringInfoString(es->str, "- "); + es->grouping_stack = lcons_int(0, es->grouping_stack); + } + es->indent++; + break; + } +} + +/* + * Close a group of related objects. + * Parameters must match the corresponding ExplainOpenGroup call. + */ +void +ExplainCloseGroup(const char *objtype, const char *labelname, + bool labeled, ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + es->indent--; + ExplainXMLTag(objtype, X_CLOSING, es); + break; + + case EXPLAIN_FORMAT_JSON: + es->indent--; + appendStringInfoChar(es->str, '\n'); + appendStringInfoSpaces(es->str, 2 * es->indent); + appendStringInfoChar(es->str, labeled ? '}' : ']'); + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + + case EXPLAIN_FORMAT_YAML: + es->indent--; + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + } +} + +/* + * Open a group of related objects, without emitting actual data. + * + * Prepare the formatting state as though we were beginning a group with + * the identified properties, but don't actually emit anything. Output + * subsequent to this call can be redirected into a separate output buffer, + * and then eventually appended to the main output buffer after doing a + * regular ExplainOpenGroup call (with the same parameters). + * + * The extra "depth" parameter is the new group's depth compared to current. + * It could be more than one, in case the eventual output will be enclosed + * in additional nesting group levels. We assume we don't need to track + * formatting state for those levels while preparing this group's output. + * + * There is no ExplainCloseSetAsideGroup --- in current usage, we always + * pop this state with ExplainSaveGroup. + */ +void +ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, + bool labeled, int depth, ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + es->indent += depth; + break; + + case EXPLAIN_FORMAT_JSON: + es->grouping_stack = lcons_int(0, es->grouping_stack); + es->indent += depth; + break; + + case EXPLAIN_FORMAT_YAML: + if (labelname) + es->grouping_stack = lcons_int(1, es->grouping_stack); + else + es->grouping_stack = lcons_int(0, es->grouping_stack); + es->indent += depth; + break; + } +} + +/* + * Pop one level of grouping state, allowing for a re-push later. + * + * This is typically used after ExplainOpenSetAsideGroup; pass the + * same "depth" used for that. + * + * This should not emit any output. If state needs to be saved, + * save it at *state_save. Currently, an integer save area is sufficient + * for all formats, but we might need to revisit that someday. + */ +void +ExplainSaveGroup(ExplainState *es, int depth, int *state_save) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + es->indent -= depth; + break; + + case EXPLAIN_FORMAT_JSON: + es->indent -= depth; + *state_save = linitial_int(es->grouping_stack); + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + + case EXPLAIN_FORMAT_YAML: + es->indent -= depth; + *state_save = linitial_int(es->grouping_stack); + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + } +} + +/* + * Re-push one level of grouping state, undoing the effects of ExplainSaveGroup. + */ +void +ExplainRestoreGroup(ExplainState *es, int depth, int *state_save) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + es->indent += depth; + break; + + case EXPLAIN_FORMAT_JSON: + es->grouping_stack = lcons_int(*state_save, es->grouping_stack); + es->indent += depth; + break; + + case EXPLAIN_FORMAT_YAML: + es->grouping_stack = lcons_int(*state_save, es->grouping_stack); + es->indent += depth; + break; + } +} + +/* + * Emit a "dummy" group that never has any members. + * + * objtype is the type of the group object, labelname is its label within + * a containing object (if any). + */ +void +ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + ExplainXMLTag(objtype, X_CLOSE_IMMEDIATE, es); + break; + + case EXPLAIN_FORMAT_JSON: + ExplainJSONLineEnding(es); + appendStringInfoSpaces(es->str, 2 * es->indent); + if (labelname) + { + escape_json(es->str, labelname); + appendStringInfoString(es->str, ": "); + } + escape_json(es->str, objtype); + break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + if (labelname) + { + escape_yaml(es->str, labelname); + appendStringInfoString(es->str, ": "); + } + else + { + appendStringInfoString(es->str, "- "); + } + escape_yaml(es->str, objtype); + break; + } +} + +/* + * Emit the start-of-output boilerplate. + * + * This is just enough different from processing a subgroup that we need + * a separate pair of subroutines. + */ +void +ExplainBeginOutput(ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + appendStringInfoString(es->str, + "\n"); + es->indent++; + break; + + case EXPLAIN_FORMAT_JSON: + /* top-level structure is an array of plans */ + appendStringInfoChar(es->str, '['); + es->grouping_stack = lcons_int(0, es->grouping_stack); + es->indent++; + break; + + case EXPLAIN_FORMAT_YAML: + es->grouping_stack = lcons_int(0, es->grouping_stack); + break; + } +} + +/* + * Emit the end-of-output boilerplate. + */ +void +ExplainEndOutput(ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* nothing to do */ + break; + + case EXPLAIN_FORMAT_XML: + es->indent--; + appendStringInfoString(es->str, ""); + break; + + case EXPLAIN_FORMAT_JSON: + es->indent--; + appendStringInfoString(es->str, "\n]"); + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + + case EXPLAIN_FORMAT_YAML: + es->grouping_stack = list_delete_first(es->grouping_stack); + break; + } +} + +/* + * Put an appropriate separator between multiple plans + */ +void +ExplainSeparatePlans(ExplainState *es) +{ + switch (es->format) + { + case EXPLAIN_FORMAT_TEXT: + /* add a blank line */ + appendStringInfoChar(es->str, '\n'); + break; + + case EXPLAIN_FORMAT_XML: + case EXPLAIN_FORMAT_JSON: + case EXPLAIN_FORMAT_YAML: + /* nothing to do */ + break; + } +} + +/* + * Emit opening or closing XML tag. + * + * "flags" must contain X_OPENING, X_CLOSING, or X_CLOSE_IMMEDIATE. + * Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally + * add. + * + * XML restricts tag names more than our other output formats, eg they can't + * contain white space or slashes. Replace invalid characters with dashes, + * so that for example "I/O Read Time" becomes "I-O-Read-Time". + */ +static void +ExplainXMLTag(const char *tagname, int flags, ExplainState *es) +{ + const char *s; + const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."; + + if ((flags & X_NOWHITESPACE) == 0) + appendStringInfoSpaces(es->str, 2 * es->indent); + appendStringInfoCharMacro(es->str, '<'); + if ((flags & X_CLOSING) != 0) + appendStringInfoCharMacro(es->str, '/'); + for (s = tagname; *s; s++) + appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-'); + if ((flags & X_CLOSE_IMMEDIATE) != 0) + appendStringInfoString(es->str, " /"); + appendStringInfoCharMacro(es->str, '>'); + if ((flags & X_NOWHITESPACE) == 0) + appendStringInfoCharMacro(es->str, '\n'); +} + +/* + * Indent a text-format line. + * + * We indent by two spaces per indentation level. However, when emitting + * data for a parallel worker there might already be data on the current line + * (cf. ExplainOpenWorker); in that case, don't indent any more. + */ +void +ExplainIndentText(ExplainState *es) +{ + Assert(es->format == EXPLAIN_FORMAT_TEXT); + if (es->str->len == 0 || es->str->data[es->str->len - 1] == '\n') + appendStringInfoSpaces(es->str, es->indent * 2); +} + +/* + * Emit a JSON line ending. + * + * JSON requires a comma after each property but the last. To facilitate this, + * in JSON format, the text emitted for each property begins just prior to the + * preceding line-break (and comma, if applicable). + */ +static void +ExplainJSONLineEnding(ExplainState *es) +{ + Assert(es->format == EXPLAIN_FORMAT_JSON); + if (linitial_int(es->grouping_stack) != 0) + appendStringInfoChar(es->str, ','); + else + linitial_int(es->grouping_stack) = 1; + appendStringInfoChar(es->str, '\n'); +} + +/* + * Indent a YAML line. + * + * YAML lines are ordinarily indented by two spaces per indentation level. + * The text emitted for each property begins just prior to the preceding + * line-break, except for the first property in an unlabeled group, for which + * it begins immediately after the "- " that introduces the group. The first + * property of the group appears on the same line as the opening "- ". + */ +static void +ExplainYAMLLineStarting(ExplainState *es) +{ + Assert(es->format == EXPLAIN_FORMAT_YAML); + if (linitial_int(es->grouping_stack) == 0) + { + linitial_int(es->grouping_stack) = 1; + } + else + { + appendStringInfoChar(es->str, '\n'); + appendStringInfoSpaces(es->str, es->indent * 2); + } +} + +/* + * YAML is a superset of JSON; unfortunately, the YAML quoting rules are + * ridiculously complicated -- as documented in sections 5.3 and 7.3.3 of + * http://yaml.org/spec/1.2/spec.html -- so we chose to just quote everything. + * Empty strings, strings with leading or trailing whitespace, and strings + * containing a variety of special characters must certainly be quoted or the + * output is invalid; and other seemingly harmless strings like "0xa" or + * "true" must be quoted, lest they be interpreted as a hexadecimal or Boolean + * constant rather than a string. + */ +static void +escape_yaml(StringInfo buf, const char *str) +{ + escape_json(buf, str); +} diff --git a/src/backend/commands/explain_state.c b/src/backend/commands/explain_state.c new file mode 100644 index 0000000000000..60d98d63a62e2 --- /dev/null +++ b/src/backend/commands/explain_state.c @@ -0,0 +1,378 @@ +/*------------------------------------------------------------------------- + * + * explain_state.c + * Code for initializing and accessing ExplainState objects + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * In-core options have hard-coded fields inside ExplainState; e.g. if + * the user writes EXPLAIN (BUFFERS) then ExplainState's "buffers" member + * will be set to true. Extensions can also register options using + * RegisterExtensionExplainOption; so that e.g. EXPLAIN (BICYCLE 'red') + * will invoke a designated handler that knows what the legal values are + * for the BICYCLE option. However, it's not enough for an extension to be + * able to parse new options: it also needs a place to store the results + * of that parsing, and an ExplainState has no 'bicycle' field. + * + * To solve this problem, an ExplainState can contain an array of opaque + * pointers, one per extension. An extension can use GetExplainExtensionId + * to acquire an integer ID to acquire an offset into this array that is + * reserved for its exclusive use, and then use GetExplainExtensionState + * and SetExplainExtensionState to read and write its own private state + * within an ExplainState. + * + * Note that there is no requirement that the name of the option match + * the name of the extension; e.g. a pg_explain_conveyance extension could + * implement options for BICYCLE, MONORAIL, etc. + * + * IDENTIFICATION + * src/backend/commands/explain_state.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "commands/defrem.h" +#include "commands/explain.h" +#include "commands/explain_state.h" + +/* Hook to perform additional EXPLAIN options validation */ +explain_validate_options_hook_type explain_validate_options_hook = NULL; + +typedef struct +{ + const char *option_name; + ExplainOptionHandler option_handler; +} ExplainExtensionOption; + +static const char **ExplainExtensionNameArray = NULL; +static int ExplainExtensionNamesAssigned = 0; +static int ExplainExtensionNamesAllocated = 0; + +static ExplainExtensionOption *ExplainExtensionOptionArray = NULL; +static int ExplainExtensionOptionsAssigned = 0; +static int ExplainExtensionOptionsAllocated = 0; + +/* + * Create a new ExplainState struct initialized with default options. + */ +ExplainState * +NewExplainState(void) +{ + ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState)); + + /* Set default options (most fields can be left as zeroes). */ + es->costs = true; + /* Prepare output buffer. */ + es->str = makeStringInfo(); + + return es; +} + +/* + * Parse a list of EXPLAIN options and update an ExplainState accordingly. + */ +void +ParseExplainOptionList(ExplainState *es, List *options, ParseState *pstate) +{ + ListCell *lc; + bool timing_set = false; + bool buffers_set = false; + bool summary_set = false; + + /* Parse options list. */ + foreach(lc, options) + { + DefElem *opt = (DefElem *) lfirst(lc); + + if (strcmp(opt->defname, "analyze") == 0) + es->analyze = defGetBoolean(opt); + else if (strcmp(opt->defname, "verbose") == 0) + es->verbose = defGetBoolean(opt); + else if (strcmp(opt->defname, "costs") == 0) + es->costs = defGetBoolean(opt); + else if (strcmp(opt->defname, "buffers") == 0) + { + buffers_set = true; + es->buffers = defGetBoolean(opt); + } + else if (strcmp(opt->defname, "wal") == 0) + es->wal = defGetBoolean(opt); + else if (strcmp(opt->defname, "settings") == 0) + es->settings = defGetBoolean(opt); + else if (strcmp(opt->defname, "generic_plan") == 0) + es->generic = defGetBoolean(opt); + else if (strcmp(opt->defname, "timing") == 0) + { + timing_set = true; + es->timing = defGetBoolean(opt); + } + else if (strcmp(opt->defname, "summary") == 0) + { + summary_set = true; + es->summary = defGetBoolean(opt); + } + else if (strcmp(opt->defname, "memory") == 0) + es->memory = defGetBoolean(opt); + else if (strcmp(opt->defname, "serialize") == 0) + { + if (opt->arg) + { + char *p = defGetString(opt); + + if (strcmp(p, "off") == 0 || strcmp(p, "none") == 0) + es->serialize = EXPLAIN_SERIALIZE_NONE; + else if (strcmp(p, "text") == 0) + es->serialize = EXPLAIN_SERIALIZE_TEXT; + else if (strcmp(p, "binary") == 0) + es->serialize = EXPLAIN_SERIALIZE_BINARY; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"", + opt->defname, p), + parser_errposition(pstate, opt->location))); + } + else + { + /* SERIALIZE without an argument is taken as 'text' */ + es->serialize = EXPLAIN_SERIALIZE_TEXT; + } + } + else if (strcmp(opt->defname, "format") == 0) + { + char *p = defGetString(opt); + + if (strcmp(p, "text") == 0) + es->format = EXPLAIN_FORMAT_TEXT; + else if (strcmp(p, "xml") == 0) + es->format = EXPLAIN_FORMAT_XML; + else if (strcmp(p, "json") == 0) + es->format = EXPLAIN_FORMAT_JSON; + else if (strcmp(p, "yaml") == 0) + es->format = EXPLAIN_FORMAT_YAML; + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized value for EXPLAIN option \"%s\": \"%s\"", + opt->defname, p), + parser_errposition(pstate, opt->location))); + } + else if (!ApplyExtensionExplainOption(es, opt, pstate)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized EXPLAIN option \"%s\"", + opt->defname), + parser_errposition(pstate, opt->location))); + } + + /* check that WAL is used with EXPLAIN ANALYZE */ + if (es->wal && !es->analyze) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("EXPLAIN option %s requires ANALYZE", "WAL"))); + + /* if the timing was not set explicitly, set default value */ + es->timing = (timing_set) ? es->timing : es->analyze; + + /* if the buffers was not set explicitly, set default value */ + es->buffers = (buffers_set) ? es->buffers : es->analyze; + + /* check that timing is used with EXPLAIN ANALYZE */ + if (es->timing && !es->analyze) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("EXPLAIN option %s requires ANALYZE", "TIMING"))); + + /* check that serialize is used with EXPLAIN ANALYZE */ + if (es->serialize != EXPLAIN_SERIALIZE_NONE && !es->analyze) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("EXPLAIN option %s requires ANALYZE", "SERIALIZE"))); + + /* check that GENERIC_PLAN is not used with EXPLAIN ANALYZE */ + if (es->generic && es->analyze) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together"))); + + /* if the summary was not set explicitly, set default value */ + es->summary = (summary_set) ? es->summary : es->analyze; + + /* plugin specific option validation */ + if (explain_validate_options_hook) + (*explain_validate_options_hook) (es, options, pstate); +} + +/* + * Map the name of an EXPLAIN extension to an integer ID. + * + * Within the lifetime of a particular backend, the same name will be mapped + * to the same ID every time. IDs are not stable across backends. Use the ID + * that you get from this function to call GetExplainExtensionState and + * SetExplainExtensionState. + * + * extension_name is assumed to be a constant string or allocated in storage + * that will never be freed. + */ +int +GetExplainExtensionId(const char *extension_name) +{ + /* Search for an existing extension by this name; if found, return ID. */ + for (int i = 0; i < ExplainExtensionNamesAssigned; ++i) + if (strcmp(ExplainExtensionNameArray[i], extension_name) == 0) + return i; + + /* If there is no array yet, create one. */ + if (ExplainExtensionNameArray == NULL) + { + ExplainExtensionNamesAllocated = 16; + ExplainExtensionNameArray = (const char **) + MemoryContextAlloc(TopMemoryContext, + ExplainExtensionNamesAllocated + * sizeof(char *)); + } + + /* If there's an array but it's currently full, expand it. */ + if (ExplainExtensionNamesAssigned >= ExplainExtensionNamesAllocated) + { + int i = pg_nextpower2_32(ExplainExtensionNamesAssigned + 1); + + ExplainExtensionNameArray = (const char **) + repalloc(ExplainExtensionNameArray, i * sizeof(char *)); + ExplainExtensionNamesAllocated = i; + } + + /* Assign and return new ID. */ + ExplainExtensionNameArray[ExplainExtensionNamesAssigned] = extension_name; + return ExplainExtensionNamesAssigned++; +} + +/* + * Get extension-specific state from an ExplainState. + * + * See comments for SetExplainExtensionState, below. + */ +void * +GetExplainExtensionState(ExplainState *es, int extension_id) +{ + Assert(extension_id >= 0); + + if (extension_id >= es->extension_state_allocated) + return NULL; + + return es->extension_state[extension_id]; +} + +/* + * Store extension-specific state into an ExplainState. + * + * To use this function, first obtain an integer extension_id using + * GetExplainExtensionId. Then use this function to store an opaque pointer + * in the ExplainState. Later, you can retrieve the opaque pointer using + * GetExplainExtensionState. + */ +void +SetExplainExtensionState(ExplainState *es, int extension_id, void *opaque) +{ + Assert(extension_id >= 0); + + /* If there is no array yet, create one. */ + if (es->extension_state == NULL) + { + es->extension_state_allocated = 16; + es->extension_state = + palloc0(es->extension_state_allocated * sizeof(void *)); + } + + /* If there's an array but it's currently full, expand it. */ + if (extension_id >= es->extension_state_allocated) + { + int i; + + i = pg_nextpower2_32(es->extension_state_allocated + 1); + es->extension_state = (void **) + repalloc0(es->extension_state, + es->extension_state_allocated * sizeof(void *), + i * sizeof(void *)); + es->extension_state_allocated = i; + } + + es->extension_state[extension_id] = opaque; +} + +/* + * Register a new EXPLAIN option. + * + * When option_name is used as an EXPLAIN option, handler will be called and + * should update the ExplainState passed to it. See comments at top of file + * for a more detailed explanation. + * + * option_name is assumed to be a constant string or allocated in storage + * that will never be freed. + */ +void +RegisterExtensionExplainOption(const char *option_name, + ExplainOptionHandler handler) +{ + ExplainExtensionOption *exopt; + + /* Search for an existing option by this name; if found, update handler. */ + for (int i = 0; i < ExplainExtensionOptionsAssigned; ++i) + { + if (strcmp(ExplainExtensionOptionArray[i].option_name, + option_name) == 0) + { + ExplainExtensionOptionArray[i].option_handler = handler; + return; + } + } + + /* If there is no array yet, create one. */ + if (ExplainExtensionOptionArray == NULL) + { + ExplainExtensionOptionsAllocated = 16; + ExplainExtensionOptionArray = (ExplainExtensionOption *) + MemoryContextAlloc(TopMemoryContext, + ExplainExtensionOptionsAllocated + * sizeof(char *)); + } + + /* If there's an array but it's currently full, expand it. */ + if (ExplainExtensionOptionsAssigned >= ExplainExtensionOptionsAllocated) + { + int i = pg_nextpower2_32(ExplainExtensionOptionsAssigned + 1); + + ExplainExtensionOptionArray = (ExplainExtensionOption *) + repalloc(ExplainExtensionOptionArray, i * sizeof(char *)); + ExplainExtensionOptionsAllocated = i; + } + + /* Assign and return new ID. */ + exopt = &ExplainExtensionOptionArray[ExplainExtensionOptionsAssigned++]; + exopt->option_name = option_name; + exopt->option_handler = handler; +} + +/* + * Apply an EXPLAIN option registered by an extension. + * + * If no extension has registered the named option, returns false. Otherwise, + * calls the appropriate handler function and then returns true. + */ +bool +ApplyExtensionExplainOption(ExplainState *es, DefElem *opt, ParseState *pstate) +{ + for (int i = 0; i < ExplainExtensionOptionsAssigned; ++i) + { + if (strcmp(ExplainExtensionOptionArray[i].option_name, + opt->defname) == 0) + { + ExplainExtensionOptionArray[i].option_handler(es, opt, pstate); + return true; + } + } + + return false; +} diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 1643c8c69a0d8..e6f9ab6dfd66b 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -12,7 +12,7 @@ * postgresql.conf. An extension also has an installation script file, * containing SQL commands to create the extension's objects. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -54,6 +54,8 @@ #include "funcapi.h" #include "mb/pg_wchar.h" #include "miscadmin.h" +#include "nodes/pg_list.h" +#include "nodes/queryjumble.h" #include "storage/fd.h" #include "tcop/utility.h" #include "utils/acl.h" @@ -64,9 +66,13 @@ #include "utils/memutils.h" #include "utils/rel.h" #include "utils/snapmgr.h" +#include "utils/syscache.h" #include "utils/varlena.h" +/* GUC */ +char *Extension_control_path; + /* Globally visible state variables */ bool creating_extension = false; Oid CurrentExtensionObject = InvalidOid; @@ -77,6 +83,9 @@ Oid CurrentExtensionObject = InvalidOid; typedef struct ExtensionControlFile { char *name; /* name of the extension */ + char *basedir; /* base directory where control and script + * files are located */ + char *control_dir; /* directory where control file was found */ char *directory; /* directory for script files */ char *default_version; /* default install target version, if any */ char *module_pathname; /* string to substitute for @@ -106,6 +115,17 @@ typedef struct ExtensionVersionInfo struct ExtensionVersionInfo *previous; /* current best predecessor */ } ExtensionVersionInfo; +/* + * Information for script_error_callback() + */ +typedef struct +{ + const char *sql; /* entire script file contents */ + const char *filename; /* script file pathname */ + ParseLoc stmt_location; /* current stmt start loc, or -1 if unknown */ + ParseLoc stmt_len; /* length in bytes; 0 means "rest of string" */ +} script_error_callback_arg; + /* Local functions */ static List *find_update_path(List *evi_list, ExtensionVersionInfo *evi_start, @@ -133,7 +153,9 @@ static void ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt, ObjectAddress extension, ObjectAddress object); static char *read_whole_file(const char *filename, int *length); +static ExtensionControlFile *new_ExtensionControlFile(const char *extname); +char *find_in_paths(const char *basename, List *paths); /* * get_extension_oid - given an extension name, look up the OID @@ -145,32 +167,9 @@ Oid get_extension_oid(const char *extname, bool missing_ok) { Oid result; - Relation rel; - SysScanDesc scandesc; - HeapTuple tuple; - ScanKeyData entry[1]; - rel = table_open(ExtensionRelationId, AccessShareLock); - - ScanKeyInit(&entry[0], - Anum_pg_extension_extname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(extname)); - - scandesc = systable_beginscan(rel, ExtensionNameIndexId, true, - NULL, 1, entry); - - tuple = systable_getnext(scandesc); - - /* We assume that there can be at most one matching tuple */ - if (HeapTupleIsValid(tuple)) - result = ((Form_pg_extension) GETSTRUCT(tuple))->oid; - else - result = InvalidOid; - - systable_endscan(scandesc); - - table_close(rel, AccessShareLock); + result = GetSysCacheOid1(EXTENSIONNAME, Anum_pg_extension_oid, + CStringGetDatum(extname)); if (!OidIsValid(result) && !missing_ok) ereport(ERROR, @@ -190,32 +189,15 @@ char * get_extension_name(Oid ext_oid) { char *result; - Relation rel; - SysScanDesc scandesc; HeapTuple tuple; - ScanKeyData entry[1]; - - rel = table_open(ExtensionRelationId, AccessShareLock); - - ScanKeyInit(&entry[0], - Anum_pg_extension_oid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(ext_oid)); - - scandesc = systable_beginscan(rel, ExtensionOidIndexId, true, - NULL, 1, entry); - - tuple = systable_getnext(scandesc); - /* We assume that there can be at most one matching tuple */ - if (HeapTupleIsValid(tuple)) - result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname)); - else - result = NULL; + tuple = SearchSysCache1(EXTENSIONOID, ObjectIdGetDatum(ext_oid)); - systable_endscan(scandesc); + if (!HeapTupleIsValid(tuple)) + return NULL; - table_close(rel, AccessShareLock); + result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname)); + ReleaseSysCache(tuple); return result; } @@ -229,32 +211,15 @@ Oid get_extension_schema(Oid ext_oid) { Oid result; - Relation rel; - SysScanDesc scandesc; HeapTuple tuple; - ScanKeyData entry[1]; - rel = table_open(ExtensionRelationId, AccessShareLock); + tuple = SearchSysCache1(EXTENSIONOID, ObjectIdGetDatum(ext_oid)); - ScanKeyInit(&entry[0], - Anum_pg_extension_oid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(ext_oid)); + if (!HeapTupleIsValid(tuple)) + return InvalidOid; - scandesc = systable_beginscan(rel, ExtensionOidIndexId, true, - NULL, 1, entry); - - tuple = systable_getnext(scandesc); - - /* We assume that there can be at most one matching tuple */ - if (HeapTupleIsValid(tuple)) - result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace; - else - result = InvalidOid; - - systable_endscan(scandesc); - - table_close(rel, AccessShareLock); + result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace; + ReleaseSysCache(tuple); return result; } @@ -372,29 +337,99 @@ is_extension_script_filename(const char *filename) return (extension != NULL) && (strcmp(extension, ".sql") == 0); } -static char * -get_extension_control_directory(void) +/* + * Return a list of directories declared on extension_control_path GUC. + */ +static List * +get_extension_control_directories(void) { char sharepath[MAXPGPATH]; - char *result; + char *system_dir; + char *ecp; + List *paths = NIL; get_share_path(my_exec_path, sharepath); - result = (char *) palloc(MAXPGPATH); - snprintf(result, MAXPGPATH, "%s/extension", sharepath); - return result; + system_dir = psprintf("%s/extension", sharepath); + + if (strlen(Extension_control_path) == 0) + { + paths = lappend(paths, system_dir); + } + else + { + /* Duplicate the string so we can modify it */ + ecp = pstrdup(Extension_control_path); + + for (;;) + { + int len; + char *mangled; + char *piece = first_path_var_separator(ecp); + + /* Get the length of the next path on ecp */ + if (piece == NULL) + len = strlen(ecp); + else + len = piece - ecp; + + /* Copy the next path found on ecp */ + piece = palloc(len + 1); + strlcpy(piece, ecp, len + 1); + + /* + * Substitute the path macro if needed or append "extension" + * suffix if it is a custom extension control path. + */ + if (strcmp(piece, "$system") == 0) + mangled = substitute_path_macro(piece, "$system", system_dir); + else + mangled = psprintf("%s/extension", piece); + + pfree(piece); + + /* Canonicalize the path based on the OS and add to the list */ + canonicalize_path(mangled); + paths = lappend(paths, mangled); + + /* Break if ecp is empty or move to the next path on ecp */ + if (ecp[len] == '\0') + break; + else + ecp += len + 1; + } + } + + return paths; } +/* + * Find control file for extension with name in control->name, looking in the + * path. Return the full file name, or NULL if not found. If found, the + * directory is recorded in control->control_dir. + */ static char * -get_extension_control_filename(const char *extname) +find_extension_control_filename(ExtensionControlFile *control) { - char sharepath[MAXPGPATH]; + char *basename; char *result; + List *paths; - get_share_path(my_exec_path, sharepath); - result = (char *) palloc(MAXPGPATH); - snprintf(result, MAXPGPATH, "%s/extension/%s.control", - sharepath, extname); + Assert(control->name); + + basename = psprintf("%s.control", control->name); + + paths = get_extension_control_directories(); + result = find_in_paths(basename, paths); + + if (result) + { + const char *p; + + p = strrchr(result, '/'); + Assert(p); + control->control_dir = pnstrdup(result, p - result); + } return result; } @@ -402,24 +437,20 @@ get_extension_control_filename(const char *extname) static char * get_extension_script_directory(ExtensionControlFile *control) { - char sharepath[MAXPGPATH]; - char *result; - /* * The directory parameter can be omitted, absolute, or relative to the - * installation's share directory. + * installation's base directory, which can be the sharedir or a custom + * path that it was set extension_control_path. It depends where the + * .control file was found. */ if (!control->directory) - return get_extension_control_directory(); + return pstrdup(control->control_dir); if (is_absolute_path(control->directory)) return pstrdup(control->directory); - get_share_path(my_exec_path, sharepath); - result = (char *) palloc(MAXPGPATH); - snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory); - - return result; + Assert(control->basedir != NULL); + return psprintf("%s/%s", control->basedir, control->directory); } static char * @@ -468,6 +499,11 @@ get_extension_script_filename(ExtensionControlFile *control, * fields of *control. We parse primary file if version == NULL, * else the optional auxiliary file for that version. * + * The control file will be search on Extension_control_path paths if + * control->control_dir is NULL, otherwise it will use the value of control_dir + * to read and parse the .control file, so it assume that the control_dir is a + * valid path for the control file being parsed. + * * Control files are supposed to be very short, half a dozen lines, * so we don't worry about memory allocation risks here. Also we don't * worry about what encoding it's in; all values are expected to be ASCII. @@ -488,27 +524,43 @@ parse_extension_control_file(ExtensionControlFile *control, if (version) filename = get_extension_aux_control_filename(control, version); else - filename = get_extension_control_filename(control->name); + { + /* + * If control_dir is already set, use it, else do a path search. + */ + if (control->control_dir) + { + filename = psprintf("%s/%s.control", control->control_dir, control->name); + } + else + filename = find_extension_control_filename(control); + } + + if (!filename) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("extension \"%s\" is not available", control->name), + errhint("The extension must first be installed on the system where PostgreSQL is running."))); + } + + /* Assert that the control_dir ends with /extension */ + Assert(control->control_dir != NULL); + Assert(strcmp(control->control_dir + strlen(control->control_dir) - strlen("/extension"), "/extension") == 0); + + control->basedir = pnstrdup( + control->control_dir, + strlen(control->control_dir) - strlen("/extension")); if ((file = AllocateFile(filename, "r")) == NULL) { - if (errno == ENOENT) + /* no complaint for missing auxiliary file */ + if (errno == ENOENT && version) { - /* no complaint for missing auxiliary file */ - if (version) - { - pfree(filename); - return; - } - - /* missing control file indicates extension is not installed */ - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("extension \"%s\" is not available", control->name), - errdetail("Could not open extension control file \"%s\": %m.", - filename), - errhint("The extension must first be installed on the system where PostgreSQL is running."))); + pfree(filename); + return; } + ereport(ERROR, (errcode_for_file_access(), errmsg("could not open extension control file \"%s\": %m", @@ -647,17 +699,7 @@ parse_extension_control_file(ExtensionControlFile *control, static ExtensionControlFile * read_extension_control_file(const char *extname) { - ExtensionControlFile *control; - - /* - * Set up default values. Pointer fields are initially null. - */ - control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile)); - control->name = pstrdup(extname); - control->relocatable = false; - control->superuser = true; - control->trusted = false; - control->encoding = -1; + ExtensionControlFile *control = new_ExtensionControlFile(extname); /* * Parse the primary control file. @@ -726,9 +768,143 @@ read_extension_script_file(const ExtensionControlFile *control, return dest_str; } +/* + * error context callback for failures in script-file execution + */ +static void +script_error_callback(void *arg) +{ + script_error_callback_arg *callback_arg = (script_error_callback_arg *) arg; + const char *query = callback_arg->sql; + int location = callback_arg->stmt_location; + int len = callback_arg->stmt_len; + int syntaxerrposition; + const char *lastslash; + + /* + * If there is a syntax error position, convert to internal syntax error; + * otherwise report the current query as an item of context stack. + * + * Note: we'll provide no context except the filename if there's neither + * an error position nor any known current query. That shouldn't happen + * though: all errors reported during raw parsing should come with an + * error position. + */ + syntaxerrposition = geterrposition(); + if (syntaxerrposition > 0) + { + /* + * If we do not know the bounds of the current statement (as would + * happen for an error occurring during initial raw parsing), we have + * to use a heuristic to decide how much of the script to show. We'll + * also use the heuristic in the unlikely case that syntaxerrposition + * is outside what we think the statement bounds are. + */ + if (location < 0 || syntaxerrposition < location || + (len > 0 && syntaxerrposition > location + len)) + { + /* + * Our heuristic is pretty simple: look for semicolon-newline + * sequences, and break at the last one strictly before + * syntaxerrposition and the first one strictly after. It's + * certainly possible to fool this with semicolon-newline embedded + * in a string literal, but it seems better to do this than to + * show the entire extension script. + * + * Notice we cope with Windows-style newlines (\r\n) regardless of + * platform. This is because there might be such newlines in + * script files on other platforms. + */ + int slen = strlen(query); + + location = len = 0; + for (int loc = 0; loc < slen; loc++) + { + if (query[loc] != ';') + continue; + if (query[loc + 1] == '\r') + loc++; + if (query[loc + 1] == '\n') + { + int bkpt = loc + 2; + + if (bkpt < syntaxerrposition) + location = bkpt; + else if (bkpt > syntaxerrposition) + { + len = bkpt - location; + break; /* no need to keep searching */ + } + } + } + } + + /* Trim leading/trailing whitespace, for consistency */ + query = CleanQuerytext(query, &location, &len); + + /* + * Adjust syntaxerrposition. It shouldn't be pointing into the + * whitespace we just trimmed, but cope if it is. + */ + syntaxerrposition -= location; + if (syntaxerrposition < 0) + syntaxerrposition = 0; + else if (syntaxerrposition > len) + syntaxerrposition = len; + + /* And report. */ + errposition(0); + internalerrposition(syntaxerrposition); + internalerrquery(pnstrdup(query, len)); + } + else if (location >= 0) + { + /* + * Since no syntax cursor will be shown, it's okay and helpful to trim + * the reported query string to just the current statement. + */ + query = CleanQuerytext(query, &location, &len); + errcontext("SQL statement \"%.*s\"", len, query); + } + + /* + * Trim the reported file name to remove the path. We know that + * get_extension_script_filename() inserted a '/', regardless of whether + * we're on Windows. + */ + lastslash = strrchr(callback_arg->filename, '/'); + if (lastslash) + lastslash++; + else + lastslash = callback_arg->filename; /* shouldn't happen, but cope */ + + /* + * If we have a location (which, as said above, we really always should) + * then report a line number to aid in localizing problems in big scripts. + */ + if (location >= 0) + { + int linenumber = 1; + + for (query = callback_arg->sql; *query; query++) + { + if (--location < 0) + break; + if (*query == '\n') + linenumber++; + } + errcontext("extension script file \"%s\", near line %d", + lastslash, linenumber); + } + else + errcontext("extension script file \"%s\"", lastslash); +} + /* * Execute given SQL string. * + * The filename the string came from is also provided, for error reporting. + * * Note: it's tempting to just use SPI to execute the string, but that does * not work very well. The really serious problem is that SPI will parse, * analyze, and plan the whole string before executing any of it; of course @@ -738,12 +914,27 @@ read_extension_script_file(const ExtensionControlFile *control, * could be very long. */ static void -execute_sql_string(const char *sql) +execute_sql_string(const char *sql, const char *filename) { + script_error_callback_arg callback_arg; + ErrorContextCallback scripterrcontext; List *raw_parsetree_list; DestReceiver *dest; ListCell *lc1; + /* + * Setup error traceback support for ereport(). + */ + callback_arg.sql = sql; + callback_arg.filename = filename; + callback_arg.stmt_location = -1; + callback_arg.stmt_len = -1; + + scripterrcontext.callback = script_error_callback; + scripterrcontext.arg = (void *) &callback_arg; + scripterrcontext.previous = error_context_stack; + error_context_stack = &scripterrcontext; + /* * Parse the SQL string into a list of raw parse trees. */ @@ -765,6 +956,10 @@ execute_sql_string(const char *sql) List *stmt_list; ListCell *lc2; + /* Report location of this query for error context callback */ + callback_arg.stmt_location = parsetree->stmt_location; + callback_arg.stmt_len = parsetree->stmt_len; + /* * We do the work for each parsetree in a short-lived context, to * limit the memory used when there are many commands in the string. @@ -803,7 +998,7 @@ execute_sql_string(const char *sql) dest, NULL, NULL, 0); ExecutorStart(qdesc, 0); - ExecutorRun(qdesc, ForwardScanDirection, 0, true); + ExecutorRun(qdesc, ForwardScanDirection, 0); ExecutorFinish(qdesc); ExecutorEnd(qdesc); @@ -834,6 +1029,8 @@ execute_sql_string(const char *sql) MemoryContextDelete(per_parsetree_context); } + error_context_stack = scripterrcontext.previous; + /* Be sure to advance the command counter after the last script command */ CommandCounterIncrement(); } @@ -871,7 +1068,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, const char *from_version, const char *version, List *requiredSchemas, - const char *schemaName, Oid schemaOid) + const char *schemaName) { bool switch_to_superuser = false; char *filename; @@ -1110,7 +1307,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, /* And now back to C string */ c_sql = text_to_cstring(DatumGetTextPP(t_sql)); - execute_sql_string(c_sql); + execute_sql_string(c_sql, filename); } PG_FINALLY(); { @@ -1677,7 +1874,7 @@ CreateExtensionInternal(char *extensionName, execute_extension_script(extensionOid, control, NULL, versionName, requiredSchemas, - schemaName, schemaOid); + schemaName); /* * If additional update scripts have to be executed, apply the updates as @@ -2008,68 +2205,74 @@ Datum pg_available_extensions(PG_FUNCTION_ARGS) { ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; - char *location; + List *locations; DIR *dir; struct dirent *de; /* Build tuplestore to hold the result rows */ InitMaterializedSRF(fcinfo, 0); - location = get_extension_control_directory(); - dir = AllocateDir(location); + locations = get_extension_control_directories(); - /* - * If the control directory doesn't exist, we want to silently return an - * empty set. Any other error will be reported by ReadDir. - */ - if (dir == NULL && errno == ENOENT) - { - /* do nothing */ - } - else + foreach_ptr(char, location, locations) { - while ((de = ReadDir(dir, location)) != NULL) - { - ExtensionControlFile *control; - char *extname; - Datum values[3]; - bool nulls[3]; - - if (!is_extension_control_filename(de->d_name)) - continue; - - /* extract extension name from 'name.control' filename */ - extname = pstrdup(de->d_name); - *strrchr(extname, '.') = '\0'; - - /* ignore it if it's an auxiliary control file */ - if (strstr(extname, "--")) - continue; - - control = read_extension_control_file(extname); + dir = AllocateDir(location); - memset(values, 0, sizeof(values)); - memset(nulls, 0, sizeof(nulls)); + /* + * If the control directory doesn't exist, we want to silently return + * an empty set. Any other error will be reported by ReadDir. + */ + if (dir == NULL && errno == ENOENT) + { + /* do nothing */ + } + else + { + while ((de = ReadDir(dir, location)) != NULL) + { + ExtensionControlFile *control; + char *extname; + Datum values[3]; + bool nulls[3]; + + if (!is_extension_control_filename(de->d_name)) + continue; + + /* extract extension name from 'name.control' filename */ + extname = pstrdup(de->d_name); + *strrchr(extname, '.') = '\0'; + + /* ignore it if it's an auxiliary control file */ + if (strstr(extname, "--")) + continue; + + control = new_ExtensionControlFile(extname); + control->control_dir = pstrdup(location); + parse_extension_control_file(control, NULL); + + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); + + /* name */ + values[0] = DirectFunctionCall1(namein, + CStringGetDatum(control->name)); + /* default_version */ + if (control->default_version == NULL) + nulls[1] = true; + else + values[1] = CStringGetTextDatum(control->default_version); + /* comment */ + if (control->comment == NULL) + nulls[2] = true; + else + values[2] = CStringGetTextDatum(control->comment); - /* name */ - values[0] = DirectFunctionCall1(namein, - CStringGetDatum(control->name)); - /* default_version */ - if (control->default_version == NULL) - nulls[1] = true; - else - values[1] = CStringGetTextDatum(control->default_version); - /* comment */ - if (control->comment == NULL) - nulls[2] = true; - else - values[2] = CStringGetTextDatum(control->comment); + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, + values, nulls); + } - tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, - values, nulls); + FreeDir(dir); } - - FreeDir(dir); } return (Datum) 0; @@ -2088,51 +2291,57 @@ Datum pg_available_extension_versions(PG_FUNCTION_ARGS) { ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; - char *location; + List *locations; DIR *dir; struct dirent *de; /* Build tuplestore to hold the result rows */ InitMaterializedSRF(fcinfo, 0); - location = get_extension_control_directory(); - dir = AllocateDir(location); + locations = get_extension_control_directories(); - /* - * If the control directory doesn't exist, we want to silently return an - * empty set. Any other error will be reported by ReadDir. - */ - if (dir == NULL && errno == ENOENT) + foreach_ptr(char, location, locations) { - /* do nothing */ - } - else - { - while ((de = ReadDir(dir, location)) != NULL) + dir = AllocateDir(location); + + /* + * If the control directory doesn't exist, we want to silently return + * an empty set. Any other error will be reported by ReadDir. + */ + if (dir == NULL && errno == ENOENT) + { + /* do nothing */ + } + else { - ExtensionControlFile *control; - char *extname; + while ((de = ReadDir(dir, location)) != NULL) + { + ExtensionControlFile *control; + char *extname; - if (!is_extension_control_filename(de->d_name)) - continue; + if (!is_extension_control_filename(de->d_name)) + continue; - /* extract extension name from 'name.control' filename */ - extname = pstrdup(de->d_name); - *strrchr(extname, '.') = '\0'; + /* extract extension name from 'name.control' filename */ + extname = pstrdup(de->d_name); + *strrchr(extname, '.') = '\0'; - /* ignore it if it's an auxiliary control file */ - if (strstr(extname, "--")) - continue; + /* ignore it if it's an auxiliary control file */ + if (strstr(extname, "--")) + continue; - /* read the control file */ - control = read_extension_control_file(extname); + /* read the control file */ + control = new_ExtensionControlFile(extname); + control->control_dir = pstrdup(location); + parse_extension_control_file(control, NULL); - /* scan extension's script directory for install scripts */ - get_available_versions_for_extension(control, rsinfo->setResult, - rsinfo->setDesc); - } + /* scan extension's script directory for install scripts */ + get_available_versions_for_extension(control, rsinfo->setResult, + rsinfo->setDesc); + } - FreeDir(dir); + FreeDir(dir); + } } return (Datum) 0; @@ -2260,47 +2469,53 @@ bool extension_file_exists(const char *extensionName) { bool result = false; - char *location; + List *locations; DIR *dir; struct dirent *de; - location = get_extension_control_directory(); - dir = AllocateDir(location); + locations = get_extension_control_directories(); - /* - * If the control directory doesn't exist, we want to silently return - * false. Any other error will be reported by ReadDir. - */ - if (dir == NULL && errno == ENOENT) + foreach_ptr(char, location, locations) { - /* do nothing */ - } - else - { - while ((de = ReadDir(dir, location)) != NULL) + dir = AllocateDir(location); + + /* + * If the control directory doesn't exist, we want to silently return + * false. Any other error will be reported by ReadDir. + */ + if (dir == NULL && errno == ENOENT) { - char *extname; + /* do nothing */ + } + else + { + while ((de = ReadDir(dir, location)) != NULL) + { + char *extname; - if (!is_extension_control_filename(de->d_name)) - continue; + if (!is_extension_control_filename(de->d_name)) + continue; - /* extract extension name from 'name.control' filename */ - extname = pstrdup(de->d_name); - *strrchr(extname, '.') = '\0'; + /* extract extension name from 'name.control' filename */ + extname = pstrdup(de->d_name); + *strrchr(extname, '.') = '\0'; - /* ignore it if it's an auxiliary control file */ - if (strstr(extname, "--")) - continue; + /* ignore it if it's an auxiliary control file */ + if (strstr(extname, "--")) + continue; - /* done if it matches request */ - if (strcmp(extname, extensionName) == 0) - { - result = true; - break; + /* done if it matches request */ + if (strcmp(extname, extensionName) == 0) + { + result = true; + break; + } } - } - FreeDir(dir); + FreeDir(dir); + } + if (result) + break; } return result; @@ -2596,6 +2811,59 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * pg_get_loaded_modules + * + * SQL-callable function to get per-loaded-module information. Modules + * (shared libraries) aren't necessarily one-to-one with extensions, but + * they're sufficiently closely related to make this file a good home. + */ +Datum +pg_get_loaded_modules(PG_FUNCTION_ARGS) +{ + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + DynamicFileList *file_scanner; + + /* Build tuplestore to hold the result rows */ + InitMaterializedSRF(fcinfo, 0); + + for (file_scanner = get_first_loaded_module(); file_scanner != NULL; + file_scanner = get_next_loaded_module(file_scanner)) + { + const char *library_path, + *module_name, + *module_version; + const char *sep; + Datum values[3] = {0}; + bool nulls[3] = {0}; + + get_loaded_module_details(file_scanner, + &library_path, + &module_name, + &module_version); + + if (module_name == NULL) + nulls[0] = true; + else + values[0] = CStringGetTextDatum(module_name); + if (module_version == NULL) + nulls[1] = true; + else + values[1] = CStringGetTextDatum(module_version); + + /* For security reasons, we don't show the directory path */ + sep = last_dir_separator(library_path); + if (sep) + library_path = sep + 1; + values[2] = CStringGetTextDatum(library_path); + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, + values, nulls); + } + + return (Datum) 0; +} + /* * extension_config_remove * @@ -3269,7 +3537,7 @@ ApplyExtensionUpdates(Oid extensionOid, execute_extension_script(extensionOid, control, oldVersionName, versionName, requiredSchemas, - schemaName, schemaOid); + schemaName); /* * Update prior-version name and loop around. Since @@ -3511,7 +3779,8 @@ ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt, * Read the whole of file into memory. * * The file contents are returned as a single palloc'd chunk. For convenience - * of the callers, an extra \0 byte is added to the end. + * of the callers, an extra \0 byte is added to the end. That is not counted + * in the length returned into *length. */ static char * read_whole_file(const char *filename, int *length) @@ -3540,7 +3809,7 @@ read_whole_file(const char *filename, int *length) buf = (char *) palloc(bytes_to_read + 1); - *length = fread(buf, 1, bytes_to_read, file); + bytes_to_read = fread(buf, 1, bytes_to_read, file); if (ferror(file)) ereport(ERROR, @@ -3549,6 +3818,89 @@ read_whole_file(const char *filename, int *length) FreeFile(file); - buf[*length] = '\0'; + buf[bytes_to_read] = '\0'; + + /* + * On Windows, manually convert Windows-style newlines (\r\n) to the Unix + * convention of \n only. This avoids gotchas due to script files + * possibly getting converted when being transferred between platforms. + * Ideally we'd do this by using text mode to read the file, but that also + * causes control-Z to be treated as end-of-file. Historically we've + * allowed control-Z in script files, so breaking that seems unwise. + */ +#ifdef WIN32 + { + char *s, + *d; + + for (s = d = buf; *s; s++) + { + if (!(*s == '\r' && s[1] == '\n')) + *d++ = *s; + } + *d = '\0'; + bytes_to_read = d - buf; + } +#endif + + *length = bytes_to_read; return buf; } + +static ExtensionControlFile * +new_ExtensionControlFile(const char *extname) +{ + /* + * Set up default values. Pointer fields are initially null. + */ + ExtensionControlFile *control = palloc0_object(ExtensionControlFile); + + control->name = pstrdup(extname); + control->relocatable = false; + control->superuser = true; + control->trusted = false; + control->encoding = -1; + + return control; +} + +/* + * Work in a very similar way with find_in_path but it receives an already + * parsed List of paths to search the basename and it do not support macro + * replacement or custom error messages (for simplicity). + * + * By "already parsed List of paths" this function expected that paths already + * have all macros replaced. + */ +char * +find_in_paths(const char *basename, List *paths) +{ + ListCell *cell; + + foreach(cell, paths) + { + char *path = lfirst(cell); + char *full; + + Assert(path != NULL); + + path = pstrdup(path); + canonicalize_path(path); + + /* only absolute paths */ + if (!is_absolute_path(path)) + ereport(ERROR, + errcode(ERRCODE_INVALID_NAME), + errmsg("component in parameter \"%s\" is not an absolute path", "extension_control_path")); + + full = psprintf("%s/%s", path, basename); + + if (pg_file_exists(full)) + return full; + + pfree(path); + pfree(full); + } + + return NULL; +} diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index cf61bbac1fa10..8d2d743154462 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -3,7 +3,7 @@ * foreigncmds.c * foreign-data wrapper/server creation/manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -71,15 +71,26 @@ optionListToArray(List *options) foreach(cell, options) { DefElem *def = lfirst(cell); + const char *name; const char *value; Size len; text *t; + name = def->defname; value = defGetString(def); - len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value); + + /* Insist that name not contain "=", else "a=b=c" is ambiguous */ + if (strchr(name, '=') != NULL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid option name \"%s\": must not contain \"=\"", + name))); + + len = VARHDRSZ + strlen(name) + 1 + strlen(value); + /* +1 leaves room for sprintf's trailing null */ t = palloc(len + 1); SET_VARSIZE(t, len); - sprintf(VARDATA(t), "%s=%s", def->defname, value); + sprintf(VARDATA(t), "%s=%s", name, value); astate = accumArrayResult(astate, PointerGetDatum(t), false, TEXTOID, @@ -1532,7 +1543,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt) callback_arg.tablename = NULL; /* not known yet */ callback_arg.cmd = cmd; sqlerrcontext.callback = import_error_callback; - sqlerrcontext.arg = (void *) &callback_arg; + sqlerrcontext.arg = &callback_arg; sqlerrcontext.previous = error_context_stack; error_context_stack = &sqlerrcontext; diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 6593fd7d81152..0335e982b318b 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -5,7 +5,7 @@ * Routines for CREATE and DROP FUNCTION commands and CREATE and DROP * CAST commands. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -15,7 +15,7 @@ * DESCRIPTION * These routines take the parse tree and pick out the * appropriate arguments/flags, and pass the results to the - * corresponding "FooDefine" routines (in src/catalog) that do + * corresponding "FooCreate" routines (in src/backend/catalog) that do * the actual catalog-munging. These routines also verify permission * of the user to execute the command. * @@ -74,7 +74,7 @@ /* * Examine the RETURNS clause of the CREATE FUNCTION statement - * and return information about it as *prorettype_p and *returnsSet. + * and return information about it as *prorettype_p and *returnsSet_p. * * This is more complex than the average typename lookup because we want to * allow a shell type to be used, or even created if the specified return type @@ -232,7 +232,7 @@ interpret_function_parameter_list(ParseState *pstate, if (fpmode == FUNC_PARAM_DEFAULT) fpmode = FUNC_PARAM_IN; - typtup = LookupTypeName(NULL, t, NULL, false); + typtup = LookupTypeName(pstate, t, NULL, false); if (typtup) { if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined) @@ -242,18 +242,21 @@ interpret_function_parameter_list(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("SQL function cannot accept shell type %s", - TypeNameToString(t)))); + TypeNameToString(t)), + parser_errposition(pstate, t->location))); /* We don't allow creating aggregates on shell types either */ else if (objtype == OBJECT_AGGREGATE) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("aggregate cannot accept shell type %s", - TypeNameToString(t)))); + TypeNameToString(t)), + parser_errposition(pstate, t->location))); else ereport(NOTICE, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("argument type %s is only a shell", - TypeNameToString(t)))); + TypeNameToString(t)), + parser_errposition(pstate, t->location))); } toid = typeTypeId(typtup); ReleaseSysCache(typtup); @@ -263,7 +266,8 @@ interpret_function_parameter_list(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("type %s does not exist", - TypeNameToString(t)))); + TypeNameToString(t)), + parser_errposition(pstate, t->location))); toid = InvalidOid; /* keep compiler quiet */ } @@ -276,15 +280,18 @@ interpret_function_parameter_list(ParseState *pstate, if (objtype == OBJECT_AGGREGATE) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("aggregates cannot accept set arguments"))); + errmsg("aggregates cannot accept set arguments"), + parser_errposition(pstate, fp->location))); else if (objtype == OBJECT_PROCEDURE) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("procedures cannot accept set arguments"))); + errmsg("procedures cannot accept set arguments"), + parser_errposition(pstate, fp->location))); else ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("functions cannot accept set arguments"))); + errmsg("functions cannot accept set arguments"), + parser_errposition(pstate, fp->location))); } /* handle input parameters */ @@ -294,7 +301,8 @@ interpret_function_parameter_list(ParseState *pstate, if (varCount > 0) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("VARIADIC parameter must be the last input parameter"))); + errmsg("VARIADIC parameter must be the last input parameter"), + parser_errposition(pstate, fp->location))); inTypes[inCount++] = toid; isinput = true; if (parameterTypes_list) @@ -314,7 +322,8 @@ interpret_function_parameter_list(ParseState *pstate, if (varCount > 0) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("VARIADIC parameter must be the last parameter"))); + errmsg("VARIADIC parameter must be the last parameter"), + parser_errposition(pstate, fp->location))); /* Procedures with output parameters always return RECORD */ *requiredResultType = RECORDOID; } @@ -339,7 +348,8 @@ interpret_function_parameter_list(ParseState *pstate, if (!OidIsValid(get_element_type(toid))) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("VARIADIC parameter must be an array"))); + errmsg("VARIADIC parameter must be an array"), + parser_errposition(pstate, fp->location))); break; } } @@ -385,7 +395,8 @@ interpret_function_parameter_list(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("parameter name \"%s\" used more than once", - fp->name))); + fp->name), + parser_errposition(pstate, fp->location))); } paramNames[i] = CStringGetTextDatum(fp->name); @@ -402,7 +413,8 @@ interpret_function_parameter_list(ParseState *pstate, if (!isinput) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("only input parameters can have default values"))); + errmsg("only input parameters can have default values"), + parser_errposition(pstate, fp->location))); def = transformExpr(pstate, fp->defexpr, EXPR_KIND_FUNCTION_DEFAULT); @@ -417,7 +429,8 @@ interpret_function_parameter_list(ParseState *pstate, contain_var_clause(def)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("cannot use table references in parameter default value"))); + errmsg("cannot use table references in parameter default value"), + parser_errposition(pstate, fp->location))); /* * transformExpr() should have already rejected subqueries, @@ -441,7 +454,8 @@ interpret_function_parameter_list(ParseState *pstate, if (isinput && have_defaults) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("input parameters after one with a default value must also have defaults"))); + errmsg("input parameters after one with a default value must also have defaults"), + parser_errposition(pstate, fp->location))); /* * For procedures, we also can't allow OUT parameters after one @@ -451,7 +465,8 @@ interpret_function_parameter_list(ParseState *pstate, if (objtype == OBJECT_PROCEDURE && have_defaults) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), - errmsg("procedure OUT parameters cannot appear after one with a default value"))); + errmsg("procedure OUT parameters cannot appear after one with a default value"), + parser_errposition(pstate, fp->location))); } i++; @@ -1031,6 +1046,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) List *parameterDefaults; Oid variadicArgType; List *trftypes_list = NIL; + List *trfoids_list = NIL; ArrayType *trftypes; Oid requiredResultType; bool isWindowFunc, @@ -1142,11 +1158,12 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) Oid typeid = typenameTypeId(NULL, lfirst_node(TypeName, lc)); Oid elt = get_base_element_type(typeid); + Oid transformid; typeid = elt ? elt : typeid; - - get_transform_oid(typeid, languageOid, false); + transformid = get_transform_oid(typeid, languageOid, false); trftypes_list = lappend_oid(trftypes_list, typeid); + trfoids_list = lappend_oid(trfoids_list, transformid); } } @@ -1277,6 +1294,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) PointerGetDatum(parameterNames), parameterDefaults, PointerGetDatum(trftypes), + trfoids_list, PointerGetDatum(proconfig), prosupport, procost, @@ -1689,13 +1707,18 @@ CreateCast(CreateCastStmt *stmt) errmsg("source and target data types are not physically compatible"))); /* - * We know that composite, enum and array types are never binary- - * compatible with each other. They all have OIDs embedded in them. + * We know that composite, array, range and enum types are never + * binary-compatible with each other. They all have OIDs embedded in + * them. * * Theoretically you could build a user-defined base type that is - * binary-compatible with a composite, enum, or array type. But we - * disallow that too, as in practice such a cast is surely a mistake. - * You can always work around that by writing a cast function. + * binary-compatible with such a type. But we disallow it anyway, as + * in practice such a cast is surely a mistake. You can always work + * around that by writing a cast function. + * + * NOTE: if we ever have a kind of container type that doesn't need to + * be rejected for this reason, we'd likely need to recursively apply + * all of these same checks to the contained type(s). */ if (sourcetyptype == TYPTYPE_COMPOSITE || targettyptype == TYPTYPE_COMPOSITE) @@ -1703,18 +1726,26 @@ CreateCast(CreateCastStmt *stmt) (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("composite data types are not binary-compatible"))); - if (sourcetyptype == TYPTYPE_ENUM || - targettyptype == TYPTYPE_ENUM) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("enum data types are not binary-compatible"))); - if (OidIsValid(get_element_type(sourcetypeid)) || OidIsValid(get_element_type(targettypeid))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("array data types are not binary-compatible"))); + if (sourcetyptype == TYPTYPE_RANGE || + targettyptype == TYPTYPE_RANGE || + sourcetyptype == TYPTYPE_MULTIRANGE || + targettyptype == TYPTYPE_MULTIRANGE) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("range data types are not binary-compatible"))); + + if (sourcetyptype == TYPTYPE_ENUM || + targettyptype == TYPTYPE_ENUM) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("enum data types are not binary-compatible"))); + /* * We also disallow creating binary-compatibility casts involving * domains. Casting from a domain to its base type is already diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index c5a56c75f6995..c3ec2076a52ef 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -3,7 +3,7 @@ * indexcmds.c * POSTGRES define and remove index code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -16,6 +16,7 @@ #include "postgres.h" #include "access/amapi.h" +#include "access/gist.h" #include "access/heapam.h" #include "access/htup_details.h" #include "access/reloptions.h" @@ -28,12 +29,12 @@ #include "catalog/namespace.h" #include "catalog/pg_am.h" #include "catalog/pg_authid.h" +#include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" #include "catalog/pg_database.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_opfamily.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" #include "commands/comment.h" @@ -50,17 +51,18 @@ #include "optimizer/optimizer.h" #include "parser/parse_coerce.h" #include "parser/parse_oper.h" +#include "parser/parse_utilcmd.h" #include "partitioning/partdesc.h" #include "pgstat.h" #include "rewrite/rewriteManip.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" -#include "storage/sinvaladt.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/guc.h" +#include "utils/injection_point.h" #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -87,6 +89,7 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo, Oid accessMethodId, bool amcanorder, bool isconstraint, + bool iswithoutoverlaps, Oid ddl_userid, int ddl_sec_context, int *ddl_save_nestlevel); @@ -145,6 +148,7 @@ typedef struct ReindexErrorInfo * to index on. * 'exclusionOpNames': list of names of exclusion-constraint operators, * or NIL if not an exclusion constraint. + * 'isWithoutOverlaps': true iff this index has a WITHOUT OVERLAPS clause. * * This is tailored to the needs of ALTER TABLE ALTER TYPE, which recreates * any indexes that depended on a changing column from their pg_get_indexdef @@ -174,7 +178,8 @@ bool CheckIndexCompatible(Oid oldId, const char *accessMethodName, const List *attributeList, - const List *exclusionOpNames) + const List *exclusionOpNames, + bool isWithoutOverlaps) { bool isconstraint; Oid *typeIds; @@ -238,7 +243,7 @@ CheckIndexCompatible(Oid oldId, */ indexInfo = makeIndexInfo(numberOfAttributes, numberOfAttributes, accessMethodId, NIL, NIL, false, false, - false, false, amsummarizing); + false, false, amsummarizing, isWithoutOverlaps); typeIds = palloc_array(Oid, numberOfAttributes); collationIds = palloc_array(Oid, numberOfAttributes); opclassIds = palloc_array(Oid, numberOfAttributes); @@ -249,8 +254,8 @@ CheckIndexCompatible(Oid oldId, coloptions, attributeList, exclusionOpNames, relationId, accessMethodName, accessMethodId, - amcanorder, isconstraint, InvalidOid, 0, NULL); - + amcanorder, isconstraint, isWithoutOverlaps, InvalidOid, + 0, NULL); /* Get the soon-obsolete pg_index tuple. */ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(oldId)); @@ -357,10 +362,12 @@ static bool CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts) { int i; + FmgrInfo fm; if (!opts1 && !opts2) return true; + fmgr_info(F_ARRAY_EQ, &fm); for (i = 0; i < natts; i++) { Datum opt1 = opts1 ? opts1[i] : (Datum) 0; @@ -376,8 +383,12 @@ CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts) else if (opt2 == (Datum) 0) return false; - /* Compare non-NULL text[] datums. */ - if (!DatumGetBool(DirectFunctionCall2(array_eq, opt1, opt2))) + /* + * Compare non-NULL text[] datums. Use C collation to enforce binary + * equivalence of texts, because we don't know anything about the + * semantics of opclass options. + */ + if (!DatumGetBool(FunctionCall2Coll(&fm, C_COLLATION_OID, opt1, opt2))) return false; } @@ -560,6 +571,7 @@ DefineIndex(Oid tableId, bool amcanorder; bool amissummarizing; amoptions_function amoptions; + bool exclusion; bool partitioned; bool safe_index; Datum reloptions; @@ -680,6 +692,12 @@ DefineIndex(Oid tableId, namespaceId = RelationGetNamespace(rel); + /* + * It has exclusion constraint behavior if it's an EXCLUDE constraint or a + * temporal PRIMARY KEY/UNIQUE constraint + */ + exclusion = stmt->excludeOpNames || stmt->iswithoutoverlaps; + /* Ensure that it makes sense to index this kind of relation */ switch (rel->rd_rel->relkind) { @@ -848,7 +866,7 @@ DefineIndex(Oid tableId, pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID, accessMethodId); - if (stmt->unique && !amRoutine->amcanunique) + if (stmt->unique && !stmt->iswithoutoverlaps && !amRoutine->amcanunique) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support unique indexes", @@ -863,11 +881,16 @@ DefineIndex(Oid tableId, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support multicolumn indexes", accessMethodName))); - if (stmt->excludeOpNames && amRoutine->amgettuple == NULL) + if (exclusion && amRoutine->amgettuple == NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support exclusion constraints", accessMethodName))); + if (stmt->iswithoutoverlaps && strcmp(accessMethodName, "gist") != 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("access method \"%s\" does not support WITHOUT OVERLAPS constraints", + accessMethodName))); amcanorder = amRoutine->amcanorder; amoptions = amRoutine->amoptions; @@ -904,7 +927,8 @@ DefineIndex(Oid tableId, stmt->nulls_not_distinct, !concurrent, concurrent, - amissummarizing); + amissummarizing, + stmt->iswithoutoverlaps); typeIds = palloc_array(Oid, numberOfAttributes); collationIds = palloc_array(Oid, numberOfAttributes); @@ -916,8 +940,9 @@ DefineIndex(Oid tableId, coloptions, allIndexParams, stmt->excludeOpNames, tableId, accessMethodName, accessMethodId, - amcanorder, stmt->isconstraint, root_save_userid, - root_save_sec_context, &root_save_nestlevel); + amcanorder, stmt->isconstraint, stmt->iswithoutoverlaps, + root_save_userid, root_save_sec_context, + &root_save_nestlevel); /* * Extra checks when creating a PRIMARY KEY index. @@ -935,7 +960,7 @@ DefineIndex(Oid tableId, * We could lift this limitation if we had global indexes, but those have * their own problems, so this is a useful feature combination. */ - if (partitioned && (stmt->unique || stmt->excludeOpNames)) + if (partitioned && (stmt->unique || exclusion)) { PartitionKey key = RelationGetPartitionKey(rel); const char *constraint_type; @@ -984,20 +1009,6 @@ DefineIndex(Oid tableId, eq_strategy, key->partopcintype[i], key->partopcintype[i], key->partopfamily[i]); - /* - * We'll need to be able to identify the equality operators - * associated with index columns, too. We know what to do with - * btree opclasses; if there are ever any other index types that - * support unique indexes, this logic will need extension. But if - * we have an exclusion constraint, it already knows the - * operators, so we don't have to infer them. - */ - if (stmt->unique && accessMethodId != BTREE_AM_OID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot match partition key to an index using access method \"%s\"", - accessMethodName))); - /* * It may be possible to support UNIQUE constraints when partition * keys are expressions, but is it worth it? Give up for now. @@ -1031,21 +1042,27 @@ DefineIndex(Oid tableId, { Oid idx_eqop = InvalidOid; - if (stmt->unique) - idx_eqop = get_opfamily_member(idx_opfamily, - idx_opcintype, - idx_opcintype, - BTEqualStrategyNumber); - else if (stmt->excludeOpNames) + if (stmt->unique && !stmt->iswithoutoverlaps) + idx_eqop = get_opfamily_member_for_cmptype(idx_opfamily, + idx_opcintype, + idx_opcintype, + COMPARE_EQ); + else if (exclusion) idx_eqop = indexInfo->ii_ExclusionOps[j]; - Assert(idx_eqop); + + if (!idx_eqop) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("could not identify an equality operator for type %s", format_type_be(idx_opcintype)), + errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".", + get_opfamily_name(idx_opfamily, false), get_am_name(get_opfamily_method(idx_opfamily)))); if (ptkey_eqop == idx_eqop) { found = true; break; } - else if (stmt->excludeOpNames) + else if (exclusion) { /* * We found a match, but it's not an equality @@ -1085,6 +1102,9 @@ DefineIndex(Oid tableId, /* * We disallow indexes on system columns. They would not necessarily get * updated correctly, and they don't seem useful anyway. + * + * Also disallow virtual generated columns in indexes (use expression + * index instead). */ for (int i = 0; i < indexInfo->ii_NumIndexAttrs; i++) { @@ -1094,14 +1114,26 @@ DefineIndex(Oid tableId, ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("index creation on system columns is not supported"))); + + + if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + stmt->primary ? + errmsg("primary keys on virtual generated columns are not supported") : + stmt->isconstraint ? + errmsg("unique constraints on virtual generated columns are not supported") : + errmsg("indexes on virtual generated columns are not supported")); } /* - * Also check for system columns used in expressions or predicates. + * Also check for system and generated columns used in expressions or + * predicates. */ if (indexInfo->ii_Expressions || indexInfo->ii_Predicate) { Bitmapset *indexattrs = NULL; + int j; pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs); pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs); @@ -1114,6 +1146,24 @@ DefineIndex(Oid tableId, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("index creation on system columns is not supported"))); } + + /* + * XXX Virtual generated columns in index expressions or predicates + * could be supported, but it needs support in + * RelationGetIndexExpressions() and RelationGetIndexPredicate(). + */ + j = -1; + while ((j = bms_next_member(indexattrs, j)) >= 0) + { + AttrNumber attno = j + FirstLowInvalidHeapAttributeNumber; + + if (TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + stmt->isconstraint ? + errmsg("unique constraints on virtual generated columns are not supported") : + errmsg("indexes on virtual generated columns are not supported"))); + } } /* Is index safe for others to ignore? See set_indexsafe_procflags() */ @@ -1189,6 +1239,8 @@ DefineIndex(Oid tableId, constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE; if (stmt->initdeferred) constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED; + if (stmt->iswithoutoverlaps) + constr_flags |= INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS; indexRelationId = index_create(rel, indexRelationName, indexRelationId, parentIndexId, @@ -1444,55 +1496,20 @@ DefineIndex(Oid tableId, */ if (!found) { - IndexStmt *childStmt = copyObject(stmt); - bool found_whole_row; - ListCell *lc; + IndexStmt *childStmt; ObjectAddress childAddr; /* - * We can't use the same index name for the child index, - * so clear idxname to let the recursive invocation choose - * a new name. Likewise, the existing target relation - * field is wrong, and if indexOid or oldNumber are set, - * they mustn't be applied to the child either. + * Build an IndexStmt describing the desired child index + * in the same way that we do during ATTACH PARTITION. + * Notably, we rely on generateClonedIndexStmt to produce + * a search-path-independent representation, which the + * original IndexStmt might not be. */ - childStmt->idxname = NULL; - childStmt->relation = NULL; - childStmt->indexOid = InvalidOid; - childStmt->oldNumber = InvalidRelFileNumber; - childStmt->oldCreateSubid = InvalidSubTransactionId; - childStmt->oldFirstRelfilelocatorSubid = InvalidSubTransactionId; - - /* - * Adjust any Vars (both in expressions and in the index's - * WHERE clause) to match the partition's column numbering - * in case it's different from the parent's. - */ - foreach(lc, childStmt->indexParams) - { - IndexElem *ielem = lfirst(lc); - - /* - * If the index parameter is an expression, we must - * translate it to contain child Vars. - */ - if (ielem->expr) - { - ielem->expr = - map_variable_attnos((Node *) ielem->expr, - 1, 0, attmap, - InvalidOid, - &found_whole_row); - if (found_whole_row) - elog(ERROR, "cannot convert whole-row table reference"); - } - } - childStmt->whereClause = - map_variable_attnos(stmt->whereClause, 1, 0, - attmap, - InvalidOid, &found_whole_row); - if (found_whole_row) - elog(ERROR, "cannot convert whole-row table reference"); + childStmt = generateClonedIndexStmt(NULL, + parentIndex, + attmap, + NULL); /* * Recurse as the starting user ID. Callee will use that @@ -1777,11 +1794,19 @@ DefineIndex(Oid tableId, PROGRESS_CREATEIDX_PHASE_WAIT_3); WaitForOlderSnapshots(limitXmin, true); + /* + * Updating pg_index might involve TOAST table access, so ensure we have a + * valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Index can now be marked valid -- update its pg_index entry */ index_set_state_flags(indexRelationId, INDEX_CREATE_SET_VALID); + PopActiveSnapshot(); + /* * The pg_index update will cause backends (including this one) to update * relcache entries for the index itself, but we should also send a @@ -1855,6 +1880,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo, Oid accessMethodId, bool amcanorder, bool isconstraint, + bool iswithoutoverlaps, Oid ddl_userid, int ddl_sec_context, int *ddl_save_nestlevel) @@ -1878,6 +1904,23 @@ ComputeIndexAttrs(IndexInfo *indexInfo, else nextExclOp = NULL; + /* + * If this is a WITHOUT OVERLAPS constraint, we need space for exclusion + * ops, but we don't need to parse anything, so we can let nextExclOp be + * NULL. Note that for partitions/inheriting/LIKE, exclusionOpNames will + * be set, so we already allocated above. + */ + if (iswithoutoverlaps) + { + if (exclusionOpNames == NIL) + { + indexInfo->ii_ExclusionOps = palloc_array(Oid, nkeycols); + indexInfo->ii_ExclusionProcs = palloc_array(Oid, nkeycols); + indexInfo->ii_ExclusionStrats = palloc_array(uint16, nkeycols); + } + nextExclOp = NULL; + } + if (OidIsValid(ddl_userid)) GetUserIdAndSecContext(&save_userid, &save_sec_context); @@ -2128,35 +2171,33 @@ ComputeIndexAttrs(IndexInfo *indexInfo, opfamily = get_opclass_family(opclassOids[attn]); strat = get_op_opfamily_strategy(opid, opfamily); if (strat == 0) - { - HeapTuple opftuple; - Form_pg_opfamily opfform; - - /* - * attribute->opclass might not explicitly name the opfamily, - * so fetch the name of the selected opfamily for use in the - * error message. - */ - opftuple = SearchSysCache1(OPFAMILYOID, - ObjectIdGetDatum(opfamily)); - if (!HeapTupleIsValid(opftuple)) - elog(ERROR, "cache lookup failed for opfamily %u", - opfamily); - opfform = (Form_pg_opfamily) GETSTRUCT(opftuple); - ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("operator %s is not a member of operator family \"%s\"", format_operator(opid), - NameStr(opfform->opfname)), + get_opfamily_name(opfamily, false)), errdetail("The exclusion operator must be related to the index operator class for the constraint."))); - } indexInfo->ii_ExclusionOps[attn] = opid; indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid); indexInfo->ii_ExclusionStrats[attn] = strat; nextExclOp = lnext(exclusionOpNames, nextExclOp); } + else if (iswithoutoverlaps) + { + CompareType cmptype; + StrategyNumber strat; + Oid opid; + + if (attn == nkeycols - 1) + cmptype = COMPARE_OVERLAP; + else + cmptype = COMPARE_EQ; + GetOperatorFromCompareType(opclassOids[attn], InvalidOid, cmptype, &opid, &strat); + indexInfo->ii_ExclusionOps[attn] = opid; + indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid); + indexInfo->ii_ExclusionStrats[attn] = strat; + } /* * Set up the per-column options (indoption field). For now, this is @@ -2387,6 +2428,70 @@ GetDefaultOpClass(Oid type_id, Oid am_id) return InvalidOid; } +/* + * GetOperatorFromCompareType + * + * opclass - the opclass to use + * rhstype - the type for the right-hand side, or InvalidOid to use the type of the given opclass. + * cmptype - kind of operator to find + * opid - holds the operator we found + * strat - holds the output strategy number + * + * Finds an operator from a CompareType. This is used for temporal index + * constraints (and other temporal features) to look up equality and overlaps + * operators. We ask an opclass support function to translate from the + * compare type to the internal strategy numbers. If the function isn't + * defined or it gives no result, we set *strat to InvalidStrategy. + */ +void +GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, + Oid *opid, StrategyNumber *strat) +{ + Oid amid; + Oid opfamily; + Oid opcintype; + + Assert(cmptype == COMPARE_EQ || cmptype == COMPARE_OVERLAP || cmptype == COMPARE_CONTAINED_BY); + + amid = get_opclass_method(opclass); + + *opid = InvalidOid; + + if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype)) + { + /* + * Ask the index AM to translate to its internal stratnum + */ + *strat = IndexAmTranslateCompareType(cmptype, amid, opfamily, true); + if (*strat == InvalidStrategy) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + cmptype == COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) : + cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) : + cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0, + errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".", + cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid))); + + /* + * We parameterize rhstype so foreign keys can ask for a <@ operator + * whose rhs matches the aggregate function. For example range_agg + * returns anymultirange. + */ + if (!OidIsValid(rhstype)) + rhstype = opcintype; + *opid = get_opfamily_member(opfamily, opcintype, rhstype, *strat); + } + + if (!OidIsValid(*opid)) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + cmptype == COMPARE_EQ ? errmsg("could not identify an equality operator for type %s", format_type_be(opcintype)) : + cmptype == COMPARE_OVERLAP ? errmsg("could not identify an overlaps operator for type %s", format_type_be(opcintype)) : + cmptype == COMPARE_CONTAINED_BY ? errmsg("could not identify a contained-by operator for type %s", format_type_be(opcintype)) : 0, + errdetail("There is no suitable operator in operator family \"%s\" for access method \"%s\".", + get_opfamily_name(opfamily, false), get_am_name(amid))); +} + /* * makeObjectName() * @@ -3228,7 +3333,7 @@ ReindexPartitions(const ReindexStmt *stmt, Oid relid, const ReindexParams *param errinfo.relnamespace = pstrdup(relnamespace); errinfo.relkind = relkind; errcallback.callback = reindex_error_callback; - errcallback.arg = (void *) &errinfo; + errcallback.arg = &errinfo; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -3782,8 +3887,16 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein RestrictSearchPath(); /* determine safety of this index for set_indexsafe_procflags */ - idx->safe = (indexRel->rd_indexprs == NIL && - indexRel->rd_indpred == NIL); + idx->safe = (RelationGetIndexExpressions(indexRel) == NIL && + RelationGetIndexPredicate(indexRel) == NIL); + +#ifdef USE_INJECTION_POINTS + if (idx->safe) + INJECTION_POINT("reindex-conc-index-safe", NULL); + else + INJECTION_POINT("reindex-conc-index-not-safe", NULL); +#endif + idx->tableId = RelationGetRelid(heapRel); idx->amId = indexRel->rd_rel->relam; @@ -4112,12 +4225,20 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein get_rel_namespace(oldidx->tableId), false); + /* + * Swapping the indexes might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Swap old index with the new one. This also marks the new one as * valid and the old one as not valid. */ index_concurrently_swap(newidx->indexId, oldidx->indexId, oldName); + PopActiveSnapshot(); + /* * Invalidate the relcache for the table, so that after this commit * all sessions will refresh any cached plans that might reference the @@ -4168,7 +4289,15 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein */ CHECK_FOR_INTERRUPTS(); + /* + * Updating pg_index might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + index_concurrently_set_dead(oldidx->tableId, oldidx->indexId); + + PopActiveSnapshot(); } /* Commit this transaction to make the updates visible. */ @@ -4413,14 +4542,17 @@ update_relispartition(Oid relationId, bool newval) { HeapTuple tup; Relation classRel; + ItemPointerData otid; classRel = table_open(RelationRelationId, RowExclusiveLock); - tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId)); + tup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relationId)); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for relation %u", relationId); + otid = tup->t_self; Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval); ((Form_pg_class) GETSTRUCT(tup))->relispartition = newval; - CatalogTupleUpdate(classRel, &tup->t_self, tup); + CatalogTupleUpdate(classRel, &otid, tup); + UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); heap_freetuple(tup); table_close(classRel, RowExclusiveLock); } diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index cd20ae76badbc..616da19671499 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -3,7 +3,7 @@ * lockcmds.c * LOCK command support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -54,7 +54,7 @@ LockTableCommand(LockStmt *lockstmt) reloid = RangeVarGetRelidExtended(rv, lockstmt->mode, lockstmt->nowait ? RVR_NOWAIT : 0, RangeVarCallbackForLockTable, - (void *) &lockstmt->mode); + &lockstmt->mode); if (get_rel_relkind(reloid) == RELKIND_VIEW) LockViewRecurse(reloid, lockstmt->mode, lockstmt->nowait, NIL); diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 84245b65f7dad..27c2cb26ef5f3 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -3,7 +3,7 @@ * matview.c * materialized view support * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -60,7 +60,7 @@ static bool transientrel_receive(TupleTableSlot *slot, DestReceiver *self); static void transientrel_shutdown(DestReceiver *self); static void transientrel_destroy(DestReceiver *self); static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, - const char *queryString); + const char *queryString, bool is_create); static char *make_temptable_name_n(char *tempname, int n); static void refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, int save_sec_context); @@ -119,7 +119,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate) */ ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, - ParamListInfo params, QueryCompletion *qc) + QueryCompletion *qc) { Oid matviewOid; LOCKMODE lockmode; @@ -135,8 +135,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, RangeVarCallbackMaintainsTable, NULL); - return RefreshMatViewByOid(matviewOid, stmt->skipData, stmt->concurrent, - queryString, params, qc); + return RefreshMatViewByOid(matviewOid, false, stmt->skipData, + stmt->concurrent, queryString, qc); } /* @@ -157,10 +157,13 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, * * The matview's "populated" state is changed based on whether the contents * reflect the result set of the materialized view's query. + * + * This is also used to populate the materialized view created by CREATE + * MATERIALIZED VIEW command. */ ObjectAddress -RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, - const char *queryString, ParamListInfo params, +RefreshMatViewByOid(Oid matviewOid, bool is_create, bool skipData, + bool concurrent, const char *queryString, QueryCompletion *qc) { Relation matviewRel; @@ -170,7 +173,6 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, Oid tableSpace; Oid relowner; Oid OIDNewHeap; - DestReceiver *dest; uint64 processed = 0; char relpersistence; Oid save_userid; @@ -249,6 +251,8 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, ListCell *indexoidscan; bool hasUniqueIndex = false; + Assert(!is_create); + foreach(indexoidscan, indexoidlist) { Oid indexoid = lfirst_oid(indexoidscan); @@ -285,7 +289,9 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, * NB: We count on this to protect us against problems with refreshing the * data using TABLE_INSERT_FROZEN. */ - CheckTableNotInUse(matviewRel, "REFRESH MATERIALIZED VIEW"); + CheckTableNotInUse(matviewRel, + is_create ? "CREATE MATERIALIZED VIEW" : + "REFRESH MATERIALIZED VIEW"); /* * Tentatively mark the matview as populated or not (this will roll back @@ -313,12 +319,17 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, OIDNewHeap = make_new_heap(matviewOid, tableSpace, matviewRel->rd_rel->relam, relpersistence, ExclusiveLock); - LockRelationOid(OIDNewHeap, AccessExclusiveLock); - dest = CreateTransientRelDestReceiver(OIDNewHeap); + Assert(CheckRelationOidLockedByMe(OIDNewHeap, AccessExclusiveLock, false)); /* Generate the data, if wanted. */ if (!skipData) - processed = refresh_matview_datafill(dest, dataQuery, queryString); + { + DestReceiver *dest; + + dest = CreateTransientRelDestReceiver(OIDNewHeap); + processed = refresh_matview_datafill(dest, dataQuery, queryString, + is_create); + } /* Make the matview match the newly generated data. */ if (concurrent) @@ -370,9 +381,14 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, * i.e., the display_rowcount flag of CMDTAG_REFRESH_MATERIALIZED_VIEW * command tag is left false in cmdtaglist.h. Otherwise, the change of * completion tag output might break applications using it. + * + * When called from CREATE MATERIALIZED VIEW command, the rowcount is + * displayed with the command tag CMDTAG_SELECT. */ if (qc) - SetQueryCompletion(qc, CMDTAG_REFRESH_MATERIALIZED_VIEW, processed); + SetQueryCompletion(qc, + is_create ? CMDTAG_SELECT : CMDTAG_REFRESH_MATERIALIZED_VIEW, + processed); return address; } @@ -387,7 +403,7 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, */ static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, - const char *queryString) + const char *queryString, bool is_create) { List *rewritten; PlannedStmt *plan; @@ -402,7 +418,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) - elog(ERROR, "unexpected rewrite result for REFRESH MATERIALIZED VIEW"); + elog(ERROR, "unexpected rewrite result for %s", + is_create ? "CREATE MATERIALIZED VIEW " : "REFRESH MATERIALIZED VIEW"); query = (Query *) linitial(rewritten); /* Check for user-requested abort. */ @@ -429,7 +446,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, ExecutorStart(queryDesc, 0); /* run the plan */ - ExecutorRun(queryDesc, ForwardScanDirection, 0, true); + ExecutorRun(queryDesc, ForwardScanDirection, 0); processed = queryDesc->estate->es_processed; @@ -622,8 +639,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, relnatts = RelationGetNumberOfAttributes(matviewRel); /* Open SPI context. */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* Analyze the temp table with the new contents. */ appendStringInfo(&querybuf, "ANALYZE %s", tempname); @@ -757,16 +773,14 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, if (!HeapTupleIsValid(cla_ht)) elog(ERROR, "cache lookup failed for opclass %u", opclass); cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht); - Assert(cla_tup->opcmethod == BTREE_AM_OID); opfamily = cla_tup->opcfamily; opcintype = cla_tup->opcintype; ReleaseSysCache(cla_ht); - op = get_opfamily_member(opfamily, opcintype, opcintype, - BTEqualStrategyNumber); + op = get_opfamily_member_for_cmptype(opfamily, opcintype, opcintype, COMPARE_EQ); if (!OidIsValid(op)) - elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - BTEqualStrategyNumber, opcintype, opcintype, opfamily); + elog(ERROR, "missing equality operator for (%u,%u) in opfamily %u", + opcintype, opcintype, opfamily); /* * If we find the same column with the same equality semantics @@ -903,15 +917,10 @@ is_usable_unique_index(Relation indexRel) /* * Must be unique, valid, immediate, non-partial, and be defined over - * plain user columns (not expressions). We also require it to be a - * btree. Even if we had any other unique index kinds, we'd not know how - * to identify the corresponding equality operator, nor could we be sure - * that the planner could implement the required FULL JOIN with non-btree - * operators. + * plain user columns (not expressions). */ if (indexStruct->indisunique && indexStruct->indimmediate && - indexRel->rd_rel->relam == BTREE_AM_OID && indexStruct->indisvalid && RelationGetIndexPredicate(indexRel) == NIL && indexStruct->indnatts > 0) diff --git a/src/backend/commands/meson.build b/src/backend/commands/meson.build index 6dd00a4abdeaf..dd4cde41d32cc 100644 --- a/src/backend/commands/meson.build +++ b/src/backend/commands/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'aggregatecmds.c', @@ -22,6 +22,9 @@ backend_sources += files( 'dropcmds.c', 'event_trigger.c', 'explain.c', + 'explain_dr.c', + 'explain_format.c', + 'explain_state.c', 'extension.c', 'foreigncmds.c', 'functioncmds.c', diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index b8b5c147c5dab..a6dd8eab5186b 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -4,7 +4,7 @@ * * Routines for opclass (and opfamily) manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -65,6 +65,7 @@ static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators, bool isAdd); static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures, bool isAdd); +static bool typeDepNeeded(Oid typid, OpFamilyMember *member); static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators); static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, @@ -1241,25 +1242,25 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, } /* - * btree comparison procs must be 2-arg procs returning int4. btree - * sortsupport procs must take internal and return void. btree in_range - * procs must be 5-arg procs returning bool. btree equalimage procs must - * take 1 arg and return bool. hash support proc 1 must be a 1-arg proc - * returning int4, while proc 2 must be a 2-arg proc returning int8. - * Otherwise we don't know. + * Ordering comparison procs must be 2-arg procs returning int4. Ordering + * sortsupport procs must take internal and return void. Ordering + * in_range procs must be 5-arg procs returning bool. Ordering equalimage + * procs must take 1 arg and return bool. Hashing support proc 1 must be + * a 1-arg proc returning int4, while proc 2 must be a 2-arg proc + * returning int8. Otherwise we don't know. */ - else if (amoid == BTREE_AM_OID) + else if (GetIndexAmRoutineByAmId(amoid, false)->amcanorder) { if (member->number == BTORDER_PROC) { if (procform->pronargs != 2) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree comparison functions must have two arguments"))); + errmsg("ordering comparison functions must have two arguments"))); if (procform->prorettype != INT4OID) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree comparison functions must return integer"))); + errmsg("ordering comparison functions must return integer"))); /* * If lefttype/righttype isn't specified, use the proc's input @@ -1276,11 +1277,11 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, procform->proargtypes.values[0] != INTERNALOID) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree sort support functions must accept type \"internal\""))); + errmsg("ordering sort support functions must accept type \"internal\""))); if (procform->prorettype != VOIDOID) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree sort support functions must return void"))); + errmsg("ordering sort support functions must return void"))); /* * Can't infer lefttype/righttype from proc, so use default rule @@ -1291,11 +1292,11 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, if (procform->pronargs != 5) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree in_range functions must have five arguments"))); + errmsg("ordering in_range functions must have five arguments"))); if (procform->prorettype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree in_range functions must return boolean"))); + errmsg("ordering in_range functions must return boolean"))); /* * If lefttype/righttype isn't specified, use the proc's input @@ -1311,11 +1312,11 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, if (procform->pronargs != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree equal image functions must have one argument"))); + errmsg("ordering equal image functions must have one argument"))); if (procform->prorettype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree equal image functions must return boolean"))); + errmsg("ordering equal image functions must return boolean"))); /* * pg_amproc functions are indexed by (lefttype, righttype), but @@ -1328,10 +1329,35 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid, if (member->lefttype != member->righttype) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("btree equal image functions must not be cross-type"))); + errmsg("ordering equal image functions must not be cross-type"))); + } + else if (member->number == BTSKIPSUPPORT_PROC) + { + if (procform->pronargs != 1 || + procform->proargtypes.values[0] != INTERNALOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree skip support functions must accept type \"internal\""))); + if (procform->prorettype != VOIDOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree skip support functions must return void"))); + + /* + * pg_amproc functions are indexed by (lefttype, righttype), but a + * skip support function doesn't make sense in cross-type + * scenarios. The same opclass opcintype OID is always used for + * lefttype and righttype. Providing a cross-type routine isn't + * sensible. Reject cross-type ALTER OPERATOR FAMILY ... ADD + * FUNCTION 6 statements here. + */ + if (member->lefttype != member->righttype) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree skip support functions must not be cross-type"))); } } - else if (amoid == HASH_AM_OID) + else if (GetIndexAmRoutineByAmId(amoid, false)->amcanhash) { if (member->number == HASHSTANDARD_PROC) { @@ -1507,6 +1533,29 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, recordDependencyOn(&myself, &referenced, op->ref_is_hard ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); + if (typeDepNeeded(op->lefttype, op)) + { + referenced.classId = TypeRelationId; + referenced.objectId = op->lefttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + op->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + + if (op->lefttype != op->righttype && + typeDepNeeded(op->righttype, op)) + { + referenced.classId = TypeRelationId; + referenced.objectId = op->righttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + op->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + /* A search operator also needs a dep on the referenced opfamily */ if (OidIsValid(op->sortfamily)) { @@ -1608,6 +1657,29 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, recordDependencyOn(&myself, &referenced, proc->ref_is_hard ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); + if (typeDepNeeded(proc->lefttype, proc)) + { + referenced.classId = TypeRelationId; + referenced.objectId = proc->lefttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + proc->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + + if (proc->lefttype != proc->righttype && + typeDepNeeded(proc->righttype, proc)) + { + referenced.classId = TypeRelationId; + referenced.objectId = proc->righttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + proc->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + /* Post create hook of access method procedure */ InvokeObjectPostCreateHook(AccessMethodProcedureRelationId, entryoid, 0); @@ -1616,6 +1688,57 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, table_close(rel, RowExclusiveLock); } +/* + * Detect whether a pg_amop or pg_amproc entry needs an explicit dependency + * on its lefttype or righttype. + * + * We make such a dependency unless the entry has an indirect dependency + * via its referenced operator or function. That's nearly always true + * for operators, but might well not be true for support functions. + */ +static bool +typeDepNeeded(Oid typid, OpFamilyMember *member) +{ + bool result = true; + + /* + * If the type is pinned, we don't need a dependency. This is a bit of a + * layering violation perhaps (recordDependencyOn would ignore the request + * anyway), but it's a cheap test and will frequently save a syscache + * lookup here. + */ + if (IsPinnedObject(TypeRelationId, typid)) + return false; + + /* Nope, so check the input types of the function or operator. */ + if (member->is_func) + { + Oid *argtypes; + int nargs; + + (void) get_func_signature(member->object, &argtypes, &nargs); + for (int i = 0; i < nargs; i++) + { + if (typid == argtypes[i]) + { + result = false; /* match, no dependency needed */ + break; + } + } + pfree(argtypes); + } + else + { + Oid lefttype, + righttype; + + op_input_types(member->object, &lefttype, &righttype); + if (typid == lefttype || typid == righttype) + result = false; /* match, no dependency needed */ + } + return result; +} + /* * Remove operator entries from an opfamily. diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index 5872a3e1922dd..673648f1fc6f5 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -4,7 +4,7 @@ * * Routines for operator manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,7 +14,7 @@ * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the * appropriate arguments/flags, passing the results to the - * corresponding "FooDefine" routines (in src/catalog) that do + * corresponding "FooCreate" routines (in src/backend/catalog) that do * the actual catalog-munging. These routines also verify permission * of the user to execute the command. * diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 6ff3eba8249d7..83056960fe47e 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -3,7 +3,7 @@ * policy.c * Commands for manipulating policies. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/commands/policy.c @@ -627,7 +627,7 @@ CreatePolicy(CreatePolicyStmt *stmt) table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0, RangeVarCallbackForPolicy, - (void *) stmt); + stmt); /* Open target_table to build quals. No additional lock is necessary. */ target_table = relation_open(table_id, NoLock); @@ -803,7 +803,7 @@ AlterPolicy(AlterPolicyStmt *stmt) table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0, RangeVarCallbackForPolicy, - (void *) stmt); + stmt); target_table = relation_open(table_id, NoLock); @@ -1108,7 +1108,7 @@ rename_policy(RenameStmt *stmt) table_id = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, 0, RangeVarCallbackForPolicy, - (void *) stmt); + stmt); target_table = relation_open(table_id, NoLock); diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 4f6acf67198dd..e7c8171c10207 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -9,7 +9,7 @@ * storage management for portals (but doesn't run any queries in them). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,6 +28,8 @@ #include "executor/executor.h" #include "executor/tstoreReceiver.h" #include "miscadmin.h" +#include "nodes/queryjumble.h" +#include "parser/analyze.h" #include "rewrite/rewriteHandler.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" @@ -44,6 +46,7 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa bool isTopLevel) { Query *query = castNode(Query, cstmt->query); + JumbleState *jstate = NULL; List *rewritten; PlannedStmt *plan; Portal portal; @@ -71,6 +74,13 @@ PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo pa (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot create a cursor WITH HOLD within security-restricted operation"))); + /* Query contained by DeclareCursor needs to be jumbled if requested */ + if (IsQueryIdEnabled()) + jstate = JumbleQuery(query); + + if (post_parse_analyze_hook) + (*post_parse_analyze_hook) (pstate, query, jstate); + /* * Parse analysis was done already, but we still have to run the rule * rewriter. We do not do AcquireRewriteLocks: we assume the query either @@ -417,7 +427,7 @@ PersistHoldablePortal(Portal portal) NULL); /* Fetch the result set into the tuplestore */ - ExecutorRun(queryDesc, direction, 0, false); + ExecutorRun(queryDesc, direction, 0); queryDesc->dest->rDestroy(queryDesc->dest); queryDesc->dest = NULL; diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 07257d4db9477..34b6410d6a26c 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -7,7 +7,7 @@ * accessed via the extended FE/BE query protocol. * * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/commands/prepare.c @@ -21,6 +21,9 @@ #include "access/xact.h" #include "catalog/pg_type.h" #include "commands/createas.h" +#include "commands/explain.h" +#include "commands/explain_format.h" +#include "commands/explain_state.h" #include "commands/prepare.h" #include "funcapi.h" #include "nodes/nodeFuncs.h" @@ -252,7 +255,7 @@ ExecuteQuery(ParseState *pstate, */ PortalStart(portal, paramLI, eflags, GetActiveSnapshot()); - (void) PortalRun(portal, count, false, true, dest, dest, qc); + (void) PortalRun(portal, count, false, dest, dest, qc); PortalDrop(portal, false); @@ -561,13 +564,12 @@ DropAllPreparedStatements(void) * "into" is NULL unless we are doing EXPLAIN CREATE TABLE AS EXECUTE, * in which case executing the query should result in creating that table. * - * Note: the passed-in queryString is that of the EXPLAIN EXECUTE, + * Note: the passed-in pstate's queryString is that of the EXPLAIN EXECUTE, * not the original PREPARE; we get the latter string from the plancache. */ void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, - const char *queryString, ParamListInfo params, - QueryEnvironment *queryEnv) + ParseState *pstate, ParamListInfo params) { PreparedStatement *entry; const char *query_string; @@ -610,10 +612,10 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, /* Evaluate parameters, if any */ if (entry->plansource->num_params) { - ParseState *pstate; + ParseState *pstate_params; - pstate = make_parsestate(NULL); - pstate->p_sourcetext = queryString; + pstate_params = make_parsestate(NULL); + pstate_params->p_sourcetext = pstate->p_sourcetext; /* * Need an EState to evaluate parameters; must not delete it till end @@ -624,12 +626,12 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, estate = CreateExecutorState(); estate->es_param_list_info = params; - paramLI = EvaluateParams(pstate, entry, execstmt->params, estate); + paramLI = EvaluateParams(pstate_params, entry, execstmt->params, estate); } /* Replan if needed, and acquire a transient refcount */ cplan = GetCachedPlan(entry->plansource, paramLI, - CurrentResourceOwner, queryEnv); + CurrentResourceOwner, pstate->p_queryEnv); INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SUBTRACT(planduration, planstart); @@ -655,12 +657,11 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, PlannedStmt *pstmt = lfirst_node(PlannedStmt, p); if (pstmt->commandType != CMD_UTILITY) - ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv, + ExplainOnePlan(pstmt, into, es, query_string, paramLI, pstate->p_queryEnv, &planduration, (es->buffers ? &bufusage : NULL), es->memory ? &mem_counters : NULL); else - ExplainOneUtility(pstmt->utilityStmt, into, es, query_string, - paramLI, queryEnv); + ExplainOneUtility(pstmt->utilityStmt, into, es, pstate, paramLI); /* No need for CommandCounterIncrement, as ExplainOnePlan did it */ diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 881f90017efd2..5036ac03639d6 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -3,7 +3,7 @@ * proclang.c * PostgreSQL LANGUAGE support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 6ea709988ee7d..0b23d94c38e20 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -3,7 +3,7 @@ * publicationcmds.c * publication manipulation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -38,6 +38,7 @@ #include "parser/parse_clause.h" #include "parser/parse_collate.h" #include "parser/parse_relation.h" +#include "rewrite/rewriteHandler.h" #include "storage/lmgr.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -70,6 +71,7 @@ static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok); static void PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists, AlterPublicationStmt *stmt); static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok); +static char defGetGeneratedColsOption(DefElem *def); static void @@ -78,12 +80,15 @@ parse_publication_options(ParseState *pstate, bool *publish_given, PublicationActions *pubactions, bool *publish_via_partition_root_given, - bool *publish_via_partition_root) + bool *publish_via_partition_root, + bool *publish_generated_columns_given, + char *publish_generated_columns) { ListCell *lc; *publish_given = false; *publish_via_partition_root_given = false; + *publish_generated_columns_given = false; /* defaults */ pubactions->pubinsert = true; @@ -91,6 +96,7 @@ parse_publication_options(ParseState *pstate, pubactions->pubdelete = true; pubactions->pubtruncate = true; *publish_via_partition_root = false; + *publish_generated_columns = PUBLISH_GENCOLS_NONE; /* Parse options */ foreach(lc, options) @@ -151,6 +157,13 @@ parse_publication_options(ParseState *pstate, *publish_via_partition_root_given = true; *publish_via_partition_root = defGetBoolean(defel); } + else if (strcmp(defel->defname, "publish_generated_columns") == 0) + { + if (*publish_generated_columns_given) + errorConflictingDefElem(defel, pstate); + *publish_generated_columns_given = true; + *publish_generated_columns = defGetGeneratedColsOption(defel); + } else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -245,7 +258,7 @@ contain_invalid_rfcolumn_walker(Node *node, rf_context *context) } return expression_tree_walker(node, contain_invalid_rfcolumn_walker, - (void *) context); + context); } /* @@ -325,21 +338,37 @@ pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, } /* - * Check if all columns referenced in the REPLICA IDENTITY are covered by - * the column list. + * Check for invalid columns in the publication table definition. * - * Returns true if any replica identity column is not covered by column list. + * This function evaluates two conditions: + * + * 1. Ensures that all columns referenced in the REPLICA IDENTITY are covered + * by the column list. If any column is missing, *invalid_column_list is set + * to true. + * 2. Ensures that all the generated columns referenced in the REPLICA IDENTITY + * are published, either by being explicitly named in the column list or, if + * no column list is specified, by setting the option + * publish_generated_columns to stored. If any unpublished + * generated column is found, *invalid_gen_col is set to true. + * + * Returns true if any of the above conditions are not met. */ bool -pub_collist_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, - bool pubviaroot) +pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, + bool pubviaroot, char pubgencols_type, + bool *invalid_column_list, + bool *invalid_gen_col) { - HeapTuple tuple; Oid relid = RelationGetRelid(relation); Oid publish_as_relid = RelationGetRelid(relation); - bool result = false; - Datum datum; - bool isnull; + Bitmapset *idattrs; + Bitmapset *columns = NULL; + TupleDesc desc = RelationGetDescr(relation); + Publication *pub; + int x; + + *invalid_column_list = false; + *invalid_gen_col = false; /* * For a partition, if pubviaroot is true, find the topmost ancestor that @@ -357,80 +386,148 @@ pub_collist_contains_invalid_column(Oid pubid, Relation relation, List *ancestor publish_as_relid = relid; } - tuple = SearchSysCache2(PUBLICATIONRELMAP, - ObjectIdGetDatum(publish_as_relid), - ObjectIdGetDatum(pubid)); - - if (!HeapTupleIsValid(tuple)) - return false; - - datum = SysCacheGetAttr(PUBLICATIONRELMAP, tuple, - Anum_pg_publication_rel_prattrs, - &isnull); + /* Fetch the column list */ + pub = GetPublication(pubid); + check_and_fetch_column_list(pub, publish_as_relid, NULL, &columns); - if (!isnull) + if (relation->rd_rel->relreplident == REPLICA_IDENTITY_FULL) { - int x; - Bitmapset *idattrs; - Bitmapset *columns = NULL; - /* With REPLICA IDENTITY FULL, no column list is allowed. */ - if (relation->rd_rel->relreplident == REPLICA_IDENTITY_FULL) - result = true; + *invalid_column_list = (columns != NULL); - /* Transform the column list datum to a bitmapset. */ - columns = pub_collist_to_bitmapset(NULL, datum, NULL); - - /* Remember columns that are part of the REPLICA IDENTITY */ - idattrs = RelationGetIndexAttrBitmap(relation, - INDEX_ATTR_BITMAP_IDENTITY_KEY); + /* + * As we don't allow a column list with REPLICA IDENTITY FULL, the + * publish_generated_columns option must be set to stored if the table + * has any stored generated columns. + */ + if (pubgencols_type != PUBLISH_GENCOLS_STORED && + relation->rd_att->constr && + relation->rd_att->constr->has_generated_stored) + *invalid_gen_col = true; /* - * Attnums in the bitmap returned by RelationGetIndexAttrBitmap are - * offset (to handle system columns the usual way), while column list - * does not use offset, so we can't do bms_is_subset(). Instead, we - * have to loop over the idattrs and check all of them are in the - * list. + * Virtual generated columns are currently not supported for logical + * replication at all. */ - x = -1; - while ((x = bms_next_member(idattrs, x)) >= 0) - { - AttrNumber attnum = (x + FirstLowInvalidHeapAttributeNumber); + if (relation->rd_att->constr && + relation->rd_att->constr->has_generated_virtual) + *invalid_gen_col = true; + + if (*invalid_gen_col && *invalid_column_list) + return true; + } + + /* Remember columns that are part of the REPLICA IDENTITY */ + idattrs = RelationGetIndexAttrBitmap(relation, + INDEX_ATTR_BITMAP_IDENTITY_KEY); + + /* + * Attnums in the bitmap returned by RelationGetIndexAttrBitmap are offset + * (to handle system columns the usual way), while column list does not + * use offset, so we can't do bms_is_subset(). Instead, we have to loop + * over the idattrs and check all of them are in the list. + */ + x = -1; + while ((x = bms_next_member(idattrs, x)) >= 0) + { + AttrNumber attnum = (x + FirstLowInvalidHeapAttributeNumber); + Form_pg_attribute att = TupleDescAttr(desc, attnum - 1); + if (columns == NULL) + { /* - * If pubviaroot is true, we are validating the column list of the - * parent table, but the bitmap contains the replica identity - * information of the child table. The parent/child attnums may - * not match, so translate them to the parent - get the attname - * from the child, and look it up in the parent. + * The publish_generated_columns option must be set to stored if + * the REPLICA IDENTITY contains any stored generated column. */ - if (pubviaroot) + if (att->attgenerated == ATTRIBUTE_GENERATED_STORED && pubgencols_type != PUBLISH_GENCOLS_STORED) { - /* attribute name in the child table */ - char *colname = get_attname(relid, attnum, false); - - /* - * Determine the attnum for the attribute name in parent (we - * are using the column list defined on the parent). - */ - attnum = get_attnum(publish_as_relid, colname); + *invalid_gen_col = true; + break; } - /* replica identity column, not covered by the column list */ - if (!bms_is_member(attnum, columns)) + /* + * The equivalent setting for virtual generated columns does not + * exist yet. + */ + if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) { - result = true; + *invalid_gen_col = true; break; } + + /* Skip validating the column list since it is not defined */ + continue; } - bms_free(idattrs); - bms_free(columns); + /* + * If pubviaroot is true, we are validating the column list of the + * parent table, but the bitmap contains the replica identity + * information of the child table. The parent/child attnums may not + * match, so translate them to the parent - get the attname from the + * child, and look it up in the parent. + */ + if (pubviaroot) + { + /* attribute name in the child table */ + char *colname = get_attname(relid, attnum, false); + + /* + * Determine the attnum for the attribute name in parent (we are + * using the column list defined on the parent). + */ + attnum = get_attnum(publish_as_relid, colname); + } + + /* replica identity column, not covered by the column list */ + *invalid_column_list |= !bms_is_member(attnum, columns); + + if (*invalid_column_list && *invalid_gen_col) + break; } - ReleaseSysCache(tuple); + bms_free(columns); + bms_free(idattrs); - return result; + return *invalid_column_list || *invalid_gen_col; +} + +/* + * Invalidate entries in the RelationSyncCache for relations included in the + * specified publication, either via FOR TABLE or FOR TABLES IN SCHEMA. + * + * If 'puballtables' is true, invalidate all cache entries. + */ +void +InvalidatePubRelSyncCache(Oid pubid, bool puballtables) +{ + if (puballtables) + { + CacheInvalidateRelSyncAll(); + } + else + { + List *relids = NIL; + List *schemarelids = NIL; + + /* + * For partitioned tables, we must invalidate all partitions and + * itself. WAL records for INSERT/UPDATE/DELETE specify leaf tables as + * a target. However, WAL records for TRUNCATE specify both a root and + * its leaves. + */ + relids = GetPublicationRelations(pubid, + PUBLICATION_PART_ALL); + schemarelids = GetAllSchemaPublicationRelations(pubid, + PUBLICATION_PART_ALL); + + relids = list_concat_unique_oid(relids, schemarelids); + + /* Invalidate the relsyncache */ + foreach_oid(relid, relids) + CacheInvalidateRelSync(relid); + } + + return; } /* check_functions_in_node callback */ @@ -559,7 +656,7 @@ check_simple_rowfilter_expr_walker(Node *node, ParseState *pstate) if (exprType(node) >= FirstNormalObjectId) errdetail_msg = _("User-defined types are not allowed."); else if (check_functions_in_node(node, contain_mutable_or_user_functions_checker, - (void *) pstate)) + pstate)) errdetail_msg = _("User-defined or built-in mutable functions are not allowed."); else if (exprCollation(node) >= FirstNormalObjectId || exprInputCollation(node) >= FirstNormalObjectId) @@ -578,7 +675,7 @@ check_simple_rowfilter_expr_walker(Node *node, ParseState *pstate) parser_errposition(pstate, exprLocation(node)))); return expression_tree_walker(node, check_simple_rowfilter_expr_walker, - (void *) pstate); + pstate); } /* @@ -650,6 +747,8 @@ TransformPubWhereClauses(List *tables, const char *queryString, /* Fix up collation information */ assign_expr_collations(pstate, whereclause); + whereclause = expand_generated_columns_in_expr(whereclause, pri->relation, 1); + /* * We allow only simple expressions in row filters. See * check_simple_rowfilter_expr_walker. @@ -737,6 +836,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) PublicationActions pubactions; bool publish_via_partition_root_given; bool publish_via_partition_root; + bool publish_generated_columns_given; + char publish_generated_columns; AclResult aclresult; List *relations = NIL; List *schemaidlist = NIL; @@ -776,7 +877,9 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) stmt->options, &publish_given, &pubactions, &publish_via_partition_root_given, - &publish_via_partition_root); + &publish_via_partition_root, + &publish_generated_columns_given, + &publish_generated_columns); puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId, Anum_pg_publication_oid); @@ -793,6 +896,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) BoolGetDatum(pubactions.pubtruncate); values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root); + values[Anum_pg_publication_pubgencols - 1] = + CharGetDatum(publish_generated_columns); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); @@ -878,6 +983,8 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, PublicationActions pubactions; bool publish_via_partition_root_given; bool publish_via_partition_root; + bool publish_generated_columns_given; + char publish_generated_columns; ObjectAddress obj; Form_pg_publication pubform; List *root_relids = NIL; @@ -887,7 +994,9 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, stmt->options, &publish_given, &pubactions, &publish_via_partition_root_given, - &publish_via_partition_root); + &publish_via_partition_root, + &publish_generated_columns_given, + &publish_generated_columns); pubform = (Form_pg_publication) GETSTRUCT(tup); @@ -997,6 +1106,12 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, replaces[Anum_pg_publication_pubviaroot - 1] = true; } + if (publish_generated_columns_given) + { + values[Anum_pg_publication_pubgencols - 1] = CharGetDatum(publish_generated_columns); + replaces[Anum_pg_publication_pubgencols - 1] = true; + } + tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, replaces); @@ -1176,21 +1291,13 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup, newrelid = RelationGetRelid(newpubrel->relation); /* - * If the new publication has column list, transform it to a - * bitmap too. + * Validate the column list. If the column list or WHERE + * clause changes, then the validation done here will be + * duplicated inside PublicationAddTables(). The validation + * is cheap enough that that seems harmless. */ - if (newpubrel->columns) - { - ListCell *lc; - - foreach(lc, newpubrel->columns) - { - char *colname = strVal(lfirst(lc)); - AttrNumber attnum = get_attnum(newrelid, colname); - - newcolumns = bms_add_member(newcolumns, attnum); - } - } + newcolumns = pub_collist_validate(newpubrel->relation, + newpubrel->columns); /* * Check if any of the new set of relations matches with the @@ -1199,7 +1306,7 @@ AlterPublicationTables(AlterPublicationStmt *stmt, HeapTuple tup, * expressions also match. Same for the column list. Drop the * rest. */ - if (RelationGetRelid(newpubrel->relation) == oldrelid) + if (newrelid == oldrelid) { if (equal(oldrelwhereclause, newpubrel->whereClause) && bms_equal(oldcolumns, newcolumns)) @@ -1945,7 +2052,7 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId) { - Oid subid; + Oid pubid; HeapTuple tup; Relation rel; ObjectAddress address; @@ -1961,11 +2068,11 @@ AlterPublicationOwner(const char *name, Oid newOwnerId) errmsg("publication \"%s\" does not exist", name))); pubform = (Form_pg_publication) GETSTRUCT(tup); - subid = pubform->oid; + pubid = pubform->oid; AlterPublicationOwner_internal(rel, tup, newOwnerId); - ObjectAddressSet(address, PublicationRelationId, subid); + ObjectAddressSet(address, PublicationRelationId, pubid); heap_freetuple(tup); @@ -1978,19 +2085,19 @@ AlterPublicationOwner(const char *name, Oid newOwnerId) * Change publication owner -- by OID */ void -AlterPublicationOwner_oid(Oid subid, Oid newOwnerId) +AlterPublicationOwner_oid(Oid pubid, Oid newOwnerId) { HeapTuple tup; Relation rel; rel = table_open(PublicationRelationId, RowExclusiveLock); - tup = SearchSysCacheCopy1(PUBLICATIONOID, ObjectIdGetDatum(subid)); + tup = SearchSysCacheCopy1(PUBLICATIONOID, ObjectIdGetDatum(pubid)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("publication with OID %u does not exist", subid))); + errmsg("publication with OID %u does not exist", pubid))); AlterPublicationOwner_internal(rel, tup, newOwnerId); @@ -1998,3 +2105,33 @@ AlterPublicationOwner_oid(Oid subid, Oid newOwnerId) table_close(rel, RowExclusiveLock); } + +/* + * Extract the publish_generated_columns option value from a DefElem. "stored" + * and "none" values are accepted. + */ +static char +defGetGeneratedColsOption(DefElem *def) +{ + char *sval; + + /* + * If no parameter value given, assume "stored" is meant. + */ + if (!def->arg) + return PUBLISH_GENCOLS_STORED; + + sval = defGetString(def); + + if (pg_strcasecmp(sval, "none") == 0) + return PUBLISH_GENCOLS_NONE; + if (pg_strcasecmp(sval, "stored") == 0) + return PUBLISH_GENCOLS_STORED; + + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s requires a \"none\" or \"stored\" value", + def->defname)); + + return PUBLISH_GENCOLS_NONE; /* keep compiler quiet */ +} diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 233f8ad1d4473..546160f09410e 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -3,7 +3,7 @@ * schemacmds.c * schema creation/manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index 5607273bf9ff0..cee5d7bbb9c7e 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -3,7 +3,7 @@ * seclabel.c * routines to support security label feature. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * ------------------------------------------------------------------------- diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 9f28d40466b5a..451ae6f7f6940 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -3,7 +3,7 @@ * sequence.c * PostgreSQL sequences support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -415,8 +415,8 @@ fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum) xlrec.locator = rel->rd_locator; - XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec)); - XLogRegisterData((char *) tuple->t_data, tuple->t_len); + XLogRegisterData(&xlrec, sizeof(xl_seq_rec)); + XLogRegisterData(tuple->t_data, tuple->t_len); recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG); @@ -745,9 +745,9 @@ nextval_internal(Oid relid, bool check_permissions) if (!cycle) ereport(ERROR, (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED), - errmsg("nextval: reached maximum value of sequence \"%s\" (%lld)", + errmsg("nextval: reached maximum value of sequence \"%s\" (%" PRId64 ")", RelationGetRelationName(seqrel), - (long long) maxv))); + maxv))); next = minv; } else @@ -764,9 +764,9 @@ nextval_internal(Oid relid, bool check_permissions) if (!cycle) ereport(ERROR, (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED), - errmsg("nextval: reached minimum value of sequence \"%s\" (%lld)", + errmsg("nextval: reached minimum value of sequence \"%s\" (%" PRId64 ")", RelationGetRelationName(seqrel), - (long long) minv))); + minv))); next = maxv; } else @@ -840,8 +840,8 @@ nextval_internal(Oid relid, bool check_permissions) xlrec.locator = seqrel->rd_locator; - XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec)); - XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len); + XLogRegisterData(&xlrec, sizeof(xl_seq_rec)); + XLogRegisterData(seqdatatuple.t_data, seqdatatuple.t_len); recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG); @@ -988,9 +988,9 @@ do_setval(Oid relid, int64 next, bool iscalled) if ((next < minv) || (next > maxv)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)", - (long long) next, RelationGetRelationName(seqrel), - (long long) minv, (long long) maxv))); + errmsg("setval: value %" PRId64 " is out of bounds for sequence \"%s\" (%" PRId64 "..%" PRId64 ")", + next, RelationGetRelationName(seqrel), + minv, maxv))); /* Set the currval() state only if iscalled = true */ if (iscalled) @@ -1026,8 +1026,8 @@ do_setval(Oid relid, int64 next, bool iscalled) XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT); xlrec.locator = seqrel->rd_locator; - XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec)); - XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len); + XLogRegisterData(&xlrec, sizeof(xl_seq_rec)); + XLogRegisterData(seqdatatuple.t_data, seqdatatuple.t_len); recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG); @@ -1347,7 +1347,10 @@ init_params(ParseState *pstate, List *options, bool for_identity, /* * The parser allows this, but it is only for identity columns, in * which case it is filtered out in parse_utilcmd.c. We only get - * here if someone puts it into a CREATE SEQUENCE. + * here if someone puts it into a CREATE SEQUENCE, where it'd be + * redundant. (The same is true for the equally-nonstandard + * LOGGED and UNLOGGED options, but for those, the default error + * below seems sufficient.) */ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -1460,8 +1463,8 @@ init_params(ParseState *pstate, List *options, bool for_identity, || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MAXVALUE (%lld) is out of range for sequence data type %s", - (long long) seqform->seqmax, + errmsg("MAXVALUE (%" PRId64 ") is out of range for sequence data type %s", + seqform->seqmax, format_type_be(seqform->seqtypid)))); /* MINVALUE (null arg means NO MINVALUE) */ @@ -1492,17 +1495,17 @@ init_params(ParseState *pstate, List *options, bool for_identity, || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MINVALUE (%lld) is out of range for sequence data type %s", - (long long) seqform->seqmin, + errmsg("MINVALUE (%" PRId64 ") is out of range for sequence data type %s", + seqform->seqmin, format_type_be(seqform->seqtypid)))); /* crosscheck min/max */ if (seqform->seqmin >= seqform->seqmax) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MINVALUE (%lld) must be less than MAXVALUE (%lld)", - (long long) seqform->seqmin, - (long long) seqform->seqmax))); + errmsg("MINVALUE (%" PRId64 ") must be less than MAXVALUE (%" PRId64 ")", + seqform->seqmin, + seqform->seqmax))); /* START WITH */ if (start_value != NULL) @@ -1521,15 +1524,15 @@ init_params(ParseState *pstate, List *options, bool for_identity, if (seqform->seqstart < seqform->seqmin) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("START value (%lld) cannot be less than MINVALUE (%lld)", - (long long) seqform->seqstart, - (long long) seqform->seqmin))); + errmsg("START value (%" PRId64 ") cannot be less than MINVALUE (%" PRId64 ")", + seqform->seqstart, + seqform->seqmin))); if (seqform->seqstart > seqform->seqmax) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("START value (%lld) cannot be greater than MAXVALUE (%lld)", - (long long) seqform->seqstart, - (long long) seqform->seqmax))); + errmsg("START value (%" PRId64 ") cannot be greater than MAXVALUE (%" PRId64 ")", + seqform->seqstart, + seqform->seqmax))); /* RESTART [WITH] */ if (restart_value != NULL) @@ -1551,15 +1554,15 @@ init_params(ParseState *pstate, List *options, bool for_identity, if (seqdataform->last_value < seqform->seqmin) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("RESTART value (%lld) cannot be less than MINVALUE (%lld)", - (long long) seqdataform->last_value, - (long long) seqform->seqmin))); + errmsg("RESTART value (%" PRId64 ") cannot be less than MINVALUE (%" PRId64 ")", + seqdataform->last_value, + seqform->seqmin))); if (seqdataform->last_value > seqform->seqmax) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("RESTART value (%lld) cannot be greater than MAXVALUE (%lld)", - (long long) seqdataform->last_value, - (long long) seqform->seqmax))); + errmsg("RESTART value (%" PRId64 ") cannot be greater than MAXVALUE (%" PRId64 ")", + seqdataform->last_value, + seqform->seqmax))); /* CACHE */ if (cache_value != NULL) @@ -1568,8 +1571,8 @@ init_params(ParseState *pstate, List *options, bool for_identity, if (seqform->seqcache <= 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("CACHE (%lld) must be greater than zero", - (long long) seqform->seqcache))); + errmsg("CACHE (%" PRId64 ") must be greater than zero", + seqform->seqcache))); seqdataform->log_cnt = 0; } else if (isInit) @@ -1773,6 +1776,66 @@ pg_sequence_parameters(PG_FUNCTION_ARGS) return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); } + +/* + * Return the sequence tuple. + * + * This is primarily intended for use by pg_dump to gather sequence data + * without needing to individually query each sequence relation. + */ +Datum +pg_get_sequence_data(PG_FUNCTION_ARGS) +{ +#define PG_GET_SEQUENCE_DATA_COLS 2 + Oid relid = PG_GETARG_OID(0); + SeqTable elm; + Relation seqrel; + Datum values[PG_GET_SEQUENCE_DATA_COLS] = {0}; + bool isnull[PG_GET_SEQUENCE_DATA_COLS] = {0}; + TupleDesc resultTupleDesc; + HeapTuple resultHeapTuple; + Datum result; + + resultTupleDesc = CreateTemplateTupleDesc(PG_GET_SEQUENCE_DATA_COLS); + TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "last_value", + INT8OID, -1, 0); + TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "is_called", + BOOLOID, -1, 0); + resultTupleDesc = BlessTupleDesc(resultTupleDesc); + + init_sequence(relid, &elm, &seqrel); + + /* + * Return all NULLs for sequences for which we lack privileges, other + * sessions' temporary sequences, and unlogged sequences on standbys. + */ + if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT) == ACLCHECK_OK && + !RELATION_IS_OTHER_TEMP(seqrel) && + (RelationIsPermanent(seqrel) || !RecoveryInProgress())) + { + Buffer buf; + HeapTupleData seqtuple; + Form_pg_sequence_data seq; + + seq = read_seq_tuple(seqrel, &buf, &seqtuple); + + values[0] = Int64GetDatum(seq->last_value); + values[1] = BoolGetDatum(seq->is_called); + + UnlockReleaseBuffer(buf); + } + else + memset(isnull, true, sizeof(isnull)); + + sequence_close(seqrel, NoLock); + + resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull); + result = HeapTupleGetDatum(resultHeapTuple); + PG_RETURN_DATUM(result); +#undef PG_GET_SEQUENCE_DATA_COLS +} + + /* * Return the last value from the sequence * diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 1db3ef69d22fc..e24d540cd45ba 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -3,7 +3,7 @@ * statscmds.c * Commands for creating and altering extended statistics objects * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -246,6 +246,12 @@ CreateStatistics(CreateStatsStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("statistics creation on system columns is not supported"))); + /* Disallow use of virtual generated columns in extended stats */ + if (attForm->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("statistics creation on virtual generated columns is not supported"))); + /* Disallow data types without a less-than operator */ type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR); if (type->lt_opr == InvalidOid) @@ -269,6 +275,12 @@ CreateStatistics(CreateStatsStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("statistics creation on system columns is not supported"))); + /* Disallow use of virtual generated columns in extended stats */ + if (get_attgenerated(relid, var->varattno) == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("statistics creation on virtual generated columns is not supported"))); + /* Disallow data types without a less-than operator */ type = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR); if (type->lt_opr == InvalidOid) @@ -290,7 +302,6 @@ CreateStatistics(CreateStatsStmt *stmt) Assert(expr != NULL); - /* Disallow expressions referencing system attributes. */ pull_varattnos(expr, 1, &attnums); k = -1; @@ -298,10 +309,17 @@ CreateStatistics(CreateStatsStmt *stmt) { AttrNumber attnum = k + FirstLowInvalidHeapAttributeNumber; + /* Disallow expressions referencing system attributes. */ if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("statistics creation on system columns is not supported"))); + + /* Disallow use of virtual generated columns in extended stats */ + if (get_attgenerated(relid, attnum) == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("statistics creation on virtual generated columns is not supported"))); } /* diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index d124bfe55caaa..4aec73bcc6bbc 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -3,7 +3,7 @@ * subscriptioncmds.c * subscription catalog manipulation functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -151,7 +151,7 @@ parse_subscription_options(ParseState *pstate, List *stmt_options, if (IsSet(supported_opts, SUBOPT_BINARY)) opts->binary = false; if (IsSet(supported_opts, SUBOPT_STREAMING)) - opts->streaming = LOGICALREP_STREAM_OFF; + opts->streaming = LOGICALREP_STREAM_PARALLEL; if (IsSet(supported_opts, SUBOPT_TWOPHASE_COMMIT)) opts->twophase = false; if (IsSet(supported_opts, SUBOPT_DISABLE_ON_ERR)) @@ -439,37 +439,6 @@ parse_subscription_options(ParseState *pstate, List *stmt_options, } } -/* - * Add publication names from the list to a string. - */ -static void -get_publications_str(List *publications, StringInfo dest, bool quote_literal) -{ - ListCell *lc; - bool first = true; - - Assert(publications != NIL); - - foreach(lc, publications) - { - char *pubname = strVal(lfirst(lc)); - - if (first) - first = false; - else - appendStringInfoString(dest, ", "); - - if (quote_literal) - appendStringInfoString(dest, quote_literal_cstr(pubname)); - else - { - appendStringInfoChar(dest, '"'); - appendStringInfoString(dest, pubname); - appendStringInfoChar(dest, '"'); - } - } -} - /* * Check that the specified publications are present on the publisher. */ @@ -486,7 +455,7 @@ check_publications(WalReceiverConn *wrconn, List *publications) appendStringInfoString(cmd, "SELECT t.pubname FROM\n" " pg_catalog.pg_publication t WHERE\n" " t.pubname IN ("); - get_publications_str(publications, cmd, true); + GetPublicationsStr(publications, cmd, true); appendStringInfoChar(cmd, ')'); res = walrcv_exec(wrconn, cmd->data, 1, tableRow); @@ -523,7 +492,7 @@ check_publications(WalReceiverConn *wrconn, List *publications) /* Prepare the list of non-existent publication(s) for error message. */ StringInfo pubnames = makeStringInfo(); - get_publications_str(publicationsCopy, pubnames, false); + GetPublicationsStr(publicationsCopy, pubnames, false); ereport(WARNING, errcode(ERRCODE_UNDEFINED_OBJECT), errmsg_plural("publication %s does not exist on the publisher", @@ -1098,7 +1067,7 @@ CheckAlterSubOption(Subscription *sub, const char *option, if (sub->enabled) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("cannot set %s for enabled subscription", + errmsg("cannot set option \"%s\" for enabled subscription", option))); if (slot_needs_update) @@ -1112,7 +1081,7 @@ CheckAlterSubOption(Subscription *sub, const char *option, if (!sub->slotname) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("cannot set %s for a subscription that does not have a slot name", + errmsg("cannot set option \"%s\" for a subscription that does not have a slot name", option))); /* The changed option of the slot can't be rolled back. */ @@ -2114,11 +2083,12 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId) } /* - * Check and log a warning if the publisher has subscribed to the same table - * from some other publisher. This check is required only if "copy_data = true" - * and "origin = none" for CREATE SUBSCRIPTION and - * ALTER SUBSCRIPTION ... REFRESH statements to notify the user that data - * having origin might have been copied. + * Check and log a warning if the publisher has subscribed to the same table, + * its partition ancestors (if it's a partition), or its partition children (if + * it's a partitioned table), from some other publishers. This check is + * required only if "copy_data = true" and "origin = none" for CREATE + * SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH statements to notify the + * user that data having origin might have been copied. * * This check need not be performed on the tables that are already added * because incremental sync for those tables will happen through WAL and the @@ -2148,10 +2118,12 @@ check_publications_origin(WalReceiverConn *wrconn, List *publications, "SELECT DISTINCT P.pubname AS pubname\n" "FROM pg_publication P,\n" " LATERAL pg_get_publication_tables(P.pubname) GPT\n" - " JOIN pg_subscription_rel PS ON (GPT.relid = PS.srrelid),\n" + " JOIN pg_subscription_rel PS ON (GPT.relid = PS.srrelid OR" + " GPT.relid IN (SELECT relid FROM pg_partition_ancestors(PS.srrelid) UNION" + " SELECT relid FROM pg_partition_tree(PS.srrelid))),\n" " pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)\n" "WHERE C.oid = GPT.relid AND P.pubname IN ("); - get_publications_str(publications, &cmd, true); + GetPublicationsStr(publications, &cmd, true); appendStringInfoString(&cmd, ")\n"); /* @@ -2208,7 +2180,7 @@ check_publications_origin(WalReceiverConn *wrconn, List *publications, StringInfo pubnames = makeStringInfo(); /* Prepare the list of publication(s) for warning message. */ - get_publications_str(publist, pubnames, false); + GetPublicationsStr(publist, pubnames, false); ereport(WARNING, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin", @@ -2243,17 +2215,17 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications) List *tablelist = NIL; int server_version = walrcv_server_version(wrconn); bool check_columnlist = (server_version >= 150000); + StringInfo pub_names = makeStringInfo(); initStringInfo(&cmd); + /* Build the pub_names comma-separated string. */ + GetPublicationsStr(publications, pub_names, true); + /* Get the list of tables from the publisher. */ if (server_version >= 160000) { - StringInfoData pub_names; - tableRow[2] = INT2VECTOROID; - initStringInfo(&pub_names); - get_publications_str(publications, &pub_names, true); /* * From version 16, we allowed passing multiple publications to the @@ -2266,7 +2238,7 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications) * * Note that attrs are always stored in sorted order so we don't need * to worry if different publications have specified them in a - * different order. See publication_translate_columns. + * different order. See pub_collist_validate. */ appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname, gpt.attrs\n" " FROM pg_class c\n" @@ -2275,9 +2247,7 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications) " FROM pg_publication\n" " WHERE pubname IN ( %s )) AS gpt\n" " ON gpt.relid = c.oid\n", - pub_names.data); - - pfree(pub_names.data); + pub_names->data); } else { @@ -2288,12 +2258,13 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications) if (check_columnlist) appendStringInfoString(&cmd, ", t.attnames\n"); - appendStringInfoString(&cmd, "FROM pg_catalog.pg_publication_tables t\n" - " WHERE t.pubname IN ("); - get_publications_str(publications, &cmd, true); - appendStringInfoChar(&cmd, ')'); + appendStringInfo(&cmd, "FROM pg_catalog.pg_publication_tables t\n" + " WHERE t.pubname IN ( %s )", + pub_names->data); } + destroyStringInfo(pub_names); + res = walrcv_exec(wrconn, cmd.data, check_columnlist ? 3 : 2, tableRow); pfree(cmd.data); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 0b2a52463f16b..ea96947d81305 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3,7 +3,7 @@ * tablecmds.c * Commands for creating and altering table structures and settings * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -16,6 +16,7 @@ #include "access/attmap.h" #include "access/genam.h" +#include "access/gist.h" #include "access/heapam.h" #include "access/heapam_xlog.h" #include "access/multixact.h" @@ -65,6 +66,7 @@ #include "commands/typecmds.h" #include "commands/user.h" #include "commands/vacuum.h" +#include "common/int.h" #include "executor/executor.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" @@ -215,6 +217,7 @@ typedef struct NewConstraint ConstrType contype; /* CHECK or FOREIGN */ Oid refrelid; /* PK rel, if FOREIGN */ Oid refindid; /* OID of PK's index, if FOREIGN */ + bool conwithperiod; /* Whether the new FOREIGN KEY uses PERIOD */ Oid conid; /* OID of pg_constraint entry, if FOREIGN */ Node *qual; /* Check expr or CONSTR_FOREIGN Constraint */ ExprState *qualstate; /* Execution state for CHECK expr */ @@ -330,6 +333,7 @@ struct DropRelationCallbackState #define ATT_FOREIGN_TABLE 0x0020 #define ATT_PARTITIONED_INDEX 0x0040 #define ATT_SEQUENCE 0x0080 +#define ATT_PARTITIONED_TABLE 0x0100 /* * ForeignTruncateInfo @@ -345,6 +349,14 @@ typedef struct ForeignTruncateInfo List *rels; } ForeignTruncateInfo; +/* Partial or complete FK creation in addFkConstraint() */ +typedef enum addFkConstraintSides +{ + addFkReferencedSide, + addFkReferencingSide, + addFkBothSides, +} addFkConstraintSides; + /* * Partition tables are expected to be dropped when the parent partitioned * table gets dropped. Hence for partitioning we use AUTO dependency. @@ -359,8 +371,9 @@ static void truncate_check_activity(Relation rel); static void RangeVarCallbackForTruncate(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); static List *MergeAttributes(List *columns, const List *supers, char relpersistence, - bool is_partition, List **supconstr); -static List *MergeCheckConstraint(List *constraints, const char *name, Node *expr); + bool is_partition, List **supconstr, + List **supnotnulls); +static List *MergeCheckConstraint(List *constraints, const char *name, Node *expr, bool is_enforced); static void MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const ColumnDef *newdef); static ColumnDef *MergeInheritedAttribute(List *inh_columns, int exist_attno, const ColumnDef *newdef); static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispartition); @@ -376,29 +389,71 @@ static void AlterIndexNamespaces(Relation classRel, Relation rel, static void AlterSeqNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved, LOCKMODE lockmode); -static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, - bool recurse, bool recursing, LOCKMODE lockmode); -static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel, - Relation rel, HeapTuple contuple, List **otherrelids, - LOCKMODE lockmode); +static ObjectAddress ATExecAlterConstraint(List **wqueue, Relation rel, + ATAlterConstraint *cmdcon, + bool recurse, LOCKMODE lockmode); +static bool ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon, Relation conrel, + Relation tgrel, Relation rel, HeapTuple contuple, + bool recurse, LOCKMODE lockmode); +static bool ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, + Oid fkrelid, Oid pkrelid, + HeapTuple contuple, LOCKMODE lockmode, + Oid ReferencedParentDelTrigger, + Oid ReferencedParentUpdTrigger, + Oid ReferencingParentInsTrigger, + Oid ReferencingParentUpdTrigger); +static bool ATExecAlterConstrDeferrability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, Relation rel, + HeapTuple contuple, bool recurse, + List **otherrelids, LOCKMODE lockmode); +static bool ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation rel, + HeapTuple contuple, LOCKMODE lockmode); +static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, + bool deferrable, bool initdeferred, + List **otherrelids); +static void AlterConstrEnforceabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, + Oid fkrelid, Oid pkrelid, + HeapTuple contuple, LOCKMODE lockmode, + Oid ReferencedParentDelTrigger, + Oid ReferencedParentUpdTrigger, + Oid ReferencingParentInsTrigger, + Oid ReferencingParentUpdTrigger); +static void AlterConstrDeferrabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, Relation rel, + HeapTuple contuple, bool recurse, + List **otherrelids, LOCKMODE lockmode); +static void AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, + HeapTuple contuple); static ObjectAddress ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName, bool recurse, bool recursing, LOCKMODE lockmode); +static void QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, + Oid pkrelid, HeapTuple contuple, LOCKMODE lockmode); +static void QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, + char *constrName, HeapTuple contuple, + bool recurse, bool recursing, LOCKMODE lockmode); +static void QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, + HeapTuple contuple, bool recurse, bool recursing, + LOCKMODE lockmode); static int transformColumnNameList(Oid relId, List *colList, - int16 *attnums, Oid *atttypids); + int16 *attnums, Oid *atttypids, Oid *attcollids); static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid, List **attnamelist, - int16 *attnums, Oid *atttypids, - Oid *opclasses); + int16 *attnums, Oid *atttypids, Oid *attcollids, + Oid *opclasses, bool *pk_has_without_overlaps); static Oid transformFkeyCheckAttrs(Relation pkrel, int numattrs, int16 *attnums, - Oid *opclasses); + bool with_period, Oid *opclasses, + bool *pk_has_without_overlaps); static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts); static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId, Oid *funcid); static void validateForeignKeyConstraint(char *conname, Relation rel, Relation pkrel, - Oid pkindOid, Oid constraintOid); + Oid pkindOid, Oid constraintOid, bool hasperiod); static void CheckAlterTableIsSafe(Relation rel); static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode, @@ -419,7 +474,7 @@ static AlterTableCmd *ATParseTransformCmd(List **wqueue, AlteredTableInfo *tab, static void ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, AlterTableUtilityContext *context); -static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode); +static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap); static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel); static void ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets); static void ATSimpleRecursion(List **wqueue, Relation rel, @@ -443,16 +498,14 @@ static bool check_for_column_name_collision(Relation rel, const char *colname, bool if_not_exists); static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid); static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid); -static void ATPrepDropNotNull(Relation rel, bool recurse, bool recursing); -static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode); -static void ATPrepSetNotNull(List **wqueue, Relation rel, - AlterTableCmd *cmd, bool recurse, bool recursing, - LOCKMODE lockmode, - AlterTableUtilityContext *context); -static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, - const char *colName, LOCKMODE lockmode); -static void ATExecCheckNotNull(AlteredTableInfo *tab, Relation rel, - const char *colName, LOCKMODE lockmode); +static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, bool recurse, + LOCKMODE lockmode); +static void set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, + bool is_valid, bool queue_validation); +static ObjectAddress ATExecSetNotNull(List **wqueue, Relation rel, + char *conName, char *colName, + bool recurse, bool recursing, + LOCKMODE lockmode); static bool NotNullImpliedByRelConstraints(Relation rel, Form_pg_attribute attr); static bool ConstraintImpliedByRelConstraint(Relation scanrel, List *testConstraint, List *provenConstraint); @@ -484,6 +537,10 @@ static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *c bool recurse, bool recursing, bool missing_ok, LOCKMODE lockmode, ObjectAddresses *addrs); +static void ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd, + bool recurse, LOCKMODE lockmode, + AlterTableUtilityContext *context); +static void verifyNotNullPKCompatible(HeapTuple tuple, const char *colname); static ObjectAddress ATExecAddIndex(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode); static ObjectAddress ATExecAddStatistics(AlteredTableInfo *tab, Relation rel, @@ -495,32 +552,44 @@ static ObjectAddress ATExecAddConstraint(List **wqueue, static char *ChooseForeignKeyConstraintNameAddition(List *colnames); static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel, IndexStmt *stmt, LOCKMODE lockmode); -static ObjectAddress ATAddCheckConstraint(List **wqueue, - AlteredTableInfo *tab, Relation rel, - Constraint *constr, - bool recurse, bool recursing, bool is_readd, - LOCKMODE lockmode); +static ObjectAddress ATAddCheckNNConstraint(List **wqueue, + AlteredTableInfo *tab, Relation rel, + Constraint *constr, + bool recurse, bool recursing, bool is_readd, + LOCKMODE lockmode); static ObjectAddress ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Constraint *fkconstraint, bool recurse, bool recursing, LOCKMODE lockmode); -static ObjectAddress addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, - Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr, - int numfks, int16 *pkattnum, int16 *fkattnum, - Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators, - int numfkdelsetcols, int16 *fkdelsetcols, - bool old_check_ok, - Oid parentDelTrigger, Oid parentUpdTrigger); -static void validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums, - int numfksetcols, const int16 *fksetcolsattnums, +static int validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums, + int numfksetcols, int16 *fksetcolsattnums, List *fksetcols); +static ObjectAddress addFkConstraint(addFkConstraintSides fkside, + char *constraintname, + Constraint *fkconstraint, Relation rel, + Relation pkrel, Oid indexOid, + Oid parentConstr, + int numfks, int16 *pkattnum, int16 *fkattnum, + Oid *pfeqoperators, Oid *ppeqoperators, + Oid *ffeqoperators, int numfkdelsetcols, + int16 *fkdelsetcols, bool is_internal, + bool with_period); +static void addFkRecurseReferenced(Constraint *fkconstraint, + Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr, + int numfks, int16 *pkattnum, int16 *fkattnum, + Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators, + int numfkdelsetcols, int16 *fkdelsetcols, + bool old_check_ok, + Oid parentDelTrigger, Oid parentUpdTrigger, + bool with_period); static void addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr, int numfks, int16 *pkattnum, int16 *fkattnum, Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators, int numfkdelsetcols, int16 *fkdelsetcols, bool old_check_ok, LOCKMODE lockmode, - Oid parentInsTrigger, Oid parentUpdTrigger); + Oid parentInsTrigger, Oid parentUpdTrigger, + bool with_period); static void CloneForeignKeyConstraints(List **wqueue, Relation parentRel, Relation partitionRel); static void CloneFkReferenced(Relation parentRel, Relation partitionRel); @@ -531,19 +600,28 @@ static void createForeignKeyCheckTriggers(Oid myRelOid, Oid refRelOid, Oid indexOid, Oid parentInsTrigger, Oid parentUpdTrigger, Oid *insertTrigOid, Oid *updateTrigOid); -static void createForeignKeyActionTriggers(Relation rel, Oid refRelOid, +static void createForeignKeyActionTriggers(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, Oid constraintOid, Oid indexOid, Oid parentDelTrigger, Oid parentUpdTrigger, Oid *deleteTrigOid, Oid *updateTrigOid); -static bool tryAttachPartitionForeignKey(ForeignKeyCacheInfo *fk, - Oid partRelid, +static bool tryAttachPartitionForeignKey(List **wqueue, + ForeignKeyCacheInfo *fk, + Relation partition, Oid parentConstrOid, int numfks, AttrNumber *mapped_conkey, AttrNumber *confkey, Oid *conpfeqop, Oid parentInsTrigger, Oid parentUpdTrigger, Relation trigrel); +static void AttachPartitionForeignKey(List **wqueue, Relation partition, + Oid partConstrOid, Oid parentConstrOid, + Oid parentInsTrigger, Oid parentUpdTrigger, + Relation trigrel); +static void RemoveInheritedConstraint(Relation conrel, Relation trigrel, + Oid conoid, Oid conrelid); +static void DropForeignKeyConstraintTriggers(Relation trigrel, Oid conoid, + Oid confrelid, Oid conrelid); static void GetForeignKeyActionTriggers(Relation trigrel, Oid conoid, Oid confrelid, Oid conrelid, Oid *deleteTriggerOid, @@ -553,9 +631,12 @@ static void GetForeignKeyCheckTriggers(Relation trigrel, Oid *insertTriggerOid, Oid *updateTriggerOid); static void ATExecDropConstraint(Relation rel, const char *constrName, - DropBehavior behavior, - bool recurse, bool recursing, + DropBehavior behavior, bool recurse, bool missing_ok, LOCKMODE lockmode); +static ObjectAddress dropconstraint_internal(Relation rel, + HeapTuple constraintTup, DropBehavior behavior, + bool recurse, bool recursing, + bool missing_ok, LOCKMODE lockmode); static void ATPrepAlterColumnType(List **wqueue, AlteredTableInfo *tab, Relation rel, bool recurse, bool recursing, @@ -590,7 +671,8 @@ static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName, static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname); static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId); -static bool ATPrepChangePersistence(Relation rel, bool toLogged); +static void ATPrepChangePersistence(AlteredTableInfo *tab, Relation rel, + bool toLogged); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, const char *tablespacename, LOCKMODE lockmode); static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode); @@ -652,16 +734,12 @@ static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl); static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx, Relation partitionTbl); +static void verifyPartitionIndexNotNull(IndexInfo *iinfo, Relation partition); static List *GetParentedForeignKeyRefs(Relation partition); static void ATDetachCheckNoForeignKeyRefs(Relation partition); static char GetAttributeCompression(Oid atttypid, const char *compression); static char GetAttributeStorage(Oid atttypid, const char *storagemode); -static void ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab, - Relation rel, PartitionCmd *cmd, - AlterTableUtilityContext *context); -static void ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, - PartitionCmd *cmd, AlterTableUtilityContext *context); /* ---------------------------------------------------------------- * DefineRelation @@ -694,13 +772,15 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, TupleDesc descriptor; List *inheritOids; List *old_constraints; + List *old_notnulls; List *rawDefaults; List *cookedDefaults; + List *nncols; Datum reloptions; ListCell *listptr; AttrNumber attnum; bool partitioned; - static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; Oid ofTypeId; ObjectAddress address; LOCKMODE parentLockmode; @@ -732,6 +812,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, else partitioned = false; + if (relkind == RELKIND_PARTITIONED_TABLE && + stmt->relation->relpersistence == RELPERSISTENCE_UNLOGGED) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("partitioned tables cannot be unlogged"))); + /* * Look up the namespace in which we are supposed to create the relation, * check we have permission to create there, lock it against concurrent @@ -880,12 +966,13 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, MergeAttributes(stmt->tableElts, inheritOids, stmt->relation->relpersistence, stmt->partbound != NULL, - &old_constraints); + &old_constraints, &old_notnulls); /* * Create a tuple descriptor from the relation schema. Note that this - * deals with column names, types, and not-null constraints, but not - * default values or CHECK constraints; we handle those below. + * deals with column names, types, and in-descriptor NOT NULL flags, but + * not default values, NOT NULL or CHECK constraints; we handle those + * below. */ descriptor = BuildDescForRelation(stmt->tableElts); @@ -896,10 +983,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, * while raw defaults go into a list of RawColumnDefault structs that will * be processed by AddRelationNewConstraints. (We can't deal with raw * expressions until we can do transformExpr.) - * - * We can set the atthasdef flags now in the tuple descriptor; this just - * saves StoreAttrDefault from having to do an immediate update of the - * pg_attribute rows. */ rawDefaults = NIL; cookedDefaults = NIL; @@ -908,11 +991,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, foreach(listptr, stmt->tableElts) { ColumnDef *colDef = lfirst(listptr); - Form_pg_attribute attr; attnum++; - attr = TupleDescAttr(descriptor, attnum - 1); - if (colDef->raw_default != NULL) { RawColumnDefault *rawEnt; @@ -922,10 +1002,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt->attnum = attnum; rawEnt->raw_default = colDef->raw_default; - rawEnt->missingMode = false; rawEnt->generated = colDef->generated; rawDefaults = lappend(rawDefaults, rawEnt); - attr->atthasdef = true; } else if (colDef->cooked_default != NULL) { @@ -937,12 +1015,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, cooked->name = NULL; cooked->attnum = attnum; cooked->expr = colDef->cooked_default; + cooked->is_enforced = true; cooked->skip_validation = false; cooked->is_local = true; /* not used for defaults */ cooked->inhcount = 0; /* ditto */ cooked->is_no_inherit = false; cookedDefaults = lappend(cookedDefaults, cooked); - attr->atthasdef = true; } } @@ -969,9 +1047,9 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, } /* - * Create the relation. Inherited defaults and constraints are passed in - * for immediate handling --- since they don't need parsing, they can be - * stored immediately. + * Create the relation. Inherited defaults and CHECK constraints are + * passed in for immediate handling --- since they don't need parsing, + * they can be stored immediately. */ relationId = heap_create_with_catalog(relname, namespaceId, @@ -1257,6 +1335,17 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, AddRelationNewConstraints(rel, NIL, stmt->constraints, true, true, false, queryString); + /* + * Finally, merge the not-null constraints that are declared directly with + * those that come from parent relations (making sure to count inheritance + * appropriately for each), create them, and set the attnotnull flag on + * columns that don't yet have it. + */ + nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints, + old_notnulls); + foreach_int(attrnum, nncols) + set_attnotnull(NULL, rel, attrnum, true, false); + ObjectAddressSet(address, RelationRelationId, relationId); /* @@ -1349,6 +1438,8 @@ BuildDescForRelation(const List *columns) att->attstorage = entry->storage; else if (entry->storage_name) att->attstorage = GetAttributeStorage(att->atttypid, entry->storage_name); + + populate_compact_attribute(desc, attnum - 1); } return desc; @@ -1534,7 +1625,7 @@ RemoveRelations(DropStmt *drop) relOid = RangeVarGetRelidExtended(rel, lockmode, RVR_MISSING_OK, RangeVarCallbackForDropRelation, - (void *) &state); + &state); /* Not there? */ if (!OidIsValid(relOid)) @@ -2219,8 +2310,8 @@ ExecuteTruncateGuts(List *explicit_rels, xlrec.flags |= XLH_TRUNCATE_RESTART_SEQS; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfHeapTruncate); - XLogRegisterData((char *) logrelids, list_length(relids_logged) * sizeof(Oid)); + XLogRegisterData(&xlrec, SizeOfHeapTruncate); + XLogRegisterData(logrelids, list_length(relids_logged) * sizeof(Oid)); XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); @@ -2386,8 +2477,11 @@ storage_name(char c) * 'is_partition' tells if the table is a partition. * * Output arguments: - * 'supconstr' receives a list of constraints belonging to the parents, - * updated as necessary to be valid for the child. + * 'supconstr' receives a list of CookedConstraint representing + * CHECK constraints belonging to parent relations, updated as + * necessary to be valid for the child. + * 'supnotnulls' receives a list of CookedConstraint representing + * not-null constraints based on those from parent relations. * * Return value: * Completed schema list. @@ -2418,7 +2512,10 @@ storage_name(char c) * * Constraints (including not-null constraints) for the child table * are the union of all relevant constraints, from both the child schema - * and parent tables. + * and parent tables. In addition, in legacy inheritance, each column that + * appears in a primary key in any of the parents also gets a NOT NULL + * constraint (partitioning doesn't need this, because the PK itself gets + * inherited.) * * The default value for a child column is defined as: * (1) If the child schema specifies a default, that value is used. @@ -2437,10 +2534,11 @@ storage_name(char c) */ static List * MergeAttributes(List *columns, const List *supers, char relpersistence, - bool is_partition, List **supconstr) + bool is_partition, List **supconstr, List **supnotnulls) { List *inh_columns = NIL; List *constraints = NIL; + List *nnconstraints = NIL; bool have_bogus_defaults = false; int child_attno; static Node bogus_marker = {0}; /* marks conflicting defaults */ @@ -2551,8 +2649,10 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, AttrMap *newattmap; List *inherited_defaults; List *cols_with_defaults; + List *nnconstrs; ListCell *lc1; ListCell *lc2; + Bitmapset *nncols = NULL; /* caller already got lock */ relation = table_open(parent, NoLock); @@ -2640,6 +2740,15 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, /* We can't process inherited defaults until newattmap is complete. */ inherited_defaults = cols_with_defaults = NIL; + /* + * Request attnotnull on columns that have a not-null constraint + * that's not marked NO INHERIT (even if not valid). + */ + nnconstrs = RelationGetNotNullConstraints(RelationGetRelid(relation), + true, false); + foreach_ptr(CookedConstraint, cc, nnconstrs) + nncols = bms_add_member(nncols, cc->attnum); + for (AttrNumber parent_attno = 1; parent_attno <= tupleDesc->natts; parent_attno++) { @@ -2661,7 +2770,6 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, */ newdef = makeColumnDef(attributeName, attribute->atttypid, attribute->atttypmod, attribute->attcollation); - newdef->is_not_null = attribute->attnotnull; newdef->storage = attribute->attstorage; newdef->generated = attribute->attgenerated; if (CompressionMethodIsValid(attribute->attcompression)) @@ -2709,6 +2817,12 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, mergeddef = newdef; } + /* + * mark attnotnull if parent has it + */ + if (bms_is_member(parent_attno, nncols)) + mergeddef->is_not_null = true; + /* * Locate default/generation expression if any */ @@ -2816,10 +2930,24 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, name, RelationGetRelationName(relation)))); - constraints = MergeCheckConstraint(constraints, name, expr); + constraints = MergeCheckConstraint(constraints, name, expr, + check[i].ccenforced); } } + /* + * Also copy the not-null constraints from this parent. The + * attnotnull markings were already installed above. + */ + foreach_ptr(CookedConstraint, nn, nnconstrs) + { + Assert(nn->contype == CONSTR_NOTNULL); + + nn->attnum = newattmap->attnums[nn->attnum - 1]; + + nnconstraints = lappend(nnconstraints, nn); + } + free_attrmap(newattmap); /* @@ -2890,8 +3018,7 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, /* * Now that we have the column definition list for a partition, we can * check whether the columns referenced in the column constraint specs - * actually exist. Also, we merge parent's not-null constraints and - * defaults into each corresponding column definition. + * actually exist. Also, merge column defaults. */ if (is_partition) { @@ -2908,7 +3035,6 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, if (strcmp(coldef->colname, restdef->colname) == 0) { found = true; - coldef->is_not_null |= restdef->is_not_null; /* * Check for conflicts related to generated columns. @@ -2940,6 +3066,15 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, errhint("A child table column cannot be generated unless its parent column is."))); } + if (coldef->generated && restdef->generated && coldef->generated != restdef->generated) + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_DEFINITION), + errmsg("column \"%s\" inherits from generated column of different kind", + restdef->colname), + errdetail("Parent column is %s, child column is %s.", + coldef->generated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL", + restdef->generated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL"))); + /* * Override the parent's default value for this column * (coldef->cooked_default) with the partition's local @@ -2997,6 +3132,7 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, } *supconstr = constraints; + *supnotnulls = nnconstraints; return columns; } @@ -3018,7 +3154,7 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, * the list. */ static List * -MergeCheckConstraint(List *constraints, const char *name, Node *expr) +MergeCheckConstraint(List *constraints, const char *name, Node *expr, bool is_enforced) { ListCell *lc; CookedConstraint *newcon; @@ -3036,11 +3172,22 @@ MergeCheckConstraint(List *constraints, const char *name, Node *expr) if (equal(expr, ccon->expr)) { /* OK to merge constraint with existing */ - ccon->inhcount++; - if (ccon->inhcount < 0) + if (pg_add_s16_overflow(ccon->inhcount, 1, + &ccon->inhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + + /* + * When enforceability differs, the merged constraint should be + * marked as ENFORCED because one of the parents is ENFORCED. + */ + if (!ccon->is_enforced && is_enforced) + { + ccon->is_enforced = true; + ccon->skip_validation = false; + } + return constraints; } @@ -3059,6 +3206,8 @@ MergeCheckConstraint(List *constraints, const char *name, Node *expr) newcon->name = pstrdup(name); newcon->expr = expr; newcon->inhcount = 1; + newcon->is_enforced = is_enforced; + newcon->skip_validation = !is_enforced; return lappend(constraints, newcon); } @@ -3211,6 +3360,15 @@ MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const errhint("A child table column cannot be generated unless its parent column is."))); } + if (inhdef->generated && newdef->generated && newdef->generated != inhdef->generated) + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_DEFINITION), + errmsg("column \"%s\" inherits from generated column of different kind", + inhdef->colname), + errdetail("Parent column is %s, child column is %s.", + inhdef->generated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL", + newdef->generated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL"))); + /* * If new def has a default, override previous default */ @@ -3277,11 +3435,6 @@ MergeInheritedAttribute(List *inh_columns, format_type_with_typemod(prevtypeid, prevtypmod), format_type_with_typemod(newtypeid, newtypmod)))); - /* - * Merge of not-null constraints = OR 'em together - */ - prevdef->is_not_null |= newdef->is_not_null; - /* * Must have the same collation */ @@ -3339,8 +3492,8 @@ MergeInheritedAttribute(List *inh_columns, * Default and other constraints are handled by the caller. */ - prevdef->inhcount++; - if (prevdef->inhcount < 0) + if (pg_add_s16_overflow(prevdef->inhcount, 1, + &prevdef->inhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); @@ -3590,6 +3743,7 @@ SetRelationTableSpace(Relation rel, { Relation pg_class; HeapTuple tuple; + ItemPointerData otid; Form_pg_class rd_rel; Oid reloid = RelationGetRelid(rel); @@ -3598,9 +3752,10 @@ SetRelationTableSpace(Relation rel, /* Get a modifiable copy of the relation's pg_class row. */ pg_class = table_open(RelationRelationId, RowExclusiveLock); - tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid)); + tuple = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(reloid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", reloid); + otid = tuple->t_self; rd_rel = (Form_pg_class) GETSTRUCT(tuple); /* Update the pg_class row. */ @@ -3608,7 +3763,8 @@ SetRelationTableSpace(Relation rel, InvalidOid : newTableSpaceId; if (RelFileNumberIsValid(newRelFilenumber)) rd_rel->relfilenode = newRelFilenumber; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_class, &otid, tuple); + UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); /* * Record dependency on tablespace. This is only required for relations @@ -3917,7 +4073,10 @@ rename_constraint_internal(Oid myrelid, constraintOid); con = (Form_pg_constraint) GETSTRUCT(tuple); - if (myrelid && con->contype == CONSTRAINT_CHECK && !con->connoinherit) + if (myrelid && + (con->contype == CONSTRAINT_CHECK || + con->contype == CONSTRAINT_NOTNULL) && + !con->connoinherit) { if (recurse) { @@ -4060,7 +4219,7 @@ RenameRelation(RenameStmt *stmt) relid = RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok ? RVR_MISSING_OK : 0, RangeVarCallbackForAlterRelation, - (void *) stmt); + stmt); if (!OidIsValid(relid)) { @@ -4102,6 +4261,7 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo { Relation targetrelation; Relation relrelation; /* for RELATION relation */ + ItemPointerData otid; HeapTuple reltup; Form_pg_class relform; Oid namespaceId; @@ -4124,9 +4284,10 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo */ relrelation = table_open(RelationRelationId, RowExclusiveLock); - reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid)); + reltup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(myrelid)); if (!HeapTupleIsValid(reltup)) /* shouldn't happen */ elog(ERROR, "cache lookup failed for relation %u", myrelid); + otid = reltup->t_self; relform = (Form_pg_class) GETSTRUCT(reltup); if (get_relname_relid(newrelname, namespaceId) != InvalidOid) @@ -4151,7 +4312,8 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo */ namestrcpy(&(relform->relname), newrelname); - CatalogTupleUpdate(relrelation, &reltup->t_self, reltup); + CatalogTupleUpdate(relrelation, &otid, reltup); + UnlockTuple(relrelation, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0, InvalidOid, is_internal); @@ -4305,7 +4467,7 @@ AlterTableLookupRelation(AlterTableStmt *stmt, LOCKMODE lockmode) return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok ? RVR_MISSING_OK : 0, RangeVarCallbackForAlterRelation, - (void *) stmt); + stmt); } /* @@ -4672,23 +4834,6 @@ AlterTableGetLockLevel(List *cmds) cmd_lockmode = ShareUpdateExclusiveLock; break; - case AT_SplitPartition: - cmd_lockmode = AccessExclusiveLock; - break; - - case AT_MergePartitions: - cmd_lockmode = AccessExclusiveLock; - break; - - case AT_CheckNotNull: - - /* - * This only examines the table's schema; but lock must be - * strong enough to prevent concurrent DROP NOT NULL. - */ - cmd_lockmode = AccessShareLock; - break; - default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -4789,7 +4934,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, { case AT_AddColumn: /* ADD COLUMN */ ATSimplePermissions(cmd->subtype, rel, - ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); + ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd, lockmode, context); /* Recursion occurs during execution phase */ @@ -4810,7 +4956,9 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, * substitutes default values into INSERTs before it expands * rules. */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW | + ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); /* No command-specific prep needed */ pass = cmd->def ? AT_PASS_ADD_OTHERCONSTR : AT_PASS_DROP; @@ -4818,19 +4966,24 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_CookedColumnDefault: /* add a pre-cooked default */ /* This is currently used only in CREATE TABLE */ /* (so the permission check really isn't necessary) */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* This command never recurses */ pass = AT_PASS_ADD_OTHERCONSTR; break; case AT_AddIdentity: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW | + ATT_FOREIGN_TABLE); /* Set up recursion for phase 2; no other prep needed */ if (recurse) cmd->recurse = true; pass = AT_PASS_ADD_OTHERCONSTR; break; case AT_SetIdentity: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW | + ATT_FOREIGN_TABLE); /* Set up recursion for phase 2; no other prep needed */ if (recurse) cmd->recurse = true; @@ -4838,96 +4991,110 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; break; case AT_DropIdentity: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW | + ATT_FOREIGN_TABLE); /* Set up recursion for phase 2; no other prep needed */ if (recurse) cmd->recurse = true; pass = AT_PASS_DROP; break; case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); - ATPrepDropNotNull(rel, recurse, recursing); - ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); + /* Set up recursion for phase 2; no other prep needed */ + if (recurse) + cmd->recurse = true; pass = AT_PASS_DROP; break; case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); - /* Need command-specific recursion decision */ - ATPrepSetNotNull(wqueue, rel, cmd, recurse, recursing, - lockmode, context); - pass = AT_PASS_COL_ATTRS; - break; - case AT_CheckNotNull: /* check column is already marked NOT NULL */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); - ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); - /* No command-specific prep needed */ + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); + /* Set up recursion for phase 2; no other prep needed */ + if (recurse) + cmd->recurse = true; pass = AT_PASS_COL_ATTRS; break; case AT_SetExpression: /* ALTER COLUMN SET EXPRESSION */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); pass = AT_PASS_SET_EXPRESSION; break; case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode); pass = AT_PASS_DROP; break; case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW | + ATT_INDEX | ATT_PARTITIONED_INDEX | ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_SetOptions: /* ALTER COLUMN SET ( options ) */ case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_MATVIEW | ATT_FOREIGN_TABLE); /* This command never recurses */ pass = AT_PASS_MISC; break; case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_MATVIEW | ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_DropColumn: /* DROP COLUMN */ ATSimplePermissions(cmd->subtype, rel, - ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); + ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd, lockmode, context); /* Recursion occurs during execution phase */ pass = AT_PASS_DROP; break; case AT_AddIndex: /* ADD INDEX */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_ADD_INDEX; break; case AT_AddConstraint: /* ADD CONSTRAINT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); - /* Recursion occurs during execution phase */ - /* No command-specific prep needed except saving recurse flag */ + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); + ATPrepAddPrimaryKey(wqueue, rel, cmd, recurse, lockmode, context); if (recurse) + { + /* recurses at exec time; lock descendants and set flag */ + (void) find_all_inheritors(RelationGetRelid(rel), lockmode, NULL); cmd->recurse = true; + } pass = AT_PASS_ADD_CONSTR; break; case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_ADD_INDEXCONSTR; break; case AT_DropConstraint: /* DROP CONSTRAINT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); ATCheckPartitionsNotInUse(rel, lockmode); /* Other recursion occurs during execution phase */ /* No command-specific prep needed except saving recurse flag */ @@ -4937,7 +5104,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, break; case AT_AlterColumnType: /* ALTER COLUMN TYPE */ ATSimplePermissions(cmd->subtype, rel, - ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); + ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE); /* See comments for ATPrepAlterColumnType */ cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, recurse, lockmode, AT_PASS_UNSET, context); @@ -4960,47 +5128,30 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, break; case AT_ClusterOn: /* CLUSTER ON */ case AT_DropCluster: /* SET WITHOUT CLUSTER */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW); /* These commands never recurse */ /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_SetLogged: /* SET LOGGED */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_SEQUENCE); - if (tab->chgPersistence) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot change persistence setting twice"))); - tab->chgPersistence = ATPrepChangePersistence(rel, true); - /* force rewrite if necessary; see comment in ATRewriteTables */ - if (tab->chgPersistence) - { - tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE; - tab->newrelpersistence = RELPERSISTENCE_PERMANENT; - } - pass = AT_PASS_MISC; - break; case AT_SetUnLogged: /* SET UNLOGGED */ ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_SEQUENCE); if (tab->chgPersistence) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot change persistence setting twice"))); - tab->chgPersistence = ATPrepChangePersistence(rel, false); - /* force rewrite if necessary; see comment in ATRewriteTables */ - if (tab->chgPersistence) - { - tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE; - tab->newrelpersistence = RELPERSISTENCE_UNLOGGED; - } + ATPrepChangePersistence(tab, rel, cmd->subtype == AT_SetLogged); pass = AT_PASS_MISC; break; case AT_DropOids: /* SET WITHOUT OIDS */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); pass = AT_PASS_DROP; break; case AT_SetAccessMethod: /* SET ACCESS METHOD */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW); /* check if another access method change was already requested */ if (tab->chgAccessMethod) @@ -5012,8 +5163,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; /* does not matter; no work in Phase 2 */ break; case AT_SetTableSpace: /* SET TABLESPACE */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | - ATT_PARTITIONED_INDEX); + ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_TABLE | + ATT_MATVIEW | ATT_INDEX | ATT_PARTITIONED_INDEX); /* This command never recurses */ ATPrepSetTableSpace(tab, rel, cmd->name, lockmode); pass = AT_PASS_MISC; /* doesn't actually matter */ @@ -5021,30 +5172,38 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_SetRelOptions: /* SET (...) */ case AT_ResetRelOptions: /* RESET (...) */ case AT_ReplaceRelOptions: /* reset them all, then set just these */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_VIEW | + ATT_MATVIEW | ATT_INDEX); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_AddInherit: /* INHERIT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* This command never recurses */ ATPrepAddInherit(rel); pass = AT_PASS_MISC; break; case AT_DropInherit: /* NO INHERIT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* This command never recurses */ /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_AlterConstraint: /* ALTER CONSTRAINT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE); /* Recursion occurs during execution phase */ + if (recurse) + cmd->recurse = true; pass = AT_PASS_MISC; break; case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* Recursion occurs during execution phase */ /* No command-specific prep needed except saving recurse flag */ if (recurse) @@ -5052,7 +5211,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; break; case AT_ReplicaIdentity: /* REPLICA IDENTITY ... */ - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_MATVIEW); pass = AT_PASS_MISC; /* This command never recurses */ /* No command-specific prep needed */ @@ -5065,7 +5225,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_DisableTrig: /* DISABLE TRIGGER variants */ case AT_DisableTrigAll: case AT_DisableTrigUser: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* Set up recursion for phase 2; no other prep needed */ if (recurse) cmd->recurse = true; @@ -5081,7 +5242,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_DisableRowSecurity: case AT_ForceRowSecurity: case AT_NoForceRowSecurity: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE); /* These commands never recurse */ /* No command-specific prep needed */ pass = AT_PASS_MISC; @@ -5092,27 +5254,18 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, pass = AT_PASS_MISC; break; case AT_AttachPartition: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_PARTITIONED_INDEX); + ATSimplePermissions(cmd->subtype, rel, + ATT_PARTITIONED_TABLE | ATT_PARTITIONED_INDEX); /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_DetachPartition: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, ATT_PARTITIONED_TABLE); /* No command-specific prep needed */ pass = AT_PASS_MISC; break; case AT_DetachPartitionFinalize: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); - /* No command-specific prep needed */ - pass = AT_PASS_MISC; - break; - case AT_SplitPartition: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); - /* No command-specific prep needed */ - pass = AT_PASS_MISC; - break; - case AT_MergePartitions: - ATSimplePermissions(cmd->subtype, rel, ATT_TABLE); + ATSimplePermissions(cmd->subtype, rel, ATT_PARTITIONED_TABLE); /* No command-specific prep needed */ pass = AT_PASS_MISC; break; @@ -5247,13 +5400,11 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, address = ATExecDropIdentity(rel, cmd->name, cmd->missing_ok, lockmode, cmd->recurse, false); break; case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ - address = ATExecDropNotNull(rel, cmd->name, lockmode); + address = ATExecDropNotNull(rel, cmd->name, cmd->recurse, lockmode); break; case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ - address = ATExecSetNotNull(tab, rel, cmd->name, lockmode); - break; - case AT_CheckNotNull: /* check column is already marked NOT NULL */ - ATExecCheckNotNull(tab, rel, cmd->name, lockmode); + address = ATExecSetNotNull(wqueue, rel, NULL, cmd->name, + cmd->recurse, false, lockmode); break; case AT_SetExpression: address = ATExecSetExpression(tab, rel, cmd->name, cmd->def, lockmode); @@ -5328,7 +5479,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, lockmode); break; case AT_AlterConstraint: /* ALTER CONSTRAINT */ - address = ATExecAlterConstraint(rel, cmd, false, false, lockmode); + address = ATExecAlterConstraint(wqueue, rel, + castNode(ATAlterConstraint, cmd->def), + cmd->recurse, lockmode); break; case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */ address = ATExecValidateConstraint(wqueue, rel, cmd->name, cmd->recurse, @@ -5336,7 +5489,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, break; case AT_DropConstraint: /* DROP CONSTRAINT */ ATExecDropConstraint(rel, cmd->name, cmd->behavior, - cmd->recurse, false, + cmd->recurse, cmd->missing_ok, lockmode); break; case AT_AlterColumnType: /* ALTER COLUMN TYPE */ @@ -5512,22 +5665,6 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, case AT_DetachPartitionFinalize: address = ATExecDetachPartitionFinalize(rel, ((PartitionCmd *) cmd->def)->name); break; - case AT_SplitPartition: - cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode, - cur_pass, context); - Assert(cmd != NULL); - Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); - ATExecSplitPartition(wqueue, tab, rel, (PartitionCmd *) cmd->def, - context); - break; - case AT_MergePartitions: - cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode, - cur_pass, context); - Assert(cmd != NULL); - Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); - ATExecMergePartitions(wqueue, tab, rel, (PartitionCmd *) cmd->def, - context); - break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -5615,21 +5752,10 @@ ATParseTransformCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, */ switch (cmd2->subtype) { - case AT_SetNotNull: - /* Need command-specific recursion decision */ - ATPrepSetNotNull(wqueue, rel, cmd2, - recurse, false, - lockmode, context); - pass = AT_PASS_COL_ATTRS; - break; case AT_AddIndex: - /* This command never recurses */ - /* No command-specific prep needed */ pass = AT_PASS_ADD_INDEX; break; case AT_AddIndexConstraint: - /* This command never recurses */ - /* No command-specific prep needed */ pass = AT_PASS_ADD_INDEXCONSTR; break; case AT_AddConstraint: @@ -5638,6 +5764,9 @@ ATParseTransformCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, cmd2->recurse = true; switch (castNode(Constraint, cmd2->def)->contype) { + case CONSTR_NOTNULL: + pass = AT_PASS_COL_ATTRS; + break; case CONSTR_PRIMARY: case CONSTR_UNIQUE: case CONSTR_EXCLUSION: @@ -5848,7 +5977,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, * modifications, and test the current data within the table * against new constraints generated by ALTER TABLE commands. */ - ATRewriteTable(tab, OIDNewHeap, lockmode); + ATRewriteTable(tab, OIDNewHeap); /* * Swap the physical files of the old and new heaps, then rebuild @@ -5881,7 +6010,7 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, */ if (tab->constraints != NIL || tab->verify_new_notnull || tab->partition_constraint != NULL) - ATRewriteTable(tab, InvalidOid, lockmode); + ATRewriteTable(tab, InvalidOid); /* * If we had SET TABLESPACE but no reason to reconstruct tuples, @@ -5945,7 +6074,8 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, validateForeignKeyConstraint(fkconstraint->conname, rel, refrel, con->refindid, - con->conid); + con->conid, + con->conwithperiod); /* * No need to mark the constraint row as validated, we did @@ -5979,10 +6109,11 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode, /* * ATRewriteTable: scan or rewrite one table * - * OIDNewHeap is InvalidOid if we don't need to rewrite + * A rewrite is requested by passing a valid OIDNewHeap; in that case, caller + * must already hold AccessExclusiveLock on it. */ static void -ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) +ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap) { Relation oldrel; Relation newrel; @@ -5990,6 +6121,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) TupleDesc newTupDesc; bool needscan = false; List *notnull_attrs; + List *notnull_virtual_attrs; int i; ListCell *l; EState *estate; @@ -6007,7 +6139,11 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) newTupDesc = RelationGetDescr(oldrel); /* includes all mods */ if (OidIsValid(OIDNewHeap)) - newrel = table_open(OIDNewHeap, lockmode); + { + Assert(CheckRelationOidLockedByMe(OIDNewHeap, AccessExclusiveLock, + false)); + newrel = table_open(OIDNewHeap, NoLock); + } else newrel = NULL; @@ -6044,7 +6180,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) { case CONSTR_CHECK: needscan = true; - con->qualstate = ExecPrepareExpr((Expr *) con->qual, estate); + con->qualstate = ExecPrepareExpr((Expr *) expand_generated_columns_in_expr(con->qual, oldrel, 1), estate); break; case CONSTR_FOREIGN: /* Nothing to do here */ @@ -6070,23 +6206,36 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) ex->exprstate = ExecInitExpr((Expr *) ex->expr, NULL); } - notnull_attrs = NIL; + notnull_attrs = notnull_virtual_attrs = NIL; if (newrel || tab->verify_new_notnull) { /* * If we are rebuilding the tuples OR if we added any new but not - * verified not-null constraints, check all not-null constraints. This - * is a bit of overkill but it minimizes risk of bugs, and - * heap_attisnull is a pretty cheap test anyway. + * verified not-null constraints, check all *valid* not-null + * constraints. This is a bit of overkill but it minimizes risk of + * bugs. + * + * notnull_attrs does *not* collect attribute numbers for valid + * not-null constraints over virtual generated columns; instead, they + * are collected in notnull_virtual_attrs for verification elsewhere. */ for (i = 0; i < newTupDesc->natts; i++) { - Form_pg_attribute attr = TupleDescAttr(newTupDesc, i); + CompactAttribute *attr = TupleDescCompactAttr(newTupDesc, i); + + if (attr->attnullability == ATTNULLABLE_VALID && + !attr->attisdropped) + { + Form_pg_attribute wholeatt = TupleDescAttr(newTupDesc, i); - if (attr->attnotnull && !attr->attisdropped) - notnull_attrs = lappend_int(notnull_attrs, i); + if (wholeatt->attgenerated != ATTRIBUTE_GENERATED_VIRTUAL) + notnull_attrs = lappend_int(notnull_attrs, wholeatt->attnum); + else + notnull_virtual_attrs = lappend_int(notnull_virtual_attrs, + wholeatt->attnum); + } } - if (notnull_attrs) + if (notnull_attrs || notnull_virtual_attrs) needscan = true; } @@ -6100,6 +6249,29 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) List *dropped_attrs = NIL; ListCell *lc; Snapshot snapshot; + ResultRelInfo *rInfo = NULL; + + /* + * When adding or changing a virtual generated column with a not-null + * constraint, we need to evaluate whether the generation expression + * is null. For that, we borrow ExecRelGenVirtualNotNull(). Here, we + * prepare a dummy ResultRelInfo. + */ + if (notnull_virtual_attrs != NIL) + { + MemoryContext oldcontext; + + Assert(newTupDesc->constr->has_generated_virtual); + Assert(newTupDesc->constr->has_not_null); + oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + rInfo = makeNode(ResultRelInfo); + InitResultRelInfo(rInfo, + oldrel, + 0, /* dummy rangetable index */ + NULL, + estate->es_instrument); + MemoryContextSwitchTo(oldcontext); + } if (newrel) ereport(DEBUG1, @@ -6265,20 +6437,38 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) /* Now check any constraints on the possibly-changed tuple */ econtext->ecxt_scantuple = insertslot; - foreach(l, notnull_attrs) + foreach_int(attn, notnull_attrs) { - int attn = lfirst_int(l); - - if (slot_attisnull(insertslot, attn + 1)) + if (slot_attisnull(insertslot, attn)) { - Form_pg_attribute attr = TupleDescAttr(newTupDesc, attn); + Form_pg_attribute attr = TupleDescAttr(newTupDesc, attn - 1); ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("column \"%s\" of relation \"%s\" contains null values", NameStr(attr->attname), RelationGetRelationName(oldrel)), - errtablecol(oldrel, attn + 1))); + errtablecol(oldrel, attn))); + } + } + + if (notnull_virtual_attrs != NIL) + { + AttrNumber attnum; + + attnum = ExecRelGenVirtualNotNull(rInfo, insertslot, + estate, + notnull_virtual_attrs); + if (attnum != InvalidAttrNumber) + { + Form_pg_attribute attr = TupleDescAttr(newTupDesc, attnum - 1); + + ereport(ERROR, + errcode(ERRCODE_NOT_NULL_VIOLATION), + errmsg("column \"%s\" of relation \"%s\" contains null values", + NameStr(attr->attname), + RelationGetRelationName(oldrel)), + errtablecol(oldrel, attnum)); } } @@ -6297,6 +6487,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) RelationGetRelationName(oldrel)), errtableconstraint(oldrel, con->name))); break; + case CONSTR_NOTNULL: case CONSTR_FOREIGN: /* Nothing to do here */ break; @@ -6410,8 +6601,6 @@ alter_table_type_to_string(AlterTableType cmdtype) return "ALTER COLUMN ... SET EXPRESSION"; case AT_DropExpression: return "ALTER COLUMN ... DROP EXPRESSION"; - case AT_CheckNotNull: - return NULL; /* not real grammar */ case AT_SetStatistics: return "ALTER COLUMN ... SET STATISTICS"; case AT_SetOptions: @@ -6516,10 +6705,6 @@ alter_table_type_to_string(AlterTableType cmdtype) return "DETACH PARTITION"; case AT_DetachPartitionFinalize: return "DETACH PARTITION ... FINALIZE"; - case AT_SplitPartition: - return "SPLIT PARTITION"; - case AT_MergePartitions: - return "MERGE PARTITIONS"; case AT_AddIdentity: return "ALTER COLUMN ... ADD IDENTITY"; case AT_SetIdentity: @@ -6548,9 +6733,11 @@ ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets) switch (rel->rd_rel->relkind) { case RELKIND_RELATION: - case RELKIND_PARTITIONED_TABLE: actual_target = ATT_TABLE; break; + case RELKIND_PARTITIONED_TABLE: + actual_target = ATT_PARTITIONED_TABLE; + break; case RELKIND_VIEW: actual_target = ATT_VIEW; break; @@ -7028,6 +7215,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, Relation pgclass, attrdesc; HeapTuple reltup; + Form_pg_class relform; Form_pg_attribute attribute; int newattnum; char relkind; @@ -7043,7 +7231,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) - ATSimplePermissions((*cmd)->subtype, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions((*cmd)->subtype, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); if (rel->rd_rel->relispartition && !recursing) ereport(ERROR, @@ -7090,8 +7279,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, get_collation_name(childatt->attcollation)))); /* Bump the existing child att's inhcount */ - childatt->attinhcount++; - if (childatt->attinhcount < 0) + if (pg_add_s16_overflow(childatt->attinhcount, 1, + &childatt->attinhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); @@ -7161,10 +7350,11 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid)); if (!HeapTupleIsValid(reltup)) elog(ERROR, "cache lookup failed for relation %u", myrelid); - relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind; + relform = (Form_pg_class) GETSTRUCT(reltup); + relkind = relform->relkind; /* Determine the new attribute's number */ - newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1; + newattnum = relform->relnatts + 1; if (newattnum > MaxHeapAttributeNumber) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_COLUMNS), @@ -7193,7 +7383,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * Update pg_class tuple as appropriate */ - ((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum; + relform->relnatts = newattnum; CatalogTupleUpdate(pgclass, &reltup->t_self, reltup); @@ -7217,14 +7407,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt->attnum = attribute->attnum; rawEnt->raw_default = copyObject(colDef->raw_default); - - /* - * Attempt to skip a complete table rewrite by storing the specified - * DEFAULT value outside of the heap. This may be disabled inside - * AddRelationNewConstraints if the optimization cannot be applied. - */ - rawEnt->missingMode = (!colDef->generated); - rawEnt->generated = colDef->generated; /* @@ -7236,13 +7418,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* Make the additional catalog changes visible */ CommandCounterIncrement(); - - /* - * Did the request for a missing value work? If not we'll have to do a - * rewrite - */ - if (!rawEnt->missingMode) - tab->rewrite |= AT_REWRITE_DEFAULT_VAL; } /* @@ -7259,9 +7434,9 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, * rejects nulls. If there are any domain constraints then we construct * an explicit NULL default value that will be passed through * CoerceToDomain processing. (This is a tad inefficient, since it causes - * rewriting the table which we really don't have to do, but the present - * design of domain processing doesn't offer any simple way of checking - * the constraints more directly.) + * rewriting the table which we really wouldn't have to do; but we do it + * to preserve the historical behavior that such a failure will be raised + * only if the table currently contains some rows.) * * Note: we use build_column_default, and not just the cooked default * returned by AddRelationNewConstraints, so that the right thing happens @@ -7275,11 +7450,13 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, * and the later subcommands had been issued in new ALTER TABLE commands. * * We can skip this entirely for relations without storage, since Phase 3 - * is certainly not going to touch them. System attributes don't have - * interesting defaults, either. + * is certainly not going to touch them. */ if (RELKIND_HAS_STORAGE(relkind)) { + bool has_domain_constraints; + bool has_missing = false; + /* * For an identity column, we can't use build_column_default(), * because the sequence ownership isn't set yet. So do it manually. @@ -7292,14 +7469,13 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, nve->typeId = attribute->atttypid; defval = (Expr *) nve; - - /* must do a rewrite for identity columns */ - tab->rewrite |= AT_REWRITE_DEFAULT_VAL; } else defval = (Expr *) build_column_default(rel, attribute->attnum); - if (!defval && DomainHasConstraints(attribute->atttypid)) + /* Build CoerceToDomain(NULL) expression if needed */ + has_domain_constraints = DomainHasConstraints(attribute->atttypid); + if (!defval && has_domain_constraints) { Oid baseTypeId; int32 baseTypeMod; @@ -7325,18 +7501,65 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, { NewColumnValue *newval; + /* Prepare defval for execution, either here or in Phase 3 */ + defval = expression_planner(defval); + + /* Add the new default to the newvals list */ newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue)); newval->attnum = attribute->attnum; - newval->expr = expression_planner(defval); + newval->expr = defval; newval->is_generated = (colDef->generated != '\0'); tab->newvals = lappend(tab->newvals, newval); - } - if (DomainHasConstraints(attribute->atttypid)) - tab->rewrite |= AT_REWRITE_DEFAULT_VAL; + /* + * Attempt to skip a complete table rewrite by storing the + * specified DEFAULT value outside of the heap. This is only + * allowed for plain relations and non-generated columns, and the + * default expression can't be volatile (stable is OK). Note that + * contain_volatile_functions deems CoerceToDomain immutable, but + * here we consider that coercion to a domain with constraints is + * volatile; else it might fail even when the table is empty. + */ + if (rel->rd_rel->relkind == RELKIND_RELATION && + !colDef->generated && + !has_domain_constraints && + !contain_volatile_functions((Node *) defval)) + { + EState *estate; + ExprState *exprState; + Datum missingval; + bool missingIsNull; + + /* Evaluate the default expression */ + estate = CreateExecutorState(); + exprState = ExecPrepareExpr(defval, estate); + missingval = ExecEvalExpr(exprState, + GetPerTupleExprContext(estate), + &missingIsNull); + /* If it turns out NULL, nothing to do; else store it */ + if (!missingIsNull) + { + StoreAttrMissingVal(rel, attribute->attnum, missingval); + /* Make the additional catalog change visible */ + CommandCounterIncrement(); + has_missing = true; + } + FreeExecutorState(estate); + } + else + { + /* + * Failed to use missing mode. We have to do a table rewrite + * to install the value --- unless it's a virtual generated + * column. + */ + if (colDef->generated != ATTRIBUTE_GENERATED_VIRTUAL) + tab->rewrite |= AT_REWRITE_DEFAULT_VAL; + } + } - if (!TupleDescAttr(rel->rd_att, attribute->attnum - 1)->atthasmissing) + if (!has_missing) { /* * If the new column is NOT NULL, and there is no missing value, @@ -7501,40 +7724,19 @@ add_column_collation_dependency(Oid relid, int32 attnum, Oid collid) /* * ALTER TABLE ALTER COLUMN DROP NOT NULL - */ - -static void -ATPrepDropNotNull(Relation rel, bool recurse, bool recursing) -{ - /* - * If the parent is a partitioned table, like check constraints, we do not - * support removing the NOT NULL while partitions exist. - */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - PartitionDesc partdesc = RelationGetPartitionDesc(rel, true); - - Assert(partdesc != NULL); - if (partdesc->nparts > 0 && !recurse && !recursing) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot remove constraint from only the partitioned table when partitions exist"), - errhint("Do not specify the ONLY keyword."))); - } -} - -/* + * * Return the address of the modified column. If the column was already * nullable, InvalidObjectAddress is returned. */ static ObjectAddress -ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) +ATExecDropNotNull(Relation rel, const char *colName, bool recurse, + LOCKMODE lockmode) { HeapTuple tuple; + HeapTuple conTup; Form_pg_attribute attTup; AttrNumber attnum; Relation attr_rel; - List *indexoidlist; ObjectAddress address; /* @@ -7550,6 +7752,15 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) colName, RelationGetRelationName(rel)))); attTup = (Form_pg_attribute) GETSTRUCT(tuple); attnum = attTup->attnum; + ObjectAddressSubSet(address, RelationRelationId, + RelationGetRelid(rel), attnum); + + /* If the column is already nullable there's nothing to do. */ + if (!attTup->attnotnull) + { + table_close(attr_rel, RowExclusiveLock); + return InvalidObjectAddress; + } /* Prevent them from altering a system attribute */ if (attnum <= 0) @@ -7565,60 +7776,8 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) colName, RelationGetRelationName(rel)))); /* - * Check that the attribute is not in a primary key or in an index used as - * a replica identity. - * - * Note: we'll throw error even if the pkey index is not valid. + * If rel is partition, shouldn't drop NOT NULL if parent has the same. */ - - /* Loop over all indexes on the relation */ - indexoidlist = RelationGetIndexList(rel); - - foreach_oid(indexoid, indexoidlist) - { - HeapTuple indexTuple; - Form_pg_index indexStruct; - - indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid)); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "cache lookup failed for index %u", indexoid); - indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); - - /* - * If the index is not a primary key or an index used as replica - * identity, skip the check. - */ - if (indexStruct->indisprimary || indexStruct->indisreplident) - { - /* - * Loop over each attribute in the primary key or the index used - * as replica identity and see if it matches the to-be-altered - * attribute. - */ - for (int i = 0; i < indexStruct->indnkeyatts; i++) - { - if (indexStruct->indkey.values[i] == attnum) - { - if (indexStruct->indisprimary) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("column \"%s\" is in a primary key", - colName))); - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("column \"%s\" is in index used as replica identity", - colName))); - } - } - } - - ReleaseSysCache(indexTuple); - } - - list_free(indexoidlist); - - /* If rel is partition, shouldn't drop NOT NULL if parent has the same */ if (rel->rd_rel->relispartition) { Oid parentId = get_partition_parent(RelationGetRelid(rel), false); @@ -7636,19 +7795,18 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) } /* - * Okay, actually perform the catalog change ... if needed + * Find the constraint that makes this column NOT NULL, and drop it. + * dropconstraint_internal() resets attnotnull. */ - if (attTup->attnotnull) - { - attTup->attnotnull = false; + conTup = findNotNullConstraintAttnum(RelationGetRelid(rel), attnum); + if (conTup == NULL) + elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation \"%s\"", + colName, RelationGetRelationName(rel)); - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); - - ObjectAddressSubSet(address, RelationRelationId, - RelationGetRelid(rel), attnum); - } - else - address = InvalidObjectAddress; + /* The normal case: we have a pg_constraint row, remove it */ + dropconstraint_internal(rel, conTup, DROP_RESTRICT, recurse, false, + false, lockmode); + heap_freetuple(conTup); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attnum); @@ -7659,102 +7817,118 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) } /* - * ALTER TABLE ALTER COLUMN SET NOT NULL + * set_attnotnull + * Helper to update/validate the pg_attribute status of a not-null + * constraint + * + * pg_attribute.attnotnull is set true, if it isn't already. + * If queue_validation is true, also set up wqueue to validate the constraint. + * wqueue may be given as NULL when validation is not needed (e.g., on table + * creation). */ - static void -ATPrepSetNotNull(List **wqueue, Relation rel, - AlterTableCmd *cmd, bool recurse, bool recursing, - LOCKMODE lockmode, AlterTableUtilityContext *context) +set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, + bool is_valid, bool queue_validation) { + Form_pg_attribute attr; + CompactAttribute *thisatt; + + Assert(!queue_validation || wqueue); + + CheckAlterTableIsSafe(rel); + /* - * If we're already recursing, there's nothing to do; the topmost - * invocation of ATSimpleRecursion already visited all children. + * Exit quickly by testing attnotnull from the tupledesc's copy of the + * attribute. */ - if (recursing) + attr = TupleDescAttr(RelationGetDescr(rel), attnum - 1); + if (attr->attisdropped) return; - /* - * If the target column is already marked NOT NULL, we can skip recursing - * to children, because their columns should already be marked NOT NULL as - * well. But there's no point in checking here unless the relation has - * some children; else we can just wait till execution to check. (If it - * does have children, however, this can save taking per-child locks - * unnecessarily. This greatly improves concurrency in some parallel - * restore scenarios.) - * - * Unfortunately, we can only apply this optimization to partitioned - * tables, because traditional inheritance doesn't enforce that child - * columns be NOT NULL when their parent is. (That's a bug that should - * get fixed someday.) - */ - if (rel->rd_rel->relhassubclass && - rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + if (!attr->attnotnull) { + Relation attr_rel; HeapTuple tuple; - bool attnotnull; - tuple = SearchSysCacheAttName(RelationGetRelid(rel), cmd->name); + attr_rel = table_open(AttributeRelationId, RowExclusiveLock); - /* Might as well throw the error now, if name is bad */ + tuple = SearchSysCacheCopyAttNum(RelationGetRelid(rel), attnum); if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - cmd->name, RelationGetRelationName(rel)))); + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, RelationGetRelid(rel)); - attnotnull = ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull; - ReleaseSysCache(tuple); - if (attnotnull) - return; - } + thisatt = TupleDescCompactAttr(RelationGetDescr(rel), attnum - 1); + thisatt->attnullability = ATTNULLABLE_VALID; - /* - * If we have ALTER TABLE ONLY ... SET NOT NULL on a partitioned table, - * apply ALTER TABLE ... CHECK NOT NULL to every child. Otherwise, use - * normal recursion logic. - */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && - !recurse) - { - AlterTableCmd *newcmd = makeNode(AlterTableCmd); + attr = (Form_pg_attribute) GETSTRUCT(tuple); + + attr->attnotnull = true; + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + + /* + * If the nullness isn't already proven by validated constraints, have + * ALTER TABLE phase 3 test for it. + */ + if (queue_validation && wqueue && + !NotNullImpliedByRelConstraints(rel, attr)) + { + AlteredTableInfo *tab; + + tab = ATGetQueueEntry(wqueue, rel); + tab->verify_new_notnull = true; + } + + CommandCounterIncrement(); - newcmd->subtype = AT_CheckNotNull; - newcmd->name = pstrdup(cmd->name); - ATSimpleRecursion(wqueue, rel, newcmd, true, lockmode, context); + table_close(attr_rel, RowExclusiveLock); + heap_freetuple(tuple); } else - ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); + { + CacheInvalidateRelcache(rel); + } } /* - * Return the address of the modified column. If the column was already NOT - * NULL, InvalidObjectAddress is returned. + * ALTER TABLE ALTER COLUMN SET NOT NULL + * + * Add a not-null constraint to a single table and its children. Returns + * the address of the constraint added to the parent relation, if one gets + * added, or InvalidObjectAddress otherwise. + * + * We must recurse to child tables during execution, rather than using + * ALTER TABLE's normal prep-time recursion. */ static ObjectAddress -ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, - const char *colName, LOCKMODE lockmode) +ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, + bool recurse, bool recursing, LOCKMODE lockmode) { HeapTuple tuple; AttrNumber attnum; - Relation attr_rel; ObjectAddress address; + Constraint *constraint; + CookedConstraint *ccon; + List *cooked; + bool is_no_inherit = false; - /* - * lookup the attribute - */ - attr_rel = table_open(AttributeRelationId, RowExclusiveLock); + /* Guard against stack overflow due to overly deep inheritance tree. */ + check_stack_depth(); - tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); + /* At top level, permission check was done in ATPrepCmd, else do it */ + if (recursing) + { + ATSimplePermissions(AT_AddConstraint, rel, + ATT_PARTITIONED_TABLE | ATT_TABLE | ATT_FOREIGN_TABLE); + Assert(conName != NULL); + } - if (!HeapTupleIsValid(tuple)) + attnum = get_attnum(RelationGetRelid(rel), colName); + if (attnum == InvalidAttrNumber) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); - attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum; - /* Prevent them from altering a system attribute */ if (attnum <= 0) ereport(ERROR, @@ -7762,80 +7936,139 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel, errmsg("cannot alter system column \"%s\"", colName))); - /* - * Okay, actually perform the catalog change ... if needed - */ - if (!((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull) + /* See if there's already a constraint */ + tuple = findNotNullConstraintAttnum(RelationGetRelid(rel), attnum); + if (HeapTupleIsValid(tuple)) { - ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = true; + Form_pg_constraint conForm = (Form_pg_constraint) GETSTRUCT(tuple); + bool changed = false; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + /* + * Don't let a NO INHERIT constraint be changed into inherit. + */ + if (conForm->connoinherit && recurse) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"", + NameStr(conForm->conname), + RelationGetRelationName(rel))); /* - * Ordinarily phase 3 must ensure that no NULLs exist in columns that - * are set NOT NULL; however, if we can find a constraint which proves - * this then we can skip that. We needn't bother looking if we've - * already found that we must verify some other not-null constraint. + * If we find an appropriate constraint, we're almost done, but just + * need to change some properties on it: if we're recursing, increment + * coninhcount; if not, set conislocal if not already set. */ - if (!tab->verify_new_notnull && - !NotNullImpliedByRelConstraints(rel, (Form_pg_attribute) GETSTRUCT(tuple))) + if (recursing) { - /* Tell Phase 3 it needs to test the constraint */ - tab->verify_new_notnull = true; + if (pg_add_s16_overflow(conForm->coninhcount, 1, + &conForm->coninhcount)) + ereport(ERROR, + errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("too many inheritance parents")); + changed = true; + } + else if (!conForm->conislocal) + { + conForm->conislocal = true; + changed = true; + } + else if (!conForm->convalidated) + { + /* + * Flip attnotnull and convalidated, and also validate the + * constraint. + */ + return ATExecValidateConstraint(wqueue, rel, NameStr(conForm->conname), + recurse, recursing, lockmode); } - ObjectAddressSubSet(address, RelationRelationId, - RelationGetRelid(rel), attnum); + if (changed) + { + Relation constr_rel; + + constr_rel = table_open(ConstraintRelationId, RowExclusiveLock); + + CatalogTupleUpdate(constr_rel, &tuple->t_self, tuple); + ObjectAddressSet(address, ConstraintRelationId, conForm->oid); + table_close(constr_rel, RowExclusiveLock); + } + + if (changed) + return address; + else + return InvalidObjectAddress; + } + + /* + * If we're asked not to recurse, and children exist, raise an error for + * partitioned tables. For inheritance, we act as if NO INHERIT had been + * specified. + */ + if (!recurse && + find_inheritance_children(RelationGetRelid(rel), + NoLock) != NIL) + { + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be added to child tables too"), + errhint("Do not specify the ONLY keyword.")); + else + is_no_inherit = true; + } + + /* + * No constraint exists; we must add one. First determine a name to use, + * if we haven't already. + */ + if (!recursing) + { + Assert(conName == NULL); + conName = ChooseConstraintName(RelationGetRelationName(rel), + colName, "not_null", + RelationGetNamespace(rel), + NIL); } - else - address = InvalidObjectAddress; + + constraint = makeNotNullConstraint(makeString(colName)); + constraint->is_no_inherit = is_no_inherit; + constraint->conname = conName; + + /* and do it */ + cooked = AddRelationNewConstraints(rel, NIL, list_make1(constraint), + false, !recursing, false, NULL); + ccon = linitial(cooked); + ObjectAddressSet(address, ConstraintRelationId, ccon->conoid); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attnum); - table_close(attr_rel, RowExclusiveLock); + /* Mark pg_attribute.attnotnull for the column and queue validation */ + set_attnotnull(wqueue, rel, attnum, true, true); - return address; -} + /* + * Recurse to propagate the constraint to children that don't have one. + */ + if (recurse) + { + List *children; -/* - * ALTER TABLE ALTER COLUMN CHECK NOT NULL - * - * This doesn't exist in the grammar, but we generate AT_CheckNotNull - * commands against the partitions of a partitioned table if the user - * writes ALTER TABLE ONLY ... SET NOT NULL on the partitioned table, - * or tries to create a primary key on it (which internally creates - * AT_SetNotNull on the partitioned table). Such a command doesn't - * allow us to actually modify any partition, but we want to let it - * go through if the partitions are already properly marked. - * - * In future, this might need to adjust the child table's state, likely - * by incrementing an inheritance count for the attnotnull constraint. - * For now we need only check for the presence of the flag. - */ -static void -ATExecCheckNotNull(AlteredTableInfo *tab, Relation rel, - const char *colName, LOCKMODE lockmode) -{ - HeapTuple tuple; + children = find_inheritance_children(RelationGetRelid(rel), + lockmode); - tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName); + foreach_oid(childoid, children) + { + Relation childrel = table_open(childoid, NoLock); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - colName, RelationGetRelationName(rel))); + CommandCounterIncrement(); - if (!((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("constraint must be added to child tables too"), - errdetail("Column \"%s\" of relation \"%s\" is not already NOT NULL.", - colName, RelationGetRelationName(rel)), - errhint("Do not specify the ONLY keyword."))); + ATExecSetNotNull(wqueue, childrel, conName, colName, + recurse, true, lockmode); + table_close(childrel, NoLock); + } + } - ReleaseSysCache(tuple); + return address; } /* @@ -7944,7 +8177,6 @@ ATExecColumnDefault(Relation rel, const char *colName, rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt->attnum = attnum; rawEnt->raw_default = newDefault; - rawEnt->missingMode = false; rawEnt->generated = '\0'; /* @@ -7982,7 +8214,7 @@ ATExecCookedColumnDefault(Relation rel, AttrNumber attnum, RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false, true); - (void) StoreAttrDefault(rel, attnum, newDefault, true, false); + (void) StoreAttrDefault(rel, attnum, newDefault, true); ObjectAddressSubSet(address, RelationRelationId, RelationGetRelid(rel), attnum); @@ -8338,6 +8570,8 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName, HeapTuple tuple; Form_pg_attribute attTup; AttrNumber attnum; + char attgenerated; + bool rewrite; Oid attrdefoid; ObjectAddress address; Expr *defval; @@ -8352,36 +8586,73 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName, colName, RelationGetRelationName(rel)))); attTup = (Form_pg_attribute) GETSTRUCT(tuple); - attnum = attTup->attnum; + attnum = attTup->attnum; if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", colName))); - if (attTup->attgenerated != ATTRIBUTE_GENERATED_STORED) + attgenerated = attTup->attgenerated; + if (!attgenerated) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("column \"%s\" of relation \"%s\" is not a generated column", colName, RelationGetRelationName(rel)))); - ReleaseSysCache(tuple); /* - * Clear all the missing values if we're rewriting the table, since this - * renders them pointless. + * TODO: This could be done, just need to recheck any constraints + * afterwards. */ - RelationClearMissing(rel); + if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL && + rel->rd_att->constr && rel->rd_att->constr->num_check > 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables with check constraints"), + errdetail("Column \"%s\" of relation \"%s\" is a virtual generated column.", + colName, RelationGetRelationName(rel)))); - /* make sure we don't conflict with later attribute modifications */ - CommandCounterIncrement(); + if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL && attTup->attnotnull) + tab->verify_new_notnull = true; /* - * Find everything that depends on the column (constraints, indexes, etc), - * and record enough information to let us recreate the objects after - * rewrite. + * We need to prevent this because a change of expression could affect a + * row filter and inject expressions that are not permitted in a row + * filter. XXX We could try to have a more precise check to catch only + * publications with row filters, or even re-verify the row filter + * expressions. */ - RememberAllDependentForRebuilding(tab, AT_SetExpression, rel, attnum, colName); + if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL && + GetRelationPublications(RelationGetRelid(rel)) != NIL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables that are part of a publication"), + errdetail("Column \"%s\" of relation \"%s\" is a virtual generated column.", + colName, RelationGetRelationName(rel)))); + + rewrite = (attgenerated == ATTRIBUTE_GENERATED_STORED); + + ReleaseSysCache(tuple); + + if (rewrite) + { + /* + * Clear all the missing values if we're rewriting the table, since + * this renders them pointless. + */ + RelationClearMissing(rel); + + /* make sure we don't conflict with later attribute modifications */ + CommandCounterIncrement(); + + /* + * Find everything that depends on the column (constraints, indexes, + * etc), and record enough information to let us recreate the objects + * after rewrite. + */ + RememberAllDependentForRebuilding(tab, AT_SetExpression, rel, attnum, colName); + } /* * Drop the dependency records of the GENERATED expression, in particular @@ -8409,8 +8680,7 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName, rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt->attnum = attnum; rawEnt->raw_default = newExpr; - rawEnt->missingMode = false; - rawEnt->generated = ATTRIBUTE_GENERATED_STORED; + rawEnt->generated = attgenerated; /* Store the generated expression */ AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, @@ -8419,16 +8689,19 @@ ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName, /* Make above new expression visible */ CommandCounterIncrement(); - /* Prepare for table rewrite */ - defval = (Expr *) build_column_default(rel, attnum); + if (rewrite) + { + /* Prepare for table rewrite */ + defval = (Expr *) build_column_default(rel, attnum); - newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue)); - newval->attnum = attnum; - newval->expr = expression_planner(defval); - newval->is_generated = true; + newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue)); + newval->attnum = attnum; + newval->expr = expression_planner(defval); + newval->is_generated = true; - tab->newvals = lappend(tab->newvals, newval); - tab->rewrite |= AT_REWRITE_DEFAULT_VAL; + tab->newvals = lappend(tab->newvals, newval); + tab->rewrite |= AT_REWRITE_DEFAULT_VAL; + } /* Drop any pg_statistic entry for the column */ RemoveStatistics(RelationGetRelid(rel), attnum); @@ -8517,17 +8790,30 @@ ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMOD errmsg("cannot alter system column \"%s\"", colName))); - if (attTup->attgenerated != ATTRIBUTE_GENERATED_STORED) + /* + * TODO: This could be done, but it would need a table rewrite to + * materialize the generated values. Note that for the time being, we + * still error with missing_ok, so that we don't silently leave the column + * as generated. + */ + if (attTup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER TABLE / DROP EXPRESSION is not supported for virtual generated columns"), + errdetail("Column \"%s\" of relation \"%s\" is a virtual generated column.", + colName, RelationGetRelationName(rel)))); + + if (!attTup->attgenerated) { if (!missing_ok) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("column \"%s\" of relation \"%s\" is not a stored generated column", + errmsg("column \"%s\" of relation \"%s\" is not a generated column", colName, RelationGetRelationName(rel)))); else { ereport(NOTICE, - (errmsg("column \"%s\" of relation \"%s\" is not a stored generated column, skipping", + (errmsg("column \"%s\" of relation \"%s\" is not a generated column, skipping", colName, RelationGetRelationName(rel)))); heap_freetuple(tuple); table_close(attrelation, RowExclusiveLock); @@ -8670,6 +8956,16 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa errmsg("cannot alter system column \"%s\"", colName))); + /* + * Prevent this as long as the ANALYZE code skips virtual generated + * columns. + */ + if (attrtuple->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter statistics on virtual generated column \"%s\"", + colName))); + if (rel->rd_rel->relkind == RELKIND_INDEX || rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) { @@ -8965,7 +9261,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) - ATSimplePermissions(AT_DropColumn, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(AT_DropColumn, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* Initialize addrs on the first invocation */ Assert(!recursing || addrs != NULL); @@ -9141,6 +9438,140 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, return object; } +/* + * Prepare to add a primary key on a table, by adding not-null constraints + * on all columns. + * + * The not-null constraints for a primary key must cover the whole inheritance + * hierarchy (failing to ensure that leads to funny corner cases). For the + * normal case where we're asked to recurse, this routine checks if the + * not-null constraints exist already, and if not queues a requirement for + * them to be created by phase 2. + * + * For the case where we're asked not to recurse, we verify that a not-null + * constraint exists on each column of each (direct) child table, throwing an + * error if not. Not throwing an error would also work, because a not-null + * constraint would be created anyway, but it'd cause a silent scan of the + * child table to verify absence of nulls. We prefer to let the user know so + * that they can add the constraint manually without having to hold + * AccessExclusiveLock while at it. + * + * However, it's also important that we do not acquire locks on children if + * the not-null constraints already exist on the parent, to avoid risking + * deadlocks during parallel pg_restore of PKs on partitioned tables. + */ +static void +ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd, + bool recurse, LOCKMODE lockmode, + AlterTableUtilityContext *context) +{ + Constraint *pkconstr; + List *children = NIL; + bool got_children = false; + + pkconstr = castNode(Constraint, cmd->def); + if (pkconstr->contype != CONSTR_PRIMARY) + return; + + /* Verify that columns are not-null, or request that they be made so */ + foreach_node(String, column, pkconstr->keys) + { + AlterTableCmd *newcmd; + Constraint *nnconstr; + HeapTuple tuple; + + /* + * First check if a suitable constraint exists. If it does, we don't + * need to request another one. We do need to bail out if it's not + * valid, though. + */ + tuple = findNotNullConstraint(RelationGetRelid(rel), strVal(column)); + if (tuple != NULL) + { + verifyNotNullPKCompatible(tuple, strVal(column)); + + /* All good with this one; don't request another */ + heap_freetuple(tuple); + continue; + } + else if (!recurse) + { + /* + * No constraint on this column. Asked not to recurse, we won't + * create one here, but verify that all children have one. + */ + if (!got_children) + { + children = find_inheritance_children(RelationGetRelid(rel), + lockmode); + /* only search for children on the first time through */ + got_children = true; + } + + foreach_oid(childrelid, children) + { + HeapTuple tup; + + tup = findNotNullConstraint(childrelid, strVal(column)); + if (!tup) + ereport(ERROR, + errmsg("column \"%s\" of table \"%s\" is not marked NOT NULL", + strVal(column), get_rel_name(childrelid))); + /* verify it's good enough */ + verifyNotNullPKCompatible(tup, strVal(column)); + } + } + + /* This column is not already not-null, so add it to the queue */ + nnconstr = makeNotNullConstraint(column); + + newcmd = makeNode(AlterTableCmd); + newcmd->subtype = AT_AddConstraint; + /* note we force recurse=true here; see above */ + newcmd->recurse = true; + newcmd->def = (Node *) nnconstr; + + ATPrepCmd(wqueue, rel, newcmd, true, false, lockmode, context); + } +} + +/* + * Verify whether the given not-null constraint is compatible with a + * primary key. If not, an error is thrown. + */ +static void +verifyNotNullPKCompatible(HeapTuple tuple, const char *colname) +{ + Form_pg_constraint conForm = (Form_pg_constraint) GETSTRUCT(tuple); + + if (conForm->contype != CONSTRAINT_NOTNULL) + elog(ERROR, "constraint %u is not a not-null constraint", conForm->oid); + + /* a NO INHERIT constraint is no good */ + if (conForm->connoinherit) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot create primary key on column \"%s\"", colname), + /*- translator: fourth %s is a constraint characteristic such as NOT VALID */ + errdetail("The constraint \"%s\" on column \"%s\" of table \"%s\", marked %s, is incompatible with a primary key.", + NameStr(conForm->conname), colname, + get_rel_name(conForm->conrelid), "NO INHERIT"), + errhint("You might need to make the existing constraint inheritable using %s.", + "ALTER TABLE ... ALTER CONSTRAINT ... INHERIT")); + + /* an unvalidated constraint is no good */ + if (!conForm->convalidated) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot create primary key on column \"%s\"", colname), + /*- translator: fourth %s is a constraint characteristic such as NOT VALID */ + errdetail("The constraint \"%s\" on column \"%s\" of table \"%s\", marked %s, is incompatible with a primary key.", + NameStr(conForm->conname), colname, + get_rel_name(conForm->conrelid), "NOT VALID"), + errhint("You might need to validate it using %s.", + "ALTER TABLE ... VALIDATE CONSTRAINT")); +} + /* * ALTER TABLE ADD INDEX * @@ -9336,17 +9767,18 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Assert(IsA(newConstraint, Constraint)); /* - * Currently, we only expect to see CONSTR_CHECK and CONSTR_FOREIGN nodes - * arriving here (see the preprocessing done in parse_utilcmd.c). Use a - * switch anyway to make it easier to add more code later. + * Currently, we only expect to see CONSTR_CHECK, CONSTR_NOTNULL and + * CONSTR_FOREIGN nodes arriving here (see the preprocessing done in + * parse_utilcmd.c). */ switch (newConstraint->contype) { case CONSTR_CHECK: + case CONSTR_NOTNULL: address = - ATAddCheckConstraint(wqueue, tab, rel, - newConstraint, recurse, false, is_readd, - lockmode); + ATAddCheckNNConstraint(wqueue, tab, rel, + newConstraint, recurse, false, is_readd, + lockmode); break; case CONSTR_FOREIGN: @@ -9427,9 +9859,9 @@ ChooseForeignKeyConstraintNameAddition(List *colnames) } /* - * Add a check constraint to a single table and its children. Returns the - * address of the constraint added to the parent relation, if one gets added, - * or InvalidObjectAddress otherwise. + * Add a check or not-null constraint to a single table and its children. + * Returns the address of the constraint added to the parent relation, + * if one gets added, or InvalidObjectAddress otherwise. * * Subroutine for ATExecAddConstraint. * @@ -9442,9 +9874,9 @@ ChooseForeignKeyConstraintNameAddition(List *colnames) * the parent table and pass that down. */ static ObjectAddress -ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, - Constraint *constr, bool recurse, bool recursing, - bool is_readd, LOCKMODE lockmode) +ATAddCheckNNConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, + Constraint *constr, bool recurse, bool recursing, + bool is_readd, LOCKMODE lockmode) { List *newcons; ListCell *lcon; @@ -9452,9 +9884,13 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ListCell *child; ObjectAddress address = InvalidObjectAddress; + /* Guard against stack overflow due to overly deep inheritance tree. */ + check_stack_depth(); + /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) - ATSimplePermissions(AT_AddConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(AT_AddConstraint, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* * Call AddRelationNewConstraints to do the work, making sure it works on @@ -9482,7 +9918,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, { CookedConstraint *ccon = (CookedConstraint *) lfirst(lcon); - if (!ccon->skip_validation) + if (!ccon->skip_validation && ccon->contype != CONSTR_NOTNULL) { NewConstraint *newcon; @@ -9498,11 +9934,22 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, if (constr->conname == NULL) constr->conname = ccon->name; + /* + * If adding a valid not-null constraint, set the pg_attribute flag + * and tell phase 3 to verify existing rows, if needed. For an + * invalid constraint, just set attnotnull, without queueing + * verification. + */ + if (constr->contype == CONSTR_NOTNULL) + set_attnotnull(wqueue, rel, ccon->attnum, + !constr->skip_validation, + !constr->skip_validation); + ObjectAddressSet(address, ConstraintRelationId, ccon->conoid); } /* At this point we must have a locked-down name to use */ - Assert(constr->conname != NULL); + Assert(newcons == NIL || constr->conname != NULL); /* Advance command counter in case same table is visited multiple times */ CommandCounterIncrement(); @@ -9532,7 +9979,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * Check if ONLY was specified with ALTER TABLE. If so, allow the - * constraint creation only if there are no children currently. Error out + * constraint creation only if there are no children currently. Error out * otherwise. */ if (!recurse && children != NIL) @@ -9540,6 +9987,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("constraint must be added to child tables too"))); + /* + * Recurse to create the constraint on each child. + */ foreach(child, children) { Oid childrelid = lfirst_oid(child); @@ -9553,9 +10003,9 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* Find or create work queue entry for this table */ childtab = ATGetQueueEntry(wqueue, childrel); - /* Recurse to child */ - ATAddCheckConstraint(wqueue, childtab, childrel, - constr, recurse, true, is_readd, lockmode); + /* Recurse to this child */ + ATAddCheckNNConstraint(wqueue, childtab, childrel, + constr, recurse, true, is_readd, lockmode); table_close(childrel, NoLock); } @@ -9588,11 +10038,15 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, int16 fkattnum[INDEX_MAX_KEYS] = {0}; Oid pktypoid[INDEX_MAX_KEYS] = {0}; Oid fktypoid[INDEX_MAX_KEYS] = {0}; + Oid pkcolloid[INDEX_MAX_KEYS] = {0}; + Oid fkcolloid[INDEX_MAX_KEYS] = {0}; Oid opclasses[INDEX_MAX_KEYS] = {0}; Oid pfeqoperators[INDEX_MAX_KEYS] = {0}; Oid ppeqoperators[INDEX_MAX_KEYS] = {0}; Oid ffeqoperators[INDEX_MAX_KEYS] = {0}; int16 fkdelsetcols[INDEX_MAX_KEYS] = {0}; + bool with_period; + bool pk_has_without_overlaps; int i; int numfks, numpks, @@ -9615,22 +10069,12 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * Validity checks (permission checks wait till we have the column * numbers) */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - if (!recurse) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"", - RelationGetRelationName(rel), - RelationGetRelationName(pkrel)))); - if (fkconstraint->skip_validation && !fkconstraint->initially_valid) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"", - RelationGetRelationName(rel), - RelationGetRelationName(pkrel)), - errdetail("This feature is not yet supported on partitioned tables."))); - } + if (!recurse && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"", + RelationGetRelationName(rel), + RelationGetRelationName(pkrel))); if (pkrel->rd_rel->relkind != RELKIND_RELATION && pkrel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) @@ -9682,46 +10126,75 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * Look up the referencing attributes to make sure they exist, and record - * their attnums and type OIDs. + * their attnums and type and collation OIDs. */ numfks = transformColumnNameList(RelationGetRelid(rel), fkconstraint->fk_attrs, - fkattnum, fktypoid); + fkattnum, fktypoid, fkcolloid); + with_period = fkconstraint->fk_with_period || fkconstraint->pk_with_period; + if (with_period && !fkconstraint->fk_with_period) + ereport(ERROR, + errcode(ERRCODE_INVALID_FOREIGN_KEY), + errmsg("foreign key uses PERIOD on the referenced table but not the referencing table")); numfkdelsetcols = transformColumnNameList(RelationGetRelid(rel), fkconstraint->fk_del_set_cols, - fkdelsetcols, NULL); - validateFkOnDeleteSetColumns(numfks, fkattnum, - numfkdelsetcols, fkdelsetcols, - fkconstraint->fk_del_set_cols); + fkdelsetcols, NULL, NULL); + numfkdelsetcols = validateFkOnDeleteSetColumns(numfks, fkattnum, + numfkdelsetcols, + fkdelsetcols, + fkconstraint->fk_del_set_cols); /* * If the attribute list for the referenced table was omitted, lookup the * definition of the primary key and use it. Otherwise, validate the * supplied attribute list. In either case, discover the index OID and - * index opclasses, and the attnums and type OIDs of the attributes. + * index opclasses, and the attnums and type and collation OIDs of the + * attributes. */ if (fkconstraint->pk_attrs == NIL) { numpks = transformFkeyGetPrimaryKey(pkrel, &indexOid, &fkconstraint->pk_attrs, - pkattnum, pktypoid, - opclasses); + pkattnum, pktypoid, pkcolloid, + opclasses, &pk_has_without_overlaps); + + /* If the primary key uses WITHOUT OVERLAPS, the fk must use PERIOD */ + if (pk_has_without_overlaps && !fkconstraint->fk_with_period) + ereport(ERROR, + errcode(ERRCODE_INVALID_FOREIGN_KEY), + errmsg("foreign key uses PERIOD on the referenced table but not the referencing table")); } else { numpks = transformColumnNameList(RelationGetRelid(pkrel), fkconstraint->pk_attrs, - pkattnum, pktypoid); + pkattnum, pktypoid, pkcolloid); + + /* Since we got pk_attrs, one should be a period. */ + if (with_period && !fkconstraint->pk_with_period) + ereport(ERROR, + errcode(ERRCODE_INVALID_FOREIGN_KEY), + errmsg("foreign key uses PERIOD on the referencing table but not the referenced table")); + /* Look for an index matching the column list */ indexOid = transformFkeyCheckAttrs(pkrel, numpks, pkattnum, - opclasses); + with_period, opclasses, &pk_has_without_overlaps); } /* - * Now we can check permissions. + * If the referenced primary key has WITHOUT OVERLAPS, the foreign key + * must use PERIOD. */ - checkFkeyPermissions(pkrel, pkattnum, numpks); + if (pk_has_without_overlaps && !with_period) + ereport(ERROR, + errcode(ERRCODE_INVALID_FOREIGN_KEY), + errmsg("foreign key must use PERIOD when referencing a primary using WITHOUT OVERLAPS")); + + /* + * Now we can check permissions. + */ + checkFkeyPermissions(pkrel, pkattnum, numpks); /* * Check some things for generated columns. @@ -9749,6 +10222,43 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, errmsg("invalid %s action for foreign key constraint containing generated column", "ON DELETE"))); } + + /* + * FKs on virtual columns are not supported. This would require + * various additional support in ri_triggers.c, including special + * handling in ri_NullCheck(), ri_KeysEqual(), + * RI_FKey_fk_upd_check_required() (since all virtual columns appear + * as NULL there). Also not really practical as long as you can't + * index virtual columns. + */ + if (attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("foreign key constraints on virtual generated columns are not supported"))); + } + + /* + * Some actions are currently unsupported for foreign keys using PERIOD. + */ + if (fkconstraint->fk_with_period) + { + if (fkconstraint->fk_upd_action == FKCONSTR_ACTION_RESTRICT || + fkconstraint->fk_upd_action == FKCONSTR_ACTION_CASCADE || + fkconstraint->fk_upd_action == FKCONSTR_ACTION_SETNULL || + fkconstraint->fk_upd_action == FKCONSTR_ACTION_SETDEFAULT) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported %s action for foreign key constraint using PERIOD", + "ON UPDATE")); + + if (fkconstraint->fk_del_action == FKCONSTR_ACTION_RESTRICT || + fkconstraint->fk_del_action == FKCONSTR_ACTION_CASCADE || + fkconstraint->fk_del_action == FKCONSTR_ACTION_SETNULL || + fkconstraint->fk_del_action == FKCONSTR_ACTION_SETDEFAULT) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported %s action for foreign key constraint using PERIOD", + "ON DELETE")); } /* @@ -9776,11 +10286,15 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, Oid pktype = pktypoid[i]; Oid fktype = fktypoid[i]; Oid fktyped; + Oid pkcoll = pkcolloid[i]; + Oid fkcoll = fkcolloid[i]; HeapTuple cla_ht; Form_pg_opclass cla_tup; Oid amid; Oid opfamily; Oid opcintype; + bool for_overlaps; + CompareType cmptype; Oid pfeqop; Oid ppeqop; Oid ffeqop; @@ -9798,15 +10312,26 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, ReleaseSysCache(cla_ht); /* - * Check it's a btree; currently this can never fail since no other - * index AMs support unique indexes. If we ever did have other types - * of unique indexes, we'd need a way to determine which operator - * strategy number is equality. (Is it reasonable to insist that - * every such index AM use btree's number for equality?) + * Get strategy number from index AM. + * + * For a normal foreign-key constraint, this should not fail, since we + * already checked that the index is unique and should therefore have + * appropriate equal operators. For a period foreign key, this could + * fail if we selected a non-matching exclusion constraint earlier. + * (XXX Maybe we should do these lookups earlier so we don't end up + * doing that.) */ - if (amid != BTREE_AM_OID) - elog(ERROR, "only b-tree indexes are supported for foreign keys"); - eqstrategy = BTEqualStrategyNumber; + for_overlaps = with_period && i == numpks - 1; + cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ; + eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, true); + if (eqstrategy == InvalidStrategy) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + for_overlaps + ? errmsg("could not identify an overlaps operator for foreign key") + : errmsg("could not identify an equality operator for foreign key"), + errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".", + cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid))); /* * There had better be a primary equality operator for the index. @@ -9871,13 +10396,48 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("foreign key constraint \"%s\" cannot be implemented", fkconstraint->conname), - errdetail("Key columns \"%s\" and \"%s\" " + errdetail("Key columns \"%s\" of the referencing table and \"%s\" of the referenced table " "are of incompatible types: %s and %s.", strVal(list_nth(fkconstraint->fk_attrs, i)), strVal(list_nth(fkconstraint->pk_attrs, i)), format_type_be(fktype), format_type_be(pktype)))); + /* + * This shouldn't be possible, but better check to make sure we have a + * consistent state for the check below. + */ + if ((OidIsValid(pkcoll) && !OidIsValid(fkcoll)) || (!OidIsValid(pkcoll) && OidIsValid(fkcoll))) + elog(ERROR, "key columns are not both collatable"); + + if (OidIsValid(pkcoll) && OidIsValid(fkcoll)) + { + bool pkcolldet; + bool fkcolldet; + + pkcolldet = get_collation_isdeterministic(pkcoll); + fkcolldet = get_collation_isdeterministic(fkcoll); + + /* + * SQL requires that both collations are the same. This is + * because we need a consistent notion of equality on both + * columns. We relax this by allowing different collations if + * they are both deterministic. (This is also for backward + * compatibility, because PostgreSQL has always allowed this.) + */ + if ((!pkcolldet || !fkcolldet) && pkcoll != fkcoll) + ereport(ERROR, + (errcode(ERRCODE_COLLATION_MISMATCH), + errmsg("foreign key constraint \"%s\" cannot be implemented", fkconstraint->conname), + errdetail("Key columns \"%s\" of the referencing table and \"%s\" of the referenced table " + "have incompatible collations: \"%s\" and \"%s\". " + "If either collation is nondeterministic, then both collations have to be the same.", + strVal(list_nth(fkconstraint->fk_attrs, i)), + strVal(list_nth(fkconstraint->pk_attrs, i)), + get_collation_name(fkcoll), + get_collation_name(pkcoll)))); + } + if (old_check_ok) { /* @@ -9898,6 +10458,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, CoercionPathType new_pathtype; Oid old_castfunc; Oid new_castfunc; + Oid old_fkcoll; + Oid new_fkcoll; Form_pg_attribute attr = TupleDescAttr(tab->oldDesc, fkattnum[i] - 1); @@ -9913,6 +10475,9 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, new_pathtype = findFkeyCast(pfeqop_right, new_fktype, &new_castfunc); + old_fkcoll = attr->attcollation; + new_fkcoll = fkcoll; + /* * Upon a change to the cast from the FK column to its pfeqop * operand, revalidate the constraint. For this evaluation, a @@ -9936,9 +10501,10 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * turn conform to the domain. Consequently, we need not treat * domains specially here. * - * Since we require that all collations share the same notion of - * equality (which they do, because texteq reduces to bitwise - * equality), we don't compare collation here. + * If the collation changes, revalidation is required, unless both + * collations are deterministic, because those share the same + * notion of equality (because texteq reduces to bitwise + * equality). * * We need not directly consider the PK type. It's necessarily * binary coercible to the opcintype of the unique index column, @@ -9948,7 +10514,9 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, old_check_ok = (new_pathtype == old_pathtype && new_castfunc == old_castfunc && (!IsPolymorphicType(pfeqop_right) || - new_fktype == old_fktype)); + new_fktype == old_fktype) && + (new_fkcoll == old_fkcoll || + (get_collation_isdeterministic(old_fkcoll) && get_collation_isdeterministic(new_fkcoll)))); } pfeqoperators[i] = pfeqop; @@ -9957,24 +10525,56 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, } /* - * Create all the constraint and trigger objects, recursing to partitions - * as necessary. First handle the referenced side. - */ - address = addFkRecurseReferenced(wqueue, fkconstraint, rel, pkrel, - indexOid, - InvalidOid, /* no parent constraint */ - numfks, - pkattnum, - fkattnum, - pfeqoperators, - ppeqoperators, - ffeqoperators, - numfkdelsetcols, - fkdelsetcols, - old_check_ok, - InvalidOid, InvalidOid); - - /* Now handle the referencing side. */ + * For FKs with PERIOD we need additional operators to check whether the + * referencing row's range is contained by the aggregated ranges of the + * referenced row(s). For rangetypes and multirangetypes this is + * fk.periodatt <@ range_agg(pk.periodatt). Those are the only types we + * support for now. FKs will look these up at "runtime", but we should + * make sure the lookup works here, even if we don't use the values. + */ + if (with_period) + { + Oid periodoperoid; + Oid aggedperiodoperoid; + Oid intersectoperoid; + + FindFKPeriodOpers(opclasses[numpks - 1], &periodoperoid, &aggedperiodoperoid, + &intersectoperoid); + } + + /* First, create the constraint catalog entry itself. */ + address = addFkConstraint(addFkBothSides, + fkconstraint->conname, fkconstraint, rel, pkrel, + indexOid, + InvalidOid, /* no parent constraint */ + numfks, + pkattnum, + fkattnum, + pfeqoperators, + ppeqoperators, + ffeqoperators, + numfkdelsetcols, + fkdelsetcols, + false, + with_period); + + /* Next process the action triggers at the referenced side and recurse */ + addFkRecurseReferenced(fkconstraint, rel, pkrel, + indexOid, + address.objectId, + numfks, + pkattnum, + fkattnum, + pfeqoperators, + ppeqoperators, + ffeqoperators, + numfkdelsetcols, + fkdelsetcols, + old_check_ok, + InvalidOid, InvalidOid, + with_period); + + /* Lastly create the check triggers at the referencing side and recurse */ addFkRecurseReferencing(wqueue, fkconstraint, rel, pkrel, indexOid, address.objectId, @@ -9988,7 +10588,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, fkdelsetcols, old_check_ok, lockmode, - InvalidOid, InvalidOid); + InvalidOid, InvalidOid, + with_period); /* * Done. Close pk table, but keep lock until we've committed. @@ -10002,17 +10603,23 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * validateFkOnDeleteSetColumns * Verifies that columns used in ON DELETE SET NULL/DEFAULT (...) * column lists are valid. + * + * If there are duplicates in the fksetcolsattnums[] array, this silently + * removes the dups. The new count of numfksetcols is returned. */ -void +static int validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums, - int numfksetcols, const int16 *fksetcolsattnums, + int numfksetcols, int16 *fksetcolsattnums, List *fksetcols) { + int numcolsout = 0; + for (int i = 0; i < numfksetcols; i++) { int16 setcol_attnum = fksetcolsattnums[i]; bool seen = false; + /* Make sure it's in fkattnums[] */ for (int j = 0; j < numfks; j++) { if (fkattnums[j] == setcol_attnum) @@ -10030,59 +10637,67 @@ validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("column \"%s\" referenced in ON DELETE SET action must be part of foreign key", col))); } + + /* Now check for dups */ + seen = false; + for (int j = 0; j < numcolsout; j++) + { + if (fksetcolsattnums[j] == setcol_attnum) + { + seen = true; + break; + } + } + if (!seen) + fksetcolsattnums[numcolsout++] = setcol_attnum; } + return numcolsout; } /* - * addFkRecurseReferenced - * subroutine for ATAddForeignKeyConstraint; recurses on the referenced - * side of the constraint + * addFkConstraint + * Install pg_constraint entries to implement a foreign key constraint. + * Caller must separately invoke addFkRecurseReferenced and + * addFkRecurseReferencing, as appropriate, to install pg_trigger entries + * and (for partitioned tables) recurse to partitions. * - * Create pg_constraint rows for the referenced side of the constraint, - * referencing the parent of the referencing side; also create action triggers - * on leaf partitions. If the table is partitioned, recurse to handle each - * partition. - * - * wqueue is the ALTER TABLE work queue; can be NULL when not running as part - * of an ALTER TABLE sequence. - * fkconstraint is the constraint being added. - * rel is the root referencing relation. - * pkrel is the referenced relation; might be a partition, if recursing. - * indexOid is the OID of the index (on pkrel) implementing this constraint. - * parentConstr is the OID of a parent constraint; InvalidOid if this is a - * top-level constraint. - * numfks is the number of columns in the foreign key - * pkattnum is the attnum array of referenced attributes. - * fkattnum is the attnum array of referencing attributes. - * numfkdelsetcols is the number of columns in the ON DELETE SET NULL/DEFAULT + * fkside: the side of the FK (or both) to create. Caller should + * call addFkRecurseReferenced if this is addFkReferencedSide, + * addFkRecurseReferencing if it's addFkReferencingSide, or both if it's + * addFkBothSides. + * constraintname: the base name for the constraint being added, + * copied to fkconstraint->conname if the latter is not set + * fkconstraint: the constraint being added + * rel: the root referencing relation + * pkrel: the referenced relation; might be a partition, if recursing + * indexOid: the OID of the index (on pkrel) implementing this constraint + * parentConstr: the OID of a parent constraint; InvalidOid if this is a + * top-level constraint + * numfks: the number of columns in the foreign key + * pkattnum: the attnum array of referenced attributes + * fkattnum: the attnum array of referencing attributes + * pf/pp/ffeqoperators: OID array of operators between columns + * numfkdelsetcols: the number of columns in the ON DELETE SET NULL/DEFAULT * (...) clause - * fkdelsetcols is the attnum array of the columns in the ON DELETE SET + * fkdelsetcols: the attnum array of the columns in the ON DELETE SET * NULL/DEFAULT clause - * pf/pp/ffeqoperators are OID array of operators between columns. - * old_check_ok signals that this constraint replaces an existing one that - * was already validated (thus this one doesn't need validation). - * parentDelTrigger and parentUpdTrigger, when being recursively called on - * a partition, are the OIDs of the parent action triggers for DELETE and - * UPDATE respectively. + * with_period: true if this is a temporal FK */ static ObjectAddress -addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, - Relation pkrel, Oid indexOid, Oid parentConstr, - int numfks, - int16 *pkattnum, int16 *fkattnum, Oid *pfeqoperators, - Oid *ppeqoperators, Oid *ffeqoperators, - int numfkdelsetcols, int16 *fkdelsetcols, - bool old_check_ok, - Oid parentDelTrigger, Oid parentUpdTrigger) +addFkConstraint(addFkConstraintSides fkside, + char *constraintname, Constraint *fkconstraint, + Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr, + int numfks, int16 *pkattnum, + int16 *fkattnum, Oid *pfeqoperators, Oid *ppeqoperators, + Oid *ffeqoperators, int numfkdelsetcols, int16 *fkdelsetcols, + bool is_internal, bool with_period) { ObjectAddress address; Oid constrOid; char *conname; bool conislocal; - int coninhcount; + int16 coninhcount; bool connoinherit; - Oid deleteTriggerOid, - updateTriggerOid; /* * Verify relkind for each referenced partition. At the top level, this @@ -10097,17 +10712,22 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, /* * Caller supplies us with a constraint name; however, it may be used in - * this partition, so come up with a different one in that case. + * this partition, so come up with a different one in that case. Unless + * truncation to NAMEDATALEN dictates otherwise, the new name will be the + * supplied name with an underscore and digit(s) appended. */ if (ConstraintNameIsUsed(CONSTRAINT_RELATION, RelationGetRelid(rel), - fkconstraint->conname)) - conname = ChooseConstraintName(RelationGetRelationName(rel), - ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs), - "fkey", + constraintname)) + conname = ChooseConstraintName(constraintname, + NULL, + "", RelationGetNamespace(rel), NIL); else - conname = fkconstraint->conname; + conname = constraintname; + + if (fkconstraint->conname == NULL) + fkconstraint->conname = pstrdup(conname); if (OidIsValid(parentConstr)) { @@ -10134,6 +10754,7 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, CONSTRAINT_FOREIGN, fkconstraint->deferrable, fkconstraint->initdeferred, + fkconstraint->is_enforced, fkconstraint->initially_valid, parentConstr, RelationGetRelid(rel), @@ -10159,35 +10780,115 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, conislocal, /* islocal */ coninhcount, /* inhcount */ connoinherit, /* conNoInherit */ - false); /* is_internal */ + with_period, /* conPeriod */ + is_internal); /* is_internal */ ObjectAddressSet(address, ConstraintRelationId, constrOid); /* - * Mark the child constraint as part of the parent constraint; it must not - * be dropped on its own. (This constraint is deleted when the partition - * is detached, but a special check needs to occur that the partition - * contains no referenced values.) + * In partitioning cases, create the dependency entries for this + * constraint. (For non-partitioned cases, relevant entries were created + * by CreateConstraintEntry.) + * + * On the referenced side, we need the constraint to have an internal + * dependency on its parent constraint; this means that this constraint + * cannot be dropped on its own -- only through the parent constraint. It + * also means the containing partition cannot be dropped on its own, but + * it can be detached, at which point this dependency is removed (after + * verifying that no rows are referenced via this FK.) + * + * When processing the referencing side, we link the constraint via the + * special partitioning dependencies: the parent constraint is the primary + * dependent, and the partition on which the foreign key exists is the + * secondary dependency. That way, this constraint is dropped if either + * of these objects is. + * + * Note that this is only necessary for the subsidiary pg_constraint rows + * in partitions; the topmost row doesn't need any of this. */ if (OidIsValid(parentConstr)) { ObjectAddress referenced; ObjectAddressSet(referenced, ConstraintRelationId, parentConstr); - recordDependencyOn(&address, &referenced, DEPENDENCY_INTERNAL); + + Assert(fkside != addFkBothSides); + if (fkside == addFkReferencedSide) + recordDependencyOn(&address, &referenced, DEPENDENCY_INTERNAL); + else + { + recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_PRI); + ObjectAddressSet(referenced, RelationRelationId, RelationGetRelid(rel)); + recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_SEC); + } } /* make new constraint visible, in case we add more */ CommandCounterIncrement(); + return address; +} + +/* + * addFkRecurseReferenced + * Recursive helper for the referenced side of foreign key creation, + * which creates the action triggers and recurses + * + * If the referenced relation is a plain relation, create the necessary action + * triggers that implement the constraint. If the referenced relation is a + * partitioned table, then we create a pg_constraint row referencing the parent + * of the referencing side for it and recurse on this routine for each + * partition. + * + * fkconstraint: the constraint being added + * rel: the root referencing relation + * pkrel: the referenced relation; might be a partition, if recursing + * indexOid: the OID of the index (on pkrel) implementing this constraint + * parentConstr: the OID of a parent constraint; InvalidOid if this is a + * top-level constraint + * numfks: the number of columns in the foreign key + * pkattnum: the attnum array of referenced attributes + * fkattnum: the attnum array of referencing attributes + * numfkdelsetcols: the number of columns in the ON DELETE SET + * NULL/DEFAULT (...) clause + * fkdelsetcols: the attnum array of the columns in the ON DELETE SET + * NULL/DEFAULT clause + * pf/pp/ffeqoperators: OID array of operators between columns + * old_check_ok: true if this constraint replaces an existing one that + * was already validated (thus this one doesn't need validation) + * parentDelTrigger and parentUpdTrigger: when recursively called on a + * partition, the OIDs of the parent action triggers for DELETE and + * UPDATE respectively. + * with_period: true if this is a temporal FK + */ +static void +addFkRecurseReferenced(Constraint *fkconstraint, Relation rel, + Relation pkrel, Oid indexOid, Oid parentConstr, + int numfks, + int16 *pkattnum, int16 *fkattnum, Oid *pfeqoperators, + Oid *ppeqoperators, Oid *ffeqoperators, + int numfkdelsetcols, int16 *fkdelsetcols, + bool old_check_ok, + Oid parentDelTrigger, Oid parentUpdTrigger, + bool with_period) +{ + Oid deleteTriggerOid = InvalidOid, + updateTriggerOid = InvalidOid; + + Assert(CheckRelationLockedByMe(pkrel, ShareRowExclusiveLock, true)); + Assert(CheckRelationLockedByMe(rel, ShareRowExclusiveLock, true)); + /* - * Create the action triggers that enforce the constraint. + * Create action triggers to enforce the constraint, or skip them if the + * constraint is NOT ENFORCED. */ - createForeignKeyActionTriggers(rel, RelationGetRelid(pkrel), - fkconstraint, - constrOid, indexOid, - parentDelTrigger, parentUpdTrigger, - &deleteTriggerOid, &updateTriggerOid); + if (fkconstraint->is_enforced) + createForeignKeyActionTriggers(RelationGetRelid(rel), + RelationGetRelid(pkrel), + fkconstraint, + parentConstr, indexOid, + parentDelTrigger, parentUpdTrigger, + &deleteTriggerOid, &updateTriggerOid); /* * If the referenced table is partitioned, recurse on ourselves to handle @@ -10204,7 +10905,9 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, AttrMap *map; AttrNumber *mapped_pkattnum; Oid partIndexId; + ObjectAddress address; + /* XXX would it be better to acquire these locks beforehand? */ partRel = table_open(pd->oids[i], ShareRowExclusiveLock); /* @@ -10223,18 +10926,29 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, else mapped_pkattnum = pkattnum; - /* do the deed */ + /* Determine the index to use at this level */ partIndexId = index_get_partition(partRel, indexOid); if (!OidIsValid(partIndexId)) elog(ERROR, "index for %u not found in partition %s", indexOid, RelationGetRelationName(partRel)); - addFkRecurseReferenced(wqueue, fkconstraint, rel, partRel, - partIndexId, constrOid, numfks, + + /* Create entry at this level ... */ + address = addFkConstraint(addFkReferencedSide, + fkconstraint->conname, fkconstraint, rel, + partRel, partIndexId, parentConstr, + numfks, mapped_pkattnum, + fkattnum, pfeqoperators, ppeqoperators, + ffeqoperators, numfkdelsetcols, + fkdelsetcols, true, with_period); + /* ... and recurse to our children */ + addFkRecurseReferenced(fkconstraint, rel, partRel, + partIndexId, address.objectId, numfks, mapped_pkattnum, fkattnum, pfeqoperators, ppeqoperators, ffeqoperators, numfkdelsetcols, fkdelsetcols, old_check_ok, - deleteTriggerOid, updateTriggerOid); + deleteTriggerOid, updateTriggerOid, + with_period); /* Done -- clean up (but keep the lock) */ table_close(partRel, NoLock); @@ -10245,13 +10959,12 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, } } } - - return address; } /* * addFkRecurseReferencing - * subroutine for ATAddForeignKeyConstraint and CloneFkReferencing + * Recursive helper for the referencing side of foreign key creation, + * which creates the check triggers and recurses * * If the referencing relation is a plain relation, create the necessary check * triggers that implement the constraint, and set up for Phase 3 constraint @@ -10263,27 +10976,28 @@ addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint, Relation rel, * deletions. If it's a partitioned relation, every partition must be so * locked. * - * wqueue is the ALTER TABLE work queue; can be NULL when not running as part - * of an ALTER TABLE sequence. - * fkconstraint is the constraint being added. - * rel is the referencing relation; might be a partition, if recursing. - * pkrel is the root referenced relation. - * indexOid is the OID of the index (on pkrel) implementing this constraint. - * parentConstr is the OID of the parent constraint (there is always one). - * numfks is the number of columns in the foreign key - * pkattnum is the attnum array of referenced attributes. - * fkattnum is the attnum array of referencing attributes. - * pf/pp/ffeqoperators are OID array of operators between columns. - * numfkdelsetcols is the number of columns in the ON DELETE SET NULL/DEFAULT + * wqueue: the ALTER TABLE work queue; NULL when not running as part + * of an ALTER TABLE sequence. + * fkconstraint: the constraint being added + * rel: the referencing relation; might be a partition, if recursing + * pkrel: the root referenced relation + * indexOid: the OID of the index (on pkrel) implementing this constraint + * parentConstr: the OID of the parent constraint (there is always one) + * numfks: the number of columns in the foreign key + * pkattnum: the attnum array of referenced attributes + * fkattnum: the attnum array of referencing attributes + * pf/pp/ffeqoperators: OID array of operators between columns + * numfkdelsetcols: the number of columns in the ON DELETE SET NULL/DEFAULT * (...) clause - * fkdelsetcols is the attnum array of the columns in the ON DELETE SET + * fkdelsetcols: the attnum array of the columns in the ON DELETE SET * NULL/DEFAULT clause - * old_check_ok signals that this constraint replaces an existing one that - * was already validated (thus this one doesn't need validation). - * lockmode is the lockmode to acquire on partitions when recursing. - * parentInsTrigger and parentUpdTrigger, when being recursively called on - * a partition, are the OIDs of the parent check triggers for INSERT and - * UPDATE respectively. + * old_check_ok: true if this constraint replaces an existing one that + * was already validated (thus this one doesn't need validation) + * lockmode: the lockmode to acquire on partitions when recursing + * parentInsTrigger and parentUpdTrigger: when being recursively called on + * a partition, the OIDs of the parent check triggers for INSERT and + * UPDATE respectively. + * with_period: true if this is a temporal FK */ static void addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, @@ -10292,12 +11006,15 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators, int numfkdelsetcols, int16 *fkdelsetcols, bool old_check_ok, LOCKMODE lockmode, - Oid parentInsTrigger, Oid parentUpdTrigger) + Oid parentInsTrigger, Oid parentUpdTrigger, + bool with_period) { - Oid insertTriggerOid, - updateTriggerOid; + Oid insertTriggerOid = InvalidOid, + updateTriggerOid = InvalidOid; Assert(OidIsValid(parentConstr)); + Assert(CheckRelationLockedByMe(rel, ShareRowExclusiveLock, true)); + Assert(CheckRelationLockedByMe(pkrel, ShareRowExclusiveLock, true)); if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) ereport(ERROR, @@ -10305,29 +11022,32 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, errmsg("foreign key constraints are not supported on foreign tables"))); /* - * Add the check triggers to it and, if necessary, schedule it to be - * checked in Phase 3. + * Add check triggers if the constraint is ENFORCED, and if needed, + * schedule them to be checked in Phase 3. * * If the relation is partitioned, drill down to do it to its partitions. */ - createForeignKeyCheckTriggers(RelationGetRelid(rel), - RelationGetRelid(pkrel), - fkconstraint, - parentConstr, - indexOid, - parentInsTrigger, parentUpdTrigger, - &insertTriggerOid, &updateTriggerOid); + if (fkconstraint->is_enforced) + createForeignKeyCheckTriggers(RelationGetRelid(rel), + RelationGetRelid(pkrel), + fkconstraint, + parentConstr, + indexOid, + parentInsTrigger, parentUpdTrigger, + &insertTriggerOid, &updateTriggerOid); if (rel->rd_rel->relkind == RELKIND_RELATION) { /* * Tell Phase 3 to check that the constraint is satisfied by existing - * rows. We can skip this during table creation, when requested - * explicitly by specifying NOT VALID in an ADD FOREIGN KEY command, - * and when we're recreating a constraint following a SET DATA TYPE - * operation that did not impugn its validity. + * rows. We can skip this during table creation, when constraint is + * specified as NOT ENFORCED, or when requested explicitly by + * specifying NOT VALID in an ADD FOREIGN KEY command, and when we're + * recreating a constraint following a SET DATA TYPE operation that + * did not impugn its validity. */ - if (wqueue && !old_check_ok && !fkconstraint->skip_validation) + if (wqueue && !old_check_ok && !fkconstraint->skip_validation && + fkconstraint->is_enforced) { NewConstraint *newcon; AlteredTableInfo *tab; @@ -10340,6 +11060,7 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, newcon->refrelid = RelationGetRelid(pkrel); newcon->refindid = indexOid; newcon->conid = parentConstr; + newcon->conwithperiod = fkconstraint->fk_with_period; newcon->qual = (Node *) fkconstraint; tab->constraints = lappend(tab->constraints, newcon); @@ -10365,17 +11086,12 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, */ for (int i = 0; i < pd->nparts; i++) { - Oid partitionId = pd->oids[i]; - Relation partition = table_open(partitionId, lockmode); + Relation partition = table_open(pd->oids[i], lockmode); List *partFKs; AttrMap *attmap; AttrNumber mapped_fkattnum[INDEX_MAX_KEYS]; bool attached; - char *conname; - Oid constrOid; - ObjectAddress address, - referenced; - ListCell *cell; + ObjectAddress address; CheckAlterTableIsSafe(partition); @@ -10388,13 +11104,11 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, /* Check whether an existing constraint can be repurposed */ partFKs = copyObject(RelationGetFKeyList(partition)); attached = false; - foreach(cell, partFKs) + foreach_node(ForeignKeyCacheInfo, fk, partFKs) { - ForeignKeyCacheInfo *fk; - - fk = lfirst_node(ForeignKeyCacheInfo, cell); - if (tryAttachPartitionForeignKey(fk, - partitionId, + if (tryAttachPartitionForeignKey(wqueue, + fk, + partition, parentConstr, numfks, mapped_fkattnum, @@ -10417,65 +11131,19 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, /* * No luck finding a good constraint to reuse; create our own. */ - if (ConstraintNameIsUsed(CONSTRAINT_RELATION, - RelationGetRelid(partition), - fkconstraint->conname)) - conname = ChooseConstraintName(RelationGetRelationName(partition), - ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs), - "fkey", - RelationGetNamespace(partition), NIL); - else - conname = fkconstraint->conname; - constrOid = - CreateConstraintEntry(conname, - RelationGetNamespace(partition), - CONSTRAINT_FOREIGN, - fkconstraint->deferrable, - fkconstraint->initdeferred, - fkconstraint->initially_valid, - parentConstr, - partitionId, - mapped_fkattnum, - numfks, - numfks, - InvalidOid, - indexOid, - RelationGetRelid(pkrel), - pkattnum, - pfeqoperators, - ppeqoperators, - ffeqoperators, - numfks, - fkconstraint->fk_upd_action, - fkconstraint->fk_del_action, - fkdelsetcols, - numfkdelsetcols, - fkconstraint->fk_matchtype, - NULL, - NULL, - NULL, - false, - 1, - false, - false); - - /* - * Give this constraint partition-type dependencies on the parent - * constraint as well as the table. - */ - ObjectAddressSet(address, ConstraintRelationId, constrOid); - ObjectAddressSet(referenced, ConstraintRelationId, parentConstr); - recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_PRI); - ObjectAddressSet(referenced, RelationRelationId, partitionId); - recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_SEC); - - /* Make all this visible before recursing */ - CommandCounterIncrement(); + address = addFkConstraint(addFkReferencingSide, + fkconstraint->conname, fkconstraint, + partition, pkrel, indexOid, parentConstr, + numfks, pkattnum, + mapped_fkattnum, pfeqoperators, + ppeqoperators, ffeqoperators, + numfkdelsetcols, fkdelsetcols, true, + with_period); /* call ourselves to finalize the creation and we're done */ addFkRecurseReferencing(wqueue, fkconstraint, partition, pkrel, indexOid, - constrOid, + address.objectId, numfks, pkattnum, mapped_fkattnum, @@ -10487,7 +11155,8 @@ addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint, Relation rel, old_check_ok, lockmode, insertTriggerOid, - updateTriggerOid); + updateTriggerOid, + with_period); table_close(partition, NoLock); } @@ -10517,14 +11186,14 @@ CloneForeignKeyConstraints(List **wqueue, Relation parentRel, Assert(parentRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); /* - * Clone constraints for which the parent is on the referenced side. + * First, clone constraints where the parent is on the referencing side. */ - CloneFkReferenced(parentRel, partitionRel); + CloneFkReferencing(wqueue, parentRel, partitionRel); /* - * Now clone constraints where the parent is on the referencing side. + * Clone constraints for which the parent is on the referenced side. */ - CloneFkReferencing(wqueue, parentRel, partitionRel); + CloneFkReferenced(parentRel, partitionRel); } /* @@ -10535,8 +11204,6 @@ CloneForeignKeyConstraints(List **wqueue, Relation parentRel, * clone those constraints to the given partition. This is to be called * when the partition is being created or attached. * - * This ignores self-referencing FKs; those are handled by CloneFkReferencing. - * * This recurses to partitions, if the relation being attached is partitioned. * Recursion is done by calling addFkRecurseReferenced. */ @@ -10608,8 +11275,9 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) int numfkdelsetcols; AttrNumber confdelsetcols[INDEX_MAX_KEYS]; Constraint *fkconstraint; - Oid deleteTriggerOid, - updateTriggerOid; + ObjectAddress address; + Oid deleteTriggerOid = InvalidOid, + updateTriggerOid = InvalidOid; tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constrOid)); if (!HeapTupleIsValid(tuple)) @@ -10626,24 +11294,8 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) continue; } - /* - * Don't clone self-referencing foreign keys, which can be in the - * partitioned table or in the partition-to-be. - */ - if (constrForm->conrelid == RelationGetRelid(parentRel) || - constrForm->conrelid == RelationGetRelid(partitionRel)) - { - ReleaseSysCache(tuple); - continue; - } - - /* - * Because we're only expanding the key space at the referenced side, - * we don't need to prevent any operation in the referencing table, so - * AccessShareLock suffices (assumes that dropping the constraint - * acquires AEL). - */ - fkRel = table_open(constrForm->conrelid, AccessShareLock); + /* We need the same lock level that CreateTrigger will acquire */ + fkRel = table_open(constrForm->conrelid, ShareRowExclusiveLock); indexOid = constrForm->conindid; DeconstructFkConstraintRow(tuple, @@ -10674,8 +11326,9 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) fkconstraint->fk_del_set_cols = NIL; fkconstraint->old_conpfeqop = NIL; fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->is_enforced = constrForm->conenforced; fkconstraint->skip_validation = false; - fkconstraint->initially_valid = true; + fkconstraint->initially_valid = constrForm->convalidated; /* set up colnames that are used to generate the constraint name */ for (int i = 0; i < numfks; i++) @@ -10703,16 +11356,25 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) * parent OIDs for similar triggers that will be created on the * partition in addFkRecurseReferenced(). */ - GetForeignKeyActionTriggers(trigrel, constrOid, - constrForm->confrelid, constrForm->conrelid, - &deleteTriggerOid, &updateTriggerOid); - - addFkRecurseReferenced(NULL, - fkconstraint, + if (constrForm->conenforced) + GetForeignKeyActionTriggers(trigrel, constrOid, + constrForm->confrelid, constrForm->conrelid, + &deleteTriggerOid, &updateTriggerOid); + + /* Add this constraint ... */ + address = addFkConstraint(addFkReferencedSide, + fkconstraint->conname, fkconstraint, fkRel, + partitionRel, partIndexId, constrOid, + numfks, mapped_confkey, + conkey, conpfeqop, conppeqop, conffeqop, + numfkdelsetcols, confdelsetcols, false, + constrForm->conperiod); + /* ... and recurse */ + addFkRecurseReferenced(fkconstraint, fkRel, partitionRel, partIndexId, - constrOid, + address.objectId, numfks, mapped_confkey, conkey, @@ -10723,7 +11385,8 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) confdelsetcols, true, deleteTriggerOid, - updateTriggerOid); + updateTriggerOid, + constrForm->conperiod); table_close(fkRel, NoLock); ReleaseSysCache(tuple); @@ -10742,8 +11405,8 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) * child. * * If wqueue is given, it is used to set up phase-3 verification for each - * cloned constraint; if omitted, we assume that such verification is not - * needed (example: the partition is being created anew). + * cloned constraint; omit it if such verification is not needed + * (example: the partition is being created anew). */ static void CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) @@ -10759,6 +11422,23 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) { ForeignKeyCacheInfo *fk = lfirst(cell); + /* + * Refuse to attach a table as partition that this partitioned table + * already has a foreign key to. This isn't useful schema, which is + * proven by the fact that there have been no user complaints that + * it's already impossible to achieve this in the opposite direction, + * i.e., creating a foreign key that references a partition. This + * restriction allows us to dodge some complexities around + * pg_constraint and pg_trigger row creations that would be needed + * during ATTACH/DETACH for this kind of relationship. + */ + if (fk->confrelid == RelationGetRelid(partRel)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot attach table \"%s\" as a partition because it is referenced by foreign key \"%s\"", + RelationGetRelationName(partRel), + get_constraint_name(fk->conoid)))); + clone = lappend_oid(clone, fk->conoid); } @@ -10810,12 +11490,11 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) Constraint *fkconstraint; bool attached; Oid indexOid; - Oid constrOid; - ObjectAddress address, - referenced; + ObjectAddress address; ListCell *lc; - Oid insertTriggerOid, - updateTriggerOid; + Oid insertTriggerOid = InvalidOid, + updateTriggerOid = InvalidOid; + bool with_period; tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(parentConstrOid)); if (!HeapTupleIsValid(tuple)) @@ -10846,17 +11525,18 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) mapped_conkey[i] = attmap->attnums[conkey[i] - 1]; /* - * Get the "check" triggers belonging to the constraint to pass as - * parent OIDs for similar triggers that will be created on the - * partition in addFkRecurseReferencing(). They are also passed to - * tryAttachPartitionForeignKey() below to simply assign as parents to - * the partition's existing "check" triggers, that is, if the - * corresponding constraints is deemed attachable to the parent - * constraint. + * Get the "check" triggers belonging to the constraint, if it is + * ENFORCED, to pass as parent OIDs for similar triggers that will be + * created on the partition in addFkRecurseReferencing(). They are + * also passed to tryAttachPartitionForeignKey() below to simply + * assign as parents to the partition's existing "check" triggers, + * that is, if the corresponding constraints is deemed attachable to + * the parent constraint. */ - GetForeignKeyCheckTriggers(trigrel, constrForm->oid, - constrForm->confrelid, constrForm->conrelid, - &insertTriggerOid, &updateTriggerOid); + if (constrForm->conenforced) + GetForeignKeyCheckTriggers(trigrel, constrForm->oid, + constrForm->confrelid, constrForm->conrelid, + &insertTriggerOid, &updateTriggerOid); /* * Before creating a new constraint, see whether any existing FKs are @@ -10870,8 +11550,9 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) { ForeignKeyCacheInfo *fk = lfirst_node(ForeignKeyCacheInfo, lc); - if (tryAttachPartitionForeignKey(fk, - RelationGetRelid(partRel), + if (tryAttachPartitionForeignKey(wqueue, + fk, + partRel, parentConstrOid, numfks, mapped_conkey, @@ -10908,8 +11589,9 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) fkconstraint->fk_del_set_cols = NIL; fkconstraint->old_conpfeqop = NIL; fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->is_enforced = constrForm->conenforced; fkconstraint->skip_validation = false; - fkconstraint->initially_valid = true; + fkconstraint->initially_valid = constrForm->convalidated; for (int i = 0; i < numfks; i++) { Form_pg_attribute att; @@ -10919,71 +11601,30 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) fkconstraint->fk_attrs = lappend(fkconstraint->fk_attrs, makeString(NameStr(att->attname))); } - if (ConstraintNameIsUsed(CONSTRAINT_RELATION, - RelationGetRelid(partRel), - NameStr(constrForm->conname))) - fkconstraint->conname = - ChooseConstraintName(RelationGetRelationName(partRel), - ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs), - "fkey", - RelationGetNamespace(partRel), NIL); - else - fkconstraint->conname = pstrdup(NameStr(constrForm->conname)); indexOid = constrForm->conindid; - constrOid = - CreateConstraintEntry(fkconstraint->conname, - constrForm->connamespace, - CONSTRAINT_FOREIGN, - fkconstraint->deferrable, - fkconstraint->initdeferred, - constrForm->convalidated, - parentConstrOid, - RelationGetRelid(partRel), - mapped_conkey, - numfks, - numfks, - InvalidOid, /* not a domain constraint */ - indexOid, - constrForm->confrelid, /* same foreign rel */ - confkey, - conpfeqop, - conppeqop, - conffeqop, - numfks, - fkconstraint->fk_upd_action, - fkconstraint->fk_del_action, - confdelsetcols, - numfkdelsetcols, - fkconstraint->fk_matchtype, - NULL, - NULL, - NULL, - false, /* islocal */ - 1, /* inhcount */ - false, /* conNoInherit */ - true); - - /* Set up partition dependencies for the new constraint */ - ObjectAddressSet(address, ConstraintRelationId, constrOid); - ObjectAddressSet(referenced, ConstraintRelationId, parentConstrOid); - recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_PRI); - ObjectAddressSet(referenced, RelationRelationId, - RelationGetRelid(partRel)); - recordDependencyOn(&address, &referenced, DEPENDENCY_PARTITION_SEC); + with_period = constrForm->conperiod; + + /* Create the pg_constraint entry at this level */ + address = addFkConstraint(addFkReferencingSide, + NameStr(constrForm->conname), fkconstraint, + partRel, pkrel, indexOid, parentConstrOid, + numfks, confkey, + mapped_conkey, conpfeqop, + conppeqop, conffeqop, + numfkdelsetcols, confdelsetcols, + false, with_period); /* Done with the cloned constraint's tuple */ ReleaseSysCache(tuple); - /* Make all this visible before recursing */ - CommandCounterIncrement(); - + /* Create the check triggers, and recurse to partitions, if any */ addFkRecurseReferencing(wqueue, fkconstraint, partRel, pkrel, indexOid, - constrOid, + address.objectId, numfks, confkey, mapped_conkey, @@ -10995,7 +11636,8 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) false, /* no old check exists */ AccessExclusiveLock, insertTriggerOid, - updateTriggerOid); + updateTriggerOid, + with_period); table_close(pkrel, NoLock); } @@ -11014,8 +11656,9 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) * return false. */ static bool -tryAttachPartitionForeignKey(ForeignKeyCacheInfo *fk, - Oid partRelid, +tryAttachPartitionForeignKey(List **wqueue, + ForeignKeyCacheInfo *fk, + Relation partition, Oid parentConstrOid, int numfks, AttrNumber *mapped_conkey, @@ -11029,11 +11672,6 @@ tryAttachPartitionForeignKey(ForeignKeyCacheInfo *fk, Form_pg_constraint parentConstr; HeapTuple partcontup; Form_pg_constraint partConstr; - ScanKeyData key; - SysScanDesc scan; - HeapTuple trigtup; - Oid insertTriggerOid, - updateTriggerOid; parentConstrTup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(parentConstrOid)); @@ -11061,18 +11699,29 @@ tryAttachPartitionForeignKey(ForeignKeyCacheInfo *fk, } } - /* - * Looks good so far; do some more extensive checks. Presumably the check - * for 'convalidated' could be dropped, since we don't really care about - * that, but let's be careful for now. - */ - partcontup = SearchSysCache1(CONSTROID, - ObjectIdGetDatum(fk->conoid)); + /* Looks good so far; perform more extensive checks. */ + partcontup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(fk->conoid)); if (!HeapTupleIsValid(partcontup)) elog(ERROR, "cache lookup failed for constraint %u", fk->conoid); partConstr = (Form_pg_constraint) GETSTRUCT(partcontup); + + /* + * An error should be raised if the constraint enforceability is + * different. Returning false without raising an error, as we do for other + * attributes, could lead to a duplicate constraint with the same + * enforceability as the parent. While this may be acceptable, it may not + * be ideal. Therefore, it's better to raise an error and allow the user + * to correct the enforceability before proceeding. + */ + if (partConstr->conenforced != parentConstr->conenforced) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("constraint \"%s\" enforceability conflicts with constraint \"%s\" on relation \"%s\"", + NameStr(parentConstr->conname), + NameStr(partConstr->conname), + RelationGetRelationName(partition)))); + if (OidIsValid(partConstr->conparentid) || - !partConstr->convalidated || partConstr->condeferrable != parentConstr->condeferrable || partConstr->condeferred != parentConstr->condeferred || partConstr->confupdtype != parentConstr->confupdtype || @@ -11084,77 +11733,304 @@ tryAttachPartitionForeignKey(ForeignKeyCacheInfo *fk, return false; } - ReleaseSysCache(partcontup); ReleaseSysCache(parentConstrTup); + ReleaseSysCache(partcontup); + + /* Looks good! Attach this constraint. */ + AttachPartitionForeignKey(wqueue, partition, fk->conoid, + parentConstrOid, parentInsTrigger, + parentUpdTrigger, trigrel); + + return true; +} + +/* + * AttachPartitionForeignKey + * + * The subroutine for tryAttachPartitionForeignKey performs the final tasks of + * attaching the constraint, removing redundant triggers and entries from + * pg_constraint, and setting the constraint's parent. + */ +static void +AttachPartitionForeignKey(List **wqueue, + Relation partition, + Oid partConstrOid, + Oid parentConstrOid, + Oid parentInsTrigger, + Oid parentUpdTrigger, + Relation trigrel) +{ + HeapTuple parentConstrTup; + Form_pg_constraint parentConstr; + HeapTuple partcontup; + Form_pg_constraint partConstr; + bool queueValidation; + Oid partConstrFrelid; + Oid partConstrRelid; + bool parentConstrIsEnforced; + + /* Fetch the parent constraint tuple */ + parentConstrTup = SearchSysCache1(CONSTROID, + ObjectIdGetDatum(parentConstrOid)); + if (!HeapTupleIsValid(parentConstrTup)) + elog(ERROR, "cache lookup failed for constraint %u", parentConstrOid); + parentConstr = (Form_pg_constraint) GETSTRUCT(parentConstrTup); + parentConstrIsEnforced = parentConstr->conenforced; + + /* Fetch the child constraint tuple */ + partcontup = SearchSysCache1(CONSTROID, + ObjectIdGetDatum(partConstrOid)); + if (!HeapTupleIsValid(partcontup)) + elog(ERROR, "cache lookup failed for constraint %u", partConstrOid); + partConstr = (Form_pg_constraint) GETSTRUCT(partcontup); + partConstrFrelid = partConstr->confrelid; + partConstrRelid = partConstr->conrelid; /* - * Looks good! Attach this constraint. The action triggers in the new - * partition become redundant -- the parent table already has equivalent - * ones, and those will be able to reach the partition. Remove the ones - * in the partition. We identify them because they have our constraint - * OID, as well as being on the referenced rel. + * If the referenced table is partitioned, then the partition we're + * attaching now has extra pg_constraint rows and action triggers that are + * no longer needed. Remove those. */ - ScanKeyInit(&key, - Anum_pg_trigger_tgconstraint, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(fk->conoid)); - scan = systable_beginscan(trigrel, TriggerConstraintIndexId, true, - NULL, 1, &key); - while ((trigtup = systable_getnext(scan)) != NULL) + if (get_rel_relkind(partConstrFrelid) == RELKIND_PARTITIONED_TABLE) { - Form_pg_trigger trgform = (Form_pg_trigger) GETSTRUCT(trigtup); - ObjectAddress trigger; + Relation pg_constraint = table_open(ConstraintRelationId, RowShareLock); - if (trgform->tgconstrrelid != fk->conrelid) - continue; - if (trgform->tgrelid != fk->confrelid) - continue; + RemoveInheritedConstraint(pg_constraint, trigrel, partConstrOid, + partConstrRelid); - /* - * The constraint is originally set up to contain this trigger as an - * implementation object, so there's a dependency record that links - * the two; however, since the trigger is no longer needed, we remove - * the dependency link in order to be able to drop the trigger while - * keeping the constraint intact. - */ - deleteDependencyRecordsFor(TriggerRelationId, - trgform->oid, - false); - /* make dependency deletion visible to performDeletion */ - CommandCounterIncrement(); - ObjectAddressSet(trigger, TriggerRelationId, - trgform->oid); - performDeletion(&trigger, DROP_RESTRICT, 0); - /* make trigger drop visible, in case the loop iterates */ - CommandCounterIncrement(); + table_close(pg_constraint, RowShareLock); } - systable_endscan(scan); + /* + * Will we need to validate this constraint? A valid parent constraint + * implies that all child constraints have been validated, so if this one + * isn't, we must trigger phase 3 validation. + */ + queueValidation = parentConstr->convalidated && !partConstr->convalidated; + + ReleaseSysCache(partcontup); + ReleaseSysCache(parentConstrTup); + + /* + * The action triggers in the new partition become redundant -- the parent + * table already has equivalent ones, and those will be able to reach the + * partition. Remove the ones in the partition. We identify them because + * they have our constraint OID, as well as being on the referenced rel. + */ + DropForeignKeyConstraintTriggers(trigrel, partConstrOid, partConstrFrelid, + partConstrRelid); - ConstraintSetParentConstraint(fk->conoid, parentConstrOid, partRelid); + ConstraintSetParentConstraint(partConstrOid, parentConstrOid, + RelationGetRelid(partition)); /* * Like the constraint, attach partition's "check" triggers to the - * corresponding parent triggers. - */ - GetForeignKeyCheckTriggers(trigrel, - fk->conoid, fk->confrelid, fk->conrelid, - &insertTriggerOid, &updateTriggerOid); - Assert(OidIsValid(insertTriggerOid) && OidIsValid(parentInsTrigger)); - TriggerSetParentTrigger(trigrel, insertTriggerOid, parentInsTrigger, - partRelid); - Assert(OidIsValid(updateTriggerOid) && OidIsValid(parentUpdTrigger)); - TriggerSetParentTrigger(trigrel, updateTriggerOid, parentUpdTrigger, - partRelid); + * corresponding parent triggers if the constraint is ENFORCED. NOT + * ENFORCED constraints do not have these triggers. + */ + if (parentConstrIsEnforced) + { + Oid insertTriggerOid, + updateTriggerOid; + + GetForeignKeyCheckTriggers(trigrel, + partConstrOid, partConstrFrelid, partConstrRelid, + &insertTriggerOid, &updateTriggerOid); + Assert(OidIsValid(insertTriggerOid) && OidIsValid(parentInsTrigger)); + TriggerSetParentTrigger(trigrel, insertTriggerOid, parentInsTrigger, + RelationGetRelid(partition)); + Assert(OidIsValid(updateTriggerOid) && OidIsValid(parentUpdTrigger)); + TriggerSetParentTrigger(trigrel, updateTriggerOid, parentUpdTrigger, + RelationGetRelid(partition)); + } + /* + * We updated this pg_constraint row above to set its parent; validating + * it will cause its convalidated flag to change, so we need CCI here. In + * addition, we need it unconditionally for the rare case where the parent + * table has *two* identical constraints; when reaching this function for + * the second one, we must have made our changes visible, otherwise we + * would try to attach both to this one. + */ CommandCounterIncrement(); - return true; + + /* If validation is needed, put it in the queue now. */ + if (queueValidation) + { + Relation conrel; + Oid confrelid; + + conrel = table_open(ConstraintRelationId, RowExclusiveLock); + + partcontup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(partConstrOid)); + if (!HeapTupleIsValid(partcontup)) + elog(ERROR, "cache lookup failed for constraint %u", partConstrOid); + + confrelid = ((Form_pg_constraint) GETSTRUCT(partcontup))->confrelid; + + /* Use the same lock as for AT_ValidateConstraint */ + QueueFKConstraintValidation(wqueue, conrel, partition, confrelid, + partcontup, ShareUpdateExclusiveLock); + ReleaseSysCache(partcontup); + table_close(conrel, RowExclusiveLock); + } } /* - * GetForeignKeyActionTriggers - * Returns delete and update "action" triggers of the given relation - * belonging to the given constraint + * RemoveInheritedConstraint + * + * Removes the constraint and its associated trigger from the specified + * relation, which inherited the given constraint. + */ +static void +RemoveInheritedConstraint(Relation conrel, Relation trigrel, Oid conoid, + Oid conrelid) +{ + ObjectAddresses *objs; + HeapTuple consttup; + ScanKeyData key; + SysScanDesc scan; + HeapTuple trigtup; + + ScanKeyInit(&key, + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conrelid)); + + scan = systable_beginscan(conrel, + ConstraintRelidTypidNameIndexId, + true, NULL, 1, &key); + objs = new_object_addresses(); + while ((consttup = systable_getnext(scan)) != NULL) + { + Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(consttup); + + if (conform->conparentid != conoid) + continue; + else + { + ObjectAddress addr; + SysScanDesc scan2; + ScanKeyData key2; + int n PG_USED_FOR_ASSERTS_ONLY; + + ObjectAddressSet(addr, ConstraintRelationId, conform->oid); + add_exact_object_address(&addr, objs); + + /* + * First we must delete the dependency record that binds the + * constraint records together. + */ + n = deleteDependencyRecordsForSpecific(ConstraintRelationId, + conform->oid, + DEPENDENCY_INTERNAL, + ConstraintRelationId, + conoid); + Assert(n == 1); /* actually only one is expected */ + + /* + * Now search for the triggers for this constraint and set them up + * for deletion too + */ + ScanKeyInit(&key2, + Anum_pg_trigger_tgconstraint, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conform->oid)); + scan2 = systable_beginscan(trigrel, TriggerConstraintIndexId, + true, NULL, 1, &key2); + while ((trigtup = systable_getnext(scan2)) != NULL) + { + ObjectAddressSet(addr, TriggerRelationId, + ((Form_pg_trigger) GETSTRUCT(trigtup))->oid); + add_exact_object_address(&addr, objs); + } + systable_endscan(scan2); + } + } + /* make the dependency deletions visible */ + CommandCounterIncrement(); + performMultipleDeletions(objs, DROP_RESTRICT, + PERFORM_DELETION_INTERNAL); + systable_endscan(scan); +} + +/* + * DropForeignKeyConstraintTriggers + * + * The subroutine for tryAttachPartitionForeignKey handles the deletion of + * action triggers for the foreign key constraint. + * + * If valid confrelid and conrelid values are not provided, the respective + * trigger check will be skipped, and the trigger will be considered for + * removal. + */ +static void +DropForeignKeyConstraintTriggers(Relation trigrel, Oid conoid, Oid confrelid, + Oid conrelid) +{ + ScanKeyData key; + SysScanDesc scan; + HeapTuple trigtup; + + ScanKeyInit(&key, + Anum_pg_trigger_tgconstraint, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conoid)); + scan = systable_beginscan(trigrel, TriggerConstraintIndexId, true, + NULL, 1, &key); + while ((trigtup = systable_getnext(scan)) != NULL) + { + Form_pg_trigger trgform = (Form_pg_trigger) GETSTRUCT(trigtup); + ObjectAddress trigger; + + /* Invalid if trigger is not for a referential integrity constraint */ + if (!OidIsValid(trgform->tgconstrrelid)) + continue; + if (OidIsValid(conrelid) && trgform->tgconstrrelid != conrelid) + continue; + if (OidIsValid(confrelid) && trgform->tgrelid != confrelid) + continue; + + /* We should be dropping trigger related to foreign key constraint */ + Assert(trgform->tgfoid == F_RI_FKEY_CHECK_INS || + trgform->tgfoid == F_RI_FKEY_CHECK_UPD || + trgform->tgfoid == F_RI_FKEY_CASCADE_DEL || + trgform->tgfoid == F_RI_FKEY_CASCADE_UPD || + trgform->tgfoid == F_RI_FKEY_RESTRICT_DEL || + trgform->tgfoid == F_RI_FKEY_RESTRICT_UPD || + trgform->tgfoid == F_RI_FKEY_SETNULL_DEL || + trgform->tgfoid == F_RI_FKEY_SETNULL_UPD || + trgform->tgfoid == F_RI_FKEY_SETDEFAULT_DEL || + trgform->tgfoid == F_RI_FKEY_SETDEFAULT_UPD || + trgform->tgfoid == F_RI_FKEY_NOACTION_DEL || + trgform->tgfoid == F_RI_FKEY_NOACTION_UPD); + + /* + * The constraint is originally set up to contain this trigger as an + * implementation object, so there's a dependency record that links + * the two; however, since the trigger is no longer needed, we remove + * the dependency link in order to be able to drop the trigger while + * keeping the constraint intact. + */ + deleteDependencyRecordsFor(TriggerRelationId, + trgform->oid, + false); + /* make dependency deletion visible to performDeletion */ + CommandCounterIncrement(); + ObjectAddressSet(trigger, TriggerRelationId, + trgform->oid); + performDeletion(&trigger, DROP_RESTRICT, 0); + /* make trigger drop visible, in case the loop iterates */ + CommandCounterIncrement(); + } + + systable_endscan(scan); +} + +/* + * GetForeignKeyActionTriggers + * Returns delete and update "action" triggers of the given relation + * belonging to the given constraint */ static void GetForeignKeyActionTriggers(Relation trigrel, @@ -11278,16 +12154,15 @@ GetForeignKeyCheckTriggers(Relation trigrel, * * Update the attributes of a constraint. * - * Currently only works for Foreign Key constraints. + * Currently only works for Foreign Key and not null constraints. * * If the constraint is modified, returns its address; otherwise, return * InvalidObjectAddress. */ static ObjectAddress -ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, - bool recursing, LOCKMODE lockmode) +ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon, + bool recurse, LOCKMODE lockmode) { - Constraint *cmdcon; Relation conrel; Relation tgrel; SysScanDesc scan; @@ -11295,10 +12170,17 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, HeapTuple contuple; Form_pg_constraint currcon; ObjectAddress address; - List *otherrelids = NIL; - ListCell *lc; - cmdcon = castNode(Constraint, cmd->def); + /* + * Disallow altering ONLY a partitioned table, as it would make no sense. + * This is okay for legacy inheritance. + */ + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be altered in child tables too"), + errhint("Do not specify the ONLY keyword.")); + conrel = table_open(ConstraintRelationId, RowExclusiveLock); tgrel = table_open(TriggerRelationId, RowExclusiveLock); @@ -11329,11 +12211,31 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, cmdcon->conname, RelationGetRelationName(rel)))); currcon = (Form_pg_constraint) GETSTRUCT(contuple); - if (currcon->contype != CONSTRAINT_FOREIGN) + if (cmdcon->alterDeferrability && currcon->contype != CONSTRAINT_FOREIGN) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key constraint", cmdcon->conname, RelationGetRelationName(rel)))); + if (cmdcon->alterEnforceability && currcon->contype != CONSTRAINT_FOREIGN) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot alter enforceability of constraint \"%s\" of relation \"%s\"", + cmdcon->conname, RelationGetRelationName(rel)))); + if (cmdcon->alterInheritability && + currcon->contype != CONSTRAINT_NOTNULL) + ereport(ERROR, + errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("constraint \"%s\" of relation \"%s\" is not a not-null constraint", + cmdcon->conname, RelationGetRelationName(rel))); + + /* Refuse to modify inheritability of inherited constraints */ + if (cmdcon->alterInheritability && + cmdcon->noinherit && currcon->coninhcount > 0) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot alter inherited constraint \"%s\" on relation \"%s\"", + NameStr(currcon->conname), + RelationGetRelationName(rel))); /* * If it's not the topmost constraint, raise an error. @@ -11379,28 +12281,14 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, errhint("You may alter the constraint it derives from instead."))); } - /* - * Do the actual catalog work. We can skip changing if already in the - * desired state, but not if a partitioned table: partitions need to be - * processed regardless, in case they had the constraint locally changed. - */ address = InvalidObjectAddress; - if (currcon->condeferrable != cmdcon->deferrable || - currcon->condeferred != cmdcon->initdeferred || - rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - { - if (ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, rel, contuple, - &otherrelids, lockmode)) - ObjectAddressSet(address, ConstraintRelationId, currcon->oid); - } /* - * ATExecAlterConstrRecurse already invalidated relcache for the relations - * having the constraint itself; here we also invalidate for relations - * that have any triggers that are part of the constraint. + * Do the actual catalog work, and recurse if necessary. */ - foreach(lc, otherrelids) - CacheInvalidateRelcacheByRelid(lfirst_oid(lc)); + if (ATExecAlterConstraintInternal(wqueue, cmdcon, conrel, tgrel, rel, + contuple, recurse, lockmode)) + ObjectAddressSet(address, ConstraintRelationId, currcon->oid); systable_endscan(scan); @@ -11411,8 +12299,218 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, } /* - * Recursive subroutine of ATExecAlterConstraint. Returns true if the - * constraint is altered. + * A subroutine of ATExecAlterConstraint that calls the respective routines for + * altering constraint's enforceability, deferrability or inheritability. + */ +static bool +ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, Relation rel, + HeapTuple contuple, bool recurse, + LOCKMODE lockmode) +{ + Form_pg_constraint currcon; + bool changed = false; + List *otherrelids = NIL; + + currcon = (Form_pg_constraint) GETSTRUCT(contuple); + + /* + * Do the catalog work for the enforceability or deferrability change, + * recurse if necessary. + * + * Note that even if deferrability is requested to be altered along with + * enforceability, we don't need to explicitly update multiple entries in + * pg_trigger related to deferrability. + * + * Modifying enforceability involves either creating or dropping the + * trigger, during which the deferrability setting will be adjusted + * automatically. + */ + if (cmdcon->alterEnforceability && + ATExecAlterConstrEnforceability(wqueue, cmdcon, conrel, tgrel, + currcon->conrelid, currcon->confrelid, + contuple, lockmode, InvalidOid, + InvalidOid, InvalidOid, InvalidOid)) + changed = true; + + else if (cmdcon->alterDeferrability && + ATExecAlterConstrDeferrability(wqueue, cmdcon, conrel, tgrel, rel, + contuple, recurse, &otherrelids, + lockmode)) + { + /* + * AlterConstrUpdateConstraintEntry already invalidated relcache for + * the relations having the constraint itself; here we also invalidate + * for relations that have any triggers that are part of the + * constraint. + */ + foreach_oid(relid, otherrelids) + CacheInvalidateRelcacheByRelid(relid); + + changed = true; + } + + /* + * Do the catalog work for the inheritability change. + */ + if (cmdcon->alterInheritability && + ATExecAlterConstrInheritability(wqueue, cmdcon, conrel, rel, contuple, + lockmode)) + changed = true; + + return changed; +} + +/* + * Returns true if the constraint's enforceability is altered. + * + * Depending on whether the constraint is being set to ENFORCED or NOT + * ENFORCED, it creates or drops the trigger accordingly. + * + * Note that we must recurse even when trying to change a constraint to not + * enforced if it is already not enforced, in case descendant constraints + * might be enforced and need to be changed to not enforced. Conversely, we + * should do nothing if a constraint is being set to enforced and is already + * enforced, as descendant constraints cannot be different in that case. + */ +static bool +ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, + Oid fkrelid, Oid pkrelid, + HeapTuple contuple, LOCKMODE lockmode, + Oid ReferencedParentDelTrigger, + Oid ReferencedParentUpdTrigger, + Oid ReferencingParentInsTrigger, + Oid ReferencingParentUpdTrigger) +{ + Form_pg_constraint currcon; + Oid conoid; + Relation rel; + bool changed = false; + + /* Since this function recurses, it could be driven to stack overflow */ + check_stack_depth(); + + Assert(cmdcon->alterEnforceability); + + currcon = (Form_pg_constraint) GETSTRUCT(contuple); + conoid = currcon->oid; + + /* Should be foreign key constraint */ + Assert(currcon->contype == CONSTRAINT_FOREIGN); + + rel = table_open(currcon->conrelid, lockmode); + + if (currcon->conenforced != cmdcon->is_enforced) + { + AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple); + changed = true; + } + + /* Drop triggers */ + if (!cmdcon->is_enforced) + { + /* + * When setting a constraint to NOT ENFORCED, the constraint triggers + * need to be dropped. Therefore, we must process the child relations + * first, followed by the parent, to account for dependencies. + */ + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + get_rel_relkind(currcon->confrelid) == RELKIND_PARTITIONED_TABLE) + AlterConstrEnforceabilityRecurse(wqueue, cmdcon, conrel, tgrel, + fkrelid, pkrelid, contuple, + lockmode, InvalidOid, InvalidOid, + InvalidOid, InvalidOid); + + /* Drop all the triggers */ + DropForeignKeyConstraintTriggers(tgrel, conoid, InvalidOid, InvalidOid); + } + else if (changed) /* Create triggers */ + { + Oid ReferencedDelTriggerOid = InvalidOid, + ReferencedUpdTriggerOid = InvalidOid, + ReferencingInsTriggerOid = InvalidOid, + ReferencingUpdTriggerOid = InvalidOid; + + /* Prepare the minimal information required for trigger creation. */ + Constraint *fkconstraint = makeNode(Constraint); + + fkconstraint->conname = pstrdup(NameStr(currcon->conname)); + fkconstraint->fk_matchtype = currcon->confmatchtype; + fkconstraint->fk_upd_action = currcon->confupdtype; + fkconstraint->fk_del_action = currcon->confdeltype; + + /* Create referenced triggers */ + if (currcon->conrelid == fkrelid) + createForeignKeyActionTriggers(currcon->conrelid, + currcon->confrelid, + fkconstraint, + conoid, + currcon->conindid, + ReferencedParentDelTrigger, + ReferencedParentUpdTrigger, + &ReferencedDelTriggerOid, + &ReferencedUpdTriggerOid); + + /* Create referencing triggers */ + if (currcon->confrelid == pkrelid) + createForeignKeyCheckTriggers(currcon->conrelid, + pkrelid, + fkconstraint, + conoid, + currcon->conindid, + ReferencingParentInsTrigger, + ReferencingParentUpdTrigger, + &ReferencingInsTriggerOid, + &ReferencingUpdTriggerOid); + + /* + * Tell Phase 3 to check that the constraint is satisfied by existing + * rows. Only applies to leaf partitions, and (for constraints that + * reference a partitioned table) only if this is not one of the + * pg_constraint rows that exist solely to support action triggers. + */ + if (rel->rd_rel->relkind == RELKIND_RELATION && + currcon->confrelid == pkrelid) + { + AlteredTableInfo *tab; + NewConstraint *newcon; + + newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); + newcon->name = fkconstraint->conname; + newcon->contype = CONSTR_FOREIGN; + newcon->refrelid = currcon->confrelid; + newcon->refindid = currcon->conindid; + newcon->conid = currcon->oid; + newcon->qual = (Node *) fkconstraint; + + /* Find or create work queue entry for this table */ + tab = ATGetQueueEntry(wqueue, rel); + tab->constraints = lappend(tab->constraints, newcon); + } + + /* + * If the table at either end of the constraint is partitioned, we + * need to recurse and create triggers for each constraint that is a + * child of this one. + */ + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + get_rel_relkind(currcon->confrelid) == RELKIND_PARTITIONED_TABLE) + AlterConstrEnforceabilityRecurse(wqueue, cmdcon, conrel, tgrel, + fkrelid, pkrelid, contuple, + lockmode, ReferencedDelTriggerOid, + ReferencedUpdTriggerOid, + ReferencingInsTriggerOid, + ReferencingUpdTriggerOid); + } + + table_close(rel, NoLock); + + return changed; +} + +/* + * Returns true if the constraint's deferrability is altered. * * *otherrelids is appended OIDs of relations containing affected triggers. * @@ -11422,152 +12520,351 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd, bool recurse, * but existing releases don't do that.) */ static bool -ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel, - Relation rel, HeapTuple contuple, List **otherrelids, - LOCKMODE lockmode) +ATExecAlterConstrDeferrability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, Relation rel, + HeapTuple contuple, bool recurse, + List **otherrelids, LOCKMODE lockmode) { Form_pg_constraint currcon; - Oid conoid; Oid refrelid; bool changed = false; /* since this function recurses, it could be driven to stack overflow */ check_stack_depth(); + Assert(cmdcon->alterDeferrability); + currcon = (Form_pg_constraint) GETSTRUCT(contuple); - conoid = currcon->oid; refrelid = currcon->confrelid; + /* Should be foreign key constraint */ + Assert(currcon->contype == CONSTRAINT_FOREIGN); + /* - * Update pg_constraint with the flags from cmdcon. - * * If called to modify a constraint that's already in the desired state, * silently do nothing. */ if (currcon->condeferrable != cmdcon->deferrable || currcon->condeferred != cmdcon->initdeferred) { - HeapTuple copyTuple; - Form_pg_constraint copy_con; - HeapTuple tgtuple; - ScanKeyData tgkey; - SysScanDesc tgscan; - - copyTuple = heap_copytuple(contuple); - copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->condeferrable = cmdcon->deferrable; - copy_con->condeferred = cmdcon->initdeferred; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); - - InvokeObjectPostAlterHook(ConstraintRelationId, - conoid, 0); - - heap_freetuple(copyTuple); + AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple); changed = true; - /* Make new constraint flags visible to others */ - CacheInvalidateRelcache(rel); - /* * Now we need to update the multiple entries in pg_trigger that * implement the constraint. */ - ScanKeyInit(&tgkey, - Anum_pg_trigger_tgconstraint, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(conoid)); - tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true, - NULL, 1, &tgkey); - while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan))) - { - Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple); - Form_pg_trigger copy_tg; - HeapTuple tgCopyTuple; - - /* - * Remember OIDs of other relation(s) involved in FK constraint. - * (Note: it's likely that we could skip forcing a relcache inval - * for other rels that don't have a trigger whose properties - * change, but let's be conservative.) - */ - if (tgform->tgrelid != RelationGetRelid(rel)) - *otherrelids = list_append_unique_oid(*otherrelids, - tgform->tgrelid); + AlterConstrTriggerDeferrability(currcon->oid, tgrel, rel, + cmdcon->deferrable, + cmdcon->initdeferred, otherrelids); + } - /* - * Update deferrability of RI_FKey_noaction_del, - * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd - * triggers, but not others; see createForeignKeyActionTriggers - * and CreateFKCheckTrigger. - */ - if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL && - tgform->tgfoid != F_RI_FKEY_NOACTION_UPD && - tgform->tgfoid != F_RI_FKEY_CHECK_INS && - tgform->tgfoid != F_RI_FKEY_CHECK_UPD) - continue; + /* + * If the table at either end of the constraint is partitioned, we need to + * handle every constraint that is a child of this one. + */ + if (recurse && changed && + (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)) + AlterConstrDeferrabilityRecurse(wqueue, cmdcon, conrel, tgrel, rel, + contuple, recurse, otherrelids, + lockmode); - tgCopyTuple = heap_copytuple(tgtuple); - copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple); + return changed; +} - copy_tg->tgdeferrable = cmdcon->deferrable; - copy_tg->tginitdeferred = cmdcon->initdeferred; - CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple); +/* + * Returns true if the constraint's inheritability is altered. + */ +static bool +ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation rel, + HeapTuple contuple, LOCKMODE lockmode) +{ + Form_pg_constraint currcon; + AttrNumber colNum; + char *colName; + List *children; - InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); + Assert(cmdcon->alterInheritability); - heap_freetuple(tgCopyTuple); - } + currcon = (Form_pg_constraint) GETSTRUCT(contuple); - systable_endscan(tgscan); - } + /* The current implementation only works for NOT NULL constraints */ + Assert(currcon->contype == CONSTRAINT_NOTNULL); /* - * If the table at either end of the constraint is partitioned, we need to - * recurse and handle every constraint that is a child of this one. - * - * (This assumes that the recurse flag is forcibly set for partitioned - * tables, and not set for legacy inheritance, though we don't check for - * that here.) + * If called to modify a constraint that's already in the desired state, + * silently do nothing. */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || - get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE) - { - ScanKeyData pkey; - SysScanDesc pscan; - HeapTuple childtup; + if (cmdcon->noinherit == currcon->connoinherit) + return false; - ScanKeyInit(&pkey, - Anum_pg_constraint_conparentid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(conoid)); + AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple); + CommandCounterIncrement(); - pscan = systable_beginscan(conrel, ConstraintParentIndexId, - true, NULL, 1, &pkey); + /* Fetch the column number and name */ + colNum = extractNotNullColumn(contuple); + colName = get_attname(currcon->conrelid, colNum, false); - while (HeapTupleIsValid(childtup = systable_getnext(pscan))) + /* + * Propagate the change to children. For this subcommand type we don't + * recursively affect children, just the immediate level. + */ + children = find_inheritance_children(RelationGetRelid(rel), + lockmode); + foreach_oid(childoid, children) + { + ObjectAddress addr; + + if (cmdcon->noinherit) { - Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup); - Relation childrel; + HeapTuple childtup; + Form_pg_constraint childcon; + + childtup = findNotNullConstraint(childoid, colName); + if (!childtup) + elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u", + colName, childoid); + childcon = (Form_pg_constraint) GETSTRUCT(childtup); + Assert(childcon->coninhcount > 0); + childcon->coninhcount--; + childcon->conislocal = true; + CatalogTupleUpdate(conrel, &childtup->t_self, childtup); + heap_freetuple(childtup); + } + else + { + Relation childrel = table_open(childoid, NoLock); - childrel = table_open(childcon->conrelid, lockmode); - ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup, - otherrelids, lockmode); + addr = ATExecSetNotNull(wqueue, childrel, NameStr(currcon->conname), + colName, true, true, lockmode); + if (OidIsValid(addr.objectId)) + CommandCounterIncrement(); table_close(childrel, NoLock); } - - systable_endscan(pscan); } - return changed; + return true; } /* - * ALTER TABLE VALIDATE CONSTRAINT + * A subroutine of ATExecAlterConstrDeferrability that updated constraint + * trigger's deferrability. * - * XXX The reason we handle recursion here rather than at Phase 1 is because - * there's no good way to skip recursing when handling foreign keys: there is - * no need to lock children in that case, yet we wouldn't be able to avoid - * doing so at that level. + * The arguments to this function have the same meaning as the arguments to + * ATExecAlterConstrDeferrability. + */ +static void +AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, + bool deferrable, bool initdeferred, + List **otherrelids) +{ + HeapTuple tgtuple; + ScanKeyData tgkey; + SysScanDesc tgscan; + + ScanKeyInit(&tgkey, + Anum_pg_trigger_tgconstraint, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conoid)); + tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true, + NULL, 1, &tgkey); + while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan))) + { + Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple); + Form_pg_trigger copy_tg; + HeapTuple tgCopyTuple; + + /* + * Remember OIDs of other relation(s) involved in FK constraint. + * (Note: it's likely that we could skip forcing a relcache inval for + * other rels that don't have a trigger whose properties change, but + * let's be conservative.) + */ + if (tgform->tgrelid != RelationGetRelid(rel)) + *otherrelids = list_append_unique_oid(*otherrelids, + tgform->tgrelid); + + /* + * Update enable status and deferrability of RI_FKey_noaction_del, + * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd + * triggers, but not others; see createForeignKeyActionTriggers and + * CreateFKCheckTrigger. + */ + if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL && + tgform->tgfoid != F_RI_FKEY_NOACTION_UPD && + tgform->tgfoid != F_RI_FKEY_CHECK_INS && + tgform->tgfoid != F_RI_FKEY_CHECK_UPD) + continue; + + tgCopyTuple = heap_copytuple(tgtuple); + copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple); + + copy_tg->tgdeferrable = deferrable; + copy_tg->tginitdeferred = initdeferred; + CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple); + + InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); + + heap_freetuple(tgCopyTuple); + } + + systable_endscan(tgscan); +} + +/* + * Invokes ATExecAlterConstrEnforceability for each constraint that is a child of + * the specified constraint. + * + * Note that this doesn't handle recursion the normal way, viz. by scanning the + * list of child relations and recursing; instead it uses the conparentid + * relationships. This may need to be reconsidered. + * + * The arguments to this function have the same meaning as the arguments to + * ATExecAlterConstrEnforceability. + */ +static void +AlterConstrEnforceabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, + Oid fkrelid, Oid pkrelid, + HeapTuple contuple, LOCKMODE lockmode, + Oid ReferencedParentDelTrigger, + Oid ReferencedParentUpdTrigger, + Oid ReferencingParentInsTrigger, + Oid ReferencingParentUpdTrigger) +{ + Form_pg_constraint currcon; + Oid conoid; + ScanKeyData pkey; + SysScanDesc pscan; + HeapTuple childtup; + + currcon = (Form_pg_constraint) GETSTRUCT(contuple); + conoid = currcon->oid; + + ScanKeyInit(&pkey, + Anum_pg_constraint_conparentid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conoid)); + + pscan = systable_beginscan(conrel, ConstraintParentIndexId, + true, NULL, 1, &pkey); + + while (HeapTupleIsValid(childtup = systable_getnext(pscan))) + ATExecAlterConstrEnforceability(wqueue, cmdcon, conrel, tgrel, fkrelid, + pkrelid, childtup, lockmode, + ReferencedParentDelTrigger, + ReferencedParentUpdTrigger, + ReferencingParentInsTrigger, + ReferencingParentUpdTrigger); + + systable_endscan(pscan); +} + +/* + * Invokes ATExecAlterConstrDeferrability for each constraint that is a child of + * the specified constraint. + * + * Note that this doesn't handle recursion the normal way, viz. by scanning the + * list of child relations and recursing; instead it uses the conparentid + * relationships. This may need to be reconsidered. + * + * The arguments to this function have the same meaning as the arguments to + * ATExecAlterConstrDeferrability. + */ +static void +AlterConstrDeferrabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon, + Relation conrel, Relation tgrel, Relation rel, + HeapTuple contuple, bool recurse, + List **otherrelids, LOCKMODE lockmode) +{ + Form_pg_constraint currcon; + Oid conoid; + ScanKeyData pkey; + SysScanDesc pscan; + HeapTuple childtup; + + currcon = (Form_pg_constraint) GETSTRUCT(contuple); + conoid = currcon->oid; + + ScanKeyInit(&pkey, + Anum_pg_constraint_conparentid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conoid)); + + pscan = systable_beginscan(conrel, ConstraintParentIndexId, + true, NULL, 1, &pkey); + + while (HeapTupleIsValid(childtup = systable_getnext(pscan))) + { + Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup); + Relation childrel; + + childrel = table_open(childcon->conrelid, lockmode); + + ATExecAlterConstrDeferrability(wqueue, cmdcon, conrel, tgrel, childrel, + childtup, recurse, otherrelids, lockmode); + table_close(childrel, NoLock); + } + + systable_endscan(pscan); +} + +/* + * Update the constraint entry for the given ATAlterConstraint command, and + * invoke the appropriate hooks. + */ +static void +AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, + HeapTuple contuple) +{ + HeapTuple copyTuple; + Form_pg_constraint copy_con; + + Assert(cmdcon->alterEnforceability || cmdcon->alterDeferrability || + cmdcon->alterInheritability); + + copyTuple = heap_copytuple(contuple); + copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); + + if (cmdcon->alterEnforceability) + { + copy_con->conenforced = cmdcon->is_enforced; + + /* + * NB: The convalidated status is irrelevant when the constraint is + * set to NOT ENFORCED, but for consistency, it should still be set + * appropriately. Similarly, if the constraint is later changed to + * ENFORCED, validation will be performed during phase 3, so it makes + * sense to mark it as valid in that case. + */ + copy_con->convalidated = cmdcon->is_enforced; + } + if (cmdcon->alterDeferrability) + { + copy_con->condeferrable = cmdcon->deferrable; + copy_con->condeferred = cmdcon->initdeferred; + } + if (cmdcon->alterInheritability) + copy_con->connoinherit = cmdcon->noinherit; + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + InvokeObjectPostAlterHook(ConstraintRelationId, copy_con->oid, 0); + + /* Make new constraint flags visible to others */ + CacheInvalidateRelcacheByRelid(copy_con->conrelid); + + heap_freetuple(copyTuple); +} + +/* + * ALTER TABLE VALIDATE CONSTRAINT + * + * XXX The reason we handle recursion here rather than at Phase 1 is because + * there's no good way to skip recursing when handling foreign keys: there is + * no need to lock children in that case, yet we wouldn't be able to avoid + * doing so at that level. * * Return value is the address of the validated constraint. If the constraint * was already validated, InvalidObjectAddress is returned. @@ -11612,161 +12909,390 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName, con = (Form_pg_constraint) GETSTRUCT(tuple); if (con->contype != CONSTRAINT_FOREIGN && - con->contype != CONSTRAINT_CHECK) + con->contype != CONSTRAINT_CHECK && + con->contype != CONSTRAINT_NOTNULL) ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint", - constrName, RelationGetRelationName(rel)))); + errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key, check, or not-null constraint", + constrName, RelationGetRelationName(rel))); + + if (!con->conenforced) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot validate NOT ENFORCED constraint"))); if (!con->convalidated) { - AlteredTableInfo *tab; - HeapTuple copyTuple; - Form_pg_constraint copy_con; - if (con->contype == CONSTRAINT_FOREIGN) { - NewConstraint *newcon; - Constraint *fkconstraint; + QueueFKConstraintValidation(wqueue, conrel, rel, con->confrelid, + tuple, lockmode); + } + else if (con->contype == CONSTRAINT_CHECK) + { + QueueCheckConstraintValidation(wqueue, conrel, rel, constrName, + tuple, recurse, recursing, lockmode); + } + else if (con->contype == CONSTRAINT_NOTNULL) + { + QueueNNConstraintValidation(wqueue, conrel, rel, + tuple, recurse, recursing, lockmode); + } - /* Queue validation for phase 3 */ - fkconstraint = makeNode(Constraint); - /* for now this is all we need */ - fkconstraint->conname = constrName; + ObjectAddressSet(address, ConstraintRelationId, con->oid); + } + else + address = InvalidObjectAddress; /* already validated */ - newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); - newcon->name = constrName; - newcon->contype = CONSTR_FOREIGN; - newcon->refrelid = con->confrelid; - newcon->refindid = con->conindid; - newcon->conid = con->oid; - newcon->qual = (Node *) fkconstraint; + systable_endscan(scan); - /* Find or create work queue entry for this table */ - tab = ATGetQueueEntry(wqueue, rel); - tab->constraints = lappend(tab->constraints, newcon); + table_close(conrel, RowExclusiveLock); - /* - * We disallow creating invalid foreign keys to or from - * partitioned tables, so ignoring the recursion bit is okay. - */ - } - else if (con->contype == CONSTRAINT_CHECK) + return address; +} + +/* + * QueueFKConstraintValidation + * + * Add an entry to the wqueue to validate the given foreign key constraint in + * Phase 3 and update the convalidated field in the pg_constraint catalog + * for the specified relation and all its children. + */ +static void +QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, + Oid pkrelid, HeapTuple contuple, LOCKMODE lockmode) +{ + Form_pg_constraint con; + AlteredTableInfo *tab; + HeapTuple copyTuple; + Form_pg_constraint copy_con; + + con = (Form_pg_constraint) GETSTRUCT(contuple); + Assert(con->contype == CONSTRAINT_FOREIGN); + Assert(!con->convalidated); + + /* + * Add the validation to phase 3's queue; not needed for partitioned + * tables themselves, only for their partitions. + * + * When the referenced table (pkrelid) is partitioned, the referencing + * table (fkrel) has one pg_constraint row pointing to each partition + * thereof. These rows are there only to support action triggers and no + * table scan is needed, therefore skip this for them as well. + */ + if (fkrel->rd_rel->relkind == RELKIND_RELATION && + con->confrelid == pkrelid) + { + NewConstraint *newcon; + Constraint *fkconstraint; + + /* Queue validation for phase 3 */ + fkconstraint = makeNode(Constraint); + /* for now this is all we need */ + fkconstraint->conname = pstrdup(NameStr(con->conname)); + + newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); + newcon->name = fkconstraint->conname; + newcon->contype = CONSTR_FOREIGN; + newcon->refrelid = con->confrelid; + newcon->refindid = con->conindid; + newcon->conid = con->oid; + newcon->qual = (Node *) fkconstraint; + + /* Find or create work queue entry for this table */ + tab = ATGetQueueEntry(wqueue, fkrel); + tab->constraints = lappend(tab->constraints, newcon); + } + + /* + * If the table at either end of the constraint is partitioned, we need to + * recurse and handle every unvalidate constraint that is a child of this + * constraint. + */ + if (fkrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + get_rel_relkind(con->confrelid) == RELKIND_PARTITIONED_TABLE) + { + ScanKeyData pkey; + SysScanDesc pscan; + HeapTuple childtup; + + ScanKeyInit(&pkey, + Anum_pg_constraint_conparentid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(con->oid)); + + pscan = systable_beginscan(conrel, ConstraintParentIndexId, + true, NULL, 1, &pkey); + + while (HeapTupleIsValid(childtup = systable_getnext(pscan))) { - List *children = NIL; - ListCell *child; - NewConstraint *newcon; - Datum val; - char *conbin; + Form_pg_constraint childcon; + Relation childrel; + + childcon = (Form_pg_constraint) GETSTRUCT(childtup); /* - * If we're recursing, the parent has already done this, so skip - * it. Also, if the constraint is a NO INHERIT constraint, we - * shouldn't try to look for it in the children. + * If the child constraint has already been validated, no further + * action is required for it or its descendants, as they are all + * valid. */ - if (!recursing && !con->connoinherit) - children = find_all_inheritors(RelationGetRelid(rel), - lockmode, NULL); + if (childcon->convalidated) + continue; + + childrel = table_open(childcon->conrelid, lockmode); /* - * For CHECK constraints, we must ensure that we only mark the - * constraint as validated on the parent if it's already validated - * on the children. - * - * We recurse before validating on the parent, to reduce risk of - * deadlocks. + * NB: Note that pkrelid should be passed as-is during recursion, + * as it is required to identify the root referenced table. */ - foreach(child, children) - { - Oid childoid = lfirst_oid(child); - Relation childrel; + QueueFKConstraintValidation(wqueue, conrel, childrel, pkrelid, + childtup, lockmode); + table_close(childrel, NoLock); + } - if (childoid == RelationGetRelid(rel)) - continue; + systable_endscan(pscan); + } - /* - * If we are told not to recurse, there had better not be any - * child tables, because we can't mark the constraint on the - * parent valid unless it is valid for all child tables. - */ - if (!recurse) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("constraint must be validated on child tables too"))); + /* + * Now mark the pg_constraint row as validated (even if we didn't check, + * notably the ones for partitions on the referenced side). + * + * We rely on transaction abort to roll back this change if phase 3 + * ultimately finds violating rows. This is a bit ugly. + */ + copyTuple = heap_copytuple(contuple); + copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); + copy_con->convalidated = true; + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); - /* find_all_inheritors already got lock */ - childrel = table_open(childoid, NoLock); + InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); - ATExecValidateConstraint(wqueue, childrel, constrName, false, - true, lockmode); - table_close(childrel, NoLock); - } + heap_freetuple(copyTuple); +} - /* Queue validation for phase 3 */ - newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); - newcon->name = constrName; - newcon->contype = CONSTR_CHECK; - newcon->refrelid = InvalidOid; - newcon->refindid = InvalidOid; - newcon->conid = con->oid; +/* + * QueueCheckConstraintValidation + * + * Add an entry to the wqueue to validate the given check constraint in Phase 3 + * and update the convalidated field in the pg_constraint catalog for the + * specified relation and all its inheriting children. + */ +static void +QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, + char *constrName, HeapTuple contuple, + bool recurse, bool recursing, LOCKMODE lockmode) +{ + Form_pg_constraint con; + AlteredTableInfo *tab; + HeapTuple copyTuple; + Form_pg_constraint copy_con; - val = SysCacheGetAttrNotNull(CONSTROID, tuple, - Anum_pg_constraint_conbin); - conbin = TextDatumGetCString(val); - newcon->qual = (Node *) stringToNode(conbin); + List *children = NIL; + ListCell *child; + NewConstraint *newcon; + Datum val; + char *conbin; - /* Find or create work queue entry for this table */ - tab = ATGetQueueEntry(wqueue, rel); - tab->constraints = lappend(tab->constraints, newcon); + con = (Form_pg_constraint) GETSTRUCT(contuple); + Assert(con->contype == CONSTRAINT_CHECK); - /* - * Invalidate relcache so that others see the new validated - * constraint. - */ - CacheInvalidateRelcache(rel); - } + /* + * If we're recursing, the parent has already done this, so skip it. Also, + * if the constraint is a NO INHERIT constraint, we shouldn't try to look + * for it in the children. + */ + if (!recursing && !con->connoinherit) + children = find_all_inheritors(RelationGetRelid(rel), + lockmode, NULL); + + /* + * For CHECK constraints, we must ensure that we only mark the constraint + * as validated on the parent if it's already validated on the children. + * + * We recurse before validating on the parent, to reduce risk of + * deadlocks. + */ + foreach(child, children) + { + Oid childoid = lfirst_oid(child); + Relation childrel; + + if (childoid == RelationGetRelid(rel)) + continue; /* - * Now update the catalog, while we have the door open. + * If we are told not to recurse, there had better not be any child + * tables, because we can't mark the constraint on the parent valid + * unless it is valid for all child tables. */ - copyTuple = heap_copytuple(tuple); - copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); - - InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + if (!recurse) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be validated on child tables too"))); - heap_freetuple(copyTuple); + /* find_all_inheritors already got lock */ + childrel = table_open(childoid, NoLock); - ObjectAddressSet(address, ConstraintRelationId, con->oid); + ATExecValidateConstraint(wqueue, childrel, constrName, false, + true, lockmode); + table_close(childrel, NoLock); } - else - address = InvalidObjectAddress; /* already validated */ - systable_endscan(scan); + /* Queue validation for phase 3 */ + newcon = (NewConstraint *) palloc0(sizeof(NewConstraint)); + newcon->name = constrName; + newcon->contype = CONSTR_CHECK; + newcon->refrelid = InvalidOid; + newcon->refindid = InvalidOid; + newcon->conid = con->oid; - table_close(conrel, RowExclusiveLock); + val = SysCacheGetAttrNotNull(CONSTROID, contuple, + Anum_pg_constraint_conbin); + conbin = TextDatumGetCString(val); + newcon->qual = expand_generated_columns_in_expr(stringToNode(conbin), rel, 1); - return address; -} + /* Find or create work queue entry for this table */ + tab = ATGetQueueEntry(wqueue, rel); + tab->constraints = lappend(tab->constraints, newcon); + + /* + * Invalidate relcache so that others see the new validated constraint. + */ + CacheInvalidateRelcache(rel); + /* + * Now update the catalog, while we have the door open. + */ + copyTuple = heap_copytuple(contuple); + copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); + copy_con->convalidated = true; + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + + heap_freetuple(copyTuple); +} /* - * transformColumnNameList - transform list of column names + * QueueNNConstraintValidation * - * Lookup each name and return its attnum and, optionally, type OID - * - * Note: the name of this function suggests that it's general-purpose, - * but actually it's only used to look up names appearing in foreign-key - * clauses. The error messages would need work to use it in other cases, - * and perhaps the validity checks as well. + * Add an entry to the wqueue to validate the given not-null constraint in + * Phase 3 and update the convalidated field in the pg_constraint catalog for + * the specified relation and all its inheriting children. */ -static int -transformColumnNameList(Oid relId, List *colList, - int16 *attnums, Oid *atttypids) +static void +QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, + HeapTuple contuple, bool recurse, bool recursing, + LOCKMODE lockmode) { - ListCell *l; - int attnum; + Form_pg_constraint con; + AlteredTableInfo *tab; + HeapTuple copyTuple; + Form_pg_constraint copy_con; + List *children = NIL; + AttrNumber attnum; + char *colname; + + con = (Form_pg_constraint) GETSTRUCT(contuple); + Assert(con->contype == CONSTRAINT_NOTNULL); + + attnum = extractNotNullColumn(contuple); + + /* + * If we're recursing, we've already done this for parent, so skip it. + * Also, if the constraint is a NO INHERIT constraint, we shouldn't try to + * look for it in the children. + * + * We recurse before validating on the parent, to reduce risk of + * deadlocks. + */ + if (!recursing && !con->connoinherit) + children = find_all_inheritors(RelationGetRelid(rel), lockmode, NULL); + + colname = get_attname(RelationGetRelid(rel), attnum, false); + foreach_oid(childoid, children) + { + Relation childrel; + HeapTuple contup; + Form_pg_constraint childcon; + char *conname; + + if (childoid == RelationGetRelid(rel)) + continue; + + /* + * If we are told not to recurse, there had better not be any child + * tables, because we can't mark the constraint on the parent valid + * unless it is valid for all child tables. + */ + if (!recurse) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraint must be validated on child tables too")); + + /* + * The column on child might have a different attnum, so search by + * column name. + */ + contup = findNotNullConstraint(childoid, colname); + if (!contup) + elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation \"%s\"", + colname, get_rel_name(childoid)); + childcon = (Form_pg_constraint) GETSTRUCT(contup); + if (childcon->convalidated) + continue; + + /* find_all_inheritors already got lock */ + childrel = table_open(childoid, NoLock); + conname = pstrdup(NameStr(childcon->conname)); + + /* XXX improve ATExecValidateConstraint API to avoid double search */ + ATExecValidateConstraint(wqueue, childrel, conname, + false, true, lockmode); + table_close(childrel, NoLock); + } + + /* Set attnotnull appropriately without queueing another validation */ + set_attnotnull(NULL, rel, attnum, true, false); + + tab = ATGetQueueEntry(wqueue, rel); + tab->verify_new_notnull = true; + + /* + * Invalidate relcache so that others see the new validated constraint. + */ + CacheInvalidateRelcache(rel); + + /* + * Now update the catalogs, while we have the door open. + */ + copyTuple = heap_copytuple(contuple); + copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); + copy_con->convalidated = true; + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + + heap_freetuple(copyTuple); +} + +/* + * transformColumnNameList - transform list of column names + * + * Lookup each name and return its attnum and, optionally, type and collation + * OIDs + * + * Note: the name of this function suggests that it's general-purpose, + * but actually it's only used to look up names appearing in foreign-key + * clauses. The error messages would need work to use it in other cases, + * and perhaps the validity checks as well. + */ +static int +transformColumnNameList(Oid relId, List *colList, + int16 *attnums, Oid *atttypids, Oid *attcollids) +{ + ListCell *l; + int attnum; attnum = 0; foreach(l, colList) @@ -11794,6 +13320,8 @@ transformColumnNameList(Oid relId, List *colList, attnums[attnum] = attform->attnum; if (atttypids != NULL) atttypids[attnum] = attform->atttypid; + if (attcollids != NULL) + attcollids[attnum] = attform->attcollation; ReleaseSysCache(atttuple); attnum++; } @@ -11804,9 +13332,10 @@ transformColumnNameList(Oid relId, List *colList, /* * transformFkeyGetPrimaryKey - * - * Look up the names, attnums, and types of the primary key attributes + * Look up the names, attnums, types, and collations of the primary key attributes * for the pkrel. Also return the index OID and index opclasses of the - * index supporting the primary key. + * index supporting the primary key. Also return whether the index has + * WITHOUT OVERLAPS. * * All parameters except pkrel are output parameters. Also, the function * return value is the number of attributes in the primary key. @@ -11816,8 +13345,8 @@ transformColumnNameList(Oid relId, List *colList, static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid, List **attnamelist, - int16 *attnums, Oid *atttypids, - Oid *opclasses) + int16 *attnums, Oid *atttypids, Oid *attcollids, + Oid *opclasses, bool *pk_has_without_overlaps) { List *indexoidlist; ListCell *indexoidscan; @@ -11890,11 +13419,14 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid, attnums[i] = pkattno; atttypids[i] = attnumTypeId(pkrel, pkattno); + attcollids[i] = attnumCollationId(pkrel, pkattno); opclasses[i] = indclass->values[i]; *attnamelist = lappend(*attnamelist, makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno))))); } + *pk_has_without_overlaps = indexStruct->indisexclusion; + ReleaseSysCache(indexTuple); return i; @@ -11908,14 +13440,16 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid, * * Returns the OID of the unique index supporting the constraint and * populates the caller-provided 'opclasses' array with the opclasses - * associated with the index columns. + * associated with the index columns. Also sets whether the index + * uses WITHOUT OVERLAPS. * * Raises an ERROR on validation failure. */ static Oid transformFkeyCheckAttrs(Relation pkrel, int numattrs, int16 *attnums, - Oid *opclasses) + bool with_period, Oid *opclasses, + bool *pk_has_without_overlaps) { Oid indexoid = InvalidOid; bool found = false; @@ -11962,12 +13496,12 @@ transformFkeyCheckAttrs(Relation pkrel, indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); /* - * Must have the right number of columns; must be unique and not a - * partial index; forget it if there are any expressions, too. Invalid - * indexes are out as well. + * Must have the right number of columns; must be unique (or if + * temporal then exclusion instead) and not a partial index; forget it + * if there are any expressions, too. Invalid indexes are out as well. */ if (indexStruct->indnkeyatts == numattrs && - indexStruct->indisunique && + (with_period ? indexStruct->indisexclusion : indexStruct->indisunique) && indexStruct->indisvalid && heap_attisnull(indexTuple, Anum_pg_index_indpred, NULL) && heap_attisnull(indexTuple, Anum_pg_index_indexprs, NULL)) @@ -12005,6 +13539,13 @@ transformFkeyCheckAttrs(Relation pkrel, if (!found) break; } + /* The last attribute in the index must be the PERIOD FK part */ + if (found && with_period) + { + int16 periodattnum = attnums[numattrs - 1]; + + found = (periodattnum == indexStruct->indkey.values[numattrs - 1]); + } /* * Refuse to use a deferrable unique/primary key. This is per SQL @@ -12020,6 +13561,10 @@ transformFkeyCheckAttrs(Relation pkrel, found_deferrable = true; found = false; } + + /* We need to know whether the index has WITHOUT OVERLAPS */ + if (found) + *pk_has_without_overlaps = indexStruct->indisexclusion; } ReleaseSysCache(indexTuple); if (found) @@ -12114,7 +13659,8 @@ validateForeignKeyConstraint(char *conname, Relation rel, Relation pkrel, Oid pkindOid, - Oid constraintOid) + Oid constraintOid, + bool hasperiod) { TupleTableSlot *slot; TableScanDesc scan; @@ -12142,9 +13688,11 @@ validateForeignKeyConstraint(char *conname, /* * See if we can do it with a single LEFT JOIN query. A false result - * indicates we must proceed with the fire-the-trigger method. + * indicates we must proceed with the fire-the-trigger method. We can't do + * a LEFT JOIN for temporal FKs yet, but we can once we support temporal + * left joins. */ - if (RI_Initial_Check(&trig, rel, pkrel)) + if (!hasperiod && RI_Initial_Check(&trig, rel, pkrel)) return; /* @@ -12270,7 +13818,7 @@ CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, * *updateTrigOid. */ static void -createForeignKeyActionTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint, +createForeignKeyActionTriggers(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint, Oid constraintOid, Oid indexOid, Oid parentDelTrigger, Oid parentUpdTrigger, Oid *deleteTrigOid, Oid *updateTrigOid) @@ -12295,6 +13843,7 @@ createForeignKeyActionTriggers(Relation rel, Oid refRelOid, Constraint *fkconstr fk_trigger->whenClause = NULL; fk_trigger->transitionRels = NIL; fk_trigger->constrrel = NULL; + switch (fkconstraint->fk_del_action) { case FKCONSTR_ACTION_NOACTION: @@ -12328,8 +13877,7 @@ createForeignKeyActionTriggers(Relation rel, Oid refRelOid, Constraint *fkconstr break; } - trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, - RelationGetRelid(rel), + trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid, indexOid, InvalidOid, parentDelTrigger, NULL, true, false); if (deleteTrigOid) @@ -12355,6 +13903,7 @@ createForeignKeyActionTriggers(Relation rel, Oid refRelOid, Constraint *fkconstr fk_trigger->whenClause = NULL; fk_trigger->transitionRels = NIL; fk_trigger->constrrel = NULL; + switch (fkconstraint->fk_upd_action) { case FKCONSTR_ACTION_NOACTION: @@ -12388,8 +13937,7 @@ createForeignKeyActionTriggers(Relation rel, Oid refRelOid, Constraint *fkconstr break; } - trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, - RelationGetRelid(rel), + trigAddress = CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid, indexOid, InvalidOid, parentUpdTrigger, NULL, true, false); if (updateTrigOid) @@ -12426,23 +13974,14 @@ createForeignKeyCheckTriggers(Oid myRelOid, Oid refRelOid, */ static void ATExecDropConstraint(Relation rel, const char *constrName, - DropBehavior behavior, - bool recurse, bool recursing, + DropBehavior behavior, bool recurse, bool missing_ok, LOCKMODE lockmode) { - List *children; Relation conrel; - Form_pg_constraint con; SysScanDesc scan; ScanKeyData skey[3]; HeapTuple tuple; bool found = false; - bool is_no_inherit_constraint = false; - char contype; - - /* At top level, permission check was done in ATPrepCmd, else do it */ - if (recursing) - ATSimplePermissions(AT_DropConstraint, rel, ATT_TABLE | ATT_FOREIGN_TABLE); conrel = table_open(ConstraintRelationId, RowExclusiveLock); @@ -12467,80 +14006,190 @@ ATExecDropConstraint(Relation rel, const char *constrName, /* There can be at most one matching row */ if (HeapTupleIsValid(tuple = systable_getnext(scan))) { - ObjectAddress conobj; + dropconstraint_internal(rel, tuple, behavior, recurse, false, + missing_ok, lockmode); + found = true; + } - con = (Form_pg_constraint) GETSTRUCT(tuple); + systable_endscan(scan); - /* Don't drop inherited constraints */ - if (con->coninhcount > 0 && !recursing) + if (!found) + { + if (!missing_ok) ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot drop inherited constraint \"%s\" of relation \"%s\"", - constrName, RelationGetRelationName(rel)))); + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("constraint \"%s\" of relation \"%s\" does not exist", + constrName, RelationGetRelationName(rel))); + else + ereport(NOTICE, + errmsg("constraint \"%s\" of relation \"%s\" does not exist, skipping", + constrName, RelationGetRelationName(rel))); + } - is_no_inherit_constraint = con->connoinherit; - contype = con->contype; + table_close(conrel, RowExclusiveLock); +} + +/* + * Remove a constraint, using its pg_constraint tuple + * + * Implementation for ALTER TABLE DROP CONSTRAINT and ALTER TABLE ALTER COLUMN + * DROP NOT NULL. + * + * Returns the address of the constraint being removed. + */ +static ObjectAddress +dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior behavior, + bool recurse, bool recursing, bool missing_ok, + LOCKMODE lockmode) +{ + Relation conrel; + Form_pg_constraint con; + ObjectAddress conobj; + List *children; + bool is_no_inherit_constraint = false; + char *constrName; + char *colname = NULL; + + /* Guard against stack overflow due to overly deep inheritance tree. */ + check_stack_depth(); + + /* At top level, permission check was done in ATPrepCmd, else do it */ + if (recursing) + ATSimplePermissions(AT_DropConstraint, rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); + + conrel = table_open(ConstraintRelationId, RowExclusiveLock); + + con = (Form_pg_constraint) GETSTRUCT(constraintTup); + constrName = NameStr(con->conname); + + /* Don't allow drop of inherited constraints */ + if (con->coninhcount > 0 && !recursing) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("cannot drop inherited constraint \"%s\" of relation \"%s\"", + constrName, RelationGetRelationName(rel)))); + + /* + * Reset pg_constraint.attnotnull, if this is a not-null constraint. + * + * While doing that, we're in a good position to disallow dropping a not- + * null constraint underneath a primary key, a replica identity index, or + * a generated identity column. + */ + if (con->contype == CONSTRAINT_NOTNULL) + { + Relation attrel = table_open(AttributeRelationId, RowExclusiveLock); + AttrNumber attnum = extractNotNullColumn(constraintTup); + Bitmapset *pkattrs; + Bitmapset *irattrs; + HeapTuple atttup; + Form_pg_attribute attForm; + + /* save column name for recursion step */ + colname = get_attname(RelationGetRelid(rel), attnum, false); /* - * If it's a foreign-key constraint, we'd better lock the referenced - * table and check that that's not in use, just as we've already done - * for the constrained table (else we might, eg, be dropping a trigger - * that has unfired events). But we can/must skip that in the - * self-referential case. + * Disallow if it's in the primary key. For partitioned tables we + * cannot rely solely on RelationGetIndexAttrBitmap, because it'll + * return NULL if the primary key is invalid; but we still need to + * protect not-null constraints under such a constraint, so check the + * slow way. */ - if (contype == CONSTRAINT_FOREIGN && - con->confrelid != RelationGetRelid(rel)) + pkattrs = RelationGetIndexAttrBitmap(rel, INDEX_ATTR_BITMAP_PRIMARY_KEY); + + if (pkattrs == NULL && + rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { - Relation frel; + Oid pkindex = RelationGetPrimaryKeyIndex(rel, true); + + if (OidIsValid(pkindex)) + { + Relation pk = relation_open(pkindex, AccessShareLock); + + pkattrs = NULL; + for (int i = 0; i < pk->rd_index->indnkeyatts; i++) + pkattrs = bms_add_member(pkattrs, pk->rd_index->indkey.values[i]); - /* Must match lock taken by RemoveTriggerById: */ - frel = table_open(con->confrelid, AccessExclusiveLock); - CheckAlterTableIsSafe(frel); - table_close(frel, NoLock); + relation_close(pk, AccessShareLock); + } } - /* - * Perform the actual constraint deletion - */ - conobj.classId = ConstraintRelationId; - conobj.objectId = con->oid; - conobj.objectSubId = 0; + if (pkattrs && + bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber, pkattrs)) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("column \"%s\" is in a primary key", + get_attname(RelationGetRelid(rel), attnum, false))); - performDeletion(&conobj, behavior, 0); + /* Disallow if it's in the replica identity */ + irattrs = RelationGetIndexAttrBitmap(rel, INDEX_ATTR_BITMAP_IDENTITY_KEY); + if (bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber, irattrs)) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("column \"%s\" is in index used as replica identity", + get_attname(RelationGetRelid(rel), attnum, false))); + + /* Disallow if it's a GENERATED AS IDENTITY column */ + atttup = SearchSysCacheCopyAttNum(RelationGetRelid(rel), attnum); + if (!HeapTupleIsValid(atttup)) + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, RelationGetRelid(rel)); + attForm = (Form_pg_attribute) GETSTRUCT(atttup); + if (attForm->attidentity != '\0') + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("column \"%s\" of relation \"%s\" is an identity column", + get_attname(RelationGetRelid(rel), attnum, + false), + RelationGetRelationName(rel))); - found = true; + /* All good -- reset attnotnull if needed */ + if (attForm->attnotnull) + { + attForm->attnotnull = false; + CatalogTupleUpdate(attrel, &atttup->t_self, atttup); + } + + table_close(attrel, RowExclusiveLock); } - systable_endscan(scan); + is_no_inherit_constraint = con->connoinherit; - if (!found) + /* + * If it's a foreign-key constraint, we'd better lock the referenced table + * and check that that's not in use, just as we've already done for the + * constrained table (else we might, eg, be dropping a trigger that has + * unfired events). But we can/must skip that in the self-referential + * case. + */ + if (con->contype == CONSTRAINT_FOREIGN && + con->confrelid != RelationGetRelid(rel)) { - if (!missing_ok) - { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("constraint \"%s\" of relation \"%s\" does not exist", - constrName, RelationGetRelationName(rel)))); - } - else - { - ereport(NOTICE, - (errmsg("constraint \"%s\" of relation \"%s\" does not exist, skipping", - constrName, RelationGetRelationName(rel)))); - table_close(conrel, RowExclusiveLock); - return; - } + Relation frel; + + /* Must match lock taken by RemoveTriggerById: */ + frel = table_open(con->confrelid, AccessExclusiveLock); + CheckAlterTableIsSafe(frel); + table_close(frel, NoLock); } /* - * For partitioned tables, non-CHECK inherited constraints are dropped via - * the dependency mechanism, so we're done here. + * Perform the actual constraint deletion + */ + ObjectAddressSet(conobj, ConstraintRelationId, con->oid); + performDeletion(&conobj, behavior, 0); + + /* + * For partitioned tables, non-CHECK, non-NOT-NULL inherited constraints + * are dropped via the dependency mechanism, so we're done here. */ - if (contype != CONSTRAINT_CHECK && + if (con->contype != CONSTRAINT_CHECK && + con->contype != CONSTRAINT_NOTNULL && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { table_close(conrel, RowExclusiveLock); - return; + return conobj; } /* @@ -12553,63 +14202,68 @@ ATExecDropConstraint(Relation rel, const char *constrName, else children = NIL; - /* - * For a partitioned table, if partitions exist and we are told not to - * recurse, it's a user error. It doesn't make sense to have a constraint - * be defined only on the parent, especially if it's a partitioned table. - */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && - children != NIL && !recurse) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot remove constraint from only the partitioned table when partitions exist"), - errhint("Do not specify the ONLY keyword."))); - foreach_oid(childrelid, children) { Relation childrel; - HeapTuple copy_tuple; + HeapTuple tuple; + Form_pg_constraint childcon; /* find_inheritance_children already got lock */ childrel = table_open(childrelid, NoLock); CheckAlterTableIsSafe(childrel); - ScanKeyInit(&skey[0], - Anum_pg_constraint_conrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(childrelid)); - ScanKeyInit(&skey[1], - Anum_pg_constraint_contypid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(InvalidOid)); - ScanKeyInit(&skey[2], - Anum_pg_constraint_conname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(constrName)); - scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, - true, NULL, 3, skey); - - /* There can be at most one matching row */ - if (!HeapTupleIsValid(tuple = systable_getnext(scan))) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("constraint \"%s\" of relation \"%s\" does not exist", - constrName, - RelationGetRelationName(childrel)))); - - copy_tuple = heap_copytuple(tuple); - - systable_endscan(scan); + /* + * We search for not-null constraints by column name, and others by + * constraint name. + */ + if (con->contype == CONSTRAINT_NOTNULL) + { + tuple = findNotNullConstraint(childrelid, colname); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation %u", + colname, RelationGetRelid(childrel)); + } + else + { + SysScanDesc scan; + ScanKeyData skey[3]; + + ScanKeyInit(&skey[0], + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(childrelid)); + ScanKeyInit(&skey[1], + Anum_pg_constraint_contypid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(InvalidOid)); + ScanKeyInit(&skey[2], + Anum_pg_constraint_conname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(constrName)); + scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, + true, NULL, 3, skey); + /* There can only be one, so no need to loop */ + tuple = systable_getnext(scan); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("constraint \"%s\" of relation \"%s\" does not exist", + constrName, + RelationGetRelationName(childrel)))); + tuple = heap_copytuple(tuple); + systable_endscan(scan); + } - con = (Form_pg_constraint) GETSTRUCT(copy_tuple); + childcon = (Form_pg_constraint) GETSTRUCT(tuple); - /* Right now only CHECK constraints can be inherited */ - if (con->contype != CONSTRAINT_CHECK) - elog(ERROR, "inherited constraint is not a CHECK constraint"); + /* Right now only CHECK and not-null constraints can be inherited */ + if (childcon->contype != CONSTRAINT_CHECK && + childcon->contype != CONSTRAINT_NOTNULL) + elog(ERROR, "inherited constraint is not a CHECK or not-null constraint"); - if (con->coninhcount <= 0) /* shouldn't happen */ + if (childcon->coninhcount <= 0) /* shouldn't happen */ elog(ERROR, "relation %u has non-inherited constraint \"%s\"", - childrelid, constrName); + childrelid, NameStr(childcon->conname)); if (recurse) { @@ -12617,18 +14271,18 @@ ATExecDropConstraint(Relation rel, const char *constrName, * If the child constraint has other definition sources, just * decrement its inheritance count; if not, recurse to delete it. */ - if (con->coninhcount == 1 && !con->conislocal) + if (childcon->coninhcount == 1 && !childcon->conislocal) { /* Time to delete this child constraint, too */ - ATExecDropConstraint(childrel, constrName, behavior, - true, true, - false, lockmode); + dropconstraint_internal(childrel, tuple, behavior, + recurse, true, missing_ok, + lockmode); } else { /* Child constraint must survive my deletion */ - con->coninhcount--; - CatalogTupleUpdate(conrel, ©_tuple->t_self, copy_tuple); + childcon->coninhcount--; + CatalogTupleUpdate(conrel, &tuple->t_self, tuple); /* Make update visible */ CommandCounterIncrement(); @@ -12637,25 +14291,29 @@ ATExecDropConstraint(Relation rel, const char *constrName, else { /* - * If we were told to drop ONLY in this table (no recursion), we - * need to mark the inheritors' constraints as locally defined - * rather than inherited. + * If we were told to drop ONLY in this table (no recursion) and + * there are no further parents for this constraint, we need to + * mark the inheritors' constraints as locally defined rather than + * inherited. */ - con->coninhcount--; - con->conislocal = true; + childcon->coninhcount--; + if (childcon->coninhcount == 0) + childcon->conislocal = true; - CatalogTupleUpdate(conrel, ©_tuple->t_self, copy_tuple); + CatalogTupleUpdate(conrel, &tuple->t_self, tuple); /* Make update visible */ CommandCounterIncrement(); } - heap_freetuple(copy_tuple); + heap_freetuple(tuple); table_close(childrel, NoLock); } table_close(conrel, RowExclusiveLock); + + return conobj; } /* @@ -12697,10 +14355,13 @@ ATPrepAlterColumnType(List **wqueue, AclResult aclresult; bool is_expr; + pstate->p_sourcetext = context->queryString; + if (rel->rd_rel->reloftype && !recursing) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot alter column type of typed table"))); + errmsg("cannot alter column type of typed table"), + parser_errposition(pstate, def->location))); /* lookup the attribute so we can check inheritance status */ tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName); @@ -12708,7 +14369,8 @@ ATPrepAlterColumnType(List **wqueue, ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", - colName, RelationGetRelationName(rel)))); + colName, RelationGetRelationName(rel)), + parser_errposition(pstate, def->location))); attTup = (Form_pg_attribute) GETSTRUCT(tuple); attnum = attTup->attnum; @@ -12716,8 +14378,19 @@ ATPrepAlterColumnType(List **wqueue, if (attnum <= 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot alter system column \"%s\"", - colName))); + errmsg("cannot alter system column \"%s\"", colName), + parser_errposition(pstate, def->location))); + + /* + * Cannot specify USING when altering type of a generated column, because + * that would violate the generation expression. + */ + if (attTup->attgenerated && def->cooked_default) + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_DEFINITION), + errmsg("cannot specify USING when altering type of generated column"), + errdetail("Column \"%s\" is a generated column.", colName), + parser_errposition(pstate, def->location))); /* * Don't alter inherited columns. At outer level, there had better not be @@ -12727,8 +14400,8 @@ ATPrepAlterColumnType(List **wqueue, if (attTup->attinhcount > 0 && !recursing) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), - errmsg("cannot alter inherited column \"%s\"", - colName))); + errmsg("cannot alter inherited column \"%s\"", colName), + parser_errposition(pstate, def->location))); /* Don't alter columns used in the partition key */ if (has_partition_attrs(rel, @@ -12737,25 +14410,30 @@ ATPrepAlterColumnType(List **wqueue, ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("cannot alter column \"%s\" because it is part of the partition key of relation \"%s\"", - colName, RelationGetRelationName(rel)))); + colName, RelationGetRelationName(rel)), + parser_errposition(pstate, def->location))); /* Look up the target type */ - typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod); + typenameTypeIdAndMod(pstate, typeName, &targettype, &targettypmod); aclresult = object_aclcheck(TypeRelationId, targettype, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) aclcheck_error_type(aclresult, targettype); /* And the collation */ - targetcollid = GetColumnDefCollation(NULL, def, targettype); + targetcollid = GetColumnDefCollation(pstate, def, targettype); /* make sure datatype is legal for a column */ CheckAttributeType(colName, targettype, targetcollid, list_make1_oid(rel->rd_rel->reltype), 0); - if (tab->relkind == RELKIND_RELATION || - tab->relkind == RELKIND_PARTITIONED_TABLE) + if (attTup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + { + /* do nothing */ + } + else if (tab->relkind == RELKIND_RELATION || + tab->relkind == RELKIND_PARTITIONED_TABLE) { /* * Set up an expression to transform the old data value to the new @@ -12795,11 +14473,12 @@ ATPrepAlterColumnType(List **wqueue, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("column \"%s\" cannot be cast automatically to type %s", colName, format_type_be(targettype)), + !attTup->attgenerated ? /* translator: USING is SQL, don't translate it */ errhint("You might need to specify \"USING %s::%s\".", quote_identifier(colName), format_type_with_typemod(targettype, - targettypmod)))); + targettypmod)) : 0)); } /* Fix collations after all else */ @@ -12827,11 +14506,12 @@ ATPrepAlterColumnType(List **wqueue, errmsg("\"%s\" is not a table", RelationGetRelationName(rel)))); - if (!RELKIND_HAS_STORAGE(tab->relkind)) + if (!RELKIND_HAS_STORAGE(tab->relkind) || attTup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) { /* - * For relations without storage, do this check now. Regular tables - * will check it later when the table is being rewritten. + * For relations or columns without storage, do this check now. + * Regular tables will check it later when the table is being + * rewritten. */ find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL); } @@ -13303,7 +14983,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true, true); - StoreAttrDefault(rel, attnum, defaultexpr, true, false); + (void) StoreAttrDefault(rel, attnum, defaultexpr, true); } ObjectAddressSubSet(address, RelationRelationId, @@ -13593,10 +15273,26 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab) char *defstring = pg_get_constraintdef_command(conoid); Oid indoid; - tab->changedConstraintOids = lappend_oid(tab->changedConstraintOids, - conoid); - tab->changedConstraintDefs = lappend(tab->changedConstraintDefs, - defstring); + /* + * It is critical to create not-null constraints ahead of primary key + * indexes; otherwise, the not-null constraint would be created by the + * primary key, and the constraint name would be wrong. + */ + if (get_constraint_type(conoid) == CONSTRAINT_NOTNULL) + { + tab->changedConstraintOids = lcons_oid(conoid, + tab->changedConstraintOids); + tab->changedConstraintDefs = lcons(defstring, + tab->changedConstraintDefs); + } + else + { + + tab->changedConstraintOids = lappend_oid(tab->changedConstraintOids, + conoid); + tab->changedConstraintDefs = lappend(tab->changedConstraintDefs, + defstring); + } /* * For the index of a constraint, if any, remember if it is used for @@ -13759,9 +15455,10 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode) /* * If the constraint is inherited (only), we don't want to inject a - * new definition here; it'll get recreated when ATAddCheckConstraint - * recurses from adding the parent table's constraint. But we had to - * carry the info this far so that we can drop the constraint below. + * new definition here; it'll get recreated when + * ATAddCheckNNConstraint recurses from adding the parent table's + * constraint. But we had to carry the info this far so that we can + * drop the constraint below. */ if (!conislocal) continue; @@ -14000,23 +15697,21 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd, tab->subcmds[AT_PASS_OLD_CONSTR] = lappend(tab->subcmds[AT_PASS_OLD_CONSTR], cmd); - /* recreate any comment on the constraint */ - RebuildConstraintComment(tab, - AT_PASS_OLD_CONSTR, - oldId, - rel, - NIL, - con->conname); - } - else if (cmd->subtype == AT_SetNotNull) - { /* - * The parser will create AT_SetNotNull subcommands for - * columns of PRIMARY KEY indexes/constraints, but we need - * not do anything with them here, because the columns' - * NOT NULL marks will already have been propagated into - * the new table definition. + * Recreate any comment on the constraint. If we have + * recreated a primary key, then transformTableConstraint + * has added an unnamed not-null constraint here; skip + * this in that case. */ + if (con->conname) + RebuildConstraintComment(tab, + AT_PASS_OLD_CONSTR, + oldId, + rel, + NIL, + con->conname); + else + Assert(con->contype == CONSTR_NOTNULL); } else elog(ERROR, "unexpected statement subtype: %d", @@ -14131,7 +15826,8 @@ TryReuseIndex(Oid oldId, IndexStmt *stmt) if (CheckIndexCompatible(oldId, stmt->accessMethod, stmt->indexParams, - stmt->excludeOpNames)) + stmt->excludeOpNames, + stmt->iswithoutoverlaps)) { Relation irel = index_open(oldId, NoLock); @@ -14892,12 +16588,11 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, HeapTuple tuple; HeapTuple newtuple; Datum datum; - bool isnull; Datum newOptions; Datum repl_val[Natts_pg_class]; bool repl_null[Natts_pg_class]; bool repl_repl[Natts_pg_class]; - static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; if (defList == NIL && operation != AT_ReplaceRelOptions) return; /* nothing to do */ @@ -14906,7 +16601,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, /* Fetch heap tuple */ relid = RelationGetRelid(rel); - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + tuple = SearchSysCacheLocked1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); @@ -14917,25 +16612,26 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, * there were none before. */ datum = (Datum) 0; - isnull = true; } else { + bool isnull; + /* Get the old reloptions */ datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull); + if (isnull) + datum = (Datum) 0; } /* Generate new proposed reloptions (text array) */ - newOptions = transformRelOptions(isnull ? (Datum) 0 : datum, - defList, NULL, validnsps, false, + newOptions = transformRelOptions(datum, defList, NULL, validnsps, false, operation == AT_ResetRelOptions); /* Validate */ switch (rel->rd_rel->relkind) { case RELKIND_RELATION: - case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: (void) heap_reloptions(rel->rd_rel->relkind, newOptions, true); break; @@ -14949,6 +16645,8 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, case RELKIND_PARTITIONED_INDEX: (void) index_reloptions(rel->rd_indam->amoptions, newOptions, true); break; + case RELKIND_TOASTVALUE: + /* fall through to error -- shouldn't ever get here */ default: ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -15010,6 +16708,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, repl_val, repl_null, repl_repl); CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple); + UnlockTuple(pgclass, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); @@ -15037,18 +16736,20 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, * pretend there were none before. */ datum = (Datum) 0; - isnull = true; } else { + bool isnull; + /* Get the old reloptions */ datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull); + if (isnull) + datum = (Datum) 0; } - newOptions = transformRelOptions(isnull ? (Datum) 0 : datum, - defList, "toast", validnsps, false, - operation == AT_ResetRelOptions); + newOptions = transformRelOptions(datum, defList, "toast", validnsps, + false, operation == AT_ResetRelOptions); (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true); @@ -15512,7 +17213,8 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) * Must be owner of both parent and child -- child was checked by * ATSimplePermissions call in ATPrepCmd */ - ATSimplePermissions(AT_AddInherit, parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(AT_AddInherit, parent_rel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* Permanent rels cannot inherit from temporary ones */ if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && @@ -15699,6 +17401,9 @@ decompile_conbin(HeapTuple contup, TupleDesc tupdesc) * The test we apply is to see whether they reverse-compile to the same * source string. This insulates us from issues like whether attributes * have the same physical column numbers in parent and child relations. + * + * Note that we ignore enforceability as there are cases where constraints + * with differing enforceability are allowed. */ static bool constraints_equivalent(HeapTuple a, HeapTuple b, TupleDesc tupleDesc) @@ -15768,14 +17473,24 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart RelationGetRelationName(child_rel), parent_attname))); /* - * Check child doesn't discard NOT NULL property. (Other - * constraints are checked elsewhere.) + * If the parent has a not-null constraint that's not NO INHERIT, + * make sure the child has one too. + * + * Other constraints are checked elsewhere. */ if (parent_att->attnotnull && !child_att->attnotnull) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("column \"%s\" in child table must be marked NOT NULL", - parent_attname))); + { + HeapTuple contup; + + contup = findNotNullConstraintAttnum(RelationGetRelid(parent_rel), + parent_att->attnum); + if (HeapTupleIsValid(contup) && + !((Form_pg_constraint) GETSTRUCT(contup))->connoinherit) + ereport(ERROR, + errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("column \"%s\" in child table \"%s\" must be marked NOT NULL", + parent_attname, RelationGetRelationName(child_rel))); + } /* * Child column must be generated if and only if parent column is. @@ -15789,6 +17504,14 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("column \"%s\" in child table must not be a generated column", parent_attname))); + if (parent_att->attgenerated && child_att->attgenerated && child_att->attgenerated != parent_att->attgenerated) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("column \"%s\" inherits from generated column of different kind", parent_attname), + errdetail("Parent column is %s, child column is %s.", + parent_att->attgenerated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL", + child_att->attgenerated == ATTRIBUTE_GENERATED_STORED ? "STORED" : "VIRTUAL"))); + /* * Regular inheritance children are independent enough not to * inherit identity columns. But partitions are integral part of @@ -15801,8 +17524,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart * OK, bump the child column's inheritance count. (If we fail * later on, this change will just roll back.) */ - child_att->attinhcount++; - if (child_att->attinhcount < 0) + if (pg_add_s16_overflow(child_att->attinhcount, 1, + &child_att->attinhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); @@ -15857,6 +17580,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) ScanKeyData parent_key; HeapTuple parent_tuple; Oid parent_relid = RelationGetRelid(parent_rel); + AttrMap *attmap; constraintrel = table_open(ConstraintRelationId, RowExclusiveLock); @@ -15868,21 +17592,32 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) parent_scan = systable_beginscan(constraintrel, ConstraintRelidTypidNameIndexId, true, NULL, 1, &parent_key); + attmap = build_attrmap_by_name(RelationGetDescr(parent_rel), + RelationGetDescr(child_rel), + true); + while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan))) { Form_pg_constraint parent_con = (Form_pg_constraint) GETSTRUCT(parent_tuple); SysScanDesc child_scan; ScanKeyData child_key; HeapTuple child_tuple; + AttrNumber parent_attno; bool found = false; - if (parent_con->contype != CONSTRAINT_CHECK) + if (parent_con->contype != CONSTRAINT_CHECK && + parent_con->contype != CONSTRAINT_NOTNULL) continue; /* if the parent's constraint is marked NO INHERIT, it's not inherited */ if (parent_con->connoinherit) continue; + if (parent_con->contype == CONSTRAINT_NOTNULL) + parent_attno = extractNotNullColumn(parent_tuple); + else + parent_attno = InvalidAttrNumber; + /* Search for a child constraint matching this one */ ScanKeyInit(&child_key, Anum_pg_constraint_conrelid, @@ -15896,20 +17631,46 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) Form_pg_constraint child_con = (Form_pg_constraint) GETSTRUCT(child_tuple); HeapTuple child_copy; - if (child_con->contype != CONSTRAINT_CHECK) + if (child_con->contype != parent_con->contype) continue; - if (strcmp(NameStr(parent_con->conname), - NameStr(child_con->conname)) != 0) - continue; + /* + * CHECK constraint are matched by constraint name, NOT NULL ones + * by attribute number. + */ + if (child_con->contype == CONSTRAINT_CHECK) + { + if (strcmp(NameStr(parent_con->conname), + NameStr(child_con->conname)) != 0) + continue; + } + else if (child_con->contype == CONSTRAINT_NOTNULL) + { + Form_pg_attribute parent_attr; + Form_pg_attribute child_attr; + AttrNumber child_attno; + + parent_attr = TupleDescAttr(parent_rel->rd_att, parent_attno - 1); + child_attno = extractNotNullColumn(child_tuple); + if (parent_attno != attmap->attnums[child_attno - 1]) + continue; + + child_attr = TupleDescAttr(child_rel->rd_att, child_attno - 1); + /* there shouldn't be constraints on dropped columns */ + if (parent_attr->attisdropped || child_attr->attisdropped) + elog(ERROR, "found not-null constraint on dropped columns"); + } - if (!constraints_equivalent(parent_tuple, child_tuple, RelationGetDescr(constraintrel))) + if (child_con->contype == CONSTRAINT_CHECK && + !constraints_equivalent(parent_tuple, child_tuple, RelationGetDescr(constraintrel))) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("child table \"%s\" has different definition for check constraint \"%s\"", RelationGetRelationName(child_rel), NameStr(parent_con->conname)))); - /* If the child constraint is "no inherit" then cannot merge */ + /* + * If the child constraint is "no inherit" then cannot merge + */ if (child_con->connoinherit) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -15920,20 +17681,33 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) * If the child constraint is "not valid" then cannot merge with a * valid parent constraint */ - if (parent_con->convalidated && !child_con->convalidated) + if (parent_con->convalidated && child_con->conenforced && + !child_con->convalidated) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"", NameStr(child_con->conname), RelationGetRelationName(child_rel)))); + /* + * A NOT ENFORCED child constraint cannot be merged with an + * ENFORCED parent constraint. However, the reverse is allowed, + * where the child constraint is ENFORCED. + */ + if (parent_con->conenforced && !child_con->conenforced) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("constraint \"%s\" conflicts with NOT ENFORCED constraint on child table \"%s\"", + NameStr(child_con->conname), RelationGetRelationName(child_rel)))); + /* * OK, bump the child constraint's inheritance count. (If we fail * later on, this change will just roll back.) */ child_copy = heap_copytuple(child_tuple); child_con = (Form_pg_constraint) GETSTRUCT(child_copy); - child_con->coninhcount++; - if (child_con->coninhcount < 0) + + if (pg_add_s16_overflow(child_con->coninhcount, 1, + &child_con->coninhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); @@ -15959,10 +17733,21 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) systable_endscan(child_scan); if (!found) + { + if (parent_con->contype == CONSTRAINT_NOTNULL) + ereport(ERROR, + errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("column \"%s\" in child table \"%s\" must be marked NOT NULL", + get_attname(parent_relid, + extractNotNullColumn(parent_tuple), + false), + RelationGetRelationName(child_rel))); + ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("child table is missing constraint \"%s\"", NameStr(parent_con->conname)))); + } } systable_endscan(parent_scan); @@ -16107,7 +17892,9 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) ScanKeyData key[3]; HeapTuple attributeTuple, constraintTuple; + AttrMap *attmap; List *connames; + List *nncolumns; bool found; bool is_partitioning; @@ -16172,11 +17959,18 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) table_close(catalogRelation, RowExclusiveLock); /* - * Likewise, find inherited check constraints and disinherit them. To do - * this, we first need a list of the names of the parent's check - * constraints. (We cheat a bit by only checking for name matches, + * Likewise, find inherited check and not-null constraints and disinherit + * them. To do this, we first need a list of the names of the parent's + * check constraints. (We cheat a bit by only checking for name matches, * assuming that the expressions will match.) + * + * For NOT NULL columns, we store column numbers to match, mapping them in + * to the child rel's attribute numbers. */ + attmap = build_attrmap_by_name(RelationGetDescr(child_rel), + RelationGetDescr(parent_rel), + false); + catalogRelation = table_open(ConstraintRelationId, RowExclusiveLock); ScanKeyInit(&key[0], Anum_pg_constraint_conrelid, @@ -16186,18 +17980,28 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) true, NULL, 1, key); connames = NIL; + nncolumns = NIL; while (HeapTupleIsValid(constraintTuple = systable_getnext(scan))) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple); + if (con->connoinherit) + continue; + if (con->contype == CONSTRAINT_CHECK) connames = lappend(connames, pstrdup(NameStr(con->conname))); + if (con->contype == CONSTRAINT_NOTNULL) + { + AttrNumber parent_attno = extractNotNullColumn(constraintTuple); + + nncolumns = lappend_int(nncolumns, attmap->attnums[parent_attno - 1]); + } } systable_endscan(scan); - /* Now scan the child's constraints */ + /* Now scan the child's constraints to find matches */ ScanKeyInit(&key[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ, @@ -16208,20 +18012,41 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) while (HeapTupleIsValid(constraintTuple = systable_getnext(scan))) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple); - bool match; + bool match = false; - if (con->contype != CONSTRAINT_CHECK) - continue; - - match = false; - foreach_ptr(char, chkname, connames) + /* + * Match CHECK constraints by name, not-null constraints by column + * number, and ignore all others. + */ + if (con->contype == CONSTRAINT_CHECK) { - if (strcmp(NameStr(con->conname), chkname) == 0) + foreach_ptr(char, chkname, connames) { - match = true; - break; + if (con->contype == CONSTRAINT_CHECK && + strcmp(NameStr(con->conname), chkname) == 0) + { + match = true; + connames = foreach_delete_current(connames, chkname); + break; + } + } + } + else if (con->contype == CONSTRAINT_NOTNULL) + { + AttrNumber child_attno = extractNotNullColumn(constraintTuple); + + foreach_int(prevattno, nncolumns) + { + if (prevattno == child_attno) + { + match = true; + nncolumns = foreach_delete_current(nncolumns, prevattno); + break; + } } } + else + continue; if (match) { @@ -16242,6 +18067,12 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) } } + /* We should have matched all constraints */ + if (connames != NIL || nncolumns != NIL) + elog(ERROR, "%d unmatched constraints while removing inheritance from \"%s\" to \"%s\"", + list_length(connames) + list_length(nncolumns), + RelationGetRelationName(child_rel), RelationGetRelationName(parent_rel)); + systable_endscan(scan); table_close(catalogRelation, RowExclusiveLock); @@ -16640,9 +18471,15 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode errmsg("\"%s\" is not an index for table \"%s\"", RelationGetRelationName(indexRel), RelationGetRelationName(rel)))); - /* The AM must support uniqueness, and the index must in fact be unique. */ - if (!indexRel->rd_indam->amcanunique || - !indexRel->rd_index->indisunique) + + /* + * The AM must support uniqueness, and the index must in fact be unique. + * If we have a WITHOUT OVERLAPS constraint (identified by uniqueness + + * exclusion), we can use that too. + */ + if ((!indexRel->rd_indam->amcanunique || + !indexRel->rd_index->indisunique) && + !(indexRel->rd_index->indisunique && indexRel->rd_index->indisexclusion)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot use non-unique index \"%s\" as replica identity", @@ -16917,12 +18754,9 @@ ATExecSetCompression(Relation rel, * This verifies that we're not trying to change a temp table. Also, * existing foreign key constraints are checked to avoid ending up with * permanent tables referencing unlogged tables. - * - * Return value is false if the operation is a no-op (in which case the - * checks are skipped), otherwise true. */ -static bool -ATPrepChangePersistence(Relation rel, bool toLogged) +static void +ATPrepChangePersistence(AlteredTableInfo *tab, Relation rel, bool toLogged) { Relation pg_constraint; HeapTuple tuple; @@ -16946,12 +18780,12 @@ ATPrepChangePersistence(Relation rel, bool toLogged) case RELPERSISTENCE_PERMANENT: if (toLogged) /* nothing to do */ - return false; + return; break; case RELPERSISTENCE_UNLOGGED: if (!toLogged) /* nothing to do */ - return false; + return; break; } @@ -17034,7 +18868,13 @@ ATPrepChangePersistence(Relation rel, bool toLogged) table_close(pg_constraint, AccessShareLock); - return true; + /* force rewrite if necessary; see comment in ATRewriteTables */ + tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE; + if (toLogged) + tab->newrelpersistence = RELPERSISTENCE_PERMANENT; + else + tab->newrelpersistence = RELPERSISTENCE_UNLOGGED; + tab->chgPersistence = true; } /* @@ -17054,7 +18894,7 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema) relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, stmt->missing_ok ? RVR_MISSING_OK : 0, RangeVarCallbackForAlterRelation, - (void *) stmt); + stmt); if (!OidIsValid(relid)) { @@ -17159,7 +18999,8 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, ObjectAddress thisobj; bool already_done = false; - classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid)); + /* no rel lock for relkind=c so use LOCKTAG_TUPLE */ + classTup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relOid)); if (!HeapTupleIsValid(classTup)) elog(ERROR, "cache lookup failed for relation %u", relOid); classForm = (Form_pg_class) GETSTRUCT(classTup); @@ -17178,6 +19019,8 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, already_done = object_address_present(&thisobj, objsMoved); if (!already_done && oldNspOid != newNspOid) { + ItemPointerData otid = classTup->t_self; + /* check for duplicate name (more friendly than unique-index failure) */ if (get_relname_relid(NameStr(classForm->relname), newNspOid) != InvalidOid) @@ -17190,7 +19033,9 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, /* classTup is a copy, so OK to scribble on */ classForm->relnamespace = newNspOid; - CatalogTupleUpdate(classRel, &classTup->t_self, classTup); + CatalogTupleUpdate(classRel, &otid, classTup); + UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); + /* Update dependency on schema if caller said so */ if (hasDependEntry && @@ -17202,6 +19047,8 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, elog(ERROR, "could not change schema dependency for relation \"%s\"", NameStr(classForm->relname)); } + else + UnlockTuple(classRel, &classTup->t_self, InplaceUpdateTupleLock); if (!already_done) { add_exact_object_address(&thisobj, objsMoved); @@ -17912,8 +19759,11 @@ ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNu parser_errposition(pstate, pelem->location))); /* - * Generated columns cannot work: They are computed after BEFORE - * triggers, but partition routing is done before all triggers. + * Stored generated columns cannot work: They are computed after + * BEFORE triggers, but partition routing is done before all + * triggers. Maybe virtual generated columns could be made to + * work, but then they would need to be handled as an expression + * below. */ if (attform->attgenerated) ereport(ERROR, @@ -17995,9 +19845,12 @@ ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNu } /* - * Generated columns cannot work: They are computed after - * BEFORE triggers, but partition routing is done before all - * triggers. + * Stored generated columns cannot work: They are computed + * after BEFORE triggers, but partition routing is done before + * all triggers. Virtual generated columns could probably + * work, but it would require more work elsewhere (for example + * SET EXPRESSION would need to check whether the column is + * used in partition keys). Seems safer to prohibit for now. */ i = -1; while ((i = bms_next_member(expr_attrs, i)) >= 0) @@ -18144,17 +19997,19 @@ PartConstraintImpliedByRelConstraint(Relation scanrel, for (i = 1; i <= natts; i++) { - Form_pg_attribute att = TupleDescAttr(scanrel->rd_att, i - 1); + CompactAttribute *att = TupleDescCompactAttr(scanrel->rd_att, i - 1); - if (att->attnotnull && !att->attisdropped) + /* invalid not-null constraint must be ignored here */ + if (att->attnullability == ATTNULLABLE_VALID && !att->attisdropped) { + Form_pg_attribute wholeatt = TupleDescAttr(scanrel->rd_att, i - 1); NullTest *ntest = makeNode(NullTest); ntest->arg = (Expr *) makeVar(1, i, - att->atttypid, - att->atttypmod, - att->attcollation, + wholeatt->atttypid, + wholeatt->atttypmod, + wholeatt->attcollation, 0); ntest->nulltesttype = IS_NOT_NULL; @@ -18203,6 +20058,12 @@ ConstraintImpliedByRelConstraint(Relation scanrel, List *testConstraint, List *p if (!constr->check[i].ccvalid) continue; + /* + * NOT ENFORCED constraints are always marked as invalid, which should + * have been ignored. + */ + Assert(constr->check[i].ccenforced); + cexpr = stringToNode(constr->check[i].ccbin); /* @@ -18308,37 +20169,6 @@ QueuePartitionConstraintValidation(List **wqueue, Relation scanrel, } } -/* - * attachPartitionTable: attach a new partition to the partitioned table - * - * wqueue: the ALTER TABLE work queue; can be NULL when not running as part - * of an ALTER TABLE sequence. - * rel: partitioned relation; - * attachrel: relation of attached partition; - * bound: bounds of attached relation. - */ -static void -attachPartitionTable(List **wqueue, Relation rel, Relation attachrel, PartitionBoundSpec *bound) -{ - /* OK to create inheritance. Rest of the checks performed there */ - CreateInheritance(attachrel, rel, true); - - /* Update the pg_class entry. */ - StorePartitionBound(attachrel, rel, bound); - - /* Ensure there exists a correct set of indexes in the partition. */ - AttachPartitionEnsureIndexes(wqueue, rel, attachrel); - - /* and triggers */ - CloneRowTriggersToPartition(rel, attachrel); - - /* - * Clone foreign key constraints. Callee is responsible for setting up - * for phase 3 constraint verification. - */ - CloneForeignKeyConstraints(wqueue, rel, attachrel); -} - /* * ALTER TABLE ATTACH PARTITION FOR VALUES * @@ -18385,7 +20215,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd, * Must be owner of both parent and source table -- parent was checked by * ATSimplePermissions call in ATPrepCmd */ - ATSimplePermissions(AT_AttachPartition, attachrel, ATT_TABLE | ATT_FOREIGN_TABLE); + ATSimplePermissions(AT_AttachPartition, attachrel, + ATT_TABLE | ATT_PARTITIONED_TABLE | ATT_FOREIGN_TABLE); /* A partition can only have one parent */ if (attachrel->rd_rel->relispartition) @@ -18541,8 +20372,23 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd, check_new_partition_bound(RelationGetRelationName(attachrel), rel, cmd->bound, pstate); - /* Attach a new partition to the partitioned table. */ - attachPartitionTable(wqueue, rel, attachrel, cmd->bound); + /* OK to create inheritance. Rest of the checks performed there */ + CreateInheritance(attachrel, rel, true); + + /* Update the pg_class entry. */ + StorePartitionBound(attachrel, rel, cmd->bound); + + /* Ensure there exists a correct set of indexes in the partition. */ + AttachPartitionEnsureIndexes(wqueue, rel, attachrel); + + /* and triggers */ + CloneRowTriggersToPartition(rel, attachrel); + + /* + * Clone foreign key constraints. Callee is responsible for setting up + * for phase 3 constraint verification. + */ + CloneForeignKeyConstraints(wqueue, rel, attachrel); /* * Generate partition constraint from the partition bound specification. @@ -18550,8 +20396,14 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd, * constraint as well. */ partBoundConstraint = get_qual_from_partbound(rel, cmd->bound); - partConstraint = list_concat(partBoundConstraint, - RelationGetPartitionQual(rel)); + + /* + * Use list_concat_copy() to avoid modifying partBoundConstraint in place, + * since it's needed later to construct the constraint expression for + * validating against the default partition, if any. + */ + partConstraint = list_concat_copy(partBoundConstraint, + RelationGetPartitionQual(rel)); /* Skip validation if there are no constraints to validate. */ if (partConstraint) @@ -18793,7 +20645,8 @@ AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel) /* * If no suitable index was found in the partition-to-be, create one - * now. + * now. Note that if this is a PK, not-null constraints must already + * exist. */ if (!found) { @@ -19137,9 +20990,17 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, tab->rel = rel; } + /* + * Detaching the partition might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* Do the final part of detaching */ DetachPartitionFinalize(rel, partRel, concurrent, defaultPartOid); + PopActiveSnapshot(); + ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel)); /* keep our lock until commit */ @@ -19168,6 +21029,7 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, HeapTuple tuple, newtuple; Relation trigrel = NULL; + List *fkoids = NIL; if (concurrent) { @@ -19188,73 +21050,158 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, fks = copyObject(RelationGetFKeyList(partRel)); if (fks != NIL) trigrel = table_open(TriggerRelationId, RowExclusiveLock); + + /* + * It's possible that the partition being detached has a foreign key that + * references a partitioned table. When that happens, there are multiple + * pg_constraint rows for the partition: one points to the partitioned + * table itself, while the others point to each of its partitions. Only + * the topmost one is to be considered here; the child constraints must be + * left alone, because conceptually those aren't coming from our parent + * partitioned table, but from this partition itself. + * + * We implement this by collecting all the constraint OIDs in a first scan + * of the FK array, and skipping in the loop below those constraints whose + * parents are listed here. + */ + foreach_node(ForeignKeyCacheInfo, fk, fks) + fkoids = lappend_oid(fkoids, fk->conoid); + foreach(cell, fks) { ForeignKeyCacheInfo *fk = lfirst(cell); HeapTuple contup; Form_pg_constraint conform; - Constraint *fkconstraint; - Oid insertTriggerOid, - updateTriggerOid; contup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(fk->conoid)); if (!HeapTupleIsValid(contup)) elog(ERROR, "cache lookup failed for constraint %u", fk->conoid); conform = (Form_pg_constraint) GETSTRUCT(contup); - /* consider only the inherited foreign keys */ + /* + * Consider only inherited foreign keys, and only if their parents + * aren't in the list. + */ if (conform->contype != CONSTRAINT_FOREIGN || - !OidIsValid(conform->conparentid)) + !OidIsValid(conform->conparentid) || + list_member_oid(fkoids, conform->conparentid)) { ReleaseSysCache(contup); continue; } - /* unset conparentid and adjust conislocal, coninhcount, etc. */ + /* + * The constraint on this table must be marked no longer a child of + * the parent's constraint, as do its check triggers. + */ ConstraintSetParentConstraint(fk->conoid, InvalidOid, InvalidOid); /* * Also, look up the partition's "check" triggers corresponding to the - * constraint being detached and detach them from the parent triggers. + * ENFORCED constraint being detached and detach them from the parent + * triggers. NOT ENFORCED constraints do not have these triggers; + * therefore, this step is not needed. */ - GetForeignKeyCheckTriggers(trigrel, - fk->conoid, fk->confrelid, fk->conrelid, - &insertTriggerOid, &updateTriggerOid); - Assert(OidIsValid(insertTriggerOid)); - TriggerSetParentTrigger(trigrel, insertTriggerOid, InvalidOid, - RelationGetRelid(partRel)); - Assert(OidIsValid(updateTriggerOid)); - TriggerSetParentTrigger(trigrel, updateTriggerOid, InvalidOid, - RelationGetRelid(partRel)); + if (fk->conenforced) + { + Oid insertTriggerOid, + updateTriggerOid; + + GetForeignKeyCheckTriggers(trigrel, + fk->conoid, fk->confrelid, fk->conrelid, + &insertTriggerOid, &updateTriggerOid); + Assert(OidIsValid(insertTriggerOid)); + TriggerSetParentTrigger(trigrel, insertTriggerOid, InvalidOid, + RelationGetRelid(partRel)); + Assert(OidIsValid(updateTriggerOid)); + TriggerSetParentTrigger(trigrel, updateTriggerOid, InvalidOid, + RelationGetRelid(partRel)); + } /* - * Make the action triggers on the referenced relation. When this was - * a partition the action triggers pointed to the parent rel (they - * still do), but now we need separate ones of our own. + * Lastly, create the action triggers on the referenced table, using + * addFkRecurseReferenced, which requires some elaborate setup (so put + * it in a separate block). While at it, if the table is partitioned, + * that function will recurse to create the pg_constraint rows and + * action triggers for each partition. + * + * Note there's no need to do addFkConstraint() here, because the + * pg_constraint row already exists. */ - fkconstraint = makeNode(Constraint); - fkconstraint->contype = CONSTRAINT_FOREIGN; - fkconstraint->conname = pstrdup(NameStr(conform->conname)); - fkconstraint->deferrable = conform->condeferrable; - fkconstraint->initdeferred = conform->condeferred; - fkconstraint->location = -1; - fkconstraint->pktable = NULL; - fkconstraint->fk_attrs = NIL; - fkconstraint->pk_attrs = NIL; - fkconstraint->fk_matchtype = conform->confmatchtype; - fkconstraint->fk_upd_action = conform->confupdtype; - fkconstraint->fk_del_action = conform->confdeltype; - fkconstraint->fk_del_set_cols = NIL; - fkconstraint->old_conpfeqop = NIL; - fkconstraint->old_pktable_oid = InvalidOid; - fkconstraint->skip_validation = false; - fkconstraint->initially_valid = true; + { + Constraint *fkconstraint; + int numfks; + AttrNumber conkey[INDEX_MAX_KEYS]; + AttrNumber confkey[INDEX_MAX_KEYS]; + Oid conpfeqop[INDEX_MAX_KEYS]; + Oid conppeqop[INDEX_MAX_KEYS]; + Oid conffeqop[INDEX_MAX_KEYS]; + int numfkdelsetcols; + AttrNumber confdelsetcols[INDEX_MAX_KEYS]; + Relation refdRel; + + DeconstructFkConstraintRow(contup, + &numfks, + conkey, + confkey, + conpfeqop, + conppeqop, + conffeqop, + &numfkdelsetcols, + confdelsetcols); + + /* Create a synthetic node we'll use throughout */ + fkconstraint = makeNode(Constraint); + fkconstraint->contype = CONSTRAINT_FOREIGN; + fkconstraint->conname = pstrdup(NameStr(conform->conname)); + fkconstraint->deferrable = conform->condeferrable; + fkconstraint->initdeferred = conform->condeferred; + fkconstraint->is_enforced = conform->conenforced; + fkconstraint->skip_validation = true; + fkconstraint->initially_valid = conform->convalidated; + /* a few irrelevant fields omitted here */ + fkconstraint->pktable = NULL; + fkconstraint->fk_attrs = NIL; + fkconstraint->pk_attrs = NIL; + fkconstraint->fk_matchtype = conform->confmatchtype; + fkconstraint->fk_upd_action = conform->confupdtype; + fkconstraint->fk_del_action = conform->confdeltype; + fkconstraint->fk_del_set_cols = NIL; + fkconstraint->old_conpfeqop = NIL; + fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->location = -1; + + /* set up colnames, used to generate the constraint name */ + for (int i = 0; i < numfks; i++) + { + Form_pg_attribute att; - createForeignKeyActionTriggers(partRel, conform->confrelid, - fkconstraint, fk->conoid, - conform->conindid, - InvalidOid, InvalidOid, - NULL, NULL); + att = TupleDescAttr(RelationGetDescr(partRel), + conkey[i] - 1); + + fkconstraint->fk_attrs = lappend(fkconstraint->fk_attrs, + makeString(NameStr(att->attname))); + } + + refdRel = table_open(fk->confrelid, ShareRowExclusiveLock); + + addFkRecurseReferenced(fkconstraint, partRel, + refdRel, + conform->conindid, + fk->conoid, + numfks, + confkey, + conkey, + conpfeqop, + conppeqop, + conffeqop, + numfkdelsetcols, + confdelsetcols, + true, + InvalidOid, InvalidOid, + conform->conperiod); + table_close(refdRel, NoLock); /* keep lock till end of xact */ + } ReleaseSysCache(contup); } @@ -19434,7 +21381,7 @@ ATExecDetachPartitionFinalize(Relation rel, RangeVar *name) * DetachAddConstraintIfNeeded * Subroutine for ATExecDetachPartition. Create a constraint that * takes the place of the partition constraint, but avoid creating - * a dupe if an constraint already exists which implies the needed + * a dupe if a constraint already exists which implies the needed * constraint. */ static void @@ -19464,11 +21411,12 @@ DetachAddConstraintIfNeeded(List **wqueue, Relation partRel) n->is_no_inherit = false; n->raw_expr = NULL; n->cooked_expr = nodeToString(make_ands_explicit(constraintExpr)); + n->is_enforced = true; n->initially_valid = true; n->skip_validation = true; /* It's a re-add, since it nominally already exists */ - ATAddCheckConstraint(wqueue, tab, partRel, n, - true, false, true, ShareUpdateExclusiveLock); + ATAddCheckNNConstraint(wqueue, tab, partRel, n, + true, false, true, ShareUpdateExclusiveLock); } } @@ -19629,7 +21577,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) partIdxId = RangeVarGetRelidExtended(name, AccessExclusiveLock, 0, RangeVarCallbackForAttachIndex, - (void *) &state); + &state); /* Not there? */ if (!OidIsValid(partIdxId)) ereport(ERROR, @@ -19737,6 +21685,13 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) RelationGetRelationName(partIdx)))); } + /* + * If it's a primary key, make sure the columns in the partition are + * NOT NULL. + */ + if (parentIdx->rd_index->indisprimary) + verifyPartitionIndexNotNull(childInfo, partTbl); + /* All good -- do it */ IndexSetParentIndex(partIdx, RelationGetRelid(parentIdx)); if (OidIsValid(constraintOid)) @@ -19880,6 +21835,29 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) } } +/* + * When attaching an index as a partition of a partitioned index which is a + * primary key, verify that all the columns in the partition are marked NOT + * NULL. + */ +static void +verifyPartitionIndexNotNull(IndexInfo *iinfo, Relation partition) +{ + for (int i = 0; i < iinfo->ii_NumIndexKeyAttrs; i++) + { + Form_pg_attribute att = TupleDescAttr(RelationGetDescr(partition), + iinfo->ii_IndexAttrNumbers[i] - 1); + + if (!att->attnotnull) + ereport(ERROR, + errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("invalid primary key definition"), + errdetail("Column \"%s\" of relation \"%s\" is not marked NOT NULL.", + NameStr(att->attname), + RelationGetRelationName(partition))); + } +} + /* * Return an OID list of constraints that reference the given relation * that are marked as having a parent constraints. @@ -20057,728 +22035,3 @@ GetAttributeStorage(Oid atttypid, const char *storagemode) return cstorage; } - -/* - * Struct with context of new partition for inserting rows from split partition - */ -typedef struct SplitPartitionContext -{ - ExprState *partqualstate; /* expression for checking slot for partition - * (NULL for DEFAULT partition) */ - BulkInsertState bistate; /* state of bulk inserts for partition */ - TupleTableSlot *dstslot; /* slot for inserting row into partition */ - Relation partRel; /* relation for partition */ -} SplitPartitionContext; - - -/* - * createSplitPartitionContext: create context for partition and fill it - */ -static SplitPartitionContext * -createSplitPartitionContext(Relation partRel) -{ - SplitPartitionContext *pc; - - pc = (SplitPartitionContext *) palloc0(sizeof(SplitPartitionContext)); - pc->partRel = partRel; - - /* - * Prepare a BulkInsertState for table_tuple_insert. The FSM is empty, so - * don't bother using it. - */ - pc->bistate = GetBulkInsertState(); - - /* Create tuple slot for new partition. */ - pc->dstslot = MakeSingleTupleTableSlot(RelationGetDescr(pc->partRel), - table_slot_callbacks(pc->partRel)); - ExecStoreAllNullTuple(pc->dstslot); - - return pc; -} - -/* - * deleteSplitPartitionContext: delete context for partition - */ -static void -deleteSplitPartitionContext(SplitPartitionContext *pc, int ti_options) -{ - ExecDropSingleTupleTableSlot(pc->dstslot); - FreeBulkInsertState(pc->bistate); - - table_finish_bulk_insert(pc->partRel, ti_options); - - pfree(pc); -} - -/* - * moveSplitTableRows: scan split partition (splitRel) of partitioned table - * (rel) and move rows into new partitions. - * - * New partitions description: - * partlist: list of pointers to SinglePartitionSpec structures. - * newPartRels: list of Relations. - * defaultPartOid: oid of DEFAULT partition, for table rel. - */ -static void -moveSplitTableRows(Relation rel, Relation splitRel, List *partlist, List *newPartRels, Oid defaultPartOid) -{ - /* The FSM is empty, so don't bother using it. */ - int ti_options = TABLE_INSERT_SKIP_FSM; - CommandId mycid; - EState *estate; - ListCell *listptr, - *listptr2; - TupleTableSlot *srcslot; - ExprContext *econtext; - TableScanDesc scan; - Snapshot snapshot; - MemoryContext oldCxt; - List *partContexts = NIL; - TupleConversionMap *tuple_map; - SplitPartitionContext *defaultPartCtx = NULL, - *pc; - bool isOldDefaultPart = false; - - mycid = GetCurrentCommandId(true); - - estate = CreateExecutorState(); - - forboth(listptr, partlist, listptr2, newPartRels) - { - SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); - - pc = createSplitPartitionContext((Relation) lfirst(listptr2)); - - if (sps->bound->is_default) - { - /* We should not create constraint for detached DEFAULT partition. */ - defaultPartCtx = pc; - } - else - { - List *partConstraint; - - /* Build expression execution states for partition check quals. */ - partConstraint = get_qual_from_partbound(rel, sps->bound); - partConstraint = - (List *) eval_const_expressions(NULL, - (Node *) partConstraint); - /* Make boolean expression for ExecCheck(). */ - partConstraint = list_make1(make_ands_explicit(partConstraint)); - - /* - * Map the vars in the constraint expression from rel's attnos to - * splitRel's. - */ - partConstraint = map_partition_varattnos(partConstraint, - 1, splitRel, rel); - - pc->partqualstate = - ExecPrepareExpr((Expr *) linitial(partConstraint), estate); - Assert(pc->partqualstate != NULL); - } - - /* Store partition context into list. */ - partContexts = lappend(partContexts, pc); - } - - /* - * Create partition context for DEFAULT partition. We can insert values - * into this partition in case spaces with values between new partitions. - */ - if (!defaultPartCtx && OidIsValid(defaultPartOid)) - { - /* Indicate that we allocate context for old DEFAULT partition */ - isOldDefaultPart = true; - defaultPartCtx = createSplitPartitionContext(table_open(defaultPartOid, AccessExclusiveLock)); - } - - econtext = GetPerTupleExprContext(estate); - - /* Create necessary tuple slot. */ - srcslot = MakeSingleTupleTableSlot(RelationGetDescr(splitRel), - table_slot_callbacks(splitRel)); - - /* - * Map computing for moving attributes of split partition to new partition - * (for first new partition, but other new partitions can use the same - * map). - */ - pc = (SplitPartitionContext *) lfirst(list_head(partContexts)); - tuple_map = convert_tuples_by_name(RelationGetDescr(splitRel), - RelationGetDescr(pc->partRel)); - - /* Scan through the rows. */ - snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = table_beginscan(splitRel, snapshot, 0, NULL); - - /* - * Switch to per-tuple memory context and reset it for each tuple - * produced, so we don't leak memory. - */ - oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); - - while (table_scan_getnextslot(scan, ForwardScanDirection, srcslot)) - { - bool found = false; - TupleTableSlot *insertslot; - - /* Extract data from old tuple. */ - slot_getallattrs(srcslot); - - econtext->ecxt_scantuple = srcslot; - - /* Search partition for current slot srcslot. */ - foreach(listptr, partContexts) - { - pc = (SplitPartitionContext *) lfirst(listptr); - - if (pc->partqualstate /* skip DEFAULT partition */ && - ExecCheck(pc->partqualstate, econtext)) - { - found = true; - break; - } - ResetExprContext(econtext); - } - if (!found) - { - /* Use DEFAULT partition if it exists. */ - if (defaultPartCtx) - pc = defaultPartCtx; - else - ereport(ERROR, - (errcode(ERRCODE_CHECK_VIOLATION), - errmsg("can not find partition for split partition row"), - errtable(splitRel))); - } - - if (tuple_map) - { - /* Need to use map to copy attributes. */ - insertslot = execute_attr_map_slot(tuple_map->attrMap, srcslot, pc->dstslot); - } - else - { - /* Copy attributes directly. */ - insertslot = pc->dstslot; - - ExecClearTuple(insertslot); - - memcpy(insertslot->tts_values, srcslot->tts_values, - sizeof(Datum) * srcslot->tts_nvalid); - memcpy(insertslot->tts_isnull, srcslot->tts_isnull, - sizeof(bool) * srcslot->tts_nvalid); - - ExecStoreVirtualTuple(insertslot); - } - - /* Write the tuple out to the new relation. */ - table_tuple_insert(pc->partRel, insertslot, mycid, - ti_options, pc->bistate); - - ResetExprContext(econtext); - - CHECK_FOR_INTERRUPTS(); - } - - MemoryContextSwitchTo(oldCxt); - - table_endscan(scan); - UnregisterSnapshot(snapshot); - - if (tuple_map) - free_conversion_map(tuple_map); - - ExecDropSingleTupleTableSlot(srcslot); - - FreeExecutorState(estate); - - foreach(listptr, partContexts) - deleteSplitPartitionContext((SplitPartitionContext *) lfirst(listptr), ti_options); - - /* Need to close table and free buffers for DEFAULT partition. */ - if (isOldDefaultPart) - { - Relation defaultPartRel = defaultPartCtx->partRel; - - deleteSplitPartitionContext(defaultPartCtx, ti_options); - /* Keep the lock until commit. */ - table_close(defaultPartRel, NoLock); - } -} - -/* - * createPartitionTable: create table for a new partition with given name - * (newPartName) like table (modelRel) - * - * Emulates command: CREATE [TEMP] TABLE (LIKE - * INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS) - * - * Also, this function sets the new partition access method same as parent - * table access methods (similarly to CREATE TABLE ... PARTITION OF). It - * checks that parent and child tables have compatible persistence. - * - * Function returns the created relation (locked in AccessExclusiveLock mode). - */ -static Relation -createPartitionTable(RangeVar *newPartName, Relation modelRel, - AlterTableUtilityContext *context) -{ - CreateStmt *createStmt; - TableLikeClause *tlc; - PlannedStmt *wrapper; - Relation newRel; - - /* If existing rel is temp, it must belong to this session */ - if (modelRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && - !modelRel->rd_islocaltemp) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot create as partition of temporary relation of another session"))); - - /* New partition should have the same persistence as modelRel */ - newPartName->relpersistence = modelRel->rd_rel->relpersistence; - - createStmt = makeNode(CreateStmt); - createStmt->relation = newPartName; - createStmt->tableElts = NIL; - createStmt->inhRelations = NIL; - createStmt->constraints = NIL; - createStmt->options = NIL; - createStmt->oncommit = ONCOMMIT_NOOP; - createStmt->tablespacename = get_tablespace_name(modelRel->rd_rel->reltablespace); - createStmt->if_not_exists = false; - createStmt->accessMethod = get_am_name(modelRel->rd_rel->relam); - - tlc = makeNode(TableLikeClause); - tlc->relation = makeRangeVar(get_namespace_name(RelationGetNamespace(modelRel)), - RelationGetRelationName(modelRel), -1); - - /* - * Indexes will be inherited on "attach new partitions" stage, after data - * moving. We also don't copy the extended statistics for consistency - * with CREATE TABLE PARTITION OF. - */ - tlc->options = CREATE_TABLE_LIKE_ALL & - ~(CREATE_TABLE_LIKE_INDEXES | CREATE_TABLE_LIKE_IDENTITY | CREATE_TABLE_LIKE_STATISTICS); - tlc->relationOid = InvalidOid; - createStmt->tableElts = lappend(createStmt->tableElts, tlc); - - /* Need to make a wrapper PlannedStmt. */ - wrapper = makeNode(PlannedStmt); - wrapper->commandType = CMD_UTILITY; - wrapper->canSetTag = false; - wrapper->utilityStmt = (Node *) createStmt; - wrapper->stmt_location = context->pstmt->stmt_location; - wrapper->stmt_len = context->pstmt->stmt_len; - - ProcessUtility(wrapper, - context->queryString, - false, - PROCESS_UTILITY_SUBCOMMAND, - NULL, - NULL, - None_Receiver, - NULL); - - /* - * Open the new partition with no lock, because we already have - * AccessExclusiveLock placed there after creation. - */ - newRel = table_openrv(newPartName, NoLock); - - /* - * We intended to create the partition with the same persistence as the - * parent table, but we still need to recheck because that might be - * affected by the search_path. If the parent is permanent, so must be - * all of its partitions. - */ - if (modelRel->rd_rel->relpersistence != RELPERSISTENCE_TEMP && - newRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot create a temporary relation as partition of permanent relation \"%s\"", - RelationGetRelationName(modelRel)))); - - /* Permanent rels cannot be partitions belonging to temporary parent */ - if (newRel->rd_rel->relpersistence != RELPERSISTENCE_TEMP && - modelRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot create a permanent relation as partition of temporary relation \"%s\"", - RelationGetRelationName(modelRel)))); - - return newRel; -} - -/* - * ALTER TABLE SPLIT PARTITION INTO - */ -static void -ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, - PartitionCmd *cmd, AlterTableUtilityContext *context) -{ - Relation splitRel; - Oid splitRelOid; - char relname[NAMEDATALEN]; - Oid namespaceId; - ListCell *listptr, - *listptr2; - bool isSameName = false; - char tmpRelName[NAMEDATALEN]; - List *newPartRels = NIL; - ObjectAddress object; - Oid defaultPartOid; - - defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(rel, true)); - - /* - * We are going to detach and remove this partition: need to use exclusive - * lock for preventing DML-queries to the partition. - */ - splitRel = table_openrv(cmd->name, AccessExclusiveLock); - - splitRelOid = RelationGetRelid(splitRel); - - /* Check descriptions of new partitions. */ - foreach(listptr, cmd->partlist) - { - Oid existing_relid; - SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); - - strlcpy(relname, sps->name->relname, NAMEDATALEN); - - /* - * Look up the namespace in which we are supposed to create the - * partition, check we have permission to create there, lock it - * against concurrent drop, and mark stmt->relation as - * RELPERSISTENCE_TEMP if a temporary namespace is selected. - */ - sps->name->relpersistence = rel->rd_rel->relpersistence; - namespaceId = - RangeVarGetAndCheckCreationNamespace(sps->name, NoLock, NULL); - - /* - * This would fail later on anyway if the relation already exists. But - * by catching it here we can emit a nicer error message. - */ - existing_relid = get_relname_relid(relname, namespaceId); - if (existing_relid == splitRelOid && !isSameName) - /* One new partition can have the same name as split partition. */ - isSameName = true; - else if (existing_relid != InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_TABLE), - errmsg("relation \"%s\" already exists", relname))); - } - - /* Detach split partition. */ - RemoveInheritance(splitRel, rel, false); - /* Do the final part of detaching. */ - DetachPartitionFinalize(rel, splitRel, false, defaultPartOid); - - /* - * If new partition has the same name as split partition then we should - * rename split partition for reusing name. - */ - if (isSameName) - { - /* - * We must bump the command counter to make the split partition tuple - * visible for renaming. - */ - CommandCounterIncrement(); - /* Rename partition. */ - sprintf(tmpRelName, "split-%u-%X-tmp", RelationGetRelid(rel), MyProcPid); - RenameRelationInternal(splitRelOid, tmpRelName, false, false); - - /* - * We must bump the command counter to make the split partition tuple - * visible after renaming. - */ - CommandCounterIncrement(); - } - - /* Create new partitions (like split partition), without indexes. */ - foreach(listptr, cmd->partlist) - { - SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); - Relation newPartRel; - - newPartRel = createPartitionTable(sps->name, rel, context); - newPartRels = lappend(newPartRels, newPartRel); - } - - /* Copy data from split partition to new partitions. */ - moveSplitTableRows(rel, splitRel, cmd->partlist, newPartRels, defaultPartOid); - /* Keep the lock until commit. */ - table_close(splitRel, NoLock); - - /* Attach new partitions to partitioned table. */ - forboth(listptr, cmd->partlist, listptr2, newPartRels) - { - SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); - Relation newPartRel = (Relation) lfirst(listptr2); - - /* - * wqueue = NULL: verification for each cloned constraint is not - * needed. - */ - attachPartitionTable(NULL, rel, newPartRel, sps->bound); - /* Keep the lock until commit. */ - table_close(newPartRel, NoLock); - } - - /* Drop split partition. */ - object.classId = RelationRelationId; - object.objectId = splitRelOid; - object.objectSubId = 0; - /* Probably DROP_CASCADE is not needed. */ - performDeletion(&object, DROP_RESTRICT, 0); -} - -/* - * moveMergedTablesRows: scan partitions to be merged (mergingPartitionsList) - * of the partitioned table (rel) and move rows into the new partition - * (newPartRel). - */ -static void -moveMergedTablesRows(Relation rel, List *mergingPartitionsList, - Relation newPartRel) -{ - CommandId mycid; - - /* The FSM is empty, so don't bother using it. */ - int ti_options = TABLE_INSERT_SKIP_FSM; - ListCell *listptr; - BulkInsertState bistate; /* state of bulk inserts for partition */ - TupleTableSlot *dstslot; - - mycid = GetCurrentCommandId(true); - - /* Prepare a BulkInsertState for table_tuple_insert. */ - bistate = GetBulkInsertState(); - - /* Create necessary tuple slot. */ - dstslot = MakeSingleTupleTableSlot(RelationGetDescr(newPartRel), - table_slot_callbacks(newPartRel)); - ExecStoreAllNullTuple(dstslot); - - foreach(listptr, mergingPartitionsList) - { - Relation mergingPartition = (Relation) lfirst(listptr); - TupleTableSlot *srcslot; - TupleConversionMap *tuple_map; - TableScanDesc scan; - Snapshot snapshot; - - /* Create tuple slot for new partition. */ - srcslot = MakeSingleTupleTableSlot(RelationGetDescr(mergingPartition), - table_slot_callbacks(mergingPartition)); - - /* - * Map computing for moving attributes of merged partition to new - * partition. - */ - tuple_map = convert_tuples_by_name(RelationGetDescr(mergingPartition), - RelationGetDescr(newPartRel)); - - /* Scan through the rows. */ - snapshot = RegisterSnapshot(GetLatestSnapshot()); - scan = table_beginscan(mergingPartition, snapshot, 0, NULL); - - while (table_scan_getnextslot(scan, ForwardScanDirection, srcslot)) - { - TupleTableSlot *insertslot; - - /* Extract data from old tuple. */ - slot_getallattrs(srcslot); - - if (tuple_map) - { - /* Need to use map to copy attributes. */ - insertslot = execute_attr_map_slot(tuple_map->attrMap, srcslot, dstslot); - } - else - { - /* Copy attributes directly. */ - insertslot = dstslot; - - ExecClearTuple(insertslot); - - memcpy(insertslot->tts_values, srcslot->tts_values, - sizeof(Datum) * srcslot->tts_nvalid); - memcpy(insertslot->tts_isnull, srcslot->tts_isnull, - sizeof(bool) * srcslot->tts_nvalid); - - ExecStoreVirtualTuple(insertslot); - } - - /* Write the tuple out to the new relation. */ - table_tuple_insert(newPartRel, insertslot, mycid, - ti_options, bistate); - - CHECK_FOR_INTERRUPTS(); - } - - table_endscan(scan); - UnregisterSnapshot(snapshot); - - if (tuple_map) - free_conversion_map(tuple_map); - - ExecDropSingleTupleTableSlot(srcslot); - } - - ExecDropSingleTupleTableSlot(dstslot); - FreeBulkInsertState(bistate); - - table_finish_bulk_insert(newPartRel, ti_options); -} - -/* - * ALTER TABLE MERGE PARTITIONS INTO - */ -static void -ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, - PartitionCmd *cmd, AlterTableUtilityContext *context) -{ - Relation newPartRel; - ListCell *listptr; - List *mergingPartitionsList = NIL; - Oid defaultPartOid; - Oid namespaceId; - Oid existingRelid; - - /* - * Lock all merged partitions, check them and create list with partitions - * contexts. - */ - foreach(listptr, cmd->partlist) - { - RangeVar *name = (RangeVar *) lfirst(listptr); - Relation mergingPartition; - - /* - * We are going to detach and remove this partition: need to use - * exclusive lock for preventing DML-queries to the partition. - */ - mergingPartition = table_openrv(name, AccessExclusiveLock); - - /* Store a next merging partition into the list. */ - mergingPartitionsList = lappend(mergingPartitionsList, - mergingPartition); - } - - /* - * Look up the namespace in which we are supposed to create the partition, - * check we have permission to create there, lock it against concurrent - * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary - * namespace is selected. - */ - cmd->name->relpersistence = rel->rd_rel->relpersistence; - namespaceId = - RangeVarGetAndCheckCreationNamespace(cmd->name, NoLock, NULL); - - /* - * Check if this name is already taken. This helps us to detect the - * situation when one of the merging partitions has the same name as the - * new partition. Otherwise, this would fail later on anyway but catching - * this here allows us to emit a nicer error message. - */ - existingRelid = get_relname_relid(cmd->name->relname, namespaceId); - - if (OidIsValid(existingRelid)) - { - Relation sameNamePartition = NULL; - - foreach_ptr(RelationData, mergingPartition, mergingPartitionsList) - { - if (RelationGetRelid(mergingPartition) == existingRelid) - { - sameNamePartition = mergingPartition; - break; - } - } - - if (sameNamePartition) - { - /* - * The new partition has the same name as one of merging - * partitions. - */ - char tmpRelName[NAMEDATALEN]; - - /* Generate temporary name. */ - sprintf(tmpRelName, "merge-%u-%X-tmp", RelationGetRelid(rel), MyProcPid); - - /* - * Rename the existing partition with a temporary name, leaving it - * free for the new partition. We don't need to care about this - * in the future because we're going to eventually drop the - * existing partition anyway. - */ - RenameRelationInternal(RelationGetRelid(sameNamePartition), - tmpRelName, false, false); - - /* - * We must bump the command counter to make the new partition - * tuple visible for rename. - */ - CommandCounterIncrement(); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_TABLE), - errmsg("relation \"%s\" already exists", cmd->name->relname))); - } - } - - /* Detach all merged partitions. */ - defaultPartOid = - get_default_oid_from_partdesc(RelationGetPartitionDesc(rel, true)); - foreach(listptr, mergingPartitionsList) - { - Relation mergingPartition = (Relation) lfirst(listptr); - - /* Remove the pg_inherits row first. */ - RemoveInheritance(mergingPartition, rel, false); - /* Do the final part of detaching. */ - DetachPartitionFinalize(rel, mergingPartition, false, defaultPartOid); - } - - /* Create table for new partition, use partitioned table as model. */ - newPartRel = createPartitionTable(cmd->name, rel, context); - - /* Copy data from merged partitions to new partition. */ - moveMergedTablesRows(rel, mergingPartitionsList, newPartRel); - - /* Drop the current partitions before attaching the new one. */ - foreach(listptr, mergingPartitionsList) - { - ObjectAddress object; - Relation mergingPartition = (Relation) lfirst(listptr); - - /* Get relation id before table_close() call. */ - object.objectId = RelationGetRelid(mergingPartition); - object.classId = RelationRelationId; - object.objectSubId = 0; - - /* Keep the lock until commit. */ - table_close(mergingPartition, NoLock); - - performDeletion(&object, DROP_RESTRICT, 0); - } - list_free(mergingPartitionsList); - - /* - * Attach a new partition to the partitioned table. wqueue = NULL: - * verification for each cloned constraint is not needed. - */ - attachPartitionTable(NULL, rel, newPartRel, cmd->bound); - - /* Keep the lock until commit. */ - table_close(newPartRel, NoLock); -} diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 113b480731595..a9005cc7212b6 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -35,7 +35,7 @@ * and munge the system catalogs of the new database. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -363,9 +363,9 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) xlrec.ts_id = tablespaceoid; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, + XLogRegisterData(&xlrec, offsetof(xl_tblspc_create_rec, ts_path)); - XLogRegisterData((char *) location, strlen(location) + 1); + XLogRegisterData(location, strlen(location) + 1); (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE); } @@ -533,7 +533,7 @@ DropTableSpace(DropTableSpaceStmt *stmt) xlrec.ts_id = tablespaceoid; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(xl_tblspc_drop_rec)); + XLogRegisterData(&xlrec, sizeof(xl_tblspc_drop_rec)); (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP); } @@ -576,7 +576,7 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid) struct stat st; bool in_place; - linkloc = psprintf("pg_tblspc/%u", tablespaceoid); + linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, tablespaceoid); /* * If we're asked to make an 'in place' tablespace, create the directory @@ -692,7 +692,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo) char *subfile; struct stat st; - linkloc_with_version_dir = psprintf("pg_tblspc/%u/%s", tablespaceoid, + linkloc_with_version_dir = psprintf("%s/%u/%s", PG_TBLSPC_DIR, tablespaceoid, TABLESPACE_VERSION_DIRECTORY); /* @@ -1290,7 +1290,7 @@ check_temp_tablespaces(char **newval, void **extra, GucSource source) return false; myextra->numSpcs = numSpcs; memcpy(myextra->tblSpcs, tblSpcs, numSpcs * sizeof(Oid)); - *extra = (void *) myextra; + *extra = myextra; pfree(tblSpcs); } diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 170360edda8cc..67f8e70f9c166 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -3,7 +3,7 @@ * trigger.c * PostgreSQL TRIGGERs support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -43,6 +43,7 @@ #include "parser/parse_relation.h" #include "partitioning/partdesc.h" #include "pgstat.h" +#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" #include "storage/lmgr.h" #include "utils/acl.h" @@ -101,6 +102,7 @@ static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, bool is_crosspart_update); static void AfterTriggerEnlargeQueryState(void); static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType); +static HeapTuple check_modified_virtual_generated(TupleDesc tupdesc, HeapTuple tuple); /* @@ -641,7 +643,8 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, if (TRIGGER_FOR_BEFORE(tgtype) && var->varattno == 0 && RelationGetDescr(rel)->constr && - RelationGetDescr(rel)->constr->has_generated_stored) + (RelationGetDescr(rel)->constr->has_generated_stored || + RelationGetDescr(rel)->constr->has_generated_virtual)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"), @@ -809,6 +812,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, CONSTRAINT_TRIGGER, stmt->deferrable, stmt->initdeferred, + true, /* Is Enforced */ true, InvalidOid, /* no parent */ RelationGetRelid(rel), @@ -834,6 +838,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, true, /* islocal */ 0, /* inhcount */ true, /* noinherit */ + false, /* conperiod */ isInternal); /* is_internal */ } @@ -1168,7 +1173,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, * Initialize our fabricated parse node by copying the original * one, then resetting fields that we pass separately. */ - childStmt = (CreateTrigStmt *) copyObject(stmt); + childStmt = copyObject(stmt); childStmt->funcname = NIL; childStmt->whenClause = NULL; @@ -2502,6 +2507,8 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, } else if (newtuple != oldtuple) { + newtuple = check_modified_virtual_generated(RelationGetDescr(relinfo->ri_RelationDesc), newtuple); + ExecForceStoreHeapTuple(newtuple, slot, false); /* @@ -3059,6 +3066,8 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, } else if (newtuple != oldtuple) { + newtuple = check_modified_virtual_generated(RelationGetDescr(relinfo->ri_RelationDesc), newtuple); + ExecForceStoreHeapTuple(newtuple, newslot, false); /* @@ -3489,6 +3498,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo, oldContext = MemoryContextSwitchTo(estate->es_query_cxt); tgqual = stringToNode(trigger->tgqual); + tgqual = expand_generated_columns_in_expr(tgqual, relinfo->ri_RelationDesc, PRS2_OLD_VARNO); + tgqual = expand_generated_columns_in_expr(tgqual, relinfo->ri_RelationDesc, PRS2_NEW_VARNO); /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */ ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0); ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0); @@ -3633,6 +3644,7 @@ typedef struct AfterTriggerSharedData TriggerEvent ats_event; /* event type indicator, see trigger.h */ Oid ats_tgoid; /* the trigger's ID */ Oid ats_relid; /* the relation it's on */ + Oid ats_rolid; /* role to execute the trigger */ CommandId ats_firing_id; /* ID for firing cycle */ struct AfterTriggersTableData *ats_table; /* transition table access */ Bitmapset *ats_modifiedcols; /* modified columns */ @@ -4004,13 +4016,6 @@ afterTriggerCopyBitmap(Bitmapset *src) if (src == NULL) return NULL; - /* Create event context if we didn't already */ - if (afterTriggers.event_cxt == NULL) - afterTriggers.event_cxt = - AllocSetContextCreate(TopTransactionContext, - "AfterTriggerEvents", - ALLOCSET_DEFAULT_SIZES); - oldcxt = MemoryContextSwitchTo(afterTriggers.event_cxt); dst = bms_copy(src); @@ -4096,8 +4101,11 @@ afterTriggerAddEvent(AfterTriggerEventList *events, chunk->endptr = chunk->endfree = (char *) chunk + chunksize; Assert(chunk->endfree - chunk->freeptr >= needed); - if (events->head == NULL) + if (events->tail == NULL) + { + Assert(events->head == NULL); events->head = chunk; + } else events->tail->next = chunk; events->tail = chunk; @@ -4106,22 +4114,30 @@ afterTriggerAddEvent(AfterTriggerEventList *events, /* * Try to locate a matching shared-data record already in the chunk. If - * none, make a new one. + * none, make a new one. The search begins with the most recently added + * record, since newer ones are most likely to match. */ - for (newshared = ((AfterTriggerShared) chunk->endptr) - 1; - (char *) newshared >= chunk->endfree; - newshared--) + for (newshared = (AfterTriggerShared) chunk->endfree; + (char *) newshared < chunk->endptr; + newshared++) { + /* compare fields roughly by probability of them being different */ if (newshared->ats_tgoid == evtshared->ats_tgoid && - newshared->ats_relid == evtshared->ats_relid && newshared->ats_event == evtshared->ats_event && + newshared->ats_firing_id == 0 && newshared->ats_table == evtshared->ats_table && - newshared->ats_firing_id == 0) + newshared->ats_relid == evtshared->ats_relid && + newshared->ats_rolid == evtshared->ats_rolid && + bms_equal(newshared->ats_modifiedcols, + evtshared->ats_modifiedcols)) break; } - if ((char *) newshared < chunk->endfree) + if ((char *) newshared >= chunk->endptr) { + newshared = ((AfterTriggerShared) chunk->endfree) - 1; *newshared = *evtshared; + /* now we must make a suitably-long-lived copy of the bitmap */ + newshared->ats_modifiedcols = afterTriggerCopyBitmap(evtshared->ats_modifiedcols); newshared->ats_firing_id = 0; /* just to be sure */ chunk->endfree = (char *) newshared; } @@ -4284,6 +4300,8 @@ AfterTriggerExecute(EState *estate, AfterTriggerShared evtshared = GetTriggerSharedData(event); Oid tgoid = evtshared->ats_tgoid; TriggerData LocTriggerData = {0}; + Oid save_rolid; + int save_sec_context; HeapTuple rettuple; int tgindx; bool should_free_trig = false; @@ -4487,6 +4505,17 @@ AfterTriggerExecute(EState *estate, MemoryContextReset(per_tuple_context); + /* + * If necessary, become the role that was active when the trigger got + * queued. Note that the role might have been dropped since the trigger + * was queued, but if that is a problem, we will get an error later. + * Checking here would still leave a race condition. + */ + GetUserIdAndSecContext(&save_rolid, &save_sec_context); + if (save_rolid != evtshared->ats_rolid) + SetUserIdAndSecContext(evtshared->ats_rolid, + save_sec_context | SECURITY_LOCAL_USERID_CHANGE); + /* * Call the trigger and throw away any possibly returned updated tuple. * (Don't let ExecCallTriggerFunc measure EXPLAIN time.) @@ -4501,6 +4530,10 @@ AfterTriggerExecute(EState *estate, rettuple != LocTriggerData.tg_newtuple) heap_freetuple(rettuple); + /* Restore the current role if necessary */ + if (save_rolid != evtshared->ats_rolid) + SetUserIdAndSecContext(save_rolid, save_sec_context); + /* * Release resources */ @@ -4967,10 +5000,10 @@ MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType) /* Now build the TransitionCaptureState struct, in caller's context */ state = (TransitionCaptureState *) palloc0(sizeof(TransitionCaptureState)); - state->tcs_delete_old_table = trigdesc->trig_delete_old_table; - state->tcs_update_old_table = trigdesc->trig_update_old_table; - state->tcs_update_new_table = trigdesc->trig_update_new_table; - state->tcs_insert_new_table = trigdesc->trig_insert_new_table; + state->tcs_delete_old_table = need_old_del; + state->tcs_update_old_table = need_old_upd; + state->tcs_update_new_table = need_new_upd; + state->tcs_insert_new_table = need_new_ins; state->tcs_private = table; return state; @@ -6426,13 +6459,14 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0); new_shared.ats_tgoid = trigger->tgoid; new_shared.ats_relid = RelationGetRelid(rel); + new_shared.ats_rolid = GetUserId(); new_shared.ats_firing_id = 0; if ((trigger->tgoldtable || trigger->tgnewtable) && transition_capture != NULL) new_shared.ats_table = transition_capture->tcs_private; else new_shared.ats_table = NULL; - new_shared.ats_modifiedcols = afterTriggerCopyBitmap(modifiedCols); + new_shared.ats_modifiedcols = modifiedCols; afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth].events, &new_event, &new_shared); @@ -6596,3 +6630,37 @@ pg_trigger_depth(PG_FUNCTION_ARGS) { PG_RETURN_INT32(MyTriggerDepth); } + +/* + * Check whether a trigger modified a virtual generated column and replace the + * value with null if so. + * + * We need to check this so that we don't end up storing a non-null value in a + * virtual generated column. + * + * We don't need to check for stored generated columns, since those will be + * overwritten later anyway. + */ +static HeapTuple +check_modified_virtual_generated(TupleDesc tupdesc, HeapTuple tuple) +{ + if (!(tupdesc->constr && tupdesc->constr->has_generated_virtual)) + return tuple; + + for (int i = 0; i < tupdesc->natts; i++) + { + if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + { + if (!heap_attisnull(tuple, i + 1, tupdesc)) + { + int replCol = i + 1; + Datum replValue = 0; + bool replIsnull = true; + + tuple = heap_modify_tuple_by_cols(tuple, tupdesc, 1, &replCol, &replValue, &replIsnull); + } + } + } + + return tuple; +} diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index b7b5019f1e07b..ab16d42ad56ba 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -4,7 +4,7 @@ * * Routines for tsearch manipulation commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 2a1e71333568e..45ae7472ab5ad 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -3,7 +3,7 @@ * typecmds.c * Routines for SQL commands that manipulate types (and domains). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -13,7 +13,7 @@ * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the * appropriate arguments/flags, passing the results to the - * corresponding "FooDefine" routines (in src/catalog) that do + * corresponding "FooCreate" routines (in src/backend/catalog) that do * the actual catalog-munging. These routines also verify permission * of the user to execute the command. * @@ -348,7 +348,7 @@ DefineType(ParseState *pstate, List *names, List *parameters) Type likeType; Form_pg_type likeForm; - likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL); + likeType = typenameType(pstate, defGetTypeName(likeTypeEl), NULL); likeForm = (Form_pg_type) GETSTRUCT(likeType); internalLength = likeForm->typlen; byValue = likeForm->typbyval; @@ -694,7 +694,7 @@ RemoveTypeById(Oid typeOid) * Registers a new domain. */ ObjectAddress -DefineDomain(CreateDomainStmt *stmt) +DefineDomain(ParseState *pstate, CreateDomainStmt *stmt) { char *domainName; char *domainArrayName; @@ -761,7 +761,7 @@ DefineDomain(CreateDomainStmt *stmt) /* * Look up the base type. */ - typeTup = typenameType(NULL, stmt->typeName, &basetypeMod); + typeTup = typenameType(pstate, stmt->typeName, &basetypeMod); baseType = (Form_pg_type) GETSTRUCT(typeTup); basetypeoid = baseType->oid; @@ -783,7 +783,8 @@ DefineDomain(CreateDomainStmt *stmt) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("\"%s\" is not a valid base type for a domain", - TypeNameToString(stmt->typeName)))); + TypeNameToString(stmt->typeName)), + parser_errposition(pstate, stmt->typeName->location))); aclresult = object_aclcheck(TypeRelationId, basetypeoid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) @@ -809,7 +810,8 @@ DefineDomain(CreateDomainStmt *stmt) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("collations are not supported by type %s", - format_type_be(basetypeoid)))); + format_type_be(basetypeoid)), + parser_errposition(pstate, stmt->typeName->location))); /* passed by value */ byValue = baseType->typbyval; @@ -879,18 +881,15 @@ DefineDomain(CreateDomainStmt *stmt) */ if (saw_default) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple default expressions"))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple default expressions"), + parser_errposition(pstate, constr->location)); saw_default = true; if (constr->raw_expr) { - ParseState *pstate; Node *defaultExpr; - /* Create a dummy ParseState for transformExpr */ - pstate = make_parsestate(NULL); - /* * Cook the constr->raw_expr into an expression. Note: * name is strictly for error message @@ -942,8 +941,14 @@ DefineDomain(CreateDomainStmt *stmt) case CONSTR_NOTNULL: if (nullDefined && !typNotNull) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting NULL/NOT NULL constraints"))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NULL/NOT NULL constraints"), + parser_errposition(pstate, constr->location)); + if (constr->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("not-null constraints for domains cannot be marked NO INHERIT"), + parser_errposition(pstate, constr->location)); typNotNull = true; nullDefined = true; break; @@ -951,8 +956,9 @@ DefineDomain(CreateDomainStmt *stmt) case CONSTR_NULL: if (nullDefined && typNotNull) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting NULL/NOT NULL constraints"))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NULL/NOT NULL constraints"), + parser_errposition(pstate, constr->location)); typNotNull = false; nullDefined = true; break; @@ -967,8 +973,10 @@ DefineDomain(CreateDomainStmt *stmt) */ if (constr->is_no_inherit) ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("check constraints for domains cannot be marked NO INHERIT"))); + errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("check constraints for domains cannot be marked NO INHERIT"), + parser_errposition(pstate, constr->location)); + break; /* @@ -976,26 +984,30 @@ DefineDomain(CreateDomainStmt *stmt) */ case CONSTR_UNIQUE: ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unique constraints not possible for domains"))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unique constraints not possible for domains"), + parser_errposition(pstate, constr->location)); break; case CONSTR_PRIMARY: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("primary key constraints not possible for domains"))); + errmsg("primary key constraints not possible for domains"), + parser_errposition(pstate, constr->location))); break; case CONSTR_EXCLUSION: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("exclusion constraints not possible for domains"))); + errmsg("exclusion constraints not possible for domains"), + parser_errposition(pstate, constr->location))); break; case CONSTR_FOREIGN: ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("foreign key constraints not possible for domains"))); + errmsg("foreign key constraints not possible for domains"), + parser_errposition(pstate, constr->location))); break; case CONSTR_ATTR_DEFERRABLE: @@ -1004,13 +1016,27 @@ DefineDomain(CreateDomainStmt *stmt) case CONSTR_ATTR_IMMEDIATE: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("specifying constraint deferrability not supported for domains"))); + errmsg("specifying constraint deferrability not supported for domains"), + parser_errposition(pstate, constr->location))); break; - default: - elog(ERROR, "unrecognized constraint subtype: %d", - (int) constr->contype); + case CONSTR_GENERATED: + case CONSTR_IDENTITY: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying GENERATED not supported for domains"), + parser_errposition(pstate, constr->location))); break; + + case CONSTR_ATTR_ENFORCED: + case CONSTR_ATTR_NOT_ENFORCED: + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("specifying constraint enforceability not supported for domains"), + parser_errposition(pstate, constr->location))); + break; + + /* no default, to let compiler warn about missing case */ } } @@ -1784,6 +1810,7 @@ makeRangeConstructors(const char *name, Oid namespace, PointerGetDatum(NULL), /* parameterNames */ NIL, /* parameterDefaults */ PointerGetDatum(NULL), /* trftypes */ + NIL, /* trfoids */ PointerGetDatum(NULL), /* proconfig */ InvalidOid, /* prosupport */ 1.0, /* procost */ @@ -1849,6 +1876,7 @@ makeMultirangeConstructors(const char *name, Oid namespace, PointerGetDatum(NULL), /* parameterNames */ NIL, /* parameterDefaults */ PointerGetDatum(NULL), /* trftypes */ + NIL, /* trfoids */ PointerGetDatum(NULL), /* proconfig */ InvalidOid, /* prosupport */ 1.0, /* procost */ @@ -1893,6 +1921,7 @@ makeMultirangeConstructors(const char *name, Oid namespace, PointerGetDatum(NULL), /* parameterNames */ NIL, /* parameterDefaults */ PointerGetDatum(NULL), /* trftypes */ + NIL, /* trfoids */ PointerGetDatum(NULL), /* proconfig */ InvalidOid, /* prosupport */ 1.0, /* procost */ @@ -1931,6 +1960,7 @@ makeMultirangeConstructors(const char *name, Oid namespace, PointerGetDatum(NULL), /* parameterNames */ NIL, /* parameterDefaults */ PointerGetDatum(NULL), /* trftypes */ + NIL, /* trfoids */ PointerGetDatum(NULL), /* proconfig */ InvalidOid, /* prosupport */ 1.0, /* procost */ @@ -2927,51 +2957,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint, constr = (Constraint *) newConstraint; - switch (constr->contype) - { - case CONSTR_CHECK: - case CONSTR_NOTNULL: - /* processed below */ - break; - - case CONSTR_UNIQUE: - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unique constraints not possible for domains"))); - break; - - case CONSTR_PRIMARY: - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("primary key constraints not possible for domains"))); - break; - - case CONSTR_EXCLUSION: - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("exclusion constraints not possible for domains"))); - break; - - case CONSTR_FOREIGN: - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("foreign key constraints not possible for domains"))); - break; - - case CONSTR_ATTR_DEFERRABLE: - case CONSTR_ATTR_NOT_DEFERRABLE: - case CONSTR_ATTR_DEFERRED: - case CONSTR_ATTR_IMMEDIATE: - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("specifying constraint deferrability not supported for domains"))); - break; - - default: - elog(ERROR, "unrecognized constraint subtype: %d", - (int) constr->contype); - break; - } + /* enforced by parser */ + Assert(constr->contype == CONSTR_CHECK || constr->contype == CONSTR_NOTNULL); if (constr->contype == CONSTR_CHECK) { @@ -3558,7 +3545,7 @@ domainAddCheckConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, domVal->location = -1; /* will be set when/if used */ pstate->p_pre_columnref_hook = replace_domain_constraint_value; - pstate->p_ref_hook_state = (void *) domVal; + pstate->p_ref_hook_state = domVal; expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK); @@ -3596,6 +3583,7 @@ domainAddCheckConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, CONSTRAINT_CHECK, /* Constraint Type */ false, /* Is Deferrable */ false, /* Is Deferred */ + true, /* Is Enforced */ !constr->skip_validation, /* Is Validated */ InvalidOid, /* no parent constraint */ InvalidOid, /* not a relation constraint */ @@ -3621,6 +3609,7 @@ domainAddCheckConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, true, /* is local */ 0, /* inhcount */ false, /* connoinherit */ + false, /* conperiod */ false); /* is_internal */ if (constrAddr) ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid); @@ -3702,6 +3691,7 @@ domainAddNotNullConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, CONSTRAINT_NOTNULL, /* Constraint Type */ false, /* Is Deferrable */ false, /* Is Deferred */ + true, /* Is Enforced */ !constr->skip_validation, /* Is Validated */ InvalidOid, /* no parent constraint */ InvalidOid, /* not a relation constraint */ @@ -3727,6 +3717,7 @@ domainAddNotNullConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, true, /* is local */ 0, /* inhcount */ false, /* connoinherit */ + false, /* conperiod */ false); /* is_internal */ if (constrAddr) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index e7ade898a4782..0d638e29d0066 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -3,7 +3,7 @@ * user.c * Commands for manipulating roles (formerly called users). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/commands/user.c @@ -30,6 +30,7 @@ #include "commands/defrem.h" #include "commands/seclabel.h" #include "commands/user.h" +#include "lib/qunique.h" #include "libpq/crypt.h" #include "miscadmin.h" #include "storage/lmgr.h" @@ -489,8 +490,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) * Advance command counter so we can see new record; else tests in * AddRoleMems may fail. */ - if (addroleto || adminmembers || rolemembers) - CommandCounterIncrement(); + CommandCounterIncrement(); /* Default grant. */ InitGrantRoleOptions(&popt); @@ -817,12 +817,12 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) "BYPASSRLS", "BYPASSRLS"))); } - /* To add members to a role, you need ADMIN OPTION. */ + /* To add or drop members, you need ADMIN OPTION. */ if (drolemembers && !is_admin_of_role(currentUserId, roleid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to alter role"), - errdetail("Only roles with the %s option on role \"%s\" may add members.", + errdetail("Only roles with the %s option on role \"%s\" may add or drop members.", "ADMIN", rolename))); /* Convert validuntil to internal form */ @@ -1904,7 +1904,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, else { Oid objectId; - Oid *newmembers = palloc(sizeof(Oid)); + Oid *newmembers = (Oid *) palloc(3 * sizeof(Oid)); + int nnewmembers; /* * The values for these options can be taken directly from 'popt'. @@ -1946,12 +1947,22 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, new_record, new_record_nulls); CatalogTupleInsert(pg_authmem_rel, tuple); - /* updateAclDependencies wants to pfree array inputs */ - newmembers[0] = grantorId; + /* + * Record dependencies on the roleid, member, and grantor, as if a + * pg_auth_members entry were an object ACL. + * updateAclDependencies() requires an input array that is + * palloc'd (it will free it), sorted, and de-duped. + */ + newmembers[0] = roleid; + newmembers[1] = memberid; + newmembers[2] = grantorId; + qsort(newmembers, 3, sizeof(Oid), oid_cmp); + nnewmembers = qunique(newmembers, 3, sizeof(Oid), oid_cmp); + updateAclDependencies(AuthMemRelationId, objectId, 0, InvalidOid, 0, NULL, - 1, newmembers); + nnewmembers, newmembers); } /* CCI after each change, in case there are duplicates in list */ @@ -2555,6 +2566,8 @@ check_createrole_self_grant(char **newval, void **extra, GucSource source) list_free(elemlist); result = (unsigned *) guc_malloc(LOG, sizeof(unsigned)); + if (!result) + return false; *result = options; *extra = result; diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 48f8eab202264..33a33bf6b1cfa 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -12,7 +12,7 @@ * CLUSTER, handled in cluster.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -34,12 +34,12 @@ #include "access/tableam.h" #include "access/transam.h" #include "access/xact.h" -#include "catalog/index.h" #include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_inherits.h" #include "commands/cluster.h" #include "commands/defrem.h" +#include "commands/progress.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -60,6 +60,12 @@ #include "utils/snapmgr.h" #include "utils/syscache.h" +/* + * Minimum interval for cost-based vacuum delay reports from a parallel worker. + * This aims to avoid sending too many messages and waking up the leader too + * frequently. + */ +#define PARALLEL_VACUUM_DELAY_REPORT_INTERVAL_NS (NS_PER_S) /* * GUC parameters @@ -70,6 +76,9 @@ int vacuum_multixact_freeze_min_age; int vacuum_multixact_freeze_table_age; int vacuum_failsafe_age; int vacuum_multixact_failsafe_age; +double vacuum_max_eager_freeze_failure_rate; +bool track_cost_delay_timing; +bool vacuum_truncate; /* * Variables for cost-based vacuum delay. The defaults differ between @@ -80,6 +89,9 @@ int vacuum_multixact_failsafe_age; double vacuum_cost_delay = 0; int vacuum_cost_limit = 200; +/* Variable for reporting cost-based vacuum delay from parallel workers. */ +int64 parallel_vacuum_worker_delay_ns = 0; + /* * VacuumFailsafeActive is a defined as a global so that we can determine * whether or not to re-enable cost-based vacuum delay when vacuuming a table. @@ -131,7 +143,8 @@ check_vacuum_buffer_usage_limit(int *newval, void **extra, return true; /* Value does not fall within any allowable range */ - GUC_check_errdetail("\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB", + GUC_check_errdetail("\"%s\" must be 0 or between %d kB and %d kB.", + "vacuum_buffer_usage_limit", MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB); return false; @@ -405,6 +418,11 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel) /* user-invoked vacuum uses VACOPT_VERBOSE instead of log_min_duration */ params.log_min_duration = -1; + /* + * Later, in vacuum_rel(), we check if a reloption override was specified. + */ + params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate; + /* * Create special memory context for cross-transaction storage. * @@ -603,9 +621,6 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, VacuumFailsafeActive = false; VacuumUpdateCosts(); VacuumCostBalance = 0; - VacuumPageHit = 0; - VacuumPageMiss = 0; - VacuumPageDirty = 0; VacuumCostBalanceLocal = 0; VacuumSharedCostBalance = NULL; VacuumActiveNWorkers = NULL; @@ -642,6 +657,8 @@ vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, if (use_own_xacts) { PopActiveSnapshot(); + /* standard_ProcessUtility() does CCI if !use_own_xacts */ + CommandCounterIncrement(); CommitTransactionCommand(); } else @@ -854,7 +871,7 @@ vacuum_open_relation(Oid relid, RangeVar *relation, bits32 options, /* * Given a VacuumRelation, fill in the table OID if it wasn't specified, - * and optionally add VacuumRelations for partitions of the table. + * and optionally add VacuumRelations for partitions or inheritance children. * * If a VacuumRelation does not have an OID supplied and is a partitioned * table, an extra entry will be added to the output for each partition. @@ -882,11 +899,15 @@ expand_vacuum_rel(VacuumRelation *vrel, MemoryContext vac_context, } else { - /* Process a specific relation, and possibly partitions thereof */ + /* + * Process a specific relation, and possibly partitions or child + * tables thereof. + */ Oid relid; HeapTuple tuple; Form_pg_class classForm; - bool include_parts; + bool include_children; + bool is_partitioned_table; int rvr_opts; /* @@ -947,20 +968,31 @@ expand_vacuum_rel(VacuumRelation *vrel, MemoryContext vac_context, MemoryContextSwitchTo(oldcontext); } + /* + * Vacuuming a partitioned table with ONLY will not do anything since + * the partitioned table itself is empty. Issue a warning if the user + * requests this. + */ + include_children = vrel->relation->inh; + is_partitioned_table = (classForm->relkind == RELKIND_PARTITIONED_TABLE); + if ((options & VACOPT_VACUUM) && is_partitioned_table && !include_children) + ereport(WARNING, + (errmsg("VACUUM ONLY of partitioned table \"%s\" has no effect", + vrel->relation->relname))); - include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE); ReleaseSysCache(tuple); /* - * If it is, make relation list entries for its partitions. Note that - * the list returned by find_all_inheritors() includes the passed-in - * OID, so we have to skip that. There's no point in taking locks on - * the individual partitions yet, and doing so would just add - * unnecessary deadlock risk. For this last reason we do not check - * yet the ownership of the partitions, which get added to the list to - * process. Ownership will be checked later on anyway. + * Unless the user has specified ONLY, make relation list entries for + * its partitions or inheritance child tables. Note that the list + * returned by find_all_inheritors() includes the passed-in OID, so we + * have to skip that. There's no point in taking locks on the + * individual partitions or child tables yet, and doing so would just + * add unnecessary deadlock risk. For this last reason, we do not yet + * check the ownership of the partitions/tables, which get added to + * the list to process. Ownership will be checked later on anyway. */ - if (include_parts) + if (include_children) { List *part_oids = find_all_inheritors(relid, NoLock, NULL); ListCell *part_lc; @@ -1398,6 +1430,7 @@ void vac_update_relstats(Relation relation, BlockNumber num_pages, double num_tuples, BlockNumber num_all_visible_pages, + BlockNumber num_all_frozen_pages, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, bool *frozenxid_updated, bool *minmulti_updated, @@ -1405,7 +1438,9 @@ vac_update_relstats(Relation relation, { Oid relid = RelationGetRelid(relation); Relation rd; + ScanKeyData key[1]; HeapTuple ctup; + void *inplace_state; Form_pg_class pgcform; bool dirty, futurexid, @@ -1416,7 +1451,12 @@ vac_update_relstats(Relation relation, rd = table_open(RelationRelationId, RowExclusiveLock); /* Fetch a copy of the tuple to scribble on */ - ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); + ScanKeyInit(&key[0], + Anum_pg_class_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + systable_inplace_update_begin(rd, ClassOidIndexId, true, + NULL, 1, key, &ctup, &inplace_state); if (!HeapTupleIsValid(ctup)) elog(ERROR, "pg_class entry for relid %u vanished during vacuuming", relid); @@ -1440,6 +1480,11 @@ vac_update_relstats(Relation relation, pgcform->relallvisible = (int32) num_all_visible_pages; dirty = true; } + if (pgcform->relallfrozen != (int32) num_all_frozen_pages) + { + pgcform->relallfrozen = (int32) num_all_frozen_pages; + dirty = true; + } /* Apply DDL updates, but not inside an outer transaction (see above) */ @@ -1524,7 +1569,9 @@ vac_update_relstats(Relation relation, /* If anything changed, write out the tuple. */ if (dirty) - heap_inplace_update(rd, ctup); + systable_inplace_update_finish(inplace_state, ctup); + else + systable_inplace_update_cancel(inplace_state); table_close(rd, RowExclusiveLock); @@ -1576,6 +1623,7 @@ vac_update_datfrozenxid(void) bool bogus = false; bool dirty = false; ScanKeyData key[1]; + void *inplace_state; /* * Restrict this task to one backend per database. This avoids race @@ -1699,20 +1747,18 @@ vac_update_datfrozenxid(void) relation = table_open(DatabaseRelationId, RowExclusiveLock); /* - * Get the pg_database tuple to scribble on. Note that this does not - * directly rely on the syscache to avoid issues with flattened toast - * values for the in-place update. + * Fetch a copy of the tuple to scribble on. We could check the syscache + * tuple first. If that concluded !dirty, we'd avoid waiting on + * concurrent heap_update() and would avoid exclusive-locking the buffer. + * For now, don't optimize that. */ ScanKeyInit(&key[0], Anum_pg_database_oid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(MyDatabaseId)); - scan = systable_beginscan(relation, DatabaseOidIndexId, true, - NULL, 1, key); - tuple = systable_getnext(scan); - tuple = heap_copytuple(tuple); - systable_endscan(scan); + systable_inplace_update_begin(relation, DatabaseOidIndexId, true, + NULL, 1, key, &tuple, &inplace_state); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for database %u", MyDatabaseId); @@ -1746,7 +1792,9 @@ vac_update_datfrozenxid(void) newMinMulti = dbform->datminmxid; if (dirty) - heap_inplace_update(relation, tuple); + systable_inplace_update_finish(inplace_state, tuple); + else + systable_inplace_update_cancel(inplace_state); heap_freetuple(tuple); table_close(relation, RowExclusiveLock); @@ -2144,13 +2192,30 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, } /* - * Set truncate option based on truncate reloption if it wasn't specified - * in VACUUM command, or when running in an autovacuum worker + * Check if the vacuum_max_eager_freeze_failure_rate table storage + * parameter was specified. This overrides the GUC value. + */ + if (rel->rd_options != NULL && + ((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0) + params->max_eager_freeze_failure_rate = + ((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate; + + /* + * Set truncate option based on truncate reloption or GUC if it wasn't + * specified in VACUUM command, or when running in an autovacuum worker */ if (params->truncate == VACOPTVALUE_UNSPECIFIED) { - if (rel->rd_options == NULL || - ((StdRdOptions *) rel->rd_options)->vacuum_truncate) + StdRdOptions *opts = (StdRdOptions *) rel->rd_options; + + if (opts && opts->vacuum_truncate_set) + { + if (opts->vacuum_truncate) + params->truncate = VACOPTVALUE_ENABLED; + else + params->truncate = VACOPTVALUE_DISABLED; + } + else if (vacuum_truncate) params->truncate = VACOPTVALUE_ENABLED; else params->truncate = VACOPTVALUE_DISABLED; @@ -2196,15 +2261,14 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, { ClusterParams cluster_params = {0}; - /* close relation before vacuuming, but hold lock until commit */ - relation_close(rel, NoLock); - rel = NULL; - if ((params->options & VACOPT_VERBOSE) != 0) cluster_params.options |= CLUOPT_VERBOSE; /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */ - cluster_rel(relid, InvalidOid, &cluster_params); + cluster_rel(rel, InvalidOid, &cluster_params); + /* cluster_rel closes the relation, but keeps lock */ + + rel = NULL; } else table_relation_vacuum(rel, params, bstrategy); @@ -2337,7 +2401,7 @@ vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode) * typically once per page processed. */ void -vacuum_delay_point(void) +vacuum_delay_point(bool is_analyze) { double msec = 0; @@ -2380,13 +2444,66 @@ vacuum_delay_point(void) /* Nap if appropriate */ if (msec > 0) { + instr_time delay_start; + if (msec > vacuum_cost_delay * 4) msec = vacuum_cost_delay * 4; + if (track_cost_delay_timing) + INSTR_TIME_SET_CURRENT(delay_start); + pgstat_report_wait_start(WAIT_EVENT_VACUUM_DELAY); pg_usleep(msec * 1000); pgstat_report_wait_end(); + if (track_cost_delay_timing) + { + instr_time delay_end; + instr_time delay; + + INSTR_TIME_SET_CURRENT(delay_end); + INSTR_TIME_SET_ZERO(delay); + INSTR_TIME_ACCUM_DIFF(delay, delay_end, delay_start); + + /* + * For parallel workers, we only report the delay time every once + * in a while to avoid overloading the leader with messages and + * interrupts. + */ + if (IsParallelWorker()) + { + static instr_time last_report_time; + instr_time time_since_last_report; + + Assert(!is_analyze); + + /* Accumulate the delay time */ + parallel_vacuum_worker_delay_ns += INSTR_TIME_GET_NANOSEC(delay); + + /* Calculate interval since last report */ + INSTR_TIME_SET_ZERO(time_since_last_report); + INSTR_TIME_ACCUM_DIFF(time_since_last_report, delay_end, last_report_time); + + /* If we haven't reported in a while, do so now */ + if (INSTR_TIME_GET_NANOSEC(time_since_last_report) >= + PARALLEL_VACUUM_DELAY_REPORT_INTERVAL_NS) + { + pgstat_progress_parallel_incr_param(PROGRESS_VACUUM_DELAY_TIME, + parallel_vacuum_worker_delay_ns); + + /* Reset variables */ + last_report_time = delay_end; + parallel_vacuum_worker_delay_ns = 0; + } + } + else if (is_analyze) + pgstat_progress_incr_param(PROGRESS_ANALYZE_DELAY_TIME, + INSTR_TIME_GET_NANOSEC(delay)); + else + pgstat_progress_incr_param(PROGRESS_VACUUM_DELAY_TIME, + INSTR_TIME_GET_NANOSEC(delay)); + } + /* * We don't want to ignore postmaster death during very long vacuums * with vacuum_cost_delay configured. We can't use the usual @@ -2496,12 +2613,12 @@ vac_bulkdel_one_index(IndexVacuumInfo *ivinfo, IndexBulkDeleteResult *istat, { /* Do bulk deletion */ istat = index_bulk_delete(ivinfo, istat, vac_tid_reaped, - (void *) dead_items); + dead_items); ereport(ivinfo->message_level, - (errmsg("scanned index \"%s\" to remove %lld row versions", + (errmsg("scanned index \"%s\" to remove %" PRId64 " row versions", RelationGetRelationName(ivinfo->index), - (long long) dead_items_info->num_items))); + dead_items_info->num_items))); return istat; } diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index f26070bff2a12..0feea1d30ec36 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -16,7 +16,7 @@ * the parallel context is re-initialized so that the same DSM can be used for * multiple passes of index bulk-deletion and index cleanup. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -57,12 +57,13 @@ typedef struct PVShared { /* - * Target table relid and log level (for messages about parallel workers - * launched during VACUUM VERBOSE). These fields are not modified during - * the parallel vacuum. + * Target table relid, log level (for messages about parallel workers + * launched during VACUUM VERBOSE) and query ID. These fields are not + * modified during the parallel vacuum. */ Oid relid; int elevel; + int64 queryid; /* * Fields for both index vacuum and cleanup. @@ -369,11 +370,12 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes, MemSet(shared, 0, est_shared_len); shared->relid = RelationGetRelid(rel); shared->elevel = elevel; + shared->queryid = pgstat_get_my_query_id(); shared->maintenance_work_mem_worker = (nindexes_mwm > 0) ? maintenance_work_mem / Min(parallel_workers, nindexes_mwm) : maintenance_work_mem; - shared->dead_items_info.max_bytes = vac_work_mem * 1024L; + shared->dead_items_info.max_bytes = vac_work_mem * (size_t) 1024; /* Prepare DSA space for dead items */ dead_items = TidStoreCreateShared(shared->dead_items_info.max_bytes, @@ -472,7 +474,6 @@ parallel_vacuum_get_dead_items(ParallelVacuumState *pvs, VacDeadItemsInfo **dead void parallel_vacuum_reset_dead_items(ParallelVacuumState *pvs) { - TidStore *dead_items = pvs->dead_items; VacDeadItemsInfo *dead_items_info = &(pvs->shared->dead_items_info); /* @@ -480,13 +481,13 @@ parallel_vacuum_reset_dead_items(ParallelVacuumState *pvs) * operating system. Then we recreate the tidstore with the same max_bytes * limitation we just used. */ - TidStoreDestroy(dead_items); + TidStoreDestroy(pvs->dead_items); pvs->dead_items = TidStoreCreateShared(dead_items_info->max_bytes, LWTRANCHE_PARALLEL_VACUUM_DSA); /* Update the DSA pointer for dead_items to the new one */ - pvs->shared->dead_items_dsa_handle = dsa_get_handle(TidStoreGetDSA(dead_items)); - pvs->shared->dead_items_handle = TidStoreGetHandle(dead_items); + pvs->shared->dead_items_dsa_handle = dsa_get_handle(TidStoreGetDSA(pvs->dead_items)); + pvs->shared->dead_items_handle = TidStoreGetHandle(pvs->dead_items); /* Reset the counter */ dead_items_info->num_items = 0; @@ -1014,6 +1015,9 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) debug_query_string = sharedquery; pgstat_report_activity(STATE_RUNNING, debug_query_string); + /* Track query ID */ + pgstat_report_query_id(shared->queryid, false); + /* * Open table. The lock mode is the same as the leader process. It's * okay because the lock mode does not conflict among the parallel @@ -1028,6 +1032,13 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) vac_open_indexes(rel, RowExclusiveLock, &nindexes, &indrels); Assert(nindexes > 0); + /* + * Apply the desired value of maintenance_work_mem within this process. + * Really we should use SetConfigOption() to change a GUC, but since we're + * already in parallel mode guc.c would complain about that. Fortunately, + * by the same token guc.c will not let any user-defined code change it. + * So just avert your eyes while we do this: + */ if (shared->maintenance_work_mem_worker > 0) maintenance_work_mem = shared->maintenance_work_mem_worker; @@ -1043,9 +1054,6 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) /* Set cost-based vacuum delay */ VacuumUpdateCosts(); VacuumCostBalance = 0; - VacuumPageHit = 0; - VacuumPageMiss = 0; - VacuumPageDirty = 0; VacuumCostBalanceLocal = 0; VacuumSharedCostBalance = &(shared->cost_balance); VacuumActiveNWorkers = &(shared->active_nworkers); @@ -1086,6 +1094,11 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc) InstrEndParallelQuery(&buffer_usage[ParallelWorkerNumber], &wal_usage[ParallelWorkerNumber]); + /* Report any remaining cost-based vacuum delay time */ + if (track_cost_delay_timing) + pgstat_progress_parallel_incr_param(PROGRESS_VACUUM_DELAY_TIME, + parallel_vacuum_worker_delay_ns); + TidStoreDetach(dead_items); /* Pop the error context stack */ diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index f44d942aa4d45..608f10d9412da 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -4,7 +4,7 @@ * Routines for handling specialized SET variables. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -182,7 +182,7 @@ check_datestyle(char **newval, void **extra, GucSource source) if (!ok) { - GUC_check_errdetail("Conflicting \"datestyle\" specifications."); + GUC_check_errdetail("Conflicting \"DateStyle\" specifications."); return false; } @@ -232,7 +232,7 @@ check_datestyle(char **newval, void **extra, GucSource source) return false; myextra[0] = newDateStyle; myextra[1] = newDateOrder; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -381,6 +381,8 @@ void assign_timezone(const char *newval, void *extra) { session_timezone = *((pg_tz **) extra); + /* datetime.c's cache of timezone abbrevs may now be obsolete */ + ClearTimeZoneAbbrevCache(); } /* @@ -479,7 +481,7 @@ show_log_timezone(void) */ /* - * GUC check_hook for assign_timezone_abbreviations + * GUC check_hook for timezone_abbreviations */ bool check_timezone_abbreviations(char **newval, void **extra, GucSource source) @@ -511,7 +513,7 @@ check_timezone_abbreviations(char **newval, void **extra, GucSource source) } /* - * GUC assign_hook for assign_timezone_abbreviations + * GUC assign_hook for timezone_abbreviations */ void assign_timezone_abbreviations(const char *newval, void *extra) @@ -577,14 +579,16 @@ check_transaction_read_only(bool *newval, void **extra, GucSource source) * We allow idempotent changes at any time, but otherwise this can only be * changed in a toplevel transaction that has not yet taken a snapshot. * - * As in check_transaction_read_only, allow it if not inside a transaction. + * As in check_transaction_read_only, allow it if not inside a transaction, + * or if restoring state in a parallel worker. */ bool check_transaction_isolation(int *newval, void **extra, GucSource source) { int newXactIsoLevel = *newval; - if (newXactIsoLevel != XactIsoLevel && IsTransactionState()) + if (newXactIsoLevel != XactIsoLevel && + IsTransactionState() && !InitializingParallelWorker) { if (FirstSnapshotSet) { @@ -619,6 +623,10 @@ check_transaction_isolation(int *newval, void **extra, GucSource source) bool check_transaction_deferrable(bool *newval, void **extra, GucSource source) { + /* Just accept the value when restoring state in a parallel worker */ + if (InitializingParallelWorker) + return true; + if (IsSubTransaction()) { GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION); @@ -690,6 +698,24 @@ check_client_encoding(char **newval, void **extra, GucSource source) /* Get the canonical name (no aliases, uniform case) */ canonical_name = pg_encoding_to_char(encoding); + /* + * Parallel workers send data to the leader, not the client. They always + * send data using the database encoding; therefore, we should never + * actually change the client encoding in a parallel worker. However, + * during parallel worker startup, we want to accept the leader's + * client_encoding setting so that anyone who looks at the value in the + * worker sees the same value that they would see in the leader. A change + * other than during startup, for example due to a SET clause attached to + * a function definition, should be rejected, as there is nothing we can + * do inside the worker to make it take effect. + */ + if (IsParallelWorker() && !InitializingParallelWorker) + { + GUC_check_errcode(ERRCODE_INVALID_TRANSACTION_STATE); + GUC_check_errdetail("Cannot change \"client_encoding\" during a parallel operation."); + return false; + } + /* * If we are not within a transaction then PrepareClientEncoding will not * be able to look up the necessary conversion procs. If we are still @@ -700,11 +726,15 @@ check_client_encoding(char **newval, void **extra, GucSource source) * It seems like a bad idea for client_encoding to change that way anyhow, * so we don't go out of our way to support it. * + * In a parallel worker, we might as well skip PrepareClientEncoding since + * we're not going to use its results. + * * Note: in the postmaster, or any other process that never calls * InitializeClientEncoding, PrepareClientEncoding will always succeed, * and so will SetClientEncoding; but they won't do anything, which is OK. */ - if (PrepareClientEncoding(encoding) < 0) + if (!IsParallelWorker() && + PrepareClientEncoding(encoding) < 0) { if (IsTransactionState()) { @@ -758,28 +788,11 @@ assign_client_encoding(const char *newval, void *extra) int encoding = *((int *) extra); /* - * Parallel workers send data to the leader, not the client. They always - * send data using the database encoding. + * In a parallel worker, we never override the client encoding that was + * set by ParallelWorkerMain(). */ if (IsParallelWorker()) - { - /* - * During parallel worker startup, we want to accept the leader's - * client_encoding setting so that anyone who looks at the value in - * the worker sees the same value that they would see in the leader. - */ - if (InitializingParallelWorker) - return; - - /* - * A change other than during startup, for example due to a SET clause - * attached to a function definition, should be rejected, as there is - * nothing we can do inside the worker to make it take effect. - */ - ereport(ERROR, - (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("cannot change \"client_encoding\" during a parallel operation"))); - } + return; /* We do not expect an error if PrepareClientEncoding succeeded */ if (SetClientEncoding(encoding) < 0) @@ -811,63 +824,77 @@ check_session_authorization(char **newval, void **extra, GucSource source) if (*newval == NULL) return true; - if (!IsTransactionState()) + if (InitializingParallelWorker) { /* - * Can't do catalog lookups, so fail. The result of this is that - * session_authorization cannot be set in postgresql.conf, which seems - * like a good thing anyway, so we don't work hard to avoid it. + * In parallel worker initialization, we want to copy the leader's + * state even if it no longer matches the catalogs. ParallelWorkerMain + * already installed the correct role OID and superuser state. */ - return false; + roleid = GetSessionUserId(); + is_superuser = GetSessionUserIsSuperuser(); } + else + { + if (!IsTransactionState()) + { + /* + * Can't do catalog lookups, so fail. The result of this is that + * session_authorization cannot be set in postgresql.conf, which + * seems like a good thing anyway, so we don't work hard to avoid + * it. + */ + return false; + } - /* - * When source == PGC_S_TEST, we don't throw a hard error for a - * nonexistent user name or insufficient privileges, only a NOTICE. See - * comments in guc.h. - */ + /* + * When source == PGC_S_TEST, we don't throw a hard error for a + * nonexistent user name or insufficient privileges, only a NOTICE. + * See comments in guc.h. + */ - /* Look up the username */ - roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval)); - if (!HeapTupleIsValid(roleTup)) - { - if (source == PGC_S_TEST) + /* Look up the username */ + roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval)); + if (!HeapTupleIsValid(roleTup)) { - ereport(NOTICE, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("role \"%s\" does not exist", *newval))); - return true; + if (source == PGC_S_TEST) + { + ereport(NOTICE, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("role \"%s\" does not exist", *newval))); + return true; + } + GUC_check_errmsg("role \"%s\" does not exist", *newval); + return false; } - GUC_check_errmsg("role \"%s\" does not exist", *newval); - return false; - } - roleform = (Form_pg_authid) GETSTRUCT(roleTup); - roleid = roleform->oid; - is_superuser = roleform->rolsuper; + roleform = (Form_pg_authid) GETSTRUCT(roleTup); + roleid = roleform->oid; + is_superuser = roleform->rolsuper; - ReleaseSysCache(roleTup); + ReleaseSysCache(roleTup); - /* - * Only superusers may SET SESSION AUTHORIZATION a role other than itself. - * Note that in case of multiple SETs in a single session, the original - * authenticated user's superuserness is what matters. - */ - if (roleid != GetAuthenticatedUserId() && - !superuser_arg(GetAuthenticatedUserId())) - { - if (source == PGC_S_TEST) + /* + * Only superusers may SET SESSION AUTHORIZATION a role other than + * itself. Note that in case of multiple SETs in a single session, the + * original authenticated user's superuserness is what matters. + */ + if (roleid != GetAuthenticatedUserId() && + !superuser_arg(GetAuthenticatedUserId())) { - ereport(NOTICE, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission will be denied to set session authorization \"%s\"", - *newval))); - return true; + if (source == PGC_S_TEST) + { + ereport(NOTICE, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission will be denied to set session authorization \"%s\"", + *newval))); + return true; + } + GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE); + GUC_check_errmsg("permission denied to set session authorization \"%s\"", + *newval); + return false; } - GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE); - GUC_check_errmsg("permission denied to set session authorization \"%s\"", - *newval); - return false; } /* Set up "extra" struct for assign_session_authorization to use */ @@ -876,7 +903,7 @@ check_session_authorization(char **newval, void **extra, GucSource source) return false; myextra->roleid = roleid; myextra->is_superuser = is_superuser; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -917,6 +944,16 @@ check_role(char **newval, void **extra, GucSource source) roleid = InvalidOid; is_superuser = false; } + else if (InitializingParallelWorker) + { + /* + * In parallel worker initialization, we want to copy the leader's + * state even if it no longer matches the catalogs. ParallelWorkerMain + * already installed the correct role OID and superuser state. + */ + roleid = GetCurrentRoleId(); + is_superuser = current_role_is_superuser; + } else { if (!IsTransactionState()) @@ -956,13 +993,8 @@ check_role(char **newval, void **extra, GucSource source) ReleaseSysCache(roleTup); - /* - * Verify that session user is allowed to become this role, but skip - * this in parallel mode, where we must blindly recreate the parallel - * leader's state. - */ - if (!InitializingParallelWorker && - !member_can_set_role(GetSessionUserId(), roleid)) + /* Verify that session user is allowed to become this role */ + if (!member_can_set_role(GetSessionUserId(), roleid)) { if (source == PGC_S_TEST) { @@ -985,7 +1017,7 @@ check_role(char **newval, void **extra, GucSource source) return false; myextra->roleid = roleid; myextra->is_superuser = is_superuser; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -1055,13 +1087,15 @@ check_application_name(char **newval, void **extra, GucSource source) if (!clean) return false; - ret = guc_strdup(WARNING, clean); + ret = guc_strdup(LOG, clean); if (!ret) { pfree(clean); return false; } + guc_free(*newval); + pfree(clean); *newval = ret; return true; @@ -1091,13 +1125,15 @@ check_cluster_name(char **newval, void **extra, GucSource source) if (!clean) return false; - ret = guc_strdup(WARNING, clean); + ret = guc_strdup(LOG, clean); if (!ret) { pfree(clean); return false; } + guc_free(*newval); + pfree(clean); *newval = ret; return true; @@ -1109,7 +1145,6 @@ check_cluster_name(char **newval, void **extra, GucSource source) void assign_maintenance_io_concurrency(int newval, void *extra) { -#ifdef USE_PREFETCH /* * Reconfigure recovery prefetching, because a setting it depends on * changed. @@ -1117,9 +1152,24 @@ assign_maintenance_io_concurrency(int newval, void *extra) maintenance_io_concurrency = newval; if (AmStartupProcess()) XLogPrefetchReconfigure(); -#endif } +/* + * GUC assign hooks that recompute io_combine_limit whenever + * io_combine_limit_guc and io_max_combine_limit are changed. These are needed + * because the GUC subsystem doesn't support dependencies between GUCs, and + * they may be assigned in either order. + */ +void +assign_io_max_combine_limit(int newval, void *extra) +{ + io_combine_limit = Min(newval, io_combine_limit_guc); +} +void +assign_io_combine_limit(int newval, void *extra) +{ + io_combine_limit = Min(io_max_combine_limit, newval); +} /* * These show hooks just exist because we want to show the values in octal. @@ -1195,32 +1245,6 @@ check_default_with_oids(bool *newval, void **extra, GucSource source) return true; } -bool -check_effective_io_concurrency(int *newval, void **extra, GucSource source) -{ -#ifndef USE_PREFETCH - if (*newval != 0) - { - GUC_check_errdetail("\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()."); - return false; - } -#endif /* USE_PREFETCH */ - return true; -} - -bool -check_maintenance_io_concurrency(int *newval, void **extra, GucSource source) -{ -#ifndef USE_PREFETCH - if (*newval != 0) - { - GUC_check_errdetail("\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()."); - return false; - } -#endif /* USE_PREFETCH */ - return true; -} - bool check_ssl(bool *newval, void **extra, GucSource source) { diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index fdad83383245f..6f0301555e0ae 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -3,7 +3,7 @@ * view.c * use rewrite rules to construct views * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -47,7 +47,6 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, { Oid viewOid; LOCKMODE lockmode; - CreateStmt *createStmt = makeNode(CreateStmt); List *attrList; ListCell *t; @@ -223,6 +222,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, } else { + CreateStmt *createStmt = makeNode(CreateStmt); ObjectAddress address; /* diff --git a/src/backend/executor/README b/src/backend/executor/README index 642d63be613b6..54f4782f31b60 100644 --- a/src/backend/executor/README +++ b/src/backend/executor/README @@ -133,9 +133,14 @@ is used by the function evaluation step, thus avoiding extra work to copy the result values around. The last entry in a completed ExprState->steps array is always an -EEOP_DONE step; this removes the need to test for end-of-array while -iterating. Also, if the expression contains any variable references (to -user columns of the ExprContext's INNER, OUTER, or SCAN tuples), the steps +EEOP_DONE_RETURN or EEOP_DONE_NO_RETURN step; this removes the need to +test for end-of-array while iterating. The former is used when the +expression returns a value directly, the latter when side-effects of +expression initialization are the goal (e.g. for projection or +aggregate transition value computation). + +Also, if the expression contains any variable references (to user +columns of the ExprContext's INNER, OUTER, or SCAN tuples), the steps array begins with EEOP_*_FETCHSOME steps that ensure that the relevant tuples have been deconstructed to make the required columns directly available (cf. slot_getsomeattrs()). This allows individual Var-fetching diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 3289e3e021996..1d0e8ad57b4a0 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -3,7 +3,7 @@ * execAmi.c * miscellaneous executor access method routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/executor/execAmi.c @@ -15,6 +15,7 @@ #include "access/amapi.h" #include "access/htup_details.h" #include "catalog/pg_class.h" +#include "executor/executor.h" #include "executor/nodeAgg.h" #include "executor/nodeAppend.h" #include "executor/nodeBitmapAnd.h" diff --git a/src/backend/executor/execAsync.c b/src/backend/executor/execAsync.c index 6129b80337045..5d3cabe73e346 100644 --- a/src/backend/executor/execAsync.c +++ b/src/backend/executor/execAsync.c @@ -3,7 +3,7 @@ * execAsync.c * Support routines for asynchronous execution * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c index 70c62ac1108c5..3bfdc0230ff9f 100644 --- a/src/backend/executor/execCurrent.c +++ b/src/backend/executor/execCurrent.c @@ -3,7 +3,7 @@ * execCurrent.c * executor support for WHERE CURRENT OF cursor * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/executor/execCurrent.c @@ -200,7 +200,7 @@ execCurrentOf(CurrentOfExpr *cexpr, /* * For IndexOnlyScan, the tuple stored in ss_ScanTupleSlot may be * a virtual tuple that does not have the ctid column, so we have - * to get the TID from xs_ctup.t_self. + * to get the TID from xs_heaptid. */ IndexScanDesc scan = ((IndexOnlyScanState *) scanstate)->ioss_ScanDesc; diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index f1caf48036b13..f1569879b529d 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -8,7 +8,7 @@ * using ExecInitExpr() et al. This converts the tree into a flat array * of ExprEvalSteps, which may be thought of as instructions in a program. * At runtime, we'll execute steps, starting with the first, until we reach - * an EEOP_DONE opcode. + * an EEOP_DONE_{RETURN|NO_RETURN} opcode. * * This file contains the "compilation" logic. It is independent of the * specific execution technology we use (switch statement, computed goto, @@ -19,7 +19,7 @@ * and "Expression Evaluation" sections. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -55,10 +55,15 @@ typedef struct ExprSetupInfo { - /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */ + /* + * Highest attribute numbers fetched from inner/outer/scan/old/new tuple + * slots: + */ AttrNumber last_inner; AttrNumber last_outer; AttrNumber last_scan; + AttrNumber last_old; + AttrNumber last_new; /* MULTIEXPR SubPlan nodes appearing in the expression: */ List *multiexpr_subplans; } ExprSetupInfo; @@ -69,6 +74,9 @@ static void ExecInitExprRec(Expr *node, ExprState *state, static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, Oid inputcollid, ExprState *state); +static void ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull); static void ExecCreateExprSetupSteps(ExprState *state, Node *node); static void ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info); static bool expr_setup_walker(Node *node, ExprSetupInfo *info); @@ -93,6 +101,7 @@ static void ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, ExprEvalStep *scratch); static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning, ErrorSaveContext *escontext, bool omit_quotes, + bool exists_coerce, Datum *resv, bool *resnull); @@ -153,7 +162,7 @@ ExecInitExpr(Expr *node, PlanState *parent) ExecInitExprRec(node, state, &state->resvalue, &state->resnull); /* Finally, append a DONE step */ - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -190,7 +199,7 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params) ExecInitExprRec(node, state, &state->resvalue, &state->resnull); /* Finally, append a DONE step */ - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -282,7 +291,7 @@ ExecInitQual(List *qual, PlanState *parent) * have yielded TRUE, and since its result is stored in the desired output * location, we're done. */ - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -442,8 +451,25 @@ ExecBuildProjectionInfo(List *targetList, /* INDEX_VAR is handled by default case */ default: - /* get the tuple from the relation being scanned */ - scratch.opcode = EEOP_ASSIGN_SCAN_VAR; + + /* + * Get the tuple from the relation being scanned, or the + * old/new tuple slot, if old/new values were requested. + */ + switch (variable->varreturningtype) + { + case VAR_RETURNING_DEFAULT: + scratch.opcode = EEOP_ASSIGN_SCAN_VAR; + break; + case VAR_RETURNING_OLD: + scratch.opcode = EEOP_ASSIGN_OLD_VAR; + state->flags |= EEO_FLAG_HAS_OLD; + break; + case VAR_RETURNING_NEW: + scratch.opcode = EEOP_ASSIGN_NEW_VAR; + state->flags |= EEO_FLAG_HAS_NEW; + break; + } break; } @@ -477,7 +503,7 @@ ExecBuildProjectionInfo(List *targetList, } } - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_NO_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -531,7 +557,7 @@ ExecBuildUpdateProjection(List *targetList, int nAssignableCols; bool sawJunk; Bitmapset *assignedCols; - ExprSetupInfo deform = {0, 0, 0, NIL}; + ExprSetupInfo deform = {0, 0, 0, 0, 0, NIL}; ExprEvalStep scratch = {0}; int outerattnum; ListCell *lc, @@ -594,7 +620,7 @@ ExecBuildUpdateProjection(List *targetList, */ for (int attnum = relDesc->natts; attnum > 0; attnum--) { - Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1); + CompactAttribute *attr = TupleDescCompactAttr(relDesc, attnum - 1); if (attr->attisdropped) continue; @@ -690,7 +716,7 @@ ExecBuildUpdateProjection(List *targetList, */ for (int attnum = 1; attnum <= relDesc->natts; attnum++) { - Form_pg_attribute attr = TupleDescAttr(relDesc, attnum - 1); + CompactAttribute *attr = TupleDescCompactAttr(relDesc, attnum - 1); if (attr->attisdropped) { @@ -716,7 +742,7 @@ ExecBuildUpdateProjection(List *targetList, } } - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_NO_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -920,6 +946,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* system column */ scratch.d.var.attnum = variable->varattno; scratch.d.var.vartype = variable->vartype; + scratch.d.var.varreturningtype = variable->varreturningtype; switch (variable->varno) { case INNER_VAR: @@ -932,7 +959,20 @@ ExecInitExprRec(Expr *node, ExprState *state, /* INDEX_VAR is handled by default case */ default: - scratch.opcode = EEOP_SCAN_SYSVAR; + switch (variable->varreturningtype) + { + case VAR_RETURNING_DEFAULT: + scratch.opcode = EEOP_SCAN_SYSVAR; + break; + case VAR_RETURNING_OLD: + scratch.opcode = EEOP_OLD_SYSVAR; + state->flags |= EEO_FLAG_HAS_OLD; + break; + case VAR_RETURNING_NEW: + scratch.opcode = EEOP_NEW_SYSVAR; + state->flags |= EEO_FLAG_HAS_NEW; + break; + } break; } } @@ -941,6 +981,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* regular user column */ scratch.d.var.attnum = variable->varattno - 1; scratch.d.var.vartype = variable->vartype; + scratch.d.var.varreturningtype = variable->varreturningtype; switch (variable->varno) { case INNER_VAR: @@ -953,7 +994,20 @@ ExecInitExprRec(Expr *node, ExprState *state, /* INDEX_VAR is handled by default case */ default: - scratch.opcode = EEOP_SCAN_VAR; + switch (variable->varreturningtype) + { + case VAR_RETURNING_DEFAULT: + scratch.opcode = EEOP_SCAN_VAR; + break; + case VAR_RETURNING_OLD: + scratch.opcode = EEOP_OLD_VAR; + state->flags |= EEO_FLAG_HAS_OLD; + break; + case VAR_RETURNING_NEW: + scratch.opcode = EEOP_NEW_VAR; + state->flags |= EEO_FLAG_HAS_NEW; + break; + } break; } } @@ -1187,6 +1241,14 @@ ExecInitExprRec(Expr *node, ExprState *state, op->args, op->opfuncid, op->inputcollid, state); + /* + * If first argument is of varlena type, we'll need to ensure + * that the value passed to the comparison function is a + * read-only pointer. + */ + scratch.d.func.make_ro = + (get_typlen(exprType((Node *) linitial(op->args))) == -1); + /* * Change opcode of call instruction to EEOP_NULLIF. * @@ -1405,7 +1467,6 @@ ExecInitExprRec(Expr *node, ExprState *state, case T_SubPlan: { SubPlan *subplan = (SubPlan *) node; - SubPlanState *sstate; /* * Real execution of a MULTIEXPR SubPlan has already been @@ -1422,19 +1483,7 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, resv, resnull); break; } @@ -1665,7 +1714,7 @@ ExecInitExprRec(Expr *node, ExprState *state, else { /* Not trivial, so append a DONE step */ - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(elemstate, &scratch); /* and ready the subexpression */ ExecReadyExpr(elemstate); @@ -1852,13 +1901,17 @@ ExecInitExprRec(Expr *node, ExprState *state, * actually within a CaseExpr, ArrayCoerceExpr, etc structure. * That can happen because some parts of the system abuse * CaseTestExpr to cause a read of a value externally supplied - * in econtext->caseValue_datum. We'll take care of that - * scenario at runtime. + * in econtext->caseValue_datum. We'll take care of that by + * generating a specialized operation. */ - scratch.opcode = EEOP_CASE_TESTVAL; - scratch.d.casetest.value = state->innermost_caseval; - scratch.d.casetest.isnull = state->innermost_casenull; - + if (state->innermost_caseval == NULL) + scratch.opcode = EEOP_CASE_TESTVAL_EXT; + else + { + scratch.opcode = EEOP_CASE_TESTVAL; + scratch.d.casetest.value = state->innermost_caseval; + scratch.d.casetest.isnull = state->innermost_casenull; + } ExprEvalPushStep(state, &scratch); break; } @@ -2103,7 +2156,7 @@ ExecInitExprRec(Expr *node, ExprState *state, /* Finally, examine the last comparison result */ scratch.opcode = EEOP_ROWCOMPARE_FINAL; - scratch.d.rowcompare_final.rctype = rcexpr->rctype; + scratch.d.rowcompare_final.cmptype = rcexpr->cmptype; ExprEvalPushStep(state, &scratch); /* adjust jump targets */ @@ -2316,6 +2369,8 @@ ExecInitExprRec(Expr *node, ExprState *state, { JsonValueExpr *jve = (JsonValueExpr *) node; + Assert(jve->raw_expr != NULL); + ExecInitExprRec(jve->raw_expr, state, resv, resnull); Assert(jve->formatted_expr != NULL); ExecInitExprRec(jve->formatted_expr, state, resv, resnull); break; @@ -2543,14 +2598,18 @@ ExecInitExprRec(Expr *node, ExprState *state, * that innermost_domainval could be NULL, if we're compiling * a standalone domain check rather than one embedded in a * larger expression. In that case we must read from - * econtext->domainValue_datum. We'll take care of that - * scenario at runtime. + * econtext->domainValue_datum. We'll take care of that by + * generating a specialized operation. */ - scratch.opcode = EEOP_DOMAIN_TESTVAL; - /* we share instruction union variant with case testval */ - scratch.d.casetest.value = state->innermost_domainval; - scratch.d.casetest.isnull = state->innermost_domainnull; - + if (state->innermost_domainval == NULL) + scratch.opcode = EEOP_DOMAIN_TESTVAL_EXT; + else + { + scratch.opcode = EEOP_DOMAIN_TESTVAL; + /* we share instruction union variant with case testval */ + scratch.d.casetest.value = state->innermost_domainval; + scratch.d.casetest.isnull = state->innermost_domainnull; + } ExprEvalPushStep(state, &scratch); break; } @@ -2574,6 +2633,34 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } + case T_ReturningExpr: + { + ReturningExpr *rexpr = (ReturningExpr *) node; + int retstep; + + /* Skip expression evaluation if OLD/NEW row doesn't exist */ + scratch.opcode = EEOP_RETURNINGEXPR; + scratch.d.returningexpr.nullflag = rexpr->retold ? + EEO_FLAG_OLD_IS_NULL : EEO_FLAG_NEW_IS_NULL; + scratch.d.returningexpr.jumpdone = -1; /* set below */ + ExprEvalPushStep(state, &scratch); + retstep = state->steps_len - 1; + + /* Steps to evaluate expression to return */ + ExecInitExprRec(rexpr->retexpr, state, resv, resnull); + + /* Jump target used if OLD/NEW row doesn't exist */ + state->steps[retstep].d.returningexpr.jumpdone = state->steps_len; + + /* Update ExprState flags */ + if (rexpr->retold) + state->flags |= EEO_FLAG_HAS_OLD; + else + state->flags |= EEO_FLAG_HAS_NEW; + + break; + } + default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); @@ -2701,7 +2788,15 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, if (pgstat_track_functions <= flinfo->fn_stats) { if (flinfo->fn_strict && nargs > 0) - scratch->opcode = EEOP_FUNCEXPR_STRICT; + { + /* Choose nargs optimized implementation if available. */ + if (nargs == 1) + scratch->opcode = EEOP_FUNCEXPR_STRICT_1; + else if (nargs == 2) + scratch->opcode = EEOP_FUNCEXPR_STRICT_2; + else + scratch->opcode = EEOP_FUNCEXPR_STRICT; + } else scratch->opcode = EEOP_FUNCEXPR; } @@ -2714,6 +2809,70 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, } } +/* + * Append the steps necessary for the evaluation of a SubPlan node to + * ExprState->steps. + * + * subplan - SubPlan expression to evaluate + * state - ExprState to whose ->steps to append the necessary operations + * resv / resnull - where to store the result of the node into + */ +static void +ExecInitSubPlanExpr(SubPlan *subplan, + ExprState *state, + Datum *resv, bool *resnull) +{ + ExprEvalStep scratch = {0}; + SubPlanState *sstate; + ListCell *pvar; + ListCell *l; + + if (!state->parent) + elog(ERROR, "SubPlan found with no parent plan"); + + /* + * Generate steps to evaluate input arguments for the subplan. + * + * We evaluate the argument expressions into ExprState's resvalue/resnull, + * and then use PARAM_SET to update the parameter. We do that, instead of + * evaluating directly into the param, to avoid depending on the pointer + * value remaining stable / being included in the generated expression. No + * danger of conflicts with other uses of resvalue/resnull as storing and + * using the value always is in subsequent steps. + * + * Any calculation we have to do can be done in the parent econtext, since + * the Param values don't need to have per-query lifetime. + */ + Assert(list_length(subplan->parParam) == list_length(subplan->args)); + forboth(l, subplan->parParam, pvar, subplan->args) + { + int paramid = lfirst_int(l); + Expr *arg = (Expr *) lfirst(pvar); + + ExecInitExprRec(arg, state, + &state->resvalue, &state->resnull); + + scratch.opcode = EEOP_PARAM_SET; + scratch.d.param.paramid = paramid; + /* paramtype's not actually used, but we might as well fill it */ + scratch.d.param.paramtype = exprType((Node *) arg); + ExprEvalPushStep(state, &scratch); + } + + sstate = ExecInitSubPlan(subplan, state->parent); + + /* add SubPlanState nodes to state->parent->subPlan */ + state->parent->subPlan = lappend(state->parent->subPlan, + sstate); + + scratch.opcode = EEOP_SUBPLAN; + scratch.resvalue = resv; + scratch.resnull = resnull; + scratch.d.subplan.sstate = sstate; + + ExprEvalPushStep(state, &scratch); +} + /* * Add expression steps performing setup that's needed before any of the * main execution of the expression. @@ -2721,7 +2880,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid, static void ExecCreateExprSetupSteps(ExprState *state, Node *node) { - ExprSetupInfo info = {0, 0, 0, NIL}; + ExprSetupInfo info = {0, 0, 0, 0, 0, NIL}; /* Prescan to find out what we need. */ expr_setup_walker(node, &info); @@ -2744,8 +2903,8 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info) scratch.resnull = NULL; /* - * Add steps deforming the ExprState's inner/outer/scan slots as much as - * required by any Vars appearing in the expression. + * Add steps deforming the ExprState's inner/outer/scan/old/new slots as + * much as required by any Vars appearing in the expression. */ if (info->last_inner > 0) { @@ -2777,6 +2936,26 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info) if (ExecComputeSlotInfo(state, &scratch)) ExprEvalPushStep(state, &scratch); } + if (info->last_old > 0) + { + scratch.opcode = EEOP_OLD_FETCHSOME; + scratch.d.fetch.last_var = info->last_old; + scratch.d.fetch.fixed = false; + scratch.d.fetch.kind = NULL; + scratch.d.fetch.known_desc = NULL; + if (ExecComputeSlotInfo(state, &scratch)) + ExprEvalPushStep(state, &scratch); + } + if (info->last_new > 0) + { + scratch.opcode = EEOP_NEW_FETCHSOME; + scratch.d.fetch.last_var = info->last_new; + scratch.d.fetch.fixed = false; + scratch.d.fetch.kind = NULL; + scratch.d.fetch.known_desc = NULL; + if (ExecComputeSlotInfo(state, &scratch)) + ExprEvalPushStep(state, &scratch); + } /* * Add steps to execute any MULTIEXPR SubPlans appearing in the @@ -2788,29 +2967,12 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info) foreach(lc, info->multiexpr_subplans) { SubPlan *subplan = (SubPlan *) lfirst(lc); - SubPlanState *sstate; Assert(subplan->subLinkType == MULTIEXPR_SUBLINK); - /* This should match what ExecInitExprRec does for other SubPlans: */ - - if (!state->parent) - elog(ERROR, "SubPlan found with no parent plan"); - - sstate = ExecInitSubPlan(subplan, state->parent); - - /* add SubPlanState nodes to state->parent->subPlan */ - state->parent->subPlan = lappend(state->parent->subPlan, - sstate); - - scratch.opcode = EEOP_SUBPLAN; - scratch.d.subplan.sstate = sstate; - /* The result can be ignored, but we better put it somewhere */ - scratch.resvalue = &state->resvalue; - scratch.resnull = &state->resnull; - - ExprEvalPushStep(state, &scratch); + ExecInitSubPlanExpr(subplan, state, + &state->resvalue, &state->resnull); } } @@ -2840,7 +3002,18 @@ expr_setup_walker(Node *node, ExprSetupInfo *info) /* INDEX_VAR is handled by default case */ default: - info->last_scan = Max(info->last_scan, attnum); + switch (variable->varreturningtype) + { + case VAR_RETURNING_DEFAULT: + info->last_scan = Max(info->last_scan, attnum); + break; + case VAR_RETURNING_OLD: + info->last_old = Max(info->last_old, attnum); + break; + case VAR_RETURNING_NEW: + info->last_new = Max(info->last_new, attnum); + break; + } break; } return false; @@ -2868,8 +3041,7 @@ expr_setup_walker(Node *node, ExprSetupInfo *info) return false; if (IsA(node, GroupingFunc)) return false; - return expression_tree_walker(node, expr_setup_walker, - (void *) info); + return expression_tree_walker(node, expr_setup_walker, info); } /* @@ -2879,6 +3051,11 @@ expr_setup_walker(Node *node, ExprSetupInfo *info) * evaluation of the expression will have the same type of slot, with an * equivalent descriptor. * + * EEOP_OLD_FETCHSOME and EEOP_NEW_FETCHSOME are used to process RETURNING, if + * OLD/NEW columns are referred to explicitly. In both cases, the tuple + * descriptor comes from the parent scan node, so we treat them the same as + * EEOP_SCAN_FETCHSOME. + * * Returns true if the deforming step is required, false otherwise. */ static bool @@ -2892,7 +3069,9 @@ ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op) Assert(opcode == EEOP_INNER_FETCHSOME || opcode == EEOP_OUTER_FETCHSOME || - opcode == EEOP_SCAN_FETCHSOME); + opcode == EEOP_SCAN_FETCHSOME || + opcode == EEOP_OLD_FETCHSOME || + opcode == EEOP_NEW_FETCHSOME); if (op->d.fetch.known_desc != NULL) { @@ -2944,7 +3123,9 @@ ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op) desc = ExecGetResultType(os); } } - else if (opcode == EEOP_SCAN_FETCHSOME) + else if (opcode == EEOP_SCAN_FETCHSOME || + opcode == EEOP_OLD_FETCHSOME || + opcode == EEOP_NEW_FETCHSOME) { desc = parent->scandesc; @@ -2992,6 +3173,12 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state) scratch->d.wholerow.tupdesc = NULL; /* filled at runtime */ scratch->d.wholerow.junkFilter = NULL; + /* update ExprState flags if Var refers to OLD/NEW */ + if (variable->varreturningtype == VAR_RETURNING_OLD) + state->flags |= EEO_FLAG_HAS_OLD; + else if (variable->varreturningtype == VAR_RETURNING_NEW) + state->flags |= EEO_FLAG_HAS_NEW; + /* * If the input tuple came from a subquery, it might contain "resjunk" * columns (such as GROUP BY or ORDER BY columns), which we don't want to @@ -3494,7 +3681,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, PlanState *parent = &aggstate->ss.ps; ExprEvalStep scratch = {0}; bool isCombine = DO_AGGSPLIT_COMBINE(aggstate->aggsplit); - ExprSetupInfo deform = {0, 0, 0, NIL}; + ExprSetupInfo deform = {0, 0, 0, 0, 0, NIL}; state->expr = (Expr *) aggstate; state->parent = parent; @@ -3713,6 +3900,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, { if (strictnulls) scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_NULLS; + else if (strictargs && pertrans->numTransInputs == 1) + scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1; else scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS; scratch.d.agg_strict_input_check.nulls = strictnulls; @@ -3789,6 +3978,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, as->d.jump.jumpdone = state->steps_len; } else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS || + as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1 || as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS) { Assert(as->d.agg_strict_input_check.jumpnull == -1); @@ -3812,7 +4002,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, scratch.resvalue = NULL; scratch.resnull = NULL; - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_NO_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -3931,6 +4121,335 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate, } } +/* + * Build an ExprState that calls the given hash function(s) on the attnums + * given by 'keyColIdx' . When numCols > 1, the hash values returned by each + * hash function are combined to produce a single hash value. + * + * desc: tuple descriptor for the to-be-hashed columns + * ops: TupleTableSlotOps to use for the give TupleDesc + * hashfunctions: FmgrInfos for each hash function to call, one per numCols. + * These are used directly in the returned ExprState so must remain allocated. + * collations: collation to use when calling the hash function. + * numCols: array length of hashfunctions, collations and keyColIdx. + * parent: PlanState node that the resulting ExprState will be evaluated at + * init_value: Normally 0, but can be set to other values to seed the hash + * with. Non-zero is marginally slower, so best to only use if it's provably + * worthwhile. + */ +ExprState * +ExecBuildHash32FromAttrs(TupleDesc desc, const TupleTableSlotOps *ops, + FmgrInfo *hashfunctions, Oid *collations, + int numCols, AttrNumber *keyColIdx, + PlanState *parent, uint32 init_value) +{ + ExprState *state = makeNode(ExprState); + ExprEvalStep scratch = {0}; + NullableDatum *iresult = NULL; + intptr_t opcode; + AttrNumber last_attnum = 0; + + Assert(numCols >= 0); + + state->parent = parent; + + /* + * Make a place to store intermediate hash values between subsequent + * hashing of individual columns. We only need this if there is more than + * one column to hash or an initial value plus one column. + */ + if ((int64) numCols + (init_value != 0) > 1) + iresult = palloc(sizeof(NullableDatum)); + + /* find the highest attnum so we deform the tuple to that point */ + for (int i = 0; i < numCols; i++) + last_attnum = Max(last_attnum, keyColIdx[i]); + + scratch.opcode = EEOP_INNER_FETCHSOME; + scratch.d.fetch.last_var = last_attnum; + scratch.d.fetch.fixed = false; + scratch.d.fetch.kind = ops; + scratch.d.fetch.known_desc = desc; + if (ExecComputeSlotInfo(state, &scratch)) + ExprEvalPushStep(state, &scratch); + + if (init_value == 0) + { + /* + * No initial value, so we can assign the result of the hash function + * for the first attribute without having to concern ourselves with + * combining the result with any initial value. + */ + opcode = EEOP_HASHDATUM_FIRST; + } + else + { + /* + * Set up operation to set the initial value. Normally we store this + * in the intermediate hash value location, but if there are no + * columns to hash, store it in the ExprState's result field. + */ + scratch.opcode = EEOP_HASHDATUM_SET_INITVAL; + scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value); + scratch.resvalue = numCols > 0 ? &iresult->value : &state->resvalue; + scratch.resnull = numCols > 0 ? &iresult->isnull : &state->resnull; + + ExprEvalPushStep(state, &scratch); + + /* + * When using an initial value use the NEXT32 ops as the FIRST ops + * would overwrite the stored initial value. + */ + opcode = EEOP_HASHDATUM_NEXT32; + } + + for (int i = 0; i < numCols; i++) + { + FmgrInfo *finfo; + FunctionCallInfo fcinfo; + Oid inputcollid = collations[i]; + AttrNumber attnum = keyColIdx[i] - 1; + + finfo = &hashfunctions[i]; + fcinfo = palloc0(SizeForFunctionCallInfo(1)); + + /* Initialize function call parameter structure too */ + InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL); + + /* + * Fetch inner Var for this attnum and store it in the 1st arg of the + * hash func. + */ + scratch.opcode = EEOP_INNER_VAR; + scratch.resvalue = &fcinfo->args[0].value; + scratch.resnull = &fcinfo->args[0].isnull; + scratch.d.var.attnum = attnum; + scratch.d.var.vartype = TupleDescAttr(desc, attnum)->atttypid; + scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT; + + ExprEvalPushStep(state, &scratch); + + /* Call the hash function */ + scratch.opcode = opcode; + + if (i == numCols - 1) + { + /* + * The result for hashing the final column is stored in the + * ExprState. + */ + scratch.resvalue = &state->resvalue; + scratch.resnull = &state->resnull; + } + else + { + Assert(iresult != NULL); + + /* intermediate values are stored in an intermediate result */ + scratch.resvalue = &iresult->value; + scratch.resnull = &iresult->isnull; + } + + /* + * NEXT32 opcodes need to look at the intermediate result. We might + * as well just set this for all ops. FIRSTs won't look at it. + */ + scratch.d.hashdatum.iresult = iresult; + + scratch.d.hashdatum.finfo = finfo; + scratch.d.hashdatum.fcinfo_data = fcinfo; + scratch.d.hashdatum.fn_addr = finfo->fn_addr; + scratch.d.hashdatum.jumpdone = -1; + + ExprEvalPushStep(state, &scratch); + + /* subsequent attnums must be combined with the previous */ + opcode = EEOP_HASHDATUM_NEXT32; + } + + scratch.resvalue = NULL; + scratch.resnull = NULL; + scratch.opcode = EEOP_DONE_RETURN; + ExprEvalPushStep(state, &scratch); + + ExecReadyExpr(state); + + return state; +} + +/* + * Build an ExprState that calls the given hash function(s) on the given + * 'hash_exprs'. When multiple expressions are present, the hash values + * returned by each hash function are combined to produce a single hash value. + * + * desc: tuple descriptor for the to-be-hashed expressions + * ops: TupleTableSlotOps for the TupleDesc + * hashfunc_oids: Oid for each hash function to call, one for each 'hash_expr' + * collations: collation to use when calling the hash function. + * hash_expr: list of expressions to hash the value of + * opstrict: array corresponding to the 'hashfunc_oids' to store op_strict() + * parent: PlanState node that the 'hash_exprs' will be evaluated at + * init_value: Normally 0, but can be set to other values to seed the hash + * with some other value. Using non-zero is slightly less efficient but can + * be useful. + * keep_nulls: if true, evaluation of the returned ExprState will abort early + * returning NULL if the given hash function is strict and the Datum to hash + * is null. When set to false, any NULL input Datums are skipped. + */ +ExprState * +ExecBuildHash32Expr(TupleDesc desc, const TupleTableSlotOps *ops, + const Oid *hashfunc_oids, const List *collations, + const List *hash_exprs, const bool *opstrict, + PlanState *parent, uint32 init_value, bool keep_nulls) +{ + ExprState *state = makeNode(ExprState); + ExprEvalStep scratch = {0}; + NullableDatum *iresult = NULL; + List *adjust_jumps = NIL; + ListCell *lc; + ListCell *lc2; + intptr_t strict_opcode; + intptr_t opcode; + int num_exprs = list_length(hash_exprs); + + Assert(num_exprs == list_length(collations)); + + state->parent = parent; + + /* Insert setup steps as needed. */ + ExecCreateExprSetupSteps(state, (Node *) hash_exprs); + + /* + * Make a place to store intermediate hash values between subsequent + * hashing of individual expressions. We only need this if there is more + * than one expression to hash or an initial value plus one expression. + */ + if ((int64) num_exprs + (init_value != 0) > 1) + iresult = palloc(sizeof(NullableDatum)); + + if (init_value == 0) + { + /* + * No initial value, so we can assign the result of the hash function + * for the first hash_expr without having to concern ourselves with + * combining the result with any initial value. + */ + strict_opcode = EEOP_HASHDATUM_FIRST_STRICT; + opcode = EEOP_HASHDATUM_FIRST; + } + else + { + /* + * Set up operation to set the initial value. Normally we store this + * in the intermediate hash value location, but if there are no exprs + * to hash, store it in the ExprState's result field. + */ + scratch.opcode = EEOP_HASHDATUM_SET_INITVAL; + scratch.d.hashdatum_initvalue.init_value = UInt32GetDatum(init_value); + scratch.resvalue = num_exprs > 0 ? &iresult->value : &state->resvalue; + scratch.resnull = num_exprs > 0 ? &iresult->isnull : &state->resnull; + + ExprEvalPushStep(state, &scratch); + + /* + * When using an initial value use the NEXT32/NEXT32_STRICT ops as the + * FIRST/FIRST_STRICT ops would overwrite the stored initial value. + */ + strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT; + opcode = EEOP_HASHDATUM_NEXT32; + } + + forboth(lc, hash_exprs, lc2, collations) + { + Expr *expr = (Expr *) lfirst(lc); + FmgrInfo *finfo; + FunctionCallInfo fcinfo; + int i = foreach_current_index(lc); + Oid funcid; + Oid inputcollid = lfirst_oid(lc2); + + funcid = hashfunc_oids[i]; + + /* Allocate hash function lookup data. */ + finfo = palloc0(sizeof(FmgrInfo)); + fcinfo = palloc0(SizeForFunctionCallInfo(1)); + + fmgr_info(funcid, finfo); + + /* + * Build the steps to evaluate the hash function's argument have it so + * the value of that is stored in the 0th argument of the hash func. + */ + ExecInitExprRec(expr, + state, + &fcinfo->args[0].value, + &fcinfo->args[0].isnull); + + if (i == num_exprs - 1) + { + /* the result for hashing the final expr is stored in the state */ + scratch.resvalue = &state->resvalue; + scratch.resnull = &state->resnull; + } + else + { + Assert(iresult != NULL); + + /* intermediate values are stored in an intermediate result */ + scratch.resvalue = &iresult->value; + scratch.resnull = &iresult->isnull; + } + + /* + * NEXT32 opcodes need to look at the intermediate result. We might + * as well just set this for all ops. FIRSTs won't look at it. + */ + scratch.d.hashdatum.iresult = iresult; + + /* Initialize function call parameter structure too */ + InitFunctionCallInfoData(*fcinfo, finfo, 1, inputcollid, NULL, NULL); + + scratch.d.hashdatum.finfo = finfo; + scratch.d.hashdatum.fcinfo_data = fcinfo; + scratch.d.hashdatum.fn_addr = finfo->fn_addr; + + scratch.opcode = opstrict[i] && !keep_nulls ? strict_opcode : opcode; + scratch.d.hashdatum.jumpdone = -1; + + ExprEvalPushStep(state, &scratch); + adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1); + + /* + * For subsequent keys we must combine the hash value with the + * previous hashes. + */ + strict_opcode = EEOP_HASHDATUM_NEXT32_STRICT; + opcode = EEOP_HASHDATUM_NEXT32; + } + + /* adjust jump targets */ + foreach(lc, adjust_jumps) + { + ExprEvalStep *as = &state->steps[lfirst_int(lc)]; + + Assert(as->opcode == EEOP_HASHDATUM_FIRST || + as->opcode == EEOP_HASHDATUM_FIRST_STRICT || + as->opcode == EEOP_HASHDATUM_NEXT32 || + as->opcode == EEOP_HASHDATUM_NEXT32_STRICT); + Assert(as->d.hashdatum.jumpdone == -1); + as->d.hashdatum.jumpdone = state->steps_len; + } + + scratch.resvalue = NULL; + scratch.resnull = NULL; + scratch.opcode = EEOP_DONE_RETURN; + ExprEvalPushStep(state, &scratch); + + ExecReadyExpr(state); + + return state; +} + /* * Build equality expression that can be evaluated using ExecQual(), returning * true if the expression context's inner/outer tuple are NOT DISTINCT. I.e @@ -4032,6 +4551,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, scratch.opcode = EEOP_INNER_VAR; scratch.d.var.attnum = attno - 1; scratch.d.var.vartype = latt->atttypid; + scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT; scratch.resvalue = &fcinfo->args[0].value; scratch.resnull = &fcinfo->args[0].isnull; ExprEvalPushStep(state, &scratch); @@ -4040,6 +4560,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, scratch.opcode = EEOP_OUTER_VAR; scratch.d.var.attnum = attno - 1; scratch.d.var.vartype = ratt->atttypid; + scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT; scratch.resvalue = &fcinfo->args[1].value; scratch.resnull = &fcinfo->args[1].isnull; ExprEvalPushStep(state, &scratch); @@ -4076,7 +4597,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, scratch.resvalue = NULL; scratch.resnull = NULL; - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -4166,6 +4687,7 @@ ExecBuildParamSetEqual(TupleDesc desc, scratch.opcode = EEOP_INNER_VAR; scratch.d.var.attnum = attno; scratch.d.var.vartype = att->atttypid; + scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT; scratch.resvalue = &fcinfo->args[0].value; scratch.resnull = &fcinfo->args[0].isnull; ExprEvalPushStep(state, &scratch); @@ -4174,6 +4696,7 @@ ExecBuildParamSetEqual(TupleDesc desc, scratch.opcode = EEOP_OUTER_VAR; scratch.d.var.attnum = attno; scratch.d.var.vartype = att->atttypid; + scratch.d.var.varreturningtype = VAR_RETURNING_DEFAULT; scratch.resvalue = &fcinfo->args[1].value; scratch.resnull = &fcinfo->args[1].isnull; ExprEvalPushStep(state, &scratch); @@ -4210,7 +4733,7 @@ ExecBuildParamSetEqual(TupleDesc desc, scratch.resvalue = NULL; scratch.resnull = NULL; - scratch.opcode = EEOP_DONE; + scratch.opcode = EEOP_DONE_RETURN; ExprEvalPushStep(state, &scratch); ExecReadyExpr(state); @@ -4232,9 +4755,11 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, List *jumps_return_null = NIL; List *jumps_to_end = NIL; ListCell *lc; - ErrorSaveContext *escontext = - jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR ? - &jsestate->escontext : NULL; + ErrorSaveContext *escontext; + bool returning_domain = + get_typtype(jsexpr->returning->typid) == TYPTYPE_DOMAIN; + + Assert(jsexpr->on_error != NULL); jsestate->jsexpr = jsexpr; @@ -4312,6 +4837,9 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, scratch->d.constval.isnull = true; ExprEvalPushStep(state, scratch); + escontext = jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR ? + &jsestate->escontext : NULL; + /* * To handle coercion errors softly, use the following ErrorSaveContext to * pass to ExecInitExprRec() when initializing the coercion expressions @@ -4329,7 +4857,9 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, jsestate->jump_eval_coercion = state->steps_len; ExecInitJsonCoercion(state, jsexpr->returning, escontext, - jsexpr->omit_quotes, resv, resnull); + jsexpr->omit_quotes, + jsexpr->op == JSON_EXISTS_OP, + resv, resnull); } else if (jsexpr->use_io_coercion) { @@ -4381,9 +4911,18 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, * Step to check jsestate->error and return the ON ERROR expression if * there is one. This handles both the errors that occur during jsonpath * evaluation in EEOP_JSONEXPR_PATH and subsequent coercion evaluation. + * + * Speed up common cases by avoiding extra steps for a NULL-valued ON + * ERROR expression unless RETURNING a domain type, where constraints must + * be checked. ExecEvalJsonExprPath() already returns NULL on error, + * making additional steps unnecessary in typical scenarios. Note that the + * default ON ERROR behavior for JSON_VALUE() and JSON_QUERY() is to + * return NULL. */ - if (jsexpr->on_error && - jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR) + if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR && + (!(IsA(jsexpr->on_error->expr, Const) && + ((Const *) jsexpr->on_error->expr)->constisnull) || + returning_domain)) { ErrorSaveContext *saved_escontext; @@ -4410,7 +4949,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, /* Step to coerce the ON ERROR expression if needed */ if (jsexpr->on_error->coerce) ExecInitJsonCoercion(state, jsexpr->returning, escontext, - jsexpr->omit_quotes, resv, resnull); + jsexpr->omit_quotes, false, + resv, resnull); /* * Add a COERCION_FINISH step to check for errors that may occur when @@ -4437,9 +4977,15 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, /* * Step to check jsestate->empty and return the ON EMPTY expression if * there is one. + * + * See the comment above for details on the optimization for NULL-valued + * expressions. */ if (jsexpr->on_empty != NULL && - jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR) + jsexpr->on_empty->btype != JSON_BEHAVIOR_ERROR && + (!(IsA(jsexpr->on_empty->expr, Const) && + ((Const *) jsexpr->on_empty->expr)->constisnull) || + returning_domain)) { ErrorSaveContext *saved_escontext; @@ -4466,7 +5012,8 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, /* Step to coerce the ON EMPTY expression if needed */ if (jsexpr->on_empty->coerce) ExecInitJsonCoercion(state, jsexpr->returning, escontext, - jsexpr->omit_quotes, resv, resnull); + jsexpr->omit_quotes, false, + resv, resnull); /* * Add a COERCION_FINISH step to check for errors that may occur when @@ -4502,6 +5049,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state, static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning, ErrorSaveContext *escontext, bool omit_quotes, + bool exists_coerce, Datum *resv, bool *resnull) { ExprEvalStep scratch = {0}; @@ -4512,8 +5060,13 @@ ExecInitJsonCoercion(ExprState *state, JsonReturning *returning, scratch.resnull = resnull; scratch.d.jsonexpr_coercion.targettype = returning->typid; scratch.d.jsonexpr_coercion.targettypmod = returning->typmod; - scratch.d.jsonexpr_coercion.json_populate_type_cache = NULL; + scratch.d.jsonexpr_coercion.json_coercion_cache = NULL; scratch.d.jsonexpr_coercion.escontext = escontext; scratch.d.jsonexpr_coercion.omit_quotes = omit_quotes; + scratch.d.jsonexpr_coercion.exists_coerce = exists_coerce; + scratch.d.jsonexpr_coercion.exists_cast_to_int = exists_coerce && + getBaseType(returning->typid) == INT4OID; + scratch.d.jsonexpr_coercion.exists_check_domain = exists_coerce && + DomainHasConstraints(returning->typid); ExprEvalPushStep(state, &scratch); } diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 430438f668e4a..8a72b5e70a4ec 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -46,7 +46,7 @@ * exported rather than being "static" in this file.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -168,6 +168,12 @@ static Datum ExecJustScanVarVirt(ExprState *state, ExprContext *econtext, bool * static Datum ExecJustAssignInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull); static Datum ExecJustAssignOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull); static Datum ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashInnerVarWithIV(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashOuterVar(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashInnerVar(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashOuterVarVirt(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashInnerVarVirt(ExprState *state, ExprContext *econtext, bool *isnull); +static Datum ExecJustHashOuterVarStrict(ExprState *state, ExprContext *econtext, bool *isnull); /* execution helper functions */ static pg_attribute_always_inline void ExecAggPlainTransByVal(AggState *aggstate, @@ -240,7 +246,8 @@ ExecReadyInterpretedExpr(ExprState *state) /* Simple validity checks on expression */ Assert(state->steps_len >= 1); - Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE); + Assert(state->steps[state->steps_len - 1].opcode == EEOP_DONE_RETURN || + state->steps[state->steps_len - 1].opcode == EEOP_DONE_NO_RETURN); /* * Don't perform redundant initialization. This is unreachable in current @@ -273,7 +280,51 @@ ExecReadyInterpretedExpr(ExprState *state) * the full interpreter is a measurable overhead for these, and these * patterns occur often enough to be worth optimizing. */ - if (state->steps_len == 3) + if (state->steps_len == 5) + { + ExprEvalOp step0 = state->steps[0].opcode; + ExprEvalOp step1 = state->steps[1].opcode; + ExprEvalOp step2 = state->steps[2].opcode; + ExprEvalOp step3 = state->steps[3].opcode; + + if (step0 == EEOP_INNER_FETCHSOME && + step1 == EEOP_HASHDATUM_SET_INITVAL && + step2 == EEOP_INNER_VAR && + step3 == EEOP_HASHDATUM_NEXT32) + { + state->evalfunc_private = (void *) ExecJustHashInnerVarWithIV; + return; + } + } + else if (state->steps_len == 4) + { + ExprEvalOp step0 = state->steps[0].opcode; + ExprEvalOp step1 = state->steps[1].opcode; + ExprEvalOp step2 = state->steps[2].opcode; + + if (step0 == EEOP_OUTER_FETCHSOME && + step1 == EEOP_OUTER_VAR && + step2 == EEOP_HASHDATUM_FIRST) + { + state->evalfunc_private = (void *) ExecJustHashOuterVar; + return; + } + else if (step0 == EEOP_INNER_FETCHSOME && + step1 == EEOP_INNER_VAR && + step2 == EEOP_HASHDATUM_FIRST) + { + state->evalfunc_private = (void *) ExecJustHashInnerVar; + return; + } + else if (step0 == EEOP_OUTER_FETCHSOME && + step1 == EEOP_OUTER_VAR && + step2 == EEOP_HASHDATUM_FIRST_STRICT) + { + state->evalfunc_private = (void *) ExecJustHashOuterVarStrict; + return; + } + } + else if (state->steps_len == 3) { ExprEvalOp step0 = state->steps[0].opcode; ExprEvalOp step1 = state->steps[1].opcode; @@ -281,44 +332,57 @@ ExecReadyInterpretedExpr(ExprState *state) if (step0 == EEOP_INNER_FETCHSOME && step1 == EEOP_INNER_VAR) { - state->evalfunc_private = (void *) ExecJustInnerVar; + state->evalfunc_private = ExecJustInnerVar; return; } else if (step0 == EEOP_OUTER_FETCHSOME && step1 == EEOP_OUTER_VAR) { - state->evalfunc_private = (void *) ExecJustOuterVar; + state->evalfunc_private = ExecJustOuterVar; return; } else if (step0 == EEOP_SCAN_FETCHSOME && step1 == EEOP_SCAN_VAR) { - state->evalfunc_private = (void *) ExecJustScanVar; + state->evalfunc_private = ExecJustScanVar; return; } else if (step0 == EEOP_INNER_FETCHSOME && step1 == EEOP_ASSIGN_INNER_VAR) { - state->evalfunc_private = (void *) ExecJustAssignInnerVar; + state->evalfunc_private = ExecJustAssignInnerVar; return; } else if (step0 == EEOP_OUTER_FETCHSOME && step1 == EEOP_ASSIGN_OUTER_VAR) { - state->evalfunc_private = (void *) ExecJustAssignOuterVar; + state->evalfunc_private = ExecJustAssignOuterVar; return; } else if (step0 == EEOP_SCAN_FETCHSOME && step1 == EEOP_ASSIGN_SCAN_VAR) { - state->evalfunc_private = (void *) ExecJustAssignScanVar; + state->evalfunc_private = ExecJustAssignScanVar; return; } else if (step0 == EEOP_CASE_TESTVAL && - step1 == EEOP_FUNCEXPR_STRICT && - state->steps[0].d.casetest.value) + (step1 == EEOP_FUNCEXPR_STRICT || + step1 == EEOP_FUNCEXPR_STRICT_1 || + step1 == EEOP_FUNCEXPR_STRICT_2)) + { + state->evalfunc_private = ExecJustApplyFuncToCase; + return; + } + else if (step0 == EEOP_INNER_VAR && + step1 == EEOP_HASHDATUM_FIRST) + { + state->evalfunc_private = (void *) ExecJustHashInnerVarVirt; + return; + } + else if (step0 == EEOP_OUTER_VAR && + step1 == EEOP_HASHDATUM_FIRST) { - state->evalfunc_private = (void *) ExecJustApplyFuncToCase; + state->evalfunc_private = (void *) ExecJustHashOuterVarVirt; return; } } @@ -328,37 +392,37 @@ ExecReadyInterpretedExpr(ExprState *state) if (step0 == EEOP_CONST) { - state->evalfunc_private = (void *) ExecJustConst; + state->evalfunc_private = ExecJustConst; return; } else if (step0 == EEOP_INNER_VAR) { - state->evalfunc_private = (void *) ExecJustInnerVarVirt; + state->evalfunc_private = ExecJustInnerVarVirt; return; } else if (step0 == EEOP_OUTER_VAR) { - state->evalfunc_private = (void *) ExecJustOuterVarVirt; + state->evalfunc_private = ExecJustOuterVarVirt; return; } else if (step0 == EEOP_SCAN_VAR) { - state->evalfunc_private = (void *) ExecJustScanVarVirt; + state->evalfunc_private = ExecJustScanVarVirt; return; } else if (step0 == EEOP_ASSIGN_INNER_VAR) { - state->evalfunc_private = (void *) ExecJustAssignInnerVarVirt; + state->evalfunc_private = ExecJustAssignInnerVarVirt; return; } else if (step0 == EEOP_ASSIGN_OUTER_VAR) { - state->evalfunc_private = (void *) ExecJustAssignOuterVarVirt; + state->evalfunc_private = ExecJustAssignOuterVarVirt; return; } else if (step0 == EEOP_ASSIGN_SCAN_VAR) { - state->evalfunc_private = (void *) ExecJustAssignScanVarVirt; + state->evalfunc_private = ExecJustAssignScanVarVirt; return; } } @@ -379,7 +443,7 @@ ExecReadyInterpretedExpr(ExprState *state) state->flags |= EEO_FLAG_DIRECT_THREADED; #endif /* EEO_USE_COMPUTED_GOTO */ - state->evalfunc_private = (void *) ExecInterpExpr; + state->evalfunc_private = ExecInterpExpr; } @@ -400,31 +464,44 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) TupleTableSlot *innerslot; TupleTableSlot *outerslot; TupleTableSlot *scanslot; + TupleTableSlot *oldslot; + TupleTableSlot *newslot; /* * This array has to be in the same order as enum ExprEvalOp. */ #if defined(EEO_USE_COMPUTED_GOTO) static const void *const dispatch_table[] = { - &&CASE_EEOP_DONE, + &&CASE_EEOP_DONE_RETURN, + &&CASE_EEOP_DONE_NO_RETURN, &&CASE_EEOP_INNER_FETCHSOME, &&CASE_EEOP_OUTER_FETCHSOME, &&CASE_EEOP_SCAN_FETCHSOME, + &&CASE_EEOP_OLD_FETCHSOME, + &&CASE_EEOP_NEW_FETCHSOME, &&CASE_EEOP_INNER_VAR, &&CASE_EEOP_OUTER_VAR, &&CASE_EEOP_SCAN_VAR, + &&CASE_EEOP_OLD_VAR, + &&CASE_EEOP_NEW_VAR, &&CASE_EEOP_INNER_SYSVAR, &&CASE_EEOP_OUTER_SYSVAR, &&CASE_EEOP_SCAN_SYSVAR, + &&CASE_EEOP_OLD_SYSVAR, + &&CASE_EEOP_NEW_SYSVAR, &&CASE_EEOP_WHOLEROW, &&CASE_EEOP_ASSIGN_INNER_VAR, &&CASE_EEOP_ASSIGN_OUTER_VAR, &&CASE_EEOP_ASSIGN_SCAN_VAR, + &&CASE_EEOP_ASSIGN_OLD_VAR, + &&CASE_EEOP_ASSIGN_NEW_VAR, &&CASE_EEOP_ASSIGN_TMP, &&CASE_EEOP_ASSIGN_TMP_MAKE_RO, &&CASE_EEOP_CONST, &&CASE_EEOP_FUNCEXPR, &&CASE_EEOP_FUNCEXPR_STRICT, + &&CASE_EEOP_FUNCEXPR_STRICT_1, + &&CASE_EEOP_FUNCEXPR_STRICT_2, &&CASE_EEOP_FUNCEXPR_FUSAGE, &&CASE_EEOP_FUNCEXPR_STRICT_FUSAGE, &&CASE_EEOP_BOOL_AND_STEP_FIRST, @@ -450,7 +527,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_PARAM_EXEC, &&CASE_EEOP_PARAM_EXTERN, &&CASE_EEOP_PARAM_CALLBACK, + &&CASE_EEOP_PARAM_SET, &&CASE_EEOP_CASE_TESTVAL, + &&CASE_EEOP_CASE_TESTVAL_EXT, &&CASE_EEOP_MAKE_READONLY, &&CASE_EEOP_IOCOERCE, &&CASE_EEOP_IOCOERCE_SAFE, @@ -460,6 +539,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_SQLVALUEFUNCTION, &&CASE_EEOP_CURRENTOFEXPR, &&CASE_EEOP_NEXTVALUEEXPR, + &&CASE_EEOP_RETURNINGEXPR, &&CASE_EEOP_ARRAYEXPR, &&CASE_EEOP_ARRAYCOERCE, &&CASE_EEOP_ROW, @@ -474,8 +554,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_SBSREF_ASSIGN, &&CASE_EEOP_SBSREF_FETCH, &&CASE_EEOP_DOMAIN_TESTVAL, + &&CASE_EEOP_DOMAIN_TESTVAL_EXT, &&CASE_EEOP_DOMAIN_NOTNULL, &&CASE_EEOP_DOMAIN_CHECK, + &&CASE_EEOP_HASHDATUM_SET_INITVAL, + &&CASE_EEOP_HASHDATUM_FIRST, + &&CASE_EEOP_HASHDATUM_FIRST_STRICT, + &&CASE_EEOP_HASHDATUM_NEXT32, + &&CASE_EEOP_HASHDATUM_NEXT32_STRICT, &&CASE_EEOP_CONVERT_ROWTYPE, &&CASE_EEOP_SCALARARRAYOP, &&CASE_EEOP_HASHED_SCALARARRAYOP, @@ -493,6 +579,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_AGG_STRICT_DESERIALIZE, &&CASE_EEOP_AGG_DESERIALIZE, &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS, + &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1, &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS, &&CASE_EEOP_AGG_PLAIN_PERGROUP_NULLCHECK, &&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL, @@ -523,6 +610,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) innerslot = econtext->ecxt_innertuple; outerslot = econtext->ecxt_outertuple; scanslot = econtext->ecxt_scantuple; + oldslot = econtext->ecxt_oldtuple; + newslot = econtext->ecxt_newtuple; #if defined(EEO_USE_COMPUTED_GOTO) EEO_DISPATCH(); @@ -530,9 +619,16 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_SWITCH() { - EEO_CASE(EEOP_DONE) + EEO_CASE(EEOP_DONE_RETURN) + { + *isnull = state->resnull; + return state->resvalue; + } + + EEO_CASE(EEOP_DONE_NO_RETURN) { - goto out; + Assert(isnull == NULL); + return (Datum) 0; } EEO_CASE(EEOP_INNER_FETCHSOME) @@ -562,6 +658,24 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_OLD_FETCHSOME) + { + CheckOpSlotCompatibility(op, oldslot); + + slot_getsomeattrs(oldslot, op->d.fetch.last_var); + + EEO_NEXT(); + } + + EEO_CASE(EEOP_NEW_FETCHSOME) + { + CheckOpSlotCompatibility(op, newslot); + + slot_getsomeattrs(newslot, op->d.fetch.last_var); + + EEO_NEXT(); + } + EEO_CASE(EEOP_INNER_VAR) { int attnum = op->d.var.attnum; @@ -605,6 +719,32 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_OLD_VAR) + { + int attnum = op->d.var.attnum; + + /* See EEOP_INNER_VAR comments */ + + Assert(attnum >= 0 && attnum < oldslot->tts_nvalid); + *op->resvalue = oldslot->tts_values[attnum]; + *op->resnull = oldslot->tts_isnull[attnum]; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_NEW_VAR) + { + int attnum = op->d.var.attnum; + + /* See EEOP_INNER_VAR comments */ + + Assert(attnum >= 0 && attnum < newslot->tts_nvalid); + *op->resvalue = newslot->tts_values[attnum]; + *op->resnull = newslot->tts_isnull[attnum]; + + EEO_NEXT(); + } + EEO_CASE(EEOP_INNER_SYSVAR) { ExecEvalSysVar(state, op, econtext, innerslot); @@ -623,6 +763,18 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_OLD_SYSVAR) + { + ExecEvalSysVar(state, op, econtext, oldslot); + EEO_NEXT(); + } + + EEO_CASE(EEOP_NEW_SYSVAR) + { + ExecEvalSysVar(state, op, econtext, newslot); + EEO_NEXT(); + } + EEO_CASE(EEOP_WHOLEROW) { /* too complex for an inline implementation */ @@ -682,6 +834,40 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_ASSIGN_OLD_VAR) + { + int resultnum = op->d.assign_var.resultnum; + int attnum = op->d.assign_var.attnum; + + /* + * We do not need CheckVarSlotCompatibility here; that was taken + * care of at compilation time. But see EEOP_INNER_VAR comments. + */ + Assert(attnum >= 0 && attnum < oldslot->tts_nvalid); + Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts); + resultslot->tts_values[resultnum] = oldslot->tts_values[attnum]; + resultslot->tts_isnull[resultnum] = oldslot->tts_isnull[attnum]; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_ASSIGN_NEW_VAR) + { + int resultnum = op->d.assign_var.resultnum; + int attnum = op->d.assign_var.attnum; + + /* + * We do not need CheckVarSlotCompatibility here; that was taken + * care of at compilation time. But see EEOP_INNER_VAR comments. + */ + Assert(attnum >= 0 && attnum < newslot->tts_nvalid); + Assert(resultnum >= 0 && resultnum < resultslot->tts_tupleDescriptor->natts); + resultslot->tts_values[resultnum] = newslot->tts_values[attnum]; + resultslot->tts_isnull[resultnum] = newslot->tts_isnull[attnum]; + + EEO_NEXT(); + } + EEO_CASE(EEOP_ASSIGN_TMP) { int resultnum = op->d.assign_tmp.resultnum; @@ -744,6 +930,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + /* strict function call with more than two arguments */ EEO_CASE(EEOP_FUNCEXPR_STRICT) { FunctionCallInfo fcinfo = op->d.func.fcinfo_data; @@ -751,6 +938,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) int nargs = op->d.func.nargs; Datum d; + Assert(nargs > 2); + /* strict function, so check for NULL args */ for (int argno = 0; argno < nargs; argno++) { @@ -769,6 +958,54 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + /* strict function call with one argument */ + EEO_CASE(EEOP_FUNCEXPR_STRICT_1) + { + FunctionCallInfo fcinfo = op->d.func.fcinfo_data; + NullableDatum *args = fcinfo->args; + + Assert(op->d.func.nargs == 1); + + /* strict function, so check for NULL args */ + if (args[0].isnull) + *op->resnull = true; + else + { + Datum d; + + fcinfo->isnull = false; + d = op->d.func.fn_addr(fcinfo); + *op->resvalue = d; + *op->resnull = fcinfo->isnull; + } + + EEO_NEXT(); + } + + /* strict function call with two arguments */ + EEO_CASE(EEOP_FUNCEXPR_STRICT_2) + { + FunctionCallInfo fcinfo = op->d.func.fcinfo_data; + NullableDatum *args = fcinfo->args; + + Assert(op->d.func.nargs == 2); + + /* strict function, so check for NULL args */ + if (args[0].isnull || args[1].isnull) + *op->resnull = true; + else + { + Datum d; + + fcinfo->isnull = false; + d = op->d.func.fn_addr(fcinfo); + *op->resvalue = d; + *op->resnull = fcinfo->isnull; + } + + EEO_NEXT(); + } + EEO_CASE(EEOP_FUNCEXPR_FUSAGE) { /* not common enough to inline */ @@ -1093,46 +1330,25 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_PARAM_SET) + { + /* out of line, unlikely to matter performance-wise */ + ExecEvalParamSet(state, op, econtext); + EEO_NEXT(); + } + EEO_CASE(EEOP_CASE_TESTVAL) { - /* - * Normally upper parts of the expression tree have setup the - * values to be returned here, but some parts of the system - * currently misuse {caseValue,domainValue}_{datum,isNull} to set - * run-time data. So if no values have been set-up, use - * ExprContext's. This isn't pretty, but also not *that* ugly, - * and this is unlikely to be performance sensitive enough to - * worry about an extra branch. - */ - if (op->d.casetest.value) - { - *op->resvalue = *op->d.casetest.value; - *op->resnull = *op->d.casetest.isnull; - } - else - { - *op->resvalue = econtext->caseValue_datum; - *op->resnull = econtext->caseValue_isNull; - } + *op->resvalue = *op->d.casetest.value; + *op->resnull = *op->d.casetest.isnull; EEO_NEXT(); } - EEO_CASE(EEOP_DOMAIN_TESTVAL) + EEO_CASE(EEOP_CASE_TESTVAL_EXT) { - /* - * See EEOP_CASE_TESTVAL comment. - */ - if (op->d.casetest.value) - { - *op->resvalue = *op->d.casetest.value; - *op->resnull = *op->d.casetest.isnull; - } - else - { - *op->resvalue = econtext->domainValue_datum; - *op->resnull = econtext->domainValue_isNull; - } + *op->resvalue = econtext->caseValue_datum; + *op->resnull = econtext->caseValue_isNull; EEO_NEXT(); } @@ -1295,12 +1511,24 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) * The arguments are already evaluated into fcinfo->args. */ FunctionCallInfo fcinfo = op->d.func.fcinfo_data; + Datum save_arg0 = fcinfo->args[0].value; /* if either argument is NULL they can't be equal */ if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull) { Datum result; + /* + * If first argument is of varlena type, it might be an + * expanded datum. We need to ensure that the value passed to + * the comparison function is a read-only pointer. However, + * if we end by returning the first argument, that will be the + * original read-write pointer if it was read-write. + */ + if (op->d.func.make_ro) + fcinfo->args[0].value = + MakeExpandedObjectReadOnlyInternal(save_arg0); + fcinfo->isnull = false; result = op->d.func.fn_addr(fcinfo); @@ -1315,7 +1543,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) } /* Arguments aren't equal, so return the first one */ - *op->resvalue = fcinfo->args[0].value; + *op->resvalue = save_arg0; *op->resnull = fcinfo->args[0].isnull; EEO_NEXT(); @@ -1351,6 +1579,23 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_RETURNINGEXPR) + { + /* + * The next op actually evaluates the expression. If the OLD/NEW + * row doesn't exist, skip that and return NULL. + */ + if (state->flags & op->d.returningexpr.nullflag) + { + *op->resvalue = (Datum) 0; + *op->resnull = true; + + EEO_JUMP(op->d.returningexpr.jumpdone); + } + + EEO_NEXT(); + } + EEO_CASE(EEOP_ARRAYEXPR) { /* too complex for an inline implementation */ @@ -1413,22 +1658,22 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_CASE(EEOP_ROWCOMPARE_FINAL) { int32 cmpresult = DatumGetInt32(*op->resvalue); - RowCompareType rctype = op->d.rowcompare_final.rctype; + CompareType cmptype = op->d.rowcompare_final.cmptype; *op->resnull = false; - switch (rctype) + switch (cmptype) { /* EQ and NE cases aren't allowed here */ - case ROWCOMPARE_LT: + case COMPARE_LT: *op->resvalue = BoolGetDatum(cmpresult < 0); break; - case ROWCOMPARE_LE: + case COMPARE_LE: *op->resvalue = BoolGetDatum(cmpresult <= 0); break; - case ROWCOMPARE_GE: + case COMPARE_GE: *op->resvalue = BoolGetDatum(cmpresult >= 0); break; - case ROWCOMPARE_GT: + case COMPARE_GT: *op->resvalue = BoolGetDatum(cmpresult > 0); break; default: @@ -1519,6 +1764,22 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_DOMAIN_TESTVAL) + { + *op->resvalue = *op->d.casetest.value; + *op->resnull = *op->d.casetest.isnull; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_DOMAIN_TESTVAL_EXT) + { + *op->resvalue = econtext->domainValue_datum; + *op->resnull = econtext->domainValue_isNull; + + EEO_NEXT(); + } + EEO_CASE(EEOP_DOMAIN_NOTNULL) { /* too complex for an inline implementation */ @@ -1535,6 +1796,113 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_HASHDATUM_SET_INITVAL) + { + *op->resvalue = op->d.hashdatum_initvalue.init_value; + *op->resnull = false; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_HASHDATUM_FIRST) + { + FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data; + + /* + * Save the Datum on non-null inputs, otherwise store 0 so that + * subsequent NEXT32 operations combine with an initialized value. + */ + if (!fcinfo->args[0].isnull) + *op->resvalue = op->d.hashdatum.fn_addr(fcinfo); + else + *op->resvalue = (Datum) 0; + + *op->resnull = false; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_HASHDATUM_FIRST_STRICT) + { + FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data; + + if (fcinfo->args[0].isnull) + { + /* + * With strict we have the expression return NULL instead of + * ignoring NULL input values. We've nothing more to do after + * finding a NULL. + */ + *op->resnull = true; + *op->resvalue = (Datum) 0; + EEO_JUMP(op->d.hashdatum.jumpdone); + } + + /* execute the hash function and save the resulting value */ + *op->resvalue = op->d.hashdatum.fn_addr(fcinfo); + *op->resnull = false; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_HASHDATUM_NEXT32) + { + FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data; + uint32 existinghash; + + existinghash = DatumGetUInt32(op->d.hashdatum.iresult->value); + /* combine successive hash values by rotating */ + existinghash = pg_rotate_left32(existinghash, 1); + + /* leave the hash value alone on NULL inputs */ + if (!fcinfo->args[0].isnull) + { + uint32 hashvalue; + + /* execute hash func and combine with previous hash value */ + hashvalue = DatumGetUInt32(op->d.hashdatum.fn_addr(fcinfo)); + existinghash = existinghash ^ hashvalue; + } + + *op->resvalue = UInt32GetDatum(existinghash); + *op->resnull = false; + + EEO_NEXT(); + } + + EEO_CASE(EEOP_HASHDATUM_NEXT32_STRICT) + { + FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data; + + if (fcinfo->args[0].isnull) + { + /* + * With strict we have the expression return NULL instead of + * ignoring NULL input values. We've nothing more to do after + * finding a NULL. + */ + *op->resnull = true; + *op->resvalue = (Datum) 0; + EEO_JUMP(op->d.hashdatum.jumpdone); + } + else + { + uint32 existinghash; + uint32 hashvalue; + + existinghash = DatumGetUInt32(op->d.hashdatum.iresult->value); + /* combine successive hash values by rotating */ + existinghash = pg_rotate_left32(existinghash, 1); + + /* execute hash func and combine with previous hash value */ + hashvalue = DatumGetUInt32(op->d.hashdatum.fn_addr(fcinfo)); + *op->resvalue = UInt32GetDatum(existinghash ^ hashvalue); + *op->resnull = false; + } + + EEO_NEXT(); + } + EEO_CASE(EEOP_XMLEXPR) { /* too complex for an inline implementation */ @@ -1670,11 +2038,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) * input is not NULL. */ + /* when checking more than one argument */ EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS) { NullableDatum *args = op->d.agg_strict_input_check.args; int nargs = op->d.agg_strict_input_check.nargs; + Assert(nargs > 1); + for (int argno = 0; argno < nargs; argno++) { if (args[argno].isnull) @@ -1683,6 +2054,19 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + /* special case for just one argument */ + EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1) + { + NullableDatum *args = op->d.agg_strict_input_check.args; + PG_USED_FOR_ASSERTS_ONLY int nargs = op->d.agg_strict_input_check.nargs; + + Assert(nargs == 1); + + if (args[0].isnull) + EEO_JUMP(op->d.agg_strict_input_check.jumpnull); + EEO_NEXT(); + } + EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS) { bool *nulls = op->d.agg_strict_input_check.nulls; @@ -1885,13 +2269,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) { /* unreachable */ Assert(false); - goto out; + goto out_error; } } -out: - *isnull = state->resnull; - return state->resvalue; +out_error: + pg_unreachable(); + return (Datum) 0; } /* @@ -1925,10 +2309,14 @@ CheckExprStillValid(ExprState *state, ExprContext *econtext) TupleTableSlot *innerslot; TupleTableSlot *outerslot; TupleTableSlot *scanslot; + TupleTableSlot *oldslot; + TupleTableSlot *newslot; innerslot = econtext->ecxt_innertuple; outerslot = econtext->ecxt_outertuple; scanslot = econtext->ecxt_scantuple; + oldslot = econtext->ecxt_oldtuple; + newslot = econtext->ecxt_newtuple; for (int i = 0; i < state->steps_len; i++) { @@ -1959,6 +2347,22 @@ CheckExprStillValid(ExprState *state, ExprContext *econtext) CheckVarSlotCompatibility(scanslot, attnum + 1, op->d.var.vartype); break; } + + case EEOP_OLD_VAR: + { + int attnum = op->d.var.attnum; + + CheckVarSlotCompatibility(oldslot, attnum + 1, op->d.var.vartype); + break; + } + + case EEOP_NEW_VAR: + { + int attnum = op->d.var.attnum; + + CheckVarSlotCompatibility(newslot, attnum + 1, op->d.var.vartype); + break; + } default: break; } @@ -2001,6 +2405,10 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype) attr = TupleDescAttr(slot_tupdesc, attnum - 1); + /* Internal error: somebody forgot to expand it. */ + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + elog(ERROR, "unexpected virtual generated column reference"); + if (attr->attisdropped) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), @@ -2094,7 +2502,7 @@ get_cached_rowtype(Oid type_id, int32 typmod, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("type %s is not composite", format_type_be(type_id)))); - rowcache->cacheptr = (void *) typentry; + rowcache->cacheptr = typentry; rowcache->tupdesc_id = typentry->tupDesc_identifier; if (changed) *changed = true; @@ -2119,7 +2527,7 @@ get_cached_rowtype(Oid type_id, int32 typmod, tupDesc = lookup_rowtype_tupdesc(type_id, typmod); /* Drop pin acquired by lookup_rowtype_tupdesc */ ReleaseTupleDesc(tupDesc); - rowcache->cacheptr = (void *) tupDesc; + rowcache->cacheptr = tupDesc; rowcache->tupdesc_id = 0; /* not a valid value for non-RECORD */ if (changed) *changed = true; @@ -2352,6 +2760,148 @@ ExecJustAssignScanVarVirt(ExprState *state, ExprContext *econtext, bool *isnull) return ExecJustAssignVarVirtImpl(state, econtext->ecxt_scantuple, isnull); } +/* + * implementation for hashing an inner Var, seeding with an initial value. + */ +static Datum +ExecJustHashInnerVarWithIV(ExprState *state, ExprContext *econtext, + bool *isnull) +{ + ExprEvalStep *fetchop = &state->steps[0]; + ExprEvalStep *setivop = &state->steps[1]; + ExprEvalStep *innervar = &state->steps[2]; + ExprEvalStep *hashop = &state->steps[3]; + FunctionCallInfo fcinfo = hashop->d.hashdatum.fcinfo_data; + int attnum = innervar->d.var.attnum; + uint32 hashkey; + + CheckOpSlotCompatibility(fetchop, econtext->ecxt_innertuple); + slot_getsomeattrs(econtext->ecxt_innertuple, fetchop->d.fetch.last_var); + + fcinfo->args[0].value = econtext->ecxt_innertuple->tts_values[attnum]; + fcinfo->args[0].isnull = econtext->ecxt_innertuple->tts_isnull[attnum]; + + hashkey = DatumGetUInt32(setivop->d.hashdatum_initvalue.init_value); + hashkey = pg_rotate_left32(hashkey, 1); + + if (!fcinfo->args[0].isnull) + { + uint32 hashvalue; + + hashvalue = DatumGetUInt32(hashop->d.hashdatum.fn_addr(fcinfo)); + hashkey = hashkey ^ hashvalue; + } + + *isnull = false; + return UInt32GetDatum(hashkey); +} + +/* implementation of ExecJustHash(Inner|Outer)Var */ +static pg_attribute_always_inline Datum +ExecJustHashVarImpl(ExprState *state, TupleTableSlot *slot, bool *isnull) +{ + ExprEvalStep *fetchop = &state->steps[0]; + ExprEvalStep *var = &state->steps[1]; + ExprEvalStep *hashop = &state->steps[2]; + FunctionCallInfo fcinfo = hashop->d.hashdatum.fcinfo_data; + int attnum = var->d.var.attnum; + + CheckOpSlotCompatibility(fetchop, slot); + slot_getsomeattrs(slot, fetchop->d.fetch.last_var); + + fcinfo->args[0].value = slot->tts_values[attnum]; + fcinfo->args[0].isnull = slot->tts_isnull[attnum]; + + *isnull = false; + + if (!fcinfo->args[0].isnull) + return DatumGetUInt32(hashop->d.hashdatum.fn_addr(fcinfo)); + else + return (Datum) 0; +} + +/* implementation for hashing an outer Var */ +static Datum +ExecJustHashOuterVar(ExprState *state, ExprContext *econtext, bool *isnull) +{ + return ExecJustHashVarImpl(state, econtext->ecxt_outertuple, isnull); +} + +/* implementation for hashing an inner Var */ +static Datum +ExecJustHashInnerVar(ExprState *state, ExprContext *econtext, bool *isnull) +{ + return ExecJustHashVarImpl(state, econtext->ecxt_innertuple, isnull); +} + +/* implementation of ExecJustHash(Inner|Outer)VarVirt */ +static pg_attribute_always_inline Datum +ExecJustHashVarVirtImpl(ExprState *state, TupleTableSlot *slot, bool *isnull) +{ + ExprEvalStep *var = &state->steps[0]; + ExprEvalStep *hashop = &state->steps[1]; + FunctionCallInfo fcinfo = hashop->d.hashdatum.fcinfo_data; + int attnum = var->d.var.attnum; + + fcinfo->args[0].value = slot->tts_values[attnum]; + fcinfo->args[0].isnull = slot->tts_isnull[attnum]; + + *isnull = false; + + if (!fcinfo->args[0].isnull) + return DatumGetUInt32(hashop->d.hashdatum.fn_addr(fcinfo)); + else + return (Datum) 0; +} + +/* Like ExecJustHashInnerVar, optimized for virtual slots */ +static Datum +ExecJustHashInnerVarVirt(ExprState *state, ExprContext *econtext, + bool *isnull) +{ + return ExecJustHashVarVirtImpl(state, econtext->ecxt_innertuple, isnull); +} + +/* Like ExecJustHashOuterVar, optimized for virtual slots */ +static Datum +ExecJustHashOuterVarVirt(ExprState *state, ExprContext *econtext, + bool *isnull) +{ + return ExecJustHashVarVirtImpl(state, econtext->ecxt_outertuple, isnull); +} + +/* + * implementation for hashing an outer Var. Returns NULL on NULL input. + */ +static Datum +ExecJustHashOuterVarStrict(ExprState *state, ExprContext *econtext, + bool *isnull) +{ + ExprEvalStep *fetchop = &state->steps[0]; + ExprEvalStep *var = &state->steps[1]; + ExprEvalStep *hashop = &state->steps[2]; + FunctionCallInfo fcinfo = hashop->d.hashdatum.fcinfo_data; + int attnum = var->d.var.attnum; + + CheckOpSlotCompatibility(fetchop, econtext->ecxt_outertuple); + slot_getsomeattrs(econtext->ecxt_outertuple, fetchop->d.fetch.last_var); + + fcinfo->args[0].value = econtext->ecxt_outertuple->tts_values[attnum]; + fcinfo->args[0].isnull = econtext->ecxt_outertuple->tts_isnull[attnum]; + + if (!fcinfo->args[0].isnull) + { + *isnull = false; + return DatumGetUInt32(hashop->d.hashdatum.fn_addr(fcinfo)); + } + else + { + /* return NULL on NULL input */ + *isnull = true; + return (Datum) 0; + } +} + #if defined(EEO_USE_COMPUTED_GOTO) /* * Comparator used when building address->opcode lookup table for @@ -2555,6 +3105,24 @@ ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext) errmsg("no value found for parameter %d", paramId))); } +/* + * Set value of a param (currently always PARAM_EXEC) from + * state->res{value,null}. + */ +void +ExecEvalParamSet(ExprState *state, ExprEvalStep *op, ExprContext *econtext) +{ + ParamExecData *prm; + + prm = &(econtext->ecxt_param_exec_vals[op->d.param.paramid]); + + /* Shouldn't have a pending evaluation anymore */ + Assert(prm->execPlan == NULL); + + prm->value = state->resvalue; + prm->isnull = state->resnull; +} + /* * Evaluate a CoerceViaIO node in soft-error mode. * @@ -2798,7 +3366,7 @@ ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, for (int att = 1; att <= tupDesc->natts; att++) { /* ignore dropped columns */ - if (TupleDescAttr(tupDesc, att - 1)->attisdropped) + if (TupleDescCompactAttr(tupDesc, att - 1)->attisdropped) continue; if (heap_attisnull(&tmptup, att, tupDesc)) { @@ -4303,13 +4871,7 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op, if (!error) { *op->resnull = false; - if (jsexpr->use_json_coercion) - *op->resvalue = DirectFunctionCall1(jsonb_in, - BoolGetDatum(exists) ? - CStringGetDatum("true") : - CStringGetDatum("false")); - else - *op->resvalue = BoolGetDatum(exists); + *op->resvalue = BoolGetDatum(exists); } } break; @@ -4420,8 +4982,8 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op, /* Set up to catch coercion errors of the ON EMPTY value. */ jsestate->escontext.error_occurred = false; jsestate->escontext.details_wanted = true; - Assert(jsestate->jump_empty >= 0); - return jsestate->jump_empty; + /* Jump to end if the ON EMPTY behavior is to return NULL */ + return jsestate->jump_empty >= 0 ? jsestate->jump_empty : jsestate->jump_end; } } else if (jsexpr->on_error->btype != JSON_BEHAVIOR_ERROR) @@ -4430,8 +4992,9 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op, /* Set up to catch coercion errors of the ON ERROR value. */ jsestate->escontext.error_occurred = false; jsestate->escontext.details_wanted = true; - Assert(!throw_error && jsestate->jump_error >= 0); - return jsestate->jump_error; + Assert(!throw_error); + /* Jump to end if the ON ERROR behavior is to return NULL */ + return jsestate->jump_error >= 0 ? jsestate->jump_error : jsestate->jump_end; } if (jsexpr->column_name) @@ -4451,14 +5014,15 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op, */ if (error) { - Assert(!throw_error && jsestate->jump_error >= 0); + Assert(!throw_error); *op->resvalue = (Datum) 0; *op->resnull = true; jsestate->error.value = BoolGetDatum(true); /* Set up to catch coercion errors of the ON ERROR value. */ jsestate->escontext.error_occurred = false; jsestate->escontext.details_wanted = true; - return jsestate->jump_error; + /* Jump to end if the ON ERROR behavior is to return NULL */ + return jsestate->jump_error >= 0 ? jsestate->jump_error : jsestate->jump_end; } return jump_eval_coercion >= 0 ? jump_eval_coercion : jsestate->jump_end; @@ -4550,10 +5114,46 @@ ExecEvalJsonCoercion(ExprState *state, ExprEvalStep *op, { ErrorSaveContext *escontext = op->d.jsonexpr_coercion.escontext; + /* + * Prepare to call json_populate_type() to coerce the boolean result of + * JSON_EXISTS_OP to the target type. If the target type is integer or a + * domain over integer, call the boolean-to-integer cast function instead, + * because the integer's input function (which is what + * json_populate_type() calls to coerce to scalar target types) doesn't + * accept boolean literals as valid input. We only have a special case + * for integer and domains thereof as it seems common to use those types + * for EXISTS columns in JSON_TABLE(). + */ + if (op->d.jsonexpr_coercion.exists_coerce) + { + if (op->d.jsonexpr_coercion.exists_cast_to_int) + { + /* Check domain constraints if any. */ + if (op->d.jsonexpr_coercion.exists_check_domain && + !domain_check_safe(*op->resvalue, *op->resnull, + op->d.jsonexpr_coercion.targettype, + &op->d.jsonexpr_coercion.json_coercion_cache, + econtext->ecxt_per_query_memory, + (Node *) escontext)) + { + *op->resnull = true; + *op->resvalue = (Datum) 0; + } + else + *op->resvalue = DirectFunctionCall1(bool_int4, *op->resvalue); + return; + } + + *op->resvalue = DirectFunctionCall1(jsonb_in, + DatumGetBool(*op->resvalue) ? + CStringGetDatum("true") : + CStringGetDatum("false")); + } + *op->resvalue = json_populate_type(*op->resvalue, JSONBOID, op->d.jsonexpr_coercion.targettype, op->d.jsonexpr_coercion.targettypmod, - &op->d.jsonexpr_coercion.json_populate_type_cache, + &op->d.jsonexpr_coercion.json_coercion_cache, econtext->ecxt_per_query_memory, op->resnull, op->d.jsonexpr_coercion.omit_quotes, @@ -4596,7 +5196,7 @@ ExecEvalJsonCoercionFinish(ExprState *state, ExprEvalStep *op) if (SOFT_ERROR_OCCURRED(&jsestate->escontext)) { /* - * jsestate->error or jsetate->empty being set means that the error + * jsestate->error or jsestate->empty being set means that the error * occurred when coercing the JsonBehavior value. Throw the error in * that case with the actual coercion error message shown in the * DETAIL part. @@ -4604,13 +5204,17 @@ ExecEvalJsonCoercionFinish(ExprState *state, ExprEvalStep *op) if (DatumGetBool(jsestate->error.value)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("could not coerce ON ERROR expression (%s) to the RETURNING type", + /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */ + errmsg("could not coerce %s expression (%s) to the RETURNING type", + "ON ERROR", GetJsonBehaviorValueString(jsestate->jsexpr->on_error)), errdetail("%s", jsestate->escontext.error_data->message))); else if (DatumGetBool(jsestate->empty.value)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("could not coerce ON EMPTY expression (%s) to the RETURNING type", + /*- translator: first %s is a SQL/JSON clause (e.g. ON ERROR) */ + errmsg("could not coerce %s expression (%s) to the RETURNING type", + "ON EMPTY", GetJsonBehaviorValueString(jsestate->jsexpr->on_empty)), errdetail("%s", jsestate->escontext.error_data->message))); @@ -4723,7 +5327,7 @@ void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) { Var *variable = op->d.wholerow.var; - TupleTableSlot *slot; + TupleTableSlot *slot = NULL; TupleDesc output_tupdesc; MemoryContext oldcontext; HeapTupleHeader dtuple; @@ -4748,8 +5352,40 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) /* INDEX_VAR is handled by default case */ default: - /* get the tuple from the relation being scanned */ - slot = econtext->ecxt_scantuple; + + /* + * Get the tuple from the relation being scanned. + * + * By default, this uses the "scan" tuple slot, but a wholerow Var + * in the RETURNING list may explicitly refer to OLD/NEW. If the + * OLD/NEW row doesn't exist, we just return NULL. + */ + switch (variable->varreturningtype) + { + case VAR_RETURNING_DEFAULT: + slot = econtext->ecxt_scantuple; + break; + + case VAR_RETURNING_OLD: + if (state->flags & EEO_FLAG_OLD_IS_NULL) + { + *op->resvalue = (Datum) 0; + *op->resnull = true; + return; + } + slot = econtext->ecxt_oldtuple; + break; + + case VAR_RETURNING_NEW: + if (state->flags & EEO_FLAG_NEW_IS_NULL) + { + *op->resvalue = (Datum) 0; + *op->resnull = true; + return; + } + slot = econtext->ecxt_newtuple; + break; + } break; } @@ -4906,15 +5542,15 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) for (int i = 0; i < var_tupdesc->natts; i++) { - Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i); - Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i); + CompactAttribute *vattr = TupleDescCompactAttr(var_tupdesc, i); + CompactAttribute *sattr = TupleDescCompactAttr(tupleDesc, i); if (!vattr->attisdropped) continue; /* already checked non-dropped cols */ if (slot->tts_isnull[i]) continue; /* null is always okay */ if (vattr->attlen != sattr->attlen || - vattr->attalign != sattr->attalign) + vattr->attalignby != sattr->attalignby) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table row type and query-specified row type do not match"), @@ -4952,6 +5588,17 @@ ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext, { Datum d; + /* OLD/NEW system attribute is NULL if OLD/NEW row is NULL */ + if ((op->d.var.varreturningtype == VAR_RETURNING_OLD && + state->flags & EEO_FLAG_OLD_IS_NULL) || + (op->d.var.varreturningtype == VAR_RETURNING_NEW && + state->flags & EEO_FLAG_NEW_IS_NULL)) + { + *op->resvalue = (Datum) 0; + *op->resnull = true; + return; + } + /* slot_getsysattr has sufficient defenses against bad attnums */ d = slot_getsysattr(slot, op->d.var.attnum, diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 7233f1e3c039d..b540074935386 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -3,7 +3,7 @@ * execGrouping.c * executor utility routines for grouping, hashing, and aggregation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -62,13 +62,15 @@ execTuplesMatchPrepare(TupleDesc desc, const Oid *collations, PlanState *parent) { - Oid *eqFunctions = (Oid *) palloc(numCols * sizeof(Oid)); + Oid *eqFunctions; int i; ExprState *expr; if (numCols == 0) return NULL; + eqFunctions = (Oid *) palloc(numCols * sizeof(Oid)); + /* lookup equality functions */ for (i = 0; i < numCols; i++) eqFunctions[i] = get_opcode(eqOperators[i]); @@ -133,42 +135,54 @@ execTuplesHashPrepare(int numCols, /* * Construct an empty TupleHashTable * - * numCols, keyColIdx: identify the tuple fields to use as lookup key - * eqfunctions: equality comparison functions to use - * hashfunctions: datatype-specific hashing functions to use + * parent: PlanState node that will own this hash table + * inputDesc: tuple descriptor for input tuples + * inputOps: slot ops for input tuples, or NULL if unknown or not fixed + * numCols: number of columns to be compared (length of next 4 arrays) + * keyColIdx: indexes of tuple columns to compare + * eqfuncoids: OIDs of equality comparison functions to use + * hashfunctions: FmgrInfos of datatype-specific hashing functions to use + * collations: collations to use in comparisons * nbuckets: initial estimate of hashtable size - * additionalsize: size of data stored in ->additional + * additionalsize: size of data that may be stored along with the hash entry * metacxt: memory context for long-lived allocation, but not per-entry data * tablecxt: memory context in which to store table entries * tempcxt: short-lived context for evaluation hash and comparison functions + * use_variable_hash_iv: if true, adjust hash IV per-parallel-worker * - * The function arrays may be made with execTuplesHashPrepare(). Note they + * The hashfunctions array may be made with execTuplesHashPrepare(). Note they * are not cross-type functions, but expect to see the table datatype(s) * on both sides. * - * Note that keyColIdx, eqfunctions, and hashfunctions must be allocated in - * storage that will live as long as the hashtable does. + * Note that the keyColIdx, hashfunctions, and collations arrays must be + * allocated in storage that will live as long as the hashtable does. */ TupleHashTable -BuildTupleHashTableExt(PlanState *parent, - TupleDesc inputDesc, - int numCols, AttrNumber *keyColIdx, - const Oid *eqfuncoids, - FmgrInfo *hashfunctions, - Oid *collations, - long nbuckets, Size additionalsize, - MemoryContext metacxt, - MemoryContext tablecxt, - MemoryContext tempcxt, - bool use_variable_hash_iv) +BuildTupleHashTable(PlanState *parent, + TupleDesc inputDesc, + const TupleTableSlotOps *inputOps, + int numCols, + AttrNumber *keyColIdx, + const Oid *eqfuncoids, + FmgrInfo *hashfunctions, + Oid *collations, + long nbuckets, + Size additionalsize, + MemoryContext metacxt, + MemoryContext tablecxt, + MemoryContext tempcxt, + bool use_variable_hash_iv) { TupleHashTable hashtable; - Size entrysize = sizeof(TupleHashEntryData) + additionalsize; + Size entrysize; Size hash_mem_limit; MemoryContext oldcontext; bool allow_jit; + uint32 hash_iv = 0; Assert(nbuckets > 0); + additionalsize = MAXALIGN(additionalsize); + entrysize = sizeof(TupleHashEntryData) + additionalsize; /* Limit initial table size request to not more than hash_mem */ hash_mem_limit = get_hash_memory_limit() / entrysize; @@ -181,14 +195,13 @@ BuildTupleHashTableExt(PlanState *parent, hashtable->numCols = numCols; hashtable->keyColIdx = keyColIdx; - hashtable->tab_hash_funcs = hashfunctions; hashtable->tab_collations = collations; hashtable->tablecxt = tablecxt; hashtable->tempcxt = tempcxt; - hashtable->entrysize = entrysize; + hashtable->additionalsize = additionalsize; hashtable->tableslot = NULL; /* will be made on first lookup */ hashtable->inputslot = NULL; - hashtable->in_hash_funcs = NULL; + hashtable->in_hash_expr = NULL; hashtable->cur_eq_func = NULL; /* @@ -200,9 +213,7 @@ BuildTupleHashTableExt(PlanState *parent, * underestimated. */ if (use_variable_hash_iv) - hashtable->hash_iv = murmurhash32(ParallelWorkerNumber); - else - hashtable->hash_iv = 0; + hash_iv = murmurhash32(ParallelWorkerNumber); hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable); @@ -214,19 +225,29 @@ BuildTupleHashTableExt(PlanState *parent, &TTSOpsMinimalTuple); /* - * If the old reset interface is used (i.e. BuildTupleHashTable, rather - * than BuildTupleHashTableExt), allowing JIT would lead to the generated - * functions to a) live longer than the query b) be re-generated each time - * the table is being reset. Therefore prevent JIT from being used in that - * case, by not providing a parent node (which prevents accessing the - * JitContext in the EState). + * If the caller fails to make the metacxt different from the tablecxt, + * allowing JIT would lead to the generated functions to a) live longer + * than the query or b) be re-generated each time the table is being + * reset. Therefore prevent JIT from being used in that case, by not + * providing a parent node (which prevents accessing the JitContext in the + * EState). */ - allow_jit = metacxt != tablecxt; + allow_jit = (metacxt != tablecxt); + + /* build hash ExprState for all columns */ + hashtable->tab_hash_expr = ExecBuildHash32FromAttrs(inputDesc, + inputOps, + hashfunctions, + collations, + numCols, + keyColIdx, + allow_jit ? parent : NULL, + hash_iv); /* build comparator for all columns */ - /* XXX: should we support non-minimal tuples for the inputslot? */ hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc, - &TTSOpsMinimalTuple, &TTSOpsMinimalTuple, + inputOps, + &TTSOpsMinimalTuple, numCols, keyColIdx, eqfuncoids, collations, allow_jit ? parent : NULL); @@ -244,40 +265,9 @@ BuildTupleHashTableExt(PlanState *parent, return hashtable; } -/* - * BuildTupleHashTable is a backwards-compatibility wrapper for - * BuildTupleHashTableExt(), that allocates the hashtable's metadata in - * tablecxt. Note that hashtables created this way cannot be reset leak-free - * with ResetTupleHashTable(). - */ -TupleHashTable -BuildTupleHashTable(PlanState *parent, - TupleDesc inputDesc, - int numCols, AttrNumber *keyColIdx, - const Oid *eqfuncoids, - FmgrInfo *hashfunctions, - Oid *collations, - long nbuckets, Size additionalsize, - MemoryContext tablecxt, - MemoryContext tempcxt, - bool use_variable_hash_iv) -{ - return BuildTupleHashTableExt(parent, - inputDesc, - numCols, keyColIdx, - eqfuncoids, - hashfunctions, - collations, - nbuckets, additionalsize, - tablecxt, - tablecxt, - tempcxt, - use_variable_hash_iv); -} - /* * Reset contents of the hashtable to be empty, preserving all the non-content - * state. Note that the tablecxt passed to BuildTupleHashTableExt() should + * state. Note that the tablecxt passed to BuildTupleHashTable() should * also be reset, otherwise there will be leaks. */ void @@ -298,7 +288,7 @@ ResetTupleHashTable(TupleHashTable hashtable) * * If isnew isn't NULL, then a new entry is created if no existing entry * matches. On return, *isnew is true if the entry is newly created, - * false if it existed already. ->additional_data in the new entry has + * false if it existed already. The additional data in the new entry has * been zeroed. */ TupleHashEntry @@ -314,7 +304,7 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, /* set up data needed by hash and match functions */ hashtable->inputslot = slot; - hashtable->in_hash_funcs = hashtable->tab_hash_funcs; + hashtable->in_hash_expr = hashtable->tab_hash_expr; hashtable->cur_eq_func = hashtable->tab_eq_func; local_hash = TupleHashTableHash_internal(hashtable->hashtab, NULL); @@ -340,7 +330,7 @@ TupleHashTableHash(TupleHashTable hashtable, TupleTableSlot *slot) uint32 hash; hashtable->inputslot = slot; - hashtable->in_hash_funcs = hashtable->tab_hash_funcs; + hashtable->in_hash_expr = hashtable->tab_hash_expr; /* Need to run the hash functions in short-lived context */ oldContext = MemoryContextSwitchTo(hashtable->tempcxt); @@ -368,7 +358,7 @@ LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot, /* set up data needed by hash and match functions */ hashtable->inputslot = slot; - hashtable->in_hash_funcs = hashtable->tab_hash_funcs; + hashtable->in_hash_expr = hashtable->tab_hash_expr; hashtable->cur_eq_func = hashtable->tab_eq_func; entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash); @@ -384,14 +374,14 @@ LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot, * created if there's not a match. This is similar to the non-creating * case of LookupTupleHashEntry, except that it supports cross-type * comparisons, in which the given tuple is not of the same type as the - * table entries. The caller must provide the hash functions to use for - * the input tuple, as well as the equality functions, since these may be + * table entries. The caller must provide the hash ExprState to use for + * the input tuple, as well as the equality ExprState, since these may be * different from the table's internal functions. */ TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, - FmgrInfo *hashfunctions) + ExprState *hashexpr) { TupleHashEntry entry; MemoryContext oldContext; @@ -402,7 +392,7 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, /* Set up data needed by hash and match functions */ hashtable->inputslot = slot; - hashtable->in_hash_funcs = hashfunctions; + hashtable->in_hash_expr = hashexpr; hashtable->cur_eq_func = eqcomp; /* Search the hash table */ @@ -419,25 +409,24 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, * copied into the table. * * Also, the caller must select an appropriate memory context for running - * the hash functions. (dynahash.c doesn't change CurrentMemoryContext.) + * the hash functions. */ static uint32 TupleHashTableHash_internal(struct tuplehash_hash *tb, const MinimalTuple tuple) { TupleHashTable hashtable = (TupleHashTable) tb->private_data; - int numCols = hashtable->numCols; - AttrNumber *keyColIdx = hashtable->keyColIdx; - uint32 hashkey = hashtable->hash_iv; + uint32 hashkey; TupleTableSlot *slot; - FmgrInfo *hashfunctions; - int i; + bool isnull; if (tuple == NULL) { /* Process the current input tuple for the table */ - slot = hashtable->inputslot; - hashfunctions = hashtable->in_hash_funcs; + hashtable->exprcontext->ecxt_innertuple = hashtable->inputslot; + hashkey = DatumGetUInt32(ExecEvalExpr(hashtable->in_hash_expr, + hashtable->exprcontext, + &isnull)); } else { @@ -447,38 +436,17 @@ TupleHashTableHash_internal(struct tuplehash_hash *tb, * (this case never actually occurs due to the way simplehash.h is * used, as the hash-value is stored in the entries) */ - slot = hashtable->tableslot; + slot = hashtable->exprcontext->ecxt_innertuple = hashtable->tableslot; ExecStoreMinimalTuple(tuple, slot, false); - hashfunctions = hashtable->tab_hash_funcs; - } - - for (i = 0; i < numCols; i++) - { - AttrNumber att = keyColIdx[i]; - Datum attr; - bool isNull; - - /* combine successive hashkeys by rotating */ - hashkey = pg_rotate_left32(hashkey, 1); - - attr = slot_getattr(slot, att, &isNull); - - if (!isNull) /* treat nulls as having hash key 0 */ - { - uint32 hkey; - - hkey = DatumGetUInt32(FunctionCall1Coll(&hashfunctions[i], - hashtable->tab_collations[i], - attr)); - hashkey ^= hkey; - } + hashkey = DatumGetUInt32(ExecEvalExpr(hashtable->tab_hash_expr, + hashtable->exprcontext, + &isnull)); } /* - * The way hashes are combined above, among each other and with the IV, - * doesn't lead to good bit perturbation. As the IV's goal is to lead to - * achieve that, perform a round of hashing of the combined hash - - * resulting in near perfect perturbation. + * The hashing done above, even with an initial value, doesn't tend to + * result in good hash perturbation. Running the value produced above + * through murmurhash32 leads to near perfect hash perturbation. */ return murmurhash32(hashkey); } @@ -514,11 +482,21 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot, { /* created new entry */ *isnew = true; - /* zero caller data */ - entry->additional = NULL; + MemoryContextSwitchTo(hashtable->tablecxt); - /* Copy the first tuple into the table context */ - entry->firstTuple = ExecCopySlotMinimalTuple(slot); + + /* + * Copy the first tuple into the table context, and request + * additionalsize extra bytes before the allocation. + * + * The caller can get a pointer to the additional data with + * TupleHashEntryGetAdditional(), and store arbitrary data there. + * Placing both the tuple and additional data in the same + * allocation avoids the need to store an extra pointer in + * TupleHashEntryData or allocate an additional chunk. + */ + entry->firstTuple = ExecCopySlotMinimalTupleExtra(slot, + hashtable->additionalsize); } } else diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 9f05b3654c186..bdf862b24062e 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -95,7 +95,7 @@ * with the higher XID backs out. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -114,6 +114,8 @@ #include "executor/executor.h" #include "nodes/nodeFuncs.h" #include "storage/lmgr.h" +#include "utils/multirangetypes.h" +#include "utils/rangetypes.h" #include "utils/snapmgr.h" /* waitMode argument to check_exclusion_or_unique_constraint() */ @@ -141,6 +143,8 @@ static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo, Relation indexRelation); static bool index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols); +static void ExecWithoutOverlapsNotEmpty(Relation rel, NameData attname, Datum attval, + char typtype, Oid atttypid); /* ---------------------------------------------------------------- * ExecOpenIndices @@ -177,6 +181,9 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative) if (len == 0) return; + /* This Assert will fail if ExecOpenIndices is called twice */ + Assert(resultRelInfo->ri_IndexRelationDescs == NULL); + /* * allocate space for result arrays */ @@ -210,7 +217,7 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative) * If the indexes are to be used for speculative insertion, add extra * information required by unique index entries. */ - if (speculative && ii->ii_Unique) + if (speculative && ii->ii_Unique && !indexDesc->rd_index->indisexclusion) BuildSpeculativeIndexInfo(indexDesc, ii); relationDescs[i] = indexDesc; @@ -241,19 +248,23 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo) for (i = 0; i < numIndices; i++) { - if (indexDescs[i] == NULL) - continue; /* shouldn't happen? */ + /* This Assert will fail if ExecCloseIndices is called twice */ + Assert(indexDescs[i] != NULL); /* Give the index a chance to do some post-insert cleanup */ index_insert_cleanup(indexDescs[i], indexInfos[i]); /* Drop lock acquired by ExecOpenIndices */ index_close(indexDescs[i], RowExclusiveLock); + + /* Mark the index as closed */ + indexDescs[i] = NULL; } /* - * XXX should free indexInfo array here too? Currently we assume that - * such stuff will be cleaned up automatically in FreeExecutorState. + * We don't attempt to free the IndexInfo data structures or the arrays, + * instead assuming that such stuff will be cleaned up automatically in + * FreeExecutorState. */ } @@ -519,14 +530,18 @@ ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, * * Note that this doesn't lock the values in any way, so it's * possible that a conflicting tuple is inserted immediately - * after this returns. But this can be used for a pre-check - * before insertion. + * after this returns. This can be used for either a pre-check + * before insertion or a re-check after finding a conflict. + * + * 'tupleid' should be the TID of the tuple that has been recently + * inserted (or can be invalid if we haven't inserted a new tuple yet). + * This tuple will be excluded from conflict checking. * ---------------------------------------------------------------- */ bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, - List *arbiterIndexes) + ItemPointer tupleid, List *arbiterIndexes) { int i; int numIndices; @@ -629,7 +644,7 @@ ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, satisfiesConstraint = check_exclusion_or_unique_constraint(heapRelation, indexRelation, - indexInfo, &invalidItemPtr, + indexInfo, tupleid, values, isnull, estate, false, CEOUC_WAIT, true, conflictTid); @@ -720,6 +735,32 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, constr_strats = indexInfo->ii_UniqueStrats; } + /* + * If this is a WITHOUT OVERLAPS constraint, we must also forbid empty + * ranges/multiranges. This must happen before we look for NULLs below, or + * a UNIQUE constraint could insert an empty range along with a NULL + * scalar part. + */ + if (indexInfo->ii_WithoutOverlaps) + { + /* + * Look up the type from the heap tuple, but check the Datum from the + * index tuple. + */ + AttrNumber attno = indexInfo->ii_IndexAttrNumbers[indnkeyatts - 1]; + + if (!isnull[indnkeyatts - 1]) + { + TupleDesc tupdesc = RelationGetDescr(heap); + Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1); + TypeCacheEntry *typcache = lookup_type_cache(att->atttypid, 0); + + ExecWithoutOverlapsNotEmpty(heap, att->attname, + values[indnkeyatts - 1], + typcache->typtype, att->atttypid); + } + } + /* * If any of the input values are NULL, and the index uses the default * nulls-are-distinct mode, the constraint check is assumed to pass (i.e., @@ -774,7 +815,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index, retry: conflict = false; found_self = false; - index_scan = index_beginscan(heap, index, &DirtySnapshot, indnkeyatts, 0); + index_scan = index_beginscan(heap, index, &DirtySnapshot, NULL, indnkeyatts, 0); index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0); while (index_getnext_slot(index_scan, ForwardScanDirection, existing_slot)) @@ -1095,5 +1136,39 @@ index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols) } return expression_tree_walker(node, index_expression_changed_walker, - (void *) allUpdatedCols); + allUpdatedCols); +} + +/* + * ExecWithoutOverlapsNotEmpty - raise an error if the tuple has an empty + * range or multirange in the given attribute. + */ +static void +ExecWithoutOverlapsNotEmpty(Relation rel, NameData attname, Datum attval, char typtype, Oid atttypid) +{ + bool isempty; + RangeType *r; + MultirangeType *mr; + + switch (typtype) + { + case TYPTYPE_RANGE: + r = DatumGetRangeTypeP(attval); + isempty = RangeIsEmpty(r); + break; + case TYPTYPE_MULTIRANGE: + mr = DatumGetMultirangeTypeP(attval); + isempty = MultirangeIsEmpty(mr); + break; + default: + elog(ERROR, "WITHOUT OVERLAPS column \"%s\" is not a range or multirange", + NameStr(attname)); + } + + /* Report a CHECK_VIOLATION */ + if (isempty) + ereport(ERROR, + (errcode(ERRCODE_CHECK_VIOLATION), + errmsg("empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"", + NameStr(attname), RelationGetRelationName(rel)))); } diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index b962c3138345f..3f196de1ad286 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -3,7 +3,7 @@ * execJunk.c * Junk attribute support stuff.... * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -169,7 +169,7 @@ ExecInitJunkFilterConversion(List *targetList, t = list_head(targetList); for (i = 0; i < cleanLength; i++) { - if (TupleDescAttr(cleanTupType, i)->attisdropped) + if (TupleDescCompactAttr(cleanTupType, i)->attisdropped) continue; /* map entry is already zero */ for (;;) { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 4d7c92d63c198..0391798dd2c33 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * before ExecutorEnd. This can be omitted only in case of EXPLAIN, * which should also omit ExecutorRun. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -46,11 +46,14 @@ #include "commands/matview.h" #include "commands/trigger.h" #include "executor/executor.h" +#include "executor/execPartition.h" #include "executor/nodeSubplan.h" #include "foreign/fdwapi.h" #include "mb/pg_wchar.h" #include "miscadmin.h" +#include "nodes/queryjumble.h" #include "parser/parse_relation.h" +#include "pgstat.h" #include "rewrite/rewriteHandler.h" #include "tcop/utility.h" #include "utils/acl.h" @@ -75,25 +78,21 @@ static void InitPlan(QueryDesc *queryDesc, int eflags); static void CheckValidRowMarkRel(Relation rel, RowMarkType markType); static void ExecPostprocessPlan(EState *estate); static void ExecEndPlan(PlanState *planstate, EState *estate); -static void ExecutePlan(EState *estate, PlanState *planstate, - bool use_parallel_mode, +static void ExecutePlan(QueryDesc *queryDesc, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, - DestReceiver *dest, - bool execute_once); + DestReceiver *dest); static bool ExecCheckOneRelPerms(RTEPermissionInfo *perminfo); static bool ExecCheckPermissionsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms); static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt); -static char *ExecBuildSlotValueDescription(Oid reloid, - TupleTableSlot *slot, - TupleDesc tupdesc, - Bitmapset *modifiedCols, - int maxfieldlen); static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree); +static void ReportNotNullViolationError(ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, + EState *estate, int attnum); /* end of local decls */ @@ -124,10 +123,12 @@ void ExecutorStart(QueryDesc *queryDesc, int eflags) { /* - * In some cases (e.g. an EXECUTE statement) a query execution will skip - * parse analysis, which means that the query_id won't be reported. Note - * that it's harmless to report the query_id multiple times, as the call - * will be ignored if the top level query_id has already been reported. + * In some cases (e.g. an EXECUTE statement or an execute message with the + * extended query protocol) the query_id won't be reported, so do it now. + * + * Note that it's harmless to report the query_id multiple times, as the + * call will be ignored if the top level query_id has already been + * reported. */ pgstat_report_query_id(queryDesc->plannedstmt->queryId, false); @@ -295,18 +296,17 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags) */ void ExecutorRun(QueryDesc *queryDesc, - ScanDirection direction, uint64 count, - bool execute_once) + ScanDirection direction, uint64 count) { if (ExecutorRun_hook) - (*ExecutorRun_hook) (queryDesc, direction, count, execute_once); + (*ExecutorRun_hook) (queryDesc, direction, count); else - standard_ExecutorRun(queryDesc, direction, count, execute_once); + standard_ExecutorRun(queryDesc, direction, count); } void standard_ExecutorRun(QueryDesc *queryDesc, - ScanDirection direction, uint64 count, bool execute_once) + ScanDirection direction, uint64 count) { EState *estate; CmdType operation; @@ -352,24 +352,24 @@ standard_ExecutorRun(QueryDesc *queryDesc, dest->rStartup(dest, operation, queryDesc->tupDesc); /* - * run plan + * Run plan, unless direction is NoMovement. + * + * Note: pquery.c selects NoMovement if a prior call already reached + * end-of-data in the user-specified fetch direction. This is important + * because various parts of the executor can misbehave if called again + * after reporting EOF. For example, heapam.c would actually restart a + * heapscan and return all its data afresh. There is also some doubt + * about whether a parallel plan would operate properly if an additional, + * necessarily non-parallel execution request occurs after completing a + * parallel execution. (That case should work, but it's untested.) */ if (!ScanDirectionIsNoMovement(direction)) - { - if (execute_once && queryDesc->already_executed) - elog(ERROR, "can't re-execute query flagged for single execution"); - queryDesc->already_executed = true; - - ExecutePlan(estate, - queryDesc->planstate, - queryDesc->plannedstmt->parallelModeNeeded, + ExecutePlan(queryDesc, operation, sendTuples, count, direction, - dest, - execute_once); - } + dest); /* * Update es_total_processed to keep track of the number of tuples @@ -485,6 +485,10 @@ standard_ExecutorEnd(QueryDesc *queryDesc) Assert(estate != NULL); + if (estate->es_parallel_workers_to_launch > 0) + pgstat_update_parallel_workers_stats((PgStat_Counter) estate->es_parallel_workers_to_launch, + (PgStat_Counter) estate->es_parallel_workers_launched); + /* * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This * Assert is needed because ExecutorFinish is new as of 9.1, and callers @@ -850,9 +854,22 @@ InitPlan(QueryDesc *queryDesc, int eflags) /* * initialize the node's execution state */ - ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos); + ExecInitRangeTable(estate, rangeTable, plannedstmt->permInfos, + bms_copy(plannedstmt->unprunableRelids)); estate->es_plannedstmt = plannedstmt; + estate->es_part_prune_infos = plannedstmt->partPruneInfos; + + /* + * Perform runtime "initial" pruning to identify which child subplans, + * corresponding to the children of plan nodes that contain + * PartitionPruneInfo such as Append, will not be executed. The results, + * which are bitmapsets of indexes of the child subplans that will be + * executed, are saved in es_part_prune_results. These results correspond + * to each PartitionPruneInfo entry, and the es_part_prune_results list is + * parallel to es_part_prune_infos. + */ + ExecDoInitialPruning(estate); /* * Next, build the ExecRowMark array from the PlanRowMark(s), if any. @@ -868,8 +885,13 @@ InitPlan(QueryDesc *queryDesc, int eflags) Relation relation; ExecRowMark *erm; - /* ignore "parent" rowmarks; they are irrelevant at runtime */ - if (rc->isParent) + /* + * Ignore "parent" rowmarks, because they are irrelevant at + * runtime. Also ignore the rowmarks belonging to child tables + * that have been pruned in ExecDoInitialPruning(). + */ + if (rc->isParent || + !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; /* get relation's OID (will produce InvalidOid if subquery) */ @@ -883,7 +905,7 @@ InitPlan(QueryDesc *queryDesc, int eflags) case ROW_MARK_SHARE: case ROW_MARK_KEYSHARE: case ROW_MARK_REFERENCE: - relation = ExecGetRangeTableRelation(estate, rc->rti); + relation = ExecGetRangeTableRelation(estate, rc->rti, false); break; case ROW_MARK_COPY: /* no physical table access is required */ @@ -1029,6 +1051,10 @@ CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation, Relation resultRel = resultRelInfo->ri_RelationDesc; FdwRoutine *fdwroutine; + /* Expect a fully-formed ResultRelInfo from InitResultRelInfo(). */ + Assert(resultRelInfo->ri_needLockTagTuple == + IsInplaceUpdateRelation(resultRel)); + switch (resultRel->rd_rel->relkind) { case RELKIND_RELATION: @@ -1209,6 +1235,8 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, resultRelInfo->ri_NumIndices = 0; resultRelInfo->ri_IndexRelationDescs = NULL; resultRelInfo->ri_IndexRelationInfo = NULL; + resultRelInfo->ri_needLockTagTuple = + IsInplaceUpdateRelation(resultRelationDesc); /* make a copy so as not to depend on relcache info not changing... */ resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc); if (resultRelInfo->ri_TrigDesc) @@ -1242,7 +1270,8 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, resultRelInfo->ri_projectNewInfoValid = false; resultRelInfo->ri_FdwState = NULL; resultRelInfo->ri_usesFdwDirectModify = false; - resultRelInfo->ri_ConstraintExprs = NULL; + resultRelInfo->ri_CheckConstraintExprs = NULL; + resultRelInfo->ri_GenVirtualNotNullConstraintExprs = NULL; resultRelInfo->ri_GeneratedExprsI = NULL; resultRelInfo->ri_GeneratedExprsU = NULL; resultRelInfo->ri_projectReturning = NULL; @@ -1251,6 +1280,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo, resultRelInfo->ri_ReturningSlot = NULL; resultRelInfo->ri_TrigOldSlot = NULL; resultRelInfo->ri_TrigNewSlot = NULL; + resultRelInfo->ri_AllNullSlot = NULL; resultRelInfo->ri_MergeActions[MERGE_WHEN_MATCHED] = NIL; resultRelInfo->ri_MergeActions[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] = NIL; resultRelInfo->ri_MergeActions[MERGE_WHEN_NOT_MATCHED_BY_TARGET] = NIL; @@ -1592,22 +1622,19 @@ ExecCloseRangeTableRelations(EState *estate) * moving in the specified direction. * * Runs to completion if numberTuples is 0 - * - * Note: the ctid attribute is a 'junk' attribute that is removed before the - * user can see it * ---------------------------------------------------------------- */ static void -ExecutePlan(EState *estate, - PlanState *planstate, - bool use_parallel_mode, +ExecutePlan(QueryDesc *queryDesc, CmdType operation, bool sendTuples, uint64 numberTuples, ScanDirection direction, - DestReceiver *dest, - bool execute_once) + DestReceiver *dest) { + EState *estate = queryDesc->estate; + PlanState *planstate = queryDesc->planstate; + bool use_parallel_mode; TupleTableSlot *slot; uint64 current_tuple_count; @@ -1622,11 +1649,17 @@ ExecutePlan(EState *estate, estate->es_direction = direction; /* - * If the plan might potentially be executed multiple times, we must force - * it to run without parallelism, because we might exit early. + * Set up parallel mode if appropriate. + * + * Parallel mode only supports complete execution of a plan. If we've + * already partially executed it, or if the caller asks us to exit early, + * we must force the plan to run without parallelism. */ - if (!execute_once) + if (queryDesc->already_executed || numberTuples != 0) use_parallel_mode = false; + else + use_parallel_mode = queryDesc->plannedstmt->parallelModeNeeded; + queryDesc->already_executed = true; estate->es_use_parallel_mode = use_parallel_mode; if (use_parallel_mode) @@ -1709,7 +1742,7 @@ ExecutePlan(EState *estate, /* - * ExecRelCheck --- check that tuple meets constraints for result relation + * ExecRelCheck --- check that tuple meets check constraints for result relation * * Returns NULL if OK, else name of failed check constraint */ @@ -1722,10 +1755,9 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, ConstrCheck *check = rel->rd_att->constr->check; ExprContext *econtext; MemoryContext oldContext; - int i; /* - * CheckConstraintFetch let this pass with only a warning, but now we + * CheckNNConstraintFetch let this pass with only a warning, but now we * should fail rather than possibly failing to enforce an important * constraint. */ @@ -1738,17 +1770,21 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, * nodetrees for rel's constraint expressions. Keep them in the per-query * memory context so they'll survive throughout the query. */ - if (resultRelInfo->ri_ConstraintExprs == NULL) + if (resultRelInfo->ri_CheckConstraintExprs == NULL) { oldContext = MemoryContextSwitchTo(estate->es_query_cxt); - resultRelInfo->ri_ConstraintExprs = - (ExprState **) palloc(ncheck * sizeof(ExprState *)); - for (i = 0; i < ncheck; i++) + resultRelInfo->ri_CheckConstraintExprs = palloc0_array(ExprState *, ncheck); + for (int i = 0; i < ncheck; i++) { Expr *checkconstr; + /* Skip not enforced constraint */ + if (!check[i].ccenforced) + continue; + checkconstr = stringToNode(check[i].ccbin); - resultRelInfo->ri_ConstraintExprs[i] = + checkconstr = (Expr *) expand_generated_columns_in_expr((Node *) checkconstr, rel, 1); + resultRelInfo->ri_CheckConstraintExprs[i] = ExecPrepareExpr(checkconstr, estate); } MemoryContextSwitchTo(oldContext); @@ -1764,16 +1800,16 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, econtext->ecxt_scantuple = slot; /* And evaluate the constraints */ - for (i = 0; i < ncheck; i++) + for (int i = 0; i < ncheck; i++) { - ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i]; + ExprState *checkconstr = resultRelInfo->ri_CheckConstraintExprs[i]; /* * NOTE: SQL specifies that a NULL result from a constraint expression * is not to be treated as a failure. Therefore, use ExecCheck not * ExecQual. */ - if (!ExecCheck(checkconstr, econtext)) + if (checkconstr && !ExecCheck(checkconstr, econtext)) return check[i].ccname; } @@ -1920,73 +1956,45 @@ ExecConstraints(ResultRelInfo *resultRelInfo, TupleDesc tupdesc = RelationGetDescr(rel); TupleConstr *constr = tupdesc->constr; Bitmapset *modifiedCols; + List *notnull_virtual_attrs = NIL; Assert(constr); /* we should not be called otherwise */ + /* + * Verify not-null constraints. + * + * Not-null constraints on virtual generated columns are collected and + * checked separately below. + */ if (constr->has_not_null) { - int natts = tupdesc->natts; - int attrChk; - - for (attrChk = 1; attrChk <= natts; attrChk++) + for (AttrNumber attnum = 1; attnum <= tupdesc->natts; attnum++) { - Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1); - - if (att->attnotnull && slot_attisnull(slot, attrChk)) - { - char *val_desc; - Relation orig_rel = rel; - TupleDesc orig_tupdesc = RelationGetDescr(rel); - - /* - * If the tuple has been routed, it's been converted to the - * partition's rowtype, which might differ from the root - * table's. We must convert it back to the root table's - * rowtype so that val_desc shown error message matches the - * input tuple. - */ - if (resultRelInfo->ri_RootResultRelInfo) - { - ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo; - AttrMap *map; + Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1); - tupdesc = RelationGetDescr(rootrel->ri_RelationDesc); - /* a reverse map */ - map = build_attrmap_by_name_if_req(orig_tupdesc, - tupdesc, - false); + if (att->attnotnull && att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + notnull_virtual_attrs = lappend_int(notnull_virtual_attrs, attnum); + else if (att->attnotnull && slot_attisnull(slot, attnum)) + ReportNotNullViolationError(resultRelInfo, slot, estate, attnum); + } + } - /* - * Partition-specific slot's tupdesc can't be changed, so - * allocate a new one. - */ - if (map != NULL) - slot = execute_attr_map_slot(map, slot, - MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); - modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate), - ExecGetUpdatedCols(rootrel, estate)); - rel = rootrel->ri_RelationDesc; - } - else - modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate), - ExecGetUpdatedCols(resultRelInfo, estate)); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - slot, - tupdesc, - modifiedCols, - 64); + /* + * Verify not-null constraints on virtual generated column, if any. + */ + if (notnull_virtual_attrs) + { + AttrNumber attnum; - ereport(ERROR, - (errcode(ERRCODE_NOT_NULL_VIOLATION), - errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint", - NameStr(att->attname), - RelationGetRelationName(orig_rel)), - val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, - errtablecol(orig_rel, attrChk))); - } - } + attnum = ExecRelGenVirtualNotNull(resultRelInfo, slot, estate, + notnull_virtual_attrs); + if (attnum != InvalidAttrNumber) + ReportNotNullViolationError(resultRelInfo, slot, estate, attnum); } + /* + * Verify check constraints. + */ if (rel->rd_rel->relchecks > 0) { const char *failed; @@ -1996,7 +2004,12 @@ ExecConstraints(ResultRelInfo *resultRelInfo, char *val_desc; Relation orig_rel = rel; - /* See the comment above. */ + /* + * If the tuple has been routed, it's been converted to the + * partition's rowtype, which might differ from the root table's. + * We must convert it back to the root table's rowtype so that + * val_desc shown error message matches the input tuple. + */ if (resultRelInfo->ri_RootResultRelInfo) { ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo; @@ -2038,6 +2051,142 @@ ExecConstraints(ResultRelInfo *resultRelInfo, } } +/* + * Verify not-null constraints on virtual generated columns of the given + * tuple slot. + * + * Return value of InvalidAttrNumber means all not-null constraints on virtual + * generated columns are satisfied. A return value > 0 means a not-null + * violation happened for that attribute. + * + * notnull_virtual_attrs is the list of the attnums of virtual generated column with + * not-null constraints. + */ +AttrNumber +ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, + EState *estate, List *notnull_virtual_attrs) +{ + Relation rel = resultRelInfo->ri_RelationDesc; + ExprContext *econtext; + MemoryContext oldContext; + + /* + * We implement this by building a NullTest node for each virtual + * generated column, which we cache in resultRelInfo, and running those + * through ExecCheck(). + */ + if (resultRelInfo->ri_GenVirtualNotNullConstraintExprs == NULL) + { + oldContext = MemoryContextSwitchTo(estate->es_query_cxt); + resultRelInfo->ri_GenVirtualNotNullConstraintExprs = + palloc0_array(ExprState *, list_length(notnull_virtual_attrs)); + + foreach_int(attnum, notnull_virtual_attrs) + { + int i = foreach_current_index(attnum); + NullTest *nnulltest; + + /* "generated_expression IS NOT NULL" check. */ + nnulltest = makeNode(NullTest); + nnulltest->arg = (Expr *) build_generation_expression(rel, attnum); + nnulltest->nulltesttype = IS_NOT_NULL; + nnulltest->argisrow = false; + nnulltest->location = -1; + + resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i] = + ExecPrepareExpr((Expr *) nnulltest, estate); + } + MemoryContextSwitchTo(oldContext); + } + + /* + * We will use the EState's per-tuple context for evaluating virtual + * generated column not null constraint expressions (creating it if it's + * not already there). + */ + econtext = GetPerTupleExprContext(estate); + + /* Arrange for econtext's scan tuple to be the tuple under test */ + econtext->ecxt_scantuple = slot; + + /* And evaluate the check constraints for virtual generated column */ + foreach_int(attnum, notnull_virtual_attrs) + { + int i = foreach_current_index(attnum); + ExprState *exprstate = resultRelInfo->ri_GenVirtualNotNullConstraintExprs[i]; + + Assert(exprstate != NULL); + if (!ExecCheck(exprstate, econtext)) + return attnum; + } + + /* InvalidAttrNumber result means no error */ + return InvalidAttrNumber; +} + +/* + * Report a violation of a not-null constraint that was already detected. + */ +static void +ReportNotNullViolationError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, + EState *estate, int attnum) +{ + Bitmapset *modifiedCols; + char *val_desc; + Relation rel = resultRelInfo->ri_RelationDesc; + Relation orig_rel = rel; + TupleDesc tupdesc = RelationGetDescr(rel); + TupleDesc orig_tupdesc = RelationGetDescr(rel); + Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1); + + Assert(attnum > 0); + + /* + * If the tuple has been routed, it's been converted to the partition's + * rowtype, which might differ from the root table's. We must convert it + * back to the root table's rowtype so that val_desc shown error message + * matches the input tuple. + */ + if (resultRelInfo->ri_RootResultRelInfo) + { + ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo; + AttrMap *map; + + tupdesc = RelationGetDescr(rootrel->ri_RelationDesc); + /* a reverse map */ + map = build_attrmap_by_name_if_req(orig_tupdesc, + tupdesc, + false); + + /* + * Partition-specific slot's tupdesc can't be changed, so allocate a + * new one. + */ + if (map != NULL) + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); + modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate), + ExecGetUpdatedCols(rootrel, estate)); + rel = rootrel->ri_RelationDesc; + } + else + modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate), + ExecGetUpdatedCols(resultRelInfo, estate)); + + val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), + slot, + tupdesc, + modifiedCols, + 64); + ereport(ERROR, + errcode(ERRCODE_NOT_NULL_VIOLATION), + errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint", + NameStr(att->attname), + RelationGetRelationName(orig_rel)), + val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, + errtablecol(orig_rel, attnum)); +} + /* * ExecWithCheckOptions -- check that tuple satisfies any WITH CHECK OPTIONs * of the specified kind. @@ -2210,7 +2359,7 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, * column involved, that subset will be returned with a key identifying which * columns they are. */ -static char * +char * ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, TupleDesc tupdesc, @@ -2295,7 +2444,9 @@ ExecBuildSlotValueDescription(Oid reloid, if (table_perm || column_perm) { - if (slot->tts_isnull[i]) + if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + val = "virtual"; + else if (slot->tts_isnull[i]) val = "null"; else { @@ -2626,13 +2777,15 @@ bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot) { ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1]; - ExecRowMark *erm = earm->rowmark; + ExecRowMark *erm; Datum datum; bool isNull; Assert(earm != NULL); Assert(epqstate->origslot != NULL); + erm = earm->rowmark; + if (RowMarkRequiresRowShareLock(erm->markType)) elog(ERROR, "EvalPlanQual doesn't support locking rowmarks"); @@ -2906,6 +3059,13 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree) } } + /* + * Copy es_unpruned_relids so that pruned relations are ignored by + * ExecInitLockRows() and ExecInitModifyTable() when initializing the plan + * trees below. + */ + rcestate->es_unpruned_relids = parentestate->es_unpruned_relids; + /* * Initialize private state information for each SubPlan. We must do this * before running ExecInitNode on the main query tree, since diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index bfb3419efb7b1..f3e77bda27906 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -3,7 +3,7 @@ * execParallel.c * Support routines for parallel execution. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * This file contains routines that are intended to support setting up, @@ -28,6 +28,7 @@ #include "executor/nodeAgg.h" #include "executor/nodeAppend.h" #include "executor/nodeBitmapHeapscan.h" +#include "executor/nodeBitmapIndexscan.h" #include "executor/nodeCustom.h" #include "executor/nodeForeignscan.h" #include "executor/nodeHash.h" @@ -174,6 +175,7 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt = makeNode(PlannedStmt); pstmt->commandType = CMD_SELECT; pstmt->queryId = pgstat_get_my_query_id(); + pstmt->planId = pgstat_get_my_plan_id(); pstmt->hasReturning = false; pstmt->hasModifyingCTE = false; pstmt->canSetTag = true; @@ -181,7 +183,9 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->dependsOnRole = false; pstmt->parallelModeNeeded = false; pstmt->planTree = plan; + pstmt->partPruneInfos = estate->es_part_prune_infos; pstmt->rtable = estate->es_range_table; + pstmt->unprunableRelids = estate->es_unpruned_relids; pstmt->permInfos = estate->es_rteperminfos; pstmt->resultRelations = NIL; pstmt->appendRelations = NIL; @@ -242,14 +246,19 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e) e->pcxt); break; case T_IndexScanState: - if (planstate->plan->parallel_aware) - ExecIndexScanEstimate((IndexScanState *) planstate, - e->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexScanEstimate((IndexScanState *) planstate, + e->pcxt); break; case T_IndexOnlyScanState: - if (planstate->plan->parallel_aware) - ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate, - e->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate, + e->pcxt); + break; + case T_BitmapIndexScanState: + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapIndexScanEstimate((BitmapIndexScanState *) planstate, + e->pcxt); break; case T_ForeignScanState: if (planstate->plan->parallel_aware) @@ -466,14 +475,17 @@ ExecParallelInitializeDSM(PlanState *planstate, d->pcxt); break; case T_IndexScanState: - if (planstate->plan->parallel_aware) - ExecIndexScanInitializeDSM((IndexScanState *) planstate, - d->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexScanInitializeDSM((IndexScanState *) planstate, d->pcxt); break; case T_IndexOnlyScanState: - if (planstate->plan->parallel_aware) - ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate, - d->pcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate, + d->pcxt); + break; + case T_BitmapIndexScanState: + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapIndexScanInitializeDSM((BitmapIndexScanState *) planstate, d->pcxt); break; case T_ForeignScanState: if (planstate->plan->parallel_aware) @@ -1000,6 +1012,7 @@ ExecParallelReInitializeDSM(PlanState *planstate, ExecHashJoinReInitializeDSM((HashJoinState *) planstate, pcxt); break; + case T_BitmapIndexScanState: case T_HashState: case T_SortState: case T_IncrementalSortState: @@ -1061,6 +1074,15 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate, /* Perform any node-type-specific work that needs to be done. */ switch (nodeTag(planstate)) { + case T_IndexScanState: + ExecIndexScanRetrieveInstrumentation((IndexScanState *) planstate); + break; + case T_IndexOnlyScanState: + ExecIndexOnlyScanRetrieveInstrumentation((IndexOnlyScanState *) planstate); + break; + case T_BitmapIndexScanState: + ExecBitmapIndexScanRetrieveInstrumentation((BitmapIndexScanState *) planstate); + break; case T_SortState: ExecSortRetrieveInstrumentation((SortState *) planstate); break; @@ -1321,14 +1343,18 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt) ExecSeqScanInitializeWorker((SeqScanState *) planstate, pwcxt); break; case T_IndexScanState: - if (planstate->plan->parallel_aware) - ExecIndexScanInitializeWorker((IndexScanState *) planstate, - pwcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexScanInitializeWorker((IndexScanState *) planstate, pwcxt); break; case T_IndexOnlyScanState: - if (planstate->plan->parallel_aware) - ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate, - pwcxt); + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate, + pwcxt); + break; + case T_BitmapIndexScanState: + /* even when not parallel-aware, for EXPLAIN ANALYZE */ + ExecBitmapIndexScanInitializeWorker((BitmapIndexScanState *) planstate, + pwcxt); break; case T_ForeignScanState: if (planstate->plan->parallel_aware) @@ -1471,8 +1497,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) */ ExecutorRun(queryDesc, ForwardScanDirection, - fpes->tuples_needed < 0 ? (int64) 0 : fpes->tuples_needed, - true); + fpes->tuples_needed < 0 ? (int64) 0 : fpes->tuples_needed); /* Shut down the executor */ ExecutorFinish(queryDesc); diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 7651886229114..514eae1037dc3 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -3,7 +3,7 @@ * execPartition.c * Support routines for partitioning. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -181,21 +181,24 @@ static char *ExecBuildSlotPartitionKeyDescription(Relation rel, int maxfieldlen); static List *adjust_partition_colnos(List *colnos, ResultRelInfo *leaf_part_rri); static List *adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap); -static PartitionPruneState *CreatePartitionPruneState(PlanState *planstate, - PartitionPruneInfo *pruneinfo); +static PartitionPruneState *CreatePartitionPruneState(EState *estate, + PartitionPruneInfo *pruneinfo, + Bitmapset **all_leafpart_rtis); static void InitPartitionPruneContext(PartitionPruneContext *context, List *pruning_steps, PartitionDesc partdesc, PartitionKey partkey, PlanState *planstate, ExprContext *econtext); -static void PartitionPruneFixSubPlanMap(PartitionPruneState *prunestate, - Bitmapset *initially_valid_subplans, - int n_total_subplans); +static void InitExecPartitionPruneContexts(PartitionPruneState *prunestate, + PlanState *parent_plan, + Bitmapset *initially_valid_subplans, + int n_total_subplans); static void find_matching_subplans_recurse(PartitionPruningData *prunedata, PartitionedRelPruningData *pprune, bool initial_prune, - Bitmapset **validsubplans); + Bitmapset **validsubplans, + Bitmapset **validsubplan_rtis); /* @@ -872,7 +875,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * reference and make copy for this relation, converting stuff that * references attribute numbers to match this relation's. * - * This duplicates much of the logic in ExecInitMerge(), so something + * This duplicates much of the logic in ExecInitMerge(), so if something * changes there, look here too. */ if (node && node->operation == CMD_MERGE) @@ -952,6 +955,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, NULL); break; case CMD_DELETE: + case CMD_NOTHING: + /* Nothing to do */ break; default: @@ -1762,59 +1767,144 @@ adjust_partition_colnos_using_map(List *colnos, AttrMap *attrMap) * * Functions: * - * ExecInitPartitionPruning: - * Creates the PartitionPruneState required by ExecFindMatchingSubPlans. - * Details stored include how to map the partition index returned by the - * partition pruning code into subplan indexes. Also determines the set - * of subplans to initialize considering the result of performing initial - * pruning steps if any. Maps in PartitionPruneState are updated to + * ExecDoInitialPruning: + * Perform runtime "initial" pruning, if necessary, to determine the set + * of child subnodes that need to be initialized during ExecInitNode() for + * all plan nodes that contain a PartitionPruneInfo. + * + * ExecInitPartitionExecPruning: + * Updates the PartitionPruneState found at given part_prune_index in + * EState.es_part_prune_states for use during "exec" pruning if required. + * Also returns the set of subplans to initialize that would be stored at + * part_prune_index in EState.es_part_prune_results by + * ExecDoInitialPruning(). Maps in PartitionPruneState are updated to * account for initial pruning possibly having eliminated some of the * subplans. * * ExecFindMatchingSubPlans: * Returns indexes of matching subplans after evaluating the expressions * that are safe to evaluate at a given point. This function is first - * called during ExecInitPartitionPruning() to find the initially - * matching subplans based on performing the initial pruning steps and - * then must be called again each time the value of a Param listed in + * called during ExecDoInitialPruning() to find the initially matching + * subplans based on performing the initial pruning steps and then must be + * called again each time the value of a Param listed in * PartitionPruneState's 'execparamids' changes. *------------------------------------------------------------------------- */ + +/* + * ExecDoInitialPruning + * Perform runtime "initial" pruning, if necessary, to determine the set + * of child subnodes that need to be initialized during ExecInitNode() for + * plan nodes that support partition pruning. + * + * This function iterates over each PartitionPruneInfo entry in + * estate->es_part_prune_infos. For each entry, it creates a PartitionPruneState + * and adds it to es_part_prune_states. ExecInitPartitionExecPruning() accesses + * these states through their corresponding indexes in es_part_prune_states and + * assign each state to the parent node's PlanState, from where it will be used + * for "exec" pruning. + * + * If initial pruning steps exist for a PartitionPruneInfo entry, this function + * executes those pruning steps and stores the result as a bitmapset of valid + * child subplans, identifying which subplans should be initialized for + * execution. The results are saved in estate->es_part_prune_results. + * + * If no initial pruning is performed for a given PartitionPruneInfo, a NULL + * entry is still added to es_part_prune_results to maintain alignment with + * es_part_prune_infos. This ensures that ExecInitPartitionExecPruning() can + * use the same index to retrieve the pruning results. + */ +void +ExecDoInitialPruning(EState *estate) +{ + ListCell *lc; + + foreach(lc, estate->es_part_prune_infos) + { + PartitionPruneInfo *pruneinfo = lfirst_node(PartitionPruneInfo, lc); + PartitionPruneState *prunestate; + Bitmapset *validsubplans = NULL; + Bitmapset *all_leafpart_rtis = NULL; + Bitmapset *validsubplan_rtis = NULL; + + /* Create and save the PartitionPruneState. */ + prunestate = CreatePartitionPruneState(estate, pruneinfo, + &all_leafpart_rtis); + estate->es_part_prune_states = lappend(estate->es_part_prune_states, + prunestate); + + /* + * Perform initial pruning steps, if any, and save the result + * bitmapset or NULL as described in the header comment. + */ + if (prunestate->do_initial_prune) + validsubplans = ExecFindMatchingSubPlans(prunestate, true, + &validsubplan_rtis); + else + validsubplan_rtis = all_leafpart_rtis; + + estate->es_unpruned_relids = bms_add_members(estate->es_unpruned_relids, + validsubplan_rtis); + estate->es_part_prune_results = lappend(estate->es_part_prune_results, + validsubplans); + } +} + /* - * ExecInitPartitionPruning - * Initialize data structure needed for run-time partition pruning and - * do initial pruning if needed + * ExecInitPartitionExecPruning + * Initialize the data structures needed for runtime "exec" partition + * pruning and return the result of initial pruning, if available. + * + * 'relids' identifies the relation to which both the parent plan and the + * PartitionPruneInfo given by 'part_prune_index' belong. * * On return, *initially_valid_subplans is assigned the set of indexes of * child subplans that must be initialized along with the parent plan node. - * Initial pruning is performed here if needed and in that case only the - * surviving subplans' indexes are added. + * Initial pruning would have been performed by ExecDoInitialPruning(), if + * necessary, and the bitmapset of surviving subplans' indexes would have + * been stored as the part_prune_index'th element of + * EState.es_part_prune_results. * - * If subplans are indeed pruned, subplan_map arrays contained in the returned - * PartitionPruneState are re-sequenced to not count those, though only if the - * maps will be needed for subsequent execution pruning passes. + * If subplans were indeed pruned during initial pruning, the subplan_map + * arrays in the returned PartitionPruneState are re-sequenced to exclude those + * subplans, but only if the maps will be needed for subsequent execution + * pruning passes. */ PartitionPruneState * -ExecInitPartitionPruning(PlanState *planstate, - int n_total_subplans, - PartitionPruneInfo *pruneinfo, - Bitmapset **initially_valid_subplans) +ExecInitPartitionExecPruning(PlanState *planstate, + int n_total_subplans, + int part_prune_index, + Bitmapset *relids, + Bitmapset **initially_valid_subplans) { PartitionPruneState *prunestate; EState *estate = planstate->state; + PartitionPruneInfo *pruneinfo; - /* We may need an expression context to evaluate partition exprs */ - ExecAssignExprContext(estate, planstate); + /* Obtain the pruneinfo we need. */ + pruneinfo = list_nth_node(PartitionPruneInfo, estate->es_part_prune_infos, + part_prune_index); - /* Create the working data structure for pruning */ - prunestate = CreatePartitionPruneState(planstate, pruneinfo); + /* Its relids better match the plan node's or the planner messed up. */ + if (!bms_equal(relids, pruneinfo->relids)) + elog(ERROR, "wrong pruneinfo with relids=%s found at part_prune_index=%d contained in plan node with relids=%s", + bmsToString(pruneinfo->relids), part_prune_index, + bmsToString(relids)); /* - * Perform an initial partition prune pass, if required. + * The PartitionPruneState would have been created by + * ExecDoInitialPruning() and stored as the part_prune_index'th element of + * EState.es_part_prune_states. */ + prunestate = list_nth(estate->es_part_prune_states, part_prune_index); + Assert(prunestate != NULL); + + /* Use the result of initial pruning done by ExecDoInitialPruning(). */ if (prunestate->do_initial_prune) - *initially_valid_subplans = ExecFindMatchingSubPlans(prunestate, true); + *initially_valid_subplans = list_nth_node(Bitmapset, + estate->es_part_prune_results, + part_prune_index); else { /* No pruning, so we'll need to initialize all subplans */ @@ -1824,22 +1914,21 @@ ExecInitPartitionPruning(PlanState *planstate, } /* - * Re-sequence subplan indexes contained in prunestate to account for any - * that were removed above due to initial pruning. No need to do this if - * no steps were removed. + * The exec pruning state must also be initialized, if needed, before it + * can be used for pruning during execution. + * + * This also re-sequences subplan indexes contained in prunestate to + * account for any that were removed due to initial pruning; refer to the + * condition in InitExecPartitionPruneContexts() that is used to determine + * whether to do this. If no exec pruning needs to be done, we would thus + * leave the maps to be in an invalid state, but that's ok since that data + * won't be consulted again (cf initial Assert in + * ExecFindMatchingSubPlans). */ - if (bms_num_members(*initially_valid_subplans) < n_total_subplans) - { - /* - * We can safely skip this when !do_exec_prune, even though that - * leaves invalid data in prunestate, because that data won't be - * consulted again (cf initial Assert in ExecFindMatchingSubPlans). - */ - if (prunestate->do_exec_prune) - PartitionPruneFixSubPlanMap(prunestate, - *initially_valid_subplans, - n_total_subplans); - } + if (prunestate->do_exec_prune) + InitExecPartitionPruneContexts(prunestate, planstate, + *initially_valid_subplans, + n_total_subplans); return prunestate; } @@ -1848,7 +1937,11 @@ ExecInitPartitionPruning(PlanState *planstate, * CreatePartitionPruneState * Build the data structure required for calling ExecFindMatchingSubPlans * - * 'planstate' is the parent plan node's execution state. + * This includes PartitionPruneContexts (stored in each + * PartitionedRelPruningData corresponding to a PartitionedRelPruneInfo), + * which hold the ExprStates needed to evaluate pruning expressions, and + * mapping arrays to convert partition indexes from the pruning logic + * into subplan indexes in the parent plan node's list of child subplans. * * 'pruneinfo' is a PartitionPruneInfo as generated by * make_partition_pruneinfo. Here we build a PartitionPruneState containing a @@ -1860,16 +1953,32 @@ ExecInitPartitionPruning(PlanState *planstate, * stored in each PartitionedRelPruningData can be re-used each time we * re-evaluate which partitions match the pruning steps provided in each * PartitionedRelPruneInfo. + * + * Note that only the PartitionPruneContexts for initial pruning are + * initialized here. Those required for exec pruning are initialized later in + * ExecInitPartitionExecPruning(), as they depend on the availability of the + * parent plan node's PlanState. + * + * If initial pruning steps are to be skipped (e.g., during EXPLAIN + * (GENERIC_PLAN)), *all_leafpart_rtis will be populated with the RT indexes of + * all leaf partitions whose scanning subnode is included in the parent plan + * node's list of child plans. The caller must add these RT indexes to + * estate->es_unpruned_relids. */ static PartitionPruneState * -CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) +CreatePartitionPruneState(EState *estate, PartitionPruneInfo *pruneinfo, + Bitmapset **all_leafpart_rtis) { - EState *estate = planstate->state; PartitionPruneState *prunestate; int n_part_hierarchies; ListCell *lc; int i; - ExprContext *econtext = planstate->ps_ExprContext; + + /* + * Expression context that will be used by partkey_datum_from_expr() to + * evaluate expressions for comparison against partition bounds. + */ + ExprContext *econtext = CreateExprContext(estate); /* For data reading, executor always includes detached partitions */ if (estate->es_partition_directory == NULL) @@ -1886,6 +1995,8 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) palloc(offsetof(PartitionPruneState, partprunedata) + sizeof(PartitionPruningData *) * n_part_hierarchies); + /* Save ExprContext for use during InitExecPartitionPruneContexts(). */ + prunestate->econtext = econtext; prunestate->execparamids = NULL; /* other_subplans can change at runtime, so we need our own copy */ prunestate->other_subplans = bms_copy(pruneinfo->other_subplans); @@ -1934,7 +2045,11 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) * because that entry will be held open and locked for the * duration of this executor run. */ - partrel = ExecGetRangeTableRelation(estate, pinfo->rtindex); + partrel = ExecGetRangeTableRelation(estate, pinfo->rtindex, false); + + /* Remember for InitExecPartitionPruneContexts(). */ + pprune->partrel = partrel; + partkey = RelationGetPartitionKey(partrel); partdesc = PartitionDirectoryLookup(estate->es_partition_directory, partrel); @@ -1945,8 +2060,8 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) * The set of partitions that exist now might not be the same that * existed when the plan was made. The normal case is that it is; * optimize for that case with a quick comparison, and just copy - * the subplan_map and make subpart_map point to the one in - * PruneInfo. + * the subplan_map and make subpart_map, leafpart_rti_map point to + * the ones in PruneInfo. * * For the case where they aren't identical, we could have more * partitions on either side; or even exactly the same number of @@ -1965,6 +2080,7 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) sizeof(int) * partdesc->nparts) == 0) { pprune->subpart_map = pinfo->subpart_map; + pprune->leafpart_rti_map = pinfo->leafpart_rti_map; memcpy(pprune->subplan_map, pinfo->subplan_map, sizeof(int) * pinfo->nparts); } @@ -1985,6 +2101,7 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) * mismatches. */ pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts); + pprune->leafpart_rti_map = palloc(sizeof(int) * partdesc->nparts); for (pp_idx = 0; pp_idx < partdesc->nparts; pp_idx++) { @@ -2002,6 +2119,8 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) pinfo->subplan_map[pd_idx]; pprune->subpart_map[pp_idx] = pinfo->subpart_map[pd_idx]; + pprune->leafpart_rti_map[pp_idx] = + pinfo->leafpart_rti_map[pd_idx]; pd_idx++; continue; } @@ -2039,6 +2158,7 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) pprune->subpart_map[pp_idx] = -1; pprune->subplan_map[pp_idx] = -1; + pprune->leafpart_rti_map[pp_idx] = 0; } } @@ -2046,17 +2166,21 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) pprune->present_parts = bms_copy(pinfo->present_parts); /* - * Initialize pruning contexts as needed. Note that we must skip - * execution-time partition pruning in EXPLAIN (GENERIC_PLAN), - * since parameter values may be missing. + * Only initial_context is initialized here. exec_context is + * initialized during ExecInitPartitionExecPruning() when the + * parent plan's PlanState is available. + * + * Note that we must skip execution-time (both "init" and "exec") + * partition pruning in EXPLAIN (GENERIC_PLAN), since parameter + * values may be missing. */ pprune->initial_pruning_steps = pinfo->initial_pruning_steps; if (pinfo->initial_pruning_steps && !(econtext->ecxt_estate->es_top_eflags & EXEC_FLAG_EXPLAIN_GENERIC)) { InitPartitionPruneContext(&pprune->initial_context, - pinfo->initial_pruning_steps, - partdesc, partkey, planstate, + pprune->initial_pruning_steps, + partdesc, partkey, NULL, econtext); /* Record whether initial pruning is needed at any level */ prunestate->do_initial_prune = true; @@ -2065,10 +2189,6 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) if (pinfo->exec_pruning_steps && !(econtext->ecxt_estate->es_top_eflags & EXEC_FLAG_EXPLAIN_GENERIC)) { - InitPartitionPruneContext(&pprune->exec_context, - pinfo->exec_pruning_steps, - partdesc, partkey, planstate, - econtext); /* Record whether exec pruning is needed at any level */ prunestate->do_exec_prune = true; } @@ -2080,6 +2200,25 @@ CreatePartitionPruneState(PlanState *planstate, PartitionPruneInfo *pruneinfo) prunestate->execparamids = bms_add_members(prunestate->execparamids, pinfo->execparamids); + /* + * Return all leaf partition indexes if we're skipping pruning in + * the EXPLAIN (GENERIC_PLAN) case. + */ + if (pinfo->initial_pruning_steps && !prunestate->do_initial_prune) + { + int part_index = -1; + + while ((part_index = bms_next_member(pprune->present_parts, + part_index)) >= 0) + { + Index rtindex = pprune->leafpart_rti_map[part_index]; + + if (rtindex) + *all_leafpart_rtis = bms_add_member(*all_leafpart_rtis, + rtindex); + } + } + j++; } i++; @@ -2173,10 +2312,17 @@ InitPartitionPruneContext(PartitionPruneContext *context, } /* - * PartitionPruneFixSubPlanMap - * Fix mapping of partition indexes to subplan indexes contained in - * prunestate by considering the new list of subplans that survived - * initial pruning + * InitExecPartitionPruneContexts + * Initialize exec pruning contexts deferred by CreatePartitionPruneState() + * + * This function finalizes exec pruning setup for a PartitionPruneState by + * initializing contexts for pruning steps that require the parent plan's + * PlanState. It iterates over PartitionPruningData entries and sets up the + * necessary execution contexts for pruning during query execution. + * + * Also fix the mapping of partition indexes to subplan indexes contained in + * prunestate by considering the new list of subplans that survived initial + * pruning. * * Current values of the indexes present in PartitionPruneState count all the * subplans that would be present before initial pruning was done. If initial @@ -2187,27 +2333,43 @@ InitPartitionPruneContext(PartitionPruneContext *context, * subplans in the post-initial-pruning set. */ static void -PartitionPruneFixSubPlanMap(PartitionPruneState *prunestate, - Bitmapset *initially_valid_subplans, - int n_total_subplans) +InitExecPartitionPruneContexts(PartitionPruneState *prunestate, + PlanState *parent_plan, + Bitmapset *initially_valid_subplans, + int n_total_subplans) { - int *new_subplan_indexes; + EState *estate; + int *new_subplan_indexes = NULL; Bitmapset *new_other_subplans; int i; int newidx; + bool fix_subplan_map = false; + + Assert(prunestate->do_exec_prune); + Assert(parent_plan != NULL); + estate = parent_plan->state; /* - * First we must build a temporary array which maps old subplan indexes to - * new ones. For convenience of initialization, we use 1-based indexes in - * this array and leave pruned items as 0. + * No need to fix subplans maps if initial pruning didn't eliminate any + * subplans. */ - new_subplan_indexes = (int *) palloc0(sizeof(int) * n_total_subplans); - newidx = 1; - i = -1; - while ((i = bms_next_member(initially_valid_subplans, i)) >= 0) + if (bms_num_members(initially_valid_subplans) < n_total_subplans) { - Assert(i < n_total_subplans); - new_subplan_indexes[i] = newidx++; + fix_subplan_map = true; + + /* + * First we must build a temporary array which maps old subplan + * indexes to new ones. For convenience of initialization, we use + * 1-based indexes in this array and leave pruned items as 0. + */ + new_subplan_indexes = (int *) palloc0(sizeof(int) * n_total_subplans); + newidx = 1; + i = -1; + while ((i = bms_next_member(initially_valid_subplans, i)) >= 0) + { + Assert(i < n_total_subplans); + new_subplan_indexes[i] = newidx++; + } } /* @@ -2232,6 +2394,29 @@ PartitionPruneFixSubPlanMap(PartitionPruneState *prunestate, int nparts = pprune->nparts; int k; + /* Initialize PartitionPruneContext for exec pruning, if needed. */ + if (pprune->exec_pruning_steps != NIL) + { + PartitionKey partkey; + PartitionDesc partdesc; + + /* + * See the comment in CreatePartitionPruneState() regarding + * the usage of partdesc and partkey. + */ + partkey = RelationGetPartitionKey(pprune->partrel); + partdesc = PartitionDirectoryLookup(estate->es_partition_directory, + pprune->partrel); + + InitPartitionPruneContext(&pprune->exec_context, + pprune->exec_pruning_steps, + partdesc, partkey, parent_plan, + prunestate->econtext); + } + + if (!fix_subplan_map) + continue; + /* We just rebuild present_parts from scratch */ bms_free(pprune->present_parts); pprune->present_parts = NULL; @@ -2273,19 +2458,22 @@ PartitionPruneFixSubPlanMap(PartitionPruneState *prunestate, } /* - * We must also recompute the other_subplans set, since indexes in it may - * change. + * If we fixed subplan maps, we must also recompute the other_subplans + * set, since indexes in it may change. */ - new_other_subplans = NULL; - i = -1; - while ((i = bms_next_member(prunestate->other_subplans, i)) >= 0) - new_other_subplans = bms_add_member(new_other_subplans, - new_subplan_indexes[i] - 1); + if (fix_subplan_map) + { + new_other_subplans = NULL; + i = -1; + while ((i = bms_next_member(prunestate->other_subplans, i)) >= 0) + new_other_subplans = bms_add_member(new_other_subplans, + new_subplan_indexes[i] - 1); - bms_free(prunestate->other_subplans); - prunestate->other_subplans = new_other_subplans; + bms_free(prunestate->other_subplans); + prunestate->other_subplans = new_other_subplans; - pfree(new_subplan_indexes); + pfree(new_subplan_indexes); + } } /* @@ -2296,10 +2484,15 @@ PartitionPruneFixSubPlanMap(PartitionPruneState *prunestate, * Pass initial_prune if PARAM_EXEC Params cannot yet be evaluated. This * differentiates the initial executor-time pruning step from later * runtime pruning. + * + * The caller must pass a non-NULL validsubplan_rtis during initial pruning + * to collect the RT indexes of leaf partitions whose subnodes will be + * executed. These RT indexes are later added to EState.es_unpruned_relids. */ Bitmapset * ExecFindMatchingSubPlans(PartitionPruneState *prunestate, - bool initial_prune) + bool initial_prune, + Bitmapset **validsubplan_rtis) { Bitmapset *result = NULL; MemoryContext oldcontext; @@ -2311,6 +2504,7 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate, * evaluated *and* there are steps in which to do so. */ Assert(initial_prune || prunestate->do_exec_prune); + Assert(validsubplan_rtis != NULL || !initial_prune); /* * Switch to a temp context to avoid leaking memory in the executor's @@ -2334,10 +2528,14 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate, */ pprune = &prunedata->partrelprunedata[0]; find_matching_subplans_recurse(prunedata, pprune, initial_prune, - &result); + &result, validsubplan_rtis); - /* Expression eval may have used space in ExprContext too */ - if (pprune->exec_pruning_steps) + /* + * Expression eval may have used space in ExprContext too. Avoid + * accessing exec_context during initial pruning, as it is not valid + * at that stage. + */ + if (!initial_prune && pprune->exec_pruning_steps) ResetExprContext(pprune->exec_context.exprcontext); } @@ -2348,6 +2546,8 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate, /* Copy result out of the temp context before we reset it */ result = bms_copy(result); + if (validsubplan_rtis) + *validsubplan_rtis = bms_copy(*validsubplan_rtis); MemoryContextReset(prunestate->prune_context); @@ -2358,13 +2558,16 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate, * find_matching_subplans_recurse * Recursive worker function for ExecFindMatchingSubPlans * - * Adds valid (non-prunable) subplan IDs to *validsubplans + * Adds valid (non-prunable) subplan IDs to *validsubplans. If + * *validsubplan_rtis is non-NULL, it also adds the RT indexes of their + * corresponding partitions, but only if they are leaf partitions. */ static void find_matching_subplans_recurse(PartitionPruningData *prunedata, PartitionedRelPruningData *pprune, bool initial_prune, - Bitmapset **validsubplans) + Bitmapset **validsubplans, + Bitmapset **validsubplan_rtis) { Bitmapset *partset; int i; @@ -2391,8 +2594,18 @@ find_matching_subplans_recurse(PartitionPruningData *prunedata, while ((i = bms_next_member(partset, i)) >= 0) { if (pprune->subplan_map[i] >= 0) + { *validsubplans = bms_add_member(*validsubplans, pprune->subplan_map[i]); + + /* + * Only report leaf partitions. Non-leaf partitions may appear + * here when they use an unflattened Append or MergeAppend. + */ + if (validsubplan_rtis && pprune->leafpart_rti_map[i]) + *validsubplan_rtis = bms_add_member(*validsubplan_rtis, + pprune->leafpart_rti_map[i]); + } else { int partidx = pprune->subpart_map[i]; @@ -2400,7 +2613,8 @@ find_matching_subplans_recurse(PartitionPruningData *prunedata, if (partidx >= 0) find_matching_subplans_recurse(prunedata, &prunedata->partrelprunedata[partidx], - initial_prune, validsubplans); + initial_prune, validsubplans, + validsubplan_rtis); else { /* diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 6e48062f56a7a..f5f9cfbeeadad 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -7,7 +7,7 @@ * ExecProcNode, or ExecEndNode on its subnodes and do the appropriate * processing. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -393,6 +393,10 @@ ExecInitNode(Plan *node, EState *estate, int eflags) /* * Initialize any initPlans present in this node. The planner put them in * a separate list for us. + * + * The defining characteristic of initplans is that they don't have + * arguments, so we don't need to evaluate them (in contrast to + * ExecInitSubPlanExpr()). */ subps = NIL; foreach(l, node->initPlan) @@ -401,6 +405,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags) SubPlanState *sstate; Assert(IsA(subplan, SubPlan)); + Assert(subplan->args == NIL); sstate = ExecInitSubPlan(subplan, result); subps = lappend(subps, sstate); } diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index d0a89cd577821..53ddd25c42db9 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -3,7 +3,7 @@ * execReplication.c * miscellaneous executor routines for logical replication * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/genam.h" +#include "access/gist.h" #include "access/relscan.h" #include "access/tableam.h" #include "access/transam.h" @@ -23,6 +24,7 @@ #include "commands/trigger.h" #include "executor/executor.h" #include "executor/nodeModifyTable.h" +#include "replication/conflict.h" #include "replication/logicalrelation.h" #include "storage/lmgr.h" #include "utils/builtins.h" @@ -36,49 +38,6 @@ static bool tuples_equal(TupleTableSlot *slot1, TupleTableSlot *slot2, TypeCacheEntry **eq); -/* - * Returns the fixed strategy number, if any, of the equality operator for the - * given index access method, otherwise, InvalidStrategy. - * - * Currently, only Btree and Hash indexes are supported. The other index access - * methods don't have a fixed strategy for equality operation - instead, the - * support routines of each operator class interpret the strategy numbers - * according to the operator class's definition. - */ -StrategyNumber -get_equal_strategy_number_for_am(Oid am) -{ - int ret; - - switch (am) - { - case BTREE_AM_OID: - ret = BTEqualStrategyNumber; - break; - case HASH_AM_OID: - ret = HTEqualStrategyNumber; - break; - default: - /* XXX: Only Btree and Hash indexes are supported */ - ret = InvalidStrategy; - break; - } - - return ret; -} - -/* - * Return the appropriate strategy number which corresponds to the equality - * operator. - */ -static StrategyNumber -get_equal_strategy_number(Oid opclass) -{ - Oid am = get_opclass_method(opclass); - - return get_equal_strategy_number_for_am(am); -} - /* * Setup a ScanKey for a search in the relation 'rel' for a tuple 'key' that * is setup to match 'rel' (*NOT* idxrel!). @@ -132,8 +91,7 @@ build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel, */ optype = get_opclass_input_type(opclass->values[index_attoff]); opfamily = get_opclass_family(opclass->values[index_attoff]); - eq_strategy = get_equal_strategy_number(opclass->values[index_attoff]); - + eq_strategy = IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, false); operator = get_opfamily_member(opfamily, optype, optype, eq_strategy); @@ -166,6 +124,51 @@ build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel, return skey_attoff; } + +/* + * Helper function to check if it is necessary to re-fetch and lock the tuple + * due to concurrent modifications. This function should be called after + * invoking table_tuple_lock. + */ +static bool +should_refetch_tuple(TM_Result res, TM_FailureData *tmfd) +{ + bool refetch = false; + + switch (res) + { + case TM_Ok: + break; + case TM_Updated: + /* XXX: Improve handling here */ + if (ItemPointerIndicatesMovedPartitions(&tmfd->ctid)) + ereport(LOG, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying"))); + else + ereport(LOG, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("concurrent update, retrying"))); + refetch = true; + break; + case TM_Deleted: + /* XXX: Improve handling here */ + ereport(LOG, + (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), + errmsg("concurrent delete, retrying"))); + refetch = true; + break; + case TM_Invisible: + elog(ERROR, "attempted to lock invisible tuple"); + break; + default: + elog(ERROR, "unexpected table_tuple_lock status: %u", res); + break; + } + + return refetch; +} + /* * Search the relation 'rel' for tuple using the index. * @@ -199,7 +202,7 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid, skey_attoff = build_replindex_scan_key(skey, rel, idxrel, searchslot); /* Start an index scan. */ - scan = index_beginscan(rel, idxrel, &snap, skey_attoff, 0); + scan = index_beginscan(rel, idxrel, &snap, NULL, skey_attoff, 0); retry: found = false; @@ -250,7 +253,7 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid, PushActiveSnapshot(GetLatestSnapshot()); - res = table_tuple_lock(rel, &(outslot->tts_tid), GetLatestSnapshot(), + res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(), outslot, GetCurrentCommandId(false), lockmode, @@ -260,34 +263,8 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid, PopActiveSnapshot(); - switch (res) - { - case TM_Ok: - break; - case TM_Updated: - /* XXX: Improve handling here */ - if (ItemPointerIndicatesMovedPartitions(&tmfd.ctid)) - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying"))); - else - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("concurrent update, retrying"))); - goto retry; - case TM_Deleted: - /* XXX: Improve handling here */ - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("concurrent delete, retrying"))); - goto retry; - case TM_Invisible: - elog(ERROR, "attempted to lock invisible tuple"); - break; - default: - elog(ERROR, "unexpected table_tuple_lock status: %u", res); - break; - } + if (should_refetch_tuple(res, &tmfd)) + goto retry; } index_endscan(scan); @@ -434,7 +411,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, PushActiveSnapshot(GetLatestSnapshot()); - res = table_tuple_lock(rel, &(outslot->tts_tid), GetLatestSnapshot(), + res = table_tuple_lock(rel, &(outslot->tts_tid), GetActiveSnapshot(), outslot, GetCurrentCommandId(false), lockmode, @@ -444,34 +421,8 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, PopActiveSnapshot(); - switch (res) - { - case TM_Ok: - break; - case TM_Updated: - /* XXX: Improve handling here */ - if (ItemPointerIndicatesMovedPartitions(&tmfd.ctid)) - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying"))); - else - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("concurrent update, retrying"))); - goto retry; - case TM_Deleted: - /* XXX: Improve handling here */ - ereport(LOG, - (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), - errmsg("concurrent delete, retrying"))); - goto retry; - case TM_Invisible: - elog(ERROR, "attempted to lock invisible tuple"); - break; - default: - elog(ERROR, "unexpected table_tuple_lock status: %u", res); - break; - } + if (should_refetch_tuple(res, &tmfd)) + goto retry; } table_endscan(scan); @@ -480,6 +431,127 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, return found; } +/* + * Build additional index information necessary for conflict detection. + */ +static void +BuildConflictIndexInfo(ResultRelInfo *resultRelInfo, Oid conflictindex) +{ + for (int i = 0; i < resultRelInfo->ri_NumIndices; i++) + { + Relation indexRelation = resultRelInfo->ri_IndexRelationDescs[i]; + IndexInfo *indexRelationInfo = resultRelInfo->ri_IndexRelationInfo[i]; + + if (conflictindex != RelationGetRelid(indexRelation)) + continue; + + /* + * This Assert will fail if BuildSpeculativeIndexInfo() is called + * twice for the given index. + */ + Assert(indexRelationInfo->ii_UniqueOps == NULL); + + BuildSpeculativeIndexInfo(indexRelation, indexRelationInfo); + } +} + +/* + * Find the tuple that violates the passed unique index (conflictindex). + * + * If the conflicting tuple is found return true, otherwise false. + * + * We lock the tuple to avoid getting it deleted before the caller can fetch + * the required information. Note that if the tuple is deleted before a lock + * is acquired, we will retry to find the conflicting tuple again. + */ +static bool +FindConflictTuple(ResultRelInfo *resultRelInfo, EState *estate, + Oid conflictindex, TupleTableSlot *slot, + TupleTableSlot **conflictslot) +{ + Relation rel = resultRelInfo->ri_RelationDesc; + ItemPointerData conflictTid; + TM_FailureData tmfd; + TM_Result res; + + *conflictslot = NULL; + + /* + * Build additional information required to check constraints violations. + * See check_exclusion_or_unique_constraint(). + */ + BuildConflictIndexInfo(resultRelInfo, conflictindex); + +retry: + if (ExecCheckIndexConstraints(resultRelInfo, slot, estate, + &conflictTid, &slot->tts_tid, + list_make1_oid(conflictindex))) + { + if (*conflictslot) + ExecDropSingleTupleTableSlot(*conflictslot); + + *conflictslot = NULL; + return false; + } + + *conflictslot = table_slot_create(rel, NULL); + + PushActiveSnapshot(GetLatestSnapshot()); + + res = table_tuple_lock(rel, &conflictTid, GetActiveSnapshot(), + *conflictslot, + GetCurrentCommandId(false), + LockTupleShare, + LockWaitBlock, + 0 /* don't follow updates */ , + &tmfd); + + PopActiveSnapshot(); + + if (should_refetch_tuple(res, &tmfd)) + goto retry; + + return true; +} + +/* + * Check all the unique indexes in 'recheckIndexes' for conflict with the + * tuple in 'remoteslot' and report if found. + */ +static void +CheckAndReportConflict(ResultRelInfo *resultRelInfo, EState *estate, + ConflictType type, List *recheckIndexes, + TupleTableSlot *searchslot, TupleTableSlot *remoteslot) +{ + List *conflicttuples = NIL; + TupleTableSlot *conflictslot; + + /* Check all the unique indexes for conflicts */ + foreach_oid(uniqueidx, resultRelInfo->ri_onConflictArbiterIndexes) + { + if (list_member_oid(recheckIndexes, uniqueidx) && + FindConflictTuple(resultRelInfo, estate, uniqueidx, remoteslot, + &conflictslot)) + { + ConflictTupleInfo *conflicttuple = palloc0_object(ConflictTupleInfo); + + conflicttuple->slot = conflictslot; + conflicttuple->indexoid = uniqueidx; + + GetTupleTransactionInfo(conflictslot, &conflicttuple->xmin, + &conflicttuple->origin, &conflicttuple->ts); + + conflicttuples = lappend(conflicttuples, conflicttuple); + } + } + + /* Report the conflict, if found */ + if (conflicttuples) + ReportApplyConflict(estate, resultRelInfo, ERROR, + list_length(conflicttuples) > 1 ? CT_MULTIPLE_UNIQUE_CONFLICTS : type, + searchslot, remoteslot, conflicttuples); +} + /* * Insert tuple represented in the slot to the relation, update the indexes, * and execute any constraints and per-row triggers. @@ -509,6 +581,8 @@ ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo, if (!skip_tuple) { List *recheckIndexes = NIL; + List *conflictindexes; + bool conflict = false; /* Compute stored generated columns */ if (rel->rd_att->constr && @@ -525,10 +599,33 @@ ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo, /* OK, store the tuple and create index entries for it */ simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot); + conflictindexes = resultRelInfo->ri_onConflictArbiterIndexes; + if (resultRelInfo->ri_NumIndices > 0) recheckIndexes = ExecInsertIndexTuples(resultRelInfo, - slot, estate, false, false, - NULL, NIL, false); + slot, estate, false, + conflictindexes ? true : false, + &conflict, + conflictindexes, false); + + /* + * Checks the conflict indexes to fetch the conflicting local tuple + * and reports the conflict. We perform this check here, instead of + * performing an additional index scan before the actual insertion and + * reporting the conflict if any conflicting tuples are found. This is + * to avoid the overhead of executing the extra scan for each INSERT + * operation, even when no conflict arises, which could introduce + * significant overhead to replication, particularly in cases where + * conflicts are rare. + * + * XXX OTOH, this could lead to clean-up effort for dead tuples added + * in heap and index in case of conflicts. But as conflicts shouldn't + * be a frequent thing so we preferred to save the performance + * overhead of extra scan before each insertion. + */ + if (conflict) + CheckAndReportConflict(resultRelInfo, estate, CT_INSERT_EXISTS, + recheckIndexes, NULL, slot); /* AFTER ROW INSERT Triggers */ ExecARInsertTriggers(estate, resultRelInfo, slot, @@ -559,8 +656,12 @@ ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, Relation rel = resultRelInfo->ri_RelationDesc; ItemPointer tid = &(searchslot->tts_tid); - /* For now we support only tables. */ + /* + * We support only non-system tables, with + * check_publication_add_relation() accountable. + */ Assert(rel->rd_rel->relkind == RELKIND_RELATION); + Assert(!IsCatalogRelation(rel)); CheckCmdReplicaIdentity(rel, CMD_UPDATE); @@ -577,6 +678,8 @@ ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, { List *recheckIndexes = NIL; TU_UpdateIndexes update_indexes; + List *conflictindexes; + bool conflict = false; /* Compute stored generated columns */ if (rel->rd_att->constr && @@ -593,12 +696,24 @@ ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, simple_table_tuple_update(rel, tid, slot, estate->es_snapshot, &update_indexes); + conflictindexes = resultRelInfo->ri_onConflictArbiterIndexes; + if (resultRelInfo->ri_NumIndices > 0 && (update_indexes != TU_None)) recheckIndexes = ExecInsertIndexTuples(resultRelInfo, - slot, estate, true, false, - NULL, NIL, + slot, estate, true, + conflictindexes ? true : false, + &conflict, conflictindexes, (update_indexes == TU_Summarizing)); + /* + * Refer to the comments above the call to CheckAndReportConflict() in + * ExecSimpleRelationInsert to understand why this check is done at + * this point. + */ + if (conflict) + CheckAndReportConflict(resultRelInfo, estate, CT_UPDATE_EXISTS, + recheckIndexes, searchslot, slot); + /* AFTER ROW UPDATE Triggers */ ExecARUpdateTriggers(estate, resultRelInfo, NULL, NULL, @@ -665,16 +780,27 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) return; /* - * It is only safe to execute UPDATE/DELETE when all columns, referenced - * in the row filters from publications which the relation is in, are - * valid - i.e. when all referenced columns are part of REPLICA IDENTITY - * or the table does not publish UPDATEs or DELETEs. + * It is only safe to execute UPDATE/DELETE if the relation does not + * publish UPDATEs or DELETEs, or all the following conditions are + * satisfied: + * + * 1. All columns, referenced in the row filters from publications which + * the relation is in, are valid - i.e. when all referenced columns are + * part of REPLICA IDENTITY. + * + * 2. All columns, referenced in the column lists are valid - i.e. when + * all columns referenced in the REPLICA IDENTITY are covered by the + * column list. + * + * 3. All generated columns in REPLICA IDENTITY of the relation, are valid + * - i.e. when all these generated columns are published. * * XXX We could optimize it by first checking whether any of the - * publications have a row filter for this relation. If not and relation - * has replica identity then we can avoid building the descriptor but as - * this happens only one time it doesn't seem worth the additional - * complexity. + * publications have a row filter or column list for this relation, or if + * the relation contains a generated column. If none of these exist and + * the relation has replica identity then we can avoid building the + * descriptor but as this happens only one time it doesn't seem worth the + * additional complexity. */ RelationBuildPublicationDesc(rel, &pubdesc); if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update) @@ -689,6 +815,12 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) errmsg("cannot update table \"%s\"", RelationGetRelationName(rel)), errdetail("Column list used by the publication does not cover the replica identity."))); + else if (cmd == CMD_UPDATE && !pubdesc.gencols_valid_for_update) + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), + errmsg("cannot update table \"%s\"", + RelationGetRelationName(rel)), + errdetail("Replica identity must not contain unpublished generated columns."))); else if (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), @@ -701,6 +833,12 @@ CheckCmdReplicaIdentity(Relation rel, CmdType cmd) errmsg("cannot delete from table \"%s\"", RelationGetRelationName(rel)), errdetail("Column list used by the publication does not cover the replica identity."))); + else if (cmd == CMD_DELETE && !pubdesc.gencols_valid_for_delete) + ereport(ERROR, + (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), + errmsg("cannot delete from table \"%s\"", + RelationGetRelationName(rel)), + errdetail("Replica identity must not contain unpublished generated columns."))); /* If relation has replica identity we are always good. */ if (OidIsValid(RelationGetReplicaIndex(rel))) diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c index 862d3085f8328..a03fe780a02c9 100644 --- a/src/backend/executor/execSRF.c +++ b/src/backend/executor/execSRF.c @@ -7,7 +7,7 @@ * common code for calling set-returning functions according to the * ReturnSetInfo API. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index f52e28c58e9a2..90726949a8708 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -7,7 +7,7 @@ * stuff - checking the qualification and projecting the tuple * appropriately. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,118 +19,9 @@ #include "postgres.h" #include "executor/executor.h" +#include "executor/execScan.h" #include "miscadmin.h" - - -/* - * ExecScanFetch -- check interrupts & fetch next potential tuple - * - * This routine is concerned with substituting a test tuple if we are - * inside an EvalPlanQual recheck. If we aren't, just execute - * the access method's next-tuple routine. - */ -static inline TupleTableSlot * -ExecScanFetch(ScanState *node, - ExecScanAccessMtd accessMtd, - ExecScanRecheckMtd recheckMtd) -{ - EState *estate = node->ps.state; - - CHECK_FOR_INTERRUPTS(); - - if (estate->es_epq_active != NULL) - { - EPQState *epqstate = estate->es_epq_active; - - /* - * We are inside an EvalPlanQual recheck. Return the test tuple if - * one is available, after rechecking any access-method-specific - * conditions. - */ - Index scanrelid = ((Scan *) node->ps.plan)->scanrelid; - - if (scanrelid == 0) - { - /* - * This is a ForeignScan or CustomScan which has pushed down a - * join to the remote side. The recheck method is responsible not - * only for rechecking the scan/join quals but also for storing - * the correct tuple in the slot. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - if (!(*recheckMtd) (node, slot)) - ExecClearTuple(slot); /* would not be returned by scan */ - return slot; - } - else if (epqstate->relsubs_done[scanrelid - 1]) - { - /* - * Return empty slot, as either there is no EPQ tuple for this rel - * or we already returned it. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - return ExecClearTuple(slot); - } - else if (epqstate->relsubs_slot[scanrelid - 1] != NULL) - { - /* - * Return replacement tuple provided by the EPQ caller. - */ - - TupleTableSlot *slot = epqstate->relsubs_slot[scanrelid - 1]; - - Assert(epqstate->relsubs_rowmark[scanrelid - 1] == NULL); - - /* Mark to remember that we shouldn't return it again */ - epqstate->relsubs_done[scanrelid - 1] = true; - - /* Return empty slot if we haven't got a test tuple */ - if (TupIsNull(slot)) - return NULL; - - /* Check if it meets the access-method conditions */ - if (!(*recheckMtd) (node, slot)) - return ExecClearTuple(slot); /* would not be returned by - * scan */ - return slot; - } - else if (epqstate->relsubs_rowmark[scanrelid - 1] != NULL) - { - /* - * Fetch and return replacement tuple using a non-locking rowmark. - */ - - TupleTableSlot *slot = node->ss_ScanTupleSlot; - - /* Mark to remember that we shouldn't return more */ - epqstate->relsubs_done[scanrelid - 1] = true; - - if (!EvalPlanQualFetchRowMark(epqstate, scanrelid, slot)) - return NULL; - - /* Return empty slot if we haven't got a test tuple */ - if (TupIsNull(slot)) - return NULL; - - /* Check if it meets the access-method conditions */ - if (!(*recheckMtd) (node, slot)) - return ExecClearTuple(slot); /* would not be returned by - * scan */ - return slot; - } - } - - /* - * Run the node-type-specific access method function to get the next tuple - */ - return (*accessMtd) (node); -} - /* ---------------------------------------------------------------- * ExecScan * @@ -157,100 +48,20 @@ ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, /* function returning a tuple */ ExecScanRecheckMtd recheckMtd) { - ExprContext *econtext; + EPQState *epqstate; ExprState *qual; ProjectionInfo *projInfo; - /* - * Fetch data from node - */ + epqstate = node->ps.state->es_epq_active; qual = node->ps.qual; projInfo = node->ps.ps_ProjInfo; - econtext = node->ps.ps_ExprContext; - - /* interrupt checks are in ExecScanFetch */ - - /* - * If we have neither a qual to check nor a projection to do, just skip - * all the overhead and return the raw scan tuple. - */ - if (!qual && !projInfo) - { - ResetExprContext(econtext); - return ExecScanFetch(node, accessMtd, recheckMtd); - } - - /* - * Reset per-tuple memory context to free any expression evaluation - * storage allocated in the previous tuple cycle. - */ - ResetExprContext(econtext); - - /* - * get a tuple from the access method. Loop until we obtain a tuple that - * passes the qualification. - */ - for (;;) - { - TupleTableSlot *slot; - slot = ExecScanFetch(node, accessMtd, recheckMtd); - - /* - * if the slot returned by the accessMtd contains NULL, then it means - * there is nothing more to scan so we just return an empty slot, - * being careful to use the projection result slot so it has correct - * tupleDesc. - */ - if (TupIsNull(slot)) - { - if (projInfo) - return ExecClearTuple(projInfo->pi_state.resultslot); - else - return slot; - } - - /* - * place the current tuple into the expr context - */ - econtext->ecxt_scantuple = slot; - - /* - * check that the current tuple satisfies the qual-clause - * - * check for non-null qual here to avoid a function call to ExecQual() - * when the qual is null ... saves only a few cycles, but they add up - * ... - */ - if (qual == NULL || ExecQual(qual, econtext)) - { - /* - * Found a satisfactory scan tuple. - */ - if (projInfo) - { - /* - * Form a projection tuple, store it in the result tuple slot - * and return it. - */ - return ExecProject(projInfo); - } - else - { - /* - * Here, we aren't projecting, so just return scan tuple. - */ - return slot; - } - } - else - InstrCountFiltered1(node, 1); - - /* - * Tuple fails qual, so free per-tuple memory and try again. - */ - ResetExprContext(econtext); - } + return ExecScanExtended(node, + accessMtd, + recheckMtd, + epqstate, + qual, + projInfo); } /* diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 00dc3396156c5..8e02d68824fad 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -46,7 +46,7 @@ * to avoid physically constructing projection tuples in many cases. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -187,7 +187,7 @@ tts_virtual_materialize(TupleTableSlot *slot) /* compute size of memory required */ for (int natt = 0; natt < desc->natts; natt++) { - Form_pg_attribute att = TupleDescAttr(desc, natt); + CompactAttribute *att = TupleDescCompactAttr(desc, natt); Datum val; if (att->attbyval || slot->tts_isnull[natt]) @@ -202,12 +202,12 @@ tts_virtual_materialize(TupleTableSlot *slot) * We want to flatten the expanded value so that the materialized * slot doesn't depend on it. */ - sz = att_align_nominal(sz, att->attalign); + sz = att_nominal_alignby(sz, att->attalignby); sz += EOH_get_flat_size(DatumGetEOHP(val)); } else { - sz = att_align_nominal(sz, att->attalign); + sz = att_nominal_alignby(sz, att->attalignby); sz = att_addlength_datum(sz, att->attlen, val); } } @@ -223,7 +223,7 @@ tts_virtual_materialize(TupleTableSlot *slot) /* and copy all attributes into the pre-allocated space */ for (int natt = 0; natt < desc->natts; natt++) { - Form_pg_attribute att = TupleDescAttr(desc, natt); + CompactAttribute *att = TupleDescCompactAttr(desc, natt); Datum val; if (att->attbyval || slot->tts_isnull[natt]) @@ -242,8 +242,8 @@ tts_virtual_materialize(TupleTableSlot *slot) */ ExpandedObjectHeader *eoh = DatumGetEOHP(val); - data = (char *) att_align_nominal(data, - att->attalign); + data = (char *) att_nominal_alignby(data, + att->attalignby); data_length = EOH_get_flat_size(eoh); EOH_flatten_into(eoh, data, data_length); @@ -254,7 +254,7 @@ tts_virtual_materialize(TupleTableSlot *slot) { Size data_length = 0; - data = (char *) att_align_nominal(data, att->attalign); + data = (char *) att_nominal_alignby(data, att->attalignby); data_length = att_addlength_datum(data_length, att->attlen, val); memcpy(data, DatumGetPointer(val), data_length); @@ -298,13 +298,14 @@ tts_virtual_copy_heap_tuple(TupleTableSlot *slot) } static MinimalTuple -tts_virtual_copy_minimal_tuple(TupleTableSlot *slot) +tts_virtual_copy_minimal_tuple(TupleTableSlot *slot, Size extra) { Assert(!TTS_EMPTY(slot)); return heap_form_minimal_tuple(slot->tts_tupleDescriptor, slot->tts_values, - slot->tts_isnull); + slot->tts_isnull, + extra); } @@ -472,14 +473,14 @@ tts_heap_copy_heap_tuple(TupleTableSlot *slot) } static MinimalTuple -tts_heap_copy_minimal_tuple(TupleTableSlot *slot) +tts_heap_copy_minimal_tuple(TupleTableSlot *slot, Size extra) { HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot; if (!hslot->tuple) tts_heap_materialize(slot); - return minimal_tuple_from_heap_tuple(hslot->tuple); + return minimal_tuple_from_heap_tuple(hslot->tuple, extra); } static void @@ -607,7 +608,8 @@ tts_minimal_materialize(TupleTableSlot *slot) { mslot->mintuple = heap_form_minimal_tuple(slot->tts_tupleDescriptor, slot->tts_values, - slot->tts_isnull); + slot->tts_isnull, + 0); } else { @@ -617,7 +619,7 @@ tts_minimal_materialize(TupleTableSlot *slot) * TTS_FLAG_SHOULDFREE set). Copy the minimal tuple into the given * slot's memory context. */ - mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple); + mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple, 0); } slot->tts_flags |= TTS_FLAG_SHOULDFREE; @@ -666,14 +668,14 @@ tts_minimal_copy_heap_tuple(TupleTableSlot *slot) } static MinimalTuple -tts_minimal_copy_minimal_tuple(TupleTableSlot *slot) +tts_minimal_copy_minimal_tuple(TupleTableSlot *slot, Size extra) { MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot; if (!mslot->mintuple) tts_minimal_materialize(slot); - return heap_copy_minimal_tuple(mslot->mintuple); + return heap_copy_minimal_tuple(mslot->mintuple, extra); } static void @@ -926,7 +928,7 @@ tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot) } static MinimalTuple -tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot) +tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot, Size extra) { BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot; @@ -935,7 +937,7 @@ tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot) if (!bslot->base.tuple) tts_buffer_heap_materialize(slot); - return minimal_tuple_from_heap_tuple(bslot->base.tuple); + return minimal_tuple_from_heap_tuple(bslot->base.tuple, extra); } static inline void @@ -990,6 +992,118 @@ tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, } } +/* + * slot_deform_heap_tuple_internal + * An always inline helper function for use in slot_deform_heap_tuple to + * allow the compiler to emit specialized versions of this function for + * various combinations of "slow" and "hasnulls". For example, if a + * given tuple has no nulls, then we needn't check "hasnulls" for every + * attribute that we're deforming. The caller can just call this + * function with hasnulls set to constant-false and have the compiler + * remove the constant-false branches and emit more optimal code. + * + * Returns the next attnum to deform, which can be equal to natts when the + * function manages to deform all requested attributes. *offp is an input and + * output parameter which is the byte offset within the tuple to start deforming + * from which, on return, gets set to the offset where the next attribute + * should be deformed from. *slowp is set to true when subsequent deforming + * of this tuple must use a version of this function with "slow" passed as + * true. + * + * Callers cannot assume when we return "attnum" (i.e. all requested + * attributes have been deformed) that slow mode isn't required for any + * additional deforming as the final attribute may have caused a switch to + * slow mode. + */ +static pg_attribute_always_inline int +slot_deform_heap_tuple_internal(TupleTableSlot *slot, HeapTuple tuple, + int attnum, int natts, bool slow, + bool hasnulls, uint32 *offp, bool *slowp) +{ + TupleDesc tupleDesc = slot->tts_tupleDescriptor; + Datum *values = slot->tts_values; + bool *isnull = slot->tts_isnull; + HeapTupleHeader tup = tuple->t_data; + char *tp; /* ptr to tuple data */ + bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ + bool slownext = false; + + tp = (char *) tup + tup->t_hoff; + + for (; attnum < natts; attnum++) + { + CompactAttribute *thisatt = TupleDescCompactAttr(tupleDesc, attnum); + + if (hasnulls && att_isnull(attnum, bp)) + { + values[attnum] = (Datum) 0; + isnull[attnum] = true; + if (!slow) + { + *slowp = true; + return attnum + 1; + } + else + continue; + } + + isnull[attnum] = false; + + /* calculate the offset of this attribute */ + if (!slow && thisatt->attcacheoff >= 0) + *offp = thisatt->attcacheoff; + else if (thisatt->attlen == -1) + { + /* + * We can only cache the offset for a varlena attribute if the + * offset is already suitably aligned, so that there would be no + * pad bytes in any case: then the offset will be valid for either + * an aligned or unaligned value. + */ + if (!slow && *offp == att_nominal_alignby(*offp, thisatt->attalignby)) + thisatt->attcacheoff = *offp; + else + { + *offp = att_pointer_alignby(*offp, + thisatt->attalignby, + -1, + tp + *offp); + + if (!slow) + slownext = true; + } + } + else + { + /* not varlena, so safe to use att_nominal_alignby */ + *offp = att_nominal_alignby(*offp, thisatt->attalignby); + + if (!slow) + thisatt->attcacheoff = *offp; + } + + values[attnum] = fetchatt(thisatt, tp + *offp); + + *offp = att_addlength_pointer(*offp, thisatt->attlen, tp + *offp); + + /* check if we need to switch to slow mode */ + if (!slow) + { + /* + * We're unable to deform any further if the above code set + * 'slownext', or if this isn't a fixed-width attribute. + */ + if (slownext || thisatt->attlen <= 0) + { + *slowp = true; + return attnum + 1; + } + } + } + + return natts; +} + /* * slot_deform_heap_tuple * Given a TupleTableSlot, extract data from the slot's physical tuple @@ -1008,15 +1122,9 @@ static pg_attribute_always_inline void slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts) { - TupleDesc tupleDesc = slot->tts_tupleDescriptor; - Datum *values = slot->tts_values; - bool *isnull = slot->tts_isnull; - HeapTupleHeader tup = tuple->t_data; bool hasnulls = HeapTupleHasNulls(tuple); int attnum; - char *tp; /* ptr to tuple data */ uint32 off; /* offset in tuple data */ - bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bool slow; /* can we use/set attcacheoff? */ /* We can only fetch as many attributes as the tuple has. */ @@ -1040,57 +1148,52 @@ slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, slow = TTS_SLOW(slot); } - tp = (char *) tup + tup->t_hoff; - - for (; attnum < natts; attnum++) + /* + * If 'slow' isn't set, try deforming using deforming code that does not + * contain any of the extra checks required for non-fixed offset + * deforming. During deforming, if or when we find a NULL or a variable + * length attribute, we'll switch to a deforming method which includes the + * extra code required for non-fixed offset deforming, a.k.a slow mode. + * Because this is performance critical, we inline + * slot_deform_heap_tuple_internal passing the 'slow' and 'hasnull' + * parameters as constants to allow the compiler to emit specialized code + * with the known-const false comparisons and subsequent branches removed. + */ + if (!slow) { - Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum); - - if (hasnulls && att_isnull(attnum, bp)) - { - values[attnum] = (Datum) 0; - isnull[attnum] = true; - slow = true; /* can't use attcacheoff anymore */ - continue; - } - - isnull[attnum] = false; - - if (!slow && thisatt->attcacheoff >= 0) - off = thisatt->attcacheoff; - else if (thisatt->attlen == -1) - { - /* - * We can only cache the offset for a varlena attribute if the - * offset is already suitably aligned, so that there would be no - * pad bytes in any case: then the offset will be valid for either - * an aligned or unaligned value. - */ - if (!slow && - off == att_align_nominal(off, thisatt->attalign)) - thisatt->attcacheoff = off; - else - { - off = att_align_pointer(off, thisatt->attalign, -1, - tp + off); - slow = true; - } - } + /* Tuple without any NULLs? We can skip doing any NULL checking */ + if (!hasnulls) + attnum = slot_deform_heap_tuple_internal(slot, + tuple, + attnum, + natts, + false, /* slow */ + false, /* hasnulls */ + &off, + &slow); else - { - /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, thisatt->attalign); - - if (!slow) - thisatt->attcacheoff = off; - } - - values[attnum] = fetchatt(thisatt, tp + off); - - off = att_addlength_pointer(off, thisatt->attlen, tp + off); + attnum = slot_deform_heap_tuple_internal(slot, + tuple, + attnum, + natts, + false, /* slow */ + true, /* hasnulls */ + &off, + &slow); + } - if (thisatt->attlen <= 0) - slow = true; /* can't use attcacheoff anymore */ + /* If there's still work to do then we must be in slow mode */ + if (attnum < natts) + { + /* XXX is it worth adding a separate call when hasnulls is false? */ + attnum = slot_deform_heap_tuple_internal(slot, + tuple, + attnum, + natts, + true, /* slow */ + hasnulls, + &off, + &slow); } /* @@ -1104,7 +1207,6 @@ slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, slot->tts_flags &= ~TTS_FLAG_SLOW; } - const TupleTableSlotOps TTSOpsVirtual = { .base_slot_size = sizeof(VirtualTupleTableSlot), .init = tts_virtual_init, @@ -1795,7 +1897,7 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot, { if (shouldFree) *shouldFree = true; - return slot->tts_ops->copy_minimal_tuple(slot); + return slot->tts_ops->copy_minimal_tuple(slot, 0); } } @@ -2237,7 +2339,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) */ for (i = 0; i < natts; i++) { - if (!TupleDescAttr(tupdesc, i)->attisdropped) + if (!TupleDescCompactAttr(tupdesc, i)->attisdropped) { /* Non-dropped attributes */ dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i], diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 5737f9f4ebd52..fdc65c2b42b33 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -3,7 +3,7 @@ * execUtils.c * miscellaneous executor utility routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -118,6 +118,7 @@ CreateExecutorState(void) estate->es_rowmarks = NULL; estate->es_rteperminfos = NIL; estate->es_plannedstmt = NULL; + estate->es_part_prune_infos = NIL; estate->es_junkFilter = NULL; @@ -158,6 +159,8 @@ CreateExecutorState(void) estate->es_sourceText = NULL; estate->es_use_parallel_mode = false; + estate->es_parallel_workers_to_launch = 0; + estate->es_parallel_workers_launched = 0; estate->es_jit_flags = 0; estate->es_jit = NULL; @@ -318,19 +321,18 @@ CreateExprContext(EState *estate) ExprContext * CreateWorkExprContext(EState *estate) { - Size minContextSize = ALLOCSET_DEFAULT_MINSIZE; - Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE; Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE; - /* choose the maxBlockSize to be no larger than 1/16 of work_mem */ - while (16 * maxBlockSize > work_mem * 1024L) - maxBlockSize >>= 1; + maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16); - if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE) - maxBlockSize = ALLOCSET_DEFAULT_INITSIZE; + /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */ + maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE); - return CreateExprContextInternal(estate, minContextSize, - initBlockSize, maxBlockSize); + /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */ + maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE); + + return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, maxBlockSize); } /* ---------------- @@ -524,6 +526,49 @@ ExecGetResultSlotOps(PlanState *planstate, bool *isfixed) return planstate->ps_ResultTupleSlot->tts_ops; } +/* + * ExecGetCommonSlotOps - identify common result slot type, if any + * + * If all the given PlanState nodes return the same fixed tuple slot type, + * return the slot ops struct for that slot type. Else, return NULL. + */ +const TupleTableSlotOps * +ExecGetCommonSlotOps(PlanState **planstates, int nplans) +{ + const TupleTableSlotOps *result; + bool isfixed; + + if (nplans <= 0) + return NULL; + result = ExecGetResultSlotOps(planstates[0], &isfixed); + if (!isfixed) + return NULL; + for (int i = 1; i < nplans; i++) + { + const TupleTableSlotOps *thisops; + + thisops = ExecGetResultSlotOps(planstates[i], &isfixed); + if (!isfixed) + return NULL; + if (result != thisops) + return NULL; + } + return result; +} + +/* + * ExecGetCommonChildSlotOps - as above, for the PlanState's standard children + */ +const TupleTableSlotOps * +ExecGetCommonChildSlotOps(PlanState *ps) +{ + PlanState *planstates[2]; + + planstates[0] = outerPlanState(ps); + planstates[1] = innerPlanState(ps); + return ExecGetCommonSlotOps(planstates, 2); +} + /* ---------------- * ExecAssignProjectionInfo @@ -699,7 +744,7 @@ ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags) Relation rel; /* Open the relation. */ - rel = ExecGetRangeTableRelation(estate, scanrelid); + rel = ExecGetRangeTableRelation(estate, scanrelid, false); /* * Complain if we're attempting a scan of an unscannable relation, except @@ -725,7 +770,8 @@ ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags) * indexed by rangetable index. */ void -ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos) +ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos, + Bitmapset *unpruned_relids) { /* Remember the range table List as-is */ estate->es_range_table = rangeTable; @@ -736,6 +782,15 @@ ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos) /* Set size of associated arrays */ estate->es_range_table_size = list_length(rangeTable); + /* + * Initialize the bitmapset of RT indexes (es_unpruned_relids) + * representing relations that will be scanned during execution. This set + * is initially populated by the caller and may be extended later by + * ExecDoInitialPruning() to include RT indexes of unpruned leaf + * partitions. + */ + estate->es_unpruned_relids = unpruned_relids; + /* * Allocate an array to store an open Relation corresponding to each * rangetable entry, and initialize entries to NULL. Relations are opened @@ -756,15 +811,26 @@ ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos) * ExecGetRangeTableRelation * Open the Relation for a range table entry, if not already done * - * The Relations will be closed again in ExecEndPlan(). + * The Relations will be closed in ExecEndPlan(). + * + * If isResultRel is true, the relation is being used as a result relation. + * Such a relation might have been pruned, which is OK for result relations, + * but not for scan relations; see the details in ExecInitModifyTable(). If + * isResultRel is false, the caller must ensure that 'rti' refers to an + * unpruned relation (i.e., it is a member of estate->es_unpruned_relids) + * before calling this function. Attempting to open a pruned relation for + * scanning will result in an error. */ Relation -ExecGetRangeTableRelation(EState *estate, Index rti) +ExecGetRangeTableRelation(EState *estate, Index rti, bool isResultRel) { Relation rel; Assert(rti > 0 && rti <= estate->es_range_table_size); + if (!isResultRel && !bms_is_member(rti, estate->es_unpruned_relids)) + elog(ERROR, "trying to open a pruned relation"); + rel = estate->es_relations[rti - 1]; if (rel == NULL) { @@ -816,7 +882,7 @@ ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, { Relation resultRelationDesc; - resultRelationDesc = ExecGetRangeTableRelation(estate, rti); + resultRelationDesc = ExecGetRangeTableRelation(estate, rti, true); InitResultRelInfo(resultRelInfo, resultRelationDesc, rti, @@ -1197,6 +1263,34 @@ ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo) return relInfo->ri_ReturningSlot; } +/* + * Return a relInfo's all-NULL tuple slot for processing returning tuples. + * + * Note: this slot is intentionally filled with NULLs in every column, and + * should be considered read-only --- the caller must not update it. + */ +TupleTableSlot * +ExecGetAllNullSlot(EState *estate, ResultRelInfo *relInfo) +{ + if (relInfo->ri_AllNullSlot == NULL) + { + Relation rel = relInfo->ri_RelationDesc; + MemoryContext oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + TupleTableSlot *slot; + + slot = ExecInitExtraTupleSlot(estate, + RelationGetDescr(rel), + table_slot_callbacks(rel)); + ExecStoreAllNullTuple(slot); + + relInfo->ri_AllNullSlot = slot; + + MemoryContextSwitchTo(oldcontext); + } + + return relInfo->ri_AllNullSlot; +} + /* * Return the map needed to convert given child result relation's tuples to * the rowtype of the query's main target ("root") relation. Note that a @@ -1309,8 +1403,8 @@ Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate) { /* Compute the info if we didn't already */ - if (relinfo->ri_GeneratedExprsU == NULL) - ExecInitStoredGenerated(relinfo, estate, CMD_UPDATE); + if (!relinfo->ri_extraUpdatedCols_valid) + ExecInitGenerated(relinfo, estate, CMD_UPDATE); return relinfo->ri_extraUpdatedCols; } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 692854e2b3e7e..359aafea681b9 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -3,7 +3,7 @@ * functions.c * Execution of SQL-language functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -31,8 +31,10 @@ #include "tcop/utility.h" #include "utils/builtins.h" #include "utils/datum.h" +#include "utils/funccache.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/plancache.h" #include "utils/snapmgr.h" #include "utils/syscache.h" @@ -43,19 +45,20 @@ typedef struct { DestReceiver pub; /* publicly-known function pointers */ - Tuplestorestate *tstore; /* where to put result tuples */ - MemoryContext cxt; /* context containing tstore */ + Tuplestorestate *tstore; /* where to put result tuples, or NULL */ JunkFilter *filter; /* filter to convert tuple type */ } DR_sqlfunction; /* * We have an execution_state record for each query in a function. Each - * record contains a plantree for its query. If the query is currently in + * record references a plantree for its query. If the query is currently in * F_EXEC_RUN state then there's a QueryDesc too. * * The "next" fields chain together all the execution_state records generated * from a single original parsetree. (There will only be more than one in - * case of rule expansion of the original parsetree.) + * case of rule expansion of the original parsetree.) The chain structure is + * quite vestigial at this point, because we allocate the records in an array + * for ease of memory management. But we'll get rid of it some other day. */ typedef enum { @@ -74,57 +77,115 @@ typedef struct execution_state /* - * An SQLFunctionCache record is built during the first call, - * and linked to from the fn_extra field of the FmgrInfo struct. + * Data associated with a SQL-language function is kept in two main + * data structures: * - * Note that currently this has only the lifespan of the calling query. - * Someday we should rewrite this code to use plancache.c to save parse/plan - * results for longer than that. + * 1. SQLFunctionHashEntry is a long-lived (potentially session-lifespan) + * struct that holds all the info we need out of the function's pg_proc row. + * In addition it holds pointers to CachedPlanSource(s) that manage creation + * of plans for the query(s) within the function. A SQLFunctionHashEntry is + * potentially shared across multiple concurrent executions of the function, + * so it must contain no execution-specific state; but its use_count must + * reflect the number of SQLFunctionCache structs pointing at it. + * If the function's pg_proc row is updated, we throw away and regenerate + * the SQLFunctionHashEntry and subsidiary data. (Also note that if the + * function is polymorphic or used as a trigger, there is a separate + * SQLFunctionHashEntry for each usage, so that we need consider only one + * set of relevant data types.) The struct itself is in memory managed by + * funccache.c, and its subsidiary data is kept in one of two contexts: + * * pcontext ("parse context") holds the raw parse trees or Query trees + * that we read from the pg_proc row. These will be converted to + * CachedPlanSources as they are needed. Once the last one is converted, + * pcontext can be freed. + * * hcontext ("hash context") holds everything else belonging to the + * SQLFunctionHashEntry. * - * Physically, though, the data has the lifespan of the FmgrInfo that's used - * to call the function, and there are cases (particularly with indexes) - * where the FmgrInfo might survive across transactions. We cannot assume - * that the parse/plan trees are good for longer than the (sub)transaction in - * which parsing was done, so we must mark the record with the LXID/subxid of - * its creation time, and regenerate everything if that's obsolete. To avoid - * memory leakage when we do have to regenerate things, all the data is kept - * in a sub-context of the FmgrInfo's fn_mcxt. + * 2. SQLFunctionCache is subsidiary data for a single FmgrInfo struct. + * It is pointed to by the fn_extra field of the FmgrInfo struct, and is + * always allocated in the FmgrInfo's fn_mcxt. It holds a reference to + * the CachedPlan for the current query, and other execution-specific data. + * A few subsidiary items such as the ParamListInfo object are also kept + * directly in fn_mcxt (which is also called fcontext here). But most + * subsidiary data is in jfcontext or subcontext. */ -typedef struct + +typedef struct SQLFunctionHashEntry { + CachedFunction cfunc; /* fields managed by funccache.c */ + char *fname; /* function name (for error msgs) */ char *src; /* function body text (for error msgs) */ SQLFunctionParseInfoPtr pinfo; /* data for parser callback hooks */ + int16 *argtyplen; /* lengths of the input argument types */ Oid rettype; /* actual return type */ int16 typlen; /* length of the return type */ bool typbyval; /* true if return type is pass by value */ bool returnsSet; /* true if returning multiple rows */ bool returnsTuple; /* true if returning whole tuple result */ - bool shutdown_reg; /* true if registered shutdown callback */ bool readonly_func; /* true to run in "read only" mode */ + char prokind; /* prokind from pg_proc row */ + + TupleDesc rettupdesc; /* result tuple descriptor */ + + List *source_list; /* RawStmts or Queries read from pg_proc */ + int num_queries; /* original length of source_list */ + bool raw_source; /* true if source_list contains RawStmts */ + + List *plansource_list; /* CachedPlanSources for fn's queries */ + + MemoryContext pcontext; /* memory context holding source_list */ + MemoryContext hcontext; /* memory context holding all else */ +} SQLFunctionHashEntry; + +typedef struct SQLFunctionCache +{ + SQLFunctionHashEntry *func; /* associated SQLFunctionHashEntry */ + + bool lazyEvalOK; /* true if lazyEval is safe */ + bool shutdown_reg; /* true if registered shutdown callback */ bool lazyEval; /* true if using lazyEval for result query */ + bool randomAccess; /* true if tstore needs random access */ + bool ownSubcontext; /* is subcontext really a separate context? */ ParamListInfo paramLI; /* Param list representing current args */ - Tuplestorestate *tstore; /* where we accumulate result tuples */ + Tuplestorestate *tstore; /* where we accumulate result for a SRF */ + MemoryContext tscontext; /* memory context that tstore should be in */ JunkFilter *junkFilter; /* will be NULL if function returns VOID */ + int jf_generation; /* tracks whether junkFilter is up-to-date */ /* - * func_state is a List of execution_state records, each of which is the - * first for its original parsetree, with any additional records chained - * to it via the "next" fields. This sublist structure is needed to keep - * track of where the original query boundaries are. + * While executing a particular query within the function, cplan is the + * CachedPlan we've obtained for that query, and eslist is a chain of + * execution_state records for the individual plans within the CachedPlan. + * If eslist is not NULL at entry to fmgr_sql, then we are resuming + * execution of a lazyEval-mode set-returning function. + * + * next_query_index is the 0-based index of the next CachedPlanSource to + * get a CachedPlan from. */ - List *func_state; + CachedPlan *cplan; /* Plan for current query, if any */ + ResourceOwner cowner; /* CachedPlan is registered with this owner */ + int next_query_index; /* index of next CachedPlanSource to run */ + + execution_state *eslist; /* chain of execution_state records */ + execution_state *esarray; /* storage for eslist */ + int esarray_len; /* allocated length of esarray[] */ + + /* if positive, this is the 1-based index of the query we're processing */ + int error_query_index; MemoryContext fcontext; /* memory context holding this struct and all * subsidiary data */ + MemoryContext jfcontext; /* subsidiary memory context holding + * junkFilter, result slot, and related data */ + MemoryContext subcontext; /* subsidiary memory context for sub-executor */ - LocalTransactionId lxid; /* lxid in which cache was made */ - SubTransactionId subxid; /* subxid in which cache was made */ + /* Callback to release our use-count on the SQLFunctionHashEntry */ + MemoryContextCallback mcb; } SQLFunctionCache; typedef SQLFunctionCache *SQLFunctionCachePtr; @@ -138,26 +199,39 @@ static Node *sql_fn_make_param(SQLFunctionParseInfoPtr pinfo, int paramno, int location); static Node *sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo, const char *paramname, int location); -static List *init_execution_state(List *queryTree_list, - SQLFunctionCachePtr fcache, - bool lazyEvalOK); -static void init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK); +static SQLFunctionCache *init_sql_fcache(FunctionCallInfo fcinfo, + bool lazyEvalOK); +static bool init_execution_state(SQLFunctionCachePtr fcache); +static void prepare_next_query(SQLFunctionHashEntry *func); +static void sql_compile_callback(FunctionCallInfo fcinfo, + HeapTuple procedureTuple, + const CachedFunctionHashKey *hashkey, + CachedFunction *cfunc, + bool forValidator); +static void sql_delete_callback(CachedFunction *cfunc); +static void sql_postrewrite_callback(List *querytree_list, void *arg); static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache); static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache); -static void postquel_end(execution_state *es); +static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache); static void postquel_sub_params(SQLFunctionCachePtr fcache, FunctionCallInfo fcinfo); static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, - SQLFunctionCachePtr fcache, - MemoryContext resultcontext); + SQLFunctionCachePtr fcache); +static void sql_compile_error_callback(void *arg); static void sql_exec_error_callback(void *arg); static void ShutdownSQLFunction(Datum arg); +static void RemoveSQLFunctionCache(void *arg); +static void check_sql_fn_statement(List *queryTreeList); +static bool check_sql_stmt_retval(List *queryTreeList, + Oid rettype, TupleDesc rettupdesc, + char prokind, bool insertDroppedCols); static bool coerce_fn_result_column(TargetEntry *src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List **upper_tlist, bool *upper_tlist_nontrivial); +static List *get_sql_fn_result_tlist(List *queryTreeList); static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo); static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self); static void sqlfunction_shutdown(DestReceiver *self); @@ -268,7 +342,7 @@ sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo) pstate->p_post_columnref_hook = sql_fn_post_column_ref; pstate->p_paramref_hook = sql_fn_param_ref; /* no need to use p_coerce_param_hook */ - pstate->p_ref_hook_state = (void *) pinfo; + pstate->p_ref_hook_state = pinfo; } /* @@ -455,99 +529,317 @@ sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo, } /* - * Set up the per-query execution_state records for a SQL function. + * Initialize the SQLFunctionCache for a SQL function + */ +static SQLFunctionCache * +init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK) +{ + FmgrInfo *finfo = fcinfo->flinfo; + SQLFunctionHashEntry *func; + SQLFunctionCache *fcache; + + /* + * If this is the first execution for this FmgrInfo, set up a cache struct + * (initially containing null pointers). The cache must live as long as + * the FmgrInfo, so it goes in fn_mcxt. Also set up a memory context + * callback that will be invoked when fn_mcxt is deleted. + */ + fcache = finfo->fn_extra; + if (fcache == NULL) + { + fcache = (SQLFunctionCache *) + MemoryContextAllocZero(finfo->fn_mcxt, sizeof(SQLFunctionCache)); + fcache->fcontext = finfo->fn_mcxt; + fcache->mcb.func = RemoveSQLFunctionCache; + fcache->mcb.arg = fcache; + MemoryContextRegisterResetCallback(finfo->fn_mcxt, &fcache->mcb); + finfo->fn_extra = fcache; + } + + /* + * If we are resuming execution of a set-returning function, just keep + * using the same cache. We do not ask funccache.c to re-validate the + * SQLFunctionHashEntry: we want to run to completion using the function's + * initial definition. + */ + if (fcache->eslist != NULL) + { + Assert(fcache->func != NULL); + return fcache; + } + + /* + * Look up, or re-validate, the long-lived hash entry. Make the hash key + * depend on the result of get_call_result_type() when that's composite, + * so that we can safely assume that we'll build a new hash entry if the + * composite rowtype changes. + */ + func = (SQLFunctionHashEntry *) + cached_function_compile(fcinfo, + (CachedFunction *) fcache->func, + sql_compile_callback, + sql_delete_callback, + sizeof(SQLFunctionHashEntry), + true, + false); + + /* + * Install the hash pointer in the SQLFunctionCache, and increment its use + * count to reflect that. If cached_function_compile gave us back a + * different hash entry than we were using before, we must decrement that + * one's use count. + */ + if (func != fcache->func) + { + if (fcache->func != NULL) + { + Assert(fcache->func->cfunc.use_count > 0); + fcache->func->cfunc.use_count--; + } + fcache->func = func; + func->cfunc.use_count++; + /* Assume we need to rebuild the junkFilter */ + fcache->junkFilter = NULL; + } + + /* + * We're beginning a new execution of the function, so convert params to + * appropriate format. + */ + postquel_sub_params(fcache, fcinfo); + + /* Also reset lazyEval state for the new execution. */ + fcache->lazyEvalOK = lazyEvalOK; + fcache->lazyEval = false; + + /* Also reset data about where we are in the function. */ + fcache->eslist = NULL; + fcache->next_query_index = 0; + fcache->error_query_index = 0; + + return fcache; +} + +/* + * Set up the per-query execution_state records for the next query within + * the SQL function. * - * The input is a List of Lists of parsed and rewritten, but not planned, - * querytrees. The sublist structure denotes the original query boundaries. + * Returns true if successful, false if there are no more queries. */ -static List * -init_execution_state(List *queryTree_list, - SQLFunctionCachePtr fcache, - bool lazyEvalOK) +static bool +init_execution_state(SQLFunctionCachePtr fcache) { - List *eslist = NIL; + CachedPlanSource *plansource; + execution_state *preves = NULL; execution_state *lasttages = NULL; - ListCell *lc1; + int nstmts; + ListCell *lc; - foreach(lc1, queryTree_list) + /* + * Clean up after previous query, if there was one. + */ + if (fcache->cplan) { - List *qtlist = lfirst_node(List, lc1); - execution_state *firstes = NULL; - execution_state *preves = NULL; - ListCell *lc2; + ReleaseCachedPlan(fcache->cplan, fcache->cowner); + fcache->cplan = NULL; + } + fcache->eslist = NULL; - foreach(lc2, qtlist) - { - Query *queryTree = lfirst_node(Query, lc2); - PlannedStmt *stmt; - execution_state *newes; + /* + * Get the next CachedPlanSource, or stop if there are no more. We might + * need to create the next CachedPlanSource; if so, advance + * error_query_index first, so that errors detected in prepare_next_query + * are blamed on the right statement. + */ + if (fcache->next_query_index >= list_length(fcache->func->plansource_list)) + { + if (fcache->next_query_index >= fcache->func->num_queries) + return false; + fcache->error_query_index++; + prepare_next_query(fcache->func); + } + else + fcache->error_query_index++; - /* Plan the query if needed */ - if (queryTree->commandType == CMD_UTILITY) - { - /* Utility commands require no planning. */ - stmt = makeNode(PlannedStmt); - stmt->commandType = CMD_UTILITY; - stmt->canSetTag = queryTree->canSetTag; - stmt->utilityStmt = queryTree->utilityStmt; - stmt->stmt_location = queryTree->stmt_location; - stmt->stmt_len = queryTree->stmt_len; - stmt->queryId = queryTree->queryId; - } - else - stmt = pg_plan_query(queryTree, - fcache->src, - CURSOR_OPT_PARALLEL_OK, - NULL); + plansource = (CachedPlanSource *) list_nth(fcache->func->plansource_list, + fcache->next_query_index); + fcache->next_query_index++; - /* - * Precheck all commands for validity in a function. This should - * generally match the restrictions spi.c applies. - */ - if (stmt->commandType == CMD_UTILITY) - { - if (IsA(stmt->utilityStmt, CopyStmt) && - ((CopyStmt *) stmt->utilityStmt)->filename == NULL) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot COPY to/from client in an SQL function"))); + /* + * Generate plans for the query or queries within this CachedPlanSource. + * Register the CachedPlan with the current resource owner. (Saving + * cowner here is mostly paranoia, but this way we needn't assume that + * CurrentResourceOwner will be the same when ShutdownSQLFunction runs.) + */ + fcache->cowner = CurrentResourceOwner; + fcache->cplan = GetCachedPlan(plansource, + fcache->paramLI, + fcache->cowner, + NULL); - if (IsA(stmt->utilityStmt, TransactionStmt)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is a SQL statement name */ - errmsg("%s is not allowed in an SQL function", - CreateCommandName(stmt->utilityStmt)))); - } + /* + * If necessary, make esarray[] bigger to hold the needed state. + */ + nstmts = list_length(fcache->cplan->stmt_list); + if (nstmts > fcache->esarray_len) + { + if (fcache->esarray == NULL) + fcache->esarray = (execution_state *) + MemoryContextAlloc(fcache->fcontext, + sizeof(execution_state) * nstmts); + else + fcache->esarray = repalloc_array(fcache->esarray, + execution_state, nstmts); + fcache->esarray_len = nstmts; + } + + /* + * Build execution_state list to match the number of contained plans. + */ + foreach(lc, fcache->cplan->stmt_list) + { + PlannedStmt *stmt = lfirst_node(PlannedStmt, lc); + execution_state *newes; + + /* + * Precheck all commands for validity in a function. This should + * generally match the restrictions spi.c applies. + */ + if (stmt->commandType == CMD_UTILITY) + { + if (IsA(stmt->utilityStmt, CopyStmt) && + ((CopyStmt *) stmt->utilityStmt)->filename == NULL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot COPY to/from client in an SQL function"))); - if (fcache->readonly_func && !CommandIsReadOnly(stmt)) + if (IsA(stmt->utilityStmt, TransactionStmt)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is a SQL statement name */ - errmsg("%s is not allowed in a non-volatile function", - CreateCommandName((Node *) stmt)))); + errmsg("%s is not allowed in an SQL function", + CreateCommandName(stmt->utilityStmt)))); + } - /* OK, build the execution_state for this query */ - newes = (execution_state *) palloc(sizeof(execution_state)); - if (preves) - preves->next = newes; - else - firstes = newes; + if (fcache->func->readonly_func && !CommandIsReadOnly(stmt)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is a SQL statement name */ + errmsg("%s is not allowed in a non-volatile function", + CreateCommandName((Node *) stmt)))); + + /* OK, build the execution_state for this query */ + newes = &fcache->esarray[foreach_current_index(lc)]; + if (preves) + preves->next = newes; + else + fcache->eslist = newes; - newes->next = NULL; - newes->status = F_EXEC_START; - newes->setsResult = false; /* might change below */ - newes->lazyEval = false; /* might change below */ - newes->stmt = stmt; - newes->qd = NULL; + newes->next = NULL; + newes->status = F_EXEC_START; + newes->setsResult = false; /* might change below */ + newes->lazyEval = false; /* might change below */ + newes->stmt = stmt; + newes->qd = NULL; - if (queryTree->canSetTag) - lasttages = newes; + if (stmt->canSetTag) + lasttages = newes; - preves = newes; - } + preves = newes; + } + + /* + * If this isn't the last CachedPlanSource, we're done here. Otherwise, + * we need to prepare information about how to return the results. + */ + if (fcache->next_query_index < fcache->func->num_queries) + return true; + + /* + * Construct a JunkFilter we can use to coerce the returned rowtype to the + * desired form, unless the result type is VOID, in which case there's + * nothing to coerce to. (XXX Frequently, the JunkFilter isn't doing + * anything very interesting, but much of this module expects it to be + * there anyway.) + * + * Normally we can re-use the JunkFilter across executions, but if the + * plan for the last CachedPlanSource changed, we'd better rebuild it. + * + * The JunkFilter, its result slot, and its tupledesc are kept in a + * subsidiary memory context so that we can free them easily when needed. + */ + if (fcache->func->rettype != VOIDOID && + (fcache->junkFilter == NULL || + fcache->jf_generation != fcache->cplan->generation)) + { + TupleTableSlot *slot; + List *resulttlist; + MemoryContext oldcontext; + + /* Create or reset the jfcontext */ + if (fcache->jfcontext == NULL) + fcache->jfcontext = AllocSetContextCreate(fcache->fcontext, + "SQL function junkfilter", + ALLOCSET_SMALL_SIZES); + else + MemoryContextReset(fcache->jfcontext); + oldcontext = MemoryContextSwitchTo(fcache->jfcontext); + + slot = MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple); + + /* + * Re-fetch the (possibly modified) output tlist of the final + * statement. By this point, we should have thrown an error if there + * is not one. + */ + resulttlist = get_sql_fn_result_tlist(plansource->query_list); + + /* + * If the result is composite, *and* we are returning the whole tuple + * result, we need to insert nulls for any dropped columns. In the + * single-column-result case, there might be dropped columns within + * the composite column value, but it's not our problem here. There + * should be no resjunk entries in resulttlist, so in the second case + * the JunkFilter is certainly a no-op. + */ + if (fcache->func->rettupdesc && fcache->func->returnsTuple) + fcache->junkFilter = ExecInitJunkFilterConversion(resulttlist, + fcache->func->rettupdesc, + slot); + else + fcache->junkFilter = ExecInitJunkFilter(resulttlist, slot); + + /* + * The resulttlist tree belongs to the plancache and might disappear + * underneath us due to plancache invalidation. While we could + * forestall that by copying it, that'd just be a waste of cycles, + * because the junkfilter doesn't need it anymore. (It'd only be used + * by ExecFindJunkAttribute(), which we don't use here.) To ensure + * there's not a dangling pointer laying about, clear the junkFilter's + * pointer. + */ + fcache->junkFilter->jf_targetList = NIL; + + /* Make sure output rowtype is properly blessed */ + if (fcache->func->returnsTuple) + BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor); + + /* Mark the JunkFilter as up-to-date */ + fcache->jf_generation = fcache->cplan->generation; + + MemoryContextSwitchTo(oldcontext); + } - eslist = lappend(eslist, firstes); + if (fcache->func->returnsSet && + !fcache->func->returnsTuple && + type_is_rowtype(fcache->func->rettype)) + { + /* + * Returning rowtype as if it were scalar --- materialize won't work. + * Right now it's sufficient to override any caller preference for + * materialize mode, but this might need more work in future. + */ + fcache->lazyEvalOK = true; } /* @@ -567,69 +859,212 @@ init_execution_state(List *queryTree_list, if (lasttages && fcache->junkFilter) { lasttages->setsResult = true; - if (lazyEvalOK && + if (fcache->lazyEvalOK && lasttages->stmt->commandType == CMD_SELECT && !lasttages->stmt->hasModifyingCTE) fcache->lazyEval = lasttages->lazyEval = true; } - return eslist; + return true; } /* - * Initialize the SQLFunctionCache for a SQL function + * Convert the SQL function's next query from source form (RawStmt or Query) + * into a CachedPlanSource. If it's the last query, also determine whether + * the function returnsTuple. */ static void -init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK) +prepare_next_query(SQLFunctionHashEntry *func) { - FmgrInfo *finfo = fcinfo->flinfo; - Oid foid = finfo->fn_oid; - MemoryContext fcontext; + int qindex; + bool islast; + CachedPlanSource *plansource; + List *queryTree_list; MemoryContext oldcontext; + + /* Which query should we process? */ + qindex = list_length(func->plansource_list); + Assert(qindex < func->num_queries); /* else caller error */ + islast = (qindex + 1 >= func->num_queries); + + /* + * Parse and/or rewrite the query, creating a CachedPlanSource that holds + * a copy of the original parsetree. Note fine point: we make a copy of + * each original parsetree to ensure that the source_list in pcontext + * remains unmodified during parse analysis and rewrite. This is normally + * unnecessary, but we have to do it in case an error is raised during + * parse analysis. Otherwise, a fresh attempt to execute the function + * will arrive back here and try to work from a corrupted source_list. + */ + if (!func->raw_source) + { + /* Source queries are already parse-analyzed */ + Query *parsetree = list_nth_node(Query, func->source_list, qindex); + + parsetree = copyObject(parsetree); + plansource = CreateCachedPlanForQuery(parsetree, + func->src, + CreateCommandTag((Node *) parsetree)); + AcquireRewriteLocks(parsetree, true, false); + queryTree_list = pg_rewrite_query(parsetree); + } + else + { + /* Source queries are raw parsetrees */ + RawStmt *parsetree = list_nth_node(RawStmt, func->source_list, qindex); + + parsetree = copyObject(parsetree); + plansource = CreateCachedPlan(parsetree, + func->src, + CreateCommandTag(parsetree->stmt)); + queryTree_list = pg_analyze_and_rewrite_withcb(parsetree, + func->src, + (ParserSetupHook) sql_fn_parser_setup, + func->pinfo, + NULL); + } + + /* + * Check that there are no statements we don't want to allow. + */ + check_sql_fn_statement(queryTree_list); + + /* + * If this is the last query, check that the function returns the type it + * claims to. Although in simple cases this was already done when the + * function was defined, we have to recheck because database objects used + * in the function's queries might have changed type. We'd have to + * recheck anyway if the function had any polymorphic arguments. Moreover, + * check_sql_stmt_retval takes care of injecting any required column type + * coercions. (But we don't ask it to insert nulls for dropped columns; + * the junkfilter handles that.) + * + * Note: we set func->returnsTuple according to whether we are returning + * the whole tuple result or just a single column. In the latter case we + * clear returnsTuple because we need not act different from the scalar + * result case, even if it's a rowtype column. (However, we have to force + * lazy eval mode in that case; otherwise we'd need extra code to expand + * the rowtype column into multiple columns, since we have no way to + * notify the caller that it should do that.) + */ + if (islast) + func->returnsTuple = check_sql_stmt_retval(queryTree_list, + func->rettype, + func->rettupdesc, + func->prokind, + false); + + /* + * Now that check_sql_stmt_retval has done its thing, we can complete plan + * cache entry creation. + */ + CompleteCachedPlan(plansource, + queryTree_list, + NULL, + NULL, + 0, + (ParserSetupHook) sql_fn_parser_setup, + func->pinfo, + CURSOR_OPT_PARALLEL_OK | CURSOR_OPT_NO_SCROLL, + false); + + /* + * Install post-rewrite hook. Its arg is the hash entry if this is the + * last statement, else NULL. + */ + SetPostRewriteHook(plansource, + sql_postrewrite_callback, + islast ? func : NULL); + + /* + * While the CachedPlanSources can take care of themselves, our List + * pointing to them had better be in the hcontext. + */ + oldcontext = MemoryContextSwitchTo(func->hcontext); + func->plansource_list = lappend(func->plansource_list, plansource); + MemoryContextSwitchTo(oldcontext); + + /* + * As soon as we've linked the CachedPlanSource into the list, mark it as + * "saved". + */ + SaveCachedPlan(plansource); + + /* + * Finally, if this was the last statement, we can flush the pcontext with + * the original query trees; they're all safely copied into + * CachedPlanSources now. + */ + if (islast) + { + func->source_list = NIL; /* avoid dangling pointer */ + MemoryContextDelete(func->pcontext); + func->pcontext = NULL; + } +} + +/* + * Fill a new SQLFunctionHashEntry. + * + * The passed-in "cfunc" struct is expected to be zeroes, except + * for the CachedFunction fields, which we don't touch here. + * + * We expect to be called in a short-lived memory context (typically a + * query's per-tuple context). Data that is to be part of the hash entry + * must be copied into the hcontext or pcontext as appropriate. + */ +static void +sql_compile_callback(FunctionCallInfo fcinfo, + HeapTuple procedureTuple, + const CachedFunctionHashKey *hashkey, + CachedFunction *cfunc, + bool forValidator) +{ + SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) cfunc; + Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); + ErrorContextCallback comperrcontext; + MemoryContext hcontext; + MemoryContext pcontext; + MemoryContext oldcontext = CurrentMemoryContext; Oid rettype; TupleDesc rettupdesc; - HeapTuple procedureTuple; - Form_pg_proc procedureStruct; - SQLFunctionCachePtr fcache; - List *queryTree_list; - List *resulttlist; - ListCell *lc; Datum tmp; bool isNull; + List *source_list; /* - * Create memory context that holds all the SQLFunctionCache data. It - * must be a child of whatever context holds the FmgrInfo. + * Setup error traceback support for ereport() during compile. (This is + * mainly useful for reporting parse errors from pg_parse_query.) */ - fcontext = AllocSetContextCreate(finfo->fn_mcxt, - "SQL function", - ALLOCSET_DEFAULT_SIZES); - - oldcontext = MemoryContextSwitchTo(fcontext); + comperrcontext.callback = sql_compile_error_callback; + comperrcontext.arg = func; + comperrcontext.previous = error_context_stack; + error_context_stack = &comperrcontext; /* - * Create the struct proper, link it to fcontext and fn_extra. Once this - * is done, we'll be able to recover the memory after failure, even if the - * FmgrInfo is long-lived. + * Create the hash entry's memory context. For now it's a child of the + * caller's context, so that it will go away if we fail partway through. */ - fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache)); - fcache->fcontext = fcontext; - finfo->fn_extra = (void *) fcache; + hcontext = AllocSetContextCreate(CurrentMemoryContext, + "SQL function", + ALLOCSET_SMALL_SIZES); /* - * get the procedure tuple corresponding to the given function Oid + * Create the not-as-long-lived pcontext. We make this a child of + * hcontext so that it doesn't require separate deletion. */ - procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(foid)); - if (!HeapTupleIsValid(procedureTuple)) - elog(ERROR, "cache lookup failed for function %u", foid); - procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); + pcontext = AllocSetContextCreate(hcontext, + "SQL function parse trees", + ALLOCSET_SMALL_SIZES); + func->pcontext = pcontext; /* * copy function name immediately for use by error reporting callback, and * for use as memory context identifier */ - fcache->fname = pstrdup(NameStr(procedureStruct->proname)); - MemoryContextSetIdentifier(fcontext, fcache->fname); + func->fname = MemoryContextStrdup(hcontext, + NameStr(procedureStruct->proname)); + MemoryContextSetIdentifier(hcontext, func->fname); /* * Resolve any polymorphism, obtaining the actual result type, and the @@ -637,176 +1072,180 @@ init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK) */ (void) get_call_result_type(fcinfo, &rettype, &rettupdesc); - fcache->rettype = rettype; + func->rettype = rettype; + if (rettupdesc) + { + MemoryContextSwitchTo(hcontext); + func->rettupdesc = CreateTupleDescCopy(rettupdesc); + MemoryContextSwitchTo(oldcontext); + } /* Fetch the typlen and byval info for the result type */ - get_typlenbyval(rettype, &fcache->typlen, &fcache->typbyval); + get_typlenbyval(rettype, &func->typlen, &func->typbyval); /* Remember whether we're returning setof something */ - fcache->returnsSet = procedureStruct->proretset; + func->returnsSet = procedureStruct->proretset; /* Remember if function is STABLE/IMMUTABLE */ - fcache->readonly_func = + func->readonly_func = (procedureStruct->provolatile != PROVOLATILE_VOLATILE); + /* Remember routine kind */ + func->prokind = procedureStruct->prokind; + /* * We need the actual argument types to pass to the parser. Also make * sure that parameter symbols are considered to have the function's * resolved input collation. */ - fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple, - finfo->fn_expr, - collation); + MemoryContextSwitchTo(hcontext); + func->pinfo = prepare_sql_fn_parse_info(procedureTuple, + fcinfo->flinfo->fn_expr, + PG_GET_COLLATION()); + MemoryContextSwitchTo(oldcontext); + + /* + * Now that we have the resolved argument types, collect their typlens for + * use in postquel_sub_params. + */ + func->argtyplen = (int16 *) + MemoryContextAlloc(hcontext, func->pinfo->nargs * sizeof(int16)); + for (int i = 0; i < func->pinfo->nargs; i++) + func->argtyplen[i] = get_typlen(func->pinfo->argtypes[i]); /* * And of course we need the function body text. */ tmp = SysCacheGetAttrNotNull(PROCOID, procedureTuple, Anum_pg_proc_prosrc); - fcache->src = TextDatumGetCString(tmp); + func->src = MemoryContextStrdup(hcontext, + TextDatumGetCString(tmp)); /* If we have prosqlbody, pay attention to that not prosrc. */ tmp = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_prosqlbody, &isNull); - - /* - * Parse and rewrite the queries in the function text. Use sublists to - * keep track of the original query boundaries. - * - * Note: since parsing and planning is done in fcontext, we will generate - * a lot of cruft that lives as long as the fcache does. This is annoying - * but we'll not worry about it until the module is rewritten to use - * plancache.c. - */ - queryTree_list = NIL; if (!isNull) { + /* Source queries are already parse-analyzed */ Node *n; - List *stored_query_list; n = stringToNode(TextDatumGetCString(tmp)); if (IsA(n, List)) - stored_query_list = linitial_node(List, castNode(List, n)); + source_list = linitial_node(List, castNode(List, n)); else - stored_query_list = list_make1(n); - - foreach(lc, stored_query_list) - { - Query *parsetree = lfirst_node(Query, lc); - List *queryTree_sublist; - - AcquireRewriteLocks(parsetree, true, false); - queryTree_sublist = pg_rewrite_query(parsetree); - queryTree_list = lappend(queryTree_list, queryTree_sublist); - } + source_list = list_make1(n); + func->raw_source = false; } else { - List *raw_parsetree_list; - - raw_parsetree_list = pg_parse_query(fcache->src); - - foreach(lc, raw_parsetree_list) - { - RawStmt *parsetree = lfirst_node(RawStmt, lc); - List *queryTree_sublist; - - queryTree_sublist = pg_analyze_and_rewrite_withcb(parsetree, - fcache->src, - (ParserSetupHook) sql_fn_parser_setup, - fcache->pinfo, - NULL); - queryTree_list = lappend(queryTree_list, queryTree_sublist); - } + /* Source queries are raw parsetrees */ + source_list = pg_parse_query(func->src); + func->raw_source = true; } /* - * Check that there are no statements we don't want to allow. + * Note: we must save the number of queries so that we'll still remember + * how many there are after we discard source_list. */ - check_sql_fn_statements(queryTree_list); + func->num_queries = list_length(source_list); /* - * Check that the function returns the type it claims to. Although in - * simple cases this was already done when the function was defined, we - * have to recheck because database objects used in the function's queries - * might have changed type. We'd have to recheck anyway if the function - * had any polymorphic arguments. Moreover, check_sql_fn_retval takes - * care of injecting any required column type coercions. (But we don't - * ask it to insert nulls for dropped columns; the junkfilter handles - * that.) - * - * Note: we set fcache->returnsTuple according to whether we are returning - * the whole tuple result or just a single column. In the latter case we - * clear returnsTuple because we need not act different from the scalar - * result case, even if it's a rowtype column. (However, we have to force - * lazy eval mode in that case; otherwise we'd need extra code to expand - * the rowtype column into multiple columns, since we have no way to - * notify the caller that it should do that.) + * Edge case: empty function body is OK only if it returns VOID. Normally + * we validate that the last statement returns the right thing in + * check_sql_stmt_retval, but we'll never reach that if there's no last + * statement. */ - fcache->returnsTuple = check_sql_fn_retval(queryTree_list, - rettype, - rettupdesc, - procedureStruct->prokind, - false, - &resulttlist); + if (func->num_queries == 0 && rettype != VOIDOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING."))); + + /* Save the source trees in pcontext for now. */ + MemoryContextSwitchTo(pcontext); + func->source_list = copyObject(source_list); + MemoryContextSwitchTo(oldcontext); /* - * Construct a JunkFilter we can use to coerce the returned rowtype to the - * desired form, unless the result type is VOID, in which case there's - * nothing to coerce to. (XXX Frequently, the JunkFilter isn't doing - * anything very interesting, but much of this module expects it to be - * there anyway.) + * We now have a fully valid hash entry, so reparent hcontext under + * CacheMemoryContext to make all the subsidiary data long-lived, and only + * then install the hcontext link so that sql_delete_callback will know to + * delete it. */ - if (rettype != VOIDOID) - { - TupleTableSlot *slot = MakeSingleTupleTableSlot(NULL, - &TTSOpsMinimalTuple); + MemoryContextSetParent(hcontext, CacheMemoryContext); + func->hcontext = hcontext; - /* - * If the result is composite, *and* we are returning the whole tuple - * result, we need to insert nulls for any dropped columns. In the - * single-column-result case, there might be dropped columns within - * the composite column value, but it's not our problem here. There - * should be no resjunk entries in resulttlist, so in the second case - * the JunkFilter is certainly a no-op. - */ - if (rettupdesc && fcache->returnsTuple) - fcache->junkFilter = ExecInitJunkFilterConversion(resulttlist, - rettupdesc, - slot); - else - fcache->junkFilter = ExecInitJunkFilter(resulttlist, slot); - } + error_context_stack = comperrcontext.previous; +} - if (fcache->returnsTuple) - { - /* Make sure output rowtype is properly blessed */ - BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor); - } - else if (fcache->returnsSet && type_is_rowtype(fcache->rettype)) +/* + * Deletion callback used by funccache.c. + * + * Free any free-able subsidiary data of cfunc, but not the + * struct CachedFunction itself. + */ +static void +sql_delete_callback(CachedFunction *cfunc) +{ + SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) cfunc; + ListCell *lc; + + /* Release the CachedPlanSources */ + foreach(lc, func->plansource_list) { - /* - * Returning rowtype as if it were scalar --- materialize won't work. - * Right now it's sufficient to override any caller preference for - * materialize mode, but to add more smarts in init_execution_state - * about this, we'd probably need a three-way flag instead of bool. - */ - lazyEvalOK = true; - } + CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc); - /* Finally, plan the queries */ - fcache->func_state = init_execution_state(queryTree_list, - fcache, - lazyEvalOK); + DropCachedPlan(plansource); + } + func->plansource_list = NIL; - /* Mark fcache with time of creation to show it's valid */ - fcache->lxid = MyProc->vxid.lxid; - fcache->subxid = GetCurrentSubTransactionId(); + /* + * If we have an hcontext, free it, thereby getting rid of all subsidiary + * data. (If we still have a pcontext, this gets rid of that too.) + */ + if (func->hcontext) + MemoryContextDelete(func->hcontext); + func->hcontext = NULL; +} - ReleaseSysCache(procedureTuple); +/* + * Post-rewrite callback used by plancache.c. + * + * This must match the processing that prepare_next_query() does between + * rewriting and calling CompleteCachedPlan(). + */ +static void +sql_postrewrite_callback(List *querytree_list, void *arg) +{ + /* + * Check that there are no statements we don't want to allow. (Presently, + * there's no real point in this because the result can't change from what + * we saw originally. But it's cheap and maybe someday it will matter.) + */ + check_sql_fn_statement(querytree_list); - MemoryContextSwitchTo(oldcontext); + /* + * If this is the last query, we must re-do what check_sql_stmt_retval did + * to its targetlist. Also check that returnsTuple didn't change (it + * probably cannot, but be cautious). + */ + if (arg != NULL) + { + SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) arg; + bool returnsTuple; + + returnsTuple = check_sql_stmt_retval(querytree_list, + func->rettype, + func->rettupdesc, + func->prokind, + false); + if (returnsTuple != func->returnsTuple) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cached plan must not change result type"))); + } } /* Start up execution of one execution_state node */ @@ -814,6 +1253,7 @@ static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache) { DestReceiver *dest; + MemoryContext oldcontext = CurrentMemoryContext; Assert(es->qd == NULL); @@ -821,8 +1261,65 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache) Assert(ActiveSnapshotSet()); /* - * If this query produces the function result, send its output to the - * tuplestore; else discard any output. + * In lazyEval mode for a SRF, we must run the sub-executor in a child of + * fcontext, so that it can survive across multiple calls to fmgr_sql. + * (XXX in the case of a long-lived FmgrInfo, this policy potentially + * causes memory leakage, but it's not very clear where we could keep + * stuff instead. Fortunately, there are few if any cases where + * set-returning functions are invoked via FmgrInfos that would outlive + * the calling query.) Otherwise, we're going to run it to completion + * before exiting fmgr_sql, so it can perfectly well run in the caller's + * context. + */ + if (es->lazyEval && fcache->func->returnsSet) + { + fcache->subcontext = AllocSetContextCreate(fcache->fcontext, + "SQL function execution", + ALLOCSET_DEFAULT_SIZES); + fcache->ownSubcontext = true; + } + else if (es->stmt->commandType == CMD_UTILITY) + { + /* + * The code path using a sub-executor is pretty good about cleaning up + * cruft, since the executor will make its own sub-context. We don't + * really need an additional layer of sub-context in that case. + * However, if this is a utility statement, it won't make its own + * sub-context, so it seems advisable to make one that we can free on + * completion. + */ + fcache->subcontext = AllocSetContextCreate(CurrentMemoryContext, + "SQL function execution", + ALLOCSET_DEFAULT_SIZES); + fcache->ownSubcontext = true; + } + else + { + fcache->subcontext = CurrentMemoryContext; + fcache->ownSubcontext = false; + } + + /* + * Build a tuplestore if needed, that is if it's a set-returning function + * and we're producing the function result without using lazyEval mode. + */ + if (es->setsResult) + { + Assert(fcache->tstore == NULL); + if (fcache->func->returnsSet && !es->lazyEval) + { + MemoryContextSwitchTo(fcache->tscontext); + fcache->tstore = tuplestore_begin_heap(fcache->randomAccess, + false, work_mem); + } + } + + /* Switch into the selected subcontext (might be a no-op) */ + MemoryContextSwitchTo(fcache->subcontext); + + /* + * If this query produces the function result, collect its output using + * our custom DestReceiver; else discard any output. */ if (es->setsResult) { @@ -832,15 +1329,17 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache) /* pass down the needed info to the dest receiver routines */ myState = (DR_sqlfunction *) dest; Assert(myState->pub.mydest == DestSQLFunction); - myState->tstore = fcache->tstore; - myState->cxt = CurrentMemoryContext; + myState->tstore = fcache->tstore; /* might be NULL */ myState->filter = fcache->junkFilter; + + /* Make very sure the junkfilter's result slot is empty */ + ExecClearTuple(fcache->junkFilter->jf_resultSlot); } else dest = None_Receiver; es->qd = CreateQueryDesc(es->stmt, - fcache->src, + fcache->func->src, GetActiveSnapshot(), InvalidSnapshot, dest, @@ -868,6 +1367,8 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache) } es->status = F_EXEC_RUN; + + MemoryContextSwitchTo(oldcontext); } /* Run one execution_state; either to completion or to first result row */ @@ -876,11 +1377,15 @@ static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) { bool result; + MemoryContext oldcontext; + + /* Run the sub-executor in subcontext */ + oldcontext = MemoryContextSwitchTo(fcache->subcontext); if (es->qd->operation == CMD_UTILITY) { ProcessUtility(es->qd->plannedstmt, - fcache->src, + fcache->func->src, true, /* protect function cache's parsetree */ PROCESS_UTILITY_QUERY, es->qd->params, @@ -894,7 +1399,7 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) /* Run regular commands to completion unless lazyEval */ uint64 count = (es->lazyEval) ? 1 : 0; - ExecutorRun(es->qd, ForwardScanDirection, count, !fcache->returnsSet || !es->lazyEval); + ExecutorRun(es->qd, ForwardScanDirection, count); /* * If we requested run to completion OR there was no tuple returned, @@ -903,13 +1408,20 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache) result = (count == 0 || es->qd->estate->es_processed == 0); } + MemoryContextSwitchTo(oldcontext); + return result; } /* Shut down execution of one execution_state node */ static void -postquel_end(execution_state *es) +postquel_end(execution_state *es, SQLFunctionCachePtr fcache) { + MemoryContext oldcontext; + + /* Run the sub-executor in subcontext */ + oldcontext = MemoryContextSwitchTo(fcache->subcontext); + /* mark status done to ensure we don't do ExecutorEnd twice */ es->status = F_EXEC_DONE; @@ -924,6 +1436,13 @@ postquel_end(execution_state *es) FreeQueryDesc(es->qd); es->qd = NULL; + + MemoryContextSwitchTo(oldcontext); + + /* Delete the subcontext, if it's actually a separate context */ + if (fcache->ownSubcontext) + MemoryContextDelete(fcache->subcontext); + fcache->subcontext = NULL; } /* Build ParamListInfo array representing current arguments */ @@ -936,12 +1455,18 @@ postquel_sub_params(SQLFunctionCachePtr fcache, if (nargs > 0) { ParamListInfo paramLI; - Oid *argtypes = fcache->pinfo->argtypes; + Oid *argtypes = fcache->func->pinfo->argtypes; + int16 *argtyplen = fcache->func->argtyplen; if (fcache->paramLI == NULL) { + /* First time through: build a persistent ParamListInfo struct */ + MemoryContext oldcontext; + + oldcontext = MemoryContextSwitchTo(fcache->fcontext); paramLI = makeParamList(nargs); fcache->paramLI = paramLI; + MemoryContextSwitchTo(oldcontext); } else { @@ -968,8 +1493,9 @@ postquel_sub_params(SQLFunctionCachePtr fcache, prm->isnull = fcinfo->args[i].isnull; prm->value = MakeExpandedObjectReadOnly(fcinfo->args[i].value, prm->isnull, - get_typlen(argtypes[i])); - prm->pflags = 0; + argtyplen[i]); + /* Allow the value to be substituted into custom plans */ + prm->pflags = PARAM_FLAG_CONST; prm->ptype = argtypes[i]; } } @@ -980,26 +1506,23 @@ postquel_sub_params(SQLFunctionCachePtr fcache, /* * Extract the SQL function's value from a single result row. This is used * both for scalar (non-set) functions and for each row of a lazy-eval set - * result. + * result. We expect the current memory context to be that of the caller + * of fmgr_sql. */ static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, - SQLFunctionCachePtr fcache, - MemoryContext resultcontext) + SQLFunctionCachePtr fcache) { Datum value; - MemoryContext oldcontext; /* * Set up to return the function value. For pass-by-reference datatypes, - * be sure to allocate the result in resultcontext, not the current memory - * context (which has query lifespan). We can't leave the data in the - * TupleTableSlot because we intend to clear the slot before returning. + * be sure to copy the result into the current context. We can't leave + * the data in the TupleTableSlot because we must clear the slot before + * returning. */ - oldcontext = MemoryContextSwitchTo(resultcontext); - - if (fcache->returnsTuple) + if (fcache->func->returnsTuple) { /* We must return the whole tuple as a Datum. */ fcinfo->isnull = false; @@ -1009,15 +1532,16 @@ postquel_get_single_result(TupleTableSlot *slot, { /* * Returning a scalar, which we have to extract from the first column - * of the SELECT result, and then copy into result context if needed. + * of the SELECT result, and then copy into current context if needed. */ value = slot_getattr(slot, 1, &(fcinfo->isnull)); if (!fcinfo->isnull) - value = datumCopy(value, fcache->typbyval, fcache->typlen); + value = datumCopy(value, fcache->func->typbyval, fcache->func->typlen); } - MemoryContextSwitchTo(oldcontext); + /* Clear the slot for next time */ + ExecClearTuple(slot); return value; } @@ -1030,24 +1554,13 @@ fmgr_sql(PG_FUNCTION_ARGS) { SQLFunctionCachePtr fcache; ErrorContextCallback sqlerrcontext; - MemoryContext oldcontext; + MemoryContext tscontext; bool randomAccess; bool lazyEvalOK; - bool is_first; bool pushed_snapshot; execution_state *es; TupleTableSlot *slot; Datum result; - List *eslist; - ListCell *eslc; - - /* - * Setup error traceback support for ereport() - */ - sqlerrcontext.callback = sql_exec_error_callback; - sqlerrcontext.arg = fcinfo->flinfo; - sqlerrcontext.previous = error_context_stack; - error_context_stack = &sqlerrcontext; /* Check call context */ if (fcinfo->flinfo->fn_retset) @@ -1068,80 +1581,46 @@ fmgr_sql(PG_FUNCTION_ARGS) errmsg("set-valued function called in context that cannot accept a set"))); randomAccess = rsi->allowedModes & SFRM_Materialize_Random; lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred); + /* tuplestore, if used, must have query lifespan */ + tscontext = rsi->econtext->ecxt_per_query_memory; } else { randomAccess = false; lazyEvalOK = true; + /* we won't need a tuplestore */ + tscontext = NULL; } /* - * Initialize fcache (build plans) if first time through; or re-initialize - * if the cache is stale. + * Initialize fcache if starting a fresh execution. */ - fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra; - - if (fcache != NULL) - { - if (fcache->lxid != MyProc->vxid.lxid || - !SubTransactionIsActive(fcache->subxid)) - { - /* It's stale; unlink and delete */ - fcinfo->flinfo->fn_extra = NULL; - MemoryContextDelete(fcache->fcontext); - fcache = NULL; - } - } + fcache = init_sql_fcache(fcinfo, lazyEvalOK); - if (fcache == NULL) - { - init_sql_fcache(fcinfo, PG_GET_COLLATION(), lazyEvalOK); - fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra; - } + /* Remember info that we might need later to construct tuplestore */ + fcache->tscontext = tscontext; + fcache->randomAccess = randomAccess; /* - * Switch to context in which the fcache lives. This ensures that our - * tuplestore etc will have sufficient lifetime. The sub-executor is - * responsible for deleting per-tuple information. (XXX in the case of a - * long-lived FmgrInfo, this policy represents more memory leakage, but - * it's not entirely clear where to keep stuff instead.) + * Now we can set up error traceback support for ereport() */ - oldcontext = MemoryContextSwitchTo(fcache->fcontext); + sqlerrcontext.callback = sql_exec_error_callback; + sqlerrcontext.arg = fcache; + sqlerrcontext.previous = error_context_stack; + error_context_stack = &sqlerrcontext; /* - * Find first unfinished query in function, and note whether it's the - * first query. + * Find first unfinished execution_state. If none, advance to the next + * query in function. */ - eslist = fcache->func_state; - es = NULL; - is_first = true; - foreach(eslc, eslist) + do { - es = (execution_state *) lfirst(eslc); - + es = fcache->eslist; while (es && es->status == F_EXEC_DONE) - { - is_first = false; es = es->next; - } - if (es) break; - } - - /* - * Convert params to appropriate format if starting a fresh execution. (If - * continuing execution, we can re-use prior params.) - */ - if (is_first && es && es->status == F_EXEC_START) - postquel_sub_params(fcache, fcinfo); - - /* - * Build tuplestore to hold results, if we don't have one already. Note - * it's in the query-lifespan context. - */ - if (!fcache->tstore) - fcache->tstore = tuplestore_begin_heap(randomAccess, false, work_mem); + } while (init_execution_state(fcache)); /* * Execute each command in the function one after another until we either @@ -1174,7 +1653,7 @@ fmgr_sql(PG_FUNCTION_ARGS) * visible. Take a new snapshot if we don't have one yet, * otherwise just bump the command ID in the existing snapshot. */ - if (!fcache->readonly_func) + if (!fcache->func->readonly_func) { CommandCounterIncrement(); if (!pushed_snapshot) @@ -1188,7 +1667,7 @@ fmgr_sql(PG_FUNCTION_ARGS) postquel_start(es, fcache); } - else if (!fcache->readonly_func && !pushed_snapshot) + else if (!fcache->func->readonly_func && !pushed_snapshot) { /* Re-establish active snapshot when re-entering function */ PushActiveSnapshot(es->qd->snapshot); @@ -1199,14 +1678,15 @@ fmgr_sql(PG_FUNCTION_ARGS) /* * If we ran the command to completion, we can shut it down now. Any - * row(s) we need to return are safely stashed in the tuplestore, and - * we want to be sure that, for example, AFTER triggers get fired - * before we return anything. Also, if the function doesn't return - * set, we can shut it down anyway because it must be a SELECT and we - * don't care about fetching any more result rows. + * row(s) we need to return are safely stashed in the result slot or + * tuplestore, and we want to be sure that, for example, AFTER + * triggers get fired before we return anything. Also, if the + * function doesn't return set, we can shut it down anyway because it + * must be a SELECT and we don't care about fetching any more result + * rows. */ - if (completed || !fcache->returnsSet) - postquel_end(es); + if (completed || !fcache->func->returnsSet) + postquel_end(es, fcache); /* * Break from loop if we didn't shut down (implying we got a @@ -1221,17 +1701,11 @@ fmgr_sql(PG_FUNCTION_ARGS) break; /* - * Advance to next execution_state, which might be in the next list. + * Advance to next execution_state, and perhaps next query. */ es = es->next; while (!es) { - eslc = lnext(eslist, eslc); - if (!eslc) - break; /* end of function */ - - es = (execution_state *) lfirst(eslc); - /* * Flush the current snapshot so that we will take a new one for * the new query list. This ensures that new snaps are taken at @@ -1243,13 +1717,19 @@ fmgr_sql(PG_FUNCTION_ARGS) PopActiveSnapshot(); pushed_snapshot = false; } + + if (!init_execution_state(fcache)) + break; /* end of function */ + + es = fcache->eslist; } } /* - * The tuplestore now contains whatever row(s) we are supposed to return. + * The result slot or tuplestore now contains whatever row(s) we are + * supposed to return. */ - if (fcache->returnsSet) + if (fcache->func->returnsSet) { ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo; @@ -1260,17 +1740,12 @@ fmgr_sql(PG_FUNCTION_ARGS) * row. */ Assert(es->lazyEval); - /* Re-use the junkfilter's output slot to fetch back the tuple */ + /* The junkfilter's result slot contains the query result tuple */ Assert(fcache->junkFilter); slot = fcache->junkFilter->jf_resultSlot; - if (!tuplestore_gettupleslot(fcache->tstore, true, false, slot)) - elog(ERROR, "failed to fetch lazy-eval tuple"); + Assert(!TTS_EMPTY(slot)); /* Extract the result as a datum, and copy out from the slot */ - result = postquel_get_single_result(slot, fcinfo, - fcache, oldcontext); - /* Clear the tuplestore, but keep it for next time */ - /* NB: this might delete the slot's content, but we don't care */ - tuplestore_clear(fcache->tstore); + result = postquel_get_single_result(slot, fcinfo, fcache); /* * Let caller know we're not finished. @@ -1292,12 +1767,8 @@ fmgr_sql(PG_FUNCTION_ARGS) else if (fcache->lazyEval) { /* - * We are done with a lazy evaluation. Clean up. - */ - tuplestore_clear(fcache->tstore); - - /* - * Let caller know we're finished. + * We are done with a lazy evaluation. Let caller know we're + * finished. */ rsi->isDone = ExprEndResult; @@ -1319,7 +1790,12 @@ fmgr_sql(PG_FUNCTION_ARGS) * We are done with a non-lazy evaluation. Return whatever is in * the tuplestore. (It is now caller's responsibility to free the * tuplestore when done.) + * + * Note an edge case: we could get here without having made a + * tuplestore if the function is declared to return SETOF VOID. + * ExecMakeTableFunctionResult will cope with null setResult. */ + Assert(fcache->tstore || fcache->func->rettype == VOIDOID); rsi->returnMode = SFRM_Materialize; rsi->setResult = fcache->tstore; fcache->tstore = NULL; @@ -1347,11 +1823,10 @@ fmgr_sql(PG_FUNCTION_ARGS) */ if (fcache->junkFilter) { - /* Re-use the junkfilter's output slot to fetch back the tuple */ + /* The junkfilter's result slot contains the query result tuple */ slot = fcache->junkFilter->jf_resultSlot; - if (tuplestore_gettupleslot(fcache->tstore, true, false, slot)) - result = postquel_get_single_result(slot, fcinfo, - fcache, oldcontext); + if (!TTS_EMPTY(slot)) + result = postquel_get_single_result(slot, fcinfo, fcache); else { fcinfo->isnull = true; @@ -1361,13 +1836,10 @@ fmgr_sql(PG_FUNCTION_ARGS) else { /* Should only get here for VOID functions and procedures */ - Assert(fcache->rettype == VOIDOID); + Assert(fcache->func->rettype == VOIDOID); fcinfo->isnull = true; result = (Datum) 0; } - - /* Clear the tuplestore, but keep it for next time */ - tuplestore_clear(fcache->tstore); } /* Pop snapshot if we have pushed one */ @@ -1376,154 +1848,154 @@ fmgr_sql(PG_FUNCTION_ARGS) /* * If we've gone through every command in the function, we are done. Reset - * the execution states to start over again on next call. + * state to start over again on next call. */ if (es == NULL) - { - foreach(eslc, fcache->func_state) - { - es = (execution_state *) lfirst(eslc); - while (es) - { - es->status = F_EXEC_START; - es = es->next; - } - } - } + fcache->eslist = NULL; error_context_stack = sqlerrcontext.previous; - MemoryContextSwitchTo(oldcontext); - return result; } /* - * error context callback to let us supply a call-stack traceback + * error context callback to let us supply a traceback during compile */ static void -sql_exec_error_callback(void *arg) +sql_compile_error_callback(void *arg) { - FmgrInfo *flinfo = (FmgrInfo *) arg; - SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) flinfo->fn_extra; + SQLFunctionHashEntry *func = (SQLFunctionHashEntry *) arg; int syntaxerrposition; /* - * We can do nothing useful if init_sql_fcache() didn't get as far as - * saving the function name + * We can do nothing useful if sql_compile_callback() didn't get as far as + * copying the function name */ - if (fcache == NULL || fcache->fname == NULL) + if (func->fname == NULL) return; /* * If there is a syntax error position, convert to internal syntax error */ syntaxerrposition = geterrposition(); - if (syntaxerrposition > 0 && fcache->src != NULL) + if (syntaxerrposition > 0 && func->src != NULL) { errposition(0); internalerrposition(syntaxerrposition); - internalerrquery(fcache->src); + internalerrquery(func->src); } /* - * Try to determine where in the function we failed. If there is a query - * with non-null QueryDesc, finger it. (We check this rather than looking - * for F_EXEC_RUN state, so that errors during ExecutorStart or - * ExecutorEnd are blamed on the appropriate query; see postquel_start and - * postquel_end.) + * sql_compile_callback() doesn't do any per-query processing, so just + * report the context as "during startup". */ - if (fcache->func_state) - { - execution_state *es; - int query_num; - ListCell *lc; + errcontext("SQL function \"%s\" during startup", func->fname); +} - es = NULL; - query_num = 1; - foreach(lc, fcache->func_state) - { - es = (execution_state *) lfirst(lc); - while (es) - { - if (es->qd) - { - errcontext("SQL function \"%s\" statement %d", - fcache->fname, query_num); - break; - } - es = es->next; - } - if (es) - break; - query_num++; - } - if (es == NULL) - { - /* - * couldn't identify a running query; might be function entry, - * function exit, or between queries. - */ - errcontext("SQL function \"%s\"", fcache->fname); - } - } - else +/* + * error context callback to let us supply a call-stack traceback at runtime + */ +static void +sql_exec_error_callback(void *arg) +{ + SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) arg; + int syntaxerrposition; + + /* + * If there is a syntax error position, convert to internal syntax error + */ + syntaxerrposition = geterrposition(); + if (syntaxerrposition > 0 && fcache->func->src != NULL) { - /* - * Assume we failed during init_sql_fcache(). (It's possible that the - * function actually has an empty body, but in that case we may as - * well report all errors as being "during startup".) - */ - errcontext("SQL function \"%s\" during startup", fcache->fname); + errposition(0); + internalerrposition(syntaxerrposition); + internalerrquery(fcache->func->src); } + + /* + * If we failed while executing an identifiable query within the function, + * report that. Otherwise say it was "during startup". + */ + if (fcache->error_query_index > 0) + errcontext("SQL function \"%s\" statement %d", + fcache->func->fname, fcache->error_query_index); + else + errcontext("SQL function \"%s\" during startup", fcache->func->fname); } /* - * callback function in case a function-returning-set needs to be shut down - * before it has been run to completion + * ExprContext callback function + * + * We register this in the active ExprContext while a set-returning SQL + * function is running, in case the function needs to be shut down before it + * has been run to completion. Note that this will not be called during an + * error abort, but we don't need it because transaction abort will take care + * of releasing executor resources. */ static void ShutdownSQLFunction(Datum arg) { SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) DatumGetPointer(arg); execution_state *es; - ListCell *lc; - foreach(lc, fcache->func_state) + es = fcache->eslist; + while (es) { - es = (execution_state *) lfirst(lc); - while (es) + /* Shut down anything still running */ + if (es->status == F_EXEC_RUN) { - /* Shut down anything still running */ - if (es->status == F_EXEC_RUN) - { - /* Re-establish active snapshot for any called functions */ - if (!fcache->readonly_func) - PushActiveSnapshot(es->qd->snapshot); - - postquel_end(es); + /* Re-establish active snapshot for any called functions */ + if (!fcache->func->readonly_func) + PushActiveSnapshot(es->qd->snapshot); - if (!fcache->readonly_func) - PopActiveSnapshot(); - } + postquel_end(es, fcache); - /* Reset states to START in case we're called again */ - es->status = F_EXEC_START; - es = es->next; + if (!fcache->func->readonly_func) + PopActiveSnapshot(); } + es = es->next; } + fcache->eslist = NULL; /* Release tuplestore if we have one */ if (fcache->tstore) tuplestore_end(fcache->tstore); fcache->tstore = NULL; + /* Release CachedPlan if we have one */ + if (fcache->cplan) + ReleaseCachedPlan(fcache->cplan, fcache->cowner); + fcache->cplan = NULL; + /* execUtils will deregister the callback... */ fcache->shutdown_reg = false; } +/* + * MemoryContext callback function + * + * We register this in the memory context that contains a SQLFunctionCache + * struct. When the memory context is reset or deleted, we release the + * reference count (if any) that the cache holds on the long-lived hash entry. + * Note that this will happen even during error aborts. + */ +static void +RemoveSQLFunctionCache(void *arg) +{ + SQLFunctionCache *fcache = (SQLFunctionCache *) arg; + + /* Release reference count on SQLFunctionHashEntry */ + if (fcache->func != NULL) + { + Assert(fcache->func->cfunc.use_count > 0); + fcache->func->cfunc.use_count--; + /* This should be unnecessary, but let's just be sure: */ + fcache->func = NULL; + } +} + /* * check_sql_fn_statements * @@ -1539,29 +2011,39 @@ check_sql_fn_statements(List *queryTreeLists) foreach(lc, queryTreeLists) { List *sublist = lfirst_node(List, lc); - ListCell *lc2; - foreach(lc2, sublist) - { - Query *query = lfirst_node(Query, lc2); + check_sql_fn_statement(sublist); + } +} - /* - * Disallow calling procedures with output arguments. The current - * implementation would just throw the output values away, unless - * the statement is the last one. Per SQL standard, we should - * assign the output values by name. By disallowing this here, we - * preserve an opportunity for future improvement. - */ - if (query->commandType == CMD_UTILITY && - IsA(query->utilityStmt, CallStmt)) - { - CallStmt *stmt = (CallStmt *) query->utilityStmt; +/* + * As above, for a single sublist of Queries. + */ +static void +check_sql_fn_statement(List *queryTreeList) +{ + ListCell *lc; - if (stmt->outargs != NIL) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("calling procedures with output arguments is not supported in SQL functions"))); - } + foreach(lc, queryTreeList) + { + Query *query = lfirst_node(Query, lc); + + /* + * Disallow calling procedures with output arguments. The current + * implementation would just throw the output values away, unless the + * statement is the last one. Per SQL standard, we should assign the + * output values by name. By disallowing this here, we preserve an + * opportunity for future improvement. + */ + if (query->commandType == CMD_UTILITY && + IsA(query->utilityStmt, CallStmt)) + { + CallStmt *stmt = (CallStmt *) query->utilityStmt; + + if (stmt->outargs != NIL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("calling procedures with output arguments is not supported in SQL functions"))); } } } @@ -1600,17 +2082,45 @@ check_sql_fn_statements(List *queryTreeLists) * In addition to coercing individual output columns, we can modify the * output to include dummy NULL columns for any dropped columns appearing * in rettupdesc. This is done only if the caller asks for it. - * - * If resultTargetList isn't NULL, then *resultTargetList is set to the - * targetlist that defines the final statement's result. Exception: if the - * function is defined to return VOID then *resultTargetList is set to NIL. */ bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, - bool insertDroppedCols, - List **resultTargetList) + bool insertDroppedCols) +{ + List *queryTreeList; + + /* + * We consider only the last sublist of Query nodes, so that only the last + * original statement is a candidate to produce the result. This is a + * change from pre-v18 versions, which would back up to the last statement + * that includes a canSetTag query, thus ignoring any ending statement(s) + * that rewrite to DO INSTEAD NOTHING. That behavior was undocumented and + * there seems no good reason for it, except that it was an artifact of + * the original coding. + * + * If the function body is completely empty, handle that the same as if + * the last query had rewritten to nothing. + */ + if (queryTreeLists != NIL) + queryTreeList = llast_node(List, queryTreeLists); + else + queryTreeList = NIL; + + return check_sql_stmt_retval(queryTreeList, + rettype, rettupdesc, + prokind, insertDroppedCols); +} + +/* + * As for check_sql_fn_retval, but we are given just the last query's + * rewritten-queries list. + */ +static bool +check_sql_stmt_retval(List *queryTreeList, + Oid rettype, TupleDesc rettupdesc, + char prokind, bool insertDroppedCols) { bool is_tuple_result = false; Query *parse; @@ -1623,9 +2133,6 @@ check_sql_fn_retval(List *queryTreeLists, bool upper_tlist_nontrivial = false; ListCell *lc; - if (resultTargetList) - *resultTargetList = NIL; /* initialize in case of VOID result */ - /* * If it's declared to return VOID, we don't care what's in the function. * (This takes care of procedures with no output parameters, as well.) @@ -1634,30 +2141,20 @@ check_sql_fn_retval(List *queryTreeLists, return false; /* - * Find the last canSetTag query in the function body (which is presented - * to us as a list of sublists of Query nodes). This isn't necessarily - * the last parsetree, because rule rewriting can insert queries after - * what the user wrote. Note that it might not even be in the last - * sublist, for example if the last query rewrites to DO INSTEAD NOTHING. - * (It might not be unreasonable to throw an error in such a case, but - * this is the historical behavior and it doesn't seem worth changing.) + * Find the last canSetTag query in the list of Query nodes. This isn't + * necessarily the last parsetree, because rule rewriting can insert + * queries after what the user wrote. */ parse = NULL; parse_cell = NULL; - foreach(lc, queryTreeLists) + foreach(lc, queryTreeList) { - List *sublist = lfirst_node(List, lc); - ListCell *lc2; + Query *q = lfirst_node(Query, lc); - foreach(lc2, sublist) + if (q->canSetTag) { - Query *q = lfirst_node(Query, lc2); - - if (q->canSetTag) - { - parse = q; - parse_cell = lc2; - } + parse = q; + parse_cell = lc; } } @@ -1692,7 +2189,7 @@ check_sql_fn_retval(List *queryTreeLists, } else { - /* Empty function body, or last statement is a utility command */ + /* Last statement is a utility command, or it rewrote to nothing */ ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", @@ -1810,12 +2307,7 @@ check_sql_fn_retval(List *queryTreeLists, * further checking. Assume we're returning the whole tuple. */ if (rettupdesc == NULL) - { - /* Return tlist if requested */ - if (resultTargetList) - *resultTargetList = tlist; return true; - } /* * Verify that the targetlist matches the return tuple type. We scan @@ -1886,7 +2378,7 @@ check_sql_fn_retval(List *queryTreeLists, /* remaining columns in rettupdesc had better all be dropped */ for (colindex++; colindex <= tupnatts; colindex++) { - if (!TupleDescAttr(rettupdesc, colindex - 1)->attisdropped) + if (!TupleDescCompactAttr(rettupdesc, colindex - 1)->attisdropped) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", @@ -1972,14 +2464,16 @@ check_sql_fn_retval(List *queryTreeLists, rtr->rtindex = 1; newquery->jointree = makeFromExpr(list_make1(rtr), NULL); + /* + * Make sure the new query is marked as having row security if the + * original one does. + */ + newquery->hasRowSecurity = parse->hasRowSecurity; + /* Replace original query in the correct element of the query list */ lfirst(parse_cell) = newquery; } - /* Return tlist (possibly modified) if requested */ - if (resultTargetList) - *resultTargetList = upper_tlist; - return is_tuple_result; } @@ -2055,6 +2549,37 @@ coerce_fn_result_column(TargetEntry *src_tle, return true; } +/* + * Extract the targetlist of the last canSetTag query in the given list + * of parsed-and-rewritten Queries. Returns NIL if there is none. + */ +static List * +get_sql_fn_result_tlist(List *queryTreeList) +{ + Query *parse = NULL; + ListCell *lc; + + foreach(lc, queryTreeList) + { + Query *q = lfirst_node(Query, lc); + + if (q->canSetTag) + parse = q; + } + if (parse && + parse->commandType == CMD_SELECT) + return parse->targetList; + else if (parse && + (parse->commandType == CMD_INSERT || + parse->commandType == CMD_UPDATE || + parse->commandType == CMD_DELETE || + parse->commandType == CMD_MERGE) && + parse->returningList) + return parse->returningList; + else + return NIL; +} + /* * CreateSQLFunctionDestReceiver -- create a suitable DestReceiver object @@ -2092,11 +2617,32 @@ sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self) { DR_sqlfunction *myState = (DR_sqlfunction *) self; - /* Filter tuple as needed */ - slot = ExecFilterJunk(myState->filter, slot); + if (myState->tstore) + { + /* We are collecting all of a set result into the tuplestore */ + + /* Filter tuple as needed */ + slot = ExecFilterJunk(myState->filter, slot); - /* Store the filtered tuple into the tuplestore */ - tuplestore_puttupleslot(myState->tstore, slot); + /* Store the filtered tuple into the tuplestore */ + tuplestore_puttupleslot(myState->tstore, slot); + } + else + { + /* + * We only want the first tuple, which we'll save in the junkfilter's + * result slot. Ignore any additional tuples passed. + */ + if (TTS_EMPTY(myState->filter->jf_resultSlot)) + { + /* Filter tuple as needed */ + slot = ExecFilterJunk(myState->filter, slot); + Assert(slot == myState->filter->jf_resultSlot); + + /* Materialize the slot so it preserves pass-by-ref values */ + ExecMaterializeSlot(slot); + } + } return true; } diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c index 268ae8a945f2a..56e635f47000d 100644 --- a/src/backend/executor/instrument.c +++ b/src/backend/executor/instrument.c @@ -4,7 +4,7 @@ * functions for instrumentation of plan execution * * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/executor/instrument.c @@ -280,6 +280,7 @@ WalUsageAdd(WalUsage *dst, WalUsage *add) dst->wal_bytes += add->wal_bytes; dst->wal_records += add->wal_records; dst->wal_fpi += add->wal_fpi; + dst->wal_buffers_full += add->wal_buffers_full; } void @@ -288,4 +289,5 @@ WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub) dst->wal_bytes += add->wal_bytes - sub->wal_bytes; dst->wal_records += add->wal_records - sub->wal_records; dst->wal_fpi += add->wal_fpi - sub->wal_fpi; + dst->wal_buffers_full += add->wal_buffers_full - sub->wal_buffers_full; } diff --git a/src/backend/executor/meson.build b/src/backend/executor/meson.build index b511a429adf14..2cea41f877113 100644 --- a/src/backend/executor/meson.build +++ b/src/backend/executor/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'execAmi.c', diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 53ead77ece8cb..377e016d73225 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -237,7 +237,7 @@ * to filter expressions having to be evaluated early, and allows to JIT * the entire expression into one native function. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -269,9 +269,11 @@ #include "utils/datum.h" #include "utils/dynahash.h" #include "utils/expandeddatum.h" +#include "utils/injection_point.h" #include "utils/logtape.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/memutils_memorychunk.h" #include "utils/syscache.h" #include "utils/tuplesort.h" @@ -314,10 +316,9 @@ #define HASHAGG_HLL_BIT_WIDTH 5 /* - * Estimate chunk overhead as a constant 16 bytes. XXX: should this be - * improved? + * Assume the palloc overhead always uses sizeof(MemoryChunk) bytes. */ -#define CHUNKHDRSZ 16 +#define CHUNKHDRSZ sizeof(MemoryChunk) /* * Represents partitioned spill data for a single hashtable. Contains the @@ -405,6 +406,7 @@ static void build_hash_tables(AggState *aggstate); static void build_hash_table(AggState *aggstate, int setno, long nbuckets); static void hashagg_recompile_expressions(AggState *aggstate, bool minslot, bool nullcheck); +static void hash_create_memory(AggState *aggstate); static long hash_choose_num_buckets(double hashentrysize, long ngroups, Size memory); static int hash_choose_num_partitions(double input_groups, @@ -815,11 +817,8 @@ advance_transition_function(AggState *aggstate, static void advance_aggregates(AggState *aggstate) { - bool dummynull; - - ExecEvalExprSwitchContext(aggstate->phase->evaltrans, - aggstate->tmpcontext, - &dummynull); + ExecEvalExprNoReturnSwitchContext(aggstate->phase->evaltrans, + aggstate->tmpcontext); } /* @@ -1088,7 +1087,7 @@ finalize_aggregate(AggState *aggstate, InitFunctionCallInfoData(*fcinfo, &peragg->finalfn, numFinalArgs, pertrans->aggCollation, - (void *) aggstate, NULL); + (Node *) aggstate, NULL); /* Fill in the transition state value */ fcinfo->args[0].value = @@ -1440,12 +1439,11 @@ find_cols_walker(Node *node, FindColsContext *context) { Assert(!context->is_aggref); context->is_aggref = true; - expression_tree_walker(node, find_cols_walker, (void *) context); + expression_tree_walker(node, find_cols_walker, context); context->is_aggref = false; return false; } - return expression_tree_walker(node, find_cols_walker, - (void *) context); + return expression_tree_walker(node, find_cols_walker, context); } /* @@ -1454,7 +1452,7 @@ find_cols_walker(Node *node, FindColsContext *context) * To implement hashed aggregation, we need a hashtable that stores a * representative tuple and an array of AggStatePerGroup structs for each * distinct set of GROUP BY column values. We compute the hash key from the - * GROUP BY columns. The per-group data is allocated in lookup_hash_entry(), + * GROUP BY columns. The per-group data is allocated in initialize_hash_entry(), * for each entry. * * We have a separate hashtable and associated perhash data structure for each @@ -1490,6 +1488,14 @@ build_hash_tables(AggState *aggstate) perhash->aggnode->numGroups, memory); +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-oversize-table")) + { + nbuckets = memory / TupleHashEntrySize(); + INJECTION_POINT_CACHED("hash-aggregate-oversize-table", NULL); + } +#endif + build_hash_table(aggstate, setno, nbuckets); } @@ -1504,7 +1510,7 @@ build_hash_table(AggState *aggstate, int setno, long nbuckets) { AggStatePerHash perhash = &aggstate->perhash[setno]; MemoryContext metacxt = aggstate->hash_metacxt; - MemoryContext hashcxt = aggstate->hashcontext->ecxt_per_tuple_memory; + MemoryContext tablecxt = aggstate->hash_tablecxt; MemoryContext tmpcxt = aggstate->tmpcontext->ecxt_per_tuple_memory; Size additionalsize; @@ -1519,19 +1525,20 @@ build_hash_table(AggState *aggstate, int setno, long nbuckets) */ additionalsize = aggstate->numtrans * sizeof(AggStatePerGroupData); - perhash->hashtable = BuildTupleHashTableExt(&aggstate->ss.ps, - perhash->hashslot->tts_tupleDescriptor, - perhash->numCols, - perhash->hashGrpColIdxHash, - perhash->eqfuncoids, - perhash->hashfunctions, - perhash->aggnode->grpCollations, - nbuckets, - additionalsize, - metacxt, - hashcxt, - tmpcxt, - DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit)); + perhash->hashtable = BuildTupleHashTable(&aggstate->ss.ps, + perhash->hashslot->tts_tupleDescriptor, + perhash->hashslot->tts_ops, + perhash->numCols, + perhash->hashGrpColIdxHash, + perhash->eqfuncoids, + perhash->hashfunctions, + perhash->aggnode->grpCollations, + nbuckets, + additionalsize, + metacxt, + tablecxt, + tmpcxt, + DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit)); } /* @@ -1542,7 +1549,7 @@ build_hash_table(AggState *aggstate, int setno, long nbuckets) * at all. Only columns of the first two types need to be stored in the * hashtable, and getting rid of the others can make the table entries * significantly smaller. The hashtable only contains the relevant columns, - * and is packed/unpacked in lookup_hash_entry() / agg_retrieve_hash_table() + * and is packed/unpacked in lookup_hash_entries() / agg_retrieve_hash_table() * into the format of the normal input descriptor. * * Additional columns, in addition to the columns grouped by, come from two @@ -1700,20 +1707,24 @@ hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace) tupleWidth); Size pergroupSize = numTrans * sizeof(AggStatePerGroupData); - tupleChunkSize = CHUNKHDRSZ + tupleSize; - - if (pergroupSize > 0) - pergroupChunkSize = CHUNKHDRSZ + pergroupSize; - else - pergroupChunkSize = 0; + /* + * Entries use the Bump allocator, so the chunk sizes are the same as the + * requested sizes. + */ + tupleChunkSize = MAXALIGN(tupleSize); + pergroupChunkSize = pergroupSize; + /* + * Transition values use AllocSet, which has a chunk header and also uses + * power-of-two allocations. + */ if (transitionSpace > 0) - transitionChunkSize = CHUNKHDRSZ + transitionSpace; + transitionChunkSize = CHUNKHDRSZ + pg_nextpower2_size_t(transitionSpace); else transitionChunkSize = 0; return - sizeof(TupleHashEntryData) + + TupleHashEntrySize() + tupleChunkSize + pergroupChunkSize + transitionChunkSize; @@ -1858,19 +1869,37 @@ hash_agg_check_limits(AggState *aggstate) uint64 ngroups = aggstate->hash_ngroups_current; Size meta_mem = MemoryContextMemAllocated(aggstate->hash_metacxt, true); - Size hashkey_mem = MemoryContextMemAllocated(aggstate->hashcontext->ecxt_per_tuple_memory, - true); + Size entry_mem = MemoryContextMemAllocated(aggstate->hash_tablecxt, + true); + Size tval_mem = MemoryContextMemAllocated(aggstate->hashcontext->ecxt_per_tuple_memory, + true); + Size total_mem = meta_mem + entry_mem + tval_mem; + bool do_spill = false; + +#ifdef USE_INJECTION_POINTS + if (ngroups >= 1000) + { + if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-spill-1000")) + { + do_spill = true; + INJECTION_POINT_CACHED("hash-aggregate-spill-1000", NULL); + } + } +#endif /* * Don't spill unless there's at least one group in the hash table so we * can be sure to make progress even in edge cases. */ if (aggstate->hash_ngroups_current > 0 && - (meta_mem + hashkey_mem > aggstate->hash_mem_limit || + (total_mem > aggstate->hash_mem_limit || ngroups > aggstate->hash_ngroups_limit)) { - hash_agg_enter_spill_mode(aggstate); + do_spill = true; } + + if (do_spill) + hash_agg_enter_spill_mode(aggstate); } /* @@ -1881,6 +1910,7 @@ hash_agg_check_limits(AggState *aggstate) static void hash_agg_enter_spill_mode(AggState *aggstate) { + INJECTION_POINT("hash-aggregate-enter-spill-mode", NULL); aggstate->hash_spill_mode = true; hashagg_recompile_expressions(aggstate, aggstate->table_filled, true); @@ -1917,6 +1947,7 @@ static void hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) { Size meta_mem; + Size entry_mem; Size hashkey_mem; Size buffer_mem; Size total_mem; @@ -1928,7 +1959,10 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) /* memory for the hash table itself */ meta_mem = MemoryContextMemAllocated(aggstate->hash_metacxt, true); - /* memory for the group keys and transition states */ + /* memory for hash entries */ + entry_mem = MemoryContextMemAllocated(aggstate->hash_tablecxt, true); + + /* memory for byref transition states */ hashkey_mem = MemoryContextMemAllocated(aggstate->hashcontext->ecxt_per_tuple_memory, true); /* memory for read/write tape buffers, if spilled */ @@ -1937,7 +1971,7 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) buffer_mem += HASHAGG_READ_BUFFER_SIZE; /* update peak mem */ - total_mem = meta_mem + hashkey_mem + buffer_mem; + total_mem = meta_mem + entry_mem + hashkey_mem + buffer_mem; if (total_mem > aggstate->hash_mem_peak) aggstate->hash_mem_peak = total_mem; @@ -1954,11 +1988,69 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions) if (aggstate->hash_ngroups_current > 0) { aggstate->hashentrysize = - sizeof(TupleHashEntryData) + + TupleHashEntrySize() + (hashkey_mem / (double) aggstate->hash_ngroups_current); } } +/* + * Create memory contexts used for hash aggregation. + */ +static void +hash_create_memory(AggState *aggstate) +{ + Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE; + + /* + * The hashcontext's per-tuple memory will be used for byref transition + * values and returned by AggCheckCallContext(). + */ + aggstate->hashcontext = CreateWorkExprContext(aggstate->ss.ps.state); + + /* + * The meta context will be used for the bucket array of + * TupleHashEntryData (or arrays, in the case of grouping sets). As the + * hash table grows, the bucket array will double in size and the old one + * will be freed, so an AllocSet is appropriate. For large bucket arrays, + * the large allocation path will be used, so it's not worth worrying + * about wasting space due to power-of-two allocations. + */ + aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt, + "HashAgg meta context", + ALLOCSET_DEFAULT_SIZES); + + /* + * The hash entries themselves, which include the grouping key + * (firstTuple) and pergroup data, are stored in the table context. The + * bump allocator can be used because the entries are not freed until the + * entire hash table is reset. The bump allocator is faster for + * allocations and avoids wasting space on the chunk header or + * power-of-two allocations. + * + * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem, + * to avoid large jumps in memory usage. + */ + + /* + * Like CreateWorkExprContext(), use smaller sizings for smaller work_mem, + * to avoid large jumps in memory usage. + */ + maxBlockSize = pg_prevpower2_size_t(work_mem * (Size) 1024 / 16); + + /* But no bigger than ALLOCSET_DEFAULT_MAXSIZE */ + maxBlockSize = Min(maxBlockSize, ALLOCSET_DEFAULT_MAXSIZE); + + /* and no smaller than ALLOCSET_DEFAULT_INITSIZE */ + maxBlockSize = Max(maxBlockSize, ALLOCSET_DEFAULT_INITSIZE); + + aggstate->hash_tablecxt = BumpContextCreate(aggstate->ss.ps.state->es_query_cxt, + "HashAgg table context", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + maxBlockSize); + +} + /* * Choose a reasonable number of buckets for the initial hash table size. */ @@ -2055,11 +2147,7 @@ initialize_hash_entry(AggState *aggstate, TupleHashTable hashtable, if (aggstate->numtrans == 0) return; - pergroup = (AggStatePerGroup) - MemoryContextAlloc(hashtable->tablecxt, - sizeof(AggStatePerGroupData) * aggstate->numtrans); - - entry->additional = pergroup; + pergroup = (AggStatePerGroup) TupleHashEntryGetAdditional(hashtable, entry); /* * Initialize aggregates for new tuple group, lookup_hash_entries() @@ -2077,8 +2165,6 @@ initialize_hash_entry(AggState *aggstate, TupleHashTable hashtable, /* * Look up hash entries for the current tuple in all hashed grouping sets. * - * Be aware that lookup_hash_entry can reset the tmpcontext. - * * Some entries may be left NULL if we are in "spill mode". The same tuple * will belong to different groups for each grouping set, so may match a group * already in memory for one set and match a group not in memory for another @@ -2123,7 +2209,7 @@ lookup_hash_entries(AggState *aggstate) { if (isnew) initialize_hash_entry(aggstate, hashtable, entry); - pergroup[setno] = entry->additional; + pergroup[setno] = TupleHashEntryGetAdditional(hashtable, entry); } else { @@ -2622,6 +2708,7 @@ agg_refill_hash_table(AggState *aggstate) /* free memory and reset hash tables */ ReScanExprContext(aggstate->hashcontext); + MemoryContextReset(aggstate->hash_tablecxt); for (int setno = 0; setno < aggstate->num_hashes; setno++) ResetTupleHashTable(aggstate->perhash[setno].hashtable); @@ -2652,10 +2739,12 @@ agg_refill_hash_table(AggState *aggstate) */ hashagg_recompile_expressions(aggstate, true, true); + INJECTION_POINT("hash-aggregate-process-batch", NULL); for (;;) { TupleTableSlot *spillslot = aggstate->hash_spill_rslot; TupleTableSlot *hashslot = perhash->hashslot; + TupleHashTable hashtable = perhash->hashtable; TupleHashEntry entry; MinimalTuple tuple; uint32 hash; @@ -2674,14 +2763,14 @@ agg_refill_hash_table(AggState *aggstate) prepare_hash_slot(perhash, aggstate->tmpcontext->ecxt_outertuple, hashslot); - entry = LookupTupleHashEntryHash(perhash->hashtable, hashslot, + entry = LookupTupleHashEntryHash(hashtable, hashslot, p_isnew, hash); if (entry != NULL) { if (isnew) - initialize_hash_entry(aggstate, perhash->hashtable, entry); - aggstate->hash_pergroup[batch->setno] = entry->additional; + initialize_hash_entry(aggstate, hashtable, entry); + aggstate->hash_pergroup[batch->setno] = TupleHashEntryGetAdditional(hashtable, entry); advance_aggregates(aggstate); } else @@ -2773,7 +2862,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) ExprContext *econtext; AggStatePerAgg peragg; AggStatePerGroup pergroup; - TupleHashEntryData *entry; + TupleHashEntry entry; TupleTableSlot *firstSlot; TupleTableSlot *result; AggStatePerHash perhash; @@ -2800,6 +2889,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) for (;;) { TupleTableSlot *hashslot = perhash->hashslot; + TupleHashTable hashtable = perhash->hashtable; int i; CHECK_FOR_INTERRUPTS(); @@ -2807,7 +2897,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) /* * Find the next entry in the hash table */ - entry = ScanTupleHashTable(perhash->hashtable, &perhash->hashiter); + entry = ScanTupleHashTable(hashtable, &perhash->hashiter); if (entry == NULL) { int nextset = aggstate->current_set + 1; @@ -2822,7 +2912,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) perhash = &aggstate->perhash[aggstate->current_set]; - ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter); + ResetTupleHashIterator(hashtable, &perhash->hashiter); continue; } @@ -2845,7 +2935,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) * Transform representative tuple back into one with the right * columns. */ - ExecStoreMinimalTuple(entry->firstTuple, hashslot, false); + ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), hashslot, false); slot_getallattrs(hashslot); ExecClearTuple(firstSlot); @@ -2861,7 +2951,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate) } ExecStoreVirtualTuple(firstSlot); - pergroup = (AggStatePerGroup) entry->additional; + pergroup = (AggStatePerGroup) TupleHashEntryGetAdditional(hashtable, entry); /* * Use the representative input tuple for any references to @@ -2900,6 +2990,15 @@ hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits, npartitions = hash_choose_num_partitions(input_groups, hashentrysize, used_bits, &partition_bits); +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("hash-aggregate-single-partition")) + { + npartitions = 1; + partition_bits = 0; + INJECTION_POINT_CACHED("hash-aggregate-single-partition", NULL); + } +#endif + spill->partitions = palloc0(sizeof(LogicalTape *) * npartitions); spill->ntuples = palloc0(sizeof(int64) * npartitions); spill->hll_card = palloc0(sizeof(hyperLogLogState) * npartitions); @@ -2908,7 +3007,10 @@ hashagg_spill_init(HashAggSpill *spill, LogicalTapeSet *tapeset, int used_bits, spill->partitions[i] = LogicalTapeCreate(tapeset); spill->shift = 32 - used_bits - partition_bits; - spill->mask = (npartitions - 1) << spill->shift; + if (spill->shift < 32) + spill->mask = (npartitions - 1) << spill->shift; + else + spill->mask = 0; spill->npartitions = npartitions; for (int i = 0; i < npartitions; i++) @@ -2957,7 +3059,11 @@ hashagg_spill_tuple(AggState *aggstate, HashAggSpill *spill, tuple = ExecFetchSlotMinimalTuple(spillslot, &shouldFree); - partition = (hash & spill->mask) >> spill->shift; + if (spill->shift < 32) + partition = (hash & spill->mask) >> spill->shift; + else + partition = 0; + spill->ntuples[partition]++; /* @@ -3289,7 +3395,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) } if (use_hashing) - aggstate->hashcontext = CreateWorkExprContext(estate); + hash_create_memory(aggstate); ExecAssignExprContext(estate, &aggstate->ss.ps); @@ -3379,8 +3485,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) max_aggno = Max(max_aggno, aggref->aggno); max_transno = Max(max_transno, aggref->aggtransno); } - numaggs = max_aggno + 1; - numtrans = max_transno + 1; + aggstate->numaggs = numaggs = max_aggno + 1; + aggstate->numtrans = numtrans = max_transno + 1; /* * For each phase, prepare grouping set data and fmgr lookup data for @@ -3584,9 +3690,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) Plan *outerplan = outerPlan(node); uint64 totalGroups = 0; - aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt, - "HashAgg meta context", - ALLOCSET_DEFAULT_SIZES); aggstate->hash_spill_rslot = ExecInitExtraTupleSlot(estate, scanDesc, &TTSOpsMinimalTuple); aggstate->hash_spill_wslot = ExecInitExtraTupleSlot(estate, scanDesc, @@ -3943,13 +4046,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) ReleaseSysCache(aggTuple); } - /* - * Update aggstate->numaggs to be the number of unique aggregates found. - * Also set numstates to the number of unique transition states found. - */ - aggstate->numaggs = numaggs; - aggstate->numtrans = numtrans; - /* * Last, check whether any more aggregates got added onto the node while * we processed the expressions for the aggregate arguments (including not @@ -4101,7 +4197,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, &pertrans->transfn, numTransArgs, pertrans->aggCollation, - (void *) aggstate, NULL); + (Node *) aggstate, NULL); /* get info about the state value's datatype */ get_typlenbyval(aggtranstype, @@ -4121,7 +4217,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, &pertrans->serialfn, 1, InvalidOid, - (void *) aggstate, NULL); + (Node *) aggstate, NULL); } if (OidIsValid(aggdeserialfn)) @@ -4137,7 +4233,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, &pertrans->deserialfn, 2, InvalidOid, - (void *) aggstate, NULL); + (Node *) aggstate, NULL); } /* @@ -4338,6 +4434,12 @@ ExecEndAgg(AggState *node) MemoryContextDelete(node->hash_metacxt); node->hash_metacxt = NULL; } + if (node->hash_tablecxt != NULL) + { + MemoryContextDelete(node->hash_tablecxt); + node->hash_tablecxt = NULL; + } + for (transno = 0; transno < node->numtrans; transno++) { @@ -4454,6 +4556,7 @@ ExecReScanAgg(AggState *node) node->hash_ngroups_current = 0; ReScanExprContext(node->hashcontext); + MemoryContextReset(node->hash_tablecxt); /* Rebuild an empty hash table */ build_hash_tables(node); node->table_filled = false; diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index ca0f54d676f4a..a11b36c717662 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -3,7 +3,7 @@ * nodeAppend.c * routines to handle append nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -110,6 +110,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) { AppendState *appendstate = makeNode(AppendState); PlanState **appendplanstates; + const TupleTableSlotOps *appendops; Bitmapset *validsubplans; Bitmapset *asyncplans; int nplans; @@ -134,7 +135,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendstate->as_begun = false; /* If run-time partition pruning is enabled, then set that up now */ - if (node->part_prune_info != NULL) + if (node->part_prune_index >= 0) { PartitionPruneState *prunestate; @@ -143,10 +144,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags) * subplans to initialize (validsubplans) by taking into account the * result of performing initial pruning if any. */ - prunestate = ExecInitPartitionPruning(&appendstate->ps, - list_length(node->appendplans), - node->part_prune_info, - &validsubplans); + prunestate = ExecInitPartitionExecPruning(&appendstate->ps, + list_length(node->appendplans), + node->part_prune_index, + node->apprelids, + &validsubplans); appendstate->as_prune_state = prunestate; nplans = bms_num_members(validsubplans); @@ -176,15 +178,6 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendstate->as_prune_state = NULL; } - /* - * Initialize result tuple type and slot. - */ - ExecInitResultTupleSlotTL(&appendstate->ps, &TTSOpsVirtual); - - /* node returns slots from each of its subnodes, therefore not fixed */ - appendstate->ps.resultopsset = true; - appendstate->ps.resultopsfixed = false; - appendplanstates = (PlanState **) palloc(nplans * sizeof(PlanState *)); @@ -227,6 +220,28 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendstate->appendplans = appendplanstates; appendstate->as_nplans = nplans; + /* + * Initialize Append's result tuple type and slot. If the child plans all + * produce the same fixed slot type, we can use that slot type; otherwise + * make a virtual slot. (Note that the result slot itself is used only to + * return a null tuple at end of execution; real tuples are returned to + * the caller in the children's own result slots. What we are doing here + * is allowing the parent plan node to optimize if the Append will return + * only one kind of slot.) + */ + appendops = ExecGetCommonSlotOps(appendplanstates, j); + if (appendops != NULL) + { + ExecInitResultTupleSlotTL(&appendstate->ps, appendops); + } + else + { + ExecInitResultTupleSlotTL(&appendstate->ps, &TTSOpsVirtual); + /* show that the output slot type is not fixed */ + appendstate->ps.resultopsset = true; + appendstate->ps.resultopsfixed = false; + } + /* Initialize async state */ appendstate->as_asyncplans = asyncplans; appendstate->as_nasyncplans = nasyncplans; @@ -580,7 +595,7 @@ choose_next_subplan_locally(AppendState *node) else if (!node->as_valid_subplans_identified) { node->as_valid_subplans = - ExecFindMatchingSubPlans(node->as_prune_state, false); + ExecFindMatchingSubPlans(node->as_prune_state, false, NULL); node->as_valid_subplans_identified = true; } @@ -647,7 +662,7 @@ choose_next_subplan_for_leader(AppendState *node) if (!node->as_valid_subplans_identified) { node->as_valid_subplans = - ExecFindMatchingSubPlans(node->as_prune_state, false); + ExecFindMatchingSubPlans(node->as_prune_state, false, NULL); node->as_valid_subplans_identified = true; /* @@ -723,7 +738,7 @@ choose_next_subplan_for_worker(AppendState *node) else if (!node->as_valid_subplans_identified) { node->as_valid_subplans = - ExecFindMatchingSubPlans(node->as_prune_state, false); + ExecFindMatchingSubPlans(node->as_prune_state, false, NULL); node->as_valid_subplans_identified = true; mark_invalid_subplans_as_finished(node); @@ -876,7 +891,7 @@ ExecAppendAsyncBegin(AppendState *node) if (!node->as_valid_subplans_identified) { node->as_valid_subplans = - ExecFindMatchingSubPlans(node->as_prune_state, false); + ExecFindMatchingSubPlans(node->as_prune_state, false, NULL); node->as_valid_subplans_identified = true; classify_matching_subplans(node); @@ -1016,7 +1031,7 @@ ExecAppendAsyncRequest(AppendState *node, TupleTableSlot **result) static void ExecAppendAsyncEventWait(AppendState *node) { - int nevents = node->as_nasyncplans + 1; + int nevents = node->as_nasyncplans + 2; long timeout = node->as_syncdone ? -1 : 0; WaitEvent occurred_event[EVENT_BUFFER_SIZE]; int noccurred; @@ -1041,8 +1056,8 @@ ExecAppendAsyncEventWait(AppendState *node) } /* - * No need for further processing if there are no configured events other - * than the postmaster death event. + * No need for further processing if none of the subplans configured any + * events. */ if (GetNumRegisteredWaitEvents(node->as_eventset) == 1) { @@ -1051,6 +1066,21 @@ ExecAppendAsyncEventWait(AppendState *node) return; } + /* + * Add the process latch to the set, so that we wake up to process the + * standard interrupts with CHECK_FOR_INTERRUPTS(). + * + * NOTE: For historical reasons, it's important that this is added to the + * WaitEventSet after the ExecAsyncConfigureWait() calls. Namely, + * postgres_fdw calls "GetNumRegisteredWaitEvents(set) == 1" to check if + * any other events are in the set. That's a poor design, it's + * questionable for postgres_fdw to be doing that in the first place, but + * we cannot change it now. The pattern has possibly been copied to other + * extensions too. + */ + AddWaitEventToSet(node->as_eventset, WL_LATCH_SET, PGINVALID_SOCKET, + MyLatch, NULL); + /* Return at most EVENT_BUFFER_SIZE events in one call. */ if (nevents > EVENT_BUFFER_SIZE) nevents = EVENT_BUFFER_SIZE; @@ -1092,6 +1122,13 @@ ExecAppendAsyncEventWait(AppendState *node) ExecAsyncNotify(areq); } } + + /* Handle standard interrupts */ + if ((w->events & WL_LATCH_SET) != 0) + { + ResetLatch(MyLatch); + CHECK_FOR_INTERRUPTS(); + } } } diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index 9c9c66687218c..939907b6fcd4b 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -3,7 +3,7 @@ * nodeBitmapAnd.c * routines to handle BitmapAnd nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 3c63bdd93dff3..bf24f3d7fe0a8 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -16,7 +16,7 @@ * required index qual conditions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -46,261 +46,110 @@ #include "pgstat.h" #include "storage/bufmgr.h" #include "utils/rel.h" -#include "utils/snapmgr.h" #include "utils/spccache.h" +static void BitmapTableScanSetup(BitmapHeapScanState *node); static TupleTableSlot *BitmapHeapNext(BitmapHeapScanState *node); static inline void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate); -static inline void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node, - BlockNumber blockno); -static inline void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node); -static inline void BitmapPrefetch(BitmapHeapScanState *node, - TableScanDesc scan); static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate); -/* ---------------------------------------------------------------- - * BitmapHeapNext - * - * Retrieve next tuple from the BitmapHeapScan node's currentRelation - * ---------------------------------------------------------------- +/* + * Do the underlying index scan, build the bitmap, set up the parallel state + * needed for parallel workers to iterate through the bitmap, and set up the + * underlying table scan descriptor. */ -static TupleTableSlot * -BitmapHeapNext(BitmapHeapScanState *node) +static void +BitmapTableScanSetup(BitmapHeapScanState *node) { - ExprContext *econtext; - TableScanDesc scan; - TIDBitmap *tbm; - TBMIterator *tbmiterator = NULL; - TBMSharedIterator *shared_tbmiterator = NULL; - TBMIterateResult *tbmres; - TupleTableSlot *slot; + TBMIterator tbmiterator = {0}; ParallelBitmapHeapState *pstate = node->pstate; dsa_area *dsa = node->ss.ps.state->es_query_dsa; - /* - * extract necessary information from index scan node - */ - econtext = node->ss.ps.ps_ExprContext; - slot = node->ss.ss_ScanTupleSlot; - scan = node->ss.ss_currentScanDesc; - tbm = node->tbm; - if (pstate == NULL) - tbmiterator = node->tbmiterator; - else - shared_tbmiterator = node->shared_tbmiterator; - tbmres = node->tbmres; - - /* - * If we haven't yet performed the underlying index scan, do it, and begin - * the iteration over the bitmap. - * - * For prefetching, we use *two* iterators, one for the pages we are - * actually scanning and another that runs ahead of the first for - * prefetching. node->prefetch_pages tracks exactly how many pages ahead - * the prefetch iterator is. Also, node->prefetch_target tracks the - * desired prefetch distance, which starts small and increases up to the - * node->prefetch_maximum. This is to avoid doing a lot of prefetching in - * a scan that stops after a few tuples because of a LIMIT. - */ - if (!node->initialized) + if (!pstate) { - if (!pstate) - { - tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node)); - - if (!tbm || !IsA(tbm, TIDBitmap)) - elog(ERROR, "unrecognized result from subplan"); - - node->tbm = tbm; - node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm); - node->tbmres = tbmres = NULL; + node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node)); -#ifdef USE_PREFETCH - if (node->prefetch_maximum > 0) - { - node->prefetch_iterator = tbm_begin_iterate(tbm); - node->prefetch_pages = 0; - node->prefetch_target = -1; - } -#endif /* USE_PREFETCH */ - } - else - { - /* - * The leader will immediately come out of the function, but - * others will be blocked until leader populates the TBM and wakes - * them up. - */ - if (BitmapShouldInitializeSharedState(pstate)) - { - tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node)); - if (!tbm || !IsA(tbm, TIDBitmap)) - elog(ERROR, "unrecognized result from subplan"); - - node->tbm = tbm; - - /* - * Prepare to iterate over the TBM. This will return the - * dsa_pointer of the iterator state which will be used by - * multiple processes to iterate jointly. - */ - pstate->tbmiterator = tbm_prepare_shared_iterate(tbm); -#ifdef USE_PREFETCH - if (node->prefetch_maximum > 0) - { - pstate->prefetch_iterator = - tbm_prepare_shared_iterate(tbm); - - /* - * We don't need the mutex here as we haven't yet woke up - * others. - */ - pstate->prefetch_pages = 0; - pstate->prefetch_target = -1; - } -#endif - - /* We have initialized the shared state so wake up others. */ - BitmapDoneInitializingSharedState(pstate); - } - - /* Allocate a private iterator and attach the shared state to it */ - node->shared_tbmiterator = shared_tbmiterator = - tbm_attach_shared_iterate(dsa, pstate->tbmiterator); - node->tbmres = tbmres = NULL; - -#ifdef USE_PREFETCH - if (node->prefetch_maximum > 0) - { - node->shared_prefetch_iterator = - tbm_attach_shared_iterate(dsa, pstate->prefetch_iterator); - } -#endif /* USE_PREFETCH */ - } - - /* - * If this is the first scan of the underlying table, create the table - * scan descriptor and begin the scan. - */ - if (!scan) - { - bool need_tuples = false; - - /* - * We can potentially skip fetching heap pages if we do not need - * any columns of the table, either for checking non-indexable - * quals or for returning data. This test is a bit simplistic, as - * it checks the stronger condition that there's no qual or return - * tlist at all. But in most cases it's probably not worth working - * harder than that. - */ - need_tuples = (node->ss.ps.plan->qual != NIL || - node->ss.ps.plan->targetlist != NIL); - - scan = table_beginscan_bm(node->ss.ss_currentRelation, - node->ss.ps.state->es_snapshot, - 0, - NULL, - need_tuples); - - node->ss.ss_currentScanDesc = scan; - } - - node->initialized = true; + if (!node->tbm || !IsA(node->tbm, TIDBitmap)) + elog(ERROR, "unrecognized result from subplan"); } - - for (;;) + else if (BitmapShouldInitializeSharedState(pstate)) { - bool valid_block; - - CHECK_FOR_INTERRUPTS(); - /* - * Get next page of results if needed + * The leader will immediately come out of the function, but others + * will be blocked until leader populates the TBM and wakes them up. */ - if (tbmres == NULL) - { - if (!pstate) - node->tbmres = tbmres = tbm_iterate(tbmiterator); - else - node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator); - if (tbmres == NULL) - { - /* no more entries in the bitmap */ - break; - } - - BitmapAdjustPrefetchIterator(node, tbmres->blockno); + node->tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node)); + if (!node->tbm || !IsA(node->tbm, TIDBitmap)) + elog(ERROR, "unrecognized result from subplan"); - valid_block = table_scan_bitmap_next_block(scan, tbmres); + /* + * Prepare to iterate over the TBM. This will return the dsa_pointer + * of the iterator state which will be used by multiple processes to + * iterate jointly. + */ + pstate->tbmiterator = tbm_prepare_shared_iterate(node->tbm); - if (tbmres->ntuples >= 0) - node->stats.exact_pages++; - else - node->stats.lossy_pages++; + /* We have initialized the shared state so wake up others. */ + BitmapDoneInitializingSharedState(pstate); + } - if (!valid_block) - { - /* AM doesn't think this block is valid, skip */ - continue; - } + tbmiterator = tbm_begin_iterate(node->tbm, dsa, + pstate ? + pstate->tbmiterator : + InvalidDsaPointer); - /* Adjust the prefetch target */ - BitmapAdjustPrefetchTarget(node); - } - else - { - /* - * Continuing in previously obtained page. - */ + /* + * If this is the first scan of the underlying table, create the table + * scan descriptor and begin the scan. + */ + if (!node->ss.ss_currentScanDesc) + { + node->ss.ss_currentScanDesc = + table_beginscan_bm(node->ss.ss_currentRelation, + node->ss.ps.state->es_snapshot, + 0, + NULL); + } -#ifdef USE_PREFETCH + node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator; + node->initialized = true; +} - /* - * Try to prefetch at least a few pages even before we get to the - * second page if we don't stop reading after the first tuple. - */ - if (!pstate) - { - if (node->prefetch_target < node->prefetch_maximum) - node->prefetch_target++; - } - else if (pstate->prefetch_target < node->prefetch_maximum) - { - /* take spinlock while updating shared state */ - SpinLockAcquire(&pstate->mutex); - if (pstate->prefetch_target < node->prefetch_maximum) - pstate->prefetch_target++; - SpinLockRelease(&pstate->mutex); - } -#endif /* USE_PREFETCH */ - } +/* ---------------------------------------------------------------- + * BitmapHeapNext + * + * Retrieve next tuple from the BitmapHeapScan node's currentRelation + * ---------------------------------------------------------------- + */ +static TupleTableSlot * +BitmapHeapNext(BitmapHeapScanState *node) +{ + ExprContext *econtext = node->ss.ps.ps_ExprContext; + TupleTableSlot *slot = node->ss.ss_ScanTupleSlot; - /* - * We issue prefetch requests *after* fetching the current page to try - * to avoid having prefetching interfere with the main I/O. Also, this - * should happen only when we have determined there is still something - * to do on the current page, else we may uselessly prefetch the same - * page we are just about to request for real. - */ - BitmapPrefetch(node, scan); + /* + * If we haven't yet performed the underlying index scan, do it, and begin + * the iteration over the bitmap. + */ + if (!node->initialized) + BitmapTableScanSetup(node); + while (table_scan_bitmap_next_tuple(node->ss.ss_currentScanDesc, + slot, &node->recheck, + &node->stats.lossy_pages, + &node->stats.exact_pages)) + { /* - * Attempt to fetch tuple from AM. + * Continuing in previously obtained page. */ - if (!table_scan_bitmap_next_tuple(scan, tbmres, slot)) - { - /* nothing more to look at on this page */ - node->tbmres = tbmres = NULL; - continue; - } + CHECK_FOR_INTERRUPTS(); /* * If we are using lossy info, we have to recheck the qual conditions * at every tuple. */ - if (tbmres->recheck) + if (node->recheck) { econtext->ecxt_scantuple = slot; if (!ExecQualAndReset(node->bitmapqualorig, econtext)) @@ -337,210 +186,6 @@ BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate) ConditionVariableBroadcast(&pstate->cv); } -/* - * BitmapAdjustPrefetchIterator - Adjust the prefetch iterator - */ -static inline void -BitmapAdjustPrefetchIterator(BitmapHeapScanState *node, - BlockNumber blockno) -{ -#ifdef USE_PREFETCH - ParallelBitmapHeapState *pstate = node->pstate; - - if (pstate == NULL) - { - TBMIterator *prefetch_iterator = node->prefetch_iterator; - - if (node->prefetch_pages > 0) - { - /* The main iterator has closed the distance by one page */ - node->prefetch_pages--; - } - else if (prefetch_iterator) - { - /* Do not let the prefetch iterator get behind the main one */ - TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator); - - if (tbmpre == NULL || tbmpre->blockno != blockno) - elog(ERROR, "prefetch and main iterators are out of sync"); - } - return; - } - - if (node->prefetch_maximum > 0) - { - TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator; - - SpinLockAcquire(&pstate->mutex); - if (pstate->prefetch_pages > 0) - { - pstate->prefetch_pages--; - SpinLockRelease(&pstate->mutex); - } - else - { - /* Release the mutex before iterating */ - SpinLockRelease(&pstate->mutex); - - /* - * In case of shared mode, we can not ensure that the current - * blockno of the main iterator and that of the prefetch iterator - * are same. It's possible that whatever blockno we are - * prefetching will be processed by another process. Therefore, - * we don't validate the blockno here as we do in non-parallel - * case. - */ - if (prefetch_iterator) - tbm_shared_iterate(prefetch_iterator); - } - } -#endif /* USE_PREFETCH */ -} - -/* - * BitmapAdjustPrefetchTarget - Adjust the prefetch target - * - * Increase prefetch target if it's not yet at the max. Note that - * we will increase it to zero after fetching the very first - * page/tuple, then to one after the second tuple is fetched, then - * it doubles as later pages are fetched. - */ -static inline void -BitmapAdjustPrefetchTarget(BitmapHeapScanState *node) -{ -#ifdef USE_PREFETCH - ParallelBitmapHeapState *pstate = node->pstate; - - if (pstate == NULL) - { - if (node->prefetch_target >= node->prefetch_maximum) - /* don't increase any further */ ; - else if (node->prefetch_target >= node->prefetch_maximum / 2) - node->prefetch_target = node->prefetch_maximum; - else if (node->prefetch_target > 0) - node->prefetch_target *= 2; - else - node->prefetch_target++; - return; - } - - /* Do an unlocked check first to save spinlock acquisitions. */ - if (pstate->prefetch_target < node->prefetch_maximum) - { - SpinLockAcquire(&pstate->mutex); - if (pstate->prefetch_target >= node->prefetch_maximum) - /* don't increase any further */ ; - else if (pstate->prefetch_target >= node->prefetch_maximum / 2) - pstate->prefetch_target = node->prefetch_maximum; - else if (pstate->prefetch_target > 0) - pstate->prefetch_target *= 2; - else - pstate->prefetch_target++; - SpinLockRelease(&pstate->mutex); - } -#endif /* USE_PREFETCH */ -} - -/* - * BitmapPrefetch - Prefetch, if prefetch_pages are behind prefetch_target - */ -static inline void -BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan) -{ -#ifdef USE_PREFETCH - ParallelBitmapHeapState *pstate = node->pstate; - - if (pstate == NULL) - { - TBMIterator *prefetch_iterator = node->prefetch_iterator; - - if (prefetch_iterator) - { - while (node->prefetch_pages < node->prefetch_target) - { - TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator); - bool skip_fetch; - - if (tbmpre == NULL) - { - /* No more pages to prefetch */ - tbm_end_iterate(prefetch_iterator); - node->prefetch_iterator = NULL; - break; - } - node->prefetch_pages++; - - /* - * If we expect not to have to actually read this heap page, - * skip this prefetch call, but continue to run the prefetch - * logic normally. (Would it be better not to increment - * prefetch_pages?) - */ - skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) && - !tbmpre->recheck && - VM_ALL_VISIBLE(node->ss.ss_currentRelation, - tbmpre->blockno, - &node->pvmbuffer)); - - if (!skip_fetch) - PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno); - } - } - - return; - } - - if (pstate->prefetch_pages < pstate->prefetch_target) - { - TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator; - - if (prefetch_iterator) - { - while (1) - { - TBMIterateResult *tbmpre; - bool do_prefetch = false; - bool skip_fetch; - - /* - * Recheck under the mutex. If some other process has already - * done enough prefetching then we need not to do anything. - */ - SpinLockAcquire(&pstate->mutex); - if (pstate->prefetch_pages < pstate->prefetch_target) - { - pstate->prefetch_pages++; - do_prefetch = true; - } - SpinLockRelease(&pstate->mutex); - - if (!do_prefetch) - return; - - tbmpre = tbm_shared_iterate(prefetch_iterator); - if (tbmpre == NULL) - { - /* No more pages to prefetch */ - tbm_end_shared_iterate(prefetch_iterator); - node->shared_prefetch_iterator = NULL; - break; - } - - /* As above, skip prefetch if we expect not to need page */ - skip_fetch = (!(scan->rs_flags & SO_NEED_TUPLES) && - !tbmpre->recheck && - VM_ALL_VISIBLE(node->ss.ss_currentRelation, - tbmpre->blockno, - &node->pvmbuffer)); - - if (!skip_fetch) - PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno); - } - } - } -#endif /* USE_PREFETCH */ -} - /* * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual */ @@ -582,31 +227,27 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node) { PlanState *outerPlan = outerPlanState(node); - /* rescan to release any page pin */ - if (node->ss.ss_currentScanDesc) + TableScanDesc scan = node->ss.ss_currentScanDesc; + + if (scan) + { + /* + * End iteration on iterators saved in scan descriptor if they have + * not already been cleaned up. + */ + if (!tbm_exhausted(&scan->st.rs_tbmiterator)) + tbm_end_iterate(&scan->st.rs_tbmiterator); + + /* rescan to release any page pin */ table_rescan(node->ss.ss_currentScanDesc, NULL); + } /* release bitmaps and buffers if any */ - if (node->tbmiterator) - tbm_end_iterate(node->tbmiterator); - if (node->prefetch_iterator) - tbm_end_iterate(node->prefetch_iterator); - if (node->shared_tbmiterator) - tbm_end_shared_iterate(node->shared_tbmiterator); - if (node->shared_prefetch_iterator) - tbm_end_shared_iterate(node->shared_prefetch_iterator); if (node->tbm) tbm_free(node->tbm); - if (node->pvmbuffer != InvalidBuffer) - ReleaseBuffer(node->pvmbuffer); node->tbm = NULL; - node->tbmiterator = NULL; - node->tbmres = NULL; - node->prefetch_iterator = NULL; node->initialized = false; - node->shared_tbmiterator = NULL; - node->shared_prefetch_iterator = NULL; - node->pvmbuffer = InvalidBuffer; + node->recheck = true; ExecScanReScan(&node->ss); @@ -660,28 +301,26 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) */ ExecEndNode(outerPlanState(node)); + if (scanDesc) + { + /* + * End iteration on iterators saved in scan descriptor if they have + * not already been cleaned up. + */ + if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator)) + tbm_end_iterate(&scanDesc->st.rs_tbmiterator); + + /* + * close table scan + */ + table_endscan(scanDesc); + } + /* * release bitmaps and buffers if any */ - if (node->tbmiterator) - tbm_end_iterate(node->tbmiterator); - if (node->prefetch_iterator) - tbm_end_iterate(node->prefetch_iterator); if (node->tbm) tbm_free(node->tbm); - if (node->shared_tbmiterator) - tbm_end_shared_iterate(node->shared_tbmiterator); - if (node->shared_prefetch_iterator) - tbm_end_shared_iterate(node->shared_prefetch_iterator); - if (node->pvmbuffer != InvalidBuffer) - ReleaseBuffer(node->pvmbuffer); - - /* - * close heap scan - */ - if (scanDesc) - table_endscan(scanDesc); - } /* ---------------------------------------------------------------- @@ -714,20 +353,13 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan; scanstate->tbm = NULL; - scanstate->tbmiterator = NULL; - scanstate->tbmres = NULL; - scanstate->pvmbuffer = InvalidBuffer; /* Zero the statistics counters */ memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation)); - scanstate->prefetch_iterator = NULL; - scanstate->prefetch_pages = 0; - scanstate->prefetch_target = 0; scanstate->initialized = false; - scanstate->shared_tbmiterator = NULL; - scanstate->shared_prefetch_iterator = NULL; scanstate->pstate = NULL; + scanstate->recheck = true; /* * Miscellaneous initialization @@ -767,13 +399,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) scanstate->bitmapqualorig = ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate); - /* - * Maximum number of prefetches for the tablespace if configured, - * otherwise the current value of the effective_io_concurrency GUC. - */ - scanstate->prefetch_maximum = - get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace); - scanstate->ss.ss_currentRelation = currentRelation; /* @@ -877,12 +502,9 @@ ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node, sinstrument = (SharedBitmapHeapInstrumentation *) ptr; pstate->tbmiterator = 0; - pstate->prefetch_iterator = 0; /* Initialize the mutex */ SpinLockInit(&pstate->mutex); - pstate->prefetch_pages = 0; - pstate->prefetch_target = 0; pstate->state = BM_INITIAL; ConditionVariableInit(&pstate->cv); @@ -923,11 +545,7 @@ ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node, if (DsaPointerIsValid(pstate->tbmiterator)) tbm_free_shared_area(dsa, pstate->tbmiterator); - if (DsaPointerIsValid(pstate->prefetch_iterator)) - tbm_free_shared_area(dsa, pstate->prefetch_iterator); - pstate->tbmiterator = InvalidDsaPointer; - pstate->prefetch_iterator = InvalidDsaPointer; } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 6df8e17ec84ca..abbb033881a22 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -3,7 +3,7 @@ * nodeBitmapIndexscan.c * Routines to support bitmapped index scans of relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -91,7 +91,7 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node) else { /* XXX should we use less than work_mem for this? */ - tbm = tbm_create(work_mem * 1024L, + tbm = tbm_create(work_mem * (Size) 1024, ((BitmapIndexScan *) node->ss.ps.plan)->isshared ? node->ss.ps.state->es_query_dsa : NULL); } @@ -183,6 +183,27 @@ ExecEndBitmapIndexScan(BitmapIndexScanState *node) indexRelationDesc = node->biss_RelationDesc; indexScanDesc = node->biss_ScanDesc; + /* + * When ending a parallel worker, copy the statistics gathered by the + * worker back into shared memory so that it can be picked up by the main + * process to report in EXPLAIN ANALYZE + */ + if (node->biss_SharedInfo != NULL && IsParallelWorker()) + { + IndexScanInstrumentation *winstrument; + + Assert(ParallelWorkerNumber <= node->biss_SharedInfo->num_workers); + winstrument = &node->biss_SharedInfo->winstrument[ParallelWorkerNumber]; + + /* + * We have to accumulate the stats rather than performing a memcpy. + * When a Gather/GatherMerge node finishes it will perform planner + * shutdown on the workers. On rescan it will spin up new workers + * which will have a new BitmapIndexScanState and zeroed stats. + */ + winstrument->nsearches += node->biss_Instrument.nsearches; + } + /* * close the index relation (no-op if we didn't open it) */ @@ -302,6 +323,7 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) indexstate->biss_ScanDesc = index_beginscan_bitmap(indexstate->biss_RelationDesc, estate->es_snapshot, + &indexstate->biss_Instrument, indexstate->biss_NumScanKeys); /* @@ -319,3 +341,97 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) */ return indexstate; } + +/* ---------------------------------------------------------------- + * ExecBitmapIndexScanEstimate + * + * Compute the amount of space we'll need in the parallel + * query DSM, and inform pcxt->estimator about our needs. + * ---------------------------------------------------------------- + */ +void +ExecBitmapIndexScanEstimate(BitmapIndexScanState *node, ParallelContext *pcxt) +{ + Size size; + + /* + * Parallel bitmap index scans are not supported, but we still need to + * store the scan's instrumentation in DSM during parallel query + */ + if (!node->ss.ps.instrument || pcxt->nworkers == 0) + return; + + size = offsetof(SharedIndexScanInstrumentation, winstrument) + + pcxt->nworkers * sizeof(IndexScanInstrumentation); + shm_toc_estimate_chunk(&pcxt->estimator, size); + shm_toc_estimate_keys(&pcxt->estimator, 1); +} + +/* ---------------------------------------------------------------- + * ExecBitmapIndexScanInitializeDSM + * + * Set up bitmap index scan shared instrumentation. + * ---------------------------------------------------------------- + */ +void +ExecBitmapIndexScanInitializeDSM(BitmapIndexScanState *node, + ParallelContext *pcxt) +{ + Size size; + + /* don't need this if not instrumenting or no workers */ + if (!node->ss.ps.instrument || pcxt->nworkers == 0) + return; + + size = offsetof(SharedIndexScanInstrumentation, winstrument) + + pcxt->nworkers * sizeof(IndexScanInstrumentation); + node->biss_SharedInfo = + (SharedIndexScanInstrumentation *) shm_toc_allocate(pcxt->toc, + size); + shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, + node->biss_SharedInfo); + + /* Each per-worker area must start out as zeroes */ + memset(node->biss_SharedInfo, 0, size); + node->biss_SharedInfo->num_workers = pcxt->nworkers; +} + +/* ---------------------------------------------------------------- + * ExecBitmapIndexScanInitializeWorker + * + * Copy relevant information from TOC into planstate. + * ---------------------------------------------------------------- + */ +void +ExecBitmapIndexScanInitializeWorker(BitmapIndexScanState *node, + ParallelWorkerContext *pwcxt) +{ + /* don't need this if not instrumenting */ + if (!node->ss.ps.instrument) + return; + + node->biss_SharedInfo = (SharedIndexScanInstrumentation *) + shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); +} + +/* ---------------------------------------------------------------- + * ExecBitmapIndexScanRetrieveInstrumentation + * + * Transfer bitmap index scan statistics from DSM to private memory. + * ---------------------------------------------------------------- + */ +void +ExecBitmapIndexScanRetrieveInstrumentation(BitmapIndexScanState *node) +{ + SharedIndexScanInstrumentation *SharedInfo = node->biss_SharedInfo; + size_t size; + + if (SharedInfo == NULL) + return; + + /* Create a copy of SharedInfo in backend-local memory */ + size = offsetof(SharedIndexScanInstrumentation, winstrument) + + SharedInfo->num_workers * sizeof(IndexScanInstrumentation); + node->biss_SharedInfo = palloc(size); + memcpy(node->biss_SharedInfo, SharedInfo, size); +} diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index 7029536c64382..231760ec93d57 100644 --- a/src/backend/executor/nodeBitmapOr.c +++ b/src/backend/executor/nodeBitmapOr.c @@ -3,7 +3,7 @@ * nodeBitmapOr.c * routines to handle BitmapOr nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -143,7 +143,7 @@ MultiExecBitmapOr(BitmapOrState *node) if (result == NULL) /* first subplan */ { /* XXX should we use less than work_mem for this? */ - result = tbm_create(work_mem * 1024L, + result = tbm_create(work_mem * (Size) 1024, ((BitmapOr *) node->ps.plan)->isshared ? node->ps.state->es_query_dsa : NULL); } diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index 8081eed887b0b..e1675f66b4341 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -3,7 +3,7 @@ * nodeCtescan.c * routines to handle CteScan nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c index e559cd23464bc..ac2196b64c7ad 100644 --- a/src/backend/executor/nodeCustom.c +++ b/src/backend/executor/nodeCustom.c @@ -3,7 +3,7 @@ * nodeCustom.c * Routines to handle execution of custom scan node * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * ------------------------------------------------------------------------ diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c index fe4ae55c0f68a..9c56c2f3acfe2 100644 --- a/src/backend/executor/nodeForeignscan.c +++ b/src/backend/executor/nodeForeignscan.c @@ -3,7 +3,7 @@ * nodeForeignscan.c * Routines to support scans of foreign tables * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 3fdd1c51e1c2c..644363582d913 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -3,7 +3,7 @@ * nodeFunctionscan.c * Support routines for scanning RangeFunctions (functions in rangetable). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index 5d4ffe989cb23..dc7d1830259f5 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -3,7 +3,7 @@ * nodeGather.c * Support routines for scanning a plan via multiple workers. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * A Gather executor launches parallel workers to run multiple copies of a @@ -182,6 +182,13 @@ ExecGather(PlanState *pstate) /* We save # workers launched for the benefit of EXPLAIN */ node->nworkers_launched = pcxt->nworkers_launched; + /* + * Count number of workers originally wanted and actually + * launched. + */ + estate->es_parallel_workers_to_launch += pcxt->nworkers_to_launch; + estate->es_parallel_workers_launched += pcxt->nworkers_launched; + /* Set up tuple queue readers to read the results. */ if (pcxt->nworkers_launched > 0) { diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 45f6017c29ef8..15f8459706773 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -3,7 +3,7 @@ * nodeGatherMerge.c * Scan a plan in multiple workers, and do order-preserving merge. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -223,6 +223,13 @@ ExecGatherMerge(PlanState *pstate) /* We save # workers launched for the benefit of EXPLAIN */ node->nworkers_launched = pcxt->nworkers_launched; + /* + * Count number of workers originally wanted and actually + * launched. + */ + estate->es_parallel_workers_to_launch += pcxt->nworkers_to_launch; + estate->es_parallel_workers_launched += pcxt->nworkers_launched; + /* Set up tuple queue readers to read the results. */ if (pcxt->nworkers_launched > 0) { @@ -728,7 +735,7 @@ gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait, * Since we'll be buffering these across multiple calls, we need to make a * copy. */ - return tup ? heap_copy_minimal_tuple(tup) : NULL; + return tup ? heap_copy_minimal_tuple(tup, 0) : NULL; } /* diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index da32bec1811ca..05fdd96f83584 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -3,7 +3,7 @@ * nodeGroup.c * Routines to handle group nodes (used for queries with GROUP BY clause). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 61480733a1227..8d2201ab67fa5 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -3,7 +3,7 @@ * nodeHash.c * Routines to hash relations for hashjoin * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -35,7 +35,6 @@ #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "miscadmin.h" -#include "port/atomics.h" #include "port/pg_bitutils.h" #include "utils/dynahash.h" #include "utils/lsyscache.h" @@ -47,7 +46,8 @@ static void ExecHashIncreaseNumBatches(HashJoinTable hashtable); static void ExecHashIncreaseNumBuckets(HashJoinTable hashtable); static void ExecParallelHashIncreaseNumBatches(HashJoinTable hashtable); static void ExecParallelHashIncreaseNumBuckets(HashJoinTable hashtable); -static void ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, +static void ExecHashBuildSkewHash(HashState *hashstate, + HashJoinTable hashtable, Hash *node, int mcvsToUse); static void ExecHashSkewTableInsert(HashJoinTable hashtable, TupleTableSlot *slot, @@ -138,11 +138,9 @@ static void MultiExecPrivateHash(HashState *node) { PlanState *outerNode; - List *hashkeys; HashJoinTable hashtable; TupleTableSlot *slot; ExprContext *econtext; - uint32 hashvalue; /* * get state info from node @@ -153,7 +151,6 @@ MultiExecPrivateHash(HashState *node) /* * set expression context */ - hashkeys = node->hashkeys; econtext = node->ps.ps_ExprContext; /* @@ -162,15 +159,23 @@ MultiExecPrivateHash(HashState *node) */ for (;;) { + bool isnull; + Datum hashdatum; + slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; /* We have to compute the hash value */ econtext->ecxt_outertuple = slot; - if (ExecHashGetHashValue(hashtable, econtext, hashkeys, - false, hashtable->keepNulls, - &hashvalue)) + + ResetExprContext(econtext); + + hashdatum = ExecEvalExprSwitchContext(node->hash_expr, econtext, + &isnull); + + if (!isnull) { + uint32 hashvalue = DatumGetUInt32(hashdatum); int bucketNumber; bucketNumber = ExecHashGetSkewBucket(hashtable, hashvalue); @@ -215,7 +220,6 @@ MultiExecParallelHash(HashState *node) { ParallelHashJoinState *pstate; PlanState *outerNode; - List *hashkeys; HashJoinTable hashtable; TupleTableSlot *slot; ExprContext *econtext; @@ -232,7 +236,6 @@ MultiExecParallelHash(HashState *node) /* * set expression context */ - hashkeys = node->hashkeys; econtext = node->ps.ps_ExprContext; /* @@ -279,13 +282,20 @@ MultiExecParallelHash(HashState *node) ExecParallelHashTableSetCurrentBatch(hashtable, 0); for (;;) { + bool isnull; + slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; econtext->ecxt_outertuple = slot; - if (ExecHashGetHashValue(hashtable, econtext, hashkeys, - false, hashtable->keepNulls, - &hashvalue)) + + ResetExprContext(econtext); + + hashvalue = DatumGetUInt32(ExecEvalExprSwitchContext(node->hash_expr, + econtext, + &isnull)); + + if (!isnull) ExecParallelHashTableInsert(hashtable, slot, hashvalue); hashtable->partialTuples++; } @@ -371,8 +381,8 @@ ExecInitHash(Hash *node, EState *estate, int eflags) hashstate->ps.plan = (Plan *) node; hashstate->ps.state = estate; hashstate->ps.ExecProcNode = ExecHash; + /* delay building hashtable until ExecHashTableCreate() in executor run */ hashstate->hashtable = NULL; - hashstate->hashkeys = NIL; /* will be set by parent HashJoin */ /* * Miscellaneous initialization @@ -393,12 +403,16 @@ ExecInitHash(Hash *node, EState *estate, int eflags) ExecInitResultTupleSlotTL(&hashstate->ps, &TTSOpsMinimalTuple); hashstate->ps.ps_ProjInfo = NULL; + Assert(node->plan.qual == NIL); + /* - * initialize child expressions + * Delay initialization of hash_expr until ExecInitHashJoin(). We cannot + * build the ExprState here as we don't yet know the join type we're going + * to be hashing values for and we need to know that before calling + * ExecBuildHash32Expr as the keep_nulls parameter depends on the join + * type. */ - Assert(node->plan.qual == NIL); - hashstate->hashkeys = - ExecInitExprList(node->hashkeys, (PlanState *) hashstate); + hashstate->hash_expr = NULL; return hashstate; } @@ -429,7 +443,7 @@ ExecEndHash(HashState *node) * ---------------------------------------------------------------- */ HashJoinTable -ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, bool keepNulls) +ExecHashTableCreate(HashState *state) { Hash *node; HashJoinTable hashtable; @@ -440,10 +454,6 @@ ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, double rows; int num_skew_mcvs; int log2_nbuckets; - int nkeys; - int i; - ListCell *ho; - ListCell *hc; MemoryContext oldcxt; /* @@ -487,7 +497,6 @@ ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, hashtable->log2_nbuckets = log2_nbuckets; hashtable->log2_nbuckets_optimal = log2_nbuckets; hashtable->buckets.unshared = NULL; - hashtable->keepNulls = keepNulls; hashtable->skewEnabled = false; hashtable->skewBucket = NULL; hashtable->skewBucketLen = 0; @@ -540,32 +549,6 @@ ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, oldcxt = MemoryContextSwitchTo(hashtable->hashCxt); - /* - * Get info about the hash functions to be used for each hash key. Also - * remember whether the join operators are strict. - */ - nkeys = list_length(hashOperators); - hashtable->outer_hashfunctions = palloc_array(FmgrInfo, nkeys); - hashtable->inner_hashfunctions = palloc_array(FmgrInfo, nkeys); - hashtable->hashStrict = palloc_array(bool, nkeys); - hashtable->collations = palloc_array(Oid, nkeys); - i = 0; - forboth(ho, hashOperators, hc, hashCollations) - { - Oid hashop = lfirst_oid(ho); - Oid left_hashfn; - Oid right_hashfn; - - if (!get_op_hash_functions(hashop, &left_hashfn, &right_hashfn)) - elog(ERROR, "could not find hash function for hash operator %u", - hashop); - fmgr_info(left_hashfn, &hashtable->outer_hashfunctions[i]); - fmgr_info(right_hashfn, &hashtable->inner_hashfunctions[i]); - hashtable->hashStrict[i] = op_strict(hashop); - hashtable->collations[i] = lfirst_oid(hc); - i++; - } - if (nbatch > 1 && hashtable->parallel_state == NULL) { MemoryContext oldctx; @@ -652,7 +635,7 @@ ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, * it.) */ if (nbatch > 1) - ExecHashBuildSkewHash(hashtable, node, num_skew_mcvs); + ExecHashBuildSkewHash(state, hashtable, node, num_skew_mcvs); MemoryContextSwitchTo(oldcxt); } @@ -865,6 +848,90 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew, nbatch = pg_nextpower2_32(Max(2, minbatch)); } + /* + * Optimize the total amount of memory consumed by the hash node. + * + * The nbatch calculation above focuses on the size of the in-memory hash + * table, assuming no per-batch overhead. Now adjust the number of batches + * and the size of the hash table to minimize total memory consumed by the + * hash node. + * + * Each batch file has a BLCKSZ buffer, and we may need two files per + * batch (inner and outer side). So with enough batches this can be + * significantly more memory than the hashtable itself. + * + * The total memory usage may be expressed by this formula: + * + * (inner_rel_bytes / nbatch) + (2 * nbatch * BLCKSZ) <= hash_table_bytes + * + * where (inner_rel_bytes / nbatch) is the size of the in-memory hash + * table and (2 * nbatch * BLCKSZ) is the amount of memory used by file + * buffers. But for sufficiently large values of inner_rel_bytes value + * there may not be a nbatch value that would make both parts fit into + * hash_table_bytes. + * + * In this case we can't enforce the memory limit - we're going to exceed + * it. We can however minimize the impact and use as little memory as + * possible. (We haven't really enforced it before either, as we simply + * ignored the batch files.) + * + * The formula for total memory usage says that given an inner relation of + * size inner_rel_bytes, we may divide it into an arbitrary number of + * batches. This determines both the size of the in-memory hash table and + * the amount of memory needed for batch files. These two terms work in + * opposite ways - when one decreases, the other increases. + * + * For low nbatch values, the hash table takes most of the memory, but at + * some point the batch files start to dominate. If you combine these two + * terms, the memory consumption (for a fixed size of the inner relation) + * has a u-shape, with a minimum at some nbatch value. + * + * Our goal is to find this nbatch value, minimizing the memory usage. We + * calculate the memory usage with half the batches (i.e. nbatch/2), and + * if it's lower than the current memory usage we know it's better to use + * fewer batches. We repeat this until reducing the number of batches does + * not reduce the memory usage - we found the optimum. We know the optimum + * exists, thanks to the u-shape. + * + * We only want to do this when exceeding the memory limit, not every + * time. The goal is not to minimize memory usage in every case, but to + * minimize the memory usage when we can't stay within the memory limit. + * + * For this reason we only consider reducing the number of batches. We + * could try the opposite direction too, but that would save memory only + * when most of the memory is used by the hash table. And the hash table + * was used for the initial sizing, so we shouldn't be exceeding the + * memory limit too much. We might save memory by using more batches, but + * it would result in spilling more batch files, which does not seem like + * a great trade off. + * + * While growing the hashtable, we also adjust the number of buckets, to + * not have more than one tuple per bucket (load factor 1). We can only do + * this during the initial sizing - once we start building the hash, + * nbucket is fixed. + */ + while (nbatch > 0) + { + /* how much memory are we using with current nbatch value */ + size_t current_space = hash_table_bytes + (2 * nbatch * BLCKSZ); + + /* how much memory would we use with half the batches */ + size_t new_space = hash_table_bytes * 2 + (nbatch * BLCKSZ); + + /* If the memory usage would not decrease, we found the optimum. */ + if (current_space < new_space) + break; + + /* + * It's better to use half the batches, so do that and adjust the + * nbucket in the opposite direction, and double the allowance. + */ + nbatch /= 2; + nbuckets *= 2; + + *space_allowed = (*space_allowed) * 2; + } + Assert(nbuckets > 0); Assert(nbatch > 0); @@ -907,6 +974,47 @@ ExecHashTableDestroy(HashJoinTable hashtable) pfree(hashtable); } +/* + * Consider adjusting the allowed hash table size, depending on the number + * of batches, to minimize the overall memory usage (for both the hashtable + * and batch files). + * + * We're adjusting the size of the hash table, not the (optimal) number of + * buckets. We can't change that once we start building the hash, due to how + * ExecHashGetBucketAndBatch calculates batchno/bucketno from the hash. This + * means the load factor may not be optimal, but we're in damage control so + * we accept slower lookups. It's still much better than batch explosion. + * + * Returns true if we chose to increase the batch size (and thus we don't + * need to add batches), and false if we should increase nbatch. + */ +static bool +ExecHashIncreaseBatchSize(HashJoinTable hashtable) +{ + /* + * How much additional memory would doubling nbatch use? Each batch may + * require two buffered files (inner/outer), with a BLCKSZ buffer. + */ + size_t batchSpace = (hashtable->nbatch * 2 * BLCKSZ); + + /* + * Compare the new space needed for doubling nbatch and for enlarging the + * in-memory hash table. If doubling the hash table needs less memory, + * just do that. Otherwise, continue with doubling the nbatch. + * + * We're either doubling spaceAllowed of batchSpace, so which of those + * increases the memory usage the least is the same as comparing the + * values directly. + */ + if (hashtable->spaceAllowed <= batchSpace) + { + hashtable->spaceAllowed *= 2; + return true; + } + + return false; +} + /* * ExecHashIncreaseNumBatches * increase the original number of batches in order to reduce @@ -930,6 +1038,10 @@ ExecHashIncreaseNumBatches(HashJoinTable hashtable) if (oldnbatch > Min(INT_MAX / 2, MaxAllocSize / (sizeof(void *) * 2))) return; + /* consider increasing size of the in-memory hash table instead */ + if (ExecHashIncreaseBatchSize(hashtable)) + return; + nbatch = oldnbatch * 2; Assert(nbatch > 1); @@ -1244,6 +1356,7 @@ ExecParallelHashIncreaseNumBatches(HashJoinTable hashtable) if (BarrierArriveAndWait(&pstate->grow_batches_barrier, WAIT_EVENT_HASH_GROW_BATCHES_DECIDE)) { + ParallelHashJoinBatch *old_batches; bool space_exhausted = false; bool extreme_skew_detected = false; @@ -1251,25 +1364,31 @@ ExecParallelHashIncreaseNumBatches(HashJoinTable hashtable) ExecParallelHashEnsureBatchAccessors(hashtable); ExecParallelHashTableSetCurrentBatch(hashtable, 0); + old_batches = dsa_get_address(hashtable->area, pstate->old_batches); + /* Are any of the new generation of batches exhausted? */ for (int i = 0; i < hashtable->nbatch; ++i) { - ParallelHashJoinBatch *batch = hashtable->batches[i].shared; + ParallelHashJoinBatch *batch; + ParallelHashJoinBatch *old_batch; + int parent; + batch = hashtable->batches[i].shared; if (batch->space_exhausted || batch->estimated_size > pstate->space_allowed) - { - int parent; - space_exhausted = true; + parent = i % pstate->old_nbatch; + old_batch = NthParallelHashJoinBatch(old_batches, parent); + if (old_batch->space_exhausted || + batch->estimated_size > pstate->space_allowed) + { /* * Did this batch receive ALL of the tuples from its * parent batch? That would indicate that further * repartitioning isn't going to help (the hash values * are probably all the same). */ - parent = i % pstate->old_nbatch; if (batch->ntuples == hashtable->batches[parent].shared->old_ntuples) extreme_skew_detected = true; } @@ -1803,103 +1922,6 @@ ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable, heap_free_minimal_tuple(tuple); } -/* - * ExecHashGetHashValue - * Compute the hash value for a tuple - * - * The tuple to be tested must be in econtext->ecxt_outertuple (thus Vars in - * the hashkeys expressions need to have OUTER_VAR as varno). If outer_tuple - * is false (meaning it's the HashJoin's inner node, Hash), econtext, - * hashkeys, and slot need to be from Hash, with hashkeys/slot referencing and - * being suitable for tuples from the node below the Hash. Conversely, if - * outer_tuple is true, econtext is from HashJoin, and hashkeys/slot need to - * be appropriate for tuples from HashJoin's outer node. - * - * A true result means the tuple's hash value has been successfully computed - * and stored at *hashvalue. A false result means the tuple cannot match - * because it contains a null attribute, and hence it should be discarded - * immediately. (If keep_nulls is true then false is never returned.) - */ -bool -ExecHashGetHashValue(HashJoinTable hashtable, - ExprContext *econtext, - List *hashkeys, - bool outer_tuple, - bool keep_nulls, - uint32 *hashvalue) -{ - uint32 hashkey = 0; - FmgrInfo *hashfunctions; - ListCell *hk; - int i = 0; - MemoryContext oldContext; - - /* - * We reset the eval context each time to reclaim any memory leaked in the - * hashkey expressions. - */ - ResetExprContext(econtext); - - oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); - - if (outer_tuple) - hashfunctions = hashtable->outer_hashfunctions; - else - hashfunctions = hashtable->inner_hashfunctions; - - foreach(hk, hashkeys) - { - ExprState *keyexpr = (ExprState *) lfirst(hk); - Datum keyval; - bool isNull; - - /* combine successive hashkeys by rotating */ - hashkey = pg_rotate_left32(hashkey, 1); - - /* - * Get the join attribute value of the tuple - */ - keyval = ExecEvalExpr(keyexpr, econtext, &isNull); - - /* - * If the attribute is NULL, and the join operator is strict, then - * this tuple cannot pass the join qual so we can reject it - * immediately (unless we're scanning the outside of an outer join, in - * which case we must not reject it). Otherwise we act like the - * hashcode of NULL is zero (this will support operators that act like - * IS NOT DISTINCT, though not any more-random behavior). We treat - * the hash support function as strict even if the operator is not. - * - * Note: currently, all hashjoinable operators must be strict since - * the hash index AM assumes that. However, it takes so little extra - * code here to allow non-strict that we may as well do it. - */ - if (isNull) - { - if (hashtable->hashStrict[i] && !keep_nulls) - { - MemoryContextSwitchTo(oldContext); - return false; /* cannot match */ - } - /* else, leave hashkey unmodified, equivalent to hashcode 0 */ - } - else - { - /* Compute the hash function */ - uint32 hkey; - - hkey = DatumGetUInt32(FunctionCall1Coll(&hashfunctions[i], hashtable->collations[i], keyval)); - hashkey ^= hkey; - } - - i++; - } - - MemoryContextSwitchTo(oldContext); - - *hashvalue = hashkey; - return true; -} /* * ExecHashGetBucketAndBatch @@ -2372,7 +2394,8 @@ ExecReScanHash(HashState *node) * based on available memory. */ static void -ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse) +ExecHashBuildSkewHash(HashState *hashstate, HashJoinTable hashtable, + Hash *node, int mcvsToUse) { HeapTupleData *statsTuple; AttStatsSlot sslot; @@ -2400,7 +2423,6 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse) { double frac; int nbuckets; - FmgrInfo *hashfunctions; int i; if (mcvsToUse > sslot.nvalues) @@ -2468,15 +2490,14 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse) * ExecHashRemoveNextSkewBucket) and we want the least common MCVs to * be removed first. */ - hashfunctions = hashtable->outer_hashfunctions; for (i = 0; i < mcvsToUse; i++) { uint32 hashvalue; int bucket; - hashvalue = DatumGetUInt32(FunctionCall1Coll(&hashfunctions[0], - hashtable->collations[0], + hashvalue = DatumGetUInt32(FunctionCall1Coll(hashstate->skew_hashfunction, + hashstate->skew_collation, sslot.values[i])); /* diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 5429e68734266..5661ad7683004 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -3,7 +3,7 @@ * nodeHashjoin.c * Routines to handle hash join nodes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -169,6 +169,7 @@ #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "miscadmin.h" +#include "utils/lsyscache.h" #include "utils/sharedtuplestore.h" #include "utils/wait_event.h" @@ -331,10 +332,7 @@ ExecHashJoinImpl(PlanState *pstate, bool parallel) * whoever gets here first will create the hash table and any * later arrivals will merely attach to it. */ - hashtable = ExecHashTableCreate(hashNode, - node->hj_HashOperators, - node->hj_Collations, - HJ_FILL_INNER(node)); + hashtable = ExecHashTableCreate(hashNode); node->hj_HashTable = hashtable; /* @@ -820,9 +818,96 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) */ { HashState *hashstate = (HashState *) innerPlanState(hjstate); + Hash *hash = (Hash *) hashstate->ps.plan; TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot; + Oid *outer_hashfuncid; + Oid *inner_hashfuncid; + bool *hash_strict; + ListCell *lc; + int nkeys; + hjstate->hj_HashTupleSlot = slot; + + /* + * Build ExprStates to obtain hash values for either side of the join. + * This must be done here as ExecBuildHash32Expr needs to know how to + * handle NULL inputs and the required handling of that depends on the + * jointype. We don't know the join type in ExecInitHash() and we + * must build the ExprStates before ExecHashTableCreate() so we + * properly attribute any SubPlans that exist in the hash expressions + * to the correct PlanState. + */ + nkeys = list_length(node->hashoperators); + + outer_hashfuncid = palloc_array(Oid, nkeys); + inner_hashfuncid = palloc_array(Oid, nkeys); + hash_strict = palloc_array(bool, nkeys); + + /* + * Determine the hash function for each side of the join for the given + * hash operator. + */ + foreach(lc, node->hashoperators) + { + Oid hashop = lfirst_oid(lc); + int i = foreach_current_index(lc); + + if (!get_op_hash_functions(hashop, + &outer_hashfuncid[i], + &inner_hashfuncid[i])) + elog(ERROR, + "could not find hash function for hash operator %u", + hashop); + hash_strict[i] = op_strict(hashop); + } + + /* + * Build an ExprState to generate the hash value for the expressions + * on the outer of the join. This ExprState must finish generating + * the hash value when HJ_FILL_OUTER() is true. Otherwise, + * ExecBuildHash32Expr will set up the ExprState to abort early if it + * finds a NULL. In these cases, we don't need to store these tuples + * in the hash table as the jointype does not require it. + */ + hjstate->hj_OuterHash = + ExecBuildHash32Expr(hjstate->js.ps.ps_ResultTupleDesc, + hjstate->js.ps.resultops, + outer_hashfuncid, + node->hashcollations, + node->hashkeys, + hash_strict, + &hjstate->js.ps, + 0, + HJ_FILL_OUTER(hjstate)); + + /* As above, but for the inner side of the join */ + hashstate->hash_expr = + ExecBuildHash32Expr(hashstate->ps.ps_ResultTupleDesc, + hashstate->ps.resultops, + inner_hashfuncid, + node->hashcollations, + hash->hashkeys, + hash_strict, + &hashstate->ps, + 0, + HJ_FILL_INNER(hjstate)); + + /* + * Set up the skew table hash function while we have a record of the + * first key's hash function Oid. + */ + if (OidIsValid(hash->skewTable)) + { + hashstate->skew_hashfunction = palloc0(sizeof(FmgrInfo)); + hashstate->skew_collation = linitial_oid(node->hashcollations); + fmgr_info(outer_hashfuncid[0], hashstate->skew_hashfunction); + } + + /* no need to keep these */ + pfree(outer_hashfuncid); + pfree(inner_hashfuncid); + pfree(hash_strict); } /* @@ -846,11 +931,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags) hjstate->hj_CurSkewBucketNo = INVALID_SKEW_BUCKET_NO; hjstate->hj_CurTuple = NULL; - hjstate->hj_OuterHashKeys = ExecInitExprList(node->hashkeys, - (PlanState *) hjstate); - hjstate->hj_HashOperators = node->hashoperators; - hjstate->hj_Collations = node->hashcollations; - hjstate->hj_JoinState = HJ_BUILD_HASHTABLE; hjstate->hj_MatchedOuter = false; hjstate->hj_OuterNotEmpty = false; @@ -918,17 +998,22 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode, while (!TupIsNull(slot)) { + bool isnull; + /* * We have to compute the tuple's hash value. */ ExprContext *econtext = hjstate->js.ps.ps_ExprContext; econtext->ecxt_outertuple = slot; - if (ExecHashGetHashValue(hashtable, econtext, - hjstate->hj_OuterHashKeys, - true, /* outer tuple */ - HJ_FILL_OUTER(hjstate), - hashvalue)) + + ResetExprContext(econtext); + + *hashvalue = DatumGetUInt32(ExecEvalExprSwitchContext(hjstate->hj_OuterHash, + econtext, + &isnull)); + + if (!isnull) { /* remember outer relation is not empty for possible rescan */ hjstate->hj_OuterNotEmpty = true; @@ -989,14 +1074,19 @@ ExecParallelHashJoinOuterGetTuple(PlanState *outerNode, while (!TupIsNull(slot)) { + bool isnull; + ExprContext *econtext = hjstate->js.ps.ps_ExprContext; econtext->ecxt_outertuple = slot; - if (ExecHashGetHashValue(hashtable, econtext, - hjstate->hj_OuterHashKeys, - true, /* outer tuple */ - HJ_FILL_OUTER(hjstate), - hashvalue)) + + ResetExprContext(econtext); + + *hashvalue = DatumGetUInt32(ExecEvalExprSwitchContext(hjstate->hj_OuterHash, + econtext, + &isnull)); + + if (!isnull) return slot; /* @@ -1421,10 +1511,11 @@ ExecReScanHashJoin(HashJoinState *node) /* * Okay to reuse the hash table; needn't rescan inner, either. * - * However, if it's a right/right-anti/full join, we'd better - * reset the inner-tuple match flags contained in the table. + * However, if it's a right/right-anti/right-semi/full join, we'd + * better reset the inner-tuple match flags contained in the + * table. */ - if (HJ_FILL_INNER(node)) + if (HJ_FILL_INNER(node) || node->js.jointype == JOIN_RIGHT_SEMI) ExecHashTableResetMatchFlags(node->hj_HashTable); /* @@ -1518,15 +1609,20 @@ ExecParallelHashJoinPartitionOuter(HashJoinState *hjstate) /* Execute outer plan, writing all tuples to shared tuplestores. */ for (;;) { + bool isnull; + slot = ExecProcNode(outerState); if (TupIsNull(slot)) break; econtext->ecxt_outertuple = slot; - if (ExecHashGetHashValue(hashtable, econtext, - hjstate->hj_OuterHashKeys, - true, /* outer tuple */ - HJ_FILL_OUTER(hjstate), - &hashvalue)) + + ResetExprContext(econtext); + + hashvalue = DatumGetUInt32(ExecEvalExprSwitchContext(hjstate->hj_OuterHash, + econtext, + &isnull)); + + if (!isnull) { int batchno; int bucketno; @@ -1618,8 +1714,13 @@ void ExecHashJoinReInitializeDSM(HashJoinState *state, ParallelContext *pcxt) { int plan_node_id = state->js.ps.plan->plan_node_id; - ParallelHashJoinState *pstate = - shm_toc_lookup(pcxt->toc, plan_node_id, false); + ParallelHashJoinState *pstate; + + /* Nothing to do if we failed to create a DSM segment. */ + if (pcxt->seg == NULL) + return; + + pstate = shm_toc_lookup(pcxt->toc, plan_node_id, false); /* * It would be possible to reuse the shared hash table in single-batch diff --git a/src/backend/executor/nodeIncrementalSort.c b/src/backend/executor/nodeIncrementalSort.c index 2ce5ed5ec8cd4..975b0397e7aa8 100644 --- a/src/backend/executor/nodeIncrementalSort.c +++ b/src/backend/executor/nodeIncrementalSort.c @@ -3,7 +3,7 @@ * nodeIncrementalSort.c * Routines to handle incremental sorting of relations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 612c6738950e1..f464cca9507a5 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -3,7 +3,7 @@ * nodeIndexonlyscan.c * Routines to support index-only scans * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -92,6 +92,7 @@ IndexOnlyNext(IndexOnlyScanState *node) scandesc = index_beginscan(node->ss.ss_currentRelation, node->ioss_RelationDesc, estate->es_snapshot, + &node->ioss_Instrument, node->ioss_NumScanKeys, node->ioss_NumOrderByKeys); @@ -413,6 +414,27 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node) node->ioss_VMBuffer = InvalidBuffer; } + /* + * When ending a parallel worker, copy the statistics gathered by the + * worker back into shared memory so that it can be picked up by the main + * process to report in EXPLAIN ANALYZE + */ + if (node->ioss_SharedInfo != NULL && IsParallelWorker()) + { + IndexScanInstrumentation *winstrument; + + Assert(ParallelWorkerNumber <= node->ioss_SharedInfo->num_workers); + winstrument = &node->ioss_SharedInfo->winstrument[ParallelWorkerNumber]; + + /* + * We have to accumulate the stats rather than performing a memcpy. + * When a Gather/GatherMerge node finishes it will perform planner + * shutdown on the workers. On rescan it will spin up new workers + * which will have a new IndexOnlyScanState and zeroed stats. + */ + winstrument->nsearches += node->ioss_Instrument.nsearches; + } + /* * close the index relation (no-op if we didn't open it) */ @@ -707,11 +729,21 @@ ExecIndexOnlyScanEstimate(IndexOnlyScanState *node, ParallelContext *pcxt) { EState *estate = node->ss.ps.state; + bool instrument = (node->ss.ps.instrument != NULL); + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc, node->ioss_NumScanKeys, node->ioss_NumOrderByKeys, - estate->es_snapshot); + estate->es_snapshot, + instrument, parallel_aware, + pcxt->nworkers); shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen); shm_toc_estimate_keys(&pcxt->estimator, 1); } @@ -728,16 +760,33 @@ ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node, { EState *estate = node->ss.ps.state; ParallelIndexScanDesc piscan; + bool instrument = node->ss.ps.instrument != NULL; + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } piscan = shm_toc_allocate(pcxt->toc, node->ioss_PscanLen); index_parallelscan_initialize(node->ss.ss_currentRelation, node->ioss_RelationDesc, estate->es_snapshot, - piscan); + instrument, parallel_aware, pcxt->nworkers, + &node->ioss_SharedInfo, piscan); shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan); + + if (!parallel_aware) + { + /* Only here to initialize SharedInfo in DSM */ + return; + } + node->ioss_ScanDesc = index_beginscan_parallel(node->ss.ss_currentRelation, node->ioss_RelationDesc, + &node->ioss_Instrument, node->ioss_NumScanKeys, node->ioss_NumOrderByKeys, piscan); @@ -764,6 +813,7 @@ void ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node, ParallelContext *pcxt) { + Assert(node->ss.ps.plan->parallel_aware); index_parallelrescan(node->ioss_ScanDesc); } @@ -778,11 +828,31 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, ParallelWorkerContext *pwcxt) { ParallelIndexScanDesc piscan; + bool instrument = node->ss.ps.instrument != NULL; + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } piscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); + + if (instrument) + node->ioss_SharedInfo = (SharedIndexScanInstrumentation *) + OffsetToPointer(piscan, piscan->ps_offset_ins); + + if (!parallel_aware) + { + /* Only here to set up worker node's SharedInfo */ + return; + } + node->ioss_ScanDesc = index_beginscan_parallel(node->ss.ss_currentRelation, node->ioss_RelationDesc, + &node->ioss_Instrument, node->ioss_NumScanKeys, node->ioss_NumOrderByKeys, piscan); @@ -797,3 +867,25 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, node->ioss_ScanKeys, node->ioss_NumScanKeys, node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); } + +/* ---------------------------------------------------------------- + * ExecIndexOnlyScanRetrieveInstrumentation + * + * Transfer index-only scan statistics from DSM to private memory. + * ---------------------------------------------------------------- + */ +void +ExecIndexOnlyScanRetrieveInstrumentation(IndexOnlyScanState *node) +{ + SharedIndexScanInstrumentation *SharedInfo = node->ioss_SharedInfo; + size_t size; + + if (SharedInfo == NULL) + return; + + /* Create a copy of SharedInfo in backend-local memory */ + size = offsetof(SharedIndexScanInstrumentation, winstrument) + + SharedInfo->num_workers * sizeof(IndexScanInstrumentation); + node->ioss_SharedInfo = palloc(size); + memcpy(node->ioss_SharedInfo, SharedInfo, size); +} diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 8000feff4c9f9..7fcaa37fe6253 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -3,7 +3,7 @@ * nodeIndexscan.c * Routines to support indexed scans of relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -109,6 +109,7 @@ IndexNext(IndexScanState *node) scandesc = index_beginscan(node->ss.ss_currentRelation, node->iss_RelationDesc, estate->es_snapshot, + &node->iss_Instrument, node->iss_NumScanKeys, node->iss_NumOrderByKeys); @@ -204,6 +205,7 @@ IndexNextWithReorder(IndexScanState *node) scandesc = index_beginscan(node->ss.ss_currentRelation, node->iss_RelationDesc, estate->es_snapshot, + &node->iss_Instrument, node->iss_NumScanKeys, node->iss_NumOrderByKeys); @@ -793,6 +795,27 @@ ExecEndIndexScan(IndexScanState *node) indexRelationDesc = node->iss_RelationDesc; indexScanDesc = node->iss_ScanDesc; + /* + * When ending a parallel worker, copy the statistics gathered by the + * worker back into shared memory so that it can be picked up by the main + * process to report in EXPLAIN ANALYZE + */ + if (node->iss_SharedInfo != NULL && IsParallelWorker()) + { + IndexScanInstrumentation *winstrument; + + Assert(ParallelWorkerNumber <= node->iss_SharedInfo->num_workers); + winstrument = &node->iss_SharedInfo->winstrument[ParallelWorkerNumber]; + + /* + * We have to accumulate the stats rather than performing a memcpy. + * When a Gather/GatherMerge node finishes it will perform planner + * shutdown on the workers. On rescan it will spin up new workers + * which will have a new IndexOnlyScanState and zeroed stats. + */ + winstrument->nsearches += node->iss_Instrument.nsearches; + } + /* * close the index relation (no-op if we didn't open it) */ @@ -1331,10 +1354,10 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, varattno = ((Var *) leftop)->varattno; /* - * We have to look up the operator's associated btree support + * We have to look up the operator's associated support * function */ - if (index->rd_rel->relam != BTREE_AM_OID || + if (!index->rd_indam->amcanorder || varattno < 1 || varattno > indnkeyatts) elog(ERROR, "bogus RowCompare index qualification"); opfamily = index->rd_opfamily[varattno - 1]; @@ -1344,7 +1367,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, &op_lefttype, &op_righttype); - if (op_strategy != rc->rctype) + if (op_strategy != rc->cmptype) elog(ERROR, "RowCompare index qualification contains wrong operator"); opfuncid = get_opfamily_proc(opfamily, @@ -1421,7 +1444,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, MemSet(this_scan_key, 0, sizeof(ScanKeyData)); this_scan_key->sk_flags = SK_ROW_HEADER; this_scan_key->sk_attno = first_sub_key->sk_attno; - this_scan_key->sk_strategy = rc->rctype; + this_scan_key->sk_strategy = rc->cmptype; /* sk_subtype, sk_collation, sk_func not used in a header */ this_scan_key->sk_argument = PointerGetDatum(first_sub_key); } @@ -1642,11 +1665,21 @@ ExecIndexScanEstimate(IndexScanState *node, ParallelContext *pcxt) { EState *estate = node->ss.ps.state; + bool instrument = node->ss.ps.instrument != NULL; + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } node->iss_PscanLen = index_parallelscan_estimate(node->iss_RelationDesc, node->iss_NumScanKeys, node->iss_NumOrderByKeys, - estate->es_snapshot); + estate->es_snapshot, + instrument, parallel_aware, + pcxt->nworkers); shm_toc_estimate_chunk(&pcxt->estimator, node->iss_PscanLen); shm_toc_estimate_keys(&pcxt->estimator, 1); } @@ -1663,16 +1696,33 @@ ExecIndexScanInitializeDSM(IndexScanState *node, { EState *estate = node->ss.ps.state; ParallelIndexScanDesc piscan; + bool instrument = node->ss.ps.instrument != NULL; + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen); index_parallelscan_initialize(node->ss.ss_currentRelation, node->iss_RelationDesc, estate->es_snapshot, - piscan); + instrument, parallel_aware, pcxt->nworkers, + &node->iss_SharedInfo, piscan); shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan); + + if (!parallel_aware) + { + /* Only here to initialize SharedInfo in DSM */ + return; + } + node->iss_ScanDesc = index_beginscan_parallel(node->ss.ss_currentRelation, node->iss_RelationDesc, + &node->iss_Instrument, node->iss_NumScanKeys, node->iss_NumOrderByKeys, piscan); @@ -1697,6 +1747,7 @@ void ExecIndexScanReInitializeDSM(IndexScanState *node, ParallelContext *pcxt) { + Assert(node->ss.ps.plan->parallel_aware); index_parallelrescan(node->iss_ScanDesc); } @@ -1711,11 +1762,31 @@ ExecIndexScanInitializeWorker(IndexScanState *node, ParallelWorkerContext *pwcxt) { ParallelIndexScanDesc piscan; + bool instrument = node->ss.ps.instrument != NULL; + bool parallel_aware = node->ss.ps.plan->parallel_aware; + + if (!instrument && !parallel_aware) + { + /* No DSM required by the scan */ + return; + } piscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false); + + if (instrument) + node->iss_SharedInfo = (SharedIndexScanInstrumentation *) + OffsetToPointer(piscan, piscan->ps_offset_ins); + + if (!parallel_aware) + { + /* Only here to set up worker node's SharedInfo */ + return; + } + node->iss_ScanDesc = index_beginscan_parallel(node->ss.ss_currentRelation, node->iss_RelationDesc, + &node->iss_Instrument, node->iss_NumScanKeys, node->iss_NumOrderByKeys, piscan); @@ -1729,3 +1800,25 @@ ExecIndexScanInitializeWorker(IndexScanState *node, node->iss_ScanKeys, node->iss_NumScanKeys, node->iss_OrderByKeys, node->iss_NumOrderByKeys); } + +/* ---------------------------------------------------------------- + * ExecIndexScanRetrieveInstrumentation + * + * Transfer index scan statistics from DSM to private memory. + * ---------------------------------------------------------------- + */ +void +ExecIndexScanRetrieveInstrumentation(IndexScanState *node) +{ + SharedIndexScanInstrumentation *SharedInfo = node->iss_SharedInfo; + size_t size; + + if (SharedInfo == NULL) + return; + + /* Create a copy of SharedInfo in backend-local memory */ + size = offsetof(SharedIndexScanInstrumentation, winstrument) + + SharedInfo->num_workers * sizeof(IndexScanInstrumentation); + node->iss_SharedInfo = palloc(size); + memcpy(node->iss_SharedInfo, SharedInfo, size); +} diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index e6f1fb15629fe..f957da4470e7a 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -3,7 +3,7 @@ * nodeLimit.c * Routines to handle limiting of query results where appropriate * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index 41754ddfea9f5..a8afbf93b4882 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -3,7 +3,7 @@ * nodeLockRows.c * Routines to handle FOR UPDATE/FOR SHARE row locking * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -347,8 +347,13 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) ExecRowMark *erm; ExecAuxRowMark *aerm; - /* ignore "parent" rowmarks; they are irrelevant at runtime */ - if (rc->isParent) + /* + * Ignore "parent" rowmarks, because they are irrelevant at runtime. + * Also ignore the rowmarks belonging to child tables that have been + * pruned in ExecDoInitialPruning(). + */ + if (rc->isParent || + !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; /* find ExecRowMark and build ExecAuxRowMark */ diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 22e1787fbdd8d..9798bb753651e 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -3,7 +3,7 @@ * nodeMaterial.c * Routines to handle materialization nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c index df8e3fff0824b..609deb12afb2a 100644 --- a/src/backend/executor/nodeMemoize.c +++ b/src/backend/executor/nodeMemoize.c @@ -3,7 +3,7 @@ * nodeMemoize.c * Routines to handle caching of results from parameterized nodes * - * Portions Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2021-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -175,10 +175,10 @@ MemoizeHash_hash(struct memoize_hash *tb, const MemoizeKey *key) if (!pslot->tts_isnull[i]) /* treat nulls as having hash key 0 */ { - Form_pg_attribute attr; + CompactAttribute *attr; uint32 hkey; - attr = TupleDescAttr(pslot->tts_tupleDescriptor, i); + attr = TupleDescCompactAttr(pslot->tts_tupleDescriptor, i); hkey = datum_image_hash(pslot->tts_values[i], attr->attbyval, attr->attlen); @@ -242,7 +242,7 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1, for (int i = 0; i < numkeys; i++) { - Form_pg_attribute attr; + CompactAttribute *attr; if (tslot->tts_isnull[i] != pslot->tts_isnull[i]) { @@ -255,7 +255,7 @@ MemoizeHash_equal(struct memoize_hash *tb, const MemoizeKey *key1, continue; /* perform binary comparison on the two datums */ - attr = TupleDescAttr(tslot->tts_tupleDescriptor, i); + attr = TupleDescCompactAttr(tslot->tts_tupleDescriptor, i); if (!datum_image_eq(tslot->tts_values[i], pslot->tts_values[i], attr->attbyval, attr->attlen)) { diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index e1b9b984a7a32..405e8f942857f 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -3,7 +3,7 @@ * nodeMergeAppend.c * routines to handle MergeAppend nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -66,6 +66,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) { MergeAppendState *mergestate = makeNode(MergeAppendState); PlanState **mergeplanstates; + const TupleTableSlotOps *mergeops; Bitmapset *validsubplans; int nplans; int i, @@ -82,7 +83,7 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) mergestate->ps.ExecProcNode = ExecMergeAppend; /* If run-time partition pruning is enabled, then set that up now */ - if (node->part_prune_info != NULL) + if (node->part_prune_index >= 0) { PartitionPruneState *prunestate; @@ -91,10 +92,11 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) * subplans to initialize (validsubplans) by taking into account the * result of performing initial pruning if any. */ - prunestate = ExecInitPartitionPruning(&mergestate->ps, - list_length(node->mergeplans), - node->part_prune_info, - &validsubplans); + prunestate = ExecInitPartitionExecPruning(&mergestate->ps, + list_length(node->mergeplans), + node->part_prune_index, + node->apprelids, + &validsubplans); mergestate->ms_prune_state = prunestate; nplans = bms_num_members(validsubplans); @@ -128,18 +130,6 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) mergestate->ms_heap = binaryheap_allocate(nplans, heap_compare_slots, mergestate); - /* - * Miscellaneous initialization - * - * MergeAppend nodes do have Result slots, which hold pointers to tuples, - * so we have to initialize them. FIXME - */ - ExecInitResultTupleSlotTL(&mergestate->ps, &TTSOpsVirtual); - - /* node returns slots from each of its subnodes, therefore not fixed */ - mergestate->ps.resultopsset = true; - mergestate->ps.resultopsfixed = false; - /* * call ExecInitNode on each of the valid plans to be executed and save * the results into the mergeplanstates array. @@ -153,6 +143,31 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) mergeplanstates[j++] = ExecInitNode(initNode, estate, eflags); } + /* + * Initialize MergeAppend's result tuple type and slot. If the child + * plans all produce the same fixed slot type, we can use that slot type; + * otherwise make a virtual slot. (Note that the result slot itself is + * used only to return a null tuple at end of execution; real tuples are + * returned to the caller in the children's own result slots. What we are + * doing here is allowing the parent plan node to optimize if the + * MergeAppend will return only one kind of slot.) + */ + mergeops = ExecGetCommonSlotOps(mergeplanstates, j); + if (mergeops != NULL) + { + ExecInitResultTupleSlotTL(&mergestate->ps, mergeops); + } + else + { + ExecInitResultTupleSlotTL(&mergestate->ps, &TTSOpsVirtual); + /* show that the output slot type is not fixed */ + mergestate->ps.resultopsset = true; + mergestate->ps.resultopsfixed = false; + } + + /* + * Miscellaneous initialization + */ mergestate->ps.ps_ProjInfo = NULL; /* @@ -218,7 +233,7 @@ ExecMergeAppend(PlanState *pstate) */ if (node->ms_valid_subplans == NULL) node->ms_valid_subplans = - ExecFindMatchingSubPlans(node->ms_prune_state, false); + ExecFindMatchingSubPlans(node->ms_prune_state, false, NULL); /* * First time through: pull the first tuple from each valid subplan, diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 29c54fcd7538b..a233313128acb 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -3,7 +3,7 @@ * nodeMergejoin.c * routines supporting merge joins * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -175,7 +175,7 @@ static MergeJoinClause MJExamineQuals(List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, - int *mergestrategies, + bool *mergereversals, bool *mergenullsfirst, PlanState *parent) { @@ -193,7 +193,7 @@ MJExamineQuals(List *mergeclauses, MergeJoinClause clause = &clauses[iClause]; Oid opfamily = mergefamilies[iClause]; Oid collation = mergecollations[iClause]; - StrategyNumber opstrategy = mergestrategies[iClause]; + bool reversed = mergereversals[iClause]; bool nulls_first = mergenullsfirst[iClause]; int op_strategy; Oid op_lefttype; @@ -212,12 +212,7 @@ MJExamineQuals(List *mergeclauses, /* Set up sort support data */ clause->ssup.ssup_cxt = CurrentMemoryContext; clause->ssup.ssup_collation = collation; - if (opstrategy == BTLessStrategyNumber) - clause->ssup.ssup_reverse = false; - else if (opstrategy == BTGreaterStrategyNumber) - clause->ssup.ssup_reverse = true; - else /* planner screwed up */ - elog(ERROR, "unsupported mergejoin strategy %d", opstrategy); + clause->ssup.ssup_reverse = reversed; clause->ssup.ssup_nulls_first = nulls_first; /* Extract the operator's declared left/right datatypes */ @@ -225,7 +220,7 @@ MJExamineQuals(List *mergeclauses, &op_strategy, &op_lefttype, &op_righttype); - if (op_strategy != BTEqualStrategyNumber) /* should not happen */ + if (IndexAmTranslateStrategy(op_strategy, get_opfamily_method(opfamily), opfamily, true) != COMPARE_EQ) /* should not happen */ elog(ERROR, "cannot merge using non-equality operator %u", qual->opno); @@ -1608,7 +1603,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses, node->mergeFamilies, node->mergeCollations, - node->mergeStrategies, + node->mergeReversals, node->mergeNullsFirst, (PlanState *) mergestate); diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 4913e493199db..54da8e7995bd3 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -3,7 +3,7 @@ * nodeModifyTable.c * routines to handle ModifyTable nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -64,6 +64,7 @@ #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" #include "rewrite/rewriteHandler.h" +#include "rewrite/rewriteManip.h" #include "storage/lmgr.h" #include "utils/builtins.h" #include "utils/datum.h" @@ -101,6 +102,13 @@ typedef struct ModifyTableContext */ TM_FailureData tmfd; + /* + * The tuple deleted when doing a cross-partition UPDATE with a RETURNING + * clause that refers to OLD columns (converted to the root's tuple + * descriptor). + */ + TupleTableSlot *cpDeletedSlot; + /* * The tuple projected by the INSERT's RETURNING clause, when doing a * cross-partition UPDATE @@ -205,33 +213,53 @@ ExecCheckPlanOutput(Relation resultRel, List *targetList) attr = TupleDescAttr(resultDesc, attno); attno++; - if (!attr->attisdropped) + /* + * Special cases here should match planner's expand_insert_targetlist. + */ + if (attr->attisdropped) { - /* Normal case: demand type match */ - if (exprType((Node *) tle->expr) != attr->atttypid) + /* + * For a dropped column, we can't check atttypid (it's likely 0). + * In any case the planner has most likely inserted an INT4 null. + * What we insist on is just *some* NULL constant. + */ + if (!IsA(tle->expr, Const) || + !((Const *) tle->expr)->constisnull) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table row type and query-specified row type do not match"), - errdetail("Table has type %s at ordinal position %d, but query expects %s.", - format_type_be(attr->atttypid), - attno, - format_type_be(exprType((Node *) tle->expr))))); + errdetail("Query provides a value for a dropped column at ordinal position %d.", + attno))); } - else + else if (attr->attgenerated) { /* - * For a dropped column, we can't check atttypid (it's likely 0). - * In any case the planner has most likely inserted an INT4 null. - * What we insist on is just *some* NULL constant. + * For a generated column, the planner will have inserted a null + * of the column's base type (to avoid possibly failing on domain + * not-null constraints). It doesn't seem worth insisting on that + * exact type though, since a null value is type-independent. As + * above, just insist on *some* NULL constant. */ if (!IsA(tle->expr, Const) || !((Const *) tle->expr)->constisnull) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table row type and query-specified row type do not match"), - errdetail("Query provides a value for a dropped column at ordinal position %d.", + errdetail("Query provides a value for a generated column at ordinal position %d.", attno))); } + else + { + /* Normal case: demand type match */ + if (exprType((Node *) tle->expr) != attr->atttypid) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("table row type and query-specified row type do not match"), + errdetail("Table has type %s at ordinal position %d, but query expects %s.", + format_type_be(attr->atttypid), + attno, + format_type_be(exprType((Node *) tle->expr))))); + } } if (attno != resultDesc->natts) ereport(ERROR, @@ -243,34 +271,81 @@ ExecCheckPlanOutput(Relation resultRel, List *targetList) /* * ExecProcessReturning --- evaluate a RETURNING list * + * context: context for the ModifyTable operation * resultRelInfo: current result rel - * tupleSlot: slot holding tuple actually inserted/updated/deleted + * cmdType: operation/merge action performed (INSERT, UPDATE, or DELETE) + * oldSlot: slot holding old tuple deleted or updated + * newSlot: slot holding new tuple inserted or updated * planSlot: slot holding tuple returned by top subplan node * - * Note: If tupleSlot is NULL, the FDW should have already provided econtext's - * scan tuple. + * Note: If oldSlot and newSlot are NULL, the FDW should have already provided + * econtext's scan tuple and its old & new tuples are not needed (FDW direct- + * modify is disabled if the RETURNING list refers to any OLD/NEW values). * * Returns a slot holding the result tuple */ static TupleTableSlot * -ExecProcessReturning(ResultRelInfo *resultRelInfo, - TupleTableSlot *tupleSlot, +ExecProcessReturning(ModifyTableContext *context, + ResultRelInfo *resultRelInfo, + CmdType cmdType, + TupleTableSlot *oldSlot, + TupleTableSlot *newSlot, TupleTableSlot *planSlot) { + EState *estate = context->estate; ProjectionInfo *projectReturning = resultRelInfo->ri_projectReturning; ExprContext *econtext = projectReturning->pi_exprContext; /* Make tuple and any needed join variables available to ExecProject */ - if (tupleSlot) - econtext->ecxt_scantuple = tupleSlot; + switch (cmdType) + { + case CMD_INSERT: + case CMD_UPDATE: + /* return new tuple by default */ + if (newSlot) + econtext->ecxt_scantuple = newSlot; + break; + + case CMD_DELETE: + /* return old tuple by default */ + if (oldSlot) + econtext->ecxt_scantuple = oldSlot; + break; + + default: + elog(ERROR, "unrecognized commandType: %d", (int) cmdType); + } econtext->ecxt_outertuple = planSlot; + /* Make old/new tuples available to ExecProject, if required */ + if (oldSlot) + econtext->ecxt_oldtuple = oldSlot; + else if (projectReturning->pi_state.flags & EEO_FLAG_HAS_OLD) + econtext->ecxt_oldtuple = ExecGetAllNullSlot(estate, resultRelInfo); + else + econtext->ecxt_oldtuple = NULL; /* No references to OLD columns */ + + if (newSlot) + econtext->ecxt_newtuple = newSlot; + else if (projectReturning->pi_state.flags & EEO_FLAG_HAS_NEW) + econtext->ecxt_newtuple = ExecGetAllNullSlot(estate, resultRelInfo); + else + econtext->ecxt_newtuple = NULL; /* No references to NEW columns */ + /* - * RETURNING expressions might reference the tableoid column, so - * reinitialize tts_tableOid before evaluating them. + * Tell ExecProject whether or not the OLD/NEW rows actually exist. This + * information is required to evaluate ReturningExpr nodes and also in + * ExecEvalSysVar() and ExecEvalWholeRowVar(). */ - econtext->ecxt_scantuple->tts_tableOid = - RelationGetRelid(resultRelInfo->ri_RelationDesc); + if (oldSlot == NULL) + projectReturning->pi_state.flags |= EEO_FLAG_OLD_IS_NULL; + else + projectReturning->pi_state.flags &= ~EEO_FLAG_OLD_IS_NULL; + + if (newSlot == NULL) + projectReturning->pi_state.flags |= EEO_FLAG_NEW_IS_NULL; + else + projectReturning->pi_state.flags &= ~EEO_FLAG_NEW_IS_NULL; /* Compute the RETURNING expressions */ return ExecProject(projectReturning); @@ -337,11 +412,14 @@ ExecCheckTIDVisible(EState *estate, } /* - * Initialize to compute stored generated columns for a tuple + * Initialize generated columns handling for a tuple + * + * This fills the resultRelInfo's ri_GeneratedExprsI/ri_NumGeneratedNeededI or + * ri_GeneratedExprsU/ri_NumGeneratedNeededU fields, depending on cmdtype. + * This is used only for stored generated columns. * - * This fills the resultRelInfo's ri_GeneratedExprsI/ri_NumGeneratedNeededI - * or ri_GeneratedExprsU/ri_NumGeneratedNeededU fields, depending on cmdtype. * If cmdType == CMD_UPDATE, the ri_extraUpdatedCols field is filled too. + * This is used by both stored and virtual generated columns. * * Note: usually, a given query would need only one of ri_GeneratedExprsI and * ri_GeneratedExprsU per result rel; but MERGE can need both, and so can @@ -349,9 +427,9 @@ ExecCheckTIDVisible(EState *estate, * UPDATE and INSERT actions. */ void -ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, - EState *estate, - CmdType cmdtype) +ExecInitGenerated(ResultRelInfo *resultRelInfo, + EState *estate, + CmdType cmdtype) { Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); @@ -362,7 +440,7 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, MemoryContext oldContext; /* Nothing to do if no generated columns */ - if (!(tupdesc->constr && tupdesc->constr->has_generated_stored)) + if (!(tupdesc->constr && (tupdesc->constr->has_generated_stored || tupdesc->constr->has_generated_virtual))) return; /* @@ -388,7 +466,9 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, for (int i = 0; i < natts; i++) { - if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED) + char attgenerated = TupleDescAttr(tupdesc, i)->attgenerated; + + if (attgenerated) { Expr *expr; @@ -413,8 +493,11 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, } /* No luck, so prepare the expression for execution */ - ri_GeneratedExprs[i] = ExecPrepareExpr(expr, estate); - ri_NumGeneratedNeeded++; + if (attgenerated == ATTRIBUTE_GENERATED_STORED) + { + ri_GeneratedExprs[i] = ExecPrepareExpr(expr, estate); + ri_NumGeneratedNeeded++; + } /* If UPDATE, mark column in resultRelInfo->ri_extraUpdatedCols */ if (cmdtype == CMD_UPDATE) @@ -424,6 +507,13 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, } } + if (ri_NumGeneratedNeeded == 0) + { + /* didn't need it after all */ + pfree(ri_GeneratedExprs); + ri_GeneratedExprs = NULL; + } + /* Save in appropriate set of fields */ if (cmdtype == CMD_UPDATE) { @@ -432,6 +522,8 @@ ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, resultRelInfo->ri_GeneratedExprsU = ri_GeneratedExprs; resultRelInfo->ri_NumGeneratedNeededU = ri_NumGeneratedNeeded; + + resultRelInfo->ri_extraUpdatedCols_valid = true; } else { @@ -472,7 +564,7 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, if (cmdtype == CMD_UPDATE) { if (resultRelInfo->ri_GeneratedExprsU == NULL) - ExecInitStoredGenerated(resultRelInfo, estate, cmdtype); + ExecInitGenerated(resultRelInfo, estate, cmdtype); if (resultRelInfo->ri_NumGeneratedNeededU == 0) return; ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsU; @@ -480,7 +572,7 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, else { if (resultRelInfo->ri_GeneratedExprsI == NULL) - ExecInitStoredGenerated(resultRelInfo, estate, cmdtype); + ExecInitGenerated(resultRelInfo, estate, cmdtype); /* Early exit is impossible given the prior Assert */ Assert(resultRelInfo->ri_NumGeneratedNeededI > 0); ri_GeneratedExprs = resultRelInfo->ri_GeneratedExprsI; @@ -496,14 +588,14 @@ ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, for (int i = 0; i < natts; i++) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, i); if (ri_GeneratedExprs[i]) { Datum val; bool isnull; - Assert(attr->attgenerated == ATTRIBUTE_GENERATED_STORED); + Assert(TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED); econtext->ecxt_scantuple = slot; @@ -636,7 +728,7 @@ ExecInitUpdateProjection(ModifyTableState *mtstate, Assert(whichrel >= 0 && whichrel < mtstate->mt_nrels); } - updateColnos = (List *) list_nth(node->updateColnosLists, whichrel); + updateColnos = (List *) list_nth(mtstate->mt_updateColnosLists, whichrel); /* * For UPDATE, we use the old tuple to fill up missing values in the tuple @@ -1019,9 +1111,11 @@ ExecInsert(ModifyTableContext *context, /* Perform a speculative insertion. */ uint32 specToken; ItemPointerData conflictTid; + ItemPointerData invalidItemPtr; bool specConflict; List *arbiterIndexes; + ItemPointerSetInvalid(&invalidItemPtr); arbiterIndexes = resultRelInfo->ri_onConflictArbiterIndexes; /* @@ -1041,7 +1135,8 @@ ExecInsert(ModifyTableContext *context, CHECK_FOR_INTERRUPTS(); specConflict = false; if (!ExecCheckIndexConstraints(resultRelInfo, slot, estate, - &conflictTid, arbiterIndexes)) + &conflictTid, &invalidItemPtr, + arbiterIndexes)) { /* committed conflict tuple found */ if (onconflict == ONCONFLICT_UPDATE) @@ -1201,7 +1296,56 @@ ExecInsert(ModifyTableContext *context, /* Process RETURNING if present */ if (resultRelInfo->ri_projectReturning) - result = ExecProcessReturning(resultRelInfo, slot, planSlot); + { + TupleTableSlot *oldSlot = NULL; + + /* + * If this is part of a cross-partition UPDATE, and the RETURNING list + * refers to any OLD columns, ExecDelete() will have saved the tuple + * deleted from the original partition, which we must use here to + * compute the OLD column values. Otherwise, all OLD column values + * will be NULL. + */ + if (context->cpDeletedSlot) + { + TupleConversionMap *tupconv_map; + + /* + * Convert the OLD tuple to the new partition's format/slot, if + * needed. Note that ExecDelete() already converted it to the + * root's partition's format/slot. + */ + oldSlot = context->cpDeletedSlot; + tupconv_map = ExecGetRootToChildMap(resultRelInfo, estate); + if (tupconv_map != NULL) + { + oldSlot = execute_attr_map_slot(tupconv_map->attrMap, + oldSlot, + ExecGetReturningSlot(estate, + resultRelInfo)); + + oldSlot->tts_tableOid = context->cpDeletedSlot->tts_tableOid; + ItemPointerCopy(&context->cpDeletedSlot->tts_tid, &oldSlot->tts_tid); + } + } + + result = ExecProcessReturning(context, resultRelInfo, CMD_INSERT, + oldSlot, slot, planSlot); + + /* + * For a cross-partition UPDATE, release the old tuple, first making + * sure that the result slot has a local copy of any pass-by-reference + * values. + */ + if (context->cpDeletedSlot) + { + ExecMaterializeSlot(result); + ExecClearTuple(oldSlot); + if (context->cpDeletedSlot != oldSlot) + ExecClearTuple(context->cpDeletedSlot); + context->cpDeletedSlot = NULL; + } + } if (inserted_tuple) *inserted_tuple = slot; @@ -1439,6 +1583,7 @@ ExecDelete(ModifyTableContext *context, Relation resultRelationDesc = resultRelInfo->ri_RelationDesc; TupleTableSlot *slot = NULL; TM_Result result; + bool saveOld; if (tupleDeleted) *tupleDeleted = false; @@ -1673,8 +1818,17 @@ ExecDelete(ModifyTableContext *context, ExecDeleteEpilogue(context, resultRelInfo, tupleid, oldtuple, changingPart); - /* Process RETURNING if present and if requested */ - if (processReturning && resultRelInfo->ri_projectReturning) + /* + * Process RETURNING if present and if requested. + * + * If this is part of a cross-partition UPDATE, and the RETURNING list + * refers to any OLD column values, save the old tuple here for later + * processing of the RETURNING list by ExecInsert(). + */ + saveOld = changingPart && resultRelInfo->ri_projectReturning && + resultRelInfo->ri_projectReturning->pi_state.flags & EEO_FLAG_HAS_OLD; + + if (resultRelInfo->ri_projectReturning && (processReturning || saveOld)) { /* * We have to put the target tuple into a slot, which means first we @@ -1702,7 +1856,41 @@ ExecDelete(ModifyTableContext *context, } } - rslot = ExecProcessReturning(resultRelInfo, slot, context->planSlot); + /* + * If required, save the old tuple for later processing of the + * RETURNING list by ExecInsert(). + */ + if (saveOld) + { + TupleConversionMap *tupconv_map; + + /* + * Convert the tuple into the root partition's format/slot, if + * needed. ExecInsert() will then convert it to the new + * partition's format/slot, if necessary. + */ + tupconv_map = ExecGetChildToRootMap(resultRelInfo); + if (tupconv_map != NULL) + { + ResultRelInfo *rootRelInfo = context->mtstate->rootResultRelInfo; + TupleTableSlot *oldSlot = slot; + + slot = execute_attr_map_slot(tupconv_map->attrMap, + slot, + ExecGetReturningSlot(estate, + rootRelInfo)); + + slot->tts_tableOid = oldSlot->tts_tableOid; + ItemPointerCopy(&oldSlot->tts_tid, &slot->tts_tid); + } + + context->cpDeletedSlot = slot; + + return NULL; + } + + rslot = ExecProcessReturning(context, resultRelInfo, CMD_DELETE, + slot, NULL, context->planSlot); /* * Before releasing the target tuple again, make sure rslot has a @@ -1755,6 +1943,7 @@ ExecCrossPartitionUpdate(ModifyTableContext *context, bool tuple_deleted; TupleTableSlot *epqslot = NULL; + context->cpDeletedSlot = NULL; context->cpUpdateReturningSlot = NULL; *retry_slot = NULL; @@ -2255,6 +2444,7 @@ ExecCrossPartitionUpdateForeignKey(ModifyTableContext *context, * the planSlot. oldtuple is passed to foreign table triggers; it is * NULL when the foreign table has no relevant triggers. * + * oldSlot contains the old tuple value. * slot contains the new tuple value to be stored. * planSlot is the output of the ModifyTable's subplan; we use it * to access values from other input tables (for RETURNING), @@ -2267,8 +2457,8 @@ ExecCrossPartitionUpdateForeignKey(ModifyTableContext *context, */ static TupleTableSlot * ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, - ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *slot, - bool canSetTag) + ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *oldSlot, + TupleTableSlot *slot, bool canSetTag) { EState *estate = context->estate; Relation resultRelationDesc = resultRelInfo->ri_RelationDesc; @@ -2321,6 +2511,8 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, } else { + ItemPointerData lockedtid; + /* * If we generate a new candidate tuple after EvalPlanQual testing, we * must loop back here to try again. (We don't need to redo triggers, @@ -2329,6 +2521,7 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * to do them again.) */ redo_act: + lockedtid = *tupleid; result = ExecUpdateAct(context, resultRelInfo, tupleid, oldtuple, slot, canSetTag, &updateCxt); @@ -2383,7 +2576,6 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, { TupleTableSlot *inputslot; TupleTableSlot *epqslot; - TupleTableSlot *oldSlot; if (IsolationUsesXactSnapshot()) ereport(ERROR, @@ -2422,6 +2614,14 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, ExecInitUpdateProjection(context->mtstate, resultRelInfo); + if (resultRelInfo->ri_needLockTagTuple) + { + UnlockTuple(resultRelationDesc, + &lockedtid, InplaceUpdateTupleLock); + LockTuple(resultRelationDesc, + tupleid, InplaceUpdateTupleLock); + } + /* Fetch the most recent version of old tuple. */ oldSlot = resultRelInfo->ri_oldTupleSlot; if (!table_tuple_fetch_row_version(resultRelationDesc, @@ -2490,7 +2690,8 @@ ExecUpdate(ModifyTableContext *context, ResultRelInfo *resultRelInfo, /* Process RETURNING if present */ if (resultRelInfo->ri_projectReturning) - return ExecProcessReturning(resultRelInfo, slot, context->planSlot); + return ExecProcessReturning(context, resultRelInfo, CMD_UPDATE, + oldSlot, slot, context->planSlot); return NULL; } @@ -2526,6 +2727,14 @@ ExecOnConflictUpdate(ModifyTableContext *context, TransactionId xmin; bool isnull; + /* + * Parse analysis should have blocked ON CONFLICT for all system + * relations, which includes these. There's no fundamental obstacle to + * supporting this; we'd just need to handle LOCKTAG_TUPLE like the other + * ExecUpdate() caller. + */ + Assert(!resultRelInfo->ri_needLockTagTuple); + /* Determine lock mode to use */ lockmode = ExecUpdateLockMode(context->estate, resultRelInfo); @@ -2702,16 +2911,23 @@ ExecOnConflictUpdate(ModifyTableContext *context, /* Execute UPDATE with projection */ *returning = ExecUpdate(context, resultRelInfo, - conflictTid, NULL, + conflictTid, NULL, existing, resultRelInfo->ri_onConflict->oc_ProjSlot, canSetTag); /* * Clear out existing tuple, as there might not be another conflict among * the next input rows. Don't want to hold resources till the end of the - * query. + * query. First though, make sure that the returning slot, if any, has a + * local copy of any OLD pass-by-reference values, if it refers to any OLD + * columns. */ + if (*returning != NULL && + resultRelInfo->ri_projectReturning->pi_state.flags & EEO_FLAG_HAS_OLD) + ExecMaterializeSlot(*returning); + ExecClearTuple(existing); + return true; } @@ -2851,6 +3067,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, { ModifyTableState *mtstate = context->mtstate; List **mergeActions = resultRelInfo->ri_MergeActions; + ItemPointerData lockedtid; List *actionStates; TupleTableSlot *newslot = NULL; TupleTableSlot *rslot = NULL; @@ -2887,14 +3104,32 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * target wholerow junk attr. */ Assert(tupleid != NULL || oldtuple != NULL); + ItemPointerSetInvalid(&lockedtid); if (oldtuple != NULL) + { + Assert(!resultRelInfo->ri_needLockTagTuple); ExecForceStoreHeapTuple(oldtuple, resultRelInfo->ri_oldTupleSlot, false); - else if (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc, - tupleid, - SnapshotAny, - resultRelInfo->ri_oldTupleSlot)) - elog(ERROR, "failed to fetch the target tuple"); + } + else + { + if (resultRelInfo->ri_needLockTagTuple) + { + /* + * This locks even for CMD_DELETE, for CMD_NOTHING, and for tuples + * that don't match mas_whenqual. MERGE on system catalogs is a + * minor use case, so don't bother optimizing those. + */ + LockTuple(resultRelInfo->ri_RelationDesc, tupleid, + InplaceUpdateTupleLock); + lockedtid = *tupleid; + } + if (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc, + tupleid, + SnapshotAny, + resultRelInfo->ri_oldTupleSlot)) + elog(ERROR, "failed to fetch the target tuple"); + } /* * Test the join condition. If it's satisfied, perform a MATCHED action. @@ -2966,7 +3201,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, tupleid, NULL, newslot, &result)) { if (result == TM_Ok) - return NULL; /* "do nothing" */ + goto out; /* "do nothing" */ break; /* concurrent update/delete */ } @@ -2977,11 +3212,11 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, { if (!ExecIRUpdateTriggers(estate, resultRelInfo, oldtuple, newslot)) - return NULL; /* "do nothing" */ + goto out; /* "do nothing" */ } else { - /* called table_tuple_fetch_row_version() above */ + /* checked ri_needLockTagTuple above */ Assert(oldtuple == NULL); result = ExecUpdateAct(context, resultRelInfo, tupleid, @@ -3000,7 +3235,8 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, if (updateCxt.crossPartUpdate) { mtstate->mt_merge_updated += 1; - return context->cpUpdateReturningSlot; + rslot = context->cpUpdateReturningSlot; + goto out; } } @@ -3018,7 +3254,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, NULL, NULL, &result)) { if (result == TM_Ok) - return NULL; /* "do nothing" */ + goto out; /* "do nothing" */ break; /* concurrent update/delete */ } @@ -3029,11 +3265,11 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, { if (!ExecIRDeleteTriggers(estate, resultRelInfo, oldtuple)) - return NULL; /* "do nothing" */ + goto out; /* "do nothing" */ } else { - /* called table_tuple_fetch_row_version() above */ + /* checked ri_needLockTagTuple above */ Assert(oldtuple == NULL); result = ExecDeleteAct(context, resultRelInfo, tupleid, @@ -3115,7 +3351,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * let caller handle it under NOT MATCHED [BY TARGET] clauses. */ *matched = false; - return NULL; + goto out; case TM_Updated: { @@ -3189,7 +3425,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * more to do. */ if (TupIsNull(epqslot)) - return NULL; + goto out; /* * If we got a NULL ctid from the subplan, the @@ -3207,6 +3443,15 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * we need to switch to the NOT MATCHED BY * SOURCE case. */ + if (resultRelInfo->ri_needLockTagTuple) + { + if (ItemPointerIsValid(&lockedtid)) + UnlockTuple(resultRelInfo->ri_RelationDesc, &lockedtid, + InplaceUpdateTupleLock); + LockTuple(resultRelInfo->ri_RelationDesc, &context->tmfd.ctid, + InplaceUpdateTupleLock); + lockedtid = context->tmfd.ctid; + } if (!table_tuple_fetch_row_version(resultRelationDesc, &context->tmfd.ctid, SnapshotAny, @@ -3235,7 +3480,7 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * MATCHED [BY TARGET] actions */ *matched = false; - return NULL; + goto out; case TM_SelfModified: @@ -3263,13 +3508,13 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, /* This shouldn't happen */ elog(ERROR, "attempted to update or delete invisible tuple"); - return NULL; + goto out; default: /* see table_tuple_lock call in ExecDelete() */ elog(ERROR, "unexpected table_tuple_lock status: %u", result); - return NULL; + goto out; } } @@ -3287,13 +3532,20 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, switch (commandType) { case CMD_UPDATE: - rslot = ExecProcessReturning(resultRelInfo, newslot, + rslot = ExecProcessReturning(context, + resultRelInfo, + CMD_UPDATE, + resultRelInfo->ri_oldTupleSlot, + newslot, context->planSlot); break; case CMD_DELETE: - rslot = ExecProcessReturning(resultRelInfo, + rslot = ExecProcessReturning(context, + resultRelInfo, + CMD_DELETE, resultRelInfo->ri_oldTupleSlot, + NULL, context->planSlot); break; @@ -3316,6 +3568,10 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, /* * Successfully executed an action or no qualifying action was found. */ +out: + if (ItemPointerIsValid(&lockedtid)) + UnlockTuple(resultRelInfo->ri_RelationDesc, &lockedtid, + InplaceUpdateTupleLock); return rslot; } @@ -3408,14 +3664,15 @@ ExecMergeNotMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo, void ExecInitMerge(ModifyTableState *mtstate, EState *estate) { - ModifyTable *node = (ModifyTable *) mtstate->ps.plan; + List *mergeActionLists = mtstate->mt_mergeActionLists; + List *mergeJoinConditions = mtstate->mt_mergeJoinConditions; ResultRelInfo *rootRelInfo = mtstate->rootResultRelInfo; ResultRelInfo *resultRelInfo; ExprContext *econtext; ListCell *lc; int i; - if (node->mergeActionLists == NIL) + if (mergeActionLists == NIL) return; mtstate->mt_merge_subcommands = 0; @@ -3432,14 +3689,14 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate) * anything here, do so there too. */ i = 0; - foreach(lc, node->mergeActionLists) + foreach(lc, mergeActionLists) { List *mergeActionList = lfirst(lc); Node *joinCondition; TupleDesc relationDesc; ListCell *l; - joinCondition = (Node *) list_nth(node->mergeJoinConditions, i); + joinCondition = (Node *) list_nth(mergeJoinConditions, i); resultRelInfo = mtstate->resultRelInfo + i; i++; relationDesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); @@ -3479,6 +3736,7 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate) switch (action->commandType) { case CMD_INSERT: + /* INSERT actions always use rootRelInfo */ ExecCheckPlanOutput(rootRelInfo->ri_RelationDesc, action->targetList); @@ -3518,9 +3776,23 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate) } else { - /* not partitioned? use the stock relation and slot */ - tgtslot = resultRelInfo->ri_newTupleSlot; - tgtdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + /* + * If the MERGE targets an inherited table, we insert + * into the root table, so we must initialize its + * "new" tuple slot, if not already done, and use its + * relation descriptor for the projection. + * + * For non-inherited tables, rootRelInfo and + * resultRelInfo are the same, and the "new" tuple + * slot will already have been initialized. + */ + if (rootRelInfo->ri_newTupleSlot == NULL) + rootRelInfo->ri_newTupleSlot = + table_slot_create(rootRelInfo->ri_RelationDesc, + &estate->es_tupleTable); + + tgtslot = rootRelInfo->ri_newTupleSlot; + tgtdesc = RelationGetDescr(rootRelInfo->ri_RelationDesc); } action_state->mas_proj = @@ -3548,11 +3820,119 @@ ExecInitMerge(ModifyTableState *mtstate, EState *estate) case CMD_NOTHING: break; default: - elog(ERROR, "unknown operation"); + elog(ERROR, "unknown action in MERGE WHEN clause"); break; } } } + + /* + * If the MERGE targets an inherited table, any INSERT actions will use + * rootRelInfo, and rootRelInfo will not be in the resultRelInfo array. + * Therefore we must initialize its WITH CHECK OPTION constraints and + * RETURNING projection, as ExecInitModifyTable did for the resultRelInfo + * entries. + * + * Note that the planner does not build a withCheckOptionList or + * returningList for the root relation, but as in ExecInitPartitionInfo, + * we can use the first resultRelInfo entry as a reference to calculate + * the attno's for the root table. + */ + if (rootRelInfo != mtstate->resultRelInfo && + rootRelInfo->ri_RelationDesc->rd_rel->relkind != RELKIND_PARTITIONED_TABLE && + (mtstate->mt_merge_subcommands & MERGE_INSERT) != 0) + { + ModifyTable *node = (ModifyTable *) mtstate->ps.plan; + Relation rootRelation = rootRelInfo->ri_RelationDesc; + Relation firstResultRel = mtstate->resultRelInfo[0].ri_RelationDesc; + int firstVarno = mtstate->resultRelInfo[0].ri_RangeTableIndex; + AttrMap *part_attmap = NULL; + bool found_whole_row; + + if (node->withCheckOptionLists != NIL) + { + List *wcoList; + List *wcoExprs = NIL; + + /* There should be as many WCO lists as result rels */ + Assert(list_length(node->withCheckOptionLists) == + list_length(node->resultRelations)); + + /* + * Use the first WCO list as a reference. In the most common case, + * this will be for the same relation as rootRelInfo, and so there + * will be no need to adjust its attno's. + */ + wcoList = linitial(node->withCheckOptionLists); + if (rootRelation != firstResultRel) + { + /* Convert any Vars in it to contain the root's attno's */ + part_attmap = + build_attrmap_by_name(RelationGetDescr(rootRelation), + RelationGetDescr(firstResultRel), + false); + + wcoList = (List *) + map_variable_attnos((Node *) wcoList, + firstVarno, 0, + part_attmap, + RelationGetForm(rootRelation)->reltype, + &found_whole_row); + } + + foreach(lc, wcoList) + { + WithCheckOption *wco = lfirst_node(WithCheckOption, lc); + ExprState *wcoExpr = ExecInitQual(castNode(List, wco->qual), + &mtstate->ps); + + wcoExprs = lappend(wcoExprs, wcoExpr); + } + + rootRelInfo->ri_WithCheckOptions = wcoList; + rootRelInfo->ri_WithCheckOptionExprs = wcoExprs; + } + + if (node->returningLists != NIL) + { + List *returningList; + + /* There should be as many returning lists as result rels */ + Assert(list_length(node->returningLists) == + list_length(node->resultRelations)); + + /* + * Use the first returning list as a reference. In the most common + * case, this will be for the same relation as rootRelInfo, and so + * there will be no need to adjust its attno's. + */ + returningList = linitial(node->returningLists); + if (rootRelation != firstResultRel) + { + /* Convert any Vars in it to contain the root's attno's */ + if (part_attmap == NULL) + part_attmap = + build_attrmap_by_name(RelationGetDescr(rootRelation), + RelationGetDescr(firstResultRel), + false); + + returningList = (List *) + map_variable_attnos((Node *) returningList, + firstVarno, 0, + part_attmap, + RelationGetForm(rootRelation)->reltype, + &found_whole_row); + } + rootRelInfo->ri_returningList = returningList; + + /* Initialize the RETURNING projection */ + rootRelInfo->ri_projectReturning = + ExecBuildProjectionInfo(returningList, econtext, + mtstate->ps.ps_ResultTupleSlot, + &mtstate->ps, + RelationGetDescr(rootRelation)); + } + } } /* @@ -3767,6 +4147,7 @@ ExecModifyTable(PlanState *pstate) HeapTupleData oldtupdata; HeapTuple oldtuple; ItemPointer tupleid; + bool tuplock; CHECK_FOR_INTERRUPTS(); @@ -3838,6 +4219,7 @@ ExecModifyTable(PlanState *pstate) if (node->mt_merge_pending_not_matched != NULL) { context.planSlot = node->mt_merge_pending_not_matched; + context.cpDeletedSlot = NULL; slot = ExecMergeNotMatched(&context, node->resultRelInfo, node->canSetTag); @@ -3857,6 +4239,7 @@ ExecModifyTable(PlanState *pstate) /* Fetch the next row from subplan */ context.planSlot = ExecProcNode(subplanstate); + context.cpDeletedSlot = NULL; /* No more tuples to process? */ if (TupIsNull(context.planSlot)) @@ -3924,9 +4307,15 @@ ExecModifyTable(PlanState *pstate) * A scan slot containing the data that was actually inserted, * updated or deleted has already been made available to * ExecProcessReturning by IterateDirectModify, so no need to - * provide it here. + * provide it here. The individual old and new slots are not + * needed, since direct-modify is disabled if the RETURNING list + * refers to OLD/NEW values. */ - slot = ExecProcessReturning(resultRelInfo, NULL, context.planSlot); + Assert((resultRelInfo->ri_projectReturning->pi_state.flags & EEO_FLAG_HAS_OLD) == 0 && + (resultRelInfo->ri_projectReturning->pi_state.flags & EEO_FLAG_HAS_NEW) == 0); + + slot = ExecProcessReturning(&context, resultRelInfo, operation, + NULL, NULL, context.planSlot); return slot; } @@ -4079,6 +4468,8 @@ ExecModifyTable(PlanState *pstate) break; case CMD_UPDATE: + tuplock = false; + /* Initialize projection info if first time for this table */ if (unlikely(!resultRelInfo->ri_projectNewInfoValid)) ExecInitUpdateProjection(node, resultRelInfo); @@ -4090,6 +4481,7 @@ ExecModifyTable(PlanState *pstate) oldSlot = resultRelInfo->ri_oldTupleSlot; if (oldtuple != NULL) { + Assert(!resultRelInfo->ri_needLockTagTuple); /* Use the wholerow junk attr as the old tuple. */ ExecForceStoreHeapTuple(oldtuple, oldSlot, false); } @@ -4098,6 +4490,11 @@ ExecModifyTable(PlanState *pstate) /* Fetch the most recent version of old tuple. */ Relation relation = resultRelInfo->ri_RelationDesc; + if (resultRelInfo->ri_needLockTagTuple) + { + LockTuple(relation, tupleid, InplaceUpdateTupleLock); + tuplock = true; + } if (!table_tuple_fetch_row_version(relation, tupleid, SnapshotAny, oldSlot)) @@ -4108,7 +4505,10 @@ ExecModifyTable(PlanState *pstate) /* Now apply the update. */ slot = ExecUpdate(&context, resultRelInfo, tupleid, oldtuple, - slot, node->canSetTag); + oldSlot, slot, node->canSetTag); + if (tuplock) + UnlockTuple(resultRelInfo->ri_RelationDesc, tupleid, + InplaceUpdateTupleLock); break; case CMD_DELETE: @@ -4215,7 +4615,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ModifyTableState *mtstate; Plan *subplan = outerPlan(node); CmdType operation = node->operation; - int nrels = list_length(node->resultRelations); + int total_nrels = list_length(node->resultRelations); + int nrels; + List *resultRelations = NIL; + List *withCheckOptionLists = NIL; + List *returningLists = NIL; + List *updateColnosLists = NIL; + List *mergeActionLists = NIL; + List *mergeJoinConditions = NIL; ResultRelInfo *resultRelInfo; List *arowmarks; ListCell *l; @@ -4225,6 +4632,80 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); + /* + * Only consider unpruned relations for initializing their ResultRelInfo + * struct and other fields such as withCheckOptions, etc. + * + * Note: We must avoid pruning every result relation. This is important + * for MERGE, since even if every result relation is pruned from the + * subplan, there might still be NOT MATCHED rows, for which there may be + * INSERT actions to perform. To allow these actions to be found, at + * least one result relation must be kept. Also, when inserting into a + * partitioned table, ExecInitPartitionInfo() needs a ResultRelInfo struct + * as a reference for building the ResultRelInfo of the target partition. + * In either case, it doesn't matter which result relation is kept, so we + * just keep the first one, if all others have been pruned. See also, + * ExecDoInitialPruning(), which ensures that this first result relation + * has been locked. + */ + i = 0; + foreach(l, node->resultRelations) + { + Index rti = lfirst_int(l); + bool keep_rel; + + keep_rel = bms_is_member(rti, estate->es_unpruned_relids); + if (!keep_rel && i == total_nrels - 1 && resultRelations == NIL) + { + /* all result relations pruned; keep the first one */ + keep_rel = true; + rti = linitial_int(node->resultRelations); + i = 0; + } + + if (keep_rel) + { + resultRelations = lappend_int(resultRelations, rti); + if (node->withCheckOptionLists) + { + List *withCheckOptions = list_nth_node(List, + node->withCheckOptionLists, + i); + + withCheckOptionLists = lappend(withCheckOptionLists, withCheckOptions); + } + if (node->returningLists) + { + List *returningList = list_nth_node(List, + node->returningLists, + i); + + returningLists = lappend(returningLists, returningList); + } + if (node->updateColnosLists) + { + List *updateColnosList = list_nth(node->updateColnosLists, i); + + updateColnosLists = lappend(updateColnosLists, updateColnosList); + } + if (node->mergeActionLists) + { + List *mergeActionList = list_nth(node->mergeActionLists, i); + + mergeActionLists = lappend(mergeActionLists, mergeActionList); + } + if (node->mergeJoinConditions) + { + List *mergeJoinCondition = list_nth(node->mergeJoinConditions, i); + + mergeJoinConditions = lappend(mergeJoinConditions, mergeJoinCondition); + } + } + i++; + } + nrels = list_length(resultRelations); + Assert(nrels > 0); + /* * create state structure */ @@ -4245,6 +4726,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) mtstate->mt_merge_inserted = 0; mtstate->mt_merge_updated = 0; mtstate->mt_merge_deleted = 0; + mtstate->mt_updateColnosLists = updateColnosLists; + mtstate->mt_mergeActionLists = mergeActionLists; + mtstate->mt_mergeJoinConditions = mergeJoinConditions; /*---------- * Resolve the target relation. This is the same as: @@ -4257,11 +4741,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * If it's a partitioned or inherited table, the root partition or * appendrel RTE doesn't appear elsewhere in the plan and its RT index is * given explicitly in node->rootRelation. Otherwise, the target relation - * is the sole relation in the node->resultRelations list. + * is the sole relation in the node->resultRelations list and, since it can + * never be pruned, also in the resultRelations list constructed above. *---------- */ if (node->rootRelation > 0) { + Assert(bms_is_member(node->rootRelation, estate->es_unpruned_relids)); mtstate->rootResultRelInfo = makeNode(ResultRelInfo); ExecInitResultRelation(estate, mtstate->rootResultRelInfo, node->rootRelation); @@ -4269,14 +4755,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) else { Assert(list_length(node->resultRelations) == 1); + Assert(list_length(resultRelations) == 1); mtstate->rootResultRelInfo = mtstate->resultRelInfo; ExecInitResultRelation(estate, mtstate->resultRelInfo, - linitial_int(node->resultRelations)); + linitial_int(resultRelations)); } /* set up epqstate with dummy subplan data for the moment */ EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, - node->epqParam, node->resultRelations); + node->epqParam, resultRelations); mtstate->fireBSTriggers = true; /* @@ -4294,13 +4781,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) */ resultRelInfo = mtstate->resultRelInfo; i = 0; - foreach(l, node->resultRelations) + foreach(l, resultRelations) { Index resultRelation = lfirst_int(l); List *mergeActions = NIL; - if (node->mergeActionLists) - mergeActions = list_nth(node->mergeActionLists, i); + if (mergeActionLists) + mergeActions = list_nth(mergeActionLists, i); if (resultRelInfo != mtstate->rootResultRelInfo) { @@ -4416,7 +4903,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) */ mtstate->mt_resultOidAttno = ExecFindJunkAttributeInTlist(subplan->targetlist, "tableoid"); - Assert(AttributeNumberIsValid(mtstate->mt_resultOidAttno) || nrels == 1); + Assert(AttributeNumberIsValid(mtstate->mt_resultOidAttno) || total_nrels == 1); mtstate->mt_lastResultOid = InvalidOid; /* force lookup at first tuple */ mtstate->mt_lastResultIndex = 0; /* must be zero if no such attr */ @@ -4438,7 +4925,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * Initialize any WITH CHECK OPTION constraints if needed. */ resultRelInfo = mtstate->resultRelInfo; - foreach(l, node->withCheckOptionLists) + foreach(l, withCheckOptionLists) { List *wcoList = (List *) lfirst(l); List *wcoExprs = NIL; @@ -4461,18 +4948,17 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* * Initialize RETURNING projections if needed. */ - if (node->returningLists) + if (returningLists) { TupleTableSlot *slot; ExprContext *econtext; /* - * Initialize result tuple slot and assign its rowtype using the first - * RETURNING list. We assume the rest will look the same. + * Initialize result tuple slot and assign its rowtype using the plan + * node's declared targetlist, which the planner set up to be the same + * as the first (before runtime pruning) RETURNING list. We assume + * all the result rels will produce compatible output. */ - mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists); - - /* Set up a slot for the output of the RETURNING projection(s) */ ExecInitResultTupleSlotTL(&mtstate->ps, &TTSOpsVirtual); slot = mtstate->ps.ps_ResultTupleSlot; @@ -4485,7 +4971,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * Build a projection for each result rel. */ resultRelInfo = mtstate->resultRelInfo; - foreach(l, node->returningLists) + foreach(l, returningLists) { List *rlist = (List *) lfirst(l); @@ -4502,7 +4988,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * We still must construct a dummy result tuple type, because InitPlan * expects one (maybe should change that?). */ - mtstate->ps.plan->targetlist = NIL; ExecInitResultTypeTL(&mtstate->ps); mtstate->ps.ps_ExprContext = NULL; @@ -4513,7 +4998,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) if (node->onConflictAction != ONCONFLICT_NONE) { /* insert may only have one relation, inheritance is not expanded */ - Assert(nrels == 1); + Assert(total_nrels == 1); resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes; } @@ -4586,8 +5071,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ExecRowMark *erm; ExecAuxRowMark *aerm; - /* ignore "parent" rowmarks; they are irrelevant at runtime */ - if (rc->isParent) + /* + * Ignore "parent" rowmarks, because they are irrelevant at runtime. + * Also ignore the rowmarks belonging to child tables that have been + * pruned in ExecDoInitialPruning(). + */ + if (rc->isParent || + !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; /* Find ExecRowMark and build ExecAuxRowMark */ @@ -4655,7 +5145,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) if (operation == CMD_INSERT) { /* insert may only have one relation, inheritance is not expanded */ - Assert(nrels == 1); + Assert(total_nrels == 1); resultRelInfo = mtstate->resultRelInfo; if (!resultRelInfo->ri_usesFdwDirectModify && resultRelInfo->ri_FdwRoutine != NULL && diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c index 580f235248bf2..047788d9e4ea3 100644 --- a/src/backend/executor/nodeNamedtuplestorescan.c +++ b/src/backend/executor/nodeNamedtuplestorescan.c @@ -3,7 +3,7 @@ * nodeNamedtuplestorescan.c * routines to handle NamedTuplestoreScan nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index 7f4bf6c4dbb5f..5cd1a251625ca 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -3,7 +3,7 @@ * nodeNestloop.c * routines to support nest-loop joins * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c index e483730015224..880f39fb2ff1e 100644 --- a/src/backend/executor/nodeProjectSet.c +++ b/src/backend/executor/nodeProjectSet.c @@ -11,7 +11,7 @@ * can't be inside more-complex expressions. If that'd otherwise be * the case, the planner adds additional ProjectSet nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index c7f8a19fa44fc..40f66fd0680b2 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -7,7 +7,7 @@ * already seen. The hash key is computed from the grouping columns. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -37,19 +37,25 @@ build_hash_table(RecursiveUnionState *rustate) Assert(node->numCols > 0); Assert(node->numGroups > 0); - rustate->hashtable = BuildTupleHashTableExt(&rustate->ps, - desc, - node->numCols, - node->dupColIdx, - rustate->eqfuncoids, - rustate->hashfunctions, - node->dupCollations, - node->numGroups, - 0, - rustate->ps.state->es_query_cxt, - rustate->tableContext, - rustate->tempContext, - false); + /* + * If both child plans deliver the same fixed tuple slot type, we can tell + * BuildTupleHashTable to expect that slot type as input. Otherwise, + * we'll pass NULL denoting that any slot type is possible. + */ + rustate->hashtable = BuildTupleHashTable(&rustate->ps, + desc, + ExecGetCommonChildSlotOps(&rustate->ps), + node->numCols, + node->dupColIdx, + rustate->eqfuncoids, + rustate->hashfunctions, + node->dupCollations, + node->numGroups, + 0, + rustate->ps.state->es_query_cxt, + rustate->tableContext, + rustate->tempContext, + false); } @@ -115,19 +121,26 @@ ExecRecursiveUnion(PlanState *pstate) slot = ExecProcNode(innerPlan); if (TupIsNull(slot)) { + Tuplestorestate *swaptemp; + /* Done if there's nothing in the intermediate table */ if (node->intermediate_empty) break; - /* done with old working table ... */ - tuplestore_end(node->working_table); + /* + * Now we let the intermediate table become the work table. We + * need a fresh intermediate table, so delete the tuples from the + * current working table and use that as the new intermediate + * table. This saves a round of free/malloc from creating a new + * tuple store. + */ + tuplestore_clear(node->working_table); - /* intermediate table becomes working table */ + swaptemp = node->working_table; node->working_table = node->intermediate_table; + node->intermediate_table = swaptemp; - /* create new empty intermediate table */ - node->intermediate_table = tuplestore_begin_heap(false, false, - work_mem); + /* mark the intermediate table as empty */ node->intermediate_empty = true; /* reset the recursive term */ diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index 348361e7f4431..06842a48ecae6 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -34,7 +34,7 @@ * plan normally and pass back the results. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c index 714b076e64689..6b3db7548ed99 100644 --- a/src/backend/executor/nodeSamplescan.c +++ b/src/backend/executor/nodeSamplescan.c @@ -3,7 +3,7 @@ * nodeSamplescan.c * Support routines for sample scans of relations (table sampling). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 7cb12a11c2d84..ed35c58c2c346 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -3,7 +3,7 @@ * nodeSeqscan.c * Support routines for sequential scans of relations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -29,6 +29,7 @@ #include "access/relscan.h" #include "access/tableam.h" +#include "executor/execScan.h" #include "executor/executor.h" #include "executor/nodeSeqscan.h" #include "utils/rel.h" @@ -99,9 +100,10 @@ SeqRecheck(SeqScanState *node, TupleTableSlot *slot) * ExecSeqScan(node) * * Scans the relation sequentially and returns the next qualifying - * tuple. - * We call the ExecScan() routine and pass it the appropriate - * access method functions. + * tuple. This variant is used when there is no es_epq_active, no qual + * and no projection. Passing const-NULLs for these to ExecScanExtended + * allows the compiler to eliminate the additional code that would + * ordinarily be required for the evaluation of these. * ---------------------------------------------------------------- */ static TupleTableSlot * @@ -109,12 +111,94 @@ ExecSeqScan(PlanState *pstate) { SeqScanState *node = castNode(SeqScanState, pstate); + Assert(pstate->state->es_epq_active == NULL); + Assert(pstate->qual == NULL); + Assert(pstate->ps_ProjInfo == NULL); + + return ExecScanExtended(&node->ss, + (ExecScanAccessMtd) SeqNext, + (ExecScanRecheckMtd) SeqRecheck, + NULL, + NULL, + NULL); +} + +/* + * Variant of ExecSeqScan() but when qual evaluation is required. + */ +static TupleTableSlot * +ExecSeqScanWithQual(PlanState *pstate) +{ + SeqScanState *node = castNode(SeqScanState, pstate); + + Assert(pstate->state->es_epq_active == NULL); + Assert(pstate->qual != NULL); + Assert(pstate->ps_ProjInfo == NULL); + + return ExecScanExtended(&node->ss, + (ExecScanAccessMtd) SeqNext, + (ExecScanRecheckMtd) SeqRecheck, + NULL, + pstate->qual, + NULL); +} + +/* + * Variant of ExecSeqScan() but when projection is required. + */ +static TupleTableSlot * +ExecSeqScanWithProject(PlanState *pstate) +{ + SeqScanState *node = castNode(SeqScanState, pstate); + + Assert(pstate->state->es_epq_active == NULL); + Assert(pstate->qual == NULL); + Assert(pstate->ps_ProjInfo != NULL); + + return ExecScanExtended(&node->ss, + (ExecScanAccessMtd) SeqNext, + (ExecScanRecheckMtd) SeqRecheck, + NULL, + NULL, + pstate->ps_ProjInfo); +} + +/* + * Variant of ExecSeqScan() but when qual evaluation and projection are + * required. + */ +static TupleTableSlot * +ExecSeqScanWithQualProject(PlanState *pstate) +{ + SeqScanState *node = castNode(SeqScanState, pstate); + + Assert(pstate->state->es_epq_active == NULL); + Assert(pstate->qual != NULL); + Assert(pstate->ps_ProjInfo != NULL); + + return ExecScanExtended(&node->ss, + (ExecScanAccessMtd) SeqNext, + (ExecScanRecheckMtd) SeqRecheck, + NULL, + pstate->qual, + pstate->ps_ProjInfo); +} + +/* + * Variant of ExecSeqScan for when EPQ evaluation is required. We don't + * bother adding variants of this for with/without qual and projection as + * EPQ doesn't seem as exciting a case to optimize for. + */ +static TupleTableSlot * +ExecSeqScanEPQ(PlanState *pstate) +{ + SeqScanState *node = castNode(SeqScanState, pstate); + return ExecScan(&node->ss, (ExecScanAccessMtd) SeqNext, (ExecScanRecheckMtd) SeqRecheck); } - /* ---------------------------------------------------------------- * ExecInitSeqScan * ---------------------------------------------------------------- @@ -137,7 +221,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) scanstate = makeNode(SeqScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; - scanstate->ss.ps.ExecProcNode = ExecSeqScan; /* * Miscellaneous initialization @@ -171,6 +254,28 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags) scanstate->ss.ps.qual = ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate); + /* + * When EvalPlanQual() is not in use, assign ExecProcNode for this node + * based on the presence of qual and projection. Each ExecSeqScan*() + * variant is optimized for the specific combination of these conditions. + */ + if (scanstate->ss.ps.state->es_epq_active != NULL) + scanstate->ss.ps.ExecProcNode = ExecSeqScanEPQ; + else if (scanstate->ss.ps.qual == NULL) + { + if (scanstate->ss.ps.ps_ProjInfo == NULL) + scanstate->ss.ps.ExecProcNode = ExecSeqScan; + else + scanstate->ss.ps.ExecProcNode = ExecSeqScanWithProject; + } + else + { + if (scanstate->ss.ps.ps_ProjInfo == NULL) + scanstate->ss.ps.ExecProcNode = ExecSeqScanWithQual; + else + scanstate->ss.ps.ExecProcNode = ExecSeqScanWithQualProject; + } + return scanstate; } diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index a8ac68b482601..4068481a52392 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -3,36 +3,37 @@ * nodeSetOp.c * Routines to handle INTERSECT and EXCEPT selection * - * The input of a SetOp node consists of tuples from two relations, - * which have been combined into one dataset, with a junk attribute added - * that shows which relation each tuple came from. In SETOP_SORTED mode, - * the input has furthermore been sorted according to all the grouping - * columns (ie, all the non-junk attributes). The SetOp node scans each - * group of identical tuples to determine how many came from each input - * relation. Then it is a simple matter to emit the output demanded by the - * SQL spec for INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL. + * The input of a SetOp node consists of two relations (outer and inner) + * with identical column sets. In EXCEPT queries the outer relation is + * always the left side, while in INTERSECT cases the planner tries to + * make the outer relation be the smaller of the two inputs. * - * In SETOP_HASHED mode, the input is delivered in no particular order, - * except that we know all the tuples from one input relation will come before - * all the tuples of the other. The planner guarantees that the first input - * relation is the left-hand one for EXCEPT, and tries to make the smaller - * input relation come first for INTERSECT. We build a hash table in memory - * with one entry for each group of identical tuples, and count the number of - * tuples in the group from each relation. After seeing all the input, we - * scan the hashtable and generate the correct output using those counts. - * We can avoid making hashtable entries for any tuples appearing only in the - * second input relation, since they cannot result in any output. + * In SETOP_SORTED mode, each input has been sorted according to all the + * grouping columns. The SetOp node essentially performs a merge join on + * the grouping columns, except that it is only interested in counting how + * many tuples from each input match. Then it is a simple matter to emit + * the output demanded by the SQL spec for INTERSECT, INTERSECT ALL, EXCEPT, + * or EXCEPT ALL. + * + * In SETOP_HASHED mode, the inputs are delivered in no particular order. + * We read the outer relation and build a hash table in memory with one entry + * for each group of identical tuples, counting the number of tuples in the + * group. Then we read the inner relation and count the number of tuples + * matching each outer group. (We can disregard any tuples appearing only + * in the inner relation, since they cannot result in any output.) After + * seeing all the input, we scan the hashtable and generate the correct + * output using those counts. * * This node type is not used for UNION or UNION ALL, since those can be - * implemented more cheaply (there's no need for the junk attribute to - * identify the source relation). + * implemented more cheaply (there's no need to count the number of + * matching tuples). * * Note that SetOp does no qual checking nor projection. The delivered * output tuples are just copies of the first-to-arrive tuple in each * input group. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -54,65 +55,28 @@ /* * SetOpStatePerGroupData - per-group working state * - * These values are working state that is initialized at the start of - * an input tuple group and updated for each input tuple. - * - * In SETOP_SORTED mode, we need only one of these structs, and it's kept in - * the plan state node. In SETOP_HASHED mode, the hash table contains one - * of these for each tuple group. + * In SETOP_SORTED mode, we need only one of these structs, and it's just a + * local in setop_retrieve_sorted. In SETOP_HASHED mode, the hash table + * contains one of these for each tuple group. */ typedef struct SetOpStatePerGroupData { - long numLeft; /* number of left-input dups in group */ - long numRight; /* number of right-input dups in group */ -} SetOpStatePerGroupData; + int64 numLeft; /* number of left-input dups in group */ + int64 numRight; /* number of right-input dups in group */ +} SetOpStatePerGroupData; + +typedef SetOpStatePerGroupData *SetOpStatePerGroup; -static TupleTableSlot *setop_retrieve_direct(SetOpState *setopstate); +static TupleTableSlot *setop_retrieve_sorted(SetOpState *setopstate); +static void setop_load_group(SetOpStatePerInput *input, PlanState *inputPlan, + SetOpState *setopstate); +static int setop_compare_slots(TupleTableSlot *s1, TupleTableSlot *s2, + SetOpState *setopstate); static void setop_fill_hash_table(SetOpState *setopstate); static TupleTableSlot *setop_retrieve_hash_table(SetOpState *setopstate); -/* - * Initialize state for a new group of input values. - */ -static inline void -initialize_counts(SetOpStatePerGroup pergroup) -{ - pergroup->numLeft = pergroup->numRight = 0; -} - -/* - * Advance the appropriate counter for one input tuple. - */ -static inline void -advance_counts(SetOpStatePerGroup pergroup, int flag) -{ - if (flag) - pergroup->numRight++; - else - pergroup->numLeft++; -} - -/* - * Fetch the "flag" column from an input tuple. - * This is an integer column with value 0 for left side, 1 for right side. - */ -static int -fetch_tuple_flag(SetOpState *setopstate, TupleTableSlot *inputslot) -{ - SetOp *node = (SetOp *) setopstate->ps.plan; - int flag; - bool isNull; - - flag = DatumGetInt32(slot_getattr(inputslot, - node->flagColIdx, - &isNull)); - Assert(!isNull); - Assert(flag == 0 || flag == 1); - return flag; -} - /* * Initialize the hash table to empty. */ @@ -126,19 +90,25 @@ build_hash_table(SetOpState *setopstate) Assert(node->strategy == SETOP_HASHED); Assert(node->numGroups > 0); - setopstate->hashtable = BuildTupleHashTableExt(&setopstate->ps, - desc, - node->numCols, - node->dupColIdx, - setopstate->eqfuncoids, - setopstate->hashfunctions, - node->dupCollations, - node->numGroups, - 0, - setopstate->ps.state->es_query_cxt, - setopstate->tableContext, - econtext->ecxt_per_tuple_memory, - false); + /* + * If both child plans deliver the same fixed tuple slot type, we can tell + * BuildTupleHashTable to expect that slot type as input. Otherwise, + * we'll pass NULL denoting that any slot type is possible. + */ + setopstate->hashtable = BuildTupleHashTable(&setopstate->ps, + desc, + ExecGetCommonChildSlotOps(&setopstate->ps), + node->numCols, + node->cmpColIdx, + setopstate->eqfuncoids, + setopstate->hashfunctions, + node->cmpCollations, + node->numGroups, + sizeof(SetOpStatePerGroupData), + setopstate->ps.state->es_query_cxt, + setopstate->tableContext, + econtext->ecxt_per_tuple_memory, + false); } /* @@ -217,108 +187,126 @@ ExecSetOp(PlanState *pstate) return setop_retrieve_hash_table(node); } else - return setop_retrieve_direct(node); + return setop_retrieve_sorted(node); } /* * ExecSetOp for non-hashed case */ static TupleTableSlot * -setop_retrieve_direct(SetOpState *setopstate) +setop_retrieve_sorted(SetOpState *setopstate) { PlanState *outerPlan; - SetOpStatePerGroup pergroup; - TupleTableSlot *outerslot; + PlanState *innerPlan; TupleTableSlot *resultTupleSlot; - ExprContext *econtext = setopstate->ps.ps_ExprContext; /* * get state info from node */ outerPlan = outerPlanState(setopstate); - pergroup = (SetOpStatePerGroup) setopstate->pergroup; + innerPlan = innerPlanState(setopstate); resultTupleSlot = setopstate->ps.ps_ResultTupleSlot; /* - * We loop retrieving groups until we find one we should return + * If first time through, establish the invariant that setop_load_group + * expects: each side's nextTupleSlot is the next output from the child + * plan, or empty if there is no more output from it. */ - while (!setopstate->setop_done) + if (setopstate->need_init) { + setopstate->need_init = false; + + setopstate->leftInput.nextTupleSlot = ExecProcNode(outerPlan); + /* - * If we don't already have the first tuple of the new group, fetch it - * from the outer plan. + * If the outer relation is empty, then we will emit nothing, and we + * don't need to read the inner relation at all. */ - if (setopstate->grp_firstTuple == NULL) + if (TupIsNull(setopstate->leftInput.nextTupleSlot)) { - outerslot = ExecProcNode(outerPlan); - if (!TupIsNull(outerslot)) - { - /* Make a copy of the first input tuple */ - setopstate->grp_firstTuple = ExecCopySlotHeapTuple(outerslot); - } - else - { - /* outer plan produced no tuples at all */ - setopstate->setop_done = true; - return NULL; - } + setopstate->setop_done = true; + return NULL; } - /* - * Store the copied first input tuple in the tuple table slot reserved - * for it. The tuple will be deleted when it is cleared from the - * slot. - */ - ExecStoreHeapTuple(setopstate->grp_firstTuple, - resultTupleSlot, - true); - setopstate->grp_firstTuple = NULL; /* don't keep two pointers */ + setopstate->rightInput.nextTupleSlot = ExecProcNode(innerPlan); - /* Initialize working state for a new input tuple group */ - initialize_counts(pergroup); + /* Set flags that we've not completed either side's group */ + setopstate->leftInput.needGroup = true; + setopstate->rightInput.needGroup = true; + } - /* Count the first input tuple */ - advance_counts(pergroup, - fetch_tuple_flag(setopstate, resultTupleSlot)); + /* + * We loop retrieving groups until we find one we should return + */ + while (!setopstate->setop_done) + { + int cmpresult; + SetOpStatePerGroupData pergroup; /* - * Scan the outer plan until we exhaust it or cross a group boundary. + * Fetch the rest of the current outer group, if we didn't already. */ - for (;;) + if (setopstate->leftInput.needGroup) + setop_load_group(&setopstate->leftInput, outerPlan, setopstate); + + /* + * If no more outer groups, we're done, and don't need to look at any + * more of the inner relation. + */ + if (setopstate->leftInput.numTuples == 0) { - outerslot = ExecProcNode(outerPlan); - if (TupIsNull(outerslot)) - { - /* no more outer-plan tuples available */ - setopstate->setop_done = true; - break; - } + setopstate->setop_done = true; + break; + } - /* - * Check whether we've crossed a group boundary. - */ - econtext->ecxt_outertuple = resultTupleSlot; - econtext->ecxt_innertuple = outerslot; + /* + * Fetch the rest of the current inner group, if we didn't already. + */ + if (setopstate->rightInput.needGroup) + setop_load_group(&setopstate->rightInput, innerPlan, setopstate); - if (!ExecQualAndReset(setopstate->eqfunction, econtext)) - { - /* - * Save the first input tuple of the next group. - */ - setopstate->grp_firstTuple = ExecCopySlotHeapTuple(outerslot); - break; - } + /* + * Determine whether we have matching groups on both sides (this is + * basically like the core logic of a merge join). + */ + if (setopstate->rightInput.numTuples == 0) + cmpresult = -1; /* as though left input is lesser */ + else + cmpresult = setop_compare_slots(setopstate->leftInput.firstTupleSlot, + setopstate->rightInput.firstTupleSlot, + setopstate); - /* Still in same group, so count this tuple */ - advance_counts(pergroup, - fetch_tuple_flag(setopstate, outerslot)); + if (cmpresult < 0) + { + /* Left group is first, and has no right matches */ + pergroup.numLeft = setopstate->leftInput.numTuples; + pergroup.numRight = 0; + /* We'll need another left group next time */ + setopstate->leftInput.needGroup = true; + } + else if (cmpresult == 0) + { + /* We have matching groups */ + pergroup.numLeft = setopstate->leftInput.numTuples; + pergroup.numRight = setopstate->rightInput.numTuples; + /* We'll need to read from both sides next time */ + setopstate->leftInput.needGroup = true; + setopstate->rightInput.needGroup = true; + } + else + { + /* Right group has no left matches, so we can ignore it */ + setopstate->rightInput.needGroup = true; + continue; } /* - * Done scanning input tuple group. See if we should emit any copies - * of result tuple, and if so return the first copy. + * Done scanning these input tuple groups. See if we should emit any + * copies of result tuple, and if so return the first copy. (Note + * that the result tuple is the same as the left input's firstTuple + * slot.) */ - set_output_count(setopstate, pergroup); + set_output_count(setopstate, &pergroup); if (setopstate->numOutput > 0) { @@ -333,84 +321,175 @@ setop_retrieve_direct(SetOpState *setopstate) } /* - * ExecSetOp for hashed case: phase 1, read input and build hash table + * Load next group of tuples from one child plan or the other. + * + * On entry, we've already read the first tuple of the next group + * (if there is one) into input->nextTupleSlot. This invariant + * is maintained on exit. + */ +static void +setop_load_group(SetOpStatePerInput *input, PlanState *inputPlan, + SetOpState *setopstate) +{ + input->needGroup = false; + + /* If we've exhausted this child plan, report an empty group */ + if (TupIsNull(input->nextTupleSlot)) + { + ExecClearTuple(input->firstTupleSlot); + input->numTuples = 0; + return; + } + + /* Make a local copy of the first tuple for comparisons */ + ExecStoreMinimalTuple(ExecCopySlotMinimalTuple(input->nextTupleSlot), + input->firstTupleSlot, + true); + /* and count it */ + input->numTuples = 1; + + /* Scan till we find the end-of-group */ + for (;;) + { + int cmpresult; + + /* Get next input tuple, if there is one */ + input->nextTupleSlot = ExecProcNode(inputPlan); + if (TupIsNull(input->nextTupleSlot)) + break; + + /* There is; does it belong to same group as firstTuple? */ + cmpresult = setop_compare_slots(input->firstTupleSlot, + input->nextTupleSlot, + setopstate); + Assert(cmpresult <= 0); /* else input is mis-sorted */ + if (cmpresult != 0) + break; + + /* Still in same group, so count this tuple */ + input->numTuples++; + } +} + +/* + * Compare the tuples in the two given slots. + */ +static int +setop_compare_slots(TupleTableSlot *s1, TupleTableSlot *s2, + SetOpState *setopstate) +{ + /* We'll often need to fetch all the columns, so just do it */ + slot_getallattrs(s1); + slot_getallattrs(s2); + for (int nkey = 0; nkey < setopstate->numCols; nkey++) + { + SortSupport sortKey = setopstate->sortKeys + nkey; + AttrNumber attno = sortKey->ssup_attno; + Datum datum1 = s1->tts_values[attno - 1], + datum2 = s2->tts_values[attno - 1]; + bool isNull1 = s1->tts_isnull[attno - 1], + isNull2 = s2->tts_isnull[attno - 1]; + int compare; + + compare = ApplySortComparator(datum1, isNull1, + datum2, isNull2, + sortKey); + if (compare != 0) + return compare; + } + return 0; +} + +/* + * ExecSetOp for hashed case: phase 1, read inputs and build hash table */ static void setop_fill_hash_table(SetOpState *setopstate) { - SetOp *node = (SetOp *) setopstate->ps.plan; PlanState *outerPlan; - int firstFlag; - bool in_first_rel PG_USED_FOR_ASSERTS_ONLY; + PlanState *innerPlan; ExprContext *econtext = setopstate->ps.ps_ExprContext; + bool have_tuples = false; /* * get state info from node */ outerPlan = outerPlanState(setopstate); - firstFlag = node->firstFlag; - /* verify planner didn't mess up */ - Assert(firstFlag == 0 || - (firstFlag == 1 && - (node->cmd == SETOPCMD_INTERSECT || - node->cmd == SETOPCMD_INTERSECT_ALL))); + innerPlan = innerPlanState(setopstate); /* * Process each outer-plan tuple, and then fetch the next one, until we * exhaust the outer plan. */ - in_first_rel = true; for (;;) { TupleTableSlot *outerslot; - int flag; + TupleHashTable hashtable = setopstate->hashtable; TupleHashEntryData *entry; + SetOpStatePerGroup pergroup; bool isnew; outerslot = ExecProcNode(outerPlan); if (TupIsNull(outerslot)) break; + have_tuples = true; - /* Identify whether it's left or right input */ - flag = fetch_tuple_flag(setopstate, outerslot); + /* Find or build hashtable entry for this tuple's group */ + entry = LookupTupleHashEntry(hashtable, + outerslot, + &isnew, NULL); - if (flag == firstFlag) + pergroup = TupleHashEntryGetAdditional(hashtable, entry); + /* If new tuple group, initialize counts to zero */ + if (isnew) { - /* (still) in first input relation */ - Assert(in_first_rel); + pergroup->numLeft = 0; + pergroup->numRight = 0; + } - /* Find or build hashtable entry for this tuple's group */ - entry = LookupTupleHashEntry(setopstate->hashtable, outerslot, - &isnew, NULL); + /* Advance the counts */ + pergroup->numLeft++; - /* If new tuple group, initialize counts */ - if (isnew) - { - entry->additional = (SetOpStatePerGroup) - MemoryContextAlloc(setopstate->hashtable->tablecxt, - sizeof(SetOpStatePerGroupData)); - initialize_counts((SetOpStatePerGroup) entry->additional); - } + /* Must reset expression context after each hashtable lookup */ + ResetExprContext(econtext); + } - /* Advance the counts */ - advance_counts((SetOpStatePerGroup) entry->additional, flag); - } - else + /* + * If the outer relation is empty, then we will emit nothing, and we don't + * need to read the inner relation at all. + */ + if (have_tuples) + { + /* + * Process each inner-plan tuple, and then fetch the next one, until + * we exhaust the inner plan. + */ + for (;;) { - /* reached second relation */ - in_first_rel = false; + TupleTableSlot *innerslot; + TupleHashTable hashtable = setopstate->hashtable; + TupleHashEntryData *entry; + + innerslot = ExecProcNode(innerPlan); + if (TupIsNull(innerslot)) + break; /* For tuples not seen previously, do not make hashtable entry */ - entry = LookupTupleHashEntry(setopstate->hashtable, outerslot, + entry = LookupTupleHashEntry(hashtable, + innerslot, NULL, NULL); /* Advance the counts if entry is already present */ if (entry) - advance_counts((SetOpStatePerGroup) entry->additional, flag); - } + { + SetOpStatePerGroup pergroup = TupleHashEntryGetAdditional(hashtable, entry); - /* Must reset expression context after each hashtable lookup */ - ResetExprContext(econtext); + pergroup->numRight++; + } + + /* Must reset expression context after each hashtable lookup */ + ResetExprContext(econtext); + } } setopstate->table_filled = true; @@ -424,7 +503,7 @@ setop_fill_hash_table(SetOpState *setopstate) static TupleTableSlot * setop_retrieve_hash_table(SetOpState *setopstate) { - TupleHashEntryData *entry; + TupleHashEntry entry; TupleTableSlot *resultTupleSlot; /* @@ -437,12 +516,15 @@ setop_retrieve_hash_table(SetOpState *setopstate) */ while (!setopstate->setop_done) { + TupleHashTable hashtable = setopstate->hashtable; + SetOpStatePerGroup pergroup; + CHECK_FOR_INTERRUPTS(); /* * Find the next entry in the hash table */ - entry = ScanTupleHashTable(setopstate->hashtable, &setopstate->hashiter); + entry = ScanTupleHashTable(hashtable, &setopstate->hashiter); if (entry == NULL) { /* No more entries in hashtable, so done */ @@ -454,12 +536,13 @@ setop_retrieve_hash_table(SetOpState *setopstate) * See if we should emit any copies of this tuple, and if so return * the first copy. */ - set_output_count(setopstate, (SetOpStatePerGroup) entry->additional); + pergroup = TupleHashEntryGetAdditional(hashtable, entry); + set_output_count(setopstate, pergroup); if (setopstate->numOutput > 0) { setopstate->numOutput--; - return ExecStoreMinimalTuple(entry->firstTuple, + return ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), resultTupleSlot, false); } @@ -481,7 +564,6 @@ SetOpState * ExecInitSetOp(SetOp *node, EState *estate, int eflags) { SetOpState *setopstate; - TupleDesc outerDesc; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); @@ -494,14 +576,10 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) setopstate->ps.state = estate; setopstate->ps.ExecProcNode = ExecSetOp; - setopstate->eqfuncoids = NULL; - setopstate->hashfunctions = NULL; setopstate->setop_done = false; setopstate->numOutput = 0; - setopstate->pergroup = NULL; - setopstate->grp_firstTuple = NULL; - setopstate->hashtable = NULL; - setopstate->tableContext = NULL; + setopstate->numCols = node->numCols; + setopstate->need_init = true; /* * create expression context @@ -522,52 +600,72 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) /* * initialize child nodes * - * If we are hashing then the child plan does not need to handle REWIND + * If we are hashing then the child plans do not need to handle REWIND * efficiently; see ExecReScanSetOp. */ if (node->strategy == SETOP_HASHED) eflags &= ~EXEC_FLAG_REWIND; outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate, eflags); - outerDesc = ExecGetResultType(outerPlanState(setopstate)); + innerPlanState(setopstate) = ExecInitNode(innerPlan(node), estate, eflags); /* - * Initialize result slot and type. Setop nodes do no projections, so - * initialize projection info for this node appropriately. + * Initialize locally-allocated slots. In hashed mode, we just need a + * result slot. In sorted mode, we need one first-tuple-of-group slot for + * each input; we use the result slot for the left input's slot and create + * another for the right input. (Note: the nextTupleSlot slots are not + * ours, but just point to the last slot returned by the input plan node.) */ - ExecInitResultTupleSlotTL(&setopstate->ps, - node->strategy == SETOP_HASHED ? - &TTSOpsMinimalTuple : &TTSOpsHeapTuple); + ExecInitResultTupleSlotTL(&setopstate->ps, &TTSOpsMinimalTuple); + if (node->strategy != SETOP_HASHED) + { + setopstate->leftInput.firstTupleSlot = + setopstate->ps.ps_ResultTupleSlot; + setopstate->rightInput.firstTupleSlot = + ExecInitExtraTupleSlot(estate, + setopstate->ps.ps_ResultTupleDesc, + &TTSOpsMinimalTuple); + } + + /* Setop nodes do no projections. */ setopstate->ps.ps_ProjInfo = NULL; /* - * Precompute fmgr lookup data for inner loop. We need both equality and - * hashing functions to do it by hashing, but only equality if not - * hashing. + * Precompute fmgr lookup data for inner loop. We need equality and + * hashing functions to do it by hashing, while for sorting we need + * SortSupport data. */ if (node->strategy == SETOP_HASHED) execTuplesHashPrepare(node->numCols, - node->dupOperators, + node->cmpOperators, &setopstate->eqfuncoids, &setopstate->hashfunctions); else - setopstate->eqfunction = - execTuplesMatchPrepare(outerDesc, - node->numCols, - node->dupColIdx, - node->dupOperators, - node->dupCollations, - &setopstate->ps); + { + int nkeys = node->numCols; + + setopstate->sortKeys = (SortSupport) + palloc0(nkeys * sizeof(SortSupportData)); + for (int i = 0; i < nkeys; i++) + { + SortSupport sortKey = setopstate->sortKeys + i; + + sortKey->ssup_cxt = CurrentMemoryContext; + sortKey->ssup_collation = node->cmpCollations[i]; + sortKey->ssup_nulls_first = node->cmpNullsFirst[i]; + sortKey->ssup_attno = node->cmpColIdx[i]; + /* abbreviated key conversion is not useful here */ + sortKey->abbreviate = false; + + PrepareSortSupportFromOrderingOp(node->cmpOperators[i], sortKey); + } + } + /* Create a hash table if needed */ if (node->strategy == SETOP_HASHED) { build_hash_table(setopstate); setopstate->table_filled = false; } - else - { - setopstate->pergroup = - (SetOpStatePerGroup) palloc0(sizeof(SetOpStatePerGroupData)); - } return setopstate; } @@ -575,7 +673,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags) /* ---------------------------------------------------------------- * ExecEndSetOp * - * This shuts down the subplan and frees resources allocated + * This shuts down the subplans and frees resources allocated * to this node. * ---------------------------------------------------------------- */ @@ -587,6 +685,7 @@ ExecEndSetOp(SetOpState *node) MemoryContextDelete(node->tableContext); ExecEndNode(outerPlanState(node)); + ExecEndNode(innerPlanState(node)); } @@ -594,6 +693,7 @@ void ExecReScanSetOp(SetOpState *node) { PlanState *outerPlan = outerPlanState(node); + PlanState *innerPlan = innerPlanState(node); ExecClearTuple(node->ps.ps_ResultTupleSlot); node->setop_done = false; @@ -611,34 +711,29 @@ ExecReScanSetOp(SetOpState *node) return; /* - * If we do have the hash table and the subplan does not have any + * If we do have the hash table and the subplans do not have any * parameter changes, then we can just rescan the existing hash table; * no need to build it again. */ - if (outerPlan->chgParam == NULL) + if (outerPlan->chgParam == NULL && innerPlan->chgParam == NULL) { ResetTupleHashIterator(node->hashtable, &node->hashiter); return; } - } - /* Release first tuple of group, if we have made a copy */ - if (node->grp_firstTuple != NULL) - { - heap_freetuple(node->grp_firstTuple); - node->grp_firstTuple = NULL; - } + /* Release any hashtable storage */ + if (node->tableContext) + MemoryContextReset(node->tableContext); - /* Release any hashtable storage */ - if (node->tableContext) - MemoryContextReset(node->tableContext); - - /* And rebuild empty hashtable if needed */ - if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED) - { + /* And rebuild an empty hashtable */ ResetTupleHashTable(node->hashtable); node->table_filled = false; } + else + { + /* Need to re-read first input from each side */ + node->need_init = true; + } /* * if chgParam of subnode is not null then plan will be re-scanned by @@ -646,4 +741,6 @@ ExecReScanSetOp(SetOpState *node) */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); + if (innerPlan->chgParam == NULL) + ExecReScan(innerPlan); } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 3fc925d7b48e5..f603337ecd344 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -3,7 +3,7 @@ * nodeSort.c * Routines to handle sorting of relations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -122,7 +122,7 @@ ExecSort(PlanState *pstate) tuplesortopts); if (node->bounded) tuplesort_set_bound(tuplesortstate, node->bound); - node->tuplesortstate = (void *) tuplesortstate; + node->tuplesortstate = tuplesortstate; /* * Scan the subplan and feed all the tuples to tuplesort using the diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 9697b1f396d56..f7f6fc2da0b95 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -11,7 +11,7 @@ * subplans, which are re-evaluated every time their result is required. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -107,7 +107,7 @@ ExecHashSubPlan(SubPlanState *node, TupleTableSlot *slot; /* Shouldn't have any direct correlation Vars */ - if (subplan->parParam != NIL || node->args != NIL) + if (subplan->parParam != NIL || subplan->args != NIL) elog(ERROR, "hashed subplan with direct correlation not supported"); /* @@ -160,7 +160,7 @@ ExecHashSubPlan(SubPlanState *node, FindTupleHashEntry(node->hashtable, slot, node->cur_eq_comp, - node->lhs_hash_funcs) != NULL) + node->lhs_hash_expr) != NULL) { ExecClearTuple(slot); return BoolGetDatum(true); @@ -231,7 +231,6 @@ ExecScanSubPlan(SubPlanState *node, TupleTableSlot *slot; Datum result; bool found = false; /* true if got at least one subplan tuple */ - ListCell *pvar; ListCell *l; ArrayBuildStateAny *astate = NULL; @@ -248,26 +247,19 @@ ExecScanSubPlan(SubPlanState *node, oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); /* - * Set Params of this plan from parent plan correlation values. (Any - * calculation we have to do is done in the parent econtext, since the - * Param values don't need to have per-query lifetime.) + * We rely on the caller to evaluate plan correlation values, if + * necessary. However we still need to record the fact that the values + * (might have) changed, otherwise the ExecReScan() below won't know that + * nodes need to be rescanned. */ - Assert(list_length(subplan->parParam) == list_length(node->args)); - - forboth(l, subplan->parParam, pvar, node->args) + foreach(l, subplan->parParam) { int paramid = lfirst_int(l); - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); - prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), - econtext, - &(prm->isnull)); planstate->chgParam = bms_add_member(planstate->chgParam, paramid); } - /* - * Now that we've set up its parameters, we can reset the subplan. - */ + /* with that done, we can reset the subplan */ ExecReScan(planstate); /* @@ -527,6 +519,11 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) * * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't * need to store subplan output rows that contain NULL. + * + * Because the input slot for each hash table is always the slot resulting + * from an ExecProject(), we can use TTSOpsVirtual for the input ops. This + * saves a needless fetch inner op step for the hashing ExprState created + * in BuildTupleHashTable(). */ MemoryContextReset(node->hashtablecxt); node->havehashrows = false; @@ -539,19 +536,20 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) if (node->hashtable) ResetTupleHashTable(node->hashtable); else - node->hashtable = BuildTupleHashTableExt(node->parent, - node->descRight, - ncols, - node->keyColIdx, - node->tab_eq_funcoids, - node->tab_hash_funcs, - node->tab_collations, - nbuckets, - 0, - node->planstate->state->es_query_cxt, - node->hashtablecxt, - node->hashtempcxt, - false); + node->hashtable = BuildTupleHashTable(node->parent, + node->descRight, + &TTSOpsVirtual, + ncols, + node->keyColIdx, + node->tab_eq_funcoids, + node->tab_hash_funcs, + node->tab_collations, + nbuckets, + 0, + node->planstate->state->es_query_cxt, + node->hashtablecxt, + node->hashtempcxt, + false); if (!subplan->unknownEqFalse) { @@ -567,19 +565,20 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) if (node->hashnulls) ResetTupleHashTable(node->hashnulls); else - node->hashnulls = BuildTupleHashTableExt(node->parent, - node->descRight, - ncols, - node->keyColIdx, - node->tab_eq_funcoids, - node->tab_hash_funcs, - node->tab_collations, - nbuckets, - 0, - node->planstate->state->es_query_cxt, - node->hashtablecxt, - node->hashtempcxt, - false); + node->hashnulls = BuildTupleHashTable(node->parent, + node->descRight, + &TTSOpsVirtual, + ncols, + node->keyColIdx, + node->tab_eq_funcoids, + node->tab_hash_funcs, + node->tab_collations, + nbuckets, + 0, + node->planstate->state->es_query_cxt, + node->hashtablecxt, + node->hashtempcxt, + false); } else node->hashnulls = NULL; @@ -754,7 +753,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot, { CHECK_FOR_INTERRUPTS(); - ExecStoreMinimalTuple(entry->firstTuple, hashtable->tableslot, false); + ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry), hashtable->tableslot, false); if (!execTuplesUnequal(slot, hashtable->tableslot, numCols, keyColIdx, eqfunctions, @@ -817,6 +816,10 @@ slotNoNulls(TupleTableSlot *slot) * as well as regular SubPlans. Note that we don't link the SubPlan into * the parent's subPlan list, because that shouldn't happen for InitPlans. * Instead, ExecInitExpr() does that one part. + * + * We also rely on ExecInitExpr(), more precisely ExecInitSubPlanExpr(), to + * evaluate input parameters, as that allows them to be evaluated as part of + * the expression referencing the SubPlan. * ---------------------------------------------------------------- */ SubPlanState * @@ -844,7 +847,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) /* Initialize subexpressions */ sstate->testexpr = ExecInitExpr((Expr *) subplan->testexpr, parent); - sstate->args = ExecInitExprList(subplan->args, parent); /* * initialize my state @@ -861,9 +863,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->keyColIdx = NULL; sstate->tab_eq_funcoids = NULL; sstate->tab_hash_funcs = NULL; - sstate->tab_eq_funcs = NULL; sstate->tab_collations = NULL; - sstate->lhs_hash_funcs = NULL; sstate->cur_eq_funcs = NULL; /* @@ -903,6 +903,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) TupleDesc tupDescRight; Oid *cross_eq_funcoids; TupleTableSlot *slot; + FmgrInfo *lhs_hash_funcs; List *oplist, *lefttlist, *righttlist; @@ -959,8 +960,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->tab_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid)); sstate->tab_collations = (Oid *) palloc(ncols * sizeof(Oid)); sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); - sstate->tab_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); - sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); + lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); sstate->cur_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); /* we'll need the cross-type equality fns below, but not in sstate */ cross_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid)); @@ -1004,15 +1004,13 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) elog(ERROR, "could not find compatible hash operator for operator %u", opexpr->opno); sstate->tab_eq_funcoids[i - 1] = get_opcode(rhs_eq_oper); - fmgr_info(sstate->tab_eq_funcoids[i - 1], - &sstate->tab_eq_funcs[i - 1]); /* Lookup the associated hash functions */ if (!get_op_hash_functions(opexpr->opno, &left_hashfn, &right_hashfn)) elog(ERROR, "could not find hash function for hash operator %u", opexpr->opno); - fmgr_info(left_hashfn, &sstate->lhs_hash_funcs[i - 1]); + fmgr_info(left_hashfn, &lhs_hash_funcs[i - 1]); fmgr_info(right_hashfn, &sstate->tab_hash_funcs[i - 1]); /* Set collation */ @@ -1048,6 +1046,16 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->planstate, NULL); + /* Build the ExprState for generating hash values */ + sstate->lhs_hash_expr = ExecBuildHash32FromAttrs(tupDescLeft, + &TTSOpsVirtual, + lhs_hash_funcs, + sstate->tab_collations, + sstate->numCols, + sstate->keyColIdx, + parent, + 0); + /* * Create comparator for lookups of rows in the table (potentially * cross-type comparisons). @@ -1107,7 +1115,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) elog(ERROR, "ANY/ALL subselect unsupported as initplan"); if (subLinkType == CTE_SUBLINK) elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan"); - if (subplan->parParam || node->args) + if (subplan->parParam || subplan->args) elog(ERROR, "correlated subplans should not be executed via ExecSetParamPlan"); /* diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 782097eaf296e..8dd1ae4630832 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -7,7 +7,7 @@ * we need two sets of code. Ought to look at trying to unify the cases. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index f483221bb8efe..83ade3f943763 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -3,7 +3,7 @@ * nodeTableFuncscan.c * Support routines for scanning RangeTableFunc (XMLTABLE like functions). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeTidrangescan.c b/src/backend/executor/nodeTidrangescan.c index 9aa7683d7e373..26f7420b64b0e 100644 --- a/src/backend/executor/nodeTidrangescan.c +++ b/src/backend/executor/nodeTidrangescan.c @@ -3,7 +3,7 @@ * nodeTidrangescan.c * Routines to support TID range scans of relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -128,9 +128,11 @@ TidExprListCreate(TidRangeScanState *tidrangestate) * TidRangeEval * * Compute and set node's block and offset range to scan by evaluating - * the trss_tidexprs. Returns false if we detect the range cannot + * node->trss_tidexprs. Returns false if we detect the range cannot * contain any tuples. Returns true if it's possible for the range to - * contain tuples. + * contain tuples. We don't bother validating that trss_mintid is less + * than or equal to trss_maxtid, as the scan_set_tidrange() table AM + * function will handle that. * ---------------------------------------------------------------- */ static bool diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 864a9013b624c..5e56e29a15fc4 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -3,7 +3,7 @@ * nodeTidscan.c * Routines to support direct tid scans of relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index a125923e9359f..3854ad285c4eb 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -11,7 +11,7 @@ * (It's debatable whether the savings justifies carrying two plan node * types, though.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index 92948917a08b4..8e85a5f2e9a9c 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -4,7 +4,7 @@ * Support routines for scanning Values lists * ("VALUES (...), (...), ..." in rangetable). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -142,8 +142,8 @@ ValuesNext(ValuesScanState *node) foreach(lc, exprstatelist) { ExprState *estate = (ExprState *) lfirst(lc); - Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, - resind); + CompactAttribute *attr = TupleDescCompactAttr(slot->tts_tupleDescriptor, + resind); values[resind] = ExecEvalExpr(estate, econtext, diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 3221fa1522a3a..9a1acce2b5d36 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -23,7 +23,7 @@ * aggregate function over all rows in the current row's window frame. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -339,7 +339,7 @@ advance_windowaggregate(WindowAggState *winstate, InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn), numArguments + 1, perfuncstate->winCollation, - (void *) winstate, NULL); + (Node *) winstate, NULL); fcinfo->args[0].value = peraggstate->transValue; fcinfo->args[0].isnull = peraggstate->transValueIsNull; winstate->curaggcontext = peraggstate->aggcontext; @@ -510,7 +510,7 @@ advance_windowaggregate_base(WindowAggState *winstate, InitFunctionCallInfoData(*fcinfo, &(peraggstate->invtransfn), numArguments + 1, perfuncstate->winCollation, - (void *) winstate, NULL); + (Node *) winstate, NULL); fcinfo->args[0].value = peraggstate->transValue; fcinfo->args[0].isnull = peraggstate->transValueIsNull; winstate->curaggcontext = peraggstate->aggcontext; @@ -601,7 +601,7 @@ finalize_windowaggregate(WindowAggState *winstate, InitFunctionCallInfoData(fcinfodata.fcinfo, &(peraggstate->finalfn), numFinalArgs, perfuncstate->winCollation, - (void *) winstate, NULL); + (Node *) winstate, NULL); fcinfo->args[0].value = MakeExpandedObjectReadOnly(peraggstate->transValue, peraggstate->transValueIsNull, @@ -1047,7 +1047,7 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, InitFunctionCallInfoData(*fcinfo, &(perfuncstate->flinfo), perfuncstate->numArguments, perfuncstate->winCollation, - (void *) perfuncstate->winobj, NULL); + (Node *) perfuncstate->winobj, NULL); /* Just in case, make all the regular argument slots be null */ for (int argno = 0; argno < perfuncstate->numArguments; argno++) fcinfo->args[argno].isnull = true; @@ -1074,57 +1074,24 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, } /* - * begin_partition - * Start buffering rows of the next partition. + * prepare_tuplestore + * Prepare the tuplestore and all of the required read pointers for the + * WindowAggState's frameOptions. + * + * Note: We use pg_noinline to avoid bloating the calling function with code + * which is only called once. */ -static void -begin_partition(WindowAggState *winstate) +static pg_noinline void +prepare_tuplestore(WindowAggState *winstate) { WindowAgg *node = (WindowAgg *) winstate->ss.ps.plan; - PlanState *outerPlan = outerPlanState(winstate); int frameOptions = winstate->frameOptions; int numfuncs = winstate->numfuncs; - int i; - - winstate->partition_spooled = false; - winstate->framehead_valid = false; - winstate->frametail_valid = false; - winstate->grouptail_valid = false; - winstate->spooled_rows = 0; - winstate->currentpos = 0; - winstate->frameheadpos = 0; - winstate->frametailpos = 0; - winstate->currentgroup = 0; - winstate->frameheadgroup = 0; - winstate->frametailgroup = 0; - winstate->groupheadpos = 0; - winstate->grouptailpos = -1; /* see update_grouptailpos */ - ExecClearTuple(winstate->agg_row_slot); - if (winstate->framehead_slot) - ExecClearTuple(winstate->framehead_slot); - if (winstate->frametail_slot) - ExecClearTuple(winstate->frametail_slot); - /* - * If this is the very first partition, we need to fetch the first input - * row to store in first_part_slot. - */ - if (TupIsNull(winstate->first_part_slot)) - { - TupleTableSlot *outerslot = ExecProcNode(outerPlan); + /* we shouldn't be called if this was done already */ + Assert(winstate->buffer == NULL); - if (!TupIsNull(outerslot)) - ExecCopySlot(winstate->first_part_slot, outerslot); - else - { - /* outer plan is empty, so we have nothing to do */ - winstate->partition_spooled = true; - winstate->more_partitions = false; - return; - } - } - - /* Create new tuplestore for this partition */ + /* Create new tuplestore */ winstate->buffer = tuplestore_begin_heap(false, false, work_mem); /* @@ -1158,16 +1125,10 @@ begin_partition(WindowAggState *winstate) agg_winobj->readptr = tuplestore_alloc_read_pointer(winstate->buffer, readptr_flags); - agg_winobj->markpos = -1; - agg_winobj->seekpos = -1; - - /* Also reset the row counters for aggregates */ - winstate->aggregatedbase = 0; - winstate->aggregatedupto = 0; } /* create mark and read pointers for each real window function */ - for (i = 0; i < numfuncs; i++) + for (int i = 0; i < numfuncs; i++) { WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); @@ -1179,8 +1140,6 @@ begin_partition(WindowAggState *winstate) 0); winobj->readptr = tuplestore_alloc_read_pointer(winstate->buffer, EXEC_FLAG_BACKWARD); - winobj->markpos = -1; - winobj->seekpos = -1; } } @@ -1224,6 +1183,88 @@ begin_partition(WindowAggState *winstate) winstate->grouptail_ptr = tuplestore_alloc_read_pointer(winstate->buffer, 0); } +} + +/* + * begin_partition + * Start buffering rows of the next partition. + */ +static void +begin_partition(WindowAggState *winstate) +{ + PlanState *outerPlan = outerPlanState(winstate); + int numfuncs = winstate->numfuncs; + + winstate->partition_spooled = false; + winstate->framehead_valid = false; + winstate->frametail_valid = false; + winstate->grouptail_valid = false; + winstate->spooled_rows = 0; + winstate->currentpos = 0; + winstate->frameheadpos = 0; + winstate->frametailpos = 0; + winstate->currentgroup = 0; + winstate->frameheadgroup = 0; + winstate->frametailgroup = 0; + winstate->groupheadpos = 0; + winstate->grouptailpos = -1; /* see update_grouptailpos */ + ExecClearTuple(winstate->agg_row_slot); + if (winstate->framehead_slot) + ExecClearTuple(winstate->framehead_slot); + if (winstate->frametail_slot) + ExecClearTuple(winstate->frametail_slot); + + /* + * If this is the very first partition, we need to fetch the first input + * row to store in first_part_slot. + */ + if (TupIsNull(winstate->first_part_slot)) + { + TupleTableSlot *outerslot = ExecProcNode(outerPlan); + + if (!TupIsNull(outerslot)) + ExecCopySlot(winstate->first_part_slot, outerslot); + else + { + /* outer plan is empty, so we have nothing to do */ + winstate->partition_spooled = true; + winstate->more_partitions = false; + return; + } + } + + /* Create new tuplestore if not done already. */ + if (unlikely(winstate->buffer == NULL)) + prepare_tuplestore(winstate); + + winstate->next_partition = false; + + if (winstate->numaggs > 0) + { + WindowObject agg_winobj = winstate->agg_winobj; + + /* reset mark and see positions for aggregate functions */ + agg_winobj->markpos = -1; + agg_winobj->seekpos = -1; + + /* Also reset the row counters for aggregates */ + winstate->aggregatedbase = 0; + winstate->aggregatedupto = 0; + } + + /* reset mark and seek positions for each real window function */ + for (int i = 0; i < numfuncs; i++) + { + WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]); + + if (!perfuncstate->plain_agg) + { + WindowObject winobj = perfuncstate->winobj; + + winobj->markpos = -1; + winobj->seekpos = -1; + } + } /* * Store the first tuple into the tuplestore (it's always available now; @@ -1360,9 +1401,9 @@ release_partition(WindowAggState *winstate) } if (winstate->buffer) - tuplestore_end(winstate->buffer); - winstate->buffer = NULL; + tuplestore_clear(winstate->buffer); winstate->partition_spooled = false; + winstate->next_partition = true; } /* @@ -2032,6 +2073,82 @@ update_grouptailpos(WindowAggState *winstate) MemoryContextSwitchTo(oldcontext); } +/* + * calculate_frame_offsets + * Determine the startOffsetValue and endOffsetValue values for the + * WindowAgg's frame options. + */ +static pg_noinline void +calculate_frame_offsets(PlanState *pstate) +{ + WindowAggState *winstate = castNode(WindowAggState, pstate); + ExprContext *econtext; + int frameOptions = winstate->frameOptions; + Datum value; + bool isnull; + int16 len; + bool byval; + + /* Ensure we've not been called before for this scan */ + Assert(winstate->all_first); + + econtext = winstate->ss.ps.ps_ExprContext; + + if (frameOptions & FRAMEOPTION_START_OFFSET) + { + Assert(winstate->startOffset != NULL); + value = ExecEvalExprSwitchContext(winstate->startOffset, + econtext, + &isnull); + if (isnull) + ereport(ERROR, + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("frame starting offset must not be null"))); + /* copy value into query-lifespan context */ + get_typlenbyval(exprType((Node *) winstate->startOffset->expr), + &len, + &byval); + winstate->startOffsetValue = datumCopy(value, byval, len); + if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) + { + /* value is known to be int8 */ + int64 offset = DatumGetInt64(value); + + if (offset < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), + errmsg("frame starting offset must not be negative"))); + } + } + + if (frameOptions & FRAMEOPTION_END_OFFSET) + { + Assert(winstate->endOffset != NULL); + value = ExecEvalExprSwitchContext(winstate->endOffset, + econtext, + &isnull); + if (isnull) + ereport(ERROR, + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("frame ending offset must not be null"))); + /* copy value into query-lifespan context */ + get_typlenbyval(exprType((Node *) winstate->endOffset->expr), + &len, + &byval); + winstate->endOffsetValue = datumCopy(value, byval, len); + if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) + { + /* value is known to be int8 */ + int64 offset = DatumGetInt64(value); + + if (offset < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), + errmsg("frame ending offset must not be negative"))); + } + } + winstate->all_first = false; +} /* ----------------- * ExecWindowAgg @@ -2061,73 +2178,13 @@ ExecWindowAgg(PlanState *pstate) * rescan). These are assumed to hold constant throughout the scan; if * user gives us a volatile expression, we'll only use its initial value. */ - if (winstate->all_first) - { - int frameOptions = winstate->frameOptions; - Datum value; - bool isnull; - int16 len; - bool byval; - - econtext = winstate->ss.ps.ps_ExprContext; - - if (frameOptions & FRAMEOPTION_START_OFFSET) - { - Assert(winstate->startOffset != NULL); - value = ExecEvalExprSwitchContext(winstate->startOffset, - econtext, - &isnull); - if (isnull) - ereport(ERROR, - (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("frame starting offset must not be null"))); - /* copy value into query-lifespan context */ - get_typlenbyval(exprType((Node *) winstate->startOffset->expr), - &len, &byval); - winstate->startOffsetValue = datumCopy(value, byval, len); - if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) - { - /* value is known to be int8 */ - int64 offset = DatumGetInt64(value); - - if (offset < 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), - errmsg("frame starting offset must not be negative"))); - } - } - if (frameOptions & FRAMEOPTION_END_OFFSET) - { - Assert(winstate->endOffset != NULL); - value = ExecEvalExprSwitchContext(winstate->endOffset, - econtext, - &isnull); - if (isnull) - ereport(ERROR, - (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("frame ending offset must not be null"))); - /* copy value into query-lifespan context */ - get_typlenbyval(exprType((Node *) winstate->endOffset->expr), - &len, &byval); - winstate->endOffsetValue = datumCopy(value, byval, len); - if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS)) - { - /* value is known to be int8 */ - int64 offset = DatumGetInt64(value); - - if (offset < 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), - errmsg("frame ending offset must not be negative"))); - } - } - winstate->all_first = false; - } + if (unlikely(winstate->all_first)) + calculate_frame_offsets(pstate); /* We need to loop as the runCondition or qual may filter out tuples */ for (;;) { - if (winstate->buffer == NULL) + if (winstate->next_partition) { /* Initialize for first partition and set current row = 0 */ begin_partition(winstate); @@ -2296,6 +2353,23 @@ ExecWindowAgg(PlanState *pstate) */ if (winstate->use_pass_through) { + /* + * When switching into a pass-through mode, we'd better + * NULLify the aggregate results as these are no longer + * updated and NULLifying them avoids the old stale + * results lingering. Some of these might be byref types + * so we can't have them pointing to free'd memory. The + * planner insisted that quals used in the runcondition + * are strict, so the top-level WindowAgg will always + * filter these NULLs out in the filter clause. + */ + numfuncs = winstate->numfuncs; + for (i = 0; i < numfuncs; i++) + { + econtext->ecxt_aggvalues[i] = (Datum) 0; + econtext->ecxt_aggnulls[i] = true; + } + /* * STRICT pass-through mode is required for the top window * when there is a PARTITION BY clause. Otherwise we must @@ -2310,24 +2384,6 @@ ExecWindowAgg(PlanState *pstate) else { winstate->status = WINDOWAGG_PASSTHROUGH; - - /* - * If we're not the top-window, we'd better NULLify - * the aggregate results. In pass-through mode we no - * longer update these and this avoids the old stale - * results lingering. Some of these might be byref - * types so we can't have them pointing to free'd - * memory. The planner insisted that quals used in - * the runcondition are strict, so the top-level - * WindowAgg will filter these NULLs out in the filter - * clause. - */ - numfuncs = winstate->numfuncs; - for (i = 0; i < numfuncs; i++) - { - econtext->ecxt_aggvalues[i] = (Datum) 0; - econtext->ecxt_aggnulls[i] = true; - } } } else @@ -2670,6 +2726,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) winstate->all_first = true; winstate->partition_spooled = false; winstate->more_partitions = false; + winstate->next_partition = true; return winstate; } @@ -2684,6 +2741,14 @@ ExecEndWindowAgg(WindowAggState *node) PlanState *outerPlan; int i; + if (node->buffer != NULL) + { + tuplestore_end(node->buffer); + + /* nullify so that release_partition skips the tuplestore_clear() */ + node->buffer = NULL; + } + release_partition(node); for (i = 0; i < node->numaggs; i++) diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c index 3f883d8ff6638..f6379c35d2f14 100644 --- a/src/backend/executor/nodeWorktablescan.c +++ b/src/backend/executor/nodeWorktablescan.c @@ -3,7 +3,7 @@ * nodeWorktablescan.c * routines to handle WorkTableScan nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index e516c0a67c623..ecb2e4ccaa1ca 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -3,7 +3,7 @@ * spi.c * Server Programming Interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -334,13 +334,13 @@ _SPI_rollback(bool chain) MemoryContext oldcontext = CurrentMemoryContext; SavedTransactionCharacteristics savetc; - /* see under SPI_commit() */ + /* see comments in _SPI_commit() */ if (_SPI_current->atomic) ereport(ERROR, (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION), errmsg("invalid transaction termination"))); - /* see under SPI_commit() */ + /* see comments in _SPI_commit() */ if (IsSubTransaction()) ereport(ERROR, (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION), @@ -582,8 +582,11 @@ SPI_inside_nonatomic_context(void) { if (_SPI_current == NULL) return false; /* not in any SPI context at all */ + /* these tests must match _SPI_commit's opinion of what's atomic: */ if (_SPI_current->atomic) return false; /* it's atomic (ie function not procedure) */ + if (IsSubTransaction()) + return false; /* if within subtransaction, it's atomic */ return true; } @@ -2044,6 +2047,8 @@ SPI_result_code_string(int code) * SPI_plan_get_plan_sources --- get a SPI plan's underlying list of * CachedPlanSources. * + * CAUTION: there is no check on whether the CachedPlanSources are up-to-date. + * * This is exported so that PL/pgSQL can use it (this beats letting PL/pgSQL * look directly into the SPIPlan for itself). It's not documented in * spi.sgml because we'd just as soon not have too many places using this. @@ -2409,9 +2414,12 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, /* * We allow nonatomic behavior only if options->allow_nonatomic is set - * *and* the SPI_OPT_NONATOMIC flag was given when connecting. + * *and* the SPI_OPT_NONATOMIC flag was given when connecting and we are + * not inside a subtransaction. The latter two tests match whether + * _SPI_commit() would allow a commit; see there for more commentary. */ - allow_nonatomic = options->allow_nonatomic && !_SPI_current->atomic; + allow_nonatomic = options->allow_nonatomic && + !_SPI_current->atomic && !IsSubTransaction(); /* * Setup error traceback support for ereport() @@ -2921,7 +2929,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount) ExecutorStart(queryDesc, eflags); - ExecutorRun(queryDesc, ForwardScanDirection, tcount, true); + ExecutorRun(queryDesc, ForwardScanDirection, tcount); _SPI_current->processed = queryDesc->estate->es_processed; @@ -2976,7 +2984,7 @@ _SPI_error_callback(void *arg) switch (carg->mode) { case RAW_PARSE_PLPGSQL_EXPR: - errcontext("SQL expression \"%s\"", query); + errcontext("PL/pgSQL expression \"%s\"", query); break; case RAW_PARSE_PLPGSQL_ASSIGN1: case RAW_PARSE_PLPGSQL_ASSIGN2: diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c index ae3ef69ca9f73..6c5e1f1262d82 100644 --- a/src/backend/executor/tqueue.c +++ b/src/backend/executor/tqueue.c @@ -8,7 +8,7 @@ * * A TupleQueueReader reads tuples from a shm_mq and returns the tuples. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c index de4646b5c26ef..562de67645771 100644 --- a/src/backend/executor/tstoreReceiver.c +++ b/src/backend/executor/tstoreReceiver.c @@ -11,7 +11,7 @@ * Also optionally, we can apply a tuple conversion map before storing. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -65,7 +65,7 @@ tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo) { for (i = 0; i < natts; i++) { - Form_pg_attribute attr = TupleDescAttr(typeinfo, i); + CompactAttribute *attr = TupleDescCompactAttr(typeinfo, i); if (attr->attisdropped) continue; @@ -154,7 +154,7 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self) for (i = 0; i < natts; i++) { Datum val = slot->tts_values[i]; - Form_pg_attribute attr = TupleDescAttr(typeinfo, i); + CompactAttribute *attr = TupleDescCompactAttr(typeinfo, i); if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i]) { diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index f4f35728b4067..a57e59f27ea64 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -3,7 +3,7 @@ * foreign.c * support for foreign-data wrappers, servers and user mappings. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/foreign/foreign.c @@ -22,6 +22,8 @@ #include "foreign/foreign.h" #include "funcapi.h" #include "miscadmin.h" +#include "optimizer/paths.h" +#include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -326,6 +328,15 @@ GetFdwRoutine(Oid fdwhandler) Datum datum; FdwRoutine *routine; + /* Check if the access to foreign tables is restricted */ + if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0)) + { + /* there must not be built-in FDW handler */ + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access to non-system foreign table is restricted"))); + } + datum = OidFunctionCall0(fdwhandler); routine = (FdwRoutine *) DatumGetPointer(datum); @@ -514,7 +525,7 @@ pg_options_to_table(PG_FUNCTION_ARGS) Datum array = PG_GETARG_DATUM(0); ListCell *cell; List *options; - ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + ReturnSetInfo *rsinfo; options = untransformRelOptions(array); rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; @@ -798,7 +809,24 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel) foreign_path = (ForeignPath *) joinpath->outerjoinpath; if (IS_JOIN_REL(foreign_path->path.parent)) + { joinpath->outerjoinpath = foreign_path->fdw_outerpath; + + if (joinpath->path.pathtype == T_MergeJoin) + { + MergePath *merge_path = (MergePath *) joinpath; + + /* + * If the new outer path is already well enough ordered + * for the mergejoin, we can skip doing an explicit sort. + */ + if (merge_path->outersortkeys && + pathkeys_count_contained_in(merge_path->outersortkeys, + joinpath->outerjoinpath->pathkeys, + &merge_path->outer_presorted_keys)) + merge_path->outersortkeys = NIL; + } + } } if (IsA(joinpath->innerjoinpath, ForeignPath)) @@ -807,7 +835,23 @@ GetExistingLocalJoinPath(RelOptInfo *joinrel) foreign_path = (ForeignPath *) joinpath->innerjoinpath; if (IS_JOIN_REL(foreign_path->path.parent)) + { joinpath->innerjoinpath = foreign_path->fdw_outerpath; + + if (joinpath->path.pathtype == T_MergeJoin) + { + MergePath *merge_path = (MergePath *) joinpath; + + /* + * If the new inner path is already well enough ordered + * for the mergejoin, we can skip doing an explicit sort. + */ + if (merge_path->innersortkeys && + pathkeys_contained_in(merge_path->innersortkeys, + joinpath->innerjoinpath->pathkeys)) + merge_path->innersortkeys = NIL; + } + } } return (Path *) joinpath; diff --git a/src/backend/foreign/meson.build b/src/backend/foreign/meson.build index dc511867ab494..219c32f535105 100644 --- a/src/backend/foreign/meson.build +++ b/src/backend/foreign/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'foreign.c' diff --git a/src/backend/jit/README b/src/backend/jit/README index 5427bdf2153ff..a40950dfb039e 100644 --- a/src/backend/jit/README +++ b/src/backend/jit/README @@ -205,7 +205,7 @@ The ability to do so allows us to get the LLVM IR for all operators bitcode files get installed into the server's $pkglibdir/bitcode/postgres/ Using existing LLVM functionality (for parallel LTO compilation), -additionally an index is over these is stored to +additionally an index over these is stored to $pkglibdir/bitcode/postgres.index.bc Similarly extensions can install code into diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c index 815b58f33c547..d2ccef9de8515 100644 --- a/src/backend/jit/jit.c +++ b/src/backend/jit/jit.c @@ -8,7 +8,7 @@ * should end up here. * * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/jit/jit.c diff --git a/src/backend/jit/llvm/Makefile b/src/backend/jit/llvm/Makefile index 0036c4f55209c..e8c12060b93df 100644 --- a/src/backend/jit/llvm/Makefile +++ b/src/backend/jit/llvm/Makefile @@ -37,7 +37,7 @@ SHLIB_LINK += $(LLVM_LIBS) # Because this module includes C++ files, we need to use a C++ # compiler for linking. Makefile.shlib uses $(COMPILER) to build # loadable modules. -override COMPILER = $(CXX) $(CFLAGS) +override COMPILER = $(CXX) $(CXXFLAGS) OBJS = \ $(WIN32RES) @@ -47,7 +47,8 @@ OBJS += \ llvmjit.o \ llvmjit_error.o \ llvmjit_inline.o \ - llvmjit_wrap.o + llvmjit_wrap.o \ + SectionMemoryManager.o # Code generation OBJS += \ diff --git a/src/backend/jit/llvm/SectionMemoryManager.LICENSE b/src/backend/jit/llvm/SectionMemoryManager.LICENSE new file mode 100644 index 0000000000000..fa6ac54000703 --- /dev/null +++ b/src/backend/jit/llvm/SectionMemoryManager.LICENSE @@ -0,0 +1,279 @@ +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + diff --git a/src/backend/jit/llvm/SectionMemoryManager.cpp b/src/backend/jit/llvm/SectionMemoryManager.cpp new file mode 100644 index 0000000000000..2171db5f382d0 --- /dev/null +++ b/src/backend/jit/llvm/SectionMemoryManager.cpp @@ -0,0 +1,412 @@ +/* + * This file is from https://github.com/llvm/llvm-project/pull/71968 + * with minor modifications to avoid name clash and work with older + * LLVM versions. The llvm::backport::SectionMemoryManager class is a + * drop-in replacement for llvm::SectionMemoryManager, for use with + * llvm::RuntimeDyld. It fixes a memory layout bug on large memory + * ARM systems (see pull request for details). If the LLVM project + * eventually commits the change, we may need to resynchronize our + * copy with any further modifications, but they would be unlikely to + * backport it into the LLVM versions that we target so we would still + * need this copy. + * + * In the future we will switch to using JITLink instead of + * RuntimeDyld where possible, and later remove this code (.cpp, .h, + * .LICENSE) after all LLVM versions that we target allow it. + * + * This file is a modified copy of a part of the LLVM source code that + * we would normally access from the LLVM library. It is therefore + * covered by the license at https://llvm.org/LICENSE.txt, reproduced + * verbatim in SectionMemoryManager.LICENSE in fulfillment of clause + * 4a. The bugfix changes from the pull request are also covered, per + * clause 5. + */ + +//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the section-based memory manager used by the MCJIT +// execution engine and RuntimeDyld +// +//===----------------------------------------------------------------------===// + +#include "jit/llvmjit_backport.h" + +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER + +#include "jit/SectionMemoryManager.h" +#include +#include + +namespace llvm { +namespace backport { + +bool SectionMemoryManager::hasSpace(const MemoryGroup &MemGroup, + uintptr_t Size) const { + for (const FreeMemBlock &FreeMB : MemGroup.FreeMem) { + if (FreeMB.Free.allocatedSize() >= Size) + return true; + } + return false; +} + +#if LLVM_VERSION_MAJOR < 16 +void SectionMemoryManager::reserveAllocationSpace(uintptr_t CodeSize, + uint32_t CodeAlign_i, + uintptr_t RODataSize, + uint32_t RODataAlign_i, + uintptr_t RWDataSize, + uint32_t RWDataAlign_i) { + Align CodeAlign(CodeAlign_i); + Align RODataAlign(RODataAlign_i); + Align RWDataAlign(RWDataAlign_i); +#else +void SectionMemoryManager::reserveAllocationSpace( + uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize, + Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) { +#endif + if (CodeSize == 0 && RODataSize == 0 && RWDataSize == 0) + return; + + static const size_t PageSize = sys::Process::getPageSizeEstimate(); + + // Code alignment needs to be at least the stub alignment - however, we + // don't have an easy way to get that here so as a workaround, we assume + // it's 8, which is the largest value I observed across all platforms. + constexpr uint64_t StubAlign = 8; + CodeAlign = Align(std::max(CodeAlign.value(), StubAlign)); + RODataAlign = Align(std::max(RODataAlign.value(), StubAlign)); + RWDataAlign = Align(std::max(RWDataAlign.value(), StubAlign)); + + // Get space required for each section. Use the same calculation as + // allocateSection because we need to be able to satisfy it. + uint64_t RequiredCodeSize = alignTo(CodeSize, CodeAlign) + CodeAlign.value(); + uint64_t RequiredRODataSize = + alignTo(RODataSize, RODataAlign) + RODataAlign.value(); + uint64_t RequiredRWDataSize = + alignTo(RWDataSize, RWDataAlign) + RWDataAlign.value(); + + if (hasSpace(CodeMem, RequiredCodeSize) && + hasSpace(RODataMem, RequiredRODataSize) && + hasSpace(RWDataMem, RequiredRWDataSize)) { + // Sufficient space in contiguous block already available. + return; + } + + // MemoryManager does not have functions for releasing memory after it's + // allocated. Normally it tries to use any excess blocks that were allocated + // due to page alignment, but if we have insufficient free memory for the + // request this can lead to allocating disparate memory that can violate the + // ARM ABI. Clear free memory so only the new allocations are used, but do + // not release allocated memory as it may still be in-use. + CodeMem.FreeMem.clear(); + RODataMem.FreeMem.clear(); + RWDataMem.FreeMem.clear(); + + // Round up to the nearest page size. Blocks must be page-aligned. + RequiredCodeSize = alignTo(RequiredCodeSize, PageSize); + RequiredRODataSize = alignTo(RequiredRODataSize, PageSize); + RequiredRWDataSize = alignTo(RequiredRWDataSize, PageSize); + uint64_t RequiredSize = + RequiredCodeSize + RequiredRODataSize + RequiredRWDataSize; + + std::error_code ec; + sys::MemoryBlock MB = MMapper->allocateMappedMemory( + AllocationPurpose::RWData, RequiredSize, nullptr, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec); + if (ec) { + return; + } + // CodeMem will arbitrarily own this MemoryBlock to handle cleanup. + CodeMem.AllocatedMem.push_back(MB); + uintptr_t Addr = (uintptr_t)MB.base(); + FreeMemBlock FreeMB; + FreeMB.PendingPrefixIndex = (unsigned)-1; + + if (CodeSize > 0) { + assert(isAddrAligned(CodeAlign, (void *)Addr)); + FreeMB.Free = sys::MemoryBlock((void *)Addr, RequiredCodeSize); + CodeMem.FreeMem.push_back(FreeMB); + Addr += RequiredCodeSize; + } + + if (RODataSize > 0) { + assert(isAddrAligned(RODataAlign, (void *)Addr)); + FreeMB.Free = sys::MemoryBlock((void *)Addr, RequiredRODataSize); + RODataMem.FreeMem.push_back(FreeMB); + Addr += RequiredRODataSize; + } + + if (RWDataSize > 0) { + assert(isAddrAligned(RWDataAlign, (void *)Addr)); + FreeMB.Free = sys::MemoryBlock((void *)Addr, RequiredRWDataSize); + RWDataMem.FreeMem.push_back(FreeMB); + } +} + +uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) { + if (IsReadOnly) + return allocateSection(SectionMemoryManager::AllocationPurpose::ROData, + Size, Alignment); + return allocateSection(SectionMemoryManager::AllocationPurpose::RWData, Size, + Alignment); +} + +uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID, + StringRef SectionName) { + return allocateSection(SectionMemoryManager::AllocationPurpose::Code, Size, + Alignment); +} + +uint8_t *SectionMemoryManager::allocateSection( + SectionMemoryManager::AllocationPurpose Purpose, uintptr_t Size, + unsigned Alignment) { + if (!Alignment) + Alignment = 16; + + assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two."); + + uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1) / Alignment + 1); + uintptr_t Addr = 0; + + MemoryGroup &MemGroup = [&]() -> MemoryGroup & { + switch (Purpose) { + case AllocationPurpose::Code: + return CodeMem; + case AllocationPurpose::ROData: + return RODataMem; + case AllocationPurpose::RWData: + return RWDataMem; + } + llvm_unreachable("Unknown SectionMemoryManager::AllocationPurpose"); + }(); + + // Look in the list of free memory regions and use a block there if one + // is available. + for (FreeMemBlock &FreeMB : MemGroup.FreeMem) { + if (FreeMB.Free.allocatedSize() >= RequiredSize) { + Addr = (uintptr_t)FreeMB.Free.base(); + uintptr_t EndOfBlock = Addr + FreeMB.Free.allocatedSize(); + // Align the address. + Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); + + if (FreeMB.PendingPrefixIndex == (unsigned)-1) { + // The part of the block we're giving out to the user is now pending + MemGroup.PendingMem.push_back(sys::MemoryBlock((void *)Addr, Size)); + + // Remember this pending block, such that future allocations can just + // modify it rather than creating a new one + FreeMB.PendingPrefixIndex = MemGroup.PendingMem.size() - 1; + } else { + sys::MemoryBlock &PendingMB = + MemGroup.PendingMem[FreeMB.PendingPrefixIndex]; + PendingMB = sys::MemoryBlock(PendingMB.base(), + Addr + Size - (uintptr_t)PendingMB.base()); + } + + // Remember how much free space is now left in this block + FreeMB.Free = + sys::MemoryBlock((void *)(Addr + Size), EndOfBlock - Addr - Size); + return (uint8_t *)Addr; + } + } + + // No pre-allocated free block was large enough. Allocate a new memory region. + // Note that all sections get allocated as read-write. The permissions will + // be updated later based on memory group. + // + // FIXME: It would be useful to define a default allocation size (or add + // it as a constructor parameter) to minimize the number of allocations. + // + // FIXME: Initialize the Near member for each memory group to avoid + // interleaving. + std::error_code ec; + sys::MemoryBlock MB = MMapper->allocateMappedMemory( + Purpose, RequiredSize, &MemGroup.Near, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, ec); + if (ec) { + // FIXME: Add error propagation to the interface. + return nullptr; + } + + // Save this address as the basis for our next request + MemGroup.Near = MB; + + // Copy the address to all the other groups, if they have not + // been initialized. + if (CodeMem.Near.base() == nullptr) + CodeMem.Near = MB; + if (RODataMem.Near.base() == nullptr) + RODataMem.Near = MB; + if (RWDataMem.Near.base() == nullptr) + RWDataMem.Near = MB; + + // Remember that we allocated this memory + MemGroup.AllocatedMem.push_back(MB); + Addr = (uintptr_t)MB.base(); + uintptr_t EndOfBlock = Addr + MB.allocatedSize(); + + // Align the address. + Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); + + // The part of the block we're giving out to the user is now pending + MemGroup.PendingMem.push_back(sys::MemoryBlock((void *)Addr, Size)); + + // The allocateMappedMemory may allocate much more memory than we need. In + // this case, we store the unused memory as a free memory block. + unsigned FreeSize = EndOfBlock - Addr - Size; + if (FreeSize > 16) { + FreeMemBlock FreeMB; + FreeMB.Free = sys::MemoryBlock((void *)(Addr + Size), FreeSize); + FreeMB.PendingPrefixIndex = (unsigned)-1; + MemGroup.FreeMem.push_back(FreeMB); + } + + // Return aligned address + return (uint8_t *)Addr; +} + +bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) { + // FIXME: Should in-progress permissions be reverted if an error occurs? + std::error_code ec; + + // Make code memory executable. + ec = applyMemoryGroupPermissions(CodeMem, + sys::Memory::MF_READ | sys::Memory::MF_EXEC); + if (ec) { + if (ErrMsg) { + *ErrMsg = ec.message(); + } + return true; + } + + // Make read-only data memory read-only. + ec = applyMemoryGroupPermissions(RODataMem, sys::Memory::MF_READ); + if (ec) { + if (ErrMsg) { + *ErrMsg = ec.message(); + } + return true; + } + + // Read-write data memory already has the correct permissions + + // Some platforms with separate data cache and instruction cache require + // explicit cache flush, otherwise JIT code manipulations (like resolved + // relocations) will get to the data cache but not to the instruction cache. + invalidateInstructionCache(); + + return false; +} + +static sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) { + static const size_t PageSize = sys::Process::getPageSizeEstimate(); + + size_t StartOverlap = + (PageSize - ((uintptr_t)M.base() % PageSize)) % PageSize; + + size_t TrimmedSize = M.allocatedSize(); + TrimmedSize -= StartOverlap; + TrimmedSize -= TrimmedSize % PageSize; + + sys::MemoryBlock Trimmed((void *)((uintptr_t)M.base() + StartOverlap), + TrimmedSize); + + assert(((uintptr_t)Trimmed.base() % PageSize) == 0); + assert((Trimmed.allocatedSize() % PageSize) == 0); + assert(M.base() <= Trimmed.base() && + Trimmed.allocatedSize() <= M.allocatedSize()); + + return Trimmed; +} + +std::error_code +SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, + unsigned Permissions) { + for (sys::MemoryBlock &MB : MemGroup.PendingMem) + if (std::error_code EC = MMapper->protectMappedMemory(MB, Permissions)) + return EC; + + MemGroup.PendingMem.clear(); + + // Now go through free blocks and trim any of them that don't span the entire + // page because one of the pending blocks may have overlapped it. + for (FreeMemBlock &FreeMB : MemGroup.FreeMem) { + FreeMB.Free = trimBlockToPageSize(FreeMB.Free); + // We cleared the PendingMem list, so all these pointers are now invalid + FreeMB.PendingPrefixIndex = (unsigned)-1; + } + + // Remove all blocks which are now empty + erase_if(MemGroup.FreeMem, [](FreeMemBlock &FreeMB) { + return FreeMB.Free.allocatedSize() == 0; + }); + + return std::error_code(); +} + +void SectionMemoryManager::invalidateInstructionCache() { + for (sys::MemoryBlock &Block : CodeMem.PendingMem) + sys::Memory::InvalidateInstructionCache(Block.base(), + Block.allocatedSize()); +} + +SectionMemoryManager::~SectionMemoryManager() { + for (MemoryGroup *Group : {&CodeMem, &RWDataMem, &RODataMem}) { + for (sys::MemoryBlock &Block : Group->AllocatedMem) + MMapper->releaseMappedMemory(Block); + } +} + +SectionMemoryManager::MemoryMapper::~MemoryMapper() = default; + +void SectionMemoryManager::anchor() {} + +namespace { +// Trivial implementation of SectionMemoryManager::MemoryMapper that just calls +// into sys::Memory. +class DefaultMMapper final : public SectionMemoryManager::MemoryMapper { +public: + sys::MemoryBlock + allocateMappedMemory(SectionMemoryManager::AllocationPurpose Purpose, + size_t NumBytes, const sys::MemoryBlock *const NearBlock, + unsigned Flags, std::error_code &EC) override { + return sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, EC); + } + + std::error_code protectMappedMemory(const sys::MemoryBlock &Block, + unsigned Flags) override { + return sys::Memory::protectMappedMemory(Block, Flags); + } + + std::error_code releaseMappedMemory(sys::MemoryBlock &M) override { + return sys::Memory::releaseMappedMemory(M); + } +}; +} // namespace + +SectionMemoryManager::SectionMemoryManager(MemoryMapper *UnownedMM, + bool ReserveAlloc) + : MMapper(UnownedMM), OwnedMMapper(nullptr), + ReserveAllocation(ReserveAlloc) { + if (!MMapper) { + OwnedMMapper = std::make_unique(); + MMapper = OwnedMMapper.get(); + } +} + +} // namespace backport +} // namespace llvm + +#endif diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index 0f6cec524960c..46511624f0166 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -3,7 +3,7 @@ * llvmjit.c * Core part of the LLVM JIT provider. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/jit/llvm/llvmjit.c @@ -21,13 +21,9 @@ #if LLVM_VERSION_MAJOR > 16 #include #endif -#if LLVM_VERSION_MAJOR > 11 #include #include #include -#else -#include -#endif #include #include #if LLVM_VERSION_MAJOR < 17 @@ -38,6 +34,7 @@ #endif #include "jit/llvmjit.h" +#include "jit/llvmjit_backport.h" #include "jit/llvmjit_emit.h" #include "miscadmin.h" #include "portability/instr_time.h" @@ -50,13 +47,8 @@ /* Handle of a module emitted via ORC JIT */ typedef struct LLVMJitHandle { -#if LLVM_VERSION_MAJOR > 11 LLVMOrcLLJITRef lljit; LLVMOrcResourceTrackerRef resource_tracker; -#else - LLVMOrcJITStackRef stack; - LLVMOrcModuleHandle orc_handle; -#endif } LLVMJitHandle; @@ -103,14 +95,9 @@ static LLVMContextRef llvm_context; static LLVMTargetRef llvm_targetref; -#if LLVM_VERSION_MAJOR > 11 static LLVMOrcThreadSafeContextRef llvm_ts_context; static LLVMOrcLLJITRef llvm_opt0_orc; static LLVMOrcLLJITRef llvm_opt3_orc; -#else /* LLVM_VERSION_MAJOR > 11 */ -static LLVMOrcJITStackRef llvm_opt0_orc; -static LLVMOrcJITStackRef llvm_opt3_orc; -#endif /* LLVM_VERSION_MAJOR > 11 */ static void llvm_release_context(JitContext *context); @@ -124,10 +111,8 @@ static void llvm_set_target(void); static void llvm_recreate_llvm_context(void); static uint64_t llvm_resolve_symbol(const char *name, void *ctx); -#if LLVM_VERSION_MAJOR > 11 static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm); static char *llvm_error_message(LLVMErrorRef error); -#endif /* LLVM_VERSION_MAJOR > 11 */ /* ResourceOwner callbacks to hold JitContexts */ static void ResOwnerReleaseJitContext(Datum res); @@ -153,7 +138,10 @@ ResourceOwnerForgetJIT(ResourceOwner owner, LLVMJitContext *handle) ResourceOwnerForget(owner, PointerGetDatum(handle), &jit_resowner_desc); } -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "llvmjit", + .version = PG_VERSION +); /* @@ -292,7 +280,6 @@ llvm_release_context(JitContext *context) { LLVMJitHandle *jit_handle = (LLVMJitHandle *) lfirst(lc); -#if LLVM_VERSION_MAJOR > 11 { LLVMOrcExecutionSessionRef ee; LLVMOrcSymbolStringPoolRef sp; @@ -310,11 +297,6 @@ llvm_release_context(JitContext *context) sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee); LLVMOrcSymbolStringPoolClearDeadEntries(sp); } -#else /* LLVM_VERSION_MAJOR > 11 */ - { - LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle); - } -#endif /* LLVM_VERSION_MAJOR > 11 */ pfree(jit_handle); } @@ -397,7 +379,6 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) * to mangle here. */ -#if LLVM_VERSION_MAJOR > 11 foreach(lc, context->handles) { LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc); @@ -427,19 +408,6 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) if (addr) return (void *) (uintptr_t) addr; } -#else - foreach(lc, context->handles) - { - LLVMOrcTargetAddress addr; - LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc); - - addr = 0; - if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, funcname)) - elog(ERROR, "failed to look up symbol \"%s\"", funcname); - if (addr) - return (void *) (uintptr_t) addr; - } -#endif elog(ERROR, "failed to JIT: %s", funcname); @@ -740,11 +708,7 @@ llvm_compile_module(LLVMJitContext *context) MemoryContext oldcontext; instr_time starttime; instr_time endtime; -#if LLVM_VERSION_MAJOR > 11 LLVMOrcLLJITRef compile_orc; -#else - LLVMOrcJITStackRef compile_orc; -#endif if (context->base.flags & PGJIT_OPT3) compile_orc = llvm_opt3_orc; @@ -801,7 +765,6 @@ llvm_compile_module(LLVMJitContext *context) * faster instruction selection mechanism is used. */ INSTR_TIME_SET_CURRENT(starttime); -#if LLVM_VERSION_MAJOR > 11 { LLVMOrcThreadSafeModuleRef ts_module; LLVMErrorRef error; @@ -829,16 +792,6 @@ llvm_compile_module(LLVMJitContext *context) /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */ } -#else - { - handle->stack = compile_orc; - if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module, - llvm_resolve_symbol, NULL)) - elog(ERROR, "failed to JIT module"); - - /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */ - } -#endif INSTR_TIME_SET_CURRENT(endtime); INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter, @@ -891,19 +844,6 @@ llvm_session_initialize(void) llvm_llvm_context_reuse_count = 0; } - /* - * When targeting LLVM 15, turn off opaque pointers for the context we - * build our code in. We don't need to do so for other contexts (e.g. - * llvm_ts_context). Once the IR is generated, it carries the necessary - * information. - * - * For 16 and above, opaque pointers must be used, and we have special - * code for that. - */ -#if LLVM_VERSION_MAJOR == 15 - LLVMContextSetOpaquePointers(LLVMGetGlobalContext(), false); -#endif - /* * Synchronize types early, as that also includes inferring the target * triple. @@ -950,7 +890,6 @@ llvm_session_initialize(void) /* force symbols in main binary to be loaded */ LLVMLoadLibraryPermanently(NULL); -#if LLVM_VERSION_MAJOR > 11 { llvm_ts_context = LLVMOrcCreateNewThreadSafeContext(); @@ -960,31 +899,6 @@ llvm_session_initialize(void) llvm_opt3_orc = llvm_create_jit_instance(opt3_tm); opt3_tm = 0; } -#else /* LLVM_VERSION_MAJOR > 11 */ - { - llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm); - llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm); - -#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER - if (jit_debugging_support) - { - LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener(); - - LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); - LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); - } -#endif -#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER - if (jit_profiling_support) - { - LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener(); - - LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); - LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); - } -#endif - } -#endif /* LLVM_VERSION_MAJOR > 11 */ on_proc_exit(llvm_shutdown, 0); @@ -1014,7 +928,6 @@ llvm_shutdown(int code, Datum arg) elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)", llvm_jit_context_in_use_count); -#if LLVM_VERSION_MAJOR > 11 { if (llvm_opt3_orc) { @@ -1032,23 +945,6 @@ llvm_shutdown(int code, Datum arg) llvm_ts_context = NULL; } } -#else /* LLVM_VERSION_MAJOR > 11 */ - { - /* unregister profiling support, needs to be flushed to be useful */ - - if (llvm_opt3_orc) - { - LLVMOrcDisposeInstance(llvm_opt3_orc); - llvm_opt3_orc = NULL; - } - - if (llvm_opt0_orc) - { - LLVMOrcDisposeInstance(llvm_opt0_orc); - llvm_opt0_orc = NULL; - } - } -#endif /* LLVM_VERSION_MAJOR > 11 */ } /* helper for llvm_create_types, returning a function's return type */ @@ -1218,8 +1114,6 @@ llvm_resolve_symbol(const char *symname, void *ctx) return (uint64_t) addr; } -#if LLVM_VERSION_MAJOR > 11 - static LLVMErrorRef llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, @@ -1238,9 +1132,7 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, { const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name); -#if LLVM_VERSION_MAJOR > 12 LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name); -#endif symbols[i].Name = LookupSet[i].Name; symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL); symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported; @@ -1278,8 +1170,14 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error) static LLVMOrcObjectLayerRef llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple) { +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER + LLVMOrcObjectLayerRef objlayer = + LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES); +#else LLVMOrcObjectLayerRef objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES); +#endif + #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER if (jit_debugging_support) @@ -1369,8 +1267,6 @@ llvm_error_message(LLVMErrorRef error) return msg; } -#endif /* LLVM_VERSION_MAJOR > 11 */ - /* * ResourceOwner callbacks */ diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c index b07f8e7f75675..c562edd094bb2 100644 --- a/src/backend/jit/llvm/llvmjit_deform.c +++ b/src/backend/jit/llvm/llvmjit_deform.c @@ -7,7 +7,7 @@ * knowledge of the tuple descriptor. Fixed column widths, NOT NULLness, etc * can be taken advantage of. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -110,7 +110,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, */ for (attnum = 0; attnum < desc->natts; attnum++) { - Form_pg_attribute att = TupleDescAttr(desc, attnum); + CompactAttribute *att = TupleDescCompactAttr(desc, attnum); /* * If the column is declared NOT NULL then it must be present in every @@ -123,7 +123,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, * combination of attisdropped && attnotnull combination shouldn't * exist. */ - if (att->attnotnull && + if (att->attnullability == ATTNULLABLE_VALID && !att->atthasmissing && !att->attisdropped) guaranteed_column_number = attnum; @@ -393,9 +393,9 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, */ for (attnum = 0; attnum < natts; attnum++) { - Form_pg_attribute att = TupleDescAttr(desc, attnum); + CompactAttribute *att = TupleDescCompactAttr(desc, attnum); LLVMValueRef v_incby; - int alignto; + int alignto = att->attalignby; LLVMValueRef l_attno = l_int16_const(lc, attnum); LLVMValueRef v_attdatap; LLVMValueRef v_resultp; @@ -438,7 +438,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, * into account, because if they're present the heaptuple's natts * would have indicated that a slot_getmissingattrs() is needed. */ - if (!att->attnotnull) + if (att->attnullability != ATTNULLABLE_VALID) { LLVMBasicBlockRef b_ifnotnull; LLVMBasicBlockRef b_ifnull; @@ -494,21 +494,6 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, } LLVMPositionBuilderAtEnd(b, attcheckalignblocks[attnum]); - /* determine required alignment */ - if (att->attalign == TYPALIGN_INT) - alignto = ALIGNOF_INT; - else if (att->attalign == TYPALIGN_CHAR) - alignto = 1; - else if (att->attalign == TYPALIGN_DOUBLE) - alignto = ALIGNOF_DOUBLE; - else if (att->attalign == TYPALIGN_SHORT) - alignto = ALIGNOF_SHORT; - else - { - elog(ERROR, "unknown alignment"); - alignto = 0; - } - /* ------ * Even if alignment is required, we can skip doing it if provably * unnecessary: @@ -619,7 +604,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, known_alignment = -1; attguaranteedalign = false; } - else if (att->attnotnull && attguaranteedalign && known_alignment >= 0) + else if (att->attnullability == ATTNULLABLE_VALID && + attguaranteedalign && known_alignment >= 0) { /* * If the offset to the column was previously known, a NOT NULL & @@ -629,7 +615,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, Assert(att->attlen > 0); known_alignment += att->attlen; } - else if (att->attnotnull && (att->attlen % alignto) == 0) + else if (att->attnullability == ATTNULLABLE_VALID && + (att->attlen % alignto) == 0) { /* * After a NOT NULL fixed-width column with a length that is a diff --git a/src/backend/jit/llvm/llvmjit_error.cpp b/src/backend/jit/llvm/llvmjit_error.cpp index ebe2f1baa10f8..b16444d978ef6 100644 --- a/src/backend/jit/llvm/llvmjit_error.cpp +++ b/src/backend/jit/llvm/llvmjit_error.cpp @@ -6,7 +6,7 @@ * Unfortunately neither (re)setting the C++ new handler, nor the LLVM OOM * handler are exposed to C. Therefore this file wraps the necessary code. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/jit/llvm/llvmjit_error.cpp @@ -30,13 +30,7 @@ static std::new_handler old_new_handler = NULL; static void fatal_system_new_handler(void); static void fatal_llvm_new_handler(void *user_data, const char *reason, bool gen_crash_diag); -#if LLVM_VERSION_MAJOR < 14 -static void fatal_llvm_new_handler(void *user_data, const std::string& reason, bool gen_crash_diag); -#endif static void fatal_llvm_error_handler(void *user_data, const char *reason, bool gen_crash_diag); -#if LLVM_VERSION_MAJOR < 14 -static void fatal_llvm_error_handler(void *user_data, const std::string& reason, bool gen_crash_diag); -#endif /* @@ -135,15 +129,6 @@ fatal_llvm_new_handler(void *user_data, errmsg("out of memory"), errdetail("While in LLVM: %s", reason))); } -#if LLVM_VERSION_MAJOR < 14 -static void -fatal_llvm_new_handler(void *user_data, - const std::string& reason, - bool gen_crash_diag) -{ - fatal_llvm_new_handler(user_data, reason.c_str(), gen_crash_diag); -} -#endif static void fatal_llvm_error_handler(void *user_data, @@ -154,13 +139,3 @@ fatal_llvm_error_handler(void *user_data, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("fatal llvm error: %s", reason))); } - -#if LLVM_VERSION_MAJOR < 14 -static void -fatal_llvm_error_handler(void *user_data, - const std::string& reason, - bool gen_crash_diag) -{ - fatal_llvm_error_handler(user_data, reason.c_str(), gen_crash_diag); -} -#endif diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index cbd9ed7cc4b65..890bcb0b0a79d 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -3,7 +3,7 @@ * llvmjit_expr.c * JIT compile expressions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -105,6 +105,8 @@ llvm_compile_expr(ExprState *state) LLVMValueRef v_innerslot; LLVMValueRef v_outerslot; LLVMValueRef v_scanslot; + LLVMValueRef v_oldslot; + LLVMValueRef v_newslot; LLVMValueRef v_resultslot; /* nulls/values of slots */ @@ -114,6 +116,10 @@ llvm_compile_expr(ExprState *state) LLVMValueRef v_outernulls; LLVMValueRef v_scanvalues; LLVMValueRef v_scannulls; + LLVMValueRef v_oldvalues; + LLVMValueRef v_oldnulls; + LLVMValueRef v_newvalues; + LLVMValueRef v_newnulls; LLVMValueRef v_resultvalues; LLVMValueRef v_resultnulls; @@ -200,6 +206,16 @@ llvm_compile_expr(ExprState *state) v_econtext, FIELDNO_EXPRCONTEXT_OUTERTUPLE, "v_outerslot"); + v_oldslot = l_load_struct_gep(b, + StructExprContext, + v_econtext, + FIELDNO_EXPRCONTEXT_OLDTUPLE, + "v_oldslot"); + v_newslot = l_load_struct_gep(b, + StructExprContext, + v_econtext, + FIELDNO_EXPRCONTEXT_NEWTUPLE, + "v_newslot"); v_resultslot = l_load_struct_gep(b, StructExprState, v_state, @@ -237,6 +253,26 @@ llvm_compile_expr(ExprState *state) v_outerslot, FIELDNO_TUPLETABLESLOT_ISNULL, "v_outernulls"); + v_oldvalues = l_load_struct_gep(b, + StructTupleTableSlot, + v_oldslot, + FIELDNO_TUPLETABLESLOT_VALUES, + "v_oldvalues"); + v_oldnulls = l_load_struct_gep(b, + StructTupleTableSlot, + v_oldslot, + FIELDNO_TUPLETABLESLOT_ISNULL, + "v_oldnulls"); + v_newvalues = l_load_struct_gep(b, + StructTupleTableSlot, + v_newslot, + FIELDNO_TUPLETABLESLOT_VALUES, + "v_newvalues"); + v_newnulls = l_load_struct_gep(b, + StructTupleTableSlot, + v_newslot, + FIELDNO_TUPLETABLESLOT_ISNULL, + "v_newnulls"); v_resultvalues = l_load_struct_gep(b, StructTupleTableSlot, v_resultslot, @@ -285,7 +321,7 @@ llvm_compile_expr(ExprState *state) switch (opcode) { - case EEOP_DONE: + case EEOP_DONE_RETURN: { LLVMValueRef v_tmpisnull; LLVMValueRef v_tmpvalue; @@ -299,9 +335,15 @@ llvm_compile_expr(ExprState *state) break; } + case EEOP_DONE_NO_RETURN: + LLVMBuildRet(b, l_sizet_const(0)); + break; + case EEOP_INNER_FETCHSOME: case EEOP_OUTER_FETCHSOME: case EEOP_SCAN_FETCHSOME: + case EEOP_OLD_FETCHSOME: + case EEOP_NEW_FETCHSOME: { TupleDesc desc = NULL; LLVMValueRef v_slot; @@ -326,8 +368,12 @@ llvm_compile_expr(ExprState *state) v_slot = v_innerslot; else if (opcode == EEOP_OUTER_FETCHSOME) v_slot = v_outerslot; - else + else if (opcode == EEOP_SCAN_FETCHSOME) v_slot = v_scanslot; + else if (opcode == EEOP_OLD_FETCHSOME) + v_slot = v_oldslot; + else + v_slot = v_newslot; /* * Check if all required attributes are available, or @@ -396,6 +442,8 @@ llvm_compile_expr(ExprState *state) case EEOP_INNER_VAR: case EEOP_OUTER_VAR: case EEOP_SCAN_VAR: + case EEOP_OLD_VAR: + case EEOP_NEW_VAR: { LLVMValueRef value, isnull; @@ -413,11 +461,21 @@ llvm_compile_expr(ExprState *state) v_values = v_outervalues; v_nulls = v_outernulls; } - else + else if (opcode == EEOP_SCAN_VAR) { v_values = v_scanvalues; v_nulls = v_scannulls; } + else if (opcode == EEOP_OLD_VAR) + { + v_values = v_oldvalues; + v_nulls = v_oldnulls; + } + else + { + v_values = v_newvalues; + v_nulls = v_newnulls; + } v_attnum = l_int32_const(lc, op->d.var.attnum); value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, ""); @@ -432,6 +490,8 @@ llvm_compile_expr(ExprState *state) case EEOP_INNER_SYSVAR: case EEOP_OUTER_SYSVAR: case EEOP_SCAN_SYSVAR: + case EEOP_OLD_SYSVAR: + case EEOP_NEW_SYSVAR: { LLVMValueRef v_slot; @@ -439,8 +499,12 @@ llvm_compile_expr(ExprState *state) v_slot = v_innerslot; else if (opcode == EEOP_OUTER_SYSVAR) v_slot = v_outerslot; - else + else if (opcode == EEOP_SCAN_SYSVAR) v_slot = v_scanslot; + else if (opcode == EEOP_OLD_SYSVAR) + v_slot = v_oldslot; + else + v_slot = v_newslot; build_EvalXFunc(b, mod, "ExecEvalSysVar", v_state, op, v_econtext, v_slot); @@ -458,6 +522,8 @@ llvm_compile_expr(ExprState *state) case EEOP_ASSIGN_INNER_VAR: case EEOP_ASSIGN_OUTER_VAR: case EEOP_ASSIGN_SCAN_VAR: + case EEOP_ASSIGN_OLD_VAR: + case EEOP_ASSIGN_NEW_VAR: { LLVMValueRef v_value; LLVMValueRef v_isnull; @@ -478,11 +544,21 @@ llvm_compile_expr(ExprState *state) v_values = v_outervalues; v_nulls = v_outernulls; } - else + else if (opcode == EEOP_ASSIGN_SCAN_VAR) { v_values = v_scanvalues; v_nulls = v_scannulls; } + else if (opcode == EEOP_ASSIGN_OLD_VAR) + { + v_values = v_oldvalues; + v_nulls = v_oldnulls; + } + else + { + v_values = v_newvalues; + v_nulls = v_newnulls; + } /* load data */ v_attnum = l_int32_const(lc, op->d.assign_var.attnum); @@ -586,12 +662,16 @@ llvm_compile_expr(ExprState *state) case EEOP_FUNCEXPR: case EEOP_FUNCEXPR_STRICT: + case EEOP_FUNCEXPR_STRICT_1: + case EEOP_FUNCEXPR_STRICT_2: { FunctionCallInfo fcinfo = op->d.func.fcinfo_data; LLVMValueRef v_fcinfo_isnull; LLVMValueRef v_retval; - if (opcode == EEOP_FUNCEXPR_STRICT) + if (opcode == EEOP_FUNCEXPR_STRICT || + opcode == EEOP_FUNCEXPR_STRICT_1 || + opcode == EEOP_FUNCEXPR_STRICT_2) { LLVMBasicBlockRef b_nonull; LLVMBasicBlockRef *b_checkargnulls; @@ -720,11 +800,6 @@ llvm_compile_expr(ExprState *state) v_boolnull = l_load(b, TypeStorageBool, v_resnullp, ""); v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, ""); - /* set resnull to boolnull */ - LLVMBuildStore(b, v_boolnull, v_resnullp); - /* set revalue to boolvalue */ - LLVMBuildStore(b, v_boolvalue, v_resvaluep); - /* check if current input is NULL */ LLVMBuildCondBr(b, LLVMBuildICmp(b, LLVMIntEQ, v_boolnull, @@ -816,11 +891,6 @@ llvm_compile_expr(ExprState *state) v_boolnull = l_load(b, TypeStorageBool, v_resnullp, ""); v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, ""); - /* set resnull to boolnull */ - LLVMBuildStore(b, v_boolnull, v_resnullp); - /* set revalue to boolvalue */ - LLVMBuildStore(b, v_boolvalue, v_resvaluep); - LLVMBuildCondBr(b, LLVMBuildICmp(b, LLVMIntEQ, v_boolnull, l_sbool_const(1), ""), @@ -875,21 +945,22 @@ llvm_compile_expr(ExprState *state) case EEOP_BOOL_NOT_STEP: { LLVMValueRef v_boolvalue; - LLVMValueRef v_boolnull; LLVMValueRef v_negbool; - v_boolnull = l_load(b, TypeStorageBool, v_resnullp, ""); + /* compute !boolvalue */ v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, ""); - v_negbool = LLVMBuildZExt(b, LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue, l_sizet_const(0), ""), TypeSizeT, ""); - /* set resnull to boolnull */ - LLVMBuildStore(b, v_boolnull, v_resnullp); - /* set revalue to !boolvalue */ + + /* + * Store it back in resvalue. We can ignore resnull here; + * if it was true, it stays true, and the value we store + * in resvalue doesn't matter. + */ LLVMBuildStore(b, v_negbool, v_resvaluep); LLVMBuildBr(b, opblocks[opno + 1]); @@ -1145,6 +1216,12 @@ llvm_compile_expr(ExprState *state) break; } + case EEOP_PARAM_SET: + build_EvalXFunc(b, mod, "ExecEvalParamSet", + v_state, op, v_econtext); + LLVMBuildBr(b, opblocks[opno + 1]); + break; + case EEOP_SBSREF_SUBSCRIPTS: { int jumpdone = op->d.sbsref_subscript.jumpdone; @@ -1196,41 +1273,30 @@ llvm_compile_expr(ExprState *state) case EEOP_CASE_TESTVAL: { - LLVMBasicBlockRef b_avail, - b_notavail; LLVMValueRef v_casevaluep, v_casevalue; LLVMValueRef v_casenullp, v_casenull; - LLVMValueRef v_casevaluenull; - - b_avail = l_bb_before_v(opblocks[opno + 1], - "op.%d.avail", opno); - b_notavail = l_bb_before_v(opblocks[opno + 1], - "op.%d.notavail", opno); v_casevaluep = l_ptr_const(op->d.casetest.value, l_ptr(TypeSizeT)); v_casenullp = l_ptr_const(op->d.casetest.isnull, l_ptr(TypeStorageBool)); - v_casevaluenull = - LLVMBuildICmp(b, LLVMIntEQ, - LLVMBuildPtrToInt(b, v_casevaluep, - TypeSizeT, ""), - l_sizet_const(0), ""); - LLVMBuildCondBr(b, v_casevaluenull, b_notavail, b_avail); - - /* if casetest != NULL */ - LLVMPositionBuilderAtEnd(b, b_avail); v_casevalue = l_load(b, TypeSizeT, v_casevaluep, ""); v_casenull = l_load(b, TypeStorageBool, v_casenullp, ""); LLVMBuildStore(b, v_casevalue, v_resvaluep); LLVMBuildStore(b, v_casenull, v_resnullp); + LLVMBuildBr(b, opblocks[opno + 1]); + break; + } + + case EEOP_CASE_TESTVAL_EXT: + { + LLVMValueRef v_casevalue; + LLVMValueRef v_casenull; - /* if casetest == NULL */ - LLVMPositionBuilderAtEnd(b, b_notavail); v_casevalue = l_load_struct_gep(b, StructExprContext, @@ -1562,6 +1628,9 @@ llvm_compile_expr(ExprState *state) v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData)); + /* save original arg[0] */ + v_arg0 = l_funcvalue(b, v_fcinfo, 0); + /* if either argument is NULL they can't be equal */ v_argnull0 = l_funcnull(b, v_fcinfo, 0); v_argnull1 = l_funcnull(b, v_fcinfo, 1); @@ -1578,7 +1647,6 @@ llvm_compile_expr(ExprState *state) /* one (or both) of the arguments are null, return arg[0] */ LLVMPositionBuilderAtEnd(b, b_hasnull); - v_arg0 = l_funcvalue(b, v_fcinfo, 0); LLVMBuildStore(b, v_argnull0, v_resnullp); LLVMBuildStore(b, v_arg0, v_resvaluep); LLVMBuildBr(b, opblocks[opno + 1]); @@ -1586,12 +1654,35 @@ llvm_compile_expr(ExprState *state) /* build block to invoke function and check result */ LLVMPositionBuilderAtEnd(b, b_nonull); + /* + * If first argument is of varlena type, it might be an + * expanded datum. We need to ensure that the value + * passed to the comparison function is a read-only + * pointer. However, if we end by returning the first + * argument, that will be the original read-write pointer + * if it was read-write. + */ + if (op->d.func.make_ro) + { + LLVMValueRef v_params[1]; + LLVMValueRef v_arg0_ro; + + v_params[0] = v_arg0; + v_arg0_ro = + l_call(b, + llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"), + llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"), + v_params, lengthof(v_params), ""); + LLVMBuildStore(b, v_arg0_ro, + l_funcvaluep(b, v_fcinfo, 0)); + } + v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull); /* - * If result not null, and arguments are equal return null - * (same result as if there'd been NULLs, hence reuse - * b_hasnull). + * If result not null and arguments are equal return null, + * else return arg[0] (same result as if there'd been + * NULLs, hence reuse b_hasnull). */ v_argsequal = LLVMBuildAnd(b, LLVMBuildICmp(b, LLVMIntEQ, @@ -1609,7 +1700,6 @@ llvm_compile_expr(ExprState *state) LLVMPositionBuilderAtEnd(b, b_argsequal); LLVMBuildStore(b, l_sbool_const(1), v_resnullp); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); - LLVMBuildStore(b, v_retval, v_resvaluep); LLVMBuildBr(b, opblocks[opno + 1]); break; @@ -1633,6 +1723,45 @@ llvm_compile_expr(ExprState *state) LLVMBuildBr(b, opblocks[opno + 1]); break; + case EEOP_RETURNINGEXPR: + { + LLVMBasicBlockRef b_isnull; + LLVMValueRef v_flagsp; + LLVMValueRef v_flags; + LLVMValueRef v_nullflag; + + b_isnull = l_bb_before_v(opblocks[opno + 1], + "op.%d.row.isnull", opno); + + /* + * The next op actually evaluates the expression. If the + * OLD/NEW row doesn't exist, skip that and return NULL. + */ + v_flagsp = l_struct_gep(b, + StructExprState, + v_state, + FIELDNO_EXPRSTATE_FLAGS, + "v.state.flags"); + v_flags = l_load(b, TypeStorageBool, v_flagsp, ""); + + v_nullflag = l_int8_const(lc, op->d.returningexpr.nullflag); + + LLVMBuildCondBr(b, + LLVMBuildICmp(b, LLVMIntEQ, + LLVMBuildAnd(b, v_flags, + v_nullflag, ""), + l_sbool_const(0), ""), + opblocks[opno + 1], b_isnull); + + LLVMPositionBuilderAtEnd(b, b_isnull); + + LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); + LLVMBuildStore(b, l_sbool_const(1), v_resnullp); + + LLVMBuildBr(b, opblocks[op->d.returningexpr.jumpdone]); + break; + } + case EEOP_ARRAYEXPR: build_EvalXFunc(b, mod, "ExecEvalArrayExpr", v_state, op); @@ -1749,7 +1878,7 @@ llvm_compile_expr(ExprState *state) case EEOP_ROWCOMPARE_FINAL: { - RowCompareType rctype = op->d.rowcompare_final.rctype; + CompareType cmptype = op->d.rowcompare_final.cmptype; LLVMValueRef v_cmpresult; LLVMValueRef v_result; @@ -1765,18 +1894,18 @@ llvm_compile_expr(ExprState *state) l_load(b, TypeSizeT, v_resvaluep, ""), LLVMInt32TypeInContext(lc), ""); - switch (rctype) + switch (cmptype) { - case ROWCOMPARE_LT: + case COMPARE_LT: predicate = LLVMIntSLT; break; - case ROWCOMPARE_LE: + case COMPARE_LE: predicate = LLVMIntSLE; break; - case ROWCOMPARE_GT: + case COMPARE_GT: predicate = LLVMIntSGT; break; - case ROWCOMPARE_GE: + case COMPARE_GE: predicate = LLVMIntSGE; break; default: @@ -1826,43 +1955,30 @@ llvm_compile_expr(ExprState *state) case EEOP_DOMAIN_TESTVAL: { - LLVMBasicBlockRef b_avail, - b_notavail; LLVMValueRef v_casevaluep, v_casevalue; LLVMValueRef v_casenullp, v_casenull; - LLVMValueRef v_casevaluenull; - - b_avail = l_bb_before_v(opblocks[opno + 1], - "op.%d.avail", opno); - b_notavail = l_bb_before_v(opblocks[opno + 1], - "op.%d.notavail", opno); v_casevaluep = l_ptr_const(op->d.casetest.value, l_ptr(TypeSizeT)); v_casenullp = l_ptr_const(op->d.casetest.isnull, l_ptr(TypeStorageBool)); - v_casevaluenull = - LLVMBuildICmp(b, LLVMIntEQ, - LLVMBuildPtrToInt(b, v_casevaluep, - TypeSizeT, ""), - l_sizet_const(0), ""); - LLVMBuildCondBr(b, - v_casevaluenull, - b_notavail, b_avail); - - /* if casetest != NULL */ - LLVMPositionBuilderAtEnd(b, b_avail); v_casevalue = l_load(b, TypeSizeT, v_casevaluep, ""); v_casenull = l_load(b, TypeStorageBool, v_casenullp, ""); LLVMBuildStore(b, v_casevalue, v_resvaluep); LLVMBuildStore(b, v_casenull, v_resnullp); + LLVMBuildBr(b, opblocks[opno + 1]); + break; + } + + case EEOP_DOMAIN_TESTVAL_EXT: + { + LLVMValueRef v_casevalue; + LLVMValueRef v_casenull; - /* if casetest == NULL */ - LLVMPositionBuilderAtEnd(b, b_notavail); v_casevalue = l_load_struct_gep(b, StructExprContext, @@ -1894,6 +2010,216 @@ llvm_compile_expr(ExprState *state) LLVMBuildBr(b, opblocks[opno + 1]); break; + case EEOP_HASHDATUM_SET_INITVAL: + { + LLVMValueRef v_initvalue; + + v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value); + + LLVMBuildStore(b, v_initvalue, v_resvaluep); + LLVMBuildStore(b, l_sbool_const(0), v_resnullp); + LLVMBuildBr(b, opblocks[opno + 1]); + break; + } + + case EEOP_HASHDATUM_FIRST: + case EEOP_HASHDATUM_FIRST_STRICT: + case EEOP_HASHDATUM_NEXT32: + case EEOP_HASHDATUM_NEXT32_STRICT: + { + FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data; + LLVMValueRef v_fcinfo; + LLVMValueRef v_fcinfo_isnull; + LLVMValueRef v_retval; + LLVMBasicBlockRef b_checkargnull; + LLVMBasicBlockRef b_ifnotnull; + LLVMBasicBlockRef b_ifnullblock; + LLVMValueRef v_argisnull; + LLVMValueRef v_prevhash = NULL; + + /* + * When performing the next hash and not in strict mode we + * perform a rotation of the previously stored hash value + * before doing the NULL check. We want to do this even + * when we receive a NULL Datum to hash. In strict mode, + * we do this after the NULL check so as not to waste the + * effort of rotating the bits when we're going to throw + * away the hash value and return NULL. + */ + if (opcode == EEOP_HASHDATUM_NEXT32) + { + LLVMValueRef v_tmp1; + LLVMValueRef v_tmp2; + LLVMValueRef tmp; + + tmp = l_ptr_const(&op->d.hashdatum.iresult->value, + l_ptr(TypeSizeT)); + + /* + * Fetch the previously hashed value from where the + * previous hash operation stored it. + */ + v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash"); + + /* + * Rotate bits left by 1 bit. Be careful not to + * overflow uint32 when working with size_t. + */ + v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1), + ""); + v_tmp1 = LLVMBuildAnd(b, v_tmp1, + l_sizet_const(0xffffffff), ""); + v_tmp2 = LLVMBuildLShr(b, v_prevhash, + l_sizet_const(31), ""); + v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2, + "rotatedhash"); + } + + /* + * Block for the actual function call, if args are + * non-NULL. + */ + b_ifnotnull = l_bb_before_v(opblocks[opno + 1], + "b.%d.ifnotnull", + opno); + + /* we expect the hash function to have 1 argument */ + if (fcinfo->nargs != 1) + elog(ERROR, "incorrect number of function arguments"); + + v_fcinfo = l_ptr_const(fcinfo, + l_ptr(StructFunctionCallInfoData)); + + b_checkargnull = l_bb_before_v(b_ifnotnull, + "b.%d.isnull.0", opno); + + LLVMBuildBr(b, b_checkargnull); + + /* + * Determine what to do if we find the argument to be + * NULL. + */ + if (opcode == EEOP_HASHDATUM_FIRST_STRICT || + opcode == EEOP_HASHDATUM_NEXT32_STRICT) + { + b_ifnullblock = l_bb_before_v(b_ifnotnull, + "b.%d.strictnull", + opno); + + LLVMPositionBuilderAtEnd(b, b_ifnullblock); + + /* + * In strict node, NULL inputs result in NULL. Save + * the NULL result and goto jumpdone. + */ + LLVMBuildStore(b, l_sbool_const(1), v_resnullp); + LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); + LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]); + } + else + { + b_ifnullblock = l_bb_before_v(b_ifnotnull, + "b.%d.null", + opno); + + LLVMPositionBuilderAtEnd(b, b_ifnullblock); + + + LLVMBuildStore(b, l_sbool_const(0), v_resnullp); + + if (opcode == EEOP_HASHDATUM_NEXT32) + { + Assert(v_prevhash != NULL); + + /* + * Save the rotated hash value and skip to the + * next op. + */ + LLVMBuildStore(b, v_prevhash, v_resvaluep); + } + else + { + Assert(opcode == EEOP_HASHDATUM_FIRST); + + /* + * Store a zero Datum when the Datum to hash is + * NULL + */ + LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); + } + + LLVMBuildBr(b, opblocks[opno + 1]); + } + + LLVMPositionBuilderAtEnd(b, b_checkargnull); + + /* emit code to check if the input parameter is NULL */ + v_argisnull = l_funcnull(b, v_fcinfo, 0); + LLVMBuildCondBr(b, + LLVMBuildICmp(b, + LLVMIntEQ, + v_argisnull, + l_sbool_const(1), + ""), + b_ifnullblock, + b_ifnotnull); + + LLVMPositionBuilderAtEnd(b, b_ifnotnull); + + /* + * Rotate the previously stored hash value when performing + * NEXT32 in strict mode. In non-strict mode we already + * did this before checking for NULLs. + */ + if (opcode == EEOP_HASHDATUM_NEXT32_STRICT) + { + LLVMValueRef v_tmp1; + LLVMValueRef v_tmp2; + LLVMValueRef tmp; + + tmp = l_ptr_const(&op->d.hashdatum.iresult->value, + l_ptr(TypeSizeT)); + + /* + * Fetch the previously hashed value from where the + * previous hash operation stored it. + */ + v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash"); + + /* + * Rotate bits left by 1 bit. Be careful not to + * overflow uint32 when working with size_t. + */ + v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1), + ""); + v_tmp1 = LLVMBuildAnd(b, v_tmp1, + l_sizet_const(0xffffffff), ""); + v_tmp2 = LLVMBuildLShr(b, v_prevhash, + l_sizet_const(31), ""); + v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2, + "rotatedhash"); + } + + /* call the hash function */ + v_retval = BuildV1Call(context, b, mod, fcinfo, + &v_fcinfo_isnull); + + /* + * For NEXT32 ops, XOR (^) the returned hash value with + * the existing hash value. + */ + if (opcode == EEOP_HASHDATUM_NEXT32 || + opcode == EEOP_HASHDATUM_NEXT32_STRICT) + v_retval = LLVMBuildXor(b, v_prevhash, v_retval, + "xorhash"); + + LLVMBuildStore(b, v_retval, v_resvaluep); + LLVMBuildStore(b, l_sbool_const(0), v_resnullp); + + LLVMBuildBr(b, opblocks[opno + 1]); + break; + } + case EEOP_CONVERT_ROWTYPE: build_EvalXFunc(b, mod, "ExecEvalConvertRowtype", v_state, op, v_econtext); @@ -2160,6 +2486,7 @@ llvm_compile_expr(ExprState *state) } case EEOP_AGG_STRICT_INPUT_CHECK_ARGS: + case EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1: case EEOP_AGG_STRICT_INPUT_CHECK_NULLS: { int nargs = op->d.agg_strict_input_check.nargs; diff --git a/src/backend/jit/llvm/llvmjit_inline.cpp b/src/backend/jit/llvm/llvmjit_inline.cpp index 2007eb523c9b6..2764c3bbe2f03 100644 --- a/src/backend/jit/llvm/llvmjit_inline.cpp +++ b/src/backend/jit/llvm/llvmjit_inline.cpp @@ -11,7 +11,7 @@ * so for all external functions, all the referenced functions (and * prerequisites) will be imported. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/llvmjit/llvmjit_inline.cpp @@ -594,10 +594,6 @@ function_inlinable(llvm::Function &F, if (F.materialize()) elog(FATAL, "failed to materialize metadata"); -#if LLVM_VERSION_MAJOR < 14 -#define hasFnAttr hasFnAttribute -#endif - if (F.getAttributes().hasFnAttr(llvm::Attribute::NoInline)) { ilog(DEBUG1, "ineligibile to import %s due to noinline", @@ -858,9 +854,6 @@ create_redirection_function(std::unique_ptr &importMod, llvm::Function *AF; llvm::BasicBlock *BB; llvm::CallInst *fwdcall; -#if LLVM_VERSION_MAJOR < 14 - llvm::Attribute inlineAttribute; -#endif AF = llvm::Function::Create(F->getFunctionType(), LinkageTypes::AvailableExternallyLinkage, @@ -869,13 +862,7 @@ create_redirection_function(std::unique_ptr &importMod, Builder.SetInsertPoint(BB); fwdcall = Builder.CreateCall(F, &*AF->arg_begin()); -#if LLVM_VERSION_MAJOR < 14 - inlineAttribute = llvm::Attribute::get(Context, - llvm::Attribute::AlwaysInline); - fwdcall->addAttribute(~0U, inlineAttribute); -#else fwdcall->addFnAttr(llvm::Attribute::AlwaysInline); -#endif Builder.CreateRet(fwdcall); return AF; diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index f93c383fd52c5..dbe0282e98f4b 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -16,7 +16,7 @@ * bitcode. * * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/jit/llvm/llvmjit_types.c @@ -117,11 +117,9 @@ ExecEvalBoolSubroutineTemplate(ExprState *state, } /* - * Clang represents stdbool.h style booleans that are returned by functions - * differently (as i1) than stored ones (as i8). Therefore we do not just need - * TypeBool (above), but also a way to determine the width of a returned - * integer. This allows us to keep compatible with non-stdbool using - * architectures. + * Clang represents bool returned by functions differently (as i1) than stored + * ones (as i8). Therefore we do not just need TypeStorageBool (above), but + * also a way to determine the width of a returned integer. */ extern bool FunctionReturningBool(void); bool @@ -160,6 +158,7 @@ void *referenced_functions[] = ExecEvalNextValueExpr, ExecEvalParamExec, ExecEvalParamExtern, + ExecEvalParamSet, ExecEvalRow, ExecEvalRowNotNull, ExecEvalRowNull, diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp index 641c8841ca3ea..da850d67ab647 100644 --- a/src/backend/jit/llvm/llvmjit_wrap.cpp +++ b/src/backend/jit/llvm/llvmjit_wrap.cpp @@ -3,7 +3,7 @@ * llvmjit_wrap.cpp * Parts of the LLVM interface not (yet) exposed to C. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/llvm/llvmjit_wrap.cpp @@ -17,13 +17,17 @@ extern "C" } #include - -/* Avoid macro clash with LLVM's C++ headers */ -#undef Min - #include #include "jit/llvmjit.h" +#include "jit/llvmjit_backport.h" + +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER +#include +#include +#include "jit/SectionMemoryManager.h" +#include +#endif /* @@ -41,3 +45,15 @@ LLVMGetFunctionType(LLVMValueRef r) { return llvm::wrap(llvm::unwrap(r)->getFunctionType()); } + +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ExecutionSession, LLVMOrcExecutionSessionRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ObjectLayer, LLVMOrcObjectLayerRef); + +LLVMOrcObjectLayerRef +LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES) +{ + return wrap(new llvm::orc::RTDyldObjectLinkingLayer( + *unwrap(ES), [] { return std::make_unique(nullptr, true); })); +} +#endif diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build index 4a4232661ba4f..c8e06dfbe351b 100644 --- a/src/backend/jit/llvm/meson.build +++ b/src/backend/jit/llvm/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not llvm.found() subdir_done() @@ -14,6 +14,7 @@ llvmjit_sources += files( 'llvmjit_error.cpp', 'llvmjit_inline.cpp', 'llvmjit_wrap.cpp', + 'SectionMemoryManager.cpp', ) # Code generation @@ -60,9 +61,6 @@ endif # XXX: Need to determine proper version of the function cflags for clang bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv'] -if llvm.version().version_compare('=15.0') - bitcode_cflags += ['-Xclang', '-no-opaque-pointers'] -endif bitcode_cflags += get_option('c_args') bitcode_cflags += cppflags diff --git a/src/backend/jit/meson.build b/src/backend/jit/meson.build index 42951a87944fb..c83d056254584 100644 --- a/src/backend/jit/meson.build +++ b/src/backend/jit/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'jit.c' diff --git a/src/backend/lib/bipartite_match.c b/src/backend/lib/bipartite_match.c index e01514e96ea98..5af789652c794 100644 --- a/src/backend/lib/bipartite_match.c +++ b/src/backend/lib/bipartite_match.c @@ -7,7 +7,7 @@ * * https://en.wikipedia.org/w/index.php?title=Hopcroft%E2%80%93Karp_algorithm&oldid=593898016 * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/bipartite_match.c diff --git a/src/backend/lib/bloomfilter.c b/src/backend/lib/bloomfilter.c index 360d21ca45be5..d3f935170db4b 100644 --- a/src/backend/lib/bloomfilter.c +++ b/src/backend/lib/bloomfilter.c @@ -24,7 +24,7 @@ * caller many authoritative lookups, such as expensive probes of a much larger * on-disk structure. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/bloomfilter.c diff --git a/src/backend/lib/dshash.c b/src/backend/lib/dshash.c index 93a9e21ddd209..b8d031f201520 100644 --- a/src/backend/lib/dshash.c +++ b/src/backend/lib/dshash.c @@ -20,7 +20,7 @@ * Future versions may support iterators and incremental resizing; for now * the implementation is minimalist. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -887,8 +887,10 @@ resize(dshash_table *hash_table, size_t new_size_log2) Assert(new_size_log2 == hash_table->control->size_log2 + 1); /* Allocate the space for the new table. */ - new_buckets_shared = dsa_allocate0(hash_table->area, - sizeof(dsa_pointer) * new_size); + new_buckets_shared = + dsa_allocate_extended(hash_table->area, + sizeof(dsa_pointer) * new_size, + DSA_ALLOC_HUGE | DSA_ALLOC_ZERO); new_buckets = dsa_get_address(hash_table->area, new_buckets_shared); /* diff --git a/src/backend/lib/hyperloglog.c b/src/backend/lib/hyperloglog.c index 0c4191af8f56e..0144ecb5d6345 100644 --- a/src/backend/lib/hyperloglog.c +++ b/src/backend/lib/hyperloglog.c @@ -3,7 +3,7 @@ * hyperloglog.c * HyperLogLog cardinality estimator * - * Portions Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2014-2025, PostgreSQL Global Development Group * * Based on Hideaki Ohno's C++ implementation. This is probably not ideally * suited to estimating the cardinality of very large sets; in particular, we diff --git a/src/backend/lib/ilist.c b/src/backend/lib/ilist.c index ce6306f0c233b..2862dce479672 100644 --- a/src/backend/lib/ilist.c +++ b/src/backend/lib/ilist.c @@ -3,7 +3,7 @@ * ilist.c * support for integrated/inline doubly- and singly- linked lists * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/lib/integerset.c b/src/backend/lib/integerset.c index 9f1d4db52b2df..f4153b0e15a24 100644 --- a/src/backend/lib/integerset.c +++ b/src/backend/lib/integerset.c @@ -61,7 +61,7 @@ * (https://doi.org/10.1002/spe.948) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -72,7 +72,6 @@ #include "postgres.h" #include "lib/integerset.h" -#include "port/pg_bitutils.h" #include "utils/memutils.h" diff --git a/src/backend/lib/knapsack.c b/src/backend/lib/knapsack.c index 5aa8f3791b415..5b3697a090fa6 100644 --- a/src/backend/lib/knapsack.c +++ b/src/backend/lib/knapsack.c @@ -15,7 +15,7 @@ * allows approximate solutions in polynomial time (the general case of the * exact problem is NP-hard). * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/knapsack.c diff --git a/src/backend/lib/meson.build b/src/backend/lib/meson.build index 956536078e4fd..463612fe97636 100644 --- a/src/backend/lib/meson.build +++ b/src/backend/lib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bipartite_match.c', diff --git a/src/backend/lib/pairingheap.c b/src/backend/lib/pairingheap.c index fe1deba13ec3c..0aef8a88f1b5e 100644 --- a/src/backend/lib/pairingheap.c +++ b/src/backend/lib/pairingheap.c @@ -14,7 +14,7 @@ * The pairing heap: a new form of self-adjusting heap. * Algorithmica 1, 1 (January 1986), pages 111-129. DOI: 10.1007/BF01840439 * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/pairingheap.c diff --git a/src/backend/lib/rbtree.c b/src/backend/lib/rbtree.c index 19ae7482321e5..3b5e5faa9bf5f 100644 --- a/src/backend/lib/rbtree.c +++ b/src/backend/lib/rbtree.c @@ -17,7 +17,7 @@ * longest path from root to leaf is only about twice as long as the shortest, * so lookups are guaranteed to run in O(lg n) time. * - * Copyright (c) 2009-2024, PostgreSQL Global Development Group + * Copyright (c) 2009-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/lib/rbtree.c diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile index 6d385fd6a450d..98eb2a8242d55 100644 --- a/src/backend/libpq/Makefile +++ b/src/backend/libpq/Makefile @@ -15,6 +15,7 @@ include $(top_builddir)/src/Makefile.global # be-fsstubs is here for historical reasons, probably belongs elsewhere OBJS = \ + auth-oauth.o \ auth-sasl.o \ auth-scram.o \ auth.o \ diff --git a/src/backend/libpq/auth-oauth.c b/src/backend/libpq/auth-oauth.c new file mode 100644 index 0000000000000..27f7af7be0024 --- /dev/null +++ b/src/backend/libpq/auth-oauth.c @@ -0,0 +1,894 @@ +/*------------------------------------------------------------------------- + * + * auth-oauth.c + * Server-side implementation of the SASL OAUTHBEARER mechanism. + * + * See the following RFC for more details: + * - RFC 7628: https://datatracker.ietf.org/doc/html/rfc7628 + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/backend/libpq/auth-oauth.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include + +#include "common/oauth-common.h" +#include "fmgr.h" +#include "lib/stringinfo.h" +#include "libpq/auth.h" +#include "libpq/hba.h" +#include "libpq/oauth.h" +#include "libpq/sasl.h" +#include "storage/fd.h" +#include "storage/ipc.h" +#include "utils/json.h" +#include "utils/varlena.h" + +/* GUC */ +char *oauth_validator_libraries_string = NULL; + +static void oauth_get_mechanisms(Port *port, StringInfo buf); +static void *oauth_init(Port *port, const char *selected_mech, const char *shadow_pass); +static int oauth_exchange(void *opaq, const char *input, int inputlen, + char **output, int *outputlen, const char **logdetail); + +static void load_validator_library(const char *libname); +static void shutdown_validator_library(void *arg); + +static ValidatorModuleState *validator_module_state; +static const OAuthValidatorCallbacks *ValidatorCallbacks; + +/* Mechanism declaration */ +const pg_be_sasl_mech pg_be_oauth_mech = { + .get_mechanisms = oauth_get_mechanisms, + .init = oauth_init, + .exchange = oauth_exchange, + + .max_message_length = PG_MAX_AUTH_TOKEN_LENGTH, +}; + +/* Valid states for the oauth_exchange() machine. */ +enum oauth_state +{ + OAUTH_STATE_INIT = 0, + OAUTH_STATE_ERROR, + OAUTH_STATE_FINISHED, +}; + +/* Mechanism callback state. */ +struct oauth_ctx +{ + enum oauth_state state; + Port *port; + const char *issuer; + const char *scope; +}; + +static char *sanitize_char(char c); +static char *parse_kvpairs_for_auth(char **input); +static void generate_error_response(struct oauth_ctx *ctx, char **output, int *outputlen); +static bool validate(Port *port, const char *auth); + +/* Constants seen in an OAUTHBEARER client initial response. */ +#define KVSEP 0x01 /* separator byte for key/value pairs */ +#define AUTH_KEY "auth" /* key containing the Authorization header */ +#define BEARER_SCHEME "Bearer " /* required header scheme (case-insensitive!) */ + +/* + * Retrieves the OAUTHBEARER mechanism list (currently a single item). + * + * For a full description of the API, see libpq/sasl.h. + */ +static void +oauth_get_mechanisms(Port *port, StringInfo buf) +{ + /* Only OAUTHBEARER is supported. */ + appendStringInfoString(buf, OAUTHBEARER_NAME); + appendStringInfoChar(buf, '\0'); +} + +/* + * Initializes mechanism state and loads the configured validator module. + * + * For a full description of the API, see libpq/sasl.h. + */ +static void * +oauth_init(Port *port, const char *selected_mech, const char *shadow_pass) +{ + struct oauth_ctx *ctx; + + if (strcmp(selected_mech, OAUTHBEARER_NAME) != 0) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("client selected an invalid SASL authentication mechanism")); + + ctx = palloc0(sizeof(*ctx)); + + ctx->state = OAUTH_STATE_INIT; + ctx->port = port; + + Assert(port->hba); + ctx->issuer = port->hba->oauth_issuer; + ctx->scope = port->hba->oauth_scope; + + load_validator_library(port->hba->oauth_validator); + + return ctx; +} + +/* + * Implements the OAUTHBEARER SASL exchange (RFC 7628, Sec. 3.2). This pulls + * apart the client initial response and validates the Bearer token. It also + * handles the dummy error response for a failed handshake, as described in + * Sec. 3.2.3. + * + * For a full description of the API, see libpq/sasl.h. + */ +static int +oauth_exchange(void *opaq, const char *input, int inputlen, + char **output, int *outputlen, const char **logdetail) +{ + char *input_copy; + char *p; + char cbind_flag; + char *auth; + int status; + + struct oauth_ctx *ctx = opaq; + + *output = NULL; + *outputlen = -1; + + /* + * If the client didn't include an "Initial Client Response" in the + * SASLInitialResponse message, send an empty challenge, to which the + * client will respond with the same data that usually comes in the + * Initial Client Response. + */ + if (input == NULL) + { + Assert(ctx->state == OAUTH_STATE_INIT); + + *output = pstrdup(""); + *outputlen = 0; + return PG_SASL_EXCHANGE_CONTINUE; + } + + /* + * Check that the input length agrees with the string length of the input. + */ + if (inputlen == 0) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("The message is empty.")); + if (inputlen != strlen(input)) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message length does not match input length.")); + + switch (ctx->state) + { + case OAUTH_STATE_INIT: + /* Handle this case below. */ + break; + + case OAUTH_STATE_ERROR: + + /* + * Only one response is valid for the client during authentication + * failure: a single kvsep. + */ + if (inputlen != 1 || *input != KVSEP) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Client did not send a kvsep response.")); + + /* The (failed) handshake is now complete. */ + ctx->state = OAUTH_STATE_FINISHED; + return PG_SASL_EXCHANGE_FAILURE; + + default: + elog(ERROR, "invalid OAUTHBEARER exchange state"); + return PG_SASL_EXCHANGE_FAILURE; + } + + /* Handle the client's initial message. */ + p = input_copy = pstrdup(input); + + /* + * OAUTHBEARER does not currently define a channel binding (so there is no + * OAUTHBEARER-PLUS, and we do not accept a 'p' specifier). We accept a + * 'y' specifier purely for the remote chance that a future specification + * could define one; then future clients can still interoperate with this + * server implementation. 'n' is the expected case. + */ + cbind_flag = *p; + switch (cbind_flag) + { + case 'p': + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("The server does not support channel binding for OAuth, but the client message includes channel binding data.")); + break; + + case 'y': /* fall through */ + case 'n': + p++; + if (*p != ',') + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Comma expected, but found character \"%s\".", + sanitize_char(*p))); + p++; + break; + + default: + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Unexpected channel-binding flag \"%s\".", + sanitize_char(cbind_flag))); + } + + /* + * Forbid optional authzid (authorization identity). We don't support it. + */ + if (*p == 'a') + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("client uses authorization identity, but it is not supported")); + if (*p != ',') + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Unexpected attribute \"%s\" in client-first-message.", + sanitize_char(*p))); + p++; + + /* All remaining fields are separated by the RFC's kvsep (\x01). */ + if (*p != KVSEP) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Key-value separator expected, but found character \"%s\".", + sanitize_char(*p))); + p++; + + auth = parse_kvpairs_for_auth(&p); + if (!auth) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message does not contain an auth value.")); + + /* We should be at the end of our message. */ + if (*p) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains additional data after the final terminator.")); + + if (!validate(ctx->port, auth)) + { + generate_error_response(ctx, output, outputlen); + + ctx->state = OAUTH_STATE_ERROR; + status = PG_SASL_EXCHANGE_CONTINUE; + } + else + { + ctx->state = OAUTH_STATE_FINISHED; + status = PG_SASL_EXCHANGE_SUCCESS; + } + + /* Don't let extra copies of the bearer token hang around. */ + explicit_bzero(input_copy, inputlen); + + return status; +} + +/* + * Convert an arbitrary byte to printable form. For error messages. + * + * If it's a printable ASCII character, print it as a single character. + * otherwise, print it in hex. + * + * The returned pointer points to a static buffer. + */ +static char * +sanitize_char(char c) +{ + static char buf[5]; + + if (c >= 0x21 && c <= 0x7E) + snprintf(buf, sizeof(buf), "'%c'", c); + else + snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c); + return buf; +} + +/* + * Performs syntactic validation of a key and value from the initial client + * response. (Semantic validation of interesting values must be performed + * later.) + */ +static void +validate_kvpair(const char *key, const char *val) +{ + /*----- + * From Sec 3.1: + * key = 1*(ALPHA) + */ + static const char *key_allowed_set = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + size_t span; + + if (!key[0]) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains an empty key name.")); + + span = strspn(key, key_allowed_set); + if (key[span] != '\0') + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains an invalid key name.")); + + /*----- + * From Sec 3.1: + * value = *(VCHAR / SP / HTAB / CR / LF ) + * + * The VCHAR (visible character) class is large; a loop is more + * straightforward than strspn(). + */ + for (; *val; ++val) + { + if (0x21 <= *val && *val <= 0x7E) + continue; /* VCHAR */ + + switch (*val) + { + case ' ': + case '\t': + case '\r': + case '\n': + continue; /* SP, HTAB, CR, LF */ + + default: + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains an invalid value.")); + } + } +} + +/* + * Consumes all kvpairs in an OAUTHBEARER exchange message. If the "auth" key is + * found, its value is returned. + */ +static char * +parse_kvpairs_for_auth(char **input) +{ + char *pos = *input; + char *auth = NULL; + + /*---- + * The relevant ABNF, from Sec. 3.1: + * + * kvsep = %x01 + * key = 1*(ALPHA) + * value = *(VCHAR / SP / HTAB / CR / LF ) + * kvpair = key "=" value kvsep + * ;;gs2-header = See RFC 5801 + * client-resp = (gs2-header kvsep *kvpair kvsep) / kvsep + * + * By the time we reach this code, the gs2-header and initial kvsep have + * already been validated. We start at the beginning of the first kvpair. + */ + + while (*pos) + { + char *end; + char *sep; + char *key; + char *value; + + /* + * Find the end of this kvpair. Note that input is null-terminated by + * the SASL code, so the strchr() is bounded. + */ + end = strchr(pos, KVSEP); + if (!end) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains an unterminated key/value pair.")); + *end = '\0'; + + if (pos == end) + { + /* Empty kvpair, signifying the end of the list. */ + *input = pos + 1; + return auth; + } + + /* + * Find the end of the key name. + */ + sep = strchr(pos, '='); + if (!sep) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains a key without a value.")); + *sep = '\0'; + + /* Both key and value are now safely terminated. */ + key = pos; + value = sep + 1; + validate_kvpair(key, value); + + if (strcmp(key, AUTH_KEY) == 0) + { + if (auth) + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message contains multiple auth values.")); + + auth = value; + } + else + { + /* + * The RFC also defines the host and port keys, but they are not + * required for OAUTHBEARER and we do not use them. Also, per Sec. + * 3.1, any key/value pairs we don't recognize must be ignored. + */ + } + + /* Move to the next pair. */ + pos = end + 1; + } + + ereport(ERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAUTHBEARER message"), + errdetail("Message did not contain a final terminator.")); + + pg_unreachable(); + return NULL; +} + +/* + * Builds the JSON response for failed authentication (RFC 7628, Sec. 3.2.2). + * This contains the required scopes for entry and a pointer to the OAuth/OpenID + * discovery document, which the client may use to conduct its OAuth flow. + */ +static void +generate_error_response(struct oauth_ctx *ctx, char **output, int *outputlen) +{ + StringInfoData buf; + StringInfoData issuer; + + /* + * The admin needs to set an issuer and scope for OAuth to work. There's + * not really a way to hide this from the user, either, because we can't + * choose a "default" issuer, so be honest in the failure message. (In + * practice such configurations are rejected during HBA parsing.) + */ + if (!ctx->issuer || !ctx->scope) + ereport(FATAL, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("OAuth is not properly configured for this user"), + errdetail_log("The issuer and scope parameters must be set in pg_hba.conf.")); + + /* + * Build a default .well-known URI based on our issuer, unless the HBA has + * already provided one. + */ + initStringInfo(&issuer); + appendStringInfoString(&issuer, ctx->issuer); + if (strstr(ctx->issuer, "/.well-known/") == NULL) + appendStringInfoString(&issuer, "/.well-known/openid-configuration"); + + initStringInfo(&buf); + + /* + * Escaping the string here is belt-and-suspenders defensive programming + * since escapable characters aren't valid in either the issuer URI or the + * scope list, but the HBA doesn't enforce that yet. + */ + appendStringInfoString(&buf, "{ \"status\": \"invalid_token\", "); + + appendStringInfoString(&buf, "\"openid-configuration\": "); + escape_json(&buf, issuer.data); + pfree(issuer.data); + + appendStringInfoString(&buf, ", \"scope\": "); + escape_json(&buf, ctx->scope); + + appendStringInfoString(&buf, " }"); + + *output = buf.data; + *outputlen = buf.len; +} + +/*----- + * Validates the provided Authorization header and returns the token from + * within it. NULL is returned on validation failure. + * + * Only Bearer tokens are accepted. The ABNF is defined in RFC 6750, Sec. + * 2.1: + * + * b64token = 1*( ALPHA / DIGIT / + * "-" / "." / "_" / "~" / "+" / "/" ) *"=" + * credentials = "Bearer" 1*SP b64token + * + * The "credentials" construction is what we receive in our auth value. + * + * Since that spec is subordinate to HTTP (i.e. the HTTP Authorization + * header format; RFC 9110 Sec. 11), the "Bearer" scheme string must be + * compared case-insensitively. (This is not mentioned in RFC 6750, but the + * OAUTHBEARER spec points it out: RFC 7628 Sec. 4.) + * + * Invalid formats are technically a protocol violation, but we shouldn't + * reflect any information about the sensitive Bearer token back to the + * client; log at COMMERROR instead. + */ +static const char * +validate_token_format(const char *header) +{ + size_t span; + const char *token; + static const char *const b64token_allowed_set = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-._~+/"; + + /* Missing auth headers should be handled by the caller. */ + Assert(header); + + if (header[0] == '\0') + { + /* + * A completely empty auth header represents a query for + * authentication parameters. The client expects it to fail; there's + * no need to make any extra noise in the logs. + * + * TODO: should we find a way to return STATUS_EOF at the top level, + * to suppress the authentication error entirely? + */ + return NULL; + } + + if (pg_strncasecmp(header, BEARER_SCHEME, strlen(BEARER_SCHEME))) + { + ereport(COMMERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAuth bearer token"), + errdetail_log("Client response indicated a non-Bearer authentication scheme.")); + return NULL; + } + + /* Pull the bearer token out of the auth value. */ + token = header + strlen(BEARER_SCHEME); + + /* Swallow any additional spaces. */ + while (*token == ' ') + token++; + + /* Tokens must not be empty. */ + if (!*token) + { + ereport(COMMERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAuth bearer token"), + errdetail_log("Bearer token is empty.")); + return NULL; + } + + /* + * Make sure the token contains only allowed characters. Tokens may end + * with any number of '=' characters. + */ + span = strspn(token, b64token_allowed_set); + while (token[span] == '=') + span++; + + if (token[span] != '\0') + { + /* + * This error message could be more helpful by printing the + * problematic character(s), but that'd be a bit like printing a piece + * of someone's password into the logs. + */ + ereport(COMMERROR, + errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("malformed OAuth bearer token"), + errdetail_log("Bearer token is not in the correct format.")); + return NULL; + } + + return token; +} + +/* + * Checks that the "auth" kvpair in the client response contains a syntactically + * valid Bearer token, then passes it along to the loaded validator module for + * authorization. Returns true if validation succeeds. + */ +static bool +validate(Port *port, const char *auth) +{ + int map_status; + ValidatorModuleResult *ret; + const char *token; + bool status; + + /* Ensure that we have a correct token to validate */ + if (!(token = validate_token_format(auth))) + return false; + + /* + * Ensure that we have a validation library loaded, this should always be + * the case and an error here is indicative of a bug. + */ + if (!ValidatorCallbacks || !ValidatorCallbacks->validate_cb) + ereport(FATAL, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("validation of OAuth token requested without a validator loaded")); + + /* Call the validation function from the validator module */ + ret = palloc0(sizeof(ValidatorModuleResult)); + if (!ValidatorCallbacks->validate_cb(validator_module_state, token, + port->user_name, ret)) + { + ereport(WARNING, + errcode(ERRCODE_INTERNAL_ERROR), + errmsg("internal error in OAuth validator module")); + return false; + } + + /* + * Log any authentication results even if the token isn't authorized; it + * might be useful for auditing or troubleshooting. + */ + if (ret->authn_id) + set_authn_id(port, ret->authn_id); + + if (!ret->authorized) + { + ereport(LOG, + errmsg("OAuth bearer authentication failed for user \"%s\"", + port->user_name), + errdetail_log("Validator failed to authorize the provided token.")); + + status = false; + goto cleanup; + } + + if (port->hba->oauth_skip_usermap) + { + /* + * If the validator is our authorization authority, we're done. + * Authentication may or may not have been performed depending on the + * validator implementation; all that matters is that the validator + * says the user can log in with the target role. + */ + status = true; + goto cleanup; + } + + /* Make sure the validator authenticated the user. */ + if (ret->authn_id == NULL || ret->authn_id[0] == '\0') + { + ereport(LOG, + errmsg("OAuth bearer authentication failed for user \"%s\"", + port->user_name), + errdetail_log("Validator provided no identity.")); + + status = false; + goto cleanup; + } + + /* Finally, check the user map. */ + map_status = check_usermap(port->hba->usermap, port->user_name, + MyClientConnectionInfo.authn_id, false); + status = (map_status == STATUS_OK); + +cleanup: + + /* + * Clear and free the validation result from the validator module once + * we're done with it. + */ + if (ret->authn_id != NULL) + pfree(ret->authn_id); + pfree(ret); + + return status; +} + +/* + * load_validator_library + * + * Load the configured validator library in order to perform token validation. + * There is no built-in fallback since validation is implementation specific. If + * no validator library is configured, or if it fails to load, then error out + * since token validation won't be possible. + */ +static void +load_validator_library(const char *libname) +{ + OAuthValidatorModuleInit validator_init; + MemoryContextCallback *mcb; + + /* + * The presence, and validity, of libname has already been established by + * check_oauth_validator so we don't need to perform more than Assert + * level checking here. + */ + Assert(libname && *libname); + + validator_init = (OAuthValidatorModuleInit) + load_external_function(libname, "_PG_oauth_validator_module_init", + false, NULL); + + /* + * The validator init function is required since it will set the callbacks + * for the validator library. + */ + if (validator_init == NULL) + ereport(ERROR, + errmsg("%s module \"%s\" must define the symbol %s", + "OAuth validator", libname, "_PG_oauth_validator_module_init")); + + ValidatorCallbacks = (*validator_init) (); + Assert(ValidatorCallbacks); + + /* + * Check the magic number, to protect against break-glass scenarios where + * the ABI must change within a major version. load_external_function() + * already checks for compatibility across major versions. + */ + if (ValidatorCallbacks->magic != PG_OAUTH_VALIDATOR_MAGIC) + ereport(ERROR, + errmsg("%s module \"%s\": magic number mismatch", + "OAuth validator", libname), + errdetail("Server has magic number 0x%08X, module has 0x%08X.", + PG_OAUTH_VALIDATOR_MAGIC, ValidatorCallbacks->magic)); + + /* + * Make sure all required callbacks are present in the ValidatorCallbacks + * structure. Right now only the validation callback is required. + */ + if (ValidatorCallbacks->validate_cb == NULL) + ereport(ERROR, + errmsg("%s module \"%s\" must provide a %s callback", + "OAuth validator", libname, "validate_cb")); + + /* Allocate memory for validator library private state data */ + validator_module_state = (ValidatorModuleState *) palloc0(sizeof(ValidatorModuleState)); + validator_module_state->sversion = PG_VERSION_NUM; + + if (ValidatorCallbacks->startup_cb != NULL) + ValidatorCallbacks->startup_cb(validator_module_state); + + /* Shut down the library before cleaning up its state. */ + mcb = palloc0(sizeof(*mcb)); + mcb->func = shutdown_validator_library; + + MemoryContextRegisterResetCallback(CurrentMemoryContext, mcb); +} + +/* + * Call the validator module's shutdown callback, if one is provided. This is + * invoked during memory context reset. + */ +static void +shutdown_validator_library(void *arg) +{ + if (ValidatorCallbacks->shutdown_cb != NULL) + ValidatorCallbacks->shutdown_cb(validator_module_state); +} + +/* + * Ensure an OAuth validator named in the HBA is permitted by the configuration. + * + * If the validator is currently unset and exactly one library is declared in + * oauth_validator_libraries, then that library will be used as the validator. + * Otherwise the name must be present in the list of oauth_validator_libraries. + */ +bool +check_oauth_validator(HbaLine *hbaline, int elevel, char **err_msg) +{ + int line_num = hbaline->linenumber; + const char *file_name = hbaline->sourcefile; + char *rawstring; + List *elemlist = NIL; + + *err_msg = NULL; + + if (oauth_validator_libraries_string[0] == '\0') + { + ereport(elevel, + errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("oauth_validator_libraries must be set for authentication method %s", + "oauth"), + errcontext("line %d of configuration file \"%s\"", + line_num, file_name)); + *err_msg = psprintf("oauth_validator_libraries must be set for authentication method %s", + "oauth"); + return false; + } + + /* SplitDirectoriesString needs a modifiable copy */ + rawstring = pstrdup(oauth_validator_libraries_string); + + if (!SplitDirectoriesString(rawstring, ',', &elemlist)) + { + /* syntax error in list */ + ereport(elevel, + errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid list syntax in parameter \"%s\"", + "oauth_validator_libraries")); + *err_msg = psprintf("invalid list syntax in parameter \"%s\"", + "oauth_validator_libraries"); + goto done; + } + + if (!hbaline->oauth_validator) + { + if (elemlist->length == 1) + { + hbaline->oauth_validator = pstrdup(linitial(elemlist)); + goto done; + } + + ereport(elevel, + errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options"), + errcontext("line %d of configuration file \"%s\"", + line_num, file_name)); + *err_msg = "authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options"; + goto done; + } + + foreach_ptr(char, allowed, elemlist) + { + if (strcmp(allowed, hbaline->oauth_validator) == 0) + goto done; + } + + ereport(elevel, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("validator \"%s\" is not permitted by %s", + hbaline->oauth_validator, "oauth_validator_libraries"), + errcontext("line %d of configuration file \"%s\"", + line_num, file_name)); + *err_msg = psprintf("validator \"%s\" is not permitted by %s", + hbaline->oauth_validator, "oauth_validator_libraries"); + +done: + list_free_deep(elemlist); + pfree(rawstring); + + return (*err_msg == NULL); +} diff --git a/src/backend/libpq/auth-sasl.c b/src/backend/libpq/auth-sasl.c index 08b24d90b4bf6..52c79882c1137 100644 --- a/src/backend/libpq/auth-sasl.c +++ b/src/backend/libpq/auth-sasl.c @@ -3,7 +3,7 @@ * auth-sasl.c * Routines to handle authentication via SASL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -20,14 +20,6 @@ #include "libpq/pqformat.h" #include "libpq/sasl.h" -/* - * Maximum accepted size of SASL messages. - * - * The messages that the server or libpq generate are much smaller than this, - * but have some headroom. - */ -#define PG_MAX_SASL_MESSAGE_LENGTH 1024 - /* * Perform a SASL exchange with a libpq client, using a specific mechanism * implementation. @@ -103,7 +95,7 @@ CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, char *shadow_pass, /* Get the actual SASL message */ initStringInfo(&buf); - if (pq_getmessage(&buf, PG_MAX_SASL_MESSAGE_LENGTH)) + if (pq_getmessage(&buf, mech->max_message_length)) { /* EOF - pq_getmessage already logged error */ pfree(buf.data); diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 03ddddc3c27ab..db778405724ad 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -80,7 +80,7 @@ * general, after logging in, but let's do what we can here. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/auth-scram.c @@ -101,6 +101,7 @@ #include "libpq/crypt.h" #include "libpq/sasl.h" #include "libpq/scram.h" +#include "miscadmin.h" static void scram_get_mechanisms(Port *port, StringInfo buf); static void *scram_init(Port *port, const char *selected_mech, @@ -113,7 +114,9 @@ static int scram_exchange(void *opaq, const char *input, int inputlen, const pg_be_sasl_mech pg_be_scram_mech = { scram_get_mechanisms, scram_init, - scram_exchange + scram_exchange, + + PG_MAX_SASL_MESSAGE_LENGTH }; /* @@ -142,6 +145,7 @@ typedef struct int iterations; char *salt; /* base64-encoded */ + uint8 ClientKey[SCRAM_MAX_KEY_LEN]; uint8 StoredKey[SCRAM_MAX_KEY_LEN]; uint8 ServerKey[SCRAM_MAX_KEY_LEN]; @@ -154,7 +158,7 @@ typedef struct /* Fields from the last message from client */ char *client_final_message_without_proof; char *client_final_nonce; - char ClientProof[SCRAM_MAX_KEY_LEN]; + uint8 ClientProof[SCRAM_MAX_KEY_LEN]; /* Fields generated in the server */ char *server_first_message; @@ -182,9 +186,9 @@ static void mock_scram_secret(const char *username, pg_cryptohash_type *hash_typ static bool is_scram_printable(char *p); static char *sanitize_char(char c); static char *sanitize_str(const char *s); -static char *scram_mock_salt(const char *username, - pg_cryptohash_type hash_type, - int key_length); +static uint8 *scram_mock_salt(const char *username, + pg_cryptohash_type hash_type, + int key_length); /* * The number of iterations to use when generating new secrets. @@ -460,6 +464,13 @@ scram_exchange(void *opaq, const char *input, int inputlen, if (*output) *outputlen = strlen(*output); + if (result == PG_SASL_EXCHANGE_SUCCESS && state->state == SCRAM_AUTH_FINISHED) + { + memcpy(MyProcPort->scram_ClientKey, state->ClientKey, sizeof(MyProcPort->scram_ClientKey)); + memcpy(MyProcPort->scram_ServerKey, state->ServerKey, sizeof(MyProcPort->scram_ServerKey)); + MyProcPort->has_scram_keys = true; + } + return result; } @@ -473,7 +484,7 @@ pg_be_scram_build_secret(const char *password) { char *prep_password; pg_saslprep_rc rc; - char saltbuf[SCRAM_DEFAULT_SALT_LEN]; + uint8 saltbuf[SCRAM_DEFAULT_SALT_LEN]; char *result; const char *errstr = NULL; @@ -513,7 +524,7 @@ scram_verify_plain_password(const char *username, const char *password, const char *secret) { char *encoded_salt; - char *salt; + uint8 *salt; int saltlen; int iterations; int key_length = 0; @@ -598,9 +609,9 @@ parse_scram_secret(const char *secret, int *iterations, char *storedkey_str; char *serverkey_str; int decoded_len; - char *decoded_salt_buf; - char *decoded_stored_buf; - char *decoded_server_buf; + uint8 *decoded_salt_buf; + uint8 *decoded_stored_buf; + uint8 *decoded_server_buf; /* * The secret is of form: @@ -608,13 +619,17 @@ parse_scram_secret(const char *secret, int *iterations, * SCRAM-SHA-256$:$: */ v = pstrdup(secret); - if ((scheme_str = strsep(&v, "$")) == NULL) + scheme_str = strsep(&v, "$"); + if (v == NULL) goto invalid_secret; - if ((iterations_str = strsep(&v, ":")) == NULL) + iterations_str = strsep(&v, ":"); + if (v == NULL) goto invalid_secret; - if ((salt_str = strsep(&v, "$")) == NULL) + salt_str = strsep(&v, "$"); + if (v == NULL) goto invalid_secret; - if ((storedkey_str = strsep(&v, ":")) == NULL) + storedkey_str = strsep(&v, ":"); + if (v == NULL) goto invalid_secret; serverkey_str = v; @@ -683,7 +698,7 @@ mock_scram_secret(const char *username, pg_cryptohash_type *hash_type, int *iterations, int *key_length, char **salt, uint8 *stored_key, uint8 *server_key) { - char *raw_salt; + uint8 *raw_salt; char *encoded_salt; int encoded_len; @@ -1134,7 +1149,6 @@ static bool verify_client_proof(scram_state *state) { uint8 ClientSignature[SCRAM_MAX_KEY_LEN]; - uint8 ClientKey[SCRAM_MAX_KEY_LEN]; uint8 client_StoredKey[SCRAM_MAX_KEY_LEN]; pg_hmac_ctx *ctx = pg_hmac_create(state->hash_type); int i; @@ -1167,10 +1181,10 @@ verify_client_proof(scram_state *state) /* Extract the ClientKey that the client calculated from the proof */ for (i = 0; i < state->key_length; i++) - ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i]; + state->ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i]; /* Hash it one more time, and compare with StoredKey */ - if (scram_H(ClientKey, state->hash_type, state->key_length, + if (scram_H(state->ClientKey, state->hash_type, state->key_length, client_StoredKey, &errstr) < 0) elog(ERROR, "could not hash stored key: %s", errstr); @@ -1217,7 +1231,7 @@ build_server_first_message(scram_state *state) * For convenience, however, we don't use the whole range available, * rather, we generate some random bytes, and base64 encode them. */ - char raw_nonce[SCRAM_RAW_NONCE_LEN]; + uint8 raw_nonce[SCRAM_RAW_NONCE_LEN]; int encoded_len; if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN)) @@ -1257,7 +1271,7 @@ read_client_final_message(scram_state *state, const char *input) char *begin, *proof; char *p; - char *client_proof; + uint8 *client_proof; int client_proof_len; begin = p = pstrdup(input); @@ -1326,7 +1340,7 @@ read_client_final_message(scram_state *state, const char *input) b64_message_len = pg_b64_enc_len(cbind_input_len); /* don't forget the zero-terminator */ b64_message = palloc(b64_message_len + 1); - b64_message_len = pg_b64_encode(cbind_input, cbind_input_len, + b64_message_len = pg_b64_encode((uint8 *) cbind_input, cbind_input_len, b64_message, b64_message_len); if (b64_message_len < 0) elog(ERROR, "could not encode channel binding data"); @@ -1426,7 +1440,7 @@ build_server_final_message(scram_state *state) siglen = pg_b64_enc_len(state->key_length); /* don't forget the zero-terminator */ server_signature_base64 = palloc(siglen + 1); - siglen = pg_b64_encode((const char *) ServerSignature, + siglen = pg_b64_encode(ServerSignature, state->key_length, server_signature_base64, siglen); if (siglen < 0) @@ -1453,7 +1467,7 @@ build_server_final_message(scram_state *state) * hash based on the username and a cluster-level secret key. Returns a * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN, or NULL. */ -static char * +static uint8 * scram_mock_salt(const char *username, pg_cryptohash_type hash_type, int key_length) { @@ -1487,5 +1501,5 @@ scram_mock_salt(const char *username, pg_cryptohash_type hash_type, } pg_cryptohash_free(ctx); - return (char *) sha_digest; + return sha_digest; } diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 2b607c52704ca..9f4d05ffbd453 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -3,7 +3,7 @@ * auth.c * Routines to handle network authentication * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -29,6 +29,7 @@ #include "libpq/auth.h" #include "libpq/crypt.h" #include "libpq/libpq.h" +#include "libpq/oauth.h" #include "libpq/pqformat.h" #include "libpq/sasl.h" #include "libpq/scram.h" @@ -37,6 +38,7 @@ #include "postmaster/postmaster.h" #include "replication/walsender.h" #include "storage/ipc.h" +#include "tcop/backend_startup.h" #include "utils/memutils.h" /*---------------------------------------------------------------- @@ -45,7 +47,6 @@ */ static void auth_failed(Port *port, int status, const char *logdetail); static char *recv_password_packet(Port *port); -static void set_authn_id(Port *port, const char *id); /*---------------------------------------------------------------- @@ -201,22 +202,6 @@ static int CheckRADIUSAuth(Port *port); static int PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd); -/* - * Maximum accepted size of GSS and SSPI authentication tokens. - * We also use this as a limit on ordinary password packet lengths. - * - * Kerberos tickets are usually quite small, but the TGTs issued by Windows - * domain controllers include an authorization field known as the Privilege - * Attribute Certificate (PAC), which contains the user's Windows permissions - * (group memberships etc.). The PAC is copied into all tickets obtained on - * the basis of this TGT (even those issued by Unix realms which the Windows - * realm trusts), and can be several kB in size. The maximum token size - * accepted by Windows systems is determined by the MaxAuthToken Windows - * registry setting. Microsoft recommends that it is not set higher than - * 65535 bytes, so that seems like a reasonable limit for us as well. - */ -#define PG_MAX_AUTH_TOKEN_LENGTH 65535 - /*---------------------------------------------------------------- * Global authentication functions *---------------------------------------------------------------- @@ -305,6 +290,9 @@ auth_failed(Port *port, int status, const char *logdetail) case uaRADIUS: errstr = gettext_noop("RADIUS authentication failed for user \"%s\""); break; + case uaOAuth: + errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\""); + break; default: errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method"); break; @@ -330,7 +318,8 @@ auth_failed(Port *port, int status, const char *logdetail) /* * Sets the authenticated identity for the current user. The provided string * will be stored into MyClientConnectionInfo, alongside the current HBA - * method in use. The ID will be logged if log_connections is enabled. + * method in use. The ID will be logged if log_connections has the + * 'authentication' option specified. * * Auth methods should call this routine exactly once, as soon as the user is * successfully authenticated, even if they have reasons to know that @@ -340,7 +329,7 @@ auth_failed(Port *port, int status, const char *logdetail) * lifetime of MyClientConnectionInfo, so it is safe to pass a string that is * managed by an external library. */ -static void +void set_authn_id(Port *port, const char *id) { Assert(id); @@ -362,7 +351,7 @@ set_authn_id(Port *port, const char *id) MyClientConnectionInfo.authn_id = MemoryContextStrdup(TopMemoryContext, id); MyClientConnectionInfo.auth_method = port->hba->auth_method; - if (Log_connections) + if (log_connections & LOG_CONNECTION_AUTHENTICATION) { ereport(LOG, errmsg("connection authenticated: identity=\"%s\" method=%s " @@ -627,6 +616,9 @@ ClientAuthentication(Port *port) case uaTrust: status = STATUS_OK; break; + case uaOAuth: + status = CheckSASLAuth(&pg_be_oauth_mech, port, NULL, NULL); + break; } if ((status == STATUS_OK && port->hba->clientcert == clientCertFull) @@ -643,7 +635,8 @@ ClientAuthentication(Port *port) #endif } - if (Log_connections && status == STATUS_OK && + if ((log_connections & LOG_CONNECTION_AUTHENTICATION) && + status == STATUS_OK && !MyClientConnectionInfo.authn_id) { /* @@ -673,7 +666,7 @@ ClientAuthentication(Port *port) * Send an authentication request packet to the frontend. */ void -sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen) +sendAuthRequest(Port *port, AuthRequest areq, const void *extradata, int extralen) { StringInfoData buf; @@ -881,7 +874,7 @@ CheckPWChallengeAuth(Port *port, const char **logdetail) static int CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail) { - char md5Salt[4]; /* Password salt */ + uint8 md5Salt[4]; /* Password salt */ char *passwd; int result; @@ -1857,7 +1850,10 @@ auth_peer(hbaPort *port) uid_t uid; gid_t gid; #ifndef WIN32 + struct passwd pwbuf; struct passwd *pw; + char buf[1024]; + int rc; int ret; #endif @@ -1876,16 +1872,18 @@ auth_peer(hbaPort *port) } #ifndef WIN32 - errno = 0; /* clear errno before call */ - pw = getpwuid(uid); - if (!pw) + rc = getpwuid_r(uid, &pwbuf, buf, sizeof buf, &pw); + if (rc != 0) + { + errno = rc; + ereport(LOG, + errmsg("could not look up local user ID %ld: %m", (long) uid)); + return STATUS_ERROR; + } + else if (!pw) { - int save_errno = errno; - ereport(LOG, - (errmsg("could not look up local user ID %ld: %s", - (long) uid, - save_errno ? strerror(save_errno) : _("user does not exist")))); + errmsg("local user with ID %ld does not exist", (long) uid)); return STATUS_ERROR; } @@ -2937,8 +2935,8 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por radius_packet radius_recv_pack; radius_packet *packet = &radius_send_pack; radius_packet *receivepacket = &radius_recv_pack; - char *radius_buffer = (char *) &radius_send_pack; - char *receive_buffer = (char *) &radius_recv_pack; + void *radius_buffer = &radius_send_pack; + void *receive_buffer = &radius_recv_pack; int32 service = pg_hton32(RADIUS_AUTHENTICATE_ONLY); uint8 *cryptvector; int encryptedpasswordlen; @@ -3209,7 +3207,9 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por * original packet */ if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no * attributes at all */ - memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH); + memcpy(cryptvector + RADIUS_HEADER_LENGTH, + (char *) receive_buffer + RADIUS_HEADER_LENGTH, + packetlength - RADIUS_HEADER_LENGTH); memcpy(cryptvector + packetlength, secret, strlen(secret)); if (!pg_md5_binary(cryptvector, diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c index 27d317dfdc087..e5a34c6193165 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -3,7 +3,7 @@ * be-fsstubs.c * Builtin functions for open/close/read/write operations on large objects * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -317,6 +317,11 @@ be_lo_unlink(PG_FUNCTION_ARGS) PreventCommandIfReadOnly("lo_unlink()"); + if (!LargeObjectExists(lobjId)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("large object %u does not exist", lobjId))); + /* * Must be owner of the large object. It would be cleaner to check this * in inv_drop(), but we want to throw the error before not after closing diff --git a/src/backend/libpq/be-gssapi-common.c b/src/backend/libpq/be-gssapi-common.c index 005bf2717680b..7adea3060e17e 100644 --- a/src/backend/libpq/be-gssapi-common.c +++ b/src/backend/libpq/be-gssapi-common.c @@ -3,7 +3,7 @@ * be-gssapi-common.c * Common code for GSSAPI authentication and encryption * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/libpq/be-secure-common.c b/src/backend/libpq/be-secure-common.c index 0cb201acb1e50..e8b837d1fa78d 100644 --- a/src/backend/libpq/be-secure-common.c +++ b/src/backend/libpq/be-secure-common.c @@ -8,7 +8,7 @@ * communications code calls, this file contains support routines that are * used by the library-specific implementations such as be-secure-openssl.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/libpq/be-secure-gssapi.c b/src/backend/libpq/be-secure-gssapi.c index 483636503c188..5d98c58ffa8be 100644 --- a/src/backend/libpq/be-secure-gssapi.c +++ b/src/backend/libpq/be-secure-gssapi.c @@ -3,7 +3,7 @@ * be-secure-gssapi.c * GSSAPI encryption support * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/libpq/be-secure-gssapi.c @@ -18,9 +18,9 @@ #include "libpq/auth.h" #include "libpq/be-gssapi-common.h" #include "libpq/libpq.h" -#include "libpq/pqformat.h" #include "miscadmin.h" #include "pgstat.h" +#include "port/pg_bswap.h" #include "utils/injection_point.h" #include "utils/memutils.h" @@ -46,11 +46,18 @@ * don't want the other side to send arbitrarily huge packets as we * would have to allocate memory for them to then pass them to GSSAPI. * - * Therefore, these two #define's are effectively part of the protocol + * Therefore, this #define is effectively part of the protocol * spec and can't ever be changed. */ -#define PQ_GSS_SEND_BUFFER_SIZE 16384 -#define PQ_GSS_RECV_BUFFER_SIZE 16384 +#define PQ_GSS_MAX_PACKET_SIZE 16384 /* includes uint32 header word */ + +/* + * However, during the authentication exchange we must cope with whatever + * message size the GSSAPI library wants to send (because our protocol + * doesn't support splitting those messages). Depending on configuration + * those messages might be as much as 64kB. + */ +#define PQ_GSS_AUTH_BUFFER_SIZE 65536 /* includes uint32 header word */ /* * Since we manage at most one GSS-encrypted connection per backend, @@ -93,7 +100,7 @@ static uint32 PqGSSMaxPktSize; /* Maximum size we can encrypt and fit the * failure if necessary, and then return an errno indicating connection loss. */ ssize_t -be_gssapi_write(Port *port, void *ptr, size_t len) +be_gssapi_write(Port *port, const void *ptr, size_t len) { OM_uint32 major, minor; @@ -114,9 +121,9 @@ be_gssapi_write(Port *port, void *ptr, size_t len) * again, so if it offers a len less than that, something is wrong. * * Note: it may seem attractive to report partial write completion once - * we've successfully sent any encrypted packets. However, that can cause - * problems for callers; notably, pqPutMsgEnd's heuristic to send only - * full 8K blocks interacts badly with such a hack. We won't save much, + * we've successfully sent any encrypted packets. However, doing that + * expands the state space of this processing and has been responsible for + * bugs in the past (cf. commit d053a879b). We won't save much, * typically, by letting callers discard data early, so don't risk it. */ if (len < PqGSSSendConsumed) @@ -210,12 +217,12 @@ be_gssapi_write(Port *port, void *ptr, size_t len) errno = ECONNRESET; return -1; } - if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)) { ereport(COMMERROR, (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)", (size_t) output.length, - PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)))); + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)))); errno = ECONNRESET; return -1; } @@ -346,12 +353,12 @@ be_gssapi_read(Port *port, void *ptr, size_t len) /* Decode the packet length and check for overlength packet */ input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer); - if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)) + if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)) { ereport(COMMERROR, (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)", (size_t) input.length, - PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)))); + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)))); errno = ECONNRESET; return -1; } @@ -450,7 +457,7 @@ read_or_wait(Port *port, ssize_t len) */ if (ret <= 0) { - WaitLatchOrSocket(MyLatch, + WaitLatchOrSocket(NULL, WL_SOCKET_READABLE | WL_EXIT_ON_PM_DEATH, port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER); @@ -500,7 +507,7 @@ secure_open_gssapi(Port *port) minor; gss_cred_id_t delegated_creds; - INJECTION_POINT("backend-gssapi-startup"); + INJECTION_POINT("backend-gssapi-startup", NULL); /* * Allocate subsidiary Port data for GSSAPI operations. @@ -517,10 +524,13 @@ secure_open_gssapi(Port *port) * that will never use them, and we ensure that the buffers are * sufficiently aligned for the length-word accesses that we do in some * places in this file. + * + * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport + * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE. */ - PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE); - PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); - PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); + PqGSSSendBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); + PqGSSRecvBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); + PqGSSResultBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -568,16 +578,16 @@ secure_open_gssapi(Port *port) /* * During initialization, packets are always fully consumed and - * shouldn't ever be over PQ_GSS_RECV_BUFFER_SIZE in length. + * shouldn't ever be over PQ_GSS_AUTH_BUFFER_SIZE in total length. * * Verify on our side that the client doesn't do something funny. */ - if (input.length > PQ_GSS_RECV_BUFFER_SIZE) + if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)) { ereport(COMMERROR, - (errmsg("oversize GSSAPI packet sent by the client (%zu > %d)", + (errmsg("oversize GSSAPI packet sent by the client (%zu > %zu)", (size_t) input.length, - PQ_GSS_RECV_BUFFER_SIZE))); + PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)))); return -1; } @@ -631,17 +641,17 @@ secure_open_gssapi(Port *port) { uint32 netlen = pg_hton32(output.length); - if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)) { ereport(COMMERROR, (errmsg("server tried to send oversize GSSAPI packet (%zu > %zu)", (size_t) output.length, - PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)))); + PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)))); gss_release_buffer(&minor, &output); return -1; } - memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32)); + memcpy(PqGSSSendBuffer, &netlen, sizeof(uint32)); PqGSSSendLength += sizeof(uint32); memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length); @@ -668,7 +678,7 @@ secure_open_gssapi(Port *port) /* Wait and retry if we couldn't write yet */ if (ret <= 0) { - WaitLatchOrSocket(MyLatch, + WaitLatchOrSocket(NULL, WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH, port->sock, 0, WAIT_EVENT_GSS_OPEN_SERVER); continue; @@ -691,12 +701,29 @@ secure_open_gssapi(Port *port) break; } + /* + * Release the large authentication buffers and allocate the ones we want + * for normal operation. + */ + free(PqGSSSendBuffer); + free(PqGSSRecvBuffer); + free(PqGSSResultBuffer); + PqGSSSendBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + PqGSSRecvBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + PqGSSResultBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0; + PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0; + /* * Determine the max packet size which will fit in our buffer, after * accounting for the length. be_gssapi_write will need this. */ major = gss_wrap_size_limit(&minor, port->gss->ctx, 1, GSS_C_QOP_DEFAULT, - PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32), + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32), &PqGSSMaxPktSize); if (GSS_ERROR(major)) diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index eed7ec7ce56a7..64ff3ce3d6a7a 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -4,7 +4,7 @@ * functions for OpenSSL support in the backend. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -33,8 +33,7 @@ #include "pgstat.h" #include "storage/fd.h" #include "storage/latch.h" -#include "tcop/tcopprot.h" -#include "utils/builtins.h" +#include "utils/guc.h" #include "utils/memutils.h" /* @@ -44,6 +43,7 @@ * include , but some other Windows headers do.) */ #include "common/openssl.h" +#include #include #include #ifndef OPENSSL_NO_ECDH @@ -56,10 +56,10 @@ static void default_openssl_tls_init(SSL_CTX *context, bool isServerStart); openssl_tls_init_hook_typ openssl_tls_init_hook = default_openssl_tls_init; -static int my_sock_read(BIO *h, char *buf, int size); -static int my_sock_write(BIO *h, const char *buf, int size); -static BIO_METHOD *my_BIO_s_socket(void); -static int my_SSL_set_fd(Port *port, int fd); +static int port_bio_read(BIO *h, char *buf, int size); +static int port_bio_write(BIO *h, const char *buf, int size); +static BIO_METHOD *port_bio_method(void); +static int ssl_set_port_bio(Port *port); static DH *load_dh_file(char *filename, bool isServerStart); static DH *load_dh_buffer(const char *buffer, size_t len); @@ -75,12 +75,12 @@ static int alpn_cb(SSL *ssl, void *userdata); static bool initialize_dh(SSL_CTX *context, bool isServerStart); static bool initialize_ecdh(SSL_CTX *context, bool isServerStart); +static const char *SSLerrmessageExt(unsigned long ecode, const char *replacement); static const char *SSLerrmessage(unsigned long ecode); static char *X509_NAME_to_cstring(X509_NAME *name); static SSL_CTX *SSL_context = NULL; -static bool SSL_initialized = false; static bool dummy_ssl_passwd_cb_called = false; static bool ssl_is_server_start; @@ -101,19 +101,6 @@ be_tls_init(bool isServerStart) int ssl_ver_min = -1; int ssl_ver_max = -1; - /* This stuff need be done only once. */ - if (!SSL_initialized) - { -#ifdef HAVE_OPENSSL_INIT_SSL - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); -#else - OPENSSL_config(NULL); - SSL_library_init(); - SSL_load_error_strings(); -#endif - SSL_initialized = true; - } - /* * Create a new SSL context into which we'll load all the configuration * settings. If we fail partway through, we can avoid memory leakage by @@ -270,9 +257,8 @@ be_tls_init(bool isServerStart) */ #ifdef HAVE_SSL_CTX_SET_NUM_TICKETS SSL_CTX_set_num_tickets(context, 0); -#else - SSL_CTX_set_options(context, SSL_OP_NO_TICKET); #endif + SSL_CTX_set_options(context, SSL_OP_NO_TICKET); /* disallow SSL session caching, too */ SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF); @@ -301,15 +287,31 @@ be_tls_init(bool isServerStart) if (!initialize_ecdh(context, isServerStart)) goto error; - /* set up the allowed cipher list */ - if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1) + /* set up the allowed cipher list for TLSv1.2 and below */ + if (SSL_CTX_set_cipher_list(context, SSLCipherList) != 1) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not set the cipher list (no valid ciphers available)"))); + errmsg("could not set the TLSv1.2 cipher list (no valid ciphers available)"))); goto error; } + /* + * Set up the allowed cipher suites for TLSv1.3. If the GUC is an empty + * string we leave the allowed suites to be the OpenSSL default value. + */ + if (SSLCipherSuites[0]) + { + /* set up the allowed cipher suites */ + if (SSL_CTX_set_ciphersuites(context, SSLCipherSuites) != 1) + { + ereport(isServerStart ? FATAL : LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not set the TLSv1.3 cipher suites (no valid ciphers available)"))); + goto error; + } + } + /* Let server choose order */ if (SSLPreferServerCiphers) SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE); @@ -467,7 +469,7 @@ be_tls_open_server(Port *port) SSLerrmessage(ERR_get_error())))); return -1; } - if (!my_SSL_set_fd(port, port->sock)) + if (!ssl_set_port_bio(port)) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), @@ -520,7 +522,7 @@ be_tls_open_server(Port *port) else waitfor = WL_SOCKET_WRITEABLE | WL_EXIT_ON_PM_DEATH; - (void) WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0, + (void) WaitLatchOrSocket(NULL, waitfor, port->sock, 0, WAIT_EVENT_SSL_OPEN_SERVER); goto aloop; case SSL_ERROR_SYSCALL: @@ -819,7 +821,7 @@ be_tls_read(Port *port, void *ptr, size_t len, int *waitfor) } ssize_t -be_tls_write(Port *port, void *ptr, size_t len, int *waitfor) +be_tls_write(Port *port, const void *ptr, size_t len, int *waitfor) { ssize_t n; int err; @@ -904,17 +906,19 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor) * see sock_read() and sock_write() in OpenSSL's crypto/bio/bss_sock.c. */ -static BIO_METHOD *my_bio_methods = NULL; +static BIO_METHOD *port_bio_method_ptr = NULL; static int -my_sock_read(BIO *h, char *buf, int size) +port_bio_read(BIO *h, char *buf, int size) { int res = 0; + Port *port = (Port *) BIO_get_data(h); if (buf != NULL) { - res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size); + res = secure_raw_read(port, buf, size); BIO_clear_retry_flags(h); + port->last_read_was_eof = res == 0; if (res <= 0) { /* If we were interrupted, tell caller to retry */ @@ -929,11 +933,11 @@ my_sock_read(BIO *h, char *buf, int size) } static int -my_sock_write(BIO *h, const char *buf, int size) +port_bio_write(BIO *h, const char *buf, int size) { int res = 0; - res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size); + res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size); BIO_clear_retry_flags(h); if (res <= 0) { @@ -947,75 +951,81 @@ my_sock_write(BIO *h, const char *buf, int size) return res; } +static long +port_bio_ctrl(BIO *h, int cmd, long num, void *ptr) +{ + long res; + Port *port = (Port *) BIO_get_data(h); + + switch (cmd) + { + case BIO_CTRL_EOF: + + /* + * This should not be needed. port_bio_read already has a way to + * signal EOF to OpenSSL. However, OpenSSL made an undocumented, + * backwards-incompatible change and now expects EOF via BIO_ctrl. + * See https://github.com/openssl/openssl/issues/8208 + */ + res = port->last_read_was_eof; + break; + case BIO_CTRL_FLUSH: + /* libssl expects all BIOs to support BIO_flush. */ + res = 1; + break; + default: + res = 0; + break; + } + + return res; +} + static BIO_METHOD * -my_BIO_s_socket(void) +port_bio_method(void) { - if (!my_bio_methods) + if (!port_bio_method_ptr) { - BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); -#ifdef HAVE_BIO_METH_NEW int my_bio_index; my_bio_index = BIO_get_new_index(); if (my_bio_index == -1) return NULL; - my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK); - my_bio_methods = BIO_meth_new(my_bio_index, "PostgreSQL backend socket"); - if (!my_bio_methods) + my_bio_index |= BIO_TYPE_SOURCE_SINK; + port_bio_method_ptr = BIO_meth_new(my_bio_index, "PostgreSQL backend socket"); + if (!port_bio_method_ptr) return NULL; - if (!BIO_meth_set_write(my_bio_methods, my_sock_write) || - !BIO_meth_set_read(my_bio_methods, my_sock_read) || - !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) || - !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) || - !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) || - !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) || - !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) || - !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom))) + if (!BIO_meth_set_write(port_bio_method_ptr, port_bio_write) || + !BIO_meth_set_read(port_bio_method_ptr, port_bio_read) || + !BIO_meth_set_ctrl(port_bio_method_ptr, port_bio_ctrl)) { - BIO_meth_free(my_bio_methods); - my_bio_methods = NULL; + BIO_meth_free(port_bio_method_ptr); + port_bio_method_ptr = NULL; return NULL; } -#else - my_bio_methods = malloc(sizeof(BIO_METHOD)); - if (!my_bio_methods) - return NULL; - memcpy(my_bio_methods, biom, sizeof(BIO_METHOD)); - my_bio_methods->bread = my_sock_read; - my_bio_methods->bwrite = my_sock_write; -#endif } - return my_bio_methods; + return port_bio_method_ptr; } -/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */ static int -my_SSL_set_fd(Port *port, int fd) +ssl_set_port_bio(Port *port) { - int ret = 0; BIO *bio; BIO_METHOD *bio_method; - bio_method = my_BIO_s_socket(); + bio_method = port_bio_method(); if (bio_method == NULL) - { - SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); - goto err; - } - bio = BIO_new(bio_method); + return 0; + bio = BIO_new(bio_method); if (bio == NULL) - { - SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); - goto err; - } - BIO_set_app_data(bio, port); + return 0; + + BIO_set_data(bio, port); + BIO_set_init(bio, 1); - BIO_set_fd(bio, fd, BIO_NOCLOSE); SSL_set_bio(port->ssl, bio, bio); - ret = 1; -err: - return ret; + return 1; } /* @@ -1098,7 +1108,7 @@ load_dh_buffer(const char *buffer, size_t len) BIO *bio; DH *dh = NULL; - bio = BIO_new_mem_buf(unconstify(char *, buffer), len); + bio = BIO_new_mem_buf(buffer, len); if (bio == NULL) return NULL; dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); @@ -1415,35 +1425,50 @@ static bool initialize_ecdh(SSL_CTX *context, bool isServerStart) { #ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh; - int nid; - - nid = OBJ_sn2nid(SSLECDHCurve); - if (!nid) - { - ereport(isServerStart ? FATAL : LOG, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve))); - return false; - } - - ecdh = EC_KEY_new_by_curve_name(nid); - if (!ecdh) + if (SSL_CTX_set1_groups_list(context, SSLECDHCurve) != 1) { + /* + * OpenSSL 3.3.0 introduced proper error messages for group parsing + * errors, earlier versions returns "no SSL error reported" which is + * far from helpful. For older versions, we replace with a better + * error message. Injecting the error into the OpenSSL error queue + * need APIs from OpenSSL 3.0. + */ ereport(isServerStart ? FATAL : LOG, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("ECDH: could not create key"))); + errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("failed to set group names specified in ssl_groups: %s", + SSLerrmessageExt(ERR_get_error(), + _("No valid groups found"))), + errhint("Ensure that each group name is spelled correctly and supported by the installed version of OpenSSL")); return false; } - - SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); - SSL_CTX_set_tmp_ecdh(context, ecdh); - EC_KEY_free(ecdh); #endif return true; } +/* + * Obtain reason string for passed SSL errcode with replacement + * + * The error message supplied in replacement will be used in case the error + * code from OpenSSL is 0, else the error message from SSLerrmessage() will + * be returned. + * + * Not all versions of OpenSSL place an error on the queue even for failing + * operations, which will yield "no SSL error reported" by SSLerrmessage. This + * function can be used to ensure that a proper error message is displayed for + * versions reporting no error, while using the OpenSSL error via SSLerrmessage + * for versions where there is one. + */ +static const char * +SSLerrmessageExt(unsigned long ecode, const char *replacement) +{ + if (ecode == 0) + return replacement; + else + return SSLerrmessage(ecode); +} + /* * Obtain reason string for passed SSL errcode * @@ -1466,10 +1491,11 @@ SSLerrmessage(unsigned long ecode) return errreason; /* - * In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to - * map system errno values. We can cover that shortcoming with this bit - * of code. Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro, - * but that's okay because they don't have the shortcoming either. + * In OpenSSL 3.0.0 and later, ERR_reason_error_string does not map system + * errno values anymore. (See OpenSSL source code for the explanation.) + * We can cover that shortcoming with this bit of code. Older OpenSSL + * versions don't have the ERR_SYSTEM_ERROR macro, but that's okay because + * they don't have the shortcoming either. */ #ifdef ERR_SYSTEM_ERROR if (ERR_SYSTEM_ERROR(ecode)) diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index ef20ea755b70b..d723e74e8137b 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -6,7 +6,7 @@ * message integrity and endpoint authentication. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -49,6 +49,7 @@ bool ssl_loaded_verify_locations = false; /* GUC variable controlling SSL cipher list */ char *SSLCipherSuites = NULL; +char *SSLCipherList = NULL; /* GUC variable for default ECHD curve. */ char *SSLECDHCurve; @@ -130,7 +131,7 @@ secure_open_server(Port *port) } Assert(pq_buffer_remaining_data() == 0); - INJECTION_POINT("backend-ssl-startup"); + INJECTION_POINT("backend-ssl-startup", NULL); r = be_tls_open_server(port); @@ -301,7 +302,7 @@ secure_raw_read(Port *port, void *ptr, size_t len) * Write data to a secure connection. */ ssize_t -secure_write(Port *port, void *ptr, size_t len) +secure_write(Port *port, const void *ptr, size_t len) { ssize_t n; int waitfor; diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index 629e51e00be9e..f6b641e726ec3 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -4,7 +4,7 @@ * Functions for dealing with encrypted passwords stored in * pg_authid.rolpassword. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/crypt.c @@ -24,6 +24,8 @@ #include "utils/syscache.h" #include "utils/timestamp.h" +/* Enables deprecation warnings for MD5 passwords. */ +bool md5_password_warnings = true; /* * Fetch stored password for a user, for authentication. @@ -116,7 +118,7 @@ encrypt_password(PasswordType target_type, const char *role, const char *password) { PasswordType guessed_type = get_password_type(password); - char *encrypted_password; + char *encrypted_password = NULL; const char *errstr = NULL; if (guessed_type != PASSWORD_TYPE_PLAINTEXT) @@ -125,32 +127,64 @@ encrypt_password(PasswordType target_type, const char *role, * Cannot convert an already-encrypted password from one format to * another, so return it as it is. */ - return pstrdup(password); + encrypted_password = pstrdup(password); } - - switch (target_type) + else { - case PASSWORD_TYPE_MD5: - encrypted_password = palloc(MD5_PASSWD_LEN + 1); + switch (target_type) + { + case PASSWORD_TYPE_MD5: + encrypted_password = palloc(MD5_PASSWD_LEN + 1); - if (!pg_md5_encrypt(password, role, strlen(role), - encrypted_password, &errstr)) - elog(ERROR, "password encryption failed: %s", errstr); - return encrypted_password; + if (!pg_md5_encrypt(password, (uint8 *) role, strlen(role), + encrypted_password, &errstr)) + elog(ERROR, "password encryption failed: %s", errstr); + break; - case PASSWORD_TYPE_SCRAM_SHA_256: - return pg_be_scram_build_secret(password); + case PASSWORD_TYPE_SCRAM_SHA_256: + encrypted_password = pg_be_scram_build_secret(password); + break; - case PASSWORD_TYPE_PLAINTEXT: - elog(ERROR, "cannot encrypt password with 'plaintext'"); + case PASSWORD_TYPE_PLAINTEXT: + elog(ERROR, "cannot encrypt password with 'plaintext'"); + break; + } } + Assert(encrypted_password); + /* - * This shouldn't happen, because the above switch statements should - * handle every combination of source and target password types. + * Valid password hashes may be very long, but we don't want to store + * anything that might need out-of-line storage, since de-TOASTing won't + * work during authentication because we haven't selected a database yet + * and cannot read pg_class. 512 bytes should be more than enough for all + * practical use, so fail for anything longer. */ - elog(ERROR, "cannot encrypt password to requested type"); - return NULL; /* keep compiler quiet */ + if (encrypted_password && /* keep compiler quiet */ + strlen(encrypted_password) > MAX_ENCRYPTED_PASSWORD_LEN) + { + /* + * We don't expect any of our own hashing routines to produce hashes + * that are too long. + */ + Assert(guessed_type != PASSWORD_TYPE_PLAINTEXT); + + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("encrypted password is too long"), + errdetail("Encrypted passwords must be no longer than %d bytes.", + MAX_ENCRYPTED_PASSWORD_LEN))); + } + + if (md5_password_warnings && + get_password_type(encrypted_password) == PASSWORD_TYPE_MD5) + ereport(WARNING, + (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE), + errmsg("setting an MD5-encrypted password"), + errdetail("MD5 password support is deprecated and will be removed in a future release of PostgreSQL."), + errhint("Refer to the PostgreSQL documentation for details about migrating to another password type."))); + + return encrypted_password; } /* @@ -167,7 +201,7 @@ encrypt_password(PasswordType target_type, const char *role, int md5_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, - const char *md5_salt, int md5_salt_len, + const uint8 *md5_salt, int md5_salt_len, const char **logdetail) { int retval; @@ -250,7 +284,7 @@ plain_crypt_verify(const char *role, const char *shadow_pass, case PASSWORD_TYPE_MD5: if (!pg_md5_encrypt(client_pass, - role, + (uint8 *) role, strlen(role), crypt_client_pass, &errstr)) diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 75d588e36a10e..332fad278351c 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -5,7 +5,7 @@ * wherein you authenticate a user by seeing what IP address the system * says he comes from and choosing authentication method based on it). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,6 +32,7 @@ #include "libpq/hba.h" #include "libpq/ifaddr.h" #include "libpq/libpq-be.h" +#include "libpq/oauth.h" #include "postmaster/postmaster.h" #include "regex/regex.h" #include "replication/walsender.h" @@ -114,7 +115,8 @@ static const char *const UserAuthName[] = "ldap", "cert", "radius", - "peer" + "peer", + "oauth", }; /* @@ -624,8 +626,11 @@ open_auth_file(const char *filename, int elevel, int depth, errmsg("could not open file \"%s\": %m", filename))); if (err_msg) - *err_msg = psprintf("could not open file \"%s\": %s", - filename, strerror(save_errno)); + { + errno = save_errno; + *err_msg = psprintf("could not open file \"%s\": %m", + filename); + } /* the caller may care about some specific errno */ errno = save_errno; return NULL; @@ -699,7 +704,7 @@ tokenize_auth_file(const char *filename, FILE *file, List **tok_lines, callback_arg.linenum = line_number; tokenerrcontext.callback = tokenize_error_callback; - tokenerrcontext.arg = (void *) &callback_arg; + tokenerrcontext.arg = &callback_arg; tokenerrcontext.previous = error_context_stack; error_context_stack = &tokenerrcontext; @@ -762,8 +767,9 @@ tokenize_auth_file(const char *filename, FILE *file, List **tok_lines, ereport(elevel, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", filename))); - err_msg = psprintf("could not read file \"%s\": %s", - filename, strerror(save_errno)); + errno = save_errno; + err_msg = psprintf("could not read file \"%s\": %m", + filename); break; } @@ -1743,6 +1749,8 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel) #endif else if (strcmp(token->string, "radius") == 0) parsedline->auth_method = uaRADIUS; + else if (strcmp(token->string, "oauth") == 0) + parsedline->auth_method = uaOAuth; else { ereport(elevel, @@ -2035,6 +2043,36 @@ parse_hba_line(TokenizedAuthLine *tok_line, int elevel) parsedline->clientcert = clientCertFull; } + /* + * Enforce proper configuration of OAuth authentication. + */ + if (parsedline->auth_method == uaOAuth) + { + MANDATORY_AUTH_ARG(parsedline->oauth_scope, "scope", "oauth"); + MANDATORY_AUTH_ARG(parsedline->oauth_issuer, "issuer", "oauth"); + + /* Ensure a validator library is set and permitted by the config. */ + if (!check_oauth_validator(parsedline, elevel, err_msg)) + return NULL; + + /* + * Supplying a usermap combined with the option to skip usermapping is + * nonsensical and indicates a configuration error. + */ + if (parsedline->oauth_skip_usermap && parsedline->usermap != NULL) + { + ereport(elevel, + errcode(ERRCODE_CONFIG_FILE_ERROR), + /* translator: strings are replaced with hba options */ + errmsg("%s cannot be used in combination with %s", + "map", "delegate_ident_mapping"), + errcontext("line %d of configuration file \"%s\"", + line_num, file_name)); + *err_msg = "map cannot be used in combination with delegate_ident_mapping"; + return NULL; + } + } + return parsedline; } @@ -2062,8 +2100,9 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, hbaline->auth_method != uaPeer && hbaline->auth_method != uaGSS && hbaline->auth_method != uaSSPI && - hbaline->auth_method != uaCert) - INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, and cert")); + hbaline->auth_method != uaCert && + hbaline->auth_method != uaOAuth) + INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, cert, and oauth")); hbaline->usermap = pstrdup(val); } else if (strcmp(name, "clientcert") == 0) @@ -2446,6 +2485,29 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, hbaline->radiusidentifiers = parsed_identifiers; hbaline->radiusidentifiers_s = pstrdup(val); } + else if (strcmp(name, "issuer") == 0) + { + REQUIRE_AUTH_OPTION(uaOAuth, "issuer", "oauth"); + hbaline->oauth_issuer = pstrdup(val); + } + else if (strcmp(name, "scope") == 0) + { + REQUIRE_AUTH_OPTION(uaOAuth, "scope", "oauth"); + hbaline->oauth_scope = pstrdup(val); + } + else if (strcmp(name, "validator") == 0) + { + REQUIRE_AUTH_OPTION(uaOAuth, "validator", "oauth"); + hbaline->oauth_validator = pstrdup(val); + } + else if (strcmp(name, "delegate_ident_mapping") == 0) + { + REQUIRE_AUTH_OPTION(uaOAuth, "delegate_ident_mapping", "oauth"); + if (strcmp(val, "1") == 0) + hbaline->oauth_skip_usermap = true; + else + hbaline->oauth_skip_usermap = false; + } else { ereport(elevel, diff --git a/src/backend/libpq/ifaddr.c b/src/backend/libpq/ifaddr.c index 4c25af7ac3be1..1303a4543e7a3 100644 --- a/src/backend/libpq/ifaddr.c +++ b/src/backend/libpq/ifaddr.c @@ -3,7 +3,7 @@ * ifaddr.c * IP netmask calculations, and enumerating network interfaces. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/libpq/meson.build b/src/backend/libpq/meson.build index 7c65314512caa..31aa2faae1ecc 100644 --- a/src/backend/libpq/meson.build +++ b/src/backend/libpq/meson.build @@ -1,6 +1,7 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( + 'auth-oauth.c', 'auth-sasl.c', 'auth-scram.c', 'auth.c', diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index bad13497a3465..b64c8dea97c31 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -53,8 +53,8 @@ # directly connected to. # # METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", -# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". -# Note that "password" sends passwords in clear text; "md5" or +# "gss", "sspi", "ident", "peer", "pam", "oauth", "ldap", "radius" or +# "cert". Note that "password" sends passwords in clear text; "md5" or # "scram-sha-256" are preferred since they send encrypted passwords. # # OPTIONS are a set of options for the authentication in the format diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 896e1476b50d7..e5171467de18d 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -17,7 +17,7 @@ * the backend's "backend/libpq" is quite separate from "interfaces/libpq". * All that remains is similarities of names to trap the unwary... * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/pqcomm.c @@ -144,7 +144,7 @@ static int socket_flush_if_writable(void); static bool socket_is_send_pending(void); static int socket_putmessage(char msgtype, const char *s, size_t len); static void socket_putmessage_noblock(char msgtype, const char *s, size_t len); -static inline int internal_putbytes(const char *s, size_t len); +static inline int internal_putbytes(const void *b, size_t len); static inline int internal_flush(void); static pg_noinline int internal_flush_buffer(const char *buf, size_t *start, size_t *end); @@ -571,7 +571,7 @@ ListenServerPort(int family, const char *hostName, unsigned short portNumber, { ereport(LOG, (errcode_for_socket_access(), - /* translator: third %s is IPv4, IPv6, or Unix */ + /* translator: third %s is IPv4 or IPv6 */ errmsg("%s(%s) failed for %s address \"%s\": %m", "setsockopt", "SO_REUSEADDR", familyDesc, addrDesc))); @@ -589,7 +589,7 @@ ListenServerPort(int family, const char *hostName, unsigned short portNumber, { ereport(LOG, (errcode_for_socket_access(), - /* translator: third %s is IPv4, IPv6, or Unix */ + /* translator: third %s is IPv6 */ errmsg("%s(%s) failed for %s address \"%s\": %m", "setsockopt", "IPV6_V6ONLY", familyDesc, addrDesc))); @@ -1060,8 +1060,9 @@ pq_getbyte_if_available(unsigned char *c) * -------------------------------- */ int -pq_getbytes(char *s, size_t len) +pq_getbytes(void *b, size_t len) { + char *s = b; size_t amount; Assert(PqCommReadingMsg); @@ -1209,7 +1210,7 @@ pq_getmessage(StringInfo s, int maxlen) resetStringInfo(s); /* Read message length word */ - if (pq_getbytes((char *) &len, 4) == EOF) + if (pq_getbytes(&len, 4) == EOF) { ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), @@ -1274,8 +1275,10 @@ pq_getmessage(StringInfo s, int maxlen) static inline int -internal_putbytes(const char *s, size_t len) +internal_putbytes(const void *b, size_t len) { + const char *s = b; + while (len > 0) { /* If buffer is full, then flush it out */ @@ -1368,7 +1371,7 @@ internal_flush_buffer(const char *buf, size_t *start, size_t *end) { int r; - r = secure_write(MyProcPort, (char *) bufptr, bufend - bufptr); + r = secure_write(MyProcPort, bufptr, bufend - bufptr); if (r <= 0) { @@ -1499,7 +1502,7 @@ socket_putmessage(char msgtype, const char *s, size_t len) goto fail; n32 = pg_hton32((uint32) (len + 4)); - if (internal_putbytes((char *) &n32, 4)) + if (internal_putbytes(&n32, 4)) goto fail; if (internal_putbytes(s, len)) diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index aa9433bb3b240..1cc126772f7c0 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -21,7 +21,7 @@ * are different. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/pqformat.c @@ -422,15 +422,15 @@ pq_getmsgint(StringInfo msg, int b) switch (b) { case 1: - pq_copymsgbytes(msg, (char *) &n8, 1); + pq_copymsgbytes(msg, &n8, 1); result = n8; break; case 2: - pq_copymsgbytes(msg, (char *) &n16, 2); + pq_copymsgbytes(msg, &n16, 2); result = pg_ntoh16(n16); break; case 4: - pq_copymsgbytes(msg, (char *) &n32, 4); + pq_copymsgbytes(msg, &n32, 4); result = pg_ntoh32(n32); break; default: @@ -454,7 +454,7 @@ pq_getmsgint64(StringInfo msg) { uint64 n64; - pq_copymsgbytes(msg, (char *) &n64, sizeof(n64)); + pq_copymsgbytes(msg, &n64, sizeof(n64)); return pg_ntoh64(n64); } @@ -525,7 +525,7 @@ pq_getmsgbytes(StringInfo msg, int datalen) * -------------------------------- */ void -pq_copymsgbytes(StringInfo msg, char *buf, int datalen) +pq_copymsgbytes(StringInfo msg, void *buf, int datalen) { if (datalen < 0 || datalen > (msg->len - msg->cursor)) ereport(ERROR, diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c index fd735e2fea9d6..f1a08bc32ca17 100644 --- a/src/backend/libpq/pqmq.c +++ b/src/backend/libpq/pqmq.c @@ -3,7 +3,7 @@ * pqmq.c * Use the frontend/backend protocol for communication over a shm_mq * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/libpq/pqmq.c diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c index 22a16c50b2150..d866307a4dc2e 100644 --- a/src/backend/libpq/pqsignal.c +++ b/src/backend/libpq/pqsignal.c @@ -3,7 +3,7 @@ * pqsignal.c * Backend signal(2) support (see also src/port/pqsignal.c) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -42,7 +42,7 @@ pqinitmask(void) { sigemptyset(&UnBlockSig); - /* Note: InitializeLatchSupport() modifies UnBlockSig. */ + /* Note: InitializeWaitEventSupport() modifies UnBlockSig. */ /* First set all signals, then clear some. */ sigfillset(&BlockSig); diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 4672aab83786c..7d63cf94a6b44 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -9,7 +9,7 @@ * proper FooMain() routine for the incarnation. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,7 +32,7 @@ #include "bootstrap/bootstrap.h" #include "common/username.h" -#include "port/atomics.h" +#include "miscadmin.h" #include "postmaster/postmaster.h" #include "tcop/tcopprot.h" #include "utils/help_config.h" @@ -44,6 +44,19 @@ const char *progname; static bool reached_main = false; +/* names of special must-be-first options for dispatching to subprograms */ +static const char *const DispatchOptionNames[] = +{ + [DISPATCH_CHECK] = "check", + [DISPATCH_BOOT] = "boot", + [DISPATCH_FORKCHILD] = "forkchild", + [DISPATCH_DESCRIBE_CONFIG] = "describe-config", + [DISPATCH_SINGLE] = "single", + /* DISPATCH_POSTMASTER has no name */ +}; + +StaticAssertDecl(lengthof(DispatchOptionNames) == DISPATCH_POSTMASTER, + "array length mismatch"); static void startup_hacks(const char *progname); static void init_locale(const char *categoryname, int category, const char *locale); @@ -58,6 +71,7 @@ int main(int argc, char *argv[]) { bool do_check_root = true; + DispatchOption dispatch_option = DISPATCH_POSTMASTER; reached_main = true; @@ -96,8 +110,15 @@ main(int argc, char *argv[]) * localization of messages may not work right away, and messages won't go * anywhere but stderr until GUC settings get loaded. */ + MyProcPid = getpid(); MemoryContextInit(); + /* + * Set reference point for stack-depth checking. (There's no point in + * enabling this before error reporting works.) + */ + (void) set_stack_base(); + /* * Set up locale information */ @@ -121,10 +142,7 @@ main(int argc, char *argv[]) init_locale("LC_MESSAGES", LC_MESSAGES, ""); #endif - /* - * We keep these set to "C" always, except transiently in pg_locale.c; see - * that file for explanations. - */ + /* We keep these set to "C" always. See pg_locale.c for explanation. */ init_locale("LC_MONETARY", LC_MONETARY, "C"); init_locale("LC_NUMERIC", LC_NUMERIC, "C"); init_locale("LC_TIME", LC_TIME, "C"); @@ -180,26 +198,72 @@ main(int argc, char *argv[]) * Dispatch to one of various subprograms depending on first argument. */ - if (argc > 1 && strcmp(argv[1], "--check") == 0) - BootstrapModeMain(argc, argv, true); - else if (argc > 1 && strcmp(argv[1], "--boot") == 0) - BootstrapModeMain(argc, argv, false); + if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') + dispatch_option = parse_dispatch_option(&argv[1][2]); + + switch (dispatch_option) + { + case DISPATCH_CHECK: + BootstrapModeMain(argc, argv, true); + break; + case DISPATCH_BOOT: + BootstrapModeMain(argc, argv, false); + break; + case DISPATCH_FORKCHILD: #ifdef EXEC_BACKEND - else if (argc > 1 && strncmp(argv[1], "--forkchild", 11) == 0) - SubPostmasterMain(argc, argv); + SubPostmasterMain(argc, argv); +#else + Assert(false); /* should never happen */ #endif - else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) - GucInfoMain(); - else if (argc > 1 && strcmp(argv[1], "--single") == 0) - PostgresSingleUserMain(argc, argv, - strdup(get_user_name_or_exit(progname))); - else - PostmasterMain(argc, argv); + break; + case DISPATCH_DESCRIBE_CONFIG: + GucInfoMain(); + break; + case DISPATCH_SINGLE: + PostgresSingleUserMain(argc, argv, + strdup(get_user_name_or_exit(progname))); + break; + case DISPATCH_POSTMASTER: + PostmasterMain(argc, argv); + break; + } + /* the functions above should not return */ abort(); } +/* + * Returns the matching DispatchOption value for the given option name. If no + * match is found, DISPATCH_POSTMASTER is returned. + */ +DispatchOption +parse_dispatch_option(const char *name) +{ + for (int i = 0; i < lengthof(DispatchOptionNames); i++) + { + /* + * Unlike the other dispatch options, "forkchild" takes an argument, + * so we just look for the prefix for that one. For non-EXEC_BACKEND + * builds, we never want to return DISPATCH_FORKCHILD, so skip over it + * in that case. + */ + if (i == DISPATCH_FORKCHILD) + { +#ifdef EXEC_BACKEND + if (strncmp(DispatchOptionNames[DISPATCH_FORKCHILD], name, + strlen(DispatchOptionNames[DISPATCH_FORKCHILD])) == 0) + return DISPATCH_FORKCHILD; +#endif + continue; + } + + if (strcmp(DispatchOptionNames[i], name) == 0) + return (DispatchOption) i; + } + /* no match means this is a postmaster */ + return DISPATCH_POSTMASTER; +} /* * Place platform-specific startup hacks here. This is the right diff --git a/src/backend/main/meson.build b/src/backend/main/meson.build index fa8bf8af8badd..bb0c8ff8198ed 100644 --- a/src/backend/main/meson.build +++ b/src/backend/main/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group main_file = files('main.c') backend_sources += main_file diff --git a/src/backend/meson.build b/src/backend/meson.build index 78c57268142c2..2b0db21480470 100644 --- a/src/backend/meson.build +++ b/src/backend/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_build_deps = [backend_code] backend_sources = [] diff --git a/src/backend/nls.mk b/src/backend/nls.mk index 6c2716149d99b..b7d5dd46e4513 100644 --- a/src/backend/nls.mk +++ b/src/backend/nls.mk @@ -7,11 +7,11 @@ GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS) \ GUC_check_errhint \ write_stderr \ yyerror \ - jsonpath_yyerror:3 \ + jsonpath_yyerror:4 \ parser_yyerror \ - replication_yyerror \ + replication_yyerror:3 \ scanner_yyerror \ - syncrep_yyerror \ + syncrep_yyerror:4 \ report_invalid_record:2 \ ereport_startup_progress \ json_token_error:2 \ diff --git a/src/backend/nodes/Makefile b/src/backend/nodes/Makefile index 66bbad8e6e02d..77ddb9ca53f1e 100644 --- a/src/backend/nodes/Makefile +++ b/src/backend/nodes/Makefile @@ -46,6 +46,7 @@ node_headers = \ nodes/plannodes.h \ nodes/execnodes.h \ access/amapi.h \ + access/cmptype.h \ access/sdir.h \ access/tableam.h \ access/tsmapi.h \ diff --git a/src/backend/nodes/README b/src/backend/nodes/README index 523644702053a..f8bbd60538607 100644 --- a/src/backend/nodes/README +++ b/src/backend/nodes/README @@ -98,10 +98,11 @@ Suppose you want to define a node Foo: node types to find all the places to touch. (Except for frequently-created nodes, don't bother writing a creator function in makefuncs.c.) -4. Consider testing your new code with COPY_PARSE_PLAN_TREES, - WRITE_READ_PARSE_PLAN_TREES, and RAW_EXPRESSION_COVERAGE_TEST to ensure - support has been added everywhere that it's necessary; see - pg_config_manual.h about these. +4. Consider testing your new code with debug_copy_parse_plan_trees, + debug_write_read_parse_plan_trees, and + debug_raw_expression_coverage_test to ensure support has been added + everywhere that it's necessary (e.g., run the tests with + PG_TEST_INITDB_EXTRA_OPTS='-c debug_...=on'). Adding a new node type moves the numbers associated with existing tags, so you'll need to recompile the whole tree after doing this. diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index cd05c642b0441..bf512cf806ff7 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -29,7 +29,7 @@ * any users of the old set will be accessing pfree'd memory. This option is * only intended to be used for debugging. * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/nodes/bitmapset.c diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 74b7def804056..475693b08bc5a 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -4,7 +4,7 @@ * Copy functions for Postgres tree nodes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -40,7 +40,7 @@ /* Copy a field that is a pointer to a C string, or perhaps NULL */ #define COPY_STRING_FIELD(fldname) \ - (newnode->fldname = from->fldname ? pstrdup(from->fldname) : (char *) NULL) + (newnode->fldname = from->fldname ? pstrdup(from->fldname) : NULL) /* Copy a field that is an inline array */ #define COPY_ARRAY_FIELD(fldname) \ diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 7caae4d48b050..f2598a1b69a32 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -8,7 +8,7 @@ * "x" to be considered equal() to another reference to "x" in the query. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c index b4353d6d840b7..3ede1ee0f5d64 100644 --- a/src/backend/nodes/extensible.c +++ b/src/backend/nodes/extensible.c @@ -10,7 +10,7 @@ * and GetExtensibleNodeMethods to get information about a previously * registered type of extensible node. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl index 81df3bdf95f01..9ecddb1423143 100644 --- a/src/backend/nodes/gen_node_support.pl +++ b/src/backend/nodes/gen_node_support.pl @@ -8,7 +8,7 @@ # - readfuncs # - outfuncs # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/nodes/gen_node_support.pl @@ -58,6 +58,7 @@ sub elem nodes/plannodes.h nodes/execnodes.h access/amapi.h + access/cmptype.h access/sdir.h access/tableam.h access/tsmapi.h @@ -194,6 +195,7 @@ sub elem foreach my $infile (@ARGV) { my $in_struct; + my $in_struct_lineno; my $subline; my $is_node_struct; my $supertype; @@ -470,11 +472,13 @@ sub elem && $attr !~ /^read_as\(\w+\)$/ && !elem $attr, qw(copy_as_scalar + custom_query_jumble equal_as_scalar equal_ignore equal_ignore_if_zero query_jumble_ignore query_jumble_location + query_jumble_squash read_write_ignore write_only_relids write_only_nondefault_pathtarget @@ -540,6 +544,7 @@ sub elem if ($line =~ /^(?:typedef )?struct (\w+)$/ && $1 ne 'Node') { $in_struct = $1; + $in_struct_lineno = $lineno; $subline = 0; } # one node type typedef'ed directly from another @@ -567,7 +572,8 @@ sub elem if ($in_struct) { - die "runaway \"$in_struct\" in file \"$infile\"\n"; + die + "$infile:$in_struct_lineno: could not find closing brace for struct \"$in_struct\"\n"; } close $ifh; @@ -585,7 +591,7 @@ sub elem * %s * Generated node infrastructure code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -1033,6 +1039,11 @@ sub elem print $off "\tWRITE_UINT_FIELD($f);\n"; print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read; } + elsif ($t eq 'int64') + { + print $off "\tWRITE_INT64_FIELD($f);\n"; + print $rff "\tREAD_INT64_FIELD($f);\n" unless $no_read; + } elsif ($t eq 'uint64' || $t eq 'AclMode') { @@ -1281,11 +1292,17 @@ sub elem my $t = $node_type_info{$n}->{field_types}{$f}; my @a = @{ $node_type_info{$n}->{field_attrs}{$f} }; my $query_jumble_ignore = $struct_no_query_jumble; + my $query_jumble_custom = 0; my $query_jumble_location = 0; + my $query_jumble_squash = 0; # extract per-field attributes foreach my $a (@a) { + if ($a eq 'custom_query_jumble') + { + $query_jumble_custom = 1; + } if ($a eq 'query_jumble_ignore') { $query_jumble_ignore = 1; @@ -1294,15 +1311,33 @@ sub elem { $query_jumble_location = 1; } + elsif ($a eq 'query_jumble_squash') + { + $query_jumble_squash = 1; + } } - # node type - if (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/) - and elem $1, @node_types) + if ($query_jumble_custom) { - print $jff "\tJUMBLE_NODE($f);\n" + # Custom function that applies to one field of a node. + print $jff "\tJUMBLE_CUSTOM($n, $f);\n" unless $query_jumble_ignore; } + elsif (($t =~ /^(\w+)\*$/ or $t =~ /^struct\s+(\w+)\*$/) + and elem $1, @node_types) + { + # Node type. Squash constants if requested. + if ($query_jumble_squash) + { + print $jff "\tJUMBLE_ELEMENTS($f, node);\n" + unless $query_jumble_ignore; + } + else + { + print $jff "\tJUMBLE_NODE($f);\n" + unless $query_jumble_ignore; + } + } elsif ($t eq 'ParseLoc') { # Track the node's location only if directly requested. diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index e2615ab10503c..1597b8e812756 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -6,7 +6,7 @@ * See comments in pg_list.h. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 61ac172a85748..e2d9e9be41a65 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -4,7 +4,7 @@ * creator functions for various nodes. The functions here are for the * most frequently created nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -51,7 +51,7 @@ makeSimpleA_Expr(A_Expr_Kind kind, char *name, A_Expr *a = makeNode(A_Expr); a->kind = kind; - a->name = list_make1(makeString((char *) name)); + a->name = list_make1(makeString(name)); a->lexpr = lexpr; a->rexpr = rexpr; a->location = location; @@ -80,12 +80,14 @@ makeVar(int varno, var->varlevelsup = varlevelsup; /* - * Only a few callers need to make Var nodes with non-null varnullingrels, - * or with varnosyn/varattnosyn different from varno/varattno. We don't - * provide separate arguments for them, but just initialize them to NULL - * and the given varno/varattno. This reduces code clutter and chance of - * error for most callers. + * Only a few callers need to make Var nodes with varreturningtype + * different from VAR_RETURNING_DEFAULT, non-null varnullingrels, or with + * varnosyn/varattnosyn different from varno/varattno. We don't provide + * separate arguments for them, but just initialize them to sensible + * default values. This reduces code clutter and chance of error for most + * callers. */ + var->varreturningtype = VAR_RETURNING_DEFAULT; var->varnullingrels = NULL; var->varnosyn = (Index) varno; var->varattnosyn = varattno; @@ -159,6 +161,53 @@ makeWholeRowVar(RangeTblEntry *rte, varlevelsup); break; + case RTE_SUBQUERY: + + /* + * For a standard subquery, the Var should be of RECORD type. + * However, if we're looking at a subquery that was expanded from + * a view or SRF (only possible during planning), we must use the + * appropriate rowtype, so that the resulting Var has the same + * type that we would have produced from the original RTE. + */ + if (OidIsValid(rte->relid)) + { + /* Subquery was expanded from a view */ + toid = get_rel_type_id(rte->relid); + if (!OidIsValid(toid)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" does not have a composite type", + get_rel_name(rte->relid)))); + } + else if (rte->functions) + { + /* + * Subquery was expanded from a set-returning function. That + * would not have happened if there's more than one function + * or ordinality was requested. We also needn't worry about + * the allowScalar case, since the planner doesn't use that. + * Otherwise this must match the RTE_FUNCTION code below. + */ + Assert(!allowScalar); + fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; + toid = exprType(fexpr); + if (!type_is_rowtype(toid)) + toid = RECORDOID; + } + else + { + /* Normal subquery-in-FROM */ + toid = RECORDOID; + } + result = makeVar(varno, + InvalidAttrNumber, + toid, + -1, + InvalidOid, + varlevelsup); + break; + case RTE_FUNCTION: /* @@ -215,8 +264,8 @@ makeWholeRowVar(RangeTblEntry *rte, default: /* - * RTE is a join, subselect, tablefunc, or VALUES. We represent - * this as a whole-row Var of RECORD type. (Note that in most + * RTE is a join, tablefunc, VALUES, CTE, etc. We represent these + * cases as a whole-row Var of RECORD type. (Note that in most * cases the Var will be expanded to a RowExpr during planning, * but that is not our concern here.) */ @@ -436,6 +485,30 @@ makeRangeVar(char *schemaname, char *relname, int location) return r; } +/* + * makeNotNullConstraint - + * creates a Constraint node for NOT NULL constraints + */ +Constraint * +makeNotNullConstraint(String *colname) +{ + Constraint *notnull; + + notnull = makeNode(Constraint); + notnull->contype = CONSTR_NOTNULL; + notnull->conname = NULL; + notnull->is_no_inherit = false; + notnull->deferrable = false; + notnull->initdeferred = false; + notnull->location = -1; + notnull->keys = list_make1(colname); + notnull->is_enforced = true; + notnull->skip_validation = false; + notnull->initially_valid = true; + + return notnull; +} + /* * makeTypeName - * build a TypeName node for an unqualified name. @@ -760,7 +833,8 @@ make_ands_implicit(Expr *clause) IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool nulls_not_distinct, - bool isready, bool concurrent, bool summarizing) + bool isready, bool concurrent, bool summarizing, + bool withoutoverlaps) { IndexInfo *n = makeNode(IndexInfo); @@ -775,6 +849,7 @@ makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, n->ii_IndexUnchanged = false; n->ii_Concurrent = concurrent; n->ii_Summarizing = summarizing; + n->ii_WithoutOverlaps = withoutoverlaps; /* summarizing indexes cannot contain non-key attributes */ Assert(!summarizing || (numkeyattrs == numattrs)); diff --git a/src/backend/nodes/meson.build b/src/backend/nodes/meson.build index 49626f160e16e..9a1c1b7b987bd 100644 --- a/src/backend/nodes/meson.build +++ b/src/backend/nodes/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bitmapset.c', diff --git a/src/backend/nodes/multibitmapset.c b/src/backend/nodes/multibitmapset.c index 610d634e59fb0..d88e39c1a89c1 100644 --- a/src/backend/nodes/multibitmapset.c +++ b/src/backend/nodes/multibitmapset.c @@ -18,7 +18,7 @@ * a small fraction of that has been built out; we'll add more as needed. * * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/nodes/multibitmapset.c diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index d2e2af4f8116d..7bc823507f1b3 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -3,7 +3,7 @@ * nodeFuncs.c * Various general-purpose manipulations of Node trees * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -278,6 +278,9 @@ exprType(const Node *expr) type = exprType((Node *) n->expr); } break; + case T_ReturningExpr: + type = exprType((Node *) ((const ReturningExpr *) expr)->retexpr); + break; case T_PlaceHolderVar: type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; @@ -529,6 +532,8 @@ exprTypmod(const Node *expr) return ((const CoerceToDomainValue *) expr)->typeMod; case T_SetToDefault: return ((const SetToDefault *) expr)->typeMod; + case T_ReturningExpr: + return exprTypmod((Node *) ((const ReturningExpr *) expr)->retexpr); case T_PlaceHolderVar: return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr); default: @@ -1047,6 +1052,9 @@ exprCollation(const Node *expr) case T_InferenceElem: coll = exprCollation((Node *) ((const InferenceElem *) expr)->expr); break; + case T_ReturningExpr: + coll = exprCollation((Node *) ((const ReturningExpr *) expr)->retexpr); + break; case T_PlaceHolderVar: coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; @@ -1110,7 +1118,7 @@ exprInputCollation(const Node *expr) * Assign collation information to an expression tree node. * * Note: since this is only used during parse analysis, we don't need to - * worry about subplans or PlaceHolderVars. + * worry about subplans, PlaceHolderVars, or ReturningExprs. */ void exprSetCollation(Node *expr, Oid collation) @@ -1624,6 +1632,9 @@ exprLocation(const Node *expr) case T_SetToDefault: loc = ((const SetToDefault *) expr)->location; break; + case T_ReturningExpr: + loc = exprLocation((Node *) ((const ReturningExpr *) expr)->retexpr); + break; case T_TargetEntry: /* just use argument's location */ loc = exprLocation((Node *) ((const TargetEntry *) expr)->expr); @@ -1723,8 +1734,7 @@ exprLocation(const Node *expr) loc = ((const Constraint *) expr)->location; break; case T_FunctionParameter: - /* just use typename's location */ - loc = exprLocation((Node *) ((const FunctionParameter *) expr)->argType); + loc = ((const FunctionParameter *) expr)->location; break; case T_XmlSerialize: /* XMLSERIALIZE keyword should always be the first thing */ @@ -2021,7 +2031,7 @@ check_functions_in_node(Node *node, check_function_callback checker, * ... do special actions for other node types * } * // for any node type not specially processed, do: - * return expression_tree_walker(node, my_walker, (void *) context); + * return expression_tree_walker(node, my_walker, context); * } * * The "context" argument points to a struct that holds whatever context @@ -2614,6 +2624,8 @@ expression_tree_walker_impl(Node *node, return WALK(((PlaceHolderVar *) node)->phexpr); case T_InferenceElem: return WALK(((InferenceElem *) node)->expr); + case T_ReturningExpr: + return WALK(((ReturningExpr *) node)->retexpr); case T_AppendRelInfo: { AppendRelInfo *appinfo = (AppendRelInfo *) node; @@ -2854,6 +2866,11 @@ range_table_entry_walker_impl(RangeTblEntry *rte, case RTE_RESULT: /* nothing to do */ break; + case RTE_GROUP: + if (!(flags & QTW_IGNORE_GROUPEXPRS)) + if (WALK(rte->groupexprs)) + return true; + break; } if (WALK(rte->securityQuals)) @@ -2889,7 +2906,7 @@ range_table_entry_walker_impl(RangeTblEntry *rte, * ... do special transformations of other node types * } * // for any node type not specially processed, do: - * return expression_tree_mutator(node, my_mutator, (void *) context); + * return expression_tree_mutator(node, my_mutator, context); * } * * The "context" argument points to a struct that holds whatever context @@ -2991,7 +3008,7 @@ expression_tree_mutator_impl(Node *node, case T_SortGroupClause: case T_CTESearchClause: case T_MergeSupportFunc: - return (Node *) copyObject(node); + return copyObject(node); case T_WithCheckOption: { WithCheckOption *wco = (WithCheckOption *) node; @@ -3450,6 +3467,16 @@ expression_tree_mutator_impl(Node *node, return (Node *) newnode; } break; + case T_ReturningExpr: + { + ReturningExpr *rexpr = (ReturningExpr *) node; + ReturningExpr *newnode; + + FLATCOPY(newnode, rexpr, ReturningExpr); + MUTATE(newnode->retexpr, rexpr->retexpr, Expr *); + return (Node *) newnode; + } + break; case T_TargetEntry: { TargetEntry *targetentry = (TargetEntry *) node; @@ -3599,7 +3626,7 @@ expression_tree_mutator_impl(Node *node, break; case T_PartitionPruneStepCombine: /* no expression sub-nodes */ - return (Node *) copyObject(node); + return copyObject(node); case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; @@ -3891,6 +3918,15 @@ range_table_mutator_impl(List *rtable, case RTE_RESULT: /* nothing to do */ break; + case RTE_GROUP: + if (!(flags & QTW_IGNORE_GROUPEXPRS)) + MUTATE(newrte->groupexprs, rte->groupexprs, List *); + else + { + /* else, copy grouping exprs as-is */ + newrte->groupexprs = copyObject(rte->groupexprs); + } + break; } MUTATE(newrte->securityQuals, rte->securityQuals, List *); newrt = lappend(newrt, newrte); @@ -3992,6 +4028,7 @@ raw_expression_tree_walker_impl(Node *node, case T_A_Const: case T_A_Star: case T_MergeSupportFunc: + case T_ReturningOption: /* primitive node types with no subnodes */ break; case T_Alias: @@ -4220,7 +4257,7 @@ raw_expression_tree_walker_impl(Node *node, return true; if (WALK(stmt->onConflictClause)) return true; - if (WALK(stmt->returningList)) + if (WALK(stmt->returningClause)) return true; if (WALK(stmt->withClause)) return true; @@ -4236,7 +4273,7 @@ raw_expression_tree_walker_impl(Node *node, return true; if (WALK(stmt->whereClause)) return true; - if (WALK(stmt->returningList)) + if (WALK(stmt->returningClause)) return true; if (WALK(stmt->withClause)) return true; @@ -4254,7 +4291,7 @@ raw_expression_tree_walker_impl(Node *node, return true; if (WALK(stmt->fromClause)) return true; - if (WALK(stmt->returningList)) + if (WALK(stmt->returningClause)) return true; if (WALK(stmt->withClause)) return true; @@ -4272,7 +4309,7 @@ raw_expression_tree_walker_impl(Node *node, return true; if (WALK(stmt->mergeWhenClauses)) return true; - if (WALK(stmt->returningList)) + if (WALK(stmt->returningClause)) return true; if (WALK(stmt->withClause)) return true; @@ -4290,6 +4327,16 @@ raw_expression_tree_walker_impl(Node *node, return true; } break; + case T_ReturningClause: + { + ReturningClause *returning = (ReturningClause *) node; + + if (WALK(returning->options)) + return true; + if (WALK(returning->exprs)) + return true; + } + break; case T_SelectStmt: { SelectStmt *stmt = (SelectStmt *) node; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3337b77ae6d7a..eaf391fc2abdc 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -3,7 +3,7 @@ * outfuncs.c * Output functions for Postgres tree nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -51,6 +51,12 @@ static void outDouble(StringInfo str, double d); #define WRITE_UINT_FIELD(fldname) \ appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) +/* Write a signed integer field (anything written with INT64_FORMAT) */ +#define WRITE_INT64_FIELD(fldname) \ + appendStringInfo(str, \ + " :" CppAsString(fldname) " " INT64_FORMAT, \ + node->fldname) + /* Write an unsigned integer field (anything written with UINT64_FORMAT) */ #define WRITE_UINT64_FIELD(fldname) \ appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \ @@ -465,9 +471,12 @@ _outEquivalenceClass(StringInfo str, const EquivalenceClass *node) WRITE_NODE_FIELD(ec_opfamilies); WRITE_OID_FIELD(ec_collation); + WRITE_INT_FIELD(ec_childmembers_size); WRITE_NODE_FIELD(ec_members); + WRITE_NODE_ARRAY(ec_childmembers, node->ec_childmembers_size); WRITE_NODE_FIELD(ec_sources); - WRITE_NODE_FIELD(ec_derives); + /* Only ec_derives_list is written; hash is not serialized. */ + WRITE_NODE_FIELD(ec_derives_list); WRITE_BITMAPSET_FIELD(ec_relids); WRITE_BOOL_FIELD(ec_has_const); WRITE_BOOL_FIELD(ec_has_volatile); @@ -562,6 +571,9 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) case RTE_RESULT: /* no extra fields */ break; + case RTE_GROUP: + WRITE_NODE_FIELD(groupexprs); + break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind); break; @@ -641,6 +653,8 @@ _outA_Expr(StringInfo str, const A_Expr *node) WRITE_NODE_FIELD(lexpr); WRITE_NODE_FIELD(rexpr); + WRITE_LOCATION_FIELD(rexpr_list_start); + WRITE_LOCATION_FIELD(rexpr_list_end); WRITE_LOCATION_FIELD(location); } diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index cf54ffbe0d923..ec5946c5777dc 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -4,7 +4,7 @@ * Support for finding the values associated with Param nodes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -55,7 +55,7 @@ makeParamList(int numParams) retval->paramCompile = NULL; retval->paramCompileArg = NULL; retval->parserSetup = paramlist_parser_setup; - retval->parserSetupArg = (void *) retval; + retval->parserSetupArg = retval; retval->paramValuesStr = NULL; retval->numParams = numParams; diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index 02798f4482d04..65011aaf278ac 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -3,7 +3,7 @@ * print.c * various print routines (used mostly for debugging) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -300,6 +300,10 @@ print_rt(const List *rtable) printf("%d\t%s\t[result]", i, rte->eref->aliasname); break; + case RTE_GROUP: + printf("%d\t%s\t[group]", + i, rte->eref->aliasname); + break; default: printf("%d\t%s\t[unknown rtekind]", i, rte->eref->aliasname); diff --git a/src/backend/nodes/queryjumblefuncs.c b/src/backend/nodes/queryjumblefuncs.c index 129fb447099fe..fb33e6931ada3 100644 --- a/src/backend/nodes/queryjumblefuncs.c +++ b/src/backend/nodes/queryjumblefuncs.c @@ -21,7 +21,7 @@ * tree(s) generated from the query. The executor can then use this value * to blame query costs on the proper queryId. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,9 +32,13 @@ */ #include "postgres.h" +#include "access/transam.h" +#include "catalog/pg_proc.h" #include "common/hashfn.h" #include "miscadmin.h" +#include "nodes/nodeFuncs.h" #include "nodes/queryjumble.h" +#include "utils/lsyscache.h" #include "parser/scansup.h" #define JUMBLE_SIZE 1024 /* query serialization buffer size */ @@ -51,12 +55,21 @@ int compute_query_id = COMPUTE_QUERY_ID_AUTO; */ bool query_id_enabled = false; +static JumbleState *InitJumble(void); +static int64 DoJumble(JumbleState *jstate, Node *node); static void AppendJumble(JumbleState *jstate, - const unsigned char *item, Size size); -static void RecordConstLocation(JumbleState *jstate, int location); + const unsigned char *value, Size size); +static void FlushPendingNulls(JumbleState *jstate); +static void RecordConstLocation(JumbleState *jstate, + int location, int len); static void _jumbleNode(JumbleState *jstate, Node *node); +static void _jumbleElements(JumbleState *jstate, List *elements, Node *node); static void _jumbleA_Const(JumbleState *jstate, Node *node); static void _jumbleList(JumbleState *jstate, Node *node); +static void _jumbleVariableSetStmt(JumbleState *jstate, Node *node); +static void _jumbleRangeTblEntry_eref(JumbleState *jstate, + RangeTblEntry *rte, + Alias *expr); /* * Given a possibly multi-statement source string, confine our attention to the @@ -89,6 +102,12 @@ CleanQuerytext(const char *query, int *location, int *len) /* * Discard leading and trailing whitespace, too. Use scanner_isspace() * not libc's isspace(), because we want to match the lexer's behavior. + * + * Note: the parser now strips leading comments and whitespace from the + * reported stmt_location, so this first loop will only iterate in the + * unusual case that the location didn't propagate to here. But the + * statement length will extend to the end-of-string or terminating + * semicolon, so the second loop often does something useful. */ while (query_len > 0 && scanner_isspace(query[0])) query++, query_location++, query_len--; @@ -101,40 +120,33 @@ CleanQuerytext(const char *query, int *location, int *len) return query; } +/* + * JumbleQuery + * Recursively process the given Query producing a 64-bit hash value by + * hashing the relevant fields and record that value in the Query's queryId + * field. Return the JumbleState object used for jumbling the query. + */ JumbleState * JumbleQuery(Query *query) { - JumbleState *jstate = NULL; + JumbleState *jstate; Assert(IsQueryIdEnabled()); - jstate = (JumbleState *) palloc(sizeof(JumbleState)); + jstate = InitJumble(); - /* Set up workspace for query jumbling */ - jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE); - jstate->jumble_len = 0; - jstate->clocations_buf_size = 32; - jstate->clocations = (LocationLen *) - palloc(jstate->clocations_buf_size * sizeof(LocationLen)); - jstate->clocations_count = 0; - jstate->highest_extern_param_id = 0; - - /* Compute query ID and mark the Query node with it */ - _jumbleNode(jstate, (Node *) query); - query->queryId = DatumGetUInt64(hash_any_extended(jstate->jumble, - jstate->jumble_len, - 0)); + query->queryId = DoJumble(jstate, (Node *) query); /* * If we are unlucky enough to get a hash of zero, use 1 instead for * normal statements and 2 for utility queries. */ - if (query->queryId == UINT64CONST(0)) + if (query->queryId == INT64CONST(0)) { if (query->utilityStmt) - query->queryId = UINT64CONST(2); + query->queryId = INT64CONST(2); else - query->queryId = UINT64CONST(1); + query->queryId = INT64CONST(1); } return jstate; @@ -154,30 +166,100 @@ EnableQueryId(void) } /* - * AppendJumble: Append a value that is substantive in a given query to - * the current jumble. + * InitJumble + * Allocate a JumbleState object and make it ready to jumble. */ -static void -AppendJumble(JumbleState *jstate, const unsigned char *item, Size size) +static JumbleState * +InitJumble(void) +{ + JumbleState *jstate; + + jstate = (JumbleState *) palloc(sizeof(JumbleState)); + + /* Set up workspace for query jumbling */ + jstate->jumble = (unsigned char *) palloc(JUMBLE_SIZE); + jstate->jumble_len = 0; + jstate->clocations_buf_size = 32; + jstate->clocations = (LocationLen *) palloc(jstate->clocations_buf_size * + sizeof(LocationLen)); + jstate->clocations_count = 0; + jstate->highest_extern_param_id = 0; + jstate->pending_nulls = 0; +#ifdef USE_ASSERT_CHECKING + jstate->total_jumble_len = 0; +#endif + + return jstate; +} + +/* + * DoJumble + * Jumble the given Node using the given JumbleState and return the resulting + * jumble hash. + */ +static int64 +DoJumble(JumbleState *jstate, Node *node) +{ + /* Jumble the given node */ + _jumbleNode(jstate, node); + + /* Flush any pending NULLs before doing the final hash */ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + /* Process the jumble buffer and produce the hash value */ + return DatumGetInt64(hash_any_extended(jstate->jumble, + jstate->jumble_len, + 0)); +} + +/* + * AppendJumbleInternal: Internal function for appending to the jumble buffer + * + * Note: Callers must ensure that size > 0. + */ +static pg_attribute_always_inline void +AppendJumbleInternal(JumbleState *jstate, const unsigned char *item, + Size size) { unsigned char *jumble = jstate->jumble; Size jumble_len = jstate->jumble_len; + /* Ensure the caller didn't mess up */ + Assert(size > 0); + + /* + * Fast path for when there's enough space left in the buffer. This is + * worthwhile as means the memcpy can be inlined into very efficient code + * when 'size' is a compile-time constant. + */ + if (likely(size <= JUMBLE_SIZE - jumble_len)) + { + memcpy(jumble + jumble_len, item, size); + jstate->jumble_len += size; + +#ifdef USE_ASSERT_CHECKING + jstate->total_jumble_len += size; +#endif + + return; + } + /* * Whenever the jumble buffer is full, we hash the current contents and * reset the buffer to contain just that hash value, thus relying on the * hash to summarize everything so far. */ - while (size > 0) + do { Size part_size; - if (jumble_len >= JUMBLE_SIZE) + if (unlikely(jumble_len >= JUMBLE_SIZE)) { - uint64 start_hash; + int64 start_hash; - start_hash = DatumGetUInt64(hash_any_extended(jumble, - JUMBLE_SIZE, 0)); + start_hash = DatumGetInt64(hash_any_extended(jumble, + JUMBLE_SIZE, 0)); memcpy(jumble, &start_hash, sizeof(start_hash)); jumble_len = sizeof(start_hash); } @@ -186,16 +268,122 @@ AppendJumble(JumbleState *jstate, const unsigned char *item, Size size) jumble_len += part_size; item += part_size; size -= part_size; - } + +#ifdef USE_ASSERT_CHECKING + jstate->total_jumble_len += part_size; +#endif + } while (size > 0); + jstate->jumble_len = jumble_len; } /* - * Record location of constant within query string of query tree - * that is currently being walked. + * AppendJumble + * Add 'size' bytes of the given jumble 'value' to the jumble state + */ +static pg_noinline void +AppendJumble(JumbleState *jstate, const unsigned char *value, Size size) +{ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + AppendJumbleInternal(jstate, value, size); +} + +/* + * AppendJumbleNull + * For jumbling NULL pointers + */ +static pg_attribute_always_inline void +AppendJumbleNull(JumbleState *jstate) +{ + jstate->pending_nulls++; +} + +/* + * AppendJumble8 + * Add the first byte from the given 'value' pointer to the jumble state + */ +static pg_noinline void +AppendJumble8(JumbleState *jstate, const unsigned char *value) +{ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + AppendJumbleInternal(jstate, value, 1); +} + +/* + * AppendJumble16 + * Add the first 2 bytes from the given 'value' pointer to the jumble + * state. + */ +static pg_noinline void +AppendJumble16(JumbleState *jstate, const unsigned char *value) +{ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + AppendJumbleInternal(jstate, value, 2); +} + +/* + * AppendJumble32 + * Add the first 4 bytes from the given 'value' pointer to the jumble + * state. + */ +static pg_noinline void +AppendJumble32(JumbleState *jstate, const unsigned char *value) +{ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + AppendJumbleInternal(jstate, value, 4); +} + +/* + * AppendJumble64 + * Add the first 8 bytes from the given 'value' pointer to the jumble + * state. + */ +static pg_noinline void +AppendJumble64(JumbleState *jstate, const unsigned char *value) +{ + if (jstate->pending_nulls > 0) + FlushPendingNulls(jstate); + + AppendJumbleInternal(jstate, value, 8); +} + +/* + * FlushPendingNulls + * Incorporate the pending_nulls value into the jumble buffer. + * + * Note: Callers must ensure that there's at least 1 pending NULL. + */ +static pg_attribute_always_inline void +FlushPendingNulls(JumbleState *jstate) +{ + Assert(jstate->pending_nulls > 0); + + AppendJumbleInternal(jstate, + (const unsigned char *) &jstate->pending_nulls, 4); + jstate->pending_nulls = 0; +} + + +/* + * Record the location of some kind of constant within a query string. + * These are not only bare constants but also expressions that ultimately + * constitute a constant, such as those inside casts and simple function + * calls. + * + * If length is -1, it indicates a single such constant element. If + * it's a positive integer, it indicates the length of a squashable + * list of them. */ static void -RecordConstLocation(JumbleState *jstate, int location) +RecordConstLocation(JumbleState *jstate, int location, int len) { /* -1 indicates unknown or undefined location */ if (location >= 0) @@ -210,35 +398,192 @@ RecordConstLocation(JumbleState *jstate, int location) sizeof(LocationLen)); } jstate->clocations[jstate->clocations_count].location = location; - /* initialize lengths to -1 to simplify third-party module usage */ - jstate->clocations[jstate->clocations_count].length = -1; + + /* + * Lengths are either positive integers (indicating a squashable + * list), or -1. + */ + Assert(len > -1 || len == -1); + jstate->clocations[jstate->clocations_count].length = len; + jstate->clocations[jstate->clocations_count].squashed = (len > -1); jstate->clocations_count++; } } +/* + * Subroutine for _jumbleElements: Verify a few simple cases where we can + * deduce that the expression is a constant: + * + * - Ignore a possible wrapping RelabelType and CoerceViaIO. + * - If it's a FuncExpr, check that the function is a builtin + * cast and its arguments are Const. + * - Otherwise test if the expression is a simple Const. + */ +static bool +IsSquashableConstant(Node *element) +{ + if (IsA(element, RelabelType)) + element = (Node *) ((RelabelType *) element)->arg; + + if (IsA(element, CoerceViaIO)) + element = (Node *) ((CoerceViaIO *) element)->arg; + + switch (nodeTag(element)) + { + case T_FuncExpr: + { + FuncExpr *func = (FuncExpr *) element; + ListCell *temp; + + if (func->funcformat != COERCE_IMPLICIT_CAST && + func->funcformat != COERCE_EXPLICIT_CAST) + return false; + + if (func->funcid > FirstGenbkiObjectId) + return false; + + /* + * We can check function arguments recursively, being careful + * about recursing too deep. At each recursion level it's + * enough to test the stack on the first element. (Note that + * I wasn't able to hit this without bloating the stack + * artificially in this function: the parser errors out before + * stack size becomes a problem here.) + */ + foreach(temp, func->args) + { + Node *arg = lfirst(temp); + + if (!IsA(arg, Const)) + { + if (foreach_current_index(temp) == 0 && + stack_is_too_deep()) + return false; + else if (!IsSquashableConstant(arg)) + return false; + } + } + + return true; + } + + default: + if (!IsA(element, Const)) + return false; + } + + return true; +} + +/* + * Subroutine for _jumbleElements: Verify whether the provided list + * can be squashed, meaning it contains only constant expressions. + * + * Return value indicates if squashing is possible. + * + * Note that this function searches only for explicit Const nodes with + * possibly very simple decorations on top, and does not try to simplify + * expressions. + */ +static bool +IsSquashableConstantList(List *elements) +{ + ListCell *temp; + + /* If the list is too short, we don't try to squash it. */ + if (list_length(elements) < 2) + return false; + + foreach(temp, elements) + { + if (!IsSquashableConstant(lfirst(temp))) + return false; + } + + return true; +} + #define JUMBLE_NODE(item) \ _jumbleNode(jstate, (Node *) expr->item) +#define JUMBLE_ELEMENTS(list, node) \ + _jumbleElements(jstate, (List *) expr->list, node) #define JUMBLE_LOCATION(location) \ - RecordConstLocation(jstate, expr->location) + RecordConstLocation(jstate, expr->location, -1) #define JUMBLE_FIELD(item) \ - AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item)) -#define JUMBLE_FIELD_SINGLE(item) \ - AppendJumble(jstate, (const unsigned char *) &(item), sizeof(item)) +do { \ + if (sizeof(expr->item) == 8) \ + AppendJumble64(jstate, (const unsigned char *) &(expr->item)); \ + else if (sizeof(expr->item) == 4) \ + AppendJumble32(jstate, (const unsigned char *) &(expr->item)); \ + else if (sizeof(expr->item) == 2) \ + AppendJumble16(jstate, (const unsigned char *) &(expr->item)); \ + else if (sizeof(expr->item) == 1) \ + AppendJumble8(jstate, (const unsigned char *) &(expr->item)); \ + else \ + AppendJumble(jstate, (const unsigned char *) &(expr->item), sizeof(expr->item)); \ +} while (0) #define JUMBLE_STRING(str) \ do { \ if (expr->str) \ AppendJumble(jstate, (const unsigned char *) (expr->str), strlen(expr->str) + 1); \ + else \ + AppendJumbleNull(jstate); \ } while(0) +/* Function name used for the node field attribute custom_query_jumble. */ +#define JUMBLE_CUSTOM(nodetype, item) \ + _jumble##nodetype##_##item(jstate, expr, expr->item) #include "queryjumblefuncs.funcs.c" +/* + * We try to jumble lists of expressions as one individual item regardless + * of how many elements are in the list. This is know as squashing, which + * results in different queries jumbling to the same query_id, if the only + * difference is the number of elements in the list. + * + * We allow constants to be squashed. To normalize such queries, we use + * the start and end locations of the list of elements in a list. + */ +static void +_jumbleElements(JumbleState *jstate, List *elements, Node *node) +{ + bool normalize_list = false; + + if (IsSquashableConstantList(elements)) + { + if (IsA(node, ArrayExpr)) + { + ArrayExpr *aexpr = (ArrayExpr *) node; + + if (aexpr->list_start > 0 && aexpr->list_end > 0) + { + RecordConstLocation(jstate, + aexpr->list_start + 1, + (aexpr->list_end - aexpr->list_start) - 1); + normalize_list = true; + } + } + } + + if (!normalize_list) + { + _jumbleNode(jstate, (Node *) elements); + } +} + static void _jumbleNode(JumbleState *jstate, Node *node) { Node *expr = node; +#ifdef USE_ASSERT_CHECKING + Size prev_jumble_len = jstate->total_jumble_len; +#endif if (expr == NULL) + { + AppendJumbleNull(jstate); return; + } /* Guard against stack overflow due to overly complex expressions */ check_stack_depth(); @@ -286,6 +631,9 @@ _jumbleNode(JumbleState *jstate, Node *node) default: break; } + + /* Ensure we added something to the jumble buffer */ + Assert(jstate->total_jumble_len > prev_jumble_len); } static void @@ -302,15 +650,15 @@ _jumbleList(JumbleState *jstate, Node *node) break; case T_IntList: foreach(l, expr) - JUMBLE_FIELD_SINGLE(lfirst_int(l)); + AppendJumble32(jstate, (const unsigned char *) &lfirst_int(l)); break; case T_OidList: foreach(l, expr) - JUMBLE_FIELD_SINGLE(lfirst_oid(l)); + AppendJumble32(jstate, (const unsigned char *) &lfirst_oid(l)); break; case T_XidList: foreach(l, expr) - JUMBLE_FIELD_SINGLE(lfirst_xid(l)); + AppendJumble32(jstate, (const unsigned char *) &lfirst_xid(l)); break; default: elog(ERROR, "unrecognized list node type: %d", @@ -352,3 +700,37 @@ _jumbleA_Const(JumbleState *jstate, Node *node) } } } + +static void +_jumbleVariableSetStmt(JumbleState *jstate, Node *node) +{ + VariableSetStmt *expr = (VariableSetStmt *) node; + + JUMBLE_FIELD(kind); + JUMBLE_STRING(name); + + /* + * Account for the list of arguments in query jumbling only if told by the + * parser. + */ + if (expr->jumble_args) + JUMBLE_NODE(args); + JUMBLE_FIELD(is_local); + JUMBLE_LOCATION(location); +} + +/* + * Custom query jumble function for RangeTblEntry.eref. + */ +static void +_jumbleRangeTblEntry_eref(JumbleState *jstate, + RangeTblEntry *rte, + Alias *expr) +{ + JUMBLE_FIELD(type); + + /* + * This includes only the table name, the list of column names is ignored. + */ + JUMBLE_STRING(aliasname); +} diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index 4eb42445c528b..ce335dd3ff154 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -4,7 +4,7 @@ * routines to convert a string (legal ascii representation of node) back * to nodes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,7 +32,7 @@ static const char *pg_strtok_ptr = NULL; /* State flag that determines how readfuncs.c should treat location fields */ -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED bool restore_location_fields = false; #endif @@ -43,14 +43,14 @@ bool restore_location_fields = false; * * restore_loc_fields instructs readfuncs.c whether to restore location * fields rather than set them to -1. This is currently only supported - * in builds with the WRITE_READ_PARSE_PLAN_TREES debugging flag set. + * in builds with DEBUG_NODE_TESTS_ENABLED defined. */ static void * stringToNodeInternal(const char *str, bool restore_loc_fields) { void *retval; const char *save_strtok; -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED bool save_restore_location_fields; #endif @@ -67,7 +67,7 @@ stringToNodeInternal(const char *str, bool restore_loc_fields) /* * If enabled, likewise save/restore the location field handling flag. */ -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED save_restore_location_fields = restore_location_fields; restore_location_fields = restore_loc_fields; #endif @@ -76,7 +76,7 @@ stringToNodeInternal(const char *str, bool restore_loc_fields) pg_strtok_ptr = save_strtok; -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED restore_location_fields = save_restore_location_fields; #endif @@ -92,7 +92,7 @@ stringToNode(const char *str) return stringToNodeInternal(str, false); } -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED void * stringToNodeWithLocations(const char *str) @@ -507,5 +507,5 @@ nodeRead(const char *token, int tok_len) break; } - return (void *) result; + return result; } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index c4d01a441a030..48b5d13b9b62c 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -3,7 +3,7 @@ * readfuncs.c * Reader functions for Postgres tree nodes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,7 +19,7 @@ * * However, if restore_location_fields is true, we do restore location * fields from the string. This is currently intended only for use by the - * WRITE_READ_PARSE_PLAN_TREES test code, which doesn't want to cause + * debug_write_read_parse_plan_trees test code, which doesn't want to cause * any change in the node contents. * *------------------------------------------------------------------------- @@ -68,6 +68,12 @@ token = pg_strtok(&length); /* get field value */ \ local_node->fldname = atoui(token) +/* Read a signed integer field (anything written using INT64_FORMAT) */ +#define READ_INT64_FIELD(fldname) \ + token = pg_strtok(&length); /* skip :fldname */ \ + token = pg_strtok(&length); /* get field value */ \ + local_node->fldname = strtoi64(token, NULL, 10) + /* Read an unsigned integer field (anything written using UINT64_FORMAT) */ #define READ_UINT64_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ @@ -118,7 +124,7 @@ local_node->fldname = nullable_string(token, length) /* Read a parse location field (and possibly throw away the value) */ -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED #define READ_LOCATION_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ @@ -422,6 +428,9 @@ _readRangeTblEntry(void) case RTE_RESULT: /* no extra fields */ break; + case RTE_GROUP: + READ_NODE_FIELD(groupexprs); + break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) local_node->rtekind); @@ -517,6 +526,8 @@ _readA_Expr(void) READ_NODE_FIELD(lexpr); READ_NODE_FIELD(rexpr); + READ_LOCATION_FIELD(rexpr_list_start); + READ_LOCATION_FIELD(rexpr_list_end); READ_LOCATION_FIELD(location); READ_DONE(); diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index e8ab5d78fcc7c..41031aa8f2fa8 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -29,7 +29,7 @@ * and a non-lossy page. * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/nodes/tidbitmap.c @@ -40,7 +40,6 @@ #include -#include "access/htup_details.h" #include "common/hashfn.h" #include "common/int.h" #include "nodes/bitmapset.h" @@ -48,14 +47,6 @@ #include "storage/lwlock.h" #include "utils/dsa.h" -/* - * The maximum number of tuples per page is not large (typically 256 with - * 8K pages, or 1024 with 32K pages). So there's not much point in making - * the per-page bitmaps variable size. We just legislate that the size - * is this: - */ -#define MAX_TUPLES_PER_PAGE MaxHeapTuplesPerPage - /* * When we have to switch over to lossy storage, we use a data structure * with one bit per page, where all pages having the same number DIV @@ -67,7 +58,7 @@ * table, using identical data structures. (This is because the memory * management for hashtables doesn't easily/efficiently allow space to be * transferred easily from one hashtable to another.) Therefore it's best - * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not + * if PAGES_PER_CHUNK is the same as TBM_MAX_TUPLES_PER_PAGE, or at least not * too different. But we also want PAGES_PER_CHUNK to be a power of 2 to * avoid expensive integer remainder operations. So, define it like this: */ @@ -79,7 +70,7 @@ #define BITNUM(x) ((x) % BITS_PER_BITMAPWORD) /* number of active words for an exact page: */ -#define WORDS_PER_PAGE ((MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1) +#define WORDS_PER_PAGE ((TBM_MAX_TUPLES_PER_PAGE - 1) / BITS_PER_BITMAPWORD + 1) /* number of active words for a lossy chunk: */ #define WORDS_PER_CHUNK ((PAGES_PER_CHUNK - 1) / BITS_PER_BITMAPWORD + 1) @@ -170,18 +161,17 @@ struct TIDBitmap }; /* - * When iterating over a bitmap in sorted order, a TBMIterator is used to - * track our progress. There can be several iterators scanning the same - * bitmap concurrently. Note that the bitmap becomes read-only as soon as - * any iterator is created. + * When iterating over a backend-local bitmap in sorted order, a + * TBMPrivateIterator is used to track our progress. There can be several + * iterators scanning the same bitmap concurrently. Note that the bitmap + * becomes read-only as soon as any iterator is created. */ -struct TBMIterator +struct TBMPrivateIterator { TIDBitmap *tbm; /* TIDBitmap we're iterating over */ int spageptr; /* next spages index */ int schunkptr; /* next schunks index */ int schunkbit; /* next bit to check in current schunk */ - TBMIterateResult output; /* MUST BE LAST (because variable-size) */ }; /* @@ -213,8 +203,8 @@ typedef struct PTIterationArray } PTIterationArray; /* - * same as TBMIterator, but it is used for joint iteration, therefore this - * also holds a reference to the shared state. + * same as TBMPrivateIterator, but it is used for joint iteration, therefore + * this also holds a reference to the shared state. */ struct TBMSharedIterator { @@ -222,7 +212,6 @@ struct TBMSharedIterator PTEntryArray *ptbase; /* pagetable element array */ PTIterationArray *ptpages; /* sorted exact page index list */ PTIterationArray *ptchunks; /* sorted lossy page index list */ - TBMIterateResult output; /* MUST BE LAST (because variable-size) */ }; /* Local function prototypes */ @@ -263,7 +252,7 @@ static int tbm_shared_comparator(const void *left, const void *right, * be allocated from the DSA. */ TIDBitmap * -tbm_create(long maxbytes, dsa_area *dsa) +tbm_create(Size maxbytes, dsa_area *dsa) { TIDBitmap *tbm; @@ -273,7 +262,7 @@ tbm_create(long maxbytes, dsa_area *dsa) tbm->mcxt = CurrentMemoryContext; tbm->status = TBM_EMPTY; - tbm->maxentries = (int) tbm_calculate_entries(maxbytes); + tbm->maxentries = tbm_calculate_entries(maxbytes); tbm->lossify_start = 0; tbm->dsa = dsa; tbm->dsapagetable = InvalidDsaPointer; @@ -390,7 +379,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids, bitnum; /* safety check to ensure we don't overrun bit array bounds */ - if (off < 1 || off > MAX_TUPLES_PER_PAGE) + if (off < 1 || off > TBM_MAX_TUPLES_PER_PAGE) elog(ERROR, "tuple offset out of range: %u", off); /* @@ -673,31 +662,30 @@ tbm_is_empty(const TIDBitmap *tbm) } /* - * tbm_begin_iterate - prepare to iterate through a TIDBitmap + * tbm_begin_private_iterate - prepare to iterate through a TIDBitmap * - * The TBMIterator struct is created in the caller's memory context. - * For a clean shutdown of the iteration, call tbm_end_iterate; but it's - * okay to just allow the memory context to be released, too. It is caller's - * responsibility not to touch the TBMIterator anymore once the TIDBitmap - * is freed. + * The TBMPrivateIterator struct is created in the caller's memory context. + * For a clean shutdown of the iteration, call tbm_end_private_iterate; but + * it's okay to just allow the memory context to be released, too. It is + * caller's responsibility not to touch the TBMPrivateIterator anymore once + * the TIDBitmap is freed. * * NB: after this is called, it is no longer allowed to modify the contents * of the bitmap. However, you can call this multiple times to scan the * contents repeatedly, including parallel scans. */ -TBMIterator * -tbm_begin_iterate(TIDBitmap *tbm) +TBMPrivateIterator * +tbm_begin_private_iterate(TIDBitmap *tbm) { - TBMIterator *iterator; + TBMPrivateIterator *iterator; Assert(tbm->iterating != TBM_ITERATING_SHARED); /* - * Create the TBMIterator struct, with enough trailing space to serve the - * needs of the TBMIterateResult sub-struct. + * Create the TBMPrivateIterator struct, with enough trailing space to + * serve the needs of the TBMIterateResult sub-struct. */ - iterator = (TBMIterator *) palloc(sizeof(TBMIterator) + - MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber)); + iterator = (TBMPrivateIterator *) palloc(sizeof(TBMPrivateIterator)); iterator->tbm = tbm; /* @@ -878,7 +866,7 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm) ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks); /* - * For every shared iterator, referring to pagetable and iterator array, + * For every shared iterator referring to pagetable and iterator array, * increase the refcount by 1 so that while freeing the shared iterator we * don't free pagetable and iterator array until its refcount becomes 0. */ @@ -905,11 +893,16 @@ tbm_prepare_shared_iterate(TIDBitmap *tbm) /* * tbm_extract_page_tuple - extract the tuple offsets from a page * - * The extracted offsets are stored into TBMIterateResult. + * Returns the number of offsets it filled in if <= max_offsets. Otherwise, + * fills in as many offsets as fit and returns the total number of offsets in + * the page. */ -static inline int -tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output) +int +tbm_extract_page_tuple(TBMIterateResult *iteritem, + OffsetNumber *offsets, + uint32 max_offsets) { + PagetableEntry *page = iteritem->internal_page; int wordnum; int ntuples = 0; @@ -924,7 +917,11 @@ tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output) while (w != 0) { if (w & 1) - output->offsets[ntuples++] = (OffsetNumber) off; + { + if (ntuples < max_offsets) + offsets[ntuples] = (OffsetNumber) off; + ntuples++; + } off++; w >>= 1; } @@ -956,22 +953,30 @@ tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp) } /* - * tbm_iterate - scan through next page of a TIDBitmap + * tbm_private_iterate - scan through next page of a TIDBitmap + * + * Caller must pass in a TBMIterateResult to be filled. * - * Returns a TBMIterateResult representing one page, or NULL if there are - * no more pages to scan. Pages are guaranteed to be delivered in numerical - * order. If result->ntuples < 0, then the bitmap is "lossy" and failed to - * remember the exact tuples to look at on this page --- the caller must - * examine all tuples on the page and check if they meet the intended - * condition. If result->recheck is true, only the indicated tuples need - * be examined, but the condition must be rechecked anyway. (For ease of - * testing, recheck is always set true when ntuples < 0.) + * Pages are guaranteed to be delivered in numerical order. + * + * Returns false when there are no more pages to scan and true otherwise. When + * there are no more pages to scan, tbmres->blockno is set to + * InvalidBlockNumber. + * + * If lossy is true, then the bitmap is "lossy" and failed to remember + * the exact tuples to look at on this page --- the caller must examine all + * tuples on the page and check if they meet the intended condition. If lossy + * is false, the caller must later extract the tuple offsets from the page + * pointed to by internal_page with tbm_extract_page_tuple. + * + * If tbmres->recheck is true, only the indicated tuples need be examined, but + * the condition must be rechecked anyway. (For ease of testing, recheck is + * always set true when lossy is true.) */ -TBMIterateResult * -tbm_iterate(TBMIterator *iterator) +bool +tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres) { TIDBitmap *tbm = iterator->tbm; - TBMIterateResult *output = &(iterator->output); Assert(tbm->iterating == TBM_ITERATING_PRIVATE); @@ -1009,18 +1014,18 @@ tbm_iterate(TBMIterator *iterator) chunk_blockno < tbm->spages[iterator->spageptr]->blockno) { /* Return a lossy page indicator from the chunk */ - output->blockno = chunk_blockno; - output->ntuples = -1; - output->recheck = true; + tbmres->blockno = chunk_blockno; + tbmres->lossy = true; + tbmres->recheck = true; + tbmres->internal_page = NULL; iterator->schunkbit++; - return output; + return true; } } if (iterator->spageptr < tbm->npages) { PagetableEntry *page; - int ntuples; /* In TBM_ONE_PAGE state, we don't allocate an spages[] array */ if (tbm->status == TBM_ONE_PAGE) @@ -1028,17 +1033,17 @@ tbm_iterate(TBMIterator *iterator) else page = tbm->spages[iterator->spageptr]; - /* scan bitmap to extract individual offset numbers */ - ntuples = tbm_extract_page_tuple(page, output); - output->blockno = page->blockno; - output->ntuples = ntuples; - output->recheck = page->recheck; + tbmres->internal_page = page; + tbmres->blockno = page->blockno; + tbmres->lossy = false; + tbmres->recheck = page->recheck; iterator->spageptr++; - return output; + return true; } /* Nothing more in the bitmap */ - return NULL; + tbmres->blockno = InvalidBlockNumber; + return false; } /* @@ -1048,10 +1053,9 @@ tbm_iterate(TBMIterator *iterator) * across multiple processes. We need to acquire the iterator LWLock, * before accessing the shared members. */ -TBMIterateResult * -tbm_shared_iterate(TBMSharedIterator *iterator) +bool +tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres) { - TBMIterateResult *output = &iterator->output; TBMSharedIteratorState *istate = iterator->state; PagetableEntry *ptbase = NULL; int *idxpages = NULL; @@ -1102,48 +1106,48 @@ tbm_shared_iterate(TBMSharedIterator *iterator) chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno) { /* Return a lossy page indicator from the chunk */ - output->blockno = chunk_blockno; - output->ntuples = -1; - output->recheck = true; + tbmres->blockno = chunk_blockno; + tbmres->lossy = true; + tbmres->recheck = true; + tbmres->internal_page = NULL; istate->schunkbit++; LWLockRelease(&istate->lock); - return output; + return true; } } if (istate->spageptr < istate->npages) { PagetableEntry *page = &ptbase[idxpages[istate->spageptr]]; - int ntuples; - /* scan bitmap to extract individual offset numbers */ - ntuples = tbm_extract_page_tuple(page, output); - output->blockno = page->blockno; - output->ntuples = ntuples; - output->recheck = page->recheck; + tbmres->internal_page = page; + tbmres->blockno = page->blockno; + tbmres->lossy = false; + tbmres->recheck = page->recheck; istate->spageptr++; LWLockRelease(&istate->lock); - return output; + return true; } LWLockRelease(&istate->lock); /* Nothing more in the bitmap */ - return NULL; + tbmres->blockno = InvalidBlockNumber; + return false; } /* - * tbm_end_iterate - finish an iteration over a TIDBitmap + * tbm_end_private_iterate - finish an iteration over a TIDBitmap * * Currently this is just a pfree, but it might do more someday. (For * instance, it could be useful to count open iterators and allow the * bitmap to return to read/write status when there are no more iterators.) */ void -tbm_end_iterate(TBMIterator *iterator) +tbm_end_private_iterate(TBMPrivateIterator *iterator) { pfree(iterator); } @@ -1467,8 +1471,7 @@ tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp) * Create the TBMSharedIterator struct, with enough trailing space to * serve the needs of the TBMIterateResult sub-struct. */ - iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) + - MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber)); + iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator)); istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp); @@ -1538,10 +1541,10 @@ pagetable_free(pagetable_hash *pagetable, void *pointer) * * Estimate number of hashtable entries we can have within maxbytes. */ -long -tbm_calculate_entries(double maxbytes) +int +tbm_calculate_entries(Size maxbytes) { - long nbuckets; + Size nbuckets; /* * Estimate number of hashtable entries we can have within maxbytes. This @@ -1554,5 +1557,70 @@ tbm_calculate_entries(double maxbytes) nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */ nbuckets = Max(nbuckets, 16); /* sanity limit */ - return nbuckets; + return (int) nbuckets; +} + +/* + * Create a shared or private bitmap iterator and start iteration. + * + * `tbm` is only used to create the private iterator and dsa and dsp are only + * used to create the shared iterator. + * + * Before invoking tbm_begin_iterate() to create a shared iterator, one + * process must already have invoked tbm_prepare_shared_iterate() to create + * and set up the TBMSharedIteratorState. + */ +TBMIterator +tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp) +{ + TBMIterator iterator = {0}; + + /* Allocate a private iterator and attach the shared state to it */ + if (DsaPointerIsValid(dsp)) + { + iterator.shared = true; + iterator.i.shared_iterator = tbm_attach_shared_iterate(dsa, dsp); + } + else + { + iterator.shared = false; + iterator.i.private_iterator = tbm_begin_private_iterate(tbm); + } + + return iterator; +} + +/* + * Clean up shared or private bitmap iterator. + */ +void +tbm_end_iterate(TBMIterator *iterator) +{ + Assert(iterator && !tbm_exhausted(iterator)); + + if (iterator->shared) + tbm_end_shared_iterate(iterator->i.shared_iterator); + else + tbm_end_private_iterate(iterator->i.private_iterator); + + *iterator = (TBMIterator) + { + 0 + }; +} + +/* + * Populate the next TBMIterateResult using the shared or private bitmap + * iterator. Returns false when there is nothing more to scan. + */ +bool +tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres) +{ + Assert(iterator); + Assert(tbmres); + + if (iterator->shared) + return tbm_shared_iterate(iterator->i.shared_iterator, tbmres); + else + return tbm_private_iterate(iterator->i.private_iterator, tbmres); } diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c index 5a18f4035b57f..5a8c1ce24781c 100644 --- a/src/backend/nodes/value.c +++ b/src/backend/nodes/value.c @@ -4,7 +4,7 @@ * implementation of value nodes * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/optimizer/README b/src/backend/optimizer/README index 2ab4f3dbf3793..9c724ccfabf83 100644 --- a/src/backend/optimizer/README +++ b/src/backend/optimizer/README @@ -143,7 +143,6 @@ For example: {1 2},{2 3},{3 4} {1 2 3},{2 3 4} {1 2 3 4} - (other possibilities will be excluded for lack of join clauses) SELECT * FROM tab1, tab2, tab3, tab4 @@ -156,6 +155,11 @@ For example: {1 2 3},{1 3 4},{1 2 4} {1 2 3 4} +In each of these examples, other join-order possibilities will be excluded +for lack of join clauses. (In reality, use of EquivalenceClasses would +allow us to deduce additional join clauses that allow more join orders, +but here we ignore that to preserve the simplicity of the examples.) + We consider left-handed plans (the outer rel of an upper join is a joinrel, but the inner is always a single list item); right-handed plans (outer rel is always a single item); and bushy plans (both inner and outer can be @@ -649,7 +653,7 @@ RelOptInfo - a relation or joined relations GroupingSetsPath - an Agg plan node used to implement GROUPING SETS MinMaxAggPath - a Result plan node with subplans performing MIN/MAX WindowAggPath - a WindowAgg plan node applied to some sub-path - SetOpPath - a SetOp plan node applied to some sub-path + SetOpPath - a SetOp plan node applied to two sub-paths RecursiveUnionPath - a RecursiveUnion plan node applied to two sub-paths LockRowsPath - a LockRows plan node applied to some sub-path ModifyTablePath - a ModifyTable plan node applied to some sub-path(s) @@ -898,7 +902,7 @@ contain the equivalent child-relation variables or expressions. These members are *not* full-fledged members of the EquivalenceClass and do not affect the class's overall properties at all. They are kept only to simplify matching of child-relation expressions to EquivalenceClasses. -Most operations on EquivalenceClasses should ignore child members. +Most operations on EquivalenceClasses needn't look at child members. PathKeys diff --git a/src/backend/optimizer/geqo/geqo_copy.c b/src/backend/optimizer/geqo/geqo_copy.c index af98e9f0a4179..cbf21dc72e8f1 100644 --- a/src/backend/optimizer/geqo/geqo_copy.c +++ b/src/backend/optimizer/geqo/geqo_copy.c @@ -2,7 +2,7 @@ * * geqo_copy.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_copy.c diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index d2f7f4e5f3c0f..f07d1dc8ac69b 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -3,7 +3,7 @@ * geqo_eval.c * Routines to evaluate query trees * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_eval.c diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index 0c5540e2af445..38402ce58db25 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -4,7 +4,7 @@ * solution to the query optimization problem * by means of a Genetic Algorithm (GA) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_main.c @@ -99,7 +99,7 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) #endif /* set up private information */ - root->join_search_private = (void *) &private; + root->join_search_private = &private; private.initial_rels = initial_rels; /* initialize private number generator */ diff --git a/src/backend/optimizer/geqo/geqo_misc.c b/src/backend/optimizer/geqo/geqo_misc.c index f9e1ca6fd4515..b8fcc9b6a2f96 100644 --- a/src/backend/optimizer/geqo/geqo_misc.c +++ b/src/backend/optimizer/geqo/geqo_misc.c @@ -3,7 +3,7 @@ * geqo_misc.c * misc. printout and debug stuff * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_misc.c diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c index 0ec97d5a3f14c..b6de0d93f2817 100644 --- a/src/backend/optimizer/geqo/geqo_pool.c +++ b/src/backend/optimizer/geqo/geqo_pool.c @@ -3,7 +3,7 @@ * geqo_pool.c * Genetic Algorithm (GA) pool stuff * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_pool.c diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c index 510105c7eeeb7..6c7a411f69f44 100644 --- a/src/backend/optimizer/geqo/geqo_random.c +++ b/src/backend/optimizer/geqo/geqo_random.c @@ -3,7 +3,7 @@ * geqo_random.c * random number generator * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_random.c diff --git a/src/backend/optimizer/geqo/geqo_selection.c b/src/backend/optimizer/geqo/geqo_selection.c index c6d270f1f8535..9e0a5d4fec86d 100644 --- a/src/backend/optimizer/geqo/geqo_selection.c +++ b/src/backend/optimizer/geqo/geqo_selection.c @@ -3,7 +3,7 @@ * geqo_selection.c * linear selection scheme for the genetic query optimizer * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/optimizer/geqo/geqo_selection.c diff --git a/src/backend/optimizer/geqo/meson.build b/src/backend/optimizer/geqo/meson.build index fdc22d787567e..b476489143560 100644 --- a/src/backend/optimizer/geqo/meson.build +++ b/src/backend/optimizer/geqo/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'geqo_copy.c', diff --git a/src/backend/optimizer/meson.build b/src/backend/optimizer/meson.build index ff9e519b128c4..d4924e3022a25 100644 --- a/src/backend/optimizer/meson.build +++ b/src/backend/optimizer/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('geqo') subdir('path') diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 057b4b79ebb8d..6cc6966b0600a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -3,7 +3,7 @@ * allpaths.c * Routines to find possible search paths for processing a query * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -731,6 +731,10 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, case RTE_RESULT: /* RESULT RTEs, in themselves, are no problem. */ break; + case RTE_GROUP: + /* Shouldn't happen; we're only considering baserels here. */ + Assert(false); + return; } /* @@ -954,6 +958,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, { int parentRTindex = rti; bool has_live_children; + double parent_tuples; double parent_rows; double parent_size; double *parent_attrsizes; @@ -979,6 +984,15 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, /* * Initialize to compute size estimates for whole append relation. * + * We handle tuples estimates by setting "tuples" to the total number of + * tuples accumulated from each live child, rather than using "rows". + * Although an appendrel itself doesn't directly enforce any quals, its + * child relations may. Therefore, setting "tuples" equal to "rows" for + * an appendrel isn't always appropriate, and can lead to inaccurate cost + * estimates. For example, when estimating the number of distinct values + * from an appendrel, we would be unable to adjust the estimate based on + * the restriction selectivity (see estimate_num_groups). + * * We handle width estimates by weighting the widths of different child * rels proportionally to their number of rows. This is sensible because * the use of width estimates is mainly to compute the total relation @@ -991,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, * have zero rows and/or width, if they were excluded by constraints. */ has_live_children = false; + parent_tuples = 0; parent_rows = 0; parent_size = 0; nattrs = rel->max_attr - rel->min_attr + 1; @@ -1157,6 +1172,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, */ Assert(childrel->rows > 0); + parent_tuples += childrel->tuples; parent_rows += childrel->rows; parent_size += childrel->reltarget->width * childrel->rows; @@ -1203,17 +1219,12 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, int i; Assert(parent_rows > 0); + rel->tuples = parent_tuples; rel->rows = parent_rows; rel->reltarget->width = rint(parent_size / parent_rows); for (i = 0; i < nattrs; i++) rel->attr_widths[i] = rint(parent_attrsizes[i] / parent_rows); - /* - * Set "raw tuples" count equal to "rows" for the appendrel; needed - * because some places assume rel->tuples is valid for any baserel. - */ - rel->tuples = parent_rows; - /* * Note that we leave rel->pages as zero; this is important to avoid * double-counting the appendrel tree in total_table_pages. @@ -1360,9 +1371,23 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, */ if (rel->consider_startup && childrel->cheapest_startup_path != NULL) { + Path *cheapest_path; + + /* + * With an indication of how many tuples the query should provide, + * the optimizer tries to choose the path optimal for that + * specific number of tuples. + */ + if (root->tuple_fraction > 0.0) + cheapest_path = + get_cheapest_fractional_path(childrel, + root->tuple_fraction); + else + cheapest_path = childrel->cheapest_startup_path; + /* cheapest_startup_path must not be a parameterized path. */ - Assert(childrel->cheapest_startup_path->param_info == NULL); - accumulate_append_subpath(childrel->cheapest_startup_path, + Assert(cheapest_path->param_info == NULL); + accumulate_append_subpath(cheapest_path, &startup_subpaths, NULL); } @@ -1866,7 +1891,17 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel, */ if (root->tuple_fraction > 0) { - double path_fraction = (1.0 / root->tuple_fraction); + double path_fraction = root->tuple_fraction; + + /* + * Merge Append considers only live children relations. Dummy + * relations must be filtered out before. + */ + Assert(childrel->rows > 0); + + /* Convert absolute limit to a path fraction */ + if (path_fraction >= 1.0) + path_fraction /= childrel->rows; cheapest_fractional = get_cheapest_fractional_path_for_pathkeys(childrel->pathlist, @@ -2288,16 +2323,15 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti, runopexpr = NULL; runoperator = InvalidOid; - opinfos = get_op_btree_interpretation(opexpr->opno); + opinfos = get_op_index_interpretation(opexpr->opno); foreach(lc, opinfos) { - OpBtreeInterpretation *opinfo = (OpBtreeInterpretation *) lfirst(lc); - int strategy = opinfo->strategy; + OpIndexInterpretation *opinfo = (OpIndexInterpretation *) lfirst(lc); + CompareType cmptype = opinfo->cmptype; /* handle < / <= */ - if (strategy == BTLessStrategyNumber || - strategy == BTLessEqualStrategyNumber) + if (cmptype == COMPARE_LT || cmptype == COMPARE_LE) { /* * < / <= is supported for monotonically increasing functions in @@ -2314,8 +2348,7 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti, break; } /* handle > / >= */ - else if (strategy == BTGreaterStrategyNumber || - strategy == BTGreaterEqualStrategyNumber) + else if (cmptype == COMPARE_GT || cmptype == COMPARE_GE) { /* * > / >= is supported for monotonically decreasing functions in @@ -2332,9 +2365,9 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti, break; } /* handle = */ - else if (strategy == BTEqualStrategyNumber) + else if (cmptype == COMPARE_EQ) { - int16 newstrategy; + CompareType newcmptype; /* * When both monotonically increasing and decreasing then the @@ -2358,19 +2391,19 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti, * below the value in the equality condition. */ if (res->monotonic & MONOTONICFUNC_INCREASING) - newstrategy = wfunc_left ? BTLessEqualStrategyNumber : BTGreaterEqualStrategyNumber; + newcmptype = wfunc_left ? COMPARE_LE : COMPARE_GE; else - newstrategy = wfunc_left ? BTGreaterEqualStrategyNumber : BTLessEqualStrategyNumber; + newcmptype = wfunc_left ? COMPARE_GE : COMPARE_LE; /* We must keep the original equality qual */ *keep_original = true; runopexpr = opexpr; /* determine the operator to use for the WindowFuncRunCondition */ - runoperator = get_opfamily_member(opinfo->opfamily_id, - opinfo->oplefttype, - opinfo->oprighttype, - newstrategy); + runoperator = get_opfamily_member_for_cmptype(opinfo->opfamily_id, + opinfo->oplefttype, + opinfo->oprighttype, + newcmptype); break; } } @@ -3981,6 +4014,7 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual) */ qual = ReplaceVarsFromTargetList(qual, rti, 0, rte, subquery->targetList, + subquery->resultRelation, REPLACEVARS_REPORT_ERROR, 0, &subquery->hasSubLinks); diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 0ab021c1e89aa..5d51f97f21906 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -3,7 +3,7 @@ * clausesel.c * Routines to compute clause selectivities * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 79991b19807b9..3d44815ed5adf 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -50,6 +50,17 @@ * so beware of division-by-zero.) The LIMIT is applied as a top-level * plan node. * + * Each path stores the total number of disabled nodes that exist at or + * below that point in the plan tree. This is regarded as a component of + * the cost, and paths with fewer disabled nodes should be regarded as + * cheaper than those with more. Disabled nodes occur when the user sets + * a GUC like enable_seqscan=false. We can't necessarily respect such a + * setting in every part of the plan tree, but we want to respect in as many + * parts of the plan tree as possible. Simpler schemes like storing a Boolean + * here rather than a count fail to do that. We used to disable nodes by + * adding a large constant to the startup cost, but that distorted planning + * in other ways. + * * For largely historical reasons, most of the routines in this module use * the passed result Path only to store their results (rows, startup_cost and * total_cost) into. All the input data they need is passed as separate @@ -60,7 +71,7 @@ * values. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -301,9 +312,6 @@ cost_seqscan(Path *path, PlannerInfo *root, else path->rows = baserel->rows; - if (!enable_seqscan) - startup_cost += disable_cost; - /* fetch estimated page cost for tablespace containing table */ get_tablespace_page_costs(baserel->reltablespace, NULL, @@ -346,6 +354,7 @@ cost_seqscan(Path *path, PlannerInfo *root, path->rows = clamp_row_est(path->rows / parallel_divisor); } + path->disabled_nodes = enable_seqscan ? 0 : 1; path->startup_cost = startup_cost; path->total_cost = startup_cost + cpu_run_cost + disk_run_cost; } @@ -418,6 +427,7 @@ cost_samplescan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -456,6 +466,7 @@ cost_gather(GatherPath *path, PlannerInfo *root, startup_cost += parallel_setup_cost; run_cost += parallel_tuple_cost * path->path.rows; + path->path.disabled_nodes = path->subpath->disabled_nodes; path->path.startup_cost = startup_cost; path->path.total_cost = (startup_cost + run_cost); } @@ -473,6 +484,7 @@ cost_gather(GatherPath *path, PlannerInfo *root, void cost_gather_merge(GatherMergePath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double *rows) { @@ -490,9 +502,6 @@ cost_gather_merge(GatherMergePath *path, PlannerInfo *root, else path->path.rows = rel->rows; - if (!enable_gathermerge) - startup_cost += disable_cost; - /* * Add one to the number of workers to account for the leader. This might * be overgenerous since the leader will do less work than other workers @@ -523,6 +532,8 @@ cost_gather_merge(GatherMergePath *path, PlannerInfo *root, startup_cost += parallel_setup_cost; run_cost += parallel_tuple_cost * path->path.rows * 1.05; + path->path.disabled_nodes = input_disabled_nodes + + (enable_gathermerge ? 0 : 1); path->path.startup_cost = startup_cost + input_startup_cost; path->path.total_cost = (startup_cost + run_cost + input_total_cost); } @@ -603,9 +614,8 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count, path->indexclauses); } - if (!enable_indexscan) - startup_cost += disable_cost; /* we don't need to check enable_indexonlyscan; indxpath.c does that */ + path->path.disabled_nodes = enable_indexscan ? 0 : 1; /* * Call index-access-method-specific code to estimate the processing cost @@ -1038,9 +1048,6 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, else path->rows = baserel->rows; - if (!enable_bitmapscan) - startup_cost += disable_cost; - pages_fetched = compute_bitmap_pages(root, baserel, bitmapqual, loop_count, &indexTotalCost, &tuples_fetched); @@ -1102,6 +1109,7 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = enable_bitmapscan ? 0 : 1; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1187,6 +1195,7 @@ cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root) } path->bitmapselectivity = selec; path->path.rows = 0; /* per above, not used */ + path->path.disabled_nodes = 0; path->path.startup_cost = totalCost; path->path.total_cost = totalCost; } @@ -1261,6 +1270,7 @@ cost_tidscan(Path *path, PlannerInfo *root, /* Should only be applied to base relations */ Assert(baserel->relid > 0); Assert(baserel->rtekind == RTE_RELATION); + Assert(tidquals != NIL); /* Mark the path with the correct row estimate */ if (param_info) @@ -1275,6 +1285,14 @@ cost_tidscan(Path *path, PlannerInfo *root, RestrictInfo *rinfo = lfirst_node(RestrictInfo, l); Expr *qual = rinfo->clause; + /* + * We must use a TID scan for CurrentOfExpr; in any other case, we + * should be generating a TID scan only if enable_tidscan=true. Also, + * if CurrentOfExpr is the qual, there should be only one. + */ + Assert(enable_tidscan || IsA(qual, CurrentOfExpr)); + Assert(list_length(tidquals) == 1 || !IsA(qual, CurrentOfExpr)); + if (IsA(qual, ScalarArrayOpExpr)) { /* Each element of the array yields 1 tuple */ @@ -1322,6 +1340,12 @@ cost_tidscan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + /* + * There are assertions above verifying that we only reach this function + * either when enable_tidscan=true or when the TID scan is the only legal + * path, so it's safe to set disabled_nodes to zero here. + */ + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1414,6 +1438,9 @@ cost_tidrangescan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + /* we should not generate this path type when enable_tidscan=false */ + Assert(enable_tidscan); + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1466,6 +1493,7 @@ cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root, * SubqueryScan node, plus cpu_tuple_cost to account for selection and * projection overhead. */ + path->path.disabled_nodes = path->subpath->disabled_nodes; path->path.startup_cost = path->subpath->startup_cost; path->path.total_cost = path->subpath->total_cost; @@ -1556,6 +1584,7 @@ cost_functionscan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1612,6 +1641,7 @@ cost_tablefuncscan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1659,6 +1689,7 @@ cost_valuesscan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1706,6 +1737,7 @@ cost_ctescan(Path *path, PlannerInfo *root, startup_cost += path->pathtarget->cost.startup; run_cost += path->pathtarget->cost.per_tuple * path->rows; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1743,6 +1775,7 @@ cost_namedtuplestorescan(Path *path, PlannerInfo *root, cpu_per_tuple += cpu_tuple_cost + qpqual_cost.per_tuple; run_cost += cpu_per_tuple * baserel->tuples; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1777,6 +1810,7 @@ cost_resultscan(Path *path, PlannerInfo *root, cpu_per_tuple = cpu_tuple_cost + qpqual_cost.per_tuple; run_cost += cpu_per_tuple * baserel->tuples; + path->disabled_nodes = 0; path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -1816,6 +1850,7 @@ cost_recursive_union(Path *runion, Path *nrterm, Path *rterm) */ total_cost += cpu_tuple_cost * total_rows; + runion->disabled_nodes = nrterm->disabled_nodes + rterm->disabled_nodes; runion->startup_cost = startup_cost; runion->total_cost = total_cost; runion->rows = total_rows; @@ -1868,7 +1903,7 @@ cost_tuplesort(Cost *startup_cost, Cost *run_cost, double input_bytes = relation_byte_size(tuples, width); double output_bytes; double output_tuples; - long sort_mem_bytes = sort_mem * 1024L; + int64 sort_mem_bytes = sort_mem * (int64) 1024; /* * We want to be sure the cost of a sort is never estimated as zero, even @@ -1964,6 +1999,7 @@ cost_tuplesort(Cost *startup_cost, Cost *run_cost, void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples) @@ -2083,6 +2119,11 @@ cost_incremental_sort(Path *path, run_cost += 2.0 * cpu_tuple_cost * input_groups; path->rows = input_tuples; + + /* should not generate these paths when enable_incremental_sort=false */ + Assert(enable_incremental_sort); + path->disabled_nodes = input_disabled_nodes; + path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -2101,7 +2142,8 @@ cost_incremental_sort(Path *path, */ void cost_sort(Path *path, PlannerInfo *root, - List *pathkeys, Cost input_cost, double tuples, int width, + List *pathkeys, int input_disabled_nodes, + Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples) @@ -2114,12 +2156,10 @@ cost_sort(Path *path, PlannerInfo *root, comparison_cost, sort_mem, limit_tuples); - if (!enable_sort) - startup_cost += disable_cost; - startup_cost += input_cost; path->rows = tuples; + path->disabled_nodes = input_disabled_nodes + (enable_sort ? 0 : 1); path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -2211,6 +2251,7 @@ cost_append(AppendPath *apath) { ListCell *l; + apath->path.disabled_nodes = 0; apath->path.startup_cost = 0; apath->path.total_cost = 0; apath->path.rows = 0; @@ -2232,12 +2273,16 @@ cost_append(AppendPath *apath) */ apath->path.startup_cost = firstsubpath->startup_cost; - /* Compute rows and costs as sums of subplan rows and costs. */ + /* + * Compute rows, number of disabled nodes, and total cost as sums + * of underlying subplan values. + */ foreach(l, apath->subpaths) { Path *subpath = (Path *) lfirst(l); apath->path.rows += subpath->rows; + apath->path.disabled_nodes += subpath->disabled_nodes; apath->path.total_cost += subpath->total_cost; } } @@ -2277,6 +2322,7 @@ cost_append(AppendPath *apath) cost_sort(&sort_path, NULL, /* doesn't currently need root */ pathkeys, + subpath->disabled_nodes, subpath->total_cost, subpath->rows, subpath->pathtarget->width, @@ -2287,6 +2333,7 @@ cost_append(AppendPath *apath) } apath->path.rows += subpath->rows; + apath->path.disabled_nodes += subpath->disabled_nodes; apath->path.startup_cost += subpath->startup_cost; apath->path.total_cost += subpath->total_cost; } @@ -2335,6 +2382,7 @@ cost_append(AppendPath *apath) apath->path.total_cost += subpath->total_cost; } + apath->path.disabled_nodes += subpath->disabled_nodes; apath->path.rows = clamp_row_est(apath->path.rows); i++; @@ -2375,6 +2423,7 @@ cost_append(AppendPath *apath) * * 'pathkeys' is a list of sort keys * 'n_streams' is the number of input streams + * 'input_disabled_nodes' is the sum of the input streams' disabled node counts * 'input_startup_cost' is the sum of the input streams' startup costs * 'input_total_cost' is the sum of the input streams' total costs * 'tuples' is the number of tuples in all the streams @@ -2382,6 +2431,7 @@ cost_append(AppendPath *apath) void cost_merge_append(Path *path, PlannerInfo *root, List *pathkeys, int n_streams, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples) { @@ -2412,6 +2462,7 @@ cost_merge_append(Path *path, PlannerInfo *root, */ run_cost += cpu_tuple_cost * APPEND_CPU_COST_MULTIPLIER * tuples; + path->disabled_nodes = input_disabled_nodes; path->startup_cost = startup_cost + input_startup_cost; path->total_cost = startup_cost + run_cost + input_total_cost; } @@ -2430,13 +2481,14 @@ cost_merge_append(Path *path, PlannerInfo *root, */ void cost_material(Path *path, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width) { Cost startup_cost = input_startup_cost; Cost run_cost = input_total_cost - input_startup_cost; double nbytes = relation_byte_size(tuples, width); - long work_mem_bytes = work_mem * 1024L; + double work_mem_bytes = work_mem * (Size) 1024; path->rows = tuples; @@ -2467,6 +2519,7 @@ cost_material(Path *path, run_cost += seq_page_cost * npages; } + path->disabled_nodes = input_disabled_nodes + (enable_material ? 0 : 1); path->startup_cost = startup_cost; path->total_cost = startup_cost + run_cost; } @@ -2630,19 +2683,19 @@ cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, const AggClauseCosts *aggcosts, int numGroupCols, double numGroups, List *quals, + int disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, double input_width) { double output_tuples; Cost startup_cost; Cost total_cost; - AggClauseCosts dummy_aggcosts; + const AggClauseCosts dummy_aggcosts = {0}; /* Use all-zero per-aggregate costs if NULL is passed */ if (aggcosts == NULL) { Assert(aggstrategy == AGG_HASHED); - MemSet(&dummy_aggcosts, 0, sizeof(AggClauseCosts)); aggcosts = &dummy_aggcosts; } @@ -2685,10 +2738,7 @@ cost_agg(Path *path, PlannerInfo *root, startup_cost = input_startup_cost; total_cost = input_total_cost; if (aggstrategy == AGG_MIXED && !enable_hashagg) - { - startup_cost += disable_cost; - total_cost += disable_cost; - } + ++disabled_nodes; /* calcs phrased this way to match HASHED case, see note above */ total_cost += aggcosts->transCost.startup; total_cost += aggcosts->transCost.per_tuple * input_tuples; @@ -2703,7 +2753,7 @@ cost_agg(Path *path, PlannerInfo *root, /* must be AGG_HASHED */ startup_cost = input_total_cost; if (!enable_hashagg) - startup_cost += disable_cost; + ++disabled_nodes; startup_cost += aggcosts->transCost.startup; startup_cost += aggcosts->transCost.per_tuple * input_tuples; /* cost of computing hash value */ @@ -2812,6 +2862,7 @@ cost_agg(Path *path, PlannerInfo *root, } path->rows = output_tuples; + path->disabled_nodes = disabled_nodes; path->startup_cost = startup_cost; path->total_cost = total_cost; } @@ -3046,6 +3097,7 @@ get_windowclause_startup_tuples(PlannerInfo *root, WindowClause *wc, void cost_windowagg(Path *path, PlannerInfo *root, List *windowFuncs, WindowClause *winclause, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples) { @@ -3111,6 +3163,7 @@ cost_windowagg(Path *path, PlannerInfo *root, total_cost += cpu_tuple_cost * input_tuples; path->rows = input_tuples; + path->disabled_nodes = input_disabled_nodes; path->startup_cost = startup_cost; path->total_cost = total_cost; @@ -3142,6 +3195,7 @@ void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, List *quals, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples) { @@ -3180,6 +3234,7 @@ cost_group(Path *path, PlannerInfo *root, } path->rows = output_tuples; + path->disabled_nodes = input_disabled_nodes; path->startup_cost = startup_cost; path->total_cost = total_cost; } @@ -3214,6 +3269,7 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, Path *outer_path, Path *inner_path, JoinPathExtraData *extra) { + int disabled_nodes; Cost startup_cost = 0; Cost run_cost = 0; double outer_path_rows = outer_path->rows; @@ -3222,6 +3278,11 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, Cost inner_run_cost; Cost inner_rescan_run_cost; + /* Count up disabled nodes. */ + disabled_nodes = enable_nestloop ? 0 : 1; + disabled_nodes += inner_path->disabled_nodes; + disabled_nodes += outer_path->disabled_nodes; + /* estimate costs to rescan the inner relation */ cost_rescan(root, inner_path, &inner_rescan_start_cost, @@ -3269,6 +3330,7 @@ initial_cost_nestloop(PlannerInfo *root, JoinCostWorkspace *workspace, /* CPU costs left for later */ /* Public result fields */ + workspace->disabled_nodes = disabled_nodes; workspace->startup_cost = startup_cost; workspace->total_cost = startup_cost + run_cost; /* Save private data for final_cost_nestloop */ @@ -3298,6 +3360,9 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path, QualCost restrict_qual_cost; double ntuples; + /* Set the number of disabled nodes. */ + path->jpath.path.disabled_nodes = workspace->disabled_nodes; + /* Protect some assumptions below that rowcounts aren't zero */ if (outer_path_rows <= 0) outer_path_rows = 1; @@ -3318,14 +3383,6 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path, clamp_row_est(path->jpath.path.rows / parallel_divisor); } - /* - * We could include disable_cost in the preliminary estimate, but that - * would amount to optimizing for the case where the join method is - * disabled, which doesn't seem like the way to bet. - */ - if (!enable_nestloop) - startup_cost += disable_cost; - /* cost of inner-relation source data (we already dealt with outer rel) */ if (path->jpath.jointype == JOIN_SEMI || path->jpath.jointype == JOIN_ANTI || @@ -3474,7 +3531,8 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path, * join quals here, except for obtaining the scan selectivity estimate which * is really essential (but fortunately, use of caching keeps the cost of * getting that down to something reasonable). - * We also assume that cost_sort is cheap enough to use here. + * We also assume that cost_sort/cost_incremental_sort is cheap enough to use + * here. * * 'workspace' is to be filled with startup_cost, total_cost, and perhaps * other data to be used by final_cost_mergejoin @@ -3484,6 +3542,7 @@ final_cost_nestloop(PlannerInfo *root, NestPath *path, * 'inner_path' is the inner input to the join * 'outersortkeys' is the list of sort keys for the outer path * 'innersortkeys' is the list of sort keys for the inner path + * 'outer_presorted_keys' is the number of presorted keys of the outer path * 'extra' contains miscellaneous information about the join * * Note: outersortkeys and innersortkeys should be NIL if no explicit @@ -3495,8 +3554,10 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, List *mergeclauses, Path *outer_path, Path *inner_path, List *outersortkeys, List *innersortkeys, + int outer_presorted_keys, JoinPathExtraData *extra) { + int disabled_nodes; Cost startup_cost = 0; Cost run_cost = 0; double outer_path_rows = outer_path->rows; @@ -3510,7 +3571,8 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, outerendsel, innerstartsel, innerendsel; - Path sort_path; /* dummy for result of cost_sort */ + Path sort_path; /* dummy for result of + * cost_sort/cost_incremental_sort */ /* Protect some assumptions below that rowcounts aren't zero */ if (outer_path_rows <= 0) @@ -3548,7 +3610,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, /* debugging check */ if (opathkey->pk_opfamily != ipathkey->pk_opfamily || opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation || - opathkey->pk_strategy != ipathkey->pk_strategy || + opathkey->pk_cmptype != ipathkey->pk_cmptype || opathkey->pk_nulls_first != ipathkey->pk_nulls_first) elog(ERROR, "left and right pathkeys do not match in mergejoin"); @@ -3617,19 +3679,53 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, Assert(outerstartsel <= outerendsel); Assert(innerstartsel <= innerendsel); + disabled_nodes = enable_mergejoin ? 0 : 1; + /* cost of source data */ if (outersortkeys) /* do we need to sort outer? */ { - cost_sort(&sort_path, - root, - outersortkeys, - outer_path->total_cost, - outer_path_rows, - outer_path->pathtarget->width, - 0.0, - work_mem, - -1.0); + /* + * We can assert that the outer path is not already ordered + * appropriately for the mergejoin; otherwise, outersortkeys would + * have been set to NIL. + */ + Assert(!pathkeys_contained_in(outersortkeys, outer_path->pathkeys)); + + /* + * We choose to use incremental sort if it is enabled and there are + * presorted keys; otherwise we use full sort. + */ + if (enable_incremental_sort && outer_presorted_keys > 0) + { + cost_incremental_sort(&sort_path, + root, + outersortkeys, + outer_presorted_keys, + outer_path->disabled_nodes, + outer_path->startup_cost, + outer_path->total_cost, + outer_path_rows, + outer_path->pathtarget->width, + 0.0, + work_mem, + -1.0); + } + else + { + cost_sort(&sort_path, + root, + outersortkeys, + outer_path->disabled_nodes, + outer_path->total_cost, + outer_path_rows, + outer_path->pathtarget->width, + 0.0, + work_mem, + -1.0); + } + + disabled_nodes += sort_path.disabled_nodes; startup_cost += sort_path.startup_cost; startup_cost += (sort_path.total_cost - sort_path.startup_cost) * outerstartsel; @@ -3638,6 +3734,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, } else { + disabled_nodes += outer_path->disabled_nodes; startup_cost += outer_path->startup_cost; startup_cost += (outer_path->total_cost - outer_path->startup_cost) * outerstartsel; @@ -3647,15 +3744,29 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, if (innersortkeys) /* do we need to sort inner? */ { + /* + * We can assert that the inner path is not already ordered + * appropriately for the mergejoin; otherwise, innersortkeys would + * have been set to NIL. + */ + Assert(!pathkeys_contained_in(innersortkeys, inner_path->pathkeys)); + + /* + * We do not consider incremental sort for inner path, because + * incremental sort does not support mark/restore. + */ + cost_sort(&sort_path, root, innersortkeys, + inner_path->disabled_nodes, inner_path->total_cost, inner_path_rows, inner_path->pathtarget->width, 0.0, work_mem, -1.0); + disabled_nodes += sort_path.disabled_nodes; startup_cost += sort_path.startup_cost; startup_cost += (sort_path.total_cost - sort_path.startup_cost) * innerstartsel; @@ -3664,6 +3775,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, } else { + disabled_nodes += inner_path->disabled_nodes; startup_cost += inner_path->startup_cost; startup_cost += (inner_path->total_cost - inner_path->startup_cost) * innerstartsel; @@ -3682,6 +3794,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace, /* CPU costs left for later */ /* Public result fields */ + workspace->disabled_nodes = disabled_nodes; workspace->startup_cost = startup_cost; workspace->total_cost = startup_cost + run_cost + inner_run_cost; /* Save private data for final_cost_mergejoin */ @@ -3746,6 +3859,9 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path, rescannedtuples; double rescanratio; + /* Set the number of disabled nodes. */ + path->jpath.path.disabled_nodes = workspace->disabled_nodes; + /* Protect some assumptions below that rowcounts aren't zero */ if (inner_path_rows <= 0) inner_path_rows = 1; @@ -3765,14 +3881,6 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path, clamp_row_est(path->jpath.path.rows / parallel_divisor); } - /* - * We could include disable_cost in the preliminary estimate, but that - * would amount to optimizing for the case where the join method is - * disabled, which doesn't seem like the way to bet. - */ - if (!enable_mergejoin) - startup_cost += disable_cost; - /* * Compute cost of the mergequals and qpquals (other restriction clauses) * separately. @@ -3920,7 +4028,7 @@ final_cost_mergejoin(PlannerInfo *root, MergePath *path, else if (enable_material && innersortkeys != NIL && relation_byte_size(inner_path_rows, inner_path->pathtarget->width) > - (work_mem * 1024L)) + work_mem * (Size) 1024) path->materialize_inner = true; else path->materialize_inner = false; @@ -3986,7 +4094,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey) cache = (MergeScanSelCache *) lfirst(lc); if (cache->opfamily == pathkey->pk_opfamily && cache->collation == pathkey->pk_eclass->ec_collation && - cache->strategy == pathkey->pk_strategy && + cache->cmptype == pathkey->pk_cmptype && cache->nulls_first == pathkey->pk_nulls_first) return cache; } @@ -3995,7 +4103,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey) mergejoinscansel(root, (Node *) rinfo->clause, pathkey->pk_opfamily, - pathkey->pk_strategy, + pathkey->pk_cmptype, pathkey->pk_nulls_first, &leftstartsel, &leftendsel, @@ -4008,7 +4116,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey) cache = (MergeScanSelCache *) palloc(sizeof(MergeScanSelCache)); cache->opfamily = pathkey->pk_opfamily; cache->collation = pathkey->pk_eclass->ec_collation; - cache->strategy = pathkey->pk_strategy; + cache->cmptype = pathkey->pk_cmptype; cache->nulls_first = pathkey->pk_nulls_first; cache->leftstartsel = leftstartsel; cache->leftendsel = leftendsel; @@ -4056,6 +4164,7 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, JoinPathExtraData *extra, bool parallel_hash) { + int disabled_nodes; Cost startup_cost = 0; Cost run_cost = 0; double outer_path_rows = outer_path->rows; @@ -4067,6 +4176,11 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, int num_skew_mcvs; size_t space_allowed; /* unused */ + /* Count up disabled nodes. */ + disabled_nodes = enable_hashjoin ? 0 : 1; + disabled_nodes += inner_path->disabled_nodes; + disabled_nodes += outer_path->disabled_nodes; + /* cost of source data */ startup_cost += outer_path->startup_cost; run_cost += outer_path->total_cost - outer_path->startup_cost; @@ -4136,6 +4250,7 @@ initial_cost_hashjoin(PlannerInfo *root, JoinCostWorkspace *workspace, /* CPU costs left for later */ /* Public result fields */ + workspace->disabled_nodes = disabled_nodes; workspace->startup_cost = startup_cost; workspace->total_cost = startup_cost + run_cost; /* Save private data for final_cost_hashjoin */ @@ -4180,6 +4295,9 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path, Selectivity innermcvfreq; ListCell *hcl; + /* Set the number of disabled nodes. */ + path->jpath.path.disabled_nodes = workspace->disabled_nodes; + /* Mark the path with the correct row estimate */ if (path->jpath.path.param_info) path->jpath.path.rows = path->jpath.path.param_info->ppi_rows; @@ -4195,14 +4313,6 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path, clamp_row_est(path->jpath.path.rows / parallel_divisor); } - /* - * We could include disable_cost in the preliminary estimate, but that - * would amount to optimizing for the case where the join method is - * disabled, which doesn't seem like the way to bet. - */ - if (!enable_hashjoin) - startup_cost += disable_cost; - /* mark the path with estimated # of batches */ path->num_batches = numbatches; @@ -4229,9 +4339,19 @@ final_cost_hashjoin(PlannerInfo *root, HashPath *path, } else { + List *otherclauses; + innerbucketsize = 1.0; innermcvfreq = 1.0; - foreach(hcl, hashclauses) + + /* At first, try to estimate bucket size using extended statistics. */ + otherclauses = estimate_multivariate_bucketsize(root, + inner_path->parent, + hashclauses, + &innerbucketsize); + + /* Pass through the remaining clauses */ + foreach(hcl, otherclauses) { RestrictInfo *restrictinfo = lfirst_node(RestrictInfo, hcl); Selectivity thisbucketsize; @@ -4553,7 +4673,7 @@ cost_rescan(PlannerInfo *root, Path *path, Cost run_cost = cpu_tuple_cost * path->rows; double nbytes = relation_byte_size(path->rows, path->pathtarget->width); - long work_mem_bytes = work_mem * 1024L; + double work_mem_bytes = work_mem * (Size) 1024; if (nbytes > work_mem_bytes) { @@ -4580,7 +4700,7 @@ cost_rescan(PlannerInfo *root, Path *path, Cost run_cost = cpu_operator_cost * path->rows; double nbytes = relation_byte_size(path->rows, path->pathtarget->width); - long work_mem_bytes = work_mem * 1024L; + double work_mem_bytes = work_mem * (Size) 1024; if (nbytes > work_mem_bytes) { @@ -4614,6 +4734,9 @@ cost_rescan(PlannerInfo *root, Path *path, * preferred since it allows caching of the results.) * The result includes both a one-time (startup) component, * and a per-evaluation component. + * + * Note: in some code paths root can be passed as NULL, resulting in + * slightly worse estimates. */ void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root) @@ -4916,8 +5039,7 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) } /* recurse into children */ - return expression_tree_walker(node, cost_qual_eval_walker, - (void *) context); + return expression_tree_walker(node, cost_qual_eval_walker, context); } /* @@ -5727,7 +5849,8 @@ get_foreign_key_join_selectivity(PlannerInfo *root, if (ec && ec->ec_has_const) { EquivalenceMember *em = fkinfo->fk_eclass_member[i]; - RestrictInfo *rinfo = find_derived_clause_for_ec_member(ec, + RestrictInfo *rinfo = find_derived_clause_for_ec_member(root, + ec, em); if (rinfo) @@ -6384,7 +6507,7 @@ compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, double pages_fetched; double tuples_fetched; double heap_pages; - long maxentries; + double maxentries; /* * Fetch total cost of obtaining the bitmap, as well as its total @@ -6415,7 +6538,7 @@ compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, * the bitmap at one time.) */ heap_pages = Min(pages_fetched, baserel->pages); - maxentries = tbm_calculate_entries(work_mem * 1024L); + maxentries = tbm_calculate_entries(work_mem * (Size) 1024); if (loop_count > 1) { diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 51d806326eba3..441f12f6c50cf 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -6,7 +6,7 @@ * See src/backend/optimizer/README for discussion of EquivalenceClasses. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -20,6 +20,7 @@ #include "access/stratnum.h" #include "catalog/pg_type.h" +#include "common/hashfn.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/appendinfo.h" @@ -33,12 +34,23 @@ #include "utils/lsyscache.h" +static EquivalenceMember *make_eq_member(EquivalenceClass *ec, + Expr *expr, Relids relids, + JoinDomain *jdomain, + EquivalenceMember *parent, + Oid datatype); static EquivalenceMember *add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, JoinDomain *jdomain, - EquivalenceMember *parent, Oid datatype); -static bool is_exprlist_member(Expr *node, List *exprs); +static EquivalenceMember *add_child_eq_member(PlannerInfo *root, + EquivalenceClass *ec, + int ec_index, Expr *expr, + Relids relids, + JoinDomain *jdomain, + EquivalenceMember *parent_em, + Oid datatype, + Index child_relid); static void generate_base_implied_equalities_const(PlannerInfo *root, EquivalenceClass *ec); static void generate_base_implied_equalities_no_const(PlannerInfo *root, @@ -73,7 +85,56 @@ static Bitmapset *get_eclass_indexes_for_relids(PlannerInfo *root, Relids relids); static Bitmapset *get_common_eclass_indexes(PlannerInfo *root, Relids relids1, Relids relids2); +static void ec_build_derives_hash(PlannerInfo *root, EquivalenceClass *ec); +static void ec_add_derived_clauses(EquivalenceClass *ec, List *clauses); +static void ec_add_derived_clause(EquivalenceClass *ec, RestrictInfo *clause); +static void ec_add_clause_to_derives_hash(EquivalenceClass *ec, RestrictInfo *rinfo); +static RestrictInfo *ec_search_clause_for_ems(PlannerInfo *root, EquivalenceClass *ec, + EquivalenceMember *leftem, + EquivalenceMember *rightem, + EquivalenceClass *parent_ec); +static RestrictInfo *ec_search_derived_clause_for_ems(PlannerInfo *root, + EquivalenceClass *ec, + EquivalenceMember *leftem, + EquivalenceMember *rightem, + EquivalenceClass *parent_ec); +/* + * Hash key identifying a derived clause. + * + * This structure should not be filled manually. Use fill_ec_derives_key() to + * set it up in canonical form. + */ +typedef struct +{ + EquivalenceMember *em1; + EquivalenceMember *em2; + EquivalenceClass *parent_ec; +} ECDerivesKey; + +/* Hash table entry in ec_derives_hash. */ +typedef struct +{ + uint32 status; + ECDerivesKey key; + RestrictInfo *rinfo; +} ECDerivesEntry; + +/* Threshold for switching from list to hash table */ +#define EC_DERIVES_HASH_THRESHOLD 32 + +#define SH_PREFIX derives +#define SH_ELEMENT_TYPE ECDerivesEntry +#define SH_KEY_TYPE ECDerivesKey +#define SH_KEY key +#define SH_HASH_KEY(tb, key) \ + hash_bytes((const unsigned char *) &(key), sizeof(ECDerivesKey)) +#define SH_EQUAL(tb, a, b) \ + ((a).em1 == (b).em1 && (a).em2 == (b).em2 && (a).parent_ec == (b).parent_ec) +#define SH_SCOPE static inline +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" /* * process_equivalence @@ -265,11 +326,15 @@ process_equivalence(PlannerInfo *root, if (!equal(opfamilies, cur_ec->ec_opfamilies)) continue; + /* We don't expect any children yet */ + Assert(cur_ec->ec_childmembers == NULL); + foreach(lc2, cur_ec->ec_members) { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); - Assert(!cur_em->em_is_child); /* no children yet */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * Match constants only within the same JoinDomain (see @@ -343,7 +408,12 @@ process_equivalence(PlannerInfo *root, */ ec1->ec_members = list_concat(ec1->ec_members, ec2->ec_members); ec1->ec_sources = list_concat(ec1->ec_sources, ec2->ec_sources); - ec1->ec_derives = list_concat(ec1->ec_derives, ec2->ec_derives); + + /* + * Appends ec2's derived clauses to ec1->ec_derives_list and adds them + * to ec1->ec_derives_hash if present. + */ + ec_add_derived_clauses(ec1, ec2->ec_derives_list); ec1->ec_relids = bms_join(ec1->ec_relids, ec2->ec_relids); ec1->ec_has_const |= ec2->ec_has_const; /* can't need to set has_volatile */ @@ -356,7 +426,7 @@ process_equivalence(PlannerInfo *root, /* just to avoid debugging confusion w/ dangling pointers: */ ec2->ec_members = NIL; ec2->ec_sources = NIL; - ec2->ec_derives = NIL; + ec_clear_derived_clauses(ec2); ec2->ec_relids = NULL; ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo); ec1->ec_min_security = Min(ec1->ec_min_security, @@ -374,7 +444,7 @@ process_equivalence(PlannerInfo *root, { /* Case 3: add item2 to ec1 */ em2 = add_eq_member(ec1, item2, item2_relids, - jdomain, NULL, item2_type); + jdomain, item2_type); ec1->ec_sources = lappend(ec1->ec_sources, restrictinfo); ec1->ec_min_security = Min(ec1->ec_min_security, restrictinfo->security_level); @@ -391,7 +461,7 @@ process_equivalence(PlannerInfo *root, { /* Case 3: add item1 to ec2 */ em1 = add_eq_member(ec2, item1, item1_relids, - jdomain, NULL, item1_type); + jdomain, item1_type); ec2->ec_sources = lappend(ec2->ec_sources, restrictinfo); ec2->ec_min_security = Min(ec2->ec_min_security, restrictinfo->security_level); @@ -411,9 +481,12 @@ process_equivalence(PlannerInfo *root, ec->ec_opfamilies = opfamilies; ec->ec_collation = collation; + ec->ec_childmembers_size = 0; ec->ec_members = NIL; + ec->ec_childmembers = NULL; ec->ec_sources = list_make1(restrictinfo); - ec->ec_derives = NIL; + ec->ec_derives_list = NIL; + ec->ec_derives_hash = NULL; ec->ec_relids = NULL; ec->ec_has_const = false; ec->ec_has_volatile = false; @@ -423,9 +496,9 @@ process_equivalence(PlannerInfo *root, ec->ec_max_security = restrictinfo->security_level; ec->ec_merged = NULL; em1 = add_eq_member(ec, item1, item1_relids, - jdomain, NULL, item1_type); + jdomain, item1_type); em2 = add_eq_member(ec, item2, item2_relids, - jdomain, NULL, item2_type); + jdomain, item2_type); root->eq_classes = lappend(root->eq_classes, ec); @@ -511,11 +584,13 @@ canonicalize_ec_expression(Expr *expr, Oid req_type, Oid req_collation) } /* - * add_eq_member - build a new EquivalenceMember and add it to an EC + * make_eq_member + * Build a new EquivalenceMember without adding it to an EC. If 'parent' + * is NULL, the result will be a parent member, otherwise a child member. */ static EquivalenceMember * -add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, - JoinDomain *jdomain, EquivalenceMember *parent, Oid datatype) +make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, + JoinDomain *jdomain, EquivalenceMember *parent, Oid datatype) { EquivalenceMember *em = makeNode(EquivalenceMember); @@ -542,11 +617,85 @@ add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, ec->ec_has_const = true; /* it can't affect ec_relids */ } - else if (!parent) /* child members don't add to ec_relids */ + + return em; +} + +/* + * add_eq_member - build a new non-child EquivalenceMember and add it to 'ec'. + */ +static EquivalenceMember * +add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, + JoinDomain *jdomain, Oid datatype) +{ + EquivalenceMember *em = make_eq_member(ec, expr, relids, jdomain, + NULL, datatype); + + /* add to the members list */ + ec->ec_members = lappend(ec->ec_members, em); + + /* record the relids for parent members */ + ec->ec_relids = bms_add_members(ec->ec_relids, relids); + + return em; +} + +/* + * add_child_eq_member + * Create an em_is_child=true EquivalenceMember and add it to 'ec'. + * + * 'root' is the PlannerInfo that 'ec' belongs to. + * 'ec' is the EquivalenceClass to add the child member to. + * 'ec_index' the index of 'ec' within root->eq_classes, or -1 if maintaining + * the RelOptInfo.eclass_indexes isn't needed. + * 'expr' is the em_expr for the new member. + * 'relids' is the 'em_relids' for the new member. + * 'jdomain' is the 'em_jdomain' for the new member. + * 'parent_em' is the parent member of the child to create. + * 'datatype' is the em_datatype of the new member. + * 'child_relid' defines which element of ec_childmembers to add this member + * to. This is generally a RELOPT_OTHER_MEMBER_REL, but for set operations + * can be a RELOPT_BASEREL representing the set-op children. + */ +static EquivalenceMember * +add_child_eq_member(PlannerInfo *root, EquivalenceClass *ec, int ec_index, + Expr *expr, Relids relids, JoinDomain *jdomain, + EquivalenceMember *parent_em, Oid datatype, + Index child_relid) +{ + EquivalenceMember *em; + + Assert(parent_em != NULL); + + /* + * Allocate the array to store child members; an array of Lists indexed by + * relid, or expand the existing one, if necessary. + */ + if (unlikely(ec->ec_childmembers_size < root->simple_rel_array_size)) { - ec->ec_relids = bms_add_members(ec->ec_relids, relids); + if (ec->ec_childmembers == NULL) + ec->ec_childmembers = palloc0_array(List *, root->simple_rel_array_size); + else + ec->ec_childmembers = repalloc0_array(ec->ec_childmembers, List *, + ec->ec_childmembers_size, + root->simple_rel_array_size); + + ec->ec_childmembers_size = root->simple_rel_array_size; + } + + em = make_eq_member(ec, expr, relids, jdomain, parent_em, datatype); + + /* add member to the ec_childmembers List for the given child_relid */ + ec->ec_childmembers[child_relid] = lappend(ec->ec_childmembers[child_relid], em); + + /* Record this EC index for the child rel */ + if (ec_index >= 0) + { + RelOptInfo *child_rel = root->simple_rel_array[child_relid]; + + child_rel->eclass_indexes = + bms_add_member(child_rel->eclass_indexes, ec_index); } - ec->ec_members = lappend(ec->ec_members, em); return em; } @@ -617,7 +766,8 @@ get_eclass_for_sort_expr(PlannerInfo *root, foreach(lc1, root->eq_classes) { EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1); - ListCell *lc2; + EquivalenceMemberIterator it; + EquivalenceMember *cur_em; /* * Never match to a volatile EC, except when we are looking at another @@ -632,10 +782,9 @@ get_eclass_for_sort_expr(PlannerInfo *root, if (!equal(opfamilies, cur_ec->ec_opfamilies)) continue; - foreach(lc2, cur_ec->ec_members) + setup_eclass_member_iterator(&it, cur_ec, rel); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); - /* * Ignore child members unless they match the request. */ @@ -670,9 +819,12 @@ get_eclass_for_sort_expr(PlannerInfo *root, newec = makeNode(EquivalenceClass); newec->ec_opfamilies = list_copy(opfamilies); newec->ec_collation = collation; + newec->ec_childmembers_size = 0; newec->ec_members = NIL; + newec->ec_childmembers = NULL; newec->ec_sources = NIL; - newec->ec_derives = NIL; + newec->ec_derives_list = NIL; + newec->ec_derives_hash = NULL; newec->ec_relids = NULL; newec->ec_has_const = false; newec->ec_has_volatile = contain_volatile_functions((Node *) expr); @@ -691,7 +843,7 @@ get_eclass_for_sort_expr(PlannerInfo *root, expr_relids = pull_varnos(root, (Node *) expr); newem = add_eq_member(newec, copyObject(expr), expr_relids, - jdomain, NULL, opcintype); + jdomain, opcintype); /* * add_eq_member doesn't check for volatile functions, set-returning @@ -726,6 +878,10 @@ get_eclass_for_sort_expr(PlannerInfo *root, { RelOptInfo *rel = root->simple_rel_array[i]; + /* ignore the RTE_GROUP RTE */ + if (i == root->group_rtindex) + continue; + if (rel == NULL) /* must be an outer join */ { Assert(bms_is_member(i, root->outer_join_rels)); @@ -761,15 +917,16 @@ find_ec_member_matching_expr(EquivalenceClass *ec, Expr *expr, Relids relids) { - ListCell *lc; + EquivalenceMemberIterator it; + EquivalenceMember *em; /* We ignore binary-compatible relabeling on both ends */ while (expr && IsA(expr, RelabelType)) expr = ((RelabelType *) expr)->arg; - foreach(lc, ec->ec_members) + setup_eclass_member_iterator(&it, ec, relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *em = (EquivalenceMember *) lfirst(lc); Expr *emexpr; /* @@ -806,9 +963,18 @@ find_ec_member_matching_expr(EquivalenceClass *ec, * expressions appearing in "exprs"; return NULL if no match. * * "exprs" can be either a list of bare expression trees, or a list of - * TargetEntry nodes. Either way, it should contain Vars and possibly - * Aggrefs and WindowFuncs, which are matched to the corresponding elements - * of the EquivalenceClass's expressions. + * TargetEntry nodes. Typically it will contain Vars and possibly Aggrefs + * and WindowFuncs; however, when considering an appendrel member the list + * could contain arbitrary expressions. We consider an EC member to be + * computable if all the Vars, PlaceHolderVars, Aggrefs, and WindowFuncs + * it needs are present in "exprs". + * + * There is some subtlety in that definition: for example, if an EC member is + * Var_A + 1 while what is in "exprs" is Var_A + 2, it's still computable. + * This works because in the final plan tree, the EC member's expression will + * be computed as part of the same plan node targetlist that is currently + * represented by "exprs". So if we have Var_A available for the existing + * tlist member, it must be OK to use it in the EC expression too. * * Unlike find_ec_member_matching_expr, there's no special provision here * for binary-compatible relabeling. This is intentional: if we have to @@ -828,12 +994,26 @@ find_computable_ec_member(PlannerInfo *root, Relids relids, bool require_parallel_safe) { - ListCell *lc; + List *exprvars; + EquivalenceMemberIterator it; + EquivalenceMember *em; - foreach(lc, ec->ec_members) + /* + * Pull out the Vars and quasi-Vars present in "exprs". In the typical + * non-appendrel case, this is just another representation of the same + * list. However, it does remove the distinction between the case of a + * list of plain expressions and a list of TargetEntrys. + */ + exprvars = pull_var_clause((Node *) exprs, + PVC_INCLUDE_AGGREGATES | + PVC_INCLUDE_WINDOWFUNCS | + PVC_INCLUDE_PLACEHOLDERS | + PVC_INCLUDE_CONVERTROWTYPES); + + setup_eclass_member_iterator(&it, ec, relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *em = (EquivalenceMember *) lfirst(lc); - List *exprvars; + List *emvars; ListCell *lc2; /* @@ -851,18 +1031,18 @@ find_computable_ec_member(PlannerInfo *root, continue; /* - * Match if all Vars and quasi-Vars are available in "exprs". + * Match if all Vars and quasi-Vars are present in "exprs". */ - exprvars = pull_var_clause((Node *) em->em_expr, - PVC_INCLUDE_AGGREGATES | - PVC_INCLUDE_WINDOWFUNCS | - PVC_INCLUDE_PLACEHOLDERS); - foreach(lc2, exprvars) + emvars = pull_var_clause((Node *) em->em_expr, + PVC_INCLUDE_AGGREGATES | + PVC_INCLUDE_WINDOWFUNCS | + PVC_INCLUDE_PLACEHOLDERS); + foreach(lc2, emvars) { - if (!is_exprlist_member(lfirst(lc2), exprs)) + if (!list_member(exprvars, lfirst(lc2))) break; } - list_free(exprvars); + list_free(emvars); if (lc2) continue; /* we hit a non-available Var */ @@ -880,31 +1060,6 @@ find_computable_ec_member(PlannerInfo *root, return NULL; } -/* - * is_exprlist_member - * Subroutine for find_computable_ec_member: is "node" in "exprs"? - * - * Per the requirements of that function, "exprs" might or might not have - * TargetEntry superstructure. - */ -static bool -is_exprlist_member(Expr *node, List *exprs) -{ - ListCell *lc; - - foreach(lc, exprs) - { - Expr *expr = (Expr *) lfirst(lc); - - if (expr && IsA(expr, TargetEntry)) - expr = ((TargetEntry *) expr)->expr; - - if (equal(node, expr)) - return true; - } - return false; -} - /* * relation_can_be_sorted_early * Can this relation be sorted on this EC before the final output step? @@ -1026,8 +1181,8 @@ relation_can_be_sorted_early(PlannerInfo *root, RelOptInfo *rel, * scanning of the quals and before Path construction begins. * * We make no attempt to avoid generating duplicate RestrictInfos here: we - * don't search ec_sources or ec_derives for matches. It doesn't really - * seem worth the trouble to do so. + * don't search existing source or derived clauses in the EC for matches. It + * doesn't really seem worth the trouble to do so. */ void generate_base_implied_equalities(PlannerInfo *root) @@ -1087,6 +1242,10 @@ generate_base_implied_equalities(PlannerInfo *root) { RelOptInfo *rel = root->simple_rel_array[i]; + /* ignore the RTE_GROUP RTE */ + if (i == root->group_rtindex) + continue; + if (rel == NULL) /* must be an outer join */ { Assert(bms_is_member(i, root->outer_join_rels)); @@ -1132,6 +1291,9 @@ generate_base_implied_equalities_const(PlannerInfo *root, return; } + /* We don't expect any children yet */ + Assert(ec->ec_childmembers == NULL); + /* * Find the constant member to use. We prefer an actual constant to * pseudo-constants (such as Params), because the constraint exclusion @@ -1158,7 +1320,8 @@ generate_base_implied_equalities_const(PlannerInfo *root, Oid eq_op; RestrictInfo *rinfo; - Assert(!cur_em->em_is_child); /* no children yet */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); if (cur_em == const_em) continue; eq_op = select_equality_operator(ec, @@ -1184,11 +1347,11 @@ generate_base_implied_equalities_const(PlannerInfo *root, /* * If the clause didn't degenerate to a constant, fill in the correct - * markings for a mergejoinable clause, and save it in ec_derives. (We - * will not re-use such clauses directly, but selectivity estimation - * may consult the list later. Note that this use of ec_derives does - * not overlap with its use for join clauses, since we never generate - * join clauses from an ec_has_const eclass.) + * markings for a mergejoinable clause, and save it as a derived + * clause. (We will not re-use such clauses directly, but selectivity + * estimation may consult those later. Note that this use of derived + * clauses does not overlap with its use for join clauses, since we + * never generate join clauses from an ec_has_const eclass.) */ if (rinfo && rinfo->mergeopfamilies) { @@ -1196,7 +1359,7 @@ generate_base_implied_equalities_const(PlannerInfo *root, rinfo->left_ec = rinfo->right_ec = ec; rinfo->left_em = cur_em; rinfo->right_em = const_em; - ec->ec_derives = lappend(ec->ec_derives, rinfo); + ec_add_derived_clause(ec, rinfo); } } } @@ -1222,12 +1385,17 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, prev_ems = (EquivalenceMember **) palloc0(root->simple_rel_array_size * sizeof(EquivalenceMember *)); + /* We don't expect any children yet */ + Assert(ec->ec_childmembers == NULL); + foreach(lc, ec->ec_members) { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc); int relid; - Assert(!cur_em->em_is_child); /* no children yet */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); + if (!bms_get_singleton_member(cur_em->em_relids, &relid)) continue; Assert(relid < root->simple_rel_array_size); @@ -1261,10 +1429,10 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, /* * If the clause didn't degenerate to a constant, fill in the - * correct markings for a mergejoinable clause. We don't put it - * in ec_derives however; we don't currently need to re-find such - * clauses, and we don't want to clutter that list with non-join - * clauses. + * correct markings for a mergejoinable clause. We don't record + * it as a derived clause, since we don't currently need to + * re-find such clauses, and don't want to clutter the + * derived-clause set with non-join clauses. */ if (rinfo && rinfo->mergeopfamilies) { @@ -1285,7 +1453,8 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, * For the moment we force all the Vars to be available at all join nodes * for this eclass. Perhaps this could be improved by doing some * pre-analysis of which members we prefer to join, but it's no worse than - * what happened in the pre-8.3 code. + * what happened in the pre-8.3 code. (Note: rebuild_eclass_attr_needed + * needs to match this code.) */ foreach(lc, ec->ec_members) { @@ -1364,7 +1533,7 @@ generate_base_implied_equalities_broken(PlannerInfo *root, * we consider different join paths, we avoid generating multiple copies: * whenever we select a particular pair of EquivalenceMembers to join, * we check to see if the pair matches any original clause (in ec_sources) - * or previously-built clause (in ec_derives). This saves memory and allows + * or previously-built derived clause. This saves memory and allows * re-use of information cached in RestrictInfos. We also avoid generating * commutative duplicates, i.e. if the algorithm selects "a.x = b.y" but * we already have "b.y = a.x", we return the existing clause. @@ -1559,7 +1728,8 @@ generate_join_implied_equalities_normal(PlannerInfo *root, List *new_members = NIL; List *outer_members = NIL; List *inner_members = NIL; - ListCell *lc1; + EquivalenceMemberIterator it; + EquivalenceMember *cur_em; /* * First, scan the EC to identify member values that are computable at the @@ -1570,10 +1740,9 @@ generate_join_implied_equalities_normal(PlannerInfo *root, * as well as to at least one input member, plus enforce at least one * outer-rel member equal to at least one inner-rel member. */ - foreach(lc1, ec->ec_members) + setup_eclass_member_iterator(&it, ec, join_relids); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc1); - /* * We don't need to check explicitly for child EC members. This test * against join_relids will cause them to be ignored except when @@ -1606,6 +1775,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root, Oid best_eq_op = InvalidOid; int best_score = -1; RestrictInfo *rinfo; + ListCell *lc1; foreach(lc1, outer_members) { @@ -1680,6 +1850,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root, List *old_members = list_concat(outer_members, inner_members); EquivalenceMember *prev_em = NULL; RestrictInfo *rinfo; + ListCell *lc1; /* For now, arbitrarily take the first old_member as the one to use */ if (old_members) @@ -1687,7 +1858,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root, foreach(lc1, new_members) { - EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc1); + cur_em = (EquivalenceMember *) lfirst(lc1); if (prev_em != NULL) { @@ -1749,9 +1920,9 @@ generate_join_implied_equalities_broken(PlannerInfo *root, /* * If we have to translate, just brute-force apply adjust_appendrel_attrs * to all the RestrictInfos at once. This will result in returning - * RestrictInfos that are not listed in ec_derives, but there shouldn't be - * any duplication, and it's a sufficiently narrow corner case that we - * shouldn't sweat too much over it anyway. + * RestrictInfos that are not included in EC's derived clauses, but there + * shouldn't be any duplication, and it's a sufficiently narrow corner + * case that we shouldn't sweat too much over it anyway. * * Since inner_rel might be an indirect descendant of the baserel * mentioned in the ec_sources clauses, we have to be prepared to apply @@ -1783,8 +1954,7 @@ select_equality_operator(EquivalenceClass *ec, Oid lefttype, Oid righttype) Oid opfamily = lfirst_oid(lc); Oid opno; - opno = get_opfamily_member(opfamily, lefttype, righttype, - BTEqualStrategyNumber); + opno = get_opfamily_member_for_cmptype(opfamily, lefttype, righttype, COMPARE_EQ); if (!OidIsValid(opno)) continue; /* If no barrier quals in query, don't worry about leaky operators */ @@ -1818,43 +1988,11 @@ create_join_clause(PlannerInfo *root, { RestrictInfo *rinfo; RestrictInfo *parent_rinfo = NULL; - ListCell *lc; MemoryContext oldcontext; - /* - * Search to see if we already built a RestrictInfo for this pair of - * EquivalenceMembers. We can use either original source clauses or - * previously-derived clauses, and a commutator clause is acceptable. - * - * We used to verify that opno matches, but that seems redundant: even if - * it's not identical, it'd better have the same effects, or the operator - * families we're using are broken. - */ - foreach(lc, ec->ec_sources) - { - rinfo = (RestrictInfo *) lfirst(lc); - if (rinfo->left_em == leftem && - rinfo->right_em == rightem && - rinfo->parent_ec == parent_ec) - return rinfo; - if (rinfo->left_em == rightem && - rinfo->right_em == leftem && - rinfo->parent_ec == parent_ec) - return rinfo; - } - - foreach(lc, ec->ec_derives) - { - rinfo = (RestrictInfo *) lfirst(lc); - if (rinfo->left_em == leftem && - rinfo->right_em == rightem && - rinfo->parent_ec == parent_ec) - return rinfo; - if (rinfo->left_em == rightem && - rinfo->right_em == leftem && - rinfo->parent_ec == parent_ec) - return rinfo; - } + rinfo = ec_search_clause_for_ems(root, ec, leftem, rightem, parent_ec); + if (rinfo) + return rinfo; /* * Not there, so build it, in planner context so we can re-use it. (Not @@ -1918,7 +2056,7 @@ create_join_clause(PlannerInfo *root, rinfo->left_em = leftem; rinfo->right_em = rightem; /* and save it for possible re-use */ - ec->ec_derives = lappend(ec->ec_derives, rinfo); + ec_add_derived_clause(ec, rinfo); MemoryContextSwitchTo(oldcontext); @@ -2159,6 +2297,9 @@ reconsider_outer_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo, bool match; ListCell *lc2; + /* We don't expect any children yet */ + Assert(cur_ec->ec_childmembers == NULL); + /* Ignore EC unless it contains pseudoconstants */ if (!cur_ec->ec_has_const) continue; @@ -2176,7 +2317,8 @@ reconsider_outer_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo, { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); - Assert(!cur_em->em_is_child); /* no children yet */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); if (equal(outervar, cur_em->em_expr)) { match = true; @@ -2274,6 +2416,9 @@ reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo) ListCell *lc2; int coal_idx = -1; + /* We don't expect any children yet */ + Assert(cur_ec->ec_childmembers == NULL); + /* Ignore EC unless it contains pseudoconstants */ if (!cur_ec->ec_has_const) continue; @@ -2303,7 +2448,9 @@ reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo) foreach(lc2, cur_ec->ec_members) { coal_em = (EquivalenceMember *) lfirst(lc2); - Assert(!coal_em->em_is_child); /* no children yet */ + + /* Child members should not exist in ec_members */ + Assert(!coal_em->em_is_child); if (IsA(coal_em->em_expr, CoalesceExpr)) { CoalesceExpr *cexpr = (CoalesceExpr *) coal_em->em_expr; @@ -2414,6 +2561,51 @@ reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo) return false; /* failed to make any deduction */ } +/* + * rebuild_eclass_attr_needed + * Put back attr_needed bits for Vars/PHVs needed for join eclasses. + * + * This is used to rebuild attr_needed/ph_needed sets after removal of a + * useless outer join. It should match what + * generate_base_implied_equalities_no_const did, except that we call + * add_vars_to_attr_needed not add_vars_to_targetlist. + */ +void +rebuild_eclass_attr_needed(PlannerInfo *root) +{ + ListCell *lc; + + foreach(lc, root->eq_classes) + { + EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc); + + /* + * We don't expect any EC child members to exist at this point. Ensure + * that's the case, otherwise, we might be getting asked to do + * something this function hasn't been coded for. + */ + Assert(ec->ec_childmembers == NULL); + + /* Need do anything only for a multi-member, no-const EC. */ + if (list_length(ec->ec_members) > 1 && !ec->ec_has_const) + { + ListCell *lc2; + + foreach(lc2, ec->ec_members) + { + EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); + List *vars = pull_var_clause((Node *) cur_em->em_expr, + PVC_RECURSE_AGGREGATES | + PVC_RECURSE_WINDOWFUNCS | + PVC_INCLUDE_PLACEHOLDERS); + + add_vars_to_attr_needed(root, vars, ec->ec_relids); + list_free(vars); + } + } + } +} + /* * find_join_domain * Find the highest JoinDomain enclosed within the given relid set. @@ -2443,15 +2635,17 @@ find_join_domain(PlannerInfo *root, Relids relids) * Detect whether two expressions are known equal due to equivalence * relationships. * - * Actually, this only shows that the expressions are equal according - * to some opfamily's notion of equality --- but we only use it for - * selectivity estimation, so a fuzzy idea of equality is OK. + * If opfamily is given, the expressions must be known equal per the semantics + * of that opfamily (note it has to be a btree opfamily, since those are the + * only opfamilies equivclass.c deals with). If opfamily is InvalidOid, we'll + * return true if they're equal according to any opfamily, which is fuzzy but + * OK for estimation purposes. * * Note: does not bother to check for "equal(item1, item2)"; caller must * check that case if it's possible to pass identical items. */ bool -exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2) +exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily) { ListCell *lc1; @@ -2466,12 +2660,24 @@ exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2) if (ec->ec_has_volatile) continue; + /* + * It's okay to consider ec_broken ECs here. Brokenness just means we + * couldn't derive all the implied clauses we'd have liked to; it does + * not invalidate our knowledge that the members are equal. + */ + + /* Ignore if this EC doesn't use specified opfamily */ + if (OidIsValid(opfamily) && + !list_member_oid(ec->ec_opfamilies, opfamily)) + continue; + + /* Ignore children here */ foreach(lc2, ec->ec_members) { EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); - if (em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!em->em_is_child); if (equal(item1, em->em_expr)) item1member = true; else if (equal(item2, em->em_expr)) @@ -2494,8 +2700,7 @@ exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2) * (In principle there might be more than one matching eclass if multiple * collations are involved, but since collation doesn't matter for equality, * we ignore that fine point here.) This is much like exprs_known_equal, - * except that we insist on the comparison operator matching the eclass, so - * that the result is definite not approximate. + * except for the format of the input. * * On success, we also set fkinfo->eclass[colno] to the matching eclass, * and set fkinfo->fk_eclass_member[colno] to the eclass member for the @@ -2536,15 +2741,18 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root, /* Never match to a volatile EC */ if (ec->ec_has_volatile) continue; - /* Note: it seems okay to match to "broken" eclasses here */ + /* + * It's okay to consider "broken" ECs here, see exprs_known_equal. + * Ignore children here. + */ foreach(lc2, ec->ec_members) { EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); Var *var; - if (em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!em->em_is_child); /* EM must be a Var, possibly with RelabelType */ var = (Var *) em->em_expr; @@ -2593,25 +2801,14 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root, * Returns NULL if no such clause can be found. */ RestrictInfo * -find_derived_clause_for_ec_member(EquivalenceClass *ec, +find_derived_clause_for_ec_member(PlannerInfo *root, + EquivalenceClass *ec, EquivalenceMember *em) { - ListCell *lc; - Assert(ec->ec_has_const); Assert(!em->em_is_const); - foreach(lc, ec->ec_derives) - { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); - /* - * generate_base_implied_equalities_const will have put non-const - * members on the left side of derived clauses. - */ - if (rinfo->left_em == em) - return rinfo; - } - return NULL; + return ec_search_derived_clause_for_ems(root, ec, em, NULL, NULL); } @@ -2653,7 +2850,6 @@ add_child_rel_equivalences(PlannerInfo *root, while ((i = bms_next_member(parent_rel->eclass_indexes, i)) >= 0) { EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); - int num_members; /* * If this EC contains a volatile expression, then generating child @@ -2666,29 +2862,13 @@ add_child_rel_equivalences(PlannerInfo *root, /* Sanity check eclass_indexes only contain ECs for parent_rel */ Assert(bms_is_subset(top_parent_relids, cur_ec->ec_relids)); - /* - * We don't use foreach() here because there's no point in scanning - * newly-added child members, so we can stop after the last - * pre-existing EC member. - */ - num_members = list_length(cur_ec->ec_members); - for (int pos = 0; pos < num_members; pos++) + foreach_node(EquivalenceMember, cur_em, cur_ec->ec_members) { - EquivalenceMember *cur_em = (EquivalenceMember *) list_nth(cur_ec->ec_members, pos); - if (cur_em->em_is_const) continue; /* ignore consts here */ - /* - * We consider only original EC members here, not - * already-transformed child members. Otherwise, if some original - * member expression references more than one appendrel, we'd get - * an O(N^2) explosion of useless derived expressions for - * combinations of children. (But add_child_join_rel_equivalences - * may add targeted combinations for partitionwise-join purposes.) - */ - if (cur_em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * Consider only members that reference and can be computed at @@ -2733,12 +2913,15 @@ add_child_rel_equivalences(PlannerInfo *root, top_parent_relids); new_relids = bms_add_members(new_relids, child_relids); - (void) add_eq_member(cur_ec, child_expr, new_relids, - cur_em->em_jdomain, - cur_em, cur_em->em_datatype); - - /* Record this EC index for the child rel */ - child_rel->eclass_indexes = bms_add_member(child_rel->eclass_indexes, i); + add_child_eq_member(root, + cur_ec, + i, + child_expr, + new_relids, + cur_em->em_jdomain, + cur_em, + cur_em->em_datatype, + child_rel->relid); } } } @@ -2785,7 +2968,6 @@ add_child_join_rel_equivalences(PlannerInfo *root, while ((i = bms_next_member(matching_ecs, i)) >= 0) { EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); - int num_members; /* * If this EC contains a volatile expression, then generating child @@ -2798,25 +2980,13 @@ add_child_join_rel_equivalences(PlannerInfo *root, /* Sanity check on get_eclass_indexes_for_relids result */ Assert(bms_overlap(top_parent_relids, cur_ec->ec_relids)); - /* - * We don't use foreach() here because there's no point in scanning - * newly-added child members, so we can stop after the last - * pre-existing EC member. - */ - num_members = list_length(cur_ec->ec_members); - for (int pos = 0; pos < num_members; pos++) + foreach_node(EquivalenceMember, cur_em, cur_ec->ec_members) { - EquivalenceMember *cur_em = (EquivalenceMember *) list_nth(cur_ec->ec_members, pos); - if (cur_em->em_is_const) continue; /* ignore consts here */ - /* - * We consider only original EC members here, not - * already-transformed child members. - */ - if (cur_em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * We may ignore expressions that reference a single baserel, @@ -2861,9 +3031,35 @@ add_child_join_rel_equivalences(PlannerInfo *root, top_parent_relids); new_relids = bms_add_members(new_relids, child_relids); - (void) add_eq_member(cur_ec, child_expr, new_relids, - cur_em->em_jdomain, - cur_em, cur_em->em_datatype); + /* + * Add new child member to the EquivalenceClass. Because this + * is a RELOPT_OTHER_JOINREL which has multiple component + * relids, there is no ideal place to store these members in + * the class. Ordinarily, child members are stored in the + * ec_childmembers[] array element corresponding to their + * relid, however, here we have multiple component relids, so + * there's no single ec_childmembers[] array element to store + * this member. So that we still correctly find this member + * in loops iterating over an EquivalenceMemberIterator, we + * opt to store the member in the ec_childmembers array in + * only the first component relid slot of the array. This + * allows the member to be found, providing callers of + * setup_eclass_member_iterator() specify all the component + * relids for the RELOPT_OTHER_JOINREL, which they do. If we + * opted to store the member in each ec_childmembers[] element + * for all the component relids, then that would just result + * in eclass_member_iterator_next() finding the member + * multiple times, which is a waste of effort. + */ + add_child_eq_member(root, + cur_ec, + -1, + child_expr, + new_relids, + cur_em->em_jdomain, + cur_em, + cur_em->em_datatype, + bms_next_member(child_joinrel->relids, -1)); } } } @@ -2910,14 +3106,18 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, * We can safely pass the parent member as the first member in the * ec_members list as this is added first in generate_union_paths, * likewise, the JoinDomain can be that of the initial member of the - * Pathkey's EquivalenceClass. + * Pathkey's EquivalenceClass. We pass -1 for ec_index since we + * maintain the eclass_indexes for the child_rel after the loop. */ - add_eq_member(pk->pk_eclass, - tle->expr, - child_rel->relids, - parent_em->em_jdomain, - parent_em, - exprType((Node *) tle->expr)); + add_child_eq_member(root, + pk->pk_eclass, + -1, + tle->expr, + child_rel->relids, + parent_em->em_jdomain, + parent_em, + exprType((Node *) tle->expr), + child_rel->relid); lc2 = lnext(setop_pathkeys, lc2); } @@ -2932,6 +3132,85 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, list_length(root->eq_classes) - 1); } +/* + * setup_eclass_member_iterator + * Setup an EquivalenceMemberIterator 'it' to iterate over all parent + * EquivalenceMembers and child members belonging to the given 'ec'. + * + * This iterator returns: + * - All parent members stored directly in ec_members for 'ec', and; + * - Any child member added to the given ec by add_child_eq_member() where + * the child_relid specified in the add_child_eq_member() call is a member + * of the 'child_relids' parameter. + * + * Note: + * The given 'child_relids' must remain allocated and not be changed for the + * lifetime of the iterator. + * + * Parameters: + * 'it' is a pointer to the iterator to set up. Normally stack allocated. + * 'ec' is the EquivalenceClass from which to iterate members for. + * 'child_relids' is the relids to return child members for. + */ +void +setup_eclass_member_iterator(EquivalenceMemberIterator *it, + EquivalenceClass *ec, Relids child_relids) +{ + it->ec = ec; + /* no need to set this if the class has no child members array set */ + it->child_relids = ec->ec_childmembers != NULL ? child_relids : NULL; + it->current_relid = -1; + it->current_list = ec->ec_members; + it->current_cell = list_head(it->current_list); +} + +/* + * eclass_member_iterator_next + * Get the next EquivalenceMember from the EquivalenceMemberIterator 'it', + * as setup by setup_eclass_member_iterator(). NULL is returned if there + * are no members left, after which callers must not call + * eclass_member_iterator_next() again for the given iterator. + */ +EquivalenceMember * +eclass_member_iterator_next(EquivalenceMemberIterator *it) +{ + while (it->current_list != NULL) + { + while (it->current_cell != NULL) + { + EquivalenceMember *em; + + nextcell: + em = lfirst_node(EquivalenceMember, it->current_cell); + it->current_cell = lnext(it->current_list, it->current_cell); + return em; + } + + /* Search for the next list to return members from */ + while ((it->current_relid = bms_next_member(it->child_relids, it->current_relid)) > 0) + { + /* + * Be paranoid in case we're given relids above what we've sized + * the ec_childmembers array to. + */ + if (it->current_relid >= it->ec->ec_childmembers_size) + return NULL; + + it->current_list = it->ec->ec_childmembers[it->current_relid]; + + /* If there are members in this list, use it. */ + if (it->current_list != NIL) + { + /* point current_cell to the head of this list */ + it->current_cell = list_head(it->current_list); + goto nextcell; + } + } + return NULL; + } + + return NULL; +} /* * generate_implied_equalities_for_column @@ -2984,6 +3263,7 @@ generate_implied_equalities_for_column(PlannerInfo *root, while ((i = bms_next_member(rel->eclass_indexes, i)) >= 0) { EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); + EquivalenceMemberIterator it; EquivalenceMember *cur_em; ListCell *lc2; @@ -3007,14 +3287,12 @@ generate_implied_equalities_for_column(PlannerInfo *root, * corner cases, so for now we live with just reporting the first * match. See also get_eclass_for_sort_expr.) */ - cur_em = NULL; - foreach(lc2, cur_ec->ec_members) + setup_eclass_member_iterator(&it, cur_ec, rel->relids); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { - cur_em = (EquivalenceMember *) lfirst(lc2); if (bms_equal(cur_em->em_relids, rel->relids) && callback(root, rel, cur_ec, cur_em, callback_arg)) break; - cur_em = NULL; } if (!cur_em) @@ -3022,7 +3300,7 @@ generate_implied_equalities_for_column(PlannerInfo *root, /* * Found our match. Scan the other EC members and attempt to generate - * joinclauses. + * joinclauses. Ignore children here. */ foreach(lc2, cur_ec->ec_members) { @@ -3030,8 +3308,8 @@ generate_implied_equalities_for_column(PlannerInfo *root, Oid eq_op; RestrictInfo *rinfo; - if (other_em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!other_em->em_is_child); /* Make sure it'll be a join to a different rel */ if (other_em == cur_em || @@ -3244,13 +3522,15 @@ eclass_useful_for_merging(PlannerInfo *root, if (bms_is_subset(eclass->ec_relids, relids)) return false; - /* To join, we need a member not in the given rel */ + /* + * To join, we need a member not in the given rel. Ignore children here. + */ foreach(lc, eclass->ec_members) { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc); - if (cur_em->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); if (!bms_overlap(cur_em->em_relids, relids)) return true; @@ -3342,6 +3622,10 @@ get_eclass_indexes_for_relids(PlannerInfo *root, Relids relids) { RelOptInfo *rel = root->simple_rel_array[i]; + /* ignore the RTE_GROUP RTE */ + if (i == root->group_rtindex) + continue; + if (rel == NULL) /* must be an outer join */ { Assert(bms_is_member(i, root->outer_join_rels)); @@ -3380,3 +3664,281 @@ get_common_eclass_indexes(PlannerInfo *root, Relids relids1, Relids relids2) /* Calculate and return the common EC indexes, recycling the left input. */ return bms_int_members(rel1ecs, rel2ecs); } + +/* + * ec_build_derives_hash + * Construct the auxiliary hash table for derived clause lookups. + */ +static void +ec_build_derives_hash(PlannerInfo *root, EquivalenceClass *ec) +{ + Assert(!ec->ec_derives_hash); + + /* + * Create the hash table. + * + * We pass list_length(ec->ec_derives_list) as the initial size. + * Simplehash will divide this by the fillfactor (typically 0.9) and round + * up to the next power of two, so this will usually give us at least 64 + * buckets around the threshold. That avoids immediate resizing without + * hardcoding a specific size. + */ + ec->ec_derives_hash = derives_create(root->planner_cxt, + list_length(ec->ec_derives_list), + NULL); + + foreach_node(RestrictInfo, rinfo, ec->ec_derives_list) + ec_add_clause_to_derives_hash(ec, rinfo); +} + +/* + * ec_add_derived_clause + * Add a clause to the set of derived clauses for the given + * EquivalenceClass. Always appends to ec_derives_list; also adds + * to ec_derives_hash if it exists. + * + * Also asserts expected invariants of derived clauses. + */ +static void +ec_add_derived_clause(EquivalenceClass *ec, RestrictInfo *clause) +{ + /* + * Constant, if present, is always placed on the RHS; see + * generate_base_implied_equalities_const(). LHS is never a constant. + */ + Assert(!clause->left_em->em_is_const); + + /* + * Clauses containing a constant are never considered redundant, so + * parent_ec is not set. + */ + Assert(!clause->parent_ec || !clause->right_em->em_is_const); + + ec->ec_derives_list = lappend(ec->ec_derives_list, clause); + if (ec->ec_derives_hash) + ec_add_clause_to_derives_hash(ec, clause); +} + +/* + * ec_add_derived_clauses + * Add a list of clauses to the set of clauses derived from the given + * EquivalenceClass; adding to the list and hash table if needed. + * + * This function is similar to ec_add_derived_clause() but optimized for adding + * multiple clauses at a time to the ec_derives_list. The assertions from + * ec_add_derived_clause() are not repeated here, as the input clauses are + * assumed to have already been validated. + */ +static void +ec_add_derived_clauses(EquivalenceClass *ec, List *clauses) +{ + ec->ec_derives_list = list_concat(ec->ec_derives_list, clauses); + if (ec->ec_derives_hash) + foreach_node(RestrictInfo, rinfo, clauses) + ec_add_clause_to_derives_hash(ec, rinfo); +} + +/* + * fill_ec_derives_key + * Compute a canonical key for ec_derives_hash lookup or insertion. + * + * Derived clauses are looked up using a pair of EquivalenceMembers and a + * parent EquivalenceClass. To avoid storing or searching for both EM orderings, + * we canonicalize the key: + * + * - For clauses involving two non-constant EMs, em1 is set to the EM with lower + * memory address and em2 is set to the other one. + * - For clauses involving a constant EM, the caller must pass the non-constant + * EM as leftem and NULL as rightem; we then set em1 = NULL and em2 = leftem. + */ +static inline void +fill_ec_derives_key(ECDerivesKey *key, + EquivalenceMember *leftem, + EquivalenceMember *rightem, + EquivalenceClass *parent_ec) +{ + Assert(leftem); /* Always required for lookup or insertion */ + + if (rightem == NULL) + { + key->em1 = NULL; + key->em2 = leftem; + } + else if (leftem < rightem) + { + key->em1 = leftem; + key->em2 = rightem; + } + else + { + key->em1 = rightem; + key->em2 = leftem; + } + key->parent_ec = parent_ec; +} + +/* + * ec_add_clause_to_derives_hash + * Add a derived clause to ec_derives_hash in the given EquivalenceClass. + * + * Each clause is associated with a canonicalized key. For constant-containing + * clauses, only the non-constant EM is used for lookup; see comments in + * fill_ec_derives_key(). + */ +static void +ec_add_clause_to_derives_hash(EquivalenceClass *ec, RestrictInfo *rinfo) +{ + ECDerivesKey key; + ECDerivesEntry *entry; + bool found; + + /* + * Constants are always placed on the RHS; see + * generate_base_implied_equalities_const(). + */ + Assert(!rinfo->left_em->em_is_const); + + /* + * Clauses containing a constant are never considered redundant, so + * parent_ec is not set. + */ + Assert(!rinfo->parent_ec || !rinfo->right_em->em_is_const); + + /* + * See fill_ec_derives_key() for details: we use a canonicalized key to + * avoid storing both EM orderings. For constant EMs, only the + * non-constant EM is included in the key. + */ + fill_ec_derives_key(&key, + rinfo->left_em, + rinfo->right_em->em_is_const ? NULL : rinfo->right_em, + rinfo->parent_ec); + entry = derives_insert(ec->ec_derives_hash, key, &found); + Assert(!found); + entry->rinfo = rinfo; +} + +/* + * ec_clear_derived_clauses + * Reset ec_derives_list and ec_derives_hash. + * + * We destroy the hash table explicitly, since it may consume significant + * space. The list holds the same set of entries and can become equally large + * when thousands of partitions are involved, so we free it as well -- even + * though we do not typically free lists. + */ +void +ec_clear_derived_clauses(EquivalenceClass *ec) +{ + list_free(ec->ec_derives_list); + ec->ec_derives_list = NIL; + + if (ec->ec_derives_hash) + { + derives_destroy(ec->ec_derives_hash); + ec->ec_derives_hash = NULL; + } +} + +/* + * ec_search_clause_for_ems + * Search for an existing RestrictInfo that equates the given pair + * of EquivalenceMembers, either from ec_sources or ec_derives. + * + * Returns a clause with matching operands in either given order or commuted + * order. We used to require matching operator OIDs, but dropped that since any + * semantically different operator here would indicate a broken operator family. + * + * Returns NULL if no matching clause is found. + */ +static RestrictInfo * +ec_search_clause_for_ems(PlannerInfo *root, EquivalenceClass *ec, + EquivalenceMember *leftem, EquivalenceMember *rightem, + EquivalenceClass *parent_ec) +{ + /* Check original source clauses */ + foreach_node(RestrictInfo, rinfo, ec->ec_sources) + { + if (rinfo->left_em == leftem && + rinfo->right_em == rightem && + rinfo->parent_ec == parent_ec) + return rinfo; + if (rinfo->left_em == rightem && + rinfo->right_em == leftem && + rinfo->parent_ec == parent_ec) + return rinfo; + } + + /* Not found in ec_sources; search derived clauses */ + return ec_search_derived_clause_for_ems(root, ec, leftem, rightem, + parent_ec); +} + +/* + * ec_search_derived_clause_for_ems + * Search for an existing derived clause between two EquivalenceMembers. + * + * If the number of derived clauses exceeds a threshold, switch to hash table + * lookup; otherwise, scan ec_derives_list linearly. + * + * Clauses involving constants are looked up by passing the non-constant EM + * as leftem and setting rightem to NULL. In that case, we expect to find a + * clause with a constant on the RHS. + * + * While searching the list, we compare each given EM with both sides of each + * clause. But for hash table lookups, we construct a canonicalized key and + * perform a single lookup. + */ +static RestrictInfo * +ec_search_derived_clause_for_ems(PlannerInfo *root, EquivalenceClass *ec, + EquivalenceMember *leftem, + EquivalenceMember *rightem, + EquivalenceClass *parent_ec) +{ + /* Switch to using hash lookup when list grows "too long". */ + if (!ec->ec_derives_hash && + list_length(ec->ec_derives_list) >= EC_DERIVES_HASH_THRESHOLD) + ec_build_derives_hash(root, ec); + + /* Perform hash table lookup if available */ + if (ec->ec_derives_hash) + { + ECDerivesKey key; + RestrictInfo *rinfo; + ECDerivesEntry *entry; + + fill_ec_derives_key(&key, leftem, rightem, parent_ec); + entry = derives_lookup(ec->ec_derives_hash, key); + if (entry) + { + rinfo = entry->rinfo; + Assert(rinfo); + Assert(rightem || rinfo->right_em->em_is_const); + return rinfo; + } + } + else + { + /* Fallback to linear search over ec_derives_list */ + foreach_node(RestrictInfo, rinfo, ec->ec_derives_list) + { + /* Handle special case: lookup by non-const EM alone */ + if (!rightem && + rinfo->left_em == leftem) + { + Assert(rinfo->right_em->em_is_const); + return rinfo; + } + if (rinfo->left_em == leftem && + rinfo->right_em == rightem && + rinfo->parent_ec == parent_ec) + return rinfo; + if (rinfo->left_em == rightem && + rinfo->right_em == leftem && + rinfo->parent_ec == parent_ec) + return rinfo; + } + } + + return NULL; +} diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index c0fcc7d78dfca..601354ea3e056 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -4,7 +4,7 @@ * Routines to determine which indexes are usable for scanning a * given relation, and create Paths accordingly. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -20,6 +20,7 @@ #include "access/stratnum.h" #include "access/sysattr.h" #include "catalog/pg_am.h" +#include "catalog/pg_amop.h" #include "catalog/pg_operator.h" #include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" @@ -177,6 +178,10 @@ static IndexClause *match_rowcompare_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index); +static IndexClause *match_orclause_to_indexcol(PlannerInfo *root, + RestrictInfo *rinfo, + int indexcol, + IndexOptInfo *index); static IndexClause *expand_indexqual_rowcompare(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, @@ -1166,6 +1171,449 @@ build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel, return result; } +/* + * Utility structure used to group similar OR-clause arguments in + * group_similar_or_args(). It represents information about the OR-clause + * argument and its matching index key. + */ +typedef struct +{ + int indexnum; /* index of the matching index, or -1 if no + * matching index */ + int colnum; /* index of the matching column, or -1 if no + * matching index */ + Oid opno; /* OID of the OpClause operator, or InvalidOid + * if not an OpExpr */ + Oid inputcollid; /* OID of the OpClause input collation */ + int argindex; /* index of the clause in the list of + * arguments */ + int groupindex; /* value of argindex for the fist clause in + * the group of similar clauses */ +} OrArgIndexMatch; + +/* + * Comparison function for OrArgIndexMatch which provides sort order placing + * similar OR-clause arguments together. + */ +static int +or_arg_index_match_cmp(const void *a, const void *b) +{ + const OrArgIndexMatch *match_a = (const OrArgIndexMatch *) a; + const OrArgIndexMatch *match_b = (const OrArgIndexMatch *) b; + + if (match_a->indexnum < match_b->indexnum) + return -1; + else if (match_a->indexnum > match_b->indexnum) + return 1; + + if (match_a->colnum < match_b->colnum) + return -1; + else if (match_a->colnum > match_b->colnum) + return 1; + + if (match_a->opno < match_b->opno) + return -1; + else if (match_a->opno > match_b->opno) + return 1; + + if (match_a->inputcollid < match_b->inputcollid) + return -1; + else if (match_a->inputcollid > match_b->inputcollid) + return 1; + + if (match_a->argindex < match_b->argindex) + return -1; + else if (match_a->argindex > match_b->argindex) + return 1; + + return 0; +} + +/* + * Another comparison function for OrArgIndexMatch. It sorts groups together + * using groupindex. The group items are then sorted by argindex. + */ +static int +or_arg_index_match_cmp_group(const void *a, const void *b) +{ + const OrArgIndexMatch *match_a = (const OrArgIndexMatch *) a; + const OrArgIndexMatch *match_b = (const OrArgIndexMatch *) b; + + if (match_a->groupindex < match_b->groupindex) + return -1; + else if (match_a->groupindex > match_b->groupindex) + return 1; + + if (match_a->argindex < match_b->argindex) + return -1; + else if (match_a->argindex > match_b->argindex) + return 1; + + return 0; +} + +/* + * group_similar_or_args + * Transform incoming OR-restrictinfo into a list of sub-restrictinfos, + * each of them containing a subset of similar OR-clause arguments from + * the source rinfo. + * + * Similar OR-clause arguments are of the form "indexkey op constant" having + * the same indexkey, operator, and collation. Constant may comprise either + * Const or Param. It may be employed later, during the + * match_clause_to_indexcol() to transform the whole OR-sub-rinfo to an SAOP + * clause. + * + * Returns the processed list of OR-clause arguments. + */ +static List * +group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo) +{ + int n; + int i; + int group_start; + OrArgIndexMatch *matches; + bool matched = false; + ListCell *lc; + ListCell *lc2; + List *orargs; + List *result = NIL; + Index relid = rel->relid; + + Assert(IsA(rinfo->orclause, BoolExpr)); + orargs = ((BoolExpr *) rinfo->orclause)->args; + n = list_length(orargs); + + /* + * To avoid N^2 behavior, take utility pass along the list of OR-clause + * arguments. For each argument, fill the OrArgIndexMatch structure, + * which will be used to sort these arguments at the next step. + */ + i = -1; + matches = (OrArgIndexMatch *) palloc(sizeof(OrArgIndexMatch) * n); + foreach(lc, orargs) + { + Node *arg = lfirst(lc); + RestrictInfo *argrinfo; + OpExpr *clause; + Oid opno; + Node *leftop, + *rightop; + Node *nonConstExpr; + int indexnum; + int colnum; + + i++; + matches[i].argindex = i; + matches[i].groupindex = i; + matches[i].indexnum = -1; + matches[i].colnum = -1; + matches[i].opno = InvalidOid; + matches[i].inputcollid = InvalidOid; + + if (!IsA(arg, RestrictInfo)) + continue; + + argrinfo = castNode(RestrictInfo, arg); + + /* Only operator clauses can match */ + if (!IsA(argrinfo->clause, OpExpr)) + continue; + + clause = (OpExpr *) argrinfo->clause; + opno = clause->opno; + + /* Only binary operators can match */ + if (list_length(clause->args) != 2) + continue; + + /* + * Ignore any RelabelType node above the operands. This is needed to + * be able to apply indexscanning in binary-compatible-operator cases. + * Note: we can assume there is at most one RelabelType node; + * eval_const_expressions() will have simplified if more than one. + */ + leftop = get_leftop(clause); + if (IsA(leftop, RelabelType)) + leftop = (Node *) ((RelabelType *) leftop)->arg; + + rightop = get_rightop(clause); + if (IsA(rightop, RelabelType)) + rightop = (Node *) ((RelabelType *) rightop)->arg; + + /* + * Check for clauses of the form: (indexkey operator constant) or + * (constant operator indexkey). But we don't know a particular index + * yet. Therefore, we try to distinguish the potential index key and + * constant first, then search for a matching index key among all + * indexes. + */ + if (bms_is_member(relid, argrinfo->right_relids) && + !bms_is_member(relid, argrinfo->left_relids) && + !contain_volatile_functions(leftop)) + { + opno = get_commutator(opno); + + if (!OidIsValid(opno)) + { + /* commutator doesn't exist, we can't reverse the order */ + continue; + } + nonConstExpr = rightop; + } + else if (bms_is_member(relid, argrinfo->left_relids) && + !bms_is_member(relid, argrinfo->right_relids) && + !contain_volatile_functions(rightop)) + { + nonConstExpr = leftop; + } + else + { + continue; + } + + /* + * Match non-constant part to the index key. It's possible that a + * single non-constant part matches multiple index keys. It's OK, we + * just stop with first matching index key. Given that this choice is + * determined the same for every clause, we will group similar clauses + * together anyway. + */ + indexnum = 0; + foreach(lc2, rel->indexlist) + { + IndexOptInfo *index = (IndexOptInfo *) lfirst(lc2); + + /* + * Ignore index if it doesn't support bitmap scans or SAOP + * clauses. + */ + if (!index->amhasgetbitmap || !index->amsearcharray) + continue; + + for (colnum = 0; colnum < index->nkeycolumns; colnum++) + { + if (match_index_to_operand(nonConstExpr, colnum, index)) + { + matches[i].indexnum = indexnum; + matches[i].colnum = colnum; + matches[i].opno = opno; + matches[i].inputcollid = clause->inputcollid; + matched = true; + break; + } + } + + /* + * Stop looping through the indexes, if we managed to match + * nonConstExpr to any index column. + */ + if (matches[i].indexnum >= 0) + break; + indexnum++; + } + } + + /* + * Fast-path check: if no clause is matching to the index column, we can + * just give up at this stage and return the clause list as-is. + */ + if (!matched) + { + pfree(matches); + return orargs; + } + + /* + * Sort clauses to make similar clauses go together. But at the same + * time, we would like to change the order of clauses as little as + * possible. To do so, we reorder each group of similar clauses so that + * the first item of the group stays in place, and all the other items are + * moved after it. So, if there are no similar clauses, the order of + * clauses stays the same. When there are some groups, required + * reordering happens while the rest of the clauses remain in their + * places. That is achieved by assigning a 'groupindex' to each clause: + * the number of the first item in the group in the original clause list. + */ + qsort(matches, n, sizeof(OrArgIndexMatch), or_arg_index_match_cmp); + + /* Assign groupindex to the sorted clauses */ + for (i = 1; i < n; i++) + { + /* + * When two clauses are similar and should belong to the same group, + * copy the 'groupindex' from the previous clause. Given we are + * considering clauses in direct order, all the clauses would have a + * 'groupindex' equal to the 'groupindex' of the first clause in the + * group. + */ + if (matches[i].indexnum == matches[i - 1].indexnum && + matches[i].colnum == matches[i - 1].colnum && + matches[i].opno == matches[i - 1].opno && + matches[i].inputcollid == matches[i - 1].inputcollid && + matches[i].indexnum != -1) + matches[i].groupindex = matches[i - 1].groupindex; + } + + /* Re-sort clauses first by groupindex then by argindex */ + qsort(matches, n, sizeof(OrArgIndexMatch), or_arg_index_match_cmp_group); + + /* + * Group similar clauses into single sub-restrictinfo. Side effect: the + * resulting list of restrictions will be sorted by indexnum and colnum. + */ + group_start = 0; + for (i = 1; i <= n; i++) + { + /* Check if it's a group boundary */ + if (group_start >= 0 && + (i == n || + matches[i].indexnum != matches[group_start].indexnum || + matches[i].colnum != matches[group_start].colnum || + matches[i].opno != matches[group_start].opno || + matches[i].inputcollid != matches[group_start].inputcollid || + matches[i].indexnum == -1)) + { + /* + * One clause in group: add it "as is" to the upper-level OR. + */ + if (i - group_start == 1) + { + result = lappend(result, + list_nth(orargs, + matches[group_start].argindex)); + } + else + { + /* + * Two or more clauses in a group: create a nested OR. + */ + List *args = NIL; + List *rargs = NIL; + RestrictInfo *subrinfo; + int j; + + Assert(i - group_start >= 2); + + /* Construct the list of nested OR arguments */ + for (j = group_start; j < i; j++) + { + Node *arg = list_nth(orargs, matches[j].argindex); + + rargs = lappend(rargs, arg); + if (IsA(arg, RestrictInfo)) + args = lappend(args, ((RestrictInfo *) arg)->clause); + else + args = lappend(args, arg); + } + + /* Construct the nested OR and wrap it with RestrictInfo */ + subrinfo = make_plain_restrictinfo(root, + make_orclause(args), + make_orclause(rargs), + rinfo->is_pushed_down, + rinfo->has_clone, + rinfo->is_clone, + rinfo->pseudoconstant, + rinfo->security_level, + rinfo->required_relids, + rinfo->incompatible_relids, + rinfo->outer_relids); + result = lappend(result, subrinfo); + } + + group_start = i; + } + } + pfree(matches); + return result; +} + +/* + * make_bitmap_paths_for_or_group + * Generate bitmap paths for a group of similar OR-clause arguments + * produced by group_similar_or_args(). + * + * This function considers two cases: (1) matching a group of clauses to + * the index as a whole, and (2) matching the individual clauses one-by-one. + * (1) typically comprises an optimal solution. If not, (2) typically + * comprises fair alternative. + * + * Ideally, we could consider all arbitrary splits of arguments into + * subgroups, but that could lead to unacceptable computational complexity. + * This is why we only consider two cases of above. + */ +static List * +make_bitmap_paths_for_or_group(PlannerInfo *root, RelOptInfo *rel, + RestrictInfo *ri, List *other_clauses) +{ + List *jointlist = NIL; + List *splitlist = NIL; + ListCell *lc; + List *orargs; + List *args = ((BoolExpr *) ri->orclause)->args; + Cost jointcost = 0.0, + splitcost = 0.0; + Path *bitmapqual; + List *indlist; + + /* + * First, try to match the whole group to the one index. + */ + orargs = list_make1(ri); + indlist = build_paths_for_OR(root, rel, + orargs, + other_clauses); + if (indlist != NIL) + { + bitmapqual = choose_bitmap_and(root, rel, indlist); + jointcost = bitmapqual->total_cost; + jointlist = list_make1(bitmapqual); + } + + /* + * If we manage to find a bitmap scan, which uses the group of OR-clause + * arguments as a whole, we can skip matching OR-clause arguments + * one-by-one as long as there are no other clauses, which can bring more + * efficiency to one-by-one case. + */ + if (jointlist != NIL && other_clauses == NIL) + return jointlist; + + /* + * Also try to match all containing clauses one-by-one. + */ + foreach(lc, args) + { + orargs = list_make1(lfirst(lc)); + + indlist = build_paths_for_OR(root, rel, + orargs, + other_clauses); + + if (indlist == NIL) + { + splitlist = NIL; + break; + } + + bitmapqual = choose_bitmap_and(root, rel, indlist); + splitcost += bitmapqual->total_cost; + splitlist = lappend(splitlist, bitmapqual); + } + + /* + * Pick the best option. + */ + if (splitlist == NIL) + return jointlist; + else if (jointlist == NIL) + return splitlist; + else + return (jointcost < splitcost) ? jointlist : splitlist; +} + + /* * generate_bitmap_or_paths * Look through the list of clauses to find OR clauses, and generate @@ -1196,6 +1644,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *pathlist; Path *bitmapqual; ListCell *j; + List *groupedArgs; + List *inner_other_clauses = NIL; /* Ignore RestrictInfos that aren't ORs */ if (!restriction_is_or_clause(rinfo)) @@ -1206,7 +1656,29 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, * the OR, else we can't use it. */ pathlist = NIL; - foreach(j, ((BoolExpr *) rinfo->orclause)->args) + + /* + * Group the similar OR-clause arguments into dedicated RestrictInfos, + * because each of those RestrictInfos has a chance to match the index + * as a whole. + */ + groupedArgs = group_similar_or_args(root, rel, rinfo); + + if (groupedArgs != ((BoolExpr *) rinfo->orclause)->args) + { + /* + * Some parts of the rinfo were probably grouped. In this case, + * we have a set of sub-rinfos that together are an exact + * duplicate of rinfo. Thus, we need to remove the rinfo from + * other clauses. match_clauses_to_index detects duplicated + * iclauses by comparing pointers to original rinfos that would be + * different. So, we must delete rinfo to avoid de-facto + * duplicated clauses in the index clauses list. + */ + inner_other_clauses = list_delete(list_copy(all_clauses), rinfo); + } + + foreach(j, groupedArgs) { Node *orarg = (Node *) lfirst(j); List *indlist; @@ -1226,12 +1698,34 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, andargs, all_clauses)); } + else if (restriction_is_or_clause(castNode(RestrictInfo, orarg))) + { + RestrictInfo *ri = castNode(RestrictInfo, orarg); + + /* + * Generate bitmap paths for the group of similar OR-clause + * arguments. + */ + indlist = make_bitmap_paths_for_or_group(root, + rel, ri, + inner_other_clauses); + + if (indlist == NIL) + { + pathlist = NIL; + break; + } + else + { + pathlist = list_concat(pathlist, indlist); + continue; + } + } else { RestrictInfo *ri = castNode(RestrictInfo, orarg); List *orargs; - Assert(!restriction_is_or_clause(ri)); orargs = list_make1(ri); indlist = build_paths_for_OR(root, rel, @@ -1257,6 +1751,9 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, pathlist = lappend(pathlist, bitmapqual); } + if (inner_other_clauses != NIL) + list_free(inner_other_clauses); + /* * If we have a match for every arm, then turn them into a * BitmapOrPath, and add to result list. @@ -1978,6 +2475,7 @@ match_restriction_clauses_to_index(PlannerInfo *root, * Identify join clauses for the rel that match the index. * Matching clauses are added to *clauseset. * Also, add any potentially usable join OR clauses to *joinorclauses. + * They also might be processed by match_clause_to_index() as a whole. */ static void match_join_clauses_to_index(PlannerInfo *root, @@ -1996,11 +2494,15 @@ match_join_clauses_to_index(PlannerInfo *root, if (!join_clause_is_movable_to(rinfo, rel)) continue; - /* Potentially usable, so see if it matches the index or is an OR */ + /* + * Potentially usable, so see if it matches the index or is an OR. Use + * list_append_unique_ptr() here to avoid possible duplicates when + * processing the same clauses with different indexes. + */ if (restriction_is_or_clause(rinfo)) - *joinorclauses = lappend(*joinorclauses, rinfo); - else - match_clause_to_index(root, rinfo, index, clauseset); + *joinorclauses = list_append_unique_ptr(*joinorclauses, rinfo); + + match_clause_to_index(root, rinfo, index, clauseset); } } @@ -2030,7 +2532,7 @@ match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, clauses = generate_implied_equalities_for_column(root, index->rel, ec_member_matches_indexcol, - (void *) &arg, + &arg, index->rel->lateral_referencers); /* @@ -2179,6 +2681,10 @@ match_clause_to_index(PlannerInfo *root, * It is also possible to match ScalarArrayOpExpr clauses to indexes, when * the clause is of the form "indexkey op ANY (arrayconst)". * + * It is also possible to match a list of OR clauses if it might be + * transformed into a single ScalarArrayOpExpr clause. On success, + * the returning index clause will contain a transformed clause. + * * For boolean indexes, it is also possible to match the clause directly * to the indexkey; or perhaps the clause is (NOT indexkey). * @@ -2196,8 +2702,9 @@ match_clause_to_index(PlannerInfo *root, * Returns an IndexClause if the clause can be used with this index key, * or NULL if not. * - * NOTE: returns NULL if clause is an OR or AND clause; it is the - * responsibility of higher-level routines to cope with those. + * NOTE: This routine always returns NULL if the clause is an AND clause. + * Higher-level routines deal with OR and AND clauses. OR clause can be + * matched as a whole by match_orclause_to_indexcol() though. */ static IndexClause * match_clause_to_indexcol(PlannerInfo *root, @@ -2228,9 +2735,9 @@ match_clause_to_indexcol(PlannerInfo *root, } /* - * Clause must be an opclause, funcclause, ScalarArrayOpExpr, or - * RowCompareExpr. Or, if the index supports it, we can handle IS - * NULL/NOT NULL clauses. + * Clause must be an opclause, funcclause, ScalarArrayOpExpr, + * RowCompareExpr, or OR-clause that could be converted to SAOP. Or, if + * the index supports it, we can handle IS NULL/NOT NULL clauses. */ if (IsA(clause, OpExpr)) { @@ -2248,6 +2755,10 @@ match_clause_to_indexcol(PlannerInfo *root, { return match_rowcompare_to_indexcol(root, rinfo, indexcol, index); } + else if (restriction_is_or_clause(rinfo)) + { + return match_orclause_to_indexcol(root, rinfo, indexcol, index); + } else if (index->amsearchnulls && IsA(clause, NullTest)) { NullTest *nt = (NullTest *) clause; @@ -2771,6 +3282,216 @@ match_rowcompare_to_indexcol(PlannerInfo *root, return NULL; } +/* + * match_orclause_to_indexcol() + * Handles the OR-expr case for match_clause_to_indexcol() in the case + * when it could be transformed to ScalarArrayOpExpr. + * + * In this routine, we attempt to transform a list of OR-clause args into a + * single SAOP expression matching the target index column. On success, + * return an IndexClause, containing the transformed expression or NULL, + * if failed. + */ +static IndexClause * +match_orclause_to_indexcol(PlannerInfo *root, + RestrictInfo *rinfo, + int indexcol, + IndexOptInfo *index) +{ + ListCell *lc; + BoolExpr *orclause = (BoolExpr *) rinfo->orclause; + Node *indexExpr = NULL; + List *consts = NIL; + ScalarArrayOpExpr *saopexpr = NULL; + Oid matchOpno = InvalidOid; + IndexClause *iclause; + Oid consttype = InvalidOid; + Oid arraytype = InvalidOid; + Oid inputcollid = InvalidOid; + bool firstTime = true; + bool haveNonConst = false; + Index indexRelid = index->rel->relid; + + Assert(IsA(orclause, BoolExpr)); + Assert(orclause->boolop == OR_EXPR); + + /* Ignore index if it doesn't support SAOP clauses */ + if (!index->amsearcharray) + return NULL; + + /* + * Try to convert a list of OR-clauses to a single SAOP expression. Each + * OR entry must be in the form: (indexkey operator constant) or (constant + * operator indexkey). Operators of all the entries must match. To be + * effective, give up on the first non-matching entry. Exit is + * implemented as a break from the loop, which is catched afterwards. + */ + foreach(lc, orclause->args) + { + RestrictInfo *subRinfo; + OpExpr *subClause; + Oid opno; + Node *leftop, + *rightop; + Node *constExpr; + + if (!IsA(lfirst(lc), RestrictInfo)) + break; + + subRinfo = (RestrictInfo *) lfirst(lc); + + /* Only operator clauses can match */ + if (!IsA(subRinfo->clause, OpExpr)) + break; + + subClause = (OpExpr *) subRinfo->clause; + opno = subClause->opno; + + /* Only binary operators can match */ + if (list_length(subClause->args) != 2) + break; + + /* + * The parameters below must match between sub-rinfo and its parent as + * make_restrictinfo() fills them with the same values, and further + * modifications are also the same for the whole subtree. However, + * still make a sanity check. + */ + Assert(subRinfo->is_pushed_down == rinfo->is_pushed_down); + Assert(subRinfo->is_clone == rinfo->is_clone); + Assert(subRinfo->security_level == rinfo->security_level); + Assert(bms_equal(subRinfo->incompatible_relids, rinfo->incompatible_relids)); + Assert(bms_equal(subRinfo->outer_relids, rinfo->outer_relids)); + + /* + * Also, check that required_relids in sub-rinfo is subset of parent's + * required_relids. + */ + Assert(bms_is_subset(subRinfo->required_relids, rinfo->required_relids)); + + /* Only the operator returning a boolean suit the transformation. */ + if (get_op_rettype(opno) != BOOLOID) + break; + + /* + * Check for clauses of the form: (indexkey operator constant) or + * (constant operator indexkey). See match_clause_to_indexcol's notes + * about const-ness. + */ + leftop = (Node *) linitial(subClause->args); + rightop = (Node *) lsecond(subClause->args); + if (match_index_to_operand(leftop, indexcol, index) && + !bms_is_member(indexRelid, subRinfo->right_relids) && + !contain_volatile_functions(rightop)) + { + indexExpr = leftop; + constExpr = rightop; + } + else if (match_index_to_operand(rightop, indexcol, index) && + !bms_is_member(indexRelid, subRinfo->left_relids) && + !contain_volatile_functions(leftop)) + { + opno = get_commutator(opno); + if (!OidIsValid(opno)) + { + /* commutator doesn't exist, we can't reverse the order */ + break; + } + indexExpr = rightop; + constExpr = leftop; + } + else + { + break; + } + + /* + * Ignore any RelabelType node above the operands. This is needed to + * be able to apply indexscanning in binary-compatible-operator cases. + * Note: we can assume there is at most one RelabelType node; + * eval_const_expressions() will have simplified if more than one. + */ + if (IsA(constExpr, RelabelType)) + constExpr = (Node *) ((RelabelType *) constExpr)->arg; + if (IsA(indexExpr, RelabelType)) + indexExpr = (Node *) ((RelabelType *) indexExpr)->arg; + + /* Forbid transformation for composite types, records. */ + if (type_is_rowtype(exprType(constExpr)) || + type_is_rowtype(exprType(indexExpr))) + break; + + /* + * Save information about the operator, type, and collation for the + * first matching qual. Then, check that subsequent quals match the + * first. + */ + if (firstTime) + { + matchOpno = opno; + consttype = exprType(constExpr); + arraytype = get_array_type(consttype); + inputcollid = subClause->inputcollid; + + /* + * Check that the operator is presented in the opfamily and that + * the expression collation matches the index collation. Also, + * there must be an array type to construct an array later. + */ + if (!IndexCollMatchesExprColl(index->indexcollations[indexcol], inputcollid) || + !op_in_opfamily(matchOpno, index->opfamily[indexcol]) || + !OidIsValid(arraytype)) + break; + firstTime = false; + } + else + { + if (opno != matchOpno || + inputcollid != subClause->inputcollid || + consttype != exprType(constExpr)) + break; + } + + /* + * Check if our list of constants in match_clause_to_indexcol's + * understanding of const-ness have something other than Const. + */ + if (!IsA(constExpr, Const)) + haveNonConst = true; + consts = lappend(consts, constExpr); + } + + /* + * Catch the break from the loop above. Normally, a foreach() loop ends + * up with a NULL list cell. A non-NULL list cell indicates a break from + * the foreach() loop. Free the consts list and return NULL then. + */ + if (lc != NULL) + { + list_free(consts); + return NULL; + } + + saopexpr = make_SAOP_expr(matchOpno, indexExpr, consttype, inputcollid, + inputcollid, consts, haveNonConst); + + /* + * Finally, build an IndexClause based on the SAOP node. Use + * make_simple_restrictinfo() to get RestrictInfo with clean selectivity + * estimations, because they may differ from the estimation made for an OR + * clause. Although it is not a lossy expression, keep the original rinfo + * in iclause->rinfo as prescribed. + */ + iclause = makeNode(IndexClause); + iclause->rinfo = rinfo; + iclause->indexquals = list_make1(make_simple_restrictinfo(root, + &saopexpr->xpr)); + iclause->lossy = false; + iclause->indexcol = indexcol; + iclause->indexcols = NIL; + return iclause; +} + /* * expand_indexqual_rowcompare --- expand a single indexqual condition * that is a RowCompareExpr @@ -2966,7 +3687,7 @@ expand_indexqual_rowcompare(PlannerInfo *root, { RowCompareExpr *rc = makeNode(RowCompareExpr); - rc->rctype = (RowCompareType) op_strategy; + rc->cmptype = (CompareType) op_strategy; rc->opnos = new_ops; rc->opfamilies = list_copy_head(clause->opfamilies, matching_cols); @@ -3034,12 +3755,12 @@ match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, { PathKey *pathkey = (PathKey *) lfirst(lc1); bool found = false; - ListCell *lc2; + EquivalenceMemberIterator it; + EquivalenceMember *member; /* Pathkey must request default sort order for the target opfamily */ - if (pathkey->pk_strategy != BTLessStrategyNumber || - pathkey->pk_nulls_first) + if (pathkey->pk_cmptype != COMPARE_LT || pathkey->pk_nulls_first) return; /* If eclass is volatile, no hope of using an indexscan */ @@ -3054,9 +3775,10 @@ match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, * be considered to match more than one pathkey list, which is OK * here. See also get_eclass_for_sort_expr.) */ - foreach(lc2, pathkey->pk_eclass->ec_members) + setup_eclass_member_iterator(&it, pathkey->pk_eclass, + index->rel->relids); + while ((member = eclass_member_iterator_next(&it)) != NULL) { - EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2); int indexcol; /* No possibility of match if it references other relations */ @@ -3440,6 +4162,22 @@ bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist) +{ + return relation_has_unique_index_ext(root, rel, restrictlist, + exprlist, oprlist, NULL); +} + +/* + * relation_has_unique_index_ext + * Same as relation_has_unique_index_for(), but supports extra_clauses + * parameter. If extra_clauses isn't NULL, return baserestrictinfo clauses + * which were used to derive uniqueness. + */ +bool +relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel, + List *restrictlist, + List *exprlist, List *oprlist, + List **extra_clauses) { ListCell *ic; @@ -3495,6 +4233,7 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, { IndexOptInfo *ind = (IndexOptInfo *) lfirst(ic); int c; + List *exprs = NIL; /* * If the index is not unique, or not immediately enforced, or if it's @@ -3546,6 +4285,24 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, if (match_index_to_operand(rexpr, c, ind)) { matched = true; /* column is unique */ + + if (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) + { + MemoryContext oldMemCtx = + MemoryContextSwitchTo(root->planner_cxt); + + /* + * Add filter clause into a list allowing caller to + * know if uniqueness have made not only by join + * clauses. + */ + Assert(bms_is_empty(rinfo->left_relids) || + bms_is_empty(rinfo->right_relids)); + if (extra_clauses) + exprs = lappend(exprs, rinfo); + MemoryContextSwitchTo(oldMemCtx); + } + break; } } @@ -3588,7 +4345,11 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, /* Matched all key columns of this index? */ if (c == ind->nkeycolumns) + { + if (extra_clauses) + *extra_clauses = exprs; return true; + } } return false; diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 7a2c20b145077..26f0336f1e409 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -3,7 +3,7 @@ * joinpath.c * Routines to find all possible paths for processing a set of joins * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -25,6 +25,8 @@ #include "optimizer/paths.h" #include "optimizer/placeholder.h" #include "optimizer/planmain.h" +#include "optimizer/restrictinfo.h" +#include "utils/lsyscache.h" #include "utils/typcache.h" /* Hook for plugins to get control in add_paths_to_joinrel() */ @@ -57,9 +59,6 @@ static void try_partial_mergejoin_path(PlannerInfo *root, static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra); -static inline bool clause_sides_match_join(RestrictInfo *rinfo, - RelOptInfo *outerrel, - RelOptInfo *innerrel); static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra); @@ -469,7 +468,8 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info, * with 2 args. */ if (!IsA(opexpr, OpExpr) || list_length(opexpr->args) != 2 || - !clause_sides_match_join(rinfo, outerrel, innerrel)) + !clause_sides_match_join(rinfo, outerrel->relids, + innerrel->relids)) { list_free(*operators); list_free(*param_exprs); @@ -748,16 +748,22 @@ get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel, * * Lateral vars needn't be considered here as they're not considered when * determining if the join is unique. - * - * XXX this could be enabled if the remaining join quals were made part of - * the inner scan's filter instead of the join filter. Maybe it's worth - * considering doing that? */ - if (extra->inner_unique && - (inner_path->param_info == NULL || - bms_num_members(inner_path->param_info->ppi_serials) < - list_length(extra->restrictlist))) - return NULL; + if (extra->inner_unique) + { + Bitmapset *ppi_serials; + + if (inner_path->param_info == NULL) + return NULL; + + ppi_serials = inner_path->param_info->ppi_serials; + + foreach_node(RestrictInfo, rinfo, extra->restrictlist) + { + if (!bms_is_member(rinfo->rinfo_serial, ppi_serials)) + return NULL; + } + } /* * We can't use a memoize node if there are volatile functions in the @@ -915,7 +921,7 @@ try_nestloop_path(PlannerInfo *root, initial_cost_nestloop(root, &workspace, jointype, outer_path, inner_path, extra); - if (add_path_precheck(joinrel, + if (add_path_precheck(joinrel, workspace.disabled_nodes, workspace.startup_cost, workspace.total_cost, pathkeys, required_outer)) { @@ -961,6 +967,7 @@ try_partial_nestloop_path(PlannerInfo *root, * rels are required here. */ Assert(bms_is_empty(joinrel->lateral_relids)); + Assert(bms_is_empty(PATH_REQ_OUTER(outer_path))); if (inner_path->param_info != NULL) { Relids inner_paramrels = inner_path->param_info->ppi_req_outer; @@ -998,7 +1005,8 @@ try_partial_nestloop_path(PlannerInfo *root, */ initial_cost_nestloop(root, &workspace, jointype, outer_path, inner_path, extra); - if (!add_partial_path_precheck(joinrel, workspace.total_cost, pathkeys)) + if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes, + workspace.total_cost, pathkeys)) return; /* Might be good enough to be worth trying, so let's try it. */ @@ -1034,6 +1042,7 @@ try_mergejoin_path(PlannerInfo *root, bool is_partial) { Relids required_outer; + int outer_presorted_keys = 0; JoinCostWorkspace workspace; if (is_partial) @@ -1079,9 +1088,16 @@ try_mergejoin_path(PlannerInfo *root, /* * If the given paths are already well enough ordered, we can skip doing * an explicit sort. + * + * We need to determine the number of presorted keys of the outer path to + * decide whether explicit incremental sort can be applied when + * outersortkeys is not NIL. We do not need to do the same for the inner + * path though, as incremental sort currently does not support + * mark/restore. */ if (outersortkeys && - pathkeys_contained_in(outersortkeys, outer_path->pathkeys)) + pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys, + &outer_presorted_keys)) outersortkeys = NIL; if (innersortkeys && pathkeys_contained_in(innersortkeys, inner_path->pathkeys)) @@ -1093,9 +1109,10 @@ try_mergejoin_path(PlannerInfo *root, initial_cost_mergejoin(root, &workspace, jointype, mergeclauses, outer_path, inner_path, outersortkeys, innersortkeys, + outer_presorted_keys, extra); - if (add_path_precheck(joinrel, + if (add_path_precheck(joinrel, workspace.disabled_nodes, workspace.startup_cost, workspace.total_cost, pathkeys, required_outer)) { @@ -1112,7 +1129,8 @@ try_mergejoin_path(PlannerInfo *root, required_outer, mergeclauses, outersortkeys, - innersortkeys)); + innersortkeys, + outer_presorted_keys)); } else { @@ -1138,26 +1156,30 @@ try_partial_mergejoin_path(PlannerInfo *root, JoinType jointype, JoinPathExtraData *extra) { + int outer_presorted_keys = 0; JoinCostWorkspace workspace; /* * See comments in try_partial_hashjoin_path(). */ Assert(bms_is_empty(joinrel->lateral_relids)); - if (inner_path->param_info != NULL) - { - Relids inner_paramrels = inner_path->param_info->ppi_req_outer; - - if (!bms_is_empty(inner_paramrels)) - return; - } + Assert(bms_is_empty(PATH_REQ_OUTER(outer_path))); + if (!bms_is_empty(PATH_REQ_OUTER(inner_path))) + return; /* * If the given paths are already well enough ordered, we can skip doing * an explicit sort. + * + * We need to determine the number of presorted keys of the outer path to + * decide whether explicit incremental sort can be applied when + * outersortkeys is not NIL. We do not need to do the same for the inner + * path though, as incremental sort currently does not support + * mark/restore. */ if (outersortkeys && - pathkeys_contained_in(outersortkeys, outer_path->pathkeys)) + pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys, + &outer_presorted_keys)) outersortkeys = NIL; if (innersortkeys && pathkeys_contained_in(innersortkeys, inner_path->pathkeys)) @@ -1169,9 +1191,11 @@ try_partial_mergejoin_path(PlannerInfo *root, initial_cost_mergejoin(root, &workspace, jointype, mergeclauses, outer_path, inner_path, outersortkeys, innersortkeys, + outer_presorted_keys, extra); - if (!add_partial_path_precheck(joinrel, workspace.total_cost, pathkeys)) + if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes, + workspace.total_cost, pathkeys)) return; /* Might be good enough to be worth trying, so let's try it. */ @@ -1188,7 +1212,8 @@ try_partial_mergejoin_path(PlannerInfo *root, NULL, mergeclauses, outersortkeys, - innersortkeys)); + innersortkeys, + outer_presorted_keys)); } /* @@ -1240,7 +1265,7 @@ try_hashjoin_path(PlannerInfo *root, initial_cost_hashjoin(root, &workspace, jointype, hashclauses, outer_path, inner_path, extra, false); - if (add_path_precheck(joinrel, + if (add_path_precheck(joinrel, workspace.disabled_nodes, workspace.startup_cost, workspace.total_cost, NIL, required_outer)) { @@ -1286,19 +1311,14 @@ try_partial_hashjoin_path(PlannerInfo *root, JoinCostWorkspace workspace; /* - * If the inner path is parameterized, the parameterization must be fully - * satisfied by the proposed outer path. Parameterized partial paths are - * not supported. The caller should already have verified that no lateral - * rels are required here. + * If the inner path is parameterized, we can't use a partial hashjoin. + * Parameterized partial paths are not supported. The caller should + * already have verified that no lateral rels are required here. */ Assert(bms_is_empty(joinrel->lateral_relids)); - if (inner_path->param_info != NULL) - { - Relids inner_paramrels = inner_path->param_info->ppi_req_outer; - - if (!bms_is_empty(inner_paramrels)) - return; - } + Assert(bms_is_empty(PATH_REQ_OUTER(outer_path))); + if (!bms_is_empty(PATH_REQ_OUTER(inner_path))) + return; /* * Before creating a path, get a quick lower bound on what it is likely to @@ -1306,7 +1326,8 @@ try_partial_hashjoin_path(PlannerInfo *root, */ initial_cost_hashjoin(root, &workspace, jointype, hashclauses, outer_path, inner_path, extra, parallel_hash); - if (!add_partial_path_precheck(joinrel, workspace.total_cost, NIL)) + if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes, + workspace.total_cost, NIL)) return; /* Might be good enough to be worth trying, so let's try it. */ @@ -1324,37 +1345,6 @@ try_partial_hashjoin_path(PlannerInfo *root, hashclauses)); } -/* - * clause_sides_match_join - * Determine whether a join clause is of the right form to use in this join. - * - * We already know that the clause is a binary opclause referencing only the - * rels in the current join. The point here is to check whether it has the - * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr", - * rather than mixing outer and inner vars on either side. If it matches, - * we set the transient flag outer_is_left to identify which side is which. - */ -static inline bool -clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel, - RelOptInfo *innerrel) -{ - if (bms_is_subset(rinfo->left_relids, outerrel->relids) && - bms_is_subset(rinfo->right_relids, innerrel->relids)) - { - /* lefthand side is outer */ - rinfo->outer_is_left = true; - return true; - } - else if (bms_is_subset(rinfo->left_relids, innerrel->relids) && - bms_is_subset(rinfo->right_relids, outerrel->relids)) - { - /* righthand side is outer */ - rinfo->outer_is_left = false; - return true; - } - return false; /* no good for these input relations */ -} - /* * sort_inner_and_outer * Create mergejoin join paths by explicitly sorting both the outer and @@ -1382,6 +1372,10 @@ sort_inner_and_outer(PlannerInfo *root, List *all_pathkeys; ListCell *l; + /* Nothing to do if there are no available mergejoin clauses */ + if (extra->mergeclause_list == NIL) + return; + /* * We only consider the cheapest-total-cost input paths, since we are * assuming here that a sort is required. We will consider @@ -2264,9 +2258,24 @@ hash_inner_and_outer(PlannerInfo *root, /* * Check if clause has the form "outer op inner" or "inner op outer". */ - if (!clause_sides_match_join(restrictinfo, outerrel, innerrel)) + if (!clause_sides_match_join(restrictinfo, outerrel->relids, + innerrel->relids)) continue; /* no good for these input relations */ + /* + * If clause has the form "inner op outer", check if its operator has + * valid commutator. This is necessary because hashclauses in this + * form will get commuted in createplan.c to put the outer var on the + * left (see get_switched_clauses). This probably shouldn't ever + * fail, since hashable operators ought to have commutators, but be + * paranoid. + * + * The clause being hashjoinable indicates that it's an OpExpr. + */ + if (!restrictinfo->outer_is_left && + !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno))) + continue; + hashclauses = lappend(hashclauses, restrictinfo); } @@ -2535,12 +2544,30 @@ select_mergejoin_clauses(PlannerInfo *root, /* * Check if clause has the form "outer op inner" or "inner op outer". */ - if (!clause_sides_match_join(restrictinfo, outerrel, innerrel)) + if (!clause_sides_match_join(restrictinfo, outerrel->relids, + innerrel->relids)) { have_nonmergeable_joinclause = true; continue; /* no good for these input relations */ } + /* + * If clause has the form "inner op outer", check if its operator has + * valid commutator. This is necessary because mergejoin clauses in + * this form will get commuted in createplan.c to put the outer var on + * the left (see get_switched_clauses). This probably shouldn't ever + * fail, since mergejoinable operators ought to have commutators, but + * be paranoid. + * + * The clause being mergejoinable indicates that it's an OpExpr. + */ + if (!restrictinfo->outer_is_left && + !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno))) + { + have_nonmergeable_joinclause = true; + continue; + } + /* * Insist that each side have a non-redundant eclass. This * restriction is needed because various bits of the planner expect diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index a3677f824fe8e..60d65762b5d5e 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -3,7 +3,7 @@ * joinrels.c * Routines to determine which relations should be joined * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -45,7 +45,8 @@ static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, Relids left_relids, Relids right_relids); -static void free_child_join_sjinfo(SpecialJoinInfo *sjinfo); +static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo, + SpecialJoinInfo *parent_sjinfo); static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo, @@ -1547,6 +1548,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, RelOptInfo *child_joinrel; AppendRelInfo **appinfos; int nappinfos; + Relids child_relids; if (joinrel->partbounds_merged) { @@ -1642,9 +1644,8 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_rel2->relids); /* Find the AppendRelInfo structures */ - appinfos = find_appinfos_by_relids(root, - bms_union(child_rel1->relids, - child_rel2->relids), + child_relids = bms_union(child_rel1->relids, child_rel2->relids); + appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos); /* @@ -1662,7 +1663,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, { child_joinrel = build_child_join_rel(root, child_rel1, child_rel2, joinrel, child_restrictlist, - child_sjinfo); + child_sjinfo, nappinfos, appinfos); joinrel->part_rels[cnt_parts] = child_joinrel; joinrel->live_parts = bms_add_member(joinrel->live_parts, cnt_parts); joinrel->all_partrels = bms_add_members(joinrel->all_partrels, @@ -1679,8 +1680,15 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_joinrel, child_sjinfo, child_restrictlist); + /* + * When there are thousands of partitions involved, this loop will + * accumulate a significant amount of memory usage from objects that + * are only needed within the loop. Free these local objects eagerly + * at the end of each iteration. + */ pfree(appinfos); - free_child_join_sjinfo(child_sjinfo); + bms_free(child_relids); + free_child_join_sjinfo(child_sjinfo, parent_sjinfo); } } @@ -1747,18 +1755,33 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, * SpecialJoinInfo are freed here. */ static void -free_child_join_sjinfo(SpecialJoinInfo *sjinfo) +free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo, + SpecialJoinInfo *parent_sjinfo) { /* * Dummy SpecialJoinInfos of inner joins do not have any translated fields * and hence no fields that to be freed. */ - if (sjinfo->jointype != JOIN_INNER) + if (child_sjinfo->jointype != JOIN_INNER) { - bms_free(sjinfo->min_lefthand); - bms_free(sjinfo->min_righthand); - bms_free(sjinfo->syn_lefthand); - bms_free(sjinfo->syn_righthand); + if (child_sjinfo->min_lefthand != parent_sjinfo->min_lefthand) + bms_free(child_sjinfo->min_lefthand); + + if (child_sjinfo->min_righthand != parent_sjinfo->min_righthand) + bms_free(child_sjinfo->min_righthand); + + if (child_sjinfo->syn_lefthand != parent_sjinfo->syn_lefthand) + bms_free(child_sjinfo->syn_lefthand); + + if (child_sjinfo->syn_righthand != parent_sjinfo->syn_righthand) + bms_free(child_sjinfo->syn_righthand); + + Assert(child_sjinfo->commute_above_l == parent_sjinfo->commute_above_l); + Assert(child_sjinfo->commute_above_r == parent_sjinfo->commute_above_r); + Assert(child_sjinfo->commute_below_l == parent_sjinfo->commute_below_l); + Assert(child_sjinfo->commute_below_r == parent_sjinfo->commute_below_r); + + Assert(child_sjinfo->semi_operators == parent_sjinfo->semi_operators); /* * semi_rhs_exprs may in principle be freed, but a simple pfree() does @@ -1766,7 +1789,7 @@ free_child_join_sjinfo(SpecialJoinInfo *sjinfo) */ } - pfree(sjinfo); + pfree(child_sjinfo); } /* diff --git a/src/backend/optimizer/path/meson.build b/src/backend/optimizer/path/meson.build index b09fbe44669b9..12f36d85cb65b 100644 --- a/src/backend/optimizer/path/meson.build +++ b/src/backend/optimizer/path/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'allpaths.c', diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index e25798972f6c7..8b04d40d36d73 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -7,7 +7,7 @@ * the nature and use of path keys. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -25,6 +25,7 @@ #include "optimizer/pathnode.h" #include "optimizer/paths.h" #include "partitioning/partbounds.h" +#include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" /* Consider reordering of GROUP BY keys? */ @@ -54,7 +55,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey); PathKey * make_canonical_pathkey(PlannerInfo *root, EquivalenceClass *eclass, Oid opfamily, - int strategy, bool nulls_first) + CompareType cmptype, bool nulls_first) { PathKey *pk; ListCell *lc; @@ -73,7 +74,7 @@ make_canonical_pathkey(PlannerInfo *root, pk = (PathKey *) lfirst(lc); if (eclass == pk->pk_eclass && opfamily == pk->pk_opfamily && - strategy == pk->pk_strategy && + cmptype == pk->pk_cmptype && nulls_first == pk->pk_nulls_first) return pk; } @@ -87,7 +88,7 @@ make_canonical_pathkey(PlannerInfo *root, pk = makeNode(PathKey); pk->pk_eclass = eclass; pk->pk_opfamily = opfamily; - pk->pk_strategy = strategy; + pk->pk_cmptype = cmptype; pk->pk_nulls_first = nulls_first; root->canon_pathkeys = lappend(root->canon_pathkeys, pk); @@ -205,12 +206,12 @@ make_pathkey_from_sortinfo(PlannerInfo *root, Relids rel, bool create_it) { - int16 strategy; + CompareType cmptype; Oid equality_op; List *opfamilies; EquivalenceClass *eclass; - strategy = reverse_sort ? BTGreaterStrategyNumber : BTLessStrategyNumber; + cmptype = reverse_sort ? COMPARE_GT : COMPARE_LT; /* * EquivalenceClasses need to contain opfamily lists based on the family @@ -218,13 +219,13 @@ make_pathkey_from_sortinfo(PlannerInfo *root, * more than one opfamily. So we have to look up the opfamily's equality * operator and get its membership. */ - equality_op = get_opfamily_member(opfamily, - opcintype, - opcintype, - BTEqualStrategyNumber); + equality_op = get_opfamily_member_for_cmptype(opfamily, + opcintype, + opcintype, + COMPARE_EQ); if (!OidIsValid(equality_op)) /* shouldn't happen */ elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - BTEqualStrategyNumber, opcintype, opcintype, opfamily); + COMPARE_EQ, opcintype, opcintype, opfamily); opfamilies = get_mergejoin_opfamilies(equality_op); if (!opfamilies) /* certainly should find some */ elog(ERROR, "could not find opfamilies for equality operator %u", @@ -241,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root, /* And finally we can find or create a PathKey node */ return make_canonical_pathkey(root, eclass, opfamily, - strategy, nulls_first); + cmptype, nulls_first); } /* @@ -255,6 +256,7 @@ static PathKey * make_pathkey_from_sortop(PlannerInfo *root, Expr *expr, Oid ordering_op, + bool reverse_sort, bool nulls_first, Index sortref, bool create_it) @@ -262,11 +264,11 @@ make_pathkey_from_sortop(PlannerInfo *root, Oid opfamily, opcintype, collation; - int16 strategy; + CompareType cmptype; /* Find the operator in pg_amop --- failure shouldn't happen */ if (!get_ordering_op_properties(ordering_op, - &opfamily, &opcintype, &strategy)) + &opfamily, &opcintype, &cmptype)) elog(ERROR, "operator %u is not a valid ordering operator", ordering_op); @@ -278,7 +280,7 @@ make_pathkey_from_sortop(PlannerInfo *root, opfamily, opcintype, collation, - (strategy == BTGreaterStrategyNumber), + reverse_sort, nulls_first, sortref, NULL, @@ -1004,12 +1006,12 @@ build_expression_pathkey(PlannerInfo *root, List *pathkeys; Oid opfamily, opcintype; - int16 strategy; + CompareType cmptype; PathKey *cpathkey; /* Find the operator in pg_amop --- failure shouldn't happen */ if (!get_ordering_op_properties(opno, - &opfamily, &opcintype, &strategy)) + &opfamily, &opcintype, &cmptype)) elog(ERROR, "operator %u is not a valid ordering operator", opno); @@ -1018,8 +1020,8 @@ build_expression_pathkey(PlannerInfo *root, opfamily, opcintype, exprCollation((Node *) expr), - (strategy == BTGreaterStrategyNumber), - (strategy == BTGreaterStrategyNumber), + (cmptype == COMPARE_GT), + (cmptype == COMPARE_GT), 0, rel, create_it); @@ -1116,7 +1118,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, make_canonical_pathkey(root, outer_ec, sub_pathkey->pk_opfamily, - sub_pathkey->pk_strategy, + sub_pathkey->pk_cmptype, sub_pathkey->pk_nulls_first); } } @@ -1141,6 +1143,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, int best_score = -1; ListCell *j; + /* Ignore children here */ foreach(j, sub_eclass->ec_members) { EquivalenceMember *sub_member = (EquivalenceMember *) lfirst(j); @@ -1149,8 +1152,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, Oid sub_expr_coll = sub_eclass->ec_collation; ListCell *k; - if (sub_member->em_is_child) - continue; /* ignore children here */ + /* Child members should not exist in ec_members */ + Assert(!sub_member->em_is_child); foreach(k, subquery_tlist) { @@ -1198,7 +1201,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, outer_pk = make_canonical_pathkey(root, outer_ec, sub_pathkey->pk_opfamily, - sub_pathkey->pk_strategy, + sub_pathkey->pk_cmptype, sub_pathkey->pk_nulls_first); /* score = # of equivalence peers */ score = list_length(outer_ec->ec_members) - 1; @@ -1341,6 +1344,7 @@ make_pathkeys_for_sortclauses(PlannerInfo *root, &sortclauses, tlist, false, + false, &sortable, false); /* It's caller error if not all clauses were sortable */ @@ -1359,6 +1363,9 @@ make_pathkeys_for_sortclauses(PlannerInfo *root, * give rise to redundant pathkeys are removed from the sortclauses list * (which therefore must be pass-by-reference in this version). * + * If remove_group_rtindex is true, then we need to remove the RT index of the + * grouping step from the sort expressions before we make PathKeys for them. + * * *sortable is set to true if all the sort clauses are in fact sortable. * If any are not, they are ignored except for setting *sortable false. * (In that case, the output pathkey list isn't really useful. However, @@ -1375,6 +1382,7 @@ make_pathkeys_for_sortclauses_extended(PlannerInfo *root, List **sortclauses, List *tlist, bool remove_redundant, + bool remove_group_rtindex, bool *sortable, bool set_ec_sortref) { @@ -1394,9 +1402,18 @@ make_pathkeys_for_sortclauses_extended(PlannerInfo *root, *sortable = false; continue; } + if (remove_group_rtindex) + { + Assert(root->group_rtindex > 0); + sortkey = (Expr *) + remove_nulling_relids((Node *) sortkey, + bms_make_singleton(root->group_rtindex), + NULL); + } pathkey = make_pathkey_from_sortop(root, sortkey, sortcl->sortop, + sortcl->reverse_sort, sortcl->nulls_first, sortcl->tleSortGroupRef, true); @@ -1693,8 +1710,11 @@ select_outer_pathkeys_for_merge(PlannerInfo *root, { EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); + /* Child members should not exist in ec_members */ + Assert(!em->em_is_child); + /* Potential future join partner? */ - if (!em->em_is_const && !em->em_is_child && + if (!em->em_is_const && !bms_overlap(em->em_relids, joinrel->relids)) score++; } @@ -1800,7 +1820,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root, pathkey = make_canonical_pathkey(root, ec, linitial_oid(ec->ec_opfamilies), - BTLessStrategyNumber, + COMPARE_LT, false); /* can't be redundant because no duplicate ECs */ Assert(!pathkey_is_redundant(pathkey, pathkeys)); @@ -1893,7 +1913,7 @@ make_inner_pathkeys_for_merge(PlannerInfo *root, pathkey = make_canonical_pathkey(root, ieclass, opathkey->pk_opfamily, - opathkey->pk_strategy, + opathkey->pk_cmptype, opathkey->pk_nulls_first); /* @@ -2118,12 +2138,12 @@ right_merge_direction(PlannerInfo *root, PathKey *pathkey) * want to prefer only one of the two possible directions, and we * might as well use this one. */ - return (pathkey->pk_strategy == query_pathkey->pk_strategy); + return (pathkey->pk_cmptype == query_pathkey->pk_cmptype); } } /* If no matching ORDER BY request, prefer the ASC direction */ - return (pathkey->pk_strategy == BTLessStrategyNumber); + return (pathkey->pk_cmptype == COMPARE_LT); } /* @@ -2191,6 +2211,41 @@ pathkeys_useful_for_grouping(PlannerInfo *root, List *pathkeys) return n; } +/* + * pathkeys_useful_for_distinct + * Count the number of pathkeys that are useful for DISTINCT or DISTINCT + * ON clause. + * + * DISTINCT keys could be reordered to benefit from the given pathkey list. As + * with pathkeys_useful_for_grouping, we return the number of leading keys in + * the list that are shared by the distinctClause pathkeys. + */ +static int +pathkeys_useful_for_distinct(PlannerInfo *root, List *pathkeys) +{ + int n_common_pathkeys; + + /* + * distinct_pathkeys may have become empty if all of the pathkeys were + * determined to be redundant. Return 0 in this case. + */ + if (root->distinct_pathkeys == NIL) + return 0; + + /* walk the pathkeys and search for matching DISTINCT key */ + n_common_pathkeys = 0; + foreach_node(PathKey, pathkey, pathkeys) + { + /* no matching DISTINCT key, we're done */ + if (!list_member_ptr(root->distinct_pathkeys, pathkey)) + break; + + n_common_pathkeys++; + } + + return n_common_pathkeys; +} + /* * pathkeys_useful_for_setop * Count the number of leading common pathkeys root's 'setop_pathkeys' in @@ -2224,6 +2279,9 @@ truncate_useless_pathkeys(PlannerInfo *root, if (nuseful2 > nuseful) nuseful = nuseful2; nuseful2 = pathkeys_useful_for_grouping(root, pathkeys); + if (nuseful2 > nuseful) + nuseful = nuseful2; + nuseful2 = pathkeys_useful_for_distinct(root, pathkeys); if (nuseful2 > nuseful) nuseful = nuseful2; nuseful2 = pathkeys_useful_for_setop(root, pathkeys); diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c index b0323b26ecaec..2bfb338b81ced 100644 --- a/src/backend/optimizer/path/tidpath.c +++ b/src/backend/optimizer/path/tidpath.c @@ -27,7 +27,7 @@ * "CTID relop pseudoconstant", where relop is one of >,>=,<,<=, and * AND-clauses composed of such conditions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index c3fd4a81f8a61..4d55c2ea59162 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -11,7 +11,7 @@ * is that we have to work harder to clean up after ourselves when we modify * the query, since the derived data structures have to be updated too. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,34 +22,60 @@ */ #include "postgres.h" +#include "catalog/pg_class.h" #include "nodes/nodeFuncs.h" #include "optimizer/joininfo.h" #include "optimizer/optimizer.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" +#include "optimizer/placeholder.h" #include "optimizer/planmain.h" #include "optimizer/restrictinfo.h" +#include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" +/* + * Utility structure. A sorting procedure is needed to simplify the search + * of SJE-candidate baserels referencing the same database relation. Having + * collected all baserels from the query jointree, the planner sorts them + * according to the reloid value, groups them with the next pass and attempts + * to remove self-joins. + * + * Preliminary sorting prevents quadratic behavior that can be harmful in the + * case of numerous joins. + */ +typedef struct +{ + int relid; + Oid reloid; +} SelfJoinCandidate; + +bool enable_self_join_elimination; + /* local functions */ static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo); -static void remove_rel_from_query(PlannerInfo *root, int relid, - SpecialJoinInfo *sjinfo); +static void remove_leftjoinrel_from_query(PlannerInfo *root, int relid, + SpecialJoinInfo *sjinfo); static void remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid); static void remove_rel_from_eclass(EquivalenceClass *ec, - int relid, int ojrelid); + SpecialJoinInfo *sjinfo, + int relid, int subst); static List *remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved); static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel); static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, - List *clause_list); + List *clause_list, List **extra_clauses); static Oid distinct_col_search(int colno, List *colnos, List *opids); static bool is_innerrel_unique_for(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, - List *restrictlist); + List *restrictlist, + List **extra_clauses); +static int self_join_candidates_cmp(const void *a, const void *b); +static bool replace_relid_callback(Node *node, + ChangeVarNodes_context *context); /* @@ -87,7 +113,7 @@ remove_useless_joins(PlannerInfo *root, List *joinlist) */ innerrelid = bms_singleton_member(sjinfo->min_righthand); - remove_rel_from_query(root, innerrelid, sjinfo); + remove_leftjoinrel_from_query(root, innerrelid, sjinfo); /* We verify that exactly one reference gets removed from joinlist */ nremoved = 0; @@ -114,37 +140,6 @@ remove_useless_joins(PlannerInfo *root, List *joinlist) return joinlist; } -/* - * clause_sides_match_join - * Determine whether a join clause is of the right form to use in this join. - * - * We already know that the clause is a binary opclause referencing only the - * rels in the current join. The point here is to check whether it has the - * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr", - * rather than mixing outer and inner vars on either side. If it matches, - * we set the transient flag outer_is_left to identify which side is which. - */ -static inline bool -clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids, - Relids innerrelids) -{ - if (bms_is_subset(rinfo->left_relids, outerrelids) && - bms_is_subset(rinfo->right_relids, innerrelids)) - { - /* lefthand side is outer */ - rinfo->outer_is_left = true; - return true; - } - else if (bms_is_subset(rinfo->left_relids, innerrelids) && - bms_is_subset(rinfo->right_relids, outerrelids)) - { - /* righthand side is outer */ - rinfo->outer_is_left = false; - return true; - } - return false; /* no good for these input relations */ -} - /* * join_is_removable * Check whether we need not perform this special join at all, because @@ -306,7 +301,7 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo) * Now that we have the relevant equality join clauses, try to prove the * innerrel distinct. */ - if (rel_is_distinct_for(root, innerrel, clause_list)) + if (rel_is_distinct_for(root, innerrel, clause_list, NULL)) return true; /* @@ -318,66 +313,37 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo) /* - * Remove the target relid and references to the target join from the + * Remove the target rel->relid and references to the target join from the * planner's data structures, having determined that there is no need - * to include them in the query. + * to include them in the query. Optionally replace them with subst if subst + * is non-negative. * - * We are not terribly thorough here. We only bother to update parts of - * the planner's data structures that will actually be consulted later. + * This function updates only parts needed for both left-join removal and + * self-join removal. */ static void -remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) +remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel, + int subst, SpecialJoinInfo *sjinfo, + Relids joinrelids) { - RelOptInfo *rel = find_base_rel(root, relid); - int ojrelid = sjinfo->ojrelid; - Relids joinrelids; - Relids join_plus_commute; - List *joininfos; + int relid = rel->relid; Index rti; ListCell *l; - /* Compute the relid set for the join we are considering */ - joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); - Assert(ojrelid != 0); - joinrelids = bms_add_member(joinrelids, ojrelid); - /* - * Remove references to the rel from other baserels' attr_needed arrays. + * Update all_baserels and related relid sets. */ - for (rti = 1; rti < root->simple_rel_array_size; rti++) - { - RelOptInfo *otherrel = root->simple_rel_array[rti]; - int attroff; - - /* there may be empty slots corresponding to non-baserel RTEs */ - if (otherrel == NULL) - continue; - - Assert(otherrel->relid == rti); /* sanity check on array */ - - /* no point in processing target rel itself */ - if (otherrel == rel) - continue; + root->all_baserels = adjust_relid_set(root->all_baserels, relid, subst); + root->all_query_rels = adjust_relid_set(root->all_query_rels, relid, subst); - for (attroff = otherrel->max_attr - otherrel->min_attr; - attroff >= 0; - attroff--) - { - otherrel->attr_needed[attroff] = - bms_del_member(otherrel->attr_needed[attroff], relid); - otherrel->attr_needed[attroff] = - bms_del_member(otherrel->attr_needed[attroff], ojrelid); - } + if (sjinfo != NULL) + { + root->outer_join_rels = bms_del_member(root->outer_join_rels, + sjinfo->ojrelid); + root->all_query_rels = bms_del_member(root->all_query_rels, + sjinfo->ojrelid); } - /* - * Update all_baserels and related relid sets. - */ - root->all_baserels = bms_del_member(root->all_baserels, relid); - root->outer_join_rels = bms_del_member(root->outer_join_rels, ojrelid); - root->all_query_rels = bms_del_member(root->all_query_rels, relid); - root->all_query_rels = bms_del_member(root->all_query_rels, ojrelid); - /* * Likewise remove references from SpecialJoinInfo data structures. * @@ -400,25 +366,52 @@ remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) sjinf->min_righthand = bms_copy(sjinf->min_righthand); sjinf->syn_lefthand = bms_copy(sjinf->syn_lefthand); sjinf->syn_righthand = bms_copy(sjinf->syn_righthand); - /* Now remove relid and ojrelid bits from the sets: */ - sjinf->min_lefthand = bms_del_member(sjinf->min_lefthand, relid); - sjinf->min_righthand = bms_del_member(sjinf->min_righthand, relid); - sjinf->syn_lefthand = bms_del_member(sjinf->syn_lefthand, relid); - sjinf->syn_righthand = bms_del_member(sjinf->syn_righthand, relid); - sjinf->min_lefthand = bms_del_member(sjinf->min_lefthand, ojrelid); - sjinf->min_righthand = bms_del_member(sjinf->min_righthand, ojrelid); - sjinf->syn_lefthand = bms_del_member(sjinf->syn_lefthand, ojrelid); - sjinf->syn_righthand = bms_del_member(sjinf->syn_righthand, ojrelid); - /* relid cannot appear in these fields, but ojrelid can: */ - sjinf->commute_above_l = bms_del_member(sjinf->commute_above_l, ojrelid); - sjinf->commute_above_r = bms_del_member(sjinf->commute_above_r, ojrelid); - sjinf->commute_below_l = bms_del_member(sjinf->commute_below_l, ojrelid); - sjinf->commute_below_r = bms_del_member(sjinf->commute_below_r, ojrelid); + /* Now remove relid from the sets: */ + sjinf->min_lefthand = adjust_relid_set(sjinf->min_lefthand, relid, subst); + sjinf->min_righthand = adjust_relid_set(sjinf->min_righthand, relid, subst); + sjinf->syn_lefthand = adjust_relid_set(sjinf->syn_lefthand, relid, subst); + sjinf->syn_righthand = adjust_relid_set(sjinf->syn_righthand, relid, subst); + + if (sjinfo != NULL) + { + Assert(subst <= 0); + + /* Remove sjinfo->ojrelid bits from the sets: */ + sjinf->min_lefthand = bms_del_member(sjinf->min_lefthand, + sjinfo->ojrelid); + sjinf->min_righthand = bms_del_member(sjinf->min_righthand, + sjinfo->ojrelid); + sjinf->syn_lefthand = bms_del_member(sjinf->syn_lefthand, + sjinfo->ojrelid); + sjinf->syn_righthand = bms_del_member(sjinf->syn_righthand, + sjinfo->ojrelid); + /* relid cannot appear in these fields, but ojrelid can: */ + sjinf->commute_above_l = bms_del_member(sjinf->commute_above_l, + sjinfo->ojrelid); + sjinf->commute_above_r = bms_del_member(sjinf->commute_above_r, + sjinfo->ojrelid); + sjinf->commute_below_l = bms_del_member(sjinf->commute_below_l, + sjinfo->ojrelid); + sjinf->commute_below_r = bms_del_member(sjinf->commute_below_r, + sjinfo->ojrelid); + } + else + { + Assert(subst > 0); + + ChangeVarNodesExtended((Node *) sjinf->semi_rhs_exprs, relid, subst, + 0, replace_relid_callback); + } } /* * Likewise remove references from PlaceHolderVar data structures, - * removing any no-longer-needed placeholders entirely. + * removing any no-longer-needed placeholders entirely. We remove PHV + * only for left-join removal. With self-join elimination, PHVs already + * get moved to the remaining relation, where they might still be needed. + * It might also happen that we skip the removal of some PHVs that could + * be removed. However, the overhead of extra PHVs is small compared to + * the complexity of analysis needed to remove them. * * Removal is a bit trickier than it might seem: we can remove PHVs that * are used at the target rel and/or in the join qual, but not those that @@ -434,11 +427,17 @@ remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l); - Assert(!bms_is_member(relid, phinfo->ph_lateral)); - if (bms_is_subset(phinfo->ph_needed, joinrelids) && + Assert(sjinfo == NULL || !bms_is_member(relid, phinfo->ph_lateral)); + if (sjinfo != NULL && + bms_is_subset(phinfo->ph_needed, joinrelids) && bms_is_member(relid, phinfo->ph_eval_at) && - !bms_is_member(ojrelid, phinfo->ph_eval_at)) + !bms_is_member(sjinfo->ojrelid, phinfo->ph_eval_at)) { + /* + * This code shouldn't be executed if one relation is substituted + * with another: in this case, the placeholder may be employed in + * a filter inside the scan node the SJE removes. + */ root->placeholder_list = foreach_delete_current(root->placeholder_list, l); root->placeholder_array[phinfo->phid] = NULL; @@ -447,19 +446,118 @@ remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) { PlaceHolderVar *phv = phinfo->ph_var; - phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at, relid); - phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at, ojrelid); + phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at, relid, subst); + if (sjinfo != NULL) + phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at, + sjinfo->ojrelid, subst); Assert(!bms_is_empty(phinfo->ph_eval_at)); /* checked previously */ - phinfo->ph_needed = bms_del_member(phinfo->ph_needed, relid); - phinfo->ph_needed = bms_del_member(phinfo->ph_needed, ojrelid); - /* ph_needed might or might not become empty */ - phv->phrels = bms_del_member(phv->phrels, relid); - phv->phrels = bms_del_member(phv->phrels, ojrelid); + /* Reduce ph_needed to contain only "relation 0"; see below */ + if (bms_is_member(0, phinfo->ph_needed)) + phinfo->ph_needed = bms_make_singleton(0); + else + phinfo->ph_needed = NULL; + + phinfo->ph_lateral = adjust_relid_set(phinfo->ph_lateral, relid, subst); + + /* + * ph_lateral might contain rels mentioned in ph_eval_at after the + * replacement, remove them. + */ + phinfo->ph_lateral = bms_difference(phinfo->ph_lateral, phinfo->ph_eval_at); + /* ph_lateral might or might not be empty */ + + phv->phrels = adjust_relid_set(phv->phrels, relid, subst); + if (sjinfo != NULL) + phv->phrels = adjust_relid_set(phv->phrels, + sjinfo->ojrelid, subst); Assert(!bms_is_empty(phv->phrels)); + + ChangeVarNodesExtended((Node *) phv->phexpr, relid, subst, 0, + replace_relid_callback); + Assert(phv->phnullingrels == NULL); /* no need to adjust */ } } + /* + * Likewise remove references from EquivalenceClasses. + */ + foreach(l, root->eq_classes) + { + EquivalenceClass *ec = (EquivalenceClass *) lfirst(l); + + if (bms_is_member(relid, ec->ec_relids) || + (sjinfo == NULL || bms_is_member(sjinfo->ojrelid, ec->ec_relids))) + remove_rel_from_eclass(ec, sjinfo, relid, subst); + } + + /* + * Finally, we must recompute per-Var attr_needed and per-PlaceHolderVar + * ph_needed relid sets. These have to be known accurately, else we may + * fail to remove other now-removable outer joins. And our removal of the + * join clause(s) for this outer join may mean that Vars that were + * formerly needed no longer are. So we have to do this honestly by + * repeating the construction of those relid sets. We can cheat to one + * small extent: we can avoid re-examining the targetlist and HAVING qual + * by preserving "relation 0" bits from the existing relid sets. This is + * safe because we'd never remove such references. + * + * So, start by removing all other bits from attr_needed sets and + * lateral_vars lists. (We already did this above for ph_needed.) + */ + for (rti = 1; rti < root->simple_rel_array_size; rti++) + { + RelOptInfo *otherrel = root->simple_rel_array[rti]; + int attroff; + + /* there may be empty slots corresponding to non-baserel RTEs */ + if (otherrel == NULL) + continue; + + Assert(otherrel->relid == rti); /* sanity check on array */ + + for (attroff = otherrel->max_attr - otherrel->min_attr; + attroff >= 0; + attroff--) + { + if (bms_is_member(0, otherrel->attr_needed[attroff])) + otherrel->attr_needed[attroff] = bms_make_singleton(0); + else + otherrel->attr_needed[attroff] = NULL; + } + + if (subst > 0) + ChangeVarNodesExtended((Node *) otherrel->lateral_vars, relid, + subst, 0, replace_relid_callback); + } +} + +/* + * Remove the target relid and references to the target join from the + * planner's data structures, having determined that there is no need + * to include them in the query. + * + * We are not terribly thorough here. We only bother to update parts of + * the planner's data structures that will actually be consulted later. + */ +static void +remove_leftjoinrel_from_query(PlannerInfo *root, int relid, + SpecialJoinInfo *sjinfo) +{ + RelOptInfo *rel = find_base_rel(root, relid); + int ojrelid = sjinfo->ojrelid; + Relids joinrelids; + Relids join_plus_commute; + List *joininfos; + ListCell *l; + + /* Compute the relid set for the join we are considering */ + joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand); + Assert(ojrelid != 0); + joinrelids = bms_add_member(joinrelids, ojrelid); + + remove_rel_from_query(root, rel, -1, sjinfo, joinrelids); + /* * Remove any joinquals referencing the rel from the joininfo lists. * @@ -522,25 +620,13 @@ remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) } } - /* - * Likewise remove references from EquivalenceClasses. - */ - foreach(l, root->eq_classes) - { - EquivalenceClass *ec = (EquivalenceClass *) lfirst(l); - - if (bms_is_member(relid, ec->ec_relids) || - bms_is_member(ojrelid, ec->ec_relids)) - remove_rel_from_eclass(ec, relid, ojrelid); - } - /* * There may be references to the rel in root->fkey_list, but if so, * match_foreign_keys_to_quals() will get rid of them. */ /* - * Finally, remove the rel from the baserel array to prevent it from being + * Now remove the rel from the baserel array to prevent it from being * referenced again. (We can't do this earlier because * remove_join_clause_from_rels will touch it.) */ @@ -548,6 +634,15 @@ remove_rel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo) /* And nuke the RelOptInfo, just in case there's another access path */ pfree(rel); + + /* + * Now repeat construction of attr_needed bits coming from all other + * sources. + */ + rebuild_placeholder_attr_needed(root); + rebuild_joinclause_attr_needed(root); + rebuild_eclass_attr_needed(root); + rebuild_lateral_attr_needed(root); } /* @@ -610,7 +705,8 @@ remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid) } /* - * Remove any references to relid or ojrelid from the EquivalenceClass. + * Remove any references to relid or sjinfo->ojrelid (if sjinfo != NULL) + * from the EquivalenceClass. * * Like remove_rel_from_restrictinfo, we don't worry about cleaning out * any nullingrel bits in contained Vars and PHVs. (This might have to be @@ -619,13 +715,23 @@ remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid) * level(s). */ static void -remove_rel_from_eclass(EquivalenceClass *ec, int relid, int ojrelid) +remove_rel_from_eclass(EquivalenceClass *ec, SpecialJoinInfo *sjinfo, + int relid, int subst) { ListCell *lc; /* Fix up the EC's overall relids */ - ec->ec_relids = bms_del_member(ec->ec_relids, relid); - ec->ec_relids = bms_del_member(ec->ec_relids, ojrelid); + ec->ec_relids = adjust_relid_set(ec->ec_relids, relid, subst); + if (sjinfo != NULL) + ec->ec_relids = adjust_relid_set(ec->ec_relids, + sjinfo->ojrelid, subst); + + /* + * We don't expect any EC child members to exist at this point. Ensure + * that's the case, otherwise, we might be getting asked to do something + * this function hasn't been coded for. + */ + Assert(ec->ec_childmembers == NULL); /* * Fix up the member expressions. Any non-const member that ends with @@ -637,11 +743,14 @@ remove_rel_from_eclass(EquivalenceClass *ec, int relid, int ojrelid) EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc); if (bms_is_member(relid, cur_em->em_relids) || - bms_is_member(ojrelid, cur_em->em_relids)) + (sjinfo != NULL && bms_is_member(sjinfo->ojrelid, + cur_em->em_relids))) { Assert(!cur_em->em_is_const); - cur_em->em_relids = bms_del_member(cur_em->em_relids, relid); - cur_em->em_relids = bms_del_member(cur_em->em_relids, ojrelid); + cur_em->em_relids = adjust_relid_set(cur_em->em_relids, relid, subst); + if (sjinfo != NULL) + cur_em->em_relids = adjust_relid_set(cur_em->em_relids, + sjinfo->ojrelid, subst); if (bms_is_empty(cur_em->em_relids)) ec->ec_members = foreach_delete_current(ec->ec_members, lc); } @@ -652,7 +761,11 @@ remove_rel_from_eclass(EquivalenceClass *ec, int relid, int ojrelid) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); - remove_rel_from_restrictinfo(rinfo, relid, ojrelid); + if (sjinfo == NULL) + ChangeVarNodesExtended((Node *) rinfo, relid, subst, 0, + replace_relid_callback); + else + remove_rel_from_restrictinfo(rinfo, relid, sjinfo->ojrelid); } /* @@ -660,7 +773,7 @@ remove_rel_from_eclass(EquivalenceClass *ec, int relid, int ojrelid) * drop them. (At this point, any such clauses would be base restriction * clauses, which we'd not need anymore anyway.) */ - ec->ec_derives = NIL; + ec_clear_derived_clauses(ec); } /* @@ -856,9 +969,15 @@ rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel) * Note that the passed-in clause_list may be destructively modified! This * is OK for current uses, because the clause_list is built by the caller for * the sole purpose of passing to this function. + * + * (*extra_clauses) to be set to the right sides of baserestrictinfo clauses, + * looking like "x = const" if distinctness is derived from such clauses, not + * joininfo clauses. Pass NULL to the extra_clauses if this value is not + * needed. */ static bool -rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list) +rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list, + List **extra_clauses) { /* * We could skip a couple of tests here if we assume all callers checked @@ -871,10 +990,11 @@ rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list) { /* * Examine the indexes to see if we have a matching unique index. - * relation_has_unique_index_for automatically adds any usable + * relation_has_unique_index_ext automatically adds any usable * restriction clauses for the rel, so we needn't do that here. */ - if (relation_has_unique_index_for(root, rel, clause_list, NIL, NIL)) + if (relation_has_unique_index_ext(root, rel, clause_list, NIL, NIL, + extra_clauses)) return true; } else if (rel->rtekind == RTE_SUBQUERY) @@ -987,9 +1107,10 @@ query_supports_distinctness(Query *query) * the values are distinct. (Note: the opids entries could be cross-type * operators, and thus not exactly the equality operators that the subquery * would use itself. We use equality_ops_are_compatible() to check - * compatibility. That looks at btree or hash opfamily membership, and so - * should give trustworthy answers for all operators that we might need - * to deal with here.) + * compatibility. That looks at opfamily membership for index AMs that have + * declared that they support consistent equality semantics within an + * opfamily, and so should give trustworthy answers for all operators that we + * might need to deal with here.) */ bool query_is_distinct_for(Query *query, List *colnos, List *opids) @@ -1188,9 +1309,35 @@ innerrel_is_unique(PlannerInfo *root, JoinType jointype, List *restrictlist, bool force_cache) +{ + return innerrel_is_unique_ext(root, joinrelids, outerrelids, innerrel, + jointype, restrictlist, force_cache, NULL); +} + +/* + * innerrel_is_unique_ext + * Do the same as innerrel_is_unique(), but also set to (*extra_clauses) + * additional clauses from a baserestrictinfo list used to prove the + * uniqueness. + * + * A non-NULL extra_clauses indicates that we're checking for self-join and + * correspondingly dealing with filtered clauses. + */ +bool +innerrel_is_unique_ext(PlannerInfo *root, + Relids joinrelids, + Relids outerrelids, + RelOptInfo *innerrel, + JoinType jointype, + List *restrictlist, + bool force_cache, + List **extra_clauses) { MemoryContext old_context; ListCell *lc; + UniqueRelInfo *uniqueRelInfo; + List *outer_exprs = NIL; + bool self_join = (extra_clauses != NULL); /* Certainly can't prove uniqueness when there are no joinclauses */ if (restrictlist == NIL) @@ -1205,17 +1352,28 @@ innerrel_is_unique(PlannerInfo *root, /* * Query the cache to see if we've managed to prove that innerrel is - * unique for any subset of this outerrel. We don't need an exact match, - * as extra outerrels can't make the innerrel any less unique (or more - * formally, the restrictlist for a join to a superset outerrel must be a - * superset of the conditions we successfully used before). + * unique for any subset of this outerrel. For non-self-join search, we + * don't need an exact match, as extra outerrels can't make the innerrel + * any less unique (or more formally, the restrictlist for a join to a + * superset outerrel must be a superset of the conditions we successfully + * used before). For self-join search, we require an exact match of + * outerrels because we need extra clauses to be valid for our case. Also, + * for self-join checking we've filtered the clauses list. Thus, we can + * match only the result cached for a self-join search for another + * self-join check. */ foreach(lc, innerrel->unique_for_rels) { - Relids unique_for_rels = (Relids) lfirst(lc); + uniqueRelInfo = (UniqueRelInfo *) lfirst(lc); - if (bms_is_subset(unique_for_rels, outerrelids)) + if ((!self_join && bms_is_subset(uniqueRelInfo->outerrelids, outerrelids)) || + (self_join && bms_equal(uniqueRelInfo->outerrelids, outerrelids) && + uniqueRelInfo->self_join)) + { + if (extra_clauses) + *extra_clauses = uniqueRelInfo->extra_clauses; return true; /* Success! */ + } } /* @@ -1232,7 +1390,8 @@ innerrel_is_unique(PlannerInfo *root, /* No cached information, so try to make the proof. */ if (is_innerrel_unique_for(root, joinrelids, outerrelids, innerrel, - jointype, restrictlist)) + jointype, restrictlist, + self_join ? &outer_exprs : NULL)) { /* * Cache the positive result for future probes, being sure to keep it @@ -1245,10 +1404,16 @@ innerrel_is_unique(PlannerInfo *root, * supersets of them anyway. */ old_context = MemoryContextSwitchTo(root->planner_cxt); + uniqueRelInfo = makeNode(UniqueRelInfo); + uniqueRelInfo->outerrelids = bms_copy(outerrelids); + uniqueRelInfo->self_join = self_join; + uniqueRelInfo->extra_clauses = outer_exprs; innerrel->unique_for_rels = lappend(innerrel->unique_for_rels, - bms_copy(outerrelids)); + uniqueRelInfo); MemoryContextSwitchTo(old_context); + if (extra_clauses) + *extra_clauses = outer_exprs; return true; /* Success! */ } else @@ -1294,7 +1459,8 @@ is_innerrel_unique_for(PlannerInfo *root, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, - List *restrictlist) + List *restrictlist, + List **extra_clauses) { List *clause_list = NIL; ListCell *lc; @@ -1324,17 +1490,1025 @@ is_innerrel_unique_for(PlannerInfo *root, continue; /* not mergejoinable */ /* - * Check if clause has the form "outer op inner" or "inner op outer", - * and if so mark which side is inner. + * Check if the clause has the form "outer op inner" or "inner op + * outer", and if so mark which side is inner. */ if (!clause_sides_match_join(restrictinfo, outerrelids, innerrel->relids)) continue; /* no good for these input relations */ - /* OK, add to list */ + /* OK, add to the list */ clause_list = lappend(clause_list, restrictinfo); } /* Let rel_is_distinct_for() do the hard work */ - return rel_is_distinct_for(root, innerrel, clause_list); + return rel_is_distinct_for(root, innerrel, clause_list, extra_clauses); +} + +/* + * Update EC members to point to the remaining relation instead of the removed + * one, removing duplicates. + * + * Restriction clauses for base relations are already distributed to + * the respective baserestrictinfo lists (see + * generate_implied_equalities_for_column). The above code has already processed + * this list and updated these clauses to reference the remaining + * relation, so that we can skip them here based on their relids. + * + * Likewise, we have already processed the join clauses that join the + * removed relation to the remaining one. + * + * Finally, there might be join clauses tying the removed relation to + * some third relation. We can't just delete the source clauses and + * regenerate them from the EC because the corresponding equality + * operators might be missing (see the handling of ec_broken). + * Therefore, we will update the references in the source clauses. + * + * Derived clauses can be generated again, so it is simpler just to + * delete them. + */ +static void +update_eclasses(EquivalenceClass *ec, int from, int to) +{ + List *new_members = NIL; + List *new_sources = NIL; + + /* + * We don't expect any EC child members to exist at this point. Ensure + * that's the case, otherwise, we might be getting asked to do something + * this function hasn't been coded for. + */ + Assert(ec->ec_childmembers == NULL); + + foreach_node(EquivalenceMember, em, ec->ec_members) + { + bool is_redundant = false; + + if (!bms_is_member(from, em->em_relids)) + { + new_members = lappend(new_members, em); + continue; + } + + em->em_relids = adjust_relid_set(em->em_relids, from, to); + em->em_jdomain->jd_relids = adjust_relid_set(em->em_jdomain->jd_relids, from, to); + + /* We only process inner joins */ + ChangeVarNodesExtended((Node *) em->em_expr, from, to, 0, + replace_relid_callback); + + foreach_node(EquivalenceMember, other, new_members) + { + if (!equal(em->em_relids, other->em_relids)) + continue; + + if (equal(em->em_expr, other->em_expr)) + { + is_redundant = true; + break; + } + } + + if (!is_redundant) + new_members = lappend(new_members, em); + } + + list_free(ec->ec_members); + ec->ec_members = new_members; + + ec_clear_derived_clauses(ec); + + /* Update EC source expressions */ + foreach_node(RestrictInfo, rinfo, ec->ec_sources) + { + bool is_redundant = false; + + if (!bms_is_member(from, rinfo->required_relids)) + { + new_sources = lappend(new_sources, rinfo); + continue; + } + + ChangeVarNodesExtended((Node *) rinfo, from, to, 0, + replace_relid_callback); + + /* + * After switching the clause to the remaining relation, check it for + * redundancy with existing ones. We don't have to check for + * redundancy with derived clauses, because we've just deleted them. + */ + foreach_node(RestrictInfo, other, new_sources) + { + if (!equal(rinfo->clause_relids, other->clause_relids)) + continue; + + if (equal(rinfo->clause, other->clause)) + { + is_redundant = true; + break; + } + } + + if (!is_redundant) + new_sources = lappend(new_sources, rinfo); + } + + list_free(ec->ec_sources); + ec->ec_sources = new_sources; + ec->ec_relids = adjust_relid_set(ec->ec_relids, from, to); +} + +/* + * "Logically" compares two RestrictInfo's ignoring the 'rinfo_serial' field, + * which makes almost every RestrictInfo unique. This type of comparison is + * useful when removing duplicates while moving RestrictInfo's from removed + * relation to remaining relation during self-join elimination. + * + * XXX: In the future, we might remove the 'rinfo_serial' field completely and + * get rid of this function. + */ +static bool +restrict_infos_logically_equal(RestrictInfo *a, RestrictInfo *b) +{ + int saved_rinfo_serial = a->rinfo_serial; + bool result; + + a->rinfo_serial = b->rinfo_serial; + result = equal(a, b); + a->rinfo_serial = saved_rinfo_serial; + + return result; +} + +/* + * This function adds all non-redundant clauses to the keeping relation + * during self-join elimination. That is a contradictory operation. On the + * one hand, we reduce the length of the `restrict` lists, which can + * impact planning or executing time. Additionally, we improve the + * accuracy of cardinality estimation. On the other hand, it is one more + * place that can make planning time much longer in specific cases. It + * would have been better to avoid calling the equal() function here, but + * it's the only way to detect duplicated inequality expressions. + * + * (*keep_rinfo_list) is given by pointer because it might be altered by + * distribute_restrictinfo_to_rels(). + */ +static void +add_non_redundant_clauses(PlannerInfo *root, + List *rinfo_candidates, + List **keep_rinfo_list, + Index removed_relid) +{ + foreach_node(RestrictInfo, rinfo, rinfo_candidates) + { + bool is_redundant = false; + + Assert(!bms_is_member(removed_relid, rinfo->required_relids)); + + foreach_node(RestrictInfo, src, (*keep_rinfo_list)) + { + if (!bms_equal(src->clause_relids, rinfo->clause_relids)) + /* Can't compare trivially different clauses */ + continue; + + if (src == rinfo || + (rinfo->parent_ec != NULL && + src->parent_ec == rinfo->parent_ec) || + restrict_infos_logically_equal(rinfo, src)) + { + is_redundant = true; + break; + } + } + if (!is_redundant) + distribute_restrictinfo_to_rels(root, rinfo); + } +} + +/* + * A custom callback for ChangeVarNodesExtended() providing + * Self-join elimination (SJE) related functionality + * + * SJE needs to skip the RangeTblRef node + * type. During SJE's last step, remove_rel_from_joinlist() removes + * remaining RangeTblRefs with target relid. If ChangeVarNodes() replaces + * the target relid before, remove_rel_from_joinlist() fails to identify + * the nodes to delete. + * + * SJE also needs to change the relids within RestrictInfo's. + */ +static bool +replace_relid_callback(Node *node, ChangeVarNodes_context *context) +{ + if (IsA(node, RangeTblRef)) + { + return true; + } + else if (IsA(node, RestrictInfo)) + { + RestrictInfo *rinfo = (RestrictInfo *) node; + int relid = -1; + bool is_req_equal = + (rinfo->required_relids == rinfo->clause_relids); + bool clause_relids_is_multiple = + (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE); + + /* + * Recurse down into clauses if the target relation is present in + * clause_relids or required_relids. We must check required_relids + * because the relation not present in clause_relids might still be + * present somewhere in orclause. + */ + if (bms_is_member(context->rt_index, rinfo->clause_relids) || + bms_is_member(context->rt_index, rinfo->required_relids)) + { + Relids new_clause_relids; + + ChangeVarNodesWalkExpression((Node *) rinfo->clause, context); + ChangeVarNodesWalkExpression((Node *) rinfo->orclause, context); + + new_clause_relids = adjust_relid_set(rinfo->clause_relids, + context->rt_index, + context->new_index); + + /* + * Incrementally adjust num_base_rels based on the change of + * clause_relids, which could contain both base relids and + * outer-join relids. This operation is legal until we remove + * only baserels. + */ + rinfo->num_base_rels -= bms_num_members(rinfo->clause_relids) - + bms_num_members(new_clause_relids); + + rinfo->clause_relids = new_clause_relids; + rinfo->left_relids = + adjust_relid_set(rinfo->left_relids, context->rt_index, context->new_index); + rinfo->right_relids = + adjust_relid_set(rinfo->right_relids, context->rt_index, context->new_index); + } + + if (is_req_equal) + rinfo->required_relids = rinfo->clause_relids; + else + rinfo->required_relids = + adjust_relid_set(rinfo->required_relids, context->rt_index, context->new_index); + + rinfo->outer_relids = + adjust_relid_set(rinfo->outer_relids, context->rt_index, context->new_index); + rinfo->incompatible_relids = + adjust_relid_set(rinfo->incompatible_relids, context->rt_index, context->new_index); + + if (rinfo->mergeopfamilies && + bms_get_singleton_member(rinfo->clause_relids, &relid) && + clause_relids_is_multiple && + relid == context->new_index && IsA(rinfo->clause, OpExpr)) + { + Expr *leftOp; + Expr *rightOp; + + leftOp = (Expr *) get_leftop(rinfo->clause); + rightOp = (Expr *) get_rightop(rinfo->clause); + + /* + * For self-join elimination, changing varnos could transform + * "t1.a = t2.a" into "t1.a = t1.a". That is always true as long + * as "t1.a" is not null. We use qual() to check for such a case, + * and then we replace the qual for a check for not null + * (NullTest). + */ + if (leftOp != NULL && equal(leftOp, rightOp)) + { + NullTest *ntest = makeNode(NullTest); + + ntest->arg = leftOp; + ntest->nulltesttype = IS_NOT_NULL; + ntest->argisrow = false; + ntest->location = -1; + rinfo->clause = (Expr *) ntest; + rinfo->mergeopfamilies = NIL; + rinfo->left_em = NULL; + rinfo->right_em = NULL; + } + Assert(rinfo->orclause == NULL); + } + return true; + } + + return false; +} + +/* + * Remove a relation after we have proven that it participates only in an + * unneeded unique self-join. + * + * Replace any links in planner info structures. + * + * Transfer join and restriction clauses from the removed relation to the + * remaining one. We change the Vars of the clause to point to the + * remaining relation instead of the removed one. The clauses that require + * a subset of joinrelids become restriction clauses of the remaining + * relation, and others remain join clauses. We append them to + * baserestrictinfo and joininfo, respectively, trying not to introduce + * duplicates. + * + * We also have to process the 'joinclauses' list here, because it + * contains EC-derived join clauses which must become filter clauses. It + * is not enough to just correct the ECs because the EC-derived + * restrictions are generated before join removal (see + * generate_base_implied_equalities). + * + * NOTE: Remember to keep the code in sync with PlannerInfo to be sure all + * cached relids and relid bitmapsets can be correctly cleaned during the + * self-join elimination procedure. + */ +static void +remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark, + RelOptInfo *toKeep, RelOptInfo *toRemove, + List *restrictlist) +{ + List *joininfos; + ListCell *lc; + int i; + List *jinfo_candidates = NIL; + List *binfo_candidates = NIL; + + Assert(toKeep->relid > 0); + Assert(toRemove->relid > 0); + + /* + * Replace the index of the removing table with the keeping one. The + * technique of removing/distributing restrictinfo is used here to attach + * just appeared (for keeping relation) join clauses and avoid adding + * duplicates of those that already exist in the joininfo list. + */ + joininfos = list_copy(toRemove->joininfo); + foreach_node(RestrictInfo, rinfo, joininfos) + { + remove_join_clause_from_rels(root, rinfo, rinfo->required_relids); + ChangeVarNodesExtended((Node *) rinfo, toRemove->relid, toKeep->relid, + 0, replace_relid_callback); + + if (bms_membership(rinfo->required_relids) == BMS_MULTIPLE) + jinfo_candidates = lappend(jinfo_candidates, rinfo); + else + binfo_candidates = lappend(binfo_candidates, rinfo); + } + + /* + * Concatenate restrictlist to the list of base restrictions of the + * removing table just to simplify the replacement procedure: all of them + * weren't connected to any keeping relations and need to be added to some + * rels. + */ + toRemove->baserestrictinfo = list_concat(toRemove->baserestrictinfo, + restrictlist); + foreach_node(RestrictInfo, rinfo, toRemove->baserestrictinfo) + { + ChangeVarNodesExtended((Node *) rinfo, toRemove->relid, toKeep->relid, + 0, replace_relid_callback); + + if (bms_membership(rinfo->required_relids) == BMS_MULTIPLE) + jinfo_candidates = lappend(jinfo_candidates, rinfo); + else + binfo_candidates = lappend(binfo_candidates, rinfo); + } + + /* + * Now, add all non-redundant clauses to the keeping relation. + */ + add_non_redundant_clauses(root, binfo_candidates, + &toKeep->baserestrictinfo, toRemove->relid); + add_non_redundant_clauses(root, jinfo_candidates, + &toKeep->joininfo, toRemove->relid); + + list_free(binfo_candidates); + list_free(jinfo_candidates); + + /* + * Arrange equivalence classes, mentioned removing a table, with the + * keeping one: varno of removing table should be replaced in members and + * sources lists. Also, remove duplicated elements if this replacement + * procedure created them. + */ + i = -1; + while ((i = bms_next_member(toRemove->eclass_indexes, i)) >= 0) + { + EquivalenceClass *ec = (EquivalenceClass *) list_nth(root->eq_classes, i); + + update_eclasses(ec, toRemove->relid, toKeep->relid); + toKeep->eclass_indexes = bms_add_member(toKeep->eclass_indexes, i); + } + + /* + * Transfer the targetlist and attr_needed flags. + */ + + foreach(lc, toRemove->reltarget->exprs) + { + Node *node = lfirst(lc); + + ChangeVarNodesExtended(node, toRemove->relid, toKeep->relid, 0, + replace_relid_callback); + if (!list_member(toKeep->reltarget->exprs, node)) + toKeep->reltarget->exprs = lappend(toKeep->reltarget->exprs, node); + } + + for (i = toKeep->min_attr; i <= toKeep->max_attr; i++) + { + int attno = i - toKeep->min_attr; + + toRemove->attr_needed[attno] = adjust_relid_set(toRemove->attr_needed[attno], + toRemove->relid, toKeep->relid); + toKeep->attr_needed[attno] = bms_add_members(toKeep->attr_needed[attno], + toRemove->attr_needed[attno]); + } + + /* + * If the removed relation has a row mark, transfer it to the remaining + * one. + * + * If both rels have row marks, just keep the one corresponding to the + * remaining relation because we verified earlier that they have the same + * strength. + */ + if (rmark) + { + if (kmark) + { + Assert(kmark->markType == rmark->markType); + + root->rowMarks = list_delete_ptr(root->rowMarks, rmark); + } + else + { + /* Shouldn't have inheritance children here. */ + Assert(rmark->rti == rmark->prti); + + rmark->rti = rmark->prti = toKeep->relid; + } + } + + /* + * Replace varno in all the query structures, except nodes RangeTblRef + * otherwise later remove_rel_from_joinlist will yield errors. + */ + ChangeVarNodesExtended((Node *) root->parse, toRemove->relid, toKeep->relid, + 0, replace_relid_callback); + + /* Replace links in the planner info */ + remove_rel_from_query(root, toRemove, toKeep->relid, NULL, NULL); + + /* At last, replace varno in root targetlist and HAVING clause */ + ChangeVarNodesExtended((Node *) root->processed_tlist, toRemove->relid, + toKeep->relid, 0, replace_relid_callback); + ChangeVarNodesExtended((Node *) root->processed_groupClause, + toRemove->relid, toKeep->relid, 0, + replace_relid_callback); + + adjust_relid_set(root->all_result_relids, toRemove->relid, toKeep->relid); + adjust_relid_set(root->leaf_result_relids, toRemove->relid, toKeep->relid); + + /* + * There may be references to the rel in root->fkey_list, but if so, + * match_foreign_keys_to_quals() will get rid of them. + */ + + /* + * Finally, remove the rel from the baserel array to prevent it from being + * referenced again. (We can't do this earlier because + * remove_join_clause_from_rels will touch it.) + */ + root->simple_rel_array[toRemove->relid] = NULL; + + /* And nuke the RelOptInfo, just in case there's another access path. */ + pfree(toRemove); + + /* + * Now repeat construction of attr_needed bits coming from all other + * sources. + */ + rebuild_placeholder_attr_needed(root); + rebuild_joinclause_attr_needed(root); + rebuild_eclass_attr_needed(root); + rebuild_lateral_attr_needed(root); +} + +/* + * split_selfjoin_quals + * Processes 'joinquals' by building two lists: one containing the quals + * where the columns/exprs are on either side of the join match and + * another one containing the remaining quals. + * + * 'joinquals' must only contain quals for a RTE_RELATION being joined to + * itself. + */ +static void +split_selfjoin_quals(PlannerInfo *root, List *joinquals, List **selfjoinquals, + List **otherjoinquals, int from, int to) +{ + List *sjoinquals = NIL; + List *ojoinquals = NIL; + + foreach_node(RestrictInfo, rinfo, joinquals) + { + OpExpr *expr; + Node *leftexpr; + Node *rightexpr; + + /* In general, clause looks like F(arg1) = G(arg2) */ + if (!rinfo->mergeopfamilies || + bms_num_members(rinfo->clause_relids) != 2 || + bms_membership(rinfo->left_relids) != BMS_SINGLETON || + bms_membership(rinfo->right_relids) != BMS_SINGLETON) + { + ojoinquals = lappend(ojoinquals, rinfo); + continue; + } + + expr = (OpExpr *) rinfo->clause; + + if (!IsA(expr, OpExpr) || list_length(expr->args) != 2) + { + ojoinquals = lappend(ojoinquals, rinfo); + continue; + } + + leftexpr = get_leftop(rinfo->clause); + rightexpr = copyObject(get_rightop(rinfo->clause)); + + if (leftexpr && IsA(leftexpr, RelabelType)) + leftexpr = (Node *) ((RelabelType *) leftexpr)->arg; + if (rightexpr && IsA(rightexpr, RelabelType)) + rightexpr = (Node *) ((RelabelType *) rightexpr)->arg; + + /* + * Quite an expensive operation, narrowing the use case. For example, + * when we have cast of the same var to different (but compatible) + * types. + */ + ChangeVarNodesExtended(rightexpr, + bms_singleton_member(rinfo->right_relids), + bms_singleton_member(rinfo->left_relids), 0, + replace_relid_callback); + + if (equal(leftexpr, rightexpr)) + sjoinquals = lappend(sjoinquals, rinfo); + else + ojoinquals = lappend(ojoinquals, rinfo); + } + + *selfjoinquals = sjoinquals; + *otherjoinquals = ojoinquals; +} + +/* + * Check for a case when uniqueness is at least partly derived from a + * baserestrictinfo clause. In this case, we have a chance to return only + * one row (if such clauses on both sides of SJ are equal) or nothing (if they + * are different). + */ +static bool +match_unique_clauses(PlannerInfo *root, RelOptInfo *outer, List *uclauses, + Index relid) +{ + foreach_node(RestrictInfo, rinfo, uclauses) + { + Expr *clause; + Node *iclause; + Node *c1; + bool matched = false; + + Assert(outer->relid > 0 && relid > 0); + + /* Only filters like f(R.x1,...,R.xN) == expr we should consider. */ + Assert(bms_is_empty(rinfo->left_relids) ^ + bms_is_empty(rinfo->right_relids)); + + clause = (Expr *) copyObject(rinfo->clause); + ChangeVarNodesExtended((Node *) clause, relid, outer->relid, 0, + replace_relid_callback); + + iclause = bms_is_empty(rinfo->left_relids) ? get_rightop(clause) : + get_leftop(clause); + c1 = bms_is_empty(rinfo->left_relids) ? get_leftop(clause) : + get_rightop(clause); + + /* + * Compare these left and right sides with the corresponding sides of + * the outer's filters. If no one is detected - return immediately. + */ + foreach_node(RestrictInfo, orinfo, outer->baserestrictinfo) + { + Node *oclause; + Node *c2; + + if (orinfo->mergeopfamilies == NIL) + /* Don't consider clauses that aren't similar to 'F(X)=G(Y)' */ + continue; + + Assert(is_opclause(orinfo->clause)); + + oclause = bms_is_empty(orinfo->left_relids) ? + get_rightop(orinfo->clause) : get_leftop(orinfo->clause); + c2 = (bms_is_empty(orinfo->left_relids) ? + get_leftop(orinfo->clause) : get_rightop(orinfo->clause)); + + if (equal(iclause, oclause) && equal(c1, c2)) + { + matched = true; + break; + } + } + + if (!matched) + return false; + } + + return true; +} + +/* + * Find and remove unique self-joins in a group of base relations that have + * the same Oid. + * + * Returns a set of relids that were removed. + */ +static Relids +remove_self_joins_one_group(PlannerInfo *root, Relids relids) +{ + Relids result = NULL; + int k; /* Index of kept relation */ + int r = -1; /* Index of removed relation */ + + while ((r = bms_next_member(relids, r)) > 0) + { + RelOptInfo *inner = root->simple_rel_array[r]; + + k = r; + + while ((k = bms_next_member(relids, k)) > 0) + { + Relids joinrelids = NULL; + RelOptInfo *outer = root->simple_rel_array[k]; + List *restrictlist; + List *selfjoinquals; + List *otherjoinquals; + ListCell *lc; + bool jinfo_check = true; + PlanRowMark *omark = NULL; + PlanRowMark *imark = NULL; + List *uclauses = NIL; + + /* A sanity check: the relations have the same Oid. */ + Assert(root->simple_rte_array[k]->relid == + root->simple_rte_array[r]->relid); + + /* + * It is impossible to eliminate the join of two relations if they + * belong to different rules of order. Otherwise, the planner + * can't find any variants of the correct query plan. + */ + foreach(lc, root->join_info_list) + { + SpecialJoinInfo *info = (SpecialJoinInfo *) lfirst(lc); + + if ((bms_is_member(k, info->syn_lefthand) ^ + bms_is_member(r, info->syn_lefthand)) || + (bms_is_member(k, info->syn_righthand) ^ + bms_is_member(r, info->syn_righthand))) + { + jinfo_check = false; + break; + } + } + if (!jinfo_check) + continue; + + /* + * Check Row Marks equivalence. We can't remove the join if the + * relations have row marks of different strength (e.g., one is + * locked FOR UPDATE, and another just has ROW_MARK_REFERENCE for + * EvalPlanQual rechecking). + */ + foreach(lc, root->rowMarks) + { + PlanRowMark *rowMark = (PlanRowMark *) lfirst(lc); + + if (rowMark->rti == k) + { + Assert(imark == NULL); + imark = rowMark; + } + else if (rowMark->rti == r) + { + Assert(omark == NULL); + omark = rowMark; + } + + if (omark && imark) + break; + } + if (omark && imark && omark->markType != imark->markType) + continue; + + /* + * We only deal with base rels here, so their relids bitset + * contains only one member -- their relid. + */ + joinrelids = bms_add_member(joinrelids, r); + joinrelids = bms_add_member(joinrelids, k); + + /* + * PHVs should not impose any constraints on removing self-joins. + */ + + /* + * At this stage, joininfo lists of inner and outer can contain + * only clauses required for a superior outer join that can't + * influence this optimization. So, we can avoid to call the + * build_joinrel_restrictlist() routine. + */ + restrictlist = generate_join_implied_equalities(root, joinrelids, + inner->relids, + outer, NULL); + if (restrictlist == NIL) + continue; + + /* + * Process restrictlist to separate the self-join quals from the + * other quals. e.g., "x = x" goes to selfjoinquals and "a = b" to + * otherjoinquals. + */ + split_selfjoin_quals(root, restrictlist, &selfjoinquals, + &otherjoinquals, inner->relid, outer->relid); + + Assert(list_length(restrictlist) == + (list_length(selfjoinquals) + list_length(otherjoinquals))); + + /* + * To enable SJE for the only degenerate case without any self + * join clauses at all, add baserestrictinfo to this list. The + * degenerate case works only if both sides have the same clause. + * So doesn't matter which side to add. + */ + selfjoinquals = list_concat(selfjoinquals, outer->baserestrictinfo); + + /* + * Determine if the inner table can duplicate outer rows. We must + * bypass the unique rel cache here since we're possibly using a + * subset of join quals. We can use 'force_cache' == true when all + * join quals are self-join quals. Otherwise, we could end up + * putting false negatives in the cache. + */ + if (!innerrel_is_unique_ext(root, joinrelids, inner->relids, + outer, JOIN_INNER, selfjoinquals, + list_length(otherjoinquals) == 0, + &uclauses)) + continue; + + /* + * 'uclauses' is the copy of outer->baserestrictinfo that are + * associated with an index. We proved by matching selfjoinquals + * to a unique index that the outer relation has at most one + * matching row for each inner row. Sometimes that is not enough. + * e.g. "WHERE s1.b = s2.b AND s1.a = 1 AND s2.a = 2" when the + * unique index is (a,b). Having non-empty uclauses, we must + * validate that the inner baserestrictinfo contains the same + * expressions, or we won't match the same row on each side of the + * join. + */ + if (!match_unique_clauses(root, inner, uclauses, outer->relid)) + continue; + + /* + * We can remove either relation, so remove the inner one in order + * to simplify this loop. + */ + remove_self_join_rel(root, omark, imark, outer, inner, restrictlist); + + result = bms_add_member(result, r); + + /* We have removed the outer relation, try the next one. */ + break; + } + } + + return result; +} + +/* + * Gather indexes of base relations from the joinlist and try to eliminate self + * joins. + */ +static Relids +remove_self_joins_recurse(PlannerInfo *root, List *joinlist, Relids toRemove) +{ + ListCell *jl; + Relids relids = NULL; + SelfJoinCandidate *candidates = NULL; + int i; + int j; + int numRels; + + /* Collect indexes of base relations of the join tree */ + foreach(jl, joinlist) + { + Node *jlnode = (Node *) lfirst(jl); + + if (IsA(jlnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jlnode)->rtindex; + RangeTblEntry *rte = root->simple_rte_array[varno]; + + /* + * We only consider ordinary relations as candidates to be + * removed, and these relations should not have TABLESAMPLE + * clauses specified. Removing a relation with TABLESAMPLE clause + * could potentially change the syntax of the query. Because of + * UPDATE/DELETE EPQ mechanism, currently Query->resultRelation or + * Query->mergeTargetRelation associated rel cannot be eliminated. + */ + if (rte->rtekind == RTE_RELATION && + rte->relkind == RELKIND_RELATION && + rte->tablesample == NULL && + varno != root->parse->resultRelation && + varno != root->parse->mergeTargetRelation) + { + Assert(!bms_is_member(varno, relids)); + relids = bms_add_member(relids, varno); + } + } + else if (IsA(jlnode, List)) + { + /* Recursively go inside the sub-joinlist */ + toRemove = remove_self_joins_recurse(root, (List *) jlnode, + toRemove); + } + else + elog(ERROR, "unrecognized joinlist node type: %d", + (int) nodeTag(jlnode)); + } + + numRels = bms_num_members(relids); + + /* Need at least two relations for the join */ + if (numRels < 2) + return toRemove; + + /* + * In order to find relations with the same oid we first build an array of + * candidates and then sort it by oid. + */ + candidates = (SelfJoinCandidate *) palloc(sizeof(SelfJoinCandidate) * + numRels); + i = -1; + j = 0; + while ((i = bms_next_member(relids, i)) >= 0) + { + candidates[j].relid = i; + candidates[j].reloid = root->simple_rte_array[i]->relid; + j++; + } + + qsort(candidates, numRels, sizeof(SelfJoinCandidate), + self_join_candidates_cmp); + + /* + * Iteratively form a group of relation indexes with the same oid and + * launch the routine that detects self-joins in this group and removes + * excessive range table entries. + * + * At the end of the iteration, exclude the group from the overall relids + * list. So each next iteration of the cycle will involve less and less + * value of relids. + */ + i = 0; + for (j = 1; j < numRels + 1; j++) + { + if (j == numRels || candidates[j].reloid != candidates[i].reloid) + { + if (j - i >= 2) + { + /* Create a group of relation indexes with the same oid */ + Relids group = NULL; + Relids removed; + + while (i < j) + { + group = bms_add_member(group, candidates[i].relid); + i++; + } + relids = bms_del_members(relids, group); + + /* + * Try to remove self-joins from a group of identical entries. + * Make the next attempt iteratively - if something is deleted + * from a group, changes in clauses and equivalence classes + * can give us a chance to find more candidates. + */ + do + { + Assert(!bms_overlap(group, toRemove)); + removed = remove_self_joins_one_group(root, group); + toRemove = bms_add_members(toRemove, removed); + group = bms_del_members(group, removed); + } while (!bms_is_empty(removed) && + bms_membership(group) == BMS_MULTIPLE); + bms_free(removed); + bms_free(group); + } + else + { + /* Single relation, just remove it from the set */ + relids = bms_del_member(relids, candidates[i].relid); + i = j; + } + } + } + + Assert(bms_is_empty(relids)); + + return toRemove; +} + +/* + * Compare self-join candidates by their oids. + */ +static int +self_join_candidates_cmp(const void *a, const void *b) +{ + const SelfJoinCandidate *ca = (const SelfJoinCandidate *) a; + const SelfJoinCandidate *cb = (const SelfJoinCandidate *) b; + + if (ca->reloid != cb->reloid) + return (ca->reloid < cb->reloid ? -1 : 1); + else + return 0; +} + +/* + * Find and remove useless self joins. + * + * Search for joins where a relation is joined to itself. If the join clause + * for each tuple from one side of the join is proven to match the same + * physical row (or nothing) on the other side, that self-join can be + * eliminated from the query. Suitable join clauses are assumed to be in the + * form of X = X, and can be replaced with NOT NULL clauses. + * + * For the sake of simplicity, we don't apply this optimization to special + * joins. Here is a list of what we could do in some particular cases: + * 'a a1 semi join a a2': is reduced to inner by reduce_unique_semijoins, + * and then removed normally. + * 'a a1 anti join a a2': could simplify to a scan with 'outer quals AND + * (IS NULL on join columns OR NOT inner quals)'. + * 'a a1 left join a a2': could simplify to a scan like inner but without + * NOT NULL conditions on join columns. + * 'a a1 left join (a a2 join b)': can't simplify this, because join to b + * can both remove rows and introduce duplicates. + * + * To search for removable joins, we order all the relations on their Oid, + * go over each set with the same Oid, and consider each pair of relations + * in this set. + * + * To remove the join, we mark one of the participating relations as dead + * and rewrite all references to it to point to the remaining relation. + * This includes modifying RestrictInfos, EquivalenceClasses, and + * EquivalenceMembers. We also have to modify the row marks. The join clauses + * of the removed relation become either restriction or join clauses, based on + * whether they reference any relations not participating in the removed join. + * + * 'joinlist' is the top-level joinlist of the query. If it has any + * references to the removed relations, we update them to point to the + * remaining ones. + */ +List * +remove_useless_self_joins(PlannerInfo *root, List *joinlist) +{ + Relids toRemove = NULL; + int relid = -1; + + if (!enable_self_join_elimination || joinlist == NIL || + (list_length(joinlist) == 1 && !IsA(linitial(joinlist), List))) + return joinlist; + + /* + * Merge pairs of relations participated in self-join. Remove unnecessary + * range table entries. + */ + toRemove = remove_self_joins_recurse(root, joinlist, toRemove); + + if (unlikely(toRemove != NULL)) + { + /* At the end, remove orphaned relation links */ + while ((relid = bms_next_member(toRemove, relid)) >= 0) + { + int nremoved = 0; + + joinlist = remove_rel_from_joinlist(joinlist, relid, &nremoved); + if (nremoved != 1) + elog(ERROR, "failed to find relation %d in joinlist", relid); + } + } + + return joinlist; } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index fe5a323cfd7f1..4ad30b7627e6e 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -5,7 +5,7 @@ * Planning is complete, we just need to convert the selected * Path into a Plan. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -41,6 +41,7 @@ #include "parser/parse_clause.h" #include "parser/parsetree.h" #include "partitioning/partprune.h" +#include "tcop/tcopprot.h" #include "utils/lsyscache.h" @@ -178,6 +179,8 @@ static void copy_generic_path_info(Plan *dest, Path *src); static void copy_plan_costsize(Plan *dest, Plan *src); static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples); +static void label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan, + List *pathkeys, double limit_tuples); static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid); static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc); @@ -249,7 +252,7 @@ static MergeJoin *make_mergejoin(List *tlist, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, - int *mergestrategies, + bool *mergereversals, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, @@ -282,12 +285,9 @@ static Memoize *make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids); -static WindowAgg *make_windowagg(List *tlist, Index winref, +static WindowAgg *make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, - int frameOptions, Node *startOffset, Node *endOffset, - Oid startInRangeFunc, Oid endInRangeFunc, - Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree); static Group *make_group(List *tlist, List *qual, int numGroupCols, @@ -298,9 +298,9 @@ static Unique *make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols); static Gather *make_gather(List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan); -static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, - List *distinctList, AttrNumber flagColIdx, int firstFlag, - long numGroups); +static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, + List *tlist, Plan *lefttree, Plan *righttree, + List *groupList, long numGroups); static LockRows *make_lockrows(Plan *lefttree, List *rowMarks, int epqParam); static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); static ProjectSet *make_project_set(List *tlist, Plan *subplan); @@ -1224,7 +1224,6 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) ListCell *subpaths; int nasyncplans = 0; RelOptInfo *rel = best_path->path.parent; - PartitionPruneInfo *partpruneinfo = NULL; int nodenumsortkeys = 0; AttrNumber *nodeSortColIdx = NULL; Oid *nodeSortOperators = NULL; @@ -1375,6 +1374,9 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) subplans = lappend(subplans, subplan); } + /* Set below if we find quals that we can use to run-time prune */ + plan->part_prune_index = -1; + /* * If any quals exist, they may be useful to perform further partition * pruning during execution. Gather information needed by the executor to @@ -1398,16 +1400,14 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags) } if (prunequal != NIL) - partpruneinfo = - make_partition_pruneinfo(root, rel, - best_path->subpaths, - prunequal); + plan->part_prune_index = make_partition_pruneinfo(root, rel, + best_path->subpaths, + prunequal); } plan->appendplans = subplans; plan->nasyncplans = nasyncplans; plan->first_partial_plan = best_path->first_partial_path; - plan->part_prune_info = partpruneinfo; copy_generic_path_info(&plan->plan, (Path *) best_path); @@ -1446,7 +1446,6 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, List *subplans = NIL; ListCell *subpaths; RelOptInfo *rel = best_path->path.parent; - PartitionPruneInfo *partpruneinfo = NULL; /* * We don't have the actual creation of the MergeAppend node split out @@ -1539,6 +1538,9 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, subplans = lappend(subplans, subplan); } + /* Set below if we find quals that we can use to run-time prune */ + node->part_prune_index = -1; + /* * If any quals exist, they may be useful to perform further partition * pruning during execution. Gather information needed by the executor to @@ -1554,13 +1556,12 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, Assert(best_path->path.param_info == NULL); if (prunequal != NIL) - partpruneinfo = make_partition_pruneinfo(root, rel, - best_path->subpaths, - prunequal); + node->part_prune_index = make_partition_pruneinfo(root, rel, + best_path->subpaths, + prunequal); } node->mergeplans = subplans; - node->part_prune_info = partpruneinfo; /* * If prepare_sort_from_pathkeys added sort columns, but we were told to @@ -1893,6 +1894,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags) subplan->targetlist); sortcl->eqop = eqop; sortcl->sortop = sortop; + sortcl->reverse_sort = false; sortcl->nulls_first = false; sortcl->hashable = false; /* no need to make this accurate */ sortList = lappend(sortList, sortcl); @@ -2021,7 +2023,7 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags) * Convert our subpath to a Plan and determine whether we need a Result * node. * - * In most cases where we don't need to project, creation_projection_path + * In most cases where we don't need to project, create_projection_path * will have set dummypp, but not always. First, some createplan.c * routines change the tlists of their nodes. (An example is that * create_merge_append_plan might add resjunk sort columns to a @@ -2571,6 +2573,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path) 0, NULL, NULL, NULL); /* Must apply correct cost/width data to Limit node */ + plan->disabled_nodes = mminfo->path->disabled_nodes; plan->startup_cost = mminfo->path->startup_cost; plan->total_cost = mminfo->pathcost; plan->plan_rows = 1; @@ -2677,7 +2680,7 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path) /* And finally we can make the WindowAgg node */ plan = make_windowagg(tlist, - wc->winref, + wc, partNumCols, partColIdx, partOperators, @@ -2686,14 +2689,6 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path) ordColIdx, ordOperators, ordCollations, - wc->frameOptions, - wc->startOffset, - wc->endOffset, - wc->startInRangeFunc, - wc->endInRangeFunc, - wc->inRangeColl, - wc->inRangeAsc, - wc->inRangeNullsFirst, best_path->runCondition, best_path->qual, best_path->topwindow, @@ -2714,25 +2709,29 @@ static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags) { SetOp *plan; - Plan *subplan; + List *tlist = build_path_tlist(root, &best_path->path); + Plan *leftplan; + Plan *rightplan; long numGroups; /* * SetOp doesn't project, so tlist requirements pass through; moreover we * need grouping columns to be labeled. */ - subplan = create_plan_recurse(root, best_path->subpath, - flags | CP_LABEL_TLIST); + leftplan = create_plan_recurse(root, best_path->leftpath, + flags | CP_LABEL_TLIST); + rightplan = create_plan_recurse(root, best_path->rightpath, + flags | CP_LABEL_TLIST); /* Convert numGroups to long int --- but 'ware overflow! */ numGroups = clamp_cardinality_to_long(best_path->numGroups); plan = make_setop(best_path->cmd, best_path->strategy, - subplan, - best_path->distinctList, - best_path->flagColIdx, - best_path->firstFlag, + tlist, + leftplan, + rightplan, + best_path->groupList, numGroups); copy_generic_path_info(&plan->plan, (Path *) best_path); @@ -3130,13 +3129,13 @@ create_indexscan_plan(PlannerInfo *root, Oid sortop; /* Get sort operator from opfamily */ - sortop = get_opfamily_member(pathkey->pk_opfamily, - exprtype, - exprtype, - pathkey->pk_strategy); + sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily, + exprtype, + exprtype, + pathkey->pk_cmptype); if (!OidIsValid(sortop)) elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - pathkey->pk_strategy, exprtype, exprtype, pathkey->pk_opfamily); + pathkey->pk_cmptype, exprtype, exprtype, pathkey->pk_opfamily); indexorderbyops = lappend_oid(indexorderbyops, sortop); } } @@ -4446,7 +4445,7 @@ create_mergejoin_plan(PlannerInfo *root, int nClauses; Oid *mergefamilies; Oid *mergecollations; - int *mergestrategies; + bool *mergereversals; bool *mergenullsfirst; PathKey *opathkey; EquivalenceClass *opeclass; @@ -4521,12 +4520,44 @@ create_mergejoin_plan(PlannerInfo *root, if (best_path->outersortkeys) { Relids outer_relids = outer_path->parent->relids; - Sort *sort = make_sort_from_pathkeys(outer_plan, + Plan *sort_plan; + + /* + * We can assert that the outer path is not already ordered + * appropriately for the mergejoin; otherwise, outersortkeys would + * have been set to NIL. + */ + Assert(!pathkeys_contained_in(best_path->outersortkeys, + outer_path->pathkeys)); + + /* + * We choose to use incremental sort if it is enabled and there are + * presorted keys; otherwise we use full sort. + */ + if (enable_incremental_sort && best_path->outer_presorted_keys > 0) + { + sort_plan = (Plan *) + make_incrementalsort_from_pathkeys(outer_plan, best_path->outersortkeys, - outer_relids); + outer_relids, + best_path->outer_presorted_keys); - label_sort_with_costsize(root, sort, -1.0); - outer_plan = (Plan *) sort; + label_incrementalsort_with_costsize(root, + (IncrementalSort *) sort_plan, + best_path->outersortkeys, + -1.0); + } + else + { + sort_plan = (Plan *) + make_sort_from_pathkeys(outer_plan, + best_path->outersortkeys, + outer_relids); + + label_sort_with_costsize(root, (Sort *) sort_plan, -1.0); + } + + outer_plan = sort_plan; outerpathkeys = best_path->outersortkeys; } else @@ -4534,10 +4565,25 @@ create_mergejoin_plan(PlannerInfo *root, if (best_path->innersortkeys) { + /* + * We do not consider incremental sort for inner path, because + * incremental sort does not support mark/restore. + */ + Relids inner_relids = inner_path->parent->relids; - Sort *sort = make_sort_from_pathkeys(inner_plan, - best_path->innersortkeys, - inner_relids); + Sort *sort; + + /* + * We can assert that the inner path is not already ordered + * appropriately for the mergejoin; otherwise, innersortkeys would + * have been set to NIL. + */ + Assert(!pathkeys_contained_in(best_path->innersortkeys, + inner_path->pathkeys)); + + sort = make_sort_from_pathkeys(inner_plan, + best_path->innersortkeys, + inner_relids); label_sort_with_costsize(root, sort, -1.0); inner_plan = (Plan *) sort; @@ -4576,7 +4622,7 @@ create_mergejoin_plan(PlannerInfo *root, Assert(nClauses == list_length(best_path->path_mergeclauses)); mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid)); mergecollations = (Oid *) palloc(nClauses * sizeof(Oid)); - mergestrategies = (int *) palloc(nClauses * sizeof(int)); + mergereversals = (bool *) palloc(nClauses * sizeof(bool)); mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool)); opathkey = NULL; @@ -4696,14 +4742,14 @@ create_mergejoin_plan(PlannerInfo *root, opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation) elog(ERROR, "left and right pathkeys do not match in mergejoin"); if (first_inner_match && - (opathkey->pk_strategy != ipathkey->pk_strategy || + (opathkey->pk_cmptype != ipathkey->pk_cmptype || opathkey->pk_nulls_first != ipathkey->pk_nulls_first)) elog(ERROR, "left and right pathkeys do not match in mergejoin"); /* OK, save info for executor */ mergefamilies[i] = opathkey->pk_opfamily; mergecollations[i] = opathkey->pk_eclass->ec_collation; - mergestrategies[i] = opathkey->pk_strategy; + mergereversals[i] = (opathkey->pk_cmptype == COMPARE_GT ? true : false); mergenullsfirst[i] = opathkey->pk_nulls_first; i++; } @@ -4723,7 +4769,7 @@ create_mergejoin_plan(PlannerInfo *root, mergeclauses, mergefamilies, mergecollations, - mergestrategies, + mergereversals, mergenullsfirst, outer_plan, inner_plan, @@ -4988,9 +5034,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root) /* Replace the PlaceHolderVar with a nestloop Param */ return (Node *) replace_nestloop_param_placeholdervar(root, phv); } - return expression_tree_mutator(node, - replace_nestloop_params_mutator, - (void *) root); + return expression_tree_mutator(node, replace_nestloop_params_mutator, root); } /* @@ -5403,6 +5447,7 @@ order_qual_clauses(PlannerInfo *root, List *clauses) static void copy_generic_path_info(Plan *dest, Path *src) { + dest->disabled_nodes = src->disabled_nodes; dest->startup_cost = src->startup_cost; dest->total_cost = src->total_cost; dest->plan_rows = src->rows; @@ -5418,6 +5463,7 @@ copy_generic_path_info(Plan *dest, Path *src) static void copy_plan_costsize(Plan *dest, Plan *src) { + dest->disabled_nodes = src->disabled_nodes; dest->startup_cost = src->startup_cost; dest->total_cost = src->total_cost; dest->plan_rows = src->plan_rows; @@ -5443,13 +5489,10 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples) Plan *lefttree = plan->plan.lefttree; Path sort_path; /* dummy for result of cost_sort */ - /* - * This function shouldn't have to deal with IncrementalSort plans because - * they are only created from corresponding Path nodes. - */ Assert(IsA(plan, Sort)); cost_sort(&sort_path, root, NIL, + plan->plan.disabled_nodes, lefttree->total_cost, lefttree->plan_rows, lefttree->plan_width, @@ -5464,6 +5507,37 @@ label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples) plan->plan.parallel_safe = lefttree->parallel_safe; } +/* + * Same as label_sort_with_costsize, but labels the IncrementalSort node + * instead. + */ +static void +label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan, + List *pathkeys, double limit_tuples) +{ + Plan *lefttree = plan->sort.plan.lefttree; + Path sort_path; /* dummy for result of cost_incremental_sort */ + + Assert(IsA(plan, IncrementalSort)); + + cost_incremental_sort(&sort_path, root, pathkeys, + plan->nPresortedCols, + plan->sort.plan.disabled_nodes, + lefttree->startup_cost, + lefttree->total_cost, + lefttree->plan_rows, + lefttree->plan_width, + 0.0, + work_mem, + limit_tuples); + plan->sort.plan.startup_cost = sort_path.startup_cost; + plan->sort.plan.total_cost = sort_path.total_cost; + plan->sort.plan.plan_rows = lefttree->plan_rows; + plan->sort.plan.plan_width = lefttree->plan_width; + plan->sort.plan.parallel_aware = false; + plan->sort.plan.parallel_safe = lefttree->parallel_safe; +} + /* * bitmap_subplan_mark_shared * Set isshared flag in bitmap subplan so that it will be created in @@ -6025,7 +6099,7 @@ make_mergejoin(List *tlist, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, - int *mergestrategies, + bool *mergereversals, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, @@ -6044,7 +6118,7 @@ make_mergejoin(List *tlist, node->mergeclauses = mergeclauses; node->mergeFamilies = mergefamilies; node->mergeCollations = mergecollations; - node->mergeStrategies = mergestrategies; + node->mergeReversals = mergereversals; node->mergeNullsFirst = mergenullsfirst; node->join.jointype = jointype; node->join.inner_unique = inner_unique; @@ -6071,6 +6145,7 @@ make_sort(Plan *lefttree, int numCols, plan = &node->plan; plan->targetlist = lefttree->targetlist; + plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false); plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; @@ -6302,13 +6377,13 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, * Look up the correct sort operator from the PathKey's slightly * abstracted representation. */ - sortop = get_opfamily_member(pathkey->pk_opfamily, - pk_datatype, - pk_datatype, - pathkey->pk_strategy); + sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily, + pk_datatype, + pk_datatype, + pathkey->pk_cmptype); if (!OidIsValid(sortop)) /* should not happen */ elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - pathkey->pk_strategy, pk_datatype, pk_datatype, + pathkey->pk_cmptype, pk_datatype, pk_datatype, pathkey->pk_opfamily); /* Add the column to the sort arrays */ @@ -6545,10 +6620,12 @@ materialize_finished_plan(Plan *subplan) /* Set cost data */ cost_material(&matpath, + subplan->disabled_nodes, subplan->startup_cost, subplan->total_cost, subplan->plan_rows, subplan->plan_width); + matplan->disabled_nodes = subplan->disabled_nodes; matplan->startup_cost = matpath.startup_cost + initplan_cost; matplan->total_cost = matpath.total_cost + initplan_cost; matplan->plan_rows = subplan->plan_rows; @@ -6619,18 +6696,16 @@ make_agg(List *tlist, List *qual, } static WindowAgg * -make_windowagg(List *tlist, Index winref, +make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, - int frameOptions, Node *startOffset, Node *endOffset, - Oid startInRangeFunc, Oid endInRangeFunc, - Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree) { WindowAgg *node = makeNode(WindowAgg); Plan *plan = &node->plan; - node->winref = winref; + node->winname = wc->name; + node->winref = wc->winref; node->partNumCols = partNumCols; node->partColIdx = partColIdx; node->partOperators = partOperators; @@ -6639,17 +6714,17 @@ make_windowagg(List *tlist, Index winref, node->ordColIdx = ordColIdx; node->ordOperators = ordOperators; node->ordCollations = ordCollations; - node->frameOptions = frameOptions; - node->startOffset = startOffset; - node->endOffset = endOffset; + node->frameOptions = wc->frameOptions; + node->startOffset = wc->startOffset; + node->endOffset = wc->endOffset; node->runCondition = runCondition; /* a duplicate of the above for EXPLAIN */ node->runConditionOrig = runCondition; - node->startInRangeFunc = startInRangeFunc; - node->endInRangeFunc = endInRangeFunc; - node->inRangeColl = inRangeColl; - node->inRangeAsc = inRangeAsc; - node->inRangeNullsFirst = inRangeNullsFirst; + node->startInRangeFunc = wc->startInRangeFunc; + node->endInRangeFunc = wc->endInRangeFunc; + node->inRangeColl = wc->inRangeColl; + node->inRangeAsc = wc->inRangeAsc; + node->inRangeNullsFirst = wc->inRangeNullsFirst; node->topWindow = topWindow; plan->targetlist = tlist; @@ -6821,13 +6896,13 @@ make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols) * Look up the correct equality operator from the PathKey's slightly * abstracted representation. */ - eqop = get_opfamily_member(pathkey->pk_opfamily, - pk_datatype, - pk_datatype, - BTEqualStrategyNumber); + eqop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily, + pk_datatype, + pk_datatype, + COMPARE_EQ); if (!OidIsValid(eqop)) /* should not happen */ elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", - BTEqualStrategyNumber, pk_datatype, pk_datatype, + COMPARE_EQ, pk_datatype, pk_datatype, pathkey->pk_opfamily); uniqColIdx[keyno] = tle->resno; @@ -6870,57 +6945,62 @@ make_gather(List *qptlist, } /* - * distinctList is a list of SortGroupClauses, identifying the targetlist - * items that should be considered by the SetOp filter. The input path must - * already be sorted accordingly. + * groupList is a list of SortGroupClauses, identifying the targetlist + * items that should be considered by the SetOp filter. The input plans must + * already be sorted accordingly, if we're doing SETOP_SORTED mode. */ static SetOp * -make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, - List *distinctList, AttrNumber flagColIdx, int firstFlag, - long numGroups) +make_setop(SetOpCmd cmd, SetOpStrategy strategy, + List *tlist, Plan *lefttree, Plan *righttree, + List *groupList, long numGroups) { SetOp *node = makeNode(SetOp); Plan *plan = &node->plan; - int numCols = list_length(distinctList); + int numCols = list_length(groupList); int keyno = 0; - AttrNumber *dupColIdx; - Oid *dupOperators; - Oid *dupCollations; + AttrNumber *cmpColIdx; + Oid *cmpOperators; + Oid *cmpCollations; + bool *cmpNullsFirst; ListCell *slitem; - plan->targetlist = lefttree->targetlist; + plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; - plan->righttree = NULL; + plan->righttree = righttree; /* - * convert SortGroupClause list into arrays of attr indexes and equality + * convert SortGroupClause list into arrays of attr indexes and comparison * operators, as wanted by executor */ - dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols); - dupOperators = (Oid *) palloc(sizeof(Oid) * numCols); - dupCollations = (Oid *) palloc(sizeof(Oid) * numCols); + cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols); + cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols); + cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols); + cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols); - foreach(slitem, distinctList) + foreach(slitem, groupList) { SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem); TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist); - dupColIdx[keyno] = tle->resno; - dupOperators[keyno] = sortcl->eqop; - dupCollations[keyno] = exprCollation((Node *) tle->expr); - Assert(OidIsValid(dupOperators[keyno])); + cmpColIdx[keyno] = tle->resno; + if (strategy == SETOP_HASHED) + cmpOperators[keyno] = sortcl->eqop; + else + cmpOperators[keyno] = sortcl->sortop; + Assert(OidIsValid(cmpOperators[keyno])); + cmpCollations[keyno] = exprCollation((Node *) tle->expr); + cmpNullsFirst[keyno] = sortcl->nulls_first; keyno++; } node->cmd = cmd; node->strategy = strategy; node->numCols = numCols; - node->dupColIdx = dupColIdx; - node->dupOperators = dupOperators; - node->dupCollations = dupCollations; - node->flagColIdx = flagColIdx; - node->firstFlag = firstFlag; + node->cmpColIdx = cmpColIdx; + node->cmpOperators = cmpOperators; + node->cmpCollations = cmpCollations; + node->cmpNullsFirst = cmpNullsFirst; node->numGroups = numGroups; return node; @@ -7032,6 +7112,8 @@ make_modifytable(PlannerInfo *root, Plan *subplan, int epqParam) { ModifyTable *node = makeNode(ModifyTable); + bool returning_old_or_new = false; + bool returning_old_or_new_valid = false; List *fdw_private_list; Bitmapset *direct_modify_plans; ListCell *lc; @@ -7096,6 +7178,8 @@ make_modifytable(PlannerInfo *root, Plan *subplan, } node->updateColnosLists = updateColnosLists; node->withCheckOptionLists = withCheckOptionLists; + node->returningOldAlias = root->parse->returningOldAlias; + node->returningNewAlias = root->parse->returningNewAlias; node->returningLists = returningLists; node->rowMarks = rowMarks; node->mergeActionLists = mergeActionLists; @@ -7136,7 +7220,19 @@ make_modifytable(PlannerInfo *root, Plan *subplan, if (rte->rtekind == RTE_RELATION && rte->relkind == RELKIND_FOREIGN_TABLE) + { + /* Check if the access to foreign tables is restricted */ + if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0)) + { + /* there must not be built-in foreign tables */ + Assert(rte->relid >= FirstNormalObjectId); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access to non-system foreign table is restricted"))); + } + fdwroutine = GetFdwRoutineByRelId(rte->relid); + } else fdwroutine = NULL; } @@ -7164,7 +7260,8 @@ make_modifytable(PlannerInfo *root, Plan *subplan, * callback functions needed for that and (2) there are no local * structures that need to be run for each modified row: row-level * triggers on the foreign table, stored generated columns, WITH CHECK - * OPTIONs from parent views. + * OPTIONs from parent views, or Vars returning OLD/NEW in the + * RETURNING list. */ direct_modify = false; if (fdwroutine != NULL && @@ -7175,7 +7272,18 @@ make_modifytable(PlannerInfo *root, Plan *subplan, withCheckOptionLists == NIL && !has_row_triggers(root, rti, operation) && !has_stored_generated_columns(root, rti)) - direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i); + { + /* returning_old_or_new is the same for all result relations */ + if (!returning_old_or_new_valid) + { + returning_old_or_new = + contain_vars_returning_old_or_new((Node *) + root->parse->returningList); + returning_old_or_new_valid = true; + } + if (!returning_old_or_new) + direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i); + } if (direct_modify) direct_modify_plans = bms_add_member(direct_modify_plans, i); diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e2c68fe6f995e..01804b085b3ba 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -1,9 +1,9 @@ /*------------------------------------------------------------------------- * * initsplan.c - * Target list, qualification, joininfo initialization routines + * Target list, group by, qualification, joininfo initialization routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,6 +14,7 @@ */ #include "postgres.h" +#include "catalog/pg_constraint.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -274,6 +275,8 @@ build_base_rel_tlists(PlannerInfo *root, List *final_tlist) * have a single owning relation; we keep their attr_needed info in * root->placeholder_list instead. Find or create the associated * PlaceHolderInfo entry, and update its ph_needed. + * + * See also add_vars_to_attr_needed. */ void add_vars_to_targetlist(PlannerInfo *root, List *vars, @@ -327,6 +330,303 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, } } +/* + * add_vars_to_attr_needed + * This does a subset of what add_vars_to_targetlist does: it just + * updates attr_needed for Vars and ph_needed for PlaceHolderVars. + * We assume the Vars are already in their relations' targetlists. + * + * This is used to rebuild attr_needed/ph_needed sets after removal + * of a useless outer join. The removed join clause might have been + * the only upper-level use of some other relation's Var, in which + * case we can reduce that Var's attr_needed and thereby possibly + * open the door to further join removals. But we can't tell that + * without tedious reconstruction of the attr_needed data. + * + * Note that if a Var's attr_needed is successfully reduced to empty, + * it will still be in the relation's targetlist even though we do + * not really need the scan plan node to emit it. The extra plan + * inefficiency seems tiny enough to not be worth spending planner + * cycles to get rid of it. + */ +void +add_vars_to_attr_needed(PlannerInfo *root, List *vars, + Relids where_needed) +{ + ListCell *temp; + + Assert(!bms_is_empty(where_needed)); + + foreach(temp, vars) + { + Node *node = (Node *) lfirst(temp); + + if (IsA(node, Var)) + { + Var *var = (Var *) node; + RelOptInfo *rel = find_base_rel(root, var->varno); + int attno = var->varattno; + + if (bms_is_subset(where_needed, rel->relids)) + continue; + Assert(attno >= rel->min_attr && attno <= rel->max_attr); + attno -= rel->min_attr; + rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno], + where_needed); + } + else if (IsA(node, PlaceHolderVar)) + { + PlaceHolderVar *phv = (PlaceHolderVar *) node; + PlaceHolderInfo *phinfo = find_placeholder_info(root, phv); + + phinfo->ph_needed = bms_add_members(phinfo->ph_needed, + where_needed); + } + else + elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); + } +} + +/***************************************************************************** + * + * GROUP BY + * + *****************************************************************************/ + +/* + * remove_useless_groupby_columns + * Remove any columns in the GROUP BY clause that are redundant due to + * being functionally dependent on other GROUP BY columns. + * + * Since some other DBMSes do not allow references to ungrouped columns, it's + * not unusual to find all columns listed in GROUP BY even though listing the + * primary-key columns, or columns of a unique constraint would be sufficient. + * Deleting such excess columns avoids redundant sorting or hashing work, so + * it's worth doing. + * + * Relcache invalidations will ensure that cached plans become invalidated + * when the underlying supporting indexes are dropped or if a column's NOT + * NULL attribute is removed. + */ +void +remove_useless_groupby_columns(PlannerInfo *root) +{ + Query *parse = root->parse; + Bitmapset **groupbyattnos; + Bitmapset **surplusvars; + bool tryremove = false; + ListCell *lc; + int relid; + + /* No chance to do anything if there are less than two GROUP BY items */ + if (list_length(root->processed_groupClause) < 2) + return; + + /* Don't fiddle with the GROUP BY clause if the query has grouping sets */ + if (parse->groupingSets) + return; + + /* + * Scan the GROUP BY clause to find GROUP BY items that are simple Vars. + * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k + * that are GROUP BY items. + */ + groupbyattnos = (Bitmapset **) palloc0(sizeof(Bitmapset *) * + (list_length(parse->rtable) + 1)); + foreach(lc, root->processed_groupClause) + { + SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); + TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); + Var *var = (Var *) tle->expr; + + /* + * Ignore non-Vars and Vars from other query levels. + * + * XXX in principle, stable expressions containing Vars could also be + * removed, if all the Vars are functionally dependent on other GROUP + * BY items. But it's not clear that such cases occur often enough to + * be worth troubling over. + */ + if (!IsA(var, Var) || + var->varlevelsup > 0) + continue; + + /* OK, remember we have this Var */ + relid = var->varno; + Assert(relid <= list_length(parse->rtable)); + + /* + * If this isn't the first column for this relation then we now have + * multiple columns. That means there might be some that can be + * removed. + */ + tryremove |= !bms_is_empty(groupbyattnos[relid]); + groupbyattnos[relid] = bms_add_member(groupbyattnos[relid], + var->varattno - FirstLowInvalidHeapAttributeNumber); + } + + /* + * No Vars or didn't find multiple Vars for any relation in the GROUP BY? + * If so, nothing can be removed, so don't waste more effort trying. + */ + if (!tryremove) + return; + + /* + * Consider each relation and see if it is possible to remove some of its + * Vars from GROUP BY. For simplicity and speed, we do the actual removal + * in a separate pass. Here, we just fill surplusvars[k] with a bitmapset + * of the column attnos of RTE k that are removable GROUP BY items. + */ + surplusvars = NULL; /* don't allocate array unless required */ + relid = 0; + foreach(lc, parse->rtable) + { + RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); + RelOptInfo *rel; + Bitmapset *relattnos; + Bitmapset *best_keycolumns = NULL; + int32 best_nkeycolumns = PG_INT32_MAX; + + relid++; + + /* Only plain relations could have primary-key constraints */ + if (rte->rtekind != RTE_RELATION) + continue; + + /* + * We must skip inheritance parent tables as some of the child rels + * may cause duplicate rows. This cannot happen with partitioned + * tables, however. + */ + if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE) + continue; + + /* Nothing to do unless this rel has multiple Vars in GROUP BY */ + relattnos = groupbyattnos[relid]; + if (bms_membership(relattnos) != BMS_MULTIPLE) + continue; + + rel = root->simple_rel_array[relid]; + + /* + * Now check each index for this relation to see if there are any with + * columns which are a proper subset of the grouping columns for this + * relation. + */ + foreach_node(IndexOptInfo, index, rel->indexlist) + { + Bitmapset *ind_attnos; + bool nulls_check_ok; + + /* + * Skip any non-unique and deferrable indexes. Predicate indexes + * have not been checked yet, so we must skip those too as the + * predOK check that's done later might fail. + */ + if (!index->unique || !index->immediate || index->indpred != NIL) + continue; + + /* For simplicity, we currently don't support expression indexes */ + if (index->indexprs != NIL) + continue; + + ind_attnos = NULL; + nulls_check_ok = true; + for (int i = 0; i < index->nkeycolumns; i++) + { + /* + * We must insist that the index columns are all defined NOT + * NULL otherwise duplicate NULLs could exist. However, we + * can relax this check when the index is defined with NULLS + * NOT DISTINCT as there can only be 1 NULL row, therefore + * functional dependency on the unique columns is maintained, + * despite the NULL. + */ + if (!index->nullsnotdistinct && + !bms_is_member(index->indexkeys[i], + rel->notnullattnums)) + { + nulls_check_ok = false; + break; + } + + ind_attnos = + bms_add_member(ind_attnos, + index->indexkeys[i] - + FirstLowInvalidHeapAttributeNumber); + } + + if (!nulls_check_ok) + continue; + + /* + * Skip any indexes where the indexed columns aren't a proper + * subset of the GROUP BY. + */ + if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1) + continue; + + /* + * Record the attribute numbers from the index with the fewest + * columns. This allows the largest number of columns to be + * removed from the GROUP BY clause. In the future, we may wish + * to consider using the narrowest set of columns and looking at + * pg_statistic.stawidth as it might be better to use an index + * with, say two INT4s, rather than, say, one long varlena column. + */ + if (index->nkeycolumns < best_nkeycolumns) + { + best_keycolumns = ind_attnos; + best_nkeycolumns = index->nkeycolumns; + } + } + + /* Did we find a suitable index? */ + if (!bms_is_empty(best_keycolumns)) + { + /* + * To easily remember whether we've found anything to do, we don't + * allocate the surplusvars[] array until we find something. + */ + if (surplusvars == NULL) + surplusvars = (Bitmapset **) palloc0(sizeof(Bitmapset *) * + (list_length(parse->rtable) + 1)); + + /* Remember the attnos of the removable columns */ + surplusvars[relid] = bms_difference(relattnos, best_keycolumns); + } + } + + /* + * If we found any surplus Vars, build a new GROUP BY clause without them. + * (Note: this may leave some TLEs with unreferenced ressortgroupref + * markings, but that's harmless.) + */ + if (surplusvars != NULL) + { + List *new_groupby = NIL; + + foreach(lc, root->processed_groupClause) + { + SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); + TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); + Var *var = (Var *) tle->expr; + + /* + * New list must include non-Vars, outer Vars, and anything not + * marked as surplus. + */ + if (!IsA(var, Var) || + var->varlevelsup > 0 || + !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber, + surplusvars[var->varno])) + new_groupby = lappend(new_groupby, sgc); + } + + root->processed_groupClause = new_groupby; + } +} /***************************************************************************** * @@ -488,10 +788,54 @@ extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex) */ add_vars_to_targetlist(root, newvars, where_needed); - /* Remember the lateral references for create_lateral_join_info */ + /* + * Remember the lateral references for rebuild_lateral_attr_needed and + * create_lateral_join_info. + */ brel->lateral_vars = newvars; } +/* + * rebuild_lateral_attr_needed + * Put back attr_needed bits for Vars/PHVs needed for lateral references. + * + * This is used to rebuild attr_needed/ph_needed sets after removal of a + * useless outer join. It should match what find_lateral_references did, + * except that we call add_vars_to_attr_needed not add_vars_to_targetlist. + */ +void +rebuild_lateral_attr_needed(PlannerInfo *root) +{ + Index rti; + + /* We need do nothing if the query contains no LATERAL RTEs */ + if (!root->hasLateralRTEs) + return; + + /* Examine the same baserels that find_lateral_references did */ + for (rti = 1; rti < root->simple_rel_array_size; rti++) + { + RelOptInfo *brel = root->simple_rel_array[rti]; + Relids where_needed; + + if (brel == NULL) + continue; + if (brel->reloptkind != RELOPT_BASEREL) + continue; + + /* + * We don't need to repeat all of extract_lateral_references, since it + * kindly saved the extracted Vars/PHVs in lateral_vars. + */ + if (brel->lateral_vars == NIL) + continue; + + where_needed = bms_make_singleton(rti); + + add_vars_to_attr_needed(root, brel->lateral_vars, where_needed); + } +} + /* * create_lateral_join_info * Fill in the per-base-relation direct_lateral_relids, lateral_relids @@ -1328,6 +1672,10 @@ mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid, { RelOptInfo *rel = root->simple_rel_array[relid]; + /* ignore the RTE_GROUP RTE */ + if (relid == root->group_rtindex) + continue; + if (rel == NULL) /* must be an outer join */ { Assert(bms_is_member(relid, root->outer_join_rels)); @@ -2441,6 +2789,9 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, * var propagation is ensured by making ojscope include input rels from * both sides of the join. * + * See also rebuild_joinclause_attr_needed, which has to partially repeat + * this work after removal of an outer join. + * * Note: if the clause gets absorbed into an EquivalenceClass then this * may be unnecessary, but for now we have to do it to cover the case * where the EC becomes ec_broken and we end up reinserting the original @@ -2657,11 +3008,18 @@ add_base_clause_to_rel(PlannerInfo *root, Index relid, /* * Substitute the origin qual with constant-FALSE if it is provably - * always false. Note that we keep the same rinfo_serial. + * always false. + * + * Note that we need to keep the same rinfo_serial, since it is in + * practice the same condition. We also need to reset the + * last_rinfo_serial counter, which is essential to ensure that the + * RestrictInfos for the "same" qual condition get identical serial + * numbers (see deconstruct_distribute_oj_quals). */ if (restriction_is_always_false(root, restrictinfo)) { int save_rinfo_serial = restrictinfo->rinfo_serial; + int save_last_rinfo_serial = root->last_rinfo_serial; restrictinfo = make_restrictinfo(root, (Expr *) makeBoolConst(false, false), @@ -2674,6 +3032,7 @@ add_base_clause_to_rel(PlannerInfo *root, Index relid, restrictinfo->incompatible_relids, restrictinfo->outer_relids); restrictinfo->rinfo_serial = save_rinfo_serial; + root->last_rinfo_serial = save_last_rinfo_serial; } } @@ -2732,6 +3091,15 @@ bool restriction_is_always_true(PlannerInfo *root, RestrictInfo *restrictinfo) { + /* + * For a clone clause, we don't have a reliable way to determine if the + * input expression of a NullTest is non-nullable: nullingrel bits in + * clone clauses may not reflect reality, so we dare not draw conclusions + * from clones about whether Vars are guaranteed not-null. + */ + if (restrictinfo->has_clone || restrictinfo->is_clone) + return false; + /* Check for NullTest qual */ if (IsA(restrictinfo->clause, NullTest)) { @@ -2741,6 +3109,13 @@ restriction_is_always_true(PlannerInfo *root, if (nulltest->nulltesttype != IS_NOT_NULL) return false; + /* + * Empty rows can appear NULL in some contexts and NOT NULL in others, + * so avoid this optimization for row expressions. + */ + if (nulltest->argisrow) + return false; + return expr_is_nonnullable(root, nulltest->arg); } @@ -2781,6 +3156,15 @@ bool restriction_is_always_false(PlannerInfo *root, RestrictInfo *restrictinfo) { + /* + * For a clone clause, we don't have a reliable way to determine if the + * input expression of a NullTest is non-nullable: nullingrel bits in + * clone clauses may not reflect reality, so we dare not draw conclusions + * from clones about whether Vars are guaranteed not-null. + */ + if (restrictinfo->has_clone || restrictinfo->is_clone) + return false; + /* Check for NullTest qual */ if (IsA(restrictinfo->clause, NullTest)) { @@ -2790,6 +3174,13 @@ restriction_is_always_false(PlannerInfo *root, if (nulltest->nulltesttype != IS_NULL) return false; + /* + * Empty rows can appear NULL in some contexts and NOT NULL in others, + * so avoid this optimization for row expressions. + */ + if (nulltest->argisrow) + return false; + return expr_is_nonnullable(root, nulltest->arg); } @@ -3010,6 +3401,11 @@ process_implied_equality(PlannerInfo *root, * some of the Vars could have missed having that done because they only * appeared in single-relation clauses originally. So do it here for * safety. + * + * See also rebuild_joinclause_attr_needed, which has to partially repeat + * this work after removal of an outer join. (Since we will put this + * clause into the joininfo lists, that function needn't do any extra work + * to find it.) */ if (bms_membership(relids) == BMS_MULTIPLE) { @@ -3151,6 +3547,72 @@ get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids) } +/* + * rebuild_joinclause_attr_needed + * Put back attr_needed bits for Vars/PHVs needed for join clauses. + * + * This is used to rebuild attr_needed/ph_needed sets after removal of a + * useless outer join. It should match what distribute_qual_to_rels did, + * except that we call add_vars_to_attr_needed not add_vars_to_targetlist. + */ +void +rebuild_joinclause_attr_needed(PlannerInfo *root) +{ + /* + * We must examine all join clauses, but there's no value in processing + * any join clause more than once. So it's slightly annoying that we have + * to find them via the per-base-relation joininfo lists. Avoid duplicate + * processing by tracking the rinfo_serial numbers of join clauses we've + * already seen. (This doesn't work for is_clone clauses, so we must + * waste effort on them.) + */ + Bitmapset *seen_serials = NULL; + Index rti; + + /* Scan all baserels for join clauses */ + for (rti = 1; rti < root->simple_rel_array_size; rti++) + { + RelOptInfo *brel = root->simple_rel_array[rti]; + ListCell *lc; + + if (brel == NULL) + continue; + if (brel->reloptkind != RELOPT_BASEREL) + continue; + + foreach(lc, brel->joininfo) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); + Relids relids = rinfo->required_relids; + + if (!rinfo->is_clone) /* else serial number is not unique */ + { + if (bms_is_member(rinfo->rinfo_serial, seen_serials)) + continue; /* saw it already */ + seen_serials = bms_add_member(seen_serials, + rinfo->rinfo_serial); + } + + if (bms_membership(relids) == BMS_MULTIPLE) + { + List *vars = pull_var_clause((Node *) rinfo->clause, + PVC_RECURSE_AGGREGATES | + PVC_RECURSE_WINDOWFUNCS | + PVC_INCLUDE_PLACEHOLDERS); + Relids where_needed; + + if (rinfo->is_clone) + where_needed = bms_intersect(relids, root->all_baserels); + else + where_needed = relids; + add_vars_to_attr_needed(root, vars, where_needed); + list_free(vars); + } + } + } +} + + /* * match_foreign_keys_to_quals * Match foreign-key constraints to equivalence classes and join quals diff --git a/src/backend/optimizer/plan/meson.build b/src/backend/optimizer/plan/meson.build index c3b191cdf8199..edf64fe7c51a9 100644 --- a/src/backend/optimizer/plan/meson.build +++ b/src/backend/optimizer/plan/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'analyzejoins.c', diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index afb5445b77b94..64605be31781f 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -17,7 +17,7 @@ * scan all the rows anyway. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -48,7 +48,8 @@ static bool can_minmax_aggs(PlannerInfo *root, List **context); static bool build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, - Oid eqop, Oid sortop, bool nulls_first); + Oid eqop, Oid sortop, bool reverse_sort, + bool nulls_first); static void minmax_qp_callback(PlannerInfo *root, void *extra); static Oid fetch_agg_sort_op(Oid aggfnoid); @@ -172,9 +173,9 @@ preprocess_minmax_aggregates(PlannerInfo *root) * FIRST is more likely to be available if the operator is a * reverse-sort operator, so try that first if reverse. */ - if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, reverse)) + if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, reverse, reverse)) continue; - if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, !reverse)) + if (build_minmax_path(root, mminfo, eqop, mminfo->aggsortop, reverse, !reverse)) continue; /* No indexable path for this aggregate, so fail */ @@ -314,7 +315,7 @@ can_minmax_aggs(PlannerInfo *root, List **context) */ static bool build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, - Oid eqop, Oid sortop, bool nulls_first) + Oid eqop, Oid sortop, bool reverse_sort, bool nulls_first) { PlannerInfo *subroot; Query *parse; @@ -399,6 +400,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, sortcl->tleSortGroupRef = assignSortGroupRef(tle, subroot->processed_tlist); sortcl->eqop = eqop; sortcl->sortop = sortop; + sortcl->reverse_sort = reverse_sort; sortcl->nulls_first = nulls_first; sortcl->hashable = false; /* no need to make this accurate */ parse->sortClause = list_make1(sortcl); diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index e17d31a5c3ec3..5467e094ca7e0 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -9,7 +9,7 @@ * shorn of features like subselects, inheritance, aggregates, grouping, * and so on. (Those are the things planner.c deals with.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -169,6 +169,9 @@ query_planner(PlannerInfo *root, */ add_base_rels_to_query(root, (Node *) parse->jointree); + /* Remove any redundant GROUP BY columns */ + remove_useless_groupby_columns(root); + /* * Examine the targetlist and join tree, adding entries to baserel * targetlists for all referenced Vars, and generating PlaceHolderInfo @@ -230,6 +233,11 @@ query_planner(PlannerInfo *root, */ reduce_unique_semijoins(root); + /* + * Remove self joins on a unique column. + */ + joinlist = remove_useless_self_joins(root, joinlist); + /* * Now distribute "placeholders" to base rels as needed. This has to be * done after join removal because removal could change whether a diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 948afd90948b5..ff65867eebee7 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -3,7 +3,7 @@ * planner.c * The query optimizer external interface. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -23,7 +23,6 @@ #include "access/sysattr.h" #include "access/table.h" #include "catalog/pg_aggregate.h" -#include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" @@ -58,6 +57,8 @@ #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "partitioning/partdesc.h" +#include "rewrite/rewriteManip.h" +#include "utils/backend_status.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/selfuncs.h" @@ -66,6 +67,7 @@ double cursor_tuple_fraction = DEFAULT_CURSOR_TUPLE_FRACTION; int debug_parallel_query = DEBUG_PARALLEL_OFF; bool parallel_leader_participation = true; +bool enable_distinct_reordering = true; /* Hook for plugins to get control in planner() */ planner_hook_type planner_hook = NULL; @@ -88,6 +90,7 @@ create_upper_paths_hook_type create_upper_paths_hook = NULL; #define EXPRKIND_ARBITER_ELEM 10 #define EXPRKIND_TABLEFUNC 11 #define EXPRKIND_TABLEFUNC_LATERAL 12 +#define EXPRKIND_GROUPEXPR 13 /* * Data specific to grouping sets @@ -136,7 +139,6 @@ static void preprocess_rowmarks(PlannerInfo *root); static double preprocess_limit(PlannerInfo *root, double tuple_fraction, int64 *offset_est, int64 *count_est); -static void remove_useless_groupby_columns(PlannerInfo *root); static List *preprocess_groupclause(PlannerInfo *root, List *force); static List *extract_rollup_sets(List *groupingSets); static List *reorder_grouping_sets(List *groupingSets, List *sortclause); @@ -196,6 +198,9 @@ static void create_partial_distinct_paths(PlannerInfo *root, static RelOptInfo *create_final_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo *distinct_rel); +static List *get_useful_pathkeys_for_distinct(PlannerInfo *root, + List *needed_pathkeys, + List *path_pathkeys); static RelOptInfo *create_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, @@ -210,6 +215,7 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist); static void optimize_window_clauses(PlannerInfo *root, WindowFuncLists *wflists); static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists); +static void name_active_windows(List *activeWindows); static PathTarget *make_window_input_target(PlannerInfo *root, PathTarget *final_target, List *activeWindows); @@ -233,6 +239,12 @@ static RelOptInfo *create_partial_grouping_paths(PlannerInfo *root, grouping_sets_data *gd, GroupPathExtraData *extra, bool force_rel_creation); +static Path *make_ordered_path(PlannerInfo *root, + RelOptInfo *rel, + Path *path, + Path *cheapest_path, + List *pathkeys, + double limit_tuples); static void gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel); static bool can_partial_agg(PlannerInfo *root); static void apply_scanjoin_target_to_paths(PlannerInfo *root, @@ -280,6 +292,9 @@ planner(Query *parse, const char *query_string, int cursorOptions, result = (*planner_hook) (parse, query_string, cursorOptions, boundParams); else result = standard_planner(parse, query_string, cursorOptions, boundParams); + + pgstat_report_plan_id(result->planId, false); + return result; } @@ -311,10 +326,13 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, glob->subroots = NIL; glob->rewindPlanIDs = NULL; glob->finalrtable = NIL; + glob->allRelids = NULL; + glob->prunableRelids = NULL; glob->finalrteperminfos = NIL; glob->finalrowmarks = NIL; glob->resultRelations = NIL; glob->appendRelations = NIL; + glob->partPruneInfos = NIL; glob->relationOids = NIL; glob->invalItems = NIL; glob->paramExecTypes = NIL; @@ -323,6 +341,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, glob->lastPlanNodeId = 0; glob->transientPlan = false; glob->dependsOnRole = false; + glob->partition_directory = NULL; /* * Assess whether it's feasible to use parallel mode for this query. We @@ -545,7 +564,10 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, result->dependsOnRole = glob->dependsOnRole; result->parallelModeNeeded = glob->parallelModeNeeded; result->planTree = top_plan; + result->partPruneInfos = glob->partPruneInfos; result->rtable = glob->finalrtable; + result->unprunableRelids = bms_difference(glob->allRelids, + glob->prunableRelids); result->permInfos = glob->finalrteperminfos; result->resultRelations = glob->resultRelations; result->appendRelations = glob->appendRelations; @@ -606,7 +628,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, * setops is used for set operation subqueries to provide the subquery with * the context in which it's being used so that Paths correctly sorted for the * set operation can be generated. NULL when not planning a set operation - * child. + * child, or when a child of a set op that isn't interested in sorted input. * * Basically, this routine does the stuff that should only be done once * per Query object. It then calls grouping_planner. At one time, @@ -721,6 +743,14 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, */ preprocess_function_rtes(root); + /* + * Scan the rangetable for relations with virtual generated columns, and + * replace all Var nodes in the query that reference these columns with + * the generation expressions. Recursion issues here are handled in the + * same way as for SubLinks. + */ + parse = root->parse = expand_virtual_generated_columns(root); + /* * Check to see if any subqueries in the jointree can be merged into this * query. @@ -748,6 +778,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, */ root->hasJoinRTEs = false; root->hasLateralRTEs = false; + root->group_rtindex = 0; hasOuterJoins = false; hasResultRTEs = false; foreach(l, parse->rtable) @@ -781,6 +812,10 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, case RTE_RESULT: hasResultRTEs = true; break; + case RTE_GROUP: + Assert(parse->hasGroupRTE); + root->group_rtindex = list_cell_number(parse->rtable, l) + 1; + break; default: /* No work here for other RTE types */ break; @@ -836,10 +871,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, preprocess_expression(root, (Node *) parse->targetList, EXPRKIND_TARGET); - /* Constant-folding might have removed all set-returning functions */ - if (parse->hasTargetSRFs) - parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList); - newWithCheckOptions = NIL; foreach(l, parse->withCheckOptions) { @@ -969,6 +1000,13 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, rte->values_lists = (List *) preprocess_expression(root, (Node *) rte->values_lists, kind); } + else if (rte->rtekind == RTE_GROUP) + { + /* Preprocess the groupexprs list fully */ + rte->groupexprs = (List *) + preprocess_expression(root, (Node *) rte->groupexprs, + EXPRKIND_GROUPEXPR); + } /* * Process each element of the securityQuals list as if it were a @@ -1005,15 +1043,36 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, } } + /* + * Replace any Vars in the subquery's targetlist and havingQual that + * reference GROUP outputs with the underlying grouping expressions. + * + * Note that we need to perform this replacement after we've preprocessed + * the grouping expressions. This is to ensure that there is only one + * instance of SubPlan for each SubLink contained within the grouping + * expressions. + */ + if (parse->hasGroupRTE) + { + parse->targetList = (List *) + flatten_group_exprs(root, root->parse, (Node *) parse->targetList); + parse->havingQual = + flatten_group_exprs(root, root->parse, parse->havingQual); + } + + /* Constant-folding might have removed all set-returning functions */ + if (parse->hasTargetSRFs) + parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList); + /* * In some cases we may want to transfer a HAVING clause into WHERE. We * cannot do so if the HAVING clause contains aggregates (obviously) or * volatile functions (since a HAVING clause is supposed to be executed * only once per group). We also can't do this if there are any nonempty - * grouping sets; moving such a clause into WHERE would potentially change - * the results, if any referenced column isn't present in all the grouping - * sets. (If there are only empty grouping sets, then the HAVING clause - * must be degenerate as discussed below.) + * grouping sets and the clause references any columns that are nullable + * by the grouping sets; moving such a clause into WHERE would potentially + * change the results. (If there are only empty grouping sets, then the + * HAVING clause must be degenerate as discussed below.) * * Also, it may be that the clause is so expensive to execute that we're * better off doing it only once per group, despite the loss of @@ -1032,6 +1091,16 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, * don't emit a bogus aggregated row. (This could be done better, but it * seems not worth optimizing.) * + * Note that a HAVING clause may contain expressions that are not fully + * preprocessed. This can happen if these expressions are part of + * grouping items. In such cases, they are replaced with GROUP Vars in + * the parser and then replaced back after we've done with expression + * preprocessing on havingQual. This is not an issue if the clause + * remains in HAVING, because these expressions will be matched to lower + * target items in setrefs.c. However, if the clause is moved or copied + * into WHERE, we need to ensure that these expressions are fully + * preprocessed. + * * Note that both havingQual and parse->jointree->quals are in * implicitly-ANDed-list form at this point, even though they are declared * as Node *. @@ -1041,26 +1110,39 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, { Node *havingclause = (Node *) lfirst(l); - if ((parse->groupClause && parse->groupingSets) || - contain_agg_clause(havingclause) || + if (contain_agg_clause(havingclause) || contain_volatile_functions(havingclause) || - contain_subplans(havingclause)) + contain_subplans(havingclause) || + (parse->groupClause && parse->groupingSets && + bms_is_member(root->group_rtindex, pull_varnos(root, havingclause)))) { /* keep it in HAVING */ newHaving = lappend(newHaving, havingclause); } - else if (parse->groupClause && !parse->groupingSets) + else if (parse->groupClause) { - /* move it to WHERE */ + Node *whereclause; + + /* Preprocess the HAVING clause fully */ + whereclause = preprocess_expression(root, havingclause, + EXPRKIND_QUAL); + /* ... and move it to WHERE */ parse->jointree->quals = (Node *) - lappend((List *) parse->jointree->quals, havingclause); + list_concat((List *) parse->jointree->quals, + (List *) whereclause); } else { - /* put a copy in WHERE, keep it in HAVING */ + Node *whereclause; + + /* Preprocess the HAVING clause fully */ + whereclause = preprocess_expression(root, copyObject(havingclause), + EXPRKIND_QUAL); + /* ... and put a copy in WHERE */ parse->jointree->quals = (Node *) - lappend((List *) parse->jointree->quals, - copyObject(havingclause)); + list_concat((List *) parse->jointree->quals, + (List *) whereclause); + /* ... and also keep it in HAVING */ newHaving = lappend(newHaving, havingclause); } } @@ -1288,7 +1370,7 @@ preprocess_phv_expression(PlannerInfo *root, Expr *expr) * setops is used for set operation subqueries to provide the subquery with * the context in which it's being used so that Paths correctly sorted for the * set operation can be generated. NULL when not planning a set operation - * child. + * child, or when a child of a set op that isn't interested in sorted input. * * Returns nothing; the useful output is in the Paths we attach to the * (UPPERREL_FINAL, NULL) upperrel in *root. In addition, @@ -1423,8 +1505,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, { /* Preprocess regular GROUP BY clause, if any */ root->processed_groupClause = preprocess_groupclause(root, NIL); - /* Remove any redundant GROUP BY columns */ - remove_useless_groupby_columns(root); } /* @@ -1468,7 +1548,11 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, */ optimize_window_clauses(root, wflists); + /* Extract the list of windows actually in use. */ activeWindows = select_active_windows(root, wflists); + + /* Make sure they all have names, for EXPLAIN's use. */ + name_active_windows(activeWindows); } else parse->hasWindowFuncs = false; @@ -2660,166 +2744,6 @@ limit_needed(Query *parse) return false; /* don't need a Limit plan node */ } - -/* - * remove_useless_groupby_columns - * Remove any columns in the GROUP BY clause that are redundant due to - * being functionally dependent on other GROUP BY columns. - * - * Since some other DBMSes do not allow references to ungrouped columns, it's - * not unusual to find all columns listed in GROUP BY even though listing the - * primary-key columns would be sufficient. Deleting such excess columns - * avoids redundant sorting work, so it's worth doing. - * - * Relcache invalidations will ensure that cached plans become invalidated - * when the underlying index of the pkey constraint is dropped. - * - * Currently, we only make use of pkey constraints for this, however, we may - * wish to take this further in the future and also use unique constraints - * which have NOT NULL columns. In that case, plan invalidation will still - * work since relations will receive a relcache invalidation when a NOT NULL - * constraint is dropped. - */ -static void -remove_useless_groupby_columns(PlannerInfo *root) -{ - Query *parse = root->parse; - Bitmapset **groupbyattnos; - Bitmapset **surplusvars; - ListCell *lc; - int relid; - - /* No chance to do anything if there are less than two GROUP BY items */ - if (list_length(root->processed_groupClause) < 2) - return; - - /* Don't fiddle with the GROUP BY clause if the query has grouping sets */ - if (parse->groupingSets) - return; - - /* - * Scan the GROUP BY clause to find GROUP BY items that are simple Vars. - * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k - * that are GROUP BY items. - */ - groupbyattnos = (Bitmapset **) palloc0(sizeof(Bitmapset *) * - (list_length(parse->rtable) + 1)); - foreach(lc, root->processed_groupClause) - { - SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); - TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); - Var *var = (Var *) tle->expr; - - /* - * Ignore non-Vars and Vars from other query levels. - * - * XXX in principle, stable expressions containing Vars could also be - * removed, if all the Vars are functionally dependent on other GROUP - * BY items. But it's not clear that such cases occur often enough to - * be worth troubling over. - */ - if (!IsA(var, Var) || - var->varlevelsup > 0) - continue; - - /* OK, remember we have this Var */ - relid = var->varno; - Assert(relid <= list_length(parse->rtable)); - groupbyattnos[relid] = bms_add_member(groupbyattnos[relid], - var->varattno - FirstLowInvalidHeapAttributeNumber); - } - - /* - * Consider each relation and see if it is possible to remove some of its - * Vars from GROUP BY. For simplicity and speed, we do the actual removal - * in a separate pass. Here, we just fill surplusvars[k] with a bitmapset - * of the column attnos of RTE k that are removable GROUP BY items. - */ - surplusvars = NULL; /* don't allocate array unless required */ - relid = 0; - foreach(lc, parse->rtable) - { - RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); - Bitmapset *relattnos; - Bitmapset *pkattnos; - Oid constraintOid; - - relid++; - - /* Only plain relations could have primary-key constraints */ - if (rte->rtekind != RTE_RELATION) - continue; - - /* - * We must skip inheritance parent tables as some of the child rels - * may cause duplicate rows. This cannot happen with partitioned - * tables, however. - */ - if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE) - continue; - - /* Nothing to do unless this rel has multiple Vars in GROUP BY */ - relattnos = groupbyattnos[relid]; - if (bms_membership(relattnos) != BMS_MULTIPLE) - continue; - - /* - * Can't remove any columns for this rel if there is no suitable - * (i.e., nondeferrable) primary key constraint. - */ - pkattnos = get_primary_key_attnos(rte->relid, false, &constraintOid); - if (pkattnos == NULL) - continue; - - /* - * If the primary key is a proper subset of relattnos then we have - * some items in the GROUP BY that can be removed. - */ - if (bms_subset_compare(pkattnos, relattnos) == BMS_SUBSET1) - { - /* - * To easily remember whether we've found anything to do, we don't - * allocate the surplusvars[] array until we find something. - */ - if (surplusvars == NULL) - surplusvars = (Bitmapset **) palloc0(sizeof(Bitmapset *) * - (list_length(parse->rtable) + 1)); - - /* Remember the attnos of the removable columns */ - surplusvars[relid] = bms_difference(relattnos, pkattnos); - } - } - - /* - * If we found any surplus Vars, build a new GROUP BY clause without them. - * (Note: this may leave some TLEs with unreferenced ressortgroupref - * markings, but that's harmless.) - */ - if (surplusvars != NULL) - { - List *new_groupby = NIL; - - foreach(lc, root->processed_groupClause) - { - SortGroupClause *sgc = lfirst_node(SortGroupClause, lc); - TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList); - Var *var = (Var *) tle->expr; - - /* - * New list must include non-Vars, outer Vars, and anything not - * marked as surplus. - */ - if (!IsA(var, Var) || - var->varlevelsup > 0 || - !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber, - surplusvars[var->varno])) - new_groupby = lappend(new_groupby, sgc); - } - - root->processed_groupClause = new_groupby; - } -} - /* * preprocess_groupclause - do preparatory work on GROUP BY clause * @@ -3280,10 +3204,53 @@ adjust_group_pathkeys_for_groupagg(PlannerInfo *root) if (AGGKIND_IS_ORDERED_SET(aggref->aggkind)) continue; - /* only add aggregates with a DISTINCT or ORDER BY */ - if (aggref->aggdistinct != NIL || aggref->aggorder != NIL) - unprocessed_aggs = bms_add_member(unprocessed_aggs, - foreach_current_index(lc)); + /* Skip unless there's a DISTINCT or ORDER BY clause */ + if (aggref->aggdistinct == NIL && aggref->aggorder == NIL) + continue; + + /* Additional safety checks are needed if there's a FILTER clause */ + if (aggref->aggfilter != NULL) + { + ListCell *lc2; + bool allow_presort = true; + + /* + * When the Aggref has a FILTER clause, it's possible that the + * filter removes rows that cannot be sorted because the + * expression to sort by results in an error during its + * evaluation. This is a problem for presorting as that happens + * before the FILTER, whereas without presorting, the Aggregate + * node will apply the FILTER *before* sorting. So that we never + * try to sort anything that might error, here we aim to skip over + * any Aggrefs with arguments with expressions which, when + * evaluated, could cause an ERROR. Vars and Consts are ok. There + * may be more cases that should be allowed, but more thought + * needs to be given. Err on the side of caution. + */ + foreach(lc2, aggref->args) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc2); + Expr *expr = tle->expr; + + while (IsA(expr, RelabelType)) + expr = (Expr *) (castNode(RelabelType, expr))->arg; + + /* Common case, Vars and Consts are ok */ + if (IsA(expr, Var) || IsA(expr, Const)) + continue; + + /* Unsupported. Don't try to presort for this Aggref */ + allow_presort = false; + break; + } + + /* Skip unsupported Aggrefs */ + if (!allow_presort) + continue; + } + + unprocessed_aggs = bms_add_member(unprocessed_aggs, + foreach_current_index(lc)); } /* @@ -3454,9 +3421,23 @@ standard_qp_callback(PlannerInfo *root, void *extra) if (grouping_is_sortable(groupClause)) { - root->group_pathkeys = make_pathkeys_for_sortclauses(root, - groupClause, - tlist); + bool sortable; + + /* + * The groupClause is logically below the grouping step. So if + * there is an RTE entry for the grouping step, we need to remove + * its RT index from the sort expressions before we make PathKeys + * for them. + */ + root->group_pathkeys = + make_pathkeys_for_sortclauses_extended(root, + &groupClause, + tlist, + false, + parse->hasGroupRTE, + &sortable, + false); + Assert(sortable); root->num_groupby_pathkeys = list_length(root->group_pathkeys); } else @@ -3486,6 +3467,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &root->processed_groupClause, tlist, true, + false, &sortable, true); if (!sortable) @@ -3537,6 +3519,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &root->processed_distinctClause, tlist, true, + false, &sortable, false); if (!sortable) @@ -3551,8 +3534,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) tlist); /* setting setop_pathkeys might be useful to the union planner */ - if (qp_extra->setop != NULL && - set_operation_ordered_results_useful(qp_extra->setop)) + if (qp_extra->setop != NULL) { List *groupClauses; bool sortable; @@ -3564,6 +3546,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &groupClauses, tlist, false, + false, &sortable, false); if (!sortable) @@ -4017,9 +4000,10 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, * If this is the topmost relation or if the parent relation is doing * full partitionwise aggregation, then we can do full partitionwise * aggregation provided that the GROUP BY clause contains all of the - * partitioning columns at this level. Otherwise, we can do at most - * partial partitionwise aggregation. But if partial aggregation is - * not supported in general then we can't use it for partitionwise + * partitioning columns at this level and the collation used by GROUP + * BY matches the partitioning collation. Otherwise, we can do at + * most partial partitionwise aggregation. But if partial aggregation + * is not supported in general then we can't use it for partitionwise * aggregation either. * * Check parse->groupClause not processed_groupClause, because it's @@ -4866,7 +4850,10 @@ create_partial_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, /* * Try sorting the cheapest path and incrementally sorting any paths with - * presorted keys and put a unique paths atop of those. + * presorted keys and put a unique paths atop of those. We'll also + * attempt to reorder the required pathkeys to match the input path's + * pathkeys as much as possible, in hopes of avoiding a possible need to + * re-sort. */ if (grouping_is_sortable(root->processed_distinctClause)) { @@ -4874,86 +4861,67 @@ create_partial_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, { Path *input_path = (Path *) lfirst(lc); Path *sorted_path; - bool is_sorted; - int presorted_keys; + List *useful_pathkeys_list = NIL; - is_sorted = pathkeys_count_contained_in(root->distinct_pathkeys, - input_path->pathkeys, - &presorted_keys); + useful_pathkeys_list = + get_useful_pathkeys_for_distinct(root, + root->distinct_pathkeys, + input_path->pathkeys); + Assert(list_length(useful_pathkeys_list) > 0); - if (is_sorted) - sorted_path = input_path; - else + foreach_node(List, useful_pathkeys, useful_pathkeys_list) { - /* - * Try at least sorting the cheapest path and also try - * incrementally sorting any path which is partially sorted - * already (no need to deal with paths which have presorted - * keys when incremental sort is disabled unless it's the - * cheapest partial path). - */ - if (input_path != cheapest_partial_path && - (presorted_keys == 0 || !enable_incremental_sort)) + sorted_path = make_ordered_path(root, + partial_distinct_rel, + input_path, + cheapest_partial_path, + useful_pathkeys, + -1.0); + + if (sorted_path == NULL) continue; /* - * We've no need to consider both a sort and incremental sort. - * We'll just do a sort if there are no presorted keys and an - * incremental sort when there are presorted keys. + * An empty distinct_pathkeys means all tuples have the same + * value for the DISTINCT clause. See + * create_final_distinct_paths() */ - if (presorted_keys == 0 || !enable_incremental_sort) - sorted_path = (Path *) create_sort_path(root, - partial_distinct_rel, - input_path, - root->distinct_pathkeys, - -1.0); - else - sorted_path = (Path *) create_incremental_sort_path(root, - partial_distinct_rel, - input_path, - root->distinct_pathkeys, - presorted_keys, - -1.0); - } - - /* - * An empty distinct_pathkeys means all tuples have the same value - * for the DISTINCT clause. See create_final_distinct_paths() - */ - if (root->distinct_pathkeys == NIL) - { - Node *limitCount; + if (root->distinct_pathkeys == NIL) + { + Node *limitCount; - limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid, - sizeof(int64), - Int64GetDatum(1), false, - FLOAT8PASSBYVAL); + limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid, + sizeof(int64), + Int64GetDatum(1), false, + FLOAT8PASSBYVAL); - /* - * Apply a LimitPath onto the partial path to restrict the - * tuples from each worker to 1. create_final_distinct_paths - * will need to apply an additional LimitPath to restrict this - * to a single row after the Gather node. If the query - * already has a LIMIT clause, then we could end up with three - * Limit nodes in the final plan. Consolidating the top two - * of these could be done, but does not seem worth troubling - * over. - */ - add_partial_path(partial_distinct_rel, (Path *) - create_limit_path(root, partial_distinct_rel, - sorted_path, - NULL, - limitCount, - LIMIT_OPTION_COUNT, - 0, 1)); - } - else - { - add_partial_path(partial_distinct_rel, (Path *) - create_upper_unique_path(root, partial_distinct_rel, - sorted_path, - list_length(root->distinct_pathkeys), - numDistinctRows)); + /* + * Apply a LimitPath onto the partial path to restrict the + * tuples from each worker to 1. + * create_final_distinct_paths will need to apply an + * additional LimitPath to restrict this to a single row + * after the Gather node. If the query already has a + * LIMIT clause, then we could end up with three Limit + * nodes in the final plan. Consolidating the top two of + * these could be done, but does not seem worth troubling + * over. + */ + add_partial_path(partial_distinct_rel, (Path *) + create_limit_path(root, partial_distinct_rel, + sorted_path, + NULL, + limitCount, + LIMIT_OPTION_COUNT, + 0, 1)); + } + else + { + add_partial_path(partial_distinct_rel, (Path *) + create_upper_unique_path(root, partial_distinct_rel, + sorted_path, + list_length(root->distinct_pathkeys), + numDistinctRows)); + } } } } @@ -5062,7 +5030,9 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, * Unique node on those. We also, consider doing an explicit sort of * the cheapest input path and Unique'ing that. If any paths have * presorted keys then we'll create an incremental sort atop of those - * before adding a unique node on the top. + * before adding a unique node on the top. We'll also attempt to + * reorder the required pathkeys to match the input path's pathkeys as + * much as possible, in hopes of avoiding a possible need to re-sort. * * When we have DISTINCT ON, we must sort by the more rigorous of * DISTINCT and ORDER BY, else it won't have the desired behavior. @@ -5086,86 +5056,66 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, { Path *input_path = (Path *) lfirst(lc); Path *sorted_path; - bool is_sorted; - int presorted_keys; + List *useful_pathkeys_list = NIL; - is_sorted = pathkeys_count_contained_in(needed_pathkeys, - input_path->pathkeys, - &presorted_keys); + useful_pathkeys_list = + get_useful_pathkeys_for_distinct(root, + needed_pathkeys, + input_path->pathkeys); + Assert(list_length(useful_pathkeys_list) > 0); - if (is_sorted) - sorted_path = input_path; - else + foreach_node(List, useful_pathkeys, useful_pathkeys_list) { - /* - * Try at least sorting the cheapest path and also try - * incrementally sorting any path which is partially sorted - * already (no need to deal with paths which have presorted - * keys when incremental sort is disabled unless it's the - * cheapest input path). - */ - if (input_path != cheapest_input_path && - (presorted_keys == 0 || !enable_incremental_sort)) + sorted_path = make_ordered_path(root, + distinct_rel, + input_path, + cheapest_input_path, + useful_pathkeys, + limittuples); + + if (sorted_path == NULL) continue; /* - * We've no need to consider both a sort and incremental sort. - * We'll just do a sort if there are no presorted keys and an - * incremental sort when there are presorted keys. + * distinct_pathkeys may have become empty if all of the + * pathkeys were determined to be redundant. If all of the + * pathkeys are redundant then each DISTINCT target must only + * allow a single value, therefore all resulting tuples must + * be identical (or at least indistinguishable by an equality + * check). We can uniquify these tuples simply by just taking + * the first tuple. All we do here is add a path to do "LIMIT + * 1" atop of 'sorted_path'. When doing a DISTINCT ON we may + * still have a non-NIL sort_pathkeys list, so we must still + * only do this with paths which are correctly sorted by + * sort_pathkeys. */ - if (presorted_keys == 0 || !enable_incremental_sort) - sorted_path = (Path *) create_sort_path(root, - distinct_rel, - input_path, - needed_pathkeys, - limittuples); - else - sorted_path = (Path *) create_incremental_sort_path(root, - distinct_rel, - input_path, - needed_pathkeys, - presorted_keys, - limittuples); - } - - /* - * distinct_pathkeys may have become empty if all of the pathkeys - * were determined to be redundant. If all of the pathkeys are - * redundant then each DISTINCT target must only allow a single - * value, therefore all resulting tuples must be identical (or at - * least indistinguishable by an equality check). We can uniquify - * these tuples simply by just taking the first tuple. All we do - * here is add a path to do "LIMIT 1" atop of 'sorted_path'. When - * doing a DISTINCT ON we may still have a non-NIL sort_pathkeys - * list, so we must still only do this with paths which are - * correctly sorted by sort_pathkeys. - */ - if (root->distinct_pathkeys == NIL) - { - Node *limitCount; + if (root->distinct_pathkeys == NIL) + { + Node *limitCount; - limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid, - sizeof(int64), - Int64GetDatum(1), false, - FLOAT8PASSBYVAL); + limitCount = (Node *) makeConst(INT8OID, -1, InvalidOid, + sizeof(int64), + Int64GetDatum(1), false, + FLOAT8PASSBYVAL); - /* - * If the query already has a LIMIT clause, then we could end - * up with a duplicate LimitPath in the final plan. That does - * not seem worth troubling over too much. - */ - add_path(distinct_rel, (Path *) - create_limit_path(root, distinct_rel, sorted_path, - NULL, limitCount, - LIMIT_OPTION_COUNT, 0, 1)); - } - else - { - add_path(distinct_rel, (Path *) - create_upper_unique_path(root, distinct_rel, - sorted_path, - list_length(root->distinct_pathkeys), - numDistinctRows)); + /* + * If the query already has a LIMIT clause, then we could + * end up with a duplicate LimitPath in the final plan. + * That does not seem worth troubling over too much. + */ + add_path(distinct_rel, (Path *) + create_limit_path(root, distinct_rel, sorted_path, + NULL, limitCount, + LIMIT_OPTION_COUNT, 0, 1)); + } + else + { + add_path(distinct_rel, (Path *) + create_upper_unique_path(root, distinct_rel, + sorted_path, + list_length(root->distinct_pathkeys), + numDistinctRows)); + } } } } @@ -5208,6 +5158,82 @@ create_final_distinct_paths(PlannerInfo *root, RelOptInfo *input_rel, return distinct_rel; } +/* + * get_useful_pathkeys_for_distinct + * Get useful orderings of pathkeys for distinctClause by reordering + * 'needed_pathkeys' to match the given 'path_pathkeys' as much as possible. + * + * This returns a list of pathkeys that can be useful for DISTINCT or DISTINCT + * ON clause. For convenience, it always includes the given 'needed_pathkeys'. + */ +static List * +get_useful_pathkeys_for_distinct(PlannerInfo *root, List *needed_pathkeys, + List *path_pathkeys) +{ + List *useful_pathkeys_list = NIL; + List *useful_pathkeys = NIL; + + /* always include the given 'needed_pathkeys' */ + useful_pathkeys_list = lappend(useful_pathkeys_list, + needed_pathkeys); + + if (!enable_distinct_reordering) + return useful_pathkeys_list; + + /* + * Scan the given 'path_pathkeys' and construct a list of PathKey nodes + * that match 'needed_pathkeys', but only up to the longest matching + * prefix. + * + * When we have DISTINCT ON, we must ensure that the resulting pathkey + * list matches initial distinctClause pathkeys; otherwise, it won't have + * the desired behavior. + */ + foreach_node(PathKey, pathkey, path_pathkeys) + { + /* + * The PathKey nodes are canonical, so they can be checked for + * equality by simple pointer comparison. + */ + if (!list_member_ptr(needed_pathkeys, pathkey)) + break; + if (root->parse->hasDistinctOn && + !list_member_ptr(root->distinct_pathkeys, pathkey)) + break; + + useful_pathkeys = lappend(useful_pathkeys, pathkey); + } + + /* If no match at all, no point in reordering needed_pathkeys */ + if (useful_pathkeys == NIL) + return useful_pathkeys_list; + + /* + * If not full match, the resulting pathkey list is not useful without + * incremental sort. + */ + if (list_length(useful_pathkeys) < list_length(needed_pathkeys) && + !enable_incremental_sort) + return useful_pathkeys_list; + + /* Append the remaining PathKey nodes in needed_pathkeys */ + useful_pathkeys = list_concat_unique_ptr(useful_pathkeys, + needed_pathkeys); + + /* + * If the resulting pathkey list is the same as the 'needed_pathkeys', + * just drop it. + */ + if (compare_pathkeys(needed_pathkeys, + useful_pathkeys) == PATHKEYS_EQUAL) + return useful_pathkeys_list; + + useful_pathkeys_list = lappend(useful_pathkeys_list, + useful_pathkeys); + + return useful_pathkeys_list; +} + /* * create_ordered_paths * @@ -5300,8 +5326,11 @@ create_ordered_paths(PlannerInfo *root, limit_tuples); } - /* Add projection step if needed */ - if (sorted_path->pathtarget != target) + /* + * If the pathtarget of the result path has different expressions from + * the target to be applied, a projection step is needed. + */ + if (!equal(sorted_path->pathtarget->exprs, target->exprs)) sorted_path = apply_projection_to_path(root, ordered_rel, sorted_path, target); @@ -5378,8 +5407,11 @@ create_ordered_paths(PlannerInfo *root, root->sort_pathkeys, NULL, &total_groups); - /* Add projection step if needed */ - if (sorted_path->pathtarget != target) + /* + * If the pathtarget of the result path has different expressions + * from the target to be applied, a projection step is needed. + */ + if (!equal(sorted_path->pathtarget->exprs, target->exprs)) sorted_path = apply_projection_to_path(root, ordered_rel, sorted_path, target); @@ -5468,7 +5500,19 @@ make_group_input_target(PlannerInfo *root, PathTarget *final_target) { /* * It's a grouping column, so add it to the input target as-is. + * + * Note that the target is logically below the grouping step. So + * with grouping sets we need to remove the RT index of the + * grouping step if there is any from the target expression. */ + if (parse->hasGroupRTE && parse->groupingSets != NIL) + { + Assert(root->group_rtindex > 0); + expr = (Expr *) + remove_nulling_relids((Node *) expr, + bms_make_singleton(root->group_rtindex), + NULL); + } add_column_to_pathtarget(input_target, expr, sgref); } else @@ -5496,11 +5540,23 @@ make_group_input_target(PlannerInfo *root, PathTarget *final_target) * includes Vars used in resjunk items, so we are covering the needs of * ORDER BY and window specifications. Vars used within Aggrefs and * WindowFuncs will be pulled out here, too. + * + * Note that the target is logically below the grouping step. So with + * grouping sets we need to remove the RT index of the grouping step if + * there is any from the non-group Vars. */ non_group_vars = pull_var_clause((Node *) non_group_cols, PVC_RECURSE_AGGREGATES | PVC_RECURSE_WINDOWFUNCS | PVC_INCLUDE_PLACEHOLDERS); + if (parse->hasGroupRTE && parse->groupingSets != NIL) + { + Assert(root->group_rtindex > 0); + non_group_vars = (List *) + remove_nulling_relids((Node *) non_group_vars, + bms_make_singleton(root->group_rtindex), + NULL); + } add_new_columns_to_pathtarget(input_target, non_group_vars); /* clean up cruft */ @@ -5914,6 +5970,52 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists) return result; } +/* + * name_active_windows + * Ensure all active windows have unique names. + * + * The parser will have checked that user-assigned window names are unique + * within the Query. Here we assign made-up names to any unnamed + * WindowClauses for the benefit of EXPLAIN. (We don't want to do this + * at parse time, because it'd mess up decompilation of views.) + * + * activeWindows: result of select_active_windows + */ +static void +name_active_windows(List *activeWindows) +{ + int next_n = 1; + char newname[16]; + ListCell *lc; + + foreach(lc, activeWindows) + { + WindowClause *wc = lfirst_node(WindowClause, lc); + + /* Nothing to do if it has a name already. */ + if (wc->name) + continue; + + /* Select a name not currently present in the list. */ + for (;;) + { + ListCell *lc2; + + snprintf(newname, sizeof(newname), "w%d", next_n++); + foreach(lc2, activeWindows) + { + WindowClause *wc2 = lfirst_node(WindowClause, lc2); + + if (wc2->name && strcmp(wc2->name, newname) == 0) + break; /* matched */ + } + if (lc2 == NULL) + break; /* reached the end with no match */ + } + wc->name = pstrdup(newname); + } +} + /* * common_prefix_cmp * QSort comparison function for WindowClauseSortData @@ -6149,6 +6251,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc, &wc->partitionClause, tlist, true, + false, &sortable, false); @@ -6413,6 +6516,11 @@ make_sort_input_target(PlannerInfo *root, * Find the cheapest path for retrieving a specified fraction of all * the tuples expected to be returned by the given relation. * + * Do not consider parameterized paths. If the caller needs a path for upper + * rel, it can't have parameterized paths. If the caller needs an append + * subpath, it could become limited by the treatment of similar + * parameterization of all the subpaths. + * * We interpret tuple_fraction the same way as grouping_planner. * * We assume set_cheapest() has been run on the given rel. @@ -6435,6 +6543,9 @@ get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction) { Path *path = (Path *) lfirst(l); + if (path->param_info) + continue; + if (path == rel->cheapest_total_path || compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0) continue; @@ -6748,6 +6859,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) /* Estimate the cost of seq scan + sort */ seqScanPath = create_seqscan_path(root, rel, NULL, 0); cost_sort(&seqScanAndSortPath, root, NIL, + seqScanPath->disabled_nodes, seqScanPath->total_cost, rel->tuples, rel->reltarget->width, comparisonCost, maintenance_work_mem, -1.0); @@ -6766,7 +6878,8 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) * CREATE INDEX should request for use * * tableOid is the table on which the index is to be built. indexOid is the - * OID of an index to be created or reindexed (which must be a btree index). + * OID of an index to be created or reindexed (which must be an index with + * support for parallel builds - currently btree or BRIN). * * Return value is the number of parallel worker processes to request. It * may be unsafe to proceed if this is 0. Note that this does not include the @@ -6894,7 +7007,7 @@ plan_create_index_workers(Oid tableOid, Oid indexOid) * parallel worker to sort. */ while (parallel_workers > 0 && - maintenance_work_mem / (parallel_workers + 1) < 32768L) + maintenance_work_mem / (parallel_workers + 1) < 32 * 1024) parallel_workers--; done: @@ -6904,58 +7017,6 @@ plan_create_index_workers(Oid tableOid, Oid indexOid) return parallel_workers; } -/* - * make_ordered_path - * Return a path ordered by 'pathkeys' based on the given 'path'. May - * return NULL if it doesn't make sense to generate an ordered path in - * this case. - */ -static Path * -make_ordered_path(PlannerInfo *root, RelOptInfo *rel, Path *path, - Path *cheapest_path, List *pathkeys) -{ - bool is_sorted; - int presorted_keys; - - is_sorted = pathkeys_count_contained_in(pathkeys, - path->pathkeys, - &presorted_keys); - - if (!is_sorted) - { - /* - * Try at least sorting the cheapest path and also try incrementally - * sorting any path which is partially sorted already (no need to deal - * with paths which have presorted keys when incremental sort is - * disabled unless it's the cheapest input path). - */ - if (path != cheapest_path && - (presorted_keys == 0 || !enable_incremental_sort)) - return NULL; - - /* - * We've no need to consider both a sort and incremental sort. We'll - * just do a sort if there are no presorted keys and an incremental - * sort when there are presorted keys. - */ - if (presorted_keys == 0 || !enable_incremental_sort) - path = (Path *) create_sort_path(root, - rel, - path, - pathkeys, - -1.0); - else - path = (Path *) create_incremental_sort_path(root, - rel, - path, - pathkeys, - presorted_keys, - -1.0); - } - - return path; -} - /* * add_paths_to_grouping_rel * @@ -7007,7 +7068,8 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel, grouped_rel, path, cheapest_path, - info->pathkeys); + info->pathkeys, + -1.0); if (path == NULL) continue; @@ -7088,7 +7150,8 @@ add_paths_to_grouping_rel(PlannerInfo *root, RelOptInfo *input_rel, grouped_rel, path, partially_grouped_rel->cheapest_total_path, - info->pathkeys); + info->pathkeys, + -1.0); if (path == NULL) continue; @@ -7339,7 +7402,8 @@ create_partial_grouping_paths(PlannerInfo *root, partially_grouped_rel, path, cheapest_total_path, - info->pathkeys); + info->pathkeys, + -1.0); if (path == NULL) continue; @@ -7396,7 +7460,8 @@ create_partial_grouping_paths(PlannerInfo *root, partially_grouped_rel, path, cheapest_partial_path, - info->pathkeys); + info->pathkeys, + -1.0); if (path == NULL) continue; @@ -7482,6 +7547,58 @@ create_partial_grouping_paths(PlannerInfo *root, return partially_grouped_rel; } +/* + * make_ordered_path + * Return a path ordered by 'pathkeys' based on the given 'path'. May + * return NULL if it doesn't make sense to generate an ordered path in + * this case. + */ +static Path * +make_ordered_path(PlannerInfo *root, RelOptInfo *rel, Path *path, + Path *cheapest_path, List *pathkeys, double limit_tuples) +{ + bool is_sorted; + int presorted_keys; + + is_sorted = pathkeys_count_contained_in(pathkeys, + path->pathkeys, + &presorted_keys); + + if (!is_sorted) + { + /* + * Try at least sorting the cheapest path and also try incrementally + * sorting any path which is partially sorted already (no need to deal + * with paths which have presorted keys when incremental sort is + * disabled unless it's the cheapest input path). + */ + if (path != cheapest_path && + (presorted_keys == 0 || !enable_incremental_sort)) + return NULL; + + /* + * We've no need to consider both a sort and incremental sort. We'll + * just do a sort if there are no presorted keys and an incremental + * sort when there are presorted keys. + */ + if (presorted_keys == 0 || !enable_incremental_sort) + path = (Path *) create_sort_path(root, + rel, + path, + pathkeys, + limit_tuples); + else + path = (Path *) create_incremental_sort_path(root, + rel, + path, + pathkeys, + presorted_keys, + limit_tuples); + } + + return path; +} + /* * Generate Gather and Gather Merge paths for a grouping relation or partial * grouping relation. @@ -7996,8 +8113,8 @@ create_partitionwise_grouping_paths(PlannerInfo *root, /* * group_by_has_partkey * - * Returns true, if all the partition keys of the given relation are part of - * the GROUP BY clauses, false otherwise. + * Returns true if all the partition keys of the given relation are part of + * the GROUP BY clauses, including having matching collation, false otherwise. */ static bool group_by_has_partkey(RelOptInfo *input_rel, @@ -8025,13 +8142,40 @@ group_by_has_partkey(RelOptInfo *input_rel, foreach(lc, partexprs) { + ListCell *lg; Expr *partexpr = lfirst(lc); + Oid partcoll = input_rel->part_scheme->partcollation[cnt]; - if (list_member(groupexprs, partexpr)) + foreach(lg, groupexprs) { - found = true; - break; + Expr *groupexpr = lfirst(lg); + Oid groupcoll = exprCollation((Node *) groupexpr); + + /* + * Note: we can assume there is at most one RelabelType node; + * eval_const_expressions() will have simplified if more than + * one. + */ + if (IsA(groupexpr, RelabelType)) + groupexpr = ((RelabelType *) groupexpr)->arg; + + if (equal(groupexpr, partexpr)) + { + /* + * Reject a match if the grouping collation does not match + * the partitioning collation. + */ + if (OidIsValid(partcoll) && OidIsValid(groupcoll) && + partcoll != groupcoll) + return false; + + found = true; + break; + } } + + if (found) + break; } /* @@ -8054,7 +8198,10 @@ group_by_has_partkey(RelOptInfo *input_rel, * child query's targetlist entries may already have a tleSortGroupRef * assigned for other purposes, such as GROUP BYs. Here we keep the * SortGroupClause list in the same order as 'op' groupClauses and just adjust - * the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'. + * the tleSortGroupRef to reference the TargetEntry's 'ressortgroupref'. If + * any of the columns in the targetlist don't match to the setop's colTypes + * then we return an empty list. This may leave some TLEs with unreferenced + * ressortgroupref markings, but that's harmless. */ static List * generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist) @@ -8062,25 +8209,42 @@ generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist) List *grouplist = copyObject(op->groupClauses); ListCell *lg; ListCell *lt; + ListCell *ct; lg = list_head(grouplist); + ct = list_head(op->colTypes); foreach(lt, targetlist) { TargetEntry *tle = (TargetEntry *) lfirst(lt); SortGroupClause *sgc; + Oid coltype; /* resjunk columns could have sortgrouprefs. Leave these alone */ if (tle->resjunk) continue; - /* we expect every non-resjunk target to have a SortGroupClause */ + /* + * We expect every non-resjunk target to have a SortGroupClause and + * colTypes. + */ Assert(lg != NULL); + Assert(ct != NULL); sgc = (SortGroupClause *) lfirst(lg); + coltype = lfirst_oid(ct); + + /* reject if target type isn't the same as the setop target type */ + if (coltype != exprType((Node *) tle->expr)) + return NIL; + lg = lnext(grouplist, lg); + ct = lnext(op->colTypes, ct); /* assign a tleSortGroupRef, or reuse the existing one */ sgc->tleSortGroupRef = assignSortGroupRef(tle, targetlist); } + Assert(lg == NULL); + Assert(ct == NULL); + return grouplist; } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 7aed84584c670..846e44186c366 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -4,7 +4,7 @@ * Post-processing of a completed plan tree: fix references to subplan * vars, compute regproc values for operators, etc * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,6 +26,7 @@ #include "optimizer/subselect.h" #include "optimizer/tlist.h" #include "parser/parse_relation.h" +#include "rewrite/rewriteManip.h" #include "tcop/utility.h" #include "utils/syscache.h" @@ -484,7 +485,7 @@ flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte) /* Use query_tree_walker to find all RTEs in the parse tree */ (void) query_tree_walker(rte->subquery, flatten_rtes_walker, - (void *) &cxt, + &cxt, QTW_EXAMINE_RTES_BEFORE); } @@ -515,13 +516,12 @@ flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt) cxt->query = (Query *) node; result = query_tree_walker((Query *) node, flatten_rtes_walker, - (void *) cxt, + cxt, QTW_EXAMINE_RTES_BEFORE); cxt->query = save_query; return result; } - return expression_tree_walker(node, flatten_rtes_walker, - (void *) cxt); + return expression_tree_walker(node, flatten_rtes_walker, cxt); } /* @@ -557,13 +557,16 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos, newrte->coltypes = NIL; newrte->coltypmods = NIL; newrte->colcollations = NIL; + newrte->groupexprs = NIL; newrte->securityQuals = NIL; glob->finalrtable = lappend(glob->finalrtable, newrte); /* * If it's a plain relation RTE (or a subquery that was once a view - * reference), add the relation OID to relationOids. + * reference), add the relation OID to relationOids. Also add its new RT + * index to the set of relations to be potentially accessed during + * execution. * * We do this even though the RTE might be unreferenced in the plan tree; * this would correspond to cases such as views that were expanded, child @@ -575,7 +578,11 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos, */ if (newrte->rtekind == RTE_RELATION || (newrte->rtekind == RTE_SUBQUERY && OidIsValid(newrte->relid))) + { glob->relationOids = lappend_oid(glob->relationOids, newrte->relid); + glob->allRelids = bms_add_member(glob->allRelids, + list_length(glob->finalrtable)); + } /* * Add a copy of the RTEPermissionInfo, if any, corresponding to this RTE @@ -1090,9 +1097,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) /* * Set up the visible plan targetlist as being the same as - * the first RETURNING list. This is for the use of - * EXPLAIN; the executor won't pay any attention to the - * targetlist. We postpone this step until here so that + * the first RETURNING list. This is mostly for the use + * of EXPLAIN; the executor won't execute that targetlist, + * although it does use it to prepare the node's result + * tuple slot. We postpone this step until here so that * we don't have to do set_returning_clause_references() * twice on identical targetlists. */ @@ -1730,6 +1738,74 @@ set_customscan_references(PlannerInfo *root, cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset); } +/* + * register_partpruneinfo + * Subroutine for set_append_references and set_mergeappend_references + * + * Add the PartitionPruneInfo from root->partPruneInfos at the given index + * into PlannerGlobal->partPruneInfos and return its index there. + * + * Also update the RT indexes present in PartitionedRelPruneInfos to add the + * offset. + * + * Finally, if there are initial pruning steps, add the RT indexes of the + * leaf partitions to the set of relations that are prunable at execution + * startup time. + */ +static int +register_partpruneinfo(PlannerInfo *root, int part_prune_index, int rtoffset) +{ + PlannerGlobal *glob = root->glob; + PartitionPruneInfo *pinfo; + ListCell *l; + + Assert(part_prune_index >= 0 && + part_prune_index < list_length(root->partPruneInfos)); + pinfo = list_nth_node(PartitionPruneInfo, root->partPruneInfos, + part_prune_index); + + pinfo->relids = offset_relid_set(pinfo->relids, rtoffset); + foreach(l, pinfo->prune_infos) + { + List *prune_infos = lfirst(l); + ListCell *l2; + + foreach(l2, prune_infos) + { + PartitionedRelPruneInfo *prelinfo = lfirst(l2); + int i; + + prelinfo->rtindex += rtoffset; + prelinfo->initial_pruning_steps = + fix_scan_list(root, prelinfo->initial_pruning_steps, + rtoffset, 1); + prelinfo->exec_pruning_steps = + fix_scan_list(root, prelinfo->exec_pruning_steps, + rtoffset, 1); + + for (i = 0; i < prelinfo->nparts; i++) + { + /* + * Non-leaf partitions and partitions that do not have a + * subplan are not included in this map as mentioned in + * make_partitionedrel_pruneinfo(). + */ + if (prelinfo->leafpart_rti_map[i]) + { + prelinfo->leafpart_rti_map[i] += rtoffset; + if (prelinfo->initial_pruning_steps) + glob->prunableRelids = bms_add_member(glob->prunableRelids, + prelinfo->leafpart_rti_map[i]); + } + } + } + } + + glob->partPruneInfos = lappend(glob->partPruneInfos, pinfo); + + return list_length(glob->partPruneInfos) - 1; +} + /* * set_append_references * Do set_plan_references processing on an Append @@ -1782,21 +1858,13 @@ set_append_references(PlannerInfo *root, aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset); - if (aplan->part_prune_info) - { - foreach(l, aplan->part_prune_info->prune_infos) - { - List *prune_infos = lfirst(l); - ListCell *l2; - - foreach(l2, prune_infos) - { - PartitionedRelPruneInfo *pinfo = lfirst(l2); - - pinfo->rtindex += rtoffset; - } - } - } + /* + * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index. + * Also update the RT indexes present in it to add the offset. + */ + if (aplan->part_prune_index >= 0) + aplan->part_prune_index = + register_partpruneinfo(root, aplan->part_prune_index, rtoffset); /* We don't need to recurse to lefttree or righttree ... */ Assert(aplan->plan.lefttree == NULL); @@ -1858,21 +1926,13 @@ set_mergeappend_references(PlannerInfo *root, mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset); - if (mplan->part_prune_info) - { - foreach(l, mplan->part_prune_info->prune_infos) - { - List *prune_infos = lfirst(l); - ListCell *l2; - - foreach(l2, prune_infos) - { - PartitionedRelPruneInfo *pinfo = lfirst(l2); - - pinfo->rtindex += rtoffset; - } - } - } + /* + * Add PartitionPruneInfo, if any, to PlannerGlobal and update the index. + * Also update the RT indexes present in it to add the offset. + */ + if (mplan->part_prune_index >= 0) + mplan->part_prune_index = + register_partpruneinfo(root, mplan->part_prune_index, rtoffset); /* We don't need to recurse to lefttree or righttree ... */ Assert(mplan->plan.lefttree == NULL); @@ -2241,8 +2301,7 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context) context->num_exec), context); fix_expr_common(context->root, node); - return expression_tree_mutator(node, fix_scan_expr_mutator, - (void *) context); + return expression_tree_mutator(node, fix_scan_expr_mutator, context); } static bool @@ -2254,8 +2313,7 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context) Assert(!IsA(node, PlaceHolderVar)); Assert(!IsA(node, AlternativeSubPlan)); fix_expr_common(context->root, node); - return expression_tree_walker(node, fix_scan_expr_walker, - (void *) context); + return expression_tree_walker(node, fix_scan_expr_walker, context); } /* @@ -2425,6 +2483,28 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset) subplan_itlist = build_tlist_index(subplan->targetlist); + /* + * If it's a grouping node with grouping sets, any Vars and PHVs appearing + * in the targetlist and quals should have nullingrels that include the + * effects of the grouping step, ie they will have nullingrels equal to + * the input Vars/PHVs' nullingrels plus the RT index of the grouping + * step. In order to perform exact nullingrels matches, we remove the RT + * index of the grouping step first. + */ + if (IsA(plan, Agg) && + root->group_rtindex > 0 && + ((Agg *) plan)->groupingSets) + { + plan->targetlist = (List *) + remove_nulling_relids((Node *) plan->targetlist, + bms_make_singleton(root->group_rtindex), + NULL); + plan->qual = (List *) + remove_nulling_relids((Node *) plan->qual, + bms_make_singleton(root->group_rtindex), + NULL); + } + output_targetlist = NIL; foreach(l, plan->targetlist) { @@ -2588,8 +2668,7 @@ convert_combining_aggrefs(Node *node, void *context) return (Node *) parent_agg; } - return expression_tree_mutator(node, convert_combining_aggrefs, - (void *) context); + return expression_tree_mutator(node, convert_combining_aggrefs, context); } /* @@ -3050,6 +3129,21 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context) { Var *var = (Var *) node; + /* + * Verify that Vars with non-default varreturningtype only appear in + * the RETURNING list, and refer to the target relation. + */ + if (var->varreturningtype != VAR_RETURNING_DEFAULT) + { + if (context->inner_itlist != NULL || + context->outer_itlist == NULL || + context->acceptable_rel == 0) + elog(ERROR, "variable returning old/new found outside RETURNING list"); + if (var->varno != context->acceptable_rel) + elog(ERROR, "wrong varno %d (expected %d) for variable returning old/new", + var->varno, context->acceptable_rel); + } + /* Look for the var in the input tlists, first in the outer */ if (context->outer_itlist) { @@ -3141,9 +3235,7 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context) context->num_exec), context); fix_expr_common(context->root, node); - return expression_tree_mutator(node, - fix_join_expr_mutator, - (void *) context); + return expression_tree_mutator(node, fix_join_expr_mutator, context); } /* @@ -3268,9 +3360,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context) context->num_exec), context); fix_expr_common(context->root, node); - return expression_tree_mutator(node, - fix_upper_expr_mutator, - (void *) context); + return expression_tree_mutator(node, fix_upper_expr_mutator, context); } /* @@ -3366,7 +3456,7 @@ fix_windowagg_condition_expr_mutator(Node *node, return expression_tree_mutator(node, fix_windowagg_condition_expr_mutator, - (void *) context); + context); } /* @@ -3632,10 +3722,10 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context) /* And recurse into the query's subexpressions */ return query_tree_walker(query, extract_query_dependencies_walker, - (void *) context, 0); + context, 0); } /* Extract function dependencies and check for regclass Consts */ fix_expr_common(context, node); return expression_tree_walker(node, extract_query_dependencies_walker, - (void *) context); + context); } diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 6d003cc8e5cbe..e7cb3fede6658 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -6,7 +6,7 @@ * This module deals with SubLinks and CTEs, but not subquery RTEs (i.e., * not sub-SELECT-in-FROM cases). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -354,17 +354,19 @@ build_subplan(PlannerInfo *root, Plan *plan, Path *path, Node *arg = pitem->item; /* - * The Var, PlaceHolderVar, Aggref or GroupingFunc has already been - * adjusted to have the correct varlevelsup, phlevelsup, or - * agglevelsup. + * The Var, PlaceHolderVar, Aggref, GroupingFunc, or ReturningExpr has + * already been adjusted to have the correct varlevelsup, phlevelsup, + * agglevelsup, or retlevelsup. * - * If it's a PlaceHolderVar, Aggref or GroupingFunc, its arguments - * might contain SubLinks, which have not yet been processed (see the - * comments for SS_replace_correlation_vars). Do that now. + * If it's a PlaceHolderVar, Aggref, GroupingFunc, or ReturningExpr, + * its arguments might contain SubLinks, which have not yet been + * processed (see the comments for SS_replace_correlation_vars). Do + * that now. */ if (IsA(arg, PlaceHolderVar) || IsA(arg, Aggref) || - IsA(arg, GroupingFunc)) + IsA(arg, GroupingFunc) || + IsA(arg, ReturningExpr)) arg = SS_process_sublinks(root, arg, false); splan->parParam = lappend_int(splan->parParam, pitem->paramId); @@ -697,9 +699,7 @@ convert_testexpr_mutator(Node *node, */ return node; } - return expression_tree_mutator(node, - convert_testexpr_mutator, - (void *) context); + return expression_tree_mutator(node, convert_testexpr_mutator, context); } /* @@ -1121,14 +1121,13 @@ contain_outer_selfref_walker(Node *node, Index *depth) (*depth)++; result = query_tree_walker(query, contain_outer_selfref_walker, - (void *) depth, QTW_EXAMINE_RTES_BEFORE); + depth, QTW_EXAMINE_RTES_BEFORE); (*depth)--; return result; } - return expression_tree_walker(node, contain_outer_selfref_walker, - (void *) depth); + return expression_tree_walker(node, contain_outer_selfref_walker, depth); } /* @@ -1215,6 +1214,86 @@ inline_cte_walker(Node *node, inline_cte_walker_context *context) return expression_tree_walker(node, inline_cte_walker, context); } +/* + * Attempt to transform 'testexpr' over the VALUES subquery into + * a ScalarArrayOpExpr. We currently support the transformation only when + * it ends up with a constant array. Otherwise, the evaluation of non-hashed + * SAOP might be slower than the corresponding Hash Join with VALUES. + * + * Return transformed ScalarArrayOpExpr or NULL if transformation isn't + * allowed. + */ +ScalarArrayOpExpr * +convert_VALUES_to_ANY(PlannerInfo *root, Node *testexpr, Query *values) +{ + RangeTblEntry *rte; + Node *leftop; + Node *rightop; + Oid opno; + ListCell *lc; + Oid inputcollid; + List *exprs = NIL; + + /* + * Check we have a binary operator over a single-column subquery with no + * joins and no LIMIT/OFFSET/ORDER BY clauses. + */ + if (!IsA(testexpr, OpExpr) || + list_length(((OpExpr *) testexpr)->args) != 2 || + list_length(values->targetList) > 1 || + values->limitCount != NULL || + values->limitOffset != NULL || + values->sortClause != NIL || + list_length(values->rtable) != 1) + return NULL; + + rte = linitial_node(RangeTblEntry, values->rtable); + leftop = linitial(((OpExpr *) testexpr)->args); + rightop = lsecond(((OpExpr *) testexpr)->args); + opno = ((OpExpr *) testexpr)->opno; + inputcollid = ((OpExpr *) testexpr)->inputcollid; + + /* + * Also, check that only RTE corresponds to VALUES; the list of values has + * at least two items and no volatile functions. + */ + if (rte->rtekind != RTE_VALUES || + list_length(rte->values_lists) < 2 || + contain_volatile_functions((Node *) rte->values_lists)) + return NULL; + + foreach(lc, rte->values_lists) + { + List *elem = lfirst(lc); + Node *value = linitial(elem); + + /* + * Prepare an evaluation of the right side of the operator with + * substitution of the given value. + */ + value = convert_testexpr(root, rightop, list_make1(value)); + + /* + * Try to evaluate constant expressions. We could get Const as a + * result. + */ + value = eval_const_expressions(root, value); + + /* + * As we only support constant output arrays, all the items must also + * be constant. + */ + if (!IsA(value, Const)) + return NULL; + + exprs = lappend(exprs, value); + } + + /* Finally, build ScalarArrayOpExpr at the top of the 'exprs' list. */ + return make_SAOP_expr(opno, leftop, exprType(rightop), + linitial_oid(rte->colcollations), inputcollid, + exprs, false); +} /* * convert_ANY_sublink_to_join: try to convert an ANY SubLink to a join @@ -1539,6 +1618,8 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, static bool simplify_EXISTS_query(PlannerInfo *root, Query *query) { + ListCell *lc; + /* * We don't try to simplify at all if the query uses set operations, * aggregates, grouping sets, SRFs, modifying CTEs, HAVING, OFFSET, or FOR @@ -1607,6 +1688,28 @@ simplify_EXISTS_query(PlannerInfo *root, Query *query) query->sortClause = NIL; query->hasDistinctOn = false; + /* + * Since we have thrown away the GROUP BY clauses, we'd better remove the + * RTE_GROUP RTE and clear the hasGroupRTE flag. + */ + foreach(lc, query->rtable) + { + RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc); + + /* + * Remove the RTE_GROUP RTE and clear the hasGroupRTE flag. (Since + * we'll exit the foreach loop immediately, we don't bother with + * foreach_delete_current.) + */ + if (rte->rtekind == RTE_GROUP) + { + Assert(query->hasGroupRTE); + query->rtable = list_delete_cell(query->rtable, lc); + query->hasGroupRTE = false; + break; + } + } + return true; } @@ -1842,8 +1945,8 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect, /* * Replace correlation vars (uplevel vars) with Params. * - * Uplevel PlaceHolderVars, aggregates, GROUPING() expressions, and - * MergeSupportFuncs are replaced, too. + * Uplevel PlaceHolderVars, aggregates, GROUPING() expressions, + * MergeSupportFuncs, and ReturningExprs are replaced, too. * * Note: it is critical that this runs immediately after SS_process_sublinks. * Since we do not recurse into the arguments of uplevel PHVs and aggregates, @@ -1903,9 +2006,13 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root) return (Node *) replace_outer_merge_support(root, (MergeSupportFunc *) node); } - return expression_tree_mutator(node, - replace_correlation_vars_mutator, - (void *) root); + if (IsA(node, ReturningExpr)) + { + if (((ReturningExpr *) node)->retlevelsup > 0) + return (Node *) replace_outer_returning(root, + (ReturningExpr *) node); + } + return expression_tree_mutator(node, replace_correlation_vars_mutator, root); } /* @@ -1958,11 +2065,11 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context) } /* - * Don't recurse into the arguments of an outer PHV, Aggref or - * GroupingFunc here. Any SubLinks in the arguments have to be dealt with - * at the outer query level; they'll be handled when build_subplan - * collects the PHV, Aggref or GroupingFunc into the arguments to be - * passed down to the current subplan. + * Don't recurse into the arguments of an outer PHV, Aggref, GroupingFunc, + * or ReturningExpr here. Any SubLinks in the arguments have to be dealt + * with at the outer query level; they'll be handled when build_subplan + * collects the PHV, Aggref, GroupingFunc, or ReturningExpr into the + * arguments to be passed down to the current subplan. */ if (IsA(node, PlaceHolderVar)) { @@ -1979,6 +2086,11 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context) if (((GroupingFunc *) node)->agglevelsup > 0) return node; } + else if (IsA(node, ReturningExpr)) + { + if (((ReturningExpr *) node)->retlevelsup > 0) + return node; + } /* * We should never see a SubPlan expression in the input (since this is @@ -2053,7 +2165,7 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context) return expression_tree_mutator(node, process_sublinks_mutator, - (void *) &locContext); + &locContext); } /* @@ -2091,7 +2203,9 @@ SS_identify_outer_params(PlannerInfo *root) outer_params = NULL; for (proot = root->parent_root; proot != NULL; proot = proot->parent_root) { - /* Include ordinary Var/PHV/Aggref/GroupingFunc params */ + /* + * Include ordinary Var/PHV/Aggref/GroupingFunc/ReturningExpr params. + */ foreach(l, proot->plan_params) { PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l); @@ -2961,8 +3075,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context) return false; /* no more to do here */ } - return expression_tree_walker(node, finalize_primnode, - (void *) context); + return expression_tree_walker(node, finalize_primnode, context); } /* @@ -2984,8 +3097,7 @@ finalize_agg_primnode(Node *node, finalize_primnode_context *context) finalize_primnode((Node *) agg->aggfilter, context); return false; /* there can't be any Aggrefs below here */ } - return expression_tree_walker(node, finalize_agg_primnode, - (void *) context); + return expression_tree_walker(node, finalize_agg_primnode, context); } /* diff --git a/src/backend/optimizer/prep/meson.build b/src/backend/optimizer/prep/meson.build index ac37c98e13b27..4e219148a7b8b 100644 --- a/src/backend/optimizer/prep/meson.build +++ b/src/backend/optimizer/prep/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'prepagg.c', diff --git a/src/backend/optimizer/prep/prepagg.c b/src/backend/optimizer/prep/prepagg.c index 4606df379a82e..c0a2f04a8c30f 100644 --- a/src/backend/optimizer/prep/prepagg.c +++ b/src/backend/optimizer/prep/prepagg.c @@ -22,7 +22,7 @@ * at executor startup. The Agg nodes are constructed much later in the * planning, however, so it's not trivial. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -359,8 +359,7 @@ preprocess_aggrefs_walker(Node *node, PlannerInfo *root) return false; } Assert(!IsA(node, SubLink)); - return expression_tree_walker(node, preprocess_aggrefs_walker, - (void *) root); + return expression_tree_walker(node, preprocess_aggrefs_walker, root); } diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 969e257f70b40..87dc6f56b576f 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -7,6 +7,7 @@ * replace_empty_jointree * pull_up_sublinks * preprocess_function_rtes + * expand_virtual_generated_columns * pull_up_subqueries * flatten_simple_union_all * do expression preprocessing (including flattening JOIN alias vars) @@ -14,7 +15,7 @@ * remove_useless_result_rtes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -25,6 +26,7 @@ */ #include "postgres.h" +#include "access/table.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "miscadmin.h" @@ -39,19 +41,45 @@ #include "optimizer/tlist.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" +#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" +#include "utils/rel.h" +typedef struct nullingrel_info +{ + /* + * For each leaf RTE, nullingrels[rti] is the set of relids of outer joins + * that potentially null that RTE. + */ + Relids *nullingrels; + /* Length of range table (maximum index in nullingrels[]) */ + int rtlength; /* used only for assertion checks */ +} nullingrel_info; + +/* Options for wrapping an expression for identification purposes */ +typedef enum ReplaceWrapOption +{ + REPLACE_WRAP_NONE, /* no expressions need to be wrapped */ + REPLACE_WRAP_ALL, /* all expressions need to be wrapped */ + REPLACE_WRAP_VARFREE, /* variable-free expressions need to be + * wrapped */ +} ReplaceWrapOption; + typedef struct pullup_replace_vars_context { PlannerInfo *root; List *targetlist; /* tlist of subquery being pulled up */ RangeTblEntry *target_rte; /* RTE of subquery */ + int result_relation; /* the index of the result relation in the + * rewritten query */ Relids relids; /* relids within subquery, as numbered after * pullup (set only if target_rte->lateral) */ + nullingrel_info *nullinfo; /* per-RTE nullingrel info (set only if + * target_rte->lateral) */ bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */ int varno; /* varno of subquery */ - bool wrap_non_vars; /* do we need all non-Var outputs to be PHVs? */ + ReplaceWrapOption wrap_option; /* do we need certain outputs to be PHVs? */ Node **rv_cache; /* cache for results with PHVs */ } pullup_replace_vars_context; @@ -142,6 +170,9 @@ static void substitute_phv_relids(Node *node, static void fix_append_rel_relids(PlannerInfo *root, int varno, Relids subrelids); static Node *find_jointree_node_for_rel(Node *jtnode, int relid); +static nullingrel_info *get_nullingrels(Query *parse); +static void get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels, + nullingrel_info *info); /* @@ -158,6 +189,9 @@ transform_MERGE_to_join(Query *parse) int joinrti; List *vars; RangeTblRef *rtr; + FromExpr *target; + Node *source; + int sourcerti; if (parse->commandType != CMD_MERGE) return; @@ -226,13 +260,36 @@ transform_MERGE_to_join(Query *parse) * parse->jointree->quals are restrictions on the target relation (if the * target relation is an auto-updatable view). */ + /* target rel, with any quals */ rtr = makeNode(RangeTblRef); rtr->rtindex = parse->mergeTargetRelation; + target = makeFromExpr(list_make1(rtr), parse->jointree->quals); + + /* source rel (expect exactly one -- see transformMergeStmt()) */ + Assert(list_length(parse->jointree->fromlist) == 1); + source = linitial(parse->jointree->fromlist); + + /* + * index of source rel (expect either a RangeTblRef or a JoinExpr -- see + * transformFromClauseItem()). + */ + if (IsA(source, RangeTblRef)) + sourcerti = ((RangeTblRef *) source)->rtindex; + else if (IsA(source, JoinExpr)) + sourcerti = ((JoinExpr *) source)->rtindex; + else + { + elog(ERROR, "unrecognized source node type: %d", + (int) nodeTag(source)); + sourcerti = 0; /* keep compiler quiet */ + } + + /* Join the source and target */ joinexpr = makeNode(JoinExpr); joinexpr->jointype = jointype; joinexpr->isNatural = false; - joinexpr->larg = (Node *) makeFromExpr(list_make1(rtr), parse->jointree->quals); - joinexpr->rarg = linitial(parse->jointree->fromlist); /* source rel */ + joinexpr->larg = (Node *) target; + joinexpr->rarg = source; joinexpr->usingClause = NIL; joinexpr->join_using_alias = NULL; joinexpr->quals = parse->mergeJoinCondition; @@ -256,14 +313,83 @@ transform_MERGE_to_join(Query *parse) bms_make_singleton(parse->mergeTargetRelation), bms_make_singleton(joinrti)); + /* + * If the source relation is on the outer side of the join, mark any + * source relation Vars in the join condition, actions, and RETURNING list + * as nullable by the join. These Vars will be added to the targetlist by + * preprocess_targetlist(), so it's important to mark them correctly here. + * + * It might seem that this is not necessary for Vars in the join + * condition, since it is inside the join, but it is also needed above the + * join (in the ModifyTable node) to distinguish between the MATCHED and + * NOT MATCHED BY SOURCE cases -- see ExecMergeMatched(). Note that this + * creates a modified copy of the join condition, for use above the join, + * without modifying the original join condition, inside the join. + */ + if (jointype == JOIN_LEFT || jointype == JOIN_FULL) + { + parse->mergeJoinCondition = + add_nulling_relids(parse->mergeJoinCondition, + bms_make_singleton(sourcerti), + bms_make_singleton(joinrti)); + + foreach_node(MergeAction, action, parse->mergeActionList) + { + action->qual = + add_nulling_relids(action->qual, + bms_make_singleton(sourcerti), + bms_make_singleton(joinrti)); + + action->targetList = (List *) + add_nulling_relids((Node *) action->targetList, + bms_make_singleton(sourcerti), + bms_make_singleton(joinrti)); + } + + parse->returningList = (List *) + add_nulling_relids((Node *) parse->returningList, + bms_make_singleton(sourcerti), + bms_make_singleton(joinrti)); + } + /* * If there are any WHEN NOT MATCHED BY SOURCE actions, the executor will * use the join condition to distinguish between MATCHED and NOT MATCHED * BY SOURCE cases. Otherwise, it's no longer needed, and we set it to * NULL, saving cycles during planning and execution. + * + * We need to be careful though: the executor evaluates this condition + * using the output of the join subplan node, which nulls the output from + * the source relation when the join condition doesn't match. That risks + * producing incorrect results when rechecking using a "non-strict" join + * condition, such as "src.col IS NOT DISTINCT FROM tgt.col". To guard + * against that, we add an additional "src IS NOT NULL" check to the join + * condition, so that it does the right thing when performing a recheck + * based on the output of the join subplan. */ - if (!have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE]) - parse->mergeJoinCondition = NULL; + if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE]) + { + Var *var; + NullTest *ntest; + + /* source wholerow Var (nullable by the new join) */ + var = makeWholeRowVar(rt_fetch(sourcerti, parse->rtable), + sourcerti, 0, false); + var->varnullingrels = bms_make_singleton(joinrti); + + /* "src IS NOT NULL" check */ + ntest = makeNode(NullTest); + ntest->arg = (Expr *) var; + ntest->nulltesttype = IS_NOT_NULL; + ntest->argisrow = false; + ntest->location = -1; + + /* combine it with the original join condition */ + parse->mergeJoinCondition = + (Node *) make_and_qual((Node *) ntest, parse->mergeJoinCondition); + } + else + parse->mergeJoinCondition = NULL; /* join condition not needed */ } /* @@ -538,6 +664,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, /* Is it a convertible ANY or EXISTS clause? */ if (sublink->subLinkType == ANY_SUBLINK) { + ScalarArrayOpExpr *saop; + + if ((saop = convert_VALUES_to_ANY(root, + sublink->testexpr, + (Query *) sublink->subselect)) != NULL) + + /* + * The VALUES sequence was simplified. Nothing more to do + * here. + */ + return (Node *) saop; + if ((j = convert_ANY_sublink_to_join(root, sublink, available_rels1)) != NULL) { @@ -797,14 +935,142 @@ preprocess_function_rtes(PlannerInfo *root) rte->rtekind = RTE_SUBQUERY; rte->subquery = funcquery; rte->security_barrier = false; - /* Clear fields that should not be set in a subquery RTE */ - rte->functions = NIL; + + /* + * Clear fields that should not be set in a subquery RTE. + * However, we leave rte->functions filled in for the moment, + * in case makeWholeRowVar needs to consult it. We'll clear + * it in setrefs.c (see add_rte_to_flat_rtable) so that this + * abuse of the data structure doesn't escape the planner. + */ rte->funcordinality = false; } } } } +/* + * expand_virtual_generated_columns + * Expand all virtual generated column references in a query. + * + * This scans the rangetable for relations with virtual generated columns, and + * replaces all Var nodes in the query that reference these columns with the + * generation expressions. Note that we do not descend into subqueries; that + * is taken care of when the subqueries are planned. + * + * This has to be done after we have pulled up any SubLinks within the query's + * quals; otherwise any virtual generated column references within the SubLinks + * that should be transformed into joins wouldn't get expanded. + * + * Returns a modified copy of the query tree, if any relations with virtual + * generated columns are present. + */ +Query * +expand_virtual_generated_columns(PlannerInfo *root) +{ + Query *parse = root->parse; + int rt_index; + ListCell *lc; + + rt_index = 0; + foreach(lc, parse->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + Relation rel; + TupleDesc tupdesc; + + ++rt_index; + + /* + * Only normal relations can have virtual generated columns. + */ + if (rte->rtekind != RTE_RELATION) + continue; + + rel = table_open(rte->relid, NoLock); + + tupdesc = RelationGetDescr(rel); + if (tupdesc->constr && tupdesc->constr->has_generated_virtual) + { + List *tlist = NIL; + pullup_replace_vars_context rvcontext; + + for (int i = 0; i < tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + TargetEntry *tle; + + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + { + Node *defexpr; + + defexpr = build_generation_expression(rel, i + 1); + ChangeVarNodes(defexpr, 1, rt_index, 0); + + tle = makeTargetEntry((Expr *) defexpr, i + 1, 0, false); + tlist = lappend(tlist, tle); + } + else + { + Var *var; + + var = makeVar(rt_index, + i + 1, + attr->atttypid, + attr->atttypmod, + attr->attcollation, + 0); + + tle = makeTargetEntry((Expr *) var, i + 1, 0, false); + tlist = lappend(tlist, tle); + } + } + + Assert(list_length(tlist) > 0); + Assert(!rte->lateral); + + /* + * The relation's targetlist items are now in the appropriate form + * to insert into the query, except that we may need to wrap them + * in PlaceHolderVars. Set up required context data for + * pullup_replace_vars. + */ + rvcontext.root = root; + rvcontext.targetlist = tlist; + rvcontext.target_rte = rte; + rvcontext.result_relation = parse->resultRelation; + /* won't need these values */ + rvcontext.relids = NULL; + rvcontext.nullinfo = NULL; + /* pass NULL for outer_hasSubLinks */ + rvcontext.outer_hasSubLinks = NULL; + rvcontext.varno = rt_index; + /* this flag will be set below, if needed */ + rvcontext.wrap_option = REPLACE_WRAP_NONE; + /* initialize cache array with indexes 0 .. length(tlist) */ + rvcontext.rv_cache = palloc0((list_length(tlist) + 1) * + sizeof(Node *)); + + /* + * If the query uses grouping sets, we need a PlaceHolderVar for + * each expression of the relation's targetlist items. (See + * comments in pull_up_simple_subquery().) + */ + if (parse->groupingSets) + rvcontext.wrap_option = REPLACE_WRAP_ALL; + + /* + * Apply pullup variable replacement throughout the query tree. + */ + parse = (Query *) pullup_replace_vars((Node *) parse, &rvcontext); + } + + table_close(rel, NoLock); + } + + return parse; +} + /* * pull_up_subqueries * Look for subqueries in the rangetable that can be pulled up into @@ -1086,6 +1352,13 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, */ preprocess_function_rtes(subroot); + /* + * Scan the rangetable for relations with virtual generated columns, and + * replace all Var nodes in the query that reference these columns with + * the generation expressions. + */ + subquery = subroot->parse = expand_virtual_generated_columns(subroot); + /* * Recursively pull up the subquery's subqueries, so that * pull_up_subqueries' processing is complete for its jointree and @@ -1163,40 +1436,37 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, rvcontext.root = root; rvcontext.targetlist = subquery->targetList; rvcontext.target_rte = rte; + rvcontext.result_relation = 0; if (rte->lateral) + { rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree, true, true); - else /* won't need relids */ + rvcontext.nullinfo = get_nullingrels(parse); + } + else /* won't need these values */ + { rvcontext.relids = NULL; + rvcontext.nullinfo = NULL; + } rvcontext.outer_hasSubLinks = &parse->hasSubLinks; rvcontext.varno = varno; /* this flag will be set below, if needed */ - rvcontext.wrap_non_vars = false; + rvcontext.wrap_option = REPLACE_WRAP_NONE; /* initialize cache array with indexes 0 .. length(tlist) */ rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) * sizeof(Node *)); - /* - * If we are dealing with an appendrel member then anything that's not a - * simple Var has to be turned into a PlaceHolderVar. We force this to - * ensure that what we pull up doesn't get merged into a surrounding - * expression during later processing and then fail to match the - * expression actually available from the appendrel. - */ - if (containing_appendrel != NULL) - rvcontext.wrap_non_vars = true; - /* * If the parent query uses grouping sets, we need a PlaceHolderVar for - * anything that's not a simple Var. Again, this ensures that expressions - * retain their separate identity so that they will match grouping set - * columns when appropriate. (It'd be sufficient to wrap values used in - * grouping set columns, and do so only in non-aggregated portions of the - * tlist and havingQual, but that would require a lot of infrastructure - * that pullup_replace_vars hasn't currently got.) + * each expression of the subquery's targetlist items. This ensures that + * expressions retain their separate identity so that they will match + * grouping set columns when appropriate. (It'd be sufficient to wrap + * values used in grouping set columns, and do so only in non-aggregated + * portions of the tlist and havingQual, but that would require a lot of + * infrastructure that pullup_replace_vars hasn't currently got.) */ if (parse->groupingSets) - rvcontext.wrap_non_vars = true; + rvcontext.wrap_option = REPLACE_WRAP_ALL; /* * Replace all of the top query's references to the subquery's outputs @@ -1235,6 +1505,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, case RTE_CTE: case RTE_NAMEDTUPLESTORE: case RTE_RESULT: + case RTE_GROUP: /* these can't contain any lateral references */ break; } @@ -1629,6 +1900,9 @@ is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte, * such refs to be wrapped in PlaceHolderVars, even when they're below * the nearest outer join? But it's a pretty hokey usage, so not * clear this is worth sweating over.) + * + * If you change this, see also the comments about lateral references + * in pullup_replace_vars_callback(). */ if (lowest_outer_join != NULL) { @@ -1713,10 +1987,12 @@ pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte) rvcontext.root = root; rvcontext.targetlist = tlist; rvcontext.target_rte = rte; - rvcontext.relids = NULL; + rvcontext.result_relation = 0; + rvcontext.relids = NULL; /* can't be any lateral references here */ + rvcontext.nullinfo = NULL; rvcontext.outer_hasSubLinks = &parse->hasSubLinks; rvcontext.varno = varno; - rvcontext.wrap_non_vars = false; + rvcontext.wrap_option = REPLACE_WRAP_NONE; /* initialize cache array with indexes 0 .. length(tlist) */ rvcontext.rv_cache = palloc0((list_length(tlist) + 1) * sizeof(Node *)); @@ -1871,36 +2147,31 @@ pull_up_constant_function(PlannerInfo *root, Node *jtnode, NULL, /* resname */ false)); /* resjunk */ rvcontext.target_rte = rte; + rvcontext.result_relation = 0; /* * Since this function was reduced to a Const, it doesn't contain any * lateral references, even if it's marked as LATERAL. This means we - * don't need to fill relids. + * don't need to fill relids or nullinfo. */ rvcontext.relids = NULL; + rvcontext.nullinfo = NULL; rvcontext.outer_hasSubLinks = &parse->hasSubLinks; rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex; /* this flag will be set below, if needed */ - rvcontext.wrap_non_vars = false; + rvcontext.wrap_option = REPLACE_WRAP_NONE; /* initialize cache array with indexes 0 .. length(tlist) */ rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) * sizeof(Node *)); - /* - * If we are dealing with an appendrel member then anything that's not a - * simple Var has to be turned into a PlaceHolderVar. (See comments in - * pull_up_simple_subquery().) - */ - if (containing_appendrel != NULL) - rvcontext.wrap_non_vars = true; - /* * If the parent query uses grouping sets, we need a PlaceHolderVar for - * anything that's not a simple Var. + * each expression of the subquery's targetlist items. (See comments in + * pull_up_simple_subquery().) */ if (parse->groupingSets) - rvcontext.wrap_non_vars = true; + rvcontext.wrap_option = REPLACE_WRAP_ALL; /* * Replace all of the top query's references to the RTE's output with @@ -2151,13 +2422,13 @@ perform_pullup_replace_vars(PlannerInfo *root, */ if (containing_appendrel) { - bool save_wrap_non_vars = rvcontext->wrap_non_vars; + ReplaceWrapOption save_wrap_option = rvcontext->wrap_option; - rvcontext->wrap_non_vars = false; + rvcontext->wrap_option = REPLACE_WRAP_NONE; containing_appendrel->translated_vars = (List *) pullup_replace_vars((Node *) containing_appendrel->translated_vars, rvcontext); - rvcontext->wrap_non_vars = save_wrap_non_vars; + rvcontext->wrap_option = save_wrap_option; return; } @@ -2218,7 +2489,8 @@ perform_pullup_replace_vars(PlannerInfo *root, } /* - * Replace references in the joinaliasvars lists of join RTEs. + * Replace references in the joinaliasvars lists of join RTEs and the + * groupexprs list of group RTE. */ foreach(lc, parse->rtable) { @@ -2228,6 +2500,10 @@ perform_pullup_replace_vars(PlannerInfo *root, otherrte->joinaliasvars = (List *) pullup_replace_vars((Node *) otherrte->joinaliasvars, rvcontext); + else if (otherrte->rtekind == RTE_GROUP) + otherrte->groupexprs = (List *) + pullup_replace_vars((Node *) otherrte->groupexprs, + rvcontext); } } @@ -2293,6 +2569,7 @@ replace_vars_in_jointree(Node *jtnode, case RTE_CTE: case RTE_NAMEDTUPLESTORE: case RTE_RESULT: + case RTE_GROUP: /* these shouldn't be marked LATERAL */ Assert(false); break; @@ -2312,24 +2589,24 @@ replace_vars_in_jointree(Node *jtnode, else if (IsA(jtnode, JoinExpr)) { JoinExpr *j = (JoinExpr *) jtnode; - bool save_wrap_non_vars = context->wrap_non_vars; + ReplaceWrapOption save_wrap_option = context->wrap_option; replace_vars_in_jointree(j->larg, context); replace_vars_in_jointree(j->rarg, context); /* - * Use PHVs within the join quals of a full join. Otherwise, we - * cannot identify which side of the join a pulled-up var-free - * expression came from, which can lead to failure to make a plan at - * all because none of the quals appear to be mergeable or hashable - * conditions. + * Use PHVs within the join quals of a full join for variable-free + * expressions. Otherwise, we cannot identify which side of the join + * a pulled-up variable-free expression came from, which can lead to + * failure to make a plan at all because none of the quals appear to + * be mergeable or hashable conditions. */ if (j->jointype == JOIN_FULL) - context->wrap_non_vars = true; + context->wrap_option = REPLACE_WRAP_VARFREE; j->quals = pullup_replace_vars(j->quals, context); - context->wrap_non_vars = save_wrap_non_vars; + context->wrap_option = save_wrap_option; } else elog(ERROR, "unrecognized node type: %d", @@ -2348,7 +2625,7 @@ pullup_replace_vars(Node *expr, pullup_replace_vars_context *context) return replace_rte_variables(expr, context->varno, 0, pullup_replace_vars_callback, - (void *) context, + context, context->outer_hasSubLinks); } @@ -2361,14 +2638,19 @@ pullup_replace_vars_callback(Var *var, bool need_phv; Node *newnode; + /* System columns are not replaced. */ + if (varattno < InvalidAttrNumber) + return (Node *) copyObject(var); + /* * We need a PlaceHolderVar if the Var-to-be-replaced has nonempty * varnullingrels (unless we find below that the replacement expression is * a Var or PlaceHolderVar that we can just add the nullingrels to). We - * also need one if the caller has instructed us that all non-Var/PHV + * also need one if the caller has instructed us that certain expression * replacements need to be wrapped for identification purposes. */ - need_phv = (var->varnullingrels != NULL) || rcon->wrap_non_vars; + need_phv = (var->varnullingrels != NULL) || + (rcon->wrap_option != REPLACE_WRAP_NONE); /* * If PlaceHolderVars are needed, we cache the modified expressions in @@ -2390,114 +2672,174 @@ pullup_replace_vars_callback(Var *var, /* Just copy the entry and fall through to adjust phlevelsup etc */ newnode = copyObject(rcon->rv_cache[varattno]); } - else if (varattno == InvalidAttrNumber) + else { - /* Must expand whole-tuple reference into RowExpr */ - RowExpr *rowexpr; - List *colnames; - List *fields; - bool save_wrap_non_vars = rcon->wrap_non_vars; - int save_sublevelsup = context->sublevels_up; - /* - * If generating an expansion for a var of a named rowtype (ie, this - * is a plain relation RTE), then we must include dummy items for - * dropped columns. If the var is RECORD (ie, this is a JOIN), then - * omit dropped columns. In the latter case, attach column names to - * the RowExpr for use of the executor and ruleutils.c. - * - * In order to be able to cache the results, we always generate the - * expansion with varlevelsup = 0, and then adjust below if needed. + * Generate the replacement expression. This takes care of expanding + * wholerow references and dealing with non-default varreturningtype. */ - expandRTE(rcon->target_rte, - var->varno, 0 /* not varlevelsup */ , var->location, - (var->vartype != RECORDOID), - &colnames, &fields); - /* Expand the generated per-field Vars, but don't insert PHVs there */ - rcon->wrap_non_vars = false; - context->sublevels_up = 0; /* to match the expandRTE output */ - fields = (List *) replace_rte_variables_mutator((Node *) fields, - context); - rcon->wrap_non_vars = save_wrap_non_vars; - context->sublevels_up = save_sublevelsup; - - rowexpr = makeNode(RowExpr); - rowexpr->args = fields; - rowexpr->row_typeid = var->vartype; - rowexpr->row_format = COERCE_IMPLICIT_CAST; - rowexpr->colnames = (var->vartype == RECORDOID) ? colnames : NIL; - rowexpr->location = var->location; - newnode = (Node *) rowexpr; - - /* - * Insert PlaceHolderVar if needed. Notice that we are wrapping one - * PlaceHolderVar around the whole RowExpr, rather than putting one - * around each element of the row. This is because we need the - * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced - * to null by an outer join. - */ - if (need_phv) - { - newnode = (Node *) - make_placeholder_expr(rcon->root, - (Expr *) newnode, - bms_make_singleton(rcon->varno)); - /* cache it with the PHV, and with phlevelsup etc not set yet */ - rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode); - } - } - else - { - /* Normal case referencing one targetlist element */ - TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno); - - if (tle == NULL) /* shouldn't happen */ - elog(ERROR, "could not find attribute %d in subquery targetlist", - varattno); - - /* Make a copy of the tlist item to return */ - newnode = (Node *) copyObject(tle->expr); + newnode = ReplaceVarFromTargetList(var, + rcon->target_rte, + rcon->targetlist, + rcon->result_relation, + REPLACEVARS_REPORT_ERROR, + 0); /* Insert PlaceHolderVar if needed */ if (need_phv) { bool wrap; - if (newnode && IsA(newnode, Var) && - ((Var *) newnode)->varlevelsup == 0) + if (rcon->wrap_option == REPLACE_WRAP_ALL) + { + /* Caller told us to wrap all expressions in a PlaceHolderVar */ + wrap = true; + } + else if (varattno == InvalidAttrNumber) + { + /* + * Insert PlaceHolderVar for whole-tuple reference. Notice + * that we are wrapping one PlaceHolderVar around the whole + * RowExpr, rather than putting one around each element of the + * row. This is because we need the expression to yield NULL, + * not ROW(NULL,NULL,...) when it is forced to null by an + * outer join. + */ + wrap = true; + } + else if (newnode && IsA(newnode, Var) && + ((Var *) newnode)->varlevelsup == 0) { /* * Simple Vars always escape being wrapped, unless they are * lateral references to something outside the subquery being - * pulled up. (Even then, we could omit the PlaceHolderVar if - * the referenced rel is under the same lowest outer join, but - * it doesn't seem worth the trouble to check that.) + * pulled up and the referenced rel is not under the same + * lowest nulling outer join. */ + wrap = false; if (rcon->target_rte->lateral && !bms_is_member(((Var *) newnode)->varno, rcon->relids)) - wrap = true; - else - wrap = false; + { + nullingrel_info *nullinfo = rcon->nullinfo; + int lvarno = ((Var *) newnode)->varno; + + Assert(lvarno > 0 && lvarno <= nullinfo->rtlength); + if (!bms_is_subset(nullinfo->nullingrels[rcon->varno], + nullinfo->nullingrels[lvarno])) + wrap = true; + } } else if (newnode && IsA(newnode, PlaceHolderVar) && ((PlaceHolderVar *) newnode)->phlevelsup == 0) { /* The same rules apply for a PlaceHolderVar */ + wrap = false; if (rcon->target_rte->lateral && !bms_is_subset(((PlaceHolderVar *) newnode)->phrels, rcon->relids)) - wrap = true; - else - wrap = false; + { + nullingrel_info *nullinfo = rcon->nullinfo; + Relids lvarnos = ((PlaceHolderVar *) newnode)->phrels; + int lvarno; + + lvarno = -1; + while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0) + { + Assert(lvarno > 0 && lvarno <= nullinfo->rtlength); + if (!bms_is_subset(nullinfo->nullingrels[rcon->varno], + nullinfo->nullingrels[lvarno])) + { + wrap = true; + break; + } + } + } } else { /* - * Must wrap, either because we need a place to insert - * varnullingrels or because caller told us to wrap - * everything. + * If the node contains Var(s) or PlaceHolderVar(s) of the + * subquery being pulled up, or of rels that are under the + * same lowest nulling outer join as the subquery, and does + * not contain any non-strict constructs, then instead of + * adding a PHV on top we can add the required nullingrels to + * those Vars/PHVs. (This is fundamentally a generalization + * of the above cases for bare Vars and PHVs.) + * + * This test is somewhat expensive, but it avoids pessimizing + * the plan in cases where the nullingrels get removed again + * later by outer join reduction. + * + * Note that we don't force wrapping of expressions containing + * lateral references, so long as they also contain Vars/PHVs + * of the subquery, or of rels that are under the same lowest + * nulling outer join as the subquery. This is okay because + * of the restriction to strict constructs: if those Vars/PHVs + * have been forced to NULL by an outer join then the end + * result of the expression will be NULL too, regardless of + * the lateral references. So it's not necessary to force the + * expression to be evaluated below the outer join. This can + * be a very valuable optimization, because it may allow us to + * avoid using a nested loop to pass the lateral reference + * down. + * + * This analysis could be tighter: in particular, a non-strict + * construct hidden within a lower-level PlaceHolderVar is not + * reason to add another PHV. But for now it doesn't seem + * worth the code to be more exact. This is also why it's + * preferable to handle bare PHVs in the above branch, rather + * than this branch. We also prefer to handle bare Vars in a + * separate branch, as it's cheaper this way and parallels the + * handling of PHVs. + * + * For a LATERAL subquery, we have to check the actual var + * membership of the node, but if it's non-lateral then any + * level-zero var must belong to the subquery. */ - wrap = true; + bool contain_nullable_vars = false; + + if (!rcon->target_rte->lateral) + { + if (contain_vars_of_level(newnode, 0)) + contain_nullable_vars = true; + } + else + { + Relids all_varnos; + + all_varnos = pull_varnos(rcon->root, newnode); + if (bms_overlap(all_varnos, rcon->relids)) + contain_nullable_vars = true; + else + { + nullingrel_info *nullinfo = rcon->nullinfo; + int varno; + + varno = -1; + while ((varno = bms_next_member(all_varnos, varno)) >= 0) + { + Assert(varno > 0 && varno <= nullinfo->rtlength); + if (bms_is_subset(nullinfo->nullingrels[rcon->varno], + nullinfo->nullingrels[varno])) + { + contain_nullable_vars = true; + break; + } + } + } + } + + if (contain_nullable_vars && + !contain_nonstrict_functions(newnode)) + { + /* No wrap needed */ + wrap = false; + } + else + { + /* Else wrap it in a PlaceHolderVar */ + wrap = true; + } } if (wrap) @@ -2511,25 +2853,21 @@ pullup_replace_vars_callback(Var *var, * Cache it if possible (ie, if the attno is in range, which * it probably always should be). */ - if (varattno > InvalidAttrNumber && + if (varattno >= InvalidAttrNumber && varattno <= list_length(rcon->targetlist)) rcon->rv_cache[varattno] = copyObject(newnode); } } } - /* Must adjust varlevelsup if replaced Var is within a subquery */ - if (var->varlevelsup > 0) - IncrementVarSublevelsUp(newnode, var->varlevelsup, 0); - - /* Propagate any varnullingrels into the replacement Var or PHV */ + /* Propagate any varnullingrels into the replacement expression */ if (var->varnullingrels != NULL) { if (IsA(newnode, Var)) { Var *newvar = (Var *) newnode; - Assert(newvar->varlevelsup == var->varlevelsup); + Assert(newvar->varlevelsup == 0); newvar->varnullingrels = bms_add_members(newvar->varnullingrels, var->varnullingrels); } @@ -2537,14 +2875,73 @@ pullup_replace_vars_callback(Var *var, { PlaceHolderVar *newphv = (PlaceHolderVar *) newnode; - Assert(newphv->phlevelsup == var->varlevelsup); + Assert(newphv->phlevelsup == 0); newphv->phnullingrels = bms_add_members(newphv->phnullingrels, var->varnullingrels); } else - elog(ERROR, "failed to wrap a non-Var"); + { + /* + * There should be Vars/PHVs within the expression that we can + * modify. Vars/PHVs of the subquery should have the full + * var->varnullingrels added to them, but if there are lateral + * references within the expression, those must be marked with + * only the nullingrels that potentially apply to them. (This + * corresponds to the fact that the expression will now be + * evaluated at the join level of the Var that we are replacing: + * the lateral references may have bubbled up through fewer outer + * joins than the subquery's Vars have. Per the discussion above, + * we'll still get the right answers.) That relid set could be + * different for different lateral relations, so we have to do + * this work for each one. + * + * (Currently, the restrictions in is_simple_subquery() mean that + * at most we have to remove the lowest outer join's relid from + * the nullingrels of a lateral reference. However, we might + * relax those restrictions someday, so let's do this right.) + */ + if (rcon->target_rte->lateral) + { + nullingrel_info *nullinfo = rcon->nullinfo; + Relids lvarnos; + int lvarno; + + /* + * Identify lateral varnos used within newnode. We must do + * this before injecting var->varnullingrels into the tree. + */ + lvarnos = pull_varnos(rcon->root, newnode); + lvarnos = bms_del_members(lvarnos, rcon->relids); + /* For each one, add relevant nullingrels if any */ + lvarno = -1; + while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0) + { + Relids lnullingrels; + + Assert(lvarno > 0 && lvarno <= nullinfo->rtlength); + lnullingrels = bms_intersect(var->varnullingrels, + nullinfo->nullingrels[lvarno]); + if (!bms_is_empty(lnullingrels)) + newnode = add_nulling_relids(newnode, + bms_make_singleton(lvarno), + lnullingrels); + } + } + + /* Finally, deal with Vars/PHVs of the subquery itself */ + newnode = add_nulling_relids(newnode, + rcon->relids, + var->varnullingrels); + /* Assert we did put the varnullingrels into the expression */ + Assert(bms_is_subset(var->varnullingrels, + pull_varnos(rcon->root, newnode))); + } } + /* Must adjust varlevelsup if replaced Var is within a subquery */ + if (var->varlevelsup > 0) + IncrementVarSublevelsUp(newnode, var->varlevelsup, 0); + return newnode; } @@ -2563,7 +2960,7 @@ pullup_replace_vars_subquery(Query *query, return (Query *) replace_rte_variables((Node *) query, context->varno, 1, pullup_replace_vars_callback, - (void *) context, + context, NULL); } @@ -3631,7 +4028,7 @@ find_dependent_phvs_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, find_dependent_phvs_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } @@ -3640,8 +4037,7 @@ find_dependent_phvs_walker(Node *node, Assert(!IsA(node, PlaceHolderInfo)); Assert(!IsA(node, MinMaxAggInfo)); - return expression_tree_walker(node, find_dependent_phvs_walker, - (void *) context); + return expression_tree_walker(node, find_dependent_phvs_walker, context); } static bool @@ -3656,15 +4052,12 @@ find_dependent_phvs(PlannerInfo *root, int varno) context.relids = bms_make_singleton(varno); context.sublevels_up = 0; - if (query_tree_walker(root->parse, - find_dependent_phvs_walker, - (void *) &context, - 0)) + if (query_tree_walker(root->parse, find_dependent_phvs_walker, &context, 0)) return true; /* The append_rel_list could be populated already, so check it too */ if (expression_tree_walker((Node *) root->append_rel_list, find_dependent_phvs_walker, - (void *) &context)) + &context)) return true; return false; } @@ -3703,10 +4096,7 @@ find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno) RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable); if (rte->lateral && - range_table_entry_walker(rte, - find_dependent_phvs_walker, - (void *) &context, - 0)) + range_table_entry_walker(rte, find_dependent_phvs_walker, &context, 0)) return true; } @@ -3763,7 +4153,7 @@ substitute_phv_relids_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, substitute_phv_relids_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } @@ -3773,8 +4163,7 @@ substitute_phv_relids_walker(Node *node, Assert(!IsA(node, PlaceHolderInfo)); Assert(!IsA(node, MinMaxAggInfo)); - return expression_tree_walker(node, substitute_phv_relids_walker, - (void *) context); + return expression_tree_walker(node, substitute_phv_relids_walker, context); } static void @@ -3791,7 +4180,7 @@ substitute_phv_relids(Node *node, int varno, Relids subrelids) */ query_or_expression_tree_walker(node, substitute_phv_relids_walker, - (void *) &context, + &context, 0); } @@ -3969,3 +4358,94 @@ find_jointree_node_for_rel(Node *jtnode, int relid) (int) nodeTag(jtnode)); return NULL; } + +/* + * get_nullingrels: collect info about which outer joins null which relations + * + * The result struct contains, for each leaf relation used in the query, + * the set of relids of outer joins that potentially null that rel. + */ +static nullingrel_info * +get_nullingrels(Query *parse) +{ + nullingrel_info *result = palloc_object(nullingrel_info); + + result->rtlength = list_length(parse->rtable); + result->nullingrels = palloc0_array(Relids, result->rtlength + 1); + get_nullingrels_recurse((Node *) parse->jointree, NULL, result); + return result; +} + +/* + * Recursive guts of get_nullingrels(). + * + * Note: at any recursion level, the passed-down upper_nullingrels must be + * treated as a constant, but it can be stored directly into *info + * if we're at leaf level. Upper recursion levels do not free their mutated + * copies of the nullingrels, because those are probably referenced by + * at least one leaf rel. + */ +static void +get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels, + nullingrel_info *info) +{ + if (jtnode == NULL) + return; + if (IsA(jtnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jtnode)->rtindex; + + Assert(varno > 0 && varno <= info->rtlength); + info->nullingrels[varno] = upper_nullingrels; + } + else if (IsA(jtnode, FromExpr)) + { + FromExpr *f = (FromExpr *) jtnode; + ListCell *l; + + foreach(l, f->fromlist) + { + get_nullingrels_recurse(lfirst(l), upper_nullingrels, info); + } + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + Relids local_nullingrels; + + switch (j->jointype) + { + case JOIN_INNER: + get_nullingrels_recurse(j->larg, upper_nullingrels, info); + get_nullingrels_recurse(j->rarg, upper_nullingrels, info); + break; + case JOIN_LEFT: + case JOIN_SEMI: + case JOIN_ANTI: + local_nullingrels = bms_add_member(bms_copy(upper_nullingrels), + j->rtindex); + get_nullingrels_recurse(j->larg, upper_nullingrels, info); + get_nullingrels_recurse(j->rarg, local_nullingrels, info); + break; + case JOIN_FULL: + local_nullingrels = bms_add_member(bms_copy(upper_nullingrels), + j->rtindex); + get_nullingrels_recurse(j->larg, local_nullingrels, info); + get_nullingrels_recurse(j->rarg, local_nullingrels, info); + break; + case JOIN_RIGHT: + local_nullingrels = bms_add_member(bms_copy(upper_nullingrels), + j->rtindex); + get_nullingrels_recurse(j->larg, local_nullingrels, info); + get_nullingrels_recurse(j->rarg, upper_nullingrels, info); + break; + default: + elog(ERROR, "unrecognized join type: %d", + (int) j->jointype); + break; + } + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); +} diff --git a/src/backend/optimizer/prep/prepqual.c b/src/backend/optimizer/prep/prepqual.c index cbcf83f847327..008dce2478c58 100644 --- a/src/backend/optimizer/prep/prepqual.c +++ b/src/backend/optimizer/prep/prepqual.c @@ -19,7 +19,7 @@ * tree after local transformations that might introduce nested AND/ORs. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 931b9c09bda67..ffc9d6c3f301c 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -25,7 +25,7 @@ * rewriter's work is more concerned with SQL semantics. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -44,9 +44,11 @@ #include "optimizer/tlist.h" #include "parser/parse_coerce.h" #include "parser/parsetree.h" +#include "utils/lsyscache.h" #include "utils/rel.h" -static List *expand_insert_targetlist(List *tlist, Relation rel); +static List *expand_insert_targetlist(PlannerInfo *root, List *tlist, + Relation rel); /* @@ -102,7 +104,7 @@ preprocess_targetlist(PlannerInfo *root) */ tlist = parse->targetList; if (command_type == CMD_INSERT) - tlist = expand_insert_targetlist(tlist, target_relation); + tlist = expand_insert_targetlist(root, tlist, target_relation); else if (command_type == CMD_UPDATE) root->update_colnos = extract_update_targetlist_colnos(tlist); @@ -148,7 +150,8 @@ preprocess_targetlist(PlannerInfo *root) ListCell *l2; if (action->commandType == CMD_INSERT) - action->targetList = expand_insert_targetlist(action->targetList, + action->targetList = expand_insert_targetlist(root, + action->targetList, target_relation); else if (action->commandType == CMD_UPDATE) action->updateColnos = @@ -376,7 +379,7 @@ extract_update_targetlist_colnos(List *tlist) * but now this code is only applied to INSERT targetlists. */ static List * -expand_insert_targetlist(List *tlist, Relation rel) +expand_insert_targetlist(PlannerInfo *root, List *tlist, Relation rel) { List *new_tlist = NIL; ListCell *tlist_item; @@ -417,9 +420,8 @@ expand_insert_targetlist(List *tlist, Relation rel) * * INSERTs should insert NULL in this case. (We assume the * rewriter would have inserted any available non-NULL default - * value.) Also, if the column isn't dropped, apply any domain - * constraints that might exist --- this is to catch domain NOT - * NULL. + * value.) Also, normally we must apply any domain constraints + * that might exist --- this is to catch domain NOT NULL. * * When generating a NULL constant for a dropped column, we label * it INT4 (any other guaranteed-to-exist datatype would do as @@ -429,29 +431,17 @@ expand_insert_targetlist(List *tlist, Relation rel) * representation is datatype-independent. This could perhaps * confuse code comparing the finished plan to the target * relation, however. + * + * Another exception is that if the column is generated, the value + * we produce here will be ignored, and we don't want to risk + * throwing an error. So in that case we *don't* want to apply + * domain constraints, so we must produce a NULL of the base type. + * Again, code comparing the finished plan to the target relation + * must account for this. */ - Oid atttype = att_tup->atttypid; - Oid attcollation = att_tup->attcollation; Node *new_expr; - if (!att_tup->attisdropped) - { - new_expr = (Node *) makeConst(atttype, - -1, - attcollation, - att_tup->attlen, - (Datum) 0, - true, /* isnull */ - att_tup->attbyval); - new_expr = coerce_to_domain(new_expr, - InvalidOid, -1, - atttype, - COERCION_IMPLICIT, - COERCE_IMPLICIT_CAST, - -1, - false); - } - else + if (att_tup->attisdropped) { /* Insert NULL for dropped column */ new_expr = (Node *) makeConst(INT4OID, @@ -462,6 +452,33 @@ expand_insert_targetlist(List *tlist, Relation rel) true, /* isnull */ true /* byval */ ); } + else if (att_tup->attgenerated) + { + /* Generated column, insert a NULL of the base type */ + Oid baseTypeId = att_tup->atttypid; + int32 baseTypeMod = att_tup->atttypmod; + + baseTypeId = getBaseTypeAndTypmod(baseTypeId, &baseTypeMod); + new_expr = (Node *) makeConst(baseTypeId, + baseTypeMod, + att_tup->attcollation, + att_tup->attlen, + (Datum) 0, + true, /* isnull */ + att_tup->attbyval); + } + else + { + /* Normal column, insert a NULL of the column datatype */ + new_expr = coerce_null_to_domain(att_tup->atttypid, + att_tup->atttypmod, + att_tup->attcollation, + att_tup->attlen, + att_tup->attbyval); + /* Must run expression preprocessing on any non-const nodes */ + if (!IsA(new_expr, Const)) + new_expr = eval_const_expressions(root, new_expr); + } new_tle = makeTargetEntry((Expr *) new_expr, attrno, diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 1c69c6e97e80a..eab44da65b8f0 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -12,7 +12,7 @@ * case, but most of the heavy lifting for that is done elsewhere, * notably in prepjointree.c and allpaths.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -39,9 +39,9 @@ static RelOptInfo *recurse_set_operations(Node *setOp, PlannerInfo *root, + SetOperationStmt *parentOp, List *colTypes, List *colCollations, - bool junkOK, - int flag, List *refnames_tlist, + List *refnames_tlist, List **pTargetList, bool *istrivial_tlist); static RelOptInfo *generate_recursion_path(SetOperationStmt *setOp, @@ -64,19 +64,13 @@ static List *plan_union_children(PlannerInfo *root, List **tlist_list, List **istrivial_tlist); static void postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel); -static bool choose_hashed_setop(PlannerInfo *root, List *groupClauses, - Path *input_path, - double dNumGroups, double dNumOutputRows, - const char *construct); static List *generate_setop_tlist(List *colTypes, List *colCollations, - int flag, Index varno, bool hack_constants, List *input_tlist, List *refnames_tlist, bool *trivial_tlist); static List *generate_append_tlist(List *colTypes, List *colCollations, - bool flag, List *input_tlists, List *refnames_tlist); static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist); @@ -160,12 +154,11 @@ plan_set_operations(PlannerInfo *root) /* * Recurse on setOperations tree to generate paths for set ops. The * final output paths should have just the column types shown as the - * output from the top-level node, plus possibly resjunk working - * columns (we can rely on upper-level nodes to deal with that). + * output from the top-level node. */ setop_rel = recurse_set_operations((Node *) topop, root, + NULL, /* no parent */ topop->colTypes, topop->colCollations, - true, -1, leftmostQuery->targetList, &top_tlist, &trivial_tlist); @@ -177,50 +170,36 @@ plan_set_operations(PlannerInfo *root) return setop_rel; } -/* - * set_operation_ordered_results_useful - * Return true if the given SetOperationStmt can be executed by utilizing - * paths that provide sorted input according to the setop's targetlist. - * Returns false when sorted paths are not any more useful then unsorted - * ones. - */ -bool -set_operation_ordered_results_useful(SetOperationStmt *setop) -{ - /* - * Paths sorted by the targetlist are useful for UNION as we can opt to - * MergeAppend the sorted paths then Unique them. Ordered paths are no - * more useful than unordered ones for UNION ALL. - */ - if (!setop->all && setop->op == SETOP_UNION) - return true; - - /* - * EXCEPT / EXCEPT ALL / INTERSECT / INTERSECT ALL cannot yet utilize - * correctly sorted input paths. - */ - return false; -} - /* * recurse_set_operations * Recursively handle one step in a tree of set operations * + * setOp: current step (could be a SetOperationStmt or a leaf RangeTblRef) + * parentOp: parent step, or NULL if none (but see below) * colTypes: OID list of set-op's result column datatypes * colCollations: OID list of set-op's result column collations - * junkOK: if true, child resjunk columns may be left in the result - * flag: if >= 0, add a resjunk output column indicating value of flag * refnames_tlist: targetlist to take column names from * + * parentOp should be passed as NULL unless that step is interested in + * getting sorted output from this step. ("Sorted" means "sorted according + * to the default btree opclasses of the result column datatypes".) + * * Returns a RelOptInfo for the subtree, as well as these output parameters: * *pTargetList: receives the fully-fledged tlist for the subtree's top plan * *istrivial_tlist: true if, and only if, datatypes between parent and child * match. * + * If setOp is a leaf node, this function plans the sub-query but does + * not populate the pathlist of the returned RelOptInfo. The caller will + * generate SubqueryScan paths using useful path(s) of the subquery (see + * build_setop_child_paths). But this function does build the paths for + * set-operation nodes. + * * The pTargetList output parameter is mostly redundant with the pathtarget * of the returned RelOptInfo, but for the moment we need it because much of * the logic in this file depends on flag columns being marked resjunk. - * Pending a redesign of how that works, this is the easy way out. + * XXX Now that there are no flag columns and hence no resjunk columns, we + * could probably refactor this file to deal only in pathtargets. * * We don't have to care about typmods here: the only allowed difference * between set-op input and output typmods is input is a specific typmod @@ -228,9 +207,9 @@ set_operation_ordered_results_useful(SetOperationStmt *setop) */ static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, + SetOperationStmt *parentOp, List *colTypes, List *colCollations, - bool junkOK, - int flag, List *refnames_tlist, + List *refnames_tlist, List **pTargetList, bool *istrivial_tlist) { @@ -245,7 +224,6 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, { RangeTblRef *rtr = (RangeTblRef *) setOp; RangeTblEntry *rte = root->simple_rte_array[rtr->rtindex]; - SetOperationStmt *setops; Query *subquery = rte->subquery; PlannerInfo *subroot; List *tlist; @@ -260,15 +238,13 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, Assert(root->plan_params == NIL); /* - * Pass the set operation details to the subquery_planner to have it - * consider generating Paths correctly ordered for the set operation. + * Generate a subroot and Paths for the subquery. If we have a + * parentOp, pass that down to encourage subquery_planner to consider + * suitably-sorted Paths. */ - setops = castNode(SetOperationStmt, root->parse->setOperations); - - /* Generate a subroot and Paths for the subquery */ subroot = rel->subroot = subquery_planner(root->glob, subquery, root, false, root->tuple_fraction, - setops); + parentOp); /* * It should not be possible for the primitive query to contain any @@ -279,7 +255,6 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, /* Figure out the appropriate target list for this subquery. */ tlist = generate_setop_tlist(colTypes, colCollations, - flag, rtr->rtindex, true, subroot->processed_tlist, @@ -315,19 +290,17 @@ recurse_set_operations(Node *setOp, PlannerInfo *root, * to the corresponding tlist entries of the subplan. However, since * the subplan was generated by generate_union_paths() or * generate_nonunion_paths(), and hence its tlist was generated by - * generate_append_tlist(), this will work. We just tell - * generate_setop_tlist() to use varno 0. + * generate_append_tlist() or generate_setop_tlist(), this will work. + * We just tell generate_setop_tlist() to use varno 0. */ - if (flag >= 0 || - !tlist_same_datatypes(*pTargetList, colTypes, junkOK) || - !tlist_same_collations(*pTargetList, colCollations, junkOK)) + if (!tlist_same_datatypes(*pTargetList, colTypes, false) || + !tlist_same_collations(*pTargetList, colCollations, false)) { PathTarget *target; bool trivial_tlist; ListCell *lc; *pTargetList = generate_setop_tlist(colTypes, colCollations, - flag, 0, false, *pTargetList, @@ -410,8 +383,8 @@ generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, * separately without any intention of combining them into one Append. */ lrel = recurse_set_operations(setOp->larg, root, + NULL, /* no value in sorted results */ setOp->colTypes, setOp->colCollations, - false, -1, refnames_tlist, &lpath_tlist, &lpath_trivial_tlist); @@ -422,8 +395,8 @@ generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, /* The right path will want to look at the left one ... */ root->non_recursive_path = lpath; rrel = recurse_set_operations(setOp->rarg, root, + NULL, /* no value in sorted results */ setOp->colTypes, setOp->colCollations, - false, -1, refnames_tlist, &rpath_tlist, &rpath_trivial_tlist); @@ -436,7 +409,7 @@ generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, /* * Generate tlist for RecursiveUnion path node --- same as in Append cases */ - tlist = generate_append_tlist(setOp->colTypes, setOp->colCollations, false, + tlist = generate_append_tlist(setOp->colTypes, setOp->colCollations, list_make2(lpath_tlist, rpath_tlist), refnames_tlist); @@ -495,6 +468,10 @@ generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, * build_setop_child_paths * Build paths for the set op child relation denoted by 'rel'. * + * 'rel' is an RTE_SUBQUERY relation. We have already generated paths within + * the subquery's subroot; the task here is to create SubqueryScan paths for + * 'rel', representing scans of the useful subquery paths. + * * interesting_pathkeys: if not NIL, also include paths that suit these * pathkeys, sorting any unsorted paths as required. * *pNumGroups: if not NULL, we estimate the number of distinct groups @@ -662,14 +639,17 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel, * otherwise do statistical estimation. * * XXX you don't really want to know about this: we do the estimation - * using the subquery's original targetlist expressions, not the + * using the subroot->parse's original targetlist expressions, not the * subroot->processed_tlist which might seem more appropriate. The reason * is that if the subquery is itself a setop, it may return a * processed_tlist containing "varno 0" Vars generated by * generate_append_tlist, and those would confuse estimate_num_groups * mightily. We ought to get rid of the "varno 0" hack, but that requires * a redesign of the parsetree representation of setops, so that there can - * be an RTE corresponding to each setop's output. + * be an RTE corresponding to each setop's output. Note, we use this not + * subquery's targetlist but subroot->parse's targetlist, because it was + * revised by self-join removal. subquery's targetlist might contain the + * references to the removed relids. */ if (pNumGroups) { @@ -682,7 +662,7 @@ build_setop_child_paths(PlannerInfo *root, RelOptInfo *rel, *pNumGroups = rel->cheapest_total_path->rows; else *pNumGroups = estimate_num_groups(subroot, - get_tlist_exprs(subquery->targetList, false), + get_tlist_exprs(subroot->parse->targetList, false), rel->cheapest_total_path->rows, NULL, NULL); @@ -719,9 +699,9 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, /* * If any of my children are identical UNION nodes (same op, all-flag, and - * colTypes) then they can be merged into this node so that we generate - * only one Append/MergeAppend and unique-ification for the lot. Recurse - * to find such nodes. + * colTypes/colCollations) then they can be merged into this node so that + * we generate only one Append/MergeAppend and unique-ification for the + * lot. Recurse to find such nodes. */ rellist = plan_union_children(root, op, @@ -736,7 +716,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, * concerned, but we must make it look real anyway for the benefit of the * next plan level up. */ - tlist = generate_append_tlist(op->colTypes, op->colCollations, false, + tlist = generate_append_tlist(op->colTypes, op->colCollations, tlist_list, refnames_tlist); *pTargetList = tlist; @@ -1028,103 +1008,130 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, *path; List *lpath_tlist, *rpath_tlist, - *tlist_list, *tlist, - *groupList, - *pathlist; + *groupList; bool lpath_trivial_tlist, - rpath_trivial_tlist; + rpath_trivial_tlist, + result_trivial_tlist; + List *nonunion_pathkeys = NIL; double dLeftGroups, dRightGroups, dNumGroups, dNumOutputRows; - bool use_hash; + bool can_sort; + bool can_hash; SetOpCmd cmd; - int firstFlag; /* * Tell children to fetch all tuples. */ root->tuple_fraction = 0.0; - /* Recurse on children, ensuring their outputs are marked */ + /* Recurse on children */ lrel = recurse_set_operations(op->larg, root, + op, op->colTypes, op->colCollations, - false, 0, refnames_tlist, &lpath_tlist, &lpath_trivial_tlist); - if (lrel->rtekind == RTE_SUBQUERY) - build_setop_child_paths(root, lrel, lpath_trivial_tlist, lpath_tlist, - NIL, &dLeftGroups); - else - dLeftGroups = lrel->rows; - lpath = lrel->cheapest_total_path; rrel = recurse_set_operations(op->rarg, root, + op, op->colTypes, op->colCollations, - false, 1, refnames_tlist, &rpath_tlist, &rpath_trivial_tlist); + + /* + * Generate tlist for SetOp plan node. + * + * The tlist for a SetOp plan isn't important so far as the SetOp is + * concerned, but we must make it look real anyway for the benefit of the + * next plan level up. + */ + tlist = generate_setop_tlist(op->colTypes, op->colCollations, + 0, false, lpath_tlist, refnames_tlist, + &result_trivial_tlist); + + /* We should not have needed any type coercions in the tlist */ + Assert(result_trivial_tlist); + + *pTargetList = tlist; + + /* Identify the grouping semantics */ + groupList = generate_setop_grouplist(op, tlist); + + /* Check whether the operators support sorting or hashing */ + can_sort = grouping_is_sortable(groupList); + can_hash = grouping_is_hashable(groupList); + if (!can_sort && !can_hash) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is INTERSECT or EXCEPT */ + errmsg("could not implement %s", + (op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT"), + errdetail("Some of the datatypes only support hashing, while others only support sorting."))); + + if (can_sort) + { + /* Determine the pathkeys for sorting by the whole target list */ + nonunion_pathkeys = make_pathkeys_for_sortclauses(root, groupList, + tlist); + + root->query_pathkeys = nonunion_pathkeys; + } + + /* + * Now that we've got all that info, we can build the child paths. + */ + if (lrel->rtekind == RTE_SUBQUERY) + build_setop_child_paths(root, lrel, lpath_trivial_tlist, lpath_tlist, + nonunion_pathkeys, &dLeftGroups); + else + dLeftGroups = lrel->rows; if (rrel->rtekind == RTE_SUBQUERY) build_setop_child_paths(root, rrel, rpath_trivial_tlist, rpath_tlist, - NIL, &dRightGroups); + nonunion_pathkeys, &dRightGroups); else dRightGroups = rrel->rows; - rpath = rrel->cheapest_total_path; - /* Undo effects of forcing tuple_fraction to 0 */ root->tuple_fraction = save_fraction; /* * For EXCEPT, we must put the left input first. For INTERSECT, either * order should give the same results, and we prefer to put the smaller - * input first in order to minimize the size of the hash table in the - * hashing case. "Smaller" means the one with the fewer groups. + * input first in order to (a) minimize the size of the hash table in the + * hashing case, and (b) improve our chances of exploiting the executor's + * fast path for empty left-hand input. "Smaller" means the one with the + * fewer groups. */ - if (op->op == SETOP_EXCEPT || dLeftGroups <= dRightGroups) + if (op->op != SETOP_EXCEPT && dLeftGroups > dRightGroups) { - pathlist = list_make2(lpath, rpath); - tlist_list = list_make2(lpath_tlist, rpath_tlist); - firstFlag = 0; + /* need to swap the two inputs */ + RelOptInfo *tmprel; + List *tmplist; + double tmpd; + + tmprel = lrel; + lrel = rrel; + rrel = tmprel; + tmplist = lpath_tlist; + lpath_tlist = rpath_tlist; + rpath_tlist = tmplist; + tmpd = dLeftGroups; + dLeftGroups = dRightGroups; + dRightGroups = tmpd; } - else - { - pathlist = list_make2(rpath, lpath); - tlist_list = list_make2(rpath_tlist, lpath_tlist); - firstFlag = 1; - } - - /* - * Generate tlist for Append plan node. - * - * The tlist for an Append plan isn't important as far as the Append is - * concerned, but we must make it look real anyway for the benefit of the - * next plan level up. In fact, it has to be real enough that the flag - * column is shown as a variable not a constant, else setrefs.c will get - * confused. - */ - tlist = generate_append_tlist(op->colTypes, op->colCollations, true, - tlist_list, refnames_tlist); - *pTargetList = tlist; + lpath = lrel->cheapest_total_path; + rpath = rrel->cheapest_total_path; /* Build result relation. */ result_rel = fetch_upper_rel(root, UPPERREL_SETOP, bms_union(lrel->relids, rrel->relids)); result_rel->reltarget = create_pathtarget(root, tlist); - /* - * Append the child results together. - */ - path = (Path *) create_append_path(root, result_rel, pathlist, NIL, - NIL, NULL, 0, false, -1); - - /* Identify the grouping semantics */ - groupList = generate_setop_grouplist(op, tlist); - /* * Estimate number of distinct groups that we'll need hashtable entries * for; this is the size of the left-hand input for EXCEPT, or the smaller @@ -1140,29 +1147,12 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, } else { - dNumGroups = Min(dLeftGroups, dRightGroups); + dNumGroups = dLeftGroups; dNumOutputRows = op->all ? Min(lpath->rows, rpath->rows) : dNumGroups; } + result_rel->rows = dNumOutputRows; - /* - * Decide whether to hash or sort, and add a sort node if needed. - */ - use_hash = choose_hashed_setop(root, groupList, path, - dNumGroups, dNumOutputRows, - (op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT"); - - if (groupList && !use_hash) - path = (Path *) create_sort_path(root, - result_rel, - path, - make_pathkeys_for_sortclauses(root, - groupList, - tlist), - -1.0); - - /* - * Finally, add a SetOp path node to generate the correct output. - */ + /* Select the SetOpCmd type */ switch (op->op) { case SETOP_INTERSECT: @@ -1176,34 +1166,104 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */ break; } - path = (Path *) create_setop_path(root, - result_rel, - path, - cmd, - use_hash ? SETOP_HASHED : SETOP_SORTED, - groupList, - list_length(op->colTypes) + 1, - use_hash ? firstFlag : -1, - dNumGroups, - dNumOutputRows); - - result_rel->rows = path->rows; - add_path(result_rel, path); + + /* + * If we can hash, that just requires a SetOp atop the cheapest inputs. + */ + if (can_hash) + { + path = (Path *) create_setop_path(root, + result_rel, + lpath, + rpath, + cmd, + SETOP_HASHED, + groupList, + dNumGroups, + dNumOutputRows); + add_path(result_rel, path); + } + + /* + * If we can sort, generate the cheapest sorted input paths, and add a + * SetOp atop those. + */ + if (can_sort) + { + List *pathkeys; + Path *slpath, + *srpath; + + /* First the left input ... */ + pathkeys = make_pathkeys_for_sortclauses(root, + groupList, + lpath_tlist); + if (pathkeys_contained_in(pathkeys, lpath->pathkeys)) + slpath = lpath; /* cheapest path is already sorted */ + else + { + slpath = get_cheapest_path_for_pathkeys(lrel->pathlist, + nonunion_pathkeys, + NULL, + TOTAL_COST, + false); + /* Subquery failed to produce any presorted paths? */ + if (slpath == NULL) + slpath = (Path *) create_sort_path(root, + lpath->parent, + lpath, + pathkeys, + -1.0); + } + + /* and now the same for the right. */ + pathkeys = make_pathkeys_for_sortclauses(root, + groupList, + rpath_tlist); + if (pathkeys_contained_in(pathkeys, rpath->pathkeys)) + srpath = rpath; /* cheapest path is already sorted */ + else + { + srpath = get_cheapest_path_for_pathkeys(rrel->pathlist, + nonunion_pathkeys, + NULL, + TOTAL_COST, + false); + /* Subquery failed to produce any presorted paths? */ + if (srpath == NULL) + srpath = (Path *) create_sort_path(root, + rpath->parent, + rpath, + pathkeys, + -1.0); + } + + path = (Path *) create_setop_path(root, + result_rel, + slpath, + srpath, + cmd, + SETOP_SORTED, + groupList, + dNumGroups, + dNumOutputRows); + add_path(result_rel, path); + } + return result_rel; } /* - * Pull up children of a UNION node that are identically-propertied UNIONs. + * Pull up children of a UNION node that are identically-propertied UNIONs, + * and perform planning of the queries underneath the N-way UNION. + * + * The result is a list of RelOptInfos containing Paths for sub-nodes, with + * one entry for each descendant that is a leaf query or non-identical setop. + * We also return parallel lists of the childrens' targetlists and + * is-trivial-tlist flags. * * NOTE: we can also pull a UNION ALL up into a UNION, since the distinct * output rows will be lost anyway. - * - * NOTE: currently, we ignore collations while determining if a child has - * the same properties. This is semantically sound only so long as all - * collations have the same notion of equality. It is valid from an - * implementation standpoint because we don't care about the ordering of - * a UNION child's result: UNION ALL results are always unordered, and - * generate_union_paths will force a fresh sort if the top level is a UNION. */ static List * plan_union_children(PlannerInfo *root, @@ -1232,7 +1292,8 @@ plan_union_children(PlannerInfo *root, if (op->op == top_union->op && (op->all == top_union->all || op->all) && - equal(op->colTypes, top_union->colTypes)) + equal(op->colTypes, top_union->colTypes) && + equal(op->colCollations, top_union->colCollations)) { /* Same UNION, so fold children into parent */ pending_rels = lcons(op->rarg, pending_rels); @@ -1244,17 +1305,15 @@ plan_union_children(PlannerInfo *root, /* * Not same, so plan this child separately. * - * Note we disallow any resjunk columns in child results. This is - * necessary since the Append node that implements the union won't do - * any projection, and upper levels will get confused if some of our - * output tuples have junk and some don't. This case only arises when - * we have an EXCEPT or INTERSECT as child, else there won't be - * resjunk anyway. + * If top_union isn't a UNION ALL, then we are interested in sorted + * output from the child, so pass top_union as parentOp. Note that + * this isn't necessarily the child node's immediate SetOperationStmt + * parent, but that's fine: it's the effective parent. */ result = lappend(result, recurse_set_operations(setOp, root, + top_union->all ? NULL : top_union, top_union->colTypes, top_union->colCollations, - false, -1, refnames_tlist, &child_tlist, &trivial_tlist)); @@ -1283,110 +1342,11 @@ postprocess_setop_rel(PlannerInfo *root, RelOptInfo *rel) set_cheapest(rel); } -/* - * choose_hashed_setop - should we use hashing for a set operation? - */ -static bool -choose_hashed_setop(PlannerInfo *root, List *groupClauses, - Path *input_path, - double dNumGroups, double dNumOutputRows, - const char *construct) -{ - int numGroupCols = list_length(groupClauses); - Size hash_mem_limit = get_hash_memory_limit(); - bool can_sort; - bool can_hash; - Size hashentrysize; - Path hashed_p; - Path sorted_p; - double tuple_fraction; - - /* Check whether the operators support sorting or hashing */ - can_sort = grouping_is_sortable(groupClauses); - can_hash = grouping_is_hashable(groupClauses); - if (can_hash && can_sort) - { - /* we have a meaningful choice to make, continue ... */ - } - else if (can_hash) - return true; - else if (can_sort) - return false; - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is UNION, INTERSECT, or EXCEPT */ - errmsg("could not implement %s", construct), - errdetail("Some of the datatypes only support hashing, while others only support sorting."))); - - /* Prefer sorting when enable_hashagg is off */ - if (!enable_hashagg) - return false; - - /* - * Don't do it if it doesn't look like the hashtable will fit into - * hash_mem. - */ - hashentrysize = MAXALIGN(input_path->pathtarget->width) + MAXALIGN(SizeofMinimalTupleHeader); - - if (hashentrysize * dNumGroups > hash_mem_limit) - return false; - - /* - * See if the estimated cost is no more than doing it the other way. - * - * We need to consider input_plan + hashagg versus input_plan + sort + - * group. Note that the actual result plan might involve a SetOp or - * Unique node, not Agg or Group, but the cost estimates for Agg and Group - * should be close enough for our purposes here. - * - * These path variables are dummies that just hold cost fields; we don't - * make actual Paths for these steps. - */ - cost_agg(&hashed_p, root, AGG_HASHED, NULL, - numGroupCols, dNumGroups, - NIL, - input_path->startup_cost, input_path->total_cost, - input_path->rows, input_path->pathtarget->width); - - /* - * Now for the sorted case. Note that the input is *always* unsorted, - * since it was made by appending unrelated sub-relations together. - */ - sorted_p.startup_cost = input_path->startup_cost; - sorted_p.total_cost = input_path->total_cost; - /* XXX cost_sort doesn't actually look at pathkeys, so just pass NIL */ - cost_sort(&sorted_p, root, NIL, sorted_p.total_cost, - input_path->rows, input_path->pathtarget->width, - 0.0, work_mem, -1.0); - cost_group(&sorted_p, root, numGroupCols, dNumGroups, - NIL, - sorted_p.startup_cost, sorted_p.total_cost, - input_path->rows); - - /* - * Now make the decision using the top-level tuple fraction. First we - * have to convert an absolute count (LIMIT) into fractional form. - */ - tuple_fraction = root->tuple_fraction; - if (tuple_fraction >= 1.0) - tuple_fraction /= dNumOutputRows; - - if (compare_fractional_path_costs(&hashed_p, &sorted_p, - tuple_fraction) < 0) - { - /* Hashed is cheaper, so use it */ - return true; - } - return false; -} - /* * Generate targetlist for a set-operation plan node * * colTypes: OID list of set-op's result column datatypes * colCollations: OID list of set-op's result column collations - * flag: -1 if no flag column needed, 0 or 1 to create a const flag column * varno: varno to use in generated Vars * hack_constants: true to copy up constants (see comments in code) * input_tlist: targetlist of this node's input node @@ -1395,7 +1355,6 @@ choose_hashed_setop(PlannerInfo *root, List *groupClauses, */ static List * generate_setop_tlist(List *colTypes, List *colCollations, - int flag, Index varno, bool hack_constants, List *input_tlist, @@ -1494,7 +1453,7 @@ generate_setop_tlist(List *colTypes, List *colCollations, false); /* - * By convention, all non-resjunk columns in a setop tree have + * By convention, all output columns in a setop tree have * ressortgroupref equal to their resno. In some cases the ref isn't * needed, but this is a cleaner way than modifying the tlist later. */ @@ -1503,25 +1462,6 @@ generate_setop_tlist(List *colTypes, List *colCollations, tlist = lappend(tlist, tle); } - if (flag >= 0) - { - /* Add a resjunk flag column */ - /* flag value is the given constant */ - expr = (Node *) makeConst(INT4OID, - -1, - InvalidOid, - sizeof(int32), - Int32GetDatum(flag), - false, - true); - tle = makeTargetEntry((Expr *) expr, - (AttrNumber) resno++, - pstrdup("flag"), - true); - tlist = lappend(tlist, tle); - *trivial_tlist = false; /* the extra entry makes it not trivial */ - } - return tlist; } @@ -1530,7 +1470,6 @@ generate_setop_tlist(List *colTypes, List *colCollations, * * colTypes: OID list of set-op's result column datatypes * colCollations: OID list of set-op's result column collations - * flag: true to create a flag column copied up from subplans * input_tlists: list of tlists for sub-plans of the Append * refnames_tlist: targetlist to take column names from * @@ -1544,7 +1483,6 @@ generate_setop_tlist(List *colTypes, List *colCollations, */ static List * generate_append_tlist(List *colTypes, List *colCollations, - bool flag, List *input_tlists, List *refnames_tlist) { @@ -1578,8 +1516,7 @@ generate_append_tlist(List *colTypes, List *colCollations, { TargetEntry *subtle = (TargetEntry *) lfirst(subtlistl); - if (subtle->resjunk) - continue; + Assert(!subtle->resjunk); Assert(curColType != NULL); if (exprType((Node *) subtle->expr) == lfirst_oid(curColType)) { @@ -1628,7 +1565,7 @@ generate_append_tlist(List *colTypes, List *colCollations, false); /* - * By convention, all non-resjunk columns in a setop tree have + * By convention, all output columns in a setop tree have * ressortgroupref equal to their resno. In some cases the ref isn't * needed, but this is a cleaner way than modifying the tlist later. */ @@ -1637,23 +1574,6 @@ generate_append_tlist(List *colTypes, List *colCollations, tlist = lappend(tlist, tle); } - if (flag) - { - /* Add a resjunk flag column */ - /* flag value is shown as copied up from subplan */ - expr = (Node *) makeVar(0, - resno, - INT4OID, - -1, - InvalidOid, - 0); - tle = makeTargetEntry((Expr *) expr, - (AttrNumber) resno++, - pstrdup("flag"), - true); - tlist = lappend(tlist, tle); - } - pfree(colTypmods); return tlist; @@ -1683,12 +1603,7 @@ generate_setop_grouplist(SetOperationStmt *op, List *targetlist) TargetEntry *tle = (TargetEntry *) lfirst(lt); SortGroupClause *sgc; - if (tle->resjunk) - { - /* resjunk columns should not have sortgrouprefs */ - Assert(tle->ressortgroupref == 0); - continue; /* ignore resjunk columns */ - } + Assert(!tle->resjunk); /* non-resjunk columns should have sortgroupref = resno */ Assert(tle->ressortgroupref == tle->resno); diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c index 49897226371dc..5b3dc0d865399 100644 --- a/src/backend/optimizer/util/appendinfo.c +++ b/src/backend/optimizer/util/appendinfo.c @@ -3,7 +3,7 @@ * appendinfo.c * Routines for mapping between append parent(s) and children * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -253,6 +253,13 @@ adjust_appendrel_attrs_mutator(Node *node, * all non-Var outputs of such subqueries, and then we could look up * the pre-existing PHV here. Or perhaps just wrap the translations * that way to begin with? + * + * If var->varreturningtype is not VAR_RETURNING_DEFAULT, then that + * also needs to be copied to the translated Var. That too would fail + * if the translation wasn't a Var, but that should never happen since + * a non-default var->varreturningtype is only used for Vars referring + * to the result relation, which should never be a flattened UNION ALL + * subquery. */ for (cnt = 0; cnt < nappinfos; cnt++) @@ -283,9 +290,17 @@ adjust_appendrel_attrs_mutator(Node *node, elog(ERROR, "attribute %d of relation \"%s\" does not exist", var->varattno, get_rel_name(appinfo->parent_reloid)); if (IsA(newnode, Var)) + { + ((Var *) newnode)->varreturningtype = var->varreturningtype; ((Var *) newnode)->varnullingrels = var->varnullingrels; - else if (var->varnullingrels != NULL) - elog(ERROR, "failed to apply nullingrels to a non-Var"); + } + else + { + if (var->varreturningtype != VAR_RETURNING_DEFAULT) + elog(ERROR, "failed to apply returningtype to a non-Var"); + if (var->varnullingrels != NULL) + elog(ERROR, "failed to apply nullingrels to a non-Var"); + } return newnode; } else if (var->varattno == 0) @@ -339,6 +354,8 @@ adjust_appendrel_attrs_mutator(Node *node, rowexpr->colnames = copyObject(rte->eref->colnames); rowexpr->location = -1; + if (var->varreturningtype != VAR_RETURNING_DEFAULT) + elog(ERROR, "failed to apply returningtype to a non-Var"); if (var->varnullingrels != NULL) elog(ERROR, "failed to apply nullingrels to a non-Var"); @@ -425,7 +442,7 @@ adjust_appendrel_attrs_mutator(Node *node, phv = (PlaceHolderVar *) expression_tree_mutator(node, adjust_appendrel_attrs_mutator, - (void *) context); + context); /* now fix PlaceHolderVar's relid sets */ if (phv->phlevelsup == 0) { @@ -509,8 +526,7 @@ adjust_appendrel_attrs_mutator(Node *node, Assert(!IsA(node, RangeTblRef)); Assert(!IsA(node, JoinExpr)); - return expression_tree_mutator(node, adjust_appendrel_attrs_mutator, - (void *) context); + return expression_tree_mutator(node, adjust_appendrel_attrs_mutator, context); } /* diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index b4e085e9d4b5e..26a3e0500866c 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -3,7 +3,7 @@ * clauses.c * routines to manipulate qualification clauses * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -40,7 +40,9 @@ #include "optimizer/planmain.h" #include "parser/analyze.h" #include "parser/parse_coerce.h" +#include "parser/parse_collate.h" #include "parser/parse_func.h" +#include "parser/parse_oper.h" #include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" #include "tcop/tcopprot.h" @@ -265,8 +267,7 @@ find_window_functions_walker(Node *node, WindowFuncLists *lists) return false; } Assert(!IsA(node, SubLink)); - return expression_tree_walker(node, find_window_functions_walker, - (void *) lists); + return expression_tree_walker(node, find_window_functions_walker, lists); } @@ -1217,7 +1218,7 @@ contain_context_dependent_node_walker(Node *node, int *flags) *flags |= CCDN_CASETESTEXPR_OK; res = expression_tree_walker(node, contain_context_dependent_node_walker, - (void *) flags); + flags); *flags = save_flags; return res; } @@ -1241,7 +1242,7 @@ contain_context_dependent_node_walker(Node *node, int *flags) return res; } return expression_tree_walker(node, contain_context_dependent_node_walker, - (void *) flags); + flags); } /***************************************************************************** @@ -1296,6 +1297,7 @@ contain_leaked_vars_walker(Node *node, void *context) case T_NullTest: case T_BooleanTest: case T_NextValueExpr: + case T_ReturningExpr: case T_List: /* @@ -2326,7 +2328,7 @@ convert_saop_to_hashed_saop_walker(Node *node, void *context) /* Looks good. Fill in the hash functions */ saop->hashfuncid = lefthashfunc; } - return true; + return false; } } else /* !saop->useOr */ @@ -2364,7 +2366,7 @@ convert_saop_to_hashed_saop_walker(Node *node, void *context) */ saop->negfuncid = get_opcode(negator); } - return true; + return false; } } } @@ -2416,7 +2418,7 @@ estimate_expression_value(PlannerInfo *root, Node *node) */ #define ece_generic_processing(node) \ expression_tree_mutator((Node *) (node), eval_const_expressions_mutator, \ - (void *) context) + context) /* * Check whether all arguments of the given node were reduced to Consts. @@ -2552,7 +2554,7 @@ eval_const_expressions_mutator(Node *node, args = (List *) expression_tree_mutator((Node *) args, eval_const_expressions_mutator, - (void *) context); + context); /* ... and the filter expression, which isn't */ aggfilter = (Expr *) eval_const_expressions_mutator((Node *) expr->aggfilter, @@ -2697,7 +2699,7 @@ eval_const_expressions_mutator(Node *node, */ args = (List *) expression_tree_mutator((Node *) expr->args, eval_const_expressions_mutator, - (void *) context); + context); /* * We must do our own check for NULLs because DistinctExpr has @@ -2915,13 +2917,25 @@ eval_const_expressions_mutator(Node *node, case T_JsonValueExpr: { JsonValueExpr *jve = (JsonValueExpr *) node; - Node *formatted; + Node *raw_expr = (Node *) jve->raw_expr; + Node *formatted_expr = (Node *) jve->formatted_expr; - formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr, - context); - if (formatted && IsA(formatted, Const)) - return formatted; - break; + /* + * If we can fold formatted_expr to a constant, we can elide + * the JsonValueExpr altogether. Otherwise we must process + * raw_expr too. But JsonFormat is a flat node and requires + * no simplification, only copying. + */ + formatted_expr = eval_const_expressions_mutator(formatted_expr, + context); + if (formatted_expr && IsA(formatted_expr, Const)) + return formatted_expr; + + raw_expr = eval_const_expressions_mutator(raw_expr, context); + + return (Node *) makeJsonValueExpr((Expr *) raw_expr, + (Expr *) formatted_expr, + copyObject(jve->format)); } case T_SubPlan: @@ -3393,6 +3407,8 @@ eval_const_expressions_mutator(Node *node, fselect->resulttypmod, fselect->resultcollid, ((Var *) arg)->varlevelsup); + /* New Var has same OLD/NEW returning as old one */ + newvar->varreturningtype = ((Var *) arg)->varreturningtype; /* New Var is nullable by same rels as the old one */ newvar->varnullingrels = ((Var *) arg)->varnullingrels; return (Node *) newvar; @@ -4082,7 +4098,7 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod, args = expand_function_arguments(args, false, result_type, func_tuple); args = (List *) expression_tree_mutator((Node *) args, eval_const_expressions_mutator, - (void *) context); + context); /* Argument processing done, give it back to the caller */ *args_p = args; } @@ -4624,7 +4640,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, callback_arg.prosrc = src; sqlerrcontext.callback = sql_inline_error_callback; - sqlerrcontext.arg = (void *) &callback_arg; + sqlerrcontext.arg = &callback_arg; sqlerrcontext.previous = error_context_stack; error_context_stack = &sqlerrcontext; @@ -4728,7 +4744,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, if (check_sql_fn_retval(list_make1(querytree_list), result_type, rettupdesc, funcform->prokind, - false, NULL)) + false)) goto fail; /* reject whole-tuple-result cases */ /* @@ -4926,8 +4942,7 @@ substitute_actual_parameters_mutator(Node *node, /* We don't need to copy at this time (it'll get done later) */ return list_nth(context->args, param->paramid - 1); } - return expression_tree_mutator(node, substitute_actual_parameters_mutator, - (void *) context); + return expression_tree_mutator(node, substitute_actual_parameters_mutator, context); } /* @@ -5178,7 +5193,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) callback_arg.prosrc = src; sqlerrcontext.callback = sql_inline_error_callback; - sqlerrcontext.arg = (void *) &callback_arg; + sqlerrcontext.arg = &callback_arg; sqlerrcontext.previous = error_context_stack; error_context_stack = &sqlerrcontext; @@ -5275,7 +5290,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) if (!check_sql_fn_retval(list_make1(querytree_list), fexpr->funcresulttype, rettupdesc, funcform->prokind, - true, NULL) && + true) && (functypclass == TYPEFUNC_COMPOSITE || functypclass == TYPEFUNC_COMPOSITE_DOMAIN || functypclass == TYPEFUNC_RECORD)) @@ -5370,7 +5385,7 @@ substitute_actual_srf_parameters_mutator(Node *node, context->sublevels_up++; result = (Node *) query_tree_mutator((Query *) node, substitute_actual_srf_parameters_mutator, - (void *) context, + context, 0); context->sublevels_up--; return result; @@ -5395,7 +5410,7 @@ substitute_actual_srf_parameters_mutator(Node *node, } return expression_tree_mutator(node, substitute_actual_srf_parameters_mutator, - (void *) context); + context); } /* @@ -5424,6 +5439,88 @@ pull_paramids_walker(Node *node, Bitmapset **context) *context = bms_add_member(*context, param->paramid); return false; } - return expression_tree_walker(node, pull_paramids_walker, - (void *) context); + return expression_tree_walker(node, pull_paramids_walker, context); +} + +/* + * Build ScalarArrayOpExpr on top of 'exprs.' 'haveNonConst' indicates + * whether at least one of the expressions is not Const. When it's false, + * the array constant is built directly; otherwise, we have to build a child + * ArrayExpr. The 'exprs' list gets freed if not directly used in the output + * expression tree. + */ +ScalarArrayOpExpr * +make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, + Oid inputcollid, List *exprs, bool haveNonConst) +{ + Node *arrayNode = NULL; + ScalarArrayOpExpr *saopexpr = NULL; + Oid arraytype = get_array_type(coltype); + + if (!OidIsValid(arraytype)) + return NULL; + + /* + * Assemble an array from the list of constants. It seems more profitable + * to build a const array. But in the presence of other nodes, we don't + * have a specific value here and must employ an ArrayExpr instead. + */ + if (haveNonConst) + { + ArrayExpr *arrayExpr = makeNode(ArrayExpr); + + /* array_collid will be set by parse_collate.c */ + arrayExpr->element_typeid = coltype; + arrayExpr->array_typeid = arraytype; + arrayExpr->multidims = false; + arrayExpr->elements = exprs; + arrayExpr->location = -1; + + arrayNode = (Node *) arrayExpr; + } + else + { + int16 typlen; + bool typbyval; + char typalign; + Datum *elems; + bool *nulls; + int i = 0; + ArrayType *arrayConst; + int dims[1] = {list_length(exprs)}; + int lbs[1] = {1}; + + get_typlenbyvalalign(coltype, &typlen, &typbyval, &typalign); + + elems = (Datum *) palloc(sizeof(Datum) * list_length(exprs)); + nulls = (bool *) palloc(sizeof(bool) * list_length(exprs)); + foreach_node(Const, value, exprs) + { + elems[i] = value->constvalue; + nulls[i++] = value->constisnull; + } + + arrayConst = construct_md_array(elems, nulls, 1, dims, lbs, + coltype, typlen, typbyval, typalign); + arrayNode = (Node *) makeConst(arraytype, -1, arraycollid, + -1, PointerGetDatum(arrayConst), + false, false); + + pfree(elems); + pfree(nulls); + list_free(exprs); + } + + /* Build the SAOP expression node */ + saopexpr = makeNode(ScalarArrayOpExpr); + saopexpr->opno = oper; + saopexpr->opfuncid = get_opcode(oper); + saopexpr->hashfuncid = InvalidOid; + saopexpr->negfuncid = InvalidOid; + saopexpr->useOr = true; + saopexpr->inputcollid = inputcollid; + saopexpr->args = list_make2(leftexpr, arrayNode); + saopexpr->location = -1; + + return saopexpr; } diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c index 4797312ae53ea..17e51cd75d744 100644 --- a/src/backend/optimizer/util/inherit.c +++ b/src/backend/optimizer/util/inherit.c @@ -3,7 +3,7 @@ * inherit.c * Routines to process child relations in inheritance trees * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -386,8 +386,17 @@ expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, Index childRTindex; RelOptInfo *childrelinfo; - /* Open rel, acquiring required locks */ - childrel = table_open(childOID, lockmode); + /* + * Open rel, acquiring required locks. If a partition was recently + * detached and subsequently dropped, then opening it will fail. In + * this case, behave as though the partition had been pruned. + */ + childrel = try_table_open(childOID, lockmode); + if (childrel == NULL) + { + relinfo->live_parts = bms_del_member(relinfo->live_parts, i); + continue; + } /* * Temporary partitions belonging to other sessions should have been diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c index 5fb0c17630a19..f26e38c6552f0 100644 --- a/src/backend/optimizer/util/joininfo.c +++ b/src/backend/optimizer/util/joininfo.c @@ -3,7 +3,7 @@ * joininfo.c * joininfo list manipulation routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -106,12 +106,19 @@ add_join_clause_to_rels(PlannerInfo *root, return; /* - * Substitute constant-FALSE for the origin qual if it is always false. - * Note that we keep the same rinfo_serial. + * Substitute the origin qual with constant-FALSE if it is provably always + * false. + * + * Note that we need to keep the same rinfo_serial, since it is in + * practice the same condition. We also need to reset the + * last_rinfo_serial counter, which is essential to ensure that the + * RestrictInfos for the "same" qual condition get identical serial + * numbers (see deconstruct_distribute_oj_quals). */ if (restriction_is_always_false(root, restrictinfo)) { int save_rinfo_serial = restrictinfo->rinfo_serial; + int save_last_rinfo_serial = root->last_rinfo_serial; restrictinfo = make_restrictinfo(root, (Expr *) makeBoolConst(false, false), @@ -124,6 +131,7 @@ add_join_clause_to_rels(PlannerInfo *root, restrictinfo->incompatible_relids, restrictinfo->outer_relids); restrictinfo->rinfo_serial = save_rinfo_serial; + root->last_rinfo_serial = save_last_rinfo_serial; } cur_relid = -1; diff --git a/src/backend/optimizer/util/meson.build b/src/backend/optimizer/util/meson.build index 75312c4a3a94a..b3bf913d09658 100644 --- a/src/backend/optimizer/util/meson.build +++ b/src/backend/optimizer/util/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'appendinfo.c', diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c index 5e2bf26ec43dc..2ccc670be51c1 100644 --- a/src/backend/optimizer/util/orclauses.c +++ b/src/backend/optimizer/util/orclauses.c @@ -3,7 +3,7 @@ * orclauses.c * Routines to extract restriction OR clauses from join OR clauses * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/optimizer/util/paramassign.c b/src/backend/optimizer/util/paramassign.c index f461fedf194e3..3bd3ce37c8fce 100644 --- a/src/backend/optimizer/util/paramassign.c +++ b/src/backend/optimizer/util/paramassign.c @@ -40,7 +40,7 @@ * doesn't really save much executor work anyway. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -91,6 +91,7 @@ assign_param_for_var(PlannerInfo *root, Var *var) pvar->vartype == var->vartype && pvar->vartypmod == var->vartypmod && pvar->varcollid == var->varcollid && + pvar->varreturningtype == var->varreturningtype && bms_equal(pvar->varnullingrels, var->varnullingrels)) return pitem->paramId; } @@ -358,6 +359,52 @@ replace_outer_merge_support(PlannerInfo *root, MergeSupportFunc *msf) return retval; } +/* + * Generate a Param node to replace the given ReturningExpr expression which + * is expected to have retlevelsup > 0 (ie, it is not local). Record the need + * for the ReturningExpr in the proper upper-level root->plan_params. + */ +Param * +replace_outer_returning(PlannerInfo *root, ReturningExpr *rexpr) +{ + Param *retval; + PlannerParamItem *pitem; + Index levelsup; + Oid ptype = exprType((Node *) rexpr->retexpr); + + Assert(rexpr->retlevelsup > 0 && rexpr->retlevelsup < root->query_level); + + /* Find the query level the ReturningExpr belongs to */ + for (levelsup = rexpr->retlevelsup; levelsup > 0; levelsup--) + root = root->parent_root; + + /* + * It does not seem worthwhile to try to de-duplicate references to outer + * ReturningExprs. Just make a new slot every time. + */ + rexpr = copyObject(rexpr); + IncrementVarSublevelsUp((Node *) rexpr, -((int) rexpr->retlevelsup), 0); + Assert(rexpr->retlevelsup == 0); + + pitem = makeNode(PlannerParamItem); + pitem->item = (Node *) rexpr; + pitem->paramId = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + ptype); + + root->plan_params = lappend(root->plan_params, pitem); + + retval = makeNode(Param); + retval->paramkind = PARAM_EXEC; + retval->paramid = pitem->paramId; + retval->paramtype = ptype; + retval->paramtypmod = exprTypmod((Node *) rexpr->retexpr); + retval->paramcollid = exprCollation((Node *) rexpr->retexpr); + retval->location = exprLocation((Node *) rexpr->retexpr); + + return retval; +} + /* * Generate a Param node to replace the given Var, * which is expected to come from some upper NestLoop plan node. diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index b8b1eae295ec8..e0192d4a491d2 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -3,7 +3,7 @@ * pathnode.c * Routines to manipulate pathlists and create path nodes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -68,6 +68,15 @@ static bool pathlist_is_reparameterizable_by_child(List *pathlist, int compare_path_costs(Path *path1, Path *path2, CostSelector criterion) { + /* Number of disabled nodes, if different, trumps all else. */ + if (unlikely(path1->disabled_nodes != path2->disabled_nodes)) + { + if (path1->disabled_nodes < path2->disabled_nodes) + return -1; + else + return +1; + } + if (criterion == STARTUP_COST) { if (path1->startup_cost < path2->startup_cost) @@ -118,6 +127,15 @@ compare_fractional_path_costs(Path *path1, Path *path2, Cost cost1, cost2; + /* Number of disabled nodes, if different, trumps all else. */ + if (unlikely(path1->disabled_nodes != path2->disabled_nodes)) + { + if (path1->disabled_nodes < path2->disabled_nodes) + return -1; + else + return +1; + } + if (fraction <= 0.0 || fraction >= 1.0) return compare_path_costs(path1, path2, TOTAL_COST); cost1 = path1->startup_cost + @@ -166,6 +184,15 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor) #define CONSIDER_PATH_STARTUP_COST(p) \ ((p)->param_info == NULL ? (p)->parent->consider_startup : (p)->parent->consider_param_startup) + /* Number of disabled nodes, if different, trumps all else. */ + if (unlikely(path1->disabled_nodes != path2->disabled_nodes)) + { + if (path1->disabled_nodes < path2->disabled_nodes) + return COSTS_BETTER1; + else + return COSTS_BETTER2; + } + /* * Check total cost first since it's more likely to be different; many * paths have zero startup cost. @@ -362,15 +389,29 @@ set_cheapest(RelOptInfo *parent_rel) * add_path * Consider a potential implementation path for the specified parent rel, * and add it to the rel's pathlist if it is worthy of consideration. + * * A path is worthy if it has a better sort order (better pathkeys) or - * cheaper cost (on either dimension), or generates fewer rows, than any - * existing path that has the same or superset parameterization rels. - * We also consider parallel-safe paths more worthy than others. + * cheaper cost (as defined below), or generates fewer rows, than any + * existing path that has the same or superset parameterization rels. We + * also consider parallel-safe paths more worthy than others. + * + * Cheaper cost can mean either a cheaper total cost or a cheaper startup + * cost; if one path is cheaper in one of these aspects and another is + * cheaper in the other, we keep both. However, when some path type is + * disabled (e.g. due to enable_seqscan=false), the number of times that + * a disabled path type is used is considered to be a higher-order + * component of the cost. Hence, if path A uses no disabled path type, + * and path B uses 1 or more disabled path types, A is cheaper, no matter + * what we estimate for the startup and total costs. The startup and total + * cost essentially act as a tiebreak when comparing paths that use equal + * numbers of disabled path nodes; but in practice this tiebreak is almost + * always used, since normally no path types are disabled. * - * We also remove from the rel's pathlist any old paths that are dominated - * by new_path --- that is, new_path is cheaper, at least as well ordered, - * generates no more rows, requires no outer rels not required by the old - * path, and is no less parallel-safe. + * In addition to possibly adding new_path, we also remove from the rel's + * pathlist any old paths that are dominated by new_path --- that is, + * new_path is cheaper, at least as well ordered, generates no more rows, + * requires no outer rels not required by the old path, and is no less + * parallel-safe. * * In most cases, a path with a superset parameterization will generate * fewer rows (since it has more join clauses to apply), so that those two @@ -389,10 +430,10 @@ set_cheapest(RelOptInfo *parent_rel) * parent_rel->consider_param_startup is true for a parameterized one. * Again, this allows discarding useless paths sooner. * - * The pathlist is kept sorted by total_cost, with cheaper paths - * at the front. Within this routine, that's simply a speed hack: - * doing it that way makes it more likely that we will reject an inferior - * path after a few comparisons, rather than many comparisons. + * The pathlist is kept sorted by disabled_nodes and then by total_cost, + * with cheaper paths at the front. Within this routine, that's simply a + * speed hack: doing it that way makes it more likely that we will reject + * an inferior path after a few comparisons, rather than many comparisons. * However, add_path_precheck relies on this ordering to exit early * when possible. * @@ -593,8 +634,13 @@ add_path(RelOptInfo *parent_rel, Path *new_path) } else { - /* new belongs after this old path if it has cost >= old's */ - if (new_path->total_cost >= old_path->total_cost) + /* + * new belongs after this old path if it has more disabled nodes + * or if it has the same number of nodes but a greater total cost + */ + if (new_path->disabled_nodes > old_path->disabled_nodes || + (new_path->disabled_nodes == old_path->disabled_nodes && + new_path->total_cost >= old_path->total_cost)) insert_at = foreach_current_index(p1) + 1; } @@ -639,7 +685,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * so the required information has to be passed piecemeal. */ bool -add_path_precheck(RelOptInfo *parent_rel, +add_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer) { @@ -658,6 +704,20 @@ add_path_precheck(RelOptInfo *parent_rel, Path *old_path = (Path *) lfirst(p1); PathKeysComparison keyscmp; + /* + * Since the pathlist is sorted by disabled_nodes and then by + * total_cost, we can stop looking once we reach a path with more + * disabled nodes, or the same number of disabled nodes plus a + * total_cost larger than the new path's. + */ + if (unlikely(old_path->disabled_nodes != disabled_nodes)) + { + if (disabled_nodes < old_path->disabled_nodes) + break; + } + else if (total_cost <= old_path->total_cost * STD_FUZZ_FACTOR) + break; + /* * We are looking for an old_path with the same parameterization (and * by assumption the same rowcount) that dominates the new path on @@ -666,39 +726,27 @@ add_path_precheck(RelOptInfo *parent_rel, * * Cost comparisons here should match compare_path_costs_fuzzily. */ - if (total_cost > old_path->total_cost * STD_FUZZ_FACTOR) + /* new path can win on startup cost only if consider_startup */ + if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR || + !consider_startup) { - /* new path can win on startup cost only if consider_startup */ - if (startup_cost > old_path->startup_cost * STD_FUZZ_FACTOR || - !consider_startup) + /* new path loses on cost, so check pathkeys... */ + List *old_path_pathkeys; + + old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys; + keyscmp = compare_pathkeys(new_path_pathkeys, + old_path_pathkeys); + if (keyscmp == PATHKEYS_EQUAL || + keyscmp == PATHKEYS_BETTER2) { - /* new path loses on cost, so check pathkeys... */ - List *old_path_pathkeys; - - old_path_pathkeys = old_path->param_info ? NIL : old_path->pathkeys; - keyscmp = compare_pathkeys(new_path_pathkeys, - old_path_pathkeys); - if (keyscmp == PATHKEYS_EQUAL || - keyscmp == PATHKEYS_BETTER2) + /* new path does not win on pathkeys... */ + if (bms_equal(required_outer, PATH_REQ_OUTER(old_path))) { - /* new path does not win on pathkeys... */ - if (bms_equal(required_outer, PATH_REQ_OUTER(old_path))) - { - /* Found an old path that dominates the new one */ - return false; - } + /* Found an old path that dominates the new one */ + return false; } } } - else - { - /* - * Since the pathlist is sorted by total_cost, we can stop looking - * once we reach a path with a total_cost larger than the new - * path's. - */ - break; - } } return true; @@ -734,7 +782,7 @@ add_path_precheck(RelOptInfo *parent_rel, * produce the same number of rows. Neither do we need to consider startup * costs: parallelism is only used for plans that will be run to completion. * Therefore, this routine is much simpler than add_path: it needs to - * consider only pathkeys and total cost. + * consider only disabled nodes, pathkeys and total cost. * * As with add_path, we pfree paths that are found to be dominated by * another partial path; this requires that there be no other references to @@ -775,7 +823,15 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) /* Unless pathkeys are incompatible, keep just one of the two paths. */ if (keyscmp != PATHKEYS_DIFFERENT) { - if (new_path->total_cost > old_path->total_cost * STD_FUZZ_FACTOR) + if (unlikely(new_path->disabled_nodes != old_path->disabled_nodes)) + { + if (new_path->disabled_nodes > old_path->disabled_nodes) + accept_new = false; + else + remove_old = true; + } + else if (new_path->total_cost > old_path->total_cost + * STD_FUZZ_FACTOR) { /* New path costs more; keep it only if pathkeys are better. */ if (keyscmp != PATHKEYS_BETTER1) @@ -862,8 +918,8 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) * is surely a loser. */ bool -add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost, - List *pathkeys) +add_partial_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, + Cost total_cost, List *pathkeys) { ListCell *p1; @@ -906,8 +962,8 @@ add_partial_path_precheck(RelOptInfo *parent_rel, Cost total_cost, * partial path; the resulting plans, if run in parallel, will be run to * completion. */ - if (!add_path_precheck(parent_rel, total_cost, total_cost, pathkeys, - NULL)) + if (!add_path_precheck(parent_rel, disabled_nodes, total_cost, total_cost, + pathkeys, NULL)) return false; return true; @@ -1419,15 +1475,21 @@ create_merge_append_path(PlannerInfo *root, Relids required_outer) { MergeAppendPath *pathnode = makeNode(MergeAppendPath); + int input_disabled_nodes; Cost input_startup_cost; Cost input_total_cost; ListCell *l; + /* + * We don't currently support parameterized MergeAppend paths, as + * explained in the comments for generate_orderedappend_paths. + */ + Assert(bms_is_empty(rel->lateral_relids) && bms_is_empty(required_outer)); + pathnode->path.pathtype = T_MergeAppend; pathnode->path.parent = rel; pathnode->path.pathtarget = rel->reltarget; - pathnode->path.param_info = get_appendrel_parampathinfo(rel, - required_outer); + pathnode->path.param_info = NULL; pathnode->path.parallel_aware = false; pathnode->path.parallel_safe = rel->consider_parallel; pathnode->path.parallel_workers = 0; @@ -1447,12 +1509,16 @@ create_merge_append_path(PlannerInfo *root, * Add up the sizes and costs of the input paths. */ pathnode->path.rows = 0; + input_disabled_nodes = 0; input_startup_cost = 0; input_total_cost = 0; foreach(l, subpaths) { Path *subpath = (Path *) lfirst(l); + /* All child paths should be unparameterized */ + Assert(bms_is_empty(PATH_REQ_OUTER(subpath))); + pathnode->path.rows += subpath->rows; pathnode->path.parallel_safe = pathnode->path.parallel_safe && subpath->parallel_safe; @@ -1460,6 +1526,7 @@ create_merge_append_path(PlannerInfo *root, if (pathkeys_contained_in(pathkeys, subpath->pathkeys)) { /* Subpath is adequately ordered, we won't need to sort it */ + input_disabled_nodes += subpath->disabled_nodes; input_startup_cost += subpath->startup_cost; input_total_cost += subpath->total_cost; } @@ -1471,18 +1538,17 @@ create_merge_append_path(PlannerInfo *root, cost_sort(&sort_path, root, pathkeys, + subpath->disabled_nodes, subpath->total_cost, subpath->rows, subpath->pathtarget->width, 0.0, work_mem, pathnode->limit_tuples); + input_disabled_nodes += sort_path.disabled_nodes; input_startup_cost += sort_path.startup_cost; input_total_cost += sort_path.total_cost; } - - /* All child paths must have same parameterization */ - Assert(bms_equal(PATH_REQ_OUTER(subpath), required_outer)); } /* @@ -1495,12 +1561,14 @@ create_merge_append_path(PlannerInfo *root, ((Path *) linitial(subpaths))->parallel_aware == pathnode->path.parallel_aware) { + pathnode->path.disabled_nodes = input_disabled_nodes; pathnode->path.startup_cost = input_startup_cost; pathnode->path.total_cost = input_total_cost; } else cost_merge_append(&pathnode->path, root, pathkeys, list_length(subpaths), + input_disabled_nodes, input_startup_cost, input_total_cost, pathnode->path.rows); @@ -1582,6 +1650,7 @@ create_material_path(RelOptInfo *rel, Path *subpath) pathnode->subpath = subpath; cost_material(&pathnode->path, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows, @@ -1628,6 +1697,10 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, */ pathnode->est_entries = 0; + /* we should not generate this path type when enable_memoize=false */ + Assert(enable_memoize); + pathnode->path.disabled_nodes = subpath->disabled_nodes; + /* * Add a small additional charge for caching the first entry. All the * harder calculations for rescans are performed in cost_memoize_rescan(). @@ -1727,6 +1800,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, { pathnode->umethod = UNIQUE_PATH_NOOP; pathnode->path.rows = rel->rows; + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; @@ -1765,6 +1839,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, { pathnode->umethod = UNIQUE_PATH_NOOP; pathnode->path.rows = rel->rows; + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; @@ -1792,6 +1867,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, * Estimate cost for sort+unique implementation */ cost_sort(&sort_path, root, NIL, + subpath->disabled_nodes, subpath->total_cost, rel->rows, subpath->pathtarget->width, @@ -1829,6 +1905,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, AGG_HASHED, NULL, numCols, pathnode->path.rows, NIL, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, rel->rows, @@ -1837,7 +1914,9 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, if (sjinfo->semi_can_btree && sjinfo->semi_can_hash) { - if (agg_path.total_cost < sort_path.total_cost) + if (agg_path.disabled_nodes < sort_path.disabled_nodes || + (agg_path.disabled_nodes == sort_path.disabled_nodes && + agg_path.total_cost < sort_path.total_cost)) pathnode->umethod = UNIQUE_PATH_HASH; else pathnode->umethod = UNIQUE_PATH_SORT; @@ -1855,11 +1934,13 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, if (pathnode->umethod == UNIQUE_PATH_HASH) { + pathnode->path.disabled_nodes = agg_path.disabled_nodes; pathnode->path.startup_cost = agg_path.startup_cost; pathnode->path.total_cost = agg_path.total_cost; } else { + pathnode->path.disabled_nodes = sort_path.disabled_nodes; pathnode->path.startup_cost = sort_path.startup_cost; pathnode->path.total_cost = sort_path.total_cost; } @@ -1883,6 +1964,7 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, Relids required_outer, double *rows) { GatherMergePath *pathnode = makeNode(GatherMergePath); + int input_disabled_nodes = 0; Cost input_startup_cost = 0; Cost input_total_cost = 0; @@ -1910,11 +1992,13 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.pathkeys = pathkeys; pathnode->path.pathtarget = target ? target : rel->reltarget; + input_disabled_nodes += subpath->disabled_nodes; input_startup_cost += subpath->startup_cost; input_total_cost += subpath->total_cost; cost_gather_merge(pathnode, root, rel, pathnode->path.param_info, - input_startup_cost, input_total_cost, rows); + input_disabled_nodes, input_startup_cost, + input_total_cost, rows); return pathnode; } @@ -2222,7 +2306,8 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel, ForeignPath * create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, @@ -2243,6 +2328,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.parallel_safe = rel->consider_parallel; pathnode->path.parallel_workers = 0; pathnode->path.rows = rows; + pathnode->path.disabled_nodes = disabled_nodes; pathnode->path.startup_cost = startup_cost; pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; @@ -2268,7 +2354,8 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, ForeignPath * create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, @@ -2295,6 +2382,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.parallel_safe = rel->consider_parallel; pathnode->path.parallel_workers = 0; pathnode->path.rows = rows; + pathnode->path.disabled_nodes = disabled_nodes; pathnode->path.startup_cost = startup_cost; pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; @@ -2320,7 +2408,8 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, ForeignPath * create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Path *fdw_outerpath, List *fdw_restrictinfo, @@ -2342,6 +2431,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.parallel_safe = rel->consider_parallel; pathnode->path.parallel_workers = 0; pathnode->path.rows = rows; + pathnode->path.disabled_nodes = disabled_nodes; pathnode->path.startup_cost = startup_cost; pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; @@ -2536,6 +2626,7 @@ create_nestloop_path(PlannerInfo *root, * (this should be a subset of the restrict_clauses list) * 'outersortkeys' are the sort varkeys for the outer relation * 'innersortkeys' are the sort varkeys for the inner relation + * 'outer_presorted_keys' is the number of presorted keys of the outer path */ MergePath * create_mergejoin_path(PlannerInfo *root, @@ -2550,7 +2641,8 @@ create_mergejoin_path(PlannerInfo *root, Relids required_outer, List *mergeclauses, List *outersortkeys, - List *innersortkeys) + List *innersortkeys, + int outer_presorted_keys) { MergePath *pathnode = makeNode(MergePath); @@ -2579,6 +2671,7 @@ create_mergejoin_path(PlannerInfo *root, pathnode->path_mergeclauses = mergeclauses; pathnode->outersortkeys = outersortkeys; pathnode->innersortkeys = innersortkeys; + pathnode->outer_presorted_keys = outer_presorted_keys; /* pathnode->skip_mark_restore will be set by final_cost_mergejoin */ /* pathnode->materialize_inner will be set by final_cost_mergejoin */ @@ -2729,6 +2822,7 @@ create_projection_path(PlannerInfo *root, * Set cost of plan as subpath's cost, adjusted for tlist replacement. */ pathnode->path.rows = subpath->rows; + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost + (target->cost.startup - oldtarget->cost.startup); pathnode->path.total_cost = subpath->total_cost + @@ -2745,6 +2839,7 @@ create_projection_path(PlannerInfo *root, * evaluating the tlist. There is no qual to worry about. */ pathnode->path.rows = subpath->rows; + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost + target->cost.startup; pathnode->path.total_cost = subpath->total_cost + @@ -2912,6 +3007,7 @@ create_set_projection_path(PlannerInfo *root, * This is slightly bizarre maybe, but it's what 9.6 did; we may revisit * this estimate later. */ + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.rows = subpath->rows * tlist_rows; pathnode->path.startup_cost = subpath->startup_cost + target->cost.startup; @@ -2962,6 +3058,7 @@ create_incremental_sort_path(PlannerInfo *root, cost_incremental_sort(&pathnode->path, root, pathkeys, presorted_keys, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows, @@ -3008,6 +3105,7 @@ create_sort_path(PlannerInfo *root, pathnode->subpath = subpath; cost_sort(&pathnode->path, root, pathkeys, + subpath->disabled_nodes, subpath->total_cost, subpath->rows, subpath->pathtarget->width, @@ -3060,6 +3158,7 @@ create_group_path(PlannerInfo *root, list_length(groupClause), numGroups, qual, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows); @@ -3117,6 +3216,7 @@ create_upper_unique_path(PlannerInfo *root, * all columns get compared at most of the tuples. (XXX probably this is * an overestimate.) */ + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost + cpu_operator_cost * subpath->rows * numCols; @@ -3195,6 +3295,7 @@ create_agg_path(PlannerInfo *root, aggstrategy, aggcosts, list_length(groupClause), numGroups, qual, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows, subpath->pathtarget->width); @@ -3303,6 +3404,7 @@ create_groupingsets_path(PlannerInfo *root, numGroupCols, rollup->numGroups, having_qual, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows, @@ -3328,7 +3430,7 @@ create_groupingsets_path(PlannerInfo *root, numGroupCols, rollup->numGroups, having_qual, - 0.0, 0.0, + 0, 0.0, 0.0, subpath->rows, subpath->pathtarget->width); if (!rollup->is_hashed) @@ -3337,7 +3439,7 @@ create_groupingsets_path(PlannerInfo *root, else { /* Account for cost of sort, but don't charge input cost again */ - cost_sort(&sort_path, root, NIL, + cost_sort(&sort_path, root, NIL, 0, 0.0, subpath->rows, subpath->pathtarget->width, @@ -3353,12 +3455,14 @@ create_groupingsets_path(PlannerInfo *root, numGroupCols, rollup->numGroups, having_qual, + sort_path.disabled_nodes, sort_path.startup_cost, sort_path.total_cost, sort_path.rows, subpath->pathtarget->width); } + pathnode->path.disabled_nodes += agg_path.disabled_nodes; pathnode->path.total_cost += agg_path.total_cost; pathnode->path.rows += agg_path.rows; } @@ -3390,6 +3494,7 @@ create_minmaxagg_path(PlannerInfo *root, { MinMaxAggPath *pathnode = makeNode(MinMaxAggPath); Cost initplan_cost; + int initplan_disabled_nodes = 0; ListCell *lc; /* The topmost generated Plan node will be a Result */ @@ -3414,12 +3519,14 @@ create_minmaxagg_path(PlannerInfo *root, { MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc); + initplan_disabled_nodes += mminfo->path->disabled_nodes; initplan_cost += mminfo->pathcost; if (!mminfo->path->parallel_safe) pathnode->path.parallel_safe = false; } /* add tlist eval cost for each output row, plus cpu_tuple_cost */ + pathnode->path.disabled_nodes = initplan_disabled_nodes; pathnode->path.startup_cost = initplan_cost + target->cost.startup; pathnode->path.total_cost = initplan_cost + target->cost.startup + target->cost.per_tuple + cpu_tuple_cost; @@ -3512,6 +3619,7 @@ create_windowagg_path(PlannerInfo *root, cost_windowagg(&pathnode->path, root, windowFuncs, winclause, + subpath->disabled_nodes, subpath->startup_cost, subpath->total_cost, subpath->rows); @@ -3529,25 +3637,26 @@ create_windowagg_path(PlannerInfo *root, * Creates a pathnode that represents computation of INTERSECT or EXCEPT * * 'rel' is the parent relation associated with the result - * 'subpath' is the path representing the source of data + * 'leftpath' is the path representing the left-hand source of data + * 'rightpath' is the path representing the right-hand source of data * 'cmd' is the specific semantics (INTERSECT or EXCEPT, with/without ALL) * 'strategy' is the implementation strategy (sorted or hashed) - * 'distinctList' is a list of SortGroupClause's representing the grouping - * 'flagColIdx' is the column number where the flag column will be, if any - * 'firstFlag' is the flag value for the first input relation when hashing; - * or -1 when sorting - * 'numGroups' is the estimated number of distinct groups + * 'groupList' is a list of SortGroupClause's representing the grouping + * 'numGroups' is the estimated number of distinct groups in left-hand input * 'outputRows' is the estimated number of output rows + * + * leftpath and rightpath must produce the same columns. Moreover, if + * strategy is SETOP_SORTED, leftpath and rightpath must both be sorted + * by all the grouping columns. */ SetOpPath * create_setop_path(PlannerInfo *root, RelOptInfo *rel, - Path *subpath, + Path *leftpath, + Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, - List *distinctList, - AttrNumber flagColIdx, - int firstFlag, + List *groupList, double numGroups, double outputRows) { @@ -3555,33 +3664,90 @@ create_setop_path(PlannerInfo *root, pathnode->path.pathtype = T_SetOp; pathnode->path.parent = rel; - /* SetOp doesn't project, so use source path's pathtarget */ - pathnode->path.pathtarget = subpath->pathtarget; + pathnode->path.pathtarget = rel->reltarget; /* For now, assume we are above any joins, so no parameterization */ pathnode->path.param_info = NULL; pathnode->path.parallel_aware = false; pathnode->path.parallel_safe = rel->consider_parallel && - subpath->parallel_safe; - pathnode->path.parallel_workers = subpath->parallel_workers; + leftpath->parallel_safe && rightpath->parallel_safe; + pathnode->path.parallel_workers = + leftpath->parallel_workers + rightpath->parallel_workers; /* SetOp preserves the input sort order if in sort mode */ pathnode->path.pathkeys = - (strategy == SETOP_SORTED) ? subpath->pathkeys : NIL; + (strategy == SETOP_SORTED) ? leftpath->pathkeys : NIL; - pathnode->subpath = subpath; + pathnode->leftpath = leftpath; + pathnode->rightpath = rightpath; pathnode->cmd = cmd; pathnode->strategy = strategy; - pathnode->distinctList = distinctList; - pathnode->flagColIdx = flagColIdx; - pathnode->firstFlag = firstFlag; + pathnode->groupList = groupList; pathnode->numGroups = numGroups; /* - * Charge one cpu_operator_cost per comparison per input tuple. We assume - * all columns get compared at most of the tuples. + * Compute cost estimates. As things stand, we end up with the same total + * cost in this node for sort and hash methods, but different startup + * costs. This could be refined perhaps, but it'll do for now. */ - pathnode->path.startup_cost = subpath->startup_cost; - pathnode->path.total_cost = subpath->total_cost + - cpu_operator_cost * subpath->rows * list_length(distinctList); + pathnode->path.disabled_nodes = + leftpath->disabled_nodes + rightpath->disabled_nodes; + if (strategy == SETOP_SORTED) + { + /* + * In sorted mode, we can emit output incrementally. Charge one + * cpu_operator_cost per comparison per input tuple. Like cost_group, + * we assume all columns get compared at most of the tuples. + */ + pathnode->path.startup_cost = + leftpath->startup_cost + rightpath->startup_cost; + pathnode->path.total_cost = + leftpath->total_cost + rightpath->total_cost + + cpu_operator_cost * (leftpath->rows + rightpath->rows) * list_length(groupList); + + /* + * Also charge a small amount per extracted tuple. Like cost_sort, + * charge only operator cost not cpu_tuple_cost, since SetOp does no + * qual-checking or projection. + */ + pathnode->path.total_cost += cpu_operator_cost * outputRows; + } + else + { + Size hashentrysize; + + /* + * In hashed mode, we must read all the input before we can emit + * anything. Also charge comparison costs to represent the cost of + * hash table lookups. + */ + pathnode->path.startup_cost = + leftpath->total_cost + rightpath->total_cost + + cpu_operator_cost * (leftpath->rows + rightpath->rows) * list_length(groupList); + pathnode->path.total_cost = pathnode->path.startup_cost; + + /* + * Also charge a small amount per extracted tuple. Like cost_sort, + * charge only operator cost not cpu_tuple_cost, since SetOp does no + * qual-checking or projection. + */ + pathnode->path.total_cost += cpu_operator_cost * outputRows; + + /* + * Mark the path as disabled if enable_hashagg is off. While this + * isn't exactly a HashAgg node, it seems close enough to justify + * letting that switch control it. + */ + if (!enable_hashagg) + pathnode->path.disabled_nodes++; + + /* + * Also disable if it doesn't look like the hashtable will fit into + * hash_mem. + */ + hashentrysize = MAXALIGN(leftpath->pathtarget->width) + + MAXALIGN(SizeofMinimalTupleHeader); + if (hashentrysize * numGroups > get_hash_memory_limit()) + pathnode->path.disabled_nodes++; + } pathnode->path.rows = outputRows; return pathnode; @@ -3678,6 +3844,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, * possible refetches, but it's hard to say how much. For now, use * cpu_tuple_cost per row. */ + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost + cpu_tuple_cost * subpath->rows; @@ -3754,6 +3921,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, * costs to change any higher-level planning choices. But we might want * to make it look better sometime. */ + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost; if (returningLists != NIL) @@ -3830,6 +3998,7 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel, subpath->parallel_safe; pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.rows = subpath->rows; + pathnode->path.disabled_nodes = subpath->disabled_nodes; pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 81abadd6db3e8..41a4c81e94a75 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -4,7 +4,7 @@ * PlaceHolderVar and PlaceHolderInfo manipulation routines * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -314,6 +314,33 @@ fix_placeholder_input_needed_levels(PlannerInfo *root) } } +/* + * rebuild_placeholder_attr_needed + * Put back attr_needed bits for Vars/PHVs needed in PlaceHolderVars. + * + * This is used to rebuild attr_needed/ph_needed sets after removal of a + * useless outer join. It should match what + * fix_placeholder_input_needed_levels did, except that we call + * add_vars_to_attr_needed not add_vars_to_targetlist. + */ +void +rebuild_placeholder_attr_needed(PlannerInfo *root) +{ + ListCell *lc; + + foreach(lc, root->placeholder_list) + { + PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); + List *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr, + PVC_RECURSE_AGGREGATES | + PVC_RECURSE_WINDOWFUNCS | + PVC_INCLUDE_PLACEHOLDERS); + + add_vars_to_attr_needed(root, vars, phinfo->ph_eval_at); + list_free(vars); + } +} + /* * add_placeholders_to_base_rels * Add any required PlaceHolderVars to base rels' targetlists. diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 9efdd844aac44..59233b647302d 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -4,7 +4,7 @@ * routines for accessing the system catalogs * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -45,6 +45,7 @@ #include "rewrite/rewriteManip.h" #include "statistics/statistics.h" #include "storage/bufmgr.h" +#include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/partcache.h" @@ -174,12 +175,14 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, { for (int i = 0; i < relation->rd_att->natts; i++) { - Form_pg_attribute attr = TupleDescAttr(relation->rd_att, i); + CompactAttribute *attr = TupleDescCompactAttr(relation->rd_att, i); - if (attr->attnotnull) + Assert(attr->attnullability != ATTNULLABLE_UNKNOWN); + + if (attr->attnullability == ATTNULLABLE_VALID) { rel->notnullattnums = bms_add_member(rel->notnullattnums, - attr->attnum); + i + 1); /* * Per RemoveAttributeById(), dropped columns will have their @@ -240,7 +243,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Oid indexoid = lfirst_oid(l); Relation indexRelation; Form_pg_index index; - IndexAmRoutine *amroutine; + IndexAmRoutine *amroutine = NULL; IndexOptInfo *info; int ncolumns, nkeycolumns; @@ -324,7 +327,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->amcanparallel = amroutine->amcanparallel; info->amhasgettuple = (amroutine->amgettuple != NULL); info->amhasgetbitmap = amroutine->amgetbitmap != NULL && - relation->rd_tableam->scan_bitmap_next_block != NULL; + relation->rd_tableam->scan_bitmap_next_tuple != NULL; info->amcanmarkpos = (amroutine->ammarkpos != NULL && amroutine->amrestrpos != NULL); info->amcostestimate = amroutine->amcostestimate; @@ -364,14 +367,10 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, * Since "<" uniquely defines the behavior of a sort * order, this is a sufficient test. * - * XXX This method is rather slow and also requires the - * undesirable assumption that the other index AM numbers - * its strategies the same as btree. It'd be better to - * have a way to explicitly declare the corresponding - * btree opfamily for each opfamily of the other index - * type. But given the lack of current or foreseeable - * amcanorder index types, it's not worth expending more - * effort on now. + * XXX This method is rather slow and complicated. It'd + * be better to have a way to explicitly declare the + * corresponding btree opfamily for each opfamily of the + * other index type. */ info->sortopfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns); info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns); @@ -381,27 +380,27 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, { int16 opt = indexRelation->rd_indoption[i]; Oid ltopr; - Oid btopfamily; - Oid btopcintype; - int16 btstrategy; + Oid opfamily; + Oid opcintype; + CompareType cmptype; info->reverse_sort[i] = (opt & INDOPTION_DESC) != 0; info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0; - ltopr = get_opfamily_member(info->opfamily[i], - info->opcintype[i], - info->opcintype[i], - BTLessStrategyNumber); + ltopr = get_opfamily_member_for_cmptype(info->opfamily[i], + info->opcintype[i], + info->opcintype[i], + COMPARE_LT); if (OidIsValid(ltopr) && get_ordering_op_properties(ltopr, - &btopfamily, - &btopcintype, - &btstrategy) && - btopcintype == info->opcintype[i] && - btstrategy == BTLessStrategyNumber) + &opfamily, + &opcintype, + &cmptype) && + opcintype == info->opcintype[i] && + cmptype == COMPARE_LT) { /* Successful mapping */ - info->sortopfamily[i] = btopfamily; + info->sortopfamily[i] = opfamily; } else { @@ -456,6 +455,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->indrestrictinfo = NIL; /* set later, in indxpath.c */ info->predOK = false; /* set later, in indxpath.c */ info->unique = index->indisunique; + info->nullsnotdistinct = index->indnullsnotdistinct; info->immediate = index->indimmediate; info->hypothetical = false; @@ -484,13 +484,12 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->tuples = rel->tuples; } - if (info->relam == BTREE_AM_OID) + /* + * Get tree height while we have the index open + */ + if (amroutine->amgettreeheight) { - /* - * For btrees, get tree height while we have the index - * open - */ - info->tree_height = _bt_getrootheight(indexRelation); + info->tree_height = amroutine->amgettreeheight(indexRelation); } else { @@ -528,6 +527,17 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, /* Grab foreign-table info using the relcache, while we have it */ if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) { + /* Check if the access to foreign tables is restricted */ + if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_FOREIGN_TABLE) != 0)) + { + /* there must not be built-in foreign tables */ + Assert(RelationGetRelid(relation) >= FirstNormalObjectId); + + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access to non-system foreign table is restricted"))); + } + rel->serverid = GetForeignServerIdByRelId(RelationGetRelid(relation)); rel->fdwroutine = GetFdwRoutineForRelation(relation, true); } @@ -628,6 +638,10 @@ get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel, /* conrelid should always be that of the table we're considering */ Assert(cachedfk->conrelid == RelationGetRelid(relation)); + /* skip constraints currently not enforced */ + if (!cachedfk->conenforced) + continue; + /* Scan to find other RTEs matching confrelid */ rti = 0; foreach(lc2, rtable) @@ -817,7 +831,7 @@ infer_arbiter_indexes(PlannerInfo *root) */ if (indexOidFromConstraint == idxForm->indexrelid) { - if (!idxForm->indisunique && onconflict->action == ONCONFLICT_UPDATE) + if (idxForm->indisexclusion && onconflict->action == ONCONFLICT_UPDATE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints"))); @@ -842,6 +856,13 @@ infer_arbiter_indexes(PlannerInfo *root) if (!idxForm->indisunique) goto next; + /* + * So-called unique constraints with WITHOUT OVERLAPS are really + * exclusion constraints, so skip those too. + */ + if (idxForm->indisexclusion) + goto next; + /* Build BMS representation of plain (non expression) index attrs */ indexedAttrs = NULL; for (natt = 0; natt < idxForm->indnkeyatts; natt++) @@ -1232,6 +1253,7 @@ get_relation_data_width(Oid relid, int32 *attr_widths) * get_relation_constraints * * Retrieve the applicable constraint expressions of the given relation. + * Only constraints that have been validated are considered. * * Returns a List (possibly empty) of constraint expressions. Each one * has been canonicalized, and its Vars are changed to have the varno @@ -1280,11 +1302,20 @@ get_relation_constraints(PlannerInfo *root, /* * If this constraint hasn't been fully validated yet, we must - * ignore it here. Also ignore if NO INHERIT and we weren't told - * that that's safe. + * ignore it here. */ if (!constr->check[i].ccvalid) continue; + + /* + * NOT ENFORCED constraints are always marked as invalid, which + * should have been ignored. + */ + Assert(constr->check[i].ccenforced); + + /* + * Also ignore if NO INHERIT and we weren't told that that's safe. + */ if (constr->check[i].ccnoinherit && !include_noinherit) continue; @@ -1323,17 +1354,18 @@ get_relation_constraints(PlannerInfo *root, for (i = 1; i <= natts; i++) { - Form_pg_attribute att = TupleDescAttr(relation->rd_att, i - 1); + CompactAttribute *att = TupleDescCompactAttr(relation->rd_att, i - 1); - if (att->attnotnull && !att->attisdropped) + if (att->attnullability == ATTNULLABLE_VALID && !att->attisdropped) { + Form_pg_attribute wholeatt = TupleDescAttr(relation->rd_att, i - 1); NullTest *ntest = makeNode(NullTest); ntest->arg = (Expr *) makeVar(varno, i, - att->atttypid, - att->atttypmod, - att->attcollation, + wholeatt->atttypid, + wholeatt->atttypmod, + wholeatt->attcollation, 0); ntest->nulltesttype = IS_NOT_NULL; @@ -1680,6 +1712,8 @@ relation_excluded_by_constraints(PlannerInfo *root, * Currently, attnotnull constraints must be treated as NO INHERIT unless * this is a partitioned table. In future we might track their * inheritance status more accurately, allowing this to be refined. + * + * XXX do we need/want to change this? */ include_notnull = (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE); @@ -1825,8 +1859,8 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel) case RTE_NAMEDTUPLESTORE: case RTE_RESULT: /* Not all of these can have dropped cols, but share code anyway */ - expandRTE(rte, varno, 0, -1, true /* include dropped */ , - NULL, &colvars); + expandRTE(rte, varno, 0, VAR_RETURNING_DEFAULT, -1, + true /* include dropped */ , NULL, &colvars); foreach(l, colvars) { var = (Var *) lfirst(l); diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 6e3b376f3d35a..ac28573cd0a5a 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -4,7 +4,7 @@ * Routines to attempt to prove logical implications between predicate * expressions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -908,7 +908,7 @@ static void list_startup_fn(Node *clause, PredIterInfo info) { info->state_list = (List *) clause; - info->state = (void *) list_head(info->state_list); + info->state = list_head(info->state_list); } static Node * @@ -920,7 +920,7 @@ list_next_fn(PredIterInfo info) if (l == NULL) return NULL; n = lfirst(l); - info->state = (void *) lnext(info->state_list, l); + info->state = lnext(info->state_list, l); return n; } @@ -938,7 +938,7 @@ static void boolexpr_startup_fn(Node *clause, PredIterInfo info) { info->state_list = ((BoolExpr *) clause)->args; - info->state = (void *) list_head(info->state_list); + info->state = list_head(info->state_list); } /* @@ -948,7 +948,7 @@ boolexpr_startup_fn(Node *clause, PredIterInfo info) typedef struct { OpExpr opexpr; - Const constexpr; + Const const_expr; int next_elem; int num_elems; Datum *elem_values; @@ -968,7 +968,7 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info) /* Create working state struct */ state = (ArrayConstIterState *) palloc(sizeof(ArrayConstIterState)); - info->state = (void *) state; + info->state = state; /* Deconstruct the array literal */ arrayconst = (Const *) lsecond(saop->args); @@ -992,13 +992,13 @@ arrayconst_startup_fn(Node *clause, PredIterInfo info) state->opexpr.args = list_copy(saop->args); /* Set up a dummy Const node to hold the per-element values */ - state->constexpr.xpr.type = T_Const; - state->constexpr.consttype = ARR_ELEMTYPE(arrayval); - state->constexpr.consttypmod = -1; - state->constexpr.constcollid = arrayconst->constcollid; - state->constexpr.constlen = elmlen; - state->constexpr.constbyval = elmbyval; - lsecond(state->opexpr.args) = &state->constexpr; + state->const_expr.xpr.type = T_Const; + state->const_expr.consttype = ARR_ELEMTYPE(arrayval); + state->const_expr.consttypmod = -1; + state->const_expr.constcollid = arrayconst->constcollid; + state->const_expr.constlen = elmlen; + state->const_expr.constbyval = elmbyval; + lsecond(state->opexpr.args) = &state->const_expr; /* Initialize iteration state */ state->next_elem = 0; @@ -1011,8 +1011,8 @@ arrayconst_next_fn(PredIterInfo info) if (state->next_elem >= state->num_elems) return NULL; - state->constexpr.constvalue = state->elem_values[state->next_elem]; - state->constexpr.constisnull = state->elem_nulls[state->next_elem]; + state->const_expr.constvalue = state->elem_values[state->next_elem]; + state->const_expr.constisnull = state->elem_nulls[state->next_elem]; state->next_elem++; return (Node *) &(state->opexpr); } @@ -1047,7 +1047,7 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info) /* Create working state struct */ state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState)); - info->state = (void *) state; + info->state = state; /* Set up a dummy OpExpr to return as the per-item node */ state->opexpr.xpr.type = T_OpExpr; @@ -1605,36 +1605,36 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool allow_false) /* - * Define "operator implication tables" for btree operators ("strategies"), + * Define "operator implication tables" for index operators ("cmptypes"), * and similar tables for refutation. * - * The strategy numbers defined by btree indexes (see access/stratnum.h) are: - * 1 < 2 <= 3 = 4 >= 5 > + * The row compare numbers defined by indexes (see access/cmptype.h) are: + * 1 < 2 <= 3 = 4 >= 5 > 6 <> * and in addition we use 6 to represent <>. <> is not a btree-indexable * operator, but we assume here that if an equality operator of a btree * opfamily has a negator operator, the negator behaves as <> for the opfamily. - * (This convention is also known to get_op_btree_interpretation().) + * (This convention is also known to get_op_index_interpretation().) * - * BT_implies_table[] and BT_refutes_table[] are used for cases where we have + * RC_implies_table[] and RC_refutes_table[] are used for cases where we have * two identical subexpressions and we want to know whether one operator * expression implies or refutes the other. That is, if the "clause" is * EXPR1 clause_op EXPR2 and the "predicate" is EXPR1 pred_op EXPR2 for the * same two (immutable) subexpressions: - * BT_implies_table[clause_op-1][pred_op-1] + * RC_implies_table[clause_op-1][pred_op-1] * is true if the clause implies the predicate - * BT_refutes_table[clause_op-1][pred_op-1] + * RC_refutes_table[clause_op-1][pred_op-1] * is true if the clause refutes the predicate - * where clause_op and pred_op are strategy numbers (from 1 to 6) in the - * same btree opfamily. For example, "x < y" implies "x <= y" and refutes + * where clause_op and pred_op are cmptype numbers (from 1 to 6) in the + * same opfamily. For example, "x < y" implies "x <= y" and refutes * "x > y". * - * BT_implic_table[] and BT_refute_table[] are used where we have two + * RC_implic_table[] and RC_refute_table[] are used where we have two * constants that we need to compare. The interpretation of: * - * test_op = BT_implic_table[clause_op-1][pred_op-1] + * test_op = RC_implic_table[clause_op-1][pred_op-1] * - * where test_op, clause_op and pred_op are strategy numbers (from 1 to 6) - * of btree operators, is as follows: + * where test_op, clause_op and pred_op are cmptypes (from 1 to 6) + * of index operators, is as follows: * * If you know, for some EXPR, that "EXPR clause_op CONST1" is true, and you * want to determine whether "EXPR pred_op CONST2" must also be true, then @@ -1645,7 +1645,7 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool allow_false) * For example, if clause is "Quantity > 10" and pred is "Quantity > 5" * then we test "5 <= 10" which evals to true, so clause implies pred. * - * Similarly, the interpretation of a BT_refute_table entry is: + * Similarly, the interpretation of a RC_refute_table entry is: * * If you know, for some EXPR, that "EXPR clause_op CONST1" is true, and you * want to determine whether "EXPR pred_op CONST2" must be false, then @@ -1659,17 +1659,17 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool allow_false) * An entry where test_op == 0 means the implication cannot be determined. */ -#define BTLT BTLessStrategyNumber -#define BTLE BTLessEqualStrategyNumber -#define BTEQ BTEqualStrategyNumber -#define BTGE BTGreaterEqualStrategyNumber -#define BTGT BTGreaterStrategyNumber -#define BTNE ROWCOMPARE_NE +#define RCLT COMPARE_LT +#define RCLE COMPARE_LE +#define RCEQ COMPARE_EQ +#define RCGE COMPARE_GE +#define RCGT COMPARE_GT +#define RCNE COMPARE_NE /* We use "none" for 0/false to make the tables align nicely */ #define none 0 -static const bool BT_implies_table[6][6] = { +static const bool RC_implies_table[6][6] = { /* * The predicate operator: * LT LE EQ GE GT NE @@ -1682,7 +1682,7 @@ static const bool BT_implies_table[6][6] = { {none, none, none, none, none, true} /* NE */ }; -static const bool BT_refutes_table[6][6] = { +static const bool RC_refutes_table[6][6] = { /* * The predicate operator: * LT LE EQ GE GT NE @@ -1695,30 +1695,30 @@ static const bool BT_refutes_table[6][6] = { {none, none, true, none, none, none} /* NE */ }; -static const StrategyNumber BT_implic_table[6][6] = { +static const CompareType RC_implic_table[6][6] = { /* * The predicate operator: * LT LE EQ GE GT NE */ - {BTGE, BTGE, none, none, none, BTGE}, /* LT */ - {BTGT, BTGE, none, none, none, BTGT}, /* LE */ - {BTGT, BTGE, BTEQ, BTLE, BTLT, BTNE}, /* EQ */ - {none, none, none, BTLE, BTLT, BTLT}, /* GE */ - {none, none, none, BTLE, BTLE, BTLE}, /* GT */ - {none, none, none, none, none, BTEQ} /* NE */ + {RCGE, RCGE, none, none, none, RCGE}, /* LT */ + {RCGT, RCGE, none, none, none, RCGT}, /* LE */ + {RCGT, RCGE, RCEQ, RCLE, RCLT, RCNE}, /* EQ */ + {none, none, none, RCLE, RCLT, RCLT}, /* GE */ + {none, none, none, RCLE, RCLE, RCLE}, /* GT */ + {none, none, none, none, none, RCEQ} /* NE */ }; -static const StrategyNumber BT_refute_table[6][6] = { +static const CompareType RC_refute_table[6][6] = { /* * The predicate operator: * LT LE EQ GE GT NE */ - {none, none, BTGE, BTGE, BTGE, none}, /* LT */ - {none, none, BTGT, BTGT, BTGE, none}, /* LE */ - {BTLE, BTLT, BTNE, BTGT, BTGE, BTEQ}, /* EQ */ - {BTLE, BTLT, BTLT, none, none, none}, /* GE */ - {BTLE, BTLE, BTLE, none, none, none}, /* GT */ - {none, none, BTEQ, none, none, none} /* NE */ + {none, none, RCGE, RCGE, RCGE, none}, /* LT */ + {none, none, RCGT, RCGT, RCGE, none}, /* LE */ + {RCLE, RCLT, RCNE, RCGT, RCGE, RCEQ}, /* EQ */ + {RCLE, RCLT, RCLT, none, none, none}, /* GE */ + {RCLE, RCLE, RCLE, none, none, none}, /* GT */ + {none, none, RCEQ, none, none, none} /* NE */ }; @@ -2165,23 +2165,23 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it) * operator. This can happen in cases with incomplete sets of cross-type * comparison operators. */ - clause_op_infos = get_op_btree_interpretation(clause_op); + clause_op_infos = get_op_index_interpretation(clause_op); if (clause_op_infos) - pred_op_infos = get_op_btree_interpretation(pred_op); + pred_op_infos = get_op_index_interpretation(pred_op); else /* no point in looking */ pred_op_infos = NIL; foreach(lcp, pred_op_infos) { - OpBtreeInterpretation *pred_op_info = lfirst(lcp); + OpIndexInterpretation *pred_op_info = lfirst(lcp); Oid opfamily_id = pred_op_info->opfamily_id; foreach(lcc, clause_op_infos) { - OpBtreeInterpretation *clause_op_info = lfirst(lcc); - StrategyNumber pred_strategy, - clause_strategy, - test_strategy; + OpIndexInterpretation *clause_op_info = lfirst(lcc); + CompareType pred_cmptype, + clause_cmptype, + test_cmptype; /* Must find them in same opfamily */ if (opfamily_id != clause_op_info->opfamily_id) @@ -2189,51 +2189,51 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it) /* Lefttypes should match */ Assert(clause_op_info->oplefttype == pred_op_info->oplefttype); - pred_strategy = pred_op_info->strategy; - clause_strategy = clause_op_info->strategy; + pred_cmptype = pred_op_info->cmptype; + clause_cmptype = clause_op_info->cmptype; /* * Check to see if we can make a proof for same-subexpressions * cases based on the operators' relationship in this opfamily. */ if (refute_it) - same_subexprs |= BT_refutes_table[clause_strategy - 1][pred_strategy - 1]; + same_subexprs |= RC_refutes_table[clause_cmptype - 1][pred_cmptype - 1]; else - same_subexprs |= BT_implies_table[clause_strategy - 1][pred_strategy - 1]; + same_subexprs |= RC_implies_table[clause_cmptype - 1][pred_cmptype - 1]; /* - * Look up the "test" strategy number in the implication table + * Look up the "test" cmptype number in the implication table */ if (refute_it) - test_strategy = BT_refute_table[clause_strategy - 1][pred_strategy - 1]; + test_cmptype = RC_refute_table[clause_cmptype - 1][pred_cmptype - 1]; else - test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; + test_cmptype = RC_implic_table[clause_cmptype - 1][pred_cmptype - 1]; - if (test_strategy == 0) + if (test_cmptype == 0) { /* Can't determine implication using this interpretation */ continue; } /* - * See if opfamily has an operator for the test strategy and the + * See if opfamily has an operator for the test cmptype and the * datatypes. */ - if (test_strategy == BTNE) + if (test_cmptype == RCNE) { - test_op = get_opfamily_member(opfamily_id, - pred_op_info->oprighttype, - clause_op_info->oprighttype, - BTEqualStrategyNumber); + test_op = get_opfamily_member_for_cmptype(opfamily_id, + pred_op_info->oprighttype, + clause_op_info->oprighttype, + COMPARE_EQ); if (OidIsValid(test_op)) test_op = get_negator(test_op); } else { - test_op = get_opfamily_member(opfamily_id, - pred_op_info->oprighttype, - clause_op_info->oprighttype, - test_strategy); + test_op = get_opfamily_member_for_cmptype(opfamily_id, + pred_op_info->oprighttype, + clause_op_info->oprighttype, + test_cmptype); } if (!OidIsValid(test_op)) diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index e05b21c884e57..ff507331a061a 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -3,7 +3,7 @@ * relnode.c * Relation-node lookup/construction routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -876,15 +876,15 @@ build_join_rel(PlannerInfo *root, * 'restrictlist': list of RestrictInfo nodes that apply to this particular * pair of joinable relations * 'sjinfo': child join's join-type details + * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids */ RelOptInfo * build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, - List *restrictlist, SpecialJoinInfo *sjinfo) + List *restrictlist, SpecialJoinInfo *sjinfo, + int nappinfos, AppendRelInfo **appinfos) { RelOptInfo *joinrel = makeNode(RelOptInfo); - AppendRelInfo **appinfos; - int nappinfos; /* Only joins between "other" relations land here. */ Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel)); @@ -892,16 +892,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, /* The parent joinrel should have consider_partitionwise_join set. */ Assert(parent_joinrel->consider_partitionwise_join); - /* - * Find the AppendRelInfo structures for the child baserels. We'll need - * these for computing the child join's relid set, and later for mapping - * Vars to the child rel. - */ - appinfos = find_appinfos_by_relids(root, - bms_union(outer_rel->relids, - inner_rel->relids), - &nappinfos); - joinrel->reloptkind = RELOPT_OTHER_JOINREL; joinrel->relids = adjust_child_relids(parent_joinrel->relids, nappinfos, appinfos); @@ -1017,8 +1007,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, nappinfos, appinfos, parent_joinrel, joinrel); - pfree(appinfos); - return joinrel; } @@ -1923,6 +1911,13 @@ get_param_path_clause_serials(Path *path) { if (path->param_info == NULL) return NULL; /* not parameterized */ + + /* + * We don't currently support parameterized MergeAppend paths, as + * explained in the comments for generate_orderedappend_paths. + */ + Assert(!IsA(path, MergeAppendPath)); + if (IsA(path, NestPath) || IsA(path, MergePath) || IsA(path, HashPath)) @@ -1976,27 +1971,6 @@ get_param_path_clause_serials(Path *path) } return pserials; } - else if (IsA(path, MergeAppendPath)) - { - /* Same as AppendPath case */ - MergeAppendPath *apath = (MergeAppendPath *) path; - Bitmapset *pserials; - ListCell *lc; - - pserials = NULL; - foreach(lc, apath->subpaths) - { - Path *subpath = (Path *) lfirst(lc); - Bitmapset *subserials; - - subserials = get_param_path_clause_serials(subpath); - if (lc == list_head(apath->subpaths)) - pserials = bms_copy(subserials); - else - pserials = bms_int_members(pserials, subserials); - } - return pserials; - } else { /* @@ -2092,10 +2066,9 @@ have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *restrictlist) { PartitionScheme part_scheme = rel1->part_scheme; + bool pk_known_equal[PARTITION_MAX_KEYS]; + int num_equal_pks; ListCell *lc; - int cnt_pks; - bool pk_has_clause[PARTITION_MAX_KEYS]; - bool strict_op; /* * This function must only be called when the joined relations have same @@ -2104,13 +2077,19 @@ have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, Assert(rel1->part_scheme == rel2->part_scheme); Assert(part_scheme); - memset(pk_has_clause, 0, sizeof(pk_has_clause)); + /* We use a bool array to track which partkey columns are known equal */ + memset(pk_known_equal, 0, sizeof(pk_known_equal)); + /* ... as well as a count of how many are known equal */ + num_equal_pks = 0; + + /* First, look through the join's restriction clauses */ foreach(lc, restrictlist) { RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc); OpExpr *opexpr; Expr *expr1; Expr *expr2; + bool strict_op; int ipk1; int ipk2; @@ -2188,11 +2167,19 @@ have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, if (ipk1 != ipk2) continue; + /* Ignore clause if we already proved these keys equal. */ + if (pk_known_equal[ipk1]) + continue; + + /* Reject if the partition key collation differs from the clause's. */ + if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid) + return false; + /* * The clause allows partitionwise join only if it uses the same * operator family as that specified by the partition key. */ - if (rel1->part_scheme->strategy == PARTITION_STRATEGY_HASH) + if (part_scheme->strategy == PARTITION_STRATEGY_HASH) { if (!OidIsValid(rinfo->hashjoinoperator) || !op_in_opfamily(rinfo->hashjoinoperator, @@ -2204,17 +2191,109 @@ have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, continue; /* Mark the partition key as having an equi-join clause. */ - pk_has_clause[ipk1] = true; + pk_known_equal[ipk1] = true; + + /* We can stop examining clauses once we prove all keys equal. */ + if (++num_equal_pks == part_scheme->partnatts) + return true; } - /* Check whether every partition key has an equi-join condition. */ - for (cnt_pks = 0; cnt_pks < part_scheme->partnatts; cnt_pks++) + /* + * Also check to see if any keys are known equal by equivclass.c. In most + * cases there would have been a join restriction clause generated from + * any EC that had such knowledge, but there might be no such clause, or + * it might happen to constrain other members of the ECs than the ones we + * are looking for. + */ + for (int ipk = 0; ipk < part_scheme->partnatts; ipk++) { - if (!pk_has_clause[cnt_pks]) - return false; + Oid btree_opfamily; + + /* Ignore if we already proved these keys equal. */ + if (pk_known_equal[ipk]) + continue; + + /* + * We need a btree opfamily to ask equivclass.c about. If the + * partopfamily is a hash opfamily, look up its equality operator, and + * select some btree opfamily that that operator is part of. (Any + * such opfamily should be good enough, since equivclass.c will track + * multiple opfamilies as appropriate.) + */ + if (part_scheme->strategy == PARTITION_STRATEGY_HASH) + { + Oid eq_op; + List *eq_opfamilies; + + eq_op = get_opfamily_member(part_scheme->partopfamily[ipk], + part_scheme->partopcintype[ipk], + part_scheme->partopcintype[ipk], + HTEqualStrategyNumber); + if (!OidIsValid(eq_op)) + break; /* we're not going to succeed */ + eq_opfamilies = get_mergejoin_opfamilies(eq_op); + if (eq_opfamilies == NIL) + break; /* we're not going to succeed */ + btree_opfamily = linitial_oid(eq_opfamilies); + } + else + btree_opfamily = part_scheme->partopfamily[ipk]; + + /* + * We consider only non-nullable partition keys here; nullable ones + * would not be treated as part of the same equivalence classes as + * non-nullable ones. + */ + foreach(lc, rel1->partexprs[ipk]) + { + Node *expr1 = (Node *) lfirst(lc); + ListCell *lc2; + Oid partcoll1 = rel1->part_scheme->partcollation[ipk]; + Oid exprcoll1 = exprCollation(expr1); + + foreach(lc2, rel2->partexprs[ipk]) + { + Node *expr2 = (Node *) lfirst(lc2); + + if (exprs_known_equal(root, expr1, expr2, btree_opfamily)) + { + /* + * Ensure that the collation of the expression matches + * that of the partition key. Checking just one collation + * (partcoll1 and exprcoll1) suffices because partcoll1 + * and partcoll2, as well as exprcoll1 and exprcoll2, + * should be identical. This holds because both rel1 and + * rel2 use the same PartitionScheme and expr1 and expr2 + * are equal. + */ + if (partcoll1 == exprcoll1) + { + Oid partcoll2 PG_USED_FOR_ASSERTS_ONLY = + rel2->part_scheme->partcollation[ipk]; + Oid exprcoll2 PG_USED_FOR_ASSERTS_ONLY = + exprCollation(expr2); + + Assert(partcoll2 == exprcoll2); + pk_known_equal[ipk] = true; + break; + } + } + } + if (pk_known_equal[ipk]) + break; + } + + if (pk_known_equal[ipk]) + { + /* We can stop examining keys once we prove all keys equal. */ + if (++num_equal_pks == part_scheme->partnatts) + return true; + } + else + break; /* no chance to succeed, give up */ } - return true; + return false; } /* diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index 0b406e93342d3..a80083d23232b 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -3,7 +3,7 @@ * restrictinfo.c * RestrictInfo node manipulation routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -21,17 +21,6 @@ #include "optimizer/restrictinfo.h" -static RestrictInfo *make_restrictinfo_internal(PlannerInfo *root, - Expr *clause, - Expr *orclause, - bool is_pushed_down, - bool has_clone, - bool is_clone, - bool pseudoconstant, - Index security_level, - Relids required_relids, - Relids incompatible_relids, - Relids outer_relids); static Expr *make_sub_restrictinfos(PlannerInfo *root, Expr *clause, bool is_pushed_down, @@ -90,36 +79,38 @@ make_restrictinfo(PlannerInfo *root, /* Shouldn't be an AND clause, else AND/OR flattening messed up */ Assert(!is_andclause(clause)); - return make_restrictinfo_internal(root, - clause, - NULL, - is_pushed_down, - has_clone, - is_clone, - pseudoconstant, - security_level, - required_relids, - incompatible_relids, - outer_relids); + return make_plain_restrictinfo(root, + clause, + NULL, + is_pushed_down, + has_clone, + is_clone, + pseudoconstant, + security_level, + required_relids, + incompatible_relids, + outer_relids); } /* - * make_restrictinfo_internal + * make_plain_restrictinfo * - * Common code for the main entry points and the recursive cases. + * Common code for the main entry points and the recursive cases. Also, + * useful while constructing RestrictInfos above OR clause, which already has + * RestrictInfos above its subclauses. */ -static RestrictInfo * -make_restrictinfo_internal(PlannerInfo *root, - Expr *clause, - Expr *orclause, - bool is_pushed_down, - bool has_clone, - bool is_clone, - bool pseudoconstant, - Index security_level, - Relids required_relids, - Relids incompatible_relids, - Relids outer_relids) +RestrictInfo * +make_plain_restrictinfo(PlannerInfo *root, + Expr *clause, + Expr *orclause, + bool is_pushed_down, + bool has_clone, + bool is_clone, + bool pseudoconstant, + Index security_level, + Relids required_relids, + Relids incompatible_relids, + Relids outer_relids) { RestrictInfo *restrictinfo = makeNode(RestrictInfo); Relids baserels; @@ -296,17 +287,17 @@ make_sub_restrictinfos(PlannerInfo *root, NULL, incompatible_relids, outer_relids)); - return (Expr *) make_restrictinfo_internal(root, - clause, - make_orclause(orlist), - is_pushed_down, - has_clone, - is_clone, - pseudoconstant, - security_level, - required_relids, - incompatible_relids, - outer_relids); + return (Expr *) make_plain_restrictinfo(root, + clause, + make_orclause(orlist), + is_pushed_down, + has_clone, + is_clone, + pseudoconstant, + security_level, + required_relids, + incompatible_relids, + outer_relids); } else if (is_andclause(clause)) { @@ -328,17 +319,17 @@ make_sub_restrictinfos(PlannerInfo *root, return make_andclause(andlist); } else - return (Expr *) make_restrictinfo_internal(root, - clause, - NULL, - is_pushed_down, - has_clone, - is_clone, - pseudoconstant, - security_level, - required_relids, - incompatible_relids, - outer_relids); + return (Expr *) make_plain_restrictinfo(root, + clause, + NULL, + is_pushed_down, + has_clone, + is_clone, + pseudoconstant, + security_level, + required_relids, + incompatible_relids, + outer_relids); } /* diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 7ef7f34d8b5d6..d2b4ecc5e5131 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -3,7 +3,7 @@ * tlist.c * Target list manipulation routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -1139,8 +1139,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context) context->current_depth = 0; context->current_sgref = 0; /* subexpressions are not sortgroup items */ - (void) expression_tree_walker(node, split_pathtarget_walker, - (void *) context); + (void) expression_tree_walker(node, split_pathtarget_walker, context); /* Depth is one more than any SRF below it */ srf_depth = context->current_depth + 1; @@ -1181,8 +1180,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context) * examine its inputs. */ context->current_sgref = 0; /* subexpressions are not sortgroup items */ - return expression_tree_walker(node, split_pathtarget_walker, - (void *) context); + return expression_tree_walker(node, split_pathtarget_walker, context); } /* diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index 844fc30978b21..8065237a1895f 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -9,7 +9,7 @@ * contains variables. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,6 +22,7 @@ #include "access/sysattr.h" #include "nodes/nodeFuncs.h" +#include "optimizer/clauses.h" #include "optimizer/optimizer.h" #include "optimizer/placeholder.h" #include "optimizer/prep.h" @@ -75,12 +76,17 @@ static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context); static bool pull_vars_walker(Node *node, pull_vars_context *context); static bool contain_var_clause_walker(Node *node, void *context); static bool contain_vars_of_level_walker(Node *node, int *sublevels_up); +static bool contain_vars_returning_old_or_new_walker(Node *node, void *context); static bool locate_var_of_level_walker(Node *node, locate_var_of_level_context *context); static bool pull_var_clause_walker(Node *node, pull_var_clause_context *context); static Node *flatten_join_alias_vars_mutator(Node *node, flatten_join_alias_vars_context *context); +static Node *flatten_group_exprs_mutator(Node *node, + flatten_join_alias_vars_context *context); +static Node *mark_nullable_by_grouping(PlannerInfo *root, Node *newnode, + Var *oldvar); static Node *add_nullingrels_if_needed(PlannerInfo *root, Node *newnode, Var *oldvar); static bool is_standard_join_alias_expression(Node *newnode, Var *oldvar); @@ -119,7 +125,7 @@ pull_varnos(PlannerInfo *root, Node *node) */ query_or_expression_tree_walker(node, pull_varnos_walker, - (void *) &context, + &context, 0); return context.varnos; @@ -145,7 +151,7 @@ pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup) */ query_or_expression_tree_walker(node, pull_varnos_walker, - (void *) &context, + &context, 0); return context.varnos; @@ -264,12 +270,11 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, pull_varnos_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, pull_varnos_walker, - (void *) context); + return expression_tree_walker(node, pull_varnos_walker, context); } @@ -319,8 +324,7 @@ pull_varattnos_walker(Node *node, pull_varattnos_context *context) /* Should not find an unplanned subquery */ Assert(!IsA(node, Query)); - return expression_tree_walker(node, pull_varattnos_walker, - (void *) context); + return expression_tree_walker(node, pull_varattnos_walker, context); } @@ -345,7 +349,7 @@ pull_vars_of_level(Node *node, int levelsup) */ query_or_expression_tree_walker(node, pull_vars_walker, - (void *) &context, + &context, 0); return context.vars; @@ -380,12 +384,11 @@ pull_vars_walker(Node *node, pull_vars_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, pull_vars_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, pull_vars_walker, - (void *) context); + return expression_tree_walker(node, pull_vars_walker, context); } @@ -444,7 +447,7 @@ contain_vars_of_level(Node *node, int levelsup) return query_or_expression_tree_walker(node, contain_vars_of_level_walker, - (void *) &sublevels_up, + &sublevels_up, 0); } @@ -479,14 +482,57 @@ contain_vars_of_level_walker(Node *node, int *sublevels_up) (*sublevels_up)++; result = query_tree_walker((Query *) node, contain_vars_of_level_walker, - (void *) sublevels_up, + sublevels_up, 0); (*sublevels_up)--; return result; } return expression_tree_walker(node, contain_vars_of_level_walker, - (void *) sublevels_up); + sublevels_up); +} + + +/* + * contain_vars_returning_old_or_new + * Recursively scan a clause to discover whether it contains any Var nodes + * (of the current query level) whose varreturningtype is VAR_RETURNING_OLD + * or VAR_RETURNING_NEW. + * + * Returns true if any found. + * + * Any ReturningExprs are also detected --- if an OLD/NEW Var was rewritten, + * we still regard this as a clause that returns OLD/NEW values. + * + * Does not examine subqueries, therefore must only be used after reduction + * of sublinks to subplans! + */ +bool +contain_vars_returning_old_or_new(Node *node) +{ + return contain_vars_returning_old_or_new_walker(node, NULL); +} + +static bool +contain_vars_returning_old_or_new_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + if (IsA(node, Var)) + { + if (((Var *) node)->varlevelsup == 0 && + ((Var *) node)->varreturningtype != VAR_RETURNING_DEFAULT) + return true; /* abort the tree traversal and return true */ + return false; + } + if (IsA(node, ReturningExpr)) + { + if (((ReturningExpr *) node)->retlevelsup == 0) + return true; /* abort the tree traversal and return true */ + return false; + } + return expression_tree_walker(node, contain_vars_returning_old_or_new_walker, + context); } @@ -515,7 +561,7 @@ locate_var_of_level(Node *node, int levelsup) (void) query_or_expression_tree_walker(node, locate_var_of_level_walker, - (void *) &context, + &context, 0); return context.var_location; @@ -553,14 +599,14 @@ locate_var_of_level_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, locate_var_of_level_walker, - (void *) context, + context, 0); context->sublevels_up--; return result; } return expression_tree_walker(node, locate_var_of_level_walker, - (void *) context); + context); } @@ -702,8 +748,7 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) else elog(ERROR, "PlaceHolderVar found where not expected"); } - return expression_tree_walker(node, pull_var_clause_walker, - (void *) context); + return expression_tree_walker(node, pull_var_clause_walker, context); } @@ -862,7 +907,7 @@ flatten_join_alias_vars_mutator(Node *node, phv = (PlaceHolderVar *) expression_tree_mutator(node, flatten_join_alias_vars_mutator, - (void *) context); + context); /* now fix PlaceHolderVar's relid sets */ if (phv->phlevelsup == context->sublevels_up) { @@ -884,7 +929,7 @@ flatten_join_alias_vars_mutator(Node *node, context->inserted_sublink = ((Query *) node)->hasSubLinks; newnode = query_tree_mutator((Query *) node, flatten_join_alias_vars_mutator, - (void *) context, + context, QTW_IGNORE_JOINALIASES); newnode->hasSubLinks |= context->inserted_sublink; context->inserted_sublink = save_inserted_sublink; @@ -893,13 +938,231 @@ flatten_join_alias_vars_mutator(Node *node, } /* Already-planned tree not supported */ Assert(!IsA(node, SubPlan)); + Assert(!IsA(node, AlternativeSubPlan)); /* Shouldn't need to handle these planner auxiliary nodes here */ Assert(!IsA(node, SpecialJoinInfo)); Assert(!IsA(node, PlaceHolderInfo)); Assert(!IsA(node, MinMaxAggInfo)); - return expression_tree_mutator(node, flatten_join_alias_vars_mutator, - (void *) context); + return expression_tree_mutator(node, flatten_join_alias_vars_mutator, context); +} + +/* + * flatten_group_exprs + * Replace Vars that reference GROUP outputs with the underlying grouping + * expressions. + * + * We have to preserve any varnullingrels info attached to the group Vars we're + * replacing. If the replacement expression is a Var or PlaceHolderVar or + * constructed from those, we can just add the varnullingrels bits to the + * existing nullingrels field(s); otherwise we have to add a PlaceHolderVar + * wrapper. + * + * NOTE: this is also used by ruleutils.c, to deparse one query parsetree back + * to source text. For that use-case, root will be NULL, which is why we have + * to pass the Query separately. We need the root itself only for preserving + * varnullingrels. We can avoid preserving varnullingrels in the ruleutils.c's + * usage because it does not make any difference to the deparsed source text. + */ +Node * +flatten_group_exprs(PlannerInfo *root, Query *query, Node *node) +{ + flatten_join_alias_vars_context context; + + /* + * We do not expect this to be applied to the whole Query, only to + * expressions or LATERAL subqueries. Hence, if the top node is a Query, + * it's okay to immediately increment sublevels_up. + */ + Assert(node != (Node *) query); + + context.root = root; + context.query = query; + context.sublevels_up = 0; + /* flag whether grouping expressions could possibly contain SubLinks */ + context.possible_sublink = query->hasSubLinks; + /* if hasSubLinks is already true, no need to work hard */ + context.inserted_sublink = query->hasSubLinks; + + return flatten_group_exprs_mutator(node, &context); +} + +static Node * +flatten_group_exprs_mutator(Node *node, + flatten_join_alias_vars_context *context) +{ + if (node == NULL) + return NULL; + if (IsA(node, Var)) + { + Var *var = (Var *) node; + RangeTblEntry *rte; + Node *newvar; + + /* No change unless Var belongs to the GROUP of the target level */ + if (var->varlevelsup != context->sublevels_up) + return node; /* no need to copy, really */ + rte = rt_fetch(var->varno, context->query->rtable); + if (rte->rtekind != RTE_GROUP) + return node; + + /* Expand group exprs reference */ + Assert(var->varattno > 0); + newvar = (Node *) list_nth(rte->groupexprs, var->varattno - 1); + Assert(newvar != NULL); + newvar = copyObject(newvar); + + /* + * If we are expanding an expr carried down from an upper query, must + * adjust its varlevelsup fields. + */ + if (context->sublevels_up != 0) + IncrementVarSublevelsUp(newvar, context->sublevels_up, 0); + + /* Preserve original Var's location, if possible */ + if (IsA(newvar, Var)) + ((Var *) newvar)->location = var->location; + + /* Detect if we are adding a sublink to query */ + if (context->possible_sublink && !context->inserted_sublink) + context->inserted_sublink = checkExprHasSubLink(newvar); + + /* Lastly, add any varnullingrels to the replacement expression */ + return mark_nullable_by_grouping(context->root, newvar, var); + } + + if (IsA(node, Aggref)) + { + Aggref *agg = (Aggref *) node; + + if ((int) agg->agglevelsup == context->sublevels_up) + { + /* + * If we find an aggregate call of the original level, do not + * recurse into its normal arguments, ORDER BY arguments, or + * filter; there are no grouped vars there. But we should check + * direct arguments as though they weren't in an aggregate. + */ + agg = copyObject(agg); + agg->aggdirectargs = (List *) + flatten_group_exprs_mutator((Node *) agg->aggdirectargs, context); + + return (Node *) agg; + } + + /* + * We can skip recursing into aggregates of higher levels altogether, + * since they could not possibly contain Vars of concern to us (see + * transformAggregateCall). We do need to look at aggregates of lower + * levels, however. + */ + if ((int) agg->agglevelsup > context->sublevels_up) + return node; + } + + if (IsA(node, GroupingFunc)) + { + GroupingFunc *grp = (GroupingFunc *) node; + + /* + * If we find a GroupingFunc node of the original or higher level, do + * not recurse into its arguments; there are no grouped vars there. + */ + if ((int) grp->agglevelsup >= context->sublevels_up) + return node; + } + + if (IsA(node, Query)) + { + /* Recurse into RTE subquery or not-yet-planned sublink subquery */ + Query *newnode; + bool save_inserted_sublink; + + context->sublevels_up++; + save_inserted_sublink = context->inserted_sublink; + context->inserted_sublink = ((Query *) node)->hasSubLinks; + newnode = query_tree_mutator((Query *) node, + flatten_group_exprs_mutator, + context, + QTW_IGNORE_GROUPEXPRS); + newnode->hasSubLinks |= context->inserted_sublink; + context->inserted_sublink = save_inserted_sublink; + context->sublevels_up--; + return (Node *) newnode; + } + + return expression_tree_mutator(node, flatten_group_exprs_mutator, + context); +} + +/* + * Add oldvar's varnullingrels, if any, to a flattened grouping expression. + * The newnode has been copied, so we can modify it freely. + */ +static Node * +mark_nullable_by_grouping(PlannerInfo *root, Node *newnode, Var *oldvar) +{ + Relids relids; + + if (root == NULL) + return newnode; + if (oldvar->varnullingrels == NULL) + return newnode; /* nothing to do */ + + Assert(bms_equal(oldvar->varnullingrels, + bms_make_singleton(root->group_rtindex))); + + relids = pull_varnos_of_level(root, newnode, oldvar->varlevelsup); + + if (!bms_is_empty(relids)) + { + /* + * If the newnode is not variable-free, we set the nullingrels of Vars + * or PHVs that are contained in the expression. This is not really + * 'correct' in theory, because it is the whole expression that can be + * nullable by grouping sets, not its individual vars. But it works + * in practice, because what we need is that the expression can be + * somehow distinguished from the same expression in ECs, and marking + * its vars is sufficient for this purpose. + */ + newnode = add_nulling_relids(newnode, + relids, + oldvar->varnullingrels); + } + else /* variable-free? */ + { + /* + * If the newnode is variable-free and does not contain volatile + * functions or set-returning functions, it can be treated as a member + * of EC that is redundant. So wrap it in a new PlaceHolderVar to + * carry the nullingrels. Otherwise we do not bother to make any + * changes. + * + * Aggregate functions and window functions are not allowed in + * grouping expressions. + */ + Assert(!contain_agg_clause(newnode)); + Assert(!contain_window_function(newnode)); + + if (!contain_volatile_functions(newnode) && + !expression_returns_set(newnode)) + { + PlaceHolderVar *newphv; + Relids phrels; + + phrels = get_relids_in_jointree((Node *) root->parse->jointree, + true, false); + Assert(!bms_is_empty(phrels)); + + newphv = make_placeholder_expr(root, (Expr *) newnode, phrels); + /* newphv has zero phlevelsup and NULL phnullingrels; fix it */ + newphv->phlevelsup = oldvar->varlevelsup; + newphv->phnullingrels = bms_copy(oldvar->varnullingrels); + newnode = (Node *) newphv; + } + } + + return newnode; } /* diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile index 3162a01f302d4..8c0fe28d63f59 100644 --- a/src/backend/parser/Makefile +++ b/src/backend/parser/Makefile @@ -59,7 +59,6 @@ gram.c: BISON_CHECK_CMD = $(PERL) $(srcdir)/check_keywords.pl $< $(top_srcdir)/s scan.c: FLEXFLAGS = -CF -p -p scan.c: FLEX_NO_BACKUP=yes -scan.c: FLEX_FIX_WARNING=yes # Force these dependencies to be known even without dependency info built: diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 28fed9d87f6bc..34f7c17f576ef 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -14,7 +14,7 @@ * contain optimizable statements, which we should transform. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/parser/analyze.c @@ -50,6 +50,7 @@ #include "parser/parsetree.h" #include "utils/backend_status.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -84,7 +85,7 @@ static Query *transformCallStmt(ParseState *pstate, CallStmt *stmt); static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown); -#ifdef RAW_EXPRESSION_COVERAGE_TEST +#ifdef DEBUG_NODE_TESTS_ENABLED static bool test_raw_expression_coverage(Node *node, void *context); #endif @@ -312,25 +313,30 @@ transformStmt(ParseState *pstate, Node *parseTree) { Query *result; +#ifdef DEBUG_NODE_TESTS_ENABLED + /* - * We apply RAW_EXPRESSION_COVERAGE_TEST testing to basic DML statements; - * we can't just run it on everything because raw_expression_tree_walker() - * doesn't claim to handle utility statements. + * We apply debug_raw_expression_coverage_test testing to basic DML + * statements; we can't just run it on everything because + * raw_expression_tree_walker() doesn't claim to handle utility + * statements. */ -#ifdef RAW_EXPRESSION_COVERAGE_TEST - switch (nodeTag(parseTree)) + if (Debug_raw_expression_coverage_test) { - case T_SelectStmt: - case T_InsertStmt: - case T_UpdateStmt: - case T_DeleteStmt: - case T_MergeStmt: - (void) test_raw_expression_coverage(parseTree, NULL); - break; - default: - break; + switch (nodeTag(parseTree)) + { + case T_SelectStmt: + case T_InsertStmt: + case T_UpdateStmt: + case T_DeleteStmt: + case T_MergeStmt: + (void) test_raw_expression_coverage(parseTree, NULL); + break; + default: + break; + } } -#endif /* RAW_EXPRESSION_COVERAGE_TEST */ +#endif /* DEBUG_NODE_TESTS_ENABLED */ /* * Caution: when changing the set of statement types that have non-default @@ -500,6 +506,45 @@ analyze_requires_snapshot(RawStmt *parseTree) return stmt_requires_parse_analysis(parseTree); } +/* + * query_requires_rewrite_plan() + * Returns true if rewriting or planning is non-trivial for this Query. + * + * This is much like stmt_requires_parse_analysis(), but applies one step + * further down the pipeline. + * + * We do not provide an equivalent of analyze_requires_snapshot(): callers + * can assume that any rewriting or planning activity needs a snapshot. + */ +bool +query_requires_rewrite_plan(Query *query) +{ + bool result; + + if (query->commandType != CMD_UTILITY) + { + /* All optimizable statements require rewriting/planning */ + result = true; + } + else + { + /* This list should match stmt_requires_parse_analysis() */ + switch (nodeTag(query->utilityStmt)) + { + case T_DeclareCursorStmt: + case T_ExplainStmt: + case T_CreateTableAsStmt: + case T_CallStmt: + result = true; + break; + default: + result = false; + break; + } + } + return result; +} + /* * transformDeleteStmt - * transforms a Delete Statement @@ -550,8 +595,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) qual = transformWhereClause(pstate, stmt->whereClause, EXPR_KIND_WHERE, "WHERE"); - qry->returningList = transformReturningList(pstate, stmt->returningList, - EXPR_KIND_RETURNING); + transformReturningClause(pstate, qry, stmt->returningClause, + EXPR_KIND_RETURNING); /* done building the range table and jointree */ qry->rtable = pstate->p_rtable; @@ -963,7 +1008,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) * contain only the target relation, removing any entries added in a * sub-SELECT or VALUES list. */ - if (stmt->onConflictClause || stmt->returningList) + if (stmt->onConflictClause || stmt->returningClause) { pstate->p_namespace = NIL; addNSItemToQuery(pstate, pstate->p_target_nsitem, @@ -976,10 +1021,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) stmt->onConflictClause); /* Process RETURNING, if any. */ - if (stmt->returningList) - qry->returningList = transformReturningList(pstate, - stmt->returningList, - EXPR_KIND_RETURNING); + if (stmt->returningClause) + transformReturningClause(pstate, qry, stmt->returningClause, + EXPR_KIND_RETURNING); /* done building the range table and jointree */ qry->rtable = pstate->p_rtable; @@ -1596,7 +1640,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) Node *col = (Node *) lfirst(lc); col = coerce_to_common_type(pstate, col, coltype, "VALUES"); - lfirst(lc) = (void *) col; + lfirst(lc) = col; } coltypmod = select_common_typmod(pstate, colexprs[i], coltype); @@ -1979,6 +2023,7 @@ makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash) grpcl->tleSortGroupRef = 0; grpcl->eqop = eqop; grpcl->sortop = sortop; + grpcl->reverse_sort = false; /* Sort-op is "less than", or InvalidOid */ grpcl->nulls_first = false; /* OK with or without sortop */ grpcl->hashable = hashable; @@ -2456,8 +2501,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) qual = transformWhereClause(pstate, stmt->whereClause, EXPR_KIND_WHERE, "WHERE"); - qry->returningList = transformReturningList(pstate, stmt->returningList, - EXPR_KIND_RETURNING); + transformReturningClause(pstate, qry, stmt->returningClause, + EXPR_KIND_RETURNING); /* * Now we are done with SELECT-like processing, and can get on with @@ -2553,18 +2598,120 @@ transformUpdateTargetList(ParseState *pstate, List *origTlist) } /* - * transformReturningList - + * addNSItemForReturning - + * add a ParseNamespaceItem for the OLD or NEW alias in RETURNING. + */ +static void +addNSItemForReturning(ParseState *pstate, const char *aliasname, + VarReturningType returning_type) +{ + List *colnames; + int numattrs; + ParseNamespaceColumn *nscolumns; + ParseNamespaceItem *nsitem; + + /* copy per-column data from the target relation */ + colnames = pstate->p_target_nsitem->p_rte->eref->colnames; + numattrs = list_length(colnames); + + nscolumns = (ParseNamespaceColumn *) + palloc(numattrs * sizeof(ParseNamespaceColumn)); + + memcpy(nscolumns, pstate->p_target_nsitem->p_nscolumns, + numattrs * sizeof(ParseNamespaceColumn)); + + /* mark all columns as returning OLD/NEW */ + for (int i = 0; i < numattrs; i++) + nscolumns[i].p_varreturningtype = returning_type; + + /* build the nsitem, copying most fields from the target relation */ + nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem)); + nsitem->p_names = makeAlias(aliasname, colnames); + nsitem->p_rte = pstate->p_target_nsitem->p_rte; + nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex; + nsitem->p_perminfo = pstate->p_target_nsitem->p_perminfo; + nsitem->p_nscolumns = nscolumns; + nsitem->p_returning_type = returning_type; + + /* add it to the query namespace as a table-only item */ + addNSItemToQuery(pstate, nsitem, false, true, false); +} + +/* + * transformReturningClause - * handle a RETURNING clause in INSERT/UPDATE/DELETE/MERGE */ -List * -transformReturningList(ParseState *pstate, List *returningList, - ParseExprKind exprKind) +void +transformReturningClause(ParseState *pstate, Query *qry, + ReturningClause *returningClause, + ParseExprKind exprKind) { - List *rlist; + int save_nslen = list_length(pstate->p_namespace); int save_next_resno; - if (returningList == NIL) - return NIL; /* nothing to do */ + if (returningClause == NULL) + return; /* nothing to do */ + + /* + * Scan RETURNING WITH(...) options for OLD/NEW alias names. Complain if + * there is any conflict with existing relations. + */ + foreach_node(ReturningOption, option, returningClause->options) + { + switch (option->option) + { + case RETURNING_OPTION_OLD: + if (qry->returningOldAlias != NULL) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + /* translator: %s is OLD or NEW */ + errmsg("%s cannot be specified multiple times", "OLD"), + parser_errposition(pstate, option->location)); + qry->returningOldAlias = option->value; + break; + + case RETURNING_OPTION_NEW: + if (qry->returningNewAlias != NULL) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + /* translator: %s is OLD or NEW */ + errmsg("%s cannot be specified multiple times", "NEW"), + parser_errposition(pstate, option->location)); + qry->returningNewAlias = option->value; + break; + + default: + elog(ERROR, "unrecognized returning option: %d", option->option); + } + + if (refnameNamespaceItem(pstate, NULL, option->value, -1, NULL) != NULL) + ereport(ERROR, + errcode(ERRCODE_DUPLICATE_ALIAS), + errmsg("table name \"%s\" specified more than once", + option->value), + parser_errposition(pstate, option->location)); + + addNSItemForReturning(pstate, option->value, + option->option == RETURNING_OPTION_OLD ? + VAR_RETURNING_OLD : VAR_RETURNING_NEW); + } + + /* + * If OLD/NEW alias names weren't explicitly specified, use "old"/"new" + * unless masked by existing relations. + */ + if (qry->returningOldAlias == NULL && + refnameNamespaceItem(pstate, NULL, "old", -1, NULL) == NULL) + { + qry->returningOldAlias = "old"; + addNSItemForReturning(pstate, "old", VAR_RETURNING_OLD); + } + if (qry->returningNewAlias == NULL && + refnameNamespaceItem(pstate, NULL, "new", -1, NULL) == NULL) + { + qry->returningNewAlias = "new"; + addNSItemForReturning(pstate, "new", VAR_RETURNING_NEW); + } /* * We need to assign resnos starting at one in the RETURNING list. Save @@ -2574,8 +2721,10 @@ transformReturningList(ParseState *pstate, List *returningList, save_next_resno = pstate->p_next_resno; pstate->p_next_resno = 1; - /* transform RETURNING identically to a SELECT targetlist */ - rlist = transformTargetList(pstate, returningList, exprKind); + /* transform RETURNING expressions identically to a SELECT targetlist */ + qry->returningList = transformTargetList(pstate, + returningClause->exprs, + exprKind); /* * Complain if the nonempty tlist expanded to nothing (which is possible @@ -2583,24 +2732,23 @@ transformReturningList(ParseState *pstate, List *returningList, * allow this, the parsed Query will look like it didn't have RETURNING, * with results that would probably surprise the user. */ - if (rlist == NIL) + if (qry->returningList == NIL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("RETURNING must have at least one column"), parser_errposition(pstate, - exprLocation(linitial(returningList))))); + exprLocation(linitial(returningClause->exprs))))); /* mark column origins */ - markTargetListOrigins(pstate, rlist); + markTargetListOrigins(pstate, qry->returningList); /* resolve any still-unresolved output columns as being type text */ if (pstate->p_resolve_unknowns) - resolveTargetListUnknowns(pstate, rlist); + resolveTargetListUnknowns(pstate, qry->returningList); /* restore state */ + pstate->p_namespace = list_truncate(pstate->p_namespace, save_nslen); pstate->p_next_resno = save_next_resno; - - return rlist; } @@ -3070,7 +3218,7 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt) * in the IntoClause because that's where intorel_startup() can * conveniently get it from. */ - stmt->into->viewQuery = (Node *) copyObject(query); + stmt->into->viewQuery = copyObject(query); } /* represent the command as a utility Query */ @@ -3575,6 +3723,7 @@ applyLockingClause(Query *qry, Index rtindex, qry->rowMarks = lappend(qry->rowMarks, rc); } +#ifdef DEBUG_NODE_TESTS_ENABLED /* * Coverage testing for raw_expression_tree_walker(). * @@ -3583,8 +3732,6 @@ applyLockingClause(Query *qry, Index rtindex, * applied in limited cases involving CTEs, and we don't really want to have * to test everything inside as well as outside a CTE. */ -#ifdef RAW_EXPRESSION_COVERAGE_TEST - static bool test_raw_expression_coverage(Node *node, void *context) { @@ -3594,5 +3741,4 @@ test_raw_expression_coverage(Node *node, void *context) test_raw_expression_coverage, context); } - -#endif /* RAW_EXPRESSION_COVERAGE_TEST */ +#endif /* DEBUG_NODE_TESTS_ENABLED */ diff --git a/src/backend/parser/check_keywords.pl b/src/backend/parser/check_keywords.pl index 3542e8d1eb644..2f25b2a1071ec 100644 --- a/src/backend/parser/check_keywords.pl +++ b/src/backend/parser/check_keywords.pl @@ -4,7 +4,7 @@ # Usage: check_keywords.pl gram.y kwlist.h # src/backend/parser/check_keywords.pl -# Copyright (c) 2009-2024, PostgreSQL Global Development Group +# Copyright (c) 2009-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index a043fd4c669a8..50f53159d5819 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -6,7 +6,7 @@ * gram.y * POSTGRESQL BISON rules/actions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -48,7 +48,6 @@ #include #include -#include "access/tableam.h" #include "catalog/index.h" #include "catalog/namespace.h" #include "catalog/pg_am.h" @@ -59,47 +58,30 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "parser/parser.h" -#include "storage/lmgr.h" -#include "utils/date.h" #include "utils/datetime.h" -#include "utils/numeric.h" #include "utils/xml.h" /* - * Location tracking support --- simpler than bison's default, since we only - * want to track the start position not the end position of each nonterminal. + * Location tracking support. Unlike bison's default, we only want + * to track the start position not the end position of each nonterminal. + * Nonterminals that reduce to empty receive position "-1". Since a + * production's leading RHS nonterminal(s) may have reduced to empty, + * we have to scan to find the first one that's not -1. */ #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if ((N) > 0) \ - (Current) = (Rhs)[1]; \ - else \ - (Current) = (-1); \ + (Current) = (-1); \ + for (int _i = 1; _i <= (N); _i++) \ + { \ + if ((Rhs)[_i] >= 0) \ + { \ + (Current) = (Rhs)[_i]; \ + break; \ + } \ + } \ } while (0) -/* - * The above macro assigns -1 (unknown) as the parse location of any - * nonterminal that was reduced from an empty rule, or whose leftmost - * component was reduced from an empty rule. This is problematic - * for nonterminals defined like - * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ; - * because we'll set -1 as the location during the first reduction and then - * copy it during each subsequent reduction, leaving us with -1 for the - * location even when the list is not empty. To fix that, do this in the - * action for the nonempty rule(s): - * if (@$ < 0) @$ = @2; - * (Although we have many nonterminals that follow this pattern, we only - * bother with fixing @$ like this when the nonterminal's parse location - * is actually referenced in some rule.) - * - * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs - * locations until it's found one that's not -1. Then we'd get a correct - * location for any nonterminal that isn't entirely empty. But this way - * would add overhead to every rule reduction, and so far there's not been - * a compelling reason to pay that overhead. - */ - /* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents @@ -123,12 +105,15 @@ typedef struct ImportQual List *table_names; } ImportQual; -/* Private struct for the result of opt_select_limit production */ +/* Private struct for the result of select_limit & limit_clause productions */ typedef struct SelectLimit { Node *limitOffset; Node *limitCount; - LimitOption limitOption; + LimitOption limitOption; /* indicates presence of WITH TIES */ + ParseLoc offsetLoc; /* location of OFFSET token, if present */ + ParseLoc countLoc; /* location of LIMIT/FETCH token, if present */ + ParseLoc optionLoc; /* location of WITH TIES, if present */ } SelectLimit; /* Private struct for the result of group_clause production */ @@ -158,6 +143,8 @@ typedef struct KeyActions #define CAS_INITIALLY_DEFERRED 0x08 #define CAS_NOT_VALID 0x10 #define CAS_NO_INHERIT 0x20 +#define CAS_NOT_ENFORCED 0x40 +#define CAS_ENFORCED 0x80 #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) @@ -196,12 +183,12 @@ static void doNegateFloat(Float *v); static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location); static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location); static Node *makeNotExpr(Node *expr, int location); -static Node *makeAArrayExpr(List *elements, int location); +static Node *makeAArrayExpr(List *elements, int location, int end_location); static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location); static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location); -static List *mergeTableFuncParameters(List *func_args, List *columns); +static List *mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner); static TypeName *TableFuncTypeName(List *columns); static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); static RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location, @@ -210,9 +197,10 @@ static void SplitColQualList(List *qualList, List **constraintList, CollateClause **collClause, core_yyscan_t yyscanner); static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner); -static PartitionStrategy parsePartitionStrategy(char *strategy); + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner); +static PartitionStrategy parsePartitionStrategy(char *strategy, int location, + core_yyscan_t yyscanner); static void preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); @@ -269,7 +257,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); PartitionElem *partelem; PartitionSpec *partspec; PartitionBoundSpec *partboundspec; - SinglePartitionSpec *singlepartspec; RoleSpec *rolespec; PublicationObjSpec *publicationobjectspec; struct SelectLimit *selectlimit; @@ -279,6 +266,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; + ReturningClause *retclause; + ReturningOptionKind retoptionkind; } %type stmt toplevel_stmt schema_stmt routine_body_stmt @@ -448,7 +437,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); opclass_purpose opt_opfamily transaction_mode_list_or_empty OptTableFuncElementList TableFuncElementList opt_type_modifiers prep_type_clause - execute_param_clause using_clause returning_clause + execute_param_clause using_clause + returning_with_clause returning_options opt_enum_val_list enum_val_list table_func_column_list create_generic_options alter_generic_options relation_expr_list dostmt_opt_list @@ -457,6 +447,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); vacuum_relation_list opt_vacuum_relation_list drop_option_list pub_obj_list +%type returning_clause +%type returning_option +%type returning_option_kind %type opt_routine_body %type group_clause %type group_by_list @@ -495,7 +488,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type opt_instead %type opt_unique opt_verbose opt_full -%type opt_freeze opt_analyze opt_default opt_recheck +%type opt_freeze opt_analyze opt_default %type opt_binary copy_delimiter %type copy_from opt_program @@ -525,14 +518,15 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); SetResetClause FunctionSetResetClause %type TableElement TypedTableElement ConstraintElem DomainConstraintElem TableFuncElement -%type columnDef columnOptions +%type columnDef columnOptions optionalPeriodName %type def_elem reloption_elem old_aggr_elem operator_def_elem %type def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound - columnref in_expr having_clause func_table xmltable array_expr + columnref having_clause func_table xmltable array_expr OptWhereClause operator_def_arg +%type opt_column_and_period_list %type rowsfrom_item rowsfrom_list opt_col_def_list -%type opt_ordinality +%type opt_ordinality opt_without_overlaps %type ExclusionConstraintList ExclusionConstraintElem %type func_arg_list func_arg_list_opt %type func_arg_expr @@ -641,13 +635,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type opt_existing_window_name %type opt_if_not_exists %type opt_unique_null_treatment -%type generated_when override_kind +%type generated_when override_kind opt_virtual_or_stored %type PartitionSpec OptPartitionSpec %type part_elem %type part_params %type PartitionBoundSpec -%type SinglePartitionSpec -%type partitions_list %type hash_partbound %type hash_partbound_elem @@ -726,9 +718,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP - EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE - EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION - EXTENSION EXTERNAL EXTRACT + EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENFORCED ENUM_P ERROR_P + ESCAPE EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN + EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS @@ -759,18 +751,18 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC - OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR + OBJECT_P OBJECTS_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER - PARALLEL PARAMETER PARSER PARTIAL PARTITION PARTITIONS PASSING PASSWORD PATH - PLACING PLAN PLANS POLICY + PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH + PERIOD PLACING PLAN PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION QUOTE QUOTES - RANGE READ REAL REASSIGN RECHECK RECURSIVE REF_P REFERENCES REFERENCING + RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE @@ -778,7 +770,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW - SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SPLIT SOURCE SQL_P STABLE STANDALONE_P + SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SOURCE SQL_P STABLE STANDALONE_P START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRING_P STRIP_P SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P SYSTEM_USER @@ -791,7 +783,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); UNLISTEN UNLOGGED UNTIL UPDATE USER USING VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING - VERBOSE VERSION_P VIEW VIEWS VOLATILE + VERBOSE VERSION_P VIEW VIEWS VIRTUAL VOLATILE WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE @@ -932,7 +924,7 @@ parse_toplevel: | MODE_PLPGSQL_EXPR PLpgSQL_Expr { pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt($2, 0)); + list_make1(makeRawStmt($2, @2)); } | MODE_PLPGSQL_ASSIGN1 PLAssignStmt { @@ -940,7 +932,7 @@ parse_toplevel: n->nnames = 1; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN2 PLAssignStmt { @@ -948,7 +940,7 @@ parse_toplevel: n->nnames = 2; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN3 PLAssignStmt { @@ -956,19 +948,15 @@ parse_toplevel: n->nnames = 3; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } ; /* * At top level, we wrap each stmt with a RawStmt node carrying start location - * and length of the stmt's text. Notice that the start loc/len are driven - * entirely from semicolon locations (@2). It would seem natural to use - * @1 or @3 to get the true start location of a stmt, but that doesn't work - * for statements that can start with empty nonterminals (opt_with_clause is - * the main offender here); as noted in the comments for YYLLOC_DEFAULT, - * we'd get -1 for the location in such cases. - * We also take care to discard empty statements entirely. + * and length of the stmt's text. + * We also take care to discard empty statements entirely (which among other + * things dodges the problem of assigning them a location). */ stmtmulti: stmtmulti ';' toplevel_stmt { @@ -978,14 +966,14 @@ stmtmulti: stmtmulti ';' toplevel_stmt updateRawStmtEnd(llast_node(RawStmt, $1), @2); } if ($3 != NULL) - $$ = lappend($1, makeRawStmt($3, @2 + 1)); + $$ = lappend($1, makeRawStmt($3, @3)); else $$ = $1; } | toplevel_stmt { if ($1 != NULL) - $$ = list_make1(makeRawStmt($1, 0)); + $$ = list_make1(makeRawStmt($1, @1)); else $$ = NIL; } @@ -1586,8 +1574,6 @@ CreateSchemaStmt: OptSchemaEltList: OptSchemaEltList schema_stmt { - if (@$ < 0) /* see comments for YYLLOC_DEFAULT */ - @$ = @2; $$ = lappend($1, $2); } | /* EMPTY */ @@ -1649,6 +1635,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "TRANSACTION"; n->args = $2; + n->jumble_args = true; + n->location = -1; $$ = n; } | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list @@ -1658,6 +1646,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "SESSION CHARACTERISTICS"; n->args = $5; + n->jumble_args = true; + n->location = -1; $$ = n; } | set_rest_more @@ -1671,6 +1661,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name '=' var_list @@ -1680,6 +1671,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name TO DEFAULT @@ -1688,6 +1680,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } | var_name '=' DEFAULT @@ -1696,6 +1689,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } ; @@ -1708,6 +1702,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_CURRENT; n->name = $1; + n->location = -1; $$ = n; } /* Special syntaxes mandated by SQL standard: */ @@ -1717,6 +1712,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "timezone"; + n->location = -1; + n->jumble_args = true; if ($3 != NULL) n->args = list_make1($3); else @@ -1738,6 +1735,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "search_path"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | NAMES opt_encoding @@ -1746,6 +1744,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "client_encoding"; + n->location = @2; if ($2 != NULL) n->args = list_make1(makeStringConst($2, @2)); else @@ -1759,6 +1758,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "role"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | SESSION AUTHORIZATION NonReservedWord_or_Sconst @@ -1768,6 +1768,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "session_authorization"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } | SESSION AUTHORIZATION DEFAULT @@ -1776,6 +1777,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_DEFAULT; n->name = "session_authorization"; + n->location = -1; $$ = n; } | XML_P OPTION document_or_content @@ -1785,6 +1787,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "xmloption"; n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3)); + n->jumble_args = true; + n->location = -1; $$ = n; } /* Special syntaxes invented by PostgreSQL: */ @@ -1795,6 +1799,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_MULTI; n->name = "TRANSACTION SNAPSHOT"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } ; @@ -1902,6 +1907,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "timezone"; + n->location = -1; $$ = n; } | TRANSACTION ISOLATION LEVEL @@ -1910,6 +1916,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "transaction_isolation"; + n->location = -1; $$ = n; } | SESSION AUTHORIZATION @@ -1918,6 +1925,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "session_authorization"; + n->location = -1; $$ = n; } ; @@ -1929,6 +1937,7 @@ generic_reset: n->kind = VAR_RESET; n->name = $1; + n->location = -1; $$ = n; } | ALL @@ -1936,6 +1945,7 @@ generic_reset: VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET_ALL; + n->location = -1; $$ = n; } ; @@ -2311,23 +2321,6 @@ alter_table_cmds: | alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); } ; -partitions_list: - SinglePartitionSpec { $$ = list_make1($1); } - | partitions_list ',' SinglePartitionSpec { $$ = lappend($1, $3); } - ; - -SinglePartitionSpec: - PARTITION qualified_name PartitionBoundSpec - { - SinglePartitionSpec *n = makeNode(SinglePartitionSpec); - - n->name = $2; - n->bound = $3; - - $$ = n; - } - ; - partition_cmd: /* ALTER TABLE ATTACH PARTITION FOR VALUES */ ATTACH PARTITION qualified_name PartitionBoundSpec @@ -2338,7 +2331,6 @@ partition_cmd: n->subtype = AT_AttachPartition; cmd->name = $3; cmd->bound = $4; - cmd->partlist = NULL; cmd->concurrent = false; n->def = (Node *) cmd; @@ -2353,7 +2345,6 @@ partition_cmd: n->subtype = AT_DetachPartition; cmd->name = $3; cmd->bound = NULL; - cmd->partlist = NULL; cmd->concurrent = $4; n->def = (Node *) cmd; @@ -2367,35 +2358,6 @@ partition_cmd: n->subtype = AT_DetachPartitionFinalize; cmd->name = $3; cmd->bound = NULL; - cmd->partlist = NULL; - cmd->concurrent = false; - n->def = (Node *) cmd; - $$ = (Node *) n; - } - /* ALTER TABLE SPLIT PARTITION INTO () */ - | SPLIT PARTITION qualified_name INTO '(' partitions_list ')' - { - AlterTableCmd *n = makeNode(AlterTableCmd); - PartitionCmd *cmd = makeNode(PartitionCmd); - - n->subtype = AT_SplitPartition; - cmd->name = $3; - cmd->bound = NULL; - cmd->partlist = $6; - cmd->concurrent = false; - n->def = (Node *) cmd; - $$ = (Node *) n; - } - /* ALTER TABLE MERGE PARTITIONS () INTO */ - | MERGE PARTITIONS '(' qualified_name_list ')' INTO qualified_name - { - AlterTableCmd *n = makeNode(AlterTableCmd); - PartitionCmd *cmd = makeNode(PartitionCmd); - - n->subtype = AT_MergePartitions; - cmd->name = $7; - cmd->bound = NULL; - cmd->partlist = $4; cmd->concurrent = false; n->def = (Node *) cmd; $$ = (Node *) n; @@ -2412,7 +2374,6 @@ index_partition_cmd: n->subtype = AT_AttachPartition; cmd->name = $3; cmd->bound = NULL; - cmd->partlist = NULL; cmd->concurrent = false; n->def = (Node *) cmd; @@ -2695,16 +2656,39 @@ alter_table_cmd: | ALTER CONSTRAINT name ConstraintAttributeSpec { AlterTableCmd *n = makeNode(AlterTableCmd); - Constraint *c = makeNode(Constraint); + ATAlterConstraint *c = makeNode(ATAlterConstraint); n->subtype = AT_AlterConstraint; n->def = (Node *) c; - c->contype = CONSTR_FOREIGN; /* others not supported, yet */ c->conname = $3; - processCASbits($4, @4, "ALTER CONSTRAINT statement", + if ($4 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + c->alterEnforceability = true; + if ($4 & (CAS_DEFERRABLE | CAS_NOT_DEFERRABLE | + CAS_INITIALLY_DEFERRED | CAS_INITIALLY_IMMEDIATE)) + c->alterDeferrability = true; + if ($4 & CAS_NO_INHERIT) + c->alterInheritability = true; + processCASbits($4, @4, "FOREIGN KEY", &c->deferrable, &c->initdeferred, - NULL, NULL, yyscanner); + &c->is_enforced, + NULL, + &c->noinherit, + yyscanner); + $$ = (Node *) n; + } + /* ALTER TABLE ALTER CONSTRAINT INHERIT */ + | ALTER CONSTRAINT name INHERIT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + + n->subtype = AT_AlterConstraint; + n->def = (Node *) c; + c->conname = $3; + c->alterInheritability = true; + c->noinherit = false; + $$ = (Node *) n; } /* ALTER TABLE VALIDATE CONSTRAINT ... */ @@ -3195,11 +3179,13 @@ PartitionBoundSpec: if (n->modulus == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("modulus for hash partition must be specified"))); + errmsg("modulus for hash partition must be specified"), + parser_errposition(@3))); if (n->remainder == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("remainder for hash partition must be specified"))); + errmsg("remainder for hash partition must be specified"), + parser_errposition(@3))); n->location = @3; @@ -3951,12 +3937,16 @@ ColConstraint: * or be part of a_expr NOT LIKE or similar constructs). */ ColConstraintElem: - NOT NULL_P + NOT NULL_P opt_no_inherit { Constraint *n = makeNode(Constraint); n->contype = CONSTR_NOTNULL; n->location = @1; + n->is_no_inherit = $3; + n->is_enforced = true; + n->skip_validation = false; + n->initially_valid = true; $$ = (Node *) n; } | NULL_P @@ -4001,6 +3991,7 @@ ColConstraintElem: n->is_no_inherit = $5; n->raw_expr = $3; n->cooked_expr = NULL; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4025,7 +4016,7 @@ ColConstraintElem: n->location = @1; $$ = (Node *) n; } - | GENERATED generated_when AS '(' a_expr ')' STORED + | GENERATED generated_when AS '(' a_expr ')' opt_virtual_or_stored { Constraint *n = makeNode(Constraint); @@ -4033,6 +4024,7 @@ ColConstraintElem: n->generated_when = $2; n->raw_expr = $5; n->cooked_expr = NULL; + n->generated_kind = $7; n->location = @1; /* @@ -4062,6 +4054,7 @@ ColConstraintElem: n->fk_upd_action = ($5)->updateAction->action; n->fk_del_action = ($5)->deleteAction->action; n->fk_del_set_cols = ($5)->deleteAction->cols; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4079,6 +4072,12 @@ generated_when: | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; } ; +opt_virtual_or_stored: + STORED { $$ = ATTRIBUTE_GENERATED_STORED; } + | VIRTUAL { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + | /*EMPTY*/ { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + ; + /* * ConstraintAttr represents constraint attributes, which we parse as if * they were independent constraint clauses, in order to avoid shift/reduce @@ -4127,6 +4126,22 @@ ConstraintAttr: n->location = @1; $$ = (Node *) n; } + | ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } + | NOT ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_NOT_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } ; @@ -4188,12 +4203,25 @@ ConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, &n->is_enforced, &n->skip_validation, &n->is_no_inherit, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; } - | UNIQUE opt_unique_null_treatment '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | NOT NULL_P ColId ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_NOTNULL; + n->location = @1; + n->keys = list_make1(makeString($3)); + processCASbits($4, @4, "NOT NULL", + NULL, NULL, NULL, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *) n; + } + | UNIQUE opt_unique_null_treatment '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4202,13 +4230,14 @@ ConstraintElem: n->location = @1; n->nulls_not_distinct = !$2; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "UNIQUE", + n->indexspace = $9; + processCASbits($10, @10, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | UNIQUE ExistingIndex ConstraintAttributeSpec @@ -4224,10 +4253,10 @@ ConstraintElem: n->indexspace = NULL; processCASbits($3, @3, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | PRIMARY KEY '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | PRIMARY KEY '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4235,13 +4264,14 @@ ConstraintElem: n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "PRIMARY KEY", + n->indexspace = $9; + processCASbits($10, @10, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | PRIMARY KEY ExistingIndex ConstraintAttributeSpec @@ -4257,7 +4287,7 @@ ConstraintElem: n->indexspace = NULL; processCASbits($4, @4, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | EXCLUDE access_method_clause '(' ExclusionConstraintList ')' @@ -4277,26 +4307,36 @@ ConstraintElem: n->where_clause = $9; processCASbits($10, @10, "EXCLUDE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name - opt_column_list key_match key_actions ConstraintAttributeSpec + | FOREIGN KEY '(' columnList optionalPeriodName ')' REFERENCES qualified_name + opt_column_and_period_list key_match key_actions ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_FOREIGN; n->location = @1; - n->pktable = $7; + n->pktable = $8; n->fk_attrs = $4; - n->pk_attrs = $8; - n->fk_matchtype = $9; - n->fk_upd_action = ($10)->updateAction->action; - n->fk_del_action = ($10)->deleteAction->action; - n->fk_del_set_cols = ($10)->deleteAction->cols; - processCASbits($11, @11, "FOREIGN KEY", + if ($5) + { + n->fk_attrs = lappend(n->fk_attrs, $5); + n->fk_with_period = true; + } + n->pk_attrs = linitial($9); + if (lsecond($9)) + { + n->pk_attrs = lappend(n->pk_attrs, lsecond($9)); + n->pk_with_period = true; + } + n->fk_matchtype = $10; + n->fk_upd_action = ($11)->updateAction->action; + n->fk_del_action = ($11)->deleteAction->action; + n->fk_del_set_cols = ($11)->deleteAction->cols; + processCASbits($12, @12, "FOREIGN KEY", &n->deferrable, &n->initdeferred, - &n->skip_validation, NULL, + &n->is_enforced, &n->skip_validation, NULL, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; @@ -4336,8 +4376,9 @@ DomainConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); + n->is_enforced = true; n->initially_valid = !n->skip_validation; $$ = (Node *) n; } @@ -4348,10 +4389,10 @@ DomainConstraintElem: n->contype = CONSTR_NOTNULL; n->location = @1; n->keys = list_make1(makeString("value")); - /* no NOT VALID support yet */ + /* no NOT VALID, NO INHERIT support */ processCASbits($3, @3, "NOT NULL", NULL, NULL, NULL, - &n->is_no_inherit, yyscanner); + NULL, NULL, yyscanner); n->initially_valid = true; $$ = (Node *) n; } @@ -4361,6 +4402,11 @@ opt_no_inherit: NO INHERIT { $$ = true; } | /* EMPTY */ { $$ = false; } ; +opt_without_overlaps: + WITHOUT OVERLAPS { $$ = true; } + | /*EMPTY*/ { $$ = false; } + ; + opt_column_list: '(' columnList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } @@ -4371,6 +4417,16 @@ columnList: | columnList ',' columnElem { $$ = lappend($1, $3); } ; +optionalPeriodName: + ',' PERIOD columnElem { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_column_and_period_list: + '(' columnList optionalPeriodName ')' { $$ = list_make2($2, $3); } + | /*EMPTY*/ { $$ = list_make2(NIL, NULL); } + ; + columnElem: ColId { $$ = (Node *) makeString($1); @@ -4550,7 +4606,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')' { PartitionSpec *n = makeNode(PartitionSpec); - n->strategy = parsePartitionStrategy($3); + n->strategy = parsePartitionStrategy($3, @3, yyscanner); n->partParams = $5; n->location = @1; @@ -4960,6 +5016,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("increment", (Node *) $3, @1); } + | LOGGED + { + $$ = makeDefElem("logged", NULL, @1); + } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); @@ -4982,7 +5042,6 @@ SeqOptElem: AS SimpleTypename } | SEQUENCE NAME_P any_name { - /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly @@ -4997,6 +5056,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("restart", (Node *) $3, @1); } + | UNLOGGED + { + $$ = makeDefElem("unlogged", NULL, @1); + } ; opt_by: BY @@ -5977,7 +6040,8 @@ CreateTrigStmt: if (n->replace) /* not supported, see CreateTrigger */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"))); + errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"), + parser_errposition(@1))); n->isconstraint = true; n->trigname = $5; n->relation = $9; @@ -5991,7 +6055,7 @@ CreateTrigStmt: n->transitionRels = NIL; processCASbits($11, @11, "TRIGGER", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); n->constrrel = $10; $$ = (Node *) n; } @@ -6160,7 +6224,8 @@ ConstraintAttributeSpec: parser_errposition(@2))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || - (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) + (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED) || + (newspec & (CAS_NOT_ENFORCED | CAS_ENFORCED)) == (CAS_NOT_ENFORCED | CAS_ENFORCED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), @@ -6176,6 +6241,8 @@ ConstraintAttributeElem: | INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; } | NOT VALID { $$ = CAS_NOT_VALID; } | NO INHERIT { $$ = CAS_NO_INHERIT; } + | NOT ENFORCED { $$ = CAS_NOT_ENFORCED; } + | ENFORCED { $$ = CAS_ENFORCED; } ; @@ -6262,7 +6329,8 @@ CreateAssertionStmt: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE ASSERTION is not yet implemented"))); + errmsg("CREATE ASSERTION is not yet implemented"), + parser_errposition(@1))); $$ = NULL; } @@ -6622,7 +6690,7 @@ opclass_item_list: ; opclass_item: - OPERATOR Iconst any_operator opclass_purpose opt_recheck + OPERATOR Iconst any_operator opclass_purpose { CreateOpClassItem *n = makeNode(CreateOpClassItem); ObjectWithArgs *owa = makeNode(ObjectWithArgs); @@ -6636,7 +6704,6 @@ opclass_item: $$ = (Node *) n; } | OPERATOR Iconst operator_with_argtypes opclass_purpose - opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); @@ -6688,23 +6755,6 @@ opclass_purpose: FOR SEARCH { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; } ; -opt_recheck: RECHECK - { - /* - * RECHECK no longer does anything in opclass definitions, - * but we still accept it to ease porting of old database - * dumps. - */ - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("RECHECK is no longer required"), - errhint("Update your data type."), - parser_errposition(@1))); - $$ = true; - } - | /*EMPTY*/ { $$ = false; } - ; - CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING name @@ -8124,6 +8174,7 @@ defacl_privilege_target: | SEQUENCES { $$ = OBJECT_SEQUENCE; } | TYPES_P { $$ = OBJECT_TYPE; } | SCHEMAS { $$ = OBJECT_SCHEMA; } + | LARGE_P OBJECTS_P { $$ = OBJECT_LARGEOBJECT; } ; @@ -8323,7 +8374,7 @@ CreateFunctionStmt: n->is_procedure = false; n->replace = $2; n->funcname = $4; - n->parameters = mergeTableFuncParameters($5, $9); + n->parameters = mergeTableFuncParameters($5, $9, yyscanner); n->returnType = TableFuncTypeName($9); n->returnType->location = @7; n->options = $11; @@ -8456,6 +8507,7 @@ func_arg: n->argType = $3; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name arg_class func_type @@ -8466,6 +8518,7 @@ func_arg: n->argType = $3; n->mode = $2; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name func_type @@ -8476,6 +8529,7 @@ func_arg: n->argType = $2; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } | arg_class func_type @@ -8486,6 +8540,7 @@ func_arg: n->argType = $2; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | func_type @@ -8496,6 +8551,7 @@ func_arg: n->argType = $1; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -8832,6 +8888,7 @@ table_func_column: param_name func_type n->argType = $2; n->mode = FUNC_PARAM_TABLE; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -11956,7 +12013,7 @@ opt_name_list: ; vacuum_relation: - qualified_name opt_name_list + relation_expr opt_name_list { $$ = (Node *) makeVacuumRelation($1, InvalidOid, $2); } @@ -12179,7 +12236,7 @@ InsertStmt: { $5->relation = $4; $5->onConflictClause = $6; - $5->returningList = $7; + $5->returningClause = $7; $5->withClause = $1; $$ = (Node *) $5; } @@ -12312,8 +12369,45 @@ opt_conf_expr: ; returning_clause: - RETURNING target_list { $$ = $2; } - | /* EMPTY */ { $$ = NIL; } + RETURNING returning_with_clause target_list + { + ReturningClause *n = makeNode(ReturningClause); + + n->options = $2; + n->exprs = $3; + $$ = n; + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +returning_with_clause: + WITH '(' returning_options ')' { $$ = $3; } + | /* EMPTY */ { $$ = NIL; } + ; + +returning_options: + returning_option { $$ = list_make1($1); } + | returning_options ',' returning_option { $$ = lappend($1, $3); } + ; + +returning_option: + returning_option_kind AS ColId + { + ReturningOption *n = makeNode(ReturningOption); + + n->option = $1; + n->value = $3; + n->location = @1; + $$ = (Node *) n; + } + ; + +returning_option_kind: + OLD { $$ = RETURNING_OPTION_OLD; } + | NEW { $$ = RETURNING_OPTION_NEW; } ; @@ -12332,7 +12426,7 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias n->relation = $4; n->usingClause = $5; n->whereClause = $6; - n->returningList = $7; + n->returningClause = $7; n->withClause = $1; $$ = (Node *) n; } @@ -12406,7 +12500,7 @@ UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = $5; n->fromClause = $6; n->whereClause = $7; - n->returningList = $8; + n->returningClause = $8; n->withClause = $1; $$ = (Node *) n; } @@ -12484,7 +12578,7 @@ MergeStmt: m->sourceRelation = $6; m->joinCondition = $8; m->mergeWhenClauses = $9; - m->returningList = $10; + m->returningClause = $10; $$ = (Node *) m; } @@ -13163,11 +13257,13 @@ select_limit: { $$ = $1; ($$)->limitOffset = $2; + ($$)->offsetLoc = @2; } | offset_clause limit_clause { $$ = $2; ($$)->limitOffset = $1; + ($$)->offsetLoc = @1; } | limit_clause { @@ -13180,6 +13276,9 @@ select_limit: n->limitOffset = $1; n->limitCount = NULL; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = @1; + n->countLoc = -1; + n->optionLoc = -1; $$ = n; } ; @@ -13197,6 +13296,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $2; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | LIMIT select_limit_value ',' select_offset_value @@ -13222,6 +13324,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES @@ -13231,6 +13336,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @5; $$ = n; } | FETCH first_or_next row_or_rows ONLY @@ -13240,6 +13348,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next row_or_rows WITH TIES @@ -13249,6 +13360,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @4; $$ = n; } ; @@ -14093,7 +14207,7 @@ xmltable_column_el: parser_errposition(defel->location))); fc->colexpr = defel->arg; } - else if (strcmp(defel->defname, "is_not_null") == 0) + else if (strcmp(defel->defname, "__pg__is_not_null") == 0) { if (nullability_seen) ereport(ERROR, @@ -14136,13 +14250,20 @@ xmltable_column_option_list: xmltable_column_option_el: IDENT b_expr - { $$ = makeDefElem($1, $2, @1); } + { + if (strcmp($1, "__pg__is_not_null") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option name \"%s\" cannot be used in XMLTABLE", $1), + parser_errposition(@1))); + $$ = makeDefElem($1, $2, @1); + } | DEFAULT b_expr { $$ = makeDefElem("default", $2, @1); } | NOT NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); } | PATH b_expr { $$ = makeDefElem("path", $2, @1); } ; @@ -15143,49 +15264,50 @@ a_expr: c_expr { $$ = $1; } (Node *) list_make2($5, $7), @2); } - | a_expr IN_P in_expr + | a_expr IN_P select_with_parens { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($3, SubLink)) - { - /* generate foo = ANY (subquery) */ - SubLink *n = (SubLink *) $3; + /* generate foo = ANY (subquery) */ + SubLink *n = makeNode(SubLink); - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - $$ = (Node *) n; - } - else - { - /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); - } + n->subselect = $3; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + $$ = (Node *) n; } - | a_expr NOT_LA IN_P in_expr %prec NOT_LA + | a_expr IN_P '(' expr_list ')' { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) - { - /* generate NOT (foo = ANY (subquery)) */ - /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; - - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - /* Stick a NOT on top; must have same parse location */ - $$ = makeNotExpr((Node *) n, @2); - } - else - { - /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); - } + /* generate scalar IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "=", $1, (Node *) $4, @2); + + n->rexpr_list_start = @3; + n->rexpr_list_end = @5; + $$ = (Node *) n; + } + | a_expr NOT_LA IN_P select_with_parens %prec NOT_LA + { + /* generate NOT (foo = ANY (subquery)) */ + SubLink *n = makeNode(SubLink); + + n->subselect = $4; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + /* Stick a NOT on top; must have same parse location */ + $$ = makeNotExpr((Node *) n, @2); + } + | a_expr NOT_LA IN_P '(' expr_list ')' + { + /* generate scalar NOT IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "<>", $1, (Node *) $5, @2); + + n->rexpr_list_start = @4; + n->rexpr_list_end = @6; + $$ = (Node *) n; } | a_expr subquery_Op sub_type select_with_parens %prec Op { @@ -16620,15 +16742,15 @@ type_list: Typename { $$ = list_make1($1); } array_expr: '[' expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' array_expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' ']' { - $$ = makeAArrayExpr(NIL, @1); + $$ = makeAArrayExpr(NIL, @1, @2); } ; @@ -16750,17 +16872,6 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } | expr_list { $$ = $1; } ; -in_expr: select_with_parens - { - SubLink *n = makeNode(SubLink); - - n->subselect = $1; - /* other fields will be filled later */ - $$ = (Node *) n; - } - | '(' expr_list ')' { $$ = (Node *) $2; } - ; - /* * Define SQL-style CASE clause. * - Full specification @@ -16960,8 +17071,9 @@ json_format_clause: encoding = JS_ENC_UTF32; else ereport(ERROR, - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized JSON encoding: %s", $4)); + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized JSON encoding: %s", $4), + parser_errposition(@4))); $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, encoding, @1); } @@ -17463,7 +17575,8 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list $9->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition($9->optionLoc))); n->limitOption = $9->limitOption; } n->lockingClause = $10; @@ -17647,6 +17760,7 @@ unreserved_keyword: | ENABLE_P | ENCODING | ENCRYPTED + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -17742,6 +17856,7 @@ unreserved_keyword: | NOWAIT | NULLS_P | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -17761,10 +17876,10 @@ unreserved_keyword: | PARSER | PARTIAL | PARTITION - | PARTITIONS | PASSING | PASSWORD | PATH + | PERIOD | PLAN | PLANS | POLICY @@ -17784,7 +17899,6 @@ unreserved_keyword: | RANGE | READ | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCING @@ -17830,7 +17944,6 @@ unreserved_keyword: | SKIP | SNAPSHOT | SOURCE - | SPLIT | SQL_P | STABLE | STANDALONE_P @@ -17882,6 +17995,7 @@ unreserved_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHITESPACE_P | WITHIN @@ -18226,6 +18340,7 @@ bare_label_keyword: | ENCODING | ENCRYPTED | END_P + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -18364,6 +18479,7 @@ bare_label_keyword: | NULLS_P | NUMERIC | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -18387,10 +18503,10 @@ bare_label_keyword: | PARSER | PARTIAL | PARTITION - | PARTITIONS | PASSING | PASSWORD | PATH + | PERIOD | PLACING | PLAN | PLANS @@ -18414,7 +18530,6 @@ bare_label_keyword: | READ | REAL | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCES @@ -18468,7 +18583,6 @@ bare_label_keyword: | SNAPSHOT | SOME | SOURCE - | SPLIT | SQL_P | STABLE | STANDALONE_P @@ -18538,6 +18652,7 @@ bare_label_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHEN | WHITESPACE_P @@ -18605,10 +18720,10 @@ makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner) { /* - * Generate a ColumnRef node, with an A_Indirection node added if there - * is any subscripting in the specified indirection list. However, - * any field selection at the start of the indirection list must be - * transposed into the "fields" part of the ColumnRef node. + * Generate a ColumnRef node, with an A_Indirection node added if there is + * any subscripting in the specified indirection list. However, any field + * selection at the start of the indirection list must be transposed into + * the "fields" part of the ColumnRef node. */ ColumnRef *c = makeNode(ColumnRef); int nfields = 0; @@ -18674,55 +18789,55 @@ makeStringConstCast(char *str, int location, TypeName *typename) static Node * makeIntConst(int val, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.ival.type = T_Integer; n->val.ival.ival = val; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeFloatConst(char *str, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.fval.type = T_Float; n->val.fval.fval = str; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeBoolAConst(bool state, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.boolval.type = T_Boolean; n->val.boolval.boolval = state; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeBitStringConst(char *str, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.bsval.type = T_BitString; n->val.bsval.bsval = str; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeNullAConst(int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->isnull = true; n->location = location; @@ -18811,7 +18926,7 @@ check_func_name(List *names, core_yyscan_t yyscanner) static List * check_indirection(List *indirection, core_yyscan_t yyscanner) { - ListCell *l; + ListCell *l; foreach(l, indirection) { @@ -18866,7 +18981,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, core_yyscan_t yyscanner) { FunctionParameter *lastd = (FunctionParameter *) llast(directargs); - Integer *ndirectargs; + Integer *ndirectargs; /* No restriction unless last direct arg is VARIADIC */ if (lastd->mode == FUNC_PARAM_VARIADIC) @@ -18874,8 +18989,8 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs); /* - * We ignore the names, though the aggr_arg production allows them; - * it doesn't allow default values, so those need not be checked. + * We ignore the names, though the aggr_arg production allows them; it + * doesn't allow default values, so those need not be checked. */ if (list_length(orderedargs) != 1 || firsto->mode != FUNC_PARAM_VARIADIC || @@ -18883,7 +18998,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"), - parser_errposition(exprLocation((Node *) firsto)))); + parser_errposition(firsto->location))); /* OK, drop the duplicate VARIADIC argument from the internal form */ orderedargs = NIL; @@ -18931,7 +19046,7 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple OFFSET clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitOffset)))); + parser_errposition(limitClause->offsetLoc))); stmt->limitOffset = limitClause->limitOffset; } if (limitClause && limitClause->limitCount) @@ -18940,19 +19055,18 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple LIMIT clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitCount)))); + parser_errposition(limitClause->countLoc))); stmt->limitCount = limitClause->limitCount; } if (limitClause) { - if (stmt->limitOption) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple limit options not allowed"))); + /* If there was a conflict, we must have detected it above */ + Assert(!stmt->limitOption); if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition(limitClause->optionLoc))); if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause) { ListCell *lc; @@ -18965,7 +19079,8 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s and %s options cannot be used together", - "SKIP LOCKED", "WITH TIES"))); + "SKIP LOCKED", "WITH TIES"), + parser_errposition(limitClause->optionLoc))); } } stmt->limitOption = limitClause->limitOption; @@ -19033,7 +19148,7 @@ doNegate(Node *n, int location) { if (IsA(n, A_Const)) { - A_Const *con = (A_Const *) n; + A_Const *con = (A_Const *) n; /* report the constant's location as that of the '-' sign */ con->location = location; @@ -19061,7 +19176,7 @@ doNegateFloat(Float *v) if (*oldval == '+') oldval++; if (*oldval == '-') - v->fval = oldval+1; /* just strip the '-' */ + v->fval = oldval + 1; /* just strip the '-' */ else v->fval = psprintf("-%s", oldval); } @@ -19107,12 +19222,14 @@ makeNotExpr(Node *expr, int location) } static Node * -makeAArrayExpr(List *elements, int location) +makeAArrayExpr(List *elements, int location, int location_end) { A_ArrayExpr *n = makeNode(A_ArrayExpr); n->elements = elements; n->location = location; + n->list_start = location; + n->list_end = location_end; return (Node *) n; } @@ -19132,10 +19249,11 @@ static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location) { - XmlExpr *x = makeNode(XmlExpr); + XmlExpr *x = makeNode(XmlExpr); x->op = op; x->name = name; + /* * named_args is a list of ResTarget; it'll be split apart into separate * expression and name lists in transformXmlExpr(). @@ -19145,7 +19263,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, x->args = args; /* xmloption, if relevant, must be filled in by caller */ /* type and typmod will be filled in during parse analysis */ - x->type = InvalidOid; /* marks the node as not analyzed */ + x->type = InvalidOid; /* marks the node as not analyzed */ x->location = location; return (Node *) x; } @@ -19154,7 +19272,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, * Merge the input and output parameters of a table function. */ static List * -mergeTableFuncParameters(List *func_args, List *columns) +mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner) { ListCell *lc; @@ -19168,7 +19286,8 @@ mergeTableFuncParameters(List *func_args, List *columns) p->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"))); + errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"), + parser_errposition(p->location))); } return list_concat(func_args, columns); @@ -19269,7 +19388,7 @@ makeRangeVarFromQualifiedName(char *name, List *namelist, int location, errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", NameListToString(lcons(makeString(name), namelist))), - parser_errposition(location)); + parser_errposition(location)); break; } @@ -19320,8 +19439,8 @@ SplitColQualList(List *qualList, */ static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner) + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner) { /* defaults */ if (deferrable) @@ -19330,6 +19449,8 @@ processCASbits(int cas_bits, int location, const char *constrType, *initdeferred = false; if (not_valid) *not_valid = false; + if (is_enforced) + *is_enforced = true; if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) { @@ -19338,7 +19459,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19351,7 +19472,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19364,7 +19485,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NOT VALID", constrType), parser_errposition(location))); @@ -19377,11 +19498,46 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NO INHERIT", constrType), parser_errposition(location))); } + + if (cas_bits & CAS_NOT_ENFORCED) + { + if (is_enforced) + *is_enforced = false; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NOT ENFORCED", + constrType), + parser_errposition(location))); + + /* + * NB: The validated status is irrelevant when the constraint is set to + * NOT ENFORCED, but for consistency, it should be set accordingly. + * This ensures that if the constraint is later changed to ENFORCED, it + * will automatically be in the correct NOT VALIDATED state. + */ + if (not_valid) + *not_valid = true; + } + + if (cas_bits & CAS_ENFORCED) + { + if (is_enforced) + *is_enforced = true; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked ENFORCED", + constrType), + parser_errposition(location))); + } } /* @@ -19389,7 +19545,7 @@ processCASbits(int cas_bits, int location, const char *constrType, * PartitionStrategy representation, or die trying. */ static PartitionStrategy -parsePartitionStrategy(char *strategy) +parsePartitionStrategy(char *strategy, int location, core_yyscan_t yyscanner) { if (pg_strcasecmp(strategy, "list") == 0) return PARTITION_STRATEGY_LIST; @@ -19400,9 +19556,9 @@ parsePartitionStrategy(char *strategy) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized partitioning strategy \"%s\"", - strategy))); - return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ + errmsg("unrecognized partitioning strategy \"%s\"", strategy), + parser_errposition(location))); + return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ } @@ -19473,8 +19629,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) parser_errposition(pubobj->location)); /* - * We can distinguish between the different type of schema - * objects based on whether name and pubtable is set. + * We can distinguish between the different type of schema objects + * based on whether name and pubtable is set. */ if (pubobj->name) pubobj->pubobjtype = PUBLICATIONOBJ_TABLES_IN_SCHEMA; @@ -19529,11 +19685,13 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) w->ctes = list_make1(cte); w->location = -1; - /* create target list for the new SELECT from the alias list of the - * recursive view specification */ - foreach (lc, aliases) + /* + * create target list for the new SELECT from the alias list of the + * recursive view specification + */ + foreach(lc, aliases) { - ResTarget *rt = makeNode(ResTarget); + ResTarget *rt = makeNode(ResTarget); rt->name = NULL; rt->indirection = NIL; @@ -19543,8 +19701,10 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) tl = lappend(tl, rt); } - /* create new SELECT combining WITH clause, target list, and fake FROM - * clause */ + /* + * create new SELECT combining WITH clause, target list, and fake FROM + * clause + */ s->withClause = w; s->targetList = tl; s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); diff --git a/src/backend/parser/gramparse.h b/src/backend/parser/gramparse.h index d85017fb22af0..a06a918c6541e 100644 --- a/src/backend/parser/gramparse.h +++ b/src/backend/parser/gramparse.h @@ -8,7 +8,7 @@ * Definitions that are needed outside the core parser should be in parser.h. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/parser/gramparse.h diff --git a/src/backend/parser/meson.build b/src/backend/parser/meson.build index 573d70b3d1b12..874aa749aa69a 100644 --- a/src/backend/parser/meson.build +++ b/src/backend/parser/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'analyze.c', @@ -30,7 +30,7 @@ parser_sources = files('parser.c') backend_scanner = custom_target('scan', input: 'scan.l', output: 'scan.c', - command: [flex_cmd, '--no-backup', '--fix-warnings', '--', '-CF', '-p', '-p'], + command: [flex_cmd, '--no-backup', '--', '-CF', '-p', '-p'], ) generated_sources += backend_scanner parser_sources += backend_scanner diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index bee7d8346a32e..0ac8966e30ff3 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -3,7 +3,7 @@ * parse_agg.c * handle aggregates and window functions in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,6 +26,7 @@ #include "parser/parse_clause.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" +#include "parser/parse_relation.h" #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" #include "utils/builtins.h" @@ -47,11 +48,12 @@ typedef struct bool hasJoinRTEs; List *groupClauses; List *groupClauseCommonVars; + List *gset_common; bool have_non_var_grouping; List **func_grouped_rels; int sublevels_up; bool in_agg_direct_args; -} check_ungrouped_columns_context; +} substitute_grouped_columns_context; static int check_agg_arguments(ParseState *pstate, List *directargs, @@ -59,17 +61,20 @@ static int check_agg_arguments(ParseState *pstate, Expr *filter); static bool check_agg_arguments_walker(Node *node, check_agg_arguments_context *context); -static void check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry, - List *groupClauses, List *groupClauseCommonVars, - bool have_non_var_grouping, - List **func_grouped_rels); -static bool check_ungrouped_columns_walker(Node *node, - check_ungrouped_columns_context *context); +static Node *substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry, + List *groupClauses, List *groupClauseCommonVars, + List *gset_common, + bool have_non_var_grouping, + List **func_grouped_rels); +static Node *substitute_grouped_columns_mutator(Node *node, + substitute_grouped_columns_context *context); static void finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry, List *groupClauses, bool hasJoinRTEs, bool have_non_var_grouping); static bool finalize_grouping_exprs_walker(Node *node, - check_ungrouped_columns_context *context); + substitute_grouped_columns_context *context); +static Var *buildGroupedVar(int attnum, Index ressortgroupref, + substitute_grouped_columns_context *context); static void check_agglevels_and_constraints(ParseState *pstate, Node *expr); static List *expand_groupingset_node(GroupingSet *gs); static Node *make_agg_arg(Oid argtype, Oid argcollation); @@ -376,8 +381,6 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr) break; case EXPR_KIND_FROM_SUBSELECT: - /* Should only be possible in a LATERAL subquery */ - Assert(pstate->p_lateral_active); /* * Aggregate/grouping scope rules make it worth being explicit @@ -796,7 +799,7 @@ check_agg_arguments_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, check_agg_arguments_walker, - (void *) context, + context, 0); context->sublevels_up--; return result; @@ -804,7 +807,7 @@ check_agg_arguments_walker(Node *node, return expression_tree_walker(node, check_agg_arguments_walker, - (void *) context); + context); } /* @@ -1066,7 +1069,9 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc, /* * parseCheckAggregates - * Check for aggregates where they shouldn't be and improper grouping. + * Check for aggregates where they shouldn't be and improper grouping, and + * replace grouped variables in the targetlist and HAVING clause with Vars + * that reference the RTE_GROUP RTE. * This function should be called after the target list and qualifications * are finalized. * @@ -1156,7 +1161,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry) /* * Build a list of the acceptable GROUP BY expressions for use by - * check_ungrouped_columns(). + * substitute_grouped_columns(). * * We get the TLE, not just the expr, because GROUPING wants to know the * sortgroupref. @@ -1209,7 +1214,24 @@ parseCheckAggregates(ParseState *pstate, Query *qry) } /* - * Check the targetlist and HAVING clause for ungrouped variables. + * If there are any acceptable GROUP BY expressions, build an RTE and + * nsitem for the result of the grouping step. + */ + if (groupClauses) + { + pstate->p_grouping_nsitem = + addRangeTableEntryForGroup(pstate, groupClauses); + + /* Set qry->rtable again in case it was previously NIL */ + qry->rtable = pstate->p_rtable; + /* Mark the Query as having RTE_GROUP RTE */ + qry->hasGroupRTE = true; + } + + /* + * Replace grouped variables in the targetlist and HAVING clause with Vars + * that reference the RTE_GROUP RTE. Emit an error message if we find any + * ungrouped variables. * * Note: because we check resjunk tlist elements as well as regular ones, * this will also find ungrouped variables that came from ORDER BY and @@ -1225,10 +1247,12 @@ parseCheckAggregates(ParseState *pstate, Query *qry) have_non_var_grouping); if (hasJoinRTEs) clause = flatten_join_alias_vars(NULL, qry, clause); - check_ungrouped_columns(clause, pstate, qry, - groupClauses, groupClauseCommonVars, - have_non_var_grouping, - &func_grouped_rels); + qry->targetList = (List *) + substitute_grouped_columns(clause, pstate, qry, + groupClauses, groupClauseCommonVars, + gset_common, + have_non_var_grouping, + &func_grouped_rels); clause = (Node *) qry->havingQual; finalize_grouping_exprs(clause, pstate, qry, @@ -1236,10 +1260,12 @@ parseCheckAggregates(ParseState *pstate, Query *qry) have_non_var_grouping); if (hasJoinRTEs) clause = flatten_join_alias_vars(NULL, qry, clause); - check_ungrouped_columns(clause, pstate, qry, - groupClauses, groupClauseCommonVars, - have_non_var_grouping, - &func_grouped_rels); + qry->havingQual = + substitute_grouped_columns(clause, pstate, qry, + groupClauses, groupClauseCommonVars, + gset_common, + have_non_var_grouping, + &func_grouped_rels); /* * Per spec, aggregates can't appear in a recursive term. @@ -1253,14 +1279,16 @@ parseCheckAggregates(ParseState *pstate, Query *qry) } /* - * check_ungrouped_columns - - * Scan the given expression tree for ungrouped variables (variables - * that are not listed in the groupClauses list and are not within - * the arguments of aggregate functions). Emit a suitable error message - * if any are found. + * substitute_grouped_columns - + * Scan the given expression tree for grouped variables (variables that + * are listed in the groupClauses list) and replace them with Vars that + * reference the RTE_GROUP RTE. Emit a suitable error message if any + * ungrouped variables (variables that are not listed in the groupClauses + * list and are not within the arguments of aggregate functions) are + * found. * * NOTE: we assume that the given clause has been transformed suitably for - * parser output. This means we can use expression_tree_walker. + * parser output. This means we can use expression_tree_mutator. * * NOTE: we recognize grouping expressions in the main query, but only * grouping Vars in subqueries. For example, this will be rejected, @@ -1273,37 +1301,36 @@ parseCheckAggregates(ParseState *pstate, Query *qry) * This appears to require a whole custom version of equal(), which is * way more pain than the feature seems worth. */ -static void -check_ungrouped_columns(Node *node, ParseState *pstate, Query *qry, - List *groupClauses, List *groupClauseCommonVars, - bool have_non_var_grouping, - List **func_grouped_rels) +static Node * +substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry, + List *groupClauses, List *groupClauseCommonVars, + List *gset_common, + bool have_non_var_grouping, + List **func_grouped_rels) { - check_ungrouped_columns_context context; + substitute_grouped_columns_context context; context.pstate = pstate; context.qry = qry; context.hasJoinRTEs = false; /* assume caller flattened join Vars */ context.groupClauses = groupClauses; context.groupClauseCommonVars = groupClauseCommonVars; + context.gset_common = gset_common; context.have_non_var_grouping = have_non_var_grouping; context.func_grouped_rels = func_grouped_rels; context.sublevels_up = 0; context.in_agg_direct_args = false; - check_ungrouped_columns_walker(node, &context); + return substitute_grouped_columns_mutator(node, &context); } -static bool -check_ungrouped_columns_walker(Node *node, - check_ungrouped_columns_context *context) +static Node * +substitute_grouped_columns_mutator(Node *node, + substitute_grouped_columns_context *context) { ListCell *gl; if (node == NULL) - return false; - if (IsA(node, Const) || - IsA(node, Param)) - return false; /* constants are always acceptable */ + return NULL; if (IsA(node, Aggref)) { @@ -1314,19 +1341,21 @@ check_ungrouped_columns_walker(Node *node, /* * If we find an aggregate call of the original level, do not * recurse into its normal arguments, ORDER BY arguments, or - * filter; ungrouped vars there are not an error. But we should - * check direct arguments as though they weren't in an aggregate. - * We set a special flag in the context to help produce a useful + * filter; grouped vars there do not need to be replaced and + * ungrouped vars there are not an error. But we should check + * direct arguments as though they weren't in an aggregate. We + * set a special flag in the context to help produce a useful * error message for ungrouped vars in direct arguments. */ - bool result; + agg = copyObject(agg); Assert(!context->in_agg_direct_args); context->in_agg_direct_args = true; - result = check_ungrouped_columns_walker((Node *) agg->aggdirectargs, - context); + agg->aggdirectargs = (List *) + substitute_grouped_columns_mutator((Node *) agg->aggdirectargs, + context); context->in_agg_direct_args = false; - return result; + return (Node *) agg; } /* @@ -1336,7 +1365,7 @@ check_ungrouped_columns_walker(Node *node, * levels, however. */ if ((int) agg->agglevelsup > context->sublevels_up) - return false; + return node; } if (IsA(node, GroupingFunc)) @@ -1346,7 +1375,7 @@ check_ungrouped_columns_walker(Node *node, /* handled GroupingFunc separately, no need to recheck at this level */ if ((int) grp->agglevelsup >= context->sublevels_up) - return false; + return node; } /* @@ -1358,15 +1387,33 @@ check_ungrouped_columns_walker(Node *node, */ if (context->have_non_var_grouping && context->sublevels_up == 0) { + int attnum = 0; + foreach(gl, context->groupClauses) { - TargetEntry *tle = lfirst(gl); + TargetEntry *tle = (TargetEntry *) lfirst(gl); + attnum++; if (equal(node, tle->expr)) - return false; /* acceptable, do not descend more */ + { + /* acceptable, replace it with a GROUP Var */ + return (Node *) buildGroupedVar(attnum, + tle->ressortgroupref, + context); + } } } + /* + * Constants are always acceptable. We have to do this after we checked + * the subexpression as a whole for a match, because it is possible that + * we have GROUP BY items that are constants, and the constants would + * become not so constant after the grouping step. + */ + if (IsA(node, Const) || + IsA(node, Param)) + return node; + /* * If we have an ungrouped Var of the original query level, we have a * failure. Vars below the original query level are not a problem, and @@ -1380,22 +1427,31 @@ check_ungrouped_columns_walker(Node *node, char *attname; if (var->varlevelsup != context->sublevels_up) - return false; /* it's not local to my query, ignore */ + return node; /* it's not local to my query, ignore */ /* * Check for a match, if we didn't do it above. */ if (!context->have_non_var_grouping || context->sublevels_up != 0) { + int attnum = 0; + foreach(gl, context->groupClauses) { - Var *gvar = (Var *) ((TargetEntry *) lfirst(gl))->expr; + TargetEntry *tle = (TargetEntry *) lfirst(gl); + Var *gvar = (Var *) tle->expr; + attnum++; if (IsA(gvar, Var) && gvar->varno == var->varno && gvar->varattno == var->varattno && gvar->varlevelsup == 0) - return false; /* acceptable, we're okay */ + { + /* acceptable, replace it with a GROUP Var */ + return (Node *) buildGroupedVar(attnum, + tle->ressortgroupref, + context); + } } } @@ -1416,7 +1472,7 @@ check_ungrouped_columns_walker(Node *node, * the constraintDeps list. */ if (list_member_int(*context->func_grouped_rels, var->varno)) - return false; /* previously proven acceptable */ + return node; /* previously proven acceptable */ Assert(var->varno > 0 && (int) var->varno <= list_length(context->pstate->p_rtable)); @@ -1431,7 +1487,7 @@ check_ungrouped_columns_walker(Node *node, { *context->func_grouped_rels = lappend_int(*context->func_grouped_rels, var->varno); - return false; /* acceptable */ + return node; /* acceptable */ } } @@ -1456,18 +1512,18 @@ check_ungrouped_columns_walker(Node *node, if (IsA(node, Query)) { /* Recurse into subselects */ - bool result; + Query *newnode; context->sublevels_up++; - result = query_tree_walker((Query *) node, - check_ungrouped_columns_walker, - (void *) context, - 0); + newnode = query_tree_mutator((Query *) node, + substitute_grouped_columns_mutator, + context, + 0); context->sublevels_up--; - return result; + return (Node *) newnode; } - return expression_tree_walker(node, check_ungrouped_columns_walker, - (void *) context); + return expression_tree_mutator(node, substitute_grouped_columns_mutator, + context); } /* @@ -1475,9 +1531,9 @@ check_ungrouped_columns_walker(Node *node, * Scan the given expression tree for GROUPING() and related calls, * and validate and process their arguments. * - * This is split out from check_ungrouped_columns above because it needs + * This is split out from substitute_grouped_columns above because it needs * to modify the nodes (which it does in-place, not via a mutator) while - * check_ungrouped_columns may see only a copy of the original thanks to + * substitute_grouped_columns may see only a copy of the original thanks to * flattening of join alias vars. So here, we flatten each individual * GROUPING argument as we see it before comparing it. */ @@ -1486,13 +1542,14 @@ finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry, List *groupClauses, bool hasJoinRTEs, bool have_non_var_grouping) { - check_ungrouped_columns_context context; + substitute_grouped_columns_context context; context.pstate = pstate; context.qry = qry; context.hasJoinRTEs = hasJoinRTEs; context.groupClauses = groupClauses; context.groupClauseCommonVars = NIL; + context.gset_common = NIL; context.have_non_var_grouping = have_non_var_grouping; context.func_grouped_rels = NULL; context.sublevels_up = 0; @@ -1502,7 +1559,7 @@ finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry, static bool finalize_grouping_exprs_walker(Node *node, - check_ungrouped_columns_context *context) + substitute_grouped_columns_context *context) { ListCell *gl; @@ -1634,13 +1691,45 @@ finalize_grouping_exprs_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, finalize_grouping_exprs_walker, - (void *) context, + context, 0); context->sublevels_up--; return result; } return expression_tree_walker(node, finalize_grouping_exprs_walker, - (void *) context); + context); +} + +/* + * buildGroupedVar - + * build a Var node that references the RTE_GROUP RTE + */ +static Var * +buildGroupedVar(int attnum, Index ressortgroupref, + substitute_grouped_columns_context *context) +{ + Var *var; + ParseNamespaceItem *grouping_nsitem = context->pstate->p_grouping_nsitem; + ParseNamespaceColumn *nscol = grouping_nsitem->p_nscolumns + attnum - 1; + + Assert(nscol->p_varno == grouping_nsitem->p_rtindex); + Assert(nscol->p_varattno == attnum); + var = makeVar(nscol->p_varno, + nscol->p_varattno, + nscol->p_vartype, + nscol->p_vartypmod, + nscol->p_varcollid, + context->sublevels_up); + /* makeVar doesn't offer parameters for these, so set by hand: */ + var->varnosyn = nscol->p_varnosyn; + var->varattnosyn = nscol->p_varattnosyn; + + if (context->qry->groupingSets && + !list_member_int(context->gset_common, ressortgroupref)) + var->varnullingrels = + bms_add_member(var->varnullingrels, grouping_nsitem->p_rtindex); + + return var; } @@ -1963,7 +2052,7 @@ resolve_aggregate_transtype(Oid aggfuncid, /* * agg_args_support_sendreceive - * Returns true if all non-byval of aggref's arg types have send and + * Returns true if all non-byval types of aggref's args have send and * receive functions. */ bool @@ -1978,6 +2067,15 @@ agg_args_support_sendreceive(Aggref *aggref) TargetEntry *tle = (TargetEntry *) lfirst(lc); Oid type = exprType((Node *) tle->expr); + /* + * RECORD is a special case: it has typsend/typreceive functions, but + * record_recv only works if passed the correct typmod to identify the + * specific anonymous record type. array_agg_deserialize cannot do + * that, so we have to disclaim support for the case. + */ + if (type == RECORDOID) + return false; + typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type)); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 8118036495b2b..9f20a70ce13cf 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -3,7 +3,7 @@ * parse_clause.c * handle clauses in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -40,11 +40,9 @@ #include "parser/parse_target.h" #include "parser/parse_type.h" #include "parser/parser.h" -#include "parser/parsetree.h" #include "rewrite/rewriteManip.h" #include "utils/builtins.h" #include "utils/catcache.h" -#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -1587,6 +1585,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, jnsitem->p_cols_visible = true; jnsitem->p_lateral_only = false; jnsitem->p_lateral_ok = true; + jnsitem->p_returning_type = VAR_RETURNING_DEFAULT; /* Per SQL, we must check for alias conflicts */ checkNameSpaceConflicts(pstate, list_make1(jnsitem), my_namespace); my_namespace = lappend(my_namespace, jnsitem); @@ -1649,6 +1648,7 @@ buildVarFromNSColumn(ParseState *pstate, ParseNamespaceColumn *nscol) nscol->p_varcollid, 0); /* makeVar doesn't offer parameters for these, so set by hand: */ + var->varreturningtype = nscol->p_varreturningtype; var->varnosyn = nscol->p_varnosyn; var->varattnosyn = nscol->p_varattnosyn; @@ -2915,7 +2915,7 @@ transformWindowDefinitions(ParseState *pstate, { SortGroupClause *sortcl; Node *sortkey; - int16 rangestrategy; + CompareType rangecmptype; if (list_length(wc->orderClause) != 1) ereport(ERROR, @@ -2928,12 +2928,12 @@ transformWindowDefinitions(ParseState *pstate, if (!get_ordering_op_properties(sortcl->sortop, &rangeopfamily, &rangeopcintype, - &rangestrategy)) + &rangecmptype)) elog(ERROR, "operator %u is not a valid ordering operator", sortcl->sortop); /* Record properties of sort ordering */ wc->inRangeColl = exprCollation(sortkey); - wc->inRangeAsc = (rangestrategy == BTLessStrategyNumber); + wc->inRangeAsc = !sortcl->reverse_sort; wc->inRangeNullsFirst = sortcl->nulls_first; } @@ -3489,6 +3489,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle, sortcl->eqop = eqop; sortcl->sortop = sortop; sortcl->hashable = hashable; + sortcl->reverse_sort = reverse; switch (sortby->sortby_nulls) { @@ -3571,6 +3572,8 @@ addTargetToGroupList(ParseState *pstate, TargetEntry *tle, grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); grpcl->eqop = eqop; grpcl->sortop = sortop; + grpcl->reverse_sort = false; /* sortop is "less than", or + * InvalidOid */ grpcl->nulls_first = false; /* OK with or without sortop */ grpcl->hashable = hashable; diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index ca6490a9ae2fc..0b5b81c7f27ee 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -3,7 +3,7 @@ * parse_coerce.c * handle type coercions/conversions for parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -414,6 +414,12 @@ coerce_type(ParseState *pstate, Node *node, &funcId); if (pathtype != COERCION_PATH_NONE) { + Oid baseTypeId; + int32 baseTypeMod; + + baseTypeMod = targetTypeMod; + baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod); + if (pathtype != COERCION_PATH_RELABELTYPE) { /* @@ -423,12 +429,6 @@ coerce_type(ParseState *pstate, Node *node, * and we need to extract the correct typmod to use from the * domain's typtypmod. */ - Oid baseTypeId; - int32 baseTypeMod; - - baseTypeMod = targetTypeMod; - baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod); - result = build_coercion_expression(node, pathtype, funcId, baseTypeId, baseTypeMod, ccontext, cformat, location); @@ -454,7 +454,8 @@ coerce_type(ParseState *pstate, Node *node, * that must be accounted for. If the destination is a domain * then we won't need a RelabelType node. */ - result = coerce_to_domain(node, InvalidOid, -1, targetTypeId, + result = coerce_to_domain(node, baseTypeId, baseTypeMod, + targetTypeId, ccontext, cformat, location, false); if (result == node) @@ -660,10 +661,8 @@ can_coerce_type(int nargs, const Oid *input_typeids, const Oid *target_typeids, * Create an expression tree to represent coercion to a domain type. * * 'arg': input expression - * 'baseTypeId': base type of domain, if known (pass InvalidOid if caller - * has not bothered to look this up) - * 'baseTypeMod': base type typmod of domain, if known (pass -1 if caller - * has not bothered to look this up) + * 'baseTypeId': base type of domain + * 'baseTypeMod': base type typmod of domain * 'typeId': target type to coerce to * 'ccontext': context indicator to control coercions * 'cformat': coercion display format @@ -679,9 +678,8 @@ coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId, { CoerceToDomain *result; - /* Get the base type if it hasn't been supplied */ - if (baseTypeId == InvalidOid) - baseTypeId = getBaseTypeAndTypmod(typeId, &baseTypeMod); + /* We now require the caller to supply correct baseTypeId/baseTypeMod */ + Assert(OidIsValid(baseTypeId)); /* If it isn't a domain, return the node as it was passed in */ if (baseTypeId == typeId) @@ -1263,6 +1261,43 @@ coerce_to_specific_type(ParseState *pstate, Node *node, constructName); } +/* + * coerce_null_to_domain() + * Build a NULL constant, then wrap it in CoerceToDomain + * if the desired type is a domain type. This allows any + * NOT NULL domain constraint to be enforced at runtime. + */ +Node * +coerce_null_to_domain(Oid typid, int32 typmod, Oid collation, + int typlen, bool typbyval) +{ + Node *result; + Oid baseTypeId; + int32 baseTypeMod = typmod; + + /* + * The constant must appear to have the domain's base type/typmod, else + * coerce_to_domain() will apply a length coercion which is useless. + */ + baseTypeId = getBaseTypeAndTypmod(typid, &baseTypeMod); + result = (Node *) makeConst(baseTypeId, + baseTypeMod, + collation, + typlen, + (Datum) 0, + true, /* isnull */ + typbyval); + if (typid != baseTypeId) + result = coerce_to_domain(result, + baseTypeId, baseTypeMod, + typid, + COERCION_IMPLICIT, + COERCE_IMPLICIT_CAST, + -1, + false); + return result; +} + /* * parser_coercion_errposition - report coercion error location, if possible * diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c index 44529bb49e64b..d2e218353f310 100644 --- a/src/backend/parser/parse_collate.c +++ b/src/backend/parser/parse_collate.c @@ -29,7 +29,7 @@ * at runtime. If we knew exactly which functions require collation * information, we could throw those errors at parse time instead. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -108,7 +108,7 @@ assign_query_collations(ParseState *pstate, Query *query) */ (void) query_tree_walker(query, assign_query_collations_walker, - (void *) pstate, + pstate, QTW_IGNORE_RANGE_TABLE | QTW_IGNORE_CTE_SUBQUERIES); } @@ -295,7 +295,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); collation = expr->collOid; Assert(OidIsValid(collation)); @@ -317,7 +317,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) /* ... but first, recurse */ (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); if (OidIsValid(expr->resultcollid)) { @@ -403,7 +403,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) /* ... but first, recurse */ (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); if (OidIsValid(typcollation)) { @@ -444,7 +444,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) case T_TargetEntry: (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); /* * TargetEntry can have only one child, and should bubble that @@ -488,7 +488,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) case T_MergeAction: (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); /* * When we're invoked on a query's jointree, we don't need to do @@ -528,7 +528,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) case T_List: (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); /* * When processing a list, collation state just bubbles up from @@ -699,7 +699,7 @@ assign_collations_walker(Node *node, assign_collations_context *context) */ (void) expression_tree_walker(node, assign_collations_walker, - (void *) &loccontext); + &loccontext); break; } diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c index de9ae9b48348d..366fd901d9d5e 100644 --- a/src/backend/parser/parse_cte.c +++ b/src/backend/parser/parse_cte.c @@ -3,7 +3,7 @@ * parse_cte.c * handle CTEs (common table expressions) in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -88,6 +88,7 @@ static void analyzeCTE(ParseState *pstate, CommonTableExpr *cte); /* Dependency processing functions */ static void makeDependencyGraph(CteState *cstate); static bool makeDependencyGraphWalker(Node *node, CteState *cstate); +static void WalkInnerWith(Node *stmt, WithClause *withClause, CteState *cstate); static void TopologicalSort(ParseState *pstate, CteItem *items, int numitems); /* Recursion validity checker functions */ @@ -725,58 +726,69 @@ makeDependencyGraphWalker(Node *node, CteState *cstate) if (IsA(node, SelectStmt)) { SelectStmt *stmt = (SelectStmt *) node; - ListCell *lc; if (stmt->withClause) { - if (stmt->withClause->recursive) - { - /* - * In the RECURSIVE case, all query names of the WITH are - * visible to all WITH items as well as the main query. So - * push them all on, process, pop them all off. - */ - cstate->innerwiths = lcons(stmt->withClause->ctes, - cstate->innerwiths); - foreach(lc, stmt->withClause->ctes) - { - CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); + /* Examine the WITH clause and the SelectStmt */ + WalkInnerWith(node, stmt->withClause, cstate); + /* We're done examining the SelectStmt */ + return false; + } + /* if no WITH clause, just fall through for normal processing */ + } + else if (IsA(node, InsertStmt)) + { + InsertStmt *stmt = (InsertStmt *) node; - (void) makeDependencyGraphWalker(cte->ctequery, cstate); - } - (void) raw_expression_tree_walker(node, - makeDependencyGraphWalker, - (void *) cstate); - cstate->innerwiths = list_delete_first(cstate->innerwiths); - } - else - { - /* - * In the non-RECURSIVE case, query names are visible to the - * WITH items after them and to the main query. - */ - cstate->innerwiths = lcons(NIL, cstate->innerwiths); - foreach(lc, stmt->withClause->ctes) - { - CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); - ListCell *cell1; + if (stmt->withClause) + { + /* Examine the WITH clause and the InsertStmt */ + WalkInnerWith(node, stmt->withClause, cstate); + /* We're done examining the InsertStmt */ + return false; + } + /* if no WITH clause, just fall through for normal processing */ + } + else if (IsA(node, DeleteStmt)) + { + DeleteStmt *stmt = (DeleteStmt *) node; - (void) makeDependencyGraphWalker(cte->ctequery, cstate); - /* note that recursion could mutate innerwiths list */ - cell1 = list_head(cstate->innerwiths); - lfirst(cell1) = lappend((List *) lfirst(cell1), cte); - } - (void) raw_expression_tree_walker(node, - makeDependencyGraphWalker, - (void *) cstate); - cstate->innerwiths = list_delete_first(cstate->innerwiths); - } - /* We're done examining the SelectStmt */ + if (stmt->withClause) + { + /* Examine the WITH clause and the DeleteStmt */ + WalkInnerWith(node, stmt->withClause, cstate); + /* We're done examining the DeleteStmt */ return false; } /* if no WITH clause, just fall through for normal processing */ } - if (IsA(node, WithClause)) + else if (IsA(node, UpdateStmt)) + { + UpdateStmt *stmt = (UpdateStmt *) node; + + if (stmt->withClause) + { + /* Examine the WITH clause and the UpdateStmt */ + WalkInnerWith(node, stmt->withClause, cstate); + /* We're done examining the UpdateStmt */ + return false; + } + /* if no WITH clause, just fall through for normal processing */ + } + else if (IsA(node, MergeStmt)) + { + MergeStmt *stmt = (MergeStmt *) node; + + if (stmt->withClause) + { + /* Examine the WITH clause and the MergeStmt */ + WalkInnerWith(node, stmt->withClause, cstate); + /* We're done examining the MergeStmt */ + return false; + } + /* if no WITH clause, just fall through for normal processing */ + } + else if (IsA(node, WithClause)) { /* * Prevent raw_expression_tree_walker from recursing directly into a @@ -787,7 +799,61 @@ makeDependencyGraphWalker(Node *node, CteState *cstate) } return raw_expression_tree_walker(node, makeDependencyGraphWalker, - (void *) cstate); + cstate); +} + +/* + * makeDependencyGraphWalker's recursion into a statement having a WITH clause. + * + * This subroutine is concerned with updating the innerwiths list correctly + * based on the visibility rules for CTE names. + */ +static void +WalkInnerWith(Node *stmt, WithClause *withClause, CteState *cstate) +{ + ListCell *lc; + + if (withClause->recursive) + { + /* + * In the RECURSIVE case, all query names of the WITH are visible to + * all WITH items as well as the main query. So push them all on, + * process, pop them all off. + */ + cstate->innerwiths = lcons(withClause->ctes, cstate->innerwiths); + foreach(lc, withClause->ctes) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); + + (void) makeDependencyGraphWalker(cte->ctequery, cstate); + } + (void) raw_expression_tree_walker(stmt, + makeDependencyGraphWalker, + cstate); + cstate->innerwiths = list_delete_first(cstate->innerwiths); + } + else + { + /* + * In the non-RECURSIVE case, query names are visible to the WITH + * items after them and to the main query. + */ + cstate->innerwiths = lcons(NIL, cstate->innerwiths); + foreach(lc, withClause->ctes) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); + ListCell *cell1; + + (void) makeDependencyGraphWalker(cte->ctequery, cstate); + /* note that recursion could mutate innerwiths list */ + cell1 = list_head(cstate->innerwiths); + lfirst(cell1) = lappend((List *) lfirst(cell1), cte); + } + (void) raw_expression_tree_walker(stmt, + makeDependencyGraphWalker, + cstate); + cstate->innerwiths = list_delete_first(cstate->innerwiths); + } } /* @@ -1130,7 +1196,7 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate) } return raw_expression_tree_walker(node, checkWellFormedRecursionWalker, - (void *) cstate); + cstate); } /* @@ -1147,7 +1213,7 @@ checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate) /* just recurse without changing state */ raw_expression_tree_walker((Node *) stmt, checkWellFormedRecursionWalker, - (void *) cstate); + cstate); } else { @@ -1157,7 +1223,7 @@ checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate) case SETOP_UNION: raw_expression_tree_walker((Node *) stmt, checkWellFormedRecursionWalker, - (void *) cstate); + cstate); break; case SETOP_INTERSECT: if (stmt->all) diff --git a/src/backend/parser/parse_enr.c b/src/backend/parser/parse_enr.c index 420d37cb868ae..119911598b90d 100644 --- a/src/backend/parser/parse_enr.c +++ b/src/backend/parser/parse_enr.c @@ -3,7 +3,7 @@ * parse_enr.c * parser support routines dealing with ephemeral named relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 8577f278065b7..d66276801c67b 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -3,7 +3,7 @@ * parse_expr.c * handle expressions in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -16,7 +16,6 @@ #include "postgres.h" #include "catalog/pg_aggregate.h" -#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/dbcommands.h" #include "miscadmin.h" @@ -37,7 +36,6 @@ #include "utils/builtins.h" #include "utils/date.h" #include "utils/fmgroids.h" -#include "utils/jsonb.h" #include "utils/lsyscache.h" #include "utils/timestamp.h" #include "utils/xml.h" @@ -1099,7 +1097,8 @@ transformAExprNullIf(ParseState *pstate, A_Expr *a) if (result->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("NULLIF requires = operator to yield boolean"), + /* translator: %s is name of a SQL construct, eg NULLIF */ + errmsg("%s requires = operator to yield boolean", "NULLIF"), parser_errposition(pstate, a->location))); if (result->opretset) ereport(ERROR, @@ -1224,6 +1223,8 @@ transformAExprIn(ParseState *pstate, A_Expr *a) newa->element_typeid = scalar_type; newa->elements = aexprs; newa->multidims = false; + newa->list_start = a->rexpr_list_start; + newa->list_end = a->rexpr_list_end; newa->location = -1; result = (Node *) make_scalar_array_op(pstate, @@ -2054,10 +2055,18 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, /* * Check for sub-array expressions, if we haven't already found - * one. + * one. Note we don't accept domain-over-array as a sub-array, + * nor int2vector nor oidvector; those have constraints that don't + * map well to being treated as a sub-array. */ - if (!newa->multidims && type_is_array(exprType(newe))) - newa->multidims = true; + if (!newa->multidims) + { + Oid newetype = exprType(newe); + + if (newetype != INT2VECTOROID && newetype != OIDVECTOROID && + type_is_array(newetype)) + newa->multidims = true; + } } newelems = lappend(newelems, newe); @@ -2158,6 +2167,8 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, /* array_collid will be set by parse_collate.c */ newa->element_typeid = element_type; newa->elements = newcoercedelems; + newa->list_start = a->list_start; + newa->list_end = a->list_end; newa->location = a->location; return (Node *) newa; @@ -2620,6 +2631,13 @@ transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, * point, there seems no harm in expanding it now rather than during * planning. * + * Note that if the nsitem is an OLD/NEW alias for the target RTE (as can + * appear in a RETURNING list), its alias won't match the target RTE's + * alias, but we still want to make a whole-row Var here rather than a + * RowExpr, for consistency with direct references to the target RTE, and + * so that any dropped columns are handled correctly. Thus we also check + * p_returning_type here. + * * Note that if the RTE is a function returning scalar, we create just a * plain reference to the function value, not a composite containing a * single column. This is pretty inconsistent at first sight, but it's @@ -2627,13 +2645,17 @@ transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, * "rel.*" mean the same thing for composite relations, so why not for * scalar functions... */ - if (nsitem->p_names == nsitem->p_rte->eref) + if (nsitem->p_names == nsitem->p_rte->eref || + nsitem->p_returning_type != VAR_RETURNING_DEFAULT) { Var *result; result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex, sublevels_up, true); + /* mark Var for RETURNING OLD/NEW, as necessary */ + result->varreturningtype = nsitem->p_returning_type; + /* location is not filled in by makeWholeRowVar */ result->location = location; @@ -2656,9 +2678,8 @@ transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, * are in the RTE. We needn't worry about marking the RTE for SELECT * access, as the common columns are surely so marked already. */ - expandRTE(nsitem->p_rte, nsitem->p_rtindex, - sublevels_up, location, false, - NULL, &fields); + expandRTE(nsitem->p_rte, nsitem->p_rtindex, sublevels_up, + nsitem->p_returning_type, location, false, NULL, &fields); rowexpr = makeNode(RowExpr); rowexpr->args = list_truncate(fields, list_length(nsitem->p_names->colnames)); @@ -2808,14 +2829,14 @@ make_row_comparison_op(ParseState *pstate, List *opname, List *largs, List *rargs, int location) { RowCompareExpr *rcexpr; - RowCompareType rctype; + CompareType cmptype; List *opexprs; List *opnos; List *opfamilies; ListCell *l, *r; List **opinfo_lists; - Bitmapset *strats; + Bitmapset *cmptypes; int nopers; int i; @@ -2880,45 +2901,45 @@ make_row_comparison_op(ParseState *pstate, List *opname, /* * Now we must determine which row comparison semantics (= <> < <= > >=) - * apply to this set of operators. We look for btree opfamilies - * containing the operators, and see which interpretations (strategy - * numbers) exist for each operator. + * apply to this set of operators. We look for opfamilies containing the + * operators, and see which interpretations (cmptypes) exist for each + * operator. */ opinfo_lists = (List **) palloc(nopers * sizeof(List *)); - strats = NULL; + cmptypes = NULL; i = 0; foreach(l, opexprs) { Oid opno = ((OpExpr *) lfirst(l))->opno; - Bitmapset *this_strats; + Bitmapset *this_cmptypes; ListCell *j; - opinfo_lists[i] = get_op_btree_interpretation(opno); + opinfo_lists[i] = get_op_index_interpretation(opno); /* - * convert strategy numbers into a Bitmapset to make the intersection + * convert comparison types into a Bitmapset to make the intersection * calculation easy. */ - this_strats = NULL; + this_cmptypes = NULL; foreach(j, opinfo_lists[i]) { - OpBtreeInterpretation *opinfo = lfirst(j); + OpIndexInterpretation *opinfo = lfirst(j); - this_strats = bms_add_member(this_strats, opinfo->strategy); + this_cmptypes = bms_add_member(this_cmptypes, opinfo->cmptype); } if (i == 0) - strats = this_strats; + cmptypes = this_cmptypes; else - strats = bms_int_members(strats, this_strats); + cmptypes = bms_int_members(cmptypes, this_cmptypes); i++; } /* * If there are multiple common interpretations, we may use any one of - * them ... this coding arbitrarily picks the lowest btree strategy + * them ... this coding arbitrarily picks the lowest comparison type * number. */ - i = bms_next_member(strats, -1); + i = bms_next_member(cmptypes, -1); if (i < 0) { /* No common interpretation, so fail */ @@ -2929,15 +2950,15 @@ make_row_comparison_op(ParseState *pstate, List *opname, errhint("Row comparison operators must be associated with btree operator families."), parser_errposition(pstate, location))); } - rctype = (RowCompareType) i; + cmptype = (CompareType) i; /* * For = and <> cases, we just combine the pairwise operators with AND or * OR respectively. */ - if (rctype == ROWCOMPARE_EQ) + if (cmptype == COMPARE_EQ) return (Node *) makeBoolExpr(AND_EXPR, opexprs, location); - if (rctype == ROWCOMPARE_NE) + if (cmptype == COMPARE_NE) return (Node *) makeBoolExpr(OR_EXPR, opexprs, location); /* @@ -2952,9 +2973,9 @@ make_row_comparison_op(ParseState *pstate, List *opname, foreach(j, opinfo_lists[i]) { - OpBtreeInterpretation *opinfo = lfirst(j); + OpIndexInterpretation *opinfo = lfirst(j); - if (opinfo->strategy == rctype) + if (opinfo->cmptype == cmptype) { opfamily = opinfo->opfamily_id; break; @@ -2990,7 +3011,7 @@ make_row_comparison_op(ParseState *pstate, List *opname, } rcexpr = makeNode(RowCompareExpr); - rcexpr->rctype = rctype; + rcexpr->cmptype = cmptype; rcexpr->opnos = opnos; rcexpr->opfamilies = opfamilies; rcexpr->inputcollids = NIL; /* assign_expr_collations will fix this */ @@ -3060,7 +3081,9 @@ make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, if (((OpExpr *) result)->opresulttype != BOOLOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("IS DISTINCT FROM requires = operator to yield boolean"), + /* translator: %s is name of a SQL construct, eg NULLIF */ + errmsg("%s requires = operator to yield boolean", + "IS DISTINCT FROM"), parser_errposition(pstate, location))); if (((OpExpr *) result)->opretset) ereport(ERROR, @@ -3753,7 +3776,7 @@ transformJsonArrayQueryConstructor(ParseState *pstate, /* Transform query only for counting target list entries. */ qpstate = make_parsestate(pstate); - query = transformStmt(qpstate, ctor->query); + query = transformStmt(qpstate, copyObject(ctor->query)); if (count_nonjunk_tlist_entries(query->targetList) != 1) ereport(ERROR, @@ -3887,7 +3910,7 @@ transformJsonAggConstructor(ParseState *pstate, JsonAggConstructor *agg_ctor, /* * Transform JSON_OBJECTAGG() aggregate function. * - * JSON_OBJECT() is transformed into a JsonConstructorExpr node of type + * JSON_OBJECTAGG() is transformed into a JsonConstructorExpr node of type * JSCTOR_JSON_OBJECTAGG, which at runtime becomes a * json[b]_object_agg[_unique][_strict](agg->arg->key, agg->arg->value) call * depending on the output JSON format. The result is coerced to the target @@ -4112,8 +4135,9 @@ transformJsonReturning(ParseState *pstate, JsonOutput *output, const char *fname if (returning->typid != JSONOID && returning->typid != JSONBOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use RETURNING type %s in %s", + errmsg("cannot use type %s in RETURNING clause of %s", format_type_be(returning->typid), fname), + errhint("Try returning json or jsonb."), parser_errposition(pstate, output->typeName->location))); } else @@ -4232,7 +4256,7 @@ transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr) if (typcategory != TYPCATEGORY_STRING) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use RETURNING type %s in %s", + errmsg("cannot use type %s in RETURNING clause of %s", format_type_be(returning->typid), "JSON_SERIALIZE()"), errhint("Try returning a string type or bytea."))); @@ -4326,15 +4350,22 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) if (func->column_name == NULL) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON EMPTY behavior"), - errdetail("Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON EMPTY for JSON_QUERY()."), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior", "ON EMPTY"), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), + second %s is a SQL/JSON function name (e.g. JSON_QUERY) */ + errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.", + "ON EMPTY", "JSON_QUERY()"), parser_errposition(pstate, func->on_empty->location)); else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON EMPTY behavior for column \"%s\"", - func->column_name), - errdetail("Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON EMPTY for formatted columns."), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior for column \"%s\"", + "ON EMPTY", func->column_name), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.", + "ON EMPTY"), parser_errposition(pstate, func->on_empty->location)); } if (func->on_error != NULL && @@ -4348,15 +4379,22 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) if (func->column_name == NULL) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior"), - errdetail("Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for JSON_QUERY()."), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior", "ON ERROR"), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), + second %s is a SQL/JSON function name (e.g. JSON_QUERY) */ + errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.", + "ON ERROR", "JSON_QUERY()"), parser_errposition(pstate, func->on_error->location)); else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior for column \"%s\"", - func->column_name), - errdetail("Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for formatted columns."), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior for column \"%s\"", + "ON ERROR", func->column_name), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.", + "ON ERROR"), parser_errposition(pstate, func->on_error->location)); } } @@ -4372,15 +4410,20 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) if (func->column_name == NULL) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior"), - errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in ON ERROR for JSON_EXISTS()."), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior", "ON ERROR"), + errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s.", + "ON ERROR", "JSON_EXISTS()"), parser_errposition(pstate, func->on_error->location)); else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior for column \"%s\"", - func->column_name), - errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in ON ERROR for EXISTS columns."), + /*- translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior for column \"%s\"", + "ON ERROR", func->column_name), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns.", + "ON ERROR"), parser_errposition(pstate, func->on_error->location)); } if (func->op == JSON_VALUE_OP) @@ -4393,15 +4436,22 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) if (func->column_name == NULL) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON EMPTY behavior"), - errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in ON EMPTY for JSON_VALUE()."), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior", "ON EMPTY"), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), + second %s is a SQL/JSON function name (e.g. JSON_QUERY) */ + errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.", + "ON EMPTY", "JSON_VALUE()"), parser_errposition(pstate, func->on_empty->location)); else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON EMPTY behavior for column \"%s\"", - func->column_name), - errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in ON EMPTY for scalar columns."), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior for column \"%s\"", + "ON EMPTY", func->column_name), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.", + "ON EMPTY"), parser_errposition(pstate, func->on_empty->location)); } if (func->on_error != NULL && @@ -4412,15 +4462,22 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) if (func->column_name == NULL) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior"), - errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in ON ERROR for JSON_VALUE()."), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior", "ON ERROR"), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), + second %s is a SQL/JSON function name (e.g. JSON_QUERY) */ + errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.", + "ON ERROR", "JSON_VALUE()"), parser_errposition(pstate, func->on_error->location)); else ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior for column \"%s\"", - func->column_name), - errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in ON ERROR for scalar columns."), + /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errmsg("invalid %s behavior for column \"%s\"", + "ON ERROR", func->column_name), + /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */ + errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.", + "ON ERROR"), parser_errposition(pstate, func->on_error->location)); } } @@ -4567,13 +4624,13 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) } /* - * Assume EMPTY ON ERROR when ON ERROR is not specified. + * Assume EMPTY ARRAY ON ERROR when ON ERROR is not specified. * * ON EMPTY cannot be specified at the top level but it can be for * the individual columns. */ jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, - JSON_BEHAVIOR_EMPTY, + JSON_BEHAVIOR_EMPTY_ARRAY, jsexpr->returning); break; @@ -4685,51 +4742,91 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior, if (expr == NULL && btype != JSON_BEHAVIOR_ERROR) expr = GetJsonBehaviorConst(btype, location); - if (expr) + /* + * Try to coerce the expression if needed. + * + * Use runtime coercion using json_populate_type() if the expression is + * NULL, jsonb-valued, or boolean-valued (unless the target type is + * integer or domain over integer, in which case use the + * boolean-to-integer cast function). + * + * For other non-NULL expressions, try to find a cast and error out if one + * is not found. + */ + if (expr && exprType(expr) != returning->typid) { - Node *coerced_expr = expr; bool isnull = (IsA(expr, Const) && ((Const *) expr)->constisnull); - /* - * Coerce NULLs and "internal" (that is, not specified by the user) - * jsonb-valued expressions at runtime using json_populate_type(). - * - * For other (user-specified) non-NULL values, try to find a cast and - * error out if one is not found. - */ if (isnull || - (exprType(expr) == JSONBOID && - btype == default_behavior)) + exprType(expr) == JSONBOID || + (exprType(expr) == BOOLOID && + getBaseType(returning->typid) != INT4OID)) + { coerce_at_runtime = true; + + /* + * json_populate_type() expects to be passed a jsonb value, so gin + * up a Const containing the appropriate boolean value represented + * as jsonb, discarding the original Const containing a plain + * boolean. + */ + if (exprType(expr) == BOOLOID) + { + char *val = btype == JSON_BEHAVIOR_TRUE ? "true" : "false"; + + expr = (Node *) makeConst(JSONBOID, -1, InvalidOid, -1, + DirectFunctionCall1(jsonb_in, + CStringGetDatum(val)), + false, false); + } + } else { - int32 baseTypmod = returning->typmod; - - if (get_typtype(returning->typid) == TYPTYPE_DOMAIN) - (void) getBaseTypeAndTypmod(returning->typid, &baseTypmod); + Node *coerced_expr; + char typcategory = TypeCategory(returning->typid); - if (baseTypmod > 0) - expr = coerce_to_specific_type(pstate, expr, TEXTOID, - "JSON_FUNCTION()"); + /* + * Use an assignment cast if coercing to a string type so that + * build_coercion_expression() assumes implicit coercion when + * coercing the typmod, so that inputs exceeding length cause an + * error instead of silent truncation. + */ coerced_expr = coerce_to_target_type(pstate, expr, exprType(expr), - returning->typid, baseTypmod, - baseTypmod > 0 ? COERCION_IMPLICIT : + returning->typid, returning->typmod, + (typcategory == TYPCATEGORY_STRING || + typcategory == TYPCATEGORY_BITSTRING) ? + COERCION_ASSIGNMENT : COERCION_EXPLICIT, - baseTypmod > 0 ? COERCE_IMPLICIT_CAST : COERCE_EXPLICIT_CAST, exprLocation((Node *) behavior)); - } - if (coerced_expr == NULL) - ereport(ERROR, - errcode(ERRCODE_CANNOT_COERCE), - errmsg("cannot cast behavior expression of type %s to %s", - format_type_be(exprType(expr)), - format_type_be(returning->typid)), - parser_errposition(pstate, exprLocation(expr))); - else + if (coerced_expr == NULL) + { + /* + * Provide a HINT if the expression comes from a DEFAULT + * clause. + */ + if (btype == JSON_BEHAVIOR_DEFAULT) + ereport(ERROR, + errcode(ERRCODE_CANNOT_COERCE), + errmsg("cannot cast behavior expression of type %s to %s", + format_type_be(exprType(expr)), + format_type_be(returning->typid)), + errhint("You will need to explicitly cast the expression to type %s.", + format_type_be(returning->typid)), + parser_errposition(pstate, exprLocation(expr))); + else + ereport(ERROR, + errcode(ERRCODE_CANNOT_COERCE), + errmsg("cannot cast behavior expression of type %s to %s", + format_type_be(exprType(expr)), + format_type_be(returning->typid)), + parser_errposition(pstate, exprLocation(expr))); + } + expr = coerced_expr; + } } if (behavior) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 9b23344a3b1ac..583bbbf232f04 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -3,7 +3,7 @@ * parse_func.c * handle function calls in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/parser/parse_jsontable.c b/src/backend/parser/parse_jsontable.c index 8a72e498e8933..13d533b83f37a 100644 --- a/src/backend/parser/parse_jsontable.c +++ b/src/backend/parser/parse_jsontable.c @@ -3,7 +3,7 @@ * parse_jsontable.c * parsing of JSON_TABLE * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -15,9 +15,7 @@ #include "postgres.h" -#include "catalog/pg_collation.h" #include "catalog/pg_type.h" -#include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" @@ -26,7 +24,7 @@ #include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/parse_type.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/json.h" #include "utils/lsyscache.h" @@ -91,7 +89,7 @@ transformJsonTable(ParseState *pstate, JsonTable *jt) jt->on_error->btype != JSON_BEHAVIOR_EMPTY_ARRAY) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid ON ERROR behavior"), + errmsg("invalid %s behavior", "ON ERROR"), errdetail("Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause."), parser_errposition(pstate, jt->on_error->location)); @@ -292,7 +290,7 @@ transformJsonTableColumns(JsonTableParseContext *cxt, List *columns, if (ordinality_found) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot use more than one FOR ORDINALITY column"), + errmsg("only one FOR ORDINALITY column is allowed"), parser_errposition(pstate, rawc->location))); ordinality_found = true; colexpr = NULL; diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c index 87df79027d7fb..51d7703eff7e0 100644 --- a/src/backend/parser/parse_merge.c +++ b/src/backend/parser/parse_merge.c @@ -3,7 +3,7 @@ * parse_merge.c * handle merge-statement in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -247,8 +247,8 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt) qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); /* Transform the RETURNING list, if any */ - qry->returningList = transformReturningList(pstate, stmt->returningList, - EXPR_KIND_MERGE_RETURNING); + transformReturningClause(pstate, qry, stmt->returningClause, + EXPR_KIND_MERGE_RETURNING); /* * We now have a good query shape, so now look at the WHEN conditions and diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 9361b5252d89a..d6feb16aef375 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -3,7 +3,7 @@ * parse_node.c * various routines that make nodes for querytrees * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -144,7 +144,7 @@ setup_parser_errposition_callback(ParseCallbackState *pcbstate, pcbstate->pstate = pstate; pcbstate->location = location; pcbstate->errcallback.callback = pcb_error_callback; - pcbstate->errcallback.arg = (void *) pcbstate; + pcbstate->errcallback.arg = pcbstate; pcbstate->errcallback.previous = error_context_stack; error_context_stack = &pcbstate->errcallback; } diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 8dcc831c76fd5..0c4337563cf35 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -3,7 +3,7 @@ * parse_oper.c * handle operator things for parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c index b617591ef682d..930921626b6d5 100644 --- a/src/backend/parser/parse_param.c +++ b/src/backend/parser/parse_param.c @@ -12,7 +12,7 @@ * Note that other approaches to parameters are possible using the parser * hooks defined in ParseState. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -72,7 +72,7 @@ setup_parse_fixed_parameters(ParseState *pstate, parstate->paramTypes = paramTypes; parstate->numParams = numParams; - pstate->p_ref_hook_state = (void *) parstate; + pstate->p_ref_hook_state = parstate; pstate->p_paramref_hook = fixed_paramref_hook; /* no need to use p_coerce_param_hook */ } @@ -88,7 +88,7 @@ setup_parse_variable_parameters(ParseState *pstate, parstate->paramTypes = paramTypes; parstate->numParams = numParams; - pstate->p_ref_hook_state = (void *) parstate; + pstate->p_ref_hook_state = parstate; pstate->p_paramref_hook = variable_paramref_hook; pstate->p_coerce_param_hook = variable_coerce_param_hook; } @@ -274,7 +274,7 @@ check_variable_parameters(ParseState *pstate, Query *query) if (*parstate->numParams > 0) (void) query_tree_walker(query, check_parameter_resolution_walker, - (void *) pstate, 0); + pstate, 0); } /* @@ -318,10 +318,10 @@ check_parameter_resolution_walker(Node *node, ParseState *pstate) /* Recurse into RTE subquery or not-yet-planned sublink subquery */ return query_tree_walker((Query *) node, check_parameter_resolution_walker, - (void *) pstate, 0); + pstate, 0); } return expression_tree_walker(node, check_parameter_resolution_walker, - (void *) pstate); + pstate); } /* diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 2f64eaf0e371a..04ecf64b1fc25 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -3,7 +3,7 @@ * parse_relation.c * parser support routines dealing with relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -91,11 +91,13 @@ static void markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col); static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars); static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars); static int specialAttNum(const char *attname); @@ -123,7 +125,10 @@ static bool isQueryUsingTempRelation_walker(Node *node, void *context); * that (a) has no alias and (b) is for the same relation identified by * schemaname.refname. In this case we convert schemaname.refname to a * relation OID and search by relid, rather than by alias name. This is - * peculiar, but it's what SQL says to do. + * peculiar, but it's what SQL says to do. While processing a query's + * RETURNING list, there may be additional namespace items for OLD and NEW, + * with the same relation OID as the target namespace item. These are + * ignored in the search, since they don't match by schemaname.refname. */ ParseNamespaceItem * refnameNamespaceItem(ParseState *pstate, @@ -253,6 +258,9 @@ scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location) /* If not inside LATERAL, ignore lateral-only items */ if (nsitem->p_lateral_only && !pstate->p_lateral_active) continue; + /* Ignore OLD/NEW namespace items that can appear in RETURNING */ + if (nsitem->p_returning_type != VAR_RETURNING_DEFAULT) + continue; /* yes, the test for alias == NULL should be there... */ if (rte->rtekind == RTE_RELATION && @@ -704,7 +712,11 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem, colname), parser_errposition(pstate, location))); - /* In generated column, no system column is allowed except tableOid */ + /* + * In generated column, no system column is allowed except tableOid. + * (Required for stored generated, but we also do it for virtual generated + * for now for consistency.) + */ if (pstate->p_expr_kind == EXPR_KIND_GENERATED_COLUMN && attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber) ereport(ERROR, @@ -763,6 +775,9 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem, } var->location = location; + /* Mark Var for RETURNING OLD/NEW, as necessary */ + var->varreturningtype = nsitem->p_returning_type; + /* Mark Var if it's nulled by any outer joins */ markNullableIfNeeded(pstate, var); @@ -1336,6 +1351,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, nsitem->p_cols_visible = true; nsitem->p_lateral_only = false; nsitem->p_lateral_ok = true; + nsitem->p_returning_type = VAR_RETURNING_DEFAULT; return nsitem; } @@ -1399,6 +1415,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex, nsitem->p_cols_visible = true; nsitem->p_lateral_only = false; nsitem->p_lateral_ok = true; + nsitem->p_returning_type = VAR_RETURNING_DEFAULT; return nsitem; } @@ -2300,6 +2317,7 @@ addRangeTableEntryForJoin(ParseState *pstate, nsitem->p_cols_visible = true; nsitem->p_lateral_only = false; nsitem->p_lateral_ok = true; + nsitem->p_returning_type = VAR_RETURNING_DEFAULT; return nsitem; } @@ -2557,6 +2575,79 @@ addRangeTableEntryForENR(ParseState *pstate, tupdesc); } +/* + * Add an entry for grouping step to the pstate's range table (p_rtable). + * Then, construct and return a ParseNamespaceItem for the new RTE. + */ +ParseNamespaceItem * +addRangeTableEntryForGroup(ParseState *pstate, + List *groupClauses) +{ + RangeTblEntry *rte = makeNode(RangeTblEntry); + Alias *eref; + List *groupexprs; + List *coltypes, + *coltypmods, + *colcollations; + ListCell *lc; + ParseNamespaceItem *nsitem; + + Assert(pstate != NULL); + + rte->rtekind = RTE_GROUP; + rte->alias = NULL; + + eref = makeAlias("*GROUP*", NIL); + + /* fill in any unspecified alias columns, and extract column type info */ + groupexprs = NIL; + coltypes = coltypmods = colcollations = NIL; + foreach(lc, groupClauses) + { + TargetEntry *te = (TargetEntry *) lfirst(lc); + char *colname = te->resname ? pstrdup(te->resname) : "?column?"; + + eref->colnames = lappend(eref->colnames, makeString(colname)); + + groupexprs = lappend(groupexprs, copyObject(te->expr)); + + coltypes = lappend_oid(coltypes, + exprType((Node *) te->expr)); + coltypmods = lappend_int(coltypmods, + exprTypmod((Node *) te->expr)); + colcollations = lappend_oid(colcollations, + exprCollation((Node *) te->expr)); + } + + rte->eref = eref; + rte->groupexprs = groupexprs; + + /* + * Set flags. + * + * The grouping step is never checked for access rights, so no need to + * perform addRTEPermissionInfo(). + */ + rte->lateral = false; + rte->inFromCl = false; + + /* + * Add completed RTE to pstate's range table list, so that we know its + * index. But we don't add it to the join list --- caller must do that if + * appropriate. + */ + pstate->p_rtable = lappend(pstate->p_rtable, rte); + + /* + * Build a ParseNamespaceItem, but don't add it to the pstate's namespace + * list --- caller must do that if appropriate. + */ + nsitem = buildNSItemFromLists(rte, list_length(pstate->p_rtable), + coltypes, coltypmods, colcollations); + + return nsitem; +} + /* * Has the specified refname been selected FOR UPDATE/FOR SHARE? @@ -2647,9 +2738,10 @@ addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, * results. If include_dropped is true then empty strings and NULL constants * (not Vars!) are returned for dropped columns. * - * rtindex, sublevels_up, and location are the varno, varlevelsup, and location - * values to use in the created Vars. Ordinarily rtindex should match the - * actual position of the RTE in its rangetable. + * rtindex, sublevels_up, returning_type, and location are the varno, + * varlevelsup, varreturningtype, and location values to use in the created + * Vars. Ordinarily rtindex should match the actual position of the RTE in + * its rangetable. * * The output lists go into *colnames and *colvars. * If only one of the two kinds of output list is needed, pass NULL for the @@ -2657,6 +2749,7 @@ addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, */ void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars) { @@ -2672,7 +2765,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, case RTE_RELATION: /* Ordinary relation RTE */ expandRelation(rte->relid, rte->eref, - rtindex, sublevels_up, location, + rtindex, sublevels_up, returning_type, location, include_dropped, colnames, colvars); break; case RTE_SUBQUERY: @@ -2719,6 +2812,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprTypmod((Node *) te->expr), exprCollation((Node *) te->expr), sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); @@ -2756,7 +2850,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, Assert(tupdesc); expandTupleDesc(tupdesc, rte->eref, rtfunc->funccolcount, atts_done, - rtindex, sublevels_up, location, + rtindex, sublevels_up, + returning_type, location, include_dropped, colnames, colvars); } else if (functypclass == TYPEFUNC_SCALAR) @@ -2776,6 +2871,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprTypmod(rtfunc->funcexpr), exprCollation(rtfunc->funcexpr), sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); @@ -2818,6 +2914,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, attrtypmod, attrcollation, sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); } @@ -2847,6 +2944,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, InvalidOid, sublevels_up); + varnode->varreturningtype = returning_type; *colvars = lappend(*colvars, varnode); } } @@ -2929,6 +3027,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, exprTypmod(avar), exprCollation(avar), sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); @@ -2984,6 +3083,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, varnode = makeVar(rtindex, varattno, coltype, coltypmod, colcoll, sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); @@ -3003,6 +3103,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, } break; case RTE_RESULT: + case RTE_GROUP: /* These expose no columns, so nothing to do */ break; default: @@ -3015,6 +3116,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, */ static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars) { @@ -3023,7 +3125,7 @@ expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, /* Get the tupledesc and turn it over to expandTupleDesc */ rel = relation_open(relid, AccessShareLock); expandTupleDesc(rel->rd_att, eref, rel->rd_att->natts, 0, - rtindex, sublevels_up, + rtindex, sublevels_up, returning_type, location, include_dropped, colnames, colvars); relation_close(rel, AccessShareLock); @@ -3041,6 +3143,7 @@ expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, static void expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars) { @@ -3101,6 +3204,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, attr->atttypid, attr->atttypmod, attr->attcollation, sublevels_up); + varnode->varreturningtype = returning_type; varnode->location = location; *colvars = lappend(*colvars, varnode); @@ -3153,6 +3257,7 @@ expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem, nscol->p_varcollid, sublevels_up); /* makeVar doesn't offer parameters for these, so set by hand: */ + var->varreturningtype = nscol->p_varreturningtype; var->varnosyn = nscol->p_varnosyn; var->varattnosyn = nscol->p_varattnosyn; var->location = location; @@ -3317,10 +3422,11 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum) case RTE_TABLEFUNC: case RTE_VALUES: case RTE_CTE: + case RTE_GROUP: /* - * Subselect, Table Functions, Values, CTE RTEs never have dropped - * columns + * Subselect, Table Functions, Values, CTE, GROUP RTEs never have + * dropped columns */ result = false; break; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index ee6fcd0503a03..4aba0d9d4d5cc 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -3,7 +3,7 @@ * parse_target.c * handle target lists * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -420,6 +420,9 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle, tle->resorigcol = ste->resorigcol; } break; + case RTE_GROUP: + /* We couldn't get here: the RTE_GROUP RTE has not been added */ + break; } } @@ -1547,8 +1550,8 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) *lvar; int i; - expandRTE(rte, var->varno, 0, var->location, false, - &names, &vars); + expandRTE(rte, var->varno, 0, var->varreturningtype, + var->location, false, &names, &vars); tupleDesc = CreateTemplateTupleDesc(list_length(vars)); i = 1; @@ -1681,6 +1684,12 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) /* else fall through to inspect the expression */ } break; + case RTE_GROUP: + + /* + * We couldn't get here: the RTE_GROUP RTE has not been added. + */ + break; } /* diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index c1a937a43b4df..7713bdc6af0a9 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -3,7 +3,7 @@ * parse_type.c * handle type operations for parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index d5c2b2ff0b0b3..62015431fdf1a 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -12,7 +12,7 @@ * respective utility commands. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/parser/parse_utilcmd.c @@ -32,7 +32,6 @@ #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/namespace.h" -#include "catalog/partition.h" #include "catalog/pg_am.h" #include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" @@ -59,8 +58,6 @@ #include "parser/parse_type.h" #include "parser/parse_utilcmd.h" #include "parser/parser.h" -#include "partitioning/partdesc.h" -#include "partitioning/partbounds.h" #include "rewrite/rewriteManip.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -84,6 +81,7 @@ typedef struct bool isalter; /* true if altering existing table */ List *columns; /* ColumnDef items */ List *ckconstraints; /* CHECK constraints */ + List *nnconstraints; /* NOT NULL constraints */ List *fkconstraints; /* FOREIGN KEY constraints */ List *ixconstraints; /* index-creating constraints */ List *likeclauses; /* LIKE clauses that need post-processing */ @@ -136,7 +134,7 @@ static void transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void setSchemaName(const char *context_schema, char **stmt_schema_name); -static void transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound); +static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd); static List *transformPartitionRangeBounds(ParseState *pstate, List *blist, Relation parent); static void validateInfiniteBounds(ParseState *pstate, List *blist); @@ -243,6 +241,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.isalter = false; cxt.columns = NIL; cxt.ckconstraints = NIL; + cxt.nnconstraints = NIL; cxt.fkconstraints = NIL; cxt.ixconstraints = NIL; cxt.likeclauses = NIL; @@ -306,6 +305,32 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) Assert(stmt->constraints == NIL); + /* + * Before processing index constraints, which could include a primary key, + * we must scan all not-null constraints to propagate the is_not_null flag + * to each corresponding ColumnDef. This is necessary because table-level + * not-null constraints have not been marked in each ColumnDef, and the PK + * processing code needs to know whether one constraint has already been + * declared in order not to declare a redundant one. + */ + foreach_node(Constraint, nn, cxt.nnconstraints) + { + char *colname = strVal(linitial(nn->keys)); + + foreach_node(ColumnDef, cd, cxt.columns) + { + /* not our column? */ + if (strcmp(cd->colname, colname) != 0) + continue; + /* Already marked not-null? Nothing to do */ + if (cd->is_not_null) + break; + /* Bingo, we're done for this constraint */ + cd->is_not_null = true; + break; + } + } + /* * Postprocess constraints that give rise to index definitions. */ @@ -343,6 +368,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) */ stmt->tableElts = cxt.columns; stmt->constraints = cxt.ckconstraints; + stmt->nnconstraints = cxt.nnconstraints; result = lappend(cxt.blist, stmt); result = list_concat(result, cxt.alist); @@ -368,30 +394,22 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, { ListCell *option; DefElem *nameEl = NULL; + DefElem *loggedEl = NULL; Oid snamespaceid; char *snamespace; char *sname; + char seqpersistence; CreateSeqStmt *seqstmt; AlterSeqStmt *altseqstmt; List *attnamelist; - int nameEl_idx = -1; /* Make a copy of this as we may end up modifying it in the code below */ seqoptions = list_copy(seqoptions); /* - * Determine namespace and name to use for the sequence. - * - * First, check if a sequence name was passed in as an option. This is - * used by pg_dump. Else, generate a name. - * - * Although we use ChooseRelationName, it's not guaranteed that the - * selected sequence name won't conflict; given sufficiently long field - * names, two different serial columns in the same table could be assigned - * the same sequence name, and we'd not notice since we aren't creating - * the sequence quite yet. In practice this seems quite unlikely to be a - * problem, especially since few people would need two serial columns in - * one table. + * Check for non-SQL-standard options (not supported within CREATE + * SEQUENCE, because they'd be redundant), and remove them from the + * seqoptions list if found. */ foreach(option, seqoptions) { @@ -402,12 +420,24 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, if (nameEl) errorConflictingDefElem(defel, cxt->pstate); nameEl = defel; - nameEl_idx = foreach_current_index(option); + seqoptions = foreach_delete_current(seqoptions, option); + } + else if (strcmp(defel->defname, "logged") == 0 || + strcmp(defel->defname, "unlogged") == 0) + { + if (loggedEl) + errorConflictingDefElem(defel, cxt->pstate); + loggedEl = defel; + seqoptions = foreach_delete_current(seqoptions, option); } } + /* + * Determine namespace and name to use for the sequence. + */ if (nameEl) { + /* Use specified name */ RangeVar *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg)); snamespace = rv->schemaname; @@ -421,11 +451,20 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, snamespace = get_namespace_name(snamespaceid); } sname = rv->relname; - /* Remove the SEQUENCE NAME item from seqoptions */ - seqoptions = list_delete_nth_cell(seqoptions, nameEl_idx); } else { + /* + * Generate a name. + * + * Although we use ChooseRelationName, it's not guaranteed that the + * selected sequence name won't conflict; given sufficiently long + * field names, two different serial columns in the same table could + * be assigned the same sequence name, and we'd not notice since we + * aren't creating the sequence quite yet. In practice this seems + * quite unlikely to be a problem, especially since few people would + * need two serial columns in one table. + */ if (cxt->rel) snamespaceid = RelationGetNamespace(cxt->rel); else @@ -446,6 +485,30 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, cxt->stmtType, sname, cxt->relation->relname, column->colname))); + /* + * Determine the persistence of the sequence. By default we copy the + * persistence of the table, but if LOGGED or UNLOGGED was specified, use + * that (as long as the table isn't TEMP). + * + * For CREATE TABLE, we get the persistence from cxt->relation, which + * comes from the CreateStmt in progress. For ALTER TABLE, the parser + * won't set cxt->relation->relpersistence, but we have cxt->rel as the + * existing table, so we copy the persistence from there. + */ + seqpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence; + if (loggedEl) + { + if (seqpersistence == RELPERSISTENCE_TEMP) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("cannot set logged status of a temporary sequence"), + parser_errposition(cxt->pstate, loggedEl->location))); + else if (strcmp(loggedEl->defname, "logged") == 0) + seqpersistence = RELPERSISTENCE_PERMANENT; + else + seqpersistence = RELPERSISTENCE_UNLOGGED; + } + /* * Build a CREATE SEQUENCE command to create the sequence object, and add * it to the list of things to be done before this CREATE/ALTER TABLE. @@ -453,16 +516,7 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column, seqstmt = makeNode(CreateSeqStmt); seqstmt->for_identity = for_identity; seqstmt->sequence = makeRangeVar(snamespace, sname, -1); - - /* - * Copy the persistence of the table. For CREATE TABLE, we get the - * persistence from cxt->relation, which comes from the CreateStmt in - * progress. For ALTER TABLE, the parser won't set - * cxt->relation->relpersistence, but we have cxt->rel as the existing - * table, so we copy the persistence from there. - */ - seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence; - + seqstmt->sequence->relpersistence = seqpersistence; seqstmt->options = seqoptions; /* @@ -541,7 +595,9 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) bool saw_default; bool saw_identity; bool saw_generated; - ListCell *clist; + bool need_notnull = false; + bool disallow_noinherit_notnull = false; + Constraint *notnull_constraint = NULL; cxt->columns = lappend(cxt->columns, column); @@ -638,28 +694,54 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) constraint->cooked_expr = NULL; column->constraints = lappend(column->constraints, constraint); - constraint = makeNode(Constraint); - constraint->contype = CONSTR_NOTNULL; - constraint->location = -1; - column->constraints = lappend(column->constraints, constraint); + /* have a not-null constraint added later */ + need_notnull = true; + disallow_noinherit_notnull = true; } /* Process column constraints, if any... */ transformConstraintAttrs(cxt, column->constraints); + /* + * First, scan the column's constraints to see if a not-null constraint + * that we add must be prevented from being NO INHERIT. This should be + * enforced only for PRIMARY KEY, not IDENTITY or SERIAL. However, if the + * not-null constraint is specified as a table constraint rather than as a + * column constraint, AddRelationNotNullConstraints would raise an error + * if a NO INHERIT mismatch is found. To avoid inconsistently disallowing + * it in the table constraint case but not the column constraint case, we + * disallow it here as well. Maybe AddRelationNotNullConstraints can be + * improved someday, so that it doesn't complain, and then we can remove + * the restriction for SERIAL and IDENTITY here as well. + */ + if (!disallow_noinherit_notnull) + { + foreach_node(Constraint, constraint, column->constraints) + { + switch (constraint->contype) + { + case CONSTR_IDENTITY: + case CONSTR_PRIMARY: + disallow_noinherit_notnull = true; + break; + default: + break; + } + } + } + + /* Now scan them again to do full processing */ saw_nullable = false; saw_default = false; saw_identity = false; saw_generated = false; - foreach(clist, column->constraints) + foreach_node(Constraint, constraint, column->constraints) { - Constraint *constraint = lfirst_node(Constraint, clist); - switch (constraint->contype) { case CONSTR_NULL: - if (saw_nullable && column->is_not_null) + if ((saw_nullable && column->is_not_null) || need_notnull) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"", @@ -671,6 +753,12 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) break; case CONSTR_NOTNULL: + if (cxt->ispartitioned && constraint->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not-null constraints on partitioned tables cannot be NO INHERIT")); + + /* Disallow conflicting [NOT] NULL markings */ if (saw_nullable && !column->is_not_null) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -678,8 +766,52 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) column->colname, cxt->relation->relname), parser_errposition(cxt->pstate, constraint->location))); - column->is_not_null = true; - saw_nullable = true; + + if (disallow_noinherit_notnull && constraint->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NO INHERIT declarations for not-null constraints on column \"%s\"", + column->colname)); + + /* + * If this is the first time we see this column being marked + * not-null, add the constraint entry and keep track of it. + * Also, remove previous markings that we need one. + * + * If this is a redundant not-null specification, just check + * that it doesn't conflict with what was specified earlier. + * + * Any conflicts with table constraints will be further + * checked in AddRelationNotNullConstraints(). + */ + if (!column->is_not_null) + { + column->is_not_null = true; + saw_nullable = true; + need_notnull = false; + + constraint->keys = list_make1(makeString(column->colname)); + notnull_constraint = constraint; + cxt->nnconstraints = lappend(cxt->nnconstraints, constraint); + } + else if (notnull_constraint) + { + if (constraint->conname && + notnull_constraint->conname && + strcmp(notnull_constraint->conname, constraint->conname) != 0) + elog(ERROR, "conflicting not-null constraint names \"%s\" and \"%s\"", + notnull_constraint->conname, constraint->conname); + + if (notnull_constraint->is_no_inherit != constraint->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NO INHERIT declarations for not-null constraints on column \"%s\"", + column->colname)); + + if (!notnull_constraint->conname && constraint->conname) + notnull_constraint->conname = constraint->conname; + } + break; case CONSTR_DEFAULT: @@ -729,16 +861,19 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) column->identity = constraint->generated_when; saw_identity = true; - /* An identity column is implicitly NOT NULL */ - if (saw_nullable && !column->is_not_null) + /* + * Identity columns are always NOT NULL, but we may have a + * constraint already. + */ + if (!saw_nullable) + need_notnull = true; + else if (!column->is_not_null) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"", column->colname, cxt->relation->relname), parser_errposition(cxt->pstate, constraint->location))); - column->is_not_null = true; - saw_nullable = true; break; } @@ -754,7 +889,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) column->colname, cxt->relation->relname), parser_errposition(cxt->pstate, constraint->location))); - column->generated = ATTRIBUTE_GENERATED_STORED; + column->generated = constraint->generated_kind; column->raw_default = constraint->raw_expr; Assert(constraint->cooked_expr == NULL); saw_generated = true; @@ -765,6 +900,15 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) break; case CONSTR_PRIMARY: + if (saw_nullable && !column->is_not_null) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"", + column->colname, cxt->relation->relname), + parser_errposition(cxt->pstate, + constraint->location))); + need_notnull = true; + if (cxt->isforeign) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -810,6 +954,8 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_DEFERRED: case CONSTR_ATTR_IMMEDIATE: + case CONSTR_ATTR_ENFORCED: + case CONSTR_ATTR_NOT_ENFORCED: /* transformConstraintAttrs took care of these */ break; @@ -844,6 +990,17 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column) constraint->location))); } + /* + * If we need a not-null constraint for PRIMARY KEY, SERIAL or IDENTITY, + * and one was not explicitly specified, add one now. + */ + if (need_notnull && !(saw_nullable && column->is_not_null)) + { + column->is_not_null = true; + notnull_constraint = makeNotNullConstraint(makeString(column->colname)); + cxt->nnconstraints = lappend(cxt->nnconstraints, notnull_constraint); + } + /* * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add * per-column foreign data wrapper options to this column after creation. @@ -913,6 +1070,15 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint) cxt->ckconstraints = lappend(cxt->ckconstraints, constraint); break; + case CONSTR_NOTNULL: + if (cxt->ispartitioned && constraint->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("not-null constraints on partitioned tables cannot be NO INHERIT")); + + cxt->nnconstraints = lappend(cxt->nnconstraints, constraint); + break; + case CONSTR_FOREIGN: if (cxt->isforeign) ereport(ERROR, @@ -924,12 +1090,13 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint) break; case CONSTR_NULL: - case CONSTR_NOTNULL: case CONSTR_DEFAULT: case CONSTR_ATTR_DEFERRABLE: case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_DEFERRED: case CONSTR_ATTR_IMMEDIATE: + case CONSTR_ATTR_ENFORCED: + case CONSTR_ATTR_NOT_ENFORCED: elog(ERROR, "invalid context for constraint type %d", constraint->contype); break; @@ -950,6 +1117,10 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint) * process at this point, add the TableLikeClause to cxt->likeclauses, which * will cause utility.c to call expandTableLikeClause() after the new * table has been created. + * + * Some options are ignored. For example, as foreign tables have no storage, + * these INCLUDING options have no effect: STORAGE, COMPRESSION, IDENTITY + * and INDEXES. Similarly, INCLUDING INDEXES is ignored from a view. */ static void transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause) @@ -964,12 +1135,6 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla setup_parser_errposition_callback(&pcbstate, cxt->pstate, table_like_clause->relation->location); - /* we could support LIKE in many cases, but worry about it another day */ - if (cxt->isforeign) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("LIKE is not supported for creating foreign tables"))); - /* Open the relation referenced by the LIKE clause */ relation = relation_openrv(table_like_clause->relation, AccessShareLock); @@ -1028,14 +1193,10 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla continue; /* - * Create a new column, which is marked as NOT inherited. - * - * For constraints, ONLY the not-null constraint is inherited by the - * new column definition per SQL99. + * Create a new column definition */ def = makeColumnDef(NameStr(attribute->attname), attribute->atttypid, attribute->atttypmod, attribute->attcollation); - def->is_not_null = attribute->attnotnull; /* * Add to column list @@ -1054,7 +1215,8 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla * Copy identity if requested */ if (attribute->attidentity && - (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY)) + (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY) && + !cxt->isforeign) { Oid seq_relid; List *seq_options; @@ -1073,14 +1235,16 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla } /* Likewise, copy storage if requested */ - if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE) + if ((table_like_clause->options & CREATE_TABLE_LIKE_STORAGE) && + !cxt->isforeign) def->storage = attribute->attstorage; else def->storage = 0; /* Likewise, copy compression if requested */ - if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0 - && CompressionMethodIsValid(attribute->attcompression)) + if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0 && + CompressionMethodIsValid(attribute->attcompression) && + !cxt->isforeign) def->compression = pstrdup(GetCompressionMethodName(attribute->attcompression)); else @@ -1104,14 +1268,28 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla } } + /* + * Reproduce not-null constraints, if any, by copying them. We do this + * regardless of options given. + */ + if (tupleDesc->constr && tupleDesc->constr->has_not_null) + { + List *lst; + + lst = RelationGetNotNullConstraints(RelationGetRelid(relation), false, + true); + cxt->nnconstraints = list_concat(cxt->nnconstraints, lst); + } + /* * We cannot yet deal with defaults, CHECK constraints, indexes, or * statistics, since we don't yet know what column numbers the copied * columns will have in the finished table. If any of those options are * specified, add the LIKE clause to cxt->likeclauses so that - * expandTableLikeClause will be called after we do know that. Also, - * remember the relation OID so that expandTableLikeClause is certain to - * open the same table. + * expandTableLikeClause will be called after we do know that. + * + * In order for this to work, we remember the relation OID so that + * expandTableLikeClause is certain to open the same table. */ if (table_like_clause->options & (CREATE_TABLE_LIKE_DEFAULTS | @@ -1260,6 +1438,8 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause) { char *ccname = constr->check[ccnum].ccname; char *ccbin = constr->check[ccnum].ccbin; + bool ccenforced = constr->check[ccnum].ccenforced; + bool ccvalid = constr->check[ccnum].ccvalid; bool ccnoinherit = constr->check[ccnum].ccnoinherit; Node *ccbin_node; bool found_whole_row; @@ -1289,13 +1469,14 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause) n->contype = CONSTR_CHECK; n->conname = pstrdup(ccname); n->location = -1; + n->is_enforced = ccenforced; + n->initially_valid = ccvalid; n->is_no_inherit = ccnoinherit; n->raw_expr = NULL; n->cooked_expr = nodeToString(ccbin_node); /* We can skip validation, since the new table should be empty. */ n->skip_validation = true; - n->initially_valid = true; atsubcmd = makeNode(AlterTableCmd); atsubcmd->subtype = AT_AddConstraint; @@ -1342,7 +1523,8 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause) * Process indexes if required. */ if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) && - relation->rd_rel->relhasindex) + relation->rd_rel->relhasindex && + childrel->rd_rel->relkind != RELKIND_FOREIGN_TABLE) { List *parent_indexes; ListCell *l; @@ -1442,7 +1624,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) Assert(ofTypename); - tuple = typenameType(NULL, ofTypename, NULL); + tuple = typenameType(cxt->pstate, ofTypename, NULL); check_of_type(tuple); ofTypeId = ((Form_pg_type) GETSTRUCT(tuple))->oid; ofTypename->typeOid = ofTypeId; /* cached for later */ @@ -1481,8 +1663,8 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) * with the index there. * * Unlike transformIndexConstraint, we don't make any effort to force primary - * key columns to be NOT NULL. The larger cloning process this is part of - * should have cloned their NOT NULL status separately (and DefineIndex will + * key columns to be not-null. The larger cloning process this is part of + * should have cloned their not-null status separately (and DefineIndex will * complain if that fails to happen). */ IndexStmt * @@ -1558,6 +1740,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, index->unique = idxrec->indisunique; index->nulls_not_distinct = idxrec->indnullsnotdistinct; index->primary = idxrec->indisprimary; + index->iswithoutoverlaps = (idxrec->indisprimary || idxrec->indisunique) && idxrec->indisexclusion; index->transformed = true; /* don't need transformIndexStmt */ index->concurrent = false; index->if_not_exists = false; @@ -1607,7 +1790,9 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, int nElems; int i; - Assert(conrec->contype == CONSTRAINT_EXCLUSION); + Assert(conrec->contype == CONSTRAINT_EXCLUSION || + (index->iswithoutoverlaps && + (conrec->contype == CONSTRAINT_PRIMARY || conrec->contype == CONSTRAINT_UNIQUE))); /* Extract operator OIDs from the pg_constraint tuple */ datum = SysCacheGetAttrNotNull(CONSTROID, ht_constr, Anum_pg_constraint_conexclop); @@ -2038,10 +2223,10 @@ transformIndexConstraints(CreateStmtContext *cxt) ListCell *lc; /* - * Run through the constraints that need to generate an index. For PRIMARY - * KEY, mark each column as NOT NULL and create an index. For UNIQUE or - * EXCLUDE, create an index as for PRIMARY KEY, but do not insist on NOT - * NULL. + * Run through the constraints that need to generate an index, and do so. + * + * For PRIMARY KEY, this queues not-null constraints for each column, if + * needed. */ foreach(lc, cxt->ixconstraints) { @@ -2115,9 +2300,7 @@ transformIndexConstraints(CreateStmtContext *cxt) } /* - * Now append all the IndexStmts to cxt->alist. If we generated an ALTER - * TABLE SET NOT NULL statement to support a primary key, it's already in - * cxt->alist. + * Now append all the IndexStmts to cxt->alist. */ cxt->alist = list_concat(cxt->alist, finalindexlist); } @@ -2125,18 +2308,15 @@ transformIndexConstraints(CreateStmtContext *cxt) /* * transformIndexConstraint * Transform one UNIQUE, PRIMARY KEY, or EXCLUDE constraint for - * transformIndexConstraints. + * transformIndexConstraints. An IndexStmt is returned. * - * We return an IndexStmt. For a PRIMARY KEY constraint, we additionally - * produce not-null constraints, either by marking ColumnDefs in cxt->columns - * as is_not_null or by adding an ALTER TABLE SET NOT NULL command to - * cxt->alist. + * For a PRIMARY KEY constraint, we additionally create not-null constraints + * for columns that don't already have them. */ static IndexStmt * transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) { IndexStmt *index; - List *notnullcmds = NIL; ListCell *lc; index = makeNode(IndexStmt); @@ -2160,6 +2340,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) } index->nulls_not_distinct = constraint->nulls_not_distinct; index->isconstraint = true; + index->iswithoutoverlaps = constraint->without_overlaps; index->deferrable = constraint->deferrable; index->initdeferred = constraint->initdeferred; @@ -2252,6 +2433,11 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) errmsg("index \"%s\" is not valid", index_name), parser_errposition(cxt->pstate, constraint->location))); + /* + * Today we forbid non-unique indexes, but we could permit GiST + * indexes whose last entry is a range type and use that to create a + * WITHOUT OVERLAPS constraint (i.e. a temporal constraint). + */ if (!index_form->indisunique) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -2286,11 +2472,10 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) parser_errposition(cxt->pstate, constraint->location))); /* - * Insist on it being a btree. That's the only kind that supports - * uniqueness at the moment anyway; but we must have an index that - * exactly matches what you'd get from plain ADD CONSTRAINT syntax, - * else dump and reload will produce a different index (breaking - * pg_upgrade in particular). + * Insist on it being a btree. We must have an index that exactly + * matches what you'd get from plain ADD CONSTRAINT syntax, else dump + * and reload will produce a different index (breaking pg_upgrade in + * particular). */ if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false)) ereport(ERROR, @@ -2350,6 +2535,12 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) errdetail("Cannot create a primary key or unique constraint using such an index."), parser_errposition(cxt->pstate, constraint->location))); + /* If a PK, ensure the columns get not null constraints */ + if (constraint->contype == CONSTR_PRIMARY) + cxt->nnconstraints = + lappend(cxt->nnconstraints, + makeNotNullConstraint(makeString(attname))); + constraint->keys = lappend(constraint->keys, makeString(attname)); } else @@ -2388,7 +2579,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) * For UNIQUE and PRIMARY KEY, we just have a list of column names. * * Make sure referenced keys exist. If we are making a PRIMARY KEY index, - * also make sure they are NOT NULL. + * also make sure they are not-null. For WITHOUT OVERLAPS constraints, we + * make sure the last part is a range or multirange. */ else { @@ -2396,10 +2588,10 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) { char *key = strVal(lfirst(lc)); bool found = false; - bool forced_not_null = false; ColumnDef *column = NULL; ListCell *columns; IndexElem *iparam; + Oid typid = InvalidOid; /* Make sure referenced column exists. */ foreach(columns, cxt->columns) @@ -2411,27 +2603,57 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) break; } } + if (!found) + column = NULL; + if (found) { /* - * column is defined in the new table. For PRIMARY KEY, we - * can apply the not-null constraint cheaply here ... unless - * the column is marked is_from_type, in which case marking it - * here would be ineffective (see MergeAttributes). + * column is defined in the new table. For CREATE TABLE with + * a PRIMARY KEY, we can apply the not-null constraint cheaply + * here. If the not-null constraint already exists, we can + * (albeit not so cheaply) verify that it's not a NO INHERIT + * constraint. + * + * Note that ALTER TABLE never needs either check, because + * those constraints have already been added by + * ATPrepAddPrimaryKey. */ if (constraint->contype == CONSTR_PRIMARY && - !column->is_from_type) + !cxt->isalter) { - column->is_not_null = true; - forced_not_null = true; + if (column->is_not_null) + { + foreach_node(Constraint, nn, cxt->nnconstraints) + { + if (strcmp(strVal(linitial(nn->keys)), key) == 0) + { + if (nn->is_no_inherit) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting NO INHERIT declaration for not-null constraint on column \"%s\"", + key)); + break; + } + } + } + else + { + column->is_not_null = true; + cxt->nnconstraints = + lappend(cxt->nnconstraints, + makeNotNullConstraint(makeString(key))); + } } + else if (constraint->contype == CONSTR_PRIMARY) + Assert(column->is_not_null); } else if (SystemAttributeByName(key) != NULL) { /* * column will be a system column in the new table, so accept * it. System columns can't ever be null, so no need to worry - * about PRIMARY/not-null constraint. + * about PRIMARY/NOT NULL constraint. */ found = true; } @@ -2466,14 +2688,12 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) if (strcmp(key, inhname) == 0) { found = true; + typid = inhattr->atttypid; - /* - * It's tempting to set forced_not_null if the - * parent column is already NOT NULL, but that - * seems unsafe because the column's NOT NULL - * marking might disappear between now and - * execution. Do the runtime check to be safe. - */ + if (constraint->contype == CONSTR_PRIMARY) + cxt->nnconstraints = + lappend(cxt->nnconstraints, + makeNotNullConstraint(makeString(pstrdup(inhname)))); break; } } @@ -2515,6 +2735,50 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) } } + /* + * The WITHOUT OVERLAPS part (if any) must be a range or + * multirange type. + */ + if (constraint->without_overlaps && lc == list_last_cell(constraint->keys)) + { + if (!found && cxt->isalter) + { + /* + * Look up the column type on existing table. If we can't + * find it, let things fail in DefineIndex. + */ + Relation rel = cxt->rel; + + for (int i = 0; i < rel->rd_att->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i); + const char *attname; + + if (attr->attisdropped) + break; + + attname = NameStr(attr->attname); + if (strcmp(attname, key) == 0) + { + found = true; + typid = attr->atttypid; + break; + } + } + } + if (found) + { + if (!OidIsValid(typid) && column) + typid = typenameTypeId(NULL, column->typeName); + + if (!OidIsValid(typid) || !(type_is_range(typid) || type_is_multirange(typid))) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("column \"%s\" in WITHOUT OVERLAPS is not a range or multirange type", key), + parser_errposition(cxt->pstate, constraint->location))); + } + } + /* OK, add it to the index definition */ iparam = makeNode(IndexElem); iparam->name = pstrdup(key); @@ -2526,20 +2790,24 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) iparam->ordering = SORTBY_DEFAULT; iparam->nulls_ordering = SORTBY_NULLS_DEFAULT; index->indexParams = lappend(index->indexParams, iparam); + } + if (constraint->without_overlaps) + { /* - * For a primary-key column, also create an item for ALTER TABLE - * SET NOT NULL if we couldn't ensure it via is_not_null above. + * This enforces that there is at least one equality column + * besides the WITHOUT OVERLAPS columns. This is per SQL + * standard. XXX Do we need this? */ - if (constraint->contype == CONSTR_PRIMARY && !forced_not_null) - { - AlterTableCmd *notnullcmd = makeNode(AlterTableCmd); + if (list_length(constraint->keys) < 2) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("constraint using WITHOUT OVERLAPS needs at least two columns")); - notnullcmd->subtype = AT_SetNotNull; - notnullcmd->name = pstrdup(key); - notnullcmds = lappend(notnullcmds, notnullcmd); - } + /* WITHOUT OVERLAPS requires a GiST index */ + index->accessMethod = "gist"; } + } /* @@ -2640,22 +2908,6 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) index->indexIncludingParams = lappend(index->indexIncludingParams, iparam); } - /* - * If we found anything that requires run-time SET NOT NULL, build a full - * ALTER TABLE command for that and add it to cxt->alist. - */ - if (notnullcmds) - { - AlterTableStmt *alterstmt = makeNode(AlterTableStmt); - - alterstmt->relation = copyObject(cxt->relation); - alterstmt->cmds = notnullcmds; - alterstmt->objtype = OBJECT_TABLE; - alterstmt->missing_ok = false; - - cxt->alist = lappend(cxt->alist, alterstmt); - } - return index; } @@ -2677,9 +2929,11 @@ transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation) return; /* - * If creating a new table (but not a foreign table), we can safely skip - * validation of check constraints, and nonetheless mark them valid. (This - * will override any user-supplied NOT VALID flag.) + * When creating a new table (but not a foreign table), we can safely skip + * the validation of check constraints and mark them as valid based on the + * constraint enforcement flag, since NOT ENFORCED constraints must always + * be marked as NOT VALID. (This will override any user-supplied NOT VALID + * flag.) */ if (skipValidation) { @@ -2688,7 +2942,7 @@ transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation) Constraint *constraint = (Constraint *) lfirst(ckclist); constraint->skip_validation = true; - constraint->initially_valid = true; + constraint->initially_valid = constraint->is_enforced; } } } @@ -2708,8 +2962,10 @@ transformFKConstraints(CreateStmtContext *cxt, /* * If CREATE TABLE or adding a column with NULL default, we can safely - * skip validation of FK constraints, and nonetheless mark them valid. - * (This will override any user-supplied NOT VALID flag.) + * skip validation of FK constraints, and mark them as valid based on the + * constraint enforcement flag, since NOT ENFORCED constraints must always + * be marked as NOT VALID. (This will override any user-supplied NOT VALID + * flag.) */ if (skipValidation) { @@ -2718,7 +2974,7 @@ transformFKConstraints(CreateStmtContext *cxt, Constraint *constraint = (Constraint *) lfirst(fkclist); constraint->skip_validation = true; - constraint->initially_valid = true; + constraint->initially_valid = constraint->is_enforced; } } @@ -3232,160 +3488,6 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString, } -/* - * checkPartition - * Check that partRelOid is an oid of partition of the parent table rel - */ -static void -checkPartition(Relation rel, Oid partRelOid) -{ - Relation partRel; - - partRel = relation_open(partRelOid, AccessShareLock); - - if (partRel->rd_rel->relkind != RELKIND_RELATION) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table", - RelationGetRelationName(partRel)))); - - if (!partRel->rd_rel->relispartition) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a partition", - RelationGetRelationName(partRel)))); - - if (get_partition_parent(partRelOid, false) != RelationGetRelid(rel)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_TABLE), - errmsg("relation \"%s\" is not a partition of relation \"%s\"", - RelationGetRelationName(partRel), - RelationGetRelationName(rel)))); - - /* Permissions checks */ - if (!object_ownercheck(RelationRelationId, RelationGetRelid(partRel), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(partRel->rd_rel->relkind), - RelationGetRelationName(partRel)); - - relation_close(partRel, AccessShareLock); -} - -/* - * transformPartitionCmdForSplit - * Analyze the ALTER TABLE ... SPLIT PARTITION command - * - * For each new partition sps->bound is set to the transformed value of bound. - * Does checks for bounds of new partitions. - */ -static void -transformPartitionCmdForSplit(CreateStmtContext *cxt, PartitionCmd *partcmd) -{ - Relation parent = cxt->rel; - Oid splitPartOid; - ListCell *listptr; - - if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("\"%s\" is not a partitioned table", RelationGetRelationName(parent)))); - - /* Transform partition bounds for all partitions in the list: */ - foreach(listptr, partcmd->partlist) - { - SinglePartitionSpec *sps = (SinglePartitionSpec *) lfirst(listptr); - - cxt->partbound = NULL; - transformPartitionCmd(cxt, sps->bound); - /* Assign transformed value of the partition bound. */ - sps->bound = cxt->partbound; - } - - splitPartOid = RangeVarGetRelid(partcmd->name, NoLock, false); - - checkPartition(parent, splitPartOid); - - /* Then we should check partitions with transformed bounds. */ - check_partitions_for_split(parent, splitPartOid, partcmd->name, partcmd->partlist, cxt->pstate); -} - - -/* - * transformPartitionCmdForMerge - * Analyze the ALTER TABLE ... MERGE PARTITIONS command - * - * Does simple checks for merged partitions. Calculates bound of resulting - * partition. - */ -static void -transformPartitionCmdForMerge(CreateStmtContext *cxt, PartitionCmd *partcmd) -{ - Oid defaultPartOid; - Oid partOid; - Relation parent = cxt->rel; - PartitionKey key; - char strategy; - ListCell *listptr, - *listptr2; - bool isDefaultPart = false; - List *partOids = NIL; - - if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("\"%s\" is not a partitioned table", RelationGetRelationName(parent)))); - - key = RelationGetPartitionKey(parent); - strategy = get_partition_strategy(key); - - if (strategy == PARTITION_STRATEGY_HASH) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("partition of hash-partitioned table cannot be merged"))); - - /* Is current partition a DEFAULT partition? */ - defaultPartOid = get_default_oid_from_partdesc( - RelationGetPartitionDesc(parent, true)); - - foreach(listptr, partcmd->partlist) - { - RangeVar *name = (RangeVar *) lfirst(listptr); - - /* Partitions in the list should have different names. */ - for_each_cell(listptr2, partcmd->partlist, lnext(partcmd->partlist, listptr)) - { - RangeVar *name2 = (RangeVar *) lfirst(listptr2); - - if (equal(name, name2)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_TABLE), - errmsg("partition with name \"%s\" is already used", name->relname)), - parser_errposition(cxt->pstate, name2->location)); - } - - /* Search DEFAULT partition in the list. */ - partOid = RangeVarGetRelid(name, NoLock, false); - if (partOid == defaultPartOid) - isDefaultPart = true; - - checkPartition(parent, partOid); - - partOids = lappend_oid(partOids, partOid); - } - - /* Allocate bound of resulting partition. */ - Assert(partcmd->bound == NULL); - partcmd->bound = makeNode(PartitionBoundSpec); - - /* Fill partition bound. */ - partcmd->bound->strategy = strategy; - partcmd->bound->location = -1; - partcmd->bound->is_default = isDefaultPart; - if (!isDefaultPart) - calculate_partition_bound_for_merge(parent, partcmd->partlist, - partOids, partcmd->bound, - cxt->pstate); -} - /* * transformAlterTableStmt - * parse analysis for ALTER TABLE @@ -3448,6 +3550,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, cxt.isalter = true; cxt.columns = NIL; cxt.ckconstraints = NIL; + cxt.nnconstraints = NIL; cxt.fkconstraints = NIL; cxt.ixconstraints = NIL; cxt.likeclauses = NIL; @@ -3654,7 +3757,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, { PartitionCmd *partcmd = (PartitionCmd *) cmd->def; - transformPartitionCmd(&cxt, partcmd->bound); + transformPartitionCmd(&cxt, partcmd); /* assign transformed value of the partition bound */ partcmd->bound = cxt.partbound; } @@ -3662,24 +3765,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmds = lappend(newcmds, cmd); break; - case AT_SplitPartition: - case AT_MergePartitions: - { - PartitionCmd *partcmd = (PartitionCmd *) cmd->def; - - if (list_length(partcmd->partlist) < 2) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("list of new partitions should contain at least two items"))); - - if (cmd->subtype == AT_SplitPartition) - transformPartitionCmdForSplit(&cxt, partcmd); - else - transformPartitionCmdForMerge(&cxt, partcmd); - newcmds = lappend(newcmds, cmd); - break; - } - default: /* @@ -3715,9 +3800,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, Node *istmt = (Node *) lfirst(l); /* - * We assume here that cxt.alist contains only IndexStmts and possibly - * ALTER TABLE SET NOT NULL statements generated from primary key - * constraints. We absorb the subcommands of the latter directly. + * We assume here that cxt.alist contains only IndexStmts generated + * from primary key constraints. */ if (IsA(istmt, IndexStmt)) { @@ -3729,30 +3813,31 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmd->def = (Node *) idxstmt; newcmds = lappend(newcmds, newcmd); } - else if (IsA(istmt, AlterTableStmt)) - { - AlterTableStmt *alterstmt = (AlterTableStmt *) istmt; - - newcmds = list_concat(newcmds, alterstmt->cmds); - } else elog(ERROR, "unexpected stmt type %d", (int) nodeTag(istmt)); } cxt.alist = NIL; - /* Append any CHECK or FK constraints to the commands list */ - foreach(l, cxt.ckconstraints) + /* Append any CHECK, NOT NULL or FK constraints to the commands list */ + foreach_node(Constraint, def, cxt.ckconstraints) + { + newcmd = makeNode(AlterTableCmd); + newcmd->subtype = AT_AddConstraint; + newcmd->def = (Node *) def; + newcmds = lappend(newcmds, newcmd); + } + foreach_node(Constraint, def, cxt.nnconstraints) { newcmd = makeNode(AlterTableCmd); newcmd->subtype = AT_AddConstraint; - newcmd->def = (Node *) lfirst_node(Constraint, l); + newcmd->def = (Node *) def; newcmds = lappend(newcmds, newcmd); } - foreach(l, cxt.fkconstraints) + foreach_node(Constraint, def, cxt.fkconstraints) { newcmd = makeNode(AlterTableCmd); newcmd->subtype = AT_AddConstraint; - newcmd->def = (Node *) lfirst_node(Constraint, l); + newcmd->def = (Node *) def; newcmds = lappend(newcmds, newcmd); } @@ -3786,6 +3871,7 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) Constraint *lastprimarycon = NULL; bool saw_deferrability = false; bool saw_initially = false; + bool saw_enforced = false; ListCell *clist; #define SUPPORTS_ATTRS(node) \ @@ -3881,12 +3967,51 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) lastprimarycon->initdeferred = false; break; + case CONSTR_ATTR_ENFORCED: + if (lastprimarycon == NULL || + (lastprimarycon->contype != CONSTR_CHECK && + lastprimarycon->contype != CONSTR_FOREIGN)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced ENFORCED clause"), + parser_errposition(cxt->pstate, con->location))); + if (saw_enforced) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"), + parser_errposition(cxt->pstate, con->location))); + saw_enforced = true; + lastprimarycon->is_enforced = true; + break; + + case CONSTR_ATTR_NOT_ENFORCED: + if (lastprimarycon == NULL || + (lastprimarycon->contype != CONSTR_CHECK && + lastprimarycon->contype != CONSTR_FOREIGN)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced NOT ENFORCED clause"), + parser_errposition(cxt->pstate, con->location))); + if (saw_enforced) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"), + parser_errposition(cxt->pstate, con->location))); + saw_enforced = true; + lastprimarycon->is_enforced = false; + + /* A NOT ENFORCED constraint must be marked as invalid. */ + lastprimarycon->skip_validation = true; + lastprimarycon->initially_valid = false; + break; + default: /* Otherwise it's not an attribute */ lastprimarycon = con; /* reset flags for new primary node */ saw_deferrability = false; saw_initially = false; + saw_enforced = false; break; } } @@ -4070,13 +4195,13 @@ setSchemaName(const char *context_schema, char **stmt_schema_name) /* * transformPartitionCmd - * Analyze the ATTACH/DETACH/SPLIT PARTITION command + * Analyze the ATTACH/DETACH PARTITION command * - * In case of the ATTACH/SPLIT PARTITION command, cxt->partbound is set to the - * transformed value of bound. + * In case of the ATTACH PARTITION command, cxt->partbound is set to the + * transformed value of cmd->bound. */ static void -transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound) +transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd) { Relation parentRel = cxt->rel; @@ -4085,9 +4210,9 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound) case RELKIND_PARTITIONED_TABLE: /* transform the partition bound, if any */ Assert(RelationGetPartitionKey(parentRel) != NULL); - if (bound != NULL) + if (cmd->bound != NULL) cxt->partbound = transformPartitionBound(cxt->pstate, parentRel, - bound); + cmd->bound); break; case RELKIND_PARTITIONED_INDEX: @@ -4095,7 +4220,7 @@ transformPartitionCmd(CreateStmtContext *cxt, PartitionBoundSpec *bound) * A partitioned index cannot have a partition bound set. ALTER * INDEX prevents that with its grammar, but not ALTER TABLE. */ - if (bound != NULL) + if (cmd->bound != NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("\"%s\" is not a partitioned table", diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index 118488c3f30f2..33a040506b47f 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -10,7 +10,7 @@ * analyze.c and related files. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index f74059e7b0be5..08990831fe81a 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -22,7 +22,7 @@ * Postgres 9.2, this check is made automatically by the Makefile.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -89,12 +89,6 @@ const uint16 ScanKeywordTokens[] = { */ #define YYSTYPE core_YYSTYPE -/* - * Set the type of yyextra. All state variables used by the scanner should - * be in yyextra, *not* statically allocated. - */ -#define YY_EXTRA_TYPE core_yy_extra_type * - /* * Each call to yylex must set yylloc to the location of the found token * (expressed as a byte offset from the start of the input text). @@ -136,15 +130,6 @@ static void addunicode(pg_wchar c, yyscan_t yyscanner); static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner); static void check_escape_warning(core_yyscan_t yyscanner); -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int core_yyget_column(yyscan_t yyscanner); -extern void core_yyset_column(int column_no, yyscan_t yyscanner); - %} %option reentrant @@ -161,6 +146,7 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner); %option noyyfree %option warn %option prefix="core_yy" +%option extra-type="core_yy_extra_type *" /* * OK, here is a short description of lex/flex rules behavior. @@ -412,16 +398,30 @@ numericfail {decinteger}\.\. real ({decinteger}|{numeric})[Ee][-+]?{decinteger} realfail ({decinteger}|{numeric})[Ee][-+] -decinteger_junk {decinteger}{ident_start} -hexinteger_junk {hexinteger}{ident_start} -octinteger_junk {octinteger}{ident_start} -bininteger_junk {bininteger}{ident_start} -numeric_junk {numeric}{ident_start} -real_junk {real}{ident_start} - /* Positional parameters don't accept underscores. */ param \${decdigit}+ -param_junk \${decdigit}+{ident_start} + +/* + * An identifier immediately following an integer literal is disallowed because + * in some cases it's ambiguous what is meant: for example, 0x1234 could be + * either a hexinteger or a decinteger "0" and an identifier "x1234". We can + * detect such problems by seeing if integer_junk matches a longer substring + * than any of the XXXinteger patterns (decinteger, hexinteger, octinteger, + * bininteger). One "junk" pattern is sufficient because + * {decinteger}{identifier} will match all the same strings we'd match with + * {hexinteger}{identifier} etc. + * + * Note that the rule for integer_junk must appear after the ones for + * XXXinteger to make this work correctly: 0x1234 will match both hexinteger + * and integer_junk, and we need hexinteger to be chosen in that case. + * + * Also disallow strings matched by numeric_junk, real_junk and param_junk + * for consistency. + */ +integer_junk {decinteger}{identifier} +numeric_junk {numeric}{identifier} +real_junk {real}{identifier} +param_junk \${decdigit}+{identifier} other . @@ -1055,19 +1055,7 @@ other . SET_YYLLOC(); yyerror("trailing junk after numeric literal"); } -{decinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{hexinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{octinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{bininteger_junk} { +{integer_junk} { SET_YYLLOC(); yyerror("trailing junk after numeric literal"); } @@ -1203,7 +1191,7 @@ setup_scanner_errposition_callback(ScannerCallbackState *scbstate, scbstate->yyscanner = yyscanner; scbstate->location = location; scbstate->errcallback.callback = scb_error_callback; - scbstate->errcallback.arg = (void *) scbstate; + scbstate->errcallback.arg = scbstate; scbstate->errcallback.previous = error_context_stack; error_context_stack = &scbstate->errcallback; } @@ -1466,9 +1454,9 @@ check_escape_warning(core_yyscan_t yyscanner) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of escape in a string literal"), - errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), + errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), lexer_errposition())); - yyextra->warn_on_first_escape = false; /* warn only once per string */ + yyextra->warn_on_first_escape = false; /* warn only once per string */ } /* diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c index 164e61ef8bb30..2feb2b6cf5a96 100644 --- a/src/backend/parser/scansup.c +++ b/src/backend/parser/scansup.c @@ -3,7 +3,7 @@ * scansup.c * scanner support routines used by the core lexer * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/partitioning/meson.build b/src/backend/partitioning/meson.build index 34aec359f83ae..126655ef58fde 100644 --- a/src/backend/partitioning/meson.build +++ b/src/backend/partitioning/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'partbounds.c', diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index 4eda59767ce7b..4bdc2941efb21 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -3,7 +3,7 @@ * partbounds.c * Support routines for manipulating partition bounds * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -3214,9 +3214,8 @@ check_new_partition_bound(char *relname, Relation parent, PartitionRangeDatum *datum; /* - * Point to problematic key in the list of lower - * datums; if we have equality, point to the first - * one. + * Point to problematic key in the lower datums list; + * if we have equality, point to the first one. */ datum = cmpval == 0 ? linitial(spec->lowerdatums) : list_nth(spec->lowerdatums, abs(cmpval) - 1); @@ -4978,899 +4977,3 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) PG_RETURN_BOOL(rowHash % modulus == remainder); } - -/* - * check_two_partitions_bounds_range - * - * (function for BY RANGE partitioning) - * - * This is a helper function for check_partitions_for_split() and - * calculate_partition_bound_for_merge(). - * This function compares upper bound of first_bound and lower bound of - * second_bound. These bounds should be equal except when - * "defaultPart == true" (this means that one of split partitions is DEFAULT). - * In this case upper bound of first_bound can be less than lower bound of - * second_bound because space between these bounds will be included in - * DEFAULT partition. - * - * parent: partitioned table - * first_name: name of first partition - * first_bound: bound of first partition - * second_name: name of second partition - * second_bound: bound of second partition - * defaultPart: true if one of split partitions is DEFAULT - * pstate: pointer to ParseState struct for determining error position - */ -static void -check_two_partitions_bounds_range(Relation parent, - RangeVar *first_name, - PartitionBoundSpec *first_bound, - RangeVar *second_name, - PartitionBoundSpec *second_bound, - bool defaultPart, - ParseState *pstate) -{ - PartitionKey key = RelationGetPartitionKey(parent); - PartitionRangeBound *first_upper; - PartitionRangeBound *second_lower; - int cmpval; - - Assert(key->strategy == PARTITION_STRATEGY_RANGE); - - first_upper = make_one_partition_rbound(key, -1, first_bound->upperdatums, false); - second_lower = make_one_partition_rbound(key, -1, second_bound->lowerdatums, true); - - /* - * lower1=false (the second to last argument) for correct comparison of - * lower and upper bounds. - */ - cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, - key->partcollation, - second_lower->datums, second_lower->kind, - false, first_upper); - if ((!defaultPart && cmpval) || (defaultPart && cmpval < 0)) - { - PartitionRangeDatum *datum = linitial(second_bound->lowerdatums); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("lower bound of partition \"%s\" conflicts with upper bound of previous partition \"%s\"", - second_name->relname, first_name->relname), - parser_errposition(pstate, datum->location))); - } -} - -/* - * check_partitions_not_overlap_list - * - * (function for BY LIST partitioning) - * - * This is a helper function for check_partitions_for_split(). - * Checks that the values of the new partitions do not overlap. - * - * parent: partitioned table - * parts: array of SinglePartitionSpec structs with info about split partitions - * nparts: size of array "parts" - */ -static void -check_partitions_not_overlap_list(Relation parent, - SinglePartitionSpec **parts, - int nparts, - ParseState *pstate) -{ - PartitionKey key PG_USED_FOR_ASSERTS_ONLY = RelationGetPartitionKey(parent); - int overlap_location = -1; - int i, - j; - SinglePartitionSpec *sps1, - *sps2; - List *overlap; - - Assert(key->strategy == PARTITION_STRATEGY_LIST); - - for (i = 0; i < nparts; i++) - { - sps1 = parts[i]; - - for (j = i + 1; j < nparts; j++) - { - sps2 = parts[j]; - - /* - * Calculate intersection between values of two partitions. - */ - overlap = list_intersection(sps1->bound->listdatums, - sps2->bound->listdatums); - if (list_length(overlap) > 0) - { - Const *val = (Const *) lfirst(list_head(overlap)); - - overlap_location = val->location; - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partition \"%s\" would overlap with another new partition \"%s\"", - sps1->name->relname, sps2->name->relname), - parser_errposition(pstate, overlap_location))); - } - } - } -} - -/* - * get_partition_bound_spec - * - * Returns description of partition with Oid "partOid" and name "name". - * - * partOid: partition Oid - * name: partition name - */ -static PartitionBoundSpec * -get_partition_bound_spec(Oid partOid, RangeVar *name) -{ - HeapTuple tuple; - Datum datum; - bool isnull; - PartitionBoundSpec *boundspec = NULL; - - /* Try fetching the tuple from the catcache, for speed. */ - tuple = SearchSysCache1(RELOID, partOid); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for relation \"%s\"", - name->relname); - - datum = SysCacheGetAttr(RELOID, tuple, - Anum_pg_class_relpartbound, - &isnull); - if (isnull) - elog(ERROR, "partition bound for relation \"%s\" is null", - name->relname); - - boundspec = stringToNode(TextDatumGetCString(datum)); - - if (!IsA(boundspec, PartitionBoundSpec)) - elog(ERROR, "expected PartitionBoundSpec for relation \"%s\"", - name->relname); - - ReleaseSysCache(tuple); - return boundspec; -} - -/* - * check_partition_bounds_for_split_range - * - * (function for BY RANGE partitioning) - * - * Checks that bounds of new partition "spec" are inside bounds of split - * partition (with Oid splitPartOid). If first=true (this means that "spec" is - * the first of new partitions) then lower bound of "spec" should be equal (or - * greater than or equal in case defaultPart=true) to lower bound of split - * partition. If last=true (this means that "spec" is the last of new - * partitions) then upper bound of "spec" should be equal (or less than or - * equal in case defaultPart=true) to upper bound of split partition. - * - * parent: partitioned table - * relname: name of the new partition - * spec: bounds specification of the new partition - * splitPartOid: split partition Oid - * splitPartName: split partition name - * first: true in case new partition "spec" is first of new partitions - * last: true in case new partition "spec" is last of new partitions - * defaultPart: true in case partitioned table has DEFAULT partition - * pstate: pointer to ParseState struct for determine error position - */ -static void -check_partition_bounds_for_split_range(Relation parent, - char *relname, - PartitionBoundSpec *spec, - Oid splitPartOid, - RangeVar *splitPartName, - bool first, - bool last, - bool defaultPart, - ParseState *pstate) -{ - PartitionKey key = RelationGetPartitionKey(parent); - PartitionRangeBound *lower, - *upper; - int cmpval; - - Assert(key->strategy == PARTITION_STRATEGY_RANGE); - Assert(spec->strategy == PARTITION_STRATEGY_RANGE); - - lower = make_one_partition_rbound(key, -1, spec->lowerdatums, true); - upper = make_one_partition_rbound(key, -1, spec->upperdatums, false); - - /* - * First check if the resulting range would be empty with specified lower - * and upper bounds. partition_rbound_cmp cannot return zero here, since - * the lower-bound flags are different. - */ - cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, - key->partcollation, - lower->datums, lower->kind, - true, upper); - Assert(cmpval != 0); - if (cmpval > 0) - { - /* Point to problematic key in the lower datums list. */ - PartitionRangeDatum *datum = list_nth(spec->lowerdatums, cmpval - 1); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("empty range bound specified for partition \"%s\"", - relname), - errdetail("Specified lower bound %s is greater than or equal to upper bound %s.", - get_range_partbound_string(spec->lowerdatums), - get_range_partbound_string(spec->upperdatums)), - parser_errposition(pstate, datum->location))); - } - - /* Need to check first and last partitions (from set of new partitions) */ - if (first || last) - { - PartitionBoundSpec *split_spec = get_partition_bound_spec(splitPartOid, splitPartName); - PartitionRangeDatum *datum; - - if (first) - { - PartitionRangeBound *split_lower; - - split_lower = make_one_partition_rbound(key, -1, split_spec->lowerdatums, true); - - cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, - key->partcollation, - lower->datums, lower->kind, - true, split_lower); - - /* - * Lower bound of "spec" should be equal (or greater than or equal - * in case defaultPart=true) to lower bound of split partition. - */ - if (!defaultPart) - { - if (cmpval != 0) - { - datum = list_nth(spec->lowerdatums, abs(cmpval) - 1); - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("lower bound of partition \"%s\" is not equal to lower bound of split partition", - relname), - parser_errposition(pstate, datum->location))); - } - } - else - { - if (cmpval < 0) - { - datum = list_nth(spec->lowerdatums, abs(cmpval) - 1); - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("lower bound of partition \"%s\" is less than lower bound of split partition", - relname), - parser_errposition(pstate, datum->location))); - } - } - } - else - { - PartitionRangeBound *split_upper; - - split_upper = make_one_partition_rbound(key, -1, split_spec->upperdatums, false); - - cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, - key->partcollation, - upper->datums, upper->kind, - false, split_upper); - - /* - * Upper bound of "spec" should be equal (or less than or equal in - * case defaultPart=true) to upper bound of split partition. - */ - if (!defaultPart) - { - if (cmpval != 0) - { - datum = list_nth(spec->upperdatums, abs(cmpval) - 1); - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("upper bound of partition \"%s\" is not equal to upper bound of split partition", - relname), - parser_errposition(pstate, datum->location))); - } - } - else - { - if (cmpval > 0) - { - datum = list_nth(spec->upperdatums, abs(cmpval) - 1); - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("upper bound of partition \"%s\" is greater than upper bound of split partition", - relname), - parser_errposition(pstate, datum->location))); - } - } - } - } -} - -/* - * check_partition_bounds_for_split_list - * - * (function for BY LIST partitioning) - * - * Checks that bounds of new partition are inside bounds of split partition - * (with Oid splitPartOid). - * - * parent: partitioned table - * relname: name of the new partition - * spec: bounds specification of the new partition - * splitPartOid: split partition Oid - * pstate: pointer to ParseState struct for determine error position - */ -static void -check_partition_bounds_for_split_list(Relation parent, char *relname, - PartitionBoundSpec *spec, - Oid splitPartOid, - ParseState *pstate) -{ - PartitionKey key = RelationGetPartitionKey(parent); - PartitionDesc partdesc = RelationGetPartitionDesc(parent, false); - PartitionBoundInfo boundinfo = partdesc->boundinfo; - int with = -1; - bool overlap = false; - int overlap_location = -1; - ListCell *cell; - - Assert(key->strategy == PARTITION_STRATEGY_LIST); - Assert(spec->strategy == PARTITION_STRATEGY_LIST); - Assert(boundinfo && boundinfo->strategy == PARTITION_STRATEGY_LIST); - - /* - * Search each value of new partition "spec" in existing partitions. All - * of them should be in split partition (with Oid splitPartOid). - */ - foreach(cell, spec->listdatums) - { - Const *val = lfirst_node(Const, cell); - - overlap_location = val->location; - if (!val->constisnull) - { - int offset; - bool equal; - - offset = partition_list_bsearch(&key->partsupfunc[0], - key->partcollation, - boundinfo, - val->constvalue, - &equal); - if (offset >= 0 && equal) - { - with = boundinfo->indexes[offset]; - if (partdesc->oids[with] != splitPartOid) - { - overlap = true; - break; - } - } - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partition \"%s\" cannot have this value because split partition does not have", - relname), - parser_errposition(pstate, overlap_location))); - } - else if (partition_bound_accepts_nulls(boundinfo)) - { - with = boundinfo->null_index; - if (partdesc->oids[with] != splitPartOid) - { - overlap = true; - break; - } - } - else - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partition \"%s\" cannot have NULL value because split partition does not have", - relname), - parser_errposition(pstate, overlap_location))); - } - - if (overlap) - { - Assert(with >= 0); - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partition \"%s\" would overlap with another (not split) partition \"%s\"", - relname, get_rel_name(partdesc->oids[with])), - parser_errposition(pstate, overlap_location))); - } -} - -/* - * find_value_in_new_partitions_list - * - * (function for BY LIST partitioning) - * - * Function returns true in case any of new partitions contains value "value". - * - * partsupfunc: information about comparison function associated with the partition key - * partcollation: partitioning collation - * parts: pointer to array with new partitions descriptions - * nparts: number of new partitions - * value: the value that we are looking for - * isnull: true if the value that we are looking for is NULL - */ -static bool -find_value_in_new_partitions_list(FmgrInfo *partsupfunc, - Oid *partcollation, - SinglePartitionSpec **parts, - int nparts, - Datum value, - bool isnull) -{ - ListCell *valptr; - int i; - - for (i = 0; i < nparts; i++) - { - SinglePartitionSpec *sps = parts[i]; - - foreach(valptr, sps->bound->listdatums) - { - Const *val = lfirst_node(Const, valptr); - - if (isnull && val->constisnull) - return true; - - if (!isnull && !val->constisnull) - { - if (DatumGetInt32(FunctionCall2Coll(&partsupfunc[0], - partcollation[0], - val->constvalue, - value)) == 0) - return true; - } - } - } - return false; -} - -/* - * check_parent_values_in_new_partitions - * - * (function for BY LIST partitioning) - * - * Checks that all values of split partition (with Oid partOid) contains in new - * partitions. - * - * parent: partitioned table - * partOid: split partition Oid - * parts: pointer to array with new partitions descriptions - * nparts: number of new partitions - * pstate: pointer to ParseState struct for determine error position - */ -static void -check_parent_values_in_new_partitions(Relation parent, - Oid partOid, - SinglePartitionSpec **parts, - int nparts, - ParseState *pstate) -{ - PartitionKey key = RelationGetPartitionKey(parent); - PartitionDesc partdesc = RelationGetPartitionDesc(parent, false); - PartitionBoundInfo boundinfo = partdesc->boundinfo; - int i; - bool found = true; - bool searchNull = false; - Datum datum = PointerGetDatum(NULL); - - Assert(key->strategy == PARTITION_STRATEGY_LIST); - - /* - * Special processing for NULL value. Search NULL value if the split - * partition (partOid) contains it. - */ - if (partition_bound_accepts_nulls(boundinfo) && - partdesc->oids[boundinfo->null_index] == partOid) - { - if (!find_value_in_new_partitions_list(&key->partsupfunc[0], - key->partcollation, parts, nparts, datum, true)) - { - found = false; - searchNull = true; - } - } - - /* - * Search all values of split partition with partOid in PartitionDesc of - * partitioned table. - */ - for (i = 0; i < boundinfo->ndatums; i++) - { - if (partdesc->oids[boundinfo->indexes[i]] == partOid) - { - /* We found value that split partition contains. */ - datum = boundinfo->datums[i][0]; - if (!find_value_in_new_partitions_list(&key->partsupfunc[0], - key->partcollation, parts, nparts, datum, false)) - { - found = false; - break; - } - } - } - - if (!found) - { - Const *notFoundVal; - - if (!searchNull) - - /* - * Make Const for getting string representation of not found - * value. - */ - notFoundVal = makeConst(key->parttypid[0], - key->parttypmod[0], - key->parttypcoll[0], - key->parttyplen[0], - datum, - false, /* isnull */ - key->parttypbyval[0]); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partitions do not have value %s but split partition does", - searchNull ? "NULL" : get_list_partvalue_string(notFoundVal)))); - } -} - -/* - * check_partitions_for_split - * - * Checks new partitions for SPLIT PARTITIONS command: - * 1. DEFAULT partition should be one. - * 2. New partitions should have different names - * (with existing partitions too). - * 3. Bounds of new partitions should not overlap with new and existing - * partitions. - * 4. In case split partition is DEFAULT partition, one of new partitions - * should be DEFAULT. - * 5. In case new partitions or existing partitions contains DEFAULT - * partition, new partitions can have any bounds inside split - * partition bound (can be spaces between partitions bounds). - * 6. In case partitioned table does not have DEFAULT partition, DEFAULT - * partition can be defined as one of new partition. - * 7. In case new partitions not contains DEFAULT partition and - * partitioned table does not have DEFAULT partition the following - * should be true: sum bounds of new partitions should be equal - * to bound of split partition. - * - * parent: partitioned table - * splitPartOid: split partition Oid - * splitPartName: split partition name - * list: list of new partitions - * pstate: pointer to ParseState struct for determine error position - */ -void -check_partitions_for_split(Relation parent, - Oid splitPartOid, - RangeVar *splitPartName, - List *partlist, - ParseState *pstate) -{ - PartitionKey key; - char strategy; - Oid defaultPartOid; - bool isSplitPartDefault; - bool existsDefaultPart; - ListCell *listptr; - int default_index = -1; - int i, - j; - SinglePartitionSpec **new_parts; - SinglePartitionSpec *spsPrev = NULL; - int nparts = 0; - - key = RelationGetPartitionKey(parent); - strategy = get_partition_strategy(key); - - switch (strategy) - { - case PARTITION_STRATEGY_LIST: - case PARTITION_STRATEGY_RANGE: - { - /* - * Make array new_parts with new partitions except DEFAULT - * partition. - */ - new_parts = (SinglePartitionSpec **) - palloc0(list_length(partlist) * sizeof(SinglePartitionSpec *)); - i = 0; - foreach(listptr, partlist) - { - SinglePartitionSpec *sps = - (SinglePartitionSpec *) lfirst(listptr); - - if (sps->bound->is_default) - { - if (default_index >= 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("DEFAULT partition should be one")), - parser_errposition(pstate, sps->name->location)); - default_index = i; - } - else - { - new_parts[nparts++] = sps; - } - i++; - } - } - break; - - case PARTITION_STRATEGY_HASH: - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("partition of hash-partitioned table cannot be split"))); - break; - - default: - elog(ERROR, "unexpected partition strategy: %d", - (int) key->strategy); - break; - } - - if (strategy == PARTITION_STRATEGY_RANGE) - { - PartitionRangeBound **lower_bounds; - SinglePartitionSpec **tmp_new_parts; - - /* - * For simplify check for ranges of new partitions need to sort all - * partitions in ascending order of them bounds (we compare upper - * bound only). - */ - lower_bounds = (PartitionRangeBound **) - palloc0(nparts * sizeof(PartitionRangeBound *)); - - /* Create array of lower bounds. */ - for (i = 0; i < nparts; i++) - { - lower_bounds[i] = make_one_partition_rbound(key, i, - new_parts[i]->bound->lowerdatums, true); - } - - /* Sort array of lower bounds. */ - qsort_arg(lower_bounds, nparts, sizeof(PartitionRangeBound *), - qsort_partition_rbound_cmp, (void *) key); - - /* Reorder array of partitions. */ - tmp_new_parts = new_parts; - new_parts = (SinglePartitionSpec **) - palloc0(nparts * sizeof(SinglePartitionSpec *)); - for (i = 0; i < nparts; i++) - new_parts[i] = tmp_new_parts[lower_bounds[i]->index]; - - pfree(tmp_new_parts); - pfree(lower_bounds); - } - - defaultPartOid = - get_default_oid_from_partdesc(RelationGetPartitionDesc(parent, true)); - - /* isSplitPartDefault flag: is split partition a DEFAULT partition? */ - isSplitPartDefault = (defaultPartOid == splitPartOid); - - if (isSplitPartDefault && default_index < 0) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("one partition in the list should be DEFAULT because split partition is DEFAULT")), - parser_errposition(pstate, ((SinglePartitionSpec *) linitial(partlist))->name->location)); - } - else if (!isSplitPartDefault && (default_index >= 0) && OidIsValid(defaultPartOid)) - { - SinglePartitionSpec *spsDef = - (SinglePartitionSpec *) list_nth(partlist, default_index); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("new partition cannot be DEFAULT because DEFAULT partition already exists")), - parser_errposition(pstate, spsDef->name->location)); - } - - /* Indicator that partitioned table has (or will have) DEFAULT partition */ - existsDefaultPart = OidIsValid(defaultPartOid) || (default_index >= 0); - - for (i = 0; i < nparts; i++) - { - SinglePartitionSpec *sps = new_parts[i]; - - if (isSplitPartDefault) - { - /* - * In case split partition is DEFAULT partition we can use any - * free ranges - as when creating a new partition. - */ - check_new_partition_bound(sps->name->relname, parent, sps->bound, - pstate); - } - else - { - /* - * Checks that bound of current partition is inside bound of split - * partition. For range partitioning: checks that upper bound of - * previous partition is equal to lower bound of current - * partition. For list partitioning: checks that split partition - * contains all values of current partition. - */ - if (strategy == PARTITION_STRATEGY_RANGE) - { - bool first = (i == 0); - bool last = (i == (nparts - 1)); - - check_partition_bounds_for_split_range(parent, sps->name->relname, sps->bound, - splitPartOid, splitPartName, - first, last, - existsDefaultPart, pstate); - } - else - check_partition_bounds_for_split_list(parent, sps->name->relname, - sps->bound, splitPartOid, pstate); - } - - /* Ranges of new partitions should not overlap. */ - if (strategy == PARTITION_STRATEGY_RANGE && spsPrev) - check_two_partitions_bounds_range(parent, spsPrev->name, spsPrev->bound, - sps->name, sps->bound, existsDefaultPart, pstate); - - spsPrev = sps; - - /* Check: new partitions should have different names. */ - for (j = i + 1; j < nparts; j++) - { - SinglePartitionSpec *sps2 = new_parts[j]; - - if (equal(sps->name, sps2->name)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_TABLE), - errmsg("name \"%s\" is already used", sps2->name->relname)), - parser_errposition(pstate, sps2->name->location)); - } - } - - if (strategy == PARTITION_STRATEGY_LIST) - { - /* Values of new partitions should not overlap. */ - check_partitions_not_overlap_list(parent, new_parts, nparts, - pstate); - - /* - * Need to check that all values of split partition contains in new - * partitions. Skip this check if DEFAULT partition exists. - */ - if (!existsDefaultPart) - check_parent_values_in_new_partitions(parent, splitPartOid, - new_parts, nparts, pstate); - } - - pfree(new_parts); -} - -/* - * calculate_partition_bound_for_merge - * - * Calculates the bound of merged partition "spec" by using the bounds of - * partitions to be merged. - * - * parent: partitioned table - * partNames: names of partitions to be merged - * partOids: Oids of partitions to be merged - * spec (out): bounds specification of the merged partition - * pstate: pointer to ParseState struct for determine error position - */ -void -calculate_partition_bound_for_merge(Relation parent, - List *partNames, - List *partOids, - PartitionBoundSpec *spec, - ParseState *pstate) -{ - PartitionKey key = RelationGetPartitionKey(parent); - PartitionBoundSpec *bound; - - Assert(!spec->is_default); - - switch (key->strategy) - { - case PARTITION_STRATEGY_RANGE: - { - int i; - PartitionRangeBound **lower_bounds; - int nparts = list_length(partOids); - List *bounds = NIL; - - lower_bounds = (PartitionRangeBound **) - palloc0(nparts * sizeof(PartitionRangeBound *)); - - /* - * Create array of lower bounds and list of - * PartitionBoundSpec. - */ - for (i = 0; i < nparts; i++) - { - bound = get_partition_bound_spec(list_nth_oid(partOids, i), - (RangeVar *) list_nth(partNames, i)); - - lower_bounds[i] = make_one_partition_rbound(key, i, bound->lowerdatums, true); - bounds = lappend(bounds, bound); - } - - /* Sort array of lower bounds. */ - qsort_arg(lower_bounds, nparts, sizeof(PartitionRangeBound *), - qsort_partition_rbound_cmp, (void *) key); - - /* Ranges of partitions should not overlap. */ - for (i = 1; i < nparts; i++) - { - int index = lower_bounds[i]->index; - int prev_index = lower_bounds[i - 1]->index; - - check_two_partitions_bounds_range(parent, - (RangeVar *) list_nth(partNames, prev_index), - (PartitionBoundSpec *) list_nth(bounds, prev_index), - (RangeVar *) list_nth(partNames, index), - (PartitionBoundSpec *) list_nth(bounds, index), - false, pstate); - } - - /* - * Lower bound of first partition is the lower bound of merged - * partition. - */ - spec->lowerdatums = - ((PartitionBoundSpec *) list_nth(bounds, lower_bounds[0]->index))->lowerdatums; - - /* - * Upper bound of last partition is the upper bound of merged - * partition. - */ - spec->upperdatums = - ((PartitionBoundSpec *) list_nth(bounds, lower_bounds[nparts - 1]->index))->upperdatums; - - pfree(lower_bounds); - list_free(bounds); - break; - } - - case PARTITION_STRATEGY_LIST: - { - ListCell *listptr, - *listptr2; - - /* Consolidate bounds for all partitions in the list. */ - forboth(listptr, partOids, listptr2, partNames) - { - RangeVar *name = (RangeVar *) lfirst(listptr2); - Oid curOid = lfirst_oid(listptr); - - bound = get_partition_bound_spec(curOid, name); - spec->listdatums = list_concat(spec->listdatums, bound->listdatums); - } - break; - } - - default: - elog(ERROR, "unexpected partition strategy: %d", - (int) key->strategy); - } -} diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c index c661a303bf173..328b4d450e451 100644 --- a/src/backend/partitioning/partdesc.c +++ b/src/backend/partitioning/partdesc.c @@ -3,7 +3,7 @@ * partdesc.c * Support routines for manipulating partition descriptors * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -209,6 +209,10 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached) * shared queue. We solve this problem by reading pg_class directly * for the desired tuple. * + * If the partition recently detached is also dropped, we get no tuple + * from the scan. In that case, we also retry, and next time through + * here, we don't see that partition anymore. + * * The other problem is that DETACH CONCURRENTLY is in the process of * removing a partition, which happens in two steps: first it marks it * as "detach pending", commits, then unsets relpartbound. If @@ -223,8 +227,6 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached) Relation pg_class; SysScanDesc scan; ScanKeyData key[1]; - Datum datum; - bool isnull; pg_class = table_open(RelationRelationId, AccessShareLock); ScanKeyInit(&key[0], @@ -233,17 +235,29 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached) ObjectIdGetDatum(inhrelid)); scan = systable_beginscan(pg_class, ClassOidIndexId, true, NULL, 1, key); + + /* + * We could get one tuple from the scan (the normal case), or zero + * tuples if the table has been dropped meanwhile. + */ tuple = systable_getnext(scan); - datum = heap_getattr(tuple, Anum_pg_class_relpartbound, - RelationGetDescr(pg_class), &isnull); - if (!isnull) - boundspec = stringToNode(TextDatumGetCString(datum)); + if (HeapTupleIsValid(tuple)) + { + Datum datum; + bool isnull; + + datum = heap_getattr(tuple, Anum_pg_class_relpartbound, + RelationGetDescr(pg_class), &isnull); + if (!isnull) + boundspec = stringToNode(TextDatumGetCString(datum)); + } systable_endscan(scan); table_close(pg_class, AccessShareLock); /* - * If we still don't get a relpartbound value, then it must be - * because of DETACH CONCURRENTLY. Restart from the top, as + * If we still don't get a relpartbound value (either because + * boundspec is null or because there was no tuple), then it must + * be because of DETACH CONCURRENTLY. Restart from the top, as * explained above. We only do this once, for two reasons: first, * only one DETACH CONCURRENTLY session could affect us at a time, * since each of them would have to wait for the snapshot under diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index 9a1a7faac7ad9..48a35f763e906 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -25,7 +25,7 @@ * * See gen_partprune_steps_internal() for more details on step generation. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -207,16 +207,20 @@ static void partkey_datum_from_expr(PartitionPruneContext *context, /* * make_partition_pruneinfo - * Builds a PartitionPruneInfo which can be used in the executor to allow - * additional partition pruning to take place. Returns NULL when - * partition pruning would be useless. + * Checks if the given set of quals can be used to build pruning steps + * that the executor can use to prune away unneeded partitions. If + * suitable quals are found then a PartitionPruneInfo is built and tagged + * onto the PlannerInfo's partPruneInfos list. + * + * The return value is the 0-based index of the item added to the + * partPruneInfos list or -1 if nothing was added. * * 'parentrel' is the RelOptInfo for an appendrel, and 'subpaths' is the list * of scan paths for its child rels. * 'prunequal' is a list of potential pruning quals (i.e., restriction * clauses that are applicable to the appendrel). */ -PartitionPruneInfo * +int make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *subpaths, List *prunequal) @@ -330,10 +334,11 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, * quals, then we can just not bother with run-time pruning. */ if (prunerelinfos == NIL) - return NULL; + return -1; /* Else build the result data structure */ pruneinfo = makeNode(PartitionPruneInfo); + pruneinfo->relids = bms_copy(parentrel->relids); pruneinfo->prune_infos = prunerelinfos; /* @@ -356,7 +361,9 @@ make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, else pruneinfo->other_subplans = NULL; - return pruneinfo; + root->partPruneInfos = lappend(root->partPruneInfos, pruneinfo); + + return list_length(root->partPruneInfos) - 1; } /* @@ -638,6 +645,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, int *subplan_map; int *subpart_map; Oid *relid_map; + int *leafpart_rti_map; /* * Construct the subplan and subpart maps for this partitioning level. @@ -650,6 +658,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, subpart_map = (int *) palloc(nparts * sizeof(int)); memset(subpart_map, -1, nparts * sizeof(int)); relid_map = (Oid *) palloc0(nparts * sizeof(Oid)); + leafpart_rti_map = (int *) palloc0(nparts * sizeof(int)); present_parts = NULL; i = -1; @@ -664,10 +673,29 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1; subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1; relid_map[i] = planner_rt_fetch(partrel->relid, root)->relid; + + /* + * Track the RT indexes of "leaf" partitions so they can be + * included in the PlannerGlobal.prunableRelids set, indicating + * relations that may be pruned during executor startup. + * + * Only leaf partitions with a valid subplan that are prunable + * using initial pruning are added to prunableRelids. So + * partitions without a subplan due to constraint exclusion will + * remain in PlannedStmt.unprunableRelids. + */ if (subplanidx >= 0) { present_parts = bms_add_member(present_parts, i); + /* + * Non-leaf partitions may appear here when they use an + * unflattened Append or MergeAppend. These should not be + * included in prunableRelids. + */ + if (partrel->nparts == -1) + leafpart_rti_map[i] = (int) partrel->relid; + /* Record finding this subplan */ subplansfound = bms_add_member(subplansfound, subplanidx); } @@ -688,6 +716,7 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, pinfo->subplan_map = subplan_map; pinfo->subpart_map = subpart_map; pinfo->relid_map = relid_map; + pinfo->leafpart_rti_map = leafpart_rti_map; } pfree(relid_subpart_map); @@ -3365,8 +3394,7 @@ pull_exec_paramids_walker(Node *node, Bitmapset **context) *context = bms_add_member(*context, param->paramid); return false; } - return expression_tree_walker(node, pull_exec_paramids_walker, - (void *) context); + return expression_tree_walker(node, pull_exec_paramids_walker, context); } /* @@ -3777,13 +3805,8 @@ partkey_datum_from_expr(PartitionPruneContext *context, /* * We should never see a non-Const in a step unless the caller has * passed a valid ExprContext. - * - * When context->planstate is valid, context->exprcontext is same as - * context->planstate->ps_ExprContext. */ - Assert(context->planstate != NULL || context->exprcontext != NULL); - Assert(context->planstate == NULL || - (context->exprcontext == context->planstate->ps_ExprContext)); + Assert(context->exprcontext != NULL); exprstate = context->exprstates[stateidx]; ectx = context->exprcontext; diff --git a/src/backend/po/es.po b/src/backend/po/es.po index 0d6dead79e038..e2593b522719a 100644 --- a/src/backend/po/es.po +++ b/src/backend/po/es.po @@ -12,6 +12,7 @@ # Glosario: # # character carácter +# checkpoint checkpoint # checksum suma de verificación # cluster (de la orden cluster) reordenar # command orden @@ -23,8 +24,8 @@ # lexeme lexema # locale configuración regional # to lock bloquear -# lock (sustantivo) candado -# to obtain a lock bloquear un candado +# lock (sustantivo) “lock” +# to obtain a lock bloquear un “lock” # malformed mal formado # mapping mapeo # operator class clase de operadores @@ -42,7 +43,8 @@ # rule regla de reescritura # schema esquema # to skip ignorar -# trigger disparador +# trigger “trigger” +# wait event “wait event” # window function función de ventana deslizante # # FIXME varios: @@ -60,10 +62,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL server 15\n" +"Project-Id-Version: PostgreSQL server 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:10+0000\n" -"PO-Revision-Date: 2024-05-21 13:39+0200\n" +"POT-Creation-Date: 2025-02-16 19:41+0000\n" +"PO-Revision-Date: 2025-02-17 15:18+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -73,6 +75,11 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: BlackCAT 1.1\n" +#: ../common/binaryheap.c:121 ../common/binaryheap.c:159 +#, c-format +msgid "out of binary heap slots" +msgstr "se acabaron los slots de “binary heap”" + #: ../common/compression.c:132 ../common/compression.c:141 #: ../common/compression.c:150 #, c-format @@ -99,8 +106,7 @@ msgid "value for compression option \"%s\" must be an integer" msgstr "el valor para la opción de compresión «%s» debe ser un entero" #: ../common/compression.c:331 -#, fuzzy, c-format -#| msgid "value for compression option \"%s\" must be a boolean" +#, c-format msgid "value for compression option \"%s\" must be a Boolean value" msgstr "el valor para la opción de compresión «%s» debe ser un booleano" @@ -131,64 +137,66 @@ msgstr "el algoritmo de compresión «%s» no acepta modo de larga distancia" msgid "not recorded" msgstr "no registrado" -#: ../common/controldata_utils.c:69 ../common/controldata_utils.c:73 -#: commands/copyfrom.c:1669 commands/extension.c:3456 utils/adt/genfile.c:123 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 +#: commands/copyfrom.c:1739 commands/extension.c:3538 utils/adt/genfile.c:123 +#: utils/time/snapmgr.c:1430 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "no se pudo abrir archivo «%s» para lectura: %m" -#: ../common/controldata_utils.c:84 ../common/controldata_utils.c:86 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 #: access/transam/timeline.c:143 access/transam/timeline.c:362 -#: access/transam/twophase.c:1346 access/transam/xlog.c:3193 -#: access/transam/xlog.c:3996 access/transam/xlogrecovery.c:1199 -#: access/transam/xlogrecovery.c:1291 access/transam/xlogrecovery.c:1328 -#: access/transam/xlogrecovery.c:1388 backup/basebackup.c:1842 -#: commands/extension.c:3466 libpq/hba.c:791 replication/logical/origin.c:745 -#: replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5050 -#: replication/logical/snapbuild.c:2027 replication/slot.c:1946 -#: replication/slot.c:1987 replication/walsender.c:643 +#: access/transam/twophase.c:1353 access/transam/xlog.c:3477 +#: access/transam/xlog.c:4341 access/transam/xlogrecovery.c:1238 +#: access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 +#: access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 +#: backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 +#: replication/logical/reorderbuffer.c:5113 +#: replication/logical/snapbuild.c:2052 replication/slot.c:2236 +#: replication/slot.c:2277 replication/walsender.c:655 #: storage/file/buffile.c:470 storage/file/copydir.c:185 -#: utils/adt/genfile.c:197 utils/adt/misc.c:984 utils/cache/relmapper.c:827 +#: utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "no se pudo leer el archivo «%s»: %m" -#: ../common/controldata_utils.c:92 ../common/controldata_utils.c:95 -#: access/transam/xlog.c:3198 access/transam/xlog.c:4001 -#: backup/basebackup.c:1846 replication/logical/origin.c:750 -#: replication/logical/origin.c:789 replication/logical/snapbuild.c:2032 -#: replication/slot.c:1950 replication/slot.c:1991 replication/walsender.c:648 -#: utils/cache/relmapper.c:831 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 +#: access/transam/xlog.c:3482 access/transam/xlog.c:4346 +#: replication/logical/origin.c:750 replication/logical/origin.c:789 +#: replication/logical/snapbuild.c:2057 replication/slot.c:2240 +#: replication/slot.c:2281 replication/walsender.c:660 +#: utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" -#: ../common/controldata_utils.c:104 ../common/controldata_utils.c:108 -#: ../common/controldata_utils.c:233 ../common/controldata_utils.c:236 -#: access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1280 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 +#: ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 +#: access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 #: access/transam/timeline.c:392 access/transam/timeline.c:438 -#: access/transam/timeline.c:512 access/transam/twophase.c:1358 -#: access/transam/twophase.c:1770 access/transam/xlog.c:3039 -#: access/transam/xlog.c:3233 access/transam/xlog.c:3238 -#: access/transam/xlog.c:3374 access/transam/xlog.c:3966 -#: access/transam/xlog.c:4885 commands/copyfrom.c:1729 commands/copyto.c:332 +#: access/transam/timeline.c:512 access/transam/twophase.c:1365 +#: access/transam/twophase.c:1784 access/transam/xlog.c:3323 +#: access/transam/xlog.c:3517 access/transam/xlog.c:3522 +#: access/transam/xlog.c:3658 access/transam/xlog.c:4311 +#: access/transam/xlog.c:5246 commands/copyfrom.c:1799 commands/copyto.c:325 #: libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 #: replication/logical/origin.c:683 replication/logical/origin.c:822 -#: replication/logical/reorderbuffer.c:5102 -#: replication/logical/snapbuild.c:1798 replication/logical/snapbuild.c:1922 -#: replication/slot.c:1837 replication/slot.c:1998 replication/walsender.c:658 -#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:739 -#: storage/file/fd.c:3650 storage/file/fd.c:3756 utils/cache/relmapper.c:839 -#: utils/cache/relmapper.c:945 +#: replication/logical/reorderbuffer.c:5165 +#: replication/logical/snapbuild.c:1819 replication/logical/snapbuild.c:1943 +#: replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 +#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:828 +#: storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 +#: utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "no se pudo cerrar el archivo «%s»: %m" -#: ../common/controldata_utils.c:124 +#: ../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "discordancia en orden de bytes" -#: ../common/controldata_utils.c:126 +#: ../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -202,141 +210,157 @@ msgstr "" "serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" "directorio de datos." -#: ../common/controldata_utils.c:181 ../common/controldata_utils.c:186 -#: ../common/file_utils.c:228 ../common/file_utils.c:287 -#: ../common/file_utils.c:361 access/heap/rewriteheap.c:1263 -#: access/transam/timeline.c:111 access/transam/timeline.c:251 -#: access/transam/timeline.c:348 access/transam/twophase.c:1302 -#: access/transam/xlog.c:2946 access/transam/xlog.c:3109 -#: access/transam/xlog.c:3148 access/transam/xlog.c:3341 -#: access/transam/xlog.c:3986 access/transam/xlogrecovery.c:4179 -#: access/transam/xlogrecovery.c:4282 access/transam/xlogutils.c:838 -#: backup/basebackup.c:538 backup/basebackup.c:1512 libpq/hba.c:651 -#: postmaster/syslogger.c:1560 replication/logical/origin.c:735 -#: replication/logical/reorderbuffer.c:3706 -#: replication/logical/reorderbuffer.c:4257 -#: replication/logical/reorderbuffer.c:5030 -#: replication/logical/snapbuild.c:1753 replication/logical/snapbuild.c:1863 -#: replication/slot.c:1918 replication/walsender.c:616 -#: replication/walsender.c:2731 storage/file/copydir.c:151 -#: storage/file/fd.c:714 storage/file/fd.c:3407 storage/file/fd.c:3637 -#: storage/file/fd.c:3727 storage/smgr/md.c:660 utils/cache/relmapper.c:816 -#: utils/cache/relmapper.c:924 utils/error/elog.c:2082 -#: utils/init/miscinit.c:1530 utils/init/miscinit.c:1664 -#: utils/init/miscinit.c:1741 utils/misc/guc.c:4600 utils/misc/guc.c:4650 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 +#: ../common/file_utils.c:70 ../common/file_utils.c:347 +#: ../common/file_utils.c:406 ../common/file_utils.c:480 +#: access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 +#: access/transam/timeline.c:251 access/transam/timeline.c:348 +#: access/transam/twophase.c:1309 access/transam/xlog.c:3230 +#: access/transam/xlog.c:3393 access/transam/xlog.c:3432 +#: access/transam/xlog.c:3625 access/transam/xlog.c:4331 +#: access/transam/xlogrecovery.c:4264 access/transam/xlogrecovery.c:4367 +#: access/transam/xlogutils.c:836 backup/basebackup.c:547 +#: backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 +#: postmaster/syslogger.c:1511 replication/logical/origin.c:735 +#: replication/logical/reorderbuffer.c:3766 +#: replication/logical/reorderbuffer.c:4320 +#: replication/logical/reorderbuffer.c:5093 +#: replication/logical/snapbuild.c:1774 replication/logical/snapbuild.c:1884 +#: replication/slot.c:2208 replication/walsender.c:628 +#: replication/walsender.c:3051 storage/file/copydir.c:151 +#: storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 +#: storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 +#: utils/cache/relmapper.c:935 utils/error/elog.c:2124 +#: utils/init/miscinit.c:1580 utils/init/miscinit.c:1714 +#: utils/init/miscinit.c:1791 utils/misc/guc.c:4777 utils/misc/guc.c:4827 #, c-format msgid "could not open file \"%s\": %m" msgstr "no se pudo abrir el archivo «%s»: %m" -#: ../common/controldata_utils.c:202 ../common/controldata_utils.c:205 -#: access/transam/twophase.c:1743 access/transam/twophase.c:1752 -#: access/transam/xlog.c:8751 access/transam/xlogfuncs.c:708 -#: backup/basebackup_server.c:175 backup/basebackup_server.c:268 -#: postmaster/postmaster.c:5570 postmaster/syslogger.c:1571 -#: postmaster/syslogger.c:1584 postmaster/syslogger.c:1597 -#: utils/cache/relmapper.c:936 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 +#: access/transam/twophase.c:1757 access/transam/twophase.c:1766 +#: access/transam/xlog.c:9280 access/transam/xlogfuncs.c:698 +#: backup/basebackup_server.c:173 backup/basebackup_server.c:266 +#: backup/walsummary.c:304 postmaster/postmaster.c:4127 +#: postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 +#: postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "no se pudo escribir el archivo «%s»: %m" -#: ../common/controldata_utils.c:219 ../common/controldata_utils.c:224 -#: ../common/file_utils.c:299 ../common/file_utils.c:369 -#: access/heap/rewriteheap.c:959 access/heap/rewriteheap.c:1169 -#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:432 -#: access/transam/timeline.c:506 access/transam/twophase.c:1764 -#: access/transam/xlog.c:3032 access/transam/xlog.c:3227 -#: access/transam/xlog.c:3959 access/transam/xlog.c:8141 -#: access/transam/xlog.c:8186 backup/basebackup_server.c:209 -#: replication/logical/snapbuild.c:1791 replication/slot.c:1823 -#: replication/slot.c:1928 storage/file/fd.c:731 storage/file/fd.c:3748 -#: storage/smgr/md.c:1132 storage/smgr/md.c:1177 storage/sync/sync.c:453 -#: utils/misc/guc.c:4370 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 +#: ../common/file_utils.c:418 ../common/file_utils.c:488 +#: access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 +#: access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 +#: access/transam/timeline.c:506 access/transam/twophase.c:1778 +#: access/transam/xlog.c:3316 access/transam/xlog.c:3511 +#: access/transam/xlog.c:4304 access/transam/xlog.c:8655 +#: access/transam/xlog.c:8700 backup/basebackup_server.c:207 +#: commands/dbcommands.c:514 replication/logical/snapbuild.c:1812 +#: replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 +#: storage/file/fd.c:3851 storage/smgr/md.c:1331 storage/smgr/md.c:1376 +#: storage/sync/sync.c:446 utils/misc/guc.c:4530 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:133 -#: ../common/cryptohash_openssl.c:332 ../common/exec.c:550 ../common/exec.c:595 -#: ../common/exec.c:687 ../common/hmac.c:309 ../common/hmac.c:325 -#: ../common/hmac_openssl.c:132 ../common/hmac_openssl.c:327 -#: ../common/md5_common.c:155 ../common/psprintf.c:143 -#: ../common/scram-common.c:258 ../common/stringinfo.c:305 ../port/path.c:751 -#: ../port/path.c:789 ../port/path.c:806 access/transam/twophase.c:1411 -#: access/transam/xlogrecovery.c:589 lib/dshash.c:253 libpq/auth.c:1345 -#: libpq/auth.c:1389 libpq/auth.c:1946 libpq/be-secure-gssapi.c:524 -#: postmaster/bgworker.c:352 postmaster/bgworker.c:934 -#: postmaster/postmaster.c:2534 postmaster/postmaster.c:4127 -#: postmaster/postmaster.c:5495 postmaster/postmaster.c:5866 -#: replication/libpqwalreceiver/libpqwalreceiver.c:308 -#: replication/logical/logical.c:208 replication/walsender.c:686 -#: storage/buffer/localbuf.c:601 storage/file/fd.c:823 storage/file/fd.c:1354 -#: storage/file/fd.c:1515 storage/file/fd.c:2428 storage/ipc/procarray.c:1449 -#: storage/ipc/procarray.c:2232 storage/ipc/procarray.c:2239 -#: storage/ipc/procarray.c:2738 storage/ipc/procarray.c:3374 -#: utils/adt/formatting.c:1690 utils/adt/formatting.c:1812 -#: utils/adt/formatting.c:1935 utils/adt/pg_locale.c:469 -#: utils/adt/pg_locale.c:633 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:514 -#: utils/hash/dynahash.c:614 utils/hash/dynahash.c:1111 utils/mb/mbutils.c:402 -#: utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 utils/mb/mbutils.c:842 -#: utils/misc/guc.c:640 utils/misc/guc.c:665 utils/misc/guc.c:1053 -#: utils/misc/guc.c:4348 utils/misc/tzparser.c:476 utils/mmgr/aset.c:445 -#: utils/mmgr/dsa.c:713 utils/mmgr/dsa.c:735 utils/mmgr/dsa.c:816 -#: utils/mmgr/generation.c:205 utils/mmgr/mcxt.c:1046 utils/mmgr/mcxt.c:1082 -#: utils/mmgr/mcxt.c:1120 utils/mmgr/mcxt.c:1158 utils/mmgr/mcxt.c:1246 -#: utils/mmgr/mcxt.c:1277 utils/mmgr/mcxt.c:1313 utils/mmgr/mcxt.c:1502 -#: utils/mmgr/mcxt.c:1547 utils/mmgr/mcxt.c:1604 utils/mmgr/slab.c:366 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 +#: ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 +#: ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 +#: ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 +#: ../common/md5_common.c:156 ../common/parse_manifest.c:157 +#: ../common/parse_manifest.c:852 ../common/psprintf.c:143 +#: ../common/scram-common.c:268 ../common/stringinfo.c:314 ../port/path.c:828 +#: ../port/path.c:865 ../port/path.c:882 access/transam/twophase.c:1418 +#: access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 +#: libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 +#: postmaster/bgworker.c:355 postmaster/bgworker.c:945 +#: postmaster/postmaster.c:3560 postmaster/postmaster.c:4021 +#: postmaster/postmaster.c:4383 postmaster/walsummarizer.c:935 +#: replication/libpqwalreceiver/libpqwalreceiver.c:387 +#: replication/logical/logical.c:210 replication/walsender.c:835 +#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 +#: storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1465 +#: storage/ipc/procarray.c:2219 storage/ipc/procarray.c:2226 +#: storage/ipc/procarray.c:2731 storage/ipc/procarray.c:3435 +#: utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 +#: utils/adt/formatting.c:2075 utils/adt/pg_locale.c:532 +#: utils/adt/pg_locale.c:696 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 +#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 +#: utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 +#: utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 +#: utils/misc/guc.c:4508 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 +#: utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 +#: utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 +#: utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "memoria agotada" #: ../common/cryptohash.c:266 ../common/cryptohash.c:272 -#: ../common/cryptohash_openssl.c:344 ../common/cryptohash_openssl.c:352 -#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:339 -#: ../common/hmac_openssl.c:347 +#: ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 +#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 +#: ../common/hmac_openssl.c:377 msgid "success" msgstr "éxito" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:346 -#: ../common/hmac_openssl.c:341 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 +#: ../common/hmac_openssl.c:371 msgid "destination buffer too small" msgstr "el búfer de destino es demasiado pequeño" -#: ../common/cryptohash_openssl.c:348 ../common/hmac_openssl.c:343 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 msgid "OpenSSL failure" msgstr "falla de openSSL" -#: ../common/exec.c:172 +#: ../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../common/exec.c:215 +#: ../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../common/exec.c:223 +#: ../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../common/exec.c:250 +#: ../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../common/exec.c:412 libpq/pqcomm.c:728 storage/ipc/latch.c:1128 -#: storage/ipc/latch.c:1308 storage/ipc/latch.c:1541 storage/ipc/latch.c:1703 -#: storage/ipc/latch.c:1829 +#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1723 +#: commands/copyto.c:654 libpq/be-secure-common.c:59 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 +#: storage/ipc/latch.c:1349 storage/ipc/latch.c:1589 storage/ipc/latch.c:1751 +#: storage/ipc/latch.c:1877 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" #: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 #: ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 -#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:791 -#: ../port/path.c:808 utils/misc/ps_status.c:168 utils/misc/ps_status.c:176 -#: utils/misc/ps_status.c:203 utils/misc/ps_status.c:211 +#: ../common/psprintf.c:145 ../port/path.c:830 ../port/path.c:867 +#: ../port/path.c:884 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 +#: utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 #, c-format msgid "out of memory\n" msgstr "memoria agotada\n" @@ -346,39 +370,51 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" -#: ../common/file_utils.c:87 ../common/file_utils.c:447 -#: ../common/file_utils.c:451 access/transam/twophase.c:1314 -#: access/transam/xlogarchive.c:112 access/transam/xlogarchive.c:229 -#: backup/basebackup.c:346 backup/basebackup.c:544 backup/basebackup.c:615 -#: commands/copyfrom.c:1679 commands/copyto.c:702 commands/extension.c:3445 -#: commands/tablespace.c:810 commands/tablespace.c:899 postmaster/pgarch.c:590 -#: replication/logical/snapbuild.c:1649 storage/file/fd.c:1879 -#: storage/file/fd.c:1965 storage/file/fd.c:3461 utils/adt/dbsize.c:106 -#: utils/adt/dbsize.c:258 utils/adt/dbsize.c:338 utils/adt/genfile.c:483 -#: utils/adt/genfile.c:658 utils/adt/misc.c:340 +#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../common/file_utils.c:120 ../common/file_utils.c:566 +#: ../common/file_utils.c:570 access/transam/twophase.c:1321 +#: access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 +#: backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 +#: backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1749 +#: commands/copyto.c:700 commands/extension.c:3527 commands/tablespace.c:804 +#: commands/tablespace.c:893 postmaster/pgarch.c:680 +#: replication/logical/snapbuild.c:1670 replication/logical/snapbuild.c:2173 +#: storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 +#: utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 +#: utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "no se pudo hacer stat al archivo «%s»: %m" -#: ../common/file_utils.c:162 ../common/pgfnames.c:48 ../common/rmtree.c:63 -#: commands/tablespace.c:734 commands/tablespace.c:744 -#: postmaster/postmaster.c:1561 storage/file/fd.c:2830 -#: storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:338 +#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../common/file_utils.c:151 ../common/file_utils.c:281 +#: ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 +#: commands/tablespace.c:738 postmaster/postmaster.c:1470 +#: storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 +#: utils/misc/tzparser.c:339 #, c-format msgid "could not open directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: ../common/file_utils.c:196 ../common/pgfnames.c:69 ../common/rmtree.c:104 -#: storage/file/fd.c:2842 +#: ../common/file_utils.c:169 ../common/file_utils.c:315 +#: ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 #, c-format msgid "could not read directory \"%s\": %m" msgstr "no se pudo leer el directorio «%s»: %m" -#: ../common/file_utils.c:379 access/transam/xlogarchive.c:383 -#: postmaster/pgarch.c:746 postmaster/syslogger.c:1608 -#: replication/logical/snapbuild.c:1810 replication/slot.c:723 -#: replication/slot.c:1709 replication/slot.c:1851 storage/file/fd.c:749 -#: utils/time/snapmgr.c:1284 +#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 +#: postmaster/pgarch.c:834 postmaster/syslogger.c:1559 +#: replication/logical/snapbuild.c:1831 replication/slot.c:936 +#: replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 +#: utils/time/snapmgr.c:1255 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" @@ -387,90 +423,102 @@ msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" msgid "internal error" msgstr "error interno" -#: ../common/jsonapi.c:1144 +#: ../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "El parser recursivo descendiente no puede usar el lexer incremental." + +#: ../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "El parser incremental requiere el lexer incremental." + +#: ../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON anidado demasiado profundamente, profundidad máxima es 6400." + +#: ../common/jsonapi.c:2127 #, c-format -msgid "Escape sequence \"\\%s\" is invalid." -msgstr "La secuencia de escape «%s» no es válida." +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "La secuencia de escape «\\%.*s» no es válida." -#: ../common/jsonapi.c:1147 +#: ../common/jsonapi.c:2131 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Los caracteres con valor 0x%02x deben ser escapados." -#: ../common/jsonapi.c:1150 +#: ../common/jsonapi.c:2135 #, c-format -msgid "Expected end of input, but found \"%s\"." -msgstr "Se esperaba el fin de la entrada, se encontró «%s»." +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Se esperaba el fin de la entrada, se encontró «%.*s»." -#: ../common/jsonapi.c:1153 +#: ../common/jsonapi.c:2138 #, c-format -msgid "Expected array element or \"]\", but found \"%s\"." -msgstr "Se esperaba un elemento de array o «]», se encontró «%s»." +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Se esperaba un elemento de array o «]», se encontró «%.*s»." -#: ../common/jsonapi.c:1156 +#: ../common/jsonapi.c:2141 #, c-format -msgid "Expected \",\" or \"]\", but found \"%s\"." -msgstr "Se esperaba «,» o «]», se encontró «%s»." +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Se esperaba «,» o «]», se encontró «%.*s»." -#: ../common/jsonapi.c:1159 +#: ../common/jsonapi.c:2144 #, c-format -msgid "Expected \":\", but found \"%s\"." -msgstr "Se esperaba «:», se encontró «%s»." +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Se esperaba «:», se encontró «%.*s»." -#: ../common/jsonapi.c:1162 +#: ../common/jsonapi.c:2147 #, c-format -msgid "Expected JSON value, but found \"%s\"." -msgstr "Se esperaba un valor JSON, se encontró «%s»." +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Se esperaba un valor JSON, se encontró «%.*s»." -#: ../common/jsonapi.c:1165 +#: ../common/jsonapi.c:2150 msgid "The input string ended unexpectedly." msgstr "La cadena de entrada terminó inesperadamente." -#: ../common/jsonapi.c:1167 +#: ../common/jsonapi.c:2152 #, c-format -msgid "Expected string or \"}\", but found \"%s\"." -msgstr "Se esperaba una cadena o «}», se encontró «%s»." +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Se esperaba una cadena o «}», se encontró «%.*s»." -#: ../common/jsonapi.c:1170 +#: ../common/jsonapi.c:2155 #, c-format -msgid "Expected \",\" or \"}\", but found \"%s\"." -msgstr "Se esperaba «,» o «}», se encontró «%s»." +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Se esperaba «,» o «}», se encontró «%.*s»." -#: ../common/jsonapi.c:1173 +#: ../common/jsonapi.c:2158 #, c-format -msgid "Expected string, but found \"%s\"." -msgstr "Se esperaba una cadena, se encontró «%s»." +msgid "Expected string, but found \"%.*s\"." +msgstr "Se esperaba una cadena, se encontró «%.*s»." -#: ../common/jsonapi.c:1176 +#: ../common/jsonapi.c:2161 #, c-format -msgid "Token \"%s\" is invalid." -msgstr "El elemento «%s» no es válido." +msgid "Token \"%.*s\" is invalid." +msgstr "El elemento «%.*s» no es válido." -#: ../common/jsonapi.c:1179 jsonpath_scan.l:597 +#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 no puede ser convertido a text." -#: ../common/jsonapi.c:1181 +#: ../common/jsonapi.c:2166 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "«\\u» debe ser seguido por cuatro dígitos hexadecimales." -#: ../common/jsonapi.c:1184 +#: ../common/jsonapi.c:2169 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "Los valores de escape Unicode no se pueden utilizar para valores de código superiores a 007F cuando la codificación no es UTF8." -#: ../common/jsonapi.c:1187 +#: ../common/jsonapi.c:2178 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "El valor de escape Unicode no pudo ser traducido a la codificación del servidor %s." -#: ../common/jsonapi.c:1190 jsonpath_scan.l:630 +#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Un «high-surrogate» Unicode no puede venir después de un «high-surrogate»." -#: ../common/jsonapi.c:1192 jsonpath_scan.l:641 jsonpath_scan.l:651 -#: jsonpath_scan.l:702 +#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 +#: jsonpath_scan.l:713 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "Un «low-surrogate» Unicode debe seguir a un «high-surrogate»." @@ -495,11 +543,168 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "no se pudo inicializar la suma de verificación del manifiesto" + +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "el manifiesto terminó inesperadamente" + +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "no se pudo actualizar la suma de verificación del manifiesto" + +#: ../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "inicio de objeto inesperado" + +#: ../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "fin de objeto inesperado" + +#: ../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "inicio de array inesperado" + +#: ../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "fin de array inesperado" + +#: ../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "se esperaba indicador de versión" + +#: ../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "campo de nivel superior no reconocido" + +#: ../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "campo de archivo inesperado" + +#: ../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "campo de rango de WAL inesperado" + +#: ../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "campo de objeto inesperado" + +#: ../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "escalar inesperado" + +#: ../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "la versión de manifiesto no es un número entero" + +#: ../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "versión de manifiesto inesperada" + +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "el identificador de sistema en el manifiesto no es un número entero" + +#: ../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "ruta de archivo faltante" + +#: ../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "hay ambos ruta de archivo (path name) y ruta codificada (encoded path name)" + +#: ../common/parse_manifest.c:666 +msgid "missing size" +msgstr "tamaño faltante" + +#: ../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "suma de comprobación sin algoritmo" + +#: ../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "no se pudo decodificar el nombre del archivo" + +#: ../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "el tamaño del archivo no es un número entero" + +#: ../common/parse_manifest.c:699 backup/basebackup.c:870 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "algoritmo de suma de comprobación no reconocido: \"%s\"" + +#: ../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "suma de comprobación no válida para el archivo \"%s\": \"%s\"" + +#: ../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "falta el timeline" + +#: ../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "falta el LSN de inicio" + +#: ../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "falta el LSN de término" + +#: ../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "el timeline no es un número entero" + +#: ../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "no se pudo interpretar el LSN de inicio" + +#: ../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "no se pudo interpretar el LSN de término" + +#: ../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "esperado al menos 2 líneas" + +#: ../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "última línea no termina en nueva línea" + +#: ../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "no se pudo finalizar la suma de verificación del manifiesto" + +#: ../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "el manifiesto no tiene suma de comprobación" + +#: ../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "suma de comprobación de manifiesto no válida: \"%s\"" + +#: ../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "discordancia en la suma de comprobación del manifiesto" + +#: ../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "no se pudo analizar el manifiesto de la copia de seguridad: %s" + #: ../common/percentrepl.c:79 ../common/percentrepl.c:85 #: ../common/percentrepl.c:118 ../common/percentrepl.c:124 -#: postmaster/postmaster.c:2208 utils/misc/guc.c:3118 utils/misc/guc.c:3154 -#: utils/misc/guc.c:3224 utils/misc/guc.c:4547 utils/misc/guc.c:6721 -#: utils/misc/guc.c:6762 +#: tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 +#: utils/misc/guc.c:3283 utils/misc/guc.c:4712 utils/misc/guc.c:6931 +#: utils/misc/guc.c:6972 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "valor no válido para el parámetro «%s»: «%s»" @@ -510,10 +715,9 @@ msgid "String ends unexpectedly after escape character \"%%\"." msgstr "La cadena termina inesperadamente luego del carácter de escape: «%%»" #: ../common/percentrepl.c:119 ../common/percentrepl.c:125 -#, fuzzy, c-format -#| msgid "String contains unexpected escape sequence \"%c\"." +#, c-format msgid "String contains unexpected placeholder \"%%%c\"." -msgstr "La cadena contiene la secuencia de escape inesperada «%c»." +msgstr "La cadena contiene la secuencia de reemplazo inesperada «%c»." #: ../common/pgfnames.c:74 #, c-format @@ -560,45 +764,45 @@ msgstr "no se pudo re-ejecutar con el token restringido: código de error %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "no se pudo obtener el código de salida del subproceso»: código de error %lu" -#: ../common/rmtree.c:95 access/heap/rewriteheap.c:1248 -#: access/transam/twophase.c:1703 access/transam/xlogarchive.c:120 -#: access/transam/xlogarchive.c:393 postmaster/postmaster.c:1143 -#: postmaster/syslogger.c:1537 replication/logical/origin.c:591 -#: replication/logical/reorderbuffer.c:4526 -#: replication/logical/snapbuild.c:1691 replication/logical/snapbuild.c:2121 -#: replication/slot.c:1902 storage/file/fd.c:789 storage/file/fd.c:3275 -#: storage/file/fd.c:3337 storage/file/reinit.c:262 storage/ipc/dsm.c:316 -#: storage/smgr/md.c:380 storage/smgr/md.c:439 storage/sync/sync.c:250 -#: utils/time/snapmgr.c:1608 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 +#: access/transam/twophase.c:1717 access/transam/xlogarchive.c:119 +#: access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 +#: postmaster/syslogger.c:1488 replication/logical/origin.c:591 +#: replication/logical/reorderbuffer.c:4589 +#: replication/logical/snapbuild.c:1712 replication/logical/snapbuild.c:2146 +#: replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 +#: storage/file/fd.c:3440 storage/file/reinit.c:261 storage/ipc/dsm.c:343 +#: storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 +#: utils/time/snapmgr.c:1591 #, c-format msgid "could not remove file \"%s\": %m" msgstr "no se pudo eliminar el archivo «%s»: %m" -#: ../common/rmtree.c:122 commands/tablespace.c:773 commands/tablespace.c:786 -#: commands/tablespace.c:821 commands/tablespace.c:911 storage/file/fd.c:3267 -#: storage/file/fd.c:3676 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 +#: commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 +#: storage/file/fd.c:3779 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "no se pudo eliminar el directorio «%s»: %m" -#: ../common/scram-common.c:271 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "no se pudo codificar la sal" -#: ../common/scram-common.c:287 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "no se pudo codificar la llave almacenada" -#: ../common/scram-common.c:304 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "no se pudo codificar la llave del servidor" -#: ../common/stringinfo.c:306 +#: ../common/stringinfo.c:315 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "No se puede agrandar el búfer de cadena que ya tiene %d bytes en %d bytes adicionales." -#: ../common/stringinfo.c:310 +#: ../common/stringinfo.c:319 #, c-format msgid "" "out of memory\n" @@ -614,7 +818,7 @@ msgstr "" msgid "could not look up effective user ID %ld: %s" msgstr "no se pudo encontrar el ID de usuario efectivo %ld: %s" -#: ../common/username.c:45 libpq/auth.c:1881 +#: ../common/username.c:45 libpq/auth.c:1888 msgid "user does not exist" msgstr "usuario no existe" @@ -706,22 +910,22 @@ msgstr "Reintentando durante 30 segundos." msgid "You might have antivirus, backup, or similar software interfering with the database system." msgstr "Es posible que tenga antivirus, sistema de respaldos, o software similar interfiriendo con el sistema de bases de datos." -#: ../port/path.c:775 +#: ../port/path.c:852 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "no se pudo obtener el directorio de trabajo actual: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "no se pudo obtener el directorio de trabajo actual: %m\n" #: ../port/strerror.c:72 #, c-format msgid "operating system error %d" msgstr "error %d de sistema operativo" -#: ../port/thread.c:50 ../port/thread.c:86 +#: ../port/user.c:43 ../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "no se pudo buscar el usuario local de ID %d: %s" -#: ../port/thread.c:55 ../port/thread.c:91 +#: ../port/user.c:48 ../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "no existe un usuario local con ID %d" @@ -741,115 +945,104 @@ msgstr "no se pudo obtener el SID del grupo PowerUsers: código de error %lu\n" msgid "could not check access token membership: error code %lu\n" msgstr "no se pudo verificar el token de proceso: código de error %lu\n" -#: access/brin/brin.c:216 +#: access/brin/brin.c:405 #, c-format msgid "request for BRIN range summarization for index \"%s\" page %u was not recorded" msgstr "petición para sumarización BRIN de rango para el índice «%s» página %u no fue registrada" -#: access/brin/brin.c:1036 access/brin/brin.c:1137 access/gin/ginfast.c:1035 -#: access/transam/xlogfuncs.c:189 access/transam/xlogfuncs.c:214 -#: access/transam/xlogfuncs.c:247 access/transam/xlogfuncs.c:286 -#: access/transam/xlogfuncs.c:307 access/transam/xlogfuncs.c:328 -#: access/transam/xlogfuncs.c:398 access/transam/xlogfuncs.c:456 +#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 +#: access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 +#: access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 +#: access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 +#: access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 #, c-format msgid "recovery is in progress" msgstr "la recuperación está en proceso" -#: access/brin/brin.c:1037 access/brin/brin.c:1138 +#: access/brin/brin.c:1386 access/brin/brin.c:1494 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "Las funciones de control de BRIN no pueden ejecutarse durante la recuperación." -#: access/brin/brin.c:1042 access/brin/brin.c:1143 +#: access/brin/brin.c:1391 access/brin/brin.c:1499 #, c-format msgid "block number out of range: %lld" msgstr "número de bloque fuera de rango: %lld" -#: access/brin/brin.c:1086 access/brin/brin.c:1169 +#: access/brin/brin.c:1436 access/brin/brin.c:1525 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "«%s» no es un índice BRIN" -#: access/brin/brin.c:1102 access/brin/brin.c:1185 +#: access/brin/brin.c:1452 access/brin/brin.c:1541 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "no se pudo abrir la tabla padre del índice «%s»" -#: access/brin/brin_bloom.c:750 access/brin/brin_bloom.c:792 -#: access/brin/brin_minmax_multi.c:3011 access/brin/brin_minmax_multi.c:3148 -#: statistics/dependencies.c:663 statistics/dependencies.c:716 -#: statistics/mcv.c:1484 statistics/mcv.c:1515 statistics/mvdistinct.c:344 -#: statistics/mvdistinct.c:397 utils/adt/pseudotypes.c:43 -#: utils/adt/pseudotypes.c:77 utils/adt/tsgistidx.c:93 +#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 +#: parser/parse_utilcmd.c:2277 #, c-format -msgid "cannot accept a value of type %s" -msgstr "no se puede aceptar un valor de tipo %s" +msgid "index \"%s\" is not valid" +msgstr "el índice «%s» no es válido" -#: access/brin/brin_minmax_multi.c:2171 access/brin/brin_minmax_multi.c:2178 -#: access/brin/brin_minmax_multi.c:2185 utils/adt/timestamp.c:941 -#: utils/adt/timestamp.c:1518 utils/adt/timestamp.c:2708 -#: utils/adt/timestamp.c:2778 utils/adt/timestamp.c:2795 -#: utils/adt/timestamp.c:2848 utils/adt/timestamp.c:2887 -#: utils/adt/timestamp.c:3184 utils/adt/timestamp.c:3189 -#: utils/adt/timestamp.c:3194 utils/adt/timestamp.c:3244 -#: utils/adt/timestamp.c:3251 utils/adt/timestamp.c:3258 -#: utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3285 -#: utils/adt/timestamp.c:3292 utils/adt/timestamp.c:3322 -#: utils/adt/timestamp.c:3330 utils/adt/timestamp.c:3374 -#: utils/adt/timestamp.c:3796 utils/adt/timestamp.c:3920 -#: utils/adt/timestamp.c:4440 +#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 +#: access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 +#: statistics/dependencies.c:661 statistics/dependencies.c:714 +#: statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 +#: statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 +#: utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format -msgid "interval out of range" -msgstr "interval fuera de rango" +msgid "cannot accept a value of type %s" +msgstr "no se puede aceptar un valor de tipo %s" -#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 -#: access/brin/brin_pageops.c:852 access/gin/ginentrypage.c:110 -#: access/gist/gist.c:1442 access/spgist/spgdoinsert.c:2002 -#: access/spgist/spgdoinsert.c:2279 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 +#: access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 +#: access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 +#: access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "el tamaño de fila de índice %zu excede el máximo %zu para el índice «%s»" -#: access/brin/brin_revmap.c:393 access/brin/brin_revmap.c:399 +#: access/brin/brin_revmap.c:383 access/brin/brin_revmap.c:389 #, c-format msgid "corrupted BRIN index: inconsistent range map" msgstr "índice BRIN corrompido: mapa de rango inconsistente" -#: access/brin/brin_revmap.c:593 +#: access/brin/brin_revmap.c:583 #, c-format msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "tipo de página 0x%04X inesperado en el índice BRIN «%s» bloque %u" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:151 -#: access/gist/gistvalidate.c:153 access/hash/hashvalidate.c:139 +#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 +#: access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 #: access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with invalid support number %d" msgstr "familia de operadores «%s» de método de acceso %s contiene la función %s con número de soporte %d no válido" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:163 -#: access/gist/gistvalidate.c:165 access/hash/hashvalidate.c:118 +#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 +#: access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 #: access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d" msgstr "familia de operadores «%s» de método de acceso %s contiene la función %s con signatura incorrecta para el número de soporte %d" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:182 -#: access/gist/gistvalidate.c:185 access/hash/hashvalidate.c:160 +#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 +#: access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 #: access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d" msgstr "familia de operadores «%s» de método de acceso %s contiene el operador %s con número de estrategia %d no válido" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:195 +#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 #: access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 #: access/spgist/spgvalidate.c:237 #, c-format msgid "operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s" msgstr "familia de operadores «%s» de método de acceso %s contiene especificación ORDER BY no válida para el operador %s" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:208 -#: access/gist/gistvalidate.c:233 access/hash/hashvalidate.c:186 +#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 +#: access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 #: access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with wrong signature" @@ -872,38 +1065,38 @@ msgstr "la(s) función/funciones de soporte para los tipos %3$s y %4$s faltan de msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "faltan operadores de la clase de operadores «%s» del método de acceso %s" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:250 -#: access/gist/gistvalidate.c:274 +#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 +#: access/gist/gistvalidate.c:273 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d" msgstr "falta la función de soporte %3$d de la clase de operadores «%1$s» del método de acceso %2$s" -#: access/common/attmap.c:122 +#: access/common/attmap.c:121 #, c-format msgid "Returned type %s does not match expected type %s in column %d." msgstr "El tipo retornado %s no coincide con el tipo de registro esperado %s en la columna %d." -#: access/common/attmap.c:150 +#: access/common/attmap.c:149 #, c-format msgid "Number of returned columns (%d) does not match expected column count (%d)." msgstr "La cantidad de columnas retornadas (%d) no coincide con la cantidad esperada de columnas (%d)." -#: access/common/attmap.c:234 access/common/attmap.c:246 +#: access/common/attmap.c:233 access/common/attmap.c:245 #, c-format msgid "could not convert row type" msgstr "no se pudo convertir el tipo de registro" -#: access/common/attmap.c:235 +#: access/common/attmap.c:234 #, c-format msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s." msgstr "El atributo «%s» de tipo %s no coincide con el atributo correspondiente de tipo %s." -#: access/common/attmap.c:247 +#: access/common/attmap.c:246 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "El atributo «%s» de tipo %s no existe en el tipo %s." -#: access/common/heaptuple.c:1036 access/common/heaptuple.c:1371 +#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "el número de columnas (%d) excede el límite (%d)" @@ -913,124 +1106,110 @@ msgstr "el número de columnas (%d) excede el límite (%d)" msgid "number of index columns (%d) exceeds limit (%d)" msgstr "el número de columnas del índice (%d) excede el límite (%d)" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:950 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:970 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "fila de índice requiere %zu bytes, tamaño máximo es %zu" -#: access/common/printtup.c:292 tcop/fastpath.c:107 tcop/fastpath.c:454 -#: tcop/postgres.c:1944 +#: access/common/printtup.c:292 commands/explain.c:5376 tcop/fastpath.c:107 +#: tcop/fastpath.c:454 tcop/postgres.c:1956 #, c-format msgid "unsupported format code: %d" msgstr "código de formato no soportado: %d" -#: access/common/reloptions.c:521 access/common/reloptions.c:532 +#: access/common/reloptions.c:519 access/common/reloptions.c:530 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "Los valores aceptables son «on», «off» y «auto»." -#: access/common/reloptions.c:543 +#: access/common/reloptions.c:541 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "Los valores aceptables son «local» y «cascaded»." -#: access/common/reloptions.c:691 +#: access/common/reloptions.c:689 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "el límite de tipos de parámetros de relación definidos por el usuario ha sido excedido" -#: access/common/reloptions.c:1233 +#: access/common/reloptions.c:1231 #, c-format msgid "RESET must not include values for parameters" msgstr "RESET no debe incluir valores de parámetros" -#: access/common/reloptions.c:1265 +#: access/common/reloptions.c:1263 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "espacio de nombre de parámetro «%s» no reconocido" -#: access/common/reloptions.c:1302 commands/variable.c:1167 +#: access/common/reloptions.c:1300 commands/variable.c:1214 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "las tablas declaradas WITH OIDS no están soportadas" -#: access/common/reloptions.c:1470 +#: access/common/reloptions.c:1468 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "parámetro «%s» no reconocido" -#: access/common/reloptions.c:1582 +#: access/common/reloptions.c:1580 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "el parámetro «%s» fue especificado más de una vez" -#: access/common/reloptions.c:1598 +#: access/common/reloptions.c:1596 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "valor no válido para la opción booleana «%s»: «%s»" -#: access/common/reloptions.c:1610 +#: access/common/reloptions.c:1608 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "valor no válido para la opción entera «%s»: «%s»" -#: access/common/reloptions.c:1616 access/common/reloptions.c:1636 +#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "el valor %s está fuera del rango de la opción «%s»" -#: access/common/reloptions.c:1618 +#: access/common/reloptions.c:1616 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "Los valores aceptables están entre «%d» y «%d»." -#: access/common/reloptions.c:1630 +#: access/common/reloptions.c:1628 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "valor no válido para la opción de coma flotante «%s»: «%s»" -#: access/common/reloptions.c:1638 +#: access/common/reloptions.c:1636 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "Valores aceptables están entre «%f» y «%f»." -#: access/common/reloptions.c:1660 +#: access/common/reloptions.c:1658 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "valor no válido para la opción enum «%s»: %s" -#: access/common/reloptions.c:1991 -#, fuzzy, c-format -#| msgid "cannot truncate only a partitioned table" +#: access/common/reloptions.c:1989 +#, c-format msgid "cannot specify storage parameters for a partitioned table" -msgstr "no se puede truncar ONLY una tabla particionada" +msgstr "no se puede especificar parámetros de almacenamiento para una tabla particionada" -#: access/common/reloptions.c:1992 +#: access/common/reloptions.c:1990 #, c-format -msgid "Specify storage parameters for its leaf partitions, instead." -msgstr "" +msgid "Specify storage parameters for its leaf partitions instead." +msgstr "Especifique parámetros de almacenamiento para sus particiones hijas en su lugar." -#: access/common/toast_compression.c:33 +#: access/common/toast_compression.c:31 #, c-format msgid "compression method lz4 not supported" msgstr "el método de compresión lz4 no está soportado" -#: access/common/toast_compression.c:34 +#: access/common/toast_compression.c:32 #, c-format msgid "This functionality requires the server to be built with lz4 support." msgstr "Esta funcionalidad requiere que el servidor haya sido construido con soporte lz4." -#: access/common/tupdesc.c:837 commands/tablecmds.c:6953 -#: commands/tablecmds.c:12973 -#, fuzzy, c-format -#| msgid "mismatched array dimensions" -msgid "too many array dimensions" -msgstr "las dimensiones de array no coinciden" - -#: access/common/tupdesc.c:842 parser/parse_clause.c:772 -#: parser/parse_relation.c:1912 -#, c-format -msgid "column \"%s\" cannot be declared SETOF" -msgstr "la columna «%s» no puede ser declarada SETOF" - #: access/gin/ginbulk.c:44 #, c-format msgid "posting list is too long" @@ -1038,20 +1217,20 @@ msgstr "la «posting list» es demasiado larga" #: access/gin/ginbulk.c:45 #, c-format -msgid "Reduce maintenance_work_mem." -msgstr "Reduzca maintenance_work_mem." +msgid "Reduce \"maintenance_work_mem\"." +msgstr "Reduzca «maintenance_work_mem»." -#: access/gin/ginfast.c:1036 +#: access/gin/ginfast.c:1041 #, c-format msgid "GIN pending list cannot be cleaned up during recovery." msgstr "La lista de pendientes GIN no puede limpiarse durante la recuperación." -#: access/gin/ginfast.c:1043 +#: access/gin/ginfast.c:1048 #, c-format msgid "\"%s\" is not a GIN index" msgstr "«%s» no es un índice GIN" -#: access/gin/ginfast.c:1054 +#: access/gin/ginfast.c:1059 #, c-format msgid "cannot access temporary indexes of other sessions" msgstr "no se pueden acceder índices temporales de otras sesiones" @@ -1071,50 +1250,50 @@ msgstr "los índices GIN antiguos no soportan recorridos del índice completo ni msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "Para corregir esto, ejecute REINDEX INDEX \"%s\"." -#: access/gin/ginutil.c:146 executor/execExpr.c:2169 -#: utils/adt/arrayfuncs.c:3996 utils/adt/arrayfuncs.c:6683 -#: utils/adt/rowtypes.c:984 +#: access/gin/ginutil.c:147 executor/execExpr.c:2200 +#: utils/adt/arrayfuncs.c:4016 utils/adt/arrayfuncs.c:6712 +#: utils/adt/rowtypes.c:974 #, c-format msgid "could not identify a comparison function for type %s" msgstr "no se pudo identificar una función de comparación para el tipo %s" -#: access/gin/ginvalidate.c:92 access/gist/gistvalidate.c:93 +#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 #: access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 #, c-format msgid "operator family \"%s\" of access method %s contains support function %s with different left and right input types" msgstr "la familia de operadores «%s» del método de acceso %s contiene el procedimiento de soporte %s registrado entre tipos distintos" -#: access/gin/ginvalidate.c:260 +#: access/gin/ginvalidate.c:258 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d or %d" msgstr "falta la función de soporte %3$d o %4$d de la clase de operadores «%1$s» del método de accesso %2$s" -#: access/gin/ginvalidate.c:333 access/gist/gistvalidate.c:350 +#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 #: access/spgist/spgvalidate.c:387 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "el número de función de soporte %d no es válido para el método de acceso %s" -#: access/gist/gist.c:759 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "el índice «%s» contiene una tupla interna marcada como no válida" -#: access/gist/gist.c:761 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 #, c-format msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1." msgstr "Esto es causado por una división de página incompleta durante una recuperación antes de actualizar a PostgreSQL 9.1." -#: access/gist/gist.c:762 access/gist/gistutil.c:801 access/gist/gistutil.c:812 -#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:227 -#: access/hash/hashutil.c:238 access/hash/hashutil.c:250 -#: access/hash/hashutil.c:271 access/nbtree/nbtpage.c:809 -#: access/nbtree/nbtpage.c:820 +#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 +#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 +#: access/hash/hashutil.c:237 access/hash/hashutil.c:249 +#: access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 +#: access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "Por favor aplíquele REINDEX." -#: access/gist/gist.c:1176 +#: access/gist/gist.c:1196 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "arreglando división incompleta en el índice «%s», bloque %u" @@ -1129,52 +1308,52 @@ msgstr "el método picksplit para la columna %d del índice «%s» falló" msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command." msgstr "El índice no es óptimo. Para optimizarlo, contacte un desarrollador o trate de usar la columna en segunda posición en la orden CREATE INDEX." -#: access/gist/gistutil.c:798 access/hash/hashutil.c:224 -#: access/nbtree/nbtpage.c:806 +#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 +#: access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "índice «%s» contiene páginas vacías no esperadas en el bloque %u" -#: access/gist/gistutil.c:809 access/hash/hashutil.c:235 -#: access/hash/hashutil.c:247 access/nbtree/nbtpage.c:817 +#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 +#: access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "el índice «%s» contiene una página corrupta en el bloque %u" -#: access/gist/gistvalidate.c:203 +#: access/gist/gistvalidate.c:202 #, c-format msgid "operator family \"%s\" of access method %s contains unsupported ORDER BY specification for operator %s" msgstr "la familia de operadores «%s» del método de acceso %s contiene una especificación ORDER BY no soportada para el operador %s" -#: access/gist/gistvalidate.c:214 +#: access/gist/gistvalidate.c:213 #, c-format msgid "operator family \"%s\" of access method %s contains incorrect ORDER BY opfamily specification for operator %s" msgstr "la familia de operadores «%s» del método de acceso %s contiene una especificación de familia en ORDER BY incorrecta para el operador %s" -#: access/hash/hashfunc.c:279 access/hash/hashfunc.c:333 -#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:333 +#: utils/adt/varchar.c:1008 utils/adt/varchar.c:1065 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "no se pudo determinar qué ordenamiento usar para el hashing de cadenas" -#: access/hash/hashfunc.c:280 access/hash/hashfunc.c:334 catalog/heap.c:668 -#: catalog/heap.c:674 commands/createas.c:206 commands/createas.c:515 -#: commands/indexcmds.c:2023 commands/tablecmds.c:17490 commands/view.c:86 -#: regex/regc_pg_locale.c:243 utils/adt/formatting.c:1648 -#: utils/adt/formatting.c:1770 utils/adt/formatting.c:1893 utils/adt/like.c:191 -#: utils/adt/like_support.c:1025 utils/adt/varchar.c:739 -#: utils/adt/varchar.c:1010 utils/adt/varchar.c:1065 utils/adt/varlena.c:1518 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:334 catalog/heap.c:672 +#: catalog/heap.c:678 commands/createas.c:201 commands/createas.c:508 +#: commands/indexcmds.c:2021 commands/tablecmds.c:18178 commands/view.c:81 +#: regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 +#: utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 +#: utils/adt/like_support.c:1024 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1066 utils/adt/varlena.c:1521 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "Use la cláusula COLLATE para establecer el ordenamiento explícitamente." -#: access/hash/hashinsert.c:86 +#: access/hash/hashinsert.c:84 #, c-format msgid "index row size %zu exceeds hash maximum %zu" msgstr "el tamaño de fila de índice %zu excede el máximo para hash %zu" -#: access/hash/hashinsert.c:88 access/spgist/spgdoinsert.c:2006 -#: access/spgist/spgdoinsert.c:2283 access/spgist/spgutils.c:1011 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 +#: access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1031 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "Valores mayores a una página del buffer no pueden ser indexados." @@ -1189,17 +1368,17 @@ msgstr "número no válido de bloque de «overflow» %u" msgid "out of overflow pages in hash index \"%s\"" msgstr "se agotaron las páginas de desbordamiento en el índice hash «%s»" -#: access/hash/hashsearch.c:315 +#: access/hash/hashsearch.c:311 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "los índices hash no soportan recorridos del índice completo" -#: access/hash/hashutil.c:263 +#: access/hash/hashutil.c:262 #, c-format msgid "index \"%s\" is not a hash index" msgstr "el índice «%s» no es un índice hash" -#: access/hash/hashutil.c:269 +#: access/hash/hashutil.c:268 #, c-format msgid "index \"%s\" has wrong hash version" msgstr "el índice «%s» tiene una versión de hash incorrecta" @@ -1214,229 +1393,235 @@ msgstr "la familia de operadores «%s» del método de acceso %s no tiene funci msgid "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "faltan operadores entre tipos en la familia de operadores «%s» del método de acceso %s" -#: access/heap/heapam.c:2026 +#: access/heap/heapam.c:2206 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "no se pueden insertar tuplas en un ayudante paralelo" -#: access/heap/heapam.c:2545 +#: access/heap/heapam.c:2725 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "no se pueden eliminar tuplas durante una operación paralela" -#: access/heap/heapam.c:2592 +#: access/heap/heapam.c:2772 #, c-format msgid "attempted to delete invisible tuple" msgstr "se intentó eliminar una tupla invisible" -#: access/heap/heapam.c:3035 access/heap/heapam.c:5902 +#: access/heap/heapam.c:3220 access/heap/heapam.c:6501 access/index/genam.c:818 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "no se pueden actualizar tuplas durante una operación paralela" -#: access/heap/heapam.c:3163 +#: access/heap/heapam.c:3397 #, c-format msgid "attempted to update invisible tuple" msgstr "se intentó actualizar una tupla invisible" -#: access/heap/heapam.c:4550 access/heap/heapam.c:4588 -#: access/heap/heapam.c:4853 access/heap/heapam_handler.c:467 +#: access/heap/heapam.c:4908 access/heap/heapam.c:4946 +#: access/heap/heapam.c:5211 access/heap/heapam_handler.c:468 #, c-format msgid "could not obtain lock on row in relation \"%s\"" -msgstr "no se pudo bloquear un candado en la fila de la relación «%s»" +msgstr "no se pudo bloquear un “lock” en la fila de la relación «%s»" + +#: access/heap/heapam.c:6314 commands/trigger.c:3340 +#: executor/nodeModifyTable.c:2376 executor/nodeModifyTable.c:2467 +#, c-format +msgid "tuple to be updated was already modified by an operation triggered by the current command" +msgstr "el registro a ser actualizado ya fue modificado por una operación disparada por la orden actual" -#: access/heap/heapam_handler.c:412 +#: access/heap/heapam_handler.c:413 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update" msgstr "el registro a ser bloqueado ya fue movido a otra partición por un update concurrente" -#: access/heap/hio.c:517 access/heap/rewriteheap.c:659 +#: access/heap/hio.c:535 access/heap/rewriteheap.c:640 #, c-format msgid "row is too big: size %zu, maximum size %zu" msgstr "fila es demasiado grande: tamaño %zu, tamaño máximo %zu" -#: access/heap/rewriteheap.c:919 +#: access/heap/rewriteheap.c:885 #, c-format msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "no se pudo escribir al archivo «%s», se escribió %d de %d: %m" -#: access/heap/rewriteheap.c:1011 access/heap/rewriteheap.c:1128 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 #: access/transam/timeline.c:329 access/transam/timeline.c:481 -#: access/transam/xlog.c:2971 access/transam/xlog.c:3162 -#: access/transam/xlog.c:3938 access/transam/xlog.c:8740 -#: access/transam/xlogfuncs.c:702 backup/basebackup_server.c:151 -#: backup/basebackup_server.c:244 commands/dbcommands.c:518 -#: postmaster/postmaster.c:4554 postmaster/postmaster.c:5557 -#: replication/logical/origin.c:603 replication/slot.c:1770 -#: storage/file/copydir.c:157 storage/smgr/md.c:232 utils/time/snapmgr.c:1263 +#: access/transam/xlog.c:3255 access/transam/xlog.c:3446 +#: access/transam/xlog.c:4283 access/transam/xlog.c:9269 +#: access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 +#: backup/basebackup_server.c:242 commands/dbcommands.c:494 +#: postmaster/launch_backend.c:340 postmaster/postmaster.c:4114 +#: postmaster/walsummarizer.c:1212 replication/logical/origin.c:603 +#: replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 +#: utils/time/snapmgr.c:1234 #, c-format msgid "could not create file \"%s\": %m" msgstr "no se pudo crear archivo «%s»: %m" -#: access/heap/rewriteheap.c:1138 +#: access/heap/rewriteheap.c:1104 #, c-format msgid "could not truncate file \"%s\" to %u: %m" msgstr "no se pudo truncar el archivo «%s» a %u: %m" -#: access/heap/rewriteheap.c:1156 access/transam/timeline.c:384 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 #: access/transam/timeline.c:424 access/transam/timeline.c:498 -#: access/transam/xlog.c:3021 access/transam/xlog.c:3218 -#: access/transam/xlog.c:3950 commands/dbcommands.c:530 -#: postmaster/postmaster.c:4564 postmaster/postmaster.c:4574 +#: access/transam/xlog.c:3305 access/transam/xlog.c:3502 +#: access/transam/xlog.c:4295 commands/dbcommands.c:506 +#: postmaster/launch_backend.c:351 postmaster/launch_backend.c:363 #: replication/logical/origin.c:615 replication/logical/origin.c:657 -#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1767 -#: replication/slot.c:1805 storage/file/buffile.c:545 -#: storage/file/copydir.c:197 utils/init/miscinit.c:1605 -#: utils/init/miscinit.c:1616 utils/init/miscinit.c:1624 utils/misc/guc.c:4331 -#: utils/misc/guc.c:4362 utils/misc/guc.c:5490 utils/misc/guc.c:5508 -#: utils/time/snapmgr.c:1268 utils/time/snapmgr.c:1275 +#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1788 +#: replication/slot.c:2094 storage/file/buffile.c:545 +#: storage/file/copydir.c:197 utils/init/miscinit.c:1655 +#: utils/init/miscinit.c:1666 utils/init/miscinit.c:1674 utils/misc/guc.c:4491 +#: utils/misc/guc.c:4522 utils/misc/guc.c:5675 utils/misc/guc.c:5693 +#: utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 #, c-format msgid "could not write to file \"%s\": %m" msgstr "no se pudo escribir a archivo «%s»: %m" -#: access/heap/vacuumlazy.c:482 +#: access/heap/vacuumlazy.c:473 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "haciendo vacuum agresivamente a «%s.%s.%s»" -#: access/heap/vacuumlazy.c:487 +#: access/heap/vacuumlazy.c:478 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "haciendo vacuum a «%s.%s.%s»" -#: access/heap/vacuumlazy.c:635 +#: access/heap/vacuumlazy.c:626 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "se terminó el vacuum de «%s.%s.%s»: recorridos de índice: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:637 #, c-format msgid "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "vacuum agresivo automático para prevenir wraparound de la tabla «%s.%s.%s»: recorridos de índice: %d\n" -#: access/heap/vacuumlazy.c:648 +#: access/heap/vacuumlazy.c:639 #, c-format msgid "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "vacuum automático para prevenir wraparound de la tabla «%s.%s.%s»: recorridos de índice: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:644 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "vacuum agresivo automático de la tabla «%s.%s.%s»: recorridos de índice: %d\n" -#: access/heap/vacuumlazy.c:655 +#: access/heap/vacuumlazy.c:646 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "vacuum automático de la tabla «%s.%s.%s»: recorridos de índice: %d\n" -#: access/heap/vacuumlazy.c:662 +#: access/heap/vacuumlazy.c:653 #, c-format msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" msgstr "páginas: %u eliminadas, %u quedan, %u recorridas (%.2f%% del total)\n" -#: access/heap/vacuumlazy.c:669 +#: access/heap/vacuumlazy.c:660 #, c-format msgid "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" msgstr "tuplas: %lld eliminadas, %lld permanecen, %lld están muertas pero aún no se pueden quitar\n" -#: access/heap/vacuumlazy.c:675 +#: access/heap/vacuumlazy.c:666 #, c-format msgid "tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n" msgstr "tuplas faltantes: %lld muertas en %u páginas no eliminadas debido a contención del lock de limpieza\n" -#: access/heap/vacuumlazy.c:681 +#: access/heap/vacuumlazy.c:672 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" -msgstr "" +msgstr "punto de corte de eliminación: %u, que era %d XIDs de antiguo cuando la operación terminó\n" -#: access/heap/vacuumlazy.c:688 +#: access/heap/vacuumlazy.c:679 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "nuevo relfrozenxid: %u, que está %d XIDs más adelante del valor anterior\n" -#: access/heap/vacuumlazy.c:696 +#: access/heap/vacuumlazy.c:687 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "nuevo relminmxid: %u, que está %d MXIDs más adelante del valor anterior\n" -#: access/heap/vacuumlazy.c:699 -#, fuzzy, c-format -#| msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" +#: access/heap/vacuumlazy.c:690 +#, c-format msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" -msgstr "en %u páginas de la tabla (%.2f%% del total) se eliminaron %lld identificadores de elementos muertos\n" +msgstr "congelado: %u páginas de la tabla (%.2f%% del total) tuvieron %lld tuplas congeladas\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:698 msgid "index scan not needed: " msgstr "recorrido de índice no necesario: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:700 msgid "index scan needed: " msgstr "recorrido de índice necesario: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:702 #, c-format msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" msgstr "en %u páginas de la tabla (%.2f%% del total) se eliminaron %lld identificadores de elementos muertos\n" -#: access/heap/vacuumlazy.c:716 +#: access/heap/vacuumlazy.c:707 msgid "index scan bypassed: " msgstr "recorrido de índice pasado por alto: " -#: access/heap/vacuumlazy.c:718 +#: access/heap/vacuumlazy.c:709 msgid "index scan bypassed by failsafe: " msgstr "recorrido de índice pasado por alto debido a modo failsafe: " -#: access/heap/vacuumlazy.c:720 +#: access/heap/vacuumlazy.c:711 #, c-format msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" msgstr "%u páginas de la tabla (%.2f%% del total) tienen %lld identificadores de elementos muertos\n" -#: access/heap/vacuumlazy.c:735 +#: access/heap/vacuumlazy.c:726 #, c-format msgid "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u reusable\n" msgstr "índice «%s»: páginas: %u en total, %u recientemente eliminadas, %u eliminadas hasta ahora, %u reusables\n" -#: access/heap/vacuumlazy.c:747 commands/analyze.c:795 +#: access/heap/vacuumlazy.c:738 commands/analyze.c:794 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "tiempos de E/S: lectura: %.3f ms, escritura: %.3f ms\n" -#: access/heap/vacuumlazy.c:757 commands/analyze.c:798 +#: access/heap/vacuumlazy.c:748 commands/analyze.c:797 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "tasa lectura promedio: %.3f MB/s, tasa escritura promedio: %.3f MB/s\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:800 +#: access/heap/vacuumlazy.c:751 commands/analyze.c:799 #, c-format msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" msgstr "uso de búfers: %lld aciertos, %lld fallos, %lld ensuciados\n" -#: access/heap/vacuumlazy.c:765 +#: access/heap/vacuumlazy.c:756 #, c-format msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" msgstr "uso de WAL: %lld registros, %lld imágenes de página completa, %llu bytes\n" -#: access/heap/vacuumlazy.c:769 commands/analyze.c:804 +#: access/heap/vacuumlazy.c:760 commands/analyze.c:803 #, c-format msgid "system usage: %s" msgstr "uso de sistema: %s" -#: access/heap/vacuumlazy.c:2482 +#: access/heap/vacuumlazy.c:2170 #, c-format msgid "table \"%s\": removed %lld dead item identifiers in %u pages" msgstr "tabla «%s»: se eliminaron %lld identificadores de elementos muertos en %u páginas" -#: access/heap/vacuumlazy.c:2642 +#: access/heap/vacuumlazy.c:2324 #, c-format msgid "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans" msgstr "pasando por alto el mantenimiento no esencial de la tabla «%s.%s.%s» como mecanismo de seguridad (failsafe) luego de %d recorridos de índice" -#: access/heap/vacuumlazy.c:2645 +#: access/heap/vacuumlazy.c:2327 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "El relfrozenxid o el relminmxid de la tabla es demasiado antiguo." -#: access/heap/vacuumlazy.c:2646 +#: access/heap/vacuumlazy.c:2328 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" @@ -1445,67 +1630,67 @@ msgstr "" "Considere incrementar el parámetro de configuración «maintenance_work_mem» o «autovacuum_work_mem».\n" "Es probable que también deba considerar otras formas para que VACUUM pueda mantener el paso de la asignación de IDs de transacción." -#: access/heap/vacuumlazy.c:2891 +#: access/heap/vacuumlazy.c:2590 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" -msgstr "«%s»: suspendiendo el truncado debido a una petición de candado en conflicto" +msgstr "«%s»: suspendiendo el truncado debido a una petición de “lock” en conflicto" -#: access/heap/vacuumlazy.c:2961 +#: access/heap/vacuumlazy.c:2660 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "tabla «%s»: truncadas %u a %u páginas" -#: access/heap/vacuumlazy.c:3023 +#: access/heap/vacuumlazy.c:2722 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "tabla «%s»: suspendiendo el truncado debido a una petición de bloqueo en conflicto" -#: access/heap/vacuumlazy.c:3183 +#: access/heap/vacuumlazy.c:2841 #, c-format msgid "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary tables in parallel" msgstr "desactivando el comportamiento paralelo de vacuum en «%s» --- no se puede hacer vacuum de tablas temporales en paralelo" -#: access/heap/vacuumlazy.c:3399 +#: access/heap/vacuumlazy.c:3108 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "recorriendo el bloque %u posición %u de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3402 +#: access/heap/vacuumlazy.c:3111 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "recorriendo el bloque %u de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3406 +#: access/heap/vacuumlazy.c:3115 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "recorriendo la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3414 +#: access/heap/vacuumlazy.c:3123 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "haciendo «vacuum» al bloque %u posición %u de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3417 +#: access/heap/vacuumlazy.c:3126 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "haciendo «vacuum» al bloque %u de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3421 +#: access/heap/vacuumlazy.c:3130 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "mientras se hacía «vacuum» a la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3426 commands/vacuumparallel.c:1074 +#: access/heap/vacuumlazy.c:3135 commands/vacuumparallel.c:1112 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "mientras se hacía «vacuum» al índice «%s» de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3431 commands/vacuumparallel.c:1080 +#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1118 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "mientras se limpiaba el índice «%s» de la relación «%s.%s»" -#: access/heap/vacuumlazy.c:3437 +#: access/heap/vacuumlazy.c:3146 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "error mientras se truncaba la relación «%s.%s» a %u bloques" @@ -1520,19 +1705,24 @@ msgstr "el método de acceso «%s» no es de tipo %s" msgid "index access method \"%s\" does not have a handler" msgstr "el método de acceso «%s» no tiene manejador" -#: access/index/genam.c:490 +#: access/index/genam.c:489 #, c-format msgid "transaction aborted during system catalog scan" msgstr "transacción abortada durante recorrido de catálogos de sistema" -#: access/index/indexam.c:142 catalog/objectaddress.c:1394 -#: commands/indexcmds.c:2852 commands/tablecmds.c:272 commands/tablecmds.c:296 -#: commands/tablecmds.c:17191 commands/tablecmds.c:18959 +#: access/index/genam.c:657 access/index/indexam.c:82 +#, c-format +msgid "cannot access index \"%s\" while it is being reindexed" +msgstr "no se puede acceder el índice «%s» mientras está siendo reindexado" + +#: access/index/indexam.c:203 catalog/objectaddress.c:1356 +#: commands/indexcmds.c:2851 commands/tablecmds.c:281 commands/tablecmds.c:305 +#: commands/tablecmds.c:17873 commands/tablecmds.c:19762 #, c-format msgid "\"%s\" is not an index" msgstr "«%s» no es un índice" -#: access/index/indexam.c:979 +#: access/index/indexam.c:1028 #, c-format msgid "operator class %s has no options" msgstr "clase de operadores «%s» no tiene opciones" @@ -1552,38 +1742,38 @@ msgstr "Ya existe la llave %s." msgid "This may be because of a non-immutable index expression." msgstr "Esto puede deberse a una expresión de índice no inmutable." -#: access/nbtree/nbtpage.c:158 access/nbtree/nbtpage.c:607 -#: parser/parse_utilcmd.c:2317 +#: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 +#: parser/parse_utilcmd.c:2323 #, c-format msgid "index \"%s\" is not a btree" msgstr "el índice «%s» no es un btree" -#: access/nbtree/nbtpage.c:165 access/nbtree/nbtpage.c:614 +#: access/nbtree/nbtpage.c:164 access/nbtree/nbtpage.c:618 #, c-format msgid "version mismatch in index \"%s\": file version %d, current version %d, minimal supported version %d" msgstr "discordancia de versión en índice «%s»: versión de archivo %d, versión de código %d, mínima versión soportada %d" -#: access/nbtree/nbtpage.c:1862 +#: access/nbtree/nbtpage.c:1861 #, c-format msgid "index \"%s\" contains a half-dead internal page" msgstr "el índice «%s» contiene una página interna parcialmente muerta" -#: access/nbtree/nbtpage.c:1864 +#: access/nbtree/nbtpage.c:1863 #, c-format msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it." msgstr "Esto puede ser causado por la interrupción de un VACUUM en la versión 9.3 o anteriores, antes de actualizar. Ejecute REINDEX por favor." -#: access/nbtree/nbtutils.c:2663 +#: access/nbtree/nbtutils.c:5108 #, c-format msgid "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" msgstr "el tamaño de fila de índice %1$zu excede el máximo %3$zu para btree versión %2$u para el índice «%4$s»" -#: access/nbtree/nbtutils.c:2669 +#: access/nbtree/nbtutils.c:5114 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "La tupla de índice hace referencia a la tupla (%u,%u) en la relación «%s»." -#: access/nbtree/nbtutils.c:2673 +#: access/nbtree/nbtutils.c:5118 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1597,12 +1787,18 @@ msgstr "" msgid "operator family \"%s\" of access method %s is missing support function for types %s and %s" msgstr "falta una función de soporte para los tipos %3$s y %4$s en la familia de operadores «%1$s» del método de acceso %2$s" +#: access/sequence/sequence.c:75 access/table/table.c:145 +#: optimizer/util/plancat.c:144 +#, c-format +msgid "cannot open relation \"%s\"" +msgstr "no se puede abrir la relación «%s»" + #: access/spgist/spgutils.c:245 #, c-format msgid "compress method must be defined when leaf type is different from input type" msgstr "método «compress» debe estar definido cuando el tipo hoja es distinto del tipo de entrada" -#: access/spgist/spgutils.c:1008 +#: access/spgist/spgutils.c:1028 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "el tamaño de tupla interna SP-GiST %zu excede el máximo %zu" @@ -1617,69 +1813,64 @@ msgstr "el tipo de dato hoja SP-GiST %s no coincide con el tipo declarado %s" msgid "operator family \"%s\" of access method %s is missing support function %d for type %s" msgstr "falta la función de soporte %3$d para el tipo %4$s de la clase de operadores «%1$s» del método de accesso %2$s" -#: access/table/table.c:145 optimizer/util/plancat.c:145 -#, fuzzy, c-format -#| msgid "cannot change relation \"%s\"" -msgid "cannot open relation \"%s\"" -msgstr "no se puede cambiar la relación «%s»" - -#: access/table/tableam.c:265 +#: access/table/tableam.c:255 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "el tid (%u, %u) no es válido para la relación «%s»" -#: access/table/tableamapi.c:116 +#: access/table/tableamapi.c:109 #, c-format -msgid "%s cannot be empty." -msgstr "%s no puede ser vacío." +msgid "\"%s\" cannot be empty." +msgstr "«%s» no puede ser vacío." -#: access/table/tableamapi.c:123 access/transam/xlogrecovery.c:4774 +#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4859 #, c-format -msgid "%s is too long (maximum %d characters)." -msgstr "%s es demasiado largo (máximo %d caracteres)." +msgid "\"%s\" is too long (maximum %d characters)." +msgstr "«%s» es demasiado largo (máximo %d caracteres)." -#: access/table/tableamapi.c:146 +#: access/table/tableamapi.c:139 #, c-format msgid "table access method \"%s\" does not exist" msgstr "no existe el método de acceso de tabla «%s»" -#: access/table/tableamapi.c:151 +#: access/table/tableamapi.c:144 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "No existe el método de acceso de tabla «%s»." -#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:152 +#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:151 #, c-format msgid "sample percentage must be between 0 and 100" msgstr "el porcentaje de muestreo debe estar entre 0 y 100" -#: access/transam/commit_ts.c:279 +#: access/transam/commit_ts.c:287 #, c-format msgid "cannot retrieve commit timestamp for transaction %u" msgstr "no se puede obtener el timestamp de compromiso de la transacción %u" -#: access/transam/commit_ts.c:377 +#: access/transam/commit_ts.c:385 #, c-format msgid "could not get commit timestamp data" msgstr "no se pudo obtener datos de compromiso de transacción" -#: access/transam/commit_ts.c:379 +#: access/transam/commit_ts.c:387 #, c-format msgid "Make sure the configuration parameter \"%s\" is set on the primary server." msgstr "Asegúrese que el parámetro de configuración «%s» esté definido en el servidor primario." -#: access/transam/commit_ts.c:381 +#: access/transam/commit_ts.c:389 #, c-format msgid "Make sure the configuration parameter \"%s\" is set." msgstr "Asegúrese que el parámetro de configuración «%s» esté definido." -#: access/transam/multixact.c:1023 +#: access/transam/multixact.c:1091 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"" -msgstr "la base de datos no está aceptando órdenes que generen nuevos MultiXactIds para evitar pérdida de datos debido al reciclaje de transacciones en la base de datos «%s»" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"" +msgstr "la base de datos no está aceptando órdenes que asignen nuevos MultiXactIds para evitar pérdida de datos debido al “wraparound” en la base de datos «%s»" -#: access/transam/multixact.c:1025 access/transam/multixact.c:1032 -#: access/transam/multixact.c:1056 access/transam/multixact.c:1065 +#: access/transam/multixact.c:1093 access/transam/multixact.c:1100 +#: access/transam/multixact.c:1124 access/transam/multixact.c:1133 +#: access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" @@ -1688,247 +1879,250 @@ msgstr "" "Ejecute VACUUM de la base completa en esa base de datos.\n" "Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." -#: access/transam/multixact.c:1030 +#: access/transam/multixact.c:1098 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u" -msgstr "la base de datos no está aceptando órdenes que generen nuevos MultiXactIds para evitar pérdida de datos debido al problema del reciclaje de transacciones en la base con OID %u" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u" +msgstr "la base de datos no está aceptando órdenes que asignen nuevos MultiXactIds para evitar pérdida de datos debido al “wraparound” en la base con OID %u" -#: access/transam/multixact.c:1051 access/transam/multixact.c:2333 +#: access/transam/multixact.c:1119 access/transam/multixact.c:2474 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used" msgstr[0] "base de datos «%s» debe ser limpiada antes de que %u más MultiXactId sea usado" msgstr[1] "base de datos «%s» debe ser limpiada dentro de que %u más MultiXactIds sean usados" -#: access/transam/multixact.c:1060 access/transam/multixact.c:2342 +#: access/transam/multixact.c:1128 access/transam/multixact.c:2483 #, c-format msgid "database with OID %u must be vacuumed before %u more MultiXactId is used" msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used" msgstr[0] "base de datos con OID %u debe ser limpiada antes de que %u más MultiXactId sea usado" msgstr[1] "base de datos con OID %u debe ser limpiada antes de que %u más MultiXactIds sean usados" -#: access/transam/multixact.c:1121 +#: access/transam/multixact.c:1189 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "límite de miembros de multixact alcanzado" -#: access/transam/multixact.c:1122 +#: access/transam/multixact.c:1190 #, c-format msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member." msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members." msgstr[0] "Esta orden crearía un multixact con %u miembros, pero el espacio que queda sólo sirve para %u miembro." msgstr[1] "Esta orden crearía un multixact con %u miembros, pero el espacio que queda sólo sirve para %u miembros." -#: access/transam/multixact.c:1127 +#: access/transam/multixact.c:1195 #, c-format -msgid "Execute a database-wide VACUUM in database with OID %u with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Ejecute un VACUUM de la base completa en la base de datos con OID %u con vacuum_multixact_freeze_min_age y vacuum_multixact_freeze_table_age reducidos." +msgid "Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Ejecute un VACUUM de la base completa en la base de datos con OID %u con «vacuum_multixact_freeze_min_age» y «vacuum_multixact_freeze_table_age» reducidos." -#: access/transam/multixact.c:1158 +#: access/transam/multixact.c:1226 #, c-format msgid "database with OID %u must be vacuumed before %d more multixact member is used" msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used" msgstr[0] "base de datos con OID %u debe ser limpiada antes de que %d miembro más de multixact sea usado" msgstr[1] "base de datos con OID %u debe ser limpiada antes de que %d más miembros de multixact sean usados" -#: access/transam/multixact.c:1163 +#: access/transam/multixact.c:1231 #, c-format -msgid "Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Ejecute un VACUUM de la base completa en esa base de datos con vacuum_multixact_freeze_min_age y vacuum_multixact_freeze_table_age reducidos." +msgid "Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Ejecute un VACUUM de la base completa en esa base de datos con «vacuum_multixact_freeze_min_age» y «vacuum_multixact_freeze_table_age» reducidos." -#: access/transam/multixact.c:1302 +#: access/transam/multixact.c:1371 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" -msgstr "el MultiXactId %u ya no existe -- aparente problema por reciclaje" +msgstr "el MultiXactId %u ya no existe -- “wraparound” aparente" -#: access/transam/multixact.c:1308 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" -msgstr "el MultiXactId %u no se ha creado aún -- aparente problema por reciclaje" +msgstr "el MultiXactId %u no se ha creado aún -- “wraparound” aparente" -#: access/transam/multixact.c:2338 access/transam/multixact.c:2347 -#: access/transam/varsup.c:151 access/transam/varsup.c:158 -#: access/transam/varsup.c:466 access/transam/varsup.c:473 +#: access/transam/multixact.c:2479 access/transam/multixact.c:2488 #, c-format msgid "" -"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n" +"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"Para evitar que la base de datos se desactive, ejecute VACUUM en esa base de datos.\n" +"Para evitar fallos de asignación de MultiXactId, ejecute VACUUM en esa base de datos.\n" "Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." -#: access/transam/multixact.c:2622 +#: access/transam/multixact.c:2767 #, c-format msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" -msgstr "las protecciones de reciclaje de miembros de multixact están inhabilitadas porque el multixact más antiguo %u en checkpoint no existe en disco" +msgstr "las protecciones de “wraparound” de multixact están inhabilitadas porque el multixact más antiguo %u en checkpoint no existe en disco" -#: access/transam/multixact.c:2644 +#: access/transam/multixact.c:2789 #, c-format msgid "MultiXact member wraparound protections are now enabled" -msgstr "las protecciones de reciclaje de miembros de multixact están habilitadas" +msgstr "las protecciones de “wraparound” de miembros de multixact están habilitadas" -#: access/transam/multixact.c:3027 +#: access/transam/multixact.c:3180 #, c-format msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "multixact más antiguo %u no encontrado, multixact más antiguo es %u, omitiendo el truncado" -#: access/transam/multixact.c:3045 +#: access/transam/multixact.c:3198 #, c-format msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation" msgstr "no se puede truncar hasta el MultiXact %u porque no existe en disco, omitiendo el truncado" -#: access/transam/multixact.c:3359 +#: access/transam/multixact.c:3517 #, c-format msgid "invalid MultiXactId: %u" msgstr "el MultiXactId no es válido: %u" -#: access/transam/parallel.c:729 access/transam/parallel.c:848 +#: access/transam/parallel.c:748 access/transam/parallel.c:867 #, c-format msgid "parallel worker failed to initialize" msgstr "el ayudante paralelo no pudo iniciar" -#: access/transam/parallel.c:730 access/transam/parallel.c:849 +#: access/transam/parallel.c:749 access/transam/parallel.c:868 #, c-format msgid "More details may be available in the server log." msgstr "Puede haber más detalles disponibles en el log del servidor." -#: access/transam/parallel.c:910 +#: access/transam/parallel.c:929 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "postmaster terminó durante una transacción paralela" -#: access/transam/parallel.c:1097 +#: access/transam/parallel.c:1116 #, c-format msgid "lost connection to parallel worker" msgstr "se ha perdido la conexión al ayudante paralelo" -#: access/transam/parallel.c:1163 access/transam/parallel.c:1165 +#: access/transam/parallel.c:1172 access/transam/parallel.c:1174 msgid "parallel worker" msgstr "ayudante paralelo" -#: access/transam/parallel.c:1319 +#: access/transam/parallel.c:1344 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "no se pudo mapear el segmento de memoria compartida dinámica" -#: access/transam/parallel.c:1324 +#: access/transam/parallel.c:1349 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "número mágico no válido en segmento de memoria compartida dinámica" -#: access/transam/rmgr.c:84 +#: access/transam/rmgr.c:93 #, c-format msgid "resource manager with ID %d not registered" msgstr "el gestor de recursos con ID %d no está registrado" -#: access/transam/rmgr.c:85 +#: access/transam/rmgr.c:94 #, c-format -msgid "Include the extension module that implements this resource manager in shared_preload_libraries." -msgstr "Incluya el módulo de extensión que implementa este gestor de recursos en shared_preload_libraries." +msgid "Include the extension module that implements this resource manager in \"shared_preload_libraries\"." +msgstr "Incluya el módulo de extensión que implementa este gestor de recursos en «shared_preload_libraries»." -#: access/transam/rmgr.c:101 +#: access/transam/rmgr.c:110 #, c-format msgid "custom resource manager name is invalid" msgstr "el nombre de gestor de recursos personalizado no es válido" -#: access/transam/rmgr.c:102 +#: access/transam/rmgr.c:111 #, c-format msgid "Provide a non-empty name for the custom resource manager." msgstr "Provea un nombre no vacío para el gestor de recursos personalizado." -#: access/transam/rmgr.c:105 +#: access/transam/rmgr.c:114 #, c-format msgid "custom resource manager ID %d is out of range" msgstr "el ID %d de gestor de recursos está fuera de rango" -#: access/transam/rmgr.c:106 +#: access/transam/rmgr.c:115 #, c-format msgid "Provide a custom resource manager ID between %d and %d." msgstr "Provea un ID de gestor de recursos personalizado entre %d y %d." -#: access/transam/rmgr.c:111 access/transam/rmgr.c:116 -#: access/transam/rmgr.c:128 +#: access/transam/rmgr.c:120 access/transam/rmgr.c:125 +#: access/transam/rmgr.c:137 #, c-format msgid "failed to register custom resource manager \"%s\" with ID %d" msgstr "no se pudo registrar un gestor de recursos personalizado «%s» con ID %d" -#: access/transam/rmgr.c:112 +#: access/transam/rmgr.c:121 #, c-format -msgid "Custom resource manager must be registered while initializing modules in shared_preload_libraries." -msgstr "El gestor de recursos personalizado debe ser registrado en shared_preload_libraries." +msgid "Custom resource manager must be registered while initializing modules in \"shared_preload_libraries\"." +msgstr "El gestor de recursos personalizado debe ser registrado en «shared_preload_libraries» al inicializar módulos." -#: access/transam/rmgr.c:117 +#: access/transam/rmgr.c:126 #, c-format msgid "Custom resource manager \"%s\" already registered with the same ID." msgstr "El gestor de recursos «%s» ya está registrado con el mismo ID." -#: access/transam/rmgr.c:129 +#: access/transam/rmgr.c:138 #, c-format msgid "Existing resource manager with ID %d has the same name." msgstr "El gestor de recursos con ID %d tiene el mismo nombre." -#: access/transam/rmgr.c:135 +#: access/transam/rmgr.c:144 #, c-format msgid "registered custom resource manager \"%s\" with ID %d" msgstr "se registró el gestor de recursos «%s» con ID %d" -#: access/transam/slru.c:714 +#: access/transam/slru.c:361 +#, c-format +msgid "\"%s\" must be a multiple of %d" +msgstr "«%s» debe ser múltiple de %d" + +#: access/transam/slru.c:830 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "el archivo «%s» no existe, leyendo como ceros" -#: access/transam/slru.c:946 access/transam/slru.c:952 -#: access/transam/slru.c:960 access/transam/slru.c:965 -#: access/transam/slru.c:972 access/transam/slru.c:977 -#: access/transam/slru.c:984 access/transam/slru.c:991 +#: access/transam/slru.c:1059 access/transam/slru.c:1065 +#: access/transam/slru.c:1073 access/transam/slru.c:1078 +#: access/transam/slru.c:1085 access/transam/slru.c:1090 +#: access/transam/slru.c:1097 access/transam/slru.c:1104 #, c-format msgid "could not access status of transaction %u" msgstr "no se pudo encontrar el estado de la transacción %u" -#: access/transam/slru.c:947 +#: access/transam/slru.c:1060 #, c-format msgid "Could not open file \"%s\": %m." msgstr "No se pudo abrir el archivo «%s»: %m." -#: access/transam/slru.c:953 +#: access/transam/slru.c:1066 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "No se pudo posicionar (seek) en el archivo «%s» a la posición %d: %m." -#: access/transam/slru.c:961 +#: access/transam/slru.c:1074 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "No se pudo leer desde el archivo «%s» en la posición %d: %m." -#: access/transam/slru.c:966 +#: access/transam/slru.c:1079 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "No se pudo leer desde el archivo «%s» en la posición %d: se leyeron muy pocos bytes." -#: access/transam/slru.c:973 +#: access/transam/slru.c:1086 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "No se pudo escribir al archivo «%s» en la posición %d: %m." -#: access/transam/slru.c:978 +#: access/transam/slru.c:1091 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "No se pudo escribir al archivo «%s» en la posición %d: se escribieron muy pocos bytes." -#: access/transam/slru.c:985 +#: access/transam/slru.c:1098 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "No se pudo sincronizar (fsync) archivo «%s»: %m." -#: access/transam/slru.c:992 +#: access/transam/slru.c:1105 #, c-format msgid "Could not close file \"%s\": %m." msgstr "No se pudo cerrar el archivo «%s»: %m." -#: access/transam/slru.c:1253 +#: access/transam/slru.c:1431 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" -msgstr "no se pudo truncar el directorio «%s»: aparente problema por reciclaje de transacciones" +msgstr "no se pudo truncar el directorio «%s»: “wraparound” aparente" #: access/transam/timeline.c:163 access/transam/timeline.c:168 #, c-format @@ -1970,773 +2164,824 @@ msgstr "IDs de timeline deben ser menores que el ID de timeline del hijo." msgid "requested timeline %u is not in this server's history" msgstr "el timeline %u solicitado no está en la historia de este servidor" -#: access/transam/twophase.c:385 +#: access/transam/twophase.c:368 #, c-format msgid "transaction identifier \"%s\" is too long" msgstr "identificador de transacción «%s» es demasiado largo" -#: access/transam/twophase.c:392 +#: access/transam/twophase.c:375 #, c-format msgid "prepared transactions are disabled" msgstr "las transacciones preparadas están deshabilitadas" -#: access/transam/twophase.c:393 +#: access/transam/twophase.c:376 #, c-format -msgid "Set max_prepared_transactions to a nonzero value." -msgstr "Defina max_prepared_transactions a un valor distinto de cero." +msgid "Set \"max_prepared_transactions\" to a nonzero value." +msgstr "Defina «max_prepared_transactions» a un valor distinto de cero." -#: access/transam/twophase.c:412 +#: access/transam/twophase.c:395 #, c-format msgid "transaction identifier \"%s\" is already in use" msgstr "identificador de transacción «%s» ya está siendo utilizado" -#: access/transam/twophase.c:421 access/transam/twophase.c:2484 +#: access/transam/twophase.c:404 access/transam/twophase.c:2531 #, c-format msgid "maximum number of prepared transactions reached" msgstr "se alcanzó el número máximo de transacciones preparadas" -#: access/transam/twophase.c:422 access/transam/twophase.c:2485 +#: access/transam/twophase.c:405 access/transam/twophase.c:2532 #, c-format -msgid "Increase max_prepared_transactions (currently %d)." -msgstr "Incremente max_prepared_transactions (actualmente es %d)." +msgid "Increase \"max_prepared_transactions\" (currently %d)." +msgstr "Incremente «max_prepared_transactions» (actualmente es %d)." -#: access/transam/twophase.c:598 +#: access/transam/twophase.c:580 #, c-format msgid "prepared transaction with identifier \"%s\" is busy" msgstr "transacción preparada con identificador «%s» está ocupada" -#: access/transam/twophase.c:604 +#: access/transam/twophase.c:586 #, c-format msgid "permission denied to finish prepared transaction" msgstr "se ha denegado el permiso para finalizar la transacción preparada" -#: access/transam/twophase.c:605 +#: access/transam/twophase.c:587 #, c-format msgid "Must be superuser or the user that prepared the transaction." msgstr "Debe ser superusuario o el usuario que preparó la transacción." -#: access/transam/twophase.c:616 +#: access/transam/twophase.c:598 #, c-format msgid "prepared transaction belongs to another database" msgstr "la transacción preparada pertenece a otra base de datos" -#: access/transam/twophase.c:617 +#: access/transam/twophase.c:599 #, c-format msgid "Connect to the database where the transaction was prepared to finish it." msgstr "Conéctese a la base de datos donde la transacción fue preparada para terminarla." -#: access/transam/twophase.c:632 +#: access/transam/twophase.c:614 #, c-format msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "transacción preparada con identificador «%s» no existe" -#: access/transam/twophase.c:1167 +#: access/transam/twophase.c:1174 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "el largo máximo del archivo de estado de dos fases fue excedido" -#: access/transam/twophase.c:1322 +#: access/transam/twophase.c:1329 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" msgstr[0] "tamaño incorrecto de archivo «%s»: %lld byte" msgstr[1] "tamaño incorrecto de archivo «%s»: %lld bytes" -#: access/transam/twophase.c:1331 +#: access/transam/twophase.c:1338 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "alineamiento incorrecto del offset del CRC para el archivo «%s»" -#: access/transam/twophase.c:1349 +#: access/transam/twophase.c:1356 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "no se pudo leer el archivo «%s»: leídos %d de %lld" -#: access/transam/twophase.c:1364 +#: access/transam/twophase.c:1371 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "número mágico no válido almacenado en archivo «%s»" -#: access/transam/twophase.c:1370 +#: access/transam/twophase.c:1377 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "tamaño no válido en archivo «%s»" -#: access/transam/twophase.c:1382 +#: access/transam/twophase.c:1389 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "la suma de verificación calculada no coincide con el valor almacenado en el archivo «%s»" -#: access/transam/twophase.c:1412 access/transam/xlogrecovery.c:590 -#: replication/logical/logical.c:209 replication/walsender.c:687 +#: access/transam/twophase.c:1419 access/transam/xlogrecovery.c:565 +#: postmaster/walsummarizer.c:936 replication/logical/logical.c:211 +#: replication/walsender.c:836 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "Falló mientras se emplazaba un procesador de lectura de WAL." -#: access/transam/twophase.c:1422 +#: access/transam/twophase.c:1429 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "no se pudo leer el archivo de estado de dos fases desde WAL en %X/%X: %s" -#: access/transam/twophase.c:1427 +#: access/transam/twophase.c:1434 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "no se pudo leer el archivo de estado de dos fases desde WAL en %X/%X" -#: access/transam/twophase.c:1435 +#: access/transam/twophase.c:1442 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "los datos de estado de dos fases esperados no están presentes en WAL en %X/%X" -#: access/transam/twophase.c:1731 +#: access/transam/twophase.c:1745 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "no se pudo recrear archivo «%s»: %m" -#: access/transam/twophase.c:1858 +#: access/transam/twophase.c:1872 #, c-format msgid "%u two-phase state file was written for a long-running prepared transaction" msgid_plural "%u two-phase state files were written for long-running prepared transactions" msgstr[0] "%u archivo de estado de dos fases fue escrito para transacción de larga duración" msgstr[1] "%u archivos de estado de dos fases fueron escritos para transacciones de larga duración" -#: access/transam/twophase.c:2092 +#: access/transam/twophase.c:2107 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "recuperando transacción preparada %u desde memoria compartida" -#: access/transam/twophase.c:2185 +#: access/transam/twophase.c:2200 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "eliminando archivo obsoleto de estado de dos fases para transacción %u" -#: access/transam/twophase.c:2192 +#: access/transam/twophase.c:2207 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "eliminando de memoria estado de dos fases obsoleto para transacción %u" -#: access/transam/twophase.c:2205 +#: access/transam/twophase.c:2220 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "eliminando archivo futuro de estado de dos fases para transacción %u" -#: access/transam/twophase.c:2212 +#: access/transam/twophase.c:2227 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "eliminando estado de dos fases futuro de memoria para transacción %u" -#: access/transam/twophase.c:2237 +#: access/transam/twophase.c:2252 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "archivo de estado de dos fases corrupto para transacción %u" -#: access/transam/twophase.c:2242 +#: access/transam/twophase.c:2257 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "estado de dos fases en memoria corrupto para transacción %u" -#: access/transam/varsup.c:129 +#: access/transam/twophase.c:2514 #, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database \"%s\"" -msgstr "la base de datos no está aceptando órdenes para evitar pérdida de datos debido al problema del reciclaje de transacciones en la base de datos «%s»" +msgid "could not recover two-phase state file for transaction %u" +msgstr "no se pudo recuperar el archivo de estado de dos fases para la transacción %u" -#: access/transam/varsup.c:131 access/transam/varsup.c:138 +#: access/transam/twophase.c:2516 #, c-format -msgid "" -"Stop the postmaster and vacuum that database in single-user mode.\n" -"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." -msgstr "" -"Detenga el postmaster y ejecute VACUUM de la base completa en esa base de datos.\n" -"Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." +msgid "Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk." +msgstr "El archivo de estado en dos fases ha sido encontrado en el registro de WAL %X/%X, pero esta transacción ya ha sido restaurada desde disco." + +#: access/transam/twophase.c:2524 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 +#, c-format +msgid "could not access file \"%s\": %m" +msgstr "no se pudo acceder al archivo «%s»: %m" + +#: access/transam/varsup.c:156 +#, c-format +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"" +msgstr "la base de datos no está aceptando órdenes que asignen nuevos IDs de transacción para evitar pérdida de datos debido al “wraparound” en la base de datos «%s»" -#: access/transam/varsup.c:136 +#: access/transam/varsup.c:163 #, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database with OID %u" -msgstr "la base de datos no está aceptando órdenes para evitar pérdida de datos debido al problema del reciclaje de transacciones en la base con OID %u" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u" +msgstr "la base de datos no está aceptando órdenes que generen nuevos IDs de transacción para evitar pérdida de datos debido al “wraparound” en la base con OID %u" -#: access/transam/varsup.c:148 access/transam/varsup.c:463 +#: access/transam/varsup.c:175 access/transam/varsup.c:490 #, c-format msgid "database \"%s\" must be vacuumed within %u transactions" msgstr "base de datos «%s» debe ser limpiada dentro de %u transacciones" -#: access/transam/varsup.c:155 access/transam/varsup.c:470 +#: access/transam/varsup.c:178 +#, c-format +msgid "" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "" +"Para evitar fallas de asignación de IDs de transacción, ejecute VACUUM en esa base de datos.\n" +"Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." + +#: access/transam/varsup.c:182 access/transam/varsup.c:497 #, c-format msgid "database with OID %u must be vacuumed within %u transactions" msgstr "base de datos con OID %u debe ser limpiada dentro de %u transacciones" -#: access/transam/xact.c:1102 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 +#: access/transam/varsup.c:500 +#, c-format +msgid "" +"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "" +"Para evitar que la base de datos se desactive, ejecute VACUUM en esa base de datos.\n" +"Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." + +#: access/transam/xact.c:649 +#, c-format +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "no se puede asignar IDs de transacción durante una operación paralela" + +#: access/transam/xact.c:840 +#, c-format +msgid "cannot modify data in a parallel worker" +msgstr "no se pueden modificar datos en un proceso ayudante paralelo" + +#: access/transam/xact.c:1115 +#, c-format +msgid "cannot start commands during a parallel operation" +msgstr "no se puede iniciar órdenes durante una operación paralela" + +#: access/transam/xact.c:1123 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "no se pueden tener más de 2^32-2 órdenes en una transacción" -#: access/transam/xact.c:1643 +#: access/transam/xact.c:1664 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "se superó el número máximo de subtransacciones comprometidas (%d)" -#: access/transam/xact.c:2513 +#: access/transam/xact.c:2561 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "no se puede hacer PREPARE de una transacción que ha operado en objetos temporales" -#: access/transam/xact.c:2523 +#: access/transam/xact.c:2571 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "no se puede hacer PREPARE de una transacción que ha exportado snapshots" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3489 +#: access/transam/xact.c:3593 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s no puede ser ejecutado dentro de un bloque de transacción" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3499 +#: access/transam/xact.c:3603 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%s no puede ser ejecutado dentro de una subtransacción" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3509 -#, fuzzy, c-format -#| msgid "%s cannot be executed from a function" +#: access/transam/xact.c:3613 +#, c-format msgid "%s cannot be executed within a pipeline" -msgstr "%s no puede ser ejecutado desde una función" +msgstr "%s no puede ser ejecutado en un “pipeline”" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3519 +#: access/transam/xact.c:3623 #, c-format msgid "%s cannot be executed from a function" msgstr "%s no puede ser ejecutado desde una función" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3590 access/transam/xact.c:3915 -#: access/transam/xact.c:3994 access/transam/xact.c:4117 -#: access/transam/xact.c:4268 access/transam/xact.c:4337 -#: access/transam/xact.c:4448 +#: access/transam/xact.c:3694 access/transam/xact.c:4019 +#: access/transam/xact.c:4098 access/transam/xact.c:4221 +#: access/transam/xact.c:4372 access/transam/xact.c:4441 +#: access/transam/xact.c:4552 #, c-format msgid "%s can only be used in transaction blocks" msgstr "la orden %s sólo puede ser usada en bloques de transacción" -#: access/transam/xact.c:3801 +#: access/transam/xact.c:3905 #, c-format msgid "there is already a transaction in progress" msgstr "ya hay una transacción en curso" -#: access/transam/xact.c:3920 access/transam/xact.c:3999 -#: access/transam/xact.c:4122 +#: access/transam/xact.c:4024 access/transam/xact.c:4103 +#: access/transam/xact.c:4226 #, c-format msgid "there is no transaction in progress" msgstr "no hay una transacción en curso" -#: access/transam/xact.c:4010 +#: access/transam/xact.c:4114 #, c-format msgid "cannot commit during a parallel operation" msgstr "no se puede comprometer una transacción durante una operación paralela" -#: access/transam/xact.c:4133 +#: access/transam/xact.c:4237 #, c-format msgid "cannot abort during a parallel operation" msgstr "no se puede abortar durante una operación paralela" -#: access/transam/xact.c:4232 +#: access/transam/xact.c:4336 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "no se pueden definir savepoints durante una operación paralela" -#: access/transam/xact.c:4319 +#: access/transam/xact.c:4423 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "no se pueden liberar savepoints durante una operación paralela" -#: access/transam/xact.c:4329 access/transam/xact.c:4380 -#: access/transam/xact.c:4440 access/transam/xact.c:4489 +#: access/transam/xact.c:4433 access/transam/xact.c:4484 +#: access/transam/xact.c:4544 access/transam/xact.c:4593 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "no existe el «savepoint» «%s»" -#: access/transam/xact.c:4386 access/transam/xact.c:4495 +#: access/transam/xact.c:4490 access/transam/xact.c:4599 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "el «savepoint» «%s» no existe dentro del nivel de savepoint actual" -#: access/transam/xact.c:4428 +#: access/transam/xact.c:4532 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "no se puede hacer rollback a un savepoint durante una operación paralela" -#: access/transam/xact.c:4556 -#, c-format -msgid "cannot start subtransactions during a parallel operation" -msgstr "no se pueden iniciar subtransacciones durante una operación paralela" - -#: access/transam/xact.c:4624 -#, c-format -msgid "cannot commit subtransactions during a parallel operation" -msgstr "no se pueden comprometer subtransacciones durante una operación paralela" - -#: access/transam/xact.c:5270 +#: access/transam/xact.c:5376 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "no se pueden tener más de 2^32-1 subtransacciones en una transacción" -#: access/transam/xlog.c:1466 +#: access/transam/xlog.c:1542 #, c-format msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" msgstr "petición para sincronizar (flush) más allá del final del WAL generado; petición %X/%X, posición actual %X/%X" +#: access/transam/xlog.c:1769 +#, c-format +msgid "cannot read past end of generated WAL: requested %X/%X, current position %X/%X" +msgstr "no se puede ler más allá del final del WAL generado; petición %X/%X, posición actual %X/%X" + +#: access/transam/xlog.c:2210 access/transam/xlog.c:4501 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "El tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB." + #: access/transam/xlog.c:2228 #, c-format -msgid "could not write to log file %s at offset %u, length %zu: %m" -msgstr "no se pudo escribir archivo de registro %s en la posición %u, largo %zu: %m" +msgid "\"%s\" must be set to -1 during binary upgrade mode." +msgstr "«%s» debe ser establecido a -1 durante el modo de actualización binaria." + +#: access/transam/xlog.c:2477 +#, c-format +msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" +msgstr "no se pudo escribir archivo de registro «%s» en la posición %u, largo %zu: %m" -#: access/transam/xlog.c:3455 access/transam/xlogutils.c:833 -#: replication/walsender.c:2725 +#: access/transam/xlog.c:3739 access/transam/xlogutils.c:831 +#: replication/walsender.c:3045 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "el segmento de WAL solicitado %s ya ha sido eliminado" -#: access/transam/xlog.c:3739 +#: access/transam/xlog.c:4061 #, c-format msgid "could not rename file \"%s\": %m" msgstr "no se pudo renombrar el archivo «%s»: %m" -#: access/transam/xlog.c:3781 access/transam/xlog.c:3791 +#: access/transam/xlog.c:4104 access/transam/xlog.c:4115 +#: access/transam/xlog.c:4136 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "no existe el directorio WAL «%s»" -#: access/transam/xlog.c:3797 +#: access/transam/xlog.c:4121 access/transam/xlog.c:4142 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "creando el directorio WAL faltante «%s»" -#: access/transam/xlog.c:3800 commands/dbcommands.c:3095 +#: access/transam/xlog.c:4125 access/transam/xlog.c:4145 +#: commands/dbcommands.c:3262 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "no se pudo crear el directorio faltante «%s»: %m" -#: access/transam/xlog.c:3867 +#: access/transam/xlog.c:4212 #, c-format msgid "could not generate secret authorization token" msgstr "no se pudo generar un token de autorización secreto" -#: access/transam/xlog.c:4017 access/transam/xlog.c:4026 -#: access/transam/xlog.c:4050 access/transam/xlog.c:4057 -#: access/transam/xlog.c:4064 access/transam/xlog.c:4069 -#: access/transam/xlog.c:4076 access/transam/xlog.c:4083 -#: access/transam/xlog.c:4090 access/transam/xlog.c:4097 -#: access/transam/xlog.c:4104 access/transam/xlog.c:4111 -#: access/transam/xlog.c:4120 access/transam/xlog.c:4127 -#: utils/init/miscinit.c:1762 +#: access/transam/xlog.c:4363 access/transam/xlog.c:4373 +#: access/transam/xlog.c:4399 access/transam/xlog.c:4407 +#: access/transam/xlog.c:4415 access/transam/xlog.c:4421 +#: access/transam/xlog.c:4429 access/transam/xlog.c:4437 +#: access/transam/xlog.c:4445 access/transam/xlog.c:4453 +#: access/transam/xlog.c:4461 access/transam/xlog.c:4469 +#: access/transam/xlog.c:4479 access/transam/xlog.c:4487 +#: utils/init/miscinit.c:1812 #, c-format msgid "database files are incompatible with server" msgstr "los archivos de base de datos son incompatibles con el servidor" -#: access/transam/xlog.c:4018 +#: access/transam/xlog.c:4364 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)." msgstr "Los archivos de base de datos fueron inicializados con PG_CONTROL_VERSION %d (0x%08x), pero el servidor fue compilado con PG_CONTROL_VERSION %d (0x%08x)." -#: access/transam/xlog.c:4022 +#: access/transam/xlog.c:4368 #, c-format msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb." msgstr "Este puede ser un problema de discordancia en el orden de bytes. Parece que necesitará ejecutar initdb." -#: access/transam/xlog.c:4027 +#: access/transam/xlog.c:4374 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "Los archivos de base de datos fueron inicializados con PG_CONTROL_VERSION %d, pero el servidor fue compilado con PG_CONTROL_VERSION %d." -#: access/transam/xlog.c:4030 access/transam/xlog.c:4054 -#: access/transam/xlog.c:4061 access/transam/xlog.c:4066 +#: access/transam/xlog.c:4377 access/transam/xlog.c:4403 +#: access/transam/xlog.c:4411 access/transam/xlog.c:4417 #, c-format msgid "It looks like you need to initdb." msgstr "Parece que necesita ejecutar initdb." -#: access/transam/xlog.c:4041 +#: access/transam/xlog.c:4389 #, c-format msgid "incorrect checksum in control file" msgstr "la suma de verificación es incorrecta en el archivo de control" -#: access/transam/xlog.c:4051 +#: access/transam/xlog.c:4400 #, c-format msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." msgstr "Los archivos de base de datos fueron inicializados con CATALOG_VERSION_NO %d, pero el servidor fue compilado con CATALOG_VERSION_NO %d." -#: access/transam/xlog.c:4058 +#: access/transam/xlog.c:4408 #, c-format msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." msgstr "Los archivos de la base de datos fueron inicializados con MAXALIGN %d, pero el servidor fue compilado con MAXALIGN %d." -#: access/transam/xlog.c:4065 +#: access/transam/xlog.c:4416 #, c-format msgid "The database cluster appears to use a different floating-point number format than the server executable." msgstr "Los archivos de la base de datos parecen usar un formato de número de coma flotante distinto al del ejecutable del servidor." -#: access/transam/xlog.c:4070 +#: access/transam/xlog.c:4422 #, c-format msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." msgstr "Los archivos de base de datos fueron inicializados con BLCKSZ %d, pero el servidor fue compilado con BLCKSZ %d." -#: access/transam/xlog.c:4073 access/transam/xlog.c:4080 -#: access/transam/xlog.c:4087 access/transam/xlog.c:4094 -#: access/transam/xlog.c:4101 access/transam/xlog.c:4108 -#: access/transam/xlog.c:4115 access/transam/xlog.c:4123 -#: access/transam/xlog.c:4130 +#: access/transam/xlog.c:4425 access/transam/xlog.c:4433 +#: access/transam/xlog.c:4441 access/transam/xlog.c:4449 +#: access/transam/xlog.c:4457 access/transam/xlog.c:4465 +#: access/transam/xlog.c:4473 access/transam/xlog.c:4482 +#: access/transam/xlog.c:4490 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "Parece que necesita recompilar o ejecutar initdb." -#: access/transam/xlog.c:4077 +#: access/transam/xlog.c:4430 #, c-format msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." msgstr "Los archivos de la base de datos fueron inicializados con RELSEG_SIZE %d, pero el servidor fue compilado con RELSEG_SIZE %d." -#: access/transam/xlog.c:4084 +#: access/transam/xlog.c:4438 #, c-format msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." msgstr "Los archivos de base de datos fueron inicializados con XLOG_BLCKSZ %d, pero el servidor fue compilado con XLOG_BLCKSZ %d." -#: access/transam/xlog.c:4091 +#: access/transam/xlog.c:4446 #, c-format msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." msgstr "Los archivos de la base de datos fueron inicializados con NAMEDATALEN %d, pero el servidor fue compilado con NAMEDATALEN %d." -#: access/transam/xlog.c:4098 +#: access/transam/xlog.c:4454 #, c-format msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." msgstr "Los archivos de la base de datos fueron inicializados con INDEX_MAX_KEYS %d, pero el servidor fue compilado con INDEX_MAX_KEYS %d." -#: access/transam/xlog.c:4105 +#: access/transam/xlog.c:4462 #, c-format msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." msgstr "Los archivos de la base de datos fueron inicializados con TOAST_MAX_CHUNK_SIZE %d, pero el servidor fue compilado con TOAST_MAX_CHUNK_SIZE %d." -#: access/transam/xlog.c:4112 +#: access/transam/xlog.c:4470 #, c-format msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." msgstr "Los archivos de base de datos fueron inicializados con LOBLKSIZE %d, pero el servidor fue compilado con LOBLKSIZE %d." -#: access/transam/xlog.c:4121 +#: access/transam/xlog.c:4480 #, c-format msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL." msgstr "Los archivos de base de datos fueron inicializados sin USE_FLOAT8_BYVAL, pero el servidor fue compilado con USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4128 +#: access/transam/xlog.c:4488 #, c-format msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL." msgstr "Los archivos de base de datos fueron inicializados con USE_FLOAT8_BYVAL, pero el servidor fue compilado sin USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4137 +#: access/transam/xlog.c:4497 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d byte" -msgstr[1] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d bytes" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "tamaño de segmento de WAL no válido (%d byte) en archivo de control" +msgstr[1] "tamaño de segmento de WAL no válido (%d bytes) en archivo de control" -#: access/transam/xlog.c:4149 +#: access/transam/xlog.c:4510 #, c-format msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "«min_wal_size» debe ser al menos el doble de «wal_segment_size»" -#: access/transam/xlog.c:4153 +#: access/transam/xlog.c:4514 #, c-format msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "«max_wal_size» debe ser al menos el doble de «wal_segment_size»" -#: access/transam/xlog.c:4308 catalog/namespace.c:4335 -#: commands/tablespace.c:1216 commands/user.c:2536 commands/variable.c:72 -#: utils/error/elog.c:2205 +#: access/transam/xlog.c:4662 catalog/namespace.c:4696 +#: commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 +#: replication/slot.c:2429 tcop/postgres.c:3715 utils/error/elog.c:2247 #, c-format msgid "List syntax is invalid." msgstr "La sintaxis de lista no es válida." -#: access/transam/xlog.c:4354 commands/user.c:2552 commands/variable.c:173 -#: utils/error/elog.c:2231 +#: access/transam/xlog.c:4708 commands/user.c:2545 commands/variable.c:173 +#: tcop/postgres.c:3731 utils/error/elog.c:2273 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "Palabra clave no reconocida: «%s»." -#: access/transam/xlog.c:4768 +#: access/transam/xlog.c:5129 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "no se pudo escribir el archivo WAL de boostrap: %m" -#: access/transam/xlog.c:4776 +#: access/transam/xlog.c:5137 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "no se pudo sincronizar (fsync) el archivo de WAL de bootstrap: %m" -#: access/transam/xlog.c:4782 +#: access/transam/xlog.c:5143 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "no se pudo cerrar el archivo WAL de bootstrap: %m" -#: access/transam/xlog.c:4999 +#: access/transam/xlog.c:5368 #, c-format -msgid "WAL was generated with wal_level=minimal, cannot continue recovering" -msgstr "el WAL fue generado con wal_level=minimal, no se puede continuar con la recuperación" +msgid "WAL was generated with \"wal_level=minimal\", cannot continue recovering" +msgstr "el WAL fue generado con «wal_level=minimal», no se puede continuar con la recuperación" -#: access/transam/xlog.c:5000 +#: access/transam/xlog.c:5369 #, c-format -msgid "This happens if you temporarily set wal_level=minimal on the server." -msgstr "Esto sucede si temporalmente define wal_level=minimal en el servidor." +msgid "This happens if you temporarily set \"wal_level=minimal\" on the server." +msgstr "Esto sucede si temporalmente define «wal_level=minimal» en el servidor." -#: access/transam/xlog.c:5001 +#: access/transam/xlog.c:5370 #, c-format -msgid "Use a backup taken after setting wal_level to higher than minimal." -msgstr "Utilice un respaldo tomado después de establecer wal_level a un valor superior a minimal." +msgid "Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." +msgstr "Utilice un respaldo tomado después de establecer «wal_level» a un valor superior a «minimal»." -#: access/transam/xlog.c:5065 +#: access/transam/xlog.c:5435 #, c-format msgid "control file contains invalid checkpoint location" -msgstr "el archivo de control contiene una ubicación no válida de punto de control" +msgstr "el archivo de control contiene una ubicación no válida de checkpoint" -#: access/transam/xlog.c:5076 +#: access/transam/xlog.c:5446 #, c-format msgid "database system was shut down at %s" msgstr "el sistema de bases de datos fue apagado en %s" -#: access/transam/xlog.c:5082 +#: access/transam/xlog.c:5452 #, c-format msgid "database system was shut down in recovery at %s" msgstr "el sistema de bases de datos fue apagado durante la recuperación en %s" -#: access/transam/xlog.c:5088 +#: access/transam/xlog.c:5458 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "el apagado del sistema de datos fue interrumpido; última vez registrada en funcionamiento en %s" -#: access/transam/xlog.c:5094 +#: access/transam/xlog.c:5464 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "el sistema de bases de datos fue interrumpido durante la recuperación en %s" -#: access/transam/xlog.c:5096 +#: access/transam/xlog.c:5466 #, c-format msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "Esto probablemente significa que algunos datos están corruptos y tendrá que usar el respaldo más reciente para la recuperación." -#: access/transam/xlog.c:5102 +#: access/transam/xlog.c:5472 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "el sistema de bases de datos fue interrumpido durante la recuperación en el instante de registro %s" -#: access/transam/xlog.c:5104 +#: access/transam/xlog.c:5474 #, c-format msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target." msgstr "Si esto ha ocurrido más de una vez, algunos datos podrían estar corruptos y podría ser necesario escoger un punto de recuperación anterior." -#: access/transam/xlog.c:5110 +#: access/transam/xlog.c:5480 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "el sistema de bases de datos fue interrumpido; última vez en funcionamiento en %s" -#: access/transam/xlog.c:5116 +#: access/transam/xlog.c:5487 #, c-format msgid "control file contains invalid database cluster state" msgstr "el archivo de control contiene un estado no válido del clúster" -#: access/transam/xlog.c:5500 +#: access/transam/xlog.c:5875 #, c-format msgid "WAL ends before end of online backup" msgstr "WAL termina antes del fin del respaldo en línea" -#: access/transam/xlog.c:5501 +#: access/transam/xlog.c:5876 #, c-format msgid "All WAL generated while online backup was taken must be available at recovery." msgstr "Todo el WAL generado durante el respaldo en línea debe estar disponible durante la recuperación." -#: access/transam/xlog.c:5504 +#: access/transam/xlog.c:5880 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL termina antes del punto de recuperación consistente" -#: access/transam/xlog.c:5550 +#: access/transam/xlog.c:5926 #, c-format msgid "selected new timeline ID: %u" msgstr "seleccionado nuevo ID de timeline: %u" -#: access/transam/xlog.c:5583 +#: access/transam/xlog.c:5959 #, c-format msgid "archive recovery complete" msgstr "recuperación completa" -#: access/transam/xlog.c:6185 +#: access/transam/xlog.c:6612 #, c-format msgid "shutting down" msgstr "apagando" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6224 +#: access/transam/xlog.c:6651 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "empezando restartpoint:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6236 +#: access/transam/xlog.c:6663 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "empezando checkpoint:%s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6301 +#: access/transam/xlog.c:6728 #, c-format msgid "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" -msgstr "" +msgstr "restartpoint completo: escritos %d búfers (%.1f%%); %d archivos WAL añadidos, %d eliminados, %d reciclados; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; archivos sincronizados=%d, más largo=%ld.%03d s, promedio=%ld.%03d s; distancia=%d kB, estimación=%d kB; lsn=%X/%X, lsn de redo=%X/%X" -#: access/transam/xlog.c:6324 +#: access/transam/xlog.c:6751 #, c-format msgid "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" -msgstr "" +msgstr "checkpoint completo: escritos %d búfers (%.1f%%); %d archivos WAL añadidos, %d eliminados, %d reciclados; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; archivos sincronizados=%d, más largo=%ld.%03d s, promedio=%ld.%03d s; distancia=%d kB, estimación=%d kB; lsn=%X/%X, lsn de redo=%X/%X" -#: access/transam/xlog.c:6762 +#: access/transam/xlog.c:7233 #, c-format msgid "concurrent write-ahead log activity while database system is shutting down" msgstr "hay actividad de WAL mientras el sistema se está apagando" -#: access/transam/xlog.c:7323 +#: access/transam/xlog.c:7818 #, c-format msgid "recovery restart point at %X/%X" msgstr "restartpoint de recuperación en %X/%X" -#: access/transam/xlog.c:7325 +#: access/transam/xlog.c:7820 #, c-format msgid "Last completed transaction was at log time %s." msgstr "Última transacción completada al tiempo de registro %s." -#: access/transam/xlog.c:7573 +#: access/transam/xlog.c:8082 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "punto de recuperación «%s» creado en %X/%X" -#: access/transam/xlog.c:7780 +#: access/transam/xlog.c:8289 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "el respaldo en línea fue cancelado, la recuperación no puede continuar" -#: access/transam/xlog.c:7837 +#: access/transam/xlog.c:8347 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "ID de timeline %u inesperado (debería ser %u) en el registro de checkpoint de detención" -#: access/transam/xlog.c:7895 +#: access/transam/xlog.c:8405 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "ID de timeline %u inesperado (debería ser %u) en el registro de checkpoint «online»" -#: access/transam/xlog.c:7924 +#: access/transam/xlog.c:8434 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "ID de timeline %u inesperado (debería ser %u) en el registro de fin-de-recuperación" -#: access/transam/xlog.c:8191 +#: access/transam/xlog.c:8705 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "no se pudo sincronizar (fsync write-through) el archivo «%s»: %m" -#: access/transam/xlog.c:8196 +#: access/transam/xlog.c:8710 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "no se pudo sincronizar (fdatasync) archivo «%s»: %m" -#: access/transam/xlog.c:8281 access/transam/xlog.c:8604 +#: access/transam/xlog.c:8797 access/transam/xlog.c:9133 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "el nivel de WAL no es suficiente para hacer un respaldo en línea" -#: access/transam/xlog.c:8282 access/transam/xlog.c:8605 -#: access/transam/xlogfuncs.c:254 +#: access/transam/xlog.c:8798 access/transam/xlogfuncs.c:248 #, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "wal_level debe ser definido a «replica» o «logical» al inicio del servidor." +msgid "\"wal_level\" must be set to \"replica\" or \"logical\" at server start." +msgstr "«wal_level» debe ser definido a «replica» o «logical» al inicio del servidor." -#: access/transam/xlog.c:8287 +#: access/transam/xlog.c:8803 #, c-format msgid "backup label too long (max %d bytes)" msgstr "la etiqueta de respaldo es demasiado larga (máximo %d bytes)" -#: access/transam/xlog.c:8408 +#: access/transam/xlog.c:8924 #, c-format -msgid "WAL generated with full_page_writes=off was replayed since last restartpoint" -msgstr "el WAL generado con full_page_writes=off fue restaurado desde el último restartpoint" +msgid "WAL generated with \"full_page_writes=off\" was replayed since last restartpoint" +msgstr "el WAL generado con «full_page_writes=off» fue restaurado desde el último restartpoint" -#: access/transam/xlog.c:8410 access/transam/xlog.c:8693 +#: access/transam/xlog.c:8926 access/transam/xlog.c:9222 #, c-format -msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the primary, and then try an online backup again." -msgstr "Esto significa que el respaldo que estaba siendo tomado en el standby está corrupto y no debería usarse. Active full_page_writes y ejecute CHECKPOINT en el primario, luego trate de ejecutar un respaldo en línea nuevamente." +msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, and then try an online backup again." +msgstr "Esto significa que el respaldo que estaba siendo tomado en el standby está corrupto y no debería usarse. Active «full_page_writes» y ejecute CHECKPOINT en el primario, luego trate de ejecutar un respaldo en línea nuevamente." -#: access/transam/xlog.c:8477 backup/basebackup.c:1351 utils/adt/misc.c:354 +#: access/transam/xlog.c:9006 backup/basebackup.c:1417 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "no se pudo leer el enlace simbólico «%s»: %m" -#: access/transam/xlog.c:8484 backup/basebackup.c:1356 utils/adt/misc.c:359 +#: access/transam/xlog.c:9013 backup/basebackup.c:1422 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "la ruta «%s» del enlace simbólico es demasiado larga" -#: access/transam/xlog.c:8643 backup/basebackup.c:1217 +#: access/transam/xlog.c:9134 +#, c-format +msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgstr "wal_level debe ser definido a «replica» o «logical» al inicio del servidor." + +#: access/transam/xlog.c:9172 backup/basebackup.c:1281 #, c-format msgid "the standby was promoted during online backup" msgstr "el standby fue promovido durante el respaldo en línea" -#: access/transam/xlog.c:8644 backup/basebackup.c:1218 +#: access/transam/xlog.c:9173 backup/basebackup.c:1282 #, c-format msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup." msgstr "Esto significa que el respaldo que se estaba tomando está corrupto y no debería ser usado. Trate de ejecutar un nuevo respaldo en línea." -#: access/transam/xlog.c:8691 +#: access/transam/xlog.c:9220 #, c-format -msgid "WAL generated with full_page_writes=off was replayed during online backup" -msgstr "el WAL generado con full_page_writes=off fue restaurado durante el respaldo en línea" +msgid "WAL generated with \"full_page_writes=off\" was replayed during online backup" +msgstr "el WAL generado con «full_page_writes=off» fue restaurado durante el respaldo en línea" -#: access/transam/xlog.c:8807 +#: access/transam/xlog.c:9336 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "respaldo base completo, esperando que se archiven los segmentos WAL requeridos" -#: access/transam/xlog.c:8821 +#: access/transam/xlog.c:9350 #, c-format msgid "still waiting for all required WAL segments to be archived (%d seconds elapsed)" msgstr "todavía en espera de que todos los segmentos WAL requeridos sean archivados (han pasado %d segundos)" -#: access/transam/xlog.c:8823 +#: access/transam/xlog.c:9352 #, c-format -msgid "Check that your archive_command is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." -msgstr "Verifique que su archive_command se esté ejecutando con normalidad. Puede cancelar este respaldo con confianza, pero el respaldo de la base de datos no será utilizable a menos que disponga de todos los segmentos de WAL." +msgid "Check that your \"archive_command\" is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." +msgstr "Verifique que su «archive_command» se esté ejecutando con normalidad. Puede cancelar este respaldo con confianza, pero el respaldo de la base de datos no será utilizable a menos que disponga de todos los segmentos de WAL." -#: access/transam/xlog.c:8830 +#: access/transam/xlog.c:9359 #, c-format msgid "all required WAL segments have been archived" msgstr "todos los segmentos de WAL requeridos han sido archivados" -#: access/transam/xlog.c:8834 +#: access/transam/xlog.c:9363 #, c-format msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup" msgstr "el archivado de WAL no está activo; debe asegurarse que todos los segmentos WAL requeridos se copian por algún otro mecanismo para completar el respaldo" -#: access/transam/xlog.c:8873 +#: access/transam/xlog.c:9402 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "abortando el backup porque el proceso servidor terminó antes de que pg_backup_stop fuera invocada" -#: access/transam/xlogarchive.c:207 +#: access/transam/xlogarchive.c:213 #, c-format msgid "archive file \"%s\" has wrong size: %lld instead of %lld" msgstr "el archivo «%s» tiene tamaño erróneo: %lld en lugar de %lld" -#: access/transam/xlogarchive.c:216 +#: access/transam/xlogarchive.c:222 #, c-format msgid "restored log file \"%s\" from archive" msgstr "se ha restaurado el archivo «%s» desde el área de archivado" -#: access/transam/xlogarchive.c:230 +#: access/transam/xlogarchive.c:236 #, c-format -msgid "restore_command returned a zero exit status, but stat() failed." -msgstr "restore_command retornó un estado de salida cero, pero stat() falló." +msgid "\"restore_command\" returned a zero exit status, but stat() failed." +msgstr "«restore_command» retornó un estado de salida cero, pero stat() falló." -#: access/transam/xlogarchive.c:262 +#: access/transam/xlogarchive.c:268 #, c-format msgid "could not restore file \"%s\" from archive: %s" msgstr "no se pudo recuperar el archivo «%s»: %s" @@ -2744,1028 +2989,1097 @@ msgstr "no se pudo recuperar el archivo «%s»: %s" #. translator: First %s represents a postgresql.conf parameter name like #. "recovery_end_command", the 2nd is the value of that parameter, the #. third an already translated error message. -#: access/transam/xlogarchive.c:340 +#: access/transam/xlogarchive.c:346 #, c-format msgid "%s \"%s\": %s" msgstr "%s «%s»: %s" -#: access/transam/xlogarchive.c:450 access/transam/xlogarchive.c:530 +#: access/transam/xlogarchive.c:456 access/transam/xlogarchive.c:536 #, c-format msgid "could not create archive status file \"%s\": %m" msgstr "no se pudo crear el archivo de estado «%s»: %m" -#: access/transam/xlogarchive.c:458 access/transam/xlogarchive.c:538 +#: access/transam/xlogarchive.c:464 access/transam/xlogarchive.c:544 #, c-format msgid "could not write archive status file \"%s\": %m" msgstr "no se pudo escribir el archivo de estado «%s»: %m" -#: access/transam/xlogfuncs.c:75 backup/basebackup.c:973 +#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 #, c-format msgid "a backup is already in progress in this session" msgstr "ya hay un respaldo en curso en esta sesión" -#: access/transam/xlogfuncs.c:146 +#: access/transam/xlogfuncs.c:140 #, c-format msgid "backup is not in progress" msgstr "no hay respaldo en curso" -#: access/transam/xlogfuncs.c:147 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "Did you call pg_backup_start()?" msgstr "¿Invocó pg_backup_start()?" -#: access/transam/xlogfuncs.c:190 access/transam/xlogfuncs.c:248 -#: access/transam/xlogfuncs.c:287 access/transam/xlogfuncs.c:308 -#: access/transam/xlogfuncs.c:329 +#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 +#: access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 +#: access/transam/xlogfuncs.c:323 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "Las funciones de control de WAL no pueden ejecutarse durante la recuperación." -#: access/transam/xlogfuncs.c:215 access/transam/xlogfuncs.c:399 -#: access/transam/xlogfuncs.c:457 +#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 +#: access/transam/xlogfuncs.c:447 #, c-format msgid "%s cannot be executed during recovery." msgstr "No se puede ejecutar %s durante la recuperación." -# FIXME see logical.c:81 -#: access/transam/xlogfuncs.c:221 -#, fuzzy, c-format -#| msgid "replication slots can only be used if wal_level >= replica" -msgid "pg_log_standby_snapshot() can only be used if wal_level >= replica" -msgstr "los slots de replicación sólo pueden usarse si wal_level >= replica" +#: access/transam/xlogfuncs.c:215 +#, c-format +msgid "pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" +msgstr "pg_log_standby_snapshot() sólo puede usarse si «wal_level» >= «replica»" -#: access/transam/xlogfuncs.c:253 +#: access/transam/xlogfuncs.c:247 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "el nivel de WAL no es suficiente para crear un punto de recuperación" -#: access/transam/xlogfuncs.c:261 +#: access/transam/xlogfuncs.c:255 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "el valor es demasiado largo para un punto de recuperación (máximo %d caracteres)" -#: access/transam/xlogfuncs.c:496 -#, fuzzy, c-format -#| msgid "invalid locale name \"%s\"" +#: access/transam/xlogfuncs.c:486 +#, c-format msgid "invalid WAL file name \"%s\"" -msgstr "nombre de configuración regional «%s» no es válido" +msgstr "nombre de archivo WAL «%s» no válido" -#: access/transam/xlogfuncs.c:532 access/transam/xlogfuncs.c:562 -#: access/transam/xlogfuncs.c:586 access/transam/xlogfuncs.c:609 -#: access/transam/xlogfuncs.c:689 +#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 +#: access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 +#: access/transam/xlogfuncs.c:679 #, c-format msgid "recovery is not in progress" msgstr "la recuperación no está en proceso" -#: access/transam/xlogfuncs.c:533 access/transam/xlogfuncs.c:563 -#: access/transam/xlogfuncs.c:587 access/transam/xlogfuncs.c:610 -#: access/transam/xlogfuncs.c:690 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 +#: access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 +#: access/transam/xlogfuncs.c:680 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "Las funciones de control de recuperación sólo pueden ejecutarse durante la recuperación." -#: access/transam/xlogfuncs.c:538 access/transam/xlogfuncs.c:568 +#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 #, c-format msgid "standby promotion is ongoing" msgstr "la promoción del standby está en curso" -#: access/transam/xlogfuncs.c:539 access/transam/xlogfuncs.c:569 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%s no puede ser ejecutado después que una promoción es solicitada." -#: access/transam/xlogfuncs.c:695 +#: access/transam/xlogfuncs.c:685 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "«wait_seconds» no puede ser negativo o cero" -#: access/transam/xlogfuncs.c:715 storage/ipc/signalfuncs.c:260 +#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "no se pudo enviar señal a postmaster: %m" -#: access/transam/xlogfuncs.c:751 +#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#, c-format +msgid "terminating connection due to unexpected postmaster exit" +msgstr "terminando la conexión debido al término inesperado de postmaster" + +#: access/transam/xlogfuncs.c:740 +#, c-format +msgid "while waiting on promotion" +msgstr "mientras se esperaba la promoción" + +#: access/transam/xlogfuncs.c:744 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" msgstr[0] "el servidor no se promovió en %d segundo" msgstr[1] "el servidor no se promovió en %d segundos" -#: access/transam/xlogprefetcher.c:1092 +#: access/transam/xlogprefetcher.c:1088 #, c-format -msgid "recovery_prefetch is not supported on platforms that lack posix_fadvise()." -msgstr "recovery_prefetch no está soportado en plataformas que no tienen posix_fadvise()." +msgid "\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()." +msgstr "«recovery_prefetch» no está soportado en plataformas que no tienen posix_fadvise()." -#: access/transam/xlogreader.c:626 +#: access/transam/xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "desplazamiento de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: access/transam/xlogreader.c:635 +#: access/transam/xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord solicitado por %X/%X" -#: access/transam/xlogreader.c:676 access/transam/xlogreader.c:1123 +#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "largo de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: access/transam/xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "memoria agotada mientras se intentaba decodificar un registro de largo %u" - -#: access/transam/xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "largo de registro %u en %X/%X demasiado largo" - -#: access/transam/xlogreader.c:776 +#: access/transam/xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "no hay bandera de contrecord en %X/%X" -#: access/transam/xlogreader.c:789 +#: access/transam/xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "largo de contrecord %u no válido (se esperaba %lld) en %X/%X" -#: access/transam/xlogreader.c:924 -#, c-format -msgid "missing contrecord at %X/%X" -msgstr "falta un contrecord en %X/%X" - -#: access/transam/xlogreader.c:1131 +#: access/transam/xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ID de gestor de recursos %u no válido en %X/%X" -#: access/transam/xlogreader.c:1144 access/transam/xlogreader.c:1160 +#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "registro con prev-link %X/%X incorrecto en %X/%X" -#: access/transam/xlogreader.c:1196 +#: access/transam/xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "suma de verificación de los datos del gestor de recursos incorrecta en el registro en %X/%X" -#: access/transam/xlogreader.c:1230 +#: access/transam/xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "número mágico %04X no válido en segmento WAL %s, LSN %X/%X, posición %u" -#: access/transam/xlogreader.c:1245 access/transam/xlogreader.c:1287 +#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "info bits %04X no válidos en segment WAL %s, LSN %X/%X, posición %u" -#: access/transam/xlogreader.c:1261 +#: access/transam/xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "archivo WAL es de un sistema de bases de datos distinto: identificador de sistema en archivo WAL es %llu, identificador en pg_control es %llu" -#: access/transam/xlogreader.c:1269 +#: access/transam/xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: tamaño de segmento incorrecto en cabecera de paǵina" -#: access/transam/xlogreader.c:1275 +#: access/transam/xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: XLOG_BLCKSZ incorrecto en cabecera de paǵina" -#: access/transam/xlogreader.c:1307 +#: access/transam/xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "pageaddr %X/%X inesperado en segmento WAL %s, LSN %X/%X, posición %u" -#: access/transam/xlogreader.c:1333 +#: access/transam/xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "ID de timeline %u fuera de secuencia (después de %u) en segmento WAL %s, LSN %X/%X, posición %u" -#: access/transam/xlogreader.c:1739 +#: access/transam/xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u fuera de orden en %X/%X" -#: access/transam/xlogreader.c:1763 +#: access/transam/xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA está definido, pero no hay datos en %X/%X" -#: access/transam/xlogreader.c:1770 +#: access/transam/xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA no está definido, pero el largo de los datos es %u en %X/%X" -#: access/transam/xlogreader.c:1806 +#: access/transam/xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE está definido, pero posición del agujero es %u largo %u largo de imagen %u en %X/%X" -#: access/transam/xlogreader.c:1822 +#: access/transam/xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE no está definido, pero posición del agujero es %u largo %u en %X/%X" -#: access/transam/xlogreader.c:1836 +#: access/transam/xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED definido, pero largo de imagen de bloque es %u en %X/%X" -#: access/transam/xlogreader.c:1851 +#: access/transam/xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_COMPRESSED están definidos, pero el largo de imagen de bloque es %u en %X/%X" -#: access/transam/xlogreader.c:1867 +#: access/transam/xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL está definido, pero no hay «rel» anterior en %X/%X " -#: access/transam/xlogreader.c:1879 +#: access/transam/xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "block_id %u no válido en %X/%X" -#: access/transam/xlogreader.c:1946 +#: access/transam/xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "registro con largo no válido en %X/%X" -#: access/transam/xlogreader.c:1972 +#: access/transam/xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "no se pudo localizar un bloque de respaldo con ID %d en el registro WAL" -#: access/transam/xlogreader.c:2056 +#: access/transam/xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "no se pudo restaurar la imagen en %X/%X con bloque especifica %d no válido" -#: access/transam/xlogreader.c:2063 +#: access/transam/xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "no se pudo restaurar la imagen en %X/%X con estado no válido, bloque %d" -#: access/transam/xlogreader.c:2090 access/transam/xlogreader.c:2107 +#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "no se pudo restaurar la imagen en %X/%X comprimida con %s que no está soportado por esta instalación, bloque %d" -#: access/transam/xlogreader.c:2116 +#: access/transam/xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "no se pudo restaurar la imagen en %X/%X comprimida con un método desconocido, bloque %d" -#: access/transam/xlogreader.c:2124 +#: access/transam/xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "no se pudo descomprimir la imagen en %X/%X, bloque %d" -#: access/transam/xlogrecovery.c:547 -#, c-format -msgid "entering standby mode" -msgstr "entrando al modo standby" - -#: access/transam/xlogrecovery.c:550 -#, c-format -msgid "starting point-in-time recovery to XID %u" -msgstr "comenzando el proceso de recuperación hasta el XID %u" - -#: access/transam/xlogrecovery.c:554 -#, c-format -msgid "starting point-in-time recovery to %s" -msgstr "comenzando el proceso de recuperación hasta %s" - -#: access/transam/xlogrecovery.c:558 -#, c-format -msgid "starting point-in-time recovery to \"%s\"" -msgstr "comenzando el proceso de recuperación hasta «%s»" - -#: access/transam/xlogrecovery.c:562 -#, c-format -msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" -msgstr "comenzando el proceso de recuperación punto-en-el-tiempo a la ubicación (LSN) de WAL «%X/%X»" - -#: access/transam/xlogrecovery.c:566 -#, c-format -msgid "starting point-in-time recovery to earliest consistent point" -msgstr "comenzando recuperación a un punto en el tiempo hasta alcanzar un estado consistente" - -#: access/transam/xlogrecovery.c:569 +#: access/transam/xlogrecovery.c:617 #, c-format -msgid "starting archive recovery" -msgstr "comenzando proceso de recuperación" +msgid "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u" +msgstr "iniciando recuperación de backup con LSN de redo %X/%X, LSN de checkpoint %X/%X, en timeline %u" -#: access/transam/xlogrecovery.c:653 +#: access/transam/xlogrecovery.c:649 #, c-format -msgid "could not find redo location referenced by checkpoint record" -msgstr "no se pudo encontrar la ubicación de redo referida por el registro de punto de control" +msgid "could not find redo location %X/%X referenced by checkpoint record at %X/%X" +msgstr "no se pudo encontrar la ubicación de redo %X/%X referida por el registro de checkpoint en %X/%X" # Purposefully deviate from quoting convention here, since argument is a shell command. -#: access/transam/xlogrecovery.c:654 access/transam/xlogrecovery.c:664 +#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 #, c-format msgid "" -"If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n" +"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup." msgstr "" -"Si está restaurando de un respaldo, ejecute «touch \"%s.recovery.signal\"» y agregue las opciones de restauración necesarias.\n" +"Si está restaurando de un respaldo, ejecute «touch \"%s/recovery.signal\"» o «%s/standby.signal» y agregue las opciones de restauración necesarias.\n" "Si no está restaurando de un respaldo, intente eliminar el archivo \"%s/backup_label\".\n" "Tenga cuidado: eliminar \"%s/backup_label\" resultará en un clúster corrupto si está restaurando de un respaldo." -#: access/transam/xlogrecovery.c:663 +#: access/transam/xlogrecovery.c:660 #, c-format -msgid "could not locate required checkpoint record" -msgstr "no se pudo localizar el registro del punto de control requerido" +msgid "could not locate required checkpoint record at %X/%X" +msgstr "no se pudo localizar el registro de checkpoint requerido en %X/%X" -#: access/transam/xlogrecovery.c:692 commands/tablespace.c:670 +#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "no se pudo crear el enlace simbólico «%s»: %m" -#: access/transam/xlogrecovery.c:724 access/transam/xlogrecovery.c:730 +#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "ignorando el archivo «%s» porque no existe un archivo «%s»" -#: access/transam/xlogrecovery.c:726 +#: access/transam/xlogrecovery.c:725 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "El archivo «%s» fue renombrado a «%s»." -#: access/transam/xlogrecovery.c:732 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "No se pudo renombrar el archivo de «%s» a «%s»: %m." -#: access/transam/xlogrecovery.c:786 +#: access/transam/xlogrecovery.c:770 +#, c-format +msgid "restarting backup recovery with redo LSN %X/%X" +msgstr "reiniciando recuperación del backup con LSN de redo «%X/%X»" + +#: access/transam/xlogrecovery.c:795 +#, c-format +msgid "could not locate a valid checkpoint record at %X/%X" +msgstr "no se pudo localizar un registro de válido en %X/%X" + +#: access/transam/xlogrecovery.c:806 +#, c-format +msgid "entering standby mode" +msgstr "entrando al modo standby" + +#: access/transam/xlogrecovery.c:809 +#, c-format +msgid "starting point-in-time recovery to XID %u" +msgstr "comenzando el proceso de recuperación hasta el XID %u" + +#: access/transam/xlogrecovery.c:813 #, c-format -msgid "could not locate a valid checkpoint record" -msgstr "no se pudo localizar un registro de punto de control válido" +msgid "starting point-in-time recovery to %s" +msgstr "comenzando el proceso de recuperación hasta %s" + +#: access/transam/xlogrecovery.c:817 +#, c-format +msgid "starting point-in-time recovery to \"%s\"" +msgstr "comenzando el proceso de recuperación hasta «%s»" + +#: access/transam/xlogrecovery.c:821 +#, c-format +msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" +msgstr "comenzando el proceso de recuperación punto-en-el-tiempo a la ubicación (LSN) de WAL «%X/%X»" + +#: access/transam/xlogrecovery.c:825 +#, c-format +msgid "starting point-in-time recovery to earliest consistent point" +msgstr "comenzando recuperación a un punto en el tiempo hasta alcanzar un estado consistente" + +#: access/transam/xlogrecovery.c:828 +#, c-format +msgid "starting archive recovery" +msgstr "comenzando proceso de recuperación" -#: access/transam/xlogrecovery.c:810 +#: access/transam/xlogrecovery.c:849 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "el timeline solicitado %u no es un hijo de la historia de este servidor" -#: access/transam/xlogrecovery.c:812 +#: access/transam/xlogrecovery.c:851 #, c-format msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." -msgstr "El punto de control más reciente está en %X/%X en el timeline %u, pero en la historia del timeline solicitado, el servidor se desvió desde ese timeline en %X/%X." +msgstr "El checkpoint más reciente está en %X/%X en el timeline %u, pero en la historia del timeline solicitado, el servidor se desvió desde ese timeline en %X/%X." -#: access/transam/xlogrecovery.c:826 +#: access/transam/xlogrecovery.c:865 #, c-format msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u" msgstr "el timeline solicitado %u no contiene el punto mínimo de recuperación %X/%X en el timeline %u" -#: access/transam/xlogrecovery.c:854 +#: access/transam/xlogrecovery.c:893 #, c-format msgid "invalid next transaction ID" msgstr "el siguiente ID de transacción no es válido" -#: access/transam/xlogrecovery.c:859 +#: access/transam/xlogrecovery.c:898 #, c-format msgid "invalid redo in checkpoint record" -msgstr "redo no es válido en el registro de punto de control" +msgstr "redo no es válido en el registro de checkpoint" -#: access/transam/xlogrecovery.c:870 +#: access/transam/xlogrecovery.c:909 #, c-format msgid "invalid redo record in shutdown checkpoint" -msgstr "registro redo no es válido en el punto de control de apagado" +msgstr "registro redo no es válido en el checkpoint de apagado" -#: access/transam/xlogrecovery.c:899 +#: access/transam/xlogrecovery.c:938 #, c-format msgid "database system was not properly shut down; automatic recovery in progress" msgstr "el sistema de bases de datos no fue apagado apropiadamente; se está efectuando la recuperación automática" -#: access/transam/xlogrecovery.c:903 +#: access/transam/xlogrecovery.c:942 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "la recuperación comienza en el timeline %u y tiene un timeline de destino %u" -#: access/transam/xlogrecovery.c:946 +#: access/transam/xlogrecovery.c:985 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label contiene datos inconsistentes con el archivo de control" -#: access/transam/xlogrecovery.c:947 +#: access/transam/xlogrecovery.c:986 #, c-format msgid "This means that the backup is corrupted and you will have to use another backup for recovery." msgstr "Esto significa que el respaldo está corrupto y deberá usar otro respaldo para la recuperación." -#: access/transam/xlogrecovery.c:1001 +#: access/transam/xlogrecovery.c:1040 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "el uso del archivo de configuración de recuperación «%s» no está soportado" -#: access/transam/xlogrecovery.c:1066 +#: access/transam/xlogrecovery.c:1105 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "el modo standby no está soportado en el modo mono-usuario" -#: access/transam/xlogrecovery.c:1083 +#: access/transam/xlogrecovery.c:1122 #, c-format -msgid "specified neither primary_conninfo nor restore_command" -msgstr "no se especifica primary_conninfo ni restore_command" +msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" +msgstr "no se especifica «primary_conninfo» ni «restore_command»" -#: access/transam/xlogrecovery.c:1084 +#: access/transam/xlogrecovery.c:1123 #, c-format msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there." msgstr "El servidor de bases de datos monitoreará el subdirectorio pg_wal con regularidad en búsqueda de archivos almacenados ahí." -#: access/transam/xlogrecovery.c:1092 +#: access/transam/xlogrecovery.c:1131 #, c-format -msgid "must specify restore_command when standby mode is not enabled" -msgstr "debe especificarse restore_command cuando el modo standby no está activo" +msgid "must specify \"restore_command\" when standby mode is not enabled" +msgstr "debe especificarse «restore_command» cuando el modo standby no está activo" -#: access/transam/xlogrecovery.c:1130 +#: access/transam/xlogrecovery.c:1169 #, c-format msgid "recovery target timeline %u does not exist" msgstr "no existe el timeline %u especificado como destino de recuperación" -#: access/transam/xlogrecovery.c:1213 access/transam/xlogrecovery.c:1220 -#: access/transam/xlogrecovery.c:1279 access/transam/xlogrecovery.c:1359 -#: access/transam/xlogrecovery.c:1383 +#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 +#: access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 +#: access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 #, c-format msgid "invalid data in file \"%s\"" msgstr "datos no válidos en archivo «%s»" -#: access/transam/xlogrecovery.c:1280 +#: access/transam/xlogrecovery.c:1319 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "El ID de timeline interpretado es %u, pero se esperaba %u." -#: access/transam/xlogrecovery.c:1662 +#: access/transam/xlogrecovery.c:1330 +#, c-format +msgid "this is an incremental backup, not a data directory" +msgstr "esto es un backup incremental, no un directorio de datos" + +#: access/transam/xlogrecovery.c:1331 +#, c-format +msgid "Use pg_combinebackup to reconstruct a valid data directory." +msgstr "Use pg_combinebackup para reconstruir un directorio de datos válido." + +#: access/transam/xlogrecovery.c:1717 +#, c-format +msgid "unexpected record type found at redo point %X/%X" +msgstr "se encontró registro de tipo inesperada en el punto de redo %X/%X" + +#: access/transam/xlogrecovery.c:1740 #, c-format msgid "redo starts at %X/%X" msgstr "redo comienza en %X/%X" -#: access/transam/xlogrecovery.c:1675 +#: access/transam/xlogrecovery.c:1753 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "redo en progreso, tiempo transcurrido: %ld.%02d s, LSN actual: %X/%X" -#: access/transam/xlogrecovery.c:1767 +#: access/transam/xlogrecovery.c:1843 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "el punto de detención de recuperación pedido es antes del punto de recuperación consistente" -#: access/transam/xlogrecovery.c:1799 +#: access/transam/xlogrecovery.c:1875 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "redo listo en %X/%X utilización del sistema: %s" -#: access/transam/xlogrecovery.c:1805 +#: access/transam/xlogrecovery.c:1881 #, c-format msgid "last completed transaction was at log time %s" msgstr "última transacción completada al tiempo de registro %s" -#: access/transam/xlogrecovery.c:1814 +#: access/transam/xlogrecovery.c:1890 #, c-format msgid "redo is not required" msgstr "no se requiere redo" -#: access/transam/xlogrecovery.c:1825 +#: access/transam/xlogrecovery.c:1901 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "la recuperación terminó antes de alcanzar el punto configurado como destino de recuperación" -#: access/transam/xlogrecovery.c:2019 +#: access/transam/xlogrecovery.c:2095 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "se omitió con éxito contrecord no encontrado en %X/%X, sobrescrito en %s" -#: access/transam/xlogrecovery.c:2086 +#: access/transam/xlogrecovery.c:2162 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "entrada de directorio inesperada «%s» fue encontrada en %s" -#: access/transam/xlogrecovery.c:2088 +#: access/transam/xlogrecovery.c:2164 #, c-format msgid "All directory entries in pg_tblspc/ should be symbolic links." msgstr "Todas las entradas de directorio en pg_tblspc deberían ser enlaces simbólicos" -#: access/transam/xlogrecovery.c:2089 +#: access/transam/xlogrecovery.c:2165 #, c-format -msgid "Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete." -msgstr "Elimine esos directorios, o defina allow_in_place_tablespaces a ON transitoriamente para permitir que la recuperación pueda completarse." +msgid "Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete." +msgstr "Elimine esos directorios, o defina «allow_in_place_tablespaces» a ON transitoriamente para permitir que la recuperación pueda completarse." -#: access/transam/xlogrecovery.c:2163 +#: access/transam/xlogrecovery.c:2217 +#, c-format +msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" +msgstr "se completó la recuperación de backup con LSN de redo %X/%X y LSN de término %X/%X" + +#: access/transam/xlogrecovery.c:2247 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "el estado de recuperación consistente fue alcanzado en %X/%X" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2201 +#: access/transam/xlogrecovery.c:2285 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "redo WAL en %X/%X para %s" -#: access/transam/xlogrecovery.c:2299 +#: access/transam/xlogrecovery.c:2383 #, c-format msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record" -msgstr "ID de timeline previo %u inesperado (timeline actual %u) en el registro de punto de control" +msgstr "ID de timeline previo %u inesperado (timeline actual %u) en el registro de checkpoint" -#: access/transam/xlogrecovery.c:2308 +#: access/transam/xlogrecovery.c:2392 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" -msgstr "ID de timeline %u inesperado (después de %u) en el registro de punto de control" +msgstr "ID de timeline %u inesperado (después de %u) en el registro de checkpoint" -#: access/transam/xlogrecovery.c:2324 +#: access/transam/xlogrecovery.c:2408 #, c-format msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u" msgstr "timeline ID %u inesperado en registro de checkpoint, antes de alcanzar el punto mínimo de recuperación %X/%X en el timeline %u" -#: access/transam/xlogrecovery.c:2508 access/transam/xlogrecovery.c:2784 +#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 #, c-format msgid "recovery stopping after reaching consistency" msgstr "deteniendo recuperación al alcanzar un estado consistente" -#: access/transam/xlogrecovery.c:2529 +#: access/transam/xlogrecovery.c:2613 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "deteniendo recuperación antes de la ubicación (LSN) de WAL «%X/%X»" -#: access/transam/xlogrecovery.c:2619 +#: access/transam/xlogrecovery.c:2703 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "deteniendo recuperación antes de comprometer la transacción %u, hora %s" -#: access/transam/xlogrecovery.c:2626 +#: access/transam/xlogrecovery.c:2710 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "deteniendo recuperación antes de abortar la transacción %u, hora %s" -#: access/transam/xlogrecovery.c:2679 +#: access/transam/xlogrecovery.c:2763 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "deteniendo recuperación en el punto de recuperación «%s», hora %s" -#: access/transam/xlogrecovery.c:2697 +#: access/transam/xlogrecovery.c:2781 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "deteniendo recuperación después de la ubicación (LSN) de WAL «%X/%X»" -#: access/transam/xlogrecovery.c:2764 +#: access/transam/xlogrecovery.c:2848 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "deteniendo recuperación de comprometer la transacción %u, hora %s" -#: access/transam/xlogrecovery.c:2772 +#: access/transam/xlogrecovery.c:2856 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "deteniendo recuperación después de abortar la transacción %u, hora %s" -#: access/transam/xlogrecovery.c:2853 +#: access/transam/xlogrecovery.c:2937 #, c-format msgid "pausing at the end of recovery" msgstr "pausando al final de la recuperación" -#: access/transam/xlogrecovery.c:2854 +#: access/transam/xlogrecovery.c:2938 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "Ejecute pg_wal_replay_resume() para promover." -#: access/transam/xlogrecovery.c:2857 access/transam/xlogrecovery.c:4594 +#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4679 #, c-format msgid "recovery has paused" msgstr "la recuperación está en pausa" -#: access/transam/xlogrecovery.c:2858 +#: access/transam/xlogrecovery.c:2942 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "Ejecute pg_wal_replay_resume() para continuar." -#: access/transam/xlogrecovery.c:3121 -#, fuzzy, c-format -#| msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" +#: access/transam/xlogrecovery.c:3205 +#, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" -msgstr "pageaddr %X/%X inesperado en segmento WAL %s, LSN %X/%X, posición %u" +msgstr "ID de timeline %u inesperado en segmento WAL %s, LSN %X/%X, posición %u" -#: access/transam/xlogrecovery.c:3329 -#, fuzzy, c-format -#| msgid "could not read from file %s, offset %d: %m" +#: access/transam/xlogrecovery.c:3413 +#, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" -msgstr "no se pudo leer desde el archivo «%s» en la posición %d: %m" +msgstr "no se pudo leer desde el segmento de WAL %s, LSN %X/%X, posición %u: %m" -#: access/transam/xlogrecovery.c:3336 -#, fuzzy, c-format -#| msgid "could not read from file %s, offset %d: read %d of %d" +#: access/transam/xlogrecovery.c:3420 +#, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" -msgstr "no se pudo leer del archivo %s, posición %d: leídos %d de %d" +msgstr "no se pudo leer del segmento de WAL %s, LSN %X/%X, posición %u: leídos %d de %zu" -#: access/transam/xlogrecovery.c:3976 -#, fuzzy, c-format -#| msgid "invalid checkpoint record" +#: access/transam/xlogrecovery.c:4061 +#, c-format msgid "invalid checkpoint location" -msgstr "el registro del punto de control no es válido" +msgstr "ubicación de checkpoint no válida" -#: access/transam/xlogrecovery.c:3986 +#: access/transam/xlogrecovery.c:4071 #, c-format msgid "invalid checkpoint record" -msgstr "el registro del punto de control no es válido" +msgstr "el registro del checkpoint no es válido" -#: access/transam/xlogrecovery.c:3992 +#: access/transam/xlogrecovery.c:4077 #, c-format msgid "invalid resource manager ID in checkpoint record" -msgstr "el ID de gestor de recursos en el registro del punto de control no es válido" +msgstr "el ID de gestor de recursos en el registro del checkpoint no es válido" -#: access/transam/xlogrecovery.c:4000 +#: access/transam/xlogrecovery.c:4085 #, c-format msgid "invalid xl_info in checkpoint record" -msgstr "xl_info en el registro del punto de control no es válido" +msgstr "xl_info en el registro del checkpoint no es válido" -#: access/transam/xlogrecovery.c:4006 +#: access/transam/xlogrecovery.c:4091 #, c-format msgid "invalid length of checkpoint record" -msgstr "la longitud del registro de punto de control no es válida" +msgstr "la longitud del registro de checkpoint no es válida" -#: access/transam/xlogrecovery.c:4060 +#: access/transam/xlogrecovery.c:4145 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "el nuevo timeline %u especificado no es hijo del timeline de sistema %u" -#: access/transam/xlogrecovery.c:4074 +#: access/transam/xlogrecovery.c:4159 #, c-format msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X" msgstr "el nuevo timeline %u bifurcó del timeline del sistema actual %u antes del punto re recuperación actual %X/%X" -#: access/transam/xlogrecovery.c:4093 +#: access/transam/xlogrecovery.c:4178 #, c-format msgid "new target timeline is %u" msgstr "el nuevo timeline destino es %u" -#: access/transam/xlogrecovery.c:4296 +#: access/transam/xlogrecovery.c:4381 #, c-format msgid "WAL receiver process shutdown requested" msgstr "se recibió una petición de apagado para el proceso receptor de wal" -#: access/transam/xlogrecovery.c:4356 +#: access/transam/xlogrecovery.c:4441 #, c-format msgid "received promote request" msgstr "se recibió petición de promoción" -#: access/transam/xlogrecovery.c:4585 +#: access/transam/xlogrecovery.c:4670 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "hot standby no es posible porque la configuración de parámetros no es suficiente" -#: access/transam/xlogrecovery.c:4586 access/transam/xlogrecovery.c:4613 -#: access/transam/xlogrecovery.c:4643 +#: access/transam/xlogrecovery.c:4671 access/transam/xlogrecovery.c:4698 +#: access/transam/xlogrecovery.c:4728 #, c-format msgid "%s = %d is a lower setting than on the primary server, where its value was %d." msgstr "%s = %d es una configuración menor que en el servidor primario, donde su valor era %d." -#: access/transam/xlogrecovery.c:4595 +#: access/transam/xlogrecovery.c:4680 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "Si se continúa con la recuperación, el servidor se apagará." -#: access/transam/xlogrecovery.c:4596 +#: access/transam/xlogrecovery.c:4681 #, c-format msgid "You can then restart the server after making the necessary configuration changes." msgstr "Luego puede reiniciar el servidor después de hacer los cambios necesarios en la configuración." -#: access/transam/xlogrecovery.c:4607 +#: access/transam/xlogrecovery.c:4692 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "la promoción no es posible porque la configuración de parámetros no es suficiente" -#: access/transam/xlogrecovery.c:4617 +#: access/transam/xlogrecovery.c:4702 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "Reinicie el servidor luego de hacer los cambios necesarios en la configuración." -#: access/transam/xlogrecovery.c:4641 +#: access/transam/xlogrecovery.c:4726 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "se abortó la recuperación porque la configuración de parámetros no es suficiente" -#: access/transam/xlogrecovery.c:4647 +#: access/transam/xlogrecovery.c:4732 #, c-format msgid "You can restart the server after making the necessary configuration changes." msgstr "Puede reiniciar el servidor luego de hacer los cambios necesarios en la configuración." -#: access/transam/xlogrecovery.c:4689 +#: access/transam/xlogrecovery.c:4774 #, c-format msgid "multiple recovery targets specified" msgstr "múltiples valores de destino de recuperación especificados" -#: access/transam/xlogrecovery.c:4690 +#: access/transam/xlogrecovery.c:4775 #, c-format -msgid "At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set." -msgstr "A lo más uno de recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid puede estar definido." +msgid "At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set." +msgstr "A lo más uno de «recovery_target», «recovery_target_lsn», «recovery_target_name», «recovery_target_time», «recovery_target_xid» puede estar definido." -#: access/transam/xlogrecovery.c:4701 +#: access/transam/xlogrecovery.c:4786 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "El único valor permitido es «immediate»." -#: access/transam/xlogrecovery.c:4853 utils/adt/timestamp.c:186 -#: utils/adt/timestamp.c:439 +#: access/transam/xlogrecovery.c:4938 utils/adt/timestamp.c:202 +#: utils/adt/timestamp.c:455 #, c-format msgid "timestamp out of range: \"%s\"" msgstr "timestamp fuera de rango: «%s»" -#: access/transam/xlogrecovery.c:4898 +#: access/transam/xlogrecovery.c:4983 #, c-format -msgid "recovery_target_timeline is not a valid number." -msgstr "recovery_target_timeline no es un número válido." +msgid "\"recovery_target_timeline\" is not a valid number." +msgstr "«recovery_target_timeline» no es un número válido." -#: access/transam/xlogutils.c:1039 -#, fuzzy, c-format -#| msgid "could not read from file %s, offset %d: %m" +#: access/transam/xlogutils.c:1032 +#, c-format msgid "could not read from WAL segment %s, offset %d: %m" -msgstr "no se pudo leer desde el archivo «%s» en la posición %d: %m" +msgstr "no se pudo leer desde el segmento de WAL %s, posición %d: %m" -#: access/transam/xlogutils.c:1046 -#, fuzzy, c-format -#| msgid "could not read from file %s, offset %d: read %d of %d" +#: access/transam/xlogutils.c:1039 +#, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" -msgstr "no se pudo leer del archivo %s, posición %d: leídos %d de %d" +msgstr "no se pudo leer del segmento de WAL %s, posición %d: leídos %d de %d" -#: archive/shell_archive.c:96 +#: archive/shell_archive.c:98 #, c-format msgid "archive command failed with exit code %d" msgstr "la orden de archivado falló con código de retorno %d" -#: archive/shell_archive.c:98 archive/shell_archive.c:108 -#: archive/shell_archive.c:114 archive/shell_archive.c:123 +#: archive/shell_archive.c:100 archive/shell_archive.c:110 +#: archive/shell_archive.c:116 archive/shell_archive.c:125 #, c-format msgid "The failed archive command was: %s" msgstr "La orden fallida era: «%s»" -#: archive/shell_archive.c:105 +#: archive/shell_archive.c:107 #, c-format msgid "archive command was terminated by exception 0x%X" msgstr "la orden de archivado fue terminada por una excepción 0x%X" -#: archive/shell_archive.c:107 postmaster/postmaster.c:3675 +#: archive/shell_archive.c:109 postmaster/postmaster.c:3095 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "Vea el archivo «ntstatus.h» para una descripción del valor hexadecimal." -#: archive/shell_archive.c:112 +#: archive/shell_archive.c:114 #, c-format msgid "archive command was terminated by signal %d: %s" msgstr "la orden de archivado fue terminada por una señal %d: %s" -#: archive/shell_archive.c:121 +#: archive/shell_archive.c:123 #, c-format msgid "archive command exited with unrecognized status %d" msgstr "la orden de archivado fue terminada con código %d no reconocido" -#: backup/backup_manifest.c:253 +#: backup/backup_manifest.c:254 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "se esperaba el timeline de término %u pero se encontró el timeline %u" -#: backup/backup_manifest.c:277 +#: backup/backup_manifest.c:278 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "se esperaba el timeline de inicio %u pero se encontró el timeline %u" -#: backup/backup_manifest.c:304 +#: backup/backup_manifest.c:305 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "el timeline de inicio %u no fue encontrado en la historia del timeline %u" -#: backup/backup_manifest.c:355 +#: backup/backup_manifest.c:356 #, c-format msgid "could not rewind temporary file" msgstr "no se puede rebobinar el archivo temporal" -#: backup/basebackup.c:470 +#: backup/basebackup.c:479 #, c-format msgid "could not find any WAL files" msgstr "no se pudo encontrar ningún archivo de WAL" -#: backup/basebackup.c:485 backup/basebackup.c:500 backup/basebackup.c:509 +#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 #, c-format msgid "could not find WAL file \"%s\"" msgstr "no se pudo encontrar archivo de WAL «%s»" -#: backup/basebackup.c:551 backup/basebackup.c:576 +#: backup/basebackup.c:560 backup/basebackup.c:585 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "tamaño del archivo WAL «%s» inesperado" -#: backup/basebackup.c:646 +#: backup/basebackup.c:656 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" msgstr[0] "%lld falla de verificación de suma de comprobación en total" msgstr[1] "%lld fallas de verificación de suma de comprobación en total" -#: backup/basebackup.c:653 +#: backup/basebackup.c:663 #, c-format msgid "checksum verification failure during base backup" msgstr "falla en verificación de checksums durante respaldo base" -#: backup/basebackup.c:722 backup/basebackup.c:731 backup/basebackup.c:742 -#: backup/basebackup.c:759 backup/basebackup.c:768 backup/basebackup.c:779 -#: backup/basebackup.c:796 backup/basebackup.c:805 backup/basebackup.c:817 -#: backup/basebackup.c:841 backup/basebackup.c:855 backup/basebackup.c:866 -#: backup/basebackup.c:877 backup/basebackup.c:890 +#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 +#: backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 +#: backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 +#: backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 +#: backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 #, c-format msgid "duplicate option \"%s\"" msgstr "nombre de opción «%s» duplicada" -#: backup/basebackup.c:750 -#, fuzzy, c-format -#| msgid "unrecognized object type \"%s\"" +#: backup/basebackup.c:761 +#, c-format msgid "unrecognized checkpoint type: \"%s\"" -msgstr "tipo de objeto «%s» no reconocido" +msgstr "tipo de checkpoint no reconocido: «%s»" + +#: backup/basebackup.c:793 +#, c-format +msgid "incremental backups cannot be taken unless WAL summarization is enabled" +msgstr "los backups incrementales no pueden tomarse a menos que la sumarización de WAL esté activada" -#: backup/basebackup.c:785 +#: backup/basebackup.c:809 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%d está fuera del rango aceptable para el parámetro «%s» (%d .. %d)" -#: backup/basebackup.c:830 +#: backup/basebackup.c:854 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "opción de manifiesto «%s» no reconocida" -#: backup/basebackup.c:846 -#, c-format -msgid "unrecognized checksum algorithm: \"%s\"" -msgstr "algoritmo de suma de comprobación no reconocido: \"%s\"" - -#: backup/basebackup.c:881 +#: backup/basebackup.c:905 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "algoritmo de compresión no reconocido: «%s»" -#: backup/basebackup.c:897 -#, fuzzy, c-format -#| msgid "unrecognized column option \"%s\"" +#: backup/basebackup.c:921 +#, c-format msgid "unrecognized base backup option: \"%s\"" -msgstr "opción de columna «%s» no reconocida" +msgstr "opción de respaldo base no reconocida: «%s»" -#: backup/basebackup.c:908 +#: backup/basebackup.c:932 #, c-format msgid "manifest checksums require a backup manifest" msgstr "la suma de comprobación del manifiesto requiere un manifiesto de la copia de seguridad" -#: backup/basebackup.c:917 -#, fuzzy, c-format -#| msgid "--no-slot cannot be used with slot name" +#: backup/basebackup.c:941 +#, c-format msgid "target detail cannot be used without target" -msgstr "no se puede usar --no-slot junto con nombre de slot" +msgstr "no se puede usar “target detail” sin un destino" -#: backup/basebackup.c:926 backup/basebackup_target.c:218 -#, fuzzy, c-format -#| msgid "operator class \"%s\" does not accept data type %s" +#: backup/basebackup.c:950 backup/basebackup_target.c:218 +#, c-format msgid "target \"%s\" does not accept a target detail" -msgstr "la clase de operadores «%s» no acepta el tipo de datos %s" +msgstr "el destino «%s» no acepta “target details”" -#: backup/basebackup.c:937 -#, fuzzy, c-format -#| msgid "%s cannot be specified unless locale provider \"%s\" is chosen" +#: backup/basebackup.c:961 +#, c-format msgid "compression detail cannot be specified unless compression is enabled" -msgstr "%s no puede especificarse a menos que el proveedor de locale «%s» sea escogido" +msgstr "el detalle de compresión no puede especificarse a menos que la compresión esté activada" -#: backup/basebackup.c:950 +#: backup/basebackup.c:974 #, c-format msgid "invalid compression specification: %s" msgstr "especificación de compresión no válida: %s" -#: backup/basebackup.c:1116 backup/basebackup.c:1294 +#: backup/basebackup.c:1024 +#, c-format +msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" +msgstr "debe ejecutar UPLOAD_MANIFEST antes de lanzar un BASE_BACKUP incremental" + +#: backup/basebackup.c:1157 backup/basebackup.c:1358 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "no se pudo hacer stat al archivo o directorio «%s»: %m" -#: backup/basebackup.c:1430 +#: backup/basebackup.c:1544 #, c-format msgid "skipping special file \"%s\"" msgstr "omitiendo el archivo especial «%s»" -#: backup/basebackup.c:1542 -#, c-format -msgid "invalid segment number %d in file \"%s\"" -msgstr "número de segmento %d no válido en archivo «%s»" - -#: backup/basebackup.c:1574 +#: backup/basebackup.c:1751 #, c-format msgid "could not verify checksum in file \"%s\", block %u: read buffer size %d and page size %d differ" msgstr "no se pudo verificar el checksum en el archivo «%s», bloque %u: el tamaño de búfer de lectura %d y el tamaño de página %d difieren" -#: backup/basebackup.c:1658 +#: backup/basebackup.c:1813 +#, c-format +msgid "file \"%s\" has a total of %d checksum verification failure" +msgid_plural "file \"%s\" has a total of %d checksum verification failures" +msgstr[0] "el archivo «%s» tiene un total de %d falla de verificación de checksum" +msgstr[1] "el archivo «%s» tiene un total de %d fallas de verificación de checksums" + +#: backup/basebackup.c:1917 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" msgstr "verificación de checksums falló en archivo «%s», bloque %u: calculado %X pero se esperaba %X" -#: backup/basebackup.c:1665 +#: backup/basebackup.c:1924 #, c-format msgid "further checksum verification failures in file \"%s\" will not be reported" msgstr "subsiguientes fallas de verificación de checksums en el archivo «%s» no se reportarán" -#: backup/basebackup.c:1721 -#, c-format -msgid "file \"%s\" has a total of %d checksum verification failure" -msgid_plural "file \"%s\" has a total of %d checksum verification failures" -msgstr[0] "el archivo «%s» tiene un total de %d falla de verificación de checksum" -msgstr[1] "el archivo «%s» tiene un total de %d fallas de verificación de checksums" - -#: backup/basebackup.c:1767 +#: backup/basebackup.c:2048 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "nombre de archivo demasiado largo para el formato tar: «%s»" -#: backup/basebackup.c:1772 +#: backup/basebackup.c:2053 #, c-format msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "destino de enlace simbólico demasiado largo para el formato tar: nombre de archivo «%s», destino «%s»" +#: backup/basebackup.c:2127 +#, c-format +msgid "could not read file \"%s\": read %zd of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %zd de %zu" + #: backup/basebackup_gzip.c:67 -#, fuzzy, c-format -#| msgid "Bonjour is not supported by this build" +#, c-format msgid "gzip compression is not supported by this build" -msgstr "Bonjour no está soportado en este servidor" +msgstr "la compresión gzip no está soportada en este servidor" #: backup/basebackup_gzip.c:143 #, c-format msgid "could not initialize compression library" msgstr "no se pudo inicializar la biblioteca de compresión" +#: backup/basebackup_incremental.c:294 +#, c-format +msgid "manifest contains no required WAL ranges" +msgstr "el manifiesto no contiene ningún rango WAL requerido" + +#: backup/basebackup_incremental.c:349 +#, c-format +msgid "timeline %u found in manifest, but not in this server's history" +msgstr "el timeline %u fue encontrado en el manifiesto, pero no en la historia de este servidor" + +#: backup/basebackup_incremental.c:414 +#, c-format +msgid "manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "el manifiesto requiere WAL en el timeline inicial %u desde %X/%X, pero ese timeline inicia en %X/%X" + +#: backup/basebackup_incremental.c:424 +#, c-format +msgid "manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "el manifiesto requiere WAL del timeline de continuación %u desde %X/%X, pero ese timeline empieza en %X/%X" + +#: backup/basebackup_incremental.c:435 +#, c-format +msgid "manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X" +msgstr "el manifiesto requiere WAL del timeline final %u terminado en %X/%X, pero este backup empieza en %X/%X" + +#: backup/basebackup_incremental.c:439 +#, c-format +msgid "This can happen for incremental backups on a standby if there was little activity since the previous backup." +msgstr "Esto puede pasar para backups incrementales en un standby si hubo insuficiente actividad desde el backup anterior." + +#: backup/basebackup_incremental.c:446 +#, c-format +msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" +msgstr "el manifiesto requiere WAL del timeline no-final %u terminando en %X/%X, pero este servidor cambió de timelines en %X/%X" + +#: backup/basebackup_incremental.c:527 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist" +msgstr "se requieren sumarizaciones de WAL en el timeline %u desde %X/%X hasta %X/%X, pero no existen sumarizaciones para ese timeline y rango de LSN" + +#: backup/basebackup_incremental.c:534 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete" +msgstr "se requieren sumarizaciones de WAL en el timeline %u desde %X/%X hasta %X/%X, pero las sumarizaciones en ese timeline y rango de LSN están incompletos" + +#: backup/basebackup_incremental.c:538 +#, c-format +msgid "The first unsummarized LSN in this range is %X/%X." +msgstr "El primer LSN sin sumarización en este rango es %X/%X." + +#: backup/basebackup_incremental.c:938 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "el manifiesto de backup versión 1 no soporta backups incrementales" + +#: backup/basebackup_incremental.c:956 +#, c-format +msgid "system identifier in backup manifest is %llu, but database system identifier is %llu" +msgstr "el identificador de sistema en el manifiesto de backup es %llu, pero el identificador en el sistema es %llu" + #: backup/basebackup_lz4.c:67 -#, fuzzy, c-format -#| msgid "Bonjour is not supported by this build" +#, c-format msgid "lz4 compression is not supported by this build" -msgstr "Bonjour no está soportado en este servidor" +msgstr "la compresión lz4 no está soportada en este servidor" -#: backup/basebackup_server.c:75 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: backup/basebackup_server.c:73 +#, c-format msgid "permission denied to create backup stored on server" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para crear un respaldo almacenado en el servidor" -#: backup/basebackup_server.c:76 +#: backup/basebackup_server.c:74 #, c-format msgid "Only roles with privileges of the \"%s\" role may create a backup stored on the server." -msgstr "" +msgstr "Sólo los roles con privilegio del rol «%s» pueden crear un respaldo almacenado en el servidor." -#: backup/basebackup_server.c:91 -#, fuzzy, c-format -#| msgid "relative path not allowed for COPY to file" +#: backup/basebackup_server.c:89 +#, c-format msgid "relative path not allowed for backup stored on server" -msgstr "no se permiten rutas relativas para COPY hacia un archivo" +msgstr "no se permiten rutas relativas para un respaldo almacenado en el servidor" -#: backup/basebackup_server.c:104 commands/dbcommands.c:501 -#: commands/tablespace.c:163 commands/tablespace.c:179 -#: commands/tablespace.c:599 commands/tablespace.c:644 replication/slot.c:1697 +#: backup/basebackup_server.c:102 commands/dbcommands.c:477 +#: commands/tablespace.c:157 commands/tablespace.c:173 +#: commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 #: storage/file/copydir.c:47 #, c-format msgid "could not create directory \"%s\": %m" msgstr "no se pudo crear el directorio «%s»: %m" -#: backup/basebackup_server.c:117 +#: backup/basebackup_server.c:115 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "el directorio «%s» existe pero no está vacío" -#: backup/basebackup_server.c:125 utils/init/postinit.c:1154 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1178 #, c-format msgid "could not access directory \"%s\": %m" msgstr "no se pudo acceder al directorio «%s»: %m" -#: backup/basebackup_server.c:177 backup/basebackup_server.c:184 -#: backup/basebackup_server.c:270 backup/basebackup_server.c:277 -#: storage/smgr/md.c:501 storage/smgr/md.c:508 storage/smgr/md.c:590 -#: storage/smgr/md.c:612 storage/smgr/md.c:862 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 +#: backup/basebackup_server.c:268 backup/basebackup_server.c:275 +#: backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 +#: storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 #, c-format msgid "Check free disk space." msgstr "Verifique el espacio libre en disco." -#: backup/basebackup_server.c:181 backup/basebackup_server.c:274 -#, fuzzy, c-format -#| msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" +#: backup/basebackup_server.c:179 backup/basebackup_server.c:272 +#: backup/walsummary.c:309 +#, c-format msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" -msgstr "no se pudo extender el archivo «%s»: sólo se escribieron %d de %d bytes en el bloque %u" +msgstr "no se pudo escribir en el archivo «%s»: sólo se escribieron %d de %d bytes en la posición %u" #: backup/basebackup_target.c:146 -#, fuzzy, c-format -#| msgid "unrecognized reset target: \"%s\"" +#, c-format msgid "unrecognized target: \"%s\"" -msgstr "destino de reset no reconocido: «%s»" +msgstr "destino no reconocido: «%s»" #: backup/basebackup_target.c:237 -#, fuzzy, c-format -#| msgid "parameter \"%s\" requires a Boolean value" +#, c-format msgid "target \"%s\" requires a target detail" -msgstr "el parámetro «%s» requiere un valor lógico (booleano)" +msgstr "el destino «%s» requiere un “target detail”" #: backup/basebackup_zstd.c:66 -#, fuzzy, c-format -#| msgid "Bonjour is not supported by this build" +#, c-format msgid "zstd compression is not supported by this build" -msgstr "Bonjour no está soportado en este servidor" +msgstr "la compresión zstd no está soportada en este servidor" #: backup/basebackup_zstd.c:117 #, c-format @@ -3774,714 +4088,723 @@ msgstr "no se pudo definir la cantidad de procesos ayudantes de compresión a %d #: backup/basebackup_zstd.c:129 #, c-format -msgid "could not set compression flag for %s: %s" -msgstr "no se pudo definir una opción de compresión para %s: %s" +msgid "could not enable long-distance mode: %s" +msgstr "no se pudo habilitar el modo “long-distance”: %s" -#: bootstrap/bootstrap.c:243 postmaster/postmaster.c:721 tcop/postgres.c:3819 +#: backup/walsummaryfuncs.c:95 +#, c-format +msgid "invalid timeline %lld" +msgstr "timeline %lld no válido" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3946 #, c-format msgid "--%s requires a value" msgstr "--%s requiere un valor" -#: bootstrap/bootstrap.c:248 postmaster/postmaster.c:726 tcop/postgres.c:3824 +#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3951 #, c-format msgid "-c %s requires a value" msgstr "-c %s requiere un valor" -#: bootstrap/bootstrap.c:289 -#, c-format -msgid "-X requires a power of two value between 1 MB and 1 GB" -msgstr "-X require un valor potencia de dos entre 1 MB y 1 GB" - -#: bootstrap/bootstrap.c:295 postmaster/postmaster.c:844 -#: postmaster/postmaster.c:857 +#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 +#: postmaster/postmaster.c:759 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Pruebe «%s --help» para mayor información.\n" -#: bootstrap/bootstrap.c:304 +#: bootstrap/bootstrap.c:291 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: argumentos de línea de órdenes no válidos\n" -#: catalog/aclchk.c:201 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "la opción de grant sólo puede ser otorgada a roles" -#: catalog/aclchk.c:323 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "no se otorgaron privilegios para la columna «%s» de la relación «%s»" -#: catalog/aclchk.c:328 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "no se otorgaron privilegios para «%s»" -#: catalog/aclchk.c:336 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "no todos los privilegios fueron otorgados para la columna «%s» de la relación «%s»" -#: catalog/aclchk.c:341 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "no todos los privilegios fueron otorgados para «%s»" -#: catalog/aclchk.c:352 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "ningún privilegio pudo ser revocado para la columna «%s» de la relación «%s»" -#: catalog/aclchk.c:357 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "ningún privilegio pudo ser revocado para «%s»" -#: catalog/aclchk.c:365 +#: catalog/aclchk.c:375 #, c-format msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "no todos los privilegios pudieron ser revocados para la columna «%s» de la relación «%s»" -#: catalog/aclchk.c:370 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "no todos los privilegios pudieron ser revocados para «%s»" -#: catalog/aclchk.c:402 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "el cedente (grantor) debe ser el usuario actual" -#: catalog/aclchk.c:470 catalog/aclchk.c:1045 +#: catalog/aclchk.c:480 catalog/aclchk.c:1055 #, c-format msgid "invalid privilege type %s for relation" msgstr "el tipo de privilegio %s no es válido para una relación" -#: catalog/aclchk.c:474 catalog/aclchk.c:1049 +#: catalog/aclchk.c:484 catalog/aclchk.c:1059 #, c-format msgid "invalid privilege type %s for sequence" msgstr "el tipo de privilegio %s no es válido para una secuencia" -#: catalog/aclchk.c:478 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "el tipo de privilegio %s no es válido para una base de datos" -#: catalog/aclchk.c:482 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "el tipo de privilegio %s no es válido para un dominio" -#: catalog/aclchk.c:486 catalog/aclchk.c:1053 +#: catalog/aclchk.c:496 catalog/aclchk.c:1063 #, c-format msgid "invalid privilege type %s for function" msgstr "el tipo de privilegio %s no es válido para una función" -#: catalog/aclchk.c:490 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "el tipo de privilegio %s no es válido para un lenguaje" -#: catalog/aclchk.c:494 +#: catalog/aclchk.c:504 #, c-format msgid "invalid privilege type %s for large object" msgstr "el tipo de privilegio %s no es válido para un objeto grande" -#: catalog/aclchk.c:498 catalog/aclchk.c:1069 +#: catalog/aclchk.c:508 catalog/aclchk.c:1079 #, c-format msgid "invalid privilege type %s for schema" msgstr "el tipo de privilegio %s no es válido para un esquema" -#: catalog/aclchk.c:502 catalog/aclchk.c:1057 +#: catalog/aclchk.c:512 catalog/aclchk.c:1067 #, c-format msgid "invalid privilege type %s for procedure" msgstr "el tipo de privilegio %s no es válido para un procedimiento" -#: catalog/aclchk.c:506 catalog/aclchk.c:1061 +#: catalog/aclchk.c:516 catalog/aclchk.c:1071 #, c-format msgid "invalid privilege type %s for routine" msgstr "el tipo de privilegio %s no es válido para una rutina" -#: catalog/aclchk.c:510 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "el tipo de privilegio %s no es válido para un tablespace" -#: catalog/aclchk.c:514 catalog/aclchk.c:1065 +#: catalog/aclchk.c:524 catalog/aclchk.c:1075 #, c-format msgid "invalid privilege type %s for type" msgstr "el tipo de privilegio %s no es válido para un tipo" -#: catalog/aclchk.c:518 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "el tipo de privilegio %s no es válido para un conector de datos externos" -#: catalog/aclchk.c:522 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "el tipo de privilegio %s no es válido para un servidor foráneo" -#: catalog/aclchk.c:526 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "el tipo de privilegio %s no es válido para un parámetro" -#: catalog/aclchk.c:565 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "los privilegios de columna son sólo válidos para relaciones" -#: catalog/aclchk.c:728 catalog/aclchk.c:3570 catalog/objectaddress.c:1092 -#: catalog/pg_largeobject.c:116 storage/large_object/inv_api.c:287 +#: catalog/aclchk.c:738 catalog/aclchk.c:3629 catalog/objectaddress.c:1054 +#: catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 #, c-format msgid "large object %u does not exist" msgstr "no existe el objeto grande %u" -#: catalog/aclchk.c:1102 +#: catalog/aclchk.c:1112 #, c-format msgid "default privileges cannot be set for columns" msgstr "los privilegios por omisión no pueden definirse para columnas" -#: catalog/aclchk.c:1138 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: catalog/aclchk.c:1148 +#, c-format msgid "permission denied to change default privileges" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para cambiar los privilegios por omisión" -#: catalog/aclchk.c:1256 +#: catalog/aclchk.c:1266 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "No puede utilizar la cláusula IN SCHEMA cuando se utiliza GRANT / REVOKE ON SCHEMAS" -#: catalog/aclchk.c:1595 catalog/catalog.c:631 catalog/objectaddress.c:1561 -#: catalog/pg_publication.c:533 commands/analyze.c:389 commands/copy.c:837 -#: commands/sequence.c:1663 commands/tablecmds.c:7339 commands/tablecmds.c:7495 -#: commands/tablecmds.c:7545 commands/tablecmds.c:7619 -#: commands/tablecmds.c:7689 commands/tablecmds.c:7801 -#: commands/tablecmds.c:7895 commands/tablecmds.c:7954 -#: commands/tablecmds.c:8043 commands/tablecmds.c:8073 -#: commands/tablecmds.c:8201 commands/tablecmds.c:8283 -#: commands/tablecmds.c:8417 commands/tablecmds.c:8525 -#: commands/tablecmds.c:12240 commands/tablecmds.c:12421 -#: commands/tablecmds.c:12582 commands/tablecmds.c:13744 -#: commands/tablecmds.c:16273 commands/trigger.c:949 parser/analyze.c:2480 -#: parser/parse_relation.c:737 parser/parse_target.c:1054 -#: parser/parse_type.c:144 parser/parse_utilcmd.c:3413 -#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2884 -#: utils/adt/ruleutils.c:2799 +#: catalog/aclchk.c:1617 catalog/catalog.c:659 catalog/objectaddress.c:1523 +#: catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:951 +#: commands/sequence.c:1655 commands/tablecmds.c:7541 commands/tablecmds.c:7695 +#: commands/tablecmds.c:7745 commands/tablecmds.c:7819 +#: commands/tablecmds.c:7889 commands/tablecmds.c:8019 +#: commands/tablecmds.c:8148 commands/tablecmds.c:8242 +#: commands/tablecmds.c:8343 commands/tablecmds.c:8470 +#: commands/tablecmds.c:8500 commands/tablecmds.c:8642 +#: commands/tablecmds.c:8735 commands/tablecmds.c:8869 +#: commands/tablecmds.c:8981 commands/tablecmds.c:12797 +#: commands/tablecmds.c:12989 commands/tablecmds.c:13150 +#: commands/tablecmds.c:14339 commands/tablecmds.c:16966 commands/trigger.c:942 +#: parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 +#: parser/parse_type.c:144 parser/parse_utilcmd.c:3409 +#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2923 +#: utils/adt/ruleutils.c:2812 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "no existe la columna «%s» en la relación «%s»" -#: catalog/aclchk.c:1840 +#: catalog/aclchk.c:1862 #, c-format msgid "\"%s\" is an index" msgstr "«%s» es un índice" -#: catalog/aclchk.c:1847 commands/tablecmds.c:13901 commands/tablecmds.c:17200 +#: catalog/aclchk.c:1869 commands/tablecmds.c:14496 commands/tablecmds.c:17882 #, c-format msgid "\"%s\" is a composite type" msgstr "«%s» es un tipo compuesto" -#: catalog/aclchk.c:1855 catalog/objectaddress.c:1401 commands/sequence.c:1171 -#: commands/tablecmds.c:254 commands/tablecmds.c:17164 utils/adt/acl.c:2092 -#: utils/adt/acl.c:2122 utils/adt/acl.c:2154 utils/adt/acl.c:2186 -#: utils/adt/acl.c:2214 utils/adt/acl.c:2244 +#: catalog/aclchk.c:1877 catalog/objectaddress.c:1363 commands/tablecmds.c:263 +#: commands/tablecmds.c:17846 utils/adt/acl.c:2107 utils/adt/acl.c:2137 +#: utils/adt/acl.c:2170 utils/adt/acl.c:2206 utils/adt/acl.c:2237 +#: utils/adt/acl.c:2268 #, c-format msgid "\"%s\" is not a sequence" msgstr "«%s» no es una secuencia" -#: catalog/aclchk.c:1893 +#: catalog/aclchk.c:1915 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "la secuencia «%s» sólo soporta los privilegios USAGE, SELECT, y UPDATE" -#: catalog/aclchk.c:1910 +#: catalog/aclchk.c:1932 #, c-format msgid "invalid privilege type %s for table" msgstr "el tipo de privilegio %s no es válido para una tabla" -#: catalog/aclchk.c:2072 +#: catalog/aclchk.c:2097 #, c-format msgid "invalid privilege type %s for column" msgstr "el tipo de privilegio %s no es válido para una columna" -#: catalog/aclchk.c:2085 +#: catalog/aclchk.c:2110 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "la secuencia «%s» sólo soporta el privilegio SELECT" -#: catalog/aclchk.c:2275 +#: catalog/aclchk.c:2301 #, c-format msgid "language \"%s\" is not trusted" msgstr "el lenguaje «%s» no es confiable (trusted)" -#: catalog/aclchk.c:2277 +#: catalog/aclchk.c:2303 #, c-format msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages." msgstr "GRANT y REVOKE no están permitidos en lenguajes no confiables, porque sólo los superusuarios pueden usar lenguajes no confiables." -#: catalog/aclchk.c:2427 +#: catalog/aclchk.c:2454 #, c-format msgid "cannot set privileges of array types" msgstr "no se puede definir privilegios para tipos de array" -#: catalog/aclchk.c:2428 +#: catalog/aclchk.c:2455 #, c-format msgid "Set the privileges of the element type instead." msgstr "Defina los privilegios del tipo elemento en su lugar." -#: catalog/aclchk.c:2435 catalog/objectaddress.c:1667 +#: catalog/aclchk.c:2459 +#, c-format +msgid "cannot set privileges of multirange types" +msgstr "no se puede definir privilegios para tipos multirango" + +#: catalog/aclchk.c:2460 +#, c-format +msgid "Set the privileges of the range type instead." +msgstr "Defina los privilegios del tipo de rango en su lugar." + +#: catalog/aclchk.c:2467 catalog/objectaddress.c:1629 #, c-format msgid "\"%s\" is not a domain" msgstr "«%s» no es un dominio" -#: catalog/aclchk.c:2621 +#: catalog/aclchk.c:2653 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "tipo de privilegio «%s» no reconocido" -#: catalog/aclchk.c:2688 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for aggregate %s" msgstr "permiso denegado a la función de agregación %s" -#: catalog/aclchk.c:2691 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for collation %s" msgstr "permiso denegado al ordenamiento (collation) %s" -#: catalog/aclchk.c:2694 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for column %s" msgstr "permiso denegado a la columna %s" -#: catalog/aclchk.c:2697 +#: catalog/aclchk.c:2729 #, c-format msgid "permission denied for conversion %s" msgstr "permiso denegado a la conversión %s" -#: catalog/aclchk.c:2700 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for database %s" msgstr "permiso denegado a la base de datos %s" -#: catalog/aclchk.c:2703 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for domain %s" msgstr "permiso denegado al dominio %s" -#: catalog/aclchk.c:2706 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for event trigger %s" -msgstr "permiso denegado al disparador por eventos %s" +msgstr "permiso denegado al “trigger” por eventos %s" -#: catalog/aclchk.c:2709 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for extension %s" msgstr "permiso denegado a la extensión %s" -#: catalog/aclchk.c:2712 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "permiso denegado al conector de datos externos %s" -#: catalog/aclchk.c:2715 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for foreign server %s" msgstr "permiso denegado al servidor foráneo %s" -#: catalog/aclchk.c:2718 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for foreign table %s" msgstr "permiso denegado a la tabla foránea %s" -#: catalog/aclchk.c:2721 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for function %s" msgstr "permiso denegado a la función %s" -#: catalog/aclchk.c:2724 +#: catalog/aclchk.c:2756 #, c-format msgid "permission denied for index %s" msgstr "permiso denegado al índice %s" -#: catalog/aclchk.c:2727 +#: catalog/aclchk.c:2759 #, c-format msgid "permission denied for language %s" msgstr "permiso denegado al lenguaje %s" -#: catalog/aclchk.c:2730 +#: catalog/aclchk.c:2762 #, c-format msgid "permission denied for large object %s" msgstr "permiso denegado al objeto grande %s" -#: catalog/aclchk.c:2733 +#: catalog/aclchk.c:2765 #, c-format msgid "permission denied for materialized view %s" msgstr "permiso denegado a la vista materializada %s" -#: catalog/aclchk.c:2736 +#: catalog/aclchk.c:2768 #, c-format msgid "permission denied for operator class %s" msgstr "permiso denegado a la clase de operadores %s" -#: catalog/aclchk.c:2739 +#: catalog/aclchk.c:2771 #, c-format msgid "permission denied for operator %s" msgstr "permiso denegado al operador %s" -#: catalog/aclchk.c:2742 +#: catalog/aclchk.c:2774 #, c-format msgid "permission denied for operator family %s" msgstr "permiso denegado a la familia de operadores %s" -#: catalog/aclchk.c:2745 +#: catalog/aclchk.c:2777 #, c-format msgid "permission denied for parameter %s" msgstr "permiso denegado al parámetro %s" -#: catalog/aclchk.c:2748 +#: catalog/aclchk.c:2780 #, c-format msgid "permission denied for policy %s" msgstr "permiso denegado a la política %s" -#: catalog/aclchk.c:2751 +#: catalog/aclchk.c:2783 #, c-format msgid "permission denied for procedure %s" msgstr "permiso denegado al procedimiento %s" -#: catalog/aclchk.c:2754 +#: catalog/aclchk.c:2786 #, c-format msgid "permission denied for publication %s" msgstr "permiso denegado a la publicación %s" -#: catalog/aclchk.c:2757 +#: catalog/aclchk.c:2789 #, c-format msgid "permission denied for routine %s" msgstr "permiso denegado a la rutina %s" -#: catalog/aclchk.c:2760 +#: catalog/aclchk.c:2792 #, c-format msgid "permission denied for schema %s" msgstr "permiso denegado al esquema %s" -#: catalog/aclchk.c:2763 commands/sequence.c:659 commands/sequence.c:885 -#: commands/sequence.c:927 commands/sequence.c:968 commands/sequence.c:1761 -#: commands/sequence.c:1810 +#: catalog/aclchk.c:2795 commands/sequence.c:654 commands/sequence.c:880 +#: commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 +#: commands/sequence.c:1799 #, c-format msgid "permission denied for sequence %s" msgstr "permiso denegado a la secuencia %s" -#: catalog/aclchk.c:2766 +#: catalog/aclchk.c:2798 #, c-format msgid "permission denied for statistics object %s" msgstr "permiso denegado al objeto de estadísticas %s" -#: catalog/aclchk.c:2769 +#: catalog/aclchk.c:2801 #, c-format msgid "permission denied for subscription %s" msgstr "permiso denegado a la suscripción %s" -#: catalog/aclchk.c:2772 +#: catalog/aclchk.c:2804 #, c-format msgid "permission denied for table %s" msgstr "permiso denegado a la tabla %s" -#: catalog/aclchk.c:2775 +#: catalog/aclchk.c:2807 #, c-format msgid "permission denied for tablespace %s" msgstr "permiso denegado al tablespace %s" -#: catalog/aclchk.c:2778 +#: catalog/aclchk.c:2810 #, c-format msgid "permission denied for text search configuration %s" msgstr "permiso denegado a la configuración de búsqueda en texto %s" -#: catalog/aclchk.c:2781 +#: catalog/aclchk.c:2813 #, c-format msgid "permission denied for text search dictionary %s" msgstr "permiso denegado a la configuración de búsqueda en texto %s" -#: catalog/aclchk.c:2784 +#: catalog/aclchk.c:2816 #, c-format msgid "permission denied for type %s" msgstr "permiso denegado al tipo %s" -#: catalog/aclchk.c:2787 +#: catalog/aclchk.c:2819 #, c-format msgid "permission denied for view %s" msgstr "permiso denegado a la vista %s" -#: catalog/aclchk.c:2823 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of aggregate %s" msgstr "debe ser dueño de la función de agregación %s" -#: catalog/aclchk.c:2826 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of collation %s" msgstr "debe ser dueño del ordenamiento (collation) %s" -#: catalog/aclchk.c:2829 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of conversion %s" msgstr "debe ser dueño de la conversión %s" -#: catalog/aclchk.c:2832 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of database %s" msgstr "debe ser dueño de la base de datos %s" -#: catalog/aclchk.c:2835 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of domain %s" msgstr "debe ser dueño del dominio %s" -#: catalog/aclchk.c:2838 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of event trigger %s" -msgstr "debe ser dueño del disparador por eventos %s" +msgstr "debe ser dueño del “trigger” por eventos %s" -#: catalog/aclchk.c:2841 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of extension %s" msgstr "debe ser dueño de la extensión %s" -#: catalog/aclchk.c:2844 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "debe ser dueño del conector de datos externos %s" -#: catalog/aclchk.c:2847 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of foreign server %s" msgstr "debe ser dueño del servidor foráneo %s" -#: catalog/aclchk.c:2850 +#: catalog/aclchk.c:2882 #, c-format msgid "must be owner of foreign table %s" msgstr "debe ser dueño de la tabla foránea %s" -#: catalog/aclchk.c:2853 +#: catalog/aclchk.c:2885 #, c-format msgid "must be owner of function %s" msgstr "debe ser dueño de la función %s" -#: catalog/aclchk.c:2856 +#: catalog/aclchk.c:2888 #, c-format msgid "must be owner of index %s" msgstr "debe ser dueño del índice %s" -#: catalog/aclchk.c:2859 +#: catalog/aclchk.c:2891 #, c-format msgid "must be owner of language %s" msgstr "debe ser dueño del lenguaje %s" -#: catalog/aclchk.c:2862 +#: catalog/aclchk.c:2894 #, c-format msgid "must be owner of large object %s" msgstr "debe ser dueño del objeto grande %s" -#: catalog/aclchk.c:2865 +#: catalog/aclchk.c:2897 #, c-format msgid "must be owner of materialized view %s" msgstr "debe ser dueño de la vista materializada %s" -#: catalog/aclchk.c:2868 +#: catalog/aclchk.c:2900 #, c-format msgid "must be owner of operator class %s" msgstr "debe ser dueño de la clase de operadores %s" -#: catalog/aclchk.c:2871 +#: catalog/aclchk.c:2903 #, c-format msgid "must be owner of operator %s" msgstr "debe ser dueño del operador %s" -#: catalog/aclchk.c:2874 +#: catalog/aclchk.c:2906 #, c-format msgid "must be owner of operator family %s" msgstr "debe ser dueño de la familia de operadores %s" -#: catalog/aclchk.c:2877 +#: catalog/aclchk.c:2909 #, c-format msgid "must be owner of procedure %s" msgstr "debe ser dueño del procedimiento %s" -#: catalog/aclchk.c:2880 +#: catalog/aclchk.c:2912 #, c-format msgid "must be owner of publication %s" msgstr "debe ser dueño de la publicación %s" -#: catalog/aclchk.c:2883 +#: catalog/aclchk.c:2915 #, c-format msgid "must be owner of routine %s" msgstr "debe ser dueño de la rutina %s" -#: catalog/aclchk.c:2886 +#: catalog/aclchk.c:2918 #, c-format msgid "must be owner of sequence %s" msgstr "debe ser dueño de la secuencia %s" -#: catalog/aclchk.c:2889 +#: catalog/aclchk.c:2921 #, c-format msgid "must be owner of subscription %s" msgstr "debe ser dueño de la suscripción %s" -#: catalog/aclchk.c:2892 +#: catalog/aclchk.c:2924 #, c-format msgid "must be owner of table %s" msgstr "debe ser dueño de la tabla %s" -#: catalog/aclchk.c:2895 +#: catalog/aclchk.c:2927 #, c-format msgid "must be owner of type %s" msgstr "debe ser dueño del tipo %s" -#: catalog/aclchk.c:2898 +#: catalog/aclchk.c:2930 #, c-format msgid "must be owner of view %s" msgstr "debe ser dueño de la vista %s" -#: catalog/aclchk.c:2901 +#: catalog/aclchk.c:2933 #, c-format msgid "must be owner of schema %s" msgstr "debe ser dueño del esquema %s" -#: catalog/aclchk.c:2904 +#: catalog/aclchk.c:2936 #, c-format msgid "must be owner of statistics object %s" msgstr "debe ser dueño del objeto de estadísticas %s" -#: catalog/aclchk.c:2907 +#: catalog/aclchk.c:2939 #, c-format msgid "must be owner of tablespace %s" msgstr "debe ser dueño del tablespace %s" -#: catalog/aclchk.c:2910 +#: catalog/aclchk.c:2942 #, c-format msgid "must be owner of text search configuration %s" msgstr "debe ser dueño de la configuración de búsqueda en texto %s" -#: catalog/aclchk.c:2913 +#: catalog/aclchk.c:2945 #, c-format msgid "must be owner of text search dictionary %s" msgstr "debe ser dueño del diccionario de búsqueda en texto %s" -#: catalog/aclchk.c:2927 +#: catalog/aclchk.c:2959 #, c-format msgid "must be owner of relation %s" msgstr "debe ser dueño de la relación %s" -#: catalog/aclchk.c:2973 +#: catalog/aclchk.c:3005 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "permiso denegado a la columna «%s» de la relación «%s»" -#: catalog/aclchk.c:3108 catalog/aclchk.c:3994 catalog/aclchk.c:4026 -#, fuzzy, c-format -#| msgid "schema with OID %u does not exist" +#: catalog/aclchk.c:3162 catalog/aclchk.c:4170 catalog/aclchk.c:4201 +#, c-format msgid "%s with OID %u does not exist" -msgstr "no existe el esquema con OID %u" +msgstr "%s con el OID %u no existe" -#: catalog/aclchk.c:3192 catalog/aclchk.c:3211 +#: catalog/aclchk.c:3245 catalog/aclchk.c:3264 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "no existe el atributo %d de la relación con OID %u" -#: catalog/aclchk.c:3306 +#: catalog/aclchk.c:3302 catalog/aclchk.c:3365 catalog/aclchk.c:4004 #, c-format msgid "relation with OID %u does not exist" msgstr "no existe la relación con OID %u" -#: catalog/aclchk.c:3491 +#: catalog/aclchk.c:3550 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "no existe el ACL de parámetro con OID %u" -#: catalog/aclchk.c:3655 commands/collationcmds.c:808 -#: commands/publicationcmds.c:1746 +#: catalog/aclchk.c:3723 commands/collationcmds.c:853 +#: commands/publicationcmds.c:1739 #, c-format msgid "schema with OID %u does not exist" msgstr "no existe el esquema con OID %u" -#: catalog/aclchk.c:3720 utils/cache/typcache.c:385 utils/cache/typcache.c:440 +#: catalog/aclchk.c:3797 catalog/aclchk.c:3824 catalog/aclchk.c:3853 +#: utils/cache/typcache.c:392 utils/cache/typcache.c:447 #, c-format msgid "type with OID %u does not exist" msgstr "no existe el tipo con OID %u" -#: catalog/catalog.c:449 +#: catalog/catalog.c:477 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "aún se está buscando algún OID sin utilizar en la relación «%s»" -#: catalog/catalog.c:451 +#: catalog/catalog.c:479 #, c-format msgid "OID candidates have been checked %llu time, but no unused OID has been found yet." msgid_plural "OID candidates have been checked %llu times, but no unused OID has been found yet." msgstr[0] "se han revisado los OID candidatos %llu vez, pero aún no se ha encontrado algún OID sin utilizar." msgstr[1] "se han revisado los OID candidatos %llu veces, pero aún no se ha encontrado algún OID sin utilizar." -#: catalog/catalog.c:476 +#: catalog/catalog.c:504 #, c-format msgid "new OID has been assigned in relation \"%s\" after %llu retry" msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" msgstr[0] "se ha asignado un nuevo OID en la relación «%s» luego de %llu reintento" msgstr[1] "se ha asignado un nuevo OID en la relación «%s» luego de %llu reintentos" -#: catalog/catalog.c:609 catalog/catalog.c:676 +#: catalog/catalog.c:637 catalog/catalog.c:704 #, c-format msgid "must be superuser to call %s()" msgstr "debe ser superusuario para invocar %s()" -#: catalog/catalog.c:618 +#: catalog/catalog.c:646 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() sólo puede usarse en catálogos de sistema" -#: catalog/catalog.c:623 parser/parse_utilcmd.c:2264 +#: catalog/catalog.c:651 parser/parse_utilcmd.c:2270 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "el índice «%s» no pertenece a la tabla «%s»" -#: catalog/catalog.c:640 +#: catalog/catalog.c:668 #, c-format msgid "column \"%s\" is not of type oid" msgstr "la columna «%s» no es de tipo oid" -#: catalog/catalog.c:647 +#: catalog/catalog.c:675 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "«el índice %s» no es el índice para la columna «%s»" -#: catalog/dependency.c:546 catalog/pg_shdepend.c:658 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "no se puede eliminar %s porque es requerido por el sistema" -#: catalog/dependency.c:838 catalog/dependency.c:1065 +#: catalog/dependency.c:789 catalog/dependency.c:1016 #, c-format msgid "cannot drop %s because %s requires it" msgstr "no se puede eliminar %s porque %s lo requiere" -#: catalog/dependency.c:840 catalog/dependency.c:1067 +#: catalog/dependency.c:791 catalog/dependency.c:1018 #, c-format msgid "You can drop %s instead." msgstr "Puede eliminar %s en su lugar." -#: catalog/dependency.c:1146 catalog/dependency.c:1155 +#: catalog/dependency.c:1097 catalog/dependency.c:1106 #, c-format msgid "%s depends on %s" msgstr "%s depende de %s" -#: catalog/dependency.c:1170 catalog/dependency.c:1179 +#: catalog/dependency.c:1121 catalog/dependency.c:1130 #, c-format msgid "drop cascades to %s" msgstr "eliminando además %s" -#: catalog/dependency.c:1187 catalog/pg_shdepend.c:823 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -4496,720 +4819,715 @@ msgstr[1] "" "\n" "y otros %d objetos (vea el registro del servidor para obtener la lista)" -#: catalog/dependency.c:1199 +#: catalog/dependency.c:1150 #, c-format msgid "cannot drop %s because other objects depend on it" msgstr "no se puede eliminar %s porque otros objetos dependen de él" -#: catalog/dependency.c:1202 catalog/dependency.c:1209 -#: catalog/dependency.c:1220 commands/tablecmds.c:1335 -#: commands/tablecmds.c:14386 commands/tablespace.c:466 commands/user.c:1309 -#: commands/vacuum.c:212 commands/view.c:446 libpq/auth.c:326 -#: replication/logical/applyparallelworker.c:1044 replication/syncrep.c:1017 -#: storage/lmgr/deadlock.c:1135 storage/lmgr/proc.c:1358 utils/misc/guc.c:3120 -#: utils/misc/guc.c:3156 utils/misc/guc.c:3226 utils/misc/guc.c:6615 -#: utils/misc/guc.c:6649 utils/misc/guc.c:6683 utils/misc/guc.c:6726 -#: utils/misc/guc.c:6768 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 +#: catalog/dependency.c:1171 commands/tablecmds.c:1459 +#: commands/tablecmds.c:15088 commands/tablespace.c:460 commands/user.c:1302 +#: commands/vacuum.c:211 commands/view.c:441 executor/execExprInterp.c:4655 +#: executor/execExprInterp.c:4663 libpq/auth.c:324 +#: replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 +#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1432 utils/misc/guc.c:3169 +#: utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6825 +#: utils/misc/guc.c:6859 utils/misc/guc.c:6893 utils/misc/guc.c:6936 +#: utils/misc/guc.c:6978 #, c-format msgid "%s" msgstr "%s" -#: catalog/dependency.c:1203 catalog/dependency.c:1210 +#: catalog/dependency.c:1154 catalog/dependency.c:1161 #, c-format msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "Use DROP ... CASCADE para eliminar además los objetos dependientes." -#: catalog/dependency.c:1207 +#: catalog/dependency.c:1158 #, c-format msgid "cannot drop desired object(s) because other objects depend on them" msgstr "no se puede eliminar el o los objetos deseados porque otros objetos dependen de ellos" -#: catalog/dependency.c:1215 +#: catalog/dependency.c:1166 #, c-format msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" msgstr[0] "eliminando además %d objeto más" msgstr[1] "eliminando además %d objetos más" -#: catalog/dependency.c:1899 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "no se puede usar una constante de tipo %s aquí" -#: catalog/dependency.c:2420 parser/parse_relation.c:3403 -#: parser/parse_relation.c:3413 +#: catalog/dependency.c:2375 parser/parse_relation.c:3407 +#: parser/parse_relation.c:3417 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "no existe la columna %d en la relación «%s»" -#: catalog/heap.c:324 +#: catalog/heap.c:325 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "se ha denegado el permiso para crear «%s.%s»" -#: catalog/heap.c:326 +#: catalog/heap.c:327 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "Las modificaciones al catálogo del sistema están actualmente deshabilitadas." -#: catalog/heap.c:466 commands/tablecmds.c:2374 commands/tablecmds.c:3047 -#: commands/tablecmds.c:6922 +#: catalog/heap.c:467 commands/tablecmds.c:2495 commands/tablecmds.c:2917 +#: commands/tablecmds.c:7163 #, c-format msgid "tables can have at most %d columns" msgstr "las tablas pueden tener a lo más %d columnas" -#: catalog/heap.c:484 commands/tablecmds.c:7229 +#: catalog/heap.c:485 commands/tablecmds.c:7432 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "el nombre de columna «%s» colisiona con nombre de una columna de sistema" -#: catalog/heap.c:500 +#: catalog/heap.c:501 #, c-format msgid "column name \"%s\" specified more than once" msgstr "el nombre de columna «%s» fue especificado más de una vez" #. translator: first %s is an integer not a name -#: catalog/heap.c:575 +#: catalog/heap.c:579 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "la columna %s de la llave de partición tiene pseudotipo %s" -#: catalog/heap.c:580 +#: catalog/heap.c:584 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "la columna «%s» tiene pseudotipo %s" -#: catalog/heap.c:611 +#: catalog/heap.c:615 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "un tipo compuesto %s no puede ser hecho miembro de sí mismo" #. translator: first %s is an integer not a name -#: catalog/heap.c:666 +#: catalog/heap.c:670 #, c-format msgid "no collation was derived for partition key column %s with collatable type %s" msgstr "no se derivó ningún ordenamiento (collate) para la columna %s de llave de partición con tipo ordenable %s" -#: catalog/heap.c:672 commands/createas.c:203 commands/createas.c:512 +#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:505 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "no se derivó ningún ordenamiento (collate) para la columna «%s» con tipo ordenable %s" -#: catalog/heap.c:1148 catalog/index.c:886 commands/createas.c:408 -#: commands/tablecmds.c:3987 +#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:401 +#: commands/tablecmds.c:4171 #, c-format msgid "relation \"%s\" already exists" msgstr "la relación «%s» ya existe" -#: catalog/heap.c:1164 catalog/pg_type.c:434 catalog/pg_type.c:782 -#: catalog/pg_type.c:954 commands/typecmds.c:249 commands/typecmds.c:261 -#: commands/typecmds.c:754 commands/typecmds.c:1169 commands/typecmds.c:1395 -#: commands/typecmds.c:1575 commands/typecmds.c:2546 +#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 +#: catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 +#: commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 +#: commands/typecmds.c:1585 commands/typecmds.c:2556 #, c-format msgid "type \"%s\" already exists" msgstr "ya existe un tipo «%s»" -#: catalog/heap.c:1165 +#: catalog/heap.c:1178 #, c-format msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type." msgstr "Una relación tiene un tipo asociado del mismo nombre, de modo que debe usar un nombre que no entre en conflicto con un tipo existente." -#: catalog/heap.c:1205 -#, fuzzy, c-format -#| msgid "pg_enum OID value not set when in binary upgrade mode" +#: catalog/heap.c:1218 +#, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" -msgstr "el valor de OID de pg_enum no se definió en modo de actualización binaria" +msgstr "el valor de relfilenumber de toast no se definió en modo de actualización binaria" -#: catalog/heap.c:1216 +#: catalog/heap.c:1229 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "el valor de OID de heap de pg_class no se definió en modo de actualización binaria" -#: catalog/heap.c:1226 -#, fuzzy, c-format -#| msgid "pg_enum OID value not set when in binary upgrade mode" +#: catalog/heap.c:1239 +#, c-format msgid "relfilenumber value not set when in binary upgrade mode" -msgstr "el valor de OID de pg_enum no se definió en modo de actualización binaria" +msgstr "el valor de relfilenumber no se definió en modo de actualización binaria" -#: catalog/heap.c:2119 +#: catalog/heap.c:2130 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "no se puede agregar una restricción NO INHERIT a la tabla particionada «%s»" -#: catalog/heap.c:2393 +#: catalog/heap.c:2402 #, c-format msgid "check constraint \"%s\" already exists" msgstr "la restricción «check» «%s» ya existe" -#: catalog/heap.c:2563 catalog/index.c:900 catalog/pg_constraint.c:682 -#: commands/tablecmds.c:8900 +#: catalog/heap.c:2574 catalog/index.c:913 catalog/pg_constraint.c:724 +#: commands/tablecmds.c:9356 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "la restricción «%s» para la relación «%s» ya existe" -#: catalog/heap.c:2570 +#: catalog/heap.c:2581 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "la restricción «%s» está en conflicto con la restricción no heredada de la relación «%s»" -#: catalog/heap.c:2581 +#: catalog/heap.c:2592 #, c-format msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "la restricción «%s» está en conflicto con la restricción heredada de la relación «%s»" -#: catalog/heap.c:2591 +#: catalog/heap.c:2602 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "la restricción «%s» está en conflicto con la restricción NOT VALID de la relación «%s»" -#: catalog/heap.c:2596 +#: catalog/heap.c:2607 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "mezclando la restricción «%s» con la definición heredada" -#: catalog/heap.c:2622 catalog/pg_constraint.c:811 commands/tablecmds.c:2672 -#: commands/tablecmds.c:3199 commands/tablecmds.c:6858 -#: commands/tablecmds.c:15208 commands/tablecmds.c:15349 -#, fuzzy, c-format -#| msgid "too many command-line arguments" +#: catalog/heap.c:2633 catalog/pg_constraint.c:853 commands/tablecmds.c:3074 +#: commands/tablecmds.c:3377 commands/tablecmds.c:7089 +#: commands/tablecmds.c:15907 commands/tablecmds.c:16038 +#, c-format msgid "too many inheritance parents" -msgstr "demasiados argumentos de línea de órdenes" +msgstr "demasiados padres de herencia" -#: catalog/heap.c:2706 +#: catalog/heap.c:2717 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "no se puede usar la columna generada «%s» en una expresión de generación de columna" -#: catalog/heap.c:2708 +#: catalog/heap.c:2719 #, c-format msgid "A generated column cannot reference another generated column." msgstr "Una columna generada no puede hacer referencia a otra columna generada." -#: catalog/heap.c:2714 +#: catalog/heap.c:2725 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "no se puede usar una variable de fila completa (whole-row) en una expresión de generación de columna" -#: catalog/heap.c:2715 +#: catalog/heap.c:2726 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "Esto causaría que la columna generada dependa de su propio valor." -#: catalog/heap.c:2768 +#: catalog/heap.c:2781 #, c-format msgid "generation expression is not immutable" msgstr "la expresión de generación no es inmutable" -#: catalog/heap.c:2796 rewrite/rewriteHandler.c:1295 +#: catalog/heap.c:2809 rewrite/rewriteHandler.c:1276 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "la columna «%s» es de tipo %s pero la expresión default es de tipo %s" -#: catalog/heap.c:2801 commands/prepare.c:334 parser/analyze.c:2704 -#: parser/parse_target.c:593 parser/parse_target.c:874 -#: parser/parse_target.c:884 rewrite/rewriteHandler.c:1300 +#: catalog/heap.c:2814 commands/prepare.c:331 parser/analyze.c:2758 +#: parser/parse_target.c:592 parser/parse_target.c:882 +#: parser/parse_target.c:892 rewrite/rewriteHandler.c:1281 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "Necesitará reescribir la expresión o aplicarle una conversión de tipo." -#: catalog/heap.c:2848 +#: catalog/heap.c:2861 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "sólo la tabla «%s» puede ser referenciada en una restricción «check»" -#: catalog/heap.c:3154 +#: catalog/heap.c:3167 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "combinación de ON COMMIT y llaves foráneas no soportada" -#: catalog/heap.c:3155 +#: catalog/heap.c:3168 #, c-format msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting." msgstr "La tabla «%s» se refiere a «%s», pero no tienen la misma expresión para ON COMMIT." -#: catalog/heap.c:3160 +#: catalog/heap.c:3173 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "no se puede truncar una tabla referida en una llave foránea" -#: catalog/heap.c:3161 +#: catalog/heap.c:3174 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "La tabla «%s» hace referencia a «%s»." -#: catalog/heap.c:3163 +#: catalog/heap.c:3176 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "Trunque la tabla «%s» al mismo tiempo, o utilice TRUNCATE ... CASCADE." -#: catalog/index.c:224 parser/parse_utilcmd.c:2170 +#: catalog/index.c:219 parser/parse_utilcmd.c:2176 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "no se permiten múltiples llaves primarias para la tabla «%s»" -#: catalog/index.c:238 -#, fuzzy, c-format -#| msgid "primary keys cannot be expressions" +#: catalog/index.c:233 +#, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" -msgstr "las llaves primarias no pueden ser expresiones" +msgstr "las llaves primarias no pueden usar índices NULLS NOT DISTINCT" -#: catalog/index.c:255 +#: catalog/index.c:250 #, c-format msgid "primary keys cannot be expressions" msgstr "las llaves primarias no pueden ser expresiones" -#: catalog/index.c:272 +#: catalog/index.c:267 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "columna de llave primaria «%s» no está marcada NOT NULL" -#: catalog/index.c:785 catalog/index.c:1941 +#: catalog/index.c:798 catalog/index.c:1915 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "los usuarios no pueden crear índices en tablas del sistema" -#: catalog/index.c:825 +#: catalog/index.c:838 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "los ordenamientos no determinísticos no están soportados para la clase de operadores «%s»" -#: catalog/index.c:840 +#: catalog/index.c:853 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "no se pueden crear índices de forma concurrente en tablas del sistema" -#: catalog/index.c:849 catalog/index.c:1317 +#: catalog/index.c:862 catalog/index.c:1331 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "no se pueden crear índices para restricciones de exclusión de forma concurrente" -#: catalog/index.c:858 +#: catalog/index.c:871 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "no se pueden crear índices compartidos después de initdb" -#: catalog/index.c:878 commands/createas.c:423 commands/sequence.c:158 +#: catalog/index.c:891 commands/createas.c:416 commands/sequence.c:159 #: parser/parse_utilcmd.c:209 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "la relación «%s» ya existe, omitiendo" -#: catalog/index.c:928 +#: catalog/index.c:941 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "el valor de OID de índice de pg_class no se definió en modo de actualización binaria" -#: catalog/index.c:938 utils/cache/relcache.c:3730 -#, fuzzy, c-format -#| msgid "pg_enum OID value not set when in binary upgrade mode" +#: catalog/index.c:951 utils/cache/relcache.c:3791 +#, c-format msgid "index relfilenumber value not set when in binary upgrade mode" -msgstr "el valor de OID de pg_enum no se definió en modo de actualización binaria" +msgstr "el valor relfilenumber de índice no se definió en modo de actualización binaria" -#: catalog/index.c:2240 +#: catalog/index.c:2214 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY debe ser la primera acción en una transacción" -#: catalog/index.c:3647 +#: catalog/index.c:3668 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "no se puede hacer reindex de tablas temporales de otras sesiones" -#: catalog/index.c:3658 commands/indexcmds.c:3623 +#: catalog/index.c:3679 commands/indexcmds.c:3626 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "no es posible reindexar un índice no válido en tabla TOAST" -#: catalog/index.c:3674 commands/indexcmds.c:3503 commands/indexcmds.c:3647 -#: commands/tablecmds.c:3402 +#: catalog/index.c:3695 commands/indexcmds.c:3504 commands/indexcmds.c:3650 +#: commands/tablecmds.c:3581 #, c-format msgid "cannot move system relation \"%s\"" msgstr "no se puede mover la relación de sistema «%s»" -#: catalog/index.c:3818 +#: catalog/index.c:3832 #, c-format msgid "index \"%s\" was reindexed" msgstr "el índice «%s» fue reindexado" -#: catalog/index.c:3955 +#: catalog/index.c:3998 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "no se puede reindexar el índice no válido «%s.%s» en tabla TOAST, omitiendo" -#: catalog/namespace.c:260 catalog/namespace.c:464 catalog/namespace.c:556 -#: commands/trigger.c:5687 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 +#: commands/trigger.c:5729 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "no están implementadas las referencias entre bases de datos: «%s.%s.%s»" -#: catalog/namespace.c:317 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "las tablas temporales no pueden especificar un nombre de esquema" -#: catalog/namespace.c:398 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" -msgstr "no se pudo bloquear un candado en la relación «%s.%s»" +msgstr "no se pudo bloquear un “lock” en la relación «%s.%s»" -#: catalog/namespace.c:403 commands/lockcmds.c:145 commands/lockcmds.c:225 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" -msgstr "no se pudo bloquear un candado en la relación «%s»" +msgstr "no se pudo bloquear un “lock” en la relación «%s»" -#: catalog/namespace.c:431 parser/parse_relation.c:1429 +#: catalog/namespace.c:633 parser/parse_relation.c:1430 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "no existe la relación «%s.%s»" -#: catalog/namespace.c:436 parser/parse_relation.c:1442 -#: parser/parse_relation.c:1450 utils/adt/regproc.c:913 +#: catalog/namespace.c:638 parser/parse_relation.c:1443 +#: parser/parse_relation.c:1451 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "no existe la relación «%s»" -#: catalog/namespace.c:502 catalog/namespace.c:3073 commands/extension.c:1584 -#: commands/extension.c:1590 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1607 +#: commands/extension.c:1613 #, c-format msgid "no schema has been selected to create in" msgstr "no se ha seleccionado ningún esquema dentro del cual crear" -#: catalog/namespace.c:654 catalog/namespace.c:667 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "no se pueden crear relaciones en esquemas temporales de otras sesiones" -#: catalog/namespace.c:658 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "no se pueden crear tablas temporales en esquemas no temporales" -#: catalog/namespace.c:673 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "sólo relaciones temporales pueden ser creadas en los esquemas temporales" -#: catalog/namespace.c:2265 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "no existe el objeto de estadísticas «%s»" -#: catalog/namespace.c:2388 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "no existe el analizador de búsqueda en texto «%s»" -#: catalog/namespace.c:2514 utils/adt/regproc.c:1439 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "no existe el diccionario de búsqueda en texto «%s»" -#: catalog/namespace.c:2641 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "no existe la plantilla de búsqueda en texto «%s»" -#: catalog/namespace.c:2767 commands/tsearchcmds.c:1162 -#: utils/adt/regproc.c:1329 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 +#: utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "no existe la configuración de búsqueda en texto «%s»" -#: catalog/namespace.c:2880 parser/parse_expr.c:832 parser/parse_target.c:1246 +#: catalog/namespace.c:3329 parser/parse_expr.c:868 parser/parse_target.c:1259 #, c-format msgid "cross-database references are not implemented: %s" msgstr "no están implementadas las referencias entre bases de datos: %s" -#: catalog/namespace.c:2886 parser/parse_expr.c:839 parser/parse_target.c:1253 -#: gram.y:18570 gram.y:18610 +#: catalog/namespace.c:3335 parser/parse_expr.c:875 parser/parse_target.c:1266 +#: gram.y:19181 gram.y:19221 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "el nombre no es válido (demasiados puntos): %s" -#: catalog/namespace.c:3016 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "no se puede mover objetos hacia o desde esquemas temporales" -#: catalog/namespace.c:3022 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "no se puede mover objetos hacia o desde el esquema TOAST" -#: catalog/namespace.c:3095 commands/schemacmds.c:264 commands/schemacmds.c:344 -#: commands/tablecmds.c:1280 utils/adt/regproc.c:1668 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 +#: commands/tablecmds.c:1404 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "no existe el esquema «%s»" -#: catalog/namespace.c:3126 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "el nombre de relación no es válido (demasiados puntos): %s" -#: catalog/namespace.c:3693 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "no existe el ordenamiento (collation) «%s» para la codificación «%s»" -#: catalog/namespace.c:3748 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "no existe la conversión «%s»" -#: catalog/namespace.c:4012 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "se ha denegado el permiso para crear tablas temporales en la base de datos «%s»" -#: catalog/namespace.c:4028 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "no se pueden crear tablas temporales durante la recuperación" -#: catalog/namespace.c:4034 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "no se pueden crear tablas temporales durante una operación paralela" -#: catalog/objectaddress.c:1409 commands/policy.c:96 commands/policy.c:376 -#: commands/tablecmds.c:248 commands/tablecmds.c:290 commands/tablecmds.c:2206 -#: commands/tablecmds.c:12357 +#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 +#: commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2327 +#: commands/tablecmds.c:12925 #, c-format msgid "\"%s\" is not a table" msgstr "«%s» no es una tabla" -#: catalog/objectaddress.c:1416 commands/tablecmds.c:260 -#: commands/tablecmds.c:17169 commands/view.c:119 +#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 +#: commands/tablecmds.c:17851 commands/view.c:114 #, c-format msgid "\"%s\" is not a view" msgstr "«%s» no es una vista" -#: catalog/objectaddress.c:1423 commands/matview.c:187 commands/tablecmds.c:266 -#: commands/tablecmds.c:17174 +#: catalog/objectaddress.c:1385 commands/matview.c:199 commands/tablecmds.c:275 +#: commands/tablecmds.c:17856 #, c-format msgid "\"%s\" is not a materialized view" msgstr "«%s» no es una vista materializada" -#: catalog/objectaddress.c:1430 commands/tablecmds.c:284 -#: commands/tablecmds.c:17179 +#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 +#: commands/tablecmds.c:17861 #, c-format msgid "\"%s\" is not a foreign table" msgstr "«%s» no es una tabla foránea" -#: catalog/objectaddress.c:1471 +#: catalog/objectaddress.c:1433 #, c-format msgid "must specify relation and object name" msgstr "debe especificar nombre de relación y nombre de objeto" -#: catalog/objectaddress.c:1547 catalog/objectaddress.c:1600 +#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 #, c-format msgid "column name must be qualified" msgstr "el nombre de columna debe ser calificado" -#: catalog/objectaddress.c:1619 +#: catalog/objectaddress.c:1581 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "no existe el valor por omisión para la columna «%s» de la relación «%s»" -#: catalog/objectaddress.c:1656 commands/functioncmds.c:137 -#: commands/tablecmds.c:276 commands/typecmds.c:274 commands/typecmds.c:3689 +#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 +#: commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 #: parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 -#: utils/adt/acl.c:4449 +#: utils/adt/acl.c:4560 #, c-format msgid "type \"%s\" does not exist" msgstr "no existe el tipo «%s»" -#: catalog/objectaddress.c:1775 +#: catalog/objectaddress.c:1737 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "no existe el operador %d (%s, %s) de %s" -#: catalog/objectaddress.c:1806 +#: catalog/objectaddress.c:1768 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "no existe la función %d (%s, %s) de %s" -#: catalog/objectaddress.c:1857 catalog/objectaddress.c:1883 +#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "no existe el mapeo para el usuario «%s» en el servidor «%s»" -#: catalog/objectaddress.c:1872 commands/foreigncmds.c:430 -#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:700 +#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 +#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "no existe el servidor «%s»" -#: catalog/objectaddress.c:1939 +#: catalog/objectaddress.c:1901 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "no existe la relación «%s» en la publicación «%s»" -#: catalog/objectaddress.c:1986 -#, fuzzy, c-format -#| msgid "publication relation \"%s\" in publication \"%s\" does not exist" +#: catalog/objectaddress.c:1948 +#, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" -msgstr "no existe la relación «%s» en la publicación «%s»" +msgstr "no existe el esquema de publicación «%s» en la publicación «%s»" -#: catalog/objectaddress.c:2044 +#: catalog/objectaddress.c:2006 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "tipo de objeto para ACL por omisión «%c» no reconocido" -#: catalog/objectaddress.c:2045 +#: catalog/objectaddress.c:2007 #, c-format msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." msgstr "Tipos válidos de objeto son «%c», «%c», «%c», «%c» y «%c»." -#: catalog/objectaddress.c:2096 +#: catalog/objectaddress.c:2058 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "no existe el ACL por omisión para el usuario «%s» en el esquema «%s» en %s" -#: catalog/objectaddress.c:2101 +#: catalog/objectaddress.c:2063 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "no existe el ACL por omisión para el usuario «%s» en %s" -#: catalog/objectaddress.c:2127 catalog/objectaddress.c:2184 -#: catalog/objectaddress.c:2239 +#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 +#: catalog/objectaddress.c:2201 #, c-format msgid "name or argument lists may not contain nulls" msgstr "las listas de nombres o argumentos no pueden contener nulls" -#: catalog/objectaddress.c:2161 +#: catalog/objectaddress.c:2123 #, c-format msgid "unsupported object type \"%s\"" msgstr "tipo de objeto «%s» no soportado" -#: catalog/objectaddress.c:2180 catalog/objectaddress.c:2197 -#: catalog/objectaddress.c:2262 catalog/objectaddress.c:2346 +#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 +#: catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 #, c-format msgid "name list length must be exactly %d" msgstr "el largo de la lista de nombres debe ser exactamente %d" -#: catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2163 #, c-format msgid "large object OID may not be null" msgstr "el OID de objeto grande no puede ser null" -#: catalog/objectaddress.c:2210 catalog/objectaddress.c:2280 -#: catalog/objectaddress.c:2287 +#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 +#: catalog/objectaddress.c:2249 #, c-format msgid "name list length must be at least %d" msgstr "el largo de la lista de nombres debe ser al menos %d" -#: catalog/objectaddress.c:2273 catalog/objectaddress.c:2294 +#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 #, c-format msgid "argument list length must be exactly %d" msgstr "el largo de la lista de argumentos debe ser exactamente %d" -#: catalog/objectaddress.c:2508 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 #, c-format msgid "must be owner of large object %u" msgstr "debe ser dueño del objeto grande %u" -#: catalog/objectaddress.c:2523 commands/functioncmds.c:1561 +#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 #, c-format msgid "must be owner of type %s or type %s" msgstr "debe ser dueño del tipo %s o el tipo %s" -#: catalog/objectaddress.c:2550 catalog/objectaddress.c:2559 -#: catalog/objectaddress.c:2565 +#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 +#: catalog/objectaddress.c:2527 #, c-format msgid "permission denied" msgstr "permiso denegado" -#: catalog/objectaddress.c:2551 catalog/objectaddress.c:2560 +#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 #, c-format msgid "The current user must have the %s attribute." -msgstr "" +msgstr "El usuario actual debe tener el atributo %s." -#: catalog/objectaddress.c:2566 +#: catalog/objectaddress.c:2528 #, c-format msgid "The current user must have the %s option on role \"%s\"." -msgstr "" +msgstr "El usuario actual debe tener la opción %s en el rol «%s»." -#: catalog/objectaddress.c:2580 +#: catalog/objectaddress.c:2542 #, c-format msgid "must be superuser" msgstr "debe ser superusuario" -#: catalog/objectaddress.c:2649 +#: catalog/objectaddress.c:2611 #, c-format msgid "unrecognized object type \"%s\"" msgstr "tipo de objeto «%s» no reconocido" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2941 +#: catalog/objectaddress.c:2928 #, c-format msgid "column %s of %s" msgstr "columna %s de %s" -#: catalog/objectaddress.c:2956 +#: catalog/objectaddress.c:2943 #, c-format msgid "function %s" msgstr "función %s" -#: catalog/objectaddress.c:2969 +#: catalog/objectaddress.c:2956 #, c-format msgid "type %s" msgstr "tipo %s" -#: catalog/objectaddress.c:3006 +#: catalog/objectaddress.c:2993 #, c-format msgid "cast from %s to %s" msgstr "conversión de %s a %s" -#: catalog/objectaddress.c:3039 +#: catalog/objectaddress.c:3026 #, c-format msgid "collation %s" msgstr "ordenamiento (collation) %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3057 #, c-format msgid "constraint %s on %s" msgstr "restricción «%s» en %s" -#: catalog/objectaddress.c:3076 +#: catalog/objectaddress.c:3063 #, c-format msgid "constraint %s" msgstr "restricción %s" -#: catalog/objectaddress.c:3108 +#: catalog/objectaddress.c:3095 #, c-format msgid "conversion %s" msgstr "conversión %s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3130 +#: catalog/objectaddress.c:3117 #, c-format msgid "default value for %s" msgstr "valor por omisión para %s" -#: catalog/objectaddress.c:3141 +#: catalog/objectaddress.c:3128 #, c-format msgid "language %s" msgstr "lenguaje %s" -#: catalog/objectaddress.c:3149 +#: catalog/objectaddress.c:3136 #, c-format msgid "large object %u" msgstr "objeto grande %u" -#: catalog/objectaddress.c:3162 +#: catalog/objectaddress.c:3149 #, c-format msgid "operator %s" msgstr "operador %s" -#: catalog/objectaddress.c:3199 +#: catalog/objectaddress.c:3186 #, c-format msgid "operator class %s for access method %s" msgstr "clase de operadores «%s» para el método de acceso «%s»" -#: catalog/objectaddress.c:3227 +#: catalog/objectaddress.c:3214 #, c-format msgid "access method %s" msgstr "método de acceso %s" @@ -5218,7 +5536,7 @@ msgstr "método de acceso %s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3276 +#: catalog/objectaddress.c:3269 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "operador %d (%s, %s) de %s: %s" @@ -5227,237 +5545,236 @@ msgstr "operador %d (%s, %s) de %s: %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3333 +#: catalog/objectaddress.c:3334 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "función %d (%s, %s) de %s: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3385 +#: catalog/objectaddress.c:3388 #, c-format msgid "rule %s on %s" msgstr "regla %s en %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3431 +#: catalog/objectaddress.c:3434 #, c-format msgid "trigger %s on %s" -msgstr "disparador %s en %s" +msgstr "“trigger” %s en %s" -#: catalog/objectaddress.c:3451 +#: catalog/objectaddress.c:3454 #, c-format msgid "schema %s" msgstr "esquema %s" -#: catalog/objectaddress.c:3479 +#: catalog/objectaddress.c:3482 #, c-format msgid "statistics object %s" msgstr "objeto de estadísticas %s" -#: catalog/objectaddress.c:3510 +#: catalog/objectaddress.c:3513 #, c-format msgid "text search parser %s" msgstr "analizador de búsqueda en texto %s" -#: catalog/objectaddress.c:3541 +#: catalog/objectaddress.c:3544 #, c-format msgid "text search dictionary %s" msgstr "diccionario de búsqueda en texto %s" -#: catalog/objectaddress.c:3572 +#: catalog/objectaddress.c:3575 #, c-format msgid "text search template %s" msgstr "plantilla de búsqueda en texto %s" -#: catalog/objectaddress.c:3603 +#: catalog/objectaddress.c:3606 #, c-format msgid "text search configuration %s" msgstr "configuración de búsqueda en texto %s" -#: catalog/objectaddress.c:3616 +#: catalog/objectaddress.c:3619 #, c-format msgid "role %s" msgstr "rol %s" -#: catalog/objectaddress.c:3653 catalog/objectaddress.c:5505 -#, fuzzy, c-format -#| msgid "removal of role \"%s\" failed: %s" +#: catalog/objectaddress.c:3656 catalog/objectaddress.c:5505 +#, c-format msgid "membership of role %s in role %s" -msgstr "falló la eliminación del rol «%s»: %s" +msgstr "membresía del rol %s en el rol %s" -#: catalog/objectaddress.c:3674 +#: catalog/objectaddress.c:3677 #, c-format msgid "database %s" msgstr "base de datos %s" -#: catalog/objectaddress.c:3690 +#: catalog/objectaddress.c:3693 #, c-format msgid "tablespace %s" msgstr "tablespace %s" -#: catalog/objectaddress.c:3701 +#: catalog/objectaddress.c:3704 #, c-format msgid "foreign-data wrapper %s" msgstr "conector de datos externos %s" -#: catalog/objectaddress.c:3711 +#: catalog/objectaddress.c:3714 #, c-format msgid "server %s" msgstr "servidor %s" -#: catalog/objectaddress.c:3744 +#: catalog/objectaddress.c:3747 #, c-format msgid "user mapping for %s on server %s" msgstr "mapeo para el usuario %s en el servidor %s" -#: catalog/objectaddress.c:3796 +#: catalog/objectaddress.c:3799 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "privilegios por omisión en nuevas relaciones pertenecientes al rol %s en el esquema %s" -#: catalog/objectaddress.c:3800 +#: catalog/objectaddress.c:3803 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "privilegios por omisión en nuevas relaciones pertenecientes al rol %s" -#: catalog/objectaddress.c:3806 +#: catalog/objectaddress.c:3809 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "privilegios por omisión en nuevas secuencias pertenecientes al rol %s en el esquema %s" -#: catalog/objectaddress.c:3810 +#: catalog/objectaddress.c:3813 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "privilegios por omisión en nuevas secuencias pertenecientes al rol %s" -#: catalog/objectaddress.c:3816 +#: catalog/objectaddress.c:3819 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "privilegios por omisión en nuevas funciones pertenecientes al rol %s en el esquema %s" -#: catalog/objectaddress.c:3820 +#: catalog/objectaddress.c:3823 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "privilegios por omisión en nuevas funciones pertenecientes al rol %s" -#: catalog/objectaddress.c:3826 +#: catalog/objectaddress.c:3829 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "privilegios por omisión en nuevos tipos pertenecientes al rol %s en el esquema %s" -#: catalog/objectaddress.c:3830 +#: catalog/objectaddress.c:3833 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "privilegios por omisión en nuevos tipos pertenecientes al rol %s" -#: catalog/objectaddress.c:3836 +#: catalog/objectaddress.c:3839 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "privilegios por omisión en nuevos esquemas pertenecientes al rol %s" -#: catalog/objectaddress.c:3843 +#: catalog/objectaddress.c:3846 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "privilegios por omisión pertenecientes al rol %s en el esquema %s" -#: catalog/objectaddress.c:3847 +#: catalog/objectaddress.c:3850 #, c-format msgid "default privileges belonging to role %s" msgstr "privilegios por omisión pertenecientes al rol %s" -#: catalog/objectaddress.c:3869 +#: catalog/objectaddress.c:3872 #, c-format msgid "extension %s" msgstr "extensión %s" -#: catalog/objectaddress.c:3886 +#: catalog/objectaddress.c:3889 #, c-format msgid "event trigger %s" -msgstr "disparador por eventos %s" +msgstr "“trigger” por eventos %s" -#: catalog/objectaddress.c:3910 +#: catalog/objectaddress.c:3913 #, c-format msgid "parameter %s" msgstr "parámetro %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3953 +#: catalog/objectaddress.c:3956 #, c-format msgid "policy %s on %s" msgstr "política %s en %s" -#: catalog/objectaddress.c:3967 +#: catalog/objectaddress.c:3970 #, c-format msgid "publication %s" msgstr "publicación %s" -#: catalog/objectaddress.c:3980 +#: catalog/objectaddress.c:3983 #, c-format msgid "publication of schema %s in publication %s" msgstr "publicación de esquema %s en la publicación %s" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:4011 +#: catalog/objectaddress.c:4014 #, c-format msgid "publication of %s in publication %s" msgstr "publicación de %s en la publicación %s" -#: catalog/objectaddress.c:4024 +#: catalog/objectaddress.c:4027 #, c-format msgid "subscription %s" msgstr "suscripción %s" -#: catalog/objectaddress.c:4045 +#: catalog/objectaddress.c:4048 #, c-format msgid "transform for %s language %s" msgstr "transformación para %s lenguaje %s" -#: catalog/objectaddress.c:4116 +#: catalog/objectaddress.c:4117 #, c-format msgid "table %s" msgstr "tabla %s" -#: catalog/objectaddress.c:4121 +#: catalog/objectaddress.c:4122 #, c-format msgid "index %s" msgstr "índice %s" -#: catalog/objectaddress.c:4125 +#: catalog/objectaddress.c:4126 #, c-format msgid "sequence %s" msgstr "secuencia %s" -#: catalog/objectaddress.c:4129 +#: catalog/objectaddress.c:4130 #, c-format msgid "toast table %s" msgstr "tabla toast %s" -#: catalog/objectaddress.c:4133 +#: catalog/objectaddress.c:4134 #, c-format msgid "view %s" msgstr "vista %s" -#: catalog/objectaddress.c:4137 +#: catalog/objectaddress.c:4138 #, c-format msgid "materialized view %s" msgstr "vista materializada %s" -#: catalog/objectaddress.c:4141 +#: catalog/objectaddress.c:4142 #, c-format msgid "composite type %s" msgstr "tipo compuesto %s" -#: catalog/objectaddress.c:4145 +#: catalog/objectaddress.c:4146 #, c-format msgid "foreign table %s" msgstr "tabla foránea %s" -#: catalog/objectaddress.c:4150 +#: catalog/objectaddress.c:4151 #, c-format msgid "relation %s" msgstr "relación %s" -#: catalog/objectaddress.c:4191 +#: catalog/objectaddress.c:4192 #, c-format msgid "operator family %s for access method %s" msgstr "familia de operadores %s para el método de acceso %s" @@ -5499,7 +5816,7 @@ msgstr "no se puede omitir el valor inicial cuando la función de transición es msgid "return type of inverse transition function %s is not %s" msgstr "el tipo de retorno de la función inversa de transición %s no es %s" -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3009 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2991 #, c-format msgid "strictness of aggregate's forward and inverse transition functions must match" msgstr "la opción «strict» de las funciones de transición directa e inversa deben coincidir exactamente en la función de agregación" @@ -5514,7 +5831,7 @@ msgstr "la función final con argumentos extra no debe declararse STRICT" msgid "return type of combine function %s is not %s" msgstr "el tipo de retorno de la función «combine» %s no es %s" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3903 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "la función «combine» con tipo de transición %s no debe declararse STRICT" @@ -5529,12 +5846,12 @@ msgstr "el tipo de retorno de la función de serialización %s no es %s" msgid "return type of deserialization function %s is not %s" msgstr "el tipo de retorno de la función de deserialización %s no es %s" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:191 catalog/pg_proc.c:225 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 #, c-format msgid "cannot determine result data type" msgstr "no se puede determinar el tipo de dato del resultado" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:204 catalog/pg_proc.c:233 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "uso inseguro de pseudotipo «internal»" @@ -5549,7 +5866,7 @@ msgstr "la implementación de la función de agregación en modo «moving» devu msgid "sort operator can only be specified for single-argument aggregates" msgstr "el operador de ordenamiento sólo puede ser especificado para funciones de agregación de un solo argumento" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:386 +#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 #, c-format msgid "cannot change routine kind" msgstr "no se puede cambiar el tipo de rutina" @@ -5574,13 +5891,13 @@ msgstr "«%s» es una agregación de conjunto hipotético." msgid "cannot change number of direct arguments of an aggregate function" msgstr "no se puede cambiar cantidad de argumentos directos de una función de agregación" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:691 -#: commands/typecmds.c:1975 commands/typecmds.c:2021 commands/typecmds.c:2073 -#: commands/typecmds.c:2110 commands/typecmds.c:2144 commands/typecmds.c:2178 -#: commands/typecmds.c:2212 commands/typecmds.c:2241 commands/typecmds.c:2328 -#: commands/typecmds.c:2370 parser/parse_func.c:417 parser/parse_func.c:448 +#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 +#: commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 +#: commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 +#: commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 +#: commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 #: parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 -#: parser/parse_func.c:631 parser/parse_func.c:2171 parser/parse_func.c:2444 +#: parser/parse_func.c:631 parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "no existe la función %s" @@ -5655,133 +5972,133 @@ msgstr "Esta operación no está soportada en tablas particionadas." msgid "This operation is not supported for partitioned indexes." msgstr "Esta operación no está soportada en índices particionados." -#: catalog/pg_collation.c:102 catalog/pg_collation.c:160 +#: catalog/pg_collation.c:101 catalog/pg_collation.c:159 #, c-format msgid "collation \"%s\" already exists, skipping" msgstr "el ordenamiento «%s» ya existe, omitiendo" -#: catalog/pg_collation.c:104 +#: catalog/pg_collation.c:103 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists, skipping" msgstr "el ordenamiento «%s» para la codificación «%s» ya existe, omitiendo" -#: catalog/pg_collation.c:112 catalog/pg_collation.c:167 +#: catalog/pg_collation.c:111 catalog/pg_collation.c:166 #, c-format msgid "collation \"%s\" already exists" msgstr "el ordenamiento «%s» ya existe" -#: catalog/pg_collation.c:114 +#: catalog/pg_collation.c:113 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "la codificación «%2$s» ya tiene un ordenamiento llamado «%1$s»" -#: catalog/pg_constraint.c:690 +#: catalog/pg_constraint.c:732 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "el dominio %2$s ya contiene una restricción llamada «%1$s»" -#: catalog/pg_constraint.c:890 catalog/pg_constraint.c:983 +#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "no existe la restricción «%s» para la tabla «%s»" -#: catalog/pg_constraint.c:1083 +#: catalog/pg_constraint.c:1125 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "no existe la restricción «%s» para el dominio %s" -#: catalog/pg_conversion.c:67 +#: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" msgstr "ya existe la conversión «%s»" -#: catalog/pg_conversion.c:80 +#: catalog/pg_conversion.c:77 #, c-format msgid "default conversion for %s to %s already exists" msgstr "ya existe una conversión por omisión desde %s a %s" -#: catalog/pg_depend.c:222 commands/extension.c:3344 +#: catalog/pg_depend.c:224 commands/extension.c:3397 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "«%s» ya es un miembro de la extensión «%s»" -#: catalog/pg_depend.c:229 catalog/pg_depend.c:280 commands/extension.c:3384 +#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "%s no es un miembro de la extensión «%s»" -#: catalog/pg_depend.c:232 +#: catalog/pg_depend.c:234 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "A una extensión no se le permite reemplazar un objeto que no posee." -#: catalog/pg_depend.c:283 +#: catalog/pg_depend.c:285 #, c-format msgid "An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns." msgstr "Una extensión sólo puede usar CREATE ... IF NOT EXISTS para omitir la creación de un objeto si el objeto en conflicto es uno de cual ya es dueña." -#: catalog/pg_depend.c:646 +#: catalog/pg_depend.c:648 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "no se puede eliminar dependencia a %s porque es un objeto requerido por el sistema" -#: catalog/pg_enum.c:137 catalog/pg_enum.c:259 catalog/pg_enum.c:554 +#: catalog/pg_enum.c:175 catalog/pg_enum.c:314 catalog/pg_enum.c:624 #, c-format msgid "invalid enum label \"%s\"" msgstr "la etiqueta enum «%s» no es válida" -#: catalog/pg_enum.c:138 catalog/pg_enum.c:260 catalog/pg_enum.c:555 +#: catalog/pg_enum.c:176 catalog/pg_enum.c:315 catalog/pg_enum.c:625 #, c-format msgid "Labels must be %d bytes or less." msgstr "Las etiquetas deben ser de %d bytes o menos." -#: catalog/pg_enum.c:288 +#: catalog/pg_enum.c:343 #, c-format msgid "enum label \"%s\" already exists, skipping" msgstr "la etiqueta de enum «%s» ya existe, omitiendo" -#: catalog/pg_enum.c:295 catalog/pg_enum.c:598 +#: catalog/pg_enum.c:350 catalog/pg_enum.c:668 #, c-format msgid "enum label \"%s\" already exists" msgstr "la etiqueta de enum «%s» ya existe" -#: catalog/pg_enum.c:350 catalog/pg_enum.c:593 +#: catalog/pg_enum.c:405 catalog/pg_enum.c:663 #, c-format msgid "\"%s\" is not an existing enum label" msgstr "«%s» no es una etiqueta de enum existente" -#: catalog/pg_enum.c:408 +#: catalog/pg_enum.c:463 #, c-format msgid "pg_enum OID value not set when in binary upgrade mode" msgstr "el valor de OID de pg_enum no se definió en modo de actualización binaria" -#: catalog/pg_enum.c:418 +#: catalog/pg_enum.c:473 #, c-format msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade" msgstr "ALTER TYPE ADD BEFORE/AFTER es incompatible con la actualización binaria" -#: catalog/pg_inherits.c:593 +#: catalog/pg_inherits.c:592 #, c-format msgid "cannot detach partition \"%s\"" msgstr "no se puede desprender la partición «%s»" -#: catalog/pg_inherits.c:595 +#: catalog/pg_inherits.c:594 #, c-format msgid "The partition is being detached concurrently or has an unfinished detach." msgstr "La partición está siendo desprendida de forma concurrente o tiene un desprendimiento sin terminar." -#: catalog/pg_inherits.c:596 commands/tablecmds.c:4583 -#: commands/tablecmds.c:15464 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4800 +#: commands/tablecmds.c:16153 #, c-format msgid "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation." msgstr "Utilice ALTER TABLE ... DETACH PARTITION ... FINALIZE para completar la operación de desprendimiento pendiente." -#: catalog/pg_inherits.c:600 +#: catalog/pg_inherits.c:599 #, c-format msgid "cannot complete detaching partition \"%s\"" msgstr "no se puede completar el desprendimiento de la partición «%s»" -#: catalog/pg_inherits.c:602 +#: catalog/pg_inherits.c:601 #, c-format msgid "There's no pending concurrent detach." msgstr "No hay desprendimientos concurrentes pendientes." @@ -5791,116 +6108,129 @@ msgstr "No hay desprendimientos concurrentes pendientes." msgid "schema \"%s\" already exists" msgstr "ya existe el esquema «%s»" -#: catalog/pg_operator.c:219 catalog/pg_operator.c:361 +#: catalog/pg_operator.c:213 catalog/pg_operator.c:355 #, c-format msgid "\"%s\" is not a valid operator name" msgstr "«%s» no es un nombre válido de operador" -#: catalog/pg_operator.c:370 +#: catalog/pg_operator.c:379 +#, c-format +msgid "operator %s already exists" +msgstr "ya existe un operador %s" + +#: catalog/pg_operator.c:445 commands/operatorcmds.c:600 +#, c-format +msgid "operator cannot be its own negator" +msgstr "un operador no puede ser su propio negador" + +#: catalog/pg_operator.c:572 #, c-format msgid "only binary operators can have commutators" msgstr "sólo los operadores binarios pueden tener conmutadores" -#: catalog/pg_operator.c:374 commands/operatorcmds.c:509 +#: catalog/pg_operator.c:576 #, c-format msgid "only binary operators can have join selectivity" msgstr "sólo los operadores binarios pueden tener selectividad de join" -#: catalog/pg_operator.c:378 +#: catalog/pg_operator.c:580 #, c-format msgid "only binary operators can merge join" msgstr "sólo los operadores binarios pueden ser usados en merge join" -#: catalog/pg_operator.c:382 +#: catalog/pg_operator.c:584 #, c-format msgid "only binary operators can hash" msgstr "sólo los operadores binarios pueden ser usados en hash" -#: catalog/pg_operator.c:393 +#: catalog/pg_operator.c:593 #, c-format msgid "only boolean operators can have negators" msgstr "sólo los operadores booleanos pueden tener negadores" -#: catalog/pg_operator.c:397 commands/operatorcmds.c:517 +#: catalog/pg_operator.c:597 #, c-format msgid "only boolean operators can have restriction selectivity" msgstr "sólo los operadores booleanos pueden tener selectividad de restricción" -#: catalog/pg_operator.c:401 commands/operatorcmds.c:521 +#: catalog/pg_operator.c:601 #, c-format msgid "only boolean operators can have join selectivity" msgstr "sólo los operadores booleanos pueden tener selectividad de join" -#: catalog/pg_operator.c:405 +#: catalog/pg_operator.c:605 #, c-format msgid "only boolean operators can merge join" msgstr "sólo los operadores booleanos pueden ser usados en merge join" -#: catalog/pg_operator.c:409 +#: catalog/pg_operator.c:609 #, c-format msgid "only boolean operators can hash" msgstr "sólo los operadores booleanos pueden ser usados en hash" -#: catalog/pg_operator.c:421 +#: catalog/pg_operator.c:739 #, c-format -msgid "operator %s already exists" -msgstr "ya existe un operador %s" +msgid "commutator operator %s is already the commutator of operator %s" +msgstr "el operator de conmutación %s ya es el conmutador del operador %s" -#: catalog/pg_operator.c:621 +#: catalog/pg_operator.c:744 #, c-format -msgid "operator cannot be its own negator or sort operator" -msgstr "un operador no puede ser su propio negador u operador de ordenamiento" +msgid "commutator operator %s is already the commutator of operator %u" +msgstr "el operator de conmutación %s ya es el conmutador del operador %u" -#: catalog/pg_parameter_acl.c:53 -#, fuzzy, c-format -#| msgid "parameter ACL with OID %u does not exist" -msgid "parameter ACL \"%s\" does not exist" -msgstr "no existe el ACL de parámetro con OID %u" +#: catalog/pg_operator.c:807 +#, c-format +msgid "negator operator %s is already the negator of operator %s" +msgstr "el operator de negación %s ya es el negador del operador %s" -#: catalog/pg_parameter_acl.c:88 -#, fuzzy, c-format -#| msgid "invalid type name \"%s\"" -msgid "invalid parameter name \"%s\"" -msgstr "el nombre de tipo «%s» no es válido" +#: catalog/pg_operator.c:812 +#, c-format +msgid "negator operator %s is already the negator of operator %u" +msgstr "el operator de negación %s ya es el negador del operador %u" + +#: catalog/pg_parameter_acl.c:50 +#, c-format +msgid "parameter ACL \"%s\" does not exist" +msgstr "no existe el ACL de parámetro «%s»" -#: catalog/pg_proc.c:132 parser/parse_func.c:2233 +#: catalog/pg_proc.c:130 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" msgstr[0] "las funciones no pueden tener más de %d argumento" msgstr[1] "las funciones no pueden tener más de %d argumentos" -#: catalog/pg_proc.c:376 +#: catalog/pg_proc.c:374 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "ya existe una función «%s» con los mismos argumentos" -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:386 #, c-format msgid "\"%s\" is an aggregate function." msgstr "«%s» es una función de agregación." -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:388 #, c-format msgid "\"%s\" is a function." msgstr "«%s» es una función de agregación." -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:390 #, c-format msgid "\"%s\" is a procedure." msgstr "«%s» es un índice parcial." -#: catalog/pg_proc.c:394 +#: catalog/pg_proc.c:392 #, c-format msgid "\"%s\" is a window function." msgstr "«%s» es una función de ventana deslizante." -#: catalog/pg_proc.c:414 +#: catalog/pg_proc.c:412 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "no se puede cambiar que un procedimiento tenga parámetros de salida" -#: catalog/pg_proc.c:415 catalog/pg_proc.c:445 +#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 #, c-format msgid "cannot change return type of existing function" msgstr "no se puede cambiar el tipo de retorno de una función existente" @@ -5909,120 +6239,114 @@ msgstr "no se puede cambiar el tipo de retorno de una función existente" #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:421 catalog/pg_proc.c:448 catalog/pg_proc.c:493 -#: catalog/pg_proc.c:519 catalog/pg_proc.c:543 +#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 +#: catalog/pg_proc.c:517 catalog/pg_proc.c:541 #, c-format msgid "Use %s %s first." msgstr "Use %s %s primero." -#: catalog/pg_proc.c:446 +#: catalog/pg_proc.c:444 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "Tipo de registro definido por parámetros OUT es diferente." -#: catalog/pg_proc.c:490 +#: catalog/pg_proc.c:488 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "no se puede cambiar el nombre del parámetro de entrada «%s»" -#: catalog/pg_proc.c:517 +#: catalog/pg_proc.c:515 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "no se puede eliminar el valor por omisión de funciones existentes" -#: catalog/pg_proc.c:541 +#: catalog/pg_proc.c:539 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "no se puede cambiar el tipo de dato del valor por omisión de un parámetro" -#: catalog/pg_proc.c:752 +#: catalog/pg_proc.c:750 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "no hay ninguna función interna llamada «%s»" -#: catalog/pg_proc.c:845 +#: catalog/pg_proc.c:843 #, c-format msgid "SQL functions cannot return type %s" msgstr "las funciones SQL no pueden retornar el tipo %s" -#: catalog/pg_proc.c:860 +#: catalog/pg_proc.c:858 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "las funciones SQL no pueden tener argumentos de tipo %s" -#: catalog/pg_proc.c:987 executor/functions.c:1466 +#: catalog/pg_proc.c:986 executor/functions.c:1468 #, c-format msgid "SQL function \"%s\"" msgstr "función SQL «%s»" -#: catalog/pg_publication.c:71 catalog/pg_publication.c:79 -#: catalog/pg_publication.c:87 catalog/pg_publication.c:93 +#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 +#: catalog/pg_publication.c:82 catalog/pg_publication.c:88 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "no se puede agregar la relación «%s» a la publicación" -#: catalog/pg_publication.c:81 +#: catalog/pg_publication.c:76 #, c-format msgid "This operation is not supported for system tables." msgstr "Esta operación no está soportada en tablas de sistema." -#: catalog/pg_publication.c:89 +#: catalog/pg_publication.c:84 #, c-format msgid "This operation is not supported for temporary tables." msgstr "Esta operación no está soportada en tablas temporales." -#: catalog/pg_publication.c:95 +#: catalog/pg_publication.c:90 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "Esta característica no está soportada en tablas «unlogged»." -#: catalog/pg_publication.c:109 catalog/pg_publication.c:117 +#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "no se puede agregar el esquema «%s» a la partición" -#: catalog/pg_publication.c:111 -#, fuzzy, c-format -#| msgid "This operation is not supported for system tables." +#: catalog/pg_publication.c:106 +#, c-format msgid "This operation is not supported for system schemas." -msgstr "Esta operación no está soportada en tablas de sistema." +msgstr "Esta operación no está soportada en esquemas de sistema." -#: catalog/pg_publication.c:119 -#, fuzzy, c-format -#| msgid "Unlogged relations cannot be replicated." +#: catalog/pg_publication.c:114 +#, c-format msgid "Temporary schemas cannot be replicated." -msgstr "Las tablas «unlogged» no pueden replicarse." +msgstr "Los esquemas temporales no pueden replicarse." -#: catalog/pg_publication.c:397 +#: catalog/pg_publication.c:392 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "la relación «%s» ya es un miembro de la publicación «%s»" -#: catalog/pg_publication.c:539 -#, fuzzy, c-format -#| msgid "cannot use system column \"%s\" in partition key" +#: catalog/pg_publication.c:534 +#, c-format msgid "cannot use system column \"%s\" in publication column list" -msgstr "no se puede usar la columna de sistema «%s» en llave de particionamiento" +msgstr "no se puede usar la columna de sistema «%s» en lista de columnas de publicación" -#: catalog/pg_publication.c:545 -#, fuzzy, c-format -#| msgid "cannot use generated column in partition key" +#: catalog/pg_publication.c:540 +#, c-format msgid "cannot use generated column \"%s\" in publication column list" -msgstr "no se puede usar una columna generada en llave de particionamiento" +msgstr "no se puede usar la columna generada «%s» en lista de columnas de publicación" -#: catalog/pg_publication.c:551 -#, fuzzy, c-format -#| msgid "publication of %s in publication %s" +#: catalog/pg_publication.c:546 +#, c-format msgid "duplicate column \"%s\" in publication column list" -msgstr "publicación de %s en la publicación %s" +msgstr "columna «%s» duplicada en lista de columnas de publicación" -#: catalog/pg_publication.c:641 -#, fuzzy, c-format -#| msgid "relation \"%s\" is already member of publication \"%s\"" +#: catalog/pg_publication.c:636 +#, c-format msgid "schema \"%s\" is already member of publication \"%s\"" -msgstr "la relación «%s» ya es un miembro de la publicación «%s»" +msgstr "el esquema «%s» ya es miembro de la publicación «%s»" -#: catalog/pg_shdepend.c:830 +#: catalog/pg_shdepend.c:875 #, c-format msgid "" "\n" @@ -6037,65 +6361,70 @@ msgstr[1] "" "\n" "y objetos en otras %d bases de datos (vea el registro del servidor para obtener la lista)" -#: catalog/pg_shdepend.c:1177 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "el rol %u fue eliminado por una transacción concurrente" -#: catalog/pg_shdepend.c:1189 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "el tablespace %u fue eliminado por una transacción concurrente" -#: catalog/pg_shdepend.c:1203 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "la base de datos %u fue eliminado por una transacción concurrente" -#: catalog/pg_shdepend.c:1254 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "dueño de %s" -#: catalog/pg_shdepend.c:1256 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" msgstr "privilegios para %s" -#: catalog/pg_shdepend.c:1258 +#: catalog/pg_shdepend.c:1303 +#, c-format +msgid "initial privileges for %s" +msgstr "privilegios iniciales para %s" + +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "destino de %s" -#: catalog/pg_shdepend.c:1260 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "tablespace para %s" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1268 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" msgstr[0] "%d objeto en %s" msgstr[1] "%d objetos en %s" -#: catalog/pg_shdepend.c:1332 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "cannot drop objects owned by %s because they are required by the database system" msgstr "no se puede eliminar objetos de propiedad de %s porque son requeridos por el sistema" -#: catalog/pg_shdepend.c:1498 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "cannot reassign ownership of objects owned by %s because they are required by the database system" msgstr "no se puede reasignar la propiedad de objetos de %s porque son requeridos por el sistema" -#: catalog/pg_subscription.c:424 +#: catalog/pg_subscription.c:438 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "no se pudo eliminar mapeo de relación para suscripción «%s»" -#: catalog/pg_subscription.c:426 +#: catalog/pg_subscription.c:440 #, c-format msgid "Table synchronization for relation \"%s\" is in progress and is in state \"%c\"." msgstr "La sincronización de tabla para la relación «%s» está en progreso y su estado es «%c»." @@ -6103,227 +6432,227 @@ msgstr "La sincronización de tabla para la relación «%s» está en progreso y #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:433 +#: catalog/pg_subscription.c:447 #, c-format msgid "Use %s to enable subscription if not already enabled or use %s to drop the subscription." msgstr "Utilice %s para activar la suscripción si aún no está activada, o utilice %s para eliminar la suscripción." -#: catalog/pg_type.c:134 catalog/pg_type.c:474 +#: catalog/pg_type.c:133 catalog/pg_type.c:474 #, c-format msgid "pg_type OID value not set when in binary upgrade mode" msgstr "el valor de OID de pg_type no se definió en modo de actualización binaria" -#: catalog/pg_type.c:254 +#: catalog/pg_type.c:253 #, c-format msgid "invalid type internal size %d" msgstr "el tamaño interno de tipo %d no es válido" -#: catalog/pg_type.c:270 catalog/pg_type.c:278 catalog/pg_type.c:286 -#: catalog/pg_type.c:295 +#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285 +#: catalog/pg_type.c:294 #, c-format msgid "alignment \"%c\" is invalid for passed-by-value type of size %d" msgstr "el alineamiento «%c» no es válido para un tipo pasado por valor de tamaño %d" -#: catalog/pg_type.c:302 +#: catalog/pg_type.c:301 #, c-format msgid "internal size %d is invalid for passed-by-value type" msgstr "el tamaño interno %d no es válido para un tipo pasado por valor" -#: catalog/pg_type.c:312 catalog/pg_type.c:318 +#: catalog/pg_type.c:311 catalog/pg_type.c:317 #, c-format msgid "alignment \"%c\" is invalid for variable-length type" msgstr "el alineamiento «%c» no es válido para un tipo de largo variable" -#: catalog/pg_type.c:326 commands/typecmds.c:4140 +#: catalog/pg_type.c:325 commands/typecmds.c:4363 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "los tipos de tamaño fijo deben tener almacenamiento PLAIN" -#: catalog/pg_type.c:955 +#: catalog/pg_type.c:978 #, c-format msgid "Failed while creating a multirange type for type \"%s\"." msgstr "Falla al crear un tipo de multirango para el tipo «%s»." -#: catalog/pg_type.c:956 +#: catalog/pg_type.c:979 #, c-format msgid "You can manually specify a multirange type name using the \"multirange_type_name\" attribute." msgstr "Puede especificar manualmente un nombre para el tipo de multirango usando el atributo «multirange_type_name»." -#: catalog/storage.c:505 storage/buffer/bufmgr.c:1145 +#: catalog/storage.c:533 storage/buffer/bufmgr.c:1540 #, c-format msgid "invalid page in block %u of relation %s" msgstr "la página no es válida en el bloque %u de la relación %s" -#: commands/aggregatecmds.c:171 +#: commands/aggregatecmds.c:167 #, c-format msgid "only ordered-set aggregates can be hypothetical" msgstr "sólo las funciones de agregación de conjuntos ordenados pueden ser hipotéticas" -#: commands/aggregatecmds.c:196 +#: commands/aggregatecmds.c:192 #, c-format msgid "aggregate attribute \"%s\" not recognized" msgstr "el atributo de la función de agregación «%s» no es reconocido" -#: commands/aggregatecmds.c:206 +#: commands/aggregatecmds.c:202 #, c-format msgid "aggregate stype must be specified" msgstr "debe especificarse el tipo de transición (stype) de la función de agregación" -#: commands/aggregatecmds.c:210 +#: commands/aggregatecmds.c:206 #, c-format msgid "aggregate sfunc must be specified" msgstr "debe especificarse la función de transición (sfunc) de la función de agregación" -#: commands/aggregatecmds.c:222 +#: commands/aggregatecmds.c:218 #, c-format msgid "aggregate msfunc must be specified when mstype is specified" msgstr "debe especificarse la función de transición msfunc cuando se especifica mstype" -#: commands/aggregatecmds.c:226 +#: commands/aggregatecmds.c:222 #, c-format msgid "aggregate minvfunc must be specified when mstype is specified" msgstr "debe especificarse la función de transición minvfunc cuando se especifica mstype" -#: commands/aggregatecmds.c:233 +#: commands/aggregatecmds.c:229 #, c-format msgid "aggregate msfunc must not be specified without mstype" msgstr "no debe especificarse msfunc sin mstype" -#: commands/aggregatecmds.c:237 +#: commands/aggregatecmds.c:233 #, c-format msgid "aggregate minvfunc must not be specified without mstype" msgstr "no debe especificarse minvfunc sin mstype" -#: commands/aggregatecmds.c:241 +#: commands/aggregatecmds.c:237 #, c-format msgid "aggregate mfinalfunc must not be specified without mstype" msgstr "no debe especificarse mfinalfunc sin mstype" -#: commands/aggregatecmds.c:245 +#: commands/aggregatecmds.c:241 #, c-format msgid "aggregate msspace must not be specified without mstype" msgstr "no debe especificarse msspace sin mstype" -#: commands/aggregatecmds.c:249 +#: commands/aggregatecmds.c:245 #, c-format msgid "aggregate minitcond must not be specified without mstype" msgstr "no debe especificarse minitcond sin mstype" -#: commands/aggregatecmds.c:278 +#: commands/aggregatecmds.c:274 #, c-format msgid "aggregate input type must be specified" msgstr "debe especificarse el tipo de entrada de la función de agregación" -#: commands/aggregatecmds.c:308 +#: commands/aggregatecmds.c:304 #, c-format msgid "basetype is redundant with aggregate input type specification" msgstr "el tipo base es redundante con el tipo de entrada en la función de agregación" -#: commands/aggregatecmds.c:351 commands/aggregatecmds.c:392 +#: commands/aggregatecmds.c:347 commands/aggregatecmds.c:388 #, c-format msgid "aggregate transition data type cannot be %s" msgstr "el tipo de transición de la función de agregación no puede ser %s" -#: commands/aggregatecmds.c:363 +#: commands/aggregatecmds.c:359 #, c-format msgid "serialization functions may be specified only when the aggregate transition data type is %s" msgstr "las funciones de serialización pueden especificarse sólo cuando el tipo de transición de la función de agregación es %s" -#: commands/aggregatecmds.c:373 +#: commands/aggregatecmds.c:369 #, c-format msgid "must specify both or neither of serialization and deserialization functions" msgstr "debe especificar ambas o ninguna de las funciones de serialización y deserialización" -#: commands/aggregatecmds.c:438 commands/functioncmds.c:639 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "el parámetro «parallel» debe ser SAFE, RESTRICTED o UNSAFE" -#: commands/aggregatecmds.c:494 +#: commands/aggregatecmds.c:490 #, c-format msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "el parámetro «%s» debe ser READ_ONLY, SHAREABLE o READ_WRITE" -#: commands/alter.c:86 commands/event_trigger.c:174 +#: commands/alter.c:83 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" -msgstr "el disparador por eventos «%s» ya existe" +msgstr "el “trigger” por eventos «%s» ya existe" -#: commands/alter.c:89 commands/foreigncmds.c:593 +#: commands/alter.c:86 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "el conector de datos externos «%s» ya existe" -#: commands/alter.c:92 commands/foreigncmds.c:884 +#: commands/alter.c:89 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "el servidor «%s» ya existe" -#: commands/alter.c:95 commands/proclang.c:133 +#: commands/alter.c:92 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "ya existe el lenguaje «%s»" -#: commands/alter.c:98 commands/publicationcmds.c:771 +#: commands/alter.c:95 commands/publicationcmds.c:764 #, c-format msgid "publication \"%s\" already exists" msgstr "la publicación «%s» ya existe" -#: commands/alter.c:101 commands/subscriptioncmds.c:657 +#: commands/alter.c:98 commands/subscriptioncmds.c:669 #, c-format msgid "subscription \"%s\" already exists" msgstr "la suscripción «%s» ya existe" -#: commands/alter.c:124 +#: commands/alter.c:121 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "ya existe una conversión llamada «%s» en el esquema «%s»" -#: commands/alter.c:128 +#: commands/alter.c:125 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "ya existe un objeto de estadísticas llamado «%s» en el esquema «%s»" -#: commands/alter.c:132 +#: commands/alter.c:129 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "el analizador de búsqueda en texto «%s» ya existe en el esquema «%s»" -#: commands/alter.c:136 +#: commands/alter.c:133 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "el diccionario de búsqueda en texto «%s» ya existe en el esquema «%s»" -#: commands/alter.c:140 +#: commands/alter.c:137 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "la plantilla de búsqueda en texto «%s» ya existe en el esquema «%s»" -#: commands/alter.c:144 +#: commands/alter.c:141 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "la configuración de búsqueda en texto «%s» ya existe en el esquema «%s»" -#: commands/alter.c:217 +#: commands/alter.c:214 #, c-format msgid "must be superuser to rename %s" msgstr "debe ser superusuario para cambiar el nombre de «%s»" -#: commands/alter.c:259 commands/subscriptioncmds.c:636 -#: commands/subscriptioncmds.c:1116 commands/subscriptioncmds.c:1198 -#: commands/subscriptioncmds.c:1830 +#: commands/alter.c:256 commands/subscriptioncmds.c:648 +#: commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 +#: commands/subscriptioncmds.c:1918 #, c-format msgid "password_required=false is superuser-only" -msgstr "" +msgstr "password_required=false es sólo para superusuario" -#: commands/alter.c:260 commands/subscriptioncmds.c:637 -#: commands/subscriptioncmds.c:1117 commands/subscriptioncmds.c:1199 -#: commands/subscriptioncmds.c:1831 +#: commands/alter.c:257 commands/subscriptioncmds.c:649 +#: commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 +#: commands/subscriptioncmds.c:1919 #, c-format msgid "Subscriptions with the password_required option set to false may only be created or modified by the superuser." -msgstr "" +msgstr "Las suscripciones con la opción password_required puesta en falso sólo pueden ser creadas o modificadas por el superusuario." -#: commands/alter.c:775 +#: commands/alter.c:735 #, c-format msgid "must be superuser to set schema of %s" msgstr "debe ser superusuario para definir el esquema de %s" @@ -6343,7 +6672,7 @@ msgstr "Debe ser superusuario para crear un método de acceso." msgid "access method \"%s\" already exists" msgstr "el método de acceso «%s» ya existe" -#: commands/amcmds.c:154 commands/indexcmds.c:217 commands/indexcmds.c:840 +#: commands/amcmds.c:154 commands/indexcmds.c:224 commands/indexcmds.c:850 #: commands/opclasscmds.c:375 commands/opclasscmds.c:833 #, c-format msgid "access method \"%s\" does not exist" @@ -6354,175 +6683,174 @@ msgstr "no existe el método de acceso «%s»" msgid "handler function is not specified" msgstr "no se ha especificado una función manejadora" -#: commands/amcmds.c:264 commands/event_trigger.c:183 -#: commands/foreigncmds.c:489 commands/proclang.c:80 commands/trigger.c:709 -#: parser/parse_clause.c:941 +#: commands/amcmds.c:264 commands/event_trigger.c:200 +#: commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 +#: parser/parse_clause.c:943 #, c-format msgid "function %s must return type %s" msgstr "la función %s debe retornar el tipo %s" -#: commands/analyze.c:227 +#: commands/analyze.c:217 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "omitiendo «%s»: no se puede analizar esta tabla foránea" -#: commands/analyze.c:244 +#: commands/analyze.c:234 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "omitiendo «%s»: no se pueden analizar objetos que no son tablas, ni tablas especiales de sistema" -#: commands/analyze.c:324 +#: commands/analyze.c:314 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "analizando la jerarquía de herencia «%s.%s»" -#: commands/analyze.c:329 +#: commands/analyze.c:319 #, c-format msgid "analyzing \"%s.%s\"" msgstr "analizando «%s.%s»" -#: commands/analyze.c:394 +#: commands/analyze.c:385 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "la columna «%s» aparece más de una vez en la relación «%s»" -#: commands/analyze.c:786 +#: commands/analyze.c:785 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "análisis automático de la tabla «%s.%s.%s»\n" -#: commands/analyze.c:1333 +#: commands/analyze.c:1300 #, c-format msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows" msgstr "«%s»: se procesaron %d de %u páginas, que contenían %.0f filas vigentes y %.0f filas no vigentes; %d filas en la muestra, %.0f total de filas estimadas" -#: commands/analyze.c:1417 +#: commands/analyze.c:1384 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables" msgstr "omitiendo el análisis del árbol de herencia «%s.%s» --- este árbol no contiene tablas hijas" -#: commands/analyze.c:1515 +#: commands/analyze.c:1482 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables" msgstr "omitiendo el análisis del árbol de herencia «%s.%s» --- este árbol no contiene tablas hijas analizables" -#: commands/async.c:646 +#: commands/async.c:612 #, c-format msgid "channel name cannot be empty" msgstr "el nombre de canal no puede ser vacío" -#: commands/async.c:652 +#: commands/async.c:618 #, c-format msgid "channel name too long" msgstr "el nombre de canal es demasiado largo" -#: commands/async.c:657 +#: commands/async.c:623 #, c-format msgid "payload string too long" msgstr "la cadena de carga es demasiado larga" -#: commands/async.c:876 +#: commands/async.c:842 #, c-format msgid "cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY" msgstr "no se puede hacer PREPARE de una transacción que ha ejecutado LISTEN, UNLISTEN o NOTIFY" -#: commands/async.c:980 +#: commands/async.c:946 #, c-format msgid "too many notifications in the NOTIFY queue" msgstr "demasiadas notificaciones en la cola NOTIFY" -#: commands/async.c:1602 +#: commands/async.c:1553 #, c-format msgid "NOTIFY queue is %.0f%% full" msgstr "la cola NOTIFY está %.0f%% llena" -#: commands/async.c:1604 +#: commands/async.c:1555 #, c-format msgid "The server process with PID %d is among those with the oldest transactions." msgstr "El proceso servidor con PID %d está entre aquellos con transacciones más antiguas." -#: commands/async.c:1607 +#: commands/async.c:1558 #, c-format msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction." msgstr "La cola NOTIFY no puede vaciarse hasta que ese proceso cierre su transacción actual." -#: commands/cluster.c:131 +#: commands/cluster.c:128 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "opción de CLUSTER «%s» no reconocida" -#: commands/cluster.c:162 commands/cluster.c:435 +#: commands/cluster.c:159 commands/cluster.c:433 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "no se pueden reordenar tablas temporales de otras sesiones" -#: commands/cluster.c:180 +#: commands/cluster.c:177 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "no hay un índice de ordenamiento definido para la tabla «%s»" -#: commands/cluster.c:194 commands/tablecmds.c:14200 commands/tablecmds.c:16043 +#: commands/cluster.c:191 commands/tablecmds.c:14797 commands/tablecmds.c:16729 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "no existe el índice «%s» en la tabla «%s»" -#: commands/cluster.c:424 +#: commands/cluster.c:422 #, c-format msgid "cannot cluster a shared catalog" msgstr "no se puede reordenar un catálogo compartido" -#: commands/cluster.c:439 +#: commands/cluster.c:437 #, c-format msgid "cannot vacuum temporary tables of other sessions" msgstr "no se puede hacer vacuum a tablas temporales de otras sesiones" -#: commands/cluster.c:515 commands/tablecmds.c:16053 +#: commands/cluster.c:513 commands/tablecmds.c:16739 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "«%s» no es un índice de la tabla «%s»" -#: commands/cluster.c:523 +#: commands/cluster.c:521 #, c-format msgid "cannot cluster on index \"%s\" because access method does not support clustering" msgstr "no se puede reordenar en índice «%s» porque el método de acceso no soporta reordenamiento" -#: commands/cluster.c:535 +#: commands/cluster.c:533 #, c-format msgid "cannot cluster on partial index \"%s\"" msgstr "no se puede reordenar en índice parcial «%s»" -#: commands/cluster.c:549 +#: commands/cluster.c:547 #, c-format msgid "cannot cluster on invalid index \"%s\"" msgstr "no se puede reordenar en el índice no válido «%s»" -#: commands/cluster.c:573 +#: commands/cluster.c:571 #, c-format msgid "cannot mark index clustered in partitioned table" msgstr "no se puede marcar un índice «clustered» en una tabla particionada" -#: commands/cluster.c:952 +#: commands/cluster.c:956 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr "reordenando «%s.%s» usando un recorrido de índice en «%s»" -#: commands/cluster.c:958 +#: commands/cluster.c:962 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "reordenando «%s.%s» usando un recorrido secuencial y ordenamiento" -#: commands/cluster.c:963 +#: commands/cluster.c:967 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "haciendo vacuum a «%s.%s»" -#: commands/cluster.c:990 -#, fuzzy, c-format -#| msgid "index \"%s\" now contains %.0f row versions in %u pages" +#: commands/cluster.c:994 +#, c-format msgid "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" -msgstr "el índice «%s» ahora contiene %.0f versiones de filas en %u páginas" +msgstr "«%s.%s»: se encontraron %.0f versiones de filas eliminables, %.0f no eliminables en %u páginas" -#: commands/cluster.c:995 +#: commands/cluster.c:999 #, c-format msgid "" "%.0f dead row versions cannot be removed yet.\n" @@ -6531,40 +6859,39 @@ msgstr "" "%.0f versiones muertas de filas no pueden ser eliminadas aún.\n" "%s." -#: commands/cluster.c:1728 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/cluster.c:1744 +#, c-format msgid "permission denied to cluster \"%s\", skipping it" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "permiso denegado a hacer cluster a «%s», ignorando" -#: commands/collationcmds.c:112 +#: commands/collationcmds.c:110 #, c-format msgid "collation attribute \"%s\" not recognized" msgstr "el atributo de ordenamiento (collation) «%s» no es reconocido" -#: commands/collationcmds.c:125 commands/collationcmds.c:131 -#: commands/define.c:389 commands/tablecmds.c:7876 -#: replication/pgoutput/pgoutput.c:310 replication/pgoutput/pgoutput.c:333 -#: replication/pgoutput/pgoutput.c:347 replication/pgoutput/pgoutput.c:357 -#: replication/pgoutput/pgoutput.c:367 replication/pgoutput/pgoutput.c:377 -#: replication/pgoutput/pgoutput.c:387 replication/walsender.c:996 -#: replication/walsender.c:1018 replication/walsender.c:1028 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 +#: commands/define.c:388 commands/tablecmds.c:8129 +#: replication/pgoutput/pgoutput.c:314 replication/pgoutput/pgoutput.c:337 +#: replication/pgoutput/pgoutput.c:351 replication/pgoutput/pgoutput.c:361 +#: replication/pgoutput/pgoutput.c:371 replication/pgoutput/pgoutput.c:381 +#: replication/pgoutput/pgoutput.c:393 replication/walsender.c:1146 +#: replication/walsender.c:1168 replication/walsender.c:1178 +#: replication/walsender.c:1187 replication/walsender.c:1426 #, c-format msgid "conflicting or redundant options" msgstr "opciones contradictorias o redundantes" -#: commands/collationcmds.c:126 +#: commands/collationcmds.c:124 #, c-format msgid "LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE." msgstr "LOCALE no puede configurarse junto con LC_COLLATE o LC_CTYPE." -#: commands/collationcmds.c:132 -#, fuzzy, c-format -#| msgid "option \"%s\" cannot be specified with other options" +#: commands/collationcmds.c:130 +#, c-format msgid "FROM cannot be specified together with any other options." -msgstr "la opción «%s» no puede ser especificada con otras opciones" +msgstr "FROM no puede especificarse junto con otras opciones." -#: commands/collationcmds.c:191 +#: commands/collationcmds.c:189 #, c-format msgid "collation \"default\" cannot be copied" msgstr "el ordenamiento «default» no puede copiarse" @@ -6574,435 +6901,364 @@ msgstr "el ordenamiento «default» no puede copiarse" msgid "unrecognized collation provider: %s" msgstr "proveedor de ordenamiento no reconocido: %s" -#: commands/collationcmds.c:253 +#: commands/collationcmds.c:253 commands/collationcmds.c:264 +#: commands/collationcmds.c:270 commands/collationcmds.c:278 #, c-format -msgid "parameter \"lc_collate\" must be specified" -msgstr "debe especificarse el parámetro «lc_collate»" +msgid "parameter \"%s\" must be specified" +msgstr "el parámetro «%s» debe especificarse" -#: commands/collationcmds.c:258 +#: commands/collationcmds.c:293 commands/dbcommands.c:1134 #, c-format -msgid "parameter \"lc_ctype\" must be specified" -msgstr "debe especificarse el parámetro «lc_ctype»" - -#: commands/collationcmds.c:265 -#, fuzzy, c-format -#| msgid "parameter \"lc_collate\" must be specified" -msgid "parameter \"locale\" must be specified" -msgstr "debe especificarse el parámetro «lc_collate»" - -#: commands/collationcmds.c:279 commands/dbcommands.c:1074 -#, fuzzy, c-format -#| msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" -msgid "using standard form \"%s\" for locale \"%s\"" -msgstr "Usando la marca de lenguaje «%s» para la configuración regional ICU «%s».\n" +msgid "using standard form \"%s\" for ICU locale \"%s\"" +msgstr "usando la forma estándar «%s» para la configuración regional ICU «%s»" -#: commands/collationcmds.c:298 +#: commands/collationcmds.c:312 #, c-format msgid "nondeterministic collations not supported with this provider" msgstr "los ordenamientos no determinísticos no están soportados con este proveedor" -#: commands/collationcmds.c:303 commands/dbcommands.c:1093 -#, fuzzy, c-format -#| msgid "ICU locale cannot be specified unless locale provider is ICU" +#: commands/collationcmds.c:317 commands/dbcommands.c:1087 +#, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" -msgstr "no se puede especificar una configuración regional ICU a menos que el proveedor de configuración regional sea ICU" +msgstr "no se pueden especificar reglas ICU a menos que el proveedor de configuración regional sea ICU" -#: commands/collationcmds.c:322 +#: commands/collationcmds.c:340 #, c-format msgid "current database's encoding is not supported with this provider" msgstr "la codificación de la base de datos actual no está soportada con este proveedor" -#: commands/collationcmds.c:382 +#: commands/collationcmds.c:409 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "ya existe un ordenamiento (collation) llamado «%s» para la codificación «%s» en el esquema «%s»" -#: commands/collationcmds.c:393 +#: commands/collationcmds.c:420 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "ya existe un ordenamiento llamado «%s» en el esquema «%s»" -#: commands/collationcmds.c:418 -#, fuzzy, c-format -#| msgid "change the definition of a collation" +#: commands/collationcmds.c:445 +#, c-format msgid "cannot refresh version of default collation" -msgstr "cambia la definición de un ordenamiento" +msgstr "no se puede refrescar la versión del ordenamiento por omisión" -#: commands/collationcmds.c:419 -#, fuzzy, c-format -#| msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION instead." -msgid "Use ALTER DATABASE ... REFRESH COLLATION VERSION instead." -msgstr "Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION en su lugar." +#. translator: %s is an SQL command +#. translator: %s is an SQL ALTER command +#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 +#: commands/tablecmds.c:7905 commands/tablecmds.c:7915 +#: commands/tablecmds.c:7917 commands/tablecmds.c:14499 +#: commands/tablecmds.c:17884 commands/tablecmds.c:17905 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 +#, c-format +msgid "Use %s instead." +msgstr "Use %s en su lugar." -#: commands/collationcmds.c:446 commands/dbcommands.c:2447 +#: commands/collationcmds.c:480 commands/dbcommands.c:2566 #, c-format msgid "changing version from %s to %s" msgstr "cambiando versión de %s a %s" -#: commands/collationcmds.c:461 commands/dbcommands.c:2460 +#: commands/collationcmds.c:495 commands/dbcommands.c:2579 #, c-format msgid "version has not changed" msgstr "la versión no ha cambiado" -#: commands/collationcmds.c:494 commands/dbcommands.c:2626 +#: commands/collationcmds.c:528 commands/dbcommands.c:2749 #, c-format msgid "database with OID %u does not exist" msgstr "no existe la base de datos con OID %u" -#: commands/collationcmds.c:515 +#: commands/collationcmds.c:554 #, c-format msgid "collation with OID %u does not exist" msgstr "no existe el ordenamiento (collation) con OID %u" -#: commands/collationcmds.c:803 +#: commands/collationcmds.c:848 #, c-format msgid "must be superuser to import system collations" msgstr "debe ser superusuario para importar ordenamientos del sistema" -#: commands/collationcmds.c:831 commands/copyfrom.c:1653 commands/copyto.c:656 -#: libpq/be-secure-common.c:59 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "no se pudo ejecutar la orden «%s»: %m" - -#: commands/collationcmds.c:923 commands/collationcmds.c:1008 +#: commands/collationcmds.c:968 commands/collationcmds.c:1053 #, c-format msgid "no usable system locales were found" msgstr "no se encontraron locales de sistema utilizables" -#: commands/comment.c:61 commands/dbcommands.c:1594 commands/dbcommands.c:1791 -#: commands/dbcommands.c:1901 commands/dbcommands.c:2099 -#: commands/dbcommands.c:2337 commands/dbcommands.c:2420 -#: commands/dbcommands.c:2530 commands/dbcommands.c:3030 -#: utils/init/postinit.c:1025 utils/init/postinit.c:1130 -#: utils/init/postinit.c:1147 +#: commands/comment.c:61 commands/dbcommands.c:1665 commands/dbcommands.c:1883 +#: commands/dbcommands.c:1995 commands/dbcommands.c:2193 +#: commands/dbcommands.c:2433 commands/dbcommands.c:2526 +#: commands/dbcommands.c:2650 commands/dbcommands.c:3161 +#: utils/init/postinit.c:1034 utils/init/postinit.c:1098 +#: utils/init/postinit.c:1171 #, c-format msgid "database \"%s\" does not exist" msgstr "no existe la base de datos «%s»" #: commands/comment.c:101 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#, c-format msgid "cannot set comment on relation \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "no se puede definir comentario en la relación «%s»" -#: commands/constraint.c:63 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "la función «%s» no fue ejecutada por el manejador de triggers" -#: commands/constraint.c:70 utils/adt/ri_triggers.c:2037 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "la función «%s» debe ser ejecutada AFTER ROW" -#: commands/constraint.c:84 +#: commands/constraint.c:82 #, c-format msgid "function \"%s\" must be fired for INSERT or UPDATE" msgstr "la función «%s» debe ser ejecutada en INSERT o UPDATE" -#: commands/conversioncmds.c:69 +#: commands/conversioncmds.c:62 #, c-format msgid "source encoding \"%s\" does not exist" msgstr "no existe la codificación fuente «%s»" -#: commands/conversioncmds.c:76 +#: commands/conversioncmds.c:69 #, c-format msgid "destination encoding \"%s\" does not exist" msgstr "no existe la codificación de destino «%s»" -#: commands/conversioncmds.c:89 +#: commands/conversioncmds.c:82 #, c-format msgid "encoding conversion to or from \"SQL_ASCII\" is not supported" msgstr "la conversión de codificación desde o hacia a «SQL_ASCII» no está soportada" -#: commands/conversioncmds.c:102 +#: commands/conversioncmds.c:95 #, c-format msgid "encoding conversion function %s must return type %s" msgstr "la función de conversión de codificación %s debe retornar tipo %s" -#: commands/conversioncmds.c:132 +#: commands/conversioncmds.c:125 #, c-format msgid "encoding conversion function %s returned incorrect result for empty input" msgstr "la función de conversión de codificación %s retornó un resultado incorrecto para una entrada vacía" -#: commands/copy.c:86 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: commands/copy.c:84 +#, c-format msgid "permission denied to COPY to or from an external program" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para hacer COPY hacia o desde un programa externo" -#: commands/copy.c:87 +#: commands/copy.c:85 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to or from an external program." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden hacer COPY desde o hacia un programa externo." -#: commands/copy.c:89 commands/copy.c:100 commands/copy.c:109 +#: commands/copy.c:87 commands/copy.c:98 commands/copy.c:107 #, c-format msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone." msgstr "Cualquier usuario puede usar COPY hacia la salida estándar o desde la entrada estándar. La orden \\copy de psql también puede ser utilizado por cualquier usuario." -#: commands/copy.c:97 -#, fuzzy, c-format -#| msgid "permission denied to drop role" +#: commands/copy.c:95 +#, c-format msgid "permission denied to COPY from a file" -msgstr "se ha denegado el permiso para eliminar el rol" +msgstr "se ha denegado el permiso para hacer COPY desde un archivo" -#: commands/copy.c:98 +#: commands/copy.c:96 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY from a file." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden hacer COPY desde un archivo." -#: commands/copy.c:106 -#, fuzzy, c-format -#| msgid "permission denied to drop role" +#: commands/copy.c:104 +#, c-format msgid "permission denied to COPY to a file" -msgstr "se ha denegado el permiso para eliminar el rol" +msgstr "se ha denegado el permiso para hacer COPY a un archivo" -#: commands/copy.c:107 +#: commands/copy.c:105 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to a file." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden hacer COPY hacia un archivo." -#: commands/copy.c:195 +#: commands/copy.c:193 #, c-format msgid "COPY FROM not supported with row-level security" msgstr "COPY FROM no está soportado con seguridad a nivel de registros" -#: commands/copy.c:196 +#: commands/copy.c:194 #, c-format msgid "Use INSERT statements instead." msgstr "Use sentencias INSERT en su lugar." -#: commands/copy.c:290 -#, fuzzy, c-format -#| msgid "\"EEEE\" not supported for input" -msgid "MERGE not supported in COPY" -msgstr "«EEEE» no está soportado en la entrada" - -#: commands/copy.c:383 +#: commands/copy.c:375 #, c-format msgid "cannot use \"%s\" with HEADER in COPY TO" msgstr "no se puede usar «%s» con HEADER en COPY TO" -#: commands/copy.c:392 -#, fuzzy, c-format -#| msgid "%s requires a Boolean value" +#: commands/copy.c:384 +#, c-format msgid "%s requires a Boolean value or \"match\"" -msgstr "«%s» requiere un valor lógico (booleano)" +msgstr "«%s» requiere un valor lógico (booleano) o «match»" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:782 commands/copy.c:798 +#: commands/copy.c:815 commands/copy.c:841 commands/copy.c:851 +#, c-format +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s no puede usarse con %s" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:441 +#, c-format +msgid "COPY %s \"%s\" not recognized" +msgstr "no se reconoce el valor «%2$s» para COPY %1$s" -#: commands/copy.c:451 +#: commands/copy.c:502 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "el formato de COPY «%s» no es reconocido" -#: commands/copy.c:509 commands/copy.c:522 commands/copy.c:535 -#: commands/copy.c:554 +#: commands/copy.c:560 commands/copy.c:575 commands/copy.c:590 +#: commands/copy.c:609 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "el argumento de la opción «%s» debe ser una lista de nombres de columna" -#: commands/copy.c:566 +#: commands/copy.c:621 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "el argumento de la opción «%s» debe ser un nombre válido de codificación" -#: commands/copy.c:573 commands/dbcommands.c:859 commands/dbcommands.c:2285 +#: commands/copy.c:642 commands/dbcommands.c:866 commands/dbcommands.c:2381 #, c-format msgid "option \"%s\" not recognized" msgstr "no se reconoce la opción «%s»" -#: commands/copy.c:585 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:655 commands/copy.c:660 commands/copy.c:665 +#: commands/copy.c:740 #, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "no se puede especificar DELIMITER en modo BINARY" +msgid "cannot specify %s in BINARY mode" +msgstr "no se puede especificar %s en modo BINARY" -#: commands/copy.c:590 +#: commands/copy.c:670 #, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "no se puede especificar NULL en modo BINARY" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "sólo ON ERROR STOP es permitido en modo BINARY" -#: commands/copy.c:595 -#, fuzzy, c-format -#| msgid "cannot specify NULL in BINARY mode" -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "no se puede especificar NULL en modo BINARY" - -#: commands/copy.c:617 +#: commands/copy.c:692 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "el delimitador de COPY debe ser un solo carácter de un byte" -#: commands/copy.c:624 +#: commands/copy.c:699 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "el delimitador de COPY no puede ser el carácter de nueva línea ni el de retorno de carro" -#: commands/copy.c:630 +#: commands/copy.c:705 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "la representación de null de COPY no puede usar el carácter de nueva línea ni el de retorno de carro" -#: commands/copy.c:640 -#, fuzzy, c-format -#| msgid "COPY null representation cannot use newline or carriage return" +#: commands/copy.c:715 +#, c-format msgid "COPY default representation cannot use newline or carriage return" -msgstr "la representación de null de COPY no puede usar el carácter de nueva línea ni el de retorno de carro" +msgstr "la representación de default de COPY no puede usar el carácter de nueva línea ni el de retorno de carro" -#: commands/copy.c:658 +#: commands/copy.c:733 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "el delimitador de COPY no puede ser «%s»" -#: commands/copy.c:664 -#, fuzzy, c-format -#| msgid "cannot specify DELIMITER in BINARY mode" -msgid "cannot specify HEADER in BINARY mode" -msgstr "no se puede especificar DELIMITER en modo BINARY" - -#: commands/copy.c:670 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:747 commands/copy.c:764 commands/copy.c:776 +#: commands/copy.c:791 commands/copy.c:807 #, c-format -msgid "COPY quote available only in CSV mode" -msgstr "el «quote» de COPY está disponible sólo en modo CSV" +msgid "COPY %s requires CSV mode" +msgstr "COPY %s requiere modo CSV" -#: commands/copy.c:675 +#: commands/copy.c:752 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "la comilla («quote») de COPY debe ser un solo carácter de un byte" -#: commands/copy.c:680 +#: commands/copy.c:757 #, c-format msgid "COPY delimiter and quote must be different" msgstr "el delimitador de COPY y la comilla («quote») deben ser diferentes" -#: commands/copy.c:686 -#, c-format -msgid "COPY escape available only in CSV mode" -msgstr "escape de COPY disponible sólo en modo CSV" - -#: commands/copy.c:691 +#: commands/copy.c:769 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "el escape de COPY debe ser un sólo carácter de un byte" -#: commands/copy.c:697 -#, c-format -msgid "COPY force quote available only in CSV mode" -msgstr "el forzado de comillas de COPY sólo está disponible en modo CSV" - -#: commands/copy.c:701 -#, c-format -msgid "COPY force quote only available using COPY TO" -msgstr "el forzado de comillas de COPY sólo está disponible en COPY TO" - -#: commands/copy.c:707 -#, c-format -msgid "COPY force not null available only in CSV mode" -msgstr "el forzado de no nulos en COPY sólo está disponible en modo CSV" - -#: commands/copy.c:711 -#, c-format -msgid "COPY force not null only available using COPY FROM" -msgstr "el forzado de no nulos en COPY sólo está disponible usando COPY FROM" - -#: commands/copy.c:717 -#, c-format -msgid "COPY force null available only in CSV mode" -msgstr "el forzado de nulos en COPY sólo está disponible en modo CSV" - -#: commands/copy.c:722 -#, c-format -msgid "COPY force null only available using COPY FROM" -msgstr "el forzado de nulos en COPY sólo está disponible usando COPY FROM" - -#: commands/copy.c:728 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:823 commands/copy.c:859 #, c-format -msgid "COPY delimiter must not appear in the NULL specification" -msgstr "el delimitador de COPY no debe aparecer en la especificación NULL" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "el carácter delimitador de COPY no debe aparecer en la especificación %s" -#: commands/copy.c:735 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:832 commands/copy.c:868 #, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "el carácter de «quote» de CSV no debe aparecer en la especificación NULL" - -#: commands/copy.c:742 -#, fuzzy, c-format -#| msgid "COPY force null only available using COPY FROM" -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "el forzado de nulos en COPY sólo está disponible usando COPY FROM" +msgid "CSV quote character must not appear in the %s specification" +msgstr "el carácter de «quote» de CSV no debe aparecer en la especificación %s" -#: commands/copy.c:748 -#, fuzzy, c-format -#| msgid "COPY delimiter must not appear in the NULL specification" -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "el delimitador de COPY no debe aparecer en la especificación NULL" - -#: commands/copy.c:755 -#, fuzzy, c-format -#| msgid "CSV quote character must not appear in the NULL specification" -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "el carácter de «quote» de CSV no debe aparecer en la especificación NULL" - -#: commands/copy.c:763 +#: commands/copy.c:877 #, c-format msgid "NULL specification and DEFAULT specification cannot be the same" -msgstr "" +msgstr "las especificaciones NULL y DEFAULT no pueden ser la misma" -#: commands/copy.c:825 +#: commands/copy.c:939 #, c-format msgid "column \"%s\" is a generated column" msgstr "la columna «%s» es una columna generada" -#: commands/copy.c:827 +#: commands/copy.c:941 #, c-format msgid "Generated columns cannot be used in COPY." msgstr "Las columnas generadas no pueden usarse en COPY." -#: commands/copy.c:842 commands/indexcmds.c:1894 commands/statscmds.c:242 -#: commands/tablecmds.c:2405 commands/tablecmds.c:3127 -#: commands/tablecmds.c:3626 parser/parse_relation.c:3688 -#: parser/parse_relation.c:3698 parser/parse_relation.c:3716 -#: parser/parse_relation.c:3723 parser/parse_relation.c:3737 -#: utils/adt/tsvector_op.c:2855 +#: commands/copy.c:956 commands/indexcmds.c:1890 commands/statscmds.c:239 +#: commands/tablecmds.c:2526 commands/tablecmds.c:2997 +#: commands/tablecmds.c:3808 parser/parse_relation.c:3692 +#: parser/parse_relation.c:3702 parser/parse_relation.c:3720 +#: parser/parse_relation.c:3727 parser/parse_relation.c:3741 +#: utils/adt/tsvector_op.c:2853 #, c-format msgid "column \"%s\" does not exist" msgstr "no existe la columna «%s»" -#: commands/copy.c:849 commands/tablecmds.c:2431 commands/trigger.c:958 -#: parser/parse_target.c:1070 parser/parse_target.c:1081 +#: commands/copy.c:963 commands/tablecmds.c:2552 commands/trigger.c:951 +#: parser/parse_target.c:1083 parser/parse_target.c:1094 #, c-format msgid "column \"%s\" specified more than once" msgstr "la columna «%s» fue especificada más de una vez" -#: commands/copyfrom.c:122 +#: commands/copyfrom.c:118 #, c-format msgid "COPY %s" -msgstr "" +msgstr "COPY %s" -#: commands/copyfrom.c:130 +#: commands/copyfrom.c:126 #, c-format msgid "COPY %s, line %llu, column %s" -msgstr "" +msgstr "COPY %s, línea %llu, columna %s" -#: commands/copyfrom.c:135 commands/copyfrom.c:181 +#: commands/copyfrom.c:131 commands/copyfrom.c:177 #, c-format msgid "COPY %s, line %llu" -msgstr "" +msgstr "COPY %s, línea %llu" -#: commands/copyfrom.c:147 +#: commands/copyfrom.c:143 #, c-format msgid "COPY %s, line %llu, column %s: \"%s\"" -msgstr "" +msgstr "COPY %s, línea %llu, columna %s: «%s»" -#: commands/copyfrom.c:157 +#: commands/copyfrom.c:153 #, c-format msgid "COPY %s, line %llu, column %s: null input" -msgstr "" +msgstr "COPY %s, línea %llu, columna %s: entrada nula" -#: commands/copyfrom.c:174 +#: commands/copyfrom.c:170 #, c-format msgid "COPY %s, line %llu: \"%s\"" -msgstr "" +msgstr "COPY %s, línea %llu: «%s»" #: commands/copyfrom.c:673 #, c-format @@ -7012,7 +7268,7 @@ msgstr "no se puede copiar hacia la vista «%s»" #: commands/copyfrom.c:675 #, c-format msgid "To enable copying to a view, provide an INSTEAD OF INSERT trigger." -msgstr "Para posibilitar «copy» a una vista, provea un disparador INSTEAD OF INSERT." +msgstr "Para posibilitar «copy» a una vista, provea un “trigger” INSTEAD OF INSERT." #: commands/copyfrom.c:679 #, c-format @@ -7044,32 +7300,41 @@ msgstr "no se puede ejecutar COPY FREEZE debido a actividad anterior en la trans msgid "cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction" msgstr "no se puede ejecutar COPY FREEZE porque la tabla no fue creada ni truncada en la subtransacción en curso" -#: commands/copyfrom.c:1411 +#: commands/copyfrom.c:1313 +#, c-format +msgid "%llu row was skipped due to data type incompatibility" +msgid_plural "%llu rows were skipped due to data type incompatibility" +msgstr[0] "%llu fila fue ignorada por incompatibilidad de tipo de dato" +msgstr[1] "%llu filas fueron ignoradas por incompatibilidad de tipo de dato" + +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1448 commands/copyfrom.c:1491 commands/copyto.c:601 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "la columna FORCE_NOT_NULL «%s» no es referenciada en COPY" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "la columna %s «%s» no es referenciada en COPY" -#: commands/copyfrom.c:1434 +#: commands/copyfrom.c:1544 utils/mb/mbutils.c:385 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "la columna FORCE_NULL «%s» no es referenciada en COPY" +msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" +msgstr "no existe el procedimiento por omisión de conversión desde la codificación «%s» a «%s»" -#: commands/copyfrom.c:1672 +#: commands/copyfrom.c:1742 #, c-format msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY FROM indica al proceso servidor de PostgreSQL leer un archivo. Puede desear usar una facilidad del lado del cliente como \\copy de psql." -#: commands/copyfrom.c:1685 commands/copyto.c:708 +#: commands/copyfrom.c:1755 commands/copyto.c:706 #, c-format msgid "\"%s\" is a directory" msgstr "«%s» es un directorio" -#: commands/copyfrom.c:1753 commands/copyto.c:306 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1823 commands/copyto.c:299 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "no se pudo cerrar la tubería a la orden externa: %m" -#: commands/copyfrom.c:1768 commands/copyto.c:311 +#: commands/copyfrom.c:1838 commands/copyto.c:304 #, c-format msgid "program \"%s\" failed" msgstr "el programa «%s» falló" @@ -7110,26 +7375,25 @@ msgid "could not read from COPY file: %m" msgstr "no se pudo leer desde archivo COPY: %m" #: commands/copyfromparse.c:278 commands/copyfromparse.c:303 -#: tcop/postgres.c:377 +#: replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:381 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "se encontró fin de archivo inesperado en una conexión con una transacción abierta" -#: commands/copyfromparse.c:294 +#: commands/copyfromparse.c:294 replication/walsender.c:772 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "se recibió un mensaje de tipo 0x%02X inesperado durante COPY desde la entrada estándar" -#: commands/copyfromparse.c:317 +#: commands/copyfromparse.c:317 replication/walsender.c:803 #, c-format msgid "COPY from stdin failed: %s" msgstr "falló COPY desde la entrada estándar: %s" #: commands/copyfromparse.c:785 -#, fuzzy, c-format -#| msgid "wrong number of columns: %d, expected %d" +#, c-format msgid "wrong number of fields in header line: got %d, expected %d" -msgstr "número de columnas erróneo: %d, se esperaban %d" +msgstr "número de campos en línea de cabecera erróneo: %d, se esperaban %d" #: commands/copyfromparse.c:801 #, c-format @@ -7141,8 +7405,8 @@ msgstr "discordancia de nombre de columna en campo %d de la línea de encabezado msgid "column name mismatch in header line field %d: got \"%s\", expected \"%s\"" msgstr "discordancia en nombre de columna en campo %d de la línea de encabezado: se obtuvo «%s», se esperaba «%s»" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1514 -#: commands/copyfromparse.c:1770 +#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 +#: commands/copyfromparse.c:1810 #, c-format msgid "extra data after last expected column" msgstr "datos extra después de la última columna esperada" @@ -7152,1126 +7416,1177 @@ msgstr "datos extra después de la última columna esperada" msgid "missing data for column \"%s\"" msgstr "faltan datos en la columna «%s»" -#: commands/copyfromparse.c:999 +#: commands/copyfromparse.c:990 +#, c-format +msgid "skipping row due to data type incompatibility at line %llu for column \"%s\": \"%s\"" +msgstr "omitiendo fila debido a incompatibilidad de tipo en la línea %llu para la columna «%s»: «%s»" + +#: commands/copyfromparse.c:998 +#, c-format +msgid "skipping row due to data type incompatibility at line %llu for column \"%s\": null input" +msgstr "omitiendo fila debido a incompatibilidad de tipo en la línea %llu para la columna «%s»: entrada nula" + +#: commands/copyfromparse.c:1044 #, c-format msgid "received copy data after EOF marker" msgstr "se recibieron datos de copy después del marcador EOF" -#: commands/copyfromparse.c:1006 +#: commands/copyfromparse.c:1051 #, c-format msgid "row field count is %d, expected %d" msgstr "la cantidad de registros es %d, pero se esperaban %d" -#: commands/copyfromparse.c:1296 commands/copyfromparse.c:1313 +#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 #, c-format msgid "literal carriage return found in data" msgstr "se encontró un retorno de carro literal en los datos" -#: commands/copyfromparse.c:1297 commands/copyfromparse.c:1314 +#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 #, c-format msgid "unquoted carriage return found in data" msgstr "se encontró un retorno de carro fuera de comillas en los datos" -#: commands/copyfromparse.c:1299 commands/copyfromparse.c:1316 +#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "Use «\\r» para representar el retorno de carro." -#: commands/copyfromparse.c:1300 commands/copyfromparse.c:1317 +#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "Use un campo CSV entre comillas para representar el retorno de carro." -#: commands/copyfromparse.c:1329 +#: commands/copyfromparse.c:1369 #, c-format msgid "literal newline found in data" msgstr "se encontró un salto de línea literal en los datos" -#: commands/copyfromparse.c:1330 +#: commands/copyfromparse.c:1370 #, c-format msgid "unquoted newline found in data" msgstr "se encontró un salto de línea fuera de comillas en los datos" -#: commands/copyfromparse.c:1332 +#: commands/copyfromparse.c:1372 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "Use «\\n» para representar un salto de línea." -#: commands/copyfromparse.c:1333 +#: commands/copyfromparse.c:1373 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "Use un campo CSV entre comillas para representar un salto de línea." -#: commands/copyfromparse.c:1379 commands/copyfromparse.c:1415 +#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "el marcador fin-de-copy no coincide con el estilo previo de salto de línea" -#: commands/copyfromparse.c:1388 commands/copyfromparse.c:1404 +#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 #, c-format msgid "end-of-copy marker corrupt" msgstr "marcador fin-de-copy corrupto" -#: commands/copyfromparse.c:1706 commands/copyfromparse.c:1921 -#, fuzzy, c-format -#| msgid "unexpected EOF in COPY data" -msgid "unexpected DEFAULT in COPY data" -msgstr "EOF inesperado en datos de COPY" +#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 +#, c-format +msgid "unexpected default marker in COPY data" +msgstr "marcador “default” inesperado en datos de COPY" -#: commands/copyfromparse.c:1707 commands/copyfromparse.c:1922 -#, fuzzy, c-format -#| msgid "column \"%s\" can only be updated to DEFAULT" -msgid "Column \"%s\" has no DEFAULT value." -msgstr "la columna «%s» sólo puede actualizarse a DEFAULT" +#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 +#, c-format +msgid "Column \"%s\" has no default value." +msgstr "La columna «%s» no tiene valor por omisión." -#: commands/copyfromparse.c:1854 +#: commands/copyfromparse.c:1894 #, c-format msgid "unterminated CSV quoted field" msgstr "un valor entre comillas está inconcluso" -#: commands/copyfromparse.c:1956 commands/copyfromparse.c:1975 +#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 #, c-format msgid "unexpected EOF in COPY data" msgstr "EOF inesperado en datos de COPY" -#: commands/copyfromparse.c:1965 +#: commands/copyfromparse.c:2005 #, c-format msgid "invalid field size" msgstr "el tamaño de campo no es válido" -#: commands/copyfromparse.c:1988 +#: commands/copyfromparse.c:2028 #, c-format msgid "incorrect binary data format" msgstr "el formato de datos binarios es incorrecto" -#: commands/copyto.c:236 +#: commands/copyto.c:229 #, c-format msgid "could not write to COPY program: %m" msgstr "no se pudo escribir al programa COPY: %m" -#: commands/copyto.c:241 +#: commands/copyto.c:234 #, c-format msgid "could not write to COPY file: %m" msgstr "no se pudo escribir archivo COPY: %m" -#: commands/copyto.c:386 +#: commands/copyto.c:379 #, c-format msgid "cannot copy from view \"%s\"" msgstr "no se puede copiar desde la vista «%s»" -#: commands/copyto.c:388 commands/copyto.c:394 commands/copyto.c:400 -#: commands/copyto.c:411 +#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 +#: commands/copyto.c:404 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "Intente la forma COPY (SELECT ...) TO." -#: commands/copyto.c:392 +#: commands/copyto.c:385 #, c-format msgid "cannot copy from materialized view \"%s\"" msgstr "no se puede copiar desde la vista materializada «%s»" -#: commands/copyto.c:398 +#: commands/copyto.c:391 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "no se puede copiar desde la tabla foránea «%s»" -#: commands/copyto.c:404 +#: commands/copyto.c:397 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "no se puede copiar desde la secuencia «%s»" -#: commands/copyto.c:409 +#: commands/copyto.c:402 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "no se puede hacer copy de la tabla particionada «%s»" -#: commands/copyto.c:415 +#: commands/copyto.c:408 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "no se puede copiar desde la relación «%s» porque no es una tabla" -#: commands/copyto.c:467 +#: commands/copyto.c:460 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "las reglas DO INSTEAD NOTHING no están soportadas para COPY" -#: commands/copyto.c:481 +#: commands/copyto.c:474 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "las reglas DO INSTEAD condicionales no están soportadas para COPY" -#: commands/copyto.c:485 +#: commands/copyto.c:478 #, c-format -msgid "DO ALSO rules are not supported for the COPY" +msgid "DO ALSO rules are not supported for COPY" msgstr "las reglas DO ALSO no están soportadas para COPY" -#: commands/copyto.c:490 +#: commands/copyto.c:483 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "las reglas DO INSTEAD de múltiples sentencias no están soportadas para COPY" -#: commands/copyto.c:500 +#: commands/copyto.c:493 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO) no está soportado" -#: commands/copyto.c:517 +#: commands/copyto.c:499 +#, c-format +msgid "COPY query must not be a utility command" +msgstr "la consulta COPY no debe ser una orden de utilidad" + +#: commands/copyto.c:515 #, c-format msgid "COPY query must have a RETURNING clause" msgstr "la consulta COPY debe tener una cláusula RETURNING" -#: commands/copyto.c:546 +#: commands/copyto.c:544 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "la relación referenciada por la sentencia COPY ha cambiado" -#: commands/copyto.c:605 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "la columna FORCE_QUOTE «%s» no es referenciada en COPY" - -#: commands/copyto.c:673 +#: commands/copyto.c:671 #, c-format msgid "relative path not allowed for COPY to file" msgstr "no se permiten rutas relativas para COPY hacia un archivo" -#: commands/copyto.c:692 +#: commands/copyto.c:690 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "no se pudo abrir el archivo «%s» para escritura: %m" -#: commands/copyto.c:695 +#: commands/copyto.c:693 #, c-format msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY TO indica al proceso servidor PostgreSQL escribir a un archivo. Puede desear usar facilidades del lado del cliente, como \\copy de psql." -#: commands/createas.c:215 commands/createas.c:523 +#: commands/createas.c:210 commands/createas.c:516 #, c-format msgid "too many column names were specified" msgstr "se especificaron demasiados nombres de columna" -#: commands/createas.c:546 +#: commands/createas.c:539 #, c-format msgid "policies not yet implemented for this command" msgstr "las políticas no están implementadas para esta orden" -#: commands/dbcommands.c:822 +#: commands/dbcommands.c:829 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATION ya no está soportado" -#: commands/dbcommands.c:823 +#: commands/dbcommands.c:830 #, c-format msgid "Consider using tablespaces instead." msgstr "Considere usar tablespaces." -#: commands/dbcommands.c:848 +#: commands/dbcommands.c:855 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "los OIDs menores que %u están reservados para objetos del sistema" -#: commands/dbcommands.c:879 utils/adt/ascii.c:146 +#: commands/dbcommands.c:886 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "%d no es un código válido de codificación" -#: commands/dbcommands.c:890 utils/adt/ascii.c:128 +#: commands/dbcommands.c:897 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "%s no es un nombre válido de codificación" -#: commands/dbcommands.c:919 +#: commands/dbcommands.c:931 #, c-format msgid "unrecognized locale provider: %s" msgstr "proveedor de ordenamiento no reconocido: %s" -#: commands/dbcommands.c:932 commands/dbcommands.c:2318 commands/user.c:300 -#: commands/user.c:740 +#: commands/dbcommands.c:944 commands/dbcommands.c:2414 commands/user.c:299 +#: commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "límite de conexión no válido: %d" -#: commands/dbcommands.c:953 +#: commands/dbcommands.c:965 #, c-format msgid "permission denied to create database" msgstr "se ha denegado el permiso para crear la base de datos" -#: commands/dbcommands.c:977 +#: commands/dbcommands.c:989 #, c-format msgid "template database \"%s\" does not exist" msgstr "no existe la base de datos patrón «%s»" -#: commands/dbcommands.c:989 +#: commands/dbcommands.c:999 #, c-format -msgid "permission denied to copy database \"%s\"" +msgid "cannot use invalid database \"%s\" as template" +msgstr "no se puede usar la base de datos «%s» no válida como plantilla" + +#: commands/dbcommands.c:1000 commands/dbcommands.c:2444 +#: utils/init/postinit.c:1113 +#, c-format +msgid "Use DROP DATABASE to drop invalid databases." +msgstr "Use DROP DATABASE para eliminar una base de datos no válida." + +#: commands/dbcommands.c:1011 +#, c-format +msgid "permission denied to copy database \"%s\"" msgstr "se ha denegado el permiso para copiar la base de datos «%s»" -#: commands/dbcommands.c:1006 -#, fuzzy, c-format -#| msgid "invalid parameter list format: \"%s\"" +#: commands/dbcommands.c:1028 +#, c-format msgid "invalid create database strategy \"%s\"" -msgstr "el formato de la lista de parámetros no es válido: «%s»" +msgstr "estrategia de creación de base de dato no válida: «%s»" -#: commands/dbcommands.c:1007 -#, fuzzy, c-format -#| msgid "Valid values are \"local\" and \"cascaded\"." -msgid "Valid strategies are \"wal_log\", and \"file_copy\"." -msgstr "Los valores aceptables son «local» y «cascaded»." +#: commands/dbcommands.c:1029 +#, c-format +msgid "Valid strategies are \"wal_log\" and \"file_copy\"." +msgstr "Las estrategias válidas son «wal_log» y «file_copy»." -#: commands/dbcommands.c:1028 +#: commands/dbcommands.c:1050 #, c-format msgid "invalid server encoding %d" msgstr "la codificación de servidor %d no es válida" -#: commands/dbcommands.c:1034 commands/dbcommands.c:1039 +#: commands/dbcommands.c:1056 #, c-format -msgid "invalid locale name: \"%s\"" -msgstr "nombre de configuración regional no válido: «%s»" +msgid "invalid LC_COLLATE locale name: \"%s\"" +msgstr "nombre de configuración regional LC_COLLATE no válido: «%s»" -#: commands/dbcommands.c:1049 -#, fuzzy, c-format -#| msgid "encoding \"%s\" not supported by ICU" -msgid "encoding \"%s\" is not supported with ICU provider" -msgstr "la codificación «%s» no estæ soportada por ICU" +#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 +#, c-format +msgid "If the locale name is specific to ICU, use ICU_LOCALE." +msgstr "Si el nombre de configuración regional es específico a ICU, use ICU_LOCALE." + +#: commands/dbcommands.c:1062 +#, c-format +msgid "invalid LC_CTYPE locale name: \"%s\"" +msgstr "nombre de configuración regional LC_CTYPE no válido: «%s»" -#: commands/dbcommands.c:1059 +#: commands/dbcommands.c:1074 #, c-format -msgid "ICU locale must be specified" -msgstr "el locale ICU debe ser especificado" +msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" +msgstr "no se puede especificar BUILTIN_LOCALE a menos que el proveedor de configuración regional sea builtin" -#: commands/dbcommands.c:1088 +#: commands/dbcommands.c:1082 #, c-format msgid "ICU locale cannot be specified unless locale provider is ICU" msgstr "no se puede especificar una configuración regional ICU a menos que el proveedor de configuración regional sea ICU" -#: commands/dbcommands.c:1111 +#: commands/dbcommands.c:1100 +#, c-format +msgid "LOCALE or BUILTIN_LOCALE must be specified" +msgstr "debe especificarse LOCALE o BUILTIN_LOCALE" + +#: commands/dbcommands.c:1109 +#, c-format +msgid "encoding \"%s\" is not supported with ICU provider" +msgstr "la codificación «%s» no está soportada por ICU" + +#: commands/dbcommands.c:1119 +#, c-format +msgid "LOCALE or ICU_LOCALE must be specified" +msgstr "debe especificarse LOCALE o ICU_LOCALE" + +#: commands/dbcommands.c:1163 #, c-format msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)" msgstr "la nueva codificación (%s) es incompatible con la codificación de la base de datos patrón (%s)" -#: commands/dbcommands.c:1114 +#: commands/dbcommands.c:1166 #, c-format msgid "Use the same encoding as in the template database, or use template0 as template." msgstr "Use la misma codificación que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1119 +#: commands/dbcommands.c:1171 #, c-format msgid "new collation (%s) is incompatible with the collation of the template database (%s)" msgstr "la nueva «collation» (%s) es incompatible con la «collation» de la base de datos patrón (%s)" -#: commands/dbcommands.c:1121 +#: commands/dbcommands.c:1173 #, c-format msgid "Use the same collation as in the template database, or use template0 as template." msgstr "Use la misma «collation» que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1126 +#: commands/dbcommands.c:1178 #, c-format msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)" msgstr "el nuevo LC_CTYPE (%s) es incompatible con el LC_CTYPE de la base de datos patrón (%s)" -#: commands/dbcommands.c:1128 +#: commands/dbcommands.c:1180 #, c-format msgid "Use the same LC_CTYPE as in the template database, or use template0 as template." msgstr "Use el mismo LC_CTYPE que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1133 -#, fuzzy, c-format -#| msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)" +#: commands/dbcommands.c:1185 +#, c-format msgid "new locale provider (%s) does not match locale provider of the template database (%s)" -msgstr "la nueva codificación (%s) es incompatible con la codificación de la base de datos patrón (%s)" +msgstr "el nuevo proveedor de configuración regional (%s) no coincide con el proveedor de la base de datos patrón (%s)" -#: commands/dbcommands.c:1135 -#, fuzzy, c-format -#| msgid "Use the same encoding as in the template database, or use template0 as template." +#: commands/dbcommands.c:1187 +#, c-format msgid "Use the same locale provider as in the template database, or use template0 as template." -msgstr "Use la misma codificación que en la base de datos patrón, o bien use template0 como patrón." +msgstr "Use el mismo proveedor de «locale» que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1147 -#, fuzzy, c-format -#| msgid "new collation (%s) is incompatible with the collation of the template database (%s)" +#: commands/dbcommands.c:1199 +#, c-format msgid "new ICU locale (%s) is incompatible with the ICU locale of the template database (%s)" -msgstr "la nueva «collation» (%s) es incompatible con la «collation» de la base de datos patrón (%s)" +msgstr "la nueva configuración regional ICU (%s) es incompatible con la configuración regional ICU de la base de datos patrón (%s)" -#: commands/dbcommands.c:1149 -#, fuzzy, c-format -#| msgid "Use the same collation as in the template database, or use template0 as template." +#: commands/dbcommands.c:1201 +#, c-format msgid "Use the same ICU locale as in the template database, or use template0 as template." -msgstr "Use la misma «collation» que en la base de datos patrón, o bien use template0 como patrón." +msgstr "Use la misma configuración regional («locale») que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1160 -#, fuzzy, c-format -#| msgid "new collation (%s) is incompatible with the collation of the template database (%s)" +#: commands/dbcommands.c:1212 +#, c-format msgid "new ICU collation rules (%s) are incompatible with the ICU collation rules of the template database (%s)" -msgstr "la nueva «collation» (%s) es incompatible con la «collation» de la base de datos patrón (%s)" +msgstr "las nuevas reglas de «collation» ICU (%s) son incompatibles con las reglas de «collation» ICU de la base de datos patrón (%s)" -#: commands/dbcommands.c:1162 -#, fuzzy, c-format -#| msgid "Use the same collation as in the template database, or use template0 as template." +#: commands/dbcommands.c:1214 +#, c-format msgid "Use the same ICU collation rules as in the template database, or use template0 as template." -msgstr "Use la misma «collation» que en la base de datos patrón, o bien use template0 como patrón." +msgstr "Use las mismas reglas de «collation» ICU que en la base de datos patrón, o bien use template0 como patrón." -#: commands/dbcommands.c:1185 +#: commands/dbcommands.c:1243 #, c-format msgid "template database \"%s\" has a collation version, but no actual collation version could be determined" -msgstr "" +msgstr "la base de datos patrón «%s» tiene una versión de configuración regional, pero no se pudo determinar una versión real" -#: commands/dbcommands.c:1190 -#, fuzzy, c-format -#| msgid "template database \"%s\" does not exist" +#: commands/dbcommands.c:1248 +#, c-format msgid "template database \"%s\" has a collation version mismatch" -msgstr "no existe la base de datos patrón «%s»" +msgstr "discordancia en la versión de «collation» de la base de datos patrón «%s»" -#: commands/dbcommands.c:1192 -#, fuzzy, c-format -#| msgid "The collation in the database was created using version %s, but the operating system provides version %s." +#: commands/dbcommands.c:1250 +#, c-format msgid "The template database was created using collation version %s, but the operating system provides version %s." -msgstr "El ordenamiento en la base de datos fue creado usando la versión %s, pero el sistema operativo provee la versión %s." +msgstr "La base de datos patrón fue creada usando la versión %s, pero el sistema operativo provee la versión %s." -#: commands/dbcommands.c:1195 -#, fuzzy, c-format -#| msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." +#: commands/dbcommands.c:1253 +#, c-format msgid "Rebuild all objects in the template database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." -msgstr "Reconstruya todos los objetos afectados por este ordenamiento y ejecute ALTER COLLATION %s REFRESH VERSION, o construya PostgreSQL con la versión correcta de la biblioteca." +msgstr "Reconstruya todos los objetos de la base de datos patrón afectados por este ordenamiento y ejecute ALTER DATABASE %s REFRESH COLLATION VERSION, o construya PostgreSQL con la versión correcta de la biblioteca." -#: commands/dbcommands.c:1231 commands/dbcommands.c:1947 +#: commands/dbcommands.c:1298 commands/dbcommands.c:2041 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "no puede usarse pg_global como tablespace por omisión" -#: commands/dbcommands.c:1257 +#: commands/dbcommands.c:1324 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "no se puede asignar el nuevo tablespace por omisión «%s»" -#: commands/dbcommands.c:1259 +#: commands/dbcommands.c:1326 #, c-format msgid "There is a conflict because database \"%s\" already has some tables in this tablespace." msgstr "Hay un conflicto puesto que la base de datos «%s» ya tiene algunas tablas en este tablespace." -#: commands/dbcommands.c:1289 commands/dbcommands.c:1820 +#: commands/dbcommands.c:1356 commands/dbcommands.c:1912 #, c-format msgid "database \"%s\" already exists" msgstr "la base de datos «%s» ya existe" -#: commands/dbcommands.c:1303 +#: commands/dbcommands.c:1370 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "la base de datos de origen «%s» está siendo utilizada por otros usuarios" -#: commands/dbcommands.c:1325 -#, fuzzy, c-format -#| msgid "database \"%s\" already exists" +#: commands/dbcommands.c:1392 +#, c-format msgid "database OID %u is already in use by database \"%s\"" -msgstr "la base de datos «%s» ya existe" +msgstr "el OID de base de datos %u ya está en uso por la base de datos «%s»" -#: commands/dbcommands.c:1331 +#: commands/dbcommands.c:1398 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "el directorio de datos con el OID %u especificado ya existe" -#: commands/dbcommands.c:1503 commands/dbcommands.c:1518 +#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 +#: utils/adt/pg_locale.c:2588 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "la codificación «%s» no coincide con la configuración regional «%s»" -#: commands/dbcommands.c:1506 +#: commands/dbcommands.c:1574 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "El parámetro LC_CTYPE escogido requiere la codificación «%s»." -#: commands/dbcommands.c:1521 +#: commands/dbcommands.c:1589 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "El parámetro LC_COLLATE escogido requiere la codificación «%s»." -#: commands/dbcommands.c:1601 +#: commands/dbcommands.c:1672 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "no existe la base de datos «%s», omitiendo" -#: commands/dbcommands.c:1625 +#: commands/dbcommands.c:1696 #, c-format msgid "cannot drop a template database" msgstr "no se puede borrar una base de datos patrón" -#: commands/dbcommands.c:1631 +#: commands/dbcommands.c:1702 #, c-format msgid "cannot drop the currently open database" msgstr "no se puede eliminar la base de datos activa" -#: commands/dbcommands.c:1644 +#: commands/dbcommands.c:1715 #, c-format msgid "database \"%s\" is used by an active logical replication slot" -msgstr "la base de datos «%s» está en uso por un slot de replicación activo" +msgstr "la base de datos «%s» está en uso por un slot de replicación lógica activo" -#: commands/dbcommands.c:1646 +#: commands/dbcommands.c:1717 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." msgstr[0] "Hay %d slot activo." msgstr[1] "Hay %d slots activos." -#: commands/dbcommands.c:1660 +#: commands/dbcommands.c:1731 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "la base de datos «%s» está siendo utilizada por suscripciones de replicación lógica" -#: commands/dbcommands.c:1662 +#: commands/dbcommands.c:1733 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." msgstr[0] "Hay %d suscripción." msgstr[1] "Hay %d suscripciones." -#: commands/dbcommands.c:1683 commands/dbcommands.c:1842 -#: commands/dbcommands.c:1969 +#: commands/dbcommands.c:1754 commands/dbcommands.c:1934 +#: commands/dbcommands.c:2063 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "la base de datos «%s» está siendo utilizada por otros usuarios" -#: commands/dbcommands.c:1802 +#: commands/dbcommands.c:1894 #, c-format msgid "permission denied to rename database" msgstr "se ha denegado el permiso para cambiar el nombre a la base de datos" -#: commands/dbcommands.c:1831 +#: commands/dbcommands.c:1923 #, c-format msgid "current database cannot be renamed" msgstr "no se puede cambiar el nombre de la base de datos activa" -#: commands/dbcommands.c:1925 +#: commands/dbcommands.c:2019 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "no se puede cambiar el tablespace de la base de datos activa" -#: commands/dbcommands.c:2031 +#: commands/dbcommands.c:2125 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "algunas relaciones de la base de datos «%s» ya están en el tablespace «%s»" -#: commands/dbcommands.c:2033 +#: commands/dbcommands.c:2127 #, c-format msgid "You must move them back to the database's default tablespace before using this command." msgstr "Debe moverlas de vuelta al tablespace por omisión de la base de datos antes de ejecutar esta orden." -#: commands/dbcommands.c:2160 commands/dbcommands.c:2868 -#: commands/dbcommands.c:3132 commands/dbcommands.c:3245 +#: commands/dbcommands.c:2256 commands/dbcommands.c:2999 +#: commands/dbcommands.c:3299 commands/dbcommands.c:3412 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "algunos archivos inútiles pueden haber quedado en el directorio \"%s\"" -#: commands/dbcommands.c:2221 +#: commands/dbcommands.c:2317 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "opción de DROP DATABASE «%s» no reconocida" -#: commands/dbcommands.c:2299 +#: commands/dbcommands.c:2395 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "la opción «%s» no puede ser especificada con otras opciones" -#: commands/dbcommands.c:2355 +#: commands/dbcommands.c:2443 +#, c-format +msgid "cannot alter invalid database \"%s\"" +msgstr "no se puede alterar base de datos no válida «%s»" + +#: commands/dbcommands.c:2460 #, c-format msgid "cannot disallow connections for current database" msgstr "no se pueden prohibir las conexiones para la base de datos actual" -#: commands/dbcommands.c:2570 +#: commands/dbcommands.c:2690 #, c-format msgid "permission denied to change owner of database" msgstr "se ha denegado el permiso para cambiar el dueño de la base de datos" -#: commands/dbcommands.c:2974 +#: commands/dbcommands.c:3105 #, c-format msgid "There are %d other session(s) and %d prepared transaction(s) using the database." msgstr "Hay otras %d sesiones y %d transacciones preparadas usando la base de datos." -#: commands/dbcommands.c:2977 +#: commands/dbcommands.c:3108 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." msgstr[0] "Hay %d otra sesión usando la base de datos." msgstr[1] "Hay otras %d sesiones usando la base de datos." -#: commands/dbcommands.c:2982 storage/ipc/procarray.c:3798 +#: commands/dbcommands.c:3113 storage/ipc/procarray.c:3859 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." msgstr[0] "Hay %d otra transacción preparada usando la base de datos." msgstr[1] "Hay otras %d transacciones preparadas usando la base de datos." -#: commands/dbcommands.c:3088 -#, fuzzy, c-format -#| msgid "removing WAL directory \"%s\"" +#: commands/dbcommands.c:3255 +#, c-format msgid "missing directory \"%s\"" -msgstr "eliminando el directorio de WAL «%s»" +msgstr "directorio «%s» faltante" -#: commands/dbcommands.c:3146 commands/tablespace.c:190 -#: commands/tablespace.c:639 +#: commands/dbcommands.c:3313 commands/tablespace.c:184 +#: commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "no se pudo hacer stat al directorio «%s»: %m" -#: commands/define.c:54 commands/define.c:258 commands/define.c:290 -#: commands/define.c:318 commands/define.c:364 +#: commands/define.c:53 commands/define.c:257 commands/define.c:289 +#: commands/define.c:317 commands/define.c:363 #, c-format msgid "%s requires a parameter" msgstr "%s requiere un parámetro" -#: commands/define.c:87 commands/define.c:98 commands/define.c:192 -#: commands/define.c:210 commands/define.c:225 commands/define.c:243 +#: commands/define.c:86 commands/define.c:97 commands/define.c:191 +#: commands/define.c:209 commands/define.c:224 commands/define.c:242 #, c-format msgid "%s requires a numeric value" msgstr "%s requiere un valor numérico" -#: commands/define.c:154 +#: commands/define.c:153 #, c-format msgid "%s requires a Boolean value" msgstr "«%s» requiere un valor lógico (booleano)" -#: commands/define.c:168 commands/define.c:177 commands/define.c:327 +#: commands/define.c:167 commands/define.c:176 commands/define.c:326 #, c-format msgid "%s requires an integer value" msgstr "%s requiere valor entero" -#: commands/define.c:272 +#: commands/define.c:271 #, c-format msgid "argument of %s must be a name" msgstr "el argumento de %s debe ser un nombre" -#: commands/define.c:302 +#: commands/define.c:301 #, c-format msgid "argument of %s must be a type name" msgstr "el argumento de %s debe ser un nombre de tipo" -#: commands/define.c:348 +#: commands/define.c:347 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "argumento no válido para %s: «%s»" -#: commands/dropcmds.c:101 commands/functioncmds.c:1387 -#: utils/adt/ruleutils.c:2897 +#: commands/dropcmds.c:96 commands/functioncmds.c:1382 +#: utils/adt/ruleutils.c:2910 #, c-format msgid "\"%s\" is an aggregate function" msgstr "«%s» es una función de agregación" -#: commands/dropcmds.c:103 +#: commands/dropcmds.c:98 #, c-format msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "Use DROP AGGREGATE para eliminar funciones de agregación." -#: commands/dropcmds.c:158 commands/sequence.c:474 commands/tablecmds.c:3710 -#: commands/tablecmds.c:3868 commands/tablecmds.c:3920 -#: commands/tablecmds.c:16468 tcop/utility.c:1335 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3892 +#: commands/tablecmds.c:4050 commands/tablecmds.c:4102 +#: commands/tablecmds.c:17161 tcop/utility.c:1325 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "no existe la relación «%s», omitiendo" -#: commands/dropcmds.c:188 commands/dropcmds.c:287 commands/tablecmds.c:1285 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1409 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "el esquema «%s» no existe, omitiendo" -#: commands/dropcmds.c:228 commands/dropcmds.c:267 commands/tablecmds.c:277 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "el tipo «%s» no existe, omitiendo" -#: commands/dropcmds.c:257 +#: commands/dropcmds.c:252 #, c-format msgid "access method \"%s\" does not exist, skipping" msgstr "no existe el método de acceso «%s», omitiendo" -#: commands/dropcmds.c:275 +#: commands/dropcmds.c:270 #, c-format msgid "collation \"%s\" does not exist, skipping" msgstr "no existe el ordenamiento (collation) «%s», omitiendo" -#: commands/dropcmds.c:282 +#: commands/dropcmds.c:277 #, c-format msgid "conversion \"%s\" does not exist, skipping" msgstr "no existe la conversión «%s», omitiendo" -#: commands/dropcmds.c:293 commands/statscmds.c:654 +#: commands/dropcmds.c:288 commands/statscmds.c:664 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "no existe el objeto de estadísticas «%s», omitiendo" -#: commands/dropcmds.c:300 +#: commands/dropcmds.c:295 #, c-format msgid "text search parser \"%s\" does not exist, skipping" msgstr "el analizador de búsqueda en texto «%s» no existe, omitiendo" -#: commands/dropcmds.c:307 +#: commands/dropcmds.c:302 #, c-format msgid "text search dictionary \"%s\" does not exist, skipping" msgstr "el diccionario de búsqueda en texto «%s» no existe, omitiendo" -#: commands/dropcmds.c:314 +#: commands/dropcmds.c:309 #, c-format msgid "text search template \"%s\" does not exist, skipping" msgstr "la plantilla de búsqueda en texto «%s» no existe, omitiendo" -#: commands/dropcmds.c:321 +#: commands/dropcmds.c:316 #, c-format msgid "text search configuration \"%s\" does not exist, skipping" msgstr "no existe la configuración de búsqueda en texto «%s», omitiendo" -#: commands/dropcmds.c:326 +#: commands/dropcmds.c:321 #, c-format msgid "extension \"%s\" does not exist, skipping" msgstr "no existe la extensión «%s», omitiendo" -#: commands/dropcmds.c:336 +#: commands/dropcmds.c:331 #, c-format msgid "function %s(%s) does not exist, skipping" msgstr "no existe la función %s(%s), omitiendo" -#: commands/dropcmds.c:349 +#: commands/dropcmds.c:344 #, c-format msgid "procedure %s(%s) does not exist, skipping" msgstr "el procedimiento %s(%s) no existe, omitiendo" -#: commands/dropcmds.c:362 +#: commands/dropcmds.c:357 #, c-format msgid "routine %s(%s) does not exist, skipping" msgstr "no existe la rutina %s(%s), omitiendo" -#: commands/dropcmds.c:375 +#: commands/dropcmds.c:370 #, c-format msgid "aggregate %s(%s) does not exist, skipping" msgstr "la función de agregación %s(%s) no existe, omitiendo" -#: commands/dropcmds.c:388 +#: commands/dropcmds.c:383 #, c-format msgid "operator %s does not exist, skipping" msgstr "el operador %s no existe, omitiendo" -#: commands/dropcmds.c:394 +#: commands/dropcmds.c:389 #, c-format msgid "language \"%s\" does not exist, skipping" msgstr "el lenguaje «%s» no existe, omitiendo" -#: commands/dropcmds.c:403 +#: commands/dropcmds.c:398 #, c-format msgid "cast from type %s to type %s does not exist, skipping" msgstr "no existe la conversión del tipo %s al tipo %s, omitiendo" -#: commands/dropcmds.c:412 +#: commands/dropcmds.c:407 #, c-format msgid "transform for type %s language \"%s\" does not exist, skipping" msgstr "la transformación para el tipo %s lenguaje «%s» no existe, omitiendo" -#: commands/dropcmds.c:420 +#: commands/dropcmds.c:415 #, c-format msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping" -msgstr "disparador «%s» para la relación «%s» no existe, omitiendo" +msgstr "“trigger” «%s» para la relación «%s» no existe, omitiendo" -#: commands/dropcmds.c:429 +#: commands/dropcmds.c:424 #, c-format msgid "policy \"%s\" for relation \"%s\" does not exist, skipping" msgstr "la política «%s» para la relación «%s» no existe, omitiendo" -#: commands/dropcmds.c:436 +#: commands/dropcmds.c:431 #, c-format msgid "event trigger \"%s\" does not exist, skipping" -msgstr "el disparador por eventos «%s» no existe, omitiendo" +msgstr "el “trigger” por eventos «%s» no existe, omitiendo" -#: commands/dropcmds.c:442 +#: commands/dropcmds.c:437 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist, skipping" msgstr "la regla «%s» para la relación «%s» no existe, omitiendo" -#: commands/dropcmds.c:449 +#: commands/dropcmds.c:444 #, c-format msgid "foreign-data wrapper \"%s\" does not exist, skipping" msgstr "no existe el conector de datos externos «%s», omitiendo" -#: commands/dropcmds.c:453 commands/foreigncmds.c:1360 +#: commands/dropcmds.c:448 commands/foreigncmds.c:1360 #, c-format msgid "server \"%s\" does not exist, skipping" msgstr "el servidor «%s» no existe, omitiendo" -#: commands/dropcmds.c:462 +#: commands/dropcmds.c:457 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\", skipping" msgstr "no existe la clase de operadores «%s» para el método de acceso «%s», omitiendo" -#: commands/dropcmds.c:474 +#: commands/dropcmds.c:469 #, c-format msgid "operator family \"%s\" does not exist for access method \"%s\", skipping" msgstr "no existe la familia de operadores «%s» para el método de acceso «%s», omitiendo" -#: commands/dropcmds.c:481 +#: commands/dropcmds.c:476 #, c-format msgid "publication \"%s\" does not exist, skipping" msgstr "no existe la publicación «%s», omitiendo" -#: commands/event_trigger.c:125 +#: commands/event_trigger.c:137 #, c-format msgid "permission denied to create event trigger \"%s\"" -msgstr "se ha denegado el permiso para crear el disparador por eventos «%s»" +msgstr "se ha denegado el permiso para crear el “trigger” por eventos «%s»" -#: commands/event_trigger.c:127 +#: commands/event_trigger.c:139 #, c-format msgid "Must be superuser to create an event trigger." -msgstr "Debe ser superusuario para crear un disparador por eventos." +msgstr "Debe ser superusuario para crear un “trigger” por eventos." -#: commands/event_trigger.c:136 +#: commands/event_trigger.c:149 #, c-format msgid "unrecognized event name \"%s\"" msgstr "nommre de evento «%s» no reconocido" -#: commands/event_trigger.c:153 +#: commands/event_trigger.c:166 #, c-format msgid "unrecognized filter variable \"%s\"" msgstr "variable de filtro «%s» no reconocida" -#: commands/event_trigger.c:207 +#: commands/event_trigger.c:181 +#, c-format +msgid "tag filtering is not supported for login event triggers" +msgstr "el filtrado de «tags» no está soportado en “triggers” por evento de login" + +#: commands/event_trigger.c:224 #, c-format msgid "filter value \"%s\" not recognized for filter variable \"%s\"" msgstr "el valor de filtro «%s» no es reconocido por la variable de filtro «%s»" #. translator: %s represents an SQL statement name -#: commands/event_trigger.c:213 commands/event_trigger.c:235 +#: commands/event_trigger.c:230 commands/event_trigger.c:252 #, c-format msgid "event triggers are not supported for %s" -msgstr "los disparadores por eventos no están soportados para %s" +msgstr "los “triggers” por evento no están soportados para %s" -#: commands/event_trigger.c:248 +#: commands/event_trigger.c:265 #, c-format msgid "filter variable \"%s\" specified more than once" msgstr "la variable de filtro «%s» fue especificada más de una vez" -#: commands/event_trigger.c:376 commands/event_trigger.c:420 -#: commands/event_trigger.c:514 +#: commands/event_trigger.c:438 commands/event_trigger.c:490 +#: commands/event_trigger.c:584 #, c-format msgid "event trigger \"%s\" does not exist" -msgstr "no existe el disparador por eventos «%s»" +msgstr "no existe el “trigger” por eventos «%s»" -#: commands/event_trigger.c:452 +#: commands/event_trigger.c:522 #, c-format msgid "event trigger with OID %u does not exist" -msgstr "no existe el disparador por eventos con OID %u" +msgstr "no existe el “trigger” por eventos con OID %u" -#: commands/event_trigger.c:482 +#: commands/event_trigger.c:552 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" -msgstr "se ha denegado el permiso para cambiar el dueño del disparador por eventos «%s»" +msgstr "se ha denegado el permiso para cambiar el dueño del “trigger” por eventos «%s»" -#: commands/event_trigger.c:484 +#: commands/event_trigger.c:554 #, c-format msgid "The owner of an event trigger must be a superuser." -msgstr "El dueño de un disparador por eventos debe ser un superusuario." +msgstr "El dueño de un “trigger” por eventos debe ser un superusuario." -#: commands/event_trigger.c:1304 +#: commands/event_trigger.c:1409 #, c-format msgid "%s can only be called in a sql_drop event trigger function" -msgstr "%s sólo puede invocarse en una función de un disparador en el evento sql_drop" +msgstr "%s sólo puede invocarse en una función de un “trigger” en el evento sql_drop" -#: commands/event_trigger.c:1397 commands/event_trigger.c:1418 +#: commands/event_trigger.c:1502 commands/event_trigger.c:1523 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" -msgstr "%s sólo puede invocarse en una función de un disparador en el evento table_rewrite" +msgstr "%s sólo puede invocarse en una función de un “trigger” en el evento table_rewrite" -#: commands/event_trigger.c:1831 +#: commands/event_trigger.c:1936 #, c-format msgid "%s can only be called in an event trigger function" -msgstr "%s sólo puede invocarse en una función de un disparador por eventos" +msgstr "%s sólo puede invocarse en una función de un “trigger” por eventos" -#: commands/explain.c:220 +#: commands/explain.c:241 commands/explain.c:266 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "valor no reconocido para la opción de EXPLAIN «%s»: «%s»" -#: commands/explain.c:227 +#: commands/explain.c:273 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "opción de EXPLAIN «%s» no reconocida" -#: commands/explain.c:236 +#: commands/explain.c:282 #, c-format msgid "EXPLAIN option WAL requires ANALYZE" msgstr "la opción WAL de EXPLAIN requiere ANALYZE" -#: commands/explain.c:245 +#: commands/explain.c:291 #, c-format msgid "EXPLAIN option TIMING requires ANALYZE" msgstr "la opción TIMING de EXPLAIN requiere ANALYZE" -#: commands/explain.c:251 -#, fuzzy, c-format -#| msgid "options -d/--dbname and -f/--file cannot be used together" +#: commands/explain.c:297 +#, c-format +msgid "EXPLAIN option SERIALIZE requires ANALYZE" +msgstr "la opción SERIALIZE de EXPLAIN requiere ANALYZE" + +#: commands/explain.c:303 +#, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" -msgstr "las opciones -d/--dbname y -f/--file no pueden usarse juntas" +msgstr "las opciones ANALYZE y GENERIC_PLAN de EXPLAIN no pueden usarse juntas" -#: commands/extension.c:177 commands/extension.c:3009 +#: commands/extension.c:178 commands/extension.c:3031 #, c-format msgid "extension \"%s\" does not exist" msgstr "no existe la extensión «%s»" -#: commands/extension.c:276 commands/extension.c:285 commands/extension.c:297 -#: commands/extension.c:307 +#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 +#: commands/extension.c:308 #, c-format msgid "invalid extension name: \"%s\"" msgstr "nombre de extensión no válido: «%s»" -#: commands/extension.c:277 +#: commands/extension.c:278 #, c-format msgid "Extension names must not be empty." msgstr "Los nombres de extensión no deben ser vacíos." -#: commands/extension.c:286 +#: commands/extension.c:287 #, c-format msgid "Extension names must not contain \"--\"." msgstr "Los nombres de extensión no deben contener «--»." -#: commands/extension.c:298 +#: commands/extension.c:299 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "Los nombres de extensión no deben empezar ni terminar con «-»." -#: commands/extension.c:308 +#: commands/extension.c:309 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "Los nombres de extensión no deben contener caracteres separadores de directorio." -#: commands/extension.c:323 commands/extension.c:332 commands/extension.c:341 -#: commands/extension.c:351 +#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 +#: commands/extension.c:352 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "nombre de versión de extensión no válido: «%s»" -#: commands/extension.c:324 +#: commands/extension.c:325 #, c-format msgid "Version names must not be empty." msgstr "Los nombres de versión no deben ser vacíos." -#: commands/extension.c:333 +#: commands/extension.c:334 #, c-format msgid "Version names must not contain \"--\"." msgstr "Los nombres de versión no deben contener «--»." -#: commands/extension.c:342 +#: commands/extension.c:343 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "Los nombres de versión no deben empezar ni terminar con «-»." -#: commands/extension.c:352 +#: commands/extension.c:353 #, c-format msgid "Version names must not contain directory separator characters." msgstr "Los nombres de versión no deben contener caracteres separadores de directorio." -#: commands/extension.c:506 -#, fuzzy, c-format -#| msgid "extension \"%s\" does not exist" +#: commands/extension.c:507 +#, c-format msgid "extension \"%s\" is not available" -msgstr "no existe la extensión «%s»" +msgstr "la extensión «%s» no está disponible" -#: commands/extension.c:507 -#, fuzzy, c-format -#| msgid "could not open extension control file \"%s\": %m" +#: commands/extension.c:508 +#, c-format msgid "Could not open extension control file \"%s\": %m." -msgstr "no se pudo abrir el archivo de control de extensión «%s»: %m" +msgstr "No se pudo abrir el archivo de control de extensión «%s»: %m." -#: commands/extension.c:509 +#: commands/extension.c:510 #, c-format msgid "The extension must first be installed on the system where PostgreSQL is running." msgstr "La extensión debe primero ser instalada en el sistema donde PostgreSQL está ejecutándose." -#: commands/extension.c:513 +#: commands/extension.c:514 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "no se pudo abrir el archivo de control de extensión «%s»: %m" -#: commands/extension.c:536 commands/extension.c:546 +#: commands/extension.c:537 commands/extension.c:547 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "el parámetro «%s» no se puede cambiar en un archivo control secundario de extensión" -#: commands/extension.c:568 commands/extension.c:576 commands/extension.c:584 -#: utils/misc/guc.c:3098 +#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 +#: utils/misc/guc.c:3147 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "el parámetro «%s» requiere un valor lógico (booleano)" -#: commands/extension.c:593 +#: commands/extension.c:594 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "«%s» no es un nombre válido de codificación" -#: commands/extension.c:607 commands/extension.c:622 +#: commands/extension.c:608 commands/extension.c:623 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "el parámetro «%s» debe ser una lista de nombres de extensión" -#: commands/extension.c:629 +#: commands/extension.c:630 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "parámetro no reconocido «%s» en el archivo «%s»" -#: commands/extension.c:638 +#: commands/extension.c:639 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "el parámetro «schema» no puede ser especificado cuando «relocatable» es verdadero" -#: commands/extension.c:816 +#: commands/extension.c:817 #, c-format msgid "transaction control statements are not allowed within an extension script" msgstr "las sentencias de control de transacción no están permitidos dentro de un guión de transacción" -#: commands/extension.c:896 +#: commands/extension.c:897 #, c-format msgid "permission denied to create extension \"%s\"" msgstr "se ha denegado el permiso para crear la extensión «%s»" -#: commands/extension.c:899 +#: commands/extension.c:900 #, c-format msgid "Must have CREATE privilege on current database to create this extension." msgstr "Debe tener privilegio CREATE en la base de datos actual para crear esta extensión." -#: commands/extension.c:900 +#: commands/extension.c:901 #, c-format msgid "Must be superuser to create this extension." msgstr "Debe ser superusuario para crear esta extensión." -#: commands/extension.c:904 +#: commands/extension.c:905 #, c-format msgid "permission denied to update extension \"%s\"" msgstr "se ha denegado el permiso para actualizar la extensión «%s»" -#: commands/extension.c:907 +#: commands/extension.c:908 #, c-format msgid "Must have CREATE privilege on current database to update this extension." msgstr "Debe tener privilegio CREATE en la base de datos actual para actualizar esta extensión." -#: commands/extension.c:908 +#: commands/extension.c:909 #, c-format msgid "Must be superuser to update this extension." msgstr "Debe ser superusuario para actualizar esta extensión." -#: commands/extension.c:1265 +#: commands/extension.c:1042 +#, c-format +msgid "invalid character in extension owner: must not contain any of \"%s\"" +msgstr "carácter no válido en dueño de extensión: no debe contener ninguno de «%s»" + +#: commands/extension.c:1066 commands/extension.c:1093 +#, c-format +msgid "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" +msgstr "carácter no válido en esquema de extensión «%s»: no debe contener ninguno de «%s»" + +#: commands/extension.c:1288 #, c-format msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" msgstr "la extensión «%s» no tiene ruta de actualización desde la versión «%s» hasta la versión «%s»" -#: commands/extension.c:1473 commands/extension.c:3067 +#: commands/extension.c:1496 commands/extension.c:3089 #, c-format msgid "version to install must be specified" msgstr "la versión a instalar debe ser especificada" -#: commands/extension.c:1510 +#: commands/extension.c:1533 #, c-format msgid "extension \"%s\" has no installation script nor update path for version \"%s\"" msgstr "la extensión «%s» no tiene script de instalación ni ruta de actualización para la versión «%s»" -#: commands/extension.c:1544 +#: commands/extension.c:1567 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "la extensión «%s» debe ser instalada en el esquema «%s»" -#: commands/extension.c:1704 +#: commands/extension.c:1727 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "detectada una dependencia cíclica entre las extensiones «%s» y «%s»" -#: commands/extension.c:1709 +#: commands/extension.c:1732 #, c-format msgid "installing required extension \"%s\"" msgstr "instalando la extensión requerida «%s»" -#: commands/extension.c:1732 +#: commands/extension.c:1755 #, c-format msgid "required extension \"%s\" is not installed" msgstr "la extensión requerida «%s» no está instalada" -#: commands/extension.c:1735 +#: commands/extension.c:1758 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "Use CREATE EXTENSION ... CASCADE para instalar además las extensiones requeridas." -#: commands/extension.c:1770 +#: commands/extension.c:1793 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "la extensión «%s» ya existe, omitiendo" -#: commands/extension.c:1777 +#: commands/extension.c:1800 #, c-format msgid "extension \"%s\" already exists" msgstr "la extensión «%s» ya existe" -#: commands/extension.c:1788 +#: commands/extension.c:1811 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "los CREATE EXTENSION anidados no están soportados" -#: commands/extension.c:1952 +#: commands/extension.c:1975 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "no se puede eliminar la extensión «%s» porque está siendo modificada" -#: commands/extension.c:2427 +#: commands/extension.c:2450 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "%s sólo puede invocarse desde un script SQL ejecutado por CREATE EXTENSION" -#: commands/extension.c:2439 +#: commands/extension.c:2462 #, c-format msgid "OID %u does not refer to a table" msgstr "el OID %u no hace referencia a una tabla" -#: commands/extension.c:2444 +#: commands/extension.c:2467 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "el tabla «%s» no es un miembro de la extensión que se está creando" -#: commands/extension.c:2790 +#: commands/extension.c:2813 #, c-format msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema" msgstr "no se puede mover la extensión «%s» al esquema «%s» porque la extensión contiene al esquema" -#: commands/extension.c:2831 commands/extension.c:2928 +#: commands/extension.c:2854 commands/extension.c:2948 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "la extensión «%s» no soporta SET SCHEMA" -#: commands/extension.c:2885 -#, fuzzy, c-format -#| msgid "cannot drop extension \"%s\" because it is being modified" +#: commands/extension.c:2911 +#, c-format msgid "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" -msgstr "no se puede eliminar la extensión «%s» porque está siendo modificada" +msgstr "no se puede hacer SET SCHEMA de la extensión «%s» porque otras extensiones lo impiden" -#: commands/extension.c:2887 -#, fuzzy, c-format -#| msgid "relation \"%s\" is not a partition of relation \"%s\"" +#: commands/extension.c:2913 +#, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." -msgstr "relación «%s» no es una partición de la relación «%s»" +msgstr "La extensión «%s» solicita no relocalizar la extensión «%s»." -#: commands/extension.c:2930 +#: commands/extension.c:2950 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "%s no está en el esquema de la extensión, «%s»" -#: commands/extension.c:2989 +#: commands/extension.c:3011 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "los ALTER EXTENSION anidados no están soportados" -#: commands/extension.c:3078 +#: commands/extension.c:3100 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "la versión «%s» de la extensión «%s» ya está instalada" -#: commands/extension.c:3290 +#: commands/extension.c:3311 #, c-format msgid "cannot add an object of this type to an extension" msgstr "no se puede añadir un objeto de este tipo a una extensión" -#: commands/extension.c:3356 +#: commands/extension.c:3409 #, c-format msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension" msgstr "no se puede agregar el esquema «%s» a la extensión «%s» porque el esquema contiene la extensión" -#: commands/extension.c:3450 +#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#, c-format +msgid "could not find multirange type for data type %s" +msgstr "no se pudo encontrar un tipo de multirango para el tipo de dato %s" + +#: commands/extension.c:3532 #, c-format msgid "file \"%s\" is too large" msgstr "el archivo «%s» es demasiado grande" @@ -8301,7 +8616,7 @@ msgstr "Debe ser superusuario para cambiar el dueño de un conector de datos ext msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "El dueño de un conector de datos externos debe ser un superusuario." -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:678 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "no existe el conector de datos externos «%s»" @@ -8371,7 +8686,7 @@ msgstr "no existe el mapeo de usuario «%s» para el servidor «%s»" msgid "user mapping for \"%s\" does not exist for server \"%s\", skipping" msgstr "no existe el mapeo de usuario «%s» para el servidor «%s», omitiendo" -#: commands/foreigncmds.c:1507 foreign/foreign.c:391 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "el conector de datos externos «%s» no tiene manejador" @@ -8386,524 +8701,528 @@ msgstr "el conector de datos externos «%s» no soporta IMPORT FOREIGN SCHEMA" msgid "importing foreign table \"%s\"" msgstr "importando la tabla foránea «%s»" -#: commands/functioncmds.c:109 +#: commands/functioncmds.c:104 #, c-format msgid "SQL function cannot return shell type %s" msgstr "una función SQL no puede retornar el tipo inconcluso %s" -#: commands/functioncmds.c:114 +#: commands/functioncmds.c:109 #, c-format msgid "return type %s is only a shell" msgstr "el tipo de retorno %s está inconcluso" -#: commands/functioncmds.c:143 parser/parse_type.c:354 +#: commands/functioncmds.c:138 parser/parse_type.c:354 #, c-format msgid "type modifier cannot be specified for shell type \"%s\"" msgstr "no se puede especificar un modificador de tipo para el tipo inconcluso «%s»" -#: commands/functioncmds.c:149 +#: commands/functioncmds.c:144 #, c-format msgid "type \"%s\" is not yet defined" msgstr "el tipo «%s» no ha sido definido aún" -#: commands/functioncmds.c:150 +#: commands/functioncmds.c:145 #, c-format msgid "Creating a shell type definition." msgstr "Creando una definición de tipo inconclusa." -#: commands/functioncmds.c:249 +#: commands/functioncmds.c:244 #, c-format msgid "SQL function cannot accept shell type %s" msgstr "las funciones SQL no pueden aceptar el tipo inconcluso %s" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:250 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "las funciones de agregación no pueden aceptar el tipo inconcluso %s" -#: commands/functioncmds.c:260 +#: commands/functioncmds.c:255 #, c-format msgid "argument type %s is only a shell" msgstr "el tipo de argumento %s está inconcluso" -#: commands/functioncmds.c:270 +#: commands/functioncmds.c:265 #, c-format msgid "type %s does not exist" msgstr "no existe el tipo %s" -#: commands/functioncmds.c:284 +#: commands/functioncmds.c:279 #, c-format msgid "aggregates cannot accept set arguments" msgstr "las funciones de agregación no pueden aceptar argumentos de conjunto" -#: commands/functioncmds.c:288 +#: commands/functioncmds.c:283 #, c-format msgid "procedures cannot accept set arguments" msgstr "los procedimientos no pueden aceptar argumentos de conjunto" -#: commands/functioncmds.c:292 +#: commands/functioncmds.c:287 #, c-format msgid "functions cannot accept set arguments" msgstr "funciones no pueden aceptar argumentos de conjunto" -#: commands/functioncmds.c:302 +#: commands/functioncmds.c:297 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "el parámetro VARIADIC debe ser el último parámetro de entrada" -#: commands/functioncmds.c:322 +#: commands/functioncmds.c:317 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "el parámetro VARIADIC debe ser el último parámetro" -#: commands/functioncmds.c:347 +#: commands/functioncmds.c:342 #, c-format msgid "VARIADIC parameter must be an array" msgstr "el parámetro VARIADIC debe ser un array" -#: commands/functioncmds.c:392 +#: commands/functioncmds.c:387 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "nombre de parámetro «%s» usado más de una vez" -#: commands/functioncmds.c:410 +#: commands/functioncmds.c:405 #, c-format msgid "only input parameters can have default values" msgstr "solo los parámetros de entrada pueden tener valores por omisión" -#: commands/functioncmds.c:425 +#: commands/functioncmds.c:420 #, c-format msgid "cannot use table references in parameter default value" msgstr "no se pueden usar referencias a tablas en el valor por omisión de un parámetro" -#: commands/functioncmds.c:449 +#: commands/functioncmds.c:444 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "los parámetros de entrada después de uno que tenga valor por omisión también deben tener valores por omisión" -#: commands/functioncmds.c:459 +#: commands/functioncmds.c:454 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "los parámetros OUT no pueden aparecer después de uno que tenga valor por omisión" -#: commands/functioncmds.c:601 commands/functioncmds.c:780 +#: commands/functioncmds.c:596 commands/functioncmds.c:775 #, c-format msgid "invalid attribute in procedure definition" msgstr "atributo no válido en definición de procedimiento" -#: commands/functioncmds.c:697 +#: commands/functioncmds.c:692 #, c-format msgid "support function %s must return type %s" msgstr "la función de soporte %s debe retornar el tipo %s" -#: commands/functioncmds.c:708 +#: commands/functioncmds.c:703 #, c-format msgid "must be superuser to specify a support function" msgstr "debe ser superusuario para especificar una función de soporte" -#: commands/functioncmds.c:829 commands/functioncmds.c:1432 +#: commands/functioncmds.c:824 commands/functioncmds.c:1427 #, c-format msgid "COST must be positive" msgstr "COST debe ser positivo" -#: commands/functioncmds.c:837 commands/functioncmds.c:1440 +#: commands/functioncmds.c:832 commands/functioncmds.c:1435 #, c-format msgid "ROWS must be positive" msgstr "ROWS debe ser positivo" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:861 #, c-format msgid "no function body specified" msgstr "no se ha especificado un cuerpo para la función" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:866 #, c-format msgid "duplicate function body specified" msgstr "se ha especificado por duplicado el cuerpo para la función" -#: commands/functioncmds.c:876 +#: commands/functioncmds.c:871 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "cuerpo de función SQL en línea solo es válido para lenguaje SQL" -#: commands/functioncmds.c:918 +#: commands/functioncmds.c:913 #, c-format msgid "SQL function with unquoted function body cannot have polymorphic arguments" msgstr "una función SQL con el cuerpo de la función fuera de comillas no puede tener argumentos polimórficos" -#: commands/functioncmds.c:944 commands/functioncmds.c:963 +#: commands/functioncmds.c:939 commands/functioncmds.c:958 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "%s aún no está soportado en una función SQL con el cuerpo fuera de comillas" -#: commands/functioncmds.c:991 +#: commands/functioncmds.c:986 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "sólo se requiere un item AS para el lenguaje «%s»" -#: commands/functioncmds.c:1096 +#: commands/functioncmds.c:1091 #, c-format msgid "no language specified" msgstr "no se ha especificado el lenguaje" -#: commands/functioncmds.c:1104 commands/functioncmds.c:2105 -#: commands/proclang.c:237 +#: commands/functioncmds.c:1099 commands/functioncmds.c:2117 +#: commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "no existe el lenguaje «%s»" -#: commands/functioncmds.c:1106 commands/functioncmds.c:2107 +#: commands/functioncmds.c:1101 commands/functioncmds.c:2119 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "Use CREATE EXTENSION para cargar el lenguaje en la base de datos." -#: commands/functioncmds.c:1139 commands/functioncmds.c:1424 +#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 #, c-format msgid "only superuser can define a leakproof function" msgstr "sólo un superusuario puede definir funciones «leakproof»" -#: commands/functioncmds.c:1190 +#: commands/functioncmds.c:1185 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "tipo de retorno de función debe ser %s debido a los parámetros OUT" -#: commands/functioncmds.c:1203 +#: commands/functioncmds.c:1198 #, c-format msgid "function result type must be specified" msgstr "el tipo de retorno de la función debe ser especificado" -#: commands/functioncmds.c:1256 commands/functioncmds.c:1444 +#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "ROWS no es aplicable cuando una función no retorna un conjunto" -#: commands/functioncmds.c:1547 +#: commands/functioncmds.c:1546 #, c-format msgid "source data type %s is a pseudo-type" msgstr "el tipo de origen %s es un pseudotipo" -#: commands/functioncmds.c:1553 +#: commands/functioncmds.c:1552 #, c-format msgid "target data type %s is a pseudo-type" msgstr "el tipo de retorno %s es un pseudotipo" -#: commands/functioncmds.c:1577 +#: commands/functioncmds.c:1576 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "el cast será ignorado porque el tipo de datos de origen es un dominio" -#: commands/functioncmds.c:1582 +#: commands/functioncmds.c:1581 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "el cast será ignorado porque el tipo de datos de destino es un dominio" -#: commands/functioncmds.c:1607 +#: commands/functioncmds.c:1606 #, c-format msgid "cast function must take one to three arguments" msgstr "la función de conversión lleva de uno a tres argumentos" -#: commands/functioncmds.c:1613 +#: commands/functioncmds.c:1612 #, c-format msgid "argument of cast function must match or be binary-coercible from source data type" msgstr "el argumento de la función de conversión debe coincidir o ser binario-convertible con el tipo de origen" -#: commands/functioncmds.c:1617 +#: commands/functioncmds.c:1616 #, c-format msgid "second argument of cast function must be type %s" msgstr "el segundo argumento de la función de conversión debe ser de tipo %s" -#: commands/functioncmds.c:1622 +#: commands/functioncmds.c:1621 #, c-format msgid "third argument of cast function must be type %s" msgstr "el tercer argumento de la función de conversión debe ser de tipo %s" -#: commands/functioncmds.c:1629 +#: commands/functioncmds.c:1628 #, c-format msgid "return data type of cast function must match or be binary-coercible to target data type" msgstr "el tipo de salida de la función de conversión debe coincidir o ser binario-convertible con el tipo de retorno" -#: commands/functioncmds.c:1640 +#: commands/functioncmds.c:1639 #, c-format msgid "cast function must not be volatile" msgstr "la función de conversión no debe ser volatile" -#: commands/functioncmds.c:1645 +#: commands/functioncmds.c:1644 #, c-format msgid "cast function must be a normal function" msgstr "la función de conversión debe ser una función normal" -#: commands/functioncmds.c:1649 +#: commands/functioncmds.c:1648 #, c-format msgid "cast function must not return a set" msgstr "la función de conversión no debe retornar un conjunto" -#: commands/functioncmds.c:1675 +#: commands/functioncmds.c:1674 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "debe ser superusuario para crear una conversión sin especificar función" -#: commands/functioncmds.c:1690 +#: commands/functioncmds.c:1689 #, c-format msgid "source and target data types are not physically compatible" msgstr "los tipos de datos de origen y destino no son físicamente compatibles" -#: commands/functioncmds.c:1705 +#: commands/functioncmds.c:1709 #, c-format msgid "composite data types are not binary-compatible" msgstr "los tipos de datos compuestos no son binario-compatibles" -#: commands/functioncmds.c:1711 -#, c-format -msgid "enum data types are not binary-compatible" -msgstr "los tipos de datos enum no son binario-compatibles" - -#: commands/functioncmds.c:1717 +#: commands/functioncmds.c:1715 #, c-format msgid "array data types are not binary-compatible" msgstr "los tipos de datos de array no son binario-compatibles" -#: commands/functioncmds.c:1734 +#: commands/functioncmds.c:1723 +#, c-format +msgid "range data types are not binary-compatible" +msgstr "los tipos de datos de rango no son binario-compatibles" + +#: commands/functioncmds.c:1729 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "los tipos de datos enum no son binario-compatibles" + +#: commands/functioncmds.c:1746 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "los tipos de dato de dominio no deben ser marcados binario-compatibles" -#: commands/functioncmds.c:1744 +#: commands/functioncmds.c:1756 #, c-format msgid "source data type and target data type are the same" msgstr "el tipo de origen y el tipo de retorno son el mismo" -#: commands/functioncmds.c:1777 +#: commands/functioncmds.c:1789 #, c-format msgid "transform function must not be volatile" msgstr "la función de transformación no debe ser volatile" -#: commands/functioncmds.c:1781 +#: commands/functioncmds.c:1793 #, c-format msgid "transform function must be a normal function" msgstr "la función de transformación debe ser una función normal" -#: commands/functioncmds.c:1785 +#: commands/functioncmds.c:1797 #, c-format msgid "transform function must not return a set" msgstr "la función de transformación no debe retornar un conjunto" -#: commands/functioncmds.c:1789 +#: commands/functioncmds.c:1801 #, c-format msgid "transform function must take one argument" msgstr "la función de transformación debe recibir un argumento" -#: commands/functioncmds.c:1793 +#: commands/functioncmds.c:1805 #, c-format msgid "first argument of transform function must be type %s" msgstr "el primer argumento de la función de transformación debe ser de tipo %s" -#: commands/functioncmds.c:1832 +#: commands/functioncmds.c:1844 #, c-format msgid "data type %s is a pseudo-type" msgstr "el tipo de dato %s es un pseudo-tipo" -#: commands/functioncmds.c:1838 +#: commands/functioncmds.c:1850 #, c-format msgid "data type %s is a domain" msgstr "tipo de dato «%s» es un dominio" -#: commands/functioncmds.c:1878 +#: commands/functioncmds.c:1890 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "el tipo de dato de retorno de la función FROM SQL debe ser %s" -#: commands/functioncmds.c:1904 +#: commands/functioncmds.c:1916 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "el tipo de dato de retorno de la función TO SQL debe ser el tipo de dato de la transformación" -#: commands/functioncmds.c:1931 +#: commands/functioncmds.c:1943 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "la transformación para el tipo %s lenguaje «%s» ya existe" -#: commands/functioncmds.c:2017 +#: commands/functioncmds.c:2029 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "la transformación para el tipo %s lenguaje «%s» no existe" -#: commands/functioncmds.c:2041 +#: commands/functioncmds.c:2053 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "ya existe una función llamada %s en el esquema «%s»" -#: commands/functioncmds.c:2092 +#: commands/functioncmds.c:2104 #, c-format msgid "no inline code specified" msgstr "no se ha especificado código" -#: commands/functioncmds.c:2138 +#: commands/functioncmds.c:2150 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "el lenguaje «%s» no soporta ejecución de código en línea" -#: commands/functioncmds.c:2233 +#: commands/functioncmds.c:2245 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" msgstr[0] "no se pueden pasar más de %d argumento a un procedimiento" msgstr[1] "no se pueden pasar más de %d argumentos a un procedimiento" -#: commands/indexcmds.c:641 +#: commands/indexcmds.c:656 #, c-format msgid "must specify at least one column" msgstr "debe especificar al menos una columna" -#: commands/indexcmds.c:645 +#: commands/indexcmds.c:660 #, c-format msgid "cannot use more than %d columns in an index" msgstr "no se puede usar más de %d columnas en un índice" -#: commands/indexcmds.c:688 -#, fuzzy, c-format -#| msgid "cannot change relation \"%s\"" +#: commands/indexcmds.c:703 +#, c-format msgid "cannot create index on relation \"%s\"" -msgstr "no se puede cambiar la relación «%s»" +msgstr "no se puede crear índice en la relación «%s»" -#: commands/indexcmds.c:714 +#: commands/indexcmds.c:729 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "no se puede crear un índice en la tabla particionada «%s» concurrentemente" -#: commands/indexcmds.c:719 -#, c-format -msgid "cannot create exclusion constraints on partitioned table \"%s\"" -msgstr "no se pueden create restricciones de exclusión en la tabla particionada «%s»" - -#: commands/indexcmds.c:729 +#: commands/indexcmds.c:739 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "no se pueden crear índices en tablas temporales de otras sesiones" -#: commands/indexcmds.c:767 commands/tablecmds.c:784 commands/tablespace.c:1184 +#: commands/indexcmds.c:777 commands/tablecmds.c:818 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "no se puede especificar el tablespace por omisión para las relaciones particionadas" -#: commands/indexcmds.c:799 commands/tablecmds.c:819 commands/tablecmds.c:3409 +#: commands/indexcmds.c:809 commands/tablecmds.c:849 commands/tablecmds.c:3588 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "sólo relaciones compartidas pueden ser puestas en el tablespace pg_global" -#: commands/indexcmds.c:832 +#: commands/indexcmds.c:842 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "sustituyendo el método de acceso obsoleto «rtree» por «gist»" -#: commands/indexcmds.c:853 +#: commands/indexcmds.c:863 #, c-format msgid "access method \"%s\" does not support unique indexes" msgstr "el método de acceso «%s» no soporta índices únicos" -#: commands/indexcmds.c:858 +#: commands/indexcmds.c:868 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "el método de acceso «%s» no soporta columnas incluidas" -#: commands/indexcmds.c:863 +#: commands/indexcmds.c:873 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "el método de acceso «%s» no soporta índices multicolumna" -#: commands/indexcmds.c:868 +#: commands/indexcmds.c:878 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "el método de acceso «%s» no soporta restricciones de exclusión" -#: commands/indexcmds.c:995 +#: commands/indexcmds.c:1007 #, c-format msgid "cannot match partition key to an index using access method \"%s\"" msgstr "no se puede hacer coincidir la llave de partición a un índice usando el método de acceso «%s»" -#: commands/indexcmds.c:1005 +#: commands/indexcmds.c:1017 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "restricción %s no soportada con definición de llave de particionamiento" -#: commands/indexcmds.c:1007 +#: commands/indexcmds.c:1019 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "No se pueden usar restricciones %s cuando las llaves de particionamiento incluyen expresiones." -#: commands/indexcmds.c:1046 +#: commands/indexcmds.c:1069 +#, c-format +msgid "cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"" +msgstr "no se puede hacer coincidir la llave de partición en la columna «%s» usando el operador «%s» que no es igualdad" + +#: commands/indexcmds.c:1085 #, c-format msgid "unique constraint on partitioned table must include all partitioning columns" msgstr "las restricciones unique en tablas particionadas deben incluir todas las columnas de particionamiento" -#: commands/indexcmds.c:1047 +#: commands/indexcmds.c:1086 #, c-format msgid "%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key." msgstr "La restricción %s en la tabla «%s» no incluye la columna «%s» que es parte de la llave de particionamiento." -#: commands/indexcmds.c:1066 commands/indexcmds.c:1085 +#: commands/indexcmds.c:1105 commands/indexcmds.c:1124 #, c-format msgid "index creation on system columns is not supported" msgstr "la creación de índices en columnas de sistema no está soportada" -#: commands/indexcmds.c:1314 tcop/utility.c:1525 +#: commands/indexcmds.c:1354 tcop/utility.c:1515 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "no se puede crear un índice único en la tabla particionada «%s»" -#: commands/indexcmds.c:1316 tcop/utility.c:1527 +#: commands/indexcmds.c:1356 tcop/utility.c:1517 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "La tabla «%s» contiene particiones que son tablas foráneas." -#: commands/indexcmds.c:1811 +#: commands/indexcmds.c:1806 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "las funciones utilizadas en predicados de índice deben estar marcadas IMMUTABLE" -#: commands/indexcmds.c:1889 parser/parse_utilcmd.c:2513 -#: parser/parse_utilcmd.c:2648 +#: commands/indexcmds.c:1885 parser/parse_utilcmd.c:2519 +#: parser/parse_utilcmd.c:2654 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "no existe la columna «%s» en la llave" -#: commands/indexcmds.c:1913 parser/parse_utilcmd.c:1812 +#: commands/indexcmds.c:1909 parser/parse_utilcmd.c:1807 #, c-format msgid "expressions are not supported in included columns" msgstr "las expresiones no están soportadas en columnas incluidas" -#: commands/indexcmds.c:1954 +#: commands/indexcmds.c:1950 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "las funciones utilizadas en expresiones de índice deben estar marcadas IMMUTABLE" -#: commands/indexcmds.c:1969 +#: commands/indexcmds.c:1965 #, c-format msgid "including column does not support a collation" msgstr "la columna incluida no permite un ordenamiento (collation)" -#: commands/indexcmds.c:1973 +#: commands/indexcmds.c:1969 #, c-format msgid "including column does not support an operator class" msgstr "la columna incluida no permite una clase de operadores" -#: commands/indexcmds.c:1977 +#: commands/indexcmds.c:1973 #, c-format msgid "including column does not support ASC/DESC options" msgstr "la columna incluida no permite las opciones ASC/DESC" -#: commands/indexcmds.c:1981 +#: commands/indexcmds.c:1977 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "la columna incluida no permite las opciones NULLS FIRST/LAST" -#: commands/indexcmds.c:2022 +#: commands/indexcmds.c:2020 #, c-format msgid "could not determine which collation to use for index expression" msgstr "no se pudo determinar qué ordenamiento (collation) usar para la expresión de índice" -#: commands/indexcmds.c:2030 commands/tablecmds.c:17497 commands/typecmds.c:807 -#: parser/parse_expr.c:2722 parser/parse_type.c:568 parser/parse_utilcmd.c:3774 -#: utils/adt/misc.c:586 +#: commands/indexcmds.c:2028 commands/tablecmds.c:18185 commands/typecmds.c:811 +#: parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3771 +#: utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "los ordenamientos (collation) no están soportados por el tipo %s" @@ -8938,95 +9257,100 @@ msgstr "el método de acceso «%s» no soporta las opciones ASC/DESC" msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "el método de acceso «%s» no soporta las opciones NULLS FIRST/LAST" -#: commands/indexcmds.c:2212 commands/tablecmds.c:17522 -#: commands/tablecmds.c:17528 commands/typecmds.c:2301 +#: commands/indexcmds.c:2210 commands/tablecmds.c:18210 +#: commands/tablecmds.c:18216 commands/typecmds.c:2311 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "el tipo de dato %s no tiene una clase de operadores por omisión para el método de acceso «%s»" -#: commands/indexcmds.c:2214 +#: commands/indexcmds.c:2212 #, c-format msgid "You must specify an operator class for the index or define a default operator class for the data type." msgstr "Debe especificar una clase de operadores para el índice, o definir una clase de operadores por omisión para el tipo de datos." -#: commands/indexcmds.c:2243 commands/indexcmds.c:2251 +#: commands/indexcmds.c:2241 commands/indexcmds.c:2249 #: commands/opclasscmds.c:205 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "no existe la clase de operadores «%s» para el método de acceso «%s»" -#: commands/indexcmds.c:2265 commands/typecmds.c:2289 +#: commands/indexcmds.c:2263 commands/typecmds.c:2299 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "la clase de operadores «%s» no acepta el tipo de datos %s" -#: commands/indexcmds.c:2355 +#: commands/indexcmds.c:2353 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "hay múltiples clases de operadores por omisión para el tipo de datos %s" -#: commands/indexcmds.c:2683 +#: commands/indexcmds.c:2681 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "opción de REINDEX «%s» no reconocida" -#: commands/indexcmds.c:2910 +#: commands/indexcmds.c:2913 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "la tabla «%s» no tiene índices que puedan ser reindexados concurrentemente" -#: commands/indexcmds.c:2924 +#: commands/indexcmds.c:2927 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "la tabla «%s» no tiene índices para reindexar" -#: commands/indexcmds.c:2969 commands/indexcmds.c:3484 -#: commands/indexcmds.c:3612 +#: commands/indexcmds.c:2974 commands/indexcmds.c:3485 +#: commands/indexcmds.c:3615 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "no se pueden reindexar catálogos de sistema concurrentemente" -#: commands/indexcmds.c:2993 +#: commands/indexcmds.c:2998 #, c-format msgid "can only reindex the currently open database" msgstr "sólo se puede reindexar la base de datos actualmente abierta" -#: commands/indexcmds.c:3091 +#: commands/indexcmds.c:3090 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "no se puede reindexar un catálogo de sistema concurrentemente, omitiéndolos todos" -#: commands/indexcmds.c:3124 +#: commands/indexcmds.c:3123 #, c-format msgid "cannot move system relations, skipping all" msgstr "no se puede mover las relaciones de sistema, omitiendo todas" -#: commands/indexcmds.c:3170 +#: commands/indexcmds.c:3169 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "al reindexar tabla particionada «%s.%s»" -#: commands/indexcmds.c:3173 +#: commands/indexcmds.c:3172 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "al reindexar índice particionado «%s.%s»" -#: commands/indexcmds.c:3364 commands/indexcmds.c:4220 +#: commands/indexcmds.c:3365 commands/indexcmds.c:4241 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "la tabla «%s.%s» fue reindexada" -#: commands/indexcmds.c:3516 commands/indexcmds.c:3568 +#: commands/indexcmds.c:3517 commands/indexcmds.c:3570 #, c-format -msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" -msgstr "no se puede reindexar el índice no válido «%s.%s» concurrentemente, omitiendo" +msgid "skipping reindex of invalid index \"%s.%s\"" +msgstr "omitiendo reindexar índice no válido «%s.%s»" -#: commands/indexcmds.c:3522 +#: commands/indexcmds.c:3520 commands/indexcmds.c:3573 +#, c-format +msgid "Use DROP INDEX or REINDEX INDEX." +msgstr "Use DROP INDEX o REINDEX INDEX." + +#: commands/indexcmds.c:3524 #, c-format msgid "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" msgstr "no se puede reindexar el índice de restricción de exclusión «%s.%s» concurrentemente, omitiendo" -#: commands/indexcmds.c:3677 +#: commands/indexcmds.c:3680 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "no se puede reindexar este tipo de relación concurrentemente" @@ -9036,48 +9360,47 @@ msgstr "no se puede reindexar este tipo de relación concurrentemente" msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "no se puede mover relación no compartida al tablespace «%s»" -#: commands/indexcmds.c:4201 commands/indexcmds.c:4213 +#: commands/indexcmds.c:4222 commands/indexcmds.c:4234 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr "el índice «%s.%s» fue reindexado" -#: commands/indexcmds.c:4203 commands/indexcmds.c:4222 +#: commands/indexcmds.c:4224 commands/indexcmds.c:4243 #, c-format msgid "%s." msgstr "%s." -#: commands/lockcmds.c:93 -#, fuzzy, c-format -#| msgid "cannot lock rows in relation \"%s\"" +#: commands/lockcmds.c:91 +#, c-format msgid "cannot lock relation \"%s\"" -msgstr "no se puede bloquear registros en la tabla «%s»" +msgstr "no se puede bloquear la relación «%s»" -#: commands/matview.c:194 +#: commands/matview.c:206 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "no se puede usar CONCURRENTLY cuando la vista materializada no contiene datos" -#: commands/matview.c:200 gram.y:18307 +#: commands/matview.c:212 gram.y:18918 #, c-format msgid "%s and %s options cannot be used together" msgstr "las opciones %s y %s no pueden usarse juntas" -#: commands/matview.c:257 +#: commands/matview.c:269 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "no se puede refrescar la vista materializada «%s» concurrentemente" -#: commands/matview.c:260 +#: commands/matview.c:272 #, c-format msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view." msgstr "Cree un índice único sin cláusula WHERE en una o más columnas de la vista materializada." -#: commands/matview.c:654 +#: commands/matview.c:666 #, c-format msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns" msgstr "nuevos datos para la vista materializada «%s» contiene filas duplicadas sin columnas nulas" -#: commands/matview.c:656 +#: commands/matview.c:668 #, c-format msgid "Row: %s" msgstr "Fila: %s" @@ -9279,27 +9602,27 @@ msgstr "el número de operador %d para (%s,%s) aparece más de una vez" msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "ya existe un operador %d(%s,%s) en la familia de operadores «%s»" -#: commands/opclasscmds.c:1566 +#: commands/opclasscmds.c:1589 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "ya existe una función %d(%s,%s) en la familia de operador «%s»" -#: commands/opclasscmds.c:1647 +#: commands/opclasscmds.c:1744 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "no existe el operador %d(%s,%s) en la familia de operadores «%s»" -#: commands/opclasscmds.c:1687 +#: commands/opclasscmds.c:1784 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "no existe la función %d(%s,%s) en la familia de operadores «%s»" -#: commands/opclasscmds.c:1718 +#: commands/opclasscmds.c:1815 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "ya existe una clase de operadores «%s» para el método de acceso «%s» en el esquema «%s»" -#: commands/opclasscmds.c:1741 +#: commands/opclasscmds.c:1838 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "ya existe una familia de operadores «%s» para el método de acceso «%s» en el esquema «%s»" @@ -9309,7 +9632,7 @@ msgstr "ya existe una familia de operadores «%s» para el método de acceso «% msgid "SETOF type not allowed for operator argument" msgstr "no se permite un tipo SETOF en los argumentos de un operador" -#: commands/operatorcmds.c:154 commands/operatorcmds.c:481 +#: commands/operatorcmds.c:154 commands/operatorcmds.c:554 #, c-format msgid "operator attribute \"%s\" not recognized" msgstr "el atributo de operador «%s» no es reconocido" @@ -9349,53 +9672,70 @@ msgstr "la función de estimación de join %s tiene múltiples coincidencias" msgid "join estimator function %s must return type %s" msgstr "la función de estimación de join %s debe retornar tipo %s" -#: commands/operatorcmds.c:475 +#: commands/operatorcmds.c:388 parser/parse_oper.c:119 parser/parse_oper.c:637 +#: utils/adt/regproc.c:509 utils/adt/regproc.c:683 +#, c-format +msgid "operator does not exist: %s" +msgstr "el operador no existe: %s" + +#: commands/operatorcmds.c:396 parser/parse_oper.c:702 parser/parse_oper.c:815 +#, c-format +msgid "operator is only a shell: %s" +msgstr "el operador está inconcluso: %s" + +#: commands/operatorcmds.c:548 #, c-format msgid "operator attribute \"%s\" cannot be changed" msgstr "el atributo de operador «%s» no puede ser cambiado" -#: commands/policy.c:89 commands/policy.c:382 commands/statscmds.c:149 -#: commands/tablecmds.c:1616 commands/tablecmds.c:2219 -#: commands/tablecmds.c:3520 commands/tablecmds.c:6369 -#: commands/tablecmds.c:9181 commands/tablecmds.c:17090 -#: commands/tablecmds.c:17125 commands/trigger.c:323 commands/trigger.c:1339 -#: commands/trigger.c:1449 rewrite/rewriteDefine.c:275 -#: rewrite/rewriteDefine.c:786 rewrite/rewriteRemove.c:80 +#: commands/operatorcmds.c:615 commands/operatorcmds.c:622 +#: commands/operatorcmds.c:628 commands/operatorcmds.c:634 +#, c-format +msgid "operator attribute \"%s\" cannot be changed if it has already been set" +msgstr "el atributo de operador «%s» no puede ser cambiado si ya se ha establecido" + +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 +#: commands/tablecmds.c:1740 commands/tablecmds.c:2340 +#: commands/tablecmds.c:3702 commands/tablecmds.c:6605 +#: commands/tablecmds.c:9637 commands/tablecmds.c:17772 +#: commands/tablecmds.c:17807 commands/trigger.c:316 commands/trigger.c:1332 +#: commands/trigger.c:1442 rewrite/rewriteDefine.c:268 +#: rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "permiso denegado: «%s» es un catálogo de sistema" -#: commands/policy.c:172 +#: commands/policy.c:169 #, c-format msgid "ignoring specified roles other than PUBLIC" msgstr "ignorando los roles especificados que no son PUBLIC" -#: commands/policy.c:173 +#: commands/policy.c:170 #, c-format msgid "All roles are members of the PUBLIC role." msgstr "Todos los roles son miembros del rol PUBLIC." -#: commands/policy.c:606 +#: commands/policy.c:603 #, c-format msgid "WITH CHECK cannot be applied to SELECT or DELETE" msgstr "WITH CHECK no puede ser aplicado a SELECT o DELETE" -#: commands/policy.c:615 commands/policy.c:918 +#: commands/policy.c:612 commands/policy.c:915 #, c-format msgid "only WITH CHECK expression allowed for INSERT" msgstr "sólo se permite una expresión WITH CHECK para INSERT" -#: commands/policy.c:689 commands/policy.c:1141 +#: commands/policy.c:686 commands/policy.c:1138 #, c-format msgid "policy \"%s\" for table \"%s\" already exists" msgstr "la política «%s» para la tabla «%s» ya existe" -#: commands/policy.c:890 commands/policy.c:1169 commands/policy.c:1240 +#: commands/policy.c:887 commands/policy.c:1166 commands/policy.c:1237 #, c-format msgid "policy \"%s\" for table \"%s\" does not exist" msgstr "no existe la política «%s» para la tabla «%s»" -#: commands/policy.c:908 +#: commands/policy.c:905 #, c-format msgid "only USING expression allowed for SELECT, DELETE" msgstr "sólo se permite una expresión USING para SELECT, DELETE" @@ -9411,270 +9751,244 @@ msgid "cannot create a cursor WITH HOLD within security-restricted operation" msgstr "no se puede crear un cursor WITH HOLD dentro de una operación restringida por seguridad" #: commands/portalcmds.c:189 commands/portalcmds.c:242 -#: executor/execCurrent.c:70 utils/adt/xml.c:2844 utils/adt/xml.c:3014 +#: executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "no existe el cursor «%s»" -#: commands/prepare.c:75 +#: commands/prepare.c:72 #, c-format msgid "invalid statement name: must not be empty" msgstr "el nombre de sentencia no es válido: no debe ser vacío" -#: commands/prepare.c:230 commands/prepare.c:235 +#: commands/prepare.c:227 commands/prepare.c:232 #, c-format msgid "prepared statement is not a SELECT" msgstr "la sentencia preparada no es un SELECT" -#: commands/prepare.c:295 +#: commands/prepare.c:292 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "el número de parámetros es incorrecto en la sentencia preparada «%s»" -#: commands/prepare.c:297 +#: commands/prepare.c:294 #, c-format msgid "Expected %d parameters but got %d." msgstr "Se esperaban %d parámetros pero se obtuvieron %d." -#: commands/prepare.c:330 +#: commands/prepare.c:327 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "el parámetro $%d de tipo %s no puede ser convertido al tipo esperado %s" -#: commands/prepare.c:414 +#: commands/prepare.c:411 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "la sentencia preparada «%s» ya existe" -#: commands/prepare.c:453 +#: commands/prepare.c:450 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "no existe la sentencia preparada «%s»" -#: commands/proclang.c:68 +#: commands/proclang.c:66 #, c-format msgid "must be superuser to create custom procedural language" msgstr "debe ser superusuario para crear un lenguaje procedural personalizado" -#: commands/publicationcmds.c:131 postmaster/postmaster.c:1205 -#: postmaster/postmaster.c:1303 storage/file/fd.c:3861 -#: utils/init/miscinit.c:1815 +#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 +#: postmaster/postmaster.c:1210 utils/init/miscinit.c:1865 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "la sintaxis de lista no es válida para el parámetro «%s»" -#: commands/publicationcmds.c:150 -#, fuzzy, c-format -#| msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" +#: commands/publicationcmds.c:143 +#, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" -msgstr "valor no reconocido para la opción de EXPLAIN «%s»: «%s»" +msgstr "valor no reconocido para la opción de publicación «%s»: «%s»" -#: commands/publicationcmds.c:164 +#: commands/publicationcmds.c:157 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "parámetro de publicación no reconocido: «%s»" -#: commands/publicationcmds.c:205 -#, fuzzy, c-format -#| msgid "no schema has been selected to create in" +#: commands/publicationcmds.c:198 +#, c-format msgid "no schema has been selected for CURRENT_SCHEMA" -msgstr "no se ha seleccionado ningún esquema dentro del cual crear" +msgstr "no se ha seleccionado ningún esquema para CURRENT_SCHEMA" -#: commands/publicationcmds.c:502 -#, fuzzy -#| msgid "System catalog modifications are currently disallowed." +#: commands/publicationcmds.c:495 msgid "System columns are not allowed." -msgstr "Las modificaciones al catálogo del sistema están actualmente deshabilitadas." +msgstr "Las columnas de sistema no son permitidas." -#: commands/publicationcmds.c:509 commands/publicationcmds.c:514 -#: commands/publicationcmds.c:531 -#, fuzzy -#| msgid "grouping operations are not allowed in %s" +#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 +#: commands/publicationcmds.c:524 msgid "User-defined operators are not allowed." -msgstr "no se permiten operaciones «grouping» en %s" +msgstr "Los operadores definidos por el usuario no están permitidos." -#: commands/publicationcmds.c:555 +#: commands/publicationcmds.c:548 msgid "Only columns, constants, built-in operators, built-in data types, built-in collations, and immutable built-in functions are allowed." -msgstr "" +msgstr "Sólo columnas, constantes, operadores built-in, tipos de datos built-in, configuraciones regionales built-in y funciones built-in inmutables son permitidas." -#: commands/publicationcmds.c:567 -#, fuzzy -#| msgid "set-returning functions are not allowed in %s" +#: commands/publicationcmds.c:560 msgid "User-defined types are not allowed." -msgstr "no se permiten funciones que retornan conjuntos en %s" +msgstr "Los tipos definidos por el usuario no están permitidos." -#: commands/publicationcmds.c:570 -#, fuzzy -#| msgid "set-returning functions are not allowed in %s" +#: commands/publicationcmds.c:563 msgid "User-defined or built-in mutable functions are not allowed." -msgstr "no se permiten funciones que retornan conjuntos en %s" +msgstr "Las funciones definidas por el usuario, o las que son mutables, no están permitidas." -#: commands/publicationcmds.c:573 -#, fuzzy -#| msgid "set-returning functions are not allowed in %s" +#: commands/publicationcmds.c:566 msgid "User-defined collations are not allowed." -msgstr "no se permiten funciones que retornan conjuntos en %s" +msgstr "Los «collations» definidos por el usuario no están permitidos." -#: commands/publicationcmds.c:583 -#, fuzzy, c-format -#| msgid "invalid publication_names syntax" +#: commands/publicationcmds.c:576 +#, c-format msgid "invalid publication WHERE expression" -msgstr "sintaxis de publication_names no válida" +msgstr "sintaxis de cláusula WHERE de publicación no válida" -#: commands/publicationcmds.c:636 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#: commands/publicationcmds.c:629 +#, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "no se puede usar cláusula WHERE de la publicación para la relación «%s»" -#: commands/publicationcmds.c:638 +#: commands/publicationcmds.c:631 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." -msgstr "" +msgstr "la cláusula WHERE no puede ser usada para una tabla particionada cuando %s es falso." -#: commands/publicationcmds.c:709 commands/publicationcmds.c:723 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 +#, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "no se puede usar lista de columnas para la relación «%s.%s» en la publicación «%s»" -#: commands/publicationcmds.c:712 +#: commands/publicationcmds.c:705 #, c-format msgid "Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements." -msgstr "" +msgstr "Las listas de columnas no pueden ser especificadas en publicaciones que contienen elementos FOR TABLES IN SCHEMA." -#: commands/publicationcmds.c:726 +#: commands/publicationcmds.c:719 #, c-format msgid "Column lists cannot be specified for partitioned tables when %s is false." -msgstr "" +msgstr "Las listas de columnas no pueden ser especificadas para tablas particionadas cuando %s es falso." -#: commands/publicationcmds.c:761 +#: commands/publicationcmds.c:754 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "debe ser superusuario para crear publicaciones FOR ALL TABLES" -#: commands/publicationcmds.c:832 -#, fuzzy, c-format -#| msgid "must be superuser to create FOR ALL TABLES publication" +#: commands/publicationcmds.c:825 +#, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" -msgstr "debe ser superusuario para crear publicaciones FOR ALL TABLES" +msgstr "debe ser superusuario para crear publicaciones FOR TABLES IN SCHEMA" -#: commands/publicationcmds.c:868 +#: commands/publicationcmds.c:861 #, c-format -msgid "wal_level is insufficient to publish logical changes" -msgstr "wal_level es insuficiente para publicar cambios lógicos" +msgid "\"wal_level\" is insufficient to publish logical changes" +msgstr "«wal_level» es insuficiente para publicar cambios lógicos" -#: commands/publicationcmds.c:869 -#, fuzzy, c-format -#| msgid "Change wal_level to be logical or higher." -msgid "Set wal_level to \"logical\" before creating subscriptions." -msgstr "Cambie wal_level a logical o superior." +#: commands/publicationcmds.c:862 +#, c-format +msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." +msgstr "Cambie «wal_level» a «logical» antes de crear suscripciones." -#: commands/publicationcmds.c:965 commands/publicationcmds.c:973 -#, fuzzy, c-format -#| msgid "cannot set parameter \"%s\" within security-definer function" +#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 +#, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" -msgstr "no se puede definir el parámetro «%s» dentro una función security-definer" +msgstr "no se puede definir el parámetro «%s» a falso para la publicación «%s»" -#: commands/publicationcmds.c:968 +#: commands/publicationcmds.c:961 #, c-format msgid "The publication contains a WHERE clause for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "La publicación contiene una cláusula WHERE para la tabla particionada «%s», que no está permitido cuando «%s» es falso." -#: commands/publicationcmds.c:976 +#: commands/publicationcmds.c:969 #, c-format msgid "The publication contains a column list for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "La publicación contiene una lista de columns para la tabla particionada «%s», que no está permitido cuando «%s» es falso." -#: commands/publicationcmds.c:1299 -#, fuzzy, c-format -#| msgid "cannot add schema \"%s\" to publication" +#: commands/publicationcmds.c:1292 +#, c-format msgid "cannot add schema to publication \"%s\"" -msgstr "no se puede agregar el esquema «%s» a la partición" +msgstr "no se puede agregar el esquema «%s» a la publicación" -#: commands/publicationcmds.c:1301 +#: commands/publicationcmds.c:1294 #, c-format msgid "Schemas cannot be added if any tables that specify a column list are already part of the publication." -msgstr "" +msgstr "Los esquemas no pueden ser añadidos si alguna tabla que especifica una lista de columnas ya es parte de la publicación." -#: commands/publicationcmds.c:1349 +#: commands/publicationcmds.c:1342 #, c-format msgid "must be superuser to add or set schemas" msgstr "debe ser superusuario para agregar o definir esquemas" -#: commands/publicationcmds.c:1358 commands/publicationcmds.c:1366 +#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "la publicación \"%s\" se define como FOR ALL TABLES" -#: commands/publicationcmds.c:1360 -#, fuzzy, c-format -#| msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." +#: commands/publicationcmds.c:1353 +#, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." -msgstr "Las tablas no se pueden agregar ni eliminar de las publicaciones FOR ALL TABLES." +msgstr "No se pueden agregar ni eliminar esquemas de las publicaciones FOR ALL TABLES." -#: commands/publicationcmds.c:1368 +#: commands/publicationcmds.c:1361 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "Las tablas no se pueden agregar ni eliminar de las publicaciones FOR ALL TABLES." -#: commands/publicationcmds.c:1392 commands/publicationcmds.c:1431 -#: commands/publicationcmds.c:1968 utils/cache/lsyscache.c:3592 +#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 +#: commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 #, c-format msgid "publication \"%s\" does not exist" msgstr "no existe la publicación «%s»" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1657 -#, fuzzy, c-format -#| msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" +#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 +#, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" -msgstr "declaraciones NULL/NOT NULL en conflicto o redundantes para la columna «%s»" +msgstr "cláusulas WHERE en conflicto o redundantes para la tabla «%s»" -#: commands/publicationcmds.c:1601 commands/publicationcmds.c:1669 -#, fuzzy, c-format -#| msgid "conflicting or redundant options" +#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 +#, c-format msgid "conflicting or redundant column lists for table \"%s\"" -msgstr "opciones contradictorias o redundantes" +msgstr "listas de columnas contradictorias o redundantes para la tabla «%s»" -#: commands/publicationcmds.c:1803 -#, fuzzy, c-format -#| msgid "operator argument types must be specified in ALTER OPERATOR FAMILY" +#: commands/publicationcmds.c:1796 +#, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" -msgstr "los tipos de los argumentos de operador deben ser especificados en ALTER OPERATOR FAMILY" +msgstr "la lista de columnas no debe ser especificada en ALTER PUBLICATION ... DROP" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1808 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "relación «%s» no es parte de la publicación" -#: commands/publicationcmds.c:1822 +#: commands/publicationcmds.c:1815 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "no se puede usar una cláusula WHERE cuando se elimina una tabla de una publicación" -#: commands/publicationcmds.c:1882 -#, fuzzy, c-format -#| msgid "relation \"%s\" is not part of the publication" +#: commands/publicationcmds.c:1875 +#, c-format msgid "tables from schema \"%s\" are not part of the publication" -msgstr "relación «%s» no es parte de la publicación" +msgstr "las tablas del esquema «%s» no son parte de la publicación" -#: commands/publicationcmds.c:1925 commands/publicationcmds.c:1932 +#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 #, c-format msgid "permission denied to change owner of publication \"%s\"" msgstr "se ha denegado el permiso para cambiar el dueño de la publicación «%s»" -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:1920 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "El dueño de una publicación FOR ALL TABLES debe ser un superusuario." -#: commands/publicationcmds.c:1934 -#, fuzzy, c-format -#| msgid "The owner of a FOR ALL TABLES publication must be a superuser." +#: commands/publicationcmds.c:1927 +#, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." -msgstr "El dueño de una publicación FOR ALL TABLES debe ser un superusuario." +msgstr "El dueño de una publicación FOR TABLES IN SCHEMA debe ser un superusuario." -#: commands/publicationcmds.c:2000 +#: commands/publicationcmds.c:1993 #, c-format msgid "publication with OID %u does not exist" msgstr "no existe la publicación con OID %u" @@ -9715,3263 +10029,3266 @@ msgid "security labels are not supported for this type of object" msgstr "las etiquetas de seguirdad no están soportadas para este tipo de objeto" #: commands/seclabel.c:193 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#, c-format msgid "cannot set security label on relation \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "no se puede definir la etiqueta de seguridad en la relación «%s»" -#: commands/sequence.c:754 +#: commands/sequence.c:748 #, c-format msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" -msgstr "" +msgstr "nextval: se alcanzó el valor máximo de la secuencia «%s» (%lld)" -#: commands/sequence.c:773 +#: commands/sequence.c:767 #, c-format msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" -msgstr "" +msgstr "nextval: se alcanzó el valor mínimo de la secuencia «%s» (%lld)" -#: commands/sequence.c:891 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "currval de la secuencia «%s» no está definido en esta sesión" -#: commands/sequence.c:910 commands/sequence.c:916 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "lastval no está definido en esta sesión" -#: commands/sequence.c:996 -#, fuzzy, c-format -#| msgid "value %s out of bounds for option \"%s\"" +#: commands/sequence.c:991 +#, c-format msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" -msgstr "el valor %s está fuera del rango de la opción «%s»" +msgstr "setval: el valor %lld está fuera del rango para la secuencia «%s» (%lld..%lld)" -#: commands/sequence.c:1365 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "opción de secuencia no válida SEQUENCE NAME" -#: commands/sequence.c:1391 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "el tipo de columna de identidad debe ser smallint, integer o bigint" -#: commands/sequence.c:1392 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "el tipo de secuencia debe ser smallint, integer o bigint" -#: commands/sequence.c:1426 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENT no debe ser cero" -#: commands/sequence.c:1474 -#, fuzzy, c-format -#| msgid "value \"%s\" is out of range for type %s" +#: commands/sequence.c:1466 +#, c-format msgid "MAXVALUE (%lld) is out of range for sequence data type %s" -msgstr "el valor «%s» está fuera de rango para el tipo %s" +msgstr "el MAXVALUE (%lld) está fuera de rango para el tipo de la secuencia %s" -#: commands/sequence.c:1506 -#, fuzzy, c-format -#| msgid "value \"%s\" is out of range for type %s" +#: commands/sequence.c:1498 +#, c-format msgid "MINVALUE (%lld) is out of range for sequence data type %s" -msgstr "el valor «%s» está fuera de rango para el tipo %s" +msgstr "el MINVALUE (%lld) está fuera de rango para el tipo de la secuencia %s" -#: commands/sequence.c:1514 +#: commands/sequence.c:1506 #, c-format msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" -msgstr "" +msgstr "MINVALUE (%lld) debe ser menor que MAXVALUE (%lld)" -#: commands/sequence.c:1535 +#: commands/sequence.c:1527 #, c-format msgid "START value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "" +msgstr "el valor START (%lld) no puede ser menor que MINVALUE (%lld)" -#: commands/sequence.c:1541 +#: commands/sequence.c:1533 #, c-format msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "" +msgstr "el valor START (%lld) no puede ser mayor que el MAXVALUE (%lld)" -#: commands/sequence.c:1565 +#: commands/sequence.c:1557 #, c-format msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "" +msgstr "el valor RESTART (%lld) no puede ser menor que MINVALUE (%lld)" -#: commands/sequence.c:1571 +#: commands/sequence.c:1563 #, c-format msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "" +msgstr "el valor RESTART (%lld) no puede ser mayor que MAXVALUE (%lld)" -#: commands/sequence.c:1582 -#, fuzzy, c-format -#| msgid "stride must be greater than zero" +#: commands/sequence.c:1574 +#, c-format msgid "CACHE (%lld) must be greater than zero" -msgstr "el intervalo de paso (stride) debe ser mayor que cero" +msgstr "el CACHE (%lld) debe ser mayor que cero" -#: commands/sequence.c:1618 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "opción OWNED BY no válida" -#: commands/sequence.c:1619 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "Especifique OWNED BY tabla.columna o OWNED BY NONE." -#: commands/sequence.c:1644 -#, fuzzy, c-format -#| msgid "cannot move system relation \"%s\"" +#: commands/sequence.c:1636 +#, c-format msgid "sequence cannot be owned by relation \"%s\"" -msgstr "no se puede mover la relación de sistema «%s»" +msgstr "la secuencia no puede ser poseída por la relación «%s»" -#: commands/sequence.c:1652 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "la secuencia debe tener el mismo dueño que la tabla a la que está enlazada" -#: commands/sequence.c:1656 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "la secuencia debe estar en el mismo esquema que la tabla a la que está enlazada" -#: commands/sequence.c:1678 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "no se puede cambiar el dueño de la secuencia de identidad" -#: commands/sequence.c:1679 commands/tablecmds.c:13891 -#: commands/tablecmds.c:16488 +#: commands/sequence.c:1671 commands/tablecmds.c:14486 +#: commands/tablecmds.c:17181 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "La secuencia «%s» está enlazada a la tabla «%s»." -#: commands/statscmds.c:109 commands/statscmds.c:118 tcop/utility.c:1886 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "sólo se permite una relación en CREATE STATISTICS" -#: commands/statscmds.c:136 -#, fuzzy, c-format -#| msgid "cannot rewrite system relation \"%s\"" +#: commands/statscmds.c:133 +#, c-format msgid "cannot define statistics for relation \"%s\"" -msgstr "no se puede reescribir la relación de sistema «%s»" +msgstr "no se puede definir estadísticas para la relación «%s»" -#: commands/statscmds.c:190 +#: commands/statscmds.c:187 #, c-format msgid "statistics object \"%s\" already exists, skipping" msgstr "el objeto de estadísticas «%s» ya existe, omitiendo" -#: commands/statscmds.c:198 +#: commands/statscmds.c:195 #, c-format msgid "statistics object \"%s\" already exists" msgstr "el objeto de estadísticas «%s» ya existe" -#: commands/statscmds.c:209 +#: commands/statscmds.c:206 #, c-format msgid "cannot have more than %d columns in statistics" msgstr "no se puede tener más de %d columnas en estadísticas" -#: commands/statscmds.c:250 commands/statscmds.c:273 commands/statscmds.c:307 +#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 #, c-format msgid "statistics creation on system columns is not supported" msgstr "la creación de estadísticas en columnas de sistema no está soportada" -#: commands/statscmds.c:257 commands/statscmds.c:280 +#: commands/statscmds.c:254 commands/statscmds.c:277 #, c-format msgid "column \"%s\" cannot be used in statistics because its type %s has no default btree operator class" msgstr "la columna «%s» no puede ser usado en estadísticas porque su tipo %s no tiene una clase de operadores por omisión para btree" -#: commands/statscmds.c:324 +#: commands/statscmds.c:321 #, c-format msgid "expression cannot be used in multivariate statistics because its type %s has no default btree operator class" msgstr "la expresión no puede ser usada en estadísticas multivariantes porque su tipo %s no tiene una clase de operadores por omisión para btree" -#: commands/statscmds.c:345 +#: commands/statscmds.c:342 #, c-format msgid "when building statistics on a single expression, statistics kinds may not be specified" msgstr "al crear estadísticas sobre una sola expresión, no se deben especificar tipos de estadísticas" -#: commands/statscmds.c:374 +#: commands/statscmds.c:371 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "tipo de estadísticas «%s» no reconocido" -#: commands/statscmds.c:403 +#: commands/statscmds.c:400 #, c-format msgid "extended statistics require at least 2 columns" msgstr "las estadísticas extendidas requieren al menos 2 columnas" -#: commands/statscmds.c:421 +#: commands/statscmds.c:418 #, c-format msgid "duplicate column name in statistics definition" msgstr "nombre de columna duplicado en definición de estadísticas" -#: commands/statscmds.c:456 +#: commands/statscmds.c:453 #, c-format msgid "duplicate expression in statistics definition" msgstr "expresión duplicada en definición de estadísticas" -#: commands/statscmds.c:619 commands/tablecmds.c:8180 +#: commands/statscmds.c:628 commands/tablecmds.c:8620 #, c-format msgid "statistics target %d is too low" msgstr "el valor de estadísticas %d es demasiado bajo" -#: commands/statscmds.c:627 commands/tablecmds.c:8188 +#: commands/statscmds.c:636 commands/tablecmds.c:8628 #, c-format msgid "lowering statistics target to %d" msgstr "bajando el valor de estadísticas a %d" -#: commands/statscmds.c:650 +#: commands/statscmds.c:660 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "no existe el objeto de estadísticas «%s.%s», omitiendo" -#: commands/subscriptioncmds.c:271 commands/subscriptioncmds.c:359 +#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 #, c-format msgid "unrecognized subscription parameter: \"%s\"" msgstr "parámetro de suscripción no reconocido: «%s»" -#: commands/subscriptioncmds.c:327 replication/pgoutput/pgoutput.c:398 -#, fuzzy, c-format -#| msgid "unrecognized section name: \"%s\"" +#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:404 +#, c-format msgid "unrecognized origin value: \"%s\"" -msgstr "nombre de sección «%s» no reconocido" +msgstr "valor de origen no reconocido: «%s»" -#: commands/subscriptioncmds.c:350 -#, fuzzy, c-format -#| msgid "invalid WAL location: \"%s\"" +#: commands/subscriptioncmds.c:363 +#, c-format msgid "invalid WAL location (LSN): %s" -msgstr "ubicación de WAL no válida: «%s»" +msgstr "ubicación de WAL (LSN) no válida: %s" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:374 commands/subscriptioncmds.c:381 -#: commands/subscriptioncmds.c:388 commands/subscriptioncmds.c:410 -#: commands/subscriptioncmds.c:426 +#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 +#: commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 +#: commands/subscriptioncmds.c:439 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "%s y %s son opciones mutuamente excluyentes" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:416 commands/subscriptioncmds.c:432 +#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 #, c-format msgid "subscription with %s must also set %s" msgstr "suscripción con %s también debe activar %s" -#: commands/subscriptioncmds.c:494 -#, fuzzy, c-format -#| msgid "could not receive list of replicated tables from the publisher: %s" +#: commands/subscriptioncmds.c:506 +#, c-format msgid "could not receive list of publications from the publisher: %s" -msgstr "no se pudo recibir la lista de tablas replicadas desde el editor (publisher): %s" +msgstr "no se pudo recibir la lista de publicaciones desde el publicador: %s" -#: commands/subscriptioncmds.c:526 -#, fuzzy, c-format -#| msgid "publication \"%s\" does not exist" +#: commands/subscriptioncmds.c:538 +#, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" -msgstr[0] "no existe la publicación «%s»" -msgstr[1] "no existe la publicación «%s»" +msgstr[0] "no existe la publicación «%s» en el “publisher”" +msgstr[1] "no existen las publicaciones «%s» en el “publisher”" -#: commands/subscriptioncmds.c:614 -#, fuzzy, c-format -#| msgid "permission denied for subscription %s" +#: commands/subscriptioncmds.c:626 +#, c-format msgid "permission denied to create subscription" -msgstr "permiso denegado a la suscripción %s" +msgstr "permiso denegado a crear suscripción" -#: commands/subscriptioncmds.c:615 +#: commands/subscriptioncmds.c:627 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." -msgstr "" +msgstr "Sólo los roles con privilegio del rol «%s» pueden crear suscripciones." -#: commands/subscriptioncmds.c:745 commands/subscriptioncmds.c:878 -#: replication/logical/tablesync.c:1304 replication/logical/worker.c:4616 +#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 +#: commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 +#: replication/logical/worker.c:4503 #, c-format msgid "could not connect to the publisher: %s" -msgstr "no se pudo connectar con el editor (publisher): %s" +msgstr "no se pudo connectar con el publicador: %s" -#: commands/subscriptioncmds.c:816 +#: commands/subscriptioncmds.c:829 #, c-format msgid "created replication slot \"%s\" on publisher" -msgstr "se creó el slot de replicación «%s» en el editor (publisher)" +msgstr "se creó el slot de replicación «%s» en el publicador" -#: commands/subscriptioncmds.c:828 -#, fuzzy, c-format -#| msgid "subscription has no replication slot set" +#: commands/subscriptioncmds.c:841 +#, c-format msgid "subscription was created, but is not connected" -msgstr "la suscripción no tiene un slot de replicación establecido" +msgstr "la suscripción fue creada, pero no está conectada" -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:842 #, c-format msgid "To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription." -msgstr "" +msgstr "Para iniciar la replicacióñ, debe manualmente crear el slot de replicación, activar la suscripción, y refrescar la suscripción." -#: commands/subscriptioncmds.c:1096 commands/subscriptioncmds.c:1502 -#: commands/subscriptioncmds.c:1885 utils/cache/lsyscache.c:3642 +#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 +#: commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 #, c-format msgid "subscription \"%s\" does not exist" msgstr "no existe la suscripción «%s»" -#: commands/subscriptioncmds.c:1152 +#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 #, c-format msgid "cannot set %s for enabled subscription" msgstr "no se puede establecer %s para la suscripción activada" -#: commands/subscriptioncmds.c:1227 +#: commands/subscriptioncmds.c:1233 +#, c-format +msgid "cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "no se puede definir la opción «%s” para una suscripción que no tiene un nombre de slot" + +#: commands/subscriptioncmds.c:1279 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "no se puede habilitar la suscripción que no tiene un nombre de slot" -#: commands/subscriptioncmds.c:1271 commands/subscriptioncmds.c:1322 +#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 #, c-format msgid "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION con actualización no está permitido para las suscripciones desactivadas" -#: commands/subscriptioncmds.c:1272 +#: commands/subscriptioncmds.c:1324 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." -#: commands/subscriptioncmds.c:1281 commands/subscriptioncmds.c:1336 -#, fuzzy, c-format -#| msgid "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" +#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 +#, c-format msgid "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase is enabled" -msgstr "ALTER SUBSCRIPTION con actualización no está permitido para las suscripciones desactivadas" +msgstr "ALTER SUBSCRIPTION con «refresh» y «copy_data» no está permitido cuando «two_phase» está activo" -#: commands/subscriptioncmds.c:1282 -#, fuzzy, c-format -#| msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." +#: commands/subscriptioncmds.c:1334 +#, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." -msgstr "Use ALTER SUBSCRIPTION ... REFRESH con copy_data = false, o use DROP/CREATE SUBSCRIPTION." - -#. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1324 -#, fuzzy, c-format -#| msgid "Use views instead." -msgid "Use %s instead." -msgstr "Use vistas en su lugar." +msgstr "Use ALTER SUBSCRIPTION ... SET PUBLICATION con refresh = false, o con copy_data=false, o use DROP/CREATE SUBSCRIPTION." #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1338 -#, fuzzy, c-format -#| msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." +#: commands/subscriptioncmds.c:1390 +#, c-format msgid "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." -msgstr "Use ALTER SUBSCRIPTION ... REFRESH con copy_data = false, o use DROP/CREATE SUBSCRIPTION." +msgstr "Use %s con refresh = false, o con copy_data = false, o use DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1360 +#: commands/subscriptioncmds.c:1412 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION ... REFRESH no está permitido para las suscripciones desactivadas" -#: commands/subscriptioncmds.c:1385 -#, fuzzy, c-format -#| msgid "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" +#: commands/subscriptioncmds.c:1437 +#, c-format msgid "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase is enabled" -msgstr "ALTER SUBSCRIPTION ... REFRESH no está permitido para las suscripciones desactivadas" +msgstr "ALTER SUBSCRIPTION ... REFRESH con copy_data no está permitido cuando two_phase está activo" -#: commands/subscriptioncmds.c:1386 +#: commands/subscriptioncmds.c:1438 #, c-format msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "Use ALTER SUBSCRIPTION ... REFRESH con copy_data = false, o use DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1421 +#: commands/subscriptioncmds.c:1473 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "la ubicación de WAL a saltar (LSN %X/%X) debe ser mayor que el LSN de origen %X/%X" -#: commands/subscriptioncmds.c:1506 +#: commands/subscriptioncmds.c:1594 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "no existe la suscripción «%s», omitiendo" -#: commands/subscriptioncmds.c:1775 +#: commands/subscriptioncmds.c:1863 #, c-format msgid "dropped replication slot \"%s\" on publisher" -msgstr "eliminando el slot de replicación «%s» en editor (publisher)" +msgstr "eliminando el slot de replicación «%s» en publicador" -#: commands/subscriptioncmds.c:1784 commands/subscriptioncmds.c:1792 +#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" -msgstr "no se pudo eliminar el slot de replicación «%s» en editor (publisher): %s" +msgstr "no se pudo eliminar el slot de replicación «%s» en publicador: %s" -#: commands/subscriptioncmds.c:1917 +#: commands/subscriptioncmds.c:2005 #, c-format msgid "subscription with OID %u does not exist" msgstr "no existe la suscripción con OID %u" -#: commands/subscriptioncmds.c:1988 commands/subscriptioncmds.c:2113 +#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" -msgstr "no se pudo recibir la lista de tablas replicadas desde el editor (publisher): %s" +msgstr "no se pudo recibir la lista de tablas replicadas desde el publicador: %s" -#: commands/subscriptioncmds.c:2024 +#: commands/subscriptioncmds.c:2112 #, c-format msgid "subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin" -msgstr "" +msgstr "la suscripción «%s» pidió copy_data con origin = NONE pero podría copiar datos que tenían un origen diferente" -#: commands/subscriptioncmds.c:2026 -#, fuzzy, c-format -#| msgid "relation \"%s\" is not part of the publication" -msgid "Subscribed publication %s is subscribing to other publications." -msgid_plural "Subscribed publications %s are subscribing to other publications." -msgstr[0] "relación «%s» no es parte de la publicación" -msgstr[1] "relación «%s» no es parte de la publicación" +#: commands/subscriptioncmds.c:2114 +#, c-format +msgid "The subscription being created subscribes to a publication (%s) that contains tables that are written to by other subscriptions." +msgid_plural "The subscription being created subscribes to publications (%s) that contain tables that are written to by other subscriptions." +msgstr[0] "La suscripción que está siendo creada suscribe a una publicación (%s) que contiene tablas que están siendo escritas por otras suscripciones." +msgstr[1] "La suscripción que está siendo creada suscribe a publicaciones (%s) que contienen tablas que están siendo escritas por otras suscripciones." -#: commands/subscriptioncmds.c:2029 +#: commands/subscriptioncmds.c:2117 #, c-format msgid "Verify that initial data copied from the publisher tables did not come from other origins." -msgstr "" +msgstr "Verifique que los datos iniciales copiados desde el publicador no vinieron de otros orígenes." -#: commands/subscriptioncmds.c:2135 replication/logical/tablesync.c:875 -#: replication/pgoutput/pgoutput.c:1115 -#, fuzzy, c-format -#| msgid "cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"" +#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 +#: replication/pgoutput/pgoutput.c:1143 +#, c-format msgid "cannot use different column lists for table \"%s.%s\" in different publications" -msgstr "no se puede usar ONLY para una llave foránea en la tabla particionada «%s» haciendo referencia a la relación «%s»" +msgstr "no se puede usar distintas listas de columnas para la tabla «%s.%s» en distintas publicaciones" -#: commands/subscriptioncmds.c:2185 +#: commands/subscriptioncmds.c:2273 #, c-format msgid "could not connect to publisher when attempting to drop replication slot \"%s\": %s" -msgstr "no se pudo conectar con el editor (publisher) al intentar eliminar el slot de replicación \"%s\": %s" +msgstr "no se pudo conectar con el publicador al intentar eliminar el slot de replicación \"%s\": %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2188 +#: commands/subscriptioncmds.c:2276 #, c-format -msgid "Use %s to disassociate the subscription from the slot." -msgstr "Use %s para disociar la suscripción del slot." +msgid "Use %s to disable the subscription, and then use %s to disassociate it from the slot." +msgstr "Use %s para desactivar la suscripción, luego use %s para disociarla del slot." -#: commands/subscriptioncmds.c:2218 +#: commands/subscriptioncmds.c:2307 #, c-format msgid "publication name \"%s\" used more than once" msgstr "nombre de publicación «%s» usado más de una vez" -#: commands/subscriptioncmds.c:2262 +#: commands/subscriptioncmds.c:2351 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "la publicación «%s» ya existe en la suscripción «%s»" -#: commands/subscriptioncmds.c:2276 +#: commands/subscriptioncmds.c:2365 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "la publicación «%s» no está en la suscripción «%s»" -#: commands/subscriptioncmds.c:2287 +#: commands/subscriptioncmds.c:2376 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "no se puede eliminar todas las publicaciones de una suscripción" -#: commands/subscriptioncmds.c:2344 -#, fuzzy, c-format -#| msgid "%s requires a Boolean value" +#: commands/subscriptioncmds.c:2433 +#, c-format msgid "%s requires a Boolean value or \"parallel\"" -msgstr "«%s» requiere un valor lógico (booleano)" +msgstr "«%s» requiere un valor lógico (booleano) o “parallel”" -#: commands/tablecmds.c:246 commands/tablecmds.c:288 +#: commands/tablecmds.c:255 commands/tablecmds.c:297 #, c-format msgid "table \"%s\" does not exist" msgstr "no existe la tabla «%s»" -#: commands/tablecmds.c:247 commands/tablecmds.c:289 +#: commands/tablecmds.c:256 commands/tablecmds.c:298 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "la tabla «%s» no existe, omitiendo" -#: commands/tablecmds.c:249 commands/tablecmds.c:291 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 msgid "Use DROP TABLE to remove a table." msgstr "Use DROP TABLE para eliminar una tabla." -#: commands/tablecmds.c:252 +#: commands/tablecmds.c:261 #, c-format msgid "sequence \"%s\" does not exist" msgstr "no existe la secuencia «%s»" -#: commands/tablecmds.c:253 +#: commands/tablecmds.c:262 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "la secuencia «%s» no existe, omitiendo" -#: commands/tablecmds.c:255 +#: commands/tablecmds.c:264 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "Use DROP SEQUENCE para eliminar una secuencia." -#: commands/tablecmds.c:258 +#: commands/tablecmds.c:267 #, c-format msgid "view \"%s\" does not exist" msgstr "no existe la vista «%s»" -#: commands/tablecmds.c:259 +#: commands/tablecmds.c:268 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "la vista «%s» no existe, omitiendo" -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:270 msgid "Use DROP VIEW to remove a view." msgstr "Use DROP VIEW para eliminar una vista." -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:273 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "no existe la vista materializada «%s»" -#: commands/tablecmds.c:265 +#: commands/tablecmds.c:274 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "la vista materializada «%s» no existe, omitiendo" -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:276 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "Use DROP MATERIALIZED VIEW para eliminar una vista materializada." -#: commands/tablecmds.c:270 commands/tablecmds.c:294 commands/tablecmds.c:19002 -#: parser/parse_utilcmd.c:2245 +#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19805 +#: parser/parse_utilcmd.c:2251 #, c-format msgid "index \"%s\" does not exist" msgstr "no existe el índice «%s»" -#: commands/tablecmds.c:271 commands/tablecmds.c:295 +#: commands/tablecmds.c:280 commands/tablecmds.c:304 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "el índice «%s» no existe, omitiendo" -#: commands/tablecmds.c:273 commands/tablecmds.c:297 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 msgid "Use DROP INDEX to remove an index." msgstr "Use DROP INDEX para eliminar un índice." -#: commands/tablecmds.c:278 +#: commands/tablecmds.c:287 #, c-format msgid "\"%s\" is not a type" msgstr "«%s» no es un tipo" -#: commands/tablecmds.c:279 +#: commands/tablecmds.c:288 msgid "Use DROP TYPE to remove a type." msgstr "Use DROP TYPE para eliminar un tipo." -#: commands/tablecmds.c:282 commands/tablecmds.c:13730 -#: commands/tablecmds.c:16193 +#: commands/tablecmds.c:291 commands/tablecmds.c:14325 +#: commands/tablecmds.c:16886 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "no existe la tabla foránea «%s»" -#: commands/tablecmds.c:283 +#: commands/tablecmds.c:292 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "la tabla foránea «%s» no existe, omitiendo" -#: commands/tablecmds.c:285 +#: commands/tablecmds.c:294 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "Use DROP FOREIGN TABLE para eliminar una tabla foránea." -#: commands/tablecmds.c:700 +#: commands/tablecmds.c:734 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMIT sólo puede ser usado en tablas temporales" -#: commands/tablecmds.c:731 +#: commands/tablecmds.c:765 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "no se puede crear una tabla temporal dentro una operación restringida por seguridad" -#: commands/tablecmds.c:767 commands/tablecmds.c:15038 +#: commands/tablecmds.c:801 commands/tablecmds.c:15745 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "se heredaría de la relación «%s» más de una vez" -#: commands/tablecmds.c:955 -#, c-format -msgid "specifying a table access method is not supported on a partitioned table" -msgstr "especificar un método de acceso de tablas no está soportado en tablas particionadas" - -#: commands/tablecmds.c:1048 +#: commands/tablecmds.c:1067 #, c-format msgid "\"%s\" is not partitioned" msgstr "«%s» no está particionada" -#: commands/tablecmds.c:1142 +#: commands/tablecmds.c:1161 #, c-format msgid "cannot partition using more than %d columns" msgstr "no se puede particionar usando más de %d columnas" -#: commands/tablecmds.c:1198 +#: commands/tablecmds.c:1217 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "no se puede crear una partición foránea en la tabla particionada «%s»" -#: commands/tablecmds.c:1200 +#: commands/tablecmds.c:1219 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "La tabla «%s» contiene índices que son únicos." -#: commands/tablecmds.c:1365 +#: commands/tablecmds.c:1338 commands/tablecmds.c:13341 #, c-format -msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" +msgid "too many array dimensions" +msgstr "demasiadas dimensiones de array" + +#: commands/tablecmds.c:1343 parser/parse_clause.c:774 +#: parser/parse_relation.c:1912 +#, c-format +msgid "column \"%s\" cannot be declared SETOF" +msgstr "la columna «%s» no puede ser declarada SETOF" + +#: commands/tablecmds.c:1489 +#, c-format +msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" msgstr "DROP INDEX CONCURRENTLY no soporta eliminar múltiples objetos" -#: commands/tablecmds.c:1369 +#: commands/tablecmds.c:1493 #, c-format msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLY no soporta CASCADE" -#: commands/tablecmds.c:1473 +#: commands/tablecmds.c:1597 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "no se puede eliminar el índice particionado «%s» concurrentemente" -#: commands/tablecmds.c:1761 +#: commands/tablecmds.c:1885 #, c-format msgid "cannot truncate only a partitioned table" msgstr "no se puede truncar ONLY una tabla particionada" -#: commands/tablecmds.c:1762 +#: commands/tablecmds.c:1886 #, c-format msgid "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly." msgstr "No especifique la opción ONLY, o ejecute TRUNCATE ONLY en las particiones directamente." -#: commands/tablecmds.c:1835 +#: commands/tablecmds.c:1959 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "truncando además la tabla «%s»" -#: commands/tablecmds.c:2199 +#: commands/tablecmds.c:2320 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "no se puede truncar la tabla foránea «%s»" -#: commands/tablecmds.c:2256 +#: commands/tablecmds.c:2377 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "no se pueden truncar tablas temporales de otras sesiones" -#: commands/tablecmds.c:2488 commands/tablecmds.c:14935 +#: commands/tablecmds.c:2606 commands/tablecmds.c:15642 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "no se puede heredar de la tabla particionada «%s»" -#: commands/tablecmds.c:2493 +#: commands/tablecmds.c:2611 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "no se puede heredar de la partición «%s»" -#: commands/tablecmds.c:2501 parser/parse_utilcmd.c:2475 -#: parser/parse_utilcmd.c:2617 +#: commands/tablecmds.c:2619 parser/parse_utilcmd.c:2481 +#: parser/parse_utilcmd.c:2623 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "la relación heredada «%s» no es una tabla o tabla foránea" -#: commands/tablecmds.c:2513 +#: commands/tablecmds.c:2631 #, c-format msgid "cannot create a temporary relation as partition of permanent relation \"%s\"" msgstr "no se puede crear una relación temporal como partición de la relación permanente «%s»" -#: commands/tablecmds.c:2522 commands/tablecmds.c:14914 +#: commands/tablecmds.c:2640 commands/tablecmds.c:15621 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "no se puede heredar de la tabla temporal «%s»" -#: commands/tablecmds.c:2532 commands/tablecmds.c:14922 +#: commands/tablecmds.c:2650 commands/tablecmds.c:15629 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "no se puede heredar de una tabla temporal de otra sesión" -#: commands/tablecmds.c:2585 +#: commands/tablecmds.c:2791 commands/tablecmds.c:2845 +#: commands/tablecmds.c:13024 parser/parse_utilcmd.c:1265 +#: parser/parse_utilcmd.c:1308 parser/parse_utilcmd.c:1735 +#: parser/parse_utilcmd.c:1843 #, c-format -msgid "merging multiple inherited definitions of column \"%s\"" -msgstr "mezclando múltiples definiciones heredadas de la columna «%s»" +msgid "cannot convert whole-row table reference" +msgstr "no se puede convertir una referencia a la fila completa (whole-row)" -#: commands/tablecmds.c:2597 +#: commands/tablecmds.c:2792 parser/parse_utilcmd.c:1266 #, c-format -msgid "inherited column \"%s\" has a type conflict" -msgstr "columna heredada «%s» tiene conflicto de tipos" +msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." +msgstr "La expresión de generación para la columna «%s» contiene una referencia a la fila completa (whole-row) de la tabla «%s»." -#: commands/tablecmds.c:2599 commands/tablecmds.c:2628 -#: commands/tablecmds.c:2647 commands/tablecmds.c:2919 -#: commands/tablecmds.c:2955 commands/tablecmds.c:2971 -#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 -#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 -#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 -#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 -#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 -#: parser/parse_param.c:223 +#: commands/tablecmds.c:2846 parser/parse_utilcmd.c:1309 #, c-format -msgid "%s versus %s" -msgstr "%s versus %s" +msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." +msgstr "La restricción «%s» contiene una referencia a la fila completa (whole-row) de la tabla «%s»." -#: commands/tablecmds.c:2612 +#: commands/tablecmds.c:2956 commands/tablecmds.c:3227 #, c-format -msgid "inherited column \"%s\" has a collation conflict" -msgstr "columna heredada «%s» tiene conflicto de ordenamiento (collation)" +msgid "column \"%s\" inherits from generated column but specifies default" +msgstr "la columna «%s» hereda de una columna generada pero especifica un valor por omisión" -#: commands/tablecmds.c:2614 commands/tablecmds.c:2935 -#: commands/tablecmds.c:6849 +#: commands/tablecmds.c:2961 commands/tablecmds.c:3232 #, c-format -msgid "\"%s\" versus \"%s\"" -msgstr "«%s» versus «%s»" +msgid "column \"%s\" inherits from generated column but specifies identity" +msgstr "la columna «%s» hereda de una columna generada pero especifica una identidad" -#: commands/tablecmds.c:2626 +#: commands/tablecmds.c:2969 commands/tablecmds.c:3240 #, c-format -msgid "inherited column \"%s\" has a storage parameter conflict" -msgstr "columna heredada «%s» tiene conflicto de parámetros de almacenamiento" +msgid "child column \"%s\" specifies generation expression" +msgstr "la columna hija «%s» especifica una expresión de generación de columna" -#: commands/tablecmds.c:2645 commands/tablecmds.c:2969 +#: commands/tablecmds.c:2971 commands/tablecmds.c:3242 #, c-format -msgid "column \"%s\" has a compression method conflict" -msgstr "la columna «%s» tiene conflicto de método de compresión" +msgid "A child table column cannot be generated unless its parent column is." +msgstr "Una columna de tabla hija no puede ser generada a menos que su columna padre lo sea." -#: commands/tablecmds.c:2661 +#: commands/tablecmds.c:3017 #, c-format -msgid "inherited column \"%s\" has a generation conflict" -msgstr "columna heredada «%s» tiene conflicto de generación" +msgid "column \"%s\" inherits conflicting generation expressions" +msgstr "la columna «%s» hereda expresiones de generación en conflicto" -#: commands/tablecmds.c:2767 commands/tablecmds.c:2822 -#: commands/tablecmds.c:12456 parser/parse_utilcmd.c:1298 -#: parser/parse_utilcmd.c:1341 parser/parse_utilcmd.c:1740 -#: parser/parse_utilcmd.c:1848 +#: commands/tablecmds.c:3019 #, c-format -msgid "cannot convert whole-row table reference" -msgstr "no se puede convertir una referencia a la fila completa (whole-row)" +msgid "To resolve the conflict, specify a generation expression explicitly." +msgstr "Para resolver el conflicto, indique explícitamente una expresión de generación." -#: commands/tablecmds.c:2768 parser/parse_utilcmd.c:1299 +#: commands/tablecmds.c:3023 #, c-format -msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." -msgstr "La expresión de generación para la columna «%s» contiene una referencia a la fila completa (whole-row) de la tabla «%s»." +msgid "column \"%s\" inherits conflicting default values" +msgstr "la columna «%s» hereda valores por omisión no coincidentes" -#: commands/tablecmds.c:2823 parser/parse_utilcmd.c:1342 +#: commands/tablecmds.c:3025 #, c-format -msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." -msgstr "La restricción «%s» contiene una referencia a la fila completa (whole-row) de la tabla «%s»." +msgid "To resolve the conflict, specify a default explicitly." +msgstr "Para resolver el conflicto, indique explícitamente un valor por omisión." + +#: commands/tablecmds.c:3080 +#, c-format +msgid "check constraint name \"%s\" appears multiple times but with different expressions" +msgstr "la restricción «check» «%s» aparece más de una vez con diferentes expresiones" -#: commands/tablecmds.c:2901 +#: commands/tablecmds.c:3131 #, c-format msgid "merging column \"%s\" with inherited definition" msgstr "mezclando la columna «%s» con la definición heredada" -#: commands/tablecmds.c:2905 +#: commands/tablecmds.c:3135 #, c-format msgid "moving and merging column \"%s\" with inherited definition" msgstr "moviendo y mezclando la columna «%s» con la definición heredada" -#: commands/tablecmds.c:2906 +#: commands/tablecmds.c:3136 #, c-format msgid "User-specified column moved to the position of the inherited column." msgstr "La columna especificada por el usuario fue movida a la posición de la columna heredada." -#: commands/tablecmds.c:2917 +#: commands/tablecmds.c:3148 #, c-format msgid "column \"%s\" has a type conflict" msgstr "la columna «%s» tiene conflicto de tipos" -#: commands/tablecmds.c:2933 +#: commands/tablecmds.c:3150 commands/tablecmds.c:3184 +#: commands/tablecmds.c:3200 commands/tablecmds.c:3307 +#: commands/tablecmds.c:3340 commands/tablecmds.c:3356 +#: parser/parse_coerce.c:2192 parser/parse_coerce.c:2212 +#: parser/parse_coerce.c:2232 parser/parse_coerce.c:2253 +#: parser/parse_coerce.c:2308 parser/parse_coerce.c:2342 +#: parser/parse_coerce.c:2418 parser/parse_coerce.c:2449 +#: parser/parse_coerce.c:2488 parser/parse_coerce.c:2555 +#: parser/parse_param.c:223 +#, c-format +msgid "%s versus %s" +msgstr "%s versus %s" + +#: commands/tablecmds.c:3162 #, c-format msgid "column \"%s\" has a collation conflict" msgstr "la columna «%s» tiene conflicto de ordenamientos (collation)" -#: commands/tablecmds.c:2953 +#: commands/tablecmds.c:3164 commands/tablecmds.c:3326 +#: commands/tablecmds.c:7080 #, c-format -msgid "column \"%s\" has a storage parameter conflict" -msgstr "la columna «%s» tiene conflicto de parámetros de almacenamiento" +msgid "\"%s\" versus \"%s\"" +msgstr "«%s» versus «%s»" -#: commands/tablecmds.c:2999 commands/tablecmds.c:3086 +#: commands/tablecmds.c:3182 #, c-format -msgid "column \"%s\" inherits from generated column but specifies default" -msgstr "la columna «%s» hereda de una columna generada pero especifica un valor por omisión" +msgid "column \"%s\" has a storage parameter conflict" +msgstr "la columna «%s» tiene conflicto de parámetros de almacenamiento" -#: commands/tablecmds.c:3004 commands/tablecmds.c:3091 +#: commands/tablecmds.c:3198 commands/tablecmds.c:3354 #, c-format -msgid "column \"%s\" inherits from generated column but specifies identity" -msgstr "la columna «%s» hereda de una columna generada pero especifica una identidad" +msgid "column \"%s\" has a compression method conflict" +msgstr "la columna «%s» tiene conflicto de método de compresión" -#: commands/tablecmds.c:3012 commands/tablecmds.c:3099 +#: commands/tablecmds.c:3293 #, c-format -msgid "child column \"%s\" specifies generation expression" -msgstr "la columna hija «%s» especifica una expresión de generación de columna" - -#: commands/tablecmds.c:3014 commands/tablecmds.c:3101 -#, fuzzy, c-format -#| msgid "A generated column cannot reference another generated column." -msgid "A child table column cannot be generated unless its parent column is." -msgstr "Una columna generada no puede hacer referencia a otra columna generada." +msgid "merging multiple inherited definitions of column \"%s\"" +msgstr "mezclando múltiples definiciones heredadas de la columna «%s»" -#: commands/tablecmds.c:3147 +#: commands/tablecmds.c:3305 #, c-format -msgid "column \"%s\" inherits conflicting generation expressions" -msgstr "la columna «%s» hereda expresiones de generación en conflicto" - -#: commands/tablecmds.c:3149 -#, fuzzy, c-format -#| msgid "To resolve the conflict, specify a default explicitly." -msgid "To resolve the conflict, specify a generation expression explicitly." -msgstr "Para resolver el conflicto, indique explícitamente un valor por omisión." +msgid "inherited column \"%s\" has a type conflict" +msgstr "columna heredada «%s» tiene conflicto de tipos" -#: commands/tablecmds.c:3153 +#: commands/tablecmds.c:3324 #, c-format -msgid "column \"%s\" inherits conflicting default values" -msgstr "la columna «%s» hereda valores por omisión no coincidentes" +msgid "inherited column \"%s\" has a collation conflict" +msgstr "columna heredada «%s» tiene conflicto de ordenamiento (collation)" -#: commands/tablecmds.c:3155 +#: commands/tablecmds.c:3338 #, c-format -msgid "To resolve the conflict, specify a default explicitly." -msgstr "Para resolver el conflicto, indique explícitamente un valor por omisión." +msgid "inherited column \"%s\" has a storage parameter conflict" +msgstr "columna heredada «%s» tiene conflicto de parámetros de almacenamiento" -#: commands/tablecmds.c:3205 +#: commands/tablecmds.c:3366 #, c-format -msgid "check constraint name \"%s\" appears multiple times but with different expressions" -msgstr "la restricción «check» «%s» aparece más de una vez con diferentes expresiones" +msgid "inherited column \"%s\" has a generation conflict" +msgstr "columna heredada «%s» tiene conflicto de generación" -#: commands/tablecmds.c:3418 +#: commands/tablecmds.c:3597 #, c-format msgid "cannot move temporary tables of other sessions" msgstr "no se pueden mover tablas temporales de otras sesiones" -#: commands/tablecmds.c:3488 +#: commands/tablecmds.c:3670 #, c-format msgid "cannot rename column of typed table" msgstr "no se puede cambiar el nombre a una columna de una tabla tipada" -#: commands/tablecmds.c:3507 -#, fuzzy, c-format -#| msgid "cannot alter inherited column \"%s\" of relation \"%s\"" +#: commands/tablecmds.c:3689 +#, c-format msgid "cannot rename columns of relation \"%s\"" -msgstr "no se puede alterar la columna heredada «%s» de la relación «%s»" +msgstr "no se puede cambiar el nombre de columnas de la relación «%s»" -#: commands/tablecmds.c:3602 +#: commands/tablecmds.c:3784 #, c-format msgid "inherited column \"%s\" must be renamed in child tables too" msgstr "debe cambiar el nombre a la columna heredada «%s» en las tablas hijas también" -#: commands/tablecmds.c:3634 +#: commands/tablecmds.c:3816 #, c-format msgid "cannot rename system column \"%s\"" msgstr "no se puede cambiar el nombre a la columna de sistema «%s»" -#: commands/tablecmds.c:3649 +#: commands/tablecmds.c:3831 #, c-format msgid "cannot rename inherited column \"%s\"" msgstr "no se puede cambiar el nombre a la columna heredada «%s»" -#: commands/tablecmds.c:3801 +#: commands/tablecmds.c:3983 #, c-format msgid "inherited constraint \"%s\" must be renamed in child tables too" msgstr "debe cambiar el nombre a la restricción heredada «%s» en las tablas hijas también" -#: commands/tablecmds.c:3808 +#: commands/tablecmds.c:3990 #, c-format msgid "cannot rename inherited constraint \"%s\"" msgstr "no se puede cambiar el nombre a la restricción heredada «%s»" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4105 +#: commands/tablecmds.c:4290 #, c-format msgid "cannot %s \"%s\" because it is being used by active queries in this session" msgstr "no se puede hacer %s en «%s» porque está siendo usada por consultas activas en esta sesión" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4114 +#: commands/tablecmds.c:4299 #, c-format msgid "cannot %s \"%s\" because it has pending trigger events" -msgstr "no se puede hacer %s en «%s» porque tiene eventos de disparador pendientes" +msgstr "no se puede hacer %s en «%s» porque tiene eventos de “trigger” pendientes" + +#: commands/tablecmds.c:4325 +#, c-format +msgid "cannot alter temporary tables of other sessions" +msgstr "no se pueden alterar tablas temporales de otras sesiones" -#: commands/tablecmds.c:4581 +#: commands/tablecmds.c:4798 #, c-format msgid "cannot alter partition \"%s\" with an incomplete detach" msgstr "no se puede modificar la partición «%s» teniendo un desprendimiento incompleto" -#: commands/tablecmds.c:4774 commands/tablecmds.c:4789 +#: commands/tablecmds.c:5002 commands/tablecmds.c:5017 #, c-format msgid "cannot change persistence setting twice" msgstr "no se puede cambiar la opción de persistencia dos veces" -#: commands/tablecmds.c:4810 -#, fuzzy, c-format -#| msgid "cannot change inheritance of partitioned table" -msgid "cannot change access method of a partitioned table" -msgstr "no se puede cambiar la herencia de una tabla particionada" - -#: commands/tablecmds.c:4816 -#, fuzzy, c-format -#| msgid "cannot have multiple SET TABLESPACE subcommands" +#: commands/tablecmds.c:5038 +#, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" -msgstr "no se pueden tener múltiples subórdenes SET TABLESPACE" +msgstr "no se pueden tener múltiples subórdenes SET ACCESS METHOD" -#: commands/tablecmds.c:5537 +#: commands/tablecmds.c:5768 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "no se puede reescribir la relación de sistema «%s»" -#: commands/tablecmds.c:5543 +#: commands/tablecmds.c:5774 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "no se puede reescribir la tabla «%s» que es usada como tabla de catálogo" -#: commands/tablecmds.c:5553 +#: commands/tablecmds.c:5786 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "no se puede reescribir tablas temporales de otras sesiones" -#: commands/tablecmds.c:6048 +#: commands/tablecmds.c:6281 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "la columna «%s» de la relación «%s» contiene valores null" -#: commands/tablecmds.c:6065 +#: commands/tablecmds.c:6298 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "la restricción check «%s» de la relación «%s» es violada por alguna fila" -#: commands/tablecmds.c:6084 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6317 partitioning/partbounds.c:3387 #, c-format msgid "updated partition constraint for default partition \"%s\" would be violated by some row" msgstr "la restricción de partición actualizada para la partición default «%s» sería violada por alguna fila" -#: commands/tablecmds.c:6090 +#: commands/tablecmds.c:6323 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "la restricción de partición de la relación «%s» es violada por alguna fila" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6352 -#, fuzzy, c-format -#| msgid "relation \"%s\" is not a parent of relation \"%s\"" +#: commands/tablecmds.c:6588 +#, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" -msgstr "relación «%s» no es un padre de la relación «%s»" +msgstr "la acción ALTER %s no puede ser efecutada en la relación «%s»" -#: commands/tablecmds.c:6607 commands/tablecmds.c:6614 +#: commands/tablecmds.c:6843 commands/tablecmds.c:6850 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" msgstr "no se puede alterar el tipo «%s» porque la columna «%s.%s» lo usa" -#: commands/tablecmds.c:6621 +#: commands/tablecmds.c:6857 #, c-format msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" msgstr "no se puede alterar la tabla foránea «%s» porque la columna «%s.%s» usa su tipo de registro" -#: commands/tablecmds.c:6628 +#: commands/tablecmds.c:6864 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "no se puede alterar la tabla «%s» porque la columna «%s.%s» usa su tipo de registro" -#: commands/tablecmds.c:6684 +#: commands/tablecmds.c:6920 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "no se puede cambiar el tipo «%s» porque es el tipo de una tabla tipada" -#: commands/tablecmds.c:6686 +#: commands/tablecmds.c:6922 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "Use ALTER ... CASCADE para eliminar además las tablas tipadas." -#: commands/tablecmds.c:6732 +#: commands/tablecmds.c:6968 #, c-format msgid "type %s is not a composite type" msgstr "el tipo %s no es un tipo compuesto" -#: commands/tablecmds.c:6759 +#: commands/tablecmds.c:6995 #, c-format msgid "cannot add column to typed table" msgstr "no se puede agregar una columna a una tabla tipada" -#: commands/tablecmds.c:6812 +#: commands/tablecmds.c:7043 #, c-format msgid "cannot add column to a partition" msgstr "no se puede agregar una columna a una partición" -#: commands/tablecmds.c:6841 commands/tablecmds.c:15165 +#: commands/tablecmds.c:7072 commands/tablecmds.c:15860 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "la tabla hija «%s» tiene un tipo diferente para la columna «%s»" -#: commands/tablecmds.c:6847 commands/tablecmds.c:15172 +#: commands/tablecmds.c:7078 commands/tablecmds.c:15866 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "la tabla hija «%s» tiene un ordenamiento (collation) diferente para la columna «%s»" -#: commands/tablecmds.c:6865 +#: commands/tablecmds.c:7096 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "mezclando la definición de la columna «%s» en la tabla hija «%s»" -#: commands/tablecmds.c:6908 +#: commands/tablecmds.c:7149 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "no se puede agregar una columna de identidad recursivamente a una tabla que tiene tablas hijas" -#: commands/tablecmds.c:7159 +#: commands/tablecmds.c:7362 #, c-format msgid "column must be added to child tables too" msgstr "la columna debe ser agregada a las tablas hijas también" -#: commands/tablecmds.c:7237 +#: commands/tablecmds.c:7440 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "la columna «%s» de la relación «%s» ya existe, omitiendo" -#: commands/tablecmds.c:7244 +#: commands/tablecmds.c:7447 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "ya existe la columna «%s» en la relación «%s»" -#: commands/tablecmds.c:7310 commands/tablecmds.c:12094 +#: commands/tablecmds.c:7513 commands/tablecmds.c:12652 #, c-format msgid "cannot remove constraint from only the partitioned table when partitions exist" msgstr "no se pueden eliminar restricciones sólo de la tabla particionada cuando existen particiones" -#: commands/tablecmds.c:7311 commands/tablecmds.c:7628 -#: commands/tablecmds.c:8593 commands/tablecmds.c:12095 +#: commands/tablecmds.c:7514 commands/tablecmds.c:7828 +#: commands/tablecmds.c:8006 commands/tablecmds.c:8113 +#: commands/tablecmds.c:8230 commands/tablecmds.c:9049 +#: commands/tablecmds.c:12653 #, c-format msgid "Do not specify the ONLY keyword." msgstr "No especifique la opción ONLY." -#: commands/tablecmds.c:7348 commands/tablecmds.c:7554 -#: commands/tablecmds.c:7696 commands/tablecmds.c:7810 -#: commands/tablecmds.c:7904 commands/tablecmds.c:7963 -#: commands/tablecmds.c:8082 commands/tablecmds.c:8221 -#: commands/tablecmds.c:8291 commands/tablecmds.c:8425 -#: commands/tablecmds.c:12249 commands/tablecmds.c:13753 -#: commands/tablecmds.c:16282 +#: commands/tablecmds.c:7550 commands/tablecmds.c:7754 +#: commands/tablecmds.c:7896 commands/tablecmds.c:8028 +#: commands/tablecmds.c:8157 commands/tablecmds.c:8251 +#: commands/tablecmds.c:8352 commands/tablecmds.c:8509 +#: commands/tablecmds.c:8662 commands/tablecmds.c:8743 +#: commands/tablecmds.c:8877 commands/tablecmds.c:12806 +#: commands/tablecmds.c:14348 commands/tablecmds.c:16975 #, c-format msgid "cannot alter system column \"%s\"" msgstr "no se puede alterar columna de sistema «%s»" -#: commands/tablecmds.c:7354 commands/tablecmds.c:7702 +#: commands/tablecmds.c:7556 commands/tablecmds.c:7902 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "la columna «%s» en la relación «%s» es una columna de identidad" -#: commands/tablecmds.c:7397 +#: commands/tablecmds.c:7597 #, c-format msgid "column \"%s\" is in a primary key" msgstr "la columna «%s» está en la llave primaria" -#: commands/tablecmds.c:7402 +#: commands/tablecmds.c:7602 #, c-format msgid "column \"%s\" is in index used as replica identity" msgstr "la columna «%s» se encuentra en un índice utilizado como identidad de réplica" -#: commands/tablecmds.c:7425 +#: commands/tablecmds.c:7625 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "columna «%s» está marcada NOT NULL en la tabla padre" -#: commands/tablecmds.c:7625 commands/tablecmds.c:9077 +#: commands/tablecmds.c:7825 commands/tablecmds.c:9533 #, c-format msgid "constraint must be added to child tables too" msgstr "la restricción debe ser agregada a las tablas hijas también" -#: commands/tablecmds.c:7626 +#: commands/tablecmds.c:7826 #, c-format msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." msgstr "La columna «%s» de la relación «%s» no está previamente marcada NOT NULL." -#: commands/tablecmds.c:7704 -#, c-format -msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead." -msgstr "Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY en su lugar." - -#: commands/tablecmds.c:7709 +#: commands/tablecmds.c:7911 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "la columna «%s» en la relación «%s» es una columna generada" -#: commands/tablecmds.c:7712 +#: commands/tablecmds.c:8005 #, c-format -msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION instead." -msgstr "Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION en su lugar." +msgid "cannot add identity to a column of only the partitioned table" +msgstr "no se puede agregar identidad a una columna de sólo una tabla particionada" -#: commands/tablecmds.c:7821 +#: commands/tablecmds.c:8011 +#, c-format +msgid "cannot add identity to a column of a partition" +msgstr "no se puede agregar identidad a una columna de una partición" + +#: commands/tablecmds.c:8039 #, c-format msgid "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added" msgstr "la columna «%s» en la relación «%s» debe ser declarada NOT NULL antes de que una identidad pueda agregarse" -#: commands/tablecmds.c:7827 +#: commands/tablecmds.c:8045 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "la columna «%s» en la relación «%s» ya es una columna de identidad" -#: commands/tablecmds.c:7833 +#: commands/tablecmds.c:8051 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "la columna «%s» en la relación «%s» ya tiene un valor por omisión" -#: commands/tablecmds.c:7910 commands/tablecmds.c:7971 +#: commands/tablecmds.c:8112 +#, c-format +msgid "cannot change identity column of only the partitioned table" +msgstr "no se puede cambiar la columna de identidad de una tabla particionada" + +#: commands/tablecmds.c:8118 +#, c-format +msgid "cannot change identity column of a partition" +msgstr "no puede cambiar la columna de identidad de una partición" + +#: commands/tablecmds.c:8163 commands/tablecmds.c:8259 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "la columna «%s» en la relación «%s» no es una columna identidad" -#: commands/tablecmds.c:7976 +#: commands/tablecmds.c:8229 +#, c-format +msgid "cannot drop identity from a column of only the partitioned table" +msgstr "no se pueden eliminar la identidad de la columna de sólo una tabla particionada" + +#: commands/tablecmds.c:8235 +#, c-format +msgid "cannot drop identity from a column of a partition" +msgstr "no se puede eliminar la identidad de la columna de una partición" + +#: commands/tablecmds.c:8264 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "la columna «%s» de la relación «%s» no es una columna identidad, omitiendo" -#: commands/tablecmds.c:8029 +#: commands/tablecmds.c:8358 +#, c-format +msgid "column \"%s\" of relation \"%s\" is not a generated column" +msgstr "la columna «%s» en la relación «%s» no es una columna generada" + +#: commands/tablecmds.c:8456 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "ALTER TABLE / DROP EXPRESSION se debe aplicar a las tablas hijas también" -#: commands/tablecmds.c:8051 +#: commands/tablecmds.c:8478 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "no se puede eliminar la expresión de generación de una columna heredada" -#: commands/tablecmds.c:8090 +#: commands/tablecmds.c:8517 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column" msgstr "la columna «%s» en la relación «%s» no es una columna generada almacenada" -#: commands/tablecmds.c:8095 +#: commands/tablecmds.c:8522 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" msgstr "la columna «%s» de la relación «%s» no es una columna generada almacenada, omitiendo" -#: commands/tablecmds.c:8168 +#: commands/tablecmds.c:8600 #, c-format msgid "cannot refer to non-index column by number" msgstr "no se puede referir a columnas que no son de índice por número" -#: commands/tablecmds.c:8211 +#: commands/tablecmds.c:8652 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "no existe la columna número %d en la relación «%s»" -#: commands/tablecmds.c:8230 +#: commands/tablecmds.c:8671 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "no se puede alterar estadísticas en la columna incluida «%s» del índice «%s»" -#: commands/tablecmds.c:8235 +#: commands/tablecmds.c:8676 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "no se puede alterar estadísticas en la columna no-de-expresión «%s» del índice «%s»" -#: commands/tablecmds.c:8237 +#: commands/tablecmds.c:8678 #, c-format msgid "Alter statistics on table column instead." msgstr "Altere las estadísticas en la columna de la tabla en su lugar." -#: commands/tablecmds.c:8472 +#: commands/tablecmds.c:8924 #, c-format msgid "cannot drop column from typed table" msgstr "no se pueden eliminar columnas de una tabla tipada" -#: commands/tablecmds.c:8531 +#: commands/tablecmds.c:8987 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "no existe la columna «%s» en la relación «%s», omitiendo" -#: commands/tablecmds.c:8544 +#: commands/tablecmds.c:9000 #, c-format msgid "cannot drop system column \"%s\"" msgstr "no se puede eliminar la columna de sistema «%s»" -#: commands/tablecmds.c:8554 +#: commands/tablecmds.c:9010 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "no se puede eliminar la columna heredada «%s»" -#: commands/tablecmds.c:8567 +#: commands/tablecmds.c:9023 #, c-format msgid "cannot drop column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "no se puede eliminar la columna «%s» porque es parte de la llave de partición de la relación «%s»" -#: commands/tablecmds.c:8592 +#: commands/tablecmds.c:9048 #, c-format msgid "cannot drop column from only the partitioned table when partitions exist" msgstr "no se pueden eliminar columnas sólo de una tabla particionada cuando existe particiones" -#: commands/tablecmds.c:8797 +#: commands/tablecmds.c:9253 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX no está soportado en tablas particionadas" -#: commands/tablecmds.c:8822 +#: commands/tablecmds.c:9278 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX renombrará el índice «%s» a «%s»" -#: commands/tablecmds.c:9159 +#: commands/tablecmds.c:9615 #, c-format msgid "cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "no se puede usar ONLY para una llave foránea en la tabla particionada «%s» haciendo referencia a la relación «%s»" -#: commands/tablecmds.c:9165 +#: commands/tablecmds.c:9621 #, c-format msgid "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "no se puede agregar una llave foránea NOT VALID a la tabla particionada «%s» haciendo referencia a la relación «%s»" -#: commands/tablecmds.c:9168 +#: commands/tablecmds.c:9624 #, c-format msgid "This feature is not yet supported on partitioned tables." msgstr "Esta característica no está aún soportada en tablas particionadas." -#: commands/tablecmds.c:9175 commands/tablecmds.c:9631 +#: commands/tablecmds.c:9631 commands/tablecmds.c:10092 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "la relación referida «%s» no es una tabla" -#: commands/tablecmds.c:9198 +#: commands/tablecmds.c:9654 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "las restricciones en tablas permanentes sólo pueden hacer referencia a tablas permanentes" -#: commands/tablecmds.c:9205 +#: commands/tablecmds.c:9661 #, c-format msgid "constraints on unlogged tables may reference only permanent or unlogged tables" msgstr "las restricciones en tablas «unlogged» sólo pueden hacer referencia a tablas permanentes o «unlogged»" -#: commands/tablecmds.c:9211 +#: commands/tablecmds.c:9667 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "las restricciones en tablas temporales sólo pueden hacer referencia a tablas temporales" -#: commands/tablecmds.c:9215 +#: commands/tablecmds.c:9671 #, c-format msgid "constraints on temporary tables must involve temporary tables of this session" msgstr "las restricciones en tablas temporales sólo pueden hacer referencia a tablas temporales de esta sesión" -#: commands/tablecmds.c:9279 commands/tablecmds.c:9285 +#: commands/tablecmds.c:9735 commands/tablecmds.c:9741 #, c-format msgid "invalid %s action for foreign key constraint containing generated column" msgstr "acción %s no válida para restricción de llave foránea que contiene columnas generadas" -#: commands/tablecmds.c:9301 +#: commands/tablecmds.c:9757 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "el número de columnas referidas en la llave foránea no coincide con el número de columnas de referencia" -#: commands/tablecmds.c:9408 +#: commands/tablecmds.c:9864 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "la restricción de llave foránea «%s» no puede ser implementada" -#: commands/tablecmds.c:9410 +#: commands/tablecmds.c:9866 #, c-format msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." msgstr "Las columnas llave «%s» y «%s» son de tipos incompatibles: %s y %s" -#: commands/tablecmds.c:9567 +#: commands/tablecmds.c:10035 #, c-format msgid "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" msgstr "la columna «%s» referenciada en la acción ON DELETE SET debe ser parte de la llave foránea" -#: commands/tablecmds.c:9841 commands/tablecmds.c:10311 -#: parser/parse_utilcmd.c:791 parser/parse_utilcmd.c:920 +#: commands/tablecmds.c:10392 commands/tablecmds.c:10832 +#: parser/parse_utilcmd.c:822 parser/parse_utilcmd.c:945 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "las restricciones de llave foránea no están soportadas en tablas foráneas" -#: commands/tablecmds.c:10864 commands/tablecmds.c:11142 -#: commands/tablecmds.c:12051 commands/tablecmds.c:12126 +#: commands/tablecmds.c:10815 +#, c-format +msgid "cannot attach table \"%s\" as a partition because it is referenced by foreign key \"%s\"" +msgstr "no se puede adjuntar la tabla foránea «%s» como partición porque es referenciada por la llave foránea «%s»" + +#: commands/tablecmds.c:11416 commands/tablecmds.c:11697 +#: commands/tablecmds.c:12609 commands/tablecmds.c:12683 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "no existe la restricción «%s» en la relación «%s»" -#: commands/tablecmds.c:10871 +#: commands/tablecmds.c:11423 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "la restricción «%s» de la relación «%s» no es una restricción de llave foránea" -#: commands/tablecmds.c:10909 +#: commands/tablecmds.c:11461 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" msgstr "no se puede modificar la restricción «%s» en la relación «%s»" -#: commands/tablecmds.c:10912 +#: commands/tablecmds.c:11464 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "La restricción «%s» deriva de la restricción «%s» de la relación «%s»." -#: commands/tablecmds.c:10914 +#: commands/tablecmds.c:11466 #, c-format -msgid "You may alter the constraint it derives from, instead." +msgid "You may alter the constraint it derives from instead." msgstr "En su lugar, puede modificar la restricción de la cual deriva." -#: commands/tablecmds.c:11150 +#: commands/tablecmds.c:11705 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" msgstr "la restricción «%s» de la relación «%s» no es una llave foránea o restricción «check»" -#: commands/tablecmds.c:11227 +#: commands/tablecmds.c:11782 #, c-format msgid "constraint must be validated on child tables too" msgstr "la restricción debe ser validada en las tablas hijas también" -#: commands/tablecmds.c:11314 +#: commands/tablecmds.c:11869 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "no existe la columna «%s» referida en la llave foránea" -#: commands/tablecmds.c:11320 -#, fuzzy, c-format -#| msgid "Generated columns cannot be used in COPY." +#: commands/tablecmds.c:11875 +#, c-format msgid "system columns cannot be used in foreign keys" -msgstr "Las columnas generadas no pueden usarse en COPY." +msgstr "las columnas de sistema no pueden usarse en llaves foráneas" -#: commands/tablecmds.c:11324 +#: commands/tablecmds.c:11879 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "no se puede tener más de %d columnas en una llave foránea" -#: commands/tablecmds.c:11389 +#: commands/tablecmds.c:11944 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "no se puede usar una llave primaria postergable para la tabla referenciada «%s»" -#: commands/tablecmds.c:11406 +#: commands/tablecmds.c:11961 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "no hay llave primaria para la tabla referida «%s»" -#: commands/tablecmds.c:11470 +#: commands/tablecmds.c:12029 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "la lista de columnas referidas en una llave foránea no debe contener duplicados" -#: commands/tablecmds.c:11562 +#: commands/tablecmds.c:12121 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "no se puede usar una restricción unique postergable para la tabla referenciada «%s»" -#: commands/tablecmds.c:11567 +#: commands/tablecmds.c:12126 #, c-format msgid "there is no unique constraint matching given keys for referenced table \"%s\"" msgstr "no hay restricción unique que coincida con las columnas dadas en la tabla referida «%s»" -#: commands/tablecmds.c:12007 +#: commands/tablecmds.c:12565 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "no se puede eliminar la restricción «%s» heredada de la relación «%s»" -#: commands/tablecmds.c:12057 +#: commands/tablecmds.c:12615 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" msgstr "no existe la restricción «%s» en la relación «%s», omitiendo" -#: commands/tablecmds.c:12233 +#: commands/tablecmds.c:12790 #, c-format msgid "cannot alter column type of typed table" msgstr "no se puede cambiar el tipo de una columna de una tabla tipada" -#: commands/tablecmds.c:12260 +#: commands/tablecmds.c:12816 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "no se puede especificar USING al alterar el tipo de una columna generada" + +#: commands/tablecmds.c:12817 commands/tablecmds.c:18028 +#: commands/tablecmds.c:18118 commands/trigger.c:656 +#: rewrite/rewriteHandler.c:941 rewrite/rewriteHandler.c:976 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "La columna «%s» es una columna generada." + +#: commands/tablecmds.c:12827 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "no se puede alterar la columna heredada «%s»" -#: commands/tablecmds.c:12269 +#: commands/tablecmds.c:12836 #, c-format msgid "cannot alter column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "no se puede alterar la columna «%s» porque es parte de la llave de partición de la relación «%s»" -#: commands/tablecmds.c:12319 +#: commands/tablecmds.c:12886 #, c-format msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s" msgstr "el resultado de la cláusula USING para la columna «%s» no puede ser convertido automáticamente al tipo %s" -#: commands/tablecmds.c:12322 +#: commands/tablecmds.c:12889 #, c-format msgid "You might need to add an explicit cast." msgstr "Puede ser necesario agregar un cast explícito." -#: commands/tablecmds.c:12326 +#: commands/tablecmds.c:12893 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "la columna «%s» no puede convertirse automáticamente al tipo %s" #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12329 +#: commands/tablecmds.c:12897 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "Puede ser necesario especificar «USING %s::%s»." -#: commands/tablecmds.c:12428 +#: commands/tablecmds.c:12996 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "no se puede alterar la columna heredada «%s» de la relación «%s»" -#: commands/tablecmds.c:12457 +#: commands/tablecmds.c:13025 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "La expresión USING contiene una referencia a la fila completa (whole-row)." -#: commands/tablecmds.c:12468 +#: commands/tablecmds.c:13036 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "debe cambiar el tipo a la columna heredada «%s» en las tablas hijas también" -#: commands/tablecmds.c:12593 +#: commands/tablecmds.c:13161 #, c-format msgid "cannot alter type of column \"%s\" twice" msgstr "no se puede alterar el tipo de la columna «%s» dos veces" -#: commands/tablecmds.c:12631 +#: commands/tablecmds.c:13199 #, c-format msgid "generation expression for column \"%s\" cannot be cast automatically to type %s" msgstr "la expresión de generación para la columna «%s» no puede ser convertido automáticamente al tipo %s" -#: commands/tablecmds.c:12636 +#: commands/tablecmds.c:13204 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "el valor por omisión para la columna «%s» no puede ser convertido automáticamente al tipo %s" -#: commands/tablecmds.c:12717 +#: commands/tablecmds.c:13508 #, c-format -msgid "cannot alter type of a column used by a view or rule" -msgstr "no se puede alterar el tipo de una columna usada en una regla o vista" +msgid "cannot alter type of a column used by a function or procedure" +msgstr "no se puede alterar el tipo de una columna usada en una función o procedimiento" -#: commands/tablecmds.c:12718 commands/tablecmds.c:12737 -#: commands/tablecmds.c:12755 +#: commands/tablecmds.c:13509 commands/tablecmds.c:13524 +#: commands/tablecmds.c:13544 commands/tablecmds.c:13563 +#: commands/tablecmds.c:13622 #, c-format msgid "%s depends on column \"%s\"" msgstr "%s depende de la columna «%s»" -#: commands/tablecmds.c:12736 +#: commands/tablecmds.c:13523 +#, c-format +msgid "cannot alter type of a column used by a view or rule" +msgstr "no se puede alterar el tipo de una columna usada en una regla o vista" + +#: commands/tablecmds.c:13543 #, c-format msgid "cannot alter type of a column used in a trigger definition" msgstr "no se puede alterar el tipo de una columna usada en una definición de trigger" -#: commands/tablecmds.c:12754 +#: commands/tablecmds.c:13562 #, c-format msgid "cannot alter type of a column used in a policy definition" msgstr "no se puede alterar el tipo de una columna usada en una definición de política" -#: commands/tablecmds.c:12785 +#: commands/tablecmds.c:13593 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "no se puede alterar el tipo de una columna usada por una columna generada" -#: commands/tablecmds.c:12786 +#: commands/tablecmds.c:13594 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "La columna «%s» es usada por la columna generada «%s»." -#: commands/tablecmds.c:13861 commands/tablecmds.c:13873 +#: commands/tablecmds.c:13621 +#, c-format +msgid "cannot alter type of a column used by a publication WHERE clause" +msgstr "no se puede alterar el tipo de una columna usada en una cláusula WHERE de publicación" + +#: commands/tablecmds.c:14456 commands/tablecmds.c:14468 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "no se puede cambiar el dueño del índice «%s»" -#: commands/tablecmds.c:13863 commands/tablecmds.c:13875 +#: commands/tablecmds.c:14458 commands/tablecmds.c:14470 #, c-format -msgid "Change the ownership of the index's table, instead." -msgstr "Considere cambiar el dueño de la tabla en vez de cambiar el dueño del índice." +msgid "Change the ownership of the index's table instead." +msgstr "Cambie el dueño de la tabla del índice en su lugar." -#: commands/tablecmds.c:13889 +#: commands/tablecmds.c:14484 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "no se puede cambiar el dueño de la secuencia «%s»" -#: commands/tablecmds.c:13903 commands/tablecmds.c:17201 -#: commands/tablecmds.c:17220 +#: commands/tablecmds.c:14509 #, c-format -msgid "Use ALTER TYPE instead." -msgstr "Considere usar ALTER TYPE." - -#: commands/tablecmds.c:13912 -#, fuzzy, c-format -#| msgid "cannot change owner of index \"%s\"" msgid "cannot change owner of relation \"%s\"" -msgstr "no se puede cambiar el dueño del índice «%s»" +msgstr "no se puede cambiar el dueño de la relación «%s»" -#: commands/tablecmds.c:14274 +#: commands/tablecmds.c:14976 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "no se pueden tener múltiples subórdenes SET TABLESPACE" -#: commands/tablecmds.c:14351 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#: commands/tablecmds.c:15053 +#, c-format msgid "cannot set options for relation \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "no se puede definir opciones para la relación «%s»" -#: commands/tablecmds.c:14385 commands/view.c:445 +#: commands/tablecmds.c:15087 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "WITH CHECK OPTION sólo puede usarse en vistas automáticamente actualizables" -#: commands/tablecmds.c:14635 +#: commands/tablecmds.c:15338 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "solamente tablas, índices y vistas materializadas existen en tablespaces" -#: commands/tablecmds.c:14647 +#: commands/tablecmds.c:15350 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "no se puede mover objetos hacia o desde el tablespace pg_global" -#: commands/tablecmds.c:14739 +#: commands/tablecmds.c:15442 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "cancelando porque el lock en la relación «%s.%s» no está disponible" -#: commands/tablecmds.c:14755 +#: commands/tablecmds.c:15458 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr "no se encontraron relaciones coincidentes en el tablespace «%s»" -#: commands/tablecmds.c:14873 +#: commands/tablecmds.c:15580 #, c-format msgid "cannot change inheritance of typed table" msgstr "no se puede cambiar la herencia de una tabla tipada" -#: commands/tablecmds.c:14878 commands/tablecmds.c:15396 +#: commands/tablecmds.c:15585 commands/tablecmds.c:16085 #, c-format msgid "cannot change inheritance of a partition" msgstr "no puede cambiar la herencia de una partición" -#: commands/tablecmds.c:14883 +#: commands/tablecmds.c:15590 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "no se puede cambiar la herencia de una tabla particionada" -#: commands/tablecmds.c:14929 +#: commands/tablecmds.c:15636 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "no se puede agregar herencia a tablas temporales de otra sesión" -#: commands/tablecmds.c:14942 +#: commands/tablecmds.c:15649 #, c-format msgid "cannot inherit from a partition" msgstr "no se puede heredar de una partición" -#: commands/tablecmds.c:14964 commands/tablecmds.c:17841 +#: commands/tablecmds.c:15671 commands/tablecmds.c:18529 #, c-format msgid "circular inheritance not allowed" msgstr "la herencia circular no está permitida" -#: commands/tablecmds.c:14965 commands/tablecmds.c:17842 +#: commands/tablecmds.c:15672 commands/tablecmds.c:18530 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "«%s» ya es un hijo de «%s»." -#: commands/tablecmds.c:14978 +#: commands/tablecmds.c:15685 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "el trigger «%s» impide a la tabla «%s» convertirse en hija de herencia" -#: commands/tablecmds.c:14980 +#: commands/tablecmds.c:15687 #, c-format msgid "ROW triggers with transition tables are not supported in inheritance hierarchies." msgstr "Los triggers ROW con tablas de transición no están permitidos en jerarquías de herencia." -#: commands/tablecmds.c:15183 +#: commands/tablecmds.c:15876 #, c-format msgid "column \"%s\" in child table must be marked NOT NULL" msgstr "columna «%s» en tabla hija debe marcarse como NOT NULL" -#: commands/tablecmds.c:15192 +#: commands/tablecmds.c:15885 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "columna «%s» en tabla hija debe ser una columna generada" -#: commands/tablecmds.c:15197 -#, fuzzy, c-format -#| msgid "column \"%s\" in child table must be a generated column" +#: commands/tablecmds.c:15889 +#, c-format msgid "column \"%s\" in child table must not be a generated column" -msgstr "columna «%s» en tabla hija debe ser una columna generada" +msgstr "columna «%s» en tabla hija no puede ser una columna generada" -#: commands/tablecmds.c:15228 +#: commands/tablecmds.c:15927 #, c-format msgid "child table is missing column \"%s\"" msgstr "tabla hija no tiene la columna «%s»" -#: commands/tablecmds.c:15316 +#: commands/tablecmds.c:16008 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "la tabla hija «%s» tiene una definición diferente para la restricción «check» «%s»" -#: commands/tablecmds.c:15324 +#: commands/tablecmds.c:16015 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"" msgstr "la restricción «%s» está en conflicto con la restricción no heredada en la tabla hija «%s»" -#: commands/tablecmds.c:15335 +#: commands/tablecmds.c:16025 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" msgstr "la restricción «%s» está en conflicto con la restricción NOT VALID en la tabla hija «%s»" -#: commands/tablecmds.c:15374 +#: commands/tablecmds.c:16063 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "tabla hija no tiene la restricción «%s»" -#: commands/tablecmds.c:15460 +#: commands/tablecmds.c:16149 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "la partición «%s» ya tiene un desprendimiento pendiente en la tabla particionada «%s.%s»" -#: commands/tablecmds.c:15489 commands/tablecmds.c:15537 +#: commands/tablecmds.c:16178 commands/tablecmds.c:16224 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "relación «%s» no es una partición de la relación «%s»" -#: commands/tablecmds.c:15543 +#: commands/tablecmds.c:16230 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "relación «%s» no es un padre de la relación «%s»" -#: commands/tablecmds.c:15771 +#: commands/tablecmds.c:16457 #, c-format msgid "typed tables cannot inherit" msgstr "las tablas tipadas no pueden heredar" -#: commands/tablecmds.c:15801 +#: commands/tablecmds.c:16487 #, c-format msgid "table is missing column \"%s\"" msgstr "la tabla no tiene la columna «%s»" -#: commands/tablecmds.c:15812 +#: commands/tablecmds.c:16498 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "la tabla tiene columna «%s» en la posición en que el tipo requiere «%s»." -#: commands/tablecmds.c:15821 +#: commands/tablecmds.c:16507 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "la tabla «%s» tiene un tipo diferente para la columna «%s»" -#: commands/tablecmds.c:15835 +#: commands/tablecmds.c:16521 #, c-format msgid "table has extra column \"%s\"" msgstr "tabla tiene la columna extra «%s»" -#: commands/tablecmds.c:15887 +#: commands/tablecmds.c:16573 #, c-format msgid "\"%s\" is not a typed table" msgstr "«%s» no es una tabla tipada" -#: commands/tablecmds.c:16061 +#: commands/tablecmds.c:16747 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "no se puede usar el índice no-único «%s» como identidad de réplica" -#: commands/tablecmds.c:16067 +#: commands/tablecmds.c:16753 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "no puede usar el índice no-inmediato «%s» como identidad de réplica" -#: commands/tablecmds.c:16073 +#: commands/tablecmds.c:16759 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "no se puede usar el índice funcional «%s» como identidad de réplica" -#: commands/tablecmds.c:16079 +#: commands/tablecmds.c:16765 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "no se puede usar el índice parcial «%s» como identidad de réplica" -#: commands/tablecmds.c:16096 +#: commands/tablecmds.c:16782 #, c-format msgid "index \"%s\" cannot be used as replica identity because column %d is a system column" msgstr "el índice «%s» no puede usarse como identidad de réplica porque la column %d es una columna de sistema" -#: commands/tablecmds.c:16103 +#: commands/tablecmds.c:16789 #, c-format msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable" msgstr "el índice «%s» no puede usarse como identidad de réplica porque la column «%s» acepta valores nulos" -#: commands/tablecmds.c:16348 +#: commands/tablecmds.c:17041 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "no se puede cambiar el estado «logged» de la tabla «%s» porque es temporal" -#: commands/tablecmds.c:16372 +#: commands/tablecmds.c:17065 #, c-format msgid "cannot change table \"%s\" to unlogged because it is part of a publication" msgstr "no se pudo cambiar la tabla «%s» a «unlogged» porque es parte de una publicación" -#: commands/tablecmds.c:16374 +#: commands/tablecmds.c:17067 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "Las tablas «unlogged» no pueden replicarse." -#: commands/tablecmds.c:16419 +#: commands/tablecmds.c:17112 #, c-format msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\"" msgstr "no se pudo cambiar la tabla «%s» a «logged» porque hace referencia a la tabla «unlogged» «%s»" -#: commands/tablecmds.c:16429 +#: commands/tablecmds.c:17122 #, c-format msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\"" msgstr "no se pudo cambiar la tabla «%s» a «unlogged» porque hace referencia a la tabla «logged» «%s»" -#: commands/tablecmds.c:16487 +#: commands/tablecmds.c:17180 #, c-format msgid "cannot move an owned sequence into another schema" msgstr "no se puede mover una secuencia enlazada a una tabla hacia otro esquema" -#: commands/tablecmds.c:16594 +#: commands/tablecmds.c:17288 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "ya existe una relación llamada «%s» en el esquema «%s»" -#: commands/tablecmds.c:17006 +#: commands/tablecmds.c:17713 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "«%s» no es una tabla o vista materializada" -#: commands/tablecmds.c:17184 +#: commands/tablecmds.c:17866 #, c-format msgid "\"%s\" is not a composite type" msgstr "«%s» no es un tipo compuesto" -#: commands/tablecmds.c:17212 -#, fuzzy, c-format -#| msgid "cannot change owner of index \"%s\"" +#: commands/tablecmds.c:17896 +#, c-format msgid "cannot change schema of index \"%s\"" -msgstr "no se puede cambiar el dueño del índice «%s»" +msgstr "no se puede cambiar el esquema del índice «%s»" -#: commands/tablecmds.c:17214 commands/tablecmds.c:17226 -#, fuzzy, c-format -#| msgid "Change the ownership of the index's table, instead." +#: commands/tablecmds.c:17898 commands/tablecmds.c:17912 +#, c-format msgid "Change the schema of the table instead." -msgstr "Considere cambiar el dueño de la tabla en vez de cambiar el dueño del índice." +msgstr "Cambie el esquema de la tabla en su lugar." -#: commands/tablecmds.c:17218 -#, fuzzy, c-format -#| msgid "cannot convert Perl hash to non-composite type %s" +#: commands/tablecmds.c:17902 +#, c-format msgid "cannot change schema of composite type \"%s\"" -msgstr "no se puede convertir un hash de Perl al tipo no compuesto %s" +msgstr "no se puede cambiar el esquema del tipo compuesto «%s»" -#: commands/tablecmds.c:17224 -#, fuzzy, c-format -#| msgid "cannot change TOAST relation \"%s\"" +#: commands/tablecmds.c:17910 +#, c-format msgid "cannot change schema of TOAST table \"%s\"" -msgstr "no se puede cambiar la relación TOAST «%s»" +msgstr "no se puede cambiar el esquema de la relación TOAST «%s»" -#: commands/tablecmds.c:17256 +#: commands/tablecmds.c:17942 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "no se puede usar la estrategia de particionamiento «list» con más de una columna" -#: commands/tablecmds.c:17322 +#: commands/tablecmds.c:18008 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "la columna «%s» nombrada en llave de particionamiento no existe" -#: commands/tablecmds.c:17330 +#: commands/tablecmds.c:18016 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "no se puede usar la columna de sistema «%s» en llave de particionamiento" -#: commands/tablecmds.c:17341 commands/tablecmds.c:17455 +#: commands/tablecmds.c:18027 commands/tablecmds.c:18117 #, c-format msgid "cannot use generated column in partition key" msgstr "no se puede usar una columna generada en llave de particionamiento" -#: commands/tablecmds.c:17342 commands/tablecmds.c:17456 commands/trigger.c:663 -#: rewrite/rewriteHandler.c:934 rewrite/rewriteHandler.c:969 +#: commands/tablecmds.c:18100 #, c-format -msgid "Column \"%s\" is a generated column." -msgstr "La columna «%s» es una columna generada." +msgid "partition key expressions cannot contain system column references" +msgstr "las expresiones en la llave de particionamiento no pueden contener referencias a columnas de sistema" -#: commands/tablecmds.c:17418 +#: commands/tablecmds.c:18147 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "las funciones utilizadas en expresiones de la llave de particionamiento deben estar marcadas IMMUTABLE" -#: commands/tablecmds.c:17438 -#, c-format -msgid "partition key expressions cannot contain system column references" -msgstr "las expresiones en la llave de particionamiento no pueden contener referencias a columnas de sistema" - -#: commands/tablecmds.c:17468 +#: commands/tablecmds.c:18156 #, c-format msgid "cannot use constant expression as partition key" msgstr "no se pueden usar expresiones constantes como llave de particionamiento" -#: commands/tablecmds.c:17489 +#: commands/tablecmds.c:18177 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "no se pudo determinar qué ordenamiento (collation) usar para la expresión de particionamiento" -#: commands/tablecmds.c:17524 +#: commands/tablecmds.c:18212 #, c-format msgid "You must specify a hash operator class or define a default hash operator class for the data type." msgstr "Debe especificar una clase de operadores hash, o definir una clase de operadores por omisión para hash para el tipo de datos." -#: commands/tablecmds.c:17530 +#: commands/tablecmds.c:18218 #, c-format msgid "You must specify a btree operator class or define a default btree operator class for the data type." msgstr "Debe especificar una clase de operadores btree, o definir una clase de operadores por omisión para btree para el tipo de datos." -#: commands/tablecmds.c:17781 +#: commands/tablecmds.c:18469 #, c-format msgid "\"%s\" is already a partition" msgstr "«%s» ya es una partición" -#: commands/tablecmds.c:17787 +#: commands/tablecmds.c:18475 #, c-format msgid "cannot attach a typed table as partition" msgstr "no puede adjuntar tabla tipada como partición" -#: commands/tablecmds.c:17803 +#: commands/tablecmds.c:18491 #, c-format msgid "cannot attach inheritance child as partition" msgstr "no puede adjuntar hija de herencia como partición" -#: commands/tablecmds.c:17817 +#: commands/tablecmds.c:18505 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "no puede adjuntar ancestro de herencia como partición" -#: commands/tablecmds.c:17851 +#: commands/tablecmds.c:18539 #, c-format msgid "cannot attach a temporary relation as partition of permanent relation \"%s\"" msgstr "no se puede adjuntar una relación temporal como partición de la relación permanente «%s»" -#: commands/tablecmds.c:17859 +#: commands/tablecmds.c:18547 #, c-format msgid "cannot attach a permanent relation as partition of temporary relation \"%s\"" msgstr "no se puede adjuntar una relación permanente como partición de la relación temporal «%s»" -#: commands/tablecmds.c:17867 +#: commands/tablecmds.c:18555 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "no se puede adjuntar como partición de una relación temporal de otra sesión" -#: commands/tablecmds.c:17874 +#: commands/tablecmds.c:18562 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "no se adjuntar una relación temporal de otra sesión como partición" -#: commands/tablecmds.c:17894 +#: commands/tablecmds.c:18582 +#, c-format +msgid "table \"%s\" being attached contains an identity column \"%s\"" +msgstr "la tabla «%s» siendo adjuntada contiene la columna de identidad «%s»" + +#: commands/tablecmds.c:18584 +#, c-format +msgid "The new partition may not contain an identity column." +msgstr "La nueva partición no puede contener una columna de identidad." + +#: commands/tablecmds.c:18592 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "la tabla «%s» contiene la columna «%s» no encontrada en el padre «%s»" -#: commands/tablecmds.c:17897 +#: commands/tablecmds.c:18595 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "La nueva partición sólo puede contener las columnas presentes en el padre." -#: commands/tablecmds.c:17909 +#: commands/tablecmds.c:18607 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "el trigger «%s» impide a la tabla «%s» devenir partición" -#: commands/tablecmds.c:17911 +#: commands/tablecmds.c:18609 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "Los triggers ROW con tablas de transición no están soportados en particiones." -#: commands/tablecmds.c:18090 +#: commands/tablecmds.c:18785 #, c-format msgid "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "no se puede adjuntar la tabla foránea «%s» como partición de la tabla particionada «%s»" -#: commands/tablecmds.c:18093 +#: commands/tablecmds.c:18788 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "La tabla particionada «%s» contiene índices únicos." -#: commands/tablecmds.c:18406 +#: commands/tablecmds.c:19110 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "no se puede desprender particiones concurrentemente cuando existe una partición por omisión" -#: commands/tablecmds.c:18515 +#: commands/tablecmds.c:19219 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "la tabla particionada «%s» fue eliminada concurrentemente" -#: commands/tablecmds.c:18521 +#: commands/tablecmds.c:19225 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "la partición «%s» fue eliminada concurrentemente" -#: commands/tablecmds.c:19036 commands/tablecmds.c:19056 -#: commands/tablecmds.c:19077 commands/tablecmds.c:19096 -#: commands/tablecmds.c:19138 +#: commands/tablecmds.c:19839 commands/tablecmds.c:19859 +#: commands/tablecmds.c:19880 commands/tablecmds.c:19899 +#: commands/tablecmds.c:19941 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "no se puede adjuntar el índice «%s» como partición del índice «%s»" -#: commands/tablecmds.c:19039 +#: commands/tablecmds.c:19842 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "El índice «%s» ya está adjunto a otro índice." -#: commands/tablecmds.c:19059 +#: commands/tablecmds.c:19862 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "El índice «%s» no es un índice en una partición de la tabla «%s»." -#: commands/tablecmds.c:19080 +#: commands/tablecmds.c:19883 #, c-format msgid "The index definitions do not match." msgstr "Las definiciones de los índices no coinciden." -#: commands/tablecmds.c:19099 +#: commands/tablecmds.c:19902 #, c-format msgid "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint exists for index \"%s\"." msgstr "El índice «%s» pertenece a una restricción en la tabla «%s», pero no existe una restricción para el índice «%s»." -#: commands/tablecmds.c:19141 +#: commands/tablecmds.c:19944 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "Otro índice ya está adjunto para la partición «%s»." -#: commands/tablecmds.c:19370 +#: commands/tablecmds.c:20180 #, c-format msgid "column data type %s does not support compression" msgstr "el tipo de dato de columna %s no soporta compresión" -#: commands/tablecmds.c:19377 +#: commands/tablecmds.c:20187 #, c-format msgid "invalid compression method \"%s\"" msgstr "método de compresión «%s» no válido" -#: commands/tablecmds.c:19403 +#: commands/tablecmds.c:20213 #, c-format msgid "invalid storage type \"%s\"" msgstr "tipo de almacenamiento no válido «%s»" -#: commands/tablecmds.c:19413 +#: commands/tablecmds.c:20223 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "el tipo de datos %s de la columna sólo puede tener almacenamiento PLAIN" -#: commands/tablespace.c:199 commands/tablespace.c:650 +#: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" msgstr "«%s» existe pero no es un directorio" -#: commands/tablespace.c:230 +#: commands/tablespace.c:224 #, c-format msgid "permission denied to create tablespace \"%s\"" msgstr "se ha denegado el permiso para crear el tablespace «%s»" -#: commands/tablespace.c:232 +#: commands/tablespace.c:226 #, c-format msgid "Must be superuser to create a tablespace." msgstr "Debe ser superusuario para crear tablespaces." -#: commands/tablespace.c:248 +#: commands/tablespace.c:242 #, c-format msgid "tablespace location cannot contain single quotes" msgstr "la ruta del tablespace no puede contener comillas simples" -#: commands/tablespace.c:261 +#: commands/tablespace.c:255 #, c-format msgid "tablespace location must be an absolute path" msgstr "la ubicación del tablespace debe ser una ruta absoluta" -#: commands/tablespace.c:273 +#: commands/tablespace.c:267 #, c-format msgid "tablespace location \"%s\" is too long" msgstr "la ruta «%s» del tablespace es demasiado larga" -#: commands/tablespace.c:280 +#: commands/tablespace.c:274 #, c-format msgid "tablespace location should not be inside the data directory" msgstr "la ubicación del tablespace no debe estar dentro del directorio de datos" -#: commands/tablespace.c:289 commands/tablespace.c:976 +#: commands/tablespace.c:283 commands/tablespace.c:970 #, c-format msgid "unacceptable tablespace name \"%s\"" msgstr "el nombre de tablespace «%s» es inaceptable" -#: commands/tablespace.c:291 commands/tablespace.c:977 +#: commands/tablespace.c:285 commands/tablespace.c:971 #, c-format msgid "The prefix \"pg_\" is reserved for system tablespaces." msgstr "El prefijo «pg_» está reservado para tablespaces del sistema." -#: commands/tablespace.c:310 commands/tablespace.c:998 +#: commands/tablespace.c:304 commands/tablespace.c:992 #, c-format msgid "tablespace \"%s\" already exists" msgstr "el tablespace «%s» ya existe" -#: commands/tablespace.c:326 -#, fuzzy, c-format -#| msgid "pg_type OID value not set when in binary upgrade mode" +#: commands/tablespace.c:320 +#, c-format msgid "pg_tablespace OID value not set when in binary upgrade mode" -msgstr "el valor de OID de pg_type no se definió en modo de actualización binaria" +msgstr "el valor de OID de pg_tablespace no se definió en modo de actualización binaria" -#: commands/tablespace.c:431 commands/tablespace.c:959 -#: commands/tablespace.c:1048 commands/tablespace.c:1117 -#: commands/tablespace.c:1263 commands/tablespace.c:1466 +#: commands/tablespace.c:425 commands/tablespace.c:953 +#: commands/tablespace.c:1042 commands/tablespace.c:1111 +#: commands/tablespace.c:1257 commands/tablespace.c:1460 #, c-format msgid "tablespace \"%s\" does not exist" msgstr "no existe el tablespace «%s»" -#: commands/tablespace.c:437 +#: commands/tablespace.c:431 #, c-format msgid "tablespace \"%s\" does not exist, skipping" msgstr "el tablespace «%s» no existe, omitiendo" -#: commands/tablespace.c:463 +#: commands/tablespace.c:457 #, c-format msgid "tablespace \"%s\" cannot be dropped because some objects depend on it" msgstr "no se puede eliminar el tablespace «%s» porque otros objetos dependen de él" -#: commands/tablespace.c:530 +#: commands/tablespace.c:524 #, c-format msgid "tablespace \"%s\" is not empty" msgstr "el tablespace «%s» no está vacío" -#: commands/tablespace.c:617 +#: commands/tablespace.c:611 #, c-format msgid "directory \"%s\" does not exist" msgstr "no existe el directorio «%s»" -#: commands/tablespace.c:618 +#: commands/tablespace.c:612 #, c-format msgid "Create this directory for the tablespace before restarting the server." msgstr "Cree este directorio para el tablespace antes de reiniciar el servidor." -#: commands/tablespace.c:623 +#: commands/tablespace.c:617 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "no se pudo definir los permisos del directorio «%s»: %m" -#: commands/tablespace.c:655 +#: commands/tablespace.c:649 #, c-format msgid "directory \"%s\" already in use as a tablespace" msgstr "el directorio «%s» ya está siendo usado como tablespace" -#: commands/tablespace.c:833 commands/tablespace.c:919 +#: commands/tablespace.c:827 commands/tablespace.c:913 #, c-format msgid "could not remove symbolic link \"%s\": %m" msgstr "no se pudo eliminar el enlace simbólico «%s»: %m" -#: commands/tablespace.c:842 commands/tablespace.c:927 +#: commands/tablespace.c:836 commands/tablespace.c:921 #, c-format msgid "\"%s\" is not a directory or symbolic link" msgstr "«%s» no es un directorio o enlace simbólico" -#: commands/tablespace.c:1122 +#: commands/tablespace.c:1116 #, c-format msgid "Tablespace \"%s\" does not exist." msgstr "No existe el tablespace «%s»." -#: commands/tablespace.c:1568 +#: commands/tablespace.c:1562 #, c-format msgid "directories for tablespace %u could not be removed" msgstr "algunos directorios para el tablespace %u no pudieron eliminarse" -#: commands/tablespace.c:1570 +#: commands/tablespace.c:1564 #, c-format msgid "You can remove the directories manually if necessary." msgstr "Puede eliminar los directorios manualmente, si es necesario." -#: commands/trigger.c:232 commands/trigger.c:243 +#: commands/trigger.c:225 commands/trigger.c:236 #, c-format msgid "\"%s\" is a table" msgstr "«%s» es una tabla" -#: commands/trigger.c:234 commands/trigger.c:245 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "Tables cannot have INSTEAD OF triggers." -msgstr "Las tablas no pueden tener disparadores INSTEAD OF." +msgstr "Las tablas no pueden tener “triggers” INSTEAD OF." -#: commands/trigger.c:266 +#: commands/trigger.c:259 #, c-format msgid "\"%s\" is a partitioned table" msgstr "«%s» es una tabla particionada" -#: commands/trigger.c:268 -#, fuzzy, c-format -#| msgid "ROW triggers with transition tables are not supported on partitions." +#: commands/trigger.c:261 +#, c-format msgid "ROW triggers with transition tables are not supported on partitioned tables." -msgstr "Los triggers ROW con tablas de transición no están soportados en particiones." +msgstr "Los triggers ROW con tablas de transición no están soportados en tablas particionadas." -#: commands/trigger.c:280 commands/trigger.c:287 commands/trigger.c:451 +#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 #, c-format msgid "\"%s\" is a view" msgstr "«%s» es una vista" -#: commands/trigger.c:282 +#: commands/trigger.c:275 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." -msgstr "Las vistas no pueden tener disparadores BEFORE o AFTER a nivel de fila." +msgstr "Las vistas no pueden tener “triggers” BEFORE o AFTER a nivel de fila." -#: commands/trigger.c:289 +#: commands/trigger.c:282 #, c-format msgid "Views cannot have TRUNCATE triggers." -msgstr "Las vistas no pueden tener disparadores TRUNCATE." +msgstr "Las vistas no pueden tener “triggers” TRUNCATE." -#: commands/trigger.c:297 commands/trigger.c:309 commands/trigger.c:444 +#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 #, c-format msgid "\"%s\" is a foreign table" msgstr "«%s» es una tabla foránea" -#: commands/trigger.c:299 +#: commands/trigger.c:292 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." -msgstr "Las tablas foráneas no pueden tener disparadores INSTEAD OF." +msgstr "Las tablas foráneas no pueden tener “triggers” INSTEAD OF." -#: commands/trigger.c:311 +#: commands/trigger.c:304 #, c-format msgid "Foreign tables cannot have constraint triggers." -msgstr "Las tablas foráneas no pueden tener disparadores de restricción." +msgstr "Las tablas foráneas no pueden tener “triggers” de restricción." -#: commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1439 -#, fuzzy, c-format -#| msgid "relation \"%s\" does not exist" +#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 +#, c-format msgid "relation \"%s\" cannot have triggers" -msgstr "no existe la relación «%s»" +msgstr "la relación «%s» no puede tener triggers." -#: commands/trigger.c:387 +#: commands/trigger.c:380 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" -msgstr "los disparadores TRUNCATE FOR EACH ROW no están soportados" +msgstr "los “triggers” TRUNCATE FOR EACH ROW no están soportados" -#: commands/trigger.c:395 +#: commands/trigger.c:388 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" -msgstr "los disparadores INSTEAD OF deben ser FOR EACH ROW" +msgstr "los “triggers” INSTEAD OF deben ser FOR EACH ROW" -#: commands/trigger.c:399 +#: commands/trigger.c:392 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" -msgstr "los disparadores INSTEAD OF no pueden tener condiciones WHEN" +msgstr "los “triggers” INSTEAD OF no pueden tener condiciones WHEN" -#: commands/trigger.c:403 +#: commands/trigger.c:396 #, c-format msgid "INSTEAD OF triggers cannot have column lists" -msgstr "los disparadores INSTEAD OF no pueden tener listas de columnas" +msgstr "los “triggers” INSTEAD OF no pueden tener listas de columnas" -#: commands/trigger.c:432 +#: commands/trigger.c:425 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "dar nombre a una variable ROW en la cláusula REFERENCING no está soportado" -#: commands/trigger.c:433 +#: commands/trigger.c:426 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "utilice OLD TABLE o NEW TABLE para nombrar tablas de transición." -#: commands/trigger.c:446 +#: commands/trigger.c:439 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "Las tablas foráneas no pueden tener tablas de transición." -#: commands/trigger.c:453 +#: commands/trigger.c:446 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "Las triggers en vistas no pueden tener tablas de transición." -#: commands/trigger.c:469 +#: commands/trigger.c:462 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "los triggers ROW con tablas de transición no están soportados en particiones" -#: commands/trigger.c:473 +#: commands/trigger.c:466 #, c-format msgid "ROW triggers with transition tables are not supported on inheritance children" msgstr "los triggers ROW con tablas de transición no están soportados con hijas de herencia" -#: commands/trigger.c:479 +#: commands/trigger.c:472 #, c-format msgid "transition table name can only be specified for an AFTER trigger" -msgstr "el nombre de la tabla de transición solo se puede especificar para un disparador AFTER" +msgstr "el nombre de la tabla de transición solo se puede especificar para un “trigger” AFTER" -#: commands/trigger.c:484 +#: commands/trigger.c:477 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "los triggers TRUNCATE con tablas de transición no están soportados" -#: commands/trigger.c:501 +#: commands/trigger.c:494 #, c-format msgid "transition tables cannot be specified for triggers with more than one event" msgstr "las tablas de transición no pueden especificarse para triggers con más de un evento" -#: commands/trigger.c:512 +#: commands/trigger.c:505 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "las tablas de transición no pueden especificarse para triggers con lista de columnas" -#: commands/trigger.c:529 +#: commands/trigger.c:522 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" -msgstr "NEW TABLE sólo se puede especificar para un disparador INSERT o UPDATE" +msgstr "NEW TABLE sólo se puede especificar para un “trigger” INSERT o UPDATE" -#: commands/trigger.c:534 +#: commands/trigger.c:527 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE no se puede especificar varias veces" -#: commands/trigger.c:544 +#: commands/trigger.c:537 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" -msgstr "OLD TABLE sólo se puede especificar para un disparador DELETE o UPDATE" +msgstr "OLD TABLE sólo se puede especificar para un “trigger” DELETE o UPDATE" -#: commands/trigger.c:549 +#: commands/trigger.c:542 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE no se puede especificar varias veces" -#: commands/trigger.c:559 +#: commands/trigger.c:552 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "el nombre de OLD TABLE y el nombre de NEW TABLE no pueden ser iguales" -#: commands/trigger.c:623 commands/trigger.c:636 +#: commands/trigger.c:616 commands/trigger.c:629 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" -msgstr "la condición WHEN de un disparador por sentencias no pueden referirse a los valores de las columnas" +msgstr "la condición WHEN de un “trigger” por sentencias no pueden referirse a los valores de las columnas" -#: commands/trigger.c:628 +#: commands/trigger.c:621 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" -msgstr "la condición WHEN de un disparador en INSERT no puede referirse a valores OLD" +msgstr "la condición WHEN de un “trigger” en INSERT no puede referirse a valores OLD" -#: commands/trigger.c:641 +#: commands/trigger.c:634 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" -msgstr "la condición WHEN de un disparador en DELETE no puede referirse a valores NEW" +msgstr "la condición WHEN de un “trigger” en DELETE no puede referirse a valores NEW" -#: commands/trigger.c:646 +#: commands/trigger.c:639 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" -msgstr "la condición WHEN de un disparador BEFORE no puede referirse a columnas de sistema de NEW" +msgstr "la condición WHEN de un “trigger” BEFORE no puede referirse a columnas de sistema de NEW" -#: commands/trigger.c:654 commands/trigger.c:662 +#: commands/trigger.c:647 commands/trigger.c:655 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "la condición WHEN del trigger BEFORE no puede hacer referencia a columnas NEW generadas" -#: commands/trigger.c:655 +#: commands/trigger.c:648 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "Se utiliza una referencia de la tupla completa, y la tabla contiene columnas generadas" -#: commands/trigger.c:770 commands/trigger.c:1614 +#: commands/trigger.c:763 commands/trigger.c:1607 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "ya existe un trigger «%s» para la relación «%s»" -#: commands/trigger.c:783 -#, fuzzy, c-format -#| msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" +#: commands/trigger.c:776 +#, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" -msgstr "disparador «%s» para la relación «%s» es un disparador de restricción" +msgstr "trigger «%s» para la relación «%s» es interno o derivado" -#: commands/trigger.c:802 +#: commands/trigger.c:795 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" -msgstr "disparador «%s» para la relación «%s» es un disparador de restricción" +msgstr "“trigger” «%s» para la relación «%s» es un “trigger” de restricción" -#: commands/trigger.c:1404 commands/trigger.c:1557 commands/trigger.c:1838 +#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "no existe el trigger «%s» para la tabla «%s»" -#: commands/trigger.c:1529 -#, fuzzy, c-format -#| msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" +#: commands/trigger.c:1522 +#, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" -msgstr "no hay una entrada en pg_constraint para el trigger «%s» en tabla «%s»" +msgstr "no se puede cambiar el nombre del trigger «%s» en tabla «%s»" -#: commands/trigger.c:1531 -#, fuzzy, c-format -#| msgid "Change the ownership of the index's table, instead." +#: commands/trigger.c:1524 +#, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." -msgstr "Considere cambiar el dueño de la tabla en vez de cambiar el dueño del índice." +msgstr "Cambie el nombre del trigger en la tabla particionada «%s» en su lugar." -#: commands/trigger.c:1631 -#, fuzzy, c-format -#| msgid "cannot alter constraint \"%s\" on relation \"%s\"" +#: commands/trigger.c:1624 +#, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" -msgstr "no se puede modificar la restricción «%s» en la relación «%s»" +msgstr "se renombró el trigger «%s» en la relación «%s»" -#: commands/trigger.c:1777 +#: commands/trigger.c:1770 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "permiso denegado: «%s» es un trigger de sistema" -#: commands/trigger.c:2386 +#: commands/trigger.c:2379 #, c-format msgid "trigger function %u returned null value" msgstr "la función de trigger %u ha retornado un valor null" -#: commands/trigger.c:2446 commands/trigger.c:2664 commands/trigger.c:2917 -#: commands/trigger.c:3252 +#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 +#: commands/trigger.c:3263 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "un trigger BEFORE STATEMENT no puede retornar un valor" -#: commands/trigger.c:2522 +#: commands/trigger.c:2515 #, c-format msgid "moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported" msgstr "mover registros a otra partición durante un trigger BEFORE FOR EACH ROW no está soportado" -#: commands/trigger.c:2523 +#: commands/trigger.c:2516 #, c-format msgid "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." msgstr "Antes de ejecutar el trigger «%s», la fila iba a estar en la partición «%s.%s»." -#: commands/trigger.c:3329 executor/nodeModifyTable.c:2363 -#: executor/nodeModifyTable.c:2446 -#, c-format -msgid "tuple to be updated was already modified by an operation triggered by the current command" -msgstr "el registro a ser actualizado ya fue modificado por una operación disparada por la orden actual" - -#: commands/trigger.c:3330 executor/nodeModifyTable.c:1531 -#: executor/nodeModifyTable.c:1605 executor/nodeModifyTable.c:2364 -#: executor/nodeModifyTable.c:2447 executor/nodeModifyTable.c:3077 +#: commands/trigger.c:3341 executor/nodeModifyTable.c:1541 +#: executor/nodeModifyTable.c:1615 executor/nodeModifyTable.c:2377 +#: executor/nodeModifyTable.c:2468 executor/nodeModifyTable.c:3132 +#: executor/nodeModifyTable.c:3302 #, c-format msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows." -msgstr "Considere usar un disparador AFTER en lugar de un disparador BEFORE para propagar cambios a otros registros." +msgstr "Considere usar un “trigger” AFTER en lugar de un “trigger” BEFORE para propagar cambios a otros registros." -#: commands/trigger.c:3371 executor/nodeLockRows.c:228 -#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:308 -#: executor/nodeModifyTable.c:1547 executor/nodeModifyTable.c:2381 -#: executor/nodeModifyTable.c:2589 +#: commands/trigger.c:3382 executor/nodeLockRows.c:228 +#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:314 +#: executor/nodeModifyTable.c:1557 executor/nodeModifyTable.c:2394 +#: executor/nodeModifyTable.c:2618 #, c-format msgid "could not serialize access due to concurrent update" msgstr "no se pudo serializar el acceso debido a un update concurrente" -#: commands/trigger.c:3379 executor/nodeModifyTable.c:1637 -#: executor/nodeModifyTable.c:2464 executor/nodeModifyTable.c:2613 -#: executor/nodeModifyTable.c:2965 +#: commands/trigger.c:3390 executor/nodeModifyTable.c:1647 +#: executor/nodeModifyTable.c:2485 executor/nodeModifyTable.c:2642 +#: executor/nodeModifyTable.c:3150 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "no se pudo serializar el acceso debido a un delete concurrente" -#: commands/trigger.c:4555 +#: commands/trigger.c:4599 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" -msgstr "no se puede ejecutar un disparador postergado dentro de una operación restringida por seguridad" +msgstr "no se puede ejecutar un “trigger” postergado dentro de una operación restringida por seguridad" -#: commands/trigger.c:5738 +#: commands/trigger.c:5780 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "la restricción «%s» no es postergable" -#: commands/trigger.c:5761 +#: commands/trigger.c:5803 #, c-format msgid "constraint \"%s\" does not exist" msgstr "no existe la restricción «%s»" -#: commands/tsearchcmds.c:118 commands/tsearchcmds.c:635 +#: commands/tsearchcmds.c:124 commands/tsearchcmds.c:641 #, c-format msgid "function %s should return type %s" msgstr "la función %s debería retornar el tipo %s" -#: commands/tsearchcmds.c:194 +#: commands/tsearchcmds.c:200 #, c-format msgid "must be superuser to create text search parsers" msgstr "debe ser superusuario para crear analizadores de búsqueda en texto" -#: commands/tsearchcmds.c:247 +#: commands/tsearchcmds.c:253 #, c-format msgid "text search parser parameter \"%s\" not recognized" msgstr "el parámetro de analizador de búsqueda en texto «%s» no es reconocido" -#: commands/tsearchcmds.c:257 +#: commands/tsearchcmds.c:263 #, c-format msgid "text search parser start method is required" msgstr "el método «start» del analizador de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:262 +#: commands/tsearchcmds.c:268 #, c-format msgid "text search parser gettoken method is required" msgstr "el método «gettoken» del analizador de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:267 +#: commands/tsearchcmds.c:273 #, c-format msgid "text search parser end method is required" msgstr "el método «end» del analizador de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:272 +#: commands/tsearchcmds.c:278 #, c-format msgid "text search parser lextypes method is required" msgstr "el método «lextypes» del analizador de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:366 +#: commands/tsearchcmds.c:372 #, c-format msgid "text search template \"%s\" does not accept options" msgstr "la plantilla de búsquede en texto «%s» no acepta opciones" -#: commands/tsearchcmds.c:440 +#: commands/tsearchcmds.c:446 #, c-format msgid "text search template is required" msgstr "la plantilla de búsqueda en texto es obligatoria" -#: commands/tsearchcmds.c:701 +#: commands/tsearchcmds.c:707 #, c-format msgid "must be superuser to create text search templates" msgstr "debe ser superusuario para crear una plantilla de búsqueda en texto" -#: commands/tsearchcmds.c:743 +#: commands/tsearchcmds.c:749 #, c-format msgid "text search template parameter \"%s\" not recognized" msgstr "el parámetro de la plantilla de búsqueda en texto «%s» no es reconocido" -#: commands/tsearchcmds.c:753 +#: commands/tsearchcmds.c:759 #, c-format msgid "text search template lexize method is required" msgstr "el método «lexize» de la plantilla de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:933 +#: commands/tsearchcmds.c:939 #, c-format msgid "text search configuration parameter \"%s\" not recognized" msgstr "el parámetro de configuración de búsqueda en texto «%s» no es reconocido" -#: commands/tsearchcmds.c:940 +#: commands/tsearchcmds.c:946 #, c-format msgid "cannot specify both PARSER and COPY options" msgstr "no se puede especificar simultáneamente las opciones PARSER y COPY" -#: commands/tsearchcmds.c:976 +#: commands/tsearchcmds.c:982 #, c-format msgid "text search parser is required" msgstr "el analizador de búsqueda en texto es obligatorio" -#: commands/tsearchcmds.c:1241 +#: commands/tsearchcmds.c:1277 #, c-format msgid "token type \"%s\" does not exist" msgstr "no existe el tipo de elemento «%s»" -#: commands/tsearchcmds.c:1501 +#: commands/tsearchcmds.c:1540 #, c-format msgid "mapping for token type \"%s\" does not exist" msgstr "no existe un mapeo para el tipo de elemento «%s»" -#: commands/tsearchcmds.c:1507 +#: commands/tsearchcmds.c:1546 #, c-format msgid "mapping for token type \"%s\" does not exist, skipping" msgstr "el mapeo para el tipo de elemento «%s» no existe, omitiendo" -#: commands/tsearchcmds.c:1670 commands/tsearchcmds.c:1785 +#: commands/tsearchcmds.c:1707 commands/tsearchcmds.c:1822 #, c-format msgid "invalid parameter list format: \"%s\"" msgstr "el formato de la lista de parámetros no es válido: «%s»" -#: commands/typecmds.c:217 +#: commands/typecmds.c:221 #, c-format msgid "must be superuser to create a base type" msgstr "debe ser superusuario para crear un tipo base" -#: commands/typecmds.c:275 +#: commands/typecmds.c:279 #, c-format msgid "Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE." msgstr "Cree el tipo como un tipo inconcluso, luego cree sus funciones de I/O, luego haga un CREATE TYPE completo." -#: commands/typecmds.c:327 commands/typecmds.c:1450 commands/typecmds.c:4257 +#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "el atributo de tipo «%s» no es reconocido" -#: commands/typecmds.c:382 +#: commands/typecmds.c:386 #, c-format msgid "invalid type category \"%s\": must be simple ASCII" msgstr "la categoría de tipo «%s» no es válida: debe ser ASCII simple" -#: commands/typecmds.c:401 +#: commands/typecmds.c:405 #, c-format msgid "array element type cannot be %s" msgstr "el tipo de elemento de array no puede ser %s" -#: commands/typecmds.c:433 +#: commands/typecmds.c:437 #, c-format msgid "alignment \"%s\" not recognized" msgstr "el alineamiento «%s» no es reconocido" -#: commands/typecmds.c:450 commands/typecmds.c:4131 +#: commands/typecmds.c:454 commands/typecmds.c:4354 #, c-format msgid "storage \"%s\" not recognized" msgstr "el almacenamiento «%s» no es reconocido" -#: commands/typecmds.c:461 +#: commands/typecmds.c:465 #, c-format msgid "type input function must be specified" msgstr "debe especificarse la función de ingreso del tipo" -#: commands/typecmds.c:465 +#: commands/typecmds.c:469 #, c-format msgid "type output function must be specified" msgstr "debe especificarse la función de salida de tipo" -#: commands/typecmds.c:470 +#: commands/typecmds.c:474 #, c-format msgid "type modifier output function is useless without a type modifier input function" msgstr "la función de salida de modificadores de tipo es inútil sin una función de entrada de modificadores de tipo" -#: commands/typecmds.c:512 +#: commands/typecmds.c:516 #, c-format msgid "element type cannot be specified without a subscripting function" msgstr "no se puede especificar tipo de elemento sin una función de subindexación" -#: commands/typecmds.c:781 +#: commands/typecmds.c:785 #, c-format msgid "\"%s\" is not a valid base type for a domain" msgstr "«%s» no es un tipo de dato base válido para un dominio" -#: commands/typecmds.c:879 +#: commands/typecmds.c:883 #, c-format msgid "multiple default expressions" msgstr "múltiples expresiones default" -#: commands/typecmds.c:942 commands/typecmds.c:951 +#: commands/typecmds.c:946 commands/typecmds.c:955 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "las restricciones NULL/NOT NULL no coinciden" -#: commands/typecmds.c:967 +#: commands/typecmds.c:971 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "las restricciones «check» en dominios no pueden ser marcadas NO INHERIT" -#: commands/typecmds.c:976 commands/typecmds.c:2956 +#: commands/typecmds.c:980 commands/typecmds.c:2940 #, c-format msgid "unique constraints not possible for domains" msgstr "no se pueden poner restricciones de unicidad a un dominio" -#: commands/typecmds.c:982 commands/typecmds.c:2962 +#: commands/typecmds.c:986 commands/typecmds.c:2946 #, c-format msgid "primary key constraints not possible for domains" msgstr "no se pueden poner restricciones de llave primaria a un dominio" -#: commands/typecmds.c:988 commands/typecmds.c:2968 +#: commands/typecmds.c:992 commands/typecmds.c:2952 #, c-format msgid "exclusion constraints not possible for domains" msgstr "las restricciones de exclusión no son posibles para los dominios" -#: commands/typecmds.c:994 commands/typecmds.c:2974 +#: commands/typecmds.c:998 commands/typecmds.c:2958 #, c-format msgid "foreign key constraints not possible for domains" msgstr "no se pueden poner restricciones de llave foránea a un dominio" -#: commands/typecmds.c:1003 commands/typecmds.c:2983 +#: commands/typecmds.c:1007 commands/typecmds.c:2967 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "no se puede especificar la postergabilidad de las restricciones a un dominio" -#: commands/typecmds.c:1317 utils/cache/typcache.c:2561 +#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 #, c-format msgid "%s is not an enum" msgstr "%s no es un enum" -#: commands/typecmds.c:1458 +#: commands/typecmds.c:1468 #, c-format msgid "type attribute \"subtype\" is required" msgstr "el atributo de tipo «subtype» es obligatorio" -#: commands/typecmds.c:1463 +#: commands/typecmds.c:1473 #, c-format msgid "range subtype cannot be %s" msgstr "el subtipo de rango no puede ser %s" -#: commands/typecmds.c:1482 +#: commands/typecmds.c:1492 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "se especificó un ordenamiento (collation) al rango, pero el subtipo no soporta ordenamiento" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1502 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "no se puede especificar una función canónica sin antes crear un tipo inconcluso" -#: commands/typecmds.c:1493 +#: commands/typecmds.c:1503 #, c-format msgid "Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE." msgstr "Cree el tipo como un tipo inconcluso, luego cree su función de canonicalización, luego haga un CREATE TYPE completo." -#: commands/typecmds.c:1965 +#: commands/typecmds.c:1975 #, c-format msgid "type input function %s has multiple matches" msgstr "la función de entrada %s del tipo tiene múltiples coincidencias" -#: commands/typecmds.c:1983 +#: commands/typecmds.c:1993 #, c-format msgid "type input function %s must return type %s" msgstr "la función de entrada %s del tipo debe retornar %s" -#: commands/typecmds.c:1999 +#: commands/typecmds.c:2009 #, c-format msgid "type input function %s should not be volatile" msgstr "la función de entrada %s no debe ser volatile" -#: commands/typecmds.c:2027 +#: commands/typecmds.c:2037 #, c-format msgid "type output function %s must return type %s" msgstr "la función de salida %s del tipo debe retornar %s" -#: commands/typecmds.c:2034 +#: commands/typecmds.c:2044 #, c-format msgid "type output function %s should not be volatile" msgstr "la función de salida %s no debe ser volatile" -#: commands/typecmds.c:2063 +#: commands/typecmds.c:2073 #, c-format msgid "type receive function %s has multiple matches" msgstr "la función de recepción %s del tipo tiene múltiples coincidencias" -#: commands/typecmds.c:2081 +#: commands/typecmds.c:2091 #, c-format msgid "type receive function %s must return type %s" msgstr "la función de recepción %s del tipo debe retornar %s" -#: commands/typecmds.c:2088 +#: commands/typecmds.c:2098 #, c-format msgid "type receive function %s should not be volatile" msgstr "la función «receive» %s del tipo no debe ser volatile" -#: commands/typecmds.c:2116 +#: commands/typecmds.c:2126 #, c-format msgid "type send function %s must return type %s" msgstr "la función «send» %s del tipo debe retornar %s" -#: commands/typecmds.c:2123 +#: commands/typecmds.c:2133 #, c-format msgid "type send function %s should not be volatile" msgstr "la función «send» %s no debe ser volatile" -#: commands/typecmds.c:2150 +#: commands/typecmds.c:2160 #, c-format msgid "typmod_in function %s must return type %s" msgstr "la función typmod_in %s debe retornar tipo %s" -#: commands/typecmds.c:2157 +#: commands/typecmds.c:2167 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "la función de modificadores de tipo %s no debe ser volatile" -#: commands/typecmds.c:2184 +#: commands/typecmds.c:2194 #, c-format msgid "typmod_out function %s must return type %s" msgstr "la función typmod_out %s debe retornar tipo %s" -#: commands/typecmds.c:2191 +#: commands/typecmds.c:2201 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "la función de salida de modificadores de tipo %s no debe ser volatile" -#: commands/typecmds.c:2218 +#: commands/typecmds.c:2228 #, c-format msgid "type analyze function %s must return type %s" msgstr "la función de análisis %s del tipo debe retornar %s" -#: commands/typecmds.c:2247 +#: commands/typecmds.c:2257 #, c-format msgid "type subscripting function %s must return type %s" msgstr "la función de subindexación %s del tipo debe retornar %s" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2267 #, c-format msgid "user-defined types cannot use subscripting function %s" msgstr "los tipos definidos por el usuario no pueden usar la función de subindexación %s" -#: commands/typecmds.c:2303 +#: commands/typecmds.c:2313 #, c-format msgid "You must specify an operator class for the range type or define a default operator class for the subtype." msgstr "Debe especificar una clase de operadores para el tipo de rango, o definir una clase de operadores por omisión para el subtipo." -#: commands/typecmds.c:2334 +#: commands/typecmds.c:2344 #, c-format msgid "range canonical function %s must return range type" msgstr "la función canónica %s del rango debe retornar tipo de rango" -#: commands/typecmds.c:2340 +#: commands/typecmds.c:2350 #, c-format msgid "range canonical function %s must be immutable" msgstr "la función canónica %s del rango debe ser inmutable" -#: commands/typecmds.c:2376 +#: commands/typecmds.c:2386 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "la función «diff» de subtipo, %s, debe retornar tipo %s" -#: commands/typecmds.c:2383 +#: commands/typecmds.c:2393 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "la función «diff» de subtipo, %s, debe ser inmutable" -#: commands/typecmds.c:2410 +#: commands/typecmds.c:2420 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "el valor de OID de pg_type no se definió en modo de actualización binaria" -#: commands/typecmds.c:2443 +#: commands/typecmds.c:2453 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "el valor de OID de multirango de pg_type no se definió en modo de actualización binaria" -#: commands/typecmds.c:2476 +#: commands/typecmds.c:2486 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" -msgstr "el valor de OID de arreglo de multirango de pg_type no se definió en modo de actualización binaria" +msgstr "el valor de OID de array de multirango de pg_type no se definió en modo de actualización binaria" -#: commands/typecmds.c:2772 -#, c-format -msgid "column \"%s\" of table \"%s\" contains null values" -msgstr "la columna «%s» de la tabla «%s» contiene valores null" - -#: commands/typecmds.c:2885 commands/typecmds.c:3086 +#: commands/typecmds.c:2868 commands/typecmds.c:3093 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "no existe la restricción «%s» en el dominio «%s»" -#: commands/typecmds.c:2889 +#: commands/typecmds.c:2872 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "no existe la restricción «%s» en el dominio «%s», omitiendo" -#: commands/typecmds.c:3093 +#: commands/typecmds.c:3100 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "la restricción «%s» en el dominio «%s» no es una restricción «check»" -#: commands/typecmds.c:3194 +#: commands/typecmds.c:3180 +#, c-format +msgid "column \"%s\" of table \"%s\" contains null values" +msgstr "la columna «%s» de la tabla «%s» contiene valores null" + +#: commands/typecmds.c:3269 #, c-format msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint" msgstr "la columna «%s» de la relación «%s» contiene valores que violan la nueva restricción" -#: commands/typecmds.c:3423 commands/typecmds.c:3622 commands/typecmds.c:3703 -#: commands/typecmds.c:3889 +#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 +#: commands/typecmds.c:4073 #, c-format msgid "%s is not a domain" msgstr "%s no es un dominio" -#: commands/typecmds.c:3455 +#: commands/typecmds.c:3532 commands/typecmds.c:3686 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "el dominio «%2$s» ya contiene una restricción llamada «%1$s»" -#: commands/typecmds.c:3506 +#: commands/typecmds.c:3583 #, c-format msgid "cannot use table references in domain check constraint" msgstr "no se pueden usar referencias a tablas en restricción «check» para un dominio" -#: commands/typecmds.c:3634 commands/typecmds.c:3715 commands/typecmds.c:4006 +#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 #, c-format msgid "%s is a table's row type" msgstr "%s es el tipo de registro de una tabla" -#: commands/typecmds.c:3636 commands/typecmds.c:3717 commands/typecmds.c:4008 -#, c-format -msgid "Use ALTER TABLE instead." -msgstr "Considere usar ALTER TABLE." - -#: commands/typecmds.c:3642 commands/typecmds.c:3723 commands/typecmds.c:3921 +#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 #, c-format msgid "cannot alter array type %s" -msgstr "no se puede alterar el tipo de array «%s»" +msgstr "no se puede alterar el tipo de array %s" -#: commands/typecmds.c:3644 commands/typecmds.c:3725 commands/typecmds.c:3923 +#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 #, c-format msgid "You can alter type %s, which will alter the array type as well." msgstr "Puede alterar el tipo %s, lo cual alterará el tipo de array también." -#: commands/typecmds.c:3991 +#: commands/typecmds.c:3892 +#, c-format +msgid "cannot alter multirange type %s" +msgstr "no se puede alterar el tipo multirango %s" + +#: commands/typecmds.c:3895 +#, c-format +msgid "You can alter type %s, which will alter the multirange type as well." +msgstr "Puede alterar el tipo %s, lo cual alterará el tipo de multirango también." + +#: commands/typecmds.c:4202 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "ya existe un tipo llamado «%s» en el esquema «%s»" -#: commands/typecmds.c:4159 +#: commands/typecmds.c:4382 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "no se puede cambiar el almacenamiento del tipo a PLAIN" -#: commands/typecmds.c:4252 +#: commands/typecmds.c:4475 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "el atributo de tipo «%s» no puede ser cambiado" -#: commands/typecmds.c:4270 +#: commands/typecmds.c:4493 #, c-format msgid "must be superuser to alter a type" msgstr "debe ser superusuario para alterar un tipo" -#: commands/typecmds.c:4291 commands/typecmds.c:4300 +#: commands/typecmds.c:4514 commands/typecmds.c:4523 #, c-format msgid "%s is not a base type" msgstr "«%s» no es un tipo base" -#: commands/user.c:201 +#: commands/user.c:200 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSID ya no puede ser especificado" -#: commands/user.c:319 commands/user.c:325 commands/user.c:331 -#: commands/user.c:337 commands/user.c:343 +#: commands/user.c:318 commands/user.c:324 commands/user.c:330 +#: commands/user.c:336 commands/user.c:342 #, c-format msgid "permission denied to create role" msgstr "se ha denegado el permiso para crear el rol" -#: commands/user.c:320 +#: commands/user.c:319 #, c-format msgid "Only roles with the %s attribute may create roles." -msgstr "" +msgstr "Sólo los roles con el atributo %s pueden crear roles." -#: commands/user.c:326 commands/user.c:332 commands/user.c:338 -#: commands/user.c:344 +#: commands/user.c:325 commands/user.c:331 commands/user.c:337 +#: commands/user.c:343 #, c-format -msgid "Only roles with the %s attribute may create roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may create roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden crear roles con el atributo %s." -#: commands/user.c:355 commands/user.c:1393 commands/user.c:1400 -#: utils/adt/acl.c:5409 utils/adt/acl.c:5415 gram.y:16727 gram.y:16773 +#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 +#: utils/adt/acl.c:5574 utils/adt/acl.c:5580 gram.y:17310 gram.y:17356 #, c-format msgid "role name \"%s\" is reserved" msgstr "el nombre de rol «%s» está reservado" -#: commands/user.c:357 commands/user.c:1395 commands/user.c:1402 +#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "Los nombres de rol que empiezan con «pg_» están reservados." -#: commands/user.c:378 commands/user.c:1417 +#: commands/user.c:377 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "el rol «%s» ya existe" -#: commands/user.c:440 commands/user.c:925 +#: commands/user.c:439 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "la cadena vacía no es una contraseña válida, limpiando la contraseña" -#: commands/user.c:469 +#: commands/user.c:468 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "el valor de OID de pg_authid no se definió en modo de actualización binaria" -#: commands/user.c:653 commands/user.c:1011 -#, fuzzy -#| msgid "cannot alter inherited column \"%s\"" +#: commands/user.c:652 commands/user.c:1010 msgid "Cannot alter reserved roles." -msgstr "no se puede alterar la columna heredada «%s»" +msgstr "No se pueden alterar roles reservados." -#: commands/user.c:760 commands/user.c:766 commands/user.c:782 -#: commands/user.c:790 commands/user.c:804 commands/user.c:810 -#: commands/user.c:816 commands/user.c:825 commands/user.c:870 -#: commands/user.c:1033 commands/user.c:1044 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: commands/user.c:759 commands/user.c:765 commands/user.c:781 +#: commands/user.c:789 commands/user.c:803 commands/user.c:809 +#: commands/user.c:815 commands/user.c:824 commands/user.c:869 +#: commands/user.c:1032 commands/user.c:1043 +#, c-format msgid "permission denied to alter role" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para alterar el rol" -#: commands/user.c:761 commands/user.c:1034 +#: commands/user.c:760 commands/user.c:1033 #, c-format -msgid "Only roles with the %s attribute may alter roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may alter roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden alterar roles con el atributo %s." -#: commands/user.c:767 commands/user.c:805 commands/user.c:811 -#: commands/user.c:817 +#: commands/user.c:766 commands/user.c:804 commands/user.c:810 +#: commands/user.c:816 #, c-format msgid "Only roles with the %s attribute may change the %s attribute." -msgstr "" +msgstr "Sólo roles con el atributo %s pueden cambiar el atributo %s." -#: commands/user.c:783 commands/user.c:1045 +#: commands/user.c:782 commands/user.c:1044 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may alter this role." -msgstr "" +msgstr "Sólo los roles con el atributo %s y la opción %s en el rol «%s» pueden alterar este rol." -#: commands/user.c:791 +#: commands/user.c:790 #, c-format msgid "To change another role's password, the current user must have the %s attribute and the %s option on the role." -msgstr "" +msgstr "Para cambiar la password de otro rol, el usuario actual debe tener el atributo %s y la opción %s en el rol." -#: commands/user.c:826 +#: commands/user.c:825 #, c-format -msgid "Only roles with the %s option on role \"%s\" may add members." -msgstr "" +#| msgid "Only roles with the %s option on role \"%s\" may add members." +msgid "Only roles with the %s option on role \"%s\" may add or drop members." +msgstr "Sólo los roles con la opción %s en el rol «%s» pueden agregar miembros." -#: commands/user.c:871 +#: commands/user.c:870 #, c-format -msgid "The bootstrap user must have the %s attribute." -msgstr "" +msgid "The bootstrap superuser must have the %s attribute." +msgstr "El superusuario de \"bootstrap\" debe tener el atributo %s." -#: commands/user.c:1076 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: commands/user.c:1075 +#, c-format msgid "permission denied to alter setting" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para modificar la configuración" -#: commands/user.c:1077 +#: commands/user.c:1076 #, c-format msgid "Only roles with the %s attribute may alter settings globally." -msgstr "" +msgstr "Sólo los roles con el atributo %s pueden modificar parámetros de configuración globalmente." -#: commands/user.c:1101 commands/user.c:1173 commands/user.c:1179 +#: commands/user.c:1100 commands/user.c:1171 commands/user.c:1177 #, c-format msgid "permission denied to drop role" msgstr "se ha denegado el permiso para eliminar el rol" -#: commands/user.c:1102 +#: commands/user.c:1101 #, c-format msgid "Only roles with the %s attribute and the %s option on the target roles may drop roles." -msgstr "" +msgstr "Sólo los roles con el atributo %s y la opción %s en los roles de destino pueden borrar roles." -#: commands/user.c:1127 +#: commands/user.c:1125 #, c-format msgid "cannot use special role specifier in DROP ROLE" msgstr "no se puede usar un especificador especial de rol en DROP ROLE" -#: commands/user.c:1137 commands/user.c:1364 commands/variable.c:836 -#: commands/variable.c:839 commands/variable.c:923 commands/variable.c:926 -#: utils/adt/acl.c:359 utils/adt/acl.c:379 utils/adt/acl.c:5264 -#: utils/adt/acl.c:5312 utils/adt/acl.c:5340 utils/adt/acl.c:5359 -#: utils/adt/regproc.c:1551 utils/init/miscinit.c:757 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:851 +#: commands/variable.c:854 commands/variable.c:971 commands/variable.c:974 +#: utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5429 +#: utils/adt/acl.c:5477 utils/adt/acl.c:5505 utils/adt/acl.c:5524 +#: utils/adt/regproc.c:1571 utils/init/miscinit.c:799 #, c-format msgid "role \"%s\" does not exist" msgstr "no existe el rol «%s»" -#: commands/user.c:1142 +#: commands/user.c:1140 #, c-format msgid "role \"%s\" does not exist, skipping" msgstr "el rol «%s» no existe, omitiendo" -#: commands/user.c:1155 commands/user.c:1159 +#: commands/user.c:1153 commands/user.c:1157 #, c-format msgid "current user cannot be dropped" msgstr "el usuario activo no puede ser eliminado" -#: commands/user.c:1163 +#: commands/user.c:1161 #, c-format msgid "session user cannot be dropped" msgstr "no se puede eliminar un usuario de la sesión" -#: commands/user.c:1174 +#: commands/user.c:1172 #, c-format -msgid "Only roles with the %s attribute may drop roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may drop roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden borrar roles con el atributo %s." -#: commands/user.c:1180 +#: commands/user.c:1178 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may drop this role." -msgstr "" +msgstr "Sólo los roles con el atributo %s y la opción %s en el rol «%s» pueden borrar este rol." -#: commands/user.c:1306 +#: commands/user.c:1299 #, c-format msgid "role \"%s\" cannot be dropped because some objects depend on it" msgstr "no se puede eliminar el rol «%s» porque otros objetos dependen de él" -#: commands/user.c:1380 +#: commands/user.c:1373 #, c-format msgid "session user cannot be renamed" msgstr "no se puede cambiar el nombre a un usuario de la sesión" -#: commands/user.c:1384 +#: commands/user.c:1377 #, c-format msgid "current user cannot be renamed" msgstr "no se puede cambiar el nombre al usuario activo" -#: commands/user.c:1428 commands/user.c:1438 +#: commands/user.c:1421 commands/user.c:1431 #, c-format msgid "permission denied to rename role" msgstr "se ha denegado el permiso para cambiar el nombre al rol" -#: commands/user.c:1429 +#: commands/user.c:1422 #, c-format -msgid "Only roles with the %s attribute may rename roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may rename roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden cambiar nombre a roles con el atributo %s." -#: commands/user.c:1439 +#: commands/user.c:1432 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may rename this role." -msgstr "" +msgstr "Sólo los roles con el atributo %s y la opción %s en el rol «%s» pueden cambiar nombre a este rol." -#: commands/user.c:1461 +#: commands/user.c:1454 #, c-format msgid "MD5 password cleared because of role rename" msgstr "la contraseña MD5 fue borrada debido al cambio de nombre del rol" -#: commands/user.c:1525 gram.y:1263 +#: commands/user.c:1518 gram.y:1294 #, c-format msgid "unrecognized role option \"%s\"" msgstr "opción de rol «%s» no reconocida" -#: commands/user.c:1530 -#, fuzzy, c-format -#| msgid "unrecognized value for option %s: %s" +#: commands/user.c:1523 +#, c-format msgid "unrecognized value for role option \"%s\": \"%s\"" -msgstr "valor no reconocido para la opción %s: %s" +msgstr "valor no reconocido para la opción de rol «%s»: «%s»" -#: commands/user.c:1563 +#: commands/user.c:1556 #, c-format msgid "column names cannot be included in GRANT/REVOKE ROLE" msgstr "los nombres de columna no pueden ser incluidos en GRANT/REVOKE ROLE" -#: commands/user.c:1603 +#: commands/user.c:1596 #, c-format msgid "permission denied to drop objects" msgstr "se ha denegado el permiso para eliminar objetos" -#: commands/user.c:1604 +#: commands/user.c:1597 #, c-format msgid "Only roles with privileges of role \"%s\" may drop objects owned by it." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden borrar objetos de que es dueño." -#: commands/user.c:1632 commands/user.c:1643 +#: commands/user.c:1625 commands/user.c:1636 #, c-format msgid "permission denied to reassign objects" msgstr "se ha denegado el permiso para reasignar objetos" -#: commands/user.c:1633 +#: commands/user.c:1626 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects owned by it." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden reasignar objetos de que es dueño." -#: commands/user.c:1644 +#: commands/user.c:1637 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects to it." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden reasignar objetos a él." -#: commands/user.c:1740 +#: commands/user.c:1733 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "el rol «%s» no puede ser miembro de ningún rol" -#: commands/user.c:1753 +#: commands/user.c:1746 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "el rol «%s» es un miembro del rol «%s»" -#: commands/user.c:1793 commands/user.c:1819 -#, fuzzy, c-format -#| msgid "grant options cannot be granted back to your own grantor" +#: commands/user.c:1786 commands/user.c:1812 +#, c-format msgid "%s option cannot be granted back to your own grantor" -msgstr "la opción de grant no puede ser otorgada de vuelta a quien la otorgó" +msgstr "la opción %s no puede ser otorgada de vuelta a quien la otorgó" -#: commands/user.c:1896 -#, fuzzy, c-format -#| msgid "role \"%s\" is a member of role \"%s\"" +#: commands/user.c:1889 +#, c-format msgid "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" -msgstr "el rol «%s» es un miembro del rol «%s»" +msgstr "el rol «%s» ya recibió membresía en el rol «%s» por parte del rol «%s»" -#: commands/user.c:2031 -#, fuzzy, c-format -#| msgid "role \"%s\" cannot be a member of any role" +#: commands/user.c:2024 +#, c-format msgid "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" -msgstr "el rol «%s» no puede ser miembro de ningún rol" +msgstr "al rol «%s» no se le ha otorgado membresía en el rol «%s» por parte del rol «%s»" -#: commands/user.c:2131 +#: commands/user.c:2124 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "el rol «%s» no puede tener miembros explícitos" -#: commands/user.c:2142 commands/user.c:2165 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/user.c:2135 commands/user.c:2158 +#, c-format msgid "permission denied to grant role \"%s\"" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "se ha denegado el permiso para otorgar el rol «%s»" -#: commands/user.c:2144 +#: commands/user.c:2137 #, c-format -msgid "Only roles with the %s attribute may grant roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may grant roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden otorgar roles con el atributo %s." -#: commands/user.c:2149 commands/user.c:2172 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/user.c:2142 commands/user.c:2165 +#, c-format msgid "permission denied to revoke role \"%s\"" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "se ha denegado el permiso para revocar el rol «%s»" -#: commands/user.c:2151 +#: commands/user.c:2144 #, c-format -msgid "Only roles with the %s attribute may revoke roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may revoke roles with the %s attribute." +msgstr "Sólo los roles con el atributo %s pueden revocar roles con el atributo %s." -#: commands/user.c:2167 +#: commands/user.c:2160 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." -msgstr "" +msgstr "Sólo los roles con la opción %s en el rol «%s» pueden otorgar este rol." -#: commands/user.c:2174 +#: commands/user.c:2167 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." -msgstr "" +msgstr "Sólo los roles con la opción %s en el rol «%s» pueden revocar este rol." -#: commands/user.c:2254 commands/user.c:2263 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/user.c:2247 commands/user.c:2256 +#, c-format msgid "permission denied to grant privileges as role \"%s\"" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "se ha denegado el permiso para otorgar privilegio de rol «%s»" -#: commands/user.c:2256 +#: commands/user.c:2249 #, c-format msgid "Only roles with privileges of role \"%s\" may grant privileges as this role." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden otorgar privilegios como este rol." -#: commands/user.c:2265 -#, fuzzy, c-format -#| msgid "cannot use the \"%s\" option with the \"%s\" option" +#: commands/user.c:2258 +#, c-format msgid "The grantor must have the %s option on role \"%s\"." -msgstr "no se puede usar la opción «%s» junto con la opción «%s»" +msgstr "El otorgador debe tener la opción %s en el rol «%s»." -#: commands/user.c:2273 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/user.c:2266 +#, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "se ha denegado el permiso a revocar permisos otorgados por el rol «%s»" -#: commands/user.c:2275 +#: commands/user.c:2268 #, c-format msgid "Only roles with privileges of role \"%s\" may revoke privileges granted by this role." -msgstr "" +msgstr "Sólo los roles con privilegios del rol «%s» pueden revocar privilegios otorgados por este rol." -#: commands/user.c:2498 utils/adt/acl.c:1312 +#: commands/user.c:2491 utils/adt/acl.c:1324 #, c-format msgid "dependent privileges exist" msgstr "existen privilegios dependientes" -#: commands/user.c:2499 utils/adt/acl.c:1313 +#: commands/user.c:2492 utils/adt/acl.c:1325 #, c-format msgid "Use CASCADE to revoke them too." msgstr "Use CASCADE para revocarlos también." -#: commands/vacuum.c:138 +#: commands/vacuum.c:134 #, c-format msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" -msgstr "" +msgstr "«vacuum_buffer_usage_limit» debe ser 0 o estar entre %d kB y %d kB" -#: commands/vacuum.c:210 -#, fuzzy, c-format -#| msgid "NUMERIC precision %d must be between 1 and %d" +#: commands/vacuum.c:209 +#, c-format msgid "BUFFER_USAGE_LIMIT option must be 0 or between %d kB and %d kB" -msgstr "la precisión %d de NUMERIC debe estar entre 1 y %d" +msgstr "la opción BUFFER_USAGE_LIMIT debe ser 0 o estar entre %d kB y %d kB" -#: commands/vacuum.c:220 +#: commands/vacuum.c:219 #, c-format msgid "unrecognized ANALYZE option \"%s\"" msgstr "opción de ANALYZE «%s» no reconocida" -#: commands/vacuum.c:260 +#: commands/vacuum.c:259 #, c-format msgid "parallel option requires a value between 0 and %d" msgstr "la opción parallel requiere un valor entre 0 y %d" -#: commands/vacuum.c:272 +#: commands/vacuum.c:271 #, c-format msgid "parallel workers for vacuum must be between 0 and %d" msgstr "el número de procesos paralelos para vacuum debe estar entre 0 y %d" -#: commands/vacuum.c:293 +#: commands/vacuum.c:292 #, c-format msgid "unrecognized VACUUM option \"%s\"" msgstr "opción de VACUUM «%s» no reconocida" -#: commands/vacuum.c:319 +#: commands/vacuum.c:318 #, c-format msgid "VACUUM FULL cannot be performed in parallel" msgstr "VACUUM FULL no puede ser ejecutado en paralelo" -#: commands/vacuum.c:330 +#: commands/vacuum.c:329 #, c-format msgid "BUFFER_USAGE_LIMIT cannot be specified for VACUUM FULL" -msgstr "" +msgstr "BUFFER_USAGE_LIMIT no puede ser especificado para VACUUM FULL" -#: commands/vacuum.c:344 +#: commands/vacuum.c:343 #, c-format msgid "ANALYZE option must be specified when a column list is provided" msgstr "la opción ANALYZE debe especificarse cuando se provee una lista de columnas" -#: commands/vacuum.c:356 +#: commands/vacuum.c:355 #, c-format msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL" msgstr "la opción DISABLE_PAGE_SKIPPING de VACUUM no puede usarse con FULL" -#: commands/vacuum.c:363 +#: commands/vacuum.c:362 #, c-format msgid "PROCESS_TOAST required with VACUUM FULL" msgstr "se requiere especificar PROCESS_TOAST al hacer VACUUM FULL" -#: commands/vacuum.c:372 -#, fuzzy, c-format -#| msgid "OLD TABLE cannot be specified multiple times" +#: commands/vacuum.c:371 +#, c-format msgid "ONLY_DATABASE_STATS cannot be specified with a list of tables" -msgstr "OLD TABLE no se puede especificar varias veces" +msgstr "ONLY_DATABASE_STATS no se puede especificar con una lista de tablas" -#: commands/vacuum.c:381 -#, fuzzy, c-format -#| msgid "option \"%s\" cannot be specified with other options" +#: commands/vacuum.c:380 +#, c-format msgid "ONLY_DATABASE_STATS cannot be specified with other VACUUM options" -msgstr "la opción «%s» no puede ser especificada con otras opciones" +msgstr "ONLY_DATABASE_STATS no puede ser especificada con otras opciones de VACUUM" -#: commands/vacuum.c:516 +#: commands/vacuum.c:515 #, c-format msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%s no puede ejecutarse desde VACUUM o ANALYZE" -#: commands/vacuum.c:736 -#, fuzzy, c-format -#| msgid "permission denied for column %s" +#: commands/vacuum.c:730 +#, c-format msgid "permission denied to vacuum \"%s\", skipping it" -msgstr "permiso denegado a la columna %s" +msgstr "permiso denegado a hacer vacuum a «%s», ignorando" -#: commands/vacuum.c:749 -#, fuzzy, c-format -#| msgid "permission denied to set role \"%s\"" +#: commands/vacuum.c:743 +#, c-format msgid "permission denied to analyze \"%s\", skipping it" -msgstr "se ha denegado el permiso para definir el rol «%s»" +msgstr "se ha denegado el permiso para hacer analyze a «%s», ignorando" -#: commands/vacuum.c:827 commands/vacuum.c:924 +#: commands/vacuum.c:821 commands/vacuum.c:918 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" -msgstr "omitiendo el vacuum de «%s»: el candado no está disponible" +msgstr "omitiendo el vacuum de «%s»: el “lock” no está disponible" -#: commands/vacuum.c:832 +#: commands/vacuum.c:826 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "omitiendo el vacuum de «%s» --- la relación ya no existe" -#: commands/vacuum.c:848 commands/vacuum.c:929 +#: commands/vacuum.c:842 commands/vacuum.c:923 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" -msgstr "omitiendo analyze de «%s»: el candado no está disponible" +msgstr "omitiendo analyze de «%s»: el “lock” no está disponible" -#: commands/vacuum.c:853 +#: commands/vacuum.c:847 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "omitiendo analyze de «%s» --- la relación ya no existe" -#: commands/vacuum.c:1164 +#: commands/vacuum.c:1139 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" -msgstr "" +msgstr "el punto de corte para eliminar y congelar tuplas es demasiado antiguo" -#: commands/vacuum.c:1165 commands/vacuum.c:1170 +#: commands/vacuum.c:1140 commands/vacuum.c:1145 #, c-format msgid "" "Close open transactions soon to avoid wraparound problems.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"Cierre transaciones abiertas pronto para impedir problemas por reciclaje de contadores.\n" +"Cierre transaciones abiertas pronto para impedir problemas por “wraparound”.\n" "Puede que además necesite comprometer o abortar transacciones preparadas antiguas, o eliminar slots de replicación añejos." -#: commands/vacuum.c:1169 +#: commands/vacuum.c:1144 #, c-format msgid "cutoff for freezing multixacts is far in the past" -msgstr "" +msgstr "el punto de corte para congelar multixacts es demasiado antiguo" -#: commands/vacuum.c:1897 +#: commands/vacuum.c:1900 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "algunas bases de datos no han tenido VACUUM en más de 2 mil millones de transacciones" -#: commands/vacuum.c:1898 +#: commands/vacuum.c:1901 #, c-format msgid "You might have already suffered transaction-wraparound data loss." -msgstr "Puede haber sufrido ya problemas de pérdida de datos por reciclaje del contador de transacciones." +msgstr "Puede haber sufrido ya problemas de pérdida de datos por “wraparound” del contador de transacciones." -#: commands/vacuum.c:2063 +#: commands/vacuum.c:2080 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "omitiendo «%s»: no se puede aplicar VACUUM a objetos que no son tablas o a tablas especiales de sistema" -#: commands/vacuum.c:2488 +#: commands/vacuum.c:2512 #, c-format -msgid "scanned index \"%s\" to remove %d row versions" -msgstr "se recorrió el índice «%s» para eliminar %d versiones de filas" +msgid "scanned index \"%s\" to remove %lld row versions" +msgstr "se recorrió el índice «%s» para eliminar %lld versiones de filas" -#: commands/vacuum.c:2507 +#: commands/vacuum.c:2531 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "el índice «%s» ahora contiene %.0f versiones de filas en %u páginas" -#: commands/vacuum.c:2511 +#: commands/vacuum.c:2535 #, c-format msgid "" "%.0f index row versions were removed.\n" "%u index pages were newly deleted.\n" "%u index pages are currently deleted, of which %u are currently reusable." msgstr "" +"%.0f versiones de filas de índice fueron eliminadas.\n" +"%u páginas de índice fueron recién eliminadas.\n" +"%u páginas de índice están actualmente eliminadas, de las cuales %u son actualmente reusables." -#: commands/vacuumparallel.c:677 +#: commands/vacuumparallel.c:707 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index vacuuming (planned: %d)" msgstr[0] "se lanzó %d proceso asistente para «vacuum» de índices (planeados: %d)" msgstr[1] "se lanzaron %d procesos asistentes para «vacuum» índices (planeados: %d)" -#: commands/vacuumparallel.c:683 +#: commands/vacuumparallel.c:713 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index cleanup (planned: %d)" @@ -13033,7 +13350,7 @@ msgstr "SET TRANSACTION ISOLATION LEVEL debe ser llamado antes de cualquier cons msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "SET TRANSACTION ISOLATION LEVEL no debe ser llamado en una subtransacción" -#: commands/variable.c:606 storage/lmgr/predicate.c:1629 +#: commands/variable.c:606 storage/lmgr/predicate.c:1685 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "no se puede utilizar el modo serializable en un hot standby" @@ -13065,91 +13382,100 @@ msgstr "No se puede cambiar «client_encoding» ahora." #: commands/variable.c:781 #, c-format -msgid "cannot change client_encoding during a parallel operation" +msgid "cannot change \"client_encoding\" during a parallel operation" msgstr "no se puede cambiar «client_encoding» durante una operación paralela" -#: commands/variable.c:948 +#: commands/variable.c:876 +#, c-format +msgid "permission will be denied to set session authorization \"%s\"" +msgstr "se denegará el permiso para definir autorización de sesión «%s»" + +#: commands/variable.c:881 +#, c-format +msgid "permission denied to set session authorization \"%s\"" +msgstr "se ha denegado el permiso para definir autorización de sesión «%s»" + +#: commands/variable.c:991 #, c-format msgid "permission will be denied to set role \"%s\"" msgstr "se denegará el permiso para definir el rol «%s»" -#: commands/variable.c:953 +#: commands/variable.c:996 #, c-format msgid "permission denied to set role \"%s\"" msgstr "se ha denegado el permiso para definir el rol «%s»" -#: commands/variable.c:1153 +#: commands/variable.c:1200 #, c-format msgid "Bonjour is not supported by this build" msgstr "Bonjour no está soportado en este servidor" -#: commands/variable.c:1181 +#: commands/variable.c:1228 #, c-format -msgid "effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise()." -msgstr "effective_io_concurrency debe ser 0 en plataformas que no tienen posix_fadvise()." +msgid "\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." +msgstr "«effective_io_concurrency» debe ser 0 en plataformas que no tienen posix_fadvise()." -#: commands/variable.c:1194 +#: commands/variable.c:1241 #, c-format -msgid "maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise()." -msgstr "maintenance_io_concurrency debe ser 0 en plataformas que no tienen posix_fadvise()." +msgid "\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." +msgstr "«maintenance_io_concurrency» debe ser 0 en plataformas que no tienen posix_fadvise()." -#: commands/variable.c:1207 +#: commands/variable.c:1254 #, c-format msgid "SSL is not supported by this build" msgstr "SSL no está soportado en este servidor" -#: commands/view.c:84 +#: commands/view.c:79 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "no se pudo determinar el ordenamiento (collation) a usar para la columna «%s» de vista" -#: commands/view.c:279 commands/view.c:290 +#: commands/view.c:274 commands/view.c:285 #, c-format msgid "cannot drop columns from view" msgstr "no se pueden eliminar columnas de una vista" -#: commands/view.c:295 +#: commands/view.c:290 #, c-format msgid "cannot change name of view column \"%s\" to \"%s\"" msgstr "no se puede cambiar el nombre de la columna «%s» de la vista a «%s»" -#: commands/view.c:298 +#: commands/view.c:293 #, c-format msgid "Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead." msgstr "Use ALTER VIEW ... RENAME COLUMN ... para cambiar el nombre de una columna de una vista." -#: commands/view.c:309 +#: commands/view.c:304 #, c-format msgid "cannot change data type of view column \"%s\" from %s to %s" msgstr "no se puede cambiar el tipo de dato de la columna «%s» de la vista de %s a %s" -#: commands/view.c:323 -#, fuzzy, c-format -#| msgid "cannot change data type of view column \"%s\" from %s to %s" +#: commands/view.c:318 +#, c-format msgid "cannot change collation of view column \"%s\" from \"%s\" to \"%s\"" -msgstr "no se puede cambiar el tipo de dato de la columna «%s» de la vista de %s a %s" +msgstr "no se puede cambiar el ordenamiento de la columna «%s» de la vista de «%s» a «%s»" -#: commands/view.c:392 +#: commands/view.c:387 #, c-format msgid "views must not contain SELECT INTO" msgstr "una vista no puede tener SELECT INTO" -#: commands/view.c:404 +#: commands/view.c:399 #, c-format msgid "views must not contain data-modifying statements in WITH" msgstr "las vistas no deben contener sentencias que modifiquen datos en WITH" -#: commands/view.c:474 +#: commands/view.c:469 #, c-format msgid "CREATE VIEW specifies more column names than columns" msgstr "CREATE VIEW especifica más nombres de columna que columnas" -#: commands/view.c:482 +#: commands/view.c:477 #, c-format msgid "views cannot be unlogged because they do not have storage" msgstr "las vistas no pueden ser «unlogged» porque no tienen almacenamiento" -#: commands/view.c:496 +#: commands/view.c:491 #, c-format msgid "view \"%s\" will be a temporary view" msgstr "la vista «%s» será una vista temporal" @@ -13185,515 +13511,505 @@ msgstr "el cursor «%s» no está posicionado en una fila" msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "el cursor «%s» no es un recorrido simplemente actualizable de la tabla «%s»" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2497 +#: executor/execCurrent.c:280 executor/execExprInterp.c:2555 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "el tipo del parámetro %d (%s) no coincide aquel con que fue preparado el plan (%s)" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2509 +#: executor/execCurrent.c:292 executor/execExprInterp.c:2567 #, c-format msgid "no value found for parameter %d" msgstr "no se encontró un valor para parámetro %d" -#: executor/execExpr.c:637 executor/execExpr.c:644 executor/execExpr.c:650 -#: executor/execExprInterp.c:4229 executor/execExprInterp.c:4246 -#: executor/execExprInterp.c:4345 executor/nodeModifyTable.c:197 -#: executor/nodeModifyTable.c:208 executor/nodeModifyTable.c:225 -#: executor/nodeModifyTable.c:233 +#: executor/execExpr.c:642 executor/execExpr.c:649 executor/execExpr.c:655 +#: executor/execExprInterp.c:4852 executor/execExprInterp.c:4869 +#: executor/execExprInterp.c:4968 executor/nodeModifyTable.c:203 +#: executor/nodeModifyTable.c:214 executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:239 #, c-format msgid "table row type and query-specified row type do not match" msgstr "el tipo de registro de la tabla no coincide con el tipo de registro de la consulta" -#: executor/execExpr.c:638 executor/nodeModifyTable.c:198 +#: executor/execExpr.c:643 executor/nodeModifyTable.c:204 #, c-format msgid "Query has too many columns." msgstr "La consulta tiene demasiadas columnas." -#: executor/execExpr.c:645 executor/nodeModifyTable.c:226 +#: executor/execExpr.c:650 executor/nodeModifyTable.c:232 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "La consulta entrega un valor para una columna eliminada en la posición %d." -#: executor/execExpr.c:651 executor/execExprInterp.c:4247 -#: executor/nodeModifyTable.c:209 +#: executor/execExpr.c:656 executor/execExprInterp.c:4870 +#: executor/nodeModifyTable.c:215 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "La tabla tiene tipo %s en posición ordinal %d, pero la consulta esperaba %s." -#: executor/execExpr.c:1099 parser/parse_agg.c:827 +#: executor/execExpr.c:1104 parser/parse_agg.c:838 #, c-format msgid "window function calls cannot be nested" msgstr "no se pueden anidar llamadas a funciones de ventana deslizante" -#: executor/execExpr.c:1618 +#: executor/execExpr.c:1649 #, c-format msgid "target type is not an array" msgstr "el tipo de destino no es un array" -#: executor/execExpr.c:1958 +#: executor/execExpr.c:1989 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "la columna de ROW() es de tipo %s en lugar de ser de tipo %s" -#: executor/execExpr.c:2587 executor/execSRF.c:719 parser/parse_func.c:138 -#: parser/parse_func.c:655 parser/parse_func.c:1032 +#: executor/execExpr.c:2653 executor/execSRF.c:718 parser/parse_func.c:138 +#: parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" msgstr[0] "no se pueden pasar más de %d argumento a una función" msgstr[1] "no se pueden pasar más de %d argumentos a una función" -#: executor/execExpr.c:2614 executor/execSRF.c:739 executor/functions.c:1066 -#: utils/adt/jsonfuncs.c:3780 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2680 executor/execSRF.c:738 executor/functions.c:1068 +#: utils/adt/jsonfuncs.c:4054 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "se llamó una función que retorna un conjunto en un contexto que no puede aceptarlo" -#: executor/execExpr.c:3020 parser/parse_node.c:277 parser/parse_node.c:327 +#: executor/execExpr.c:3086 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "no se puede poner subíndices al tipo %s porque no soporta subíndices" -#: executor/execExpr.c:3148 executor/execExpr.c:3170 +#: executor/execExpr.c:3214 executor/execExpr.c:3236 #, c-format msgid "type %s does not support subscripted assignment" msgstr "el tipo %s no soporta asignación subindexada" -#: executor/execExprInterp.c:1962 +#: executor/execExprInterp.c:2019 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "El atributo %d de tipo %s ha sido eliminado" -#: executor/execExprInterp.c:1968 +#: executor/execExprInterp.c:2025 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "el atributo %d del tipo %s tiene tipo erróneo" -#: executor/execExprInterp.c:1970 executor/execExprInterp.c:3103 -#: executor/execExprInterp.c:3149 +#: executor/execExprInterp.c:2027 executor/execExprInterp.c:3226 +#: executor/execExprInterp.c:3272 #, c-format msgid "Table has type %s, but query expects %s." msgstr "La tabla tiene tipo %s, pero la consulta esperaba %s." -#: executor/execExprInterp.c:2049 utils/adt/expandedrecord.c:99 -#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1743 -#: utils/cache/typcache.c:1902 utils/cache/typcache.c:2049 -#: utils/fmgr/funcapi.c:561 +#: executor/execExprInterp.c:2107 utils/adt/expandedrecord.c:99 +#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 +#: utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 +#: utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "el tipo %s no es compuesto" -#: executor/execExprInterp.c:2587 +#: executor/execExprInterp.c:2710 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "WHERE CURRENT OF no está soportado para este tipo de tabla" -#: executor/execExprInterp.c:2800 +#: executor/execExprInterp.c:2923 #, c-format msgid "cannot merge incompatible arrays" msgstr "no se puede mezclar arrays incompatibles" -#: executor/execExprInterp.c:2801 +#: executor/execExprInterp.c:2924 #, c-format msgid "Array with element type %s cannot be included in ARRAY construct with element type %s." msgstr "El array con tipo de elemento %s no puede ser incluido en una sentencia ARRAY con tipo de elemento %s." -#: executor/execExprInterp.c:2822 utils/adt/arrayfuncs.c:265 -#: utils/adt/arrayfuncs.c:575 utils/adt/arrayfuncs.c:1329 -#: utils/adt/arrayfuncs.c:3483 utils/adt/arrayfuncs.c:5567 -#: utils/adt/arrayfuncs.c:6084 utils/adt/arraysubs.c:150 +#: executor/execExprInterp.c:2945 utils/adt/arrayfuncs.c:1305 +#: utils/adt/arrayfuncs.c:3503 utils/adt/arrayfuncs.c:5593 +#: utils/adt/arrayfuncs.c:6110 utils/adt/arraysubs.c:150 #: utils/adt/arraysubs.c:488 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "el número de dimensiones del array (%d) excede el máximo permitido (%d)" -#: executor/execExprInterp.c:2842 executor/execExprInterp.c:2877 +#: executor/execExprInterp.c:2965 executor/execExprInterp.c:3000 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "los arrays multidimensionales deben tener expresiones de arrays con dimensiones coincidentes" -#: executor/execExprInterp.c:2854 utils/adt/array_expanded.c:274 -#: utils/adt/arrayfuncs.c:959 utils/adt/arrayfuncs.c:1568 -#: utils/adt/arrayfuncs.c:3285 utils/adt/arrayfuncs.c:3513 -#: utils/adt/arrayfuncs.c:6176 utils/adt/arrayfuncs.c:6517 -#: utils/adt/arrayutils.c:104 utils/adt/arrayutils.c:113 -#: utils/adt/arrayutils.c:120 +#: executor/execExprInterp.c:2977 utils/adt/array_expanded.c:274 +#: utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 +#: utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 +#: utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 +#: utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 +#: utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 +#: utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 +#: utils/adt/arrayfuncs.c:3533 utils/adt/arrayfuncs.c:5365 +#: utils/adt/arrayfuncs.c:6202 utils/adt/arrayfuncs.c:6546 +#: utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 +#: utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "el tamaño del array excede el máximo permitido (%d)" -#: executor/execExprInterp.c:3102 executor/execExprInterp.c:3148 +#: executor/execExprInterp.c:3225 executor/execExprInterp.c:3271 #, c-format msgid "attribute %d has wrong type" msgstr "el atributo %d tiene tipo erróneo" -#: executor/execExprInterp.c:3730 utils/adt/domains.c:155 +#: executor/execExprInterp.c:3857 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "el dominio %s no permite valores null" -#: executor/execExprInterp.c:3745 utils/adt/domains.c:193 +#: executor/execExprInterp.c:3872 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "el valor para el dominio %s viola la restricción «check» «%s»" -#: executor/execExprInterp.c:4230 +#: executor/execExprInterp.c:4447 +#, c-format +msgid "no SQL/JSON item found for specified path of column \"%s\"" +msgstr "ningún ítem SQL/JSON fue encontrado para la ruta especificada de la columna «%s»" + +#: executor/execExprInterp.c:4452 +#, c-format +msgid "no SQL/JSON item found for specified path" +msgstr "ningún ítem SQL/JSON fue encontrado para la ruta especificada" + +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:4652 executor/execExprInterp.c:4660 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "no se pudo convertir la expresión %s (%s) al tipo RETURNING" + +#: executor/execExprInterp.c:4853 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." msgstr[0] "La fila de la tabla contiene %d atributo, pero la consulta esperaba %d." msgstr[1] "La fila de la tabla contiene %d atributos, pero la consulta esperaba %d." -#: executor/execExprInterp.c:4346 executor/execSRF.c:978 +#: executor/execExprInterp.c:4969 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "Discordancia de almacenamiento físico en atributo eliminado en la posición %d." -#: executor/execIndexing.c:588 +#: executor/execIndexing.c:593 #, c-format msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters" msgstr "ON CONFLICT no soporta las restricciones únicas o de exclusión postergables como árbitros" -#: executor/execIndexing.c:865 +#: executor/execIndexing.c:870 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "no se pudo crear la restricción de exclusión «%s»" -#: executor/execIndexing.c:868 +#: executor/execIndexing.c:873 #, c-format msgid "Key %s conflicts with key %s." msgstr "La llave %s está en conflicto con la llave %s." -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:875 #, c-format msgid "Key conflicts exist." msgstr "Existe un conflicto de llave." -#: executor/execIndexing.c:876 +#: executor/execIndexing.c:881 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "llave en conflicto viola la restricción de exclusión «%s»" -#: executor/execIndexing.c:879 +#: executor/execIndexing.c:884 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "La llave %s está en conflicto con la llave existente %s." -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:886 #, c-format msgid "Key conflicts with existing key." msgstr "La llave está en conflicto con una llave existente." -#: executor/execMain.c:1030 +#: executor/execMain.c:1039 #, c-format msgid "cannot change sequence \"%s\"" msgstr "no se puede cambiar la secuencia «%s»" -#: executor/execMain.c:1036 +#: executor/execMain.c:1045 #, c-format msgid "cannot change TOAST relation \"%s\"" msgstr "no se puede cambiar la relación TOAST «%s»" -#: executor/execMain.c:1054 rewrite/rewriteHandler.c:3078 -#: rewrite/rewriteHandler.c:3965 -#, c-format -msgid "cannot insert into view \"%s\"" -msgstr "no se puede insertar en la vista «%s»" - -#: executor/execMain.c:1056 rewrite/rewriteHandler.c:3081 -#: rewrite/rewriteHandler.c:3968 -#, c-format -msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." -msgstr "Para posibilitar las inserciones en la vista, provea un disparador INSTEAD OF INSERT o una regla incodicional ON INSERT DO INSTEAD." - -#: executor/execMain.c:1062 rewrite/rewriteHandler.c:3086 -#: rewrite/rewriteHandler.c:3973 -#, c-format -msgid "cannot update view \"%s\"" -msgstr "no se puede actualizar la vista «%s»" - -#: executor/execMain.c:1064 rewrite/rewriteHandler.c:3089 -#: rewrite/rewriteHandler.c:3976 -#, c-format -msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." -msgstr "Para posibilitar las actualizaciones en la vista, provea un disparador INSTEAD OF UPDATE o una regla incondicional ON UPDATE DO INSTEAD." - -#: executor/execMain.c:1070 rewrite/rewriteHandler.c:3094 -#: rewrite/rewriteHandler.c:3981 -#, c-format -msgid "cannot delete from view \"%s\"" -msgstr "no se puede eliminar de la vista «%s»" - -#: executor/execMain.c:1072 rewrite/rewriteHandler.c:3097 -#: rewrite/rewriteHandler.c:3984 -#, c-format -msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." -msgstr "Para posibilitar las eliminaciones en la vista, provea un disparador INSTEAD OF DELETE o una regla incondicional ON DELETE DO INSTEAD." - -#: executor/execMain.c:1083 +#: executor/execMain.c:1064 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "no se puede cambiar la vista materializada «%s»" -#: executor/execMain.c:1095 +#: executor/execMain.c:1076 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "no se puede insertar en la tabla foránea «%s»" -#: executor/execMain.c:1101 +#: executor/execMain.c:1082 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "la tabla foránea «%s» no permite inserciones" -#: executor/execMain.c:1108 +#: executor/execMain.c:1089 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "no se puede actualizar la tabla foránea «%s»" -#: executor/execMain.c:1114 +#: executor/execMain.c:1095 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "la tabla foránea «%s» no permite actualizaciones" -#: executor/execMain.c:1121 +#: executor/execMain.c:1102 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "no se puede eliminar desde la tabla foránea «%s»" -#: executor/execMain.c:1127 +#: executor/execMain.c:1108 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "la tabla foránea «%s» no permite eliminaciones" -#: executor/execMain.c:1138 +#: executor/execMain.c:1119 #, c-format msgid "cannot change relation \"%s\"" msgstr "no se puede cambiar la relación «%s»" -#: executor/execMain.c:1165 +#: executor/execMain.c:1146 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "no se puede bloquear registros de la secuencia «%s»" -#: executor/execMain.c:1172 +#: executor/execMain.c:1153 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "no se puede bloquear registros en la relación TOAST «%s»" -#: executor/execMain.c:1179 +#: executor/execMain.c:1160 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "no se puede bloquear registros en la vista «%s»" -#: executor/execMain.c:1187 +#: executor/execMain.c:1168 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "no se puede bloquear registros en la vista materializada «%s»" -#: executor/execMain.c:1196 executor/execMain.c:2699 +#: executor/execMain.c:1177 executor/execMain.c:2689 #: executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "no se puede bloquear registros en la tabla foránea «%s»" -#: executor/execMain.c:1202 +#: executor/execMain.c:1183 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "no se puede bloquear registros en la tabla «%s»" -#: executor/execMain.c:1913 +#: executor/execMain.c:1901 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "el nuevo registro para la relación «%s» viola la restricción de partición" -#: executor/execMain.c:1915 executor/execMain.c:1999 executor/execMain.c:2050 -#: executor/execMain.c:2160 +#: executor/execMain.c:1903 executor/execMain.c:1987 executor/execMain.c:2038 +#: executor/execMain.c:2148 #, c-format msgid "Failing row contains %s." msgstr "La fila que falla contiene %s." -#: executor/execMain.c:1996 +#: executor/execMain.c:1984 #, c-format msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" msgstr "el valor nulo en la columna «%s» de la relación «%s» viola la restricción de no nulo" -#: executor/execMain.c:2048 +#: executor/execMain.c:2036 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "el nuevo registro para la relación «%s» viola la restricción «check» «%s»" -#: executor/execMain.c:2158 +#: executor/execMain.c:2146 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "el nuevo registro para la vista «%s» viola la opción check" -#: executor/execMain.c:2168 +#: executor/execMain.c:2156 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "el nuevo registro viola la política de seguridad de registros «%s» para la tabla «%s»" -#: executor/execMain.c:2173 +#: executor/execMain.c:2161 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "el nuevo registro viola la política de seguridad de registros para la tabla «%s»" -#: executor/execMain.c:2181 -#, fuzzy, c-format -#| msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" +#: executor/execMain.c:2169 +#, c-format msgid "target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" -msgstr "el nuevo registro viola la política de seguridad de registros «%s» (expresión USING) para la tabla «%s»" +msgstr "el registro destino viola la política de seguridad de registros «%s» (expresión USING) para la tabla «%s»" -#: executor/execMain.c:2186 -#, fuzzy, c-format -#| msgid "new row violates row-level security policy (USING expression) for table \"%s\"" +#: executor/execMain.c:2174 +#, c-format msgid "target row violates row-level security policy (USING expression) for table \"%s\"" -msgstr "el nuevo registro viola la política de seguridad de registros (expresión USING) para la tabla «%s»" +msgstr "el registro destino viola la política de seguridad de registros (expresión USING) para la tabla «%s»" -#: executor/execMain.c:2193 +#: executor/execMain.c:2181 #, c-format msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "el nuevo registro viola la política de seguridad de registros «%s» (expresión USING) para la tabla «%s»" -#: executor/execMain.c:2198 +#: executor/execMain.c:2186 #, c-format msgid "new row violates row-level security policy (USING expression) for table \"%s\"" msgstr "el nuevo registro viola la política de seguridad de registros (expresión USING) para la tabla «%s»" -#: executor/execPartition.c:330 +#: executor/execPartition.c:327 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "no se encontró una partición de «%s» para el registro" -#: executor/execPartition.c:333 +#: executor/execPartition.c:330 #, c-format msgid "Partition key of the failing row contains %s." msgstr "La llave de particionamiento de la fila que falla contiene %s." -#: executor/execReplication.c:240 executor/execReplication.c:424 +#: executor/execReplication.c:272 executor/execReplication.c:456 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update, retrying" msgstr "el registro a ser bloqueado ya fue movido a otra partición debido a un update concurrente, reintentando" -#: executor/execReplication.c:244 executor/execReplication.c:428 +#: executor/execReplication.c:276 executor/execReplication.c:460 #, c-format msgid "concurrent update, retrying" msgstr "actualización simultánea, reintentando" -#: executor/execReplication.c:250 executor/execReplication.c:434 +#: executor/execReplication.c:282 executor/execReplication.c:466 #, c-format msgid "concurrent delete, retrying" msgstr "eliminacón concurrente, reintentando" -#: executor/execReplication.c:320 parser/parse_cte.c:308 -#: parser/parse_oper.c:233 utils/adt/array_userfuncs.c:1348 -#: utils/adt/array_userfuncs.c:1491 utils/adt/arrayfuncs.c:3832 -#: utils/adt/arrayfuncs.c:4387 utils/adt/arrayfuncs.c:6397 -#: utils/adt/rowtypes.c:1230 +#: executor/execReplication.c:352 parser/parse_cte.c:302 +#: parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 +#: utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3852 +#: utils/adt/arrayfuncs.c:4407 utils/adt/arrayfuncs.c:6426 +#: utils/adt/rowtypes.c:1220 #, c-format msgid "could not identify an equality operator for type %s" msgstr "no se pudo identificar un operador de igualdad para el tipo %s" -#: executor/execReplication.c:651 executor/execReplication.c:657 -#, fuzzy, c-format -#| msgid "cannot update foreign table \"%s\"" +#: executor/execReplication.c:687 executor/execReplication.c:693 +#, c-format msgid "cannot update table \"%s\"" -msgstr "no se puede actualizar la tabla foránea «%s»" +msgstr "no se puede actualizar la tabla «%s»" -#: executor/execReplication.c:653 executor/execReplication.c:665 +#: executor/execReplication.c:689 executor/execReplication.c:701 #, c-format msgid "Column used in the publication WHERE expression is not part of the replica identity." msgstr "La columna usada en la expresión WHERE de la publicación no es parte de la identidad de replicación." -#: executor/execReplication.c:659 executor/execReplication.c:671 +#: executor/execReplication.c:695 executor/execReplication.c:707 #, c-format msgid "Column list used by the publication does not cover the replica identity." msgstr "La lista de columnas usada por la publicación no incluye la identidad de replicación." -#: executor/execReplication.c:663 executor/execReplication.c:669 -#, fuzzy, c-format -#| msgid "cannot delete from foreign table \"%s\"" +#: executor/execReplication.c:699 executor/execReplication.c:705 +#, c-format msgid "cannot delete from table \"%s\"" -msgstr "no se puede eliminar desde la tabla foránea «%s»" +msgstr "no se puede eliminar desde la tabla «%s»" -#: executor/execReplication.c:689 +#: executor/execReplication.c:725 #, c-format msgid "cannot update table \"%s\" because it does not have a replica identity and publishes updates" msgstr "no se puede actualizar la tabla «%s» porque no tiene identidad de replicación y publica updates" -#: executor/execReplication.c:691 +#: executor/execReplication.c:727 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "Para habilitar la actualización de la tabla, configure REPLICA IDENTITY utilizando ALTER TABLE." -#: executor/execReplication.c:695 +#: executor/execReplication.c:731 #, c-format msgid "cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes" msgstr "no se puede eliminar de la tabla «%s» porque no tiene una identidad de replicación y publica deletes" -#: executor/execReplication.c:697 +#: executor/execReplication.c:733 #, c-format msgid "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "para habilitar la eliminación en la tabla, configure REPLICA IDENTITY utilizando ALTER TABLE." -#: executor/execReplication.c:713 +#: executor/execReplication.c:749 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "no se puede usar la relación «%s.%s» como destino de replicación lógica" -#: executor/execSRF.c:316 +#: executor/execSRF.c:315 #, c-format msgid "rows returned by function are not all of the same row type" msgstr "las filas retornadas por la función no tienen todas el mismo tipo de registro" -#: executor/execSRF.c:366 +#: executor/execSRF.c:365 #, c-format msgid "table-function protocol for value-per-call mode was not followed" msgstr "no se siguió el protocolo de función tabular para el modo de valor por llamada" -#: executor/execSRF.c:374 executor/execSRF.c:668 +#: executor/execSRF.c:373 executor/execSRF.c:667 #, c-format msgid "table-function protocol for materialize mode was not followed" msgstr "no se siguió el protocolo de función tabular para el modo de materialización" -#: executor/execSRF.c:381 executor/execSRF.c:686 +#: executor/execSRF.c:380 executor/execSRF.c:685 #, c-format msgid "unrecognized table-function returnMode: %d" msgstr "modo de retorno de la función tabular no es reconocido: %d" -#: executor/execSRF.c:895 +#: executor/execSRF.c:894 #, c-format msgid "function returning setof record called in context that cannot accept type record" msgstr "se llamó una función que retorna «setof record» en un contexto que no puede aceptar el tipo record" -#: executor/execSRF.c:951 executor/execSRF.c:967 executor/execSRF.c:977 +#: executor/execSRF.c:950 executor/execSRF.c:966 executor/execSRF.c:976 #, c-format msgid "function return row and query-specified return row do not match" msgstr "la fila de retorno especificada en la consulta no coincide con fila de retorno de la función" -#: executor/execSRF.c:952 +#: executor/execSRF.c:951 #, c-format msgid "Returned row contains %d attribute, but query expects %d." msgid_plural "Returned row contains %d attributes, but query expects %d." msgstr[0] "Fila retornada contiene %d atributo, pero la consulta esperaba %d." msgstr[1] "Fila retornada contiene %d atributos, pero la consulta esperaba %d." -#: executor/execSRF.c:968 +#: executor/execSRF.c:967 #, c-format msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "Tipo retornado %s en posición ordinal %d, pero la consulta esperaba %s." -#: executor/execTuples.c:146 executor/execTuples.c:353 -#: executor/execTuples.c:521 executor/execTuples.c:713 +#: executor/execTuples.c:147 executor/execTuples.c:368 +#: executor/execTuples.c:563 executor/execTuples.c:772 #, c-format msgid "cannot retrieve a system column in this context" msgstr "no se puede obtener una columna de sistema en este contexto" -#: executor/execUtils.c:744 +#: executor/execTuples.c:163 executor/execTuples.c:580 +#, c-format +msgid "don't have transaction information for this type of tuple" +msgstr "no se tiene información de transacción para este tipo de tupla" + +#: executor/execTuples.c:390 executor/execTuples.c:794 +#, c-format +msgid "don't have a storage tuple in this context" +msgstr "no se tiene una tupla de almacenamiento en este contexto" + +#: executor/execUtils.c:713 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "la vista materializada «%s» no ha sido poblada" -#: executor/execUtils.c:746 +#: executor/execUtils.c:715 #, c-format msgid "Use the REFRESH MATERIALIZED VIEW command." msgstr "Use la orden REFRESH MATERIALIZED VIEW." @@ -13703,111 +14019,111 @@ msgstr "Use la orden REFRESH MATERIALIZED VIEW." msgid "could not determine actual type of argument declared %s" msgstr "no se pudo determinar el tipo de argumento declarado %s" -#: executor/functions.c:512 +#: executor/functions.c:513 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "no se puede ejecutar COPY desde/a un cliente en una función SQL" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:519 #, c-format msgid "%s is not allowed in an SQL function" msgstr "%s no está permitido en una función SQL" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1742 executor/spi.c:2635 +#: executor/functions.c:527 executor/spi.c:1744 executor/spi.c:2657 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "%s no está permitido en una función no-«volatile»" -#: executor/functions.c:1450 +#: executor/functions.c:1452 #, c-format msgid "SQL function \"%s\" statement %d" msgstr "función SQL «%s» en la sentencia %d" -#: executor/functions.c:1476 +#: executor/functions.c:1478 #, c-format msgid "SQL function \"%s\" during startup" msgstr "función SQL «%s» durante el inicio" -#: executor/functions.c:1561 +#: executor/functions.c:1563 #, c-format msgid "calling procedures with output arguments is not supported in SQL functions" msgstr "no está permitido invocar procedimientos con argumentos de salida en funciones SQL" -#: executor/functions.c:1694 executor/functions.c:1732 -#: executor/functions.c:1746 executor/functions.c:1836 -#: executor/functions.c:1869 executor/functions.c:1883 +#: executor/functions.c:1698 executor/functions.c:1736 +#: executor/functions.c:1750 executor/functions.c:1845 +#: executor/functions.c:1878 executor/functions.c:1892 #, c-format msgid "return type mismatch in function declared to return %s" msgstr "el tipo de retorno de función declarada para retornar %s no concuerda" -#: executor/functions.c:1696 +#: executor/functions.c:1700 #, c-format -msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING." -msgstr "La sentencia final de la función debe ser un SELECT o INSERT/UPDATE/DELETE RETURNING." +msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." +msgstr "La sentencia final de la función debe ser un SELECT o INSERT/UPDATE/DELETE/MERGE RETURNING." -#: executor/functions.c:1734 +#: executor/functions.c:1738 #, c-format msgid "Final statement must return exactly one column." msgstr "La sentencia final debe retornar exactamente una columna." -#: executor/functions.c:1748 +#: executor/functions.c:1752 #, c-format msgid "Actual return type is %s." msgstr "El verdadero tipo de retorno es %s." -#: executor/functions.c:1838 +#: executor/functions.c:1847 #, c-format msgid "Final statement returns too many columns." msgstr "La sentencia final retorna demasiadas columnas." -#: executor/functions.c:1871 +#: executor/functions.c:1880 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "La sentencia final retorna %s en lugar de %s en la columna %d." -#: executor/functions.c:1885 +#: executor/functions.c:1894 #, c-format msgid "Final statement returns too few columns." msgstr "La sentencia final retorna muy pocas columnas." -#: executor/functions.c:1913 +#: executor/functions.c:1922 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "el tipo de retorno %s no es soportado en funciones SQL" -#: executor/nodeAgg.c:3937 executor/nodeWindowAgg.c:2993 +#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2975 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "la función de agregación %u necesita tener tipos de entrada y transición compatibles" -#: executor/nodeAgg.c:3967 parser/parse_agg.c:669 parser/parse_agg.c:697 +#: executor/nodeAgg.c:3966 parser/parse_agg.c:680 parser/parse_agg.c:708 #, c-format msgid "aggregate function calls cannot be nested" msgstr "no se pueden anidar llamadas a funciones de agregación" -#: executor/nodeCustom.c:154 executor/nodeCustom.c:165 +#: executor/nodeCustom.c:144 executor/nodeCustom.c:155 #, c-format msgid "custom scan \"%s\" does not support MarkPos" msgstr "el scan personalizado «%s» no soporta MarkPos" -#: executor/nodeHashjoin.c:1143 executor/nodeHashjoin.c:1173 +#: executor/nodeHashjoin.c:1131 executor/nodeHashjoin.c:1161 #, c-format msgid "could not rewind hash-join temporary file" msgstr "no se puede rebobinar el archivo temporal del hash-join" -#: executor/nodeIndexonlyscan.c:238 +#: executor/nodeIndexonlyscan.c:239 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "no se permiten funciones de ventana deslizante en predicados de índice" -#: executor/nodeLimit.c:374 +#: executor/nodeLimit.c:373 #, c-format msgid "OFFSET must not be negative" msgstr "OFFSET no debe ser negativo" -#: executor/nodeLimit.c:400 +#: executor/nodeLimit.c:399 #, c-format msgid "LIMIT must not be negative" msgstr "LIMIT no debe ser negativo" @@ -13822,76 +14138,74 @@ msgstr "RIGHT JOIN sólo está soportado con condiciones que se pueden usar con msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "FULL JOIN sólo está soportado con condiciones que se pueden usar con merge join" -#: executor/nodeModifyTable.c:234 +#: executor/nodeModifyTable.c:240 #, c-format msgid "Query has too few columns." msgstr "La consulta tiene muy pocas columnas." -#: executor/nodeModifyTable.c:1530 executor/nodeModifyTable.c:1604 +#: executor/nodeModifyTable.c:1540 executor/nodeModifyTable.c:1614 #, c-format msgid "tuple to be deleted was already modified by an operation triggered by the current command" msgstr "el registro a ser eliminado ya fue modificado por una operación disparada por la orden actual" -#: executor/nodeModifyTable.c:1758 +#: executor/nodeModifyTable.c:1769 #, c-format msgid "invalid ON UPDATE specification" msgstr "especificación ON UPDATE no válida" -#: executor/nodeModifyTable.c:1759 +#: executor/nodeModifyTable.c:1770 #, c-format msgid "The result tuple would appear in a different partition than the original tuple." msgstr "La tupla de resultado aparecería en una partición diferente que la tupla original." -#: executor/nodeModifyTable.c:2217 +#: executor/nodeModifyTable.c:2226 #, c-format msgid "cannot move tuple across partitions when a non-root ancestor of the source partition is directly referenced in a foreign key" msgstr "no se puede mover una tupla entre particiones cuando un ancestro no-raíz de la partición de origen es referenciada directamente en una llave foránea" -#: executor/nodeModifyTable.c:2218 +#: executor/nodeModifyTable.c:2227 #, c-format msgid "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." -msgstr "" +msgstr "Una llave foránea apunta al ancestro «%s» pero no al ancestro raíz «%s»." -#: executor/nodeModifyTable.c:2221 -#, fuzzy, c-format -#| msgid "cannot insert into foreign table \"%s\"" +#: executor/nodeModifyTable.c:2230 +#, c-format msgid "Consider defining the foreign key on table \"%s\"." -msgstr "no se puede insertar en la tabla foránea «%s»" +msgstr "Considere definir una llave foránea en la tabla «%s»." #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2567 executor/nodeModifyTable.c:2954 +#: executor/nodeModifyTable.c:2596 executor/nodeModifyTable.c:3138 +#: executor/nodeModifyTable.c:3308 #, c-format msgid "%s command cannot affect row a second time" -msgstr "" +msgstr "la orden %s no puede afectar una fila por segunda vez" -#: executor/nodeModifyTable.c:2569 +#: executor/nodeModifyTable.c:2598 #, c-format msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values." msgstr "Asegúrese de que ningún registro propuesto para inserción dentro de la misma orden tenga valores duplicados restringidos." -#: executor/nodeModifyTable.c:2956 +#: executor/nodeModifyTable.c:3131 executor/nodeModifyTable.c:3301 +#, c-format +msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" +msgstr "la tupla a ser actualizada o borrada ya fue modificada por una operación disparada por la orden actual" + +#: executor/nodeModifyTable.c:3140 executor/nodeModifyTable.c:3310 #, c-format msgid "Ensure that not more than one source row matches any one target row." msgstr "Asegúrese que no más de un registro de origen coincide con cada registro de destino." -#: executor/nodeModifyTable.c:3037 -#, fuzzy, c-format -#| msgid "tuple to be locked was already moved to another partition due to concurrent update" -msgid "tuple to be deleted was already moved to another partition due to concurrent update" -msgstr "el registro a ser bloqueado ya fue movido a otra partición por un update concurrente" - -#: executor/nodeModifyTable.c:3076 -#, fuzzy, c-format -#| msgid "tuple to be updated was already modified by an operation triggered by the current command" -msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" -msgstr "el registro a ser actualizado ya fue modificado por una operación disparada por la orden actual" +#: executor/nodeModifyTable.c:3209 +#, c-format +msgid "tuple to be merged was already moved to another partition due to concurrent update" +msgstr "la tupla a ser mezclada ya fue movida a otra partición por un update concurrente" -#: executor/nodeSamplescan.c:260 +#: executor/nodeSamplescan.c:244 #, c-format msgid "TABLESAMPLE parameter cannot be null" msgstr "el parámetro TABLESAMPLE no puede ser null" -#: executor/nodeSamplescan.c:272 +#: executor/nodeSamplescan.c:256 #, c-format msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "el parámetro TABLESAMPLE REPEATABLE no puede ser null" @@ -13902,7 +14216,7 @@ msgstr "el parámetro TABLESAMPLE REPEATABLE no puede ser null" msgid "more than one row returned by a subquery used as an expression" msgstr "una subconsulta utilizada como expresión retornó más de un registro" -#: executor/nodeTableFuncscan.c:375 +#: executor/nodeTableFuncscan.c:370 #, c-format msgid "namespace URI must not be null" msgstr "la URI del espacio de nombres no debe ser null" @@ -13912,17 +14226,17 @@ msgstr "la URI del espacio de nombres no debe ser null" msgid "row filter expression must not be null" msgstr "la expresión filtro de filas no debe ser null" -#: executor/nodeTableFuncscan.c:415 +#: executor/nodeTableFuncscan.c:416 #, c-format msgid "column filter expression must not be null" msgstr "la expresión filtro de columnas no debe ser null" -#: executor/nodeTableFuncscan.c:416 +#: executor/nodeTableFuncscan.c:417 #, c-format msgid "Filter for column \"%s\" is null." msgstr "El filtro para la columna «%s» es null." -#: executor/nodeTableFuncscan.c:506 +#: executor/nodeTableFuncscan.c:507 #, c-format msgid "null is not allowed in column \"%s\"" msgstr "null no está permitido en la columna «%s»" @@ -13952,84 +14266,84 @@ msgstr "la posición final del marco no debe ser null" msgid "frame ending offset must not be negative" msgstr "la posición final del marco no debe ser negativa" -#: executor/nodeWindowAgg.c:2909 +#: executor/nodeWindowAgg.c:2891 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "la función de agregación %s no permite ser usada como función ventana" -#: executor/spi.c:242 executor/spi.c:342 +#: executor/spi.c:241 executor/spi.c:341 #, c-format msgid "invalid transaction termination" msgstr "terminación de transacción no válida" -#: executor/spi.c:257 +#: executor/spi.c:256 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "no se puede comprometer mientras hay una subtransacción activa" -#: executor/spi.c:348 +#: executor/spi.c:347 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "no se puede hacer rollback mientras hay una subtransacción activa" -#: executor/spi.c:472 +#: executor/spi.c:471 #, c-format msgid "transaction left non-empty SPI stack" msgstr "transacción dejó un stack SPI no vacío" -#: executor/spi.c:473 executor/spi.c:533 +#: executor/spi.c:472 executor/spi.c:532 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "Revise llamadas a «SPI_finish» faltantes." -#: executor/spi.c:532 +#: executor/spi.c:531 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "subtransacción dejó un stack SPI no vacío" -#: executor/spi.c:1600 +#: executor/spi.c:1602 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "no se puede abrir plan de varias consultas como cursor" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1610 +#: executor/spi.c:1612 #, c-format msgid "cannot open %s query as cursor" msgstr "no se puede abrir consulta %s como cursor" -#: executor/spi.c:1716 +#: executor/spi.c:1718 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE no está soportado" -#: executor/spi.c:1717 parser/analyze.c:2874 +#: executor/spi.c:1719 parser/analyze.c:2928 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "Los cursores declarados SCROLL deben ser READ ONLY." -#: executor/spi.c:2474 +#: executor/spi.c:2496 #, c-format msgid "empty query does not return tuples" msgstr "la consulta vacía no retorna tuplas" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2548 +#: executor/spi.c:2570 #, c-format msgid "%s query does not return tuples" msgstr "la consulta «%s» no retorna tuplas" -#: executor/spi.c:2963 +#: executor/spi.c:2987 #, c-format msgid "SQL expression \"%s\"" msgstr "expresión SQL «%s»" -#: executor/spi.c:2968 +#: executor/spi.c:2992 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "asignación PL/pgSQL «%s»" -#: executor/spi.c:2971 +#: executor/spi.c:2995 #, c-format msgid "SQL statement \"%s\"" msgstr "sentencia SQL: «%s»" @@ -14039,35 +14353,34 @@ msgstr "sentencia SQL: «%s»" msgid "could not send tuple to shared-memory queue" msgstr "no se pudo enviar la tupla a la cola en memoria compartida" -#: foreign/foreign.c:222 +#: foreign/foreign.c:225 +#, c-format +msgid "user mapping not found for user \"%s\", server \"%s\"" +msgstr "no se encontró un mapeo para el usuario «%s», servidor «%s»" + +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7153 +#: optimizer/util/plancat.c:540 #, c-format -msgid "user mapping not found for \"%s\"" -msgstr "no se encontró un mapeo para el usuario «%s»" +msgid "access to non-system foreign table is restricted" +msgstr "el acceso a la tabla foránea no de sistema está restringido" -#: foreign/foreign.c:647 storage/file/fd.c:3881 +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "el nombre de opción «%s» no es válido" -#: foreign/foreign.c:649 -#, fuzzy, c-format -#| msgid "Perhaps you meant to reference the column \"%s.%s\"." +#: foreign/foreign.c:662 +#, c-format msgid "Perhaps you meant the option \"%s\"." -msgstr "Probablemente quiera hacer referencia a la columna «%s.%s»." - -#: foreign/foreign.c:651 -#, fuzzy, c-format -#| msgid "There are no old transactions anymore." -msgid "There are no valid options in this context." -msgstr "Ya no hay transacciones antiguas en ejecución." +msgstr "Quizás se refiere a la opción «%s»." -#: jit/jit.c:205 utils/fmgr/dfmgr.c:209 utils/fmgr/dfmgr.c:415 +#: foreign/foreign.c:664 #, c-format -msgid "could not access file \"%s\": %m" -msgstr "no se pudo acceder al archivo «%s»: %m" +msgid "There are no valid options in this context." +msgstr "No hay opciones válidas en este contexto." -#: lib/dshash.c:254 utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:736 -#: utils/mmgr/dsa.c:817 +#: lib/dshash.c:254 utils/mmgr/dsa.c:708 utils/mmgr/dsa.c:730 +#: utils/mmgr/dsa.c:811 #, c-format msgid "Failed on DSA request of size %zu." msgstr "Falla en petición DSA de tamaño %zu." @@ -14077,708 +14390,700 @@ msgstr "Falla en petición DSA de tamaño %zu." msgid "expected SASL response, got message type %d" msgstr "se esperaba una respuesta SASL, se obtuvo mensaje de tipo %d" -#: libpq/auth-scram.c:270 +#: libpq/auth-scram.c:263 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "cliente eligió un mecanismo de autentificación SASL no válido" -#: libpq/auth-scram.c:294 libpq/auth-scram.c:543 libpq/auth-scram.c:554 +#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "el secreto SCRAM para el usuario «%s» no es válido" -#: libpq/auth-scram.c:305 +#: libpq/auth-scram.c:298 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "El usuario «%s» no tiene un secreto SCRAM válido." -#: libpq/auth-scram.c:385 libpq/auth-scram.c:390 libpq/auth-scram.c:744 -#: libpq/auth-scram.c:752 libpq/auth-scram.c:857 libpq/auth-scram.c:870 -#: libpq/auth-scram.c:880 libpq/auth-scram.c:988 libpq/auth-scram.c:995 -#: libpq/auth-scram.c:1010 libpq/auth-scram.c:1025 libpq/auth-scram.c:1039 -#: libpq/auth-scram.c:1057 libpq/auth-scram.c:1072 libpq/auth-scram.c:1386 -#: libpq/auth-scram.c:1394 +#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 +#: libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 +#: libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 +#: libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 +#: libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 +#: libpq/auth-scram.c:1387 #, c-format msgid "malformed SCRAM message" msgstr "mensaje SCRAM mal formado" -#: libpq/auth-scram.c:386 +#: libpq/auth-scram.c:379 #, c-format msgid "The message is empty." msgstr "El mensaje está vacío." -#: libpq/auth-scram.c:391 +#: libpq/auth-scram.c:384 #, c-format msgid "Message length does not match input length." msgstr "El largo del mensaje no coincide con el largo de entrada." -#: libpq/auth-scram.c:423 +#: libpq/auth-scram.c:416 #, c-format msgid "invalid SCRAM response" msgstr "respuesta SCRAM no válida" -#: libpq/auth-scram.c:424 +#: libpq/auth-scram.c:417 #, c-format msgid "Nonce does not match." msgstr "El «nonce» no coincide." -#: libpq/auth-scram.c:500 +#: libpq/auth-scram.c:493 #, c-format msgid "could not generate random salt" msgstr "no se pudo generar una sal aleatoria" -#: libpq/auth-scram.c:745 +#: libpq/auth-scram.c:738 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "Se esperaba un atributo «%c» pero se encontró «%s»." -#: libpq/auth-scram.c:753 libpq/auth-scram.c:881 +#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "Se esperaba el carácter «=» para el atributo «%c»." -#: libpq/auth-scram.c:858 +#: libpq/auth-scram.c:851 #, c-format msgid "Attribute expected, but found end of string." msgstr "Se esperaba un atributo, se encontró el fin de la cadena." -#: libpq/auth-scram.c:871 +#: libpq/auth-scram.c:864 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "Se esperaba un atributo, se encontró el carácter no válido «%s»." -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 #, c-format msgid "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data." msgstr "El cliente seleccionó SCRAM-SHA-256-PLUS, pero el mensaje SCRAM no incluye los datos de enlazado (binding) del canal." -#: libpq/auth-scram.c:996 libpq/auth-scram.c:1026 +#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 #, c-format msgid "Comma expected, but found character \"%s\"." msgstr "Se esperaba una coma, se encontró el carácter «%s»." -#: libpq/auth-scram.c:1017 +#: libpq/auth-scram.c:1010 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "error de negociación de enlazado (binding) de canal SCRAM" -#: libpq/auth-scram.c:1018 +#: libpq/auth-scram.c:1011 #, c-format msgid "The client supports SCRAM channel binding but thinks the server does not. However, this server does support channel binding." msgstr "El cliente soporta enlazado (binding) de canal SCRAM, pero piensa que el servidor no. Sin embargo, este servidor sí soporta enlazado de canal." -#: libpq/auth-scram.c:1040 +#: libpq/auth-scram.c:1033 #, c-format msgid "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data." msgstr "El cliente seleccionó SCRAM-SHA-256 sin enlazado de canal, pero el mensaje SCRAM incluye datos de enlazado de canal." -#: libpq/auth-scram.c:1051 +#: libpq/auth-scram.c:1044 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "tipo de enlazado de canal SCRAM «%s» no soportado" -#: libpq/auth-scram.c:1058 +#: libpq/auth-scram.c:1051 #, c-format msgid "Unexpected channel-binding flag \"%s\"." msgstr "Indicador de enlazado de canal «%s» inesperado." -#: libpq/auth-scram.c:1068 +#: libpq/auth-scram.c:1061 #, c-format msgid "client uses authorization identity, but it is not supported" msgstr "el cliente usa identidad de autorización, pero no está soportada" -#: libpq/auth-scram.c:1073 +#: libpq/auth-scram.c:1066 #, c-format msgid "Unexpected attribute \"%s\" in client-first-message." msgstr "Atributo inesperado \"%s\" en client-first-message." -#: libpq/auth-scram.c:1089 +#: libpq/auth-scram.c:1082 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "el cliente requiere una extensión SCRAM no soportada" -#: libpq/auth-scram.c:1103 +#: libpq/auth-scram.c:1096 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "caracteres no imprimibles en el «nonce» SCRAM" -#: libpq/auth-scram.c:1234 +#: libpq/auth-scram.c:1227 #, c-format msgid "could not generate random nonce" msgstr "no se pudo generar un «nonce» aleatorio" -#: libpq/auth-scram.c:1244 +#: libpq/auth-scram.c:1237 #, c-format msgid "could not encode random nonce" msgstr "no se pudo codificar un «nonce» aleatorio" -#: libpq/auth-scram.c:1350 +#: libpq/auth-scram.c:1343 #, c-format msgid "SCRAM channel binding check failed" msgstr "la verificación de enlazado (binding) de canal SCRAM falló" -#: libpq/auth-scram.c:1368 +#: libpq/auth-scram.c:1361 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "atributo de enlazado de canal SCRAM inesperado en client-final-message" -#: libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:1380 #, c-format msgid "Malformed proof in client-final-message." msgstr "Prueba (proof) mal formada en client-final-message." -#: libpq/auth-scram.c:1395 +#: libpq/auth-scram.c:1388 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "Basura encontrada al final de client-final-message." -#: libpq/auth.c:271 +#: libpq/auth.c:269 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "la autentificación falló para el usuario «%s»: anfitrión rechazado" -#: libpq/auth.c:274 +#: libpq/auth.c:272 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "la autentificación «trust» falló para el usuario «%s»" -#: libpq/auth.c:277 +#: libpq/auth.c:275 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "la autentificación Ident falló para el usuario «%s»" -#: libpq/auth.c:280 +#: libpq/auth.c:278 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "la autentificación Peer falló para el usuario «%s»" -#: libpq/auth.c:285 +#: libpq/auth.c:283 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "la autentificación password falló para el usuario «%s»" -#: libpq/auth.c:290 +#: libpq/auth.c:288 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "la autentificación GSSAPI falló para el usuario «%s»" -#: libpq/auth.c:293 +#: libpq/auth.c:291 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "la autentificación SSPI falló para el usuario «%s»" -#: libpq/auth.c:296 +#: libpq/auth.c:294 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "la autentificación PAM falló para el usuario «%s»" -#: libpq/auth.c:299 +#: libpq/auth.c:297 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "la autentificación BSD falló para el usuario «%s»" -#: libpq/auth.c:302 +#: libpq/auth.c:300 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "la autentificación LDAP falló para el usuario «%s»" -#: libpq/auth.c:305 +#: libpq/auth.c:303 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "la autentificación por certificado falló para el usuario «%s»" -#: libpq/auth.c:308 +#: libpq/auth.c:306 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "la autentificación RADIUS falló para el usuario «%s»" -#: libpq/auth.c:311 +#: libpq/auth.c:309 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "la autentificación falló para el usuario «%s»: método de autentificación no válido" -#: libpq/auth.c:315 -#, fuzzy, c-format -#| msgid "reconnection failed: %s" -msgid "Connection matched %s line %d: \"%s\"" -msgstr "falló la reconexión: %s" +#: libpq/auth.c:313 +#, c-format +msgid "Connection matched file \"%s\" line %d: \"%s\"" +msgstr "La conexión coincidió con el archivo «%s» línea %d: «%s»" -#: libpq/auth.c:359 +#: libpq/auth.c:357 #, c-format msgid "authentication identifier set more than once" msgstr "identificador de autentificación establecido más de una vez" -#: libpq/auth.c:360 +#: libpq/auth.c:358 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "identificador anterior: «%s»; nuevo identificador: «%s»" -#: libpq/auth.c:370 +#: libpq/auth.c:368 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "conexión autenticada: identidad=«%s» método=%s (%s:%d)" -#: libpq/auth.c:410 +#: libpq/auth.c:408 #, c-format msgid "client certificates can only be checked if a root certificate store is available" msgstr "los certificados de cliente sólo pueden verificarse si un almacén de certificado raíz está disponible" -#: libpq/auth.c:421 +#: libpq/auth.c:419 #, c-format msgid "connection requires a valid client certificate" msgstr "la conexión requiere un certificado de cliente válido" -#: libpq/auth.c:452 libpq/auth.c:498 +#: libpq/auth.c:450 libpq/auth.c:496 msgid "GSS encryption" msgstr "cifrado GSS" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:453 libpq/auth.c:499 msgid "SSL encryption" msgstr "cifrado SSL" -#: libpq/auth.c:457 libpq/auth.c:503 +#: libpq/auth.c:455 libpq/auth.c:501 msgid "no encryption" msgstr "sin cifrado" #. translator: last %s describes encryption state -#: libpq/auth.c:463 +#: libpq/auth.c:461 #, c-format msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf rechaza la conexión de replicación para el servidor «%s», usuario «%s», %s" #. translator: last %s describes encryption state -#: libpq/auth.c:470 +#: libpq/auth.c:468 #, c-format msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf rechaza la conexión para el servidor «%s», usuario «%s», base de datos «%s», %s" -#: libpq/auth.c:508 +#: libpq/auth.c:506 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "La dirección IP del cliente fue resuelta a «%s», este resultado es coincidente." -#: libpq/auth.c:511 +#: libpq/auth.c:509 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "La dirección IP del cliente fue resuelta a «%s», este resultado no fue verificado." -#: libpq/auth.c:514 +#: libpq/auth.c:512 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "La dirección IP del cliente fue resuelta a «%s», este resultado no es coincidente." -#: libpq/auth.c:517 +#: libpq/auth.c:515 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "No se pudo traducir el nombre de host del cliente «%s» a una dirección IP: %s." -#: libpq/auth.c:522 +#: libpq/auth.c:520 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "No se pudo obtener la dirección IP del cliente a un nombre de host: %s." #. translator: last %s describes encryption state -#: libpq/auth.c:530 +#: libpq/auth.c:528 #, c-format msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s" msgstr "no hay una línea en pg_hba.conf para la conexión de replicación desde el servidor «%s», usuario «%s», %s" #. translator: last %s describes encryption state -#: libpq/auth.c:538 +#: libpq/auth.c:536 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "no hay una línea en pg_hba.conf para «%s», usuario «%s», base de datos «%s», %s" -#: libpq/auth.c:711 +#: libpq/auth.c:656 +#, c-format +msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" +msgstr "conexión autenticada: usuario=«%s» método=%s (%s:%d)" + +#: libpq/auth.c:725 #, c-format msgid "expected password response, got message type %d" msgstr "se esperaba una respuesta de contraseña, se obtuvo mensaje de tipo %d" -#: libpq/auth.c:732 +#: libpq/auth.c:746 #, c-format msgid "invalid password packet size" msgstr "el tamaño del paquete de contraseña no es válido" -#: libpq/auth.c:750 +#: libpq/auth.c:764 #, c-format msgid "empty password returned by client" msgstr "el cliente retornó una contraseña vacía" -#: libpq/auth.c:879 libpq/hba.c:1749 -#, c-format -msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled" -msgstr "la autentificación MD5 no está soportada cuando «db_user_namespace» está activo" - -#: libpq/auth.c:885 +#: libpq/auth.c:892 #, c-format msgid "could not generate random MD5 salt" msgstr "no se pudo generar una sal MD5 aleatoria" -#: libpq/auth.c:936 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 #, c-format msgid "could not set environment: %m" msgstr "no se pudo establecer el ambiente: %m" -#: libpq/auth.c:975 +#: libpq/auth.c:982 #, c-format msgid "expected GSS response, got message type %d" msgstr "se esperaba una respuesta GSS, se obtuvo mensaje de tipo %d" -#: libpq/auth.c:1041 +#: libpq/auth.c:1048 msgid "accepting GSS security context failed" msgstr "falló la aceptación del contexto de seguridad GSS" -#: libpq/auth.c:1082 +#: libpq/auth.c:1089 msgid "retrieving GSS user name failed" msgstr "falló la obtención del nombre de usuario GSS" -#: libpq/auth.c:1228 +#: libpq/auth.c:1235 msgid "could not acquire SSPI credentials" msgstr "no se pudo obtener las credenciales SSPI" -#: libpq/auth.c:1253 +#: libpq/auth.c:1260 #, c-format msgid "expected SSPI response, got message type %d" msgstr "se esperaba una respuesta SSPI, se obtuvo mensaje de tipo %d" -#: libpq/auth.c:1331 +#: libpq/auth.c:1338 msgid "could not accept SSPI security context" msgstr "no se pudo aceptar un contexto SSPI" -#: libpq/auth.c:1372 +#: libpq/auth.c:1379 msgid "could not get token from SSPI security context" msgstr "no se pudo obtener un testigo (token) desde el contexto de seguridad SSPI" -#: libpq/auth.c:1508 libpq/auth.c:1527 +#: libpq/auth.c:1515 libpq/auth.c:1534 #, c-format msgid "could not translate name" msgstr "no se pudo traducir el nombre" -#: libpq/auth.c:1540 +#: libpq/auth.c:1547 #, c-format msgid "realm name too long" msgstr "nombre de «realm» demasiado largo" -#: libpq/auth.c:1555 +#: libpq/auth.c:1562 #, c-format msgid "translated account name too long" msgstr "nombre de cuenta traducido demasiado largo" -#: libpq/auth.c:1734 +#: libpq/auth.c:1741 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "no se pudo crear un socket para conexión Ident: %m" -#: libpq/auth.c:1749 +#: libpq/auth.c:1756 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "no se pudo enlazar a la dirección local «%s»: %m" -#: libpq/auth.c:1761 +#: libpq/auth.c:1768 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "no se pudo conectar al servidor Ident en dirección «%s», port %s: %m" -#: libpq/auth.c:1783 +#: libpq/auth.c:1790 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "no se pudo enviar consulta Ident al servidor «%s», port %s: %m" -#: libpq/auth.c:1800 +#: libpq/auth.c:1807 #, c-format msgid "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "no se pudo recibir respuesta Ident desde el servidor «%s», port %s: %m" -#: libpq/auth.c:1810 +#: libpq/auth.c:1817 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "respuesta del servidor Ident en formato no válido: «%s»" -#: libpq/auth.c:1863 +#: libpq/auth.c:1870 #, c-format msgid "peer authentication is not supported on this platform" msgstr "método de autentificación peer no está soportado en esta plataforma" -#: libpq/auth.c:1867 +#: libpq/auth.c:1874 #, c-format msgid "could not get peer credentials: %m" msgstr "no se pudo recibir credenciales: %m" -#: libpq/auth.c:1879 +#: libpq/auth.c:1886 #, c-format msgid "could not look up local user ID %ld: %s" msgstr "no se pudo encontrar el ID del usuario local %ld: %s" -#: libpq/auth.c:1981 +#: libpq/auth.c:1988 #, c-format msgid "error from underlying PAM layer: %s" msgstr "se ha recibido un error de la biblioteca PAM: %s" -#: libpq/auth.c:1992 +#: libpq/auth.c:1999 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "conversación PAM no soportada: %d/«%s»" -#: libpq/auth.c:2049 +#: libpq/auth.c:2056 #, c-format msgid "could not create PAM authenticator: %s" msgstr "no se pudo crear autenticador PAM: %s" -#: libpq/auth.c:2060 +#: libpq/auth.c:2067 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "pam_set_item(PAM_USER) falló: %s" -#: libpq/auth.c:2092 +#: libpq/auth.c:2099 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "pam_set_item(PAM_RHOST) falló: %s" -#: libpq/auth.c:2104 +#: libpq/auth.c:2111 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "pam_set_item(PAM_CONV) falló: %s" -#: libpq/auth.c:2117 +#: libpq/auth.c:2124 #, c-format msgid "pam_authenticate failed: %s" msgstr "pam_authenticate falló: %s" -#: libpq/auth.c:2130 +#: libpq/auth.c:2137 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "pam_acct_mgmt falló: %s" -#: libpq/auth.c:2141 +#: libpq/auth.c:2148 #, c-format msgid "could not release PAM authenticator: %s" msgstr "no se pudo liberar autenticador PAM: %s" -#: libpq/auth.c:2221 +#: libpq/auth.c:2228 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "no se pudo inicializar LDAP: código de error %d" -#: libpq/auth.c:2258 +#: libpq/auth.c:2265 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "no se pudo extraer el nombre de dominio de ldapbasedn" -#: libpq/auth.c:2266 +#: libpq/auth.c:2273 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "la autentificación LDAP no pudo encontrar registros DNS SRV para «%s»" -#: libpq/auth.c:2268 +#: libpq/auth.c:2275 #, c-format msgid "Set an LDAP server name explicitly." msgstr "Defina un nombre de servidor LDAP explícitamente." -#: libpq/auth.c:2320 +#: libpq/auth.c:2327 #, c-format msgid "could not initialize LDAP: %s" msgstr "no se pudo inicializar LDAP: %s" -#: libpq/auth.c:2330 +#: libpq/auth.c:2337 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "ldaps no está soportado con esta biblioteca LDAP" -#: libpq/auth.c:2338 +#: libpq/auth.c:2345 #, c-format msgid "could not initialize LDAP: %m" msgstr "no se pudo inicializar LDAP: %m" -#: libpq/auth.c:2348 +#: libpq/auth.c:2355 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "no se pudo definir la versión de protocolo LDAP: %s" -#: libpq/auth.c:2364 +#: libpq/auth.c:2371 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "no se pudo iniciar sesión de LDAP TLS: %s" -#: libpq/auth.c:2441 +#: libpq/auth.c:2448 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "servidor LDAP no especificado, y no hay ldapbasedn" -#: libpq/auth.c:2448 +#: libpq/auth.c:2455 #, c-format msgid "LDAP server not specified" msgstr "servidor LDAP no especificado" -#: libpq/auth.c:2510 +#: libpq/auth.c:2517 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "carácter no válido en nombre de usuario para autentificación LDAP" -#: libpq/auth.c:2527 +#: libpq/auth.c:2534 #, c-format msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s" msgstr "no se pudo hacer el enlace LDAP inicial para el ldapbinddb «%s» en el servidor «%s»: %s" -#: libpq/auth.c:2557 +#: libpq/auth.c:2564 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "no se pudo hacer la búsqueda LDAP para el filtro «%s» en el servidor «%s»: %s" -#: libpq/auth.c:2573 +#: libpq/auth.c:2580 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "no existe el usuario LDAP «%s»" -#: libpq/auth.c:2574 +#: libpq/auth.c:2581 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "La búsqueda LDAP para el filtro «%s» en el servidor «%s» no retornó elementos." -#: libpq/auth.c:2578 +#: libpq/auth.c:2585 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "el usuario LDAP «%s» no es única" -#: libpq/auth.c:2579 +#: libpq/auth.c:2586 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries." msgstr[0] "La búsqueda LDAP para el filtro «%s» en el servidor «%s» retornó %d elemento." msgstr[1] "La búsqueda LDAP para el filtro «%s» en el servidor «%s» retornó %d elementos." -#: libpq/auth.c:2599 +#: libpq/auth.c:2606 #, c-format msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" msgstr "no se pudo obtener el dn para la primera entrada que coincide con «%s» en el servidor «%s»: %s" -#: libpq/auth.c:2620 -#, c-format -msgid "could not unbind after searching for user \"%s\" on server \"%s\"" -msgstr "no se pudo desconectar (unbind) después de buscar al usuario «%s» en el servidor «%s»" - -#: libpq/auth.c:2651 +#: libpq/auth.c:2633 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "falló el inicio de sesión LDAP para el usuario «%s» en el servidor «%s»: %s" -#: libpq/auth.c:2683 +#: libpq/auth.c:2665 #, c-format msgid "LDAP diagnostics: %s" msgstr "Diagnóstico LDAP: %s" -#: libpq/auth.c:2721 +#: libpq/auth.c:2703 #, c-format msgid "certificate authentication failed for user \"%s\": client certificate contains no user name" msgstr "la autentificación con certificado falló para el usuario «%s»: el certificado de cliente no contiene un nombre de usuario" -#: libpq/auth.c:2742 +#: libpq/auth.c:2724 #, c-format msgid "certificate authentication failed for user \"%s\": unable to retrieve subject DN" msgstr "la autentificación por certificado falló para el usuario «%s»: no se pudo obtener el DN del sujeto" -#: libpq/auth.c:2765 +#: libpq/auth.c:2747 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch" msgstr "la validación de certificado (clientcert=verify-full) falló para el usuario «%s»: discordancia de DN" -#: libpq/auth.c:2770 +#: libpq/auth.c:2752 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch" msgstr "la validación de certificado (clientcert=verify-full) falló para el usuario «%s»: discordancia de CN" -#: libpq/auth.c:2872 +#: libpq/auth.c:2854 #, c-format msgid "RADIUS server not specified" msgstr "servidor RADIUS no especificado" -#: libpq/auth.c:2879 +#: libpq/auth.c:2861 #, c-format msgid "RADIUS secret not specified" msgstr "secreto RADIUS no especificado" -#: libpq/auth.c:2893 +#: libpq/auth.c:2875 #, c-format msgid "RADIUS authentication does not support passwords longer than %d characters" msgstr "la autentificación RADIUS no soporta contraseñas más largas de %d caracteres" -#: libpq/auth.c:2995 libpq/hba.c:2391 +#: libpq/auth.c:2977 libpq/hba.c:2352 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "no se pudo traducir el nombre de servidor RADIUS «%s» a dirección: %s" -#: libpq/auth.c:3009 +#: libpq/auth.c:2991 #, c-format msgid "could not generate random encryption vector" msgstr "no se pudo generar un vector aleatorio de encriptación" -#: libpq/auth.c:3046 -#, fuzzy, c-format -#| msgid "could not encrypt password: %s" +#: libpq/auth.c:3028 +#, c-format msgid "could not perform MD5 encryption of password: %s" -msgstr "no se pudo cifrar contraseña: %s" +msgstr "no se pudo efectuar cifrado MD5 de contraseña: %s" -#: libpq/auth.c:3073 +#: libpq/auth.c:3055 #, c-format msgid "could not create RADIUS socket: %m" msgstr "no se pudo crear el socket RADIUS: %m" -#: libpq/auth.c:3089 +#: libpq/auth.c:3071 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "no se pudo enlazar el socket RADIUS local: %m" -#: libpq/auth.c:3099 +#: libpq/auth.c:3081 #, c-format msgid "could not send RADIUS packet: %m" msgstr "no se pudo enviar el paquete RADIUS: %m" -#: libpq/auth.c:3133 libpq/auth.c:3159 +#: libpq/auth.c:3115 libpq/auth.c:3141 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "se agotó el tiempo de espera de la respuesta RADIUS desde %s" -#: libpq/auth.c:3152 +#: libpq/auth.c:3134 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "no se pudo verificar el estado en el socket %m" -#: libpq/auth.c:3182 +#: libpq/auth.c:3164 #, c-format msgid "could not read RADIUS response: %m" msgstr "no se pudo leer la respuesta RADIUS: %m" -#: libpq/auth.c:3190 +#: libpq/auth.c:3172 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "la respuesta RADIUS desde %s fue enviada desde el port incorrecto: %d" -#: libpq/auth.c:3198 +#: libpq/auth.c:3180 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "la respuesta RADIUS desde %s es demasiado corta: %d" -#: libpq/auth.c:3205 +#: libpq/auth.c:3187 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "la respuesta RADIUS desde %ss tiene largo corrupto: %d (largo real %d)" -#: libpq/auth.c:3213 +#: libpq/auth.c:3195 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "la respuesta RADIUS desde %s es a una petición diferente: %d (debería ser %d)" -#: libpq/auth.c:3238 -#, fuzzy, c-format -#| msgid "could not send feedback packet: %s" +#: libpq/auth.c:3220 +#, c-format msgid "could not perform MD5 encryption of received packet: %s" -msgstr "no se pudo enviar el paquete de retroalimentación: %s" +msgstr "no se pudo efectuar cifrado MD5 del paquete recibido: %s" -#: libpq/auth.c:3248 +#: libpq/auth.c:3230 #, c-format msgid "RADIUS response from %s has incorrect MD5 signature" msgstr "la respuesta RADIUS desde %s tiene firma MD5 incorrecta" -#: libpq/auth.c:3266 +#: libpq/auth.c:3248 #, c-format msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "la respuesta RADIUS desde %s tiene código no válido (%d) para el usuario «%s»" @@ -14835,64 +15140,51 @@ msgstr "no se pudo escribir el archivo del servidor «%s»: %m" msgid "large object read request is too large" msgstr "el tamaño de petición de lectura de objeto grande es muy grande" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:262 utils/adt/genfile.c:294 -#: utils/adt/genfile.c:315 +#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "el tamaño solicitado no puede ser negativo" -#: libpq/be-fsstubs.c:871 storage/large_object/inv_api.c:299 -#: storage/large_object/inv_api.c:311 storage/large_object/inv_api.c:508 -#: storage/large_object/inv_api.c:619 storage/large_object/inv_api.c:809 -#, c-format -msgid "permission denied for large object %u" -msgstr "permiso denegado al objeto grande %u" - -#: libpq/be-secure-common.c:71 -#, c-format -msgid "could not read from command \"%s\": %m" -msgstr "no se pudo leer desde la orden «%s»: %m" - -#: libpq/be-secure-common.c:91 +#: libpq/be-secure-common.c:94 #, c-format msgid "command \"%s\" failed" msgstr "la orden «%s» falló" -#: libpq/be-secure-common.c:119 +#: libpq/be-secure-common.c:123 #, c-format msgid "could not access private key file \"%s\": %m" msgstr "no se pudo acceder al archivo de la llave privada «%s»: %m" -#: libpq/be-secure-common.c:129 +#: libpq/be-secure-common.c:133 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "el archivo de llave privada «%s» no es un archivo regular" -#: libpq/be-secure-common.c:155 +#: libpq/be-secure-common.c:159 #, c-format msgid "private key file \"%s\" must be owned by the database user or root" msgstr "el archivo de llave privada «%s» debe ser de propiedad del usuario de base de datos o root" -#: libpq/be-secure-common.c:165 +#: libpq/be-secure-common.c:169 #, c-format msgid "private key file \"%s\" has group or world access" msgstr "el archivo de la llave privada «%s» tiene acceso para el grupo u otros" -#: libpq/be-secure-common.c:167 +#: libpq/be-secure-common.c:171 #, c-format msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root." msgstr "El archivo debe tener permisos u=rw (0600) o menos si es de propiedad del usuario de base deatos, o permisos u=rw,g=r (0640) o menos si es de root." -#: libpq/be-secure-gssapi.c:204 +#: libpq/be-secure-gssapi.c:201 msgid "GSSAPI wrap error" msgstr "error de «wrap» de GSSAPI" -#: libpq/be-secure-gssapi.c:211 +#: libpq/be-secure-gssapi.c:208 #, c-format msgid "outgoing GSSAPI message would not use confidentiality" msgstr "mensaje saliente GSSAPI no proveería confidencialidad" -#: libpq/be-secure-gssapi.c:218 libpq/be-secure-gssapi.c:634 +#: libpq/be-secure-gssapi.c:215 libpq/be-secure-gssapi.c:634 #, c-format msgid "server tried to send oversize GSSAPI packet (%zu > %zu)" msgstr "el servidor intentó enviar un paquete GSSAPI demasiado grande (%zu > %zu)" @@ -14924,819 +15216,810 @@ msgstr "no se pudo aceptar un contexto de seguridad GSSAPI" msgid "GSSAPI size check error" msgstr "error de verificación de tamaño GSSAPI" -#: libpq/be-secure-openssl.c:125 +#: libpq/be-secure-openssl.c:131 #, c-format msgid "could not create SSL context: %s" msgstr "no se pudo crear un contexto SSL: %s" -#: libpq/be-secure-openssl.c:151 +#: libpq/be-secure-openssl.c:157 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "no se pudo cargar el archivo de certificado de servidor «%s»: %s" -#: libpq/be-secure-openssl.c:171 +#: libpq/be-secure-openssl.c:177 #, c-format msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "el archivo de clave privada \"%s\" no se puede volver a cargar porque requiere una contraseña" -#: libpq/be-secure-openssl.c:176 +#: libpq/be-secure-openssl.c:182 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "no se pudo cargar el archivo de la llave privada «%s»: %s" -#: libpq/be-secure-openssl.c:185 +#: libpq/be-secure-openssl.c:191 #, c-format msgid "check of private key failed: %s" msgstr "falló la revisión de la llave privada: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:198 libpq/be-secure-openssl.c:221 +#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "el valor «%2$s» para la opción «%1$s» no está soportado en este servidor" -#: libpq/be-secure-openssl.c:208 +#: libpq/be-secure-openssl.c:214 #, c-format msgid "could not set minimum SSL protocol version" msgstr "no se pudo definir la versión mínima de protocolo SSL" -#: libpq/be-secure-openssl.c:231 +#: libpq/be-secure-openssl.c:237 #, c-format msgid "could not set maximum SSL protocol version" msgstr "no se pudo definir la versión máxima de protocolo SSL" -#: libpq/be-secure-openssl.c:247 +#: libpq/be-secure-openssl.c:253 #, c-format msgid "could not set SSL protocol version range" msgstr "no se pudo definir el rango de versión de protocolo SSL" -#: libpq/be-secure-openssl.c:248 +#: libpq/be-secure-openssl.c:254 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "«%s» no puede ser más alto que «%s»" -#: libpq/be-secure-openssl.c:285 +#: libpq/be-secure-openssl.c:307 #, c-format msgid "could not set the cipher list (no valid ciphers available)" msgstr "no se pudo establecer la lista de cifrado (no hay cifradores disponibles)" -#: libpq/be-secure-openssl.c:305 +#: libpq/be-secure-openssl.c:327 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "no se pudo cargar el archivo del certificado raíz «%s»: %s" -#: libpq/be-secure-openssl.c:354 +#: libpq/be-secure-openssl.c:376 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "no se pudo cargar el archivo de lista de revocación de certificados SSL «%s»: %s" -#: libpq/be-secure-openssl.c:362 +#: libpq/be-secure-openssl.c:384 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "no se pudo cargar el directorio de lista de revocación de certificados SSL «%s»: %s" -#: libpq/be-secure-openssl.c:370 +#: libpq/be-secure-openssl.c:392 #, c-format msgid "could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s" msgstr "no se pudo cargar el archivo de lista de revocación de certificados SSL «%s» o directorio «%s»: %s" -#: libpq/be-secure-openssl.c:428 +#: libpq/be-secure-openssl.c:450 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "no se pudo inicializar la conexión SSL: el contexto SSL no está instalado" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:464 #, c-format msgid "could not initialize SSL connection: %s" msgstr "no se pudo inicializar la conexión SSL: %s" -#: libpq/be-secure-openssl.c:447 +#: libpq/be-secure-openssl.c:472 #, c-format msgid "could not set SSL socket: %s" msgstr "no se definir un socket SSL: %s" -#: libpq/be-secure-openssl.c:502 +#: libpq/be-secure-openssl.c:528 #, c-format msgid "could not accept SSL connection: %m" msgstr "no se pudo aceptar una conexión SSL: %m" -#: libpq/be-secure-openssl.c:506 libpq/be-secure-openssl.c:561 +#: libpq/be-secure-openssl.c:532 libpq/be-secure-openssl.c:589 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "no se pudo aceptar una conexión SSL: se detectó EOF" -#: libpq/be-secure-openssl.c:545 +#: libpq/be-secure-openssl.c:573 #, c-format msgid "could not accept SSL connection: %s" msgstr "no se pudo aceptar una conexión SSL: %s" -#: libpq/be-secure-openssl.c:549 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "This may indicate that the client does not support any SSL protocol version between %s and %s." msgstr "Esto puede indicar que el cliente no soporta ninguna versión del protocolo SSL entre %s y %s." -#: libpq/be-secure-openssl.c:566 libpq/be-secure-openssl.c:746 -#: libpq/be-secure-openssl.c:810 +#: libpq/be-secure-openssl.c:594 libpq/be-secure-openssl.c:809 +#: libpq/be-secure-openssl.c:879 #, c-format msgid "unrecognized SSL error code: %d" msgstr "código de error SSL no reconocido: %d" -#: libpq/be-secure-openssl.c:612 +#: libpq/be-secure-openssl.c:622 +#, c-format +msgid "received SSL connection request with unexpected ALPN protocol" +msgstr "recibido una solicitud de conexión SSL con protocolo ALPN inesperado" + +#: libpq/be-secure-openssl.c:666 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "el «common name» del certificado SSL contiene un carácter null" -#: libpq/be-secure-openssl.c:652 +#: libpq/be-secure-openssl.c:712 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "el elemento de nombre distinguido en el certificado SSL contiene un carácter null" -#: libpq/be-secure-openssl.c:735 libpq/be-secure-openssl.c:794 +#: libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:863 #, c-format msgid "SSL error: %s" msgstr "error de SSL: %s" -#: libpq/be-secure-openssl.c:976 +#: libpq/be-secure-openssl.c:1038 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "no se pudo abrir el archivo de parámetros DH «%s»: %m" -#: libpq/be-secure-openssl.c:988 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not load DH parameters file: %s" msgstr "no se pudo cargar el archivo de parámetros DH: %s" -#: libpq/be-secure-openssl.c:998 +#: libpq/be-secure-openssl.c:1060 #, c-format msgid "invalid DH parameters: %s" msgstr "parámetros DH no válidos: %s" -#: libpq/be-secure-openssl.c:1007 +#: libpq/be-secure-openssl.c:1069 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "parámetros DH no válidos: p no es primo" -#: libpq/be-secure-openssl.c:1016 +#: libpq/be-secure-openssl.c:1078 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "parámetros DH no válidos: no hay generador apropiado o primo seguro" -#: libpq/be-secure-openssl.c:1152 -#, fuzzy, c-format -#| msgid "certificate authentication failed for user \"%s\"" +#: libpq/be-secure-openssl.c:1214 +#, c-format msgid "Client certificate verification failed at depth %d: %s." -msgstr "la autentificación por certificado falló para el usuario «%s»" +msgstr "La autentificación por certificado de cliente falló en la profundidad %d: %s." -#: libpq/be-secure-openssl.c:1189 +#: libpq/be-secure-openssl.c:1251 #, c-format msgid "Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"." -msgstr "" +msgstr "Datos del certificado fallido (sin verificar): sujeto «%s», número de serie %s, emisor «%s»." -#: libpq/be-secure-openssl.c:1190 +#: libpq/be-secure-openssl.c:1252 msgid "unknown" msgstr "desconocido" -#: libpq/be-secure-openssl.c:1281 +#: libpq/be-secure-openssl.c:1389 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: no se pudo cargar los parámetros DH" -#: libpq/be-secure-openssl.c:1289 +#: libpq/be-secure-openssl.c:1397 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: no se pudo definir los parámetros DH: %s" -#: libpq/be-secure-openssl.c:1316 +#: libpq/be-secure-openssl.c:1424 #, c-format msgid "ECDH: unrecognized curve name: %s" msgstr "ECDH: nombre de curva no reconocida: %s" -#: libpq/be-secure-openssl.c:1325 +#: libpq/be-secure-openssl.c:1433 #, c-format msgid "ECDH: could not create key" msgstr "ECDH: no se pudo crear la llave" -#: libpq/be-secure-openssl.c:1353 +#: libpq/be-secure-openssl.c:1461 msgid "no SSL error reported" msgstr "código de error SSL no reportado" -#: libpq/be-secure-openssl.c:1357 +#: libpq/be-secure-openssl.c:1479 #, c-format msgid "SSL error code %lu" msgstr "código de error SSL %lu" -#: libpq/be-secure-openssl.c:1516 +#: libpq/be-secure-openssl.c:1636 #, c-format msgid "could not create BIO" msgstr "no se pudo crear BIO" -#: libpq/be-secure-openssl.c:1526 +#: libpq/be-secure-openssl.c:1646 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "no se pudo obtener NID para objeto ASN1_OBJECT" -#: libpq/be-secure-openssl.c:1534 +#: libpq/be-secure-openssl.c:1654 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "no se pudo convertir NID %d en una estructura ASN1_OBJECT" -#: libpq/be-secure.c:207 libpq/be-secure.c:303 -#, c-format -msgid "terminating connection due to unexpected postmaster exit" -msgstr "terminando la conexión debido al término inesperado de postmaster" - -#: libpq/crypt.c:49 +#: libpq/crypt.c:48 #, c-format msgid "Role \"%s\" does not exist." msgstr "No existe el rol «%s»." -#: libpq/crypt.c:59 +#: libpq/crypt.c:58 #, c-format msgid "User \"%s\" has no password assigned." msgstr "El usuario «%s» no tiene una contraseña asignada." -#: libpq/crypt.c:77 +#: libpq/crypt.c:76 #, c-format msgid "User \"%s\" has an expired password." msgstr "El usuario «%s» tiene contraseña expirada." -#: libpq/crypt.c:183 +#: libpq/crypt.c:182 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "El usuario \"%s\" tiene una contraseña que no se puede usar con la autentificación MD5." -#: libpq/crypt.c:204 libpq/crypt.c:246 libpq/crypt.c:266 +#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 #, c-format msgid "Password does not match for user \"%s\"." msgstr "La contraseña no coincide para el usuario «%s»." -#: libpq/crypt.c:285 +#: libpq/crypt.c:284 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "La contraseña del usuario \"%s\" está en un formato no reconocido." -#: libpq/hba.c:234 -#, c-format -msgid "authentication file token too long, skipping: \"%s\"" -msgstr "una palabra en el archivo de autentificación es demasiado larga, omitiendo: «%s»" - -#: libpq/hba.c:357 +#: libpq/hba.c:327 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "la expresión regular «%s» no es válida: %s" -#: libpq/hba.c:359 libpq/hba.c:688 libpq/hba.c:1272 libpq/hba.c:1292 -#: libpq/hba.c:1315 libpq/hba.c:1328 libpq/hba.c:1381 libpq/hba.c:1409 -#: libpq/hba.c:1417 libpq/hba.c:1429 libpq/hba.c:1450 libpq/hba.c:1463 -#: libpq/hba.c:1488 libpq/hba.c:1515 libpq/hba.c:1527 libpq/hba.c:1586 -#: libpq/hba.c:1606 libpq/hba.c:1620 libpq/hba.c:1640 libpq/hba.c:1651 -#: libpq/hba.c:1666 libpq/hba.c:1685 libpq/hba.c:1701 libpq/hba.c:1713 -#: libpq/hba.c:1750 libpq/hba.c:1791 libpq/hba.c:1804 libpq/hba.c:1826 -#: libpq/hba.c:1838 libpq/hba.c:1856 libpq/hba.c:1906 libpq/hba.c:1950 -#: libpq/hba.c:1961 libpq/hba.c:1977 libpq/hba.c:1994 libpq/hba.c:2005 -#: libpq/hba.c:2024 libpq/hba.c:2040 libpq/hba.c:2056 libpq/hba.c:2115 -#: libpq/hba.c:2132 libpq/hba.c:2145 libpq/hba.c:2157 libpq/hba.c:2176 -#: libpq/hba.c:2262 libpq/hba.c:2280 libpq/hba.c:2374 libpq/hba.c:2393 -#: libpq/hba.c:2422 libpq/hba.c:2435 libpq/hba.c:2458 libpq/hba.c:2480 -#: libpq/hba.c:2494 tsearch/ts_locale.c:243 +#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 +#: libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 +#: libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 +#: libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 +#: libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 +#: libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 +#: libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 libpq/hba.c:1799 +#: libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 +#: libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 +#: libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 +#: libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 +#: libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 +#: libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 +#: tsearch/ts_locale.c:241 #, c-format msgid "line %d of configuration file \"%s\"" msgstr "línea %d del archivo de configuración «%s»" -#: libpq/hba.c:484 -#, fuzzy, c-format -#| msgid "skipping missing configuration file \"%s\"" +#: libpq/hba.c:457 +#, c-format msgid "skipping missing authentication file \"%s\"" -msgstr "omitiendo el archivo de configuración faltante «%s»" +msgstr "omitiendo el archivo de autentificación faltante «%s»" -#: libpq/hba.c:636 -#, fuzzy, c-format -#| msgid "could not open configuration file \"%s\": maximum nesting depth exceeded" +#: libpq/hba.c:609 +#, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" -msgstr "no se pudo abrir el archivo de configuración «%s»: nivel de anidamiento máximo excedido" +msgstr "no se pudo abrir el archivo «%s»: nivel de anidamiento máximo excedido" -#: libpq/hba.c:1243 +#: libpq/hba.c:1216 #, c-format msgid "error enumerating network interfaces: %m" msgstr "error al enumerar interfaces de red: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1270 +#: libpq/hba.c:1243 #, c-format msgid "authentication option \"%s\" is only valid for authentication methods %s" msgstr "la opción de autentificación «%s» sólo es válida para los métodos de autentificación %s" -#: libpq/hba.c:1290 +#: libpq/hba.c:1263 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "el método de autentificación «%s» requiere que el argumento «%s» esté definido" -#: libpq/hba.c:1314 -#, fuzzy, c-format -#| msgid "missing \"%s\" at end of SQL expression" +#: libpq/hba.c:1287 +#, c-format msgid "missing entry at end of line" -msgstr "falta «%s» al final de la expresión SQL" +msgstr "falta una entrada al final de la línea" -#: libpq/hba.c:1327 +#: libpq/hba.c:1300 #, c-format msgid "multiple values in ident field" msgstr "múltiples valores en campo «ident»" -#: libpq/hba.c:1379 +#: libpq/hba.c:1352 #, c-format msgid "multiple values specified for connection type" msgstr "múltiples valores especificados para tipo de conexión" -#: libpq/hba.c:1380 +#: libpq/hba.c:1353 #, c-format msgid "Specify exactly one connection type per line." msgstr "Especifique exactamente un tipo de conexión por línea." -#: libpq/hba.c:1407 +#: libpq/hba.c:1380 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "el registro hostssl no puede coincidir porque SSL está deshabilitado" -#: libpq/hba.c:1408 +#: libpq/hba.c:1381 #, c-format -msgid "Set ssl = on in postgresql.conf." +msgid "Set \"ssl = on\" in postgresql.conf." msgstr "Defina «ssl = on» en postgresql.conf." -#: libpq/hba.c:1416 +#: libpq/hba.c:1389 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "el registro hostssl no puede coincidir porque SSL no está soportado en esta instalación" -#: libpq/hba.c:1428 +#: libpq/hba.c:1401 #, c-format msgid "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "el registro hostgssenc no puede coincidir porque GSSAPI no está soportado en esta instalación" -#: libpq/hba.c:1448 +#: libpq/hba.c:1421 #, c-format msgid "invalid connection type \"%s\"" msgstr "tipo de conexión «%s» no válido" -#: libpq/hba.c:1462 +#: libpq/hba.c:1435 #, c-format msgid "end-of-line before database specification" msgstr "fin de línea antes de especificación de base de datos" -#: libpq/hba.c:1487 +#: libpq/hba.c:1460 #, c-format msgid "end-of-line before role specification" msgstr "fin de línea antes de especificación de rol" -#: libpq/hba.c:1514 +#: libpq/hba.c:1487 #, c-format msgid "end-of-line before IP address specification" msgstr "fin de línea antes de especificación de dirección IP" -#: libpq/hba.c:1525 +#: libpq/hba.c:1498 #, c-format msgid "multiple values specified for host address" msgstr "múltiples valores especificados para la dirección de anfitrión" -#: libpq/hba.c:1526 +#: libpq/hba.c:1499 #, c-format msgid "Specify one address range per line." msgstr "Especifique un rango de direcciones por línea." -#: libpq/hba.c:1584 +#: libpq/hba.c:1557 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "dirección IP «%s» no válida: %s" -#: libpq/hba.c:1604 +#: libpq/hba.c:1577 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "especificar tanto el nombre de host como la máscara CIDR no es válido: «%s»" -#: libpq/hba.c:1618 +#: libpq/hba.c:1591 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "máscara CIDR no válida en dirección «%s»" -#: libpq/hba.c:1638 +#: libpq/hba.c:1611 #, c-format msgid "end-of-line before netmask specification" msgstr "fin de línea antes de especificación de máscara de red" -#: libpq/hba.c:1639 +#: libpq/hba.c:1612 #, c-format msgid "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "Especifique un rango de direcciones en notación CIDR, o provea una netmask separadamente." -#: libpq/hba.c:1650 +#: libpq/hba.c:1623 #, c-format msgid "multiple values specified for netmask" msgstr "múltiples valores especificados para la máscara de red" -#: libpq/hba.c:1664 +#: libpq/hba.c:1637 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "máscara IP «%s» no válida: %s" -#: libpq/hba.c:1684 +#: libpq/hba.c:1657 #, c-format msgid "IP address and mask do not match" msgstr "La dirección y máscara IP no coinciden" -#: libpq/hba.c:1700 +#: libpq/hba.c:1673 #, c-format msgid "end-of-line before authentication method" msgstr "fin de línea antes de especificación de método de autentificación" -#: libpq/hba.c:1711 +#: libpq/hba.c:1684 #, c-format msgid "multiple values specified for authentication type" msgstr "múltiples valores especificados para el tipo de autentificación" -#: libpq/hba.c:1712 +#: libpq/hba.c:1685 #, c-format msgid "Specify exactly one authentication type per line." msgstr "Especifique exactamente un tipo de autentificación por línea." -#: libpq/hba.c:1789 +#: libpq/hba.c:1750 #, c-format msgid "invalid authentication method \"%s\"" msgstr "método de autentificación «%s» no válido" -#: libpq/hba.c:1802 +#: libpq/hba.c:1763 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "método de autentificación «%s» no válido: este servidor no lo soporta" -#: libpq/hba.c:1825 +#: libpq/hba.c:1786 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "la autentificación gssapi no está soportada en conexiones locales" -#: libpq/hba.c:1837 +#: libpq/hba.c:1798 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "la autentificación peer sólo está soportada en conexiones locales" -#: libpq/hba.c:1855 +#: libpq/hba.c:1816 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "la autentificación cert sólo está soportada en conexiones hostssl" -#: libpq/hba.c:1905 +#: libpq/hba.c:1866 #, c-format msgid "authentication option not in name=value format: %s" msgstr "opción de autentificación en formato nombre=valor: %s" -#: libpq/hba.c:1949 +#: libpq/hba.c:1910 #, c-format msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" msgstr "no se puede usar ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter o ldapurl junto con ldapprefix" -#: libpq/hba.c:1960 +#: libpq/hba.c:1921 #, c-format msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "el método de autentificación «ldap» requiere que los argumento «ldapbasedn», «ldapprefix» o «ldapsuffix» estén definidos" -#: libpq/hba.c:1976 +#: libpq/hba.c:1937 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "no se puede usar ldapsearchattribute junto con ldapsearchfilter" -#: libpq/hba.c:1993 +#: libpq/hba.c:1954 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "la lista de servidores RADIUS no puede ser vacía" -#: libpq/hba.c:2004 +#: libpq/hba.c:1965 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "la lista de secretos RADIUS no puede ser vacía" -#: libpq/hba.c:2021 +#: libpq/hba.c:1982 #, c-format msgid "the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "el número de secretos RADIUS (%d) debe ser 1 o igual al número de servidores RADIUS (%d)" -#: libpq/hba.c:2037 +#: libpq/hba.c:1998 #, c-format msgid "the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "el número de puertos RADIUS (%d) debe ser 1 o igual al número de servidores RADIUS (%d)" -#: libpq/hba.c:2053 +#: libpq/hba.c:2014 #, c-format msgid "the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "el número de identificadores RADIUS (%d) debe ser 1 o igual al número de servidores RADIUS (%d)" -#: libpq/hba.c:2105 +#: libpq/hba.c:2066 msgid "ident, peer, gssapi, sspi, and cert" msgstr "ident, peer, gssapi, sspi y cert" -#: libpq/hba.c:2114 +#: libpq/hba.c:2075 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert sólo puede ser configurado en líneas «hostssl»" -#: libpq/hba.c:2131 +#: libpq/hba.c:2092 #, c-format msgid "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "clientcert solo acepta «verify-full» cuando se emplea autentificación «cert»" -#: libpq/hba.c:2144 +#: libpq/hba.c:2105 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "valor no válido para el parámetro clientcert: «%s»" -#: libpq/hba.c:2156 +#: libpq/hba.c:2117 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname solo puede ser configurado en líneas «hostssl»" -#: libpq/hba.c:2175 +#: libpq/hba.c:2136 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "valor no válido para el parámetro clientname: «%s»" -#: libpq/hba.c:2208 +#: libpq/hba.c:2169 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "no se pudo interpretar la URL LDAP «%s»: %s" -#: libpq/hba.c:2219 +#: libpq/hba.c:2180 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "esquema de URL LDAP no soportado: %s" -#: libpq/hba.c:2243 +#: libpq/hba.c:2204 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "las URLs LDAP no está soportado en esta plataforma" -#: libpq/hba.c:2261 +#: libpq/hba.c:2222 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "valor ldapscheme no válido: «%s»" -#: libpq/hba.c:2279 +#: libpq/hba.c:2240 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "número de puerto LDAP no válido: «%s»" -#: libpq/hba.c:2325 libpq/hba.c:2332 +#: libpq/hba.c:2286 libpq/hba.c:2293 msgid "gssapi and sspi" msgstr "gssapi y sspi" -#: libpq/hba.c:2341 libpq/hba.c:2350 +#: libpq/hba.c:2302 libpq/hba.c:2311 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2372 +#: libpq/hba.c:2333 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "no se pudo interpretar la lista de servidores RADIUS «%s»" -#: libpq/hba.c:2420 +#: libpq/hba.c:2381 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "no se pudo interpretar la lista de port RADIUS «%s»" -#: libpq/hba.c:2434 +#: libpq/hba.c:2395 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "número de puerto RADIUS no válido: «%s»" -#: libpq/hba.c:2456 +#: libpq/hba.c:2417 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "no se pudo interpretar la lista de secretos RADIUS «%s»" -#: libpq/hba.c:2478 +#: libpq/hba.c:2439 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "no se pudo interpretar la lista de identificadores RADIUS «%s»" -#: libpq/hba.c:2492 +#: libpq/hba.c:2453 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "nombre de opción de autentificación desconocido: «%s»" -#: libpq/hba.c:2684 +#: libpq/hba.c:2645 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "el archivo de configuración «%s» no contiene líneas" -#: libpq/hba.c:2838 +#: libpq/hba.c:2798 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "la coincidencia de expresión regular para «%s» falló: %s" -#: libpq/hba.c:2862 +#: libpq/hba.c:2822 #, c-format msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"" msgstr "la expresión regular «%s» no tiene subexpresiones según lo requiere la referencia hacia atrás en «%s»" -#: libpq/hba.c:2965 +#: libpq/hba.c:2925 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "el nombre de usuario entregado (%s) y el nombre de usuario autentificado (%s) no coinciden" -#: libpq/hba.c:2985 +#: libpq/hba.c:2945 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "no hay coincidencia en el mapa «%s» para el usuario «%s» autentificado como «%s»" -#: libpq/pqcomm.c:200 +#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 +#: libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 +#: libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 +#: libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#, c-format +msgid "%s(%s) failed: %m" +msgstr "%s(%s) falló: %m" + +#: libpq/pqcomm.c:296 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "no se pudo establecer el socket en modo no bloqueante: %m" -#: libpq/pqcomm.c:361 +#: libpq/pqcomm.c:456 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "la ruta al socket de dominio Unix «%s» es demasiado larga (máximo %d bytes)" -#: libpq/pqcomm.c:381 +#: libpq/pqcomm.c:476 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "no se pudo traducir el nombre de host «%s», servicio «%s» a dirección: %s" -#: libpq/pqcomm.c:385 +#: libpq/pqcomm.c:480 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "no se pudo traducir el servicio «%s» a dirección: %s" -#: libpq/pqcomm.c:412 +#: libpq/pqcomm.c:502 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "no se pudo enlazar a todas las direcciones pedidas: MAXLISTEN (%d) fue excedido" -#: libpq/pqcomm.c:421 +#: libpq/pqcomm.c:511 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:424 +#: libpq/pqcomm.c:514 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:427 +#: libpq/pqcomm.c:517 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:431 +#: libpq/pqcomm.c:521 #, c-format msgid "unrecognized address family %d" msgstr "la familia de direcciones %d no reconocida" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:455 +#: libpq/pqcomm.c:545 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "no se pudo crear el socket %s de escucha para la dirección «%s»: %m" #. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:481 libpq/pqcomm.c:499 +#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%s(%s) falló para la dirección %s «%s»: %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:522 +#: libpq/pqcomm.c:615 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "no se pudo enlazar a la dirección %s «%s»: %m" -#: libpq/pqcomm.c:526 +#: libpq/pqcomm.c:619 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "¿Hay otro postmaster en ejecución en el puerto %d?" -#: libpq/pqcomm.c:528 +#: libpq/pqcomm.c:621 #, c-format msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry." msgstr "¿Hay otro postmaster en ejecución en el puerto %d? Si no, aguarde unos segundos y reintente." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:557 +#: libpq/pqcomm.c:650 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "no se pudo escuchar en la dirección %s «%s»: %m" -#: libpq/pqcomm.c:565 +#: libpq/pqcomm.c:658 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "escuchando en el socket Unix «%s»" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:570 +#: libpq/pqcomm.c:663 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "escuchando en la dirección %s «%s», port %d" -#: libpq/pqcomm.c:659 +#: libpq/pqcomm.c:753 #, c-format msgid "group \"%s\" does not exist" msgstr "no existe el grupo «%s»" -#: libpq/pqcomm.c:669 +#: libpq/pqcomm.c:763 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "no se pudo definir el grupo del archivo «%s»: %m" -#: libpq/pqcomm.c:680 +#: libpq/pqcomm.c:774 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "no se pudo definir los permisos del archivo «%s»: %m" -#: libpq/pqcomm.c:708 +#: libpq/pqcomm.c:803 #, c-format msgid "could not accept new connection: %m" msgstr "no se pudo aceptar una nueva conexión: %m" -#: libpq/pqcomm.c:748 libpq/pqcomm.c:757 libpq/pqcomm.c:789 libpq/pqcomm.c:799 -#: libpq/pqcomm.c:1624 libpq/pqcomm.c:1669 libpq/pqcomm.c:1709 -#: libpq/pqcomm.c:1753 libpq/pqcomm.c:1792 libpq/pqcomm.c:1831 -#: libpq/pqcomm.c:1867 libpq/pqcomm.c:1906 -#, c-format -msgid "%s(%s) failed: %m" -msgstr "%s(%s) falló: %m" - -#: libpq/pqcomm.c:903 +#: libpq/pqcomm.c:885 #, c-format msgid "there is no client connection" msgstr "no hay conexión de cliente" -#: libpq/pqcomm.c:954 libpq/pqcomm.c:1050 +#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 #, c-format msgid "could not receive data from client: %m" msgstr "no se pudo recibir datos del cliente: %m" -#: libpq/pqcomm.c:1155 tcop/postgres.c:4403 +#: libpq/pqcomm.c:1149 tcop/postgres.c:4533 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "terminando la conexión por pérdida de sincronía del protocolo" -#: libpq/pqcomm.c:1221 +#: libpq/pqcomm.c:1215 #, c-format msgid "unexpected EOF within message length word" msgstr "EOF inesperado dentro de la palabra de tamaño del mensaje" -#: libpq/pqcomm.c:1231 +#: libpq/pqcomm.c:1225 #, c-format msgid "invalid message length" msgstr "el largo de mensaje no es válido" -#: libpq/pqcomm.c:1253 libpq/pqcomm.c:1266 +#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 #, c-format msgid "incomplete message from client" msgstr "mensaje incompleto del cliente" -#: libpq/pqcomm.c:1377 +#: libpq/pqcomm.c:1401 #, c-format msgid "could not send data to client: %m" msgstr "no se pudo enviar datos al cliente: %m" -#: libpq/pqcomm.c:1592 +#: libpq/pqcomm.c:1616 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) falló: código de error %d" -#: libpq/pqcomm.c:1681 +#: libpq/pqcomm.c:1705 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "establecer el tiempo de inactividad para keepalive no está soportado" -#: libpq/pqcomm.c:1765 libpq/pqcomm.c:1840 libpq/pqcomm.c:1915 +#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s) no está soportado" -#: libpq/pqformat.c:407 +#: libpq/pqformat.c:404 #, c-format msgid "no data left in message" msgstr "no hay datos restantes en el mensaje" -#: libpq/pqformat.c:518 libpq/pqformat.c:536 libpq/pqformat.c:557 -#: utils/adt/array_userfuncs.c:799 utils/adt/arrayfuncs.c:1506 -#: utils/adt/rowtypes.c:615 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 +#: utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 +#: utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "los datos restantes del mensaje son insuficientes" -#: libpq/pqformat.c:598 libpq/pqformat.c:627 +#: libpq/pqformat.c:595 libpq/pqformat.c:624 #, c-format msgid "invalid string in message" msgstr "cadena no válida en el mensaje" -#: libpq/pqformat.c:643 +#: libpq/pqformat.c:640 #, c-format msgid "invalid message format" msgstr "formato de mensaje no válido" -#: main/main.c:235 +#: main/main.c:236 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: WSAStartup falló: %d\n" -#: main/main.c:329 +#: main/main.c:324 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -15745,7 +16028,7 @@ msgstr "" "%s es el servidor PostgreSQL.\n" "\n" -#: main/main.c:330 +#: main/main.c:325 #, c-format msgid "" "Usage:\n" @@ -15756,110 +16039,109 @@ msgstr "" " %s [OPCION]...\n" "\n" -#: main/main.c:331 +#: main/main.c:326 #, c-format msgid "Options:\n" msgstr "Opciones:\n" -#: main/main.c:332 +#: main/main.c:327 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS número de búfers de memoria compartida\n" -#: main/main.c:333 +#: main/main.c:328 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c VAR=VALOR definir parámetro de ejecución\n" -#: main/main.c:334 +#: main/main.c:329 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C NOMBRE imprimir valor de parámetro de configuración, luego salir\n" -#: main/main.c:335 +#: main/main.c:330 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 nivel de depuración\n" -#: main/main.c:336 +#: main/main.c:331 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR directorio de bases de datos\n" -#: main/main.c:337 +#: main/main.c:332 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e usar estilo europeo de fechas (DMY)\n" -#: main/main.c:338 +#: main/main.c:333 #, c-format msgid " -F turn fsync off\n" msgstr " -F desactivar fsync\n" -#: main/main.c:339 +#: main/main.c:334 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h NOMBRE nombre de host o dirección IP en que escuchar\n" -#: main/main.c:340 -#, fuzzy, c-format -#| msgid " -l enable SSL connections\n" +#: main/main.c:335 +#, c-format msgid " -i enable TCP/IP connections (deprecated)\n" -msgstr " -l activar conexiones SSL\n" +msgstr " -i activar conexiones TCP/IP (obsoleto)\n" -#: main/main.c:341 +#: main/main.c:336 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k DIRECTORIO ubicación del socket Unix\n" -#: main/main.c:343 +#: main/main.c:338 #, c-format msgid " -l enable SSL connections\n" msgstr " -l activar conexiones SSL\n" -#: main/main.c:345 +#: main/main.c:340 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N MAX-CONN número máximo de conexiones permitidas\n" -#: main/main.c:346 +#: main/main.c:341 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p PUERTO número de puerto en el cual escuchar\n" -#: main/main.c:347 +#: main/main.c:342 #, c-format msgid " -s show statistics after each query\n" msgstr " -s mostrar estadísticas después de cada consulta\n" -#: main/main.c:348 +#: main/main.c:343 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S WORK-MEM definir cantidad de memoria para ordenamientos (en kB)\n" -#: main/main.c:349 +#: main/main.c:344 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de la versión, luego salir\n" -#: main/main.c:350 +#: main/main.c:345 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --NOMBRE=VALOR definir parámetro de ejecución\n" -#: main/main.c:351 +#: main/main.c:346 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr "" " --describe-config\n" " mostrar parámetros de configuración y salir\n" -#: main/main.c:352 +#: main/main.c:347 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help muestra esta ayuda, luego sale\n" -#: main/main.c:354 +#: main/main.c:349 #, c-format msgid "" "\n" @@ -15868,38 +16150,37 @@ msgstr "" "\n" "Opciones de desarrollador:\n" -#: main/main.c:355 +#: main/main.c:350 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" -msgstr "" +msgstr " -f s|i|o|b|t|n|m|h impedir el uso de algunos tipos de planes\n" -#: main/main.c:356 +#: main/main.c:351 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O permitir cambios en estructura de tablas de sistema\n" -#: main/main.c:357 +#: main/main.c:352 #, c-format msgid " -P disable system indexes\n" msgstr " -P desactivar índices de sistema\n" -#: main/main.c:358 +#: main/main.c:353 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex mostrar tiempos después de cada consulta\n" -#: main/main.c:359 -#, fuzzy, c-format -#| msgid " -P disable system indexes\n" +#: main/main.c:354 +#, c-format msgid " -T send SIGABRT to all backend processes if one dies\n" -msgstr " -P desactivar índices de sistema\n" +msgstr " -T enviar SIGABRT a todos los procesos backend si uno muere\n" -#: main/main.c:360 +#: main/main.c:355 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr " -W NÚM espera NÚM segundos para permitir acoplar un depurador\n" -#: main/main.c:362 +#: main/main.c:357 #, c-format msgid "" "\n" @@ -15908,37 +16189,37 @@ msgstr "" "\n" "Opciones para modo mono-usuario:\n" -#: main/main.c:363 +#: main/main.c:358 #, c-format msgid " --single selects single-user mode (must be first argument)\n" msgstr " --single selecciona modo mono-usuario (debe ser el primer argumento)\n" -#: main/main.c:364 +#: main/main.c:359 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAME nombre de base de datos (el valor por omisión es el nombre de usuario)\n" -#: main/main.c:365 +#: main/main.c:360 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 nivel de depuración\n" -#: main/main.c:366 +#: main/main.c:361 #, c-format msgid " -E echo statement before execution\n" msgstr " -E mostrar las consultas antes de su ejecución\n" -#: main/main.c:367 +#: main/main.c:362 #, c-format msgid " -j do not use newline as interactive query delimiter\n" msgstr " -j no usar saltos de línea como delimitadores de consulta\n" -#: main/main.c:368 main/main.c:374 +#: main/main.c:363 main/main.c:369 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r ARCHIVO enviar salida estándar y de error a ARCHIVO\n" -#: main/main.c:370 +#: main/main.c:365 #, c-format msgid "" "\n" @@ -15947,23 +16228,22 @@ msgstr "" "\n" "Opciones para modo de inicio (bootstrapping):\n" -#: main/main.c:371 +#: main/main.c:366 #, c-format msgid " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot selecciona modo de inicio (debe ser el primer argumento)\n" -#: main/main.c:372 -#, fuzzy, c-format -#| msgid " --single selects single-user mode (must be first argument)\n" +#: main/main.c:367 +#, c-format msgid " --check selects check mode (must be first argument)\n" -msgstr " --single selecciona modo mono-usuario (debe ser el primer argumento)\n" +msgstr " --check selecciona modo de verificación (debe ser el primer argumento)\n" -#: main/main.c:373 +#: main/main.c:368 #, c-format msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n" msgstr " DBNAME nombre de base de datos (argumento obligatorio en modo de inicio)\n" -#: main/main.c:376 +#: main/main.c:371 #, c-format msgid "" "\n" @@ -15980,12 +16260,12 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: main/main.c:380 +#: main/main.c:375 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: main/main.c:391 +#: main/main.c:386 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -15999,12 +16279,12 @@ msgstr "" "Vea la documentación para obtener más información acerca de cómo\n" "iniciar correctamente el servidor.\n" -#: main/main.c:408 +#: main/main.c:403 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: los IDs de usuario real y efectivo deben coincidir\n" -#: main/main.c:415 +#: main/main.c:410 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -16029,21 +16309,15 @@ msgstr "el tipo de nodo extensible «%s» ya existe" msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "ExtensibleNodeMethods «%s» no fue registrado" -#: nodes/makefuncs.c:153 statistics/extended_stats.c:2335 +#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "la relación «%s» no tiene un tipo compuesto" -#: nodes/makefuncs.c:878 -#, fuzzy, c-format -#| msgid "unrecognized encoding: \"%s\"" -msgid "unrecognized JSON encoding: %s" -msgstr "no se reconoce la codificación: «%s»" - -#: nodes/nodeFuncs.c:116 nodes/nodeFuncs.c:147 parser/parse_coerce.c:2567 -#: parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 -#: parser/parse_expr.c:2049 parser/parse_func.c:710 parser/parse_oper.c:883 -#: utils/fmgr/funcapi.c:661 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2604 +#: parser/parse_coerce.c:2742 parser/parse_coerce.c:2789 +#: parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 +#: utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "no se pudo encontrar un tipo de array para el tipo de dato %s" @@ -16058,938 +16332,936 @@ msgstr "portal «%s» con parámetros: %s" msgid "unnamed portal with parameters: %s" msgstr "portal sin nombre con parámetros: %s" -#: optimizer/path/joinrels.c:973 +#: optimizer/path/joinrels.c:972 #, c-format msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions" msgstr "FULL JOIN sólo está soportado con condiciones que se pueden usar con merge join o hash join" -#: optimizer/plan/createplan.c:7111 parser/parse_merge.c:182 -#: parser/parse_merge.c:189 -#, fuzzy, c-format -#| msgid "cannot change relation \"%s\"" +#: optimizer/plan/createplan.c:7175 parser/parse_merge.c:203 +#: rewrite/rewriteHandler.c:1680 +#, c-format msgid "cannot execute MERGE on relation \"%s\"" -msgstr "no se puede cambiar la relación «%s»" +msgstr "no se puede ejecutar MERGE en la relación «%s»" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1392 +#: optimizer/plan/initsplan.c:1407 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "%s no puede ser aplicado al lado nulable de un outer join" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1359 parser/analyze.c:1723 parser/analyze.c:1980 -#: parser/analyze.c:3193 +#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 +#: parser/analyze.c:3247 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s no está permitido con UNION/INTERSECT/EXCEPT" -#: optimizer/plan/planner.c:2080 optimizer/plan/planner.c:4038 +#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4108 #, c-format msgid "could not implement GROUP BY" msgstr "no se pudo implementar GROUP BY" -#: optimizer/plan/planner.c:2081 optimizer/plan/planner.c:4039 -#: optimizer/plan/planner.c:4679 optimizer/prep/prepunion.c:1053 +#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4109 +#: optimizer/plan/planner.c:4790 optimizer/prep/prepunion.c:1320 #, c-format msgid "Some of the datatypes only support hashing, while others only support sorting." msgstr "Algunos de los tipos sólo soportan hashing, mientras que otros sólo soportan ordenamiento." -#: optimizer/plan/planner.c:4678 +#: optimizer/plan/planner.c:4789 #, c-format msgid "could not implement DISTINCT" msgstr "no se pudo implementar DISTINCT" -#: optimizer/plan/planner.c:6017 +#: optimizer/plan/planner.c:6134 #, c-format msgid "could not implement window PARTITION BY" msgstr "No se pudo implementar PARTITION BY de ventana" -#: optimizer/plan/planner.c:6018 +#: optimizer/plan/planner.c:6135 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "Las columnas de particionamiento de ventana deben de tipos que se puedan ordenar." -#: optimizer/plan/planner.c:6022 +#: optimizer/plan/planner.c:6139 #, c-format msgid "could not implement window ORDER BY" msgstr "no se pudo implementar ORDER BY de ventana" -#: optimizer/plan/planner.c:6023 +#: optimizer/plan/planner.c:6140 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "Las columnas de ordenamiento de ventana debe ser de tipos que se puedan ordenar." -#: optimizer/prep/prepunion.c:516 +#: optimizer/prep/prepunion.c:467 #, c-format msgid "could not implement recursive UNION" msgstr "no se pudo implementar UNION recursivo" -#: optimizer/prep/prepunion.c:517 +#: optimizer/prep/prepunion.c:468 #, c-format msgid "All column datatypes must be hashable." msgstr "Todos los tipos de dato de las columnas deben ser tipos de los que se puedan hacer un hash." #. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1052 +#: optimizer/prep/prepunion.c:1319 #, c-format msgid "could not implement %s" msgstr "no se pudo implementar %s" -#: optimizer/util/clauses.c:4869 +#: optimizer/util/clauses.c:4963 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "función SQL «%s», durante expansión en línea" -#: optimizer/util/plancat.c:154 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "no se puede acceder a tablas temporales o «unlogged» durante la recuperación" -#: optimizer/util/plancat.c:726 +#: optimizer/util/plancat.c:768 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "no están soportadas las especificaciones de inferencia de índice único de registro completo" -#: optimizer/util/plancat.c:743 +#: optimizer/util/plancat.c:785 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "la restricción en la cláusula ON CONFLICT no tiene un índice asociado" -#: optimizer/util/plancat.c:793 +#: optimizer/util/plancat.c:835 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATE no está soportado con restricciones de exclusión" -#: optimizer/util/plancat.c:898 +#: optimizer/util/plancat.c:945 #, c-format msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification" msgstr "no hay restricción única o de exclusión que coincida con la especificación ON CONFLICT" -#: parser/analyze.c:788 parser/analyze.c:1502 +#: parser/analyze.c:824 parser/analyze.c:1550 #, c-format msgid "VALUES lists must all be the same length" msgstr "las listas VALUES deben ser todas de la misma longitud" -#: parser/analyze.c:990 +#: parser/analyze.c:1027 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT tiene más expresiones que columnas de destino" -#: parser/analyze.c:1008 +#: parser/analyze.c:1045 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERT tiene más columnas de destino que expresiones" -#: parser/analyze.c:1012 +#: parser/analyze.c:1049 #, c-format msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?" msgstr "La fuente de inserción es una expresión de fila que contiene la misma cantidad de columnas que esperaba el INSERT. ¿Usó accidentalmente paréntesis extra?" -#: parser/analyze.c:1309 parser/analyze.c:1696 +#: parser/analyze.c:1357 parser/analyze.c:1744 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO no está permitido aquí" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1625 parser/analyze.c:3425 +#: parser/analyze.c:1673 parser/analyze.c:3479 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s no puede ser aplicado a VALUES" -#: parser/analyze.c:1862 +#: parser/analyze.c:1911 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "cláusula UNION/INTERSECT/EXCEPT ORDER BY no válida" -#: parser/analyze.c:1863 +#: parser/analyze.c:1912 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "Sólo nombres de columna del resultado pueden usarse, no expresiones o funciones." -#: parser/analyze.c:1864 +#: parser/analyze.c:1913 #, c-format msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause." msgstr "Agregue la función o expresión a todos los SELECT, o mueva el UNION dentro de una cláusula FROM." -#: parser/analyze.c:1970 +#: parser/analyze.c:2019 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "sólo se permite INTO en el primer SELECT de UNION/INTERSECT/EXCEPT" -#: parser/analyze.c:2042 +#: parser/analyze.c:2091 #, c-format msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level" msgstr "una sentencia miembro de UNION/INSERT/EXCEPT no puede referirse a otras relaciones del mismo nivel de la consulta" -#: parser/analyze.c:2129 +#: parser/analyze.c:2178 #, c-format msgid "each %s query must have the same number of columns" msgstr "cada consulta %s debe tener el mismo número de columnas" #: parser/analyze.c:2535 #, c-format +msgid "SET target columns cannot be qualified with the relation name." +msgstr "Las columnas de destino SET no pueden ser calificadas con el nombre de relación." + +#: parser/analyze.c:2589 +#, c-format msgid "RETURNING must have at least one column" msgstr "RETURNING debe tener al menos una columna" -#: parser/analyze.c:2638 +#: parser/analyze.c:2692 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" msgstr[0] "fuente de asignación retornó %d columna" msgstr[1] "fuente de asignación retornó %d columnas" -#: parser/analyze.c:2699 +#: parser/analyze.c:2753 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "la variable «%s» es de tipo %s pero la expresión es de tipo %s" #. translator: %s is a SQL keyword -#: parser/analyze.c:2824 parser/analyze.c:2832 +#: parser/analyze.c:2878 parser/analyze.c:2886 #, c-format msgid "cannot specify both %s and %s" msgstr "no se puede especificar %s junto con %s" -#: parser/analyze.c:2852 +#: parser/analyze.c:2906 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR no debe contener sentencias que modifiquen datos en WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2860 +#: parser/analyze.c:2914 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s no está soportado" -#: parser/analyze.c:2863 +#: parser/analyze.c:2917 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "Los cursores declarados HOLD deben ser READ ONLY." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2871 +#: parser/analyze.c:2925 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s no está soportado" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2882 +#: parser/analyze.c:2936 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s no es válido" -#: parser/analyze.c:2885 +#: parser/analyze.c:2939 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "Los cursores insensitivos deben ser READ ONLY." -#: parser/analyze.c:2979 +#: parser/analyze.c:3033 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "las vistas materializadas no deben usar sentencias que modifiquen datos en WITH" -#: parser/analyze.c:2989 +#: parser/analyze.c:3043 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "las vistas materializadas no deben usar tablas temporales o vistas" -#: parser/analyze.c:2999 +#: parser/analyze.c:3053 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "las vistas materializadas no pueden definirse usando parámetros enlazados" -#: parser/analyze.c:3011 +#: parser/analyze.c:3065 #, c-format msgid "materialized views cannot be unlogged" msgstr "las vistas materializadas no pueden ser «unlogged»" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3200 +#: parser/analyze.c:3254 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s no está permitido con cláusulas DISTINCT" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3207 +#: parser/analyze.c:3261 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s no está permitido con cláusulas GROUP BY" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3214 +#: parser/analyze.c:3268 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s no está permitido con cláusulas HAVING" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3221 +#: parser/analyze.c:3275 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s no está permitido con funciones de agregación" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3228 +#: parser/analyze.c:3282 #, c-format msgid "%s is not allowed with window functions" msgstr "%s no está permitido con funciones de ventana deslizante" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3235 +#: parser/analyze.c:3289 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "%s no está permitido con funciones que retornan conjuntos en la lista de resultados" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3334 +#: parser/analyze.c:3388 #, c-format msgid "%s must specify unqualified relation names" msgstr "%s debe especificar nombres de relaciones sin calificar" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3398 +#: parser/analyze.c:3452 #, c-format msgid "%s cannot be applied to a join" msgstr "%s no puede ser aplicado a un join" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3407 +#: parser/analyze.c:3461 #, c-format msgid "%s cannot be applied to a function" msgstr "%s no puede ser aplicado a una función" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3416 +#: parser/analyze.c:3470 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s no puede ser aplicado a una función de tabla" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3434 +#: parser/analyze.c:3488 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s no puede ser aplicado a una consulta WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3443 +#: parser/analyze.c:3497 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%s no puede ser aplicado a un «tuplestore» con nombre" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3463 +#: parser/analyze.c:3517 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "la relación «%s» en la cláusula %s no fue encontrada en la cláusula FROM" -#: parser/parse_agg.c:221 parser/parse_oper.c:227 +#: parser/parse_agg.c:210 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "no se pudo identificar un operador de ordenamiento para el tipo %s" -#: parser/parse_agg.c:223 +#: parser/parse_agg.c:212 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "Las funciones de agregación con DISTINCT deben ser capaces de ordenar sus valores de entrada." -#: parser/parse_agg.c:258 +#: parser/parse_agg.c:270 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPING debe tener menos de 32 argumentos" -#: parser/parse_agg.c:361 +#: parser/parse_agg.c:373 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "no se permiten funciones de agregación en las condiciones de JOIN" -#: parser/parse_agg.c:363 +#: parser/parse_agg.c:375 msgid "grouping operations are not allowed in JOIN conditions" msgstr "no se permiten las operaciones «grouping» en condiciones JOIN" -#: parser/parse_agg.c:375 +#: parser/parse_agg.c:385 msgid "aggregate functions are not allowed in FROM clause of their own query level" msgstr "las funciones de agregación no están permitidas en la cláusula FROM de su mismo nivel de consulta" -#: parser/parse_agg.c:377 +#: parser/parse_agg.c:387 msgid "grouping operations are not allowed in FROM clause of their own query level" msgstr "las operaciones «grouping» no están permitidas en la cláusula FROM de su mismo nivel de consulta" -#: parser/parse_agg.c:382 +#: parser/parse_agg.c:392 msgid "aggregate functions are not allowed in functions in FROM" msgstr "no se permiten funciones de agregación en una función en FROM" -#: parser/parse_agg.c:384 +#: parser/parse_agg.c:394 msgid "grouping operations are not allowed in functions in FROM" msgstr "no se permiten operaciones «grouping» en funciones en FROM" -#: parser/parse_agg.c:392 +#: parser/parse_agg.c:402 msgid "aggregate functions are not allowed in policy expressions" msgstr "no se permiten funciones de agregación en expresiones de políticas" -#: parser/parse_agg.c:394 +#: parser/parse_agg.c:404 msgid "grouping operations are not allowed in policy expressions" msgstr "no se permiten operaciones «grouping» en expresiones de políticas" -#: parser/parse_agg.c:411 +#: parser/parse_agg.c:421 msgid "aggregate functions are not allowed in window RANGE" msgstr "no se permiten funciones de agregación en RANGE de ventana deslizante" -#: parser/parse_agg.c:413 +#: parser/parse_agg.c:423 msgid "grouping operations are not allowed in window RANGE" msgstr "no se permiten operaciones «grouping» en RANGE de ventana deslizante" -#: parser/parse_agg.c:418 +#: parser/parse_agg.c:428 msgid "aggregate functions are not allowed in window ROWS" msgstr "no se permiten funciones de agregación en ROWS de ventana deslizante" -#: parser/parse_agg.c:420 +#: parser/parse_agg.c:430 msgid "grouping operations are not allowed in window ROWS" msgstr "no se permiten operaciones «grouping» en ROWS de ventana deslizante" -#: parser/parse_agg.c:425 +#: parser/parse_agg.c:435 msgid "aggregate functions are not allowed in window GROUPS" msgstr "no se permiten funciones de agregación en GROUPS de ventana deslizante" -#: parser/parse_agg.c:427 +#: parser/parse_agg.c:437 msgid "grouping operations are not allowed in window GROUPS" msgstr "no se permiten operaciones «grouping» en GROUPS de ventana deslizante" -#: parser/parse_agg.c:440 -#, fuzzy -#| msgid "aggregate functions are not allowed in trigger WHEN conditions" +#: parser/parse_agg.c:450 msgid "aggregate functions are not allowed in MERGE WHEN conditions" -msgstr "no se permiten funciones de agregación en condición WHEN de un disparador" +msgstr "no se permiten funciones de agregación en condiciones MERGE WHEN" -#: parser/parse_agg.c:442 -#, fuzzy -#| msgid "grouping operations are not allowed in trigger WHEN conditions" +#: parser/parse_agg.c:452 msgid "grouping operations are not allowed in MERGE WHEN conditions" -msgstr "no se permiten operaciones «grouping» en condiciones WHEN de un disparador" +msgstr "no se permiten operaciones «grouping» en condiciones MERGE WHEN" -#: parser/parse_agg.c:468 +#: parser/parse_agg.c:479 msgid "aggregate functions are not allowed in check constraints" msgstr "no se permiten funciones de agregación en restricciones «check»" -#: parser/parse_agg.c:470 +#: parser/parse_agg.c:481 msgid "grouping operations are not allowed in check constraints" msgstr "no se permiten operaciones «grouping» en restricciones «check»" -#: parser/parse_agg.c:477 +#: parser/parse_agg.c:488 msgid "aggregate functions are not allowed in DEFAULT expressions" msgstr "no se permiten funciones de agregación en expresiones DEFAULT" -#: parser/parse_agg.c:479 +#: parser/parse_agg.c:490 msgid "grouping operations are not allowed in DEFAULT expressions" msgstr "no se permiten operaciones «grouping» en expresiones DEFAULT" -#: parser/parse_agg.c:484 +#: parser/parse_agg.c:495 msgid "aggregate functions are not allowed in index expressions" msgstr "no se permiten funciones de agregación en una expresión de índice" -#: parser/parse_agg.c:486 +#: parser/parse_agg.c:497 msgid "grouping operations are not allowed in index expressions" msgstr "no se permiten operaciones «grouping» en expresiones de índice" -#: parser/parse_agg.c:491 +#: parser/parse_agg.c:502 msgid "aggregate functions are not allowed in index predicates" msgstr "no se permiten funciones de agregación en predicados de índice" -#: parser/parse_agg.c:493 +#: parser/parse_agg.c:504 msgid "grouping operations are not allowed in index predicates" msgstr "no se permiten operaciones «grouping» en predicados de índice" -#: parser/parse_agg.c:498 +#: parser/parse_agg.c:509 msgid "aggregate functions are not allowed in statistics expressions" msgstr "no se permiten funciones de agregación en expresiones de estadísticas" -#: parser/parse_agg.c:500 +#: parser/parse_agg.c:511 msgid "grouping operations are not allowed in statistics expressions" msgstr "no se permiten operaciones «grouping» en expresiones de estadísticas" -#: parser/parse_agg.c:505 +#: parser/parse_agg.c:516 msgid "aggregate functions are not allowed in transform expressions" msgstr "no se permiten funciones de agregación en una expresión de transformación" -#: parser/parse_agg.c:507 +#: parser/parse_agg.c:518 msgid "grouping operations are not allowed in transform expressions" msgstr "no se permiten operaciones «grouping» en expresiones de transformación" -#: parser/parse_agg.c:512 +#: parser/parse_agg.c:523 msgid "aggregate functions are not allowed in EXECUTE parameters" msgstr "no se permiten funciones de agregación en un parámetro a EXECUTE" -#: parser/parse_agg.c:514 +#: parser/parse_agg.c:525 msgid "grouping operations are not allowed in EXECUTE parameters" msgstr "no se permiten operaciones «grouping» en parámetros a EXECUTE" -#: parser/parse_agg.c:519 +#: parser/parse_agg.c:530 msgid "aggregate functions are not allowed in trigger WHEN conditions" -msgstr "no se permiten funciones de agregación en condición WHEN de un disparador" +msgstr "no se permiten funciones de agregación en condición WHEN de un “trigger”" -#: parser/parse_agg.c:521 +#: parser/parse_agg.c:532 msgid "grouping operations are not allowed in trigger WHEN conditions" -msgstr "no se permiten operaciones «grouping» en condiciones WHEN de un disparador" +msgstr "no se permiten operaciones «grouping» en condiciones WHEN de un “trigger”" -#: parser/parse_agg.c:526 +#: parser/parse_agg.c:537 msgid "aggregate functions are not allowed in partition bound" msgstr "no se permiten funciones de agregación en borde de partición" -#: parser/parse_agg.c:528 +#: parser/parse_agg.c:539 msgid "grouping operations are not allowed in partition bound" msgstr "no se permiten operaciones «grouping» en borde de partición" -#: parser/parse_agg.c:533 +#: parser/parse_agg.c:544 msgid "aggregate functions are not allowed in partition key expressions" msgstr "no se permiten funciones de agregación en una expresión de llave de particionamiento" -#: parser/parse_agg.c:535 +#: parser/parse_agg.c:546 msgid "grouping operations are not allowed in partition key expressions" msgstr "no se permiten operaciones «grouping» en expresiones de llave de particionamiento" -#: parser/parse_agg.c:541 +#: parser/parse_agg.c:552 msgid "aggregate functions are not allowed in column generation expressions" msgstr "no se permiten funciones de agregación en expresiones de generación de columna" -#: parser/parse_agg.c:543 +#: parser/parse_agg.c:554 msgid "grouping operations are not allowed in column generation expressions" msgstr "no se permiten operaciones «grouping» en expresiones de generación de columna" -#: parser/parse_agg.c:549 +#: parser/parse_agg.c:560 msgid "aggregate functions are not allowed in CALL arguments" msgstr "no se permiten funciones de agregación en argumentos de CALL" -#: parser/parse_agg.c:551 +#: parser/parse_agg.c:562 msgid "grouping operations are not allowed in CALL arguments" msgstr "no se permiten operaciones «grouping» en argumentos de CALL" -#: parser/parse_agg.c:557 +#: parser/parse_agg.c:568 msgid "aggregate functions are not allowed in COPY FROM WHERE conditions" msgstr "no se permiten funciones de agregación en las condiciones WHERE de COPY FROM" -#: parser/parse_agg.c:559 +#: parser/parse_agg.c:570 msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "no se permiten las operaciones «grouping» en condiciones WHERE de COPY FROM" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:586 parser/parse_clause.c:1955 +#: parser/parse_agg.c:597 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "no se permiten funciones de agregación en %s" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:589 +#: parser/parse_agg.c:600 #, c-format msgid "grouping operations are not allowed in %s" msgstr "no se permiten operaciones «grouping» en %s" -#: parser/parse_agg.c:690 +#: parser/parse_agg.c:701 #, c-format msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments" msgstr "una función de agregación de nivel exterior no puede contener una variable de nivel inferior en sus argumentos directos" -#: parser/parse_agg.c:768 +#: parser/parse_agg.c:779 #, c-format msgid "aggregate function calls cannot contain set-returning function calls" msgstr "las llamadas a funciones de agregación no pueden contener llamadas a funciones que retornan conjuntos" -#: parser/parse_agg.c:769 parser/parse_expr.c:1700 parser/parse_expr.c:2182 -#: parser/parse_func.c:884 +#: parser/parse_agg.c:780 parser/parse_expr.c:1762 parser/parse_expr.c:2245 +#: parser/parse_func.c:885 #, c-format msgid "You might be able to move the set-returning function into a LATERAL FROM item." msgstr "Puede intentar mover la función que retorna conjuntos a un elemento LATERAL FROM." -#: parser/parse_agg.c:774 +#: parser/parse_agg.c:785 #, c-format msgid "aggregate function calls cannot contain window function calls" msgstr "las llamadas a funciones de agregación no pueden contener llamadas a funciones de ventana deslizante" -#: parser/parse_agg.c:853 +#: parser/parse_agg.c:864 msgid "window functions are not allowed in JOIN conditions" msgstr "no se permiten funciones de ventana deslizante en condiciones JOIN" -#: parser/parse_agg.c:860 +#: parser/parse_agg.c:871 msgid "window functions are not allowed in functions in FROM" msgstr "no se permiten funciones de ventana deslizante en funciones en FROM" -#: parser/parse_agg.c:866 +#: parser/parse_agg.c:877 msgid "window functions are not allowed in policy expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de políticas" -#: parser/parse_agg.c:879 +#: parser/parse_agg.c:890 msgid "window functions are not allowed in window definitions" msgstr "no se permiten funciones de ventana deslizante en definiciones de ventana deslizante" -#: parser/parse_agg.c:890 -#, fuzzy -#| msgid "window functions are not allowed in trigger WHEN conditions" +#: parser/parse_agg.c:901 msgid "window functions are not allowed in MERGE WHEN conditions" -msgstr "no se permiten funciones de ventana deslizante en condiciones WHEN de un disparador" +msgstr "no se permiten funciones de ventana deslizante en condiciones MERGE WHEN" -#: parser/parse_agg.c:914 +#: parser/parse_agg.c:926 msgid "window functions are not allowed in check constraints" msgstr "no se permiten funciones de ventana deslizante en restricciones «check»" -#: parser/parse_agg.c:918 +#: parser/parse_agg.c:930 msgid "window functions are not allowed in DEFAULT expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones DEFAULT" -#: parser/parse_agg.c:921 +#: parser/parse_agg.c:933 msgid "window functions are not allowed in index expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de índice" -#: parser/parse_agg.c:924 +#: parser/parse_agg.c:936 msgid "window functions are not allowed in statistics expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de estadísticas" -#: parser/parse_agg.c:927 +#: parser/parse_agg.c:939 msgid "window functions are not allowed in index predicates" msgstr "no se permiten funciones de ventana deslizante en predicados de índice" -#: parser/parse_agg.c:930 +#: parser/parse_agg.c:942 msgid "window functions are not allowed in transform expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de transformación" -#: parser/parse_agg.c:933 +#: parser/parse_agg.c:945 msgid "window functions are not allowed in EXECUTE parameters" msgstr "no se permiten funciones de ventana deslizante en parámetros a EXECUTE" -#: parser/parse_agg.c:936 +#: parser/parse_agg.c:948 msgid "window functions are not allowed in trigger WHEN conditions" -msgstr "no se permiten funciones de ventana deslizante en condiciones WHEN de un disparador" +msgstr "no se permiten funciones de ventana deslizante en condiciones WHEN de un “trigger”" -#: parser/parse_agg.c:939 +#: parser/parse_agg.c:951 msgid "window functions are not allowed in partition bound" msgstr "no se permiten funciones de ventana deslizante en borde de partición" -#: parser/parse_agg.c:942 +#: parser/parse_agg.c:954 msgid "window functions are not allowed in partition key expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de llave de particionamiento" -#: parser/parse_agg.c:945 +#: parser/parse_agg.c:957 msgid "window functions are not allowed in CALL arguments" msgstr "no se permiten funciones de ventana deslizante en argumentos de CALL" -#: parser/parse_agg.c:948 +#: parser/parse_agg.c:960 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "no se permiten funciones de ventana deslizante en las condiciones WHERE de COPY FROM" -#: parser/parse_agg.c:951 +#: parser/parse_agg.c:963 msgid "window functions are not allowed in column generation expressions" msgstr "no se permiten funciones de ventana deslizante en expresiones de generación de columna" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:974 parser/parse_clause.c:1964 +#: parser/parse_agg.c:986 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "no se permiten funciones de ventana deslizante en %s" -#: parser/parse_agg.c:1008 parser/parse_clause.c:2797 +#: parser/parse_agg.c:1020 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "la ventana «%s» no existe" -#: parser/parse_agg.c:1096 +#: parser/parse_agg.c:1108 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "demasiados conjuntos «grouping» presentes (máximo 4096)" -#: parser/parse_agg.c:1236 +#: parser/parse_agg.c:1248 #, c-format msgid "aggregate functions are not allowed in a recursive query's recursive term" msgstr "no se permiten funciones de agregación en el término recursivo de una consulta recursiva" -#: parser/parse_agg.c:1429 +#: parser/parse_agg.c:1441 #, c-format msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function" msgstr "la columna «%s.%s» debe aparecer en la cláusula GROUP BY o ser usada en una función de agregación" -#: parser/parse_agg.c:1432 +#: parser/parse_agg.c:1444 #, c-format msgid "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "Argumentos directos de una función de agregación de conjuntos ordenados debe usar sólo columnas agrupadas." -#: parser/parse_agg.c:1437 +#: parser/parse_agg.c:1449 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "la subconsulta usa la columna «%s.%s» no agrupada de una consulta exterior" -#: parser/parse_agg.c:1601 +#: parser/parse_agg.c:1613 #, c-format msgid "arguments to GROUPING must be grouping expressions of the associated query level" msgstr "los argumentos de GROUPING deben ser expresiones agrupantes del nivel de consulta asociado" -#: parser/parse_clause.c:195 +#: parser/parse_clause.c:193 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "relación «%s» no puede ser destino de una sentencia modificadora" -#: parser/parse_clause.c:571 parser/parse_clause.c:599 parser/parse_func.c:2552 +#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "las funciones que retornan conjuntos deben aparecer en el nivel más externo del FROM" -#: parser/parse_clause.c:611 +#: parser/parse_clause.c:609 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "no se permiten múltiples definiciones de columnas para la misma función" -#: parser/parse_clause.c:644 +#: parser/parse_clause.c:642 #, c-format msgid "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "ROWS FROM() con varias funciones no puede tener una lista de definición de columnas" -#: parser/parse_clause.c:645 +#: parser/parse_clause.c:643 #, c-format msgid "Put a separate column definition list for each function inside ROWS FROM()." msgstr "Ponga una lista de columnas separada para cada función dentro de ROWS FROM()." -#: parser/parse_clause.c:651 +#: parser/parse_clause.c:649 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "UNNEST() con varios argumentos no puede tener una lista de definición de columnas" -#: parser/parse_clause.c:652 +#: parser/parse_clause.c:650 #, c-format msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one." msgstr "Use llamadas a UNNEST() separadas dentro de ROWS FROM() y adjunte una lista de columnas a cada una." -#: parser/parse_clause.c:659 +#: parser/parse_clause.c:657 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY no puede usarse con una lista de definición de columnas" -#: parser/parse_clause.c:660 +#: parser/parse_clause.c:658 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "Ponga una lista de columnas dentro de ROWS FROM()." -#: parser/parse_clause.c:760 +#: parser/parse_clause.c:762 parser/parse_jsontable.c:295 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "sólo se permite una columna FOR ORDINALITY" -#: parser/parse_clause.c:821 +#: parser/parse_clause.c:823 #, c-format msgid "column name \"%s\" is not unique" msgstr "el nombre de columna «%s» no es único" -#: parser/parse_clause.c:863 +#: parser/parse_clause.c:865 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "el espacio de nombres «%s» no es único" -#: parser/parse_clause.c:873 +#: parser/parse_clause.c:875 #, c-format msgid "only one default namespace is allowed" msgstr "sólo se permite un espacio de nombres predeterminado" -#: parser/parse_clause.c:933 +#: parser/parse_clause.c:935 #, c-format msgid "tablesample method %s does not exist" msgstr "no existe el método de tablesample «%s»" -#: parser/parse_clause.c:955 +#: parser/parse_clause.c:957 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" msgstr[0] "el método de tablesample «%s» requiere %d argumento, no %d" msgstr[1] "el método de tablesample «%s» requiere %d argumentos, no %d" -#: parser/parse_clause.c:989 +#: parser/parse_clause.c:991 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "el método de tablesample «%s» no soporta la opción REPEATABLE" -#: parser/parse_clause.c:1138 +#: parser/parse_clause.c:1144 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "la cláusula TABLESAMPLE sólo puede aplicarse a tablas y vistas materializadas" -#: parser/parse_clause.c:1325 +#: parser/parse_clause.c:1331 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "la columna «%s» aparece más de una vez en la cláusula USING" -#: parser/parse_clause.c:1340 +#: parser/parse_clause.c:1346 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "la columna común «%s» aparece más de una vez en la tabla izquierda" -#: parser/parse_clause.c:1349 +#: parser/parse_clause.c:1355 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "la columna «%s» especificada en la cláusula USING no existe en la tabla izquierda" -#: parser/parse_clause.c:1364 +#: parser/parse_clause.c:1370 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "la columna común «%s» aparece más de una vez en la tabla derecha" -#: parser/parse_clause.c:1373 +#: parser/parse_clause.c:1379 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "la columna «%s» especificada en la cláusula USING no existe en la tabla derecha" -#: parser/parse_clause.c:1900 +#: parser/parse_clause.c:1907 #, c-format msgid "row count cannot be null in FETCH FIRST ... WITH TIES clause" msgstr "la cantidad de registros no puede ser NULL en la cláusula FETCH FIRST ... WITH TIES" #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_clause.c:1925 +#: parser/parse_clause.c:1932 #, c-format msgid "argument of %s must not contain variables" msgstr "el argumento de %s no puede contener variables" #. translator: first %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2090 +#: parser/parse_clause.c:2097 #, c-format msgid "%s \"%s\" is ambiguous" msgstr "%s «%s» es ambiguo" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2118 +#: parser/parse_clause.c:2125 #, c-format msgid "non-integer constant in %s" msgstr "constante no entera en %s" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2140 +#: parser/parse_clause.c:2147 #, c-format msgid "%s position %d is not in select list" msgstr "la posición %2$d de %1$s no está en la lista de resultados" -#: parser/parse_clause.c:2579 +#: parser/parse_clause.c:2586 #, c-format msgid "CUBE is limited to 12 elements" msgstr "CUBE está limitado a 12 elementos" -#: parser/parse_clause.c:2785 +#: parser/parse_clause.c:2792 #, c-format msgid "window \"%s\" is already defined" msgstr "la ventana «%s» ya está definida" -#: parser/parse_clause.c:2846 +#: parser/parse_clause.c:2853 #, c-format msgid "cannot override PARTITION BY clause of window \"%s\"" msgstr "no se puede pasar a llevar la cláusula PARTITION BY de la ventana «%s»" -#: parser/parse_clause.c:2858 +#: parser/parse_clause.c:2865 #, c-format msgid "cannot override ORDER BY clause of window \"%s\"" msgstr "no se puede pasar a llevar la cláusula ORDER BY de la ventana «%s»" -#: parser/parse_clause.c:2888 parser/parse_clause.c:2894 +#: parser/parse_clause.c:2895 parser/parse_clause.c:2901 #, c-format msgid "cannot copy window \"%s\" because it has a frame clause" msgstr "no se puede copiar la ventana «%s» porque tiene una cláusula «frame»" -#: parser/parse_clause.c:2896 +#: parser/parse_clause.c:2903 #, c-format msgid "Omit the parentheses in this OVER clause." msgstr "Omita el uso de paréntesis en esta cláusula OVER." -#: parser/parse_clause.c:2916 +#: parser/parse_clause.c:2923 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column" msgstr "RANGE con desplazamiento PRECEDING/FOLLOWING requiere exactamente una columna ORDER BY" -#: parser/parse_clause.c:2939 +#: parser/parse_clause.c:2946 #, c-format msgid "GROUPS mode requires an ORDER BY clause" msgstr "el modo GROUPS requiere una cláusula ORDER BY" -#: parser/parse_clause.c:3010 +#: parser/parse_clause.c:3016 #, c-format msgid "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list" msgstr "en una agregación con DISTINCT, las expresiones en ORDER BY deben aparecer en la lista de argumentos" -#: parser/parse_clause.c:3011 +#: parser/parse_clause.c:3017 #, c-format msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list" msgstr "para SELECT DISTINCT, las expresiones en ORDER BY deben aparecer en la lista de resultados" -#: parser/parse_clause.c:3043 +#: parser/parse_clause.c:3049 #, c-format msgid "an aggregate with DISTINCT must have at least one argument" msgstr "una función de agregación con DISTINCT debe tener al menos un argumento" -#: parser/parse_clause.c:3044 +#: parser/parse_clause.c:3050 #, c-format msgid "SELECT DISTINCT must have at least one column" msgstr "SELECT DISTINCT debe tener al menos una columna" -#: parser/parse_clause.c:3110 parser/parse_clause.c:3142 +#: parser/parse_clause.c:3116 parser/parse_clause.c:3148 #, c-format msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions" msgstr "las expresiones de SELECT DISTINCT ON deben coincidir con las expresiones iniciales de ORDER BY" -#: parser/parse_clause.c:3220 +#: parser/parse_clause.c:3226 #, c-format msgid "ASC/DESC is not allowed in ON CONFLICT clause" msgstr "ASC/DESC no están permitidos en cláusulas ON CONFLICT" -#: parser/parse_clause.c:3226 +#: parser/parse_clause.c:3232 #, c-format msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause" msgstr "NULLS FIRST/LAST no están permitidos en cláusulas ON CONFLICT" -#: parser/parse_clause.c:3305 +#: parser/parse_clause.c:3311 #, c-format msgid "ON CONFLICT DO UPDATE requires inference specification or constraint name" msgstr "ON CONFLICT DO UPDATE requiere una especificación de inferencia o nombre de restricción" -#: parser/parse_clause.c:3306 +#: parser/parse_clause.c:3312 #, c-format msgid "For example, ON CONFLICT (column_name)." msgstr "Por ejemplo, ON CONFLICT (nombre_de_columna)." -#: parser/parse_clause.c:3317 +#: parser/parse_clause.c:3323 #, c-format msgid "ON CONFLICT is not supported with system catalog tables" msgstr "ON CONFLICT no está soportado con tablas que son catálogos de sistema" -#: parser/parse_clause.c:3325 +#: parser/parse_clause.c:3331 #, c-format msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table" msgstr "ON CONFLICT no está soportado en la tabla «%s» usada como catálogo de sistema" -#: parser/parse_clause.c:3456 +#: parser/parse_clause.c:3462 #, c-format msgid "operator %s is not a valid ordering operator" msgstr "el operador «%s» no es un operador válido de ordenamiento" -#: parser/parse_clause.c:3458 +#: parser/parse_clause.c:3464 #, c-format msgid "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "Los operadores de ordenamiento deben ser miembros «<» o «>» de una familia de operadores btree." -#: parser/parse_clause.c:3769 +#: parser/parse_clause.c:3775 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "RANGE con desplazamiento PRECEDING/FOLLOWING no está soportado para la columna de tipo %s" -#: parser/parse_clause.c:3775 +#: parser/parse_clause.c:3781 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s and offset type %s" msgstr "RANGE con desplazamiento PRECEDING/FOLLOWING no está soportado para la columna de tipo %s y tipo de desplazamiento %s" -#: parser/parse_clause.c:3778 +#: parser/parse_clause.c:3784 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "Convierta el valor de desplazamiento a un tipo apropiado." -#: parser/parse_clause.c:3783 +#: parser/parse_clause.c:3789 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for column type %s and offset type %s" msgstr "RANGE con desplazamiento PRECEDING/FOLLOWING tiene múltiples interpretaciones para la columna de tipo %s y tipo de desplazamiento %s" -#: parser/parse_clause.c:3786 +#: parser/parse_clause.c:3792 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "Convierta el valor de desplazamiento al tipo deseado exacto." #: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 #: parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 -#: parser/parse_expr.c:2083 parser/parse_expr.c:2691 parser/parse_expr.c:3516 -#: parser/parse_target.c:985 +#: parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3405 +#: parser/parse_expr.c:3634 parser/parse_target.c:998 #, c-format msgid "cannot cast type %s to %s" msgstr "no se puede convertir el tipo %s a %s" @@ -17024,121 +17296,121 @@ msgid "argument of %s must not return a set" msgstr "el argumento de %s no debe retornar un conjunto" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1383 +#: parser/parse_coerce.c:1420 #, c-format msgid "%s types %s and %s cannot be matched" msgstr "los tipos %2$s y %3$s no son coincidentes en %1$s" -#: parser/parse_coerce.c:1499 +#: parser/parse_coerce.c:1536 #, c-format msgid "argument types %s and %s cannot be matched" msgstr "los tipos de argumento %s y %s no pueden hacerse coincidir" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1551 +#: parser/parse_coerce.c:1588 #, c-format msgid "%s could not convert type %s to %s" msgstr "%s no pudo convertir el tipo %s a %s" -#: parser/parse_coerce.c:2154 parser/parse_coerce.c:2174 -#: parser/parse_coerce.c:2194 parser/parse_coerce.c:2215 -#: parser/parse_coerce.c:2270 parser/parse_coerce.c:2304 +#: parser/parse_coerce.c:2191 parser/parse_coerce.c:2211 +#: parser/parse_coerce.c:2231 parser/parse_coerce.c:2252 +#: parser/parse_coerce.c:2307 parser/parse_coerce.c:2341 #, c-format msgid "arguments declared \"%s\" are not all alike" msgstr "los argumentos declarados «%s» no son de tipos compatibles" -#: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 -#: utils/fmgr/funcapi.c:592 +#: parser/parse_coerce.c:2286 parser/parse_coerce.c:2399 +#: utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "el argumento declarado %s no es un array sino de tipo %s" -#: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 -#: utils/fmgr/funcapi.c:606 +#: parser/parse_coerce.c:2319 parser/parse_coerce.c:2469 +#: utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "el argumento declarado %s no es un tipo de rango sino tipo %s" -#: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 -#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:624 utils/fmgr/funcapi.c:689 +#: parser/parse_coerce.c:2353 parser/parse_coerce.c:2433 +#: parser/parse_coerce.c:2566 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "el argumento declarado %s no es un tipo de multirango sino tipo %s" -#: parser/parse_coerce.c:2353 +#: parser/parse_coerce.c:2390 #, c-format msgid "cannot determine element type of \"anyarray\" argument" msgstr "no se puede determinar el tipo del argumento «anyarray»" -#: parser/parse_coerce.c:2379 parser/parse_coerce.c:2410 -#: parser/parse_coerce.c:2449 parser/parse_coerce.c:2515 +#: parser/parse_coerce.c:2416 parser/parse_coerce.c:2447 +#: parser/parse_coerce.c:2486 parser/parse_coerce.c:2552 #, c-format msgid "argument declared %s is not consistent with argument declared %s" msgstr "el argumento declarado %s no es consistente con el argumento declarado %s" -#: parser/parse_coerce.c:2474 +#: parser/parse_coerce.c:2511 #, c-format msgid "could not determine polymorphic type because input has type %s" msgstr "no se pudo determinar el tipo polimórfico porque la entrada es de tipo %s" -#: parser/parse_coerce.c:2488 +#: parser/parse_coerce.c:2525 #, c-format msgid "type matched to anynonarray is an array type: %s" msgstr "el argumento emparejado con anynonarray es un array: %s" -#: parser/parse_coerce.c:2498 +#: parser/parse_coerce.c:2535 #, c-format msgid "type matched to anyenum is not an enum type: %s" msgstr "el tipo emparejado con anyenum no es un tipo enum: %s" -#: parser/parse_coerce.c:2559 +#: parser/parse_coerce.c:2596 #, c-format msgid "arguments of anycompatible family cannot be cast to a common type" msgstr "los argumentos de la familia anycompatible no pueden ser convertidos a un tipo común" -#: parser/parse_coerce.c:2577 parser/parse_coerce.c:2598 -#: parser/parse_coerce.c:2648 parser/parse_coerce.c:2653 -#: parser/parse_coerce.c:2717 parser/parse_coerce.c:2729 +#: parser/parse_coerce.c:2614 parser/parse_coerce.c:2635 +#: parser/parse_coerce.c:2685 parser/parse_coerce.c:2690 +#: parser/parse_coerce.c:2754 parser/parse_coerce.c:2766 #, c-format msgid "could not determine polymorphic type %s because input has type %s" msgstr "no se pudo determinar el tipo polimórfico %s porque la entrada es de tipo %s" -#: parser/parse_coerce.c:2587 +#: parser/parse_coerce.c:2624 #, c-format msgid "anycompatiblerange type %s does not match anycompatible type %s" msgstr "el tipo anycompatiblerange %s no coincide con el tipo anycompatible %s" -#: parser/parse_coerce.c:2608 +#: parser/parse_coerce.c:2645 #, c-format msgid "anycompatiblemultirange type %s does not match anycompatible type %s" msgstr "el tipo anycompatiblemultirange %s no coincide con el tipo anycompatible %s" -#: parser/parse_coerce.c:2622 +#: parser/parse_coerce.c:2659 #, c-format msgid "type matched to anycompatiblenonarray is an array type: %s" msgstr "el argumento emparejado a anycompatiblenonarray es un array: %s" -#: parser/parse_coerce.c:2857 +#: parser/parse_coerce.c:2894 #, c-format msgid "A result of type %s requires at least one input of type anyrange or anymultirange." msgstr "Un resultado de tipo %s requiere al menos una entrada de tipo anyrange o anymultirange." -#: parser/parse_coerce.c:2874 +#: parser/parse_coerce.c:2911 #, c-format msgid "A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange." msgstr "Un resultado de tipo %s requiere al menos una entrada de tipo anycompatiblerange o anycompatiblemultirange." -#: parser/parse_coerce.c:2886 +#: parser/parse_coerce.c:2923 #, c-format msgid "A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange." msgstr "Un resultado de tipo %s requiere al menos una entrada de tipo anyelement, anyarray, anynonarray, anyenum, anyrange o anymultirange." -#: parser/parse_coerce.c:2898 +#: parser/parse_coerce.c:2935 #, c-format msgid "A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange." msgstr "Un resultado de tipo %s requiere al menos una entrada de tipo anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange o anycompatiblemultirange." -#: parser/parse_coerce.c:2928 +#: parser/parse_coerce.c:2965 msgid "A result of type internal requires at least one input of type internal." msgstr "Un resultado de tipo internal requiere al menos una entrada de tipo internal." @@ -17184,442 +17456,553 @@ msgstr "la referencia recursiva a la consulta «%s» no debe aparecer dentro de msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "la referencia recursiva a la consulta «%s» no debe aparecer dentro de EXCEPT" -#: parser/parse_cte.c:133 -#, fuzzy, c-format -#| msgid "\"EEEE\" not supported for input" -msgid "MERGE not supported in WITH query" -msgstr "«EEEE» no está soportado en la entrada" - -#: parser/parse_cte.c:143 +#: parser/parse_cte.c:136 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "el nombre de consulta WITH «%s» fue especificado más de una vez" -#: parser/parse_cte.c:314 +#: parser/parse_cte.c:308 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "no se pudo identificar un operador de desigualdad para el tipo %s" -#: parser/parse_cte.c:341 +#: parser/parse_cte.c:335 #, c-format msgid "WITH clause containing a data-modifying statement must be at the top level" msgstr "la cláusula WITH que contiene las sentencias que modifican datos debe estar en el nivel más externo" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:384 #, c-format msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall" msgstr "la columna %2$d en la consulta recursiva «%1$s» tiene tipo %3$s en el término no recursivo, pero %4$s en general" -#: parser/parse_cte.c:396 +#: parser/parse_cte.c:390 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "Aplique una conversión de tipo a la salida del término no recursivo al tipo correcto." -#: parser/parse_cte.c:401 +#: parser/parse_cte.c:395 #, c-format msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall" msgstr "la columna %2$d en la consulta recursiva «%1$s» tiene ordenamiento (collation) %3$s en el término no recursivo, pero %4$s en general" -#: parser/parse_cte.c:405 +#: parser/parse_cte.c:399 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "Use la clásula COLLATE para definir el ordenamiento del término no-recursivo." -#: parser/parse_cte.c:426 +#: parser/parse_cte.c:420 #, c-format msgid "WITH query is not recursive" msgstr "la consulta WITH no es recursiva" -#: parser/parse_cte.c:457 +#: parser/parse_cte.c:451 #, c-format msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "con una cláusula SEARCH o CYCLE, el lado izquierdo de UNION debe ser un SELECT" -#: parser/parse_cte.c:462 +#: parser/parse_cte.c:456 #, c-format msgid "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "con una cláusula SEARCH o CYCLE, el lado derecho de UNION debe ser un SELECT" -#: parser/parse_cte.c:477 +#: parser/parse_cte.c:471 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "columna de búsqueda «%s» no se encuentra en la lista de columnas de la consulta WITH" -#: parser/parse_cte.c:484 +#: parser/parse_cte.c:478 #, c-format msgid "search column \"%s\" specified more than once" msgstr "columna de búsqueda «%s» fue especificada más de una vez" -#: parser/parse_cte.c:493 +#: parser/parse_cte.c:487 #, c-format msgid "search sequence column name \"%s\" already used in WITH query column list" msgstr "el nombre para la columna de secuencia de búsqueda «%s» ya ha sido utilizado en la lista de columnas de la consulta WITH" -#: parser/parse_cte.c:510 +#: parser/parse_cte.c:504 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "la columna de ciclo «%s» no se encuentra en la lista de columnas de la consulta WITH" -#: parser/parse_cte.c:517 +#: parser/parse_cte.c:511 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "columna de ciclo «%s» fue especificada más de una vez" -#: parser/parse_cte.c:526 +#: parser/parse_cte.c:520 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "el nombre para la columna de marca de ciclo «%s» ya ha sido utilizada en la lista de columnas de la consulta WITH" -#: parser/parse_cte.c:533 +#: parser/parse_cte.c:527 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "el nombre para la columna de ruta de ciclo «%s» ya ha sido utilizada en la lista de columnas de la consulta WITH" -#: parser/parse_cte.c:541 +#: parser/parse_cte.c:535 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "el nombre para la columna de marca de ciclo es igual que el nombre para la columna de ruta de ciclo" -#: parser/parse_cte.c:551 +#: parser/parse_cte.c:545 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "el nombre para la columna de secuencia de búsqueda es igual que el nombre para la columna de marca de ciclo" -#: parser/parse_cte.c:558 +#: parser/parse_cte.c:552 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "el nombre para la columna de secuencia de búsqueda es igual que el nombre para la columna de ruta de ciclo" -#: parser/parse_cte.c:642 +#: parser/parse_cte.c:636 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "la consulta WITH «%s» tiene %d columnas disponibles pero se especificaron %d" -#: parser/parse_cte.c:822 +#: parser/parse_cte.c:816 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "la recursión mutua entre elementos de WITH no está implementada" -#: parser/parse_cte.c:874 +#: parser/parse_cte.c:868 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "la consulta recursiva «%s» no debe contener sentencias que modifiquen datos" -#: parser/parse_cte.c:882 +#: parser/parse_cte.c:876 #, c-format msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term" msgstr "la consulta recursiva «%s» no tiene la forma término-no-recursivo UNION [ALL] término-recursivo" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:911 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "ORDER BY no está implementado en una consulta recursiva" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:917 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "OFFSET no está implementado en una consulta recursiva" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:923 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "LIMIT no está implementado en una consulta recursiva" -#: parser/parse_cte.c:944 +#: parser/parse_cte.c:929 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "FOR UPDATE/SHARE no está implementado en una consulta recursiva" -#: parser/parse_cte.c:1001 +#: parser/parse_cte.c:1008 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "la referencia recursiva a la consulta «%s» no debe aparecer más de una vez" -#: parser/parse_expr.c:294 +#: parser/parse_expr.c:313 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "DEFAULT no está permitido en este contexto" -#: parser/parse_expr.c:371 parser/parse_relation.c:3687 -#: parser/parse_relation.c:3697 parser/parse_relation.c:3715 -#: parser/parse_relation.c:3722 parser/parse_relation.c:3736 +#: parser/parse_expr.c:406 parser/parse_relation.c:3691 +#: parser/parse_relation.c:3701 parser/parse_relation.c:3719 +#: parser/parse_relation.c:3726 parser/parse_relation.c:3740 #, c-format msgid "column %s.%s does not exist" msgstr "no existe la columna %s.%s" -#: parser/parse_expr.c:383 +#: parser/parse_expr.c:418 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "la columna «%s» no fue encontrado en el tipo %s" -#: parser/parse_expr.c:389 +#: parser/parse_expr.c:424 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "no se pudo identificar la columna «%s» en el tipo de dato record" -#: parser/parse_expr.c:395 +#: parser/parse_expr.c:430 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "la notación de columna .%s fue aplicada al tipo %s, que no es un tipo compuesto" -#: parser/parse_expr.c:426 parser/parse_target.c:733 +#: parser/parse_expr.c:461 parser/parse_target.c:732 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "la expansión de filas a través de «*» no está soportado aquí" -#: parser/parse_expr.c:548 +#: parser/parse_expr.c:584 msgid "cannot use column reference in DEFAULT expression" msgstr "no se pueden usar referencias a columnas en una cláusula DEFAULT" -#: parser/parse_expr.c:551 +#: parser/parse_expr.c:587 msgid "cannot use column reference in partition bound expression" msgstr "no se pueden usar referencias a columnas en expresión de borde de partición" -#: parser/parse_expr.c:810 parser/parse_relation.c:833 -#: parser/parse_relation.c:915 parser/parse_target.c:1225 +#: parser/parse_expr.c:846 parser/parse_relation.c:833 +#: parser/parse_relation.c:915 parser/parse_target.c:1238 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "la referencia a la columna «%s» es ambigua" -#: parser/parse_expr.c:866 parser/parse_param.c:110 parser/parse_param.c:142 +#: parser/parse_expr.c:902 parser/parse_param.c:110 parser/parse_param.c:142 #: parser/parse_param.c:204 parser/parse_param.c:303 #, c-format msgid "there is no parameter $%d" msgstr "no hay parámetro $%d" -#: parser/parse_expr.c:1066 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1103 parser/parse_expr.c:3065 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "NULLIF requiere que el operador = retorne boolean" +msgid "%s requires = operator to yield boolean" +msgstr "%s requiere que el operador = retorne boolean" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1072 parser/parse_expr.c:3007 +#: parser/parse_expr.c:1109 parser/parse_expr.c:3072 #, c-format msgid "%s must not return a set" msgstr "%s no debe retornar un conjunto" -#: parser/parse_expr.c:1457 parser/parse_expr.c:1489 +#: parser/parse_expr.c:1395 +#, c-format +msgid "MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" +msgstr "MERGE_ACTION() sólo puede usarse en la lista RETURNING de una orden MERGE" + +#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 #, c-format msgid "number of columns does not match number of values" msgstr "el número de columnas no coincide con el número de valores" -#: parser/parse_expr.c:1503 +#: parser/parse_expr.c:1565 #, c-format msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" msgstr "el origen para un UPDATE de varias columnas debe ser una expresión sub-SELECT o ROW ()" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1698 parser/parse_expr.c:2180 parser/parse_func.c:2677 +#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "no se permiten funciones que retornan conjuntos en %s" -#: parser/parse_expr.c:1761 +#: parser/parse_expr.c:1824 msgid "cannot use subquery in check constraint" msgstr "no se pueden usar subconsultas en una restricción «check»" -#: parser/parse_expr.c:1765 +#: parser/parse_expr.c:1828 msgid "cannot use subquery in DEFAULT expression" msgstr "no se puede usar una subconsulta en una expresión DEFAULT" -#: parser/parse_expr.c:1768 +#: parser/parse_expr.c:1831 msgid "cannot use subquery in index expression" msgstr "no se puede usar una subconsulta en una expresión de índice" -#: parser/parse_expr.c:1771 +#: parser/parse_expr.c:1834 msgid "cannot use subquery in index predicate" msgstr "no se puede usar una subconsulta en un predicado de índice" -#: parser/parse_expr.c:1774 +#: parser/parse_expr.c:1837 msgid "cannot use subquery in statistics expression" msgstr "no se puede usar una subconsulta en una expresión de estadísticas" -#: parser/parse_expr.c:1777 +#: parser/parse_expr.c:1840 msgid "cannot use subquery in transform expression" msgstr "no se puede usar una subconsulta en una expresión de transformación" -#: parser/parse_expr.c:1780 +#: parser/parse_expr.c:1843 msgid "cannot use subquery in EXECUTE parameter" msgstr "no se puede usar una subconsulta en un parámetro a EXECUTE" -#: parser/parse_expr.c:1783 +#: parser/parse_expr.c:1846 msgid "cannot use subquery in trigger WHEN condition" -msgstr "no se puede usar una subconsulta en la condición WHEN de un disparador" +msgstr "no se puede usar una subconsulta en la condición WHEN de un “trigger”" -#: parser/parse_expr.c:1786 +#: parser/parse_expr.c:1849 msgid "cannot use subquery in partition bound" msgstr "no se puede usar una subconsulta en un borde de partición" -#: parser/parse_expr.c:1789 +#: parser/parse_expr.c:1852 msgid "cannot use subquery in partition key expression" msgstr "no se puede usar una subconsulta en una expresión de llave de partición" -#: parser/parse_expr.c:1792 +#: parser/parse_expr.c:1855 msgid "cannot use subquery in CALL argument" msgstr "no se puede usar una subconsulta en un argumento a CALL" -#: parser/parse_expr.c:1795 +#: parser/parse_expr.c:1858 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "no se puede usar una subconsulta en la condición WHERE de COPY FROM" -#: parser/parse_expr.c:1798 +#: parser/parse_expr.c:1861 msgid "cannot use subquery in column generation expression" msgstr "no se puede usar una subconsulta en una expresión de generación de columna" -#: parser/parse_expr.c:1851 parser/parse_expr.c:3632 +#: parser/parse_expr.c:1914 parser/parse_expr.c:3764 #, c-format msgid "subquery must return only one column" msgstr "la subconsulta debe retornar sólo una columna" -#: parser/parse_expr.c:1922 +#: parser/parse_expr.c:1985 #, c-format msgid "subquery has too many columns" msgstr "la subconsulta tiene demasiadas columnas" -#: parser/parse_expr.c:1927 +#: parser/parse_expr.c:1990 #, c-format msgid "subquery has too few columns" msgstr "la subconsulta tiene muy pocas columnas" -#: parser/parse_expr.c:2023 +#: parser/parse_expr.c:2086 #, c-format msgid "cannot determine type of empty array" msgstr "no se puede determinar el tipo de un array vacío" -#: parser/parse_expr.c:2024 +#: parser/parse_expr.c:2087 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "Agregue una conversión de tipo explícita al tipo deseado, por ejemplo ARRAY[]::integer[]." -#: parser/parse_expr.c:2038 +#: parser/parse_expr.c:2101 #, c-format msgid "could not find element type for data type %s" msgstr "no se pudo encontrar el tipo de dato de elemento para el tipo de dato %s" -#: parser/parse_expr.c:2121 -#, fuzzy, c-format -#| msgid "target lists can have at most %d entries" +#: parser/parse_expr.c:2184 +#, c-format msgid "ROW expressions can have at most %d entries" -msgstr "las listas de resultados pueden tener a lo más %d entradas" +msgstr "las expresiones ROW pueden tener a lo más %d entradas" -#: parser/parse_expr.c:2326 +#: parser/parse_expr.c:2389 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "el valor del atributo XML sin nombre debe ser una referencia a una columna" -#: parser/parse_expr.c:2327 +#: parser/parse_expr.c:2390 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "el valor del elemento XML sin nombre debe ser una referencia a una columna" -#: parser/parse_expr.c:2342 +#: parser/parse_expr.c:2405 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "el nombre de atributo XML «%s» aparece más de una vez" -#: parser/parse_expr.c:2450 +#: parser/parse_expr.c:2513 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "no se puede convertir el resultado de XMLSERIALIZE a %s" -#: parser/parse_expr.c:2764 parser/parse_expr.c:2960 +#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 #, c-format msgid "unequal number of entries in row expressions" msgstr "número desigual de entradas en expresiones de registro" -#: parser/parse_expr.c:2774 +#: parser/parse_expr.c:2837 #, c-format msgid "cannot compare rows of zero length" msgstr "no se pueden comparar registros de largo cero" -#: parser/parse_expr.c:2799 +#: parser/parse_expr.c:2862 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "el operador de comparación de registros debe retornar tipo boolean, no tipo %s" -#: parser/parse_expr.c:2806 +#: parser/parse_expr.c:2869 #, c-format msgid "row comparison operator must not return a set" msgstr "el operador de comparación de registros no puede retornar un conjunto" -#: parser/parse_expr.c:2865 parser/parse_expr.c:2906 +#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "no se pudo determinar la interpretación del operador de comparación de registros %s" -#: parser/parse_expr.c:2867 +#: parser/parse_expr.c:2930 #, c-format msgid "Row comparison operators must be associated with btree operator families." msgstr "Los operadores de comparación de registros deben estar asociados a una familia de operadores btree." -#: parser/parse_expr.c:2908 +#: parser/parse_expr.c:2971 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "Hay múltiples candidatos igualmente plausibles." -#: parser/parse_expr.c:3001 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "IS DISTINCT FROM requiere que el operador = retorne boolean" - -#: parser/parse_expr.c:3254 +#: parser/parse_expr.c:3306 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" -msgstr "" +msgstr "la cláusula ENCODING de JSON sólo está permitida para el tipo de entrada bytea" -#: parser/parse_expr.c:3261 +#: parser/parse_expr.c:3370 #, c-format -msgid "FORMAT JSON has no effect for json and jsonb types" -msgstr "" +msgid "cannot use non-string types with implicit FORMAT JSON clause" +msgstr "no se puede usar tipos que no son string con la cláusula implícita FORMAT JSON" -#: parser/parse_expr.c:3284 +#: parser/parse_expr.c:3371 #, c-format -msgid "cannot use non-string types with implicit FORMAT JSON clause" -msgstr "" +msgid "cannot use non-string types with explicit FORMAT JSON clause" +msgstr "no se puede usar tipos que no son string con la cláusula explítica FORMAT JSON" -#: parser/parse_expr.c:3354 -#, fuzzy, c-format -#| msgid "cannot cast jsonb string to type %s" +#: parser/parse_expr.c:3460 +#, c-format msgid "cannot use JSON format with non-string output types" -msgstr "no se puede convertir un string jsonb a tipo %s" +msgstr "no se puede usar formato JSON con tipos de salida que no son string" -#: parser/parse_expr.c:3367 +#: parser/parse_expr.c:3473 #, c-format msgid "cannot set JSON encoding for non-bytea output types" -msgstr "" +msgstr "no se puede definir codificación JSON para tipos de salida que no sea bytea" -#: parser/parse_expr.c:3372 -#, fuzzy, c-format -#| msgid "unsupported format code: %d" +#: parser/parse_expr.c:3478 +#, c-format msgid "unsupported JSON encoding" -msgstr "código de formato no soportado: %d" +msgstr "codificación JSON no soportada" -#: parser/parse_expr.c:3373 +#: parser/parse_expr.c:3479 #, c-format msgid "Only UTF8 JSON encoding is supported." -msgstr "" +msgstr "Sólo la codificación JSON UTF8 está soportada." -#: parser/parse_expr.c:3410 -#, fuzzy, c-format -#| msgid "return type %s is not supported for SQL functions" +#: parser/parse_expr.c:3516 +#, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" -msgstr "el tipo de retorno %s no es soportado en funciones SQL" +msgstr "retornar tipos SETOF no está soportado en funciones SQL/JSON" + +#: parser/parse_expr.c:3521 +#, c-format +msgid "returning pseudo-types is not supported in SQL/JSON functions" +msgstr "retornar pseudo-tipos no está soportado en funciones SQL/JSON" -#: parser/parse_expr.c:3711 parser/parse_func.c:865 +#: parser/parse_expr.c:3849 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "el ORDER BY de funciones de agregación no está implementado para funciones de ventana deslizante" -#: parser/parse_expr.c:3930 +#: parser/parse_expr.c:4072 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" -msgstr "" +msgstr "no se puede usar la cláusula FORMAT ENCODING de JSON para tipos de entrada que no son bytea" -#: parser/parse_expr.c:3950 -#, fuzzy, c-format -#| msgid "cannot use subquery in index predicate" +#: parser/parse_expr.c:4092 +#, c-format msgid "cannot use type %s in IS JSON predicate" -msgstr "no se puede usar una subconsulta en un predicado de índice" +msgstr "no se puede tipo %s en predicado IS JSON" + +#: parser/parse_expr.c:4118 parser/parse_expr.c:4239 +#, c-format +#| msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "no se puede usar el tipo %s en la cláusula RETURNING de %s" + +#: parser/parse_expr.c:4120 +#, c-format +#| msgid "Try returning a string type or bytea." +msgid "Try returning json or jsonb." +msgstr "Intente retornando tipo json o jsonb." + +#: parser/parse_expr.c:4168 +#, c-format +msgid "cannot use non-string types with WITH UNIQUE KEYS clause" +msgstr "no se puede usar tipos que no sean strings con cláusula WITH UNIQUE KEYS" + +#: parser/parse_expr.c:4242 +#, c-format +msgid "Try returning a string type or bytea." +msgstr "Intente retornando un tipo de string o bytea." + +#: parser/parse_expr.c:4307 +#, c-format +msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgstr "no se puede especificar FORMAT JSON en la cláusula RETURNING de %s()" + +#: parser/parse_expr.c:4320 +#, c-format +msgid "SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" +msgstr "el comportamiento QUOTES de SQL/JSON no debe ser especificado cuando se usa WITH WRAPPER" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4334 parser/parse_expr.c:4363 parser/parse_expr.c:4394 +#: parser/parse_expr.c:4420 parser/parse_expr.c:4446 +#: parser/parse_jsontable.c:94 +#, c-format +msgid "invalid %s behavior" +msgstr "especificación %s no válida" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4337 parser/parse_expr.c:4366 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s." +msgstr "Sólo ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT o expresión DEFAULT se permite en %s para %s." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4344 parser/parse_expr.c:4373 parser/parse_expr.c:4402 +#: parser/parse_expr.c:4430 parser/parse_expr.c:4456 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "comportamiento %s no válido para la columna «%s»" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4347 parser/parse_expr.c:4376 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns." +msgstr "Sólo ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT o expresión DEFAULT se permite en %s para columnas con formato." + +#: parser/parse_expr.c:4395 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "Sólo ERROR, TRUE, FALSE o UNKNOWN están permitidos en %s para %s." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4405 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "Sólo ERROR, TRUE, FALSE o UNKNOWN están permitidos en %s para columnas EXISTS." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4423 parser/parse_expr.c:4449 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "Sólo ERROR, NULL o expresión DEFAULT se permite en %s para %s." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4433 parser/parse_expr.c:4459 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "Sólo ERROR, NULL o expresión DEFAULT se permite en %s para columnas escalares." + +#: parser/parse_expr.c:4489 +#, c-format +msgid "JSON path expression must be of type %s, not of type %s" +msgstr "la expresión de ruta JSON debe ser de tipo %s, no tipo %s" + +#: parser/parse_expr.c:4707 +#, c-format +msgid "can only specify a constant, non-aggregate function, or operator expression for DEFAULT" +msgstr "sólo se puede especificar constantes, funciones no de agregación, o expresión de operador para DEFAULT" + +#: parser/parse_expr.c:4712 +#, c-format +msgid "DEFAULT expression must not contain column references" +msgstr "las expresiones DEFAULT no pueden contener referencias a columnas" + +#: parser/parse_expr.c:4717 +#, c-format +msgid "DEFAULT expression must not return a set" +msgstr "las expresiones DEFAULT no deben retornar un conjunto" + +#: parser/parse_expr.c:4793 parser/parse_expr.c:4802 +#, c-format +msgid "cannot cast behavior expression of type %s to %s" +msgstr "no se puede convertir la expresión de tipo %s a %s" + +#: parser/parse_expr.c:4796 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "Necesitará aplicar una conversión de la expresión a tipo %s." #: parser/parse_func.c:194 #, c-format @@ -17631,7 +18014,7 @@ msgstr "nombre de argumento «%s» especificado más de una vez" msgid "positional argument cannot follow named argument" msgstr "un argumento posicional no puede seguir a un argumento con nombre" -#: parser/parse_func.c:287 parser/parse_func.c:2367 +#: parser/parse_func.c:287 parser/parse_func.c:2368 #, c-format msgid "%s is not a procedure" msgstr "%s no es un procedimiento" @@ -17750,7 +18133,7 @@ msgstr "No se pudo escoger la función más adecuada. Puede ser necesario agrega msgid "No aggregate function matches the given name and argument types. Perhaps you misplaced ORDER BY; ORDER BY must appear after all regular arguments of the aggregate." msgstr "Ninguna función coincide en el nombre y tipos de argumentos. Quizás puso ORDER BY en una mala posición; ORDER BY debe aparecer después de todos los argumentos normales de la función de agregación." -#: parser/parse_func.c:622 parser/parse_func.c:2410 +#: parser/parse_func.c:622 parser/parse_func.c:2411 #, c-format msgid "procedure %s does not exist" msgstr "no existe el procedimiento «%s»" @@ -17770,7 +18153,7 @@ msgstr "Ninguna función coincide en el nombre y tipos de argumentos. Puede ser msgid "VARIADIC argument must be an array" msgstr "el parámetro VARIADIC debe ser un array" -#: parser/parse_func.c:791 parser/parse_func.c:855 +#: parser/parse_func.c:791 parser/parse_func.c:856 #, c-format msgid "%s(*) must be used to call a parameterless aggregate function" msgstr "%s(*) debe ser usado para invocar una función de agregación sin parámetros" @@ -17785,267 +18168,257 @@ msgstr "las funciones de agregación no pueden retornar conjuntos" msgid "aggregates cannot use named arguments" msgstr "las funciones de agregación no pueden usar argumentos con nombre" -#: parser/parse_func.c:845 +#: parser/parse_func.c:846 #, c-format msgid "DISTINCT is not implemented for window functions" msgstr "DISTINCT no está implementado para funciones de ventana deslizante" -#: parser/parse_func.c:874 +#: parser/parse_func.c:875 #, c-format msgid "FILTER is not implemented for non-aggregate window functions" msgstr "FILTER no está implementado para funciones de ventana deslizante" -#: parser/parse_func.c:883 +#: parser/parse_func.c:884 #, c-format msgid "window function calls cannot contain set-returning function calls" msgstr "las llamadas a funciones de ventana no pueden contener llamadas a funciones que retornan conjuntos" -#: parser/parse_func.c:891 +#: parser/parse_func.c:892 #, c-format msgid "window functions cannot return sets" msgstr "las funciones de ventana deslizante no pueden retornar conjuntos" -#: parser/parse_func.c:2166 parser/parse_func.c:2439 +#: parser/parse_func.c:2167 parser/parse_func.c:2440 #, c-format msgid "could not find a function named \"%s\"" msgstr "no se pudo encontrar una función llamada «%s»" -#: parser/parse_func.c:2180 parser/parse_func.c:2457 +#: parser/parse_func.c:2181 parser/parse_func.c:2458 #, c-format msgid "function name \"%s\" is not unique" msgstr "el nombre de función «%s» no es único" -#: parser/parse_func.c:2182 parser/parse_func.c:2460 +#: parser/parse_func.c:2183 parser/parse_func.c:2461 #, c-format msgid "Specify the argument list to select the function unambiguously." msgstr "Especifique la lista de argumentos para seleccionar la función sin ambigüedad." -#: parser/parse_func.c:2226 +#: parser/parse_func.c:2227 #, c-format msgid "procedures cannot have more than %d argument" msgid_plural "procedures cannot have more than %d arguments" msgstr[0] "los procedimientos no pueden tener más de %d argumento" msgstr[1] "los procedimientos no pueden tener más de %d argumentos" -#: parser/parse_func.c:2357 +#: parser/parse_func.c:2358 #, c-format msgid "%s is not a function" msgstr "«%s» no es una función" -#: parser/parse_func.c:2377 +#: parser/parse_func.c:2378 #, c-format msgid "function %s is not an aggregate" msgstr "la función %s no es una función de agregación" -#: parser/parse_func.c:2405 +#: parser/parse_func.c:2406 #, c-format msgid "could not find a procedure named \"%s\"" msgstr "no se pudo encontrar un procedimiento llamado «%s»" -#: parser/parse_func.c:2419 +#: parser/parse_func.c:2420 #, c-format msgid "could not find an aggregate named \"%s\"" msgstr "no se pudo encontrar una función de agregación llamada «%s»" -#: parser/parse_func.c:2424 +#: parser/parse_func.c:2425 #, c-format msgid "aggregate %s(*) does not exist" msgstr "no existe la función de agregación %s(*)" -#: parser/parse_func.c:2429 +#: parser/parse_func.c:2430 #, c-format msgid "aggregate %s does not exist" msgstr "no existe la función de agregación %s" -#: parser/parse_func.c:2465 +#: parser/parse_func.c:2466 #, c-format msgid "procedure name \"%s\" is not unique" msgstr "el nombre de procedimiento «%s» no es única" -#: parser/parse_func.c:2468 +#: parser/parse_func.c:2469 #, c-format msgid "Specify the argument list to select the procedure unambiguously." msgstr "Especifique la lista de argumentos para seleccionar el procedimiento sin ambigüedad." -#: parser/parse_func.c:2473 +#: parser/parse_func.c:2474 #, c-format msgid "aggregate name \"%s\" is not unique" msgstr "el atributo de la función de agregación «%s» no es único" -#: parser/parse_func.c:2476 +#: parser/parse_func.c:2477 #, c-format msgid "Specify the argument list to select the aggregate unambiguously." msgstr "Especifique la lista de argumentos para seleccionar la función de agregación sin ambigüedad." -#: parser/parse_func.c:2481 +#: parser/parse_func.c:2482 #, c-format msgid "routine name \"%s\" is not unique" msgstr "el nombre de rutina «%s» no es único" -#: parser/parse_func.c:2484 +#: parser/parse_func.c:2485 #, c-format msgid "Specify the argument list to select the routine unambiguously." msgstr "Especifique la lista de argumentos para seleccionar la rutina sin ambigüedad." -#: parser/parse_func.c:2539 +#: parser/parse_func.c:2540 msgid "set-returning functions are not allowed in JOIN conditions" msgstr "no se permiten funciones que retornan conjuntos en condiciones JOIN" -#: parser/parse_func.c:2560 +#: parser/parse_func.c:2561 msgid "set-returning functions are not allowed in policy expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de política" -#: parser/parse_func.c:2576 +#: parser/parse_func.c:2577 msgid "set-returning functions are not allowed in window definitions" msgstr "no se permiten funciones que retornan conjuntos definiciones de ventana deslizante" -#: parser/parse_func.c:2613 -#, fuzzy -#| msgid "set-returning functions are not allowed in trigger WHEN conditions" +#: parser/parse_func.c:2615 msgid "set-returning functions are not allowed in MERGE WHEN conditions" -msgstr "no se permiten funciones que retornan conjuntos en condiciones WHEN de un disparador" +msgstr "no se permiten funciones que retornan conjuntos en condiciones MERGE WHEN" -#: parser/parse_func.c:2617 +#: parser/parse_func.c:2619 msgid "set-returning functions are not allowed in check constraints" msgstr "no se permiten funciones de que retornan conjuntos en restricciones «check»" -#: parser/parse_func.c:2621 +#: parser/parse_func.c:2623 msgid "set-returning functions are not allowed in DEFAULT expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones DEFAULT" -#: parser/parse_func.c:2624 +#: parser/parse_func.c:2626 msgid "set-returning functions are not allowed in index expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de índice" -#: parser/parse_func.c:2627 +#: parser/parse_func.c:2629 msgid "set-returning functions are not allowed in index predicates" msgstr "no se permiten funciones que retornan conjuntos en predicados de índice" -#: parser/parse_func.c:2630 +#: parser/parse_func.c:2632 msgid "set-returning functions are not allowed in statistics expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de estadísticas" -#: parser/parse_func.c:2633 +#: parser/parse_func.c:2635 msgid "set-returning functions are not allowed in transform expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de transformación" -#: parser/parse_func.c:2636 +#: parser/parse_func.c:2638 msgid "set-returning functions are not allowed in EXECUTE parameters" msgstr "no se permiten funciones que retornan conjuntos en parámetros a EXECUTE" -#: parser/parse_func.c:2639 +#: parser/parse_func.c:2641 msgid "set-returning functions are not allowed in trigger WHEN conditions" -msgstr "no se permiten funciones que retornan conjuntos en condiciones WHEN de un disparador" +msgstr "no se permiten funciones que retornan conjuntos en condiciones WHEN de un “trigger”" -#: parser/parse_func.c:2642 +#: parser/parse_func.c:2644 msgid "set-returning functions are not allowed in partition bound" msgstr "no se permiten funciones que retornan conjuntos en bordes de partición" -#: parser/parse_func.c:2645 +#: parser/parse_func.c:2647 msgid "set-returning functions are not allowed in partition key expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de llave de particionamiento" -#: parser/parse_func.c:2648 +#: parser/parse_func.c:2650 msgid "set-returning functions are not allowed in CALL arguments" msgstr "no se permiten funciones que retornan conjuntos en argumentos de CALL" -#: parser/parse_func.c:2651 +#: parser/parse_func.c:2653 msgid "set-returning functions are not allowed in COPY FROM WHERE conditions" msgstr "no se permiten funciones que retornan conjuntos en las condiciones WHERE de COPY FROM" -#: parser/parse_func.c:2654 +#: parser/parse_func.c:2656 msgid "set-returning functions are not allowed in column generation expressions" msgstr "no se permiten funciones que retornan conjuntos en expresiones de generación de columna" -#: parser/parse_merge.c:119 -#, fuzzy, c-format -#| msgid "WHERE CURRENT OF is not supported for this table type" +#: parser/parse_jsontable.c:95 +#, c-format +msgid "Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "Sólo EMPTY [ ARRAY ] o ERROR son permitidos en la cláusula ON ERROR de nivel superior." + +#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#, c-format +msgid "duplicate JSON_TABLE column or path name: %s" +msgstr "nombre de columna o de “path” duplicada en JSON_TABLE: %s" + +#: parser/parse_merge.c:129 +#, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" -msgstr "WHERE CURRENT OF no está soportado para este tipo de tabla" +msgstr "WITH RECURSIVE no está soportado para la sentencia MERGE" -#: parser/parse_merge.c:161 +#: parser/parse_merge.c:176 #, c-format msgid "unreachable WHEN clause specified after unconditional WHEN clause" msgstr "se especificó una cláusula WHEN no alcanzable después de una cláusula WHEN incondicional" -#: parser/parse_merge.c:191 -#, fuzzy, c-format -#| msgid "LIKE is not supported for creating foreign tables" -msgid "MERGE is not supported for relations with rules." -msgstr "LIKE no está soportado para la creación de tablas foráneas" - -#: parser/parse_merge.c:208 +#: parser/parse_merge.c:222 #, c-format msgid "name \"%s\" specified more than once" msgstr "el nombre «%s» fue especificado más de una vez" -#: parser/parse_merge.c:210 +#: parser/parse_merge.c:224 #, c-format msgid "The name is used both as MERGE target table and data source." msgstr "El nombre es usado tanto como tabla de destino de MERGE como como tabla de origen." -#: parser/parse_node.c:87 +#: parser/parse_node.c:82 #, c-format msgid "target lists can have at most %d entries" msgstr "las listas de resultados pueden tener a lo más %d entradas" -#: parser/parse_oper.c:123 parser/parse_oper.c:690 +#: parser/parse_oper.c:114 parser/parse_oper.c:678 #, c-format msgid "postfix operators are not supported" msgstr "los operadores postfix no están soportados" -#: parser/parse_oper.c:130 parser/parse_oper.c:649 utils/adt/regproc.c:509 -#: utils/adt/regproc.c:683 -#, c-format -msgid "operator does not exist: %s" -msgstr "el operador no existe: %s" - -#: parser/parse_oper.c:229 +#: parser/parse_oper.c:217 #, c-format msgid "Use an explicit ordering operator or modify the query." msgstr "Use un operador de ordenamiento explícito o modifique la consulta." -#: parser/parse_oper.c:485 +#: parser/parse_oper.c:473 #, c-format msgid "operator requires run-time type coercion: %s" msgstr "el operador requiere conversión explícita de tipos: %s" -#: parser/parse_oper.c:641 +#: parser/parse_oper.c:629 #, c-format msgid "operator is not unique: %s" msgstr "el operador no es único: %s" -#: parser/parse_oper.c:643 +#: parser/parse_oper.c:631 #, c-format msgid "Could not choose a best candidate operator. You might need to add explicit type casts." msgstr "No se pudo escoger el operador más adecuado. Puede ser necesario agregar conversiones explícitas de tipos." -#: parser/parse_oper.c:652 +#: parser/parse_oper.c:640 #, c-format msgid "No operator matches the given name and argument type. You might need to add an explicit type cast." msgstr "Ningún operador coincide en el nombre y tipo de argumento. Puede ser necesario agregar conversión explícita de tipos." -#: parser/parse_oper.c:654 +#: parser/parse_oper.c:642 #, c-format msgid "No operator matches the given name and argument types. You might need to add explicit type casts." msgstr "Ningún operador coincide en el nombre y tipos de argumentos. Puede ser necesario agregar conversión explícita de tipos." -#: parser/parse_oper.c:714 parser/parse_oper.c:828 -#, c-format -msgid "operator is only a shell: %s" -msgstr "el operador está inconcluso: %s" - -#: parser/parse_oper.c:816 +#: parser/parse_oper.c:803 #, c-format msgid "op ANY/ALL (array) requires array on right side" msgstr "op ANY/ALL (array) requiere un array al lado derecho" -#: parser/parse_oper.c:858 +#: parser/parse_oper.c:844 #, c-format msgid "op ANY/ALL (array) requires operator to yield boolean" msgstr "op ANY/ALL (array) requiere un operador que entregue boolean" -#: parser/parse_oper.c:863 +#: parser/parse_oper.c:849 #, c-format msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "op ANY/ALL (array) requiere un operador que no retorne un conjunto" @@ -18055,7 +18428,7 @@ msgstr "op ANY/ALL (array) requiere un operador que no retorne un conjunto" msgid "inconsistent types deduced for parameter $%d" msgstr "para el parámetro $%d se dedujeron tipos de dato inconsistentes" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:309 tcop/postgres.c:744 #, c-format msgid "could not determine data type of parameter $%d" msgstr "no se pudo determinar el tipo del parámetro $%d" @@ -18075,13 +18448,13 @@ msgstr "la referencia a la tabla %u es ambigua" msgid "table name \"%s\" specified more than once" msgstr "el nombre de tabla «%s» fue especificado más de una vez" -#: parser/parse_relation.c:494 parser/parse_relation.c:3629 -#: parser/parse_relation.c:3638 +#: parser/parse_relation.c:494 parser/parse_relation.c:3633 +#: parser/parse_relation.c:3642 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "referencia a la entrada de la cláusula FROM para la tabla «%s» no válida" -#: parser/parse_relation.c:498 parser/parse_relation.c:3640 +#: parser/parse_relation.c:498 parser/parse_relation.c:3644 #, c-format msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query." msgstr "Hay una entrada para la tabla «%s», pero no puede ser referenciada desde esta parte de la consulta." @@ -18102,23 +18475,22 @@ msgid "cannot use system column \"%s\" in column generation expression" msgstr "no se puede usar la columna de sistema «%s» en una expresión de generación de columna" #: parser/parse_relation.c:723 -#, fuzzy, c-format -#| msgid "cannot use system column \"%s\" in partition key" +#, c-format msgid "cannot use system column \"%s\" in MERGE WHEN condition" -msgstr "no se puede usar la columna de sistema «%s» en llave de particionamiento" +msgstr "no se puede usar la columna de sistema «%s» en condición MERGE WHEN" -#: parser/parse_relation.c:1236 parser/parse_relation.c:1690 -#: parser/parse_relation.c:2387 +#: parser/parse_relation.c:1236 parser/parse_relation.c:1691 +#: parser/parse_relation.c:2384 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "la tabla «%s» tiene %d columnas pero se especificaron %d" -#: parser/parse_relation.c:1444 +#: parser/parse_relation.c:1445 #, c-format msgid "There is a WITH item named \"%s\", but it cannot be referenced from this part of the query." msgstr "Hay un elemento WITH llamado «%s», pero no puede ser referenciada desde esta parte de la consulta." -#: parser/parse_relation.c:1446 +#: parser/parse_relation.c:1447 #, c-format msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references." msgstr "Use WITH RECURSIVE, o reordene los elementos de WITH para eliminar referencias hacia adelante." @@ -18144,141 +18516,136 @@ msgid "a column definition list is required for functions returning \"record\"" msgstr "la lista de definición de columnas es obligatoria para funciones que retornan «record»" #: parser/parse_relation.c:1894 -#, fuzzy, c-format -#| msgid "target lists can have at most %d entries" +#, c-format msgid "column definition lists can have at most %d entries" -msgstr "las listas de resultados pueden tener a lo más %d entradas" +msgstr "las listas de definición de columnas pueden tener a lo más %d entradas" #: parser/parse_relation.c:1954 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "la función «%s» en FROM tiene el tipo de retorno no soportado %s" -#: parser/parse_relation.c:1981 parser/parse_relation.c:2067 -#, fuzzy, c-format -#| msgid "joins can have at most %d columns" +#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 +#, c-format msgid "functions in FROM can return at most %d columns" -msgstr "los joins pueden tener a lo más %d columnas" +msgstr "las funciones en FROM pueden tener a lo más %d columnas" -#: parser/parse_relation.c:2097 -#, fuzzy, c-format -#| msgid "table \"%s\" has %d columns available but %d columns specified" +#: parser/parse_relation.c:2096 +#, c-format msgid "%s function has %d columns available but %d columns specified" -msgstr "la tabla «%s» tiene %d columnas pero se especificaron %d" +msgstr "la función %s tiene %d columnas disponibles pero se especificaron %d" -#: parser/parse_relation.c:2179 +#: parser/parse_relation.c:2177 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "la lista VALUES «%s» tiene %d columnas disponibles pero se especificaron %d" -#: parser/parse_relation.c:2245 +#: parser/parse_relation.c:2242 #, c-format msgid "joins can have at most %d columns" msgstr "los joins pueden tener a lo más %d columnas" -#: parser/parse_relation.c:2270 -#, fuzzy, c-format -#| msgid "table \"%s\" has %d columns available but %d columns specified" +#: parser/parse_relation.c:2267 +#, c-format msgid "join expression \"%s\" has %d columns available but %d columns specified" -msgstr "la tabla «%s» tiene %d columnas pero se especificaron %d" +msgstr "la expresión de join «%s» tiene %d columnas disponibles pero se especificaron %d" -#: parser/parse_relation.c:2360 +#: parser/parse_relation.c:2357 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "la consulta WITH «%s» no tiene una cláusula RETURNING" -#: parser/parse_relation.c:3631 +#: parser/parse_relation.c:3635 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "Probablemente quiera hacer referencia al alias de la tabla «%s»." -#: parser/parse_relation.c:3643 +#: parser/parse_relation.c:3647 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." -msgstr "" +msgstr "Para hacer referencia a esa tabla, debe marcar esta subconsulta con LATERAL." -#: parser/parse_relation.c:3649 +#: parser/parse_relation.c:3653 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "falta una entrada para la tabla «%s» en la cláusula FROM" -#: parser/parse_relation.c:3689 -#, fuzzy, c-format -#| msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." +#: parser/parse_relation.c:3693 +#, c-format msgid "There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query." -msgstr "Hay una columna llamada «%s» en la tabla «%s», pero no puede ser referenciada desde esta parte de la consulta." +msgstr "Hay columnas llamadas «%s», pero están en tablas que no pueden ser referenciadas desde esta parte de la consulta." -#: parser/parse_relation.c:3691 +#: parser/parse_relation.c:3695 #, c-format msgid "Try using a table-qualified name." -msgstr "" +msgstr "Intente usar un nombre calificado con nombre de tabla." -#: parser/parse_relation.c:3699 +#: parser/parse_relation.c:3703 #, c-format msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." msgstr "Hay una columna llamada «%s» en la tabla «%s», pero no puede ser referenciada desde esta parte de la consulta." -#: parser/parse_relation.c:3702 +#: parser/parse_relation.c:3706 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." -msgstr "" +msgstr "Para hacer referencia a esa columna, debe marcar esta subconsulta con LATERAL." -#: parser/parse_relation.c:3704 +#: parser/parse_relation.c:3708 #, c-format msgid "To reference that column, you must use a table-qualified name." -msgstr "" +msgstr "Para hacer referencia a esa columna, debe usar un nombre calificado con nombre de tabla." -#: parser/parse_relation.c:3724 +#: parser/parse_relation.c:3728 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "Probablemente quiera hacer referencia a la columna «%s.%s»." -#: parser/parse_relation.c:3738 +#: parser/parse_relation.c:3742 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "Probablemente quiera hacer referencia a la columna «%s.%s» o la columna «%s.%s»." -#: parser/parse_target.c:481 parser/parse_target.c:796 +#: parser/parse_target.c:480 parser/parse_target.c:795 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "no se puede asignar a la columna de sistema «%s»" -#: parser/parse_target.c:509 +#: parser/parse_target.c:508 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "no se puede definir un elemento de array a DEFAULT" -#: parser/parse_target.c:514 +#: parser/parse_target.c:513 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "no se puede definir un subcampo a DEFAULT" -#: parser/parse_target.c:588 +#: parser/parse_target.c:587 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "la columna «%s» es de tipo %s pero la expresión es de tipo %s" -#: parser/parse_target.c:780 +#: parser/parse_target.c:779 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type" msgstr "no se puede asignar al campo «%s» de la columna «%s» porque su tipo %s no es un tipo compuesto" -#: parser/parse_target.c:789 +#: parser/parse_target.c:788 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s" msgstr "no se puede asignar al campo «%s» de la columna «%s» porque no existe esa columna en el tipo de dato %s" -#: parser/parse_target.c:869 +#: parser/parse_target.c:877 #, c-format msgid "subscripted assignment to \"%s\" requires type %s but expression is of type %s" msgstr "la asignación subindexada a «%s» requiere tipo %s pero la expresión es de tipo %s" -#: parser/parse_target.c:879 +#: parser/parse_target.c:887 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "el subcampo «%s» es de tipo %s pero la expresión es de tipo %s" -#: parser/parse_target.c:1314 +#: parser/parse_target.c:1327 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "SELECT * sin especificar tablas no es válido" @@ -18298,8 +18665,8 @@ msgstr "la referencia a %%TYPE es inapropiada (demasiados nombres con punto): %s msgid "type reference %s converted to %s" msgstr "la referencia al tipo %s convertida a %s" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:390 -#: utils/cache/typcache.c:445 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 +#: utils/cache/typcache.c:452 #, c-format msgid "type \"%s\" is only a shell" msgstr "el tipo «%s» está inconcluso" @@ -18319,336 +18686,330 @@ msgstr "los modificadores de tipo deben ser constantes simples o identificadores msgid "invalid type name \"%s\"" msgstr "el nombre de tipo «%s» no es válido" -#: parser/parse_utilcmd.c:264 +#: parser/parse_utilcmd.c:263 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "no se puede crear una tabla particionada como hija de herencia" -#: parser/parse_utilcmd.c:580 +#: parser/parse_utilcmd.c:475 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "no se puede cambiar el estado «logged» de una secuencia temporal" + +#: parser/parse_utilcmd.c:611 #, c-format msgid "array of serial is not implemented" msgstr "array de serial no está implementado" -#: parser/parse_utilcmd.c:659 parser/parse_utilcmd.c:671 -#: parser/parse_utilcmd.c:730 +#: parser/parse_utilcmd.c:690 parser/parse_utilcmd.c:702 +#: parser/parse_utilcmd.c:761 #, c-format msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "las declaraciones NULL/NOT NULL no son coincidentes para la columna «%s» de la tabla «%s»" -#: parser/parse_utilcmd.c:683 +#: parser/parse_utilcmd.c:714 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "múltiples valores default especificados para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:700 +#: parser/parse_utilcmd.c:731 #, c-format msgid "identity columns are not supported on typed tables" msgstr "las columnas identidad no está soportadas en tablas tipadas" -#: parser/parse_utilcmd.c:704 +#: parser/parse_utilcmd.c:735 #, c-format msgid "identity columns are not supported on partitions" msgstr "las columnas identidad no están soportadas en particiones" -#: parser/parse_utilcmd.c:713 +#: parser/parse_utilcmd.c:744 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "múltiples especificaciones de identidad para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:743 +#: parser/parse_utilcmd.c:774 #, c-format msgid "generated columns are not supported on typed tables" msgstr "las columnas generadas no están soportadas en tablas tipadas" -#: parser/parse_utilcmd.c:747 +#: parser/parse_utilcmd.c:778 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "múltiples cláusulas de generación especificadas para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:765 parser/parse_utilcmd.c:880 +#: parser/parse_utilcmd.c:796 parser/parse_utilcmd.c:911 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "las restricciones de llave primaria no están soportadas en tablas foráneas" -#: parser/parse_utilcmd.c:774 parser/parse_utilcmd.c:890 +#: parser/parse_utilcmd.c:805 parser/parse_utilcmd.c:921 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "las restricciones unique no están soportadas en tablas foráneas" -#: parser/parse_utilcmd.c:819 +#: parser/parse_utilcmd.c:850 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "tanto el valor por omisión como identidad especificados para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:827 +#: parser/parse_utilcmd.c:858 #, c-format msgid "both default and generation expression specified for column \"%s\" of table \"%s\"" msgstr "tanto el valor por omisión como expresión de generación especificados para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:835 +#: parser/parse_utilcmd.c:866 #, c-format msgid "both identity and generation expression specified for column \"%s\" of table \"%s\"" msgstr "tanto identidad como expresión de generación especificados para columna «%s» de tabla «%s»" -#: parser/parse_utilcmd.c:900 +#: parser/parse_utilcmd.c:931 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "las restricciones de exclusión no están soportadas en tablas foráneas" -#: parser/parse_utilcmd.c:906 -#, c-format -msgid "exclusion constraints are not supported on partitioned tables" -msgstr "las restricciones de exclusión no están soportadas en tablas particionadas" - -#: parser/parse_utilcmd.c:971 +#: parser/parse_utilcmd.c:996 #, c-format msgid "LIKE is not supported for creating foreign tables" msgstr "LIKE no está soportado para la creación de tablas foráneas" -#: parser/parse_utilcmd.c:984 -#, fuzzy, c-format -#| msgid "relation \"%s\" in %s clause not found in FROM clause" +#: parser/parse_utilcmd.c:1009 +#, c-format msgid "relation \"%s\" is invalid in LIKE clause" -msgstr "la relación «%s» en la cláusula %s no fue encontrada en la cláusula FROM" +msgstr "la relación «%s» no es válida en cláusula LIKE" -#: parser/parse_utilcmd.c:1741 parser/parse_utilcmd.c:1849 +#: parser/parse_utilcmd.c:1736 parser/parse_utilcmd.c:1844 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "El índice «%s» contiene una referencia a la fila completa (whole-row)." -#: parser/parse_utilcmd.c:2236 +#: parser/parse_utilcmd.c:2242 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "no se puede usar un índice existente en CREATE TABLE" -#: parser/parse_utilcmd.c:2256 +#: parser/parse_utilcmd.c:2262 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "el índice «%s» ya está asociado a una restricción" -#: parser/parse_utilcmd.c:2271 -#, c-format -msgid "index \"%s\" is not valid" -msgstr "el índice «%s» no es válido" - -#: parser/parse_utilcmd.c:2277 +#: parser/parse_utilcmd.c:2283 #, c-format msgid "\"%s\" is not a unique index" msgstr "«%s» no es un índice único" -#: parser/parse_utilcmd.c:2278 parser/parse_utilcmd.c:2285 -#: parser/parse_utilcmd.c:2292 parser/parse_utilcmd.c:2369 +#: parser/parse_utilcmd.c:2284 parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2298 parser/parse_utilcmd.c:2375 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "No se puede crear una restricción de llave primaria o única usando un índice así." -#: parser/parse_utilcmd.c:2284 +#: parser/parse_utilcmd.c:2290 #, c-format msgid "index \"%s\" contains expressions" msgstr "el índice «%s» contiene expresiones" -#: parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2297 #, c-format msgid "\"%s\" is a partial index" msgstr "«%s» es un índice parcial" -#: parser/parse_utilcmd.c:2303 +#: parser/parse_utilcmd.c:2309 #, c-format msgid "\"%s\" is a deferrable index" msgstr "«%s» no es un índice postergable (deferrable)" -#: parser/parse_utilcmd.c:2304 +#: parser/parse_utilcmd.c:2310 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "No se puede crear una restricción no postergable usando un índice postergable." -#: parser/parse_utilcmd.c:2368 +#: parser/parse_utilcmd.c:2374 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "el índice «%s» columna número %d no tiene comportamiento de ordenamiento por omisión" -#: parser/parse_utilcmd.c:2525 +#: parser/parse_utilcmd.c:2531 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "la columna «%s» aparece dos veces en llave primaria" -#: parser/parse_utilcmd.c:2531 +#: parser/parse_utilcmd.c:2537 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "la columna «%s» aparece dos veces en restricción unique" -#: parser/parse_utilcmd.c:2878 +#: parser/parse_utilcmd.c:2871 #, c-format msgid "index expressions and predicates can refer only to the table being indexed" msgstr "las expresiones y predicados de índice sólo pueden referirse a la tabla en indexación" -#: parser/parse_utilcmd.c:2950 +#: parser/parse_utilcmd.c:2943 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "las expresiones estadísticas sólo pueden referirse a la tabla que está siendo referida" -#: parser/parse_utilcmd.c:2993 +#: parser/parse_utilcmd.c:2986 #, c-format msgid "rules on materialized views are not supported" msgstr "las reglas en vistas materializadas no están soportadas" -#: parser/parse_utilcmd.c:3053 +#: parser/parse_utilcmd.c:3046 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "la condición WHERE de la regla no puede contener referencias a otras relaciones" -#: parser/parse_utilcmd.c:3125 +#: parser/parse_utilcmd.c:3118 #, c-format msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions" msgstr "las reglas con condiciones WHERE sólo pueden tener acciones SELECT, INSERT, UPDATE o DELETE" -#: parser/parse_utilcmd.c:3143 parser/parse_utilcmd.c:3244 -#: rewrite/rewriteHandler.c:537 rewrite/rewriteManip.c:1082 +#: parser/parse_utilcmd.c:3136 parser/parse_utilcmd.c:3237 +#: rewrite/rewriteHandler.c:544 rewrite/rewriteManip.c:1096 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "las sentencias UNION/INTERSECT/EXCEPT condicionales no están implementadas" -#: parser/parse_utilcmd.c:3161 +#: parser/parse_utilcmd.c:3154 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "una regla ON SELECT no puede usar OLD" -#: parser/parse_utilcmd.c:3165 +#: parser/parse_utilcmd.c:3158 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "una regla ON SELECT no puede usar NEW" -#: parser/parse_utilcmd.c:3174 +#: parser/parse_utilcmd.c:3167 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "una regla ON INSERT no puede usar OLD" -#: parser/parse_utilcmd.c:3180 +#: parser/parse_utilcmd.c:3173 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "una regla ON DELETE no puede usar NEW" -#: parser/parse_utilcmd.c:3208 +#: parser/parse_utilcmd.c:3201 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "no se puede hacer referencia a OLD dentro de una consulta WITH" -#: parser/parse_utilcmd.c:3215 +#: parser/parse_utilcmd.c:3208 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "no se puede hacer referencia a NEW dentro de una consulta WITH" -#: parser/parse_utilcmd.c:3667 +#: parser/parse_utilcmd.c:3664 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "cláusula DEFERRABLE mal puesta" -#: parser/parse_utilcmd.c:3672 parser/parse_utilcmd.c:3687 +#: parser/parse_utilcmd.c:3669 parser/parse_utilcmd.c:3684 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "no se permiten múltiples cláusulas DEFERRABLE/NOT DEFERRABLE" -#: parser/parse_utilcmd.c:3682 +#: parser/parse_utilcmd.c:3679 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "la cláusula NOT DEFERRABLE está mal puesta" -#: parser/parse_utilcmd.c:3695 parser/parse_utilcmd.c:3721 gram.y:5993 +#: parser/parse_utilcmd.c:3692 parser/parse_utilcmd.c:3718 gram.y:6114 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" msgstr "una restricción declarada INITIALLY DEFERRED debe ser DEFERRABLE" -#: parser/parse_utilcmd.c:3703 +#: parser/parse_utilcmd.c:3700 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "la cláusula INITIALLY DEFERRED está mal puesta" -#: parser/parse_utilcmd.c:3708 parser/parse_utilcmd.c:3734 +#: parser/parse_utilcmd.c:3705 parser/parse_utilcmd.c:3731 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "no se permiten múltiples cláusulas INITIALLY IMMEDIATE/DEFERRED" -#: parser/parse_utilcmd.c:3729 +#: parser/parse_utilcmd.c:3726 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "la cláusula INITIALLY IMMEDIATE está mal puesta" -#: parser/parse_utilcmd.c:3922 +#: parser/parse_utilcmd.c:3919 #, c-format msgid "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "CREATE especifica un esquema (%s) diferente del que se está creando (%s)" -#: parser/parse_utilcmd.c:3957 +#: parser/parse_utilcmd.c:3954 #, c-format msgid "\"%s\" is not a partitioned table" msgstr "«%s» no es una tabla particionada" -#: parser/parse_utilcmd.c:3964 +#: parser/parse_utilcmd.c:3961 #, c-format msgid "table \"%s\" is not partitioned" -msgstr "«la tabla %s» no está particionada" +msgstr "la tabla «%s» no está particionada" -#: parser/parse_utilcmd.c:3971 +#: parser/parse_utilcmd.c:3968 #, c-format msgid "index \"%s\" is not partitioned" msgstr "el índice «%s» no está particionado" -#: parser/parse_utilcmd.c:4011 +#: parser/parse_utilcmd.c:4008 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "una tabla particionada por hash no puede tener una partición default" -#: parser/parse_utilcmd.c:4028 +#: parser/parse_utilcmd.c:4025 #, c-format msgid "invalid bound specification for a hash partition" msgstr "especificación de borde no válida para partición de hash" -#: parser/parse_utilcmd.c:4034 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4031 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "el módulo para una partición hash debe ser un valor entero mayor que cero" -#: parser/parse_utilcmd.c:4041 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4038 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "remanente en partición hash debe ser menor que el módulo" -#: parser/parse_utilcmd.c:4054 +#: parser/parse_utilcmd.c:4051 #, c-format msgid "invalid bound specification for a list partition" msgstr "especificación de borde no válida para partición de lista" -#: parser/parse_utilcmd.c:4107 +#: parser/parse_utilcmd.c:4104 #, c-format msgid "invalid bound specification for a range partition" msgstr "especificación de borde no válida para partición de rango" -#: parser/parse_utilcmd.c:4113 +#: parser/parse_utilcmd.c:4110 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "FROM debe especificar exactamente un valor por cada columna de particionado" -#: parser/parse_utilcmd.c:4117 +#: parser/parse_utilcmd.c:4114 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "TO debe especificar exactamente un valor por cada columna de particionado" -#: parser/parse_utilcmd.c:4231 +#: parser/parse_utilcmd.c:4228 #, c-format msgid "cannot specify NULL in range bound" msgstr "no se puede especificar NULL en borde de rango" -#: parser/parse_utilcmd.c:4280 +#: parser/parse_utilcmd.c:4277 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "cada borde que sigue a un MAXVALUE debe ser también MAXVALUE" -#: parser/parse_utilcmd.c:4287 +#: parser/parse_utilcmd.c:4284 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "cada borde que siga a un MINVALUE debe ser también MINVALUE" -#: parser/parse_utilcmd.c:4330 +#: parser/parse_utilcmd.c:4327 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "el valor especificado no puede ser convertido al tipo %s para la columna «%s»" @@ -18661,12 +19022,12 @@ msgstr "UESCAPE debe ser seguido por un literal de cadena simple" msgid "invalid Unicode escape character" msgstr "carácter de escape Unicode no válido" -#: parser/parser.c:347 scan.l:1390 +#: parser/parser.c:347 scan.l:1393 #, c-format msgid "invalid Unicode escape value" msgstr "valor de escape Unicode no válido" -#: parser/parser.c:494 utils/adt/varlena.c:6505 scan.l:701 +#: parser/parser.c:494 utils/adt/varlena.c:6640 scan.l:716 #, c-format msgid "invalid Unicode escape" msgstr "valor de escape Unicode no válido" @@ -18676,8 +19037,8 @@ msgstr "valor de escape Unicode no válido" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "Los escapes Unicode deben ser \\XXXX o \\+XXXXXX." -#: parser/parser.c:523 utils/adt/varlena.c:6530 scan.l:662 scan.l:678 -#: scan.l:694 +#: parser/parser.c:523 utils/adt/varlena.c:6665 scan.l:677 scan.l:693 +#: scan.l:709 #, c-format msgid "invalid Unicode surrogate pair" msgstr "par sustituto (surrogate) Unicode no válido" @@ -18687,89 +19048,89 @@ msgstr "par sustituto (surrogate) Unicode no válido" msgid "identifier \"%s\" will be truncated to \"%.*s\"" msgstr "el identificador «%s» se truncará a «%.*s»" -#: partitioning/partbounds.c:2921 +#: partitioning/partbounds.c:2920 #, c-format msgid "partition \"%s\" conflicts with existing default partition \"%s\"" msgstr "la partición «%s» está en conflicto con la partición default «%s» existente" -#: partitioning/partbounds.c:2973 partitioning/partbounds.c:2992 -#: partitioning/partbounds.c:3014 +#: partitioning/partbounds.c:2972 partitioning/partbounds.c:2991 +#: partitioning/partbounds.c:3013 #, c-format msgid "every hash partition modulus must be a factor of the next larger modulus" msgstr "cada módulo de partición hash debe ser un factor del próximo mayor módulo" -#: partitioning/partbounds.c:2974 partitioning/partbounds.c:3015 +#: partitioning/partbounds.c:2973 partitioning/partbounds.c:3014 #, c-format msgid "The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\"." msgstr "El nuevo módulo %d no es un factor de %d, el módulo de la partición existente «%s»." -#: partitioning/partbounds.c:2993 +#: partitioning/partbounds.c:2992 #, c-format msgid "The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\"." msgstr "El nuevo módulo %d no es divisible para %d, el módulo de la partición existente «%s»." -#: partitioning/partbounds.c:3128 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "borde de rango vació especificado para la partición «%s»" -#: partitioning/partbounds.c:3130 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "El límite inferior %s especificado es mayor o igual al límite superior %s." -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "la partición «%s» traslaparía con la partición «%s»" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"" msgstr "se omitió recorrer la tabla foránea «%s» que es una partición de la partición default «%s»" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "remainder for hash partition must be an integer value greater than or equal to zero" msgstr "remanente en partición hash debe ser un valor entero mayor que o igual a cero" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "«%s» es una tabla particionada por hash" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" msgstr "el número de columnas de particionamiento (%d) no coincide con el número de llaves de particionamiento provistas (%d)" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "la columna %d de la llave de particionamiento tiene tipo «%s», pero el valor dado es de tipo «%s»" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"" msgstr "la columna %d de la llave de particionamiento tiene tipo «%s», pero el valor dado es de tipo «%s»" -#: port/pg_sema.c:209 port/pg_shmem.c:708 port/posix_sema.c:209 -#: port/sysv_sema.c:323 port/sysv_shmem.c:708 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 +#: port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "no se pudo hacer stat al directorio de datos «%s»: %m" -#: port/pg_shmem.c:223 port/sysv_shmem.c:223 +#: port/pg_shmem.c:224 port/sysv_shmem.c:224 #, c-format msgid "could not create shared memory segment: %m" msgstr "no se pudo crear el segmento de memoria compartida: %m" -#: port/pg_shmem.c:224 port/sysv_shmem.c:224 +#: port/pg_shmem.c:225 port/sysv_shmem.c:225 #, c-format msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)." msgstr "La llamada a sistema fallida fue shmget(key=%lu, size=%zu, 0%o)." -#: port/pg_shmem.c:228 port/sysv_shmem.c:228 +#: port/pg_shmem.c:229 port/sysv_shmem.c:229 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n" @@ -18778,7 +19139,7 @@ msgstr "" "Este error normalmente significa que la petición de un segmento de memoria compartida de PostgreSQL excedió el parámetro SHMMAX del kernel, o posiblemente que es menor que el parámetro SHMMIN del kernel.\n" "La documentación de PostgreSQL contiene más información acerca de la configuración de memoria compartida." -#: port/pg_shmem.c:235 port/sysv_shmem.c:235 +#: port/pg_shmem.c:236 port/sysv_shmem.c:236 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n" @@ -18787,7 +19148,7 @@ msgstr "" "Este error normalmente significa que la petición de un segmento de memoria compartida de PostgreSQL excedió el parámetro SHMALL del kernel. Puede ser necesario reconfigurar el kernel con un SHMALL mayor.\n" "La documentación de PostgreSQL contiene más información acerca de la configuración de memoria compartida." -#: port/pg_shmem.c:241 port/sysv_shmem.c:241 +#: port/pg_shmem.c:242 port/sysv_shmem.c:242 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n" @@ -18796,62 +19157,62 @@ msgstr "" "Este error *no* significa que se haya quedado sin espacio en disco. Ocurre cuando se han usado todos los IDs de memoria compartida disponibles, en cuyo caso puede incrementar el parámetro SHMMNI del kernel, o bien porque se ha alcanzado el límite total de memoria compartida.\n" "La documentación de PostgreSQL contiene más información acerca de la configuración de memoria compartida." -#: port/pg_shmem.c:583 port/sysv_shmem.c:583 port/win32_shmem.c:641 +#: port/pg_shmem.c:584 port/sysv_shmem.c:584 port/win32_shmem.c:646 #, c-format -msgid "huge_page_size must be 0 on this platform." -msgstr "huge_page_size debe ser 0 en esta plataforma." +msgid "\"huge_page_size\" must be 0 on this platform." +msgstr "«huge_page_size» debe ser 0 en esta plataforma." -#: port/pg_shmem.c:646 port/sysv_shmem.c:646 +#: port/pg_shmem.c:655 port/sysv_shmem.c:655 #, c-format msgid "could not map anonymous shared memory: %m" msgstr "no se pudo mapear memoria compartida anónima: %m" -#: port/pg_shmem.c:648 port/sysv_shmem.c:648 +#: port/pg_shmem.c:657 port/sysv_shmem.c:657 #, c-format -msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections." -msgstr "Este error normalmente significa que la petición de un segmento de memoria compartida de PostgreSQL excedía la memoria disponible, el espacio de intercambio (swap), o las huge pages. Para reducir el tamaño de la petición (actualmente %zu bytes), reduzca el uso de memoria compartida de PostgreSQL, quizás reduciendo el parámetro shared_buffers o el parámetro max_connections." +msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing \"shared_buffers\" or \"max_connections\"." +msgstr "Este error normalmente significa que la petición de un segmento de memoria compartida de PostgreSQL excedía la memoria disponible, el espacio de intercambio (swap), o las huge pages. Para reducir el tamaño de la petición (actualmente %zu bytes), reduzca el uso de memoria compartida de PostgreSQL, quizás reduciendo el parámetro «shared_buffers» o el parámetro «max_connections»." -#: port/pg_shmem.c:716 port/sysv_shmem.c:716 +#: port/pg_shmem.c:725 port/sysv_shmem.c:725 #, c-format msgid "huge pages not supported on this platform" msgstr "las huge pages no están soportadas en esta plataforma" -#: port/pg_shmem.c:723 port/sysv_shmem.c:723 +#: port/pg_shmem.c:732 port/sysv_shmem.c:732 #, c-format -msgid "huge pages not supported with the current shared_memory_type setting" -msgstr "las huge pages no están soportadas con la configuración actual de shared_memory_type" +msgid "huge pages not supported with the current \"shared_memory_type\" setting" +msgstr "las huge pages no están soportadas con la configuración actual de «shared_memory_type»" -#: port/pg_shmem.c:783 port/sysv_shmem.c:783 utils/init/miscinit.c:1351 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1401 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "el bloque de memoria compartida preexistente (clave %lu, ID %lu) aún está en uso" -#: port/pg_shmem.c:786 port/sysv_shmem.c:786 utils/init/miscinit.c:1353 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1403 #, c-format msgid "Terminate any old server processes associated with data directory \"%s\"." msgstr "Termine cualquier proceso de servidor asociado al directorio de datos «%s»." -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "no se pudo crear semáforos: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "La llamada a sistema fallida fue semget(%lu, %d, 0%o)." -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" -"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its max_connections parameter.\n" +"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its \"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring your system for PostgreSQL." msgstr "" "Este error *no* significa que se haya quedado sin espacio en disco.\n" -"Ocurre cuando se alcanza el límite del sistema del número de semáforos (SEMMNI), o bien cuando se excede el total de semáforos del sistema (SEMMNS).Necesita incrementar el parámetro respectivo del kernel. Alternativamente, reduzca el consumo de semáforos de PostgreSQL reduciendo el parámetro max_connections.\n" +"Ocurre cuando se alcanza el límite del sistema del número de semáforos (SEMMNI), o bien cuando se excede el total de semáforos del sistema (SEMMNS). Necesita incrementar el parámetro respectivo del kernel. Alternativamente, reduzca el consumo de semáforos de PostgreSQL reduciendo el parámetro «max_connections».\n" "La documentación de PostgreSQL contiene más información acerca de cómo configurar su sistema para PostgreSQL." -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details." msgstr "Probablemente necesita incrementar el valor SEMVMX del kernel hasta al menos %d. Examine la documentación de PostgreSQL para obtener más detalles." @@ -18976,1185 +19337,1079 @@ msgstr "La llamada a sistema fallida fue DuplicateHandle." msgid "Failed system call was MapViewOfFileEx." msgstr "La llamada a sistema fallida fue MapViewOfFileEx." -#: postmaster/autovacuum.c:417 -#, c-format -msgid "could not fork autovacuum launcher process: %m" -msgstr "no se pudo iniciar el lanzador autovacuum: %m" - -#: postmaster/autovacuum.c:764 +#: postmaster/autovacuum.c:686 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "proceso ayudante autovacuum tomó demasiado tiempo para iniciarse; cancelado" -#: postmaster/autovacuum.c:1489 -#, c-format -msgid "could not fork autovacuum worker process: %m" -msgstr "no se pudo lanzar el proceso «autovacuum worker»: %m" - -#: postmaster/autovacuum.c:2322 +#: postmaster/autovacuum.c:2203 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "autovacuum: eliminando tabla temporal huérfana «%s.%s.%s»" -#: postmaster/autovacuum.c:2558 +#: postmaster/autovacuum.c:2439 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "vacuum automático de la tabla «%s.%s.%s»" -#: postmaster/autovacuum.c:2561 +#: postmaster/autovacuum.c:2442 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "análisis automático de la tabla «%s.%s.%s»" -#: postmaster/autovacuum.c:2755 +#: postmaster/autovacuum.c:2636 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "procesando elemento de tarea de la tabla «%s.%s.%s»" -#: postmaster/autovacuum.c:3369 +#: postmaster/autovacuum.c:3254 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "autovacuum no fue iniciado debido a un error de configuración" -#: postmaster/autovacuum.c:3370 +#: postmaster/autovacuum.c:3255 #, c-format msgid "Enable the \"track_counts\" option." msgstr "Active la opción «track_counts»." -#: postmaster/bgworker.c:259 +#: postmaster/bgworker.c:260 #, c-format msgid "inconsistent background worker state (max_worker_processes=%d, total_slots=%d)" msgstr "estado inconsistente de proceso ayudante (max_worker_processes=%d, total_slots=%d)" -#: postmaster/bgworker.c:669 -#, fuzzy, c-format -#| msgid "background worker \"%s\": only dynamic background workers can request notification" +#: postmaster/bgworker.c:651 +#, c-format msgid "background worker \"%s\": background workers without shared memory access are not supported" -msgstr "proceso ayudante «%s»: sólo los ayudantes dinámicos pueden pedir notificaciones" +msgstr "proceso ayudante «%s»: los ayudantes sin acceso a memoria compartida no están soportdos" -#: postmaster/bgworker.c:680 +#: postmaster/bgworker.c:662 #, c-format msgid "background worker \"%s\": cannot request database access if starting at postmaster start" msgstr "proceso ayudante «%s»: no se puede solicitar una conexión a base de datos si está iniciando en el momento de inicio de postmaster" -#: postmaster/bgworker.c:694 +#: postmaster/bgworker.c:676 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "proceso ayudante «%s»: intervalo de reinicio no válido" -#: postmaster/bgworker.c:709 +#: postmaster/bgworker.c:691 #, c-format msgid "background worker \"%s\": parallel workers may not be configured for restart" msgstr "proceso ayudante «%s»: los ayudantes paralelos no pueden ser configurados «restart»" -#: postmaster/bgworker.c:733 tcop/postgres.c:3255 +#: postmaster/bgworker.c:715 tcop/postgres.c:3312 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "terminando el proceso ayudante «%s» debido a una orden del administrador" -#: postmaster/bgworker.c:890 +#: postmaster/bgworker.c:888 #, c-format -msgid "background worker \"%s\": must be registered in shared_preload_libraries" -msgstr "proceso ayudante «%s»: debe ser registrado en shared_preload_libraries" +msgid "background worker \"%s\": must be registered in \"shared_preload_libraries\"" +msgstr "proceso ayudante «%s»: debe ser registrado en «shared_preload_libraries»" -#: postmaster/bgworker.c:902 +#: postmaster/bgworker.c:911 #, c-format msgid "background worker \"%s\": only dynamic background workers can request notification" msgstr "proceso ayudante «%s»: sólo los ayudantes dinámicos pueden pedir notificaciones" -#: postmaster/bgworker.c:917 +#: postmaster/bgworker.c:926 #, c-format msgid "too many background workers" msgstr "demasiados procesos ayudantes" -#: postmaster/bgworker.c:918 +#: postmaster/bgworker.c:927 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "Up to %d background workers can be registered with the current settings." msgstr[0] "Hasta %d proceso ayudante puede registrarse con la configuración actual." msgstr[1] "Hasta %d procesos ayudantes pueden registrarse con la configuración actual." -# FIXME a %s would be nice here -#: postmaster/bgworker.c:922 +#: postmaster/bgworker.c:931 postmaster/checkpointer.c:445 #, c-format -msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "Considere incrementar el parámetro de configuración «max_worker_processes»." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "Considere incrementar el parámetro de configuración «%s»." -#: postmaster/checkpointer.c:431 +#: postmaster/checkpointer.c:441 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" msgstr[0] "los puntos de control están ocurriendo con demasiada frecuencia (cada %d segundo)" msgstr[1] "los puntos de control están ocurriendo con demasiada frecuencia (cada %d segundos)" -# FIXME a %s would be nice here -#: postmaster/checkpointer.c:435 -#, c-format -msgid "Consider increasing the configuration parameter \"max_wal_size\"." -msgstr "Considere incrementar el parámetro de configuración «max_wal_size»." - -#: postmaster/checkpointer.c:1059 +#: postmaster/checkpointer.c:1067 #, c-format msgid "checkpoint request failed" -msgstr "falló la petición de punto de control" +msgstr "falló la petición de checkpoint" -#: postmaster/checkpointer.c:1060 +#: postmaster/checkpointer.c:1068 #, c-format msgid "Consult recent messages in the server log for details." msgstr "Vea los mensajes recientes en el registro del servidor para obtener más detalles." -#: postmaster/pgarch.c:416 +#: postmaster/launch_backend.c:381 #, c-format -msgid "archive_mode enabled, yet archiving is not configured" -msgstr "" +msgid "could not execute server process \"%s\": %m" +msgstr "no se pudo lanzar el proceso servidor «%s»: %m" + +#: postmaster/launch_backend.c:434 +#, c-format +msgid "could not create backend parameter file mapping: error code %lu" +msgstr "no se pudo crear mapeo de archivo de parámetros de servidor: código de error %lu" + +#: postmaster/launch_backend.c:442 +#, c-format +msgid "could not map backend parameter memory: error code %lu" +msgstr "no se pudo mapear memoria para parámetros de servidor: código de error %lu" + +#: postmaster/launch_backend.c:459 +#, c-format +msgid "subprocess command line too long" +msgstr "orden de subproceso demasiado larga" + +#: postmaster/launch_backend.c:477 +#, c-format +msgid "CreateProcess() call failed: %m (error code %lu)" +msgstr "llamada a CreateProcess() falló: %m (código de error %lu)" + +#: postmaster/launch_backend.c:504 +#, c-format +msgid "could not unmap view of backend parameter file: error code %lu" +msgstr "no se pudo desmapear la vista del archivo de parámetros de servidor: código de error %lu" + +#: postmaster/launch_backend.c:508 +#, c-format +msgid "could not close handle to backend parameter file: error code %lu" +msgstr "no se pudo cerrar el archivo de parámetros de servidor: código de error %lu" + +#: postmaster/launch_backend.c:530 +#, c-format +msgid "giving up after too many tries to reserve shared memory" +msgstr "renunciar después de demasiados intentos de reservar memoria compartida" + +#: postmaster/launch_backend.c:531 +#, c-format +msgid "This might be caused by ASLR or antivirus software." +msgstr "Esto podría deberse a ASLR o un software antivirus." + +#: postmaster/launch_backend.c:834 +#, c-format +msgid "could not duplicate socket %d for use in backend: error code %d" +msgstr "no se pudo duplicar el socket %d para su empleo en el backend: código de error %d" + +#: postmaster/launch_backend.c:866 +#, c-format +msgid "could not create inherited socket: error code %d\n" +msgstr "no se pudo crear el socket heradado: código de error %d\n" + +#: postmaster/launch_backend.c:895 +#, c-format +msgid "could not open backend variables file \"%s\": %m\n" +msgstr "no se pudo abrir el archivo de variables de servidor «%s»: %m\n" + +#: postmaster/launch_backend.c:901 +#, c-format +msgid "could not read from backend variables file \"%s\": %m\n" +msgstr "no se pudo leer el archivo de variables de servidor «%s»: %m\n" -#: postmaster/pgarch.c:438 +#: postmaster/launch_backend.c:912 +#, c-format +msgid "could not read startup data from backend variables file \"%s\": %m\n" +msgstr "no se pudo leer el archivo de variables de servidor «%s»: %m\n" + +#: postmaster/launch_backend.c:924 +#, c-format +msgid "could not remove file \"%s\": %m\n" +msgstr "no se pudo eliminar el archivo «%s»: %m\n" + +#: postmaster/launch_backend.c:940 +#, c-format +msgid "could not map view of backend variables: error code %lu\n" +msgstr "no se pudo mapear la vista del archivo de variables: código de error %lu\n" + +#: postmaster/launch_backend.c:959 +#, c-format +msgid "could not unmap view of backend variables: error code %lu\n" +msgstr "no se pudo desmapear la vista del archivo de variables: código de error %lu\n" + +#: postmaster/launch_backend.c:966 +#, c-format +msgid "could not close handle to backend parameter variables: error code %lu\n" +msgstr "no se pudo cerrar el archivo de variables de servidor: código de error %lu\n" + +#: postmaster/pgarch.c:428 +#, c-format +msgid "\"archive_mode\" enabled, yet archiving is not configured" +msgstr "«archive_mode» está activado, pero el archivado no está configurado" + +#: postmaster/pgarch.c:452 #, c-format msgid "removed orphan archive status file \"%s\"" msgstr "eliminando archivo de estado huérfano «%s»" -#: postmaster/pgarch.c:448 +#: postmaster/pgarch.c:462 #, c-format msgid "removal of orphan archive status file \"%s\" failed too many times, will try again later" msgstr "la eliminación del archivo de estado huérfano «%s» falló demasiadas veces, se tratará de nuevo después" -#: postmaster/pgarch.c:484 +#: postmaster/pgarch.c:498 #, c-format msgid "archiving write-ahead log file \"%s\" failed too many times, will try again later" msgstr "el archivado del archivo de WAL «%s» falló demasiadas veces, se tratará de nuevo más tarde" -#: postmaster/pgarch.c:791 postmaster/pgarch.c:830 +#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 #, c-format -msgid "both archive_command and archive_library set" -msgstr "" +msgid "both \"archive_command\" and \"archive_library\" set" +msgstr "tanto «archive_command» como «archive_library» están definidos" -#: postmaster/pgarch.c:792 postmaster/pgarch.c:831 +#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 #, c-format -msgid "Only one of archive_command, archive_library may be set." -msgstr "" +msgid "Only one of \"archive_command\", \"archive_library\" may be set." +msgstr "Sólo uno de «archive_command», «archive_library» puede ser definido." -#: postmaster/pgarch.c:809 +#: postmaster/pgarch.c:897 #, c-format msgid "restarting archiver process because value of \"archive_library\" was changed" msgstr "reiniciando el proceso archivador porque el valor de «archive_library» cambió" -#: postmaster/pgarch.c:846 +#: postmaster/pgarch.c:934 #, c-format msgid "archive modules have to define the symbol %s" -msgstr "" +msgstr "los módulos de archivado tienen que definir el símbolo %s" -#: postmaster/pgarch.c:852 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules must register an archive callback" msgstr "los módulos de archivado deben registrar un callback de archivado" -#: postmaster/postmaster.c:759 +#: postmaster/postmaster.c:661 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: argumento no válido para la opción -f: «%s»\n" -#: postmaster/postmaster.c:832 +#: postmaster/postmaster.c:734 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: argumento no válido para la opción -t: «%s»\n" -#: postmaster/postmaster.c:855 +#: postmaster/postmaster.c:757 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: argumento no válido: «%s»\n" -#: postmaster/postmaster.c:923 +#: postmaster/postmaster.c:825 #, c-format -msgid "%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must be less than max_connections (%d)\n" -msgstr "" +msgid "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" +msgstr "%s: «superuser_reserved_connections» (%d) más «reserved_connections» (%d) debe ser menor que «max_connections» (%d)\n" + +#: postmaster/postmaster.c:833 +#, c-format +msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" +msgstr "el archivador de WAL no puede activarse cuando «wal_level» es «minimal»" -#: postmaster/postmaster.c:931 +#: postmaster/postmaster.c:836 #, c-format -msgid "WAL archival cannot be enabled when wal_level is \"minimal\"" -msgstr "el archivador de WAL no puede activarse cuando wal_level es «minimal»" +msgid "WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be \"replica\" or \"logical\"" +msgstr "el flujo de WAL («max_wal_senders» > 0) requiere que «wal_level» sea «replica» o «logical»" -#: postmaster/postmaster.c:934 +#: postmaster/postmaster.c:839 #, c-format -msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or \"logical\"" -msgstr "el flujo de WAL (max_wal_senders > 0) requiere wal_level «replica» o «logical»" +msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" +msgstr "no se puede sumarizar WAL cuando «wal_level» es «minimal»" -#: postmaster/postmaster.c:942 +#: postmaster/postmaster.c:847 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "%s: las tablas de palabras clave de fecha no son válidas, arréglelas\n" -#: postmaster/postmaster.c:1099 +#: postmaster/postmaster.c:1004 #, c-format msgid "could not create I/O completion port for child queue" msgstr "no se pudo crear el port E/S de reporte de completitud para la cola de procesos hijos" -#: postmaster/postmaster.c:1164 +#: postmaster/postmaster.c:1069 #, c-format msgid "ending log output to stderr" msgstr "terminando la salida de registro a stderr" -#: postmaster/postmaster.c:1165 +#: postmaster/postmaster.c:1070 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "La salida futura del registro será enviada al destino de log «%s»." -#: postmaster/postmaster.c:1176 +#: postmaster/postmaster.c:1081 #, c-format msgid "starting %s" msgstr "iniciando %s" -#: postmaster/postmaster.c:1236 +#: postmaster/postmaster.c:1143 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "no se pudo crear el socket de escucha para «%s»" -#: postmaster/postmaster.c:1242 +#: postmaster/postmaster.c:1149 #, c-format msgid "could not create any TCP/IP sockets" msgstr "no se pudo crear ningún socket TCP/IP" -#: postmaster/postmaster.c:1274 +#: postmaster/postmaster.c:1181 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "DNSServiceRegister() falló: código de error %ld" -#: postmaster/postmaster.c:1325 +#: postmaster/postmaster.c:1234 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "no se pudo crear el socket de dominio Unix en el directorio «%s»" -#: postmaster/postmaster.c:1331 +#: postmaster/postmaster.c:1240 #, c-format msgid "could not create any Unix-domain sockets" msgstr "no se pudo crear ningún socket de dominio Unix" -#: postmaster/postmaster.c:1342 +#: postmaster/postmaster.c:1251 #, c-format msgid "no socket created for listening" msgstr "no se creó el socket de atención" -#: postmaster/postmaster.c:1373 +#: postmaster/postmaster.c:1282 #, c-format -msgid "%s: could not change permissions of external PID file \"%s\": %s\n" -msgstr "%s: no se pudo cambiar los permisos del archivo de PID externo «%s»: %s\n" +msgid "%s: could not change permissions of external PID file \"%s\": %m\n" +msgstr "%s: no se pudo cambiar los permisos del archivo de PID externo «%s»: %m\n" -#: postmaster/postmaster.c:1377 +#: postmaster/postmaster.c:1286 #, c-format -msgid "%s: could not write external PID file \"%s\": %s\n" -msgstr "%s: no pudo escribir en el archivo externo de PID «%s»: %s\n" +msgid "%s: could not write external PID file \"%s\": %m\n" +msgstr "%s: no pudo escribir en el archivo externo de PID «%s»: %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1405 utils/init/postinit.c:221 -#, fuzzy, c-format -#| msgid "could not load locale \"%s\"" +#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 +#, c-format msgid "could not load %s" -msgstr "no se pudo cargar la configuración regional «%s»" +msgstr "no se pudo cargar %s" -#: postmaster/postmaster.c:1431 +#: postmaster/postmaster.c:1342 #, c-format msgid "postmaster became multithreaded during startup" msgstr "postmaster se volvió multi-hilo durante la partida" -#: postmaster/postmaster.c:1432 +#: postmaster/postmaster.c:1343 postmaster/postmaster.c:3684 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "Defina la variable de ambiente LC_ALL a un valor válido." -#: postmaster/postmaster.c:1533 +#: postmaster/postmaster.c:1442 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: no se pudo localizar la ruta de mi propio ejecutable" -#: postmaster/postmaster.c:1540 +#: postmaster/postmaster.c:1449 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: no se pudo localizar el ejecutable postgres correspondiente" -#: postmaster/postmaster.c:1563 utils/misc/tzparser.c:340 +#: postmaster/postmaster.c:1472 utils/misc/tzparser.c:341 #, c-format msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location." msgstr "Esto puede indicar una instalación de PostgreSQL incompleta, o que el archivo «%s» ha sido movido de la ubicación adecuada." -#: postmaster/postmaster.c:1590 +#: postmaster/postmaster.c:1499 #, c-format msgid "" "%s: could not find the database system\n" "Expected to find it in the directory \"%s\",\n" -"but could not open file \"%s\": %s\n" +"but could not open file \"%s\": %m\n" msgstr "" "%s: no se pudo encontrar el sistema de base de datos\n" "Se esperaba encontrar en el directorio PGDATA «%s»,\n" -"pero no se pudo abrir el archivo «%s»: %s\n" +"pero no se pudo abrir el archivo «%s»: %m\n" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1887 +#: postmaster/postmaster.c:1789 #, c-format msgid "issuing %s to recalcitrant children" -msgstr "" +msgstr "enviando %s a hijos recalcitrantes" -#: postmaster/postmaster.c:1909 +#: postmaster/postmaster.c:1811 #, c-format msgid "performing immediate shutdown because data directory lock file is invalid" msgstr "ejecutando un apagado inmediato porque el archivo de bloqueo del directorio de datos no es válido" -#: postmaster/postmaster.c:1984 postmaster/postmaster.c:2012 +#: postmaster/postmaster.c:1874 #, c-format -msgid "incomplete startup packet" -msgstr "el paquete de inicio está incompleto" +msgid "wrong key in cancel request for process %d" +msgstr "llave incorrecta en la petición de cancelación para el proceso %d" -#: postmaster/postmaster.c:1996 postmaster/postmaster.c:2029 +#: postmaster/postmaster.c:1886 #, c-format -msgid "invalid length of startup packet" -msgstr "el de paquete de inicio tiene largo incorrecto" +msgid "PID %d in cancel request did not match any process" +msgstr "el PID %d en la petición de cancelación no coincidió con ningún proceso" -#: postmaster/postmaster.c:2058 +#: postmaster/postmaster.c:2106 #, c-format -msgid "failed to send SSL negotiation response: %m" -msgstr "no se pudo enviar la respuesta de negociación SSL: %m" +msgid "received SIGHUP, reloading configuration files" +msgstr "se recibió SIGHUP, volviendo a cargar archivos de configuración" -#: postmaster/postmaster.c:2076 +#. translator: %s is a configuration file +#: postmaster/postmaster.c:2134 postmaster/postmaster.c:2138 #, c-format -msgid "received unencrypted data after SSL request" -msgstr "se recibieron datos no cifrados después de petición SSL" +msgid "%s was not reloaded" +msgstr "%s no fue vuelto a cargar" -#: postmaster/postmaster.c:2077 postmaster/postmaster.c:2121 +#: postmaster/postmaster.c:2148 #, c-format -msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." -msgstr "Esto podría ser un error en el software cliente o evidencia de un intento de ataque man-in-the-middle." +msgid "SSL configuration was not reloaded" +msgstr "la configuración SSL no fue vuelta a cargar" -#: postmaster/postmaster.c:2102 +#: postmaster/postmaster.c:2234 #, c-format -msgid "failed to send GSSAPI negotiation response: %m" -msgstr "no se pudo enviar la respuesta de negociación GSSAPI: %m" +msgid "received smart shutdown request" +msgstr "se recibió petición de apagado inteligente" -#: postmaster/postmaster.c:2120 +#: postmaster/postmaster.c:2275 #, c-format -msgid "received unencrypted data after GSSAPI encryption request" -msgstr "se recibieron datos no cifrados después de petición de cifrado GSSAPI" +msgid "received fast shutdown request" +msgstr "se recibió petición de apagado rápido" -#: postmaster/postmaster.c:2144 +#: postmaster/postmaster.c:2293 #, c-format -msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" -msgstr "el protocolo %u.%u no está soportado: servidor soporta %u.0 hasta %u.%u" +msgid "aborting any active transactions" +msgstr "abortando transacciones activas" -#: postmaster/postmaster.c:2211 -#, c-format -msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." -msgstr "Los valores válidos son: «false», 0, «true», 1, «database»." - -#: postmaster/postmaster.c:2252 -#, c-format -msgid "invalid startup packet layout: expected terminator as last byte" -msgstr "el paquete de inicio no es válido: se esperaba un terminador en el último byte" - -#: postmaster/postmaster.c:2269 -#, c-format -msgid "no PostgreSQL user name specified in startup packet" -msgstr "no se especifica un nombre de usuario en el paquete de inicio" - -#: postmaster/postmaster.c:2333 -#, c-format -msgid "the database system is starting up" -msgstr "el sistema de base de datos está iniciándose" - -#: postmaster/postmaster.c:2339 -#, c-format -msgid "the database system is not yet accepting connections" -msgstr "el sistema de bases de datos aún no está aceptando conexiones" - -#: postmaster/postmaster.c:2340 -#, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "Aún no se ha alcanzado un estado de recuperación consistente." - -#: postmaster/postmaster.c:2344 -#, c-format -msgid "the database system is not accepting connections" -msgstr "el sistema de bases de datos no está aceptando conexiones" - -#: postmaster/postmaster.c:2345 -#, c-format -msgid "Hot standby mode is disabled." -msgstr "El modo hot standby está desactivado." - -#: postmaster/postmaster.c:2350 -#, c-format -msgid "the database system is shutting down" -msgstr "el sistema de base de datos está apagándose" - -#: postmaster/postmaster.c:2355 -#, c-format -msgid "the database system is in recovery mode" -msgstr "el sistema de base de datos está en modo de recuperación" - -#: postmaster/postmaster.c:2360 storage/ipc/procarray.c:491 -#: storage/ipc/sinvaladt.c:306 storage/lmgr/proc.c:353 -#, c-format -msgid "sorry, too many clients already" -msgstr "lo siento, ya tenemos demasiados clientes" - -#: postmaster/postmaster.c:2447 -#, c-format -msgid "wrong key in cancel request for process %d" -msgstr "llave incorrecta en la petición de cancelación para el proceso %d" - -#: postmaster/postmaster.c:2459 -#, c-format -msgid "PID %d in cancel request did not match any process" -msgstr "el PID %d en la petición de cancelación no coincidió con ningún proceso" - -#: postmaster/postmaster.c:2726 -#, c-format -msgid "received SIGHUP, reloading configuration files" -msgstr "se recibió SIGHUP, volviendo a cargar archivos de configuración" - -#. translator: %s is a configuration file -#: postmaster/postmaster.c:2750 postmaster/postmaster.c:2754 -#, c-format -msgid "%s was not reloaded" -msgstr "%s no fue vuelto a cargar" - -#: postmaster/postmaster.c:2764 -#, c-format -msgid "SSL configuration was not reloaded" -msgstr "la configuración SSL no fue vuelta a cargar" - -#: postmaster/postmaster.c:2854 -#, c-format -msgid "received smart shutdown request" -msgstr "se recibió petición de apagado inteligente" - -#: postmaster/postmaster.c:2895 -#, c-format -msgid "received fast shutdown request" -msgstr "se recibió petición de apagado rápido" - -#: postmaster/postmaster.c:2913 -#, c-format -msgid "aborting any active transactions" -msgstr "abortando transacciones activas" - -#: postmaster/postmaster.c:2937 +#: postmaster/postmaster.c:2317 #, c-format msgid "received immediate shutdown request" msgstr "se recibió petición de apagado inmediato" -#: postmaster/postmaster.c:3013 +#: postmaster/postmaster.c:2389 #, c-format msgid "shutdown at recovery target" msgstr "apagándose al alcanzar el destino de recuperación" -#: postmaster/postmaster.c:3031 postmaster/postmaster.c:3067 +#: postmaster/postmaster.c:2407 postmaster/postmaster.c:2443 msgid "startup process" msgstr "proceso de inicio" -#: postmaster/postmaster.c:3034 +#: postmaster/postmaster.c:2410 #, c-format msgid "aborting startup due to startup process failure" msgstr "abortando el inicio debido a una falla en el procesamiento de inicio" -#: postmaster/postmaster.c:3107 +#: postmaster/postmaster.c:2485 #, c-format msgid "database system is ready to accept connections" msgstr "el sistema de bases de datos está listo para aceptar conexiones" -#: postmaster/postmaster.c:3128 +#: postmaster/postmaster.c:2506 msgid "background writer process" msgstr "proceso background writer" -#: postmaster/postmaster.c:3175 +#: postmaster/postmaster.c:2553 msgid "checkpointer process" msgstr "proceso checkpointer" -#: postmaster/postmaster.c:3191 +#: postmaster/postmaster.c:2569 msgid "WAL writer process" msgstr "proceso escritor de WAL" -#: postmaster/postmaster.c:3206 +#: postmaster/postmaster.c:2584 msgid "WAL receiver process" msgstr "proceso receptor de WAL" -#: postmaster/postmaster.c:3221 +#: postmaster/postmaster.c:2598 +msgid "WAL summarizer process" +msgstr "proceso sumarizador de WAL" + +#: postmaster/postmaster.c:2613 msgid "autovacuum launcher process" msgstr "proceso lanzador de autovacuum" -#: postmaster/postmaster.c:3239 +#: postmaster/postmaster.c:2631 msgid "archiver process" msgstr "proceso de archivado" -#: postmaster/postmaster.c:3252 +#: postmaster/postmaster.c:2644 msgid "system logger process" msgstr "proceso de log" -#: postmaster/postmaster.c:3309 +#: postmaster/postmaster.c:2661 +msgid "slot sync worker process" +msgstr "proceso sincronizador de slot" + +#: postmaster/postmaster.c:2717 #, c-format msgid "background worker \"%s\"" msgstr "proceso ayudante «%s»" -#: postmaster/postmaster.c:3388 postmaster/postmaster.c:3408 -#: postmaster/postmaster.c:3415 postmaster/postmaster.c:3433 +#: postmaster/postmaster.c:2796 postmaster/postmaster.c:2816 +#: postmaster/postmaster.c:2823 postmaster/postmaster.c:2841 msgid "server process" msgstr "proceso de servidor" -#: postmaster/postmaster.c:3487 +#: postmaster/postmaster.c:2895 #, c-format msgid "terminating any other active server processes" msgstr "terminando todos los otros procesos de servidor activos" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3662 +#: postmaster/postmaster.c:3082 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) terminó con código de salida %d" -#: postmaster/postmaster.c:3664 postmaster/postmaster.c:3676 -#: postmaster/postmaster.c:3686 postmaster/postmaster.c:3697 +#: postmaster/postmaster.c:3084 postmaster/postmaster.c:3096 +#: postmaster/postmaster.c:3106 postmaster/postmaster.c:3117 #, c-format msgid "Failed process was running: %s" msgstr "El proceso que falló estaba ejecutando: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3673 +#: postmaster/postmaster.c:3093 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) fue terminado por una excepción 0x%X" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3683 +#: postmaster/postmaster.c:3103 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) fue terminado por una señal %d: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3695 +#: postmaster/postmaster.c:3115 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d) terminó con código %d no reconocido" -#: postmaster/postmaster.c:3903 +#: postmaster/postmaster.c:3331 #, c-format msgid "abnormal database system shutdown" msgstr "apagado anormal del sistema de bases de datos" -#: postmaster/postmaster.c:3929 +#: postmaster/postmaster.c:3357 #, c-format msgid "shutting down due to startup process failure" msgstr "apagando debido a una falla en el procesamiento de inicio" -#: postmaster/postmaster.c:3935 +#: postmaster/postmaster.c:3363 #, c-format -msgid "shutting down because restart_after_crash is off" -msgstr "apagando debido a que restart_after_crash está desactivado" +msgid "shutting down because \"restart_after_crash\" is off" +msgstr "apagando debido a que «restart_after_crash» está desactivado" -#: postmaster/postmaster.c:3947 +#: postmaster/postmaster.c:3375 #, c-format msgid "all server processes terminated; reinitializing" msgstr "todos los procesos fueron terminados; reinicializando" -#: postmaster/postmaster.c:4141 postmaster/postmaster.c:5459 -#: postmaster/postmaster.c:5857 +#: postmaster/postmaster.c:3574 postmaster/postmaster.c:3985 +#: postmaster/postmaster.c:4374 #, c-format msgid "could not generate random cancel key" msgstr "no se pudo generar una llave de cancelación aleatoria" -#: postmaster/postmaster.c:4203 +#: postmaster/postmaster.c:3607 #, c-format msgid "could not fork new process for connection: %m" msgstr "no se pudo lanzar el nuevo proceso para la conexión: %m" -#: postmaster/postmaster.c:4245 +#: postmaster/postmaster.c:3649 msgid "could not fork new process for connection: " msgstr "no se pudo lanzar el nuevo proceso para la conexión: " -#: postmaster/postmaster.c:4351 -#, c-format -msgid "connection received: host=%s port=%s" -msgstr "conexión recibida: host=%s port=%s" - -#: postmaster/postmaster.c:4356 -#, c-format -msgid "connection received: host=%s" -msgstr "conexión recibida: host=%s" - -#: postmaster/postmaster.c:4593 -#, c-format -msgid "could not execute server process \"%s\": %m" -msgstr "no se pudo lanzar el proceso servidor «%s»: %m" - -#: postmaster/postmaster.c:4651 -#, c-format -msgid "could not create backend parameter file mapping: error code %lu" -msgstr "no se pudo crear mapeo de archivo de parámetros de servidor: código de error %lu" - -#: postmaster/postmaster.c:4660 -#, c-format -msgid "could not map backend parameter memory: error code %lu" -msgstr "no se pudo mapear memoria para parámetros de servidor: código de error %lu" - -#: postmaster/postmaster.c:4687 -#, c-format -msgid "subprocess command line too long" -msgstr "orden de subproceso demasiado larga" - -#: postmaster/postmaster.c:4705 -#, c-format -msgid "CreateProcess() call failed: %m (error code %lu)" -msgstr "llamada a CreateProcess() falló: %m (código de error %lu)" - -#: postmaster/postmaster.c:4732 -#, c-format -msgid "could not unmap view of backend parameter file: error code %lu" -msgstr "no se pudo desmapear la vista del archivo de parámetros de servidor: código de error %lu" - -#: postmaster/postmaster.c:4736 -#, c-format -msgid "could not close handle to backend parameter file: error code %lu" -msgstr "no se pudo cerrar el archivo de parámetros de servidor: código de error %lu" - -#: postmaster/postmaster.c:4758 -#, c-format -msgid "giving up after too many tries to reserve shared memory" -msgstr "renunciar después de demasiados intentos de reservar memoria compartida" - -#: postmaster/postmaster.c:4759 -#, c-format -msgid "This might be caused by ASLR or antivirus software." -msgstr "Esto podría deberse a ASLR o un software antivirus." - -#: postmaster/postmaster.c:4932 -#, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "No se pudo cargar la configuración SSL en proceso secundario" - -#: postmaster/postmaster.c:5057 +#: postmaster/postmaster.c:3683 #, c-format -msgid "Please report this to <%s>." -msgstr "Por favor reporte esto a <%s>." +#| msgid "postmaster became multithreaded during startup" +msgid "postmaster became multithreaded" +msgstr "postmaster se volvió multi-hilo" -#: postmaster/postmaster.c:5125 +#: postmaster/postmaster.c:3752 #, c-format msgid "database system is ready to accept read-only connections" msgstr "el sistema de bases de datos está listo para aceptar conexiones de sólo lectura" -#: postmaster/postmaster.c:5383 -#, c-format -msgid "could not fork startup process: %m" -msgstr "no se pudo lanzar el proceso de inicio: %m" - -#: postmaster/postmaster.c:5387 -#, c-format -msgid "could not fork archiver process: %m" -msgstr "no se pudo lanzar el proceso de archivado: %m" - -#: postmaster/postmaster.c:5391 -#, c-format -msgid "could not fork background writer process: %m" -msgstr "no se pudo lanzar el background writer: %m" - -#: postmaster/postmaster.c:5395 -#, c-format -msgid "could not fork checkpointer process: %m" -msgstr "no se pudo lanzar el checkpointer: %m" - -#: postmaster/postmaster.c:5399 -#, c-format -msgid "could not fork WAL writer process: %m" -msgstr "no se pudo lanzar el proceso escritor de WAL: %m" - -#: postmaster/postmaster.c:5403 -#, c-format -msgid "could not fork WAL receiver process: %m" -msgstr "no se pudo lanzar el proceso receptor de WAL: %m" - -#: postmaster/postmaster.c:5407 +#: postmaster/postmaster.c:3935 #, c-format -msgid "could not fork process: %m" -msgstr "no se pudo lanzar el proceso: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "no se pudo lanzar el proceso «%s»: %m" -#: postmaster/postmaster.c:5608 postmaster/postmaster.c:5635 +#: postmaster/postmaster.c:4173 postmaster/postmaster.c:4207 #, c-format msgid "database connection requirement not indicated during registration" msgstr "el requerimiento de conexión a base de datos no fue indicado durante el registro" -#: postmaster/postmaster.c:5619 postmaster/postmaster.c:5646 +#: postmaster/postmaster.c:4183 postmaster/postmaster.c:4217 #, c-format msgid "invalid processing mode in background worker" msgstr "modo de procesamiento no válido en proceso ayudante" -#: postmaster/postmaster.c:5731 +#: postmaster/postmaster.c:4277 #, c-format -msgid "could not fork worker process: %m" -msgstr "no se pudo lanzar el proceso ayudante: %m" +msgid "could not fork background worker process: %m" +msgstr "no se pudo lanzar el background writer: %m" -#: postmaster/postmaster.c:5843 +#: postmaster/postmaster.c:4360 #, c-format -msgid "no slot available for new worker process" +msgid "no slot available for new background worker process" msgstr "no hay slot disponible para un nuevo proceso ayudante" -#: postmaster/postmaster.c:6174 -#, c-format -msgid "could not duplicate socket %d for use in backend: error code %d" -msgstr "no se pudo duplicar el socket %d para su empleo en el backend: código de error %d" - -#: postmaster/postmaster.c:6206 -#, c-format -msgid "could not create inherited socket: error code %d\n" -msgstr "no se pudo crear el socket heradado: código de error %d\n" - -#: postmaster/postmaster.c:6235 -#, c-format -msgid "could not open backend variables file \"%s\": %s\n" -msgstr "no se pudo abrir el archivo de variables de servidor «%s»: %s\n" - -#: postmaster/postmaster.c:6242 -#, c-format -msgid "could not read from backend variables file \"%s\": %s\n" -msgstr "no se pudo leer el archivo de variables de servidor «%s»: %s\n" - -#: postmaster/postmaster.c:6251 -#, c-format -msgid "could not remove file \"%s\": %s\n" -msgstr "no se pudo eliminar el archivo «%s»: %s\n" - -#: postmaster/postmaster.c:6268 -#, c-format -msgid "could not map view of backend variables: error code %lu\n" -msgstr "no se pudo mapear la vista del archivo de variables: código de error %lu\n" - -#: postmaster/postmaster.c:6277 -#, c-format -msgid "could not unmap view of backend variables: error code %lu\n" -msgstr "no se pudo desmapear la vista del archivo de variables: código de error %lu\n" - -#: postmaster/postmaster.c:6284 -#, c-format -msgid "could not close handle to backend parameter variables: error code %lu\n" -msgstr "no se pudo cerrar el archivo de variables de servidor: código de error %lu\n" - -#: postmaster/postmaster.c:6443 +#: postmaster/postmaster.c:4623 #, c-format msgid "could not read exit code for process\n" msgstr "no se pudo leer el código de salida del proceso\n" -#: postmaster/postmaster.c:6485 +#: postmaster/postmaster.c:4665 #, c-format msgid "could not post child completion status\n" msgstr "no se pudo publicar el estado de completitud del proceso hijo\n" -#: postmaster/syslogger.c:501 postmaster/syslogger.c:1222 +#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 #, c-format msgid "could not read from logger pipe: %m" msgstr "no se pudo leer desde la tubería de log: %m" -#: postmaster/syslogger.c:598 postmaster/syslogger.c:612 +#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 #, c-format msgid "could not create pipe for syslog: %m" msgstr "no se pudo crear la tubería para syslog: %m" -#: postmaster/syslogger.c:677 +#: postmaster/syslogger.c:712 #, c-format msgid "could not fork system logger: %m" msgstr "no se pudo crear el proceso de log: %m" -#: postmaster/syslogger.c:713 +#: postmaster/syslogger.c:731 #, c-format msgid "redirecting log output to logging collector process" msgstr "redirigiendo la salida del registro al proceso recolector de registro" -#: postmaster/syslogger.c:714 +#: postmaster/syslogger.c:732 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "La salida futura del registro aparecerá en el directorio «%s»." -#: postmaster/syslogger.c:722 +#: postmaster/syslogger.c:740 #, c-format msgid "could not redirect stdout: %m" msgstr "no se pudo redirigir stdout: %m" -#: postmaster/syslogger.c:727 postmaster/syslogger.c:744 +#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 #, c-format msgid "could not redirect stderr: %m" msgstr "no se pudo redirigir stderr: %m" -#: postmaster/syslogger.c:1177 +#: postmaster/syslogger.c:1128 #, c-format -msgid "could not write to log file: %s\n" -msgstr "no se pudo escribir al archivo de log: %s\n" +msgid "could not write to log file: %m\n" +msgstr "no se pudo escribir al archivo de log: %m\n" -#: postmaster/syslogger.c:1295 +#: postmaster/syslogger.c:1246 #, c-format msgid "could not open log file \"%s\": %m" msgstr "no se pudo abrir el archivo de registro «%s»: %m" -#: postmaster/syslogger.c:1385 +#: postmaster/syslogger.c:1336 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "desactivando rotación automática (use SIGHUP para reactivarla)" -#: regex/regc_pg_locale.c:242 +#: postmaster/walsummarizer.c:740 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "la sumarización de WAL no está progresando" + +#: postmaster/walsummarizer.c:741 +#, c-format +msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." +msgstr "La sumarización de WAL se necesita hasta %X/%X, pero está detenido en %X/%X en disco y %X/%X en memoria." + +#: postmaster/walsummarizer.c:755 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "todavía esperando al resumen de WAL hasta %X/%X después de %ld segundo" +msgstr[1] "todavía esperando al resumen de WAL hasta %X/%X después de %ld segundos" + +#: postmaster/walsummarizer.c:760 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "El resumen ha alcanzado %X/%X en disco y %X/%X en memoria." + +#: postmaster/walsummarizer.c:1000 +#, c-format +msgid "could not find a valid record after %X/%X" +msgstr "no se pudo encontrar un registro válido después de %X/%X" + +#: postmaster/walsummarizer.c:1045 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X: %s" +msgstr "no se pudo leer WAL del timeline %u en %X/%X: %s" + +#: postmaster/walsummarizer.c:1051 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X" +msgstr "no se pudo leer WAL del timeline %u en %X/%X" + +#: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "no se pudo determinar qué ordenamiento usar para la expresión regular" -#: regex/regc_pg_locale.c:265 +#: regex/regc_pg_locale.c:262 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "los ordenamientos no determinísticos no están soportados para expresiones regulares" -#: replication/libpqwalreceiver/libpqwalreceiver.c:197 -#: replication/libpqwalreceiver/libpqwalreceiver.c:280 -#, fuzzy, c-format -#| msgid "redo is not required" +#: replication/libpqwalreceiver/libpqwalreceiver.c:267 +#: replication/libpqwalreceiver/libpqwalreceiver.c:358 +#, c-format msgid "password is required" -msgstr "no se requiere redo" +msgstr "una contraseña es requerida" -#: replication/libpqwalreceiver/libpqwalreceiver.c:198 +#: replication/libpqwalreceiver/libpqwalreceiver.c:268 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." -msgstr "" +msgstr "No-superusuario no se puede conectar si el servidor no pide una constraseña." -#: replication/libpqwalreceiver/libpqwalreceiver.c:199 +#: replication/libpqwalreceiver/libpqwalreceiver.c:269 #, c-format -msgid "Target server's authentication method must be changed. or set password_required=false in the subscription attributes." -msgstr "" +msgid "Target server's authentication method must be changed, or set password_required=false in the subscription parameters." +msgstr "El método de autenticación del servidor de destino debe cambiarse, o definir password_required=false en los parámetros de suscripción." -#: replication/libpqwalreceiver/libpqwalreceiver.c:211 +#: replication/libpqwalreceiver/libpqwalreceiver.c:285 #, c-format msgid "could not clear search path: %s" msgstr "no se pudo limpiar la ruta de búsqueda: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:257 +#: replication/libpqwalreceiver/libpqwalreceiver.c:331 +#: replication/libpqwalreceiver/libpqwalreceiver.c:517 #, c-format msgid "invalid connection string syntax: %s" msgstr "sintaxis de cadena de conexión no válida: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:281 +#: replication/libpqwalreceiver/libpqwalreceiver.c:359 #, c-format msgid "Non-superusers must provide a password in the connection string." -msgstr "" +msgstr "No-superusuario debe proveer una contraseña en la cadena de conexión." -#: replication/libpqwalreceiver/libpqwalreceiver.c:307 +#: replication/libpqwalreceiver/libpqwalreceiver.c:386 #, c-format msgid "could not parse connection string: %s" msgstr "no se pudo interpretar la cadena de conexión: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:380 +#: replication/libpqwalreceiver/libpqwalreceiver.c:459 #, c-format msgid "could not receive database system identifier and timeline ID from the primary server: %s" msgstr "no se pudo recibir el identificador de sistema y el ID de timeline del servidor primario: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:392 -#: replication/libpqwalreceiver/libpqwalreceiver.c:635 +#: replication/libpqwalreceiver/libpqwalreceiver.c:476 +#: replication/libpqwalreceiver/libpqwalreceiver.c:763 #, c-format msgid "invalid response from primary server" msgstr "respuesta no válida del servidor primario" -#: replication/libpqwalreceiver/libpqwalreceiver.c:393 +#: replication/libpqwalreceiver/libpqwalreceiver.c:477 #, c-format msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields." msgstr "No se pudo identificar el sistema: se obtuvieron %d filas y %d campos, se esperaban %d filas y %d o más campos." -#: replication/libpqwalreceiver/libpqwalreceiver.c:478 -#: replication/libpqwalreceiver/libpqwalreceiver.c:485 -#: replication/libpqwalreceiver/libpqwalreceiver.c:515 +#: replication/libpqwalreceiver/libpqwalreceiver.c:606 +#: replication/libpqwalreceiver/libpqwalreceiver.c:613 +#: replication/libpqwalreceiver/libpqwalreceiver.c:643 #, c-format msgid "could not start WAL streaming: %s" msgstr "no se pudo iniciar el flujo de WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:539 +#: replication/libpqwalreceiver/libpqwalreceiver.c:667 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "no se pudo enviar el mensaje fin-de-flujo al primario: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:562 +#: replication/libpqwalreceiver/libpqwalreceiver.c:690 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "conjunto de resultados inesperado después del fin-de-flujo" -#: replication/libpqwalreceiver/libpqwalreceiver.c:577 +#: replication/libpqwalreceiver/libpqwalreceiver.c:705 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "ocurrió un error mientras se apagaba el flujo COPY: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:587 +#: replication/libpqwalreceiver/libpqwalreceiver.c:715 #, c-format msgid "error reading result of streaming command: %s" msgstr "ocurrió un error mientras se leía la orden de flujo: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:596 -#: replication/libpqwalreceiver/libpqwalreceiver.c:832 +#: replication/libpqwalreceiver/libpqwalreceiver.c:724 +#: replication/libpqwalreceiver/libpqwalreceiver.c:957 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "resultado inesperado después de CommandComplete: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:623 +#: replication/libpqwalreceiver/libpqwalreceiver.c:751 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "no se pudo recibir el archivo de historia de timeline del servidor primario: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:636 +#: replication/libpqwalreceiver/libpqwalreceiver.c:764 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "Se esperaba 1 tupla con 2 campos, se obtuvieron %d tuplas con %d campos." -#: replication/libpqwalreceiver/libpqwalreceiver.c:795 -#: replication/libpqwalreceiver/libpqwalreceiver.c:848 -#: replication/libpqwalreceiver/libpqwalreceiver.c:855 +#: replication/libpqwalreceiver/libpqwalreceiver.c:920 +#: replication/libpqwalreceiver/libpqwalreceiver.c:973 +#: replication/libpqwalreceiver/libpqwalreceiver.c:980 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "no se pudo recibir datos desde el flujo de WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:875 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 #, c-format msgid "could not send data to WAL stream: %s" msgstr "no se pudo enviar datos al flujo de WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:967 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 #, c-format msgid "could not create replication slot \"%s\": %s" -msgstr "no se pudo create el slot de replicación «%s»: %s" +msgstr "no se pudo crear el slot de replicación «%s»: %s" + +#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#, c-format +msgid "could not alter replication slot \"%s\": %s" +msgstr "no se pudo alterar el slot de replicación «%s»: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1013 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 #, c-format msgid "invalid query response" msgstr "respuesta no válida a consulta" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1014 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 #, c-format msgid "Expected %d fields, got %d fields." msgstr "Se esperaban %d campos, se obtuvieron %d campos." -#: replication/libpqwalreceiver/libpqwalreceiver.c:1084 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 #, c-format msgid "the query interface requires a database connection" msgstr "la interfaz de consulta requiere una conexión a base de datos" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1115 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 msgid "empty query" msgstr "consulta vacía" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1121 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 msgid "unexpected pipeline mode" msgstr "modo pipeline inesperado" #: replication/logical/applyparallelworker.c:719 -#, fuzzy, c-format -#| msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" +#, c-format msgid "logical replication parallel apply worker for subscription \"%s\" has finished" -msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha terminado" +msgstr "el ayudante paralelo «apply» de replicación lógica para la suscripción «%s» ha terminado" -#: replication/logical/applyparallelworker.c:825 -#, fuzzy, c-format -#| msgid "lost connection to parallel worker" +#: replication/logical/applyparallelworker.c:822 +#, c-format msgid "lost connection to the logical replication apply worker" -msgstr "se ha perdido la conexión al ayudante paralelo" - -#: replication/logical/applyparallelworker.c:893 -#, fuzzy, c-format -#| msgid "could not map dynamic shared memory segment" -msgid "unable to map dynamic shared memory segment" -msgstr "no se pudo mapear el segmento de memoria compartida dinámica" +msgstr "se ha perdido la conexión al ayudante paralelo “apply” de replicación" -#: replication/logical/applyparallelworker.c:899 -#, fuzzy, c-format -#| msgid "invalid magic number in dynamic shared memory segment" -msgid "bad magic number in dynamic shared memory segment" -msgstr "número mágico no válido en segmento de memoria compartida dinámica" - -#: replication/logical/applyparallelworker.c:1027 -#: replication/logical/applyparallelworker.c:1029 -#: replication/logical/worker.c:447 -#, fuzzy -#| msgid "lost connection to parallel worker" +#: replication/logical/applyparallelworker.c:1024 +#: replication/logical/applyparallelworker.c:1026 msgid "logical replication parallel apply worker" -msgstr "se ha perdido la conexión al ayudante paralelo" +msgstr "ayudante paralelo “apply” de replicación lógica" -#: replication/logical/applyparallelworker.c:1043 -#, fuzzy, c-format -#| msgid "terminating logical replication worker due to timeout" +#: replication/logical/applyparallelworker.c:1040 +#, c-format msgid "logical replication parallel apply worker exited due to error" -msgstr "terminando el proceso de replicación lógica debido a que se agotó el tiempo de espera" +msgstr "el ayudante paralelo “apply” de replicación lógica terminó debido a un error" -#: replication/logical/applyparallelworker.c:1130 -#: replication/logical/applyparallelworker.c:1303 -#, fuzzy, c-format -#| msgid "lost connection to parallel worker" +#: replication/logical/applyparallelworker.c:1127 +#: replication/logical/applyparallelworker.c:1300 +#, c-format msgid "lost connection to the logical replication parallel apply worker" -msgstr "se ha perdido la conexión al ayudante paralelo" +msgstr "se perdió la conexión al ayudante paralelo “apply” de replicación lógica" -#: replication/logical/applyparallelworker.c:1183 -#, fuzzy, c-format -#| msgid "could not send tuple to shared-memory queue" +#: replication/logical/applyparallelworker.c:1180 +#, c-format msgid "could not send data to shared-memory queue" -msgstr "no se pudo enviar la tupla a la cola en memoria compartida" +msgstr "no se pudo enviar datos a la cola en memoria compartida" -#: replication/logical/applyparallelworker.c:1218 +#: replication/logical/applyparallelworker.c:1215 #, c-format msgid "logical replication apply worker will serialize the remaining changes of remote transaction %u to a file" -msgstr "" +msgstr "el ayudante paralelo «apply» de replicación lógica serializará los cambios restantes de la transacción remota %u a un archivo" # FIXME see slot.c:779. See also postmaster.c:835 -#: replication/logical/decode.c:180 replication/logical/logical.c:140 -#, fuzzy, c-format -#| msgid "logical decoding requires wal_level >= logical" -msgid "logical decoding on standby requires wal_level >= logical on the primary" -msgstr "la decodificación lógica requiere wal_level >= logical" +#: replication/logical/decode.c:177 replication/logical/logical.c:141 +#, c-format +msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" +msgstr "la decodificación lógica en standby requiere «wal_level» >= «logical» en el primario" -#: replication/logical/launcher.c:331 +#: replication/logical/launcher.c:334 #, c-format msgid "cannot start logical replication workers when max_replication_slots = 0" -msgstr "no se pueden iniciar procesos ayudantes de replicación cuando max_replication_slots = 0" +msgstr "no se pueden iniciar procesos ayudantes de replicación lógica cuando max_replication_slots = 0" -#: replication/logical/launcher.c:424 +#: replication/logical/launcher.c:427 #, c-format msgid "out of logical replication worker slots" -msgstr "se agotaron los slots de procesos ayudantes de replicación" +msgstr "se agotaron los slots de procesos ayudantes de replicación lógica" -#: replication/logical/launcher.c:425 +#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 +#: replication/slot.c:1524 storage/lmgr/lock.c:985 storage/lmgr/lock.c:1023 +#: storage/lmgr/lock.c:2836 storage/lmgr/lock.c:4221 storage/lmgr/lock.c:4286 +#: storage/lmgr/lock.c:4636 storage/lmgr/predicate.c:2469 +#: storage/lmgr/predicate.c:2484 storage/lmgr/predicate.c:3881 #, c-format -msgid "You might need to increase max_logical_replication_workers." -msgstr "Puede ser necesario incrementar max_logical_replication_workers." +msgid "You might need to increase \"%s\"." +msgstr "Puede ser necesario incrementar «%s»." -#: replication/logical/launcher.c:498 +#: replication/logical/launcher.c:513 #, c-format msgid "out of background worker slots" msgstr "se acabaron los slots de procesos ayudante" -#: replication/logical/launcher.c:499 -#, c-format -msgid "You might need to increase max_worker_processes." -msgstr "Puede ser necesario incrementar max_worker_processes." - -#: replication/logical/launcher.c:705 +#: replication/logical/launcher.c:720 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "el slot del worker de replicación lógica %d está vacío, no se puede adjuntar" -#: replication/logical/launcher.c:714 +#: replication/logical/launcher.c:729 #, c-format msgid "logical replication worker slot %d is already used by another worker, cannot attach" msgstr "el slot de replicación lógica %d ya está siendo utilizado por otro worker, no se puede adjuntar" # FIXME see slot.c:779. See also postmaster.c:835 -#: replication/logical/logical.c:120 +#: replication/logical/logical.c:121 #, c-format -msgid "logical decoding requires wal_level >= logical" -msgstr "la decodificación lógica requiere wal_level >= logical" +msgid "logical decoding requires \"wal_level\" >= \"logical\"" +msgstr "la decodificación lógica requiere «wal_level» >= «logical»" -#: replication/logical/logical.c:125 +#: replication/logical/logical.c:126 #, c-format msgid "logical decoding requires a database connection" msgstr "decodificación lógica requiere una conexión a una base de datos" -#: replication/logical/logical.c:363 replication/logical/logical.c:517 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "no se puede usar un slot de replicación física para decodificación lógica" -#: replication/logical/logical.c:368 replication/logical/logical.c:522 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "el slot de replicación «%s» no fue creado en esta base de datos" -#: replication/logical/logical.c:375 +#: replication/logical/logical.c:377 #, c-format msgid "cannot create logical replication slot in transaction that has performed writes" msgstr "no se puede crear un slot de replicación lógica en una transacción que ha efectuado escrituras" -#: replication/logical/logical.c:534 replication/logical/logical.c:541 +#: replication/logical/logical.c:540 +#, c-format +msgid "cannot use replication slot \"%s\" for logical decoding" +msgstr "no se puede usar el slot de replicación «%s» para decodificación lógica" + +#: replication/logical/logical.c:542 replication/slot.c:798 +#: replication/slot.c:829 +#, c-format +msgid "This replication slot is being synchronized from the primary server." +msgstr "Este slot de replicación está siendo sincronizado desde el servidor primario." + +#: replication/logical/logical.c:543 +#, c-format +msgid "Specify another replication slot." +msgstr "Especifique otro slot de replicación." + +#: replication/logical/logical.c:554 replication/logical/logical.c:561 #, c-format msgid "can no longer get changes from replication slot \"%s\"" msgstr "ya no se pueden recibir cambios desde el slot de replicación «%s»" -#: replication/logical/logical.c:536 +#: replication/logical/logical.c:556 #, c-format msgid "This slot has been invalidated because it exceeded the maximum reserved size." msgstr "Este slot ha sido invalidado porque excedió el máximo del tamaño de reserva." -#: replication/logical/logical.c:543 -#, fuzzy, c-format -#| msgid "This slot has been invalidated because it exceeded the maximum reserved size." +#: replication/logical/logical.c:563 +#, c-format msgid "This slot has been invalidated because it was conflicting with recovery." -msgstr "Este slot ha sido invalidado porque excedió el máximo del tamaño de reserva." +msgstr "Este slot ha sido invalidado porque estaba en conflicto con la recuperación." -#: replication/logical/logical.c:608 +#: replication/logical/logical.c:628 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "iniciando la decodificación lógica para el slot «%s»" -#: replication/logical/logical.c:610 +#: replication/logical/logical.c:630 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "Transacciones en flujo comprometiendo después de %X/%X, leyendo WAL desde %X/%X." -#: replication/logical/logical.c:758 +#: replication/logical/logical.c:778 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "slot «%s», plugin de salida «%s», en el callback %s, LSN asociado %X/%X" # FIXME must quote callback name? Need a translator: comment? -#: replication/logical/logical.c:764 +#: replication/logical/logical.c:784 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "slot «%s», plugin de salida «%s», en el callback %s" -#: replication/logical/logical.c:935 replication/logical/logical.c:980 -#: replication/logical/logical.c:1025 replication/logical/logical.c:1071 +#: replication/logical/logical.c:955 replication/logical/logical.c:1000 +#: replication/logical/logical.c:1045 replication/logical/logical.c:1091 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "durante la preparación, la replicación lógica requiere una función callback %s" -#: replication/logical/logical.c:1303 replication/logical/logical.c:1352 -#: replication/logical/logical.c:1393 replication/logical/logical.c:1479 -#: replication/logical/logical.c:1528 +#: replication/logical/logical.c:1323 replication/logical/logical.c:1372 +#: replication/logical/logical.c:1413 replication/logical/logical.c:1499 +#: replication/logical/logical.c:1548 #, c-format msgid "logical streaming requires a %s callback" msgstr "el flujo lógico requiere una función callback %s" -#: replication/logical/logical.c:1438 +#: replication/logical/logical.c:1458 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "durante la preparación, el flujo lógico requiere una función callback %s" -#: replication/logical/logicalfuncs.c:126 +#: replication/logical/logicalfuncs.c:123 #, c-format msgid "slot name must not be null" msgstr "el nombre de slot no debe ser null" -#: replication/logical/logicalfuncs.c:142 +#: replication/logical/logicalfuncs.c:139 #, c-format msgid "options array must not be null" msgstr "el array de opciones no debe ser null" -#: replication/logical/logicalfuncs.c:159 +#: replication/logical/logicalfuncs.c:156 #, c-format msgid "array must be one-dimensional" msgstr "el array debe ser unidimensional" -#: replication/logical/logicalfuncs.c:165 +#: replication/logical/logicalfuncs.c:162 #, c-format msgid "array must not contain nulls" msgstr "el array no debe contener nulls" -#: replication/logical/logicalfuncs.c:180 utils/adt/json.c:1484 -#: utils/adt/jsonb.c:1403 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1420 +#: utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "el array debe tener un número par de elementos" -#: replication/logical/logicalfuncs.c:227 +#: replication/logical/logicalfuncs.c:224 #, c-format msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data" msgstr "el plugin de salida de decodificación lógica «%s» produce salida binaria, pero «%s» espera datos textuales" #: replication/logical/origin.c:190 #, c-format -msgid "cannot query or manipulate replication origin when max_replication_slots = 0" -msgstr "no se puede consultar o manipular orígenes de replicación cuando max_replication_slots = 0" +msgid "cannot query or manipulate replication origin when \"max_replication_slots\" is 0" +msgstr "no se puede consultar o manipular orígenes de replicación cuando «max_replication_slots» = 0" #: replication/logical/origin.c:195 #, c-format @@ -20167,22 +20422,19 @@ msgid "replication origin \"%s\" does not exist" msgstr "no existe el origen de replicación «%s»" #: replication/logical/origin.c:331 -#, fuzzy, c-format -#| msgid "could not create replication slot \"%s\": %s" +#, c-format msgid "could not find free replication origin ID" -msgstr "no se pudo create el slot de replicación «%s»: %s" +msgstr "no se pudo encontrar un ID de origen de replicación disponible" #: replication/logical/origin.c:365 -#, fuzzy, c-format -#| msgid "could not drop replication slot \"%s\" on publisher: %s" +#, c-format msgid "could not drop replication origin with ID %d, in use by PID %d" -msgstr "no se pudo eliminar el slot de replicación «%s» en editor (publisher): %s" +msgstr "no se pudo eliminar el origen de replicación con ID %d, en uso por el PID %d" #: replication/logical/origin.c:492 -#, fuzzy, c-format -#| msgid "replication origin \"%s\" does not exist" +#, c-format msgid "replication origin with ID %d does not exist" -msgstr "no existe el origen de replicación «%s»" +msgstr "no existe el origen de replicación con ID %d" #: replication/logical/origin.c:757 #, c-format @@ -20191,1319 +20443,1582 @@ msgstr "el checkpoint de replicación tiene número mágico erróneo %u en lugar #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase max_replication_slots" -msgstr "no se pudo encontrar una estructura de replicación libre, incremente max_replication_slots" +msgid "could not find free replication state, increase \"max_replication_slots\"" +msgstr "no se pudo encontrar una estructura de replicación libre, incremente «max_replication_slots»" #: replication/logical/origin.c:806 -#, fuzzy, c-format -#| msgid "recovery restart point at %X/%X" +#, c-format msgid "recovered replication state of node %d to %X/%X" -msgstr "restartpoint de recuperación en %X/%X" +msgstr "recuperado el estado de replicación del nodo %d a %X/%X" #: replication/logical/origin.c:816 #, c-format msgid "replication slot checkpoint has wrong checksum %u, expected %u" msgstr "el checkpoint del slot de replicación tiene suma de verificación errónea %u, se esperaba %u" -#: replication/logical/origin.c:944 replication/logical/origin.c:1141 -#, fuzzy, c-format -#| msgid "replication slot \"%s\" is active for PID %d" +#: replication/logical/origin.c:944 replication/logical/origin.c:1143 +#, c-format msgid "replication origin with ID %d is already active for PID %d" -msgstr "el slot de replicación «%s» está activo para el PID %d" +msgstr "el origen de replicación con ID %d está activo para el PID %d" -#: replication/logical/origin.c:955 replication/logical/origin.c:1153 -#, fuzzy, c-format -#| msgid "could not find free replication state, increase max_replication_slots" +#: replication/logical/origin.c:955 replication/logical/origin.c:1156 +#, c-format msgid "could not find free replication state slot for replication origin with ID %d" -msgstr "no se pudo encontrar una estructura de replicación libre, incremente max_replication_slots" +msgstr "no se pudo encontrar una estructura de replicación libre para el origen de replicación con el ID %d" -#: replication/logical/origin.c:957 replication/logical/origin.c:1155 -#: replication/slot.c:2086 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 +#: replication/slot.c:2384 #, c-format -msgid "Increase max_replication_slots and try again." -msgstr "Aumente max_replication_slots y reintente." +msgid "Increase \"max_replication_slots\" and try again." +msgstr "Aumente «max_replication_slots» y reintente." -#: replication/logical/origin.c:1112 +#: replication/logical/origin.c:1114 #, c-format msgid "cannot setup replication origin when one is already setup" msgstr "no se puede establecer un destino de replicación cuando ya hay uno definido" -#: replication/logical/origin.c:1196 replication/logical/origin.c:1412 -#: replication/logical/origin.c:1432 +#: replication/logical/origin.c:1199 replication/logical/origin.c:1415 +#: replication/logical/origin.c:1435 #, c-format msgid "no replication origin is configured" msgstr "no hay un destino de replicación configurado" -#: replication/logical/origin.c:1282 +#: replication/logical/origin.c:1285 #, c-format msgid "replication origin name \"%s\" is reserved" msgstr "el nombre de origen de replicación «%s» está reservado" -#: replication/logical/origin.c:1284 -#, fuzzy, c-format -#| msgid "Role names starting with \"pg_\" are reserved." +#: replication/logical/origin.c:1287 +#, c-format msgid "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." -msgstr "Los nombres de rol que empiezan con «pg_» están reservados." +msgstr "Los nombres de origen «%s», «%s» y los que empiezan con «pg_» están reservados." -#: replication/logical/relation.c:240 +#: replication/logical/relation.c:242 #, c-format msgid "\"%s\"" msgstr "«%s»" -#: replication/logical/relation.c:243 +#: replication/logical/relation.c:245 #, c-format msgid ", \"%s\"" msgstr ", «%s»" -#: replication/logical/relation.c:249 +#: replication/logical/relation.c:251 #, c-format msgid "logical replication target relation \"%s.%s\" is missing replicated column: %s" msgid_plural "logical replication target relation \"%s.%s\" is missing replicated columns: %s" msgstr[0] "a la relación destino de replicación lógica «%s.%s» le falta la columna replicada: %s" msgstr[1] "a la relación destino de replicación lógica «%s.%s» le faltan las columnas replicadas: %s" -#: replication/logical/relation.c:304 +#: replication/logical/relation.c:306 #, c-format msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index" msgstr "la relación de destino de replicación lógica «%s.%s» usa columnas de sistemas en el índice REPLICA IDENTITY" -#: replication/logical/relation.c:396 +#: replication/logical/relation.c:398 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "la relación destino de replicación lógica «%s.%s» no existe" -#: replication/logical/reorderbuffer.c:3936 +#: replication/logical/reorderbuffer.c:3999 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "no se pudo escribir al archivo de datos para el XID %u: %m" -#: replication/logical/reorderbuffer.c:4282 -#: replication/logical/reorderbuffer.c:4307 +#: replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4370 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "no se pudo leer desde el archivo de desborde de reorderbuffer: %m" -#: replication/logical/reorderbuffer.c:4286 -#: replication/logical/reorderbuffer.c:4311 +#: replication/logical/reorderbuffer.c:4349 +#: replication/logical/reorderbuffer.c:4374 #, c-format msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "no se pudo leer desde el archivo de desborde de reorderbuffer: se leyeron sólo %d en ve de %u bytes" -#: replication/logical/reorderbuffer.c:4561 +#: replication/logical/reorderbuffer.c:4624 #, c-format msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" msgstr "no se pudo borrar el archivo «%s» durante la eliminación de pg_replslot/%s/xid*: %m" # FIXME almost duplicated again!? -#: replication/logical/reorderbuffer.c:5057 +#: replication/logical/reorderbuffer.c:5120 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "no se pudo leer del archivo «%s»: se leyeron %d en lugar de %d bytes" -#: replication/logical/snapbuild.c:639 +#: replication/logical/slotsync.c:215 +#, c-format +msgid "could not synchronize replication slot \"%s\" because remote slot precedes local slot" +msgstr "no se puede sincronizar el slot de replicación «%s» porque el slot remoto precede al slot local" + +#: replication/logical/slotsync.c:217 +#, c-format +msgid "The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u." +msgstr "El slot remoto tiene LSN %X/%X y xmin de catálogo %u, pero el slot local tiene LSN %X/%X y xmin de catálogo %u." + +#: replication/logical/slotsync.c:459 +#, c-format +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "se eliminó el slot de replicación «%s» de la base de datos con OID %u" + +#: replication/logical/slotsync.c:579 +#, c-format +msgid "could not synchronize replication slot \"%s\"" +msgstr "no se pudo sincronizar el slot de replicación «%s»" + +#: replication/logical/slotsync.c:580 +#, c-format +msgid "Logical decoding could not find consistent point from local slot's LSN %X/%X." +msgstr "La decodificación lógica no pudo encontrar un punto consistente desde el LSN del slot local %X/%X." + +#: replication/logical/slotsync.c:589 +#, c-format +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "el slot de replicación «%s» recién creado está listo para la sincronización" + +#: replication/logical/slotsync.c:628 +#, c-format +msgid "skipping slot synchronization because the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" +msgstr "omitiendo sincronización de slot porque el LSN %X/%X de sincronización recibido para el slot «%s» está adelantado respecto a la posición del standby %X/%X" + +#: replication/logical/slotsync.c:650 +#, c-format +msgid "exiting from slot synchronization because same name slot \"%s\" already exists on the standby" +msgstr "saliendo de la sincronización de slot porque un slot con el mismo nombre «%s» ya existe en el standby" + +#: replication/logical/slotsync.c:819 +#, c-format +msgid "could not fetch failover logical slots info from the primary server: %s" +msgstr "no se pudo obtener la información de slots “failover” de replicación lógica del servidor primario: %s" + +#: replication/logical/slotsync.c:965 +#, c-format +msgid "could not fetch primary_slot_name \"%s\" info from the primary server: %s" +msgstr "no se pudo obtener información del primary_slot_name «%s» del servidor primario: %s" + +#: replication/logical/slotsync.c:967 +#, c-format +msgid "Check if primary_slot_name is configured correctly." +msgstr "Verificando si primary_slot_name está configurado correctamente." + +#: replication/logical/slotsync.c:987 +#, c-format +msgid "cannot synchronize replication slots from a standby server" +msgstr "no puede sincronizar slots de replicación de un servidor standby" + +#. translator: second %s is a GUC variable name +#: replication/logical/slotsync.c:996 +#, c-format +msgid "replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "el slot de replicación «%s» especificado por «%s» no existe en el servidor primario" + +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1029 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "la sincronización de slots de replicación requiere que «%s» esté especificado en «%s»" + +# FIXME see slot.c:779. See also postmaster.c:835 +#: replication/logical/slotsync.c:1050 +#, c-format +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "la sincronización de slots de replicación requiere «wal_level» >= «logical»" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "la sincronización de slots de replicación requiere que «%s» esté definido" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1077 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "la sincronización de slots de replicación requiere que «%s» esté activado" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1129 +#, c-format +msgid "replication slot synchronization worker will shut down because \"%s\" is disabled" +msgstr "el proceso de sincronización de slots de replicación terminará porque «%s» está desactivado" + +#: replication/logical/slotsync.c:1138 +#, c-format +msgid "replication slot synchronization worker will restart because of a parameter change" +msgstr "el proceso de sincronización de slots de replicación se reiniciará debido a un cambio de parámetro" + +#: replication/logical/slotsync.c:1162 +#, c-format +msgid "replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "el trabajador de sincronización de slots de replicación está apagándose al recibir SIGINT" + +#: replication/logical/slotsync.c:1287 +#, c-format +msgid "cannot synchronize replication slots when standby promotion is ongoing" +msgstr "no se puede sincronizar los slots de replicación cuando la promoción de standby está teniendo lugar" + +#: replication/logical/slotsync.c:1295 +#, c-format +msgid "cannot synchronize replication slots concurrently" +msgstr "no se puede sincronizar slots de replicación concurrentemente" + +#: replication/logical/slotsync.c:1403 +#, c-format +msgid "slot sync worker started" +msgstr "iniciado el trabajador de sincronización de slots" + +#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 +#: replication/walreceiver.c:307 +#, c-format +msgid "could not connect to the primary server: %s" +msgstr "no se pudo conectar al servidor primario: %s" + +#: replication/logical/snapbuild.c:653 #, c-format msgid "initial slot snapshot too large" msgstr "el snapshot inicial del slot es demasiado grande" # FIXME: snapshot? instantánea? -#: replication/logical/snapbuild.c:693 +#: replication/logical/snapbuild.c:707 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs" msgstr[0] "se exportó un snapshot de decodificación lógica: «%s» con %u ID de transacción" msgstr[1] "se exportó un snapshot de decodificación lógica: «%s» con %u IDs de transacción" -#: replication/logical/snapbuild.c:1388 replication/logical/snapbuild.c:1480 -#: replication/logical/snapbuild.c:1992 +#: replication/logical/snapbuild.c:1404 replication/logical/snapbuild.c:1501 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "la decodificación lógica encontró un punto consistente en %X/%X" -#: replication/logical/snapbuild.c:1390 +#: replication/logical/snapbuild.c:1406 #, c-format msgid "There are no running transactions." msgstr "No hay transacciones en ejecución." -#: replication/logical/snapbuild.c:1432 +#: replication/logical/snapbuild.c:1453 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "decodificación lógica encontró punto de inicio en %X/%X" -#: replication/logical/snapbuild.c:1434 replication/logical/snapbuild.c:1458 +#: replication/logical/snapbuild.c:1455 replication/logical/snapbuild.c:1479 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "Esperando que las (aproximadamente %d) transacciones más antiguas que %u terminen." -#: replication/logical/snapbuild.c:1456 +#: replication/logical/snapbuild.c:1477 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "la decodificación lógica encontró un punto consistente inicial en %X/%X" -#: replication/logical/snapbuild.c:1482 +#: replication/logical/snapbuild.c:1503 #, c-format msgid "There are no old transactions anymore." msgstr "Ya no hay transacciones antiguas en ejecución." # FIXME "snapbuild"? -#: replication/logical/snapbuild.c:1883 +#: replication/logical/snapbuild.c:1904 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "el archivo de estado de snapbuild «%s» tiene número mágico erróneo: %u en lugar de %u" -#: replication/logical/snapbuild.c:1889 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "el archivo de estado de snapbuild «%s» tiene versión no soportada: %u en vez de %u" -#: replication/logical/snapbuild.c:1930 +#: replication/logical/snapbuild.c:1951 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "suma de verificación no coincidente para el archivo de estado de snapbuild «%s»: es %u, debería ser %u" -#: replication/logical/snapbuild.c:1994 +#: replication/logical/snapbuild.c:2019 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "La decodificación lógica comenzará usando el snapshot guardado." -#: replication/logical/snapbuild.c:2101 +#: replication/logical/snapbuild.c:2126 #, c-format msgid "could not parse file name \"%s\"" msgstr "no se pudo interpretar el nombre de archivo «%s»" -#: replication/logical/tablesync.c:152 +#: replication/logical/tablesync.c:161 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha terminado" -#: replication/logical/tablesync.c:621 -#, fuzzy, c-format -#| msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" +#: replication/logical/tablesync.c:641 +#, c-format msgid "logical replication apply worker for subscription \"%s\" will restart so that two_phase can be enabled" -msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha iniciado" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» se reiniciará para activar «two_phase»" -#: replication/logical/tablesync.c:796 replication/logical/tablesync.c:938 +#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" -msgstr "no se pudo obtener información de la tabla «%s.%s» del editor (publisher): %s" +msgstr "no se pudo obtener información de la tabla «%s.%s» del publicador: %s" -#: replication/logical/tablesync.c:803 +#: replication/logical/tablesync.c:834 #, c-format msgid "table \"%s.%s\" not found on publisher" -msgstr "la tabla \"%s.%s\" no fue encontrada en el editor (publisher)" +msgstr "la tabla \"%s.%s\" no fue encontrada en el publicador" -#: replication/logical/tablesync.c:861 -#, fuzzy, c-format -#| msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" +#: replication/logical/tablesync.c:892 +#, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" -msgstr "no se pudo obtener información de la tabla «%s.%s» del editor (publisher): %s" +msgstr "no se pudo obtener información de la lista de columnas para la tabla «%s.%s» del publicador: %s" -#: replication/logical/tablesync.c:1040 -#, fuzzy, c-format -#| msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" +#: replication/logical/tablesync.c:1071 +#, c-format msgid "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: %s" -msgstr "no se pudo obtener información de la tabla «%s.%s» del editor (publisher): %s" +msgstr "no se pudo obtener información de la cláusula WHERE para la tabla «%s.%s» del publicador: %s" -#: replication/logical/tablesync.c:1191 +#: replication/logical/tablesync.c:1230 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "no se pudo iniciar la copia de contenido inicial para de la tabla «%s.%s»: %s" -#: replication/logical/tablesync.c:1398 replication/logical/worker.c:2387 -#, c-format -msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" -msgstr "" - -#: replication/logical/tablesync.c:1413 +#: replication/logical/tablesync.c:1429 #, c-format msgid "table copy could not start transaction on publisher: %s" -msgstr "la copia de la tabla no pudo iniciar una transacción en el editor (publisher): %s" +msgstr "la copia de la tabla no pudo iniciar una transacción en el publicador: %s" -#: replication/logical/tablesync.c:1455 +#: replication/logical/tablesync.c:1472 #, c-format msgid "replication origin \"%s\" already exists" msgstr "el origen de replicación «%s» ya existe" -#: replication/logical/tablesync.c:1468 +#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 #, c-format -msgid "table copy could not finish transaction on publisher: %s" -msgstr "la copia de tabla no pudo terminar la transacción en el editor (publisher): %s" - -#: replication/logical/worker.c:445 -#, fuzzy -#| msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" -msgid "logical replication table synchronization worker" -msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha iniciado" +msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" +msgstr "el usuario «%s» no puede replicar en relaciones con seguridad de registros activa: «%s»" -#: replication/logical/worker.c:449 -#, fuzzy -#| msgid "out of logical replication worker slots" -msgid "logical replication apply worker" -msgstr "se agotaron los slots de procesos ayudantes de replicación" +#: replication/logical/tablesync.c:1518 +#, c-format +msgid "table copy could not finish transaction on publisher: %s" +msgstr "la copia de tabla no pudo terminar la transacción en el publicador: %s" -#: replication/logical/worker.c:512 -#, fuzzy, c-format -#| msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" +#: replication/logical/worker.c:481 +#, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop" -msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha iniciado" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» se detendrá" -#: replication/logical/worker.c:514 +#: replication/logical/worker.c:483 #, c-format msgid "Cannot handle streamed replication transactions using parallel apply workers until all tables have been synchronized." -msgstr "" +msgstr "No se puede gestionar replicación en flujo usando procesos en paralelo hasta que todas las tablas han sido sincronizadas." -#: replication/logical/worker.c:876 replication/logical/worker.c:991 +#: replication/logical/worker.c:852 replication/logical/worker.c:967 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "el formato de datos binarios es incorrecto en columna de replicación lógica %d" -#: replication/logical/worker.c:2526 +#: replication/logical/worker.c:2500 #, c-format msgid "publisher did not send replica identity column expected by the logical replication target relation \"%s.%s\"" -msgstr "el editor (publisher) no envía la columna identidad de réplica esperada por la relación de destino de replicación lógica «%s.%s»" +msgstr "el publicador no envía la columna identidad de réplica esperada por la relación de destino de replicación lógica «%s.%s»" -#: replication/logical/worker.c:2533 +#: replication/logical/worker.c:2507 #, c-format msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL" msgstr "la relación destino de replicación lógica «%s.%s» no tiene índice REPLICA IDENTITY ni PRIMARY KEY y la relación publicada no tiene REPLICA IDENTITY FULL" -#: replication/logical/worker.c:3384 -#, fuzzy, c-format -#| msgid "invalid standby message type \"%c\"" -msgid "invalid logical replication message type \"%c\"" -msgstr "el tipo «%c» de mensaje del standby no es válido" +#: replication/logical/worker.c:3371 +#, c-format +msgid "invalid logical replication message type \"??? (%d)\"" +msgstr "tipo de mensaje de replicación lógica no válido «??? (%d)»" -#: replication/logical/worker.c:3556 +#: replication/logical/worker.c:3543 #, c-format msgid "data stream from publisher has ended" msgstr "el flujo de datos del publisher ha terminado" -#: replication/logical/worker.c:3707 +#: replication/logical/worker.c:3697 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "terminando el proceso de replicación lógica debido a que se agotó el tiempo de espera" -#. translator: first %s is the name of logical replication worker -#: replication/logical/worker.c:3902 +#: replication/logical/worker.c:3891 #, c-format -msgid "%s for subscription \"%s\" will stop because the subscription was removed" -msgstr "" +msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» se detendrá porque la suscripción fue eliminada" -#. translator: first %s is the name of logical replication worker -#: replication/logical/worker.c:3916 +#: replication/logical/worker.c:3905 #, c-format -msgid "%s for subscription \"%s\" will stop because the subscription was disabled" -msgstr "" +msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» se detendrá porque la suscripción fue inhabilitada" -#: replication/logical/worker.c:3947 -#, fuzzy, c-format -#| msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" +#: replication/logical/worker.c:3936 +#, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because of a parameter change" -msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha iniciado" +msgstr "el ayudante paralelo «apply» de replicación lógica para la suscripción «%s» se reiniciará por un cambio de parámetro" -#. translator: first %s is the name of logical replication worker -#: replication/logical/worker.c:3952 +#: replication/logical/worker.c:3940 #, c-format -msgid "%s for subscription \"%s\" will restart because of a parameter change" -msgstr "" +msgid "logical replication worker for subscription \"%s\" will restart because of a parameter change" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» se reiniciará por un cambio de parámetro" -#. translator: %s is the name of logical replication worker -#: replication/logical/worker.c:4476 +#: replication/logical/worker.c:3954 #, c-format -msgid "%s for subscription %u will not start because the subscription was removed during startup" -msgstr "" +msgid "logical replication parallel apply worker for subscription \"%s\" will stop because the subscription owner's superuser privileges have been revoked" +msgstr "el proceso “apply” paralelo de replicación lógica para la suscripción «%s» se detendrá porque los privilegios de superusuario del dueño de la suscripción han sido revocados" -#. translator: first %s is the name of logical replication worker -#: replication/logical/worker.c:4492 +#: replication/logical/worker.c:3958 #, c-format -msgid "%s for subscription \"%s\" will not start because the subscription was disabled during startup" -msgstr "" +msgid "logical replication worker for subscription \"%s\" will restart because the subscription owner's superuser privileges have been revoked" +msgstr "el proceso de replicación lógica para la suscripción «%s» se reiniciará porque los privilegios de superusuario del dueño de la suscripción han sido revocados" + +#: replication/logical/worker.c:4478 +#, c-format +msgid "subscription has no replication slot set" +msgstr "la suscripción no tiene un slot de replicación establecido" + +#: replication/logical/worker.c:4591 +#, c-format +msgid "logical replication worker for subscription %u will not start because the subscription was removed during startup" +msgstr "el ayudante «apply» de replicación lógica para la suscripción %u no se iniciará porque la suscripción fue eliminada durante el inicio" + +#: replication/logical/worker.c:4607 +#, c-format +msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» no se iniciará porque la suscripción fue inhabilitada durante el inicio" -#: replication/logical/worker.c:4509 +#: replication/logical/worker.c:4631 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" msgstr "el ayudante de sincronización de tabla de replicación lógica para la suscripción «%s», tabla «%s» ha iniciado" -#. translator: first %s is the name of logical replication worker -#: replication/logical/worker.c:4515 -#, fuzzy, c-format -#| msgid "subscription \"%s\" already exists" -msgid "%s for subscription \"%s\" has started" -msgstr "la suscripción «%s» ya existe" - -#: replication/logical/worker.c:4590 +#: replication/logical/worker.c:4636 #, c-format -msgid "subscription has no replication slot set" -msgstr "la suscripción no tiene un slot de replicación establecido" +msgid "logical replication apply worker for subscription \"%s\" has started" +msgstr "el ayudante «apply» de replicación lógica para la suscripción «%s» ha iniciado" -#: replication/logical/worker.c:4757 -#, fuzzy, c-format -#| msgid "cursor \"%s\" has been declared but not opened" +#: replication/logical/worker.c:4758 +#, c-format msgid "subscription \"%s\" has been disabled because of an error" -msgstr "el cursor «%s» fue declarado pero no abierto" +msgstr "la suscripción «%s» ha sido inhabilitada debido a un error" -#: replication/logical/worker.c:4805 -#, fuzzy, c-format -#| msgid "cannot create logical replication slot in transaction that has performed writes" +#: replication/logical/worker.c:4806 +#, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" -msgstr "no se puede crear un slot de replicación lógica en una transacción que ha efectuado escrituras" +msgstr "iniciando el ignorado en la replicación lógica de la transacción en el LSN %X/%X" -#: replication/logical/worker.c:4819 +#: replication/logical/worker.c:4820 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" -msgstr "" +msgstr "finalizó el ignorado en la replicación lógica de la transacción en el LSN %X/%X" -#: replication/logical/worker.c:4901 -#, fuzzy, c-format -#| msgid "subscription \"%s\" already exists" +#: replication/logical/worker.c:4902 +#, c-format msgid "skip-LSN of subscription \"%s\" cleared" -msgstr "la suscripción «%s» ya existe" +msgstr "el «skip-LSN» de la suscripción «%s» ha sido borrado" -#: replication/logical/worker.c:4902 +#: replication/logical/worker.c:4903 #, c-format msgid "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X." -msgstr "" +msgstr "La ubicación de WAL (LSN) de término %X/%X de la transacción remota no coincidió con el skip-LSN %X/%X." -#: replication/logical/worker.c:4928 +#: replication/logical/worker.c:4940 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\"" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s»" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:4944 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» en la transacción %u" -#: replication/logical/worker.c:4937 +#: replication/logical/worker.c:4949 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» en la transacción %u, concluida en %X/%X" -#: replication/logical/worker.c:4948 +#: replication/logical/worker.c:4960 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» para la relación destino de replicación «%s.%s» en la transacción %u" -#: replication/logical/worker.c:4955 +#: replication/logical/worker.c:4967 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» para la relación de destino «%s.%s» en la transacción %u, concluida en %X/%X" -#: replication/logical/worker.c:4966 +#: replication/logical/worker.c:4978 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» para la relación de destino «%s.%s» columna «%s» en la transacción %u" -#: replication/logical/worker.c:4974 +#: replication/logical/worker.c:4986 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X" -msgstr "" +msgstr "procesando datos remotos de origen de replicación «%s» durante el mensaje de tipo «%s» para la relación de destino «%s.%s» columna «%s» en la transacción %u, concluida en %X/%X" -#: replication/pgoutput/pgoutput.c:318 +#: replication/pgoutput/pgoutput.c:322 #, c-format msgid "invalid proto_version" msgstr "proto_version no válido" -#: replication/pgoutput/pgoutput.c:323 +#: replication/pgoutput/pgoutput.c:327 #, c-format msgid "proto_version \"%s\" out of range" msgstr "proto_version «%s» fuera de rango" -#: replication/pgoutput/pgoutput.c:340 +#: replication/pgoutput/pgoutput.c:344 #, c-format msgid "invalid publication_names syntax" msgstr "sintaxis de publication_names no válida" -#: replication/pgoutput/pgoutput.c:443 +#: replication/pgoutput/pgoutput.c:414 replication/pgoutput/pgoutput.c:418 #, c-format -msgid "client sent proto_version=%d but server only supports protocol %d or lower" -msgstr "" +msgid "option \"%s\" missing" +msgstr "falta la opción «%s»" -#: replication/pgoutput/pgoutput.c:449 -#, fuzzy, c-format -#| msgid "requested proto_version=%d does not support streaming, need %d or higher" -msgid "client sent proto_version=%d but server only supports protocol %d or higher" -msgstr "la proto_version=%d no soporta flujo, se necesita %d o superior" +#: replication/pgoutput/pgoutput.c:478 +#, c-format +msgid "client sent proto_version=%d but server only supports protocol %d or lower" +msgstr "el cliente envió proto_version=%d pero el servidor sólo soporta el protocolo %d o inferior" -#: replication/pgoutput/pgoutput.c:455 +#: replication/pgoutput/pgoutput.c:484 #, c-format -msgid "publication_names parameter missing" -msgstr "parámetro publication_names faltante" +msgid "client sent proto_version=%d but server only supports protocol %d or higher" +msgstr "el cliente envió proto_version=%d pero el servidor sólo soporta el protocolo %d o superior" -#: replication/pgoutput/pgoutput.c:469 +#: replication/pgoutput/pgoutput.c:499 #, c-format msgid "requested proto_version=%d does not support streaming, need %d or higher" msgstr "la proto_version=%d no soporta flujo, se necesita %d o superior" -#: replication/pgoutput/pgoutput.c:475 -#, fuzzy, c-format -#| msgid "requested proto_version=%d does not support streaming, need %d or higher" +#: replication/pgoutput/pgoutput.c:505 +#, c-format msgid "requested proto_version=%d does not support parallel streaming, need %d or higher" -msgstr "la proto_version=%d no soporta flujo, se necesita %d o superior" +msgstr "la proto_version=%d solicitada no soporta flujo en paralelo, se necesita %d o superior" -#: replication/pgoutput/pgoutput.c:480 +#: replication/pgoutput/pgoutput.c:510 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "se solicitó flujo, pero no está soportado por plugin de salida" -#: replication/pgoutput/pgoutput.c:497 -#, fuzzy, c-format -#| msgid "requested proto_version=%d does not support streaming, need %d or higher" +#: replication/pgoutput/pgoutput.c:524 +#, c-format msgid "requested proto_version=%d does not support two-phase commit, need %d or higher" -msgstr "la proto_version=%d no soporta flujo, se necesita %d o superior" +msgstr "la proto_version=%d solicitada no soporta «two-phase commit», se necesita %d o superior" -#: replication/pgoutput/pgoutput.c:502 -#, fuzzy, c-format -#| msgid "streaming requested, but not supported by output plugin" +#: replication/pgoutput/pgoutput.c:529 +#, c-format msgid "two-phase commit requested, but not supported by output plugin" -msgstr "se solicitó flujo, pero no está soportado por plugin de salida" +msgstr "«two-phase commit» fue solicitado, pero no está soportado por el plugin de salida" -#: replication/slot.c:207 +#: replication/slot.c:260 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "el nombre de slot de replicación «%s» es demasiado corto" -#: replication/slot.c:216 +#: replication/slot.c:269 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "el nombre de slot de replicación «%s» es demasiado largo" -#: replication/slot.c:229 +#: replication/slot.c:282 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "el nombre de slot de replicación «%s» contiene caracteres no válidos" -#: replication/slot.c:231 +#: replication/slot.c:284 #, c-format msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character." msgstr "Los nombres de slots de replicación sólo pueden contener letras minúsculas, números y el carácter «_»." -#: replication/slot.c:285 +#: replication/slot.c:333 +#, c-format +msgid "cannot enable failover for a replication slot created on the standby" +msgstr "no se puede activar “failover” para un slot de replicación creado en el standby" + +#: replication/slot.c:345 replication/slot.c:849 +#, c-format +msgid "cannot enable failover for a temporary replication slot" +msgstr "no se puede activar “failover” para un slot de replicación temporal" + +#: replication/slot.c:370 #, c-format msgid "replication slot \"%s\" already exists" msgstr "el slot de replicación «%s» ya existe" -#: replication/slot.c:295 +#: replication/slot.c:380 #, c-format msgid "all replication slots are in use" msgstr "todos los slots de replicación están en uso" -#: replication/slot.c:296 +#: replication/slot.c:381 #, c-format -msgid "Free one or increase max_replication_slots." -msgstr "Libere uno o incremente max_replication_slots." +msgid "Free one or increase \"max_replication_slots\"." +msgstr "Libere uno o incremente «max_replication_slots»." -#: replication/slot.c:474 replication/slotfuncs.c:736 -#: utils/activity/pgstat_replslot.c:55 utils/adt/genfile.c:774 +#: replication/slot.c:560 replication/slot.c:2450 replication/slotfuncs.c:661 +#: utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "no existe el slot de replicación «%s»" -#: replication/slot.c:520 replication/slot.c:1110 +#: replication/slot.c:606 replication/slot.c:1337 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "el slot de replicación «%s» está activo para el PID %d" -#: replication/slot.c:756 replication/slot.c:1638 replication/slot.c:2021 +#: replication/slot.c:638 +#, c-format +msgid "acquired logical replication slot \"%s\"" +msgstr "se adquirió el slot de replicación lógica «%s»" + +#: replication/slot.c:640 +#, c-format +msgid "acquired physical replication slot \"%s\"" +msgstr "se adquirió el slot de replicación física «%s»" + +#: replication/slot.c:729 +#, c-format +msgid "released logical replication slot \"%s\"" +msgstr "se liberó el slot de replicación lógica «%s»" + +#: replication/slot.c:731 +#, c-format +msgid "released physical replication slot \"%s\"" +msgstr "se liberó el slot de replicación física «%s»" + +#: replication/slot.c:797 +#, c-format +msgid "cannot drop replication slot \"%s\"" +msgstr "no se puede eliminar el slot de replicación «%s»" + +#: replication/slot.c:816 +#, c-format +msgid "cannot use %s with a physical replication slot" +msgstr "no se puede usar %s con un slot de replicación física" + +#: replication/slot.c:828 +#, c-format +msgid "cannot alter replication slot \"%s\"" +msgstr "no se puede alterar el slot de replicación «%s»" + +#: replication/slot.c:838 +#, c-format +msgid "cannot enable failover for a replication slot on the standby" +msgstr "no se puede activar el “failover” para un slot de replicación en el standby" + +#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 #, c-format msgid "could not remove directory \"%s\"" msgstr "no se pudo eliminar el directorio «%s»" -#: replication/slot.c:1145 +#: replication/slot.c:1372 #, c-format -msgid "replication slots can only be used if max_replication_slots > 0" -msgstr "los slots de replicación sólo pueden usarse si max_replication_slots > 0" +msgid "replication slots can only be used if \"max_replication_slots\" > 0" +msgstr "los slots de replicación sólo pueden usarse si «max_replication_slots» > 0" # FIXME see logical.c:81 -#: replication/slot.c:1150 +#: replication/slot.c:1377 #, c-format -msgid "replication slots can only be used if wal_level >= replica" -msgstr "los slots de replicación sólo pueden usarse si wal_level >= replica" +msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" +msgstr "los slots de replicación sólo pueden usarse si «wal_level» >= «replica»" -#: replication/slot.c:1162 -#, fuzzy, c-format -#| msgid "permission denied for publication %s" +#: replication/slot.c:1389 +#, c-format msgid "permission denied to use replication slots" -msgstr "permiso denegado a la publicación %s" +msgstr "permiso denegado a usar slots de replicación" -#: replication/slot.c:1163 +#: replication/slot.c:1390 #, c-format msgid "Only roles with the %s attribute may use replication slots." -msgstr "" +msgstr "Sólo roles con el atributo %s pueden usar slots de replicación." -#: replication/slot.c:1267 +#: replication/slot.c:1498 #, c-format -msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." -msgstr "" +msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." +msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." +msgstr[0] "El restart_lsn %X/%X del slot excede el límite por %llu byte." +msgstr[1] "El restart_lsn %X/%X del slot excede el límite por %llu bytes." -#: replication/slot.c:1272 -#, fuzzy, c-format -#| msgid "Key %s conflicts with existing key %s." +#: replication/slot.c:1506 +#, c-format msgid "The slot conflicted with xid horizon %u." -msgstr "La llave %s está en conflicto con la llave existente %s." +msgstr "El slot estaba en conflicto con el horizonte de XID %u." # FIXME see slot.c:779. See also postmaster.c:835 -#: replication/slot.c:1277 -#, fuzzy -#| msgid "logical decoding requires wal_level >= logical" -msgid "Logical decoding on standby requires wal_level >= logical on the primary server." -msgstr "la decodificación lógica requiere wal_level >= logical" +#: replication/slot.c:1511 +msgid "Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server." +msgstr "La decodificación lógica en standby requiere «wal_level» >= «logical» en el primario." -#: replication/slot.c:1285 +#: replication/slot.c:1519 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "terminando el proceso %d para liberar el slot de replicación «%s»" -#: replication/slot.c:1287 -#, fuzzy, c-format -#| msgid "creating replication slot \"%s\"" +#: replication/slot.c:1521 +#, c-format msgid "invalidating obsolete replication slot \"%s\"" -msgstr "creando el slot de replicación «%s»" +msgstr "invalidando el slot de replicación obsoleto «%s»" -#: replication/slot.c:1290 -#, fuzzy, c-format -#| msgid "You might need to increase max_worker_processes." -msgid "You might need to increase max_slot_wal_keep_size." -msgstr "Puede ser necesario incrementar max_worker_processes." - -#: replication/slot.c:1959 +#: replication/slot.c:2249 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "el archivo de slot de replicación «%s» tiene número mágico erróneo: %u en lugar de %u" -#: replication/slot.c:1966 +#: replication/slot.c:2256 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "el archivo de slot de replicación «%s» tiene versión no soportada %u" -#: replication/slot.c:1973 +#: replication/slot.c:2263 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "el archivo de slot de replicación «%s» tiene largo corrupto %u" -#: replication/slot.c:2009 +#: replication/slot.c:2299 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "suma de verificación no coincidente en archivo de slot de replicación «%s»: es %u, debería ser %u" # FIXME see slot.c:779. See also postmaster.c:835 -#: replication/slot.c:2043 +#: replication/slot.c:2333 #, c-format -msgid "logical replication slot \"%s\" exists, but wal_level < logical" -msgstr "existe el slot de replicación lógica «%s», pero wal_level < logical" +msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" +msgstr "existe el slot de replicación lógica «%s», pero «wal_level» < «logical»" -#: replication/slot.c:2045 +#: replication/slot.c:2335 #, c-format -msgid "Change wal_level to be logical or higher." -msgstr "Cambie wal_level a logical o superior." +msgid "Change \"wal_level\" to be \"logical\" or higher." +msgstr "Cambie «wal_level» a «logical» o superior." # FIXME see slot.c:779. See also postmaster.c:835 -#: replication/slot.c:2049 +#: replication/slot.c:2339 #, c-format -msgid "physical replication slot \"%s\" exists, but wal_level < replica" -msgstr "existe el slot de replicación lógica «%s», pero wal_level < logical" +msgid "physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" +msgstr "existe el slot de replicación lógica «%s», pero «wal_level» < «replica»" # <> hello vim -#: replication/slot.c:2051 +#: replication/slot.c:2341 #, c-format -msgid "Change wal_level to be replica or higher." -msgstr "Cambie wal_level a replica o superior." +msgid "Change \"wal_level\" to be \"replica\" or higher." +msgstr "Cambie «wal_level» a «replica» o superior." -#: replication/slot.c:2085 +#: replication/slot.c:2383 #, c-format msgid "too many replication slots active before shutdown" msgstr "demasiados slots de replicación activos antes del apagado" -#: replication/slotfuncs.c:601 +#: replication/slot.c:2458 +#, c-format +msgid "\"%s\" is not a physical replication slot" +msgstr "«%s» no es un slot de replicación física" + +#: replication/slot.c:2635 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "el slot de replicación «%s» especificado en el parámetro «%s» no existe" + +#: replication/slot.c:2637 replication/slot.c:2671 replication/slot.c:2686 +#, c-format +msgid "Logical replication is waiting on the standby associated with replication slot \"%s\"." +msgstr "La replicación lógica está esperando al standby asociado con el slot de replicación «%s»." + +#: replication/slot.c:2639 +#, c-format +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "Cree el slot de replicación «%s» o corrija el parámetro «%s»." + +#: replication/slot.c:2649 +#, c-format +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "no se puede especificar el slot de replicación lógica «%s» en el parámetro «%s»" + +#: replication/slot.c:2651 +#, c-format +msgid "Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "La replicación lógica está esperando a una corrección en el slot de replicación «%s»." + +#: replication/slot.c:2653 +#, c-format +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "Elimine el slot de replicación lógica «%s» del parámetro «%s»." + +#: replication/slot.c:2669 +#, c-format +msgid "physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated" +msgstr "el slot de replicación física «%s» especificado en el parámetro «%s» ha sido invalidado" + +#: replication/slot.c:2673 +#, c-format +msgid "Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "Elimine y vuelva a crear el slot de replicación «%s», o corrija el parámetro «%s»." + +#: replication/slot.c:2684 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not have active_pid" +msgstr "el slot de replicación «%s» especificado en el parámetro «%s» no tiene active_pid" + +#: replication/slot.c:2688 +#, c-format +msgid "Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "Inicie el standby asociado con el slot de replicación «%s», o corrija el parámetro «%s»." + +#: replication/slotfuncs.c:526 #, c-format msgid "invalid target WAL LSN" msgstr "el LSN de wal de destino no es válido" -#: replication/slotfuncs.c:623 +#: replication/slotfuncs.c:548 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "no se puede avanzar el slot de replicación «%s»" -#: replication/slotfuncs.c:625 +#: replication/slotfuncs.c:550 #, c-format msgid "This slot has never previously reserved WAL, or it has been invalidated." msgstr "Este slot nunca ha reservado WAL previamente, o ha sido invalidado." -#: replication/slotfuncs.c:641 +#: replication/slotfuncs.c:566 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "no puede avanzar un slot de replicación a %X/%X, el mínimo es %X/%X" -#: replication/slotfuncs.c:748 +#: replication/slotfuncs.c:673 #, c-format msgid "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "no se puede copiar el slot de replicación física «%s» como slot de replicación lógica" -#: replication/slotfuncs.c:750 +#: replication/slotfuncs.c:675 #, c-format msgid "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "no se puede copiar el slot de replicación lógica «%s» como slot de replicación física" -#: replication/slotfuncs.c:757 +#: replication/slotfuncs.c:682 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "no puede copiar un slot de replicación que no ha reservado WAL" -#: replication/slotfuncs.c:834 +#: replication/slotfuncs.c:768 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "no se pudo copiar el slot de replicación «%s»" -#: replication/slotfuncs.c:836 +#: replication/slotfuncs.c:770 #, c-format msgid "The source replication slot was modified incompatibly during the copy operation." msgstr "El slot de replicación de origen fue modificado incompatiblemente durante la operación de copia." -#: replication/slotfuncs.c:842 +#: replication/slotfuncs.c:776 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "no se puede copiar el slot de replicación lógica no terminado «%s»" -#: replication/slotfuncs.c:844 +#: replication/slotfuncs.c:778 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "Reintente cuando el confirmed_flush_lsn del slot de replicación de origen sea válido." -#: replication/syncrep.c:262 +# FIXME see logical.c:81 +#: replication/slotfuncs.c:877 +#, c-format +msgid "replication slots can only be synchronized to a standby server" +msgstr "los slots de replicación sólo pueden sincronizarse a un servidor standby" + +#: replication/syncrep.c:261 #, c-format msgid "canceling the wait for synchronous replication and terminating connection due to administrator command" msgstr "cancelando la espera para la replicación sincrónica y terminando la conexión debido a una orden del administrador" -#: replication/syncrep.c:263 replication/syncrep.c:280 +#: replication/syncrep.c:262 replication/syncrep.c:279 #, c-format msgid "The transaction has already committed locally, but might not have been replicated to the standby." msgstr "La transacción ya fue comprometida localmente, pero pudo no haber sido replicada al standby." -#: replication/syncrep.c:279 +#: replication/syncrep.c:278 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "cancelando espera para la replicación sincrónica debido a una petición del usuario" -#: replication/syncrep.c:486 +#: replication/syncrep.c:485 #, c-format -msgid "standby \"%s\" is now a synchronous standby with priority %u" -msgstr "el standby «%s» es ahora un standby sincrónico con prioridad %u" +msgid "standby \"%s\" is now a synchronous standby with priority %d" +msgstr "el standby «%s» es ahora un standby sincrónico con prioridad %d" -#: replication/syncrep.c:490 +#: replication/syncrep.c:489 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "el standby «%s» es ahora un candidato para standby sincrónico de quórum" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1013 #, c-format -msgid "synchronous_standby_names parser failed" -msgstr "falló la interpretación de synchronous_standby_names" +msgid "\"synchronous_standby_names\" parser failed" +msgstr "falló la interpretación de «synchronous_standby_names»" -#: replication/syncrep.c:1025 +#: replication/syncrep.c:1019 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "el argumento de standby sincrónicos (%d) debe ser mayor que cero" -#: replication/walreceiver.c:180 +#: replication/walreceiver.c:176 #, c-format msgid "terminating walreceiver process due to administrator command" msgstr "terminando el proceso walreceiver debido a una orden del administrador" -#: replication/walreceiver.c:305 -#, c-format -msgid "could not connect to the primary server: %s" -msgstr "no se pudo conectar al servidor primario: %s" - -#: replication/walreceiver.c:352 +#: replication/walreceiver.c:354 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "el identificador de sistema difiere entre el primario y el standby" -#: replication/walreceiver.c:353 +#: replication/walreceiver.c:355 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "El identificador del primario es %s, el identificador del standby es %s." -#: replication/walreceiver.c:364 +#: replication/walreceiver.c:366 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "el timeline más alto del primario, %u, está más atrás que el timeline de recuperación %u" -#: replication/walreceiver.c:417 +#: replication/walreceiver.c:419 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "iniciando el flujo de WAL desde el primario en %X/%X en el timeline %u" -#: replication/walreceiver.c:421 +#: replication/walreceiver.c:423 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "reiniciando el flujo de WAL en %X/%X en el timeline %u" -#: replication/walreceiver.c:457 +#: replication/walreceiver.c:458 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "no se puede continuar el flujo de WAL; la recuperación ya ha terminado" -#: replication/walreceiver.c:501 +#: replication/walreceiver.c:502 #, c-format msgid "replication terminated by primary server" msgstr "replicación terminada por el servidor primario" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:503 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "Se alcanzó el fin de WAL en el timeline %u en la posición %X/%X." -#: replication/walreceiver.c:592 +#: replication/walreceiver.c:593 #, c-format msgid "terminating walreceiver due to timeout" msgstr "terminando el proceso walreceiver debido a que se agotó el tiempo de espera" -#: replication/walreceiver.c:624 +#: replication/walreceiver.c:625 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "el servidor primario no contiene más WAL en el timeline %u solicitado" -#: replication/walreceiver.c:640 replication/walreceiver.c:1066 -#, fuzzy, c-format -#| msgid "could not close shared memory segment \"%s\": %m" +#: replication/walreceiver.c:641 replication/walreceiver.c:1071 +#, c-format msgid "could not close WAL segment %s: %m" -msgstr "no se pudo cerrar el segmento de memoria compartida «%s»: %m" +msgstr "no se pudo cerrar el segmento de WAL %s: %m" -#: replication/walreceiver.c:759 +#: replication/walreceiver.c:760 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "trayendo el archivo de historia del timeline para el timeline %u desde el servidor primario" -#: replication/walreceiver.c:954 -#, fuzzy, c-format -#| msgid "could not write to log file %s at offset %u, length %zu: %m" -msgid "could not write to WAL segment %s at offset %u, length %lu: %m" -msgstr "no se pudo escribir archivo de registro %s en la posición %u, largo %zu: %m" +#: replication/walreceiver.c:959 +#, c-format +msgid "could not write to WAL segment %s at offset %d, length %lu: %m" +msgstr "no se pudo escribir al segmento de WAL %s en la posición %d, largo %lu: %m" -#: replication/walsender.c:519 -#, fuzzy, c-format -#| msgid "cannot use relation \"%s.%s\" as logical replication target" +#: replication/walsender.c:531 +#, c-format msgid "cannot use %s with a logical replication slot" -msgstr "no se puede usar la relación «%s.%s» como destino de replicación lógica" +msgstr "no se puede usar %s con un slot de replicación lógica" -#: replication/walsender.c:623 storage/smgr/md.c:1526 +#: replication/walsender.c:635 storage/smgr/md.c:1735 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "no se pudo posicionar (seek) al fin del archivo «%s»: %m" -#: replication/walsender.c:627 +#: replication/walsender.c:639 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "no se pudo posicionar (seek) al comienzo del archivo «%s»: %m" -#: replication/walsender.c:704 +#: replication/walsender.c:853 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "no se puede usar un slot de replicación lógica para replicación física" -#: replication/walsender.c:770 +#: replication/walsender.c:919 #, c-format msgid "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "el punto de inicio solicitado %X/%X del timeline %u no está en la historia de este servidor" -#: replication/walsender.c:773 +#: replication/walsender.c:922 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "La historia de este servidor bifurcó desde el timeline %u en %X/%X." -#: replication/walsender.c:817 +#: replication/walsender.c:966 #, c-format msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X" msgstr "el punto de inicio solicitado %X/%X está más adelante que la posición de sincronización (flush) de WAL de este servidor %X/%X" -#: replication/walsender.c:1010 -#, fuzzy, c-format -#| msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" +#: replication/walsender.c:1160 +#, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" -msgstr "valor no reconocido para la opción de EXPLAIN «%s»: «%s»" +msgstr "valor no reconocido para la opción de CREATE_REPLICATION_SLOT «%s»: «%s»" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1095 +#: replication/walsender.c:1266 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s no debe ser ejecutado dentro de una transacción" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1105 +#: replication/walsender.c:1276 #, c-format msgid "%s must be called inside a transaction" msgstr "%s no debe ser ejecutado dentro de una transacción" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1111 +#: replication/walsender.c:1282 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s debe llamarse en una transacción de modo de aislamiento REPEATABLE READ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1116 -#, fuzzy, c-format -#| msgid "%s must be called inside a transaction" -msgid "%s must be called in a read only transaction" -msgstr "%s no debe ser ejecutado dentro de una transacción" +#: replication/walsender.c:1287 +#, c-format +msgid "%s must be called in a read-only transaction" +msgstr "%s debe ser ejecutado en una transacción de sólo lectura" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1122 +#: replication/walsender.c:1293 #, c-format msgid "%s must be called before any query" msgstr "%s debe ser llamado antes de cualquier consulta" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1128 +#: replication/walsender.c:1299 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s no está permitido en una subtransacción" -#: replication/walsender.c:1275 +#: replication/walsender.c:1472 #, c-format msgid "terminating walsender process after promotion" msgstr "terminando el proceso walsender luego de la promoción" -#: replication/walsender.c:1696 +#: replication/walsender.c:2000 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" -msgstr "no puede ejecutar nuevas órdenes mientras el «WAL sender» está en modo de apagarse" +msgstr "no puede ejecutar nuevas órdenes mientras el “WAL sender” está en modo de apagarse" -#: replication/walsender.c:1731 +#: replication/walsender.c:2035 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" -msgstr "no puede ejecutar órdenes SQL en el «WAL sender» para replicación física" +msgstr "no puede ejecutar órdenes SQL en el “WAL sender” para replicación física" -#: replication/walsender.c:1764 +#: replication/walsender.c:2068 #, c-format msgid "received replication command: %s" msgstr "se recibió orden de replicación: %s" -#: replication/walsender.c:1772 tcop/fastpath.c:209 tcop/postgres.c:1138 -#: tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2210 -#: tcop/postgres.c:2648 tcop/postgres.c:2726 +#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1142 +#: tcop/postgres.c:1500 tcop/postgres.c:1752 tcop/postgres.c:2234 +#: tcop/postgres.c:2672 tcop/postgres.c:2749 #, c-format msgid "current transaction is aborted, commands ignored until end of transaction block" msgstr "transacción abortada, las órdenes serán ignoradas hasta el fin de bloque de transacción" -#: replication/walsender.c:1914 replication/walsender.c:1949 +#: replication/walsender.c:2233 replication/walsender.c:2268 #, c-format msgid "unexpected EOF on standby connection" msgstr "se encontró fin de archivo inesperado en la conexión standby" -#: replication/walsender.c:1937 +#: replication/walsender.c:2256 #, c-format msgid "invalid standby message type \"%c\"" msgstr "el tipo «%c» de mensaje del standby no es válido" -#: replication/walsender.c:2026 +#: replication/walsender.c:2345 #, c-format msgid "unexpected message type \"%c\"" msgstr "mensaje de tipo «%c» inesperado" -#: replication/walsender.c:2439 +#: replication/walsender.c:2759 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "terminando el proceso walsender debido a que se agotó el tiempo de espera de replicación" -#: rewrite/rewriteDefine.c:111 rewrite/rewriteDefine.c:842 +#: rewrite/rewriteDefine.c:104 rewrite/rewriteDefine.c:835 #, c-format msgid "rule \"%s\" for relation \"%s\" already exists" msgstr "ya existe una regla llamada «%s» para la relación «%s»" -#: rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:780 -#, fuzzy, c-format -#| msgid "portal \"%s\" cannot be run" +#: rewrite/rewriteDefine.c:261 rewrite/rewriteDefine.c:773 +#, c-format msgid "relation \"%s\" cannot have rules" -msgstr "el portal «%s» no puede ser ejecutado" +msgstr "la relación «%s» no puede tener reglas" -#: rewrite/rewriteDefine.c:299 +#: rewrite/rewriteDefine.c:292 #, c-format msgid "rule actions on OLD are not implemented" msgstr "las acciones de regla en OLD no están implementadas" -#: rewrite/rewriteDefine.c:300 +#: rewrite/rewriteDefine.c:293 #, c-format msgid "Use views or triggers instead." msgstr "Use vistas o triggers en su lugar." -#: rewrite/rewriteDefine.c:304 +#: rewrite/rewriteDefine.c:297 #, c-format msgid "rule actions on NEW are not implemented" msgstr "las acciones de regla en NEW no están implementadas" -#: rewrite/rewriteDefine.c:305 +#: rewrite/rewriteDefine.c:298 #, c-format msgid "Use triggers instead." msgstr "Use triggers en su lugar." -#: rewrite/rewriteDefine.c:319 -#, fuzzy, c-format -#| msgid "cursor \"%s\" is not a SELECT query" +#: rewrite/rewriteDefine.c:312 +#, c-format msgid "relation \"%s\" cannot have ON SELECT rules" -msgstr "el cursor «%s» no es una orden SELECT" +msgstr "la relación «%s» no puede tener reglas ON SELECT" -#: rewrite/rewriteDefine.c:329 +#: rewrite/rewriteDefine.c:322 #, c-format msgid "INSTEAD NOTHING rules on SELECT are not implemented" msgstr "las reglas INSTEAD NOTHING en SELECT no están implementadas" -#: rewrite/rewriteDefine.c:330 +#: rewrite/rewriteDefine.c:323 #, c-format msgid "Use views instead." msgstr "Use vistas en su lugar." -#: rewrite/rewriteDefine.c:338 +#: rewrite/rewriteDefine.c:331 #, c-format msgid "multiple actions for rules on SELECT are not implemented" msgstr "las reglas de múltiples acciones en SELECT no están implementadas" -#: rewrite/rewriteDefine.c:348 +#: rewrite/rewriteDefine.c:341 #, c-format msgid "rules on SELECT must have action INSTEAD SELECT" msgstr "las reglas en SELECT deben tener una acción INSTEAD SELECT" -#: rewrite/rewriteDefine.c:356 +#: rewrite/rewriteDefine.c:349 #, c-format msgid "rules on SELECT must not contain data-modifying statements in WITH" msgstr "las reglas en SELECT no deben contener sentencias que modifiquen datos en WITH" -#: rewrite/rewriteDefine.c:364 +#: rewrite/rewriteDefine.c:357 #, c-format msgid "event qualifications are not implemented for rules on SELECT" msgstr "las calificaciones de eventos no están implementadas para las reglas en SELECT" -#: rewrite/rewriteDefine.c:391 +#: rewrite/rewriteDefine.c:384 #, c-format msgid "\"%s\" is already a view" msgstr "«%s» ya es una vista" -#: rewrite/rewriteDefine.c:415 +#: rewrite/rewriteDefine.c:408 #, c-format msgid "view rule for \"%s\" must be named \"%s\"" msgstr "la regla de vista para «%s» debe llamarse «%s»" -#: rewrite/rewriteDefine.c:442 +#: rewrite/rewriteDefine.c:435 #, c-format msgid "cannot have multiple RETURNING lists in a rule" msgstr "no se pueden tener múltiples listas RETURNING en una regla" -#: rewrite/rewriteDefine.c:447 +#: rewrite/rewriteDefine.c:440 #, c-format msgid "RETURNING lists are not supported in conditional rules" msgstr "listas de RETURNING no están soportadas en reglas condicionales" -#: rewrite/rewriteDefine.c:451 +#: rewrite/rewriteDefine.c:444 #, c-format msgid "RETURNING lists are not supported in non-INSTEAD rules" msgstr "listas de RETURNING no están soportadas en reglas que no estén marcadas INSTEAD" -#: rewrite/rewriteDefine.c:465 -#, fuzzy, c-format -#| msgid "view rule for \"%s\" must be named \"%s\"" +#: rewrite/rewriteDefine.c:458 +#, c-format msgid "non-view rule for \"%s\" must not be named \"%s\"" -msgstr "la regla de vista para «%s» debe llamarse «%s»" +msgstr "la regla que no es de vista para «%s» no debe llamarse «%s»" -#: rewrite/rewriteDefine.c:539 +#: rewrite/rewriteDefine.c:532 #, c-format msgid "SELECT rule's target list has too many entries" msgstr "la lista de destinos en la regla de SELECT tiene demasiadas entradas" -#: rewrite/rewriteDefine.c:540 +#: rewrite/rewriteDefine.c:533 #, c-format msgid "RETURNING list has too many entries" msgstr "la lista de RETURNING tiene demasiadas entradas" -#: rewrite/rewriteDefine.c:567 +#: rewrite/rewriteDefine.c:560 #, c-format msgid "cannot convert relation containing dropped columns to view" msgstr "no se puede convertir en vista una relación que contiene columnas eliminadas" -#: rewrite/rewriteDefine.c:568 +#: rewrite/rewriteDefine.c:561 #, c-format msgid "cannot create a RETURNING list for a relation containing dropped columns" msgstr "no se puede crear una lista RETURNING para una relación que contiene columnas eliminadas" -#: rewrite/rewriteDefine.c:574 +#: rewrite/rewriteDefine.c:567 #, c-format msgid "SELECT rule's target entry %d has different column name from column \"%s\"" msgstr "la entrada de destino %d de la regla de SELECT tiene un nombre de columna diferente de «%s»" -#: rewrite/rewriteDefine.c:576 +#: rewrite/rewriteDefine.c:569 #, c-format msgid "SELECT target entry is named \"%s\"." msgstr "La entrada de destino de SELECT tiene nombre «%s»." -#: rewrite/rewriteDefine.c:585 +#: rewrite/rewriteDefine.c:578 #, c-format msgid "SELECT rule's target entry %d has different type from column \"%s\"" msgstr "el destino %d de la regla de SELECT tiene un tipo diferente de la columna «%s»" -#: rewrite/rewriteDefine.c:587 +#: rewrite/rewriteDefine.c:580 #, c-format msgid "RETURNING list's entry %d has different type from column \"%s\"" msgstr "el destino %d de la lista de RETURNING tiene un tipo diferente de la columna «%s»" -#: rewrite/rewriteDefine.c:590 rewrite/rewriteDefine.c:614 +#: rewrite/rewriteDefine.c:583 rewrite/rewriteDefine.c:607 #, c-format msgid "SELECT target entry has type %s, but column has type %s." msgstr "La entrada de destino de SELECT tiene un tipo «%s», pero la columna tiene tipo «%s»." -#: rewrite/rewriteDefine.c:593 rewrite/rewriteDefine.c:618 +#: rewrite/rewriteDefine.c:586 rewrite/rewriteDefine.c:611 #, c-format msgid "RETURNING list entry has type %s, but column has type %s." msgstr "una entrada de la lista RETURNING tiene tipo %s, pero la columna tiene tipo %s." -#: rewrite/rewriteDefine.c:609 +#: rewrite/rewriteDefine.c:602 #, c-format msgid "SELECT rule's target entry %d has different size from column \"%s\"" msgstr "el destino %d de la regla de SELECT tiene un tamaño diferente de la columna «%s»" -#: rewrite/rewriteDefine.c:611 +#: rewrite/rewriteDefine.c:604 #, c-format msgid "RETURNING list's entry %d has different size from column \"%s\"" msgstr "el destino %d de la lista RETURNING tiene un tamaño diferente de la columna «%s»" -#: rewrite/rewriteDefine.c:628 +#: rewrite/rewriteDefine.c:621 #, c-format msgid "SELECT rule's target list has too few entries" msgstr "la lista de destinos de regla de SELECT tiene muy pocas entradas" -#: rewrite/rewriteDefine.c:629 +#: rewrite/rewriteDefine.c:622 #, c-format msgid "RETURNING list has too few entries" msgstr "la lista de RETURNING tiene muy pocas entradas" -#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:833 -#: rewrite/rewriteSupport.c:109 +#: rewrite/rewriteDefine.c:711 rewrite/rewriteDefine.c:826 +#: rewrite/rewriteSupport.c:108 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist" msgstr "no existe la regla «%s» para la relación «%s»" -#: rewrite/rewriteDefine.c:852 +#: rewrite/rewriteDefine.c:845 #, c-format msgid "renaming an ON SELECT rule is not allowed" msgstr "no se permite cambiar el nombre de una regla ON SELECT" -#: rewrite/rewriteHandler.c:581 +#: rewrite/rewriteHandler.c:588 #, c-format msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten" msgstr "el nombre de consulta WITH «%s» aparece tanto en una acción de regla y en la consulta que está siendo reescrita" -#: rewrite/rewriteHandler.c:608 -#, fuzzy, c-format -#| msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" +#: rewrite/rewriteHandler.c:615 +#, c-format msgid "INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH" -msgstr "las reglas DO INSTEAD NOTIFY no están soportadas para sentencias que modifiquen datos en WITH" +msgstr "las acciones de regla INSERT ... SELECT no están soportadas para sentencias que modifiquen datos en WITH" -#: rewrite/rewriteHandler.c:661 +#: rewrite/rewriteHandler.c:668 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "no se puede usar RETURNING en múltiples reglas" -#: rewrite/rewriteHandler.c:893 rewrite/rewriteHandler.c:932 +#: rewrite/rewriteHandler.c:900 rewrite/rewriteHandler.c:939 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "no se puede insertar un valor no-predeterminado en la columna «%s»" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:961 +#: rewrite/rewriteHandler.c:902 rewrite/rewriteHandler.c:968 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "La columna \"%s\" es una columna de identidad definida como GENERATED ALWAYS." -#: rewrite/rewriteHandler.c:897 +#: rewrite/rewriteHandler.c:904 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "Use OVERRIDING SYSTEM VALUE para controlar manualmente." -#: rewrite/rewriteHandler.c:959 rewrite/rewriteHandler.c:967 +#: rewrite/rewriteHandler.c:966 rewrite/rewriteHandler.c:974 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "la columna «%s» sólo puede actualizarse a DEFAULT" -#: rewrite/rewriteHandler.c:1114 rewrite/rewriteHandler.c:1132 +#: rewrite/rewriteHandler.c:1109 rewrite/rewriteHandler.c:1127 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "hay múltiples asignaciones a la misma columna «%s»" -#: rewrite/rewriteHandler.c:2118 rewrite/rewriteHandler.c:4039 +#: rewrite/rewriteHandler.c:1682 +#, c-format +msgid "MERGE is not supported for relations with rules." +msgstr "MERGE no está soportado para relaciones con reglas." + +#: rewrite/rewriteHandler.c:1722 rewrite/rewriteHandler.c:3262 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "el acceso a la vista no de sistema «%s» está restringido" + +#: rewrite/rewriteHandler.c:2122 rewrite/rewriteHandler.c:4254 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "se detectó recursión infinita en las reglas de la relación «%s»" -#: rewrite/rewriteHandler.c:2203 +#: rewrite/rewriteHandler.c:2227 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "se detectó recursión infinita en la política para la relación «%s»" -#: rewrite/rewriteHandler.c:2523 +#: rewrite/rewriteHandler.c:2589 msgid "Junk view columns are not updatable." msgstr "Las columnas «basura» de vistas no son actualizables." -#: rewrite/rewriteHandler.c:2528 +#: rewrite/rewriteHandler.c:2594 msgid "View columns that are not columns of their base relation are not updatable." msgstr "Las columnas de vistas que no son columnas de su relación base no son actualizables." -#: rewrite/rewriteHandler.c:2531 +#: rewrite/rewriteHandler.c:2597 msgid "View columns that refer to system columns are not updatable." msgstr "Las columnas de vistas que se refieren a columnas de sistema no son actualizables." -#: rewrite/rewriteHandler.c:2534 +#: rewrite/rewriteHandler.c:2600 msgid "View columns that return whole-row references are not updatable." msgstr "Las columnas de vistas que retornan referencias a la fila completa no son actualizables." # XXX a %s here would be nice ... -#: rewrite/rewriteHandler.c:2595 +#: rewrite/rewriteHandler.c:2661 msgid "Views containing DISTINCT are not automatically updatable." msgstr "Las vistas que contienen DISTINCT no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2598 +#: rewrite/rewriteHandler.c:2664 msgid "Views containing GROUP BY are not automatically updatable." msgstr "Las vistas que contienen GROUP BY no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2601 +#: rewrite/rewriteHandler.c:2667 msgid "Views containing HAVING are not automatically updatable." msgstr "Las vistas que contienen HAVING no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2604 +#: rewrite/rewriteHandler.c:2670 msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "Las vistas que contienen UNION, INTERSECT o EXCEPT no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2607 +#: rewrite/rewriteHandler.c:2673 msgid "Views containing WITH are not automatically updatable." msgstr "Las vistas que contienen WITH no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2610 +#: rewrite/rewriteHandler.c:2676 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "Las vistas que contienen LIMIT u OFFSET no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:2622 -msgid "Views that return aggregate functions are not automatically updatable." -msgstr "Las vistas que retornan funciones de agregación no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:2688 +msgid "Views that return aggregate functions are not automatically updatable." +msgstr "Las vistas que retornan funciones de agregación no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:2691 +msgid "Views that return window functions are not automatically updatable." +msgstr "Las vistas que retornan funciones ventana no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:2694 +msgid "Views that return set-returning functions are not automatically updatable." +msgstr "Las vistas que retornan funciones-que-retornan-conjuntos no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:2701 rewrite/rewriteHandler.c:2705 +#: rewrite/rewriteHandler.c:2713 +msgid "Views that do not select from a single table or view are not automatically updatable." +msgstr "Las vistas que no extraen desde una única tabla o vista no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:2716 +msgid "Views containing TABLESAMPLE are not automatically updatable." +msgstr "Las vistas que contienen TABLESAMPLE no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:2740 +msgid "Views that have no updatable columns are not automatically updatable." +msgstr "Las vistas que no tienen columnas actualizables no son automáticamente actualizables." + +#: rewrite/rewriteHandler.c:3121 rewrite/rewriteHandler.c:3156 +#, c-format +msgid "cannot insert into view \"%s\"" +msgstr "no se puede insertar en la vista «%s»" + +#: rewrite/rewriteHandler.c:3124 +#, c-format +msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." +msgstr "Para posibilitar las inserciones en la vista, provea un “trigger” INSTEAD OF INSERT o una regla incodicional ON INSERT DO INSTEAD." + +#: rewrite/rewriteHandler.c:3129 rewrite/rewriteHandler.c:3165 +#, c-format +msgid "cannot update view \"%s\"" +msgstr "no se puede actualizar la vista «%s»" + +#: rewrite/rewriteHandler.c:3132 +#, c-format +msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." +msgstr "Para posibilitar las actualizaciones en la vista, provea un “trigger” INSTEAD OF UPDATE o una regla incondicional ON UPDATE DO INSTEAD." -#: rewrite/rewriteHandler.c:2625 -msgid "Views that return window functions are not automatically updatable." -msgstr "Las vistas que retornan funciones ventana no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:3137 rewrite/rewriteHandler.c:3174 +#, c-format +msgid "cannot delete from view \"%s\"" +msgstr "no se puede eliminar de la vista «%s»" -#: rewrite/rewriteHandler.c:2628 -msgid "Views that return set-returning functions are not automatically updatable." -msgstr "Las vistas que retornan funciones-que-retornan-conjuntos no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:3140 +#, c-format +msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." +msgstr "Para posibilitar las eliminaciones en la vista, provea un “trigger” INSTEAD OF DELETE o una regla incondicional ON DELETE DO INSTEAD." -#: rewrite/rewriteHandler.c:2635 rewrite/rewriteHandler.c:2639 -#: rewrite/rewriteHandler.c:2647 -msgid "Views that do not select from a single table or view are not automatically updatable." -msgstr "Las vistas que no extraen desde una única tabla o vista no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:3159 +#, c-format +msgid "To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger." +msgstr "Para posibilitar insertar en la vista usando MERGE, provea un “trigger” INSTEAD OF INSERT." -#: rewrite/rewriteHandler.c:2650 -msgid "Views containing TABLESAMPLE are not automatically updatable." -msgstr "Las vistas que contienen TABLESAMPLE no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:3168 +#, c-format +msgid "To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger." +msgstr "Para posibilitar actualizar la vista usando MERGE, provea un “trigger” INSTEAD OF UPDATE." -#: rewrite/rewriteHandler.c:2674 -msgid "Views that have no updatable columns are not automatically updatable." -msgstr "Las vistas que no tienen columnas actualizables no son automáticamente actualizables." +#: rewrite/rewriteHandler.c:3177 +#, c-format +msgid "To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger." +msgstr "Para posibilitar eliminar de la vista usando MERGE, provea un “trigger” INSTEAD OF DELETE." -#: rewrite/rewriteHandler.c:3154 +#: rewrite/rewriteHandler.c:3352 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "no se puede insertar en la columna «%s» de la vista «%s»" -#: rewrite/rewriteHandler.c:3162 +#: rewrite/rewriteHandler.c:3360 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "no se puede actualizar la columna «%s» vista «%s»" -#: rewrite/rewriteHandler.c:3666 +#: rewrite/rewriteHandler.c:3368 +#, c-format +msgid "cannot merge into column \"%s\" of view \"%s\"" +msgstr "no se puede hacer «merge» en la columna «%s» de la vista «%s»" + +#: rewrite/rewriteHandler.c:3396 +#, c-format +msgid "cannot merge into view \"%s\"" +msgstr "no se puede hacer «merge» en la vista «%s»" + +#: rewrite/rewriteHandler.c:3398 +#, c-format +msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions but not all." +msgstr "MERGE no está soportado para vistas con triggers INSTEAD OF para algunas acciones pero no todas." + +#: rewrite/rewriteHandler.c:3399 +#, c-format +msgid "To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers." +msgstr "Para posibilitar hacer “merge” en la vista, provea un conjunto completo de “triggers” INSTEAD OF o elimine los “triggers” INSTEAD OF existentes." + +#: rewrite/rewriteHandler.c:3912 #, c-format msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" msgstr "las reglas DO INSTEAD NOTIFY no están soportadas para sentencias que modifiquen datos en WITH" -#: rewrite/rewriteHandler.c:3677 +#: rewrite/rewriteHandler.c:3923 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" msgstr "las reglas DO INSTEAD NOTHING no están soportadas para sentencias que modifiquen datos en WITH" -#: rewrite/rewriteHandler.c:3691 +#: rewrite/rewriteHandler.c:3937 #, c-format msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "las reglas DO INSTEAD condicionales no están soportadas para sentencias que modifiquen datos en WITH" -#: rewrite/rewriteHandler.c:3695 +#: rewrite/rewriteHandler.c:3941 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "las reglas DO ALSO no están soportadas para sentencias que modifiquen datos en WITH" -#: rewrite/rewriteHandler.c:3700 +#: rewrite/rewriteHandler.c:3946 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "las reglas DO INSTEAD de múltiples sentencias no están soportadas para sentencias que modifiquen datos en WITH" # XXX a %s here would be nice ... -#: rewrite/rewriteHandler.c:3967 rewrite/rewriteHandler.c:3975 -#: rewrite/rewriteHandler.c:3983 -#, c-format +#: rewrite/rewriteHandler.c:4206 msgid "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "Las vistas con reglas DO INSTEAD condicionales no son automáticamente actualizables." -#: rewrite/rewriteHandler.c:4088 +#: rewrite/rewriteHandler.c:4303 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "no se puede hacer INSERT RETURNING a la relación «%s»" -#: rewrite/rewriteHandler.c:4090 +#: rewrite/rewriteHandler.c:4305 #, c-format msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "Necesita un regla incondicional ON INSERT DO INSTEAD con una cláusula RETURNING." -#: rewrite/rewriteHandler.c:4095 +#: rewrite/rewriteHandler.c:4310 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "no se puede hacer UPDATE RETURNING a la relación «%s»" -#: rewrite/rewriteHandler.c:4097 +#: rewrite/rewriteHandler.c:4312 #, c-format msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "Necesita un regla incondicional ON UPDATE DO INSTEAD con una cláusula RETURNING." -#: rewrite/rewriteHandler.c:4102 +#: rewrite/rewriteHandler.c:4317 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "no se puede hacer DELETE RETURNING a la relación «%s»" -#: rewrite/rewriteHandler.c:4104 +#: rewrite/rewriteHandler.c:4319 #, c-format msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "Necesita un regla incondicional ON DELETE DO INSTEAD con una clásula RETURNING." -#: rewrite/rewriteHandler.c:4122 +#: rewrite/rewriteHandler.c:4337 #, c-format msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" msgstr "INSERT con una cláusula ON CONFLICT no puede usarse con una tabla que tiene reglas INSERT o UPDATE" -#: rewrite/rewriteHandler.c:4179 +#: rewrite/rewriteHandler.c:4394 #, c-format msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries" msgstr "WITH no puede ser usado en una consulta que está siendo convertida en múltiples consultas a través de reglas" -#: rewrite/rewriteManip.c:1070 +#: rewrite/rewriteManip.c:1084 #, c-format msgid "conditional utility statements are not implemented" msgstr "las sentencias condicionales de utilidad no están implementadas" -#: rewrite/rewriteManip.c:1414 +#: rewrite/rewriteManip.c:1431 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "WHERE CURRENT OF no está implementado en una vista" -#: rewrite/rewriteManip.c:1749 +#: rewrite/rewriteManip.c:1767 #, c-format msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command" msgstr "las variables NEW en reglas ON UPDATE no pueden referenciar columnas que son parte de una asignación múltiple en la orden UPDATE" #: rewrite/rewriteSearchCycle.c:410 -#, fuzzy, c-format -#| msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" +#, c-format msgid "with a SEARCH or CYCLE clause, the recursive reference to WITH query \"%s\" must be at the top level of its right-hand SELECT" -msgstr "con una cláusula SEARCH o CYCLE, el lado izquierdo de UNION debe ser un SELECT" +msgstr "con una cláusula SEARCH o CYCLE, la referencia recursiva a la consulta de WITH «%s» debe estar en el nivel superior de su SELECT del lado derecho" #: snowball/dict_snowball.c:215 #, c-format @@ -21531,72 +22046,67 @@ msgstr "parámetro Snowball no reconocido: «%s»" msgid "missing Language parameter" msgstr "falta un parámetro Language" -#: statistics/extended_stats.c:179 +#: statistics/extended_stats.c:176 #, c-format msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "el objeto de estadísticas «%s.%s» no pudo ser calculado para la relación «%s.%s»" -#: statistics/mcv.c:1372 +#: statistics/mcv.c:1368 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "se llamó una función que retorna un registro en un contexto que no puede aceptarlo" -#: storage/buffer/bufmgr.c:612 storage/buffer/bufmgr.c:769 +#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 #, c-format msgid "cannot access temporary tables of other sessions" msgstr "no se pueden acceder tablas temporales de otras sesiones" -#: storage/buffer/bufmgr.c:1137 +#: storage/buffer/bufmgr.c:1532 #, c-format msgid "invalid page in block %u of relation %s; zeroing out page" msgstr "la página no es válida en el bloque %u de la relación «%s»; reinicializando la página" -#: storage/buffer/bufmgr.c:1931 storage/buffer/localbuf.c:359 +#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "no se puede extender la relación %s más allá de %u bloques" -#: storage/buffer/bufmgr.c:1998 +#: storage/buffer/bufmgr.c:2348 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "datos inesperados más allá del EOF en el bloque %u de relación %s" -#: storage/buffer/bufmgr.c:2000 +#: storage/buffer/bufmgr.c:2350 #, c-format msgid "This has been seen to occur with buggy kernels; consider updating your system." msgstr "Esto parece ocurrir sólo con kernels defectuosos; considere actualizar su sistema." -#: storage/buffer/bufmgr.c:5219 +#: storage/buffer/bufmgr.c:5653 #, c-format msgid "could not write block %u of %s" msgstr "no se pudo escribir el bloque %u de %s" -#: storage/buffer/bufmgr.c:5221 +#: storage/buffer/bufmgr.c:5655 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "Múltiples fallas --- el error de escritura puede ser permanente." -#: storage/buffer/bufmgr.c:5243 storage/buffer/bufmgr.c:5263 +#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 #, c-format msgid "writing block %u of relation %s" msgstr "escribiendo el bloque %u de la relación %s" -#: storage/buffer/bufmgr.c:5593 -#, c-format -msgid "snapshot too old" -msgstr "snapshot demasiado antiguo" - -#: storage/buffer/localbuf.c:219 +#: storage/buffer/localbuf.c:220 #, c-format msgid "no empty local buffer available" msgstr "no hay ningún búfer local disponible" -#: storage/buffer/localbuf.c:592 +#: storage/buffer/localbuf.c:597 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "no se pueden acceder tablas temporales durante una operación paralela" -#: storage/buffer/localbuf.c:699 +#: storage/buffer/localbuf.c:712 #, c-format msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." msgstr "«temp_buffers» no puede ser cambiado después de que cualquier tabla temporal haya sido accedida en la sesión." @@ -21607,164 +22117,165 @@ msgid "could not open temporary file \"%s\" from BufFile \"%s\": %m" msgstr "no se pudo abrir archivo temporal «%s» del BufFile «%s»: %m" #: storage/file/buffile.c:632 -#, fuzzy, c-format -#| msgid "could not read block %u in file \"%s\": read only %d of %d bytes" +#, c-format msgid "could not read from file set \"%s\": read only %zu of %zu bytes" -msgstr "no se pudo leer el bloque %u del archivo «%s»: se leyeron sólo %d de %d bytes" +msgstr "no se pudo leer del “file set” «%s»: se leyeron sólo %zu de %zu bytes" #: storage/file/buffile.c:634 -#, fuzzy, c-format -#| msgid "could not read block %u in file \"%s\": read only %d of %d bytes" +#, c-format msgid "could not read from temporary file: read only %zu of %zu bytes" -msgstr "no se pudo leer el bloque %u del archivo «%s»: se leyeron sólo %d de %d bytes" +msgstr "no se pudo leer del archivo temporal: se leyeron sólo %zu de %zu bytes" -#: storage/file/buffile.c:774 storage/file/buffile.c:895 +#: storage/file/buffile.c:774 storage/file/buffile.c:877 #, c-format msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" msgstr "no se pudo determinar el tamaño del archivo temporal «%s» del BufFile «%s»: %m" -#: storage/file/buffile.c:974 -#, fuzzy, c-format -#| msgid "could not delete file \"%s\": %m" +#: storage/file/buffile.c:956 +#, c-format msgid "could not delete fileset \"%s\": %m" -msgstr "no se pudo borrar el archivo «%s»: %m" +msgstr "no se pudo borrar el “fileset” «%s»: %m" -#: storage/file/buffile.c:992 storage/smgr/md.c:335 storage/smgr/md.c:1038 +#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1194 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "no se pudo truncar el archivo «%s»: %m" -#: storage/file/fd.c:516 storage/file/fd.c:588 storage/file/fd.c:624 +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" msgstr "no se pudo sincronizar (flush) datos «sucios»: %m" -#: storage/file/fd.c:546 +#: storage/file/fd.c:613 #, c-format msgid "could not determine dirty data size: %m" msgstr "no se pudo determinar el tamaño de los datos «sucios»: %m" -#: storage/file/fd.c:598 +#: storage/file/fd.c:665 #, c-format msgid "could not munmap() while flushing data: %m" msgstr "no se pudo ejecutar munmap() mientras se sincronizaban (flush) datos: %m" -#: storage/file/fd.c:894 +#: storage/file/fd.c:983 #, c-format msgid "getrlimit failed: %m" msgstr "getrlimit falló: %m" -#: storage/file/fd.c:984 +#: storage/file/fd.c:1073 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "los descriptores de archivo disponibles son insuficientes para iniciar un proceso servidor" -#: storage/file/fd.c:985 +#: storage/file/fd.c:1074 #, c-format msgid "System allows %d, server needs at least %d." -msgstr "" +msgstr "El sistema permite %d, el servidor necesita al menos %d." -#: storage/file/fd.c:1073 storage/file/fd.c:2515 storage/file/fd.c:2624 -#: storage/file/fd.c:2775 +#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 +#: storage/file/fd.c:2878 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "se agotaron los descriptores de archivo: %m; libere e intente nuevamente" -#: storage/file/fd.c:1447 +#: storage/file/fd.c:1536 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "archivo temporal: ruta «%s», tamaño %lu" -#: storage/file/fd.c:1586 +#: storage/file/fd.c:1675 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "no se pudo crear el directorio temporal «%s»: %m" -#: storage/file/fd.c:1593 +#: storage/file/fd.c:1682 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "no se pudo crear el subdirectorio temporal «%s»: %m" -#: storage/file/fd.c:1790 +#: storage/file/fd.c:1879 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "no se pudo crear el archivo temporal «%s»: %m" -#: storage/file/fd.c:1826 +#: storage/file/fd.c:1915 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "no se pudo abrir el archivo temporal «%s»: %m" -#: storage/file/fd.c:1867 +#: storage/file/fd.c:1956 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "no se pudo eliminar (unlink) el archivo temporal «%s»: %m" -#: storage/file/fd.c:1955 +#: storage/file/fd.c:2044 #, c-format msgid "could not delete file \"%s\": %m" msgstr "no se pudo borrar el archivo «%s»: %m" -#: storage/file/fd.c:2138 +#: storage/file/fd.c:2234 #, c-format msgid "temporary file size exceeds temp_file_limit (%dkB)" msgstr "el tamaño del archivo temporal excede temp_file_limit permitido (%dkB)" -#: storage/file/fd.c:2491 storage/file/fd.c:2550 +#: storage/file/fd.c:2594 storage/file/fd.c:2653 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "se excedió maxAllocatedDescs (%d) mientras se trataba de abrir el archivo «%s»" -#: storage/file/fd.c:2595 +#: storage/file/fd.c:2698 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "se excedió maxAllocatedDescs (%d) mientras se trataba de ejecutar la orden «%s»" -#: storage/file/fd.c:2751 +#: storage/file/fd.c:2854 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "se excedió maxAllocatedDescs (%d) mientras se trataba de abrir el directorio «%s»" -#: storage/file/fd.c:3281 +#: storage/file/fd.c:3384 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "archivo inesperado en directorio de archivos temporales: «%s»" -#: storage/file/fd.c:3399 +#: storage/file/fd.c:3502 #, c-format msgid "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "sincronizando el directorio de datos (syncfs), transcurrido: %ld.%02d s, ruta actual: %s" -#: storage/file/fd.c:3413 -#, c-format -msgid "could not synchronize file system for file \"%s\": %m" -msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" - -#: storage/file/fd.c:3626 +#: storage/file/fd.c:3729 #, c-format msgid "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "sincronizando el directorio de datos (pre-fsync), transcurrido: %ld.%02d s, ruta actual: %s" -#: storage/file/fd.c:3658 +#: storage/file/fd.c:3761 #, c-format msgid "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "sincronizando el directorio de datos (fsync), transcurrido: %ld.%02d s, ruta actual: %s" -#: storage/file/fd.c:3847 -#, fuzzy, c-format -#| msgid "Direct I/O is not supported on this platform.\n" -msgid "debug_io_direct is not supported on this platform." -msgstr "Direct I/O no está soportado en esta plataforma.\n" +#: storage/file/fd.c:3950 +#, c-format +msgid "\"debug_io_direct\" is not supported on this platform." +msgstr "«debug_io_direct» no está soportado en esta plataforma." + +#: storage/file/fd.c:3964 +#, c-format +msgid "Invalid list syntax in parameter \"%s\"" +msgstr "Sintaxis de lista no válida en el parámetro «%s»" -#: storage/file/fd.c:3894 +#: storage/file/fd.c:3984 #, c-format -msgid "debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small" -msgstr "" +msgid "Invalid option \"%s\"" +msgstr "Nombre de opción «%s» no válido." -#: storage/file/fd.c:3901 +#: storage/file/fd.c:3997 #, c-format -msgid "debug_io_direct is not supported for data because BLCKSZ is too small" -msgstr "" +msgid "\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" +msgstr "«debug_io_direct» no está soportado para WAL porque XLOG_BLCKSZ es demasiado pequeño" + +#: storage/file/fd.c:4004 +#, c-format +msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" +msgstr "«debug_io_direct» no está soportado para datos porque BLCKSZ es demasiado pequeño" #: storage/file/reinit.c:145 #, c-format @@ -21776,22 +22287,22 @@ msgstr "reseteando relaciones «unlogged» (init), transcurrido: %ld.%02d s, rut msgid "resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s" msgstr "reseteando relaciones «unlogged» (cleanup), transcurrido: %ld.%02d s, ruta actual: %s" -#: storage/file/sharedfileset.c:79 +#: storage/file/sharedfileset.c:73 #, c-format msgid "could not attach to a SharedFileSet that is already destroyed" msgstr "no se puede adjuntar a un SharedFileSet que ya está destruido" -#: storage/ipc/dsm.c:352 +#: storage/ipc/dsm.c:379 #, c-format msgid "dynamic shared memory control segment is corrupt" msgstr "el segmento de control de memoria compartida dinámica está corrupto" -#: storage/ipc/dsm.c:417 +#: storage/ipc/dsm.c:444 #, c-format msgid "dynamic shared memory control segment is not valid" msgstr "el segmento de control de memoria compartida dinámica no es válido" -#: storage/ipc/dsm.c:599 +#: storage/ipc/dsm.c:626 #, c-format msgid "too many dynamic shared memory segments" msgstr "demasiados segmentos de memoria compartida dinámica" @@ -21851,457 +22362,456 @@ msgstr "no se pudo cerrar el segmento de memoria compartida «%s»: %m" msgid "could not duplicate handle for \"%s\": %m" msgstr "no se pudo duplicar el «handle» para «%s»: %m" -#: storage/ipc/procarray.c:3796 +#: storage/ipc/dsm_registry.c:142 +#, c-format +msgid "DSM segment name cannot be empty" +msgstr "el nombre del segmento DSM no puede ser vacío" + +#: storage/ipc/dsm_registry.c:146 +#, c-format +msgid "DSM segment name too long" +msgstr "nombre de segmento DSM es demasiado largo" + +#: storage/ipc/dsm_registry.c:150 +#, c-format +msgid "DSM segment size must be nonzero" +msgstr "el tamaño del segmento DSM debe ser distinto de cero" + +#: storage/ipc/dsm_registry.c:176 +#, c-format +msgid "requested DSM segment size does not match size of existing segment" +msgstr "el tamaño solicitado de segmento de DSM no coincide con el tamaño del segmento existente" + +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:357 +#: tcop/backend_startup.c:304 +#, c-format +msgid "sorry, too many clients already" +msgstr "lo siento, ya tenemos demasiados clientes" + +#: storage/ipc/procarray.c:3857 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "la base de datos «%s» está siendo utilizada por transacciones preparadas" -#: storage/ipc/procarray.c:3828 +#: storage/ipc/procarray.c:3893 storage/ipc/procarray.c:3901 +#: storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 #, c-format -msgid "must be a superuser to terminate superuser process" -msgstr "debe ser superusuario para terminar proceso de superusuario" - -#: storage/ipc/procarray.c:3835 storage/ipc/signalfuncs.c:230 -#: storage/ipc/signalfuncs.c:237 -#, fuzzy, c-format -#| msgid "permission denied to create role" msgid "permission denied to terminate process" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para terminar el proceso" -#: storage/ipc/procarray.c:3836 storage/ipc/signalfuncs.c:238 +#: storage/ipc/procarray.c:3894 storage/ipc/signalfuncs.c:236 +#, c-format +msgid "Only roles with the %s attribute may terminate processes of roles with the %s attribute." +msgstr "Sólo roles con el atributo %s pueden terminar procesos de roles con el atributo %s." + +#: storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:243 #, c-format msgid "Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process." -msgstr "" +msgstr "Sólo roles con privilegios del rol cuyo proceso está siendo terminados o con privilegios del rol «%s» pueden terminar este proceso." -#: storage/ipc/procsignal.c:420 +#: storage/ipc/procsignal.c:416 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" -msgstr "" +msgstr "aún esperando que el backend con PID %d acepte ProcSignalBarrier" -#: storage/ipc/shm_mq.c:384 +#: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" msgstr "no se puede enviar un mensaje de tamaño %zu mediante la cola de memoria compartida" -#: storage/ipc/shm_mq.c:719 +#: storage/ipc/shm_mq.c:718 #, c-format msgid "invalid message size %zu in shared memory queue" msgstr "tamaño no válido de mensaje %zu en cola de memoria compartida" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:982 -#: storage/lmgr/lock.c:1020 storage/lmgr/lock.c:2810 storage/lmgr/lock.c:4195 -#: storage/lmgr/lock.c:4260 storage/lmgr/lock.c:4610 -#: storage/lmgr/predicate.c:2412 storage/lmgr/predicate.c:2427 -#: storage/lmgr/predicate.c:3824 storage/lmgr/predicate.c:4871 -#: utils/hash/dynahash.c:1107 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:984 +#: storage/lmgr/lock.c:1022 storage/lmgr/lock.c:2835 storage/lmgr/lock.c:4220 +#: storage/lmgr/lock.c:4285 storage/lmgr/lock.c:4635 +#: storage/lmgr/predicate.c:2468 storage/lmgr/predicate.c:2483 +#: storage/lmgr/predicate.c:3880 storage/lmgr/predicate.c:4927 +#: utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "memoria compartida agotada" -#: storage/ipc/shmem.c:170 storage/ipc/shmem.c:266 +#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "memoria compartida agotada (%zu bytes solicitados)" -#: storage/ipc/shmem.c:445 +#: storage/ipc/shmem.c:436 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "no se pudo crear la entrada en ShmemIndex para la estructura «%s»" -#: storage/ipc/shmem.c:460 +#: storage/ipc/shmem.c:451 #, c-format msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu" msgstr "el tamaño de la entrada ShmemIndex es incorrecto para la estructura «%s»: se esperaba %zu, real %zu" -#: storage/ipc/shmem.c:479 +#: storage/ipc/shmem.c:470 #, c-format msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)" msgstr "el espacio de memoria compartida es insuficiente para la estructura «%s» (%zu bytes solicitados)" -#: storage/ipc/shmem.c:511 storage/ipc/shmem.c:530 +#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 #, c-format msgid "requested shared memory size overflows size_t" msgstr "la petición de tamaño de memoria compartida desborda size_t" #: storage/ipc/signalfuncs.c:72 -#, fuzzy, c-format -#| msgid "PID %d is not a PostgreSQL server process" +#, c-format msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %d no es un proceso servidor de PostgreSQL" -#: storage/ipc/signalfuncs.c:104 storage/lmgr/proc.c:1379 -#: utils/adt/mcxtfuncs.c:190 +#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1453 +#: utils/adt/mcxtfuncs.c:182 #, c-format msgid "could not send signal to process %d: %m" msgstr "no se pudo enviar la señal al proceso %d: %m" -#: storage/ipc/signalfuncs.c:124 storage/ipc/signalfuncs.c:131 -#, fuzzy, c-format -#| msgid "permission denied to create role" +#: storage/ipc/signalfuncs.c:129 storage/ipc/signalfuncs.c:136 +#, c-format msgid "permission denied to cancel query" -msgstr "se ha denegado el permiso para crear el rol" +msgstr "se ha denegado el permiso para cancelar la consulta" -#: storage/ipc/signalfuncs.c:125 +#: storage/ipc/signalfuncs.c:130 #, c-format -msgid "Only roles with the %s attribute may cancel queries of roles with %s." -msgstr "" +msgid "Only roles with the %s attribute may cancel queries of roles with the %s attribute." +msgstr "Sólo roles con el atributo %s pueden cancelar consultas de roles con el atributo %s." -#: storage/ipc/signalfuncs.c:132 +#: storage/ipc/signalfuncs.c:137 #, c-format msgid "Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query." -msgstr "" +msgstr "Sólo roles con privilegios del rol cuya consulta está siendo cancelada o con privilegios del rol «%s» pueden cancelar esta consulta." -#: storage/ipc/signalfuncs.c:174 +#: storage/ipc/signalfuncs.c:179 #, c-format msgid "could not check the existence of the backend with PID %d: %m" msgstr "no se pudo comprobar la existencia del proceso de servidor con PID %d: %m" -#: storage/ipc/signalfuncs.c:192 +#: storage/ipc/signalfuncs.c:197 #, c-format msgid "backend with PID %d did not terminate within %lld millisecond" msgid_plural "backend with PID %d did not terminate within %lld milliseconds" msgstr[0] "el proceso de servidor con PID %d no terminó dentro de %lld milisegundo" msgstr[1] "el proceso de servidor con PID %d no terminó dentro de %lld milisegundos" -#: storage/ipc/signalfuncs.c:223 +#: storage/ipc/signalfuncs.c:228 #, c-format msgid "\"timeout\" must not be negative" msgstr "\"timeout\" no debe ser negativo" -#: storage/ipc/signalfuncs.c:231 -#, c-format -msgid "Only roles with the %s attribute may terminate processes of roles with %s." -msgstr "" - -#: storage/ipc/signalfuncs.c:279 -#, c-format -msgid "must be superuser to rotate log files with adminpack 1.0" -msgstr "bebe ser superusuario para rotar archivos de log con adminpack 1.0" - -#. translator: %s is a SQL function name -#: storage/ipc/signalfuncs.c:281 utils/adt/genfile.c:250 -#, c-format -msgid "Consider using %s, which is part of core, instead." -msgstr "Considere usar %s, que es parte del servidor, en su lugar." - -#: storage/ipc/signalfuncs.c:287 storage/ipc/signalfuncs.c:307 +#: storage/ipc/signalfuncs.c:285 #, c-format msgid "rotation not possible because log collection not active" msgstr "la rotación no es posible porque la recoleccion de log no está activa" -#: storage/ipc/standby.c:330 +#: storage/ipc/standby.c:329 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "la recuperación aún está esperando después de %ld.%03d ms: %s" -#: storage/ipc/standby.c:339 +#: storage/ipc/standby.c:338 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "la recuperación terminó de esperar después de %ld.%03d ms: %s" -#: storage/ipc/standby.c:921 tcop/postgres.c:3384 +#: storage/ipc/standby.c:920 tcop/postgres.c:3196 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "cancelando la sentencia debido a un conflicto con la recuperación" -#: storage/ipc/standby.c:922 tcop/postgres.c:2533 +#: storage/ipc/standby.c:921 tcop/postgres.c:2557 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "La transacción del usuario causó un «deadlock» con la recuperación." -#: storage/ipc/standby.c:1479 +#: storage/ipc/standby.c:1486 msgid "unknown reason" msgstr "razón desconocida" -#: storage/ipc/standby.c:1484 +#: storage/ipc/standby.c:1491 msgid "recovery conflict on buffer pin" msgstr "conflicto de recuperación en «pin» de búfer" -#: storage/ipc/standby.c:1487 +#: storage/ipc/standby.c:1494 msgid "recovery conflict on lock" msgstr "conflicto de recuperación en bloqueo" -#: storage/ipc/standby.c:1490 +#: storage/ipc/standby.c:1497 msgid "recovery conflict on tablespace" msgstr "conflicto de recuperación en tablespace" -#: storage/ipc/standby.c:1493 +#: storage/ipc/standby.c:1500 msgid "recovery conflict on snapshot" msgstr "conflicto de recuperación en snapshot" -#: storage/ipc/standby.c:1496 -#, fuzzy -#| msgid "recovery conflict on snapshot" +#: storage/ipc/standby.c:1503 msgid "recovery conflict on replication slot" -msgstr "conflicto de recuperación en snapshot" +msgstr "conflicto de recuperación en slot de replicación" -#: storage/ipc/standby.c:1499 +#: storage/ipc/standby.c:1506 msgid "recovery conflict on buffer deadlock" msgstr "conflicto de recuperación en deadlock de búfer" -#: storage/ipc/standby.c:1502 +#: storage/ipc/standby.c:1509 msgid "recovery conflict on database" msgstr "conflicto de recuperación en base de datos" -#: storage/large_object/inv_api.c:191 +#: storage/large_object/inv_api.c:190 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "la entrada pg_largeobject para el OID %u, página %d tiene tamaño de campo %d no válido" -#: storage/large_object/inv_api.c:274 +#: storage/large_object/inv_api.c:272 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "opciones no válidas para abrir un objeto grande: %d" -#: storage/large_object/inv_api.c:457 +#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 +#: storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 +#: storage/large_object/inv_api.c:807 +#, c-format +msgid "permission denied for large object %u" +msgstr "permiso denegado al objeto grande %u" + +#: storage/large_object/inv_api.c:455 #, c-format msgid "invalid whence setting: %d" msgstr "parámetro «whence» no válido: %d" -#: storage/large_object/inv_api.c:629 +#: storage/large_object/inv_api.c:627 #, c-format msgid "invalid large object write request size: %d" msgstr "tamaño de petición de escritura de objeto grande no válido: %d" -#: storage/lmgr/deadlock.c:1105 +#: storage/lmgr/deadlock.c:1104 #, c-format msgid "Process %d waits for %s on %s; blocked by process %d." msgstr "El proceso %d espera %s en %s; bloqueado por proceso %d." -#: storage/lmgr/deadlock.c:1124 +#: storage/lmgr/deadlock.c:1123 #, c-format msgid "Process %d: %s" msgstr "Proceso %d: %s" -#: storage/lmgr/deadlock.c:1133 +#: storage/lmgr/deadlock.c:1132 #, c-format msgid "deadlock detected" msgstr "se ha detectado un deadlock" -#: storage/lmgr/deadlock.c:1136 +#: storage/lmgr/deadlock.c:1135 #, c-format msgid "See server log for query details." msgstr "Vea el registro del servidor para obtener detalles de las consultas." -#: storage/lmgr/lmgr.c:859 +#: storage/lmgr/lmgr.c:848 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "mientras se actualizaba la tupla (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:862 +#: storage/lmgr/lmgr.c:851 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "mientras se borraba la tupla (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:865 +#: storage/lmgr/lmgr.c:854 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "mientras se bloqueaba la tupla (%u,%u) de la relación «%s»" -#: storage/lmgr/lmgr.c:868 +#: storage/lmgr/lmgr.c:857 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "mientras se bloqueaba la versión actualizada (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:871 +#: storage/lmgr/lmgr.c:860 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "mientras se insertaba la tupla de índice (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:874 +#: storage/lmgr/lmgr.c:863 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "mientras se verificaba la unicidad de la tupla (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:877 +#: storage/lmgr/lmgr.c:866 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "mientras se verificaba la tupla actualizada (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:880 +#: storage/lmgr/lmgr.c:869 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "mientras se verificaba una restricción de exclusión en la tupla (%u,%u) en la relación «%s»" -#: storage/lmgr/lmgr.c:1174 +#: storage/lmgr/lmgr.c:1239 #, c-format msgid "relation %u of database %u" msgstr "relación %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1180 +#: storage/lmgr/lmgr.c:1245 #, c-format msgid "extension of relation %u of database %u" msgstr "extensión de la relación %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1186 +#: storage/lmgr/lmgr.c:1251 #, c-format msgid "pg_database.datfrozenxid of database %u" msgstr "pg_database.datfrozenxid de la base de datos %u" -#: storage/lmgr/lmgr.c:1191 +#: storage/lmgr/lmgr.c:1256 #, c-format msgid "page %u of relation %u of database %u" msgstr "página %u de la relación %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1198 +#: storage/lmgr/lmgr.c:1263 #, c-format msgid "tuple (%u,%u) of relation %u of database %u" msgstr "tupla (%u,%u) de la relación %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1206 +#: storage/lmgr/lmgr.c:1271 #, c-format msgid "transaction %u" msgstr "transacción %u" -#: storage/lmgr/lmgr.c:1211 +#: storage/lmgr/lmgr.c:1276 #, c-format msgid "virtual transaction %d/%u" msgstr "transacción virtual %d/%u" -#: storage/lmgr/lmgr.c:1217 +#: storage/lmgr/lmgr.c:1282 #, c-format msgid "speculative token %u of transaction %u" msgstr "token especulativo %u de la transacción %u" -#: storage/lmgr/lmgr.c:1223 +#: storage/lmgr/lmgr.c:1288 #, c-format msgid "object %u of class %u of database %u" msgstr "objeto %u de clase %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1231 +#: storage/lmgr/lmgr.c:1296 #, c-format msgid "user lock [%u,%u,%u]" -msgstr "candado de usuario [%u,%u,%u]" +msgstr "“lock” de usuario [%u,%u,%u]" # XXX is this a good translation? -#: storage/lmgr/lmgr.c:1238 +#: storage/lmgr/lmgr.c:1303 #, c-format msgid "advisory lock [%u,%u,%u,%u]" -msgstr "candado consultivo [%u,%u,%u,%u]" +msgstr "“lock” consultivo [%u,%u,%u,%u]" -#: storage/lmgr/lmgr.c:1246 -#, fuzzy, c-format -#| msgid "extension of relation %u of database %u" +#: storage/lmgr/lmgr.c:1311 +#, c-format msgid "remote transaction %u of subscription %u of database %u" -msgstr "extensión de la relación %u de la base de datos %u" +msgstr "transacción remota %u de la suscripción %u de la base de datos %u" -#: storage/lmgr/lmgr.c:1253 +#: storage/lmgr/lmgr.c:1318 #, c-format msgid "unrecognized locktag type %d" msgstr "tipo de locktag %d no reconocido" -#: storage/lmgr/lock.c:803 +#: storage/lmgr/lock.c:812 #, c-format msgid "cannot acquire lock mode %s on database objects while recovery is in progress" -msgstr "no se puede adquirir candado en modo %s en objetos de la base de datos mientras la recuperación está en proceso" +msgstr "no se puede adquirir “lock” en modo %s en objetos de la base de datos mientras la recuperación está en proceso" -#: storage/lmgr/lock.c:805 +#: storage/lmgr/lock.c:814 #, c-format msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery." -msgstr "Sólo candados RowExclusiveLock o menor pueden ser adquiridos en objetos de la base de datos durante la recuperación." - -#: storage/lmgr/lock.c:983 storage/lmgr/lock.c:1021 storage/lmgr/lock.c:2811 -#: storage/lmgr/lock.c:4196 storage/lmgr/lock.c:4261 storage/lmgr/lock.c:4611 -#, c-format -msgid "You might need to increase max_locks_per_transaction." -msgstr "Puede ser necesario incrementar max_locks_per_transaction." +msgstr "Sólo “locks” RowExclusiveLock o menor pueden ser adquiridos en objetos de la base de datos durante la recuperación." -#: storage/lmgr/lock.c:3259 storage/lmgr/lock.c:3327 storage/lmgr/lock.c:3443 +#: storage/lmgr/lock.c:3284 storage/lmgr/lock.c:3352 storage/lmgr/lock.c:3468 #, c-format msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object" -msgstr "no se puede hacer PREPARE mientras se mantienen candados a nivel de sesión y transacción simultáneamente sobre el mismo objeto" +msgstr "no se puede hacer PREPARE mientras se mantienen “locks” a nivel de sesión y transacción simultáneamente sobre el mismo objeto" -#: storage/lmgr/predicate.c:649 +#: storage/lmgr/predicate.c:653 #, c-format msgid "not enough elements in RWConflictPool to record a read/write conflict" msgstr "no hay suficientes elementos en RWConflictPool para registrar un conflicto read/write" -#: storage/lmgr/predicate.c:650 storage/lmgr/predicate.c:675 +#: storage/lmgr/predicate.c:654 storage/lmgr/predicate.c:679 #, c-format -msgid "You might need to run fewer transactions at a time or increase max_connections." -msgstr "Puede ser necesario ejecutar menos transacciones al mismo tiempo, o incrementar max_connections." +msgid "You might need to run fewer transactions at a time or increase \"max_connections\"." +msgstr "Puede ser necesario ejecutar menos transacciones al mismo tiempo, o incrementar «max_connections»." -#: storage/lmgr/predicate.c:674 +#: storage/lmgr/predicate.c:678 #, c-format msgid "not enough elements in RWConflictPool to record a potential read/write conflict" msgstr "no hay suficientes elementos en RWConflictPool para registrar un potencial conflicto read/write" -#: storage/lmgr/predicate.c:1630 +#: storage/lmgr/predicate.c:1686 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "«default_transaction_isolation» está definido a «serializable»." -#: storage/lmgr/predicate.c:1631 +#: storage/lmgr/predicate.c:1687 #, c-format msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default." msgstr "Puede usar «SET default_transaction_isolation = 'repeatable read'» para cambiar el valor por omisión." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1738 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "una transacción que importa un snapshot no debe ser READ ONLY DEFERRABLE" -#: storage/lmgr/predicate.c:1761 utils/time/snapmgr.c:570 -#: utils/time/snapmgr.c:576 +#: storage/lmgr/predicate.c:1817 utils/time/snapmgr.c:535 +#: utils/time/snapmgr.c:541 #, c-format msgid "could not import the requested snapshot" msgstr "no se pudo importar el snapshot solicitado" -#: storage/lmgr/predicate.c:1762 utils/time/snapmgr.c:577 +#: storage/lmgr/predicate.c:1818 utils/time/snapmgr.c:542 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "El proceso de origen con PID %d ya no está en ejecución." -#: storage/lmgr/predicate.c:2413 storage/lmgr/predicate.c:2428 -#: storage/lmgr/predicate.c:3825 -#, c-format -msgid "You might need to increase max_pred_locks_per_transaction." -msgstr "Puede ser necesario incrementar max_pred_locks_per_transaction." - -#: storage/lmgr/predicate.c:3935 storage/lmgr/predicate.c:3971 -#: storage/lmgr/predicate.c:4004 storage/lmgr/predicate.c:4012 -#: storage/lmgr/predicate.c:4051 storage/lmgr/predicate.c:4281 -#: storage/lmgr/predicate.c:4600 storage/lmgr/predicate.c:4612 -#: storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4695 +#: storage/lmgr/predicate.c:3991 storage/lmgr/predicate.c:4027 +#: storage/lmgr/predicate.c:4060 storage/lmgr/predicate.c:4068 +#: storage/lmgr/predicate.c:4107 storage/lmgr/predicate.c:4337 +#: storage/lmgr/predicate.c:4656 storage/lmgr/predicate.c:4668 +#: storage/lmgr/predicate.c:4715 storage/lmgr/predicate.c:4751 #, c-format msgid "could not serialize access due to read/write dependencies among transactions" msgstr "no se pudo serializar el acceso debido a dependencias read/write entre transacciones" -#: storage/lmgr/predicate.c:3937 storage/lmgr/predicate.c:3973 -#: storage/lmgr/predicate.c:4006 storage/lmgr/predicate.c:4014 -#: storage/lmgr/predicate.c:4053 storage/lmgr/predicate.c:4283 -#: storage/lmgr/predicate.c:4602 storage/lmgr/predicate.c:4614 -#: storage/lmgr/predicate.c:4661 storage/lmgr/predicate.c:4697 +#: storage/lmgr/predicate.c:3993 storage/lmgr/predicate.c:4029 +#: storage/lmgr/predicate.c:4062 storage/lmgr/predicate.c:4070 +#: storage/lmgr/predicate.c:4109 storage/lmgr/predicate.c:4339 +#: storage/lmgr/predicate.c:4658 storage/lmgr/predicate.c:4670 +#: storage/lmgr/predicate.c:4717 storage/lmgr/predicate.c:4753 #, c-format msgid "The transaction might succeed if retried." msgstr "La transacción podría tener éxito si es reintentada." -#: storage/lmgr/proc.c:349 +#: storage/lmgr/proc.c:353 #, c-format -msgid "number of requested standby connections exceeds max_wal_senders (currently %d)" -msgstr "la cantidad de conexiones standby pedidas excede max_wal_senders (actualmente %d)" +msgid "number of requested standby connections exceeds \"max_wal_senders\" (currently %d)" +msgstr "la cantidad de conexiones standby pedidas excede «max_wal_senders» (actualmente %d)" -#: storage/lmgr/proc.c:1472 +#: storage/lmgr/proc.c:1546 #, c-format msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" msgstr "el proceso %d evitó un deadlock para %s en %s reordenando la cola después de %ld.%03d ms" -#: storage/lmgr/proc.c:1487 +#: storage/lmgr/proc.c:1561 #, c-format msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "el proceso %d detectó un deadlock mientras esperaba %s en %s después de %ld.%03d ms" -#: storage/lmgr/proc.c:1496 +#: storage/lmgr/proc.c:1570 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "el proceso %d aún espera %s en %s después de %ld.%03d ms" -#: storage/lmgr/proc.c:1503 +#: storage/lmgr/proc.c:1577 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "el proceso %d adquirió %s en %s después de %ld.%03d ms" -#: storage/lmgr/proc.c:1520 +#: storage/lmgr/proc.c:1594 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "el proceso %d no pudo adquirir %s en %s después de %ld.%03d ms" @@ -22334,68 +22844,202 @@ msgstr "los largos de ítem están corruptos: total %u, espacio disponible %u" msgid "corrupted line pointer: offset = %u, size = %u" msgstr "puntero de ítem corrupto: desplazamiento = %u, tamaño = %u" -#: storage/smgr/md.c:484 storage/smgr/md.c:546 +#: storage/smgr/md.c:485 storage/smgr/md.c:547 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "no se pudo extender el archivo «%s» más allá de %u bloques" -#: storage/smgr/md.c:499 storage/smgr/md.c:610 +#: storage/smgr/md.c:500 storage/smgr/md.c:611 #, c-format msgid "could not extend file \"%s\": %m" msgstr "no se pudo extender el archivo «%s»: %m" -#: storage/smgr/md.c:505 +#: storage/smgr/md.c:506 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "no se pudo extender el archivo «%s»: sólo se escribieron %d de %d bytes en el bloque %u" -#: storage/smgr/md.c:588 -#, fuzzy, c-format -#| msgid "could not extend file \"%s\": %m" -msgid "could not extend file \"%s\" with FileFallocate(): %m" -msgstr "no se pudo extender el archivo «%s»: %m" - -#: storage/smgr/md.c:779 +#: storage/smgr/md.c:589 #, c-format -msgid "could not read block %u in file \"%s\": %m" -msgstr "no se pudo leer el bloque %u del archivo «%s»: %m" +msgid "could not extend file \"%s\" with FileFallocate(): %m" +msgstr "no se pudo extender el archivo «%s» con FileFallocate(): %m" -#: storage/smgr/md.c:795 +#: storage/smgr/md.c:869 #, c-format -msgid "could not read block %u in file \"%s\": read only %d of %d bytes" -msgstr "no se pudo leer el bloque %u del archivo «%s»: se leyeron sólo %d de %d bytes" +msgid "could not read blocks %u..%u in file \"%s\": %m" +msgstr "no se pudo leer los bloques %u..%u del archivo «%s»: %m" -#: storage/smgr/md.c:853 +#: storage/smgr/md.c:895 #, c-format -msgid "could not write block %u in file \"%s\": %m" -msgstr "no se pudo escribir el bloque %u en el archivo «%s»: %m" +msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" +msgstr "no se pudo leer los bloques %u..%u del archivo «%s»: se leyeron sólo %zu de %zu bytes" -#: storage/smgr/md.c:858 +#: storage/smgr/md.c:995 #, c-format -msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" -msgstr "no se pudo escribir el bloque %u en el archivo «%s»: se escribieron sólo %d de %d bytes" +msgid "could not write blocks %u..%u in file \"%s\": %m" +msgstr "no se pudo escribir los bloques %u..%u en el archivo «%s»: %m" -#: storage/smgr/md.c:1009 +#: storage/smgr/md.c:1165 #, c-format msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" msgstr "no se pudo truncar el archivo «%s» a %u bloques: es de sólo %u bloques ahora" -#: storage/smgr/md.c:1064 +#: storage/smgr/md.c:1220 #, c-format msgid "could not truncate file \"%s\" to %u blocks: %m" msgstr "no se pudo truncar el archivo «%s» a %u bloques: %m" -#: storage/smgr/md.c:1491 +#: storage/smgr/md.c:1700 #, c-format msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" msgstr "no se pudo abrir el archivo «%s» (bloque buscado %u): el segmento previo sólo tiene %u bloques" -#: storage/smgr/md.c:1505 +#: storage/smgr/md.c:1714 #, c-format msgid "could not open file \"%s\" (target block %u): %m" msgstr "no se pudo abrir el archivo «%s» (bloque buscado %u): %m" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2132 +#: tcop/backend_startup.c:85 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "No se pudo cargar la configuración SSL en proceso secundario" + +#: tcop/backend_startup.c:208 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "conexión recibida: host=%s port=%s" + +#: tcop/backend_startup.c:213 +#, c-format +msgid "connection received: host=%s" +msgstr "conexión recibida: host=%s" + +#: tcop/backend_startup.c:277 +#, c-format +msgid "the database system is starting up" +msgstr "el sistema de base de datos está iniciándose" + +#: tcop/backend_startup.c:283 +#, c-format +msgid "the database system is not yet accepting connections" +msgstr "el sistema de bases de datos aún no está aceptando conexiones" + +#: tcop/backend_startup.c:284 +#, c-format +msgid "Consistent recovery state has not been yet reached." +msgstr "Aún no se ha alcanzado un estado de recuperación consistente." + +#: tcop/backend_startup.c:288 +#, c-format +msgid "the database system is not accepting connections" +msgstr "el sistema de bases de datos no está aceptando conexiones" + +#: tcop/backend_startup.c:289 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "El modo hot standby está desactivado." + +#: tcop/backend_startup.c:294 +#, c-format +msgid "the database system is shutting down" +msgstr "el sistema de base de datos está apagándose" + +#: tcop/backend_startup.c:299 +#, c-format +msgid "the database system is in recovery mode" +msgstr "el sistema de base de datos está en modo de recuperación" + +#: tcop/backend_startup.c:414 +#, c-format +msgid "received direct SSL connection request without ALPN protocol negotiation extension" +msgstr "se recibió petición de conexión SSL directa sin la extensión de negociación de protocolo ALPN" + +#: tcop/backend_startup.c:420 +#, c-format +msgid "direct SSL connection accepted" +msgstr "conexión SSL directa aceptada" + +#: tcop/backend_startup.c:430 +#, c-format +msgid "direct SSL connection rejected" +msgstr "conexión SSL directa rechazada" + +#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#, c-format +msgid "incomplete startup packet" +msgstr "el paquete de inicio está incompleto" + +#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#, c-format +msgid "invalid length of startup packet" +msgstr "el de paquete de inicio tiene largo incorrecto" + +#: tcop/backend_startup.c:573 +#, c-format +msgid "SSLRequest accepted" +msgstr "SSLRequest aceptado" + +#: tcop/backend_startup.c:576 +#, c-format +msgid "SSLRequest rejected" +msgstr "SSLRequest rechazado" + +#: tcop/backend_startup.c:585 +#, c-format +msgid "failed to send SSL negotiation response: %m" +msgstr "no se pudo enviar la respuesta de negociación SSL: %m" + +#: tcop/backend_startup.c:603 +#, c-format +msgid "received unencrypted data after SSL request" +msgstr "se recibieron datos no cifrados después de petición SSL" + +#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#, c-format +msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." +msgstr "Esto podría ser un error en el software cliente o evidencia de un intento de ataque man-in-the-middle." + +#: tcop/backend_startup.c:627 +#, c-format +msgid "GSSENCRequest accepted" +msgstr "GSSENCRequest aceptado" + +#: tcop/backend_startup.c:630 +#, c-format +msgid "GSSENCRequest rejected" +msgstr "GSSENCRequest rechazado" + +#: tcop/backend_startup.c:639 +#, c-format +msgid "failed to send GSSAPI negotiation response: %m" +msgstr "no se pudo enviar la respuesta de negociación GSSAPI: %m" + +#: tcop/backend_startup.c:657 +#, c-format +msgid "received unencrypted data after GSSAPI encryption request" +msgstr "se recibieron datos no cifrados después de petición de cifrado GSSAPI" + +#: tcop/backend_startup.c:681 +#, c-format +msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" +msgstr "el protocolo %u.%u no está soportado: servidor soporta %u.0 hasta %u.%u" + +#: tcop/backend_startup.c:744 +#, c-format +msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." +msgstr "Los valores válidos son: «false», 0, «true», 1, «database»." + +#: tcop/backend_startup.c:785 +#, c-format +msgid "invalid startup packet layout: expected terminator as last byte" +msgstr "el paquete de inicio no es válido: se esperaba un terminador en el último byte" + +#: tcop/backend_startup.c:802 +#, c-format +msgid "no PostgreSQL user name specified in startup packet" +msgstr "no se especifica un nombre de usuario en el paquete de inicio" + +#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "no existe la función con OID %u" @@ -22410,8 +23054,8 @@ msgstr "no se puede llamar a la función «%s» mediante la interfaz fastpath" msgid "fastpath function call: \"%s\" (OID %u)" msgstr "llamada a función fastpath: «%s» (OID %u)" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 -#: tcop/postgres.c:2059 tcop/postgres.c:2309 +#: tcop/fastpath.c:313 tcop/postgres.c:1369 tcop/postgres.c:1605 +#: tcop/postgres.c:2071 tcop/postgres.c:2333 #, c-format msgid "duration: %s ms" msgstr "duración: %s ms" @@ -22441,317 +23085,320 @@ msgstr "el tamaño de argumento %d no es válido en el mensaje de llamada a func msgid "incorrect binary data format in function argument %d" msgstr "el formato de datos binarios es incorrecto en argumento %d a función" -#: tcop/postgres.c:463 tcop/postgres.c:4877 +#: tcop/postgres.c:467 tcop/postgres.c:5012 #, c-format msgid "invalid frontend message type %d" msgstr "el tipo de mensaje de frontend %d no es válido" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1076 #, c-format msgid "statement: %s" msgstr "sentencia: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1374 #, c-format msgid "duration: %s ms statement: %s" msgstr "duración: %s ms sentencia: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1480 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "no se pueden insertar múltiples órdenes en una sentencia preparada" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1610 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "duración: %s ms parse: %s: %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2629 +#: tcop/postgres.c:1677 tcop/postgres.c:2653 #, c-format msgid "unnamed prepared statement does not exist" msgstr "no existe una sentencia preparada sin nombre" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1729 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "el mensaje de «bind» tiene %d formatos de parámetro pero %d parámetros" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1735 #, c-format msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d" msgstr "el mensaje de «bind» entrega %d parámetros, pero la sentencia preparada «%s» requiere %d" -#: tcop/postgres.c:1937 +#: tcop/postgres.c:1949 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "el formato de datos binarios es incorrecto en el parámetro de «bind» %d" -#: tcop/postgres.c:2064 +#: tcop/postgres.c:2076 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "duración: %s ms bind %s%s%s: %s" -#: tcop/postgres.c:2118 tcop/postgres.c:2712 +#: tcop/postgres.c:2131 tcop/postgres.c:2735 #, c-format msgid "portal \"%s\" does not exist" msgstr "no existe el portal «%s»" -#: tcop/postgres.c:2189 +#: tcop/postgres.c:2213 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2191 tcop/postgres.c:2317 +#: tcop/postgres.c:2215 tcop/postgres.c:2341 msgid "execute fetch from" msgstr "ejecutar fetch desde" -#: tcop/postgres.c:2192 tcop/postgres.c:2318 +#: tcop/postgres.c:2216 tcop/postgres.c:2342 msgid "execute" msgstr "ejecutar" -#: tcop/postgres.c:2314 +#: tcop/postgres.c:2338 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "duración: %s ms %s %s%s%s: %s" -#: tcop/postgres.c:2462 +#: tcop/postgres.c:2486 #, c-format msgid "prepare: %s" msgstr "prepare: %s" -#: tcop/postgres.c:2487 +#: tcop/postgres.c:2511 #, c-format -msgid "parameters: %s" -msgstr "parámetros: %s" +msgid "Parameters: %s" +msgstr "Parámetros: %s" -#: tcop/postgres.c:2502 +#: tcop/postgres.c:2526 #, c-format -msgid "abort reason: recovery conflict" -msgstr "razón para abortar: conflicto en la recuperación" +msgid "Abort reason: recovery conflict" +msgstr "Razón para abortar: conflicto en la recuperación" -#: tcop/postgres.c:2518 +#: tcop/postgres.c:2542 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "El usuario mantuvo el búfer compartido «clavado» por demasiado tiempo." -#: tcop/postgres.c:2521 +#: tcop/postgres.c:2545 #, c-format msgid "User was holding a relation lock for too long." msgstr "El usuario mantuvo una relación bloqueada por demasiado tiempo." -#: tcop/postgres.c:2524 +#: tcop/postgres.c:2548 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "El usuario estaba o pudo haber estado usando un tablespace que debía ser eliminado." -#: tcop/postgres.c:2527 +#: tcop/postgres.c:2551 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "La consulta del usuario pudo haber necesitado examinar versiones de tuplas que debían eliminarse." -#: tcop/postgres.c:2530 -#, fuzzy, c-format -#| msgid "User was connected to a database that must be dropped." -msgid "User was using a logical slot that must be invalidated." -msgstr "El usuario estaba conectado a una base de datos que debía ser eliminada." +#: tcop/postgres.c:2554 +#, c-format +msgid "User was using a logical replication slot that must be invalidated." +msgstr "El usuario estaba usando un slot de replicación lógica que debía ser invalidado." -#: tcop/postgres.c:2536 +#: tcop/postgres.c:2560 #, c-format msgid "User was connected to a database that must be dropped." msgstr "El usuario estaba conectado a una base de datos que debía ser eliminada." -#: tcop/postgres.c:2575 +#: tcop/postgres.c:2599 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "portal «%s» parámetro $%d = %s" -#: tcop/postgres.c:2578 +#: tcop/postgres.c:2602 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "portal «%s» parámetro $%d" -#: tcop/postgres.c:2584 +#: tcop/postgres.c:2608 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "portal sin nombre, parámetro %d = %s" -#: tcop/postgres.c:2587 +#: tcop/postgres.c:2611 #, c-format msgid "unnamed portal parameter $%d" msgstr "portal sin nombre, parámetro %d" -#: tcop/postgres.c:2932 +#: tcop/postgres.c:2955 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "terminando la conexión debido a una señal SIGQUIT inesperada" -#: tcop/postgres.c:2938 +#: tcop/postgres.c:2961 #, c-format msgid "terminating connection because of crash of another server process" msgstr "terminando la conexión debido a una falla en otro proceso servidor" -#: tcop/postgres.c:2939 +#: tcop/postgres.c:2962 #, c-format msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory." msgstr "Postmaster ha ordenado que este proceso servidor cancele la transacción en curso y finalice la conexión, porque otro proceso servidor ha terminado anormalmente y podría haber corrompido la memoria compartida." -#: tcop/postgres.c:2943 tcop/postgres.c:3310 +#: tcop/postgres.c:2966 tcop/postgres.c:3219 #, c-format msgid "In a moment you should be able to reconnect to the database and repeat your command." msgstr "Dentro de un momento debería poder reconectarse y repetir la consulta." -#: tcop/postgres.c:2950 +#: tcop/postgres.c:2973 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "terminando la conexión debido a una orden de apagado inmediato" -#: tcop/postgres.c:3036 +#: tcop/postgres.c:3051 #, c-format msgid "floating-point exception" msgstr "excepción de coma flotante" -#: tcop/postgres.c:3037 +#: tcop/postgres.c:3052 #, c-format msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero." msgstr "Se ha recibido una señal de una operación de coma flotante no válida. Esto puede significar un resultado fuera de rango o una operación no válida, como una división por cero." -#: tcop/postgres.c:3214 +#: tcop/postgres.c:3217 +#, c-format +msgid "terminating connection due to conflict with recovery" +msgstr "terminando la conexión debido a un conflicto con la recuperación" + +#: tcop/postgres.c:3289 #, c-format msgid "canceling authentication due to timeout" msgstr "cancelando la autentificación debido a que se agotó el tiempo de espera" -#: tcop/postgres.c:3218 +#: tcop/postgres.c:3293 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "terminando el proceso autovacuum debido a una orden del administrador" -#: tcop/postgres.c:3222 +#: tcop/postgres.c:3297 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "terminando el proceso de replicación lógica debido a una orden del administrador" -#: tcop/postgres.c:3239 tcop/postgres.c:3249 tcop/postgres.c:3308 -#, c-format -msgid "terminating connection due to conflict with recovery" -msgstr "terminando la conexión debido a un conflicto con la recuperación" - -#: tcop/postgres.c:3260 +#: tcop/postgres.c:3317 #, c-format msgid "terminating connection due to administrator command" msgstr "terminando la conexión debido a una orden del administrador" -#: tcop/postgres.c:3291 +#: tcop/postgres.c:3348 #, c-format msgid "connection to client lost" msgstr "se ha perdido la conexión al cliente" -#: tcop/postgres.c:3361 +#: tcop/postgres.c:3400 #, c-format msgid "canceling statement due to lock timeout" -msgstr "cancelando la sentencia debido a que se agotó el tiempo de espera de candados (locks)" +msgstr "cancelando la sentencia debido a que se agotó el tiempo de espera de “locks”" -#: tcop/postgres.c:3368 +#: tcop/postgres.c:3407 #, c-format msgid "canceling statement due to statement timeout" msgstr "cancelando la sentencia debido a que se agotó el tiempo de espera de sentencias" -#: tcop/postgres.c:3375 +#: tcop/postgres.c:3414 #, c-format msgid "canceling autovacuum task" msgstr "cancelando tarea de autovacuum" -#: tcop/postgres.c:3398 +#: tcop/postgres.c:3427 #, c-format msgid "canceling statement due to user request" msgstr "cancelando la sentencia debido a una petición del usuario" -#: tcop/postgres.c:3412 +#: tcop/postgres.c:3448 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "terminando la conexión debido a que se agotó el tiempo de espera para transacciones abiertas inactivas" -#: tcop/postgres.c:3423 +#: tcop/postgres.c:3461 +#, c-format +msgid "terminating connection due to transaction timeout" +msgstr "terminando la conexión debido a que se agotó el tiempo de espera para transacciones" + +#: tcop/postgres.c:3474 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "terminando la conexión debido a que se agotó el tiempo de espera para sesiones abiertas inactivas" -#: tcop/postgres.c:3514 +#: tcop/postgres.c:3564 #, c-format msgid "stack depth limit exceeded" msgstr "límite de profundidad de stack alcanzado" -#: tcop/postgres.c:3515 +#: tcop/postgres.c:3565 #, c-format msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." msgstr "Incremente el parámetro de configuración «max_stack_depth» (actualmente %dkB), después de asegurarse que el límite de profundidad de stack de la plataforma es adecuado." -#: tcop/postgres.c:3562 +#: tcop/postgres.c:3612 #, c-format msgid "\"max_stack_depth\" must not exceed %ldkB." msgstr "«max_stack_depth» no debe exceder %ldkB." -#: tcop/postgres.c:3564 +#: tcop/postgres.c:3614 #, c-format msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." msgstr "Incremente el límite de profundidad del stack del sistema usando «ulimit -s» o el equivalente de su sistema." -#: tcop/postgres.c:3587 -#, fuzzy, c-format -#| msgid "huge_page_size must be 0 on this platform." -msgid "client_connection_check_interval must be set to 0 on this platform." -msgstr "huge_page_size debe ser 0 en esta plataforma." +#: tcop/postgres.c:3637 +#, c-format +msgid "\"client_connection_check_interval\" must be set to 0 on this platform." +msgstr "«client_connection_check_interval» debe ser 0 en esta plataforma." -#: tcop/postgres.c:3608 +#: tcop/postgres.c:3658 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "No se puede activar el parámetro cuando «log_statement_stats» está activo." -#: tcop/postgres.c:3623 +#: tcop/postgres.c:3673 #, c-format msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true." msgstr "No se puede activar «log_statement_stats» cuando «log_parser_stats», «log_planner_stats» o «log_executor_stats» están activos." -#: tcop/postgres.c:3971 +#: tcop/postgres.c:4098 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "argumentos de línea de órdenes no válidos para proceso servidor: %s" -#: tcop/postgres.c:3972 tcop/postgres.c:3978 +#: tcop/postgres.c:4099 tcop/postgres.c:4105 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: tcop/postgres.c:3976 +#: tcop/postgres.c:4103 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: argumento de línea de órdenes no válido: %s" -#: tcop/postgres.c:4029 +#: tcop/postgres.c:4156 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: no se ha especificado base de datos ni usuario" -#: tcop/postgres.c:4774 +#: tcop/postgres.c:4909 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "subtipo %d de mensaje CLOSE no válido" -#: tcop/postgres.c:4811 +#: tcop/postgres.c:4946 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "subtipo %d de mensaje DESCRIBE no válido" -#: tcop/postgres.c:4898 +#: tcop/postgres.c:5033 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "la invocación «fastpath» de funciones no está soportada en conexiones de replicación" -#: tcop/postgres.c:4902 +#: tcop/postgres.c:5037 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "el protocolo extendido de consultas no está soportado en conexiones de replicación" -#: tcop/postgres.c:5082 +#: tcop/postgres.c:5217 #, c-format msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s" msgstr "desconexión: duración de sesión: %d:%02d:%02d.%03d usuario=%s base=%s host=%s%s%s" @@ -22761,57 +23408,56 @@ msgstr "desconexión: duración de sesión: %d:%02d:%02d.%03d usuario=%s base=%s msgid "bind message has %d result formats but query has %d columns" msgstr "el mensaje de «bind» tiene %d formatos de resultado pero la consulta tiene %d columnas" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:942 tcop/pquery.c:1696 #, c-format msgid "cursor can only scan forward" msgstr "el cursor sólo se puede desplazar hacia adelante" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:943 tcop/pquery.c:1697 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "Declárelo con SCROLL para permitirle desplazar hacia atrás." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:417 +#: tcop/utility.c:410 #, c-format msgid "cannot execute %s in a read-only transaction" msgstr "no se puede ejecutar %s en una transacción de sólo lectura" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:435 +#: tcop/utility.c:428 #, c-format msgid "cannot execute %s during a parallel operation" msgstr "no se puede ejecutar %s durante una operación paralela" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:454 +#: tcop/utility.c:447 #, c-format msgid "cannot execute %s during recovery" msgstr "no se puede ejecutar %s durante la recuperación" #. translator: %s is name of a SQL command, eg PREPARE -#: tcop/utility.c:472 +#: tcop/utility.c:465 #, c-format msgid "cannot execute %s within security-restricted operation" msgstr "no se puede ejecutar %s durante una operación restringida por seguridad" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:828 +#: tcop/utility.c:821 #, c-format msgid "cannot execute %s within a background process" msgstr "no se puede ejecutar %s dentro de un proceso en segundo plano" -#: tcop/utility.c:953 -#, fuzzy, c-format -#| msgid "permission denied for sequence %s" +#. translator: %s is name of a SQL command, eg CHECKPOINT +#: tcop/utility.c:947 +#, c-format msgid "permission denied to execute %s command" -msgstr "permiso denegado a la secuencia %s" +msgstr "permiso denegado a ejecutar la sentencia %s" -#: tcop/utility.c:955 -#, fuzzy, c-format -#| msgid "Set the privileges of the element type instead." +#: tcop/utility.c:949 +#, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." -msgstr "Defina los privilegios del tipo elemento en su lugar." +msgstr "Sólo los roles con privilegios del rol «%s» pueden ejecutar esta sentencia." #: tsearch/dict_ispell.c:52 tsearch/dict_thesaurus.c:616 #, c-format @@ -22962,13 +23608,13 @@ msgstr "marca de afijo «%s» no válida con el valor de marca «long»" msgid "could not open dictionary file \"%s\": %m" msgstr "no se pudo abrir el archivo de diccionario «%s»: %m" -#: tsearch/spell.c:749 utils/adt/regexp.c:224 jsonpath_gram.y:559 +#: tsearch/spell.c:749 utils/adt/regexp.c:223 jsonpath_gram.y:629 #, c-format msgid "invalid regular expression: %s" msgstr "la expresión regular no es válida: %s" #: tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 -#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18124 gram.y:18141 +#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18735 gram.y:18752 #, c-format msgid "syntax error" msgstr "error de sintaxis" @@ -23004,17 +23650,17 @@ msgstr "el número de aliases excede el número especificado %d" msgid "affix file contains both old-style and new-style commands" msgstr "el archivo de «affix» contiene órdenes en estilos antiguo y nuevo" -#: tsearch/to_tsany.c:195 utils/adt/tsvector.c:278 utils/adt/tsvector_op.c:1128 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "la cadena es demasiado larga para tsvector (%d bytes, máximo %d bytes)" -#: tsearch/ts_locale.c:238 +#: tsearch/ts_locale.c:236 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "línea %d del archivo de configuración «%s»: «%s»" -#: tsearch/ts_locale.c:317 +#: tsearch/ts_locale.c:315 #, c-format msgid "conversion from wchar_t to server encoding failed: %m" msgstr "conversión desde un wchar_t a la codificación del servidor falló: %m" @@ -23041,193 +23687,197 @@ msgstr "nombre de configuración de búsqueda en texto «%s» no válido" msgid "could not open stop-word file \"%s\": %m" msgstr "no se pudo abrir el archivo de stopwords «%s»: %m" -#: tsearch/wparser.c:308 tsearch/wparser.c:396 tsearch/wparser.c:473 +#: tsearch/wparser.c:306 tsearch/wparser.c:394 tsearch/wparser.c:471 #, c-format msgid "text search parser does not support headline creation" msgstr "el analizador de búsqueda en texto no soporta creación de encabezados (headline)" -#: tsearch/wparser_def.c:2648 +#: tsearch/wparser_def.c:2664 #, c-format msgid "unrecognized headline parameter: \"%s\"" msgstr "parámetro de encabezado (headline) no reconocido: «%s»" -#: tsearch/wparser_def.c:2658 +#: tsearch/wparser_def.c:2674 #, c-format -msgid "MinWords should be less than MaxWords" -msgstr "MinWords debería ser menor que MaxWords" +#| msgid "%s must be in range %d..%d" +msgid "%s must be less than %s" +msgstr "%s debe ser menor que %s" -#: tsearch/wparser_def.c:2662 +#: tsearch/wparser_def.c:2678 #, c-format -msgid "MinWords should be positive" -msgstr "MinWords debería ser positivo" +#| msgid "COST must be positive" +msgid "%s must be positive" +msgstr "%s debe ser positivo" -#: tsearch/wparser_def.c:2666 +#: tsearch/wparser_def.c:2682 tsearch/wparser_def.c:2686 #, c-format -msgid "ShortWord should be >= 0" -msgstr "ShortWord debería ser >= 0" +msgid "%s must be >= 0" +msgstr "%s debe ser >= 0" -#: tsearch/wparser_def.c:2670 +#: utils/activity/pgstat.c:435 #, c-format -msgid "MaxFragments should be >= 0" -msgstr "MaxFragments debería ser >= 0" - -#: utils/activity/pgstat.c:438 -#, fuzzy, c-format -#| msgid "could not open statistics file \"%s\": %m" msgid "could not unlink permanent statistics file \"%s\": %m" -msgstr "no se pudo abrir el archivo de estadísticas «%s»: %m" +msgstr "no se pudo eliminar el archivo permanente de estadísticas «%s»: %m" -#: utils/activity/pgstat.c:1241 -#, fuzzy, c-format -#| msgid "unrecognized statistics kind \"%s\"" +#: utils/activity/pgstat.c:1255 +#, c-format msgid "invalid statistics kind: \"%s\"" -msgstr "tipo de estadísticas «%s» no reconocido" +msgstr "tipo de estadísticas no válido: «%s»" -#: utils/activity/pgstat.c:1321 +#: utils/activity/pgstat.c:1335 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "no se pudo abrir el archivo temporal de estadísticas «%s»: %m" -#: utils/activity/pgstat.c:1433 +#: utils/activity/pgstat.c:1455 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "no se pudo escribir el archivo temporal de estadísticas «%s»: %m" -#: utils/activity/pgstat.c:1442 +#: utils/activity/pgstat.c:1464 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "no se pudo cerrar el archivo temporal de estadísticas «%s»: %m" -#: utils/activity/pgstat.c:1450 +#: utils/activity/pgstat.c:1472 #, c-format msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" msgstr "no se pudo cambiar el nombre al archivo temporal de estadísticas de «%s» a «%s»: %m" -#: utils/activity/pgstat.c:1499 +#: utils/activity/pgstat.c:1521 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "no se pudo abrir el archivo de estadísticas «%s»: %m" -#: utils/activity/pgstat.c:1661 +#: utils/activity/pgstat.c:1683 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "el archivo de estadísticas «%s» está corrupto" #: utils/activity/pgstat_function.c:118 -#, fuzzy, c-format -#| msgid "cast function must be a normal function" +#, c-format msgid "function call to dropped function" -msgstr "la función de conversión debe ser una función normal" +msgstr "invocación a una función eliminada" -#: utils/activity/pgstat_xact.c:363 +#: utils/activity/pgstat_xact.c:362 #, c-format msgid "resetting existing statistics for kind %s, db=%u, oid=%u" -msgstr "" +msgstr "reseteando estadísticas existentes para el tipo %s, db=%u, oid=%u" + +#: utils/activity/wait_event.c:207 utils/activity/wait_event.c:232 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "ya existe un “wait event” llamado «%s» en el tipo «%s»" + +#: utils/activity/wait_event.c:246 +#, c-format +msgid "too many custom wait events" +msgstr "demasiados “wait events” definidos por el usuario" -#: utils/adt/acl.c:177 utils/adt/name.c:93 +#: utils/adt/acl.c:183 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "el identificador es demasiado largo" -#: utils/adt/acl.c:178 utils/adt/name.c:94 +#: utils/adt/acl.c:184 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "El identificador debe ser menor a %d caracteres." -#: utils/adt/acl.c:266 +#: utils/adt/acl.c:272 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "palabra clave no reconocida: «%s»" -#: utils/adt/acl.c:267 +#: utils/adt/acl.c:273 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "Palabra clave de ACL debe ser «group» o «user»." -#: utils/adt/acl.c:275 +#: utils/adt/acl.c:281 #, c-format msgid "missing name" msgstr "falta un nombre" -#: utils/adt/acl.c:276 +#: utils/adt/acl.c:282 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "Debe venir un nombre después de una palabra clave «group» o «user»." -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:288 #, c-format msgid "missing \"=\" sign" msgstr "falta un signo «=»" -#: utils/adt/acl.c:344 +#: utils/adt/acl.c:350 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "carácter de modo no válido: debe ser uno de «%s»" -#: utils/adt/acl.c:374 +#: utils/adt/acl.c:380 #, c-format msgid "a name must follow the \"/\" sign" msgstr "debe venir un nombre después del signo «/»" -#: utils/adt/acl.c:386 +#: utils/adt/acl.c:392 #, c-format msgid "defaulting grantor to user ID %u" msgstr "usando el cedente por omisión con ID %u" -#: utils/adt/acl.c:572 +#: utils/adt/acl.c:578 #, c-format msgid "ACL array contains wrong data type" msgstr "el array ACL contiene tipo de datos incorrecto" -#: utils/adt/acl.c:576 +#: utils/adt/acl.c:582 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "los array de ACL debe ser unidimensional" -#: utils/adt/acl.c:580 +#: utils/adt/acl.c:586 #, c-format msgid "ACL arrays must not contain null values" msgstr "los arrays de ACL no pueden contener valores nulos" -#: utils/adt/acl.c:609 +#: utils/adt/acl.c:615 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "basura extra al final de la especificación de la ACL" -#: utils/adt/acl.c:1251 +#: utils/adt/acl.c:1263 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "la opción de grant no puede ser otorgada de vuelta a quien la otorgó" -#: utils/adt/acl.c:1567 +#: utils/adt/acl.c:1579 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert ya no está soportado" -#: utils/adt/acl.c:1577 +#: utils/adt/acl.c:1589 #, c-format msgid "aclremove is no longer supported" msgstr "aclremove ya no está soportado" -#: utils/adt/acl.c:1697 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "tipo de privilegio no reconocido: «%s»" -#: utils/adt/acl.c:3484 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3550 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "no existe la función «%s»" -#: utils/adt/acl.c:5031 +#: utils/adt/acl.c:5196 #, c-format msgid "must be able to SET ROLE \"%s\"" -msgstr "" +msgstr "debe ser capaz de hacer SET ROLE «%s»" #: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 -#: utils/adt/array_userfuncs.c:878 utils/adt/json.c:694 utils/adt/json.c:831 -#: utils/adt/json.c:869 utils/adt/jsonb.c:1139 utils/adt/jsonb.c:1211 -#: utils/adt/jsonb.c:1629 utils/adt/jsonb.c:1817 utils/adt/jsonb.c:1827 +#: utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 +#: utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 +#: utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "no se pudo determinar el tipo de dato de entrada" @@ -23238,17 +23888,17 @@ msgid "input data type is not an array" msgstr "el tipo de entrada no es un array" #: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 -#: utils/adt/float.c:1228 utils/adt/float.c:1302 utils/adt/float.c:4117 -#: utils/adt/float.c:4155 utils/adt/int.c:778 utils/adt/int.c:800 +#: utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 +#: utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 #: utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 #: utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 #: utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 #: utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 #: utils/adt/int.c:1263 utils/adt/int.c:1331 utils/adt/int.c:1337 -#: utils/adt/int8.c:1257 utils/adt/numeric.c:1901 utils/adt/numeric.c:4388 -#: utils/adt/rangetypes.c:1481 utils/adt/rangetypes.c:1494 -#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1132 -#: utils/adt/varlena.c:3134 +#: utils/adt/int8.c:1256 utils/adt/numeric.c:1917 utils/adt/numeric.c:4454 +#: utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 +#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 +#: utils/adt/varlena.c:3137 #, c-format msgid "integer out of range" msgstr "entero fuera de rango" @@ -23285,268 +23935,278 @@ msgstr "Los arrays con elementos de diferentes dimensiones son incompatibles par msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "Los arrays con diferentes dimensiones son incompatibles para la concatenación." -#: utils/adt/array_userfuncs.c:987 utils/adt/array_userfuncs.c:995 -#: utils/adt/arrayfuncs.c:5590 utils/adt/arrayfuncs.c:5596 +#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 +#: utils/adt/arrayfuncs.c:5616 utils/adt/arrayfuncs.c:5622 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "no se pueden acumular arrays de distinta dimensionalidad" -#: utils/adt/array_userfuncs.c:1286 utils/adt/array_userfuncs.c:1440 +#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "no está soportada la búsqueda de elementos en arrays multidimensionales" -#: utils/adt/array_userfuncs.c:1315 +#: utils/adt/array_userfuncs.c:1301 #, c-format msgid "initial position must not be null" msgstr "la posición inicial no debe ser null" -#: utils/adt/array_userfuncs.c:1688 -#, fuzzy, c-format -#| msgid "sample percentage must be between 0 and 100" +#: utils/adt/array_userfuncs.c:1674 +#, c-format msgid "sample size must be between 0 and %d" -msgstr "el porcentaje de muestreo debe estar entre 0 y 100" - -#: utils/adt/arrayfuncs.c:273 utils/adt/arrayfuncs.c:287 -#: utils/adt/arrayfuncs.c:298 utils/adt/arrayfuncs.c:320 -#: utils/adt/arrayfuncs.c:337 utils/adt/arrayfuncs.c:351 -#: utils/adt/arrayfuncs.c:359 utils/adt/arrayfuncs.c:366 -#: utils/adt/arrayfuncs.c:506 utils/adt/arrayfuncs.c:521 -#: utils/adt/arrayfuncs.c:532 utils/adt/arrayfuncs.c:547 -#: utils/adt/arrayfuncs.c:568 utils/adt/arrayfuncs.c:598 -#: utils/adt/arrayfuncs.c:605 utils/adt/arrayfuncs.c:613 -#: utils/adt/arrayfuncs.c:647 utils/adt/arrayfuncs.c:670 -#: utils/adt/arrayfuncs.c:690 utils/adt/arrayfuncs.c:807 -#: utils/adt/arrayfuncs.c:816 utils/adt/arrayfuncs.c:846 -#: utils/adt/arrayfuncs.c:861 utils/adt/arrayfuncs.c:914 +msgstr "el tamaño de la muestra debe estar entre 0 y %d" + +#: utils/adt/arrayfuncs.c:264 utils/adt/arrayfuncs.c:273 +#: utils/adt/arrayfuncs.c:284 utils/adt/arrayfuncs.c:307 +#: utils/adt/arrayfuncs.c:440 utils/adt/arrayfuncs.c:454 +#: utils/adt/arrayfuncs.c:466 utils/adt/arrayfuncs.c:636 +#: utils/adt/arrayfuncs.c:668 utils/adt/arrayfuncs.c:703 +#: utils/adt/arrayfuncs.c:718 utils/adt/arrayfuncs.c:777 +#: utils/adt/arrayfuncs.c:782 utils/adt/arrayfuncs.c:870 +#: utils/adt/arrayfuncs.c:897 utils/adt/arrayfuncs.c:904 +#: utils/adt/arrayfuncs.c:941 #, c-format msgid "malformed array literal: \"%s\"" msgstr "literal de array mal formado: «%s»" -#: utils/adt/arrayfuncs.c:274 -#, c-format -msgid "\"[\" must introduce explicitly-specified array dimensions." -msgstr "Un «[» debe introducir dimensiones de array especificadas explícitamente." - -#: utils/adt/arrayfuncs.c:288 +#: utils/adt/arrayfuncs.c:265 #, c-format -msgid "Missing array dimension value." -msgstr "Falta un valor de dimensión de array." +msgid "Array value must start with \"{\" or dimension information." +msgstr "El valor de array debe comenzar con «{» o información de dimensión." -#: utils/adt/arrayfuncs.c:299 utils/adt/arrayfuncs.c:338 +#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:467 #, c-format msgid "Missing \"%s\" after array dimensions." msgstr "Falta «%s» luego de las dimensiones de array." -#: utils/adt/arrayfuncs.c:308 utils/adt/arrayfuncs.c:2933 -#: utils/adt/arrayfuncs.c:2965 utils/adt/arrayfuncs.c:2980 +#: utils/adt/arrayfuncs.c:285 #, c-format -msgid "upper bound cannot be less than lower bound" -msgstr "el límite superior no puede ser menor que el límite inferior" +msgid "Array contents must start with \"{\"." +msgstr "El contenido del array debe empezar con «{»." + +#: utils/adt/arrayfuncs.c:308 utils/adt/multirangetypes.c:292 +#, c-format +msgid "Junk after closing right brace." +msgstr "Basura después de la llave derecha de cierre." + +#: utils/adt/arrayfuncs.c:431 utils/adt/arrayfuncs.c:643 +#, c-format +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "el número de dimensiones del array excede el máximo permitido (%d)" + +#: utils/adt/arrayfuncs.c:441 +#, c-format +msgid "\"[\" must introduce explicitly-specified array dimensions." +msgstr "Un «[» debe introducir dimensiones de array especificadas explícitamente." -#: utils/adt/arrayfuncs.c:321 +#: utils/adt/arrayfuncs.c:455 #, c-format -msgid "Array value must start with \"{\" or dimension information." -msgstr "El valor de array debe comenzar con «{» o información de dimensión." +msgid "Missing array dimension value." +msgstr "Falta un valor de dimensión de array." -#: utils/adt/arrayfuncs.c:352 +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 +#: utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 #, c-format -msgid "Array contents must start with \"{\"." -msgstr "El contenido del array debe empezar con «{»." +msgid "upper bound cannot be less than lower bound" +msgstr "el límite superior no puede ser menor que el límite inferior" -#: utils/adt/arrayfuncs.c:360 utils/adt/arrayfuncs.c:367 +#: utils/adt/arrayfuncs.c:487 #, c-format -msgid "Specified array dimensions do not match array contents." -msgstr "Las dimensiones del array especificadas no coinciden con el contenido del array." +msgid "array upper bound is too large: %d" +msgstr "el límite superior del array es demasiado grande: %d" -#: utils/adt/arrayfuncs.c:507 utils/adt/arrayfuncs.c:533 -#: utils/adt/multirangetypes.c:166 utils/adt/rangetypes.c:2405 -#: utils/adt/rangetypes.c:2413 utils/adt/rowtypes.c:219 -#: utils/adt/rowtypes.c:230 +#: utils/adt/arrayfuncs.c:538 #, c-format -msgid "Unexpected end of input." -msgstr "Fin inesperado de la entrada." +msgid "array bound is out of integer range" +msgstr "límite de array está fuera del rango entero" -#: utils/adt/arrayfuncs.c:522 utils/adt/arrayfuncs.c:569 -#: utils/adt/arrayfuncs.c:599 utils/adt/arrayfuncs.c:648 +#: utils/adt/arrayfuncs.c:637 utils/adt/arrayfuncs.c:669 +#: utils/adt/arrayfuncs.c:704 utils/adt/arrayfuncs.c:898 #, c-format msgid "Unexpected \"%c\" character." msgstr "Carácter «%c» inesperado." -#: utils/adt/arrayfuncs.c:548 utils/adt/arrayfuncs.c:671 +#: utils/adt/arrayfuncs.c:719 #, c-format msgid "Unexpected array element." msgstr "Elemento de array inesperado." -#: utils/adt/arrayfuncs.c:606 +#: utils/adt/arrayfuncs.c:778 #, c-format -msgid "Unmatched \"%c\" character." -msgstr "Carácter «%c» desemparejado." +msgid "Specified array dimensions do not match array contents." +msgstr "Las dimensiones del array especificadas no coinciden con el contenido del array." -#: utils/adt/arrayfuncs.c:614 utils/adt/jsonfuncs.c:2553 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2598 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "Los arrays multidimensionales deben tener sub-arrays con dimensiones coincidentes." -#: utils/adt/arrayfuncs.c:691 utils/adt/multirangetypes.c:293 +#: utils/adt/arrayfuncs.c:871 utils/adt/arrayfuncs.c:905 #, c-format -msgid "Junk after closing right brace." -msgstr "Basura después de la llave derecha de cierre." +msgid "Incorrectly quoted array element." +msgstr "Elemento de array entrecomillado incorrectamente." + +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 +#: utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 +#: utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#, c-format +msgid "Unexpected end of input." +msgstr "Fin inesperado de la entrada." -#: utils/adt/arrayfuncs.c:1325 utils/adt/arrayfuncs.c:3479 -#: utils/adt/arrayfuncs.c:6080 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3499 +#: utils/adt/arrayfuncs.c:6106 #, c-format msgid "invalid number of dimensions: %d" msgstr "número incorrecto de dimensiones: %d" -#: utils/adt/arrayfuncs.c:1336 +#: utils/adt/arrayfuncs.c:1312 #, c-format msgid "invalid array flags" msgstr "opciones de array no válidas" -#: utils/adt/arrayfuncs.c:1358 +#: utils/adt/arrayfuncs.c:1334 #, c-format msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "los datos binarios tienen el tipo de elemento de array %u (%s) en lugar del esperado %u (%s)" -#: utils/adt/arrayfuncs.c:1402 utils/adt/multirangetypes.c:451 -#: utils/adt/rangetypes.c:344 utils/cache/lsyscache.c:2916 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 +#: utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 #, c-format msgid "no binary input function available for type %s" msgstr "no hay una función binaria de entrada para el tipo %s" -#: utils/adt/arrayfuncs.c:1542 +#: utils/adt/arrayfuncs.c:1509 #, c-format msgid "improper binary format in array element %d" msgstr "el formato binario no es válido en elemento %d de array" -#: utils/adt/arrayfuncs.c:1623 utils/adt/multirangetypes.c:456 -#: utils/adt/rangetypes.c:349 utils/cache/lsyscache.c:2949 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 +#: utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 #, c-format msgid "no binary output function available for type %s" msgstr "no hay una función binaria de salida para el tipo %s" -#: utils/adt/arrayfuncs.c:2102 +#: utils/adt/arrayfuncs.c:2067 #, c-format msgid "slices of fixed-length arrays not implemented" msgstr "no está implementada la obtención de segmentos de arrays de largo fijo" -#: utils/adt/arrayfuncs.c:2280 utils/adt/arrayfuncs.c:2302 -#: utils/adt/arrayfuncs.c:2351 utils/adt/arrayfuncs.c:2589 -#: utils/adt/arrayfuncs.c:2911 utils/adt/arrayfuncs.c:6066 -#: utils/adt/arrayfuncs.c:6092 utils/adt/arrayfuncs.c:6103 -#: utils/adt/json.c:1497 utils/adt/json.c:1569 utils/adt/jsonb.c:1416 -#: utils/adt/jsonb.c:1500 utils/adt/jsonfuncs.c:4434 utils/adt/jsonfuncs.c:4587 -#: utils/adt/jsonfuncs.c:4698 utils/adt/jsonfuncs.c:4746 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 +#: utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 +#: utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6092 +#: utils/adt/arrayfuncs.c:6118 utils/adt/arrayfuncs.c:6129 +#: utils/adt/json.c:1433 utils/adt/json.c:1505 utils/adt/jsonb.c:1317 +#: utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4710 utils/adt/jsonfuncs.c:4863 +#: utils/adt/jsonfuncs.c:4974 utils/adt/jsonfuncs.c:5022 #, c-format msgid "wrong number of array subscripts" msgstr "número incorrecto de subíndices del array" -#: utils/adt/arrayfuncs.c:2285 utils/adt/arrayfuncs.c:2393 -#: utils/adt/arrayfuncs.c:2656 utils/adt/arrayfuncs.c:2970 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 +#: utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "subíndice de array fuera de rango" -#: utils/adt/arrayfuncs.c:2290 +#: utils/adt/arrayfuncs.c:2255 #, c-format msgid "cannot assign null value to an element of a fixed-length array" msgstr "no se puede asignar un valor nulo a un elemento de un array de longitud fija" -#: utils/adt/arrayfuncs.c:2858 +#: utils/adt/arrayfuncs.c:2855 #, c-format msgid "updates on slices of fixed-length arrays not implemented" msgstr "no están implementadas las actualizaciones en segmentos de arrays de largo fija" -#: utils/adt/arrayfuncs.c:2889 +#: utils/adt/arrayfuncs.c:2886 #, c-format msgid "array slice subscript must provide both boundaries" msgstr "los subíndices del segmento de array deben especificar ambos bordes" -#: utils/adt/arrayfuncs.c:2890 +#: utils/adt/arrayfuncs.c:2887 #, c-format msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified." msgstr "Cuando se asigna a un segmento de un array vacío, los bordes del segmento deben ser especificados completamente." -#: utils/adt/arrayfuncs.c:2901 utils/adt/arrayfuncs.c:2997 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "el array de origen es demasiado pequeño" -#: utils/adt/arrayfuncs.c:3637 +#: utils/adt/arrayfuncs.c:3657 #, c-format msgid "null array element not allowed in this context" msgstr "los arrays con elementos null no son permitidos en este contexto" -#: utils/adt/arrayfuncs.c:3808 utils/adt/arrayfuncs.c:3979 -#: utils/adt/arrayfuncs.c:4370 +#: utils/adt/arrayfuncs.c:3828 utils/adt/arrayfuncs.c:3999 +#: utils/adt/arrayfuncs.c:4390 #, c-format msgid "cannot compare arrays of different element types" msgstr "no se pueden comparar arrays con elementos de distintos tipos" -#: utils/adt/arrayfuncs.c:4157 utils/adt/multirangetypes.c:2806 -#: utils/adt/multirangetypes.c:2878 utils/adt/rangetypes.c:1354 -#: utils/adt/rangetypes.c:1418 utils/adt/rowtypes.c:1885 +#: utils/adt/arrayfuncs.c:4177 utils/adt/multirangetypes.c:2805 +#: utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 +#: utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 #, c-format msgid "could not identify a hash function for type %s" msgstr "no se pudo identificar una función de hash para el tipo %s" -#: utils/adt/arrayfuncs.c:4285 utils/adt/rowtypes.c:2006 +#: utils/adt/arrayfuncs.c:4305 utils/adt/rowtypes.c:1996 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "no se pudo identificar una función de hash extendida para el tipo %s" -#: utils/adt/arrayfuncs.c:5480 +#: utils/adt/arrayfuncs.c:5506 #, c-format msgid "data type %s is not an array type" msgstr "el tipo %s no es un array" -#: utils/adt/arrayfuncs.c:5535 +#: utils/adt/arrayfuncs.c:5561 #, c-format msgid "cannot accumulate null arrays" msgstr "no se pueden acumular arrays nulos" -#: utils/adt/arrayfuncs.c:5563 +#: utils/adt/arrayfuncs.c:5589 #, c-format msgid "cannot accumulate empty arrays" msgstr "no se pueden acumular arrays vacíos" -#: utils/adt/arrayfuncs.c:5964 utils/adt/arrayfuncs.c:6004 +#: utils/adt/arrayfuncs.c:5990 utils/adt/arrayfuncs.c:6030 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "el array de dimensiones o el array de límites inferiores debe ser no nulo" -#: utils/adt/arrayfuncs.c:6067 utils/adt/arrayfuncs.c:6093 +#: utils/adt/arrayfuncs.c:6093 utils/adt/arrayfuncs.c:6119 #, c-format msgid "Dimension array must be one dimensional." msgstr "El array de dimensiones debe ser unidimensional." -#: utils/adt/arrayfuncs.c:6072 utils/adt/arrayfuncs.c:6098 +#: utils/adt/arrayfuncs.c:6098 utils/adt/arrayfuncs.c:6124 #, c-format msgid "dimension values cannot be null" msgstr "los valores de dimensión no pueden ser null" -#: utils/adt/arrayfuncs.c:6104 +#: utils/adt/arrayfuncs.c:6130 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "El array de límites inferiores tiene tamaño diferente que el array de dimensiones." -#: utils/adt/arrayfuncs.c:6382 +#: utils/adt/arrayfuncs.c:6411 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "la eliminación de elementos desde arrays multidimensionales no está soportada" -#: utils/adt/arrayfuncs.c:6659 +#: utils/adt/arrayfuncs.c:6688 #, c-format msgid "thresholds must be one-dimensional array" msgstr "los umbrales deben ser un array unidimensional" -#: utils/adt/arrayfuncs.c:6664 +#: utils/adt/arrayfuncs.c:6693 #, c-format msgid "thresholds array must not contain NULLs" msgstr "el array de umbrales no debe contener nulos" -#: utils/adt/arrayfuncs.c:6897 +#: utils/adt/arrayfuncs.c:6926 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "el número de elementos a recortar debe estar entre 0 y %d" @@ -23561,22 +24221,22 @@ msgstr "los subíndices de arrays deben tener tipo entero" msgid "array subscript in assignment must not be null" msgstr "subíndice de array en asignación no puede ser nulo" -#: utils/adt/arrayutils.c:161 +#: utils/adt/arrayutils.c:140 #, c-format msgid "array lower bound is too large: %d" msgstr "el límite inferior del array es demasiado grande: %d" -#: utils/adt/arrayutils.c:263 +#: utils/adt/arrayutils.c:242 #, c-format msgid "typmod array must be type cstring[]" msgstr "el array de typmod debe ser de tipo cstring[]" -#: utils/adt/arrayutils.c:268 +#: utils/adt/arrayutils.c:247 #, c-format msgid "typmod array must be one-dimensional" msgstr "array de typmod debe ser unidimensional" -#: utils/adt/arrayutils.c:273 +#: utils/adt/arrayutils.c:252 #, c-format msgid "typmod array must not contain nulls" msgstr "los arrays de typmod no deben contener valores nulos" @@ -23587,214 +24247,242 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "la conversión de codificación de %s a ASCII no está soportada" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:153 utils/adt/cash.c:277 utils/adt/datetime.c:4017 -#: utils/adt/float.c:206 utils/adt/float.c:293 utils/adt/float.c:307 -#: utils/adt/float.c:412 utils/adt/float.c:495 utils/adt/float.c:509 +#: utils/adt/bool.c:149 utils/adt/cash.c:354 utils/adt/datetime.c:4142 +#: utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 +#: utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 #: utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 #: utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 #: utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 #: utils/adt/geo_ops.c:4672 utils/adt/int.c:174 utils/adt/int.c:186 -#: utils/adt/jsonpath.c:183 utils/adt/mac.c:94 utils/adt/mac8.c:225 -#: utils/adt/network.c:99 utils/adt/numeric.c:795 utils/adt/numeric.c:7136 -#: utils/adt/numeric.c:7339 utils/adt/numeric.c:8286 utils/adt/numutils.c:273 -#: utils/adt/numutils.c:451 utils/adt/numutils.c:629 utils/adt/numutils.c:668 -#: utils/adt/numutils.c:690 utils/adt/numutils.c:754 utils/adt/numutils.c:776 -#: utils/adt/pg_lsn.c:74 utils/adt/tid.c:72 utils/adt/tid.c:80 -#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:494 -#: utils/adt/uuid.c:135 utils/adt/xid8funcs.c:354 +#: utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 +#: utils/adt/network.c:99 utils/adt/numeric.c:803 utils/adt/numeric.c:7221 +#: utils/adt/numeric.c:7424 utils/adt/numeric.c:8371 utils/adt/numutils.c:356 +#: utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 +#: utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 +#: utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 +#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:510 +#: utils/adt/uuid.c:140 utils/adt/xid8funcs.c:323 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "la sintaxis de entrada no es válida para tipo %s: «%s»" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 -#: utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:267 -#: utils/adt/numutils.c:445 utils/adt/numutils.c:623 utils/adt/numutils.c:674 -#: utils/adt/numutils.c:713 utils/adt/numutils.c:760 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 +#: utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "el valor «%s» está fuera de rango para el tipo %s" +msgid "money out of range" +msgstr "money fuera de rango" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 -#: utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 -#: utils/adt/float.c:105 utils/adt/int.c:843 utils/adt/int.c:959 -#: utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 -#: utils/adt/int.c:1167 utils/adt/int8.c:515 utils/adt/int8.c:573 -#: utils/adt/int8.c:943 utils/adt/int8.c:1023 utils/adt/int8.c:1085 -#: utils/adt/int8.c:1165 utils/adt/numeric.c:3175 utils/adt/numeric.c:3198 -#: utils/adt/numeric.c:3283 utils/adt/numeric.c:3301 utils/adt/numeric.c:3397 -#: utils/adt/numeric.c:8835 utils/adt/numeric.c:9148 utils/adt/numeric.c:9496 -#: utils/adt/numeric.c:9612 utils/adt/numeric.c:11122 -#: utils/adt/timestamp.c:3406 +#: utils/adt/cash.c:161 utils/adt/cash.c:723 utils/adt/float.c:99 +#: utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 +#: utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 +#: utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 +#: utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 +#: utils/adt/numeric.c:3191 utils/adt/numeric.c:3214 utils/adt/numeric.c:3299 +#: utils/adt/numeric.c:3317 utils/adt/numeric.c:3413 utils/adt/numeric.c:8920 +#: utils/adt/numeric.c:9233 utils/adt/numeric.c:9581 utils/adt/numeric.c:9697 +#: utils/adt/numeric.c:11208 utils/adt/timestamp.c:3713 #, c-format msgid "division by zero" msgstr "división por cero" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 +#: utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 +#: utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 +#: utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "el valor «%s» está fuera de rango para el tipo %s" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" msgstr "«char» fuera de rango" #: utils/adt/cryptohashfuncs.c:48 utils/adt/cryptohashfuncs.c:70 -#, fuzzy, c-format -#| msgid "could not decompress: %s" +#, c-format msgid "could not compute %s hash: %s" -msgstr "no se pudo descomprimir: %s" +msgstr "no se pudo calcular el hash %s: %s" -#: utils/adt/date.c:63 utils/adt/timestamp.c:100 utils/adt/varbit.c:105 -#: utils/adt/varchar.c:49 +#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 +#: utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "el modificador de tipo no es válido" -#: utils/adt/date.c:75 +#: utils/adt/date.c:76 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "la precisión de TIME(%d)%s no debe ser negativa" -#: utils/adt/date.c:81 +#: utils/adt/date.c:82 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "la precisión de TIME(%d)%s fue reducida al máximo permitido, %d" -#: utils/adt/date.c:166 utils/adt/date.c:174 utils/adt/formatting.c:4241 -#: utils/adt/formatting.c:4250 utils/adt/formatting.c:4363 -#: utils/adt/formatting.c:4373 +#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 +#: utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 +#: utils/adt/formatting.c:4548 #, c-format msgid "date out of range: \"%s\"" msgstr "fecha fuera de rango: «%s»" -#: utils/adt/date.c:221 utils/adt/date.c:519 utils/adt/date.c:543 -#: utils/adt/rangetypes.c:1577 utils/adt/rangetypes.c:1592 utils/adt/xml.c:2460 +#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 +#: utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "fecha fuera de rango" -#: utils/adt/date.c:267 utils/adt/timestamp.c:582 +#: utils/adt/date.c:268 utils/adt/timestamp.c:598 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "valor en campo de fecha fuera de rango: %d-%02d-%02d" -#: utils/adt/date.c:274 utils/adt/date.c:283 utils/adt/timestamp.c:588 +#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "fecha fuera de rango: %d-%02d-%02d" -#: utils/adt/date.c:494 +#: utils/adt/date.c:495 #, c-format msgid "cannot subtract infinite dates" msgstr "no se pueden restar fechas infinitas" -#: utils/adt/date.c:592 utils/adt/date.c:655 utils/adt/date.c:691 -#: utils/adt/date.c:2885 utils/adt/date.c:2895 +#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 +#: utils/adt/date.c:2906 utils/adt/date.c:2916 #, c-format msgid "date out of range for timestamp" msgstr "fecha fuera de rango para timestamp" -#: utils/adt/date.c:1121 utils/adt/date.c:1204 utils/adt/date.c:1220 -#: utils/adt/date.c:2206 utils/adt/date.c:2990 utils/adt/timestamp.c:4097 -#: utils/adt/timestamp.c:4290 utils/adt/timestamp.c:4432 -#: utils/adt/timestamp.c:4685 utils/adt/timestamp.c:4886 -#: utils/adt/timestamp.c:4933 utils/adt/timestamp.c:5157 -#: utils/adt/timestamp.c:5204 utils/adt/timestamp.c:5334 -#, fuzzy, c-format -#| msgid "\"RN\" not supported for input" +#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 +#: utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 +#: utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 +#: utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 +#: utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 +#: utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 +#: utils/adt/timestamp.c:6070 +#, c-format msgid "unit \"%s\" not supported for type %s" -msgstr "«RN» no está soportado en la entrada" +msgstr "unidades «%s» no soportada para el tipo %s" -#: utils/adt/date.c:1229 utils/adt/date.c:2222 utils/adt/date.c:3010 -#: utils/adt/timestamp.c:4111 utils/adt/timestamp.c:4307 -#: utils/adt/timestamp.c:4446 utils/adt/timestamp.c:4645 -#: utils/adt/timestamp.c:4942 utils/adt/timestamp.c:5213 -#: utils/adt/timestamp.c:5395 -#, fuzzy, c-format -#| msgid "%s: unrecognized start type \"%s\"\n" +#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 +#: utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 +#: utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 +#: utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 +#: utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 +#, c-format msgid "unit \"%s\" not recognized for type %s" -msgstr "%s: tipo de inicio «%s» no reconocido\n" - -#: utils/adt/date.c:1313 utils/adt/date.c:1359 utils/adt/date.c:1918 -#: utils/adt/date.c:1949 utils/adt/date.c:1978 utils/adt/date.c:2848 -#: utils/adt/date.c:3080 utils/adt/datetime.c:424 utils/adt/datetime.c:1809 -#: utils/adt/formatting.c:4081 utils/adt/formatting.c:4117 -#: utils/adt/formatting.c:4210 utils/adt/formatting.c:4339 utils/adt/json.c:467 -#: utils/adt/json.c:506 utils/adt/timestamp.c:232 utils/adt/timestamp.c:264 -#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:709 -#: utils/adt/timestamp.c:787 utils/adt/timestamp.c:820 -#: utils/adt/timestamp.c:2933 utils/adt/timestamp.c:2954 -#: utils/adt/timestamp.c:2967 utils/adt/timestamp.c:2976 -#: utils/adt/timestamp.c:2984 utils/adt/timestamp.c:3045 -#: utils/adt/timestamp.c:3068 utils/adt/timestamp.c:3081 -#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3100 -#: utils/adt/timestamp.c:3801 utils/adt/timestamp.c:3925 -#: utils/adt/timestamp.c:4015 utils/adt/timestamp.c:4105 -#: utils/adt/timestamp.c:4198 utils/adt/timestamp.c:4301 -#: utils/adt/timestamp.c:4750 utils/adt/timestamp.c:5024 -#: utils/adt/timestamp.c:5463 utils/adt/timestamp.c:5473 -#: utils/adt/timestamp.c:5478 utils/adt/timestamp.c:5484 -#: utils/adt/timestamp.c:5517 utils/adt/timestamp.c:5604 -#: utils/adt/timestamp.c:5645 utils/adt/timestamp.c:5649 -#: utils/adt/timestamp.c:5703 utils/adt/timestamp.c:5707 -#: utils/adt/timestamp.c:5713 utils/adt/timestamp.c:5747 utils/adt/xml.c:2482 -#: utils/adt/xml.c:2489 utils/adt/xml.c:2509 utils/adt/xml.c:2516 +msgstr "unidad «%s» no reconocida para el tipo %s" + +#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 +#: utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 +#: utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 +#: utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 +#: utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 +#: utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 +#: utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 +#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 +#: utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 +#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 +#: utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 +#: utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 +#: utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 +#: utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 +#: utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 +#: utils/adt/timestamp.c:3266 utils/adt/timestamp.c:3279 +#: utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 +#: utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 +#: utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 +#: utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 +#: utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 +#: utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 +#: utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 +#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 +#: utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 +#: utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 +#: utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 +#: utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2574 +#: utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "timestamp fuera de rango" -#: utils/adt/date.c:1535 utils/adt/date.c:2343 utils/adt/formatting.c:4431 +#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 #, c-format msgid "time out of range" msgstr "hora fuera de rango" -#: utils/adt/date.c:1587 utils/adt/timestamp.c:597 +#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "valor en campo de hora fuera de rango: %d:%02d:%02g" -#: utils/adt/date.c:2107 utils/adt/date.c:2647 utils/adt/float.c:1042 -#: utils/adt/float.c:1118 utils/adt/int.c:635 utils/adt/int.c:682 -#: utils/adt/int.c:717 utils/adt/int8.c:414 utils/adt/numeric.c:2579 -#: utils/adt/timestamp.c:3455 utils/adt/timestamp.c:3482 -#: utils/adt/timestamp.c:3513 +#: utils/adt/date.c:2020 +#, c-format +msgid "cannot convert infinite interval to time" +msgstr "no se puede convertir intervalo infinito a time" + +#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#, c-format +msgid "cannot add infinite interval to time" +msgstr "no se puede sumar intervalo infinito a time" + +#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#, c-format +msgid "cannot subtract infinite interval from time" +msgstr "no se pueden restar intervalo infinito de time" + +#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 +#: utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 +#: utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2595 +#: utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 +#: utils/adt/timestamp.c:3888 #, c-format msgid "invalid preceding or following size in window function" msgstr "tamaño «preceding» o «following» no válido en ventana deslizante" -#: utils/adt/date.c:2351 +#: utils/adt/date.c:2360 #, c-format msgid "time zone displacement out of range" msgstr "desplazamiento de huso horario fuera de rango" -#: utils/adt/date.c:3110 utils/adt/timestamp.c:5506 utils/adt/timestamp.c:5736 +#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#, c-format +msgid "interval time zone \"%s\" must be finite" +msgstr "el intervalo de huso horario «%s» debe ser finito" + +#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "el intervalo de huso horario «%s» no debe especificar meses o días" -#: utils/adt/datetime.c:3223 utils/adt/datetime.c:4002 -#: utils/adt/datetime.c:4008 utils/adt/timestamp.c:512 +#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 +#: utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 #, c-format msgid "time zone \"%s\" not recognized" msgstr "el huso horario «%s» no es reconocido" -#: utils/adt/datetime.c:3976 utils/adt/datetime.c:3983 +#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "valor de hora/fecha fuera de rango: «%s»" -#: utils/adt/datetime.c:3985 +#: utils/adt/datetime.c:4110 #, c-format msgid "Perhaps you need a different \"datestyle\" setting." msgstr "Quizás necesite una configuración diferente de «datestyle»." -#: utils/adt/datetime.c:3990 +#: utils/adt/datetime.c:4115 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "valor de interval fuera de rango: «%s»" -#: utils/adt/datetime.c:3996 +#: utils/adt/datetime.c:4121 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "desplazamiento de huso horario fuera de rango: «%s»" -#: utils/adt/datetime.c:4010 +#: utils/adt/datetime.c:4135 #, c-format msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"." msgstr "Este nombre de huso horario aparece en el archivo de configuración para abreviaciones de husos horarios «%s»." @@ -23804,23 +24492,22 @@ msgstr "Este nombre de huso horario aparece en el archivo de configuración para msgid "invalid Datum pointer" msgstr "puntero a Datum no válido" -#: utils/adt/dbsize.c:761 utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:764 utils/adt/dbsize.c:840 #, c-format msgid "invalid size: \"%s\"" msgstr "tamaño no válido: «%s»" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:841 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "Nombre de unidad de tamaño no válido: «%s»." -#: utils/adt/dbsize.c:839 -#, fuzzy, c-format -#| msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." +#: utils/adt/dbsize.c:842 +#, c-format msgid "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." -msgstr "Unidades válidas para este parámetro son «B», «kB», «MB», «GB» y «TB»." +msgstr "Unidades aceptables son «bytes«, «B», «kB», «MB», «GB», «TB» y «PB»." -#: utils/adt/domains.c:92 +#: utils/adt/domains.c:95 #, c-format msgid "type %s is not a domain" msgstr "tipo «%s» no es un dominio" @@ -23870,10 +24557,10 @@ msgstr "secuencia de término base64 no válida" msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "A los datos de entrada les falta relleno, o están truncados, o están corruptos de alguna otra forma." -#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:648 -#: utils/adt/varlena.c:331 utils/adt/varlena.c:372 jsonpath_gram.y:528 -#: jsonpath_scan.l:629 jsonpath_scan.l:640 jsonpath_scan.l:650 -#: jsonpath_scan.l:701 +#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:659 +#: utils/adt/varlena.c:333 utils/adt/varlena.c:374 jsonpath_gram.y:266 +#: jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 +#: jsonpath_scan.l:661 jsonpath_scan.l:712 #, c-format msgid "invalid input syntax for type %s" msgstr "sintaxis de entrada no válida para tipo %s" @@ -23910,353 +24597,348 @@ msgstr "no se pudo determinar el tipo enum efectivo" msgid "enum %s contains no values" msgstr "el enum %s no contiene valores" -#: utils/adt/float.c:89 +#: utils/adt/float.c:83 #, c-format msgid "value out of range: overflow" msgstr "valor fuera de rango: desbordamiento" -#: utils/adt/float.c:97 +#: utils/adt/float.c:91 #, c-format msgid "value out of range: underflow" msgstr "valor fuera de rango: desbordamiento por abajo" -#: utils/adt/float.c:286 +#: utils/adt/float.c:280 #, c-format msgid "\"%s\" is out of range for type real" msgstr "«%s» está fuera de rango para el tipo real" -#: utils/adt/float.c:488 +#: utils/adt/float.c:482 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "«%s» está fuera de rango para el tipo double precision" -#: utils/adt/float.c:1253 utils/adt/float.c:1327 utils/adt/int.c:355 +#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 #: utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 #: utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 -#: utils/adt/int8.c:1278 utils/adt/numeric.c:4500 utils/adt/numeric.c:4505 +#: utils/adt/int8.c:1277 utils/adt/numeric.c:4593 utils/adt/numeric.c:4598 #, c-format msgid "smallint out of range" msgstr "smallint fuera de rango" -#: utils/adt/float.c:1453 utils/adt/numeric.c:3693 utils/adt/numeric.c:10027 +#: utils/adt/float.c:1447 utils/adt/numeric.c:3709 utils/adt/numeric.c:10112 #, c-format msgid "cannot take square root of a negative number" msgstr "no se puede calcular la raíz cuadrada un de número negativo" -#: utils/adt/float.c:1521 utils/adt/numeric.c:3981 utils/adt/numeric.c:4093 +#: utils/adt/float.c:1515 utils/adt/numeric.c:3997 utils/adt/numeric.c:4109 #, c-format msgid "zero raised to a negative power is undefined" msgstr "cero elevado a una potencia negativa es indefinido" -#: utils/adt/float.c:1525 utils/adt/numeric.c:3985 utils/adt/numeric.c:10918 +#: utils/adt/float.c:1519 utils/adt/numeric.c:4001 utils/adt/numeric.c:11003 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "un número negativo elevado a una potencia no positiva entrega un resultado complejo" -#: utils/adt/float.c:1701 utils/adt/float.c:1734 utils/adt/numeric.c:3893 -#: utils/adt/numeric.c:10698 +#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3909 +#: utils/adt/numeric.c:10783 #, c-format msgid "cannot take logarithm of zero" msgstr "no se puede calcular logaritmo de cero" -#: utils/adt/float.c:1705 utils/adt/float.c:1738 utils/adt/numeric.c:3831 -#: utils/adt/numeric.c:3888 utils/adt/numeric.c:10702 +#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3847 +#: utils/adt/numeric.c:3904 utils/adt/numeric.c:10787 #, c-format msgid "cannot take logarithm of a negative number" msgstr "no se puede calcular logaritmo de un número negativo" -#: utils/adt/float.c:1771 utils/adt/float.c:1802 utils/adt/float.c:1897 -#: utils/adt/float.c:1924 utils/adt/float.c:1952 utils/adt/float.c:1979 -#: utils/adt/float.c:2126 utils/adt/float.c:2163 utils/adt/float.c:2333 -#: utils/adt/float.c:2389 utils/adt/float.c:2454 utils/adt/float.c:2511 -#: utils/adt/float.c:2702 utils/adt/float.c:2726 +#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 +#: utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 +#: utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 +#: utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 +#: utils/adt/float.c:2696 utils/adt/float.c:2720 #, c-format msgid "input is out of range" msgstr "la entrada está fuera de rango" -#: utils/adt/float.c:2867 -#, c-format -msgid "setseed parameter %g is out of allowed range [-1,1]" -msgstr "parámetro setseed %g fuera del rango permitido [-1,1]" - -#: utils/adt/float.c:4095 utils/adt/numeric.c:1841 +#: utils/adt/float.c:4000 utils/adt/numeric.c:1857 #, c-format msgid "count must be greater than zero" msgstr "count debe ser mayor que cero" -#: utils/adt/float.c:4100 utils/adt/numeric.c:1852 +#: utils/adt/float.c:4005 utils/adt/numeric.c:1868 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "el operando, límite inferior y límite superior no pueden ser NaN" -#: utils/adt/float.c:4106 utils/adt/numeric.c:1857 +#: utils/adt/float.c:4011 utils/adt/numeric.c:1873 #, c-format msgid "lower and upper bounds must be finite" msgstr "los límites inferior y superior deben ser finitos" -#: utils/adt/float.c:4172 utils/adt/numeric.c:1871 +#: utils/adt/float.c:4077 utils/adt/numeric.c:1887 #, c-format msgid "lower bound cannot equal upper bound" msgstr "el límite superior no puede ser igual al límite inferior" -#: utils/adt/formatting.c:519 +#: utils/adt/formatting.c:530 #, c-format msgid "invalid format specification for an interval value" msgstr "especificación de formato no válida para un valor de interval" -#: utils/adt/formatting.c:520 +#: utils/adt/formatting.c:531 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "Los Interval no están ... a valores determinados de fechas de calendario." -#: utils/adt/formatting.c:1150 +#: utils/adt/formatting.c:1161 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "«EEEE» debe ser el último patrón usado" -#: utils/adt/formatting.c:1158 +#: utils/adt/formatting.c:1169 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "«9» debe ir antes de «PR»" -#: utils/adt/formatting.c:1174 +#: utils/adt/formatting.c:1185 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "«0» debe ir antes de «PR»" -#: utils/adt/formatting.c:1201 +#: utils/adt/formatting.c:1212 #, c-format msgid "multiple decimal points" msgstr "hay múltiples puntos decimales" -#: utils/adt/formatting.c:1205 utils/adt/formatting.c:1288 +#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "no se puede usar «V» y un punto decimal simultáneamente" -#: utils/adt/formatting.c:1217 +#: utils/adt/formatting.c:1228 #, c-format msgid "cannot use \"S\" twice" msgstr "no se puede usar «S» dos veces" -#: utils/adt/formatting.c:1221 +#: utils/adt/formatting.c:1232 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "no se puede usar «S» y «PL»/«MI»/«SG»/«PR» simultáneamente" -#: utils/adt/formatting.c:1241 +#: utils/adt/formatting.c:1252 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "no se puede usar «S» y «MI» simultáneamente" -#: utils/adt/formatting.c:1251 +#: utils/adt/formatting.c:1262 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "no se puede usar «S» y «PL» simultáneamente" -#: utils/adt/formatting.c:1261 +#: utils/adt/formatting.c:1272 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "no se puede usar «S» y «SG» simultáneamente" -#: utils/adt/formatting.c:1270 +#: utils/adt/formatting.c:1281 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "no se puede usar «PR» y «S»/«PL»/«MI»/«SG» simultáneamente" -#: utils/adt/formatting.c:1296 +#: utils/adt/formatting.c:1307 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "no se puede usar «EEEE» dos veces" -#: utils/adt/formatting.c:1302 +#: utils/adt/formatting.c:1313 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "«EEEE» es incompatible con otros formatos" -#: utils/adt/formatting.c:1303 +#: utils/adt/formatting.c:1314 #, c-format msgid "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "«EEEE» sólo puede ser usado en conjunción con patrones de dígitos y puntos decimales." -#: utils/adt/formatting.c:1387 +#: utils/adt/formatting.c:1398 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "separador de formato «datetime» no válido: «%s»" -#: utils/adt/formatting.c:1514 +#: utils/adt/formatting.c:1525 #, c-format msgid "\"%s\" is not a number" msgstr "«%s» no es un número" -#: utils/adt/formatting.c:1592 +#: utils/adt/formatting.c:1603 #, c-format msgid "case conversion failed: %s" msgstr "falló la conversión de mayúsculas: %s" -#: utils/adt/formatting.c:1646 utils/adt/formatting.c:1768 -#: utils/adt/formatting.c:1891 +#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 +#: utils/adt/formatting.c:1989 #, c-format msgid "could not determine which collation to use for %s function" msgstr "no se pudo determinar qué ordenamiento usar para la función %s" -#: utils/adt/formatting.c:2274 +#: utils/adt/formatting.c:2410 #, c-format msgid "invalid combination of date conventions" msgstr "combinación no válida de convenciones de fecha" -#: utils/adt/formatting.c:2275 +#: utils/adt/formatting.c:2411 #, c-format msgid "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr " No mezclar convenciones de semana Gregorianas e ISO en una plantilla formateada" -#: utils/adt/formatting.c:2297 +#: utils/adt/formatting.c:2433 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "valores en conflicto para le campo \"%s\" en cadena de formato" -#: utils/adt/formatting.c:2299 +#: utils/adt/formatting.c:2435 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "Este valor se contradice con un seteo previo para el mismo tipo de campo" -#: utils/adt/formatting.c:2366 +#: utils/adt/formatting.c:2502 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "cadena de texto fuente muy corta para campo formateado \"%s\" " -#: utils/adt/formatting.c:2368 +#: utils/adt/formatting.c:2504 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "El campo requiere %d caractéres, pero solo quedan %d." -#: utils/adt/formatting.c:2370 utils/adt/formatting.c:2384 +#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 #, c-format msgid "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "Si su cadena de texto no es de ancho modificado, trate de usar el modificador \"FM\" " -#: utils/adt/formatting.c:2380 utils/adt/formatting.c:2393 -#: utils/adt/formatting.c:2614 +#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 +#: utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "el valor «%s» no es válido para «%s»" -#: utils/adt/formatting.c:2382 +#: utils/adt/formatting.c:2518 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "El campo requiere %d caracteres, pero sólo %d pudieron ser analizados." -#: utils/adt/formatting.c:2395 +#: utils/adt/formatting.c:2531 #, c-format msgid "Value must be an integer." msgstr "El valor debe ser un entero." -#: utils/adt/formatting.c:2400 +#: utils/adt/formatting.c:2536 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "el valor para «%s» en la cadena de origen está fuera de rango" -#: utils/adt/formatting.c:2402 +#: utils/adt/formatting.c:2538 #, c-format msgid "Value must be in the range %d to %d." msgstr "El valor debe estar en el rango de %d a %d." -#: utils/adt/formatting.c:2616 +#: utils/adt/formatting.c:2752 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "El valor dado no concuerda con ninguno de los valores permitidos para este campo." -#: utils/adt/formatting.c:2832 utils/adt/formatting.c:2852 -#: utils/adt/formatting.c:2872 utils/adt/formatting.c:2892 -#: utils/adt/formatting.c:2911 utils/adt/formatting.c:2930 -#: utils/adt/formatting.c:2954 utils/adt/formatting.c:2972 -#: utils/adt/formatting.c:2990 utils/adt/formatting.c:3008 -#: utils/adt/formatting.c:3025 utils/adt/formatting.c:3042 +#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 +#: utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 +#: utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 +#: utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 +#: utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 +#: utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 #, c-format msgid "localized string format value too long" msgstr "cadena traducida en cadena de formato es demasiado larga" -#: utils/adt/formatting.c:3322 +#: utils/adt/formatting.c:3458 #, c-format msgid "unmatched format separator \"%c\"" msgstr "separador de formato «%c» desemparejado" -#: utils/adt/formatting.c:3383 +#: utils/adt/formatting.c:3519 #, c-format msgid "unmatched format character \"%s\"" msgstr "carácter de formato «%s» desemparejado" -#: utils/adt/formatting.c:3491 +#: utils/adt/formatting.c:3652 #, c-format -msgid "formatting field \"%s\" is only supported in to_char" -msgstr "el campo de formato «%s» sólo está soportado en to_char" +msgid "Time zone abbreviation is not recognized." +msgstr "La abreviatura de huso horario no es reconocida." -#: utils/adt/formatting.c:3665 +#: utils/adt/formatting.c:3853 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "cadena de entrada no válida para «Y,YYY»" -#: utils/adt/formatting.c:3754 +#: utils/adt/formatting.c:3942 #, c-format msgid "input string is too short for datetime format" msgstr "cadena de entrada muy corta para formato de fecha/hora" -#: utils/adt/formatting.c:3762 +#: utils/adt/formatting.c:3950 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "quedan caracteres al final de la cadena de entrada después del formato fecha/hora" -#: utils/adt/formatting.c:4319 +#: utils/adt/formatting.c:4494 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "falta el huso horario en la cadena de entrada para el tipo timestamptz" -#: utils/adt/formatting.c:4325 +#: utils/adt/formatting.c:4500 #, c-format msgid "timestamptz out of range" msgstr "timestamptz fuera de rango" -#: utils/adt/formatting.c:4353 +#: utils/adt/formatting.c:4528 #, c-format msgid "datetime format is zoned but not timed" msgstr "el formato de fecha/hora tiene huso horario pero no hora" -#: utils/adt/formatting.c:4411 +#: utils/adt/formatting.c:4577 #, c-format msgid "missing time zone in input string for type timetz" msgstr "falta el huso horario en la cadena de entrada del tipo timetz" -#: utils/adt/formatting.c:4417 +#: utils/adt/formatting.c:4583 #, c-format msgid "timetz out of range" msgstr "timetz fuera de rango" -#: utils/adt/formatting.c:4443 +#: utils/adt/formatting.c:4609 #, c-format msgid "datetime format is not dated and not timed" msgstr "el formato de fecha/hora no tiene fecha ni hora" -#: utils/adt/formatting.c:4575 +#: utils/adt/formatting.c:4786 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "la hora «%d» no es válida para el reloj de 12 horas" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4788 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "Use el reloj de 24 horas, o entregue una hora entre 1 y 12." -#: utils/adt/formatting.c:4689 +#: utils/adt/formatting.c:4900 #, c-format msgid "cannot calculate day of year without year information" msgstr "no se puede calcular el día del año sin conocer el año" -#: utils/adt/formatting.c:5621 +#: utils/adt/formatting.c:5852 #, c-format msgid "\"EEEE\" not supported for input" msgstr "«EEEE» no está soportado en la entrada" -#: utils/adt/formatting.c:5633 +#: utils/adt/formatting.c:5864 #, c-format msgid "\"RN\" not supported for input" msgstr "«RN» no está soportado en la entrada" @@ -24267,10 +24949,9 @@ msgid "absolute path not allowed" msgstr "no se permiten rutas absolutas" #: utils/adt/genfile.c:89 -#, fuzzy, c-format -#| msgid "Shows the mode of the data directory." +#, c-format msgid "path must be in or below the data directory" -msgstr "Muestra el modo del directorio de datos." +msgstr "la ruta debe estar en o debajo del directorio de datos" #: utils/adt/genfile.c:114 utils/adt/oracle_compat.c:190 #: utils/adt/oracle_compat.c:288 utils/adt/oracle_compat.c:839 @@ -24289,12 +24970,7 @@ msgstr "no se pudo posicionar (seek) el archivo «%s»: %m" msgid "file length too large" msgstr "el tamaño del archivo es demasiado grande" -#: utils/adt/genfile.c:248 -#, c-format -msgid "must be superuser to read files with adminpack 1.0" -msgstr "Debe ser superusuario leer archivos con adminpack 1.0." - -#: utils/adt/genfile.c:702 +#: utils/adt/genfile.c:656 #, c-format msgid "tablespace with OID %u does not exist" msgstr "no existe el tablespace con OID %u" @@ -24350,569 +25026,649 @@ msgstr "debe pedir al menos 2 puntos" msgid "invalid int2vector data" msgstr "datos de int2vector no válidos" -#: utils/adt/int.c:1529 utils/adt/int8.c:1404 utils/adt/numeric.c:1749 -#: utils/adt/timestamp.c:5797 utils/adt/timestamp.c:5879 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1765 +#: utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 #, c-format msgid "step size cannot equal zero" msgstr "el tamaño de paso no puede ser cero" -#: utils/adt/int8.c:449 utils/adt/int8.c:472 utils/adt/int8.c:486 -#: utils/adt/int8.c:500 utils/adt/int8.c:531 utils/adt/int8.c:555 -#: utils/adt/int8.c:637 utils/adt/int8.c:705 utils/adt/int8.c:711 -#: utils/adt/int8.c:737 utils/adt/int8.c:751 utils/adt/int8.c:775 -#: utils/adt/int8.c:788 utils/adt/int8.c:900 utils/adt/int8.c:914 -#: utils/adt/int8.c:928 utils/adt/int8.c:959 utils/adt/int8.c:981 -#: utils/adt/int8.c:995 utils/adt/int8.c:1009 utils/adt/int8.c:1042 -#: utils/adt/int8.c:1056 utils/adt/int8.c:1070 utils/adt/int8.c:1101 -#: utils/adt/int8.c:1123 utils/adt/int8.c:1137 utils/adt/int8.c:1151 -#: utils/adt/int8.c:1313 utils/adt/int8.c:1348 utils/adt/numeric.c:4459 -#: utils/adt/rangetypes.c:1528 utils/adt/rangetypes.c:1541 +#: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 +#: utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 +#: utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 +#: utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 +#: utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 +#: utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 +#: utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 +#: utils/adt/int8.c:1055 utils/adt/int8.c:1069 utils/adt/int8.c:1100 +#: utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 +#: utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4542 +#: utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 #: utils/adt/varbit.c:1676 #, c-format msgid "bigint out of range" msgstr "bigint fuera de rango" -#: utils/adt/int8.c:1361 +#: utils/adt/int8.c:1360 #, c-format msgid "OID out of range" msgstr "OID fuera de rango" -#: utils/adt/json.c:320 utils/adt/jsonb.c:781 +#: utils/adt/json.c:202 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "el valor de llave debe ser escalar, no array, composite o json" -#: utils/adt/json.c:1113 utils/adt/json.c:1123 utils/fmgr/funcapi.c:2082 +#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "no se pudo determinar el tipo de dato para el argumento %d" -#: utils/adt/json.c:1146 utils/adt/json.c:1337 utils/adt/json.c:1513 -#: utils/adt/json.c:1591 utils/adt/jsonb.c:1432 utils/adt/jsonb.c:1522 +#: utils/adt/json.c:1067 utils/adt/json.c:1266 utils/adt/json.c:1449 +#: utils/adt/json.c:1527 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "no se permite el valor nulo como llave en un objeto" -#: utils/adt/json.c:1189 utils/adt/json.c:1352 -#, fuzzy, c-format -#| msgid "Duplicate keys exist." -msgid "duplicate JSON key %s" -msgstr "Existe una llave duplicada." +#: utils/adt/json.c:1117 utils/adt/json.c:1288 +#, c-format +msgid "duplicate JSON object key value: %s" +msgstr "valor de llave de objeto JSON duplicado: %s" -#: utils/adt/json.c:1297 utils/adt/jsonb.c:1233 +#: utils/adt/json.c:1226 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "la lista de argumentos debe tener un número par de elementos" #. translator: %s is a SQL function name -#: utils/adt/json.c:1299 utils/adt/jsonb.c:1235 +#: utils/adt/json.c:1228 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "El argumento de %s debe consistir de llaves y valores alternados." -#: utils/adt/json.c:1491 utils/adt/jsonb.c:1410 +#: utils/adt/json.c:1427 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "un array debe tener dos columnas" -#: utils/adt/json.c:1580 utils/adt/jsonb.c:1511 +#: utils/adt/json.c:1516 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "las dimensiones de array no coinciden" -#: utils/adt/json.c:1764 +#: utils/adt/json.c:1702 utils/adt/jsonb_util.c:1956 #, c-format msgid "duplicate JSON object key value" -msgstr "" +msgstr "valor de llavo del objeto JSON duplicado" -#: utils/adt/jsonb.c:294 +#: utils/adt/jsonb.c:282 #, c-format msgid "string too long to represent as jsonb string" msgstr "la cadena es demasiado larga para representarla como cadena jsonb." -#: utils/adt/jsonb.c:295 +#: utils/adt/jsonb.c:283 #, c-format msgid "Due to an implementation restriction, jsonb strings cannot exceed %d bytes." msgstr "Debido a una restricción de la implementación, las cadenas en jsonb no pueden exceder los %d bytes." -#: utils/adt/jsonb.c:1252 +#: utils/adt/jsonb.c:1153 #, c-format msgid "argument %d: key must not be null" msgstr "argumento %d: la llave no puede ser null" -#: utils/adt/jsonb.c:1843 +#: utils/adt/jsonb.c:1744 #, c-format msgid "field name must not be null" msgstr "el nombre de campo no debe ser null" -#: utils/adt/jsonb.c:1905 +#: utils/adt/jsonb.c:1806 #, c-format msgid "object keys must be strings" msgstr "las llaves de un objeto deben ser cadenas" -#: utils/adt/jsonb.c:2116 +#: utils/adt/jsonb.c:2017 #, c-format msgid "cannot cast jsonb null to type %s" msgstr "no se puede convertir un null jsonb a tipo %s" -#: utils/adt/jsonb.c:2117 +#: utils/adt/jsonb.c:2018 #, c-format msgid "cannot cast jsonb string to type %s" msgstr "no se puede convertir un string jsonb a tipo %s" -#: utils/adt/jsonb.c:2118 +#: utils/adt/jsonb.c:2019 #, c-format msgid "cannot cast jsonb numeric to type %s" msgstr "no se puede convertir un numérico jsonb a tipo %s" -#: utils/adt/jsonb.c:2119 +#: utils/adt/jsonb.c:2020 #, c-format msgid "cannot cast jsonb boolean to type %s" msgstr "no se puede convertir un booleano jsonb a tipo %s" -#: utils/adt/jsonb.c:2120 +#: utils/adt/jsonb.c:2021 #, c-format msgid "cannot cast jsonb array to type %s" msgstr "no se puede convertir un array jsonb a tipo %s" -#: utils/adt/jsonb.c:2121 +#: utils/adt/jsonb.c:2022 #, c-format msgid "cannot cast jsonb object to type %s" msgstr "no se puede convertir un objeto jsonb a tipo %s" -#: utils/adt/jsonb.c:2122 +#: utils/adt/jsonb.c:2023 #, c-format msgid "cannot cast jsonb array or object to type %s" msgstr "no se puede convertir un array u objeto jsonb a tipo %s" -#: utils/adt/jsonb_util.c:758 +#: utils/adt/jsonb_util.c:756 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "el número de pares en objeto jsonb excede el máximo permitido (%zu)" -#: utils/adt/jsonb_util.c:799 +#: utils/adt/jsonb_util.c:797 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "el número de elementos del array jsonb excede el máximo permitido (%zu)" -#: utils/adt/jsonb_util.c:1673 utils/adt/jsonb_util.c:1693 -#, fuzzy, c-format -#| msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" +#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 +#, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" -msgstr "el número de elementos del array jsonb excede el máximo permitido (%zu)" +msgstr "el tamaño total de los elementos del array jsonb excede el máximo de %d bytes" -#: utils/adt/jsonb_util.c:1754 utils/adt/jsonb_util.c:1789 -#: utils/adt/jsonb_util.c:1809 -#, fuzzy, c-format -#| msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" +#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 +#: utils/adt/jsonb_util.c:1807 +#, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" -msgstr "el número de elementos del array jsonb excede el máximo permitido (%zu)" - -#: utils/adt/jsonb_util.c:1958 -#, fuzzy, c-format -#| msgid "unexpected object end" -msgid "duplicate JSON object key" -msgstr "fin de objeto inesperado" +msgstr "el tamaño total de los elementos del objeto jsonb excede el máximo de %d bytes" -#: utils/adt/jsonbsubs.c:70 utils/adt/jsonbsubs.c:151 +#: utils/adt/jsonbsubs.c:67 utils/adt/jsonbsubs.c:148 #, c-format msgid "jsonb subscript does not support slices" msgstr "el subíndice jsonb no soporta segmentos" -#: utils/adt/jsonbsubs.c:103 utils/adt/jsonbsubs.c:117 +#: utils/adt/jsonbsubs.c:100 utils/adt/jsonbsubs.c:114 #, c-format msgid "subscript type %s is not supported" msgstr "el tipo de subíndice %s no está soportado" -#: utils/adt/jsonbsubs.c:104 +#: utils/adt/jsonbsubs.c:101 #, c-format msgid "jsonb subscript must be coercible to only one type, integer or text." msgstr "subíndice jsonb debe ser coercible solo para un tipo, integer o text." -#: utils/adt/jsonbsubs.c:118 +#: utils/adt/jsonbsubs.c:115 #, c-format msgid "jsonb subscript must be coercible to either integer or text." msgstr "subíndice jsonb debe ser coercible ya sea para integer o para text." -#: utils/adt/jsonbsubs.c:139 +#: utils/adt/jsonbsubs.c:136 #, c-format msgid "jsonb subscript must have text type" msgstr "subíndice jsonb debe tener tipo text" -#: utils/adt/jsonbsubs.c:207 +#: utils/adt/jsonbsubs.c:204 #, c-format msgid "jsonb subscript in assignment must not be null" msgstr "subíndice jsonb en asignación no puede ser nulo" -#: utils/adt/jsonfuncs.c:572 utils/adt/jsonfuncs.c:821 -#: utils/adt/jsonfuncs.c:2429 utils/adt/jsonfuncs.c:2881 -#: utils/adt/jsonfuncs.c:3676 utils/adt/jsonfuncs.c:4018 +#: utils/adt/jsonfuncs.c:583 utils/adt/jsonfuncs.c:830 +#: utils/adt/jsonfuncs.c:2439 utils/adt/jsonfuncs.c:3015 +#: utils/adt/jsonfuncs.c:3948 utils/adt/jsonfuncs.c:4295 #, c-format msgid "cannot call %s on a scalar" msgstr "no se puede invocar %s en un escalar" -#: utils/adt/jsonfuncs.c:577 utils/adt/jsonfuncs.c:806 -#: utils/adt/jsonfuncs.c:2883 utils/adt/jsonfuncs.c:3663 +#: utils/adt/jsonfuncs.c:588 utils/adt/jsonfuncs.c:815 +#: utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3935 #, c-format msgid "cannot call %s on an array" msgstr "no se puede invocar %s en un array" -#: utils/adt/jsonfuncs.c:636 jsonpath_scan.l:596 +#: utils/adt/jsonfuncs.c:647 jsonpath_scan.l:607 #, c-format msgid "unsupported Unicode escape sequence" msgstr "secuencia de escape Unicode no soportado" -#: utils/adt/jsonfuncs.c:713 +#: utils/adt/jsonfuncs.c:724 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "Datos JSON, línea %d: %s%s%s" -#: utils/adt/jsonfuncs.c:1875 utils/adt/jsonfuncs.c:1912 +#: utils/adt/jsonfuncs.c:1883 utils/adt/jsonfuncs.c:1920 #, c-format msgid "cannot get array length of a scalar" msgstr "no se puede obtener el largo de array de un escalar" -#: utils/adt/jsonfuncs.c:1879 utils/adt/jsonfuncs.c:1898 +#: utils/adt/jsonfuncs.c:1887 utils/adt/jsonfuncs.c:1906 #, c-format msgid "cannot get array length of a non-array" msgstr "no se puede obtener el largo de array de un no-array" -#: utils/adt/jsonfuncs.c:1978 +#: utils/adt/jsonfuncs.c:1986 #, c-format msgid "cannot call %s on a non-object" msgstr "no se puede invocar %s en un no-objeto" -#: utils/adt/jsonfuncs.c:2166 +#: utils/adt/jsonfuncs.c:2174 #, c-format msgid "cannot deconstruct an array as an object" msgstr "no se puede desconstruir un array como un objeto" -#: utils/adt/jsonfuncs.c:2180 +#: utils/adt/jsonfuncs.c:2188 #, c-format msgid "cannot deconstruct a scalar" msgstr "no se puede desconstruir un escalar" -#: utils/adt/jsonfuncs.c:2225 +#: utils/adt/jsonfuncs.c:2233 #, c-format msgid "cannot extract elements from a scalar" msgstr "no se pueden extraer elementos de un escalar" -#: utils/adt/jsonfuncs.c:2229 +#: utils/adt/jsonfuncs.c:2237 #, c-format msgid "cannot extract elements from an object" msgstr "no se pudo extraer elementos de un objeto" -#: utils/adt/jsonfuncs.c:2414 utils/adt/jsonfuncs.c:3896 +#: utils/adt/jsonfuncs.c:2424 utils/adt/jsonfuncs.c:4173 #, c-format msgid "cannot call %s on a non-array" msgstr "no se puede invocar %s en un no-array" -#: utils/adt/jsonfuncs.c:2488 utils/adt/jsonfuncs.c:2493 -#: utils/adt/jsonfuncs.c:2510 utils/adt/jsonfuncs.c:2516 +#: utils/adt/jsonfuncs.c:2515 utils/adt/jsonfuncs.c:2520 +#: utils/adt/jsonfuncs.c:2538 utils/adt/jsonfuncs.c:2544 #, c-format msgid "expected JSON array" msgstr "se esperaba un array JSON" -#: utils/adt/jsonfuncs.c:2489 +#: utils/adt/jsonfuncs.c:2516 #, c-format msgid "See the value of key \"%s\"." msgstr "Vea el valor de la llave «%s»." -#: utils/adt/jsonfuncs.c:2511 +#: utils/adt/jsonfuncs.c:2539 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "Vea el elemento %s de la llave «%s»." -#: utils/adt/jsonfuncs.c:2517 +#: utils/adt/jsonfuncs.c:2545 #, c-format msgid "See the array element %s." msgstr "Veo el elemento de array %s." -#: utils/adt/jsonfuncs.c:2552 +#: utils/adt/jsonfuncs.c:2597 #, c-format msgid "malformed JSON array" msgstr "array JSON mal formado" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3389 +#: utils/adt/jsonfuncs.c:3647 #, c-format msgid "first argument of %s must be a row type" msgstr "el primer argumento de %s debe ser un tipo de registro" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3413 +#: utils/adt/jsonfuncs.c:3671 #, c-format msgid "could not determine row type for result of %s" msgstr "no se pudo determinar el tipo de dato para el resultado de %s" -#: utils/adt/jsonfuncs.c:3415 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "Provide a non-null record argument, or call the function in the FROM clause using a column definition list." msgstr "Provea un argumento de registro no-nulo, o invoque la función en la cláusula FROM usando una lista de definición de columnas." -#: utils/adt/jsonfuncs.c:3785 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4059 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "se requiere un nodo «materialize», pero no está permitido en este contexto" -#: utils/adt/jsonfuncs.c:3913 utils/adt/jsonfuncs.c:3997 +#: utils/adt/jsonfuncs.c:4190 utils/adt/jsonfuncs.c:4274 #, c-format msgid "argument of %s must be an array of objects" msgstr "el argumento de %s debe ser un array de objetos" -#: utils/adt/jsonfuncs.c:3946 +#: utils/adt/jsonfuncs.c:4223 #, c-format msgid "cannot call %s on an object" msgstr "no se puede invocar %s en un objeto" -#: utils/adt/jsonfuncs.c:4380 utils/adt/jsonfuncs.c:4439 -#: utils/adt/jsonfuncs.c:4519 +#: utils/adt/jsonfuncs.c:4656 utils/adt/jsonfuncs.c:4715 +#: utils/adt/jsonfuncs.c:4795 #, c-format msgid "cannot delete from scalar" msgstr "no se puede eliminar de un escalar" -#: utils/adt/jsonfuncs.c:4524 +#: utils/adt/jsonfuncs.c:4800 #, c-format msgid "cannot delete from object using integer index" msgstr "no se puede eliminar de un objeto usando un índice numérico" -#: utils/adt/jsonfuncs.c:4592 utils/adt/jsonfuncs.c:4751 +#: utils/adt/jsonfuncs.c:4868 utils/adt/jsonfuncs.c:5027 #, c-format msgid "cannot set path in scalar" msgstr "no se puede definir una ruta en un escalar" -#: utils/adt/jsonfuncs.c:4633 utils/adt/jsonfuncs.c:4675 +#: utils/adt/jsonfuncs.c:4909 utils/adt/jsonfuncs.c:4951 #, c-format msgid "null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"" msgstr "null_value_treatment debe ser «delete_key», «return_target», «use_json_null», o «raise_exception»" -#: utils/adt/jsonfuncs.c:4646 +#: utils/adt/jsonfuncs.c:4922 #, c-format msgid "JSON value must not be null" msgstr "valor JSON no debe ser null" -#: utils/adt/jsonfuncs.c:4647 +#: utils/adt/jsonfuncs.c:4923 #, c-format msgid "Exception was raised because null_value_treatment is \"raise_exception\"." msgstr "Una excepción fue lanzada porque null_value_treatment es «raise_exception»." -#: utils/adt/jsonfuncs.c:4648 +#: utils/adt/jsonfuncs.c:4924 #, c-format msgid "To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed." msgstr "Para impedir esto, puede cambiar el argumento null_value_treatment o asegurarse que no se pase un nulo SQL." -#: utils/adt/jsonfuncs.c:4703 +#: utils/adt/jsonfuncs.c:4979 #, c-format msgid "cannot delete path in scalar" msgstr "no se puede eliminar una ruta en un escalar" -#: utils/adt/jsonfuncs.c:4917 +#: utils/adt/jsonfuncs.c:5193 #, c-format msgid "path element at position %d is null" msgstr "el elemento en la posición %d de la ruta es null" -#: utils/adt/jsonfuncs.c:4936 utils/adt/jsonfuncs.c:4967 -#: utils/adt/jsonfuncs.c:5040 +#: utils/adt/jsonfuncs.c:5212 utils/adt/jsonfuncs.c:5243 +#: utils/adt/jsonfuncs.c:5316 #, c-format msgid "cannot replace existing key" msgstr "no se puede reemplazar una llave existente" -#: utils/adt/jsonfuncs.c:4937 utils/adt/jsonfuncs.c:4968 +#: utils/adt/jsonfuncs.c:5213 utils/adt/jsonfuncs.c:5244 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "La ruta asume que la llave es un objeto compuesto, pero es un valor escalar." -#: utils/adt/jsonfuncs.c:5041 +#: utils/adt/jsonfuncs.c:5317 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "Intente usar la función jsonb_set para reemplazar el valor de la llave." -#: utils/adt/jsonfuncs.c:5145 +#: utils/adt/jsonfuncs.c:5421 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "el elemento de ruta en la posición %d no es un entero: «%s»" -#: utils/adt/jsonfuncs.c:5162 +#: utils/adt/jsonfuncs.c:5438 #, c-format msgid "path element at position %d is out of range: %d" msgstr "el elemento de ruta en la posición %d está fuera de rango: %d" -#: utils/adt/jsonfuncs.c:5314 +#: utils/adt/jsonfuncs.c:5590 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "indicador de tipo errónea, sólo se permiten arrays y tipos escalares" -#: utils/adt/jsonfuncs.c:5321 +#: utils/adt/jsonfuncs.c:5597 #, c-format msgid "flag array element is not a string" msgstr "elemento del array de opciones no es un string" -#: utils/adt/jsonfuncs.c:5322 utils/adt/jsonfuncs.c:5344 +#: utils/adt/jsonfuncs.c:5598 utils/adt/jsonfuncs.c:5620 #, c-format msgid "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\"." msgstr "Los valores posibles son: «string», «numeric», «boolean», «key» y «all»." -#: utils/adt/jsonfuncs.c:5342 +#: utils/adt/jsonfuncs.c:5618 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "indicador erróneo en array de indicadores: «%s»" -#: utils/adt/jsonpath.c:382 +#: utils/adt/jsonpath.c:389 #, c-format msgid "@ is not allowed in root expressions" msgstr "@ no es permitido en expresiones raíz" -#: utils/adt/jsonpath.c:388 +#: utils/adt/jsonpath.c:395 #, c-format msgid "LAST is allowed only in array subscripts" msgstr "LAST sólo está permitido en subíndices de array" -#: utils/adt/jsonpath_exec.c:361 +#: utils/adt/jsonpath_exec.c:491 #, c-format msgid "single boolean result is expected" msgstr "se esperaba un único resultado booleano" -#: utils/adt/jsonpath_exec.c:557 +#: utils/adt/jsonpath_exec.c:851 #, c-format -msgid "\"vars\" argument is not an object" -msgstr "el argumento «vars» no es un objeto" +msgid "jsonpath wildcard array accessor can only be applied to an array" +msgstr "el método de acceso comodín de array jsonpath sólo puede aplicarse a un array" -#: utils/adt/jsonpath_exec.c:558 +#: utils/adt/jsonpath_exec.c:874 #, c-format -msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." -msgstr "Los parámetros jsonpath deben codificarse como pares llave-valor del objeto «vars»." +msgid "jsonpath wildcard member accessor can only be applied to an object" +msgstr "el método de acesso comodín de objeto jsonpath sólo puede aplicarse a un objeto" + +#: utils/adt/jsonpath_exec.c:923 +#, c-format +msgid "jsonpath array subscript is out of bounds" +msgstr "subíndice de array jsonpath fuera de los bordes" -#: utils/adt/jsonpath_exec.c:675 +#: utils/adt/jsonpath_exec.c:980 +#, c-format +msgid "jsonpath array accessor can only be applied to an array" +msgstr "el método de acceso de array jsonpath sólo puede aplicarse a un array" + +#: utils/adt/jsonpath_exec.c:1044 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "el objeto JSON no contiene la llave «%s»" -#: utils/adt/jsonpath_exec.c:687 +#: utils/adt/jsonpath_exec.c:1056 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "el método de acceso a un miembro jsonpath sólo puede aplicarse a un objeto" -#: utils/adt/jsonpath_exec.c:716 +#: utils/adt/jsonpath_exec.c:1114 #, c-format -msgid "jsonpath wildcard array accessor can only be applied to an array" -msgstr "el método de acceso comodín de array jsonpath sólo puede aplicarse a un array" +msgid "jsonpath item method .%s() can only be applied to an array" +msgstr "el método de ítem jsonpath .%s() sólo puede aplicase a un array" -#: utils/adt/jsonpath_exec.c:764 +#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 #, c-format -msgid "jsonpath array subscript is out of bounds" -msgstr "subíndice de array jsonpath fuera de los bordes" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type double precision" +msgstr "el argumento «%s» del método de item jsonpath .%s() no es válido para el tipo de precisión doble" -#: utils/adt/jsonpath_exec.c:821 +#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 +#: utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 #, c-format -msgid "jsonpath array accessor can only be applied to an array" -msgstr "el método de acceso de array jsonpath sólo puede aplicarse a un array" +msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" +msgstr "NaN o infinito no son permitidos para el método de ítem jsonpath .%s()" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 +#: utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 #, c-format -msgid "jsonpath wildcard member accessor can only be applied to an object" -msgstr "el método de acesso comodín de objeto jsonpath sólo puede aplicarse a un objeto" +msgid "jsonpath item method .%s() can only be applied to a string or numeric value" +msgstr "el método de ítem jsonpath .%s() sólo puede aplicarse a un valor numérico o de cadena" -#: utils/adt/jsonpath_exec.c:1007 +#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 #, c-format -msgid "jsonpath item method .%s() can only be applied to an array" -msgstr "el método de ítem jsonpath .%s() sólo puede aplicase a un array" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" +msgstr "el argumento «%s» del método de item jsonpath .%s() es inválido para el tipo bigint" -#: utils/adt/jsonpath_exec.c:1060 +#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 #, c-format -msgid "numeric argument of jsonpath item method .%s() is out of range for type double precision" -msgstr "el argumento numérico del método de item jsonpath .%s() está fuera de rango para el tipo de precisión doble" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" +msgstr "el argumento «%s» del método de item jsonpath .%s() no es válido para el tipo booleano" -#: utils/adt/jsonpath_exec.c:1081 +#: utils/adt/jsonpath_exec.c:1386 #, c-format -msgid "string argument of jsonpath item method .%s() is not a valid representation of a double precision number" -msgstr "el argumento cadena del método de item jsonpath .%s() no es una representación válida de un número de precisión doble" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, or numeric value" +msgstr "el método de ítem jsonpath .%s() sólo puede aplicarse a un valor booleano, de cadena o numérico" -#: utils/adt/jsonpath_exec.c:1094 +#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 #, c-format -msgid "jsonpath item method .%s() can only be applied to a string or numeric value" -msgstr "el método de ítem jsonpath .%s() sólo puede aplicarse a un valor numérico o de cadena" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" +msgstr "el argumento «%s» del método de item jsonpath .%s() no es válido para el tipo numeric" + +#: utils/adt/jsonpath_exec.c:1487 +#, c-format +msgid "precision of jsonpath item method .%s() is out of range for type integer" +msgstr "la precisión del método de item jsonpath .%s() está fuera de rango para el tipo integer" + +#: utils/adt/jsonpath_exec.c:1501 +#, c-format +msgid "scale of jsonpath item method .%s() is out of range for type integer" +msgstr "la escala del método de item jsonpath .%s() está fuera de rango para el tipo integer" -#: utils/adt/jsonpath_exec.c:1584 +#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 +#, c-format +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type integer" +msgstr "el argumento «%s» del método de item jsonpath .%s() no es válido para el tipo integer" + +#: utils/adt/jsonpath_exec.c:1648 +#, c-format +msgid "jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value" +msgstr "el método de ítem jsonpath .%s() sólo puede aplicarse a un valor boolean, datetime, numérico o de cadena" + +#: utils/adt/jsonpath_exec.c:2137 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "el operando izquierdo del operador jsonpath %s no es un valor numérico escalar" -#: utils/adt/jsonpath_exec.c:1591 +#: utils/adt/jsonpath_exec.c:2144 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "el operando derecho del operador jsonpath %s no es un valor numérico escalar" -#: utils/adt/jsonpath_exec.c:1659 +#: utils/adt/jsonpath_exec.c:2212 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "el operando del operador jsonpath unario %s no es un valor numérico" -#: utils/adt/jsonpath_exec.c:1758 +#: utils/adt/jsonpath_exec.c:2311 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "el método de ítem jsonpath .%s() sólo puede aplicarse a un valor numérico" -#: utils/adt/jsonpath_exec.c:1798 +#: utils/adt/jsonpath_exec.c:2357 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "el método de ítem jsonpath .%s() sólo puede aplicase a una cadena" -#: utils/adt/jsonpath_exec.c:1892 +#: utils/adt/jsonpath_exec.c:2450 +#, c-format +msgid "time precision of jsonpath item method .%s() is out of range for type integer" +msgstr "la precisión de tiempo del método de item jsonpath .%s() está fuera de rango para el tipo integer" + +#: utils/adt/jsonpath_exec.c:2484 utils/adt/jsonpath_exec.c:2490 +#: utils/adt/jsonpath_exec.c:2517 utils/adt/jsonpath_exec.c:2545 +#: utils/adt/jsonpath_exec.c:2598 utils/adt/jsonpath_exec.c:2649 +#: utils/adt/jsonpath_exec.c:2720 #, c-format -msgid "datetime format is not recognized: \"%s\"" -msgstr "el formato de fecha/hora no se reconoce: «%s»" +msgid "%s format is not recognized: \"%s\"" +msgstr "formato de %s no se reconoce: «%s»" -#: utils/adt/jsonpath_exec.c:1894 +#: utils/adt/jsonpath_exec.c:2486 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "Use un argumento de patrón fecha/hora para especificar el formato de entrada del dato." -#: utils/adt/jsonpath_exec.c:1962 +#: utils/adt/jsonpath_exec.c:2679 utils/adt/jsonpath_exec.c:2760 +#, c-format +msgid "time precision of jsonpath item method .%s() is invalid" +msgstr "la precisión de tiempo del método de item jsonpath .%s() no es válida" + +#: utils/adt/jsonpath_exec.c:2840 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "el método de ítem jsonpath .%s() sólo puede ser aplicado a un objeto" -#: utils/adt/jsonpath_exec.c:2144 +#: utils/adt/jsonpath_exec.c:3124 +#, c-format +msgid "could not convert value of type %s to jsonpath" +msgstr "no se pudo convertir el valor de tipo %s a jsonpath" + +#: utils/adt/jsonpath_exec.c:3158 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "no se pudo encontrar la variable jsonpath «%s»" -#: utils/adt/jsonpath_exec.c:2408 +#: utils/adt/jsonpath_exec.c:3211 +#, c-format +msgid "\"vars\" argument is not an object" +msgstr "el argumento «vars» no es un objeto" + +#: utils/adt/jsonpath_exec.c:3212 +#, c-format +msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgstr "Los parámetros jsonpath deben codificarse como pares llave-valor del objeto «vars»." + +#: utils/adt/jsonpath_exec.c:3475 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "el subíndice de array jsonpath no es un único valor numérico" -#: utils/adt/jsonpath_exec.c:2420 +#: utils/adt/jsonpath_exec.c:3487 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "subíndice de array jsonpath fuera del rango entero" -#: utils/adt/jsonpath_exec.c:2597 +#: utils/adt/jsonpath_exec.c:3671 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "no se puede convertir el valor de %s a %s sin uso de huso horario" -#: utils/adt/jsonpath_exec.c:2599 +#: utils/adt/jsonpath_exec.c:3673 #, c-format msgid "Use *_tz() function for time zone support." msgstr "Utilice una función *_tz() para el soporte de huso horario." +#: utils/adt/jsonpath_exec.c:3981 +#, c-format +#| msgid "JSON path expression for column \"%s\" should return single item without wrapper" +msgid "JSON path expression for column \"%s\" must return single item when no wrapper is requested" +msgstr "la expresión de ruta JSON para la columna «%s» debe retornar un único elemento cuando no se pide un “wrapper”" + +#: utils/adt/jsonpath_exec.c:3983 utils/adt/jsonpath_exec.c:3988 +#, c-format +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." +msgstr "Use la cláusula WITH WRAPPER para envolver elementos SQL/JSON en un array." + +#: utils/adt/jsonpath_exec.c:3987 +#, c-format +#| msgid "JSON path expression in JSON_QUERY should return single item without wrapper" +msgid "JSON path expression in JSON_QUERY must return single item when no wrapper is requested" +msgstr "la expresión de ruta en JSON_QUERY debe retornar un único elemento cuando no se pide un “wrapper”" + +#: utils/adt/jsonpath_exec.c:4045 utils/adt/jsonpath_exec.c:4069 +#, c-format +#| msgid "JSON path expression for column \"%s\" should return single scalar item" +msgid "JSON path expression for column \"%s\" must return single scalar item" +msgstr "la expresión de ruta JSON para la columna «%s» debe retornar un único elemento escalar" + +#: utils/adt/jsonpath_exec.c:4050 utils/adt/jsonpath_exec.c:4074 +#, c-format +#| msgid "JSON path expression in JSON_VALUE should return single scalar item" +msgid "JSON path expression in JSON_VALUE must return single scalar item" +msgstr "la expresión de ruta JSON en JSON_VALUE debe retornar un único elemento escalar" + #: utils/adt/levenshtein.c:132 #, c-format msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "el argumento levenshtein excede el largo máximo de %d caracteres" -#: utils/adt/like.c:161 +#: utils/adt/like.c:159 #, c-format msgid "nondeterministic collations are not supported for LIKE" msgstr "los ordenamientos no determinísticos no están soportados para LIKE" -#: utils/adt/like.c:190 utils/adt/like_support.c:1024 +#: utils/adt/like.c:188 utils/adt/like_support.c:1023 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "no se pudo determinar qué ordenamiento (collation) usar para ILIKE" -#: utils/adt/like.c:202 +#: utils/adt/like.c:200 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "los ordenamientos no determinísticos no están soportados para ILIKE" @@ -24922,22 +25678,22 @@ msgstr "los ordenamientos no determinísticos no están soportados para ILIKE" msgid "LIKE pattern must not end with escape character" msgstr "el patrón de LIKE debe no terminar con un carácter de escape" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "cadena de escape no válida" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:802 +#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "La cadena de escape debe ser vacía o un carácter." -#: utils/adt/like_support.c:1014 +#: utils/adt/like_support.c:1013 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "no está soportada la comparación insensible a mayúsculas en bytea" -#: utils/adt/like_support.c:1115 +#: utils/adt/like_support.c:1114 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "no está soportada la comparación con expresiones regulares en bytea" @@ -24947,17 +25703,17 @@ msgstr "no está soportada la comparación con expresiones regulares en bytea" msgid "invalid octet value in \"macaddr\" value: \"%s\"" msgstr "valor de octeto no válido en valor «macaddr»: «%s»" -#: utils/adt/mac8.c:554 +#: utils/adt/mac8.c:555 #, c-format msgid "macaddr8 data out of range to convert to macaddr" msgstr "datos macaddr8 fuera de rango para convertir a macaddr" -#: utils/adt/mac8.c:555 +#: utils/adt/mac8.c:556 #, c-format msgid "Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr." msgstr "Sólo las direcciones que tienen FF y FF como valores en el cuarto y quinto bytes desde la izquierda, por ejemplo xx:xx:xx:ff:fe:xx:xx:xx se pueden convertir de macaddr8 a macaddr." -#: utils/adt/mcxtfuncs.c:182 +#: utils/adt/mcxtfuncs.c:173 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %d no es un proceso servidor de PostgreSQL" @@ -24996,70 +25752,70 @@ msgstr "puede ser una etiqueta sola" msgid "requires AS" msgstr "requiere AS" -#: utils/adt/misc.c:853 utils/adt/misc.c:867 utils/adt/misc.c:906 -#: utils/adt/misc.c:912 utils/adt/misc.c:918 utils/adt/misc.c:941 +#: utils/adt/misc.c:897 utils/adt/misc.c:911 utils/adt/misc.c:950 +#: utils/adt/misc.c:956 utils/adt/misc.c:962 utils/adt/misc.c:985 #, c-format msgid "string is not a valid identifier: \"%s\"" msgstr "la cadena no es un identificador válido: «%s»" -#: utils/adt/misc.c:855 +#: utils/adt/misc.c:899 #, c-format msgid "String has unclosed double quotes." msgstr "La cadena tiene comillas dobles sin cerrar." -#: utils/adt/misc.c:869 +#: utils/adt/misc.c:913 #, c-format msgid "Quoted identifier must not be empty." msgstr "El identificador en comillas no debe ser vacío." -#: utils/adt/misc.c:908 +#: utils/adt/misc.c:952 #, c-format msgid "No valid identifier before \".\"." msgstr "No hay un identificador válido antes de «.»." -#: utils/adt/misc.c:914 +#: utils/adt/misc.c:958 #, c-format msgid "No valid identifier after \".\"." msgstr "No hay un identificador válido después de «.»." -#: utils/adt/misc.c:974 +#: utils/adt/misc.c:1018 #, c-format msgid "log format \"%s\" is not supported" msgstr "el formato de log «%s» no está soportado" -#: utils/adt/misc.c:975 +#: utils/adt/misc.c:1019 #, c-format msgid "The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\"." -msgstr "" +msgstr "Los formatos de log soportados son «stderr», «csvlog» y «jsonlog»." -#: utils/adt/multirangetypes.c:151 utils/adt/multirangetypes.c:164 -#: utils/adt/multirangetypes.c:193 utils/adt/multirangetypes.c:267 -#: utils/adt/multirangetypes.c:291 +#: utils/adt/multirangetypes.c:150 utils/adt/multirangetypes.c:163 +#: utils/adt/multirangetypes.c:192 utils/adt/multirangetypes.c:266 +#: utils/adt/multirangetypes.c:290 #, c-format msgid "malformed multirange literal: \"%s\"" msgstr "literal de multirango mal formado: «%s»" -#: utils/adt/multirangetypes.c:153 +#: utils/adt/multirangetypes.c:152 #, c-format msgid "Missing left brace." msgstr "Falta llave izquierda." -#: utils/adt/multirangetypes.c:195 +#: utils/adt/multirangetypes.c:194 #, c-format msgid "Expected range start." msgstr "Se esperaba inicio de rango." -#: utils/adt/multirangetypes.c:269 +#: utils/adt/multirangetypes.c:268 #, c-format msgid "Expected comma or end of multirange." msgstr "Se esperaba una coma o el final del multirango." -#: utils/adt/multirangetypes.c:982 +#: utils/adt/multirangetypes.c:981 #, c-format msgid "multiranges cannot be constructed from multidimensional arrays" msgstr "no se puede construir multirangos a partir de arrays multidimensionales" -#: utils/adt/multirangetypes.c:1008 +#: utils/adt/multirangetypes.c:1007 #, c-format msgid "multirange values cannot contain null members" msgstr "valores de multirango no pueden contener miembros nulos" @@ -25138,113 +25894,138 @@ msgstr "el resultado está fuera de rango" msgid "cannot subtract inet values of different sizes" msgstr "no se puede sustraer valores inet de distintos tamaños" -#: utils/adt/numeric.c:785 utils/adt/numeric.c:3643 utils/adt/numeric.c:7131 -#: utils/adt/numeric.c:7334 utils/adt/numeric.c:7806 utils/adt/numeric.c:10501 -#: utils/adt/numeric.c:10975 utils/adt/numeric.c:11069 -#: utils/adt/numeric.c:11203 +#: utils/adt/numeric.c:793 utils/adt/numeric.c:3659 utils/adt/numeric.c:7216 +#: utils/adt/numeric.c:7419 utils/adt/numeric.c:7891 utils/adt/numeric.c:10586 +#: utils/adt/numeric.c:11061 utils/adt/numeric.c:11155 +#: utils/adt/numeric.c:11290 #, c-format msgid "value overflows numeric format" msgstr "el valor excede el formato numeric" -#: utils/adt/numeric.c:1098 +#: utils/adt/numeric.c:1106 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "el signo no es válido en el valor «numeric» externo" -#: utils/adt/numeric.c:1104 +#: utils/adt/numeric.c:1112 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "la escala no es válida en el valor «numeric» externo" -#: utils/adt/numeric.c:1113 +#: utils/adt/numeric.c:1121 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "hay un dígito no válido en el valor «numeric» externo" -#: utils/adt/numeric.c:1328 utils/adt/numeric.c:1342 +#: utils/adt/numeric.c:1336 utils/adt/numeric.c:1350 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "la precisión %d de NUMERIC debe estar entre 1 y %d" -#: utils/adt/numeric.c:1333 -#, fuzzy, c-format -#| msgid "NUMERIC precision %d must be between 1 and %d" +#: utils/adt/numeric.c:1341 +#, c-format msgid "NUMERIC scale %d must be between %d and %d" -msgstr "la precisión %d de NUMERIC debe estar entre 1 y %d" +msgstr "escala NUMERIC %d debe estar entre %d y %d" -#: utils/adt/numeric.c:1351 +#: utils/adt/numeric.c:1359 #, c-format msgid "invalid NUMERIC type modifier" msgstr "modificador de tipo NUMERIC no es válido" -#: utils/adt/numeric.c:1709 +#: utils/adt/numeric.c:1725 #, c-format msgid "start value cannot be NaN" msgstr "el valor de inicio no puede ser NaN" -#: utils/adt/numeric.c:1713 +#: utils/adt/numeric.c:1729 #, c-format msgid "start value cannot be infinity" msgstr "el valor de inicio no puede ser infinito" -#: utils/adt/numeric.c:1720 +#: utils/adt/numeric.c:1736 #, c-format msgid "stop value cannot be NaN" msgstr "el valor de término no puede ser NaN" -#: utils/adt/numeric.c:1724 +#: utils/adt/numeric.c:1740 #, c-format msgid "stop value cannot be infinity" msgstr "el valor de término no puede ser infinito" -#: utils/adt/numeric.c:1737 +#: utils/adt/numeric.c:1753 #, c-format msgid "step size cannot be NaN" msgstr "el tamaño de paso no puede ser NaN" -#: utils/adt/numeric.c:1741 +#: utils/adt/numeric.c:1757 #, c-format msgid "step size cannot be infinity" msgstr "el tamaño de paso no puede ser infinito" -#: utils/adt/numeric.c:3633 +#: utils/adt/numeric.c:3649 #, c-format msgid "factorial of a negative number is undefined" msgstr "el factorial de un número negativo es indefinido" -#: utils/adt/numeric.c:4366 utils/adt/numeric.c:4446 utils/adt/numeric.c:4487 -#: utils/adt/numeric.c:4683 +#: utils/adt/numeric.c:4256 +#, c-format +msgid "lower bound cannot be NaN" +msgstr "el límite inferior no puede ser NaN" + +#: utils/adt/numeric.c:4260 +#, c-format +msgid "lower bound cannot be infinity" +msgstr "el límite inferior no puede ser infinito" + +#: utils/adt/numeric.c:4267 +#, c-format +msgid "upper bound cannot be NaN" +msgstr "el límite superior no puede ser NaN" + +#: utils/adt/numeric.c:4271 +#, c-format +msgid "upper bound cannot be infinity" +msgstr "el límite superior no puede ser infinito" + +#: utils/adt/numeric.c:4432 utils/adt/numeric.c:4520 utils/adt/numeric.c:4580 +#: utils/adt/numeric.c:4776 #, c-format msgid "cannot convert NaN to %s" msgstr "no se puede convertir NaN a %s" -#: utils/adt/numeric.c:4370 utils/adt/numeric.c:4450 utils/adt/numeric.c:4491 -#: utils/adt/numeric.c:4687 +#: utils/adt/numeric.c:4436 utils/adt/numeric.c:4524 utils/adt/numeric.c:4584 +#: utils/adt/numeric.c:4780 #, c-format msgid "cannot convert infinity to %s" msgstr "no se puede convertir infinito a %s" -#: utils/adt/numeric.c:4696 +#: utils/adt/numeric.c:4789 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn fuera de rango" -#: utils/adt/numeric.c:7896 utils/adt/numeric.c:7947 +#: utils/adt/numeric.c:7981 utils/adt/numeric.c:8032 #, c-format msgid "numeric field overflow" msgstr "desbordamiento de campo numeric" -#: utils/adt/numeric.c:7897 +#: utils/adt/numeric.c:7982 #, c-format msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d." msgstr "Un campo con precisión %d, escala %d debe redondear a un valor absoluto menor que %s%d." -#: utils/adt/numeric.c:7948 +#: utils/adt/numeric.c:8033 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "Un campo con precisión %d, escala %d no puede contener un valor infinito." -#: utils/adt/oid.c:216 +#: utils/adt/numeric.c:11359 utils/adt/pseudorandomfuncs.c:135 +#: utils/adt/pseudorandomfuncs.c:159 +#, c-format +msgid "lower bound must be less than or equal to upper bound" +msgstr "el límite inferior debe ser menor o igual al límite superior" + +#: utils/adt/oid.c:217 #, c-format msgid "invalid oidvector data" msgstr "datos de oidvector no válidos" @@ -25255,10 +26036,9 @@ msgid "requested character too large" msgstr "el carácter solicitado es demasiado grande" #: utils/adt/oracle_compat.c:1020 -#, fuzzy, c-format -#| msgid "host name must be specified" +#, c-format msgid "character number must be positive" -msgstr "el nombre de servidor debe ser especificado" +msgstr "el número de carácter debe ser positivo" #: utils/adt/oracle_compat.c:1024 #, c-format @@ -25266,322 +26046,326 @@ msgid "null character not permitted" msgstr "el carácter nulo no está permitido" #: utils/adt/oracle_compat.c:1042 utils/adt/oracle_compat.c:1095 -#, fuzzy, c-format -#| msgid "requested character too large" +#, c-format msgid "requested character too large for encoding: %u" -msgstr "el carácter solicitado es demasiado grande" +msgstr "el carácter pedido es demasiado largo para el encoding: %u" #: utils/adt/oracle_compat.c:1083 -#, fuzzy, c-format -#| msgid "requested character too large" +#, c-format msgid "requested character not valid for encoding: %u" -msgstr "el carácter solicitado es demasiado grande" +msgstr "el carácter pedido no es válido para el encoding: %u" -#: utils/adt/orderedsetaggs.c:448 utils/adt/orderedsetaggs.c:553 -#: utils/adt/orderedsetaggs.c:693 +#: utils/adt/orderedsetaggs.c:446 utils/adt/orderedsetaggs.c:551 +#: utils/adt/orderedsetaggs.c:691 #, c-format msgid "percentile value %g is not between 0 and 1" msgstr "el valor de percentil %g no está entre 0 y 1" -#: utils/adt/pg_locale.c:1406 -#, fuzzy, c-format -#| msgid "could not open collator for locale \"%s\": %s" +#: utils/adt/pg_locale.c:326 utils/adt/pg_locale.c:358 +#, c-format +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "el nombre de configuración regional «%s» contiene caracteres no ASCII" + +#: utils/adt/pg_locale.c:1507 +#, c-format msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" -msgstr "no se pudo abrir el «collator» para la configuración regional «%s»: %s" +msgstr "no se pudo abrir el «collator» para la configuración regional «%s» con reglas «%s»: %s" -#: utils/adt/pg_locale.c:1417 utils/adt/pg_locale.c:2847 -#: utils/adt/pg_locale.c:2919 +#: utils/adt/pg_locale.c:1518 utils/adt/pg_locale.c:2992 +#: utils/adt/pg_locale.c:3065 #, c-format msgid "ICU is not supported in this build" msgstr "ICU no está soportado en este servidor" -#: utils/adt/pg_locale.c:1446 +#: utils/adt/pg_locale.c:1546 #, c-format msgid "could not create locale \"%s\": %m" msgstr "no se pudo crear la configuración regional «%s»: %m" -#: utils/adt/pg_locale.c:1449 +#: utils/adt/pg_locale.c:1549 #, c-format msgid "The operating system could not find any locale data for the locale name \"%s\"." msgstr "El sistema operativo no pudo encontrar datos de configuración regional para la configuración «%s»." -#: utils/adt/pg_locale.c:1564 +#: utils/adt/pg_locale.c:1670 #, c-format msgid "collations with different collate and ctype values are not supported on this platform" msgstr "los ordenamientos (collation) con valores collate y ctype diferentes no están soportados en esta plataforma" -#: utils/adt/pg_locale.c:1573 +#: utils/adt/pg_locale.c:1717 #, c-format -msgid "collation provider LIBC is not supported on this platform" -msgstr "el proveedor de ordenamientos LIBC no está soportado en esta plataforma" - -#: utils/adt/pg_locale.c:1614 -#, fuzzy, c-format -#| msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" msgid "collation \"%s\" has no actual version, but a version was recorded" -msgstr "la extensión «%s» no tiene ruta de actualización desde la versión «%s» hasta la versión «%s»" +msgstr "la “collation” «%s» no tiene versión actual, pero una versión fue registrada" -#: utils/adt/pg_locale.c:1620 +#: utils/adt/pg_locale.c:1723 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "el ordenamiento (collation) «%s» tiene una discordancia de versión" -#: utils/adt/pg_locale.c:1622 +#: utils/adt/pg_locale.c:1725 #, c-format msgid "The collation in the database was created using version %s, but the operating system provides version %s." msgstr "El ordenamiento en la base de datos fue creado usando la versión %s, pero el sistema operativo provee la versión %s." -#: utils/adt/pg_locale.c:1625 +#: utils/adt/pg_locale.c:1728 #, c-format msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." msgstr "Reconstruya todos los objetos afectados por este ordenamiento y ejecute ALTER COLLATION %s REFRESH VERSION, o construya PostgreSQL con la versión correcta de la biblioteca." -#: utils/adt/pg_locale.c:1691 +#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:2556 +#: utils/adt/pg_locale.c:2581 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "nombre de configuración regional «%s» no válido para el proveedor builtin" + +#: utils/adt/pg_locale.c:1814 #, c-format msgid "could not load locale \"%s\"" msgstr "no se pudo cargar la configuración regional «%s»" -#: utils/adt/pg_locale.c:1716 +#: utils/adt/pg_locale.c:1839 #, c-format msgid "could not get collation version for locale \"%s\": error code %lu" msgstr "no se pudo obtener la versión de «collation» para la configuración regional «%s»: código de error %lu" -#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:1785 +#: utils/adt/pg_locale.c:1895 utils/adt/pg_locale.c:1908 #, c-format msgid "could not convert string to UTF-16: error code %lu" msgstr "no se pudo convertir la cadena a UTF-16: código de error %lu" -#: utils/adt/pg_locale.c:1799 +#: utils/adt/pg_locale.c:1920 #, c-format msgid "could not compare Unicode strings: %m" msgstr "no se pudieron comparar las cadenas Unicode: %m" -#: utils/adt/pg_locale.c:1980 +#: utils/adt/pg_locale.c:2094 #, c-format msgid "collation failed: %s" msgstr "el ordenamiento falló: %s" -#: utils/adt/pg_locale.c:2201 utils/adt/pg_locale.c:2233 +#: utils/adt/pg_locale.c:2313 utils/adt/pg_locale.c:2345 #, c-format msgid "sort key generation failed: %s" msgstr "la generación de la llave de ordenamiento falló: %s" -#: utils/adt/pg_locale.c:2474 utils/adt/pg_locale.c:2798 +#: utils/adt/pg_locale.c:2635 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "no se pudo el lenguaje de la configuración regional «%s»: %s" -#: utils/adt/pg_locale.c:2495 utils/adt/pg_locale.c:2511 +#: utils/adt/pg_locale.c:2656 utils/adt/pg_locale.c:2672 #, c-format msgid "could not open collator for locale \"%s\": %s" msgstr "no se pudo abrir el «collator» para la configuración regional «%s»: %s" -#: utils/adt/pg_locale.c:2536 +#: utils/adt/pg_locale.c:2697 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "la codificación «%s» no estæ soportada por ICU" -#: utils/adt/pg_locale.c:2543 +#: utils/adt/pg_locale.c:2704 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "no se pudo abrir el conversor ICU para la codificación «%s»: %s" -#: utils/adt/pg_locale.c:2561 utils/adt/pg_locale.c:2580 -#: utils/adt/pg_locale.c:2636 utils/adt/pg_locale.c:2647 +#: utils/adt/pg_locale.c:2722 utils/adt/pg_locale.c:2741 +#: utils/adt/pg_locale.c:2797 utils/adt/pg_locale.c:2808 #, c-format msgid "%s failed: %s" msgstr "%s falló: %s" -#: utils/adt/pg_locale.c:2838 +#: utils/adt/pg_locale.c:2983 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "no se pudo convertir el nombre de configuración regional «%s» a etiqueta de lenguaje: %s" -#: utils/adt/pg_locale.c:2879 -#, fuzzy, c-format -#| msgid "could not get language from locale \"%s\": %s" +#: utils/adt/pg_locale.c:3024 +#, c-format msgid "could not get language from ICU locale \"%s\": %s" -msgstr "no se pudo el lenguaje de la configuración regional «%s»: %s" +msgstr "no se pudo obtener el lenguaje de la configuración regional ICU «%s»: %s" -#: utils/adt/pg_locale.c:2881 utils/adt/pg_locale.c:2910 +#: utils/adt/pg_locale.c:3026 utils/adt/pg_locale.c:3055 #, c-format -msgid "To disable ICU locale validation, set parameter icu_validation_level to DISABLED." -msgstr "" +msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." +msgstr "Par desactivar la validación ICU de configuración regional, defina «%s» a «%s»." -#: utils/adt/pg_locale.c:2908 -#, fuzzy, c-format -#| msgid "locale \"%s\" has unknown language \"%s\"" +#: utils/adt/pg_locale.c:3053 +#, c-format msgid "ICU locale \"%s\" has unknown language \"%s\"" -msgstr "la configuración regional «%s» tiene lenguaje «%s» desconocido" +msgstr "el locale ICU «%s» tiene lenguaje desconocido «%s»" -#: utils/adt/pg_locale.c:3088 +#: utils/adt/pg_locale.c:3204 #, c-format msgid "invalid multibyte character for locale" msgstr "el carácter multibyte no es válido para esta configuración regional" -#: utils/adt/pg_locale.c:3089 +#: utils/adt/pg_locale.c:3205 #, c-format msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding." msgstr "La configuración regional LC_CTYPE del servidor es probablemente incompatible con la codificación de la base de datos." -#: utils/adt/pg_lsn.c:263 +#: utils/adt/pg_lsn.c:262 #, c-format msgid "cannot add NaN to pg_lsn" msgstr "no se puede sumar NaN a bigint" -#: utils/adt/pg_lsn.c:297 +#: utils/adt/pg_lsn.c:296 #, c-format msgid "cannot subtract NaN from pg_lsn" msgstr "no se puede restar NaN de pg_lsn" -#: utils/adt/pg_upgrade_support.c:29 +#: utils/adt/pg_upgrade_support.c:39 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "la función sólo puede invocarse cuando el servidor está en modo de actualización binaria" -#: utils/adt/pgstatfuncs.c:253 +#: utils/adt/pgstatfuncs.c:252 #, c-format msgid "invalid command name: \"%s\"" msgstr "nombre de orden no válido: «%s»" -#: utils/adt/pgstatfuncs.c:1773 +#: utils/adt/pgstatfuncs.c:1739 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "destino de reset no reconocido: «%s»" -#: utils/adt/pgstatfuncs.c:1774 +#: utils/adt/pgstatfuncs.c:1740 #, c-format -msgid "Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or \"wal\"." -msgstr "" +msgid "Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"." +msgstr "El destino debe ser «archiver», «bgwriter», «checkpointer», «io», «recovery_prefetch», «slru» o «wal»." -#: utils/adt/pgstatfuncs.c:1852 -#, fuzzy, c-format -#| msgid "invalid role OID: %u" +#: utils/adt/pgstatfuncs.c:1822 +#, c-format msgid "invalid subscription OID %u" -msgstr "el OID de rol no es válido: %u" +msgstr "OID de suscripción %u no válido" + +#: utils/adt/pseudorandomfuncs.c:69 +#, c-format +msgid "setseed parameter %g is out of allowed range [-1,1]" +msgstr "parámetro setseed %g fuera del rango permitido [-1,1]" -#: utils/adt/pseudotypes.c:58 utils/adt/pseudotypes.c:92 +#: utils/adt/pseudotypes.c:55 utils/adt/pseudotypes.c:89 #, c-format msgid "cannot display a value of type %s" msgstr "no se puede desplegar un valor de tipo %s" -#: utils/adt/pseudotypes.c:310 +#: utils/adt/pseudotypes.c:307 #, c-format msgid "cannot accept a value of a shell type" msgstr "no se puede aceptar un valor de un tipo inconcluso" -#: utils/adt/pseudotypes.c:320 +#: utils/adt/pseudotypes.c:317 #, c-format msgid "cannot display a value of a shell type" msgstr "no se puede desplegar un valor de un tipo inconcluso" -#: utils/adt/rangetypes.c:415 +#: utils/adt/rangetypes.c:422 #, c-format msgid "range constructor flags argument must not be null" msgstr "el argumento de opciones del constructor de rango no debe ser null" -#: utils/adt/rangetypes.c:1014 +#: utils/adt/rangetypes.c:1021 #, c-format msgid "result of range difference would not be contiguous" msgstr "el resultado de la diferencia de rangos no sería contiguo" -#: utils/adt/rangetypes.c:1075 +#: utils/adt/rangetypes.c:1082 #, c-format msgid "result of range union would not be contiguous" msgstr "el resultado de la unión de rangos no sería contiguo" -#: utils/adt/rangetypes.c:1750 +#: utils/adt/rangetypes.c:1757 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "el límite inferior del rango debe ser menor o igual al límite superior del rango" -#: utils/adt/rangetypes.c:2197 utils/adt/rangetypes.c:2210 -#: utils/adt/rangetypes.c:2224 +#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 +#: utils/adt/rangetypes.c:2283 #, c-format msgid "invalid range bound flags" msgstr "opciones de bordes de rango no válidas" -#: utils/adt/rangetypes.c:2198 utils/adt/rangetypes.c:2211 -#: utils/adt/rangetypes.c:2225 +#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 +#: utils/adt/rangetypes.c:2284 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "Los valores aceptables son «[]», «[)», «(]» y «()»." -#: utils/adt/rangetypes.c:2293 utils/adt/rangetypes.c:2310 -#: utils/adt/rangetypes.c:2325 utils/adt/rangetypes.c:2345 -#: utils/adt/rangetypes.c:2356 utils/adt/rangetypes.c:2403 -#: utils/adt/rangetypes.c:2411 +#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 +#: utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 +#: utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "malformed range literal: \"%s\"" msgstr "literal de rango mal formado: «%s»" -#: utils/adt/rangetypes.c:2295 +#: utils/adt/rangetypes.c:2354 #, c-format msgid "Junk after \"empty\" key word." msgstr "Basura a continuación de la palabra «empty»." -#: utils/adt/rangetypes.c:2312 +#: utils/adt/rangetypes.c:2371 #, c-format msgid "Missing left parenthesis or bracket." msgstr "Falta paréntesis o corchete izquierdo." -#: utils/adt/rangetypes.c:2327 +#: utils/adt/rangetypes.c:2386 #, c-format msgid "Missing comma after lower bound." msgstr "Coma faltante después del límite inferior." -#: utils/adt/rangetypes.c:2347 +#: utils/adt/rangetypes.c:2406 #, c-format msgid "Too many commas." msgstr "Demasiadas comas." -#: utils/adt/rangetypes.c:2358 +#: utils/adt/rangetypes.c:2417 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "Basura después del paréntesis o corchete derecho." -#: utils/adt/regexp.c:305 utils/adt/regexp.c:1997 utils/adt/varlena.c:4270 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 #, c-format msgid "regular expression failed: %s" msgstr "la expresión regular falló: %s" -#: utils/adt/regexp.c:446 utils/adt/regexp.c:681 +#: utils/adt/regexp.c:445 utils/adt/regexp.c:680 #, c-format msgid "invalid regular expression option: \"%.*s\"" msgstr "opción de expresión regular no válida: «%.*s»" -#: utils/adt/regexp.c:683 +#: utils/adt/regexp.c:682 #, c-format msgid "If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly." msgstr "Si su intención era usar regexp_replace() con un parámetro de inicio, convierta el cuarto argumento a integer explícitamente." -#: utils/adt/regexp.c:717 utils/adt/regexp.c:726 utils/adt/regexp.c:1083 -#: utils/adt/regexp.c:1147 utils/adt/regexp.c:1156 utils/adt/regexp.c:1165 -#: utils/adt/regexp.c:1174 utils/adt/regexp.c:1854 utils/adt/regexp.c:1863 -#: utils/adt/regexp.c:1872 utils/misc/guc.c:6610 utils/misc/guc.c:6644 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 +#: utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 +#: utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 +#: utils/adt/regexp.c:1871 utils/misc/guc.c:6820 utils/misc/guc.c:6854 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "valor no válido para el parámetro «%s»: %d" -#: utils/adt/regexp.c:937 +#: utils/adt/regexp.c:936 #, c-format msgid "SQL regular expression may not contain more than two escape-double-quote separators" msgstr "la expresión regular SQL no puede contener más de dos separadores escape-comilla doble" #. translator: %s is a SQL function name -#: utils/adt/regexp.c:1094 utils/adt/regexp.c:1185 utils/adt/regexp.c:1272 -#: utils/adt/regexp.c:1311 utils/adt/regexp.c:1699 utils/adt/regexp.c:1754 -#: utils/adt/regexp.c:1883 +#: utils/adt/regexp.c:1093 utils/adt/regexp.c:1184 utils/adt/regexp.c:1271 +#: utils/adt/regexp.c:1310 utils/adt/regexp.c:1698 utils/adt/regexp.c:1753 +#: utils/adt/regexp.c:1882 #, c-format msgid "%s does not support the \"global\" option" msgstr "%s no soporta la opción «global»" -#: utils/adt/regexp.c:1313 +#: utils/adt/regexp.c:1312 #, c-format msgid "Use the regexp_matches function instead." msgstr "En su lugar, utilice la función regexp_matches." -#: utils/adt/regexp.c:1501 +#: utils/adt/regexp.c:1500 #, c-format msgid "too many regular expression matches" msgstr "demasiadas coincidencias de la expresión regular" @@ -25596,18 +26380,18 @@ msgstr "existe más de una función llamada «%s»" msgid "more than one operator named %s" msgstr "existe más de un operador llamado %s" -#: utils/adt/regproc.c:670 gram.y:8844 +#: utils/adt/regproc.c:670 gram.y:8992 #, c-format msgid "missing argument" msgstr "falta un argumento" -#: utils/adt/regproc.c:671 gram.y:8845 +#: utils/adt/regproc.c:671 gram.y:8993 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "Use NONE para denotar el argumento faltante de un operador unario." -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2009 utils/adt/ruleutils.c:10013 -#: utils/adt/ruleutils.c:10226 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10509 +#: utils/adt/ruleutils.c:10722 #, c-format msgid "too many arguments" msgstr "demasiados argumentos" @@ -25617,296 +26401,319 @@ msgstr "demasiados argumentos" msgid "Provide two argument types for operator." msgstr "Provea dos tipos de argumento para un operador." -#: utils/adt/regproc.c:1544 utils/adt/regproc.c:1661 utils/adt/regproc.c:1790 -#: utils/adt/regproc.c:1795 utils/adt/varlena.c:3410 utils/adt/varlena.c:3415 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 +#: utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 #, c-format msgid "invalid name syntax" msgstr "la sintaxis de nombre no es válida" -#: utils/adt/regproc.c:1904 +#: utils/adt/regproc.c:1924 #, c-format msgid "expected a left parenthesis" msgstr "se esperaba un paréntesis izquierdo" -#: utils/adt/regproc.c:1922 +#: utils/adt/regproc.c:1942 #, c-format msgid "expected a right parenthesis" msgstr "se esperaba un paréntesis derecho" -#: utils/adt/regproc.c:1941 +#: utils/adt/regproc.c:1961 #, c-format msgid "expected a type name" msgstr "se esperaba un nombre de tipo" -#: utils/adt/regproc.c:1973 +#: utils/adt/regproc.c:1993 #, c-format msgid "improper type name" msgstr "el nombre de tipo no es válido" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1625 -#: utils/adt/ri_triggers.c:2610 +#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 +#: utils/adt/ri_triggers.c:2601 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "inserción o actualización en la tabla «%s» viola la llave foránea «%s»" -#: utils/adt/ri_triggers.c:309 utils/adt/ri_triggers.c:1628 +#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MATCH FULL no permite la mezcla de valores de clave nulos y no nulos." -#: utils/adt/ri_triggers.c:2045 +#: utils/adt/ri_triggers.c:2036 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "la función «%s» debe ser ejecutada en INSERT" -#: utils/adt/ri_triggers.c:2051 +#: utils/adt/ri_triggers.c:2042 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "la función «%s» debe ser ejecutada en UPDATE" -#: utils/adt/ri_triggers.c:2057 +#: utils/adt/ri_triggers.c:2048 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "la función «%s» debe ser ejecutada en DELETE" -#: utils/adt/ri_triggers.c:2080 +#: utils/adt/ri_triggers.c:2071 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "no hay una entrada en pg_constraint para el trigger «%s» en tabla «%s»" -#: utils/adt/ri_triggers.c:2082 +#: utils/adt/ri_triggers.c:2073 #, c-format msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT." msgstr "Elimine este trigger de integridad referencial y sus pares, y utilice ALTER TABLE ADD CONSTRAINT." -#: utils/adt/ri_triggers.c:2112 gram.y:4226 +#: utils/adt/ri_triggers.c:2103 gram.y:4340 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "MATCH PARTIAL no está implementada" -#: utils/adt/ri_triggers.c:2435 +#: utils/adt/ri_triggers.c:2426 #, c-format msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result" msgstr "la consulta de integridad referencial en «%s» de la restricción «%s» en «%s» entregó un resultado inesperado" -#: utils/adt/ri_triggers.c:2439 +#: utils/adt/ri_triggers.c:2430 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "Esto probablemente es causado por una regla que reescribió la consulta." -#: utils/adt/ri_triggers.c:2600 +#: utils/adt/ri_triggers.c:2591 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "eliminar la partición «%s» viola la llave foránea «%s»" -#: utils/adt/ri_triggers.c:2603 utils/adt/ri_triggers.c:2628 +#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "La llave (%s)=(%s) todavía es referida desde la tabla «%s»." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2605 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "La llave (%s)=(%s) no está presente en la tabla «%s»." -#: utils/adt/ri_triggers.c:2617 +#: utils/adt/ri_triggers.c:2608 #, c-format msgid "Key is not present in table \"%s\"." msgstr "La llave no está presente en la tabla «%s»." -#: utils/adt/ri_triggers.c:2623 +#: utils/adt/ri_triggers.c:2614 #, c-format msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"" msgstr "update o delete en «%s» viola la llave foránea «%s» en la tabla «%s»" -#: utils/adt/ri_triggers.c:2631 +#: utils/adt/ri_triggers.c:2622 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "La llave todavía es referida desde la tabla «%s»." -#: utils/adt/rowtypes.c:106 utils/adt/rowtypes.c:510 +#: utils/adt/rowtypes.c:105 utils/adt/rowtypes.c:509 #, c-format msgid "input of anonymous composite types is not implemented" msgstr "el ingreso de tipos compuestos anónimos no está implementado" -#: utils/adt/rowtypes.c:159 utils/adt/rowtypes.c:191 utils/adt/rowtypes.c:217 -#: utils/adt/rowtypes.c:228 utils/adt/rowtypes.c:286 utils/adt/rowtypes.c:297 +#: utils/adt/rowtypes.c:158 utils/adt/rowtypes.c:190 utils/adt/rowtypes.c:216 +#: utils/adt/rowtypes.c:227 utils/adt/rowtypes.c:285 utils/adt/rowtypes.c:296 #, c-format msgid "malformed record literal: \"%s\"" msgstr "literal de record mal formado: «%s»" -#: utils/adt/rowtypes.c:160 +#: utils/adt/rowtypes.c:159 #, c-format msgid "Missing left parenthesis." msgstr "Falta paréntesis izquierdo." -#: utils/adt/rowtypes.c:192 +#: utils/adt/rowtypes.c:191 #, c-format msgid "Too few columns." msgstr "Muy pocas columnas." -#: utils/adt/rowtypes.c:287 +#: utils/adt/rowtypes.c:286 #, c-format msgid "Too many columns." msgstr "Demasiadas columnas." -#: utils/adt/rowtypes.c:298 +#: utils/adt/rowtypes.c:297 #, c-format msgid "Junk after right parenthesis." msgstr "Basura después del paréntesis derecho." -#: utils/adt/rowtypes.c:559 +#: utils/adt/rowtypes.c:558 #, c-format msgid "wrong number of columns: %d, expected %d" msgstr "número de columnas erróneo: %d, se esperaban %d" -#: utils/adt/rowtypes.c:601 +#: utils/adt/rowtypes.c:599 #, c-format msgid "binary data has type %u (%s) instead of expected %u (%s) in record column %d" msgstr "los datos binarios tienen tipo %u (%s) en lugar del esperado %u (%s) en columna de registro %d" -#: utils/adt/rowtypes.c:668 +#: utils/adt/rowtypes.c:660 #, c-format msgid "improper binary format in record column %d" msgstr "formato binario incorrecto en la columna record %d" -#: utils/adt/rowtypes.c:959 utils/adt/rowtypes.c:1205 utils/adt/rowtypes.c:1463 -#: utils/adt/rowtypes.c:1709 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 +#: utils/adt/rowtypes.c:1699 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "no se pueden comparar los tipos de columnas disímiles %s y %s en la columna %d" -#: utils/adt/rowtypes.c:1050 utils/adt/rowtypes.c:1275 -#: utils/adt/rowtypes.c:1560 utils/adt/rowtypes.c:1745 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 +#: utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "no se pueden comparar registros con cantidad distinta de columnas" #: utils/adt/ruleutils.c:2694 -#, fuzzy, c-format -#| msgid "cannot use subquery in index expression" +#, c-format msgid "input is a query, not an expression" -msgstr "no se puede usar una subconsulta en una expresión de índice" +msgstr "la entrada es una consulta, no una expresión" #: utils/adt/ruleutils.c:2706 -#, fuzzy, c-format -#| msgid "USING expression contains a whole-row table reference." +#, c-format msgid "expression contains variables of more than one relation" -msgstr "La expresión USING contiene una referencia a la fila completa (whole-row)." +msgstr "la expresión contiene variables de más de una relación" #: utils/adt/ruleutils.c:2713 -#, fuzzy, c-format -#| msgid "argument of %s must not contain variables" +#, c-format msgid "expression contains variables" -msgstr "el argumento de %s no puede contener variables" +msgstr "la expresión contiene variables" -#: utils/adt/ruleutils.c:5227 +#: utils/adt/ruleutils.c:5246 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "la regla «%s» tiene el tipo de evento no soportado %d" -#: utils/adt/timestamp.c:112 +#: utils/adt/timestamp.c:128 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "la precisión de TIMESTAMP(%d)%s no debe ser negativa" -#: utils/adt/timestamp.c:118 +#: utils/adt/timestamp.c:134 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "la precisión de TIMESTAMP(%d)%s fue reducida al máximo permitido, %d" -#: utils/adt/timestamp.c:378 +#: utils/adt/timestamp.c:394 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "la precisión de timestamp(%d) debe estar entre %d y %d" -#: utils/adt/timestamp.c:496 +#: utils/adt/timestamp.c:512 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "Los husos horarios numéricos deben tener «-» o «+» como su primer carácter." -#: utils/adt/timestamp.c:508 +#: utils/adt/timestamp.c:524 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "huso horario numérico «%s» fuera de rango" -#: utils/adt/timestamp.c:609 utils/adt/timestamp.c:619 -#: utils/adt/timestamp.c:627 +#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 +#: utils/adt/timestamp.c:643 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "timestamp fuera de rango: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:728 +#: utils/adt/timestamp.c:744 #, c-format msgid "timestamp cannot be NaN" msgstr "el timestamp no puede ser NaN" -#: utils/adt/timestamp.c:746 utils/adt/timestamp.c:758 +#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "timestamp fuera de rango: «%g»" -#: utils/adt/timestamp.c:1065 utils/adt/timestamp.c:1098 +#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 +#: utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 +#: utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 +#: utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 +#: utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 +#: utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 +#: utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 +#: utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 +#: utils/adt/timestamp.c:3537 utils/adt/timestamp.c:3546 +#: utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 +#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 +#: utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 +#: utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 +#: utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 +#: utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 +#: utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 +#: utils/adt/timestamp.c:5097 +#, c-format +msgid "interval out of range" +msgstr "interval fuera de rango" + +#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 #, c-format msgid "invalid INTERVAL type modifier" msgstr "modificador de tipo INTERVAL no válido" -#: utils/adt/timestamp.c:1081 +#: utils/adt/timestamp.c:1110 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "la precisión de INTERVAL(%d) no debe ser negativa" -#: utils/adt/timestamp.c:1087 +#: utils/adt/timestamp.c:1116 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "la precisión de INTERVAL(%d) fue reducida al máximo permitido, %d" -#: utils/adt/timestamp.c:1473 +#: utils/adt/timestamp.c:1506 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "la precisión de interval(%d) debe estar entre %d y %d" -#: utils/adt/timestamp.c:2703 -#, c-format -msgid "cannot subtract infinite timestamps" -msgstr "no se pueden restar timestamps infinitos" - -#: utils/adt/timestamp.c:3956 utils/adt/timestamp.c:4139 +#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 #, c-format msgid "origin out of range" msgstr "origen fuera de rango" -#: utils/adt/timestamp.c:3961 utils/adt/timestamp.c:4144 +#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#, c-format +msgid "timestamps cannot be binned into infinite intervals" +msgstr "no se puede aproximar (bin) timestamps hacia intervalos infinitos" + +#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "no se puede aproximar (bin) timestamps hacia intervalos que contengan meses o años" -#: utils/adt/timestamp.c:3968 utils/adt/timestamp.c:4151 +#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 #, c-format msgid "stride must be greater than zero" msgstr "el intervalo de paso (stride) debe ser mayor que cero" -#: utils/adt/timestamp.c:4434 +#: utils/adt/timestamp.c:5091 #, c-format msgid "Months usually have fractional weeks." -msgstr "" +msgstr "Los meses usualmente tienen semanas fraccionales." + +#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#, c-format +msgid "step size cannot be infinite" +msgstr "el tamaño de paso no puede ser infinito" -#: utils/adt/trigfuncs.c:42 +#: utils/adt/trigfuncs.c:41 #, c-format msgid "suppress_redundant_updates_trigger: must be called as trigger" msgstr "suppress_redundant_updates_trigger: debe ser invocado como trigger" -#: utils/adt/trigfuncs.c:48 +#: utils/adt/trigfuncs.c:47 #, c-format msgid "suppress_redundant_updates_trigger: must be called on update" msgstr "suppress_redundant_updates_trigger: debe ser invocado en «UPDATE»" -#: utils/adt/trigfuncs.c:54 +#: utils/adt/trigfuncs.c:53 #, c-format msgid "suppress_redundant_updates_trigger: must be called before update" msgstr "suppress_redundant_updates_trigger: debe ser invocado «BEFORE UPDATE»" -#: utils/adt/trigfuncs.c:60 +#: utils/adt/trigfuncs.c:59 #, c-format msgid "suppress_redundant_updates_trigger: must be called for each row" msgstr "suppress_redundant_updates_trigger: debe ser invocado «FOR EACH ROW»" @@ -25921,32 +26728,32 @@ msgstr "distancia en operador de frases debe ser un valor entero entre zero y %d msgid "no operand in tsquery: \"%s\"" msgstr "no hay operando en tsquery: «%s»" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "el valor es demasiado grande en tsquery: «%s»" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "el operando es muy largo en tsquery: «%s»" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "palabra demasiado larga en tsquery: «%s»" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "error de sintaxis en tsquery: «%s»" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "la consulta de búsqueda en texto no contiene lexemas: «%s»" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "el tsquery es demasiado grande" @@ -25981,73 +26788,72 @@ msgstr "los arrays de pesos no deben contener valores nulos" msgid "weight out of range" msgstr "peso fuera de rango" -#: utils/adt/tsvector.c:217 +#: utils/adt/tsvector.c:216 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "la palabra es demasiado larga (%ld, máximo %ld bytes)" -#: utils/adt/tsvector.c:224 +#: utils/adt/tsvector.c:223 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "la cadena es demasiado larga para tsvector (%ld bytes, máximo %ld bytes)" -#: utils/adt/tsvector_op.c:773 +#: utils/adt/tsvector_op.c:771 #, c-format msgid "lexeme array may not contain nulls" msgstr "el array de lexemas no debe contener nulls" -#: utils/adt/tsvector_op.c:778 -#, fuzzy, c-format -#| msgid "lexeme array may not contain nulls" +#: utils/adt/tsvector_op.c:776 +#, c-format msgid "lexeme array may not contain empty strings" -msgstr "el array de lexemas no debe contener nulls" +msgstr "el array de lexemas no debe contener cadenas vacías" -#: utils/adt/tsvector_op.c:847 +#: utils/adt/tsvector_op.c:845 #, c-format msgid "weight array may not contain nulls" msgstr "el array de pesos no debe contener nulls" -#: utils/adt/tsvector_op.c:871 +#: utils/adt/tsvector_op.c:869 #, c-format msgid "unrecognized weight: \"%c\"" msgstr "no se reconoce el peso: «%c»" -#: utils/adt/tsvector_op.c:2601 +#: utils/adt/tsvector_op.c:2599 #, c-format msgid "ts_stat query must return one tsvector column" msgstr "la consulta ts_stat debe retornar una columna tsvector" -#: utils/adt/tsvector_op.c:2790 +#: utils/adt/tsvector_op.c:2788 #, c-format msgid "tsvector column \"%s\" does not exist" msgstr "la columna tsvector «%s» no existe" -#: utils/adt/tsvector_op.c:2797 +#: utils/adt/tsvector_op.c:2795 #, c-format msgid "column \"%s\" is not of tsvector type" msgstr "la columna «%s» no es de tipo tsvector" -#: utils/adt/tsvector_op.c:2809 +#: utils/adt/tsvector_op.c:2807 #, c-format msgid "configuration column \"%s\" does not exist" msgstr "la columna de configuración «%s» no existe" -#: utils/adt/tsvector_op.c:2815 +#: utils/adt/tsvector_op.c:2813 #, c-format msgid "column \"%s\" is not of regconfig type" msgstr "la columna «%s» no es de tipo regconfig" -#: utils/adt/tsvector_op.c:2822 +#: utils/adt/tsvector_op.c:2820 #, c-format msgid "configuration column \"%s\" must not be null" msgstr "la columna de configuración «%s» no debe ser nula" -#: utils/adt/tsvector_op.c:2835 +#: utils/adt/tsvector_op.c:2833 #, c-format msgid "text search configuration name \"%s\" must be schema-qualified" msgstr "el nombre de la configuración de búsqueda «%s» debe ser calificada con esquema" -#: utils/adt/tsvector_op.c:2860 +#: utils/adt/tsvector_op.c:2858 #, c-format msgid "column \"%s\" is not of a character type" msgstr "la columna «%s» no es de un tipo textual" @@ -26067,17 +26873,17 @@ msgstr "no hay carácter escapado: «%s»" msgid "wrong position info in tsvector: \"%s\"" msgstr "información posicional incorrecta en tsvector: «%s»" -#: utils/adt/uuid.c:413 +#: utils/adt/uuid.c:418 #, c-format msgid "could not generate random values" msgstr "no se pudo generar valores aleatorios" -#: utils/adt/varbit.c:110 utils/adt/varchar.c:54 +#: utils/adt/varbit.c:110 utils/adt/varchar.c:53 #, c-format msgid "length for type %s must be at least 1" msgstr "el largo para el tipo %s debe ser al menos 1" -#: utils/adt/varbit.c:115 utils/adt/varchar.c:58 +#: utils/adt/varbit.c:115 utils/adt/varchar.c:57 #, c-format msgid "length for type %s cannot exceed %d" msgstr "el largo del tipo %s no puede exceder %d" @@ -26112,9 +26918,9 @@ msgstr "el largo no es válido en cadena de bits externa" msgid "bit string too long for type bit varying(%d)" msgstr "la cadena de bits es demasiado larga para el tipo bit varying(%d)" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:908 -#: utils/adt/varlena.c:971 utils/adt/varlena.c:1128 utils/adt/varlena.c:3052 -#: utils/adt/varlena.c:3130 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 +#: utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 +#: utils/adt/varlena.c:3133 #, c-format msgid "negative substring length not allowed" msgstr "no se permite un largo negativo de subcadena" @@ -26139,334 +26945,342 @@ msgstr "no se puede hacer XOR entre cadenas de bits de distintos tamaños" msgid "bit index %d out of valid range (0..%d)" msgstr "el índice de bit %d está fuera del rango válido (0..%d)" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3334 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 #, c-format msgid "new bit must be 0 or 1" msgstr "el nuevo bit debe ser 0 o 1" -#: utils/adt/varchar.c:162 utils/adt/varchar.c:313 +#: utils/adt/varchar.c:161 utils/adt/varchar.c:312 #, c-format msgid "value too long for type character(%d)" msgstr "el valor es demasiado largo para el tipo character(%d)" -#: utils/adt/varchar.c:476 utils/adt/varchar.c:640 +#: utils/adt/varchar.c:475 utils/adt/varchar.c:639 #, c-format msgid "value too long for type character varying(%d)" msgstr "el valor es demasiado largo para el tipo character varying(%d)" -#: utils/adt/varchar.c:738 utils/adt/varlena.c:1517 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "no se pudo determinar qué ordenamiento usar para la comparación de cadenas" -#: utils/adt/varlena.c:1227 utils/adt/varlena.c:1806 +#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "los ordenamientos no determinísticos no están soportados para búsquedas de sub-cadenas" -#: utils/adt/varlena.c:3218 utils/adt/varlena.c:3285 +#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "el índice %d está fuera de rango [0..%d]" -#: utils/adt/varlena.c:3249 utils/adt/varlena.c:3321 +#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 #, c-format msgid "index %lld out of valid range, 0..%lld" msgstr "el índice %lld está fuera de rango, 0..%lld" -#: utils/adt/varlena.c:4382 +#: utils/adt/varlena.c:4385 #, c-format msgid "field position must not be zero" msgstr "la posición del campo no debe ser cero" -#: utils/adt/varlena.c:5554 +#: utils/adt/varlena.c:5630 #, c-format msgid "unterminated format() type specifier" msgstr "especificador de tipo inconcluso en format()" -#: utils/adt/varlena.c:5555 utils/adt/varlena.c:5689 utils/adt/varlena.c:5810 +#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "Para un «%%» solo, use «%%%%»." -#: utils/adt/varlena.c:5687 utils/adt/varlena.c:5808 +#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "especificador de tipo no reconocido «%.*s» en format()" -#: utils/adt/varlena.c:5700 utils/adt/varlena.c:5757 +#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 #, c-format msgid "too few arguments for format()" msgstr "muy pocos argumentos para format()" -#: utils/adt/varlena.c:5853 utils/adt/varlena.c:6035 +#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 #, c-format msgid "number is out of range" msgstr "el número está fuera de rango" -#: utils/adt/varlena.c:5916 utils/adt/varlena.c:5944 +#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "la conversión especifica el argumento 0, pero los argumentos se numeran desde 1" -#: utils/adt/varlena.c:5937 +#: utils/adt/varlena.c:6013 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "la posición del argumento de anchura debe terminar con «$»" -#: utils/adt/varlena.c:5982 +#: utils/adt/varlena.c:6058 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "los valores nulos no pueden ser formateados como un identificador SQL" -#: utils/adt/varlena.c:6190 +#: utils/adt/varlena.c:6266 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "la normalización Unicode sólo puede ser hecha si la codificación de servidor es UTF8" -#: utils/adt/varlena.c:6203 +#: utils/adt/varlena.c:6279 #, c-format msgid "invalid normalization form: %s" msgstr "forma de normalización no válida: %s" -#: utils/adt/varlena.c:6406 utils/adt/varlena.c:6441 utils/adt/varlena.c:6476 +#: utils/adt/varlena.c:6324 +#, c-format +msgid "Unicode categorization can only be performed if server encoding is UTF8" +msgstr "la categorización Unicode sólo puede ser hecha si la codificación de servidor es UTF8" + +#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 #, c-format msgid "invalid Unicode code point: %04X" msgstr "punto de código Unicode no válido: %04X" -#: utils/adt/varlena.c:6506 +#: utils/adt/varlena.c:6641 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "Los escapes Unicode deben ser \\XXXX, \\+XXXXXX, \\uXXXX o \\UXXXXXXXX." -#: utils/adt/windowfuncs.c:442 +#: utils/adt/windowfuncs.c:443 #, c-format msgid "argument of ntile must be greater than zero" msgstr "el argumento de ntile debe ser mayor que cero" -#: utils/adt/windowfuncs.c:706 +#: utils/adt/windowfuncs.c:707 #, c-format msgid "argument of nth_value must be greater than zero" msgstr "el argumento de nth_value debe ser mayor que cero" -#: utils/adt/xid8funcs.c:125 +#: utils/adt/xid8funcs.c:120 #, c-format msgid "transaction ID %llu is in the future" -msgstr "" +msgstr "el ID de transacción %llu está en el futuro" -#: utils/adt/xid8funcs.c:547 +#: utils/adt/xid8funcs.c:522 #, c-format msgid "invalid external pg_snapshot data" msgstr "datos externos pg_snapshot no válidos" -#: utils/adt/xml.c:228 +#: utils/adt/xml.c:238 #, c-format msgid "unsupported XML feature" msgstr "característica XML no soportada" -#: utils/adt/xml.c:229 +#: utils/adt/xml.c:239 #, c-format msgid "This functionality requires the server to be built with libxml support." msgstr "Esta funcionalidad requiere que el servidor haya sido construido con soporte libxml." -#: utils/adt/xml.c:248 utils/mb/mbutils.c:628 +#: utils/adt/xml.c:258 utils/mb/mbutils.c:627 #, c-format msgid "invalid encoding name \"%s\"" msgstr "nombre de codificación «%s» no válido" -#: utils/adt/xml.c:496 utils/adt/xml.c:501 +#: utils/adt/xml.c:506 utils/adt/xml.c:511 #, c-format msgid "invalid XML comment" msgstr "comentario XML no válido" -#: utils/adt/xml.c:660 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "no es un documento XML" -#: utils/adt/xml.c:956 utils/adt/xml.c:979 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "instrucción de procesamiento XML no válida" -#: utils/adt/xml.c:957 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "el nombre de destino de la instrucción de procesamiento XML no puede ser «%s»." -#: utils/adt/xml.c:980 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "la instrucción de procesamiento XML no puede contener «?>»." -#: utils/adt/xml.c:1059 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "xmlvalidate no está implementado" -#: utils/adt/xml.c:1115 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "no se pudo inicializar la biblioteca XML" -#: utils/adt/xml.c:1116 +#: utils/adt/xml.c:1168 #, c-format msgid "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." -msgstr "" +msgstr "libxml2 tiene un tipo char incompatible: sizeof(char)=%zu, sizeof(xmlChar)=%zu." -#: utils/adt/xml.c:1202 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "no se pudo instalar un gestor de errores XML" -#: utils/adt/xml.c:1203 +#: utils/adt/xml.c:1255 #, c-format msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with." msgstr "Esto probablemente indica que la versión de libxml2 en uso no es compatible con los archivos de cabecera libxml2 con los que PostgreSQL fue construido." -#: utils/adt/xml.c:2189 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "Valor de carácter no válido." -#: utils/adt/xml.c:2192 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "Se requiere un espacio." -#: utils/adt/xml.c:2195 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "standalone acepta sólo 'yes' y 'no'." -#: utils/adt/xml.c:2198 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "Declaración mal formada: falta la versión." -#: utils/adt/xml.c:2201 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "Falta especificación de codificación en declaración de texto." -#: utils/adt/xml.c:2204 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "Procesando declaración XML: se esperaba '?>'." -#: utils/adt/xml.c:2207 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "Código de error libxml no reconocido: %d." -#: utils/adt/xml.c:2461 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML no soporta valores infinitos de fecha." -#: utils/adt/xml.c:2483 utils/adt/xml.c:2510 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML no soporta valores infinitos de timestamp." -#: utils/adt/xml.c:2926 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "consulta no válido" -#: utils/adt/xml.c:4266 +#: utils/adt/xml.c:3110 +#, c-format +msgid "portal \"%s\" does not return tuples" +msgstr "el portal «%s» no retorna tuplas" + +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "array no válido para mapeo de espacio de nombres XML" -#: utils/adt/xml.c:4267 +#: utils/adt/xml.c:4363 #, c-format msgid "The array must be two-dimensional with length of the second axis equal to 2." msgstr "El array debe ser bidimensional y el largo del segundo eje igual a 2." -#: utils/adt/xml.c:4291 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "expresion XPath vacía" -#: utils/adt/xml.c:4343 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "ni el espacio de nombres ni la URI pueden ser vacíos" -#: utils/adt/xml.c:4350 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "no se pudo registrar un espacio de nombres XML llamado «%s» con URI «%s»" -#: utils/adt/xml.c:4693 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "el espacio de nombres DEFAULT no está soportado" -#: utils/adt/xml.c:4722 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "el «path» de filtro de registros no debe ser la cadena vacía" -#: utils/adt/xml.c:4753 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "el «path» de filtro de columna no debe ser la cadena vacía" -#: utils/adt/xml.c:4897 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "la expresión XPath de columna retornó más de un valor" -#: utils/cache/lsyscache.c:1043 +#: utils/cache/lsyscache.c:1017 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "no existe la conversión del tipo %s al tipo %s" -#: utils/cache/lsyscache.c:2845 utils/cache/lsyscache.c:2878 -#: utils/cache/lsyscache.c:2911 utils/cache/lsyscache.c:2944 +#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 +#: utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 #, c-format msgid "type %s is only a shell" msgstr "el tipo %s está inconcluso" -#: utils/cache/lsyscache.c:2850 +#: utils/cache/lsyscache.c:2892 #, c-format msgid "no input function available for type %s" msgstr "no hay una función de entrada para el tipo %s" -#: utils/cache/lsyscache.c:2883 +#: utils/cache/lsyscache.c:2925 #, c-format msgid "no output function available for type %s" msgstr "no hay una función de salida para el tipo %s" -#: utils/cache/partcache.c:219 +#: utils/cache/partcache.c:216 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d for type %s" msgstr "falta la función de soporte %3$d para el tipo %4$s de la clase de operadores «%1$s» del método de acceso %2$s" -#: utils/cache/plancache.c:720 +#: utils/cache/plancache.c:747 #, c-format msgid "cached plan must not change result type" msgstr "el plan almacenado no debe cambiar el tipo de resultado" -#: utils/cache/relcache.c:3740 -#, fuzzy, c-format -#| msgid "pg_enum OID value not set when in binary upgrade mode" +#: utils/cache/relcache.c:3801 +#, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" -msgstr "el valor de OID de pg_enum no se definió en modo de actualización binaria" +msgstr "el valor de relfilenumber de heap no se definió en modo de actualización binaria" -#: utils/cache/relcache.c:3748 -#, fuzzy, c-format -#| msgid "must be superuser to connect in binary upgrade mode" +#: utils/cache/relcache.c:3809 +#, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" -msgstr "debe ser superusuario para conectarse en modo de actualización binaria" +msgstr "petición inesperada de un nuevo relfilenode en modo de actualización binaria" -#: utils/cache/relcache.c:6488 +#: utils/cache/relcache.c:6539 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "no se pudo crear el archivo de cache de catálogos de sistema «%s»: %m" -#: utils/cache/relcache.c:6490 +#: utils/cache/relcache.c:6541 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "Prosiguiendo de todas maneras, pero hay algo mal." -#: utils/cache/relcache.c:6812 +#: utils/cache/relcache.c:6871 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "no se pudo eliminar el archivo de cache «%s»: %m" @@ -26476,17 +27290,17 @@ msgstr "no se pudo eliminar el archivo de cache «%s»: %m" msgid "cannot PREPARE a transaction that modified relation mapping" msgstr "no se puede hacer PREPARE de una transacción que ha modificado el mapeo de relaciones" -#: utils/cache/relmapper.c:850 +#: utils/cache/relmapper.c:852 #, c-format msgid "relation mapping file \"%s\" contains invalid data" msgstr "el archivo de mapeo de relaciones «%s» contiene datos no válidos" -#: utils/cache/relmapper.c:860 +#: utils/cache/relmapper.c:862 #, c-format msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "el archivo de mapeo de relaciones «%s» tiene una suma de verificación incorrecta" -#: utils/cache/typcache.c:1803 utils/fmgr/funcapi.c:566 +#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "el tipo record no ha sido registrado" @@ -26499,104 +27313,104 @@ msgstr "TRAP: ExceptionalCondition: argumentos erróneos en PID %d\n" #: utils/error/assert.c:40 #, c-format msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" -msgstr "" +msgstr "TRAP: falló Assert(«%s»), Archivo «%s», Línea %d, PID %d\n" -#: utils/error/elog.c:416 +#: utils/error/elog.c:415 #, c-format msgid "error occurred before error message processing is available\n" msgstr "ocurrió un error antes de que el procesamiento de errores esté disponible\n" -#: utils/error/elog.c:2092 +#: utils/error/elog.c:2134 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "no se pudo reabrir «%s» para error estándar: %m" -#: utils/error/elog.c:2105 +#: utils/error/elog.c:2147 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "no se pudo reabrir «%s» para usar como salida estándar: %m" -#: utils/error/elog.c:2141 +#: utils/error/elog.c:2183 #, c-format -msgid "invalid character" -msgstr "carácter no válido" +msgid "Invalid character" +msgstr "Carácter no válido" -#: utils/error/elog.c:2847 utils/error/elog.c:2874 utils/error/elog.c:2890 +#: utils/error/elog.c:2889 utils/error/elog.c:2916 utils/error/elog.c:2932 msgid "[unknown]" msgstr "[desconocido]" -#: utils/error/elog.c:3163 utils/error/elog.c:3484 utils/error/elog.c:3591 +#: utils/error/elog.c:3202 utils/error/elog.c:3526 utils/error/elog.c:3633 msgid "missing error text" msgstr "falta un texto de mensaje de error" -#: utils/error/elog.c:3166 utils/error/elog.c:3169 +#: utils/error/elog.c:3205 utils/error/elog.c:3208 #, c-format msgid " at character %d" msgstr " en carácter %d" -#: utils/error/elog.c:3179 utils/error/elog.c:3186 +#: utils/error/elog.c:3218 utils/error/elog.c:3225 msgid "DETAIL: " msgstr "DETALLE: " -#: utils/error/elog.c:3193 +#: utils/error/elog.c:3232 msgid "HINT: " msgstr "HINT: " -#: utils/error/elog.c:3200 +#: utils/error/elog.c:3239 msgid "QUERY: " msgstr "CONSULTA: " -#: utils/error/elog.c:3207 +#: utils/error/elog.c:3246 msgid "CONTEXT: " msgstr "CONTEXTO: " -#: utils/error/elog.c:3217 +#: utils/error/elog.c:3256 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "UBICACIÓN: %s, %s:%d\n" -#: utils/error/elog.c:3224 +#: utils/error/elog.c:3263 #, c-format msgid "LOCATION: %s:%d\n" msgstr "UBICACIÓN: %s:%d\n" -#: utils/error/elog.c:3231 +#: utils/error/elog.c:3270 msgid "BACKTRACE: " msgstr "BACKTRACE: " -#: utils/error/elog.c:3243 +#: utils/error/elog.c:3282 msgid "STATEMENT: " msgstr "SENTENCIA: " -#: utils/error/elog.c:3636 +#: utils/error/elog.c:3678 msgid "DEBUG" msgstr "DEBUG" -#: utils/error/elog.c:3640 +#: utils/error/elog.c:3682 msgid "LOG" msgstr "LOG" -#: utils/error/elog.c:3643 +#: utils/error/elog.c:3685 msgid "INFO" msgstr "INFO" -#: utils/error/elog.c:3646 +#: utils/error/elog.c:3688 msgid "NOTICE" msgstr "NOTICE" -#: utils/error/elog.c:3650 +#: utils/error/elog.c:3692 msgid "WARNING" msgstr "WARNING" -#: utils/error/elog.c:3653 +#: utils/error/elog.c:3695 msgid "ERROR" msgstr "ERROR" -#: utils/error/elog.c:3656 +#: utils/error/elog.c:3698 msgid "FATAL" msgstr "FATAL" -#: utils/error/elog.c:3659 +#: utils/error/elog.c:3701 msgid "PANIC" msgstr "PANIC" @@ -26631,16 +27445,14 @@ msgid "Server is version %d, library is version %s." msgstr "Versión del servidor %d, versión de biblioteca %s." #: utils/fmgr/dfmgr.c:341 -#, fuzzy, c-format -#| msgid "incompatible library \"%s\": version mismatch" +#, c-format msgid "incompatible library \"%s\": ABI mismatch" -msgstr "biblioteca «%s» incompatible: versión no coincide" +msgstr "biblioteca «%s» incompatible: ABI no coincide" #: utils/fmgr/dfmgr.c:343 -#, fuzzy, c-format -#| msgid "Server has FLOAT8PASSBYVAL = %s, library has %s." +#, c-format msgid "Server has ABI \"%s\", library has \"%s\"." -msgstr "El servidor tiene FLOAT8PASSBYVAL = %s, la librería tiene %s" +msgstr "El servidor tiene ABI «%s», la librería tiene «%s»." #: utils/fmgr/dfmgr.c:361 #, c-format @@ -26671,22 +27483,22 @@ msgstr "El bloque mágico tiene un largo inesperado, o una diferencia de relleno msgid "incompatible library \"%s\": magic block mismatch" msgstr "biblioteca «%s» incompatible: bloque mágico no coincide" -#: utils/fmgr/dfmgr.c:492 +#: utils/fmgr/dfmgr.c:475 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "no está permitido el acceso a la biblioteca «%s»" -#: utils/fmgr/dfmgr.c:518 +#: utils/fmgr/dfmgr.c:501 #, c-format msgid "invalid macro name in dynamic library path: %s" msgstr "el nombre de macro no es válido en la ruta a biblioteca dinámica: %s" -#: utils/fmgr/dfmgr.c:558 +#: utils/fmgr/dfmgr.c:541 #, c-format msgid "zero-length component in parameter \"dynamic_library_path\"" msgstr "se encontró componente de largo cero en el parámetro «dynamic_library_path»" -#: utils/fmgr/dfmgr.c:577 +#: utils/fmgr/dfmgr.c:560 #, c-format msgid "component in parameter \"dynamic_library_path\" is not an absolute path" msgstr "un componente en el parámetro «dynamic_library_path» no es una ruta absoluta" @@ -26711,223 +27523,213 @@ msgstr "Funciones invocables desde SQL necesitan PG_FUNCTION_INFO_V1(función) q msgid "unrecognized API version %d reported by info function \"%s\"" msgstr "la versión de API %d no reconocida fue reportada por la función «%s»" -#: utils/fmgr/fmgr.c:2080 +#: utils/fmgr/fmgr.c:2109 #, c-format msgid "operator class options info is absent in function call context" msgstr "la información de opciones de la clase de operadores está ausente en el contexto de llamada a función" -#: utils/fmgr/fmgr.c:2147 +#: utils/fmgr/fmgr.c:2176 #, c-format msgid "language validation function %u called for language %u instead of %u" msgstr "función de validación de lenguaje %u invocada para el lenguaje %u en lugar de %u" -#: utils/fmgr/funcapi.c:489 +#: utils/fmgr/funcapi.c:496 #, c-format msgid "could not determine actual result type for function \"%s\" declared to return type %s" msgstr "no se pudo determinar el tipo verdadero de resultado para la función «%s» declarada retornando tipo %s" -#: utils/fmgr/funcapi.c:634 +#: utils/fmgr/funcapi.c:642 #, c-format msgid "argument declared %s does not contain a range type but type %s" msgstr "el argumento declarado %s no contiene un tipo de rango sino tipo %s" -#: utils/fmgr/funcapi.c:717 -#, c-format -msgid "could not find multirange type for data type %s" -msgstr "no se pudo encontrar un tipo de multirango para el tipo de dato %s" - -#: utils/fmgr/funcapi.c:1921 utils/fmgr/funcapi.c:1953 +#: utils/fmgr/funcapi.c:1929 utils/fmgr/funcapi.c:1961 #, c-format msgid "number of aliases does not match number of columns" msgstr "el número de aliases no coincide con el número de columnas" -#: utils/fmgr/funcapi.c:1947 +#: utils/fmgr/funcapi.c:1955 #, c-format msgid "no column alias was provided" msgstr "no se entregó alias de columna" -#: utils/fmgr/funcapi.c:1971 +#: utils/fmgr/funcapi.c:1979 #, c-format msgid "could not determine row description for function returning record" msgstr "no se pudo encontrar descripción de registro de función que retorna record" -#: utils/init/miscinit.c:347 +#: utils/init/miscinit.c:353 #, c-format msgid "data directory \"%s\" does not exist" msgstr "no existe el directorio de datos «%s»" -#: utils/init/miscinit.c:352 +#: utils/init/miscinit.c:358 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "no se pudo obtener los permisos del directorio «%s»: %m" -#: utils/init/miscinit.c:360 +#: utils/init/miscinit.c:366 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "el directorio de datos especificado «%s» no es un directorio" -#: utils/init/miscinit.c:376 +#: utils/init/miscinit.c:382 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "el directorio de datos «%s» tiene dueño equivocado" -#: utils/init/miscinit.c:378 +#: utils/init/miscinit.c:384 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "El servidor debe ser iniciado por el usuario dueño del directorio de datos." -#: utils/init/miscinit.c:396 +#: utils/init/miscinit.c:402 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "el directorio de datos «%s» tiene permisos no válidos" -#: utils/init/miscinit.c:398 +#: utils/init/miscinit.c:404 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "Los permisos deberían ser u=rwx (0700) o u=rwx,g=rx (0750)." -#: utils/init/miscinit.c:456 +#: utils/init/miscinit.c:462 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "no se pudo cambiar al directorio «%s»: %m" -#: utils/init/miscinit.c:693 utils/misc/guc.c:3548 +#: utils/init/miscinit.c:720 utils/misc/guc.c:3650 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "no se puede definir el parámetro «%s» dentro de una operación restringida por seguridad" -#: utils/init/miscinit.c:765 +#: utils/init/miscinit.c:807 #, c-format msgid "role with OID %u does not exist" msgstr "no existe el rol con OID %u" -#: utils/init/miscinit.c:795 +#: utils/init/miscinit.c:853 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "al rol «%s» no se le permite conectarse" -#: utils/init/miscinit.c:813 +#: utils/init/miscinit.c:874 #, c-format msgid "too many connections for role \"%s\"" msgstr "demasiadas conexiones para el rol «%s»" -#: utils/init/miscinit.c:912 -#, c-format -msgid "permission denied to set session authorization" -msgstr "se ha denegado el permiso para cambiar el usuario actual" - -#: utils/init/miscinit.c:995 +#: utils/init/miscinit.c:1045 #, c-format msgid "invalid role OID: %u" msgstr "el OID de rol no es válido: %u" -#: utils/init/miscinit.c:1142 +#: utils/init/miscinit.c:1192 #, c-format msgid "database system is shut down" msgstr "el sistema de bases de datos está apagado" -#: utils/init/miscinit.c:1229 +#: utils/init/miscinit.c:1279 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "no se pudo crear el archivo de bloqueo «%s»: %m" -#: utils/init/miscinit.c:1243 +#: utils/init/miscinit.c:1293 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "no se pudo abrir el archivo de bloqueo «%s»: %m" -#: utils/init/miscinit.c:1250 +#: utils/init/miscinit.c:1300 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "no se pudo leer el archivo de bloqueo «%s»: %m" -#: utils/init/miscinit.c:1259 +#: utils/init/miscinit.c:1309 #, c-format msgid "lock file \"%s\" is empty" msgstr "el archivo de bloqueo «%s» está vacío" -#: utils/init/miscinit.c:1260 +#: utils/init/miscinit.c:1310 #, c-format msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash." msgstr "Otro proceso servidor está iniciándose, o el archivo de bloqueo es remanente de una caída durante un inicio anterior." -#: utils/init/miscinit.c:1304 +#: utils/init/miscinit.c:1354 #, c-format msgid "lock file \"%s\" already exists" msgstr "el archivo de bloqueo «%s» ya existe" -#: utils/init/miscinit.c:1308 +#: utils/init/miscinit.c:1358 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "¿Hay otro postgres (PID %d) en ejecución en el directorio de datos «%s»?" -#: utils/init/miscinit.c:1310 +#: utils/init/miscinit.c:1360 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "¿Hay otro postmaster (PID %d) en ejecución en el directorio de datos «%s»?" -#: utils/init/miscinit.c:1313 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "¿Hay otro postgres (PID %d) usando el socket «%s»?" -#: utils/init/miscinit.c:1315 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "¿Hay otro postmaster (PID %d) usando el socket «%s»?" -#: utils/init/miscinit.c:1366 +#: utils/init/miscinit.c:1416 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "no se pudo eliminar el archivo de bloqueo antiguo «%s»: %m" -#: utils/init/miscinit.c:1368 +#: utils/init/miscinit.c:1418 #, c-format msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again." msgstr "El archivo parece accidentalmente abandonado, pero no pudo ser eliminado. Por favor elimine el archivo manualmente e intente nuevamente." -#: utils/init/miscinit.c:1405 utils/init/miscinit.c:1419 -#: utils/init/miscinit.c:1430 +#: utils/init/miscinit.c:1455 utils/init/miscinit.c:1469 +#: utils/init/miscinit.c:1480 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "no se pudo escribir el archivo de bloqueo «%s»: %m" -#: utils/init/miscinit.c:1541 utils/init/miscinit.c:1683 utils/misc/guc.c:5580 +#: utils/init/miscinit.c:1591 utils/init/miscinit.c:1733 utils/misc/guc.c:5765 #, c-format msgid "could not read from file \"%s\": %m" msgstr "no se pudo leer el archivo «%s»: %m" -#: utils/init/miscinit.c:1671 +#: utils/init/miscinit.c:1721 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "no se pudo abrir el archivo «%s»: %m; continuando de todas formas" -#: utils/init/miscinit.c:1696 +#: utils/init/miscinit.c:1746 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "el archivo de bloqueo «%s» tiene un PID erróneo: %ld en lugar de %ld" -#: utils/init/miscinit.c:1735 utils/init/miscinit.c:1751 +#: utils/init/miscinit.c:1785 utils/init/miscinit.c:1801 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "«%s» no es un directorio de datos válido" -#: utils/init/miscinit.c:1737 +#: utils/init/miscinit.c:1787 #, c-format msgid "File \"%s\" is missing." msgstr "Falta el archivo «%s»." -#: utils/init/miscinit.c:1753 +#: utils/init/miscinit.c:1803 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "El archivo «%s» no contiene datos válidos." -#: utils/init/miscinit.c:1755 +#: utils/init/miscinit.c:1805 #, c-format msgid "You might need to initdb." msgstr "Puede ser necesario ejecutar initdb." -#: utils/init/miscinit.c:1763 +#: utils/init/miscinit.c:1813 #, c-format msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s." msgstr "El directorio de datos fue inicializado por PostgreSQL versión %s, que no es compatible con esta versión %s." @@ -26960,7 +27762,7 @@ msgstr " SSL habilitado (protocolo=%s, cifrado=%s, bits=%d)" #: utils/init/postinit.c:285 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s, principal=%s)" -msgstr "" +msgstr " GSS (autenticado=%s, cifrado=%s, delegado_credenciales=%s, principal=%s)" #: utils/init/postinit.c:286 utils/init/postinit.c:287 #: utils/init/postinit.c:288 utils/init/postinit.c:293 @@ -26977,7 +27779,7 @@ msgstr "sí" #: utils/init/postinit.c:292 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s)" -msgstr "" +msgstr " GSS (autenticado=%s, cifrado=%s, delegado_credentiales=%s)" #: utils/init/postinit.c:333 #, c-format @@ -27004,106 +27806,105 @@ msgstr "permiso denegado a la base de datos «%s»" msgid "User does not have CONNECT privilege." msgstr "Usuario no tiene privilegios de conexión." -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:389 #, c-format msgid "too many connections for database \"%s\"" msgstr "demasiadas conexiones para la base de datos «%s»" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:413 utils/init/postinit.c:420 #, c-format msgid "database locale is incompatible with operating system" msgstr "la configuración regional es incompatible con el sistema operativo" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:414 #, c-format msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()." msgstr "La base de datos fue inicializada con LC_COLLATE «%s», el cual no es reconocido por setlocale()." -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:416 utils/init/postinit.c:423 #, c-format msgid "Recreate the database with another locale or install the missing locale." msgstr "Recree la base de datos con otra configuración regional, o instale la configuración regional faltante." -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:421 #, c-format msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "La base de datos fue inicializada con LC_CTYPE «%s», el cual no es reconocido por setlocale()." -#: utils/init/postinit.c:475 -#, fuzzy, c-format -#| msgid "collation \"%s\" has version mismatch" +#: utils/init/postinit.c:493 +#, c-format msgid "database \"%s\" has a collation version mismatch" -msgstr "el ordenamiento (collation) «%s» tiene una discordancia de versión" +msgstr "la base de datos «%s» tiene una discordancia de versión de ordenamiento (“collation”)" -#: utils/init/postinit.c:477 -#, fuzzy, c-format -#| msgid "The collation in the database was created using version %s, but the operating system provides version %s." +#: utils/init/postinit.c:495 +#, c-format msgid "The database was created using collation version %s, but the operating system provides version %s." -msgstr "El ordenamiento en la base de datos fue creado usando la versión %s, pero el sistema operativo provee la versión %s." +msgstr "La base de datos fue creada usando la versión de ordenamiento %s, pero el sistema operativo provee la versión %s." -#: utils/init/postinit.c:480 -#, fuzzy, c-format -#| msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." +#: utils/init/postinit.c:498 +#, c-format msgid "Rebuild all objects in this database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." -msgstr "Reconstruya todos los objetos afectados por este ordenamiento y ejecute ALTER COLLATION %s REFRESH VERSION, o construya PostgreSQL con la versión correcta de la biblioteca." +msgstr "Reconstruya todos los objetos en esta base de datos que usen el ordenamiento por omisión y ejecute ALTER DATABASE %s REFRESH COLLATION VERSION, o construya PostgreSQL con la versión correcta de la biblioteca." -#: utils/init/postinit.c:895 +#: utils/init/postinit.c:904 #, c-format msgid "no roles are defined in this database system" msgstr "no hay roles definidos en esta base de datos" -#: utils/init/postinit.c:896 +#: utils/init/postinit.c:905 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "Debería ejecutar imediatamente CREATE USER \"%s\" SUPERUSER;." -#: utils/init/postinit.c:932 +#: utils/init/postinit.c:942 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "debe ser superusuario para conectarse en modo de actualización binaria" -#: utils/init/postinit.c:953 -#, fuzzy, c-format -#| msgid "terminating connection because of crash of another server process" -msgid "remaining connection slots are reserved for roles with %s" -msgstr "terminando la conexión debido a una falla en otro proceso servidor" +#: utils/init/postinit.c:962 +#, c-format +msgid "remaining connection slots are reserved for roles with the %s attribute" +msgstr "las conexiones restantes están reservadas a roles con el atributo %s" -#: utils/init/postinit.c:959 +#: utils/init/postinit.c:968 #, c-format msgid "remaining connection slots are reserved for roles with privileges of the \"%s\" role" -msgstr "" +msgstr "las conexiones restantes están reservadas a roles con privilegios del rol «%s»" -#: utils/init/postinit.c:971 -#, fuzzy, c-format -#| msgid "permission denied to rename role" +#: utils/init/postinit.c:980 +#, c-format msgid "permission denied to start WAL sender" -msgstr "se ha denegado el permiso para cambiar el nombre al rol" +msgstr "se ha denegado el permiso para iniciar “WAL sender”" -#: utils/init/postinit.c:972 +#: utils/init/postinit.c:981 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." -msgstr "" +msgstr "Sólo roles con el atributo %s pueden iniciar un proceso “WAL sender”." + +#: utils/init/postinit.c:1099 +#, c-format +msgid "It seems to have just been dropped or renamed." +msgstr "Parece haber sido eliminada o renombrada." -#: utils/init/postinit.c:1042 +#: utils/init/postinit.c:1103 #, c-format msgid "database %u does not exist" msgstr "no existe la base de datos %u" -#: utils/init/postinit.c:1131 +#: utils/init/postinit.c:1112 #, c-format -msgid "It seems to have just been dropped or renamed." -msgstr "Parece haber sido eliminada o renombrada." +msgid "cannot connect to invalid database \"%s\"" +msgstr "no se puede conectar a la base de datos no válida «%s»" -#: utils/init/postinit.c:1149 +#: utils/init/postinit.c:1173 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "Falta el subdirectorio de base de datos «%s»." #: utils/init/usercontext.c:43 -#, fuzzy, c-format -#| msgid "\"%s\" cannot be higher than \"%s\"" +#, c-format msgid "role \"%s\" cannot SET ROLE to \"%s\"" -msgstr "«%s» no puede ser más alto que «%s»" +msgstr "el rol «%s» no puede hacer SET ROLE a «%s»" #: utils/mb/conv.c:522 utils/mb/conv.c:733 #, c-format @@ -27122,53 +27923,48 @@ msgstr "ID de codificación %d inesperado para juegos de caracteres ISO 8859" msgid "unexpected encoding ID %d for WIN character sets" msgstr "ID de codificación %d inesperado para juegos de caracteres WIN" -#: utils/mb/mbutils.c:298 utils/mb/mbutils.c:901 +#: utils/mb/mbutils.c:297 utils/mb/mbutils.c:900 #, c-format msgid "conversion between %s and %s is not supported" msgstr "la conversión entre %s y %s no está soportada" -#: utils/mb/mbutils.c:386 -#, c-format -msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" -msgstr "no existe el procedimiento por omisión de conversión desde la codificación «%s» a «%s»" - -#: utils/mb/mbutils.c:403 utils/mb/mbutils.c:431 utils/mb/mbutils.c:816 -#: utils/mb/mbutils.c:843 +#: utils/mb/mbutils.c:402 utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 +#: utils/mb/mbutils.c:842 #, c-format msgid "String of %d bytes is too long for encoding conversion." msgstr "La cadena de %d bytes es demasiado larga para la recodificación." -#: utils/mb/mbutils.c:569 +#: utils/mb/mbutils.c:568 #, c-format msgid "invalid source encoding name \"%s\"" msgstr "la codificación de origen «%s» no es válida" -#: utils/mb/mbutils.c:574 +#: utils/mb/mbutils.c:573 #, c-format msgid "invalid destination encoding name \"%s\"" msgstr "la codificación de destino «%s» no es válida" -#: utils/mb/mbutils.c:714 +#: utils/mb/mbutils.c:713 #, c-format msgid "invalid byte value for encoding \"%s\": 0x%02x" msgstr "byte no válido para codificación «%s»: 0x%02x" -#: utils/mb/mbutils.c:878 +#: utils/mb/mbutils.c:877 #, c-format msgid "invalid Unicode code point" msgstr "punto de código Unicode no válido" -#: utils/mb/mbutils.c:1204 +#: utils/mb/mbutils.c:1201 #, c-format msgid "bind_textdomain_codeset failed" msgstr "bind_textdomain_codeset falló" -#: utils/mb/mbutils.c:1725 +#: utils/mb/mbutils.c:1718 #, c-format msgid "invalid byte sequence for encoding \"%s\": %s" msgstr "secuencia de bytes no válida para codificación «%s»: %s" -#: utils/mb/mbutils.c:1758 +#: utils/mb/mbutils.c:1751 #, c-format msgid "character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"" msgstr "carácter con secuencia de bytes %s en codificación «%s» no tiene equivalente en la codificación «%s»" @@ -27183,83 +27979,82 @@ msgstr "nombre de directorio de configuración vacío: «%s»" msgid "could not open configuration directory \"%s\": %m" msgstr "no se pudo abrir el directorio de configuración «%s»: %m" -#: utils/misc/guc.c:115 +#: utils/misc/guc.c:122 msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "Unidades válidas para este parámetro son «B», «kB», «MB», «GB» y «TB»." -#: utils/misc/guc.c:152 +#: utils/misc/guc.c:159 msgid "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\"." msgstr "Unidades válidas son para este parámetro son «us», «ms», «s», «min», «h» y «d»." -#: utils/misc/guc.c:421 +#: utils/misc/guc.c:430 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "parámetro de configuración «%s» no reconocido en el archivo «%s» línea %d" -#: utils/misc/guc.c:461 utils/misc/guc.c:3406 utils/misc/guc.c:3646 -#: utils/misc/guc.c:3744 utils/misc/guc.c:3842 utils/misc/guc.c:3966 -#: utils/misc/guc.c:4069 +#: utils/misc/guc.c:470 utils/misc/guc.c:3504 utils/misc/guc.c:3748 +#: utils/misc/guc.c:3846 utils/misc/guc.c:3944 utils/misc/guc.c:4071 +#: utils/misc/guc.c:4212 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "el parámetro «%s» no se puede cambiar sin reiniciar el servidor" -#: utils/misc/guc.c:497 +#: utils/misc/guc.c:506 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "parámetro «%s» eliminado del archivo de configuración, volviendo al valor por omisión" -#: utils/misc/guc.c:562 +#: utils/misc/guc.c:571 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "el parámetro «%s» fue cambiado a «%s»" -#: utils/misc/guc.c:604 +#: utils/misc/guc.c:613 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "el archivo de configuración «%s» contiene errores" -#: utils/misc/guc.c:609 +#: utils/misc/guc.c:618 #, c-format msgid "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "el archivo de configuración «%s» contiene errores; los cambios no afectados fueron aplicados" -#: utils/misc/guc.c:614 +#: utils/misc/guc.c:623 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "el archivo de configuración «%s» contiene errores; no se aplicó ningún cambio" -#: utils/misc/guc.c:1211 utils/misc/guc.c:1227 +#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "nombre de parámetro de configuración «%s» no válido" -#: utils/misc/guc.c:1213 +#: utils/misc/guc.c:1141 #, c-format msgid "Custom parameter names must be two or more simple identifiers separated by dots." msgstr "Los nombres de los parámetros personalizados deben ser dos o más identificadores sencillos separados por puntos." -#: utils/misc/guc.c:1229 -#, fuzzy, c-format -#| msgid "\"%s\" is a procedure." +#: utils/misc/guc.c:1157 +#, c-format msgid "\"%s\" is a reserved prefix." -msgstr "«%s» es un índice parcial." +msgstr "«%s» es un prefijo reservado." -#: utils/misc/guc.c:1243 +#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "parámetro de configuración «%s» no reconocido" -#: utils/misc/guc.c:1765 +#: utils/misc/guc.c:1802 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: no se pudo acceder al directorio «%s»: %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: no se pudo acceder al directorio «%s»: %m\n" -#: utils/misc/guc.c:1770 +#: utils/misc/guc.c:1806 #, c-format msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" msgstr "Ejecute initdb o pg_basebackup para inicializar un directorio de datos de PostgreSQL.\n" -#: utils/misc/guc.c:1794 +#: utils/misc/guc.c:1830 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" @@ -27268,12 +28063,12 @@ msgstr "" "%s no sabe dónde encontrar el archivo de configuración del servidor.\n" "Debe especificar la opción --config-file o -D o definir la variable de ambiente PGDATA.\n" -#: utils/misc/guc.c:1817 +#: utils/misc/guc.c:1853 #, c-format -msgid "%s: could not access the server configuration file \"%s\": %s\n" -msgstr "%s: no se pudo acceder al archivo de configuración «%s»: %s\n" +msgid "%s: could not access the server configuration file \"%s\": %m\n" +msgstr "%s: no se pudo acceder al archivo de configuración «%s»: %m\n" -#: utils/misc/guc.c:1845 +#: utils/misc/guc.c:1881 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -27282,7 +28077,7 @@ msgstr "" "%s no sabe dónde encontrar los archivos de sistema de la base de datos.\n" "Esto puede especificarse como «data_directory» en «%s», o usando la opción -D, o a través de la variable de ambiente PGDATA.\n" -#: utils/misc/guc.c:1897 +#: utils/misc/guc.c:1933 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" @@ -27291,7 +28086,7 @@ msgstr "" "%s no sabe dónde encontrar el archivo de configuración «hba».\n" "Esto puede especificarse como «hba_file» en «%s», o usando la opción -D, o a través de la variable de ambiente PGDATA.\n" -#: utils/misc/guc.c:1928 +#: utils/misc/guc.c:1964 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" @@ -27300,127 +28095,131 @@ msgstr "" "%s no sabe dónde encontrar el archivo de configuración «ident».\n" "Esto puede especificarse como «ident_file» en «%s», o usando la opción -D, o a través de la variable de ambiente PGDATA.\n" -#: utils/misc/guc.c:2894 +#: utils/misc/guc.c:2943 msgid "Value exceeds integer range." msgstr "El valor excede el rango para enteros." -#: utils/misc/guc.c:3130 +#: utils/misc/guc.c:3185 #, c-format -msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)" -msgstr "%d%s%s está fuera del rango aceptable para el parámetro «%s» (%d .. %d)" +msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" +msgstr "%d%s%s está fuera del rango aceptable para el parámetro «%s» (%d%s%s .. %d%s%s)" -#: utils/misc/guc.c:3166 +#: utils/misc/guc.c:3226 #, c-format -msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)" -msgstr "%g%s%s está fuera del rango aceptable para el parámetro «%s» (%g .. %g)" +msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" +msgstr "%g%s%s está fuera del rango aceptable para el parámetro «%s» (%g%s%s .. %g%s%s)" -#: utils/misc/guc.c:3366 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3465 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "no se puede definir parámetros durante una operación paralela" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "no se puede establecer el parámetro «%s» durante una operación paralela" -#: utils/misc/guc.c:3383 utils/misc/guc.c:4530 +#: utils/misc/guc.c:3481 utils/misc/guc.c:4696 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "no se puede cambiar el parámetro «%s»" -#: utils/misc/guc.c:3416 +#: utils/misc/guc.c:3514 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "el parámetro «%s» no se puede cambiar en este momento" -#: utils/misc/guc.c:3443 utils/misc/guc.c:3501 utils/misc/guc.c:4506 -#: utils/misc/guc.c:6546 +#: utils/misc/guc.c:3541 utils/misc/guc.c:3603 utils/misc/guc.c:4671 +#: utils/misc/guc.c:6756 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "se ha denegado el permiso para cambiar la opción «%s»" -#: utils/misc/guc.c:3481 +#: utils/misc/guc.c:3583 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "el parámetro «%s» no se puede cambiar después de efectuar la conexión" -#: utils/misc/guc.c:3540 +#: utils/misc/guc.c:3642 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "no se puede definir el parámetro «%s» dentro una función security-definer" -#: utils/misc/guc.c:3561 -#, fuzzy, c-format -#| msgid "parameter \"%s\" could not be set" +#: utils/misc/guc.c:3663 +#, c-format msgid "parameter \"%s\" cannot be reset" -msgstr "no se pudo cambiar el parámetro «%s»" +msgstr "el parámetro «%s» no puede ser reseteado" -#: utils/misc/guc.c:3568 -#, fuzzy, c-format -#| msgid "parameter \"%s\" cannot be set after connection start" +#: utils/misc/guc.c:3670 +#, c-format msgid "parameter \"%s\" cannot be set locally in functions" -msgstr "el parámetro «%s» no se puede cambiar después de efectuar la conexión" +msgstr "el parámetro «%s» no se puede cambiar localmente en funciones" -#: utils/misc/guc.c:4212 utils/misc/guc.c:4259 utils/misc/guc.c:5266 -#, fuzzy, c-format -#| msgid "permission denied to create \"%s.%s\"" +#: utils/misc/guc.c:4370 utils/misc/guc.c:4418 utils/misc/guc.c:5450 +#, c-format msgid "permission denied to examine \"%s\"" -msgstr "se ha denegado el permiso para crear «%s.%s»" +msgstr "se ha denegado el permiso a examinar «%s»" -#: utils/misc/guc.c:4213 utils/misc/guc.c:4260 utils/misc/guc.c:5267 +#: utils/misc/guc.c:4371 utils/misc/guc.c:4419 utils/misc/guc.c:5451 #, c-format msgid "Only roles with privileges of the \"%s\" role may examine this parameter." -msgstr "" +msgstr "Sólo roles con privilegios del rol «%s» pueden examinar este parámetro." + +#: utils/misc/guc.c:4629 +#, c-format +msgid "ALTER SYSTEM is not allowed in this environment" +msgstr "ALTER SYSTEM no está permitido en este ambiente" -#: utils/misc/guc.c:4496 -#, fuzzy, c-format -#| msgid "permission denied for operator %s" +#: utils/misc/guc.c:4661 +#, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" -msgstr "permiso denegado al operador %s" +msgstr "permiso denegado a ejecutar ALTER SYSTEM RESET ALL" -#: utils/misc/guc.c:4562 +#: utils/misc/guc.c:4740 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "los valores de parámetros para ALTER SYSTEM no deben contener saltos de línea" -#: utils/misc/guc.c:4608 +#: utils/misc/guc.c:4785 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "no se pudo interpretar el contenido del archivo «%s»" -#: utils/misc/guc.c:4790 +#: utils/misc/guc.c:4967 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "intento de cambiar la opción «%s»" -#: utils/misc/guc.c:5129 -#, fuzzy, c-format -#| msgid "invalid configuration parameter name \"%s\"" +#: utils/misc/guc.c:5306 +#, c-format msgid "invalid configuration parameter name \"%s\", removing it" -msgstr "nombre de parámetro de configuración «%s» no válido" +msgstr "nombre de parámetro de configuración «%s» no válido, eliminándolo" -#: utils/misc/guc.c:5131 -#, fuzzy, c-format -#| msgid "\"%s\" is not a sequence" +#: utils/misc/guc.c:5308 +#, c-format msgid "\"%s\" is now a reserved prefix." -msgstr "«%s» no es una secuencia" +msgstr "«%s» es ahora un prefijo reservado." -#: utils/misc/guc.c:6000 +#: utils/misc/guc.c:6179 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "al establecer el parámetro «%s» a «%s»" -#: utils/misc/guc.c:6169 +#: utils/misc/guc.c:6348 #, c-format msgid "parameter \"%s\" could not be set" msgstr "no se pudo cambiar el parámetro «%s»" -#: utils/misc/guc.c:6259 +#: utils/misc/guc.c:6438 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "no se pudo interpretar el valor de para el parámetro «%s»" -#: utils/misc/guc.c:6678 +#: utils/misc/guc.c:6888 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "valor no válido para el parámetro «%s»: %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "no se puede definir parámetros durante una operación paralela" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -27436,41 +28235,39 @@ msgstr "SET %s lleva sólo un argumento" msgid "SET requires parameter name" msgstr "SET requiere el nombre de un parámetro" -#: utils/misc/guc_tables.c:667 +#: utils/misc/guc_tables.c:676 msgid "Ungrouped" msgstr "Sin Grupo" -#: utils/misc/guc_tables.c:669 +#: utils/misc/guc_tables.c:677 msgid "File Locations" msgstr "Ubicaciones de Archivos" -#: utils/misc/guc_tables.c:671 +#: utils/misc/guc_tables.c:678 msgid "Connections and Authentication / Connection Settings" msgstr "Conexiones y Autentificación / Parámetros de Conexión" -#: utils/misc/guc_tables.c:673 -#, fuzzy -#| msgid "Connections and Authentication / Connection Settings" +#: utils/misc/guc_tables.c:679 msgid "Connections and Authentication / TCP Settings" -msgstr "Conexiones y Autentificación / Parámetros de Conexión" +msgstr "Conexiones y Autentificación / Parámetros TCP" -#: utils/misc/guc_tables.c:675 +#: utils/misc/guc_tables.c:680 msgid "Connections and Authentication / Authentication" msgstr "Conexiones y Autentificación / Autentificación" -#: utils/misc/guc_tables.c:677 +#: utils/misc/guc_tables.c:681 msgid "Connections and Authentication / SSL" msgstr "Conexiones y Autentificación / SSL" -#: utils/misc/guc_tables.c:679 +#: utils/misc/guc_tables.c:682 msgid "Resource Usage / Memory" msgstr "Uso de Recursos / Memoria" -#: utils/misc/guc_tables.c:681 +#: utils/misc/guc_tables.c:683 msgid "Resource Usage / Disk" msgstr "Uso de Recursos / Disco" -#: utils/misc/guc_tables.c:683 +#: utils/misc/guc_tables.c:684 msgid "Resource Usage / Kernel Resources" msgstr "Uso de Recursos / Recursos del Kernel" @@ -27478,1985 +28275,2032 @@ msgstr "Uso de Recursos / Recursos del Kernel" msgid "Resource Usage / Cost-Based Vacuum Delay" msgstr "Uso de Recursos / Retardo de Vacuum por Costos" -#: utils/misc/guc_tables.c:687 +#: utils/misc/guc_tables.c:686 msgid "Resource Usage / Background Writer" msgstr "Uso de Recursos / Escritor en Segundo Plano" -#: utils/misc/guc_tables.c:689 +#: utils/misc/guc_tables.c:687 msgid "Resource Usage / Asynchronous Behavior" msgstr "Uso de Recursos / Comportamiento Asíncrono" -#: utils/misc/guc_tables.c:691 +#: utils/misc/guc_tables.c:688 msgid "Write-Ahead Log / Settings" msgstr "Write-Ahead Log / Configuraciones" -#: utils/misc/guc_tables.c:693 +#: utils/misc/guc_tables.c:689 msgid "Write-Ahead Log / Checkpoints" msgstr "Write-Ahead Log / Puntos de Control (Checkpoints)" -#: utils/misc/guc_tables.c:695 +#: utils/misc/guc_tables.c:690 msgid "Write-Ahead Log / Archiving" msgstr "Write-Ahead Log / Archivado" -#: utils/misc/guc_tables.c:697 -#, fuzzy -#| msgid "Write-Ahead Log / Recovery Target" +#: utils/misc/guc_tables.c:691 msgid "Write-Ahead Log / Recovery" -msgstr "Write-Ahead Log / Destino de Recuperación" +msgstr "Write-Ahead Log / Recuperación" -#: utils/misc/guc_tables.c:699 +#: utils/misc/guc_tables.c:692 msgid "Write-Ahead Log / Archive Recovery" msgstr "Write-Ahead Log / Recuperación desde Archivo" -#: utils/misc/guc_tables.c:701 +#: utils/misc/guc_tables.c:693 msgid "Write-Ahead Log / Recovery Target" msgstr "Write-Ahead Log / Destino de Recuperación" -#: utils/misc/guc_tables.c:703 +#: utils/misc/guc_tables.c:694 +msgid "Write-Ahead Log / Summarization" +msgstr "Write-Ahead Log / Sumarización" + +#: utils/misc/guc_tables.c:695 msgid "Replication / Sending Servers" msgstr "Replicación / Servidores de Envío" -#: utils/misc/guc_tables.c:705 +#: utils/misc/guc_tables.c:696 msgid "Replication / Primary Server" msgstr "Replicación / Servidor Primario" -#: utils/misc/guc_tables.c:707 +#: utils/misc/guc_tables.c:697 msgid "Replication / Standby Servers" msgstr "Replicación / Servidores Standby" -#: utils/misc/guc_tables.c:709 +#: utils/misc/guc_tables.c:698 msgid "Replication / Subscribers" msgstr "Replicación / Suscriptores" -#: utils/misc/guc_tables.c:711 +#: utils/misc/guc_tables.c:699 msgid "Query Tuning / Planner Method Configuration" msgstr "Afinamiento de Consultas / Configuración de Métodos del Planner" -#: utils/misc/guc_tables.c:713 +#: utils/misc/guc_tables.c:700 msgid "Query Tuning / Planner Cost Constants" msgstr "Afinamiento de Consultas / Constantes de Costo del Planner" -#: utils/misc/guc_tables.c:715 +#: utils/misc/guc_tables.c:701 msgid "Query Tuning / Genetic Query Optimizer" msgstr "Afinamiento de Consultas / Optimizador Genético de Consultas" -#: utils/misc/guc_tables.c:717 +#: utils/misc/guc_tables.c:702 msgid "Query Tuning / Other Planner Options" msgstr "Afinamiento de Consultas / Otras Opciones del Planner" -#: utils/misc/guc_tables.c:719 +#: utils/misc/guc_tables.c:703 msgid "Reporting and Logging / Where to Log" msgstr "Reporte y Registro / Dónde Registrar" -#: utils/misc/guc_tables.c:721 +#: utils/misc/guc_tables.c:704 msgid "Reporting and Logging / When to Log" msgstr "Reporte y Registro / Cuándo Registrar" -#: utils/misc/guc_tables.c:723 +#: utils/misc/guc_tables.c:705 msgid "Reporting and Logging / What to Log" msgstr "Reporte y Registro / Qué Registrar" -#: utils/misc/guc_tables.c:725 +#: utils/misc/guc_tables.c:706 msgid "Reporting and Logging / Process Title" msgstr "Reporte y Registro / Título del Proceso" -#: utils/misc/guc_tables.c:727 +#: utils/misc/guc_tables.c:707 msgid "Statistics / Monitoring" msgstr "Estadísticas / Monitoreo" -#: utils/misc/guc_tables.c:729 +#: utils/misc/guc_tables.c:708 msgid "Statistics / Cumulative Query and Index Statistics" -msgstr "" +msgstr "Estadísticas / Acumuladores de Consultas e Índices" -#: utils/misc/guc_tables.c:731 +#: utils/misc/guc_tables.c:709 msgid "Autovacuum" msgstr "Autovacuum" -#: utils/misc/guc_tables.c:733 +#: utils/misc/guc_tables.c:710 msgid "Client Connection Defaults / Statement Behavior" msgstr "Valores por Omisión de Conexiones / Comportamiento de Sentencias" -#: utils/misc/guc_tables.c:735 +#: utils/misc/guc_tables.c:711 msgid "Client Connection Defaults / Locale and Formatting" msgstr "Valores por Omisión de Conexiones / Configuraciones Regionales y Formateo" -#: utils/misc/guc_tables.c:737 +#: utils/misc/guc_tables.c:712 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "Valores por Omisión de Conexiones / Precargado de Bibliotecas Compartidas" -#: utils/misc/guc_tables.c:739 +#: utils/misc/guc_tables.c:713 msgid "Client Connection Defaults / Other Defaults" msgstr "Valores por Omisión de Conexiones / Otros Valores" -#: utils/misc/guc_tables.c:741 +#: utils/misc/guc_tables.c:714 msgid "Lock Management" msgstr "Manejo de Bloqueos" -#: utils/misc/guc_tables.c:743 +#: utils/misc/guc_tables.c:715 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "Compatibilidad de Versión y Plataforma / Versiones Anteriores de PostgreSQL" -#: utils/misc/guc_tables.c:745 +#: utils/misc/guc_tables.c:716 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "Compatibilidad de Versión y Plataforma / Otras Plataformas y Clientes" -#: utils/misc/guc_tables.c:747 +#: utils/misc/guc_tables.c:717 msgid "Error Handling" msgstr "Gestión de Errores" -#: utils/misc/guc_tables.c:749 +#: utils/misc/guc_tables.c:718 msgid "Preset Options" msgstr "Opciones Predefinidas" -#: utils/misc/guc_tables.c:751 +#: utils/misc/guc_tables.c:719 msgid "Customized Options" msgstr "Opciones Personalizadas" -#: utils/misc/guc_tables.c:753 +#: utils/misc/guc_tables.c:720 msgid "Developer Options" msgstr "Opciones de Desarrollador" -#: utils/misc/guc_tables.c:810 +#: utils/misc/guc_tables.c:775 msgid "Enables the planner's use of sequential-scan plans." msgstr "Permitir el uso de planes de recorrido secuencial." -#: utils/misc/guc_tables.c:820 +#: utils/misc/guc_tables.c:785 msgid "Enables the planner's use of index-scan plans." msgstr "Permitir el uso de planes de recorrido de índice." -#: utils/misc/guc_tables.c:830 +#: utils/misc/guc_tables.c:795 msgid "Enables the planner's use of index-only-scan plans." msgstr "Permitir el uso de planes de recorrido de sólo-índice." -#: utils/misc/guc_tables.c:840 +#: utils/misc/guc_tables.c:805 msgid "Enables the planner's use of bitmap-scan plans." msgstr "Permitir el uso de planes de recorrido de índice por mapas de bits." -#: utils/misc/guc_tables.c:850 +#: utils/misc/guc_tables.c:815 msgid "Enables the planner's use of TID scan plans." msgstr "Permitir el uso de planes de recorrido por TID." -#: utils/misc/guc_tables.c:860 +#: utils/misc/guc_tables.c:825 msgid "Enables the planner's use of explicit sort steps." msgstr "Permitir el uso de pasos explícitos de ordenamiento." -#: utils/misc/guc_tables.c:870 +#: utils/misc/guc_tables.c:835 msgid "Enables the planner's use of incremental sort steps." msgstr "Permitir el uso de pasos incrementales de ordenamiento." -#: utils/misc/guc_tables.c:880 +#: utils/misc/guc_tables.c:845 msgid "Enables the planner's use of hashed aggregation plans." msgstr "Permitir el uso de planes de agregación a través de hash." -#: utils/misc/guc_tables.c:890 +#: utils/misc/guc_tables.c:855 msgid "Enables the planner's use of materialization." msgstr "Permitir el uso de materialización de planes." -#: utils/misc/guc_tables.c:900 +#: utils/misc/guc_tables.c:865 msgid "Enables the planner's use of memoization." msgstr "Permitir el uso de memoización de planes." -#: utils/misc/guc_tables.c:910 +#: utils/misc/guc_tables.c:875 msgid "Enables the planner's use of nested-loop join plans." msgstr "Permitir el uso de planes «nested-loop join»." -#: utils/misc/guc_tables.c:920 +#: utils/misc/guc_tables.c:885 msgid "Enables the planner's use of merge join plans." msgstr "Permitir el uso de planes «merge join»." -#: utils/misc/guc_tables.c:930 +#: utils/misc/guc_tables.c:895 msgid "Enables the planner's use of hash join plans." msgstr "Permitir el uso de planes «hash join»." -#: utils/misc/guc_tables.c:940 +#: utils/misc/guc_tables.c:905 msgid "Enables the planner's use of gather merge plans." msgstr "Permitir el uso de planes «gather merge»." -#: utils/misc/guc_tables.c:950 +#: utils/misc/guc_tables.c:915 msgid "Enables partitionwise join." msgstr "Permitir el uso de joins por particiones." -#: utils/misc/guc_tables.c:960 +#: utils/misc/guc_tables.c:925 msgid "Enables partitionwise aggregation and grouping." msgstr "Permitir el uso de agregación y agrupamiento por particiones." -#: utils/misc/guc_tables.c:970 +#: utils/misc/guc_tables.c:935 msgid "Enables the planner's use of parallel append plans." msgstr "Permitir el uso de planes «append» paralelos." -#: utils/misc/guc_tables.c:980 +#: utils/misc/guc_tables.c:945 msgid "Enables the planner's use of parallel hash plans." msgstr "Permitir el uso de planes «hash join» paralelos." -#: utils/misc/guc_tables.c:990 +#: utils/misc/guc_tables.c:955 msgid "Enables plan-time and execution-time partition pruning." msgstr "Permitir el uso de poda de particiones en tiempo de plan y ejecución." -#: utils/misc/guc_tables.c:991 +#: utils/misc/guc_tables.c:956 msgid "Allows the query planner and executor to compare partition bounds to conditions in the query to determine which partitions must be scanned." msgstr "Permite al optimizador de consultas y al ejecutor a comparar bordes de particiones a condiciones en las consultas para determinar qué particiones deben recorrerse." -#: utils/misc/guc_tables.c:1002 -msgid "Enables the planner's ability to produce plans which provide presorted input for ORDER BY / DISTINCT aggregate functions." -msgstr "" +#: utils/misc/guc_tables.c:967 +msgid "Enables the planner's ability to produce plans that provide presorted input for ORDER BY / DISTINCT aggregate functions." +msgstr "Activa la capacidad del optimizador de permitir planes que proveen entrada pre-ordenada para funciones de agregación ORDER BY / DISTINCT" -#: utils/misc/guc_tables.c:1005 -msgid "Allows the query planner to build plans which provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." -msgstr "" +#: utils/misc/guc_tables.c:970 +msgid "Allows the query planner to build plans that provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." +msgstr "Permite al optimizador construir planes que proveen entrada pre-ordenada para funciones de agregación con una cláusula ORDER BY / DISTINCT. Cuando está desactivado, siempre se efectúan ordenamientos implícitos durante la ejecución." -#: utils/misc/guc_tables.c:1017 +#: utils/misc/guc_tables.c:982 msgid "Enables the planner's use of async append plans." msgstr "Permitir el uso de planes «append» asíncronos." -#: utils/misc/guc_tables.c:1027 +#: utils/misc/guc_tables.c:992 +msgid "Enables reordering of GROUP BY keys." +msgstr "Activa el reordenamiento de claves GROUP BY." + +#: utils/misc/guc_tables.c:1002 msgid "Enables genetic query optimization." msgstr "Permitir el uso del optimizador genético de consultas." -#: utils/misc/guc_tables.c:1028 +#: utils/misc/guc_tables.c:1003 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "Este algoritmo intenta planear las consultas sin hacer búsqueda exhaustiva." -#: utils/misc/guc_tables.c:1039 +#: utils/misc/guc_tables.c:1017 msgid "Shows whether the current user is a superuser." msgstr "Indica si el usuario actual es superusuario." -#: utils/misc/guc_tables.c:1049 +#: utils/misc/guc_tables.c:1032 +msgid "Allows running the ALTER SYSTEM command." +msgstr "Permite ejecutar la orden ALTER SYSTEM." + +#: utils/misc/guc_tables.c:1033 +msgid "Can be set to off for environments where global configuration changes should be made using a different method." +msgstr "Puede desactivarse en ambientes donde los cambios globales de configuración deban hacerse usando un método diferente." + +#: utils/misc/guc_tables.c:1043 msgid "Enables advertising the server via Bonjour." msgstr "Permitir la publicación del servidor vía Bonjour." -#: utils/misc/guc_tables.c:1058 +#: utils/misc/guc_tables.c:1052 msgid "Collects transaction commit time." msgstr "Recolectar tiempo de compromiso de transacciones." -#: utils/misc/guc_tables.c:1067 +#: utils/misc/guc_tables.c:1061 msgid "Enables SSL connections." msgstr "Permitir conexiones SSL." -#: utils/misc/guc_tables.c:1076 -msgid "Controls whether ssl_passphrase_command is called during server reload." -msgstr "" +#: utils/misc/guc_tables.c:1070 +msgid "Controls whether \"ssl_passphrase_command\" is called during server reload." +msgstr "Controla si «ssl_passphrase_command» es invocado durante el “reload” del servidor." -#: utils/misc/guc_tables.c:1085 +#: utils/misc/guc_tables.c:1079 msgid "Give priority to server ciphersuite order." msgstr "Da prioridad al orden de algoritmos de cifrado especificado por el servidor." -#: utils/misc/guc_tables.c:1094 +#: utils/misc/guc_tables.c:1088 msgid "Forces synchronization of updates to disk." msgstr "Forzar la sincronización de escrituras a disco." -#: utils/misc/guc_tables.c:1095 +#: utils/misc/guc_tables.c:1089 msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This ensures that a database cluster will recover to a consistent state after an operating system or hardware crash." msgstr "El servidor usará la llamada a sistema fsync() en varios lugares para asegurarse que las actualizaciones son escritas físicamente a disco. Esto asegura que las bases de datos se recuperarán a un estado consistente después de una caída de hardware o sistema operativo." -#: utils/misc/guc_tables.c:1106 +#: utils/misc/guc_tables.c:1100 msgid "Continues processing after a checksum failure." msgstr "Continuar procesando después de una falla de suma de verificación." -#: utils/misc/guc_tables.c:1107 +#: utils/misc/guc_tables.c:1101 msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled." msgstr "La detección de una suma de verificación que no coincide normalmente hace que PostgreSQL reporte un error, abortando la transacción en curso. Definiendo ignore_checksum_failure a true hace que el sistema ignore la falla (pero aún así reporta un mensaje de warning), y continúe el procesamiento. Este comportamiento podría causar caídas del sistema u otros problemas serios. Sólo tiene efecto si las sumas de verificación están activadas." -#: utils/misc/guc_tables.c:1121 +#: utils/misc/guc_tables.c:1115 msgid "Continues processing past damaged page headers." msgstr "Continuar procesando después de detectar encabezados de página dañados." -#: utils/misc/guc_tables.c:1122 -msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." -msgstr "La detección de un encabezado de página dañado normalmente hace que PostgreSQL reporte un error, abortando la transacción en curso. Definiendo zero_damaged_pages a true hace que el sistema reporte un mensaje de warning, escriba ceros en toda la página, y continúe el procesamiento. Este comportamiento destruirá datos; en particular, todas las tuplas en la página dañada." +#: utils/misc/guc_tables.c:1116 +msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting \"zero_damaged_pages\" to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." +msgstr "La detección de un encabezado de página dañado normalmente hace que PostgreSQL reporte un error, abortando la transacción en curso. Definiendo «zero_damaged_pages» a true hace que el sistema reporte un mensaje de warning, escriba ceros en toda la página, y continúe el procesamiento. Este comportamiento destruirá datos; en particular, todas las tuplas en la página dañada." -#: utils/misc/guc_tables.c:1135 +#: utils/misc/guc_tables.c:1129 msgid "Continues recovery after an invalid pages failure." msgstr "Continuar procesando después de una falla de páginas no válidas." -#: utils/misc/guc_tables.c:1136 -msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting ignore_invalid_pages to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." -msgstr "La detección de que registros de WAL tengan referencias a páginas no válidas durante la recuperación hace que PostgreSQL produzca un error de nivel PANIC, abortando la recuperación. Establecer el valor de ignore_invalid_pages a true hace que el sistema ignore las referencias a páginas no válidas en registros de WAL (pero aún así reporta un mensaje de warning), y continúe la recuperación. Este comportamiento podría causar caídas del sistema, pérdida de datos, propagar u ocultar corrupción, u otros problemas serios. Sólo tiene efecto durante la recuperación o en modo standby." +#: utils/misc/guc_tables.c:1130 +msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." +msgstr "La detección de que registros de WAL tengan referencias a páginas no válidas durante la recuperación hace que PostgreSQL produzca un error de nivel PANIC, abortando la recuperación. Establecer el valor de «ignore_invalid_pages» a true hace que el sistema ignore las referencias a páginas no válidas en registros de WAL (pero aún así reporta un mensaje de warning), y continúe la recuperación. Este comportamiento podría causar caídas del sistema, pérdida de datos, propagar u ocultar corrupción, u otros problemas serios. Sólo tiene efecto durante la recuperación o en modo standby." -#: utils/misc/guc_tables.c:1154 +#: utils/misc/guc_tables.c:1148 msgid "Writes full pages to WAL when first modified after a checkpoint." -msgstr "Escribe páginas completas a WAL cuando son modificadas después de un punto de control." +msgstr "Escribe páginas completas a WAL cuando son modificadas después de un checkpoint." -#: utils/misc/guc_tables.c:1155 +#: utils/misc/guc_tables.c:1149 msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible." -msgstr "Una escritura de página que está siendo procesada durante una caída del sistema operativo puede ser completada sólo parcialmente. Durante la recuperación, los cambios de registros (tuplas) almacenados en WAL no son suficientes para la recuperación. Esta opción activa la escritura de las páginas a WAL cuando son modificadas por primera vez después de un punto de control, de manera que una recuperación total es posible." +msgstr "Una escritura de página que está siendo procesada durante una caída del sistema operativo puede ser completada sólo parcialmente. Durante la recuperación, los cambios de registros (tuplas) almacenados en WAL no son suficientes para la recuperación. Esta opción activa la escritura de las páginas a WAL cuando son modificadas por primera vez después de un checkpoint, de manera que una recuperación total es posible." -#: utils/misc/guc_tables.c:1168 +#: utils/misc/guc_tables.c:1162 msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification." -msgstr "Escribir páginas completas al WAL cuando son modificadas después de un punto de control, incluso para una modificación no crítica." +msgstr "Escribir páginas completas al WAL cuando son modificadas después de un checkpoint, incluso para una modificación no crítica." -#: utils/misc/guc_tables.c:1178 +#: utils/misc/guc_tables.c:1172 msgid "Writes zeroes to new WAL files before first use." msgstr "Escribir ceros a nuevos archivos WAL antes del primer uso." -#: utils/misc/guc_tables.c:1188 +#: utils/misc/guc_tables.c:1182 msgid "Recycles WAL files by renaming them." msgstr "Reciclar archivos de WAL cambiándoles de nombre." -#: utils/misc/guc_tables.c:1198 +#: utils/misc/guc_tables.c:1192 msgid "Logs each checkpoint." -msgstr "Registrar cada punto de control." +msgstr "Registrar cada checkpoint." -#: utils/misc/guc_tables.c:1207 +#: utils/misc/guc_tables.c:1201 msgid "Logs each successful connection." msgstr "Registrar cada conexión exitosa." -#: utils/misc/guc_tables.c:1216 +#: utils/misc/guc_tables.c:1210 +msgid "Logs details of pre-authentication connection handshake." +msgstr "Registrar detalles de “handshake” de conexión anteriores a la autentificación." + +#: utils/misc/guc_tables.c:1220 msgid "Logs end of a session, including duration." msgstr "Registrar el fin de una sesión, incluyendo su duración." -#: utils/misc/guc_tables.c:1225 +#: utils/misc/guc_tables.c:1229 msgid "Logs each replication command." msgstr "Registrar cada orden de replicación." -#: utils/misc/guc_tables.c:1234 +#: utils/misc/guc_tables.c:1238 msgid "Shows whether the running server has assertion checks enabled." msgstr "Indica si el servidor actual tiene activas las aseveraciones (asserts) activas." -#: utils/misc/guc_tables.c:1245 +#: utils/misc/guc_tables.c:1249 msgid "Terminate session on any error." msgstr "Terminar sesión ante cualquier error." -#: utils/misc/guc_tables.c:1254 +#: utils/misc/guc_tables.c:1258 msgid "Reinitialize server after backend crash." msgstr "Reinicializar el servidor después de una caída de un proceso servidor." -#: utils/misc/guc_tables.c:1263 +#: utils/misc/guc_tables.c:1267 msgid "Remove temporary files after backend crash." msgstr "Eliminar archivos temporales después de una caída de un proceso servidor." -#: utils/misc/guc_tables.c:1273 +#: utils/misc/guc_tables.c:1277 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." -msgstr "" +msgstr "Enviar SIGABRT en vez de SIGQUIT a procesos hijos después de una caída de un proceso servidor." -#: utils/misc/guc_tables.c:1283 +#: utils/misc/guc_tables.c:1287 msgid "Send SIGABRT not SIGKILL to stuck child processes." -msgstr "" +msgstr "Enviar SIGABRT en vez de SIGKILL a procesos hijos atascados." -#: utils/misc/guc_tables.c:1294 +#: utils/misc/guc_tables.c:1298 msgid "Logs the duration of each completed SQL statement." msgstr "Registrar la duración de cada sentencia SQL ejecutada." -#: utils/misc/guc_tables.c:1303 +#: utils/misc/guc_tables.c:1307 msgid "Logs each query's parse tree." msgstr "Registrar cada arbol analizado de consulta " -#: utils/misc/guc_tables.c:1312 +#: utils/misc/guc_tables.c:1316 msgid "Logs each query's rewritten parse tree." msgstr "Registrar cada reescritura del arból analizado de consulta" -#: utils/misc/guc_tables.c:1321 +#: utils/misc/guc_tables.c:1325 msgid "Logs each query's execution plan." msgstr "Registrar el plan de ejecución de cada consulta." -#: utils/misc/guc_tables.c:1330 +#: utils/misc/guc_tables.c:1334 msgid "Indents parse and plan tree displays." msgstr "Indentar los árboles de parse y plan." -#: utils/misc/guc_tables.c:1339 +#: utils/misc/guc_tables.c:1343 msgid "Writes parser performance statistics to the server log." msgstr "Escribir estadísticas de parser al registro del servidor." -#: utils/misc/guc_tables.c:1348 +#: utils/misc/guc_tables.c:1352 msgid "Writes planner performance statistics to the server log." msgstr "Escribir estadísticas de planner al registro del servidor." -#: utils/misc/guc_tables.c:1357 +#: utils/misc/guc_tables.c:1361 msgid "Writes executor performance statistics to the server log." msgstr "Escribir estadísticas del executor al registro del servidor." -#: utils/misc/guc_tables.c:1366 +#: utils/misc/guc_tables.c:1370 msgid "Writes cumulative performance statistics to the server log." msgstr "Escribir estadísticas acumulativas al registro del servidor." -#: utils/misc/guc_tables.c:1376 +#: utils/misc/guc_tables.c:1380 msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations." msgstr "Registrar uso de recursos de sistema (memoria y CPU) en varias operaciones B-tree." -#: utils/misc/guc_tables.c:1388 +#: utils/misc/guc_tables.c:1392 msgid "Collects information about executing commands." msgstr "Recolectar estadísticas sobre órdenes en ejecución." -#: utils/misc/guc_tables.c:1389 +#: utils/misc/guc_tables.c:1393 msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution." msgstr "Activa la recolección de información sobre la orden actualmente en ejecución en cada sesión, junto con el momento en el cual esa orden comenzó la ejecución." -#: utils/misc/guc_tables.c:1399 +#: utils/misc/guc_tables.c:1403 msgid "Collects statistics on database activity." msgstr "Recolectar estadísticas de actividad de la base de datos." -#: utils/misc/guc_tables.c:1408 +#: utils/misc/guc_tables.c:1412 msgid "Collects timing statistics for database I/O activity." msgstr "Recolectar estadísticas de tiempos en las operaciones de I/O de la base de datos." -#: utils/misc/guc_tables.c:1417 +#: utils/misc/guc_tables.c:1421 msgid "Collects timing statistics for WAL I/O activity." msgstr "Recolectar estadísticas de tiempos en las operaciones de I/O del WAL." -#: utils/misc/guc_tables.c:1427 +#: utils/misc/guc_tables.c:1431 msgid "Updates the process title to show the active SQL command." msgstr "Actualiza el título del proceso para mostrar la orden SQL activo." -#: utils/misc/guc_tables.c:1428 +#: utils/misc/guc_tables.c:1432 msgid "Enables updating of the process title every time a new SQL command is received by the server." msgstr "Habilita que se actualice el título del proceso cada vez que una orden SQL es recibido por el servidor." -#: utils/misc/guc_tables.c:1437 +#: utils/misc/guc_tables.c:1441 msgid "Starts the autovacuum subprocess." msgstr "Iniciar el subproceso de autovacuum." -#: utils/misc/guc_tables.c:1447 +#: utils/misc/guc_tables.c:1451 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "Generar salida de depuración para LISTEN y NOTIFY." -#: utils/misc/guc_tables.c:1459 +#: utils/misc/guc_tables.c:1463 msgid "Emits information about lock usage." msgstr "Emitir información acerca del uso de locks." -#: utils/misc/guc_tables.c:1469 +#: utils/misc/guc_tables.c:1473 msgid "Emits information about user lock usage." msgstr "Emitir información acerca del uso de locks de usuario." -#: utils/misc/guc_tables.c:1479 +#: utils/misc/guc_tables.c:1483 msgid "Emits information about lightweight lock usage." msgstr "Emitir información acerca del uso de «lightweight locks»." -#: utils/misc/guc_tables.c:1489 +#: utils/misc/guc_tables.c:1493 msgid "Dumps information about all current locks when a deadlock timeout occurs." msgstr "Volcar información acerca de los locks existentes cuando se agota el tiempo de deadlock." -#: utils/misc/guc_tables.c:1501 +#: utils/misc/guc_tables.c:1505 msgid "Logs long lock waits." msgstr "Registrar esperas largas de bloqueos." -#: utils/misc/guc_tables.c:1510 +#: utils/misc/guc_tables.c:1514 msgid "Logs standby recovery conflict waits." msgstr "Registrar esperas por conflictos en recuperación de standby" -#: utils/misc/guc_tables.c:1519 +#: utils/misc/guc_tables.c:1523 msgid "Logs the host name in the connection logs." msgstr "Registrar el nombre del host en la conexión." -#: utils/misc/guc_tables.c:1520 +#: utils/misc/guc_tables.c:1524 msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty." msgstr "Por omisión, los registros de conexión sólo muestran la dirección IP del host que establece la conexión. Si desea que se despliegue el nombre del host puede activar esta opción, pero dependiendo de su configuración de resolución de nombres esto puede imponer una penalización de rendimiento no despreciable." -#: utils/misc/guc_tables.c:1531 +#: utils/misc/guc_tables.c:1535 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "Tratar expr=NULL como expr IS NULL." -#: utils/misc/guc_tables.c:1532 +#: utils/misc/guc_tables.c:1536 msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)." msgstr "Cuando está activado, expresiones de la forma expr = NULL (o NULL = expr) son tratadas como expr IS NULL, esto es, retornarán verdadero si expr es evaluada al valor nulo, y falso en caso contrario. El comportamiento correcto de expr = NULL es retornar siempre null (desconocido)." -#: utils/misc/guc_tables.c:1544 -msgid "Enables per-database user names." -msgstr "Activar el uso de nombre de usuario locales a cada base de datos." - -#: utils/misc/guc_tables.c:1553 +#: utils/misc/guc_tables.c:1548 msgid "Sets the default read-only status of new transactions." msgstr "Estado por omisión de sólo lectura de nuevas transacciones." -#: utils/misc/guc_tables.c:1563 +#: utils/misc/guc_tables.c:1558 msgid "Sets the current transaction's read-only status." msgstr "Activa el estado de sólo lectura de la transacción en curso." -#: utils/misc/guc_tables.c:1573 +#: utils/misc/guc_tables.c:1568 msgid "Sets the default deferrable status of new transactions." msgstr "Estado por omisión de postergable de nuevas transacciones." -#: utils/misc/guc_tables.c:1582 +#: utils/misc/guc_tables.c:1577 msgid "Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures." msgstr "Si está activo, las transacciones serializables de sólo lectura serán pausadas hasta que puedan ejecutarse sin posibles fallas de serialización." -#: utils/misc/guc_tables.c:1592 +#: utils/misc/guc_tables.c:1587 msgid "Enable row security." msgstr "Activar seguridad de registros." -#: utils/misc/guc_tables.c:1593 +#: utils/misc/guc_tables.c:1588 msgid "When enabled, row security will be applied to all users." msgstr "Cuando está activada, la seguridad de registros se aplicará a todos los usuarios." -#: utils/misc/guc_tables.c:1601 +#: utils/misc/guc_tables.c:1596 msgid "Check routine bodies during CREATE FUNCTION and CREATE PROCEDURE." msgstr "Verificar definición de rutinas durante CREATE FUNCTION y CREATE PROCEDURE." -#: utils/misc/guc_tables.c:1610 +#: utils/misc/guc_tables.c:1605 msgid "Enable input of NULL elements in arrays." msgstr "Habilita el ingreso de elementos nulos en arrays." -#: utils/misc/guc_tables.c:1611 +#: utils/misc/guc_tables.c:1606 msgid "When turned on, unquoted NULL in an array input value means a null value; otherwise it is taken literally." msgstr "Cuando está activo, un valor NULL sin comillas en la entrada de un array significa un valor nulo; en caso contrario es tomado literalmente." -#: utils/misc/guc_tables.c:1627 +#: utils/misc/guc_tables.c:1622 msgid "WITH OIDS is no longer supported; this can only be false." msgstr "WITH OIDS ya no está soportado; esto sólo puede ser false." -#: utils/misc/guc_tables.c:1637 -msgid "Start a subprocess to capture stderr output and/or csvlogs into log files." -msgstr "Lanzar un subproceso para capturar stderr y/o logs CSV en archivos de log." +#: utils/misc/guc_tables.c:1632 +#| msgid "Start a subprocess to capture stderr output and/or csvlogs into log files." +msgid "Start a subprocess to capture stderr, csvlog and/or jsonlog into log files." +msgstr "Lanzar un subproceso para capturar stderr, csvlog y/o jsonlog en archivos de log." -#: utils/misc/guc_tables.c:1646 +#: utils/misc/guc_tables.c:1641 msgid "Truncate existing log files of same name during log rotation." msgstr "Truncar archivos de log del mismo nombre durante la rotación." -#: utils/misc/guc_tables.c:1657 +#: utils/misc/guc_tables.c:1652 msgid "Emit information about resource usage in sorting." msgstr "Emitir información acerca de uso de recursos durante los ordenamientos." -#: utils/misc/guc_tables.c:1671 +#: utils/misc/guc_tables.c:1666 msgid "Generate debugging output for synchronized scanning." msgstr "Generar salida de depuración para recorrido sincronizado." -#: utils/misc/guc_tables.c:1686 +#: utils/misc/guc_tables.c:1681 msgid "Enable bounded sorting using heap sort." msgstr "Activar ordenamiento acotado usando «heap sort»." -#: utils/misc/guc_tables.c:1699 +#: utils/misc/guc_tables.c:1694 msgid "Emit WAL-related debugging output." msgstr "Activar salida de depuración de WAL." -#: utils/misc/guc_tables.c:1711 +#: utils/misc/guc_tables.c:1706 msgid "Shows whether datetimes are integer based." msgstr "Mostrar si las fechas y horas se basan en tipos enteros." -#: utils/misc/guc_tables.c:1722 +#: utils/misc/guc_tables.c:1717 msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive." msgstr "Define que los nombres de usuario Kerberos y GSSAPI deberían ser tratados sin distinción de mayúsculas." -#: utils/misc/guc_tables.c:1732 -#, fuzzy -#| msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive." +#: utils/misc/guc_tables.c:1727 msgid "Sets whether GSSAPI delegation should be accepted from the client." -msgstr "Define que los nombres de usuario Kerberos y GSSAPI deberían ser tratados sin distinción de mayúsculas." +msgstr "Define si la delegación GSSAPI debería ser aceptada por el cliente." -#: utils/misc/guc_tables.c:1742 +#: utils/misc/guc_tables.c:1737 msgid "Warn about backslash escapes in ordinary string literals." msgstr "Avisa acerca de escapes de backslash en literales de cadena corrientes." -#: utils/misc/guc_tables.c:1752 +#: utils/misc/guc_tables.c:1747 msgid "Causes '...' strings to treat backslashes literally." msgstr "Provoca que las cadenas '...' traten las barras inclinadas inversas (\\) en forma literal." -#: utils/misc/guc_tables.c:1763 +#: utils/misc/guc_tables.c:1758 msgid "Enable synchronized sequential scans." msgstr "Permitir la sincronización de recorridos secuenciales." -#: utils/misc/guc_tables.c:1773 +#: utils/misc/guc_tables.c:1768 msgid "Sets whether to include or exclude transaction with recovery target." msgstr "Define si incluir o excluir la transacción con el destino de recuperación." -#: utils/misc/guc_tables.c:1783 +#: utils/misc/guc_tables.c:1778 +msgid "Starts the WAL summarizer process to enable incremental backup." +msgstr "Inicia el proceso sumarizador de WAL para activar backups incrementales." + +#: utils/misc/guc_tables.c:1788 msgid "Allows connections and queries during recovery." msgstr "Permite conexiones y consultas durante la recuperación." -#: utils/misc/guc_tables.c:1793 +#: utils/misc/guc_tables.c:1798 msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts." msgstr "Permite retroalimentación desde un hot standby hacia el primario que evitará conflictos en consultas." -#: utils/misc/guc_tables.c:1803 +#: utils/misc/guc_tables.c:1808 msgid "Shows whether hot standby is currently active." msgstr "Muestra si hot standby está activo actualmente." -#: utils/misc/guc_tables.c:1814 +#: utils/misc/guc_tables.c:1819 msgid "Allows modifications of the structure of system tables." msgstr "Permite modificaciones de la estructura de las tablas del sistema." -#: utils/misc/guc_tables.c:1825 +#: utils/misc/guc_tables.c:1830 msgid "Disables reading from system indexes." msgstr "Deshabilita lectura de índices del sistema." -#: utils/misc/guc_tables.c:1826 +#: utils/misc/guc_tables.c:1831 msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness." msgstr "No evita la actualización de índices, así que es seguro. Lo peor que puede ocurrir es lentitud del sistema." -#: utils/misc/guc_tables.c:1837 +#: utils/misc/guc_tables.c:1842 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "Permite tablespaces directamente dentro de pg_tblspc, para pruebas." -#: utils/misc/guc_tables.c:1848 +#: utils/misc/guc_tables.c:1853 msgid "Enables backward compatibility mode for privilege checks on large objects." msgstr "Activa el modo de compatibilidad con versiones anteriores de las comprobaciones de privilegios de objetos grandes." -#: utils/misc/guc_tables.c:1849 +#: utils/misc/guc_tables.c:1854 msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0." msgstr "Omite las comprobaciones de privilegios cuando se leen o modifican los objetos grandes, para compatibilidad con versiones de PostgreSQL anteriores a 9.0." -#: utils/misc/guc_tables.c:1859 +#: utils/misc/guc_tables.c:1864 msgid "When generating SQL fragments, quote all identifiers." msgstr "Al generar fragmentos SQL, entrecomillar todos los identificadores." -#: utils/misc/guc_tables.c:1869 +#: utils/misc/guc_tables.c:1874 msgid "Shows whether data checksums are turned on for this cluster." msgstr "Indica si las sumas de verificación están activas en este cluster." -#: utils/misc/guc_tables.c:1880 +#: utils/misc/guc_tables.c:1885 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "Agregar número de secuencia a mensajes syslog para evitar supresión de duplicados." -#: utils/misc/guc_tables.c:1890 +#: utils/misc/guc_tables.c:1895 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "Dividir mensajes enviados a syslog en líneas y que quepan en 1024 bytes." -#: utils/misc/guc_tables.c:1900 +#: utils/misc/guc_tables.c:1905 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "Controla si los Gather y Gather Merge también ejecutan subplanes." -#: utils/misc/guc_tables.c:1901 +#: utils/misc/guc_tables.c:1906 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "¿Deben los nodos de recolección ejecutar subplanes o sólo recolectar tuplas?" -#: utils/misc/guc_tables.c:1911 +#: utils/misc/guc_tables.c:1916 msgid "Allow JIT compilation." msgstr "Permitir compilación JIT." -#: utils/misc/guc_tables.c:1922 +#: utils/misc/guc_tables.c:1927 msgid "Register JIT-compiled functions with debugger." msgstr "Registrar las funciones JIT compiladas con el depurador." -#: utils/misc/guc_tables.c:1939 +#: utils/misc/guc_tables.c:1944 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "Escribe el bitcode LLVM para facilitar depuración de JIT." -#: utils/misc/guc_tables.c:1950 +#: utils/misc/guc_tables.c:1955 msgid "Allow JIT compilation of expressions." msgstr "Permitir compilación JIT de expresiones." -#: utils/misc/guc_tables.c:1961 +#: utils/misc/guc_tables.c:1966 msgid "Register JIT-compiled functions with perf profiler." msgstr "Registrar las funciones JIT compiladas con el analizador «perf»." -#: utils/misc/guc_tables.c:1978 +#: utils/misc/guc_tables.c:1983 msgid "Allow JIT compilation of tuple deforming." msgstr "Permitir compilación JIT de deformación de tuplas." -#: utils/misc/guc_tables.c:1989 +#: utils/misc/guc_tables.c:1994 msgid "Whether to continue running after a failure to sync data files." msgstr "Si continuar ejecutando después de una falla al sincronizar archivos de datos." -#: utils/misc/guc_tables.c:1998 +#: utils/misc/guc_tables.c:2003 msgid "Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured." msgstr "Definir si un receptor de WAL debe crear un slot de replicación temporal en caso de no haber configurado un slot permanente." -#: utils/misc/guc_tables.c:2016 -#, fuzzy -#| msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." +#: utils/misc/guc_tables.c:2012 +msgid "Enables event triggers." +msgstr "Activa “triggers” por evento." + +#: utils/misc/guc_tables.c:2013 +msgid "When enabled, event triggers will fire for all applicable statements." +msgstr "Cuando se activa, los “triggers” por evento se ejecutarán para todas las sentencias aplicables." + +#: utils/misc/guc_tables.c:2022 +msgid "Enables a physical standby to synchronize logical failover replication slots from the primary server." +msgstr "Habilita un standby físico para sincronizar slots de “failover” de replicación lógica desde el servidor primario." + +#: utils/misc/guc_tables.c:2040 msgid "Sets the amount of time to wait before forcing a switch to the next WAL file." -msgstr "Define el tiempo a esperar antes de reintentar obtener WAL después de un intento fallido." +msgstr "Define el tiempo a esperar antes de forzar un cambio al siguiente archivo WAL." -#: utils/misc/guc_tables.c:2027 -#, fuzzy -#| msgid "Sets the maximum time to wait for WAL replication." +#: utils/misc/guc_tables.c:2051 msgid "Sets the amount of time to wait after authentication on connection startup." -msgstr "Define el tiempo máximo a esperar la replicación de WAL." +msgstr "Define el tiempo máximo a esperar la autentificación durante el establecimiento de una conexión." -#: utils/misc/guc_tables.c:2029 utils/misc/guc_tables.c:2663 +#: utils/misc/guc_tables.c:2053 utils/misc/guc_tables.c:2780 msgid "This allows attaching a debugger to the process." msgstr "Esto permite adjuntar un depurador al proceso." -#: utils/misc/guc_tables.c:2038 +#: utils/misc/guc_tables.c:2062 msgid "Sets the default statistics target." msgstr "Definir el valor por omisión de toma de estadísticas." -#: utils/misc/guc_tables.c:2039 +#: utils/misc/guc_tables.c:2063 msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS." msgstr "Esto se aplica a columnas de tablas que no tienen un valor definido a través de ALTER TABLE SET STATISTICS." -#: utils/misc/guc_tables.c:2048 +#: utils/misc/guc_tables.c:2072 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "Tamaño de lista de FROM a partir del cual subconsultas no serán colapsadas." -#: utils/misc/guc_tables.c:2050 +#: utils/misc/guc_tables.c:2074 msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items." msgstr "El planner mezclará subconsultas en consultas de nivel superior si la lista FROM resultante es menor que esta cantidad de ítems." -#: utils/misc/guc_tables.c:2061 +#: utils/misc/guc_tables.c:2085 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "Tamaño de lista de FROM a partir del cual constructos JOIN no serán aplanados." -#: utils/misc/guc_tables.c:2063 +#: utils/misc/guc_tables.c:2087 msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result." msgstr "El planner aplanará constructos JOIN explícitos en listas de ítems FROM siempre que la lista resultante no tenga más que esta cantidad de ítems." -#: utils/misc/guc_tables.c:2074 +#: utils/misc/guc_tables.c:2098 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "Umbral de ítems en FROM a partir del cual se usará GEQO." -#: utils/misc/guc_tables.c:2084 +#: utils/misc/guc_tables.c:2108 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "GEQO: effort se usa para determinar los valores por defecto para otros parámetros." -#: utils/misc/guc_tables.c:2094 +#: utils/misc/guc_tables.c:2118 msgid "GEQO: number of individuals in the population." msgstr "GEQO: número de individuos en una población." -#: utils/misc/guc_tables.c:2095 utils/misc/guc_tables.c:2105 +#: utils/misc/guc_tables.c:2119 utils/misc/guc_tables.c:2129 msgid "Zero selects a suitable default value." msgstr "Cero selecciona un valor por omisión razonable." -#: utils/misc/guc_tables.c:2104 +#: utils/misc/guc_tables.c:2128 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: número de iteraciones del algoritmo." -#: utils/misc/guc_tables.c:2116 +#: utils/misc/guc_tables.c:2140 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "Define el tiempo a esperar un lock antes de buscar un deadlock." -#: utils/misc/guc_tables.c:2127 +#: utils/misc/guc_tables.c:2151 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data." msgstr "Define el máximo retardo antes de cancelar consultas cuando un servidor hot standby está procesando datos de WAL archivado." -#: utils/misc/guc_tables.c:2138 +#: utils/misc/guc_tables.c:2162 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data." msgstr "Define el máximo retardo antes de cancelar consultas cuando un servidor hot standby está procesando datos de WAL en flujo." -#: utils/misc/guc_tables.c:2149 +#: utils/misc/guc_tables.c:2173 msgid "Sets the minimum delay for applying changes during recovery." msgstr "Define el retraso mínimo para aplicar cambios durante la recuperación." -#: utils/misc/guc_tables.c:2160 +#: utils/misc/guc_tables.c:2184 msgid "Sets the maximum interval between WAL receiver status reports to the sending server." msgstr "Define el intervalo máximo entre reportes de estado que el receptor de WAL envía al servidor origen." -#: utils/misc/guc_tables.c:2171 +#: utils/misc/guc_tables.c:2195 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "Define el máximo tiempo de espera para recibir datos desde el servidor origen." -#: utils/misc/guc_tables.c:2182 +#: utils/misc/guc_tables.c:2206 msgid "Sets the maximum number of concurrent connections." msgstr "Número máximo de conexiones concurrentes." -#: utils/misc/guc_tables.c:2193 +#: utils/misc/guc_tables.c:2217 msgid "Sets the number of connection slots reserved for superusers." msgstr "Número de conexiones reservadas para superusuarios." -#: utils/misc/guc_tables.c:2203 -#, fuzzy -#| msgid "Sets the number of connection slots reserved for superusers." +#: utils/misc/guc_tables.c:2227 msgid "Sets the number of connection slots reserved for roles with privileges of pg_use_reserved_connections." -msgstr "Número de conexiones reservadas para superusuarios." +msgstr "Número de conexiones reservadas para con privilegios de pg_use_reserved_connections." -#: utils/misc/guc_tables.c:2214 +#: utils/misc/guc_tables.c:2238 msgid "Amount of dynamic shared memory reserved at startup." msgstr "Cantidad de memoria compartida dinámica reservada al iniciar." -#: utils/misc/guc_tables.c:2229 +#: utils/misc/guc_tables.c:2253 msgid "Sets the number of shared memory buffers used by the server." msgstr "Número de búfers de memoria compartida usados por el servidor." -#: utils/misc/guc_tables.c:2240 +#: utils/misc/guc_tables.c:2264 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." -msgstr "" +msgstr "Define el tamaño del pool de búfers para VACUUM, ANALYZE y autovacuum." -#: utils/misc/guc_tables.c:2251 +#: utils/misc/guc_tables.c:2275 msgid "Shows the size of the server's main shared memory area (rounded up to the nearest MB)." msgstr "Muestra el tamaño del área principal de memoria compartida del servidor (redondeado al número de MB más cercano)." -#: utils/misc/guc_tables.c:2262 -#, fuzzy -#| msgid "Sets the number of disk-page buffers in shared memory for WAL." +#: utils/misc/guc_tables.c:2286 msgid "Shows the number of huge pages needed for the main shared memory area." -msgstr "Búfers en memoria compartida para páginas de WAL." +msgstr "Muestra la cantidad de “huge pages” necesarias para el área de memoria compartida principal." -#: utils/misc/guc_tables.c:2263 +#: utils/misc/guc_tables.c:2287 msgid "-1 indicates that the value could not be determined." msgstr "-1 indica que el valor no pudo ser determinado." -#: utils/misc/guc_tables.c:2273 +#: utils/misc/guc_tables.c:2297 +msgid "Sets the size of the dedicated buffer pool used for the commit timestamp cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de timestamps de commit." + +#: utils/misc/guc_tables.c:2298 utils/misc/guc_tables.c:2353 +#: utils/misc/guc_tables.c:2364 +msgid "Specify 0 to have this value determined as a fraction of shared_buffers." +msgstr "Especifique 0 para que este valor sea determinado como fracción de shared_buffers." + +#: utils/misc/guc_tables.c:2308 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact member cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de miembros de MultiXact." + +#: utils/misc/guc_tables.c:2319 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact offset cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de offsets de MultiXact." + +#: utils/misc/guc_tables.c:2330 +msgid "Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY message cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de mensajes LISTEN/NOTIFY." + +#: utils/misc/guc_tables.c:2341 +msgid "Sets the size of the dedicated buffer pool used for the serializable transaction cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de transacciones serializables." + +#: utils/misc/guc_tables.c:2352 +msgid "Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de subtransacciones." + +#: utils/misc/guc_tables.c:2363 +msgid "Sets the size of the dedicated buffer pool used for the transaction status cache." +msgstr "Define el tamaño del pool de búfers dedicado al caché de estatus de transacciones." + +#: utils/misc/guc_tables.c:2374 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "Número de búfers de memoria temporal usados por cada sesión." -#: utils/misc/guc_tables.c:2284 +#: utils/misc/guc_tables.c:2385 msgid "Sets the TCP port the server listens on." msgstr "Puerto TCP en el cual escuchará el servidor." -#: utils/misc/guc_tables.c:2294 +#: utils/misc/guc_tables.c:2395 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Privilegios de acceso al socket Unix." -#: utils/misc/guc_tables.c:2295 +#: utils/misc/guc_tables.c:2396 msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Los sockets de dominio Unix usan la funcionalidad de permisos de archivos estándar de Unix. Se espera que el valor de esta opción sea una especificación numérica de modo, en la forma aceptada por las llamadas a sistema chmod y umask. Para usar el modo octal acostumbrado, comience el número con un 0 (cero)." -#: utils/misc/guc_tables.c:2309 +#: utils/misc/guc_tables.c:2410 msgid "Sets the file permissions for log files." msgstr "Define los privilegios para los archivos del registro del servidor." -#: utils/misc/guc_tables.c:2310 +#: utils/misc/guc_tables.c:2411 msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Se espera que el valor de esta opción sea una especificación numérica de modo, en la forma aceptada por las llamadas a sistema chmod y umask. Para usar el modo octal acostumbrado, comience el número con un 0 (cero)." -#: utils/misc/guc_tables.c:2324 +#: utils/misc/guc_tables.c:2425 msgid "Shows the mode of the data directory." msgstr "Muestra el modo del directorio de datos." -#: utils/misc/guc_tables.c:2325 +#: utils/misc/guc_tables.c:2426 msgid "The parameter value is a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "El valor del parámetro es una especificación numérica de modo, en la forma aceptada por las llamadas a sistema chmod y umask. (Para usar el modo octal acostumbrado, comience el número con un 0 (cero).)" -#: utils/misc/guc_tables.c:2338 +#: utils/misc/guc_tables.c:2439 msgid "Sets the maximum memory to be used for query workspaces." msgstr "Establece el límite de memoria que se usará para espacios de trabajo de consultas." -#: utils/misc/guc_tables.c:2339 +#: utils/misc/guc_tables.c:2440 msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files." msgstr "Esta es la cantidad máxima de memoria que se usará para operaciones internas de ordenamiento y tablas de hashing, antes de comenzar a usar archivos temporales en disco." -#: utils/misc/guc_tables.c:2351 +#: utils/misc/guc_tables.c:2457 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "Establece el límite de memoria que se usará para operaciones de mantención." -#: utils/misc/guc_tables.c:2352 +#: utils/misc/guc_tables.c:2458 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "Esto incluye operaciones como VACUUM y CREATE INDEX." -#: utils/misc/guc_tables.c:2362 +#: utils/misc/guc_tables.c:2468 msgid "Sets the maximum memory to be used for logical decoding." msgstr "Establece el límite de memoria que se usará para decodificación lógica." -#: utils/misc/guc_tables.c:2363 +#: utils/misc/guc_tables.c:2469 msgid "This much memory can be used by each internal reorder buffer before spilling to disk." msgstr "Esta es la cantidad máxima de memoria que puede ser usada para cada búfer interno de ordenamiento, antes de comenzar a usar disco." -#: utils/misc/guc_tables.c:2379 +#: utils/misc/guc_tables.c:2485 msgid "Sets the maximum stack depth, in kilobytes." msgstr "Establece el tamaño máximo del stack, en kilobytes." -#: utils/misc/guc_tables.c:2390 +#: utils/misc/guc_tables.c:2496 msgid "Limits the total size of all temporary files used by each process." msgstr "Limita el tamaño total de todos los archivos temporales usados en cada proceso." -#: utils/misc/guc_tables.c:2391 +#: utils/misc/guc_tables.c:2497 msgid "-1 means no limit." msgstr "-1 significa sin límite." -#: utils/misc/guc_tables.c:2401 +#: utils/misc/guc_tables.c:2507 msgid "Vacuum cost for a page found in the buffer cache." msgstr "Costo de Vacuum de una página encontrada en el buffer." -#: utils/misc/guc_tables.c:2411 +#: utils/misc/guc_tables.c:2517 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "Costo de Vacuum de una página no encontrada en el cache." -#: utils/misc/guc_tables.c:2421 +#: utils/misc/guc_tables.c:2527 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "Costo de Vacuum de una página ensuciada por vacuum." -#: utils/misc/guc_tables.c:2431 +#: utils/misc/guc_tables.c:2537 msgid "Vacuum cost amount available before napping." msgstr "Costo de Vacuum disponible antes de descansar." -#: utils/misc/guc_tables.c:2441 +#: utils/misc/guc_tables.c:2547 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "Costo de Vacuum disponible antes de descansar, para autovacuum." -#: utils/misc/guc_tables.c:2451 +#: utils/misc/guc_tables.c:2557 msgid "Sets the maximum number of simultaneously open files for each server process." msgstr "Define la cantidad máxima de archivos abiertos por cada subproceso." -#: utils/misc/guc_tables.c:2464 +#: utils/misc/guc_tables.c:2570 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "Define la cantidad máxima de transacciones preparadas simultáneas." -#: utils/misc/guc_tables.c:2475 +#: utils/misc/guc_tables.c:2581 msgid "Sets the minimum OID of tables for tracking locks." msgstr "Define el OID mínimo para hacer seguimiento de locks." -#: utils/misc/guc_tables.c:2476 +#: utils/misc/guc_tables.c:2582 msgid "Is used to avoid output on system tables." msgstr "Se usa para evitar salida excesiva por tablas de sistema." -#: utils/misc/guc_tables.c:2485 +#: utils/misc/guc_tables.c:2591 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "Define el OID de una tabla con trazado incondicional de locks." -#: utils/misc/guc_tables.c:2497 +#: utils/misc/guc_tables.c:2603 msgid "Sets the maximum allowed duration of any statement." msgstr "Define la duración máxima permitida de sentencias." -#: utils/misc/guc_tables.c:2498 utils/misc/guc_tables.c:2509 -#: utils/misc/guc_tables.c:2520 utils/misc/guc_tables.c:2531 +#: utils/misc/guc_tables.c:2604 utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2626 utils/misc/guc_tables.c:2637 +#: utils/misc/guc_tables.c:2648 msgid "A value of 0 turns off the timeout." msgstr "Un valor de 0 desactiva el máximo." -#: utils/misc/guc_tables.c:2508 +#: utils/misc/guc_tables.c:2614 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "Define la duración máxima permitida de cualquier espera por un lock." -#: utils/misc/guc_tables.c:2519 +#: utils/misc/guc_tables.c:2625 msgid "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "Define el tiempo máximo permitido de inactividad entre consultas, cuando están dentro de una transacción." -#: utils/misc/guc_tables.c:2530 +#: utils/misc/guc_tables.c:2636 +msgid "Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)." +msgstr "Define la duración máxima permitida cualquier transacción dentro de una sesión (no una transacción preparada)." + +#: utils/misc/guc_tables.c:2647 msgid "Sets the maximum allowed idle time between queries, when not in a transaction." msgstr "Define el tiempo máximo permitido de inactividad entre consultas, cuando no están dentro de una transacción." -#: utils/misc/guc_tables.c:2541 +#: utils/misc/guc_tables.c:2658 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "Mínima edad a la cual VACUUM debería congelar (freeze) una fila de una tabla." -#: utils/misc/guc_tables.c:2551 +#: utils/misc/guc_tables.c:2668 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "Edad a la cual VACUUM debería recorrer una tabla completa para congelar (freeze) las filas." -#: utils/misc/guc_tables.c:2561 +#: utils/misc/guc_tables.c:2678 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "Mínima edad a la cual VACUUM debería congelar (freeze) el multixact en una fila." -#: utils/misc/guc_tables.c:2571 +#: utils/misc/guc_tables.c:2688 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "Edad de multixact a la cual VACUUM debería recorrer una tabla completa para congelar (freeze) las filas." -#: utils/misc/guc_tables.c:2581 +#: utils/misc/guc_tables.c:2698 msgid "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." -msgstr "Edad a la cual VACUUM debería activar el modo failsafe para evitar pérdida de servicio por reciclaje (wraparound)." +msgstr "Edad a la cual VACUUM debería activar el modo failsafe para evitar pérdida de servicio por ”wraparound”." -#: utils/misc/guc_tables.c:2590 +#: utils/misc/guc_tables.c:2707 msgid "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage." -msgstr "Edad de multixact a la cual VACUUM debería activar el modo failsafe para evitar pérdida de servicio por reciclaje (wraparound)." +msgstr "Edad de multixact a la cual VACUUM debería activar el modo failsafe para evitar pérdida de servicio por “wraparound”." -#: utils/misc/guc_tables.c:2603 +#: utils/misc/guc_tables.c:2720 msgid "Sets the maximum number of locks per transaction." -msgstr "Cantidad máxima de candados (locks) por transacción." +msgstr "Cantidad máxima de “locks” por transacción." -#: utils/misc/guc_tables.c:2604 -msgid "The shared lock table is sized on the assumption that at most max_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "" +#: utils/misc/guc_tables.c:2721 +msgid "The shared lock table is sized on the assumption that at most \"max_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "La tabla compartida de “locks” se dimensiona bajo la suposoción que a lo más «max_locks_per_transaction» objetos por cada proceso servidor o transacción preparada necesitarán ser bloqueados en un momento dado." -#: utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2732 msgid "Sets the maximum number of predicate locks per transaction." -msgstr "Cantidad máxima de candados (locks) de predicado por transacción." +msgstr "Cantidad máxima de “locks” de predicado por transacción." -#: utils/misc/guc_tables.c:2616 -msgid "The shared predicate lock table is sized on the assumption that at most max_pred_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "" +#: utils/misc/guc_tables.c:2733 +msgid "The shared predicate lock table is sized on the assumption that at most \"max_pred_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "La tabla compartida de “locks” de predicados se dimensiona bajo la suposición de que a lo más «max_pred_locks_per_transaction» objetos por cada proceso servidor o transacción preparada necesitarán ser bloqueados en un momento dado." -#: utils/misc/guc_tables.c:2627 +#: utils/misc/guc_tables.c:2744 msgid "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "Cantidad máxima de páginas y tuplas bloqueadas por predicado." -#: utils/misc/guc_tables.c:2628 +#: utils/misc/guc_tables.c:2745 msgid "If more than this total of pages and tuples in the same relation are locked by a connection, those locks are replaced by a relation-level lock." msgstr "Si más que este total de páginas y tuplas en la misma relación están bloqueadas por una conexión, esos locks son reemplazados por un lock a nivel de relación." -#: utils/misc/guc_tables.c:2638 +#: utils/misc/guc_tables.c:2755 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "Cantidad máxima de locks de predicado por página." -#: utils/misc/guc_tables.c:2639 +#: utils/misc/guc_tables.c:2756 msgid "If more than this number of tuples on the same page are locked by a connection, those locks are replaced by a page-level lock." msgstr "Si más que este número de tuplas de la misma página están bloqueadas por una conexión, esos locks son reemplazados por un lock a nivel de página." -#: utils/misc/guc_tables.c:2649 +#: utils/misc/guc_tables.c:2766 msgid "Sets the maximum allowed time to complete client authentication." msgstr "Define el tiempo máximo para completar proceso de autentificación." -#: utils/misc/guc_tables.c:2661 -#, fuzzy -#| msgid "Sets the maximum time to wait for WAL replication." +#: utils/misc/guc_tables.c:2778 msgid "Sets the amount of time to wait before authentication on connection startup." -msgstr "Define el tiempo máximo a esperar la replicación de WAL." +msgstr "Define el tiempo máximo a esperar antes de la autentificación al abrir una conexión." -#: utils/misc/guc_tables.c:2673 +#: utils/misc/guc_tables.c:2790 +msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." +msgstr "Cantidad máxima de páginas dedicadas a la cola de NOTIFY / LISTEN." + +#: utils/misc/guc_tables.c:2800 msgid "Buffer size for reading ahead in the WAL during recovery." -msgstr "" +msgstr "Tamaño de búfer para lectura adelantada de WAL durante la recuperación." -#: utils/misc/guc_tables.c:2674 +#: utils/misc/guc_tables.c:2801 msgid "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." -msgstr "" +msgstr "Máxima distancia que leer adelantado en el WAL para pre-cargar bloques de datos referenciados." -#: utils/misc/guc_tables.c:2684 +#: utils/misc/guc_tables.c:2811 msgid "Sets the size of WAL files held for standby servers." msgstr "Establece el tamaño de los archivos de WAL retenidos para los servidores standby." -#: utils/misc/guc_tables.c:2695 +#: utils/misc/guc_tables.c:2822 msgid "Sets the minimum size to shrink the WAL to." msgstr "Define el tamaño mínimo al cual reducir el WAL." -#: utils/misc/guc_tables.c:2707 +#: utils/misc/guc_tables.c:2834 msgid "Sets the WAL size that triggers a checkpoint." msgstr "Define el tamaño de WAL que desencadena un checkpoint." -#: utils/misc/guc_tables.c:2719 +#: utils/misc/guc_tables.c:2846 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "Define el tiempo máximo entre puntos de control de WAL automáticos." -#: utils/misc/guc_tables.c:2730 +#: utils/misc/guc_tables.c:2857 msgid "Sets the maximum time before warning if checkpoints triggered by WAL volume happen too frequently." msgstr "Define el máximo tiempo antes de emitir un advertencia si los checkpoints iniciados a causa del volumen de WAL ocurren con demasiada frecuencia." -#: utils/misc/guc_tables.c:2732 +#: utils/misc/guc_tables.c:2859 msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. Zero turns off the warning." -msgstr "" +msgstr "Escribe una advertencia al log del servidor si los checkpoints causados por el llenado de segmentos de WAL occur más frecuentemente que esta cantidad de tiempo. Cero inhabilita la advertencia." -#: utils/misc/guc_tables.c:2745 utils/misc/guc_tables.c:2963 -#: utils/misc/guc_tables.c:3003 +#: utils/misc/guc_tables.c:2872 utils/misc/guc_tables.c:3090 +#: utils/misc/guc_tables.c:3144 msgid "Number of pages after which previously performed writes are flushed to disk." msgstr "Número de páginas después del cual las escrituras previamente ejecutadas se sincronizan a disco." -#: utils/misc/guc_tables.c:2756 +#: utils/misc/guc_tables.c:2883 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "Búfers en memoria compartida para páginas de WAL." -#: utils/misc/guc_tables.c:2767 +#: utils/misc/guc_tables.c:2884 +msgid "Specify -1 to have this value determined as a fraction of shared_buffers." +msgstr "Especifique -1 para que este valor sea determinado como fracción de shared_buffers." + +#: utils/misc/guc_tables.c:2894 msgid "Time between WAL flushes performed in the WAL writer." msgstr "Tiempo entre sincronizaciones de WAL ejecutadas por el proceso escritor de WAL." -#: utils/misc/guc_tables.c:2778 +#: utils/misc/guc_tables.c:2905 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "Cantidad de WAL escrito por el proceso escritor de WAL que desencadena una sincronización (flush)." -#: utils/misc/guc_tables.c:2789 +#: utils/misc/guc_tables.c:2916 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "Tamaño mínimo del nuevo archivo para hacer fsync en lugar de escribir WAL." -#: utils/misc/guc_tables.c:2800 +#: utils/misc/guc_tables.c:2927 msgid "Sets the maximum number of simultaneously running WAL sender processes." -msgstr "Define la cantidad máxima de procesos «WAL sender» simultáneos." +msgstr "Define la cantidad máxima de procesos “WAL sender” simultáneos." -#: utils/misc/guc_tables.c:2811 +#: utils/misc/guc_tables.c:2938 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "Define la cantidad máxima de slots de replicación definidos simultáneamente." -#: utils/misc/guc_tables.c:2821 +#: utils/misc/guc_tables.c:2948 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "Define el tamaño máximo de WAL que puede ser reservado por slots de replicación." -#: utils/misc/guc_tables.c:2822 +#: utils/misc/guc_tables.c:2949 msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk." msgstr "Los slots de replicación serán invalidados, y los segmentos de WAL eliminados o reciclados, si se usa esta cantidad de espacio de disco en WAL." -#: utils/misc/guc_tables.c:2834 +#: utils/misc/guc_tables.c:2961 msgid "Sets the maximum time to wait for WAL replication." msgstr "Define el tiempo máximo a esperar la replicación de WAL." -#: utils/misc/guc_tables.c:2845 +#: utils/misc/guc_tables.c:2972 msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk." msgstr "Retardo en microsegundos entre completar una transacción y escribir WAL a disco." -#: utils/misc/guc_tables.c:2857 -#, fuzzy -#| msgid "Sets the maximum number of concurrent connections." -msgid "Sets the minimum number of concurrent open transactions required before performing commit_delay." -msgstr "Número máximo de conexiones concurrentes." +#: utils/misc/guc_tables.c:2984 +msgid "Sets the minimum number of concurrent open transactions required before performing \"commit_delay\"." +msgstr "Número mínimo de transacciones abiertas concurrentes antes de efectuar «commit_delay»." -#: utils/misc/guc_tables.c:2868 +#: utils/misc/guc_tables.c:2995 msgid "Sets the number of digits displayed for floating-point values." msgstr "Ajustar el número de dígitos mostrados para valores de coma flotante." -#: utils/misc/guc_tables.c:2869 +#: utils/misc/guc_tables.c:2996 msgid "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than zero selects precise output mode." msgstr "Esto afecta los tipos real, de doble precisión, y geométricos. Un valor del parámetro cero o negativo se agrega a la cantidad estándar de dígitos (FLT_DIG o DBL_DIG, según sea apropiado). Cualquier valor mayor que cero selecciona el modo de salida preciso." -#: utils/misc/guc_tables.c:2881 +#: utils/misc/guc_tables.c:3008 msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by log_statement_sample_rate." msgstr "Establece el tiempo mínimo de ejecución a partir del cual se registra una muestra de la sentencia. El muestreo es determinado por log_statement_sample_rate." -#: utils/misc/guc_tables.c:2884 +#: utils/misc/guc_tables.c:3011 msgid "Zero logs a sample of all queries. -1 turns this feature off." msgstr "Cero registra una muestra de todas las consultas. -1 desactiva esta funcionalidad." -#: utils/misc/guc_tables.c:2894 +#: utils/misc/guc_tables.c:3021 msgid "Sets the minimum execution time above which all statements will be logged." msgstr "Establece el tiempo mínimo de ejecución a partir del cual se registran todas las sentencias." -#: utils/misc/guc_tables.c:2896 +#: utils/misc/guc_tables.c:3023 msgid "Zero prints all queries. -1 turns this feature off." msgstr "Cero imprime todas las consultas. -1 desactiva esta funcionalidad." -#: utils/misc/guc_tables.c:2906 +#: utils/misc/guc_tables.c:3033 msgid "Sets the minimum execution time above which autovacuum actions will be logged." msgstr "Tiempo mínimo de ejecución a partir del cual se registran las acciones de autovacuum." -#: utils/misc/guc_tables.c:2908 +#: utils/misc/guc_tables.c:3035 msgid "Zero prints all actions. -1 turns autovacuum logging off." msgstr "Cero registra todas las acciones. -1 desactiva el registro de autovacuum." -#: utils/misc/guc_tables.c:2918 +#: utils/misc/guc_tables.c:3045 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements." msgstr "Define el largo máximo en bytes de valores de parámetros «bind» enviados al log al registrar sentencias." -#: utils/misc/guc_tables.c:2920 utils/misc/guc_tables.c:2932 +#: utils/misc/guc_tables.c:3047 utils/misc/guc_tables.c:3059 msgid "-1 to print values in full." msgstr "-1 para mostrar los valores completos." -#: utils/misc/guc_tables.c:2930 +#: utils/misc/guc_tables.c:3057 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements, on error." msgstr "Define el largo máximo en bytes de valores de parámetros «bind» enviados al log, en caso de error." -#: utils/misc/guc_tables.c:2942 +#: utils/misc/guc_tables.c:3069 msgid "Background writer sleep time between rounds." msgstr "Tiempo de descanso entre rondas del background writer" -#: utils/misc/guc_tables.c:2953 +#: utils/misc/guc_tables.c:3080 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "Número máximo de páginas LRU a escribir en cada ronda del background writer" -#: utils/misc/guc_tables.c:2976 +#: utils/misc/guc_tables.c:3103 msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem." msgstr "Cantidad máxima de peticiones simultáneas que pueden ser manejadas eficientemente por el sistema de disco." -#: utils/misc/guc_tables.c:2990 -msgid "A variant of effective_io_concurrency that is used for maintenance work." -msgstr "Una variante de effective_io_concurrency que se usa para tareas de mantención." +#: utils/misc/guc_tables.c:3117 +msgid "A variant of \"effective_io_concurrency\" that is used for maintenance work." +msgstr "Una variante de «effective_io_concurrency» que se usa para tareas de mantención." -#: utils/misc/guc_tables.c:3016 +#: utils/misc/guc_tables.c:3132 +msgid "Limit on the size of data reads and writes." +msgstr "Límite del tamaño de lecturas y escrituras de datos." + +#: utils/misc/guc_tables.c:3157 msgid "Maximum number of concurrent worker processes." msgstr "Número máximo de procesos ayudantes concurrentes." -#: utils/misc/guc_tables.c:3028 +#: utils/misc/guc_tables.c:3169 msgid "Maximum number of logical replication worker processes." msgstr "Número máximo de procesos ayudantes de replicación lógica." -#: utils/misc/guc_tables.c:3040 +#: utils/misc/guc_tables.c:3181 msgid "Maximum number of table synchronization workers per subscription." msgstr "Número máximo de procesos ayudantes de sincronización por suscripción." -#: utils/misc/guc_tables.c:3052 -#, fuzzy -#| msgid "Maximum number of table synchronization workers per subscription." +#: utils/misc/guc_tables.c:3193 msgid "Maximum number of parallel apply workers per subscription." -msgstr "Número máximo de procesos ayudantes de sincronización por suscripción." +msgstr "Número máximo de procesos ayudantes de “apply” por suscripción." -#: utils/misc/guc_tables.c:3062 -#, fuzzy -#| msgid "Sets the maximum time to wait for WAL replication." +#: utils/misc/guc_tables.c:3203 msgid "Sets the amount of time to wait before forcing log file rotation." -msgstr "Define el tiempo máximo a esperar la replicación de WAL." +msgstr "Define el tiempo a esperar antes de forzar la rotación del archivo de registro del servidor." -#: utils/misc/guc_tables.c:3074 -#, fuzzy -#| msgid "Sets the maximum WAL size that can be reserved by replication slots." +#: utils/misc/guc_tables.c:3215 msgid "Sets the maximum size a log file can reach before being rotated." -msgstr "Define el tamaño máximo de WAL que puede ser reservado por slots de replicación." +msgstr "Define el tamaño máximo que un archivo de registro del servidor puede alcanzar antes de ser rotado." -#: utils/misc/guc_tables.c:3086 +#: utils/misc/guc_tables.c:3227 msgid "Shows the maximum number of function arguments." msgstr "Muestra la cantidad máxima de argumentos de funciones." -#: utils/misc/guc_tables.c:3097 +#: utils/misc/guc_tables.c:3238 msgid "Shows the maximum number of index keys." msgstr "Muestra la cantidad máxima de claves de índices." -#: utils/misc/guc_tables.c:3108 +#: utils/misc/guc_tables.c:3249 msgid "Shows the maximum identifier length." msgstr "Muestra el largo máximo de identificadores." -#: utils/misc/guc_tables.c:3119 +#: utils/misc/guc_tables.c:3260 msgid "Shows the size of a disk block." msgstr "Muestra el tamaño de un bloque de disco." -#: utils/misc/guc_tables.c:3130 +#: utils/misc/guc_tables.c:3271 msgid "Shows the number of pages per disk file." msgstr "Muestra el número de páginas por archivo en disco." -#: utils/misc/guc_tables.c:3141 +#: utils/misc/guc_tables.c:3282 msgid "Shows the block size in the write ahead log." msgstr "Muestra el tamaño de bloque en el write-ahead log." -#: utils/misc/guc_tables.c:3152 +#: utils/misc/guc_tables.c:3293 msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "Define el tiempo a esperar antes de reintentar obtener WAL después de un intento fallido." -#: utils/misc/guc_tables.c:3164 +#: utils/misc/guc_tables.c:3305 msgid "Shows the size of write ahead log segments." msgstr "Muestra el tamaño de los segmentos de WAL." -#: utils/misc/guc_tables.c:3177 +#: utils/misc/guc_tables.c:3318 +msgid "Time for which WAL summary files should be kept." +msgstr "Período durante el cual se deberían conservar los archivos de sumarización de WAL." + +#: utils/misc/guc_tables.c:3331 msgid "Time to sleep between autovacuum runs." msgstr "Tiempo de descanso entre ejecuciones de autovacuum." -#: utils/misc/guc_tables.c:3187 +#: utils/misc/guc_tables.c:3341 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "Número mínimo de updates o deletes antes de ejecutar vacuum." -#: utils/misc/guc_tables.c:3196 +#: utils/misc/guc_tables.c:3350 msgid "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums." msgstr "Número mínimo de inserciones de tuplas antes de ejecutar vacuum, o -1 para desactivar vacuums por inserciones." -#: utils/misc/guc_tables.c:3205 +#: utils/misc/guc_tables.c:3359 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "Número mínimo de inserciones, actualizaciones y eliminaciones de tuplas antes de ejecutar analyze." -#: utils/misc/guc_tables.c:3215 +#: utils/misc/guc_tables.c:3369 msgid "Age at which to autovacuum a table to prevent transaction ID wraparound." -msgstr "Edad a la cual aplicar VACUUM automáticamente a una tabla para prevenir problemas por reciclaje de ID de transacción." +msgstr "Edad a la cual aplicar VACUUM automáticamente a una tabla para prevenir problemas por “wraparound” de ID de transacción." -#: utils/misc/guc_tables.c:3227 +#: utils/misc/guc_tables.c:3381 msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound." -msgstr "Edad de multixact a la cual aplicar VACUUM automáticamente a una tabla para prevenir problemas por reciclaje de ID de multixacts." +msgstr "Edad de multixact a la cual aplicar VACUUM automáticamente a una tabla para prevenir problemas por “wraparound” de ID de multixacts." -#: utils/misc/guc_tables.c:3237 +#: utils/misc/guc_tables.c:3391 msgid "Sets the maximum number of simultaneously running autovacuum worker processes." msgstr "Define la cantidad máxima de procesos «autovacuum worker» simultáneos." -#: utils/misc/guc_tables.c:3247 +#: utils/misc/guc_tables.c:3401 msgid "Sets the maximum number of parallel processes per maintenance operation." msgstr "Cantidad máxima de procesos ayudantes paralelos por operación de mantención." -#: utils/misc/guc_tables.c:3257 +#: utils/misc/guc_tables.c:3411 msgid "Sets the maximum number of parallel processes per executor node." msgstr "Cantidad máxima de locks de predicado por nodo de ejecución." -#: utils/misc/guc_tables.c:3268 +#: utils/misc/guc_tables.c:3422 msgid "Sets the maximum number of parallel workers that can be active at one time." msgstr "Define la cantidad máxima de procesos ayudantes que pueden estar activos en un momento dado." -#: utils/misc/guc_tables.c:3279 +#: utils/misc/guc_tables.c:3433 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "Establece el límite de memoria que cada proceso «autovacuum worker» usará." -#: utils/misc/guc_tables.c:3290 -msgid "Time before a snapshot is too old to read pages changed after the snapshot was taken." -msgstr "Tiempo antes de que un snapshot sea demasiado antiguo para leer páginas después de que el snapshot fue tomado." - -#: utils/misc/guc_tables.c:3291 -msgid "A value of -1 disables this feature." -msgstr "El valor -1 desactiva esta característica." - -#: utils/misc/guc_tables.c:3301 +#: utils/misc/guc_tables.c:3444 msgid "Time between issuing TCP keepalives." msgstr "Tiempo entre cada emisión de TCP keepalive." -#: utils/misc/guc_tables.c:3302 utils/misc/guc_tables.c:3313 -#: utils/misc/guc_tables.c:3437 +#: utils/misc/guc_tables.c:3445 utils/misc/guc_tables.c:3456 +#: utils/misc/guc_tables.c:3580 msgid "A value of 0 uses the system default." msgstr "Un valor 0 usa el valor por omisión del sistema." -#: utils/misc/guc_tables.c:3312 +#: utils/misc/guc_tables.c:3455 msgid "Time between TCP keepalive retransmits." msgstr "Tiempo entre retransmisiones TCP keepalive." -#: utils/misc/guc_tables.c:3323 +#: utils/misc/guc_tables.c:3466 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "La renegociación SSL ya no está soportada; esto sólo puede ser 0." -#: utils/misc/guc_tables.c:3334 +#: utils/misc/guc_tables.c:3477 msgid "Maximum number of TCP keepalive retransmits." msgstr "Cantidad máxima de retransmisiones TCP keepalive." -#: utils/misc/guc_tables.c:3335 +#: utils/misc/guc_tables.c:3478 msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default." -msgstr "" +msgstr "Número de retransmisiones consecutivas de keepalive que pueden ser perdidas antes que una conexión se considere muerta. Cero usa el valor por omisión del sistema." -#: utils/misc/guc_tables.c:3346 +#: utils/misc/guc_tables.c:3489 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "Define el máximo de resultados permitidos por búsquedas exactas con GIN." -#: utils/misc/guc_tables.c:3357 +#: utils/misc/guc_tables.c:3500 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "Define la suposición del optimizador sobre el tamaño total de los caches de datos." -#: utils/misc/guc_tables.c:3358 +#: utils/misc/guc_tables.c:3501 msgid "That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each." msgstr "Esto es, el tamaño total de caches (cache del kernel y búfers compartidos) usados por archivos de datos de PostgreSQL. Esto se mide en páginas de disco, que normalmente son de 8 kB cada una." -#: utils/misc/guc_tables.c:3369 +#: utils/misc/guc_tables.c:3512 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "Define la cantidad mínima de datos en una tabla para un recorrido paralelo." -#: utils/misc/guc_tables.c:3370 +#: utils/misc/guc_tables.c:3513 msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered." msgstr "Si el planificador estima que leerá un número de páginas de tabla demasiado pequeñas para alcanzar este límite, no se considerará una búsqueda paralela." -#: utils/misc/guc_tables.c:3380 +#: utils/misc/guc_tables.c:3523 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "Define la cantidad mínima de datos en un índice para un recorrido paralelo." -#: utils/misc/guc_tables.c:3381 +#: utils/misc/guc_tables.c:3524 msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered." msgstr "Si el planificador estima que leerá un número de páginas de índice demasiado pequeñas para alcanzar este límite, no se considerará una búsqueda paralela." -#: utils/misc/guc_tables.c:3392 +#: utils/misc/guc_tables.c:3535 msgid "Shows the server version as an integer." msgstr "Muestra la versión del servidor como un número entero." -#: utils/misc/guc_tables.c:3403 +#: utils/misc/guc_tables.c:3546 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "Registra el uso de archivos temporales que crezcan más allá de este número de kilobytes." -#: utils/misc/guc_tables.c:3404 +#: utils/misc/guc_tables.c:3547 msgid "Zero logs all files. The default is -1 (turning this feature off)." msgstr "Cero registra todos los archivos. El valor por omisión es -1 (lo cual desactiva el registro)." -#: utils/misc/guc_tables.c:3414 +#: utils/misc/guc_tables.c:3557 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "Tamaño reservado para pg_stat_activity.query, en bytes." -#: utils/misc/guc_tables.c:3425 +#: utils/misc/guc_tables.c:3568 msgid "Sets the maximum size of the pending list for GIN index." msgstr "Define el tamaño máximo de la lista de pendientes de un índice GIN." -#: utils/misc/guc_tables.c:3436 +#: utils/misc/guc_tables.c:3579 msgid "TCP user timeout." msgstr "Tiempo de expiración de TCP." -#: utils/misc/guc_tables.c:3447 +#: utils/misc/guc_tables.c:3590 msgid "The size of huge page that should be requested." msgstr "El tamaño de huge page que se debería solicitar." -#: utils/misc/guc_tables.c:3458 +#: utils/misc/guc_tables.c:3601 msgid "Aggressively flush system caches for debugging purposes." msgstr "Escribir cachés de sistema de forma agresiva para propósitos de depuración." -#: utils/misc/guc_tables.c:3481 +#: utils/misc/guc_tables.c:3624 msgid "Sets the time interval between checks for disconnection while running queries." msgstr "Establece el intervalo entre revisiones de desconexión mientras se ejecutan consultas." -#: utils/misc/guc_tables.c:3492 +#: utils/misc/guc_tables.c:3635 msgid "Time between progress updates for long-running startup operations." msgstr "Tiempo a esperar entre actualizaciones para operaciones largas durante el inicio." -#: utils/misc/guc_tables.c:3494 -#, fuzzy -#| msgid "Zero prints all queries. -1 turns this feature off." +#: utils/misc/guc_tables.c:3637 msgid "0 turns this feature off." -msgstr "Cero imprime todas las consultas. -1 desactiva esta funcionalidad." +msgstr "Cero desactiva esta característica." -#: utils/misc/guc_tables.c:3504 -#, fuzzy -#| msgid "Sets the seed for random-number generation." +#: utils/misc/guc_tables.c:3647 msgid "Sets the iteration count for SCRAM secret generation." -msgstr "Semilla para la generación de números aleatorios." +msgstr "Define la cantidad de iteraciones para generación de secretos SCRAM." -#: utils/misc/guc_tables.c:3524 +#: utils/misc/guc_tables.c:3667 msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "Estimación del costo de una página leída secuencialmente." -#: utils/misc/guc_tables.c:3535 +#: utils/misc/guc_tables.c:3678 msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page." msgstr "Estimación del costo de una página leída no secuencialmente." -#: utils/misc/guc_tables.c:3546 +#: utils/misc/guc_tables.c:3689 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "Estimación del costo de procesar cada tupla (fila)." -#: utils/misc/guc_tables.c:3557 +#: utils/misc/guc_tables.c:3700 msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan." msgstr "Estimación del costo de procesar cada fila de índice durante un recorrido de índice." -#: utils/misc/guc_tables.c:3568 +#: utils/misc/guc_tables.c:3711 msgid "Sets the planner's estimate of the cost of processing each operator or function call." msgstr "Estimación del costo de procesar cada operador o llamada a función." -#: utils/misc/guc_tables.c:3579 +#: utils/misc/guc_tables.c:3722 msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to leader backend." msgstr "Estimación del costo de pasar cada tupla (fila) desde un proceso ayudante al proceso servidor principal." -#: utils/misc/guc_tables.c:3590 +#: utils/misc/guc_tables.c:3733 msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query." msgstr "Estimación del costo de lanzar procesos ayudantes para consultas en paralelo." -#: utils/misc/guc_tables.c:3602 +#: utils/misc/guc_tables.c:3745 msgid "Perform JIT compilation if query is more expensive." msgstr "Ejecutar compilación JIT si la consulta es más cara." -#: utils/misc/guc_tables.c:3603 +#: utils/misc/guc_tables.c:3746 msgid "-1 disables JIT compilation." msgstr "-1 inhabilita compilación JIT." -#: utils/misc/guc_tables.c:3613 +#: utils/misc/guc_tables.c:3756 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "Optimizar funciones compiladas en tiempo de ejecución (JIT) si la consulta es más cara." -#: utils/misc/guc_tables.c:3614 +#: utils/misc/guc_tables.c:3757 msgid "-1 disables optimization." msgstr "-1 inhabilita la optimización." -#: utils/misc/guc_tables.c:3624 +#: utils/misc/guc_tables.c:3767 msgid "Perform JIT inlining if query is more expensive." msgstr "Ejecutar «inlining» JIT si la consulta es más cara." -#: utils/misc/guc_tables.c:3625 +#: utils/misc/guc_tables.c:3768 msgid "-1 disables inlining." msgstr "-1 inhabilita el «inlining»." -#: utils/misc/guc_tables.c:3635 +#: utils/misc/guc_tables.c:3778 msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." msgstr "Estimación de la fracción de filas de un cursor que serán extraídas." -#: utils/misc/guc_tables.c:3647 -#, fuzzy -#| msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." +#: utils/misc/guc_tables.c:3790 msgid "Sets the planner's estimate of the average size of a recursive query's working table." -msgstr "Estimación de la fracción de filas de un cursor que serán extraídas." +msgstr "Estimación del tamaño promedio de la tabla de trabajo de una consulta recursiva." -#: utils/misc/guc_tables.c:3659 +#: utils/misc/guc_tables.c:3802 msgid "GEQO: selective pressure within the population." msgstr "GEQO: presión selectiva dentro de la población." -#: utils/misc/guc_tables.c:3670 +#: utils/misc/guc_tables.c:3813 msgid "GEQO: seed for random path selection." msgstr "GEQO: semilla para la selección aleatoria de caminos." -#: utils/misc/guc_tables.c:3681 -msgid "Multiple of work_mem to use for hash tables." -msgstr "Múltiplo de work_mem para el uso de tablas de hash." +#: utils/misc/guc_tables.c:3824 +msgid "Multiple of \"work_mem\" to use for hash tables." +msgstr "Múltiplo de «work_mem» para el uso de tablas de hash." -#: utils/misc/guc_tables.c:3692 +#: utils/misc/guc_tables.c:3835 msgid "Multiple of the average buffer usage to free per round." msgstr "Múltiplo del uso promedio de búfers que liberar en cada ronda." -#: utils/misc/guc_tables.c:3702 +#: utils/misc/guc_tables.c:3845 msgid "Sets the seed for random-number generation." msgstr "Semilla para la generación de números aleatorios." -#: utils/misc/guc_tables.c:3713 +#: utils/misc/guc_tables.c:3856 msgid "Vacuum cost delay in milliseconds." msgstr "Tiempo de descanso de vacuum en milisegundos." -#: utils/misc/guc_tables.c:3724 +#: utils/misc/guc_tables.c:3867 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "Tiempo de descanso de vacuum en milisegundos, para autovacuum." -#: utils/misc/guc_tables.c:3735 +#: utils/misc/guc_tables.c:3878 msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples." msgstr "Número de updates o deletes de tuplas antes de ejecutar un vacuum, como fracción de reltuples." -#: utils/misc/guc_tables.c:3745 +#: utils/misc/guc_tables.c:3888 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "Número de inserts de tuplas antes de ejecutar un vacuum, como fracción de reltuples." -#: utils/misc/guc_tables.c:3755 +#: utils/misc/guc_tables.c:3898 msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples." msgstr "Número mínimo de inserciones, actualizaciones y eliminaciones de tuplas antes de ejecutar analyze, como fracción de reltuples." -#: utils/misc/guc_tables.c:3765 +#: utils/misc/guc_tables.c:3908 msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval." -msgstr "Tiempo utilizado en escribir páginas «sucias» durante los puntos de control, medido como fracción del intervalo del punto de control." +msgstr "Tiempo utilizado en escribir páginas «sucias» durante los puntos de control, medido como fracción del intervalo del checkpoint." -#: utils/misc/guc_tables.c:3775 -msgid "Fraction of statements exceeding log_min_duration_sample to be logged." -msgstr "Fracción de sentencias que duren más de log_min_duration_sample a ser registradas." +#: utils/misc/guc_tables.c:3918 +msgid "Fraction of statements exceeding \"log_min_duration_sample\" to be logged." +msgstr "Fracción de sentencias que duren más de «log_min_duration_sample» a ser registradas." -#: utils/misc/guc_tables.c:3776 +#: utils/misc/guc_tables.c:3919 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "Use un valor entre 0.0 (no registrar nunca) y 1.0 (registrar siempre)." -#: utils/misc/guc_tables.c:3785 +#: utils/misc/guc_tables.c:3928 msgid "Sets the fraction of transactions from which to log all statements." msgstr "Define la fracción de transacciones desde la cual registrar en el log todas las sentencias." -#: utils/misc/guc_tables.c:3786 +#: utils/misc/guc_tables.c:3929 msgid "Use a value between 0.0 (never log) and 1.0 (log all statements for all transactions)." msgstr "Use un valor entre 0.0 (nunca registrar) y 1.0 (registrar todas las sentencias de todas las transacciones)." -#: utils/misc/guc_tables.c:3805 +#: utils/misc/guc_tables.c:3948 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "Orden de shell que se invocará para archivar un archivo WAL." -#: utils/misc/guc_tables.c:3806 +#: utils/misc/guc_tables.c:3949 msgid "This is used only if \"archive_library\" is not set." msgstr "Esto sólo se utiliza si «archive_library» no está definido." -#: utils/misc/guc_tables.c:3815 -#, fuzzy -#| msgid "Sets the shell command that will be called to archive a WAL file." +#: utils/misc/guc_tables.c:3958 msgid "Sets the library that will be called to archive a WAL file." -msgstr "Orden de shell que se invocará para archivar un archivo WAL." +msgstr "Biblioteca que se invocará para archivar un archivo WAL." -#: utils/misc/guc_tables.c:3816 +#: utils/misc/guc_tables.c:3959 msgid "An empty string indicates that \"archive_command\" should be used." msgstr "Una cadena vacía indica que «archive_command» debería usarse." -#: utils/misc/guc_tables.c:3825 +#: utils/misc/guc_tables.c:3968 msgid "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "Orden de shell que se invocará para recuperar un archivo WAL archivado." -#: utils/misc/guc_tables.c:3835 +#: utils/misc/guc_tables.c:3978 msgid "Sets the shell command that will be executed at every restart point." msgstr "Orden de shell que se invocará en cada «restart point»." -#: utils/misc/guc_tables.c:3845 +#: utils/misc/guc_tables.c:3988 msgid "Sets the shell command that will be executed once at the end of recovery." msgstr "Orden de shell que se invocará una vez al terminar la recuperación." -#: utils/misc/guc_tables.c:3855 +#: utils/misc/guc_tables.c:3998 msgid "Specifies the timeline to recover into." msgstr "Especifica la línea de tiempo a la cual recuperar." -#: utils/misc/guc_tables.c:3865 +#: utils/misc/guc_tables.c:4008 msgid "Set to \"immediate\" to end recovery as soon as a consistent state is reached." msgstr "Defina a «immediate» para terminar la recuperación en cuando se alcance el estado consistente." -#: utils/misc/guc_tables.c:3874 +#: utils/misc/guc_tables.c:4017 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "Define el ID de transacción hasta el cual se ejecutará la recuperación." -#: utils/misc/guc_tables.c:3883 +#: utils/misc/guc_tables.c:4026 msgid "Sets the time stamp up to which recovery will proceed." msgstr "Define la marca de tiempo hasta la cual se ejecutará la recuperación." -#: utils/misc/guc_tables.c:3892 +#: utils/misc/guc_tables.c:4035 msgid "Sets the named restore point up to which recovery will proceed." msgstr "Define el nombre del punto de restauración hasta el cual se ejecutará la recuperación." -#: utils/misc/guc_tables.c:3901 +#: utils/misc/guc_tables.c:4044 msgid "Sets the LSN of the write-ahead log location up to which recovery will proceed." msgstr "Define el LSN de la ubicación de WAL hasta la cual se ejecutará la recuperación." -#: utils/misc/guc_tables.c:3911 +#: utils/misc/guc_tables.c:4054 msgid "Sets the connection string to be used to connect to the sending server." msgstr "Define la cadena de conexión que se usará para conectarse al servidor de origen." -#: utils/misc/guc_tables.c:3922 +#: utils/misc/guc_tables.c:4065 msgid "Sets the name of the replication slot to use on the sending server." msgstr "Define el nombre del slot de replicación a utilizar en el servidor de origen." -#: utils/misc/guc_tables.c:3932 +#: utils/misc/guc_tables.c:4075 msgid "Sets the client's character set encoding." msgstr "Codificación del juego de caracteres del cliente." -#: utils/misc/guc_tables.c:3943 +#: utils/misc/guc_tables.c:4086 msgid "Controls information prefixed to each log line." msgstr "Controla el prefijo que antecede cada línea registrada." -#: utils/misc/guc_tables.c:3944 +#: utils/misc/guc_tables.c:4087 msgid "If blank, no prefix is used." msgstr "si está en blanco, no se usa prefijo." -#: utils/misc/guc_tables.c:3953 +#: utils/misc/guc_tables.c:4096 msgid "Sets the time zone to use in log messages." msgstr "Define el huso horario usando en los mensajes registrados." -#: utils/misc/guc_tables.c:3963 +#: utils/misc/guc_tables.c:4106 msgid "Sets the display format for date and time values." msgstr "Formato de salida para valores de horas y fechas." -#: utils/misc/guc_tables.c:3964 +#: utils/misc/guc_tables.c:4107 msgid "Also controls interpretation of ambiguous date inputs." msgstr "También controla la interpretación de entradas ambiguas de fechas" -#: utils/misc/guc_tables.c:3975 +#: utils/misc/guc_tables.c:4118 msgid "Sets the default table access method for new tables." msgstr "Define el método de acceso a tablas por omisión para nuevas tablas." -#: utils/misc/guc_tables.c:3986 +#: utils/misc/guc_tables.c:4129 msgid "Sets the default tablespace to create tables and indexes in." msgstr "Define el tablespace en el cual crear tablas e índices." -#: utils/misc/guc_tables.c:3987 +#: utils/misc/guc_tables.c:4130 msgid "An empty string selects the database's default tablespace." msgstr "Una cadena vacía especifica el tablespace por omisión de la base de datos." -#: utils/misc/guc_tables.c:3997 +#: utils/misc/guc_tables.c:4140 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "Define el/los tablespace/s en el cual crear tablas temporales y archivos de ordenamiento." -#: utils/misc/guc_tables.c:4008 +#: utils/misc/guc_tables.c:4151 msgid "Sets whether a CREATEROLE user automatically grants the role to themselves, and with which options." -msgstr "" +msgstr "define si un rol con CREATEROLE automáticamente se otorga ese rol a si mismo, y con qué opciones." -#: utils/misc/guc_tables.c:4020 +#: utils/misc/guc_tables.c:4163 msgid "Sets the path for dynamically loadable modules." msgstr "Ruta para módulos dinámicos." -#: utils/misc/guc_tables.c:4021 +#: utils/misc/guc_tables.c:4164 msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file." msgstr "Si se necesita abrir un módulo dinámico y el nombre especificado no tiene un componente de directorio (es decir, no contiene un slash), el sistema buscará el archivo especificado en esta ruta." -#: utils/misc/guc_tables.c:4034 +#: utils/misc/guc_tables.c:4177 msgid "Sets the location of the Kerberos server key file." msgstr "Ubicación del archivo de llave del servidor Kerberos." -#: utils/misc/guc_tables.c:4045 +#: utils/misc/guc_tables.c:4188 msgid "Sets the Bonjour service name." msgstr "Nombre del servicio Bonjour." -#: utils/misc/guc_tables.c:4057 -msgid "Shows the collation order locale." -msgstr "Configuración regional de ordenamiento de cadenas (collation)." - -#: utils/misc/guc_tables.c:4068 -msgid "Shows the character classification and case conversion locale." -msgstr "Configuración regional de clasificación de caracteres y conversión de mayúsculas." - -#: utils/misc/guc_tables.c:4079 +#: utils/misc/guc_tables.c:4198 msgid "Sets the language in which messages are displayed." msgstr "Idioma en el que se despliegan los mensajes." -#: utils/misc/guc_tables.c:4089 +#: utils/misc/guc_tables.c:4208 msgid "Sets the locale for formatting monetary amounts." msgstr "Configuración regional para formatos de moneda." -#: utils/misc/guc_tables.c:4099 +#: utils/misc/guc_tables.c:4218 msgid "Sets the locale for formatting numbers." msgstr "Configuración regional para formatos de números." -#: utils/misc/guc_tables.c:4109 +#: utils/misc/guc_tables.c:4228 msgid "Sets the locale for formatting date and time values." msgstr "Configuración regional para formatos de horas y fechas." -#: utils/misc/guc_tables.c:4119 +#: utils/misc/guc_tables.c:4238 msgid "Lists shared libraries to preload into each backend." msgstr "Bibliotecas compartidas a precargar en cada proceso." -#: utils/misc/guc_tables.c:4130 +#: utils/misc/guc_tables.c:4249 msgid "Lists shared libraries to preload into server." msgstr "Bibliotecas compartidas a precargar en el servidor." -#: utils/misc/guc_tables.c:4141 +#: utils/misc/guc_tables.c:4260 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "Bibliotecas compartidas no privilegiadas a precargar en cada proceso." -#: utils/misc/guc_tables.c:4152 +#: utils/misc/guc_tables.c:4271 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "Orden de búsqueda en schemas para nombres que no especifican schema." -#: utils/misc/guc_tables.c:4164 +#: utils/misc/guc_tables.c:4283 msgid "Shows the server (database) character set encoding." msgstr "Muestra la codificación de caracteres del servidor (base de datos)." -#: utils/misc/guc_tables.c:4176 +#: utils/misc/guc_tables.c:4295 msgid "Shows the server version." msgstr "Versión del servidor." -#: utils/misc/guc_tables.c:4188 +#: utils/misc/guc_tables.c:4307 msgid "Sets the current role." msgstr "Define el rol actual." -#: utils/misc/guc_tables.c:4200 +#: utils/misc/guc_tables.c:4319 msgid "Sets the session user name." msgstr "Define el nombre del usuario de sesión." -#: utils/misc/guc_tables.c:4211 +#: utils/misc/guc_tables.c:4330 msgid "Sets the destination for server log output." msgstr "Define el destino de la salida del registro del servidor." -#: utils/misc/guc_tables.c:4212 +#: utils/misc/guc_tables.c:4331 msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", and \"eventlog\", depending on the platform." -msgstr "" +msgstr "Son aceptables combinaciones de «stderr», «syslog», «csvlog», «jsonlog» y «eventlog», dependendiendo de la plataforma." -#: utils/misc/guc_tables.c:4223 +#: utils/misc/guc_tables.c:4342 msgid "Sets the destination directory for log files." msgstr "Define el directorio de destino de los archivos del registro del servidor." -#: utils/misc/guc_tables.c:4224 +#: utils/misc/guc_tables.c:4343 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "Puede ser una ruta relativa al directorio de datos o una ruta absoluta." -#: utils/misc/guc_tables.c:4234 +#: utils/misc/guc_tables.c:4353 msgid "Sets the file name pattern for log files." msgstr "Define el patrón para los nombres de archivo del registro del servidor." -#: utils/misc/guc_tables.c:4245 +#: utils/misc/guc_tables.c:4364 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "Nombre de programa para identificar PostgreSQL en mensajes de syslog." -#: utils/misc/guc_tables.c:4256 +#: utils/misc/guc_tables.c:4375 msgid "Sets the application name used to identify PostgreSQL messages in the event log." msgstr "Nombre de programa para identificar PostgreSQL en mensajes del log de eventos." -#: utils/misc/guc_tables.c:4267 +#: utils/misc/guc_tables.c:4386 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "Huso horario para desplegar e interpretar valores de tiempo." -#: utils/misc/guc_tables.c:4277 +#: utils/misc/guc_tables.c:4396 msgid "Selects a file of time zone abbreviations." msgstr "Selecciona un archivo de abreviaciones de huso horario." -#: utils/misc/guc_tables.c:4287 +#: utils/misc/guc_tables.c:4406 msgid "Sets the owning group of the Unix-domain socket." msgstr "Grupo dueño del socket de dominio Unix." -#: utils/misc/guc_tables.c:4288 +#: utils/misc/guc_tables.c:4407 msgid "The owning user of the socket is always the user that starts the server." msgstr "El usuario dueño del socket siempre es el usuario que inicia el servidor." -#: utils/misc/guc_tables.c:4298 +#: utils/misc/guc_tables.c:4417 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "Directorios donde se crearán los sockets de dominio Unix." -#: utils/misc/guc_tables.c:4309 +#: utils/misc/guc_tables.c:4428 msgid "Sets the host name or IP address(es) to listen to." msgstr "Define el nombre de anfitrión o dirección IP en la cual escuchar." -#: utils/misc/guc_tables.c:4324 +#: utils/misc/guc_tables.c:4443 msgid "Sets the server's data directory." msgstr "Define la ubicación del directorio de datos." -#: utils/misc/guc_tables.c:4335 +#: utils/misc/guc_tables.c:4454 msgid "Sets the server's main configuration file." msgstr "Define la ubicación del archivo principal de configuración del servidor." -#: utils/misc/guc_tables.c:4346 +#: utils/misc/guc_tables.c:4465 msgid "Sets the server's \"hba\" configuration file." msgstr "Define la ubicación del archivo de configuración «hba» del servidor." -#: utils/misc/guc_tables.c:4357 +#: utils/misc/guc_tables.c:4476 msgid "Sets the server's \"ident\" configuration file." msgstr "Define la ubicación del archivo de configuración «ident» del servidor." -#: utils/misc/guc_tables.c:4368 +#: utils/misc/guc_tables.c:4487 msgid "Writes the postmaster PID to the specified file." msgstr "Registra el PID de postmaster en el archivo especificado." -#: utils/misc/guc_tables.c:4379 +#: utils/misc/guc_tables.c:4498 msgid "Shows the name of the SSL library." msgstr "Muestra el nombre de la biblioteca SSL." -#: utils/misc/guc_tables.c:4394 +#: utils/misc/guc_tables.c:4513 msgid "Location of the SSL server certificate file." msgstr "Ubicación del archivo de certificado SSL del servidor." -#: utils/misc/guc_tables.c:4404 +#: utils/misc/guc_tables.c:4523 msgid "Location of the SSL server private key file." msgstr "Ubicación del archivo de la llave SSL privada del servidor." -#: utils/misc/guc_tables.c:4414 +#: utils/misc/guc_tables.c:4533 msgid "Location of the SSL certificate authority file." msgstr "Ubicación del archivo de autoridad certificadora SSL." -#: utils/misc/guc_tables.c:4424 +#: utils/misc/guc_tables.c:4543 msgid "Location of the SSL certificate revocation list file." msgstr "Ubicación del archivo de lista de revocación de certificados SSL" -#: utils/misc/guc_tables.c:4434 +#: utils/misc/guc_tables.c:4553 msgid "Location of the SSL certificate revocation list directory." msgstr "Ubicación del directorio de lista de revocación de certificados SSL" -#: utils/misc/guc_tables.c:4444 +#: utils/misc/guc_tables.c:4563 msgid "Number of synchronous standbys and list of names of potential synchronous ones." msgstr "Número de standbys sincrónicos y lista de nombres de los potenciales sincrónicos." -#: utils/misc/guc_tables.c:4455 +#: utils/misc/guc_tables.c:4574 msgid "Sets default text search configuration." msgstr "Define la configuración de búsqueda en texto por omisión." -#: utils/misc/guc_tables.c:4465 +#: utils/misc/guc_tables.c:4584 msgid "Sets the list of allowed SSL ciphers." msgstr "Define la lista de cifrados SSL permitidos." -#: utils/misc/guc_tables.c:4480 +#: utils/misc/guc_tables.c:4599 msgid "Sets the curve to use for ECDH." msgstr "Define la curva a usar para ECDH." -#: utils/misc/guc_tables.c:4495 +#: utils/misc/guc_tables.c:4614 msgid "Location of the SSL DH parameters file." msgstr "Ubicación del archivo de parámetros DH para SSL." -#: utils/misc/guc_tables.c:4506 +#: utils/misc/guc_tables.c:4625 msgid "Command to obtain passphrases for SSL." msgstr "Orden para obtener frases clave para SSL." -#: utils/misc/guc_tables.c:4517 +#: utils/misc/guc_tables.c:4636 msgid "Sets the application name to be reported in statistics and logs." msgstr "Define el nombre de aplicación a reportarse en estadísticas y logs." -#: utils/misc/guc_tables.c:4528 +#: utils/misc/guc_tables.c:4647 msgid "Sets the name of the cluster, which is included in the process title." msgstr "Define el nombre del clúster, el cual se incluye en el título de proceso." -#: utils/misc/guc_tables.c:4539 +#: utils/misc/guc_tables.c:4658 msgid "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "Define los gestores de recursos WAL para los cuales hacer verificaciones de consistencia WAL." -#: utils/misc/guc_tables.c:4540 +#: utils/misc/guc_tables.c:4659 msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay." msgstr "Se registrarán imágenes de página completa para todos los bloques de datos, y comparados con los resultados de la aplicación de WAL." -#: utils/misc/guc_tables.c:4550 +#: utils/misc/guc_tables.c:4669 msgid "JIT provider to use." msgstr "Proveedor JIT a usar." -#: utils/misc/guc_tables.c:4561 +#: utils/misc/guc_tables.c:4680 msgid "Log backtrace for errors in these functions." msgstr "Registrar el backtrace para errores que se produzcan en estas funciones." -#: utils/misc/guc_tables.c:4572 +#: utils/misc/guc_tables.c:4691 msgid "Use direct I/O for file access." -msgstr "" +msgstr "Usar I/O directo para accesos a archivos." + +#: utils/misc/guc_tables.c:4702 +msgid "Lists streaming replication standby server replication slot names that logical WAL sender processes will wait for." +msgstr "Lista los nombres de slots de replicación de servidores standby a los que los procesos “WAL sender” esperarán." + +#: utils/misc/guc_tables.c:4704 +msgid "Logical WAL sender processes will send decoded changes to output plugins only after the specified replication slots have confirmed receiving WAL." +msgstr "Los procesos “WAL sender” lógicos enviarán cambios decodificados a los “plugins” de salida sólo después de que los slots de replicación especificados han confirmado recibir el WAL." + +#: utils/misc/guc_tables.c:4716 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "Prohibir acceso a las relaciones no de sistema de los tipos especificados." -#: utils/misc/guc_tables.c:4592 +#: utils/misc/guc_tables.c:4736 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "Define si «\\'» está permitido en literales de cadena." -#: utils/misc/guc_tables.c:4602 +#: utils/misc/guc_tables.c:4746 msgid "Sets the output format for bytea." msgstr "Formato de salida para bytea." -#: utils/misc/guc_tables.c:4612 +#: utils/misc/guc_tables.c:4756 msgid "Sets the message levels that are sent to the client." msgstr "Nivel de mensajes enviados al cliente." -#: utils/misc/guc_tables.c:4613 utils/misc/guc_tables.c:4709 -#: utils/misc/guc_tables.c:4720 utils/misc/guc_tables.c:4792 +#: utils/misc/guc_tables.c:4757 utils/misc/guc_tables.c:4853 +#: utils/misc/guc_tables.c:4864 msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent." msgstr "Cada nivel incluye todos los niveles que lo siguen. Mientras más posterior el nivel, menos mensajes se enviarán." -#: utils/misc/guc_tables.c:4623 +#: utils/misc/guc_tables.c:4767 msgid "Enables in-core computation of query identifiers." -msgstr "" +msgstr "Habilita el cálculo de identificadores de consulta." -#: utils/misc/guc_tables.c:4633 +#: utils/misc/guc_tables.c:4777 msgid "Enables the planner to use constraints to optimize queries." msgstr "Permitir el uso de restricciones para limitar los accesos a tablas." -#: utils/misc/guc_tables.c:4634 +#: utils/misc/guc_tables.c:4778 msgid "Table scans will be skipped if their constraints guarantee that no rows match the query." msgstr "Las tablas no serán recorridas si sus restricciones garantizan que ninguna fila coincidirá con la consulta." -#: utils/misc/guc_tables.c:4645 +#: utils/misc/guc_tables.c:4789 msgid "Sets the default compression method for compressible values." msgstr "Define el método de compresión por omisión para valores comprimibles." -#: utils/misc/guc_tables.c:4656 +#: utils/misc/guc_tables.c:4800 msgid "Sets the transaction isolation level of each new transaction." msgstr "Nivel de aislación (isolation level) de transacciones nuevas." -#: utils/misc/guc_tables.c:4666 +#: utils/misc/guc_tables.c:4810 msgid "Sets the current transaction's isolation level." msgstr "Define el nivel de aislación de la transacción en curso." -#: utils/misc/guc_tables.c:4677 +#: utils/misc/guc_tables.c:4821 msgid "Sets the display format for interval values." msgstr "Formato de salida para valores de intervalos." -#: utils/misc/guc_tables.c:4688 +#: utils/misc/guc_tables.c:4832 msgid "Log level for reporting invalid ICU locale strings." -msgstr "" +msgstr "Nivel de log a usar para reportar cadenas de configuración ICU no válidas." -#: utils/misc/guc_tables.c:4698 +#: utils/misc/guc_tables.c:4842 msgid "Sets the verbosity of logged messages." msgstr "Verbosidad de los mensajes registrados." -#: utils/misc/guc_tables.c:4708 +#: utils/misc/guc_tables.c:4852 msgid "Sets the message levels that are logged." msgstr "Nivel de mensajes registrados." -#: utils/misc/guc_tables.c:4719 +#: utils/misc/guc_tables.c:4863 msgid "Causes all statements generating error at or above this level to be logged." msgstr "Registrar sentencias que generan error de nivel superior o igual a éste." -#: utils/misc/guc_tables.c:4730 +#: utils/misc/guc_tables.c:4874 msgid "Sets the type of statements logged." msgstr "Define el tipo de sentencias que se registran." -#: utils/misc/guc_tables.c:4740 +#: utils/misc/guc_tables.c:4884 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "«Facility» de syslog que se usará cuando syslog esté habilitado." -#: utils/misc/guc_tables.c:4751 +#: utils/misc/guc_tables.c:4895 msgid "Sets the session's behavior for triggers and rewrite rules." -msgstr "Define el comportamiento de la sesión con respecto a disparadores y reglas de reescritura." +msgstr "Define el comportamiento de la sesión con respecto a “triggers” y reglas de reescritura." -#: utils/misc/guc_tables.c:4761 +#: utils/misc/guc_tables.c:4905 msgid "Sets the current transaction's synchronization level." msgstr "Define el nivel de sincronización de la transacción en curso." -#: utils/misc/guc_tables.c:4771 -msgid "Allows archiving of WAL files using archive_command." -msgstr "Permite el archivado de WAL usando archive_command." +#: utils/misc/guc_tables.c:4915 +msgid "Allows archiving of WAL files using \"archive_command\"." +msgstr "Permite el archivado de WAL usando «archive_command»." -#: utils/misc/guc_tables.c:4781 +#: utils/misc/guc_tables.c:4925 msgid "Sets the action to perform upon reaching the recovery target." msgstr "Acción a ejecutar al alcanzar el destino de recuperación." -#: utils/misc/guc_tables.c:4791 -msgid "Enables logging of recovery-related debugging information." -msgstr "Recolectar información de depuración relacionada con la recuperación." - -#: utils/misc/guc_tables.c:4808 +#: utils/misc/guc_tables.c:4935 msgid "Collects function-level statistics on database activity." msgstr "Recolectar estadísticas de actividad de funciones en la base de datos." -#: utils/misc/guc_tables.c:4819 -#, fuzzy -#| msgid "Sets the default statistics target." +#: utils/misc/guc_tables.c:4946 msgid "Sets the consistency of accesses to statistics data." -msgstr "Definir el valor por omisión de toma de estadísticas." +msgstr "Definir la consistencia de accesos a los datos de estadísticas." -#: utils/misc/guc_tables.c:4829 +#: utils/misc/guc_tables.c:4956 msgid "Compresses full-page writes written in WAL file with specified method." -msgstr "" +msgstr "Comprime las páginas completas escritas a WAL (FPI) con el método especificado." -#: utils/misc/guc_tables.c:4839 +#: utils/misc/guc_tables.c:4966 msgid "Sets the level of information written to the WAL." msgstr "Establece el nivel de información escrita al WAL." -#: utils/misc/guc_tables.c:4849 +#: utils/misc/guc_tables.c:4976 msgid "Selects the dynamic shared memory implementation used." msgstr "Escoge la implementación de memoria compartida dinámica que se usará." -#: utils/misc/guc_tables.c:4859 +#: utils/misc/guc_tables.c:4986 msgid "Selects the shared memory implementation used for the main shared memory region." msgstr "Escoge la implementación de memoria compartida dinámica que se usará para la región principal de memoria compartida." -#: utils/misc/guc_tables.c:4869 +#: utils/misc/guc_tables.c:4996 msgid "Selects the method used for forcing WAL updates to disk." msgstr "Selecciona el método usado para forzar escritura de WAL a disco." -#: utils/misc/guc_tables.c:4879 +#: utils/misc/guc_tables.c:5006 msgid "Sets how binary values are to be encoded in XML." msgstr "Define cómo se codificarán los valores binarios en XML." -#: utils/misc/guc_tables.c:4889 +#: utils/misc/guc_tables.c:5016 msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments." msgstr "Define si los datos XML implícitos en operaciones de análisis y serialización serán considerados documentos o fragmentos de contenido." -#: utils/misc/guc_tables.c:4900 +#: utils/misc/guc_tables.c:5027 msgid "Use of huge pages on Linux or Windows." msgstr "Usar páginas grandes (huge) en Linux o Windows." -#: utils/misc/guc_tables.c:4910 -#, fuzzy -#| msgid "cannot execute %s during recovery" +#: utils/misc/guc_tables.c:5037 +msgid "Indicates the status of huge pages." +msgstr "Indica el estado de las “huge pages”." + +#: utils/misc/guc_tables.c:5048 msgid "Prefetch referenced blocks during recovery." -msgstr "no se puede ejecutar %s durante la recuperación" +msgstr "Pre-cargar bloques referenciados durante la recuperación." -#: utils/misc/guc_tables.c:4911 +#: utils/misc/guc_tables.c:5049 msgid "Look ahead in the WAL to find references to uncached data." msgstr "Busca adelantadamente en el WAL para encontrar referencias a datos que no están en cache." -#: utils/misc/guc_tables.c:4920 -#, fuzzy -#| msgid "Enables the planner's use of parallel append plans." +#: utils/misc/guc_tables.c:5058 msgid "Forces the planner's use parallel query nodes." -msgstr "Permitir el uso de planes «append» paralelos." +msgstr "Fuerza al optimizador a usar planes paralelos." -#: utils/misc/guc_tables.c:4921 -msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans which contains nodes which perform tuple communication between workers and the main process." -msgstr "" +#: utils/misc/guc_tables.c:5059 +msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans that contain nodes that perform tuple communication between workers and the main process." +msgstr "Esto puede usarse para verificar la infrastructura de consultas paralelas forzando al optimizar a generar planes que contienen nodos que utilizan la comunicación entre procesos hijos y el principal." -#: utils/misc/guc_tables.c:4933 +#: utils/misc/guc_tables.c:5071 msgid "Chooses the algorithm for encrypting passwords." msgstr "Escoge el algoritmo para cifrar contraseñas." -#: utils/misc/guc_tables.c:4943 +#: utils/misc/guc_tables.c:5081 msgid "Controls the planner's selection of custom or generic plan." msgstr "Controla la selección del optimizador de planes genéricos o «custom»." -#: utils/misc/guc_tables.c:4944 +#: utils/misc/guc_tables.c:5082 msgid "Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior." msgstr "Las sentencias preparadas pueden tener planes genéricos y «custom», y el optimizador intentará escoger cuál es mejor. Esto puede usarse para controlar manualmente el comportamiento." -#: utils/misc/guc_tables.c:4956 +#: utils/misc/guc_tables.c:5094 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "Define la versión mínima del protocolo SSL/TLS a usar." -#: utils/misc/guc_tables.c:4968 +#: utils/misc/guc_tables.c:5106 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "Define la versión máxima del protocolo SSL/TLS a usar." -#: utils/misc/guc_tables.c:4980 +#: utils/misc/guc_tables.c:5118 msgid "Sets the method for synchronizing the data directory before crash recovery." msgstr "Establece el método para sincronizar el directorio de datos antes de la recuperación ante una caída." -#: utils/misc/guc_tables.c:4989 -msgid "Controls when to replicate or apply each change." -msgstr "" +#: utils/misc/guc_tables.c:5127 +msgid "Forces immediate streaming or serialization of changes in large transactions." +msgstr "Fuerza el flujo o serialización inmediatos de los cambios en transacciones grandes." -#: utils/misc/guc_tables.c:4990 +#: utils/misc/guc_tables.c:5128 msgid "On the publisher, it allows streaming or serializing each change in logical decoding. On the subscriber, it allows serialization of all changes to files and notifies the parallel apply workers to read and apply them at the end of the transaction." -msgstr "" +msgstr "En el publicador, permite serializar o transmitir en flujo cada cambio en la decodificación lógica. En el suscriptor, permite la serialización de todos los cambios a archivos y notifica a los procesos paralelos de “apply” para leerlos y aplicarlos al término de la transacción." #: utils/misc/help_config.c:129 #, c-format msgid "internal error: unrecognized run-time parameter type\n" msgstr "error interno: tipo parámetro no reconocido\n" -#: utils/misc/pg_controldata.c:48 utils/misc/pg_controldata.c:86 -#: utils/misc/pg_controldata.c:175 utils/misc/pg_controldata.c:214 +#: utils/misc/pg_controldata.c:50 utils/misc/pg_controldata.c:90 +#: utils/misc/pg_controldata.c:181 utils/misc/pg_controldata.c:222 #, c-format msgid "calculated CRC checksum does not match value stored in file" msgstr "la suma de verificación calculada no coincide con el valor almacenado en el archivo" @@ -29476,145 +30320,143 @@ msgstr "la consulta sería afectada por la política de seguridad de registros p msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." msgstr "Para desactivar la política para el dueño de la tabla, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." -#: utils/misc/timeout.c:524 +#: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" msgstr "no se pueden agregar más razones de timeout" -#: utils/misc/tzparser.c:60 +#: utils/misc/tzparser.c:61 #, c-format msgid "time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d" msgstr "la abreviación del huso horario «%s» es demasiado larga (máximo %d caracteres) en archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:72 +#: utils/misc/tzparser.c:73 #, c-format msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "desplazamiento de huso horario %d está fuera de rango en el archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:111 +#: utils/misc/tzparser.c:112 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "falta una abreviación de huso horario en el archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:120 +#: utils/misc/tzparser.c:121 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "falta un desplazamiento de huso horario en el archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:132 +#: utils/misc/tzparser.c:133 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "número no válido para desplazamiento de huso horario en archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:168 +#: utils/misc/tzparser.c:169 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "sintaxis no válida en archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:236 +#: utils/misc/tzparser.c:237 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "abreviación de huso horario «%s» está definida múltiples veces" -#: utils/misc/tzparser.c:238 +#: utils/misc/tzparser.c:239 #, c-format msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d." msgstr "Entrada en archivo de huso horario «%s», línea %d, causa conflictos con entrada en archivo «%s», línea %d." -#: utils/misc/tzparser.c:300 +#: utils/misc/tzparser.c:301 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "nombre de huso horario «%s» no válido" -#: utils/misc/tzparser.c:313 +#: utils/misc/tzparser.c:314 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "límite de recursión excedido en el archivo «%s»" -#: utils/misc/tzparser.c:352 utils/misc/tzparser.c:365 +#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "no se pudo leer archivo de huso horario «%s»: %m" -#: utils/misc/tzparser.c:376 +#: utils/misc/tzparser.c:377 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "línea demasiado larga en archivo de huso horario «%s», línea %d" -#: utils/misc/tzparser.c:400 +#: utils/misc/tzparser.c:401 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "@INCLUDE sin nombre de archivo en archivo de huso horario «%s», línea %d" -#: utils/mmgr/aset.c:446 utils/mmgr/generation.c:206 utils/mmgr/slab.c:367 +#: utils/mmgr/aset.c:452 utils/mmgr/bump.c:184 utils/mmgr/generation.c:216 +#: utils/mmgr/slab.c:371 #, c-format msgid "Failed while creating memory context \"%s\"." msgstr "Falla al crear el contexto de memoria «%s»." -#: utils/mmgr/dsa.c:531 utils/mmgr/dsa.c:1341 +#: utils/mmgr/dsa.c:523 utils/mmgr/dsa.c:1364 #, c-format msgid "could not attach to dynamic shared area" msgstr "no se pudo adjuntar al segmento de memoria compartida dinámica" -#: utils/mmgr/mcxt.c:1047 utils/mmgr/mcxt.c:1083 utils/mmgr/mcxt.c:1121 -#: utils/mmgr/mcxt.c:1159 utils/mmgr/mcxt.c:1247 utils/mmgr/mcxt.c:1278 -#: utils/mmgr/mcxt.c:1314 utils/mmgr/mcxt.c:1503 utils/mmgr/mcxt.c:1548 -#: utils/mmgr/mcxt.c:1605 +#: utils/mmgr/mcxt.c:1155 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "Falló una petición de tamaño %zu en el contexto de memoria «%s»." -#: utils/mmgr/mcxt.c:1210 +#: utils/mmgr/mcxt.c:1299 #, c-format msgid "logging memory contexts of PID %d" msgstr "registrando contextos de memoria del PID %d" -#: utils/mmgr/portalmem.c:188 +#: utils/mmgr/portalmem.c:187 #, c-format msgid "cursor \"%s\" already exists" msgstr "el cursor «%s» ya existe" -#: utils/mmgr/portalmem.c:192 +#: utils/mmgr/portalmem.c:191 #, c-format msgid "closing existing cursor \"%s\"" msgstr "cerrando el cursor «%s» preexistente" -#: utils/mmgr/portalmem.c:402 +#: utils/mmgr/portalmem.c:401 #, c-format msgid "portal \"%s\" cannot be run" msgstr "el portal «%s» no puede ser ejecutado" -#: utils/mmgr/portalmem.c:480 +#: utils/mmgr/portalmem.c:479 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "no se puede eliminar el portal «pinned» «%s»" -#: utils/mmgr/portalmem.c:488 +#: utils/mmgr/portalmem.c:487 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "no se puede eliminar el portal activo «%s»" -#: utils/mmgr/portalmem.c:739 +#: utils/mmgr/portalmem.c:738 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "no se puede hacer PREPARE de una transacción que ha creado un cursor WITH HOLD" -#: utils/mmgr/portalmem.c:1230 +#: utils/mmgr/portalmem.c:1232 #, c-format msgid "cannot perform transaction commands inside a cursor loop that is not read-only" msgstr "no se pueden ejecutar órdenes de transacción dentro de un bucle de cursor que no es de sólo lectura" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %ld of temporary file" -msgstr "no se pudo posicionar (seek) en el bloque %ld del archivo temporal" +msgid "could not seek to block %lld of temporary file" +msgstr "no se pudo posicionar (seek) en el bloque %lld del archivo temporal" -#: utils/sort/sharedtuplestore.c:467 +#: utils/sort/sharedtuplestore.c:466 #, c-format msgid "unexpected chunk in shared tuplestore temporary file" msgstr "trozo inesperado en archivo temporal del tuplestore compartido" -#: utils/sort/sharedtuplestore.c:549 +#: utils/sort/sharedtuplestore.c:548 #, c-format msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "no se pudo posicionar (seek) en el bloque %u en el archivo temporal del tuplestore compartido" @@ -29624,17 +30466,17 @@ msgstr "no se pudo posicionar (seek) en el bloque %u en el archivo temporal del msgid "cannot have more than %d runs for an external sort" msgstr "no se pueden tener más de %d pasadas para un ordenamiento externo" -#: utils/sort/tuplesortvariants.c:1364 +#: utils/sort/tuplesortvariants.c:1552 #, c-format msgid "could not create unique index \"%s\"" msgstr "no se pudo crear el índice único «%s»" -#: utils/sort/tuplesortvariants.c:1366 +#: utils/sort/tuplesortvariants.c:1554 #, c-format msgid "Key %s is duplicated." msgstr "La llave %s está duplicada." -#: utils/sort/tuplesortvariants.c:1367 +#: utils/sort/tuplesortvariants.c:1555 #, c-format msgid "Duplicate keys exist." msgstr "Existe una llave duplicada." @@ -29648,412 +30490,426 @@ msgstr "Existe una llave duplicada." msgid "could not seek in tuplestore temporary file" msgstr "no se pudo posicionar (seek) en el archivo temporal del tuplestore" -#: utils/time/snapmgr.c:571 +#: utils/time/snapmgr.c:536 #, c-format msgid "The source transaction is not running anymore." msgstr "La transacción de origen ya no está en ejecución." -#: utils/time/snapmgr.c:1166 +#: utils/time/snapmgr.c:1136 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "no se puede exportar snapshots desde una subtransacción" -#: utils/time/snapmgr.c:1325 utils/time/snapmgr.c:1330 -#: utils/time/snapmgr.c:1335 utils/time/snapmgr.c:1350 -#: utils/time/snapmgr.c:1355 utils/time/snapmgr.c:1360 -#: utils/time/snapmgr.c:1375 utils/time/snapmgr.c:1380 -#: utils/time/snapmgr.c:1385 utils/time/snapmgr.c:1487 -#: utils/time/snapmgr.c:1503 utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 +#: utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 +#: utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 +#: utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 +#: utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 +#: utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "datos no válidos en archivo de snapshot «%s»" -#: utils/time/snapmgr.c:1422 +#: utils/time/snapmgr.c:1393 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "SET TRANSACTION SNAPSHOT debe ser llamado antes de cualquier consulta" -#: utils/time/snapmgr.c:1431 +#: utils/time/snapmgr.c:1402 #, c-format msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ" msgstr "una transacción que importa un snapshot no debe tener nivel de aislación SERIALIZABLE o REPEATABLE READ" -#: utils/time/snapmgr.c:1440 utils/time/snapmgr.c:1449 +#: utils/time/snapmgr.c:1411 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "identificador de snapshot no válido: «%s»" -#: utils/time/snapmgr.c:1541 +#: utils/time/snapmgr.c:1426 +#, c-format +msgid "snapshot \"%s\" does not exist" +msgstr "no existe el snapshot «%s»" + +#: utils/time/snapmgr.c:1524 #, c-format msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction" msgstr "una transacción serializable no puede importar un snapshot desde una transacción no serializable" -#: utils/time/snapmgr.c:1545 +#: utils/time/snapmgr.c:1528 #, c-format msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction" msgstr "una transacción serializable que no es de sólo lectura no puede importar un snapshot de una transacción de sólo lectura" -#: utils/time/snapmgr.c:1560 +#: utils/time/snapmgr.c:1543 #, c-format msgid "cannot import a snapshot from a different database" msgstr "no se puede importar un snapshot desde una base de datos diferente" -#: gram.y:1200 +#: gram.y:1231 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "UNENCRYPTED PASSWORD ya no está soportado" -#: gram.y:1201 +#: gram.y:1232 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." msgstr "Quite UNENCRYPTED para almacenar la contraseña en su lugar en forma cifrada." -#: gram.y:1528 gram.y:1544 +#: gram.y:1559 gram.y:1575 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "CREATE SCHEMA IF NOT EXISTS no puede incluir elementos de esquema" -#: gram.y:1696 +#: gram.y:1727 #, c-format msgid "current database cannot be changed" msgstr "no se puede cambiar la base de datos activa" -#: gram.y:1829 +#: gram.y:1860 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "el intervalo de huso horario debe ser HOUR o HOUR TO MINUTE" -#: gram.y:2446 +#: gram.y:2487 #, c-format msgid "column number must be in range from 1 to %d" msgstr "el número de columna debe estar en el rango de 1 a %d" -#: gram.y:3042 +#: gram.y:3083 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "la opción de secuencia «%s» no está soportada aquí" -#: gram.y:3071 +#: gram.y:3122 #, c-format msgid "modulus for hash partition provided more than once" msgstr "el módulo para partición de hash fue especificado más de una vez" -#: gram.y:3080 +#: gram.y:3131 #, c-format msgid "remainder for hash partition provided more than once" msgstr "el remanente para partición de hash fue especificado más de una vez" -#: gram.y:3087 +#: gram.y:3138 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "especificación de borde de partición hash «%s» no reconocida" -#: gram.y:3095 +#: gram.y:3146 #, c-format msgid "modulus for hash partition must be specified" msgstr "el módulo para una partición hash debe ser especificado" -#: gram.y:3099 +#: gram.y:3150 #, c-format msgid "remainder for hash partition must be specified" msgstr "remanente en partición hash debe ser especificado" -#: gram.y:3307 gram.y:3341 +#: gram.y:3358 gram.y:3392 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "STDIN/STDOUT no están permitidos con PROGRAM" -#: gram.y:3313 +#: gram.y:3364 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "la cláusula WHERE no está permitida con COPY TO" -#: gram.y:3652 gram.y:3659 gram.y:12824 gram.y:12832 +#: gram.y:3712 gram.y:3719 gram.y:13023 gram.y:13031 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "GLOBAL está obsoleto para la creación de tablas temporales" -#: gram.y:3935 +#: gram.y:3995 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" msgstr "para una columna generada, GENERATED ALWAYS debe ser especificado" -#: gram.y:4318 -#, fuzzy, c-format -#| msgid "return type %s is not supported for SQL functions" +#: gram.y:4432 +#, c-format msgid "a column list with %s is only supported for ON DELETE actions" -msgstr "el tipo de retorno %s no es soportado en funciones SQL" +msgstr "una lista de columnas con %s sólo está soportada para acciones ON DELETE" -#: gram.y:5030 +#: gram.y:5151 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM ya no está soportado" -#: gram.y:5728 +#: gram.y:5849 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "opción de seguridad de registro «%s» no reconocida" -#: gram.y:5729 +#: gram.y:5850 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." msgstr "sólo se admiten actualmente políticas PERMISSIVE o RESTRICTIVE." -#: gram.y:5814 +#: gram.y:5935 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGER no está soportado" -#: gram.y:5851 +#: gram.y:5972 msgid "duplicate trigger events specified" -msgstr "se han especificado eventos de disparador duplicados" +msgstr "se han especificado “triggers” por eventos duplicados" -#: gram.y:6000 +#: gram.y:6121 #, c-format msgid "conflicting constraint properties" msgstr "propiedades de restricción contradictorias" -#: gram.y:6099 +#: gram.y:6220 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "CREATE ASSERTION no está implementado" -#: gram.y:6507 +#: gram.y:6537 +#, c-format +msgid "dropping an enum value is not implemented" +msgstr "eliminar un valor de enum no está implementado" + +#: gram.y:6655 #, c-format msgid "RECHECK is no longer required" msgstr "RECHECK ya no es requerido" -#: gram.y:6508 +#: gram.y:6656 #, c-format msgid "Update your data type." msgstr "Actualice su tipo de datos." -#: gram.y:8381 +#: gram.y:8529 #, c-format msgid "aggregates cannot have output arguments" msgstr "las funciones de agregación no pueden tener argumentos de salida" -#: gram.y:11057 gram.y:11076 +#: gram.y:11221 gram.y:11240 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "WITH CHECK OPTION no está soportado con vistas recursivas" -#: gram.y:12963 +#: gram.y:13162 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "la sintaxis LIMIT #,# no está soportada" -#: gram.y:12964 +#: gram.y:13163 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "Use cláusulas LIMIT y OFFSET separadas." -#: gram.y:13824 +#: gram.y:14038 #, c-format msgid "only one DEFAULT value is allowed" msgstr "Sólo se permite un valor DEFAULT" -#: gram.y:13833 +#: gram.y:14047 #, c-format msgid "only one PATH value per column is allowed" msgstr "sólo se permite un valor de PATH por columna" -#: gram.y:13842 +#: gram.y:14056 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "declaraciones NULL/NOT NULL en conflicto o redundantes para la columna «%s»" -#: gram.y:13851 +#: gram.y:14065 #, c-format msgid "unrecognized column option \"%s\"" msgstr "opción de columna «%s» no reconocida" -#: gram.y:14105 +#: gram.y:14147 +#, c-format +msgid "only string constants are supported in JSON_TABLE path specification" +msgstr "sólo cadenas constantes están permitidas en la especificación de ruta JSON_TABLE" + +#: gram.y:14469 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "la precisión para el tipo float debe ser al menos 1 bit" -#: gram.y:14114 +#: gram.y:14478 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "la precisión para el tipo float debe ser menor de 54 bits" -#: gram.y:14617 +#: gram.y:14995 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "el número de parámetros es incorrecto al lado izquierdo de la expresión OVERLAPS" -#: gram.y:14622 +#: gram.y:15000 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "el número de parámetros es incorrecto al lado derecho de la expresión OVERLAPS" -#: gram.y:14799 +#: gram.y:15177 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "el predicado UNIQUE no está implementado" -#: gram.y:15215 +#: gram.y:15591 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "no se permiten múltiples cláusulas ORDER BY con WITHIN GROUP" -#: gram.y:15220 +#: gram.y:15596 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "no se permite DISTINCT con WITHIN GROUP" -#: gram.y:15225 +#: gram.y:15601 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "no se permite VARIADIC con WITHIN GROUP" -#: gram.y:15859 gram.y:15883 +#: gram.y:16328 gram.y:16352 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "el inicio de «frame» no puede ser UNBOUNDED FOLLOWING" -#: gram.y:15864 +#: gram.y:16333 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "el «frame» que se inicia desde la siguiente fila no puede terminar en la fila actual" -#: gram.y:15888 +#: gram.y:16357 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "el fin de «frame» no puede ser UNBOUNDED PRECEDING" -#: gram.y:15894 +#: gram.y:16363 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "el «frame» que se inicia desde la fila actual no puede tener filas precedentes" -#: gram.y:15901 +#: gram.y:16370 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "el «frame» que se inicia desde la fila siguiente no puede tener filas precedentes" -#: gram.y:16660 +#: gram.y:16919 +#, c-format +msgid "unrecognized JSON encoding: %s" +msgstr "no se reconoce la codificación JSON: %s" + +#: gram.y:17243 #, c-format msgid "type modifier cannot have parameter name" msgstr "el modificador de tipo no puede tener nombre de parámetro" -#: gram.y:16666 +#: gram.y:17249 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "el modificador de tipo no puede tener ORDER BY" -#: gram.y:16734 gram.y:16741 gram.y:16748 +#: gram.y:17317 gram.y:17324 gram.y:17331 #, c-format msgid "%s cannot be used as a role name here" msgstr "%s no puede ser usado como nombre de rol aquí" -#: gram.y:16838 gram.y:18295 +#: gram.y:17421 gram.y:18906 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" msgstr "la opción WITH TIES no puede ser especificada sin una cláusula ORDER BY" -#: gram.y:17974 gram.y:18161 +#: gram.y:18597 gram.y:18772 msgid "improper use of \"*\"" msgstr "uso impropio de «*»" -#: gram.y:18225 +#: gram.y:18836 #, c-format msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type" msgstr "una agregación de conjunto-ordenado con un argumento directo VARIADIC debe tener al menos un argumento agregado VARIADIC del mismo tipo de datos" -#: gram.y:18262 +#: gram.y:18873 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "no se permiten múltiples cláusulas ORDER BY" -#: gram.y:18273 +#: gram.y:18884 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "no se permiten múltiples cláusulas OFFSET" -#: gram.y:18282 +#: gram.y:18893 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "no se permiten múltiples cláusulas LIMIT" -#: gram.y:18291 +#: gram.y:18902 #, c-format msgid "multiple limit options not allowed" msgstr "no se permiten múltiples opciones limit" -#: gram.y:18318 +#: gram.y:18929 #, c-format msgid "multiple WITH clauses not allowed" msgstr "no se permiten múltiples cláusulas WITH" -#: gram.y:18511 +#: gram.y:19122 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "los argumentos OUT e INOUT no están permitidos en funciones TABLE" -#: gram.y:18644 +#: gram.y:19255 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "no se permiten múltiples cláusulas COLLATE" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18682 gram.y:18695 +#: gram.y:19293 gram.y:19306 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "las restricciones %s no pueden ser marcadas DEFERRABLE" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18708 +#: gram.y:19319 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "las restricciones %s no pueden ser marcadas NOT VALID" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18721 +#: gram.y:19332 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "las restricciones %s no pueden ser marcadas NO INHERIT" -#: gram.y:18743 +#: gram.y:19354 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "estrategia de particionamiento «%s» no reconocida" -#: gram.y:18767 -#, fuzzy, c-format -#| msgid "invalid publication_names syntax" +#: gram.y:19378 +#, c-format msgid "invalid publication object list" -msgstr "sintaxis de publication_names no válida" +msgstr "sintaxis de lista de objetos de publicación no válida" -#: gram.y:18768 +#: gram.y:19379 #, c-format msgid "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name." -msgstr "" +msgstr "Uno de TABLE o TABLES IN SCHEMA debe ser especificado antes de un nombre de tabla o esquema." -#: gram.y:18784 -#, fuzzy, c-format -#| msgid "invalid locale name \"%s\"" +#: gram.y:19395 +#, c-format msgid "invalid table name" -msgstr "nombre de configuración regional «%s» no es válido" +msgstr "nombre de tabla no válido" -#: gram.y:18805 -#, fuzzy, c-format -#| msgid "WHERE clause not allowed with COPY TO" +#: gram.y:19416 +#, c-format msgid "WHERE clause not allowed for schema" -msgstr "la cláusula WHERE no está permitida con COPY TO" +msgstr "cláusula WHERE no permitida para esquemas" -#: gram.y:18812 -#, fuzzy, c-format -#| msgid "interval specification not allowed here" +#: gram.y:19423 +#, c-format msgid "column specification not allowed for schema" -msgstr "la especificación de intervalo no está permitida aquí" +msgstr "especificación de columnas no permitida para esquemas" -#: gram.y:18826 -#, fuzzy, c-format -#| msgid "invalid fork name" +#: gram.y:19437 +#, c-format msgid "invalid schema name" -msgstr "nombre de «fork» no válido" +msgstr "nombre de esquema no válido" #: guc-file.l:192 #, c-format @@ -30095,54 +30951,47 @@ msgstr "error de sintaxis en el archivo «%s» línea %u, cerca de la palabra « msgid "too many syntax errors found, abandoning file \"%s\"" msgstr "se encontraron demasiados errores de sintaxis, abandonando el archivo «%s»" -#: jsonpath_gram.y:529 +#: jsonpath_gram.y:267 +#, c-format +msgid ".decimal() can only have an optional precision[,scale]." +msgstr ".decimal() sólo puede tener un parámetro opcional precisión[,escala]." + +#: jsonpath_gram.y:599 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." -msgstr "" +msgstr "Carácter de bandera «%.*s» no reconocido en predicado LIKE_REGEX." -#: jsonpath_gram.y:607 +#: jsonpath_gram.y:677 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "la opción «x» de XQuery (expresiones regulares expandidas) no está implementada" #: jsonpath_scan.l:174 -#, fuzzy -#| msgid "invalid Unicode escape" -msgid "invalid unicode sequence" -msgstr "valor de escape Unicode no válido" +msgid "invalid Unicode escape sequence" +msgstr "secuencia de escape Unicode no válida" #: jsonpath_scan.l:180 -#, fuzzy -#| msgid "invalid character" -msgid "invalid hex character sequence" -msgstr "carácter no válido" +msgid "invalid hexadecimal character sequence" +msgstr "secuencia de caracteres hexadecimales no válido" #: jsonpath_scan.l:195 -#, fuzzy -#| msgid "unexpected end of line" msgid "unexpected end after backslash" -msgstr "fin de línea inesperado" +msgstr "fin inesperado después de backslash" -#: jsonpath_scan.l:201 -#, fuzzy -#| msgid "unexpected end of line" -msgid "unexpected end of quoted string" -msgstr "fin de línea inesperado" +#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:756 +msgid "unterminated quoted string" +msgstr "una cadena de caracteres entre comillas está inconclusa" #: jsonpath_scan.l:228 -#, fuzzy -#| msgid "unexpected end of line" msgid "unexpected end of comment" -msgstr "fin de línea inesperado" +msgstr "fin de comentario inesperado" #: jsonpath_scan.l:319 -#, fuzzy -#| msgid "numeric_literal" msgid "invalid numeric literal" -msgstr "literal_numérico" +msgstr "literal numérico no válido" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1049 -#: scan.l:1053 scan.l:1057 scan.l:1061 scan.l:1065 scan.l:1069 scan.l:1073 +#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1064 +#: scan.l:1068 scan.l:1072 scan.l:1076 msgid "trailing junk after numeric literal" msgstr "basura sigue después de un literal numérico" @@ -30158,162 +31007,139 @@ msgstr "%s al final de la entrada jsonpath" msgid "%s at or near \"%s\" of jsonpath input" msgstr "%s en o cerca de «%s» de la entrada jsonpath" -#: jsonpath_scan.l:557 -msgid "bogus input" -msgstr "" +#: jsonpath_scan.l:568 +msgid "invalid input" +msgstr "entrada no válida" -#: jsonpath_scan.l:583 -#, fuzzy -#| msgid "invalid hexadecimal digit: \"%.*s\"" +#: jsonpath_scan.l:594 msgid "invalid hexadecimal digit" -msgstr "dígito hexadecimal no válido: «%.*s»" +msgstr "dígito hexadecimal no válido" -#: jsonpath_scan.l:614 -#, fuzzy, c-format -#| msgid "could not encode server key" -msgid "could not convert unicode to server encoding" -msgstr "no se pudo codificar la llave del servidor" +#: jsonpath_scan.l:625 +#, c-format +msgid "could not convert Unicode to server encoding" +msgstr "no se pudo convertir Unicode a la codificación del servidor" -#: repl_gram.y:301 repl_gram.y:333 +#: repl_gram.y:318 repl_gram.y:359 #, c-format msgid "invalid timeline %u" msgstr "timeline %u no válido" -#: repl_scanner.l:152 -#, fuzzy -#| msgid "invalid transaction termination" +#: repl_scanner.l:154 msgid "invalid streaming start location" -msgstr "terminación de transacción no válida" - -#: repl_scanner.l:209 scan.l:741 -msgid "unterminated quoted string" -msgstr "una cadena de caracteres entre comillas está inconclusa" +msgstr "ubicación de inicio de flujo no válida" -#: scan.l:482 +#: scan.l:497 msgid "unterminated /* comment" msgstr "un comentario /* está inconcluso" -#: scan.l:502 +#: scan.l:517 msgid "unterminated bit string literal" msgstr "una cadena de bits está inconclusa" -#: scan.l:516 +#: scan.l:531 msgid "unterminated hexadecimal string literal" msgstr "una cadena hexadecimal está inconclusa" -#: scan.l:566 +#: scan.l:581 #, c-format msgid "unsafe use of string constant with Unicode escapes" msgstr "uso inseguro de literal de cadena con escapes Unicode" -#: scan.l:567 +#: scan.l:582 #, c-format -msgid "String constants with Unicode escapes cannot be used when standard_conforming_strings is off." -msgstr "Los literales de cadena con escapes Unicode no pueden usarse cuando standard_conforming_strings está desactivado." +msgid "String constants with Unicode escapes cannot be used when \"standard_conforming_strings\" is off." +msgstr "Los literales de cadena con escapes Unicode no pueden usarse cuando «standard_conforming_strings» está desactivado." -#: scan.l:628 +#: scan.l:643 msgid "unhandled previous state in xqs" msgstr "estado previo no manejado en xqs" -#: scan.l:702 +#: scan.l:717 #, c-format msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX." msgstr "Los escapes Unicode deben ser \\uXXXX o \\UXXXXXXXX." -#: scan.l:713 +#: scan.l:728 #, c-format msgid "unsafe use of \\' in a string literal" msgstr "uso inseguro de \\' en un literal de cadena" -#: scan.l:714 +#: scan.l:729 #, c-format msgid "Use '' to write quotes in strings. \\' is insecure in client-only encodings." msgstr "Use '' para escribir comillas en cadenas. \\' es inseguro en codificaciones de sólo cliente." -#: scan.l:786 +#: scan.l:801 msgid "unterminated dollar-quoted string" msgstr "una cadena separada por $ está inconclusa" -#: scan.l:803 scan.l:813 +#: scan.l:818 scan.l:828 msgid "zero-length delimited identifier" msgstr "un identificador delimitado tiene largo cero" -#: scan.l:824 syncrep_scanner.l:101 +#: scan.l:839 syncrep_scanner.l:101 msgid "unterminated quoted identifier" msgstr "un identificador entre comillas está inconcluso" -#: scan.l:987 +#: scan.l:1002 msgid "operator too long" msgstr "el operador es demasiado largo" -#: scan.l:1000 +#: scan.l:1015 msgid "trailing junk after parameter" msgstr "basura sigue después de un parámetro" -#: scan.l:1021 -#, fuzzy -#| msgid "invalid hexadecimal string literal" +#: scan.l:1036 msgid "invalid hexadecimal integer" -msgstr "cadena hexadecimal no válida" +msgstr "entero hexadecimal no válido" -#: scan.l:1025 -#, fuzzy -#| msgid "invalid Datum pointer" +#: scan.l:1040 msgid "invalid octal integer" -msgstr "puntero a Datum no válido" +msgstr "entero octal no válido" -#: scan.l:1029 -#, fuzzy -#| msgid "invalid Datum pointer" +#: scan.l:1044 msgid "invalid binary integer" -msgstr "puntero a Datum no válido" +msgstr "entero binario no válido" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1236 +#: scan.l:1239 #, c-format msgid "%s at end of input" msgstr "%s al final de la entrada" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1244 +#: scan.l:1247 #, c-format msgid "%s at or near \"%s\"" msgstr "%s en o cerca de «%s»" -#: scan.l:1434 +#: scan.l:1439 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "uso no estandar de \\' en un literal de cadena" -#: scan.l:1435 +#: scan.l:1440 #, c-format msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "Use '' para escribir comillas en cadenas, o use la sintaxis de escape de cadenas (E'...')." -#: scan.l:1444 +#: scan.l:1449 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "uso no estandar de \\\\ en un literal de cadena" -#: scan.l:1445 +#: scan.l:1450 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "Use '' para escribir comillas en cadenas, o use la sintaxis de escape de cadenas (E'\\\\')." -#: scan.l:1459 +#: scan.l:1464 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "uso no estandar de escape en un literal de cadena" -#: scan.l:1460 +#: scan.l:1465 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "Use la sintaxis de escape para cadenas, por ej. E'\\r\\n'." - -#, c-format -#~ msgid "value for compression option \"%s\" must be a boolean" -#~ msgstr "el valor para la opción de compresión «%s» debe ser un booleano" - -#, c-format -#~ msgid "String contains unexpected escape sequence \"%c\"." -#~ msgstr "La cadena contiene la secuencia de escape inesperada «%c»." diff --git a/src/backend/po/ja.po b/src/backend/po/ja.po index 1e638d075be6b..5309f0ca14d47 100644 --- a/src/backend/po/ja.po +++ b/src/backend/po/ja.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: postgres (PostgreSQL 17)\n" +"Project-Id-Version: postgres (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-11 15:46+0900\n" -"PO-Revision-Date: 2024-06-11 16:55+0900\n" +"POT-Creation-Date: 2025-04-09 09:36+0900\n" +"PO-Revision-Date: 2025-04-09 10:06+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: jpug-doc \n" "Language: ja\n" @@ -82,25 +82,25 @@ msgstr "圧縮アルゴリズム\"%s\"は長距離モードをサポートしま msgid "not recorded" msgstr "記録されていません" -#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 commands/copyfrom.c:1737 commands/extension.c:3538 utils/adt/genfile.c:123 utils/time/snapmgr.c:1430 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 commands/copyfrom.c:1879 commands/extension.c:3807 utils/adt/genfile.c:123 utils/time/snapmgr.c:1437 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "ファイル\"%s\"を読み込み用にオープンできませんでした: %m" -#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 access/transam/timeline.c:143 access/transam/timeline.c:362 access/transam/twophase.c:1369 access/transam/xlog.c:3471 access/transam/xlog.c:4335 access/transam/xlogrecovery.c:1238 access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 -#: replication/logical/origin.c:745 replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5084 replication/logical/snapbuild.c:2035 replication/slot.c:2236 replication/slot.c:2277 replication/walsender.c:655 storage/file/buffile.c:470 storage/file/copydir.c:185 utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 access/transam/timeline.c:143 access/transam/timeline.c:362 access/transam/twophase.c:1353 access/transam/xlog.c:3621 access/transam/xlog.c:4512 access/transam/xlogrecovery.c:1246 access/transam/xlogrecovery.c:1344 access/transam/xlogrecovery.c:1381 access/transam/xlogrecovery.c:1448 backup/basebackup.c:2128 backup/walsummary.c:283 commands/extension.c:3817 libpq/hba.c:769 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5236 replication/logical/snapbuild.c:1903 replication/slot.c:2430 replication/slot.c:2471 replication/walsender.c:629 storage/file/buffile.c:470 storage/file/copydir.c:201 utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "ファイル\"%s\"の読み込みに失敗しました: %m" -#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 access/transam/xlog.c:3476 access/transam/xlog.c:4340 replication/logical/origin.c:750 replication/logical/origin.c:789 replication/logical/snapbuild.c:2040 replication/slot.c:2240 replication/slot.c:2281 replication/walsender.c:660 utils/cache/relmapper.c:833 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 access/transam/xlog.c:3626 access/transam/xlog.c:4517 replication/logical/origin.c:750 replication/logical/origin.c:789 replication/logical/snapbuild.c:1908 replication/slot.c:2434 replication/slot.c:2475 replication/walsender.c:634 utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" -#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 access/transam/timeline.c:392 access/transam/timeline.c:438 access/transam/timeline.c:512 access/transam/twophase.c:1381 access/transam/twophase.c:1793 access/transam/xlog.c:3317 access/transam/xlog.c:3511 access/transam/xlog.c:3516 access/transam/xlog.c:3652 -#: access/transam/xlog.c:4305 access/transam/xlog.c:5239 commands/copyfrom.c:1797 commands/copyto.c:325 libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 replication/logical/origin.c:683 replication/logical/origin.c:822 replication/logical/reorderbuffer.c:5136 replication/logical/snapbuild.c:1802 replication/logical/snapbuild.c:1926 replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 storage/file/copydir.c:208 storage/file/copydir.c:213 -#: storage/file/fd.c:828 storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 utils/cache/relmapper.c:956 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 access/transam/timeline.c:392 access/transam/timeline.c:438 access/transam/timeline.c:512 access/transam/twophase.c:1365 access/transam/twophase.c:1783 access/transam/xlog.c:3467 access/transam/xlog.c:3661 access/transam/xlog.c:3666 access/transam/xlog.c:3802 +#: access/transam/xlog.c:4482 access/transam/xlog.c:5458 commands/copyfrom.c:1929 commands/copyto.c:598 libpq/be-fsstubs.c:475 libpq/be-fsstubs.c:545 replication/logical/origin.c:683 replication/logical/origin.c:822 replication/logical/reorderbuffer.c:5288 replication/logical/snapbuild.c:1648 replication/logical/snapbuild.c:1774 replication/slot.c:2319 replication/slot.c:2482 replication/walsender.c:644 storage/file/copydir.c:224 storage/file/copydir.c:229 +#: storage/file/copydir.c:284 storage/file/copydir.c:289 storage/file/fd.c:828 storage/file/fd.c:3818 storage/file/fd.c:3924 utils/cache/relmapper.c:841 utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "ファイル\"%s\"をクローズできませんでした: %m" @@ -122,41 +122,41 @@ msgstr "" "されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" "PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" -#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 ../common/file_utils.c:70 ../common/file_utils.c:347 ../common/file_utils.c:406 ../common/file_utils.c:480 access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 access/transam/timeline.c:251 access/transam/timeline.c:348 access/transam/twophase.c:1325 access/transam/xlog.c:3224 access/transam/xlog.c:3387 access/transam/xlog.c:3426 access/transam/xlog.c:3619 access/transam/xlog.c:4325 -#: access/transam/xlogrecovery.c:4263 access/transam/xlogrecovery.c:4366 access/transam/xlogutils.c:836 backup/basebackup.c:547 backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 postmaster/syslogger.c:1511 replication/logical/origin.c:735 replication/logical/reorderbuffer.c:3737 replication/logical/reorderbuffer.c:4291 replication/logical/reorderbuffer.c:5064 replication/logical/snapbuild.c:1757 replication/logical/snapbuild.c:1867 -#: replication/slot.c:2208 replication/walsender.c:628 replication/walsender.c:3051 storage/file/copydir.c:151 storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 utils/cache/relmapper.c:935 utils/error/elog.c:2091 utils/init/miscinit.c:1526 utils/init/miscinit.c:1660 utils/init/miscinit.c:1737 utils/misc/guc.c:4727 utils/misc/guc.c:4777 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 ../common/file_utils.c:69 ../common/file_utils.c:370 ../common/file_utils.c:428 ../common/file_utils.c:502 access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 access/transam/timeline.c:251 access/transam/timeline.c:348 access/transam/twophase.c:1309 access/transam/xlog.c:3357 access/transam/xlog.c:3537 access/transam/xlog.c:3576 access/transam/xlog.c:3769 access/transam/xlog.c:4502 +#: access/transam/xlogrecovery.c:4285 access/transam/xlogrecovery.c:4386 access/transam/xlogutils.c:825 backup/basebackup.c:549 backup/basebackup.c:1600 backup/walsummary.c:220 libpq/hba.c:626 postmaster/syslogger.c:1512 replication/logical/origin.c:735 replication/logical/reorderbuffer.c:3889 replication/logical/reorderbuffer.c:4443 replication/logical/reorderbuffer.c:5216 replication/logical/snapbuild.c:1603 replication/logical/snapbuild.c:1715 +#: replication/slot.c:2402 replication/walsender.c:602 replication/walsender.c:3056 storage/file/copydir.c:167 storage/file/copydir.c:255 storage/file/fd.c:803 storage/file/fd.c:3575 storage/file/fd.c:3805 storage/file/fd.c:3895 storage/smgr/md.c:675 utils/cache/relmapper.c:818 utils/cache/relmapper.c:935 utils/error/elog.c:2149 utils/init/miscinit.c:1585 utils/init/miscinit.c:1719 utils/init/miscinit.c:1796 utils/misc/guc.c:4774 utils/misc/guc.c:4824 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 access/transam/twophase.c:1766 access/transam/twophase.c:1775 access/transam/xlog.c:9210 access/transam/xlogfuncs.c:698 backup/basebackup_server.c:173 backup/basebackup_server.c:266 backup/walsummary.c:304 postmaster/postmaster.c:4125 postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 access/transam/twophase.c:1756 access/transam/twophase.c:1765 access/transam/xlog.c:9467 access/transam/xlogfuncs.c:699 backup/basebackup_server.c:173 backup/basebackup_server.c:266 backup/walsummary.c:304 postmaster/postmaster.c:4098 postmaster/syslogger.c:1523 postmaster/syslogger.c:1536 postmaster/syslogger.c:1549 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 ../common/file_utils.c:418 ../common/file_utils.c:488 access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 access/transam/timeline.c:506 access/transam/twophase.c:1787 access/transam/xlog.c:3310 access/transam/xlog.c:3505 access/transam/xlog.c:4298 access/transam/xlog.c:8585 access/transam/xlog.c:8630 -#: backup/basebackup_server.c:207 commands/dbcommands.c:514 replication/logical/snapbuild.c:1795 replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 storage/file/fd.c:3851 storage/smgr/md.c:1329 storage/smgr/md.c:1374 storage/sync/sync.c:446 utils/misc/guc.c:4480 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 ../common/file_utils.c:440 ../common/file_utils.c:510 access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 access/transam/timeline.c:506 access/transam/twophase.c:1777 access/transam/xlog.c:3457 access/transam/xlog.c:3655 access/transam/xlog.c:4475 access/transam/xlog.c:8853 access/transam/xlog.c:8897 +#: backup/basebackup_server.c:207 commands/dbcommands.c:515 replication/logical/snapbuild.c:1641 replication/slot.c:2305 replication/slot.c:2412 storage/file/fd.c:820 storage/file/fd.c:3916 storage/smgr/md.c:1455 storage/smgr/md.c:1515 storage/sync/sync.c:446 utils/misc/guc.c:4527 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 ../common/md5_common.c:156 ../common/parse_manifest.c:157 ../common/parse_manifest.c:853 ../common/psprintf.c:143 ../common/scram-common.c:269 ../common/stringinfo.c:314 ../port/path.c:751 ../port/path.c:788 -#: ../port/path.c:805 access/transam/twophase.c:1434 access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 postmaster/bgworker.c:355 postmaster/bgworker.c:945 postmaster/postmaster.c:3559 postmaster/postmaster.c:4019 postmaster/postmaster.c:4381 postmaster/walsummarizer.c:820 replication/libpqwalreceiver/libpqwalreceiver.c:387 replication/logical/logical.c:209 replication/walsender.c:835 -#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1453 storage/ipc/procarray.c:2207 storage/ipc/procarray.c:2214 storage/ipc/procarray.c:2719 storage/ipc/procarray.c:3423 utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 utils/adt/formatting.c:2075 utils/adt/pg_locale.c:509 utils/adt/pg_locale.c:673 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 -#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 utils/misc/guc.c:4458 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 utils/mmgr/slab.c:370 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 ../common/cryptohash_openssl.c:356 ../common/exec.c:543 ../common/exec.c:588 ../common/exec.c:680 ../common/hmac.c:309 ../common/hmac.c:325 ../common/hmac_openssl.c:151 ../common/hmac_openssl.c:339 ../common/jsonapi.c:2407 ../common/md5_common.c:156 ../common/parse_manifest.c:157 ../common/parse_manifest.c:852 ../common/psprintf.c:140 ../common/scram-common.c:268 ../port/path.c:829 ../port/path.c:866 +#: ../port/path.c:883 access/transam/twophase.c:1418 access/transam/xlogrecovery.c:570 lib/dshash.c:253 libpq/auth.c:1345 libpq/auth.c:1389 libpq/auth.c:1951 libpq/be-secure-gssapi.c:527 postmaster/bgworker.c:355 postmaster/bgworker.c:1022 postmaster/postmaster.c:3568 postmaster/walsummarizer.c:942 replication/libpqwalreceiver/libpqwalreceiver.c:351 replication/logical/logical.c:210 replication/walsender.c:811 storage/buffer/localbuf.c:745 storage/file/fd.c:912 +#: storage/file/fd.c:1447 storage/file/fd.c:1608 storage/file/fd.c:2592 storage/ipc/procarray.c:1465 storage/ipc/procarray.c:2217 storage/ipc/procarray.c:2224 storage/ipc/procarray.c:2727 storage/ipc/procarray.c:3436 utils/adt/pg_locale.c:509 utils/adt/pg_locale.c:583 utils/adt/pg_locale_icu.c:364 utils/adt/pg_locale_libc.c:207 utils/adt/pg_locale_libc.c:302 utils/adt/pg_locale_libc.c:390 utils/fmgr/dfmgr.c:219 utils/hash/dynahash.c:516 utils/hash/dynahash.c:616 +#: utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 utils/misc/guc.c:647 utils/misc/guc.c:672 utils/misc/guc.c:1060 utils/misc/guc.c:4505 utils/misc/tzparser.c:479 utils/mmgr/aset.c:451 utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1230 utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "メモリ不足です" -#: ../common/cryptohash.c:266 ../common/cryptohash.c:272 ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 ../common/hmac_openssl.c:377 +#: ../common/cryptohash.c:266 ../common/cryptohash.c:272 ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:351 ../common/hmac_openssl.c:359 msgid "success" msgstr "成功" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 ../common/hmac_openssl.c:371 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 ../common/hmac_openssl.c:353 msgid "destination buffer too small" msgstr "出力先バッファが小さすぎます" -#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:355 msgid "OpenSSL failure" msgstr "OpenSSLのエラー" @@ -180,27 +180,27 @@ msgstr "実行すべき\"%s\"がありませんでした" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "パス\"%s\"を絶対パス形式に変換できませんでした: %m" -#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1721 commands/copyto.c:649 libpq/be-secure-common.c:59 +#: ../common/exec.c:363 commands/collationcmds.c:872 commands/copyfrom.c:1863 commands/copyto.c:934 libpq/be-secure-common.c:59 #, c-format msgid "could not execute command \"%s\": %m" msgstr "コマンド\"%s\"を実行できませんでした: %m" -#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#: ../common/exec.c:375 libpq/be-secure-common.c:71 #, c-format msgid "could not read from command \"%s\": %m" msgstr "コマンド\"%s\"から読み取れませんでした: %m" -#: ../common/exec.c:397 +#: ../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "コマンド\"%s\"からデータが返却されませんでした" -#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 storage/ipc/latch.c:1349 storage/ipc/latch.c:1582 storage/ipc/latch.c:1744 storage/ipc/latch.c:1870 +#: ../common/exec.c:405 libpq/pqcomm.c:193 storage/ipc/waiteventset.c:782 storage/ipc/waiteventset.c:962 storage/ipc/waiteventset.c:1202 storage/ipc/waiteventset.c:1364 storage/ipc/waiteventset.c:1490 #, c-format msgid "%s() failed: %m" msgstr "%s() が失敗しました: %m" -#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:790 ../port/path.c:807 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 +#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 ../common/psprintf.c:142 ../port/path.c:831 ../port/path.c:868 ../port/path.c:885 utils/misc/ps_status.c:195 utils/misc/ps_status.c:203 utils/misc/ps_status.c:230 utils/misc/ps_status.c:238 #, c-format msgid "out of memory\n" msgstr "メモリ不足です\n" @@ -210,33 +210,33 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "nullポインタは複製できません(内部エラー)\n" -#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#: ../common/file_utils.c:75 storage/file/fd.c:3581 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../common/file_utils.c:120 ../common/file_utils.c:566 ../common/file_utils.c:570 access/transam/twophase.c:1337 access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1747 commands/copyto.c:695 commands/extension.c:3527 commands/tablespace.c:804 commands/tablespace.c:893 postmaster/pgarch.c:680 -#: replication/logical/snapbuild.c:1653 replication/logical/snapbuild.c:2156 storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 +#: ../common/file_utils.c:123 ../common/file_utils.c:588 ../common/file_utils.c:592 access/transam/twophase.c:1321 access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 backup/basebackup.c:357 backup/basebackup.c:555 backup/basebackup.c:626 backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1889 commands/copyto.c:980 commands/extension.c:3796 commands/tablespace.c:804 commands/tablespace.c:893 postmaster/pgarch.c:682 +#: replication/logical/snapbuild.c:1498 replication/logical/snapbuild.c:2025 storage/file/fd.c:1972 storage/file/fd.c:2060 storage/file/fd.c:3629 utils/adt/dbsize.c:105 utils/adt/dbsize.c:266 utils/adt/dbsize.c:355 utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#: ../common/file_utils.c:133 ../common/file_utils.c:243 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../common/file_utils.c:151 ../common/file_utils.c:281 ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 commands/tablespace.c:738 postmaster/postmaster.c:1468 storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:339 +#: ../common/file_utils.c:156 ../common/file_utils.c:304 ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 commands/tablespace.c:738 postmaster/postmaster.c:1496 storage/file/fd.c:2997 storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:340 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../common/file_utils.c:169 ../common/file_utils.c:315 ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 +#: ../common/file_utils.c:174 ../common/file_utils.c:338 ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:3009 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 postmaster/pgarch.c:834 postmaster/syslogger.c:1559 replication/logical/snapbuild.c:1814 replication/slot.c:936 replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 utils/time/snapmgr.c:1255 +#: ../common/file_utils.c:520 access/transam/xlogarchive.c:389 postmaster/pgarch.c:836 postmaster/syslogger.c:1560 replication/logical/snapbuild.c:1660 replication/slot.c:987 replication/slot.c:2191 replication/slot.c:2333 storage/file/fd.c:838 utils/time/snapmgr.c:1262 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -245,283 +245,287 @@ msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: % msgid "internal error" msgstr "内部エラー" -#: ../common/jsonapi.c:2121 +#: ../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "再帰降下パーサーは差分字句解析器を使用できません。" -#: ../common/jsonapi.c:2123 +#: ../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "差分パーサーは差分字句解析器を必要とします。" -#: ../common/jsonapi.c:2125 +#: ../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSONのネストが深すぎます、可能な最大の深さは6400です。" -#: ../common/jsonapi.c:2127 +#: ../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "エスケープシーケンス\"\\%.*s\"は不正です。" -#: ../common/jsonapi.c:2131 +#: ../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "0x%02x値を持つ文字はエスケープしなければなりません" -#: ../common/jsonapi.c:2135 +#: ../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "入力の終端を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2138 +#: ../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "配列要素または\"]\"を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2141 +#: ../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "\",\"または\"]\"を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2144 +#: ../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "\":\"を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2147 +#: ../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "JSON値を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2150 +#: ../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "入力文字列が予期せず終了しました。" -#: ../common/jsonapi.c:2152 +#: ../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "文字列または\"}\"を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2155 +#: ../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "\",\"または\"}\"を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2158 +#: ../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "文字列を想定していましたが、\"%.*s\"でした。" -#: ../common/jsonapi.c:2161 +#: ../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "トークン\"%.*s\"は不正です。" -#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 +#: ../common/jsonapi.c:2478 jsonpath_scan.l:585 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 はテキストに変換できません。" -#: ../common/jsonapi.c:2166 +#: ../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\"の後には16進数の4桁が続かなければなりません。" -#: ../common/jsonapi.c:2169 +#: ../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "エンコーディングがUTF-8ではない場合、コードポイントの値が 007F 以上についてはUnicodeエスケープの値は使用できません。" -#: ../common/jsonapi.c:2178 +#: ../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Unicodeエスケープの値がサーバーエンコーディング%sに変換できませんでした。" -#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 +#: ../common/jsonapi.c:2499 jsonpath_scan.l:618 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicodeのハイサロゲートはハイサロゲートに続いてはいけません。" -#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 jsonpath_scan.l:713 +#: ../common/jsonapi.c:2501 jsonpath_scan.l:629 jsonpath_scan.l:639 jsonpath_scan.l:691 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicodeのローサロゲートはハイサロゲートに続かなければなりません。" -#: ../common/logging.c:276 +#: ../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "エラー記述の構築中のメモリ不足" + +#: ../common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../common/logging.c:283 +#: ../common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../common/logging.c:294 +#: ../common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../common/logging.c:301 +#: ../common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " -#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:855 +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "目録のチェックサムの初期化ができませんでした" -#: ../common/parse_manifest.c:204 ../common/parse_manifest.c:261 +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "目録が予期せず終了しました。" -#: ../common/parse_manifest.c:210 ../common/parse_manifest.c:862 +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "目録のチェックサムの更新ができませんでした" -#: ../common/parse_manifest.c:302 +#: ../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "予期しないオブジェクトの開始" -#: ../common/parse_manifest.c:337 +#: ../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "予期しないオブジェクトの終わり" -#: ../common/parse_manifest.c:366 +#: ../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "予期しない配列の開始" -#: ../common/parse_manifest.c:391 +#: ../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "予期しない配列の終わり" -#: ../common/parse_manifest.c:418 +#: ../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "バージョン指示子を想定していました" -#: ../common/parse_manifest.c:454 +#: ../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "認識できないトップレベルフィールド" -#: ../common/parse_manifest.c:473 +#: ../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "予期しないファイルフィールド" -#: ../common/parse_manifest.c:487 +#: ../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "予期しないWAL範囲フィールド" -#: ../common/parse_manifest.c:493 +#: ../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "予期しないオブジェクトフィールド" -#: ../common/parse_manifest.c:583 +#: ../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "予期しないスカラー" -#: ../common/parse_manifest.c:609 +#: ../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "目録バージョンが整数ではありません" -#: ../common/parse_manifest.c:613 +#: ../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "予期しない目録バージョン" -#: ../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" -msgstr "目録のシステム識別子が整数ではありません" +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "目録中のシステム識別子が整数ではありません" -#: ../common/parse_manifest.c:662 +#: ../common/parse_manifest.c:661 msgid "missing path name" msgstr "パス名がありません" -#: ../common/parse_manifest.c:665 +#: ../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "パス名とエンコードされたパス名の両方" -#: ../common/parse_manifest.c:667 +#: ../common/parse_manifest.c:666 msgid "missing size" msgstr "サイズがありません" -#: ../common/parse_manifest.c:670 +#: ../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "アルゴリズムなしのチェックサム" -#: ../common/parse_manifest.c:684 +#: ../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ファイル名をデコードできませんでした" -#: ../common/parse_manifest.c:694 +#: ../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ファイルサイズが整数ではありません" -#: ../common/parse_manifest.c:700 backup/basebackup.c:870 +#: ../common/parse_manifest.c:699 backup/basebackup.c:872 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "認識できないチェックサムアルゴリズム: \"%s\"" -#: ../common/parse_manifest.c:719 +#: ../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "\"%s\" ファイルのチェックサムが無効: \"%s\"" -#: ../common/parse_manifest.c:762 +#: ../common/parse_manifest.c:761 msgid "missing timeline" msgstr "タイムラインがありません" -#: ../common/parse_manifest.c:764 +#: ../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "開始LSNがありません" -#: ../common/parse_manifest.c:766 +#: ../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "終了LSNがありません" -#: ../common/parse_manifest.c:772 +#: ../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "タイムラインが整数ではありません" -#: ../common/parse_manifest.c:775 +#: ../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "開始LSNをパースできませんでした" -#: ../common/parse_manifest.c:778 +#: ../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "終了LSNをパースできませんでした" -#: ../common/parse_manifest.c:843 +#: ../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "少なくとも2行が必要です" -#: ../common/parse_manifest.c:846 +#: ../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "最後の行が改行で終わっていません" -#: ../common/parse_manifest.c:865 +#: ../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "目録のチェックサムの完了ができませんでした" -#: ../common/parse_manifest.c:869 +#: ../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "目録にチェックサムがありません" -#: ../common/parse_manifest.c:873 +#: ../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "無効な目録チェックサム: \"%s\"" -#: ../common/parse_manifest.c:877 +#: ../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "目録チェックサムの不一致" -#: ../common/parse_manifest.c:892 +#: ../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "バックアップ目録をパースできませんでした: %s" -#: ../common/percentrepl.c:79 ../common/percentrepl.c:85 ../common/percentrepl.c:118 ../common/percentrepl.c:124 tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 utils/misc/guc.c:3283 utils/misc/guc.c:4662 utils/misc/guc.c:6887 utils/misc/guc.c:6928 +#: ../common/percentrepl.c:79 ../common/percentrepl.c:85 ../common/percentrepl.c:118 ../common/percentrepl.c:124 tcop/backend_startup.c:769 utils/misc/guc.c:3164 utils/misc/guc.c:3205 utils/misc/guc.c:3280 utils/misc/guc.c:4709 utils/misc/guc.c:6929 utils/misc/guc.c:6970 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "パラメータ\"%s\"の値が不正です: \"%s\"" @@ -581,51 +585,56 @@ msgstr "制限付きトークンで再実行できませんでした: %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "サブプロセスの終了コードを取得できませんでした: エラーコード %lu" -#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 access/transam/twophase.c:1726 access/transam/xlogarchive.c:119 access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 postmaster/syslogger.c:1488 replication/logical/origin.c:591 replication/logical/reorderbuffer.c:4560 replication/logical/snapbuild.c:1695 replication/logical/snapbuild.c:2129 replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 storage/file/fd.c:3440 -#: storage/file/reinit.c:261 storage/ipc/dsm.c:343 storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 utils/time/snapmgr.c:1591 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 access/transam/twophase.c:1716 access/transam/xlogarchive.c:119 access/transam/xlogarchive.c:399 postmaster/postmaster.c:1069 postmaster/syslogger.c:1489 replication/logical/origin.c:591 replication/logical/reorderbuffer.c:4711 replication/logical/snapbuild.c:1541 replication/logical/snapbuild.c:1997 replication/slot.c:2386 storage/file/fd.c:878 storage/file/fd.c:3443 storage/file/fd.c:3505 +#: storage/file/reinit.c:261 storage/ipc/dsm.c:343 storage/smgr/md.c:401 storage/smgr/md.c:460 storage/sync/sync.c:243 utils/time/snapmgr.c:1598 #, c-format msgid "could not remove file \"%s\": %m" msgstr "ファイル\"%s\"を削除できませんでした: %m" -#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 storage/file/fd.c:3779 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3435 storage/file/fd.c:3844 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を削除できませんでした: %m" -#: ../common/scram-common.c:282 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "saltのエンコードに失敗しました" -#: ../common/scram-common.c:298 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "nonceのエンコードに失敗しました" -#: ../common/scram-common.c:315 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "サーバーキーのエンコードに失敗しました" -#: ../common/stringinfo.c:315 +#: ../common/stringinfo.c:362 +#, c-format +msgid "string buffer exceeds maximum allowed length (%zu bytes)" +msgstr "文字列バッファの長さが上限値を超えています(%zuバイト)" + +#: ../common/stringinfo.c:363 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "%dバイトを持つ文字列バッファを%dバイト多く、大きくすることができません。" -#: ../common/stringinfo.c:319 +#: ../common/stringinfo.c:367 #, c-format msgid "" -"out of memory\n" +"string buffer exceeds maximum allowed length (%zu bytes)\n" "\n" "Cannot enlarge string buffer containing %d bytes by %d more bytes.\n" msgstr "" -"メモリが足りません\n" +"文字列バッファの長さが上限値を超えています(%zuバイト)\n" "\n" -"%dバイトの文字列バッファを%dバイト拡げることができません。\n" +"%dバイトを格納する文字列バッファを%dバイト拡げることができません。\n" #: ../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" msgstr "実効ユーザーID %ld が見つかりませんでした: %s" -#: ../common/username.c:45 libpq/auth.c:1888 +#: ../common/username.c:45 msgid "user does not exist" msgstr "ユーザーが存在しません" @@ -664,12 +673,12 @@ msgstr "子プロセスはシグナル%dにより終了しました: %s" msgid "child process exited with unrecognized status %d" msgstr "子プロセスは認識できないステータス%dで終了しました" -#: ../port/chklocale.c:283 +#: ../port/chklocale.c:280 #, c-format msgid "could not determine encoding for codeset \"%s\"" msgstr "コードセット\"%s\"用の符号化方式を特定できませんでした" -#: ../port/chklocale.c:404 ../port/chklocale.c:410 +#: ../port/chklocale.c:370 ../port/chklocale.c:376 #, c-format msgid "could not determine encoding for locale \"%s\": codeset is \"%s\"" msgstr "ロケール\"%s\"用の符号化方式を特定できませんでした: コードセットは\"%s\"です" @@ -717,7 +726,7 @@ msgstr "再試行を30秒間続けます。" msgid "You might have antivirus, backup, or similar software interfering with the database system." msgstr "データベースシステムに干渉するアンチウィルス、バックアップといったソフトウェアが存在する可能性があります。" -#: ../port/path.c:775 +#: ../port/path.c:853 #, c-format msgid "could not get current working directory: %m\n" msgstr "現在の作業ディレクトリを取得できませんでした: %m\n" @@ -727,16 +736,6 @@ msgstr "現在の作業ディレクトリを取得できませんでした: %m\n msgid "operating system error %d" msgstr "オペレーティングシステムエラー %d" -#: ../port/user.c:43 ../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "ローカルユーザーID %dの参照に失敗しました: %s" - -#: ../port/user.c:48 ../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "ID %d を持つローカルユーザーは存在しません" - #: ../port/win32security.c:62 #, c-format msgid "could not get SID for Administrators group: error code %lu\n" @@ -752,47 +751,47 @@ msgstr "PowerUsersグループのSIDを取得できませんでした: エラー msgid "could not check access token membership: error code %lu\n" msgstr "アクセストークンのメンバーシップを確認できませんでした: エラーコード %lu\n" -#: access/brin/brin.c:405 +#: access/brin/brin.c:414 #, c-format msgid "request for BRIN range summarization for index \"%s\" page %u was not recorded" msgstr "インデックス\"%s\" ページ%uのBRIN範囲要約のリクエストは登録されていません" -#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 +#: access/brin/brin.c:1397 access/brin/brin.c:1504 access/gin/ginfast.c:1040 access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:242 access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 access/transam/xlogfuncs.c:323 access/transam/xlogfuncs.c:389 access/transam/xlogfuncs.c:447 statistics/attribute_stats.c:190 statistics/attribute_stats.c:931 statistics/relation_stats.c:97 #, c-format msgid "recovery is in progress" msgstr "リカバリは現在進行中です" -#: access/brin/brin.c:1386 access/brin/brin.c:1494 +#: access/brin/brin.c:1398 access/brin/brin.c:1505 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "BRIN制御関数はリカバリ中は実行できません。" -#: access/brin/brin.c:1391 access/brin/brin.c:1499 +#: access/brin/brin.c:1403 access/brin/brin.c:1510 #, c-format -msgid "block number out of range: %lld" -msgstr "ブロック番号が範囲外です: %lld" +msgid "block number out of range: %" +msgstr "ブロック番号が範囲外です: %" -#: access/brin/brin.c:1436 access/brin/brin.c:1525 +#: access/brin/brin.c:1447 access/brin/brin.c:1536 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\"はBRINインデックスではありません" -#: access/brin/brin.c:1452 access/brin/brin.c:1541 +#: access/brin/brin.c:1463 access/brin/brin.c:1552 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "インデックス\"%s\"の親テーブルをオープンできませんでした" -#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 parser/parse_utilcmd.c:2252 +#: access/brin/brin.c:1472 access/brin/brin.c:1568 access/gin/ginfast.c:1085 parser/parse_utilcmd.c:2433 #, c-format msgid "index \"%s\" is not valid" msgstr "インデックス\"%s\"は有効ではありません" -#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 statistics/dependencies.c:661 statistics/dependencies.c:714 statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 +#: access/brin/brin_bloom.c:784 access/brin/brin_bloom.c:826 access/brin/brin_minmax_multi.c:2984 access/brin/brin_minmax_multi.c:3121 statistics/dependencies.c:661 statistics/dependencies.c:714 statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format msgid "cannot accept a value of type %s" msgstr "%s型の値は受け付けられません" -#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 access/spgist/spgdoinsert.c:2278 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 access/gist/gist.c:1475 access/spgist/spgdoinsert.c:2001 access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "インデックス行サイズ%1$zuはインデックス\"%3$s\"での最大値%2$zuを超えています" @@ -807,77 +806,77 @@ msgstr "BRINインデックスが壊れています: 範囲マップの不整合 msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "BRINインデックス\"%2$s\"のブロック %3$u のページタイプが予期しない値 0x%1$04X です" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 +#: access/brin/brin_validate.c:111 access/gin/ginvalidate.c:142 access/gist/gistvalidate.c:150 access/hash/hashvalidate.c:112 access/nbtree/nbtvalidate.c:116 access/spgist/spgvalidate.c:181 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with invalid support number %d" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は不正なサポート番号%4$dを持つ関数%3$sを含んでいます" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 +#: access/brin/brin_validate.c:127 access/gin/ginvalidate.c:154 access/gist/gistvalidate.c:162 access/hash/hashvalidate.c:124 access/nbtree/nbtvalidate.c:128 access/spgist/spgvalidate.c:193 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"はサポート番号%4$dに対して間違ったシグネチャを持つ関数%3$sを含んでいます" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 +#: access/brin/brin_validate.c:149 access/gin/ginvalidate.c:173 access/gist/gistvalidate.c:182 access/hash/hashvalidate.c:150 access/nbtree/nbtvalidate.c:148 access/spgist/spgvalidate.c:213 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は不正なストラテジ番号%4$dを持つ演算子\"%3$s\"を含んでいます" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 access/spgist/spgvalidate.c:237 +#: access/brin/brin_validate.c:178 access/gin/ginvalidate.c:186 access/hash/hashvalidate.c:163 access/nbtree/nbtvalidate.c:161 access/spgist/spgvalidate.c:229 #, c-format msgid "operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は演算子%3$sに対する不正なORDER BY指定を含んでいます" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 +#: access/brin/brin_validate.c:191 access/gin/ginvalidate.c:199 access/gist/gistvalidate.c:230 access/hash/hashvalidate.c:176 access/nbtree/nbtvalidate.c:174 access/spgist/spgvalidate.c:245 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with wrong signature" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は間違ったシグネチャを持つ演算子%3$sを含んでいます" -#: access/brin/brin_validate.c:236 access/hash/hashvalidate.c:226 access/nbtree/nbtvalidate.c:236 access/spgist/spgvalidate.c:280 +#: access/brin/brin_validate.c:229 access/hash/hashvalidate.c:216 access/nbtree/nbtvalidate.c:232 access/spgist/spgvalidate.c:272 #, c-format msgid "operator family \"%s\" of access method %s is missing operator(s) for types %s and %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は%3$sと%4$sの型に対する演算子が含まれていません" -#: access/brin/brin_validate.c:246 +#: access/brin/brin_validate.c:239 #, c-format msgid "operator family \"%s\" of access method %s is missing support function(s) for types %s and %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は型%3$sと%4$sに対するサポート関数を含んでいません" -#: access/brin/brin_validate.c:259 access/hash/hashvalidate.c:240 access/nbtree/nbtvalidate.c:260 access/spgist/spgvalidate.c:315 +#: access/brin/brin_validate.c:252 access/hash/hashvalidate.c:230 access/nbtree/nbtvalidate.c:256 access/spgist/spgvalidate.c:307 #, c-format msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "アクセスメソッド\"%2$s\"の演算子クラス\"%1$s\"は演算子を含んでいません" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 access/gist/gistvalidate.c:273 +#: access/brin/brin_validate.c:263 access/gin/ginvalidate.c:241 access/gist/gistvalidate.c:272 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d" msgstr "アクセスメソッド\"%2$s\"の演算子クラス\"%1$s\"はサポート関数%3$dを含んでいません" -#: access/common/attmap.c:121 +#: access/common/attmap.c:118 #, c-format -msgid "Returned type %s does not match expected type %s in column %d." -msgstr "列%3$dで返された%1$s型が、期待している%2$s型と一致しません。" +msgid "Returned type %s does not match expected type %s in column \"%s\" (position %d)." +msgstr "返却型 %1$s が、列”%3$s\" (位置%4$d)で期待される型 %2$s と一致しません。" -#: access/common/attmap.c:149 +#: access/common/attmap.c:147 #, c-format msgid "Number of returned columns (%d) does not match expected column count (%d)." msgstr "返された列数(%d)が、期待する列数(%d)と一致しません。" -#: access/common/attmap.c:233 access/common/attmap.c:245 +#: access/common/attmap.c:231 access/common/attmap.c:243 #, c-format msgid "could not convert row type" msgstr "行型に変換できませんでした" -#: access/common/attmap.c:234 +#: access/common/attmap.c:232 #, c-format msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s." msgstr "%2$s型の属性\"%1$s\"が%3$s型の対応する属性と合致しません。" -#: access/common/attmap.c:246 +#: access/common/attmap.c:244 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "%2$s型の属性\"%1$s\"が%3$s型の中に存在しません。" -#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 +#: access/common/heaptuple.c:1133 access/common/heaptuple.c:1472 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "列数(%d)が上限(%d)を超えています" @@ -887,95 +886,95 @@ msgstr "列数(%d)が上限(%d)を超えています" msgid "number of index columns (%d) exceeds limit (%d)" msgstr "インデックス列数(%d)が上限(%d)を超えています" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:959 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:978 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "インデックス行が%zuバイトを必要としますが最大値は%zuです" -#: access/common/printtup.c:291 commands/explain.c:5375 tcop/fastpath.c:107 tcop/fastpath.c:454 tcop/postgres.c:1940 +#: access/common/printtup.c:292 commands/explain_dr.c:94 tcop/fastpath.c:106 tcop/fastpath.c:453 tcop/postgres.c:1951 #, c-format msgid "unsupported format code: %d" msgstr "非サポートの書式コード: %d" -#: access/common/reloptions.c:519 access/common/reloptions.c:530 +#: access/common/reloptions.c:530 access/common/reloptions.c:541 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "有効な値の範囲は\"on\"、\"off\"、\"auto\"です。" -#: access/common/reloptions.c:541 +#: access/common/reloptions.c:552 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "有効な値は\"local\"と\"cascaded\"です。" -#: access/common/reloptions.c:689 +#: access/common/reloptions.c:700 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "ユーザー定義リレーションのパラメータ型の制限を超えました" -#: access/common/reloptions.c:1231 +#: access/common/reloptions.c:1242 #, c-format msgid "RESET must not include values for parameters" msgstr "RESETにはパラメータの値を含めてはいけません" -#: access/common/reloptions.c:1263 +#: access/common/reloptions.c:1274 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "認識できないパラメータ namaspace \"%s\"" -#: access/common/reloptions.c:1300 commands/variable.c:1191 +#: access/common/reloptions.c:1311 commands/variable.c:1242 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "WITH OIDSと定義されたテーブルはサポートされません" -#: access/common/reloptions.c:1468 +#: access/common/reloptions.c:1479 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "認識できないラメータ \"%s\"" -#: access/common/reloptions.c:1580 +#: access/common/reloptions.c:1591 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "パラメータ\"%s\"が複数回指定されました" -#: access/common/reloptions.c:1596 +#: access/common/reloptions.c:1607 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "不正なブール型オプションの値 \"%s\": %s" -#: access/common/reloptions.c:1608 +#: access/common/reloptions.c:1619 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "不正な整数型オプションの値 \"%s\": %s" -#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 +#: access/common/reloptions.c:1625 access/common/reloptions.c:1645 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "値%sはオプション\"%s\"の範囲外です" -#: access/common/reloptions.c:1616 +#: access/common/reloptions.c:1627 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "有効な値の範囲は\"%d\"~\"%d\"です。" -#: access/common/reloptions.c:1628 +#: access/common/reloptions.c:1639 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "不正な浮動小数点型オプションの値 \"%s\": %s" -#: access/common/reloptions.c:1636 +#: access/common/reloptions.c:1647 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "有効な値の範囲は\"%f\"~\"%f\"です。" -#: access/common/reloptions.c:1658 +#: access/common/reloptions.c:1669 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "不正な列挙型オプションの値 \"%s\": %s" -#: access/common/reloptions.c:1989 +#: access/common/reloptions.c:2016 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "パーティション親テーブルに対してストレージパラメータは指定できません" -#: access/common/reloptions.c:1990 +#: access/common/reloptions.c:2017 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "代わりにリーフパーティションに対してストレージパラメータを指定してください。" @@ -1020,52 +1019,52 @@ msgstr "他のセッションの一時インデックスにはアクセスでき msgid "failed to re-find tuple within index \"%s\"" msgstr "インデックス\"%s\"内で行の再検索に失敗しました" -#: access/gin/ginscan.c:431 +#: access/gin/gininsert.c:1283 access/gin/ginutil.c:152 executor/execExpr.c:2244 utils/adt/array_userfuncs.c:1963 utils/adt/arrayfuncs.c:4028 utils/adt/arrayfuncs.c:6726 utils/adt/rowtypes.c:974 +#, c-format +msgid "could not identify a comparison function for type %s" +msgstr "%s型の比較関数が見つかりません" + +#: access/gin/ginscan.c:437 #, c-format msgid "old GIN indexes do not support whole-index scans nor searches for nulls" msgstr "古いGINインデックスはインデックス全体のスキャンやnullの検索をサポートしていません" -#: access/gin/ginscan.c:432 +#: access/gin/ginscan.c:438 #, c-format msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "これを修復するには REINDEX INDEX \"%s\" をおこなってください。" -#: access/gin/ginutil.c:147 executor/execExpr.c:2191 utils/adt/arrayfuncs.c:4009 utils/adt/arrayfuncs.c:6705 utils/adt/rowtypes.c:974 -#, c-format -msgid "could not identify a comparison function for type %s" -msgstr "%s型の比較関数が見つかりません" - -#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 +#: access/gin/ginvalidate.c:83 access/gist/gistvalidate.c:84 access/hash/hashvalidate.c:89 access/spgist/spgvalidate.c:94 #, c-format msgid "operator family \"%s\" of access method %s contains support function %s with different left and right input types" msgstr "アクセスメソッド %2$s の演算子族\"%1$s\"が左右辺の入力型が異なるサポート関数 %3$s を含んでいます" -#: access/gin/ginvalidate.c:258 +#: access/gin/ginvalidate.c:251 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d or %d" msgstr "アクセスメソッド\"%2$s\"の演算子クラス\"%1$s\"はサポート関数%3$dまたは%4$dを含んでいません" -#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 access/spgist/spgvalidate.c:387 +#: access/gin/ginvalidate.c:323 access/gist/gistvalidate.c:348 access/spgist/spgvalidate.c:378 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "サポート関数番号%dはアクセスメソッド%sに対して不正です" -#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:765 access/gist/gistvacuum.c:462 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "インデックス\"%s\"内に無効と判断されている内部タプルがあります" -#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:767 access/gist/gistvacuum.c:464 #, c-format msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1." msgstr "これは、PostgreSQL 9.1へアップグレードする前のクラッシュリカバリにおける不完全なページ分割が原因で発生します。" -#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 access/hash/hashutil.c:237 access/hash/hashutil.c:249 access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 access/nbtree/nbtpage.c:824 +#: access/gist/gist.c:768 access/gist/gistutil.c:801 access/gist/gistutil.c:812 access/gist/gistvacuum.c:465 access/hash/hashutil.c:226 access/hash/hashutil.c:237 access/hash/hashutil.c:249 access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "REINDEXを行ってください。" -#: access/gist/gist.c:1196 +#: access/gist/gist.c:1208 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "インデックス\"%s\"内の不完全な分割を修正します、ブロック%u" @@ -1080,33 +1079,33 @@ msgstr "インデックス\"%2$s\"の列%1$dに対するピックスプリット msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command." msgstr "インデックスは最適ではありません。最適化するためには開発者に連絡するか、この列をCREATE INDEXコマンドの2番目の列としてみてください。" -#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 access/nbtree/nbtpage.c:810 +#: access/gist/gistutil.c:798 access/hash/hashutil.c:223 access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "インデックス\"%s\"のブロック%uに予期していないゼロで埋められたページがあります" -#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:809 access/hash/hashutil.c:234 access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "インデックス\"%s\"のブロック%uに破損したページがあります" -#: access/gist/gistvalidate.c:202 +#: access/gist/gistvalidate.c:200 #, c-format msgid "operator family \"%s\" of access method %s contains unsupported ORDER BY specification for operator %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は演算子%3$sに対する非サポートのORDER BY指定を含んでいます" -#: access/gist/gistvalidate.c:213 +#: access/gist/gistvalidate.c:211 #, c-format msgid "operator family \"%s\" of access method %s contains incorrect ORDER BY opfamily specification for operator %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は演算子%3$sに対する正しくないORDER BY演算子族を含んでいます" -#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:331 utils/adt/varchar.c:1008 utils/adt/varchar.c:1063 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:332 utils/adt/varchar.c:1000 utils/adt/varchar.c:1056 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "文字列のハッシュ値計算で使用する照合順序を特定できませんでした" -#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:332 catalog/heap.c:672 catalog/heap.c:678 commands/createas.c:201 commands/createas.c:510 commands/indexcmds.c:2045 commands/tablecmds.c:18071 commands/view.c:81 regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 utils/adt/like_support.c:1024 utils/adt/varchar.c:738 utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 -#: utils/adt/varlena.c:1521 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:333 catalog/heap.c:679 catalog/heap.c:685 commands/createas.c:203 commands/createas.c:516 commands/indexcmds.c:2090 commands/tablecmds.c:19879 commands/view.c:80 regex/regc_pg_locale.c:245 utils/adt/formatting.c:1655 utils/adt/formatting.c:1719 utils/adt/formatting.c:1783 utils/adt/formatting.c:1847 utils/adt/like.c:163 utils/adt/like.c:194 utils/adt/like_support.c:1020 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1001 utils/adt/varchar.c:1057 utils/adt/varlena.c:1592 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "照合順序を明示するには COLLATE 句を使います。" @@ -1116,7 +1115,7 @@ msgstr "照合順序を明示するには COLLATE 句を使います。" msgid "index row size %zu exceeds hash maximum %zu" msgstr "インデックス行のサイズ%zuがハッシュでの最大値%zuを超えています" -#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1020 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1039 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "バッファページよりも大きな値をインデックスすることはできません。" @@ -1131,7 +1130,7 @@ msgstr "不正なオーバーフローブロック番号%u" msgid "out of overflow pages in hash index \"%s\"" msgstr "ハッシュインデックス\"%s\"の中のオーバーフローページが足りません" -#: access/hash/hashsearch.c:311 +#: access/hash/hashsearch.c:313 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "ハッシュインデックスはインデックス全体のスキャンをサポートしていません" @@ -1146,47 +1145,52 @@ msgstr "インデックス\"%s\"はハッシュインデックスではありま msgid "index \"%s\" has wrong hash version" msgstr "インデックス\"%s\"のハッシュバージョンが不正です" -#: access/hash/hashvalidate.c:198 +#: access/hash/hashvalidate.c:188 #, c-format msgid "operator family \"%s\" of access method %s lacks support function for operator %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は演算子%3$sに対するサポート関数を含んでいません" -#: access/hash/hashvalidate.c:256 access/nbtree/nbtvalidate.c:276 +#: access/hash/hashvalidate.c:246 access/nbtree/nbtvalidate.c:272 #, c-format msgid "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は異なる型間に対応する演算子を含んでいません" -#: access/heap/heapam.c:2194 +#: access/heap/heapam.c:2257 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "並列ワーカーではタプルの挿入はできません" -#: access/heap/heapam.c:2713 +#: access/heap/heapam.c:2776 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "並列処理中はタプルの削除はできません" -#: access/heap/heapam.c:2760 +#: access/heap/heapam.c:2823 #, c-format msgid "attempted to delete invisible tuple" msgstr "不可視のタプルを削除しようとしました" -#: access/heap/heapam.c:3208 access/heap/heapam.c:6081 +#: access/heap/heapam.c:3271 access/index/genam.c:829 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "並列処理中はタプルの更新はできません" -#: access/heap/heapam.c:3336 +#: access/heap/heapam.c:3448 #, c-format msgid "attempted to update invisible tuple" msgstr "不可視のタプルを更新しようとしました" -#: access/heap/heapam.c:4725 access/heap/heapam.c:4763 access/heap/heapam.c:5028 access/heap/heapam_handler.c:468 +#: access/heap/heapam.c:4959 access/heap/heapam.c:4997 access/heap/heapam.c:5262 access/heap/heapam_handler.c:470 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "リレーション\"%s\"の行ロックを取得できませんでした" -#: access/heap/heapam_handler.c:413 +#: access/heap/heapam.c:6376 commands/trigger.c:3350 executor/nodeModifyTable.c:2545 executor/nodeModifyTable.c:2635 +#, c-format +msgid "tuple to be updated was already modified by an operation triggered by the current command" +msgstr "更新対象のタプルはすでに現在のコマンドによって起動された操作によって変更されています" + +#: access/heap/heapam_handler.c:415 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update" msgstr "ロック対象のタプルは同時に行われた更新によってすでに他の子テーブルに移動されています" @@ -1201,8 +1205,8 @@ msgstr "行が大きすぎます: サイズは%zu、上限は%zu" msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "ファイル\"%1$s\"に書き込めませんでした、%3$dバイト中%2$dバイト書き込みました: %m" -#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 access/transam/timeline.c:329 access/transam/timeline.c:481 access/transam/xlog.c:3249 access/transam/xlog.c:3440 access/transam/xlog.c:4277 access/transam/xlog.c:9199 access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 backup/basebackup_server.c:242 commands/dbcommands.c:494 postmaster/launch_backend.c:328 postmaster/postmaster.c:4112 postmaster/walsummarizer.c:1067 -#: replication/logical/origin.c:603 replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 utils/time/snapmgr.c:1234 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 access/transam/timeline.c:329 access/transam/timeline.c:481 access/transam/xlog.c:3382 access/transam/xlog.c:3590 access/transam/xlog.c:4454 access/transam/xlog.c:9456 access/transam/xlogfuncs.c:693 backup/basebackup_server.c:149 backup/basebackup_server.c:242 commands/dbcommands.c:495 postmaster/launch_backend.c:354 postmaster/postmaster.c:4085 postmaster/walsummarizer.c:1219 +#: replication/logical/origin.c:603 replication/slot.c:2252 storage/file/copydir.c:173 storage/file/copydir.c:261 storage/smgr/md.c:252 utils/time/snapmgr.c:1241 #, c-format msgid "could not create file \"%s\": %m" msgstr "ファイル\"%s\"を作成できませんでした: %m" @@ -1212,156 +1216,171 @@ msgstr "ファイル\"%s\"を作成できませんでした: %m" msgid "could not truncate file \"%s\" to %u: %m" msgstr "ファイル\"%s\"を%uバイトに切り詰められませんでした: %m" -#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 access/transam/timeline.c:424 access/transam/timeline.c:498 access/transam/xlog.c:3299 access/transam/xlog.c:3496 access/transam/xlog.c:4289 commands/dbcommands.c:506 postmaster/launch_backend.c:339 postmaster/launch_backend.c:351 replication/logical/origin.c:615 replication/logical/origin.c:657 replication/logical/origin.c:676 replication/logical/snapbuild.c:1771 replication/slot.c:2094 -#: storage/file/buffile.c:545 storage/file/copydir.c:197 utils/init/miscinit.c:1601 utils/init/miscinit.c:1612 utils/init/miscinit.c:1620 utils/misc/guc.c:4441 utils/misc/guc.c:4472 utils/misc/guc.c:5625 utils/misc/guc.c:5643 utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 access/transam/timeline.c:424 access/transam/timeline.c:498 access/transam/xlog.c:3443 access/transam/xlog.c:3646 access/transam/xlog.c:4466 commands/dbcommands.c:507 postmaster/launch_backend.c:365 postmaster/launch_backend.c:377 replication/logical/origin.c:615 replication/logical/origin.c:657 replication/logical/origin.c:676 replication/logical/snapbuild.c:1617 replication/slot.c:2287 +#: storage/file/buffile.c:545 storage/file/copydir.c:213 utils/init/miscinit.c:1660 utils/init/miscinit.c:1671 utils/init/miscinit.c:1679 utils/misc/guc.c:4488 utils/misc/guc.c:4519 utils/misc/guc.c:5673 utils/misc/guc.c:5691 utils/time/snapmgr.c:1246 utils/time/snapmgr.c:1253 #, c-format msgid "could not write to file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: access/heap/vacuumlazy.c:473 +#: access/heap/vacuumlazy.c:814 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "\"%s.%s.%s\"に対して積極的VACUUMを実行しています" -#: access/heap/vacuumlazy.c:478 +#: access/heap/vacuumlazy.c:819 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "\"%s.%s.%s\"に対してVACUUMを実行しています" -#: access/heap/vacuumlazy.c:626 +#: access/heap/vacuumlazy.c:987 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "テーブル\"%s.%s.%s\"のVACUUM完了: インデックススキャン: %d\n" -#: access/heap/vacuumlazy.c:637 +#: access/heap/vacuumlazy.c:998 #, c-format msgid "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "テーブル\"%s.%s.%s\"の周回防止のための積極的自動VACUUM: インデックススキャン: %d\n" -#: access/heap/vacuumlazy.c:639 +#: access/heap/vacuumlazy.c:1000 #, c-format msgid "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "テーブル\"%s.%s.%s\"の周回防止のための自動VACUUM: インデックススキャン: %d\n" -#: access/heap/vacuumlazy.c:644 +#: access/heap/vacuumlazy.c:1005 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "テーブル\"%s.%s.%s\"の積極的自動VACUUM: インデックススキャン: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:1007 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "テーブル\"%s.%s.%s\"の自動VACUUM: インデックススキャン: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:1014 #, c-format -msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" -msgstr "ページ: %u削除、%u残存、%uスキャン (全体の%.2f%%)\n" +msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total), %u eagerly scanned\n" +msgstr "ページ: %u削除、%u残存、%uスキャン (全体の%.2f%%)、%u貪欲スキャン\n" -#: access/heap/vacuumlazy.c:660 +#: access/heap/vacuumlazy.c:1023 #, c-format -msgid "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" -msgstr "タプル: %lld削除、%lld残存、%lldが削除されているがまだ除去できない\n" +msgid "tuples: % removed, % remain, % are dead but not yet removable\n" +msgstr "タプル:%削除、%残存、%が削除されているがまだ除去できません\n" -#: access/heap/vacuumlazy.c:666 +#: access/heap/vacuumlazy.c:1029 #, c-format -msgid "tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n" -msgstr "未処理のタプル: クリーンナップロックの競合により、%2$uページ中の%1$lld行の削除済みタプルは除去されません\n" +msgid "tuples missed: % dead from %u pages not removed due to cleanup lock contention\n" +msgstr "未処理のタプル: クリーンナップロックの競合により、%2$uページ中の%1$行の削除済みタプルは除去されません\n" -#: access/heap/vacuumlazy.c:672 +#: access/heap/vacuumlazy.c:1035 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "削除可能限界: %u、これは処理完了時には%d XID分過去になります\n" -#: access/heap/vacuumlazy.c:679 +#: access/heap/vacuumlazy.c:1042 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "新しいrelfrozenxid: %u、これは前回の値よりも%d XID分進んでいます\n" -#: access/heap/vacuumlazy.c:687 +#: access/heap/vacuumlazy.c:1050 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "" "新しいrelminmxid: %u、これは前回の値よりも%d MXID分進んでいます\n" "\n" -#: access/heap/vacuumlazy.c:690 +#: access/heap/vacuumlazy.c:1053 +#, c-format +msgid "frozen: %u pages from table (%.2f%% of total) had % tuples frozen\n" +msgstr "凍結: テーブルから%uページ(全体の%.2f%%)で%タプルが凍結されました\n" + +#: access/heap/vacuumlazy.c:1061 #, c-format -msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" -msgstr "凍結: テーブルから%uページ(全体の%.2f%%)で%lldタプルが凍結されました\n" +msgid "visibility map: %u pages set all-visible, %u pages set all-frozen (%u were all-visible)\n" +msgstr "可視性マップ: %uページが全可視 (all-visible)、%uページが全凍結 (all-frozen) (前回は%uページが全可視でした)\n" -#: access/heap/vacuumlazy.c:698 +#: access/heap/vacuumlazy.c:1069 msgid "index scan not needed: " msgstr "インデックススキャンは不要です: " -#: access/heap/vacuumlazy.c:700 +#: access/heap/vacuumlazy.c:1071 msgid "index scan needed: " msgstr "インデックススキャンが必要です: " -#: access/heap/vacuumlazy.c:702 +#: access/heap/vacuumlazy.c:1073 #, c-format -msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" -msgstr "テーブル内の%uページ(全体の%.2f%%)にあった%lld行の削除行識別子が削除されました\n" +msgid "%u pages from table (%.2f%% of total) had % dead item identifiers removed\n" +msgstr "テーブル内の%uページ(全体の%.2f%%)にあった%行の削除行識別子が削除されました\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:1078 msgid "index scan bypassed: " msgstr "インデックススキャンはスキップされました: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:1080 msgid "index scan bypassed by failsafe: " msgstr "フェイルセーフによりインデックススキャンがスキップされました: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:1082 #, c-format -msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" -msgstr "テーブル内の%uページ(全体の%.2f%%)には%lld行の削除行識別子があります\n" +msgid "%u pages from table (%.2f%% of total) have % dead item identifiers\n" +msgstr "テーブル内の%uページ(全体の%.2f%%)には%行の削除行識別子があります\n" -#: access/heap/vacuumlazy.c:726 +#: access/heap/vacuumlazy.c:1097 #, c-format msgid "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u reusable\n" msgstr "インデックス\"%s\": ページ数: 合計%u、新規削除%u、削除済%u、再利用可%u\n" -#: access/heap/vacuumlazy.c:738 commands/analyze.c:789 +#: access/heap/vacuumlazy.c:1112 commands/analyze.c:817 +#, c-format +msgid "delay time: %.3f ms\n" +msgstr "遅延時間: %.3f ミリ秒\n" + +#: access/heap/vacuumlazy.c:1120 commands/analyze.c:825 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "I/O時間: 読み込み: %.3fミリ秒, 書き込み: %.3fミリ秒\n" -#: access/heap/vacuumlazy.c:748 commands/analyze.c:792 +#: access/heap/vacuumlazy.c:1130 commands/analyze.c:828 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "平均読み込み速度: %.3f MB/s, 平均書き込み速度: %.3f MB/s\n" -#: access/heap/vacuumlazy.c:751 commands/analyze.c:794 +#: access/heap/vacuumlazy.c:1133 commands/analyze.c:830 #, c-format -msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" -msgstr "バッファ使用: %lldヒット, %lld失敗, %lld ダーティ化\n" +msgid "buffer usage: % hits, % reads, % dirtied\n" +msgstr "バッファ使用: ヒット %, 読み込み %, ダーティ化 %\n" -#: access/heap/vacuumlazy.c:756 +#: access/heap/vacuumlazy.c:1138 commands/analyze.c:835 #, c-format -msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" -msgstr "WAL使用量: %lldのレコード, %lldの全ページイメージ, %lluバイト\n" +msgid "WAL usage: % records, % full page images, % bytes, % buffers full\n" +msgstr "WAL使用量: %のレコード, %の全ページイメージ, %バイト, %のバッファフル\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:798 +#: access/heap/vacuumlazy.c:1143 commands/analyze.c:840 #, c-format msgid "system usage: %s" msgstr "システム使用状況: %s" -#: access/heap/vacuumlazy.c:2172 +#: access/heap/vacuumlazy.c:1431 +#, c-format +msgid "disabling eager scanning after freezing %u eagerly scanned blocks of \"%s.%s.%s\"" +msgstr "\"%2$s.%3$s.%4$s\"を貪欲スキャンで%1$uブロックを凍結した後、貪欲スキャンを無効にします" + +#: access/heap/vacuumlazy.c:2820 #, c-format -msgid "table \"%s\": removed %lld dead item identifiers in %u pages" -msgstr "テーブル\"%1$s\": %3$uページ内の%2$lldの削除済み行識別子を除去" +msgid "table \"%s\": removed % dead item identifiers in %u pages" +msgstr "テーブル\"%1$s\": %3$uページ内の%2$の削除済み行識別子を除去" -#: access/heap/vacuumlazy.c:2326 +#: access/heap/vacuumlazy.c:2992 #, c-format msgid "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans" msgstr "%4$d回のインデックススキャンののち、フェイルセーフとしてテーブル\"%1$s.%2$s.%3$s\"の必須ではないメンテナンスをスキップします" -#: access/heap/vacuumlazy.c:2329 +#: access/heap/vacuumlazy.c:2995 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "このテーブルのrelfrozenxidまたはrelminmxidは古すぎます。" -#: access/heap/vacuumlazy.c:2330 +#: access/heap/vacuumlazy.c:2996 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" @@ -1370,67 +1389,67 @@ msgstr "" "設定パラメータ\"maintenance_work_mem\"または\"autovacuum_work_mem\"を増やすことを検討してください。\n" "VACUUMがトランザクションIDの割り当てに追従できるようにする他の方法を検討する必要があるかもしれません。" -#: access/heap/vacuumlazy.c:2592 +#: access/heap/vacuumlazy.c:3258 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "\"%s\":競合するロックが存在するため切り詰めを中断します" -#: access/heap/vacuumlazy.c:2662 +#: access/heap/vacuumlazy.c:3328 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "テーブル\"%s\": %uページから%uページに切り詰め" -#: access/heap/vacuumlazy.c:2724 +#: access/heap/vacuumlazy.c:3390 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "テーブル\"%s\": 競合するロック要求が存在するため、切り詰めを保留します" -#: access/heap/vacuumlazy.c:2843 +#: access/heap/vacuumlazy.c:3509 #, c-format msgid "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary tables in parallel" msgstr "\"%s\"のVACUUMに対するパラレルオプションを無効化します --- 一時テーブルは並列にVACUUMできません" -#: access/heap/vacuumlazy.c:3107 +#: access/heap/vacuumlazy.c:3776 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "リレーション\"%3$s.%4$s\"のブロック%1$u、オフセット%2$uのスキャン中" -#: access/heap/vacuumlazy.c:3110 +#: access/heap/vacuumlazy.c:3779 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "リレーション\\\"%2$s.%3$s\\\"のブロック%1$uのスキャン中" -#: access/heap/vacuumlazy.c:3114 +#: access/heap/vacuumlazy.c:3783 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "リレーション\"%s.%s\"のスキャン中" -#: access/heap/vacuumlazy.c:3122 +#: access/heap/vacuumlazy.c:3791 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "リレーション\"%3$s.%4$s\"のブロック%1$u、オフセット%2$uのVACUUM処理中" -#: access/heap/vacuumlazy.c:3125 +#: access/heap/vacuumlazy.c:3794 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "リレーション\\\"%2$s.%3$s\\\"のブロック%1$uのVACUUM処理中" -#: access/heap/vacuumlazy.c:3129 +#: access/heap/vacuumlazy.c:3798 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "リレーション\"%s.%s\"のVACUUM処理中" -#: access/heap/vacuumlazy.c:3134 commands/vacuumparallel.c:1113 +#: access/heap/vacuumlazy.c:3803 commands/vacuumparallel.c:1126 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "リレーション\\\"%2$s.%3$s\\\"のインデックス%1$sのVACUUM処理中" -#: access/heap/vacuumlazy.c:3139 commands/vacuumparallel.c:1119 +#: access/heap/vacuumlazy.c:3808 commands/vacuumparallel.c:1132 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "リレーション\\\"%2$s.%3$s\\\"のインデックス%1$sのクリーンアップ処理中" -#: access/heap/vacuumlazy.c:3145 +#: access/heap/vacuumlazy.c:3814 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "リレーション \"%s.%s\"を%uブロックに切り詰め中" @@ -1445,22 +1464,22 @@ msgstr "アクセスメソッド\"%s\"のタイプが%sではありません" msgid "index access method \"%s\" does not have a handler" msgstr "インデックスアクセスメソッド\"%s\"はハンドラを持っていません" -#: access/index/genam.c:487 +#: access/index/genam.c:498 #, c-format msgid "transaction aborted during system catalog scan" msgstr "システムカタログのスキャン中にトランザクションがアボートしました" -#: access/index/genam.c:655 access/index/indexam.c:82 +#: access/index/genam.c:663 access/index/indexam.c:82 #, c-format msgid "cannot access index \"%s\" while it is being reindexed" msgstr "再作成中であるためインデックス\"%s\"にアクセスできません" -#: access/index/indexam.c:203 catalog/objectaddress.c:1356 commands/indexcmds.c:2873 commands/tablecmds.c:281 commands/tablecmds.c:305 commands/tablecmds.c:17766 commands/tablecmds.c:19584 +#: access/index/indexam.c:203 catalog/objectaddress.c:1361 commands/indexcmds.c:2982 commands/tablecmds.c:284 commands/tablecmds.c:308 commands/tablecmds.c:19568 commands/tablecmds.c:21488 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\"はインデックスではありません" -#: access/index/indexam.c:1028 +#: access/index/indexam.c:1075 #, c-format msgid "operator class %s has no options" msgstr "演算子クラス%sにはオプションはありません" @@ -1480,7 +1499,7 @@ msgstr "キー %s はすでに存在します。" msgid "This may be because of a non-immutable index expression." msgstr "これは不変でないインデックス式が原因である可能性があります" -#: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 parser/parse_utilcmd.c:2298 +#: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 parser/parse_utilcmd.c:2483 #, c-format msgid "index \"%s\" is not a btree" msgstr "インデックス\"%s\"はbtreeではありません" @@ -1500,17 +1519,17 @@ msgstr "インデックス\"%s\"に削除処理中の内部ページがありま msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it." msgstr "これは9.3かそれ以前のバージョンで、アップグレード前にVACUUMが中断された際に起きた可能性があります。REINDEXしてください。" -#: access/nbtree/nbtutils.c:5112 +#: access/nbtree/nbtutils.c:4247 #, c-format msgid "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" msgstr "インデックス行サイズ%1$zuはインデックス\"%4$s\"でのbtreeバージョン %2$u の最大値%3$zuを超えています" -#: access/nbtree/nbtutils.c:5118 +#: access/nbtree/nbtutils.c:4252 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "インデックス行はリレーション\"%3$s\"のタプル(%1$u,%2$u)を参照しています。" -#: access/nbtree/nbtutils.c:5122 +#: access/nbtree/nbtutils.c:4256 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1519,57 +1538,57 @@ msgstr "" "バッファページの1/3を超える値はインデックス化できません。\n" "MD5ハッシュによる関数インデックスを検討するか、もしくは全文テキストインデックスを使用してください。" -#: access/nbtree/nbtvalidate.c:246 +#: access/nbtree/nbtvalidate.c:242 #, c-format msgid "operator family \"%s\" of access method %s is missing support function for types %s and %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は型%3$sと%4$sに対応するサポート関数を含んでいません" -#: access/sequence/sequence.c:75 access/table/table.c:145 optimizer/util/plancat.c:143 +#: access/sequence/sequence.c:75 access/table/table.c:145 optimizer/util/plancat.c:144 #, c-format msgid "cannot open relation \"%s\"" msgstr "リレーション\"%s\"はopenできません" -#: access/spgist/spgutils.c:245 +#: access/spgist/spgutils.c:251 #, c-format msgid "compress method must be defined when leaf type is different from input type" msgstr "リーフ型が入力型と異なる場合は圧縮メソッドの定義が必要です" -#: access/spgist/spgutils.c:1017 +#: access/spgist/spgutils.c:1036 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "SP-GiST内部タプルのサイズ%zuが最大値%zuを超えています" -#: access/spgist/spgvalidate.c:136 +#: access/spgist/spgvalidate.c:128 #, c-format msgid "SP-GiST leaf data type %s does not match declared type %s" msgstr "SP-GiSTのリーフデータ型%sは宣言された型%sと一致しません" -#: access/spgist/spgvalidate.c:302 +#: access/spgist/spgvalidate.c:294 #, c-format msgid "operator family \"%s\" of access method %s is missing support function %d for type %s" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"は%4$s型に対するサポート関数%3$dを含んでいません" -#: access/table/tableam.c:255 +#: access/table/tableam.c:256 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "tid (%u, %u) はリレーション\"%s\"に対して妥当ではありません" -#: access/table/tableamapi.c:109 +#: access/table/tableamapi.c:106 #, c-format msgid "\"%s\" cannot be empty." msgstr "\"%s\"は空にはできません。" -#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4858 +#: access/table/tableamapi.c:113 access/transam/xlogrecovery.c:4879 #, c-format msgid "\"%s\" is too long (maximum %d characters)." msgstr "\"%s\"が長過ぎます(最大%d文字)。" -#: access/table/tableamapi.c:139 +#: access/table/tableamapi.c:136 #, c-format msgid "table access method \"%s\" does not exist" msgstr "テーブルアクセスメソッド\"%s\"は存在しません" -#: access/table/tableamapi.c:144 +#: access/table/tableamapi.c:141 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "テーブルアクセスメソッド\"%s\"は存在しません。" @@ -1599,12 +1618,12 @@ msgstr "プライマリサーバーで設定パラメータ\"%s\"がonに設定 msgid "Make sure the configuration parameter \"%s\" is set." msgstr "設定パラメータ\"%s\"が設定されていることを確認してください。" -#: access/transam/multixact.c:1050 +#: access/transam/multixact.c:1097 #, c-format msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"" msgstr "データベース\"%s\"はMultiXactIds周回によるデータ損失を防ぐために、新規のMultiXactIdsを割り当てるコマンドを受け付けていません" -#: access/transam/multixact.c:1052 access/transam/multixact.c:1059 access/transam/multixact.c:1083 access/transam/multixact.c:1092 access/transam/varsup.c:158 access/transam/varsup.c:165 +#: access/transam/multixact.c:1099 access/transam/multixact.c:1106 access/transam/multixact.c:1130 access/transam/multixact.c:1139 access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" @@ -1613,61 +1632,61 @@ msgstr "" "そのデータベース全体の VACUUM を実行してください。\n" "古い準備済みトランザクションのコミットまたはロールバック、もしくは古いレプリケーションスロットの削除も必要かもしれません。" -#: access/transam/multixact.c:1057 +#: access/transam/multixact.c:1104 #, c-format msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u" msgstr "OID %u のデータベースは周回によるデータ損失を防ぐために、新規のMultiXactIdsを割り当てるコマンドを受け付けていません" -#: access/transam/multixact.c:1078 access/transam/multixact.c:2433 +#: access/transam/multixact.c:1125 access/transam/multixact.c:2482 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used" msgstr[0] "データベース\"%s\"はあと%u個のMultiXactIdが使われる前にVACUUMする必要があります" -#: access/transam/multixact.c:1087 access/transam/multixact.c:2442 +#: access/transam/multixact.c:1134 access/transam/multixact.c:2491 #, c-format msgid "database with OID %u must be vacuumed before %u more MultiXactId is used" msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used" msgstr[0] "OID %u のデータベースはあと%u個のMultiXactIdが使われる前にVACUUMする必要があります" -#: access/transam/multixact.c:1148 +#: access/transam/multixact.c:1195 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "マルチトランザクションの\"メンバ\"が制限を超えました" -#: access/transam/multixact.c:1149 +#: access/transam/multixact.c:1196 #, c-format msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member." msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members." msgstr[0] "このコマンドで%u個のメンバを持つマルチトランザクションが生成されますが、残りのスペースは %u 個のメンバ分しかありません。" -#: access/transam/multixact.c:1154 +#: access/transam/multixact.c:1201 #, c-format msgid "Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." msgstr "\"vacuum_multixact_freeze_min_age\"と\"vacuum_multixact_freeze_table_age\"をより小さな値に設定してOID %u のデータベースでデータベース全体にVACUUMを実行してください。" -#: access/transam/multixact.c:1185 +#: access/transam/multixact.c:1232 #, c-format msgid "database with OID %u must be vacuumed before %d more multixact member is used" msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used" msgstr[0] "OID %u のデータベースは更に%d個のマルチトランザクションメンバが使用される前にVACUUMを実行する必要があります" -#: access/transam/multixact.c:1190 +#: access/transam/multixact.c:1237 #, c-format msgid "Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." msgstr "\"vacuum_multixact_freeze_min_age\"'と\"vacuum_multixact_freeze_table_age\"をより小さな値に設定した上で、そのデータベースでVACUUMを実行してください。" -#: access/transam/multixact.c:1330 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "MultiXactId %uはもう存在しません: 周回しているようです" -#: access/transam/multixact.c:1336 +#: access/transam/multixact.c:1383 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "MultiXactId %uを作成できませんでした: 周回している様子" -#: access/transam/multixact.c:2438 access/transam/multixact.c:2447 +#: access/transam/multixact.c:2487 access/transam/multixact.c:2496 #, c-format msgid "" "To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" @@ -1676,61 +1695,61 @@ msgstr "" "MultiXactIdの割り当て失敗を防ぐために、このデータベースでデータベース全体に対するVACUUMを実行してください。\n" "古い準備済みトランザクションのコミットまたはロールバック、もしくは古いレプリケーションスロットの削除も必要かもしれません。" -#: access/transam/multixact.c:2726 +#: access/transam/multixact.c:2775 #, c-format msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" msgstr "最古のチェックポイント済みのマルチトランザクション%uがディスク上に存在しないため、マルチトランザクションメンバーの周回防止機能を無効にしました" -#: access/transam/multixact.c:2748 +#: access/transam/multixact.c:2797 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "マルチトランザクションメンバーの周回防止機能が有効になりました" -#: access/transam/multixact.c:3131 +#: access/transam/multixact.c:3188 #, c-format msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "最古のマルチトランザクション%uが見つかりません、アクセス可能な最古のものは%u、切り詰めをスキップします" -#: access/transam/multixact.c:3149 +#: access/transam/multixact.c:3206 #, c-format msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation" msgstr "マルチトランザクション%uがディスク上に存在しないため、そこまでの切り詰めができません、切り詰めをスキップします" -#: access/transam/multixact.c:3468 +#: access/transam/multixact.c:3525 #, c-format msgid "invalid MultiXactId: %u" msgstr "不正なMultiXactId: %u" -#: access/transam/parallel.c:731 access/transam/parallel.c:850 +#: access/transam/parallel.c:752 access/transam/parallel.c:871 #, c-format msgid "parallel worker failed to initialize" msgstr "パラレルワーカーの初期化に失敗しました" -#: access/transam/parallel.c:732 access/transam/parallel.c:851 +#: access/transam/parallel.c:753 access/transam/parallel.c:872 #, c-format msgid "More details may be available in the server log." msgstr "詳細な情報がサーバーログにあるかもしれません。" -#: access/transam/parallel.c:912 +#: access/transam/parallel.c:933 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "並列処理中にpostmasterが終了しました" -#: access/transam/parallel.c:1099 +#: access/transam/parallel.c:1120 #, c-format msgid "lost connection to parallel worker" msgstr "パラレルワーカーへの接続を失いました" -#: access/transam/parallel.c:1155 access/transam/parallel.c:1157 +#: access/transam/parallel.c:1176 access/transam/parallel.c:1178 msgid "parallel worker" msgstr "パラレルワーカー" -#: access/transam/parallel.c:1327 replication/logical/applyparallelworker.c:890 +#: access/transam/parallel.c:1348 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "動的共有メモリセグメントをマップできませんでした" -#: access/transam/parallel.c:1332 replication/logical/applyparallelworker.c:896 +#: access/transam/parallel.c:1353 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "動的共有メモリセグメントのマジックナンバーが不正です" @@ -1790,62 +1809,62 @@ msgstr "ID %d の既存の独自リソースマネージャが同じ名前です msgid "registered custom resource manager \"%s\" with ID %d" msgstr "独自リソースマネージャ\"%s\"をID %dで登録しました" -#: access/transam/slru.c:346 +#: access/transam/slru.c:360 #, c-format -msgid "\"%s\" must be a multiple of %d" -msgstr "\"%s\"は%dの倍数でなければなりません" +msgid "\"%s\" must be a multiple of %d." +msgstr "\"%s\"は%dの倍数でなければなりません。" -#: access/transam/slru.c:815 +#: access/transam/slru.c:832 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "ファイル\"%s\"が存在しません。ゼロとして読み込みます" -#: access/transam/slru.c:1044 access/transam/slru.c:1050 access/transam/slru.c:1058 access/transam/slru.c:1063 access/transam/slru.c:1070 access/transam/slru.c:1075 access/transam/slru.c:1082 access/transam/slru.c:1089 +#: access/transam/slru.c:1061 access/transam/slru.c:1067 access/transam/slru.c:1075 access/transam/slru.c:1080 access/transam/slru.c:1087 access/transam/slru.c:1092 access/transam/slru.c:1099 access/transam/slru.c:1106 #, c-format msgid "could not access status of transaction %u" msgstr "トランザクション%uのステータスにアクセスできませんでした" -#: access/transam/slru.c:1045 +#: access/transam/slru.c:1062 #, c-format msgid "Could not open file \"%s\": %m." msgstr "ファイル\"%s\"をオープンできませんでした: %m。" -#: access/transam/slru.c:1051 +#: access/transam/slru.c:1068 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "ファイル\"%s\"のオフセット%dにシークできませんでした: %m。" -#: access/transam/slru.c:1059 +#: access/transam/slru.c:1076 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "ファイル\"%s\"のオフセット%dを読み取れませんでした: %m。" -#: access/transam/slru.c:1064 +#: access/transam/slru.c:1081 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "ファイル\"%s\"のオフセット%dを読み取れませんでした: 読み込んだバイト数が足りません。" -#: access/transam/slru.c:1071 +#: access/transam/slru.c:1088 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "ファイル\"%s\"のオフセット%dに書き出せませんでした: %m。" -#: access/transam/slru.c:1076 +#: access/transam/slru.c:1093 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "ファイル\"%s\"のオフセット%dに書き出せませんでした: 書き込んだバイト数が足りません。" -#: access/transam/slru.c:1083 +#: access/transam/slru.c:1100 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "ファイル\"%s\"をfsyncできませんでした: %m。" -#: access/transam/slru.c:1090 +#: access/transam/slru.c:1107 #, c-format msgid "Could not close file \"%s\": %m." msgstr "ファイル\"%s\"をクローズできませんでした: %m。" -#: access/transam/slru.c:1416 +#: access/transam/slru.c:1433 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "ディレクトリ\"%s\"を切り詰めできませんでした: 明らかに周回しています" @@ -1910,12 +1929,12 @@ msgstr "\"max_prepared_transactions\"を0以外の値に設定してください msgid "transaction identifier \"%s\" is already in use" msgstr "トランザクション識別子\"%s\"はすでに存在します" -#: access/transam/twophase.c:404 access/transam/twophase.c:2541 +#: access/transam/twophase.c:404 access/transam/twophase.c:2530 #, c-format msgid "maximum number of prepared transactions reached" msgstr "準備済みのトランザクションの最大数に達しました" -#: access/transam/twophase.c:405 access/transam/twophase.c:2542 +#: access/transam/twophase.c:405 access/transam/twophase.c:2531 #, c-format msgid "Increase \"max_prepared_transactions\" (currently %d)." msgstr "\"max_prepared_transactions\"を大きくしてください(現在は%d)。" @@ -1950,145 +1969,145 @@ msgstr "終了させるためにはこのトランザクションを準備した msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "識別子\"%s\"の準備されたトランザクションはありません" -#: access/transam/twophase.c:1190 +#: access/transam/twophase.c:1174 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "2相状態ファイルの最大長が制限を超えました" -#: access/transam/twophase.c:1345 +#: access/transam/twophase.c:1329 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" msgstr[0] "ファイル\"%s\"のサイズが不正: %lld バイト" -#: access/transam/twophase.c:1354 +#: access/transam/twophase.c:1338 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "ファイル\"%s\"のCRCオフセットのアライメントが不正です" -#: access/transam/twophase.c:1372 +#: access/transam/twophase.c:1356 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイトのうち%2$dバイトを読み込みました" -#: access/transam/twophase.c:1387 +#: access/transam/twophase.c:1371 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "ファイル\"%s\"に格納されているマジックナンバーが不正です" -#: access/transam/twophase.c:1393 +#: access/transam/twophase.c:1377 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "ファイル\"%s\"内に格納されているサイズが不正です" -#: access/transam/twophase.c:1405 +#: access/transam/twophase.c:1389 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "算出されたCRCチェックサムがファイル\"%s\"に格納されている値と一致しません" -#: access/transam/twophase.c:1435 access/transam/xlogrecovery.c:565 postmaster/walsummarizer.c:821 replication/logical/logical.c:210 replication/walsender.c:836 +#: access/transam/twophase.c:1419 access/transam/xlogrecovery.c:571 postmaster/walsummarizer.c:943 replication/logical/logical.c:211 replication/walsender.c:812 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "WALリーダの割り当てに中に失敗しました。" -#: access/transam/twophase.c:1445 +#: access/transam/twophase.c:1429 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "WALの%X/%Xから2相状態を読み取れませんでした: %s" -#: access/transam/twophase.c:1450 +#: access/transam/twophase.c:1434 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "WALの%X/%Xから2相状態を読み取れませんでした" -#: access/transam/twophase.c:1458 +#: access/transam/twophase.c:1442 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "WALの%X/%Xにあるはずの2相状態のデータがありません" -#: access/transam/twophase.c:1754 +#: access/transam/twophase.c:1744 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "ファイル\"%s\"を再作成できませんでした: %m" -#: access/transam/twophase.c:1881 +#: access/transam/twophase.c:1871 #, c-format msgid "%u two-phase state file was written for a long-running prepared transaction" msgid_plural "%u two-phase state files were written for long-running prepared transactions" msgstr[0] "長時間実行中の準備済みトランザクションのために%u個の2相状態ファイルが書き込まれました" -#: access/transam/twophase.c:2117 +#: access/transam/twophase.c:2106 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "共有メモリから準備済みトランザクション%uを復元します" -#: access/transam/twophase.c:2210 +#: access/transam/twophase.c:2199 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "不要になったトランザクション%uの2相状態ファイルを削除します" -#: access/transam/twophase.c:2217 +#: access/transam/twophase.c:2206 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "不要になったトランザクション%uの2相状態をメモリから削除します" -#: access/transam/twophase.c:2230 +#: access/transam/twophase.c:2219 #, c-format msgid "removing future two-phase state file for transaction %u" -msgstr "未来のトランザクション%uの2相状態ファイルを削除します" +msgstr "トランザクション%uの未来の2相状態ファイルを削除します" -#: access/transam/twophase.c:2237 +#: access/transam/twophase.c:2226 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "未来のトランザクション%uの2相状態をメモリから削除します" -#: access/transam/twophase.c:2262 +#: access/transam/twophase.c:2251 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "トランザクション%uの2相状態ファイルが破損しています" -#: access/transam/twophase.c:2267 +#: access/transam/twophase.c:2256 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "メモリ上にあるトランザクション%uの2相状態が破損しています" -#: access/transam/twophase.c:2524 +#: access/transam/twophase.c:2513 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "トランザクション%uの2相状態ファイルを復元できませんでした" -#: access/transam/twophase.c:2526 +#: access/transam/twophase.c:2515 #, c-format msgid "Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk." msgstr "2相状態ファイルがWALレコード%X/%Xで見つかりましたが、このトランザクションはすでにディスクから復元済みです。" -#: access/transam/twophase.c:2534 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 +#: access/transam/twophase.c:2523 storage/file/fd.c:514 utils/fmgr/dfmgr.c:199 #, c-format msgid "could not access file \"%s\": %m" msgstr "ファイル\"%s\"にアクセスできませんでした: %m" #: access/transam/varsup.c:156 #, c-format -msgid "database is not accepting commands that assign new XIDs to avoid wraparound data loss in database \"%s\"" -msgstr "データベース\"%s\"はXID周回によるデータ損失を防ぐために、新規のXIDを割り当てるコマンドを受け付けていません" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"" +msgstr "データベース\"%s\"はXID周回によるデータ損失を防ぐために、新規のトランザクションIDを割り当てるコマンドを受け付けていません" #: access/transam/varsup.c:163 #, c-format -msgid "database is not accepting commands that assign new XIDs to avoid wraparound data loss in database with OID %u" -msgstr "OID %u を持つデータベースはXID周回によるデータ損失を防ぐために、新規のXIDを割り当てるマンドを受け付けていません" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u" +msgstr "OID %u を持つデータベースは周回によるデータ損失を防ぐために、新規のトランザクションIDを割り当てるマンドを受け付けていません" #: access/transam/varsup.c:175 access/transam/varsup.c:490 #, c-format msgid "database \"%s\" must be vacuumed within %u transactions" msgstr "データベース\"%s\"は%uトランザクション以内にVACUUMする必要があります" -#: access/transam/varsup.c:178 access/transam/varsup.c:185 access/transam/varsup.c:493 access/transam/varsup.c:500 +#: access/transam/varsup.c:178 #, c-format msgid "" -"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"XIDの割り当て失敗を防ぐために、このデータベースでデータベース全体の VACUUM を実行してください。\n" +"トランザクションIDの割り当て失敗を防ぐために、このデータベースでデータベース全体の VACUUM を実行してください。\n" "古い準備済みトランザクションのコミットまたはロールバック、もしくは古いレプリケーションスロットの削除も必要かもしれません。" #: access/transam/varsup.c:182 access/transam/varsup.c:497 @@ -2096,560 +2115,515 @@ msgstr "" msgid "database with OID %u must be vacuumed within %u transactions" msgstr "OID %uのデータベースは%uトランザクション以内にVACUUMを実行する必要があります" -#: access/transam/xact.c:649 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 access/transam/varsup.c:500 +#, c-format +msgid "" +"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "" +"XIDの割り当て失敗を防ぐために、このデータベースでデータベース全体の VACUUM を実行してください。\n" +"古い準備済みトランザクションのコミットまたはロールバック、もしくは古いレプリケーションスロットの削除も必要かもしれません。" + +#: access/transam/xact.c:652 #, c-format -msgid "cannot assign XIDs during a parallel operation" -msgstr "並列処理中にXIDの割り当てはできません" +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "並列処理中にトランザクションIDの割り当てはできません" -#: access/transam/xact.c:840 +#: access/transam/xact.c:843 #, c-format msgid "cannot modify data in a parallel worker" msgstr "並列ワーカーではデータの更新はできません" -#: access/transam/xact.c:1115 +#: access/transam/xact.c:1118 #, c-format msgid "cannot start commands during a parallel operation" msgstr "並列処理中にはコマンドは起動できません" -#: access/transam/xact.c:1123 +#: access/transam/xact.c:1126 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "1トランザクション内では 2^32-2 個より多くのコマンドを実行できません" -#: access/transam/xact.c:1664 +#: access/transam/xact.c:1695 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "コミットされたサブトランザクション数の最大値(%d)が制限を越えました" -#: access/transam/xact.c:2561 +#: access/transam/xact.c:2616 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "一時オブジェクトに対する操作を行ったトランザクションをPREPAREすることはできません" -#: access/transam/xact.c:2571 +#: access/transam/xact.c:2626 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "エクスポートされたスナップショットを持つトランザクションをPREPAREすることはできません" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3593 +#: access/transam/xact.c:3657 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%sはトランザクションブロックの内側では実行できません" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3603 +#: access/transam/xact.c:3667 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%sはサブトランザクションブロックの内側では実行できません" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3613 -#, c-format -msgid "%s cannot be executed within a pipeline" -msgstr "%s はパイプライン内での実行はできません" - -#. translator: %s represents an SQL statement name -#: access/transam/xact.c:3623 +#: access/transam/xact.c:3677 #, c-format msgid "%s cannot be executed from a function" msgstr "%s は関数内での実行はできません" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3694 access/transam/xact.c:4019 access/transam/xact.c:4098 access/transam/xact.c:4221 access/transam/xact.c:4372 access/transam/xact.c:4441 access/transam/xact.c:4552 +#: access/transam/xact.c:3748 access/transam/xact.c:4070 access/transam/xact.c:4149 access/transam/xact.c:4272 access/transam/xact.c:4423 access/transam/xact.c:4492 access/transam/xact.c:4603 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%sはトランザクションブロック内でのみ使用できます" -#: access/transam/xact.c:3905 +#: access/transam/xact.c:3956 #, c-format msgid "there is already a transaction in progress" msgstr "すでにトランザクションが実行中です" -#: access/transam/xact.c:4024 access/transam/xact.c:4103 access/transam/xact.c:4226 +#: access/transam/xact.c:4075 access/transam/xact.c:4154 access/transam/xact.c:4277 #, c-format msgid "there is no transaction in progress" msgstr "実行中のトランザクションがありません" -#: access/transam/xact.c:4114 +#: access/transam/xact.c:4165 #, c-format msgid "cannot commit during a parallel operation" msgstr "並列処理中にはコミットはできません" -#: access/transam/xact.c:4237 +#: access/transam/xact.c:4288 #, c-format msgid "cannot abort during a parallel operation" msgstr "パラレル処理中にロールバックはできません" -#: access/transam/xact.c:4336 +#: access/transam/xact.c:4387 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "パラレル処理中にセーブポイントは定義できません" -#: access/transam/xact.c:4423 +#: access/transam/xact.c:4474 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "並列処理中はセーブポイントの解放はできません" -#: access/transam/xact.c:4433 access/transam/xact.c:4484 access/transam/xact.c:4544 access/transam/xact.c:4593 +#: access/transam/xact.c:4484 access/transam/xact.c:4535 access/transam/xact.c:4595 access/transam/xact.c:4644 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "セーブポイント\"%s\"は存在しません" -#: access/transam/xact.c:4490 access/transam/xact.c:4599 +#: access/transam/xact.c:4541 access/transam/xact.c:4650 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "セーブポイント\"%s\"は現在のセーブポイントレベルには存在しません" -#: access/transam/xact.c:4532 +#: access/transam/xact.c:4583 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "パラレル処理中にセーブポイントのロールバックはできません" -#: access/transam/xact.c:5376 +#: access/transam/xact.c:5438 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "1トランザクション内には 2^32-1 個より多くのサブトランザクションを作成できません" -#: access/transam/xlog.c:1536 +#: access/transam/xlog.c:1552 #, c-format msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" msgstr "生成されたWALより先の位置までのフラッシュ要求; 要求 %X/%X, 現在位置 %X/%X" -#: access/transam/xlog.c:1763 +#: access/transam/xlog.c:1779 #, c-format msgid "cannot read past end of generated WAL: requested %X/%X, current position %X/%X" msgstr "生成されたWALより先の位置までの読み込み要求; 要求 %X/%X, 現在位置 %X/%X" -#: access/transam/xlog.c:2204 access/transam/xlog.c:4495 +#: access/transam/xlog.c:2342 access/transam/xlog.c:4690 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WALセグメントサイズは1MBから1GBまでの間の2の累乗でなければなりません。" -#: access/transam/xlog.c:2222 +#: access/transam/xlog.c:2360 #, c-format msgid "\"%s\" must be set to -1 during binary upgrade mode." msgstr "バイナリアップグレードモード中は\"%s\"は-1に設定されている必要があります。" -#: access/transam/xlog.c:2471 +#: access/transam/xlog.c:2597 #, c-format msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" msgstr "ログファイル \"%s\" のオフセット%uに長さ%zuの書き込みができませんでした: %m" -#: access/transam/xlog.c:3733 access/transam/xlogutils.c:831 replication/walsender.c:3045 +#: access/transam/xlog.c:3883 access/transam/xlogutils.c:820 replication/walsender.c:3050 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "要求された WAL セグメント %s はすでに削除されています" -#: access/transam/xlog.c:4055 +#: access/transam/xlog.c:4205 #, c-format msgid "could not rename file \"%s\": %m" msgstr "ファイル\"%s\"の名前を変更できませんでした: %m" -#: access/transam/xlog.c:4098 access/transam/xlog.c:4109 access/transam/xlog.c:4130 +#: access/transam/xlog.c:4248 access/transam/xlog.c:4259 access/transam/xlog.c:4280 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "WALディレクトリ\"%s\"は存在しません" -#: access/transam/xlog.c:4115 access/transam/xlog.c:4136 +#: access/transam/xlog.c:4265 access/transam/xlog.c:4286 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "なかったWALディレクトリ\"%s\"を作成しています" -#: access/transam/xlog.c:4119 access/transam/xlog.c:4139 commands/dbcommands.c:3242 +#: access/transam/xlog.c:4269 access/transam/xlog.c:4289 commands/dbcommands.c:3276 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "なかったディレクトリ\"%s\"の作成に失敗しました: %m" -#: access/transam/xlog.c:4206 +#: access/transam/xlog.c:4356 #, c-format msgid "could not generate secret authorization token" msgstr "秘密の認証トークンを生成できませんでした" -#: access/transam/xlog.c:4357 access/transam/xlog.c:4367 access/transam/xlog.c:4393 access/transam/xlog.c:4401 access/transam/xlog.c:4409 access/transam/xlog.c:4415 access/transam/xlog.c:4423 access/transam/xlog.c:4431 access/transam/xlog.c:4439 access/transam/xlog.c:4447 access/transam/xlog.c:4455 access/transam/xlog.c:4463 access/transam/xlog.c:4473 access/transam/xlog.c:4481 utils/init/miscinit.c:1758 +#: access/transam/xlog.c:4534 access/transam/xlog.c:4544 access/transam/xlog.c:4570 access/transam/xlog.c:4580 access/transam/xlog.c:4590 access/transam/xlog.c:4596 access/transam/xlog.c:4606 access/transam/xlog.c:4616 access/transam/xlog.c:4626 access/transam/xlog.c:4636 access/transam/xlog.c:4646 access/transam/xlog.c:4656 access/transam/xlog.c:4668 access/transam/xlog.c:4676 utils/init/miscinit.c:1817 #, c-format msgid "database files are incompatible with server" msgstr "データベースファイルがサーバーと互換性がありません" -#: access/transam/xlog.c:4358 +#: access/transam/xlog.c:4535 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)." msgstr "データベースクラスタはPG_CONTROL_VERSION %d (0x%08x)で初期化されましたが、サーバーはPG_CONTROL_VERSION %d (0x%08x)でコンパイルされています。" -#: access/transam/xlog.c:4362 +#: access/transam/xlog.c:4539 #, c-format msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb." msgstr "これはバイトオーダの不整合の可能性があります。initdbを実行する必要がありそうです。" -#: access/transam/xlog.c:4368 +#: access/transam/xlog.c:4545 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "データベースクラスタはPG_CONTROL_VERSION %d で初期化されましたが、サーバーは PG_CONTROL_VERSION %d でコンパイルされています。" -#: access/transam/xlog.c:4371 access/transam/xlog.c:4397 access/transam/xlog.c:4405 access/transam/xlog.c:4411 +#: access/transam/xlog.c:4548 access/transam/xlog.c:4576 access/transam/xlog.c:4586 access/transam/xlog.c:4592 #, c-format msgid "It looks like you need to initdb." msgstr "initdbが必要のようです。" -#: access/transam/xlog.c:4383 +#: access/transam/xlog.c:4560 #, c-format msgid "incorrect checksum in control file" msgstr "制御ファイル内のチェックサムが不正です" -#: access/transam/xlog.c:4394 +#. translator: %s is a variable name and %d is its value +#: access/transam/xlog.c:4572 access/transam/xlog.c:4582 access/transam/xlog.c:4598 access/transam/xlog.c:4608 access/transam/xlog.c:4618 access/transam/xlog.c:4628 access/transam/xlog.c:4638 access/transam/xlog.c:4648 access/transam/xlog.c:4658 #, c-format -msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." -msgstr "データベースクラスタは CATALOG_VERSION_NO %d で初期化されましたが、サーバーは CATALOG_VERSION_NO %d でコンパイルされています。" +msgid "The database cluster was initialized with %s %d, but the server was compiled with %s %d." +msgstr "データベースクラスタは %s %d で初期化されましたが、サーバーは %s %d でコンパイルされています。" -#: access/transam/xlog.c:4402 -#, c-format -msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." -msgstr "データベースクラスタは MAXALIGN %d で初期化されましたが、サーバーは MAXALIGN %d でコンパイルされています。" - -#: access/transam/xlog.c:4410 +#: access/transam/xlog.c:4591 #, c-format msgid "The database cluster appears to use a different floating-point number format than the server executable." msgstr "データベースクラスタはサーバー実行ファイルと異なる浮動小数点書式を使用しているようです。" -#: access/transam/xlog.c:4416 -#, c-format -msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." -msgstr "データベースクラスタは BLCKSZ %d で初期化されましたが、サーバーは BLCKSZ %d でコンパイルされています。" - -#: access/transam/xlog.c:4419 access/transam/xlog.c:4427 access/transam/xlog.c:4435 access/transam/xlog.c:4443 access/transam/xlog.c:4451 access/transam/xlog.c:4459 access/transam/xlog.c:4467 access/transam/xlog.c:4476 access/transam/xlog.c:4484 +#: access/transam/xlog.c:4602 access/transam/xlog.c:4612 access/transam/xlog.c:4622 access/transam/xlog.c:4632 access/transam/xlog.c:4642 access/transam/xlog.c:4652 access/transam/xlog.c:4662 access/transam/xlog.c:4671 access/transam/xlog.c:4679 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "再コンパイルもしくは initdb が必要そうです。" -#: access/transam/xlog.c:4424 -#, c-format -msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." -msgstr "データベースクラスタは RELSEG_SIZE %d で初期化されましたが、サーバーは RELSEG_SIZE %d でコンパイルされています。" - -#: access/transam/xlog.c:4432 -#, c-format -msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." -msgstr "データベースクラスタは XLOG_BLCKSZ %d で初期化されましたが、サーバーは XLOG_BLCKSZ %d でコンパイルされています。" - -#: access/transam/xlog.c:4440 -#, c-format -msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." -msgstr "データベースクラスタは NAMEDATALEN %d で初期化されましたが、サーバーは NAMEDATALEN %d でコンパイルされています。" - -#: access/transam/xlog.c:4448 -#, c-format -msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." -msgstr "データベースクラスタは INDEX_MAX_KEYS %d で初期化されましたが、サーバーは INDEX_MAX_KEYS %d でコンパイルされています。" - -#: access/transam/xlog.c:4456 -#, c-format -msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." -msgstr "データベースクラスタは TOAST_MAX_CHUNK_SIZE %d で初期化されましたが、サーバーは TOAST_MAX_CHUNK_SIZE %d でコンパイルされています。" - -#: access/transam/xlog.c:4464 -#, c-format -msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." -msgstr "データベースクラスタは LOBLKSIZE %d で初期化されましたが、サーバーは LOBLKSIZE %d でコンパイルされています。" - -#: access/transam/xlog.c:4474 +#: access/transam/xlog.c:4669 #, c-format msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL." msgstr "データベースクラスタは USE_FLOAT8_BYVAL なしで初期化されましたが、サーバー側は USE_FLOAT8_BYVAL 付きでコンパイルされています。" -#: access/transam/xlog.c:4482 +#: access/transam/xlog.c:4677 #, c-format msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL." msgstr "データベースクラスタは USE_FLOAT8_BYVAL 付きで初期化されましたが、サーバー側は USE_FLOAT8_BYVAL なしでコンパイルされています。" -#: access/transam/xlog.c:4491 +#: access/transam/xlog.c:4686 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "制御ファイル中の不正なWALセグメントサイズ (%dバイト)" -#: access/transam/xlog.c:4504 +#. translator: both %s are GUC names +#: access/transam/xlog.c:4700 access/transam/xlog.c:4706 #, c-format -msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" -msgstr "\"min_wal_size\"は最低でも\"wal_segment_size\"の2倍である必要があります" +msgid "\"%s\" must be at least twice \"%s\"" +msgstr "\"%s\"は\"%s\"の2倍以上でなければなりません" -#: access/transam/xlog.c:4508 -#, c-format -msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" -msgstr "\"max_wal_size\"は最低でも\"wal_segment_size\"の2倍である必要があります" - -#: access/transam/xlog.c:4656 catalog/namespace.c:4681 commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 replication/slot.c:2429 utils/error/elog.c:2214 +#: access/transam/xlog.c:4868 catalog/namespace.c:4696 commands/tablespace.c:1210 commands/user.c:2542 commands/variable.c:72 replication/slot.c:2655 tcop/postgres.c:3631 utils/error/elog.c:2274 #, c-format msgid "List syntax is invalid." msgstr "リスト文法が無効です" -#: access/transam/xlog.c:4702 commands/user.c:2545 commands/variable.c:173 utils/error/elog.c:2240 +#: access/transam/xlog.c:4914 commands/user.c:2558 commands/variable.c:173 tcop/postgres.c:3647 utils/error/elog.c:2300 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "不明なキーワードです: \"%s\"" -#: access/transam/xlog.c:5122 +#: access/transam/xlog.c:5341 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "ブートストラップの先行書き込みログファイルに書き込めませんでした: %m" -#: access/transam/xlog.c:5130 +#: access/transam/xlog.c:5349 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "ブートストラップの先行書き込みログファイルをfsyncできませんでした: %m" -#: access/transam/xlog.c:5136 +#: access/transam/xlog.c:5355 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "ブートストラップの先行書き込みログファイルをクローズできませんでした: %m" -#: access/transam/xlog.c:5354 +#: access/transam/xlog.c:5580 #, c-format msgid "WAL was generated with \"wal_level=minimal\", cannot continue recovering" msgstr "\"wal_level=minimal\"でWALが生成されました、リカバリは続行不可です" -#: access/transam/xlog.c:5355 +#: access/transam/xlog.c:5581 #, c-format msgid "This happens if you temporarily set \"wal_level=minimal\" on the server." msgstr "これはこのサーバーで一時的に\"wal_level=minimal\"にした場合に起こります。" -#: access/transam/xlog.c:5356 +#: access/transam/xlog.c:5582 #, c-format msgid "Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." msgstr "\"wal_level\"を\"minimal\"より上位に設定したあとに取得したバックアップを使用してください。" -#: access/transam/xlog.c:5421 +#: access/transam/xlog.c:5647 #, c-format msgid "control file contains invalid checkpoint location" msgstr "制御ファイル内のチェックポイント位置が不正です" -#: access/transam/xlog.c:5432 +#: access/transam/xlog.c:5658 #, c-format msgid "database system was shut down at %s" msgstr "データベースシステムは %s にシャットダウンしました" -#: access/transam/xlog.c:5438 +#: access/transam/xlog.c:5664 #, c-format msgid "database system was shut down in recovery at %s" msgstr "データベースシステムはリカバリ中 %s にシャットダウンしました" -#: access/transam/xlog.c:5444 +#: access/transam/xlog.c:5670 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "データベースシステムはシャットダウン中に中断されました; %s まで動作していたことは確認できます" -#: access/transam/xlog.c:5450 +#: access/transam/xlog.c:5676 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "データベースシステムはリカバリ中 %s に中断されました" -#: access/transam/xlog.c:5452 +#: access/transam/xlog.c:5678 #, c-format msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "これはおそらくデータ破損があり、リカバリのために直前のバックアップを使用しなければならないことを意味します。" -#: access/transam/xlog.c:5458 +#: access/transam/xlog.c:5684 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "データベースシステムはリカバリ中ログ時刻 %s に中断されました" -#: access/transam/xlog.c:5460 +#: access/transam/xlog.c:5686 #, c-format msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target." msgstr "これが1回以上起きた場合はデータが破損している可能性があるため、より以前のリカバリ目標を選ぶ必要があるかもしれません。" -#: access/transam/xlog.c:5466 +#: access/transam/xlog.c:5692 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "データベースシステムは中断されました: %s まで動作していたことは確認できます" -#: access/transam/xlog.c:5473 +#: access/transam/xlog.c:5699 #, c-format msgid "control file contains invalid database cluster state" msgstr "制御ファイル内のデータベース・クラスタ状態が不正です" -#: access/transam/xlog.c:5860 +#: access/transam/xlog.c:6087 #, c-format msgid "WAL ends before end of online backup" msgstr "オンラインバックアップの終了より前にWALが終了しました" -#: access/transam/xlog.c:5861 +#: access/transam/xlog.c:6088 #, c-format msgid "All WAL generated while online backup was taken must be available at recovery." msgstr "オンラインバックアップ中に生成されたすべてのWALがリカバリで利用可能である必要があります。" -#: access/transam/xlog.c:5865 +#: access/transam/xlog.c:6092 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WALが一貫性があるリカバリポイントより前で終了しました" -#: access/transam/xlog.c:5911 +#: access/transam/xlog.c:6138 #, c-format msgid "selected new timeline ID: %u" msgstr "新しいタイムラインIDを選択: %u" -#: access/transam/xlog.c:5944 +#: access/transam/xlog.c:6171 #, c-format msgid "archive recovery complete" msgstr "アーカイブリカバリが完了しました" -#: access/transam/xlog.c:6552 +#: access/transam/xlog.c:6803 #, c-format msgid "shutting down" msgstr "シャットダウンしています" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6591 +#: access/transam/xlog.c:6842 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "リスタートポイント開始:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6603 +#: access/transam/xlog.c:6854 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "チェックポイント開始:%s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6668 +#: access/transam/xlog.c:6919 #, c-format -msgid "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" -msgstr "リスタートポイント完了: %d個のバッファを出力 (%.1f%%); %d個のWALファイルを追加、%d個を削除、%d個を再利用; 書き出し=%ld.%03d秒, 同期=%ld.%03d秒, 全体=%ld.%03d秒; 同期したファイル=%d, 最長=%ld.%03d秒, 平均=%ld.%03d秒; 距離=%d kB, 予測=%d kB; lsn=%X/%X, 再生lsn=%X/%X" +msgid "restartpoint complete: wrote %d buffers (%.1f%%), wrote %d SLRU buffers; %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" +msgstr "リスタートポイント完了: %d個のバッファを出力 (%.1f%%), %d個のSLRUバッファを出力; %d個のWALファイルを追加、%d個を削除、%d個を再利用; 書き出し=%ld.%03d秒, 同期=%ld.%03d秒, 全体=%ld.%03d秒; 同期したファイル=%d, 最長=%ld.%03d秒, 平均=%ld.%03d秒; 距離=%d kB, 予測=%d kB; lsn=%X/%X, 再生lsn=%X/%X" -#: access/transam/xlog.c:6691 +#: access/transam/xlog.c:6943 #, c-format -msgid "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" -msgstr "チェックポイント完了: %d個のバッファを出力 (%.1f%%); %d個のWALファイルを追加、%d個を削除、%d個を再利用; 書き出し=%ld.%03d秒, 同期=%ld.%03d秒, 全体=%ld.%03d秒; 同期したファイル=%d, 最長=%ld.%03d秒, 平均=%ld.%03d秒; 距離=%d kB, 予測=%d kB; lsn=%X/%X, 再生lsn=%X/%X" +msgid "checkpoint complete: wrote %d buffers (%.1f%%), wrote %d SLRU buffers; %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" +msgstr "チェックポイント完了: %d個のバッファを出力 (%.1f%%), %d個のSLRUバッファを出力; %d個のWALファイルを追加、%d個を削除、%d個を再利用; 書き出し=%ld.%03d秒, 同期=%ld.%03d秒, 全体=%ld.%03d秒; 同期したファイル=%d, 最長=%ld.%03d秒, 平均=%ld.%03d秒; 距離=%d kB, 予測=%d kB; lsn=%X/%X, 再生lsn=%X/%X" -#: access/transam/xlog.c:7165 +#: access/transam/xlog.c:7429 #, c-format msgid "concurrent write-ahead log activity while database system is shutting down" msgstr "データベースのシャットダウンに並行して、先行書き込みログが発生しました" -#: access/transam/xlog.c:7749 +#: access/transam/xlog.c:8016 #, c-format msgid "recovery restart point at %X/%X" msgstr "リカバリ再開ポイントは%X/%Xです" -#: access/transam/xlog.c:7751 +#: access/transam/xlog.c:8018 #, c-format msgid "Last completed transaction was at log time %s." msgstr "最後に完了したトランザクションはログ時刻 %s のものです" -#: access/transam/xlog.c:8013 +#: access/transam/xlog.c:8280 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "復帰ポイント\"%s\"が%X/%Xに作成されました" -#: access/transam/xlog.c:8220 +#: access/transam/xlog.c:8487 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "オンラインバックアップはキャンセルされ、リカバリを継続できません" -#: access/transam/xlog.c:8277 +#: access/transam/xlog.c:8545 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "シャットダウンチェックポイントレコードにおいて想定外のタイムラインID %u(%uのはず)がありました" -#: access/transam/xlog.c:8335 +#: access/transam/xlog.c:8603 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "オンラインチェックポイントレコードにおいて想定外のタイムラインID %u(%uのはず)がありました" -#: access/transam/xlog.c:8364 +#: access/transam/xlog.c:8632 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "リカバリ終了チェックポイントレコードにおいて想定外のタイムラインID %u(%uのはず)がありました" -#: access/transam/xlog.c:8635 +#: access/transam/xlog.c:8902 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "ライトスルーファイル\"%s\"をfsyncできませんでした: %m" -#: access/transam/xlog.c:8640 +#: access/transam/xlog.c:8907 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "ファイル\"%s\"をfdatasyncできませんでした: %m" -#: access/transam/xlog.c:8727 access/transam/xlog.c:9063 +#: access/transam/xlog.c:8984 access/transam/xlog.c:9320 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "オンラインバックアップを行うにはWALレベルが不十分です" -#: access/transam/xlog.c:8728 access/transam/xlogfuncs.c:248 +#: access/transam/xlog.c:8985 access/transam/xlog.c:9321 access/transam/xlogfuncs.c:249 #, c-format msgid "\"wal_level\" must be set to \"replica\" or \"logical\" at server start." msgstr "サーバーの開始時に\"wal_level\"を\"replica\"または \"logical\"にセットする必要があります。" -#: access/transam/xlog.c:8733 +#: access/transam/xlog.c:8990 #, c-format msgid "backup label too long (max %d bytes)" msgstr "バックアップラベルが長すぎます (最大%dバイト)" -#: access/transam/xlog.c:8854 +#: access/transam/xlog.c:9111 #, c-format msgid "WAL generated with \"full_page_writes=off\" was replayed since last restartpoint" msgstr "\"full_page_writes=off\"で生成されたWALが最終リスタートポイント以降に再生されました" -#: access/transam/xlog.c:8856 access/transam/xlog.c:9152 +#: access/transam/xlog.c:9113 access/transam/xlog.c:9409 #, c-format msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, and then try an online backup again." msgstr "つまりこのスタンバイで取得されたバックアップは破損しており、使用すべきではありません。プライマリで\"full_page_writes\"を有効にしCHECKPOINTを実行したのち、再度オンラインバックアップを試行してください。" -#: access/transam/xlog.c:8936 backup/basebackup.c:1417 utils/adt/misc.c:354 +#: access/transam/xlog.c:9193 backup/basebackup.c:1419 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "シンボリックリンク\"%s\"を読めませんでした: %m" -#: access/transam/xlog.c:8943 backup/basebackup.c:1422 utils/adt/misc.c:359 +#: access/transam/xlog.c:9200 backup/basebackup.c:1424 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "シンボリックリンク\"%s\"の参照先が長すぎます" -#: access/transam/xlog.c:9064 -#, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "サーバーの開始時にwal_levelを\"replica\"または \"logical\"にセットする必要があります。" - -#: access/transam/xlog.c:9102 backup/basebackup.c:1281 +#: access/transam/xlog.c:9359 backup/basebackup.c:1283 #, c-format msgid "the standby was promoted during online backup" msgstr "オンラインバックアップ中にスタンバイが昇格しました" -#: access/transam/xlog.c:9103 backup/basebackup.c:1282 +#: access/transam/xlog.c:9360 backup/basebackup.c:1284 #, c-format msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup." msgstr "つまり取得中のバックアップは破損しているため使用してはいけません。再度オンラインバックアップを取得してください。" -#: access/transam/xlog.c:9150 +#: access/transam/xlog.c:9407 #, c-format msgid "WAL generated with \"full_page_writes=off\" was replayed during online backup" msgstr "\"full_page_writes=off\"で生成されたWALがオンラインバックアップ中に再生されました" -#: access/transam/xlog.c:9266 +#: access/transam/xlog.c:9523 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "ベースバックアップ完了、必要な WAL セグメントがアーカイブされるのを待っています" -#: access/transam/xlog.c:9280 +#: access/transam/xlog.c:9537 #, c-format msgid "still waiting for all required WAL segments to be archived (%d seconds elapsed)" msgstr "まだ必要なすべての WAL セグメントがアーカイブされるのを待っています(%d 秒経過)" -#: access/transam/xlog.c:9282 +#: access/transam/xlog.c:9539 #, c-format msgid "Check that your \"archive_command\" is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." msgstr "\"archive_command\"が正しく実行されていることを確認してください。バックアップ処理は安全に取り消すことができますが、全てのWALセグメントがそろわなければこのバックアップは利用できません。" -#: access/transam/xlog.c:9289 +#: access/transam/xlog.c:9546 #, c-format msgid "all required WAL segments have been archived" msgstr "必要なすべての WAL セグメントがアーカイブされました" -#: access/transam/xlog.c:9293 +#: access/transam/xlog.c:9550 #, c-format msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup" msgstr "WAL アーカイブが有効になっていません。バックアップを完了させるには、すべての必要なWALセグメントが他の方法でコピーされたことを確認してください。" -#: access/transam/xlog.c:9332 +#: access/transam/xlog.c:9589 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "バックエンドがpg_backup_stopの呼び出し前に終了したため、バックアップは異常終了しました" @@ -2692,268 +2666,268 @@ msgstr "アーカイブステータスファイル\"%s\"を作成できません msgid "could not write archive status file \"%s\": %m" msgstr "アーカイブステータスファイル\"%s\"に書き込めませんでした: %m" -#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 +#: access/transam/xlogfuncs.c:70 backup/basebackup.c:999 #, c-format msgid "a backup is already in progress in this session" msgstr "このセッションではすでにバックアップが進行中です" -#: access/transam/xlogfuncs.c:140 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "backup is not in progress" msgstr "バックアップが進行中ではありません" -#: access/transam/xlogfuncs.c:141 +#: access/transam/xlogfuncs.c:142 #, c-format msgid "Did you call pg_backup_start()?" msgstr "pg_backup_start()を呼び出しましたか?" -#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 access/transam/xlogfuncs.c:323 +#: access/transam/xlogfuncs.c:185 access/transam/xlogfuncs.c:243 access/transam/xlogfuncs.c:282 access/transam/xlogfuncs.c:303 access/transam/xlogfuncs.c:324 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "リカバリ中はWAL制御関数は実行できません。" -#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 access/transam/xlogfuncs.c:447 +#: access/transam/xlogfuncs.c:210 access/transam/xlogfuncs.c:390 access/transam/xlogfuncs.c:448 #, c-format msgid "%s cannot be executed during recovery." msgstr "リカバリ中は %s を実行できません。" -#: access/transam/xlogfuncs.c:215 +#: access/transam/xlogfuncs.c:216 #, c-format msgid "pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" msgstr "pg_log_standby_snapshot()は\"wal_level >= replica\"のときだけ使用できます" -#: access/transam/xlogfuncs.c:247 +#: access/transam/xlogfuncs.c:248 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "リストアポイントを作るにはWALレベルが不足しています" -#: access/transam/xlogfuncs.c:255 +#: access/transam/xlogfuncs.c:256 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "リストアポイントとしては値が長すぎます(最大%d文字)" -#: access/transam/xlogfuncs.c:486 +#: access/transam/xlogfuncs.c:487 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "WALファイル名\"%s\"は不正です" -#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 access/transam/xlogfuncs.c:679 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 access/transam/xlogfuncs.c:680 #, c-format msgid "recovery is not in progress" msgstr "リカバリが進行中ではありません" -#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 access/transam/xlogfuncs.c:680 +#: access/transam/xlogfuncs.c:524 access/transam/xlogfuncs.c:554 access/transam/xlogfuncs.c:578 access/transam/xlogfuncs.c:601 access/transam/xlogfuncs.c:681 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "リカバリ制御関数リカバリ中にのみを実行可能です。" -#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "standby promotion is ongoing" msgstr "スタンバイの昇格を実行中です" -#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 +#: access/transam/xlogfuncs.c:530 access/transam/xlogfuncs.c:560 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%sは昇格を開始した後には実行できません。" -#: access/transam/xlogfuncs.c:685 +#: access/transam/xlogfuncs.c:686 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "\"wait_seconds\"は負の値もしくはゼロにはできません" -#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 +#: access/transam/xlogfuncs.c:708 storage/ipc/signalfuncs.c:293 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "postmasterにシグナルを送信できませんでした: %m" -#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#: access/transam/xlogfuncs.c:740 libpq/be-secure.c:241 libpq/be-secure.c:350 #, c-format msgid "terminating connection due to unexpected postmaster exit" msgstr "予期しないpostmasterの終了のため、コネクションを終了します" -#: access/transam/xlogfuncs.c:740 +#: access/transam/xlogfuncs.c:741 #, c-format msgid "while waiting on promotion" msgstr "昇格の待機中" -#: access/transam/xlogfuncs.c:744 +#: access/transam/xlogfuncs.c:745 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" msgstr[0] "サーバーは%d秒以内に昇格しませんでした" -#: access/transam/xlogprefetcher.c:1088 +#: access/transam/xlogprefetcher.c:1086 #, c-format -msgid "\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()." -msgstr "\"recovery_prefetch\"はposix_fadvise()を持たないプラットフォームではサポートされません。" +msgid "\"recovery_prefetch\" is not supported on platforms that lack support for issuing read-ahead advice." +msgstr "\"recovery_prefetch\"は先読み指示の発行をサポートしないプラットフォームではサポートされません。" -#: access/transam/xlogreader.c:619 +#: access/transam/xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "%X/%Xのレコードオフセットが不正です:最低でも%uを期待していましたが、実際は%uでした" -#: access/transam/xlogreader.c:628 +#: access/transam/xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "%X/%Xでは継続レコードが必要です" -#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 +#: access/transam/xlogreader.c:670 access/transam/xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "%X/%Xのレコード長が不正です:長さは最低でも%uを期待していましたが、実際は%uでした" -#: access/transam/xlogreader.c:758 +#: access/transam/xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "%X/%Xでcontrecordフラグがありません" -#: access/transam/xlogreader.c:771 +#: access/transam/xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "%3$X/%4$Xの継続レコードの長さ%1$u(正しくは%2$lld)は不正です" -#: access/transam/xlogreader.c:1142 +#: access/transam/xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "%2$X/%3$XのリソースマネージャID %1$uは不正です" -#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 +#: access/transam/xlogreader.c:1156 access/transam/xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "%3$X/%4$Xのレコードの後方リンク%1$X/%2$Xが不正です" -#: access/transam/xlogreader.c:1209 +#: access/transam/xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "%X/%Xのレコード内のリソースマネージャデータのチェックサムが不正です" -#: access/transam/xlogreader.c:1243 +#: access/transam/xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%2$s、LSN %3$X/%4$X、オフセット%5$uで不正なマジックナンバー%1$04X" -#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 +#: access/transam/xlogreader.c:1259 access/transam/xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント %2$s、LSN %3$X/%4$X、オフセット%5$uで不正な情報ビット列%1$04X" -#: access/transam/xlogreader.c:1274 +#: access/transam/xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WALファイルは異なるデータベースシステム由来のものです: WALファイルのデータベースシステム識別子は %lluで、pg_control におけるデータベースシステム識別子は %lluです" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WALファイルは異なるデータベースシステム由来のものです: WALファイルのデータベースシステム識別子は %で、pg_control におけるデータベースシステム識別子は %です" -#: access/transam/xlogreader.c:1282 +#: access/transam/xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのセグメントサイズが正しくありません" -#: access/transam/xlogreader.c:1288 +#: access/transam/xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのXLOG_BLCKSZが正しくありません" -#: access/transam/xlogreader.c:1320 +#: access/transam/xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%3$s、LSN %4$X/%5$X、オフセット%6$uで想定外のページアドレス%1$X/%2$X" -#: access/transam/xlogreader.c:1346 +#: access/transam/xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%3$s、LSN %4$X/%5$X、オフセット%6$uで異常な順序のタイムラインID %1$u(%2$uの後)" -#: access/transam/xlogreader.c:1749 +#: access/transam/xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %uが%X/%Xで不正です" -#: access/transam/xlogreader.c:1773 +#: access/transam/xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATAが設定されていますが、%X/%Xにデータがありません" -#: access/transam/xlogreader.c:1780 +#: access/transam/xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATAが設定されていませんが、%2$X/%3$Xのデータ長は%1$uです" -#: access/transam/xlogreader.c:1816 +#: access/transam/xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEが設定されていますが、%4$X/%5$Xでホールオフセット%1$u、長さ%2$u、ブロックイメージ長%3$uです" -#: access/transam/xlogreader.c:1832 +#: access/transam/xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEが設定されていませんが、%3$X/%4$Xにおけるホールオフセット%1$uの長さが%2$uです" -#: access/transam/xlogreader.c:1846 +#: access/transam/xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSEDが設定されていますが、%2$X/%3$Xにおいてブロックイメージ長が%1$uです" -#: access/transam/xlogreader.c:1861 +#: access/transam/xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEもBKPIMAGE_COMPRESSEDも設定されていませんが、%2$X/%3$Xにおいてブロックイメージ長が%1$uです" -#: access/transam/xlogreader.c:1877 +#: access/transam/xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_RELが設定されていますが、%X/%Xにおいて以前のリレーションがありません" -#: access/transam/xlogreader.c:1889 +#: access/transam/xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "%2$X/%3$Xにおけるblock_id %1$uが不正です" -#: access/transam/xlogreader.c:1956 +#: access/transam/xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "%X/%Xのレコードのサイズが不正です" -#: access/transam/xlogreader.c:1982 +#: access/transam/xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "WALレコード中ID %dのバックアップブロックを特定できませんでした" -#: access/transam/xlogreader.c:2066 +#: access/transam/xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "%X/%Xで不正なブロック%dが指定されているためイメージが復元できませんでした" -#: access/transam/xlogreader.c:2073 +#: access/transam/xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "%X/%Xでブロック%dのイメージが不正な状態であるため復元できませんでした" -#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 +#: access/transam/xlogreader.c:2110 access/transam/xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "%1$X/%2$Xで、ブロック%4$dがこのビルドでサポートされない圧縮方式%3$sで圧縮されているため復元できませんでした" -#: access/transam/xlogreader.c:2126 +#: access/transam/xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "%X/%Xでブロック%dのイメージが不明な方式で圧縮されているため復元できませんでした" -#: access/transam/xlogreader.c:2134 +#: access/transam/xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "%X/%Xのブロック%dが伸張できませんでした" -#: access/transam/xlogrecovery.c:617 +#: access/transam/xlogrecovery.c:623 #, c-format msgid "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u" msgstr "タイムラインID %5$u上でREDO LSN %1$X/%2$X、チェックポイントLSN %3$X/%4$Xからのバックアップ・リカバリを開始しました" -#: access/transam/xlogrecovery.c:649 +#: access/transam/xlogrecovery.c:655 #, c-format msgid "could not find redo location %X/%X referenced by checkpoint record at %X/%X" msgstr "%3$X/%4$Xのチェックポイントレコードが参照しているredo位置%1$X/%2$Xを見つけられませんでした" -#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 +#: access/transam/xlogrecovery.c:657 access/transam/xlogrecovery.c:668 #, c-format msgid "" "If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" @@ -2965,463 +2939,464 @@ msgstr "" " バックアップからの復旧でなければ、\"%s/backup_label\"の削除を試みてください。.\n" "バックアップからの復旧で\"%s/backup_label\"を削除すると、クラスタが破壊されることに注意してください。" -#: access/transam/xlogrecovery.c:660 +#: access/transam/xlogrecovery.c:666 #, c-format msgid "could not locate required checkpoint record at %X/%X" msgstr "必須のチェックポイントが%X/%Xで見つかりませんでした" -#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 +#: access/transam/xlogrecovery.c:696 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "シンボリックリンク\"%s\"を作成できませんでした: %m" -#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 +#: access/transam/xlogrecovery.c:729 access/transam/xlogrecovery.c:735 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "ファイル\"%2$s\"が存在しないためファイル\"%1$s\"を無視します" -#: access/transam/xlogrecovery.c:725 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "ファイル\"%s\"は\"%s\"にリネームされました。" -#: access/transam/xlogrecovery.c:731 +#: access/transam/xlogrecovery.c:737 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m。" -#: access/transam/xlogrecovery.c:770 +#: access/transam/xlogrecovery.c:776 #, c-format msgid "restarting backup recovery with redo LSN %X/%X" msgstr "REDO LSN %X/%Xのバックアプリカバリを再開しました" -#: access/transam/xlogrecovery.c:795 +#: access/transam/xlogrecovery.c:801 #, c-format msgid "could not locate a valid checkpoint record at %X/%X" msgstr "%X/%Xには有効なチェックポイントレコードがありませんでした" -#: access/transam/xlogrecovery.c:806 +#: access/transam/xlogrecovery.c:812 #, c-format msgid "entering standby mode" msgstr "スタンバイモードに入ります" -#: access/transam/xlogrecovery.c:809 +#: access/transam/xlogrecovery.c:815 #, c-format msgid "starting point-in-time recovery to XID %u" msgstr "XID%uまでのポイントインタイムリカバリを開始します" -#: access/transam/xlogrecovery.c:813 +#: access/transam/xlogrecovery.c:819 #, c-format msgid "starting point-in-time recovery to %s" msgstr "%sまでのポイントインタイムリカバリを開始します" -#: access/transam/xlogrecovery.c:817 +#: access/transam/xlogrecovery.c:823 #, c-format msgid "starting point-in-time recovery to \"%s\"" msgstr "\"%s\"までのポイントインタイムリカバリを開始します" -#: access/transam/xlogrecovery.c:821 +#: access/transam/xlogrecovery.c:827 #, c-format msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" msgstr "WAL位置(LSN) \"%X/%X\"までのポイントインタイムリカバリを開始します" -#: access/transam/xlogrecovery.c:825 +#: access/transam/xlogrecovery.c:831 #, c-format msgid "starting point-in-time recovery to earliest consistent point" msgstr "最も古い一貫性確保点までのポイントインタイムリカバリを開始します" -#: access/transam/xlogrecovery.c:828 +#: access/transam/xlogrecovery.c:834 #, c-format msgid "starting archive recovery" msgstr "アーカイブリカバリを開始しています" -#: access/transam/xlogrecovery.c:849 +#: access/transam/xlogrecovery.c:855 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "要求されたタイムライン%uはこのサーバーの履歴からの子孫ではありません" -#: access/transam/xlogrecovery.c:851 +#. translator: %s is a backup_label file or a pg_control file +#: access/transam/xlogrecovery.c:858 #, c-format -msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." -msgstr "タイムライン%3$uの最終チェックポイントは%1$X/%2$Xですが、要求されたタイムラインの履歴の中ではサーバーはそのタイムラインから%4$X/%5$Xで分岐しています。" +msgid "Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." +msgstr "ファイル\"%1$s\"での最終チェックポイントはタイムライン%4$uの%2$X/%3$Xですが、要求されたタイムラインの履歴上、サーバーはそのタイムラインから%5$X/%6$Xで分岐しています。" -#: access/transam/xlogrecovery.c:865 +#: access/transam/xlogrecovery.c:873 #, c-format msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u" msgstr "要求されたタイムライン%1$uはタイムライン%4$uの最小リカバリポイント%2$X/%3$Xを含みません" -#: access/transam/xlogrecovery.c:893 +#: access/transam/xlogrecovery.c:901 #, c-format msgid "invalid next transaction ID" msgstr "次のトランザクションIDが不正です" -#: access/transam/xlogrecovery.c:898 +#: access/transam/xlogrecovery.c:906 #, c-format msgid "invalid redo in checkpoint record" msgstr "チェックポイントレコード内の不正なREDO" -#: access/transam/xlogrecovery.c:909 +#: access/transam/xlogrecovery.c:917 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "シャットダウン・チェックポイントにおける不正なREDOレコード" -#: access/transam/xlogrecovery.c:938 +#: access/transam/xlogrecovery.c:946 #, c-format msgid "database system was not properly shut down; automatic recovery in progress" msgstr "データベースシステムは正しくシャットダウンされていません; 自動リカバリを実行中" -#: access/transam/xlogrecovery.c:942 +#: access/transam/xlogrecovery.c:950 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "タイムライン%uから、タイムライン%uを目標としてクラッシュリカバリを開始します" -#: access/transam/xlogrecovery.c:985 +#: access/transam/xlogrecovery.c:993 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_labelに制御ファイルと整合しないデータが含まれます" -#: access/transam/xlogrecovery.c:986 +#: access/transam/xlogrecovery.c:994 #, c-format msgid "This means that the backup is corrupted and you will have to use another backup for recovery." msgstr "これはバックアップが破損しており、リカバリには他のバックアップを使用しなければならないことを意味します。" -#: access/transam/xlogrecovery.c:1040 +#: access/transam/xlogrecovery.c:1048 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "リカバリコマンドファイル \"%s\"の使用はサポートされません" -#: access/transam/xlogrecovery.c:1105 +#: access/transam/xlogrecovery.c:1113 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "スタンバイモードはシングルユーザーサーバーではサポートされません" -#: access/transam/xlogrecovery.c:1122 +#: access/transam/xlogrecovery.c:1130 #, c-format msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" msgstr "\"primary_conninfo\"と\"restore_command\"のどちらも指定されていません" -#: access/transam/xlogrecovery.c:1123 +#: access/transam/xlogrecovery.c:1131 #, c-format msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there." msgstr "データベースサーバーはpg_walサブディレクトリに置かれたファイルを定期的に確認します。" -#: access/transam/xlogrecovery.c:1131 +#: access/transam/xlogrecovery.c:1139 #, c-format msgid "must specify \"restore_command\" when standby mode is not enabled" msgstr "スタンバイモードを有効にしない場合は、\"restore_command\"の指定が必要です" -#: access/transam/xlogrecovery.c:1169 +#: access/transam/xlogrecovery.c:1177 #, c-format msgid "recovery target timeline %u does not exist" msgstr "リカバリ目標タイムライン%uが存在しません" -#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 +#: access/transam/xlogrecovery.c:1260 access/transam/xlogrecovery.c:1267 access/transam/xlogrecovery.c:1326 access/transam/xlogrecovery.c:1414 access/transam/xlogrecovery.c:1423 access/transam/xlogrecovery.c:1443 #, c-format msgid "invalid data in file \"%s\"" msgstr "ファイル\"%s\"内の不正なデータ" -#: access/transam/xlogrecovery.c:1319 +#: access/transam/xlogrecovery.c:1327 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "読み取られたタイムラインIDは%uでしたが、%uであるはずです。" -#: access/transam/xlogrecovery.c:1330 +#: access/transam/xlogrecovery.c:1338 #, c-format msgid "this is an incremental backup, not a data directory" msgstr "これはデータディレクトリではなく、差分バックアップです" -#: access/transam/xlogrecovery.c:1331 +#: access/transam/xlogrecovery.c:1339 #, c-format msgid "Use pg_combinebackup to reconstruct a valid data directory." msgstr "有効なデータディレクトリを再構築するにはpg_combinebackupを使ってください。" -#: access/transam/xlogrecovery.c:1717 +#: access/transam/xlogrecovery.c:1725 #, c-format msgid "unexpected record type found at redo point %X/%X" msgstr "REDOポイント%X/%Xで想定外のレコードタイプが見つかりました" -#: access/transam/xlogrecovery.c:1740 +#: access/transam/xlogrecovery.c:1748 #, c-format msgid "redo starts at %X/%X" msgstr "REDOを%X/%Xから開始します" -#: access/transam/xlogrecovery.c:1753 +#: access/transam/xlogrecovery.c:1761 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "REDO進行中、経過時間 %ld.%02d秒, 現在のLSN: %X/%X" -#: access/transam/xlogrecovery.c:1843 +#: access/transam/xlogrecovery.c:1851 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "要求されたリカバリ停止ポイントは、一貫性があるリカバリポイントより前にあります" -#: access/transam/xlogrecovery.c:1875 +#: access/transam/xlogrecovery.c:1883 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "REDOが%X/%Xで終了しました、システム使用状況: %s" -#: access/transam/xlogrecovery.c:1881 +#: access/transam/xlogrecovery.c:1889 #, c-format msgid "last completed transaction was at log time %s" msgstr "最後に完了したトランザクションのログ時刻は%sでした" -#: access/transam/xlogrecovery.c:1890 +#: access/transam/xlogrecovery.c:1898 #, c-format msgid "redo is not required" msgstr "REDOは必要ありません" -#: access/transam/xlogrecovery.c:1901 +#: access/transam/xlogrecovery.c:1910 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "指定したリカバリターゲットに到達する前にリカバリが終了しました" -#: access/transam/xlogrecovery.c:2095 +#: access/transam/xlogrecovery.c:2104 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "%X/%Xで%sに上書きされて失われた継続行を正常にスキップしました" -#: access/transam/xlogrecovery.c:2162 +#: access/transam/xlogrecovery.c:2171 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "%2$s で想定外のディレクトリエントリ\"%1$s\"が見つかりました" -#: access/transam/xlogrecovery.c:2164 +#: access/transam/xlogrecovery.c:2173 #, c-format -msgid "All directory entries in pg_tblspc/ should be symbolic links." -msgstr "Pg_tblspc/ のすべてのディレクトリエントリは、シンボリックリンクである必要があります。" +msgid "All directory entries in %s/ should be symbolic links." +msgstr "%s 内のすべてのディレクトリエントリは、シンボリックリンクである必要があります。" -#: access/transam/xlogrecovery.c:2165 +#: access/transam/xlogrecovery.c:2175 #, c-format msgid "Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete." msgstr "これらのディレクトリを削除するか、または\"allow_in_place_tablespaces\"を一時的にONに設定することでリカバリを完了させることができます。" -#: access/transam/xlogrecovery.c:2217 +#: access/transam/xlogrecovery.c:2227 #, c-format msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" msgstr "REDO LSN%X/%X、終了LSN %X/%Xのバックアップ・リカバリが完了しました" -#: access/transam/xlogrecovery.c:2247 +#: access/transam/xlogrecovery.c:2258 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "%X/%X でリカバリの一貫性が確保されました" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2285 +#: access/transam/xlogrecovery.c:2296 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "%X/%Xにある%sのWAL再生" -#: access/transam/xlogrecovery.c:2383 +#: access/transam/xlogrecovery.c:2394 #, c-format msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record" msgstr "チェックポイントレコードにおいて想定外の前回のタイムラインID %u(現在のタイムラインIDは%u)がありました" -#: access/transam/xlogrecovery.c:2392 +#: access/transam/xlogrecovery.c:2403 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "チェックポイントレコードにおいて想定外のタイムラインID %u (%uの後)がありました" -#: access/transam/xlogrecovery.c:2408 +#: access/transam/xlogrecovery.c:2419 #, c-format msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u" msgstr "タイムライン%4$uの最小リカバリポイント%2$X/%3$Xに達する前のチェックポイントレコード内の想定外のタイムラインID%1$u。" -#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 +#: access/transam/xlogrecovery.c:2603 access/transam/xlogrecovery.c:2879 #, c-format msgid "recovery stopping after reaching consistency" msgstr "リカバリ処理は一貫性確保後に停止します" -#: access/transam/xlogrecovery.c:2613 +#: access/transam/xlogrecovery.c:2624 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "リカバリ処理はWAL位置(LSN)\"%X/%X\"の前で停止します" -#: access/transam/xlogrecovery.c:2703 +#: access/transam/xlogrecovery.c:2714 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "リカバリ処理はトランザクション%uのコミット、時刻%sの前に停止します" -#: access/transam/xlogrecovery.c:2710 +#: access/transam/xlogrecovery.c:2721 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "リカバリ処理はトランザクション%uのアボート、時刻%sの前に停止します" -#: access/transam/xlogrecovery.c:2763 +#: access/transam/xlogrecovery.c:2774 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "リカバリ処理は復元ポイント\"%s\"、時刻%s に停止します" -#: access/transam/xlogrecovery.c:2781 +#: access/transam/xlogrecovery.c:2792 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "リカバリ処理はWAL位置(LSN)\"%X/%X\"の後で停止します" -#: access/transam/xlogrecovery.c:2848 +#: access/transam/xlogrecovery.c:2859 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "リカバリ処理はトランザクション%uのコミット、時刻%sの後に停止します" -#: access/transam/xlogrecovery.c:2856 +#: access/transam/xlogrecovery.c:2867 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "リカバリ処理はトランザクション%uのアボート、時刻%sの後に停止します" -#: access/transam/xlogrecovery.c:2937 +#: access/transam/xlogrecovery.c:2948 #, c-format msgid "pausing at the end of recovery" msgstr "リカバリ完了位置で一時停止しています" -#: access/transam/xlogrecovery.c:2938 +#: access/transam/xlogrecovery.c:2949 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "再開するには pg_wal_replay_resume() を実行してください" -#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4678 +#: access/transam/xlogrecovery.c:2952 access/transam/xlogrecovery.c:4698 #, c-format msgid "recovery has paused" msgstr "リカバリは一時停止中です" -#: access/transam/xlogrecovery.c:2942 +#: access/transam/xlogrecovery.c:2953 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "再開するには pg_xlog_replay_resume() を実行してください" -#: access/transam/xlogrecovery.c:3205 +#: access/transam/xlogrecovery.c:3216 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%2$s、LSN %3$X/%4$X、オフセット%5$uで想定外のタイムラインID%1$u" -#: access/transam/xlogrecovery.c:3413 +#: access/transam/xlogrecovery.c:3432 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "WALセグメント%s、LSN %X/%X、オフセット%uを読み取れませんでした: %m" -#: access/transam/xlogrecovery.c:3420 +#: access/transam/xlogrecovery.c:3439 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" msgstr "WALセグメント%1$s、LSN %2$X/%3$X、オフセット%4$uを読み取れませんでした: %6$zu 中 %5$d の読み込み" -#: access/transam/xlogrecovery.c:4060 +#: access/transam/xlogrecovery.c:4082 #, c-format msgid "invalid checkpoint location" msgstr "不正なチェックポイント位置" -#: access/transam/xlogrecovery.c:4070 +#: access/transam/xlogrecovery.c:4092 #, c-format msgid "invalid checkpoint record" msgstr "チェックポイントレコードが不正です" -#: access/transam/xlogrecovery.c:4076 +#: access/transam/xlogrecovery.c:4098 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "チェックポイントレコード内のリソースマネージャIDがで不正です" -#: access/transam/xlogrecovery.c:4084 +#: access/transam/xlogrecovery.c:4106 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "チェックポイントレコード内のxl_infoが不正です" -#: access/transam/xlogrecovery.c:4090 +#: access/transam/xlogrecovery.c:4112 #, c-format msgid "invalid length of checkpoint record" msgstr "チェックポイントレコード長が不正です" -#: access/transam/xlogrecovery.c:4144 +#: access/transam/xlogrecovery.c:4166 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "新しいタイムライン%uはデータベースシステムのタイムライン%uの子ではありません" -#: access/transam/xlogrecovery.c:4158 +#: access/transam/xlogrecovery.c:4180 #, c-format msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X" msgstr "新しいタイムライン%uは現在のデータベースシステムのタイムライン%uから現在のリカバリポイント%X/%Xより前に分岐しています" -#: access/transam/xlogrecovery.c:4177 +#: access/transam/xlogrecovery.c:4199 #, c-format msgid "new target timeline is %u" msgstr "新しい目標タイムラインは%uです" -#: access/transam/xlogrecovery.c:4380 +#: access/transam/xlogrecovery.c:4400 #, c-format msgid "WAL receiver process shutdown requested" msgstr "wal receiverプロセスのシャットダウンが要求されました" -#: access/transam/xlogrecovery.c:4440 +#: access/transam/xlogrecovery.c:4460 #, c-format msgid "received promote request" msgstr "昇格要求を受信しました" -#: access/transam/xlogrecovery.c:4669 +#: access/transam/xlogrecovery.c:4689 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "不十分なパラメータ設定のため、ホットスタンバイを使用できません" -#: access/transam/xlogrecovery.c:4670 access/transam/xlogrecovery.c:4697 access/transam/xlogrecovery.c:4727 +#: access/transam/xlogrecovery.c:4690 access/transam/xlogrecovery.c:4717 access/transam/xlogrecovery.c:4747 #, c-format msgid "%s = %d is a lower setting than on the primary server, where its value was %d." msgstr "%s = %d はプライマリサーバーの設定値より小さいです、プライマリサーバーではこの値は%dでした。" -#: access/transam/xlogrecovery.c:4679 +#: access/transam/xlogrecovery.c:4699 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "リカバリの一時停止を解除すると、サーバーはシャットダウンします。" -#: access/transam/xlogrecovery.c:4680 +#: access/transam/xlogrecovery.c:4700 #, c-format msgid "You can then restart the server after making the necessary configuration changes." msgstr "その後、必要な設定変更を行った後にサーバーを再起動できます。" -#: access/transam/xlogrecovery.c:4691 +#: access/transam/xlogrecovery.c:4711 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "不十分なパラメータ設定のため、昇格できません" -#: access/transam/xlogrecovery.c:4701 +#: access/transam/xlogrecovery.c:4721 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "必要な設定変更を行ったのち、サーバーを再起動してください。" -#: access/transam/xlogrecovery.c:4725 +#: access/transam/xlogrecovery.c:4745 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "不十分なパラメータ設定値のためリカバリが停止しました" -#: access/transam/xlogrecovery.c:4731 +#: access/transam/xlogrecovery.c:4751 #, c-format msgid "You can restart the server after making the necessary configuration changes." msgstr "必要な設定変更を行うことでサーバーを再起動できます。" -#: access/transam/xlogrecovery.c:4773 +#: access/transam/xlogrecovery.c:4792 #, c-format msgid "multiple recovery targets specified" msgstr "複数のリカバリ目標が指定されています" -#: access/transam/xlogrecovery.c:4774 +#: access/transam/xlogrecovery.c:4793 #, c-format msgid "At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set." msgstr "\" recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time, recovery_target_xid\" はこの中の1つまで設定可能です。" -#: access/transam/xlogrecovery.c:4785 +#: access/transam/xlogrecovery.c:4804 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "\"immediate\"のみが指定可能です。" -#: access/transam/xlogrecovery.c:4937 utils/adt/timestamp.c:202 utils/adt/timestamp.c:455 +#: access/transam/xlogrecovery.c:4958 #, c-format -msgid "timestamp out of range: \"%s\"" -msgstr "timestampが範囲外です: \"%s\"" +msgid "Timestamp out of range: \"%s\"." +msgstr "timestampが範囲外です: \"%s\"。" -#: access/transam/xlogrecovery.c:4982 +#: access/transam/xlogrecovery.c:5003 #, c-format msgid "\"recovery_target_timeline\" is not a valid number." msgstr "\"recovery_target_timeline\"が数値として妥当ではありません。" -#: access/transam/xlogutils.c:1032 +#: access/transam/xlogutils.c:1023 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "WALセグメント%s、オフセット%dを読み取れませんでした: %m" -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1030 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "WALセグメント%1$s、オフセット%2$dを読み取れませんでした: %4$d 中 %3$d 読み込みました" @@ -3441,7 +3416,7 @@ msgstr "失敗したアーカイブコマンドは次のとおりです: %s" msgid "archive command was terminated by exception 0x%X" msgstr "アーカイブコマンドが例外0x%Xで終了しました" -#: archive/shell_archive.c:109 postmaster/postmaster.c:3094 +#: archive/shell_archive.c:109 postmaster/postmaster.c:2843 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "16進値の説明についてはC インクルードファイル\"ntstatus.h\"を参照してください。" @@ -3456,159 +3431,159 @@ msgstr "アーカイブコマンドはシグナル%dにより終了しました: msgid "archive command exited with unrecognized status %d" msgstr "アーカイブコマンドは不明のステータス%dで終了しました" -#: backup/backup_manifest.c:254 +#: backup/backup_manifest.c:255 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "最終タイムライン%uを期待していましたがタイムライン%uが見つかりました" -#: backup/backup_manifest.c:278 +#: backup/backup_manifest.c:279 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "開始タイムライン%uを期待していましたがタイムライン%uが見つかりました" -#: backup/backup_manifest.c:305 +#: backup/backup_manifest.c:306 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "開始タイムライン%uはタイムライン%uの履歴中にありません" -#: backup/backup_manifest.c:356 +#: backup/backup_manifest.c:357 #, c-format msgid "could not rewind temporary file" msgstr "一時ファイルを巻き戻しに失敗しました" -#: backup/basebackup.c:479 +#: backup/basebackup.c:481 #, c-format msgid "could not find any WAL files" msgstr "WALファイルが全くありません" -#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 +#: backup/basebackup.c:496 backup/basebackup.c:511 backup/basebackup.c:520 #, c-format msgid "could not find WAL file \"%s\"" msgstr "WALファイル\"%s\"がありませんでした" -#: backup/basebackup.c:560 backup/basebackup.c:585 +#: backup/basebackup.c:562 backup/basebackup.c:587 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "想定しないWALファイルのサイズ\"%s\"" -#: backup/basebackup.c:656 +#: backup/basebackup.c:658 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" msgstr[0] "合計%lld個のデータチェックサム検証エラー" -#: backup/basebackup.c:663 +#: backup/basebackup.c:665 #, c-format msgid "checksum verification failure during base backup" msgstr "ベースバックアップ中にチェックサム確認が失敗しました" -#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 +#: backup/basebackup.c:735 backup/basebackup.c:744 backup/basebackup.c:755 backup/basebackup.c:772 backup/basebackup.c:781 backup/basebackup.c:790 backup/basebackup.c:805 backup/basebackup.c:822 backup/basebackup.c:831 backup/basebackup.c:843 backup/basebackup.c:867 backup/basebackup.c:881 backup/basebackup.c:892 backup/basebackup.c:903 backup/basebackup.c:916 #, c-format msgid "duplicate option \"%s\"" msgstr "\"%s\"オプションは重複しています" -#: backup/basebackup.c:761 +#: backup/basebackup.c:763 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "認識されないチェックポイントタイプ: \"%s\"" -#: backup/basebackup.c:793 +#: backup/basebackup.c:795 #, c-format msgid "incremental backups cannot be taken unless WAL summarization is enabled" msgstr "WAL集約が有効でなければ差分バックアップは取得できません" -#: backup/basebackup.c:809 +#: backup/basebackup.c:811 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%dはパラメータ\"%s\"の有効範囲を超えています(%d .. %d)" -#: backup/basebackup.c:854 +#: backup/basebackup.c:856 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "認識できない目録オプション: \"%s\"" -#: backup/basebackup.c:905 +#: backup/basebackup.c:907 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "認識できない圧縮アルゴリズム: \"%s\"" -#: backup/basebackup.c:921 +#: backup/basebackup.c:923 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "認識できないベースバックアップオプション: \"%s\"" -#: backup/basebackup.c:932 +#: backup/basebackup.c:934 #, c-format msgid "manifest checksums require a backup manifest" msgstr "目録のチェックサムにはバックアップ目録が必要です" -#: backup/basebackup.c:941 +#: backup/basebackup.c:943 #, c-format msgid "target detail cannot be used without target" msgstr "ターゲット詳細はターゲットの指定なしでは指定できません" -#: backup/basebackup.c:950 backup/basebackup_target.c:218 +#: backup/basebackup.c:952 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "ターゲット\"%s\"はターゲット詳細を受け付けません" -#: backup/basebackup.c:961 +#: backup/basebackup.c:963 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "圧縮詳細は圧縮が有効でない場合は指定できません" -#: backup/basebackup.c:974 +#: backup/basebackup.c:976 #, c-format msgid "invalid compression specification: %s" msgstr "不正な圧縮指定: %s" -#: backup/basebackup.c:1024 +#: backup/basebackup.c:1026 #, c-format msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" msgstr "差分のBASE_BACKUPの実行前にUPLOAD_MANIFESTを実行する必要があります" -#: backup/basebackup.c:1157 backup/basebackup.c:1358 +#: backup/basebackup.c:1159 backup/basebackup.c:1360 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "\"%s\"というファイルまたはディレクトリの情報を取得できませんでした。: %m" -#: backup/basebackup.c:1544 +#: backup/basebackup.c:1546 #, c-format msgid "skipping special file \"%s\"" msgstr "スペシャルファイル\"%s\"をスキップしています" -#: backup/basebackup.c:1751 +#: backup/basebackup.c:1753 #, c-format msgid "could not verify checksum in file \"%s\", block %u: read buffer size %d and page size %d differ" msgstr "ファイル\"%s\"、ブロック%uでチェックサム検証に失敗しました: 読み込みバッファサイズ%dとページサイズ%dが異なっています" -#: backup/basebackup.c:1813 +#: backup/basebackup.c:1815 #, c-format msgid "file \"%s\" has a total of %d checksum verification failure" msgid_plural "file \"%s\" has a total of %d checksum verification failures" msgstr[0] "ファイル\"%s\"では合計%d個のチェックサムエラーが発生しました" -#: backup/basebackup.c:1917 +#: backup/basebackup.c:1920 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" msgstr "ファイル\"%s\"のブロック%uでチェックサム検証が失敗しました: 計算されたチェックサムは%Xですが想定は%Xです" -#: backup/basebackup.c:1924 +#: backup/basebackup.c:1927 #, c-format msgid "further checksum verification failures in file \"%s\" will not be reported" msgstr "ファイル\"%s\"における以降のチェックサムエラーは報告されません" -#: backup/basebackup.c:2048 +#: backup/basebackup.c:2052 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "ファイル名がtarフォーマットに対して長すぎます: \"%s\"" -#: backup/basebackup.c:2053 +#: backup/basebackup.c:2058 #, c-format msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "シンボリックリンクのリンク先tarのフォーマットにとって長すぎます: ファイル名 \"%s\", リンク先 \"%s\"" -#: backup/basebackup.c:2127 +#: backup/basebackup.c:2132 #, c-format msgid "could not read file \"%s\": read %zd of %zu" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$zdバイトを読み込みました" @@ -3623,80 +3598,65 @@ msgstr "このビルドではgzip圧縮はサポートされていません" msgid "could not initialize compression library" msgstr "圧縮ライブラリを初期化できませんでした" -#: backup/basebackup_incremental.c:300 +#: backup/basebackup_incremental.c:292 #, c-format msgid "manifest contains no required WAL ranges" msgstr "必要となるWAL範囲がマニフェストに含まれてません" -#: backup/basebackup_incremental.c:355 +#: backup/basebackup_incremental.c:347 #, c-format msgid "timeline %u found in manifest, but not in this server's history" msgstr "タイムライン%uがマニフェストにありましたが、サーバーの履歴上に存在しません" -#: backup/basebackup_incremental.c:420 +#: backup/basebackup_incremental.c:412 #, c-format msgid "manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X" msgstr "マニフェストが%2$X/%3$Xから始まる初期タイムライン%1$uのWALを必要としてますが、このタイムラインは%4$X/%5$Xから始まっています" -#: backup/basebackup_incremental.c:430 +#: backup/basebackup_incremental.c:422 #, c-format msgid "manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X" msgstr "マニフェストが%2$X/%3$Xから始まる継続タイムライン%1$uのWALをを必要としてますが、このタイムラインは%4$X/%5$Xから始まっています" -#: backup/basebackup_incremental.c:441 +#: backup/basebackup_incremental.c:433 #, c-format msgid "manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X" msgstr "マニフェストは%2$X/%3$Xで終了する最終タイムライン%1$uからのWALを必要としますが、このバックアップは%4$X/%5$Xで開始されます" -#: backup/basebackup_incremental.c:451 -#, c-format -msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" -msgstr "マニフェストが%2$X/%3$Xで終了する非最終タイムライン%1$uのWALをを必要としてますが、このサーバーではタイムラインが%4$X/%5$Xで切り替わっています" - -#: backup/basebackup_incremental.c:518 -#, c-format -msgid "WAL summarization is not progressing" -msgstr "WAL集計が進んでいません" - -#: backup/basebackup_incremental.c:519 -#, c-format -msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." -msgstr "集計は%X/%Xまで進んでいる必要がありますが、ディスク上では%X/%X、メモリ上では%X/%Xよりあとまで進んでいません。" - -#: backup/basebackup_incremental.c:532 +#: backup/basebackup_incremental.c:437 #, c-format -msgid "still waiting for WAL summarization through %X/%X after %ld seconds" -msgstr "%3$ld秒経過しましたが、WAL集計が%1$X/%2$Xに到達するのを待っている状況です" +msgid "This can happen for incremental backups on a standby if there was little activity since the previous backup." +msgstr "これはスタンバイ上の差分バックアップで前回のバックアップ以降の更新が少なかった場合に起きることがあります。" -#: backup/basebackup_incremental.c:535 +#: backup/basebackup_incremental.c:444 #, c-format -msgid "Summarization has reached %X/%X on disk and %X/%X in memory." -msgstr "集計がディスク上で%X/%X、メモリ上で%X/%Xに到達しました。" +msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" +msgstr "マニフェストが%2$X/%3$Xで終了する非最終タイムライン%1$uのWALをを必要としてますが、このサーバーではタイムラインが%4$X/%5$Xで切り替わっています" -#: backup/basebackup_incremental.c:604 +#: backup/basebackup_incremental.c:525 #, c-format msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist" msgstr "WAL集計がタイムライン%u上の%X/%Xから%X/%Xまで必要ですが、そのタイムライン上のそのLSN範囲での集計は存在しません" -#: backup/basebackup_incremental.c:611 +#: backup/basebackup_incremental.c:532 #, c-format msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete" msgstr "WAL集計がタイムライン%u上の%X/%Xから%X/%Xまで必要ですが、そのタイムライン上のそのLSN範囲での集計は不完全です" -#: backup/basebackup_incremental.c:615 +#: backup/basebackup_incremental.c:536 #, c-format msgid "The first unsummarized LSN in this range is %X/%X." msgstr "この範囲で集計されていない最初のLSNは%X/%Xです。" -#: backup/basebackup_incremental.c:1015 +#: backup/basebackup_incremental.c:934 #, c-format msgid "backup manifest version 1 does not support incremental backup" msgstr "バックアップ目録のバージョン1は差分バックアップをサポートしていません" -#: backup/basebackup_incremental.c:1033 +#: backup/basebackup_incremental.c:952 #, c-format -msgid "manifest system identifier is %llu, but database system identifier is %llu" -msgstr "目録のシステム識別子が%lluですが、データベースのシステム識別子は%lluです" +msgid "system identifier in backup manifest is %, but database system identifier is %" +msgstr "バックアップ目録中のシステム識別子が%ですが、データベースのシステム識別子は%です" #: backup/basebackup_lz4.c:67 #, c-format @@ -3718,7 +3678,7 @@ msgstr "\"%s\"ロールの権限を持つロールのみが、サーバー上に msgid "relative path not allowed for backup stored on server" msgstr "サーバー上に格納されるバックアップでは相対パスは指定できません" -#: backup/basebackup_server.c:102 commands/dbcommands.c:477 commands/tablespace.c:157 commands/tablespace.c:173 commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 storage/file/copydir.c:47 +#: backup/basebackup_server.c:102 commands/dbcommands.c:478 commands/tablespace.c:157 commands/tablespace.c:173 commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:2179 storage/file/copydir.c:58 #, c-format msgid "could not create directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" @@ -3728,12 +3688,12 @@ msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" msgid "directory \"%s\" exists but is not empty" msgstr "ディレクトリ\"%s\"は存在しますが、空ではありません" -#: backup/basebackup_server.c:123 utils/init/postinit.c:1177 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1171 #, c-format msgid "could not access directory \"%s\": %m" msgstr "ディレクトリ\"%s\"にアクセスできませんでした: %m" -#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 backup/basebackup_server.c:268 backup/basebackup_server.c:275 backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 backup/basebackup_server.c:268 backup/basebackup_server.c:275 backup/walsummary.c:312 storage/smgr/md.c:519 storage/smgr/md.c:526 storage/smgr/md.c:608 storage/smgr/md.c:630 storage/smgr/md.c:1123 #, c-format msgid "Check free disk space." msgstr "ディスクの空き容量をチェックしてください。" @@ -3770,669 +3730,669 @@ msgstr "長距離モードを有効化できませんでした: %s" #: backup/walsummaryfuncs.c:95 #, c-format -msgid "invalid timeline %lld" -msgstr "不正なタイムライン%lld" +msgid "invalid timeline %" +msgstr "不正なタイムライン%" -#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3859 +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:626 tcop/postgres.c:3863 +#, c-format +msgid "--%s must be first argument" +msgstr "--%sは最初の引数でなければなりません" + +#: bootstrap/bootstrap.c:253 postmaster/postmaster.c:640 tcop/postgres.c:3877 #, c-format msgid "--%s requires a value" msgstr "--%sには値が必要です" -#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3864 +#: bootstrap/bootstrap.c:258 postmaster/postmaster.c:645 tcop/postgres.c:3882 #, c-format msgid "-c %s requires a value" msgstr "-c %sは値が必要です" -#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 postmaster/postmaster.c:759 +#: bootstrap/bootstrap.c:296 postmaster/postmaster.c:763 postmaster/postmaster.c:776 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "詳細については\"%s --help\"を実行してください。\n" -#: bootstrap/bootstrap.c:291 +#: bootstrap/bootstrap.c:305 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: コマンドライン引数が不正です\n" -#: catalog/aclchk.c:210 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "グラントオプションはロールにのみ付与できます" -#: catalog/aclchk.c:332 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の列\"%1$s\"に付与された権限はありません" -#: catalog/aclchk.c:337 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "\"%s\"に付与された権限はありません" -#: catalog/aclchk.c:345 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の列\"%1$s\"に対して一部の権限が付与されませんでした" -#: catalog/aclchk.c:350 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "\"%s\"に対して一部の権限が付与されませんでした" -#: catalog/aclchk.c:361 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の列\"%1$s\"から剥奪できた権限はありません" -#: catalog/aclchk.c:366 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "\"%s\"に対して剥奪できた権限はありません" -#: catalog/aclchk.c:374 +#: catalog/aclchk.c:375 #, c-format msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の列\"%1$s\"に対して一部の権限が剥奪できませんでした" -#: catalog/aclchk.c:379 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "\"%s\"に対して一部の権限が剥奪できませんでした" -#: catalog/aclchk.c:411 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "権限付与者は現在のユーザーでなければなりません" -#: catalog/aclchk.c:479 catalog/aclchk.c:1054 +#: catalog/aclchk.c:480 catalog/aclchk.c:982 #, c-format msgid "invalid privilege type %s for relation" msgstr "リレーションに対する不正な権限のタイプ %s" -#: catalog/aclchk.c:483 catalog/aclchk.c:1058 +#: catalog/aclchk.c:484 catalog/aclchk.c:986 #, c-format msgid "invalid privilege type %s for sequence" msgstr "シーケンスに対する不正な権限のタイプ %s" -#: catalog/aclchk.c:487 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "データベースに対する不正な権限タイプ %s" -#: catalog/aclchk.c:491 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "ドメインに対する不正な権限タイプ %s" -#: catalog/aclchk.c:495 catalog/aclchk.c:1062 +#: catalog/aclchk.c:496 catalog/aclchk.c:990 #, c-format msgid "invalid privilege type %s for function" msgstr "関数に対する不正な権限タイプ %s" -#: catalog/aclchk.c:499 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "言語に対する不正な権限タイプ %s" -#: catalog/aclchk.c:503 +#: catalog/aclchk.c:504 catalog/aclchk.c:1010 #, c-format msgid "invalid privilege type %s for large object" msgstr "ラージオブジェクトに対する不正な権限タイプ %s" -#: catalog/aclchk.c:507 catalog/aclchk.c:1078 +#: catalog/aclchk.c:508 catalog/aclchk.c:1006 #, c-format msgid "invalid privilege type %s for schema" msgstr "スキーマに対する不正な権限タイプ %s" -#: catalog/aclchk.c:511 catalog/aclchk.c:1066 +#: catalog/aclchk.c:512 catalog/aclchk.c:994 #, c-format msgid "invalid privilege type %s for procedure" msgstr "プロシージャに対する不正な権限タイプ %s" -#: catalog/aclchk.c:515 catalog/aclchk.c:1070 +#: catalog/aclchk.c:516 catalog/aclchk.c:998 #, c-format msgid "invalid privilege type %s for routine" msgstr "ルーチンに対する不正な権限のタイプ %s" -#: catalog/aclchk.c:519 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "テーブル空間に対する不正な権限タイプ %s" -#: catalog/aclchk.c:523 catalog/aclchk.c:1074 +#: catalog/aclchk.c:524 catalog/aclchk.c:1002 #, c-format msgid "invalid privilege type %s for type" msgstr "型に対する不正な権限タイプ %s" -#: catalog/aclchk.c:527 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "外部データラッパーに対する不正な権限タイプ %s" -#: catalog/aclchk.c:531 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "外部サーバーに対する不正な権限タイプ %s" -#: catalog/aclchk.c:535 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "パラメータに対する不正な権限タイプ %s" -#: catalog/aclchk.c:574 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "列権限はリレーションに対してのみ有効です" -#: catalog/aclchk.c:737 catalog/aclchk.c:3626 catalog/objectaddress.c:1054 catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 -#, c-format -msgid "large object %u does not exist" -msgstr "ラージオブジェクト%uは存在しません" - -#: catalog/aclchk.c:1111 +#: catalog/aclchk.c:1043 #, c-format msgid "default privileges cannot be set for columns" msgstr "デフォルト権限は列には設定できません" -#: catalog/aclchk.c:1147 +#: catalog/aclchk.c:1079 #, c-format msgid "permission denied to change default privileges" msgstr "デフォルト権限を変更する権限がありません" -#: catalog/aclchk.c:1265 +#: catalog/aclchk.c:1197 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "GRANT/REVOKE ON SCHEMAS を使っている時には IN SCHEMA 句は指定できません" -#: catalog/aclchk.c:1616 catalog/catalog.c:629 catalog/objectaddress.c:1523 catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:913 commands/sequence.c:1645 commands/tablecmds.c:7549 commands/tablecmds.c:7703 commands/tablecmds.c:7753 commands/tablecmds.c:7827 commands/tablecmds.c:7897 commands/tablecmds.c:8027 commands/tablecmds.c:8156 commands/tablecmds.c:8250 commands/tablecmds.c:8351 commands/tablecmds.c:8478 commands/tablecmds.c:8508 -#: commands/tablecmds.c:8650 commands/tablecmds.c:8743 commands/tablecmds.c:8877 commands/tablecmds.c:8989 commands/tablecmds.c:12709 commands/tablecmds.c:12890 commands/tablecmds.c:13051 commands/tablecmds.c:14240 commands/tablecmds.c:16866 commands/trigger.c:942 parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 parser/parse_type.c:144 parser/parse_utilcmd.c:3538 parser/parse_utilcmd.c:3578 parser/parse_utilcmd.c:3620 utils/adt/acl.c:2917 -#: utils/adt/ruleutils.c:2811 +#: catalog/aclchk.c:1207 +#, c-format +msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON LARGE OBJECTS" +msgstr "GRANT/REVOKE ON LARGE OBJECTS を使っている時には IN SCHEMA 句は指定できません" + +#: catalog/aclchk.c:1561 catalog/catalog.c:655 catalog/heap.c:2611 catalog/heap.c:2930 catalog/objectaddress.c:1528 catalog/pg_publication.c:570 commands/analyze.c:388 commands/copy.c:1000 commands/sequence.c:1655 commands/tablecmds.c:7750 commands/tablecmds.c:7928 commands/tablecmds.c:8129 commands/tablecmds.c:8258 commands/tablecmds.c:8387 commands/tablecmds.c:8481 commands/tablecmds.c:8584 commands/tablecmds.c:8750 commands/tablecmds.c:8780 +#: commands/tablecmds.c:8935 commands/tablecmds.c:9038 commands/tablecmds.c:9172 commands/tablecmds.c:9285 commands/tablecmds.c:14325 commands/tablecmds.c:14525 commands/tablecmds.c:14686 commands/tablecmds.c:15891 commands/tablecmds.c:18658 commands/trigger.c:947 parser/analyze.c:2660 parser/parse_relation.c:749 parser/parse_target.c:1070 parser/parse_type.c:144 parser/parse_utilcmd.c:3641 parser/parse_utilcmd.c:3681 parser/parse_utilcmd.c:3723 +#: statistics/attribute_stats.c:209 statistics/attribute_stats.c:948 utils/adt/acl.c:2921 utils/adt/ruleutils.c:2858 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "リレーション\"%2$s\"の列\"%1$s\"は存在しません" -#: catalog/aclchk.c:1861 +#: catalog/aclchk.c:1806 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\"はインデックスです" -#: catalog/aclchk.c:1868 commands/tablecmds.c:14397 commands/tablecmds.c:17775 +#: catalog/aclchk.c:1813 commands/tablecmds.c:16048 commands/tablecmds.c:19577 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\"は複合型です" -#: catalog/aclchk.c:1876 catalog/objectaddress.c:1363 commands/tablecmds.c:263 commands/tablecmds.c:17739 utils/adt/acl.c:2101 utils/adt/acl.c:2131 utils/adt/acl.c:2164 utils/adt/acl.c:2200 utils/adt/acl.c:2231 utils/adt/acl.c:2262 +#: catalog/aclchk.c:1821 catalog/objectaddress.c:1368 commands/tablecmds.c:266 commands/tablecmds.c:19541 utils/adt/acl.c:2105 utils/adt/acl.c:2135 utils/adt/acl.c:2168 utils/adt/acl.c:2204 utils/adt/acl.c:2235 utils/adt/acl.c:2266 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\"はシーケンスではありません" -#: catalog/aclchk.c:1914 +#: catalog/aclchk.c:1859 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "シーケンス \"%s\"では USAGE, SELECT, UPDATE 権限のみをサポートします" -#: catalog/aclchk.c:1931 +#: catalog/aclchk.c:1876 #, c-format msgid "invalid privilege type %s for table" msgstr "テーブルに対する権限タイプ%sは不正です" -#: catalog/aclchk.c:2094 +#: catalog/aclchk.c:2041 #, c-format msgid "invalid privilege type %s for column" msgstr "列では権限タイプ %s は無効です" -#: catalog/aclchk.c:2107 +#: catalog/aclchk.c:2054 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "シーケンス \"%s\"では USAGE, SELECT, UPDATE のみをサポートします" -#: catalog/aclchk.c:2297 +#: catalog/aclchk.c:2245 #, c-format msgid "language \"%s\" is not trusted" msgstr "言語\"%s\"は信頼されていません" -#: catalog/aclchk.c:2299 +#: catalog/aclchk.c:2247 #, c-format msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages." msgstr "信頼されない言語はスーパーユーザーのみが使用可能なため、GRANTとREVOKEは信頼されない言語上では実行不可です。" -#: catalog/aclchk.c:2451 +#: catalog/aclchk.c:2398 #, c-format msgid "cannot set privileges of array types" msgstr "配列型の権限を設定できません" -#: catalog/aclchk.c:2452 +#: catalog/aclchk.c:2399 #, c-format msgid "Set the privileges of the element type instead." msgstr "代わりに要素型の権限を設定してください。" -#: catalog/aclchk.c:2456 +#: catalog/aclchk.c:2403 #, c-format msgid "cannot set privileges of multirange types" msgstr "複範囲型の権限を設定できません" -#: catalog/aclchk.c:2457 +#: catalog/aclchk.c:2404 #, c-format msgid "Set the privileges of the range type instead." msgstr "代わりに範囲型の権限を設定してください。" -#: catalog/aclchk.c:2464 catalog/objectaddress.c:1629 -#, c-format -msgid "\"%s\" is not a domain" -msgstr "\"%s\"はドメインではありません" - -#: catalog/aclchk.c:2650 +#: catalog/aclchk.c:2587 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "認識できない権限タイプ\"%s\"" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2654 #, c-format msgid "permission denied for aggregate %s" msgstr "集約 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2657 #, c-format msgid "permission denied for collation %s" msgstr "照合順序 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2660 #, c-format msgid "permission denied for column %s" msgstr "列 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2663 #, c-format msgid "permission denied for conversion %s" msgstr "変換 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2666 #, c-format msgid "permission denied for database %s" msgstr "データベース %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2669 #, c-format msgid "permission denied for domain %s" msgstr "ドメイン %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2672 #, c-format msgid "permission denied for event trigger %s" msgstr "イベントトリガ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2675 #, c-format msgid "permission denied for extension %s" msgstr "機能拡張 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2678 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "外部データラッパ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2681 #, c-format msgid "permission denied for foreign server %s" msgstr "外部サーバー %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2684 #, c-format msgid "permission denied for foreign table %s" msgstr "外部テーブル %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2687 #, c-format msgid "permission denied for function %s" msgstr "関数 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2690 #, c-format msgid "permission denied for index %s" msgstr "インデックス %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2693 #, c-format msgid "permission denied for language %s" msgstr "言語 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2759 +#: catalog/aclchk.c:2696 #, c-format msgid "permission denied for large object %s" msgstr "ラージオブジェクト %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2699 #, c-format msgid "permission denied for materialized view %s" msgstr "実体化ビュー %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2702 #, c-format msgid "permission denied for operator class %s" msgstr "演算子クラス %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2705 #, c-format msgid "permission denied for operator %s" msgstr "演算子 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2708 #, c-format msgid "permission denied for operator family %s" msgstr "演算子族 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2711 #, c-format msgid "permission denied for parameter %s" msgstr "パラメータ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2714 #, c-format msgid "permission denied for policy %s" msgstr "ポリシ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2717 #, c-format msgid "permission denied for procedure %s" msgstr "プロシージャ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for publication %s" msgstr "パブリケーション%sへのアクセスが拒否されました" -#: catalog/aclchk.c:2786 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for routine %s" msgstr "ルーチン %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2789 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for schema %s" msgstr "スキーマ %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2792 commands/sequence.c:647 commands/sequence.c:873 commands/sequence.c:915 commands/sequence.c:956 commands/sequence.c:1743 commands/sequence.c:1789 +#: catalog/aclchk.c:2729 commands/sequence.c:654 commands/sequence.c:880 commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 #, c-format msgid "permission denied for sequence %s" msgstr "シーケンス %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2795 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for statistics object %s" msgstr "統計情報オブジェクト %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2798 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for subscription %s" msgstr "サブスクリプション %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2801 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for table %s" msgstr "テーブル %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2804 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for tablespace %s" msgstr "テーブル空間 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2807 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for text search configuration %s" msgstr "テキスト検索設定 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2810 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for text search dictionary %s" msgstr "テキスト検索辞書 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2813 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for type %s" msgstr "型 %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2816 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for view %s" msgstr "ビュー %s へのアクセスが拒否されました" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2789 #, c-format msgid "must be owner of aggregate %s" msgstr "集約 %s の所有者である必要があります" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2792 #, c-format msgid "must be owner of collation %s" msgstr "照合順序 %s の所有者である必要があります" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2795 #, c-format msgid "must be owner of conversion %s" msgstr "変換 %s の所有者である必要があります" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2798 #, c-format msgid "must be owner of database %s" msgstr "データベース %s の所有者である必要があります" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2801 #, c-format msgid "must be owner of domain %s" msgstr "ドメイン %s の所有者である必要があります" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2804 #, c-format msgid "must be owner of event trigger %s" msgstr "イベントトリガ %s の所有者である必要があります" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2807 #, c-format msgid "must be owner of extension %s" msgstr "機能拡張 %s の所有者である必要があります" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2810 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "外部データラッパー %s の所有者である必要があります" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2813 #, c-format msgid "must be owner of foreign server %s" msgstr "外部サーバー %s の所有者である必要があります" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2816 #, c-format msgid "must be owner of foreign table %s" msgstr "外部テーブル %s の所有者である必要があります" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2819 #, c-format msgid "must be owner of function %s" msgstr "関数 %s の所有者である必要があります" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2822 #, c-format msgid "must be owner of index %s" msgstr "インデックス %s の所有者である必要があります" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2825 #, c-format msgid "must be owner of language %s" msgstr "言語 %s の所有者である必要があります" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2828 #, c-format msgid "must be owner of large object %s" msgstr "ラージオブジェクト %s の所有者である必要があります" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2831 #, c-format msgid "must be owner of materialized view %s" msgstr "実体化ビュー %s の所有者である必要があります" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2834 #, c-format msgid "must be owner of operator class %s" msgstr "演算子クラス %s の所有者である必要があります" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2837 #, c-format msgid "must be owner of operator %s" msgstr "演算子 %s の所有者である必要があります" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2840 #, c-format msgid "must be owner of operator family %s" msgstr "演算子族 %s の所有者である必要があります" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2843 #, c-format msgid "must be owner of procedure %s" msgstr "プロシージャ %s の所有者である必要があります" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2846 #, c-format msgid "must be owner of publication %s" msgstr "パブリケーション %s の所有者である必要があります" -#: catalog/aclchk.c:2912 +#: catalog/aclchk.c:2849 #, c-format msgid "must be owner of routine %s" msgstr "ルーチン %s の所有者である必要があります" -#: catalog/aclchk.c:2915 +#: catalog/aclchk.c:2852 #, c-format msgid "must be owner of sequence %s" msgstr "シーケンス %s の所有者である必要があります" -#: catalog/aclchk.c:2918 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of subscription %s" msgstr "サブスクリプション %s の所有者である必要があります" -#: catalog/aclchk.c:2921 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of table %s" msgstr "テーブル %s の所有者である必要があります" -#: catalog/aclchk.c:2924 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of type %s" msgstr "型 %s の所有者である必要があります" -#: catalog/aclchk.c:2927 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of view %s" msgstr "ビュー %s の所有者である必要があります" -#: catalog/aclchk.c:2930 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of schema %s" msgstr "スキーマ %s の所有者である必要があります" -#: catalog/aclchk.c:2933 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of statistics object %s" msgstr "統計情報オブジェクト %s の所有者である必要があります" -#: catalog/aclchk.c:2936 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of tablespace %s" msgstr "テーブル空間 %s の所有者である必要があります" -#: catalog/aclchk.c:2939 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of text search configuration %s" msgstr "テキスト検索設定 %s の所有者である必要があります" -#: catalog/aclchk.c:2942 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of text search dictionary %s" msgstr "テキスト検索辞書 %s の所有者である必要があります" -#: catalog/aclchk.c:2956 +#: catalog/aclchk.c:2893 #, c-format msgid "must be owner of relation %s" msgstr "リレーション %s の所有者である必要があります" -#: catalog/aclchk.c:3002 +#: catalog/aclchk.c:2939 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の列\"%1$s\"へのアクセスが拒否されました" -#: catalog/aclchk.c:3159 catalog/aclchk.c:4167 catalog/aclchk.c:4198 -#, c-format -msgid "%s with OID %u does not exist" -msgstr "OID %2$uの%1$sは存在しません" - -#: catalog/aclchk.c:3242 catalog/aclchk.c:3261 +#: catalog/aclchk.c:3173 catalog/aclchk.c:3192 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "OID %2$uのリレーションに属性%1$dは存在しません" -#: catalog/aclchk.c:3299 catalog/aclchk.c:3362 catalog/aclchk.c:4001 +#: catalog/aclchk.c:3230 catalog/aclchk.c:3293 catalog/aclchk.c:3932 #, c-format msgid "relation with OID %u does not exist" msgstr "OID %uのリレーションは存在しません" -#: catalog/aclchk.c:3547 +#: catalog/aclchk.c:3478 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "OID %uのパラメータACLは存在しません" -#: catalog/aclchk.c:3720 commands/collationcmds.c:853 commands/publicationcmds.c:1739 +#: catalog/aclchk.c:3557 catalog/objectaddress.c:1055 catalog/pg_largeobject.c:125 libpq/be-fsstubs.c:323 storage/large_object/inv_api.c:247 +#, c-format +msgid "large object %u does not exist" +msgstr "ラージオブジェクト%uは存在しません" + +#: catalog/aclchk.c:3651 commands/collationcmds.c:849 commands/publicationcmds.c:1846 #, c-format msgid "schema with OID %u does not exist" msgstr "OID %uのスキーマは存在しません" -#: catalog/aclchk.c:3794 catalog/aclchk.c:3821 catalog/aclchk.c:3850 utils/cache/typcache.c:392 utils/cache/typcache.c:447 +#: catalog/aclchk.c:3725 catalog/aclchk.c:3752 catalog/aclchk.c:3781 utils/cache/typcache.c:473 utils/cache/typcache.c:528 #, c-format msgid "type with OID %u does not exist" msgstr "OID %uの型は存在しません" -#: catalog/catalog.c:447 +#: catalog/catalog.c:475 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "リレーション\"%s\"での未使用のOIDを探索を継続中" -#: catalog/catalog.c:449 +#: catalog/catalog.c:477 #, c-format -msgid "OID candidates have been checked %llu time, but no unused OID has been found yet." -msgid_plural "OID candidates have been checked %llu times, but no unused OID has been found yet." -msgstr[0] "OID候補のチェックを%llu回行いましたが、使用されていないOIDはまだ見つかっていません。" +msgid "OID candidates have been checked % time, but no unused OID has been found yet." +msgid_plural "OID candidates have been checked % times, but no unused OID has been found yet." +msgstr[0] "OID候補のチェックを%回行いましたが、使用されていないOIDはまだ見つかっていません。" -#: catalog/catalog.c:474 +#: catalog/catalog.c:502 #, c-format -msgid "new OID has been assigned in relation \"%s\" after %llu retry" -msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" -msgstr[0] "リレーション\\\"%s\\\"で%llu回の試行後に新しいOIDが割り当てられました" +msgid "new OID has been assigned in relation \"%s\" after % retry" +msgid_plural "new OID has been assigned in relation \"%s\" after % retries" +msgstr[0] "リレーション\\\"%s\\\"で%回の試行後に新しいOIDが割り当てられました" -#: catalog/catalog.c:607 catalog/catalog.c:674 +#: catalog/catalog.c:633 catalog/catalog.c:700 #, c-format msgid "must be superuser to call %s()" msgstr "%s()を呼び出すにはスーパーユーザーである必要があります" -#: catalog/catalog.c:616 +#: catalog/catalog.c:642 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() はシステムカタログでのみ使用できます" -#: catalog/catalog.c:621 parser/parse_utilcmd.c:2245 +#: catalog/catalog.c:647 parser/parse_utilcmd.c:2426 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "インデックス\"%s\"はテーブル\"%s\"には属していません" -#: catalog/catalog.c:638 +#: catalog/catalog.c:664 #, c-format msgid "column \"%s\" is not of type oid" msgstr "列\"%s\"はoid型ではありません" -#: catalog/catalog.c:645 +#: catalog/catalog.c:671 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "インデックス\"%s\"は列\"%s\"に対するインデックスではありません" -#: catalog/dependency.c:497 catalog/pg_shdepend.c:695 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "データベースシステムが必要としているため%sを削除できません" @@ -4457,7 +4417,7 @@ msgstr "%sは%sに依存しています" msgid "drop cascades to %s" msgstr "削除は%sへ伝播します" -#: catalog/dependency.c:1138 catalog/pg_shdepend.c:860 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -4474,8 +4434,8 @@ msgstr[0] "" msgid "cannot drop %s because other objects depend on it" msgstr "他のオブジェクトが依存しているため%sを削除できません" -#: catalog/dependency.c:1153 catalog/dependency.c:1160 catalog/dependency.c:1171 commands/tablecmds.c:1447 commands/tablecmds.c:14989 commands/tablespace.c:460 commands/user.c:1302 commands/vacuum.c:211 commands/view.c:441 libpq/auth.c:324 replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1427 utils/misc/guc.c:3169 utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6781 -#: utils/misc/guc.c:6815 utils/misc/guc.c:6849 utils/misc/guc.c:6892 utils/misc/guc.c:6934 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 catalog/dependency.c:1171 commands/tablecmds.c:1518 commands/tablecmds.c:16642 commands/tablespace.c:460 commands/user.c:1302 commands/vacuum.c:224 commands/view.c:441 executor/execExprInterp.c:5211 executor/execExprInterp.c:5219 libpq/auth.c:312 replication/logical/applyparallelworker.c:1041 replication/slot.c:1594 replication/syncrep.c:1012 storage/aio/method_io_uring.c:191 storage/lmgr/deadlock.c:1137 +#: storage/lmgr/proc.c:1526 utils/misc/guc.c:3166 utils/misc/guc.c:3207 utils/misc/guc.c:3282 utils/misc/guc.c:6823 utils/misc/guc.c:6857 utils/misc/guc.c:6891 utils/misc/guc.c:6934 utils/misc/guc.c:6976 #, c-format msgid "%s" msgstr "%s" @@ -4496,647 +4456,692 @@ msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" msgstr[0] "削除は他の%d個のオブジェクトに対しても行われます" -#: catalog/dependency.c:1848 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "%s型の定数をここで使用することはできません" -#: catalog/dependency.c:2373 parser/parse_relation.c:3407 parser/parse_relation.c:3417 +#: catalog/dependency.c:2205 +#, c-format +msgid "transition table \"%s\" cannot be referenced in a persistent object" +msgstr "遷移テーブル\"%s\"は永続オブジェクトからは参照できません" + +#: catalog/dependency.c:2390 parser/parse_relation.c:3513 parser/parse_relation.c:3523 statistics/attribute_stats.c:221 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "リレーション\"%2$s\"の列\"%1$d\"は存在しません" -#: catalog/heap.c:325 +#: catalog/heap.c:321 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "\"%s.%s\"を作成する権限がありません" -#: catalog/heap.c:327 +#: catalog/heap.c:323 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "システムカタログの更新は現在禁止されています" -#: catalog/heap.c:467 commands/tablecmds.c:2483 commands/tablecmds.c:2905 commands/tablecmds.c:7171 +#: catalog/heap.c:463 commands/tablecmds.c:2561 commands/tablecmds.c:3013 commands/tablecmds.c:7360 #, c-format msgid "tables can have at most %d columns" msgstr "テーブルは最大で%d列までしか持てません" -#: catalog/heap.c:485 commands/tablecmds.c:7440 +#: catalog/heap.c:481 commands/tablecmds.c:7662 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "列名\"%s\"はシステム用の列名に使われています" -#: catalog/heap.c:501 +#: catalog/heap.c:497 #, c-format msgid "column name \"%s\" specified more than once" msgstr "列名\"%s\"が複数指定されました" #. translator: first %s is an integer not a name -#: catalog/heap.c:579 +#: catalog/heap.c:575 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "パーティションキー列%sは疑似型%sです" -#: catalog/heap.c:584 +#: catalog/heap.c:580 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "列\"%s\"は疑似型%sです" -#: catalog/heap.c:615 +#: catalog/heap.c:595 +#, c-format +msgid "virtual generated column \"%s\" cannot have a domain type" +msgstr "仮想生成列\"%s\"ではドメイン型は使用できません" + +#: catalog/heap.c:622 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "複合型 %s がそれ自身のメンバーになることはできません" #. translator: first %s is an integer not a name -#: catalog/heap.c:670 +#: catalog/heap.c:677 #, c-format msgid "no collation was derived for partition key column %s with collatable type %s" msgstr "照合可能な型 %2$s のパーティションキー列%1$sのための照合順序が見つかりませんでした" -#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:507 +#: catalog/heap.c:683 commands/createas.c:200 commands/createas.c:513 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "照合可能な型 %2$s を持つ列\"%1$s\"のための照合順序を決定できませんでした" -#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:403 commands/tablecmds.c:4142 commands/tablecmds.c:20463 commands/tablecmds.c:20725 +#: catalog/heap.c:1169 catalog/index.c:901 commands/createas.c:409 commands/tablecmds.c:4295 #, c-format msgid "relation \"%s\" already exists" msgstr "リレーション\"%s\"はすでに存在します" -#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 commands/typecmds.c:1585 commands/typecmds.c:2556 +#: catalog/heap.c:1185 catalog/pg_type.c:434 catalog/pg_type.c:805 catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 commands/typecmds.c:758 commands/typecmds.c:1205 commands/typecmds.c:1431 commands/typecmds.c:1611 commands/typecmds.c:2586 #, c-format msgid "type \"%s\" already exists" msgstr "型\"%s\"はすでに存在します" -#: catalog/heap.c:1178 +#: catalog/heap.c:1186 #, c-format msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type." msgstr "リレーションは同じ名前の関連する型を持ちます。このため既存の型と競合しない名前である必要があります。" -#: catalog/heap.c:1218 +#: catalog/heap.c:1226 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にTOASTのrelfilenumberの値が設定されていません" -#: catalog/heap.c:1229 +#: catalog/heap.c:1237 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_classのヒープOIDが設定されていません" -#: catalog/heap.c:1239 +#: catalog/heap.c:1247 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にrelfilenumberの値が設定されていません" -#: catalog/heap.c:2121 +#: catalog/heap.c:2192 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "パーティション親テーブル\"%s\"に NO INHERIT 制約は追加できません" -#: catalog/heap.c:2393 +#: catalog/heap.c:2515 #, c-format msgid "check constraint \"%s\" already exists" msgstr "検査制約\"%s\"はすでに存在します" -#: catalog/heap.c:2565 catalog/index.c:913 catalog/pg_constraint.c:724 commands/tablecmds.c:9364 +#: catalog/heap.c:2616 catalog/heap.c:2936 +#, c-format +msgid "cannot add not-null constraint on system column \"%s\"" +msgstr "システム列\"%s\"に対して非NULL制約を追加することはできません" + +#: catalog/heap.c:2643 catalog/heap.c:2769 catalog/heap.c:3020 catalog/index.c:915 catalog/pg_constraint.c:1000 commands/tablecmds.c:9765 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "すでに制約\"%s\"はリレーション\"%s\"に存在します" -#: catalog/heap.c:2572 +#: catalog/heap.c:2776 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "制約\"%s\"は、リレーション\"%s\"上の継承されていない制約と競合します" -#: catalog/heap.c:2583 +#: catalog/heap.c:2787 #, c-format msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "制約\"%s\"は、リレーション\"%s\"上の継承された制約と競合します" -#: catalog/heap.c:2593 +#: catalog/heap.c:2797 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "制約\"%s\"は、リレーション\"%s\"上の NOT VALID 制約と競合します" -#: catalog/heap.c:2598 +#: catalog/heap.c:2809 +#, c-format +msgid "constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"" +msgstr "制約\"%s\"は、リレーション\"%s\"上の \\NOT ENFORCED制約と競合します" + +#: catalog/heap.c:2814 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "継承された定義により制約\"%s\"をマージしています" -#: catalog/heap.c:2624 catalog/pg_constraint.c:853 commands/tablecmds.c:3062 commands/tablecmds.c:3365 commands/tablecmds.c:7097 commands/tablecmds.c:15807 commands/tablecmds.c:15938 +#: catalog/heap.c:2838 catalog/pg_constraint.c:778 catalog/pg_constraint.c:1129 commands/tablecmds.c:3178 commands/tablecmds.c:3498 commands/tablecmds.c:7285 commands/tablecmds.c:7966 commands/tablecmds.c:17485 commands/tablecmds.c:17667 #, c-format msgid "too many inheritance parents" msgstr "継承の親テーブルが多すぎます" -#: catalog/heap.c:2708 +#: catalog/heap.c:2955 parser/parse_utilcmd.c:2634 +#, c-format +msgid "conflicting NO INHERIT declaration for not-null constraint on column \"%s\"" +msgstr "列\"%s\"に対する非NULL制約にNO INHERIT宣言が競合しています" + +#: catalog/heap.c:2969 +#, c-format +msgid "conflicting not-null constraint names \"%s\" and \"%s\"" +msgstr "非NULL制約の名前\"%s\"と\"%s\"が競合しています" + +#: catalog/heap.c:2999 +#, c-format +msgid "cannot define not-null constraint on column \"%s\" with NO INHERIT" +msgstr "NO INHERIT指定されている列\"%s\"に対して非NULL制約を定義することはできません" + +#: catalog/heap.c:3001 +#, c-format +msgid "The column has an inherited not-null constraint." +msgstr "この列には継承された非NULL制約が存在します。" + +#: catalog/heap.c:3191 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "生成カラム\"%s\"はカラム生成式中では使用できません" -#: catalog/heap.c:2710 +#: catalog/heap.c:3193 #, c-format msgid "A generated column cannot reference another generated column." msgstr "生成カラムは他の生成カラムを参照できません。" -#: catalog/heap.c:2716 +#: catalog/heap.c:3199 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "列生成式内では行全体参照は使用できません" -#: catalog/heap.c:2717 +#: catalog/heap.c:3200 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "これは生成列を自身の値に依存させることにつながります。" -#: catalog/heap.c:2772 +#: catalog/heap.c:3255 #, c-format msgid "generation expression is not immutable" msgstr "生成式は不変ではありません" -#: catalog/heap.c:2800 rewrite/rewriteHandler.c:1281 +#: catalog/heap.c:3283 rewrite/rewriteHandler.c:1285 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "列\"%s\"の型は%sですが、デフォルト式の型は%sです" -#: catalog/heap.c:2805 commands/prepare.c:331 parser/analyze.c:2758 parser/parse_target.c:592 parser/parse_target.c:882 parser/parse_target.c:892 rewrite/rewriteHandler.c:1286 +#: catalog/heap.c:3288 commands/prepare.c:335 parser/analyze.c:2991 parser/parse_target.c:595 parser/parse_target.c:885 parser/parse_target.c:895 rewrite/rewriteHandler.c:1290 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "式を書き換えるかキャストする必要があります。" -#: catalog/heap.c:2852 +#: catalog/heap.c:3335 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "検査制約ではテーブル\"%s\"のみを参照することができます" -#: catalog/heap.c:3158 +#: catalog/heap.c:3641 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "ON COMMITと外部キーの組み合わせはサポートされていません" -#: catalog/heap.c:3159 +#: catalog/heap.c:3642 #, c-format msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting." msgstr "テーブル\"%s\"は\"%s\"を参照します。しかし、これらのON COMMIT設定は同一ではありません。" -#: catalog/heap.c:3164 +#: catalog/heap.c:3647 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "外部キー制約で参照されているテーブルを削除できません" -#: catalog/heap.c:3165 +#: catalog/heap.c:3648 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "テーブル\"%s\"は\"%s\"を参照します。" -#: catalog/heap.c:3167 +#: catalog/heap.c:3650 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "同時にテーブル\"%s\"がtruncateされました。TRUNCATE ... CASCADEを使用してください。" -#: catalog/index.c:219 parser/parse_utilcmd.c:2151 +#: catalog/index.c:220 parser/parse_utilcmd.c:2331 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "テーブル\"%s\"に複数のプライマリキーを持たせることはできません" -#: catalog/index.c:233 +#: catalog/index.c:234 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "プライマリキーではNULLS NOT DISTINCTであるインデックスを使用することはできません" -#: catalog/index.c:250 +#: catalog/index.c:251 #, c-format msgid "primary keys cannot be expressions" msgstr "プライマリキーを式にすることはできません" -#: catalog/index.c:267 +#: catalog/index.c:268 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "主キー列\"%s\"がNOT NULL指定されていません" -#: catalog/index.c:798 catalog/index.c:1914 +#: catalog/index.c:800 catalog/index.c:1921 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "ユーザーによるシステムカタログテーブルに対するインデックスの定義はサポートされていません" -#: catalog/index.c:838 +#: catalog/index.c:840 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "非決定的照合順序は演算子クラス \"%s\" ではサポートされません" -#: catalog/index.c:853 +#: catalog/index.c:855 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "システムカタログテーブルの並行的インデックス作成はサポートされていません" -#: catalog/index.c:862 catalog/index.c:1330 +#: catalog/index.c:864 catalog/index.c:1333 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "排他制約のためのインデックスの並列的作成はサポートされていません" -#: catalog/index.c:871 +#: catalog/index.c:873 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "initdbの後に共有インデックスを作成できません" -#: catalog/index.c:891 commands/createas.c:418 commands/sequence.c:159 parser/parse_utilcmd.c:212 +#: catalog/index.c:893 commands/createas.c:424 commands/sequence.c:159 parser/parse_utilcmd.c:210 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "リレーション\"%s\"はすでに存在します、スキップします" -#: catalog/index.c:941 +#: catalog/index.c:943 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_classのインデックスOIDが設定されていません" -#: catalog/index.c:951 utils/cache/relcache.c:3787 +#: catalog/index.c:953 utils/cache/relcache.c:3781 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にインデックスのrelfilenumberの値が設定されていません" -#: catalog/index.c:2213 +#: catalog/index.c:2222 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLYはトランザクション内で最初の操作でなければなりません" -#: catalog/index.c:3669 +#: catalog/index.c:3729 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "他のセッションの一時テーブルはインデクス再構築できません" -#: catalog/index.c:3680 commands/indexcmds.c:3648 +#: catalog/index.c:3740 commands/indexcmds.c:3757 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "TOASTテーブルの無効なインデックスの再作成はできません" -#: catalog/index.c:3696 commands/indexcmds.c:3526 commands/indexcmds.c:3672 commands/tablecmds.c:3557 +#: catalog/index.c:3756 commands/indexcmds.c:3635 commands/indexcmds.c:3781 commands/tablecmds.c:3702 #, c-format msgid "cannot move system relation \"%s\"" msgstr "システムリレーション\"%s\"を移動できません" -#: catalog/index.c:3833 +#: catalog/index.c:3893 #, c-format msgid "index \"%s\" was reindexed" msgstr "インデックス\"%s\"のインデックス再構築が完了しました" -#: catalog/index.c:3999 +#: catalog/index.c:4059 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "TOASTテーブルの無効なインデックス \"%s.%s\"の再作成はできません、スキップします " -#: catalog/namespace.c:447 catalog/namespace.c:651 catalog/namespace.c:743 commands/trigger.c:5729 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 commands/trigger.c:5780 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "データベース間の参照は実装されていません: \"%s.%s.%s\"" -#: catalog/namespace.c:504 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "一時テーブルにはスキーマ名を指定できません" -#: catalog/namespace.c:585 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "リレーション\"%s.%s\"のロックを取得できませんでした" -#: catalog/namespace.c:590 commands/lockcmds.c:143 commands/lockcmds.c:223 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "リレーション\"%s\"のロックを取得できませんでした" -#: catalog/namespace.c:618 parser/parse_relation.c:1430 +#: catalog/namespace.c:633 parser/parse_relation.c:1447 statistics/stat_utils.c:231 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "リレーション\"%s.%s\"は存在しません" -#: catalog/namespace.c:623 parser/parse_relation.c:1443 parser/parse_relation.c:1451 utils/adt/regproc.c:913 +#: catalog/namespace.c:638 parser/parse_relation.c:1460 parser/parse_relation.c:1468 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "リレーション\"%s\"は存在しません" -#: catalog/namespace.c:689 catalog/namespace.c:3507 commands/extension.c:1607 commands/extension.c:1613 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1804 commands/extension.c:1810 #, c-format msgid "no schema has been selected to create in" msgstr "作成先のスキーマが選択されていません" -#: catalog/namespace.c:841 catalog/namespace.c:854 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "他のセッションの一時スキーマの中にリレーションを作成できません" -#: catalog/namespace.c:845 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "非一時スキーマの中に一時リレーションを作成できません" -#: catalog/namespace.c:860 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "一時スキーマの中には一時リレーションしか作成できません" -#: catalog/namespace.c:2604 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "統計情報オブジェクト\"%s\"は存在しません" -#: catalog/namespace.c:2746 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "テキスト検索パーサ\"%s\"は存在しません" -#: catalog/namespace.c:2891 utils/adt/regproc.c:1459 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "テキスト検索辞書\"%s\"は存在しません" -#: catalog/namespace.c:3037 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "テキスト検索テンプレート\"%s\"は存在しません" -#: catalog/namespace.c:3182 commands/tsearchcmds.c:1168 utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "テキスト検索設定\"%s\"は存在しません" -#: catalog/namespace.c:3314 parser/parse_expr.c:869 parser/parse_target.c:1259 +#: catalog/namespace.c:3329 parser/parse_expr.c:866 parser/parse_target.c:1262 #, c-format msgid "cross-database references are not implemented: %s" msgstr "データベース間の参照は実装されていません: %s" -#: catalog/namespace.c:3320 gram.y:19230 gram.y:19270 parser/parse_expr.c:876 parser/parse_target.c:1266 +#: catalog/namespace.c:3335 gram.y:19418 gram.y:19458 parser/parse_expr.c:873 parser/parse_target.c:1269 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "修飾名が不適切です(ドット区切りの名前が多すぎます): %s" -#: catalog/namespace.c:3450 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "一時スキーマへ、または一時スキーマからオブジェクトを移動できません" -#: catalog/namespace.c:3456 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "TOASTスキーマへ、またはTOASTスキーマからオブジェクトを移動できません" -#: catalog/namespace.c:3529 commands/schemacmds.c:264 commands/schemacmds.c:344 commands/tablecmds.c:1392 utils/adt/regproc.c:1688 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 commands/tablecmds.c:1463 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "スキーマ\"%s\"は存在しません" -#: catalog/namespace.c:3560 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "リレーション名が不適切です(ドット区切りの名前が多すぎます): %s" -#: catalog/namespace.c:4001 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "エンコーディング\"%2$s\"の照合順序\"%1$s\"は存在しません" -#: catalog/namespace.c:4056 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "変換\"%sは存在しません" -#: catalog/namespace.c:4397 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "データベース\"%s\"に一時テーブルを作成する権限がありません" -#: catalog/namespace.c:4413 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "リカバリ中は一時テーブルを作成できません" -#: catalog/namespace.c:4419 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "並行処理中は一時テーブルを作成できません" -#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2315 commands/tablecmds.c:12826 parser/parse_utilcmd.c:3249 +#: catalog/objectaddress.c:1376 commands/policy.c:93 commands/policy.c:373 commands/tablecmds.c:260 commands/tablecmds.c:302 commands/tablecmds.c:2386 commands/tablecmds.c:14460 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\"はテーブルではありません" -#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 commands/tablecmds.c:17744 commands/view.c:114 +#: catalog/objectaddress.c:1383 commands/tablecmds.c:272 commands/tablecmds.c:19546 commands/view.c:113 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\"はビューではありません" -#: catalog/objectaddress.c:1385 commands/matview.c:183 commands/tablecmds.c:275 commands/tablecmds.c:17749 +#: catalog/objectaddress.c:1390 commands/matview.c:201 commands/tablecmds.c:278 commands/tablecmds.c:19551 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\"は実体化ビューではありません" -#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 commands/tablecmds.c:17754 +#: catalog/objectaddress.c:1397 commands/tablecmds.c:296 commands/tablecmds.c:19556 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\"は外部テーブルではありません" -#: catalog/objectaddress.c:1433 +#: catalog/objectaddress.c:1438 #, c-format msgid "must specify relation and object name" msgstr "リレーションとオブジェクトの名前の指定が必要です" -#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 +#: catalog/objectaddress.c:1514 catalog/objectaddress.c:1567 #, c-format msgid "column name must be qualified" msgstr "列名を修飾する必要があります" -#: catalog/objectaddress.c:1581 +#: catalog/objectaddress.c:1586 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "リレーション\"%2$s\"の列\"%1$s\"に対するデフォルト値が存在しません" -#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 utils/adt/acl.c:4554 +#: catalog/objectaddress.c:1623 commands/functioncmds.c:132 commands/tablecmds.c:288 commands/typecmds.c:278 commands/typecmds.c:3834 parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 utils/adt/acl.c:4558 #, c-format msgid "type \"%s\" does not exist" msgstr "型\"%s\"は存在しません" -#: catalog/objectaddress.c:1737 +#: catalog/objectaddress.c:1634 +#, c-format +msgid "\"%s\" is not a domain" +msgstr "\"%s\"はドメインではありません" + +#: catalog/objectaddress.c:1742 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "%4$sの演算子 %1$d (%2$s, %3$s) がありません" -#: catalog/objectaddress.c:1768 +#: catalog/objectaddress.c:1773 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "%4$s の関数 %1$d (%2$s, %3$s) がありません" -#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 +#: catalog/objectaddress.c:1824 catalog/objectaddress.c:1850 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "ユーザー\"%s\"に対するユーザーマッピングがサーバー\"%s\"には存在しません" -#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:703 +#: catalog/objectaddress.c:1839 commands/foreigncmds.c:430 commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "サーバー\"%s\"は存在しません" -#: catalog/objectaddress.c:1901 +#: catalog/objectaddress.c:1906 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "パブリケーション\"%2$s\"にパブリケーションリレーション\"%1$s\"は存在しません" -#: catalog/objectaddress.c:1948 +#: catalog/objectaddress.c:1953 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "パブリケーション\"%2$s\"にパブリケーションスキーマ\"%1$s\"は存在しません" -#: catalog/objectaddress.c:2006 +#: catalog/objectaddress.c:2014 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "デフォルトのACLオブジェクトタイプ\"%c\"は認識できません" -#: catalog/objectaddress.c:2007 +#: catalog/objectaddress.c:2015 #, c-format -msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -msgstr "有効な値は \"%c\", \"%c\", \"%c\", \"%c\", \"%c\" です。" +msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." +msgstr "有効なオブジェクトタイプは \"%c\"、\"%c\"、\"%c\"、\"%c\"、\"%c\"、\"%c\" です。" -#: catalog/objectaddress.c:2058 +#: catalog/objectaddress.c:2067 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "ユーザー\"%s\"に対する、名前空間\"%s\"の%sへのデフォルトのACLはありません" -#: catalog/objectaddress.c:2063 +#: catalog/objectaddress.c:2072 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "ユーザー\"%s\"に対する%sへのデフォルトACLは存在しません" -#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2098 catalog/objectaddress.c:2155 catalog/objectaddress.c:2210 #, c-format msgid "name or argument lists may not contain nulls" msgstr "名前または引数のリストはnullを含むことができません" -#: catalog/objectaddress.c:2123 +#: catalog/objectaddress.c:2132 #, c-format msgid "unsupported object type \"%s\"" msgstr "サポートされないオブジェクトタイプ\"%s\"" -#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 +#: catalog/objectaddress.c:2151 catalog/objectaddress.c:2168 catalog/objectaddress.c:2233 catalog/objectaddress.c:2317 #, c-format msgid "name list length must be exactly %d" msgstr "名前リストの長さは正確に%dでなくてはなりません" -#: catalog/objectaddress.c:2163 +#: catalog/objectaddress.c:2172 #, c-format msgid "large object OID may not be null" msgstr "ラージオブジェクトのOIDはnullにはなり得ません" -#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 catalog/objectaddress.c:2249 +#: catalog/objectaddress.c:2181 catalog/objectaddress.c:2251 catalog/objectaddress.c:2258 #, c-format msgid "name list length must be at least %d" msgstr "名前リストの長さは%d以上でなくてはなりません" -#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 +#: catalog/objectaddress.c:2244 catalog/objectaddress.c:2265 #, c-format msgid "argument list length must be exactly %d" msgstr "引数リストの長さはちょうど%dである必要があります" -#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2479 libpq/be-fsstubs.c:334 #, c-format msgid "must be owner of large object %u" msgstr "ラージオブジェクト %u の所有者である必要があります" -#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 +#: catalog/objectaddress.c:2494 commands/functioncmds.c:1578 #, c-format msgid "must be owner of type %s or type %s" msgstr "型%sまたは型%sの所有者である必要があります" -#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 catalog/objectaddress.c:2527 +#: catalog/objectaddress.c:2521 catalog/objectaddress.c:2530 catalog/objectaddress.c:2536 #, c-format msgid "permission denied" msgstr "権限がありません" -#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 +#: catalog/objectaddress.c:2522 catalog/objectaddress.c:2531 #, c-format msgid "The current user must have the %s attribute." msgstr "現在のユーザーは%s属性を持つ必要があります。" -#: catalog/objectaddress.c:2528 +#: catalog/objectaddress.c:2537 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "現在のユーザーはロール\"%2$s\"に対する%1$sオプションを持っている必要があります。" -#: catalog/objectaddress.c:2542 +#: catalog/objectaddress.c:2551 #, c-format msgid "must be superuser" msgstr "スーパーユーザーである必要があります" -#: catalog/objectaddress.c:2611 +#: catalog/objectaddress.c:2620 #, c-format msgid "unrecognized object type \"%s\"" msgstr "認識されないオブジェクトタイプ\"%s\"" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2903 +#: catalog/objectaddress.c:2937 #, c-format msgid "column %s of %s" msgstr "%2$s の列 %1$s" -#: catalog/objectaddress.c:2918 +#: catalog/objectaddress.c:2952 #, c-format msgid "function %s" msgstr "関数%s" -#: catalog/objectaddress.c:2931 +#: catalog/objectaddress.c:2965 #, c-format msgid "type %s" msgstr "型%s" -#: catalog/objectaddress.c:2968 +#: catalog/objectaddress.c:3002 #, c-format msgid "cast from %s to %s" msgstr "%sから%sへの型変換" -#: catalog/objectaddress.c:3001 +#: catalog/objectaddress.c:3035 #, c-format msgid "collation %s" msgstr "照合順序%s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3032 +#: catalog/objectaddress.c:3066 #, c-format msgid "constraint %s on %s" msgstr "%2$sに対する制約%1$s" -#: catalog/objectaddress.c:3038 +#: catalog/objectaddress.c:3072 #, c-format msgid "constraint %s" msgstr "制約%s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3104 #, c-format msgid "conversion %s" msgstr "変換%s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3092 +#: catalog/objectaddress.c:3126 #, c-format msgid "default value for %s" msgstr "%s のデフォルト値" -#: catalog/objectaddress.c:3103 +#: catalog/objectaddress.c:3137 #, c-format msgid "language %s" msgstr "言語%s" -#: catalog/objectaddress.c:3111 +#: catalog/objectaddress.c:3145 #, c-format msgid "large object %u" msgstr "ラージオブジェクト%u" -#: catalog/objectaddress.c:3124 +#: catalog/objectaddress.c:3158 #, c-format msgid "operator %s" msgstr "演算子%s" -#: catalog/objectaddress.c:3161 +#: catalog/objectaddress.c:3195 #, c-format msgid "operator class %s for access method %s" msgstr "アクセスメソッド%2$s用の演算子クラス%1$s" -#: catalog/objectaddress.c:3189 +#: catalog/objectaddress.c:3223 #, c-format msgid "access method %s" msgstr "アクセスメソッド%s" @@ -5145,7 +5150,7 @@ msgstr "アクセスメソッド%s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3238 +#: catalog/objectaddress.c:3278 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "%4$sの演算子%1$d (%2$s, %3$s): %5$s" @@ -5154,236 +5159,241 @@ msgstr "%4$sの演算子%1$d (%2$s, %3$s): %5$s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3295 +#: catalog/objectaddress.c:3343 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "%4$s の関数 %1$d (%2$s, %3$s): %5$s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3347 +#: catalog/objectaddress.c:3397 #, c-format msgid "rule %s on %s" msgstr "%2$s のルール %1$s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3393 +#: catalog/objectaddress.c:3443 #, c-format msgid "trigger %s on %s" msgstr "%2$s のトリガ %1$s" -#: catalog/objectaddress.c:3413 +#: catalog/objectaddress.c:3463 #, c-format msgid "schema %s" msgstr "スキーマ%s" -#: catalog/objectaddress.c:3441 +#: catalog/objectaddress.c:3491 #, c-format msgid "statistics object %s" msgstr "統計オブジェクト%s" -#: catalog/objectaddress.c:3472 +#: catalog/objectaddress.c:3522 #, c-format msgid "text search parser %s" msgstr "テキスト検索パーサ%s" -#: catalog/objectaddress.c:3503 +#: catalog/objectaddress.c:3553 #, c-format msgid "text search dictionary %s" msgstr "テキスト検索辞書%s" -#: catalog/objectaddress.c:3534 +#: catalog/objectaddress.c:3584 #, c-format msgid "text search template %s" msgstr "テキスト検索テンプレート%s" -#: catalog/objectaddress.c:3565 +#: catalog/objectaddress.c:3615 #, c-format msgid "text search configuration %s" msgstr "テキスト検索設定%s" -#: catalog/objectaddress.c:3578 +#: catalog/objectaddress.c:3628 #, c-format msgid "role %s" msgstr "ロール%s" -#: catalog/objectaddress.c:3615 catalog/objectaddress.c:5464 +#: catalog/objectaddress.c:3665 catalog/objectaddress.c:5589 #, c-format msgid "membership of role %s in role %s" msgstr "ロール%sのロール%sへの所属" -#: catalog/objectaddress.c:3636 +#: catalog/objectaddress.c:3686 #, c-format msgid "database %s" msgstr "データベース%s" -#: catalog/objectaddress.c:3652 +#: catalog/objectaddress.c:3702 #, c-format msgid "tablespace %s" msgstr "テーブル空間%s" -#: catalog/objectaddress.c:3663 +#: catalog/objectaddress.c:3713 #, c-format msgid "foreign-data wrapper %s" msgstr "外部データラッパー%s" -#: catalog/objectaddress.c:3673 +#: catalog/objectaddress.c:3723 #, c-format msgid "server %s" msgstr "サーバー%s" -#: catalog/objectaddress.c:3706 +#: catalog/objectaddress.c:3756 #, c-format msgid "user mapping for %s on server %s" msgstr "サーバー%2$s上のユーザーマッピング%1$s" -#: catalog/objectaddress.c:3758 +#: catalog/objectaddress.c:3808 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" -msgstr "スキーマ %2$s のロール %1$s のものである新しいリレーションのデフォルト権限" +msgstr "スキーマ %2$s のロール %1$s に属する新しいリレーションのデフォルト権限" -#: catalog/objectaddress.c:3762 +#: catalog/objectaddress.c:3812 #, c-format msgid "default privileges on new relations belonging to role %s" -msgstr "新しいリレーションに関するデフォルトの権限は、ロール%sに属します。" +msgstr "ロール %s に属する新しいリレーションのデフォルト権限" -#: catalog/objectaddress.c:3768 +#: catalog/objectaddress.c:3818 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" -msgstr "スキーマ %2$s のロール %1$s のものである新しいシーケンスのデフォルト権限" +msgstr "スキーマ %2$s のロール %1$s に属する新しいシーケンスのデフォルト権限" -#: catalog/objectaddress.c:3772 +#: catalog/objectaddress.c:3822 #, c-format msgid "default privileges on new sequences belonging to role %s" -msgstr "新しいシーケンスに関するデフォルトの権限は、ロール%sに属します。" +msgstr "ロール %s に属する新しい新しいシーケンスのデフォルト権限" -#: catalog/objectaddress.c:3778 +#: catalog/objectaddress.c:3828 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" -msgstr "スキーマ %2$s のロール %1$s のものである新しい関数のデフォルト権限" +msgstr "スキーマ %2$s のロール %1$s に属する新しい関数のデフォルト権限" -#: catalog/objectaddress.c:3782 +#: catalog/objectaddress.c:3832 #, c-format msgid "default privileges on new functions belonging to role %s" -msgstr "新しい関数に関するデフォルトの権限は、ロール%sに属します。" +msgstr "ロール %s に属する新しい関数のデフォルト権限" -#: catalog/objectaddress.c:3788 +#: catalog/objectaddress.c:3838 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" -msgstr "スキーマ %2$s のロール %1$s のものである新しい型のデフォルト権限" +msgstr "スキーマ %2$s のロール %1$s に属する新しい型のデフォルト権限" -#: catalog/objectaddress.c:3792 +#: catalog/objectaddress.c:3842 #, c-format msgid "default privileges on new types belonging to role %s" -msgstr "新しい型に関するデフォルトの権限は、ロール%sに属します" +msgstr "ロール %s に属する新しい型のデフォルト権限" -#: catalog/objectaddress.c:3798 +#: catalog/objectaddress.c:3848 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "ロール%sに属する新しいスキーマ上のデフォルト権限" -#: catalog/objectaddress.c:3805 +#: catalog/objectaddress.c:3854 +#, c-format +msgid "default privileges on new large objects belonging to role %s" +msgstr "ロール %s に属する新しいラージオブジェクトのデフォルト権限" + +#: catalog/objectaddress.c:3861 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "スキーマ %2$s のロール %1$s に属するデフォルト権限" -#: catalog/objectaddress.c:3809 +#: catalog/objectaddress.c:3865 #, c-format msgid "default privileges belonging to role %s" -msgstr "デフォルトの権限はロール%sに属します。" +msgstr "ロール %s に属するデフォルト権限" -#: catalog/objectaddress.c:3831 +#: catalog/objectaddress.c:3887 #, c-format msgid "extension %s" msgstr "機能拡張%s" -#: catalog/objectaddress.c:3848 +#: catalog/objectaddress.c:3904 #, c-format msgid "event trigger %s" msgstr "イベントトリガ%s" -#: catalog/objectaddress.c:3872 +#: catalog/objectaddress.c:3928 #, c-format msgid "parameter %s" msgstr "パラメータ %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3915 +#: catalog/objectaddress.c:3971 #, c-format msgid "policy %s on %s" msgstr "%2$s のポリシ %1$s" -#: catalog/objectaddress.c:3929 +#: catalog/objectaddress.c:3985 #, c-format msgid "publication %s" msgstr "パブリケーション%s" -#: catalog/objectaddress.c:3942 +#: catalog/objectaddress.c:3998 #, c-format msgid "publication of schema %s in publication %s" msgstr "パブリケーション%2$sでのスキーマ%1$sのパブリケーション" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:3973 +#: catalog/objectaddress.c:4029 #, c-format msgid "publication of %s in publication %s" msgstr "パブリケーション %2$s での %1$s のパブリケーション" -#: catalog/objectaddress.c:3986 +#: catalog/objectaddress.c:4042 #, c-format msgid "subscription %s" msgstr "サブスクリプション%s" -#: catalog/objectaddress.c:4007 +#: catalog/objectaddress.c:4063 #, c-format msgid "transform for %s language %s" msgstr "言語%2$sの%1$s型に対する変換" -#: catalog/objectaddress.c:4076 +#: catalog/objectaddress.c:4132 #, c-format msgid "table %s" msgstr "テーブル%s" -#: catalog/objectaddress.c:4081 +#: catalog/objectaddress.c:4137 #, c-format msgid "index %s" msgstr "インデックス%s" -#: catalog/objectaddress.c:4085 +#: catalog/objectaddress.c:4141 #, c-format msgid "sequence %s" msgstr "シーケンス%s" -#: catalog/objectaddress.c:4089 +#: catalog/objectaddress.c:4145 #, c-format msgid "toast table %s" msgstr "TOASTテーブル%s" -#: catalog/objectaddress.c:4093 +#: catalog/objectaddress.c:4149 #, c-format msgid "view %s" msgstr "ビュー%s" -#: catalog/objectaddress.c:4097 +#: catalog/objectaddress.c:4153 #, c-format msgid "materialized view %s" msgstr "実体化ビュー%s" -#: catalog/objectaddress.c:4101 +#: catalog/objectaddress.c:4157 #, c-format msgid "composite type %s" msgstr "複合型%s" -#: catalog/objectaddress.c:4105 +#: catalog/objectaddress.c:4161 #, c-format msgid "foreign table %s" msgstr "外部テーブル%s" -#: catalog/objectaddress.c:4110 +#: catalog/objectaddress.c:4166 #, c-format msgid "relation %s" msgstr "リレーション%s" -#: catalog/objectaddress.c:4151 +#: catalog/objectaddress.c:4207 #, c-format msgid "operator family %s for access method %s" msgstr "アクセスメソッド%2$sの演算子族%1$s" @@ -5424,7 +5434,7 @@ msgstr "遷移関数がSTRICTかつ遷移用の型が入力型とバイナリ互 msgid "return type of inverse transition function %s is not %s" msgstr "逆遷移関数%sの戻り値の型が%sではありません" -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2992 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3057 #, c-format msgid "strictness of aggregate's forward and inverse transition functions must match" msgstr "集約の前進と反転の遷移関数のSTRICT属性は一致している必要があります" @@ -5439,7 +5449,7 @@ msgstr "追加の引数を持つ最終関数はSTRICT宣言できません" msgid "return type of combine function %s is not %s" msgstr "結合関数%sの戻り値の型が%sではありません" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:4005 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "遷移タイプ%sの結合関数はSTRICT宣言できません" @@ -5454,12 +5464,12 @@ msgstr "直列化関数%sの戻り値の型が%sではありません" msgid "return type of deserialization function %s is not %s" msgstr "復元関数%sの戻り値の型が%sではありません" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:217 catalog/pg_proc.c:251 #, c-format msgid "cannot determine result data type" msgstr "結果のデータ型を決定できません" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:230 catalog/pg_proc.c:259 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "\"internal\"疑似型の安全ではない使用" @@ -5474,48 +5484,48 @@ msgstr "移動集約の実装が%s型を返却しました、しかし普通の msgid "sort operator can only be specified for single-argument aggregates" msgstr "ソート演算子は単一引数の集約でのみ指定可能です" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 +#: catalog/pg_aggregate.c:707 catalog/pg_proc.c:412 #, c-format msgid "cannot change routine kind" msgstr "ルーチンの種別は変更できません" -#: catalog/pg_aggregate.c:708 +#: catalog/pg_aggregate.c:709 #, c-format msgid "\"%s\" is an ordinary aggregate function." msgstr "\"%s\"は通常の集約関数です。" -#: catalog/pg_aggregate.c:710 +#: catalog/pg_aggregate.c:711 #, c-format msgid "\"%s\" is an ordered-set aggregate." msgstr "\"%s\"は順序集合集約です。" -#: catalog/pg_aggregate.c:712 +#: catalog/pg_aggregate.c:713 #, c-format msgid "\"%s\" is a hypothetical-set aggregate." msgstr "\"%s\"は仮説集合集約です。" -#: catalog/pg_aggregate.c:717 +#: catalog/pg_aggregate.c:718 #, c-format msgid "cannot change number of direct arguments of an aggregate function" msgstr "集約関数の直接引数の数は変更できません" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 parser/parse_func.c:631 +#: catalog/pg_aggregate.c:859 commands/functioncmds.c:701 commands/typecmds.c:2015 commands/typecmds.c:2061 commands/typecmds.c:2113 commands/typecmds.c:2150 commands/typecmds.c:2184 commands/typecmds.c:2218 commands/typecmds.c:2252 commands/typecmds.c:2281 commands/typecmds.c:2368 commands/typecmds.c:2410 parser/parse_func.c:417 parser/parse_func.c:448 parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 parser/parse_func.c:631 #: parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "関数%sは存在しません" -#: catalog/pg_aggregate.c:864 +#: catalog/pg_aggregate.c:865 #, c-format msgid "function %s returns a set" msgstr "関数%sは集合を返します" -#: catalog/pg_aggregate.c:879 +#: catalog/pg_aggregate.c:880 #, c-format msgid "function %s must accept VARIADIC ANY to be used in this aggregate" msgstr "この集約で使うには関数%sは VARIADIC ANY を受け付ける必要があります" -#: catalog/pg_aggregate.c:903 +#: catalog/pg_aggregate.c:904 #, c-format msgid "function %s requires run-time type coercion" msgstr "関数%sは実行時の型強制が必要です" @@ -5595,21 +5605,46 @@ msgstr "照合順序\"%s\"はすでに存在します" msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "エンコーディング\"%2$s\"の照合順序\"%1$s\"はすでに存在します" -#: catalog/pg_constraint.c:732 +#: catalog/pg_constraint.c:758 commands/tablecmds.c:7951 +#, c-format +msgid "cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"" +msgstr "リレーション\"%2$s\"の非NULL制約\"%1$s\"のNO INHERIT設定は変更できません" + +#: catalog/pg_constraint.c:768 +#, c-format +msgid "incompatible NOT VALID constraint \"%s\" on relation \"%s\"" +msgstr "リレーション\"%2$s\"上の NOT VALID 制約\"%1$s\"は非互換です" + +#: catalog/pg_constraint.c:770 +#, c-format +msgid "You will need to use ALTER TABLE ... VALIDATE CONSTRAINT to validate it." +msgstr "ALTER TABLE ... VALIDATE CONSTRAINT を使用してこの制約を検証すべきです。" + +#: catalog/pg_constraint.c:1008 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "ドメイン\"%2$s\"の制約\"%1$s\"はすでに存在します" -#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 +#: catalog/pg_constraint.c:1209 catalog/pg_constraint.c:1302 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "テーブル\"%2$s\"の制約\"%1$s\"は存在しません" -#: catalog/pg_constraint.c:1125 +#: catalog/pg_constraint.c:1402 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "ドメイン\"%2$s\"に対する制約\"%1$s\"は存在しません" +#: catalog/pg_constraint.c:1656 +#, c-format +msgid "invalid type for PERIOD part of foreign key" +msgstr "外部キーのPERIOD部に対して不正な型" + +#: catalog/pg_constraint.c:1657 +#, c-format +msgid "Only range and multirange are supported." +msgstr "範囲型および副範囲型のみがサポートされます。" + #: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" @@ -5620,27 +5655,27 @@ msgstr "変換\"%s\"はすでに存在します" msgid "default conversion for %s to %s already exists" msgstr "%sから%sへのデフォルトの変換はすでに存在します" -#: catalog/pg_depend.c:224 commands/extension.c:3397 +#: catalog/pg_depend.c:223 commands/extension.c:3665 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "%sはすでに機能拡張\"%s\"のメンバです" -#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 +#: catalog/pg_depend.c:230 catalog/pg_depend.c:281 commands/extension.c:3705 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "%s は機能拡張\"%s\"のメンバではありません" -#: catalog/pg_depend.c:234 +#: catalog/pg_depend.c:233 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "機能拡張は自身が所有していないオブジェクトを置き換えることができません。" -#: catalog/pg_depend.c:285 +#: catalog/pg_depend.c:284 #, c-format msgid "An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns." msgstr "機能拡張はCREATE ... IF NOT EXISTSを自身がすでに所有しているオブジェクトと競合するオブジェクトの生成をスキップするためにのみ使用することができます。" -#: catalog/pg_depend.c:648 +#: catalog/pg_depend.c:647 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "システムオブジェクトであるため、%sの依存関係を削除できません。" @@ -5690,7 +5725,7 @@ msgstr "パーティション\"%s\"を取り外せません" msgid "The partition is being detached concurrently or has an unfinished detach." msgstr "このパーティションは今現在取り外し中であるか取り外し処理が未完了の状態です。" -#: catalog/pg_inherits.c:595 commands/tablecmds.c:4778 commands/tablecmds.c:16053 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4915 commands/tablecmds.c:17793 #, c-format msgid "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation." msgstr "ALTER TABLE ... DETACH PARTITION ... FINALIZE を実行して保留中の取り外し処理を完了させてください。" @@ -5795,43 +5830,43 @@ msgstr "否定演算子 %s はすでに演算子 %u の否定子です" msgid "parameter ACL \"%s\" does not exist" msgstr "パラメータACL \"%s\"は存在しません" -#: catalog/pg_proc.c:130 parser/parse_func.c:2234 +#: catalog/pg_proc.c:158 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" msgstr[0] "関数は%dを超える引数を取ることができません" -#: catalog/pg_proc.c:374 +#: catalog/pg_proc.c:402 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "同じ引数型を持つ関数\"%s\"はすでに存在します" -#: catalog/pg_proc.c:386 +#: catalog/pg_proc.c:414 #, c-format msgid "\"%s\" is an aggregate function." msgstr "\"%s\"は集約関数です。" -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:416 #, c-format msgid "\"%s\" is a function." msgstr "\"%s\"は関数です。" -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:418 #, c-format msgid "\"%s\" is a procedure." msgstr "\"%s\"はプロシージャです。" -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:420 #, c-format msgid "\"%s\" is a window function." msgstr "関数\"%s\"はウィンドウ関数です。" -#: catalog/pg_proc.c:412 +#: catalog/pg_proc.c:440 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "プロシージャの出力パラメータの有無は変更できません" -#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 +#: catalog/pg_proc.c:441 catalog/pg_proc.c:471 #, c-format msgid "cannot change return type of existing function" msgstr "既存の関数の戻り値型を変更できません" @@ -5840,112 +5875,112 @@ msgstr "既存の関数の戻り値型を変更できません" #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 catalog/pg_proc.c:517 catalog/pg_proc.c:541 +#: catalog/pg_proc.c:447 catalog/pg_proc.c:474 catalog/pg_proc.c:519 catalog/pg_proc.c:545 catalog/pg_proc.c:569 #, c-format msgid "Use %s %s first." msgstr "まず %s %s を使用してください。" -#: catalog/pg_proc.c:444 +#: catalog/pg_proc.c:472 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "OUTパラメータで定義された行型が異なります。" -#: catalog/pg_proc.c:488 +#: catalog/pg_proc.c:516 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "入力パラメーター\"%s\"の名称を変更できません" -#: catalog/pg_proc.c:515 +#: catalog/pg_proc.c:543 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "既存の関数からパラメータのデフォルト値を削除できません" -#: catalog/pg_proc.c:539 +#: catalog/pg_proc.c:567 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "既存のパラメータのデフォルト値のデータ型を変更できません" -#: catalog/pg_proc.c:750 +#: catalog/pg_proc.c:771 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "\"%s\"という名前の組み込み関数はありません" -#: catalog/pg_proc.c:843 +#: catalog/pg_proc.c:864 #, c-format msgid "SQL functions cannot return type %s" msgstr "SQL関数は型%sを返すことができません" -#: catalog/pg_proc.c:858 +#: catalog/pg_proc.c:879 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "SQL関数は型%sの引数と取ることができません" -#: catalog/pg_proc.c:986 executor/functions.c:1467 +#: catalog/pg_proc.c:1007 #, c-format msgid "SQL function \"%s\"" msgstr "SQL関数\"%s\"" -#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 catalog/pg_publication.c:82 catalog/pg_publication.c:88 +#: catalog/pg_publication.c:63 catalog/pg_publication.c:71 catalog/pg_publication.c:79 catalog/pg_publication.c:85 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "パブリケーションにリレーション\"%s\"を追加できません" -#: catalog/pg_publication.c:76 +#: catalog/pg_publication.c:73 #, c-format msgid "This operation is not supported for system tables." msgstr "この操作はシステムテーブルに対してはサポートされていません。" -#: catalog/pg_publication.c:84 +#: catalog/pg_publication.c:81 #, c-format msgid "This operation is not supported for temporary tables." msgstr "この操作は一時テーブルに対してはサポートされていません。" -#: catalog/pg_publication.c:90 +#: catalog/pg_publication.c:87 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "この操作はUNLOGGEDテーブルに対してはサポートされていません。" -#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 +#: catalog/pg_publication.c:101 catalog/pg_publication.c:109 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "パブリケーションにスキーマ\"%s\"を追加できません" -#: catalog/pg_publication.c:106 +#: catalog/pg_publication.c:103 #, c-format msgid "This operation is not supported for system schemas." msgstr "この操作はシステムスキーマに対してはサポートされていません。" -#: catalog/pg_publication.c:114 +#: catalog/pg_publication.c:111 #, c-format msgid "Temporary schemas cannot be replicated." msgstr "一時スキーマは複製できません" -#: catalog/pg_publication.c:392 +#: catalog/pg_publication.c:462 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "リレーション\"%s\"はすでにパブリケーション\"%s\"のメンバです" -#: catalog/pg_publication.c:534 +#: catalog/pg_publication.c:576 #, c-format msgid "cannot use system column \"%s\" in publication column list" msgstr "システム列\"%s\"はパブリケーション列リスト内では使用できません" -#: catalog/pg_publication.c:540 +#: catalog/pg_publication.c:582 #, c-format -msgid "cannot use generated column \"%s\" in publication column list" -msgstr "生成列\"%s\"はパブリケーション列リスト内では使用できません" +msgid "cannot use virtual generated column \"%s\" in publication column list" +msgstr "仮想生成列\"%s\"はパブリケーションの列リストでは使用できません" -#: catalog/pg_publication.c:546 +#: catalog/pg_publication.c:588 #, c-format msgid "duplicate column \"%s\" in publication column list" msgstr "パブリケーション列リスト内に重複した列 \"%s\"" -#: catalog/pg_publication.c:636 +#: catalog/pg_publication.c:700 #, c-format msgid "schema \"%s\" is already member of publication \"%s\"" msgstr "スキーマ\"%s\"はすでにパブリケーション\"%s\"のメンバです" -#: catalog/pg_shdepend.c:867 +#: catalog/pg_shdepend.c:875 #, c-format msgid "" "\n" @@ -5957,69 +5992,69 @@ msgstr[0] "" "\n" "および、他の%dのデータベース内のオブジェクト(一覧についてはサーバーログを参照してください)" -#: catalog/pg_shdepend.c:1214 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "ロール%uの削除が同時に行われました" -#: catalog/pg_shdepend.c:1226 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "テーブル空間%uの削除が同時に行われました" -#: catalog/pg_shdepend.c:1240 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "データベース%uの削除が同時に行われました" -#: catalog/pg_shdepend.c:1291 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "%sの所有者" -#: catalog/pg_shdepend.c:1293 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" msgstr "%sの権限" -#: catalog/pg_shdepend.c:1295 +#: catalog/pg_shdepend.c:1303 #, c-format msgid "initial privileges for %s" msgstr "%sの初期権限" -#: catalog/pg_shdepend.c:1297 +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "%sの対象" -#: catalog/pg_shdepend.c:1299 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "%sのテーブル空間" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1307 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" msgstr[0] "%2$s内の%1$d個のオブジェクト" -#: catalog/pg_shdepend.c:1371 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "cannot drop objects owned by %s because they are required by the database system" msgstr "データベースシステムが必要としているため%sが所有するオブジェクトを削除できません" -#: catalog/pg_shdepend.c:1545 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "cannot reassign ownership of objects owned by %s because they are required by the database system" msgstr "データベースシステムが必要としているため%sが所有するオブジェクトの所有者を再割り当てできません" -#: catalog/pg_subscription.c:438 +#: catalog/pg_subscription.c:469 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "サブスクリプション\"%s\"に対するリレーションマッピングを削除できませんでした" -#: catalog/pg_subscription.c:440 +#: catalog/pg_subscription.c:471 #, c-format msgid "Table synchronization for relation \"%s\" is in progress and is in state \"%c\"." msgstr "リレーション\\\"%s\\\"のテーブル同期が進行中で、状態は\\\"%c\\\"です。" @@ -6027,7 +6062,7 @@ msgstr "リレーション\\\"%s\\\"のテーブル同期が進行中で、状 #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:447 +#: catalog/pg_subscription.c:478 #, c-format msgid "Use %s to enable subscription if not already enabled or use %s to drop the subscription." msgstr "サブスクリプションが有効にされていない場合は%sを実行して有効化するか、%sを実行してこのサブスクリプションを削除してください。" @@ -6057,7 +6092,7 @@ msgstr "値渡し型の場合、内部サイズ%dは不正です" msgid "alignment \"%c\" is invalid for variable-length type" msgstr "可変長型の場合、アラインメント\"%c\"は不正です" -#: catalog/pg_type.c:325 commands/typecmds.c:4363 +#: catalog/pg_type.c:325 commands/typecmds.c:4354 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "固定長型の場合はPLAIN格納方式でなければなりません" @@ -6072,7 +6107,7 @@ msgstr "\"%s\"の複範囲型の作成中に失敗しました。" msgid "You can manually specify a multirange type name using the \"multirange_type_name\" attribute." msgstr "\"multirange_type_name\"属性で複範囲型の型名を手動で指定することができます。" -#: catalog/storage.c:508 storage/buffer/bufmgr.c:1540 +#: catalog/storage.c:549 storage/buffer/bufmgr.c:7269 #, c-format msgid "invalid page in block %u of relation %s" msgstr "リレーション%2$sのブロック%1$uに不正なページ" @@ -6157,7 +6192,7 @@ msgstr "直列化関数は集約遷移データの型が%sの場合にだけ指 msgid "must specify both or neither of serialization and deserialization functions" msgstr "直列化関数と復元関数は両方指定するか、両方指定しないかのどちらかである必要があります" -#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:649 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "パラメータ\"parallel\"はSAVE、RESTRICTEDまたはUNSAFEのいずれかでなければなりません" @@ -6167,82 +6202,82 @@ msgstr "パラメータ\"parallel\"はSAVE、RESTRICTEDまたはUNSAFEのいず msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "パラメータ\"%s\"は READ_ONLY、SHAREABLE または READ_WRITE でなくてはなりません" -#: commands/alter.c:82 commands/event_trigger.c:191 +#: commands/alter.c:83 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" msgstr "イベントトリガ\"%s\"はすでに存在します" -#: commands/alter.c:85 commands/foreigncmds.c:593 +#: commands/alter.c:86 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "外部データラッパー\"%s\"はすでに存在します" -#: commands/alter.c:88 commands/foreigncmds.c:884 +#: commands/alter.c:89 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "サーバー\"%s\"はすでに存在します" -#: commands/alter.c:91 commands/proclang.c:131 +#: commands/alter.c:92 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "言語\"%s\"はすでに存在します" -#: commands/alter.c:94 commands/publicationcmds.c:764 +#: commands/alter.c:95 commands/publicationcmds.c:865 #, c-format msgid "publication \"%s\" already exists" msgstr "パブリケーション\"%s\"はすでに存在します" -#: commands/alter.c:97 commands/subscriptioncmds.c:669 +#: commands/alter.c:98 commands/subscriptioncmds.c:629 #, c-format msgid "subscription \"%s\" already exists" msgstr "サブスクリプション\"%s\"はすでに存在します" -#: commands/alter.c:120 +#: commands/alter.c:121 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "変換\"%s\"はスキーマ\"%s\"内にすでに存在します" -#: commands/alter.c:124 +#: commands/alter.c:125 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "統計情報オブジェクト\"%s\"はスキーマ\"%s\"内にすでに存在します" -#: commands/alter.c:128 +#: commands/alter.c:129 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "テキスト検索パーサ\"%s\"はすでにスキーマ\"%s\"存在します" -#: commands/alter.c:132 +#: commands/alter.c:133 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "テキスト検索辞書\"%s\"はすでにスキーマ\"%s\"存在します" -#: commands/alter.c:136 +#: commands/alter.c:137 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "テキスト検索テンプレート\"%s\"はすでにスキーマ\"%s\"存在します" -#: commands/alter.c:140 +#: commands/alter.c:141 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "テキスト検索設定\"%s\"はすでにスキーマ\"%s\"存在します" -#: commands/alter.c:213 +#: commands/alter.c:214 #, c-format msgid "must be superuser to rename %s" msgstr "%sの名前を変更するにはスーパーユーザーである必要があります" -#: commands/alter.c:255 commands/subscriptioncmds.c:648 commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 commands/subscriptioncmds.c:1918 +#: commands/alter.c:256 commands/subscriptioncmds.c:608 commands/subscriptioncmds.c:1147 commands/subscriptioncmds.c:1231 commands/subscriptioncmds.c:1989 #, c-format msgid "password_required=false is superuser-only" msgstr "password_required=falseはスーパーユーザーのみ可能です" -#: commands/alter.c:256 commands/subscriptioncmds.c:649 commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 commands/subscriptioncmds.c:1919 +#: commands/alter.c:257 commands/subscriptioncmds.c:609 commands/subscriptioncmds.c:1148 commands/subscriptioncmds.c:1232 commands/subscriptioncmds.c:1990 #, c-format msgid "Subscriptions with the password_required option set to false may only be created or modified by the superuser." msgstr "password_requiredオプションがfalseに設定されたサブスクリプションはスーパーユーザのみ作成と変更が可能です。" -#: commands/alter.c:734 +#: commands/alter.c:746 #, c-format msgid "must be superuser to set schema of %s" msgstr "%sのスキーマを設定するにはスーパーユーザーである必要があります" @@ -6262,7 +6297,7 @@ msgstr "アクセスメソッドを作成するにはスーパーユーザーで msgid "access method \"%s\" already exists" msgstr "アクセスメソッド\"%s\"は存在しません" -#: commands/amcmds.c:154 commands/indexcmds.c:221 commands/indexcmds.c:841 commands/opclasscmds.c:374 commands/opclasscmds.c:832 +#: commands/amcmds.c:154 commands/indexcmds.c:226 commands/indexcmds.c:859 commands/opclasscmds.c:375 commands/opclasscmds.c:833 #, c-format msgid "access method \"%s\" does not exist" msgstr "アクセスメソッド\"%s\"は存在しません" @@ -6272,52 +6307,57 @@ msgstr "アクセスメソッド\"%s\"は存在しません" msgid "handler function is not specified" msgstr "ハンドラ関数の指定がありません" -#: commands/amcmds.c:264 commands/event_trigger.c:200 commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 parser/parse_clause.c:943 +#: commands/amcmds.c:264 commands/event_trigger.c:200 commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:705 parser/parse_clause.c:941 #, c-format msgid "function %s must return type %s" msgstr "関数%sは型%sを返さなければなりません" -#: commands/analyze.c:217 +#: commands/analyze.c:215 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "\"%s\"をスキップしています --- この外部テーブルに対してANALYZEを実行することはできません" -#: commands/analyze.c:234 +#: commands/analyze.c:232 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "\"%s\"をスキップしています --- テーブルでないものや特別なシステムテーブルに対してANALYZEを実行することはできません" -#: commands/analyze.c:314 +#: commands/analyze.c:317 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "\"%s.%s\"継承ツリーを解析しています" -#: commands/analyze.c:319 +#: commands/analyze.c:322 #, c-format msgid "analyzing \"%s.%s\"" msgstr "\"%s.%s\"を解析しています" -#: commands/analyze.c:385 +#: commands/analyze.c:393 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "リレーション\"%2$s\"の列\"%1$s\"が2回以上現れます" -#: commands/analyze.c:780 +#: commands/analyze.c:803 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "テーブル\"%s.%s.%s\"に対する自動ANALYZE\n" -#: commands/analyze.c:1295 +#: commands/analyze.c:805 +#, c-format +msgid "finished analyzing table \"%s.%s.%s\"\n" +msgstr "テーブル\"%s.%s.%s\"の解析完了\n" + +#: commands/analyze.c:1346 #, c-format msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows" msgstr "\"%1$s\": %3$uページの内%2$dをスキャン。%4$.0fの有効な行と%5$.0fの不要な行が存在。%6$d行をサンプリング。推定総行数は%7$.0f" -#: commands/analyze.c:1379 +#: commands/analyze.c:1430 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables" msgstr "継承ツリー\"%s.%s\"のANALYZEをスキップします --- このツリーには子テーブルがありません" -#: commands/analyze.c:1477 +#: commands/analyze.c:1528 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables" msgstr "継承ツリー\"%s.%s\"のANALYZEをスキップします --- このツリーにはアナライズ可能な子テーブルがありません" @@ -6362,82 +6402,82 @@ msgstr "PID %d のサーバープロセスは、この中で最も古いトラ msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction." msgstr "このプロセスが現在のトランザクションを終了するまで NOTYFY キューを空にすることはできません" -#: commands/cluster.c:128 +#: commands/cluster.c:127 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "認識できないCLUSTERオプション \"%s\"" -#: commands/cluster.c:159 commands/cluster.c:433 +#: commands/cluster.c:158 commands/cluster.c:421 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "他のセッションの一時テーブルをクラスタ化できません" -#: commands/cluster.c:177 +#: commands/cluster.c:176 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "テーブル\"%s\"には事前にクラスタ化されたインデックスはありません" -#: commands/cluster.c:191 commands/tablecmds.c:14698 commands/tablecmds.c:16629 +#: commands/cluster.c:190 commands/tablecmds.c:16349 commands/tablecmds.c:18415 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "テーブル\"%2$s\"にはインデックス\"%1$s\"は存在しません" -#: commands/cluster.c:422 +#: commands/cluster.c:410 #, c-format msgid "cannot cluster a shared catalog" msgstr "共有カタログをクラスタ化できません" -#: commands/cluster.c:437 +#: commands/cluster.c:425 #, c-format msgid "cannot vacuum temporary tables of other sessions" msgstr "他のセッションの一時テーブルに対してはVACUUMを実行できません" -#: commands/cluster.c:513 commands/tablecmds.c:16639 +#: commands/cluster.c:507 commands/tablecmds.c:18425 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "\"%s\"はテーブル\"%s\"のインデックスではありません" -#: commands/cluster.c:521 +#: commands/cluster.c:515 #, c-format msgid "cannot cluster on index \"%s\" because access method does not support clustering" msgstr "インデックス\"%s\"でクラスタ化できません。アクセスメソッドがクラスタ化をサポートしないためです" -#: commands/cluster.c:533 +#: commands/cluster.c:527 #, c-format msgid "cannot cluster on partial index \"%s\"" msgstr "部分インデックス\"%s\"をクラスタ化できません" -#: commands/cluster.c:547 +#: commands/cluster.c:541 #, c-format msgid "cannot cluster on invalid index \"%s\"" msgstr "無効なインデックス\"%s\"ではクラスタ化できません" -#: commands/cluster.c:571 +#: commands/cluster.c:565 #, c-format msgid "cannot mark index clustered in partitioned table" msgstr "パーティションテーブル内のインデックスは CLUSTER 済みとマークできません`" -#: commands/cluster.c:956 +#: commands/cluster.c:961 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr "\"%3$s\"に対するインデックススキャンを使って\"%1$s.%2$s\"をクラスタ化しています" -#: commands/cluster.c:962 +#: commands/cluster.c:967 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "シーケンシャルスキャンとソートを使って\"%s.%s\"をクラスタ化しています" -#: commands/cluster.c:967 +#: commands/cluster.c:972 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "\"%s.%s\"に対してVACUUMを実行しています" -#: commands/cluster.c:994 +#: commands/cluster.c:999 #, c-format msgid "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" msgstr "\"%1$s.%2$s\": %5$u ページ中に見つかった行バージョン: 移動可能 %3$.0f 行、削除不可 %4$.0f 行" -#: commands/cluster.c:999 +#: commands/cluster.c:1004 #, c-format msgid "" "%.0f dead row versions cannot be removed yet.\n" @@ -6446,7 +6486,7 @@ msgstr "" "%.0f 個の無効な行が今はまだ削除できません。\n" "%s." -#: commands/cluster.c:1744 +#: commands/cluster.c:1751 #, c-format msgid "permission denied to cluster \"%s\", skipping it" msgstr "\"%s\"のクラスタ化を行う権限がありません、スキップします" @@ -6456,8 +6496,8 @@ msgstr "\"%s\"のクラスタ化を行う権限がありません、スキップ msgid "collation attribute \"%s\" not recognized" msgstr "照合順序の属性\"%s\"が認識できません" -#: commands/collationcmds.c:123 commands/collationcmds.c:129 commands/define.c:388 commands/tablecmds.c:8137 replication/pgoutput/pgoutput.c:307 replication/pgoutput/pgoutput.c:330 replication/pgoutput/pgoutput.c:344 replication/pgoutput/pgoutput.c:354 replication/pgoutput/pgoutput.c:364 replication/pgoutput/pgoutput.c:374 replication/pgoutput/pgoutput.c:386 replication/walsender.c:1146 replication/walsender.c:1168 replication/walsender.c:1178 -#: replication/walsender.c:1187 replication/walsender.c:1426 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 commands/define.c:375 commands/tablecmds.c:8368 replication/pgoutput/pgoutput.c:320 replication/pgoutput/pgoutput.c:343 replication/pgoutput/pgoutput.c:357 replication/pgoutput/pgoutput.c:367 replication/pgoutput/pgoutput.c:377 replication/pgoutput/pgoutput.c:387 replication/pgoutput/pgoutput.c:399 replication/walsender.c:1123 replication/walsender.c:1145 replication/walsender.c:1155 +#: replication/walsender.c:1164 replication/walsender.c:1406 replication/walsender.c:1415 #, c-format msgid "conflicting or redundant options" msgstr "競合するオプション、あるいは余計なオプションがあります" @@ -6489,7 +6529,7 @@ msgstr "認識できないの照合順序プロバイダ: %s" msgid "parameter \"%s\" must be specified" msgstr "パラメータ\"%s\"の指定が必要です" -#: commands/collationcmds.c:293 commands/dbcommands.c:1134 +#: commands/collationcmds.c:293 commands/dbcommands.c:1148 #, c-format msgid "using standard form \"%s\" for ICU locale \"%s\"" msgstr "ICUロケール\"%s\"の標準形式\"%s\"を使用します" @@ -6499,7 +6539,7 @@ msgstr "ICUロケール\"%s\"の標準形式\"%s\"を使用します" msgid "nondeterministic collations not supported with this provider" msgstr "非決定的照合順序はこのプロバイダではサポートされません" -#: commands/collationcmds.c:317 commands/dbcommands.c:1087 +#: commands/collationcmds.c:317 commands/dbcommands.c:1101 #, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" msgstr "ICUルールはロケールプロバイダがICUでなければ指定できません" @@ -6509,59 +6549,59 @@ msgstr "ICUルールはロケールプロバイダがICUでなければ指定で msgid "current database's encoding is not supported with this provider" msgstr "現在のデータベースのエンコーディングはこのプロバイダではサポートされません" -#: commands/collationcmds.c:409 +#: commands/collationcmds.c:405 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "エンコーディング\"%2$s\"のための照合順序\"%1$s\"はすでにスキーマ\"%3$s\"内に存在します" -#: commands/collationcmds.c:420 +#: commands/collationcmds.c:416 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "照合順序\"%s\"はすでにスキーマ\"%s\"内に存在します" -#: commands/collationcmds.c:445 +#: commands/collationcmds.c:441 #, c-format msgid "cannot refresh version of default collation" msgstr "デフォルト照合順序のバーションはリフレッシュできません" #. translator: %s is an SQL command #. translator: %s is an SQL ALTER command -#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 commands/tablecmds.c:7913 commands/tablecmds.c:7923 commands/tablecmds.c:7925 commands/tablecmds.c:14400 commands/tablecmds.c:17777 commands/tablecmds.c:17798 commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 +#: commands/collationcmds.c:443 commands/subscriptioncmds.c:1445 commands/tablecmds.c:8145 commands/tablecmds.c:8155 commands/tablecmds.c:8157 commands/tablecmds.c:16051 commands/tablecmds.c:19579 commands/tablecmds.c:19600 commands/typecmds.c:3778 commands/typecmds.c:3863 commands/typecmds.c:4217 #, c-format msgid "Use %s instead." msgstr "代わりに%sを使用してください" -#: commands/collationcmds.c:480 commands/dbcommands.c:2550 +#: commands/collationcmds.c:476 commands/dbcommands.c:2580 #, c-format msgid "changing version from %s to %s" msgstr "バージョン%sから%sへの変更" -#: commands/collationcmds.c:495 commands/dbcommands.c:2563 +#: commands/collationcmds.c:491 commands/dbcommands.c:2593 #, c-format msgid "version has not changed" msgstr "バージョンが変わっていません" -#: commands/collationcmds.c:528 commands/dbcommands.c:2729 +#: commands/collationcmds.c:524 commands/dbcommands.c:2763 utils/adt/dbsize.c:180 #, c-format msgid "database with OID %u does not exist" msgstr "OID %uのデータベースは存在しません" -#: commands/collationcmds.c:554 +#: commands/collationcmds.c:550 #, c-format msgid "collation with OID %u does not exist" msgstr "OID %uの照合順序は存在しません" -#: commands/collationcmds.c:848 +#: commands/collationcmds.c:844 #, c-format msgid "must be superuser to import system collations" msgstr "システム照合順序をインポートするにはスーパーユーザーである必要があります" -#: commands/collationcmds.c:968 commands/collationcmds.c:1053 +#: commands/collationcmds.c:964 commands/collationcmds.c:1049 #, c-format msgid "no usable system locales were found" msgstr "使用できるシステムロケールが見つかりません" -#: commands/comment.c:61 commands/dbcommands.c:1663 commands/dbcommands.c:1875 commands/dbcommands.c:1985 commands/dbcommands.c:2183 commands/dbcommands.c:2421 commands/dbcommands.c:2512 commands/dbcommands.c:2633 commands/dbcommands.c:3141 utils/init/postinit.c:1033 utils/init/postinit.c:1097 utils/init/postinit.c:1170 +#: commands/comment.c:61 commands/dbcommands.c:1679 commands/dbcommands.c:1897 commands/dbcommands.c:2009 commands/dbcommands.c:2207 commands/dbcommands.c:2447 commands/dbcommands.c:2540 commands/dbcommands.c:2664 commands/dbcommands.c:3175 utils/init/postinit.c:1027 utils/init/postinit.c:1091 utils/init/postinit.c:1164 #, c-format msgid "database \"%s\" does not exist" msgstr "データベース\"%s\"は存在しません" @@ -6571,12 +6611,12 @@ msgstr "データベース\"%s\"は存在しません" msgid "cannot set comment on relation \"%s\"" msgstr "リレーション\"%s\"にはコメントを設定できません" -#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2175 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "関数\"%s\"はトリガ関数として呼び出されていません" -#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2184 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "関数\"%s\"はAFTER ROWトリガで実行してください" @@ -6666,308 +6706,264 @@ msgstr "COPY TO の HEADERで\"%s\"は使用できません" msgid "%s requires a Boolean value or \"match\"" msgstr "パラメータ\"%s\"はBoolean値または\"match\"のみを取ります" -#: commands/copy.c:400 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:818 commands/copy.c:834 commands/copy.c:851 commands/copy.c:877 commands/copy.c:887 #, c-format -msgid "COPY ON_ERROR cannot be used with COPY TO" -msgstr "COPY ONJ_ERROR は COPY TO では使用できません" +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s は %s と同時には使えません" -#: commands/copy.c:413 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:474 #, c-format -msgid "COPY ON_ERROR \"%s\" not recognized" -msgstr "COPY ON_ERROR \"%s\"を認識できません" +msgid "COPY %s \"%s\" not recognized" +msgstr "COPY %s \"%s\"を認識できません" + +#: commands/copy.c:436 commands/define.c:73 commands/define.c:84 commands/define.c:178 commands/define.c:196 commands/define.c:211 commands/define.c:229 +#, c-format +msgid "%s requires a numeric value" +msgstr "%sは数値が必要です" -#: commands/copy.c:437 +#: commands/copy.c:446 #, c-format -msgid "COPY LOG_VERBOSITY \"%s\" not recognized" -msgstr "COPY LOG_VERBOSITY \"%s\"を認識できません" +msgid "REJECT_LIMIT (%) must be greater than zero" +msgstr "REJECT_LIMIT (%)は0より大きくなければなりません" -#: commands/copy.c:498 +#: commands/copy.c:536 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "COPY フォーマット\"%s\"を認識できません" -#: commands/copy.c:556 commands/copy.c:571 commands/copy.c:586 commands/copy.c:605 +#: commands/copy.c:594 commands/copy.c:609 commands/copy.c:624 commands/copy.c:643 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "オプション\"%s\"の引数は列名のリストでなければなりません" -#: commands/copy.c:617 +#: commands/copy.c:655 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "オプション\"%s\"の引数は有効なエンコーディング名でなければなりません" -#: commands/copy.c:638 commands/dbcommands.c:866 commands/dbcommands.c:2369 +#: commands/copy.c:683 commands/dbcommands.c:880 commands/dbcommands.c:2395 #, c-format msgid "option \"%s\" not recognized" msgstr "タイムゾーン\"%s\"を認識できません" -#: commands/copy.c:650 -#, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "BINARYモードではDELIMITERを指定できません" - -#: commands/copy.c:655 -#, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "BINARYモードではNULLを指定できません" - -#: commands/copy.c:660 -#, c-format -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "BINARYモードではDEFAULTを指定できません" - -#: commands/copy.c:665 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:696 commands/copy.c:701 commands/copy.c:706 commands/copy.c:776 #, c-format -msgid "only ON_ERROR STOP is allowed in BINARY mode" -msgstr "BINARYモードではN_ERROR STOPのみ使用可能です" +msgid "cannot specify %s in BINARY mode" +msgstr "BINARYモードでは%sを指定できません" -#: commands/copy.c:687 +#: commands/copy.c:728 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "COPYの区切り文字は単一の1バイト文字でなければなりません" -#: commands/copy.c:694 +#: commands/copy.c:735 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "COPYの区切り文字は改行や復帰記号とすることができません" -#: commands/copy.c:700 +#: commands/copy.c:741 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "COPYのNULL表現には改行や復帰記号を使用することはできません" -#: commands/copy.c:710 +#: commands/copy.c:751 #, c-format msgid "COPY default representation cannot use newline or carriage return" msgstr "COPYのデフォルト表現には改行や復帰記号を使用することはできません" -#: commands/copy.c:728 +#: commands/copy.c:769 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "COPYの区切り文字を\"%s\"とすることはできません" -#: commands/copy.c:734 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:783 commands/copy.c:800 commands/copy.c:812 commands/copy.c:827 commands/copy.c:843 #, c-format -msgid "cannot specify HEADER in BINARY mode" -msgstr "BINARYモードではHEADERを指定できません" +msgid "COPY %s requires CSV mode" +msgstr "COPY %s はCSVモードを要求します" -#: commands/copy.c:740 -#, c-format -msgid "COPY QUOTE requires CSV mode" -msgstr "COPY QUOTE はCSVモードでのみ指定できます" - -#: commands/copy.c:745 +#: commands/copy.c:788 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "COPYの引用符は単一の1バイト文字でなければなりません" -#: commands/copy.c:750 +#: commands/copy.c:793 #, c-format msgid "COPY delimiter and quote must be different" msgstr "COPYの区切り文字と引用符は異なる文字でなければなりません" -#: commands/copy.c:756 -#, c-format -msgid "COPY ESCAPE requires CSV mode" -msgstr "COPY ESCAPE はCSVモードでのみ指定できます" - -#: commands/copy.c:761 +#: commands/copy.c:805 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "COPYのエスケープは単一の1バイト文字でなければなりません" -#: commands/copy.c:767 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:859 commands/copy.c:895 #, c-format -msgid "COPY FORCE_QUOTE requires CSV mode" -msgstr "COPY FORCE_QUOTE はCSVモードでのみ指定できます" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "COPYの区切り文字は%s指定では使用できません" -#: commands/copy.c:771 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:868 commands/copy.c:904 #, c-format -msgid "COPY FORCE_QUOTE cannot be used with COPY FROM" -msgstr "COPY FORCE_QUOTE は COPY FROM では使用できません" +msgid "CSV quote character must not appear in the %s specification" +msgstr "COPYの引用符は%s指定では使用できません" -#: commands/copy.c:777 +#: commands/copy.c:913 #, c-format -msgid "COPY FORCE_NOT_NULL requires CSV mode" -msgstr "CCOPY FORCE_NOT_NULL はCSVモードでのみ指定できます" +msgid "NULL specification and DEFAULT specification cannot be the same" +msgstr "NULL指定とDEFAULT指定は同じにはできません" -#: commands/copy.c:781 +#: commands/copy.c:919 #, c-format -msgid "COPY FORCE_NOT_NULL cannot be used with COPY TO" -msgstr "COPY FORCE_NOT_NULL は COPY TO では使用できません" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "BINARYモードではN_ERROR STOPのみ使用可能です" -#: commands/copy.c:787 +#. translator: first and second %s are the names of COPY option, e.g. +#. * ON_ERROR, third is the value of the COPY option, e.g. IGNORE +#: commands/copy.c:926 #, c-format -msgid "COPY FORCE_NULL requires CSV mode" -msgstr "COPY FORCE_NULL はCSVモードでのみ指定できます" +msgid "COPY %s requires %s to be set to %s" +msgstr "COPY %s では %s が %s に設定されている必要があります" -#: commands/copy.c:792 +#: commands/copy.c:988 #, c-format -msgid "COPY FORCE_NULL cannot be used with COPY TO" -msgstr "CCOPY FORCE_NULL は COPY TO では使用できません" +msgid "column \"%s\" is a generated column" +msgstr "列\"%s\"は生成カラムです" -#: commands/copy.c:798 +#: commands/copy.c:990 #, c-format -msgid "COPY delimiter character must not appear in the NULL specification" -msgstr "COPYの区切り文字はNULL指定では使用できません" +msgid "Generated columns cannot be used in COPY." +msgstr "生成カラムはCOPYでは使えません。" -#: commands/copy.c:805 +#: commands/copy.c:1005 commands/indexcmds.c:1959 commands/statscmds.c:239 commands/tablecmds.c:2592 commands/tablecmds.c:3100 commands/tablecmds.c:3929 parser/parse_relation.c:3798 parser/parse_relation.c:3808 parser/parse_relation.c:3826 parser/parse_relation.c:3833 parser/parse_relation.c:3847 utils/adt/tsvector_op.c:2853 #, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "COPYの引用符はNULL指定では使用できません" +msgid "column \"%s\" does not exist" +msgstr "列\"%s\"は存在しません" -#: commands/copy.c:811 +#: commands/copy.c:1012 commands/tablecmds.c:2618 commands/trigger.c:956 parser/parse_target.c:1086 parser/parse_target.c:1097 #, c-format -msgid "COPY FREEZE cannot be used with COPY TO" -msgstr "COPY FREEZE は COPY TO では使用できません" +msgid "column \"%s\" specified more than once" +msgstr "列\"%s\"が複数指定されました" -#: commands/copy.c:818 +#: commands/copyfrom.c:260 #, c-format -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "COPY DEFAULTはCOPY FROMでのみ使用できます" +msgid "COPY %s" +msgstr "%sのCOPY" -#: commands/copy.c:824 +#: commands/copyfrom.c:268 #, c-format -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "COPYの区切り文字はDEFAULT指定では使用できません" +msgid "COPY %s, line %, column %s" +msgstr "%sのCOPY、行 %、列 %s" -#: commands/copy.c:831 +#: commands/copyfrom.c:273 commands/copyfrom.c:319 #, c-format -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "COPYの引用符はDEFAULT指定では使用できません" +msgid "COPY %s, line %" +msgstr "%sのCOPY、行 %" -#: commands/copy.c:839 +#: commands/copyfrom.c:285 #, c-format -msgid "NULL specification and DEFAULT specification cannot be the same" -msgstr "NULL指定とDEFAULT指定は同じにはできません" - -#: commands/copy.c:901 -#, c-format -msgid "column \"%s\" is a generated column" -msgstr "列\"%s\"は生成カラムです" - -#: commands/copy.c:903 -#, c-format -msgid "Generated columns cannot be used in COPY." -msgstr "生成カラムはCOPYでは使えません。" - -#: commands/copy.c:918 commands/indexcmds.c:1915 commands/statscmds.c:239 commands/tablecmds.c:2514 commands/tablecmds.c:2985 commands/tablecmds.c:3781 parser/parse_relation.c:3692 parser/parse_relation.c:3702 parser/parse_relation.c:3720 parser/parse_relation.c:3727 parser/parse_relation.c:3741 utils/adt/tsvector_op.c:2853 -#, c-format -msgid "column \"%s\" does not exist" -msgstr "列\"%s\"は存在しません" - -#: commands/copy.c:925 commands/tablecmds.c:2540 commands/trigger.c:951 parser/parse_target.c:1083 parser/parse_target.c:1094 -#, c-format -msgid "column \"%s\" specified more than once" -msgstr "列\"%s\"が複数指定されました" - -#: commands/copyfrom.c:118 -#, c-format -msgid "COPY %s" -msgstr "%sのCOPY" - -#: commands/copyfrom.c:126 -#, c-format -msgid "COPY %s, line %llu, column %s" -msgstr "%sのCOPY、行 %llu、列 %s" +msgid "COPY %s, line %, column %s: \"%s\"" +msgstr "%sのCOPY、行 %、列 %s: \"%s\"" -#: commands/copyfrom.c:131 commands/copyfrom.c:177 +#: commands/copyfrom.c:295 #, c-format -msgid "COPY %s, line %llu" -msgstr "%sのCOPY、行 %llu" +msgid "COPY %s, line %, column %s: null input" +msgstr "%sのCOPY、行 %、列 %s: null が入力されました" -#: commands/copyfrom.c:143 +#: commands/copyfrom.c:312 #, c-format -msgid "COPY %s, line %llu, column %s: \"%s\"" -msgstr "%sのCOPY、行 %llu、列 %s: \"%s\"" +msgid "COPY %s, line %: \"%s\"" +msgstr "%sのCOPY、行 %: \"%s\"" -#: commands/copyfrom.c:153 -#, c-format -msgid "COPY %s, line %llu, column %s: null input" -msgstr "%sのCOPY、行 %llu、列 %s: null が入力されました" - -#: commands/copyfrom.c:170 -#, c-format -msgid "COPY %s, line %llu: \"%s\"" -msgstr "%sのCOPY、行 %llu: \"%s\"" - -#: commands/copyfrom.c:673 +#: commands/copyfrom.c:823 #, c-format msgid "cannot copy to view \"%s\"" msgstr "ビュー\"%s\"へのコピーはできません" -#: commands/copyfrom.c:675 +#: commands/copyfrom.c:825 #, c-format msgid "To enable copying to a view, provide an INSTEAD OF INSERT trigger." msgstr "ビューへのコピーを可能にするためには、INSTEAD OF INSERTトリガを作成してください。" -#: commands/copyfrom.c:679 +#: commands/copyfrom.c:829 #, c-format msgid "cannot copy to materialized view \"%s\"" msgstr "実体化ビュー\"%s\"へのコピーはできません" -#: commands/copyfrom.c:684 +#: commands/copyfrom.c:834 #, c-format msgid "cannot copy to sequence \"%s\"" msgstr "シーケンス\"%s\"へのコピーはできません" -#: commands/copyfrom.c:689 +#: commands/copyfrom.c:839 #, c-format msgid "cannot copy to non-table relation \"%s\"" msgstr "テーブル以外のリレーション\"%s\"へのコピーはできません" -#: commands/copyfrom.c:729 +#: commands/copyfrom.c:879 #, c-format msgid "cannot perform COPY FREEZE on a partitioned table" msgstr "パーティション親テーブルに対して COPY FREEZE は実行できません" -#: commands/copyfrom.c:744 +#: commands/copyfrom.c:886 +#, c-format +msgid "cannot perform COPY FREEZE on a foreign table" +msgstr "外部テーブルに対して COPY FREEZE は実行できません" + +#: commands/copyfrom.c:900 #, c-format msgid "cannot perform COPY FREEZE because of prior transaction activity" msgstr "先行するトランザクション処理のためCOPY FREEZEを実行することができません" -#: commands/copyfrom.c:750 +#: commands/copyfrom.c:906 #, c-format msgid "cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction" msgstr "このテーブルは現在のサブトランザクションにおいて作成または切り詰めされていないため、COPY FREEZEを実行することができません" -#: commands/copyfrom.c:1313 +#: commands/copyfrom.c:1171 #, c-format -msgid "%llu row was skipped due to data type incompatibility" -msgid_plural "%llu rows were skipped due to data type incompatibility" -msgstr[0] "%llu行がデータ型の不適合によりスキップされました" +msgid "skipped more than REJECT_LIMIT (%) rows due to data type incompatibility" +msgstr "データ型の不適合により、REJECT_LIMIT (%)を超える行がスキップされました" -#: commands/copyfrom.c:1447 +#: commands/copyfrom.c:1474 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "FORCE_NOT_NULL指定された列\"%s\"はCOPYで参照されません" +msgid "% row was skipped due to data type incompatibility" +msgid_plural "% rows were skipped due to data type incompatibility" +msgstr[0] "%行がデータ型の不適合によりスキップされました" -#: commands/copyfrom.c:1489 +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1611 commands/copyfrom.c:1654 commands/copyto.c:881 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "FORCE_NULL指定された列\"%s\"はCOPYで参照されません" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "%s指定された列\"%s\"はCOPYで参照されません" -#: commands/copyfrom.c:1542 utils/mb/mbutils.c:385 +#: commands/copyfrom.c:1707 utils/mb/mbutils.c:385 #, c-format msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" msgstr "符号化方式\"%s\"から\"%s\"用のデフォルト変換関数は存在しません" -#: commands/copyfrom.c:1740 +#: commands/copyfrom.c:1882 #, c-format msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY FROMによってPostgreSQLサーバープロセスはファイルを読み込みます。psqlの \\copy のようなクライアント側の仕組みが必要かもしれません" -#: commands/copyfrom.c:1753 commands/copyto.c:701 +#: commands/copyfrom.c:1895 commands/copyto.c:986 #, c-format msgid "\"%s\" is a directory" msgstr "\"%s\"はディレクトリです" -#: commands/copyfrom.c:1821 commands/copyto.c:299 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1953 commands/copyto.c:572 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "外部コマンドに対するパイプをクローズできませんでした: %m" -#: commands/copyfrom.c:1836 commands/copyto.c:304 +#: commands/copyfrom.c:1968 commands/copyto.c:577 #, c-format msgid "program \"%s\" failed" msgstr "プログラム\"%s\"の実行に失敗しました" @@ -7007,661 +7003,661 @@ msgstr "COPYファイルのヘッダが不正です(サイズが不正です)" msgid "could not read from COPY file: %m" msgstr "COPYファイルから読み込めませんでした: %m" -#: commands/copyfromparse.c:278 commands/copyfromparse.c:303 replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:377 +#: commands/copyfromparse.c:278 commands/copyfromparse.c:303 replication/walsender.c:732 replication/walsender.c:758 tcop/postgres.c:369 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "トランザクションを実行中のクライアント接続で想定外のEOFがありました" -#: commands/copyfromparse.c:294 replication/walsender.c:772 +#: commands/copyfromparse.c:294 replication/walsender.c:748 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "標準入力からのCOPY中に想定外のメッセージタイプ0x%02Xがありました" -#: commands/copyfromparse.c:317 replication/walsender.c:803 +#: commands/copyfromparse.c:317 replication/walsender.c:779 #, c-format msgid "COPY from stdin failed: %s" msgstr "標準入力からのCOPYが失敗しました: %s" -#: commands/copyfromparse.c:785 +#: commands/copyfromparse.c:802 #, c-format msgid "wrong number of fields in header line: got %d, expected %d" msgstr "ヘッダ行の列数が間違っています: %dでしたが、%dを想定していました" -#: commands/copyfromparse.c:801 +#: commands/copyfromparse.c:818 #, c-format msgid "column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"" msgstr "ヘッダ行フィールド%dでカラム名の不一致: NULL値(\"%s\")を検出, 予期していた値\"%s\"" -#: commands/copyfromparse.c:808 +#: commands/copyfromparse.c:825 #, c-format msgid "column name mismatch in header line field %d: got \"%s\", expected \"%s\"" msgstr "ヘッダ行フィールド%dでカラム名の不一致: \"%s\"を検出, 予期していた値\"%s\"" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 commands/copyfromparse.c:1810 +#: commands/copyfromparse.c:962 commands/copyfromparse.c:1581 commands/copyfromparse.c:1837 #, c-format msgid "extra data after last expected column" msgstr "推定最終列の後に余計なデータがありました" -#: commands/copyfromparse.c:906 +#: commands/copyfromparse.c:976 #, c-format msgid "missing data for column \"%s\"" msgstr "列\"%s\"のデータがありません" -#: commands/copyfromparse.c:990 +#: commands/copyfromparse.c:1056 #, c-format -msgid "skipping row due to data type incompatibility at line %llu for column %s: \"%s\"" -msgstr "データ型非互換のため行をスキップします: 行%llu 列 %s: \"%s\"" +msgid "skipping row due to data type incompatibility at line % for column \"%s\": \"%s\"" +msgstr "行%での列 \"%s\"に対するデータ型非互換のため、この行をスキップします : \"%s\"" -#: commands/copyfromparse.c:998 +#: commands/copyfromparse.c:1064 #, c-format -msgid "skipping row due to data type incompatibility at line %llu for column %s: null input" -msgstr "データ型非互換のため行をスキップします: 行%llu 列 %s: NULLが入力されました" +msgid "skipping row due to data type incompatibility at line % for column \"%s\": null input" +msgstr "行%での列\"%s\"に対するデータ型非互換のため、この行をスキップします: NULL入力" -#: commands/copyfromparse.c:1044 +#: commands/copyfromparse.c:1122 #, c-format msgid "received copy data after EOF marker" msgstr "EOF マーカーの後ろでコピーデータを受信しました" -#: commands/copyfromparse.c:1051 +#: commands/copyfromparse.c:1129 #, c-format msgid "row field count is %d, expected %d" msgstr "行のフィールド数は%d、その期待値は%dです" -#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 +#: commands/copyfromparse.c:1394 commands/copyfromparse.c:1411 #, c-format msgid "literal carriage return found in data" msgstr "データの中に復帰記号そのものがありました" -#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 +#: commands/copyfromparse.c:1395 commands/copyfromparse.c:1412 #, c-format msgid "unquoted carriage return found in data" msgstr "データの中に引用符のない復帰記号がありました" -#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 +#: commands/copyfromparse.c:1397 commands/copyfromparse.c:1414 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "復帰記号は\"\\r\"と表現してください" -#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 +#: commands/copyfromparse.c:1398 commands/copyfromparse.c:1415 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "復帰記号を表現するにはCSVフィールドを引用符で括ってください" -#: commands/copyfromparse.c:1369 +#: commands/copyfromparse.c:1427 #, c-format msgid "literal newline found in data" msgstr "データの中に改行記号そのものがありました" -#: commands/copyfromparse.c:1370 +#: commands/copyfromparse.c:1428 #, c-format msgid "unquoted newline found in data" msgstr "データの中に引用符のない改行記号がありました" -#: commands/copyfromparse.c:1372 +#: commands/copyfromparse.c:1430 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "改行記号は\"\\n\"と表現してください" -#: commands/copyfromparse.c:1373 +#: commands/copyfromparse.c:1431 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "改行記号を表現するにはCSVフィールドを引用符で括ってください" -#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 +#: commands/copyfromparse.c:1469 commands/copyfromparse.c:1491 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "コピー終端記号がこれまでの改行方式と一致しません" -#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 +#: commands/copyfromparse.c:1473 commands/copyfromparse.c:1484 commands/copyfromparse.c:1500 #, c-format -msgid "end-of-copy marker corrupt" -msgstr "コピー終端記号が破損しています" +msgid "end-of-copy marker is not alone on its line" +msgstr "コピー終端記号が行内で単独ではありません" -#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 +#: commands/copyfromparse.c:1773 commands/copyfromparse.c:1988 #, c-format msgid "unexpected default marker in COPY data" msgstr "COPYデータの中に想定外のデフォルトマーカーがあります" -#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 +#: commands/copyfromparse.c:1774 commands/copyfromparse.c:1989 #, c-format msgid "Column \"%s\" has no default value." msgstr "列\"%s\"はデフォルト値を持ちません。" -#: commands/copyfromparse.c:1894 +#: commands/copyfromparse.c:1921 #, c-format msgid "unterminated CSV quoted field" msgstr "CSV引用符が閉じていません" -#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 +#: commands/copyfromparse.c:2023 commands/copyfromparse.c:2042 #, c-format msgid "unexpected EOF in COPY data" msgstr "COPYデータの中に想定外のEOFがあります" -#: commands/copyfromparse.c:2005 +#: commands/copyfromparse.c:2032 #, c-format msgid "invalid field size" msgstr "フィールドサイズが不正です" -#: commands/copyfromparse.c:2028 +#: commands/copyfromparse.c:2055 #, c-format msgid "incorrect binary data format" msgstr "バイナリデータ書式が不正です" -#: commands/copyto.c:229 +#: commands/copyto.c:477 #, c-format msgid "could not write to COPY program: %m" msgstr "COPYプログラムに書き出せませんでした: %m" -#: commands/copyto.c:234 +#: commands/copyto.c:482 #, c-format msgid "could not write to COPY file: %m" msgstr "COPYファイルに書き出せませんでした: %m" -#: commands/copyto.c:379 +#: commands/copyto.c:652 #, c-format msgid "cannot copy from view \"%s\"" msgstr "ビュー\"%s\"からのコピーはできません" -#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 commands/copyto.c:404 +#: commands/copyto.c:654 commands/copyto.c:669 commands/copyto.c:680 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "COPY (SELECT ...) TO構文を試してください" -#: commands/copyto.c:385 +#: commands/copyto.c:660 +#, c-format +msgid "cannot copy from unpopulated materialized view \"%s\"" +msgstr "データ未投入の実体化ビュー\"%s\"からのコピーはできません" + +#: commands/copyto.c:662 executor/execUtils.c:761 #, c-format -msgid "cannot copy from materialized view \"%s\"" -msgstr "実体化ビュー\"%s\"からのコピーはできません" +msgid "Use the REFRESH MATERIALIZED VIEW command." +msgstr "REFRESH MATERIALIZED VIEWコマンドを使用してください。" -#: commands/copyto.c:391 +#: commands/copyto.c:667 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "外部テーブル \"%s\" からのコピーはできません" -#: commands/copyto.c:397 +#: commands/copyto.c:673 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "シーケンス\"%s\"からのコピーはできません" -#: commands/copyto.c:402 +#: commands/copyto.c:678 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "パーティション親テーブル\"%s\"からのコピーはできません" -#: commands/copyto.c:408 +#: commands/copyto.c:684 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "テーブル以外のリレーション\"%s\"からのコピーはできません" -#: commands/copyto.c:460 +#: commands/copyto.c:739 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "DO INSTEAD NOTHING ルールは COPY ではサポートされていません" -#: commands/copyto.c:474 +#: commands/copyto.c:753 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "条件付き DO INSTEAD ルールは COPY ではサポートされていません" -#: commands/copyto.c:478 +#: commands/copyto.c:757 #, c-format -msgid "DO ALSO rules are not supported for the COPY" +msgid "DO ALSO rules are not supported for COPY" msgstr "DO ALSO ルールは COPY ではサポートされていません" -#: commands/copyto.c:483 +#: commands/copyto.c:762 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "マルチステートメントの DO INSTEAD ルールは COPY ではサポートされていません" -#: commands/copyto.c:493 +#: commands/copyto.c:772 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO)はサポートされていません" -#: commands/copyto.c:511 +#: commands/copyto.c:778 +#, c-format +msgid "COPY query must not be a utility command" +msgstr "COPY問い合わせはユーティリティコマンドであってはなりません" + +#: commands/copyto.c:794 #, c-format msgid "COPY query must have a RETURNING clause" msgstr "COPY文中の問い合わせではRETURNING句が必須です" -#: commands/copyto.c:540 +#: commands/copyto.c:823 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "COPY文で参照されているリレーションが変更されました" -#: commands/copyto.c:596 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "FORCE_QUOTE指定された列\"%s\"はCOPYで参照されません" - -#: commands/copyto.c:666 +#: commands/copyto.c:951 #, c-format msgid "relative path not allowed for COPY to file" msgstr "ファイルへのCOPYでは相対パスは指定できません" -#: commands/copyto.c:685 +#: commands/copyto.c:970 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "ファイル\"%s\"を書き込み用にオープンできませんでした: %m" -#: commands/copyto.c:688 +#: commands/copyto.c:973 #, c-format msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY TOによってPostgreSQLサーバープロセスはファイルの書き込みを行います。psqlの \\copy のようなクライアント側の仕組みが必要かもしれません" -#: commands/createas.c:210 commands/createas.c:518 +#: commands/createas.c:212 commands/createas.c:524 #, c-format msgid "too many column names were specified" msgstr "指定された列別名が多すぎます" -#: commands/createas.c:541 +#: commands/createas.c:547 #, c-format msgid "policies not yet implemented for this command" msgstr "このコマンドにはポリシは実装されていません" -#: commands/dbcommands.c:829 +#: commands/dbcommands.c:843 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATIONはもはやサポートされません" -#: commands/dbcommands.c:830 +#: commands/dbcommands.c:844 #, c-format msgid "Consider using tablespaces instead." msgstr "代わりにテーブル空間の使用を検討してください" -#: commands/dbcommands.c:855 +#: commands/dbcommands.c:869 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "%uより小さいOIDはシステムオブジェクトのために予約されています" -#: commands/dbcommands.c:886 utils/adt/ascii.c:146 +#: commands/dbcommands.c:900 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "%dは有効な符号化方式コードではありません" -#: commands/dbcommands.c:897 utils/adt/ascii.c:128 +#: commands/dbcommands.c:911 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "%sは有効な符号化方式名ではありません" -#: commands/dbcommands.c:931 +#: commands/dbcommands.c:945 #, c-format msgid "unrecognized locale provider: %s" msgstr "認識できない照合順序プロバイダ: %s" -#: commands/dbcommands.c:944 commands/dbcommands.c:2402 commands/user.c:299 commands/user.c:739 +#: commands/dbcommands.c:958 commands/dbcommands.c:2428 commands/user.c:300 commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "不正な接続数制限: %d" -#: commands/dbcommands.c:965 +#: commands/dbcommands.c:979 #, c-format msgid "permission denied to create database" msgstr "データベースを作成する権限がありません" -#: commands/dbcommands.c:989 +#: commands/dbcommands.c:1003 #, c-format msgid "template database \"%s\" does not exist" msgstr "テンプレートデータベース\"%s\"は存在しません" -#: commands/dbcommands.c:999 +#: commands/dbcommands.c:1013 #, c-format msgid "cannot use invalid database \"%s\" as template" msgstr "無効なデータベース\"%s\"はテンプレートとして使用できません" -#: commands/dbcommands.c:1000 commands/dbcommands.c:2431 utils/init/postinit.c:1112 +#: commands/dbcommands.c:1014 commands/dbcommands.c:2458 utils/init/postinit.c:1106 #, c-format msgid "Use DROP DATABASE to drop invalid databases." msgstr "DROP DATABASEを使用して無効なデータベースを削除してください。" -#: commands/dbcommands.c:1011 +#: commands/dbcommands.c:1025 #, c-format msgid "permission denied to copy database \"%s\"" msgstr "データベース\"%s\"をコピーする権限がありません" -#: commands/dbcommands.c:1028 +#: commands/dbcommands.c:1042 #, c-format msgid "invalid create database strategy \"%s\"" msgstr "データベース作成の方法\"%s\"は不正です" -#: commands/dbcommands.c:1029 +#: commands/dbcommands.c:1043 #, c-format msgid "Valid strategies are \"wal_log\" and \"file_copy\"." msgstr "有効な方法は\"wal_log\"と\"file_copy\"です。" -#: commands/dbcommands.c:1050 +#: commands/dbcommands.c:1064 #, c-format msgid "invalid server encoding %d" msgstr "サーバーの符号化方式%dは不正です" -#: commands/dbcommands.c:1056 +#: commands/dbcommands.c:1070 #, c-format msgid "invalid LC_COLLATE locale name: \"%s\"" msgstr "LC_COLLATEのロケール名\"%s\"は不正です" -#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 +#: commands/dbcommands.c:1071 commands/dbcommands.c:1077 #, c-format msgid "If the locale name is specific to ICU, use ICU_LOCALE." msgstr "ロケール名がICU特有のものである場合は、ICU_LOCALEを使用してください。" -#: commands/dbcommands.c:1062 +#: commands/dbcommands.c:1076 #, c-format msgid "invalid LC_CTYPE locale name: \"%s\"" msgstr "LC_CTYPEのロケール名\"%s\"は不正です" -#: commands/dbcommands.c:1074 +#: commands/dbcommands.c:1088 #, c-format msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" msgstr "BUILTIN_LOCALEはロケールプロバイダがbuiltinでなければ指定できません" -#: commands/dbcommands.c:1082 +#: commands/dbcommands.c:1096 #, c-format msgid "ICU locale cannot be specified unless locale provider is ICU" msgstr "ICUロケールはロケールプロバイダがICUでなければ指定できません" -#: commands/dbcommands.c:1100 +#: commands/dbcommands.c:1114 #, c-format msgid "LOCALE or BUILTIN_LOCALE must be specified" msgstr "LOCALEかBUILTIN_LOCALEのいずれかを指定しなければなりません" -#: commands/dbcommands.c:1109 +#: commands/dbcommands.c:1123 #, c-format msgid "encoding \"%s\" is not supported with ICU provider" msgstr "エンコーディング\"%s\"はICUではサポートされていません" -#: commands/dbcommands.c:1119 +#: commands/dbcommands.c:1133 #, c-format msgid "LOCALE or ICU_LOCALE must be specified" msgstr "LOCALEかICU_LOCALEのいずれかを指定しなければなりません" -#: commands/dbcommands.c:1163 +#: commands/dbcommands.c:1177 #, c-format msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)" msgstr "新しい符号化方式(%s)はテンプレートデータベースの符号化方式(%s)と互換性がありません" -#: commands/dbcommands.c:1166 +#: commands/dbcommands.c:1180 #, c-format msgid "Use the same encoding as in the template database, or use template0 as template." msgstr "テンプレートデータベースの符号化方式と同じものを使うか、もしくは template0 をテンプレートとして使用してください" -#: commands/dbcommands.c:1171 +#: commands/dbcommands.c:1185 #, c-format msgid "new collation (%s) is incompatible with the collation of the template database (%s)" msgstr "新しい照合順序(%s)はテンプレートデータベースの照合順序(%s)と互換性がありません" -#: commands/dbcommands.c:1173 +#: commands/dbcommands.c:1187 #, c-format msgid "Use the same collation as in the template database, or use template0 as template." msgstr "テンプレートデータベースの照合順序と同じものを使うか、もしくは template0 をテンプレートとして使用してください" -#: commands/dbcommands.c:1178 +#: commands/dbcommands.c:1192 #, c-format msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)" msgstr "新しいLC_CTYPE(%s)はテンプレートデータベース(%s)のLC_CTYPEと互換性がありません" -#: commands/dbcommands.c:1180 +#: commands/dbcommands.c:1194 #, c-format msgid "Use the same LC_CTYPE as in the template database, or use template0 as template." msgstr "テンプレートデータベースのLC_CTYPEと同じものを使うか、もしくはtemplate0をテンプレートとして使用してください" -#: commands/dbcommands.c:1185 +#: commands/dbcommands.c:1199 #, c-format msgid "new locale provider (%s) does not match locale provider of the template database (%s)" msgstr "新しいロケール・プロバイダ(%s)はテンプレートデータベースのロケール・プロバイダ(%s)と一致しません" -#: commands/dbcommands.c:1187 +#: commands/dbcommands.c:1201 #, c-format msgid "Use the same locale provider as in the template database, or use template0 as template." msgstr "テンプレートデータベースと同じロケールプロバイダを使うか、もしくは template0 をテンプレートとして使用してください" -#: commands/dbcommands.c:1199 +#: commands/dbcommands.c:1213 #, c-format msgid "new ICU locale (%s) is incompatible with the ICU locale of the template database (%s)" msgstr "新しいICUロケール(%s)はテンプレートデータベースのICUロケール(%s)と互換性がありません" -#: commands/dbcommands.c:1201 +#: commands/dbcommands.c:1215 #, c-format msgid "Use the same ICU locale as in the template database, or use template0 as template." msgstr "テンプレートデータベースと同じICUロケールを使うか、もしくは template0 をテンプレートとして使用してください。" -#: commands/dbcommands.c:1212 +#: commands/dbcommands.c:1226 #, c-format msgid "new ICU collation rules (%s) are incompatible with the ICU collation rules of the template database (%s)" msgstr "新しいICU照合順序ルール(%s)はテンプレートデータベースのICU照合順序(%s)と互換性がありません" -#: commands/dbcommands.c:1214 +#: commands/dbcommands.c:1228 #, c-format msgid "Use the same ICU collation rules as in the template database, or use template0 as template." msgstr "テンプレートデータベースのICU照合順序ルールと同じものを使うか、もしくは template0 をテンプレートとして使用してください" -#: commands/dbcommands.c:1243 +#: commands/dbcommands.c:1257 #, c-format msgid "template database \"%s\" has a collation version, but no actual collation version could be determined" msgstr "テンプレートデータベース\"%s\"には照合順序のバージョンが設定されていますが、実際の照合順序バージョンが特定できません" -#: commands/dbcommands.c:1248 +#: commands/dbcommands.c:1262 #, c-format msgid "template database \"%s\" has a collation version mismatch" msgstr "テンプレートデータベース\"%s\"では照合順序バージョンの不一致が起きています" -#: commands/dbcommands.c:1250 +#: commands/dbcommands.c:1264 #, c-format msgid "The template database was created using collation version %s, but the operating system provides version %s." msgstr "データベース中の照合順序はバージョン%sで作成されていますが、オペレーティングシステムはバージョン%sを提供しています。" -#: commands/dbcommands.c:1253 +#: commands/dbcommands.c:1267 #, c-format msgid "Rebuild all objects in the template database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "デフォルトの照合順序を使用しているテンプレート・データベースの全てのオブジェクトを再構築して、ALTER DATABASE %s REFRESH COLLATION VERSIONを実行するか、正しいバージョンのライブラリを用いてPostgreSQLをビルドしてください。" -#: commands/dbcommands.c:1298 commands/dbcommands.c:2031 +#: commands/dbcommands.c:1312 commands/dbcommands.c:2055 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "デフォルトのテーブル空間としてpg_globalを使用できません" -#: commands/dbcommands.c:1324 +#: commands/dbcommands.c:1338 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "新しいデフォルトのテーブル空間\"%s\"を割り当てられません" -#: commands/dbcommands.c:1326 +#: commands/dbcommands.c:1340 #, c-format msgid "There is a conflict because database \"%s\" already has some tables in this tablespace." msgstr "データベース\"%s\"のいくつかテーブルはすでにこのテーブル空間にあるため、競合しています。" -#: commands/dbcommands.c:1356 commands/dbcommands.c:1904 +#: commands/dbcommands.c:1370 commands/dbcommands.c:1926 #, c-format msgid "database \"%s\" already exists" msgstr "データベース\"%s\"はすでに存在します" -#: commands/dbcommands.c:1370 +#: commands/dbcommands.c:1384 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "元となるデータベース\"%s\"は他のユーザーによってアクセスされています" -#: commands/dbcommands.c:1392 +#: commands/dbcommands.c:1406 #, c-format msgid "database OID %u is already in use by database \"%s\"" msgstr "データベースOID %uはすでにデータベース\"%s\"で使用されています" -#: commands/dbcommands.c:1398 +#: commands/dbcommands.c:1412 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "指定されたOID %uのデータディレクトリはすでに存在します" -#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 utils/adt/pg_locale.c:2565 +#: commands/dbcommands.c:1585 commands/dbcommands.c:1600 utils/adt/pg_locale.c:1515 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "符号化方式\"%s\"がロケール\"%s\"に合いません" -#: commands/dbcommands.c:1574 +#: commands/dbcommands.c:1588 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "選択されたLC_CTYPEを設定するには、符号化方式\"%s\"である必要があります。" -#: commands/dbcommands.c:1589 +#: commands/dbcommands.c:1603 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "選択されたLC_COLLATEを設定するには、符号化方式\"%s\"である必要があります。" -#: commands/dbcommands.c:1670 +#: commands/dbcommands.c:1686 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "データベース\"%s\"は存在しません、スキップします" -#: commands/dbcommands.c:1694 +#: commands/dbcommands.c:1710 #, c-format msgid "cannot drop a template database" msgstr "テンプレートデータベースを削除できません" -#: commands/dbcommands.c:1700 +#: commands/dbcommands.c:1716 #, c-format msgid "cannot drop the currently open database" msgstr "現在オープンしているデータベースを削除できません" -#: commands/dbcommands.c:1713 +#: commands/dbcommands.c:1729 #, c-format msgid "database \"%s\" is used by an active logical replication slot" msgstr "データベース\"%s\"は有効な論理レプリケーションスロットで使用中です" -#: commands/dbcommands.c:1715 +#: commands/dbcommands.c:1731 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." msgstr[0] "%d 個のアクティブなスロットがあります。" -#: commands/dbcommands.c:1729 +#: commands/dbcommands.c:1745 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "データベース\"%s\"は論理レプリケーションのサブスクリプションで使用中です" -#: commands/dbcommands.c:1731 +#: commands/dbcommands.c:1747 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." msgstr[0] "%d個のサブスクリプションがあります" -#: commands/dbcommands.c:1752 commands/dbcommands.c:1926 commands/dbcommands.c:2053 +#: commands/dbcommands.c:1768 commands/dbcommands.c:1948 commands/dbcommands.c:2077 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "データベース\"%s\"は他のユーザーからアクセスされています" -#: commands/dbcommands.c:1886 +#: commands/dbcommands.c:1908 #, c-format msgid "permission denied to rename database" msgstr "データベースの名前を変更する権限がありません" -#: commands/dbcommands.c:1915 +#: commands/dbcommands.c:1937 #, c-format msgid "current database cannot be renamed" msgstr "現在のデータベースの名前を変更できません" -#: commands/dbcommands.c:2009 +#: commands/dbcommands.c:2033 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "現在オープン中のデータベースのテーブルスペースは変更できません" -#: commands/dbcommands.c:2115 +#: commands/dbcommands.c:2139 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "データベース\"%s\"のリレーションの中に、テーブルスペース\"%s\"にすでに存在するものがあります" -#: commands/dbcommands.c:2117 +#: commands/dbcommands.c:2141 #, c-format msgid "You must move them back to the database's default tablespace before using this command." msgstr "このコマンドを使う前に、データベースのデフォルトのテーブルスペースに戻す必要があります。" -#: commands/dbcommands.c:2244 commands/dbcommands.c:2979 commands/dbcommands.c:3279 commands/dbcommands.c:3392 +#: commands/dbcommands.c:2270 commands/dbcommands.c:3013 commands/dbcommands.c:3313 commands/dbcommands.c:3426 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "元のデータベースのディレクトリ\"%s\"に不要なファイルが残っているかもしれません" -#: commands/dbcommands.c:2305 +#: commands/dbcommands.c:2331 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "DROP DATABASEのオプション\"%s\"が認識できません" -#: commands/dbcommands.c:2383 +#: commands/dbcommands.c:2409 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "オプション\"%s\"は他のオプションと一緒に指定はできません" -#: commands/dbcommands.c:2430 +#: commands/dbcommands.c:2457 #, c-format msgid "cannot alter invalid database \"%s\"" msgstr "無効なデータベース\"%s\"は変更できません" -#: commands/dbcommands.c:2447 +#: commands/dbcommands.c:2474 #, c-format msgid "cannot disallow connections for current database" msgstr "現在のデータベースへの接続は禁止できません" -#: commands/dbcommands.c:2673 +#: commands/dbcommands.c:2704 #, c-format msgid "permission denied to change owner of database" msgstr "データベースの所有者を変更する権限がありません" -#: commands/dbcommands.c:3085 +#: commands/dbcommands.c:3119 #, c-format msgid "There are %d other session(s) and %d prepared transaction(s) using the database." msgstr "他にこのデータベースを使っている %d 個のセッションと %d 個の準備済みトランザクションがあります。" -#: commands/dbcommands.c:3088 +#: commands/dbcommands.c:3122 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." msgstr[0] "他にこのデータベースを使っている %d 個のセッションがあります。" -#: commands/dbcommands.c:3093 storage/ipc/procarray.c:3847 +#: commands/dbcommands.c:3127 storage/ipc/procarray.c:3860 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." msgstr[0] "このデータベースを使用する準備されたトランザクションが%d存在します。" -#: commands/dbcommands.c:3235 +#: commands/dbcommands.c:3269 #, c-format msgid "missing directory \"%s\"" msgstr "ディレクトリ\"%s\"がありません" -#: commands/dbcommands.c:3293 commands/tablespace.c:184 commands/tablespace.c:633 +#: commands/dbcommands.c:3327 commands/tablespace.c:184 commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "ディレクトリ\"%s\"のstatができませんでした: %m" -#: commands/define.c:53 commands/define.c:257 commands/define.c:289 commands/define.c:317 commands/define.c:363 +#: commands/define.c:40 commands/define.c:244 commands/define.c:276 commands/define.c:304 commands/define.c:350 #, c-format msgid "%s requires a parameter" msgstr "%sはパラメータが必要です" -#: commands/define.c:86 commands/define.c:97 commands/define.c:191 commands/define.c:209 commands/define.c:224 commands/define.c:242 -#, c-format -msgid "%s requires a numeric value" -msgstr "%sは数値が必要です" - -#: commands/define.c:153 +#: commands/define.c:140 #, c-format msgid "%s requires a Boolean value" msgstr "パラメータ\"%s\"はboolean値が必要です" -#: commands/define.c:167 commands/define.c:176 commands/define.c:326 +#: commands/define.c:154 commands/define.c:163 commands/define.c:313 #, c-format msgid "%s requires an integer value" msgstr "%sは整数値が必要です" -#: commands/define.c:271 +#: commands/define.c:258 #, c-format msgid "argument of %s must be a name" msgstr "%sの引数は名前でなければなりません" -#: commands/define.c:301 +#: commands/define.c:288 #, c-format msgid "argument of %s must be a type name" msgstr "%sの引数は型名でなければなりません" -#: commands/define.c:347 +#: commands/define.c:334 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "%sの引数が不正です: \"%s\"" -#: commands/dropcmds.c:96 commands/functioncmds.c:1382 utils/adt/ruleutils.c:2909 +#: commands/dropcmds.c:96 commands/functioncmds.c:1400 utils/adt/ruleutils.c:2956 #, c-format msgid "\"%s\" is an aggregate function" msgstr "\"%s\"は集約関数です" @@ -7671,17 +7667,17 @@ msgstr "\"%s\"は集約関数です" msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "集約関数を削除するにはDROP AGGREGATEを使用してください" -#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3865 commands/tablecmds.c:4023 commands/tablecmds.c:4075 commands/tablecmds.c:17061 tcop/utility.c:1325 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:4013 commands/tablecmds.c:4174 commands/tablecmds.c:4226 commands/tablecmds.c:18856 tcop/utility.c:1328 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "リレーション\"%s\"は存在しません、スキップします" -#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1397 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1468 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "スキーマ\"%s\"は存在しません、スキップします" -#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:289 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "型\"%s\"は存在しません、スキップします" @@ -7701,7 +7697,7 @@ msgstr "照合順序\"%s\"は存在しません、スキップします" msgid "conversion \"%s\" does not exist, skipping" msgstr "変換\"%sは存在しません、スキップします" -#: commands/dropcmds.c:288 commands/statscmds.c:664 +#: commands/dropcmds.c:288 commands/statscmds.c:682 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "統計情報オブジェクト\"%s\"は存在しません、スキップします" @@ -7857,347 +7853,347 @@ msgstr "%sではイベントトリガはサポートされません" msgid "filter variable \"%s\" specified more than once" msgstr "フィルタ変数\"%s\"が複数指定されました" -#: commands/event_trigger.c:435 commands/event_trigger.c:487 commands/event_trigger.c:581 +#: commands/event_trigger.c:438 commands/event_trigger.c:490 commands/event_trigger.c:584 #, c-format msgid "event trigger \"%s\" does not exist" msgstr "イベントトリガ\"%s\"は存在しません" -#: commands/event_trigger.c:519 +#: commands/event_trigger.c:522 #, c-format msgid "event trigger with OID %u does not exist" msgstr "OID %uのイベントトリガは存在しません" -#: commands/event_trigger.c:549 +#: commands/event_trigger.c:552 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" msgstr "イベントトリガ\"%s\"の所有者を変更する権限がありません" -#: commands/event_trigger.c:551 +#: commands/event_trigger.c:554 #, c-format msgid "The owner of an event trigger must be a superuser." msgstr "イベントトリガの所有者はスーパーユーザーでなければなりません" -#: commands/event_trigger.c:1411 +#: commands/event_trigger.c:1404 #, c-format msgid "%s can only be called in a sql_drop event trigger function" msgstr "%sはsql_dropイベントトリガ関数内でのみ呼び出すことができます" -#: commands/event_trigger.c:1504 commands/event_trigger.c:1525 +#: commands/event_trigger.c:1497 commands/event_trigger.c:1518 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" msgstr "%sはtable_rewriteイベントトリガ関数でのみ呼び出すことができます" -#: commands/event_trigger.c:1938 +#: commands/event_trigger.c:1931 #, c-format msgid "%s can only be called in an event trigger function" msgstr "%sはイベントトリガ関数でのみ呼び出すことができます" -#: commands/explain.c:240 commands/explain.c:265 +#: commands/explain_state.c:133 commands/explain_state.c:158 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "EXPLAIN オプション\"%s\"が認識できない値です: \"%s\"" -#: commands/explain.c:272 +#: commands/explain_state.c:165 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "EXPLAIN オプション\"%s\"が認識できません" -#: commands/explain.c:281 +#: commands/explain_state.c:174 commands/explain_state.c:186 commands/explain_state.c:192 #, c-format -msgid "EXPLAIN option WAL requires ANALYZE" -msgstr "EXPLAINのオプションWALにはANALYZE指定が必要です" +msgid "EXPLAIN option %s requires ANALYZE" +msgstr "EXPLAINのオプション %s には ANALYZE 指定が必要です" -#: commands/explain.c:290 -#, c-format -msgid "EXPLAIN option TIMING requires ANALYZE" -msgstr "EXPLAINオプションのTIMINGにはANALYZE指定が必要です" - -#: commands/explain.c:296 -#, c-format -msgid "EXPLAIN option SERIALIZE requires ANALYZE" -msgstr "EXPLAINのオプションSERIALIZEにはANALYZE指定が必要です" - -#: commands/explain.c:302 +#: commands/explain_state.c:198 #, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" msgstr "EXPLAINのオプションANALYZEとGENERIC_PLANは同時に使用できません" -#: commands/extension.c:178 commands/extension.c:3031 +#: commands/extension.c:174 commands/extension.c:3299 #, c-format msgid "extension \"%s\" does not exist" msgstr "機能拡張\"%s\"は存在しません" -#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 commands/extension.c:308 +#: commands/extension.c:239 commands/extension.c:248 commands/extension.c:260 commands/extension.c:270 #, c-format msgid "invalid extension name: \"%s\"" msgstr "機能拡張名が不正です: \"%s\"" -#: commands/extension.c:278 +#: commands/extension.c:240 #, c-format msgid "Extension names must not be empty." msgstr "機能拡張名が無効です: 空であってはなりません" -#: commands/extension.c:287 +#: commands/extension.c:249 #, c-format msgid "Extension names must not contain \"--\"." msgstr "機能拡張名に\"--\"が含まれていてはなりません" -#: commands/extension.c:299 +#: commands/extension.c:261 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "機能拡張名が\"-\"で始まったり終わったりしてはなりません" -#: commands/extension.c:309 +#: commands/extension.c:271 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "機能拡張名にディレクトリの区切り文字が含まれていてはなりません" -#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 commands/extension.c:352 +#: commands/extension.c:286 commands/extension.c:295 commands/extension.c:304 commands/extension.c:314 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "機能拡張のバージョン名が不正す: \"%s\"" -#: commands/extension.c:325 +#: commands/extension.c:287 #, c-format msgid "Version names must not be empty." msgstr "バージョン名が無効です: 空であってはなりません" -#: commands/extension.c:334 +#: commands/extension.c:296 #, c-format msgid "Version names must not contain \"--\"." msgstr "バージョン名に\"--\"が含まれていてはなりません" -#: commands/extension.c:343 +#: commands/extension.c:305 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "バージョン名が\"-\"で始まったり終わったりしてはなりません" -#: commands/extension.c:353 +#: commands/extension.c:315 #, c-format msgid "Version names must not contain directory separator characters." msgstr "バージョン名にディレクトリの区切り文字が含まれていてはなりません" -#: commands/extension.c:507 +#: commands/extension.c:549 #, c-format msgid "extension \"%s\" is not available" msgstr "機能拡張\"%s\" は利用できません" -#: commands/extension.c:508 -#, c-format -msgid "Could not open extension control file \"%s\": %m." -msgstr "機能拡張の制御ファイル\"%s\"をオープンできませんでした: %m" - -#: commands/extension.c:510 +#: commands/extension.c:550 #, c-format msgid "The extension must first be installed on the system where PostgreSQL is running." msgstr "PostgreSQLが稼働しているシステムで、事前に機能拡張がインストールされている必要があります。" -#: commands/extension.c:514 +#: commands/extension.c:564 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "機能拡張の制御ファイル\"%s\"をオープンできませんでした: %m" -#: commands/extension.c:537 commands/extension.c:547 +#: commands/extension.c:587 commands/extension.c:597 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "セカンダリの機能拡張制御ファイルにパラメータ\"%s\"を設定できません" -#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 utils/misc/guc.c:3147 +#: commands/extension.c:619 commands/extension.c:627 commands/extension.c:635 utils/misc/guc.c:3144 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "パラメータ\"%s\"にはbooleanを指定します" -#: commands/extension.c:594 +#: commands/extension.c:644 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\"は有効な符号化方式名ではありません" -#: commands/extension.c:608 commands/extension.c:623 +#: commands/extension.c:658 commands/extension.c:673 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "パラメータ\"%s\"は機能拡張名のリストでなければなりません" -#: commands/extension.c:630 +#: commands/extension.c:680 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "ファイル\"%2$s\"中に認識できないパラメータ\"%1$s\"があります" -#: commands/extension.c:639 +#: commands/extension.c:689 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "\"relocatable\"が真の場合はパラメータ\"schema\"は指定できません" -#: commands/extension.c:817 +#: commands/extension.c:865 +#, c-format +msgid "SQL statement \"%.*s\"" +msgstr "SQL文 \"%.*s\"" + +#: commands/extension.c:894 +#, c-format +msgid "extension script file \"%s\", near line %d" +msgstr "機能拡張スクリプトファイル \"%s\"、%d 行目付近" + +#: commands/extension.c:898 +#, c-format +msgid "extension script file \"%s\"" +msgstr "機能拡張スクリプトファイル \"%s\"" + +#: commands/extension.c:1012 #, c-format msgid "transaction control statements are not allowed within an extension script" msgstr "トランザクション制御ステートメントを機能拡張スクリプトの中に書くことはできません" -#: commands/extension.c:897 +#: commands/extension.c:1094 #, c-format msgid "permission denied to create extension \"%s\"" msgstr "機能拡張\"%s\"を作成する権限がありません" -#: commands/extension.c:900 +#: commands/extension.c:1097 #, c-format msgid "Must have CREATE privilege on current database to create this extension." msgstr "この機能拡張を生成するには現在のデータベースのCREATE権限が必要です。" -#: commands/extension.c:901 +#: commands/extension.c:1098 #, c-format msgid "Must be superuser to create this extension." msgstr "この機能拡張を生成するにはスーパーユーザーである必要があります。" -#: commands/extension.c:905 +#: commands/extension.c:1102 #, c-format msgid "permission denied to update extension \"%s\"" msgstr "機能拡張\"%s\"を更新する権限がありません" -#: commands/extension.c:908 +#: commands/extension.c:1105 #, c-format msgid "Must have CREATE privilege on current database to update this extension." msgstr "この機能拡張を更新するには現在のデータベースのCREATE権限が必要です。" -#: commands/extension.c:909 +#: commands/extension.c:1106 #, c-format msgid "Must be superuser to update this extension." msgstr "この機能拡張を更新するにはスーパーユーザーである必要があります。" -#: commands/extension.c:1042 +#: commands/extension.c:1239 #, c-format msgid "invalid character in extension owner: must not contain any of \"%s\"" msgstr "機能拡張の所有者名に不正な文字: \"%s\"のいずれの文字も含むことはできません" -#: commands/extension.c:1066 commands/extension.c:1093 +#: commands/extension.c:1263 commands/extension.c:1290 #, c-format msgid "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" msgstr "機能拡張\"%s\"のスキーマ名に不正な文字: \"%s\"のいずれの文字も含むことはできません" -#: commands/extension.c:1288 +#: commands/extension.c:1485 #, c-format msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" msgstr "機能拡張\"%s\"について、バージョン\"%s\"からバージョン\"%s\"へのアップデートパスがありません" -#: commands/extension.c:1496 commands/extension.c:3089 +#: commands/extension.c:1693 commands/extension.c:3357 #, c-format msgid "version to install must be specified" msgstr "インストールするバージョンを指定してください" -#: commands/extension.c:1533 +#: commands/extension.c:1730 #, c-format msgid "extension \"%s\" has no installation script nor update path for version \"%s\"" msgstr "機能拡張\"%s\"にはバージョン\"%s\"のインストールスクリプトもアップデートパスもありません" -#: commands/extension.c:1567 +#: commands/extension.c:1764 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "機能拡張\"%s\"はスキーマ\"%s\"内にインストールされていなければなりません" -#: commands/extension.c:1727 +#: commands/extension.c:1924 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "機能拡張\"%s\"と\"%s\"の間に循環依存関係が検出されました" -#: commands/extension.c:1732 +#: commands/extension.c:1929 #, c-format msgid "installing required extension \"%s\"" msgstr "必要な機能拡張をインストールします:\"%s\"" -#: commands/extension.c:1755 +#: commands/extension.c:1952 #, c-format msgid "required extension \"%s\" is not installed" msgstr "要求された機能拡張\"%s\"はインストールされていません" -#: commands/extension.c:1758 +#: commands/extension.c:1955 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "必要な機能拡張を一緒にインストールするには CREATE EXTENSION ... CASCADE を使ってください。" -#: commands/extension.c:1793 +#: commands/extension.c:1990 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "機能拡張\"%s\"はすでに存在します、スキップします" -#: commands/extension.c:1800 +#: commands/extension.c:1997 #, c-format msgid "extension \"%s\" already exists" msgstr "機能拡張\"%s\"はすでに存在します" -#: commands/extension.c:1811 +#: commands/extension.c:2008 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "入れ子の CREATE EXTENSION はサポートされません" -#: commands/extension.c:1975 +#: commands/extension.c:2172 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "変更されているため拡張\"%s\"を削除できません" -#: commands/extension.c:2450 +#: commands/extension.c:2665 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "%s はCREATE EXTENSIONにより実行されるSQLスクリプトからのみ呼び出すことができます" -#: commands/extension.c:2462 +#: commands/extension.c:2677 #, c-format msgid "OID %u does not refer to a table" msgstr "OID %u がテーブルを参照していません" -#: commands/extension.c:2467 +#: commands/extension.c:2682 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "テーブル\"%s\"は生成されようとしている機能拡張のメンバではありません" -#: commands/extension.c:2813 +#: commands/extension.c:3081 #, c-format msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema" msgstr "機能拡張がそのスキーマを含んでいるため、機能拡張\"%s\"をスキーマ\"%s\"に移動できません" -#: commands/extension.c:2854 commands/extension.c:2948 +#: commands/extension.c:3122 commands/extension.c:3216 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "機能拡張\"%s\"は SET SCHEMA をサポートしていません" -#: commands/extension.c:2911 +#: commands/extension.c:3179 #, c-format msgid "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" msgstr "他の機能拡張によって禁止されているため、機能拡張\"%s\"の SET SCHEMAが実行できません" -#: commands/extension.c:2913 +#: commands/extension.c:3181 #, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." msgstr "機能拡張\"%s\"は機能拡張\"%s\"の再配置禁止を要求しています。" -#: commands/extension.c:2950 +#: commands/extension.c:3218 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "機能拡張のスキーマ\"%2$s\"に%1$sが見つかりません" -#: commands/extension.c:3011 +#: commands/extension.c:3279 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "入れ子になった ALTER EXTENSION はサポートされていません" -#: commands/extension.c:3100 +#: commands/extension.c:3368 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "機能拡張 \"%2$s\"のバージョン\"%1$s\"はすでにインストールされています" -#: commands/extension.c:3311 +#: commands/extension.c:3579 #, c-format msgid "cannot add an object of this type to an extension" msgstr "この型のオブジェクトは機能拡張に追加できません" -#: commands/extension.c:3409 +#: commands/extension.c:3677 #, c-format msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension" msgstr "スキーマ\"%s\"を拡張\"%s\"に追加できません。そのスキーマにその拡張が含まれているためです" -#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#: commands/extension.c:3759 commands/typecmds.c:4033 utils/fmgr/funcapi.c:725 #, c-format msgid "could not find multirange type for data type %s" msgstr "データ型%sの複範囲型がありませんでした" -#: commands/extension.c:3532 +#: commands/extension.c:3801 #, c-format msgid "file \"%s\" is too large" msgstr "ファイル\"%s\"は大きすぎます" @@ -8227,7 +8223,7 @@ msgstr "外部データラッパーの所有者を変更するにはスーパー msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "外部データラッパーの所有者はスーパーユーザーでなければなりません" -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:681 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "外部データラッパー\"%s\"は存在しません" @@ -8297,7 +8293,7 @@ msgstr "\"%s\"のユーザーマッピングはサーバー\"%s\"に対しては msgid "user mapping for \"%s\" does not exist for server \"%s\", skipping" msgstr "\"%s\"のユーザーマッピングはサーバー\"%s\"に対しては存在しません、スキップします" -#: commands/foreigncmds.c:1507 foreign/foreign.c:394 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "外部データラッパー\"%s\"にはハンドラがありません" @@ -8342,628 +8338,673 @@ msgstr "シェル型の定義を作成します" msgid "SQL function cannot accept shell type %s" msgstr "SQL関数はシェル型\"%s\"を受け付けられません" -#: commands/functioncmds.c:250 +#: commands/functioncmds.c:251 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "集約はシェル型\"%s\"を受け付けられません" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:257 #, c-format msgid "argument type %s is only a shell" msgstr "引数型%sは単なるシェルです" -#: commands/functioncmds.c:265 +#: commands/functioncmds.c:268 #, c-format msgid "type %s does not exist" msgstr "型%sは存在しません" -#: commands/functioncmds.c:279 +#: commands/functioncmds.c:283 #, c-format msgid "aggregates cannot accept set arguments" msgstr "集約は集合引数を受け付けられません" -#: commands/functioncmds.c:283 +#: commands/functioncmds.c:288 #, c-format msgid "procedures cannot accept set arguments" msgstr "プロシージャは集合引数を受け付けません" -#: commands/functioncmds.c:287 +#: commands/functioncmds.c:293 #, c-format msgid "functions cannot accept set arguments" msgstr "関数は集合を引数として受け付けられません" -#: commands/functioncmds.c:297 +#: commands/functioncmds.c:304 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "VARIADIC パラメータは最後の入力パラメータでなければなりません" -#: commands/functioncmds.c:317 +#: commands/functioncmds.c:325 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "VARIADIC パラメータは最後のパラメータでなければなりません" -#: commands/functioncmds.c:342 +#: commands/functioncmds.c:351 #, c-format msgid "VARIADIC parameter must be an array" msgstr "VARIADIC パラメータは配列でなければなりません" -#: commands/functioncmds.c:387 +#: commands/functioncmds.c:397 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "パラメータ\"%s\"が複数指定されました" -#: commands/functioncmds.c:405 +#: commands/functioncmds.c:416 #, c-format msgid "only input parameters can have default values" msgstr "入力パラメータのみがデフォルト値を持てます" -#: commands/functioncmds.c:420 +#: commands/functioncmds.c:432 #, c-format msgid "cannot use table references in parameter default value" msgstr "パラメータのデフォルト値としてテーブル参照を使用できません" -#: commands/functioncmds.c:444 +#: commands/functioncmds.c:457 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "デフォルト値を持つパラメータの後にある入力パラメータは、必ずデフォルト値を持たなければなりません" -#: commands/functioncmds.c:454 +#: commands/functioncmds.c:468 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "プロシージャの出力パラメータはデフォルト値を持つパラメータの後には置けません" -#: commands/functioncmds.c:596 commands/functioncmds.c:775 +#: commands/functioncmds.c:611 commands/functioncmds.c:790 #, c-format msgid "invalid attribute in procedure definition" msgstr "プロシージャ定義内の不正な属性" -#: commands/functioncmds.c:692 +#: commands/functioncmds.c:707 #, c-format msgid "support function %s must return type %s" msgstr "サポート関数%sは%s型を返さなければなりません" -#: commands/functioncmds.c:703 +#: commands/functioncmds.c:718 #, c-format msgid "must be superuser to specify a support function" msgstr "サポート関数を指定するにはスーパーユーザーである必要があります" -#: commands/functioncmds.c:824 commands/functioncmds.c:1427 +#: commands/functioncmds.c:839 commands/functioncmds.c:1445 #, c-format msgid "COST must be positive" msgstr "COSTは正数でなければなりません" -#: commands/functioncmds.c:832 commands/functioncmds.c:1435 +#: commands/functioncmds.c:847 commands/functioncmds.c:1453 #, c-format msgid "ROWS must be positive" msgstr "ROWSは正数でなければなりません" -#: commands/functioncmds.c:861 +#: commands/functioncmds.c:876 #, c-format msgid "no function body specified" msgstr "関数本体の指定がありません" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:881 #, c-format msgid "duplicate function body specified" msgstr "関数本体の指定が重複しています" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:886 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "インラインのSQL関数本体は言語指定がSQLの場合にのみ有効です" -#: commands/functioncmds.c:913 +#: commands/functioncmds.c:928 #, c-format msgid "SQL function with unquoted function body cannot have polymorphic arguments" msgstr "本体をクォートせずに定義するSQL関数は多態引き数を取れません" -#: commands/functioncmds.c:939 commands/functioncmds.c:958 +#: commands/functioncmds.c:954 commands/functioncmds.c:973 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "%sはクォートしない関数本体ではサポートされません" -#: commands/functioncmds.c:986 +#: commands/functioncmds.c:1001 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "言語\"%s\"ではAS項目は1つだけ必要です" -#: commands/functioncmds.c:1091 +#: commands/functioncmds.c:1107 #, c-format msgid "no language specified" msgstr "言語が指定されていません" -#: commands/functioncmds.c:1099 commands/functioncmds.c:2104 commands/proclang.c:235 +#: commands/functioncmds.c:1115 commands/functioncmds.c:2135 commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "言語\"%s\"は存在しません" -#: commands/functioncmds.c:1101 commands/functioncmds.c:2106 +#: commands/functioncmds.c:1117 commands/functioncmds.c:2137 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "言語をデータベースに読み込むためには CREATE EXTENSION を使用してください" -#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 +#: commands/functioncmds.c:1150 commands/functioncmds.c:1437 #, c-format msgid "only superuser can define a leakproof function" msgstr "スーパーユーザーのみがリークプルーフ関数を定義することができます" -#: commands/functioncmds.c:1185 +#: commands/functioncmds.c:1202 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "OUTパラメータで定義されているため、関数の戻り値型は%sでなければなりません" -#: commands/functioncmds.c:1198 +#: commands/functioncmds.c:1215 #, c-format msgid "function result type must be specified" msgstr "関数の結果型を指定しなければなりません" -#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 +#: commands/functioncmds.c:1268 commands/functioncmds.c:1457 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "関数が集合を返す場合にROWSは適していません" -#: commands/functioncmds.c:1546 +#: commands/functioncmds.c:1564 #, c-format msgid "source data type %s is a pseudo-type" msgstr "変換元データ型%sは疑似型です" -#: commands/functioncmds.c:1552 +#: commands/functioncmds.c:1570 #, c-format msgid "target data type %s is a pseudo-type" msgstr "変換先データ型%sは疑似型です" -#: commands/functioncmds.c:1576 +#: commands/functioncmds.c:1594 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "元のデータ型がドメインであるため、キャストは無視されます" -#: commands/functioncmds.c:1581 +#: commands/functioncmds.c:1599 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "対象のデータ型がドメインであるため、キャストは無視されます" -#: commands/functioncmds.c:1606 +#: commands/functioncmds.c:1624 #, c-format msgid "cast function must take one to three arguments" msgstr "キャスト関数の引数は1つから3つまでです" -#: commands/functioncmds.c:1612 +#: commands/functioncmds.c:1630 #, c-format msgid "argument of cast function must match or be binary-coercible from source data type" msgstr "キャスト関数の引数は変換元データ型と同一であるか、変換元データ型からバイナリ変換可能である必要があります" -#: commands/functioncmds.c:1616 +#: commands/functioncmds.c:1634 #, c-format msgid "second argument of cast function must be type %s" msgstr "キャスト関数の第2引数は%s型でなければなりません" -#: commands/functioncmds.c:1621 +#: commands/functioncmds.c:1639 #, c-format msgid "third argument of cast function must be type %s" msgstr "キャスト関数の第3引数は%s型でなければなりません" -#: commands/functioncmds.c:1628 +#: commands/functioncmds.c:1646 #, c-format msgid "return data type of cast function must match or be binary-coercible to target data type" msgstr "キャスト関数の戻り値データ型は変換先データ型と一致するか、変換先データ型へバイナリ変換可能である必要があります" -#: commands/functioncmds.c:1639 +#: commands/functioncmds.c:1657 #, c-format msgid "cast function must not be volatile" msgstr "キャスト関数はvolatileではいけません" -#: commands/functioncmds.c:1644 +#: commands/functioncmds.c:1662 #, c-format msgid "cast function must be a normal function" msgstr "キャスト関数は通常の関数でなければなりません" -#: commands/functioncmds.c:1648 +#: commands/functioncmds.c:1666 #, c-format msgid "cast function must not return a set" msgstr "キャスト関数は集合を返してはいけません" -#: commands/functioncmds.c:1674 +#: commands/functioncmds.c:1692 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "WITHOUT FUNCTION指定のキャストを作成するにはスーパーユーザーである必要があります" -#: commands/functioncmds.c:1689 +#: commands/functioncmds.c:1707 #, c-format msgid "source and target data types are not physically compatible" msgstr "変換元と変換先のデータ型の間には物理的な互換性がありません" -#: commands/functioncmds.c:1704 +#: commands/functioncmds.c:1727 #, c-format msgid "composite data types are not binary-compatible" -msgstr "複合データ型はバイナリ互換ではありません" +msgstr "複合データ型がバイナリ互換ではありません" -#: commands/functioncmds.c:1710 +#: commands/functioncmds.c:1733 #, c-format -msgid "enum data types are not binary-compatible" -msgstr "列挙データ型はバイナリ互換ではありません" +msgid "array data types are not binary-compatible" +msgstr "配列データ型がバイナリ互換ではありません" -#: commands/functioncmds.c:1716 +#: commands/functioncmds.c:1741 #, c-format -msgid "array data types are not binary-compatible" -msgstr "配列データ型はバイナリ互換ではありません" +msgid "range data types are not binary-compatible" +msgstr "範囲データ型がバイナリ互換ではありません" -#: commands/functioncmds.c:1733 +#: commands/functioncmds.c:1747 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "列挙データ型がバイナリ互換ではありません" + +#: commands/functioncmds.c:1764 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "ドメインデータ型はバイナリ互換としてマークされていてはなりません" -#: commands/functioncmds.c:1743 +#: commands/functioncmds.c:1774 #, c-format msgid "source data type and target data type are the same" msgstr "変換元と変換先のデータ型が同一です" -#: commands/functioncmds.c:1776 +#: commands/functioncmds.c:1807 #, c-format msgid "transform function must not be volatile" msgstr "変換関数はvolatileではいけません" -#: commands/functioncmds.c:1780 +#: commands/functioncmds.c:1811 #, c-format msgid "transform function must be a normal function" msgstr "変換関数は通常の関数でなければなりません" -#: commands/functioncmds.c:1784 +#: commands/functioncmds.c:1815 #, c-format msgid "transform function must not return a set" msgstr "変換関数は集合を返してはいけません" -#: commands/functioncmds.c:1788 +#: commands/functioncmds.c:1819 #, c-format msgid "transform function must take one argument" msgstr "変換関数は引数を1つとらなければなりません" -#: commands/functioncmds.c:1792 +#: commands/functioncmds.c:1823 #, c-format msgid "first argument of transform function must be type %s" msgstr "変換関数の第1引数は%s型でなければなりません" -#: commands/functioncmds.c:1831 +#: commands/functioncmds.c:1862 #, c-format msgid "data type %s is a pseudo-type" msgstr "データ型%sは擬似型です" -#: commands/functioncmds.c:1837 +#: commands/functioncmds.c:1868 #, c-format msgid "data type %s is a domain" msgstr "データ型%sはドメインです" -#: commands/functioncmds.c:1877 +#: commands/functioncmds.c:1908 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "FROM SQL関数の戻り値のデータ型は%sでなければなりません" -#: commands/functioncmds.c:1903 +#: commands/functioncmds.c:1934 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "TO SQL関数の戻り値データ型はこの変換関数のデータ型でなければなりません" -#: commands/functioncmds.c:1930 +#: commands/functioncmds.c:1961 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "型%s、言語\"%s\"の変換はすでに存在します" -#: commands/functioncmds.c:2016 +#: commands/functioncmds.c:2047 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "型%s、言語\"%s\"の変換は存在しません" -#: commands/functioncmds.c:2040 +#: commands/functioncmds.c:2071 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "関数%sはすでにスキーマ\"%s\"内に存在します" -#: commands/functioncmds.c:2091 +#: commands/functioncmds.c:2122 #, c-format msgid "no inline code specified" msgstr "インラインコードの指定がありません" -#: commands/functioncmds.c:2137 +#: commands/functioncmds.c:2168 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "言語\"%s\"ではインラインコード実行をサポートしていません" -#: commands/functioncmds.c:2232 +#: commands/functioncmds.c:2263 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" msgstr[0] "プロシージャには %d 個以上の引数を渡すことはできません" -#: commands/indexcmds.c:647 +#: commands/indexcmds.c:659 #, c-format msgid "must specify at least one column" msgstr "少なくとも1つの列を指定しなければなりません" -#: commands/indexcmds.c:651 +#: commands/indexcmds.c:663 #, c-format msgid "cannot use more than %d columns in an index" msgstr "インデックスには%dを超える列を使用できません" -#: commands/indexcmds.c:694 +#: commands/indexcmds.c:712 #, c-format msgid "cannot create index on relation \"%s\"" msgstr "リレーション\"%s\"のインデックスを作成できません" -#: commands/indexcmds.c:720 +#: commands/indexcmds.c:738 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "パーティション親テーブル\"%s\"には CREATE INDEX CONCURRENTLY は実行できません" -#: commands/indexcmds.c:730 +#: commands/indexcmds.c:748 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "他のセッションの一時テーブルに対するインデックスを作成できません" -#: commands/indexcmds.c:768 commands/tablecmds.c:806 commands/tablespace.c:1178 +#: commands/indexcmds.c:786 commands/tablecmds.c:891 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "パーティション親リレーションにはデフォルトテーブル空間は指定できません" -#: commands/indexcmds.c:800 commands/tablecmds.c:837 commands/tablecmds.c:3564 +#: commands/indexcmds.c:818 commands/tablecmds.c:922 commands/tablecmds.c:3709 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "共有リレーションのみをpg_globalテーブル空間に格納することができます" -#: commands/indexcmds.c:833 +#: commands/indexcmds.c:851 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "古いメソッド\"rtree\"をアクセスメソッド\"gist\"に置換しています" -#: commands/indexcmds.c:854 +#: commands/indexcmds.c:872 #, c-format msgid "access method \"%s\" does not support unique indexes" -msgstr "アクセスメソッド\"%s\"では一意性インデックスをサポートしていません" +msgstr "アクセスメソッド\"%s\"ではユニークインデックスをサポートしていません" -#: commands/indexcmds.c:859 +#: commands/indexcmds.c:877 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "アクセスメソッド\"%s\"では包含列をサポートしていません" -#: commands/indexcmds.c:864 +#: commands/indexcmds.c:882 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "アクセスメソッド\"%s\"は複数列インデックスをサポートしません" -#: commands/indexcmds.c:869 +#: commands/indexcmds.c:887 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "アクセスメソッド\"%s\"は排除制約をサポートしていません" -#: commands/indexcmds.c:998 +#: commands/indexcmds.c:892 #, c-format -msgid "cannot match partition key to an index using access method \"%s\"" -msgstr "パーティションキーはアクセスメソッド\"%s\"を使っているインデックスには適合させられません" +msgid "access method \"%s\" does not support WITHOUT OVERLAPS constraints" +msgstr "アクセスメソッド\"%s\"はWITHOUT OVERLAPS制約をサポートしていません" -#: commands/indexcmds.c:1008 +#: commands/indexcmds.c:1019 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "パーティションキー定義では %s 制約はサポートしていません" -#: commands/indexcmds.c:1010 +#: commands/indexcmds.c:1021 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "%s 制約はパーティションキーが式を含む場合は使用できません" -#: commands/indexcmds.c:1060 +#: commands/indexcmds.c:1056 commands/indexcmds.c:2469 commands/indexcmds.c:2488 executor/execReplication.c:329 parser/parse_cte.c:303 parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1410 utils/adt/array_userfuncs.c:1553 utils/adt/arrayfuncs.c:3864 utils/adt/arrayfuncs.c:4419 utils/adt/arrayfuncs.c:6440 utils/adt/rowtypes.c:1220 +#, c-format +msgid "could not identify an equality operator for type %s" +msgstr "型%sの等価演算子を特定できませんでした" + +#: commands/indexcmds.c:1057 commands/indexcmds.c:2491 +#, c-format +msgid "There is no suitable operator in operator family \"%s\" for access method \"%s\"." +msgstr "アクセスメソッド\"%2$s\"に対する演算子族\"%1$s\"に適切な演算子がありません。" + +#: commands/indexcmds.c:1077 #, c-format msgid "cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"" msgstr "パーティションキーの、列\"%s\"上のインデックスへの適合を非等価演算子\"%s\"を使って行うことはできません" -#: commands/indexcmds.c:1076 +#: commands/indexcmds.c:1093 #, c-format msgid "unique constraint on partitioned table must include all partitioning columns" msgstr "パーティション親テーブル上のユニーク制約はすべてのパーティショニング列を含まなければなりません" -#: commands/indexcmds.c:1077 +#: commands/indexcmds.c:1094 #, c-format msgid "%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key." msgstr "テーブル\"%2$s\"上の%1$s制約にパーティションキーの一部である列\"%3$s\"が含まれていません。" -#: commands/indexcmds.c:1096 commands/indexcmds.c:1115 +#: commands/indexcmds.c:1116 commands/indexcmds.c:1147 #, c-format msgid "index creation on system columns is not supported" msgstr "システム列へのインデックス作成はサポートされていません" -#: commands/indexcmds.c:1344 tcop/utility.c:1515 +#: commands/indexcmds.c:1123 +#, c-format +msgid "primary keys on virtual generated columns are not supported" +msgstr "仮想生成列に対する主キーはサポートされていません" + +#: commands/indexcmds.c:1125 commands/indexcmds.c:1164 +#, c-format +msgid "unique constraints on virtual generated columns are not supported" +msgstr "一意性制約は仮想生成列ではサポートされていません" + +#: commands/indexcmds.c:1126 commands/indexcmds.c:1165 +#, c-format +msgid "indexes on virtual generated columns are not supported" +msgstr "仮想生成列に対するインデックスはサポートされていません" + +#: commands/indexcmds.c:1397 tcop/utility.c:1518 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "パーティション親テーブル\"%s\"にはユニークインデックスを構築できません" -#: commands/indexcmds.c:1346 tcop/utility.c:1517 +#: commands/indexcmds.c:1399 tcop/utility.c:1520 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "テーブル\"%s\"は外部テーブルを子テーブルとして含んでいます" -#: commands/indexcmds.c:1831 +#: commands/indexcmds.c:1857 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "インデックスの述部の関数はIMMUTABLEマークが必要です" -#: commands/indexcmds.c:1910 parser/parse_utilcmd.c:2494 parser/parse_utilcmd.c:2629 +#: commands/indexcmds.c:1954 parser/parse_utilcmd.c:2714 parser/parse_utilcmd.c:2897 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "キーとして指名された列\"%s\"は存在しません" -#: commands/indexcmds.c:1934 parser/parse_utilcmd.c:1782 +#: commands/indexcmds.c:1978 parser/parse_utilcmd.c:1967 #, c-format msgid "expressions are not supported in included columns" msgstr "包含列では式はサポートされません" -#: commands/indexcmds.c:1975 +#: commands/indexcmds.c:2019 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "式インデックスの関数はIMMUTABLEマークが必要です" -#: commands/indexcmds.c:1990 +#: commands/indexcmds.c:2034 #, c-format msgid "including column does not support a collation" msgstr "包含列は照合順序をサポートしません" -#: commands/indexcmds.c:1994 +#: commands/indexcmds.c:2038 #, c-format msgid "including column does not support an operator class" msgstr "包含列は演算子クラスをサポートしません" -#: commands/indexcmds.c:1998 +#: commands/indexcmds.c:2042 #, c-format msgid "including column does not support ASC/DESC options" msgstr "包含列は ASC/DESC オプションをサポートしません" -#: commands/indexcmds.c:2002 +#: commands/indexcmds.c:2046 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "包含列は NULLS FIRST/LAST オプションをサポートしません" -#: commands/indexcmds.c:2044 +#: commands/indexcmds.c:2089 #, c-format msgid "could not determine which collation to use for index expression" msgstr "インデックス式で使用する照合順序を特定できませんでした" -#: commands/indexcmds.c:2052 commands/tablecmds.c:18078 commands/typecmds.c:811 parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3918 utils/adt/misc.c:630 +#: commands/indexcmds.c:2097 commands/tablecmds.c:19886 commands/typecmds.c:812 parser/parse_expr.c:2801 parser/parse_type.c:568 parser/parse_utilcmd.c:4043 utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "%s 型では照合順序はサポートされません" -#: commands/indexcmds.c:2117 +#: commands/indexcmds.c:2164 #, c-format msgid "operator %s is not commutative" msgstr "演算子 %s は可換ではありません" -#: commands/indexcmds.c:2119 +#: commands/indexcmds.c:2166 #, c-format msgid "Only commutative operators can be used in exclusion constraints." msgstr "排除制約で使えるのは可換演算子だけです" -#: commands/indexcmds.c:2145 +#: commands/indexcmds.c:2176 #, c-format msgid "operator %s is not a member of operator family \"%s\"" msgstr "演算子%sは演算子族\"%s\"のメンバーではありません" -#: commands/indexcmds.c:2148 +#: commands/indexcmds.c:2179 #, c-format msgid "The exclusion operator must be related to the index operator class for the constraint." msgstr "この排除に使用する演算子はこの制約に使用するインデックス演算子に関連付けられている必要があります。" -#: commands/indexcmds.c:2183 +#: commands/indexcmds.c:2228 #, c-format msgid "access method \"%s\" does not support ASC/DESC options" msgstr "アクセスメソッド\"%s\"はASC/DESCオプションをサポートしません" -#: commands/indexcmds.c:2188 +#: commands/indexcmds.c:2233 #, c-format msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "アクセスメソッド\"%s\"はNULLS FIRST/LASTオプションをサポートしません" -#: commands/indexcmds.c:2232 commands/tablecmds.c:18103 commands/tablecmds.c:18109 commands/typecmds.c:2311 +#: commands/indexcmds.c:2277 commands/tablecmds.c:19911 commands/tablecmds.c:19917 commands/typecmds.c:2341 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "アクセスメソッド\"%2$s\"にはデータ型%1$s用のデフォルトの演算子クラスがありません" -#: commands/indexcmds.c:2234 +#: commands/indexcmds.c:2279 #, c-format msgid "You must specify an operator class for the index or define a default operator class for the data type." msgstr "このインデックスの演算子クラスを指定するか、あるいはこのデータ型のデフォルト演算子クラスを定義しなければなりません。" -#: commands/indexcmds.c:2263 commands/indexcmds.c:2271 commands/opclasscmds.c:204 +#: commands/indexcmds.c:2308 commands/indexcmds.c:2316 commands/opclasscmds.c:205 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "アクセスメソッド\"%2$s\"用の演算子クラス\"%1$s\"は存在しません" -#: commands/indexcmds.c:2285 commands/typecmds.c:2299 +#: commands/indexcmds.c:2330 commands/typecmds.c:2329 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "演算子クラス\"%s\"はデータ型%sを受け付けません" -#: commands/indexcmds.c:2375 +#: commands/indexcmds.c:2420 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "データ型%sには複数のデフォルトの演算子クラスがあります" -#: commands/indexcmds.c:2703 +#: commands/indexcmds.c:2470 commands/indexcmds.c:2489 +#, c-format +msgid "could not identify an overlaps operator for type %s" +msgstr "型%sの重複検出演算子を特定できませんでした" + +#: commands/indexcmds.c:2471 commands/indexcmds.c:2490 +#, c-format +msgid "could not identify a contained-by operator for type %s" +msgstr "型%sの被包含演算子を特定できませんでした" + +#: commands/indexcmds.c:2472 commands/tablecmds.c:10302 +#, c-format +msgid "Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\"." +msgstr "演算子ファミリー\"%2$s\"、入力型 %3$s、アクセスメソッド\"%4$s\"に対応する比較方式%1$dを変換できませんでした。" + +#: commands/indexcmds.c:2812 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "認識できないREINDEXのオプション \"%s\"" -#: commands/indexcmds.c:2935 +#: commands/indexcmds.c:3044 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "テーブル\"%s\"には並行インデックス再作成が可能なインデックスがありません" -#: commands/indexcmds.c:2949 +#: commands/indexcmds.c:3058 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "テーブル\"%s\"には再構築すべきインデックスはありません" -#: commands/indexcmds.c:2996 commands/indexcmds.c:3507 commands/indexcmds.c:3637 +#: commands/indexcmds.c:3105 commands/indexcmds.c:3616 commands/indexcmds.c:3746 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "システムカタログではインデックスの並行再構築はできません" -#: commands/indexcmds.c:3020 +#: commands/indexcmds.c:3129 #, c-format msgid "can only reindex the currently open database" msgstr "現在オープンしているデータベースのみをインデックス再構築することができます" -#: commands/indexcmds.c:3112 +#: commands/indexcmds.c:3221 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "システムカタログではインデックスの並行再構築はできません、全てスキップします" -#: commands/indexcmds.c:3145 +#: commands/indexcmds.c:3254 #, c-format msgid "cannot move system relations, skipping all" msgstr "システムリレーションは移動できません、すべてスキップします" -#: commands/indexcmds.c:3191 +#: commands/indexcmds.c:3300 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "パーティションテーブル\"%s.%s\"のインデックス再構築中" -#: commands/indexcmds.c:3194 +#: commands/indexcmds.c:3303 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "パーティションインデックス\"%s.%s\"のインデックス再構築中" -#: commands/indexcmds.c:3387 commands/indexcmds.c:4255 +#: commands/indexcmds.c:3496 commands/indexcmds.c:4388 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "テーブル\"%s.%s\"のインデックス再構築が完了しました" -#: commands/indexcmds.c:3539 commands/indexcmds.c:3592 +#: commands/indexcmds.c:3648 commands/indexcmds.c:3701 #, c-format msgid "skipping reindex of invalid index \"%s.%s\"" msgstr "無効なインデックス\"%s.%s\"の再構築をスキップします" -#: commands/indexcmds.c:3542 commands/indexcmds.c:3595 +#: commands/indexcmds.c:3651 commands/indexcmds.c:3704 #, c-format msgid "Use DROP INDEX or REINDEX INDEX." msgstr "DROP INDEXあるいはREINDEX INDEXを使用してください。" -#: commands/indexcmds.c:3546 +#: commands/indexcmds.c:3655 #, c-format msgid "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" msgstr "排他制約インデックス\"%s.%s\"を並行再構築することはできません、スキップします " -#: commands/indexcmds.c:3702 +#: commands/indexcmds.c:3811 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "このタイプのリレーションでインデックス並列再構築はできません" -#: commands/indexcmds.c:3720 +#: commands/indexcmds.c:3829 #, c-format msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "テーブルスペース\"%s\"への非共有リレーションの移動はできません" -#: commands/indexcmds.c:4236 commands/indexcmds.c:4248 +#: commands/indexcmds.c:4369 commands/indexcmds.c:4381 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr " インデックス\"%s.%s\"の再構築が完了しました " -#: commands/indexcmds.c:4238 commands/indexcmds.c:4257 +#: commands/indexcmds.c:4371 commands/indexcmds.c:4390 #, c-format msgid "%s." msgstr "%s。" @@ -8973,252 +9014,272 @@ msgstr "%s。" msgid "cannot lock relation \"%s\"" msgstr "リレーション\"%s\"はロックできません" -#: commands/matview.c:190 +#: commands/matview.c:208 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "実体化ビューにデータが投入されていない場合はCONCURRENTLYを使用することはできません" -#: commands/matview.c:196 gram.y:18967 +#: commands/matview.c:214 gram.y:19148 #, c-format msgid "%s and %s options cannot be used together" msgstr "%sオプションと%sオプションとを同時に使用することはできません" -#: commands/matview.c:253 +#: commands/matview.c:273 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "実体化ビュー\"%s\"を平行的に最新化することはできません" -#: commands/matview.c:256 +#: commands/matview.c:276 #, c-format msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view." -msgstr "実体化ビュー上の1つ以上の列に対してWHERE句を持たないUNIQUEインデックスを作成してください。" +msgstr "実体化ビュー上の1つ以上の列に対してWHERE句を持たないユニークインデックスを作成してください。" -#: commands/matview.c:650 +#: commands/matview.c:683 #, c-format msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns" msgstr "実体化ビュー\"%s\"に対する新しいデータにはNULL列を持たない重複行があります" -#: commands/matview.c:652 +#: commands/matview.c:685 #, c-format msgid "Row: %s" msgstr "行: %s" -#: commands/opclasscmds.c:123 +#: commands/matview.c:839 +#, c-format +msgid "could not find suitable unique index on materialized view" +msgstr "実体化ビューに適切なユニークインデックスがありませんでした" + +#: commands/opclasscmds.c:124 #, c-format msgid "operator family \"%s\" does not exist for access method \"%s\"" msgstr "アクセスメソッド\"%2$s\"用の演算子族\"%1$s\"は存在しません" -#: commands/opclasscmds.c:266 +#: commands/opclasscmds.c:267 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists" msgstr "アクセスメソッド\"%2$s\"の演算子族\"%1$s\"はすでに存在します" -#: commands/opclasscmds.c:415 +#: commands/opclasscmds.c:416 #, c-format msgid "must be superuser to create an operator class" msgstr "演算子クラスを作成するにはスーパーユーザーである必要があります" -#: commands/opclasscmds.c:492 commands/opclasscmds.c:909 commands/opclasscmds.c:1055 +#: commands/opclasscmds.c:493 commands/opclasscmds.c:910 commands/opclasscmds.c:1056 #, c-format msgid "invalid operator number %d, must be between 1 and %d" msgstr "演算子番号%dが不正です。1から%dまででなければなりません" -#: commands/opclasscmds.c:537 commands/opclasscmds.c:959 commands/opclasscmds.c:1071 +#: commands/opclasscmds.c:538 commands/opclasscmds.c:960 commands/opclasscmds.c:1072 #, c-format msgid "invalid function number %d, must be between 1 and %d" msgstr "演算子番号%dが不正です、1と%dの間でなければなりません" -#: commands/opclasscmds.c:566 +#: commands/opclasscmds.c:567 #, c-format msgid "storage type specified more than once" msgstr "格納型が複数指定されました" -#: commands/opclasscmds.c:593 +#: commands/opclasscmds.c:594 #, c-format msgid "storage type cannot be different from data type for access method \"%s\"" msgstr "アクセスメソッド\"%s\"用のデータ型と異なる格納型を使用できません" -#: commands/opclasscmds.c:609 +#: commands/opclasscmds.c:610 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists" msgstr "アクセスメソッド\"%2$s\"の演算子クラス\"%1$s\"はすでに存在します" -#: commands/opclasscmds.c:637 +#: commands/opclasscmds.c:638 #, c-format msgid "could not make operator class \"%s\" be default for type %s" msgstr "演算子クラス\"%s\"を型%sのデフォルトにすることができませんでした" -#: commands/opclasscmds.c:640 +#: commands/opclasscmds.c:641 #, c-format msgid "Operator class \"%s\" already is the default." msgstr "演算子クラス\"%s\"はすでにデフォルトです。" -#: commands/opclasscmds.c:800 +#: commands/opclasscmds.c:801 #, c-format msgid "must be superuser to create an operator family" msgstr "演算子族を作成するにはスーパーユーザーである必要があります" -#: commands/opclasscmds.c:860 +#: commands/opclasscmds.c:861 #, c-format msgid "must be superuser to alter an operator family" msgstr "演算子族を更新するにはスーパーユーザーである必要があります" -#: commands/opclasscmds.c:918 +#: commands/opclasscmds.c:919 #, c-format msgid "operator argument types must be specified in ALTER OPERATOR FAMILY" msgstr "ALTER OPERATOR FAMILYでは演算子の引数型の指定が必要です" -#: commands/opclasscmds.c:993 +#: commands/opclasscmds.c:994 #, c-format msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY" msgstr "ALTER OPERATOR FAMILYではSTORAGEを指定できません" -#: commands/opclasscmds.c:1127 +#: commands/opclasscmds.c:1128 #, c-format msgid "one or two argument types must be specified" msgstr "1または2つの引数型が指定する必要があります" -#: commands/opclasscmds.c:1153 +#: commands/opclasscmds.c:1154 #, c-format msgid "index operators must be binary" msgstr "インデックス演算子は二項演算子でなければなりません" -#: commands/opclasscmds.c:1172 +#: commands/opclasscmds.c:1173 #, c-format msgid "access method \"%s\" does not support ordering operators" msgstr "アクセスメソッド\"%s\"は並べ替え演算子をサポートしていません" -#: commands/opclasscmds.c:1183 +#: commands/opclasscmds.c:1184 #, c-format msgid "index search operators must return boolean" msgstr "インデックス検索演算子はブール型を返す必要があります" -#: commands/opclasscmds.c:1223 +#: commands/opclasscmds.c:1224 #, c-format msgid "associated data types for operator class options parsing functions must match opclass input type" msgstr "演算子クラスのパース関数に対応するデータ型は演算子クラスの入力型と一致している必要があります" -#: commands/opclasscmds.c:1230 +#: commands/opclasscmds.c:1231 #, c-format msgid "left and right associated data types for operator class options parsing functions must match" msgstr "演算子クラスオプションのパース関数の左右辺の対応するデータ型は一致している必要があります" -#: commands/opclasscmds.c:1238 +#: commands/opclasscmds.c:1239 #, c-format msgid "invalid operator class options parsing function" msgstr "不正な演算子クラスオプションのパース関数" -#: commands/opclasscmds.c:1239 +#: commands/opclasscmds.c:1240 #, c-format msgid "Valid signature of operator class options parsing function is %s." msgstr "演算子クラスオプションのパース関数の正しいシグネチャは %s です。" -#: commands/opclasscmds.c:1258 +#: commands/opclasscmds.c:1259 +#, c-format +msgid "ordering comparison functions must have two arguments" +msgstr "順序付け比較関数は2つの引数を取る必要があります" + +#: commands/opclasscmds.c:1263 +#, c-format +msgid "ordering comparison functions must return integer" +msgstr "順序付け比較関数は整数を返さなければなりません" + +#: commands/opclasscmds.c:1280 +#, c-format +msgid "ordering sort support functions must accept type \"internal\"" +msgstr "順序付けソートサポート関数は\"internal\"型を取らなければなりません" + +#: commands/opclasscmds.c:1284 #, c-format -msgid "btree comparison functions must have two arguments" -msgstr "btree比較関数は2つの引数を取る必要があります" +msgid "ordering sort support functions must return void" +msgstr "順序付けソートサポート関数はvoidを返さなければなりません" -#: commands/opclasscmds.c:1262 +#: commands/opclasscmds.c:1295 #, c-format -msgid "btree comparison functions must return integer" -msgstr "btree比較関数は整数を返さなければなりません" +msgid "ordering in_range functions must have five arguments" +msgstr "順序付け in_range 関数は5つの引数を取る必要があります" -#: commands/opclasscmds.c:1279 +#: commands/opclasscmds.c:1299 #, c-format -msgid "btree sort support functions must accept type \"internal\"" -msgstr "btreeソートサポート関数は\"internal\"型を取らなければなりません" +msgid "ordering in_range functions must return boolean" +msgstr "順序付け in_range 関数はブール型を返す必要があります" -#: commands/opclasscmds.c:1283 +#: commands/opclasscmds.c:1315 #, c-format -msgid "btree sort support functions must return void" -msgstr "btreeソートサポート関数はvoidを返さなければなりません" +msgid "ordering equal image functions must have one argument" +msgstr "順序付け等価イメージ関数は1つの引数を取る必要があります" -#: commands/opclasscmds.c:1294 +#: commands/opclasscmds.c:1319 #, c-format -msgid "btree in_range functions must have five arguments" -msgstr "btree in_range 関数は5つの引数を取る必要があります" +msgid "ordering equal image functions must return boolean" +msgstr "順序付け等価イメージ関数はブール型を返す必要があります" -#: commands/opclasscmds.c:1298 +#: commands/opclasscmds.c:1332 #, c-format -msgid "btree in_range functions must return boolean" -msgstr "btree in_range 関数はブール型を返す必要があります" +msgid "ordering equal image functions must not be cross-type" +msgstr "順序付け等価イメージ関数は異なる型の引数を取ってはなりません" -#: commands/opclasscmds.c:1314 +#: commands/opclasscmds.c:1340 #, c-format -msgid "btree equal image functions must have one argument" -msgstr "btreeの equal image 関数は1つの引数を取る必要があります" +msgid "btree skip support functions must accept type \"internal\"" +msgstr "btreeスキップサポート関数は\"internal\"型を取らなければなりません" -#: commands/opclasscmds.c:1318 +#: commands/opclasscmds.c:1344 #, c-format -msgid "btree equal image functions must return boolean" -msgstr "btreeの euqal image 関数はブール型を返す必要があります" +msgid "btree skip support functions must return void" +msgstr "btreeスキップサポート関数はvoidを返さなければなりません" -#: commands/opclasscmds.c:1331 +#: commands/opclasscmds.c:1357 #, c-format -msgid "btree equal image functions must not be cross-type" -msgstr "btreeの equal image 関数は同じ型の引数を取る必要があります" +msgid "btree skip support functions must not be cross-type" +msgstr "btreeスキップサポート関数は異なる型の引数を取ってはなりません" -#: commands/opclasscmds.c:1341 +#: commands/opclasscmds.c:1367 #, c-format msgid "hash function 1 must have one argument" msgstr "ハッシュ関数1は引数を1つ取る必要があります" -#: commands/opclasscmds.c:1345 +#: commands/opclasscmds.c:1371 #, c-format msgid "hash function 1 must return integer" msgstr "ハッシュ関数1は整数を返す必要があります" -#: commands/opclasscmds.c:1352 +#: commands/opclasscmds.c:1378 #, c-format msgid "hash function 2 must have two arguments" msgstr "ハッシュ関数2は2つの引数を取る必要があります" -#: commands/opclasscmds.c:1356 +#: commands/opclasscmds.c:1382 #, c-format msgid "hash function 2 must return bigint" msgstr "ハッシュ関数2は bigint を返す必要があります" -#: commands/opclasscmds.c:1381 +#: commands/opclasscmds.c:1407 #, c-format msgid "associated data types must be specified for index support function" msgstr "インデックスサポート関数に対して関連データ型を指定する必要があります" -#: commands/opclasscmds.c:1406 +#: commands/opclasscmds.c:1432 #, c-format msgid "function number %d for (%s,%s) appears more than once" msgstr "(%2$s,%3$s)に対応する演算子番号%1$dが複数あります" -#: commands/opclasscmds.c:1413 +#: commands/opclasscmds.c:1439 #, c-format msgid "operator number %d for (%s,%s) appears more than once" msgstr "(%2$s,%3$s)用の演算子番号%1$dが複数あります" -#: commands/opclasscmds.c:1459 +#: commands/opclasscmds.c:1485 #, c-format msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "演算子%d(%s,%s)はすでに演算子族\"%s\"に存在します" -#: commands/opclasscmds.c:1565 +#: commands/opclasscmds.c:1614 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "関数%d(%s,%s)はすでに演算子族\"%s\"内に存在します" -#: commands/opclasscmds.c:1646 +#: commands/opclasscmds.c:1769 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "演算子%d(%s,%s)は演算子族\"%s\"内にありません" -#: commands/opclasscmds.c:1686 +#: commands/opclasscmds.c:1809 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "関数%d(%s,%s)は演算子族\"%s\"内に存在しません" -#: commands/opclasscmds.c:1717 +#: commands/opclasscmds.c:1840 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "アクセスメソッド\"%2$s\"用の演算子クラス\"%1$s\"はスキーマ\"%3$s\"内にすでに存在します" -#: commands/opclasscmds.c:1740 +#: commands/opclasscmds.c:1863 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "アクセスメソッド\"%2$s\"用の演算子族\"%1$s\"はスキーマ\"%3$s\"内にすでに存在します" @@ -9288,7 +9349,7 @@ msgstr "演算子の属性\"%s\"は変更できません" msgid "operator attribute \"%s\" cannot be changed if it has already been set" msgstr "演算子の属性\"%s\"は、すでに設定されている場合には変更できません" -#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 commands/tablecmds.c:1728 commands/tablecmds.c:2328 commands/tablecmds.c:3675 commands/tablecmds.c:6613 commands/tablecmds.c:9645 commands/tablecmds.c:17665 commands/tablecmds.c:17700 commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1442 rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 commands/tablecmds.c:1799 commands/tablecmds.c:2399 commands/tablecmds.c:3823 commands/tablecmds.c:6792 commands/tablecmds.c:10058 commands/tablecmds.c:19467 commands/tablecmds.c:19502 commands/trigger.c:318 commands/trigger.c:1337 commands/trigger.c:1447 rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "権限がありません: \"%s\"はシステムカタログです" @@ -9328,52 +9389,52 @@ msgstr "テーブル\"%2$s\"に対するポリシ\"%1$s\"は存在しません" msgid "only USING expression allowed for SELECT, DELETE" msgstr "SELECT、DELETEにはUSING式のみが指定可能です" -#: commands/portalcmds.c:60 commands/portalcmds.c:181 commands/portalcmds.c:232 +#: commands/portalcmds.c:63 commands/portalcmds.c:192 commands/portalcmds.c:243 #, c-format msgid "invalid cursor name: must not be empty" msgstr "カーソル名が不正です: 空ではいけません" -#: commands/portalcmds.c:72 +#: commands/portalcmds.c:75 #, c-format msgid "cannot create a cursor WITH HOLD within security-restricted operation" msgstr "セキュリティー制限操作中は、WITH HOLD指定のカーソルを作成できません" -#: commands/portalcmds.c:189 commands/portalcmds.c:242 executor/execCurrent.c:70 utils/adt/xml.c:2873 utils/adt/xml.c:3043 +#: commands/portalcmds.c:200 commands/portalcmds.c:253 executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "カーソル\"%s\"は存在しません" -#: commands/prepare.c:72 +#: commands/prepare.c:75 #, c-format msgid "invalid statement name: must not be empty" msgstr "不正な文の名前: 空ではいけません" -#: commands/prepare.c:227 commands/prepare.c:232 +#: commands/prepare.c:231 commands/prepare.c:236 #, c-format msgid "prepared statement is not a SELECT" msgstr "準備された文はSELECTではありません" -#: commands/prepare.c:292 +#: commands/prepare.c:296 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "準備された文\"%s\"のパラメータ数が間違っています" -#: commands/prepare.c:294 +#: commands/prepare.c:298 #, c-format msgid "Expected %d parameters but got %d." msgstr "%dパラメータを想定しましたが、%dパラメータでした" -#: commands/prepare.c:327 +#: commands/prepare.c:331 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "パラメータ$%dの型%sを想定している型%sに強制することができません" -#: commands/prepare.c:411 +#: commands/prepare.c:415 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "準備された文\"%s\"はすでに存在します" -#: commands/prepare.c:450 +#: commands/prepare.c:454 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "準備された文\"%s\"は存在しません" @@ -9383,200 +9444,205 @@ msgstr "準備された文\"%s\"は存在しません" msgid "must be superuser to create custom procedural language" msgstr "手続き言語を生成するためにはスーパーユーザーである必要があります" -#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 postmaster/postmaster.c:1210 utils/init/miscinit.c:1811 +#: commands/publicationcmds.c:130 libpq/auth-oauth.c:850 postmaster/postmaster.c:1130 postmaster/postmaster.c:1232 utils/init/miscinit.c:1870 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "パラメータ\"%s\"のリスト構文が不正です" -#: commands/publicationcmds.c:143 +#: commands/publicationcmds.c:149 #, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" msgstr "パブリケーションオプション\"%s\"に対する認識できない値: \"%s\"" -#: commands/publicationcmds.c:157 +#: commands/publicationcmds.c:170 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "識別できないパブリケーションのパラメータ: \"%s\"" -#: commands/publicationcmds.c:198 +#: commands/publicationcmds.c:211 #, c-format msgid "no schema has been selected for CURRENT_SCHEMA" msgstr "SURRENT_SCHEMAでスキーマの選択ができませんでした" -#: commands/publicationcmds.c:495 +#: commands/publicationcmds.c:592 msgid "System columns are not allowed." msgstr "システム列は使用できません。" -#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 commands/publicationcmds.c:524 +#: commands/publicationcmds.c:599 commands/publicationcmds.c:604 commands/publicationcmds.c:621 msgid "User-defined operators are not allowed." msgstr "ユーザー定義演算子は使用できません。" -#: commands/publicationcmds.c:548 +#: commands/publicationcmds.c:645 msgid "Only columns, constants, built-in operators, built-in data types, built-in collations, and immutable built-in functions are allowed." msgstr "列、定数、組み込み演算子、組み込みデータ型、組み込み照合順序、そして不変組み込み関数のみ使用可能です。" -#: commands/publicationcmds.c:560 +#: commands/publicationcmds.c:657 msgid "User-defined types are not allowed." msgstr "ユーザー定義型は使用できません。" -#: commands/publicationcmds.c:563 +#: commands/publicationcmds.c:660 msgid "User-defined or built-in mutable functions are not allowed." msgstr "ユーザー定義または組み込みの不変関数は使用できません。" -#: commands/publicationcmds.c:566 +#: commands/publicationcmds.c:663 msgid "User-defined collations are not allowed." msgstr "ユーザー定義照合順序は使用できません。" -#: commands/publicationcmds.c:576 +#: commands/publicationcmds.c:673 #, c-format msgid "invalid publication WHERE expression" msgstr "パブリケーションのWHERE式が不正です" -#: commands/publicationcmds.c:629 +#: commands/publicationcmds.c:726 #, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" msgstr "リレーション\"%s\"に対してはパブリケーションのWHERE句は使用できません" -#: commands/publicationcmds.c:631 +#: commands/publicationcmds.c:728 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." msgstr "%sが偽のときはWHERE句をパーティション親テーブルに対して使用することはできません。" -#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 +#: commands/publicationcmds.c:801 commands/publicationcmds.c:815 #, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" msgstr "パブリケーション\"%3$s\"のリレーション\"%1$s.%2$s\"に対して列リストを使用することはできません" -#: commands/publicationcmds.c:705 +#: commands/publicationcmds.c:804 #, c-format msgid "Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements." msgstr "FOR TABLES IN SCHEMA要素を含むパブリケーションで列リストは指定できません。" -#: commands/publicationcmds.c:719 +#: commands/publicationcmds.c:818 #, c-format msgid "Column lists cannot be specified for partitioned tables when %s is false." msgstr "%sが偽のときはパーティション親テーブルに対して列リストを使用できません。" -#: commands/publicationcmds.c:754 +#: commands/publicationcmds.c:855 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "FOR ALL TABLE 指定のパブリケーションを生成するためにはスーパーユーザーである必要があります" -#: commands/publicationcmds.c:825 +#: commands/publicationcmds.c:930 #, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" msgstr "FOR TABLES IN SCHEMA設定のパブリケーションを作成するにはスーパーユーザーである必要があります" -#: commands/publicationcmds.c:861 +#: commands/publicationcmds.c:966 #, c-format msgid "\"wal_level\" is insufficient to publish logical changes" msgstr "\"wal_level\"が論理更新情報のパブリッシュには不十分です" -#: commands/publicationcmds.c:862 +#: commands/publicationcmds.c:967 #, c-format msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." msgstr "サブスクリプションを作成する前に\"wal_level\"を\"logical\"に設定にしてください。" -#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 +#: commands/publicationcmds.c:1067 commands/publicationcmds.c:1075 #, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" msgstr "パブリケーション\"%2$s\"に対してパラメーター\"%1$s\"を偽に設定することはできません" -#: commands/publicationcmds.c:961 +#: commands/publicationcmds.c:1070 #, c-format msgid "The publication contains a WHERE clause for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "このパブリケーションはパーティション親テーブル\"%s\"に対するWHERE句を含んでいますが、これは\"%s\" が偽の場合は許可されません。" -#: commands/publicationcmds.c:969 +#: commands/publicationcmds.c:1078 #, c-format msgid "The publication contains a column list for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "このパブリケーションはパーティション親テーブルに\"%s\"対する列リストを含んでいますが、これは\"%s\" が偽の場合は許可されません。" -#: commands/publicationcmds.c:1292 +#: commands/publicationcmds.c:1399 #, c-format msgid "cannot add schema to publication \"%s\"" msgstr "パブリケーション\"%s\"にはスキーマは追加できません" -#: commands/publicationcmds.c:1294 +#: commands/publicationcmds.c:1401 #, c-format msgid "Schemas cannot be added if any tables that specify a column list are already part of the publication." msgstr "カラムリストが指定されているテーブルがパブリケーションに含まれている場合はスキーマの追加ができません。" -#: commands/publicationcmds.c:1342 +#: commands/publicationcmds.c:1449 #, c-format msgid "must be superuser to add or set schemas" msgstr "スキーマを追加または設定するにはスーパーユーザーである必要があります" -#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 +#: commands/publicationcmds.c:1458 commands/publicationcmds.c:1466 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "パブリケーション\"%s\"は FOR ALL TABLES と定義されています" -#: commands/publicationcmds.c:1353 +#: commands/publicationcmds.c:1460 #, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." msgstr "FOR ALL TABLES指定のパブリケーションではスキーマの追加や削除はできません。" -#: commands/publicationcmds.c:1361 +#: commands/publicationcmds.c:1468 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "FOR ALL TABLES指定のパブリケーションではテーブルの追加や削除はできません。" -#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 +#: commands/publicationcmds.c:1492 commands/publicationcmds.c:1531 commands/publicationcmds.c:2068 utils/cache/lsyscache.c:3774 #, c-format msgid "publication \"%s\" does not exist" msgstr "パブリケーション\"%s\"は存在しません" -#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 +#: commands/publicationcmds.c:1694 commands/publicationcmds.c:1757 #, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" msgstr "テーブル\"%s\"でWHERE句が衝突しているか重複しています" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 +#: commands/publicationcmds.c:1701 commands/publicationcmds.c:1769 #, c-format msgid "conflicting or redundant column lists for table \"%s\"" msgstr "テーブル\"%s\"で列リストが衝突しているか重複しています" -#: commands/publicationcmds.c:1796 +#: commands/publicationcmds.c:1903 #, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" msgstr "ALTER PUBLICATION ... DROPでは、列リストは指定できません" -#: commands/publicationcmds.c:1808 +#: commands/publicationcmds.c:1915 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "リレーション\"%s\"はパブリケーションの一部ではありません" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1922 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "テーブルをパブリケーションから削除する際にはWHERE句を指定できません" -#: commands/publicationcmds.c:1875 +#: commands/publicationcmds.c:1982 #, c-format msgid "tables from schema \"%s\" are not part of the publication" msgstr "スキーマ\"%s\"のテーブルはこのパブリケーションに含まれてません" -#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 +#: commands/publicationcmds.c:2025 commands/publicationcmds.c:2032 #, c-format msgid "permission denied to change owner of publication \"%s\"" msgstr "パブリケーション\"%s\"の所有者を変更する権限がありません" -#: commands/publicationcmds.c:1920 +#: commands/publicationcmds.c:2027 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "FOR ALL TABLES設定のパブリケーションの所有者はスーパーユーザーである必要があります" -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:2034 #, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." msgstr "FOR TABLES IN SCHEMA設定のパブリケーションの所有者はスーパーユーザーでなければなりません。" -#: commands/publicationcmds.c:1993 +#: commands/publicationcmds.c:2100 #, c-format msgid "publication with OID %u does not exist" msgstr "OID %uのパブリケーションは存在しません" +#: commands/publicationcmds.c:2133 +#, c-format +msgid "%s requires a \"none\" or \"stored\" value" +msgstr "%sの値は\"none\"または\"stored\"である必要があります" + #: commands/schemacmds.c:109 commands/schemacmds.c:289 #, c-format msgid "unacceptable schema name \"%s\"" @@ -9618,127 +9684,127 @@ msgid "cannot set security label on relation \"%s\"" msgstr "リレーション\"%s\"のセキュリティラベルは設定できません" # (%s) -#: commands/sequence.c:741 +#: commands/sequence.c:748 #, c-format -msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" -msgstr "nextval: シーケンス\"%s\"の最大値(%lld)に達しました" +msgid "nextval: reached maximum value of sequence \"%s\" (%)" +msgstr "nextval: シーケンス\"%s\"の最大値(%)に達しました" -#: commands/sequence.c:760 +#: commands/sequence.c:767 #, c-format -msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" -msgstr "nextval: シーケンス\"%s\"の最小値(%lld)に達しました" +msgid "nextval: reached minimum value of sequence \"%s\" (%)" +msgstr "nextval: シーケンス\"%s\"の最小値(%)に達しました" -#: commands/sequence.c:879 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "本セッションでシーケンス\"%s\"のcurrvalはまだ定義されていません" -#: commands/sequence.c:898 commands/sequence.c:904 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "本セッションでlastvalはまだ定義されていません" -#: commands/sequence.c:984 +#: commands/sequence.c:991 #, c-format -msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" -msgstr "setval: 値%lldはシーケンス\"%s\"の範囲(%lld..%lld)外です\"" +msgid "setval: value % is out of bounds for sequence \"%s\" (%..%)" +msgstr "setval: 値%はシーケンス\"%s\"の範囲(%..%)外です\"" -#: commands/sequence.c:1347 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "不正なオプション SEQUENCE NAME" -#: commands/sequence.c:1373 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "識別列の型はsmallint、integerまたはbigintでなくてはなりません" -#: commands/sequence.c:1374 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "シーケンスの型はsmallint、integerまたはbigintでなくてはなりません" -#: commands/sequence.c:1408 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENTはゼロではいけません" -#: commands/sequence.c:1456 +#: commands/sequence.c:1466 #, c-format -msgid "MAXVALUE (%lld) is out of range for sequence data type %s" -msgstr "MAXVALUE (%lld) はシーケンスデータ型%sの範囲外です" +msgid "MAXVALUE (%) is out of range for sequence data type %s" +msgstr "MAXVALUE (%) はシーケンスデータ型%sの範囲外です" -#: commands/sequence.c:1488 +#: commands/sequence.c:1498 #, c-format -msgid "MINVALUE (%lld) is out of range for sequence data type %s" -msgstr "MINVALUE (%lld) はシーケンスデータ型%sの範囲外です" +msgid "MINVALUE (%) is out of range for sequence data type %s" +msgstr "MINVALUE (%) はシーケンスデータ型%sの範囲外です" -#: commands/sequence.c:1496 +#: commands/sequence.c:1506 #, c-format -msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" -msgstr "MINVALUE (%lld)はMAXVALUE (%lld)より小さくなければなりません" +msgid "MINVALUE (%) must be less than MAXVALUE (%)" +msgstr "MINVALUE (%)はMAXVALUE (%)より小さくなければなりません" -#: commands/sequence.c:1517 +#: commands/sequence.c:1527 #, c-format -msgid "START value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "STARTの値(%lld)はMINVALUE(%lld)より小さくすることはできません" +msgid "START value (%) cannot be less than MINVALUE (%)" +msgstr "STARTの値(%)はMINVALUE(%)より小さくすることはできません" -#: commands/sequence.c:1523 +#: commands/sequence.c:1533 #, c-format -msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "STARTの値(%lld)はMAXVALUE(%lld)より大きくすることはできません" +msgid "START value (%) cannot be greater than MAXVALUE (%)" +msgstr "STARTの値(%)はMAXVALUE(%)より大きくすることはできません" -#: commands/sequence.c:1547 +#: commands/sequence.c:1557 #, c-format -msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "RESTART の値(%lld)は MINVALUE(%lld) より小さくすることはできません" +msgid "RESTART value (%) cannot be less than MINVALUE (%)" +msgstr "RESTART の値(%)は MINVALUE(%) より小さくすることはできません" -#: commands/sequence.c:1553 +#: commands/sequence.c:1563 #, c-format -msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "RESTART の値(%lld)は MAXVALUE(%lld) より大きくすることはできません" +msgid "RESTART value (%) cannot be greater than MAXVALUE (%)" +msgstr "RESTART の値(%)は MAXVALUE(%) より大きくすることはできません" -#: commands/sequence.c:1564 +#: commands/sequence.c:1574 #, c-format -msgid "CACHE (%lld) must be greater than zero" -msgstr "CACHE(%lld)はゼロより大きくなければなりません" +msgid "CACHE (%) must be greater than zero" +msgstr "CACHE(%)はゼロより大きくなければなりません" -#: commands/sequence.c:1600 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "不正なOWNED BYオプションです" -#: commands/sequence.c:1601 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "OWNED BY table.column または OWNED BY NONEを指定してください。" -#: commands/sequence.c:1626 +#: commands/sequence.c:1636 #, c-format msgid "sequence cannot be owned by relation \"%s\"" msgstr "シーケンスの所有者をリレーション\"%s\"にはできません" -#: commands/sequence.c:1634 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "シーケンスは関連するテーブルと同じ所有者でなければなりません" -#: commands/sequence.c:1638 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "シーケンスは関連するテーブルと同じスキーマでなければなりません" -#: commands/sequence.c:1660 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "識別シーケンスの所有者は変更できません" -#: commands/sequence.c:1661 commands/tablecmds.c:14387 commands/tablecmds.c:17081 +#: commands/sequence.c:1671 commands/tablecmds.c:16038 commands/tablecmds.c:18876 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "シーケンス\"%s\"はテーブル\"%s\"にリンクされています" -#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1886 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "CREATE STATISTICSで指定可能なリレーションは一つのみです" @@ -9763,1754 +9829,1920 @@ msgstr "統計情報オブジェクト\"%s\"はすでに存在します" msgid "cannot have more than %d columns in statistics" msgstr "統計情報は%dを超える列を使用できません" -#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 +#: commands/statscmds.c:247 commands/statscmds.c:276 commands/statscmds.c:316 #, c-format msgid "statistics creation on system columns is not supported" msgstr "システム列に対する統計情報の作成はサポートされていません" -#: commands/statscmds.c:254 commands/statscmds.c:277 +#: commands/statscmds.c:253 commands/statscmds.c:282 commands/statscmds.c:322 +#, c-format +msgid "statistics creation on virtual generated columns is not supported" +msgstr "仮想生成列に対する統計情報の作成はサポートされていません" + +#: commands/statscmds.c:260 commands/statscmds.c:289 #, c-format msgid "column \"%s\" cannot be used in statistics because its type %s has no default btree operator class" msgstr "列\"%s\"の型%sはデフォルトのbtreeオペレータクラスを持たないため統計情報では利用できません" -#: commands/statscmds.c:321 +#: commands/statscmds.c:339 #, c-format msgid "expression cannot be used in multivariate statistics because its type %s has no default btree operator class" msgstr "式の型%sがデフォルトbtree演算子クラスを持たないためこの式は多値統計情報では使用できません" -#: commands/statscmds.c:342 +#: commands/statscmds.c:360 #, c-format msgid "when building statistics on a single expression, statistics kinds may not be specified" msgstr "単一式上の統計情報の構築時には、統計種別は指定できません" -#: commands/statscmds.c:371 +#: commands/statscmds.c:389 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "認識できない統計情報種別\"%s\"" -#: commands/statscmds.c:400 +#: commands/statscmds.c:418 #, c-format msgid "extended statistics require at least 2 columns" msgstr "拡張統計情報には最低でも2つの列が必要です" -#: commands/statscmds.c:418 +#: commands/statscmds.c:436 #, c-format msgid "duplicate column name in statistics definition" msgstr "定形情報定義中の列名が重複しています" -#: commands/statscmds.c:453 +#: commands/statscmds.c:471 #, c-format msgid "duplicate expression in statistics definition" msgstr "統計情報定義内に重複した式" -#: commands/statscmds.c:628 commands/tablecmds.c:8628 +#: commands/statscmds.c:646 commands/tablecmds.c:8913 #, c-format msgid "statistics target %d is too low" msgstr "統計情報目標%dは小さすぎます" -#: commands/statscmds.c:636 commands/tablecmds.c:8636 +#: commands/statscmds.c:654 commands/tablecmds.c:8921 #, c-format msgid "lowering statistics target to %d" msgstr "統計情報目標を%dに減らします" -#: commands/statscmds.c:660 +#: commands/statscmds.c:678 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "統計情報オブジェクト\"%s.%s\"は存在しません、スキップします" -#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 -#, c-format -msgid "unrecognized subscription parameter: \"%s\"" -msgstr "認識できないサブスクリプションパラメータ: \"%s\"" - -#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:397 +#: commands/subscriptioncmds.c:331 replication/pgoutput/pgoutput.c:410 #, c-format msgid "unrecognized origin value: \"%s\"" msgstr "識別できないoriginの値: \"%s\"" -#: commands/subscriptioncmds.c:363 +#: commands/subscriptioncmds.c:354 #, c-format msgid "invalid WAL location (LSN): %s" msgstr "不正なWAL位置(LSN): %s" +#: commands/subscriptioncmds.c:363 +#, c-format +msgid "unrecognized subscription parameter: \"%s\"" +msgstr "認識できないサブスクリプションパラメータ: \"%s\"" + #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 commands/subscriptioncmds.c:439 +#: commands/subscriptioncmds.c:378 commands/subscriptioncmds.c:385 commands/subscriptioncmds.c:392 commands/subscriptioncmds.c:414 commands/subscriptioncmds.c:430 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "%s と %s は排他なオプションです" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 +#: commands/subscriptioncmds.c:420 commands/subscriptioncmds.c:436 #, c-format msgid "subscription with %s must also set %s" msgstr "%s としたサブスクリプションでは %s を設定する必要があります" -#: commands/subscriptioncmds.c:506 +#: commands/subscriptioncmds.c:466 #, c-format msgid "could not receive list of publications from the publisher: %s" msgstr "パブリケーション一覧をパブリッシャから受け取れませんでした: %s" -#: commands/subscriptioncmds.c:538 +#: commands/subscriptioncmds.c:498 #, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" msgstr[0] "パブリケーション%sはパブリッシャ上には存在しません" -#: commands/subscriptioncmds.c:626 +#: commands/subscriptioncmds.c:586 #, c-format msgid "permission denied to create subscription" msgstr "サブスクリプションを作成する権限がありません" -#: commands/subscriptioncmds.c:627 +#: commands/subscriptioncmds.c:587 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." msgstr "\"%s\"ロールの権限を持つロールのみがサブスクリプションを作成できます。" -#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 replication/logical/worker.c:4503 +#: commands/subscriptioncmds.c:718 commands/subscriptioncmds.c:852 commands/subscriptioncmds.c:1594 #, c-format -msgid "could not connect to the publisher: %s" -msgstr "パブリッシャへの接続ができませんでした: %s" +msgid "subscription \"%s\" could not connect to the publisher: %s" +msgstr "サブスクリプション\"%s\"はパブリッシャに接続できませんでした: %s" -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:790 #, c-format msgid "created replication slot \"%s\" on publisher" msgstr "パブリッシャ上でレプリケーションスロット\"%s\"を作成しました" -#: commands/subscriptioncmds.c:841 +#: commands/subscriptioncmds.c:802 #, c-format msgid "subscription was created, but is not connected" msgstr "サブスクリプションは作成されましたが接続されていません" -#: commands/subscriptioncmds.c:842 +#: commands/subscriptioncmds.c:803 #, c-format msgid "To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription." msgstr "レプリケーションを開始するにはレプリケーションスロットの作成、サブスクリプションの有効化そしてサブスクリプションのリフレッシュを手動で行う必要があります。" -#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 +#: commands/subscriptioncmds.c:1070 +#, c-format +msgid "cannot set option \"%s\" for enabled subscription" +msgstr "有効にされているサブスクリプションにはオプション”%s”を指定できません" + +#: commands/subscriptioncmds.c:1084 +#, c-format +msgid "cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "スロット名を指定されていないサブスクリプションのオプション\"%s\"を設定することはできません" + +#: commands/subscriptioncmds.c:1127 commands/subscriptioncmds.c:1663 commands/subscriptioncmds.c:2044 utils/cache/lsyscache.c:3824 #, c-format msgid "subscription \"%s\" does not exist" msgstr "サブスクリプション\"%s\"は存在しません" -#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 +#: commands/subscriptioncmds.c:1185 #, c-format msgid "cannot set %s for enabled subscription" msgstr "有効にされているサブスクリプションには %s を指定できません" -#: commands/subscriptioncmds.c:1233 +#: commands/subscriptioncmds.c:1270 +#, c-format +msgid "slot_name and two_phase cannot be altered at the same time" +msgstr "slot_nameとtwo_phaseは同時に変更できません" + +#: commands/subscriptioncmds.c:1286 +#, c-format +msgid "cannot alter two_phase when logical replication worker is still running" +msgstr "論理レプリケーションワーカーがまだ実行中のためtwo_phaseは変更できません" + +#: commands/subscriptioncmds.c:1287 +#, c-format +msgid "Try again after some time." +msgstr "少し待ってから再試行してください。" + +#: commands/subscriptioncmds.c:1300 +#, c-format +msgid "cannot disable two_phase when prepared transactions are present" +msgstr "準備済みトランザクションが存在するためtwo_phaseを無効にできません" + +#: commands/subscriptioncmds.c:1301 #, c-format -msgid "cannot set %s for a subscription that does not have a slot name" -msgstr "スロット名を指定されていないサブスクリプションの%sを設定することはできません" +msgid "Resolve these transactions and try again." +msgstr "トランザクションの解決後に再試行してください。" -#: commands/subscriptioncmds.c:1279 +#: commands/subscriptioncmds.c:1348 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "スロット名を指定されていないサブスクリプションを有効にはできません" -#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 +#: commands/subscriptioncmds.c:1392 commands/subscriptioncmds.c:1443 #, c-format msgid "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" msgstr "refresh指定された ALTER SUBSCRIPTION は無効化されているサブスクリプションには実行できません" -#: commands/subscriptioncmds.c:1324 +#: commands/subscriptioncmds.c:1393 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false) を使ってください。" -#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 +#: commands/subscriptioncmds.c:1402 commands/subscriptioncmds.c:1457 #, c-format msgid "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase is enabled" msgstr "two_phaseが有効である場合、refreshおよびcopy_data指定された ALTER SUBSCRIPTIONは実行できません" -#: commands/subscriptioncmds.c:1334 +#: commands/subscriptioncmds.c:1403 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "refresh = false または copy_data = false を指定してALTER SUBSCRIPTION ... SET PUBLICATIONを実行するか、DROP/CREATE SUBSCRIPTIONを実行してください。" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1390 +#: commands/subscriptioncmds.c:1459 #, c-format msgid "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "refresh = false または copy_data = false を指定して%sを実行するか、DROP/CREATE SUBSCRIPTIONを実行してください。" -#: commands/subscriptioncmds.c:1412 +#: commands/subscriptioncmds.c:1481 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION ... REFRESHは無効化されているサブスクリプションには実行できません" -#: commands/subscriptioncmds.c:1437 +#: commands/subscriptioncmds.c:1506 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase is enabled" msgstr "two_phaseが有効である場合、copy_data指定のALTER SUBSCRIPTION ... REFRESHは実行できません" -#: commands/subscriptioncmds.c:1438 +#: commands/subscriptioncmds.c:1507 #, c-format msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "ALTER SUBSCRIPTION ... REFRESH を copy_data = false を指定して実行するか、DROP/CREATE SUBSCRIPTIONを実行してください。" -#: commands/subscriptioncmds.c:1473 +#: commands/subscriptioncmds.c:1542 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "WAL読み飛ばし位置(LSN %X/%X)は基点LSN %X/%Xより大きくなければなりません" -#: commands/subscriptioncmds.c:1594 +#: commands/subscriptioncmds.c:1667 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "サブスクリプション\"%s\"は存在しません、スキップします" -#: commands/subscriptioncmds.c:1863 +#: commands/subscriptioncmds.c:1934 #, c-format msgid "dropped replication slot \"%s\" on publisher" msgstr "パブリッシャ上でレプリケーションスロット\"%s\"を削除しました" -#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 +#: commands/subscriptioncmds.c:1943 commands/subscriptioncmds.c:1951 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" msgstr "パブリッシャ上でのレプリケーションスロット\"%s\"の削除に失敗しました: %s" -#: commands/subscriptioncmds.c:2005 +#: commands/subscriptioncmds.c:2076 #, c-format msgid "subscription with OID %u does not exist" msgstr "OID %uのサブスクリプションは存在しません" -#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 +#: commands/subscriptioncmds.c:2150 commands/subscriptioncmds.c:2274 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" msgstr "パブリッシャから複製テーブルの一覧を受け取れませんでした: %s" -#: commands/subscriptioncmds.c:2112 +#: commands/subscriptioncmds.c:2186 #, c-format msgid "subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin" msgstr "サブスクリプション\"%s\"がcopy_dataをorigin = NONEで要求しましたが、異なる基点を持つデータをコピーする可能性があります" -#: commands/subscriptioncmds.c:2114 +#: commands/subscriptioncmds.c:2188 #, c-format msgid "The subscription being created subscribes to a publication (%s) that contains tables that are written to by other subscriptions." msgid_plural "The subscription being created subscribes to publications (%s) that contain tables that are written to by other subscriptions." msgstr[0] "作成中のサブスクリプションは他のサブスクリプションによって書き込まれるテーブルを含むパブリケーション(%s)をサブスクライブします" -#: commands/subscriptioncmds.c:2117 +#: commands/subscriptioncmds.c:2191 #, c-format msgid "Verify that initial data copied from the publisher tables did not come from other origins." msgstr "パブリッシャテーブルからコピーされた初期データが異なる起源からのものでないことを確認してください。" -#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 replication/pgoutput/pgoutput.c:1117 +#: commands/subscriptioncmds.c:2296 replication/logical/tablesync.c:904 replication/pgoutput/pgoutput.c:1162 #, c-format msgid "cannot use different column lists for table \"%s.%s\" in different publications" msgstr "テーブル\"%s.%s\"に対して、異なるパブリケーションで異なる列リストを使用することはできません" -#: commands/subscriptioncmds.c:2273 +#: commands/subscriptioncmds.c:2346 #, c-format msgid "could not connect to publisher when attempting to drop replication slot \"%s\": %s" msgstr "レプリケーションスロット\"%s\"を削除する際にパブリッシャへの接続に失敗しました: %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2276 +#: commands/subscriptioncmds.c:2349 #, c-format msgid "Use %s to disable the subscription, and then use %s to disassociate it from the slot." msgstr "%s でサブスクリプションを無効化してから、%s でスロットとの関連付けを解除してください。" -#: commands/subscriptioncmds.c:2307 +#: commands/subscriptioncmds.c:2380 #, c-format msgid "publication name \"%s\" used more than once" msgstr "パブリケーション名\"%s\"が2回以上使われています" -#: commands/subscriptioncmds.c:2351 +#: commands/subscriptioncmds.c:2424 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "パブリケーション\"%s\"はサブスクリプション\"%s\"にすでに存在します" -#: commands/subscriptioncmds.c:2365 +#: commands/subscriptioncmds.c:2438 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "パブリケーション\"%s\"はサブスクリプション\"%s\"にはありません" -#: commands/subscriptioncmds.c:2376 +#: commands/subscriptioncmds.c:2449 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "サブスクリプションからすべてのパブリケーションを削除することはできません" -#: commands/subscriptioncmds.c:2433 +#: commands/subscriptioncmds.c:2506 #, c-format msgid "%s requires a Boolean value or \"parallel\"" msgstr "パラメータ\"%s\"はBoolean値または\"parallel\"のみを取ります" -#: commands/tablecmds.c:255 commands/tablecmds.c:297 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 #, c-format msgid "table \"%s\" does not exist" msgstr "テーブル\"%s\"は存在しません" -#: commands/tablecmds.c:256 commands/tablecmds.c:298 +#: commands/tablecmds.c:259 commands/tablecmds.c:301 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "テーブル\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:258 commands/tablecmds.c:300 +#: commands/tablecmds.c:261 commands/tablecmds.c:303 msgid "Use DROP TABLE to remove a table." msgstr "テーブルを削除するにはDROP TABLEを使用してください。" -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:264 #, c-format msgid "sequence \"%s\" does not exist" msgstr "シーケンス\"%s\"は存在しません" -#: commands/tablecmds.c:262 +#: commands/tablecmds.c:265 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "シーケンス\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:267 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "シーケンスを削除するにはDROP SEQUENCEを使用してください。" -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:270 #, c-format msgid "view \"%s\" does not exist" msgstr "ビュー\"%s\"は存在しません" -#: commands/tablecmds.c:268 +#: commands/tablecmds.c:271 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "ビュー\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:270 +#: commands/tablecmds.c:273 msgid "Use DROP VIEW to remove a view." msgstr "ビューを削除するにはDROP VIEWを使用してください。" -#: commands/tablecmds.c:273 +#: commands/tablecmds.c:276 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "実体化ビュー\"%s\"は存在しません" -#: commands/tablecmds.c:274 +#: commands/tablecmds.c:277 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "実体化ビュー\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:276 +#: commands/tablecmds.c:279 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "実体化ビューを削除するにはDROP MATERIALIZED VIEWを使用してください。" -#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19627 parser/parse_utilcmd.c:2226 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 commands/tablecmds.c:21531 parser/parse_utilcmd.c:2407 #, c-format msgid "index \"%s\" does not exist" msgstr "インデックス\"%s\"は存在しません" -#: commands/tablecmds.c:280 commands/tablecmds.c:304 +#: commands/tablecmds.c:283 commands/tablecmds.c:307 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "インデックス\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:282 commands/tablecmds.c:306 +#: commands/tablecmds.c:285 commands/tablecmds.c:309 msgid "Use DROP INDEX to remove an index." msgstr "インデックスを削除するにはDROP INDEXを使用してください" -#: commands/tablecmds.c:287 +#: commands/tablecmds.c:290 #, c-format msgid "\"%s\" is not a type" msgstr "\"%s\"は型ではありません" -#: commands/tablecmds.c:288 +#: commands/tablecmds.c:291 msgid "Use DROP TYPE to remove a type." msgstr "型を削除するにはDROP TYPEを使用してください" -#: commands/tablecmds.c:291 commands/tablecmds.c:14226 commands/tablecmds.c:16786 +#: commands/tablecmds.c:294 commands/tablecmds.c:15877 commands/tablecmds.c:18578 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "外部テーブル\"%s\"は存在しません" -#: commands/tablecmds.c:292 +#: commands/tablecmds.c:295 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "外部テーブル\"%s\"は存在しません、スキップします" -#: commands/tablecmds.c:294 +#: commands/tablecmds.c:297 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "外部テーブルを削除するには DROP FOREIGN TABLE を使用してください。" -#: commands/tablecmds.c:722 +#: commands/tablecmds.c:801 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMITは一時テーブルでのみ使用できます" -#: commands/tablecmds.c:753 +#: commands/tablecmds.c:818 +#, c-format +msgid "partitioned tables cannot be unlogged" +msgstr "パーティションテーブルはログ非取得にはできません" + +#: commands/tablecmds.c:838 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "セキュリティー制限操作中は、一時テーブルを作成できません" -#: commands/tablecmds.c:789 commands/tablecmds.c:15645 +#: commands/tablecmds.c:874 commands/tablecmds.c:17302 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "リレーション\"%s\"が複数回継承されました" -#: commands/tablecmds.c:1055 +#: commands/tablecmds.c:1132 #, c-format msgid "\"%s\" is not partitioned" msgstr "\"%s\"はパーティションされていません" -#: commands/tablecmds.c:1149 +#: commands/tablecmds.c:1226 #, c-format msgid "cannot partition using more than %d columns" msgstr "%d以上の列を使ったパーティションはできません" -#: commands/tablecmds.c:1205 +#: commands/tablecmds.c:1282 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "パーティションテーブル\"%s\"では外部子テーブルを作成できません" -#: commands/tablecmds.c:1207 +#: commands/tablecmds.c:1284 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "テーブル\"%s\"はユニークインデックスを持っています" -#: commands/tablecmds.c:1326 commands/tablecmds.c:13242 +#: commands/tablecmds.c:1414 commands/tablecmds.c:14877 #, c-format msgid "too many array dimensions" msgstr "配列の次元多すぎます" -#: commands/tablecmds.c:1331 parser/parse_clause.c:774 parser/parse_relation.c:1912 +#: commands/tablecmds.c:1419 parser/parse_clause.c:772 parser/parse_relation.c:1929 #, c-format msgid "column \"%s\" cannot be declared SETOF" msgstr "列\"%s\"はSETOFとして宣言できません" -#: commands/tablecmds.c:1477 +#: commands/tablecmds.c:1548 #, c-format msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" msgstr "DROP INDEX CONCURRENTLYは複数オブジェクトの削除をサポートしていません" -#: commands/tablecmds.c:1481 +#: commands/tablecmds.c:1552 #, c-format msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLYはCASCADEをサポートしません" -#: commands/tablecmds.c:1585 +#: commands/tablecmds.c:1656 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "パーティション親インデックス\"%s\"は並行的に削除することはできません" -#: commands/tablecmds.c:1873 +#: commands/tablecmds.c:1944 #, c-format msgid "cannot truncate only a partitioned table" msgstr "パーティションの親テーブルのみの切り詰めはできません" -#: commands/tablecmds.c:1874 +#: commands/tablecmds.c:1945 #, c-format msgid "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly." msgstr "ONLY キーワードを指定しないでください、もしくは子テーブルに対して直接 TRUNCATE ONLY を実行してください。" -#: commands/tablecmds.c:1947 +#: commands/tablecmds.c:2018 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "テーブル\"%s\"へのカスケードを削除します" -#: commands/tablecmds.c:2308 +#: commands/tablecmds.c:2379 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "外部テーブル\"%s\"の切り詰めはできません" -#: commands/tablecmds.c:2365 +#: commands/tablecmds.c:2436 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "他のセッションの一時テーブルを削除できません" -#: commands/tablecmds.c:2594 commands/tablecmds.c:15542 +#: commands/tablecmds.c:2674 commands/tablecmds.c:17199 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "パーティション親テーブル\"%s\"からの継承はできません" -#: commands/tablecmds.c:2599 +#: commands/tablecmds.c:2679 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "パーティション子テーブル\"%s\"からの継承はできません" -#: commands/tablecmds.c:2607 parser/parse_utilcmd.c:2456 parser/parse_utilcmd.c:2598 +#: commands/tablecmds.c:2687 parser/parse_utilcmd.c:2678 parser/parse_utilcmd.c:2866 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "継承しようとしたリレーション\"%s\"はテーブルまたは外部テーブルではありません" -#: commands/tablecmds.c:2619 commands/tablecmds.c:20391 +#: commands/tablecmds.c:2699 #, c-format msgid "cannot create a temporary relation as partition of permanent relation \"%s\"" msgstr "一時リレーションを永続リレーション\"%s\"のパーティション子テーブルとして作ることはできません" -#: commands/tablecmds.c:2628 commands/tablecmds.c:15521 +#: commands/tablecmds.c:2708 commands/tablecmds.c:17178 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "一時リレーション\"%s\"から継承することはできません" -#: commands/tablecmds.c:2638 commands/tablecmds.c:15529 +#: commands/tablecmds.c:2718 commands/tablecmds.c:17186 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "他のセッションの一時リレーションから継承することはできません" -#: commands/tablecmds.c:2779 commands/tablecmds.c:2833 commands/tablecmds.c:12925 parser/parse_utilcmd.c:1240 parser/parse_utilcmd.c:1283 parser/parse_utilcmd.c:1710 parser/parse_utilcmd.c:1818 +#: commands/tablecmds.c:2873 commands/tablecmds.c:2927 commands/tablecmds.c:14560 parser/parse_utilcmd.c:1418 parser/parse_utilcmd.c:1463 parser/parse_utilcmd.c:1895 parser/parse_utilcmd.c:2003 #, c-format msgid "cannot convert whole-row table reference" msgstr "行全体テーブル参照を変換できません" -#: commands/tablecmds.c:2780 parser/parse_utilcmd.c:1241 +#: commands/tablecmds.c:2874 parser/parse_utilcmd.c:1419 #, c-format msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." msgstr "制約\"%s\"はテーブル\"%s\"への行全体参照を含みます。" -#: commands/tablecmds.c:2834 parser/parse_utilcmd.c:1284 +#: commands/tablecmds.c:2928 parser/parse_utilcmd.c:1464 #, c-format msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." msgstr "制約\"%s\"はテーブル\"%s\"への行全体参照を含みます。" -#: commands/tablecmds.c:2944 commands/tablecmds.c:3215 +#: commands/tablecmds.c:3050 commands/tablecmds.c:3344 #, c-format msgid "column \"%s\" inherits from generated column but specifies default" msgstr "列\"%s\"は生成列を継承しますが、default 指定がされています" -#: commands/tablecmds.c:2949 commands/tablecmds.c:3220 +#: commands/tablecmds.c:3055 commands/tablecmds.c:3349 #, c-format msgid "column \"%s\" inherits from generated column but specifies identity" msgstr "列\"%s\"は生成列を継承しますが、識別列と指定されています" -#: commands/tablecmds.c:2957 commands/tablecmds.c:3228 +#: commands/tablecmds.c:3063 commands/tablecmds.c:3357 #, c-format msgid "child column \"%s\" specifies generation expression" msgstr "子テーブルの列\"%s\"は生成式を指定しています" -#: commands/tablecmds.c:2959 commands/tablecmds.c:3230 +#: commands/tablecmds.c:3065 commands/tablecmds.c:3359 #, c-format msgid "A child table column cannot be generated unless its parent column is." msgstr "子テーブルの列は、親となる列が生成列でなければ生成列にはできません。" -#: commands/tablecmds.c:3005 +#: commands/tablecmds.c:3071 commands/tablecmds.c:3365 commands/tablecmds.c:17464 +#, c-format +msgid "column \"%s\" inherits from generated column of different kind" +msgstr "列\"%s\"は異なる種類の生成列を継承しています" + +#: commands/tablecmds.c:3073 commands/tablecmds.c:3367 commands/tablecmds.c:17465 +#, c-format +msgid "Parent column is %s, child column is %s." +msgstr "親の列は %s、子の列は %s です。" + +#: commands/tablecmds.c:3120 #, c-format msgid "column \"%s\" inherits conflicting generation expressions" msgstr "列\"%s\"は競合する生成式を継承します" -#: commands/tablecmds.c:3007 +#: commands/tablecmds.c:3122 #, c-format msgid "To resolve the conflict, specify a generation expression explicitly." msgstr "この競合を解消するには明示的に生成式を指定してください。" -#: commands/tablecmds.c:3011 +#: commands/tablecmds.c:3126 #, c-format msgid "column \"%s\" inherits conflicting default values" msgstr "列\"%s\"は競合するデフォルト値を継承します" -#: commands/tablecmds.c:3013 +#: commands/tablecmds.c:3128 #, c-format msgid "To resolve the conflict, specify a default explicitly." msgstr "競合を解消するには明示的にデフォルトを指定してください" -#: commands/tablecmds.c:3068 +#: commands/tablecmds.c:3195 #, c-format msgid "check constraint name \"%s\" appears multiple times but with different expressions" msgstr "異なる式を持つ検査制約名\"%s\"が複数あります。" -#: commands/tablecmds.c:3119 +#: commands/tablecmds.c:3248 #, c-format msgid "merging column \"%s\" with inherited definition" msgstr "継承される定義で列\"%s\"をマージしています" -#: commands/tablecmds.c:3123 +#: commands/tablecmds.c:3252 #, c-format msgid "moving and merging column \"%s\" with inherited definition" msgstr "継承される定義で列\"%s\"を移動してマージします" -#: commands/tablecmds.c:3124 +#: commands/tablecmds.c:3253 #, c-format msgid "User-specified column moved to the position of the inherited column." msgstr "ユーザーが指定した列が継承した列の位置に移動されました。" -#: commands/tablecmds.c:3136 +#: commands/tablecmds.c:3265 #, c-format msgid "column \"%s\" has a type conflict" msgstr "列\"%s\"の型が競合しています" -#: commands/tablecmds.c:3138 commands/tablecmds.c:3172 commands/tablecmds.c:3188 commands/tablecmds.c:3295 commands/tablecmds.c:3328 commands/tablecmds.c:3344 parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 parser/parse_param.c:223 +#: commands/tablecmds.c:3267 commands/tablecmds.c:3301 commands/tablecmds.c:3317 commands/tablecmds.c:3433 commands/tablecmds.c:3461 commands/tablecmds.c:3477 parser/parse_coerce.c:2190 parser/parse_coerce.c:2210 parser/parse_coerce.c:2230 parser/parse_coerce.c:2251 parser/parse_coerce.c:2306 parser/parse_coerce.c:2340 parser/parse_coerce.c:2416 parser/parse_coerce.c:2447 parser/parse_coerce.c:2486 parser/parse_coerce.c:2553 parser/parse_param.c:224 #, c-format msgid "%s versus %s" msgstr "%s対%s" -#: commands/tablecmds.c:3150 +#: commands/tablecmds.c:3279 #, c-format msgid "column \"%s\" has a collation conflict" msgstr "列\"%s\"の照合順序が競合しています" -#: commands/tablecmds.c:3152 commands/tablecmds.c:3314 commands/tablecmds.c:7088 +#: commands/tablecmds.c:3281 commands/tablecmds.c:3447 commands/tablecmds.c:7276 #, c-format msgid "\"%s\" versus \"%s\"" msgstr "\"%s\"対\"%s\"" -#: commands/tablecmds.c:3170 +#: commands/tablecmds.c:3299 #, c-format msgid "column \"%s\" has a storage parameter conflict" msgstr "列\"%s\"でストレージパラメータが競合しています" -#: commands/tablecmds.c:3186 commands/tablecmds.c:3342 +#: commands/tablecmds.c:3315 commands/tablecmds.c:3475 #, c-format msgid "column \"%s\" has a compression method conflict" msgstr "列\"%s\"で圧縮方式が競合しています" -#: commands/tablecmds.c:3281 +#: commands/tablecmds.c:3419 #, c-format msgid "merging multiple inherited definitions of column \"%s\"" msgstr "複数の継承される列\"%s\"の定義をマージしています" -#: commands/tablecmds.c:3293 +#: commands/tablecmds.c:3431 #, c-format msgid "inherited column \"%s\" has a type conflict" msgstr "継承される列\"%s\"の型が競合しています" -#: commands/tablecmds.c:3312 +#: commands/tablecmds.c:3445 #, c-format msgid "inherited column \"%s\" has a collation conflict" msgstr "継承される列 \"%s\"の照合順序が競合しています" -#: commands/tablecmds.c:3326 +#: commands/tablecmds.c:3459 #, c-format msgid "inherited column \"%s\" has a storage parameter conflict" msgstr "継承される列\"%s\"でストレージパラメータが競合しています" -#: commands/tablecmds.c:3354 +#: commands/tablecmds.c:3487 #, c-format msgid "inherited column \"%s\" has a generation conflict" msgstr "継承された列 \"%s\"の生成が競合しています" -#: commands/tablecmds.c:3573 +#: commands/tablecmds.c:3718 #, c-format msgid "cannot move temporary tables of other sessions" msgstr "他のセッションの一時テーブルを移動できません" -#: commands/tablecmds.c:3643 +#: commands/tablecmds.c:3791 #, c-format msgid "cannot rename column of typed table" msgstr "型付けされたテーブルの列をリネームできません" -#: commands/tablecmds.c:3662 +#: commands/tablecmds.c:3810 #, c-format msgid "cannot rename columns of relation \"%s\"" msgstr "リレーション\"%s\"の列名は変更できません" -#: commands/tablecmds.c:3757 +#: commands/tablecmds.c:3905 #, c-format msgid "inherited column \"%s\" must be renamed in child tables too" msgstr "継承される列\"%s\"の名前を子テーブルでも変更する必要があります" -#: commands/tablecmds.c:3789 +#: commands/tablecmds.c:3937 #, c-format msgid "cannot rename system column \"%s\"" msgstr "システム列%s\"の名前を変更できません" -#: commands/tablecmds.c:3804 +#: commands/tablecmds.c:3952 #, c-format msgid "cannot rename inherited column \"%s\"" msgstr "継承される列\"%s\"の名前を変更できません" -#: commands/tablecmds.c:3956 +#: commands/tablecmds.c:4107 #, c-format msgid "inherited constraint \"%s\" must be renamed in child tables too" msgstr "継承される制約\"%s\"の名前を子テーブルでも変更する必要があります" -#: commands/tablecmds.c:3963 +#: commands/tablecmds.c:4114 #, c-format msgid "cannot rename inherited constraint \"%s\"" msgstr "継承される制約\"%s\"の名前を変更できません" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4260 +#: commands/tablecmds.c:4414 #, c-format msgid "cannot %s \"%s\" because it is being used by active queries in this session" msgstr "このセッションで実行中の問い合わせで使用されているため\"%2$s\"を%1$sできません" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4269 +#: commands/tablecmds.c:4423 #, c-format msgid "cannot %s \"%s\" because it has pending trigger events" msgstr "保留中のトリガイベントがあるため\"%2$s\"を%1$sできません" -#: commands/tablecmds.c:4295 +#: commands/tablecmds.c:4449 #, c-format msgid "cannot alter temporary tables of other sessions" msgstr "他のセッションの一時テーブルは変更できません" -#: commands/tablecmds.c:4776 +#: commands/tablecmds.c:4913 #, c-format msgid "cannot alter partition \"%s\" with an incomplete detach" msgstr "パーティション子テーブル\"%s\"は不完全な取り外し状態であるため変更できません" -#: commands/tablecmds.c:4980 commands/tablecmds.c:4995 +#: commands/tablecmds.c:5142 #, c-format msgid "cannot change persistence setting twice" msgstr "永続性設定の変更は2度はできません" -#: commands/tablecmds.c:5016 +#: commands/tablecmds.c:5159 #, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" msgstr "SET ACCESS METHODサブコマンドを複数指定できません" -#: commands/tablecmds.c:5772 +#: commands/tablecmds.c:5893 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "システムリレーション\"%sを書き換えられません" -#: commands/tablecmds.c:5778 +#: commands/tablecmds.c:5899 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "カタログテーブルとして使用されているテーブル\"%s\"は書き換えられません" -#: commands/tablecmds.c:5790 +#: commands/tablecmds.c:5911 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "他のセッションの一時テーブルを書き換えられません" -#: commands/tablecmds.c:6285 +#: commands/tablecmds.c:6447 commands/tablecmds.c:6467 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "リレーション\"%2$s\"の列\"%1$s\"にNULL値があります" -#: commands/tablecmds.c:6302 +#: commands/tablecmds.c:6484 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "一部の行がリレーション\"%2$s\"の検査制約\"%1$s\"に違反してます" -#: commands/tablecmds.c:6321 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6504 partitioning/partbounds.c:3387 #, c-format msgid "updated partition constraint for default partition \"%s\" would be violated by some row" msgstr "デフォルトパーティション\"%s\"の一部の行が更新後のパーティション制約に違反しています" -#: commands/tablecmds.c:6327 +#: commands/tablecmds.c:6510 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "一部の行がリレーション\"%s\"のパーティション制約に違反しています" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6596 +#: commands/tablecmds.c:6775 #, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" msgstr "ALTERのアクション%sはリレーション\"%s\"では実行できません" -#: commands/tablecmds.c:6851 commands/tablecmds.c:6858 +#: commands/tablecmds.c:7030 commands/tablecmds.c:7037 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" msgstr "型\"%s\"を変更できません。列\"%s\".\"%s\"でその型を使用しているためです" -#: commands/tablecmds.c:6865 +#: commands/tablecmds.c:7044 #, c-format msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" msgstr "列%2$s\".\"%3$s\"がその行型を使用しているため、外部テーブル\"%1$s\"を変更できません。" -#: commands/tablecmds.c:6872 +#: commands/tablecmds.c:7051 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "テーブル\"%s\"を変更できません。その行型を列\"%s\".\"%s\"で使用しているためです" -#: commands/tablecmds.c:6928 +#: commands/tablecmds.c:7107 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "型付けされたテーブルの型であるため、外部テーブル\"%s\"を変更できません。" -#: commands/tablecmds.c:6930 +#: commands/tablecmds.c:7109 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "型付けされたテーブルを変更する場合も ALTER .. CASCADE を使用してください" -#: commands/tablecmds.c:6976 +#: commands/tablecmds.c:7155 +#, c-format +msgid "type %s is the row type of another table" +msgstr "型\"%s\"は他のテーブルの行型です" + +#: commands/tablecmds.c:7157 +#, c-format +msgid "A typed table must use a stand-alone composite type created with CREATE TYPE." +msgstr "型付きテーブルは、CREATE TYPEで作成された独立した複合型を使用する必要があります。" + +#: commands/tablecmds.c:7162 #, c-format msgid "type %s is not a composite type" msgstr "型 %s は複合型ではありません" -#: commands/tablecmds.c:7003 +#: commands/tablecmds.c:7189 #, c-format msgid "cannot add column to typed table" msgstr "型付けされたテーブルに列を追加できません" -#: commands/tablecmds.c:7051 +#: commands/tablecmds.c:7239 #, c-format msgid "cannot add column to a partition" msgstr "パーティションに列は追加できません" -#: commands/tablecmds.c:7080 commands/tablecmds.c:15760 +#: commands/tablecmds.c:7268 commands/tablecmds.c:17420 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "子テーブル\"%s\"に異なる型の列\"%s\"があります" -#: commands/tablecmds.c:7086 commands/tablecmds.c:15766 +#: commands/tablecmds.c:7274 commands/tablecmds.c:17426 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "子テーブル\"%s\"に異なる照合順序の列\"%s\"があります" -#: commands/tablecmds.c:7104 +#: commands/tablecmds.c:7292 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "子\"%2$s\"の列\"%1$s\"の定義をマージしています" -#: commands/tablecmds.c:7157 +#: commands/tablecmds.c:7345 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "子テーブルを持つテーブルに識別列を再帰的に追加することはできません" -#: commands/tablecmds.c:7370 +#: commands/tablecmds.c:7592 #, c-format msgid "column must be added to child tables too" msgstr "列は子テーブルでも追加する必要があります" -#: commands/tablecmds.c:7448 +#: commands/tablecmds.c:7670 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "リレーション\"%2$s\"の列\"%1$s\"はすでに存在します、スキップします" -#: commands/tablecmds.c:7455 +#: commands/tablecmds.c:7677 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "リレーション\"%2$s\"の列\"%1$s\"はすでに存在します" -#: commands/tablecmds.c:7521 commands/tablecmds.c:12564 -#, c-format -msgid "cannot remove constraint from only the partitioned table when partitions exist" -msgstr "パーティションが存在する場合にはパーティション親テーブルのみから制約を削除することはできません" - -#: commands/tablecmds.c:7522 commands/tablecmds.c:7836 commands/tablecmds.c:8014 commands/tablecmds.c:8121 commands/tablecmds.c:8238 commands/tablecmds.c:9057 commands/tablecmds.c:12565 -#, c-format -msgid "Do not specify the ONLY keyword." -msgstr "ONLYキーワードを指定しないでください。" - -#: commands/tablecmds.c:7558 commands/tablecmds.c:7762 commands/tablecmds.c:7904 commands/tablecmds.c:8036 commands/tablecmds.c:8165 commands/tablecmds.c:8259 commands/tablecmds.c:8360 commands/tablecmds.c:8517 commands/tablecmds.c:8670 commands/tablecmds.c:8751 commands/tablecmds.c:8885 commands/tablecmds.c:12718 commands/tablecmds.c:14249 commands/tablecmds.c:16875 +#: commands/tablecmds.c:7768 commands/tablecmds.c:7935 commands/tablecmds.c:8136 commands/tablecmds.c:8267 commands/tablecmds.c:8396 commands/tablecmds.c:8490 commands/tablecmds.c:8593 commands/tablecmds.c:8789 commands/tablecmds.c:8955 commands/tablecmds.c:9046 commands/tablecmds.c:9180 commands/tablecmds.c:14335 commands/tablecmds.c:15900 commands/tablecmds.c:18667 #, c-format msgid "cannot alter system column \"%s\"" msgstr "システム列\"%s\"を変更できません" -#: commands/tablecmds.c:7564 commands/tablecmds.c:7910 +#: commands/tablecmds.c:7774 commands/tablecmds.c:8142 commands/tablecmds.c:14096 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "リレーション\"%2$s\"の列\"%1$s\"は識別列です" -#: commands/tablecmds.c:7605 -#, c-format -msgid "column \"%s\" is in a primary key" -msgstr "列\"%s\"はプライマリキーで使用しています" - -#: commands/tablecmds.c:7610 -#, c-format -msgid "column \"%s\" is in index used as replica identity" -msgstr "列\"%s\"は複製識別として使用中のインデックスに含まれています" - -#: commands/tablecmds.c:7633 +#: commands/tablecmds.c:7791 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "列\"%s\"は親テーブルでNOT NULL指定されています" -#: commands/tablecmds.c:7833 commands/tablecmds.c:9541 +#: commands/tablecmds.c:8013 commands/tablecmds.c:9957 #, c-format msgid "constraint must be added to child tables too" msgstr "制約は子テーブルにも追加する必要があります" -#: commands/tablecmds.c:7834 +#: commands/tablecmds.c:8014 commands/tablecmds.c:8245 commands/tablecmds.c:8352 commands/tablecmds.c:8469 commands/tablecmds.c:9353 commands/tablecmds.c:12159 #, c-format -msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." -msgstr "リレーション\"%2$s\"の列\"%1$s\"はすでにNOT NULLではありません。" +msgid "Do not specify the ONLY keyword." +msgstr "ONLYキーワードを指定しないでください。" -#: commands/tablecmds.c:7919 +#: commands/tablecmds.c:8151 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "リレーション\"%2$s\"の列\"%1$s\"は生成カラムです" -#: commands/tablecmds.c:8013 +#: commands/tablecmds.c:8244 #, c-format msgid "cannot add identity to a column of only the partitioned table" msgstr "パーティション親テーブルのみで列を識別列とすることはできません" -#: commands/tablecmds.c:8019 +#: commands/tablecmds.c:8250 #, c-format msgid "cannot add identity to a column of a partition" msgstr "パーティション子テーブルの列を識別列とすることはできません" -#: commands/tablecmds.c:8047 +#: commands/tablecmds.c:8278 #, c-format msgid "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added" msgstr "識別列を追加するにはリレーション\"%s\"の列\"%s\"はNOT NULLと宣言されている必要があります" -#: commands/tablecmds.c:8053 +#: commands/tablecmds.c:8284 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "リレーション\"%2$s\"の列\"%1$s\"はすでに識別列です" -#: commands/tablecmds.c:8059 +#: commands/tablecmds.c:8290 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "リレーション\"%2$s\"の列\"%1$s\"はすでにデフォルト値が指定されています" -#: commands/tablecmds.c:8120 +#: commands/tablecmds.c:8351 #, c-format msgid "cannot change identity column of only the partitioned table" msgstr "パーティション親テーブルのみで列の識別列属性を変更することはできません" -#: commands/tablecmds.c:8126 +#: commands/tablecmds.c:8357 #, c-format msgid "cannot change identity column of a partition" msgstr "パーティション子テーブルの列の識別列属性を変更することはできません" -#: commands/tablecmds.c:8171 commands/tablecmds.c:8267 +#: commands/tablecmds.c:8402 commands/tablecmds.c:8498 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "リレーション\"%2$s\"の列\"%1$s\"は識別列ではありません" -#: commands/tablecmds.c:8237 +#: commands/tablecmds.c:8468 #, c-format msgid "cannot drop identity from a column of only the partitioned table" msgstr "パーティション親テーブルのみで列の識別列属性を削除することはできません" -#: commands/tablecmds.c:8243 +#: commands/tablecmds.c:8474 #, c-format msgid "cannot drop identity from a column of a partition" msgstr "パーティション子テーブルの列の識別列属性を削除することはできません" -#: commands/tablecmds.c:8272 +#: commands/tablecmds.c:8503 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "リレーション\"%2$s\"の列\"%1$s\"は識別列ではありません、スキップします" -#: commands/tablecmds.c:8366 +#: commands/tablecmds.c:8600 commands/tablecmds.c:8810 #, c-format msgid "column \"%s\" of relation \"%s\" is not a generated column" msgstr "リレーション\"%2$s\"の列\"%1$s\"は生成列ではありません" -#: commands/tablecmds.c:8464 +#: commands/tablecmds.c:8611 +#, c-format +msgid "ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables with check constraints" +msgstr "ALTER TABLE / SET EXPRESSION は、チェック制約のあるテーブルの仮想生成列ではサポートされていません" + +#: commands/tablecmds.c:8612 commands/tablecmds.c:8630 commands/tablecmds.c:8802 +#, c-format +msgid "Column \"%s\" of relation \"%s\" is a virtual generated column." +msgstr "リレーション\"%2$s\"の列\"%1$s\"は仮想生成列です。" + +#: commands/tablecmds.c:8629 +#, c-format +msgid "ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables that are part of a publication" +msgstr "ALTER TABLE / SET EXPRESSION は、パブリケーションに含まれるテーブルの仮想生成列ではサポートされていません" + +#: commands/tablecmds.c:8736 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "ALTER TABLE / DROP EXPRESSIONは子テーブルに対しても適用されなくてはなりません" -#: commands/tablecmds.c:8486 +#: commands/tablecmds.c:8758 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "継承列から生成式を削除することはできません" -#: commands/tablecmds.c:8525 +#: commands/tablecmds.c:8801 #, c-format -msgid "column \"%s\" of relation \"%s\" is not a stored generated column" -msgstr "リレーション\"%2$s\"の列\"%1$s\"は格納生成列ではありません" +msgid "ALTER TABLE / DROP EXPRESSION is not supported for virtual generated columns" +msgstr "ALTER TABLE / DROP EXPRESSIONは仮想生成列ではサポートされていません" -#: commands/tablecmds.c:8530 +#: commands/tablecmds.c:8815 #, c-format -msgid "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" -msgstr "リレーション\"%2$s\"の列\"%1$s\"は格納生成列ではありません、スキップします" +msgid "column \"%s\" of relation \"%s\" is not a generated column, skipping" +msgstr "リレーション\"%2$s\"の列\"%1$s\"は生成列ではありません、スキップします" -#: commands/tablecmds.c:8608 +#: commands/tablecmds.c:8893 #, c-format msgid "cannot refer to non-index column by number" msgstr "非インデックス列を番号で参照することはできません" -#: commands/tablecmds.c:8660 +#: commands/tablecmds.c:8945 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "リレーション \"%2$s\"の列 %1$d は存在しません" -#: commands/tablecmds.c:8679 +#: commands/tablecmds.c:8965 +#, c-format +msgid "cannot alter statistics on virtual generated column \"%s\"" +msgstr "仮想生成列\"%s\"の統計情報は変更できません" + +#: commands/tablecmds.c:8974 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "インデックス\"%2$s\"の包含列\"%1$s\"への統計情報の変更はできません" -#: commands/tablecmds.c:8684 +#: commands/tablecmds.c:8979 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "インデックス \"%2$s\"の非式列\"%1$s\"の統計情報の変更はできません" -#: commands/tablecmds.c:8686 +#: commands/tablecmds.c:8981 #, c-format msgid "Alter statistics on table column instead." msgstr "代わりにテーブルカラムの統計情報を変更してください。" -#: commands/tablecmds.c:8932 +#: commands/tablecmds.c:9227 #, c-format msgid "cannot drop column from typed table" msgstr "型付けされたテーブルから列を削除できません" -#: commands/tablecmds.c:8995 +#: commands/tablecmds.c:9291 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "リレーション\"%2$s\"の列\"%1$s\"は存在しません、スキップします" -#: commands/tablecmds.c:9008 +#: commands/tablecmds.c:9304 #, c-format msgid "cannot drop system column \"%s\"" msgstr "システム列\"%s\"を削除できません" -#: commands/tablecmds.c:9018 +#: commands/tablecmds.c:9314 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "継承される列\"%s\"を削除できません" -#: commands/tablecmds.c:9031 +#: commands/tablecmds.c:9327 #, c-format msgid "cannot drop column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "列\"%s\"はリレーション\"%s\"のパーティションキーの一部であるため、削除できません" -#: commands/tablecmds.c:9056 +#: commands/tablecmds.c:9352 #, c-format msgid "cannot drop column from only the partitioned table when partitions exist" msgstr "子テーブルが存在する場合にはパーティション親テーブルのみから列を削除することはできません" -#: commands/tablecmds.c:9261 +#: commands/tablecmds.c:9479 +#, c-format +msgid "column \"%s\" of table \"%s\" is not marked NOT NULL" +msgstr "テーブル\"%2$s\"の列\"%1$s\"は非NULLに設定されていません" + +#: commands/tablecmds.c:9507 commands/tablecmds.c:9519 +#, c-format +msgid "cannot create primary key on column \"%s\"" +msgstr "列%s\"に主キーを作成することはできません" + +#. translator: third %s is a constraint characteristic such as NOT VALID +#: commands/tablecmds.c:9510 commands/tablecmds.c:9522 +#, c-format +msgid "The constraint \"%s\" on column \"%s\", marked %s, is incompatible with a primary key." +msgstr " %3$s とマークされている列 \"%2$s\" の制約 \"%1$s\" は、主キーと非互換です" + +#: commands/tablecmds.c:9512 +#, c-format +msgid "You will need to make it inheritable using %s." +msgstr "%s を用いてこの制約を継承可能にすべきです。" + +#: commands/tablecmds.c:9524 +#, c-format +msgid "You will need to validate it using %s." +msgstr "%s を用いてこの制約を検証してください。" + +#: commands/tablecmds.c:9661 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX はパーティションテーブルではサポートされていません" -#: commands/tablecmds.c:9286 +#: commands/tablecmds.c:9686 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX はインデックス\"%s\"を\"%s\"にリネームします" -#: commands/tablecmds.c:9623 +#: commands/tablecmds.c:10044 #, c-format msgid "cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "パーティションテーブル\"%s\"上のリレーション\"%s\"を参照する外部キー定義ではONLY指定はできません " -#: commands/tablecmds.c:9629 -#, c-format -msgid "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"" -msgstr "パーティションテーブル\"%1$s\"にリレーション\"%2$s\"を参照する NOT VALID 指定の外部キーは追加できません " - -#: commands/tablecmds.c:9632 -#, c-format -msgid "This feature is not yet supported on partitioned tables." -msgstr "この機能はパーティションテーブルに対してはサポートされていません。" - -#: commands/tablecmds.c:9639 commands/tablecmds.c:10095 +#: commands/tablecmds.c:10052 commands/tablecmds.c:10679 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "参照先のリレーション\"%s\"はテーブルではありません" -#: commands/tablecmds.c:9662 +#: commands/tablecmds.c:10075 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "永続テーブルの制約は永続テーブルだけを参照できます" -#: commands/tablecmds.c:9669 +#: commands/tablecmds.c:10082 #, c-format msgid "constraints on unlogged tables may reference only permanent or unlogged tables" msgstr "UNLOGGEDテーブルに対する制約は、永続テーブルまたはUNLOGGEDテーブルだけを参照する場合があります" -#: commands/tablecmds.c:9675 +#: commands/tablecmds.c:10088 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "一時テーブルに対する制約は一時テーブルだけを参照する場合があります" -#: commands/tablecmds.c:9679 +#: commands/tablecmds.c:10092 #, c-format msgid "constraints on temporary tables must involve temporary tables of this session" msgstr "一時テーブルに対する制約にはこのセッションの一時テーブルを加える必要があります" -#: commands/tablecmds.c:9743 commands/tablecmds.c:9749 +#: commands/tablecmds.c:10107 commands/tablecmds.c:10135 +#, c-format +msgid "foreign key uses PERIOD on the referenced table but not the referencing table" +msgstr "外部キーが参照先テーブル上ではPERIODを使用していますが、参照元テーブルでは使用していません" + +#: commands/tablecmds.c:10147 +#, c-format +msgid "foreign key uses PERIOD on the referencing table but not the referenced table" +msgstr "外部キーが参照元テーブル上ではPERIODを使用していますが、参照先テーブルでは使用していません" + +#: commands/tablecmds.c:10161 +#, c-format +msgid "foreign key must use PERIOD when referencing a primary using WITHOUT OVERLAPS" +msgstr "主キーがWITHOUT OVERLAPSを使用している場合は外部キーはPERIODを使用する必要があります" + +#: commands/tablecmds.c:10185 commands/tablecmds.c:10191 #, c-format msgid "invalid %s action for foreign key constraint containing generated column" msgstr "生成カラムを含む外部キー制約に対する不正な %s 処理" -#: commands/tablecmds.c:9765 +#: commands/tablecmds.c:10206 +#, c-format +msgid "foreign key constraints on virtual generated columns are not supported" +msgstr "外部キー制約は仮想生成列ではサポートされていません" + +#: commands/tablecmds.c:10220 commands/tablecmds.c:10229 +#, c-format +msgid "unsupported %s action for foreign key constraint using PERIOD" +msgstr "PERIODを使用する外部キー制約に対するサポートされない %s 処理" + +#: commands/tablecmds.c:10244 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "外部キーの参照列数と被参照列数が合いません" -#: commands/tablecmds.c:9872 +#: commands/tablecmds.c:10300 +#, c-format +msgid "could not identify an overlaps operator for foreign key" +msgstr "外部キーに使用する重複検出演算子を特定できませんでした" + +#: commands/tablecmds.c:10301 +#, c-format +msgid "could not identify an equality operator for foreign key" +msgstr "外部キーに使用する等価演算子を特定できませんでした" + +#: commands/tablecmds.c:10366 commands/tablecmds.c:10400 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "外部キー制約\"%sは実装されていません" -#: commands/tablecmds.c:9874 +#: commands/tablecmds.c:10368 +#, c-format +msgid "Key columns \"%s\" of the referencing table and \"%s\" of the referenced table are of incompatible types: %s and %s." +msgstr "キー列である参照元テーブルの\"%1$s\"と参照先テーブルの\"%2$s\"の型に互換性がありません: %3$sと%4$s。" + +#: commands/tablecmds.c:10401 #, c-format -msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." -msgstr "キーとなる列\"%s\"と\"%s\"との間で型に互換性がありません:%sと%s" +msgid "Key columns \"%s\" of the referencing table and \"%s\" of the referenced table have incompatible collations: \"%s\" and \"%s\". If either collation is nondeterministic, then both collations have to be the same." +msgstr "キー列である参照元テーブルの\"%1$s\"と参照先テーブルの\"%2$s\"の照合順序に互換性がありません: %3$sと%4$s。いずれかの照合順序が非決定的である場合は両方の照合順序が同一である必要があります。" -#: commands/tablecmds.c:10031 +#: commands/tablecmds.c:10607 #, c-format msgid "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" msgstr "ON DELETE SETアクションで参照されている列\"%s\"は外部キーの一部である必要があります" -#: commands/tablecmds.c:10305 commands/tablecmds.c:10775 parser/parse_utilcmd.c:797 parser/parse_utilcmd.c:920 +#: commands/tablecmds.c:10989 commands/tablecmds.c:11435 parser/parse_utilcmd.c:941 parser/parse_utilcmd.c:1086 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "外部テーブルでは外部キー制約はサポートされていません" -#: commands/tablecmds.c:11328 commands/tablecmds.c:11609 commands/tablecmds.c:12521 commands/tablecmds.c:12595 +#: commands/tablecmds.c:11418 +#, c-format +msgid "cannot attach table \"%s\" as a partition because it is referenced by foreign key \"%s\"" +msgstr "外部キー\"%2$s\"で参照されているため、テーブル\"%1$s\"を子テーブルとしてアタッチすることはできません" + +#: commands/tablecmds.c:11699 +#, c-format +msgid "constraint \"%s\" enforceability conflicts with constraint \"%s\" on relation \"%s\"" +msgstr "制約\"%1$s\"の強制性が、リレーション\"%3$s\"上の制約\"%2$s\"と競合しています" + +#: commands/tablecmds.c:12158 +#, c-format +msgid "constraint must be altered in child tables too" +msgstr "制約は子テーブルでも変更される必要があります" + +#: commands/tablecmds.c:12187 commands/tablecmds.c:12881 commands/tablecmds.c:13975 commands/tablecmds.c:14204 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "リレーション\"%2$s\"の制約\"%1$s\"は存在しません" -#: commands/tablecmds.c:11335 +#: commands/tablecmds.c:12194 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "リレーション\"%2$s\"の制約\"%1$s\"は外部キー制約ではありません" -#: commands/tablecmds.c:11373 +#: commands/tablecmds.c:12199 +#, c-format +msgid "cannot alter enforceability of constraint \"%s\" of relation \"%s\"" +msgstr "リレーション\"%2$s\"の制約\"%1$s\"の強制性を変更できません" + +#: commands/tablecmds.c:12205 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" is not a not-null constraint" +msgstr "リレーション\"%2$s\"の制約\"%1$s\"は非NULL制約ではありません" + +#: commands/tablecmds.c:12213 +#, c-format +msgid "cannot alter inherited constraint \"%s\" on relation \"%s\"" +msgstr "リレーション\"%2$s\"の継承された制約\"%1$s\"を変更できません" + +#: commands/tablecmds.c:12253 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" msgstr "リレーション\"%2$s\"の制約\"%1$s\"を変更できません" -#: commands/tablecmds.c:11376 +#: commands/tablecmds.c:12256 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "制約\"%1$s\"は、リレーション\"%3$s\"上の制約\"%2$s\"から派生しています。" -#: commands/tablecmds.c:11378 +#: commands/tablecmds.c:12258 #, c-format msgid "You may alter the constraint it derives from instead." msgstr "この制約の代わりに派生元の制約を変更することは可能です。" -#: commands/tablecmds.c:11617 +#: commands/tablecmds.c:12890 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" is not a foreign key, check, or not-null constraint" +msgstr "リレーション\"%2$s\"の制約\"%1$s\"は外部キー制約、検査制約、非NULL制約のいずれでもありません" + +#: commands/tablecmds.c:12896 #, c-format -msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" -msgstr "リレーション\"%2$s\"の制約\"%1$s\"は外部キー制約でも検査制約でもありません" +msgid "cannot validate NOT ENFORCED constraint" +msgstr "NOT ENFORCED制約は検証できません" -#: commands/tablecmds.c:11694 +#: commands/tablecmds.c:13085 commands/tablecmds.c:13185 #, c-format msgid "constraint must be validated on child tables too" msgstr "制約は子テーブルでも検証される必要があります" -#: commands/tablecmds.c:11781 +#: commands/tablecmds.c:13262 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "外部キー制約で参照される列\"%s\"が存在しません" -#: commands/tablecmds.c:11787 +#: commands/tablecmds.c:13268 #, c-format msgid "system columns cannot be used in foreign keys" msgstr "システム列は外部キーに使用できません" -#: commands/tablecmds.c:11791 +#: commands/tablecmds.c:13272 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "外部キーでは%dを超えるキーを持つことができません" -#: commands/tablecmds.c:11856 +#: commands/tablecmds.c:13340 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "被参照テーブル\"%s\"には遅延可能プライマリキーは使用できません" -#: commands/tablecmds.c:11873 +#: commands/tablecmds.c:13357 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "被参照テーブル\"%s\"にはプライマリキーがありません" -#: commands/tablecmds.c:11941 +#: commands/tablecmds.c:13430 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "外部キーの被参照列リストには重複があってはなりません" -#: commands/tablecmds.c:12033 +#: commands/tablecmds.c:13533 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "被参照テーブル\"%s\"に対しては、遅延可能な一意性制約は使用できません" -#: commands/tablecmds.c:12038 +#: commands/tablecmds.c:13538 #, c-format msgid "there is no unique constraint matching given keys for referenced table \"%s\"" msgstr "被参照テーブル\"%s\"に、指定したキーに一致する一意性制約がありません" -#: commands/tablecmds.c:12477 +#: commands/tablecmds.c:13979 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" +msgstr "リレーション\"%2$s\"の制約\"%1$s\"は存在しません、スキップします" + +#: commands/tablecmds.c:14024 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の継承された制約\"%1$s\"を削除できません" -#: commands/tablecmds.c:12527 +#: commands/tablecmds.c:14076 #, c-format -msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" -msgstr "リレーション\"%2$s\"の制約\"%1$s\"は存在しません、スキップします" +msgid "column \"%s\" is in a primary key" +msgstr "列\"%s\"はプライマリキーで使用しています" + +#: commands/tablecmds.c:14084 +#, c-format +msgid "column \"%s\" is in index used as replica identity" +msgstr "列\"%s\"は複製識別として使用中のインデックスに含まれています" -#: commands/tablecmds.c:12702 +#: commands/tablecmds.c:14317 #, c-format msgid "cannot alter column type of typed table" msgstr "型付けされたテーブルの列の型を変更できません" -#: commands/tablecmds.c:12729 +#: commands/tablecmds.c:14345 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "生成列の型変更の際にはUSINGを指定することはできません" + +#: commands/tablecmds.c:14346 commands/tablecmds.c:19726 commands/tablecmds.c:19819 commands/trigger.c:659 rewrite/rewriteHandler.c:949 rewrite/rewriteHandler.c:984 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "列\"%s\"は生成カラムです。" + +#: commands/tablecmds.c:14357 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "継承される列\"%s\"を変更できません" -#: commands/tablecmds.c:12738 +#: commands/tablecmds.c:14366 #, c-format msgid "cannot alter column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "列\"%s\"はリレーション\"%s\"のパーティションキーの一部であるため、変更できません" -#: commands/tablecmds.c:12788 +#: commands/tablecmds.c:14421 #, c-format msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s" msgstr "列\"%s\"に対するUSING句の結果は自動的に%s型に型変換できません" -#: commands/tablecmds.c:12791 +#: commands/tablecmds.c:14424 #, c-format msgid "You might need to add an explicit cast." msgstr "必要に応じて明示的な型変換を追加してください。" -#: commands/tablecmds.c:12795 +#: commands/tablecmds.c:14428 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "列\"%s\"は型%sには自動的に型変換できません" #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12798 +#: commands/tablecmds.c:14432 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "必要に応じて\"USING %s::%s\"を追加してください。" -#: commands/tablecmds.c:12897 +#: commands/tablecmds.c:14532 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "リレーション\"%2$s\"の継承列\"%1$s\"は変更できません" -#: commands/tablecmds.c:12926 +#: commands/tablecmds.c:14561 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "USING式が行全体テーブル参照を含んでいます。" -#: commands/tablecmds.c:12937 +#: commands/tablecmds.c:14572 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "継承される列\"%s\"の型を子テーブルで変更しなければなりません" -#: commands/tablecmds.c:13062 +#: commands/tablecmds.c:14697 #, c-format msgid "cannot alter type of column \"%s\" twice" msgstr "列\"%s\"の型を2回変更することはできません" -#: commands/tablecmds.c:13100 +#: commands/tablecmds.c:14735 #, c-format msgid "generation expression for column \"%s\" cannot be cast automatically to type %s" msgstr "カラム\"%s\"に対する生成式は自動的に%s型にキャストできません" -#: commands/tablecmds.c:13105 +#: commands/tablecmds.c:14740 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "列\"%s\"のデフォルト値を自動的に%s型にキャストできません" -#: commands/tablecmds.c:13409 +#: commands/tablecmds.c:15044 #, c-format msgid "cannot alter type of a column used by a function or procedure" msgstr "関数またはプロシージャで使用される列の型は変更できません" -#: commands/tablecmds.c:13410 commands/tablecmds.c:13425 commands/tablecmds.c:13445 commands/tablecmds.c:13464 commands/tablecmds.c:13523 +#: commands/tablecmds.c:15045 commands/tablecmds.c:15060 commands/tablecmds.c:15080 commands/tablecmds.c:15099 commands/tablecmds.c:15158 #, c-format msgid "%s depends on column \"%s\"" msgstr "%sは列\"%s\"に依存しています" -#: commands/tablecmds.c:13424 +#: commands/tablecmds.c:15059 #, c-format msgid "cannot alter type of a column used by a view or rule" msgstr "ビューまたはルールで使用される列の型は変更できません" -#: commands/tablecmds.c:13444 +#: commands/tablecmds.c:15079 #, c-format msgid "cannot alter type of a column used in a trigger definition" msgstr "トリガー定義で使用される列の型は変更できません" -#: commands/tablecmds.c:13463 +#: commands/tablecmds.c:15098 #, c-format msgid "cannot alter type of a column used in a policy definition" msgstr "ポリシ定義で使用されている列の型は変更できません" -#: commands/tablecmds.c:13494 +#: commands/tablecmds.c:15129 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "生成カラムで使用される列の型は変更できません" -#: commands/tablecmds.c:13495 +#: commands/tablecmds.c:15130 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "カラム\"%s\"は生成カラム\"%s\"で使われています。" -#: commands/tablecmds.c:13522 +#: commands/tablecmds.c:15157 #, c-format msgid "cannot alter type of a column used by a publication WHERE clause" msgstr "パブリケーションのWHERE句で使用される列の型は変更できません" -#: commands/tablecmds.c:14357 commands/tablecmds.c:14369 +#: commands/tablecmds.c:16008 commands/tablecmds.c:16020 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "インデックス\"%s\"の所有者を変更できません" -#: commands/tablecmds.c:14359 commands/tablecmds.c:14371 +#: commands/tablecmds.c:16010 commands/tablecmds.c:16022 #, c-format msgid "Change the ownership of the index's table instead." msgstr "代わりにインデックスのテーブルの所有者を変更してください。" -#: commands/tablecmds.c:14385 +#: commands/tablecmds.c:16036 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "シーケンス\"%s\"の所有者を変更できません" -#: commands/tablecmds.c:14410 +#: commands/tablecmds.c:16061 #, c-format msgid "cannot change owner of relation \"%s\"" msgstr "リレーション\"%s\"の所有者を変更できません" -#: commands/tablecmds.c:14877 +#: commands/tablecmds.c:16528 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "SET TABLESPACEサブコマンドを複数指定できません" -#: commands/tablecmds.c:14954 +#: commands/tablecmds.c:16607 #, c-format msgid "cannot set options for relation \"%s\"" msgstr "リレーション\"%s\"のオプションは設定できません" -#: commands/tablecmds.c:14988 commands/view.c:440 +#: commands/tablecmds.c:16641 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "WITH CHECK OPTIONは自動更新可能ビューでのみサポートされます" -#: commands/tablecmds.c:15238 +#: commands/tablecmds.c:16894 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "テーブルスペースにはテーブル、インデックスおよび実体化ビューしかありません" -#: commands/tablecmds.c:15250 +#: commands/tablecmds.c:16906 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "pg_globalテーブルスペースとの間のリレーションの移動はできません" -#: commands/tablecmds.c:15342 +#: commands/tablecmds.c:16998 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "リレーション\"%s.%s\"のロックが獲得できなかったため中断します" -#: commands/tablecmds.c:15358 +#: commands/tablecmds.c:17014 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr "テーブルスペース\"%s\"には合致するリレーションはありませんでした" -#: commands/tablecmds.c:15480 +#: commands/tablecmds.c:17136 #, c-format msgid "cannot change inheritance of typed table" msgstr "型付けされたテーブルの継承を変更できません" -#: commands/tablecmds.c:15485 commands/tablecmds.c:15985 +#: commands/tablecmds.c:17141 commands/tablecmds.c:17725 #, c-format msgid "cannot change inheritance of a partition" msgstr "パーティションの継承は変更できません" -#: commands/tablecmds.c:15490 +#: commands/tablecmds.c:17146 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "パーティションテーブルの継承は変更できません" -#: commands/tablecmds.c:15536 +#: commands/tablecmds.c:17193 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "他のセッションの一時テーブルを継承できません" -#: commands/tablecmds.c:15549 +#: commands/tablecmds.c:17206 #, c-format msgid "cannot inherit from a partition" msgstr "パーティションからの継承はできません" -#: commands/tablecmds.c:15571 commands/tablecmds.c:18453 +#: commands/tablecmds.c:17228 commands/tablecmds.c:20239 #, c-format msgid "circular inheritance not allowed" msgstr "循環継承を行うことはできません" -#: commands/tablecmds.c:15572 commands/tablecmds.c:18454 +#: commands/tablecmds.c:17229 commands/tablecmds.c:20240 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "\"%s\"はすでに\"%s\"の子です" -#: commands/tablecmds.c:15585 +#: commands/tablecmds.c:17242 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "トリガ\"%s\"によってテーブル\"%s\"が継承子テーブルになることができません" -#: commands/tablecmds.c:15587 +#: commands/tablecmds.c:17244 #, c-format msgid "ROW triggers with transition tables are not supported in inheritance hierarchies." msgstr "遷移テーブルを使用したROWトリガは継承関係ではサポートされていません。" -#: commands/tablecmds.c:15776 +#: commands/tablecmds.c:17445 commands/tablecmds.c:17694 #, c-format -msgid "column \"%s\" in child table must be marked NOT NULL" -msgstr "子テーブルの列\"%s\"はNOT NULLである必要があります" +msgid "column \"%s\" in child table \"%s\" must be marked NOT NULL" +msgstr "子テーブル\"%2$s\"の列\"%1$s\"は非NULLに設定されていません" -#: commands/tablecmds.c:15785 +#: commands/tablecmds.c:17455 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "子テーブルの列\"%s\"は生成列である必要があります" -#: commands/tablecmds.c:15789 +#: commands/tablecmds.c:17459 #, c-format msgid "column \"%s\" in child table must not be a generated column" msgstr "子テーブルの列\"%s\"は生成列であってはなりません" -#: commands/tablecmds.c:15827 +#: commands/tablecmds.c:17505 #, c-format msgid "child table is missing column \"%s\"" msgstr "子テーブルには列\"%s\"がありません" -#: commands/tablecmds.c:15908 +#: commands/tablecmds.c:17622 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "子テーブル\"%s\"では検査制約\"%s\"に異なった定義がされています" -#: commands/tablecmds.c:15915 +#: commands/tablecmds.c:17631 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"" msgstr "制約\"%s\"は子テーブル\"%s\"上の継承されない制約と競合します" -#: commands/tablecmds.c:15925 +#: commands/tablecmds.c:17642 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" msgstr "制約\"%s\"は子テーブル\"%s\"のNOT VALID制約と衝突しています" -#: commands/tablecmds.c:15963 +#: commands/tablecmds.c:17653 +#, c-format +msgid "constraint \"%s\" conflicts with NOT ENFORCED constraint on child table \"%s\"" +msgstr "制約\"%s\"は子テーブル\"%s\"のNOT ENFORCED制約と衝突しています" + +#: commands/tablecmds.c:17702 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "子テーブルには制約\"%s\"がありません" -#: commands/tablecmds.c:16049 +#: commands/tablecmds.c:17789 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "パーティション\"%s\"はすでにパーティションテーブル\"%s.%s\"からの取り外し保留中です" -#: commands/tablecmds.c:16078 commands/tablecmds.c:16124 parser/parse_utilcmd.c:3261 +#: commands/tablecmds.c:17818 commands/tablecmds.c:17866 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "リレーション\"%s\"はリレーション\"%s\"のパーティション子テーブルではありません" -#: commands/tablecmds.c:16130 +#: commands/tablecmds.c:17872 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "リレーション\"%s\"はリレーション\"%s\"の親ではありません" -#: commands/tablecmds.c:16357 +#: commands/tablecmds.c:18143 #, c-format msgid "typed tables cannot inherit" msgstr "型付けされたテーブルは継承できません" -#: commands/tablecmds.c:16387 +#: commands/tablecmds.c:18173 #, c-format msgid "table is missing column \"%s\"" msgstr "テーブルには列\"%s\"がありません" -#: commands/tablecmds.c:16398 +#: commands/tablecmds.c:18184 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "テーブルには列\"%s\"がありますが型は\"%s\"を必要としています" -#: commands/tablecmds.c:16407 +#: commands/tablecmds.c:18193 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "テーブル\"%s\"では列\"%s\"の型が異なっています" -#: commands/tablecmds.c:16421 +#: commands/tablecmds.c:18207 #, c-format msgid "table has extra column \"%s\"" msgstr "テーブルに余分な列\"%s\"があります" -#: commands/tablecmds.c:16473 +#: commands/tablecmds.c:18259 #, c-format msgid "\"%s\" is not a typed table" msgstr "\"%s\"は型付けされたテーブルではありません" -#: commands/tablecmds.c:16647 +#: commands/tablecmds.c:18439 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "非ユニークインデックス\"%s\"は複製識別としては使用できません" -#: commands/tablecmds.c:16653 +#: commands/tablecmds.c:18445 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "一意性を即時検査しないインデックス\"%s\"は複製識別には使用できません" -#: commands/tablecmds.c:16659 +#: commands/tablecmds.c:18451 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "式インデックス\"%s\"は複製識別としては使用できません" -#: commands/tablecmds.c:16665 +#: commands/tablecmds.c:18457 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "部分インデックス\"%s\"を複製識別としては使用できません" -#: commands/tablecmds.c:16682 +#: commands/tablecmds.c:18474 #, c-format msgid "index \"%s\" cannot be used as replica identity because column %d is a system column" msgstr "列%2$dはシステム列であるためインデックス\"%1$s\"は複製識別には使えません" -#: commands/tablecmds.c:16689 +#: commands/tablecmds.c:18481 #, c-format msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable" msgstr "列\"%2$s\"はnull可であるためインデックス\"%1$s\"は複製識別には使えません" -#: commands/tablecmds.c:16941 +#: commands/tablecmds.c:18730 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "テーブル\"%s\"は一時テーブルであるため、ログ出力設定を変更できません" -#: commands/tablecmds.c:16965 +#: commands/tablecmds.c:18754 #, c-format msgid "cannot change table \"%s\" to unlogged because it is part of a publication" msgstr "テーブル\"%s\"はパブリケーションの一部であるため、UNLOGGEDに変更できません" -#: commands/tablecmds.c:16967 +#: commands/tablecmds.c:18756 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "UNLOGGEDリレーションはレプリケーションできません。" -#: commands/tablecmds.c:17012 +#: commands/tablecmds.c:18801 #, c-format msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\"" msgstr "テーブル\"%s\"はUNLOGGEDテーブル\"%s\"を参照しているためLOGGEDには設定できません" -#: commands/tablecmds.c:17022 +#: commands/tablecmds.c:18811 #, c-format msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\"" msgstr "テーブル\"%s\"はLOGGEDテーブル\"%s\"を参照しているためUNLOGGEDには設定できません" -#: commands/tablecmds.c:17080 +#: commands/tablecmds.c:18875 #, c-format msgid "cannot move an owned sequence into another schema" msgstr "所有するシーケンスを他のスキーマに移動することができません" -#: commands/tablecmds.c:17185 +#: commands/tablecmds.c:18983 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "リレーション\"%s\"はスキーマ\"%s\"内にすでに存在します" -#: commands/tablecmds.c:17606 +#: commands/tablecmds.c:19408 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "\"%s\"はテーブルや実体化ビューではありません" -#: commands/tablecmds.c:17759 +#: commands/tablecmds.c:19561 #, c-format msgid "\"%s\" is not a composite type" msgstr "\"%s\"は複合型ではありません" -#: commands/tablecmds.c:17789 +#: commands/tablecmds.c:19591 #, c-format msgid "cannot change schema of index \"%s\"" msgstr "インデックス\"%s\"のスキーマを変更できません" -#: commands/tablecmds.c:17791 commands/tablecmds.c:17805 +#: commands/tablecmds.c:19593 commands/tablecmds.c:19607 #, c-format msgid "Change the schema of the table instead." msgstr "代わりにこのテーブルのスキーマを変更してください。" -#: commands/tablecmds.c:17795 +#: commands/tablecmds.c:19597 #, c-format msgid "cannot change schema of composite type \"%s\"" msgstr "複合型%sのスキーマは変更できません" -#: commands/tablecmds.c:17803 +#: commands/tablecmds.c:19605 #, c-format msgid "cannot change schema of TOAST table \"%s\"" msgstr "TOASTテーブル\"%s\"のスキーマは変更できません" -#: commands/tablecmds.c:17835 +#: commands/tablecmds.c:19637 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "\"list\"パーティションストラテジは2つ以上の列に対しては使えません" -#: commands/tablecmds.c:17901 +#: commands/tablecmds.c:19703 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "パーティションキーに指定されている列\"%s\"は存在しません" -#: commands/tablecmds.c:17909 +#: commands/tablecmds.c:19711 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "パーティションキーでシステム列\"%s\"は使用できません" -#: commands/tablecmds.c:17920 commands/tablecmds.c:18010 +#: commands/tablecmds.c:19725 commands/tablecmds.c:19818 #, c-format msgid "cannot use generated column in partition key" msgstr "パーティションキーで生成カラムは使用できません" -#: commands/tablecmds.c:17921 commands/tablecmds.c:18011 commands/trigger.c:656 rewrite/rewriteHandler.c:934 rewrite/rewriteHandler.c:969 -#, c-format -msgid "Column \"%s\" is a generated column." -msgstr "列\"%s\"は生成カラムです。" - -#: commands/tablecmds.c:17993 +#: commands/tablecmds.c:19798 #, c-format msgid "partition key expressions cannot contain system column references" msgstr "パーティションキー式はシステム列への参照を含むことができません" -#: commands/tablecmds.c:18040 +#: commands/tablecmds.c:19848 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "パーティションキー式で使われる関数はIMMUTABLE指定されている必要があります" -#: commands/tablecmds.c:18049 +#: commands/tablecmds.c:19857 #, c-format msgid "cannot use constant expression as partition key" msgstr "定数式をパーティションキーとして使うことはできません" -#: commands/tablecmds.c:18070 +#: commands/tablecmds.c:19878 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "パーティション式で使用する照合順序を特定できませんでした" -#: commands/tablecmds.c:18105 +#: commands/tablecmds.c:19913 #, c-format msgid "You must specify a hash operator class or define a default hash operator class for the data type." msgstr "ハッシュ演算子クラスを指定するか、もしくはこのデータ型にデフォルトのハッシュ演算子クラスを定義する必要があります。" -#: commands/tablecmds.c:18111 +#: commands/tablecmds.c:19919 #, c-format msgid "You must specify a btree operator class or define a default btree operator class for the data type." msgstr "btree演算子クラスを指定するか、もしくはこのデータ型にデフォルトのbtree演算子クラスを定義するかする必要があります。" -#: commands/tablecmds.c:18393 +#: commands/tablecmds.c:20179 #, c-format msgid "\"%s\" is already a partition" msgstr "\"%s\"はすでパーティションです" -#: commands/tablecmds.c:18399 +#: commands/tablecmds.c:20185 #, c-format msgid "cannot attach a typed table as partition" msgstr "型付けされたテーブルをパーティションにアタッチすることはできません" -#: commands/tablecmds.c:18415 +#: commands/tablecmds.c:20201 #, c-format msgid "cannot attach inheritance child as partition" msgstr "継承子テーブルをパーティションにアタッチすることはできません" -#: commands/tablecmds.c:18429 +#: commands/tablecmds.c:20215 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "継承親テーブルをパーティションにアタッチすることはできません" -#: commands/tablecmds.c:18463 +#: commands/tablecmds.c:20249 #, c-format msgid "cannot attach a temporary relation as partition of permanent relation \"%s\"" msgstr "一時リレーションを永続リレーション \"%s\" のパーティション子テーブルとしてアタッチすることはできません" -#: commands/tablecmds.c:18471 +#: commands/tablecmds.c:20257 #, c-format msgid "cannot attach a permanent relation as partition of temporary relation \"%s\"" msgstr "永続リレーションを一時リレーション\"%s\"のパーティション子テーブルとしてアタッチすることはできません" -#: commands/tablecmds.c:18479 +#: commands/tablecmds.c:20265 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "他セッションの一時リレーションのパーティション子テーブルとしてアタッチすることはできません" -#: commands/tablecmds.c:18486 +#: commands/tablecmds.c:20272 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "他セッションの一時リレーションにパーティション子テーブルとしてアタッチすることはできません" -#: commands/tablecmds.c:18506 +#: commands/tablecmds.c:20292 #, c-format msgid "table \"%s\" being attached contains an identity column \"%s\"" msgstr "アタッチ対象のテーブル\"%s\"には識別列\"%s\"が含まれています" -#: commands/tablecmds.c:18508 +#: commands/tablecmds.c:20294 #, c-format msgid "The new partition may not contain an identity column." msgstr "新しいパーティションは識別列を含むことはできません" -#: commands/tablecmds.c:18516 +#: commands/tablecmds.c:20302 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "テーブル\"%1$s\"は親テーブル\"%3$s\"にない列\"%2$s\"を含んでいます" -#: commands/tablecmds.c:18519 +#: commands/tablecmds.c:20305 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "新しいパーティションは親に存在する列のみを含むことができます。" -#: commands/tablecmds.c:18531 +#: commands/tablecmds.c:20317 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "トリガ\"%s\"のため、テーブル\"%s\"はパーティション子テーブルにはなれません" -#: commands/tablecmds.c:18533 +#: commands/tablecmds.c:20319 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "遷移テーブルを使用するROWトリガはパーティションではサポートされません。" -#: commands/tablecmds.c:18694 +#: commands/tablecmds.c:20501 #, c-format msgid "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "外部テーブル\"%s\"はパーティションテーブル\"%s\"の子テーブルとしてアタッチすることはできません" -#: commands/tablecmds.c:18697 +#: commands/tablecmds.c:20504 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "パーティション親テーブル\"%s\"はユニークインデックスを持っています。" -#: commands/tablecmds.c:19019 +#: commands/tablecmds.c:20827 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "デフォルトパーティションを持つパーティションは並列的に取り外しはできません" -#: commands/tablecmds.c:19128 +#: commands/tablecmds.c:20936 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "パーティション親テーブル\"%s\"には CREATE INDEX CONCURRENTLY は実行できません" -#: commands/tablecmds.c:19134 +#: commands/tablecmds.c:20942 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "パーティション子テーブル\\\"%s\\\"は同時に削除されました" -#: commands/tablecmds.c:19661 commands/tablecmds.c:19681 commands/tablecmds.c:19702 commands/tablecmds.c:19721 commands/tablecmds.c:19763 +#: commands/tablecmds.c:21565 commands/tablecmds.c:21585 commands/tablecmds.c:21606 commands/tablecmds.c:21625 commands/tablecmds.c:21674 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "インデックス\"%s\"をインデックス\"%s\"の子インデックスとしてアタッチすることはできません" -#: commands/tablecmds.c:19664 +#: commands/tablecmds.c:21568 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "インデックス\"%s\"はすでに別のインデックスにアタッチされています。" -#: commands/tablecmds.c:19684 +#: commands/tablecmds.c:21588 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "インデックス\"%s\"はテーブル\"%s\"のどの子テーブルのインデックスでもありません。" -#: commands/tablecmds.c:19705 +#: commands/tablecmds.c:21609 #, c-format msgid "The index definitions do not match." msgstr "インデックス定義が合致しません。" -#: commands/tablecmds.c:19724 +#: commands/tablecmds.c:21628 #, c-format msgid "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint exists for index \"%s\"." msgstr "インデックス\"%s\"はテーブル\"%s\"の制約に属していますが、インデックス\"%s\"には制約がありません。" -#: commands/tablecmds.c:19766 +#: commands/tablecmds.c:21677 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "子テーブル\"%s\"にはすでに他のインデックスがアタッチされています。" -#: commands/tablecmds.c:20002 +#: commands/tablecmds.c:21800 +#, c-format +msgid "invalid primary key definition" +msgstr "不正な主キー定義" + +#: commands/tablecmds.c:21801 +#, c-format +msgid "Column \"%s\" of relation \"%s\" is not marked NOT NULL." +msgstr "リレーション\"%2$s\"の列\"%1$s\"は非NULLに設定されていません。" + +#: commands/tablecmds.c:21936 #, c-format msgid "column data type %s does not support compression" msgstr "列データ型%sは圧縮をサポートしていません" -#: commands/tablecmds.c:20009 +#: commands/tablecmds.c:21943 #, c-format msgid "invalid compression method \"%s\"" msgstr "無効な圧縮方式\"%s\"" -#: commands/tablecmds.c:20035 +#: commands/tablecmds.c:21969 #, c-format msgid "invalid storage type \"%s\"" msgstr "不正な格納タイプ\"%s\"" -#: commands/tablecmds.c:20045 +#: commands/tablecmds.c:21979 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "列のデータ型%sは格納タイプPLAINしか取ることができません" -#: commands/tablecmds.c:20242 -#, c-format -msgid "can not find partition for split partition row" -msgstr "パーティション分割行に該当するパーティションが見つかりません" - -#: commands/tablecmds.c:20328 -#, c-format -msgid "cannot create as partition of temporary relation of another session" -msgstr "他セッションの一時リレーションのパーティション子テーブルとして作成することはできません" - -#: commands/tablecmds.c:20399 -#, c-format -msgid "cannot create a permanent relation as partition of temporary relation \"%s\"" -msgstr "永続リレーションを一時リレーション\"%s\"のパーティション子テーブルとして作成することはできません" - #: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" @@ -11631,277 +11863,272 @@ msgstr "テーブル空間%u用のディレクトリを削除することがで msgid "You can remove the directories manually if necessary." msgstr "必要ならば手作業でこのディレクトリを削除することができます" -#: commands/trigger.c:225 commands/trigger.c:236 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "\"%s\" is a table" msgstr "\"%s\"はテーブルです" -#: commands/trigger.c:227 commands/trigger.c:238 +#: commands/trigger.c:229 commands/trigger.c:240 #, c-format msgid "Tables cannot have INSTEAD OF triggers." msgstr "テーブルは INSTEAD OF トリガーを持つことができません" -#: commands/trigger.c:259 +#: commands/trigger.c:261 #, c-format msgid "\"%s\" is a partitioned table" msgstr "\"%s\"はパーティション親テーブルです" -#: commands/trigger.c:261 +#: commands/trigger.c:263 #, c-format msgid "ROW triggers with transition tables are not supported on partitioned tables." msgstr "遷移テーブルを使用するROWトリガはパーティション親テーブルではサポートされません。" -#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 +#: commands/trigger.c:275 commands/trigger.c:282 commands/trigger.c:446 #, c-format msgid "\"%s\" is a view" msgstr "\"%s\"はビューです" -#: commands/trigger.c:275 +#: commands/trigger.c:277 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." msgstr "ビューは行レベルの BEFORE / AFTER トリガーを持つことができません" -#: commands/trigger.c:282 +#: commands/trigger.c:284 #, c-format msgid "Views cannot have TRUNCATE triggers." msgstr "ビューは TRUNCATE トリガーを持つことができません" -#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 +#: commands/trigger.c:292 commands/trigger.c:304 commands/trigger.c:439 #, c-format msgid "\"%s\" is a foreign table" msgstr "\"%s\"は外部テーブルです" -#: commands/trigger.c:292 +#: commands/trigger.c:294 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." msgstr "外部テーブルは INSTEAD OF トリガを持つことができません。" -#: commands/trigger.c:304 +#: commands/trigger.c:306 #, c-format msgid "Foreign tables cannot have constraint triggers." msgstr "外部テーブルは制約トリガを持つことができません。" -#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 +#: commands/trigger.c:311 commands/trigger.c:1330 commands/trigger.c:1437 #, c-format msgid "relation \"%s\" cannot have triggers" msgstr "リレーション\"%s\"にはトリガーを設定できません" -#: commands/trigger.c:380 +#: commands/trigger.c:382 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" msgstr "TRUNCATE FOR EACH ROW トリガはサポートされていません" -#: commands/trigger.c:388 +#: commands/trigger.c:390 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" msgstr "INSTEAD OF トリガーは FOR EACH ROW でなければなりません" -#: commands/trigger.c:392 +#: commands/trigger.c:394 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" msgstr "INSTEAD OF トリガーは WHEN 条件を持つことができません" -#: commands/trigger.c:396 +#: commands/trigger.c:398 #, c-format msgid "INSTEAD OF triggers cannot have column lists" msgstr "INSTEAD OF トリガーは列リストを持つことができません" -#: commands/trigger.c:425 +#: commands/trigger.c:427 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "REFERENCING句でのROW変数の命名はサポートされていません" -#: commands/trigger.c:426 +#: commands/trigger.c:428 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "遷移テーブルを指定するには OLD TABLE または NEW TABLE を使ってください" -#: commands/trigger.c:439 +#: commands/trigger.c:441 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "外部テーブルに対するトリガは遷移テーブルを持てません。" -#: commands/trigger.c:446 +#: commands/trigger.c:448 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "ビューに対するトリガは遷移テーブルを持てません。" -#: commands/trigger.c:462 +#: commands/trigger.c:464 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "遷移テーブルを使用するROWトリガはパーティションではサポートされません" -#: commands/trigger.c:466 +#: commands/trigger.c:468 #, c-format msgid "ROW triggers with transition tables are not supported on inheritance children" msgstr "遷移テーブルをもったROWトリガは継承子テーブルではサポートされません" -#: commands/trigger.c:472 +#: commands/trigger.c:474 #, c-format msgid "transition table name can only be specified for an AFTER trigger" msgstr "遷移テーブル名はAFTERトリガでの指定可能です" -#: commands/trigger.c:477 +#: commands/trigger.c:479 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "遷移テーブルを使用するTRUNCATEトリガはサポートされていません" -#: commands/trigger.c:494 +#: commands/trigger.c:496 #, c-format msgid "transition tables cannot be specified for triggers with more than one event" msgstr "2つ以上のイベントに対するトリガには遷移テーブルは指定できません" -#: commands/trigger.c:505 +#: commands/trigger.c:507 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "列リストを指定したトリガに対しては遷移テーブルは指定できません" -#: commands/trigger.c:522 +#: commands/trigger.c:524 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" msgstr "NEW TABLE はINSERTまたはUPDATEトリガに対してのみ指定可能です" -#: commands/trigger.c:527 +#: commands/trigger.c:529 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE は複数回指定できません" -#: commands/trigger.c:537 +#: commands/trigger.c:539 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" msgstr "OLD TABLE はDELETEまたはUPDATEトリガに対してのみ指定可能です" -#: commands/trigger.c:542 +#: commands/trigger.c:544 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE は複数回指定できません" -#: commands/trigger.c:552 +#: commands/trigger.c:554 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "OLD TABLE の名前と NEW TABLE の名前は同じにはできません" -#: commands/trigger.c:616 commands/trigger.c:629 +#: commands/trigger.c:618 commands/trigger.c:631 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" msgstr "ステートメントトリガーの WHEN 条件では列の値を参照できません" -#: commands/trigger.c:621 +#: commands/trigger.c:623 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" msgstr "INSERT トリガーの WHEN 条件では OLD 値を参照できません" -#: commands/trigger.c:634 +#: commands/trigger.c:636 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" msgstr "DELETE トリガーの WHEN 条件では NEW 値を参照できません" -#: commands/trigger.c:639 +#: commands/trigger.c:641 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" msgstr "BEFORE トリガーの WHEN 条件では NEW システム列を参照できません" -#: commands/trigger.c:647 commands/trigger.c:655 +#: commands/trigger.c:650 commands/trigger.c:658 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "BEFORE トリガーの WHEN 条件では NEW の生成列を参照できません" -#: commands/trigger.c:648 +#: commands/trigger.c:651 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "行全体参照が使われていてかつ、このテーブルは生成カラムを含んでいます。" -#: commands/trigger.c:763 commands/trigger.c:1607 +#: commands/trigger.c:766 commands/trigger.c:1613 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "リレーション\"%2$s\"用のトリガ\"%1$s\"はすでに存在します" -#: commands/trigger.c:776 +#: commands/trigger.c:779 #, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" msgstr "リレーション\"%2$s\"のトリガー\"%1$s\"は内部トリガーまたは子トリガーです" -#: commands/trigger.c:795 +#: commands/trigger.c:798 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" msgstr "リレーション\"%2$s\"のトリガー\"%1$s\"は制約トリガーです" -#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 +#: commands/trigger.c:1402 commands/trigger.c:1556 commands/trigger.c:1837 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "テーブル\"%2$s\"のトリガ\"%1$s\"は存在しません" -#: commands/trigger.c:1522 +#: commands/trigger.c:1528 #, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" msgstr "テーブル\"%2$s\"のトリガー\"%1$s\"の名前は変更できません" -#: commands/trigger.c:1524 +#: commands/trigger.c:1530 #, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." msgstr "代わりにパーティション親テーブル\"%s\"でこのトリガーの名前を変更してください。" -#: commands/trigger.c:1624 +#: commands/trigger.c:1630 #, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" msgstr "リレーション\"%2$s\"のトリガー\"%1$s\"の名前を変更しました" -#: commands/trigger.c:1770 +#: commands/trigger.c:1776 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "権限がありません: \"%s\"はシステムトリガです" -#: commands/trigger.c:2379 +#: commands/trigger.c:2385 #, c-format msgid "trigger function %u returned null value" msgstr "トリガ関数%uはNULL値を返しました" -#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 commands/trigger.c:3263 +#: commands/trigger.c:2445 commands/trigger.c:2665 commands/trigger.c:2918 commands/trigger.c:3273 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "BEFORE STATEMENTトリガは値を返すことができません" -#: commands/trigger.c:2515 +#: commands/trigger.c:2523 #, c-format msgid "moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported" msgstr "BEFORE FOR EACH ROWトリガの実行では、他のパーティションへの行の移動はサポートされていません" -#: commands/trigger.c:2516 +#: commands/trigger.c:2524 #, c-format msgid "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." msgstr "トリガ\"%s\"の実行前には、この行はパーティション\"%s.%s\"に置かれるはずでした。" -#: commands/trigger.c:3340 executor/nodeModifyTable.c:2363 executor/nodeModifyTable.c:2446 -#, c-format -msgid "tuple to be updated was already modified by an operation triggered by the current command" -msgstr "更新対象のタプルはすでに現在のコマンドによって起動された操作によって変更されています" - -#: commands/trigger.c:3341 executor/nodeModifyTable.c:1532 executor/nodeModifyTable.c:1606 executor/nodeModifyTable.c:2364 executor/nodeModifyTable.c:2447 executor/nodeModifyTable.c:3075 executor/nodeModifyTable.c:3236 +#: commands/trigger.c:3351 executor/nodeModifyTable.c:1665 executor/nodeModifyTable.c:1739 executor/nodeModifyTable.c:2546 executor/nodeModifyTable.c:2636 executor/nodeModifyTable.c:3308 executor/nodeModifyTable.c:3478 #, c-format msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows." msgstr "他の行への変更を伝搬させるためにBEFOREトリガではなくAFTERトリガの使用を検討してください" -#: commands/trigger.c:3382 executor/nodeLockRows.c:228 executor/nodeLockRows.c:237 executor/nodeModifyTable.c:305 executor/nodeModifyTable.c:1548 executor/nodeModifyTable.c:2381 executor/nodeModifyTable.c:2589 +#: commands/trigger.c:3392 executor/nodeLockRows.c:228 executor/nodeLockRows.c:237 executor/nodeModifyTable.c:368 executor/nodeModifyTable.c:1681 executor/nodeModifyTable.c:2562 executor/nodeModifyTable.c:2787 #, c-format msgid "could not serialize access due to concurrent update" msgstr "更新が同時に行われたためアクセスの直列化ができませんでした" -#: commands/trigger.c:3390 executor/nodeModifyTable.c:1638 executor/nodeModifyTable.c:2464 executor/nodeModifyTable.c:2613 executor/nodeModifyTable.c:3093 +#: commands/trigger.c:3400 executor/nodeModifyTable.c:1771 executor/nodeModifyTable.c:2653 executor/nodeModifyTable.c:2811 executor/nodeModifyTable.c:3326 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "削除が同時に行われたためアクセスの直列化ができませんでした" -#: commands/trigger.c:4597 +#: commands/trigger.c:4635 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" msgstr "セキュリティー制限操作中は、遅延トリガーは発火させられません" -#: commands/trigger.c:5780 +#: commands/trigger.c:5831 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "制約\"%s\"は遅延可能ではありません" -#: commands/trigger.c:5803 +#: commands/trigger.c:5854 #, c-format msgid "constraint \"%s\" does not exist" msgstr "制約\"%s\"は存在しません" @@ -12011,7 +12238,7 @@ msgstr "基本型を作成するにはスーパーユーザーである必要が msgid "Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE." msgstr "最初に型をシェル型として生成して、続いてI/O関数を生成した後に完全な CREATE TYPE を実行してください。" -#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 +#: commands/typecmds.c:331 commands/typecmds.c:1486 commands/typecmds.c:4471 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "型の属性\"%s\"は不明です" @@ -12031,7 +12258,7 @@ msgstr "%sを配列要素の型にすることはできません" msgid "alignment \"%s\" not recognized" msgstr "アライメント\"%s\"は不明です" -#: commands/typecmds.c:454 commands/typecmds.c:4354 +#: commands/typecmds.c:454 commands/typecmds.c:4345 #, c-format msgid "storage \"%s\" not recognized" msgstr "格納方式\"%s\"は不明です" @@ -12061,332 +12288,347 @@ msgstr "添字処理関数なしで要素型を指定することはできませ msgid "\"%s\" is not a valid base type for a domain" msgstr "\"%s\"はドメインの基本型として無効です" -#: commands/typecmds.c:883 +#: commands/typecmds.c:885 #, c-format msgid "multiple default expressions" msgstr "デフォルト式が複数あります" -#: commands/typecmds.c:946 commands/typecmds.c:955 +#: commands/typecmds.c:945 commands/typecmds.c:960 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "NULL制約とNOT NULL制約が競合しています" -#: commands/typecmds.c:971 +#: commands/typecmds.c:950 +#, c-format +msgid "not-null constraints for domains cannot be marked NO INHERIT" +msgstr "ドメインに対する非NULL制約はNO INHERIT指定できません" + +#: commands/typecmds.c:977 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "ドメインに対する検査制約はNO INHERITとマークすることができません" -#: commands/typecmds.c:980 commands/typecmds.c:2940 +#: commands/typecmds.c:988 #, c-format msgid "unique constraints not possible for domains" msgstr "ドメインでは一意性制約は使用できません" -#: commands/typecmds.c:986 commands/typecmds.c:2946 +#: commands/typecmds.c:995 #, c-format msgid "primary key constraints not possible for domains" msgstr "ドメインではプライマリキー制約はできません" -#: commands/typecmds.c:992 commands/typecmds.c:2952 +#: commands/typecmds.c:1002 #, c-format msgid "exclusion constraints not possible for domains" msgstr "ドメインでは排除制約は使用できません" -#: commands/typecmds.c:998 commands/typecmds.c:2958 +#: commands/typecmds.c:1009 #, c-format msgid "foreign key constraints not possible for domains" msgstr "ドメイン用の外部キー制約はできません" -#: commands/typecmds.c:1007 commands/typecmds.c:2967 +#: commands/typecmds.c:1019 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "ドメインでは制約遅延の指定はサポートしていません" -#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 +#: commands/typecmds.c:1027 +#, c-format +msgid "specifying GENERATED not supported for domains" +msgstr "ドメインではGENERATEDの指定はサポートしていません" + +#: commands/typecmds.c:1035 +#, c-format +msgid "specifying constraint enforceability not supported for domains" +msgstr "ドメインでは制約の強制性指定はサポートしていません" + +#: commands/typecmds.c:1353 utils/cache/typcache.c:2745 #, c-format msgid "%s is not an enum" msgstr "%s は数値ではありません" -#: commands/typecmds.c:1468 +#: commands/typecmds.c:1494 #, c-format msgid "type attribute \"subtype\" is required" msgstr "型の属性\"subtype\"が必要です" -#: commands/typecmds.c:1473 +#: commands/typecmds.c:1499 #, c-format msgid "range subtype cannot be %s" msgstr "範囲の派生元型を%sにすることはできません" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1518 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "範囲の照合順序が指定されましたが、派生もと型が照合順序をサポートしていません" -#: commands/typecmds.c:1502 +#: commands/typecmds.c:1528 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "事前にシェル型を生成せずに正規化関数を指定することはできません" -#: commands/typecmds.c:1503 +#: commands/typecmds.c:1529 #, c-format msgid "Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE." msgstr "最初に型をシェル型として生成して、続いて正規化関数を生成した後に完全な CREATE TYPE を実行してください。" -#: commands/typecmds.c:1975 +#: commands/typecmds.c:2005 #, c-format msgid "type input function %s has multiple matches" msgstr "型の入力関数%sが複数合致します" -#: commands/typecmds.c:1993 +#: commands/typecmds.c:2023 #, c-format msgid "type input function %s must return type %s" msgstr "型の入力関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2009 +#: commands/typecmds.c:2039 #, c-format msgid "type input function %s should not be volatile" msgstr "型の入力関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2037 +#: commands/typecmds.c:2067 #, c-format msgid "type output function %s must return type %s" msgstr "型の出力関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2044 +#: commands/typecmds.c:2074 #, c-format msgid "type output function %s should not be volatile" msgstr "型の出力関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2073 +#: commands/typecmds.c:2103 #, c-format msgid "type receive function %s has multiple matches" msgstr "型の受信関数 %s が複数合致しました" -#: commands/typecmds.c:2091 +#: commands/typecmds.c:2121 #, c-format msgid "type receive function %s must return type %s" msgstr "型の受信関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2098 +#: commands/typecmds.c:2128 #, c-format msgid "type receive function %s should not be volatile" msgstr "型の受信関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2126 +#: commands/typecmds.c:2156 #, c-format msgid "type send function %s must return type %s" msgstr "型の送信関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2133 +#: commands/typecmds.c:2163 #, c-format msgid "type send function %s should not be volatile" msgstr "型の送信関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2160 +#: commands/typecmds.c:2190 #, c-format msgid "typmod_in function %s must return type %s" msgstr "typmod_in関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2167 +#: commands/typecmds.c:2197 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "型修正子の入力関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2194 +#: commands/typecmds.c:2224 #, c-format msgid "typmod_out function %s must return type %s" msgstr "typmod_out関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2201 +#: commands/typecmds.c:2231 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "型修正子の出力関数%sはvolatileであってはなりません" -#: commands/typecmds.c:2228 +#: commands/typecmds.c:2258 #, c-format msgid "type analyze function %s must return type %s" msgstr "型のANALYZE関数%sは%s型を返す必要があります" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2287 #, c-format msgid "type subscripting function %s must return type %s" msgstr "型の添字処理関数%sは型%sを返す必要があります" -#: commands/typecmds.c:2267 +#: commands/typecmds.c:2297 #, c-format msgid "user-defined types cannot use subscripting function %s" msgstr "ユーザー定義型は添字処理関数%sを使用できません" -#: commands/typecmds.c:2313 +#: commands/typecmds.c:2343 #, c-format msgid "You must specify an operator class for the range type or define a default operator class for the subtype." msgstr "この範囲型に演算子クラスを指定するか、派生元の型でデフォルト演算子クラスを定義する必要があります。" -#: commands/typecmds.c:2344 +#: commands/typecmds.c:2374 #, c-format msgid "range canonical function %s must return range type" msgstr "範囲の正規化関数 %s は範囲型を返す必要があります" -#: commands/typecmds.c:2350 +#: commands/typecmds.c:2380 #, c-format msgid "range canonical function %s must be immutable" msgstr "範囲の正規化関数 %s は不変関数でなければなりません" -#: commands/typecmds.c:2386 +#: commands/typecmds.c:2416 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "範囲の派生元の型の差分関数 %s は %s型を返す必要があります" -#: commands/typecmds.c:2393 +#: commands/typecmds.c:2423 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "範囲の派生元の型の差分関数 %s は不変関数である必要があります" -#: commands/typecmds.c:2420 +#: commands/typecmds.c:2450 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_typeの配列型OIDが設定されていません" -#: commands/typecmds.c:2453 +#: commands/typecmds.c:2483 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_typeの複範囲型OIDの値が設定されていません" -#: commands/typecmds.c:2486 +#: commands/typecmds.c:2516 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_typeの複範囲配列型OIDの値が設定されていません" -#: commands/typecmds.c:2868 commands/typecmds.c:3093 +#: commands/typecmds.c:2898 commands/typecmds.c:3080 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "ドメイン\"%2$s\"の制約\"%1$s\"は存在しません" -#: commands/typecmds.c:2872 +#: commands/typecmds.c:2902 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "ドメイン\"%2$s\"の制約\"%1$s\"は存在しません、スキップします" -#: commands/typecmds.c:3100 +#: commands/typecmds.c:3087 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "ドメイン\"%2$s\"の制約\"%1$s\"は検査制約ではありません" -#: commands/typecmds.c:3180 +#: commands/typecmds.c:3167 #, c-format msgid "column \"%s\" of table \"%s\" contains null values" msgstr "テーブル\"%2$s\"の列\"%1$s\"にNULL値があります" -#: commands/typecmds.c:3269 +#: commands/typecmds.c:3256 #, c-format msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint" msgstr "テーブル\"%2$s\"の列\"%1$s\"に新しい制約に違反する値があります" -#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 commands/typecmds.c:4073 +#: commands/typecmds.c:3485 commands/typecmds.c:3763 commands/typecmds.c:3848 commands/typecmds.c:4064 #, c-format msgid "%s is not a domain" msgstr "%s はドメインではありません" -#: commands/typecmds.c:3532 commands/typecmds.c:3686 +#: commands/typecmds.c:3519 commands/typecmds.c:3675 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "ドメイン\"%2$s\"の制約\"%1$s\"はすでに存在します" -#: commands/typecmds.c:3583 +#: commands/typecmds.c:3570 #, c-format msgid "cannot use table references in domain check constraint" msgstr "ドメインの検査制約ではテーブル参照を使用できません" -#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 +#: commands/typecmds.c:3775 commands/typecmds.c:3860 commands/typecmds.c:4214 #, c-format msgid "%s is a table's row type" msgstr "%sはテーブルの行型です" -#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 +#: commands/typecmds.c:3785 commands/typecmds.c:3870 commands/typecmds.c:4112 #, c-format msgid "cannot alter array type %s" msgstr "配列型%sを変更できません" -#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4114 #, c-format msgid "You can alter type %s, which will alter the array type as well." msgstr "型%sを変更することができます。これは同時にその配列型も変更します。" -#: commands/typecmds.c:3892 +#: commands/typecmds.c:3883 #, c-format msgid "cannot alter multirange type %s" msgstr "複範囲型%sを変更できません" -#: commands/typecmds.c:3895 +#: commands/typecmds.c:3886 #, c-format msgid "You can alter type %s, which will alter the multirange type as well." msgstr "型%sを変更することができます。これは同時にその複範囲型も変更します。" -#: commands/typecmds.c:4202 +#: commands/typecmds.c:4193 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "型\"%s\"はスキーマ\"%s\"内にすでに存在します" -#: commands/typecmds.c:4382 +#: commands/typecmds.c:4373 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "型の格納方式をPLAINには変更できません" -#: commands/typecmds.c:4475 +#: commands/typecmds.c:4466 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "型の属性\"%s\"は変更できません" -#: commands/typecmds.c:4493 +#: commands/typecmds.c:4484 #, c-format msgid "must be superuser to alter a type" msgstr "型の変更を行うにはスーパーユーザーである必要があります" -#: commands/typecmds.c:4514 commands/typecmds.c:4523 +#: commands/typecmds.c:4505 commands/typecmds.c:4514 #, c-format msgid "%s is not a base type" msgstr "\"%s\"は基本型ではありません" -#: commands/user.c:200 +#: commands/user.c:201 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSIDはもう指定することができません" -#: commands/user.c:318 commands/user.c:324 commands/user.c:330 commands/user.c:336 commands/user.c:342 +#: commands/user.c:319 commands/user.c:325 commands/user.c:331 commands/user.c:337 commands/user.c:343 #, c-format msgid "permission denied to create role" msgstr "ロールを作成する権限がありません" -#: commands/user.c:319 +#: commands/user.c:320 #, c-format msgid "Only roles with the %s attribute may create roles." msgstr "%s属性を持つロールのみがロールを作成できます。" -#: commands/user.c:325 commands/user.c:331 commands/user.c:337 commands/user.c:343 +#: commands/user.c:326 commands/user.c:332 commands/user.c:338 commands/user.c:344 #, c-format msgid "Only roles with the %s attribute may create roles with the %s attribute." msgstr "%s属性を持つロールのみが%s属性を持つロールを作成できます。" -#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 gram.y:17355 gram.y:17401 utils/adt/acl.c:5568 utils/adt/acl.c:5574 +#: commands/user.c:355 commands/user.c:1386 commands/user.c:1393 gram.y:17493 gram.y:17539 utils/adt/acl.c:5690 utils/adt/acl.c:5696 #, c-format msgid "role name \"%s\" is reserved" msgstr "ロール名\"%s\"は予約されています" -#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 +#: commands/user.c:357 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "\"pg_\"で始まるロール名は予約されています。" -#: commands/user.c:377 commands/user.c:1410 +#: commands/user.c:378 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "ロール\"%s\"はすでに存在します" -#: commands/user.c:439 commands/user.c:924 +#: commands/user.c:440 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "空の文字列はパスワードとして使えません、パスワードを消去します" -#: commands/user.c:468 +#: commands/user.c:469 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にpg_authidのOIDが設定されていません" @@ -12422,8 +12664,8 @@ msgstr "他のロールのパスワードを変更するには、現在のユー #: commands/user.c:825 #, c-format -msgid "Only roles with the %s option on role \"%s\" may add members." -msgstr "ロール\"%2$s\"に対する%1$sオプションを持つロールのみがメンバを追加することができます。" +msgid "Only roles with the %s option on role \"%s\" may add or drop members." +msgstr "ロール\"%2$s\"に対する%1$sオプションを持つロールのみがメンバの追加および削除をすることができます。" #: commands/user.c:870 #, c-format @@ -12455,7 +12697,7 @@ msgstr "%s属性および削除対象ロールに対する%sオプションを msgid "cannot use special role specifier in DROP ROLE" msgstr "DROP ROLE で特殊ロールの識別子は使えません" -#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:838 commands/variable.c:841 commands/variable.c:947 commands/variable.c:950 utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5423 utils/adt/acl.c:5471 utils/adt/acl.c:5499 utils/adt/acl.c:5518 utils/adt/regproc.c:1571 utils/init/miscinit.c:762 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:864 commands/variable.c:867 commands/variable.c:983 commands/variable.c:986 utils/adt/acl.c:366 utils/adt/acl.c:386 utils/adt/acl.c:5545 utils/adt/acl.c:5593 utils/adt/acl.c:5621 utils/adt/acl.c:5640 utils/adt/regproc.c:1571 utils/init/miscinit.c:804 #, c-format msgid "role \"%s\" does not exist" msgstr "ロール\"%s\"は存在しません" @@ -12520,7 +12762,7 @@ msgstr "%1$s属性とロール\"%3$s\"に対する%2$sオプションを持つ msgid "MD5 password cleared because of role rename" msgstr "ロール名が変更されたためMD5パスワードがクリアされました" -#: commands/user.c:1518 gram.y:1297 +#: commands/user.c:1518 gram.y:1286 #, c-format msgid "unrecognized role option \"%s\"" msgstr "ロールオプション\"%s\"が認識できません" @@ -12560,207 +12802,212 @@ msgstr "ロール\"%s\"の権限を持つロールのみが、そのロールが msgid "Only roles with privileges of role \"%s\" may reassign objects to it." msgstr "ロール\"%s\"の権限を持つロールのみが、オブジェクトの所有者をそのロールに変更できます。" -#: commands/user.c:1733 +#: commands/user.c:1734 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "ロール\"%s\"はどのロールのメンバーにもなれません" -#: commands/user.c:1746 +#: commands/user.c:1747 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "ロール\"%s\"はロール\"%s\"のメンバです" -#: commands/user.c:1786 commands/user.c:1812 +#: commands/user.c:1787 commands/user.c:1813 #, c-format msgid "%s option cannot be granted back to your own grantor" msgstr "%sオプションはもとの付与者に付与し返すことはできません" -#: commands/user.c:1889 +#: commands/user.c:1890 #, c-format msgid "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" msgstr "ロール\"%s\"はすでにロール\"%s\"のメンバ権限をロール\"%s\"によって付与されています" -#: commands/user.c:2024 +#: commands/user.c:2036 #, c-format msgid "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" msgstr "ロール\"%s\"はロール\"%s\"のメンバ権限をロール\"%s\"によって付与されていません" -#: commands/user.c:2124 +#: commands/user.c:2137 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "ロール\"%s\"は明示的なメンバーを持てません" -#: commands/user.c:2135 commands/user.c:2158 +#: commands/user.c:2148 commands/user.c:2171 #, c-format msgid "permission denied to grant role \"%s\"" msgstr "ロール\"%s\"権限を付与する権限がありません" -#: commands/user.c:2137 +#: commands/user.c:2150 #, c-format msgid "Only roles with the %s attribute may grant roles with the %s attribute." msgstr "%s属性を持つロールのみが%s属性を持つロールの権限を付与できます。" -#: commands/user.c:2142 commands/user.c:2165 +#: commands/user.c:2155 commands/user.c:2178 #, c-format msgid "permission denied to revoke role \"%s\"" msgstr "ロール\"%s\"の権限を剥奪する権限がありません" -#: commands/user.c:2144 +#: commands/user.c:2157 #, c-format msgid "Only roles with the %s attribute may revoke roles with the %s attribute." msgstr "%s属性を持つロールのみが%s属性を持つロールの権限を剥奪できます。" -#: commands/user.c:2160 +#: commands/user.c:2173 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." msgstr "ロール\"%2$s\"に対する%1$sオプションを持つロールのみがこのロール権限を付与できます。" -#: commands/user.c:2167 +#: commands/user.c:2180 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." msgstr "ロール\"%2$s\"に対する%1$sオプションを持つロールのみがこのロール権限を剥奪できます。" -#: commands/user.c:2247 commands/user.c:2256 +#: commands/user.c:2260 commands/user.c:2269 #, c-format msgid "permission denied to grant privileges as role \"%s\"" msgstr "ロール\"%s\"として権限を付与する権限がありません" -#: commands/user.c:2249 +#: commands/user.c:2262 #, c-format msgid "Only roles with privileges of role \"%s\" may grant privileges as this role." msgstr "ロール\"%s\"の権限を持つロールのみがこのロールとして権限を付与できます。" -#: commands/user.c:2258 +#: commands/user.c:2271 #, c-format msgid "The grantor must have the %s option on role \"%s\"." msgstr "付与者はロール\"%s\"に対する%sオプションを持つ必要があります。" -#: commands/user.c:2266 +#: commands/user.c:2279 #, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" msgstr "ロール\"%s\"によって付与された権限を剥奪する権限がありません" -#: commands/user.c:2268 +#: commands/user.c:2281 #, c-format msgid "Only roles with privileges of role \"%s\" may revoke privileges granted by this role." msgstr "ロール\"%s\"の権限を持つロールのみがこのロールが付与した権限を剥奪できます。" -#: commands/user.c:2491 utils/adt/acl.c:1318 +#: commands/user.c:2504 utils/adt/acl.c:1325 #, c-format msgid "dependent privileges exist" msgstr "依存する権限が存在します" -#: commands/user.c:2492 utils/adt/acl.c:1319 +#: commands/user.c:2505 utils/adt/acl.c:1326 #, c-format msgid "Use CASCADE to revoke them too." msgstr "これらも剥奪するにはCASCADEを使用してください" -#: commands/vacuum.c:134 +#: commands/vacuum.c:146 #, c-format -msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" -msgstr "\"vacuum_buffer_usage_limit\"は0または%d kBと%d kBとの間でなければなりません" +msgid "\"%s\" must be 0 or between %d kB and %d kB." +msgstr "\"%s\"は0または%d kBと%d kBとの間でなければなりません。" -#: commands/vacuum.c:209 +#: commands/vacuum.c:222 #, c-format msgid "BUFFER_USAGE_LIMIT option must be 0 or between %d kB and %d kB" msgstr "BUFFER_USAGE_LIMITオプションは0または%d kBと%d kBの間でなければなりません" -#: commands/vacuum.c:219 +#: commands/vacuum.c:232 #, c-format msgid "unrecognized ANALYZE option \"%s\"" msgstr "ANALYZEオプション\"%s\"が認識できません" -#: commands/vacuum.c:259 +#: commands/vacuum.c:272 #, c-format msgid "parallel option requires a value between 0 and %d" msgstr "パラレルオプションには0から%dまでの値である必要があります" -#: commands/vacuum.c:271 +#: commands/vacuum.c:284 #, c-format msgid "parallel workers for vacuum must be between 0 and %d" msgstr "VACUUMの並列ワーカーの数はは0から%dまでの値でなければなりません" -#: commands/vacuum.c:292 +#: commands/vacuum.c:305 #, c-format msgid "unrecognized VACUUM option \"%s\"" msgstr "認識できないVACUUMオプション \"%s\"" -#: commands/vacuum.c:318 +#: commands/vacuum.c:331 #, c-format msgid "VACUUM FULL cannot be performed in parallel" msgstr "VACUUM FULLは並列実行できません" -#: commands/vacuum.c:329 +#: commands/vacuum.c:342 #, c-format msgid "BUFFER_USAGE_LIMIT cannot be specified for VACUUM FULL" msgstr "BUFFER_USAGE_LIMITはVACUUM FULLに対しては指定できません" -#: commands/vacuum.c:343 +#: commands/vacuum.c:356 #, c-format msgid "ANALYZE option must be specified when a column list is provided" msgstr "ANALYZE オプションは列リストが与えられているときのみ指定できます" -#: commands/vacuum.c:355 +#: commands/vacuum.c:368 #, c-format msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL" msgstr "VACUUM のオプションDISABLE_PAGE_SKIPPINGはFULLと同時には指定できません" -#: commands/vacuum.c:362 +#: commands/vacuum.c:375 #, c-format msgid "PROCESS_TOAST required with VACUUM FULL" msgstr "VACUUM FULLではPROCESS_TOASTの指定が必須です" -#: commands/vacuum.c:371 +#: commands/vacuum.c:384 #, c-format msgid "ONLY_DATABASE_STATS cannot be specified with a list of tables" msgstr "ONLY_DATABASE_STATSはテーブルのリストと一緒に指定することはできません" -#: commands/vacuum.c:380 +#: commands/vacuum.c:393 #, c-format msgid "ONLY_DATABASE_STATS cannot be specified with other VACUUM options" msgstr "ONLY_DATABASE_STATSは他のVACUUMオプションと一緒に指定することはできません" -#: commands/vacuum.c:515 +#: commands/vacuum.c:533 #, c-format msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%sはVACUUMやANALYZEからは実行できません" -#: commands/vacuum.c:730 +#: commands/vacuum.c:745 #, c-format msgid "permission denied to vacuum \"%s\", skipping it" msgstr "列%sのVACUUMを行う権限がありません、スキップします" -#: commands/vacuum.c:743 +#: commands/vacuum.c:758 #, c-format msgid "permission denied to analyze \"%s\", skipping it" msgstr "列%sのANALYZEを行う権限がありません、スキップします" -#: commands/vacuum.c:821 commands/vacuum.c:918 +#: commands/vacuum.c:836 commands/vacuum.c:937 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" msgstr "\"%s\"のVACUUM処理をスキップしています -- ロックを獲得できませんでした" -#: commands/vacuum.c:826 +#: commands/vacuum.c:841 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "\"%s\"のVACUUM処理をスキップしています -- リレーションはすでに存在しません" -#: commands/vacuum.c:842 commands/vacuum.c:923 +#: commands/vacuum.c:857 commands/vacuum.c:942 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" msgstr "\"%s\"のANALYZEをスキップしています --- ロック獲得できませんでした" -#: commands/vacuum.c:847 +#: commands/vacuum.c:862 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "\"%s\"のANALYZEをスキップします --- リレーションはすでに存在しません" -#: commands/vacuum.c:1139 +#: commands/vacuum.c:978 +#, c-format +msgid "VACUUM ONLY of partitioned table \"%s\" has no effect" +msgstr "パーティション親テーブル\"%s\"に対する VACUUM ONLY は効果がありません" + +#: commands/vacuum.c:1169 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" msgstr "タプルの削除およびフリーズのカットオフ値が古すぎます" -#: commands/vacuum.c:1140 commands/vacuum.c:1145 +#: commands/vacuum.c:1170 commands/vacuum.c:1175 #, c-format msgid "" "Close open transactions soon to avoid wraparound problems.\n" @@ -12769,37 +13016,37 @@ msgstr "" "周回問題を回避するためにすぐに実行中のトランザクションを終了してください。\n" "古い準備済みトランザクションのコミットまたはロールバック、もしくは古いレプリケーションスロットの削除が必要な場合もあります。" -#: commands/vacuum.c:1144 +#: commands/vacuum.c:1174 #, c-format msgid "cutoff for freezing multixacts is far in the past" msgstr "マルチトランザクションのフリーズのカットオフ値が古すぎます" -#: commands/vacuum.c:1890 +#: commands/vacuum.c:1936 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "データベースの一部は20億トランザクション以上の間にVACUUMを実行されていませんでした" -#: commands/vacuum.c:1891 +#: commands/vacuum.c:1937 #, c-format msgid "You might have already suffered transaction-wraparound data loss." msgstr "トランザクションの周回によるデータ損失が発生している可能性があります" -#: commands/vacuum.c:2070 +#: commands/vacuum.c:2116 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "\"%s\"をスキップしています --- テーブルではないものや、特別なシステムテーブルに対してはVACUUMを実行できません" -#: commands/vacuum.c:2502 +#: commands/vacuum.c:2617 #, c-format -msgid "scanned index \"%s\" to remove %lld row versions" -msgstr "インデックス\"%s\"をスキャンして%lldの行バージョンを削除しました" +msgid "scanned index \"%s\" to remove % row versions" +msgstr "インデックス\"%s\"をスキャンして%の行バージョンを削除しました" -#: commands/vacuum.c:2521 +#: commands/vacuum.c:2636 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "現在インデックス\"%s\"は%.0f行バージョンを%uページで含んでいます" -#: commands/vacuum.c:2525 +#: commands/vacuum.c:2640 #, c-format msgid "" "%.0f index row versions were removed.\n" @@ -12810,13 +13057,13 @@ msgstr "" "%uインデックスページを新たに削除\n" "%uページが現在削除中、うち%uページが再利用可能。" -#: commands/vacuumparallel.c:708 +#: commands/vacuumparallel.c:709 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index vacuuming (planned: %d)" msgstr[0] "インデックスのVACUUMのために%d個の並列VACUUMワーカーを起動しました (計画値: %d)" -#: commands/vacuumparallel.c:714 +#: commands/vacuumparallel.c:715 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index cleanup (planned: %d)" @@ -12824,8 +13071,8 @@ msgstr[0] "インデックスのクリーンアップのために%d個の並列V #: commands/variable.c:185 #, c-format -msgid "Conflicting \"datestyle\" specifications." -msgstr "\"datestyle\"指定が競合しています。" +msgid "Conflicting \"DateStyle\" specifications." +msgstr "\"DateStyle\"指定が競合しています。" #: commands/variable.c:307 #, c-format @@ -12837,12 +13084,12 @@ msgstr "タイムゾーンのインターバル指定では月は指定できま msgid "Cannot specify days in time zone interval." msgstr "タイムゾーンのインターバル指定では日は指定できません。" -#: commands/variable.c:351 commands/variable.c:433 +#: commands/variable.c:351 commands/variable.c:435 #, c-format msgid "time zone \"%s\" appears to use leap seconds" msgstr "タイムゾーン\"%s\"はうるう秒を使用するようです" -#: commands/variable.c:353 commands/variable.c:435 +#: commands/variable.c:353 commands/variable.c:437 #, c-format msgid "PostgreSQL does not support leap seconds." msgstr "PostgreSQLはうるう秒をサポートしていません。" @@ -12852,107 +13099,97 @@ msgstr "PostgreSQLはうるう秒をサポートしていません。" msgid "UTC timezone offset is out of range." msgstr "UTCのタイムゾーンオフセットが範囲外です。" -#: commands/variable.c:552 +#: commands/variable.c:554 #, c-format msgid "cannot set transaction read-write mode inside a read-only transaction" msgstr "読み取りのみのトランザクションでトランザクションモードを読み書きモードに設定することはできません" -#: commands/variable.c:559 +#: commands/variable.c:561 #, c-format msgid "transaction read-write mode must be set before any query" msgstr "トランザクションの読み書きモードの設定は、問い合わせより前に行う必要があります" -#: commands/variable.c:566 +#: commands/variable.c:568 #, c-format msgid "cannot set transaction read-write mode during recovery" msgstr "リカバリ中にはトランザクションを読み書きモードに設定できません" -#: commands/variable.c:592 +#: commands/variable.c:596 #, c-format msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query" msgstr "SET TRANSACTION ISOLATION LEVEL は問い合わせより前に実行する必要があります" -#: commands/variable.c:599 +#: commands/variable.c:603 #, c-format msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "SET TRANSACTION ISOLATION LEVELをサブトランザクションで呼び出してはなりません" -#: commands/variable.c:606 storage/lmgr/predicate.c:1680 +#: commands/variable.c:610 storage/lmgr/predicate.c:1695 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "ホットスタンバイ中はシリアライズモードを使用できません" -#: commands/variable.c:607 +#: commands/variable.c:611 #, c-format msgid "You can use REPEATABLE READ instead." msgstr "代わりに REPEATABLE READ を使ってください" -#: commands/variable.c:625 +#: commands/variable.c:633 #, c-format msgid "SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction" msgstr "SET TRANSACTION [NOT] DEFERRABLE をサブトランザクション内部では呼び出せません" -#: commands/variable.c:631 +#: commands/variable.c:639 #, c-format msgid "SET TRANSACTION [NOT] DEFERRABLE must be called before any query" msgstr "SET TRANSACTION [NOT] DEFERRABLE は問い合わせより前に実行する必要があります" -#: commands/variable.c:713 +#: commands/variable.c:715 +#, c-format +msgid "Cannot change \"client_encoding\" during a parallel operation." +msgstr "並列処理中は\"client_encoding\"を変更できません。" + +#: commands/variable.c:743 #, c-format msgid "Conversion between %s and %s is not supported." msgstr "%sと%s 間の変換はサポートされていません。" -#: commands/variable.c:720 +#: commands/variable.c:750 #, c-format msgid "Cannot change \"client_encoding\" now." msgstr "現在\"client_encoding\"を変更できません。" -#: commands/variable.c:781 -#, c-format -msgid "cannot change \"client_encoding\" during a parallel operation" -msgstr "並列処理中は\"client_encoding\"を変更できません" - -#: commands/variable.c:863 +#: commands/variable.c:889 #, c-format msgid "permission will be denied to set session authorization \"%s\"" msgstr "セッション認証を\"%s\"に設定する権限は拒否されます" -#: commands/variable.c:868 +#: commands/variable.c:894 #, c-format msgid "permission denied to set session authorization \"%s\"" msgstr "セッション認証を\"%s\"に設定する権限は拒否されました" -#: commands/variable.c:972 +#: commands/variable.c:1003 #, c-format msgid "permission will be denied to set role \"%s\"" msgstr "ロール\"%s\"を設定する権限がありません" -#: commands/variable.c:977 +#: commands/variable.c:1008 #, c-format msgid "permission denied to set role \"%s\"" msgstr "ロール\"%s\"を設定する権限がありません" -#: commands/variable.c:1177 +#: commands/variable.c:1228 #, c-format msgid "Bonjour is not supported by this build" msgstr "このビルドでは bonjour はサポートされていません" -#: commands/variable.c:1205 -#, c-format -msgid "\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." -msgstr "posix_fadvise() をもたないプラットフォームでは\"effective_io_concurrency\"は0に設定する必要があります。" - -#: commands/variable.c:1218 -#, c-format -msgid "\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." -msgstr "posix_fadvise() をもたないプラットフォームでは\"maintenance_io_concurrency\"は0に設定する必要があります。" - -#: commands/variable.c:1231 +#: commands/variable.c:1256 #, c-format msgid "SSL is not supported by this build" msgstr "このインストレーションではSSLはサポートされていません" -#: commands/view.c:79 +#: commands/view.c:78 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "ビューの列\"%s\"で使用する照合順序を特定できませんでした" @@ -13037,400 +13274,411 @@ msgstr "カーソル\"%s\"は行上に位置していません" msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "カーソル\"%s\"はテーブル\"%s\"を単純な更新可能スキャンではありません" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2543 +#: executor/execCurrent.c:280 executor/execExprInterp.c:3093 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "パラメータの型%d(%s)が実行計画(%s)を準備する時点と一致しません" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2555 +#: executor/execCurrent.c:292 executor/execExprInterp.c:3105 #, c-format msgid "no value found for parameter %d" msgstr "パラメータ%dの値がありません" -#: executor/execExpr.c:641 executor/execExpr.c:648 executor/execExpr.c:654 executor/execExprInterp.c:4741 executor/execExprInterp.c:4758 executor/execExprInterp.c:4857 executor/nodeModifyTable.c:194 executor/nodeModifyTable.c:205 executor/nodeModifyTable.c:222 executor/nodeModifyTable.c:230 +#: executor/execExpr.c:667 executor/execExpr.c:674 executor/execExpr.c:680 executor/execExprInterp.c:5440 executor/execExprInterp.c:5457 executor/execExprInterp.c:5556 executor/nodeModifyTable.c:210 executor/nodeModifyTable.c:221 executor/nodeModifyTable.c:238 executor/nodeModifyTable.c:246 #, c-format msgid "table row type and query-specified row type do not match" msgstr "テーブルの行型と問い合わせで指定した行型が一致しません" -#: executor/execExpr.c:642 executor/nodeModifyTable.c:195 +#: executor/execExpr.c:668 executor/nodeModifyTable.c:211 #, c-format msgid "Query has too many columns." msgstr "問い合わせの列が多すぎます" -#: executor/execExpr.c:649 executor/nodeModifyTable.c:223 +#: executor/execExpr.c:675 executor/nodeModifyTable.c:239 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "問い合わせで %d 番目に削除される列の値を指定しています。" -#: executor/execExpr.c:655 executor/execExprInterp.c:4759 executor/nodeModifyTable.c:206 +#: executor/execExpr.c:681 executor/execExprInterp.c:5458 executor/nodeModifyTable.c:222 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "テーブルでは %2$d 番目の型は %1$s ですが、問い合わせでは %3$s を想定しています。" -#: executor/execExpr.c:1103 parser/parse_agg.c:840 +#: executor/execExpr.c:1157 parser/parse_agg.c:843 #, c-format msgid "window function calls cannot be nested" msgstr "ウィンドウ関数の呼び出しを入れ子にすることはできません" -#: executor/execExpr.c:1640 +#: executor/execExpr.c:1689 #, c-format msgid "target type is not an array" msgstr "対象型は配列ではありません" -#: executor/execExpr.c:1980 +#: executor/execExpr.c:2033 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "ROW()列の型が%2$sではなく%1$sです" -#: executor/execExpr.c:2642 executor/execSRF.c:718 parser/parse_func.c:138 parser/parse_func.c:655 parser/parse_func.c:1033 +#: executor/execExpr.c:2729 executor/execSRF.c:718 parser/parse_func.c:138 parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" msgstr[0] "関数に%dを超える引数を渡せません" -#: executor/execExpr.c:2669 executor/execSRF.c:738 executor/functions.c:1067 utils/adt/jsonfuncs.c:4032 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2756 executor/execSRF.c:738 executor/functions.c:1474 utils/adt/jsonfuncs.c:4056 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "このコンテキストで集合値の関数は集合を受け付けられません" -#: executor/execExpr.c:3075 parser/parse_node.c:272 parser/parse_node.c:322 +#: executor/execExpr.c:3262 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "添字をサポートしないため、型%sには添字をつけられません" -#: executor/execExpr.c:3203 executor/execExpr.c:3225 +#: executor/execExpr.c:3390 executor/execExpr.c:3412 #, c-format msgid "type %s does not support subscripted assignment" msgstr "型%sは添字を使った代入をサポートしません" -#: executor/execExprInterp.c:2007 +#: executor/execExprInterp.c:2415 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "%2$s型の属性%1$dが削除されています" -#: executor/execExprInterp.c:2013 +#: executor/execExprInterp.c:2421 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "型%2$sの属性%1$dの型が間違っています" -#: executor/execExprInterp.c:2015 executor/execExprInterp.c:3214 executor/execExprInterp.c:3260 +#: executor/execExprInterp.c:2423 executor/execExprInterp.c:3782 executor/execExprInterp.c:3828 #, c-format msgid "Table has type %s, but query expects %s." msgstr "テーブルの型は%sですが、問い合わせでは%sを想定しています。" -#: executor/execExprInterp.c:2095 utils/adt/expandedrecord.c:99 utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 utils/fmgr/funcapi.c:569 +#: executor/execExprInterp.c:2503 utils/adt/expandedrecord.c:99 utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1841 utils/cache/typcache.c:2000 utils/cache/typcache.c:2147 utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "型%sは複合型ではありません" -#: executor/execExprInterp.c:2698 +#: executor/execExprInterp.c:3266 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "このタイプのテーブルではWHERE CURRENT OFをサポートしません" -#: executor/execExprInterp.c:2911 +#: executor/execExprInterp.c:3479 #, c-format msgid "cannot merge incompatible arrays" msgstr "互換性がない配列をマージできません" -#: executor/execExprInterp.c:2912 +#: executor/execExprInterp.c:3480 #, c-format msgid "Array with element type %s cannot be included in ARRAY construct with element type %s." msgstr "要素型%sの配列を要素型%sのARRAY式に含められません" -#: executor/execExprInterp.c:2933 utils/adt/arrayfuncs.c:1305 utils/adt/arrayfuncs.c:3496 utils/adt/arrayfuncs.c:5586 utils/adt/arrayfuncs.c:6103 utils/adt/arraysubs.c:150 utils/adt/arraysubs.c:488 +#: executor/execExprInterp.c:3501 utils/adt/arrayfuncs.c:1305 utils/adt/arrayfuncs.c:3515 utils/adt/arrayfuncs.c:5605 utils/adt/arrayfuncs.c:6124 utils/adt/arraysubs.c:151 utils/adt/arraysubs.c:489 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "配列の次数(%d)が上限(%d)を超えています" -#: executor/execExprInterp.c:2953 executor/execExprInterp.c:2988 +#: executor/execExprInterp.c:3521 executor/execExprInterp.c:3556 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "多次元配列の配列式の次数があっていなければなりません" -#: executor/execExprInterp.c:2965 utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 utils/adt/arrayfuncs.c:2942 utils/adt/arrayfuncs.c:2957 utils/adt/arrayfuncs.c:3298 utils/adt/arrayfuncs.c:3526 utils/adt/arrayfuncs.c:5358 utils/adt/arrayfuncs.c:6195 -#: utils/adt/arrayfuncs.c:6539 utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 utils/adt/arrayutils.c:99 +#: executor/execExprInterp.c:3533 utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 utils/adt/arrayfuncs.c:3545 utils/adt/arrayfuncs.c:5377 +#: utils/adt/arrayfuncs.c:6216 utils/adt/arrayfuncs.c:6560 utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "配列の次数が上限(%d)を超えています" -#: executor/execExprInterp.c:3213 executor/execExprInterp.c:3259 +#: executor/execExprInterp.c:3781 executor/execExprInterp.c:3827 #, c-format msgid "attribute %d has wrong type" msgstr "属性%dの型が間違っています" -#: executor/execExprInterp.c:3845 utils/adt/domains.c:158 +#: executor/execExprInterp.c:4413 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "ドメイン%sはnull値を許しません" -#: executor/execExprInterp.c:3860 utils/adt/domains.c:196 +#: executor/execExprInterp.c:4428 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "ドメイン%sの値が検査制約\"%s\"に違反しています" -#: executor/execExprInterp.c:4433 +#: executor/execExprInterp.c:5003 #, c-format msgid "no SQL/JSON item found for specified path of column \"%s\"" msgstr "列\"%s\"の指定されたパスに対応するSQL/JSON項目が見つかりません" -#: executor/execExprInterp.c:4438 +#: executor/execExprInterp.c:5008 #, c-format msgid "no SQL/JSON item found for specified path" msgstr "指定されたパスに対応するSQL/JSON項目が見つかりません" -#: executor/execExprInterp.c:4742 +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:5208 executor/execExprInterp.c:5216 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "%s式(%s)をRETURNING型に強制変換できませんでした" + +#: executor/execExprInterp.c:5441 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." msgstr[0] "テーブル行には%d属性ありますが、問い合わせでは%dを想定しています。" -#: executor/execExprInterp.c:4858 executor/execSRF.c:977 +#: executor/execExprInterp.c:5557 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "序数位置%dの削除された属性における物理格納形式が一致しません。" -#: executor/execIndexing.c:593 +#: executor/execIndexing.c:608 #, c-format msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters" msgstr "ON CONFLICT は遅延可なユニーク制約/排除制約の調停主体としての指定をサポートしません" -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:911 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "排除制約\"%s\"を作成できませんでした" -#: executor/execIndexing.c:873 +#: executor/execIndexing.c:914 #, c-format msgid "Key %s conflicts with key %s." msgstr "キー %s がキー %s と競合しています" -#: executor/execIndexing.c:875 +#: executor/execIndexing.c:916 #, c-format msgid "Key conflicts exist." msgstr "キーの競合が存在します" -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:922 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "重複キーの値が排除制約\"%s\"に違反しています" -#: executor/execIndexing.c:884 +#: executor/execIndexing.c:925 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "キー %s が既存のキー %s と競合しています" -#: executor/execIndexing.c:886 +#: executor/execIndexing.c:927 #, c-format msgid "Key conflicts with existing key." msgstr "キーが既存のキーと衝突しています" -#: executor/execMain.c:1041 +#: executor/execIndexing.c:1172 +#, c-format +msgid "empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"" +msgstr "リレーション\"%2$s\"の列\"%1$s\"に空のWITHOUT OVERLAPS値が見つかりました" + +#: executor/execMain.c:1171 #, c-format msgid "cannot change sequence \"%s\"" msgstr "シーケンス\"%s\"を変更できません" -#: executor/execMain.c:1047 +#: executor/execMain.c:1177 #, c-format msgid "cannot change TOAST relation \"%s\"" msgstr "TOASTリレーション\"%s\"を変更できません" -#: executor/execMain.c:1066 +#: executor/execMain.c:1196 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "実体化ビュー\"%s\"を変更できません" -#: executor/execMain.c:1078 +#: executor/execMain.c:1208 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "外部テーブル\"%s\"への挿入ができません" -#: executor/execMain.c:1084 +#: executor/execMain.c:1214 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "外部テーブル\"%s\"は挿入を許しません" -#: executor/execMain.c:1091 +#: executor/execMain.c:1221 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "外部テーブル \"%s\"の更新ができません" -#: executor/execMain.c:1097 +#: executor/execMain.c:1227 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "外部テーブル\"%s\"は更新を許しません" -#: executor/execMain.c:1104 +#: executor/execMain.c:1234 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "外部テーブル\"%s\"からの削除ができません" -#: executor/execMain.c:1110 +#: executor/execMain.c:1240 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "外部テーブル\"%s\"は削除を許しません" -#: executor/execMain.c:1121 +#: executor/execMain.c:1251 #, c-format msgid "cannot change relation \"%s\"" msgstr "リレーション\"%s\"を変更できません" -#: executor/execMain.c:1148 +#: executor/execMain.c:1278 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "シーケンス\"%s\"では行のロックはできません" -#: executor/execMain.c:1155 +#: executor/execMain.c:1285 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "TOAST リレーション\"%s\"では行のロックはできません" -#: executor/execMain.c:1162 +#: executor/execMain.c:1292 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "ビュー\"%s\"では行のロックはできません" -#: executor/execMain.c:1170 +#: executor/execMain.c:1300 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "実体化ビュー\"%s\"では行のロックはできません" -#: executor/execMain.c:1179 executor/execMain.c:2684 executor/nodeLockRows.c:135 +#: executor/execMain.c:1309 executor/execMain.c:2941 executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "外部テーブル\"%s\"では行のロックはできません" -#: executor/execMain.c:1185 +#: executor/execMain.c:1315 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "リレーション\"%s\"では行のロックはできません" -#: executor/execMain.c:1898 +#: executor/execMain.c:2038 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "リレーション\"%s\"の新しい行はパーティション制約に違反しています" -#: executor/execMain.c:1900 executor/execMain.c:1984 executor/execMain.c:2035 executor/execMain.c:2145 +#: executor/execMain.c:2040 executor/execMain.c:2152 executor/execMain.c:2290 executor/execMain.c:2398 #, c-format msgid "Failing row contains %s." msgstr "失敗した行は%sを含みます" -#: executor/execMain.c:1981 -#, c-format -msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" -msgstr "リレーション\"%2$s\"の列\"%1$s\"のNULL値が非NULL制約に違反しています" - -#: executor/execMain.c:2033 +#: executor/execMain.c:2150 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "リレーション\"%s\"の新しい行は検査制約\"%s\"に違反しています" -#: executor/execMain.c:2143 +#: executor/execMain.c:2287 +#, c-format +msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" +msgstr "リレーション\"%2$s\"の列\"%1$s\"のNULL値が非NULL制約に違反しています" + +#: executor/execMain.c:2396 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "新しい行はビュー\"%s\"のチェックオプションに違反しています" -#: executor/execMain.c:2153 +#: executor/execMain.c:2406 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "新しい行はテーブル\"%2$s\"行レベルセキュリティポリシ\"%1$s\"に違反しています" -#: executor/execMain.c:2158 +#: executor/execMain.c:2411 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "新しい行はテーブル\"%s\"の行レベルセキュリティポリシに違反しています" -#: executor/execMain.c:2166 +#: executor/execMain.c:2419 #, c-format msgid "target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "ターゲットの行はテーブル\"%s\"の行レベルセキュリティポリシ\"%s\"(USING式)に違反しています" -#: executor/execMain.c:2171 +#: executor/execMain.c:2424 #, c-format msgid "target row violates row-level security policy (USING expression) for table \"%s\"" msgstr "ターゲットの行はテーブル\"%s\"の行レベルセキュリティポリシ(USING式)に違反しています" -#: executor/execMain.c:2178 +#: executor/execMain.c:2431 #, c-format msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "新しい行はテーブル\"%1$s\"の行レベルセキュリティポリシ\"%2$s\"(USING式)に違反しています" -#: executor/execMain.c:2183 +#: executor/execMain.c:2436 #, c-format msgid "new row violates row-level security policy (USING expression) for table \"%s\"" msgstr "新しい行はテーブル\"%s\"の行レベルセキュリティポリシ(USING式)に違反しています" -#: executor/execPartition.c:327 +#: executor/execPartition.c:331 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "行に対応するパーティションがリレーション\"%s\"に見つかりません" -#: executor/execPartition.c:330 +#: executor/execPartition.c:334 #, c-format msgid "Partition key of the failing row contains %s." msgstr "失敗した行のパーティションキーは%sを含みます。" -#: executor/execReplication.c:272 executor/execReplication.c:456 +#: executor/execReplication.c:147 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update, retrying" msgstr "ロック対象のタプルは同時に行われた更新によって他の子テーブルに移動されています、再試行しています" -#: executor/execReplication.c:276 executor/execReplication.c:460 +#: executor/execReplication.c:151 #, c-format msgid "concurrent update, retrying" msgstr "同時更新がありました、リトライします" -#: executor/execReplication.c:282 executor/execReplication.c:466 +#: executor/execReplication.c:158 #, c-format msgid "concurrent delete, retrying" msgstr "並行する削除がありました、リトライします" -#: executor/execReplication.c:352 parser/parse_cte.c:302 parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3845 utils/adt/arrayfuncs.c:4400 utils/adt/arrayfuncs.c:6419 utils/adt/rowtypes.c:1220 -#, c-format -msgid "could not identify an equality operator for type %s" -msgstr "型%sの等価演算子を特定できませんでした" - -#: executor/execReplication.c:683 executor/execReplication.c:689 +#: executor/execReplication.c:809 executor/execReplication.c:815 executor/execReplication.c:821 #, c-format msgid "cannot update table \"%s\"" msgstr "テーブル\"%s\"の更新ができません" -#: executor/execReplication.c:685 executor/execReplication.c:697 +#: executor/execReplication.c:811 executor/execReplication.c:829 #, c-format msgid "Column used in the publication WHERE expression is not part of the replica identity." msgstr "このパブリケーションのWHERE式で使用されている列は識別列の一部ではありません。" -#: executor/execReplication.c:691 executor/execReplication.c:703 +#: executor/execReplication.c:817 executor/execReplication.c:835 #, c-format msgid "Column list used by the publication does not cover the replica identity." msgstr "このパブリケーションで使用されてる列リストは識別列を包含していません。" -#: executor/execReplication.c:695 executor/execReplication.c:701 +#: executor/execReplication.c:823 executor/execReplication.c:841 +#, c-format +msgid "Replica identity must not contain unpublished generated columns." +msgstr "複製識別がパブリッシュされていない生成列を含んでいてはなりません。" + +#: executor/execReplication.c:827 executor/execReplication.c:833 executor/execReplication.c:839 #, c-format msgid "cannot delete from table \"%s\"" msgstr "テーブル\"%s\"からの削除ができません" -#: executor/execReplication.c:721 +#: executor/execReplication.c:859 #, c-format msgid "cannot update table \"%s\" because it does not have a replica identity and publishes updates" msgstr "テーブル\"%s\"は複製識別を持たずかつ更新をパブリッシュしているため、更新できません" -#: executor/execReplication.c:723 +#: executor/execReplication.c:861 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "テーブルの更新を可能にするには ALTER TABLE で REPLICA IDENTITY を設定してください。" -#: executor/execReplication.c:727 +#: executor/execReplication.c:865 #, c-format msgid "cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes" msgstr "テーブル\"%s\"は複製識別がなくかつ削除をパブリッシュしているため、このテーブルでは行の削除ができません" -#: executor/execReplication.c:729 +#: executor/execReplication.c:867 #, c-format msgid "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "このテーブルでの行削除を可能にするには ALTER TABLE で REPLICA IDENTITY を設定してください。" -#: executor/execReplication.c:745 +#: executor/execReplication.c:883 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "リレーション\"%s.%s\"は論理レプリケーション先としては使用できません" @@ -13476,114 +13724,114 @@ msgstr[0] "%d属性を持つ行が返されました。問い合わせでは%d msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "序数位置%2$dの型%1$sが返されました。問い合わせでは%3$sを想定しています。" -#: executor/execTuples.c:147 executor/execTuples.c:368 executor/execTuples.c:563 executor/execTuples.c:772 +#: executor/execTuples.c:147 executor/execTuples.c:369 executor/execTuples.c:564 executor/execTuples.c:774 #, c-format msgid "cannot retrieve a system column in this context" msgstr "この文脈ではシステム列は取り出せません" -#: executor/execTuples.c:163 executor/execTuples.c:580 +#: executor/execTuples.c:163 executor/execTuples.c:581 #, c-format msgid "don't have transaction information for this type of tuple" msgstr "このタイプのタプルのトランザクション情報は持たないでください" -#: executor/execTuples.c:390 executor/execTuples.c:794 +#: executor/execTuples.c:391 executor/execTuples.c:796 #, c-format msgid "don't have a storage tuple in this context" msgstr "この文脈ではストレージタプルを保持しないでください" -#: executor/execUtils.c:713 +#: executor/execUtils.c:759 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "実体化ビュー\"%s\"にはデータが格納されていません" -#: executor/execUtils.c:715 -#, c-format -msgid "Use the REFRESH MATERIALIZED VIEW command." -msgstr "REFRESH MATERIALIZED VIEWコマンドを使用してください。" - -#: executor/functions.c:217 +#: executor/functions.c:293 #, c-format msgid "could not determine actual type of argument declared %s" msgstr "%sと宣言された引数の型を特定できませんでした" -#: executor/functions.c:512 +#: executor/functions.c:726 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "SQL関数の中ではCOPY文によるクライアントとの間の入出力はできません" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:732 #, c-format msgid "%s is not allowed in an SQL function" msgstr "SQL関数では%sは使用不可です" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1741 executor/spi.c:2649 +#: executor/functions.c:740 executor/spi.c:1746 executor/spi.c:2660 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "volatile関数以外では%sは許可されません" -#: executor/functions.c:1451 +#: executor/functions.c:1135 executor/functions.c:2129 executor/functions.c:2167 executor/functions.c:2181 executor/functions.c:2271 executor/functions.c:2304 executor/functions.c:2318 #, c-format -msgid "SQL function \"%s\" statement %d" -msgstr "SQL関数\"%s\"の行番号 %d" +msgid "return type mismatch in function declared to return %s" +msgstr "%sを返すと宣言された関数において戻り値型が一致しません" -#: executor/functions.c:1477 +#: executor/functions.c:1137 executor/functions.c:2131 #, c-format -msgid "SQL function \"%s\" during startup" -msgstr "SQL関数\"%s\"の起動中" +msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." +msgstr "関数中の最後の文はSELECTまたはINSERT/UPDATE/DELETE/MERGE RETURNING のいずれかである必要があります。" -#: executor/functions.c:1562 +#: executor/functions.c:1220 utils/cache/plancache.c:869 #, c-format -msgid "calling procedures with output arguments is not supported in SQL functions" -msgstr "出力引数を持つプロシージャの呼び出しはSQL関数ではサポートされていません" +msgid "cached plan must not change result type" +msgstr "キャッシュした実行計画は結果型を変更してはなりません" -#: executor/functions.c:1697 executor/functions.c:1735 executor/functions.c:1749 executor/functions.c:1844 executor/functions.c:1877 executor/functions.c:1891 +#: executor/functions.c:1822 executor/functions.c:1853 #, c-format -msgid "return type mismatch in function declared to return %s" -msgstr "%sを返すと宣言された関数において戻り値型が一致しません" +msgid "SQL function \"%s\" during startup" +msgstr "SQL関数\"%s\"の起動中" -#: executor/functions.c:1699 +#: executor/functions.c:1850 #, c-format -msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." -msgstr "関数中の最後の文はSELECTまたはINSERT/UPDATE/DELETE/MERGE RETURNING のいずれかである必要があります。" +msgid "SQL function \"%s\" statement %d" +msgstr "SQL関数\"%s\"の行番号 %d" + +#: executor/functions.c:1980 +#, c-format +msgid "calling procedures with output arguments is not supported in SQL functions" +msgstr "出力引数を持つプロシージャの呼び出しはSQL関数ではサポートされていません" -#: executor/functions.c:1737 +#: executor/functions.c:2169 #, c-format msgid "Final statement must return exactly one column." msgstr "最後のステートメントはちょうど1列を返さなければなりません。" -#: executor/functions.c:1751 +#: executor/functions.c:2183 #, c-format msgid "Actual return type is %s." msgstr "実際の戻り値型は%sです。" -#: executor/functions.c:1846 +#: executor/functions.c:2273 #, c-format msgid "Final statement returns too many columns." msgstr "最後のステートメントが返す列が多すぎます。" -#: executor/functions.c:1879 +#: executor/functions.c:2306 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "最後のステートメントが列%3$dで%2$sではなく%1$sを返しました。" -#: executor/functions.c:1893 +#: executor/functions.c:2320 #, c-format msgid "Final statement returns too few columns." msgstr "最後のステートメントが返す列が少なすぎます。" -#: executor/functions.c:1921 +#: executor/functions.c:2348 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "戻り値型%sはSQL関数でサポートされていません" -#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2976 +#: executor/nodeAgg.c:4039 executor/nodeWindowAgg.c:3041 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "集約%uは入力データ型と遷移用の型間で互換性が必要です" -#: executor/nodeAgg.c:3966 parser/parse_agg.c:682 parser/parse_agg.c:710 +#: executor/nodeAgg.c:4062 parser/parse_agg.c:685 parser/parse_agg.c:713 #, c-format msgid "aggregate function calls cannot be nested" msgstr "集約関数の呼び出しを入れ子にすることはできません" @@ -13593,12 +13841,12 @@ msgstr "集約関数の呼び出しを入れ子にすることはできません msgid "custom scan \"%s\" does not support MarkPos" msgstr "カスタムスキャン\"%s\"はMarkPosをサポートしていません" -#: executor/nodeHashjoin.c:1130 executor/nodeHashjoin.c:1160 +#: executor/nodeHashjoin.c:1230 executor/nodeHashjoin.c:1260 #, c-format msgid "could not rewind hash-join temporary file" msgstr "ハッシュ結合用一時ファイルを巻き戻せませんでした" -#: executor/nodeIndexonlyscan.c:239 +#: executor/nodeIndexonlyscan.c:240 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "概算距離関数はインデックスオンリースキャンではサポートされていません" @@ -13613,73 +13861,73 @@ msgstr "OFFSET は負数であってはなりません" msgid "LIMIT must not be negative" msgstr "LIMIT は負数であってはなりません" -#: executor/nodeMergejoin.c:1578 +#: executor/nodeMergejoin.c:1574 #, c-format msgid "RIGHT JOIN is only supported with merge-joinable join conditions" msgstr "RIGHT JOINはマージ結合可能な結合条件でのみサポートされています" -#: executor/nodeMergejoin.c:1596 +#: executor/nodeMergejoin.c:1592 #, c-format msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "FULL JOINはマージ結合可能な結合条件でのみサポートされています" -#: executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:247 #, c-format msgid "Query has too few columns." msgstr "問い合わせの列が少なすぎます。" -#: executor/nodeModifyTable.c:1531 executor/nodeModifyTable.c:1605 +#: executor/nodeModifyTable.c:1664 executor/nodeModifyTable.c:1738 #, c-format msgid "tuple to be deleted was already modified by an operation triggered by the current command" msgstr "削除対象のタプルはすでに現在のコマンドによって引き起こされた操作によって変更されています" -#: executor/nodeModifyTable.c:1760 +#: executor/nodeModifyTable.c:1937 #, c-format msgid "invalid ON UPDATE specification" msgstr "不正な ON UPDATE 指定です" -#: executor/nodeModifyTable.c:1761 +#: executor/nodeModifyTable.c:1938 #, c-format msgid "The result tuple would appear in a different partition than the original tuple." msgstr "結果タプルをもとのパーティションではなく異なるパーティションに追加しようとしました。" -#: executor/nodeModifyTable.c:2217 +#: executor/nodeModifyTable.c:2394 #, c-format msgid "cannot move tuple across partitions when a non-root ancestor of the source partition is directly referenced in a foreign key" msgstr "ソースパーティションのルート以外の上位パーティションが外部キーで直接参照されている場合はパーティション間でタプルを移動させることができません" -#: executor/nodeModifyTable.c:2218 +#: executor/nodeModifyTable.c:2395 #, c-format msgid "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." msgstr "外部キーがパーティションルートテーブル\"%2$s\"ではなくパーティション親テーブル\"%1$s\"を指しています。" -#: executor/nodeModifyTable.c:2221 +#: executor/nodeModifyTable.c:2398 #, c-format msgid "Consider defining the foreign key on table \"%s\"." msgstr "テーブル\"%s\"上に外部キー制約を定義することを検討してください。" #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2567 executor/nodeModifyTable.c:3081 executor/nodeModifyTable.c:3242 +#: executor/nodeModifyTable.c:2765 executor/nodeModifyTable.c:3314 executor/nodeModifyTable.c:3484 #, c-format msgid "%s command cannot affect row a second time" msgstr "%sコマンドは単一の行に2度は適用できません" -#: executor/nodeModifyTable.c:2569 +#: executor/nodeModifyTable.c:2767 #, c-format msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values." msgstr "同じコマンドでの挿入候補の行が同じ制約値を持つことがないようにしてください" -#: executor/nodeModifyTable.c:3074 executor/nodeModifyTable.c:3235 +#: executor/nodeModifyTable.c:3307 executor/nodeModifyTable.c:3477 #, c-format msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" msgstr "更新または削除対象のタプルは、現在のコマンドによって発火した操作トリガーによってすでに更新されています" -#: executor/nodeModifyTable.c:3083 executor/nodeModifyTable.c:3244 +#: executor/nodeModifyTable.c:3316 executor/nodeModifyTable.c:3486 #, c-format msgid "Ensure that not more than one source row matches any one target row." msgstr "ソース行が2行以上ターゲット行に合致しないようにしてください。" -#: executor/nodeModifyTable.c:3152 +#: executor/nodeModifyTable.c:3385 #, c-format msgid "tuple to be merged was already moved to another partition due to concurrent update" msgstr "マージ対象のタプルは同時に行われた更新によってすでに他の子テーブルに移動されています" @@ -13694,7 +13942,7 @@ msgstr "TABLESAMPLEパラメータにnullは指定できません" msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "TABLESAMPLE REPEATABLE パラメータにnullは指定できません" -#: executor/nodeSubplan.c:325 executor/nodeSubplan.c:351 executor/nodeSubplan.c:405 executor/nodeSubplan.c:1174 +#: executor/nodeSubplan.c:317 executor/nodeSubplan.c:343 executor/nodeSubplan.c:397 executor/nodeSubplan.c:1182 #, c-format msgid "more than one row returned by a subquery used as an expression" msgstr "式として使用された副問い合わせが2行以上の行を返しました" @@ -13729,104 +13977,104 @@ msgstr "列\"%s\"でnullは許可されません" msgid "moving-aggregate transition function must not return null" msgstr "移動集約の推移関数はnullを返却してはなりません" -#: executor/nodeWindowAgg.c:2083 +#: executor/nodeWindowAgg.c:2106 #, c-format msgid "frame starting offset must not be null" msgstr "フレームの開始オフセットは NULL であってはなりません" -#: executor/nodeWindowAgg.c:2096 +#: executor/nodeWindowAgg.c:2120 #, c-format msgid "frame starting offset must not be negative" msgstr "フレームの開始オフセットは負数であってはなりません" -#: executor/nodeWindowAgg.c:2108 +#: executor/nodeWindowAgg.c:2133 #, c-format msgid "frame ending offset must not be null" msgstr "フレームの終了オフセットは NULL であってはなりません" -#: executor/nodeWindowAgg.c:2121 +#: executor/nodeWindowAgg.c:2147 #, c-format msgid "frame ending offset must not be negative" msgstr "フレームの終了オフセットは負数であってはなりません" -#: executor/nodeWindowAgg.c:2892 +#: executor/nodeWindowAgg.c:2957 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "集約関数 %s はウィンドウ関数としての使用をサポートしていません" -#: executor/spi.c:241 executor/spi.c:341 +#: executor/spi.c:242 executor/spi.c:342 #, c-format msgid "invalid transaction termination" msgstr "不正なトランザクション終了" -#: executor/spi.c:256 +#: executor/spi.c:257 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "サブトランザクションの実行中はコミットできません" -#: executor/spi.c:347 +#: executor/spi.c:348 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "サブトランザクションの実行中はロールバックできません" -#: executor/spi.c:471 +#: executor/spi.c:472 #, c-format msgid "transaction left non-empty SPI stack" msgstr "トランザクションは空でないSPIスタックを残しました" -#: executor/spi.c:472 executor/spi.c:532 +#: executor/spi.c:473 executor/spi.c:533 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "\"SPI_finish\"呼出の抜けを確認ください" -#: executor/spi.c:531 +#: executor/spi.c:532 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "サブトランザクションが空でないSPIスタックを残しました" -#: executor/spi.c:1599 +#: executor/spi.c:1603 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "カーソルにマルチクエリの実行計画を開くことができません" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1609 +#: executor/spi.c:1613 #, c-format msgid "cannot open %s query as cursor" msgstr "カーソルで%s問い合わせを開くことができません" -#: executor/spi.c:1715 +#: executor/spi.c:1720 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHAREはサポートされていません" -#: executor/spi.c:1716 parser/analyze.c:2928 +#: executor/spi.c:1721 parser/analyze.c:3161 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "スクロール可能カーソルは読み取り専用である必要があります。" -#: executor/spi.c:2488 +#: executor/spi.c:2498 #, c-format msgid "empty query does not return tuples" msgstr "空の問い合わせは結果を返却しません" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2562 +#: executor/spi.c:2573 #, c-format msgid "%s query does not return tuples" msgstr "%s問い合わせがタプルを返しません" -#: executor/spi.c:2979 +#: executor/spi.c:3004 #, c-format -msgid "SQL expression \"%s\"" -msgstr "SQL関数\"%s\"" +msgid "PL/pgSQL expression \"%s\"" +msgstr "PL/pgSQL式 \"%s\"" -#: executor/spi.c:2984 +#: executor/spi.c:3009 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "PL/pgSQL代入\"%s\"" -#: executor/spi.c:2987 +#: executor/spi.c:3012 #, c-format msgid "SQL statement \"%s\"" msgstr "SQL文 \"%s\"" @@ -13836,478 +14084,480 @@ msgstr "SQL文 \"%s\"" msgid "could not send tuple to shared-memory queue" msgstr "共有メモリキューにタプルを送出できませんでした" -#: foreign/foreign.c:224 +#: foreign/foreign.c:225 #, c-format msgid "user mapping not found for user \"%s\", server \"%s\"" msgstr "ユーザー\"%s\"、サーバー\"%s\"に対するユーザーマッピングが見つかりません" -#: foreign/foreign.c:650 +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7228 optimizer/util/plancat.c:538 +#, c-format +msgid "access to non-system foreign table is restricted" +msgstr "非システムの外部テーブルへのアクセスは制限されています" + +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "不正なオプション\"%s\"" -#: foreign/foreign.c:652 +#: foreign/foreign.c:662 #, c-format msgid "Perhaps you meant the option \"%s\"." msgstr "おそらくオプション\"%s\"なのではないでしょうか。" -#: foreign/foreign.c:654 +#: foreign/foreign.c:664 #, c-format msgid "There are no valid options in this context." msgstr "このコンテクストで有効なオプションはありません。" -#: gram.y:1234 +#: gram.y:1223 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "UNENCRYPTED PASSWORD は今後サポートされません" -#: gram.y:1235 +#: gram.y:1224 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." msgstr "UNENCRYPTED を削除してください。そうすれば替わりにパスワードを暗号化形式で格納します。" -#: gram.y:1562 gram.y:1578 +#: gram.y:1551 gram.y:1567 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "CREATE SCHEMA IF NOT EXISTSにはスキーマ要素を含めることはできません" -#: gram.y:1730 +#: gram.y:1728 #, c-format msgid "current database cannot be changed" msgstr "現在のデータベースを変更できません" -#: gram.y:1863 +#: gram.y:1869 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "タイムゾーンの間隔はHOURまたはHOUR TO MINUTEでなければなりません" -#: gram.y:2539 +#: gram.y:2501 #, c-format msgid "column number must be in range from 1 to %d" msgstr "列番号は1から%dまでの範囲でなければなりません" -#: gram.y:3135 +#: gram.y:3120 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "シーケンスのオプション\"%s\"はここではサポートされていません" -#: gram.y:3174 +#: gram.y:3159 #, c-format msgid "modulus for hash partition provided more than once" msgstr "ハッシュパーティションで法(除数)が2回以上指定されています" -#: gram.y:3183 +#: gram.y:3168 #, c-format msgid "remainder for hash partition provided more than once" msgstr "ハッシュパーティションで剰余が2回以上指定されています" -#: gram.y:3190 +#: gram.y:3175 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "ハッシュパーティションの境界条件\"%s\"が認識できません" -#: gram.y:3198 +#: gram.y:3183 #, c-format msgid "modulus for hash partition must be specified" msgstr "ハッシュパーティションでは法(除数)の指定が必要です" -#: gram.y:3202 +#: gram.y:3188 #, c-format msgid "remainder for hash partition must be specified" msgstr "ハッシュパーティションでは剰余の指定が必要です" -#: gram.y:3410 gram.y:3444 +#: gram.y:3397 gram.y:3432 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "STDIN/STDOUTはPROGRAMと同時に使用できません" -#: gram.y:3416 +#: gram.y:3403 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "COPY TO で WHERE 句は使用できません" -#: gram.y:3764 gram.y:3771 gram.y:13068 gram.y:13076 +#: gram.y:3752 gram.y:3759 gram.y:13184 gram.y:13192 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "一時テーブル作成におけるGLOBALは廃止予定です" -#: gram.y:4047 +#: gram.y:4041 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" msgstr "生成カラムに対しては GENERATED ALWAYS の指定が必須です" -#: gram.y:4392 utils/adt/ri_triggers.c:2103 +#: gram.y:4450 utils/adt/ri_triggers.c:2259 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "MMATCH PARTIAL はまだ実装されていません" -#: gram.y:4484 +#: gram.y:4542 #, c-format msgid "a column list with %s is only supported for ON DELETE actions" msgstr "%sが指定された列リストはON DELETEのアクションに対してのみサポートされます" -#: gram.y:5196 +#: gram.y:5261 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM はすでにサポートされていません" -#: gram.y:5894 +#: gram.y:5959 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "認識できない行セキュリティオプション \"%s\"" -#: gram.y:5895 +#: gram.y:5960 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." msgstr "現時点ではPERMISSIVEもしくはRESTRICTIVEポリシのみがサポートされています" -#: gram.y:5980 +#: gram.y:6045 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGERはサポートされません" -#: gram.y:6017 +#: gram.y:6083 msgid "duplicate trigger events specified" msgstr "重複したトリガーイベントが指定されました" -#: gram.y:6159 parser/parse_utilcmd.c:3839 parser/parse_utilcmd.c:3865 +#: gram.y:6225 parser/parse_utilcmd.c:3925 parser/parse_utilcmd.c:3951 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" msgstr "INITIALLY DEFERREDと宣言された制約はDEFERRABLEでなければなりません" -#: gram.y:6166 +#: gram.y:6233 #, c-format msgid "conflicting constraint properties" msgstr "制約属性の競合" -#: gram.y:6265 +#: gram.y:6334 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "CREATE ASSERTIONはまだ実装されていません" -#: gram.y:6582 +#: gram.y:6652 #, c-format msgid "dropping an enum value is not implemented" msgstr "列挙型の値の削除は実装されていません" -#: gram.y:6700 -#, c-format -msgid "RECHECK is no longer required" -msgstr "RECHECK はもはや必要とされません" - -#: gram.y:6701 -#, c-format -msgid "Update your data type." -msgstr "データ型を更新してください" - -#: gram.y:8574 +#: gram.y:8632 #, c-format msgid "aggregates cannot have output arguments" msgstr "集約は出力の引数を持つことができません" -#: gram.y:9037 utils/adt/regproc.c:670 +#: gram.y:9096 utils/adt/regproc.c:670 #, c-format msgid "missing argument" msgstr "引数が足りません" -#: gram.y:9038 utils/adt/regproc.c:671 +#: gram.y:9097 utils/adt/regproc.c:671 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "単項演算子の存在しない引数を表すにはNONEを使用してください。" -#: gram.y:11266 gram.y:11285 +#: gram.y:11325 gram.y:11344 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "WITH CHECK OPTIONは再帰ビューではサポートされていません" -#: gram.y:13207 +#: gram.y:13331 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "LIMIT #,#構文は実装されていません" -#: gram.y:13208 +#: gram.y:13332 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "分割してLIMITとOFFSET句を使用してください" -#: gram.y:14083 +#: gram.y:14220 #, c-format msgid "only one DEFAULT value is allowed" msgstr "DEFAULT値は一つだけ指定可能です" -#: gram.y:14092 +#: gram.y:14229 #, c-format msgid "only one PATH value per column is allowed" msgstr "列一つにつきPATH値は一つだけ指定可能です" -#: gram.y:14101 +#: gram.y:14238 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "列\"%s\"でNULL / NOT NULL宣言が衝突しているか重複しています" -#: gram.y:14110 +#: gram.y:14247 #, c-format msgid "unrecognized column option \"%s\"" msgstr "認識できない列オプション \"%s\"" -#: gram.y:14192 +#: gram.y:14329 #, c-format msgid "only string constants are supported in JSON_TABLE path specification" msgstr "JSON_TABLEパス指定では文字列定数のみがサポートされます" -#: gram.y:14514 +#: gram.y:14651 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "浮動小数点数の型の精度は最低でも1ビット必要です" -#: gram.y:14523 +#: gram.y:14660 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "浮動小数点型の精度は54ビットより低くなければなりません" -#: gram.y:15040 +#: gram.y:15177 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "OVERLAPS式の左辺のパラメータ数が間違っています" -#: gram.y:15045 +#: gram.y:15182 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "OVERLAPS式の右辺のパラメータ数が間違っています" -#: gram.y:15222 +#: gram.y:15359 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "UNIQUE 述部はまだ実装されていません" -#: gram.y:15636 +#: gram.y:15773 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "複数のORDER BY句はWITHIN GROUPと一緒には使用できません" -#: gram.y:15641 +#: gram.y:15778 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "DISTINCT は WITHIN GROUP と同時には使えません" -#: gram.y:15646 +#: gram.y:15783 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "VARIADIC は WITHIN GROUP と同時には使えません" -#: gram.y:16373 gram.y:16397 +#: gram.y:16510 gram.y:16534 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "フレームの開始は UNBOUNDED FOLLOWING であってはなりません" -#: gram.y:16378 +#: gram.y:16515 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "次の行から始まるフレームは、現在行では終了できません" -#: gram.y:16402 +#: gram.y:16539 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "フレームの終了は UNBOUNDED PRECEDING であってはなりません" -#: gram.y:16408 +#: gram.y:16545 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "現在行から始まるフレームは、先行する行を含むことができません" -#: gram.y:16415 +#: gram.y:16552 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "次の行から始まるフレームは、先行する行を含むことができません" -#: gram.y:16964 +#: gram.y:17101 #, c-format msgid "unrecognized JSON encoding: %s" msgstr "不明なJSON符号化方式: \"%s\"" -#: gram.y:17288 +#: gram.y:17426 #, c-format msgid "type modifier cannot have parameter name" msgstr "型修正子はパラメータ名を持つことはできません" -#: gram.y:17294 +#: gram.y:17432 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "型修正子はORDER BYを持つことはできません" -#: gram.y:17362 gram.y:17369 gram.y:17376 +#: gram.y:17500 gram.y:17507 gram.y:17514 #, c-format msgid "%s cannot be used as a role name here" msgstr "%sはここではロール名として使用できません" -#: gram.y:17466 gram.y:18955 +#: gram.y:17604 gram.y:19135 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" msgstr "WITH TIESはORDER BY句なしでは指定できません" -#: gram.y:18646 gram.y:18821 +#: gram.y:18828 gram.y:19003 msgid "improper use of \"*\"" msgstr "\"*\"の使い方が不適切です" -#: gram.y:18784 gram.y:18801 tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 tsearch/spell.c:1014 tsearch/spell.c:1079 +#: gram.y:18966 gram.y:18983 tsearch/spell.c:965 tsearch/spell.c:982 tsearch/spell.c:999 tsearch/spell.c:1016 tsearch/spell.c:1082 #, c-format msgid "syntax error" msgstr "構文エラー" -#: gram.y:18885 +#: gram.y:19067 #, c-format msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type" msgstr "VARIADIC直接引数を使った順序集合集約は同じデータタイプのVARIADIC集約引数を一つ持つ必要があります" -#: gram.y:18922 +#: gram.y:19104 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "複数のORDER BY句は使用できません" -#: gram.y:18933 +#: gram.y:19115 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "複数のOFFSET句は使用できません" -#: gram.y:18942 +#: gram.y:19124 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "複数のLIMIT句は使用できません" -#: gram.y:18951 -#, c-format -msgid "multiple limit options not allowed" -msgstr "複数のLIMITオプションは使用できません" - -#: gram.y:18978 +#: gram.y:19160 #, c-format msgid "multiple WITH clauses not allowed" msgstr "複数の WITH 句は使用できません" -#: gram.y:19171 +#: gram.y:19358 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "テーブル関数では OUT と INOUT 引数は使用できません" -#: gram.y:19304 +#: gram.y:19492 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "複数の COLLATE 句は使用できません" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19342 gram.y:19355 +#: gram.y:19532 gram.y:19545 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "%s制約は遅延可能にはできません" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19368 +#: gram.y:19558 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "%s制約をNOT VALIDとマークすることはできません" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19381 +#: gram.y:19571 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "%s制約をNO INHERITをマークすることはできません" -#: gram.y:19403 +#. translator: %s is CHECK, UNIQUE, or similar +#: gram.y:19584 +#, c-format +msgid "%s constraints cannot be marked NOT ENFORCED" +msgstr "%s制約をNOT ENFORCEDとマークすることはできません" + +#. translator: %s is CHECK, UNIQUE, or similar +#: gram.y:19606 +#, c-format +msgid "%s constraints cannot be marked ENFORCED" +msgstr "%s制約をENFORCEDとマークすることはできません" + +#: gram.y:19628 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "識別できないパーティションストラテジ \"%s\"" -#: gram.y:19427 +#: gram.y:19652 #, c-format msgid "invalid publication object list" msgstr "不正なパブリケーションオブジェクトリスト" -#: gram.y:19428 +#: gram.y:19653 #, c-format msgid "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name." msgstr "テーブル名やスキーマ名を単独記述の前にTABLEまたはTABLES IN SCHEMAのいずれかを指定する必要があります。" -#: gram.y:19444 +#: gram.y:19669 #, c-format msgid "invalid table name" msgstr "不正なテーブル名" -#: gram.y:19465 +#: gram.y:19690 #, c-format msgid "WHERE clause not allowed for schema" msgstr "WHERE句はスキーマに対しては使用できません" -#: gram.y:19472 +#: gram.y:19697 #, c-format msgid "column specification not allowed for schema" msgstr "列指定はスキーマに対しては使用できません" -#: gram.y:19486 +#: gram.y:19711 #, c-format msgid "invalid schema name" msgstr "不正なスキーマ名" -#: guc-file.l:192 +#: guc-file.l:193 #, c-format msgid "empty configuration file name: \"%s\"" msgstr "空の設定ファイル名: \"%s\"" -#: guc-file.l:209 +#: guc-file.l:210 #, c-format msgid "could not open configuration file \"%s\": maximum nesting depth exceeded" msgstr "設定ファイル\"%s\"をオープンできませんでした: 入れ子長が上限を超えています" -#: guc-file.l:229 +#: guc-file.l:230 #, c-format msgid "configuration file recursion in \"%s\"" msgstr "設定ファイル\"%s\"が再帰しています" -#: guc-file.l:245 +#: guc-file.l:246 #, c-format msgid "could not open configuration file \"%s\": %m" msgstr "設定ファイル\"%s\"をオープンできませんでした: %m" -#: guc-file.l:256 +#: guc-file.l:257 #, c-format msgid "skipping missing configuration file \"%s\"" msgstr "存在しない設定ファイル\"%s\"をスキップします" -#: guc-file.l:511 +#: guc-file.l:518 #, c-format msgid "syntax error in file \"%s\" line %u, near end of line" msgstr "ファイル\"%s\"の行%uの行末近辺で構文エラーがありました" -#: guc-file.l:521 +#: guc-file.l:528 #, c-format msgid "syntax error in file \"%s\" line %u, near token \"%s\"" msgstr "ファイル\"%s\"の行%uのトークン\"%s\"近辺で構文エラーがありました" -#: guc-file.l:541 +#: guc-file.l:548 #, c-format msgid "too many syntax errors found, abandoning file \"%s\"" msgstr "多くの構文エラーがありました。ファイル\"%s\"を断念します" -#: jsonpath_gram.y:266 jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 jsonpath_scan.l:661 jsonpath_scan.l:712 utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:658 utils/adt/varlena.c:333 utils/adt/varlena.c:374 +#: jsonpath_gram.y:268 jsonpath_gram.y:600 jsonpath_scan.l:617 jsonpath_scan.l:628 jsonpath_scan.l:638 jsonpath_scan.l:690 utils/adt/encode.c:513 utils/adt/encode.c:578 utils/adt/jsonfuncs.c:661 utils/adt/varlena.c:341 utils/adt/varlena.c:382 #, c-format msgid "invalid input syntax for type %s" msgstr "%s型に対する不正な入力構文" -#: jsonpath_gram.y:267 +#: jsonpath_gram.y:269 #, c-format msgid ".decimal() can only have an optional precision[,scale]." msgstr ".decimal()では\"精度[,スケール]\"のオプションを1つだけ指定可能です" -#: jsonpath_gram.y:599 +#: jsonpath_gram.y:601 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." msgstr "LIKE_REGEX 述語の中に認識できないフラグ文字\"%.*s\"があります。" -#: jsonpath_gram.y:629 tsearch/spell.c:749 utils/adt/regexp.c:223 +#: jsonpath_gram.y:631 tsearch/spell.c:751 utils/adt/regexp.c:223 #, c-format msgid "invalid regular expression: %s" msgstr "正規表現が不正です: %s" -#: jsonpath_gram.y:677 +#: jsonpath_gram.y:679 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "XQueryの\"x\"フラグ(拡張正規表現)は実装されていません" @@ -14324,48 +14574,48 @@ msgstr "不正な16進文字列" msgid "unexpected end after backslash" msgstr "バックスラッシュの後の想定外の終了" -#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:742 +#: jsonpath_scan.l:201 repl_scanner.l:217 scan.l:742 msgid "unterminated quoted string" msgstr "文字列の引用符が閉じていません" -#: jsonpath_scan.l:228 +#: jsonpath_scan.l:227 msgid "unexpected end of comment" msgstr "コメントの想定外の終了" -#: jsonpath_scan.l:319 +#: jsonpath_scan.l:317 msgid "invalid numeric literal" msgstr "不正なnumericリテラル" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1050 scan.l:1054 scan.l:1058 scan.l:1062 scan.l:1066 scan.l:1070 scan.l:1074 +#: jsonpath_scan.l:322 jsonpath_scan.l:327 jsonpath_scan.l:332 scan.l:1056 scan.l:1060 scan.l:1064 scan.l:1068 msgid "trailing junk after numeric literal" msgstr "数値リテラルの後ろにゴミがあります" #. translator: %s is typically "syntax error" -#: jsonpath_scan.l:375 +#: jsonpath_scan.l:378 #, c-format msgid "%s at end of jsonpath input" msgstr "jsonpath の最後に %s があります" #. translator: first %s is typically "syntax error" -#: jsonpath_scan.l:382 +#: jsonpath_scan.l:385 #, c-format msgid "%s at or near \"%s\" of jsonpath input" msgstr "jsonpath 入力の\"%2$s\"または近くに %1$s があります" -#: jsonpath_scan.l:568 +#: jsonpath_scan.l:545 msgid "invalid input" msgstr "不正な入力" -#: jsonpath_scan.l:594 +#: jsonpath_scan.l:571 msgid "invalid hexadecimal digit" msgstr "不正な16進数桁" -#: jsonpath_scan.l:607 utils/adt/jsonfuncs.c:646 +#: jsonpath_scan.l:584 utils/adt/jsonfuncs.c:649 #, c-format msgid "unsupported Unicode escape sequence" msgstr "サポートされないUnicodeエスケープシーケンス" -#: jsonpath_scan.l:625 +#: jsonpath_scan.l:602 #, c-format msgid "could not convert Unicode to server encoding" msgstr "Unicodeのサーバーエンコーディングへの変換に失敗しました" @@ -14375,684 +14625,851 @@ msgstr "Unicodeのサーバーエンコーディングへの変換に失敗し msgid "Failed on DSA request of size %zu." msgstr "サイズ%zuの動的共有エリアの要求に失敗しました。" -#: libpq/auth-sasl.c:97 -#, c-format -msgid "expected SASL response, got message type %d" -msgstr "SASL応答を想定していましたが、メッセージタイプ%dを受け取りました" - -#: libpq/auth-scram.c:263 +#: libpq/auth-oauth.c:109 libpq/auth-scram.c:267 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "クライアントが無効なSASL認証機構を選択しました" -#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 +#: libpq/auth-oauth.c:169 libpq/auth-oauth.c:174 libpq/auth-oauth.c:192 libpq/auth-oauth.c:220 libpq/auth-oauth.c:230 libpq/auth-oauth.c:239 libpq/auth-oauth.c:254 libpq/auth-oauth.c:263 libpq/auth-oauth.c:272 libpq/auth-oauth.c:279 libpq/auth-oauth.c:342 libpq/auth-oauth.c:349 libpq/auth-oauth.c:375 libpq/auth-oauth.c:420 libpq/auth-oauth.c:438 libpq/auth-oauth.c:452 libpq/auth-oauth.c:472 +#, c-format +msgid "malformed OAUTHBEARER message" +msgstr "不正なフォーマットのOAUTHBEARERメッセージです" + +#: libpq/auth-oauth.c:170 libpq/auth-scram.c:383 +#, c-format +msgid "The message is empty." +msgstr "メッセージが空です。" + +#: libpq/auth-oauth.c:175 libpq/auth-scram.c:388 +#, c-format +msgid "Message length does not match input length." +msgstr "メッセージの長さが入力の長さと一致しません" + +#: libpq/auth-oauth.c:193 +#, c-format +msgid "Client did not send a kvsep response." +msgstr "クライアントは kvsep レスポンスを送信しませんでした。" + +#: libpq/auth-oauth.c:221 +#, c-format +msgid "The server does not support channel binding for OAuth, but the client message includes channel binding data." +msgstr "このサーバーはOAuthのチャンネルバインディングをサポートしていませんが、クライアントからのメッセージにはチャンネルバインディングのデータが含まれています。" + +#: libpq/auth-oauth.c:231 libpq/auth-scram.c:1003 libpq/auth-scram.c:1033 +#, c-format +msgid "Comma expected, but found character \"%s\"." +msgstr "カンマを想定していましたが、文字\"%s\"が見つかりました" + +#: libpq/auth-oauth.c:240 libpq/auth-scram.c:1065 +#, c-format +msgid "Unexpected channel-binding flag \"%s\"." +msgstr "予期しないチャネル割り当てフラグ \"%s\"" + +#: libpq/auth-oauth.c:250 libpq/auth-scram.c:1075 +#, c-format +msgid "client uses authorization identity, but it is not supported" +msgstr "クライアントは認証識別子を使っていますがサポートされていません" + +#: libpq/auth-oauth.c:255 libpq/auth-scram.c:1080 +#, c-format +msgid "Unexpected attribute \"%s\" in client-first-message." +msgstr "client-fist-message での想定外の属性\"%s\"" + +#: libpq/auth-oauth.c:264 +#, c-format +msgid "Key-value separator expected, but found character \"%s\"." +msgstr "キー/値の区切り文字を期待していましたが、文字\"%s\"が見つかりました。" + +#: libpq/auth-oauth.c:273 +#, c-format +msgid "Message does not contain an auth value." +msgstr "メッセージに認証値が含まれていません。" + +#: libpq/auth-oauth.c:280 +#, c-format +msgid "Message contains additional data after the final terminator." +msgstr "メッセージには、最終終端記号の後に追加のデータが含まれています。" + +#: libpq/auth-oauth.c:343 +#, c-format +msgid "Message contains an empty key name." +msgstr "メッセージに空のキー名が含まれています。" + +#: libpq/auth-oauth.c:350 +#, c-format +msgid "Message contains an invalid key name." +msgstr "メッセージに不正なキー名が含まれています。" + +#: libpq/auth-oauth.c:376 +#, c-format +msgid "Message contains an invalid value." +msgstr "メッセージに不正な値が含まれてます。" + +#: libpq/auth-oauth.c:421 +#, c-format +msgid "Message contains an unterminated key/value pair." +msgstr "メッセージに終端されていないキー/値ペアが含まれています。" + +#: libpq/auth-oauth.c:439 +#, c-format +msgid "Message contains a key without a value." +msgstr "メッセージに値を伴わないキーが含まれています。" + +#: libpq/auth-oauth.c:453 +#, c-format +msgid "Message contains multiple auth values." +msgstr "メッセージに複数の認証値が含まれています。" + +#: libpq/auth-oauth.c:473 +#, c-format +msgid "Message did not contain a final terminator." +msgstr "メッセージに最終終端記号がありません。" + +#: libpq/auth-oauth.c:499 +#, c-format +msgid "OAuth is not properly configured for this user" +msgstr "OAuthがこのユーザーに対して適切に設定されていません" + +#: libpq/auth-oauth.c:500 +#, c-format +msgid "The issuer and scope parameters must be set in pg_hba.conf." +msgstr "issuerとscopeのパラメータは pg_hba.conf で設定する必要があります。" + +#: libpq/auth-oauth.c:585 libpq/auth-oauth.c:602 libpq/auth-oauth.c:624 +#, c-format +msgid "malformed OAuth bearer token" +msgstr "不正な形式のBearerトークン" + +#: libpq/auth-oauth.c:586 +#, c-format +msgid "Client response indicated a non-Bearer authentication scheme." +msgstr "クライアントの応答はBearer以外の認証スキームを示していました。" + +#: libpq/auth-oauth.c:603 +#, c-format +msgid "Bearer token is empty." +msgstr "Beareトークンが空です。" + +#: libpq/auth-oauth.c:625 +#, c-format +msgid "Bearer token is not in the correct format." +msgstr "Bearerトークンのフォーマットが正しくありません。" + +#: libpq/auth-oauth.c:656 +#, c-format +msgid "validation of OAuth token requested without a validator loaded" +msgstr "バリデータがロードされていない状態で、OAuthトークンの検証が要求されました" + +#: libpq/auth-oauth.c:665 +#, c-format +msgid "internal error in OAuth validator module" +msgstr "OAuthバリデータの内部エラー" + +#: libpq/auth-oauth.c:679 libpq/auth-oauth.c:703 libpq/auth.c:294 +#, c-format +msgid "OAuth bearer authentication failed for user \"%s\"" +msgstr "ユーザー \"%s\" の OAuth Bearer 認証に失敗しました" + +#: libpq/auth-oauth.c:681 +#, c-format +msgid "Validator failed to authorize the provided token." +msgstr "バリデータは、与えられたトークンを認可できませんでした。" + +#: libpq/auth-oauth.c:705 +#, c-format +msgid "Validator provided no identity." +msgstr "バリデータが識別情報を提供しませんでした。" + +#: libpq/auth-oauth.c:760 +#, c-format +msgid "%s module \"%s\" must define the symbol %s" +msgstr "%s モジュール \"%s\" はシンボル %s を定義する必要があります" + +#: libpq/auth-oauth.c:773 +#, c-format +msgid "%s module \"%s\": magic number mismatch" +msgstr "%s モジュール \"%s\": マジックナンバーが不一致です" + +#: libpq/auth-oauth.c:775 +#, c-format +msgid "Server has magic number 0x%08X, module has 0x%08X." +msgstr "サーバーのマジックナンバーは 0x%08X ですが、モジュールのマジックナンバーは 0x%08X です。" + +#: libpq/auth-oauth.c:784 +#, c-format +msgid "%s module \"%s\" must provide a %s callback" +msgstr "%s モジュール \"%s\" は %s コールバックを実装する必要があります" + +#: libpq/auth-oauth.c:833 +#, c-format +msgid "oauth_validator_libraries must be set for authentication method %s" +msgstr "認証方式 %s では、oauth_validator_libraries を設定しなければなりません。" + +#: libpq/auth-oauth.c:835 libpq/auth-oauth.c:868 libpq/auth-oauth.c:884 libpq/hba.c:331 libpq/hba.c:666 libpq/hba.c:1251 libpq/hba.c:1271 libpq/hba.c:1294 libpq/hba.c:1307 libpq/hba.c:1360 libpq/hba.c:1388 libpq/hba.c:1396 libpq/hba.c:1408 libpq/hba.c:1429 libpq/hba.c:1442 libpq/hba.c:1467 libpq/hba.c:1494 libpq/hba.c:1506 libpq/hba.c:1565 libpq/hba.c:1585 libpq/hba.c:1599 libpq/hba.c:1619 libpq/hba.c:1630 libpq/hba.c:1645 libpq/hba.c:1664 libpq/hba.c:1680 +#: libpq/hba.c:1692 libpq/hba.c:1760 libpq/hba.c:1773 libpq/hba.c:1795 libpq/hba.c:1807 libpq/hba.c:1825 libpq/hba.c:1875 libpq/hba.c:1919 libpq/hba.c:1930 libpq/hba.c:1946 libpq/hba.c:1963 libpq/hba.c:1974 libpq/hba.c:1993 libpq/hba.c:2009 libpq/hba.c:2025 libpq/hba.c:2069 libpq/hba.c:2115 libpq/hba.c:2132 libpq/hba.c:2145 libpq/hba.c:2157 libpq/hba.c:2176 libpq/hba.c:2262 libpq/hba.c:2280 libpq/hba.c:2374 libpq/hba.c:2393 libpq/hba.c:2422 libpq/hba.c:2435 +#: libpq/hba.c:2458 libpq/hba.c:2480 libpq/hba.c:2517 tsearch/ts_locale.c:196 +#, c-format +msgid "line %d of configuration file \"%s\"" +msgstr "設定ファイル \"%2$s\" の %1$d 行目" + +#: libpq/auth-oauth.c:867 +#, c-format +msgid "authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options" +msgstr "認証方式 \"oauth\" で、oauth_validator_libraries に複数のオプションを指定する場合は、引数 \"validator\" を設定する必要があります" + +#: libpq/auth-oauth.c:882 +#, c-format +msgid "validator \"%s\" is not permitted by %s" +msgstr "バリデータ \"%s\" は %s により許可されていません" + +#: libpq/auth-sasl.c:89 +#, c-format +msgid "expected SASL response, got message type %d" +msgstr "SASL応答を想定していましたが、メッセージタイプ%dを受け取りました" + +#: libpq/auth-scram.c:291 libpq/auth-scram.c:547 libpq/auth-scram.c:558 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "ユーザー\"%s\"に対する不正なSCRAMシークレット" -#: libpq/auth-scram.c:298 +#: libpq/auth-scram.c:302 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "ユーザー\"%s\"は有効なSCRAMシークレットを持ちません。" -#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:382 libpq/auth-scram.c:387 libpq/auth-scram.c:751 libpq/auth-scram.c:759 libpq/auth-scram.c:864 libpq/auth-scram.c:877 libpq/auth-scram.c:887 libpq/auth-scram.c:995 libpq/auth-scram.c:1002 libpq/auth-scram.c:1017 libpq/auth-scram.c:1032 libpq/auth-scram.c:1046 libpq/auth-scram.c:1064 libpq/auth-scram.c:1079 libpq/auth-scram.c:1392 libpq/auth-scram.c:1400 #, c-format msgid "malformed SCRAM message" msgstr "不正なフォーマットのSCRAMメッセージです" -#: libpq/auth-scram.c:379 -#, c-format -msgid "The message is empty." -msgstr "メッセージが空です。" - -#: libpq/auth-scram.c:384 -#, c-format -msgid "Message length does not match input length." -msgstr "メッセージの長さが入力の長さと一致しません" - -#: libpq/auth-scram.c:416 +#: libpq/auth-scram.c:420 #, c-format msgid "invalid SCRAM response" msgstr "不正なSCRAM応答" -#: libpq/auth-scram.c:417 +#: libpq/auth-scram.c:421 #, c-format msgid "Nonce does not match." msgstr "Nonce が合致しません" -#: libpq/auth-scram.c:493 +#: libpq/auth-scram.c:504 #, c-format msgid "could not generate random salt" msgstr "乱数ソルトを生成できませんでした" -#: libpq/auth-scram.c:738 +#: libpq/auth-scram.c:752 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "属性\"%c\"を想定していましたが、\"%s\"でした。" -#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 +#: libpq/auth-scram.c:760 libpq/auth-scram.c:888 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "属性\"%c\"としては文字\"=\"を想定していました。" -#: libpq/auth-scram.c:851 +#: libpq/auth-scram.c:865 #, c-format msgid "Attribute expected, but found end of string." msgstr "属性を想定しましたが、文字列が終了しました。" -#: libpq/auth-scram.c:864 +#: libpq/auth-scram.c:878 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "属性を想定しましたが、不正な文字\"%s\"でした。" -#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 +#: libpq/auth-scram.c:996 libpq/auth-scram.c:1018 #, c-format msgid "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data." msgstr "クライアントは SCRAM-SHA-256-PLUS を選択しましたが、SCRAM メッセージにはチャネルバインディング情報が含まれていません。" -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 -#, c-format -msgid "Comma expected, but found character \"%s\"." -msgstr "カンマを想定していましたが、文字\"%s\"が見つかりました" - -#: libpq/auth-scram.c:1010 +#: libpq/auth-scram.c:1024 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "SCRAM チャネルバインディングのネゴシエーションエラー" -#: libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:1025 #, c-format msgid "The client supports SCRAM channel binding but thinks the server does not. However, this server does support channel binding." msgstr "クライアントは SCRAM チャネルバインディングをサポートしていますが、サーバーではサポートされていないと思っています。しかし実際にはサポートしています。" -#: libpq/auth-scram.c:1033 +#: libpq/auth-scram.c:1047 #, c-format msgid "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data." msgstr "クライアントはチャネルバインディングなしの SCRAM-SHA-256 を選択しましたが、SCRAM メッセージにはチャネルバインディング情報が含まれています。" -#: libpq/auth-scram.c:1044 +#: libpq/auth-scram.c:1058 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "SCRAM チャネルバインディングタイプ \"%s\"はサポートされていません" -#: libpq/auth-scram.c:1051 -#, c-format -msgid "Unexpected channel-binding flag \"%s\"." -msgstr "予期しないチャネル割り当てフラグ \"%s\"" - -#: libpq/auth-scram.c:1061 -#, c-format -msgid "client uses authorization identity, but it is not supported" -msgstr "クライアントは認証識別子を使っていますがサポートされていません" - -#: libpq/auth-scram.c:1066 -#, c-format -msgid "Unexpected attribute \"%s\" in client-first-message." -msgstr "client-fist-message での想定外の属性\"%s\"" - -#: libpq/auth-scram.c:1082 +#: libpq/auth-scram.c:1096 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "クライアントはサポート外のSCRAM拡張を要求しています" -#: libpq/auth-scram.c:1096 +#: libpq/auth-scram.c:1110 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "SCRAM nonce の中に表示不能な文字があります" -#: libpq/auth-scram.c:1227 +#: libpq/auth-scram.c:1240 #, c-format msgid "could not generate random nonce" msgstr "乱数nonceを生成できませんでした" -#: libpq/auth-scram.c:1237 +#: libpq/auth-scram.c:1250 #, c-format msgid "could not encode random nonce" msgstr "乱数nonceをエンコードできませんでした" -#: libpq/auth-scram.c:1343 +#: libpq/auth-scram.c:1356 #, c-format msgid "SCRAM channel binding check failed" msgstr "SCRAM チャネルバインディングの確認で失敗しました" -#: libpq/auth-scram.c:1361 +#: libpq/auth-scram.c:1374 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "client-final-message 中に想定外の SCRAM channel-binding 属性がありました" -#: libpq/auth-scram.c:1380 +#: libpq/auth-scram.c:1393 #, c-format msgid "Malformed proof in client-final-message." msgstr "client-final-message 中の proof の形式が不正です" -#: libpq/auth-scram.c:1388 +#: libpq/auth-scram.c:1401 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "client-final-message の終端に不要なデータがあります。" -#: libpq/auth.c:269 +#: libpq/auth.c:254 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "ユーザー\"%s\"の認証に失敗しました: ホストを拒絶しました" -#: libpq/auth.c:272 +#: libpq/auth.c:257 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"の\"trust\"認証に失敗しました" -#: libpq/auth.c:275 +#: libpq/auth.c:260 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のIdent認証に失敗しました" -#: libpq/auth.c:278 +#: libpq/auth.c:263 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"で対向(peer)認証に失敗しました" -#: libpq/auth.c:283 +#: libpq/auth.c:268 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のパスワード認証に失敗しました" -#: libpq/auth.c:288 +#: libpq/auth.c:273 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のGSSAPI認証に失敗しました" -#: libpq/auth.c:291 +#: libpq/auth.c:276 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のSSPI認証に失敗しました" -#: libpq/auth.c:294 +#: libpq/auth.c:279 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のPAM認証に失敗しました" -#: libpq/auth.c:297 +#: libpq/auth.c:282 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のBSD認証に失敗しました" -#: libpq/auth.c:300 +#: libpq/auth.c:285 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"のLDAP認証に失敗しました" -#: libpq/auth.c:303 +#: libpq/auth.c:288 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"の証明書認証に失敗しました" -#: libpq/auth.c:306 +#: libpq/auth.c:291 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "ユーザー\"%s\"の RADIUS 認証に失敗しました" -#: libpq/auth.c:309 +#: libpq/auth.c:297 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "ユーザー\"%s\"の認証に失敗しました: 認証方式が不正です" -#: libpq/auth.c:313 +#: libpq/auth.c:301 #, c-format msgid "Connection matched file \"%s\" line %d: \"%s\"" msgstr "接続はファイル%sの行%dに一致しました: \"%s\"" -#: libpq/auth.c:357 +#: libpq/auth.c:346 #, c-format msgid "authentication identifier set more than once" msgstr "認証識別子が2度以上設定されました" -#: libpq/auth.c:358 +#: libpq/auth.c:347 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "以前の識別子: \"%s\"; 新しい識別子: \"%s\"" -#: libpq/auth.c:368 +#: libpq/auth.c:357 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "接続認証完了: 識別名=\"%s\" 方式=%s (%s:%d)" -#: libpq/auth.c:408 +#: libpq/auth.c:397 #, c-format msgid "client certificates can only be checked if a root certificate store is available" msgstr "クライアント証明書はルート証明書ストアが利用できる場合にのみ検証されます" -#: libpq/auth.c:419 +#: libpq/auth.c:408 #, c-format msgid "connection requires a valid client certificate" msgstr "この接続には有効なクライアント証明が必要です" -#: libpq/auth.c:450 libpq/auth.c:496 +#: libpq/auth.c:439 libpq/auth.c:485 msgid "GSS encryption" msgstr "GSS暗号化" -#: libpq/auth.c:453 libpq/auth.c:499 +#: libpq/auth.c:442 libpq/auth.c:488 msgid "SSL encryption" msgstr "SSL暗号化" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:444 libpq/auth.c:490 msgid "no encryption" msgstr "暗号化なし" #. translator: last %s describes encryption state -#: libpq/auth.c:461 +#: libpq/auth.c:450 #, c-format msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf の設定でホスト \"%s\"、ユーザー \"%s\", %s 用のレプリケーション接続を拒否しました" #. translator: last %s describes encryption state -#: libpq/auth.c:468 +#: libpq/auth.c:457 #, c-format msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf の設定でホスト \"%s\"、ユーザー \"%s\"、データベース \"%s\", %sの接続を拒否しました" -#: libpq/auth.c:506 +#: libpq/auth.c:495 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "クライアントIPアドレスは\"%s\"に解決され、前方検索と一致しました。" -#: libpq/auth.c:509 +#: libpq/auth.c:498 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "クライアントIPアドレスは\"%s\"に解決されました。前方検索は検査されません。" -#: libpq/auth.c:512 +#: libpq/auth.c:501 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "クライアントIPアドレスは\"%s\"に解決され、前方検索と一致しませんでした。" -#: libpq/auth.c:515 +#: libpq/auth.c:504 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "クライアントのホスト名\"%s\"をIPアドレスに変換できませんでした: %s。" -#: libpq/auth.c:520 +#: libpq/auth.c:509 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "クライアントのIPアドレスをホスト名に解決できませんでした: %s。" #. translator: last %s describes encryption state -#: libpq/auth.c:528 +#: libpq/auth.c:517 #, c-format msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf にホスト\"%s\"、ユーザー\"%s\", %s用のエントリがありません" #. translator: last %s describes encryption state -#: libpq/auth.c:536 +#: libpq/auth.c:525 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf にホスト\"%s\"、ユーザー\"%s\"、データベース\"%s, %s用のエントリがありません" -#: libpq/auth.c:656 +#: libpq/auth.c:649 #, c-format msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" msgstr "接続認証完了: ユーザー=\"%s\" 方式=%s (%s:%d)" -#: libpq/auth.c:725 +#: libpq/auth.c:718 #, c-format msgid "expected password response, got message type %d" msgstr "パスワード応答を想定しましたが、メッセージタイプ%dを受け取りました" -#: libpq/auth.c:746 +#: libpq/auth.c:739 #, c-format msgid "invalid password packet size" msgstr "パスワードパケットのサイズが不正です" -#: libpq/auth.c:764 +#: libpq/auth.c:757 #, c-format msgid "empty password returned by client" msgstr "クライアントから空のパスワードが返されました" -#: libpq/auth.c:892 +#: libpq/auth.c:885 #, c-format msgid "could not generate random MD5 salt" msgstr "ランダムなMD5ソルトの生成に失敗しました" -#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:936 libpq/be-secure-gssapi.c:543 #, c-format msgid "could not set environment: %m" msgstr "環境を設定できません: %m" -#: libpq/auth.c:982 +#: libpq/auth.c:975 #, c-format msgid "expected GSS response, got message type %d" msgstr "GSS応答を想定しましたが、メッセージタイプ %d を受け取りました" -#: libpq/auth.c:1048 +#: libpq/auth.c:1041 msgid "accepting GSS security context failed" msgstr "GSSセキュリティコンテキストの受け付けに失敗しました" -#: libpq/auth.c:1089 +#: libpq/auth.c:1082 msgid "retrieving GSS user name failed" msgstr "GSSユーザー名の受信に失敗しました" -#: libpq/auth.c:1235 +#: libpq/auth.c:1228 msgid "could not acquire SSPI credentials" msgstr "SSPIの資格ハンドルを入手できませんでした" -#: libpq/auth.c:1260 +#: libpq/auth.c:1253 #, c-format msgid "expected SSPI response, got message type %d" msgstr "SSPI応答を想定しましたが、メッセージタイプ%dを受け取りました" -#: libpq/auth.c:1338 +#: libpq/auth.c:1331 msgid "could not accept SSPI security context" msgstr "SSPIセキュリティコンテキストを受け付けられませんでした" -#: libpq/auth.c:1379 +#: libpq/auth.c:1372 msgid "could not get token from SSPI security context" msgstr "SSPIセキュリティコンテキストからトークンを入手できませんでした" -#: libpq/auth.c:1515 libpq/auth.c:1534 +#: libpq/auth.c:1508 libpq/auth.c:1527 #, c-format msgid "could not translate name" msgstr "名前の変換ができませんでした" -#: libpq/auth.c:1547 +#: libpq/auth.c:1540 #, c-format msgid "realm name too long" msgstr "realm名が長すぎます" -#: libpq/auth.c:1562 +#: libpq/auth.c:1555 #, c-format msgid "translated account name too long" msgstr "変換後のアカウント名が長すぎます" -#: libpq/auth.c:1741 +#: libpq/auth.c:1734 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "Ident接続用のソケットを作成できませんでした: %m" -#: libpq/auth.c:1756 +#: libpq/auth.c:1749 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "ローカルアドレス\"%s\"にバインドできませんでした: %m" -#: libpq/auth.c:1768 +#: libpq/auth.c:1761 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "アドレス\"%s\"、ポート%sのIdentサーバーに接続できませんでした: %m" -#: libpq/auth.c:1790 +#: libpq/auth.c:1783 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "アドレス\"%s\"、ポート%sのIdentサーバーに問い合わせを送信できませんでした: %m" -#: libpq/auth.c:1807 +#: libpq/auth.c:1800 #, c-format msgid "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "アドレス\"%s\"、ポート%sのIdentサーバーからの応答を受信できませんでした: %m" -#: libpq/auth.c:1817 +#: libpq/auth.c:1810 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "Identサーバーからの応答の書式が不正です: \"%s\"" -#: libpq/auth.c:1870 +#: libpq/auth.c:1866 #, c-format msgid "peer authentication is not supported on this platform" msgstr "このプラットフォームでは対向(peer)認証はサポートされていません" -#: libpq/auth.c:1874 +#: libpq/auth.c:1870 #, c-format msgid "could not get peer credentials: %m" msgstr "ピアの資格証明を入手できませんでした: %m" +#: libpq/auth.c:1880 +#, c-format +msgid "could not look up local user ID %ld: %m" +msgstr "ローカルユーザーID %ldの参照に失敗しました: %m" + #: libpq/auth.c:1886 #, c-format -msgid "could not look up local user ID %ld: %s" -msgstr "ローカルユーザーID %ldの参照に失敗しました: %s" +msgid "local user with ID %ld does not exist" +msgstr "ID %ld を持つローカルユーザーは存在しません" -#: libpq/auth.c:1988 +#: libpq/auth.c:1986 #, c-format msgid "error from underlying PAM layer: %s" msgstr "背後のPAM層でエラーがありました: %s" -#: libpq/auth.c:1999 +#: libpq/auth.c:1997 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "非サポートのPAM変換%d/\"%s\"" -#: libpq/auth.c:2056 +#: libpq/auth.c:2054 #, c-format msgid "could not create PAM authenticator: %s" msgstr "PAM authenticatorを作成できませんでした: %s" -#: libpq/auth.c:2067 +#: libpq/auth.c:2065 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "pam_set_item(PAM_USER)が失敗しました: %s" -#: libpq/auth.c:2099 +#: libpq/auth.c:2097 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "pam_set_item(PAM_RHOST)が失敗しました: %s" -#: libpq/auth.c:2111 +#: libpq/auth.c:2109 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "\"pam_set_item(PAM_CONV)が失敗しました: %s" -#: libpq/auth.c:2124 +#: libpq/auth.c:2122 #, c-format msgid "pam_authenticate failed: %s" msgstr "\"pam_authenticateが失敗しました: %s" -#: libpq/auth.c:2137 +#: libpq/auth.c:2135 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "pam_acct_mgmtが失敗しました: %s" -#: libpq/auth.c:2148 +#: libpq/auth.c:2146 #, c-format msgid "could not release PAM authenticator: %s" msgstr "PAM authenticatorを解放できませんでした: %s" -#: libpq/auth.c:2228 +#: libpq/auth.c:2226 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "LDAPを初期化できませんでした: %d" -#: libpq/auth.c:2265 +#: libpq/auth.c:2263 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "ldapbasedn からドメイン名を抽出できませんでした" -#: libpq/auth.c:2273 +#: libpq/auth.c:2271 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "LDAP認証で\"%s\"に対する DNS SRV レコードが見つかりませんでした" -#: libpq/auth.c:2275 +#: libpq/auth.c:2273 #, c-format msgid "Set an LDAP server name explicitly." msgstr "LDAPサーバー名を明示的に指定してください。" -#: libpq/auth.c:2327 +#: libpq/auth.c:2325 #, c-format msgid "could not initialize LDAP: %s" msgstr "LDAPを初期化できませんでした: %s" -#: libpq/auth.c:2337 +#: libpq/auth.c:2335 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "この LDAP ライブラリでは ldaps はサポートされていません" -#: libpq/auth.c:2345 +#: libpq/auth.c:2343 #, c-format msgid "could not initialize LDAP: %m" msgstr "LDAPを初期化できませんでした: %m" -#: libpq/auth.c:2355 +#: libpq/auth.c:2353 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "LDAPプロトコルバージョンを設定できませんでした: %s" -#: libpq/auth.c:2371 +#: libpq/auth.c:2369 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "LDAP TLSセッションを開始できませんでした: %s" -#: libpq/auth.c:2448 +#: libpq/auth.c:2446 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "LDAP サーバーも ldapbasedn も指定されていません" -#: libpq/auth.c:2455 +#: libpq/auth.c:2453 #, c-format msgid "LDAP server not specified" msgstr "LDAP サーバーの指定がありません" -#: libpq/auth.c:2517 +#: libpq/auth.c:2515 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "LDAP 認証でユーザー名の中に不正な文字があります" -#: libpq/auth.c:2534 +#: libpq/auth.c:2532 #, c-format msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s" msgstr "サーバー\"%2$s\"で、ldapbinddn \"%1$s\"によるLDAPバインドを実行できませんでした: %3$s" -#: libpq/auth.c:2564 +#: libpq/auth.c:2562 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "サーバー\"%2$s\"で、フィルタ\"%1$s\"によるLDAP検索ができませんでした: %3$s" -#: libpq/auth.c:2580 +#: libpq/auth.c:2578 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "LDAPサーバー\"%s\"は存在しません" -#: libpq/auth.c:2581 +#: libpq/auth.c:2579 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "サーバー\"%2$s\"で、フィルタ\"%1$s\"によるLDAP検索が何も返しませんでした。" -#: libpq/auth.c:2585 +#: libpq/auth.c:2583 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "LDAPユーザー\"%s\"は一意ではありません" -#: libpq/auth.c:2586 +#: libpq/auth.c:2584 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries." msgstr[0] "サーバー\"%2$s\"で、フィルタ\"%1$s\"によるLDAP検索が%3$d項目返しました。" -#: libpq/auth.c:2606 +#: libpq/auth.c:2604 #, c-format msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" msgstr "サーバー\"%2$s\"で\"%1$s\"にマッチする最初のエントリの dn を取得できません: %3$s" -#: libpq/auth.c:2633 +#: libpq/auth.c:2631 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "サーバー\"%2$s\"でユーザー\"%1$s\"のLDAPログインが失敗しました: %3$s" -#: libpq/auth.c:2665 +#: libpq/auth.c:2663 #, c-format msgid "LDAP diagnostics: %s" msgstr "LDAP診断: %s" -#: libpq/auth.c:2703 +#: libpq/auth.c:2701 #, c-format msgid "certificate authentication failed for user \"%s\": client certificate contains no user name" msgstr "ユーザー \"%s\" の証明書認証に失敗しました: クライアント証明書にユーザー名が含まれていません" -#: libpq/auth.c:2724 +#: libpq/auth.c:2722 #, c-format msgid "certificate authentication failed for user \"%s\": unable to retrieve subject DN" msgstr "ユーザー\"%s\"の証明書認証に失敗しました: サブジェクト識別名(DN)が取得できません" -#: libpq/auth.c:2747 +#: libpq/auth.c:2745 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch" msgstr "ユーザー\"%s\"に対する証明書の検証(clientcert=verify-full) に失敗しました: DN 不一致" -#: libpq/auth.c:2752 +#: libpq/auth.c:2750 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch" msgstr "ユーザー\"%s\"に対する証明書の検証(clientcert=verify-full) に失敗しました: CN 不一致" -#: libpq/auth.c:2854 +#: libpq/auth.c:2852 #, c-format msgid "RADIUS server not specified" msgstr "RADIUS サーバーが指定されていません" -#: libpq/auth.c:2861 +#: libpq/auth.c:2859 #, c-format msgid "RADIUS secret not specified" msgstr "RADIUS secret が指定されていません" -#: libpq/auth.c:2875 +#: libpq/auth.c:2873 #, c-format msgid "RADIUS authentication does not support passwords longer than %d characters" msgstr "RADIUS認証では%d文字より長いパスワードはサポートしていません" -#: libpq/auth.c:2977 libpq/hba.c:2352 +#: libpq/auth.c:2975 libpq/hba.c:2391 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "RADIUS サーバー名\"%s\"をアドレスに変換できませんでした: %s" -#: libpq/auth.c:2991 +#: libpq/auth.c:2989 #, c-format msgid "could not generate random encryption vector" msgstr "ランダムな暗号化ベクトルを生成できませんでした" -#: libpq/auth.c:3028 +#: libpq/auth.c:3026 #, c-format msgid "could not perform MD5 encryption of password: %s" msgstr "パスワードのMD5暗号化に失敗しました: %s" -#: libpq/auth.c:3055 +#: libpq/auth.c:3053 #, c-format msgid "could not create RADIUS socket: %m" msgstr "RADIUSのソケットを作成できませんでした: %m" -#: libpq/auth.c:3071 +#: libpq/auth.c:3069 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "ローカルの RADIUS ソケットをバインドできませんでした: %m" -#: libpq/auth.c:3081 +#: libpq/auth.c:3079 #, c-format msgid "could not send RADIUS packet: %m" msgstr "RADIUS パケットを送信できませんでした: %m" -#: libpq/auth.c:3115 libpq/auth.c:3141 +#: libpq/auth.c:3113 libpq/auth.c:3139 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "%sからのRADIUSの応答待ちがタイムアウトしました" -#: libpq/auth.c:3134 +#: libpq/auth.c:3132 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "RADIUSソケットの状態をチェックできませんでした: %m" -#: libpq/auth.c:3164 +#: libpq/auth.c:3162 #, c-format msgid "could not read RADIUS response: %m" msgstr "RADIUS応答を読めませんでした: %m" -#: libpq/auth.c:3172 +#: libpq/auth.c:3170 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "%sからのRADIUS応答が誤ったポートから送られてきました: %d" -#: libpq/auth.c:3180 +#: libpq/auth.c:3178 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "%sからのRADIUS応答が短すぎます: %d" -#: libpq/auth.c:3187 +#: libpq/auth.c:3185 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "%sからのRADIUS応答が間違った長さを保持しています: %d(実際の長さは%d)" -#: libpq/auth.c:3195 +#: libpq/auth.c:3193 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "%sからのRADIUS応答は異なるリクエストに対するものです: %d (%d であるはず)" @@ -15072,7 +15489,7 @@ msgstr "%sからのRADIUS応答が間違ったMD5シグネチャを保持して msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "%1$sからのRADIUS応答がユーザー\"%3$s\"にとって不正なコード(%2$d)を保持しています" -#: libpq/be-fsstubs.c:133 libpq/be-fsstubs.c:162 libpq/be-fsstubs.c:190 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:241 libpq/be-fsstubs.c:283 libpq/be-fsstubs.c:306 libpq/be-fsstubs.c:560 +#: libpq/be-fsstubs.c:133 libpq/be-fsstubs.c:162 libpq/be-fsstubs.c:190 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:241 libpq/be-fsstubs.c:283 libpq/be-fsstubs.c:306 libpq/be-fsstubs.c:565 #, c-format msgid "invalid large-object descriptor: %d" msgstr "ラージオブジェクト記述子が不正です: %d" @@ -15082,7 +15499,7 @@ msgstr "ラージオブジェクト記述子が不正です: %d" msgid "large object descriptor %d was not opened for reading" msgstr "ラージオブジェクト記述子 %d は読み込み用にオープンされていませんでした" -#: libpq/be-fsstubs.c:197 libpq/be-fsstubs.c:567 +#: libpq/be-fsstubs.c:197 libpq/be-fsstubs.c:572 #, c-format msgid "large object descriptor %d was not opened for writing" msgstr "ラージオブジェクト記述子%dは書き込み用に開かれていませんでした" @@ -15097,32 +15514,32 @@ msgstr "lo_lseekの結果がラージオブジェクト記述子の範囲%dを msgid "lo_tell result out of range for large-object descriptor %d" msgstr "lo_tellの結果がラージオブジェクト記述子の範囲%dを超えています" -#: libpq/be-fsstubs.c:439 +#: libpq/be-fsstubs.c:444 #, c-format msgid "could not open server file \"%s\": %m" msgstr "サーバーファイル\"%s\"をオープンできませんでした: %m" -#: libpq/be-fsstubs.c:462 +#: libpq/be-fsstubs.c:467 #, c-format msgid "could not read server file \"%s\": %m" msgstr "サーバーファイル\"%s\"を読み取れませんでした: %m" -#: libpq/be-fsstubs.c:521 +#: libpq/be-fsstubs.c:526 #, c-format msgid "could not create server file \"%s\": %m" msgstr "サーバーファイル\"%s\"を作成できませんでした: %m" -#: libpq/be-fsstubs.c:533 +#: libpq/be-fsstubs.c:538 #, c-format msgid "could not write server file \"%s\": %m" msgstr "サーバーファイル\"%s\"を書き出せませんでした: %m" -#: libpq/be-fsstubs.c:774 +#: libpq/be-fsstubs.c:779 #, c-format msgid "large object read request is too large" msgstr "ラージオブジェクトの読み込み要求が大きすぎます" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 +#: libpq/be-fsstubs.c:821 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "負の長さを指定することはできません" @@ -15157,805 +15574,840 @@ msgstr "秘密鍵ファイル\"%s\"はグループまたは全員からアクセ msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root." msgstr "ファイルはデータベースユーザーの所有の場合は u=rw (0600) かそれよりも低いパーミッション、root所有の場合は u=rw,g=r (0640) かそれよりも低いパーミッションである必要があります" -#: libpq/be-secure-gssapi.c:201 +#: libpq/be-secure-gssapi.c:202 msgid "GSSAPI wrap error" msgstr "GSSAPI名ラップエラー" -#: libpq/be-secure-gssapi.c:208 +#: libpq/be-secure-gssapi.c:209 #, c-format msgid "outgoing GSSAPI message would not use confidentiality" msgstr "送出されるGSSAPIメッセージに機密性が適用されません" -#: libpq/be-secure-gssapi.c:215 libpq/be-secure-gssapi.c:634 +#: libpq/be-secure-gssapi.c:216 libpq/be-secure-gssapi.c:637 #, c-format msgid "server tried to send oversize GSSAPI packet (%zu > %zu)" msgstr "サーバーは過大なサイズのGSSAPIパケットを送信しようとしました: (%zu > %zu)" -#: libpq/be-secure-gssapi.c:351 +#: libpq/be-secure-gssapi.c:352 #, c-format msgid "oversize GSSAPI packet sent by the client (%zu > %zu)" msgstr "過大なサイズのGSSAPIパケットがクライアントから送出されました: (%zu > %zu)" -#: libpq/be-secure-gssapi.c:389 +#: libpq/be-secure-gssapi.c:390 msgid "GSSAPI unwrap error" msgstr "GSSAPIアンラップエラー" -#: libpq/be-secure-gssapi.c:396 +#: libpq/be-secure-gssapi.c:397 #, c-format msgid "incoming GSSAPI message did not use confidentiality" msgstr "到着したGSSAPIメッセージには機密性が適用されていません" -#: libpq/be-secure-gssapi.c:575 +#: libpq/be-secure-gssapi.c:578 #, c-format msgid "oversize GSSAPI packet sent by the client (%zu > %d)" msgstr "過大なサイズのGSSAPIパケットがクライアントから送出されました: (%zu > %d)" -#: libpq/be-secure-gssapi.c:600 +#: libpq/be-secure-gssapi.c:603 msgid "could not accept GSSAPI security context" msgstr "GSSAPIセキュリティコンテキストを受け入れられませんでした" -#: libpq/be-secure-gssapi.c:701 +#: libpq/be-secure-gssapi.c:704 msgid "GSSAPI size check error" msgstr "GSSAPIサイズチェックエラー" -#: libpq/be-secure-openssl.c:131 +#: libpq/be-secure-openssl.c:118 #, c-format msgid "could not create SSL context: %s" msgstr "SSLコンテキストを作成できませんでした: %s" -#: libpq/be-secure-openssl.c:157 +#: libpq/be-secure-openssl.c:144 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "サーバー証明書ファイル\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:177 +#: libpq/be-secure-openssl.c:164 #, c-format msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "パスフレーズが要求されたため秘密鍵ファイル\"%s\"をリロードできませんでした" -#: libpq/be-secure-openssl.c:182 +#: libpq/be-secure-openssl.c:169 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "秘密鍵ファイル\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:191 +#: libpq/be-secure-openssl.c:178 #, c-format msgid "check of private key failed: %s" msgstr "秘密鍵の検査に失敗しました: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 +#: libpq/be-secure-openssl.c:191 libpq/be-secure-openssl.c:214 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "このビルドでは\"%s\"の\"%s\"への設定はサポートされていません" -#: libpq/be-secure-openssl.c:214 +#: libpq/be-secure-openssl.c:201 #, c-format msgid "could not set minimum SSL protocol version" msgstr "最小SSLプロトコルバージョンを設定できませんでした" -#: libpq/be-secure-openssl.c:237 +#: libpq/be-secure-openssl.c:224 #, c-format msgid "could not set maximum SSL protocol version" msgstr "最大SSLプロトコルバージョンを設定できませんでした" -#: libpq/be-secure-openssl.c:253 +#: libpq/be-secure-openssl.c:241 #, c-format msgid "could not set SSL protocol version range" msgstr "SSLプロトコルバージョンの範囲を設定できませんでした" -#: libpq/be-secure-openssl.c:254 +#: libpq/be-secure-openssl.c:242 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "\"%s\"は\"%s\"より大きくできません" -#: libpq/be-secure-openssl.c:296 +#: libpq/be-secure-openssl.c:295 +#, c-format +msgid "could not set the TLSv1.2 cipher list (no valid ciphers available)" +msgstr " TLSv1.2 の暗号方式リストが設定できませんでした (有効な暗号方式がありません)" + +#: libpq/be-secure-openssl.c:310 #, c-format -msgid "could not set the cipher list (no valid ciphers available)" -msgstr "暗号方式リストがセットできません (利用可能な暗号方式がありません)" +msgid "could not set the TLSv1.3 cipher suites (no valid ciphers available)" +msgstr " TLSv1.3 の暗号スイートが設定できませんでした (有効な暗号方式がありません)" -#: libpq/be-secure-openssl.c:316 +#: libpq/be-secure-openssl.c:331 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "ルート証明書ファイル\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:365 +#: libpq/be-secure-openssl.c:380 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "SSL証明失効リストファイル\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:373 +#: libpq/be-secure-openssl.c:388 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "SSL証明失効リストディレクトリ\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:381 +#: libpq/be-secure-openssl.c:396 #, c-format msgid "could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s" msgstr "SSL証明失効リストファイル\"%s\"またはディレクトリ\"%s\"をロードできませんでした: %s" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:454 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "SSL接続を初期化できませんでした: SSLコンテクストが準備できていません" -#: libpq/be-secure-openssl.c:453 +#: libpq/be-secure-openssl.c:468 #, c-format msgid "could not initialize SSL connection: %s" msgstr "SSL接続を初期化できませんでした: %s" -#: libpq/be-secure-openssl.c:461 +#: libpq/be-secure-openssl.c:476 #, c-format msgid "could not set SSL socket: %s" msgstr "SSLソケットを設定できませんでした: %s" -#: libpq/be-secure-openssl.c:517 +#: libpq/be-secure-openssl.c:532 #, c-format msgid "could not accept SSL connection: %m" msgstr "SSL接続を受け付けられませんでした: %m" -#: libpq/be-secure-openssl.c:521 libpq/be-secure-openssl.c:578 +#: libpq/be-secure-openssl.c:536 libpq/be-secure-openssl.c:593 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "SSL接続を受け付けられませんでした: EOFを検出しました" -#: libpq/be-secure-openssl.c:562 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "could not accept SSL connection: %s" msgstr "SSL接続を受け付けられませんでした: %s" -#: libpq/be-secure-openssl.c:566 +#: libpq/be-secure-openssl.c:581 #, c-format msgid "This may indicate that the client does not support any SSL protocol version between %s and %s." msgstr "このことは、クライアントがSSLプロトコルのバージョン%sから%sのいずれもサポートしていないことを示唆しているかもしれません。" -#: libpq/be-secure-openssl.c:583 libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:868 +#: libpq/be-secure-openssl.c:598 libpq/be-secure-openssl.c:813 libpq/be-secure-openssl.c:883 #, c-format msgid "unrecognized SSL error code: %d" msgstr "認識できないSSLエラーコード: %d" -#: libpq/be-secure-openssl.c:611 +#: libpq/be-secure-openssl.c:626 #, c-format msgid "received SSL connection request with unexpected ALPN protocol" msgstr "想定外のALPNプロトコルによるSSL接続要求を受信しました" -#: libpq/be-secure-openssl.c:655 +#: libpq/be-secure-openssl.c:670 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "SSL 証明書のコモンネームに null が含まれています" -#: libpq/be-secure-openssl.c:701 +#: libpq/be-secure-openssl.c:716 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "SSL証明書の識別名の途中にnullが含まれています" -#: libpq/be-secure-openssl.c:787 libpq/be-secure-openssl.c:852 +#: libpq/be-secure-openssl.c:802 libpq/be-secure-openssl.c:867 #, c-format msgid "SSL error: %s" msgstr "SSLエラー: %s" -#: libpq/be-secure-openssl.c:1027 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "DHパラメータファイル\"%s\"をオープンできませんでした: %m" -#: libpq/be-secure-openssl.c:1039 +#: libpq/be-secure-openssl.c:1062 #, c-format msgid "could not load DH parameters file: %s" msgstr "DHパラメータをロードできませんでした: %s" -#: libpq/be-secure-openssl.c:1049 +#: libpq/be-secure-openssl.c:1072 #, c-format msgid "invalid DH parameters: %s" msgstr "不正なDHパラメータです: %s" -#: libpq/be-secure-openssl.c:1058 +#: libpq/be-secure-openssl.c:1081 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "不正なDHパラメータ: pは素数ではありません" -#: libpq/be-secure-openssl.c:1067 +#: libpq/be-secure-openssl.c:1090 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "不正なDHパラメータ: 適切な生成器も安全な素数もありません" -#: libpq/be-secure-openssl.c:1203 +#: libpq/be-secure-openssl.c:1226 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "クライアント証明書の検証に深さ%dで失敗しました: %s。" -#: libpq/be-secure-openssl.c:1240 +#: libpq/be-secure-openssl.c:1263 #, c-format msgid "Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"." msgstr "失敗した証明書の情報(未検証): サブジェクト \"%s\", シリアル番号 %s, 発行者 \"%s\"。" -#: libpq/be-secure-openssl.c:1241 +#: libpq/be-secure-openssl.c:1264 msgid "unknown" msgstr "不明" -#: libpq/be-secure-openssl.c:1378 +#: libpq/be-secure-openssl.c:1401 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: DHパラメータをロードできませんでした" -#: libpq/be-secure-openssl.c:1386 +#: libpq/be-secure-openssl.c:1409 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: DHパラメータを設定できませんでした: %s" -#: libpq/be-secure-openssl.c:1413 +#: libpq/be-secure-openssl.c:1439 #, c-format -msgid "ECDH: unrecognized curve name: %s" -msgstr "ECDH: 認識できない曲線名: %s" +msgid "failed to set group names specified in ssl_groups: %s" +msgstr "ssl_groupsで指定されたグループ名の設定に失敗しました: %s" -#: libpq/be-secure-openssl.c:1422 +#: libpq/be-secure-openssl.c:1441 +msgid "No valid groups found" +msgstr "有効なグループが見つかりませんでした" + +#: libpq/be-secure-openssl.c:1442 #, c-format -msgid "ECDH: could not create key" -msgstr "ECDH: キーを生成できませんでした" +msgid "Ensure that each group name is spelled correctly and supported by the installed version of OpenSSL" +msgstr "すべてのグループ名が正しく記述されおり、インストールされているバージョンのOpenSSLでサポートされていることを確認してください" -#: libpq/be-secure-openssl.c:1450 +#: libpq/be-secure-openssl.c:1488 msgid "no SSL error reported" msgstr "SSLエラーはありませんでした" -#: libpq/be-secure-openssl.c:1467 +#: libpq/be-secure-openssl.c:1506 #, c-format msgid "SSL error code %lu" msgstr "SSLエラーコード: %lu" -#: libpq/be-secure-openssl.c:1624 +#: libpq/be-secure-openssl.c:1663 #, c-format msgid "could not create BIO" msgstr "BIOを作成できませんでした" -#: libpq/be-secure-openssl.c:1634 +#: libpq/be-secure-openssl.c:1673 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "ASN1_OBJECTオブジェクトのNIDを取得できませんでした" -#: libpq/be-secure-openssl.c:1642 +#: libpq/be-secure-openssl.c:1681 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "NID %dをASN1_OBJECT構造体へ変換できませんでした" -#: libpq/crypt.c:48 +#: libpq/crypt.c:50 #, c-format msgid "Role \"%s\" does not exist." msgstr "ロール\"%s\"は存在しません。" -#: libpq/crypt.c:58 +#: libpq/crypt.c:60 #, c-format msgid "User \"%s\" has no password assigned." msgstr "ユーザー\"%s\"はパスワードが設定されていません。" -#: libpq/crypt.c:76 +#: libpq/crypt.c:78 #, c-format msgid "User \"%s\" has an expired password." msgstr "ユーザー\"%s\"のパスワードは期限切れです。" -#: libpq/crypt.c:182 +#: libpq/crypt.c:174 #, c-format -msgid "User \"%s\" has a password that cannot be used with MD5 authentication." -msgstr "ユーザー\"%s\"のパスワードはMD5認証で使用不能です。" +msgid "encrypted password is too long" +msgstr "暗号化されたパスワードが長すぎます" -#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 +#: libpq/crypt.c:175 #, c-format -msgid "Password does not match for user \"%s\"." -msgstr "ユーザー\"%s\"のパスワードが合致しません。" +msgid "Encrypted passwords must be no longer than %d bytes." +msgstr "暗号化されたパスワードは%dバイト以下でなければなりません。" -#: libpq/crypt.c:284 +#: libpq/crypt.c:183 #, c-format -msgid "Password of user \"%s\" is in unrecognized format." -msgstr "ユーザー\"%s\"のパスワードは識別不能な形式です。" +msgid "setting an MD5-encrypted password" +msgstr "MD5暗号化パスワードを設定しています" -#: libpq/hba.c:327 +#: libpq/crypt.c:184 #, c-format -msgid "invalid regular expression \"%s\": %s" -msgstr "不正な正規表現\"%s\": %s" +msgid "MD5 password support is deprecated and will be removed in a future release of PostgreSQL." +msgstr "MD5パスワードは非推奨であり、PostgreSQLの将来のリリースでは廃止される予定です。" -#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 -#: libpq/hba.c:1799 libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 tsearch/ts_locale.c:241 +#: libpq/crypt.c:185 #, c-format -msgid "line %d of configuration file \"%s\"" -msgstr "設定ファイル \"%2$s\" の %1$d 行目" +msgid "Refer to the PostgreSQL documentation for details about migrating to another password type." +msgstr "他のパスワードタイプへの移行の詳細についてはPostgreSQL文書を参照してください。" + +#: libpq/crypt.c:216 +#, c-format +msgid "User \"%s\" has a password that cannot be used with MD5 authentication." +msgstr "ユーザー\"%s\"のパスワードはMD5認証で使用不能です。" + +#: libpq/crypt.c:237 libpq/crypt.c:279 libpq/crypt.c:299 +#, c-format +msgid "Password does not match for user \"%s\"." +msgstr "ユーザー\"%s\"のパスワードが合致しません。" + +#: libpq/crypt.c:318 +#, c-format +msgid "Password of user \"%s\" is in unrecognized format." +msgstr "ユーザー\"%s\"のパスワードは識別不能な形式です。" + +#: libpq/hba.c:329 +#, c-format +msgid "invalid regular expression \"%s\": %s" +msgstr "不正な正規表現\"%s\": %s" -#: libpq/hba.c:457 +#: libpq/hba.c:459 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "存在しない認証設定ファイル\"%s\"をスキップします" -#: libpq/hba.c:609 +#: libpq/hba.c:611 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "ファイル\"%s\"をオープンできませんでした: 入れ子の深さが上限を超えています" -#: libpq/hba.c:1216 +#: libpq/hba.c:1222 #, c-format msgid "error enumerating network interfaces: %m" msgstr "ネットワークインターフェース列挙中のエラー: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1243 +#: libpq/hba.c:1249 #, c-format msgid "authentication option \"%s\" is only valid for authentication methods %s" msgstr "認証オプション\"%s\"は認証方式%sでのみ有効です" -#: libpq/hba.c:1263 +#: libpq/hba.c:1269 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "認証方式\"%s\"の場合は引数\"%s\"がセットされなければなりません" -#: libpq/hba.c:1287 +#: libpq/hba.c:1293 #, c-format msgid "missing entry at end of line" msgstr "行末の要素が足りません" -#: libpq/hba.c:1300 +#: libpq/hba.c:1306 #, c-format msgid "multiple values in ident field" msgstr "identヂールド内の複数の値" -#: libpq/hba.c:1352 +#: libpq/hba.c:1358 #, c-format msgid "multiple values specified for connection type" msgstr "接続タイプで複数の値が指定されました" -#: libpq/hba.c:1353 +#: libpq/hba.c:1359 #, c-format msgid "Specify exactly one connection type per line." msgstr "1行に1つの接続タイプだけを指定してください" -#: libpq/hba.c:1380 +#: libpq/hba.c:1386 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "SSLが無効なため、hostssl行は照合できません" -#: libpq/hba.c:1381 +#: libpq/hba.c:1387 #, c-format msgid "Set \"ssl = on\" in postgresql.conf." msgstr "postgresql.confで\"ssl = on\"に設定してください。" -#: libpq/hba.c:1389 +#: libpq/hba.c:1395 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "このビルドではhostsslはサポートされていないため、hostssl行は照合できません" -#: libpq/hba.c:1401 +#: libpq/hba.c:1407 #, c-format msgid "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "このビルドでは GSSAPI をサポートしていないため hostgssenc レコードは照合できません" -#: libpq/hba.c:1421 +#: libpq/hba.c:1427 #, c-format msgid "invalid connection type \"%s\"" msgstr "接続オプションタイプ \"%s\" は不正です" -#: libpq/hba.c:1435 +#: libpq/hba.c:1441 #, c-format msgid "end-of-line before database specification" msgstr "データベース指定の前に行末を検出しました" -#: libpq/hba.c:1460 +#: libpq/hba.c:1466 #, c-format msgid "end-of-line before role specification" msgstr "ロール指定の前に行末を検出しました" -#: libpq/hba.c:1487 +#: libpq/hba.c:1493 #, c-format msgid "end-of-line before IP address specification" msgstr "IP アドレス指定の前に行末を検出しました" -#: libpq/hba.c:1498 +#: libpq/hba.c:1504 #, c-format msgid "multiple values specified for host address" msgstr "ホストアドレスで複数の値が指定されました" -#: libpq/hba.c:1499 +#: libpq/hba.c:1505 #, c-format msgid "Specify one address range per line." msgstr "1行に1つのアドレス範囲を指定してください" -#: libpq/hba.c:1557 +#: libpq/hba.c:1563 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "不正なIPアドレス\"%s\": %s" -#: libpq/hba.c:1577 +#: libpq/hba.c:1583 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "ホスト名とCIDRマスクを両方指定するのは不正です: \"%s\"" -#: libpq/hba.c:1591 +#: libpq/hba.c:1597 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "IPアドレス\"%s\"内の CIDR マスクが不正です" -#: libpq/hba.c:1611 +#: libpq/hba.c:1617 #, c-format msgid "end-of-line before netmask specification" msgstr "ネットマスク指定の前に行末を検出しました" -#: libpq/hba.c:1612 +#: libpq/hba.c:1618 #, c-format msgid "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "CIDR記法でアドレス範囲を指定してするか、ネットマスクを分けて指定してください。" -#: libpq/hba.c:1623 +#: libpq/hba.c:1629 #, c-format msgid "multiple values specified for netmask" msgstr "ネットマスクで複数の値が指定されました" -#: libpq/hba.c:1637 +#: libpq/hba.c:1643 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "不正なIPマスク\"%s\": %s" -#: libpq/hba.c:1657 +#: libpq/hba.c:1663 #, c-format msgid "IP address and mask do not match" msgstr "IPアドレスとマスクが一致しません" -#: libpq/hba.c:1673 +#: libpq/hba.c:1679 #, c-format msgid "end-of-line before authentication method" msgstr "認証方式指定の前に行末を検出しました" -#: libpq/hba.c:1684 +#: libpq/hba.c:1690 #, c-format msgid "multiple values specified for authentication type" msgstr "認証タイプで複数の値が指定されました" -#: libpq/hba.c:1685 +#: libpq/hba.c:1691 #, c-format msgid "Specify exactly one authentication type per line." msgstr "認証タイプは1行に1つだけ指定してください。" -#: libpq/hba.c:1750 +#: libpq/hba.c:1758 #, c-format msgid "invalid authentication method \"%s\"" msgstr "不正な認証方式\"%s\"" -#: libpq/hba.c:1763 +#: libpq/hba.c:1771 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "不正な認証方式\"%s\": このビルドではサポートされていません" -#: libpq/hba.c:1786 +#: libpq/hba.c:1794 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "ローカルソケットではgssapi認証はサポートしていません" -#: libpq/hba.c:1798 +#: libpq/hba.c:1806 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "peer認証はローカルソケットでのみサポートしています" -#: libpq/hba.c:1816 +#: libpq/hba.c:1824 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "hostssl接続では証明書認証のみをサポートしています" -#: libpq/hba.c:1866 +#: libpq/hba.c:1874 #, c-format msgid "authentication option not in name=value format: %s" msgstr "認証オプションが 名前=値 形式になっていません: %s" -#: libpq/hba.c:1910 +#: libpq/hba.c:1918 #, c-format -msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" -msgstr "ldapbasedn、 ldapbinddn、ldapbindpasswd、ldapsearchattribute、, ldapsearchfilter またはldapurlは、ldapprefixと同時には指定できません" +msgid "cannot mix options for simple bind and search+bind modes" +msgstr "単純バインドモードと検索+バインドモードのオプションを混在させることはできません" -#: libpq/hba.c:1921 +#: libpq/hba.c:1929 #, c-format msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "\"ldap\"認証方式の場合は引数 \"ldapbasedn\"、\"ldapprefix\"、\"ldapsuffix\"のいずれかを指定してください" -#: libpq/hba.c:1937 +#: libpq/hba.c:1945 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "ldapsearchattribute、ldapsearchfilter と同時には指定できません" -#: libpq/hba.c:1954 +#: libpq/hba.c:1962 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "RADIUSサーバーのリストは空にはできません" -#: libpq/hba.c:1965 +#: libpq/hba.c:1973 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "RADIUSシークレットのリストは空にはできません" -#: libpq/hba.c:1982 +#: libpq/hba.c:1990 #, c-format msgid "the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "RADIUSシークレットの数(%d)は1またはRADIUSサーバーの数(%d)と同じである必要があります" -#: libpq/hba.c:1998 +#: libpq/hba.c:2006 #, c-format msgid "the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "RADIUSポートの数(%d)は1またはRADIUSサーバーの数(%d)と同じである必要があります" -#: libpq/hba.c:2014 +#: libpq/hba.c:2022 #, c-format msgid "the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "RADIUS識別子の数(%d)は1またはRADIUSサーバーの数(%d)と同じである必要があります" +#. translator: strings are replaced with hba options +#: libpq/hba.c:2067 +#, c-format +msgid "%s cannot be used in combination with %s" +msgstr "%s は %s と同時に使用できません" + # -#: libpq/hba.c:2066 -msgid "ident, peer, gssapi, sspi, and cert" -msgstr "ident、peer、gssapi、sspiおよびcert" +#: libpq/hba.c:2105 +msgid "ident, peer, gssapi, sspi, cert, and oauth" +msgstr "ident、peer、gssapi、sspi、cert および oauth" -#: libpq/hba.c:2075 +#: libpq/hba.c:2114 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "クライアント証明書は\"hostssl\"の行でのみ設定できます" -#: libpq/hba.c:2092 +#: libpq/hba.c:2131 #, c-format msgid "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "\"cert\"認証使用時はclientcertは\"verify-full\"にしか設定できません" -#: libpq/hba.c:2105 +#: libpq/hba.c:2144 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "clientcertの値が不正です: \"%s\"" -#: libpq/hba.c:2117 +#: libpq/hba.c:2156 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "クライアント名は\"hostssl\"の行でのみ設定できます" -#: libpq/hba.c:2136 +#: libpq/hba.c:2175 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "clientnameの値が不正です: \"%s\"" -#: libpq/hba.c:2169 +#: libpq/hba.c:2208 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "LDAP URL\"%s\"をパースできませんでした: %s" -#: libpq/hba.c:2180 +#: libpq/hba.c:2219 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "非サポートのLDAP URLコード: %s" -#: libpq/hba.c:2204 +#: libpq/hba.c:2243 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "このプラットフォームではLDAP URLをサポートしていません。" -#: libpq/hba.c:2222 +#: libpq/hba.c:2261 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "不正な ldapscheme の値: \"%s\"" -#: libpq/hba.c:2240 +#: libpq/hba.c:2279 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "不正なLDAPポート番号です: \"%s\"" # -#: libpq/hba.c:2286 libpq/hba.c:2293 +#: libpq/hba.c:2325 libpq/hba.c:2332 msgid "gssapi and sspi" msgstr "gssapiおよびsspi" -#: libpq/hba.c:2302 libpq/hba.c:2311 +#: libpq/hba.c:2341 libpq/hba.c:2350 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2333 +#: libpq/hba.c:2372 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "RADIUSサーバーのリスト\"%s\"のパースに失敗しました" -#: libpq/hba.c:2381 +#: libpq/hba.c:2420 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "RADIUSポートのリスト\"%s\"のパースに失敗しました" -#: libpq/hba.c:2395 +#: libpq/hba.c:2434 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "不正なRADIUSポート番号: \"%s\"" -#: libpq/hba.c:2417 +#: libpq/hba.c:2456 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "RADIUSシークレットのリスト\"%s\"のパースに失敗しました" -#: libpq/hba.c:2439 +#: libpq/hba.c:2478 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "RADIUS識別子のリスト\"%s\"のパースに失敗しました" -#: libpq/hba.c:2453 +#: libpq/hba.c:2515 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "認証オプション名を認識できません: \"%s\"" -#: libpq/hba.c:2645 +#: libpq/hba.c:2707 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "設定ファイル\"%s\"には何も含まれていません" -#: libpq/hba.c:2798 +#: libpq/hba.c:2860 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "正規表現\"%s\"で照合に失敗しました: %s" -#: libpq/hba.c:2822 +#: libpq/hba.c:2884 #, c-format msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"" msgstr "正規表現\"%s\"には\"%s\"における後方参照が要求する副表現が含まれていません" -#: libpq/hba.c:2925 +#: libpq/hba.c:2987 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "与えられたユーザー名 (%s) と認証されたユーザー名 (%s) が一致しません" -#: libpq/hba.c:2945 +#: libpq/hba.c:3007 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "\"%3$s\"として認証されたユーザー\"%2$s\"はユーザーマップ\"%1$s\"に一致しません" -#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#: libpq/pqcomm.c:212 libpq/pqcomm.c:220 libpq/pqcomm.c:251 libpq/pqcomm.c:260 libpq/pqcomm.c:1652 libpq/pqcomm.c:1697 libpq/pqcomm.c:1737 libpq/pqcomm.c:1781 libpq/pqcomm.c:1820 libpq/pqcomm.c:1859 libpq/pqcomm.c:1895 libpq/pqcomm.c:1934 #, c-format msgid "%s(%s) failed: %m" msgstr "%s(%s)が失敗しました: %m" -#: libpq/pqcomm.c:296 +#: libpq/pqcomm.c:297 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "ソケットを非ブロッキングモードに設定できませんでした: %m" -#: libpq/pqcomm.c:456 +#: libpq/pqcomm.c:457 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Unixドメインソケットのパス\"%s\"が長すぎます(最大 %d バイト)" -#: libpq/pqcomm.c:476 +#: libpq/pqcomm.c:477 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "ホスト名\"%s\"、サービス\"%s\"をアドレスに変換できませんでした: %s" -#: libpq/pqcomm.c:480 +#: libpq/pqcomm.c:481 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "サービス\"%s\"をアドレスに変換できませんでした: %s" -#: libpq/pqcomm.c:502 +#: libpq/pqcomm.c:503 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "要求されたアドレスを全てバインドできませんでした: MAXLISTEN (%d)を超えています" -#: libpq/pqcomm.c:511 +#: libpq/pqcomm.c:512 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:514 +#: libpq/pqcomm.c:515 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:517 +#: libpq/pqcomm.c:518 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:521 +#: libpq/pqcomm.c:522 #, c-format msgid "unrecognized address family %d" msgstr "アドレスファミリ %d を認識できません" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:545 +#: libpq/pqcomm.c:546 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "アドレス\"%s\"に対する%sソケットの作成に失敗しました: %m" -#. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 +#. translator: third %s is IPv4 or IPv6 +#. translator: third %s is IPv6 +#: libpq/pqcomm.c:575 libpq/pqcomm.c:593 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%3$sアドレス%4$sに対する%1$s(%2$s)が失敗しました: %5$m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:615 +#: libpq/pqcomm.c:616 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "%sアドレス\"%s\"のbindに失敗しました: %m" -#: libpq/pqcomm.c:619 +#: libpq/pqcomm.c:620 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "すでに他のpostmasterがポート%dで稼動していませんか?" -#: libpq/pqcomm.c:621 +#: libpq/pqcomm.c:622 #, c-format msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry." msgstr "すでに他にpostmasterがポート%dで稼動していませんか? 稼動していなければ数秒待ってから再試行してください。" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:650 +#: libpq/pqcomm.c:651 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "%sアドレス\"%s\"のlistenに失敗しました: %m" -#: libpq/pqcomm.c:658 +#: libpq/pqcomm.c:659 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "Unixソケット\"%s\"で待ち受けています" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:663 +#: libpq/pqcomm.c:664 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "%sアドレス\"%s\"、ポート%dで待ち受けています" -#: libpq/pqcomm.c:753 +#: libpq/pqcomm.c:754 #, c-format msgid "group \"%s\" does not exist" msgstr "グループ\"%s\"は存在しません" -#: libpq/pqcomm.c:763 +#: libpq/pqcomm.c:764 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "ファイル\"%s\"のグループを設定できませんでした: %m" -#: libpq/pqcomm.c:774 +#: libpq/pqcomm.c:775 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "ファイル\"%s\"の権限を設定できませんでした: %m" -#: libpq/pqcomm.c:803 +#: libpq/pqcomm.c:804 #, c-format msgid "could not accept new connection: %m" msgstr "新しい接続を受け付けることができませんでした: %m" -#: libpq/pqcomm.c:885 +#: libpq/pqcomm.c:886 #, c-format msgid "there is no client connection" msgstr "クライアント接続がありません" -#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 +#: libpq/pqcomm.c:942 libpq/pqcomm.c:1043 #, c-format msgid "could not receive data from client: %m" msgstr "クライアントからデータを受信できませんでした: %m" -#: libpq/pqcomm.c:1149 tcop/postgres.c:4446 +#: libpq/pqcomm.c:1151 tcop/postgres.c:4505 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "プロトコルの同期が失われたためコネクションを終了します" -#: libpq/pqcomm.c:1215 +#: libpq/pqcomm.c:1217 #, c-format msgid "unexpected EOF within message length word" msgstr "メッセージ長ワード内のEOFは想定外です" -#: libpq/pqcomm.c:1225 +#: libpq/pqcomm.c:1227 #, c-format msgid "invalid message length" msgstr "メッセージ長が不正です" -#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 +#: libpq/pqcomm.c:1249 libpq/pqcomm.c:1262 #, c-format msgid "incomplete message from client" msgstr "クライアントからのメッセージが不完全です" -#: libpq/pqcomm.c:1401 +#: libpq/pqcomm.c:1405 #, c-format msgid "could not send data to client: %m" msgstr "クライアントにデータを送信できませんでした: %m" -#: libpq/pqcomm.c:1616 +#: libpq/pqcomm.c:1620 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s)が失敗しました: エラーコード %d" -#: libpq/pqcomm.c:1705 +#: libpq/pqcomm.c:1709 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "キープアライブのアイドル時間の設定はサポートされていません" -#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 +#: libpq/pqcomm.c:1793 libpq/pqcomm.c:1868 libpq/pqcomm.c:1943 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s)はサポートされていません" @@ -15965,7 +16417,7 @@ msgstr "%s(%s)はサポートされていません" msgid "no data left in message" msgstr "メッセージ内にデータが残っていません" -#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 utils/adt/rowtypes.c:613 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 utils/adt/array_userfuncs.c:873 utils/adt/arrayfuncs.c:1481 utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "メッセージ内に残るデータが不十分です" @@ -15980,12 +16432,12 @@ msgstr "メッセージ内の文字列が不正です" msgid "invalid message format" msgstr "メッセージの書式が不正です" -#: main/main.c:234 +#: main/main.c:298 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: WSAStartupが失敗しました: %d\n" -#: main/main.c:322 +#: main/main.c:386 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -15994,7 +16446,7 @@ msgstr "" "%sはPostgreSQLサーバーです\n" "\n" -#: main/main.c:323 +#: main/main.c:387 #, c-format msgid "" "Usage:\n" @@ -16005,107 +16457,107 @@ msgstr "" " %s [オプション]...\n" "\n" -#: main/main.c:324 +#: main/main.c:388 #, c-format msgid "Options:\n" msgstr "オプション:\n" -#: main/main.c:325 +#: main/main.c:389 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS 共有バッファの数\n" -#: main/main.c:326 +#: main/main.c:390 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c NAME=VALUE 実行時パラメータの設定\n" -#: main/main.c:327 +#: main/main.c:391 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C NAME 実行時パラメータの値を表示し、終了\n" -#: main/main.c:328 +#: main/main.c:392 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 デバッグレベル\n" -#: main/main.c:329 +#: main/main.c:393 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR データベースディレクトリ\n" -#: main/main.c:330 +#: main/main.c:394 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e ヨーロッパ式の日付フォーマットでの入力(DMY)\n" -#: main/main.c:331 +#: main/main.c:395 #, c-format msgid " -F turn fsync off\n" msgstr " -F fsyncを無効にする\n" -#: main/main.c:332 +#: main/main.c:396 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h HOSTNAME 接続を待ち受けるホスト名またはIPアドレス\n" -#: main/main.c:333 +#: main/main.c:397 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr " -i TCP/IP接続を有効にする (非推奨)\n" -#: main/main.c:334 +#: main/main.c:398 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k DIRECTORY Unixドメインソケットの場所\n" -#: main/main.c:336 +#: main/main.c:400 #, c-format msgid " -l enable SSL connections\n" msgstr " -l SSL接続を有効にする\n" -#: main/main.c:338 +#: main/main.c:402 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N MAX-CONNECT 許容する最大接続数\n" -#: main/main.c:339 +#: main/main.c:403 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p PORT 接続を待ち受けるポート番号\n" -#: main/main.c:340 +#: main/main.c:404 #, c-format msgid " -s show statistics after each query\n" msgstr " -s 各問い合わせの後に統計情報を表示\n" -#: main/main.c:341 +#: main/main.c:405 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S WORK-MEM ソート用のメモリ量 (KB単位)\n" -#: main/main.c:342 +#: main/main.c:406 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示し、終了\n" -#: main/main.c:343 +#: main/main.c:407 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --NAME=VALUE 実行時パラメータを設定\n" -#: main/main.c:344 +#: main/main.c:408 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config 設定パラメータの説明を出力し、終了\n" -#: main/main.c:345 +#: main/main.c:409 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示し、終了\n" -#: main/main.c:347 +#: main/main.c:411 #, c-format msgid "" "\n" @@ -16114,39 +16566,39 @@ msgstr "" "\n" "開発者向けオプション:\n" -#: main/main.c:348 +#: main/main.c:412 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h いくつかのプランタイプを禁止\n" -#: main/main.c:349 +#: main/main.c:413 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O システムテーブル構造の変更を許可\n" -#: main/main.c:350 +#: main/main.c:414 #, c-format msgid " -P disable system indexes\n" msgstr " -P システムインデックスを無効にする\n" -#: main/main.c:351 +#: main/main.c:415 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex 各問い合わせの後に時間情報を表示\n" -#: main/main.c:352 +#: main/main.c:416 #, c-format msgid " -T send SIGABRT to all backend processes if one dies\n" msgstr "" " -T ひとつのバックエンドプロセスが異常停止した時に全ての\n" " バックエンドプロセスにSIGABRTを送信\n" -#: main/main.c:353 +#: main/main.c:417 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr " -W NUM デバッガをアタッチできるようにNUM秒待機\n" -#: main/main.c:355 +#: main/main.c:419 #, c-format msgid "" "\n" @@ -16155,39 +16607,39 @@ msgstr "" "\n" "シングルユーザーモード用のオプション:\n" -#: main/main.c:356 +#: main/main.c:420 #, c-format msgid " --single selects single-user mode (must be first argument)\n" msgstr "" " --single シングルユーザーモードを選択(最初の引数でなければ\n" " なりません)\n" -#: main/main.c:357 +#: main/main.c:421 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAME データベース名 (デフォルトはユーザー名)\n" -#: main/main.c:358 +#: main/main.c:422 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 デバッグレベルを上書き\n" -#: main/main.c:359 +#: main/main.c:423 #, c-format msgid " -E echo statement before execution\n" msgstr " -E 実行前に文を表示\n" -#: main/main.c:360 +#: main/main.c:424 #, c-format msgid " -j do not use newline as interactive query delimiter\n" msgstr " -j 対話式問い合わせの区切りとして改行を使用しない\n" -#: main/main.c:361 main/main.c:367 +#: main/main.c:425 main/main.c:431 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r FILENAME 標準出力と標準エラー出力を指定したファイルに出力\n" -#: main/main.c:363 +#: main/main.c:427 #, c-format msgid "" "\n" @@ -16196,22 +16648,22 @@ msgstr "" "\n" "初期起動用のオプション:\n" -#: main/main.c:364 +#: main/main.c:428 #, c-format msgid " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot 初期起動モードを選択 (最初の引数でなければなりません)\n" -#: main/main.c:365 +#: main/main.c:429 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr " --check チェックモードを選択 (最初の引数でなければなりません)\n" -#: main/main.c:366 +#: main/main.c:430 #, c-format msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n" msgstr " DBNAME データベース名 (初期起動モードでは必須の引数)\n" -#: main/main.c:369 +#: main/main.c:433 #, c-format msgid "" "\n" @@ -16227,12 +16679,12 @@ msgstr "" "\n" "不具合は<%s>まで報告してください。\n" -#: main/main.c:373 +#: main/main.c:437 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: main/main.c:384 +#: main/main.c:448 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -16245,12 +16697,12 @@ msgstr "" "する必要があります。適切なサーバーの起動方法に関する詳細はドキュメントを\n" "参照してください\n" -#: main/main.c:401 +#: main/main.c:465 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: 実ユーザーIDと実効ユーザーIDは一致しなければなりません\n" -#: main/main.c:408 +#: main/main.c:472 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -16274,12 +16726,12 @@ msgstr "拡張可能ノードタイプ\"%s\"はすでに存在します" msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "ExtensibleNodeMethods \"%s\"は登録されていません" -#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 +#: nodes/makefuncs.c:154 nodes/makefuncs.c:180 statistics/extended_stats.c:2306 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "リレーション\"%s\"は複合型を持っていません" -#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2567 parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 utils/fmgr/funcapi.c:669 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2602 parser/parse_coerce.c:2740 parser/parse_coerce.c:2787 parser/parse_expr.c:2118 parser/parse_func.c:710 parser/parse_oper.c:869 utils/adt/array_userfuncs.c:1950 utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "データ型%sの配列型がありませんでした" @@ -16294,763 +16746,784 @@ msgstr "パラメータを持つポータル\"%s\": %s" msgid "unnamed portal with parameters: %s" msgstr "パラメータを持つ無名ポータル: %s" -#: optimizer/path/joinrels.c:972 +#: optimizer/path/joinrels.c:973 #, c-format msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions" msgstr "FULL JOIN はマージ結合可能もしくはハッシュ結合可能な場合のみサポートされています" -#: optimizer/plan/createplan.c:7162 parser/parse_merge.c:203 rewrite/rewriteHandler.c:1695 +#: optimizer/plan/createplan.c:7250 parser/parse_merge.c:203 rewrite/rewriteHandler.c:1689 #, c-format msgid "cannot execute MERGE on relation \"%s\"" msgstr "リレーション\"%s\"に対してMERGEは実行できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1407 +#: optimizer/plan/initsplan.c:1755 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "外部結合のNULL可な側では%sを適用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 parser/analyze.c:3247 +#: optimizer/plan/planner.c:1459 parser/analyze.c:1900 parser/analyze.c:2159 parser/analyze.c:3480 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "UNION/INTERSECT/EXCEPTでは%sを使用できません" -#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4107 +#: optimizer/plan/planner.c:2202 optimizer/plan/planner.c:4045 #, c-format msgid "could not implement GROUP BY" msgstr "GROUP BY を実行できませんでした" -#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4108 optimizer/plan/planner.c:4789 optimizer/prep/prepunion.c:1320 +#: optimizer/plan/planner.c:2203 optimizer/plan/planner.c:4046 optimizer/plan/planner.c:4727 optimizer/prep/prepunion.c:1073 #, c-format msgid "Some of the datatypes only support hashing, while others only support sorting." msgstr "一部のデータ型がハッシュのみをサポートする一方で、別の型はソートのみをサポートしています。" -#: optimizer/plan/planner.c:4788 +#: optimizer/plan/planner.c:4726 #, c-format msgid "could not implement DISTINCT" msgstr "DISTINCTを実行できませんでした" -#: optimizer/plan/planner.c:6133 +#: optimizer/plan/planner.c:6188 #, c-format msgid "could not implement window PARTITION BY" msgstr "ウィンドウの PARTITION BY を実行できませんでした" -#: optimizer/plan/planner.c:6134 +#: optimizer/plan/planner.c:6189 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "ウィンドウ分割に使用する列は、ソート可能なデータ型でなければなりません。" -#: optimizer/plan/planner.c:6138 +#: optimizer/plan/planner.c:6193 #, c-format msgid "could not implement window ORDER BY" msgstr "ウィンドウの ORDER BY を実行できませんでした" -#: optimizer/plan/planner.c:6139 +#: optimizer/plan/planner.c:6194 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "ウィンドウの順序付けをする列は、ソート可能なデータ型でなければなりません。" -#: optimizer/prep/prepunion.c:467 +#: optimizer/prep/prepunion.c:440 #, c-format msgid "could not implement recursive UNION" msgstr "再帰UNIONを実行できませんでした" -#: optimizer/prep/prepunion.c:468 +#: optimizer/prep/prepunion.c:441 #, c-format msgid "All column datatypes must be hashable." msgstr "すべての列のデータ型はハッシュ可能でなければなりません。" -#. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1319 +#. translator: %s is INTERSECT or EXCEPT +#: optimizer/prep/prepunion.c:1071 #, c-format msgid "could not implement %s" msgstr "%sを実行できませんでした" -#: optimizer/util/clauses.c:4951 +#: optimizer/util/appendinfo.c:165 +#, c-format +msgid "attribute \"%s\" of relation \"%s\" does not match parent's type" +msgstr "リレーション\"%2$s\"の属性\"%1$s\"は親での型と一致していません" + +#: optimizer/util/appendinfo.c:170 +#, c-format +msgid "attribute \"%s\" of relation \"%s\" does not match parent's collation" +msgstr "リレーション\"%2$s\"の属性\"%1$s\"は親での照合順序と一致していません" + +#: optimizer/util/clauses.c:4966 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "SQL関数\"%s\"のインライン化処理中" -#: optimizer/util/plancat.c:152 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "リカバリ中は一時テーブルやUNLOGGEDテーブルにはアクセスできません" -#: optimizer/util/plancat.c:754 +#: optimizer/util/plancat.c:770 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "行全体に渡るユニークインデックスの推定指定はサポートされていません" -#: optimizer/util/plancat.c:771 +#: optimizer/util/plancat.c:787 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "ON CONFLICT句中の制約には関連付けられるインデックスがありません" -#: optimizer/util/plancat.c:821 +#: optimizer/util/plancat.c:837 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATEでの排除制約の使用はサポートされていません" -#: optimizer/util/plancat.c:926 +#: optimizer/util/plancat.c:954 #, c-format msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification" msgstr "ON CONFLICT 指定に合致するユニーク制約または排除制約がありません" -#: parser/analyze.c:824 parser/analyze.c:1550 +#: parser/analyze.c:954 parser/analyze.c:1679 #, c-format msgid "VALUES lists must all be the same length" msgstr "VALUESリストはすべて同じ長さでなければなりません" -#: parser/analyze.c:1027 +#: parser/analyze.c:1156 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERTに対象列よりも多くの式があります" -#: parser/analyze.c:1045 +#: parser/analyze.c:1174 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERTに式よりも多くの対象列があります" -#: parser/analyze.c:1049 +#: parser/analyze.c:1178 #, c-format msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?" msgstr "挿入ソースがINSERTが期待するのと同じ列数を含む行表現になっています。うっかり余計なカッコをつけたりしませんでしたか?" -#: parser/analyze.c:1357 parser/analyze.c:1744 +#: parser/analyze.c:1486 parser/analyze.c:1873 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "ここではSELECT ... INTOは許可されません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1673 parser/analyze.c:3479 +#: parser/analyze.c:1802 parser/analyze.c:3712 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%sをVALUESに使用できません" -#: parser/analyze.c:1911 +#: parser/analyze.c:2040 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "不正なUNION/INTERSECT/EXCEPT ORDER BY句です" -#: parser/analyze.c:1912 +#: parser/analyze.c:2041 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "式や関数ではなく、結果列の名前のみが使用できます。" -#: parser/analyze.c:1913 +#: parser/analyze.c:2042 #, c-format msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause." msgstr "式/関数をすべてのSELECTにつけてください。またはこのUNIONをFROM句に移動してください。" -#: parser/analyze.c:2019 +#: parser/analyze.c:2149 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "INTOはUNION/INTERSECT/EXCEPTの最初のSELECTでのみ使用できます" -#: parser/analyze.c:2091 +#: parser/analyze.c:2221 #, c-format msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level" msgstr "UNION/INTERSECT/EXCEPTの要素となる文では同一問い合わせレベルの他のリレーションを参照できません" -#: parser/analyze.c:2178 +#: parser/analyze.c:2308 #, c-format msgid "each %s query must have the same number of columns" msgstr "すべての%s問い合わせは同じ列数を返す必要があります" -#: parser/analyze.c:2535 +#: parser/analyze.c:2665 #, c-format msgid "SET target columns cannot be qualified with the relation name." msgstr "SETの対象列はリレーション名で修飾することはできません。" -#: parser/analyze.c:2589 +#. translator: %s is OLD or NEW +#: parser/analyze.c:2753 parser/analyze.c:2763 +#, c-format +msgid "%s cannot be specified multiple times" +msgstr "%s は複数回指定できません" + +#: parser/analyze.c:2775 parser/parse_relation.c:473 +#, c-format +msgid "table name \"%s\" specified more than once" +msgstr "テーブル名\"%s\"が複数指定されました" + +#: parser/analyze.c:2823 #, c-format msgid "RETURNING must have at least one column" msgstr "RETURNINGには少なくとも1つの列が必要です" -#: parser/analyze.c:2692 +#: parser/analyze.c:2925 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" msgstr[0] "代入元が%d個の列を返しました" -#: parser/analyze.c:2753 +#: parser/analyze.c:2986 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "変数\"%s\"は型%sですが、式は型%sでした" #. translator: %s is a SQL keyword -#: parser/analyze.c:2878 parser/analyze.c:2886 +#: parser/analyze.c:3111 parser/analyze.c:3119 #, c-format msgid "cannot specify both %s and %s" msgstr "%sと%sの両方を同時には指定できません" -#: parser/analyze.c:2906 +#: parser/analyze.c:3139 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR では WITH にデータを変更する文を含んではなりません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2914 +#: parser/analyze.c:3147 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %sはサポートされていません" -#: parser/analyze.c:2917 +#: parser/analyze.c:3150 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "保持可能カーソルは読み取り専用である必要があります。" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2925 +#: parser/analyze.c:3158 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %sはサポートされていません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2936 +#: parser/analyze.c:3169 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %sはが不正です" -#: parser/analyze.c:2939 +#: parser/analyze.c:3172 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "INSENSITIVEカーソルは読み取り専用である必要があります。" -#: parser/analyze.c:3033 +#: parser/analyze.c:3266 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "実体化ビューではWITH句にデータを変更する文を含んではなりません" -#: parser/analyze.c:3043 +#: parser/analyze.c:3276 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "実体化ビューでは一時テーブルやビューを使用してはいけません" -#: parser/analyze.c:3053 +#: parser/analyze.c:3286 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "実体化ビューは境界パラメータを用いて定義してはなりません" -#: parser/analyze.c:3065 +#: parser/analyze.c:3298 #, c-format msgid "materialized views cannot be unlogged" msgstr "実体化ビューをログ非取得にはできません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3254 +#: parser/analyze.c:3487 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "DISTINCT句では%sを使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3261 +#: parser/analyze.c:3494 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "GROUP BY句で%sを使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3268 +#: parser/analyze.c:3501 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "HAVING 句では%sを使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3275 +#: parser/analyze.c:3508 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "集約関数では%sは使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3282 +#: parser/analyze.c:3515 #, c-format msgid "%s is not allowed with window functions" msgstr "ウィンドウ関数では%sは使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3289 +#: parser/analyze.c:3522 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "ターゲットリストの中では%sを集合返却関数と一緒に使うことはできません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3388 +#: parser/analyze.c:3621 #, c-format msgid "%s must specify unqualified relation names" msgstr "%sでは非修飾のリレーション名を指定してください" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3452 +#: parser/analyze.c:3685 #, c-format msgid "%s cannot be applied to a join" msgstr "%sを結合に使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3461 +#: parser/analyze.c:3694 #, c-format msgid "%s cannot be applied to a function" msgstr "%sを関数に使用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3470 +#: parser/analyze.c:3703 #, c-format msgid "%s cannot be applied to a table function" msgstr "%sはテーブル関数には適用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3488 +#: parser/analyze.c:3721 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%sはWITH問い合わせには適用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3497 +#: parser/analyze.c:3730 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%sは名前付きタプルストアには適用できません" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3517 +#: parser/analyze.c:3750 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "%2$s句のリレーション\"%1$s\"はFROM句にありません" -#: parser/parse_agg.c:210 parser/parse_oper.c:215 +#: parser/parse_agg.c:215 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "型%sの順序演算子を特定できませんでした" -#: parser/parse_agg.c:212 +#: parser/parse_agg.c:217 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "DISTINCT 付きの集約関数は、入力がソート可能である必要があります。" -#: parser/parse_agg.c:270 +#: parser/parse_agg.c:275 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPINGの引数は32より少くなければなりません" -#: parser/parse_agg.c:373 +#: parser/parse_agg.c:378 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "JOIN条件で集約関数を使用できません" -#: parser/parse_agg.c:375 +#: parser/parse_agg.c:380 msgid "grouping operations are not allowed in JOIN conditions" msgstr "グルーピング演算はJOIN条件の中では使用できません" -#: parser/parse_agg.c:387 +#: parser/parse_agg.c:390 msgid "aggregate functions are not allowed in FROM clause of their own query level" msgstr "集約関数は自身の問い合わせレベルのFROM句の中では使用できません" -#: parser/parse_agg.c:389 +#: parser/parse_agg.c:392 msgid "grouping operations are not allowed in FROM clause of their own query level" msgstr "グルーピング演算は自身のクエリレベルのFROM句の中では使用できません" -#: parser/parse_agg.c:394 +#: parser/parse_agg.c:397 msgid "aggregate functions are not allowed in functions in FROM" msgstr "集約関数はFROM句内の関数では使用できません" -#: parser/parse_agg.c:396 +#: parser/parse_agg.c:399 msgid "grouping operations are not allowed in functions in FROM" msgstr "グルーピング演算はFROM句内の関数では使用できません" -#: parser/parse_agg.c:404 +#: parser/parse_agg.c:407 msgid "aggregate functions are not allowed in policy expressions" msgstr "集約関数はポリシ式では使用できません" -#: parser/parse_agg.c:406 +#: parser/parse_agg.c:409 msgid "grouping operations are not allowed in policy expressions" msgstr "グルーピング演算はポリシ式では使用できません" -#: parser/parse_agg.c:423 +#: parser/parse_agg.c:426 msgid "aggregate functions are not allowed in window RANGE" msgstr "集約関数はウィンドウRANGEの中では集約関数を使用できません" -#: parser/parse_agg.c:425 +#: parser/parse_agg.c:428 msgid "grouping operations are not allowed in window RANGE" msgstr "ウィンドウ定義のRANGE句の中ではグルーピング演算は使用できません" -#: parser/parse_agg.c:430 +#: parser/parse_agg.c:433 msgid "aggregate functions are not allowed in window ROWS" msgstr "ウィンドウ定義のROWS句では集約関数は使用できません" -#: parser/parse_agg.c:432 +#: parser/parse_agg.c:435 msgid "grouping operations are not allowed in window ROWS" msgstr "ウィンドウ定義のROWS句ではグルーピング演算は使用できません" -#: parser/parse_agg.c:437 +#: parser/parse_agg.c:440 msgid "aggregate functions are not allowed in window GROUPS" msgstr "ウィンドウ定義のGROUPS句では集約関数は使用できません" -#: parser/parse_agg.c:439 +#: parser/parse_agg.c:442 msgid "grouping operations are not allowed in window GROUPS" msgstr "ウィンドウ定義のGROUPS句ではグルーピング演算は使用できません" -#: parser/parse_agg.c:452 +#: parser/parse_agg.c:455 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "MERGE WHEN条件では集約関数を使用できません" -#: parser/parse_agg.c:454 +#: parser/parse_agg.c:457 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "MERGE WHEN条件ではグルーピング演算を使用できません" -#: parser/parse_agg.c:481 +#: parser/parse_agg.c:484 msgid "aggregate functions are not allowed in check constraints" msgstr "検査制約では集約関数を使用できません" -#: parser/parse_agg.c:483 +#: parser/parse_agg.c:486 msgid "grouping operations are not allowed in check constraints" msgstr "検査制約ではグルーピング演算を使用できません" -#: parser/parse_agg.c:490 +#: parser/parse_agg.c:493 msgid "aggregate functions are not allowed in DEFAULT expressions" msgstr "DEFAULT式では集約関数を使用できません" -#: parser/parse_agg.c:492 +#: parser/parse_agg.c:495 msgid "grouping operations are not allowed in DEFAULT expressions" msgstr "DEFAULT式ではグルーピング演算を使用できません" -#: parser/parse_agg.c:497 +#: parser/parse_agg.c:500 msgid "aggregate functions are not allowed in index expressions" msgstr "インデックス式では集約関数を使用できません" -#: parser/parse_agg.c:499 +#: parser/parse_agg.c:502 msgid "grouping operations are not allowed in index expressions" msgstr "インデックス式ではグルーピング演算を使用できません" -#: parser/parse_agg.c:504 +#: parser/parse_agg.c:507 msgid "aggregate functions are not allowed in index predicates" msgstr "インデックス述語では集約関数を使用できません" -#: parser/parse_agg.c:506 +#: parser/parse_agg.c:509 msgid "grouping operations are not allowed in index predicates" msgstr "インデックス述語ではグルーピング演算を使用できません" -#: parser/parse_agg.c:511 +#: parser/parse_agg.c:514 msgid "aggregate functions are not allowed in statistics expressions" msgstr "統計情報式では集約関数を使用できません" -#: parser/parse_agg.c:513 +#: parser/parse_agg.c:516 msgid "grouping operations are not allowed in statistics expressions" msgstr "統計情報式ではグルーピング演算使用できません" -#: parser/parse_agg.c:518 +#: parser/parse_agg.c:521 msgid "aggregate functions are not allowed in transform expressions" msgstr "変換式では集約関数を使用できません" -#: parser/parse_agg.c:520 +#: parser/parse_agg.c:523 msgid "grouping operations are not allowed in transform expressions" msgstr "変換式ではグルーピング演算を使用できません" -#: parser/parse_agg.c:525 +#: parser/parse_agg.c:528 msgid "aggregate functions are not allowed in EXECUTE parameters" msgstr "EXECUTEのパラメータでは集約関数を使用できません" -#: parser/parse_agg.c:527 +#: parser/parse_agg.c:530 msgid "grouping operations are not allowed in EXECUTE parameters" msgstr "EXECUTEのパラメータではグルーピング演算を使用できません" -#: parser/parse_agg.c:532 +#: parser/parse_agg.c:535 msgid "aggregate functions are not allowed in trigger WHEN conditions" msgstr "トリガのWHEN条件では集約関数を使用できません" -#: parser/parse_agg.c:534 +#: parser/parse_agg.c:537 msgid "grouping operations are not allowed in trigger WHEN conditions" msgstr "トリガのWHEN条件ではグルーピング演算を使用できません" -#: parser/parse_agg.c:539 +#: parser/parse_agg.c:542 msgid "aggregate functions are not allowed in partition bound" msgstr "集約関数はパーティション境界では使用できません" -#: parser/parse_agg.c:541 +#: parser/parse_agg.c:544 msgid "grouping operations are not allowed in partition bound" msgstr "グルーピング演算はパーティション境界では使用できません" -#: parser/parse_agg.c:546 +#: parser/parse_agg.c:549 msgid "aggregate functions are not allowed in partition key expressions" msgstr "パーティションキー式では集約関数は使用できません" -#: parser/parse_agg.c:548 +#: parser/parse_agg.c:551 msgid "grouping operations are not allowed in partition key expressions" msgstr "パーティションキー式ではグルーピング演算は使用できません" -#: parser/parse_agg.c:554 +#: parser/parse_agg.c:557 msgid "aggregate functions are not allowed in column generation expressions" msgstr "集約関数はカラム生成式では使用できません" -#: parser/parse_agg.c:556 +#: parser/parse_agg.c:559 msgid "grouping operations are not allowed in column generation expressions" msgstr "グルーピング演算はカラム生成式では使用できません" -#: parser/parse_agg.c:562 +#: parser/parse_agg.c:565 msgid "aggregate functions are not allowed in CALL arguments" msgstr "CALLの引数では集約関数を使用できません" -#: parser/parse_agg.c:564 +#: parser/parse_agg.c:567 msgid "grouping operations are not allowed in CALL arguments" msgstr "CALLの引数ではグルーピング演算を使用できません" -#: parser/parse_agg.c:570 +#: parser/parse_agg.c:573 msgid "aggregate functions are not allowed in COPY FROM WHERE conditions" msgstr "集約関数は COPY FROM の WHERE 条件では使用できません" -#: parser/parse_agg.c:572 +#: parser/parse_agg.c:575 msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "グルーピング演算は COPY FROM の WHERE 条件の中では使用できません" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:599 parser/parse_clause.c:1962 +#: parser/parse_agg.c:602 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "%sでは集約関数を使用できません" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:602 +#: parser/parse_agg.c:605 #, c-format msgid "grouping operations are not allowed in %s" msgstr "%sではグルーピング演算を使用できません" -#: parser/parse_agg.c:703 +#: parser/parse_agg.c:706 #, c-format msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments" msgstr "アウタレベルの集約は直接引数に低位の変数を含むことができません" -#: parser/parse_agg.c:781 +#: parser/parse_agg.c:784 #, c-format msgid "aggregate function calls cannot contain set-returning function calls" msgstr "集合返却関数の呼び出しに集約関数の呼び出しを含むことはできません" -#: parser/parse_agg.c:782 parser/parse_expr.c:1762 parser/parse_expr.c:2245 parser/parse_func.c:885 +#: parser/parse_agg.c:785 parser/parse_expr.c:1760 parser/parse_expr.c:2251 parser/parse_func.c:885 #, c-format msgid "You might be able to move the set-returning function into a LATERAL FROM item." msgstr "この集合返却関数をLATERAL FROM項目に移動できるかもしれません。" -#: parser/parse_agg.c:787 +#: parser/parse_agg.c:790 #, c-format msgid "aggregate function calls cannot contain window function calls" msgstr "集約関数の呼び出しにウィンドウ関数の呼び出しを含むことはできません" -#: parser/parse_agg.c:866 +#: parser/parse_agg.c:869 msgid "window functions are not allowed in JOIN conditions" msgstr "JOIN条件ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:873 +#: parser/parse_agg.c:876 msgid "window functions are not allowed in functions in FROM" msgstr "FROM句内の関数ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:879 +#: parser/parse_agg.c:882 msgid "window functions are not allowed in policy expressions" msgstr "ポリシ式ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:892 +#: parser/parse_agg.c:895 msgid "window functions are not allowed in window definitions" msgstr "ウィンドウ定義ではウィンドウ関数は使用できません" -#: parser/parse_agg.c:903 +#: parser/parse_agg.c:906 msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "MERGE WHEN条件ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:928 +#: parser/parse_agg.c:931 msgid "window functions are not allowed in check constraints" msgstr "検査制約の中ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:932 +#: parser/parse_agg.c:935 msgid "window functions are not allowed in DEFAULT expressions" msgstr "DEFAULT式の中ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:935 +#: parser/parse_agg.c:938 msgid "window functions are not allowed in index expressions" msgstr "インデックス式ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:938 +#: parser/parse_agg.c:941 msgid "window functions are not allowed in statistics expressions" msgstr "統計情報式ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:941 +#: parser/parse_agg.c:944 msgid "window functions are not allowed in index predicates" msgstr "インデックス述語ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:944 +#: parser/parse_agg.c:947 msgid "window functions are not allowed in transform expressions" msgstr "変換式ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:947 +#: parser/parse_agg.c:950 msgid "window functions are not allowed in EXECUTE parameters" msgstr "EXECUTEパラメータではウィンドウ関数を使用できません" -#: parser/parse_agg.c:950 +#: parser/parse_agg.c:953 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "トリガのWHEN条件ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:953 +#: parser/parse_agg.c:956 msgid "window functions are not allowed in partition bound" msgstr "ウィンドウ関数はパーティション境界では使用できません" -#: parser/parse_agg.c:956 +#: parser/parse_agg.c:959 msgid "window functions are not allowed in partition key expressions" msgstr "パーティションキー式ではウィンドウ関数は使用できません" -#: parser/parse_agg.c:959 +#: parser/parse_agg.c:962 msgid "window functions are not allowed in CALL arguments" msgstr "CALLの引数ではウィンドウ関数は使用できません" -#: parser/parse_agg.c:962 +#: parser/parse_agg.c:965 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "ウィンドウ関数は COPY FROM の WHERE 条件では使用できません" -#: parser/parse_agg.c:965 +#: parser/parse_agg.c:968 msgid "window functions are not allowed in column generation expressions" msgstr "ウィンドウ関数はカラム生成式では使用できません" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:988 parser/parse_clause.c:1971 +#: parser/parse_agg.c:991 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "%sの中ではウィンドウ関数を使用できません" -#: parser/parse_agg.c:1022 parser/parse_clause.c:2804 +#: parser/parse_agg.c:1025 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "ウィンドウ\"%s\"は存在しません" -#: parser/parse_agg.c:1110 +#: parser/parse_agg.c:1115 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "グルーピングセットの数が多すぎます (最大4096)" -#: parser/parse_agg.c:1250 +#: parser/parse_agg.c:1276 #, c-format msgid "aggregate functions are not allowed in a recursive query's recursive term" msgstr "再帰問い合わせの再帰項では集約関数を使用できません" -#: parser/parse_agg.c:1443 +#: parser/parse_agg.c:1499 #, c-format msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function" msgstr "列\"%s.%s\"はGROUP BY句で指定するか、集約関数内で使用しなければなりません" -#: parser/parse_agg.c:1446 +#: parser/parse_agg.c:1502 #, c-format msgid "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "順序集合集約の直接引数はグルーピングされた列のみを使用しなければなりません。" -#: parser/parse_agg.c:1451 +#: parser/parse_agg.c:1507 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "外部問い合わせから副問い合わせがグループ化されていない列\"%s.%s\"を使用しています" -#: parser/parse_agg.c:1615 +#: parser/parse_agg.c:1672 #, c-format msgid "arguments to GROUPING must be grouping expressions of the associated query level" msgstr "GROUPINGの引数は関連するクエリレベルのグルーピング式でなければなりません" -#: parser/parse_clause.c:193 +#: parser/parse_clause.c:191 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "リレーション\"%s\"は更新文の対象にはなれません" -#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 +#: parser/parse_clause.c:567 parser/parse_clause.c:595 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "集合返却関数はFROMの最上位レベルにある必要があります" -#: parser/parse_clause.c:609 +#: parser/parse_clause.c:607 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "同じ関数に対して複数の列定義リストを持つことができません" -#: parser/parse_clause.c:642 +#: parser/parse_clause.c:640 #, c-format msgid "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "複数の関数を伴った ROWS FROM() は列定義リストを持つことができません" -#: parser/parse_clause.c:643 +#: parser/parse_clause.c:641 #, c-format msgid "Put a separate column definition list for each function inside ROWS FROM()." msgstr "ROWS FROM() 内のそれぞれの関数ごとに個別の列定義リストを付けてください。" -#: parser/parse_clause.c:649 +#: parser/parse_clause.c:647 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "複数の引数をもつUNNEST()は列定義リストを持つことができません" -#: parser/parse_clause.c:650 +#: parser/parse_clause.c:648 #, c-format msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one." msgstr "ROWS FROM() の中で個別に UNNEST() をコールして、列定義リストをそれぞれに付加してください。" -#: parser/parse_clause.c:657 +#: parser/parse_clause.c:655 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY は列定義リストがあるときは使えません" -#: parser/parse_clause.c:658 +#: parser/parse_clause.c:656 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "ROWS FROM() の中に列定義リストをおいてください。" -#: parser/parse_clause.c:762 +#: parser/parse_clause.c:760 parser/parse_jsontable.c:293 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "FOR ORDINALITY 列は一つまでです" -#: parser/parse_clause.c:823 +#: parser/parse_clause.c:821 #, c-format msgid "column name \"%s\" is not unique" msgstr "列名\"%s\"は一意ではありません" -#: parser/parse_clause.c:865 +#: parser/parse_clause.c:863 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "名前空間名\"%s\"は一意ではありません" -#: parser/parse_clause.c:875 +#: parser/parse_clause.c:873 #, c-format msgid "only one default namespace is allowed" msgstr "デフォルト名前空間は一つのみ指定可能です" -#: parser/parse_clause.c:935 +#: parser/parse_clause.c:933 #, c-format msgid "tablesample method %s does not exist" msgstr "テーブルサンプルメソッド%sは存在しません" -#: parser/parse_clause.c:957 +#: parser/parse_clause.c:955 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" msgstr[0] "テーブルサンプルメソッド%sは%d個の引数を必要とします、%d個ではありません" -#: parser/parse_clause.c:991 +#: parser/parse_clause.c:989 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "テーブルサンプルメソッド%sはREPEATABLEをサポートしていません" -#: parser/parse_clause.c:1144 +#: parser/parse_clause.c:1142 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "TABLESAMPLE句はテーブルおよび実体化ビューのみに適用可能です" -#: parser/parse_clause.c:1331 +#: parser/parse_clause.c:1329 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "USING句に列名\"%s\"が複数あります" -#: parser/parse_clause.c:1346 +#: parser/parse_clause.c:1344 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "左テーブルに列名\"%s\"が複数あります" -#: parser/parse_clause.c:1355 +#: parser/parse_clause.c:1353 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "USING句で指定した列\"%sが左テーブルに存在しません" -#: parser/parse_clause.c:1370 +#: parser/parse_clause.c:1368 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "右テーブルに列名\"%s\"が複数あります" -#: parser/parse_clause.c:1379 +#: parser/parse_clause.c:1377 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "USING句で指定した列\"%sが右テーブルに存在しません" @@ -17189,173 +17662,173 @@ msgstr "演算子\"%s\"は有効な順序付け演算子名ではありません msgid "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "順序付け演算子はB-Tree演算子族の\"<\"または\">\"要素でなければなりません。" -#: parser/parse_clause.c:3775 +#: parser/parse_clause.c:3778 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "offset PRECEDING/FOLLOWING を伴った RANGE は列型 %s に対してはサポートされません" -#: parser/parse_clause.c:3781 +#: parser/parse_clause.c:3784 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s and offset type %s" msgstr "offset PRECEDING/FOLLOWING を伴った RANGE は列型 %s とオフセット型 %s に対してはサポートされません" -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3787 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "オフセット値を適切な型にキャストしてください。" -#: parser/parse_clause.c:3789 +#: parser/parse_clause.c:3792 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for column type %s and offset type %s" msgstr "offset PRECEDING/FOLLOWING を伴った RANGE は列型 %s とオフセット型 %s に対して複数の解釈が可能になっています" -#: parser/parse_clause.c:3792 +#: parser/parse_clause.c:3795 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "オフセット値を意図した型そのものにキャストしてください。" -#: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3403 parser/parse_expr.c:3624 parser/parse_expr.c:4388 parser/parse_target.c:998 +#: parser/parse_coerce.c:1048 parser/parse_coerce.c:1086 parser/parse_coerce.c:1104 parser/parse_coerce.c:1119 parser/parse_expr.c:2152 parser/parse_expr.c:2770 parser/parse_expr.c:3421 parser/parse_expr.c:3650 parser/parse_target.c:1001 #, c-format msgid "cannot cast type %s to %s" msgstr "型%sから%sへの型変換ができません" -#: parser/parse_coerce.c:1091 +#: parser/parse_coerce.c:1089 #, c-format msgid "Input has too few columns." msgstr "入力列が少なすぎます。" -#: parser/parse_coerce.c:1109 +#: parser/parse_coerce.c:1107 #, c-format msgid "Cannot cast type %s to %s in column %d." msgstr "列%3$dで型%1$sから%2$sへの型変換ができません。" -#: parser/parse_coerce.c:1124 +#: parser/parse_coerce.c:1122 #, c-format msgid "Input has too many columns." msgstr "入力列が多すぎます。" #. translator: first %s is name of a SQL construct, eg WHERE #. translator: first %s is name of a SQL construct, eg LIMIT -#: parser/parse_coerce.c:1179 parser/parse_coerce.c:1227 +#: parser/parse_coerce.c:1177 parser/parse_coerce.c:1225 #, c-format msgid "argument of %s must be type %s, not type %s" msgstr "%1$sの引数は型%3$sではなく%2$s型でなければなりません" #. translator: %s is name of a SQL construct, eg WHERE #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_coerce.c:1190 parser/parse_coerce.c:1239 +#: parser/parse_coerce.c:1188 parser/parse_coerce.c:1237 #, c-format msgid "argument of %s must not return a set" msgstr "%sの引数は集合を返してはなりません" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1383 +#: parser/parse_coerce.c:1418 #, c-format msgid "%s types %s and %s cannot be matched" msgstr "%sの型%sと%sを一致させることができません" -#: parser/parse_coerce.c:1499 +#: parser/parse_coerce.c:1534 #, c-format msgid "argument types %s and %s cannot be matched" msgstr "引数の型%sと%sは合致させられません" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1551 +#: parser/parse_coerce.c:1586 #, c-format msgid "%s could not convert type %s to %s" msgstr "%sで型%sから%sへ変換できませんでした" -#: parser/parse_coerce.c:2154 parser/parse_coerce.c:2174 parser/parse_coerce.c:2194 parser/parse_coerce.c:2215 parser/parse_coerce.c:2270 parser/parse_coerce.c:2304 +#: parser/parse_coerce.c:2189 parser/parse_coerce.c:2209 parser/parse_coerce.c:2229 parser/parse_coerce.c:2250 parser/parse_coerce.c:2305 parser/parse_coerce.c:2339 #, c-format msgid "arguments declared \"%s\" are not all alike" msgstr "\"%s\"と宣言された引数が全て同じでありません" -#: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 utils/fmgr/funcapi.c:600 +#: parser/parse_coerce.c:2284 parser/parse_coerce.c:2397 utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "%sと宣言された引数が配列ではなく%s型です" -#: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 utils/fmgr/funcapi.c:614 +#: parser/parse_coerce.c:2317 parser/parse_coerce.c:2467 utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "%sと宣言された引数が範囲型ではなく型%sです" -#: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 +#: parser/parse_coerce.c:2351 parser/parse_coerce.c:2431 parser/parse_coerce.c:2564 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "%sと宣言された引数が複範囲型ではなく型%sです" -#: parser/parse_coerce.c:2353 +#: parser/parse_coerce.c:2388 #, c-format msgid "cannot determine element type of \"anyarray\" argument" msgstr "\"anyarray\"型の引数の要素型を決定できません" -#: parser/parse_coerce.c:2379 parser/parse_coerce.c:2410 parser/parse_coerce.c:2449 parser/parse_coerce.c:2515 +#: parser/parse_coerce.c:2414 parser/parse_coerce.c:2445 parser/parse_coerce.c:2484 parser/parse_coerce.c:2550 #, c-format msgid "argument declared %s is not consistent with argument declared %s" msgstr "%sと宣言された引数と%sと宣言された引数とで整合性がありません" -#: parser/parse_coerce.c:2474 +#: parser/parse_coerce.c:2509 #, c-format msgid "could not determine polymorphic type because input has type %s" msgstr "入力型が%sであったため多様型が特定できませんでした" -#: parser/parse_coerce.c:2488 +#: parser/parse_coerce.c:2523 #, c-format msgid "type matched to anynonarray is an array type: %s" msgstr "anynonarrayと照合されたは配列型です: %s" -#: parser/parse_coerce.c:2498 +#: parser/parse_coerce.c:2533 #, c-format msgid "type matched to anyenum is not an enum type: %s" msgstr "anyenumと照合された型は列挙型ではありません: %s" -#: parser/parse_coerce.c:2559 +#: parser/parse_coerce.c:2594 #, c-format msgid "arguments of anycompatible family cannot be cast to a common type" msgstr "anycompatible系の引数を共通の型にキャストできません" -#: parser/parse_coerce.c:2577 parser/parse_coerce.c:2598 parser/parse_coerce.c:2648 parser/parse_coerce.c:2653 parser/parse_coerce.c:2717 parser/parse_coerce.c:2729 +#: parser/parse_coerce.c:2612 parser/parse_coerce.c:2633 parser/parse_coerce.c:2683 parser/parse_coerce.c:2688 parser/parse_coerce.c:2752 parser/parse_coerce.c:2764 #, c-format msgid "could not determine polymorphic type %s because input has type %s" msgstr "入力型が%2$sであるため多様型%1$sが特定できませんでした" -#: parser/parse_coerce.c:2587 +#: parser/parse_coerce.c:2622 #, c-format msgid "anycompatiblerange type %s does not match anycompatible type %s" msgstr "anycompatiblerange型%sはanycompatiblerange型%sと合致しません" -#: parser/parse_coerce.c:2608 +#: parser/parse_coerce.c:2643 #, c-format msgid "anycompatiblemultirange type %s does not match anycompatible type %s" msgstr "anycompatiblemultirange型%sはanycompatible型%sと合致しません" -#: parser/parse_coerce.c:2622 +#: parser/parse_coerce.c:2657 #, c-format msgid "type matched to anycompatiblenonarray is an array type: %s" msgstr "anycompatiblenonarrayに対応する型が配列型です: %s" -#: parser/parse_coerce.c:2857 +#: parser/parse_coerce.c:2892 #, c-format msgid "A result of type %s requires at least one input of type anyrange or anymultirange." msgstr "%s型の返却値にはanyrangeまたはanymultirange型の入力が最低でも一つ必要です。" -#: parser/parse_coerce.c:2874 +#: parser/parse_coerce.c:2909 #, c-format msgid "A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange." msgstr "%s型の返却値には少なくとも一つのanycompatiblerangeまたはanycompatiblemultirange型の入力が必要です。" -#: parser/parse_coerce.c:2886 +#: parser/parse_coerce.c:2921 #, c-format msgid "A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange." msgstr "%s型の返却値には少なくとも一つのanyelement、anyarray、anynonarray、anyenum、anyrange またはanymultirange型の入力が必要です。" -#: parser/parse_coerce.c:2898 +#: parser/parse_coerce.c:2933 #, c-format msgid "A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange." msgstr "%s型の返却値には少なくとも一つのanycompatible、anycompatiblearray、anycompatiblenonarray、anycompatiblerangeまたはanycompatiblemultirange型の入力が必要です。" -#: parser/parse_coerce.c:2928 +#: parser/parse_coerce.c:2963 msgid "A result of type internal requires at least one input of type internal." msgstr "internal型の返却値には少なくとも1つのinternal型の入力が必要です。" @@ -17399,488 +17872,545 @@ msgstr "問い合わせ\"%s\"への再帰的参照が、INTERSECT内に現れて msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "問い合わせ\"%s\"への再帰的参照が、EXCEPT内で現れてはなりません" -#: parser/parse_cte.c:136 +#: parser/parse_cte.c:137 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "WITH 問い合わせ名\"%s\"が複数回指定されました" -#: parser/parse_cte.c:308 +#: parser/parse_cte.c:309 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "型%sの不等演算子を特定できませんでした" -#: parser/parse_cte.c:335 +#: parser/parse_cte.c:336 #, c-format msgid "WITH clause containing a data-modifying statement must be at the top level" msgstr "データを変更するようなステートメントを含む WITH 句はトップレベルでなければなりません" -#: parser/parse_cte.c:384 +#: parser/parse_cte.c:385 #, c-format msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall" msgstr "再帰問い合わせ\"%s\"の列%dの型は、非再帰項の内では%sになっていますが全体としては%sです" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:391 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "非再帰項の出力を正しい型に変換してください。" -#: parser/parse_cte.c:395 +#: parser/parse_cte.c:396 #, c-format msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall" msgstr "再帰問い合わせ\"%s\"の列%dの照合順序は、非再帰項では\"%s\"ですが全体としては\"%s\"です" -#: parser/parse_cte.c:399 +#: parser/parse_cte.c:400 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "COLLATE句を使って非再帰項の照合順序を設定してください。" -#: parser/parse_cte.c:420 +#: parser/parse_cte.c:421 #, c-format msgid "WITH query is not recursive" msgstr "WITH問い合わせは再帰的ではありません" -#: parser/parse_cte.c:451 +#: parser/parse_cte.c:452 #, c-format msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "SEARCHまたはCYCLE句を指定する場合、UNIONの左辺はSELECTでなければなりません" -#: parser/parse_cte.c:456 +#: parser/parse_cte.c:457 #, c-format msgid "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "SEARCHまたはCYCLE句を指定する場合、UNIONの右辺はSELECTでなければなりません" -#: parser/parse_cte.c:471 +#: parser/parse_cte.c:472 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "検索カラム\\\"%s\\\"はWITH問い合わせの列リストの中にありません" -#: parser/parse_cte.c:478 +#: parser/parse_cte.c:479 #, c-format msgid "search column \"%s\" specified more than once" msgstr "検索列\"%s\"が複数回指定されています" -#: parser/parse_cte.c:487 +#: parser/parse_cte.c:488 #, c-format msgid "search sequence column name \"%s\" already used in WITH query column list" msgstr "検索順序列の名前\\\"%s\\\"はすでにWITH問い合わせの列リストで使われています" -#: parser/parse_cte.c:504 +#: parser/parse_cte.c:505 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "循環列\"%s\"がWITH問い合わせの列リストに存在しません" -#: parser/parse_cte.c:511 +#: parser/parse_cte.c:512 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "循環列\"%s\"が複数回指定されています" -#: parser/parse_cte.c:520 +#: parser/parse_cte.c:521 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "循環識別列の名前\\\"%s\\\"はすでにWITH問い合わせの列リストで使われています" -#: parser/parse_cte.c:527 +#: parser/parse_cte.c:528 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "循環経路列の名前\\\"%s\\\"はすでにWITH問い合わせの列リストで使われています" -#: parser/parse_cte.c:535 +#: parser/parse_cte.c:536 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "循環識別列と循環経路列の名前が同一です" -#: parser/parse_cte.c:545 +#: parser/parse_cte.c:546 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "検索順序列と循環識別列の名前が同一です" -#: parser/parse_cte.c:552 +#: parser/parse_cte.c:553 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "検索順序列と循環経路列の名前が同一です" -#: parser/parse_cte.c:636 +#: parser/parse_cte.c:637 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "WITH問い合わせ\"%s\"には%d列しかありませんが、%d列指定されています" -#: parser/parse_cte.c:816 +#: parser/parse_cte.c:882 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "WITH項目間の再帰は実装されていません" -#: parser/parse_cte.c:868 +#: parser/parse_cte.c:934 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "再帰問い合わせ\"%s\"はデータを更新するス文を含んでいてはなりません" -#: parser/parse_cte.c:876 +#: parser/parse_cte.c:942 #, c-format msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term" msgstr "再帰問い合わせ\"%s\"が、<非再帰項> UNION [ALL] <再帰項> の形式になっていません" -#: parser/parse_cte.c:920 +#: parser/parse_cte.c:977 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "再帰問い合わせ内の ORDER BY は実装されていません" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:983 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "再帰問い合わせ内の OFFSET は実装されていません" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:989 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "再帰問い合わせ内の LIMIT は実装されていません" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:995 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "再帰問い合わせ内の FOR UPDATE/SHARE は実装されていません" -#: parser/parse_cte.c:995 +#: parser/parse_cte.c:1074 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "問い合わせ\"%s\"への再帰参照が2回以上現れてはなりません" -#: parser/parse_expr.c:314 +#: parser/parse_expr.c:311 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "この文脈ではDEFAULTは使えません" -#: parser/parse_expr.c:407 parser/parse_relation.c:3691 parser/parse_relation.c:3701 parser/parse_relation.c:3719 parser/parse_relation.c:3726 parser/parse_relation.c:3740 +#: parser/parse_expr.c:404 parser/parse_relation.c:3797 parser/parse_relation.c:3807 parser/parse_relation.c:3825 parser/parse_relation.c:3832 parser/parse_relation.c:3846 #, c-format msgid "column %s.%s does not exist" msgstr "列%s.%sは存在しません" -#: parser/parse_expr.c:419 +#: parser/parse_expr.c:416 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "データ型%2$sの列\"%1$s\"はありません" -#: parser/parse_expr.c:425 +#: parser/parse_expr.c:422 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "レコードデータ型の列\"%s\"を特定できませんでした" -#: parser/parse_expr.c:431 +#: parser/parse_expr.c:428 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "列記法 .%sが型%sに使用されましたが、この型は複合型ではありません" -#: parser/parse_expr.c:462 parser/parse_target.c:732 +#: parser/parse_expr.c:459 parser/parse_target.c:735 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "\"*\"を通した行展開は、ここではサポートされていません" -#: parser/parse_expr.c:585 +#: parser/parse_expr.c:582 msgid "cannot use column reference in DEFAULT expression" msgstr "列参照はDEFAULT式では使用できません" -#: parser/parse_expr.c:588 +#: parser/parse_expr.c:585 msgid "cannot use column reference in partition bound expression" msgstr "列参照はパーティション境界式では使用できません" -#: parser/parse_expr.c:847 parser/parse_relation.c:833 parser/parse_relation.c:915 parser/parse_target.c:1238 +#: parser/parse_expr.c:844 parser/parse_relation.c:848 parser/parse_relation.c:930 parser/parse_target.c:1241 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "列参照\"%s\"は曖昧です" -#: parser/parse_expr.c:903 parser/parse_param.c:110 parser/parse_param.c:142 parser/parse_param.c:204 parser/parse_param.c:303 +#: parser/parse_expr.c:900 parser/parse_param.c:111 parser/parse_param.c:143 parser/parse_param.c:205 parser/parse_param.c:304 #, c-format msgid "there is no parameter $%d" msgstr "パラメータ$%dがありません" -#: parser/parse_expr.c:1103 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1101 parser/parse_expr.c:3081 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "NULLIF では = 演算子が boolean を返す必要があります" +msgid "%s requires = operator to yield boolean" +msgstr "%sは真偽値を得るために = 演算子を必要とします" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1109 parser/parse_expr.c:3070 +#: parser/parse_expr.c:1107 parser/parse_expr.c:3088 #, c-format msgid "%s must not return a set" msgstr "%sは集合を返してはなりません" -#: parser/parse_expr.c:1395 +#: parser/parse_expr.c:1393 #, c-format msgid "MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" msgstr "MERGE_ACTION()はMERGEコマンドのRETURNINGリストの中でのみ使用可能です" -#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 +#: parser/parse_expr.c:1517 parser/parse_expr.c:1549 #, c-format msgid "number of columns does not match number of values" msgstr "列の数がVALUESの数と一致しません" -#: parser/parse_expr.c:1565 +#: parser/parse_expr.c:1563 #, c-format msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" msgstr "複数列のUPDATE項目のソースは副問合せまたはROW()式でなければなりません" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 +#: parser/parse_expr.c:1758 parser/parse_expr.c:2249 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "集合返却関数は%sでは使用できません" -#: parser/parse_expr.c:1824 +#: parser/parse_expr.c:1822 msgid "cannot use subquery in check constraint" msgstr "検査制約では副問い合わせを使用できません" -#: parser/parse_expr.c:1828 +#: parser/parse_expr.c:1826 msgid "cannot use subquery in DEFAULT expression" msgstr "DEFAULT式には副問い合わせを使用できません" -#: parser/parse_expr.c:1831 +#: parser/parse_expr.c:1829 msgid "cannot use subquery in index expression" msgstr "式インデックスには副問い合わせを使用できません" -#: parser/parse_expr.c:1834 +#: parser/parse_expr.c:1832 msgid "cannot use subquery in index predicate" msgstr "インデックスの述部に副問い合わせを使用できません" -#: parser/parse_expr.c:1837 +#: parser/parse_expr.c:1835 msgid "cannot use subquery in statistics expression" msgstr "時計情報式では副問い合わせを使用できません" -#: parser/parse_expr.c:1840 +#: parser/parse_expr.c:1838 msgid "cannot use subquery in transform expression" msgstr "変換式では副問い合わせを使用できません" -#: parser/parse_expr.c:1843 +#: parser/parse_expr.c:1841 msgid "cannot use subquery in EXECUTE parameter" msgstr "EXECUTEのパラメータに副問い合わせを使用できません" -#: parser/parse_expr.c:1846 +#: parser/parse_expr.c:1844 msgid "cannot use subquery in trigger WHEN condition" msgstr "トリガーの WHEN 条件では副問い合わせを使用できません" -#: parser/parse_expr.c:1849 +#: parser/parse_expr.c:1847 msgid "cannot use subquery in partition bound" msgstr "副問い合わせはパーティション境界では使用できません" -#: parser/parse_expr.c:1852 +#: parser/parse_expr.c:1850 msgid "cannot use subquery in partition key expression" msgstr "パーティションキー式では副問い合わせを使用できません" -#: parser/parse_expr.c:1855 +#: parser/parse_expr.c:1853 msgid "cannot use subquery in CALL argument" msgstr "CALLの引数で副問い合わせは使用できません" -#: parser/parse_expr.c:1858 +#: parser/parse_expr.c:1856 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "副問い合わせは COPY FROM の WHERE 条件では使用できません" -#: parser/parse_expr.c:1861 +#: parser/parse_expr.c:1859 msgid "cannot use subquery in column generation expression" msgstr "副問い合わせはカラム生成式では使用できません" -#: parser/parse_expr.c:1914 parser/parse_expr.c:3756 +#: parser/parse_expr.c:1912 parser/parse_expr.c:3780 #, c-format msgid "subquery must return only one column" msgstr "副問い合わせは1列のみを返さなければなりません" -#: parser/parse_expr.c:1985 +#: parser/parse_expr.c:1983 #, c-format msgid "subquery has too many columns" msgstr "副問い合わせの列が多すぎます" -#: parser/parse_expr.c:1990 +#: parser/parse_expr.c:1988 #, c-format msgid "subquery has too few columns" msgstr "副問い合わせの列が少なすぎます" -#: parser/parse_expr.c:2086 +#: parser/parse_expr.c:2092 #, c-format msgid "cannot determine type of empty array" msgstr "空の配列のデータ型を決定できません" -#: parser/parse_expr.c:2087 +#: parser/parse_expr.c:2093 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "必要な型に明示的にキャストしてください。例: ARRAY[]::integer[]" -#: parser/parse_expr.c:2101 +#: parser/parse_expr.c:2107 #, c-format msgid "could not find element type for data type %s" msgstr "データ型%sの要素を見つけられませんでした" -#: parser/parse_expr.c:2184 +#: parser/parse_expr.c:2190 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "ROW式は最大でも%dエントリまでしか持てません" -#: parser/parse_expr.c:2389 +#: parser/parse_expr.c:2395 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "無名のXML属性値は列参照でなければなりません" -#: parser/parse_expr.c:2390 +#: parser/parse_expr.c:2396 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "無名のXML要素値は列参照でなければなりません" -#: parser/parse_expr.c:2405 +#: parser/parse_expr.c:2411 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "XML属性名\"%s\"が複数あります" -#: parser/parse_expr.c:2513 +#: parser/parse_expr.c:2519 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "XMLSERIALIZE の結果を %s へキャストできません" -#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 +#: parser/parse_expr.c:2843 parser/parse_expr.c:3039 #, c-format msgid "unequal number of entries in row expressions" msgstr "行式において項目数が一致しません" -#: parser/parse_expr.c:2837 +#: parser/parse_expr.c:2853 #, c-format msgid "cannot compare rows of zero length" msgstr "長さ0の行を比較できません" -#: parser/parse_expr.c:2862 +#: parser/parse_expr.c:2878 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "行比較演算子は型%sではなくbooleanを返さなければなりません" -#: parser/parse_expr.c:2869 +#: parser/parse_expr.c:2885 #, c-format msgid "row comparison operator must not return a set" msgstr "行比較演算子は集合を返してはいけません" -#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 +#: parser/parse_expr.c:2944 parser/parse_expr.c:2985 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "行比較演算子%sの解釈を特定できませんでした" -#: parser/parse_expr.c:2930 +#: parser/parse_expr.c:2946 #, c-format msgid "Row comparison operators must be associated with btree operator families." msgstr "行比較演算子はbtree演算子族と関連付けされなければなりません。" -#: parser/parse_expr.c:2971 +#: parser/parse_expr.c:2987 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "同程度の適合度の候補が複数存在します。" -#: parser/parse_expr.c:3064 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "IS DISTINCT FROMでは=演算子はbooleanを返さなければなりません" - -#: parser/parse_expr.c:3304 +#: parser/parse_expr.c:3322 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "JSON ENCODING句は入力型がbyteaの場合にのみ使用可能です" -#: parser/parse_expr.c:3368 +#: parser/parse_expr.c:3386 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "非文字列型は暗黙のFORMAT JSON句とともには使用できません" -#: parser/parse_expr.c:3369 +#: parser/parse_expr.c:3387 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "非文字列型は明示的なFORMAT JSON句とともには使用できません" -#: parser/parse_expr.c:3458 +#: parser/parse_expr.c:3476 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "JSONフォーマットは非文字列出力型とともには使用できません" -#: parser/parse_expr.c:3471 +#: parser/parse_expr.c:3489 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "bytrea以外の出力型に対してはJSON符号化方式は設定できません" -#: parser/parse_expr.c:3476 +#: parser/parse_expr.c:3494 #, c-format msgid "unsupported JSON encoding" msgstr "サポートされてないJSON符号化方式" -#: parser/parse_expr.c:3477 +#: parser/parse_expr.c:3495 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "JSON符号化方式ではUTF8のみがサポートされています。" -#: parser/parse_expr.c:3514 +#: parser/parse_expr.c:3532 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "SQL/JSON関数ではSETOF型の返却はサポートされていません" -#: parser/parse_expr.c:3519 +#: parser/parse_expr.c:3537 #, c-format msgid "returning pseudo-types is not supported in SQL/JSON functions" msgstr "SQL/JSON関数では疑似型の返却はサポートされていません" -#: parser/parse_expr.c:3841 parser/parse_func.c:866 +#: parser/parse_expr.c:3865 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "ウィンドウ関数に対する集約の ORDER BY は実装されていません" -#: parser/parse_expr.c:4063 +#: parser/parse_expr.c:4088 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "bytrea以外の入力型に対しては JSON FORMAT ENCODING句は使用できません" -#: parser/parse_expr.c:4083 +#: parser/parse_expr.c:4108 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "JSON述語では型%sを使用できません" -#: parser/parse_expr.c:4109 parser/parse_expr.c:4229 +#: parser/parse_expr.c:4134 parser/parse_expr.c:4255 +#, c-format +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "%s()のRETURNING節では型%sは指定できません" + +#: parser/parse_expr.c:4136 #, c-format -msgid "cannot use RETURNING type %s in %s" -msgstr "%2$sではRETURNING型%1$sを使用できません" +msgid "Try returning json or jsonb." +msgstr "jsonまたはjsonbでの返却を試してください。" -#: parser/parse_expr.c:4158 +#: parser/parse_expr.c:4184 #, c-format msgid "cannot use non-string types with WITH UNIQUE KEYS clause" msgstr "非文字列型はWITH UNIQUE KEYS句とともには使用できません" -#: parser/parse_expr.c:4232 +#: parser/parse_expr.c:4258 #, c-format msgid "Try returning a string type or bytea." msgstr "文字列型またはBYTEA型での返却を試してください。" -#: parser/parse_expr.c:4297 +#: parser/parse_expr.c:4323 #, c-format msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" msgstr "%s()のRETURNING節ではFORMAT JSONは指定できません" -#: parser/parse_expr.c:4309 +#: parser/parse_expr.c:4336 #, c-format msgid "SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" msgstr "WITH WRAPPERが使われてるときにはSQL/JSONのQUOTESの挙動は指定できまえん" -#: parser/parse_expr.c:4336 +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4350 parser/parse_expr.c:4379 parser/parse_expr.c:4410 parser/parse_expr.c:4436 parser/parse_expr.c:4462 parser/parse_jsontable.c:92 +#, c-format +msgid "invalid %s behavior" +msgstr "不正な%s挙動指定" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4353 parser/parse_expr.c:4382 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s." +msgstr "%2$sに対する%1$s句ではERROR, NULL, EMPTY ARRAY, EMPTY OBJECTまたはDEFAULT式のみが使用可能です。" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4360 parser/parse_expr.c:4389 parser/parse_expr.c:4418 parser/parse_expr.c:4446 parser/parse_expr.c:4472 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "列\"%s\"に対する不正な%s挙動指定" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4363 parser/parse_expr.c:4392 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns." +msgstr "フォーマット化対象列に対する%s句ではERROR, NULL, EMPTY ARRAY, EMPTY OBJECTまたはDEFAULT式のみが使用可能です。" + +#: parser/parse_expr.c:4411 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "%2$sに対する%1$s句ではERROR, TRUE, FALSEまたはUNKNOWNのみが使用可能です。" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4421 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "EXIST列に対する%s句ではERROR, TRUE, FALSEまたはUNKNOWNのみが使用可能です。" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4439 parser/parse_expr.c:4465 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "%2$sに対する%1$s句ではERROR, NULLまたはDEFAULT式のみが使用可能です。" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4449 parser/parse_expr.c:4475 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "スカラー列に対する%s句ではERROR, NULLまたはDEFAULT式のみが使用可能です。" + +#: parser/parse_expr.c:4505 #, c-format msgid "JSON path expression must be of type %s, not of type %s" msgstr "JSONパス式は型%2$sではなく%1$s型でなければなりません" -#: parser/parse_expr.c:4677 +#: parser/parse_expr.c:4723 #, c-format msgid "can only specify a constant, non-aggregate function, or operator expression for DEFAULT" msgstr "DEFAULTには定数、非集約関数、および演算子式のみ指定可能です" -#: parser/parse_expr.c:4682 +#: parser/parse_expr.c:4728 #, c-format msgid "DEFAULT expression must not contain column references" msgstr "DEFAULT式は列参照を含むことができません" -#: parser/parse_expr.c:4687 +#: parser/parse_expr.c:4733 #, c-format msgid "DEFAULT expression must not return a set" msgstr "DEFAULT式は集合を返してはなりません" -#: parser/parse_expr.c:4721 +#: parser/parse_expr.c:4809 parser/parse_expr.c:4818 #, c-format msgid "cannot cast behavior expression of type %s to %s" msgstr "型%sの挙動式の%sへの型変換はできません" +#: parser/parse_expr.c:4812 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "式を%s型に明示的にキャストする必要があります。" + #: parser/parse_func.c:194 #, c-format msgid "argument name \"%s\" used more than once" @@ -18212,26 +18742,16 @@ msgstr "集合返却関数は COPY FROM の WHERE条件では使用できませ msgid "set-returning functions are not allowed in column generation expressions" msgstr "集合返却関数はカラム生成式では使用できません" -#: parser/parse_jsontable.c:94 +#: parser/parse_jsontable.c:93 #, c-format -msgid "invalid ON ERROR behavior" -msgstr "不正な ON ERROR 挙動指定です" +msgid "Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "最上位のON ERROR句ではEMPTY [ ARRAY ] またERRORのみ使用可能です。" -#: parser/parse_jsontable.c:95 -#, c-format -msgid "Only EMPTY or ERROR is allowed in the top-level ON ERROR clause." -msgstr "最上位のON ERROR句ではEMPTYまたERRORのみ使用可能です。" - -#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#: parser/parse_jsontable.c:187 parser/parse_jsontable.c:201 #, c-format msgid "duplicate JSON_TABLE column or path name: %s" msgstr "JSON_TABLEのカラムまたはパス名の重複: %s" -#: parser/parse_jsontable.c:295 -#, c-format -msgid "cannot use more than one FOR ORDINALITY column" -msgstr "FOR ORDINALITY 列は2つ以上は使用できません" - #: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" @@ -18307,227 +18827,222 @@ msgstr "演算子 ANY/ALL (配列) はブール型を返さなければなりま msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "演算子 ANY/ALL (配列) 集合を返してはなりません" -#: parser/parse_param.c:221 +#: parser/parse_param.c:222 #, c-format msgid "inconsistent types deduced for parameter $%d" msgstr "パラメータ$%dについて推定された型が不整合です" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:310 tcop/postgres.c:734 #, c-format msgid "could not determine data type of parameter $%d" msgstr "パラメータ$%dのデータ型が特定できませんでした" -#: parser/parse_relation.c:221 +#: parser/parse_relation.c:226 #, c-format msgid "table reference \"%s\" is ambiguous" msgstr "テーブル参照\"%s\"は曖昧です" -#: parser/parse_relation.c:265 +#: parser/parse_relation.c:273 #, c-format msgid "table reference %u is ambiguous" msgstr "テーブル参照%uは曖昧です" -#: parser/parse_relation.c:465 -#, c-format -msgid "table name \"%s\" specified more than once" -msgstr "テーブル名\"%s\"が複数指定されました" - -#: parser/parse_relation.c:494 parser/parse_relation.c:3633 parser/parse_relation.c:3642 +#: parser/parse_relation.c:502 parser/parse_relation.c:3739 parser/parse_relation.c:3748 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "テーブル\"%s\"用のFROM句に対する不正な参照" -#: parser/parse_relation.c:498 parser/parse_relation.c:3644 +#: parser/parse_relation.c:506 parser/parse_relation.c:3750 #, c-format msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query." msgstr "テーブル\"%s\"の項目がありますが、問い合わせのこの部分からは参照できません。\"" -#: parser/parse_relation.c:500 +#: parser/parse_relation.c:508 #, c-format msgid "The combining JOIN type must be INNER or LEFT for a LATERAL reference." msgstr "LATERAL参照では組み合わせる結合のタイプはINNERまたはLEFTでなければなりません" -#: parser/parse_relation.c:703 +#: parser/parse_relation.c:711 #, c-format msgid "system column \"%s\" reference in check constraint is invalid" msgstr "検査制約で参照されるシステム列\"%s\"は不正です" -#: parser/parse_relation.c:712 +#: parser/parse_relation.c:724 #, c-format msgid "cannot use system column \"%s\" in column generation expression" msgstr "カラム生成式ではシステム列\"%s\"は使用できません" -#: parser/parse_relation.c:723 +#: parser/parse_relation.c:735 #, c-format msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "MERGE WHEN条件ではシステム列\"%s\"は使用できません" -#: parser/parse_relation.c:1236 parser/parse_relation.c:1691 parser/parse_relation.c:2384 +#: parser/parse_relation.c:1251 parser/parse_relation.c:1708 parser/parse_relation.c:2402 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "テーブル\"%s\"では%d列使用できますが、%d列指定されました" -#: parser/parse_relation.c:1445 +#: parser/parse_relation.c:1462 #, c-format msgid "There is a WITH item named \"%s\", but it cannot be referenced from this part of the query." msgstr "\"%s\"というWITH項目はありますが、これは問い合わせのこの部分からは参照できません。" -#: parser/parse_relation.c:1447 +#: parser/parse_relation.c:1464 #, c-format msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references." msgstr "WITH RECURSIVE を使うか、もしくは WITH 項目の場所を変えて前方参照をなくしてください" -#: parser/parse_relation.c:1833 +#: parser/parse_relation.c:1850 #, c-format msgid "a column definition list is redundant for a function with OUT parameters" msgstr "OUTパラメータを持つ関数に対しては列定義リストは不要です" -#: parser/parse_relation.c:1839 +#: parser/parse_relation.c:1856 #, c-format msgid "a column definition list is redundant for a function returning a named composite type" msgstr "名前付き複合型w返す関数に対しては列定義リストは不要です" -#: parser/parse_relation.c:1846 +#: parser/parse_relation.c:1863 #, c-format msgid "a column definition list is only allowed for functions returning \"record\"" msgstr "列定義リストは\"record\"を返す関数でのみ使用できます" -#: parser/parse_relation.c:1857 +#: parser/parse_relation.c:1874 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "\"record\"を返す関数では列定義リストが必要です" -#: parser/parse_relation.c:1894 +#: parser/parse_relation.c:1911 #, c-format msgid "column definition lists can have at most %d entries" msgstr "列定義リストは最大でも%dエントリまでしか持てません" -#: parser/parse_relation.c:1954 +#: parser/parse_relation.c:1971 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "FROM句の関数\"%s\"の戻り値型%sはサポートされていません" -#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 +#: parser/parse_relation.c:1998 parser/parse_relation.c:2083 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "FROM内の関数は最大%d列までしか返却できません" -#: parser/parse_relation.c:2096 +#: parser/parse_relation.c:2113 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "%s関数では%d列使用できますが、%d列指定されました" -#: parser/parse_relation.c:2177 +#: parser/parse_relation.c:2194 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "VALUESリスト\"%s\"は%d列使用可能ですが、%d列が指定されました" -#: parser/parse_relation.c:2242 +#: parser/parse_relation.c:2259 #, c-format msgid "joins can have at most %d columns" msgstr "JOIN で指定できるのは、最大 %d 列です" -#: parser/parse_relation.c:2267 +#: parser/parse_relation.c:2284 #, c-format msgid "join expression \"%s\" has %d columns available but %d columns specified" msgstr "結合式\"%s\"では%d列使用できますが、%d列指定されました" -#: parser/parse_relation.c:2357 +#: parser/parse_relation.c:2375 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "WITH 問い合わせ\"%s\"にRETURNING句がありません" -#: parser/parse_relation.c:3635 +#: parser/parse_relation.c:3741 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "テーブル別名\"%s\"を参照しようとしていたようです。" -#: parser/parse_relation.c:3647 +#: parser/parse_relation.c:3753 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "そのテーブルを参照するためには、この副問合せをLATERALとマークする必要があります。" -#: parser/parse_relation.c:3653 +#: parser/parse_relation.c:3759 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "テーブル\"%s\"用のFROM句エントリがありません" -#: parser/parse_relation.c:3693 +#: parser/parse_relation.c:3799 #, c-format msgid "There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query." msgstr "\"%s\"という名前の列はありますが、問い合わせのこの部分からは参照できないテーブルに属しています。" -#: parser/parse_relation.c:3695 +#: parser/parse_relation.c:3801 #, c-format msgid "Try using a table-qualified name." msgstr "テーブル名で修飾した名前を試してください。" -#: parser/parse_relation.c:3703 +#: parser/parse_relation.c:3809 #, c-format msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." msgstr "テーブル\"%2$s\"には\"%1$s\"という名前の列がありますが、問い合わせのこの部分からは参照できません。" -#: parser/parse_relation.c:3706 +#: parser/parse_relation.c:3812 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "その列を参照するには、この副問合せをLATERALとマークする必要があります。" -#: parser/parse_relation.c:3708 +#: parser/parse_relation.c:3814 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "その列を参照するには、テーブル名で修飾した名前を使う必要があります。" -#: parser/parse_relation.c:3728 +#: parser/parse_relation.c:3834 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "列\"%s.%s\"を参照しようとしていたようです。" -#: parser/parse_relation.c:3742 +#: parser/parse_relation.c:3848 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "列\"%s.%s\"または列\"%s.%s\"を参照しようとしていたようです。" -#: parser/parse_target.c:480 parser/parse_target.c:795 +#: parser/parse_target.c:483 parser/parse_target.c:798 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "システム列\"%s\"に代入できません" -#: parser/parse_target.c:508 +#: parser/parse_target.c:511 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "配列要素にDEFAULTを設定できません" -#: parser/parse_target.c:513 +#: parser/parse_target.c:516 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "サブフィールドにDEFAULTを設定できません" -#: parser/parse_target.c:587 +#: parser/parse_target.c:590 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "列\"%s\"は型%sですが、式は型%sでした" -#: parser/parse_target.c:779 +#: parser/parse_target.c:782 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type" msgstr "型%3$sが複合型でありませんので、列\"%2$s\"のフィールド\"%1$s\"に代入できません。" -#: parser/parse_target.c:788 +#: parser/parse_target.c:791 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s" msgstr "データ型%3$sの列がありませんので、列\"%2$s\"のフィールド\"%1$s\"に代入できません。" -#: parser/parse_target.c:877 +#: parser/parse_target.c:880 #, c-format msgid "subscripted assignment to \"%s\" requires type %s but expression is of type %s" msgstr "\"%s\"への添字付き代入には型%sが必要ですが、式は型%sでした" -#: parser/parse_target.c:887 +#: parser/parse_target.c:890 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "サブフィールド\"%s\"は型%sですが、式は型%sでした" -#: parser/parse_target.c:1327 +#: parser/parse_target.c:1330 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "テーブル指定のないSELECT *は無効です" @@ -18547,7 +19062,7 @@ msgstr "%%TYPE参照が不適切です(ドット区切りの名前が多すぎ msgid "type reference %s converted to %s" msgstr "型参照%sは%sに変換されました" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 utils/cache/typcache.c:452 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:478 utils/cache/typcache.c:533 #, c-format msgid "type \"%s\" is only a shell" msgstr "型\"%s\"は単なるシェルです" @@ -18567,337 +19082,352 @@ msgstr "型修正子は単純な定数または識別子でなければなりま msgid "invalid type name \"%s\"" msgstr "不正な型名\"%s\"" -#: parser/parse_utilcmd.c:266 +#: parser/parse_utilcmd.c:265 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "パーティション親テーブルを継承の子テーブルとして作成はできません" -#: parser/parse_utilcmd.c:586 +#: parser/parse_utilcmd.c:504 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "一時シーケンスのログ出力状態は設定できません" + +#: parser/parse_utilcmd.c:642 #, c-format msgid "array of serial is not implemented" msgstr "連番(SERIAL)の配列は実装されていません" -#: parser/parse_utilcmd.c:665 parser/parse_utilcmd.c:677 parser/parse_utilcmd.c:736 +#: parser/parse_utilcmd.c:747 parser/parse_utilcmd.c:765 parser/parse_utilcmd.c:873 parser/parse_utilcmd.c:906 #, c-format msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"でNULL宣言とNOT NULL宣言が競合しています" -#: parser/parse_utilcmd.c:689 +#: parser/parse_utilcmd.c:759 parser/parse_utilcmd.c:1077 +#, c-format +msgid "not-null constraints on partitioned tables cannot be NO INHERIT" +msgstr "パーティション親テーブルに対する非NULL制約はNO INHERIT指定できません" + +#: parser/parse_utilcmd.c:773 parser/parse_utilcmd.c:808 +#, c-format +msgid "conflicting NO INHERIT declarations for not-null constraints on column \"%s\"" +msgstr "列\"%s\"の非NULL制約に関する矛盾するNO INHERIT宣言" + +#: parser/parse_utilcmd.c:821 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"で複数のデフォルト値の指定があります" -#: parser/parse_utilcmd.c:706 +#: parser/parse_utilcmd.c:838 #, c-format msgid "identity columns are not supported on typed tables" msgstr "型付けされたテーブルでは識別列はサポートされていません" -#: parser/parse_utilcmd.c:710 +#: parser/parse_utilcmd.c:842 #, c-format msgid "identity columns are not supported on partitions" msgstr "パーティションでは識別列はサポートされていません" -#: parser/parse_utilcmd.c:719 +#: parser/parse_utilcmd.c:851 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"に複数の識別指定があります" -#: parser/parse_utilcmd.c:749 +#: parser/parse_utilcmd.c:884 #, c-format msgid "generated columns are not supported on typed tables" msgstr "型付けされたテーブルでは生成カラムはサポートされていません" -#: parser/parse_utilcmd.c:753 +#: parser/parse_utilcmd.c:888 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"に複数のGENERATED句の指定があります" -#: parser/parse_utilcmd.c:771 parser/parse_utilcmd.c:886 +#: parser/parse_utilcmd.c:915 parser/parse_utilcmd.c:1043 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "外部テーブルでは主キー制約はサポートされていません" -#: parser/parse_utilcmd.c:780 parser/parse_utilcmd.c:896 +#: parser/parse_utilcmd.c:924 parser/parse_utilcmd.c:1053 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "外部テーブルではユニーク制約はサポートされていません" -#: parser/parse_utilcmd.c:825 +#: parser/parse_utilcmd.c:971 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "デフォルト値と識別指定の両方がテーブル\"%2$s\"の列\"%1$s\"に指定されています" -#: parser/parse_utilcmd.c:833 +#: parser/parse_utilcmd.c:979 #, c-format msgid "both default and generation expression specified for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"にデフォルト値と生成式の両方が指定されています" -#: parser/parse_utilcmd.c:841 +#: parser/parse_utilcmd.c:987 #, c-format msgid "both identity and generation expression specified for column \"%s\" of table \"%s\"" msgstr "テーブル\"%2$s\"の列\"%1$s\"に識別指定と生成式の両方が指定されています" -#: parser/parse_utilcmd.c:906 +#: parser/parse_utilcmd.c:1063 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "外部テーブルでは除外制約はサポートされていません" -#: parser/parse_utilcmd.c:971 -#, c-format -msgid "LIKE is not supported for creating foreign tables" -msgstr "外部テーブルの作成においてLIKEはサポートされていません" - -#: parser/parse_utilcmd.c:984 +#: parser/parse_utilcmd.c:1149 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "LIKE句ではリレーション\"%s\"は不正です" -#: parser/parse_utilcmd.c:1711 parser/parse_utilcmd.c:1819 +#: parser/parse_utilcmd.c:1896 parser/parse_utilcmd.c:2004 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "インデックス\"%s\"には行全体テーブル参照が含まれます" -#: parser/parse_utilcmd.c:2217 +#: parser/parse_utilcmd.c:2398 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "CREATE TABLE では既存のインデックスを使えません" -#: parser/parse_utilcmd.c:2237 +#: parser/parse_utilcmd.c:2418 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "インデックス\"%s\"はすでに1つの制約に割り当てられています" -#: parser/parse_utilcmd.c:2258 +#: parser/parse_utilcmd.c:2444 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\"はユニークインデックスではありません" -#: parser/parse_utilcmd.c:2259 parser/parse_utilcmd.c:2266 parser/parse_utilcmd.c:2273 parser/parse_utilcmd.c:2350 +#: parser/parse_utilcmd.c:2445 parser/parse_utilcmd.c:2452 parser/parse_utilcmd.c:2459 parser/parse_utilcmd.c:2535 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "このようなインデックスを使ってプライマリキーや一意性制約を作成することはできません" -#: parser/parse_utilcmd.c:2265 +#: parser/parse_utilcmd.c:2451 #, c-format msgid "index \"%s\" contains expressions" msgstr "インデックス\"%s\"は式を含んでいます" -#: parser/parse_utilcmd.c:2272 +#: parser/parse_utilcmd.c:2458 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\"は部分インデックスです" -#: parser/parse_utilcmd.c:2284 +#: parser/parse_utilcmd.c:2470 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\"は遅延可能インデックスです" -#: parser/parse_utilcmd.c:2285 +#: parser/parse_utilcmd.c:2471 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "遅延可能インデックスを使った遅延不可制約は作れません。" -#: parser/parse_utilcmd.c:2349 +#: parser/parse_utilcmd.c:2534 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "インデックス\"%s\"の列番号%dにはデフォルトのソート動作がありません" -#: parser/parse_utilcmd.c:2506 +#: parser/parse_utilcmd.c:2726 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "列\"%s\"がプライマリキー制約内に2回出現します" -#: parser/parse_utilcmd.c:2512 +#: parser/parse_utilcmd.c:2732 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "列\"%s\"が一意性制約内に2回出現します" -#: parser/parse_utilcmd.c:2846 +#: parser/parse_utilcmd.c:2777 +#, c-format +msgid "column \"%s\" in WITHOUT OVERLAPS is not a range or multirange type" +msgstr "WITHOUT OVERLAPS中の列\"%s\"は範囲型でも副範囲型でもありません" + +#: parser/parse_utilcmd.c:2805 +#, c-format +msgid "constraint using WITHOUT OVERLAPS needs at least two columns" +msgstr "WITHOUT OVERLAPSを使用する制約では少なくとも2つの列が必要です" + +#: parser/parse_utilcmd.c:3102 #, c-format msgid "index expressions and predicates can refer only to the table being indexed" msgstr "インデックス式と述語はインデックス付けされるテーブルのみを参照できます" -#: parser/parse_utilcmd.c:2918 +#: parser/parse_utilcmd.c:3174 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "統計情報式は参照されているテーブルのみを参照できます" -#: parser/parse_utilcmd.c:2961 +#: parser/parse_utilcmd.c:3217 #, c-format msgid "rules on materialized views are not supported" msgstr "実体化ビューに対するルールはサポートされません" -#: parser/parse_utilcmd.c:3021 +#: parser/parse_utilcmd.c:3277 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "ルールのWHERE条件に他のリレーションへの参照を持たせられません" -#: parser/parse_utilcmd.c:3093 +#: parser/parse_utilcmd.c:3349 #, c-format msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions" msgstr "ルールのWHERE条件はSELECT、INSERT、UPDATE、DELETE動作のみを持つことができます" -#: parser/parse_utilcmd.c:3111 parser/parse_utilcmd.c:3212 rewrite/rewriteHandler.c:537 rewrite/rewriteManip.c:1095 +#: parser/parse_utilcmd.c:3367 parser/parse_utilcmd.c:3468 rewrite/rewriteHandler.c:546 rewrite/rewriteManip.c:1234 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "条件付きのUNION/INTERSECT/EXCEPT文は実装されていません" -#: parser/parse_utilcmd.c:3129 +#: parser/parse_utilcmd.c:3385 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "ON SELECTルールではOLDを使用できません" -#: parser/parse_utilcmd.c:3133 +#: parser/parse_utilcmd.c:3389 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "ON SELECTルールではNEWを使用できません" -#: parser/parse_utilcmd.c:3142 +#: parser/parse_utilcmd.c:3398 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "ON INSERTルールではOLDを使用できません" -#: parser/parse_utilcmd.c:3148 +#: parser/parse_utilcmd.c:3404 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "ON DELETEルールではNEWを使用できません" -#: parser/parse_utilcmd.c:3176 +#: parser/parse_utilcmd.c:3432 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "WITH 問い合わせ内では OLD は参照できません" -#: parser/parse_utilcmd.c:3183 +#: parser/parse_utilcmd.c:3439 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "WITH 問い合わせ内では NEW は参照できません" -#: parser/parse_utilcmd.c:3255 -#, c-format -msgid "\"%s\" is not a partition" -msgstr "\"%s\"はパーティション子テーブルではありません" - -#: parser/parse_utilcmd.c:3290 parser/parse_utilcmd.c:3335 parser/parse_utilcmd.c:4101 -#, c-format -msgid "\"%s\" is not a partitioned table" -msgstr "\"%s\"はパーティションテーブルではありません" - -#: parser/parse_utilcmd.c:3343 -#, c-format -msgid "partition of hash-partitioned table cannot be merged" -msgstr "ハッシュパーティションテーブルの子テーブルは結合できません" - -#: parser/parse_utilcmd.c:3361 -#, c-format -msgid "partition with name \"%s\" is already used" -msgstr "名前\"%s\"を持つパーティションはすでに使用されてます" - -#: parser/parse_utilcmd.c:3673 -#, c-format -msgid "list of new partitions should contain at least two items" -msgstr "新しいパーティションリストには最低2つの要素が必要です" - -#: parser/parse_utilcmd.c:3811 +#: parser/parse_utilcmd.c:3897 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "DEFERRABLE句の場所が間違っています" -#: parser/parse_utilcmd.c:3816 parser/parse_utilcmd.c:3831 +#: parser/parse_utilcmd.c:3902 parser/parse_utilcmd.c:3917 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "複数のDEFERRABLE/NOT DEFERRABLE句を使用できません" -#: parser/parse_utilcmd.c:3826 +#: parser/parse_utilcmd.c:3912 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "NOT DEFERRABLE句の場所が間違っています" -#: parser/parse_utilcmd.c:3847 +#: parser/parse_utilcmd.c:3933 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "INITIALLY DEFERRED句の場所が間違っています<" -#: parser/parse_utilcmd.c:3852 parser/parse_utilcmd.c:3878 +#: parser/parse_utilcmd.c:3938 parser/parse_utilcmd.c:3964 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "複数のINITIALLY IMMEDIATE/DEFERRED句を使用できません" -#: parser/parse_utilcmd.c:3873 +#: parser/parse_utilcmd.c:3959 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "INITIALLY IMMEDIATE句の場所が間違っています<" -#: parser/parse_utilcmd.c:4066 +#: parser/parse_utilcmd.c:3976 +#, c-format +msgid "misplaced ENFORCED clause" +msgstr "ENFORCED句の場所が間違っています" + +#: parser/parse_utilcmd.c:3981 parser/parse_utilcmd.c:3998 +#, c-format +msgid "multiple ENFORCED/NOT ENFORCED clauses not allowed" +msgstr "複数のENFORCED/NOT ENFORCED句は指定できません" + +#: parser/parse_utilcmd.c:3993 +#, c-format +msgid "misplaced NOT ENFORCED clause" +msgstr "NOT ENFORCED句の場所が間違っています" + +#: parser/parse_utilcmd.c:4191 #, c-format msgid "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "CREATEで指定したスキーマ(%s)が作成先のスキーマ(%s)と異なります" -#: parser/parse_utilcmd.c:4108 +#: parser/parse_utilcmd.c:4226 +#, c-format +msgid "\"%s\" is not a partitioned table" +msgstr "\"%s\"はパーティションテーブルではありません" + +#: parser/parse_utilcmd.c:4233 #, c-format msgid "table \"%s\" is not partitioned" msgstr "テーブル\"%s\"はパーティションされていません" -#: parser/parse_utilcmd.c:4115 +#: parser/parse_utilcmd.c:4240 #, c-format msgid "index \"%s\" is not partitioned" msgstr "インデックス\"%s\"はパーティションされていません" -#: parser/parse_utilcmd.c:4155 +#: parser/parse_utilcmd.c:4280 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "ハッシュパーティションテーブルはデフォルトパーティションを持つことができません" -#: parser/parse_utilcmd.c:4172 +#: parser/parse_utilcmd.c:4297 #, c-format msgid "invalid bound specification for a hash partition" msgstr "ハッシュパーティションに対する不正な境界指定" -#: parser/parse_utilcmd.c:4178 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4303 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "ハッシュパーティションの法は0より大きい整数にする必要があります" -#: parser/parse_utilcmd.c:4185 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4310 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "ハッシュパーティションの剰余は法よりも小さくなければなりません" -#: parser/parse_utilcmd.c:4198 +#: parser/parse_utilcmd.c:4323 #, c-format msgid "invalid bound specification for a list partition" msgstr "リストパーティションに対する不正な境界指定" -#: parser/parse_utilcmd.c:4251 +#: parser/parse_utilcmd.c:4376 #, c-format msgid "invalid bound specification for a range partition" msgstr "範囲パーティションに対する不正な境界指定" -#: parser/parse_utilcmd.c:4257 +#: parser/parse_utilcmd.c:4382 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "FROMは全てのパーティション列ごとに一つの値を指定しなければなりません" -#: parser/parse_utilcmd.c:4261 +#: parser/parse_utilcmd.c:4386 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "TOは全てのパーティション列ごとに一つの値を指定しなければなりません" -#: parser/parse_utilcmd.c:4375 +#: parser/parse_utilcmd.c:4500 #, c-format msgid "cannot specify NULL in range bound" msgstr "範囲境界でNULLは使用できません" -#: parser/parse_utilcmd.c:4424 +#: parser/parse_utilcmd.c:4549 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "MAXVALUEに続く境界値はMAXVALUEでなければなりません" -#: parser/parse_utilcmd.c:4431 +#: parser/parse_utilcmd.c:4556 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "MINVALUEに続く境界値はMINVALUEでなければなりません" -#: parser/parse_utilcmd.c:4474 +#: parser/parse_utilcmd.c:4599 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "指定した値は列\"%s\"の%s型に変換できません" @@ -18910,12 +19440,12 @@ msgstr "UESCAPE の後には単純な文字列リテラルが続かなければ msgid "invalid Unicode escape character" msgstr "不正なUnicodeエスケープ文字" -#: parser/parser.c:347 scan.l:1391 +#: parser/parser.c:347 scan.l:1385 #, c-format msgid "invalid Unicode escape value" msgstr "不正なUnicodeエスケープシーケンスの値" -#: parser/parser.c:494 scan.l:702 utils/adt/varlena.c:6640 +#: parser/parser.c:494 scan.l:702 utils/adt/varlena.c:6842 #, c-format msgid "invalid Unicode escape" msgstr "不正なUnicodeエスケープ" @@ -18925,7 +19455,7 @@ msgstr "不正なUnicodeエスケープ" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "Unicodeエスケープは\\XXXXまたは\\+XXXXXXでなければなりません。" -#: parser/parser.c:523 scan.l:663 scan.l:679 scan.l:695 utils/adt/varlena.c:6665 +#: parser/parser.c:523 scan.l:663 scan.l:679 scan.l:695 utils/adt/varlena.c:6867 #, c-format msgid "invalid Unicode surrogate pair" msgstr "不正なUnicodeサロゲートペア" @@ -18955,127 +19485,52 @@ msgstr "新しい法(除数)%1$dは既存のパーティション\"%3$s\"の法 msgid "The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\"." msgstr "新しい法(除数)%1$dは既存のパーティション\"%3$s\"の法である%2$dで割り切れません。" -#: partitioning/partbounds.c:3127 partitioning/partbounds.c:5202 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "リレーション\"%s\"に対して空の範囲境界が指定されました" -#: partitioning/partbounds.c:3129 partitioning/partbounds.c:5204 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "指定された下限%sは上限%sより大きいか同じです。" -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "パーティション\"%s\"はパーティション\"%s\"と重複があります" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"" msgstr "デフォルトパーティション\"%2$s\"の子テーブルであるためテーブル\"%1$s\"のスキャンをスキップします" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "remainder for hash partition must be an integer value greater than or equal to zero" msgstr "ハッシュパーティションの剰余は`0以上の整数でなければなりません" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\"はハッシュパーティションテーブルではありません" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" msgstr "パーティション列の数(%d)と与えられたキー値の数(%d)が一致していません" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "パーティションキーの列%dは%s型です、しかし与えられた値は%s型です" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"" msgstr "パーティションキーの列 %d は \"%s\"型です、しかし与えられた値は \"%s\"型です" -#: partitioning/partbounds.c:5038 -#, c-format -msgid "lower bound of partition \"%s\" conflicts with upper bound of previous partition \"%s\"" -msgstr "パーティション\"%s\"の下界が直前のパーティション\"%s\"の上界と衝突しています" - -#: partitioning/partbounds.c:5092 -#, c-format -msgid "new partition \"%s\" would overlap with another new partition \"%s\"" -msgstr "新しいパーティション\"%s\"は他の新しいパーティション\"%s\"と重複しています" - -#: partitioning/partbounds.c:5239 -#, c-format -msgid "lower bound of partition \"%s\" is not equal to lower bound of split partition" -msgstr "パーティション\"%s\"の下界が分割対象のパーティションの下界と一致していません" - -#: partitioning/partbounds.c:5251 -#, c-format -msgid "lower bound of partition \"%s\" is less than lower bound of split partition" -msgstr "パーティション\"%s\"の下界が分割対象のパーティションの下界よりも小さいです" - -#: partitioning/partbounds.c:5280 -#, c-format -msgid "upper bound of partition \"%s\" is not equal to upper bound of split partition" -msgstr "パーティション\"%s\"の上界が分割対象のパーティションの上界と一致していません" - -#: partitioning/partbounds.c:5292 -#, c-format -msgid "upper bound of partition \"%s\" is greater than upper bound of split partition" -msgstr "パーティション\"%s\"の上界が分割対象のパーティションの上界よりも大きいです" - -#: partitioning/partbounds.c:5364 -#, c-format -msgid "new partition \"%s\" cannot have this value because split partition does not have" -msgstr "分割対象のパーティションがその値を含んでいないため、新しいパーティション\"%s\"はこの値を持てません" - -#: partitioning/partbounds.c:5380 -#, c-format -msgid "new partition \"%s\" cannot have NULL value because split partition does not have" -msgstr "分割対象パーティションがNULLを含んでいないため、新しいパーティション\"%s\"はNULLを持てません" - -#: partitioning/partbounds.c:5390 -#, c-format -msgid "new partition \"%s\" would overlap with another (not split) partition \"%s\"" -msgstr "新しいパーティション\"%s\"は他の(分割されない)パーティション\"%s\"と重複しています" - -#: partitioning/partbounds.c:5530 -#, c-format -msgid "new partitions do not have value %s but split partition does" -msgstr "新しいパーティションには値%sが含まれていませんが、分割したパーティションには含まれています" - -#: partitioning/partbounds.c:5607 -#, c-format -msgid "DEFAULT partition should be one" -msgstr "DEFAULTパーティションは一つのみ存在できます" - -#: partitioning/partbounds.c:5623 -#, c-format -msgid "partition of hash-partitioned table cannot be split" -msgstr "ハッシュパーティションテーブルの子テーブルは分割できません" - -#: partitioning/partbounds.c:5677 -#, c-format -msgid "one partition in the list should be DEFAULT because split partition is DEFAULT" -msgstr "分割対象のパーティションがDEFAULTであるため、リスト中の一つのパーティションがDEFAULTである必要があります" - -#: partitioning/partbounds.c:5687 -#, c-format -msgid "new partition cannot be DEFAULT because DEFAULT partition already exists" -msgstr "DEFAULTパーティションがすでに存在するため、新しいパーティションをDEFAULTにはできません" - -#: partitioning/partbounds.c:5746 -#, c-format -msgid "name \"%s\" is already used" -msgstr "名前\"%s\"はすでに使用されています" - -#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 port/sysv_sema.c:323 port/sysv_shmem.c:717 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "データディレクトリ\"%s\"のstatに失敗しました: %m" @@ -19142,27 +19597,27 @@ msgstr "このプラットフォームではヒュージページをサポート msgid "huge pages not supported with the current \"shared_memory_type\" setting" msgstr "ヒュージページは現在の\"shared_memory_type\"の設定ではサポートされません" -#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1347 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1406 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "既存の共有メモリブロック(キー%lu、ID %lu)がまだ使用中です" -#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1349 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1408 #, c-format msgid "Terminate any old server processes associated with data directory \"%s\"." msgstr "データディレクトリ \"%s\". に対応する古いサーバープロセスをすべて終了させてください。" -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "セマフォを作成できませんでした: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "失敗したシステムコールはsemget(%lu, %d, 0%o)です。" -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its \"max_connections\" parameter.\n" @@ -19171,7 +19626,7 @@ msgstr "" "このエラーは、ディスクが足りなくなったことを意味していません。この原因はセマフォセット数が上限(SEMMNI)に達したか、またはシステム全体でのセマフォ数を上限まで(SEMMNS)を使いきるような場合です。対処としては、対応するカーネルのパラメータを増やす必要があります。もしくは PostgreSQLの\"max_connections\"設定をを減らすことで、消費するセマフォの数を減らしてください。\n" "PostgreSQL向けの共有メモリ設定に関する詳細情報は、PostgreSQL のドキュメントに記載されています。" -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details." msgstr "" @@ -19295,385 +19750,400 @@ msgstr "失敗したシステムコールはMapViewOfFileExです。" msgid "Failed system call was MapViewOfFileEx." msgstr "失敗したシステムコールはMapViewOfFileExです。" -#: postmaster/autovacuum.c:686 +#: postmaster/autovacuum.c:693 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "自動VACUUMワーカーの起動に時間がかかりすぎています; キャンセルしました" -#: postmaster/autovacuum.c:2199 +#: postmaster/autovacuum.c:2221 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "自動VACUUM: 孤立した一時テーブル\"%s.%s.%s\"を削除します" -#: postmaster/autovacuum.c:2435 +#: postmaster/autovacuum.c:2457 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "テーブル\"%s.%s.%s\"に対する自動VACUUM" -#: postmaster/autovacuum.c:2438 +#: postmaster/autovacuum.c:2460 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "テーブル\"%s.%s.%s\"に対する自動ANALYZE" -#: postmaster/autovacuum.c:2632 +#: postmaster/autovacuum.c:2654 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "リレーション\"%s.%s.%s\"の作業エントリを処理しています" -#: postmaster/autovacuum.c:3250 +#: postmaster/autovacuum.c:3312 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "誤設定のため自動VACUUMが起動できません" -#: postmaster/autovacuum.c:3251 +#: postmaster/autovacuum.c:3313 #, c-format msgid "Enable the \"track_counts\" option." msgstr "\"track_counts\"オプションを有効にしてください。" +#: postmaster/autovacuum.c:3435 +#, c-format +msgid "\"autovacuum_max_workers\" (%d) should be less than or equal to \"autovacuum_worker_slots\" (%d)" +msgstr "\"autovacuum_max_workers\" (%d) は \"autovacuum_worker_slots\" (%d) 以下でなければなりません" + +#: postmaster/autovacuum.c:3437 +#, c-format +msgid "The server will only start up to \"autovacuum_worker_slots\" (%d) autovacuum workers at a given time." +msgstr "このサーバーは、同時に最大 \"autovacuum_worker_slots\" (%d) プロセスの自動バキュームワーカーを起動します。" + #: postmaster/bgworker.c:260 #, c-format -msgid "inconsistent background worker state (max_worker_processes=%d, total_slots=%d)" -msgstr "バックグラウンドワーカー状態の矛盾 (max_worker_processes=%d, total_slots=%d)" +msgid "inconsistent background worker state (\"max_worker_processes\"=%d, total slots=%d)" +msgstr "バックグラウンドワーカー状態の不整合 (\"max_worker_processes\"=%d, スロット総数=%d)" -#: postmaster/bgworker.c:651 +#: postmaster/bgworker.c:645 #, c-format msgid "background worker \"%s\": background workers without shared memory access are not supported" msgstr "バックグラウンドワーカー\"%s\": 共有メモリアクセスを伴わないバックグラウンドワーカーはサポートされません" -#: postmaster/bgworker.c:662 +#: postmaster/bgworker.c:656 #, c-format msgid "background worker \"%s\": cannot request database access if starting at postmaster start" msgstr "バックグラウンドワーカー\"%s\": postmaster起動中に起動している場合にはデータベースアクセスを要求することはできません" -#: postmaster/bgworker.c:676 +#: postmaster/bgworker.c:670 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "バックグラウンドワーカー\"%s\": 不正な再起動間隔" -#: postmaster/bgworker.c:691 +#: postmaster/bgworker.c:685 #, c-format msgid "background worker \"%s\": parallel workers may not be configured for restart" msgstr "バックグラウンドワーカー\"%s\": パラレルワーカーは再起動するように設定してはいけません" -#: postmaster/bgworker.c:715 tcop/postgres.c:3285 +#: postmaster/bgworker.c:709 tcop/postgres.c:3345 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "管理者コマンドによりバックグラウンドワーカー\"%s\"を終了しています" -#: postmaster/bgworker.c:888 +#: postmaster/bgworker.c:868 postmaster/bgworker.c:902 +#, c-format +msgid "database connection requirement not indicated during registration" +msgstr "登録時にデータベース接続の必要性が示されていません" + +#: postmaster/bgworker.c:878 postmaster/bgworker.c:912 +#, c-format +msgid "invalid processing mode in background worker" +msgstr "バックグラウンドワーカー内の不正な処理モード" + +#: postmaster/bgworker.c:965 #, c-format msgid "background worker \"%s\": must be registered in \"shared_preload_libraries\"" msgstr "バックグラウンドワーカー\"%s\": \"shared_preload_libraries\"に登録されていなければなりません" -#: postmaster/bgworker.c:911 +#: postmaster/bgworker.c:988 #, c-format msgid "background worker \"%s\": only dynamic background workers can request notification" msgstr "バックグラウンドワーカー\"%s\": 動的バックグラウンドワーカーのみが通知を要求できます" -#: postmaster/bgworker.c:926 +#: postmaster/bgworker.c:1003 #, c-format msgid "too many background workers" msgstr "バックグラウンドワーカーが多すぎます" -#: postmaster/bgworker.c:927 +#: postmaster/bgworker.c:1004 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "Up to %d background workers can be registered with the current settings." msgstr[0] "現在の設定では最大%dのバックグラウンドワーカーを登録することができます。" -#: postmaster/bgworker.c:931 +#: postmaster/bgworker.c:1008 postmaster/checkpointer.c:459 #, c-format -msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "設定パラメータ\"max_worker_processes\"を増やすことを検討してください。" +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "設定パラメータ\"%s\"を増やすことを検討してください。" -#: postmaster/checkpointer.c:441 +#: postmaster/checkpointer.c:455 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" msgstr[0] "チェックポイントの発生周期が短すぎます(%d秒間隔)" -#: postmaster/checkpointer.c:445 -#, c-format -msgid "Consider increasing the configuration parameter \"%s\"." -msgstr "設定パラメータ\"%s\"を増やすことを検討してください。" - -#: postmaster/checkpointer.c:1067 +#: postmaster/checkpointer.c:1125 #, c-format msgid "checkpoint request failed" msgstr "チェックポイント要求が失敗しました" -#: postmaster/checkpointer.c:1068 +#: postmaster/checkpointer.c:1126 #, c-format msgid "Consult recent messages in the server log for details." msgstr "詳細はサーバーログの最近のメッセージを調査してください" -#: postmaster/launch_backend.c:369 +#: postmaster/launch_backend.c:395 #, c-format msgid "could not execute server process \"%s\": %m" msgstr "サーバープロセス\"%s\"を実行できませんでした: %m" -#: postmaster/launch_backend.c:422 +#: postmaster/launch_backend.c:449 #, c-format msgid "could not create backend parameter file mapping: error code %lu" msgstr "バックエンドパラメータファイルのファイルマッピングを作成できませんでした: エラーコード%lu" -#: postmaster/launch_backend.c:430 +#: postmaster/launch_backend.c:457 #, c-format msgid "could not map backend parameter memory: error code %lu" msgstr "バックエンドパラメータのメモリをマップできませんでした: エラーコード %lu" -#: postmaster/launch_backend.c:447 +#: postmaster/launch_backend.c:474 #, c-format msgid "subprocess command line too long" msgstr "サブプロセスのコマンドラインが長すぎます" -#: postmaster/launch_backend.c:465 +#: postmaster/launch_backend.c:492 #, c-format msgid "CreateProcess() call failed: %m (error code %lu)" msgstr "CreateProcess() の呼び出しが失敗しました: %m (エラーコード %lu)" -#: postmaster/launch_backend.c:492 +#: postmaster/launch_backend.c:521 #, c-format msgid "could not unmap view of backend parameter file: error code %lu" msgstr "バックエンドパラメータファイルのビューをアンマップできませんでした: エラーコード %lu" -#: postmaster/launch_backend.c:496 +#: postmaster/launch_backend.c:525 #, c-format msgid "could not close handle to backend parameter file: error code %lu" msgstr "バックエンドパラメータファイルのハンドルをクローズできませんでした: エラーコード%lu" -#: postmaster/launch_backend.c:518 +#: postmaster/launch_backend.c:547 #, c-format msgid "giving up after too many tries to reserve shared memory" msgstr "共有メモリの確保のリトライ回数が多すぎるため中断します" -#: postmaster/launch_backend.c:519 +#: postmaster/launch_backend.c:548 #, c-format msgid "This might be caused by ASLR or antivirus software." msgstr "これはASLRまたはアンチウイルスソフトウェアが原因である可能性があります。" -#: postmaster/launch_backend.c:817 +#: postmaster/launch_backend.c:854 #, c-format msgid "could not duplicate socket %d for use in backend: error code %d" msgstr "バックエンドで使用するためにソケット%dを複製できませんでした: エラーコード %d" -#: postmaster/launch_backend.c:849 +#: postmaster/launch_backend.c:886 #, c-format msgid "could not create inherited socket: error code %d\n" msgstr "継承したソケットを作成できませんでした: エラーコード %d\n" -#: postmaster/launch_backend.c:878 +#: postmaster/launch_backend.c:915 #, c-format msgid "could not open backend variables file \"%s\": %m\n" msgstr "バックエンド変数ファイル\"%s\"をオープンできませんでした: %m\n" -#: postmaster/launch_backend.c:884 +#: postmaster/launch_backend.c:921 #, c-format msgid "could not read from backend variables file \"%s\": %m\n" msgstr "バックエンド変数ファイル\"%s\"から読み込めませんでした: %m\n" -#: postmaster/launch_backend.c:895 +#: postmaster/launch_backend.c:932 #, c-format msgid "could not read startup data from backend variables file \"%s\": %m\n" msgstr "バックエンド変数ファイル\"%s\"から起動データ読み込めませんでした: %m\n" -#: postmaster/launch_backend.c:907 +#: postmaster/launch_backend.c:944 #, c-format msgid "could not remove file \"%s\": %m\n" msgstr "ファイル\"%s\"を削除できませんでした: %m\n" -#: postmaster/launch_backend.c:923 +#: postmaster/launch_backend.c:960 #, c-format msgid "could not map view of backend variables: error code %lu\n" msgstr "バックエンド変数のビューをマップできませんでした: エラーコード %lu\n" -#: postmaster/launch_backend.c:942 +#: postmaster/launch_backend.c:979 #, c-format msgid "could not unmap view of backend variables: error code %lu\n" msgstr "バックエンド変数のビューをアンマップできませんでした: エラーコード %lu\n" -#: postmaster/launch_backend.c:949 +#: postmaster/launch_backend.c:986 #, c-format msgid "could not close handle to backend parameter variables: error code %lu\n" msgstr "バックエンドパラメータ変数のハンドルをクローズできませんでした: エラーコード%lu\n" -#: postmaster/pgarch.c:428 +#: postmaster/pgarch.c:429 #, c-format msgid "\"archive_mode\" enabled, yet archiving is not configured" msgstr "\"archive_mode\"は有効ですが、アーカイブ方法が設定されていません" -#: postmaster/pgarch.c:452 +#: postmaster/pgarch.c:453 #, c-format msgid "removed orphan archive status file \"%s\"" msgstr "孤立したアーカイブステータスファイル\"%s\"を削除しました" -#: postmaster/pgarch.c:462 +#: postmaster/pgarch.c:463 #, c-format msgid "removal of orphan archive status file \"%s\" failed too many times, will try again later" msgstr "孤立したアーカイブステータスファイル\"%s\"の削除の失敗回数が上限を超えました、あとでリトライします" -#: postmaster/pgarch.c:498 +#: postmaster/pgarch.c:499 #, c-format msgid "archiving write-ahead log file \"%s\" failed too many times, will try again later" msgstr "先行書き込みログファイル\"%s\"のアーカイブ処理の失敗回数が超過しました、後で再度試します" -#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 +#: postmaster/pgarch.c:885 postmaster/pgarch.c:924 #, c-format msgid "both \"archive_command\" and \"archive_library\" set" msgstr "\"archive_command\"と\"archive_library\"が両方設定されています" -#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 +#: postmaster/pgarch.c:886 postmaster/pgarch.c:925 #, c-format msgid "Only one of \"archive_command\", \"archive_library\" may be set." msgstr "\"archive_command\"と\"archive_library\"のいずれか一方のみ設定できます。" -#: postmaster/pgarch.c:897 +#: postmaster/pgarch.c:903 #, c-format msgid "restarting archiver process because value of \"archive_library\" was changed" msgstr "\"archive_library\"の設定が変更されたためアーカイバプロセスを再起動します" -#: postmaster/pgarch.c:934 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules have to define the symbol %s" msgstr "アーカイブモジュールはシンボル%sを定義しなくてはなりません" -#: postmaster/pgarch.c:940 +#: postmaster/pgarch.c:946 #, c-format msgid "archive modules must register an archive callback" msgstr "アーカイブモジュールはアーカイブコールバックを登録しなくてはなりません" -#: postmaster/postmaster.c:661 +#: postmaster/postmaster.c:678 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: -fオプションに対する不正な引数: \"%s\"\n" -#: postmaster/postmaster.c:734 +#: postmaster/postmaster.c:751 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: -tオプションに対する不正な引数: \"%s\"\n" -#: postmaster/postmaster.c:757 +#: postmaster/postmaster.c:774 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: 不正な引数: \"%s\"\n" -#: postmaster/postmaster.c:825 +#: postmaster/postmaster.c:842 #, c-format msgid "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" msgstr "%s: \"superuser_reserved_connections\" (%d)と\"reserved_connections\" (%d)との和は \"max_connections\" (%d)より小さくなければなりません\n" -#: postmaster/postmaster.c:833 +#: postmaster/postmaster.c:850 #, c-format msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" msgstr "\"wal_level\"が\"minimal\"の時はWALアーカイブは有効にできません" -#: postmaster/postmaster.c:836 +#: postmaster/postmaster.c:853 #, c-format msgid "WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be \"replica\" or \"logical\"" msgstr "WALストリーミング(\"max_wal_senders\" > 0)を行うには wal_levelを\"replica\"または\"logical\"にする必要があります" -#: postmaster/postmaster.c:839 +#: postmaster/postmaster.c:856 #, c-format msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" msgstr "\"wal_level\"が\"minimal\"の時はWALは集約できません" -#: postmaster/postmaster.c:847 +#: postmaster/postmaster.c:864 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "%s: データトークンテーブルが不正です、修復してください\n" -#: postmaster/postmaster.c:1004 +#: postmaster/postmaster.c:1025 #, c-format msgid "could not create I/O completion port for child queue" msgstr "子キュー向けのI/O終了ポートを作成できませんでした" -#: postmaster/postmaster.c:1069 +#: postmaster/postmaster.c:1091 #, c-format msgid "ending log output to stderr" msgstr "標準エラー出力へのログ出力を終了しています" -#: postmaster/postmaster.c:1070 +#: postmaster/postmaster.c:1092 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "この後のログ出力はログ配送先\"%s\"に出力されます。" -#: postmaster/postmaster.c:1081 +#: postmaster/postmaster.c:1103 #, c-format msgid "starting %s" msgstr "%s を起動しています" -#: postmaster/postmaster.c:1143 +#: postmaster/postmaster.c:1165 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "\"%s\"に関する監視用ソケットを作成できませんでした" -#: postmaster/postmaster.c:1149 +#: postmaster/postmaster.c:1171 #, c-format msgid "could not create any TCP/IP sockets" msgstr "TCP/IPソケットを作成できませんでした" -#: postmaster/postmaster.c:1181 +#: postmaster/postmaster.c:1203 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "DNSServiceRegister()が失敗しました: エラーコード %ld" -#: postmaster/postmaster.c:1234 +#: postmaster/postmaster.c:1256 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "ディレクトリ\"%s\"においてUnixドメインソケットを作成できませんでした" -#: postmaster/postmaster.c:1240 +#: postmaster/postmaster.c:1262 #, c-format msgid "could not create any Unix-domain sockets" msgstr "Unixドメインソケットを作成できませんでした" -#: postmaster/postmaster.c:1251 +#: postmaster/postmaster.c:1273 #, c-format msgid "no socket created for listening" msgstr "監視用に作成するソケットはありません" -#: postmaster/postmaster.c:1282 +#: postmaster/postmaster.c:1304 #, c-format msgid "%s: could not change permissions of external PID file \"%s\": %m\n" msgstr "%s: 外部PIDファイル\"%s\"の権限を変更できませんでした: %m\n" -#: postmaster/postmaster.c:1286 +#: postmaster/postmaster.c:1308 #, c-format msgid "%s: could not write external PID file \"%s\": %m\n" msgstr "%s: 外部PIDファイル\"%s\"に書き込めませんでした: %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1336 utils/init/postinit.c:225 #, c-format msgid "could not load %s" msgstr "%s\"をロードできませんでした" -#: postmaster/postmaster.c:1340 +#: postmaster/postmaster.c:1364 #, c-format msgid "postmaster became multithreaded during startup" -msgstr "postmasterは起動値処理中はマルチスレッドで動作します" +msgstr "postmasterは起動処理中はマルチスレッドで動作します" -#: postmaster/postmaster.c:1341 +#: postmaster/postmaster.c:1365 postmaster/postmaster.c:3661 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "LC_ALL環境変数を使用可能なロケールに設定してください。" -#: postmaster/postmaster.c:1440 +#: postmaster/postmaster.c:1468 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: 自身の実行ファイルのパスが特定できません" -#: postmaster/postmaster.c:1447 +#: postmaster/postmaster.c:1475 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: 一致するpostgres実行ファイルがありませんでした" -#: postmaster/postmaster.c:1470 utils/misc/tzparser.c:341 +#: postmaster/postmaster.c:1498 utils/misc/tzparser.c:342 #, c-format msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location." msgstr "これは、PostgreSQLのインストールが不完全であるかまたは、ファイル\"%s\"が本来の場所からなくなってしまったことを示しています。" -#: postmaster/postmaster.c:1497 +#: postmaster/postmaster.c:1525 #, c-format msgid "" "%s: could not find the database system\n" @@ -19685,472 +20155,467 @@ msgstr "" "ファイル\"%s\"をオープンできませんでした: %m\n" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1787 +#: postmaster/postmaster.c:1762 #, c-format msgid "issuing %s to recalcitrant children" msgstr "手に負えない子プロセスに%sを送出します" -#: postmaster/postmaster.c:1809 +#: postmaster/postmaster.c:1784 #, c-format msgid "performing immediate shutdown because data directory lock file is invalid" msgstr "データディレクトリのロックファイルが不正なため、即時シャットダウンを実行中です" -#: postmaster/postmaster.c:1872 -#, c-format -msgid "wrong key in cancel request for process %d" -msgstr "プロセス%dに対するキャンセル要求においてキーが間違っています" - -#: postmaster/postmaster.c:1884 -#, c-format -msgid "PID %d in cancel request did not match any process" -msgstr "キャンセル要求内のPID %dがどのプロセスにも一致しません" - -#: postmaster/postmaster.c:2105 +#: postmaster/postmaster.c:2004 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "SIGHUPを受け取りました。設定ファイルをリロードしています" #. translator: %s is a configuration file -#: postmaster/postmaster.c:2133 postmaster/postmaster.c:2137 +#: postmaster/postmaster.c:2012 postmaster/postmaster.c:2016 #, c-format msgid "%s was not reloaded" msgstr "%s は再読み込みされていません" -#: postmaster/postmaster.c:2147 +#: postmaster/postmaster.c:2026 #, c-format msgid "SSL configuration was not reloaded" msgstr "SSL設定は再読み込みされていません" -#: postmaster/postmaster.c:2233 +#: postmaster/postmaster.c:2112 #, c-format msgid "received smart shutdown request" msgstr "スマートシャットダウン要求を受け取りました" -#: postmaster/postmaster.c:2274 +#: postmaster/postmaster.c:2153 #, c-format msgid "received fast shutdown request" msgstr "高速シャットダウン要求を受け取りました" -#: postmaster/postmaster.c:2292 +#: postmaster/postmaster.c:2171 #, c-format msgid "aborting any active transactions" msgstr "活動中の全トランザクションをアボートしています" -#: postmaster/postmaster.c:2316 +#: postmaster/postmaster.c:2195 #, c-format msgid "received immediate shutdown request" msgstr "即時シャットダウン要求を受け取りました" -#: postmaster/postmaster.c:2388 +#: postmaster/postmaster.c:2270 #, c-format msgid "shutdown at recovery target" msgstr "リカバリ目標でシャットダウンします" -#: postmaster/postmaster.c:2406 postmaster/postmaster.c:2442 +#: postmaster/postmaster.c:2288 postmaster/postmaster.c:2324 msgid "startup process" msgstr "起動プロセス" -#: postmaster/postmaster.c:2409 +#: postmaster/postmaster.c:2291 #, c-format msgid "aborting startup due to startup process failure" msgstr "起動プロセスの失敗のため起動を中断しています" -#: postmaster/postmaster.c:2484 +#: postmaster/postmaster.c:2347 #, c-format msgid "database system is ready to accept connections" msgstr "データベースシステムの接続受け付け準備が整いました" -#: postmaster/postmaster.c:2505 +#: postmaster/postmaster.c:2369 msgid "background writer process" msgstr "バックグランドライタプロセス" -#: postmaster/postmaster.c:2552 +#: postmaster/postmaster.c:2402 msgid "checkpointer process" msgstr "チェックポイント処理プロセス" -#: postmaster/postmaster.c:2568 +#: postmaster/postmaster.c:2419 msgid "WAL writer process" msgstr "WALライタプロセス" -#: postmaster/postmaster.c:2583 +#: postmaster/postmaster.c:2435 msgid "WAL receiver process" msgstr "WAL 受信プロセス" -#: postmaster/postmaster.c:2597 +#: postmaster/postmaster.c:2450 msgid "WAL summarizer process" msgstr "WAL集約プロセス" -#: postmaster/postmaster.c:2612 +#: postmaster/postmaster.c:2466 msgid "autovacuum launcher process" msgstr "自動VACUUM起動プロセス" -#: postmaster/postmaster.c:2630 +#: postmaster/postmaster.c:2482 msgid "archiver process" msgstr "アーカイバプロセス" -#: postmaster/postmaster.c:2643 +#: postmaster/postmaster.c:2497 msgid "system logger process" msgstr "システムログ取得プロセス" -#: postmaster/postmaster.c:2660 +#: postmaster/postmaster.c:2515 msgid "slot sync worker process" msgstr "スロット同期ワーカープロセス" -#: postmaster/postmaster.c:2716 +#: postmaster/postmaster.c:2523 utils/init/miscinit.c:297 +msgid "io worker" +msgstr "IOワーカー" + +#: postmaster/postmaster.c:2545 postmaster/postmaster.c:2547 +msgid "untracked child process" +msgstr "追跡されていない子プロセス" + +#: postmaster/postmaster.c:2580 #, c-format msgid "background worker \"%s\"" msgstr "バックグラウンドワーカー\"%s\"" -#: postmaster/postmaster.c:2795 postmaster/postmaster.c:2815 postmaster/postmaster.c:2822 postmaster/postmaster.c:2840 -msgid "server process" -msgstr "サーバープロセス" - -#: postmaster/postmaster.c:2894 +#: postmaster/postmaster.c:2797 #, c-format msgid "terminating any other active server processes" msgstr "他の活動中のサーバープロセスを終了しています" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3081 +#: postmaster/postmaster.c:2830 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d)は終了コード%dで終了しました" -#: postmaster/postmaster.c:3083 postmaster/postmaster.c:3095 postmaster/postmaster.c:3105 postmaster/postmaster.c:3116 +#: postmaster/postmaster.c:2832 postmaster/postmaster.c:2844 postmaster/postmaster.c:2854 postmaster/postmaster.c:2865 #, c-format msgid "Failed process was running: %s" msgstr "失敗したプロセスが実行していました: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3092 +#: postmaster/postmaster.c:2841 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d)は例外%Xで終了しました" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3102 +#: postmaster/postmaster.c:2851 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d)はシグナル%dで終了しました: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3114 +#: postmaster/postmaster.c:2863 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d)は認識できないステータス%dで終了しました" -#: postmaster/postmaster.c:3330 +#: postmaster/postmaster.c:3154 #, c-format msgid "abnormal database system shutdown" msgstr "データベースシステムは異常にシャットダウンしました" -#: postmaster/postmaster.c:3356 +#: postmaster/postmaster.c:3180 #, c-format msgid "shutting down due to startup process failure" msgstr "起動プロセスの失敗のためシャットダウンしています" -#: postmaster/postmaster.c:3362 +#: postmaster/postmaster.c:3186 #, c-format msgid "shutting down because \"restart_after_crash\" is off" msgstr "\"restart_after_crash\"がoffであるためシャットダウンします" -#: postmaster/postmaster.c:3374 +#: postmaster/postmaster.c:3198 #, c-format msgid "all server processes terminated; reinitializing" msgstr "全てのサーバープロセスが終了しました: 再初期化しています" -#: postmaster/postmaster.c:3573 postmaster/postmaster.c:3983 postmaster/postmaster.c:4372 -#, c-format -msgid "could not generate random cancel key" -msgstr "ランダムなキャンセルキーを生成できませんでした" - -#: postmaster/postmaster.c:3606 +#: postmaster/postmaster.c:3591 #, c-format msgid "could not fork new process for connection: %m" msgstr "接続用の新しいプロセスをforkできませんでした: %m" -#: postmaster/postmaster.c:3648 +#: postmaster/postmaster.c:3626 msgid "could not fork new process for connection: " msgstr "接続用の新しいプロセスをforkできませんでした" -#: postmaster/postmaster.c:3682 +#: postmaster/postmaster.c:3660 #, c-format -msgid "Please report this to <%s>." -msgstr "これを<%s>まで報告してください。" +msgid "postmaster became multithreaded" +msgstr "postmasterがマルチスレッド動作になっています" -#: postmaster/postmaster.c:3750 +#: postmaster/postmaster.c:3738 #, c-format msgid "database system is ready to accept read-only connections" msgstr "データベースシステムはリードオンリー接続の受け付け準備ができました" -#: postmaster/postmaster.c:3933 -#, c-format -msgid "could not fork \"%s\" process: %m" -msgstr "\"%s\"プロセスをforkできませんでした: %m" - -#: postmaster/postmaster.c:4171 postmaster/postmaster.c:4205 +#: postmaster/postmaster.c:3839 #, c-format -msgid "database connection requirement not indicated during registration" -msgstr "登録時にデータベース接続の必要性が示されていません" +msgid "WAL was shut down unexpectedly" +msgstr "WALが予期せずシャットダウンされました。" -#: postmaster/postmaster.c:4181 postmaster/postmaster.c:4215 +#: postmaster/postmaster.c:3964 #, c-format -msgid "invalid processing mode in background worker" -msgstr "バックグラウンドワーカー内の不正な処理モード" +msgid "no slot available for new autovacuum worker process" +msgstr "新しい自動VACUUMワーカープロセスに割り当て可能なスロットがありません" -#: postmaster/postmaster.c:4275 +#: postmaster/postmaster.c:3979 #, c-format -msgid "could not fork background worker process: %m" -msgstr "バックグランドワーカープロセスをforkできませんでした: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "\"%s\"プロセスをforkできませんでした: %m" -#: postmaster/postmaster.c:4358 +#: postmaster/postmaster.c:4138 #, c-format msgid "no slot available for new background worker process" msgstr "新しいバックグラウンドワーカープロセスに割り当て可能なスロットがありません" -#: postmaster/postmaster.c:4621 +#: postmaster/postmaster.c:4156 +#, c-format +msgid "could not fork background worker process: %m" +msgstr "バックグランドワーカープロセスをforkできませんでした: %m" + +#: postmaster/postmaster.c:4489 #, c-format msgid "could not read exit code for process\n" msgstr "子プロセスの終了コードの読み込みができませんでした\n" -#: postmaster/postmaster.c:4663 +#: postmaster/postmaster.c:4531 #, c-format msgid "could not post child completion status\n" msgstr "個プロセスの終了コードを投稿できませんでした\n" -#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 +#: postmaster/syslogger.c:527 postmaster/syslogger.c:1172 #, c-format msgid "could not read from logger pipe: %m" msgstr "ロガーパイプから読み取れませんでした: %m" -#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 +#: postmaster/syslogger.c:626 postmaster/syslogger.c:640 #, c-format msgid "could not create pipe for syslog: %m" msgstr "syslog用のパイプを作成できませんでした: %m" -#: postmaster/syslogger.c:712 +#: postmaster/syslogger.c:711 #, c-format msgid "could not fork system logger: %m" msgstr "システムロガーをforkできませんでした: %m" -#: postmaster/syslogger.c:731 +#: postmaster/syslogger.c:730 #, c-format msgid "redirecting log output to logging collector process" msgstr "ログ出力をログ収集プロセスにリダイレクトしています" -#: postmaster/syslogger.c:732 +#: postmaster/syslogger.c:731 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "ここからのログ出力はディレクトリ\"%s\"に現れます。" -#: postmaster/syslogger.c:740 +#: postmaster/syslogger.c:739 #, c-format msgid "could not redirect stdout: %m" msgstr "標準出力にリダイレクトできませんでした: %m" -#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 +#: postmaster/syslogger.c:744 postmaster/syslogger.c:761 #, c-format msgid "could not redirect stderr: %m" msgstr "標準エラー出力にリダイレクトできませんでした: %m" -#: postmaster/syslogger.c:1128 +#: postmaster/syslogger.c:1127 #, c-format msgid "could not write to log file: %m\n" msgstr "ログファイルに書き込めませんでした: %m\n" -#: postmaster/syslogger.c:1246 +#: postmaster/syslogger.c:1247 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ロックファイル\"%s\"をオープンできませんでした: %m" -#: postmaster/syslogger.c:1336 +#: postmaster/syslogger.c:1337 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "自動ローテーションを無効にしています(再度有効にするにはSIGHUPを使用してください)" -#: postmaster/walsummarizer.c:384 +#: postmaster/walsummarizer.c:743 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "WAL集計が進んでいません" + +#: postmaster/walsummarizer.c:744 +#, c-format +msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." +msgstr "集計は%X/%Xまで進んでいる必要がありますが、ディスク上では%X/%X、メモリ上では%X/%Xよりあとまで進んでいません。" + +#: postmaster/walsummarizer.c:758 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "%3$ld秒経過しましたが、WAL集計が%1$X/%2$Xに到達するのをまだ待ってます" + +#: postmaster/walsummarizer.c:763 #, c-format -msgid "switch point from TLI %u to TLI %u is at %X/%X" -msgstr "TLI %uから%uへの切り替え点は%X/%X" +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "集計がディスク上で%X/%X、メモリ上で%X/%Xに到達しました。" -#: postmaster/walsummarizer.c:885 +#: postmaster/walsummarizer.c:1007 #, c-format msgid "could not find a valid record after %X/%X" msgstr "%X/%Xの後に有効なレコードが見つかりませんでした" -#: postmaster/walsummarizer.c:930 +#: postmaster/walsummarizer.c:1052 #, c-format msgid "could not read WAL from timeline %u at %X/%X: %s" msgstr "%X/%Xでタイムライン%uのWALを読み取れませんでした: %s" -#: postmaster/walsummarizer.c:936 +#: postmaster/walsummarizer.c:1058 #, c-format msgid "could not read WAL from timeline %u at %X/%X" msgstr "%X/%Xでタイムライン%uのWALを読み取れませんでした" -#: postmaster/walsummarizer.c:1077 -#, c-format -msgid "summarized WAL on TLI %u from %X/%X to %X/%X" -msgstr "TLI %uの%X/%Xから%X/%Xまで集計しました" - -#: postmaster/walsummarizer.c:1385 -#, c-format -msgid "timeline %u became historic, can read up to %X/%X" -msgstr "タイムライン%uは過去のものになりました、%X/%Xまでは読み取り可能です" - #: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "正規表現で使用する照合規則を特定できませんでした" -#: regex/regc_pg_locale.c:262 +#: regex/regc_pg_locale.c:265 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "非決定的照合順序は正規表現ではサポートされていません" -#: repl_gram.y:318 repl_gram.y:359 +#: repl_gram.y:322 repl_gram.y:363 #, c-format msgid "invalid timeline %u" msgstr "タイムライン%uは不正です" -#: repl_scanner.l:154 +#: repl_scanner.l:160 msgid "invalid streaming start location" msgstr "不正なストリーミング開始位置" -#: replication/libpqwalreceiver/libpqwalreceiver.c:267 replication/libpqwalreceiver/libpqwalreceiver.c:358 +#: replication/libpqwalreceiver/libpqwalreceiver.c:230 replication/libpqwalreceiver/libpqwalreceiver.c:322 #, c-format msgid "password is required" msgstr "パスワードが必要です" -#: replication/libpqwalreceiver/libpqwalreceiver.c:268 +#: replication/libpqwalreceiver/libpqwalreceiver.c:231 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "非スーパーユーザーはサーバーがパスワードを要求してこない場合は接続できません。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:269 +#: replication/libpqwalreceiver/libpqwalreceiver.c:232 #, c-format msgid "Target server's authentication method must be changed, or set password_required=false in the subscription parameters." msgstr "接続先サーバーの認証方式を変更するか、サブスクリプション属性でpassword_requiredをfalseに設定する必要があります。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:285 +#: replication/libpqwalreceiver/libpqwalreceiver.c:249 #, c-format msgid "could not clear search path: %s" msgstr "search_pathを消去できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:331 replication/libpqwalreceiver/libpqwalreceiver.c:517 +#: replication/libpqwalreceiver/libpqwalreceiver.c:295 replication/libpqwalreceiver/libpqwalreceiver.c:483 #, c-format msgid "invalid connection string syntax: %s" msgstr "不正な接続文字列の構文: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:359 +#: replication/libpqwalreceiver/libpqwalreceiver.c:323 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "非スーパーユーザーは接続文字列中でパスワードを指定する必要があります。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:386 +#: replication/libpqwalreceiver/libpqwalreceiver.c:350 #, c-format msgid "could not parse connection string: %s" msgstr "接続文字列をパースできませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:459 +#: replication/libpqwalreceiver/libpqwalreceiver.c:425 #, c-format msgid "could not receive database system identifier and timeline ID from the primary server: %s" msgstr "プライマリサーバーからデータベースシステムの識別子とタイムライン ID を受信できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:476 replication/libpqwalreceiver/libpqwalreceiver.c:763 +#: replication/libpqwalreceiver/libpqwalreceiver.c:442 replication/libpqwalreceiver/libpqwalreceiver.c:737 #, c-format msgid "invalid response from primary server" msgstr "プライマリサーバーからの応答が不正です" -#: replication/libpqwalreceiver/libpqwalreceiver.c:477 +#: replication/libpqwalreceiver/libpqwalreceiver.c:443 #, c-format msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields." msgstr "システムを識別できませんでした: 受信したのは%d行で%d列、期待していたのは%d行で%d以上の列でした。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:606 replication/libpqwalreceiver/libpqwalreceiver.c:613 replication/libpqwalreceiver/libpqwalreceiver.c:643 +#: replication/libpqwalreceiver/libpqwalreceiver.c:572 replication/libpqwalreceiver/libpqwalreceiver.c:579 replication/libpqwalreceiver/libpqwalreceiver.c:611 #, c-format msgid "could not start WAL streaming: %s" msgstr "WAL ストリーミングを開始できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:667 +#: replication/libpqwalreceiver/libpqwalreceiver.c:635 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "プライマリにストリーミングの終了メッセージを送信できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:690 +#: replication/libpqwalreceiver/libpqwalreceiver.c:659 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "ストリーミングの終了後の想定外の結果セット" -#: replication/libpqwalreceiver/libpqwalreceiver.c:705 +#: replication/libpqwalreceiver/libpqwalreceiver.c:675 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "ストリーミングCOPY終了中のエラー: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:715 +#: replication/libpqwalreceiver/libpqwalreceiver.c:686 #, c-format msgid "error reading result of streaming command: %s" msgstr "ストリーミングコマンドの結果読み取り中のエラー: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:724 replication/libpqwalreceiver/libpqwalreceiver.c:957 +#: replication/libpqwalreceiver/libpqwalreceiver.c:696 replication/libpqwalreceiver/libpqwalreceiver.c:832 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "CommandComplete後の想定外の結果: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:751 +#: replication/libpqwalreceiver/libpqwalreceiver.c:725 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "プライマリサーバーからタイムライン履歴ファイルを受信できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:764 +#: replication/libpqwalreceiver/libpqwalreceiver.c:738 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "2個のフィールドを持つ1個のタプルを期待していましたが、%2$d 個のフィールドを持つ %1$d 個のタプルを受信しました。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:920 replication/libpqwalreceiver/libpqwalreceiver.c:973 replication/libpqwalreceiver/libpqwalreceiver.c:980 +#: replication/libpqwalreceiver/libpqwalreceiver.c:793 replication/libpqwalreceiver/libpqwalreceiver.c:848 replication/libpqwalreceiver/libpqwalreceiver.c:855 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "WAL ストリームからデータを受信できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 +#: replication/libpqwalreceiver/libpqwalreceiver.c:875 #, c-format msgid "could not send data to WAL stream: %s" msgstr "WAL ストリームにデータを送信できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 +#: replication/libpqwalreceiver/libpqwalreceiver.c:978 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "レプリケーションスロット\"%s\"を作成できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1030 #, c-format msgid "could not alter replication slot \"%s\": %s" msgstr "レプリケーションスロット\"%s\"を変更できませんでした: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1064 #, c-format msgid "invalid query response" msgstr "不正な問い合わせ応答" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1065 #, c-format msgid "Expected %d fields, got %d fields." msgstr "%d個の列を期待していましたが、%d列を受信しました。" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1135 #, c-format msgid "the query interface requires a database connection" msgstr "クエリインタフェースの動作にはデータベースコネクションが必要です" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1169 msgid "empty query" msgstr "空の問い合わせ" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 msgid "unexpected pipeline mode" msgstr "想定されていないパイプラインモード" @@ -20188,40 +20653,149 @@ msgstr "共有メモリキューにデータを送出できませんでした" msgid "logical replication apply worker will serialize the remaining changes of remote transaction %u to a file" msgstr "論理レプリケーションt起用ワーカーはリモートトランザクション%uの残りの変更をシリアライズしてファイルに格納します" -#: replication/logical/decode.c:177 replication/logical/logical.c:141 +#: replication/logical/conflict.c:126 #, c-format -msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" -msgstr "スタンバイ上で論理デコードを行うためにはプライマリ上で\"wal_level\" >= \"logical\"である必要があります" +msgid "conflict detected on relation \"%s.%s\": conflict=%s" +msgstr "リレーション\"%s.%s\"で衝突が検出されました: conflict=%s" -#: replication/logical/launcher.c:334 +#: replication/logical/conflict.c:223 #, c-format -msgid "cannot start logical replication workers when max_replication_slots = 0" -msgstr "max_replication_slots = 0 の時は論理レプリケーションワーカーは起動できません" +msgid "Key already exists in unique index \"%s\", modified locally in transaction %u at %s." +msgstr "ユニークインデックス\"%s\"にすでにキーが存在しており、トランザクション%uで%sにローカルに更新されています。" -#: replication/logical/launcher.c:427 +#: replication/logical/conflict.c:227 #, c-format -msgid "out of logical replication worker slots" -msgstr "論理レプリケーションワーカースロットは全て使用中です" +msgid "Key already exists in unique index \"%s\", modified by origin \"%s\" in transaction %u at %s." +msgstr "ユニークインデックス\"%s\"にすでにキーが存在しており、起源\"%s\"によってトランザクション%uで%sにに更新されています。" -#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 replication/slot.c:1524 storage/lmgr/lock.c:963 storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2804 storage/lmgr/lock.c:4189 storage/lmgr/lock.c:4254 storage/lmgr/lock.c:4604 storage/lmgr/predicate.c:2464 storage/lmgr/predicate.c:2479 storage/lmgr/predicate.c:3876 +#: replication/logical/conflict.c:239 #, c-format -msgid "You might need to increase \"%s\"." -msgstr "\"%s\"を大きくする必要があるかもしれません。" +msgid "Key already exists in unique index \"%s\", modified by a non-existent origin in transaction %u at %s." +msgstr "ユニークインデックス\"%s\"にすでにキーが存在しており、存在しない起源によってトランザクション%uで%sにに更新されています。" -#: replication/logical/launcher.c:513 +#: replication/logical/conflict.c:244 #, c-format -msgid "out of background worker slots" -msgstr "バックグラウンドワーカースロットが足りません" +msgid "Key already exists in unique index \"%s\", modified in transaction %u." +msgstr "ユニークインデックス\"%s\"にすでにキーが存在しており、トランザクション%uで更新されています。" -#: replication/logical/launcher.c:720 +#: replication/logical/conflict.c:251 #, c-format -msgid "logical replication worker slot %d is empty, cannot attach" -msgstr "論理レプリケーションワーカースロット%dが空いていないため接続できません" +msgid "Updating the row that was modified locally in transaction %u at %s." +msgstr "トランザクション%uで%sにローカルに更新された行の更新中。" -#: replication/logical/launcher.c:729 +#: replication/logical/conflict.c:254 #, c-format -msgid "logical replication worker slot %d is already used by another worker, cannot attach" -msgstr "論理レプリケーションワーカースロット%dが既に他のワーカーに使用されているため接続できません" +msgid "Updating the row that was modified by a different origin \"%s\" in transaction %u at %s." +msgstr "異なる起源”%s\"よってトランザクション%uで%sに更新された行の更新中。" + +#: replication/logical/conflict.c:259 +#, c-format +msgid "Updating the row that was modified by a non-existent origin in transaction %u at %s." +msgstr "存在しない起源よってトランザクション%uで%sに更新された行の更新中。" + +#: replication/logical/conflict.c:265 +msgid "Could not find the row to be updated." +msgstr "更新すべき行が見つかりませんでした。" + +#: replication/logical/conflict.c:270 +#, c-format +msgid "Deleting the row that was modified locally in transaction %u at %s." +msgstr "トランザクション%uで%sにローカルに更新された行の削除中。" + +#: replication/logical/conflict.c:273 +#, c-format +msgid "Deleting the row that was modified by a different origin \"%s\" in transaction %u at %s." +msgstr "異なる起源”%s\"よってトランザクション%uで%sに更新された行の削除中。" + +#: replication/logical/conflict.c:278 +#, c-format +msgid "Deleting the row that was modified by a non-existent origin in transaction %u at %s." +msgstr "存在しない起源よってトランザクション%uで%sに更新された行の削除中。" + +#: replication/logical/conflict.c:284 +msgid "Could not find the row to be deleted." +msgstr "削除すべき行が見つかりませんでした。" + +#: replication/logical/conflict.c:347 +#, c-format +msgid "Key %s" +msgstr "キー %s" + +#: replication/logical/conflict.c:364 +#, c-format +msgid "existing local tuple %s" +msgstr "存在するローカルタプル %s" + +#: replication/logical/conflict.c:369 +#, c-format +msgid "Existing local tuple %s" +msgstr "存在するローカルタプル %s" + +#: replication/logical/conflict.c:396 +#, c-format +msgid "remote tuple %s" +msgstr "リモートタプル %s" + +#: replication/logical/conflict.c:400 +#, c-format +msgid "Remote tuple %s" +msgstr "リモートタプル %s" + +#: replication/logical/conflict.c:434 +#, c-format +msgid "replica identity %s" +msgstr "複製識別 %s" + +#: replication/logical/conflict.c:435 +#, c-format +msgid "replica identity full %s" +msgstr "全列複製識別 %s" + +#: replication/logical/conflict.c:440 +#, c-format +msgid "Replica identity %s" +msgstr "複製識別 %s" + +#: replication/logical/conflict.c:441 +#, c-format +msgid "Replica identity full %s" +msgstr "全列複製識別 %s" + +#: replication/logical/decode.c:177 replication/logical/logical.c:141 +#, c-format +msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" +msgstr "スタンバイ上で論理デコードを行うためにはプライマリ上で\"wal_level\" >= \"logical\"である必要があります" + +#: replication/logical/launcher.c:331 +#, c-format +msgid "cannot start logical replication workers when \"max_active_replication_origins\"=0" +msgstr "\"max_active_replication_origins\"=0 の時は論理レプリケーションワーカーは起動できません" + +#: replication/logical/launcher.c:424 +#, c-format +msgid "out of logical replication worker slots" +msgstr "論理レプリケーションワーカースロットは全て使用中です" + +#. translator: %s is a GUC variable name +#: replication/logical/launcher.c:425 replication/logical/launcher.c:511 replication/slot.c:1556 replication/slot.c:1579 storage/lmgr/lock.c:1039 storage/lmgr/lock.c:1077 storage/lmgr/lock.c:2966 storage/lmgr/lock.c:4371 storage/lmgr/lock.c:4436 storage/lmgr/lock.c:4786 storage/lmgr/predicate.c:2479 storage/lmgr/predicate.c:2494 storage/lmgr/predicate.c:3891 +#, c-format +msgid "You might need to increase \"%s\"." +msgstr "\"%s\"を大きくする必要があるかもしれません。" + +#: replication/logical/launcher.c:510 +#, c-format +msgid "out of background worker slots" +msgstr "バックグラウンドワーカースロットが足りません" + +#: replication/logical/launcher.c:717 +#, c-format +msgid "logical replication worker slot %d is empty, cannot attach" +msgstr "論理レプリケーションワーカースロット%dが空いていないため接続できません" + +#: replication/logical/launcher.c:726 +#, c-format +msgid "logical replication worker slot %d is already used by another worker, cannot attach" +msgstr "論理レプリケーションワーカースロット%dが既に他のワーカーに使用されているため接続できません" #: replication/logical/logical.c:121 #, c-format @@ -20233,82 +20807,67 @@ msgstr "論理デコードを行うためには\"wal_level\" >= \"logical\" で msgid "logical decoding requires a database connection" msgstr "論理デコードを行うにはデータベース接続が必要です" -#: replication/logical/logical.c:364 replication/logical/logical.c:518 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "物理レプリケーションスロットを論理デコードに使用するとはできません" -#: replication/logical/logical.c:369 replication/logical/logical.c:528 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "レプリケーションスロット\"%s\"はこのデータベースでは作成されていません" -#: replication/logical/logical.c:376 +#: replication/logical/logical.c:377 #, c-format msgid "cannot create logical replication slot in transaction that has performed writes" msgstr "論理レプリケーションスロットは書き込みを行ったトランザクションの中で生成することはできません" -#: replication/logical/logical.c:539 +#: replication/logical/logical.c:540 #, c-format msgid "cannot use replication slot \"%s\" for logical decoding" msgstr "レプリケーションスロット\"%s\"は論理デコードには使用できません" -#: replication/logical/logical.c:541 +#: replication/logical/logical.c:542 replication/slot.c:828 replication/slot.c:863 #, c-format -msgid "This slot is being synchronized from the primary server." -msgstr "このスロットはプライマリサーバーからの同期中です。" +msgid "This replication slot is being synchronized from the primary server." +msgstr "このレプリケーションスロットはプライマリサーバーからの同期中です。" -#: replication/logical/logical.c:542 +#: replication/logical/logical.c:543 #, c-format msgid "Specify another replication slot." msgstr "他のレプリケーションスロットを指定してください。" -#: replication/logical/logical.c:553 replication/logical/logical.c:560 -#, c-format -msgid "can no longer get changes from replication slot \"%s\"" -msgstr "すでにレプリケーションスロット\"%s\"から変更を取り出すことはできません" - -#: replication/logical/logical.c:555 -#, c-format -msgid "This slot has been invalidated because it exceeded the maximum reserved size." -msgstr "最大留保量を超えたため、このスロットは無効化されています。" - -#: replication/logical/logical.c:562 -#, c-format -msgid "This slot has been invalidated because it was conflicting with recovery." -msgstr "リカバリとの競合のため、このスロットは無効化されました。" - -#: replication/logical/logical.c:627 +#: replication/logical/logical.c:609 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "スロット\"%s\"の論理デコードを開始します" -#: replication/logical/logical.c:629 +#: replication/logical/logical.c:611 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "%3$X/%4$XからWALを読み取って、%1$X/%2$X以降にコミットされるトランザクションをストリーミングします。" -#: replication/logical/logical.c:777 +#: replication/logical/logical.c:759 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "スロット\"%s\", 出力プラグイン\"%s\", %sコールバックの処理中, 関連LSN %X/%X" -#: replication/logical/logical.c:783 +#: replication/logical/logical.c:765 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "スロット\"%s\", 出力プラグイン\"%s\", %sコールバックの処理中" -#: replication/logical/logical.c:954 replication/logical/logical.c:999 replication/logical/logical.c:1044 replication/logical/logical.c:1090 +#: replication/logical/logical.c:936 replication/logical/logical.c:981 replication/logical/logical.c:1026 replication/logical/logical.c:1072 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "プリペア時の論理レプリケーションを行うには%sコールバックが必要です" -#: replication/logical/logical.c:1322 replication/logical/logical.c:1371 replication/logical/logical.c:1412 replication/logical/logical.c:1498 replication/logical/logical.c:1547 +#: replication/logical/logical.c:1304 replication/logical/logical.c:1353 replication/logical/logical.c:1394 replication/logical/logical.c:1480 replication/logical/logical.c:1529 #, c-format msgid "logical streaming requires a %s callback" msgstr "論理ストリーミングを行うには%sコールバックが必要です" -#: replication/logical/logical.c:1457 +#: replication/logical/logical.c:1439 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "プリペア時の論理ストリーミングを行うには%sコールバックが必要です" @@ -20333,7 +20892,7 @@ msgstr "配列は1次元でなければなりません" msgid "array must not contain nulls" msgstr "配列にはNULL値を含めてはいけません" -#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1406 utils/adt/jsonb.c:1304 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1428 utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "配列の要素数は偶数でなければなりません" @@ -20343,32 +20902,32 @@ msgstr "配列の要素数は偶数でなければなりません" msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data" msgstr "論理デコード出力プラグイン\"%s\"はバイナリ出力を生成します, しかし関数\"%s\"はテキストデータを期待しています" -#: replication/logical/origin.c:190 +#: replication/logical/origin.c:195 #, c-format -msgid "cannot query or manipulate replication origin when \"max_replication_slots\" is 0" -msgstr "\"max_replication_slots\"が0の時はレプリケーション基点の問い合わせや操作はできません" +msgid "cannot query or manipulate replication origin when \"max_active_replication_origins\" is 0" +msgstr "\"max_active_replication_origins\"が0の時はレプリケーション基点の問い合わせや操作はできません" -#: replication/logical/origin.c:195 +#: replication/logical/origin.c:200 #, c-format msgid "cannot manipulate replication origins during recovery" msgstr "リカバリ中はレプリケーション基点を操作できません" -#: replication/logical/origin.c:240 +#: replication/logical/origin.c:245 #, c-format msgid "replication origin \"%s\" does not exist" msgstr "レプリケーション基点\"%s\"は存在しません" -#: replication/logical/origin.c:331 +#: replication/logical/origin.c:336 #, c-format msgid "could not find free replication origin ID" msgstr "レプリケーション基点IDの空きがありません" -#: replication/logical/origin.c:365 +#: replication/logical/origin.c:370 #, c-format msgid "could not drop replication origin with ID %d, in use by PID %d" msgstr "ID%dのレプリケーション基点を削除できません, PID%dで使用中です" -#: replication/logical/origin.c:492 +#: replication/logical/origin.c:497 #, c-format msgid "replication origin with ID %d does not exist" msgstr "IDが%dのレプリケーション基点がありません" @@ -20380,8 +20939,8 @@ msgstr "レプリケーションチェックポイントのマジックナンバ #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase \"max_replication_slots\"" -msgstr "使用可能なレプリケーション状態領域がありません、\"max_replication_slots\"を増やしてください" +msgid "could not find free replication state, increase \"max_active_replication_origins\"" +msgstr "使用可能なレプリケーション状態領域がありません、\"max_active_replication_origins\"を増やしてください" #: replication/logical/origin.c:806 #, c-format @@ -20403,10 +20962,10 @@ msgstr "ID%dのレプリケーション基点は既にPID%dで使用中です" msgid "could not find free replication state slot for replication origin with ID %d" msgstr "ID%dのレプリケーション基点に対するレプリケーション状態スロットの空きがありません" -#: replication/logical/origin.c:957 replication/logical/origin.c:1158 replication/slot.c:2384 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 #, c-format -msgid "Increase \"max_replication_slots\" and try again." -msgstr "\"max_replication_slots\"を増やして再度試してください" +msgid "Increase \"max_active_replication_origins\" and try again." +msgstr "\"max_active_replication_origins\"を増やして再度試してください" #: replication/logical/origin.c:1114 #, c-format @@ -20428,826 +20987,907 @@ msgstr "レプリケーション基点名\"%s\"は予約されています" msgid "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." msgstr "\"%s\"、\"%s\"、および\"pg_\"で始まる基点名は予約されています。" -#: replication/logical/relation.c:242 +#: replication/logical/relation.c:241 +msgid ", " +msgstr ", " + +#: replication/logical/relation.c:243 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:245 -#, c-format -msgid ", \"%s\"" -msgstr ", \"%s\"" - -#: replication/logical/relation.c:251 +#: replication/logical/relation.c:262 #, c-format msgid "logical replication target relation \"%s.%s\" is missing replicated column: %s" msgid_plural "logical replication target relation \"%s.%s\" is missing replicated columns: %s" msgstr[0] "論理レプリケーション先のリレーション\"%s.%s\"は複製された列を失っています: %s" -#: replication/logical/relation.c:306 +#: replication/logical/relation.c:273 +#, c-format +msgid "logical replication target relation \"%s.%s\" has incompatible generated column: %s" +msgid_plural "logical replication target relation \"%s.%s\" has incompatible generated columns: %s" +msgstr[0] "論理レプリケーション先のリレーション\"%s.%s\"に非互換の生成列が存在します: %s" + +#: replication/logical/relation.c:328 #, c-format msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index" msgstr "論理レプリケーションのターゲットリレーション\"%s.%s\"がREPLICA IDENTITYインデックスでシステム列を使用しています" -#: replication/logical/relation.c:398 +#: replication/logical/relation.c:421 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "論理レプリケーション先のリレーション\"%s.%s\"は存在しません" -#: replication/logical/reorderbuffer.c:3970 +#: replication/logical/reorderbuffer.c:4122 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "XID%uのためのデータファイルの書き出しに失敗しました: %m" -#: replication/logical/reorderbuffer.c:4316 replication/logical/reorderbuffer.c:4341 +#: replication/logical/reorderbuffer.c:4468 replication/logical/reorderbuffer.c:4493 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "並べ替えバッファのあふれファイルの読み込みに失敗しました: %m" -#: replication/logical/reorderbuffer.c:4320 replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4472 replication/logical/reorderbuffer.c:4497 #, c-format msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "並べ替えバッファのあふれファイルの読み込みに失敗しました: %2$uバイトのはずが%1$dバイトでした" -#: replication/logical/reorderbuffer.c:4595 +#: replication/logical/reorderbuffer.c:4746 #, c-format -msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" -msgstr "pg_replslot/%2$s/xid* の削除中にファイル\"%1$s\"が削除できませんでした: %3$m" +msgid "could not remove file \"%s\" during removal of %s/%s/xid*: %m" +msgstr "%2$s/%3$s/xid* の削除中にファイル\"%1$s\"が削除できませんでした: %4$m" -#: replication/logical/reorderbuffer.c:5091 +#: replication/logical/reorderbuffer.c:5243 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "ファイル\"%1$s\"の読み込みに失敗しました: %3$dバイトのはずが%2$dバイトでした" -#: replication/logical/slotsync.c:215 +#: replication/logical/slotsync.c:214 #, c-format -msgid "could not sync slot \"%s\" as remote slot precedes local slot" -msgstr "リモートスロットがローカルスロットよりも進んでいるためスロット\"%s\"を同期できませんでした" +msgid "could not synchronize replication slot \"%s\" because remote slot precedes local slot" +msgstr "リモートのスロットがローカルのスロットよりも進んでいるためレプリケーションスロット\"%s\"を同期できませんでした" -#: replication/logical/slotsync.c:217 +#: replication/logical/slotsync.c:216 #, c-format -msgid "Remote slot has LSN %X/%X and catalog xmin %u, but local slot has LSN %X/%X and catalog xmin %u." +msgid "The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u." msgstr "リモートスロットのLSNは%X/%Xでカタログxminは%uですが, ローカルスロットのLSNは%X/%Xでカタログxminは%uです。" -#: replication/logical/slotsync.c:459 +#: replication/logical/slotsync.c:460 #, c-format -msgid "dropped replication slot \"%s\" of dbid %u" -msgstr "dbid %2$uのレプリケーションスロット\"%1$s\"を削除しました" +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "OID %2$uのデータベースのレプリケーションスロット\"%1$s\"を削除しました" -#: replication/logical/slotsync.c:579 +#: replication/logical/slotsync.c:580 #, c-format -msgid "could not sync slot \"%s\"" -msgstr "スロット\"%s\"を同期できませんでした" +msgid "could not synchronize replication slot \"%s\"" +msgstr "レプリケーションスロット\"%s\"を同期できませんでした" -#: replication/logical/slotsync.c:580 +#: replication/logical/slotsync.c:581 #, c-format -msgid "Logical decoding cannot find consistent point from local slot's LSN %X/%X." -msgstr "論理デコードが一貫性ポイントをローカルスロットのLSN%X/%Xから見つけられません。" +msgid "Logical decoding could not find consistent point from local slot's LSN %X/%X." +msgstr "論理デコードが一貫性ポイントをローカルスロットのLSN%X/%Xから見つけられませんでした。" -#: replication/logical/slotsync.c:589 +#: replication/logical/slotsync.c:590 #, c-format -msgid "newly created slot \"%s\" is sync-ready now" -msgstr "新規に作成したスロット\"%s\"が同期可能になりました" +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "新規に作成したレプリケーションスロット\"%s\"が同期可能になりました" -#: replication/logical/slotsync.c:628 +#: replication/logical/slotsync.c:629 #, c-format -msgid "skipping slot synchronization as the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" +msgid "skipping slot synchronization because the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" msgstr "受信したスロット\"%3$s\"のスロット同期LSN%1$X/%2$XがスタンバイのLSN%4$X/%5$Xよりも進んでいるためスロット同期をスキップします" -#: replication/logical/slotsync.c:650 +#: replication/logical/slotsync.c:651 #, c-format msgid "exiting from slot synchronization because same name slot \"%s\" already exists on the standby" msgstr "スタンバイに同名のスロット\"%s\"がすでに存在するため、スロット同期を終了しました" -#: replication/logical/slotsync.c:819 +#: replication/logical/slotsync.c:820 #, c-format msgid "could not fetch failover logical slots info from the primary server: %s" msgstr "プライマリサーバーからフェイルオーバー属性を持つ論理スロットを取得できませんでした: %s" -#: replication/logical/slotsync.c:965 +#: replication/logical/slotsync.c:969 #, c-format -msgid "could not fetch primary_slot_name \"%s\" info from the primary server: %s" -msgstr "プライマリサーバーからprimary_slot_name \"%s\"の情報を取得できませんでした: %s" +msgid "could not fetch primary slot name \"%s\" info from the primary server: %s" +msgstr "プライマリサーバーからプライマリのスロット名\"%s\"の情報を取得できませんでした: %s" -#: replication/logical/slotsync.c:967 +#: replication/logical/slotsync.c:971 #, c-format -msgid "Check if primary_slot_name is configured correctly." -msgstr "primary_slot_nameが正しく設定されてるか確認してください。" +msgid "Check if \"primary_slot_name\" is configured correctly." +msgstr "\"primary_slot_name\"が正しく設定されているか確認してください。" -#: replication/logical/slotsync.c:987 +#: replication/logical/slotsync.c:991 #, c-format msgid "cannot synchronize replication slots from a standby server" msgstr "スタンバイサーバーからのリプリケーションスロットの同期ができませんでした" -#: replication/logical/slotsync.c:995 -#, c-format -msgid "slot synchronization requires valid primary_slot_name" -msgstr "スロット同期ではprimary_slot_nameを正しく設定する必要があります" - #. translator: second %s is a GUC variable name -#: replication/logical/slotsync.c:997 +#: replication/logical/slotsync.c:1000 #, c-format -msgid "The replication slot \"%s\" specified by %s does not exist on the primary server." -msgstr "%2$sで指定されたレプリケーションスロット\"%1$s\"はプライマリサーバーに存在しません。" +msgid "replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "%2$sで指定されたレプリケーションスロット\"%1$s\"はプライマリサーバーに存在しません" -#: replication/logical/slotsync.c:1029 +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1033 #, c-format -msgid "slot synchronization requires dbname to be specified in %s" -msgstr "スロット同期を行う際は%sでdbnameが指定されている必要があります" +msgid "replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "レプリケーションスロットの同期を行う際は\"%2$s\"で\"%1$s\"が指定されている必要があります" -#: replication/logical/slotsync.c:1050 +#: replication/logical/slotsync.c:1054 #, c-format -msgid "slot synchronization requires \"wal_level\" >= \"logical\"" -msgstr "スロット同期を行う際は\"wal_level\" >= \"logical\" である必要があります" +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "レプリケーションスロットの同期を行う際は\"wal_level\" >= \"logical\" である必要があります" -#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1067 replication/logical/slotsync.c:1095 #, c-format -msgid "slot synchronization requires %s to be defined" -msgstr "スロット同期を行う際は%sが定義されている必要があります" +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "レプリケーションスロットの同期を行う際は\"%s\"が設定されている必要があります" -#: replication/logical/slotsync.c:1077 +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1081 #, c-format -msgid "slot synchronization requires %s to be enabled" -msgstr "スロット同期を行う際は%sが有効になっている必要があります" +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "レプリケーションスロットの同期を行う際は\"%s\"が有効になっている必要があります" #. translator: %s is a GUC variable name -#: replication/logical/slotsync.c:1129 +#: replication/logical/slotsync.c:1133 #, c-format -msgid "slot sync worker will shutdown because %s is disabled" -msgstr "%sが無効にされたため、スロット同期ワーカーがシャットダウンします" +msgid "replication slot synchronization worker will shut down because \"%s\" is disabled" +msgstr "\"%s\"が無効にされたため、レプリケーションスロット同期ワーカーがシャットダウンします" -#: replication/logical/slotsync.c:1138 +#: replication/logical/slotsync.c:1142 #, c-format -msgid "slot sync worker will restart because of a parameter change" -msgstr "パラメータの変更があったため、スロット同期ワーカーが再起動します" +msgid "replication slot synchronization worker will restart because of a parameter change" +msgstr "パラメータの変更があったため、レプリケーションスロット同期ワーカーが再起動します" -#: replication/logical/slotsync.c:1162 +#: replication/logical/slotsync.c:1166 #, c-format -msgid "slot sync worker is shutting down on receiving SIGINT" -msgstr "SIGINTを受信したためスロット同期ワーカーがシャットダウンします" +msgid "replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "SIGINTを受信したためレプリケーションスロット同期ワーカーがシャットダウンします" -#: replication/logical/slotsync.c:1287 +#: replication/logical/slotsync.c:1291 #, c-format msgid "cannot synchronize replication slots when standby promotion is ongoing" msgstr "スタンバイの昇格処理中はリプリケーションスロットの同期はできません" -#: replication/logical/slotsync.c:1295 +#: replication/logical/slotsync.c:1299 #, c-format msgid "cannot synchronize replication slots concurrently" msgstr "複数のレプリケーションスロットの並行同期はできません" -#: replication/logical/slotsync.c:1403 +#: replication/logical/slotsync.c:1407 #, c-format msgid "slot sync worker started" msgstr "スロット同期ワーカーが起動しました" -#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 replication/walreceiver.c:307 +#: replication/logical/slotsync.c:1470 replication/slotfuncs.c:929 #, c-format -msgid "could not connect to the primary server: %s" -msgstr "プライマリサーバーへの接続ができませんでした: %s" +msgid "synchronization worker \"%s\" could not connect to the primary server: %s" +msgstr "同期ワーカー\"%s\"はプライマリ・サーバーに接続できませんでした: %s" -#: replication/logical/snapbuild.c:643 +#: replication/logical/snapbuild.c:514 #, c-format msgid "initial slot snapshot too large" msgstr "初期スロットスナップショットが大きすぎます" -#: replication/logical/snapbuild.c:697 +#: replication/logical/snapbuild.c:568 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs" msgstr[0] "エクスポートされた論理デコードスナップショット: \"%s\" (%u個のトランザクションID を含む)" -#: replication/logical/snapbuild.c:1392 replication/logical/snapbuild.c:1484 replication/logical/snapbuild.c:2000 +#: replication/logical/snapbuild.c:1265 replication/logical/snapbuild.c:1362 replication/logical/snapbuild.c:1868 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "論理デコードは一貫性ポイントを%X/%Xで発見しました" -#: replication/logical/snapbuild.c:1394 +#: replication/logical/snapbuild.c:1267 #, c-format msgid "There are no running transactions." msgstr "実行中のトランザクションはありません。" -#: replication/logical/snapbuild.c:1436 +#: replication/logical/snapbuild.c:1314 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "論理デコードは初期開始点を%X/%Xで発見しました" -#: replication/logical/snapbuild.c:1438 replication/logical/snapbuild.c:1462 +#: replication/logical/snapbuild.c:1316 replication/logical/snapbuild.c:1340 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "%2$uより古いトランザクション(おおよそ%1$d個)の完了を待っています" -#: replication/logical/snapbuild.c:1460 +#: replication/logical/snapbuild.c:1338 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "論理デコードは初期の一貫性ポイントを%X/%Xで発見しました" -#: replication/logical/snapbuild.c:1486 +#: replication/logical/snapbuild.c:1364 #, c-format msgid "There are no old transactions anymore." msgstr "古いトランザクションはこれ以上はありません" -#: replication/logical/snapbuild.c:1887 +#: replication/logical/snapbuild.c:1735 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "スナップショット構築状態ファイル\"%1$s\"のマジックナンバーが不正です: %3$uのはずが%2$uでした" -#: replication/logical/snapbuild.c:1893 +#: replication/logical/snapbuild.c:1741 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "スナップショット状態ファイル\"%1$s\"のバージョン%2$uはサポート外です: %3$uのはずが%2$uでした" -#: replication/logical/snapbuild.c:1934 +#: replication/logical/snapbuild.c:1782 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "スナップショット生成状態ファイル\"%s\"のチェックサムが一致しません: %uですが、%uであるべきです" -#: replication/logical/snapbuild.c:2002 +#: replication/logical/snapbuild.c:1870 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "論理デコードは保存されたスナップショットを使って開始します。" -#: replication/logical/snapbuild.c:2109 +#: replication/logical/snapbuild.c:1977 #, c-format msgid "could not parse file name \"%s\"" msgstr "ファイル名\"%s\"をパースできませんでした" -#: replication/logical/tablesync.c:161 +#: replication/logical/tablesync.c:160 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" msgstr "サブスクリプション\"%s\"、テーブル\"%s\"に対する論理レプリケーションテーブル同期ワーカーが終了しました" -#: replication/logical/tablesync.c:641 +#: replication/logical/tablesync.c:640 #, c-format msgid "logical replication apply worker for subscription \"%s\" will restart so that two_phase can be enabled" msgstr "two_phaseを有効化可能にするため、サブスクリプション\"%s\"に対応する論理レプリケーション適用ワーカーを再起動します" -#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 +#: replication/logical/tablesync.c:830 replication/logical/tablesync.c:971 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "パブリッシャからテーブル\"%s.%s\"のテーブル情報を取得できませんでした: %s" -#: replication/logical/tablesync.c:834 +#: replication/logical/tablesync.c:837 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr "テーブル\"%s.%s\"がパブリッシャ上で見つかりませんでした" -#: replication/logical/tablesync.c:892 +#: replication/logical/tablesync.c:890 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "パブリッシャからテーブル\"%s.%s\"の列リスト情報を取得できませんでした: %s" -#: replication/logical/tablesync.c:1071 +#: replication/logical/tablesync.c:1069 #, c-format msgid "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: %s" msgstr "パブリッシャからテーブル\"%s.%s\"のテーブルのテーブルWHERE句を取得できませんでした: %s" -#: replication/logical/tablesync.c:1230 +#: replication/logical/tablesync.c:1236 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "テーブル\"%s.%s\"の初期内容のコピーを開始できませんでした: %s" -#: replication/logical/tablesync.c:1429 +#: replication/logical/tablesync.c:1351 +#, c-format +msgid "table synchronization worker for subscription \"%s\" could not connect to the publisher: %s" +msgstr "サブスクリプション\"%s\"のテーブル同期ワーカーがパブリッシャに接続できませんでした: %s" + +#: replication/logical/tablesync.c:1436 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "テーブルコピー中にパブリッシャ上でのトランザクション開始に失敗しました: %s" -#: replication/logical/tablesync.c:1472 +#: replication/logical/tablesync.c:1479 #, c-format msgid "replication origin \"%s\" already exists" msgstr "レプリケーション基点\"%s\"はすでに存在します" -#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 +#: replication/logical/tablesync.c:1512 replication/logical/worker.c:2383 #, c-format msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" msgstr "ユーザー\"%s\"は行レベルセキュリティが有効なリレーションへのレプリケーションはできません: \"%s\"" -#: replication/logical/tablesync.c:1518 +#: replication/logical/tablesync.c:1525 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "テーブルコピー中にパブリッシャ上でのトランザクション終了に失敗しました: %s" -#: replication/logical/worker.c:481 +#: replication/logical/worker.c:479 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop" msgstr "サブスクリプション\"%s\"に対応する論理レプリケーション並列適用ワーカーが停止します" -#: replication/logical/worker.c:483 +#: replication/logical/worker.c:481 #, c-format msgid "Cannot handle streamed replication transactions using parallel apply workers until all tables have been synchronized." msgstr "すべてのテーブルの同期が完了するまでは、ストリームされたトランザクションを適用ワーカーで扱うことはできません。" -#: replication/logical/worker.c:852 replication/logical/worker.c:967 +#: replication/logical/worker.c:851 replication/logical/worker.c:966 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "論理レプリケーション列%dのバイナリデータ書式が不正です" -#: replication/logical/worker.c:2500 +#: replication/logical/worker.c:2530 #, c-format msgid "publisher did not send replica identity column expected by the logical replication target relation \"%s.%s\"" msgstr "論理レプリケーション先のリレーション\"%s.%s\"は複製の識別列を期待していましたが、パブリッシャは送信しませんでした" -#: replication/logical/worker.c:2507 +#: replication/logical/worker.c:2537 #, c-format msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL" msgstr "論理レプリケーション先のリレーション\"%s.%s\"が識別列インデックスも主キーをもっておらず、かつパブリッシュされたリレーションがREPLICA IDENTITY FULLとなっていません" -#: replication/logical/worker.c:3371 +#: replication/logical/worker.c:3472 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "不正な論理レプリケーションのメッセージタイプ \"??? (%d)\"" -#: replication/logical/worker.c:3543 +#: replication/logical/worker.c:3644 #, c-format msgid "data stream from publisher has ended" msgstr "パブリッシャからのデータストリームが終了しました" -#: replication/logical/worker.c:3697 +#: replication/logical/worker.c:3798 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "タイムアウトにより論理レプリケーションワーカーを終了しています" -#: replication/logical/worker.c:3891 +#: replication/logical/worker.c:3995 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed" msgstr "サブスクリプション\"%s\"が削除されたため、このサブスクリプションに対応する論理レプリケーションワーカーが停止します" -#: replication/logical/worker.c:3905 +#: replication/logical/worker.c:4009 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled" msgstr "サブスクリプション\"%s\"が無効化されたため、このサブスクリプションに対応する論理レプリケーションワーカーが停止します" -#: replication/logical/worker.c:3936 +#: replication/logical/worker.c:4040 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because of a parameter change" msgstr "パラメータの変更があったため、サブスクリプション\"%s\"に対応する論理レプリケーション並列適用ワーカーが停止します" -#: replication/logical/worker.c:3940 +#: replication/logical/worker.c:4044 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because of a parameter change" msgstr "パラメータの変更があったため、サブスクリプション\"%s\"に対応する論理レプリケーションワーカーが再起動します" -#: replication/logical/worker.c:3954 +#: replication/logical/worker.c:4058 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because the subscription owner's superuser privileges have been revoked" msgstr "サブスクリプション\"%s\"の所有者のスーパーユーザー権限が剥奪されたため、このサブスクリプションに対応する論理レプリケーション並列適用ワーカーが停止します" -#: replication/logical/worker.c:3958 +#: replication/logical/worker.c:4062 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because the subscription owner's superuser privileges have been revoked" msgstr "サブスクリプション\"%s\"の所有者のスーパーユーザー権限が剥奪されたため、このサブスクリプションに対応する論理レプリケーションワーカーが再起動します" -#: replication/logical/worker.c:4478 +#: replication/logical/worker.c:4564 #, c-format msgid "subscription has no replication slot set" msgstr "サブスクリプションにレプリケーションスロットが設定されていません" -#: replication/logical/worker.c:4591 +#: replication/logical/worker.c:4589 +#, c-format +msgid "apply worker for subscription \"%s\" could not connect to the publisher: %s" +msgstr "サブスクリプション\"%s\"の適用ワーカーがパブリッシャに接続できませんでした: %s" + +#: replication/logical/worker.c:4678 #, c-format msgid "logical replication worker for subscription %u will not start because the subscription was removed during startup" msgstr "サブスクリプション%uが起動中に削除されたため、このサブスクリプションに対応する論理レプリケーションワーカーは起動しません" -#: replication/logical/worker.c:4607 +#: replication/logical/worker.c:4694 #, c-format msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup" msgstr "サブスクリプション\"%s\"が起動中に無効化されたため、このサブスクリプションに対応する論理レプリケーションワーカーは起動しません" -#: replication/logical/worker.c:4631 +#: replication/logical/worker.c:4718 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" msgstr "サブスクリプション\"%s\"、テーブル\"%s\"に対応する論理レプリケーションテーブル同期ワーカーが起動しました" -#: replication/logical/worker.c:4636 +#: replication/logical/worker.c:4723 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "サブスクリプション\"%s\"に対応する論理レプリケーション適用ワーカーが起動しました" -#: replication/logical/worker.c:4734 +#: replication/logical/worker.c:4845 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "サブスクリプション\"%s\"はエラーのため無効化されました" -#: replication/logical/worker.c:4782 +#: replication/logical/worker.c:4893 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "論理レプリケーションは%X/%Xででトランザクションのスキップを開始します" -#: replication/logical/worker.c:4796 +#: replication/logical/worker.c:4907 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "論理レプリケーションは%X/%Xでトランザクションのスキップを完了しました" -#: replication/logical/worker.c:4878 +#: replication/logical/worker.c:4989 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "サブスクリプションの\"%s\"スキップLSNをクリアしました" -#: replication/logical/worker.c:4879 +#: replication/logical/worker.c:4990 #, c-format msgid "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X." msgstr "リモートトランザクションの完了WAL位置(LSN) %X/%XがスキップLSN %X/%X と一致しません。" -#: replication/logical/worker.c:4905 +#: replication/logical/worker.c:5027 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\"" msgstr "メッセージタイプ \"%2$s\"でレプリケーション基点\"%1$s\"のリモートからのデータを処理中" -#: replication/logical/worker.c:4909 +#: replication/logical/worker.c:5031 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u" msgstr "トランザクション%3$u中、メッセージタイプ\"%2$s\"でレプリケーション基点\"%1$s\"のリモートからのデータを処理中" -#: replication/logical/worker.c:4914 +#: replication/logical/worker.c:5036 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X" msgstr "%4$X/%5$Xで終了したトランザクション%3$u中、メッセージタイプ\"%2$s\"でレプリケーション基点\"%1$s\"のリモートからのデータを処理中" -#: replication/logical/worker.c:4925 +#: replication/logical/worker.c:5047 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u" msgstr "レプリケーション起点\"%1$s\"のリモートデータ処理中、トランザクション%5$uのレプリケーション対象リレーション\"%3$s.%4$s\"に対するメッセージタイプ\"%2$s\"内" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:5054 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X" msgstr "%6$X/%7$Xで終了したトランザクション%5$u中、レプリケーション先リレーション\"%3$s.%4$s\"に対するメッセージタイプ\"%2$s\"でレプリケーション基点\"%1$s\"のリモートからのデータを処理中" -#: replication/logical/worker.c:4943 +#: replication/logical/worker.c:5065 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" msgstr "レプリケーション起点\"%1$s\"のリモートデータ処理中、トランザクション%6$uのレプリケーション対象リレーション\"%3$s.%4$s\"、列\"%5$s\"に対するメッセージタイプ\"%2$s\"内" -#: replication/logical/worker.c:4951 +#: replication/logical/worker.c:5073 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X" msgstr "%7$X/%8$Xで終了したトランザクション%6$u中、レプリケーション先リレーション\"%3$s.%4$s\"、列\"%5$s\"に対するメッセージタイプ\"%2$s\"でレプリケーション基点\"%1$s\"のリモートからのデータを処理中" -#: replication/pgoutput/pgoutput.c:315 +#: replication/pgoutput/pgoutput.c:328 #, c-format msgid "invalid proto_version" msgstr "不正なproto_version" -#: replication/pgoutput/pgoutput.c:320 +#: replication/pgoutput/pgoutput.c:333 #, c-format msgid "proto_version \"%s\" out of range" msgstr "proto_version \"%s\"は範囲外です" -#: replication/pgoutput/pgoutput.c:337 +#: replication/pgoutput/pgoutput.c:350 #, c-format msgid "invalid publication_names syntax" msgstr "publication_namesの構文が不正です" -#: replication/pgoutput/pgoutput.c:407 +#: replication/pgoutput/pgoutput.c:420 replication/pgoutput/pgoutput.c:424 #, c-format -msgid "proto_version option missing" -msgstr "proto_version オプションが指定されていません" +msgid "option \"%s\" missing" +msgstr "オプション\"%s\"が指定されていません" -#: replication/pgoutput/pgoutput.c:411 -#, c-format -msgid "publication_names option missing" -msgstr "publication_names オプションが指定されていません" - -#: replication/pgoutput/pgoutput.c:452 +#: replication/pgoutput/pgoutput.c:469 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or lower" msgstr "クライアントが proto_version=%d を送信してきましたが、サーバーはバージョン%d以下のプロトコルのみしかサポートしていません" -#: replication/pgoutput/pgoutput.c:458 +#: replication/pgoutput/pgoutput.c:475 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or higher" msgstr "クライアントが proto_version=%d を送信してきましたが、サーバーはバージョン%d以上のプロトコルのみしかサポートしていません" -#: replication/pgoutput/pgoutput.c:473 +#: replication/pgoutput/pgoutput.c:490 #, c-format msgid "requested proto_version=%d does not support streaming, need %d or higher" msgstr "要求されたproto_version=%dではストリーミングをサポートしていません、%d以上が必要です" -#: replication/pgoutput/pgoutput.c:479 +#: replication/pgoutput/pgoutput.c:496 #, c-format msgid "requested proto_version=%d does not support parallel streaming, need %d or higher" msgstr "要求された proto_version=%d は並列ストリーミングをサポートしません、%d以上である必要があります" -#: replication/pgoutput/pgoutput.c:484 +#: replication/pgoutput/pgoutput.c:501 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "ストリーミングが要求されましたが、出力プラグインでサポートされていません" -#: replication/pgoutput/pgoutput.c:498 +#: replication/pgoutput/pgoutput.c:515 #, c-format msgid "requested proto_version=%d does not support two-phase commit, need %d or higher" msgstr "要求されたproto_version=%dは2相コミットをサポートしていません、%d以上が必要です" -#: replication/pgoutput/pgoutput.c:503 +#: replication/pgoutput/pgoutput.c:520 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "2相コミットが要求されました、しかし出力プラグインではサポートされていません" -#: replication/slot.c:260 +#: replication/pgoutput/pgoutput.c:1085 +#, c-format +msgid "cannot use different values of publish_generated_columns for table \"%s.%s\" in different publications" +msgstr "異なるパブリケーションでテーブル\"%s.%s\"に対してpublish_generated_columnsの値を異なる設定にすることはできません" + +#: replication/pgoutput/pgoutput.c:1792 +#, c-format +msgid "skipped loading publication: %s" +msgstr "パブリケーションの読み込みをスキップしました: %s" + +#: replication/pgoutput/pgoutput.c:1793 +#, c-format +msgid "The publication does not exist at this point in the WAL." +msgstr "このパブリケーションはWALのこの時点では存在しません。" + +#: replication/pgoutput/pgoutput.c:1794 +#, c-format +msgid "Create the publication if it does not exist." +msgstr "パブリケーションが存在しない場合は作成してください。" + +#: replication/slot.c:275 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "レプリケーションスロット名\"%s\"は短すぎます" -#: replication/slot.c:269 +#: replication/slot.c:284 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "レプリケーションスロット名\"%s\"は長すぎます" -#: replication/slot.c:282 +#: replication/slot.c:297 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "レプリケーションスロット名\"%s\"は不正な文字を含んでいます" -#: replication/slot.c:284 +#: replication/slot.c:299 #, c-format msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character." msgstr "レプリケーションスロット名は小文字、数字とアンダースコアのみを含むことができます。" -#: replication/slot.c:333 +#: replication/slot.c:348 #, c-format msgid "cannot enable failover for a replication slot created on the standby" msgstr "スタンバイ上で作成したレプリケーションスロットのフェイルオーバーを有効にすることはできません" -#: replication/slot.c:345 replication/slot.c:849 +#: replication/slot.c:360 replication/slot.c:885 #, c-format msgid "cannot enable failover for a temporary replication slot" msgstr "一時レプリケーションスロットのフェイルオーバーを有効にすることはできません" -#: replication/slot.c:370 +#: replication/slot.c:385 #, c-format msgid "replication slot \"%s\" already exists" msgstr "レプリケーションスロット\"%s\"はすでに存在します" -#: replication/slot.c:380 +#: replication/slot.c:395 #, c-format msgid "all replication slots are in use" msgstr "レプリケーションスロットは全て使用中です" -#: replication/slot.c:381 +#: replication/slot.c:396 #, c-format msgid "Free one or increase \"max_replication_slots\"." msgstr "どれか一つを解放するか、\"max_replication_slots\"を大きくしてください。" -#: replication/slot.c:560 replication/slot.c:2453 replication/slotfuncs.c:661 utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 +#: replication/slot.c:579 replication/slotfuncs.c:664 utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:739 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "レプリケーションスロット\"%s\"は存在しません" -#: replication/slot.c:606 replication/slot.c:1337 +#: replication/slot.c:634 replication/slot.c:1388 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "レプリケーションスロット\"%s\"はPID%dで使用中です" -#: replication/slot.c:638 +#: replication/slot.c:651 +#, c-format +msgid "can no longer access replication slot \"%s\"" +msgstr "レプリケーションスロット\"%s\"にはすでにアクセスできなくなっています" + +#: replication/slot.c:653 +#, c-format +msgid "This replication slot has been invalidated due to \"%s\"." +msgstr "このレプリケーションスロットは\"%s\"によって無効化されています。" + +#: replication/slot.c:672 #, c-format msgid "acquired logical replication slot \"%s\"" msgstr "論理レプリケーションスロット\"%s\"を取得しました" -#: replication/slot.c:640 +#: replication/slot.c:674 #, c-format msgid "acquired physical replication slot \"%s\"" msgstr "物理レプリケーションスロット\"%s\"を取得しました" -#: replication/slot.c:729 +#: replication/slot.c:759 #, c-format msgid "released logical replication slot \"%s\"" msgstr "論理レプリケーションスロット\"%s\"を解放しました" -#: replication/slot.c:731 +#: replication/slot.c:761 #, c-format msgid "released physical replication slot \"%s\"" msgstr "物理レプリケーションスロット\"%s\"を解放しました" -#: replication/slot.c:797 +#: replication/slot.c:827 #, c-format msgid "cannot drop replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"を削除できませんでした" -#: replication/slot.c:798 replication/slot.c:829 -#, c-format -msgid "This slot is being synced from the primary server." -msgstr "このスロットはプライマリサーバーからの同期中です。" - -#: replication/slot.c:816 +#: replication/slot.c:850 #, c-format msgid "cannot use %s with a physical replication slot" msgstr "%sは物理レプリケーションスロットでは使用できません" -#: replication/slot.c:828 +#: replication/slot.c:862 #, c-format msgid "cannot alter replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"を変更できませんでした" -#: replication/slot.c:838 +#: replication/slot.c:872 #, c-format msgid "cannot enable failover for a replication slot on the standby" msgstr "スタンバイ上ではレプリケーションスロットのフェイルオーバーを有効にすることはできません" -#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 +#: replication/slot.c:1020 replication/slot.c:2120 replication/slot.c:2505 #, c-format msgid "could not remove directory \"%s\"" msgstr "ディレクトリ\"%s\"を削除できませんでした" -#: replication/slot.c:1372 +#: replication/slot.c:1423 #, c-format msgid "replication slots can only be used if \"max_replication_slots\" > 0" msgstr "レプリケーションスロットは\"max_replication_slots\" > 0 のときだけ使用できます" -#: replication/slot.c:1377 +#: replication/slot.c:1428 #, c-format msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" msgstr "レプリケーションスロットは\"wal_level\" >= \"replica\" のときだけ使用できます" -#: replication/slot.c:1389 +#: replication/slot.c:1440 #, c-format msgid "permission denied to use replication slots" msgstr "レプリケーションスロットを使用する権限がありません" -#: replication/slot.c:1390 +#: replication/slot.c:1441 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "%s属性を持つロールのみがレプリケーションスロットを使用できます。" -#: replication/slot.c:1498 +#: replication/slot.c:1550 #, c-format -msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." -msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." -msgstr[0] "このスロットのrestart_lsn %X/%Xは制限を%lluバイト超過しています。" +msgid "The slot's restart_lsn %X/%X exceeds the limit by % byte." +msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by % bytes." +msgstr[0] "このスロットのrestart_lsn %X/%Xは制限を%バイト超過しています。" -#: replication/slot.c:1506 +#: replication/slot.c:1561 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "このスロットはXID地平線%uと競合しました。" -#: replication/slot.c:1511 +#: replication/slot.c:1566 msgid "Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server." msgstr "論理デコードを行うためにはプライマリサーバー上で\"wal_level\" >= \"logical\" である必要があります。" -#: replication/slot.c:1519 +#. translator: %s is a GUC variable name +#: replication/slot.c:1575 +#, c-format +msgid "The slot's idle time of %dmin %02ds exceeds the configured \"%s\" duration of %dmin." +msgstr "このスロットのアイドル時間 %d分%02d秒が、\"%s\"で設定された %d分を超えています。" + +#: replication/slot.c:1589 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "プロセス%dを終了してレプリケーションスロット\"%s\"を解放します" -#: replication/slot.c:1521 +#: replication/slot.c:1591 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "使用不能のレプリケーションスロット\"%s\"を無効化します" -#: replication/slot.c:2249 +#: replication/slot.c:2443 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "レプリケーションスロットファイル\"%1$s\"のマジックナンバーが不正です: %3$uのはずが%2$uでした" -#: replication/slot.c:2256 +#: replication/slot.c:2450 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "レプリケーションスロットファイル\"%s\"はサポート外のバージョン%uです" -#: replication/slot.c:2263 +#: replication/slot.c:2457 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "レプリケーションスロットファイル\"%s\"のサイズ%uは異常です" -#: replication/slot.c:2299 +#: replication/slot.c:2493 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "レプリケーションスロットファイル\"%s\"のチェックサムが一致しません: %uですが、%uであるべきです" -#: replication/slot.c:2333 +#: replication/slot.c:2529 #, c-format msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" msgstr "論理レプリケーションスロット\"%s\"がありますが、\"wal_level\" < \"logical\" です" -#: replication/slot.c:2335 +#: replication/slot.c:2531 #, c-format msgid "Change \"wal_level\" to be \"logical\" or higher." msgstr "\"wal_level\"を\"logical\"もしくはそれより上位の設定にしてください。" -#: replication/slot.c:2339 +#: replication/slot.c:2543 +#, c-format +msgid "logical replication slot \"%s\" exists on the standby, but \"hot_standby\" = \"off\"" +msgstr "論理レプリケーションスロット\"%s\"がありますが、\"hot_standby\" = \"off\" です" + +#: replication/slot.c:2545 +#, c-format +msgid "Change \"hot_standby\" to be \"on\"." +msgstr "\"hot_standby\" を \"on\" に変更してください。" + +#: replication/slot.c:2550 #, c-format msgid "physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" msgstr "物理レプリケーションスロット\"%s\"がありますが、\"wal_level\" < \"replica\" です" -#: replication/slot.c:2341 +#: replication/slot.c:2552 #, c-format msgid "Change \"wal_level\" to be \"replica\" or higher." msgstr "\"wal_level\"を\"replica\"もしくはそれより上位の設定にしてください。" -#: replication/slot.c:2383 +#: replication/slot.c:2598 #, c-format msgid "too many replication slots active before shutdown" msgstr "シャットダウン前のアクティブなレプリケーションスロットの数が多すぎます" -#: replication/slot.c:2461 +#: replication/slot.c:2599 +#, c-format +msgid "Increase \"max_replication_slots\" and try again." +msgstr "\"max_replication_slots\"を増やして再度試してください" + +#: replication/slot.c:2676 +#, c-format +msgid "Replication slot \"%s\" does not exist." +msgstr "レプリケーションスロット\"%s\"は存在しません。" + +#: replication/slot.c:2684 +#, c-format +msgid "\"%s\" is not a physical replication slot." +msgstr "\"%s\"は物理レプリケーションスロットではありません。" + +#: replication/slot.c:2863 #, c-format -msgid "\"%s\" is not a physical replication slot" -msgstr "\"%s\"は物理レプリケーションスロットではありません" +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "パラメータ\"%2$s\"で指定されているレプリケーションスロット\"%1$s\"は存在しません" -#: replication/slot.c:2637 +#: replication/slot.c:2865 replication/slot.c:2899 replication/slot.c:2914 #, c-format -msgid "replication slot \"%s\" specified in parameter %s does not exist" -msgstr "パラメータ%2$sで指定されているレプリケーションスロット\"%1$s\"は存在しません" +msgid "Logical replication is waiting on the standby associated with replication slot \"%s\"." +msgstr "論理レプリケーションはレプリケーションスロット”%s\"に対応するスタンバイを待っています。 " -#: replication/slot.c:2639 replication/slot.c:2680 replication/slot.c:2695 +#: replication/slot.c:2867 #, c-format -msgid "Logical replication is waiting on the standby associated with \"%s\"." -msgstr "論理レプリケーションは”%s\"に対応するスタンバイを待っています。 " +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "レプリケーションスロット\"%s\"を作成するか、パラメータ\"%s\"を修正してください。" -#: replication/slot.c:2641 +#: replication/slot.c:2877 #, c-format -msgid "Consider creating the slot \"%s\" or amend parameter %s." -msgstr "スロット\"%s\"を作成するか、パラメータ%sを修正することを検討してください。" +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "パラメータ\"%2$s\"では論理レプリケーションスロット\"%1$s\"は指定できません" -#: replication/slot.c:2658 +#: replication/slot.c:2879 #, c-format -msgid "cannot have logical replication slot \"%s\" in parameter %s" -msgstr "パラメータ%2$sでは論理レプリケーションスロット\"%1$s\"は指定できません" +msgid "Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "論理レプリケーションはレプリケーションスロット\"%s\"が修正されるのを待っています。" -#: replication/slot.c:2660 +#: replication/slot.c:2881 #, c-format -msgid "Logical replication is waiting for correction on \"%s\"." -msgstr "論理レプリケーションは\"%s\"が修正されるのを待っています。" +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "論理レプリケーションスロット\"%s\"をパラメータ\"%s\"から削除してください。" -#: replication/slot.c:2662 +#: replication/slot.c:2897 #, c-format -msgid "Consider removing logical slot \"%s\" from parameter %s." -msgstr "パラメータ%sから論理スロット\"%s\"を削除することを検討してください。" +msgid "physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated" +msgstr "パラメータ\"%2$s\"で指定された物理レプリケーションスロット\"%1$s\"は無効化されています" -#: replication/slot.c:2678 +#: replication/slot.c:2901 #, c-format -msgid "physical slot \"%s\" specified in parameter %s has been invalidated" -msgstr "パラメータ%2$sで指定された物理スロット\"%1$s\"は無効化されました" +msgid "Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "レプリケーションスロット\"%s\"を削除して再作成するか、パラメータ\"%s\"を修正してください。" -#: replication/slot.c:2682 +#: replication/slot.c:2912 #, c-format -msgid "Consider dropping and recreating the slot \"%s\" or amend parameter %s." -msgstr "スロット\"%s\"の削除および再作成、もしくはパラメータ%sの修正を検討してください。" +msgid "replication slot \"%s\" specified in parameter \"%s\" does not have active_pid" +msgstr "\"%2$s\"で指定されたレプリケーションスロット\"%1$s\"にはactive_pidがありません" -#: replication/slot.c:2693 +#: replication/slot.c:2916 #, c-format -msgid "replication slot \"%s\" specified in parameter %s does not have active_pid" -msgstr "%2$sで指定されたレプリケーションスロット\"%1$s\"にはactive_pidがありません" +msgid "Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "レプリケーションスロット\"%s\"に関連付けられているスタンバイを起動するか、パラメータ%sを修正してください。" -#: replication/slot.c:2697 +#: replication/slot.c:3008 #, c-format -msgid "Consider starting standby associated with \"%s\" or amend parameter %s." -msgstr "\"%s\"に関連付けられているスタンバイを起動するか、パラメータ%sを修正することを検討してくだささい。" +msgid "\"%s\" must be set to 0 during binary upgrade mode." +msgstr "バイナリアップグレードモード中は\"%s\"は0に設定されている必要があります。" -#: replication/slotfuncs.c:526 +#: replication/slotfuncs.c:529 #, c-format msgid "invalid target WAL LSN" msgstr "不正な目標WAL LSN" -#: replication/slotfuncs.c:548 +#: replication/slotfuncs.c:551 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "レプリケーションスロット\"%s\"は進められません" -#: replication/slotfuncs.c:550 +#: replication/slotfuncs.c:553 #, c-format msgid "This slot has never previously reserved WAL, or it has been invalidated." msgstr "このスロットはWALを留保したことがないか、無効化さています。" -#: replication/slotfuncs.c:566 +#: replication/slotfuncs.c:569 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "レプリケーションスロットを %X/%X に進めることはできません、最小値は %X/%X" -#: replication/slotfuncs.c:673 +#: replication/slotfuncs.c:676 #, c-format msgid "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "物理レプリケーションスロット\"%s\"を論理レプリケーションスロットとしてコピーすることはできません" -#: replication/slotfuncs.c:675 +#: replication/slotfuncs.c:678 #, c-format msgid "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "論理レプリケーションスロット\"%s\"を物理レプリケーションスロットとしてコピーすることはできません" -#: replication/slotfuncs.c:682 +#: replication/slotfuncs.c:685 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "WAL の留保をしていないレプリケーションスロットはコピーできません" -#: replication/slotfuncs.c:768 +#: replication/slotfuncs.c:691 +#, c-format +msgid "cannot copy invalidated replication slot \"%s\"" +msgstr "無効化されたレプリケーションスロット\"%s\"はコピーできません" + +#: replication/slotfuncs.c:783 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"をコピーできませんでした" -#: replication/slotfuncs.c:770 +#: replication/slotfuncs.c:785 #, c-format msgid "The source replication slot was modified incompatibly during the copy operation." msgstr "コピー処理中にコピー元のレプリケーションスロットが非互換的に変更されました。" -#: replication/slotfuncs.c:776 +#: replication/slotfuncs.c:791 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "未完成の論理レプリケーションスロット\"%s\"はコピーできません" -#: replication/slotfuncs.c:778 +#: replication/slotfuncs.c:793 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "このソースレプリケーションスロットの confirmed_flush_lsn が有効値になってから再度実行してください。" -#: replication/slotfuncs.c:877 +#: replication/slotfuncs.c:805 +#, c-format +msgid "cannot copy replication slot \"%s\"" +msgstr "レプリケーションスロット\"%s\"はコピーできません" + +#: replication/slotfuncs.c:807 +#, c-format +msgid "The source replication slot was invalidated during the copy operation." +msgstr "コピー元のレプリケーションスロットがコピー処理中に無効化されました。" + +#: replication/slotfuncs.c:906 #, c-format msgid "replication slots can only be synchronized to a standby server" msgstr "レプリケーションスロットはスタンバイサーバーへのみ同期可能です" @@ -21278,203 +21918,203 @@ msgstr "スタンバイ\"%s\"は優先度%dの同期スタンバイになりま msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "スタンバイ\"%s\"は定足数同期スタンバイの候補になりました" -#: replication/syncrep.c:1013 +#: replication/syncrep.c:1014 #, c-format -msgid "\"synchronous_standby_names\" parser failed" -msgstr "\"synchronous_standby_names\"の読み取りに失敗しました" +msgid "\"%s\" parser failed." +msgstr "\"%s\"のパーサーが失敗しました。" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1021 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "同期スタンバイの数(%d)は1以上である必要があります" -#: replication/walreceiver.c:176 +#: replication/walreceiver.c:276 #, c-format -msgid "terminating walreceiver process due to administrator command" -msgstr "管理者コマンドにより WAL 受信プロセスを終了しています" +msgid "streaming replication receiver \"%s\" could not connect to the primary server: %s" +msgstr "ストリーミングレプリケーション・レシーバー\"%s\"はプライマリ・サーバーに接続できませんでした: %s" -#: replication/walreceiver.c:354 +#: replication/walreceiver.c:324 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "データベースシステムの識別子がプライマリサーバーとスタンバイサーバー間で異なります" -#: replication/walreceiver.c:355 +#: replication/walreceiver.c:325 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "プライマリ側の識別子は %s ですが、スタンバイ側の識別子は %s です。" -#: replication/walreceiver.c:366 +#: replication/walreceiver.c:336 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "プライマリの最大のタイムライン%uが、リカバリのタイムライン %uより遅れています" -#: replication/walreceiver.c:419 +#: replication/walreceiver.c:389 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "プライマリのタイムライン%3$uの %1$X/%2$XからでWALストリーミングを始めます" -#: replication/walreceiver.c:423 +#: replication/walreceiver.c:393 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "タイムライン%3$uの %1$X/%2$XからでWALストリーミングを再開します" -#: replication/walreceiver.c:458 +#: replication/walreceiver.c:428 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "WAL ストリーミングを継続できません。リカバリはすでに終わっています。" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:472 #, c-format msgid "replication terminated by primary server" msgstr "プライマリサーバーによりレプリケーションが打ち切られました" -#: replication/walreceiver.c:503 +#: replication/walreceiver.c:473 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "タイムライン%uの%X/%XでWALの最後に達しました" -#: replication/walreceiver.c:593 +#: replication/walreceiver.c:573 #, c-format msgid "terminating walreceiver due to timeout" msgstr "レプリケーションタイムアウトによりwalreceiverを終了しています" -#: replication/walreceiver.c:625 +#: replication/walreceiver.c:605 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "プライマリサーバーには要求されたタイムライン%u上にこれ以上WALがありません" -#: replication/walreceiver.c:641 replication/walreceiver.c:1071 +#: replication/walreceiver.c:621 replication/walreceiver.c:1063 #, c-format msgid "could not close WAL segment %s: %m" msgstr "WALセグメント%sをクローズできませんでした: %m" -#: replication/walreceiver.c:760 +#: replication/walreceiver.c:740 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "プライマリサーバーからライムライン%u用のタイムライン履歴ファイルを取り込みしています" -#: replication/walreceiver.c:959 +#: replication/walreceiver.c:951 #, c-format msgid "could not write to WAL segment %s at offset %d, length %lu: %m" msgstr "WALファイルセグメント%sのオフセット%d、長さ%luの書き込みが失敗しました: %m" -#: replication/walsender.c:531 +#: replication/walsender.c:505 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "%sは論理レプリケーションスロットでは使用できません" -#: replication/walsender.c:635 storage/smgr/md.c:1723 +#: replication/walsender.c:609 storage/smgr/md.c:1867 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "ファイル\"%s\"の終端へシークできませんでした: %m" -#: replication/walsender.c:639 +#: replication/walsender.c:613 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "ファイル\"%s\"の先頭にシークできませんでした: %m" -#: replication/walsender.c:853 +#: replication/walsender.c:829 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "論理レプリケーションスロットは物理レプリケーションには使用できません" -#: replication/walsender.c:919 +#: replication/walsender.c:895 #, c-format msgid "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "タイムライン%3$u上の要求された開始ポイント%1$X/%2$Xはサーバーの履歴にありません" -#: replication/walsender.c:922 +#: replication/walsender.c:898 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "サーバーの履歴はタイムライン%uの%X/%Xからフォークしました。" -#: replication/walsender.c:966 +#: replication/walsender.c:942 #, c-format msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X" msgstr "要求された開始ポイント%X/%XはサーバーのWALフラッシュ位置%X/%Xより進んでいます" -#: replication/walsender.c:1160 +#: replication/walsender.c:1137 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "CREATE_REPLICATION_SLOTのオプション\"%s\"に対する認識できない値: \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1266 +#: replication/walsender.c:1243 #, c-format msgid "%s must not be called inside a transaction" msgstr "%sはトランザクション内では呼び出せません" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1276 +#: replication/walsender.c:1253 #, c-format msgid "%s must be called inside a transaction" msgstr "%sはトランザクション内で呼び出さなければなりません" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1282 +#: replication/walsender.c:1259 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s は REPEATABLE READ 分離レベルのトランザクションで呼び出されなければなりません" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1287 +#: replication/walsender.c:1264 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%sは読み取り専用トランザクションの中で呼び出さなければなりません" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1293 +#: replication/walsender.c:1270 #, c-format msgid "%s must be called before any query" msgstr "%s は問い合わせの実行前に呼び出されなければなりません" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1299 +#: replication/walsender.c:1276 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s はサブトランザクション内では呼び出せません" -#: replication/walsender.c:1472 +#: replication/walsender.c:1453 #, c-format msgid "terminating walsender process after promotion" msgstr "昇格後にWAL送信プロセスを終了します" -#: replication/walsender.c:2000 +#: replication/walsender.c:1994 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "WAL送信プロセスが停止モードの間は新しいコマンドを実行できません" -#: replication/walsender.c:2035 +#: replication/walsender.c:2029 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "物理レプリケーション用のWAL送信プロセスでSQLコマンドは実行できません" -#: replication/walsender.c:2068 +#: replication/walsender.c:2060 #, c-format msgid "received replication command: %s" msgstr "レプリケーションコマンドを受信しました: %s" -#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1138 tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2206 tcop/postgres.c:2644 tcop/postgres.c:2722 +#: replication/walsender.c:2068 tcop/fastpath.c:208 tcop/postgres.c:1137 tcop/postgres.c:1495 tcop/postgres.c:1747 tcop/postgres.c:2253 tcop/postgres.c:2690 tcop/postgres.c:2767 #, c-format msgid "current transaction is aborted, commands ignored until end of transaction block" msgstr "現在のトランザクションがアボートしました。トランザクションブロックが終わるまでコマンドは無視されます" -#: replication/walsender.c:2233 replication/walsender.c:2268 +#: replication/walsender.c:2225 replication/walsender.c:2260 #, c-format msgid "unexpected EOF on standby connection" msgstr "スタンバイ接続で想定外のEOFがありました" -#: replication/walsender.c:2256 +#: replication/walsender.c:2248 #, c-format msgid "invalid standby message type \"%c\"" msgstr "スタンバイのメッセージタイプ\"%c\"は不正です" -#: replication/walsender.c:2345 +#: replication/walsender.c:2337 #, c-format msgid "unexpected message type \"%c\"" msgstr "想定しないメッセージタイプ\"%c\"" -#: replication/walsender.c:2759 +#: replication/walsender.c:2751 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "レプリケーションタイムアウトにより WAL 送信プロセスを終了しています" @@ -21654,280 +22294,285 @@ msgstr "リレーション\"%2$s\"のルール\"%1$s\"は存在しません" msgid "renaming an ON SELECT rule is not allowed" msgstr "ON SELECTルールの名前を変更することはできません" -#: rewrite/rewriteHandler.c:581 +#: rewrite/rewriteHandler.c:590 #, c-format msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten" msgstr "WITH の問い合わせ名\"%s\"が、ルールのアクションと書き換えられようとしている問い合わせの両方に現れています" -#: rewrite/rewriteHandler.c:608 +#: rewrite/rewriteHandler.c:617 #, c-format msgid "INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH" msgstr "INSERT ... SELECTルールのアクションはWITHにデータ更新文を持つ問い合わせに対してはサポートされません" -#: rewrite/rewriteHandler.c:661 +#: rewrite/rewriteHandler.c:671 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "複数ルールではRETURNINGリストを持つことはできません" -#: rewrite/rewriteHandler.c:893 rewrite/rewriteHandler.c:932 +#: rewrite/rewriteHandler.c:908 rewrite/rewriteHandler.c:947 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "列\"%s\"への非デフォルト値の挿入はできません" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:961 +#: rewrite/rewriteHandler.c:910 rewrite/rewriteHandler.c:976 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "列\"%s\"は GENERATED ALWAYS として定義されています。" -#: rewrite/rewriteHandler.c:897 +#: rewrite/rewriteHandler.c:912 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "OVERRIDING SYSTEM VALUE を指定することで挿入を強制できます。" -#: rewrite/rewriteHandler.c:959 rewrite/rewriteHandler.c:967 +#: rewrite/rewriteHandler.c:974 rewrite/rewriteHandler.c:982 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "列\"%s\"はDEFAULTにのみ更新可能です" -#: rewrite/rewriteHandler.c:1114 rewrite/rewriteHandler.c:1132 +#: rewrite/rewriteHandler.c:1118 rewrite/rewriteHandler.c:1136 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "同じ列\"%s\"に複数の代入があります" -#: rewrite/rewriteHandler.c:1697 +#: rewrite/rewriteHandler.c:1691 #, c-format msgid "MERGE is not supported for relations with rules." msgstr "MERGEはルールを持つリレーションに対してはサポートされません。" -#: rewrite/rewriteHandler.c:2110 rewrite/rewriteHandler.c:4197 +#: rewrite/rewriteHandler.c:1731 rewrite/rewriteHandler.c:3271 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "非システムのビュー\"%s\"へのアクセスは制限されています" + +#: rewrite/rewriteHandler.c:2130 rewrite/rewriteHandler.c:4265 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "リレーション\"%s\"のルールで無限再帰を検出しました" -#: rewrite/rewriteHandler.c:2195 +#: rewrite/rewriteHandler.c:2235 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "リレーション\"%s\"のポリシで無限再帰を検出しました" -#: rewrite/rewriteHandler.c:2547 +#: rewrite/rewriteHandler.c:2598 msgid "Junk view columns are not updatable." msgstr "ジャンクビュー列は更新不可です。" -#: rewrite/rewriteHandler.c:2552 +#: rewrite/rewriteHandler.c:2603 msgid "View columns that are not columns of their base relation are not updatable." msgstr "基底リレーションの列ではないビュー列は更新不可です。" -#: rewrite/rewriteHandler.c:2555 +#: rewrite/rewriteHandler.c:2606 msgid "View columns that refer to system columns are not updatable." msgstr "システム列を参照するビュー列は更新不可です。" -#: rewrite/rewriteHandler.c:2558 +#: rewrite/rewriteHandler.c:2609 msgid "View columns that return whole-row references are not updatable." msgstr "行全体参照を返すビュー列は更新不可です。" -#: rewrite/rewriteHandler.c:2619 +#: rewrite/rewriteHandler.c:2670 msgid "Views containing DISTINCT are not automatically updatable." msgstr "DISTINCTを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2622 +#: rewrite/rewriteHandler.c:2673 msgid "Views containing GROUP BY are not automatically updatable." msgstr "GROUP BYを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2625 +#: rewrite/rewriteHandler.c:2676 msgid "Views containing HAVING are not automatically updatable." msgstr "HAVINGを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2628 +#: rewrite/rewriteHandler.c:2679 msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "UNION、INTERSECT、EXCEPTを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2631 +#: rewrite/rewriteHandler.c:2682 msgid "Views containing WITH are not automatically updatable." msgstr "WITHを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2634 +#: rewrite/rewriteHandler.c:2685 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "LIMIT、OFFSETを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2646 +#: rewrite/rewriteHandler.c:2697 msgid "Views that return aggregate functions are not automatically updatable." msgstr "集約関数を返すビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2649 +#: rewrite/rewriteHandler.c:2700 msgid "Views that return window functions are not automatically updatable." msgstr "ウィンドウ関数を返すビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2652 +#: rewrite/rewriteHandler.c:2703 msgid "Views that return set-returning functions are not automatically updatable." msgstr "集合返却関数を返すビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2659 rewrite/rewriteHandler.c:2663 rewrite/rewriteHandler.c:2671 +#: rewrite/rewriteHandler.c:2710 rewrite/rewriteHandler.c:2714 rewrite/rewriteHandler.c:2722 msgid "Views that do not select from a single table or view are not automatically updatable." msgstr "単一のテーブルまたはビューからselectしていないビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2674 +#: rewrite/rewriteHandler.c:2725 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "TABLESAMPLEを含むビューは自動更新できません。" -#: rewrite/rewriteHandler.c:2698 +#: rewrite/rewriteHandler.c:2749 msgid "Views that have no updatable columns are not automatically updatable." msgstr "更新可能な列を持たないビューは自動更新できません。" -#: rewrite/rewriteHandler.c:3079 rewrite/rewriteHandler.c:3114 +#: rewrite/rewriteHandler.c:3130 rewrite/rewriteHandler.c:3165 #, c-format msgid "cannot insert into view \"%s\"" msgstr "ビュー\"%s\"へは挿入(INSERT)できません" -#: rewrite/rewriteHandler.c:3082 +#: rewrite/rewriteHandler.c:3133 #, c-format msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." msgstr "ビューへの挿入を可能にするために、INSTEAD OF INSERTトリガまたは無条件のON INSERT DO INSTEADルールを作成してください。" -#: rewrite/rewriteHandler.c:3087 rewrite/rewriteHandler.c:3123 +#: rewrite/rewriteHandler.c:3138 rewrite/rewriteHandler.c:3174 #, c-format msgid "cannot update view \"%s\"" msgstr "ビュー\"%s\"は更新できません" -#: rewrite/rewriteHandler.c:3090 +#: rewrite/rewriteHandler.c:3141 #, c-format msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." msgstr "ビューへの更新を可能にするために、INSTEAD OF UPDATEトリガまたは無条件のON UPDATE DO INSTEADルールを作成してください。" -#: rewrite/rewriteHandler.c:3095 rewrite/rewriteHandler.c:3132 +#: rewrite/rewriteHandler.c:3146 rewrite/rewriteHandler.c:3183 #, c-format msgid "cannot delete from view \"%s\"" msgstr "ビュー\"%s\"からは削除できません" -#: rewrite/rewriteHandler.c:3098 +#: rewrite/rewriteHandler.c:3149 #, c-format msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." msgstr "ビューからの削除を可能にするために、INSTEAD OF DELETEトリガまたは無条件のON DELETE DO INSTEADルールを作成してください。" -#: rewrite/rewriteHandler.c:3117 +#: rewrite/rewriteHandler.c:3168 #, c-format msgid "To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger." msgstr "MERGEを用いたビューへの挿入を可能にするには、INSTEAD OF INSERTトリガーを作成してください。" -#: rewrite/rewriteHandler.c:3126 +#: rewrite/rewriteHandler.c:3177 #, c-format msgid "To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger." msgstr "MERGEを用いたビューの更新を可能にするには、INSTEAD OF UPDATEトリガーを作成してください。" -#: rewrite/rewriteHandler.c:3135 +#: rewrite/rewriteHandler.c:3186 #, c-format msgid "To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger." msgstr "MERGEを用いたビューからの削除を可能にするためには、INSTEAD OF DELETEトリガーを作成してください。" -#: rewrite/rewriteHandler.c:3289 +#: rewrite/rewriteHandler.c:3361 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "ビュー\"%2$s\"の列\"%1$s\"への挿入はできません" -#: rewrite/rewriteHandler.c:3297 +#: rewrite/rewriteHandler.c:3369 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "ビュー\"%2$s\"の列\"%1$s\"は更新できません" -#: rewrite/rewriteHandler.c:3305 +#: rewrite/rewriteHandler.c:3377 #, c-format msgid "cannot merge into column \"%s\" of view \"%s\"" msgstr "ビュー\"%2$s\"の列\"%1$s\"への統合はできません" -#: rewrite/rewriteHandler.c:3333 +#: rewrite/rewriteHandler.c:3405 #, c-format msgid "cannot merge into view \"%s\"" msgstr "ビュー\"%s\"への統合はできません" -#: rewrite/rewriteHandler.c:3335 +#: rewrite/rewriteHandler.c:3407 #, c-format -msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions, but not others." -msgstr "MERGEはINSTEAD OFトリガーが一部のアクションにのみ設定されていて、他にはされていないビューではサポートされません。" +msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions but not all." +msgstr "MERGEはINSTEAD OFトリガーが全てではなく一部のアクションに対してのみ設定されてるビューではサポートされません。" -#: rewrite/rewriteHandler.c:3336 +#: rewrite/rewriteHandler.c:3408 #, c-format msgid "To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers." msgstr "ビューへの統合を可能にするためには、完全なINSTEAD OF INSERTトリガーを作成するか、または既存のINSTEAD OFトリガーを削除してください。" -#: rewrite/rewriteHandler.c:3855 +#: rewrite/rewriteHandler.c:3923 #, c-format msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" msgstr "DO INSTEAD NOTIFYルールはWITH内のデータ更新文に対してはサポートされません" -#: rewrite/rewriteHandler.c:3866 +#: rewrite/rewriteHandler.c:3934 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" msgstr "WITH にデータを変更するステートメントがある場合は DO INSTEAD NOTHING ルールはサポートされません" -#: rewrite/rewriteHandler.c:3880 +#: rewrite/rewriteHandler.c:3948 #, c-format msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "WITH にデータを変更するステートメントがある場合は、条件付き DO INSTEAD ルールはサポートされません" -#: rewrite/rewriteHandler.c:3884 +#: rewrite/rewriteHandler.c:3952 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "WITH にデータを変更するステートメントがある場合は DO ALSO ルールはサポートされません" -#: rewrite/rewriteHandler.c:3889 +#: rewrite/rewriteHandler.c:3957 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "WITH にデータを変更するステートメントがある場合はマルチステートメントの DO INSTEAD ルールはサポートされません" -#: rewrite/rewriteHandler.c:4149 +#: rewrite/rewriteHandler.c:4217 msgid "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "条件付きDO INSTEADルールを持つビューは自動更新できません。" -#: rewrite/rewriteHandler.c:4246 +#: rewrite/rewriteHandler.c:4314 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "リレーション\"%s\"へのINSERT RETURNINGを行うことはできません" -#: rewrite/rewriteHandler.c:4248 +#: rewrite/rewriteHandler.c:4316 #, c-format msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "RETURNING句を持つ無条件のON INSERT DO INSTEADルールが必要です。" -#: rewrite/rewriteHandler.c:4253 +#: rewrite/rewriteHandler.c:4321 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "リレーション\"%s\"へのUPDATE RETURNINGを行うことはできません" -#: rewrite/rewriteHandler.c:4255 +#: rewrite/rewriteHandler.c:4323 #, c-format msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "RETURNING句を持つ無条件のON UPDATE DO INSTEADルールが必要です。" -#: rewrite/rewriteHandler.c:4260 +#: rewrite/rewriteHandler.c:4328 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "リレーション\"%s\"へのDELETE RETURNINGを行うことはできません" -#: rewrite/rewriteHandler.c:4262 +#: rewrite/rewriteHandler.c:4330 #, c-format msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "RETURNING句を持つ無条件のON DELETE DO INSTEADルールが必要です。" -#: rewrite/rewriteHandler.c:4280 +#: rewrite/rewriteHandler.c:4348 #, c-format msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" msgstr "ON CONFLICT句を伴うINSERTは、INSERTまたはUPDATEルールを持つテーブルでは使えません" -#: rewrite/rewriteHandler.c:4337 +#: rewrite/rewriteHandler.c:4405 #, c-format msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries" msgstr "複数問い合わせに対するルールにより書き換えられた問い合わせでは WITH を使用できません" -#: rewrite/rewriteManip.c:1083 +#: rewrite/rewriteManip.c:1222 #, c-format msgid "conditional utility statements are not implemented" msgstr "条件付きのユーティリティ文は実装されていません" -#: rewrite/rewriteManip.c:1427 +#: rewrite/rewriteManip.c:1567 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "ビューに対するWHERE CURRENT OFは実装されていません" -#: rewrite/rewriteManip.c:1762 +#: rewrite/rewriteManip.c:1970 #, c-format msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command" msgstr "ON UPDATE ルールのNEW変数は、対象のUPDATEコマンドでの複数列代入の一部となる列を参照することはできません" @@ -21986,7 +22631,7 @@ msgstr "文字列のドル引用符が閉じていません" msgid "zero-length delimited identifier" msgstr "二重引用符で囲まれた識別子の長さがゼロです" -#: scan.l:825 syncrep_scanner.l:101 +#: scan.l:825 syncrep_scanner.l:114 msgid "unterminated quoted identifier" msgstr "識別子の引用符が閉じていません" @@ -21995,89 +22640,163 @@ msgid "operator too long" msgstr "演算子が長すぎます" #: scan.l:1001 +msgid "parameter number too large" +msgstr "パラメータ数が多すぎます" + +#: scan.l:1007 msgid "trailing junk after parameter" msgstr "パラメータの後に余分な文字" -#: scan.l:1022 +#: scan.l:1028 msgid "invalid hexadecimal integer" msgstr "不正な16進整数" -#: scan.l:1026 +#: scan.l:1032 msgid "invalid octal integer" msgstr "不正な8進整数" -#: scan.l:1030 +#: scan.l:1036 msgid "invalid binary integer" msgstr "不正な2進整数" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1237 +#: scan.l:1231 #, c-format msgid "%s at end of input" msgstr "入力の最後で %s" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1245 +#: scan.l:1239 #, c-format msgid "%s at or near \"%s\"" msgstr "\"%2$s\"またはその近辺で%1$s" -#: scan.l:1437 +#: scan.l:1431 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "文字列リテラルないでの\\'の非標準的な使用" -#: scan.l:1438 +#: scan.l:1432 #, c-format msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "文字列内で単一引用符を記述するには''、またはエスケープ文字列構文(E'...')を使用してください。" -#: scan.l:1447 +#: scan.l:1441 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "文字列リテラル内での\\\\の非標準的な使用" -#: scan.l:1448 +#: scan.l:1442 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "バックスラッシュのエスケープ文字列構文、例えばE'\\\\'を使用してください。" -#: scan.l:1462 +#: scan.l:1456 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "文字列リテラル内でのエスケープの非標準的な使用" -#: scan.l:1463 +#: scan.l:1457 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "エスケープのエスケープ文字列構文、例えばE'\\r\\n'を使用してください。" -#: snowball/dict_snowball.c:215 +#: snowball/dict_snowball.c:220 #, c-format msgid "no Snowball stemmer available for language \"%s\" and encoding \"%s\"" msgstr "言語\"%s\"および符号化方式\"%s\"用に使用可能なSnowballステマがありません" -#: snowball/dict_snowball.c:238 tsearch/dict_ispell.c:74 tsearch/dict_simple.c:49 +#: snowball/dict_snowball.c:243 tsearch/dict_ispell.c:75 tsearch/dict_simple.c:50 #, c-format msgid "multiple StopWords parameters" msgstr "重複したStopWordsパラメータ" -#: snowball/dict_snowball.c:247 +#: snowball/dict_snowball.c:252 #, c-format msgid "multiple Language parameters" msgstr "重複したLanguageパラメータ" -#: snowball/dict_snowball.c:254 +#: snowball/dict_snowball.c:259 #, c-format msgid "unrecognized Snowball parameter: \"%s\"" msgstr "認識できないSnowballパラメータ: \"%s\"" -#: snowball/dict_snowball.c:262 +#: snowball/dict_snowball.c:267 #, c-format msgid "missing Language parameter" msgstr "Languageパラメータがありません" -#: statistics/extended_stats.c:176 +#: statistics/attribute_stats.c:191 statistics/attribute_stats.c:932 statistics/relation_stats.c:98 +#, c-format +msgid "Statistics cannot be modified during recovery." +msgstr "リカバリ中は統計情報の更新はできません。" + +#: statistics/attribute_stats.c:202 +#, c-format +msgid "cannot specify both attname and attnum" +msgstr "attname と attnum の両方を指定することはできません" + +#: statistics/attribute_stats.c:228 +#, c-format +msgid "must specify either attname or attnum" +msgstr "attname または attnum のいずれかを指定する必要があります" + +#: statistics/attribute_stats.c:236 +#, c-format +msgid "cannot modify statistics on system column \"%s\"" +msgstr "システム列\"%s\"の統計情報は更新できません" + +#: statistics/attribute_stats.c:300 +#, c-format +msgid "unable to determine element type of attribute \"%s\"" +msgstr "属性 \"%s\" の要素型を特定できません" + +#: statistics/attribute_stats.c:301 +#, c-format +msgid "Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST." +msgstr "STATISTIC_KIND_MCELEM および STATISTIC_KIND_DECHIST は設定できません。" + +#: statistics/attribute_stats.c:316 +#, c-format +msgid "could not determine less-than operator for attribute \"%s\"" +msgstr "属性 \"%s\" の小なり演算子(<)を特定できませんでした" + +#: statistics/attribute_stats.c:317 +#, c-format +msgid "Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION." +msgstr "STATISTIC_KIND_HISTOGRAM および STATISTIC_KIND_CORRELATION は設定できません。" + +#: statistics/attribute_stats.c:330 +#, c-format +msgid "attribute \"%s\" is not a range type" +msgstr "属性 \"%s\" は範囲型ではありません" + +#: statistics/attribute_stats.c:331 +#, c-format +msgid "Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM." +msgstr "STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM および STATISTIC_KIND_BOUNDS_HISTOGRAM は設定できません。" + +#: statistics/attribute_stats.c:590 statistics/attribute_stats.c:598 +#, c-format +msgid "attribute %d of relation \"%s\" does not exist" +msgstr "リレーション \"%2$s\" の属性%1$dは存在しません" + +#: statistics/attribute_stats.c:732 statistics/stat_utils.c:80 +#, c-format +msgid "\"%s\" array cannot contain NULL values" +msgstr "\"%s\" の配列はNULL値を格納できません" + +#: statistics/attribute_stats.c:775 +#, c-format +msgid "maximum number of statistics slots exceeded: %d" +msgstr "統計情報スロットの最大数を超過しました: %d" + +#: statistics/attribute_stats.c:942 +#, c-format +msgid "cannot clear statistics on system column \"%s\"" +msgstr "システム列\"%s\"の統計情報はクリアできません" + +#: statistics/extended_stats.c:175 #, c-format msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "統計オブジェクト\"%s.%s\"がリレーション\"%s.%s\"に対して計算できませんでした" @@ -22087,57 +22806,210 @@ msgstr "統計オブジェクト\"%s.%s\"がリレーション\"%s.%s\"に対し msgid "function returning record called in context that cannot accept type record" msgstr "レコード型を受け付けられないコンテキストでレコードを返す関数が呼び出されました" -#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 +#: statistics/relation_stats.c:115 #, c-format -msgid "cannot access temporary tables of other sessions" -msgstr "他のセッションの一時テーブルにはアクセスできません" +msgid "reltuples cannot be < -1.0" +msgstr "reltuplesは-1.0未満にはできません" -#: storage/buffer/bufmgr.c:1532 +#: statistics/stat_utils.c:44 #, c-format -msgid "invalid page in block %u of relation %s; zeroing out page" -msgstr "リレーション %2$s の %1$u ブロック目のページが不正です: ページをゼロで埋めました" +msgid "\"%s\" cannot be NULL" +msgstr "\"%s\"はNULLにはできません" + +#: statistics/stat_utils.c:71 +#, c-format +msgid "\"%s\" cannot be a multidimensional array" +msgstr "\"%s\"は多次元配列にはなれません" + +#: statistics/stat_utils.c:111 +#, c-format +msgid "\"%s\" must be specified when \"%s\" is specified" +msgstr "\"%s” は、\"%s\"が指定される際には必ず指定される必要があります" + +#: statistics/stat_utils.c:178 +#, c-format +msgid "cannot modify statistics for relation \"%s\"" +msgstr "リレーション\"%s\"の統計情報は変更できません" + +#: statistics/stat_utils.c:199 +#, c-format +msgid "cannot modify statistics for shared relation" +msgstr "共有リレーションの統計情報は変更できません" + +#: statistics/stat_utils.c:252 +#, c-format +msgid "unrecognized argument name: \"%s\"" +msgstr "識別できない引数名: \"%s\"" + +#: statistics/stat_utils.c:266 +#, c-format +msgid "argument \"%s\" has type \"%s\", expected type \"%s\"" +msgstr "引数\"%s\"の型は\"%s\"ですが、期待される型は\"%s\"です" + +#: statistics/stat_utils.c:307 +#, c-format +msgid "variadic arguments must be name/value pairs" +msgstr "可変長引数は名前/値のペアである必要があります" + +#: statistics/stat_utils.c:308 +#, c-format +msgid "Provide an even number of variadic arguments that can be divided into pairs." +msgstr "2つ組に分割できるよう、偶数個の可変長引数を指定してください。" + +#: statistics/stat_utils.c:322 +#, c-format +msgid "name at variadic position %d is NULL" +msgstr "可変長引数の位置%dの名前がNULLです" + +#: statistics/stat_utils.c:326 +#, c-format +msgid "name at variadic position %d has type \"%s\", expected type \"%s\"" +msgstr "可変長引数の位置%dの名前の型が\"%s\"ですが、期待される型は\"%s\"です" + +#: storage/aio/aio.c:1222 +#, c-format +msgid "Only -1 or values bigger than 0 are valid." +msgstr "-1または0より大きい値のみ有効です。" + +#: storage/aio/method_io_uring.c:171 +msgid "Check if io_uring is disabled via /proc/sys/kernel/io_uring_disabled." +msgstr "io_uringが無効化されていないかを /proc/sys/kernel/io_uring_disabled で確認してください。" + +#: storage/aio/method_io_uring.c:176 +#, c-format +msgid "Consider increasing \"ulimit -n\" to at least %d." +msgstr "\"ulimit -n\"を少なくとも%dに増やすことを検討してください。" + +#: storage/aio/method_io_uring.c:182 +msgid "Kernel does not support io_uring." +msgstr "カーネルはio_uringをサポートしていません。" + +#: storage/aio/method_io_uring.c:190 +#, c-format +msgid "could not setup io_uring queue: %m" +msgstr "io_uringキューのセットアップに失敗しました: %m" + +#: storage/aio/method_io_uring.c:324 +#, c-format +msgid "completing I/O on behalf of process %d" +msgstr "プロセス %d に代わってI/O完了させています" -#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 +#: storage/aio/method_worker.c:379 +#, c-format +msgid "I/O worker executing I/O on behalf of process %d" +msgstr "I/Oワーカーがプロセス %d に代わってI/Oを実行中" + +#: storage/buffer/bufmgr.c:655 storage/buffer/bufmgr.c:811 +#, c-format +msgid "cannot access temporary tables of other sessions" +msgstr "他のセッションの一時テーブルにはアクセスできません" + +#: storage/buffer/bufmgr.c:2701 storage/buffer/localbuf.c:393 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "リレーション\"%s\"を%uブロックを超えて拡張できません" -#: storage/buffer/bufmgr.c:2348 +#: storage/buffer/bufmgr.c:2772 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "リレーション %2$s の %1$u ブロック目で、EOF の先に想定外のデータを検出しました" -#: storage/buffer/bufmgr.c:2350 +#: storage/buffer/bufmgr.c:2775 #, c-format msgid "This has been seen to occur with buggy kernels; consider updating your system." msgstr "これはカーネルの不具合で発生した模様です。システムの更新を検討してください。" -#: storage/buffer/bufmgr.c:5653 +#: storage/buffer/bufmgr.c:6115 #, c-format msgid "could not write block %u of %s" msgstr "%u ブロックを %s に書き出せませんでした" -#: storage/buffer/bufmgr.c:5655 +#: storage/buffer/bufmgr.c:6119 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "複数回失敗しました ---ずっと書き込みエラーが続くかもしれません。" -#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 +#: storage/buffer/bufmgr.c:6136 storage/buffer/bufmgr.c:6151 #, c-format msgid "writing block %u of relation %s" msgstr "ブロック %u を リレーション %s に書き込んでいます" -#: storage/buffer/localbuf.c:220 +#: storage/buffer/bufmgr.c:7250 +#, c-format +msgid "zeroing %u page(s) and ignoring %u checksum failure(s) among blocks %u..%u of relation %s" +msgstr "リレーション %5$s のブロック %3$u..%4$u の間で%1$uページをゼロクリアして、%2$u件のチェックサムエラーを無視しています" + +#: storage/buffer/bufmgr.c:7253 storage/buffer/bufmgr.c:7279 +#, c-format +msgid "Block %u held first zeroed page." +msgstr "ゼロクリアした最初のページはブロック %u にありました。" + +#: storage/buffer/bufmgr.c:7255 +#, c-format +msgid "See server log for details about the other %u invalid block(s)." +msgstr "他の%u個の不正なブロックの詳細については、サーバーログを参照してください。" + +#: storage/buffer/bufmgr.c:7270 +#, c-format +msgid "%u invalid pages among blocks %u..%u of relation %s" +msgstr "リレーション%4$sのブロック%2$u..%3$uに%1$uの不正なページ" + +#: storage/buffer/bufmgr.c:7271 +#, c-format +msgid "Block %u held first invalid page." +msgstr "最初の不正なページはブロック %u にありました。" + +#: storage/buffer/bufmgr.c:7272 +#, c-format +msgid "See server log for the other %u invalid block(s)." +msgstr "他の%u個の不正なブロックについてはサーバーログを参照してください。" + +#: storage/buffer/bufmgr.c:7277 +#, c-format +msgid "invalid page in block %u of relation %s; zeroing out page" +msgstr "リレーション %2$s の %1$u ブロック目のページが不正です: ページをゼロで埋めました" + +#: storage/buffer/bufmgr.c:7278 +#, c-format +msgid "zeroing out %u invalid pages among blocks %u..%u of relation %s" +msgstr "リレーション %4$s のブロック%2$u~%3$uにある%1$u個の不正なページをゼロクリアします" + +#: storage/buffer/bufmgr.c:7280 +#, c-format +msgid "See server log for the other %u zeroed block(s)." +msgstr "他の%u個の0クリアしたブロックについてはサーバーログを参照してください。" + +#: storage/buffer/bufmgr.c:7285 +#, c-format +msgid "ignoring checksum failure in block %u of relation %s" +msgstr "リレーション%2$sでのブロック%1$uのチェックサムエラーを無視します" + +#: storage/buffer/bufmgr.c:7286 +#, c-format +msgid "ignoring %u checksum failures among blocks %u..%u of relation %s" +msgstr "リレーション%4$sでのブロック%2$u..%3$uの%1$u件のチェックサムエラーを無視します" + +#: storage/buffer/bufmgr.c:7287 +#, c-format +msgid "Block %u held first ignored page." +msgstr "無視した最初のページはブロック %u にありました。" + +#: storage/buffer/bufmgr.c:7288 +#, c-format +msgid "See server log for the other %u ignored block(s)." +msgstr "他の%u個のエラーを無視したブロックについてはサーバーログを参照してください。" + +#: storage/buffer/localbuf.c:272 #, c-format msgid "no empty local buffer available" msgstr "利用できる、空のローカルバッファがありません" -#: storage/buffer/localbuf.c:597 +#: storage/buffer/localbuf.c:736 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "並列処理中は一時テーブルにはアクセスできません" -#: storage/buffer/localbuf.c:712 +#: storage/buffer/localbuf.c:876 #, c-format msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." msgstr "当該セッションで何らかの一時テーブルがアクセスされた後は\"temp_buffers\"を変更できません。" @@ -22157,21 +23029,26 @@ msgstr "ファイルセット\"%1$s\"からの読み込みができませんで msgid "could not read from temporary file: read only %zu of %zu bytes" msgstr "一時ファイルからの読み込み失敗しました: %2$zuバイト中%1$zuバイト分のみ読み込みました" -#: storage/file/buffile.c:774 storage/file/buffile.c:877 +#: storage/file/buffile.c:774 storage/file/buffile.c:875 #, c-format msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" msgstr "BufFile \"%s\"の一時ファイル\"%s\"のサイズの確認に失敗しました: %m" -#: storage/file/buffile.c:956 +#: storage/file/buffile.c:951 #, c-format msgid "could not delete fileset \"%s\": %m" msgstr "ファイルセット\"%s\"を削除できませんでした: %m" -#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1192 +#: storage/file/buffile.c:969 storage/smgr/md.c:356 storage/smgr/md.c:1318 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "ファイル\"%s\"の切り詰め処理ができませんでした: %m" +#: storage/file/copydir.c:244 storage/file/copydir.c:275 +#, c-format +msgid "could not clone file \"%s\" to \"%s\": %m" +msgstr "ファイル\"%s\"を\"%s\"にクローニングできませんでした: %m" + #: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" @@ -22192,120 +23069,120 @@ msgstr "データの書き出し中にmunmap()に失敗しました: %m" msgid "getrlimit failed: %m" msgstr "getrlimitが失敗しました: %m" -#: storage/file/fd.c:1073 +#: storage/file/fd.c:1074 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "サーバープロセスを起動させるために利用できるファイル記述子が不足しています" -#: storage/file/fd.c:1074 +#: storage/file/fd.c:1075 #, c-format -msgid "System allows %d, server needs at least %d." -msgstr "システムでは%d使用できますが、サーバーでは少なくとも%d必要です。" +msgid "System allows %d, server needs at least %d, %d files are already open." +msgstr "システムでは%d個のファイルを使用できますが、サーバーでは少なくとも%d個必要で、すでに%d個がオープンされています。" -#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 storage/file/fd.c:2878 +#: storage/file/fd.c:1164 storage/file/fd.c:2679 storage/file/fd.c:2788 storage/file/fd.c:2942 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "ファイル記述子が不足しています: %m: 解放後再実行してください" -#: storage/file/fd.c:1536 +#: storage/file/fd.c:1540 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "一時ファイル: パス \"%s\"、サイズ %lu" -#: storage/file/fd.c:1675 +#: storage/file/fd.c:1679 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "一時ディレクトリ\"%s\"を作成できませんでした: %m" -#: storage/file/fd.c:1682 +#: storage/file/fd.c:1686 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "一時サブディレクトリ\"%s\"を作成できませんでした: %m" -#: storage/file/fd.c:1879 +#: storage/file/fd.c:1883 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "一時ファイル\"%s\"を作成できませんでした: %m" -#: storage/file/fd.c:1915 +#: storage/file/fd.c:1919 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "一時ファイル\"%s\"をオープンできませんでした: %m" -#: storage/file/fd.c:1956 +#: storage/file/fd.c:1960 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "一時ファイル\"%s\"を unlink できませんでした: %m" -#: storage/file/fd.c:2044 +#: storage/file/fd.c:2050 #, c-format msgid "could not delete file \"%s\": %m" msgstr "ファイル\"%s\"を削除できませんでした: %m" -#: storage/file/fd.c:2234 +#: storage/file/fd.c:2289 #, c-format -msgid "temporary file size exceeds temp_file_limit (%dkB)" -msgstr "一時ファイルのサイズがtemp_file_limit(%d KB)を超えています" +msgid "temporary file size exceeds \"temp_file_limit\" (%dkB)" +msgstr "一時ファイルのサイズが\"temp_file_limit\" (%dkB)を超えています" -#: storage/file/fd.c:2594 storage/file/fd.c:2653 +#: storage/file/fd.c:2655 storage/file/fd.c:2714 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "ファイル\"%2$s\"をオープンしようとした時にmaxAllocatedDescs(%1$d)を超えました" -#: storage/file/fd.c:2698 +#: storage/file/fd.c:2759 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "コマンド\"%2$s\"を実行しようとした時にmaxAllocatedDescs(%1$d)を超えました" -#: storage/file/fd.c:2854 +#: storage/file/fd.c:2918 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "ディレクトリ\"%2$s\"をオープンしようとした時にmaxAllocatedDescs(%1$d)を超えました" -#: storage/file/fd.c:3384 +#: storage/file/fd.c:3449 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "一時ファイル用ディレクトリに想定外のファイルがありました: \"%s\"" -#: storage/file/fd.c:3502 +#: storage/file/fd.c:3567 #, c-format msgid "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "データディレクトリを同期しています(syncfs)、経過時間: %ld.%02d秒, 現在のパス: %s" -#: storage/file/fd.c:3729 +#: storage/file/fd.c:3794 #, c-format msgid "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "データディレクトリを同期しています(pre-syncfs)、経過時間: %ld.%02d秒, 現在のパス: %s" -#: storage/file/fd.c:3761 +#: storage/file/fd.c:3826 #, c-format msgid "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "データディレクトリを同期しています(fsync)、経過時間: %ld.%02d秒, 現在のパス: %s" -#: storage/file/fd.c:3950 +#: storage/file/fd.c:4015 #, c-format -msgid "\"debug_io_direct\" is not supported on this platform." -msgstr "このプラットフォームでは\"debug_io_direct\"はサポートされていません。" +msgid "\"%s\" is not supported on this platform." +msgstr "このプラットフォームでは\"%s\"をサポートしていません。" -#: storage/file/fd.c:3964 +#: storage/file/fd.c:4030 #, c-format -msgid "Invalid list syntax in parameter \"%s\"" -msgstr "パラメータ\"%s\"のリスト構文が不正です" +msgid "Invalid list syntax in parameter \"%s\"." +msgstr "パラメータ\"%s\"のリスト構文が不正です。" -#: storage/file/fd.c:3984 +#: storage/file/fd.c:4050 tcop/backend_startup.c:1054 #, c-format -msgid "Invalid option \"%s\"" -msgstr "不正なオプション\"%s\"" +msgid "Invalid option \"%s\"." +msgstr "不正なオプション\"%s\"。" -#: storage/file/fd.c:3997 +#: storage/file/fd.c:4063 #, c-format -msgid "\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" -msgstr "XLOG_BLCKSZが小さすぎるため\"debug_io_direct\"はWALに対してはサポートされません" +msgid "\"%s\" is not supported for WAL because %s is too small." +msgstr "%2$sが小さすぎるため\"%1$s\"はWALに対してはサポートされません。" -#: storage/file/fd.c:4004 +#: storage/file/fd.c:4071 #, c-format -msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" -msgstr "BLCKSZが小さすぎるため\"debug_io_direct\"はデータに対してサポートされません" +msgid "\"%s\" is not supported for data because %s is too small." +msgstr "%2$sが小さすぎるため\"%1$s\"はデータに対してはサポートされません。" #: storage/file/reinit.c:145 #, c-format @@ -22407,36 +23284,46 @@ msgstr "DSMセグメントサイズは0以外の値である必要がありま msgid "requested DSM segment size does not match size of existing segment" msgstr "要求されたDSMセグメントサイズが既存のセグメントのサイズと異なっています" -#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:352 tcop/backend_startup.c:304 +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:458 tcop/backend_startup.c:343 #, c-format msgid "sorry, too many clients already" msgstr "現在クライアント数が多すぎます" -#: storage/ipc/procarray.c:3845 +#: storage/ipc/procarray.c:3858 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "データベース\"%s\"は準備済みトランザクションで使用中です" -#: storage/ipc/procarray.c:3881 storage/ipc/procarray.c:3889 storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 +#: storage/ipc/procarray.c:3894 storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:256 storage/ipc/signalfuncs.c:263 storage/ipc/signalfuncs.c:270 #, c-format msgid "permission denied to terminate process" msgstr "プロセスを終了させる権限がありません" -#: storage/ipc/procarray.c:3882 storage/ipc/signalfuncs.c:236 +#: storage/ipc/procarray.c:3895 storage/ipc/signalfuncs.c:257 #, c-format msgid "Only roles with the %s attribute may terminate processes of roles with the %s attribute." msgstr "%s属性を持つロールのみが%s属性を持つロールが接続中のプロセスを終了できます。" -#: storage/ipc/procarray.c:3890 storage/ipc/signalfuncs.c:243 +#: storage/ipc/procarray.c:3903 storage/ipc/signalfuncs.c:271 #, c-format msgid "Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process." msgstr "終了させようとしているプロセスに接続しているロールの権限を持つロール、または\"%sロール権限を持つロールのみがこのプロセスを終了できます。" -#: storage/ipc/procsignal.c:416 +#: storage/ipc/procsignal.c:450 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "PID %dのバックエンドがProcSignalBarrierを受け付けるのを待っています" +#: storage/ipc/procsignal.c:786 +#, c-format +msgid "wrong key in cancel request for process %d" +msgstr "プロセス%dに対するキャンセル要求においてキーが間違っています" + +#: storage/ipc/procsignal.c:795 +#, c-format +msgid "PID %d in cancel request did not match any process" +msgstr "キャンセル要求内のPID %dがどのプロセスにも一致しません" + #: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" @@ -22447,215 +23334,225 @@ msgstr "共有メモリキュー経由で大きさ%zuのメッセージは送信 msgid "invalid message size %zu in shared memory queue" msgstr "共有メモリキュー内の不正なメッセージ長%zu" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:962 storage/lmgr/lock.c:1000 storage/lmgr/lock.c:2803 storage/lmgr/lock.c:4188 storage/lmgr/lock.c:4253 storage/lmgr/lock.c:4603 storage/lmgr/predicate.c:2463 storage/lmgr/predicate.c:2478 storage/lmgr/predicate.c:3875 storage/lmgr/predicate.c:4922 utils/hash/dynahash.c:1095 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:1038 storage/lmgr/lock.c:1076 storage/lmgr/lock.c:2965 storage/lmgr/lock.c:4370 storage/lmgr/lock.c:4435 storage/lmgr/lock.c:4785 storage/lmgr/predicate.c:2478 storage/lmgr/predicate.c:2493 storage/lmgr/predicate.c:3890 storage/lmgr/predicate.c:4937 utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "共有メモリが足りません" -#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 +#: storage/ipc/shmem.c:159 storage/ipc/shmem.c:255 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "共有メモリが足りません (%zu バイト要求しました)" -#: storage/ipc/shmem.c:436 +#: storage/ipc/shmem.c:434 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "データ構造体\"%s\"のためのShmemIndexエントリを作成できませんでした" -#: storage/ipc/shmem.c:451 +#: storage/ipc/shmem.c:449 #, c-format msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu" msgstr "データ構造体\"%s\"のためのShmemIndexエントリのサイズが誤っています: %zuバイトを期待しましたが、実際は%zuバイトでした" -#: storage/ipc/shmem.c:470 +#: storage/ipc/shmem.c:468 #, c-format msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)" msgstr "データ構造体\"%s\"のための共有メモリが不足しています ( %zu バイトが必要)" -#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 +#: storage/ipc/shmem.c:500 storage/ipc/shmem.c:519 #, c-format msgid "requested shared memory size overflows size_t" msgstr "要求された共有メモリのサイズはsize_tを超えています" -#: storage/ipc/signalfuncs.c:72 +#: storage/ipc/signalfuncs.c:74 #, c-format msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %dはPostgreSQLバックエンドプロセスではありません" -#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1448 utils/adt/mcxtfuncs.c:182 +#: storage/ipc/signalfuncs.c:123 storage/lmgr/proc.c:1547 utils/adt/mcxtfuncs.c:314 utils/adt/mcxtfuncs.c:412 #, c-format msgid "could not send signal to process %d: %m" msgstr "プロセス%dにシグナルを送信できませんでした: %m" -#: storage/ipc/signalfuncs.c:129 storage/ipc/signalfuncs.c:136 +#: storage/ipc/signalfuncs.c:143 storage/ipc/signalfuncs.c:150 storage/ipc/signalfuncs.c:157 #, c-format msgid "permission denied to cancel query" msgstr "問い合わせをキャンセルする権限がありません" -#: storage/ipc/signalfuncs.c:130 +#: storage/ipc/signalfuncs.c:144 #, c-format msgid "Only roles with the %s attribute may cancel queries of roles with the %s attribute." msgstr "%s属性を持つロールのみが、%s属性を持つロールが実行中の問い合わせをキャンセルできます。" -#: storage/ipc/signalfuncs.c:137 +#: storage/ipc/signalfuncs.c:151 +#, c-format +msgid "Only roles with privileges of the \"%s\" role may cancel autovacuum workers." +msgstr "\"%s\"ロールの権限を持つロールのみが自動VACUUMワーカーのキャンセルを行うことができます。" + +#: storage/ipc/signalfuncs.c:158 #, c-format msgid "Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query." msgstr "キャンセル対象の問い合わせを実行しているロールの権限を持つロール、または\"%s\"ロールの権限を持つロールのみがこの問い合わせをキャンセルできます。" -#: storage/ipc/signalfuncs.c:179 +#: storage/ipc/signalfuncs.c:200 #, c-format msgid "could not check the existence of the backend with PID %d: %m" msgstr "PID %dのバックエンドの存在の確認に失敗しました: %m" -#: storage/ipc/signalfuncs.c:197 +#: storage/ipc/signalfuncs.c:218 #, c-format -msgid "backend with PID %d did not terminate within %lld millisecond" -msgid_plural "backend with PID %d did not terminate within %lld milliseconds" -msgstr[0] "PID %dのバックエンドが%lldミリ秒で終了しませんでした" +msgid "backend with PID %d did not terminate within % millisecond" +msgid_plural "backend with PID %d did not terminate within % milliseconds" +msgstr[0] "PID %dのバックエンドが%ミリ秒以内に終了しませんでした" -#: storage/ipc/signalfuncs.c:228 +#: storage/ipc/signalfuncs.c:249 #, c-format msgid "\"timeout\" must not be negative" msgstr "\"timeout\"は負数であってはなりません" -#: storage/ipc/signalfuncs.c:285 +#: storage/ipc/signalfuncs.c:264 +#, c-format +msgid "Only roles with privileges of the \"%s\" role may terminate autovacuum workers." +msgstr "\"%s\"ロールの権限を持つロールのみが自動VACUUMワーカーを終了させることができます。" + +#: storage/ipc/signalfuncs.c:313 #, c-format msgid "rotation not possible because log collection not active" msgstr "ログ収集が活動していませんのでローテーションを行うことができません" -#: storage/ipc/standby.c:329 +#: storage/ipc/standby.c:330 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "リカバリは%ld.%03dミリ秒経過後待機継続中: %s" -#: storage/ipc/standby.c:338 +#: storage/ipc/standby.c:339 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "リカバリは%ld.%03dミリ秒で待機終了: %s" -#: storage/ipc/standby.c:920 tcop/postgres.c:3169 +#: storage/ipc/standby.c:921 tcop/postgres.c:3225 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "リカバリで競合が発生したためステートメントをキャンセルしています" -#: storage/ipc/standby.c:921 tcop/postgres.c:2529 +#: storage/ipc/standby.c:922 tcop/postgres.c:2575 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "リカバリ時にユーザーのトランザクションがバッファのデッドロックを引き起こしました。" -#: storage/ipc/standby.c:1486 +#: storage/ipc/standby.c:1494 msgid "unknown reason" msgstr "不明な理由" -#: storage/ipc/standby.c:1491 +#: storage/ipc/standby.c:1499 msgid "recovery conflict on buffer pin" msgstr "バッファピンによるリカバリ競合" -#: storage/ipc/standby.c:1494 +#: storage/ipc/standby.c:1502 msgid "recovery conflict on lock" msgstr "ロック上のリカバリ衝突" -#: storage/ipc/standby.c:1497 +#: storage/ipc/standby.c:1505 msgid "recovery conflict on tablespace" msgstr "テーブル空間上のリカバリ衝突" -#: storage/ipc/standby.c:1500 +#: storage/ipc/standby.c:1508 msgid "recovery conflict on snapshot" msgstr "スナップショットによるリカバリ競合" -#: storage/ipc/standby.c:1503 +#: storage/ipc/standby.c:1511 msgid "recovery conflict on replication slot" msgstr "レプリケーションスロットに対するリカバリ競合" -#: storage/ipc/standby.c:1506 +#: storage/ipc/standby.c:1514 msgid "recovery conflict on buffer deadlock" msgstr "バッファのデッドロックによるリカバリ競合" -#: storage/ipc/standby.c:1509 +#: storage/ipc/standby.c:1517 msgid "recovery conflict on database" msgstr "データベース上のリカバリ衝突" -#: storage/large_object/inv_api.c:190 +#: storage/large_object/inv_api.c:152 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "OID%u、ページ%dに対応するpg_largeobjectのエントリのデータフィールドの大きさ%dは不正です" -#: storage/large_object/inv_api.c:272 +#: storage/large_object/inv_api.c:234 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "ラージオブジェクトを開くためのフラグが不正です: %d" -#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 storage/large_object/inv_api.c:807 +#: storage/large_object/inv_api.c:259 storage/large_object/inv_api.c:271 storage/large_object/inv_api.c:468 storage/large_object/inv_api.c:579 storage/large_object/inv_api.c:769 #, c-format msgid "permission denied for large object %u" msgstr "ラージオブジェクト %u に対する権限がありません" -#: storage/large_object/inv_api.c:455 +#: storage/large_object/inv_api.c:417 #, c-format msgid "invalid whence setting: %d" msgstr "不正なwhence設定: %d" -#: storage/large_object/inv_api.c:627 +#: storage/large_object/inv_api.c:589 #, c-format msgid "invalid large object write request size: %d" msgstr "ラージオブジェクトの書き出し要求サイズが不正です: %d" -#: storage/lmgr/deadlock.c:1104 +#: storage/lmgr/deadlock.c:1107 #, c-format msgid "Process %d waits for %s on %s; blocked by process %d." msgstr "プロセス %d は %s を %s で待機していましたが、プロセス %d でブロックされました" -#: storage/lmgr/deadlock.c:1123 +#: storage/lmgr/deadlock.c:1126 #, c-format msgid "Process %d: %s" msgstr "プロセス %d: %s" -#: storage/lmgr/deadlock.c:1132 +#: storage/lmgr/deadlock.c:1135 #, c-format msgid "deadlock detected" msgstr "デッドロックを検出しました" -#: storage/lmgr/deadlock.c:1135 +#: storage/lmgr/deadlock.c:1138 #, c-format msgid "See server log for query details." msgstr "問い合わせの詳細はサーバーログを参照してください" -#: storage/lmgr/lmgr.c:858 +#: storage/lmgr/lmgr.c:856 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプル(%1$u,%2$u)の更新中" -#: storage/lmgr/lmgr.c:861 +#: storage/lmgr/lmgr.c:859 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプル(%1$u,%2$u)の削除中" -#: storage/lmgr/lmgr.c:864 +#: storage/lmgr/lmgr.c:862 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプル(%1$u,%2$u)のロック中" -#: storage/lmgr/lmgr.c:867 +#: storage/lmgr/lmgr.c:865 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプルの更新後バージョン(%1$u,%2$u)のロック中" -#: storage/lmgr/lmgr.c:870 +#: storage/lmgr/lmgr.c:868 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のインデックスタプル(%1$u,%2$u)の挿入中" -#: storage/lmgr/lmgr.c:873 +#: storage/lmgr/lmgr.c:871 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプル(%1$u,%2$u)の一意性の確認中" -#: storage/lmgr/lmgr.c:876 +#: storage/lmgr/lmgr.c:874 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"の更新されたタプル(%1$u,%2$u)の再チェック中" -#: storage/lmgr/lmgr.c:879 +#: storage/lmgr/lmgr.c:877 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "リレーション\"%3$s\"のタプル(%1$u,%2$u)に対する排除制約のチェック中" @@ -22725,17 +23622,22 @@ msgstr "データベース%3$uのサブスクリプション%2$uのリモート msgid "unrecognized locktag type %d" msgstr "ロックタグタイプ%dは不明です" -#: storage/lmgr/lock.c:790 +#: storage/lmgr/lock.c:866 #, c-format msgid "cannot acquire lock mode %s on database objects while recovery is in progress" msgstr "リカバリの実行中はデータベースオブジェクトでロックモード %s を獲得できません" -#: storage/lmgr/lock.c:792 +#: storage/lmgr/lock.c:868 #, c-format msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery." msgstr "リカバリの実行中は、データベースオブジェクトで RowExclusiveLock もしくはそれ以下だけが獲得できます" -#: storage/lmgr/lock.c:3252 storage/lmgr/lock.c:3320 storage/lmgr/lock.c:3436 +#: storage/lmgr/lock.c:1182 +#, c-format +msgid "process %d could not obtain %s on %s" +msgstr "プロセス%1$dは、%3$sの%2$sを取得できませんでした" + +#: storage/lmgr/lock.c:3423 storage/lmgr/lock.c:3491 storage/lmgr/lock.c:3607 #, c-format msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object" msgstr "同一オブジェクト上にセッションレベルとトランザクションレベルのロックの両方を保持している時にPREPAREすることはできません" @@ -22755,485 +23657,535 @@ msgstr "トランザクションの同時実行数を減らすか\"max_connectio msgid "not enough elements in RWConflictPool to record a potential read/write conflict" msgstr "RWConflictPoolに読み書き競合の可能性を記録するための要素が不足しています" -#: storage/lmgr/predicate.c:1681 +#: storage/lmgr/predicate.c:1696 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "\"default_transaction_isolation\"が\"serializable\"に設定されました。" -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1697 #, c-format msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default." msgstr "このデフォルトを変更するためには\"SET default_transaction_isolation = 'repeatable read'\"を使用することができます。" -#: storage/lmgr/predicate.c:1733 +#: storage/lmgr/predicate.c:1748 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "スナップショットをインポートするトランザクションはREAD ONLY DEFERRABLEではいけません" -#: storage/lmgr/predicate.c:1812 utils/time/snapmgr.c:535 utils/time/snapmgr.c:541 +#: storage/lmgr/predicate.c:1827 utils/time/snapmgr.c:556 utils/time/snapmgr.c:562 #, c-format msgid "could not import the requested snapshot" msgstr "要求したスナップショットをインポートできませんでした" -#: storage/lmgr/predicate.c:1813 utils/time/snapmgr.c:542 +#: storage/lmgr/predicate.c:1828 utils/time/snapmgr.c:563 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "PID%dであるソースプロセスは既に実行中ではありません。" -#: storage/lmgr/predicate.c:3986 storage/lmgr/predicate.c:4022 storage/lmgr/predicate.c:4055 storage/lmgr/predicate.c:4063 storage/lmgr/predicate.c:4102 storage/lmgr/predicate.c:4332 storage/lmgr/predicate.c:4651 storage/lmgr/predicate.c:4663 storage/lmgr/predicate.c:4710 storage/lmgr/predicate.c:4746 +#: storage/lmgr/predicate.c:4001 storage/lmgr/predicate.c:4037 storage/lmgr/predicate.c:4070 storage/lmgr/predicate.c:4078 storage/lmgr/predicate.c:4117 storage/lmgr/predicate.c:4347 storage/lmgr/predicate.c:4666 storage/lmgr/predicate.c:4678 storage/lmgr/predicate.c:4725 storage/lmgr/predicate.c:4761 #, c-format msgid "could not serialize access due to read/write dependencies among transactions" msgstr "トランザクション間で read/write の依存性があったため、アクセスの直列化ができませんでした" -#: storage/lmgr/predicate.c:3988 storage/lmgr/predicate.c:4024 storage/lmgr/predicate.c:4057 storage/lmgr/predicate.c:4065 storage/lmgr/predicate.c:4104 storage/lmgr/predicate.c:4334 storage/lmgr/predicate.c:4653 storage/lmgr/predicate.c:4665 storage/lmgr/predicate.c:4712 storage/lmgr/predicate.c:4748 +#: storage/lmgr/predicate.c:4003 storage/lmgr/predicate.c:4039 storage/lmgr/predicate.c:4072 storage/lmgr/predicate.c:4080 storage/lmgr/predicate.c:4119 storage/lmgr/predicate.c:4349 storage/lmgr/predicate.c:4668 storage/lmgr/predicate.c:4680 storage/lmgr/predicate.c:4727 storage/lmgr/predicate.c:4763 #, c-format msgid "The transaction might succeed if retried." msgstr "リトライが行われた場合、このトランザクションは成功するかもしれません" -#: storage/lmgr/proc.c:348 +#: storage/lmgr/proc.c:454 #, c-format msgid "number of requested standby connections exceeds \"max_wal_senders\" (currently %d)" msgstr "要求されたスタンバイ接続が\"max_wal_senders を超えています\" (現在は %d)" -#: storage/lmgr/proc.c:1541 +#: storage/lmgr/proc.c:1592 #, c-format msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" msgstr "プロセス%1$dは、%4$ld.%5$03d ms後にキューの順番を再調整することで、%3$s上の%2$sに対するデッドロックを防ぎました。" -#: storage/lmgr/proc.c:1556 +#: storage/lmgr/proc.c:1607 #, c-format msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "プロセス%1$dは、%3$s上の%2$sに対し%4$ld.%5$03d ms待機するデッドロックを検知しました" -#: storage/lmgr/proc.c:1565 +#: storage/lmgr/proc.c:1616 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "プロセス%dは%sを%sで待機しています。%ld.%03dミリ秒後" -#: storage/lmgr/proc.c:1572 +#: storage/lmgr/proc.c:1623 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "プロセス%1$dは%4$ld.%5$03d ms後に%3$s上の%2$sを獲得しました" -#: storage/lmgr/proc.c:1589 +#: storage/lmgr/proc.c:1640 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "プロセス%1$dは%4$ld.%5$03d ms後に%3$s上で%2$sを獲得することに失敗しました" -#: storage/page/bufpage.c:152 +#: storage/page/bufpage.c:154 #, c-format msgid "page verification failed, calculated checksum %u but expected %u" msgstr "ページ検証が失敗しました。計算されたチェックサムは%uですが想定は%uです" -#: storage/page/bufpage.c:217 storage/page/bufpage.c:730 storage/page/bufpage.c:1073 storage/page/bufpage.c:1208 storage/page/bufpage.c:1314 storage/page/bufpage.c:1426 +#: storage/page/bufpage.c:216 storage/page/bufpage.c:729 storage/page/bufpage.c:1072 storage/page/bufpage.c:1207 storage/page/bufpage.c:1313 storage/page/bufpage.c:1425 #, c-format msgid "corrupted page pointers: lower = %u, upper = %u, special = %u" msgstr "ページポインタが破損しています: lower = %u, upper = %u, special = %u\"" -#: storage/page/bufpage.c:759 +#: storage/page/bufpage.c:758 #, c-format msgid "corrupted line pointer: %u" msgstr "ラインポインタが破損しています: %u" -#: storage/page/bufpage.c:789 storage/page/bufpage.c:1266 +#: storage/page/bufpage.c:788 storage/page/bufpage.c:1265 #, c-format msgid "corrupted item lengths: total %u, available space %u" msgstr "アイテム長が破損しています: 合計 %u 利用可能空間 %u" -#: storage/page/bufpage.c:1092 storage/page/bufpage.c:1233 storage/page/bufpage.c:1330 storage/page/bufpage.c:1442 +#: storage/page/bufpage.c:1091 storage/page/bufpage.c:1232 storage/page/bufpage.c:1329 storage/page/bufpage.c:1441 #, c-format msgid "corrupted line pointer: offset = %u, size = %u" msgstr "ラインポインタが破損しています: オフセット = %u サイズ = %u" -#: storage/smgr/md.c:485 storage/smgr/md.c:547 +#: storage/smgr/md.c:502 storage/smgr/md.c:564 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "ファイル\"%s\"を%uブロック以上に拡張できません" -#: storage/smgr/md.c:500 storage/smgr/md.c:611 +#: storage/smgr/md.c:517 storage/smgr/md.c:628 #, c-format msgid "could not extend file \"%s\": %m" msgstr "ファイル\"%s\"を拡張できませんでした: %m" -#: storage/smgr/md.c:506 +#: storage/smgr/md.c:523 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "ファイル\"%1$s\"を拡張できませんでした: %4$uブロックで%3$dバイト中%2$dバイト分のみを書き出しました。" -#: storage/smgr/md.c:589 +#: storage/smgr/md.c:606 #, c-format msgid "could not extend file \"%s\" with FileFallocate(): %m" msgstr "ファイル\"%s\"をFileFallocate()で拡張できませんでした: %m" -#: storage/smgr/md.c:869 +#: storage/smgr/md.c:899 storage/smgr/md.c:2047 #, c-format msgid "could not read blocks %u..%u in file \"%s\": %m" msgstr "ファイル\"%3$s\"でブロック範囲 %1$u...%2$u を読み取れませんでした: %3$m" -#: storage/smgr/md.c:895 +#: storage/smgr/md.c:946 storage/smgr/md.c:2060 #, c-format msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" msgstr "ファイル\"%3$s\"でブロック範囲 %1$u...%2$u を読み取れませんでした: %5$zuバイト中%4$zuバイト分のみ読み込みました" -#: storage/smgr/md.c:995 +#: storage/smgr/md.c:1023 +#, c-format +msgid "could not start reading blocks %u..%u in file \"%s\": %m" +msgstr "ファイル\"%3$s\"のブロック範囲 %1$u...%2$u の読み取りを開始できませんでした: %m" + +#: storage/smgr/md.c:1119 #, c-format msgid "could not write blocks %u..%u in file \"%s\": %m" msgstr "ファイル\"%3$s\"でブロック範囲 %1$u...%2$u を書き込めませんでした: %3$m" -#: storage/smgr/md.c:1163 +#: storage/smgr/md.c:1289 #, c-format msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" msgstr "ファイル\"%s\"を%uブロックに切り詰められませんでした: 現在は%uブロックのみとなりました" -#: storage/smgr/md.c:1218 +#: storage/smgr/md.c:1344 #, c-format msgid "could not truncate file \"%s\" to %u blocks: %m" msgstr "ファイル\"%s\"を%uブロックに切り詰められませんでした: %m" -#: storage/smgr/md.c:1688 +#: storage/smgr/md.c:1832 #, c-format msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" msgstr "ファイル\"%s\"(対象ブロック%u)をオープンできませんでした: 直前のセグメントは%uブロックだけでした" -#: storage/smgr/md.c:1702 +#: storage/smgr/md.c:1846 #, c-format msgid "could not open file \"%s\" (target block %u): %m" msgstr "ファイル \"%s\"(対象ブロック %u)をオープンできませんでした: %m" -#: tcop/backend_startup.c:85 +#: storage/smgr/smgr.c:1106 #, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "SSL構成は子プロセスでは読み込めません" +msgid "file \"%s\"" +msgstr "ファイル\"%s\"" -#: tcop/backend_startup.c:208 +#: storage/smgr/smgr.c:1108 #, c-format -msgid "connection received: host=%s port=%s" -msgstr "接続を受け付けました: ホスト=%s ポート番号=%s" +msgid "block %u in file \"%s\"" +msgstr "ファイル\"%2$s\"のブロック%1$u" -#: tcop/backend_startup.c:213 +#: storage/smgr/smgr.c:1112 +#, c-format +msgid "blocks %u..%u in file \"%s\"" +msgstr "ファイル\"%3$s\"でブロック範囲 %1$u...%2$u" + +#: tcop/backend_startup.c:104 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "SSL構成は子プロセスでは読み込めません" + +#: tcop/backend_startup.c:226 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "接続を受け付けました: ホスト=%s ポート番号=%s" + +#: tcop/backend_startup.c:231 #, c-format msgid "connection received: host=%s" msgstr "接続を受け付けました: ホスト=%s" -#: tcop/backend_startup.c:277 +#: tcop/backend_startup.c:309 #, c-format msgid "the database system is starting up" msgstr "データベースシステムは起動処理中です" -#: tcop/backend_startup.c:283 +#: tcop/backend_startup.c:315 +#, c-format +msgid "the database system is not accepting connections" +msgstr "データベースシステムは接続を受け付けていません" + +#: tcop/backend_startup.c:316 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "ホットスタンバイモードは無効です。" + +#: tcop/backend_startup.c:320 tcop/backend_startup.c:327 #, c-format msgid "the database system is not yet accepting connections" msgstr "データベースシステムはまだ接続を受け付けていません" -#: tcop/backend_startup.c:284 +#: tcop/backend_startup.c:321 #, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "リカバリの一貫性はまだ確保されていません。" +msgid "Recovery snapshot is not yet ready for hot standby." +msgstr "リカバリースナップショットはホットスタンバイではまだ使用できません。" -#: tcop/backend_startup.c:288 +#: tcop/backend_startup.c:322 #, c-format -msgid "the database system is not accepting connections" -msgstr "データベースシステムは接続を受け付けていません" +msgid "To enable hot standby, close write transactions with more than %d subtransactions on the primary server." +msgstr "ホットスタンバイを有効にするため、プライマリサーバー上で%d以上のサブトランザクションを持つ書き込みトランザクションを終了させてください。" -#: tcop/backend_startup.c:289 +#: tcop/backend_startup.c:328 #, c-format -msgid "Hot standby mode is disabled." -msgstr "ホットスタンバイモードは無効です。" +msgid "Consistent recovery state has not been yet reached." +msgstr "リカバリの一貫性はまだ確保されていません。" -#: tcop/backend_startup.c:294 +#: tcop/backend_startup.c:333 #, c-format msgid "the database system is shutting down" msgstr "データベースシステムはシャットダウンしています" -#: tcop/backend_startup.c:299 +#: tcop/backend_startup.c:338 #, c-format msgid "the database system is in recovery mode" msgstr "データベースシステムはリカバリモードです" -#: tcop/backend_startup.c:414 +#: tcop/backend_startup.c:453 #, c-format msgid "received direct SSL connection request without ALPN protocol negotiation extension" msgstr "ALPNプロトコルネゴシエーション拡張を持たない直接SSL接続要求を受信しました" -#: tcop/backend_startup.c:420 +#: tcop/backend_startup.c:459 #, c-format msgid "direct SSL connection accepted" msgstr "直接SSL接続を受け付けられました" -#: tcop/backend_startup.c:430 +#: tcop/backend_startup.c:469 #, c-format msgid "direct SSL connection rejected" msgstr "直接SSL接続が拒否されました" -#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#: tcop/backend_startup.c:528 tcop/backend_startup.c:556 #, c-format msgid "incomplete startup packet" msgstr "開始パケットが不完全です" -#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#: tcop/backend_startup.c:540 #, c-format msgid "invalid length of startup packet" msgstr "不正な開始パケット長" -#: tcop/backend_startup.c:573 +#: tcop/backend_startup.c:597 #, c-format msgid "SSLRequest accepted" msgstr "SSLRequestを受け付けました" -#: tcop/backend_startup.c:576 +#: tcop/backend_startup.c:600 #, c-format msgid "SSLRequest rejected" msgstr "SSLRequestを拒否しました" -#: tcop/backend_startup.c:585 +#: tcop/backend_startup.c:609 #, c-format msgid "failed to send SSL negotiation response: %m" msgstr "SSLネゴシエーション応答の送信に失敗しました: %m" -#: tcop/backend_startup.c:603 +#: tcop/backend_startup.c:627 #, c-format msgid "received unencrypted data after SSL request" msgstr "SSL要求の後に非暗号化データを受信しました" -#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#: tcop/backend_startup.c:628 tcop/backend_startup.c:682 #, c-format msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." msgstr "これはクライアントソフトウェアのバグであるか、man-in-the-middle攻撃の証左である可能性があります。" -#: tcop/backend_startup.c:627 +#: tcop/backend_startup.c:651 #, c-format msgid "GSSENCRequest accepted" msgstr "GSSENCRequestを受け付けました" -#: tcop/backend_startup.c:630 +#: tcop/backend_startup.c:654 #, c-format msgid "GSSENCRequest rejected" msgstr "GSSENCRequestを拒否しました" -#: tcop/backend_startup.c:639 +#: tcop/backend_startup.c:663 #, c-format msgid "failed to send GSSAPI negotiation response: %m" msgstr "GSSAPIネゴシエーション応答の送信に失敗しました: %m" -#: tcop/backend_startup.c:657 +#: tcop/backend_startup.c:681 #, c-format msgid "received unencrypted data after GSSAPI encryption request" msgstr "GSSAPI暗号化リクエストの後に非暗号化データを受信" -#: tcop/backend_startup.c:681 +#: tcop/backend_startup.c:709 #, c-format msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" msgstr "フロントエンドプロトコル%u.%uをサポートしていません: サーバーは%u.0から %u.%uまでをサポートします" -#: tcop/backend_startup.c:744 +#: tcop/backend_startup.c:772 #, c-format msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." msgstr "有効な値: \"false\", 0, \"true\", 1, \"database\"。" -#: tcop/backend_startup.c:785 +#: tcop/backend_startup.c:813 #, c-format msgid "invalid startup packet layout: expected terminator as last byte" msgstr "開始パケットの配置が不正です: 最終バイトはターミネータであるはずです" -#: tcop/backend_startup.c:802 +#: tcop/backend_startup.c:830 #, c-format msgid "no PostgreSQL user name specified in startup packet" msgstr "開始パケットで指定されたPostgreSQLユーザー名は存在しません" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 +#: tcop/backend_startup.c:884 +#, c-format +msgid "invalid length of query cancel packet" +msgstr "不正なキャンセルパケット長" + +#: tcop/backend_startup.c:892 +#, c-format +msgid "invalid length of query cancel key" +msgstr "不正なキャンセルパケットキー長" + +#: tcop/backend_startup.c:1022 +#, c-format +msgid "Cannot specify log_connections option \"%s\" in a list with other options." +msgstr "log_connectionsオプション\"%s\"は、リスト内で他のオプションと同時に指定できません。" + +#: tcop/backend_startup.c:1080 +#, c-format +msgid "Invalid list syntax in parameter \"log_connections\"." +msgstr "パラメータ\"log_connections\"のリスト構文が不正です。" + +#: tcop/fastpath.c:141 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "OID %uの関数は存在しません" -#: tcop/fastpath.c:149 +#: tcop/fastpath.c:148 #, c-format msgid "cannot call function \"%s\" via fastpath interface" msgstr "関数\"%s\"は高速呼び出しインタフェースでの呼び出しはできません" -#: tcop/fastpath.c:234 +#: tcop/fastpath.c:233 #, c-format msgid "fastpath function call: \"%s\" (OID %u)" msgstr "近道関数呼び出し: \"%s\"(OID %u))" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 tcop/postgres.c:2055 tcop/postgres.c:2305 +#: tcop/fastpath.c:312 tcop/postgres.c:1364 tcop/postgres.c:1600 tcop/postgres.c:2079 tcop/postgres.c:2351 #, c-format msgid "duration: %s ms" msgstr "期間: %s ミリ秒" -#: tcop/fastpath.c:317 +#: tcop/fastpath.c:316 #, c-format msgid "duration: %s ms fastpath function call: \"%s\" (OID %u)" msgstr "期間: %sミリ秒 ファストパス関数呼び出し: \"%s\" (OID %u)" -#: tcop/fastpath.c:353 +#: tcop/fastpath.c:352 #, c-format msgid "function call message contains %d arguments but function requires %d" msgstr "関数呼び出しメッセージには%d引数ありましたが、関数には%d必要です" -#: tcop/fastpath.c:361 +#: tcop/fastpath.c:360 #, c-format msgid "function call message contains %d argument formats but %d arguments" msgstr "関数呼び出しメッセージには%dの引数書式がありましたが、引数は%dでした" -#: tcop/fastpath.c:385 +#: tcop/fastpath.c:384 #, c-format msgid "invalid argument size %d in function call message" msgstr "関数呼び出しメッセージ内の引数サイズ%dが不正です" -#: tcop/fastpath.c:448 +#: tcop/fastpath.c:447 #, c-format msgid "incorrect binary data format in function argument %d" msgstr "関数引数%dのバイナリデータ書式が不正です" -#: tcop/postgres.c:463 tcop/postgres.c:4925 +#: tcop/postgres.c:455 tcop/postgres.c:5023 #, c-format msgid "invalid frontend message type %d" msgstr "フロントエンドメッセージタイプ%dが不正です" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1070 #, c-format msgid "statement: %s" msgstr "文: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1369 #, c-format msgid "duration: %s ms statement: %s" msgstr "期間: %s ミリ秒 文: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1475 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "準備された文に複数のコマンドを挿入できません" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1605 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "期間: %s ミリ秒 パース%s : %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2625 +#: tcop/postgres.c:1672 tcop/postgres.c:2671 #, c-format msgid "unnamed prepared statement does not exist" msgstr "無名の準備された文が存在しません" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1724 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "バインドメッセージは%dパラメータ書式ありましたがパラメータは%dでした" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1730 #, c-format msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d" msgstr "バインドメッセージは%dパラメータを提供しましたが、準備された文\"%s\"では%d必要でした" -#: tcop/postgres.c:1933 +#: tcop/postgres.c:1944 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "バインドパラメータ%dにおいてバイナリデータ書式が不正です" -#: tcop/postgres.c:2060 +#: tcop/postgres.c:2084 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "期間: %s ミリ秒 バインド %s%s%s: %s" -#: tcop/postgres.c:2114 tcop/postgres.c:2708 +#: tcop/postgres.c:2139 tcop/postgres.c:2753 #, c-format msgid "portal \"%s\" does not exist" msgstr "ポータル\"%s\"は存在しません" -#: tcop/postgres.c:2185 +#: tcop/postgres.c:2232 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2187 tcop/postgres.c:2313 +#: tcop/postgres.c:2234 tcop/postgres.c:2359 msgid "execute fetch from" msgstr "取り出し実行" -#: tcop/postgres.c:2188 tcop/postgres.c:2314 +#: tcop/postgres.c:2235 tcop/postgres.c:2360 msgid "execute" msgstr "実行" -#: tcop/postgres.c:2310 +#: tcop/postgres.c:2356 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "期間: %s ミリ秒 %s %s%s%s: %s" -#: tcop/postgres.c:2458 +#: tcop/postgres.c:2504 #, c-format msgid "prepare: %s" msgstr "準備: %s" -#: tcop/postgres.c:2483 +#: tcop/postgres.c:2529 #, c-format msgid "Parameters: %s" msgstr "パラメータ: %s" -#: tcop/postgres.c:2498 +#: tcop/postgres.c:2544 #, c-format msgid "Abort reason: recovery conflict" msgstr "異常終了の理由: リカバリ衝突" -#: tcop/postgres.c:2514 +#: tcop/postgres.c:2560 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "ユーザーが共有バッファ・ピンを長く保持し過ぎていました" -#: tcop/postgres.c:2517 +#: tcop/postgres.c:2563 #, c-format msgid "User was holding a relation lock for too long." msgstr "ユーザーリレーションのロックを長く保持し過ぎていました" -#: tcop/postgres.c:2520 +#: tcop/postgres.c:2566 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "削除されるべきテーブルスペースをユーザーが使っていました(もしくはその可能性がありました)。" -#: tcop/postgres.c:2523 +#: tcop/postgres.c:2569 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "削除されるべきバージョンの行をユーザー問い合わせが参照しなければならなかった可能性がありました。" -#: tcop/postgres.c:2526 +#: tcop/postgres.c:2572 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "無効化されるべき論理レプリケーションスロットをユーザーが使用していました。" -#: tcop/postgres.c:2532 +#: tcop/postgres.c:2578 #, c-format msgid "User was connected to a database that must be dropped." msgstr "削除されるべきデータベースにユーザーが接続していました。" -#: tcop/postgres.c:2571 +#: tcop/postgres.c:2617 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "ポータル\"%s\" パラメータ$%d = %s" -#: tcop/postgres.c:2574 +#: tcop/postgres.c:2620 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "ポータル\"%s\" パラメータ $%d" -#: tcop/postgres.c:2580 +#: tcop/postgres.c:2626 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "無名ポータルパラメータ $%d = %s" -#: tcop/postgres.c:2583 +#: tcop/postgres.c:2629 #, c-format msgid "unnamed portal parameter $%d" msgstr "無名ポータルパラメータ $%d" -#: tcop/postgres.c:2928 +#: tcop/postgres.c:2984 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "予期しないSIGQUITシグナルによりコネクションを終了します" -#: tcop/postgres.c:2934 +#: tcop/postgres.c:2990 #, c-format msgid "terminating connection because of crash of another server process" msgstr "他のサーバープロセスがクラッシュしたため接続を終了します" -#: tcop/postgres.c:2935 +#: tcop/postgres.c:2991 #, c-format msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory." msgstr "" @@ -23241,182 +24193,177 @@ msgstr "" "postmasterはこのサーバープロセスに対し、現在のトランザクションをロールバック\n" "し終了するよう指示しました。" -#: tcop/postgres.c:2939 tcop/postgres.c:3192 +#: tcop/postgres.c:2995 tcop/postgres.c:3248 #, c-format msgid "In a moment you should be able to reconnect to the database and repeat your command." msgstr "この後、データベースに再接続し、コマンドを繰り返さなければなりません。" -#: tcop/postgres.c:2946 +#: tcop/postgres.c:3002 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "即時シャットダウンコマンドによりコネクションを終了します" -#: tcop/postgres.c:3024 +#: tcop/postgres.c:3080 #, c-format msgid "floating-point exception" msgstr "浮動小数点例外" -#: tcop/postgres.c:3025 +#: tcop/postgres.c:3081 #, c-format msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero." msgstr "不正な浮動小数点演算がシグナルされました。おそらくこれは、範囲外の結果もしくは0除算のような不正な演算によるものです。" -#: tcop/postgres.c:3190 +#: tcop/postgres.c:3246 #, c-format msgid "terminating connection due to conflict with recovery" msgstr "リカバリで競合が発生したため、接続を終了しています" -#: tcop/postgres.c:3262 +#: tcop/postgres.c:3318 #, c-format msgid "canceling authentication due to timeout" msgstr "タイムアウトにより認証処理をキャンセルしています" -#: tcop/postgres.c:3266 +#: tcop/postgres.c:3322 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "管理者コマンドにより自動VACUUM処理を終了しています" -#: tcop/postgres.c:3270 +#: tcop/postgres.c:3326 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "管理者コマンドにより、論理レプリケーションワーカーを終了します" -#: tcop/postgres.c:3290 +#: tcop/postgres.c:3341 +#, c-format +msgid "terminating walreceiver process due to administrator command" +msgstr "管理者コマンドにより WAL 受信プロセスを終了しています" + +#: tcop/postgres.c:3357 #, c-format msgid "terminating connection due to administrator command" msgstr "管理者コマンドにより接続を終了しています" -#: tcop/postgres.c:3321 +#: tcop/postgres.c:3388 #, c-format msgid "connection to client lost" msgstr "クライアントへの接続が切れました。" -#: tcop/postgres.c:3373 +#: tcop/postgres.c:3440 #, c-format msgid "canceling statement due to lock timeout" msgstr "ロックのタイムアウトのためステートメントをキャンセルしています" -#: tcop/postgres.c:3380 +#: tcop/postgres.c:3447 #, c-format msgid "canceling statement due to statement timeout" msgstr "ステートメントのタイムアウトのためステートメントをキャンセルしています" -#: tcop/postgres.c:3387 +#: tcop/postgres.c:3454 #, c-format msgid "canceling autovacuum task" msgstr "自動VACUUM処理をキャンセルしています" -#: tcop/postgres.c:3400 +#: tcop/postgres.c:3467 #, c-format msgid "canceling statement due to user request" msgstr "ユーザーからの要求により文をキャンセルしています" -#: tcop/postgres.c:3421 +#: tcop/postgres.c:3488 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "トランザクション中アイドルタイムアウトのため接続を終了します" -#: tcop/postgres.c:3434 +#: tcop/postgres.c:3501 #, c-format msgid "terminating connection due to transaction timeout" msgstr "トランザクションタイムアウトのため接続を終了します" -#: tcop/postgres.c:3447 +#: tcop/postgres.c:3514 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "アイドルセッションタイムアウトにより接続を終了します" -#: tcop/postgres.c:3537 -#, c-format -msgid "stack depth limit exceeded" -msgstr "スタック長制限を越えました" - -#: tcop/postgres.c:3538 -#, c-format -msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." -msgstr "プラットフォームのスタック長制限が適切であることを確認した後に、設定パラメータ\"max_stack_depth\" (現在 %dkB)を増やしてください。" - -#: tcop/postgres.c:3585 -#, c-format -msgid "\"max_stack_depth\" must not exceed %ldkB." -msgstr "\"max_stack_depth\"は%ldkBを越えてはなりません。" - -#: tcop/postgres.c:3587 -#, c-format -msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." -msgstr "プラットフォームのスタック長制限を\"ulimit -s\"または同等の機能を使用して増加してください" - -#: tcop/postgres.c:3610 +#: tcop/postgres.c:3553 #, c-format msgid "\"client_connection_check_interval\" must be set to 0 on this platform." msgstr "このプラットフォームでは\"client_connection_check_interval\"を0に設定する必要があります。" -#: tcop/postgres.c:3631 +#: tcop/postgres.c:3574 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "\"log_statement_stats\"が真の場合、パラメータを有効にできません" -#: tcop/postgres.c:3646 +#: tcop/postgres.c:3589 #, c-format msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true." msgstr "\"log_parser_stats\"、\"log_planner_stats\"、または\"log_executor_stats\"のいずれかがtrueの場合は\"log_statement_stats\"を有効にできません。" -#: tcop/postgres.c:4011 +#: tcop/postgres.c:4029 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "サーバープロセスに対する不正なコマンドライン引数: %s" -#: tcop/postgres.c:4012 tcop/postgres.c:4018 +#: tcop/postgres.c:4030 tcop/postgres.c:4036 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: tcop/postgres.c:4016 +#: tcop/postgres.c:4034 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: 不正なコマンドライン引数: %s" -#: tcop/postgres.c:4069 +#: tcop/postgres.c:4087 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: データベース名もユーザー名も指定されていません" -#: tcop/postgres.c:4822 +#: tcop/postgres.c:4280 +#, c-format +msgid "could not generate random cancel key" +msgstr "ランダムなキャンセルキーを生成できませんでした" + +#: tcop/postgres.c:4682 +#, c-format +msgid "connection ready: setup total=%.3f ms, fork=%.3f ms, authentication=%.3f ms" +msgstr "接続完了: 所要時間=%.3fミリ秒、fork=%.3fミリ秒、認証処理=%.3fミリ秒" + +#: tcop/postgres.c:4913 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "不正なCLOSEメッセージのサブタイプ%d" -#: tcop/postgres.c:4859 +#: tcop/postgres.c:4950 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "不正なDESCRIBEメッセージのサブタイプ%d" -#: tcop/postgres.c:4946 +#: tcop/postgres.c:5044 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "レプリケーション接続では高速関数呼び出しはサポートされていません" -#: tcop/postgres.c:4950 +#: tcop/postgres.c:5048 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "レプリケーション接続では拡張問い合わせプロトコルはサポートされていません" -#: tcop/postgres.c:5130 +#: tcop/postgres.c:5194 #, c-format msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s" msgstr "接続を切断: セッション時間: %d:%02d:%02d.%03d ユーザー=%s データベース=%s ホスト=%s%s%s" -#: tcop/pquery.c:641 +#: tcop/pquery.c:674 #, c-format msgid "bind message has %d result formats but query has %d columns" msgstr "バインドメッセージは%dの結果書式がありましたが、問い合わせは%d列でした" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:972 tcop/pquery.c:1734 #, c-format msgid "cursor can only scan forward" msgstr "カーゾルは前方へのスキャンしかできません" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:973 tcop/pquery.c:1735 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "後方スキャンを有効にするためにはSCROLLオプションを付けて宣言してください。" @@ -23446,68 +24393,68 @@ msgid "cannot execute %s within security-restricted operation" msgstr "セキュリティー制限操作の中では %s を実行できません" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:821 +#: tcop/utility.c:824 #, c-format msgid "cannot execute %s within a background process" msgstr "バックグラウンドプロセス内で%sを実行することはできません" #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:947 +#: tcop/utility.c:950 #, c-format msgid "permission denied to execute %s command" msgstr "%sコマンドを実行する権限がありません" -#: tcop/utility.c:949 +#: tcop/utility.c:952 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "\"%s\"ロールの権限を持つロールのみがこのコマンドを実行できます。" -#: tsearch/dict_ispell.c:52 tsearch/dict_thesaurus.c:616 +#: tsearch/dict_ispell.c:53 tsearch/dict_thesaurus.c:616 #, c-format msgid "multiple DictFile parameters" msgstr "重複するDictFileパラメータ" -#: tsearch/dict_ispell.c:63 +#: tsearch/dict_ispell.c:64 #, c-format msgid "multiple AffFile parameters" msgstr "重複するAffFileパラメータ" -#: tsearch/dict_ispell.c:82 +#: tsearch/dict_ispell.c:83 #, c-format msgid "unrecognized Ispell parameter: \"%s\"" msgstr "認識不可のIspellパラメータ: \"%s\"" -#: tsearch/dict_ispell.c:96 +#: tsearch/dict_ispell.c:97 #, c-format msgid "missing AffFile parameter" msgstr "AffFileパラメータがありません" -#: tsearch/dict_ispell.c:102 tsearch/dict_thesaurus.c:640 +#: tsearch/dict_ispell.c:103 tsearch/dict_thesaurus.c:640 #, c-format msgid "missing DictFile parameter" msgstr "DictFileパラメータがありません" -#: tsearch/dict_simple.c:58 +#: tsearch/dict_simple.c:59 #, c-format msgid "multiple Accept parameters" msgstr "重複するAcceptパラメータ" -#: tsearch/dict_simple.c:66 +#: tsearch/dict_simple.c:67 #, c-format msgid "unrecognized simple dictionary parameter: \"%s\"" msgstr "認識できない単純辞書パラメータ: \"%s\"" -#: tsearch/dict_synonym.c:118 +#: tsearch/dict_synonym.c:120 #, c-format msgid "unrecognized synonym parameter: \"%s\"" msgstr "認識できない類義語パラメータ: \"%s\"" -#: tsearch/dict_synonym.c:125 +#: tsearch/dict_synonym.c:127 #, c-format msgid "missing Synonyms parameter" msgstr "類義語パラメータがありません" -#: tsearch/dict_synonym.c:132 +#: tsearch/dict_synonym.c:134 #, c-format msgid "could not open synonym file \"%s\": %m" msgstr "類義語ファイル\"%s\"をオープンできませんでした: %m" @@ -23582,76 +24529,71 @@ msgstr "認識できないシソーラスパラメータ \"%s\"" msgid "missing Dictionary parameter" msgstr "Dictionaryパラメータがありません" -#: tsearch/spell.c:381 tsearch/spell.c:398 tsearch/spell.c:407 tsearch/spell.c:1043 +#: tsearch/spell.c:383 tsearch/spell.c:400 tsearch/spell.c:409 tsearch/spell.c:1046 #, c-format msgid "invalid affix flag \"%s\"" msgstr "不正な接辞フラグ\"%s\"" -#: tsearch/spell.c:385 tsearch/spell.c:1047 +#: tsearch/spell.c:387 tsearch/spell.c:1050 #, c-format msgid "affix flag \"%s\" is out of range" msgstr "接辞フラグ\"%s\"は範囲外です" -#: tsearch/spell.c:415 +#: tsearch/spell.c:417 #, c-format msgid "invalid character in affix flag \"%s\"" msgstr "接辞フラグ中の不正な文字\"%s\"" -#: tsearch/spell.c:435 +#: tsearch/spell.c:437 #, c-format msgid "invalid affix flag \"%s\" with \"long\" flag value" msgstr "\"long\"フラグ値を伴った不正な接辞フラグ\"%s\"" -#: tsearch/spell.c:525 +#: tsearch/spell.c:527 #, c-format msgid "could not open dictionary file \"%s\": %m" msgstr "辞書ファイル\"%s\"をオープンできませんでした: %m" -#: tsearch/spell.c:1170 tsearch/spell.c:1182 tsearch/spell.c:1742 tsearch/spell.c:1747 tsearch/spell.c:1752 +#: tsearch/spell.c:1174 tsearch/spell.c:1186 tsearch/spell.c:1751 tsearch/spell.c:1756 tsearch/spell.c:1761 #, c-format msgid "invalid affix alias \"%s\"" msgstr "不正な接辞の別名 \"%s\"" -#: tsearch/spell.c:1223 tsearch/spell.c:1294 tsearch/spell.c:1443 +#: tsearch/spell.c:1227 tsearch/spell.c:1298 tsearch/spell.c:1447 #, c-format msgid "could not open affix file \"%s\": %m" msgstr "affixファイル\"%s\"をオープンできませんでした: %m" -#: tsearch/spell.c:1277 +#: tsearch/spell.c:1281 #, c-format msgid "Ispell dictionary supports only \"default\", \"long\", and \"num\" flag values" msgstr "Ispell辞書はフラグ値\"default\"、\"long\"および\"num\"のみをサポートします" -#: tsearch/spell.c:1321 +#: tsearch/spell.c:1325 #, c-format msgid "invalid number of flag vector aliases" msgstr "不正な数のフラグベクタの別名" -#: tsearch/spell.c:1344 +#: tsearch/spell.c:1348 #, c-format msgid "number of aliases exceeds specified number %d" msgstr "別名の数が指定された数 %d を超えています" -#: tsearch/spell.c:1559 +#: tsearch/spell.c:1563 #, c-format msgid "affix file contains both old-style and new-style commands" msgstr "接辞ファイルが新旧両方の形式のコマンドを含んでいます" -#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:274 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "TSベクターのための文字列が長すぎます(%dバイト、最大は%dバイト)" -#: tsearch/ts_locale.c:236 +#: tsearch/ts_locale.c:191 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "設定ファイル\"%2$s\"の%1$d行目: \"%3$s\"" -#: tsearch/ts_locale.c:315 -#, c-format -msgid "conversion from wchar_t to server encoding failed: %m" -msgstr "wchar_tからサーバー符号化方式への変換が失敗しました: %m" - #: tsearch/ts_parse.c:387 tsearch/ts_parse.c:394 tsearch/ts_parse.c:573 tsearch/ts_parse.c:580 #, c-format msgid "word is too long to be indexed" @@ -23662,12 +24604,12 @@ msgstr "インデックス付けするには単語が長すぎます" msgid "Words longer than %d characters are ignored." msgstr "%dより長い単語は無視されます。" -#: tsearch/ts_utils.c:51 +#: tsearch/ts_utils.c:52 #, c-format msgid "invalid text search configuration file name \"%s\"" msgstr "テキスト検索設定ファイル名は%sは不正です" -#: tsearch/ts_utils.c:83 +#: tsearch/ts_utils.c:84 #, c-format msgid "could not open stop-word file \"%s\": %m" msgstr "ストップワードファイル\"%s\"をオープンできませんでした: %m" @@ -23684,60 +24626,105 @@ msgstr "認識できない見出しパラメータ: \"%s\"" #: tsearch/wparser_def.c:2674 #, c-format -msgid "MinWords should be less than MaxWords" -msgstr "MinWordsはMaxWordsより小さくなければなりません" +msgid "%s must be less than %s" +msgstr "\"%s\"は\"%s\"より小さくなければなりません" #: tsearch/wparser_def.c:2678 #, c-format -msgid "MinWords should be positive" -msgstr "MinWordsは正でなければなりません" +msgid "%s must be positive" +msgstr "%sは正数でなければなりまsん" -#: tsearch/wparser_def.c:2682 +#: tsearch/wparser_def.c:2682 tsearch/wparser_def.c:2686 #, c-format -msgid "ShortWord should be >= 0" -msgstr "ShortWordは>= 0でなければなりません" +msgid "%s must be >= 0" +msgstr "%sは0以上でなければなりません" -#: tsearch/wparser_def.c:2686 -#, c-format -msgid "MaxFragments should be >= 0" -msgstr "MaxFragments は 0 以上でなければなりません" - -#: utils/activity/pgstat.c:435 +#: utils/activity/pgstat.c:533 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "永続統計情報ファイル\"%s\"をunlinkできませんでした: %m" -#: utils/activity/pgstat.c:1252 +#: utils/activity/pgstat.c:1443 #, c-format msgid "invalid statistics kind: \"%s\"" msgstr "不正な統計情報種別: \"%s\"" -#: utils/activity/pgstat.c:1332 +#: utils/activity/pgstat.c:1488 +#, c-format +msgid "custom cumulative statistics name is invalid" +msgstr "独自集積統計情報の名前が不正です" + +#: utils/activity/pgstat.c:1489 +#, c-format +msgid "Provide a non-empty name for the custom cumulative statistics." +msgstr "独自集積統計情報の名前には空ではない文字列を設定してください。" + +#: utils/activity/pgstat.c:1492 +#, c-format +msgid "custom cumulative statistics ID %u is out of range" +msgstr "独自集積統計情報のID %uは範囲外です" + +#: utils/activity/pgstat.c:1493 +#, c-format +msgid "Provide a custom cumulative statistics ID between %u and %u." +msgstr "独自集積統計情報IDは%uから%uの間の値で指定してください。" + +#: utils/activity/pgstat.c:1498 utils/activity/pgstat.c:1525 utils/activity/pgstat.c:1538 +#, c-format +msgid "failed to register custom cumulative statistics \"%s\" with ID %u" +msgstr "独自集積統計情報\"%s\"のID %uでの登録に失敗しました" + +#: utils/activity/pgstat.c:1499 +#, c-format +msgid "Custom cumulative statistics must be registered while initializing modules in \"shared_preload_libraries\"." +msgstr "独自集積統計情報は\"shared_preload_libraries\"にあるモジュールの初期化中に登録する必要があります。" + +#: utils/activity/pgstat.c:1508 +#, c-format +msgid "custom cumulative statistics property is invalid" +msgstr "独自集積統計情報の特性が不正です" + +#: utils/activity/pgstat.c:1509 +#, c-format +msgid "Custom cumulative statistics require a shared memory size for fixed-numbered objects." +msgstr "独自集積統計情報は固定数のオブジェクトのための共有メモリのサイズを必要とします。" + +#: utils/activity/pgstat.c:1526 +#, c-format +msgid "Custom cumulative statistics \"%s\" already registered with the same ID." +msgstr "独自集積統計情報\"%s\"はすでに同一のIDで登録されています。" + +#: utils/activity/pgstat.c:1539 +#, c-format +msgid "Existing cumulative statistics with ID %u has the same name." +msgstr "ID %uの既存の独自集積統計情報が同じ名前です。" + +#: utils/activity/pgstat.c:1545 +#, c-format +msgid "registered custom cumulative statistics \"%s\" with ID %u" +msgstr "独自集積統計情報\"%s\"をID %uで登録しました" + +#: utils/activity/pgstat.c:1614 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "一時統計情報ファイル\"%s\"をオープンできませんでした: %m" -#: utils/activity/pgstat.c:1444 +#: utils/activity/pgstat.c:1735 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "一時統計情報ファイル\"%s\"に書き込みできませんでした: %m" -#: utils/activity/pgstat.c:1453 +#: utils/activity/pgstat.c:1744 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "一時統計情報ファイル\"%s\"をクローズできませんでした: %m" -#: utils/activity/pgstat.c:1461 -#, c-format -msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" -msgstr "一時統計情報ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" - -#: utils/activity/pgstat.c:1510 +#: utils/activity/pgstat.c:1798 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "統計情報ファイル\"%s\"をオープンできませんでした: %m" -#: utils/activity/pgstat.c:1672 +#: utils/activity/pgstat.c:2030 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "統計情報ファイル\"%s\"が破損しています" @@ -23747,178 +24734,183 @@ msgstr "統計情報ファイル\"%s\"が破損しています" msgid "function call to dropped function" msgstr "削除された関数の呼び出し" -#: utils/activity/pgstat_xact.c:362 +#: utils/activity/pgstat_xact.c:366 +#, c-format +msgid "resetting existing statistics for kind %s, db=%u, oid=%" +msgstr "種類%s、db=%u、oid=%に対する既存の統計情報をリセットします" + +#: utils/activity/wait_event.c:206 utils/activity/wait_event.c:231 #, c-format -msgid "resetting existing statistics for kind %s, db=%u, oid=%u" -msgstr "種類%s、db=%u、oid=%uの既存統計情報をリセットします" +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "待機イベント\"%s\"は待機イベントタイプ\"%s\"内にすでに存在します" -#: utils/activity/wait_event.c:210 +#: utils/activity/wait_event.c:245 #, c-format -msgid "too many wait events for extensions" -msgstr "機能拡張の待機イベントが多すぎます" +msgid "too many custom wait events" +msgstr "独自待機イベントの数が多すぎます" -#: utils/adt/acl.c:183 utils/adt/name.c:93 +#: utils/adt/acl.c:187 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "識別子が長すぎます" -#: utils/adt/acl.c:184 utils/adt/name.c:94 +#: utils/adt/acl.c:188 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "識別子は%d文字より短くなければなりません。" -#: utils/adt/acl.c:272 +#: utils/adt/acl.c:276 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "キーワードが不明です: \"%s\"" -#: utils/adt/acl.c:273 +#: utils/adt/acl.c:277 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "ACLキーワードは\"group\"または\"user\"でなければなりません。" -#: utils/adt/acl.c:281 +#: utils/adt/acl.c:285 #, c-format msgid "missing name" msgstr "名前がありません" -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:286 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "\"group\"または\"user\"キーワードの後には名前が必要です。" -#: utils/adt/acl.c:288 +#: utils/adt/acl.c:292 #, c-format msgid "missing \"=\" sign" msgstr "\"=\"記号がありません" -#: utils/adt/acl.c:350 +#: utils/adt/acl.c:351 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "不正なモード文字: \"%s\"の一つでなければなりません" -#: utils/adt/acl.c:380 +#: utils/adt/acl.c:381 #, c-format msgid "a name must follow the \"/\" sign" msgstr "\"/\"記号の後には名前が必要です" -#: utils/adt/acl.c:392 +#: utils/adt/acl.c:393 #, c-format msgid "defaulting grantor to user ID %u" msgstr "権限付与者をデフォルトのユーザーID %uにしています" -#: utils/adt/acl.c:578 +#: utils/adt/acl.c:579 #, c-format msgid "ACL array contains wrong data type" msgstr "ACL配列に不正なデータ型があります。" -#: utils/adt/acl.c:582 +#: utils/adt/acl.c:583 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "ACL配列は1次元の配列でなければなりません" -#: utils/adt/acl.c:586 +#: utils/adt/acl.c:587 #, c-format msgid "ACL arrays must not contain null values" msgstr "ACL配列にはNULL値を含めてはいけません" -#: utils/adt/acl.c:615 +#: utils/adt/acl.c:616 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "ACL指定の後に余計なごみがあります" -#: utils/adt/acl.c:1257 +#: utils/adt/acl.c:1264 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "グラントオプションでその権限付与者に権限を付与し返すことはできません" -#: utils/adt/acl.c:1573 +#: utils/adt/acl.c:1580 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsertはもうサポートされていません" -#: utils/adt/acl.c:1583 +#: utils/adt/acl.c:1590 #, c-format msgid "aclremove is no longer supported" msgstr "aclremoveはもうサポートされていません" -#: utils/adt/acl.c:1703 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "権限タイプが不明です: \"%s\"" -#: utils/adt/acl.c:3544 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3548 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "関数\"%s\"は存在しません" -#: utils/adt/acl.c:5190 +#: utils/adt/acl.c:5330 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "SET ROLE\"%s\"ができなければなりません" -#: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 +#: utils/adt/array_userfuncs.c:118 utils/adt/array_userfuncs.c:565 utils/adt/array_userfuncs.c:942 utils/adt/json.c:611 utils/adt/json.c:749 utils/adt/json.c:799 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "入力データ型を特定できませんでした" -#: utils/adt/array_userfuncs.c:107 +#: utils/adt/array_userfuncs.c:123 #, c-format msgid "input data type is not an array" msgstr "入力データ型は配列ではありません" -#: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 utils/adt/int.c:1263 -#: utils/adt/int.c:1331 utils/adt/int.c:1337 utils/adt/int8.c:1256 utils/adt/numeric.c:1902 utils/adt/numeric.c:4439 utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 utils/adt/varlena.c:3137 +#: utils/adt/array_userfuncs.c:167 utils/adt/array_userfuncs.c:249 utils/adt/float.c:1229 utils/adt/float.c:1303 utils/adt/float.c:4107 utils/adt/float.c:4145 utils/adt/int.c:778 utils/adt/int.c:800 utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 utils/adt/int.c:1263 +#: utils/adt/int.c:1331 utils/adt/int.c:1337 utils/adt/int8.c:1256 utils/adt/numeric.c:2039 utils/adt/numeric.c:4557 utils/adt/rangetypes.c:1552 utils/adt/rangetypes.c:1565 utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1143 utils/adt/varlena.c:3184 utils/adt/varlena.c:4118 #, c-format msgid "integer out of range" msgstr "integerの範囲外です" -#: utils/adt/array_userfuncs.c:158 utils/adt/array_userfuncs.c:213 +#: utils/adt/array_userfuncs.c:174 utils/adt/array_userfuncs.c:259 #, c-format msgid "argument must be empty or one-dimensional array" msgstr "引数は空か1次元の配列でなければなりません" -#: utils/adt/array_userfuncs.c:295 utils/adt/array_userfuncs.c:334 utils/adt/array_userfuncs.c:371 utils/adt/array_userfuncs.c:400 utils/adt/array_userfuncs.c:428 +#: utils/adt/array_userfuncs.c:371 utils/adt/array_userfuncs.c:410 utils/adt/array_userfuncs.c:447 utils/adt/array_userfuncs.c:476 utils/adt/array_userfuncs.c:504 #, c-format msgid "cannot concatenate incompatible arrays" msgstr "互換性がない配列を連結できません" -#: utils/adt/array_userfuncs.c:296 +#: utils/adt/array_userfuncs.c:372 #, c-format msgid "Arrays with element types %s and %s are not compatible for concatenation." msgstr "要素型%sと%sの配列の連結には互換性がありません" -#: utils/adt/array_userfuncs.c:335 +#: utils/adt/array_userfuncs.c:411 #, c-format msgid "Arrays of %d and %d dimensions are not compatible for concatenation." msgstr "要素数%dと%dの配列の連結には互換性がありません" -#: utils/adt/array_userfuncs.c:372 +#: utils/adt/array_userfuncs.c:448 #, c-format msgid "Arrays with differing element dimensions are not compatible for concatenation." msgstr "異なる要素次数の配列の連結には互換性がありません。" -#: utils/adt/array_userfuncs.c:401 utils/adt/array_userfuncs.c:429 +#: utils/adt/array_userfuncs.c:477 utils/adt/array_userfuncs.c:505 #, c-format msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "異なる次数の配列の連結には互換性がありません。" -#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 utils/adt/arrayfuncs.c:5609 utils/adt/arrayfuncs.c:5615 +#: utils/adt/array_userfuncs.c:1051 utils/adt/array_userfuncs.c:1059 utils/adt/arrayfuncs.c:5628 utils/adt/arrayfuncs.c:5634 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "次元の異なる配列は結合できません" -#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 +#: utils/adt/array_userfuncs.c:1348 utils/adt/array_userfuncs.c:1502 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "多次元配列内の要素の検索はサポートされません" -#: utils/adt/array_userfuncs.c:1301 +#: utils/adt/array_userfuncs.c:1377 #, c-format msgid "initial position must not be null" msgstr "初期位置nullであってはなりません" -#: utils/adt/array_userfuncs.c:1674 +#: utils/adt/array_userfuncs.c:1750 #, c-format msgid "sample size must be between 0 and %d" msgstr "サンプルの大きさは0と%dの間でなければなりません" @@ -23963,7 +24955,7 @@ msgstr "\"[\"は配列次元の明示的な指定の先頭である必要があ msgid "Missing array dimension value." msgstr "配列の次元数の値がありません。" -#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2933 utils/adt/arrayfuncs.c:2978 utils/adt/arrayfuncs.c:2993 +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 #, c-format msgid "upper bound cannot be less than lower bound" msgstr "上限を下限より小さくすることはできません" @@ -23993,7 +24985,7 @@ msgstr "想定外の配列要素。" msgid "Specified array dimensions do not match array contents." msgstr "指定された配列の次元数が配列の内容と合致していません。" -#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2597 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2600 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "多次元配列は合致する次元の副配列を持たなければなりません。" @@ -24003,12 +24995,12 @@ msgstr "多次元配列は合致する次元の副配列を持たなければな msgid "Incorrectly quoted array element." msgstr "配列要素が正しくクォートされていません" -#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 utils/adt/rangetypes.c:2528 utils/adt/rangetypes.c:2536 utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 #, c-format msgid "Unexpected end of input." msgstr "想定外の入力の終端。" -#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3492 utils/adt/arrayfuncs.c:6099 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3511 utils/adt/arrayfuncs.c:6120 #, c-format msgid "invalid number of dimensions: %d" msgstr "不正な次元数: %d" @@ -24023,7 +25015,7 @@ msgstr "不正な配列フラグ" msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "バイナリデータ中に期待される型%3$u(%4$s)の代わりに%1$u(%2$s)がありました" -#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 utils/adt/rangetypes.c:353 utils/cache/lsyscache.c:3098 #, c-format msgid "no binary input function available for type %s" msgstr "型%sにはバイナリ入力関数がありません" @@ -24033,7 +25025,7 @@ msgstr "型%sにはバイナリ入力関数がありません" msgid "improper binary format in array element %d" msgstr "配列要素%dのバイナリ書式が不適切です" -#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 utils/adt/rangetypes.c:358 utils/cache/lsyscache.c:3131 #, c-format msgid "no binary output function available for type %s" msgstr "型%sにはバイナリ出力関数がありません" @@ -24043,12 +25035,12 @@ msgstr "型%sにはバイナリ出力関数がありません" msgid "slices of fixed-length arrays not implemented" msgstr "固定長配列の部分配列は実装されていません" -#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 utils/adt/arrayfuncs.c:2908 utils/adt/arrayfuncs.c:6085 utils/adt/arrayfuncs.c:6111 utils/adt/arrayfuncs.c:6122 utils/adt/json.c:1419 utils/adt/json.c:1491 utils/adt/jsonb.c:1317 utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4688 utils/adt/jsonfuncs.c:4841 utils/adt/jsonfuncs.c:4952 utils/adt/jsonfuncs.c:5000 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6106 utils/adt/arrayfuncs.c:6132 utils/adt/arrayfuncs.c:6143 utils/adt/json.c:1441 utils/adt/json.c:1509 utils/adt/jsonb.c:1317 utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4734 utils/adt/jsonfuncs.c:4887 utils/adt/jsonfuncs.c:4998 utils/adt/jsonfuncs.c:5046 #, c-format msgid "wrong number of array subscripts" msgstr "配列の添え字が不正な数値です" -#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2983 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "配列の添え字が範囲外です" @@ -24073,92 +25065,92 @@ msgstr "配列のスライスの添え字は両方の境界を示す必要があ msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified." msgstr "空の配列値のスライスに代入するには、スライスの範囲は完全に指定する必要があります。" -#: utils/adt/arrayfuncs.c:2898 utils/adt/arrayfuncs.c:3010 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "元の配列が小さすぎます" -#: utils/adt/arrayfuncs.c:3650 +#: utils/adt/arrayfuncs.c:3669 #, c-format msgid "null array element not allowed in this context" msgstr "この文脈ではNULLの配列要素は許可されません" -#: utils/adt/arrayfuncs.c:3821 utils/adt/arrayfuncs.c:3992 utils/adt/arrayfuncs.c:4383 +#: utils/adt/arrayfuncs.c:3840 utils/adt/arrayfuncs.c:4011 utils/adt/arrayfuncs.c:4402 #, c-format msgid "cannot compare arrays of different element types" msgstr "要素型の異なる配列を比較できません" -#: utils/adt/arrayfuncs.c:4170 utils/adt/multirangetypes.c:2805 utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 +#: utils/adt/arrayfuncs.c:4189 utils/adt/multirangetypes.c:2805 utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1425 utils/adt/rangetypes.c:1489 utils/adt/rowtypes.c:1893 #, c-format msgid "could not identify a hash function for type %s" msgstr "型 %s のハッシュ関数を特定できません" -#: utils/adt/arrayfuncs.c:4298 utils/adt/rowtypes.c:1996 +#: utils/adt/arrayfuncs.c:4317 utils/adt/rowtypes.c:2014 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "型 %s の拡張ハッシュ関数を特定できませんでした" -#: utils/adt/arrayfuncs.c:5499 +#: utils/adt/arrayfuncs.c:5518 #, c-format msgid "data type %s is not an array type" msgstr "データ型%sは配列型ではありません" -#: utils/adt/arrayfuncs.c:5554 +#: utils/adt/arrayfuncs.c:5573 #, c-format msgid "cannot accumulate null arrays" msgstr "null配列は連結できません" -#: utils/adt/arrayfuncs.c:5582 +#: utils/adt/arrayfuncs.c:5601 #, c-format msgid "cannot accumulate empty arrays" msgstr "空の配列は連結できません" -#: utils/adt/arrayfuncs.c:5983 utils/adt/arrayfuncs.c:6023 +#: utils/adt/arrayfuncs.c:6004 utils/adt/arrayfuncs.c:6044 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "次元配列もしくは下限値配列が NULL であってはなりません" -#: utils/adt/arrayfuncs.c:6086 utils/adt/arrayfuncs.c:6112 +#: utils/adt/arrayfuncs.c:6107 utils/adt/arrayfuncs.c:6133 #, c-format msgid "Dimension array must be one dimensional." msgstr "次元配列は1次元でなければなりません" -#: utils/adt/arrayfuncs.c:6091 utils/adt/arrayfuncs.c:6117 +#: utils/adt/arrayfuncs.c:6112 utils/adt/arrayfuncs.c:6138 #, c-format msgid "dimension values cannot be null" msgstr "次元値にnullにはできません" -#: utils/adt/arrayfuncs.c:6123 +#: utils/adt/arrayfuncs.c:6144 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "下限配列が次元配列のサイズと異なっています" -#: utils/adt/arrayfuncs.c:6404 +#: utils/adt/arrayfuncs.c:6425 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "多次元配列からの要素削除はサポートされません" -#: utils/adt/arrayfuncs.c:6681 +#: utils/adt/arrayfuncs.c:6702 #, c-format msgid "thresholds must be one-dimensional array" msgstr "閾値は1次元の配列でなければなりません" -#: utils/adt/arrayfuncs.c:6686 +#: utils/adt/arrayfuncs.c:6707 #, c-format msgid "thresholds array must not contain NULLs" msgstr "閾値配列にはNULL値を含めてはいけません" -#: utils/adt/arrayfuncs.c:6919 +#: utils/adt/arrayfuncs.c:6940 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "削除する要素の数は0と%dとの間でなければなりません" -#: utils/adt/arraysubs.c:93 utils/adt/arraysubs.c:130 +#: utils/adt/arraysubs.c:94 utils/adt/arraysubs.c:131 #, c-format msgid "array subscript must have type integer" msgstr "配列の添え字は整数型でなければなりません" -#: utils/adt/arraysubs.c:198 utils/adt/arraysubs.c:217 +#: utils/adt/arraysubs.c:199 utils/adt/arraysubs.c:218 #, c-format msgid "array subscript in assignment must not be null" msgstr "代入における配列の添え字はnullにはできません" @@ -24189,24 +25181,29 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "%s符号化方式からASCIIへの変換はサポートされていません" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:149 utils/adt/cash.c:277 utils/adt/datetime.c:4142 utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 utils/adt/geo_ops.c:4672 utils/adt/int.c:174 -#: utils/adt/int.c:186 utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 utils/adt/network.c:99 utils/adt/numeric.c:796 utils/adt/numeric.c:7206 utils/adt/numeric.c:7409 utils/adt/numeric.c:8356 utils/adt/numutils.c:356 utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 utils/adt/tid.c:94 -#: utils/adt/tid.c:103 utils/adt/timestamp.c:510 utils/adt/uuid.c:140 utils/adt/xid8funcs.c:360 +#: utils/adt/bool.c:150 utils/adt/cash.c:354 utils/adt/datetime.c:4258 utils/adt/float.c:207 utils/adt/float.c:294 utils/adt/float.c:308 utils/adt/float.c:413 utils/adt/float.c:496 utils/adt/float.c:510 utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 utils/adt/geo_ops.c:4672 utils/adt/int.c:174 +#: utils/adt/int.c:186 utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 utils/adt/network.c:99 utils/adt/numeric.c:805 utils/adt/numeric.c:7324 utils/adt/numeric.c:7527 utils/adt/numeric.c:8474 utils/adt/numutils.c:356 utils/adt/numutils.c:617 utils/adt/numutils.c:878 utils/adt/numutils.c:917 utils/adt/numutils.c:939 utils/adt/numutils.c:1003 utils/adt/numutils.c:1025 utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 utils/adt/tid.c:94 +#: utils/adt/tid.c:103 utils/adt/timestamp.c:512 utils/adt/uuid.c:176 utils/adt/xid8funcs.c:323 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "\"%s\"型の入力構文が不正です: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:350 utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "値\"%s\"は型%sの範囲外です" +msgid "money out of range" +msgstr "マネー型の値が範囲外です" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 utils/adt/float.c:99 utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 utils/adt/numeric.c:3176 utils/adt/numeric.c:3199 -#: utils/adt/numeric.c:3284 utils/adt/numeric.c:3302 utils/adt/numeric.c:3398 utils/adt/numeric.c:8905 utils/adt/numeric.c:9218 utils/adt/numeric.c:9566 utils/adt/numeric.c:9682 utils/adt/numeric.c:11192 utils/adt/timestamp.c:3713 +#: utils/adt/cash.c:161 utils/adt/cash.c:725 utils/adt/float.c:106 utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 utils/adt/numeric.c:3294 utils/adt/numeric.c:3317 utils/adt/numeric.c:3402 utils/adt/numeric.c:3420 utils/adt/numeric.c:3516 utils/adt/numeric.c:9399 +#: utils/adt/numeric.c:9923 utils/adt/numeric.c:10039 utils/adt/numeric.c:11550 utils/adt/timestamp.c:3772 #, c-format msgid "division by zero" msgstr "0 による除算が行われました" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 utils/adt/numutils.c:611 utils/adt/numutils.c:872 utils/adt/numutils.c:923 utils/adt/numutils.c:962 utils/adt/numutils.c:1009 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "値\"%s\"は型%sの範囲外です" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -24217,140 +25214,140 @@ msgstr "\"char\"の範囲外です" msgid "could not compute %s hash: %s" msgstr "%sハッシュを計算できませんでした: %s" -#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 utils/adt/varchar.c:48 +#: utils/adt/date.c:65 utils/adt/timestamp.c:118 utils/adt/varbit.c:105 utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "不正な型修飾子です。" -#: utils/adt/date.c:76 +#: utils/adt/date.c:77 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "(%d)%sの精度は負ではいけません" -#: utils/adt/date.c:82 +#: utils/adt/date.c:83 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "TIME(%d)%sの位取りを許容最大値%dまで減らしました" -#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 utils/adt/formatting.c:4548 +#: utils/adt/date.c:168 utils/adt/date.c:176 utils/adt/formatting.c:4171 utils/adt/formatting.c:4180 utils/adt/formatting.c:4285 utils/adt/formatting.c:4295 #, c-format msgid "date out of range: \"%s\"" msgstr "日付が範囲外です: \"%s\"" -#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2489 +#: utils/adt/date.c:223 utils/adt/date.c:585 utils/adt/date.c:609 utils/adt/rangetypes.c:1648 utils/adt/rangetypes.c:1663 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "日付が範囲外です" -#: utils/adt/date.c:268 utils/adt/timestamp.c:598 +#: utils/adt/date.c:266 utils/adt/date.c:276 utils/adt/timestamp.c:600 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "日付フィールドの値が範囲外です: %d-%02d-%02d" -#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 +#: utils/adt/date.c:283 utils/adt/date.c:292 utils/adt/timestamp.c:606 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "日付が範囲外です: %d-%02d-%02d" -#: utils/adt/date.c:495 +#: utils/adt/date.c:560 #, c-format msgid "cannot subtract infinite dates" msgstr "無限大の日付は減算できません" -#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 utils/adt/date.c:2906 utils/adt/date.c:2916 +#: utils/adt/date.c:658 utils/adt/date.c:721 utils/adt/date.c:757 utils/adt/date.c:2971 utils/adt/date.c:2981 #, c-format msgid "date out of range for timestamp" msgstr "タイムスタンプで日付が範囲外です" -#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 utils/adt/timestamp.c:6070 +#: utils/adt/date.c:1187 utils/adt/date.c:1270 utils/adt/date.c:1286 utils/adt/date.c:2280 utils/adt/date.c:3076 utils/adt/timestamp.c:4724 utils/adt/timestamp.c:4815 utils/adt/timestamp.c:4963 utils/adt/timestamp.c:5064 utils/adt/timestamp.c:5179 utils/adt/timestamp.c:5231 utils/adt/timestamp.c:5488 utils/adt/timestamp.c:5689 utils/adt/timestamp.c:5736 utils/adt/timestamp.c:5960 utils/adt/timestamp.c:6007 utils/adt/timestamp.c:6088 utils/adt/timestamp.c:6232 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "単位\"%s\"は型%sに対してはサポートされていません" -#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 +#: utils/adt/date.c:1295 utils/adt/date.c:2296 utils/adt/date.c:3096 utils/adt/timestamp.c:4829 utils/adt/timestamp.c:5081 utils/adt/timestamp.c:5245 utils/adt/timestamp.c:5448 utils/adt/timestamp.c:5745 utils/adt/timestamp.c:6016 utils/adt/timestamp.c:6057 utils/adt/timestamp.c:6293 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "単位\"%s\"は型%sに対しては認識できません" -#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 -#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 utils/adt/timestamp.c:3266 -#: utils/adt/timestamp.c:3279 utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 -#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2511 utils/adt/xml.c:2518 utils/adt/xml.c:2538 utils/adt/xml.c:2545 +#: utils/adt/date.c:1379 utils/adt/date.c:1425 utils/adt/date.c:1984 utils/adt/date.c:2015 utils/adt/date.c:2044 utils/adt/date.c:2934 utils/adt/date.c:3166 utils/adt/datetime.c:432 utils/adt/datetime.c:1817 utils/adt/formatting.c:4016 utils/adt/formatting.c:4052 utils/adt/formatting.c:4139 utils/adt/formatting.c:4261 utils/adt/json.c:375 utils/adt/json.c:414 utils/adt/timestamp.c:250 utils/adt/timestamp.c:282 utils/adt/timestamp.c:707 utils/adt/timestamp.c:716 +#: utils/adt/timestamp.c:794 utils/adt/timestamp.c:827 utils/adt/timestamp.c:3125 utils/adt/timestamp.c:3134 utils/adt/timestamp.c:3151 utils/adt/timestamp.c:3156 utils/adt/timestamp.c:3175 utils/adt/timestamp.c:3188 utils/adt/timestamp.c:3199 utils/adt/timestamp.c:3205 utils/adt/timestamp.c:3211 utils/adt/timestamp.c:3216 utils/adt/timestamp.c:3269 utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3299 utils/adt/timestamp.c:3304 utils/adt/timestamp.c:3325 +#: utils/adt/timestamp.c:3338 utils/adt/timestamp.c:3352 utils/adt/timestamp.c:3360 utils/adt/timestamp.c:3366 utils/adt/timestamp.c:3371 utils/adt/timestamp.c:4439 utils/adt/timestamp.c:4591 utils/adt/timestamp.c:4667 utils/adt/timestamp.c:4733 utils/adt/timestamp.c:4823 utils/adt/timestamp.c:4902 utils/adt/timestamp.c:4972 utils/adt/timestamp.c:5075 utils/adt/timestamp.c:5553 utils/adt/timestamp.c:5827 utils/adt/timestamp.c:6361 utils/adt/timestamp.c:6371 +#: utils/adt/timestamp.c:6376 utils/adt/timestamp.c:6382 utils/adt/timestamp.c:6422 utils/adt/timestamp.c:6509 utils/adt/timestamp.c:6550 utils/adt/timestamp.c:6554 utils/adt/timestamp.c:6608 utils/adt/timestamp.c:6612 utils/adt/timestamp.c:6618 utils/adt/timestamp.c:6659 utils/adt/xml.c:2574 utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "timestampの範囲外です" -#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 +#: utils/adt/date.c:1601 utils/adt/date.c:2417 utils/adt/formatting.c:4344 #, c-format msgid "time out of range" msgstr "時刻が範囲外です" -#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 +#: utils/adt/date.c:1653 utils/adt/timestamp.c:615 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "時刻フィールドの値が範囲外です: %d:%02d:%02g" -#: utils/adt/date.c:2020 +#: utils/adt/date.c:2085 #, c-format msgid "cannot convert infinite interval to time" msgstr "無限大のintervalはtimeに変換できません" -#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#: utils/adt/date.c:2126 utils/adt/date.c:2670 #, c-format msgid "cannot add infinite interval to time" msgstr "無限大のintervalのtimeへの加算はできません" -#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#: utils/adt/date.c:2149 utils/adt/date.c:2697 #, c-format msgid "cannot subtract infinite interval from time" msgstr "無限大のintervalのtimeからの減算できません" -#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2580 utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 utils/adt/timestamp.c:3888 +#: utils/adt/date.c:2180 utils/adt/date.c:2732 utils/adt/float.c:1043 utils/adt/float.c:1119 utils/adt/int.c:635 utils/adt/int.c:682 utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2698 utils/adt/timestamp.c:3869 utils/adt/timestamp.c:3906 utils/adt/timestamp.c:3947 #, c-format msgid "invalid preceding or following size in window function" msgstr "ウィンドウ関数での不正なサイズの PRECEDING または FOLLOWING 指定" -#: utils/adt/date.c:2360 +#: utils/adt/date.c:2425 #, c-format msgid "time zone displacement out of range" msgstr "タイムゾーンの置換が範囲外です" -#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#: utils/adt/date.c:3197 utils/adt/timestamp.c:6404 utils/adt/timestamp.c:6641 #, c-format msgid "interval time zone \"%s\" must be finite" msgstr "タイムゾーンのインターバル\"%s\"は有限でなければなりません" -#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 +#: utils/adt/date.c:3204 utils/adt/timestamp.c:6411 utils/adt/timestamp.c:6648 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "intervalによるタイムゾーン\"%s\"には月または日を含めてはいけません" -#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 +#: utils/adt/datetime.c:3324 utils/adt/datetime.c:4243 utils/adt/datetime.c:4249 utils/adt/timestamp.c:530 #, c-format msgid "time zone \"%s\" not recognized" msgstr "タイムゾーン\"%s\"は不明です" -#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 +#: utils/adt/datetime.c:4217 utils/adt/datetime.c:4224 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "日付時刻のフィールドが範囲外です: \"%s\"" -#: utils/adt/datetime.c:4110 +#: utils/adt/datetime.c:4226 #, c-format -msgid "Perhaps you need a different \"datestyle\" setting." -msgstr "他の\"datestyle\"設定が必要かもしれません。" +msgid "Perhaps you need a different \"DateStyle\" setting." +msgstr "他の\"DateStyle\"設定が必要かもしれません。" -#: utils/adt/datetime.c:4115 +#: utils/adt/datetime.c:4231 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "intervalフィールドの値が範囲外です: \"%s\"" -#: utils/adt/datetime.c:4121 +#: utils/adt/datetime.c:4237 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "タイムゾーンの置換が範囲外です: \"%s\"" -#: utils/adt/datetime.c:4135 +#: utils/adt/datetime.c:4251 #, c-format msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"." msgstr "このタイムゾーンはタイムゾーン省略名\"%s\"の構成ファイルにあるようです。" @@ -24360,17 +25357,22 @@ msgstr "このタイムゾーンはタイムゾーン省略名\"%s\"の構成フ msgid "invalid Datum pointer" msgstr "不正なDatumポインタ" -#: utils/adt/dbsize.c:760 utils/adt/dbsize.c:836 +#: utils/adt/dbsize.c:293 utils/adt/genfile.c:656 +#, c-format +msgid "tablespace with OID %u does not exist" +msgstr "OID %uのテーブル空間は存在しません" + +#: utils/adt/dbsize.c:782 utils/adt/dbsize.c:858 #, c-format msgid "invalid size: \"%s\"" msgstr "不正なサイズ: \"%s\"" -#: utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:859 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "不正なサイズの単位: \"%s\"" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:860 #, c-format msgid "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." msgstr "有効な単位は \"bytes\"、\"B\"、\"kB\"、\"MB\"、\"GB\"、\"TB\"そして\"PB\"です。" @@ -24395,32 +25397,32 @@ msgstr "エンコーディング変換の結果が大きすぎです" msgid "result of decoding conversion is too large" msgstr "デコード変換の結果が大きすぎます" -#: utils/adt/encode.c:217 utils/adt/encode.c:227 +#: utils/adt/encode.c:238 utils/adt/encode.c:248 #, c-format msgid "invalid hexadecimal digit: \"%.*s\"" msgstr "不正な16進数表現: \"%.*s\"" -#: utils/adt/encode.c:223 +#: utils/adt/encode.c:244 #, c-format msgid "invalid hexadecimal data: odd number of digits" msgstr "不正な16進数データ: 桁数が奇数です" -#: utils/adt/encode.c:344 +#: utils/adt/encode.c:365 #, c-format msgid "unexpected \"=\" while decoding base64 sequence" msgstr "base64シーケンスのデコード中に想定外の\"=\"" -#: utils/adt/encode.c:356 +#: utils/adt/encode.c:377 #, c-format msgid "invalid symbol \"%.*s\" found while decoding base64 sequence" msgstr "base64シーケンスのデコード中に検出された不正なシンボル\"%.*s\"" -#: utils/adt/encode.c:377 +#: utils/adt/encode.c:398 #, c-format msgid "invalid base64 end sequence" msgstr "不正なbase64終了シーケンス" -#: utils/adt/encode.c:378 +#: utils/adt/encode.c:399 #, c-format msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "入力データにパディングがありません、切り詰められたかさもなければ壊れています。" @@ -24455,335 +25457,355 @@ msgstr "実際の列挙型を特定できませんでした" msgid "enum %s contains no values" msgstr "列挙型 %s に値がありません" -#: utils/adt/float.c:83 +#: utils/adt/float.c:90 #, c-format msgid "value out of range: overflow" msgstr "範囲外の値です: オーバーフロー" -#: utils/adt/float.c:91 +#: utils/adt/float.c:98 #, c-format msgid "value out of range: underflow" msgstr "範囲外の値です: アンダーフロー" -#: utils/adt/float.c:280 +#: utils/adt/float.c:287 #, c-format msgid "\"%s\" is out of range for type real" msgstr "型realでは\"%s\"は範囲外です" -#: utils/adt/float.c:482 +#: utils/adt/float.c:489 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "型double precisionでは\"%s\"は範囲外です" -#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 utils/adt/int8.c:1277 utils/adt/numeric.c:4578 utils/adt/numeric.c:4583 +#: utils/adt/float.c:1254 utils/adt/float.c:1328 utils/adt/int.c:355 utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 utils/adt/int8.c:1277 utils/adt/numeric.c:4696 utils/adt/numeric.c:4701 utils/adt/varlena.c:4093 #, c-format msgid "smallint out of range" msgstr "smallintの範囲外です" -#: utils/adt/float.c:1447 utils/adt/numeric.c:3694 utils/adt/numeric.c:10097 +#: utils/adt/float.c:1454 utils/adt/numeric.c:3812 utils/adt/numeric.c:10454 #, c-format msgid "cannot take square root of a negative number" msgstr "負の値の平方根を取ることができません" -#: utils/adt/float.c:1515 utils/adt/numeric.c:3982 utils/adt/numeric.c:4094 +#: utils/adt/float.c:1522 utils/adt/numeric.c:4100 utils/adt/numeric.c:4212 #, c-format msgid "zero raised to a negative power is undefined" msgstr "0 の負数乗は定義されていません" -#: utils/adt/float.c:1519 utils/adt/numeric.c:3986 utils/adt/numeric.c:10988 +#: utils/adt/float.c:1526 utils/adt/numeric.c:4104 utils/adt/numeric.c:11345 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "負数を整数でない数でべき乗すると、結果が複雑になります" -#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3894 utils/adt/numeric.c:10768 +#: utils/adt/float.c:1702 utils/adt/float.c:1735 utils/adt/numeric.c:4012 utils/adt/numeric.c:11125 #, c-format msgid "cannot take logarithm of zero" msgstr "ゼロの対数を取ることができません" -#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3832 utils/adt/numeric.c:3889 utils/adt/numeric.c:10772 +#: utils/adt/float.c:1706 utils/adt/float.c:1739 utils/adt/numeric.c:3950 utils/adt/numeric.c:4007 utils/adt/numeric.c:11129 #, c-format msgid "cannot take logarithm of a negative number" msgstr "負の値の対数を取ることができません" -#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 utils/adt/float.c:2696 utils/adt/float.c:2720 +#: utils/adt/float.c:1772 utils/adt/float.c:1803 utils/adt/float.c:1898 utils/adt/float.c:1925 utils/adt/float.c:1953 utils/adt/float.c:1980 utils/adt/float.c:2127 utils/adt/float.c:2164 utils/adt/float.c:2334 utils/adt/float.c:2390 utils/adt/float.c:2455 utils/adt/float.c:2512 utils/adt/float.c:2703 utils/adt/float.c:2727 #, c-format msgid "input is out of range" msgstr "入力が範囲外です" -#: utils/adt/float.c:4000 utils/adt/numeric.c:1842 +#: utils/adt/float.c:4085 utils/adt/numeric.c:1979 #, c-format msgid "count must be greater than zero" msgstr "カウントは0より大きくなければなりません" -#: utils/adt/float.c:4005 utils/adt/numeric.c:1853 +#: utils/adt/float.c:4090 utils/adt/numeric.c:1990 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "オペランド、下限、上限をNaNにすることはできません" -#: utils/adt/float.c:4011 utils/adt/numeric.c:1858 +#: utils/adt/float.c:4096 utils/adt/numeric.c:1995 #, c-format msgid "lower and upper bounds must be finite" msgstr "下限および上限は有限でなければなりません" -#: utils/adt/float.c:4077 utils/adt/numeric.c:1872 +#: utils/adt/float.c:4162 utils/adt/numeric.c:2009 #, c-format msgid "lower bound cannot equal upper bound" msgstr "下限を上限と同じにできません" -#: utils/adt/formatting.c:530 +#: utils/adt/formatting.c:556 #, c-format msgid "invalid format specification for an interval value" msgstr "\"tinterval\"値に対する不正な書式指定" -#: utils/adt/formatting.c:531 +#: utils/adt/formatting.c:557 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "時間間隔が特定の暦日付に結びついていません" -#: utils/adt/formatting.c:1161 +#: utils/adt/formatting.c:1197 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\"は最終パターンでなければなりません。" -#: utils/adt/formatting.c:1169 +#: utils/adt/formatting.c:1205 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\"は\"PR\"の前になければなりません" -#: utils/adt/formatting.c:1185 +#: utils/adt/formatting.c:1221 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\"は\"PR\"の前になければなりません" -#: utils/adt/formatting.c:1212 +#: utils/adt/formatting.c:1248 #, c-format msgid "multiple decimal points" msgstr "複数の小数点があります" -#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 +#: utils/adt/formatting.c:1252 utils/adt/formatting.c:1339 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "\"V\"と小数点を混在できません" -#: utils/adt/formatting.c:1228 +#: utils/adt/formatting.c:1264 #, c-format msgid "cannot use \"S\" twice" msgstr "\"S\"は1回しか使用できません" -#: utils/adt/formatting.c:1232 +#: utils/adt/formatting.c:1268 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "\"S\"と\"PL\"/\"MI\"/\"SG\"/\"PR\"を混在できません" -#: utils/adt/formatting.c:1252 +#: utils/adt/formatting.c:1288 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "\"S\"と\"MI\"を混在できません" -#: utils/adt/formatting.c:1262 +#: utils/adt/formatting.c:1298 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "\"S\"と\"PL\"を混在できません" -#: utils/adt/formatting.c:1272 +#: utils/adt/formatting.c:1308 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "\"S\"と\"SG\"を混在できません" -#: utils/adt/formatting.c:1281 +#: utils/adt/formatting.c:1317 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "\"PR\"と\"S\"/\"PL\"/\"MI\"/\"SG\"を混在できません" -#: utils/adt/formatting.c:1307 +#: utils/adt/formatting.c:1326 +#, c-format +msgid "cannot use \"RN\" twice" +msgstr "\"RN\"は1回しか使用できません" + +#: utils/adt/formatting.c:1347 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "\"EEEE\"は1回しか使用できません" -#: utils/adt/formatting.c:1313 +#: utils/adt/formatting.c:1353 #, c-format msgid "\"EEEE\" is incompatible with other formats" -msgstr "\"EEEE\"が他のフォーマットと互換性がありません。" +msgstr "\"EEEE\"が他のフォーマットと互換性がありません" -#: utils/adt/formatting.c:1314 +#: utils/adt/formatting.c:1354 #, c-format msgid "\"EEEE\" may only be used together with digit and decimal point patterns." -msgstr "\"EEEE\"は数値または小数点パターンと共に指定してください。" +msgstr "\"EEEE\"は数値および小数点パターンと共にのみ使用できます。" -#: utils/adt/formatting.c:1398 +#: utils/adt/formatting.c:1363 +#, c-format +msgid "\"RN\" is incompatible with other formats" +msgstr "\"RN\"が他のフォーマットと互換性がありません" + +#: utils/adt/formatting.c:1364 +#, c-format +msgid "\"RN\" may only be used together with \"FM\"." +msgstr "\"RN\"は\"FM\"と共にのみ使用できます。" + +#: utils/adt/formatting.c:1445 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "不正なdatetime書式のセパレータ: \"%s\"" -#: utils/adt/formatting.c:1525 +#: utils/adt/formatting.c:1572 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\"は数値ではありません" -#: utils/adt/formatting.c:1603 -#, c-format -msgid "case conversion failed: %s" -msgstr "文字ケースの変換に失敗しました: %s" - -#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 utils/adt/formatting.c:1989 +#: utils/adt/formatting.c:1653 utils/adt/formatting.c:1717 utils/adt/formatting.c:1781 utils/adt/formatting.c:1845 #, c-format msgid "could not determine which collation to use for %s function" msgstr "%s 関数に対して使用する照合順序を特定できませんでした" -#: utils/adt/formatting.c:2410 +#: utils/adt/formatting.c:1853 +#, c-format +msgid "Unicode case folding can only be performed if server encoding is UTF8" +msgstr "UnicodeケースフォールディングはサーバーエンコーディングがUTF-8の場合にのみ実行可能です" + +#: utils/adt/formatting.c:2150 #, c-format msgid "invalid combination of date conventions" msgstr "不正な暦法の組み合わせ" -#: utils/adt/formatting.c:2411 +#: utils/adt/formatting.c:2151 #, c-format msgid "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr "単一の書式テンプレートの中では、グレゴリオ暦とISO歴週日付を混在させないでください。" -#: utils/adt/formatting.c:2433 +#: utils/adt/formatting.c:2173 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "書式文字列中で\"%s\"フィールドの値が衝突しています" -#: utils/adt/formatting.c:2435 +#: utils/adt/formatting.c:2175 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "この値は同じフィールド型に対する以前の設定と矛盾しています" -#: utils/adt/formatting.c:2502 +#: utils/adt/formatting.c:2242 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "書式フィールド\"%s\"に対して元の文字列が短すぎます" -#: utils/adt/formatting.c:2504 +#: utils/adt/formatting.c:2244 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "フィールドには%d文字必要ですが、%d文字しか残っていません。" -#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 +#: utils/adt/formatting.c:2246 utils/adt/formatting.c:2260 #, c-format msgid "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "元の文字列が固定長でない場合は、修飾子\"FM\"を試してみてください。" -#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 +#: utils/adt/formatting.c:2256 utils/adt/formatting.c:2269 utils/adt/formatting.c:2490 utils/adt/formatting.c:3390 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "\"%2$s\"に対する不正な値\"%1$s\"" -#: utils/adt/formatting.c:2518 +#: utils/adt/formatting.c:2258 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "このフィールドには%d文字必要ですが、%d文字しかパースされませんでした。" -#: utils/adt/formatting.c:2531 +#: utils/adt/formatting.c:2271 #, c-format msgid "Value must be an integer." msgstr "値は整数でなければなりません。" -#: utils/adt/formatting.c:2536 +#: utils/adt/formatting.c:2276 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "もとの文字列において\"%s\"に対応する値が範囲外です" -#: utils/adt/formatting.c:2538 +#: utils/adt/formatting.c:2278 #, c-format msgid "Value must be in the range %d to %d." msgstr "値は%dから%dまでの範囲でなければなりません。" -#: utils/adt/formatting.c:2752 +#: utils/adt/formatting.c:2492 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "与えられた値がこの項目に対して許されるいずれの値ともマッチしません。" -#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 +#: utils/adt/formatting.c:2708 utils/adt/formatting.c:2728 utils/adt/formatting.c:2748 utils/adt/formatting.c:2768 utils/adt/formatting.c:2787 utils/adt/formatting.c:2806 utils/adt/formatting.c:2830 utils/adt/formatting.c:2848 utils/adt/formatting.c:2866 utils/adt/formatting.c:2884 utils/adt/formatting.c:2901 utils/adt/formatting.c:2918 #, c-format msgid "localized string format value too long" msgstr "地域化した文字列のフォーマットが長すぎます" -#: utils/adt/formatting.c:3458 +#: utils/adt/formatting.c:3198 #, c-format msgid "unmatched format separator \"%c\"" msgstr "合致しないフォーマットセパレータ \"%c\"" -#: utils/adt/formatting.c:3519 +#: utils/adt/formatting.c:3259 #, c-format msgid "unmatched format character \"%s\"" msgstr "合致しないフォーマット文字\"%s\"" -#: utils/adt/formatting.c:3652 +#: utils/adt/formatting.c:3392 #, c-format msgid "Time zone abbreviation is not recognized." msgstr "タイムゾーン省略名が認識されません。" -#: utils/adt/formatting.c:3853 +#: utils/adt/formatting.c:3593 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr " \"Y,YYY\"に対応する入力文字列が不正です" -#: utils/adt/formatting.c:3942 +#: utils/adt/formatting.c:3600 +#, c-format +msgid "value for \"Y,YYY\" in source string is out of range" +msgstr "もとの文字列内の\"Y,YYY\"に対応する値が範囲外です" + +#: utils/adt/formatting.c:3689 #, c-format msgid "input string is too short for datetime format" msgstr "datetime書式に対して入力文字列が短すぎます" -#: utils/adt/formatting.c:3950 +#: utils/adt/formatting.c:3697 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "datetimeフォーマット後に文字が入力文字列中に残っています" -#: utils/adt/formatting.c:4494 +#: utils/adt/formatting.c:4241 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "timestamptz型に対応する入力に時間帯がありません" -#: utils/adt/formatting.c:4500 +#: utils/adt/formatting.c:4247 #, c-format msgid "timestamptz out of range" msgstr "timestamptzの範囲外です" -#: utils/adt/formatting.c:4528 +#: utils/adt/formatting.c:4275 #, c-format msgid "datetime format is zoned but not timed" msgstr "datetimeフォーマットで時間帯は指定されていますが、時刻が指定されていません" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4324 #, c-format msgid "missing time zone in input string for type timetz" msgstr "timetz型に対する入力文字列中に時間帯がありません" -#: utils/adt/formatting.c:4583 +#: utils/adt/formatting.c:4330 #, c-format msgid "timetz out of range" msgstr "timetzの範囲外です" -#: utils/adt/formatting.c:4609 +#: utils/adt/formatting.c:4356 #, c-format msgid "datetime format is not dated and not timed" msgstr "datetimeフォーマットで日付は指定されていますが、時間が指定されていません" -#: utils/adt/formatting.c:4786 +#: utils/adt/formatting.c:4533 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "12時間形式では\"%d\"時は不正です" -#: utils/adt/formatting.c:4788 +#: utils/adt/formatting.c:4535 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "24時間形式を使うか、もしくは 1 から 12 の間で指定してください。" -#: utils/adt/formatting.c:4900 +#: utils/adt/formatting.c:4712 #, c-format msgid "cannot calculate day of year without year information" msgstr "年の情報なしでは年内の日数は計算できません" -#: utils/adt/formatting.c:5852 +#: utils/adt/formatting.c:5833 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\"は入力としてサポートしていません" -#: utils/adt/formatting.c:5864 +#: utils/adt/formatting.c:6110 #, c-format -msgid "\"RN\" not supported for input" -msgstr "\"RN\"は入力としてサポートしていません" +msgid "invalid Roman numeral" +msgstr "不正なローマ数字" #: utils/adt/genfile.c:84 #, c-format @@ -24795,7 +25817,7 @@ msgstr "絶対パスは許可されていません" msgid "path must be in or below the data directory" msgstr "パスはデータディレクトリ内もしくはより下層でなければなりません" -#: utils/adt/genfile.c:114 utils/adt/oracle_compat.c:190 utils/adt/oracle_compat.c:288 utils/adt/oracle_compat.c:839 utils/adt/oracle_compat.c:1142 +#: utils/adt/genfile.c:114 utils/adt/oracle_compat.c:206 utils/adt/oracle_compat.c:304 utils/adt/oracle_compat.c:855 utils/adt/oracle_compat.c:1158 #, c-format msgid "requested length too large" msgstr "要求した長さが長すぎます" @@ -24810,11 +25832,6 @@ msgstr "ファイル\"%s\"をシークできませんでした: %m" msgid "file length too large" msgstr "ファイルが大きすぎます" -#: utils/adt/genfile.c:656 -#, c-format -msgid "tablespace with OID %u does not exist" -msgstr "OID %uのテーブル空間は存在しません" - #: utils/adt/geo_ops.c:998 utils/adt/geo_ops.c:1052 #, c-format msgid "invalid line specification: A and B cannot both be zero" @@ -24865,13 +25882,13 @@ msgstr "少なくとも2ポイントを要求しなければなりません" msgid "invalid int2vector data" msgstr "不正なint2vectorデータ" -#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1750 utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1767 utils/adt/timestamp.c:6708 utils/adt/timestamp.c:6794 #, c-format msgid "step size cannot equal zero" msgstr "ステップ数をゼロにすることはできません" #: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 utils/adt/int8.c:1055 -#: utils/adt/int8.c:1069 utils/adt/int8.c:1100 utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4527 utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 utils/adt/varbit.c:1676 +#: utils/adt/int8.c:1069 utils/adt/int8.c:1100 utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4645 utils/adt/rangetypes.c:1599 utils/adt/rangetypes.c:1612 utils/adt/varbit.c:1676 utils/adt/varlena.c:4143 #, c-format msgid "bigint out of range" msgstr "bigintの範囲外です" @@ -24881,48 +25898,48 @@ msgstr "bigintの範囲外です" msgid "OID out of range" msgstr "OIDの範囲外です" -#: utils/adt/json.c:202 utils/adt/jsonb.c:664 +#: utils/adt/json.c:204 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "キー値は配列でも複合型でもJSONでもなく、スカラでなくてはなりません" -#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 +#: utils/adt/json.c:1043 utils/adt/json.c:1053 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "引数%dのデータ型が特定できませんでした" -#: utils/adt/json.c:1067 utils/adt/json.c:1259 utils/adt/json.c:1435 utils/adt/json.c:1513 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 +#: utils/adt/json.c:1076 utils/adt/json.c:1275 utils/adt/json.c:1457 utils/adt/json.c:1531 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "オブジェクトキーにnullは使えません" -#: utils/adt/json.c:1110 utils/adt/json.c:1274 +#: utils/adt/json.c:1126 utils/adt/json.c:1297 #, c-format msgid "duplicate JSON object key value: %s" msgstr "JSONオブジェクトキー値の重複: %s" -#: utils/adt/json.c:1219 utils/adt/jsonb.c:1134 +#: utils/adt/json.c:1235 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "引数リストの要素数は偶数でなければなりません" #. translator: %s is a SQL function name -#: utils/adt/json.c:1221 utils/adt/jsonb.c:1136 +#: utils/adt/json.c:1237 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "%s の引数ではキーと値が交互になっている必要があります。" -#: utils/adt/json.c:1413 utils/adt/jsonb.c:1311 +#: utils/adt/json.c:1435 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "配列は最低でも2つの列が必要です" -#: utils/adt/json.c:1502 utils/adt/jsonb.c:1412 +#: utils/adt/json.c:1520 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "配列の次元が合っていません" -#: utils/adt/json.c:1688 utils/adt/jsonb_util.c:1956 +#: utils/adt/json.c:1850 utils/adt/jsonb_util.c:1963 #, c-format msgid "duplicate JSON object key value" msgstr "JSONオブジェクトキー値の重複" @@ -24987,22 +26004,22 @@ msgstr "jsonbオブジェクトは%s型へはキャストできません" msgid "cannot cast jsonb array or object to type %s" msgstr "jsonbの配列またはオブジェクトは%s型へはキャストできません" -#: utils/adt/jsonb_util.c:756 +#: utils/adt/jsonb_util.c:763 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "jsonbオブジェクトペア数が許された最大の値(%zu)を上回っています" -#: utils/adt/jsonb_util.c:797 +#: utils/adt/jsonb_util.c:804 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "jsonbの配列要素の数が許された最大の値(%zu)を上回っています" -#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 +#: utils/adt/jsonb_util.c:1678 utils/adt/jsonb_util.c:1698 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "jsonb配列全体のサイズが最大値%dバイトを超えています" -#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 utils/adt/jsonb_util.c:1807 +#: utils/adt/jsonb_util.c:1759 utils/adt/jsonb_util.c:1794 utils/adt/jsonb_util.c:1814 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "jsonbオブジェクト要素全体のサイズが最大値%dを超えています" @@ -25037,204 +26054,204 @@ msgstr "jsonb添字はテキスト型でなければなりません" msgid "jsonb subscript in assignment must not be null" msgstr "代入におけるjsonb添え字はnullにはできません" -#: utils/adt/jsonfuncs.c:582 utils/adt/jsonfuncs.c:829 utils/adt/jsonfuncs.c:2438 utils/adt/jsonfuncs.c:3013 utils/adt/jsonfuncs.c:3926 utils/adt/jsonfuncs.c:4273 +#: utils/adt/jsonfuncs.c:585 utils/adt/jsonfuncs.c:832 utils/adt/jsonfuncs.c:2441 utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3950 utils/adt/jsonfuncs.c:4297 #, c-format msgid "cannot call %s on a scalar" msgstr "スカラに対して%sを呼び出すことはできません" -#: utils/adt/jsonfuncs.c:587 utils/adt/jsonfuncs.c:814 utils/adt/jsonfuncs.c:3015 utils/adt/jsonfuncs.c:3913 +#: utils/adt/jsonfuncs.c:590 utils/adt/jsonfuncs.c:817 utils/adt/jsonfuncs.c:3019 utils/adt/jsonfuncs.c:3937 #, c-format msgid "cannot call %s on an array" msgstr "配列に対して%sを呼び出すことはできません" -#: utils/adt/jsonfuncs.c:723 +#: utils/adt/jsonfuncs.c:726 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "JSONデータ、%d行目: %s%s%s" -#: utils/adt/jsonfuncs.c:1882 utils/adt/jsonfuncs.c:1919 +#: utils/adt/jsonfuncs.c:1885 utils/adt/jsonfuncs.c:1922 #, c-format msgid "cannot get array length of a scalar" msgstr "スカラから配列長を得ることはできません" -#: utils/adt/jsonfuncs.c:1886 utils/adt/jsonfuncs.c:1905 +#: utils/adt/jsonfuncs.c:1889 utils/adt/jsonfuncs.c:1908 #, c-format msgid "cannot get array length of a non-array" msgstr "配列では無いものから配列長を得ることはできません" -#: utils/adt/jsonfuncs.c:1985 +#: utils/adt/jsonfuncs.c:1988 #, c-format msgid "cannot call %s on a non-object" msgstr "非オブジェクトに対して%sは呼び出せません" -#: utils/adt/jsonfuncs.c:2173 +#: utils/adt/jsonfuncs.c:2176 #, c-format msgid "cannot deconstruct an array as an object" msgstr "配列をオブジェクトとして再構築することはできません" -#: utils/adt/jsonfuncs.c:2187 +#: utils/adt/jsonfuncs.c:2190 #, c-format msgid "cannot deconstruct a scalar" msgstr "スカラを再構築することはできません" -#: utils/adt/jsonfuncs.c:2232 +#: utils/adt/jsonfuncs.c:2235 #, c-format msgid "cannot extract elements from a scalar" msgstr "スカラから要素を取り出すことはできません" -#: utils/adt/jsonfuncs.c:2236 +#: utils/adt/jsonfuncs.c:2239 #, c-format msgid "cannot extract elements from an object" msgstr "オブジェクトから要素を取り出すことはできません" -#: utils/adt/jsonfuncs.c:2423 utils/adt/jsonfuncs.c:4151 +#: utils/adt/jsonfuncs.c:2426 utils/adt/jsonfuncs.c:4175 #, c-format msgid "cannot call %s on a non-array" msgstr "非配列に対して%sを呼び出すことはできません" -#: utils/adt/jsonfuncs.c:2514 utils/adt/jsonfuncs.c:2519 utils/adt/jsonfuncs.c:2537 utils/adt/jsonfuncs.c:2543 +#: utils/adt/jsonfuncs.c:2517 utils/adt/jsonfuncs.c:2522 utils/adt/jsonfuncs.c:2540 utils/adt/jsonfuncs.c:2546 #, c-format msgid "expected JSON array" msgstr "JSON配列を期待していました" -#: utils/adt/jsonfuncs.c:2515 +#: utils/adt/jsonfuncs.c:2518 #, c-format msgid "See the value of key \"%s\"." msgstr "キー\"%s\"の値を見てください。" -#: utils/adt/jsonfuncs.c:2538 +#: utils/adt/jsonfuncs.c:2541 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "キー\"%s\"の配列要素%sを見てください。" -#: utils/adt/jsonfuncs.c:2544 +#: utils/adt/jsonfuncs.c:2547 #, c-format msgid "See the array element %s." msgstr "配列要素%sを見てください。" -#: utils/adt/jsonfuncs.c:2596 +#: utils/adt/jsonfuncs.c:2599 #, c-format msgid "malformed JSON array" msgstr "不正な形式のJSON配列" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3625 +#: utils/adt/jsonfuncs.c:3649 #, c-format msgid "first argument of %s must be a row type" msgstr "%sの最初の引数は行型でなければなりません" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3649 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "could not determine row type for result of %s" msgstr "%sの結果に対応する行の型を決定できませんでした" -#: utils/adt/jsonfuncs.c:3651 +#: utils/adt/jsonfuncs.c:3675 #, c-format msgid "Provide a non-null record argument, or call the function in the FROM clause using a column definition list." msgstr "非NULLのレコード引数を与えるか、列定義リストを用いてこの関数をFROM句中で呼び出してください。" -#: utils/adt/jsonfuncs.c:4037 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4061 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "マテリアライズモードが必要ですが、現在のコンテクストで禁止されています" -#: utils/adt/jsonfuncs.c:4168 utils/adt/jsonfuncs.c:4252 +#: utils/adt/jsonfuncs.c:4192 utils/adt/jsonfuncs.c:4276 #, c-format msgid "argument of %s must be an array of objects" msgstr "%sの引数はオブジェクト配列でなければなりません" -#: utils/adt/jsonfuncs.c:4201 +#: utils/adt/jsonfuncs.c:4225 #, c-format msgid "cannot call %s on an object" msgstr "オブジェクトに対して%sを呼び出すことはできません" -#: utils/adt/jsonfuncs.c:4634 utils/adt/jsonfuncs.c:4693 utils/adt/jsonfuncs.c:4773 +#: utils/adt/jsonfuncs.c:4680 utils/adt/jsonfuncs.c:4739 utils/adt/jsonfuncs.c:4819 #, c-format msgid "cannot delete from scalar" msgstr "スカラから削除することはできません" -#: utils/adt/jsonfuncs.c:4778 +#: utils/adt/jsonfuncs.c:4824 #, c-format msgid "cannot delete from object using integer index" msgstr "オブジェクトから整数添字を使って削除することはできません" -#: utils/adt/jsonfuncs.c:4846 utils/adt/jsonfuncs.c:5005 +#: utils/adt/jsonfuncs.c:4892 utils/adt/jsonfuncs.c:5051 #, c-format msgid "cannot set path in scalar" msgstr "スカラにパスを設定することはできません" -#: utils/adt/jsonfuncs.c:4887 utils/adt/jsonfuncs.c:4929 +#: utils/adt/jsonfuncs.c:4933 utils/adt/jsonfuncs.c:4975 #, c-format msgid "null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"" msgstr "null_value_treatment は \"delete_key\", \"return_target\", \"use_json_null\" または \"raise_exception\"である必要があります" -#: utils/adt/jsonfuncs.c:4900 +#: utils/adt/jsonfuncs.c:4946 #, c-format msgid "JSON value must not be null" msgstr "JSON値はnullではあってはなりません" -#: utils/adt/jsonfuncs.c:4901 +#: utils/adt/jsonfuncs.c:4947 #, c-format msgid "Exception was raised because null_value_treatment is \"raise_exception\"." msgstr "null_value_treatmentが\"raise_exception\"であるため、例外が出力されました" -#: utils/adt/jsonfuncs.c:4902 +#: utils/adt/jsonfuncs.c:4948 #, c-format msgid "To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed." msgstr "これを避けるには、 null_value_treatment引数を変更するか、SQLのNULLを渡さないようにしてください。" -#: utils/adt/jsonfuncs.c:4957 +#: utils/adt/jsonfuncs.c:5003 #, c-format msgid "cannot delete path in scalar" msgstr "スカラでパスを削除することはできません" -#: utils/adt/jsonfuncs.c:5171 +#: utils/adt/jsonfuncs.c:5217 #, c-format msgid "path element at position %d is null" msgstr "位置%dのパス要素がnullです" -#: utils/adt/jsonfuncs.c:5190 utils/adt/jsonfuncs.c:5221 utils/adt/jsonfuncs.c:5294 +#: utils/adt/jsonfuncs.c:5236 utils/adt/jsonfuncs.c:5267 utils/adt/jsonfuncs.c:5340 #, c-format msgid "cannot replace existing key" msgstr "既存のキーを置き換えることはできません" -#: utils/adt/jsonfuncs.c:5191 utils/adt/jsonfuncs.c:5222 +#: utils/adt/jsonfuncs.c:5237 utils/adt/jsonfuncs.c:5268 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "このパスではキー値は複合オブジェクトであると想定していますが、スカラー値でした" -#: utils/adt/jsonfuncs.c:5295 +#: utils/adt/jsonfuncs.c:5341 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "jsonb_set関数を使ってキー値を置き換えることを試してください。" -#: utils/adt/jsonfuncs.c:5399 +#: utils/adt/jsonfuncs.c:5445 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "位置%dのパス要素が整数ではありません: \"%s\"" -#: utils/adt/jsonfuncs.c:5416 +#: utils/adt/jsonfuncs.c:5462 #, c-format msgid "path element at position %d is out of range: %d" msgstr "位置%dのパス要素は範囲外です: %d" -#: utils/adt/jsonfuncs.c:5568 +#: utils/adt/jsonfuncs.c:5614 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "間違ったフラグのタイプ; 配列およびスカラのみ使用可能です" -#: utils/adt/jsonfuncs.c:5575 +#: utils/adt/jsonfuncs.c:5621 #, c-format msgid "flag array element is not a string" msgstr "フラグ配列の要素が文字列ではありません" -#: utils/adt/jsonfuncs.c:5576 utils/adt/jsonfuncs.c:5598 +#: utils/adt/jsonfuncs.c:5622 utils/adt/jsonfuncs.c:5644 #, c-format msgid "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\"." msgstr "使用可能な値は: \"string\", \"numeric\", \"boolean\", \"key\"、および \"all\"。" -#: utils/adt/jsonfuncs.c:5596 +#: utils/adt/jsonfuncs.c:5642 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "フラグ配列内の間違ったフラグ値: \"%s\"" @@ -25249,214 +26266,194 @@ msgstr "ルート式では@を使用できません" msgid "LAST is allowed only in array subscripts" msgstr "LAST は配列の添え字でのみ使用可能です" -#: utils/adt/jsonpath_exec.c:491 +#: utils/adt/jsonpath_exec.c:489 #, c-format msgid "single boolean result is expected" msgstr "単一のブール値の結果が必要です" -#: utils/adt/jsonpath_exec.c:851 +#: utils/adt/jsonpath_exec.c:849 #, c-format msgid "jsonpath wildcard array accessor can only be applied to an array" msgstr "jsonpath ワイルドカード配列アクセサは配列にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:874 +#: utils/adt/jsonpath_exec.c:872 #, c-format msgid "jsonpath wildcard member accessor can only be applied to an object" msgstr "jsonpathワイルドカードメンバアクセサはオブジェクトに対してのみ適用可能です" -#: utils/adt/jsonpath_exec.c:923 +#: utils/adt/jsonpath_exec.c:921 #, c-format msgid "jsonpath array subscript is out of bounds" msgstr "jsonpath配列の添え字が範囲外です" -#: utils/adt/jsonpath_exec.c:980 +#: utils/adt/jsonpath_exec.c:978 #, c-format msgid "jsonpath array accessor can only be applied to an array" msgstr "jsonpath 配列アクセサは配列にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:1044 +#: utils/adt/jsonpath_exec.c:1042 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "JSONオブジェクトはキー\"%s\"を含んでいません" -#: utils/adt/jsonpath_exec.c:1056 +#: utils/adt/jsonpath_exec.c:1054 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "jsonpathメンバアクセサはオブジェクトに対してのみ適用可能です" -#: utils/adt/jsonpath_exec.c:1114 +#: utils/adt/jsonpath_exec.c:1112 #, c-format msgid "jsonpath item method .%s() can only be applied to an array" msgstr "jsonpath 項目メソッド .%s() は配列にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 +#: utils/adt/jsonpath_exec.c:1165 utils/adt/jsonpath_exec.c:1191 utils/adt/jsonpath_exec.c:1279 utils/adt/jsonpath_exec.c:1304 utils/adt/jsonpath_exec.c:1356 utils/adt/jsonpath_exec.c:1376 utils/adt/jsonpath_exec.c:1438 utils/adt/jsonpath_exec.c:1527 utils/adt/jsonpath_exec.c:1560 utils/adt/jsonpath_exec.c:1584 #, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type double precision" -msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"がdouble precision型に適合しません" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type %s" +msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"が型%3$sに適合しません" -#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 +#: utils/adt/jsonpath_exec.c:1170 utils/adt/jsonpath_exec.c:1196 utils/adt/jsonpath_exec.c:1413 utils/adt/jsonpath_exec.c:1445 #, c-format msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" msgstr "NaNとInifinityはjsonpath項目メソッド .%s() では使用できません" -#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 +#: utils/adt/jsonpath_exec.c:1209 utils/adt/jsonpath_exec.c:1312 utils/adt/jsonpath_exec.c:1454 utils/adt/jsonpath_exec.c:1592 #, c-format msgid "jsonpath item method .%s() can only be applied to a string or numeric value" msgstr "jsonpath 項目メソッド .%s() は文字列または数値にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 -#, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" -msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"がbigint型に適合しません" - -#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 +#: utils/adt/jsonpath_exec.c:1385 #, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" -msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"がboolean型に適合しません" - -#: utils/adt/jsonpath_exec.c:1386 -#, c-format -msgid "jsonpath item method .%s() can only be applied to a bool, string, or numeric value" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, or numeric value" msgstr "jsonpath 項目メソッド .%s() は真偽値、文字列または数値にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 -#, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" -msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"がnumeric型に適合しません" - -#: utils/adt/jsonpath_exec.c:1487 +#: utils/adt/jsonpath_exec.c:1486 #, c-format msgid "precision of jsonpath item method .%s() is out of range for type integer" msgstr "JSONパス項目メソッド .%s() の精度がinteger型の範囲外です" -#: utils/adt/jsonpath_exec.c:1501 +#: utils/adt/jsonpath_exec.c:1500 #, c-format msgid "scale of jsonpath item method .%s() is out of range for type integer" msgstr "JSONパス項目メソッド .%s() のスケールがinteger型の範囲外です" -#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 +#: utils/adt/jsonpath_exec.c:1647 #, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type integer" -msgstr "jsonpath項目メソッド .%2$s() の引数\"%1$s\"がinteger型に適合しません" - -#: utils/adt/jsonpath_exec.c:1664 -#, c-format -msgid "jsonpath item method .%s() can only be applied to a bool, string, numeric, or datetime value" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value" msgstr "jsonpath 項目メソッド .%s() は真偽値、文字列、数値、または日時値にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:2153 +#: utils/adt/jsonpath_exec.c:2136 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "jsonpath演算子 %s の左辺値が単一の数値ではありません" -#: utils/adt/jsonpath_exec.c:2160 +#: utils/adt/jsonpath_exec.c:2143 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "jsonpath演算子 %s の右辺値が単一の数値ではありません" -#: utils/adt/jsonpath_exec.c:2228 +#: utils/adt/jsonpath_exec.c:2211 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "単項jsonpath演算子 %s のオペランドが数値ではありません" -#: utils/adt/jsonpath_exec.c:2327 +#: utils/adt/jsonpath_exec.c:2310 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "jsonpath 項目メソッド .%s() は数値にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:2373 +#: utils/adt/jsonpath_exec.c:2356 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "jsonpath 項目メソッド .%s() は文字列にのみ適用可能です" -#: utils/adt/jsonpath_exec.c:2466 +#: utils/adt/jsonpath_exec.c:2449 #, c-format msgid "time precision of jsonpath item method .%s() is out of range for type integer" msgstr "JSONパス項目メソッド .%s() の日付時刻精度がinteger型の範囲外です" -#: utils/adt/jsonpath_exec.c:2500 utils/adt/jsonpath_exec.c:2506 utils/adt/jsonpath_exec.c:2533 utils/adt/jsonpath_exec.c:2561 utils/adt/jsonpath_exec.c:2614 utils/adt/jsonpath_exec.c:2665 utils/adt/jsonpath_exec.c:2721 +#: utils/adt/jsonpath_exec.c:2483 utils/adt/jsonpath_exec.c:2489 utils/adt/jsonpath_exec.c:2516 utils/adt/jsonpath_exec.c:2544 utils/adt/jsonpath_exec.c:2597 utils/adt/jsonpath_exec.c:2648 utils/adt/jsonpath_exec.c:2719 #, c-format msgid "%s format is not recognized: \"%s\"" msgstr "%sの書式を認識できません: \"%s\"" -#: utils/adt/jsonpath_exec.c:2502 +#: utils/adt/jsonpath_exec.c:2485 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "datetimeテンプレート引数を使って入力データフォーマットを指定してください。" -#: utils/adt/jsonpath_exec.c:2695 utils/adt/jsonpath_exec.c:2751 +#: utils/adt/jsonpath_exec.c:2678 utils/adt/jsonpath_exec.c:2759 #, c-format msgid "time precision of jsonpath item method .%s() is invalid" msgstr "jsonpath項目メソッド .%s() の日付時刻精度が不正です" -#: utils/adt/jsonpath_exec.c:2831 +#: utils/adt/jsonpath_exec.c:2839 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "jsonpath項目メソッド .%s() はオブジェクトに対してのみ適用可能です" -#: utils/adt/jsonpath_exec.c:3114 +#: utils/adt/jsonpath_exec.c:3123 #, c-format msgid "could not convert value of type %s to jsonpath" msgstr "型%sの値のjsonpathへ変換ができませんでした" -#: utils/adt/jsonpath_exec.c:3148 +#: utils/adt/jsonpath_exec.c:3157 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "jsonpath変数\"%s\"が見つかりませんでした" -#: utils/adt/jsonpath_exec.c:3201 +#: utils/adt/jsonpath_exec.c:3210 #, c-format msgid "\"vars\" argument is not an object" msgstr "引数\"vars\"がオブジェクトではありません" -#: utils/adt/jsonpath_exec.c:3202 +#: utils/adt/jsonpath_exec.c:3211 #, c-format msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." msgstr "Jsonpath パラメータは \"vars\"オブジェクトの key-value ペアの形にエンコードされていなければなりません。" -#: utils/adt/jsonpath_exec.c:3465 +#: utils/adt/jsonpath_exec.c:3474 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "jsonpath配列添え字が単一の数値ではありません" -#: utils/adt/jsonpath_exec.c:3477 +#: utils/adt/jsonpath_exec.c:3486 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "jsonpath配列の添え字が整数の範囲外です" -#: utils/adt/jsonpath_exec.c:3661 +#: utils/adt/jsonpath_exec.c:3670 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "時間帯を使用せずに%sから%sへの値の変換はできません" -#: utils/adt/jsonpath_exec.c:3663 +#: utils/adt/jsonpath_exec.c:3672 #, c-format msgid "Use *_tz() function for time zone support." msgstr "*_tz() 関数を使用することで時間帯がサポートされます。" -#: utils/adt/jsonpath_exec.c:3957 +#: utils/adt/jsonpath_exec.c:3980 #, c-format -msgid "JSON path expression for column \"%s\" should return single item without wrapper" -msgstr "列\"%s\"に対するJSONパス式はラッパーなしの単一要素を返却する必要があります" +msgid "JSON path expression for column \"%s\" must return single item when no wrapper is requested" +msgstr "ラッパーが要求されていない場合は、列\"%s\"に対するJSONパス式は単一要素を返却する必要があります" -#: utils/adt/jsonpath_exec.c:3959 utils/adt/jsonpath_exec.c:3964 +#: utils/adt/jsonpath_exec.c:3982 utils/adt/jsonpath_exec.c:3987 #, c-format -msgid "Use WITH WRAPPER clause to wrap SQL/JSON items into array." +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." msgstr "SQL/JSON要素列を配列にまとめるにはWITH WRAPPER句を使用してください。" -#: utils/adt/jsonpath_exec.c:3963 +#: utils/adt/jsonpath_exec.c:3986 #, c-format -msgid "JSON path expression in JSON_QUERY should return single item without wrapper" -msgstr "JSON_QUERY中のJSONパス式はラッパーなしの単一要素を返却する必要があります" +msgid "JSON path expression in JSON_QUERY must return single item when no wrapper is requested" +msgstr "ラッパーが要求されていない場合は、JSON_QUERY中のJSONパス式は単一要素を返却する必要があります" -#: utils/adt/jsonpath_exec.c:4021 utils/adt/jsonpath_exec.c:4045 +#: utils/adt/jsonpath_exec.c:4044 utils/adt/jsonpath_exec.c:4068 #, c-format -msgid "JSON path expression for column \"%s\" should return single scalar item" +msgid "JSON path expression for column \"%s\" must return single scalar item" msgstr "列\"%s\"に対するJSONパス式は単一のスカラー要素を返却する必要があります" -#: utils/adt/jsonpath_exec.c:4026 utils/adt/jsonpath_exec.c:4050 +#: utils/adt/jsonpath_exec.c:4049 utils/adt/jsonpath_exec.c:4073 #, c-format -msgid "JSON path expression in JSON_VALUE should return single scalar item" +msgid "JSON path expression in JSON_VALUE must return single scalar item" msgstr "JSON_VALUE中のJSONパス式は単一のスカラー要素を返却する必要があります" #: utils/adt/levenshtein.c:132 @@ -25464,42 +26461,42 @@ msgstr "JSON_VALUE中のJSONパス式は単一のスカラー要素を返却す msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "レーベンシュタイン距離関数の引数の長さが上限の%d文字を超えています" -#: utils/adt/like.c:159 +#: utils/adt/like.c:162 #, c-format -msgid "nondeterministic collations are not supported for LIKE" -msgstr "非決定的照合順序はLIKEではサポートされません" +msgid "could not determine which collation to use for LIKE" +msgstr "LIKE で使用する照合順序を特定できませんでした" -#: utils/adt/like.c:188 utils/adt/like_support.c:1023 +#: utils/adt/like.c:193 utils/adt/like_support.c:1019 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "ILIKE で使用する照合順序を特定できませんでした" -#: utils/adt/like.c:200 +#: utils/adt/like.c:202 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "非決定的照合順序はILIKEではサポートされません" -#: utils/adt/like_match.c:108 utils/adt/like_match.c:168 +#: utils/adt/like_match.c:107 utils/adt/like_match.c:169 utils/adt/like_match.c:237 #, c-format msgid "LIKE pattern must not end with escape character" msgstr "LIKE パターンはエスケープ文字で終わってはなりません" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 +#: utils/adt/like_match.c:437 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "不正なエスケープ文字列" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:438 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "エスケープ文字は空か1文字でなければなりません。" -#: utils/adt/like_support.c:1013 +#: utils/adt/like_support.c:1009 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "型byteaでは大文字小文字の区別をしないマッチをサポートしません" -#: utils/adt/like_support.c:1114 +#: utils/adt/like_support.c:1106 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "型byteaでは正規表現のマッチをサポートしません" @@ -25519,11 +26516,16 @@ msgstr "macaddr8データがmacaddr型に変換するには範囲外です" msgid "Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr." msgstr "左から4、5バイト目にFFとFEがあるアドレス、具体的には xx:xx:xx:ff:fe:xx:xx:xx のみがmacaddr8からmacaddrに変換できます。" -#: utils/adt/mcxtfuncs.c:173 +#: utils/adt/mcxtfuncs.c:305 utils/adt/mcxtfuncs.c:391 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %dはPostgreSQLサーバープロセスではありません" +#: utils/adt/mcxtfuncs.c:480 +#, c-format +msgid "PID %d is no longer a PostgreSQL server process" +msgstr "PID %dはすでにPostgreSQLサーバープロセスではありません" + #: utils/adt/misc.c:237 #, c-format msgid "global tablespace never has databases" @@ -25633,7 +26635,7 @@ msgstr "不正なCIDR値: \"%s\"" msgid "Value has bits set to right of mask." msgstr "値ではマスクの右側のビットがセットされています。" -#: utils/adt/network.c:152 utils/adt/network.c:1184 utils/adt/network.c:1209 utils/adt/network.c:1234 +#: utils/adt/network.c:152 utils/adt/network.c:1151 utils/adt/network.c:1176 utils/adt/network.c:1201 #, c-format msgid "could not format inet value: %m" msgstr "inet値を整形できませんでした: %m" @@ -25666,157 +26668,157 @@ msgstr "\"cidr\"の外部値が不正です" msgid "invalid mask length: %d" msgstr "不正なマスク長: %d" -#: utils/adt/network.c:1252 +#: utils/adt/network.c:1219 #, c-format msgid "could not format cidr value: %m" msgstr "cidr値を整形できませんでした: %m" -#: utils/adt/network.c:1485 +#: utils/adt/network.c:1452 #, c-format msgid "cannot merge addresses from different families" msgstr "異なるファミリのアドレスは結合できません" -#: utils/adt/network.c:1893 +#: utils/adt/network.c:1860 #, c-format msgid "cannot AND inet values of different sizes" msgstr "サイズが異なるinet値のANDはできません" -#: utils/adt/network.c:1925 +#: utils/adt/network.c:1892 #, c-format msgid "cannot OR inet values of different sizes" msgstr "サイズが異なるinet値のORはできません" -#: utils/adt/network.c:1986 utils/adt/network.c:2062 +#: utils/adt/network.c:1953 utils/adt/network.c:2029 #, c-format msgid "result is out of range" msgstr "結果が範囲外です" -#: utils/adt/network.c:2027 +#: utils/adt/network.c:1994 #, c-format msgid "cannot subtract inet values of different sizes" msgstr "サイズが異なるinet値の引き算はできません" -#: utils/adt/numeric.c:786 utils/adt/numeric.c:3644 utils/adt/numeric.c:7201 utils/adt/numeric.c:7404 utils/adt/numeric.c:7876 utils/adt/numeric.c:10571 utils/adt/numeric.c:11045 utils/adt/numeric.c:11139 utils/adt/numeric.c:11273 +#: utils/adt/numeric.c:795 utils/adt/numeric.c:3762 utils/adt/numeric.c:7319 utils/adt/numeric.c:7522 utils/adt/numeric.c:7994 utils/adt/numeric.c:10928 utils/adt/numeric.c:11403 utils/adt/numeric.c:11497 utils/adt/numeric.c:11632 #, c-format msgid "value overflows numeric format" msgstr "値がnumericの形式でオーバフローします" -#: utils/adt/numeric.c:1099 +#: utils/adt/numeric.c:1108 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "外部\"numeric\"の値の符号が不正です" -#: utils/adt/numeric.c:1105 +#: utils/adt/numeric.c:1114 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "外部\"numeric\"の値の位取りが不正です" -#: utils/adt/numeric.c:1114 +#: utils/adt/numeric.c:1123 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "外部\"numeric\"の値の桁が不正です" -#: utils/adt/numeric.c:1329 utils/adt/numeric.c:1343 +#: utils/adt/numeric.c:1338 utils/adt/numeric.c:1352 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "NUMERICの精度%dは1から%dまででなければなりません" -#: utils/adt/numeric.c:1334 +#: utils/adt/numeric.c:1343 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "NUMERICの位取り%dは%dから%dまでの間でなければなりません" -#: utils/adt/numeric.c:1352 +#: utils/adt/numeric.c:1361 #, c-format msgid "invalid NUMERIC type modifier" msgstr "不正なNUMERIC型の修正子" -#: utils/adt/numeric.c:1710 +#: utils/adt/numeric.c:1727 #, c-format msgid "start value cannot be NaN" msgstr "開始値はNaNにはできません" -#: utils/adt/numeric.c:1714 +#: utils/adt/numeric.c:1731 #, c-format msgid "start value cannot be infinity" msgstr "開始値は無限大にはできません" -#: utils/adt/numeric.c:1721 +#: utils/adt/numeric.c:1738 #, c-format msgid "stop value cannot be NaN" msgstr "終了値はNaNにはできません" -#: utils/adt/numeric.c:1725 +#: utils/adt/numeric.c:1742 #, c-format msgid "stop value cannot be infinity" msgstr "終了値は無限大にはできません" -#: utils/adt/numeric.c:1738 +#: utils/adt/numeric.c:1755 #, c-format msgid "step size cannot be NaN" msgstr "加算量はNaNにはできません" -#: utils/adt/numeric.c:1742 +#: utils/adt/numeric.c:1759 #, c-format msgid "step size cannot be infinity" msgstr "加算量は無限大にはできません" -#: utils/adt/numeric.c:3634 +#: utils/adt/numeric.c:3752 #, c-format msgid "factorial of a negative number is undefined" msgstr "負数の階乗は定義されていません" -#: utils/adt/numeric.c:4241 +#: utils/adt/numeric.c:4359 #, c-format msgid "lower bound cannot be NaN" msgstr "下限をNaNにすることはできません" -#: utils/adt/numeric.c:4245 +#: utils/adt/numeric.c:4363 #, c-format msgid "lower bound cannot be infinity" msgstr "下限を無限値にすることはできません" -#: utils/adt/numeric.c:4252 +#: utils/adt/numeric.c:4370 #, c-format msgid "upper bound cannot be NaN" msgstr "上限をNaNにすることはできません" -#: utils/adt/numeric.c:4256 +#: utils/adt/numeric.c:4374 #, c-format msgid "upper bound cannot be infinity" msgstr "上限を無限値にすることはできません" -#: utils/adt/numeric.c:4417 utils/adt/numeric.c:4505 utils/adt/numeric.c:4565 utils/adt/numeric.c:4761 +#: utils/adt/numeric.c:4535 utils/adt/numeric.c:4623 utils/adt/numeric.c:4683 utils/adt/numeric.c:4879 #, c-format msgid "cannot convert NaN to %s" msgstr "NaNを%sには変換できません" -#: utils/adt/numeric.c:4421 utils/adt/numeric.c:4509 utils/adt/numeric.c:4569 utils/adt/numeric.c:4765 +#: utils/adt/numeric.c:4539 utils/adt/numeric.c:4627 utils/adt/numeric.c:4687 utils/adt/numeric.c:4883 #, c-format msgid "cannot convert infinity to %s" msgstr "無限大を%sに変換できません" -#: utils/adt/numeric.c:4774 +#: utils/adt/numeric.c:4892 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsnの範囲外です" -#: utils/adt/numeric.c:7966 utils/adt/numeric.c:8017 +#: utils/adt/numeric.c:8084 utils/adt/numeric.c:8135 #, c-format msgid "numeric field overflow" msgstr "numericフィールドのオーバーフロー" -#: utils/adt/numeric.c:7967 +#: utils/adt/numeric.c:8085 #, c-format msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d." msgstr "精度%d、位取り%dを持つフィールドは、%s%dより小さな絶対値に丸められます。" -#: utils/adt/numeric.c:8018 +#: utils/adt/numeric.c:8136 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "精度%d、位取り%dを持つフィールドは、無限大値を格納できません。" -#: utils/adt/numeric.c:11342 utils/adt/pseudorandomfuncs.c:135 utils/adt/pseudorandomfuncs.c:159 +#: utils/adt/numeric.c:11701 utils/adt/pseudorandomfuncs.c:135 utils/adt/pseudorandomfuncs.c:159 #, c-format msgid "lower bound must be less than or equal to upper bound" msgstr "下限は上限と同じあるいはより小さい必要があります" @@ -25826,27 +26828,27 @@ msgstr "下限は上限と同じあるいはより小さい必要があります msgid "invalid oidvector data" msgstr "不正なoidvectorデータ" -#: utils/adt/oracle_compat.c:976 +#: utils/adt/oracle_compat.c:992 #, c-format msgid "requested character too large" msgstr "要求された文字が大きすぎます" -#: utils/adt/oracle_compat.c:1020 +#: utils/adt/oracle_compat.c:1036 #, c-format msgid "character number must be positive" msgstr "文字番号は正数でなければなりません" -#: utils/adt/oracle_compat.c:1024 +#: utils/adt/oracle_compat.c:1040 #, c-format msgid "null character not permitted" msgstr "NULL文字は許可されません" -#: utils/adt/oracle_compat.c:1042 utils/adt/oracle_compat.c:1095 +#: utils/adt/oracle_compat.c:1058 utils/adt/oracle_compat.c:1111 #, c-format msgid "requested character too large for encoding: %u" msgstr "要求された文字は符号化するには大きすぎます: %u" -#: utils/adt/oracle_compat.c:1083 +#: utils/adt/oracle_compat.c:1099 #, c-format msgid "requested character not valid for encoding: %u" msgstr "要求された文字は符号化方式に対して不正です: %u" @@ -25856,137 +26858,147 @@ msgstr "要求された文字は符号化方式に対して不正です: %u" msgid "percentile value %g is not between 0 and 1" msgstr "百分位数の値%gが0と1の間ではありません" -#: utils/adt/pg_locale.c:1484 -#, c-format -msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" -msgstr "ルール\"%2$s\"を持つロケール\"%1$s\"の照合器をオープンできませんでした: %3$s" - -#: utils/adt/pg_locale.c:1495 utils/adt/pg_locale.c:2969 utils/adt/pg_locale.c:3042 -#, c-format -msgid "ICU is not supported in this build" -msgstr "このビルドではICUはサポートされていません" - -#: utils/adt/pg_locale.c:1523 -#, c-format -msgid "could not create locale \"%s\": %m" -msgstr "ロケール\"%s\"を作成できませんでした: %m" - -#: utils/adt/pg_locale.c:1526 -#, c-format -msgid "The operating system could not find any locale data for the locale name \"%s\"." -msgstr "オペレーティングシステムはロケール名\"%s\"のロケールデータを見つけられませんでした。" - -#: utils/adt/pg_locale.c:1647 +#: utils/adt/pg_locale.c:303 utils/adt/pg_locale.c:335 #, c-format -msgid "collations with different collate and ctype values are not supported on this platform" -msgstr "このプラットフォームでは値が異なるcollateとctypeによる照合順序をサポートしていません" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "ロケール名\"%s\"は不正な非ASCII文字を含んでいます" -#: utils/adt/pg_locale.c:1694 +#: utils/adt/pg_locale.c:1119 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "照合順序\"%s\"には実際のバージョンがありませんが、バージョンが記録されています" -#: utils/adt/pg_locale.c:1700 +#: utils/adt/pg_locale.c:1125 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "照合順序\"%s\"でバージョンの不一致が起きています" -#: utils/adt/pg_locale.c:1702 +#: utils/adt/pg_locale.c:1127 #, c-format msgid "The collation in the database was created using version %s, but the operating system provides version %s." msgstr "データベース中の照合順序はバージョン%sで作成されていますが、オペレーティングシステムはバージョン%sを提供しています。" -#: utils/adt/pg_locale.c:1705 +#: utils/adt/pg_locale.c:1130 #, c-format msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." msgstr "この照合順序の影響を受ける全てのオブジェクトを再構築して、ALTER COLLATION %s REFRESH VERSIONを実行するか、正しいバージョンのライブラリを用いてPostgreSQLをビルドしてください。" -#: utils/adt/pg_locale.c:1749 utils/adt/pg_locale.c:2533 utils/adt/pg_locale.c:2558 +#: utils/adt/pg_locale.c:1481 utils/adt/pg_locale.c:1508 utils/adt/pg_locale_builtin.c:186 #, c-format msgid "invalid locale name \"%s\" for builtin provider" msgstr "ロケール名\"%s\"は組み込みプロバイダでは不正です" -#: utils/adt/pg_locale.c:1791 +#: utils/adt/pg_locale.c:1573 #, c-format -msgid "could not load locale \"%s\"" -msgstr "ロケール\"%s\"をロードできませんでした" +msgid "could not convert locale name \"%s\" to language tag: %s" +msgstr "ロケール名\"%s\"を、言語タグに変換できませんでした: %s" -#: utils/adt/pg_locale.c:1816 +#: utils/adt/pg_locale.c:1582 utils/adt/pg_locale.c:1657 utils/adt/pg_locale_icu.c:221 #, c-format -msgid "could not get collation version for locale \"%s\": error code %lu" -msgstr "ロケール\"%s\"に対応する照合順序バージョンを取得できませんでした: エラーコード %lu" +msgid "ICU is not supported in this build" +msgstr "このビルドではICUはサポートされていません" -#: utils/adt/pg_locale.c:1872 utils/adt/pg_locale.c:1885 +#: utils/adt/pg_locale.c:1615 #, c-format -msgid "could not convert string to UTF-16: error code %lu" -msgstr "文字列をUTF-16に変換できませんでした: エラーコード %lu" +msgid "could not get language from ICU locale \"%s\": %s" +msgstr "ICUロケール\"%s\"から言語を取得できませんでした: %s" -#: utils/adt/pg_locale.c:1897 +#: utils/adt/pg_locale.c:1617 utils/adt/pg_locale.c:1647 #, c-format -msgid "could not compare Unicode strings: %m" -msgstr "Unicode文字列を比較できませんでした: %m" +msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." +msgstr "ICUロケールを無効にするには、パラメータ\"%s\"を\"%s\"に設定してください。" + +#: utils/adt/pg_locale.c:1645 +#, c-format +msgid "ICU locale \"%s\" has unknown language \"%s\"" +msgstr "ICUロケール\"%s\"には未知の言語\"%s\"が含まれています" + +#: utils/adt/pg_locale_icu.c:270 +#, c-format +msgid "could not get language from locale \"%s\": %s" +msgstr "ロケール\"%s\"から言語を取得できませんでした: %s" + +#: utils/adt/pg_locale_icu.c:292 utils/adt/pg_locale_icu.c:309 +#, c-format +msgid "could not open collator for locale \"%s\": %s" +msgstr "ロケール\"%s\"の照合器をオープンできませんでした: %s" -#: utils/adt/pg_locale.c:2071 +#: utils/adt/pg_locale_icu.c:380 +#, c-format +msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" +msgstr "ルール\"%2$s\"を持つロケール\"%1$s\"の照合器をオープンできませんでした: %3$s" + +#: utils/adt/pg_locale_icu.c:494 #, c-format msgid "collation failed: %s" msgstr "照合順序による比較に失敗しました: %s" -#: utils/adt/pg_locale.c:2290 utils/adt/pg_locale.c:2322 +#: utils/adt/pg_locale_icu.c:573 utils/adt/pg_locale_icu.c:837 #, c-format msgid "sort key generation failed: %s" msgstr "ソートキーの生成に失敗しました: %s" -#: utils/adt/pg_locale.c:2612 +#: utils/adt/pg_locale_icu.c:647 utils/adt/pg_locale_icu.c:659 utils/adt/pg_locale_icu.c:884 utils/adt/pg_locale_icu.c:905 #, c-format -msgid "could not get language from locale \"%s\": %s" -msgstr "ロケール\"%s\"から言語を取得できませんでした: %s" +msgid "%s failed: %s" +msgstr "%s が失敗しました: %s" -#: utils/adt/pg_locale.c:2633 utils/adt/pg_locale.c:2649 +#: utils/adt/pg_locale_icu.c:688 #, c-format -msgid "could not open collator for locale \"%s\": %s" -msgstr "ロケール\"%s\"の照合器をオープンできませんでした: %s" +msgid "case conversion failed: %s" +msgstr "文字ケースの変換に失敗しました: %s" -#: utils/adt/pg_locale.c:2674 +#: utils/adt/pg_locale_icu.c:857 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "エンコーディング\"%s\"はICUではサポートされていません" -#: utils/adt/pg_locale.c:2681 +#: utils/adt/pg_locale_icu.c:864 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "エンコーディング\"%s\"のICU変換器をオープンできませんでした: %s" -#: utils/adt/pg_locale.c:2699 utils/adt/pg_locale.c:2718 utils/adt/pg_locale.c:2774 utils/adt/pg_locale.c:2785 +#: utils/adt/pg_locale_libc.c:553 #, c-format -msgid "%s failed: %s" -msgstr "%s が失敗しました: %s" +msgid "collations with different collate and ctype values are not supported on this platform" +msgstr "このプラットフォームでは値が異なるcollateとctypeによる照合順序をサポートしていません" -#: utils/adt/pg_locale.c:2960 +#: utils/adt/pg_locale_libc.c:683 #, c-format -msgid "could not convert locale name \"%s\" to language tag: %s" -msgstr "ロケール名\"%s\"を、言語タグに変換できませんでした: %s" +msgid "could not load locale \"%s\"" +msgstr "ロケール\"%s\"をロードできませんでした" -#: utils/adt/pg_locale.c:3001 +#: utils/adt/pg_locale_libc.c:708 #, c-format -msgid "could not get language from ICU locale \"%s\": %s" -msgstr "ICUロケール\"%s\"から言語を取得できませんでした: %s" +msgid "could not get collation version for locale \"%s\": error code %lu" +msgstr "ロケール\"%s\"に対応する照合順序バージョンを取得できませんでした: エラーコード %lu" -#: utils/adt/pg_locale.c:3003 utils/adt/pg_locale.c:3032 +#: utils/adt/pg_locale_libc.c:771 utils/adt/pg_locale_libc.c:784 #, c-format -msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." -msgstr "ICUロケールを無効にするには、パラメータ\"%s\"を\"%s\"に設定してください。" +msgid "could not convert string to UTF-16: error code %lu" +msgstr "文字列をUTF-16に変換できませんでした: エラーコード %lu" -#: utils/adt/pg_locale.c:3030 +#: utils/adt/pg_locale_libc.c:793 #, c-format -msgid "ICU locale \"%s\" has unknown language \"%s\"" -msgstr "ICUロケール\"%s\"には未知の言語\"%s\"が含まれています" +msgid "could not compare Unicode strings: %m" +msgstr "Unicode文字列を比較できませんでした: %m" -#: utils/adt/pg_locale.c:3181 +#: utils/adt/pg_locale_libc.c:825 +#, c-format +msgid "could not create locale \"%s\": %m" +msgstr "ロケール\"%s\"を作成できませんでした: %m" + +#: utils/adt/pg_locale_libc.c:828 +#, c-format +msgid "The operating system could not find any locale data for the locale name \"%s\"." +msgstr "オペレーティングシステムはロケール名\"%s\"のロケールデータを見つけられませんでした。" + +#: utils/adt/pg_locale_libc.c:1000 #, c-format msgid "invalid multibyte character for locale" msgstr "ロケールに対する不正なマルチバイト文字" -#: utils/adt/pg_locale.c:3182 +#: utils/adt/pg_locale_libc.c:1001 #, c-format msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding." msgstr "おそらくサーバーのLC_CTYPEロケールはデータベースの符号化方式と互換性がありません" @@ -26001,27 +27013,27 @@ msgstr "pg_lsnにNaNは加算できません" msgid "cannot subtract NaN from pg_lsn" msgstr "pg_lsnからNaNは減算できません" -#: utils/adt/pg_upgrade_support.c:39 +#: utils/adt/pg_upgrade_support.c:38 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "関数はサーバーがバイナリアップグレードモードであるときのみ呼び出せます" -#: utils/adt/pgstatfuncs.c:252 +#: utils/adt/pgstatfuncs.c:280 #, c-format msgid "invalid command name: \"%s\"" msgstr "不正なコマンド名: \"%s\"" -#: utils/adt/pgstatfuncs.c:1739 +#: utils/adt/pgstatfuncs.c:1909 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "認識できないリセットターゲット: \"%s\"" -#: utils/adt/pgstatfuncs.c:1740 +#: utils/adt/pgstatfuncs.c:1910 #, c-format msgid "Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"." msgstr "対象は\"archiver\"、\"bgwriter\"、\"checkpointer\"、\"io\"、\"recovery_prefetch\"、\"slru\"または\"wal\"でなければなりません。" -#: utils/adt/pgstatfuncs.c:1822 +#: utils/adt/pgstatfuncs.c:2027 #, c-format msgid "invalid subscription OID %u" msgstr "不正なサブスクリプションOID %u" @@ -26046,67 +27058,67 @@ msgstr "シェル型の値は受け付けられません" msgid "cannot display a value of a shell type" msgstr "シェル型の値は表示できません" -#: utils/adt/rangetypes.c:422 +#: utils/adt/rangetypes.c:424 #, c-format msgid "range constructor flags argument must not be null" msgstr "範囲コンストラクタフラグ引数はNULLではいけません" -#: utils/adt/rangetypes.c:1021 +#: utils/adt/rangetypes.c:1023 #, c-format msgid "result of range difference would not be contiguous" msgstr "範囲の差分が連続ではありません" -#: utils/adt/rangetypes.c:1082 +#: utils/adt/rangetypes.c:1084 #, c-format msgid "result of range union would not be contiguous" msgstr "範囲の和が連続ではありません" -#: utils/adt/rangetypes.c:1757 +#: utils/adt/rangetypes.c:1821 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "範囲の下限は範囲の上限以下でなければなりません" -#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 utils/adt/rangetypes.c:2283 +#: utils/adt/rangetypes.c:2320 utils/adt/rangetypes.c:2333 utils/adt/rangetypes.c:2347 #, c-format msgid "invalid range bound flags" msgstr "不正な範囲境界フラグ" -#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 utils/adt/rangetypes.c:2284 +#: utils/adt/rangetypes.c:2321 utils/adt/rangetypes.c:2334 utils/adt/rangetypes.c:2348 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "有効な値は\"[]\"、\"[)\"、\"(]\"、\"()\"です" -#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 utils/adt/rangetypes.c:2470 +#: utils/adt/rangetypes.c:2416 utils/adt/rangetypes.c:2433 utils/adt/rangetypes.c:2448 utils/adt/rangetypes.c:2468 utils/adt/rangetypes.c:2479 utils/adt/rangetypes.c:2526 utils/adt/rangetypes.c:2534 #, c-format msgid "malformed range literal: \"%s\"" msgstr "不正な範囲リテラル: \"%s\"" -#: utils/adt/rangetypes.c:2354 +#: utils/adt/rangetypes.c:2418 #, c-format msgid "Junk after \"empty\" key word." msgstr "\"empty\"キーワードの後にゴミがあります。" -#: utils/adt/rangetypes.c:2371 +#: utils/adt/rangetypes.c:2435 #, c-format msgid "Missing left parenthesis or bracket." msgstr "左括弧または左角括弧がありません" -#: utils/adt/rangetypes.c:2386 +#: utils/adt/rangetypes.c:2450 #, c-format msgid "Missing comma after lower bound." msgstr "下限値の後にカンマがありません" -#: utils/adt/rangetypes.c:2406 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "Too many commas." msgstr "カンマが多すぎます" -#: utils/adt/rangetypes.c:2417 +#: utils/adt/rangetypes.c:2481 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "右括弧または右角括弧の後にごみがあります" -#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4475 #, c-format msgid "regular expression failed: %s" msgstr "正規表現が失敗しました: %s" @@ -26121,7 +27133,7 @@ msgstr "不正な正規表現オプション: \"%.*s\"" msgid "If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly." msgstr "regexp_replace()でパラメータstartを指定したいのであれば、4番目のパラメータを明示的に整数にキャストしてください。" -#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 utils/adt/regexp.c:1871 utils/misc/guc.c:6776 utils/misc/guc.c:6810 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 utils/adt/regexp.c:1871 utils/misc/guc.c:6818 utils/misc/guc.c:6852 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "パラメータ\"%s\"の値が無効です: %d" @@ -26157,7 +27169,7 @@ msgstr "\"%s\"という名前の関数が複数あります" msgid "more than one operator named %s" msgstr "%sという名前の演算子が複数あります" -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10424 utils/adt/ruleutils.c:10637 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10826 utils/adt/ruleutils.c:11039 #, c-format msgid "too many arguments" msgstr "引数が多すぎます" @@ -26167,7 +27179,7 @@ msgstr "引数が多すぎます" msgid "Provide two argument types for operator." msgstr "演算子では2つの引数型を指定してください" -#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 utils/adt/regproc.c:1815 utils/adt/varlena.c:3481 utils/adt/varlena.c:3486 #, c-format msgid "invalid name syntax" msgstr "不正な名前の構文" @@ -26192,77 +27204,92 @@ msgstr "型の名前を想定していました" msgid "improper type name" msgstr "型の名前が不適切です" -#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 utils/adt/ri_triggers.c:2601 +#: utils/adt/ri_triggers.c:314 utils/adt/ri_triggers.c:1775 utils/adt/ri_triggers.c:2774 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "テーブル\"%s\"への挿入、更新は外部キー制約\"%s\"に違反しています" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 +#: utils/adt/ri_triggers.c:317 utils/adt/ri_triggers.c:1778 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MACTH FULLではNULLキー値と非NULLキー値を混在できません" -#: utils/adt/ri_triggers.c:2036 +#: utils/adt/ri_triggers.c:2192 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "関数\"%s\"はINSERTで発火しなければなりません" -#: utils/adt/ri_triggers.c:2042 +#: utils/adt/ri_triggers.c:2198 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "関数\"%s\"はUPDATEで発火しなければなりません" -#: utils/adt/ri_triggers.c:2048 +#: utils/adt/ri_triggers.c:2204 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "関数\"%s\"はDELETEで発火しなければなりません" -#: utils/adt/ri_triggers.c:2071 +#: utils/adt/ri_triggers.c:2227 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "テーブル\"%2$s\"のトリガ\"%1$s\"用のpg_constraint項目がありません" -#: utils/adt/ri_triggers.c:2073 +#: utils/adt/ri_triggers.c:2229 #, c-format msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT." msgstr "この参照整合性トリガとその対象を削除し、ALTER TABLE ADD CONSTRAINTを実行してください" -#: utils/adt/ri_triggers.c:2426 +#: utils/adt/ri_triggers.c:2599 #, c-format msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result" msgstr "\"%3$s\"の制約\"%2$s\"から\"%1$s\"に行われた参照整合性問い合わせが想定外の結果になりました" -#: utils/adt/ri_triggers.c:2430 +#: utils/adt/ri_triggers.c:2603 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "これは概ねこの問い合わせを書き換えるルールが原因です" -#: utils/adt/ri_triggers.c:2591 +#: utils/adt/ri_triggers.c:2764 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "子テーブル \"%s\"の削除は外部キー制約\"%s\"違反となります" -#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 +#: utils/adt/ri_triggers.c:2767 utils/adt/ri_triggers.c:2806 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "キー(%s)=(%s)はまだテーブル\"%s\"から参照されています" -#: utils/adt/ri_triggers.c:2605 +#: utils/adt/ri_triggers.c:2778 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "テーブル\"%3$s\"にキー(%1$s)=(%2$s)がありません" -#: utils/adt/ri_triggers.c:2608 +#: utils/adt/ri_triggers.c:2781 #, c-format msgid "Key is not present in table \"%s\"." msgstr "テーブル\"%s\"にキーがありません。" -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2787 +#, c-format +msgid "update or delete on table \"%s\" violates RESTRICT setting of foreign key constraint \"%s\" on table \"%s\"" +msgstr "テーブル\"%1$s\"の更新または削除は、テーブル\"%3$s\"の外部キー制約\"%2$s\"のRESTRICT設定に違反しています" + +#: utils/adt/ri_triggers.c:2792 +#, c-format +msgid "Key (%s)=(%s) is referenced from table \"%s\"." +msgstr "キー(%s)=(%s)はテーブル\"%s\"から参照されています。" + +#: utils/adt/ri_triggers.c:2795 +#, c-format +msgid "Key is referenced from table \"%s\"." +msgstr "キーがテーブル\"%s\"から参照されています。" + +#: utils/adt/ri_triggers.c:2801 #, c-format msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"" msgstr "テーブル\"%1$s\"の更新または削除は、テーブル\"%3$s\"の外部キー制約\"%2$s\"に違反します" -#: utils/adt/ri_triggers.c:2622 +#: utils/adt/ri_triggers.c:2809 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "テーブル\"%s\"からキーがまだ参照されています。" @@ -26312,133 +27339,158 @@ msgstr "バイナリデータのレコードカラム%5$dで予期していた%3 msgid "improper binary format in record column %d" msgstr "レコード列%dのバイナリ書式が不適切です" -#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 utils/adt/rowtypes.c:1699 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1471 utils/adt/rowtypes.c:1717 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "レコードの列 %3$d において、全く異なる型 %1$s と %2$s では比較ができません" -#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 utils/adt/rowtypes.c:1568 utils/adt/rowtypes.c:1753 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "個数が異なる列同士ではレコード型の比較ができません" -#: utils/adt/ruleutils.c:2693 +#: utils/adt/ruleutils.c:2740 #, c-format msgid "input is a query, not an expression" msgstr "入力が式ではなく文です" -#: utils/adt/ruleutils.c:2705 +#: utils/adt/ruleutils.c:2752 #, c-format msgid "expression contains variables of more than one relation" msgstr "式が2つ以上のリレーションの変数を含んでいます" -#: utils/adt/ruleutils.c:2712 +#: utils/adt/ruleutils.c:2759 #, c-format msgid "expression contains variables" msgstr "式が変数を含んでいます" -#: utils/adt/ruleutils.c:5242 +#: utils/adt/ruleutils.c:5433 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "ルール\"%s\"はサポートしていないイベントタイプ%dを持ちます" -#: utils/adt/timestamp.c:128 +#: utils/adt/tid.c:317 +#, c-format +msgid "cannot look at latest visible tid for relation \"%s.%s\"" +msgstr "リレーション\"%s.%s\"の最新の可視TIDを参照できません" + +#: utils/adt/tid.c:356 +#, c-format +msgid "ctid isn't of type TID" +msgstr "ctidはTID型ではありません" + +#: utils/adt/tid.c:364 +#, c-format +msgid "currtid cannot handle views with no CTID" +msgstr "currtidはCTIDを持たないビューは扱えません" + +#: utils/adt/tid.c:369 +#, c-format +msgid "the view has no rules" +msgstr "このビューにはルールが設定されていません" + +#: utils/adt/tid.c:381 +#, c-format +msgid "only one select rule is allowed in views" +msgstr "ビューではSELECTルールは一つしか設定できません" + +#: utils/adt/timestamp.c:130 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "TIMESTAMP(%d)%s の精度は負であってはなりません" -#: utils/adt/timestamp.c:134 +#: utils/adt/timestamp.c:136 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "TIMESTAMP(%d)%sの位取りを許容最大値%dまで減らしました" -#: utils/adt/timestamp.c:394 +#: utils/adt/timestamp.c:204 utils/adt/timestamp.c:457 +#, c-format +msgid "timestamp out of range: \"%s\"" +msgstr "timestampが範囲外です: \"%s\"" + +#: utils/adt/timestamp.c:396 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "timestamp(%d)の精度は%dから%dまででなければなりません" -#: utils/adt/timestamp.c:512 +#: utils/adt/timestamp.c:514 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "数字タイムゾーンは先頭の文字が\"-\"または\"+\"でなければなりません。" -#: utils/adt/timestamp.c:524 +#: utils/adt/timestamp.c:526 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "数値タイムゾーン\"%s\"が範囲外です" -#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 utils/adt/timestamp.c:643 +#: utils/adt/timestamp.c:626 utils/adt/timestamp.c:634 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "timestampが範囲外です: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:744 +#: utils/adt/timestamp.c:735 #, c-format msgid "timestamp cannot be NaN" msgstr "タイムスタンプは NaN にはできません" -#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 +#: utils/adt/timestamp.c:753 utils/adt/timestamp.c:765 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "timestampが範囲外です: \"%g\"" -#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 utils/adt/timestamp.c:3537 -#: utils/adt/timestamp.c:3546 utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 utils/adt/timestamp.c:5097 +#: utils/adt/timestamp.c:948 utils/adt/timestamp.c:1507 utils/adt/timestamp.c:1517 utils/adt/timestamp.c:1578 utils/adt/timestamp.c:2866 utils/adt/timestamp.c:2875 utils/adt/timestamp.c:2890 utils/adt/timestamp.c:2964 utils/adt/timestamp.c:2981 utils/adt/timestamp.c:3038 utils/adt/timestamp.c:3081 utils/adt/timestamp.c:3459 utils/adt/timestamp.c:3517 utils/adt/timestamp.c:3540 utils/adt/timestamp.c:3549 utils/adt/timestamp.c:3573 utils/adt/timestamp.c:3596 +#: utils/adt/timestamp.c:3605 utils/adt/timestamp.c:3740 utils/adt/timestamp.c:3841 utils/adt/timestamp.c:4248 utils/adt/timestamp.c:4285 utils/adt/timestamp.c:4333 utils/adt/timestamp.c:4342 utils/adt/timestamp.c:4434 utils/adt/timestamp.c:4481 utils/adt/timestamp.c:4490 utils/adt/timestamp.c:4586 utils/adt/timestamp.c:4639 utils/adt/timestamp.c:4649 utils/adt/timestamp.c:4874 utils/adt/timestamp.c:4884 utils/adt/timestamp.c:5239 #, c-format msgid "interval out of range" msgstr "intervalが範囲外です" -#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 +#: utils/adt/timestamp.c:1085 utils/adt/timestamp.c:1118 #, c-format msgid "invalid INTERVAL type modifier" msgstr "不正なINTERVAL型の修正子です" -#: utils/adt/timestamp.c:1110 +#: utils/adt/timestamp.c:1101 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d)の精度は負ではいけません" -#: utils/adt/timestamp.c:1116 +#: utils/adt/timestamp.c:1107 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "INTERVAL(%d)の精度を許容最大値%dまで減らしました" -#: utils/adt/timestamp.c:1506 +#: utils/adt/timestamp.c:1497 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "interval(%d)の精度は%dから%dまででなければなりません" -#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 -#, c-format -msgid "interval out of range." -msgstr "intervalが範囲外です" - -#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 +#: utils/adt/timestamp.c:4623 utils/adt/timestamp.c:4858 #, c-format msgid "origin out of range" msgstr "基点が範囲外です" -#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#: utils/adt/timestamp.c:4628 utils/adt/timestamp.c:4863 #, c-format msgid "timestamps cannot be binned into infinite intervals" msgstr "タイムスタンプは無限のintervalにビニングすることはできません" -#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 +#: utils/adt/timestamp.c:4633 utils/adt/timestamp.c:4868 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "タイムスタンプ型は月や年を含む間隔にビニングすることはできません" -#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 +#: utils/adt/timestamp.c:4644 utils/adt/timestamp.c:4879 #, c-format msgid "stride must be greater than zero" msgstr "増分は0より大きくなければなりません" -#: utils/adt/timestamp.c:5091 +#: utils/adt/timestamp.c:5181 utils/adt/timestamp.c:5233 #, c-format msgid "Months usually have fractional weeks." msgstr "月は通常週の端数を含んでいます。" -#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#: utils/adt/timestamp.c:6713 utils/adt/timestamp.c:6799 #, c-format msgid "step size cannot be infinite" msgstr "加算量は無限にはできません" @@ -26473,32 +27525,32 @@ msgstr "フレーズ演算子での距離は0以上%d以下の整数でなくて msgid "no operand in tsquery: \"%s\"" msgstr "tsquery内にオペランドがありません\"%s\"" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "tsquery内の値が大きすぎます: \"%s\"" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "tsqueryのオペランドが長過ぎます: \"%s\"" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "tsquery内の単語が長すぎます: \"%s\"" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "tsquery内の構文エラー: \"%s\"" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "テキスト検索問い合わせが字句要素を含みません: \"%s\"" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "tsqueryが大きすぎます" @@ -26513,32 +27565,32 @@ msgstr "テキスト検索問い合わせはストップワードのみを含む msgid "ts_rewrite query must return two tsquery columns" msgstr "ts_rewrite問い合わせは2列のtsquery列を返さなければなりません" -#: utils/adt/tsrank.c:412 +#: utils/adt/tsrank.c:415 #, c-format msgid "array of weight must be one-dimensional" msgstr "重み配列は1次元の配列でなければなりません" -#: utils/adt/tsrank.c:417 +#: utils/adt/tsrank.c:420 #, c-format msgid "array of weight is too short" msgstr "重み配列が短すぎます" -#: utils/adt/tsrank.c:422 +#: utils/adt/tsrank.c:425 #, c-format msgid "array of weight must not contain nulls" msgstr "重み配列にはNULL値を含めてはいけません" -#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:871 +#: utils/adt/tsrank.c:434 utils/adt/tsrank.c:876 #, c-format msgid "weight out of range" msgstr "重みが範囲外です" -#: utils/adt/tsvector.c:216 +#: utils/adt/tsvector.c:213 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "単語が長すぎます(%ldバイト、最大は%ldバイト)" -#: utils/adt/tsvector.c:223 +#: utils/adt/tsvector.c:220 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "tsベクターのための文字列が長すぎます(%ldバイト、最大は%ldバイト)" @@ -26618,7 +27670,7 @@ msgstr "エスケープ文字がありません: \"%s\"" msgid "wrong position info in tsvector: \"%s\"" msgstr "tsvector内の位置情報が間違っています: \"%s\"" -#: utils/adt/uuid.c:418 +#: utils/adt/uuid.c:535 utils/adt/uuid.c:632 #, c-format msgid "could not generate random values" msgstr "乱数値を生成できませんでした" @@ -26663,7 +27715,7 @@ msgstr "ビット列の外部値の不正な長さ" msgid "bit string too long for type bit varying(%d)" msgstr "ビット列は型bit varying(%d)には長すぎます" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 utils/adt/varlena.c:3133 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:919 utils/adt/varlena.c:982 utils/adt/varlena.c:1139 utils/adt/varlena.c:3102 utils/adt/varlena.c:3180 #, c-format msgid "negative substring length not allowed" msgstr "負の長さのsubstringは許可されません" @@ -26688,7 +27740,7 @@ msgstr "サイズが異なるビット列のXORはできません" msgid "bit index %d out of valid range (0..%d)" msgstr "ビットのインデックス%dが有効範囲0..%dの間にありません" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3384 #, c-format msgid "new bit must be 0 or 1" msgstr "新しいビットは0か1でなければなりません" @@ -26703,92 +27755,92 @@ msgstr "値は型character(%d)としては長すぎます" msgid "value too long for type character varying(%d)" msgstr "値は型character varying(%d)としては長すぎます" -#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1591 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "文字列比較で使用する照合順序を特定できませんでした" -#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 +#: utils/adt/varlena.c:1864 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "非決定的照合順序は部分文字列探索ではサポートされません" -#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 +#: utils/adt/varlena.c:3268 utils/adt/varlena.c:3335 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "インデックス%dは有効範囲0..%dの間にありません" -#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 +#: utils/adt/varlena.c:3299 utils/adt/varlena.c:3371 #, c-format -msgid "index %lld out of valid range, 0..%lld" -msgstr "インデックス%lldは有効範囲0..%lldの間にありません" +msgid "index % out of valid range, 0..%" +msgstr "インデックス%は有効範囲0..%の間にありません" -#: utils/adt/varlena.c:4385 +#: utils/adt/varlena.c:4587 #, c-format msgid "field position must not be zero" msgstr "フィールド位置には0は指定できません" -#: utils/adt/varlena.c:5630 +#: utils/adt/varlena.c:5832 #, c-format msgid "unterminated format() type specifier" msgstr "終端されていないformat()型指定子" -#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 +#: utils/adt/varlena.c:5833 utils/adt/varlena.c:5967 utils/adt/varlena.c:6088 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "一つの\"%%\"には\"%%%%\"を使ってください。" -#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 +#: utils/adt/varlena.c:5965 utils/adt/varlena.c:6086 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "認識できない format() の型指定子\"%.*s\"" -#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 +#: utils/adt/varlena.c:5978 utils/adt/varlena.c:6035 #, c-format msgid "too few arguments for format()" msgstr "format()の引数が少なすぎます" -#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 +#: utils/adt/varlena.c:6131 utils/adt/varlena.c:6313 #, c-format msgid "number is out of range" msgstr "数値が範囲外です" -#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 +#: utils/adt/varlena.c:6194 utils/adt/varlena.c:6222 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "書式は引数0を指定していますが、引数が1から始まっています" -#: utils/adt/varlena.c:6013 +#: utils/adt/varlena.c:6215 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "width引数の位置は\"$\"で終わらなければなりません" -#: utils/adt/varlena.c:6058 +#: utils/adt/varlena.c:6260 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "NULLはSQL識別子として書式付けできません" -#: utils/adt/varlena.c:6266 +#: utils/adt/varlena.c:6468 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "Unicode正規化はサーバーエンコーディングがUTF-8の場合にのみ実行されます" -#: utils/adt/varlena.c:6279 +#: utils/adt/varlena.c:6481 #, c-format msgid "invalid normalization form: %s" msgstr "不正な正規化形式: %s" -#: utils/adt/varlena.c:6324 +#: utils/adt/varlena.c:6526 #, c-format msgid "Unicode categorization can only be performed if server encoding is UTF8" msgstr "Unicodeカテゴリー分類はサーバーエンコーディングがUTF-8の場合にのみ実行可能です" -#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 +#: utils/adt/varlena.c:6743 utils/adt/varlena.c:6778 utils/adt/varlena.c:6813 #, c-format msgid "invalid Unicode code point: %04X" msgstr "不正なUnicodeコードポイント: %04X" -#: utils/adt/varlena.c:6641 +#: utils/adt/varlena.c:6843 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "Unicodeエスケープは \\XXXX、\\+XXXXXX、\\uXXXX または \\UXXXXXXXX でなければなりません。" @@ -26803,12 +27855,12 @@ msgstr "ntileの値は0より大きくなければなりません" msgid "argument of nth_value must be greater than zero" msgstr "nth_valueの値0より大きくなければなりません" -#: utils/adt/xid8funcs.c:124 +#: utils/adt/xid8funcs.c:120 #, c-format -msgid "transaction ID %llu is in the future" -msgstr "トランザクションID %lluは未来の値です" +msgid "transaction ID % is in the future" +msgstr "トランザクションID %は未来の値です" -#: utils/adt/xid8funcs.c:553 +#: utils/adt/xid8funcs.c:522 #, c-format msgid "invalid external pg_snapshot data" msgstr "不正な外部pg_snapshotデータ" @@ -26833,161 +27885,166 @@ msgstr "不正な符号化方式名\"%s\"" msgid "invalid XML comment" msgstr "無効なXMLコメント" -#: utils/adt/xml.c:691 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "XML文書ではありません" -#: utils/adt/xml.c:987 utils/adt/xml.c:1010 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "無効なXML処理命令です" -#: utils/adt/xml.c:988 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "XML処理命令の対象名を\"%s\"とすることができませんでした。" -#: utils/adt/xml.c:1011 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "XML処理命令には\"?>\"を含めることはできません。" -#: utils/adt/xml.c:1090 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "XML の妥当性検査は実装されていません" -#: utils/adt/xml.c:1146 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "XMLライブラリを初期化できませんでした" -#: utils/adt/xml.c:1147 +#: utils/adt/xml.c:1168 #, c-format msgid "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." msgstr "libxml2が互換性がない文字型を持ちます: sizeof(char)=%zu、sizeof(xmlChar)=%zu" -#: utils/adt/xml.c:1233 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "XMLエラーハンドラを設定できませんでした" -#: utils/adt/xml.c:1234 +#: utils/adt/xml.c:1255 #, c-format msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with." msgstr "これはおそらく使用するlibxml2のバージョンがPostgreSQLを構築する時に使用したlibxml2ヘッダと互換性がないことを示します。" -#: utils/adt/xml.c:2218 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "文字の値が有効ではありません" -#: utils/adt/xml.c:2221 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "スペースをあけてください。" -#: utils/adt/xml.c:2224 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "standalone には 'yes' か 'no' だけが有効です。" -#: utils/adt/xml.c:2227 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "不正な形式の宣言: バージョンがありません。" -#: utils/adt/xml.c:2230 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "テキスト宣言にエンコーディングの指定がありません。" -#: utils/adt/xml.c:2233 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "XML 宣言のパース中: '>?' が必要です。" -#: utils/adt/xml.c:2236 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "認識できないlibxml のエラーコード: %d" -#: utils/adt/xml.c:2490 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XMLはデータ値として無限をサポートしません。" -#: utils/adt/xml.c:2512 utils/adt/xml.c:2539 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XMLタイムスタンプ値としては無限をサポートしません。" -#: utils/adt/xml.c:2955 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "不正な無効な問い合わせ" -#: utils/adt/xml.c:3047 +#: utils/adt/xml.c:3110 #, c-format msgid "portal \"%s\" does not return tuples" msgstr "ポータル\"%s\"はタプルを返却しません" -#: utils/adt/xml.c:4299 +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "XML名前空間マッピングに対する不正な配列" -#: utils/adt/xml.c:4300 +#: utils/adt/xml.c:4363 #, c-format msgid "The array must be two-dimensional with length of the second axis equal to 2." msgstr "この配列は第2軸の長さが2である2次元配列でなければなりません。" -#: utils/adt/xml.c:4324 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "空のXPath式" -#: utils/adt/xml.c:4376 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "名前空間名もURIもnullにはできません" -#: utils/adt/xml.c:4383 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "\"%s\"という名前のXML名前空間およびURI\"%s\"を登録できませんでした" -#: utils/adt/xml.c:4726 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "デフォルト名前空間は実装されていません" -#: utils/adt/xml.c:4755 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "行パスフィルタは空文字列であってはなりません" -#: utils/adt/xml.c:4786 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "列パスフィルタ空文字列であってはなりません" -#: utils/adt/xml.c:4930 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "列XPath式が2つ以上の値を返却しました" -#: utils/cache/lsyscache.c:1017 +#: utils/cache/funccache.c:364 #, c-format -msgid "cast from type %s to type %s does not exist" +msgid "could not determine actual argument type for polymorphic function \"%s\"" +msgstr "多相関数\"%s\"の実際の引数の型を特定できませんでした" + +#: utils/cache/lsyscache.c:1109 +#, c-format +msgid "cast from type %s to type %s does not exist" msgstr "型%sから型%sへのキャストは存在しません" -#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 +#: utils/cache/lsyscache.c:3027 utils/cache/lsyscache.c:3060 utils/cache/lsyscache.c:3093 utils/cache/lsyscache.c:3126 #, c-format msgid "type %s is only a shell" msgstr "型%sは単なるシェルです" -#: utils/cache/lsyscache.c:2892 +#: utils/cache/lsyscache.c:3032 #, c-format msgid "no input function available for type %s" msgstr "型%sの利用可能な入力関数がありません" -#: utils/cache/lsyscache.c:2925 +#: utils/cache/lsyscache.c:3065 #, c-format msgid "no output function available for type %s" msgstr "型%sの利用可能な出力関数がありません" @@ -26997,32 +28054,27 @@ msgstr "型%sの利用可能な出力関数がありません" msgid "operator class \"%s\" of access method %s is missing support function %d for type %s" msgstr "アクセスメソッド %2$s の演算子クラス\"%1$s\"は%4$s型に対応するサポート関数%3$dを含んでいません" -#: utils/cache/plancache.c:747 -#, c-format -msgid "cached plan must not change result type" -msgstr "キャッシュした実行計画は結果型を変更してはなりません" - -#: utils/cache/relcache.c:3797 +#: utils/cache/relcache.c:3791 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "バイナリアップグレードモード中にヒープのrelfilenumberの値が設定されていません" -#: utils/cache/relcache.c:3805 +#: utils/cache/relcache.c:3799 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "バイナリアップグレードモード中に、予期しない新規relfilenumberの要求がありました" -#: utils/cache/relcache.c:6533 +#: utils/cache/relcache.c:6616 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "リレーションキャッシュ初期化ファイル\"%sを作成できません: %m" -#: utils/cache/relcache.c:6535 +#: utils/cache/relcache.c:6618 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "とりあえず続行しますが、何かがおかしいです。" -#: utils/cache/relcache.c:6865 +#: utils/cache/relcache.c:6948 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "キャッシュファイル\"%s\"を削除できませんでした: %m" @@ -27042,7 +28094,7 @@ msgstr "リレーションマッピングファイル\"%s\"に不正なデータ msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "リレーションマッピングファイル\"%s\"の中に不正なチェックサムがあります" -#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 +#: utils/cache/typcache.c:1901 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "レコード型は登録されていません" @@ -27057,193 +28109,185 @@ msgstr "TRAP: 例外条件: PID %dで不正な引数\n" msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "TRAP: Assert(\"%s\")が失敗、ファイル: \"%s\"、行: %d、PID: %d)\n" -#: utils/error/elog.c:415 +#: utils/error/elog.c:412 #, c-format msgid "error occurred before error message processing is available\n" msgstr "エラーメッセージの処理が可能になる前にエラーが発生しました\n" -#: utils/error/elog.c:2101 +#: utils/error/elog.c:2159 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "ファイル\"%s\"の標準エラー出力としての再オープンに失敗しました: %m" -#: utils/error/elog.c:2114 +#: utils/error/elog.c:2172 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "ファイル\"%s\"の標準出力としての再オープンに失敗しました: %m" -#: utils/error/elog.c:2150 +#: utils/error/elog.c:2208 #, c-format -msgid "Invalid character" -msgstr "不正な文字" +msgid "Invalid character." +msgstr "不正な文字。" -#: utils/error/elog.c:2856 utils/error/elog.c:2883 utils/error/elog.c:2899 +#: utils/error/elog.c:2918 utils/error/elog.c:2945 utils/error/elog.c:2961 msgid "[unknown]" msgstr "[不明]" -#: utils/error/elog.c:3169 utils/error/elog.c:3493 utils/error/elog.c:3600 +#: utils/error/elog.c:3263 utils/error/elog.c:3587 utils/error/elog.c:3694 msgid "missing error text" msgstr "エラーテキストがありません" -#: utils/error/elog.c:3172 utils/error/elog.c:3175 +#: utils/error/elog.c:3266 utils/error/elog.c:3269 #, c-format msgid " at character %d" msgstr "(%d文字目)" -#: utils/error/elog.c:3185 utils/error/elog.c:3192 +#: utils/error/elog.c:3279 utils/error/elog.c:3286 msgid "DETAIL: " msgstr "詳細: " -#: utils/error/elog.c:3199 +#: utils/error/elog.c:3293 msgid "HINT: " msgstr "ヒント: " -#: utils/error/elog.c:3206 +#: utils/error/elog.c:3300 msgid "QUERY: " msgstr "問い合わせ: " -#: utils/error/elog.c:3213 +#: utils/error/elog.c:3307 msgid "CONTEXT: " msgstr "文脈: " -#: utils/error/elog.c:3223 +#: utils/error/elog.c:3317 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "場所: %s, %s:%d\n" -#: utils/error/elog.c:3230 +#: utils/error/elog.c:3324 #, c-format msgid "LOCATION: %s:%d\n" msgstr "場所: %s:%d\n" -#: utils/error/elog.c:3237 +#: utils/error/elog.c:3331 msgid "BACKTRACE: " msgstr "バックトレース: " -#: utils/error/elog.c:3249 +#: utils/error/elog.c:3343 msgid "STATEMENT: " msgstr "文: " -#: utils/error/elog.c:3645 +#: utils/error/elog.c:3739 msgid "DEBUG" msgstr "DEBUG" -#: utils/error/elog.c:3649 +#: utils/error/elog.c:3743 msgid "LOG" msgstr "LOG" -#: utils/error/elog.c:3652 +#: utils/error/elog.c:3746 msgid "INFO" msgstr "INFO" -#: utils/error/elog.c:3655 +#: utils/error/elog.c:3749 msgid "NOTICE" msgstr "NOTICE" -#: utils/error/elog.c:3659 +#: utils/error/elog.c:3753 msgid "WARNING" msgstr "WARNING" -#: utils/error/elog.c:3662 +#: utils/error/elog.c:3756 msgid "ERROR" msgstr "ERROR" -#: utils/error/elog.c:3665 +#: utils/error/elog.c:3759 msgid "FATAL" msgstr "FATAL" -#: utils/error/elog.c:3668 +#: utils/error/elog.c:3762 msgid "PANIC" msgstr "PANIC" -#: utils/fmgr/dfmgr.c:128 +#: utils/fmgr/dfmgr.c:118 #, c-format msgid "could not find function \"%s\" in file \"%s\"" msgstr "ファイル\"%2$s\"内に関数\"%1$s\"がありませんでした" -#: utils/fmgr/dfmgr.c:247 +#: utils/fmgr/dfmgr.c:237 #, c-format msgid "could not load library \"%s\": %s" msgstr "ライブラリ\"%s\"をロードできませんでした: %s" -#: utils/fmgr/dfmgr.c:279 +#: utils/fmgr/dfmgr.c:274 #, c-format msgid "incompatible library \"%s\": missing magic block" msgstr "\"%s\"は互換性がないライブラリです。マジックブロックの欠落" -#: utils/fmgr/dfmgr.c:281 +#: utils/fmgr/dfmgr.c:276 #, c-format msgid "Extension libraries are required to use the PG_MODULE_MAGIC macro." msgstr "拡張ライブラリはPG_MODULE_MAGICマクロを使用しなければなりません。" -#: utils/fmgr/dfmgr.c:327 +#: utils/fmgr/dfmgr.c:322 #, c-format msgid "incompatible library \"%s\": version mismatch" msgstr "\"%s\"は互換性がないライブラリです: バージョンの不一致" -#: utils/fmgr/dfmgr.c:329 +#: utils/fmgr/dfmgr.c:324 #, c-format msgid "Server is version %d, library is version %s." msgstr "サーバーはバージョン%d、ライブラリはバージョン%sです。" -#: utils/fmgr/dfmgr.c:341 +#: utils/fmgr/dfmgr.c:336 #, c-format msgid "incompatible library \"%s\": ABI mismatch" msgstr "非互換のライブラリ\"%s\": ABIの不一致" -#: utils/fmgr/dfmgr.c:343 +#: utils/fmgr/dfmgr.c:338 #, c-format msgid "Server has ABI \"%s\", library has \"%s\"." msgstr "サーバー側ABIは\"%s\"、ライブラリ側は\"%s\"です。" -#: utils/fmgr/dfmgr.c:361 +#. translator: %s is a variable name and %d its values +#: utils/fmgr/dfmgr.c:357 utils/fmgr/dfmgr.c:367 utils/fmgr/dfmgr.c:377 #, c-format -msgid "Server has FUNC_MAX_ARGS = %d, library has %d." -msgstr "サーバー側は FUNC_MAX_ARGS = %d ですが、ライブラリ側は %d です" +msgid "Server has %s = %d, library has %d." +msgstr "サーバー側では %s = %d ですが、ライブラリ側は %d です。" -#: utils/fmgr/dfmgr.c:370 +#. translator: %s is a variable name and %d its values +#: utils/fmgr/dfmgr.c:387 #, c-format -msgid "Server has INDEX_MAX_KEYS = %d, library has %d." -msgstr "サーバー側は INDEX_MAX_KEYS = %d ですが、ライブラリ側は %d です" +msgid "Server has %s = %s, library has %s." +msgstr "サーバー側では %s = \"%s\"ですが、ライブラリ側は\"%s\"です。" -#: utils/fmgr/dfmgr.c:379 -#, c-format -msgid "Server has NAMEDATALEN = %d, library has %d." -msgstr "サーバー側は NAMEDATALEN = %d ですが、ライブラリ側は %d です" - -#: utils/fmgr/dfmgr.c:388 -#, c-format -msgid "Server has FLOAT8PASSBYVAL = %s, library has %s." -msgstr "サーバー側はFLOAT8PASSBYVAL = %sですが、ライブラリ側は%sです。" - -#: utils/fmgr/dfmgr.c:395 +#: utils/fmgr/dfmgr.c:394 msgid "Magic block has unexpected length or padding difference." msgstr "マジックブロックが意図しない長さであるか、またはパディングが異なります。" -#: utils/fmgr/dfmgr.c:398 +#: utils/fmgr/dfmgr.c:397 #, c-format msgid "incompatible library \"%s\": magic block mismatch" msgstr "\"%s\"は互換性がないライブラリです: マジックブロックの不一致" -#: utils/fmgr/dfmgr.c:475 +#: utils/fmgr/dfmgr.c:520 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "ライブラリ\"%s\"へのアクセスは許可されません" -#: utils/fmgr/dfmgr.c:501 +#: utils/fmgr/dfmgr.c:547 #, c-format -msgid "invalid macro name in dynamic library path: %s" -msgstr "ダイナミックライブラリパス内のマクロが不正です: %s" +msgid "invalid macro name in path: %s" +msgstr "パス内のマクロ名が無効です: %s" -#: utils/fmgr/dfmgr.c:541 +#: utils/fmgr/dfmgr.c:599 #, c-format -msgid "zero-length component in parameter \"dynamic_library_path\"" -msgstr "パラメータ\"dynamic_library_path\"内に長さが0の要素があります" +msgid "zero-length component in parameter \"%s\"" +msgstr "パラメータ\"%s\"に長さ0の構成要素があります" -#: utils/fmgr/dfmgr.c:560 +#: utils/fmgr/dfmgr.c:618 #, c-format -msgid "component in parameter \"dynamic_library_path\" is not an absolute path" -msgstr "パラメータ\"dynamic_library_path\"内の要素が絶対パスでありません" +msgid "component in parameter \"%s\" is not an absolute path" +msgstr "パラメータ\"%s\"に絶対パスではない要素が含まれています" #: utils/fmgr/fmgr.c:236 #, c-format @@ -27300,340 +28344,422 @@ msgstr "列の別名が提供されていませんでした" msgid "could not determine row description for function returning record" msgstr "レコードを返す関数についての行定義を特定できませんでした" -#: utils/init/miscinit.c:352 +#: utils/init/miscinit.c:265 +msgid "unknown process type" +msgstr "不明なプロセスタイプ" + +#: utils/init/miscinit.c:270 +msgid "not initialized" +msgstr "未初期化プロセス" + +#: utils/init/miscinit.c:273 +msgid "archiver" +msgstr "アーカイバー" + +#: utils/init/miscinit.c:276 +msgid "autovacuum launcher" +msgstr "自動VACUUM起動プロセス" + +#: utils/init/miscinit.c:279 +msgid "autovacuum worker" +msgstr "自動VACUUMワーカー" + +#: utils/init/miscinit.c:282 +msgid "client backend" +msgstr "クライアント バックエンド" + +#: utils/init/miscinit.c:285 +msgid "dead-end client backend" +msgstr "終了待ちバックエンド" + +#: utils/init/miscinit.c:288 +msgid "background worker" +msgstr "バックグラウンドワーカー" + +#: utils/init/miscinit.c:291 +msgid "background writer" +msgstr "バックグランドライター" + +#: utils/init/miscinit.c:294 +msgid "checkpointer" +msgstr "チェックポインター" + +#: utils/init/miscinit.c:300 +msgid "logger" +msgstr "ログ出力プロセス" + +#: utils/init/miscinit.c:303 +msgid "slotsync worker" +msgstr "スロット同期ワーカー" + +#: utils/init/miscinit.c:306 +msgid "standalone backend" +msgstr "単独起動バックエンド" + +#: utils/init/miscinit.c:309 +msgid "startup" +msgstr "初期起動プロセス" + +#: utils/init/miscinit.c:312 +msgid "walreceiver" +msgstr "WAL受信プロセス" + +#: utils/init/miscinit.c:315 +msgid "walsender" +msgstr "WAL送信プロセス" + +#: utils/init/miscinit.c:318 +msgid "walsummarizer" +msgstr "WAL集計プロセス" + +#: utils/init/miscinit.c:321 +msgid "walwriter" +msgstr "WAL書き込みプロセス" + +#: utils/init/miscinit.c:358 #, c-format msgid "data directory \"%s\" does not exist" msgstr "データディレクトリ\"%s\"は存在しません" -#: utils/init/miscinit.c:357 +#: utils/init/miscinit.c:363 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "ディレクトリ\"%s\"の権限を読み取れませんでした: %m" -#: utils/init/miscinit.c:365 +#: utils/init/miscinit.c:371 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "指定されたデータディレクトリ\"%s\"はディレクトリではありません" -#: utils/init/miscinit.c:381 +#: utils/init/miscinit.c:387 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "データディレクトリ\"%s\"の所有者情報が間違っています" -#: utils/init/miscinit.c:383 +#: utils/init/miscinit.c:389 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "データディレクトリを所有するユーザーがサーバーを起動しなければなりません。" -#: utils/init/miscinit.c:401 +#: utils/init/miscinit.c:407 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "データディレクトリ\"%s\"の権限設定が不正です" -#: utils/init/miscinit.c:403 +#: utils/init/miscinit.c:409 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "権限は u=rwx(0700) または u=rwx,g=rx (0750) でなければなりません。" -#: utils/init/miscinit.c:461 +#: utils/init/miscinit.c:467 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "ディレクトリ\"%s\"に移動できませんでした: %m" -#: utils/init/miscinit.c:697 utils/misc/guc.c:3641 +#: utils/init/miscinit.c:725 utils/misc/guc.c:3647 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "セキュリティー制限操作内でパラメーター\"%s\"を設定できません" -#: utils/init/miscinit.c:770 +#: utils/init/miscinit.c:812 #, c-format msgid "role with OID %u does not exist" msgstr "OID が %u であるロールは存在しません" -#: utils/init/miscinit.c:800 +#: utils/init/miscinit.c:858 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "ロール\"%s\"はログインが許可されません" -#: utils/init/miscinit.c:818 +#: utils/init/miscinit.c:879 #, c-format msgid "too many connections for role \"%s\"" msgstr "ロール\"%s\"からの接続が多すぎます" -#: utils/init/miscinit.c:991 +#: utils/init/miscinit.c:1050 #, c-format msgid "invalid role OID: %u" msgstr "不正なロールID: %u" -#: utils/init/miscinit.c:1138 +#: utils/init/miscinit.c:1197 #, c-format msgid "database system is shut down" msgstr "データベースシステムはシャットダウンしました" -#: utils/init/miscinit.c:1225 +#: utils/init/miscinit.c:1284 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "ロックファイル\"%s\"を作成できませんでした: %m" -#: utils/init/miscinit.c:1239 +#: utils/init/miscinit.c:1298 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "ロックファイル\"%s\"をオープンできませんでした: %m" -#: utils/init/miscinit.c:1246 +#: utils/init/miscinit.c:1305 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "ロックファイル\"%s\"を読み取れませんでした: %m" -#: utils/init/miscinit.c:1255 +#: utils/init/miscinit.c:1314 #, c-format msgid "lock file \"%s\" is empty" msgstr "ロックファイル\"%s\"が空です" -#: utils/init/miscinit.c:1256 +#: utils/init/miscinit.c:1315 #, c-format msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash." msgstr "他のサーバーが稼働しているか、前回のサーバー起動失敗のためロックファイルが残っているかのいずれかです" -#: utils/init/miscinit.c:1300 +#: utils/init/miscinit.c:1359 #, c-format msgid "lock file \"%s\" already exists" msgstr "ロックファイル\"%s\"はすでに存在します" -#: utils/init/miscinit.c:1304 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "他のpostgres(PID %d)がデータディレクトリ\"%s\"で稼動していませんか?" -#: utils/init/miscinit.c:1306 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "他のpostmaster(PID %d)がデータディレクトリ\"%s\"で稼動していませんか?" -#: utils/init/miscinit.c:1309 +#: utils/init/miscinit.c:1368 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "他のpostgres(PID %d)がソケットファイル\"%s\"を使用していませんか?" -#: utils/init/miscinit.c:1311 +#: utils/init/miscinit.c:1370 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "他のpostmaster(PID %d)がソケットファイル\"%s\"を使用していませんか?" -#: utils/init/miscinit.c:1362 +#: utils/init/miscinit.c:1421 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "古いロックファイル\"%s\"を削除できませんでした: %m" -#: utils/init/miscinit.c:1364 +#: utils/init/miscinit.c:1423 #, c-format msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again." msgstr "このファイルは偶然残ってしまったようですが、削除できませんでした。手作業でこれを削除し再実行してください。" -#: utils/init/miscinit.c:1401 utils/init/miscinit.c:1415 utils/init/miscinit.c:1426 +#: utils/init/miscinit.c:1460 utils/init/miscinit.c:1474 utils/init/miscinit.c:1485 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "ロックファイル\"%s\"に書き出せませんでした: %m" -#: utils/init/miscinit.c:1537 utils/init/miscinit.c:1679 utils/misc/guc.c:5715 +#: utils/init/miscinit.c:1596 utils/init/miscinit.c:1738 utils/misc/guc.c:5763 #, c-format msgid "could not read from file \"%s\": %m" msgstr "ファイル\"%s\"から読み取れませんでした: %m" -#: utils/init/miscinit.c:1667 +#: utils/init/miscinit.c:1726 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "ファイル\"%s\"をオープンできませんでした: %m; とりあえず続けます" -#: utils/init/miscinit.c:1692 +#: utils/init/miscinit.c:1751 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "ロックファイル\"%s\"が誤ったPIDをもっています: %ld、正しくは%ld" -#: utils/init/miscinit.c:1731 utils/init/miscinit.c:1747 +#: utils/init/miscinit.c:1790 utils/init/miscinit.c:1806 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "\"%s\"は有効なデータディレクトリではありません" -#: utils/init/miscinit.c:1733 +#: utils/init/miscinit.c:1792 #, c-format msgid "File \"%s\" is missing." msgstr "ファイル\"%s\"が存在しません" -#: utils/init/miscinit.c:1749 +#: utils/init/miscinit.c:1808 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "ファイル\"%s\"に有効なデータがありません。" -#: utils/init/miscinit.c:1751 +#: utils/init/miscinit.c:1810 #, c-format msgid "You might need to initdb." msgstr "initdbする必要があるかもしれません" -#: utils/init/miscinit.c:1759 +#: utils/init/miscinit.c:1818 #, c-format msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s." msgstr "データディレクトリはPostgreSQLバージョン%sで初期化されましたが、これはバージョン%sとは互換性がありません" -#: utils/init/postinit.c:259 +#: utils/init/postinit.c:269 #, c-format msgid "replication connection authorized: user=%s" msgstr "レプリケーション接続の認証完了: ユーザー=%s" -#: utils/init/postinit.c:262 +#: utils/init/postinit.c:272 #, c-format msgid "connection authorized: user=%s" msgstr "接続の認証完了: ユーザー=%s" -#: utils/init/postinit.c:265 +#: utils/init/postinit.c:275 #, c-format msgid " database=%s" msgstr " データベース=%s" -#: utils/init/postinit.c:268 +#: utils/init/postinit.c:278 #, c-format msgid " application_name=%s" msgstr " application_name=%s" -#: utils/init/postinit.c:273 +#: utils/init/postinit.c:283 #, c-format msgid " SSL enabled (protocol=%s, cipher=%s, bits=%d)" msgstr " SSL有効(プロトコル=%s、暗号化方式=%s、ビット長=%d)" -#: utils/init/postinit.c:285 +#: utils/init/postinit.c:295 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s, principal=%s)" msgstr " GSS (認証=%s、暗号化=%s、委任資格証明=%s、プリンシパル=%s)" -#: utils/init/postinit.c:286 utils/init/postinit.c:287 utils/init/postinit.c:288 utils/init/postinit.c:293 utils/init/postinit.c:294 utils/init/postinit.c:295 +#: utils/init/postinit.c:296 utils/init/postinit.c:297 utils/init/postinit.c:298 utils/init/postinit.c:303 utils/init/postinit.c:304 utils/init/postinit.c:305 msgid "no" msgstr "いいえ" -#: utils/init/postinit.c:286 utils/init/postinit.c:287 utils/init/postinit.c:288 utils/init/postinit.c:293 utils/init/postinit.c:294 utils/init/postinit.c:295 +#: utils/init/postinit.c:296 utils/init/postinit.c:297 utils/init/postinit.c:298 utils/init/postinit.c:303 utils/init/postinit.c:304 utils/init/postinit.c:305 msgid "yes" msgstr "はい" -#: utils/init/postinit.c:292 +#: utils/init/postinit.c:302 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s)" msgstr " GSS (認証=%s、暗号化=%s、委任資格証明=%s)" -#: utils/init/postinit.c:333 +#: utils/init/postinit.c:342 #, c-format msgid "database \"%s\" has disappeared from pg_database" msgstr "データベース\"%s\"はpg_databaseから消失しました" -#: utils/init/postinit.c:335 +#: utils/init/postinit.c:344 #, c-format msgid "Database OID %u now seems to belong to \"%s\"." msgstr "OID%uのデータベースは\"%s\"に属するようです。" -#: utils/init/postinit.c:355 +#: utils/init/postinit.c:364 #, c-format msgid "database \"%s\" is not currently accepting connections" msgstr "現在データベース\"%s\"は接続を受け付けません" -#: utils/init/postinit.c:368 +#: utils/init/postinit.c:377 #, c-format msgid "permission denied for database \"%s\"" msgstr "データベース\"%s\"へのアクセスが拒否されました" -#: utils/init/postinit.c:369 +#: utils/init/postinit.c:378 #, c-format msgid "User does not have CONNECT privilege." msgstr "ユーザーはCONNECT権限を持ちません。" -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:398 #, c-format msgid "too many connections for database \"%s\"" msgstr "データベース\"%s\"への接続が多すぎます" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:422 utils/init/postinit.c:429 #, c-format msgid "database locale is incompatible with operating system" msgstr "データベースのロケールがオペレーティングシステムと互換性がありません" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:423 #, c-format msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()." msgstr "データベースは LC_COLLATE \"%s\"で初期化されていますが、setlocale() でこれを認識されません" -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:425 utils/init/postinit.c:432 #, c-format msgid "Recreate the database with another locale or install the missing locale." msgstr "データベースを別のロケールで再生成するか、または不足しているロケールをインストールしてください" -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:430 #, c-format msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "データベースは LC_CTYPE \"%s\"で初期化されていますが、setlocale()でこれを認識されません" -#: utils/init/postinit.c:491 +#: utils/init/postinit.c:471 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "データベース\"%s\"で照合順序バージョンの不一致が起きています" -#: utils/init/postinit.c:493 +#: utils/init/postinit.c:473 #, c-format msgid "The database was created using collation version %s, but the operating system provides version %s." msgstr "データベースは照合順序バージョン%sで作成されていますが、オペレーティングシステムはバージョン%sを提供しています。" -#: utils/init/postinit.c:496 +#: utils/init/postinit.c:476 #, c-format msgid "Rebuild all objects in this database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "このデータベース内でデフォルトの照合順序を使用している全てのオブジェクトを再構築して、ALTER DATABASE %s REFRESH COLLATION VERSIONを実行するか、正しいバージョンのライブラリを用いてPostgreSQLをビルドしてください。" -#: utils/init/postinit.c:902 +#: utils/init/postinit.c:566 +#, c-format +msgid "too many server processes configured" +msgstr "サーバープロセス数の設定が大きすぎます" + +#: utils/init/postinit.c:567 +#, c-format +msgid "\"max_connections\" (%d) plus \"autovacuum_worker_slots\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d." +msgstr "\"max_connections\" (%d) + \"autovacuum_worker_slots\" (%d) + \"max_worker_processes\" (%d) + \"max_wal_senders\" (%d)は%dより小さくなければなりません。" + +#: utils/init/postinit.c:889 #, c-format msgid "no roles are defined in this database system" msgstr "データベースシステム内でロールが定義されていません" -#: utils/init/postinit.c:903 +#: utils/init/postinit.c:890 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "すぐに CREATE USER \"%s\" SUPERUSER; を実行してください。" -#: utils/init/postinit.c:940 +#: utils/init/postinit.c:935 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "バイナリアップグレードモード中に接続するにはスーパーユーザーである必要があります" -#: utils/init/postinit.c:961 +#: utils/init/postinit.c:955 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "残りの接続枠は%s属性を持つロールのために予約されています" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:961 #, c-format msgid "remaining connection slots are reserved for roles with privileges of the \"%s\" role" msgstr "残りの接続枠は\"%s\"ロールの権限を持つロールのために予約されています" -#: utils/init/postinit.c:979 +#: utils/init/postinit.c:973 #, c-format msgid "permission denied to start WAL sender" msgstr "WAL送信プロセスを開始する権限がありません" -#: utils/init/postinit.c:980 +#: utils/init/postinit.c:974 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "%s属性を持つロールのみがWAL送信プロセスを開始できます。" -#: utils/init/postinit.c:1098 +#: utils/init/postinit.c:1092 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "削除またはリネームされたばかりのようです。" -#: utils/init/postinit.c:1102 +#: utils/init/postinit.c:1096 #, c-format msgid "database %u does not exist" msgstr "データベース %u は存在しません" -#: utils/init/postinit.c:1111 +#: utils/init/postinit.c:1105 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "無効なデータベース\"%s\"への接続はできません" -#: utils/init/postinit.c:1172 +#: utils/init/postinit.c:1166 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "データベースのサブディレクトリ\"%s\"がありません。" @@ -27648,12 +28774,12 @@ msgstr "ロール\"%s\"は\"%s\"へのSET ROLEはできません" msgid "invalid encoding number: %d" msgstr "不正な符号化方式番号: %d" -#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:129 utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:165 +#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:132 utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:168 #, c-format msgid "unexpected encoding ID %d for ISO 8859 character sets" msgstr "ISO8859文字セットに対する符号化方式ID %dは想定外です" -#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:110 utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:146 +#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:113 utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:149 #, c-format msgid "unexpected encoding ID %d for WIN character sets" msgstr "WIN文字セットに対する符号化方式ID %dは想定外です<" @@ -27713,80 +28839,80 @@ msgstr "空の設定ディレクトリ名: \"%s\"" msgid "could not open configuration directory \"%s\": %m" msgstr "設定ディレクトリ\"%s\"をオープンできませんでした: %m" -#: utils/misc/guc.c:122 +#: utils/misc/guc.c:119 msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "このパラメータで使用可能な単位は\"B\"、\"kB\"、\"MB\"、\"GB\"および\"TB\"です。" -#: utils/misc/guc.c:159 +#: utils/misc/guc.c:156 msgid "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\"." msgstr "このパラメータの有効単位は \"us\"、\"ms\"、\"s\"、\"min\"、\"h\"そして\"d\"です。" -#: utils/misc/guc.c:430 +#: utils/misc/guc.c:428 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "ファイル\"%2$s\"行%3$dで認識できない設定パラメータ\"%1$s\"" -#: utils/misc/guc.c:470 utils/misc/guc.c:3495 utils/misc/guc.c:3739 utils/misc/guc.c:3837 utils/misc/guc.c:3935 utils/misc/guc.c:4059 utils/misc/guc.c:4162 +#: utils/misc/guc.c:468 utils/misc/guc.c:3501 utils/misc/guc.c:3745 utils/misc/guc.c:3843 utils/misc/guc.c:3941 utils/misc/guc.c:4068 utils/misc/guc.c:4209 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "パラメータ\"%s\"を変更するにはサーバーの再起動が必要です" -#: utils/misc/guc.c:506 +#: utils/misc/guc.c:504 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "パラメーター\"%s\"が設定ファイルから削除されました。デフォルト値に戻ります。" -#: utils/misc/guc.c:571 +#: utils/misc/guc.c:569 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "パラメータ\"%s\"は\"%s\"に変更されました" -#: utils/misc/guc.c:613 +#: utils/misc/guc.c:611 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "設定ファイル\"%s\"にはエラーがあります" -#: utils/misc/guc.c:618 +#: utils/misc/guc.c:616 #, c-format msgid "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "設定ファイル\"%s\"にはエラーがあります。影響がない変更は適用されました" -#: utils/misc/guc.c:623 +#: utils/misc/guc.c:621 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "設定ファイル\"%s\"にはエラーがあります。変更は適用されませんでした" -#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 +#: utils/misc/guc.c:1137 utils/misc/guc.c:1153 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "設定パラメータ名\"%s\"は不正です" -#: utils/misc/guc.c:1141 +#: utils/misc/guc.c:1139 #, c-format msgid "Custom parameter names must be two or more simple identifiers separated by dots." msgstr "独自パラメータの名前は2つ以上の単純識別子をピリオドでつないだ形式でなければなりません。" -#: utils/misc/guc.c:1157 +#: utils/misc/guc.c:1155 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\"は予約されている接頭辞です。" -#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 +#: utils/misc/guc.c:1168 utils/misc/guc.c:1278 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "設定パラメータ\"%s\"は不明です" -#: utils/misc/guc.c:1802 +#: utils/misc/guc.c:1800 #, c-format msgid "%s: could not access directory \"%s\": %m\n" msgstr "%s: ディレクトリ\"%s\"にアクセスできませんでした: %m\n" -#: utils/misc/guc.c:1806 +#: utils/misc/guc.c:1804 #, c-format msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" msgstr "initdbまたはpg_basebackupを実行して、PostgreSQLデータディレクトリを初期化してください。\n" -#: utils/misc/guc.c:1830 +#: utils/misc/guc.c:1828 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" @@ -27796,12 +28922,12 @@ msgstr "" "--config-fileまたは-Dオプションを指定する、あるいはPGDATA環境変数を設\n" "定する必要があります。\n" -#: utils/misc/guc.c:1853 +#: utils/misc/guc.c:1851 #, c-format msgid "%s: could not access the server configuration file \"%s\": %m\n" msgstr "%s: サーバー設定ファイル\"%s\"にアクセスできませんでした: %m\n" -#: utils/misc/guc.c:1881 +#: utils/misc/guc.c:1879 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -27811,7 +28937,7 @@ msgstr "" "\"%s\"内の\"data_directory\"で指定するか、実行時に-Dオプションを指定する、またはPGDATA環\n" "境変数で設定することができます。\n" -#: utils/misc/guc.c:1933 +#: utils/misc/guc.c:1931 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" @@ -27821,7 +28947,7 @@ msgstr "" "\"%s\"内で\"hba_directory\"を指定する、-Dオプションを指定する、PGDATA環\n" "境変数で設定することができます。\n" -#: utils/misc/guc.c:1964 +#: utils/misc/guc.c:1962 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" @@ -27831,125 +28957,130 @@ msgstr "" "\"%s\"内で\"ident_directory\"を指定する、-Dオプションを指定する、PGDATA環\n" "境変数で設定することができます。\n" -#: utils/misc/guc.c:2943 +#: utils/misc/guc.c:2941 msgid "Value exceeds integer range." msgstr "値が整数範囲を超えています。" -#: utils/misc/guc.c:3185 +#: utils/misc/guc.c:3182 #, c-format msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" msgstr "%d%s%sはパラメータ\"%s\"の有効範囲(%d%s%s .. %d%s%s)の範囲外です" -#: utils/misc/guc.c:3226 +#: utils/misc/guc.c:3223 #, c-format msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" msgstr "%g%s%sはパラメータ\"%s\"の有効範囲(%g%s%s .. %g%s%s)の範囲外です" -#: utils/misc/guc.c:3447 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3462 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "並列処理中はパラメータの設定はできません" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "パラメータ\"%s\"は並列操作中には設定できません" -#: utils/misc/guc.c:3472 utils/misc/guc.c:4646 +#: utils/misc/guc.c:3478 utils/misc/guc.c:4693 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "パラメータ\"%s\"を変更できません" -#: utils/misc/guc.c:3505 +#: utils/misc/guc.c:3511 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "現在パラメータ\"%s\"を変更できません" -#: utils/misc/guc.c:3532 utils/misc/guc.c:3594 utils/misc/guc.c:4621 utils/misc/guc.c:6712 +#: utils/misc/guc.c:3538 utils/misc/guc.c:3600 utils/misc/guc.c:4668 utils/misc/guc.c:6754 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "パラメータ\"%s\"を設定する権限がありません" -#: utils/misc/guc.c:3574 +#: utils/misc/guc.c:3580 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "接続開始後にパラメータ\"%s\"を変更できません" -#: utils/misc/guc.c:3633 +#: utils/misc/guc.c:3639 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "セキュリティー定義用関数内でパラメーター\"%s\"を設定できません" -#: utils/misc/guc.c:3654 +#: utils/misc/guc.c:3660 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "パラメータ\"%s\"は設定できません" -#: utils/misc/guc.c:3661 +#: utils/misc/guc.c:3667 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "パラメータ\"%s\"は関数内では変更できません" -#: utils/misc/guc.c:4320 utils/misc/guc.c:4368 utils/misc/guc.c:5400 +#: utils/misc/guc.c:4367 utils/misc/guc.c:4415 utils/misc/guc.c:5448 #, c-format msgid "permission denied to examine \"%s\"" msgstr "”%s\"を参照する権限がありません" -#: utils/misc/guc.c:4321 utils/misc/guc.c:4369 utils/misc/guc.c:5401 +#: utils/misc/guc.c:4368 utils/misc/guc.c:4416 utils/misc/guc.c:5449 #, c-format msgid "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "\"%s\"ロールの権限を持つロールのみがこのパラメータを参照することができます。" -#: utils/misc/guc.c:4579 +#: utils/misc/guc.c:4626 #, c-format msgid "ALTER SYSTEM is not allowed in this environment" msgstr "ALTER SYSTEMはこの環境では許可されていません" -#: utils/misc/guc.c:4611 +#: utils/misc/guc.c:4658 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "ALTER SYSTEM RESET ALLを行う権限がありません" -#: utils/misc/guc.c:4690 +#: utils/misc/guc.c:4737 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "ALTER SYSTEMでのパラメータ値は改行を含んではいけません" -#: utils/misc/guc.c:4735 +#: utils/misc/guc.c:4782 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "ファイル\"%s\"の内容をパースできませんでした" -#: utils/misc/guc.c:4917 +#: utils/misc/guc.c:4965 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "パラメータ\"%s\"を再定義しようとしています" -#: utils/misc/guc.c:5256 +#: utils/misc/guc.c:5304 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "設定パラメータ名\"%s\"は不正です、削除します" -#: utils/misc/guc.c:5258 +#: utils/misc/guc.c:5306 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "\"%s\" は予約された接頭辞になりました。" -#: utils/misc/guc.c:6135 +#: utils/misc/guc.c:6177 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "パラメータ\"%s\"の\"%s\"への変更中" -#: utils/misc/guc.c:6304 +#: utils/misc/guc.c:6346 #, c-format msgid "parameter \"%s\" could not be set" msgstr "パラメータ\"%s\"を設定できません" -#: utils/misc/guc.c:6394 +#: utils/misc/guc.c:6436 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "パラメータ\"%s\"の設定をパースできません" -#: utils/misc/guc.c:6844 +#: utils/misc/guc.c:6886 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "パラメータ\"%s\"の値が無効です: %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "並列処理中はパラメータの設定はできません" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -27965,2059 +29096,2267 @@ msgstr "SET %sは1つの引数のみを取ります" msgid "SET requires parameter name" msgstr "SETにはパラメータ名が必要です" -#: utils/misc/guc_tables.c:675 +#: utils/misc/guc_tables.c:692 msgid "Ungrouped" msgstr "その他" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:693 msgid "File Locations" msgstr "ファイルの位置" -#: utils/misc/guc_tables.c:677 +#: utils/misc/guc_tables.c:694 msgid "Connections and Authentication / Connection Settings" msgstr "接続と認証/接続設定" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:695 msgid "Connections and Authentication / TCP Settings" msgstr "接続と認証/TCP設定" -#: utils/misc/guc_tables.c:679 +#: utils/misc/guc_tables.c:696 msgid "Connections and Authentication / Authentication" msgstr "接続と認証/認証" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:697 msgid "Connections and Authentication / SSL" msgstr "接続と認証/SSL" -#: utils/misc/guc_tables.c:681 +#: utils/misc/guc_tables.c:698 msgid "Resource Usage / Memory" msgstr "使用リソース/メモリ" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:699 msgid "Resource Usage / Disk" msgstr "使用リソース/ディスク" -#: utils/misc/guc_tables.c:683 +#: utils/misc/guc_tables.c:700 msgid "Resource Usage / Kernel Resources" msgstr "使用リソース/カーネルリソース" -#: utils/misc/guc_tables.c:684 -msgid "Resource Usage / Cost-Based Vacuum Delay" -msgstr "使用リソース / コストベースvacuum遅延" - -#: utils/misc/guc_tables.c:685 +#: utils/misc/guc_tables.c:701 msgid "Resource Usage / Background Writer" msgstr "使用リソース / バックグラウンド・ライタ" -#: utils/misc/guc_tables.c:686 -msgid "Resource Usage / Asynchronous Behavior" -msgstr "使用リソース / 非同期動作" +#: utils/misc/guc_tables.c:702 +msgid "Resource Usage / I/O" +msgstr "使用リソース/ I/O" -#: utils/misc/guc_tables.c:687 +#: utils/misc/guc_tables.c:703 +msgid "Resource Usage / Worker Processes" +msgstr "使用リソース/ワーカープロセス" + +#: utils/misc/guc_tables.c:704 msgid "Write-Ahead Log / Settings" msgstr "先行書き込みログ / 設定" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:705 msgid "Write-Ahead Log / Checkpoints" msgstr "先行書き込みログ / チェックポイント" -#: utils/misc/guc_tables.c:689 +#: utils/misc/guc_tables.c:706 msgid "Write-Ahead Log / Archiving" msgstr "先行書き込みログ / アーカイビング" -#: utils/misc/guc_tables.c:690 +#: utils/misc/guc_tables.c:707 msgid "Write-Ahead Log / Recovery" msgstr "先行書き込みログ / リカバリ" -#: utils/misc/guc_tables.c:691 +#: utils/misc/guc_tables.c:708 msgid "Write-Ahead Log / Archive Recovery" msgstr "先行書き込みログ / アーカイブリカバリ" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:709 msgid "Write-Ahead Log / Recovery Target" msgstr "先行書き込みログ / チェックポイント" -#: utils/misc/guc_tables.c:693 +#: utils/misc/guc_tables.c:710 msgid "Write-Ahead Log / Summarization" msgstr "先行書き込みログ / 集約" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:711 msgid "Replication / Sending Servers" msgstr "レプリケーション / 送信サーバー" -#: utils/misc/guc_tables.c:695 +#: utils/misc/guc_tables.c:712 msgid "Replication / Primary Server" msgstr "レプリケーション / プライマリサーバー" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:713 msgid "Replication / Standby Servers" msgstr "レプリケーション / スタンバイサーバー" -#: utils/misc/guc_tables.c:697 +#: utils/misc/guc_tables.c:714 msgid "Replication / Subscribers" msgstr "レプリケーション / サブスクライバ" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:715 msgid "Query Tuning / Planner Method Configuration" msgstr "問い合わせのチューニング / プランナ手法設定" -#: utils/misc/guc_tables.c:699 +#: utils/misc/guc_tables.c:716 msgid "Query Tuning / Planner Cost Constants" msgstr "問い合わせのチューニング / プランナコスト定数" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:717 msgid "Query Tuning / Genetic Query Optimizer" msgstr "問い合わせのチューニング / 遺伝的問い合わせオプティマイザ" -#: utils/misc/guc_tables.c:701 +#: utils/misc/guc_tables.c:718 msgid "Query Tuning / Other Planner Options" msgstr "問い合わせのチューニング / その他のプランオプション" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:719 msgid "Reporting and Logging / Where to Log" msgstr "レポートとログ出力 / ログの出力先" -#: utils/misc/guc_tables.c:703 +#: utils/misc/guc_tables.c:720 msgid "Reporting and Logging / When to Log" msgstr "レポートとログ出力 / ログのタイミング" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:721 msgid "Reporting and Logging / What to Log" msgstr "レポートとログ出力 / ログの内容" -#: utils/misc/guc_tables.c:705 +#: utils/misc/guc_tables.c:722 msgid "Reporting and Logging / Process Title" msgstr "レポートとログ出力 / プロセス表記" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:723 msgid "Statistics / Monitoring" msgstr "統計情報 / 監視" -#: utils/misc/guc_tables.c:707 +#: utils/misc/guc_tables.c:724 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "統計情報 / 問い合わせとインデックスの累積統計情報" -#: utils/misc/guc_tables.c:708 -msgid "Autovacuum" -msgstr "自動VACUUM" +#: utils/misc/guc_tables.c:725 +msgid "Vacuuming / Automatic Vacuuming" +msgstr "VACUUM / 自動VACUUM" -#: utils/misc/guc_tables.c:709 +#: utils/misc/guc_tables.c:726 +msgid "Vacuuming / Cost-Based Vacuum Delay" +msgstr "VACUUM / コストベースVACUUM遅延" + +#: utils/misc/guc_tables.c:727 +msgid "Vacuuming / Default Behavior" +msgstr "VACUUM / デフォルト動作" + +#: utils/misc/guc_tables.c:728 +msgid "Vacuuming / Freezing" +msgstr "VACUUM / 凍結" + +#: utils/misc/guc_tables.c:729 msgid "Client Connection Defaults / Statement Behavior" msgstr "クライアント接続のデフォルト設定 / 文の振舞い" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:730 msgid "Client Connection Defaults / Locale and Formatting" msgstr "クライアント接続のデフォルト設定 / ロケールと整形" -#: utils/misc/guc_tables.c:711 +#: utils/misc/guc_tables.c:731 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "クライアント接続のデフォルト設定 / ライブラリの事前読み込み" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:732 msgid "Client Connection Defaults / Other Defaults" msgstr "クライアント接続のデフォルト設定 / その他のデフォルト設定" -#: utils/misc/guc_tables.c:713 +#: utils/misc/guc_tables.c:733 msgid "Lock Management" msgstr "ロック管理" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:734 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "バージョンおよびプラットフォーム間の互換性 / PostgreSQLの以前のバージョン" -#: utils/misc/guc_tables.c:715 +#: utils/misc/guc_tables.c:735 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "バージョンおよびプラットフォーム間の互換性 / 他のプラットフォームおよびクライアント" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:736 msgid "Error Handling" msgstr "エラーハンドリング" -#: utils/misc/guc_tables.c:717 +#: utils/misc/guc_tables.c:737 msgid "Preset Options" msgstr "事前設定オプション" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:738 msgid "Customized Options" msgstr "独自オプション" -#: utils/misc/guc_tables.c:719 +#: utils/misc/guc_tables.c:739 msgid "Developer Options" msgstr "開発者向けオプション" -#: utils/misc/guc_tables.c:774 +#: utils/misc/guc_tables.c:794 msgid "Enables the planner's use of sequential-scan plans." msgstr "プランナでのシーケンシャルスキャンプランの使用を有効にします。" -#: utils/misc/guc_tables.c:784 +#: utils/misc/guc_tables.c:804 msgid "Enables the planner's use of index-scan plans." msgstr "プランナでのインデックススキャンプランの使用を有効にします。" -#: utils/misc/guc_tables.c:794 +#: utils/misc/guc_tables.c:814 msgid "Enables the planner's use of index-only-scan plans." msgstr "プランナでのインデックスオンリースキャンプランの使用を有効にします。" -#: utils/misc/guc_tables.c:804 +#: utils/misc/guc_tables.c:824 msgid "Enables the planner's use of bitmap-scan plans." msgstr "プランナでのビットマップスキャンプランの使用を有効にします。" -#: utils/misc/guc_tables.c:814 +#: utils/misc/guc_tables.c:834 msgid "Enables the planner's use of TID scan plans." msgstr "プランナでのTIDスキャンプランの使用を有効にします。" -#: utils/misc/guc_tables.c:824 +#: utils/misc/guc_tables.c:844 msgid "Enables the planner's use of explicit sort steps." msgstr "プランナでの明示的ソートの使用を有効にします。" -#: utils/misc/guc_tables.c:834 +#: utils/misc/guc_tables.c:854 msgid "Enables the planner's use of incremental sort steps." msgstr "プランナでの差分ソート処理の使用を有効にします。" -#: utils/misc/guc_tables.c:844 +#: utils/misc/guc_tables.c:864 msgid "Enables the planner's use of hashed aggregation plans." msgstr "プランナでのハッシュ集約プランの使用を有効にします。" -#: utils/misc/guc_tables.c:854 +#: utils/misc/guc_tables.c:874 msgid "Enables the planner's use of materialization." msgstr "プランナでの実体化の使用を有効にします。" -#: utils/misc/guc_tables.c:864 +#: utils/misc/guc_tables.c:884 msgid "Enables the planner's use of memoization." msgstr "プランナでのメモ化の使用を有効にします。" -#: utils/misc/guc_tables.c:874 +#: utils/misc/guc_tables.c:894 msgid "Enables the planner's use of nested-loop join plans." msgstr "プランナでのネストループジョインプランの使用を有効にします。" -#: utils/misc/guc_tables.c:884 +#: utils/misc/guc_tables.c:904 msgid "Enables the planner's use of merge join plans." msgstr "プランナでのマージジョインプランの使用を有効にします。" -#: utils/misc/guc_tables.c:894 +#: utils/misc/guc_tables.c:914 msgid "Enables the planner's use of hash join plans." msgstr "プランナでのハッシュジョインプランの使用を有効にします。" -#: utils/misc/guc_tables.c:904 +#: utils/misc/guc_tables.c:924 msgid "Enables the planner's use of gather merge plans." msgstr "プランナでのギャザーマージプランの使用を有効にします。" -#: utils/misc/guc_tables.c:914 +#: utils/misc/guc_tables.c:934 msgid "Enables partitionwise join." msgstr "パーティション単位ジョインを有効にします。" -#: utils/misc/guc_tables.c:924 +#: utils/misc/guc_tables.c:944 msgid "Enables partitionwise aggregation and grouping." msgstr "パーティション単位の集約およびグルーピングを有効にします。" -#: utils/misc/guc_tables.c:934 +#: utils/misc/guc_tables.c:954 msgid "Enables the planner's use of parallel append plans." msgstr "プランナでの並列アペンドプランの使用を有効にします。" -#: utils/misc/guc_tables.c:944 +#: utils/misc/guc_tables.c:964 msgid "Enables the planner's use of parallel hash plans." msgstr "プランナでの並列ハッシュプランの使用を有効にします。" -#: utils/misc/guc_tables.c:954 +#: utils/misc/guc_tables.c:974 msgid "Enables plan-time and execution-time partition pruning." msgstr "実行計画作成時および実行時のパーティション除外処理を有効にします。" -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:975 msgid "Allows the query planner and executor to compare partition bounds to conditions in the query to determine which partitions must be scanned." msgstr "実行計画時と実行時の、クエリ中の条件とパーティション境界の比較に基づいたパーティション単位のスキャン除外処理を許可します。" -#: utils/misc/guc_tables.c:966 +#: utils/misc/guc_tables.c:986 msgid "Enables the planner's ability to produce plans that provide presorted input for ORDER BY / DISTINCT aggregate functions." msgstr "プランナにおいてORDER BY / DISTINCT集約関数に対してソート済みの入力を供給する実行計画の生成を有効化します。" -#: utils/misc/guc_tables.c:969 +#: utils/misc/guc_tables.c:989 msgid "Allows the query planner to build plans that provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." msgstr "問い合わせプランナがORDER BY / DISTINCT句を使用する集約関数に対してソート済みの入力を供給する実行計画を生成することを許可します。無効にすると、実行時にソートが常に暗黙的に実行されるようになります。" -#: utils/misc/guc_tables.c:981 +#: utils/misc/guc_tables.c:1001 msgid "Enables the planner's use of async append plans." msgstr "プランナでの非同期アペンドプランの使用を有効にします。" -#: utils/misc/guc_tables.c:991 +#: utils/misc/guc_tables.c:1011 +msgid "Enables removal of unique self-joins." +msgstr "ユニークな自己結合の削除を有効にします。" + +#: utils/misc/guc_tables.c:1021 msgid "Enables reordering of GROUP BY keys." msgstr "GROUP BYキーによる再ソートを有効化します。" -#: utils/misc/guc_tables.c:1001 +#: utils/misc/guc_tables.c:1031 +msgid "Enables reordering of DISTINCT pathkeys." +msgstr "DISTINCTパスキーの順序変更を有効にします。" + +#: utils/misc/guc_tables.c:1041 msgid "Enables genetic query optimization." msgstr "遺伝的問い合わせ最適化を有効にします。" -#: utils/misc/guc_tables.c:1002 +#: utils/misc/guc_tables.c:1042 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "このアルゴリズムでは、全数探索を伴わずに行う実行計画の作成を試みます。" -#: utils/misc/guc_tables.c:1016 +#: utils/misc/guc_tables.c:1056 msgid "Shows whether the current user is a superuser." msgstr "現在のユーザーがスーパーユーザーかどうかを表示します。" -#: utils/misc/guc_tables.c:1031 +#: utils/misc/guc_tables.c:1071 msgid "Allows running the ALTER SYSTEM command." msgstr "ALTER SYSTEMコマンドの実行を許可します。" -#: utils/misc/guc_tables.c:1032 +#: utils/misc/guc_tables.c:1072 msgid "Can be set to off for environments where global configuration changes should be made using a different method." msgstr "グローバル設定の変更を他の方法で行うべき環境ではoffにすることができます。" -#: utils/misc/guc_tables.c:1042 +#: utils/misc/guc_tables.c:1082 msgid "Enables advertising the server via Bonjour." msgstr "Bonjour を経由したサーバーのアドバタイズを有効にします。" -#: utils/misc/guc_tables.c:1051 +#: utils/misc/guc_tables.c:1091 msgid "Collects transaction commit time." msgstr "トランザクションのコミット時刻を収集します。" -#: utils/misc/guc_tables.c:1060 +#: utils/misc/guc_tables.c:1100 msgid "Enables SSL connections." msgstr "SSL接続を有効にします。" -#: utils/misc/guc_tables.c:1069 +#: utils/misc/guc_tables.c:1109 msgid "Controls whether \"ssl_passphrase_command\" is called during server reload." msgstr "サーバーリロード時に\"ssl_passphrase_command\"を呼び出すかどうかを制御します。" -#: utils/misc/guc_tables.c:1078 +#: utils/misc/guc_tables.c:1118 msgid "Give priority to server ciphersuite order." msgstr "サーバー側の暗号スイート順序を優先します。" -#: utils/misc/guc_tables.c:1087 +#: utils/misc/guc_tables.c:1127 msgid "Forces synchronization of updates to disk." msgstr "強制的に更新をディスクに同期します。" -#: utils/misc/guc_tables.c:1088 +#: utils/misc/guc_tables.c:1128 msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This ensures that a database cluster will recover to a consistent state after an operating system or hardware crash." msgstr "サーバーは、確実に更新が物理的にディスクに書き込まれるように複数の場所でfsync()システムコールを使用します。これにより、オペレーティングシステムやハードウェアがクラッシュした後でもデータベースクラスタは一貫した状態に復旧することができます。" -#: utils/misc/guc_tables.c:1099 +#: utils/misc/guc_tables.c:1139 msgid "Continues processing after a checksum failure." msgstr "チェックサムエラーの発生時に処理を継続します。" -#: utils/misc/guc_tables.c:1100 +#: utils/misc/guc_tables.c:1140 msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled." msgstr "チェックサムエラーを検知すると、通常PostgreSQLはエラーの報告を行ない、現在のトランザクションを中断させます。ignore_checksum_failureを真に設定することによりエラーを無視します(代わりに警告を報告します)この動作はクラッシュや他の深刻な問題を引き起こすかもしれません。チェックサムが有効な場合にのみ効果があります。" -#: utils/misc/guc_tables.c:1114 +#: utils/misc/guc_tables.c:1154 msgid "Continues processing past damaged page headers." msgstr "破損したページヘッダがあっても処理を継続します。" -#: utils/misc/guc_tables.c:1115 +#: utils/misc/guc_tables.c:1155 msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting \"zero_damaged_pages\" to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." msgstr "ページヘッダの障害が検出されると、通常PostgreSQLはエラーの報告を行ない、現在のトランザクションを中断させます。\"zero_damaged_pages\"をtrueに設定することにより、システムは代わりに警告を報告し、障害のあるページをゼロで埋め、処理を継続します。 この動作により、障害のあったページ上にある全ての行のデータが破壊されます。" -#: utils/misc/guc_tables.c:1128 +#: utils/misc/guc_tables.c:1168 msgid "Continues recovery after an invalid pages failure." msgstr "不正ページエラーの発生時に処理を継続します。" -#: utils/misc/guc_tables.c:1129 +#: utils/misc/guc_tables.c:1169 msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." msgstr "リカバリ中に不正なページへの参照を行うWALレコードを検出した場合、PostgreSQLはPANICレベルのエラーを出力してリカバリを中断します。”ignore_invalid_pages\"をtrueに設定するとシステムはWALレコード中の不正なページへの参照を無視してリカバリを継続します(ただし、引き続き警告は出力します)。この挙動はクラッシュ、データ損失、破壊の伝播ないしは隠蔽または他の深刻な問題を引き起こします。リカバリモードもしくはスタンバイモードでのみ有効となります。" -#: utils/misc/guc_tables.c:1147 +#: utils/misc/guc_tables.c:1187 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "チェックポイントの後最初に変更された際にページ全体をWALに出力します。" -#: utils/misc/guc_tables.c:1148 +#: utils/misc/guc_tables.c:1188 msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible." msgstr "ページ書き込み処理中にオペレーティングシステムがクラッシュすると、ディスクへの書き込みが一部分のみ行われる可能性があります。リカバリでは、WALに保存された行の変更だけでは完全に復旧させることができません。このオプションにより、チェックポイントの後の最初の更新時にWALにページを出力するため、完全な復旧が可能になります。" -#: utils/misc/guc_tables.c:1161 +#: utils/misc/guc_tables.c:1201 msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification." msgstr "チェックポイントの後最初に更新された時に、重要な更新ではなくてもページ全体をWALに書き出します。" -#: utils/misc/guc_tables.c:1171 +#: utils/misc/guc_tables.c:1211 msgid "Writes zeroes to new WAL files before first use." msgstr "新しいWALファイルの使用前にゼロを書き込みます。" -#: utils/misc/guc_tables.c:1181 +#: utils/misc/guc_tables.c:1221 msgid "Recycles WAL files by renaming them." msgstr "WALファイルを名前を変更して再利用します。" -#: utils/misc/guc_tables.c:1191 +#: utils/misc/guc_tables.c:1231 msgid "Logs each checkpoint." msgstr "チェックポイントをログに記録します。" -#: utils/misc/guc_tables.c:1200 -msgid "Logs each successful connection." -msgstr "成功した接続を全てログに記録します。" - -#: utils/misc/guc_tables.c:1209 +#: utils/misc/guc_tables.c:1240 msgid "Logs details of pre-authentication connection handshake." msgstr "認証前接続ハンドシェークの詳細をログに出力します。" -#: utils/misc/guc_tables.c:1219 +#: utils/misc/guc_tables.c:1250 msgid "Logs end of a session, including duration." msgstr "セッションの終了時刻とその期間をログに記録します。" -#: utils/misc/guc_tables.c:1228 +#: utils/misc/guc_tables.c:1259 msgid "Logs each replication command." msgstr "各レプリケーションコマンドをログに記録します。" -#: utils/misc/guc_tables.c:1237 +#: utils/misc/guc_tables.c:1268 msgid "Shows whether the running server has assertion checks enabled." msgstr "起動中のサーバーがアサーションチェックを有効にしているかどうかを表示します。" -#: utils/misc/guc_tables.c:1248 +#: utils/misc/guc_tables.c:1279 msgid "Terminate session on any error." msgstr "何からのエラーがあればセッションを終了します" -#: utils/misc/guc_tables.c:1257 +#: utils/misc/guc_tables.c:1288 msgid "Reinitialize server after backend crash." msgstr "バックエンドがクラッシュした後サーバーを再初期化します" -#: utils/misc/guc_tables.c:1266 +#: utils/misc/guc_tables.c:1297 msgid "Remove temporary files after backend crash." msgstr "バックエンドのクラッシュ後に一時ファイルを削除します。" -#: utils/misc/guc_tables.c:1276 +#: utils/misc/guc_tables.c:1307 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "バックエンドのクラッシュ後にSIGQUITではなくSIGABRTを子プロセスに送信します。" -#: utils/misc/guc_tables.c:1286 +#: utils/misc/guc_tables.c:1317 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "固まっているプロセスにSIGKILLではなくSIGABRTを送信します。" -#: utils/misc/guc_tables.c:1297 +#: utils/misc/guc_tables.c:1328 msgid "Logs the duration of each completed SQL statement." msgstr "完了したSQL全ての実行時間をログに記録します。" -#: utils/misc/guc_tables.c:1306 +#: utils/misc/guc_tables.c:1338 +msgid "Set this to force all parse and plan trees to be passed through copyObject(), to facilitate catching errors and omissions in copyObject()." +msgstr "これを設定すると、すべてのパースおよび実行計画ツリーがcopyObject()を通過するようになり、copyObject()でのエラーや処理漏れを検出しやすくします。" + +#: utils/misc/guc_tables.c:1355 +msgid "Set this to force all parse and plan trees to be passed through outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in those modules." +msgstr "これを設定すると、すべてのパースおよび実行計画ツリーがoutfuncs.c/readfuncs.cを通過するようになり、これらのモジュールでのエラーや処理漏れを検出しやすくします。" + +#: utils/misc/guc_tables.c:1372 +msgid "Set this to force all raw parse trees for DML statements to be scanned by raw_expression_tree_walker(), to facilitate catching errors and omissions in that function." +msgstr "これを設定すると、DML文のすべての未処理のパースツリーがraw_expression_tree_walker()でスキャンされ、この関数でのエラーや処理漏れを検出しやすくします。" + +#: utils/misc/guc_tables.c:1390 msgid "Logs each query's parse tree." msgstr "問い合わせのパースツリーをログに記録します。" -#: utils/misc/guc_tables.c:1315 +#: utils/misc/guc_tables.c:1399 msgid "Logs each query's rewritten parse tree." msgstr "リライト後の問い合わせのパースツリーをログに記録します。" -#: utils/misc/guc_tables.c:1324 +#: utils/misc/guc_tables.c:1408 msgid "Logs each query's execution plan." msgstr "問い合わせの実行計画をログに記録します。" -#: utils/misc/guc_tables.c:1333 +#: utils/misc/guc_tables.c:1417 msgid "Indents parse and plan tree displays." msgstr "パースツリーと実行計画ツリーの表示をインデントします。" -#: utils/misc/guc_tables.c:1342 +#: utils/misc/guc_tables.c:1426 msgid "Writes parser performance statistics to the server log." msgstr "パーサの性能統計情報をサーバーログに出力します。" -#: utils/misc/guc_tables.c:1351 +#: utils/misc/guc_tables.c:1435 msgid "Writes planner performance statistics to the server log." msgstr "プランナの性能統計情報をサーバーログに出力します。" -#: utils/misc/guc_tables.c:1360 +#: utils/misc/guc_tables.c:1444 msgid "Writes executor performance statistics to the server log." msgstr "エグゼキュータの性能統計情報をサーバーログに出力します。" -#: utils/misc/guc_tables.c:1369 +#: utils/misc/guc_tables.c:1453 msgid "Writes cumulative performance statistics to the server log." msgstr "累積の性能統計情報をサーバーログに出力します。" -#: utils/misc/guc_tables.c:1379 +#: utils/misc/guc_tables.c:1463 msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations." msgstr "B-treeの各種操作に関するシステムリソース(メモリとCPU)の使用統計をログに記録します。" -#: utils/misc/guc_tables.c:1391 +#: utils/misc/guc_tables.c:1475 msgid "Collects information about executing commands." msgstr "実行中のコマンドに関する情報を収集します。" -#: utils/misc/guc_tables.c:1392 +#: utils/misc/guc_tables.c:1476 msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution." msgstr "そのコマンドが実行を開始した時刻を伴った、各セッションでの現時点で実行中のコマンドに関する情報の収集を有効にします。" -#: utils/misc/guc_tables.c:1402 +#: utils/misc/guc_tables.c:1486 msgid "Collects statistics on database activity." msgstr "データベースの活動について統計情報を収集します。" -#: utils/misc/guc_tables.c:1411 +#: utils/misc/guc_tables.c:1495 +msgid "Collects timing statistics for cost-based vacuum delay." +msgstr "コストベースのVACUUM遅延に関する時間統計を収集します。" + +#: utils/misc/guc_tables.c:1504 msgid "Collects timing statistics for database I/O activity." msgstr "データベースのI/O処理時間に関する統計情報を収集します。" -#: utils/misc/guc_tables.c:1420 +#: utils/misc/guc_tables.c:1513 msgid "Collects timing statistics for WAL I/O activity." msgstr "WALのI/O処理時間に関する統計情報を収集します。" -#: utils/misc/guc_tables.c:1430 +#: utils/misc/guc_tables.c:1523 msgid "Updates the process title to show the active SQL command." msgstr "活動中のSQLコマンドを表示するようプロセスタイトルを更新します。" -#: utils/misc/guc_tables.c:1431 +#: utils/misc/guc_tables.c:1524 msgid "Enables updating of the process title every time a new SQL command is received by the server." msgstr "新しいSQLコマンドをサーバーが受信する度に行うプロセスタイトルの更新を有効にします。" -#: utils/misc/guc_tables.c:1440 +#: utils/misc/guc_tables.c:1533 msgid "Starts the autovacuum subprocess." msgstr "autovacuumサブプロセスを起動します。" -#: utils/misc/guc_tables.c:1450 +#: utils/misc/guc_tables.c:1543 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "LISTENとNOTIFYコマンドのためのデバッグ出力を生成します。" -#: utils/misc/guc_tables.c:1462 +#: utils/misc/guc_tables.c:1555 msgid "Emits information about lock usage." msgstr "ロック使用状況に関する情報を出力します。" -#: utils/misc/guc_tables.c:1472 +#: utils/misc/guc_tables.c:1565 msgid "Emits information about user lock usage." msgstr "ユーザーロックの使用状況に関する情報を出力します。" -#: utils/misc/guc_tables.c:1482 +#: utils/misc/guc_tables.c:1575 msgid "Emits information about lightweight lock usage." msgstr "軽量ロックの使用状況に関する情報を出力します。" -#: utils/misc/guc_tables.c:1492 +#: utils/misc/guc_tables.c:1585 msgid "Dumps information about all current locks when a deadlock timeout occurs." msgstr "デッドロックの発生時点の全てのロックについての情報をダンプします。" -#: utils/misc/guc_tables.c:1504 +#: utils/misc/guc_tables.c:1597 msgid "Logs long lock waits." msgstr "長時間のロック待機をログに記録します。" -#: utils/misc/guc_tables.c:1513 +#: utils/misc/guc_tables.c:1606 +msgid "Logs lock failures." +msgstr "ロックの失敗をログ出力します。" + +#: utils/misc/guc_tables.c:1615 msgid "Logs standby recovery conflict waits." msgstr "スタンバイのリカバリ衝突による待機をログ出力します。" -#: utils/misc/guc_tables.c:1522 +#: utils/misc/guc_tables.c:1624 msgid "Logs the host name in the connection logs." msgstr "接続ログ内でホスト名を出力します。" -#: utils/misc/guc_tables.c:1523 +#: utils/misc/guc_tables.c:1625 msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty." msgstr "デフォルトでは、接続ログメッセージには接続ホストのIPアドレスのみが表示されます。 このオプションを有効にすることで、ホスト名もログに表示されるようになります。 ホスト名解決の設定によってはで、無視できないほどの性能の悪化が起きうることに注意してください。" -#: utils/misc/guc_tables.c:1534 +#: utils/misc/guc_tables.c:1636 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "\"expr=NULL\"という形の式は\"expr IS NULL\"として扱います。" -#: utils/misc/guc_tables.c:1535 +#: utils/misc/guc_tables.c:1637 msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)." msgstr "有効にした場合、expr = NULL(またはNULL = expr)という形の式はexpr IS NULLとして扱われます。つまり、exprの評価がNULL値の場合に真を、さもなくば偽を返します。expr = NULLのSQL仕様に基づいた正しい動作は常にNULL(未知)を返すことです。" -#: utils/misc/guc_tables.c:1547 +#: utils/misc/guc_tables.c:1649 msgid "Sets the default read-only status of new transactions." msgstr "新しいトランザクションのリードオンリー設定のデフォルト値を設定。" -#: utils/misc/guc_tables.c:1557 +#: utils/misc/guc_tables.c:1659 msgid "Sets the current transaction's read-only status." msgstr "現在のトランザクションのリードオンリー設定を設定。" -#: utils/misc/guc_tables.c:1567 +#: utils/misc/guc_tables.c:1669 msgid "Sets the default deferrable status of new transactions." msgstr "新しいトランザクションの遅延可否設定のデフォルト値を設定。" -#: utils/misc/guc_tables.c:1576 +#: utils/misc/guc_tables.c:1678 msgid "Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures." msgstr "リードオンリーのシリアライズ可能なトランザクションを、シリアライズに失敗することなく実行できるまで遅延させるかどうか" -#: utils/misc/guc_tables.c:1586 -msgid "Enable row security." +#: utils/misc/guc_tables.c:1688 +msgid "Enables row security." msgstr "行セキュリティを有効にします。" -#: utils/misc/guc_tables.c:1587 +#: utils/misc/guc_tables.c:1689 msgid "When enabled, row security will be applied to all users." msgstr "有効にすると、行セキュリティが全てのユーザーに適用されます。" -#: utils/misc/guc_tables.c:1595 +#: utils/misc/guc_tables.c:1697 msgid "Check routine bodies during CREATE FUNCTION and CREATE PROCEDURE." msgstr "CREATE FUNCTIONおよびCREATE PROCEDUREにおいて関数本体を検査します。" -#: utils/misc/guc_tables.c:1604 -msgid "Enable input of NULL elements in arrays." +#: utils/misc/guc_tables.c:1706 +msgid "Enables input of NULL elements in arrays." msgstr "配列内のNULL要素入力を有効化。" -#: utils/misc/guc_tables.c:1605 +#: utils/misc/guc_tables.c:1707 msgid "When turned on, unquoted NULL in an array input value means a null value; otherwise it is taken literally." msgstr "有効にすると、配列入力値における引用符のないNULLはNULL値を意味するようになります。さもなくば文字通りに解釈されます。" -#: utils/misc/guc_tables.c:1621 +#: utils/misc/guc_tables.c:1723 msgid "WITH OIDS is no longer supported; this can only be false." msgstr "WITH OIDS は今後サポートされません; false のみに設定可能です。" -#: utils/misc/guc_tables.c:1631 -msgid "Start a subprocess to capture stderr output and/or csvlogs into log files." -msgstr "標準エラー出力、CSVログ、またはその両方をログファイルに捕捉するための子プロセスを開始します。" +#: utils/misc/guc_tables.c:1733 +msgid "Start a subprocess to capture stderr, csvlog and/or jsonlog into log files." +msgstr "標準エラー出力、CSVログ、および/またはJSONログをログファイルに記録するための子プロセスを開始します。" -#: utils/misc/guc_tables.c:1640 +#: utils/misc/guc_tables.c:1742 msgid "Truncate existing log files of same name during log rotation." msgstr "ログローテーション時に既存の同一名称のログファイルを切り詰めます。" -#: utils/misc/guc_tables.c:1651 +#: utils/misc/guc_tables.c:1752 msgid "Emit information about resource usage in sorting." msgstr "ソート中にリソース使用状況に関する情報を出力します。" -#: utils/misc/guc_tables.c:1665 +#: utils/misc/guc_tables.c:1765 msgid "Generate debugging output for synchronized scanning." msgstr "同期スキャン処理のデバッグ出力を生成します。" -#: utils/misc/guc_tables.c:1680 -msgid "Enable bounded sorting using heap sort." -msgstr "ヒープソートを使用した境界のソート処理を有効にします" +#: utils/misc/guc_tables.c:1780 +msgid "Enables bounded sorting using heap sort." +msgstr "ヒープソートを使用した有界ソート処理を有効にします。" -#: utils/misc/guc_tables.c:1693 +#: utils/misc/guc_tables.c:1793 msgid "Emit WAL-related debugging output." msgstr "WAL関連のデバッグ出力を出力します。" -#: utils/misc/guc_tables.c:1705 +#: utils/misc/guc_tables.c:1805 msgid "Shows whether datetimes are integer based." msgstr "日付時刻が整数ベースかどうかを表示します。" -#: utils/misc/guc_tables.c:1716 +#: utils/misc/guc_tables.c:1816 msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive." msgstr "KerberosおよびGSSAPIユーザー名を大文字小文字を区別して扱うかどうかを設定します。" -#: utils/misc/guc_tables.c:1726 +#: utils/misc/guc_tables.c:1826 msgid "Sets whether GSSAPI delegation should be accepted from the client." msgstr "GSSAPI資格証明委任をクライアントから受け付けるかどかを設定します。" -#: utils/misc/guc_tables.c:1736 +#: utils/misc/guc_tables.c:1836 msgid "Warn about backslash escapes in ordinary string literals." msgstr "普通の文字列リテラル内のバックスラッシュエスケープを警告します。" -#: utils/misc/guc_tables.c:1746 +#: utils/misc/guc_tables.c:1846 msgid "Causes '...' strings to treat backslashes literally." msgstr "'...' 文字列はバックスラッシュをそのまま扱います。" -#: utils/misc/guc_tables.c:1757 -msgid "Enable synchronized sequential scans." +#: utils/misc/guc_tables.c:1857 +msgid "Enables synchronized sequential scans." msgstr "同期シーケンシャルスキャンを有効にします。" -#: utils/misc/guc_tables.c:1767 +#: utils/misc/guc_tables.c:1867 msgid "Sets whether to include or exclude transaction with recovery target." msgstr "リカバリ目標のトランザクションを含めるか除外するかを設定。" -#: utils/misc/guc_tables.c:1777 +#: utils/misc/guc_tables.c:1877 msgid "Starts the WAL summarizer process to enable incremental backup." msgstr "差分バックアップを可能にするためのWAL集約プロセスを起動します。" -#: utils/misc/guc_tables.c:1787 +#: utils/misc/guc_tables.c:1887 msgid "Allows connections and queries during recovery." msgstr "リカバリ中でも接続と問い合わせを受け付けます" -#: utils/misc/guc_tables.c:1797 +#: utils/misc/guc_tables.c:1897 msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts." msgstr "問い合わせの衝突を避けるためのホットスタンバイからプライマリへのフィードバックを受け付けます" -#: utils/misc/guc_tables.c:1807 +#: utils/misc/guc_tables.c:1907 msgid "Shows whether hot standby is currently active." msgstr "現在ホットスタンバイが有効であるかどうかを示します。" -#: utils/misc/guc_tables.c:1818 +#: utils/misc/guc_tables.c:1918 msgid "Allows modifications of the structure of system tables." msgstr "システムテーブル構造の変更を許可。" -#: utils/misc/guc_tables.c:1829 +#: utils/misc/guc_tables.c:1929 msgid "Disables reading from system indexes." msgstr "システムインデックスの読み込みを無効にします。" -#: utils/misc/guc_tables.c:1830 +#: utils/misc/guc_tables.c:1930 msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness." msgstr "これはインデックスの更新は妨げないため使用しても安全です。最も大きな悪影響は低速化です。" -#: utils/misc/guc_tables.c:1841 +#: utils/misc/guc_tables.c:1941 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "pg_tblspc直下のテーブル空間を許可します、テスト用。" -#: utils/misc/guc_tables.c:1852 +#: utils/misc/guc_tables.c:1952 msgid "Enables backward compatibility mode for privilege checks on large objects." msgstr "ラージオブジェクトで権限チェックを行う際、後方互換性モードを有効にします。" -#: utils/misc/guc_tables.c:1853 +#: utils/misc/guc_tables.c:1953 msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0." msgstr "9.0 より前のPostgreSQLとの互換のため、ラージオブジェクトを読んだり変更したりする際に権限チェックをスキップする。" -#: utils/misc/guc_tables.c:1863 +#: utils/misc/guc_tables.c:1963 msgid "When generating SQL fragments, quote all identifiers." msgstr "SQL文を生成する時に、すべての識別子を引用符で囲みます。" -#: utils/misc/guc_tables.c:1873 +#: utils/misc/guc_tables.c:1973 msgid "Shows whether data checksums are turned on for this cluster." msgstr "データチェックサムがこのクラスタで有効になっているかどうかを表示します。" -#: utils/misc/guc_tables.c:1884 +#: utils/misc/guc_tables.c:1984 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "シーケンス番号を付加することでsyslogメッセージの重複を防ぎます。" -#: utils/misc/guc_tables.c:1894 +#: utils/misc/guc_tables.c:1994 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "syslogに送出するメッセージを行単位で分割して、1024バイトに収まるようにします。" -#: utils/misc/guc_tables.c:1904 +#: utils/misc/guc_tables.c:2004 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "Gather および Gather Merge でも下位プランを実行するかどうかを制御します。" -#: utils/misc/guc_tables.c:1905 +#: utils/misc/guc_tables.c:2005 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "Gather ノードでも下位プランを実行するのか、もしくはただタプルの収集のみを行うのか?" -#: utils/misc/guc_tables.c:1915 +#: utils/misc/guc_tables.c:2015 msgid "Allow JIT compilation." msgstr "JITコンパイルを許可します。" -#: utils/misc/guc_tables.c:1926 +#: utils/misc/guc_tables.c:2026 msgid "Register JIT-compiled functions with debugger." msgstr "JITコンパイルされた関数をデバッガに登録します。" -#: utils/misc/guc_tables.c:1943 +#: utils/misc/guc_tables.c:2043 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "LLVMビットコードを出力して、JITデバッグを容易にします。" -#: utils/misc/guc_tables.c:1954 +#: utils/misc/guc_tables.c:2054 msgid "Allow JIT compilation of expressions." msgstr "式のJITコンパイルを許可します。" -#: utils/misc/guc_tables.c:1965 +#: utils/misc/guc_tables.c:2065 msgid "Register JIT-compiled functions with perf profiler." msgstr "perfプロファイラにJITコンパイルされた関数を登録します。" -#: utils/misc/guc_tables.c:1982 +#: utils/misc/guc_tables.c:2082 msgid "Allow JIT compilation of tuple deforming." msgstr "タプル分解処理のJITコンパイルを許可します。" -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2093 msgid "Whether to continue running after a failure to sync data files." msgstr "データファイルの同期失敗の後に処理を継続するかどうか。" -#: utils/misc/guc_tables.c:2002 +#: utils/misc/guc_tables.c:2102 msgid "Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured." msgstr "永続レプリケーションスロットがない場合にWALレシーバが一時スロットを作成するかどうかを設定します。" -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2111 msgid "Enables event triggers." msgstr "イベントトリガを有効にします。" -#: utils/misc/guc_tables.c:2012 +#: utils/misc/guc_tables.c:2112 msgid "When enabled, event triggers will fire for all applicable statements." msgstr "有効にすると、イベントトリガは適用可能なすべての文に対して発火します。" -#: utils/misc/guc_tables.c:2021 -msgid "Enables a physical standby to synchronize logical failover slots from the primary server." -msgstr "物理スタンバイがプライマリサーバーの論理フェイルオーバースロットを同期できるようにする。" +#: utils/misc/guc_tables.c:2121 +msgid "Enables a physical standby to synchronize logical failover replication slots from the primary server." +msgstr "物理スタンバイがプライマリサーバーから論理フェイルオーバーレプリケーションスロットを同期できるようにする。" -#: utils/misc/guc_tables.c:2039 +#: utils/misc/guc_tables.c:2130 +msgid "Enables deprecation warnings for MD5 passwords." +msgstr "MD5パスワードの非推奨警告を有効にする。" + +#: utils/misc/guc_tables.c:2139 +msgid "Enables vacuum to truncate empty pages at the end of the table." +msgstr "VACUUMの際にテーブル末尾の空のページを切り詰めるようにします。" + +#: utils/misc/guc_tables.c:2157 msgid "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "次のWALへの強制切り替え時間を設定します。" -#: utils/misc/guc_tables.c:2050 +#: utils/misc/guc_tables.c:2159 utils/misc/guc_tables.c:2313 utils/misc/guc_tables.c:2732 utils/misc/guc_tables.c:2743 utils/misc/guc_tables.c:2754 utils/misc/guc_tables.c:2765 utils/misc/guc_tables.c:2776 +msgid "0 disables the timeout." +msgstr "0でこのタイムアウトを無効にします。" + +#: utils/misc/guc_tables.c:2168 msgid "Sets the amount of time to wait after authentication on connection startup." msgstr "接続開始時の認証後の待ち時間を設定します。" -#: utils/misc/guc_tables.c:2052 utils/misc/guc_tables.c:2774 +#: utils/misc/guc_tables.c:2170 utils/misc/guc_tables.c:2908 msgid "This allows attaching a debugger to the process." msgstr "これによりデバッガがプロセスに接続できます。" -#: utils/misc/guc_tables.c:2061 +#: utils/misc/guc_tables.c:2179 msgid "Sets the default statistics target." msgstr "デフォルトの統計情報収集目標を設定。" -#: utils/misc/guc_tables.c:2062 +#: utils/misc/guc_tables.c:2180 msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS." msgstr "ALTER TABLE SET STATISTICS経由で列固有の目標値を持たないテーブル列についての統計情報収集目標を設定します。" -#: utils/misc/guc_tables.c:2071 +#: utils/misc/guc_tables.c:2189 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "副問い合わせを展開する上限のFROMリストのサイズを設定。" -#: utils/misc/guc_tables.c:2073 +#: utils/misc/guc_tables.c:2191 msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items." msgstr "最終的なFROMリストがこの値より多くの要素を持たない時に、プランナは副問い合わせを上位問い合わせにマージします。" -#: utils/misc/guc_tables.c:2084 +#: utils/misc/guc_tables.c:2202 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "JOIN式を平坦化する上限のFROMリストのサイズを設定。" -#: utils/misc/guc_tables.c:2086 +#: utils/misc/guc_tables.c:2204 msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result." msgstr "最終的にFROMリストの項目数がこの値を超えない時には常に、プランナは明示的なJOIN構文をFROM項目のリストに組み込みます。" -#: utils/misc/guc_tables.c:2097 +#: utils/misc/guc_tables.c:2215 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "この数を超えるとGEQOを使用するFROM項目数の閾値を設定。" -#: utils/misc/guc_tables.c:2107 +#: utils/misc/guc_tables.c:2225 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "GEQO: effortは他のGEQOパラメータのデフォルトを設定するために使用されます。" -#: utils/misc/guc_tables.c:2117 +#: utils/misc/guc_tables.c:2235 msgid "GEQO: number of individuals in the population." msgstr "GEQO: 集団内の個体数。" -#: utils/misc/guc_tables.c:2118 utils/misc/guc_tables.c:2128 -msgid "Zero selects a suitable default value." +#: utils/misc/guc_tables.c:2236 utils/misc/guc_tables.c:2246 +msgid "0 means use a suitable default value." msgstr "0は適切なデフォルト値を選択します。" -#: utils/misc/guc_tables.c:2127 +#: utils/misc/guc_tables.c:2245 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: アルゴリズムの反復回数です。" -#: utils/misc/guc_tables.c:2139 +#: utils/misc/guc_tables.c:2257 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "デッドロック状態があるかどうかを調べる前にロックを待つ時間を設定。" -#: utils/misc/guc_tables.c:2150 +#: utils/misc/guc_tables.c:2268 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data." msgstr "ホットスタンバイサーバーがアーカイブされた WAL データを処理している場合は、問い合わせをキャンセルする前に遅延秒数の最大値を設定。" -#: utils/misc/guc_tables.c:2161 +#: utils/misc/guc_tables.c:2269 utils/misc/guc_tables.c:2280 +msgid "-1 means wait forever." +msgstr "-1は無期限を意味します。" + +#: utils/misc/guc_tables.c:2279 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data." msgstr "ホットスタンバイサーバーがストリームの WAL データを処理している場合は、問い合わせをキャンセルする前に遅延秒数の最大値を設定。" -#: utils/misc/guc_tables.c:2172 +#: utils/misc/guc_tables.c:2290 msgid "Sets the minimum delay for applying changes during recovery." msgstr "リカバリ中の変更の適用の最小遅延時間を設定します。" -#: utils/misc/guc_tables.c:2183 +#: utils/misc/guc_tables.c:2301 msgid "Sets the maximum interval between WAL receiver status reports to the sending server." msgstr "WAL受信プロセスが送出側サーバーへ行う状況報告の最大間隔を設定。" -#: utils/misc/guc_tables.c:2194 +#: utils/misc/guc_tables.c:2312 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "送出側サーバーからのデータ受信を待機する最長時間を設定。" -#: utils/misc/guc_tables.c:2205 +#: utils/misc/guc_tables.c:2323 msgid "Sets the maximum number of concurrent connections." msgstr "同時接続数の最大値を設定。" -#: utils/misc/guc_tables.c:2216 +#: utils/misc/guc_tables.c:2334 msgid "Sets the number of connection slots reserved for superusers." msgstr "スーパーユーザーによる接続用に予約される接続スロットの数を設定。" -#: utils/misc/guc_tables.c:2226 +#: utils/misc/guc_tables.c:2344 msgid "Sets the number of connection slots reserved for roles with privileges of pg_use_reserved_connections." msgstr "pg_use_reserved_connections権限を持つロールのために予約する接続スロットの数を設定。" -#: utils/misc/guc_tables.c:2237 +#: utils/misc/guc_tables.c:2355 msgid "Amount of dynamic shared memory reserved at startup." msgstr "起動時に予約される動的共有メモリの量。" -#: utils/misc/guc_tables.c:2252 +#: utils/misc/guc_tables.c:2370 msgid "Sets the number of shared memory buffers used by the server." msgstr "サーバーで使用される共有メモリのバッファ数を設定。" -#: utils/misc/guc_tables.c:2263 +#: utils/misc/guc_tables.c:2381 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "VACUUM, ANALYZE, および自動VACUUMで使用するバッファプールのサイズを設定します。" -#: utils/misc/guc_tables.c:2274 +#: utils/misc/guc_tables.c:2392 msgid "Shows the size of the server's main shared memory area (rounded up to the nearest MB)." msgstr "サーバーの主共有メモリ領域のサイズを表示します(MB単位に切り上げられます)" -#: utils/misc/guc_tables.c:2285 +#: utils/misc/guc_tables.c:2403 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "主共有メモリ領域に必要となるヒュージページの数を表示します。" -#: utils/misc/guc_tables.c:2286 -msgid "-1 indicates that the value could not be determined." -msgstr "-1はこの値が確定できなかったことを示します。" +#: utils/misc/guc_tables.c:2404 +msgid "-1 means huge pages are not supported." +msgstr "-1はヒュージページがサポートされていないことを示します。" + +#: utils/misc/guc_tables.c:2414 +msgid "Shows the number of semaphores required for the server." +msgstr "サーバーで必要となるセマフォの数を表示。" -#: utils/misc/guc_tables.c:2296 +#: utils/misc/guc_tables.c:2425 msgid "Sets the size of the dedicated buffer pool used for the commit timestamp cache." msgstr "コミットタイムスタンプのキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2297 utils/misc/guc_tables.c:2352 utils/misc/guc_tables.c:2363 -msgid "Specify 0 to have this value determined as a fraction of shared_buffers." -msgstr "0を指定するとこの値がshared_buffersに対する比率で決定されます。" +#: utils/misc/guc_tables.c:2426 utils/misc/guc_tables.c:2481 utils/misc/guc_tables.c:2492 +msgid "0 means use a fraction of \"shared_buffers\"." +msgstr "0で\"shared_buffers\"の一部を使用します。" -#: utils/misc/guc_tables.c:2307 +#: utils/misc/guc_tables.c:2436 msgid "Sets the size of the dedicated buffer pool used for the MultiXact member cache." msgstr "マルチトランザクションメンバーのキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2318 +#: utils/misc/guc_tables.c:2447 msgid "Sets the size of the dedicated buffer pool used for the MultiXact offset cache." msgstr "マルチトランザクションオフセットのキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2329 +#: utils/misc/guc_tables.c:2458 msgid "Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY message cache." msgstr "LISTEN/NOTIFYのメッセージキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2340 +#: utils/misc/guc_tables.c:2469 msgid "Sets the size of the dedicated buffer pool used for the serializable transaction cache." msgstr "直列化可能トランザクションのキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2351 -msgid "Sets the size of the dedicated buffer pool used for the sub-transaction cache." -msgstr "サブトランザクションのキャッシュで専有するバッファプールのサイズを設定する。" +#: utils/misc/guc_tables.c:2480 +msgid "Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "サブトランザクションキャッシュ専用のバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2362 +#: utils/misc/guc_tables.c:2491 msgid "Sets the size of the dedicated buffer pool used for the transaction status cache." msgstr "トランザクション状態のキャッシュで専有するバッファプールのサイズを設定する。" -#: utils/misc/guc_tables.c:2373 +#: utils/misc/guc_tables.c:2502 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "各セッションで使用される一時バッファの最大数を設定。" -#: utils/misc/guc_tables.c:2384 +#: utils/misc/guc_tables.c:2513 msgid "Sets the TCP port the server listens on." msgstr "サーバーが接続を監視するTCPポートを設定。" -#: utils/misc/guc_tables.c:2394 +#: utils/misc/guc_tables.c:2523 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Unixドメインソケットのアクセス権限を設定。" -#: utils/misc/guc_tables.c:2395 +#: utils/misc/guc_tables.c:2524 msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Unixドメインソケットは、通常のUnixファイルシステム権限の設定を使います。 このパラメータ値は chmod と umask システムコールが受け付ける数値のモード指定を想定しています(慣習的な8進数書式を使うためには、0(ゼロ)で始めなくてはなりません)。 " -#: utils/misc/guc_tables.c:2409 +#: utils/misc/guc_tables.c:2538 msgid "Sets the file permissions for log files." msgstr "ログファイルのパーミッションを設定。" -#: utils/misc/guc_tables.c:2410 +#: utils/misc/guc_tables.c:2539 msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "このパタメータ値は chmod や umask システムコールで使えるような数値モード指定であることが想定されます(慣習的な記法である8進数書式を使う場合は先頭に0(ゼロ) をつけてください)。 " -#: utils/misc/guc_tables.c:2424 +#: utils/misc/guc_tables.c:2553 msgid "Shows the mode of the data directory." msgstr "データディレクトリのモードを表示します。" -#: utils/misc/guc_tables.c:2425 +#: utils/misc/guc_tables.c:2554 msgid "The parameter value is a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "このパタメータ値は chmod や umask システムコールが受け付ける数値形式のモード指定です(慣習的な8進形式を使う場合は先頭に0(ゼロ) をつけてください)。 " -#: utils/misc/guc_tables.c:2438 +#: utils/misc/guc_tables.c:2567 msgid "Sets the maximum memory to be used for query workspaces." msgstr "問い合わせの作業用空間として使用されるメモリの最大値を設定。" -#: utils/misc/guc_tables.c:2439 +#: utils/misc/guc_tables.c:2568 msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files." msgstr "内部ソート操作とハッシュテーブルで使われるメモリの量がこの量に達した時に一時ディスクファイルへの切替えを行います。" -#: utils/misc/guc_tables.c:2451 +#: utils/misc/guc_tables.c:2585 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "保守作業で使用される最大メモリ量を設定。" -#: utils/misc/guc_tables.c:2452 +#: utils/misc/guc_tables.c:2586 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "VACUUMやCREATE INDEXなどの作業が含まれます。" -#: utils/misc/guc_tables.c:2462 +#: utils/misc/guc_tables.c:2596 msgid "Sets the maximum memory to be used for logical decoding." msgstr "論理デコーディングで使用するメモリ量の上限を設定します。" -#: utils/misc/guc_tables.c:2463 +#: utils/misc/guc_tables.c:2597 msgid "This much memory can be used by each internal reorder buffer before spilling to disk." msgstr "個々の内部リオーダバッファはディスクに書き出す前にこれだけの量のメモリを使用することができます。" -#: utils/misc/guc_tables.c:2479 +#: utils/misc/guc_tables.c:2613 msgid "Sets the maximum stack depth, in kilobytes." msgstr "スタック長の最大値をキロバイト単位で設定。" -#: utils/misc/guc_tables.c:2490 +#: utils/misc/guc_tables.c:2624 msgid "Limits the total size of all temporary files used by each process." msgstr "各プロセスで使用される全ての一時ファイルの合計サイズを制限します。" -#: utils/misc/guc_tables.c:2491 +#: utils/misc/guc_tables.c:2625 msgid "-1 means no limit." msgstr "-1は無制限を意味します。" -#: utils/misc/guc_tables.c:2501 +#: utils/misc/guc_tables.c:2635 msgid "Vacuum cost for a page found in the buffer cache." msgstr "バッファキャッシュにある1つのページをVACUUM処理する際のコスト。" -#: utils/misc/guc_tables.c:2511 +#: utils/misc/guc_tables.c:2645 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "バッファキャッシュにない1つのページをVACUUM処理する際のコスト。" -#: utils/misc/guc_tables.c:2521 +#: utils/misc/guc_tables.c:2655 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "VACUUM処理が1つのページをダーティにした際に課すコスト。" -#: utils/misc/guc_tables.c:2531 +#: utils/misc/guc_tables.c:2665 msgid "Vacuum cost amount available before napping." msgstr "VACUUM処理を一時休止させるまでに使用できるコスト。" -#: utils/misc/guc_tables.c:2541 +#: utils/misc/guc_tables.c:2675 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "自動VACUUM用のVACUUM処理を一時休止させるまでに使用できるコスト。" -#: utils/misc/guc_tables.c:2551 -msgid "Sets the maximum number of simultaneously open files for each server process." +#: utils/misc/guc_tables.c:2676 +msgid "-1 means use \"vacuum_cost_limit\"." +msgstr "-1で\"vacuum_cost_limit\"を使用します。" + +#: utils/misc/guc_tables.c:2685 +msgid "Sets the maximum number of files each server process is allowed to open simultaneously." msgstr "各サーバープロセスで同時にオープンできるファイルの最大数を設定。" -#: utils/misc/guc_tables.c:2564 +#: utils/misc/guc_tables.c:2698 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "同時に準備状態にできるトランザクションの最大数を設定。" -#: utils/misc/guc_tables.c:2575 +#: utils/misc/guc_tables.c:2709 msgid "Sets the minimum OID of tables for tracking locks." msgstr "ロックの追跡を行うテーブルの最小のOIDを設定。" -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2710 msgid "Is used to avoid output on system tables." msgstr "システムテーブルに関するの出力を避けるために使います。" -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2719 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "無条件でロックの追跡を行うテーブルのOIDを設定。" -#: utils/misc/guc_tables.c:2597 +#: utils/misc/guc_tables.c:2731 msgid "Sets the maximum allowed duration of any statement." msgstr "あらゆる文に対して実行時間として許容する上限値を設定。" -#: utils/misc/guc_tables.c:2598 utils/misc/guc_tables.c:2609 utils/misc/guc_tables.c:2620 utils/misc/guc_tables.c:2631 utils/misc/guc_tables.c:2642 -msgid "A value of 0 turns off the timeout." -msgstr "0でこのタイムアウトは無効になります。 " - -#: utils/misc/guc_tables.c:2608 +#: utils/misc/guc_tables.c:2742 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "ロックの待機の最大許容時間を設定。" -#: utils/misc/guc_tables.c:2619 +#: utils/misc/guc_tables.c:2753 msgid "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "問い合わせ間のアイドル時間のトランザクション内における最大許容値を設定。" -#: utils/misc/guc_tables.c:2630 +#: utils/misc/guc_tables.c:2764 msgid "Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)." msgstr "(準備済みトランザクションではない)セッション内のトランザクションの最大許容時間を設定。" -#: utils/misc/guc_tables.c:2641 +#: utils/misc/guc_tables.c:2775 msgid "Sets the maximum allowed idle time between queries, when not in a transaction." msgstr "問い合わせ間のアイドル時間のトランザクション外における最大許容値を設定。" -#: utils/misc/guc_tables.c:2652 +#: utils/misc/guc_tables.c:2786 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "VACUUM にテーブル行の凍結をさせる最小のトランザクションID差分。" -#: utils/misc/guc_tables.c:2662 +#: utils/misc/guc_tables.c:2796 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "行の凍結のためのテーブル全体スキャンを強制させる時のトランザクションID差分。" -#: utils/misc/guc_tables.c:2672 +#: utils/misc/guc_tables.c:2806 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "テーブル行でのマルチトランザクションIDの凍結を強制する最小のマルチトランザクション差分。" -#: utils/misc/guc_tables.c:2682 +#: utils/misc/guc_tables.c:2816 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "行の凍結のためにテーブル全体スキャンを強制する時点のマルチトランザクション差分。" -#: utils/misc/guc_tables.c:2692 +#: utils/misc/guc_tables.c:2826 msgid "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "VACUUMにおいて周回による停止を回避するためのフェイルセーフを実行されるまでの経過トランザクション数。" -#: utils/misc/guc_tables.c:2701 +#: utils/misc/guc_tables.c:2835 msgid "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "VACUUMにおいて周回による停止を回避するためのフェイルセーフが実行されるまでの経過マルチトランザクション数。" -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2848 msgid "Sets the maximum number of locks per transaction." msgstr "1トランザクション当たりのロック数の上限を設定。" -#: utils/misc/guc_tables.c:2715 +#: utils/misc/guc_tables.c:2849 msgid "The shared lock table is sized on the assumption that at most \"max_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." msgstr "共有ロックテーブルの大きさは、サーバープロセスまたは準備済みトランザクションごとに最大で\"max_locks_per_transaction\"個のオブジェクトが同時にロックされることを前提として決定されます。" -#: utils/misc/guc_tables.c:2726 +#: utils/misc/guc_tables.c:2860 msgid "Sets the maximum number of predicate locks per transaction." msgstr "1トランザクション当たりの述語ロック数の上限を設定。" -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2861 msgid "The shared predicate lock table is sized on the assumption that at most \"max_pred_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." msgstr "共有述語ロックテーブルの大きさは、サーバープロセスまたは準備済みトランザクションごとに最大で\"max_pred_locks_per_transaction\"個のオブジェクトが同時にロックされることを前提として決定されます。" -#: utils/misc/guc_tables.c:2738 +#: utils/misc/guc_tables.c:2872 msgid "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "1リレーション当たりで述語ロックされるページとタプルの数の上限値を設定。" -#: utils/misc/guc_tables.c:2739 +#: utils/misc/guc_tables.c:2873 msgid "If more than this total of pages and tuples in the same relation are locked by a connection, those locks are replaced by a relation-level lock." msgstr "あるコネクションで、同じリレーション内でロックされるページ数とタプル数の合計がこの値を超えたときには、これらのロックはリレーションレベルのロックに置き換えられます。" -#: utils/misc/guc_tables.c:2749 +#: utils/misc/guc_tables.c:2883 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "1ページあたりで述語ロックされるタプル数の上限値を設定。" -#: utils/misc/guc_tables.c:2750 +#: utils/misc/guc_tables.c:2884 msgid "If more than this number of tuples on the same page are locked by a connection, those locks are replaced by a page-level lock." msgstr "あるコネクションで 、同じページ上でロックされるタプルの数がこの値を超えたときには、これらのロックはページレベルのロックに置き換えられます。" -#: utils/misc/guc_tables.c:2760 +#: utils/misc/guc_tables.c:2894 msgid "Sets the maximum allowed time to complete client authentication." msgstr "クライアント認証の完了までの最大許容時間を設定。" -#: utils/misc/guc_tables.c:2772 +#: utils/misc/guc_tables.c:2906 msgid "Sets the amount of time to wait before authentication on connection startup." msgstr "接続開始時の認証前の待ち時間を設定します。" -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2918 msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." msgstr "LISTEN / NOTIFYキュー用に割り当てられるページ数の上限を設定。" -#: utils/misc/guc_tables.c:2794 +#: utils/misc/guc_tables.c:2928 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "リカバリ中のWAL先読みバッファのサイズ。" -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2929 msgid "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "参照先データブロックの先行読み込みのためのWAL先読みの最大量。" -#: utils/misc/guc_tables.c:2805 +#: utils/misc/guc_tables.c:2939 msgid "Sets the size of WAL files held for standby servers." msgstr "スタンバイサーバーのために確保するWALの量を設定します。" -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2950 msgid "Sets the minimum size to shrink the WAL to." msgstr "WALを縮小させる際の最小のサイズを設定。" -#: utils/misc/guc_tables.c:2828 +#: utils/misc/guc_tables.c:2962 msgid "Sets the WAL size that triggers a checkpoint." msgstr "チェックポイントの契機となるWALのサイズを指定。" -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2974 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "自動WALチェックポイントの最大間隔を設定。" -#: utils/misc/guc_tables.c:2851 +#: utils/misc/guc_tables.c:2985 msgid "Sets the maximum time before warning if checkpoints triggered by WAL volume happen too frequently." msgstr "WALの量契機のチェックポイントが高頻度で起きる場合に、警告を発するまでの回数を設定。" -#: utils/misc/guc_tables.c:2853 -msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. Zero turns off the warning." -msgstr "チェックポイントセグメントファイルを使い切ることが原因で起きるチェックポイントがこの時間間隔よりも頻繁に発生する場合、サーバーログにメッセージを書き出します。ゼロはこの警告を無効にします。 " +#: utils/misc/guc_tables.c:2987 +msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. 0 disables the warning." +msgstr "チェックポイントセグメントファイルを使い切ることが原因で起きるチェックポイントがこの時間間隔よりも頻繁に発生する場合、サーバーログにメッセージを書き出します。0でこの警告を無効にします。 " -#: utils/misc/guc_tables.c:2866 utils/misc/guc_tables.c:3084 utils/misc/guc_tables.c:3138 +#: utils/misc/guc_tables.c:3000 utils/misc/guc_tables.c:3230 utils/misc/guc_tables.c:3322 msgid "Number of pages after which previously performed writes are flushed to disk." msgstr "すでに実行された書き込みがディスクに書き出されるまでのページ数。" -#: utils/misc/guc_tables.c:2877 +#: utils/misc/guc_tables.c:3001 utils/misc/guc_tables.c:3231 utils/misc/guc_tables.c:3323 +msgid "0 disables forced writeback." +msgstr "0で強制ライトバックを無効にします。" + +#: utils/misc/guc_tables.c:3011 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "共有メモリ内に割り当てられた、WALデータ用のディスクページバッファ数を設定。" -#: utils/misc/guc_tables.c:2878 -msgid "Specify -1 to have this value determined as a fraction of shared_buffers." -msgstr "-1を指定するとこの値がshared_buffersに対する比率で決定されます。" +#: utils/misc/guc_tables.c:3012 +msgid "-1 means use a fraction of \"shared_buffers\"." +msgstr "-1で\"shared_buffers\"の一部を使用します。" -#: utils/misc/guc_tables.c:2888 +#: utils/misc/guc_tables.c:3022 msgid "Time between WAL flushes performed in the WAL writer." msgstr "WALライタで実行する書き出しの時間間隔。" -#: utils/misc/guc_tables.c:2899 +#: utils/misc/guc_tables.c:3033 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "書き出しが実行されるまでにWALライタで出力するWALの量。" -#: utils/misc/guc_tables.c:2910 +#: utils/misc/guc_tables.c:3044 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "WALを出力する代わりにfsyncを使用する新規ファイルの最小サイズ。" -#: utils/misc/guc_tables.c:2921 +#: utils/misc/guc_tables.c:3055 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "WAL送信プロセスの最大同時実行数を設定。" -#: utils/misc/guc_tables.c:2932 +#: utils/misc/guc_tables.c:3066 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "同時に定義できるレプリケーションスロットの数の最大値を設定。" -#: utils/misc/guc_tables.c:2942 +#: utils/misc/guc_tables.c:3076 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "レプリケーションスロットで確保できるWALの量の最大値を設定します。" -#: utils/misc/guc_tables.c:2943 -msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk." -msgstr "ディスク内のWALがこの量に達すると、レプリケーションスロットは停止とマークされ、セグメントは削除あるいは再利用のために解放されます。" +#: utils/misc/guc_tables.c:3077 +msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk. -1 means no maximum." +msgstr "ディスク内のWALがこの量に達すると、レプリケーションスロットは停止とマークされ、セグメントは削除あるいは再利用のために解放されます。-1で上限なしとなります。" -#: utils/misc/guc_tables.c:2955 +#: utils/misc/guc_tables.c:3089 msgid "Sets the maximum time to wait for WAL replication." msgstr "WALレプリケーションを待つ時間の最大値を設定。" -#: utils/misc/guc_tables.c:2966 +#: utils/misc/guc_tables.c:3100 +msgid "Sets the duration a replication slot can remain idle before it is invalidated." +msgstr "レプリケーションスロットが無効化されるまでのアイドル時間を設定。" + +#: utils/misc/guc_tables.c:3112 msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk." msgstr "トランザクションのコミットからWALのディスク書き出しまでの遅延時間をマイクロ秒単位で設定。" -#: utils/misc/guc_tables.c:2978 +#: utils/misc/guc_tables.c:3124 msgid "Sets the minimum number of concurrent open transactions required before performing \"commit_delay\"." msgstr "”commit_delay\"の実行に必要となる、同時に開いているトランザクション数の最小値を設定。" -#: utils/misc/guc_tables.c:2989 +#: utils/misc/guc_tables.c:3135 msgid "Sets the number of digits displayed for floating-point values." msgstr "浮動小数点値の表示桁数を設定。" -#: utils/misc/guc_tables.c:2990 +#: utils/misc/guc_tables.c:3136 msgid "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than zero selects precise output mode." msgstr "このパラメータは、real、double precision、幾何データ型に影響します。ゼロまたは負のパラメータ値は標準的な桁数(FLT_DIG もしくは DBL_DIGどちらか適切な方)に追加されます。正の値は直接出力形式を指定します。" -#: utils/misc/guc_tables.c:3002 -msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by log_statement_sample_rate." -msgstr "文がログに出力される最小の実行時間を設定します。サンプリングについてはlog_statement_sample_rateで決定されます。" +#: utils/misc/guc_tables.c:3148 +msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by \"log_statement_sample_rate\"." +msgstr "文がログ出力の対象となる最小の実行時間を設定します。サンプリングは\"log_statement_sample_rate\"で決定されます。" -#: utils/misc/guc_tables.c:3005 -msgid "Zero logs a sample of all queries. -1 turns this feature off." -msgstr "ゼロにすると全ての問い合わせを記録します。-1はこの機能を無効にします。" +#: utils/misc/guc_tables.c:3151 +msgid "-1 disables sampling. 0 means sample all statements." +msgstr "-1 でサンプリングを無効にします。0 はすべての文をサンプルすることを意味します。" -#: utils/misc/guc_tables.c:3015 +#: utils/misc/guc_tables.c:3161 msgid "Sets the minimum execution time above which all statements will be logged." msgstr "全ての文のログを記録する最小の実行時間を設定。" -#: utils/misc/guc_tables.c:3017 -msgid "Zero prints all queries. -1 turns this feature off." -msgstr "ゼロにすると全ての問い合わせを出力します。-1はこの機能を無効にします。" +#: utils/misc/guc_tables.c:3163 +msgid "-1 disables logging statement durations. 0 means log all statement durations." +msgstr "-1 で文の実行時間のログ出力を無効にします。0 はすべての文の実行時間を記録することを意味します。" -#: utils/misc/guc_tables.c:3027 +#: utils/misc/guc_tables.c:3173 msgid "Sets the minimum execution time above which autovacuum actions will be logged." msgstr "自動VACUUMの活動のログを記録する最小の実行時間を設定。" -#: utils/misc/guc_tables.c:3029 -msgid "Zero prints all actions. -1 turns autovacuum logging off." -msgstr "ゼロはすべての活動を出力します。-1は自動VACUUMのログ記録を無効にします。" +#: utils/misc/guc_tables.c:3175 +msgid "-1 disables logging autovacuum actions. 0 means log all autovacuum actions." +msgstr "-1 で自動VACUUMの実行ログ出力を無効にします。0 はすべての自動VACUUMの実行を記録することを意味します。" -#: utils/misc/guc_tables.c:3039 +#: utils/misc/guc_tables.c:3185 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements." msgstr "問い合わせ文をログ出力する際に、出力するbindパラメータ値データの最大バイト数を設定。" -#: utils/misc/guc_tables.c:3041 utils/misc/guc_tables.c:3053 -msgid "-1 to print values in full." -msgstr "-1 で値を全て出力します。" +#: utils/misc/guc_tables.c:3187 utils/misc/guc_tables.c:3199 +msgid "-1 means log values in full." +msgstr "-1 で値全体を出力します。" -#: utils/misc/guc_tables.c:3051 +#: utils/misc/guc_tables.c:3197 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements, on error." msgstr "エラー時の問い合わせ文をログ出力する際に、出力するbindパラメータ値データの最大バイト数を設定。" -#: utils/misc/guc_tables.c:3063 +#: utils/misc/guc_tables.c:3209 msgid "Background writer sleep time between rounds." msgstr "バックグランドライタの周期毎の待機時間" -#: utils/misc/guc_tables.c:3074 +#: utils/misc/guc_tables.c:3220 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "バックグランドライタが1周期で書き出すLRUページ数の最大値。" -#: utils/misc/guc_tables.c:3097 +#: utils/misc/guc_tables.c:3221 +msgid "0 disables background writing." +msgstr "0でバックグラウンド書き込みを無効にします。" + +#: utils/misc/guc_tables.c:3243 msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem." msgstr "ディスクサブシステムが効率的に処理可能な同時並行リクエスト数" -#: utils/misc/guc_tables.c:3111 +#: utils/misc/guc_tables.c:3244 utils/misc/guc_tables.c:3258 +msgid "0 disables simultaneous requests." +msgstr "0で同時並列リクエストを無効にします。" + +#: utils/misc/guc_tables.c:3257 msgid "A variant of \"effective_io_concurrency\" that is used for maintenance work." msgstr "保守作業に使用される\"effective_io_concurrency\"の亜種。" -#: utils/misc/guc_tables.c:3126 +#: utils/misc/guc_tables.c:3272 +msgid "Server-wide limit that clamps io_combine_limit." +msgstr "io_combine_limit の上限を制約する、サーバ全体の制限。" + +#: utils/misc/guc_tables.c:3286 msgid "Limit on the size of data reads and writes." msgstr "データの読み込みとか書き込みのサイズ制限" -#: utils/misc/guc_tables.c:3151 +#: utils/misc/guc_tables.c:3300 +msgid "Max number of IOs that one process can execute simultaneously." +msgstr "ひとつのプロセスが同時に実行できるIOの最大数。" + +#: utils/misc/guc_tables.c:3312 +msgid "Number of IO worker processes, for io_method=worker." +msgstr "io_method=worker の場合のIOワーカープロセス数。" + +#: utils/misc/guc_tables.c:3335 msgid "Maximum number of concurrent worker processes." msgstr "同時に実行されるワーカープロセス数の最大値です。" -#: utils/misc/guc_tables.c:3163 +#: utils/misc/guc_tables.c:3347 msgid "Maximum number of logical replication worker processes." msgstr "レプリケーションワーカープロセス数の最大値です。" -#: utils/misc/guc_tables.c:3175 +#: utils/misc/guc_tables.c:3359 msgid "Maximum number of table synchronization workers per subscription." msgstr "サブスクリプション毎のテーブル同期ワーカー数の最大値です。" -#: utils/misc/guc_tables.c:3187 +#: utils/misc/guc_tables.c:3371 msgid "Maximum number of parallel apply workers per subscription." msgstr "サブスクリプション毎のテーブル適用ワーカー数の最大値です。" -#: utils/misc/guc_tables.c:3197 +#: utils/misc/guc_tables.c:3383 +msgid "Sets the maximum number of active replication origins." +msgstr "有効なレプリケーション起源の最大数を設定します。" + +#: utils/misc/guc_tables.c:3393 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "ログファイルのローテーションを行う時間間隔を設定します。" -#: utils/misc/guc_tables.c:3209 +#: utils/misc/guc_tables.c:3395 +msgid "0 disables time-based creation of new log files." +msgstr "0で時間ベースでのログファイル作成を無効にします。" + +#: utils/misc/guc_tables.c:3405 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "ローテートされるまでに許容するログファイルの最大サイズを設定します。" -#: utils/misc/guc_tables.c:3221 +#: utils/misc/guc_tables.c:3407 +msgid "0 disables size-based creation of new log files." +msgstr "0でサイズベースでのログファイル作成を無効にします。" + +#: utils/misc/guc_tables.c:3417 msgid "Shows the maximum number of function arguments." msgstr "関数の引数の最大数を示します。" -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3428 msgid "Shows the maximum number of index keys." msgstr "インデックスキーの最大数を示します。" -#: utils/misc/guc_tables.c:3243 +#: utils/misc/guc_tables.c:3439 msgid "Shows the maximum identifier length." msgstr "識別子の最大長を示します。" -#: utils/misc/guc_tables.c:3254 +#: utils/misc/guc_tables.c:3450 msgid "Shows the size of a disk block." msgstr "ディスクブロックサイズを示します。" -#: utils/misc/guc_tables.c:3265 +#: utils/misc/guc_tables.c:3461 msgid "Shows the number of pages per disk file." msgstr "ディスクファイルごとのページ数を表示します。" -#: utils/misc/guc_tables.c:3276 +#: utils/misc/guc_tables.c:3472 msgid "Shows the block size in the write ahead log." msgstr "先行書き込みログ(WAL)におけるブロックサイズを表示します" -#: utils/misc/guc_tables.c:3287 +#: utils/misc/guc_tables.c:3483 msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "WALの取り出しの失敗後に再試行する回数を設定。" -#: utils/misc/guc_tables.c:3299 +#: utils/misc/guc_tables.c:3495 msgid "Shows the size of write ahead log segments." msgstr "先行書き込みログ(WAL)セグメントのサイズを表示します" -#: utils/misc/guc_tables.c:3312 +#: utils/misc/guc_tables.c:3508 msgid "Time for which WAL summary files should be kept." msgstr "WAL集約ファイルを保持する時間。" -#: utils/misc/guc_tables.c:3325 +#: utils/misc/guc_tables.c:3509 +msgid "0 disables automatic summary file deletion." +msgstr "0で集約ファイルの自動削除を無効にします。" + +#: utils/misc/guc_tables.c:3521 msgid "Time to sleep between autovacuum runs." msgstr "自動VACUUMの実行開始間隔。" -#: utils/misc/guc_tables.c:3335 +#: utils/misc/guc_tables.c:3531 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "VACUUMを行うまでの、タプルを更新または削除した回数の最小値。" -#: utils/misc/guc_tables.c:3344 -msgid "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums." -msgstr "VACUUMが行われるまでの行挿入の回数の最小値、-1で挿入契機のVACUUMを無効化します。" +#: utils/misc/guc_tables.c:3540 +msgid "Maximum number of tuple updates or deletes prior to vacuum." +msgstr "VACUUMを行うまでの、タプルを更新または削除した回数の最大値。" + +#: utils/misc/guc_tables.c:3541 +msgid "-1 disables the maximum threshold." +msgstr "-1で上限を無効にします。" + +#: utils/misc/guc_tables.c:3549 +msgid "Minimum number of tuple inserts prior to vacuum." +msgstr "VACUUMを行うまでの、タプルを挿入した回数の最小値。" -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3550 +msgid "-1 disables insert vacuums." +msgstr "-1で挿入契機のVACUUMを無効にします。" + +#: utils/misc/guc_tables.c:3558 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "ANALYZEが実行されるまでの、タプルを挿入、更新、削除した回数の最小値。" -#: utils/misc/guc_tables.c:3363 +#: utils/misc/guc_tables.c:3568 msgid "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "トランザクションID周回を防ぐためにテーブルを自動VACUUMする時点のトランザクションID差分。" -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3580 msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "マルチトランザクション周回を防止するためにテーブルを自動VACUUMする、マルチトランザクション差分。" -#: utils/misc/guc_tables.c:3385 +#: utils/misc/guc_tables.c:3590 +msgid "Sets the number of backend slots to allocate for autovacuum workers." +msgstr "自動VACUUMプロセスに割り当てるバックエンドスロット数を設定。" + +#: utils/misc/guc_tables.c:3599 msgid "Sets the maximum number of simultaneously running autovacuum worker processes." msgstr "自動VACUUMのワーカープロセスの最大同時実行数を設定。" -#: utils/misc/guc_tables.c:3395 +#: utils/misc/guc_tables.c:3609 msgid "Sets the maximum number of parallel processes per maintenance operation." msgstr "ひとつの保守作業に割り当てる並列処理プロセスの数の最大値を設定。" -#: utils/misc/guc_tables.c:3405 +#: utils/misc/guc_tables.c:3619 msgid "Sets the maximum number of parallel processes per executor node." msgstr "エグゼキュータノードあたりの並列処理プロセスの数の最大値を設定。" -#: utils/misc/guc_tables.c:3416 +#: utils/misc/guc_tables.c:3630 msgid "Sets the maximum number of parallel workers that can be active at one time." msgstr "同時に活動可能な並列処理ワーカーの数の最大値を設定。" -#: utils/misc/guc_tables.c:3427 +#: utils/misc/guc_tables.c:3641 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "自動VACUUMプロセスで使用するメモリ量の最大値を設定。" -#: utils/misc/guc_tables.c:3438 +#: utils/misc/guc_tables.c:3642 +msgid "-1 means use \"maintenance_work_mem\"." +msgstr "-1で\"maintenance_work_mem\"を使用します。" + +#: utils/misc/guc_tables.c:3652 msgid "Time between issuing TCP keepalives." msgstr "TCPキープアライブを発行する時間間隔。" -#: utils/misc/guc_tables.c:3439 utils/misc/guc_tables.c:3450 utils/misc/guc_tables.c:3574 -msgid "A value of 0 uses the system default." -msgstr "0でシステムのデフォルトを使用します。" +#: utils/misc/guc_tables.c:3653 utils/misc/guc_tables.c:3664 utils/misc/guc_tables.c:3787 utils/misc/guc_tables.c:3798 +msgid "0 means use the system default." +msgstr "0でシステムのデフォルト値を使用します。" -#: utils/misc/guc_tables.c:3449 +#: utils/misc/guc_tables.c:3663 msgid "Time between TCP keepalive retransmits." msgstr "TCPキープアライブの再送信の時間間隔。" -#: utils/misc/guc_tables.c:3460 +#: utils/misc/guc_tables.c:3674 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "SSLの再ネゴシエーションは今後サポートされません; 0のみに設定可能です。" -#: utils/misc/guc_tables.c:3471 +#: utils/misc/guc_tables.c:3685 msgid "Maximum number of TCP keepalive retransmits." msgstr "TCPキープアライブの再送信回数の最大値です。" -#: utils/misc/guc_tables.c:3472 -msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default." -msgstr "接続が失われると判断するまでに再送信される、ひとつづきのキープアライブの数。0の場合はシステムのデフォルトを使用します。" +#: utils/misc/guc_tables.c:3686 +msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. 0 means use the system default." +msgstr "接続が失われると判断するまでに再送信される、ひとつづきのキープアライブの数。0でシステムのデフォルト値を使用します。" -#: utils/misc/guc_tables.c:3483 +#: utils/misc/guc_tables.c:3697 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "GINによる正確な検索に対して許容する結果数の最大値を設定。" -#: utils/misc/guc_tables.c:3494 +#: utils/misc/guc_tables.c:3698 +msgid "0 means no limit." +msgstr "0は無制限を意味します。" + +#: utils/misc/guc_tables.c:3707 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "プランナが想定するデータキャッシュ全体のサイズを設定。" -#: utils/misc/guc_tables.c:3495 +#: utils/misc/guc_tables.c:3708 msgid "That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each." msgstr "つまり、PostgreSQLのデータファイルに対して使用されるキャッシュ(カーネルキャッシュおよび共有バッファ)全体の量です。これは通常8KBのディスクページを単位とします。" -#: utils/misc/guc_tables.c:3506 +#: utils/misc/guc_tables.c:3719 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "並列スキャンを検討するテーブルデータの量の最小値を設定。" -#: utils/misc/guc_tables.c:3507 +#: utils/misc/guc_tables.c:3720 msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered." msgstr "この限度に到達できないような少ないテーブルページ数しか読み取らないとプランナが見積もった場合、並列スキャンは検討されません。" -#: utils/misc/guc_tables.c:3517 +#: utils/misc/guc_tables.c:3730 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "並列スキャンを検討するインデックスデータの量の最小値を設定。" -#: utils/misc/guc_tables.c:3518 +#: utils/misc/guc_tables.c:3731 msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered." msgstr "この限度に到達できないような少ないページ数しか読み取らないとプランナが見積もった場合、並列スキャンは検討されません。" -#: utils/misc/guc_tables.c:3529 +#: utils/misc/guc_tables.c:3742 msgid "Shows the server version as an integer." msgstr "サーバーのバージョンを整数値で表示します。" -#: utils/misc/guc_tables.c:3540 +#: utils/misc/guc_tables.c:3753 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "このキロバイト数よりも大きな一時ファイルの使用をログに記録します。" -#: utils/misc/guc_tables.c:3541 -msgid "Zero logs all files. The default is -1 (turning this feature off)." -msgstr "ゼロにすると、全てのファイルを記録します。デフォルトは-1です(この機能を無効にします)。" +#: utils/misc/guc_tables.c:3754 +msgid "-1 disables logging temporary files. 0 means log all temporary files." +msgstr "-1で一時ファイルのログへの記録を無効にします。0ですべての一時ファイルをログに記録します。" -#: utils/misc/guc_tables.c:3551 +#: utils/misc/guc_tables.c:3764 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "pg_stat_activity.queryのために予約するサイズをバイト単位で設定。" -#: utils/misc/guc_tables.c:3562 +#: utils/misc/guc_tables.c:3775 msgid "Sets the maximum size of the pending list for GIN index." msgstr "GINインデックスの保留リストの最大サイズを設定。" -#: utils/misc/guc_tables.c:3573 +#: utils/misc/guc_tables.c:3786 msgid "TCP user timeout." msgstr "TCPユーザータイムアウト。" -#: utils/misc/guc_tables.c:3584 +#: utils/misc/guc_tables.c:3797 msgid "The size of huge page that should be requested." msgstr "要求が見込まれるヒュージページのサイズ。" -#: utils/misc/guc_tables.c:3595 +#: utils/misc/guc_tables.c:3808 msgid "Aggressively flush system caches for debugging purposes." msgstr "デバッグ目的のために積極的にシステムキャッシュを消去する。" -#: utils/misc/guc_tables.c:3618 +#: utils/misc/guc_tables.c:3809 +msgid "0 means use normal caching behavior." +msgstr "0で通常のキャッシュ動作を行います。" + +#: utils/misc/guc_tables.c:3831 msgid "Sets the time interval between checks for disconnection while running queries." msgstr "問い合わせ実行中に接続確認を行う時間間隔を設定します。" -#: utils/misc/guc_tables.c:3629 +#: utils/misc/guc_tables.c:3832 +msgid "0 disables connection checks." +msgstr "0で接続チェックを無効にします。" + +#: utils/misc/guc_tables.c:3842 msgid "Time between progress updates for long-running startup operations." msgstr "起動処理が長引いた際のステータス更新の時間間隔。" -#: utils/misc/guc_tables.c:3631 -msgid "0 turns this feature off." -msgstr "ゼロにするとこの機能を無効にします。" +#: utils/misc/guc_tables.c:3844 +msgid "0 disables progress updates." +msgstr "0で進捗情報の更新を無効にします。" -#: utils/misc/guc_tables.c:3641 +#: utils/misc/guc_tables.c:3854 msgid "Sets the iteration count for SCRAM secret generation." msgstr "SCRAMシークレット生成の際の反復回数を設定。" -#: utils/misc/guc_tables.c:3661 +#: utils/misc/guc_tables.c:3874 msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "ひと続きに読み込むディスクページについてプランナで使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3672 +#: utils/misc/guc_tables.c:3885 msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page." msgstr "ひと続きでは読み込めないディスクページについてプランナで使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3683 +#: utils/misc/guc_tables.c:3896 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "一つのタプル(行)の処理についてプランナで使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3694 +#: utils/misc/guc_tables.c:3907 msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan." msgstr "インデックススキャンにおける一つのインデックスエントリの処理についてプランナで使用する見積もりコストを設定。 " -#: utils/misc/guc_tables.c:3705 +#: utils/misc/guc_tables.c:3918 msgid "Sets the planner's estimate of the cost of processing each operator or function call." msgstr "一つの演算子または関数の処理についてプランナで使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3716 +#: utils/misc/guc_tables.c:3929 msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to leader backend." msgstr "並列処理ワーカーからリーダーバックエンドへの一つのタプル(行)の受け渡しについてプランナが使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3727 +#: utils/misc/guc_tables.c:3940 msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query." msgstr "並列問い合わせ実行のためのワーカープロセスの起動についてプランナで使用する見積もりコストを設定。" -#: utils/misc/guc_tables.c:3739 +#: utils/misc/guc_tables.c:3952 msgid "Perform JIT compilation if query is more expensive." msgstr "問い合わせがこの値より高コストであればJITコンパイルを実行します。" -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3953 msgid "-1 disables JIT compilation." msgstr "-1 でJITコンパイルを禁止します。" -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3963 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "問い合わせがこの値より高コストであればJITコンパイルされた関数を最適化します。" -#: utils/misc/guc_tables.c:3751 +#: utils/misc/guc_tables.c:3964 msgid "-1 disables optimization." msgstr "-1で最適化を行わなくなります。" -#: utils/misc/guc_tables.c:3761 +#: utils/misc/guc_tables.c:3974 msgid "Perform JIT inlining if query is more expensive." msgstr "問い合わせがこの値より高コストであればJITコンパイルされた関数をインライン化します。" -#: utils/misc/guc_tables.c:3762 +#: utils/misc/guc_tables.c:3975 msgid "-1 disables inlining." msgstr "-1 でインライン化を禁止します。" -#: utils/misc/guc_tables.c:3772 +#: utils/misc/guc_tables.c:3985 msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." msgstr "カーソルから取り出される行数の全行に対する割合についてプランナで使用する値を設定。" -#: utils/misc/guc_tables.c:3784 +#: utils/misc/guc_tables.c:3997 msgid "Sets the planner's estimate of the average size of a recursive query's working table." msgstr "再帰問い合わせでプランナが使用する中間テーブルの平均見積もりサイズを設定します。" -#: utils/misc/guc_tables.c:3796 +#: utils/misc/guc_tables.c:4009 msgid "GEQO: selective pressure within the population." msgstr "GEQO: 集合内の選択圧力。" -#: utils/misc/guc_tables.c:3807 +#: utils/misc/guc_tables.c:4020 msgid "GEQO: seed for random path selection." msgstr "GEQO: ランダムパス選択用のシード" -#: utils/misc/guc_tables.c:3818 +#: utils/misc/guc_tables.c:4031 msgid "Multiple of \"work_mem\" to use for hash tables." msgstr "ハッシュテーブルで使用する\"work_mem\"に対する倍率。" -#: utils/misc/guc_tables.c:3829 +#: utils/misc/guc_tables.c:4042 msgid "Multiple of the average buffer usage to free per round." msgstr "周期ごとに解放するバッファ数の平均バッファ使用量に対する倍数" -#: utils/misc/guc_tables.c:3839 +#: utils/misc/guc_tables.c:4052 msgid "Sets the seed for random-number generation." msgstr "乱数生成用のシードを設定。" -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:4063 msgid "Vacuum cost delay in milliseconds." msgstr "ミリ秒単位のコストベースのVACUUM処理の遅延時間です。" -#: utils/misc/guc_tables.c:3861 +#: utils/misc/guc_tables.c:4074 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "自動VACUUM用のミリ秒単位のコストベースのVACUUM処理の遅延時間です。" -#: utils/misc/guc_tables.c:3872 +#: utils/misc/guc_tables.c:4075 +msgid "-1 means use \"vacuum_cost_delay\"." +msgstr "-1で\"vacuum_cost_delay\"を使用します。" + +#: utils/misc/guc_tables.c:4085 msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples." msgstr "VACUUMが実行されるまでのタプルの更新または削除回数のreltuplesに対する割合。" -#: utils/misc/guc_tables.c:3882 +#: utils/misc/guc_tables.c:4095 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "VACUUMが実行されるまでのタプルの挿入行数のreltuplesに対する割合。" -#: utils/misc/guc_tables.c:3892 +#: utils/misc/guc_tables.c:4105 msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples." msgstr "ANALYZEが実行されるまでのタプルの更新または削除回数のreltuplesに対する割合。" -#: utils/misc/guc_tables.c:3902 +#: utils/misc/guc_tables.c:4115 msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval." msgstr "チェックポイント中にダーティバッファの書き出しに使う時間のチェックポイント間隔に対する割合。" -#: utils/misc/guc_tables.c:3912 +#: utils/misc/guc_tables.c:4125 msgid "Fraction of statements exceeding \"log_min_duration_sample\" to be logged." msgstr "\"log_min_duration_sample\"を超過した文のうちログ出力を行う割合。" -#: utils/misc/guc_tables.c:3913 +#: utils/misc/guc_tables.c:4126 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "0.0(ログ出力しない)から1.0(すべてログ出力する)の間の値を指定してください。" -#: utils/misc/guc_tables.c:3922 +#: utils/misc/guc_tables.c:4135 msgid "Sets the fraction of transactions from which to log all statements." msgstr "すべての文をログ出力するトランザクションの割合を設定します。" -#: utils/misc/guc_tables.c:3923 +#: utils/misc/guc_tables.c:4136 msgid "Use a value between 0.0 (never log) and 1.0 (log all statements for all transactions)." msgstr "0.0 (ログ出力しない)から 1.0 (全てのトランザクションの全ての文をログ出力する)の間の値を指定してください。" +#: utils/misc/guc_tables.c:4146 +msgid "Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning." +msgstr "VACUUMが貪欲スキャンを無効にする前にスキャンできるページ数の、リレーション全体に対する割合" + +#: utils/misc/guc_tables.c:4147 +msgid "A value of 0.0 disables eager scanning and a value of 1.0 will eagerly scan up to 100 percent of the all-visible pages in the relation. If vacuum successfully freezes these pages, the cap is lower than 100 percent, because the goal is to amortize page freezing across multiple vacuums." +msgstr "0.0で貪欲スキャンを無効にし、1.0ではリレーション内の全可視ページを最大100%まで貪欲にスキャンします。ページの凍結を複数回のVACUUMに分散させることを目的としているため、VACUUMがスキャンしたページの凍結に成功した場合には、この上限は100%を下回ることがあります。" + # hoge -#: utils/misc/guc_tables.c:3942 +#: utils/misc/guc_tables.c:4165 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "WALファイルの保管のために呼び出されるシェルスクリプトを設定。" -#: utils/misc/guc_tables.c:3943 -msgid "This is used only if \"archive_library\" is not set." -msgstr "これは\"archive_library\"の設定がされていない場合にのみ使用されます。" +#: utils/misc/guc_tables.c:4166 +msgid "An empty string means use \"archive_library\"." +msgstr "空文字列で”archive_library\"を使用します。" # hoge -#: utils/misc/guc_tables.c:3952 +#: utils/misc/guc_tables.c:4175 msgid "Sets the library that will be called to archive a WAL file." msgstr "WALファイルのアーカイブのために呼び出すライブラリを設定します。" -#: utils/misc/guc_tables.c:3953 -msgid "An empty string indicates that \"archive_command\" should be used." -msgstr "空文字列は\"archive_command\"の使用を指示します。" +#: utils/misc/guc_tables.c:4176 +msgid "An empty string means use \"archive_command\"." +msgstr "空文字列で\"archive_command\"を使用します。" # hoge -#: utils/misc/guc_tables.c:3962 +#: utils/misc/guc_tables.c:4185 msgid "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "アーカイブされたWALファイルを取り出すために呼び出すシェルコマンドを設定します。" # hoge -#: utils/misc/guc_tables.c:3972 +#: utils/misc/guc_tables.c:4195 msgid "Sets the shell command that will be executed at every restart point." msgstr "リスタートポイントの時に実行するシェルコマンドを設定。" # hoge -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4205 msgid "Sets the shell command that will be executed once at the end of recovery." msgstr "リカバリ終了時に1度だけ実行されるシェルコマンドを設定。" -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4215 msgid "Specifies the timeline to recover into." msgstr "リカバリの目標タイムラインを指定します。" -#: utils/misc/guc_tables.c:4002 +#: utils/misc/guc_tables.c:4225 msgid "Set to \"immediate\" to end recovery as soon as a consistent state is reached." msgstr "\"immediate\"を指定すると一貫性が確保できた時点でリカバリを終了します。" -#: utils/misc/guc_tables.c:4011 +#: utils/misc/guc_tables.c:4234 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "リカバリを指定したトランザクションIDまで進めます。" -#: utils/misc/guc_tables.c:4020 +#: utils/misc/guc_tables.c:4243 msgid "Sets the time stamp up to which recovery will proceed." msgstr "リカバリを指定したタイムスタンプの時刻まで進めます。" -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4252 msgid "Sets the named restore point up to which recovery will proceed." msgstr "リカバリを指定した名前のリストアポイントまで進めます。" -#: utils/misc/guc_tables.c:4038 +#: utils/misc/guc_tables.c:4261 msgid "Sets the LSN of the write-ahead log location up to which recovery will proceed." msgstr "リカバリを先行書き込みログの指定したLSNまで進めます。" -#: utils/misc/guc_tables.c:4048 +#: utils/misc/guc_tables.c:4271 msgid "Sets the connection string to be used to connect to the sending server." msgstr "送出側サーバーへの接続に使用する接続文字列をしています。" -#: utils/misc/guc_tables.c:4059 +#: utils/misc/guc_tables.c:4282 msgid "Sets the name of the replication slot to use on the sending server." msgstr "送出サーバーで使用するレプリケーションスロットの名前を設定。" -#: utils/misc/guc_tables.c:4069 +#: utils/misc/guc_tables.c:4292 msgid "Sets the client's character set encoding." msgstr "クライアントの文字集合の符号化方式を設定。" -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4303 msgid "Controls information prefixed to each log line." msgstr "各ログ行の前に付ける情報を制御します。" -#: utils/misc/guc_tables.c:4081 -msgid "If blank, no prefix is used." -msgstr "もし空であればなにも付加しません。" +#: utils/misc/guc_tables.c:4304 +msgid "An empty string means no prefix." +msgstr "空文字列で何も付加しません。" -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4313 msgid "Sets the time zone to use in log messages." msgstr "ログメッセージ使用するタイムゾーンを設定。" -#: utils/misc/guc_tables.c:4100 +#: utils/misc/guc_tables.c:4323 msgid "Sets the display format for date and time values." msgstr "日付時刻値の表示用書式を設定。" -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4324 msgid "Also controls interpretation of ambiguous date inputs." msgstr "曖昧な日付の入力の解釈も制御します。" -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4335 msgid "Sets the default table access method for new tables." msgstr "新規テーブルで使用されるデフォルトテーブルアクセスメソッドを設定。" -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4346 msgid "Sets the default tablespace to create tables and indexes in." msgstr "テーブルとインデックスの作成先となるデフォルトのテーブル空間を設定。" -#: utils/misc/guc_tables.c:4124 -msgid "An empty string selects the database's default tablespace." -msgstr "空文字列はデータベースのデフォルトのテーブル空間を選択します。" +#: utils/misc/guc_tables.c:4347 utils/misc/guc_tables.c:4358 +msgid "An empty string means use the database's default tablespace." +msgstr "空文字列でデータベースのデフォルトのテーブル空間を使用します。" -#: utils/misc/guc_tables.c:4134 +#: utils/misc/guc_tables.c:4357 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "一時テーブルとファイルのソートで使用されるテーブル空間を設定。" -#: utils/misc/guc_tables.c:4145 +#: utils/misc/guc_tables.c:4368 msgid "Sets whether a CREATEROLE user automatically grants the role to themselves, and with which options." msgstr "CREATEROLEを持つユーザーが自動的にそのロールを自身にGRANTするかどうかを対象となるオプションとともに設定します" -#: utils/misc/guc_tables.c:4157 +#: utils/misc/guc_tables.c:4370 +msgid "An empty string disables automatic self grants." +msgstr "空文字列で自動の自己権限付与を無効にします。" + +#: utils/misc/guc_tables.c:4380 msgid "Sets the path for dynamically loadable modules." msgstr "動的ロード可能モジュールのパスを設定。" -#: utils/misc/guc_tables.c:4158 +#: utils/misc/guc_tables.c:4381 msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file." msgstr "オープンする必要がある動的ロード可能なモジュールについて、指定されたファイル名にディレクトリ要素がない(つまり、名前にスラッシュが含まれない)場合、システムは指定されたファイルをこのパスから検索します。 " -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4394 +msgid "Sets the path for extension control files." +msgstr "機能拡張制御ファイルのパスを設定。" + +#: utils/misc/guc_tables.c:4395 +msgid "The remaining extension script and secondary control files are then loaded from the same directory where the primary control file was found." +msgstr "残りの機能拡張スクリプトと二次制御ファイルは、主制御ファイルと同じディレクトリから読み込まれます。" + +#: utils/misc/guc_tables.c:4406 msgid "Sets the location of the Kerberos server key file." msgstr "Kerberosサーバーキーファイルの場所を設定。" -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4417 msgid "Sets the Bonjour service name." msgstr "Bonjour サービス名を設定。" -#: utils/misc/guc_tables.c:4192 +#: utils/misc/guc_tables.c:4418 +msgid "An empty string means use the computer name." +msgstr "空文字列でコンピューター名を使用します。" + +#: utils/misc/guc_tables.c:4427 msgid "Sets the language in which messages are displayed." msgstr "表示用メッセージの言語を設定。" -#: utils/misc/guc_tables.c:4202 +#: utils/misc/guc_tables.c:4428 utils/misc/guc_tables.c:4438 utils/misc/guc_tables.c:4448 utils/misc/guc_tables.c:4458 +msgid "An empty string means use the operating system setting." +msgstr "空文字列でオペレーティングシステムの設定を使用します。" + +#: utils/misc/guc_tables.c:4437 msgid "Sets the locale for formatting monetary amounts." msgstr "通貨書式で使用するロケールを設定。 " -#: utils/misc/guc_tables.c:4212 +#: utils/misc/guc_tables.c:4447 msgid "Sets the locale for formatting numbers." msgstr "数字の書式で使用するロケールを設定。" -#: utils/misc/guc_tables.c:4222 +#: utils/misc/guc_tables.c:4457 msgid "Sets the locale for formatting date and time values." msgstr "日付と時間の書式で使用するロケールを設定。" -#: utils/misc/guc_tables.c:4232 +#: utils/misc/guc_tables.c:4467 msgid "Lists shared libraries to preload into each backend." msgstr "各バックエンドに事前ロードする共有ライブラリを列挙します。" -#: utils/misc/guc_tables.c:4243 +#: utils/misc/guc_tables.c:4478 msgid "Lists shared libraries to preload into server." msgstr "サーバーに事前ロードする共有ライブラリを列挙します。" -#: utils/misc/guc_tables.c:4254 +#: utils/misc/guc_tables.c:4489 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "各バックエンドに事前読み込みする非特権共有ライブラリを列挙します。" -#: utils/misc/guc_tables.c:4265 +#: utils/misc/guc_tables.c:4500 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "スキーマ部を含まない名前に対するスキーマの検索順を設定。" -#: utils/misc/guc_tables.c:4277 +#: utils/misc/guc_tables.c:4512 msgid "Shows the server (database) character set encoding." msgstr "サーバー(データベース)文字セット符号化方式を表示します。" -#: utils/misc/guc_tables.c:4289 +#: utils/misc/guc_tables.c:4524 msgid "Shows the server version." msgstr "サーバーのバージョンを表示します。" -#: utils/misc/guc_tables.c:4301 +#: utils/misc/guc_tables.c:4536 msgid "Sets the current role." msgstr "現在のロールを設定。" -#: utils/misc/guc_tables.c:4313 +#: utils/misc/guc_tables.c:4548 msgid "Sets the session user name." msgstr "セッションユーザー名を設定。" -#: utils/misc/guc_tables.c:4324 +#: utils/misc/guc_tables.c:4559 msgid "Sets the destination for server log output." msgstr "サーバーログの出力先を設定。" -#: utils/misc/guc_tables.c:4325 +#: utils/misc/guc_tables.c:4560 msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", and \"eventlog\", depending on the platform." msgstr "有効な値は、プラットフォームに依存しますが\"stderr\"、\"syslog\"、\"csvlog\"、\"jsonlog\"そして\"eventlog\"の組み合わせです。" -#: utils/misc/guc_tables.c:4336 +#: utils/misc/guc_tables.c:4571 msgid "Sets the destination directory for log files." msgstr "ログファイルの格納ディレクトリを設定。" -#: utils/misc/guc_tables.c:4337 +#: utils/misc/guc_tables.c:4572 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "データディレクトリからの相対パスでも絶対パスでも指定できます" -#: utils/misc/guc_tables.c:4347 +#: utils/misc/guc_tables.c:4582 msgid "Sets the file name pattern for log files." msgstr "ログファイルのファイル名パターンを設定。" -#: utils/misc/guc_tables.c:4358 +#: utils/misc/guc_tables.c:4593 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "syslog内でPostgreSQLのメッセージを識別するために使用されるプログラム名を設定。" -#: utils/misc/guc_tables.c:4369 +#: utils/misc/guc_tables.c:4604 msgid "Sets the application name used to identify PostgreSQL messages in the event log." msgstr "イベントログ内でPostgreSQLのメッセージを識別するために使用されるアプリケーション名を設定。" -#: utils/misc/guc_tables.c:4380 +#: utils/misc/guc_tables.c:4615 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "タイムスタンプの表示と解釈に使用するタイムゾーンを設定。" -#: utils/misc/guc_tables.c:4390 +#: utils/misc/guc_tables.c:4625 msgid "Selects a file of time zone abbreviations." msgstr "タイムゾーン省略形用のファイルを選択します。" -#: utils/misc/guc_tables.c:4400 +#: utils/misc/guc_tables.c:4635 msgid "Sets the owning group of the Unix-domain socket." msgstr "Unixドメインソケットを所有するグループを設定。" -#: utils/misc/guc_tables.c:4401 -msgid "The owning user of the socket is always the user that starts the server." -msgstr "ソケットを所有するユーザーは常にサーバーを開始したユーザーです。" +#: utils/misc/guc_tables.c:4636 +msgid "The owning user of the socket is always the user that starts the server. An empty string means use the user's default group." +msgstr "ソケットを所有するユーザーは常にサーバーを開始したユーザーです。空文字列でユーザのデフォルトグループを使用します。" -#: utils/misc/guc_tables.c:4411 +#: utils/misc/guc_tables.c:4646 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "Unixドメインソケットの作成先ディレクトリを設定。" -#: utils/misc/guc_tables.c:4422 +#: utils/misc/guc_tables.c:4657 msgid "Sets the host name or IP address(es) to listen to." msgstr "接続を監視するホスト名またはIPアドレスを設定。" -#: utils/misc/guc_tables.c:4437 +#: utils/misc/guc_tables.c:4672 msgid "Sets the server's data directory." msgstr "サーバーのデータディレクトリを設定。" -#: utils/misc/guc_tables.c:4448 +#: utils/misc/guc_tables.c:4683 msgid "Sets the server's main configuration file." msgstr "サーバーのメイン設定ファイルを設定。" -#: utils/misc/guc_tables.c:4459 +#: utils/misc/guc_tables.c:4694 msgid "Sets the server's \"hba\" configuration file." msgstr "サーバーの\"hba\"設定ファイルを設定。" -#: utils/misc/guc_tables.c:4470 +#: utils/misc/guc_tables.c:4705 msgid "Sets the server's \"ident\" configuration file." msgstr "サーバーの\"ident\"設定ファイルを設定。" -#: utils/misc/guc_tables.c:4481 +#: utils/misc/guc_tables.c:4716 msgid "Writes the postmaster PID to the specified file." msgstr "postmasterのPIDを指定したファイルに書き込みます。" -#: utils/misc/guc_tables.c:4492 +#: utils/misc/guc_tables.c:4727 msgid "Shows the name of the SSL library." msgstr "SSLライブラリの名前を表示します。" -#: utils/misc/guc_tables.c:4507 +#: utils/misc/guc_tables.c:4742 msgid "Location of the SSL server certificate file." msgstr "SSLサーバー証明書ファイルの場所です" -#: utils/misc/guc_tables.c:4517 +#: utils/misc/guc_tables.c:4752 msgid "Location of the SSL server private key file." msgstr "SSLサーバー秘密鍵ファイルの場所です。" -#: utils/misc/guc_tables.c:4527 +#: utils/misc/guc_tables.c:4762 msgid "Location of the SSL certificate authority file." msgstr "SSL認証局ファイルの場所です" -#: utils/misc/guc_tables.c:4537 +#: utils/misc/guc_tables.c:4772 msgid "Location of the SSL certificate revocation list file." msgstr "SSL証明書失効リストファイルの場所です。" -#: utils/misc/guc_tables.c:4547 +#: utils/misc/guc_tables.c:4782 msgid "Location of the SSL certificate revocation list directory." msgstr "SSL証明書失効リストディレクトリの場所です。" -#: utils/misc/guc_tables.c:4557 +#: utils/misc/guc_tables.c:4792 msgid "Number of synchronous standbys and list of names of potential synchronous ones." msgstr "同期スタンバイの数と同期スタンバイ候補の名前の一覧。" -#: utils/misc/guc_tables.c:4568 +#: utils/misc/guc_tables.c:4803 msgid "Sets default text search configuration." msgstr "デフォルトのテキスト検索設定を設定します。" -#: utils/misc/guc_tables.c:4578 -msgid "Sets the list of allowed SSL ciphers." -msgstr "SSL暗号として許されるリストを設定。" +#: utils/misc/guc_tables.c:4813 +msgid "Sets the list of allowed TLSv1.3 cipher suites." +msgstr "使用を許可するTLSv1.3の暗号スイートのリストを設定。" -#: utils/misc/guc_tables.c:4593 -msgid "Sets the curve to use for ECDH." -msgstr "ECDHで使用する曲線を設定。" +#: utils/misc/guc_tables.c:4814 +msgid "An empty string means use the default cipher suites." +msgstr "空文字列でデフォルトの暗号スイートを使用します。" -#: utils/misc/guc_tables.c:4608 +#: utils/misc/guc_tables.c:4824 +msgid "Sets the list of allowed TLSv1.2 (and lower) ciphers." +msgstr "使用可能なTLSv1.2(およびそれ以前)の暗号方式のリストを設定。" + +#: utils/misc/guc_tables.c:4839 +msgid "Sets the group(s) to use for Diffie-Hellman key exchange." +msgstr "Diffie-Hellman鍵交換で使用するグループ(群)を設定。" + +#: utils/misc/guc_tables.c:4840 +msgid "Multiple groups can be specified using colon-separated list." +msgstr "複数のグループはコロン区切りのリストとして指定できます。" + +#: utils/misc/guc_tables.c:4854 msgid "Location of the SSL DH parameters file." msgstr "SSLのDHパラメータファイルの場所です。" -#: utils/misc/guc_tables.c:4619 +#: utils/misc/guc_tables.c:4855 +msgid "An empty string means use compiled-in default parameters." +msgstr "空文字列でコンパイル時設定のデフォルトのパラメーターを使用します。" + +#: utils/misc/guc_tables.c:4865 msgid "Command to obtain passphrases for SSL." msgstr "SSLのパスフレーズを取得するコマンド。" -#: utils/misc/guc_tables.c:4630 +#: utils/misc/guc_tables.c:4866 +msgid "An empty string means use the built-in prompting mechanism." +msgstr "空文字列で内蔵のパスワード入力機構を使用します。" + +#: utils/misc/guc_tables.c:4876 msgid "Sets the application name to be reported in statistics and logs." msgstr "統計やログで報告されるアプリケーション名を設定。" -#: utils/misc/guc_tables.c:4641 +#: utils/misc/guc_tables.c:4887 msgid "Sets the name of the cluster, which is included in the process title." msgstr "プロセスのタイトルに含まれるクラスタ名を指定。" -#: utils/misc/guc_tables.c:4652 +#: utils/misc/guc_tables.c:4898 msgid "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "WALの整合性チェックを行う対象とするリソースマネージャを設定。" -#: utils/misc/guc_tables.c:4653 +#: utils/misc/guc_tables.c:4899 msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay." msgstr "全ページイメージが全てのデータブロックに対して記録され、WAL再生の結果とクロスチェックされます。" -#: utils/misc/guc_tables.c:4663 +#: utils/misc/guc_tables.c:4909 msgid "JIT provider to use." msgstr "使用するJITプロバイダ。" -#: utils/misc/guc_tables.c:4674 +#: utils/misc/guc_tables.c:4920 msgid "Log backtrace for errors in these functions." msgstr "これらの関数でエラーが起きた場合にはバックトレースをログに出力します。" -#: utils/misc/guc_tables.c:4685 +#: utils/misc/guc_tables.c:4931 msgid "Use direct I/O for file access." msgstr "ファイルアクセスに直接I/Oを使用します。" -#: utils/misc/guc_tables.c:4696 -msgid "Lists streaming replication standby server slot names that logical WAL sender processes will wait for." -msgstr "論理walsenderプロセスが待ち受け対象とするストリーミングレプリケーションのスタンバイのスロット名を列挙します。" +#: utils/misc/guc_tables.c:4932 +msgid "An empty string disables direct I/O." +msgstr "空文字列で直接I/Oを無効にします。" + +#: utils/misc/guc_tables.c:4942 +msgid "Lists streaming replication standby server replication slot names that logical WAL sender processes will wait for." +msgstr "論理WAL senderプロセスが待ち受け対象とするストリーミングレプリケーションのスタンバイサーバーのレプリケーションスロット名を列挙します。" + +#: utils/misc/guc_tables.c:4944 +msgid "Logical WAL sender processes will send decoded changes to output plugins only after the specified replication slots have confirmed receiving WAL." +msgstr "論理WAL senderプロセスは指定されたレプリケーションスロットによるWALの受け取り確認後に初めてデコードされた変更を出力プラグインに送出します。" + +#: utils/misc/guc_tables.c:4956 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "指定した種別の非システムリレーションへのアクセスを禁止します。" + +#: utils/misc/guc_tables.c:4967 +msgid "Lists libraries that may be called to validate OAuth v2 bearer tokens." +msgstr "OAuth v2 の Bearer トークンを検証するために使用できるライブラリの一覧。" -#: utils/misc/guc_tables.c:4698 -msgid "Logical WAL sender processes will send decoded changes to plugins only after the specified replication slots confirm receiving WAL." -msgstr "論理walsenderプロセスは指定されたレプリケーションスロットによるWALの受け取り確認後に初めてデコードされた変更をプラグインに送出します。" +#: utils/misc/guc_tables.c:4978 +msgid "Logs specified aspects of connection establishment and setup." +msgstr "接続の確立やセットアップに関する指定された情報をログに記録します。" -#: utils/misc/guc_tables.c:4719 +#: utils/misc/guc_tables.c:4999 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "文字列リテラルで\"\\'\"が許可されるかどうかを設定。" -#: utils/misc/guc_tables.c:4729 +#: utils/misc/guc_tables.c:5009 msgid "Sets the output format for bytea." msgstr "bytea の出力フォーマットを設定。" -#: utils/misc/guc_tables.c:4739 +#: utils/misc/guc_tables.c:5019 msgid "Sets the message levels that are sent to the client." msgstr "クライアントに送信される最小のメッセージレベルを設定。" -#: utils/misc/guc_tables.c:4740 utils/misc/guc_tables.c:4836 utils/misc/guc_tables.c:4847 +#: utils/misc/guc_tables.c:5020 utils/misc/guc_tables.c:5116 utils/misc/guc_tables.c:5127 msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent." msgstr " 各レベルにはそのレベル以下の全てが含まれます。レベルを低くするほど、送信されるメッセージはより少なくなります。 " -#: utils/misc/guc_tables.c:4750 +#: utils/misc/guc_tables.c:5030 msgid "Enables in-core computation of query identifiers." msgstr "問い合わせ識別子の内部生成を有効にする。" -#: utils/misc/guc_tables.c:4760 +#: utils/misc/guc_tables.c:5040 msgid "Enables the planner to use constraints to optimize queries." msgstr "問い合わせの最適化の際にプランナに制約を利用させる。" -#: utils/misc/guc_tables.c:4761 +#: utils/misc/guc_tables.c:5041 msgid "Table scans will be skipped if their constraints guarantee that no rows match the query." msgstr "制約により、問い合わせに一致する行がないことが保証されているテーブルをスキップします。" -#: utils/misc/guc_tables.c:4772 +#: utils/misc/guc_tables.c:5052 msgid "Sets the default compression method for compressible values." msgstr "圧縮可能な値に対して使用されるデフォルト圧縮方式を設定。" -#: utils/misc/guc_tables.c:4783 +#: utils/misc/guc_tables.c:5063 msgid "Sets the transaction isolation level of each new transaction." msgstr "新規トランザクションのトランザクション分離レベルを設定。" -#: utils/misc/guc_tables.c:4793 +#: utils/misc/guc_tables.c:5073 msgid "Sets the current transaction's isolation level." msgstr "現在のトランザクションの分離レベルを設定。" -#: utils/misc/guc_tables.c:4804 +#: utils/misc/guc_tables.c:5084 msgid "Sets the display format for interval values." msgstr "インターバル値の表示フォーマットを設定。" -#: utils/misc/guc_tables.c:4815 +#: utils/misc/guc_tables.c:5095 msgid "Log level for reporting invalid ICU locale strings." msgstr "不正なICUロケール設定の報告に使用するログレベル。" -#: utils/misc/guc_tables.c:4825 +#: utils/misc/guc_tables.c:5105 msgid "Sets the verbosity of logged messages." msgstr "ログ出力メッセージの詳細度を設定。" -#: utils/misc/guc_tables.c:4835 +#: utils/misc/guc_tables.c:5115 msgid "Sets the message levels that are logged." msgstr "ログに出力するメッセージレベルを設定。" -#: utils/misc/guc_tables.c:4846 +#: utils/misc/guc_tables.c:5126 msgid "Causes all statements generating error at or above this level to be logged." msgstr "このレベル以上のエラーを発生させた全てのSQL文をログに記録します。" -#: utils/misc/guc_tables.c:4857 +#: utils/misc/guc_tables.c:5137 msgid "Sets the type of statements logged." msgstr "ログ出力する文の種類を設定。" -#: utils/misc/guc_tables.c:4867 +#: utils/misc/guc_tables.c:5147 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "syslogを有効にした場合に使用するsyslog \"facility\"を設定。" -#: utils/misc/guc_tables.c:4878 +#: utils/misc/guc_tables.c:5158 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "トリガと書き換えルールに関するセッションの動作を設定。" -#: utils/misc/guc_tables.c:4888 +#: utils/misc/guc_tables.c:5168 msgid "Sets the current transaction's synchronization level." msgstr "現在のトランザクションの同期レベルを設定。" -#: utils/misc/guc_tables.c:4898 +#: utils/misc/guc_tables.c:5178 msgid "Allows archiving of WAL files using \"archive_command\"." msgstr "\"archive_command\"を使用したWALファイルのアーカイブ処理を許可します。" -#: utils/misc/guc_tables.c:4908 +#: utils/misc/guc_tables.c:5188 msgid "Sets the action to perform upon reaching the recovery target." msgstr "リカバリ目標に到達した際の動作を設定。" -#: utils/misc/guc_tables.c:4918 +#: utils/misc/guc_tables.c:5198 msgid "Collects function-level statistics on database activity." msgstr "データベースの動作に関して、関数レベルの統計情報を収集します。" -#: utils/misc/guc_tables.c:4929 +#: utils/misc/guc_tables.c:5209 msgid "Sets the consistency of accesses to statistics data." msgstr "統計情報読み出し時の一貫性レベルを設定します。" -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5219 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "WALファイルに出力される全ページ出力を指定した方式で圧縮します。" -#: utils/misc/guc_tables.c:4949 +#: utils/misc/guc_tables.c:5229 msgid "Sets the level of information written to the WAL." msgstr "WALに書き出される情報のレベルを設定します。" -#: utils/misc/guc_tables.c:4959 +#: utils/misc/guc_tables.c:5239 msgid "Selects the dynamic shared memory implementation used." msgstr "動的共有メモリで使用する実装を選択します。" -#: utils/misc/guc_tables.c:4969 +#: utils/misc/guc_tables.c:5249 msgid "Selects the shared memory implementation used for the main shared memory region." msgstr "主共有メモリ領域に使用する共有メモリ実装を選択します。" -#: utils/misc/guc_tables.c:4979 +#: utils/misc/guc_tables.c:5259 +msgid "Selects the file copy method." +msgstr "ファイルのコピー方式を選択します。" + +#: utils/misc/guc_tables.c:5269 msgid "Selects the method used for forcing WAL updates to disk." msgstr "WAL更新のディスクへの書き出しを強制するめの方法を選択します。" -#: utils/misc/guc_tables.c:4989 +#: utils/misc/guc_tables.c:5279 msgid "Sets how binary values are to be encoded in XML." msgstr "XMLでどのようにバイナリ値を符号化するかを設定します。" -#: utils/misc/guc_tables.c:4999 +#: utils/misc/guc_tables.c:5289 msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments." msgstr "暗黙的なパースおよび直列化操作においてXMLデータを文書とみなすか断片とみなすかを設定します。" -#: utils/misc/guc_tables.c:5010 +#: utils/misc/guc_tables.c:5300 msgid "Use of huge pages on Linux or Windows." msgstr "LinuxおよびWindowsでヒュージページを使用。" -#: utils/misc/guc_tables.c:5020 +#: utils/misc/guc_tables.c:5310 msgid "Indicates the status of huge pages." msgstr "ヒュージページの状態を表示。" -#: utils/misc/guc_tables.c:5031 +#: utils/misc/guc_tables.c:5321 msgid "Prefetch referenced blocks during recovery." msgstr "リカバリ中に被参照ブロックの事前読み込みを行う。" -#: utils/misc/guc_tables.c:5032 +#: utils/misc/guc_tables.c:5322 msgid "Look ahead in the WAL to find references to uncached data." msgstr "キャッシュされていないデータへの参照の検出のためにWALの先読みを行う。" -#: utils/misc/guc_tables.c:5041 +#: utils/misc/guc_tables.c:5331 msgid "Forces the planner's use parallel query nodes." msgstr "プランナに並列問い合わせノードの使用を強制します。" -#: utils/misc/guc_tables.c:5042 +#: utils/misc/guc_tables.c:5332 msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans that contain nodes that perform tuple communication between workers and the main process." msgstr "これは並列問い合わせ機構のテストの際に、プランナにワーカーとメインプロセスとの間でタプルのやり取りを行わせるノードを含む実行計画を強制的に生成させるために使用できます。" -#: utils/misc/guc_tables.c:5054 +#: utils/misc/guc_tables.c:5344 msgid "Chooses the algorithm for encrypting passwords." msgstr "パスワードの暗号化に使用するアルゴリズムを選択する。" -#: utils/misc/guc_tables.c:5064 +#: utils/misc/guc_tables.c:5354 msgid "Controls the planner's selection of custom or generic plan." msgstr "プランナでのカスタムプランと汎用プランの選択を制御。" -#: utils/misc/guc_tables.c:5065 +#: utils/misc/guc_tables.c:5355 msgid "Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior." msgstr "プリペアド文は個別プランと一般プランを持ち、プランナはよりよいプランの選択を試みます。これを設定することでそのデフォルト動作を変更できます。" -#: utils/misc/guc_tables.c:5077 +#: utils/misc/guc_tables.c:5367 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "使用する SSL/TLSプロトコルの最小バージョンを設定。" -#: utils/misc/guc_tables.c:5089 +#: utils/misc/guc_tables.c:5379 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "使用可能な最大の SSL/TLS プロトコルバージョンを指定します。" -#: utils/misc/guc_tables.c:5101 +#: utils/misc/guc_tables.c:5391 msgid "Sets the method for synchronizing the data directory before crash recovery." msgstr "クラシュリカバリ前に行うデータディレクトリの同期の方法を設定する。" -#: utils/misc/guc_tables.c:5110 +#: utils/misc/guc_tables.c:5400 msgid "Forces immediate streaming or serialization of changes in large transactions." msgstr "大きなトランザクションにおいて、即時ストリーミングまたは変更のシリアライズを強制します。" -#: utils/misc/guc_tables.c:5111 +#: utils/misc/guc_tables.c:5401 msgid "On the publisher, it allows streaming or serializing each change in logical decoding. On the subscriber, it allows serialization of all changes to files and notifies the parallel apply workers to read and apply them at the end of the transaction." msgstr "パブリッシャでは、この設定はロジカルでコーディングで個々の変更のストリーミングまたはシリアル化を実行させます。サブスクライバではすべての変更をファイルへシリアライズし、トランザクション終了時にその変更情報の読み出しおよび適用の実行をパラレルワーカーに指示するようにします。" +#: utils/misc/guc_tables.c:5413 +msgid "Selects the method for executing asynchronous I/O." +msgstr "非同期I/Oの実行方式を選択します。" + #: utils/misc/help_config.c:129 #, c-format msgid "internal error: unrecognized run-time parameter type\n" @@ -30043,6 +31382,26 @@ msgstr "問い合わせはテーブル\"%s\"に対する行レベルセキュリ msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." msgstr "テーブルの所有者に対するポリシを無効にするには、ALTER TABLE NO FORCE ROW LEVEL SECURITY を使ってください。" +#: utils/misc/stack_depth.c:101 +#, c-format +msgid "stack depth limit exceeded" +msgstr "スタック長制限を越えました" + +#: utils/misc/stack_depth.c:102 +#, c-format +msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." +msgstr "プラットフォームのスタック長制限が適切であることを確認した後に、設定パラメータ\"max_stack_depth\" (現在 %dkB)を増やしてください。" + +#: utils/misc/stack_depth.c:149 +#, c-format +msgid "\"max_stack_depth\" must not exceed %zdkB." +msgstr "\"max_stack_depth\"は%zdkBを越えてはなりません。" + +#: utils/misc/stack_depth.c:151 +#, c-format +msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." +msgstr "プラットフォームのスタック長制限を\"ulimit -s\"または同等の機能を使用して増加してください" + #: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" @@ -30058,57 +31417,57 @@ msgstr "タイムゾーンファイル\"%3$s\"の%4$d行のタイムゾーン省 msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%2$s\"の%3$d行のタイムゾーンオフセット%1$dは範囲外です" -#: utils/misc/tzparser.c:112 +#: utils/misc/tzparser.c:113 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dでタイムゾーン省略形がありません" -#: utils/misc/tzparser.c:121 +#: utils/misc/tzparser.c:122 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dでタイムゾーンオフセットがありません" -#: utils/misc/tzparser.c:133 +#: utils/misc/tzparser.c:134 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dのタイムゾーンオフセット値が無効です" -#: utils/misc/tzparser.c:169 +#: utils/misc/tzparser.c:170 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dで構文が無効です" -#: utils/misc/tzparser.c:237 +#: utils/misc/tzparser.c:238 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "タイムゾーン省略形\"%s\"が複数定義されています" -#: utils/misc/tzparser.c:239 +#: utils/misc/tzparser.c:240 #, c-format msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d." msgstr "タイムゾーンファイル\"%s\"の行%dの項目は、ファイル\"%s\"の行%dと競合します。" -#: utils/misc/tzparser.c:301 +#: utils/misc/tzparser.c:302 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "タイムゾーンファイル名が無効です: \"%s\"" -#: utils/misc/tzparser.c:314 +#: utils/misc/tzparser.c:315 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "ファイル\"%s\"でタイムゾーンファイルの再帰の上限を超えました。" -#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 +#: utils/misc/tzparser.c:354 utils/misc/tzparser.c:367 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "タイムゾーンファイル\"%s\"を読み込めませんでした: %m" -#: utils/misc/tzparser.c:377 +#: utils/misc/tzparser.c:378 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dが長すぎます。" -#: utils/misc/tzparser.c:401 +#: utils/misc/tzparser.c:403 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "タイムゾーンファイル\"%s\"の行%dにファイル名がない@INCLUDEがあります" @@ -30123,12 +31482,12 @@ msgstr "メモリコンテキスト\"%s\"の作成時に失敗しました" msgid "could not attach to dynamic shared area" msgstr "動的共有エリアをアタッチできませんでした" -#: utils/mmgr/mcxt.c:1155 +#: utils/mmgr/mcxt.c:1231 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "メモリコンテクスト\"%2$s\"でサイズ%1$zuの要求が失敗しました。" -#: utils/mmgr/mcxt.c:1299 +#: utils/mmgr/mcxt.c:1391 #, c-format msgid "logging memory contexts of PID %d" msgstr "PID %dのメモリコンテクストを記録します" @@ -30143,35 +31502,35 @@ msgstr "カーソル\"%s\"はすでに存在します" msgid "closing existing cursor \"%s\"" msgstr "既存のカーソル\"%s\"をクローズしています" -#: utils/mmgr/portalmem.c:401 +#: utils/mmgr/portalmem.c:403 #, c-format msgid "portal \"%s\" cannot be run" msgstr "ポータル\"%s\"を実行できません" -#: utils/mmgr/portalmem.c:479 +#: utils/mmgr/portalmem.c:481 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "固定されたポータル\"%s\"は削除できません" -#: utils/mmgr/portalmem.c:487 +#: utils/mmgr/portalmem.c:489 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "アクティブなポータル\"%s\"は削除できません" -#: utils/mmgr/portalmem.c:738 +#: utils/mmgr/portalmem.c:740 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "WITH HOLD 付きのカーソルを作成したトランザクションは PREPARE できません" -#: utils/mmgr/portalmem.c:1229 +#: utils/mmgr/portalmem.c:1234 #, c-format msgid "cannot perform transaction commands inside a cursor loop that is not read-only" msgstr "読み込み専用ではないカーソルのループ内ではトランザクション命令は実行できません" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %lld of temporary file" -msgstr "一時ファイルのブロック%lldへのシークに失敗しました" +msgid "could not seek to block % of temporary file" +msgstr "一時ファイルのブロック%へのシークに失敗しました" #: utils/sort/sharedtuplestore.c:466 #, c-format @@ -30183,77 +31542,77 @@ msgstr "タプルストア共有一時ファイル内に予期しないチャン msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "共有タプルストア一時ファイルのブロック%uへのシークに失敗しました" -#: utils/sort/tuplesort.c:2372 +#: utils/sort/tuplesort.c:2340 #, c-format msgid "cannot have more than %d runs for an external sort" msgstr "外部ソートでは%d以上のラン数は扱えません" -#: utils/sort/tuplesortvariants.c:1552 +#: utils/sort/tuplesortvariants.c:1671 #, c-format msgid "could not create unique index \"%s\"" -msgstr "一意インデックス\"%s\"を作成できませんでした" +msgstr "ユニークインデックス\"%s\"を作成できませんでした" -#: utils/sort/tuplesortvariants.c:1554 +#: utils/sort/tuplesortvariants.c:1673 #, c-format msgid "Key %s is duplicated." msgstr "キー%sは重複しています。" -#: utils/sort/tuplesortvariants.c:1555 +#: utils/sort/tuplesortvariants.c:1674 #, c-format msgid "Duplicate keys exist." msgstr "重複したキーが存在します。" -#: utils/sort/tuplestore.c:518 utils/sort/tuplestore.c:528 utils/sort/tuplestore.c:869 utils/sort/tuplestore.c:973 utils/sort/tuplestore.c:1037 utils/sort/tuplestore.c:1054 utils/sort/tuplestore.c:1256 utils/sort/tuplestore.c:1321 utils/sort/tuplestore.c:1330 +#: utils/sort/tuplestore.c:552 utils/sort/tuplestore.c:562 utils/sort/tuplestore.c:921 utils/sort/tuplestore.c:1025 utils/sort/tuplestore.c:1089 utils/sort/tuplestore.c:1106 utils/sort/tuplestore.c:1308 utils/sort/tuplestore.c:1373 utils/sort/tuplestore.c:1382 #, c-format msgid "could not seek in tuplestore temporary file" msgstr "タプルストア一時ファイルのシークに失敗しました" -#: utils/time/snapmgr.c:536 +#: utils/time/snapmgr.c:557 #, c-format msgid "The source transaction is not running anymore." msgstr "元となるトランザクションはすでに実行中ではありません。" -#: utils/time/snapmgr.c:1136 +#: utils/time/snapmgr.c:1143 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "サブトランザクションからスナップショットをエクスポートすることはできません" -#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 +#: utils/time/snapmgr.c:1303 utils/time/snapmgr.c:1308 utils/time/snapmgr.c:1313 utils/time/snapmgr.c:1328 utils/time/snapmgr.c:1333 utils/time/snapmgr.c:1338 utils/time/snapmgr.c:1353 utils/time/snapmgr.c:1358 utils/time/snapmgr.c:1363 utils/time/snapmgr.c:1477 utils/time/snapmgr.c:1493 utils/time/snapmgr.c:1518 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "ファイル\"%s\"内のスナップショットデータが不正です" -#: utils/time/snapmgr.c:1393 +#: utils/time/snapmgr.c:1400 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "SET TRANSACTION SNAPSHOTを全ての問い合わせの前に呼び出さなければなりません" -#: utils/time/snapmgr.c:1402 +#: utils/time/snapmgr.c:1409 #, c-format msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ" msgstr "スナップショットをインポートするトランザクションはSERIALIZABLEまたはREPEATABLE READ分離レベルでなければなりません" -#: utils/time/snapmgr.c:1411 +#: utils/time/snapmgr.c:1418 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "無効なスナップショット識別子: \"%s\"" -#: utils/time/snapmgr.c:1426 +#: utils/time/snapmgr.c:1433 #, c-format msgid "snapshot \"%s\" does not exist" msgstr "スナップショット\"%s\"は存在しません" -#: utils/time/snapmgr.c:1524 +#: utils/time/snapmgr.c:1531 #, c-format msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction" msgstr "シリアライザブルトランザクションはシリアライザブルではないトランザクションからのスナップショットをインポートできません" -#: utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1535 #, c-format msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction" msgstr "読み取り専用のシリアライザブルトランザクションでは、読み取り専用トランザクションからスナップショットをインポートすることができません" -#: utils/time/snapmgr.c:1543 +#: utils/time/snapmgr.c:1550 #, c-format msgid "cannot import a snapshot from a different database" msgstr "異なるデータベースからのスナップショットを読み込むことはできません" diff --git a/src/backend/po/ka.po b/src/backend/po/ka.po index f626631f51660..23730e7181862 100644 --- a/src/backend/po/ka.po +++ b/src/backend/po/ka.po @@ -1,14 +1,14 @@ # Georgian message translation file for postgres # Copyright (C) 2023 PostgreSQL Global Development Group # This file is distributed under the same license as the postgres (PostgreSQL) package. -# Temuri Doghonadze , 2022-2023. +# Temuri Doghonadze , 2022-2025. # msgid "" msgstr "" -"Project-Id-Version: postgres (PostgreSQL) 17\n" +"Project-Id-Version: postgres (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:13+0000\n" -"PO-Revision-Date: 2024-06-14 06:17+0200\n" +"POT-Creation-Date: 2025-04-18 10:14+0000\n" +"PO-Revision-Date: 2025-04-19 04:44+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../common/binaryheap.c:121 ../common/binaryheap.c:159 #, c-format @@ -76,25 +76,25 @@ msgstr "შეკუმშვის ალგორითმს \"%s\" long-dist msgid "not recorded" msgstr "ჩაწერილი არაა" -#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 commands/copyfrom.c:1737 commands/extension.c:3538 utils/adt/genfile.c:123 utils/time/snapmgr.c:1430 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 commands/copyfrom.c:1879 commands/extension.c:3807 utils/adt/genfile.c:123 utils/time/snapmgr.c:1437 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 access/transam/timeline.c:143 access/transam/timeline.c:362 access/transam/twophase.c:1369 access/transam/xlog.c:3471 access/transam/xlog.c:4335 access/transam/xlogrecovery.c:1238 access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 -#: replication/logical/origin.c:745 replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5084 replication/logical/snapbuild.c:2035 replication/slot.c:2236 replication/slot.c:2277 replication/walsender.c:655 storage/file/buffile.c:470 storage/file/copydir.c:185 utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 access/transam/timeline.c:143 access/transam/timeline.c:362 access/transam/twophase.c:1353 access/transam/xlog.c:3621 access/transam/xlog.c:4512 access/transam/xlogrecovery.c:1246 access/transam/xlogrecovery.c:1344 access/transam/xlogrecovery.c:1381 access/transam/xlogrecovery.c:1448 backup/basebackup.c:2128 backup/walsummary.c:283 commands/extension.c:3817 libpq/hba.c:769 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5236 replication/logical/snapbuild.c:1943 replication/slot.c:2430 replication/slot.c:2471 replication/walsender.c:629 storage/file/buffile.c:470 storage/file/copydir.c:201 utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" -#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 access/transam/xlog.c:3476 access/transam/xlog.c:4340 replication/logical/origin.c:750 replication/logical/origin.c:789 replication/logical/snapbuild.c:2040 replication/slot.c:2240 replication/slot.c:2281 replication/walsender.c:660 utils/cache/relmapper.c:833 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 access/transam/xlog.c:3626 access/transam/xlog.c:4517 replication/logical/origin.c:750 replication/logical/origin.c:789 replication/logical/snapbuild.c:1948 replication/slot.c:2434 replication/slot.c:2475 replication/walsender.c:634 utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" -#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 access/transam/timeline.c:392 access/transam/timeline.c:438 access/transam/timeline.c:512 access/transam/twophase.c:1381 access/transam/twophase.c:1793 access/transam/xlog.c:3317 access/transam/xlog.c:3511 access/transam/xlog.c:3516 access/transam/xlog.c:3652 -#: access/transam/xlog.c:4305 access/transam/xlog.c:5239 commands/copyfrom.c:1797 commands/copyto.c:325 libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 replication/logical/origin.c:683 replication/logical/origin.c:822 replication/logical/reorderbuffer.c:5136 replication/logical/snapbuild.c:1802 replication/logical/snapbuild.c:1926 replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 storage/file/copydir.c:208 storage/file/copydir.c:213 -#: storage/file/fd.c:828 storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 utils/cache/relmapper.c:956 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 access/transam/timeline.c:392 access/transam/timeline.c:438 access/transam/timeline.c:512 access/transam/twophase.c:1365 access/transam/twophase.c:1783 access/transam/xlog.c:3467 access/transam/xlog.c:3661 access/transam/xlog.c:3666 access/transam/xlog.c:3802 +#: access/transam/xlog.c:4482 access/transam/xlog.c:5458 commands/copyfrom.c:1929 commands/copyto.c:598 libpq/be-fsstubs.c:475 libpq/be-fsstubs.c:545 replication/logical/origin.c:683 replication/logical/origin.c:822 replication/logical/reorderbuffer.c:5288 replication/logical/snapbuild.c:1688 replication/logical/snapbuild.c:1814 replication/slot.c:2319 replication/slot.c:2482 replication/walsender.c:644 storage/file/copydir.c:224 storage/file/copydir.c:229 +#: storage/file/copydir.c:284 storage/file/copydir.c:289 storage/file/fd.c:828 storage/file/fd.c:3818 storage/file/fd.c:3924 utils/cache/relmapper.c:841 utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "ფაილის (%s) დახურვის შეცდომა: %m" @@ -115,41 +115,41 @@ msgstr "" "ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" "მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." -#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 ../common/file_utils.c:70 ../common/file_utils.c:347 ../common/file_utils.c:406 ../common/file_utils.c:480 access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 access/transam/timeline.c:251 access/transam/timeline.c:348 access/transam/twophase.c:1325 access/transam/xlog.c:3224 access/transam/xlog.c:3387 access/transam/xlog.c:3426 access/transam/xlog.c:3619 access/transam/xlog.c:4325 -#: access/transam/xlogrecovery.c:4263 access/transam/xlogrecovery.c:4366 access/transam/xlogutils.c:836 backup/basebackup.c:547 backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 postmaster/syslogger.c:1511 replication/logical/origin.c:735 replication/logical/reorderbuffer.c:3737 replication/logical/reorderbuffer.c:4291 replication/logical/reorderbuffer.c:5064 replication/logical/snapbuild.c:1757 replication/logical/snapbuild.c:1867 -#: replication/slot.c:2208 replication/walsender.c:628 replication/walsender.c:3051 storage/file/copydir.c:151 storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 utils/cache/relmapper.c:935 utils/error/elog.c:2091 utils/init/miscinit.c:1526 utils/init/miscinit.c:1660 utils/init/miscinit.c:1737 utils/misc/guc.c:4727 utils/misc/guc.c:4777 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 ../common/file_utils.c:69 ../common/file_utils.c:370 ../common/file_utils.c:428 ../common/file_utils.c:502 access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 access/transam/timeline.c:251 access/transam/timeline.c:348 access/transam/twophase.c:1309 access/transam/xlog.c:3357 access/transam/xlog.c:3537 access/transam/xlog.c:3576 access/transam/xlog.c:3769 access/transam/xlog.c:4502 +#: access/transam/xlogrecovery.c:4285 access/transam/xlogrecovery.c:4386 access/transam/xlogutils.c:825 backup/basebackup.c:549 backup/basebackup.c:1600 backup/walsummary.c:220 libpq/hba.c:626 postmaster/syslogger.c:1512 replication/logical/origin.c:735 replication/logical/reorderbuffer.c:3889 replication/logical/reorderbuffer.c:4443 replication/logical/reorderbuffer.c:5216 replication/logical/snapbuild.c:1643 replication/logical/snapbuild.c:1755 +#: replication/slot.c:2402 replication/walsender.c:602 replication/walsender.c:3056 storage/file/copydir.c:167 storage/file/copydir.c:255 storage/file/fd.c:803 storage/file/fd.c:3575 storage/file/fd.c:3805 storage/file/fd.c:3895 storage/smgr/md.c:675 utils/cache/relmapper.c:818 utils/cache/relmapper.c:935 utils/error/elog.c:2149 utils/init/miscinit.c:1585 utils/init/miscinit.c:1719 utils/init/miscinit.c:1796 utils/misc/guc.c:4774 utils/misc/guc.c:4824 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 access/transam/twophase.c:1766 access/transam/twophase.c:1775 access/transam/xlog.c:9210 access/transam/xlogfuncs.c:698 backup/basebackup_server.c:173 backup/basebackup_server.c:266 backup/walsummary.c:304 postmaster/postmaster.c:4125 postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 access/transam/twophase.c:1756 access/transam/twophase.c:1765 access/transam/xlog.c:9467 access/transam/xlogfuncs.c:699 backup/basebackup_server.c:173 backup/basebackup_server.c:266 backup/walsummary.c:304 postmaster/postmaster.c:4098 postmaster/syslogger.c:1523 postmaster/syslogger.c:1536 postmaster/syslogger.c:1549 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 ../common/file_utils.c:418 ../common/file_utils.c:488 access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 access/transam/timeline.c:506 access/transam/twophase.c:1787 access/transam/xlog.c:3310 access/transam/xlog.c:3505 access/transam/xlog.c:4298 access/transam/xlog.c:8585 access/transam/xlog.c:8630 -#: backup/basebackup_server.c:207 commands/dbcommands.c:514 replication/logical/snapbuild.c:1795 replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 storage/file/fd.c:3851 storage/smgr/md.c:1329 storage/smgr/md.c:1374 storage/sync/sync.c:446 utils/misc/guc.c:4480 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 ../common/file_utils.c:440 ../common/file_utils.c:510 access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 access/transam/timeline.c:506 access/transam/twophase.c:1777 access/transam/xlog.c:3457 access/transam/xlog.c:3655 access/transam/xlog.c:4475 access/transam/xlog.c:8853 access/transam/xlog.c:8897 +#: backup/basebackup_server.c:207 commands/dbcommands.c:515 replication/logical/snapbuild.c:1681 replication/slot.c:2305 replication/slot.c:2412 storage/file/fd.c:820 storage/file/fd.c:3916 storage/smgr/md.c:1455 storage/smgr/md.c:1515 storage/sync/sync.c:446 utils/misc/guc.c:4527 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 ../common/md5_common.c:156 ../common/parse_manifest.c:157 ../common/parse_manifest.c:853 ../common/psprintf.c:143 ../common/scram-common.c:269 ../common/stringinfo.c:314 ../port/path.c:751 ../port/path.c:788 -#: ../port/path.c:805 access/transam/twophase.c:1434 access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 postmaster/bgworker.c:355 postmaster/bgworker.c:945 postmaster/postmaster.c:3559 postmaster/postmaster.c:4019 postmaster/postmaster.c:4381 postmaster/walsummarizer.c:820 replication/libpqwalreceiver/libpqwalreceiver.c:387 replication/logical/logical.c:209 replication/walsender.c:835 -#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1453 storage/ipc/procarray.c:2207 storage/ipc/procarray.c:2214 storage/ipc/procarray.c:2719 storage/ipc/procarray.c:3423 utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 utils/adt/formatting.c:2075 utils/adt/pg_locale.c:509 utils/adt/pg_locale.c:673 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 -#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 utils/misc/guc.c:4458 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 utils/mmgr/slab.c:370 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 ../common/cryptohash_openssl.c:356 ../common/exec.c:543 ../common/exec.c:588 ../common/exec.c:680 ../common/hmac.c:309 ../common/hmac.c:325 ../common/hmac_openssl.c:151 ../common/hmac_openssl.c:339 ../common/jsonapi.c:2407 ../common/md5_common.c:156 ../common/parse_manifest.c:157 ../common/parse_manifest.c:852 ../common/psprintf.c:140 ../common/scram-common.c:268 ../port/path.c:829 ../port/path.c:866 +#: ../port/path.c:883 access/transam/twophase.c:1418 access/transam/xlogrecovery.c:570 lib/dshash.c:253 libpq/auth.c:1345 libpq/auth.c:1389 libpq/auth.c:1951 libpq/be-secure-gssapi.c:527 postmaster/bgworker.c:355 postmaster/bgworker.c:1022 postmaster/postmaster.c:3568 postmaster/walsummarizer.c:942 replication/libpqwalreceiver/libpqwalreceiver.c:351 replication/logical/logical.c:210 replication/walsender.c:811 storage/buffer/localbuf.c:745 storage/file/fd.c:912 +#: storage/file/fd.c:1447 storage/file/fd.c:1608 storage/file/fd.c:2592 storage/ipc/procarray.c:1465 storage/ipc/procarray.c:2217 storage/ipc/procarray.c:2224 storage/ipc/procarray.c:2727 storage/ipc/procarray.c:3436 utils/adt/pg_locale.c:509 utils/adt/pg_locale.c:583 utils/adt/pg_locale_icu.c:358 utils/adt/pg_locale_libc.c:207 utils/adt/pg_locale_libc.c:302 utils/adt/pg_locale_libc.c:390 utils/fmgr/dfmgr.c:219 utils/hash/dynahash.c:516 utils/hash/dynahash.c:616 +#: utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 utils/misc/guc.c:647 utils/misc/guc.c:672 utils/misc/guc.c:1060 utils/misc/guc.c:4505 utils/misc/tzparser.c:479 utils/mmgr/aset.c:451 utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1230 utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" -#: ../common/cryptohash.c:266 ../common/cryptohash.c:272 ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 ../common/hmac_openssl.c:377 +#: ../common/cryptohash.c:266 ../common/cryptohash.c:272 ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:351 ../common/hmac_openssl.c:359 msgid "success" msgstr "წარმატება" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 ../common/hmac_openssl.c:371 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 ../common/hmac_openssl.c:353 msgid "destination buffer too small" msgstr "სამიზნე ბუფერი ძალიან პატარაა" -#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:355 msgid "OpenSSL failure" msgstr "OpenSSL -ის სეცდომა" @@ -173,27 +173,27 @@ msgstr "გასაშვებად ფაილის \"%s\" პოვნა msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "ბილიკის (\"%s\") აბსოლუტურ ფორმაში ამოხსნის შეცდომა: %m" -#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1721 commands/copyto.c:649 libpq/be-secure-common.c:59 +#: ../common/exec.c:363 commands/collationcmds.c:872 commands/copyfrom.c:1863 commands/copyto.c:934 libpq/be-secure-common.c:59 #, c-format msgid "could not execute command \"%s\": %m" msgstr "ბრძანების (\"%s\") შესრულების შეცდომა: %m" -#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#: ../common/exec.c:375 libpq/be-secure-common.c:71 #, c-format msgid "could not read from command \"%s\": %m" msgstr "ბრძანებიდან \"%s\" წაკითხვის შეცდომა: %m" -#: ../common/exec.c:397 +#: ../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "ბრძანებამ \"%s\" მონაცემები არ დააბრუნა" -#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 storage/ipc/latch.c:1349 storage/ipc/latch.c:1582 storage/ipc/latch.c:1744 storage/ipc/latch.c:1870 +#: ../common/exec.c:405 libpq/pqcomm.c:193 storage/ipc/waiteventset.c:782 storage/ipc/waiteventset.c:962 storage/ipc/waiteventset.c:1202 storage/ipc/waiteventset.c:1364 storage/ipc/waiteventset.c:1490 #, c-format msgid "%s() failed: %m" msgstr "%s()-ის შეცდომა: %m" -#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:790 ../port/path.c:807 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 +#: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 ../common/psprintf.c:142 ../port/path.c:831 ../port/path.c:868 ../port/path.c:885 utils/misc/ps_status.c:195 utils/misc/ps_status.c:203 utils/misc/ps_status.c:230 utils/misc/ps_status.c:238 #, c-format msgid "out of memory\n" msgstr "არასაკმარისი მეხსიერება\n" @@ -203,33 +203,33 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#: ../common/file_utils.c:75 storage/file/fd.c:3581 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../common/file_utils.c:120 ../common/file_utils.c:566 ../common/file_utils.c:570 access/transam/twophase.c:1337 access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1747 commands/copyto.c:695 commands/extension.c:3527 commands/tablespace.c:804 commands/tablespace.c:893 postmaster/pgarch.c:680 -#: replication/logical/snapbuild.c:1653 replication/logical/snapbuild.c:2156 storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 +#: ../common/file_utils.c:123 ../common/file_utils.c:588 ../common/file_utils.c:592 access/transam/twophase.c:1321 access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 backup/basebackup.c:357 backup/basebackup.c:555 backup/basebackup.c:626 backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1889 commands/copyto.c:980 commands/extension.c:3796 commands/tablespace.c:804 commands/tablespace.c:893 postmaster/pgarch.c:682 +#: replication/logical/snapbuild.c:1538 replication/logical/snapbuild.c:2065 storage/file/fd.c:1972 storage/file/fd.c:2060 storage/file/fd.c:3629 utils/adt/dbsize.c:105 utils/adt/dbsize.c:266 utils/adt/dbsize.c:355 utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#: ../common/file_utils.c:133 ../common/file_utils.c:243 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../common/file_utils.c:151 ../common/file_utils.c:281 ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 commands/tablespace.c:738 postmaster/postmaster.c:1468 storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:339 +#: ../common/file_utils.c:156 ../common/file_utils.c:304 ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 commands/tablespace.c:738 postmaster/postmaster.c:1496 storage/file/fd.c:2997 storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:340 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../common/file_utils.c:169 ../common/file_utils.c:315 ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 +#: ../common/file_utils.c:174 ../common/file_utils.c:338 ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:3009 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 postmaster/pgarch.c:834 postmaster/syslogger.c:1559 replication/logical/snapbuild.c:1814 replication/slot.c:936 replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 utils/time/snapmgr.c:1255 +#: ../common/file_utils.c:520 access/transam/xlogarchive.c:389 postmaster/pgarch.c:836 postmaster/syslogger.c:1560 replication/logical/snapbuild.c:1700 replication/slot.c:987 replication/slot.c:2191 replication/slot.c:2333 storage/file/fd.c:838 utils/time/snapmgr.c:1262 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -238,283 +238,287 @@ msgstr "გადარქმევის შეცდომა %s - %s: %m" msgid "internal error" msgstr "შიდა შეცდომა" -#: ../common/jsonapi.c:2121 +#: ../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "რეკურსიულ დაღმავალ დამმუშავებელს ინკრემენტული lexer-ის გამოყენება არ შეუძლია." -#: ../common/jsonapi.c:2123 +#: ../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "ინკრემენტულ დამმუშავებელს ინკრემენტული lexer სჭირდება." -#: ../common/jsonapi.c:2125 +#: ../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSON მეტისმეტად ღრმადაა ერთმანეთში ჩალაგებული. მაქსიმალური დასაშვები სიღრმეა 6400." -#: ../common/jsonapi.c:2127 +#: ../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "სპეციალური მიმდევრობა \"\\%.*s\" არასწორია." -#: ../common/jsonapi.c:2131 +#: ../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "სიმბოლო კოდით 0x%02x აუცილებლად ეკრანირებული უნდა იყოს." -#: ../common/jsonapi.c:2135 +#: ../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "მოველოდი შეყვანის დასასრულს, მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2138 +#: ../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "მოველოდი მასივის ელემენტს ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2141 +#: ../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "მოველოდი \",\" ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2144 +#: ../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "მოველოდი \":\", მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2147 +#: ../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "მოველოდი JSON მნიშვნელობას. მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2150 +#: ../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "შეყვანის სტრიქონი მოულოდნელად დასრულდა." -#: ../common/jsonapi.c:2152 +#: ../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "მოველოდი სტრიქონს ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2155 +#: ../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "მოველოდი \",\", ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2158 +#: ../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "მოველოდი სტრიქონს, მაგრამ მივიღე \"%.*s\"." -#: ../common/jsonapi.c:2161 +#: ../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "კოდი \"%.*s\" არასწორია." -#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 +#: ../common/jsonapi.c:2478 jsonpath_scan.l:585 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 ტექსტად ვერ გარდაიქმნება." -#: ../common/jsonapi.c:2166 +#: ../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\" ს თექვსმეტობითი ციფრები უნდა მოჰყვებოდეს." -#: ../common/jsonapi.c:2169 +#: ../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "უნიკოდის სპეციალური კოდების გამოყენება კოდის წერტილის მნიშვნელობებად 007F-ის ზემოთ შეუძლებელია, თუ კოდირება UTF-8 არაა." -#: ../common/jsonapi.c:2178 +#: ../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "უნიკოდის სპეციალური კოდების სერვერის კოდირებაში (%s) თარგმნა შეუძლებელია." -#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 +#: ../common/jsonapi.c:2499 jsonpath_scan.l:618 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "უნიკოდის მაღალ სუროგატს მაღალი სუროგატი არ უნდა მოსდევდეს." -#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 jsonpath_scan.l:713 +#: ../common/jsonapi.c:2501 jsonpath_scan.l:629 jsonpath_scan.l:639 jsonpath_scan.l:691 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "უნიკოდის დაბალი სუროგატი მაღალ სუროგატს უნდა მისდევდეს." -#: ../common/logging.c:276 +#: ../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "არასაკმარისი მეხსიერება შეცდომის აღწერის აგებისას" + +#: ../common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../common/logging.c:283 +#: ../common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../common/logging.c:294 +#: ../common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../common/logging.c:301 +#: ../common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " -#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:855 +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის ინიციალიზაციის შეცდომა" -#: ../common/parse_manifest.c:204 ../common/parse_manifest.c:261 +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "მანიფესტი მოულოდნელად დასრულდა" -#: ../common/parse_manifest.c:210 ../common/parse_manifest.c:862 +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის განახლების შეცდომა" -#: ../common/parse_manifest.c:302 +#: ../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "ობიექტის მოულოდნელი დასაწყისი" -#: ../common/parse_manifest.c:337 +#: ../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "ობიექტის მოულოდნელი დასასრული" -#: ../common/parse_manifest.c:366 +#: ../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "მასივის მოულოდნელი დასაწყისი" -#: ../common/parse_manifest.c:391 +#: ../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "მასივის მოულოდნელი დასასრული" -#: ../common/parse_manifest.c:418 +#: ../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "მოსალოდნელი ვერსიის მაჩვენებელი" -#: ../common/parse_manifest.c:454 +#: ../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "უცნობი ველი ზედა დონეზე" -#: ../common/parse_manifest.c:473 +#: ../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "მოულოდნელი ველი ფაილისთვის" -#: ../common/parse_manifest.c:487 +#: ../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "მოულოდნელი ველი WAL-ის დიაპაზონისთვის" -#: ../common/parse_manifest.c:493 +#: ../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "ობიექტის მოულოდნელი ველი" -#: ../common/parse_manifest.c:583 +#: ../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "მოულოდნელი სკალარი" -#: ../common/parse_manifest.c:609 +#: ../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "მანიფესტის ვერსია მთელი რიცხვი არაა" -#: ../common/parse_manifest.c:613 +#: ../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "მანიფესტის მოულოდნელი ვერსია" -#: ../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" msgstr "მანიფესტის სისტემის იდენფიტიკატორი მთელი რიცხვი არაა" -#: ../common/parse_manifest.c:662 +#: ../common/parse_manifest.c:661 msgid "missing path name" msgstr "აკლია ბილიკის სახელი" -#: ../common/parse_manifest.c:665 +#: ../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "ორივე, ბილიკის სახელი და ბილიკის კოდირებული სახელი" -#: ../common/parse_manifest.c:667 +#: ../common/parse_manifest.c:666 msgid "missing size" msgstr "ზომა აკლია" -#: ../common/parse_manifest.c:670 +#: ../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "საკონტროლო ჯამი ალგორითმის გარეშე" -#: ../common/parse_manifest.c:684 +#: ../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ფაილის სახელის გაშიფვრის შეცდომა" -#: ../common/parse_manifest.c:694 +#: ../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ფაილის ზომა მთელი რიცხვი არაა" -#: ../common/parse_manifest.c:700 backup/basebackup.c:870 +#: ../common/parse_manifest.c:699 backup/basebackup.c:872 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "საკონტროლო ჯამის უცნობი ალგორითმი: \"%s\"" -#: ../common/parse_manifest.c:719 +#: ../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "არასწორი საკონტროლო ჯამი ფაილისთვის \"%s\": \"%s\"" -#: ../common/parse_manifest.c:762 +#: ../common/parse_manifest.c:761 msgid "missing timeline" msgstr "აკლია დროის ხაზი" -#: ../common/parse_manifest.c:764 +#: ../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "აკლია საწყისი LSN" -#: ../common/parse_manifest.c:766 +#: ../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "აკლია დასასრულის LSN" -#: ../common/parse_manifest.c:772 +#: ../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "დროის ხაზი მთელი რიცხვი არაა" -#: ../common/parse_manifest.c:775 +#: ../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "საწყისი LSN-ის დამუშავების შეცდომა" -#: ../common/parse_manifest.c:778 +#: ../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "საბოლოო LSN-ის დამუშავების შეცდომა" -#: ../common/parse_manifest.c:843 +#: ../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "ველოდებოდი სულ ცოტა 2 ხაზს" -#: ../common/parse_manifest.c:846 +#: ../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "ბოლო ხაზი ხაზის გადატანით არ სრულდება" -#: ../common/parse_manifest.c:865 +#: ../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის დასრულების შეცდომა" -#: ../common/parse_manifest.c:869 +#: ../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "მანიფესტის საკონტროლო ჯამი არ გააჩნია" -#: ../common/parse_manifest.c:873 +#: ../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "მანიფესტის საკონტროლო ჯამის არასწორია: %s" -#: ../common/parse_manifest.c:877 +#: ../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "მანიფესტის საკონტროლო ჯამი არ ემთხვევა" -#: ../common/parse_manifest.c:892 +#: ../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "მარქაფის მანიფესტის დამუშავების შეცრომა: %s" -#: ../common/percentrepl.c:79 ../common/percentrepl.c:85 ../common/percentrepl.c:118 ../common/percentrepl.c:124 tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 utils/misc/guc.c:3283 utils/misc/guc.c:4662 utils/misc/guc.c:6887 utils/misc/guc.c:6928 +#: ../common/percentrepl.c:79 ../common/percentrepl.c:85 ../common/percentrepl.c:118 ../common/percentrepl.c:124 tcop/backend_startup.c:769 utils/misc/guc.c:3164 utils/misc/guc.c:3205 utils/misc/guc.c:3280 utils/misc/guc.c:4709 utils/misc/guc.c:6929 utils/misc/guc.c:6970 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "არასწორი მნიშვნელობა პარამეტრისთვის \"%s\": \"%s\"" @@ -574,51 +578,56 @@ msgstr "შეზღუდულ კოდის ხელახლა შეს msgid "could not get exit code from subprocess: error code %lu" msgstr "ქვეპროცესიდან გასასვლელი კოდი ვერ მივიღე: შეცდომის კოდი %lu" -#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 access/transam/twophase.c:1726 access/transam/xlogarchive.c:119 access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 postmaster/syslogger.c:1488 replication/logical/origin.c:591 replication/logical/reorderbuffer.c:4560 replication/logical/snapbuild.c:1695 replication/logical/snapbuild.c:2129 replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 storage/file/fd.c:3440 -#: storage/file/reinit.c:261 storage/ipc/dsm.c:343 storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 utils/time/snapmgr.c:1591 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 access/transam/twophase.c:1716 access/transam/xlogarchive.c:119 access/transam/xlogarchive.c:399 postmaster/postmaster.c:1069 postmaster/syslogger.c:1489 replication/logical/origin.c:591 replication/logical/reorderbuffer.c:4711 replication/logical/snapbuild.c:1581 replication/logical/snapbuild.c:2037 replication/slot.c:2386 storage/file/fd.c:878 storage/file/fd.c:3443 storage/file/fd.c:3505 +#: storage/file/reinit.c:261 storage/ipc/dsm.c:343 storage/smgr/md.c:401 storage/smgr/md.c:460 storage/sync/sync.c:243 utils/time/snapmgr.c:1598 #, c-format msgid "could not remove file \"%s\": %m" msgstr "ფაილის წაშლის შეცდომა \"%s\": %m" -#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 storage/file/fd.c:3779 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3435 storage/file/fd.c:3844 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "საქაღალდის (\"%s\") წაშლის შეცდომა: %m" -#: ../common/scram-common.c:282 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "მარილის კოდირების შეცდომა" -#: ../common/scram-common.c:298 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "დამახსოვრებული გასაღების კოდირების შეცდომა" -#: ../common/scram-common.c:315 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "სერვერის გასაღების კოდირების შეცდომა" -#: ../common/stringinfo.c:315 +#: ../common/stringinfo.c:362 +#, c-format +msgid "string buffer exceeds maximum allowed length (%zu bytes)" +msgstr "სტიქონის ბუფერი გადასცდა მაქსიმალურ დასაშვებ სიგრძეს (%zu ბაიტი)" + +#: ../common/stringinfo.c:363 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "სტრიქონების ბაფერის, რომელიც უკვე შეიცავს %d ბაიტს, %d ბაიტით ვერ გავადიდებ." -#: ../common/stringinfo.c:319 +#: ../common/stringinfo.c:367 #, c-format msgid "" -"out of memory\n" +"string buffer exceeds maximum allowed length (%zu bytes)\n" "\n" "Cannot enlarge string buffer containing %d bytes by %d more bytes.\n" msgstr "" -"არასაკმარისი მეხსიერების\n" +"სტიქონის ბუფერი გადასცდა მაქსიმალურ დასაშვებ სიგრძეს (%zu ბაიტი)\n" "\n" -"შეუძლებელია სტრიქონის ბუფერის (%d ბაიტიგ) აფართოება %d ბაიტით.\n" +"%d ბაიტის შემცველი სტრიქონის ბუფერის კიდევ %d ბაიტით გადიდება შეუძლებელია.\n" #: ../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" msgstr "მომხმარებლის ეფექტური ID-ის (%ld) ამოხსნა შეუძლებელია: %s" -#: ../common/username.c:45 libpq/auth.c:1888 +#: ../common/username.c:45 msgid "user does not exist" msgstr "მომხმარებელი არ არსებობს" @@ -657,12 +666,12 @@ msgstr "პროცესი გაჩერდა სიგნალით: %d msgid "child process exited with unrecognized status %d" msgstr "შვილი პროცესი დასრულდა უცნობი სტატუსით %d" -#: ../port/chklocale.c:283 +#: ../port/chklocale.c:280 #, c-format msgid "could not determine encoding for codeset \"%s\"" msgstr "კოდირების დადგენა ვერ მოხერხდა \"%s\"-ისთვის" -#: ../port/chklocale.c:404 ../port/chklocale.c:410 +#: ../port/chklocale.c:370 ../port/chklocale.c:376 #, c-format msgid "could not determine encoding for locale \"%s\": codeset is \"%s\"" msgstr "ენისთვის \"%s\" კოდირების დადგენა ვერ მოხერხდა: კოდების ნაკრები არის \"%s\"" @@ -710,7 +719,7 @@ msgstr "ვაგრძელებ თავიდან ცდას 30 წა msgid "You might have antivirus, backup, or similar software interfering with the database system." msgstr "შეიძლება თქვენი ანტივირუსი, მარქაფი ან რამე სხვა პროგრამა ხელს უშლის მონაცემთა ბაზის სისტემის მუშაობას." -#: ../port/path.c:775 +#: ../port/path.c:853 #, c-format msgid "could not get current working directory: %m\n" msgstr "მიმდინარე სამუშაო საქაღალდის მიღების შეცდომა: %m\n" @@ -720,16 +729,6 @@ msgstr "მიმდინარე სამუშაო საქაღალ msgid "operating system error %d" msgstr "ოპერაციული სისტემის შეცდომა %d" -#: ../port/user.c:43 ../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "ლოკალური მომხმარებლის ID-ის (%d) ამოხსნა შეუძლებელია: %s" - -#: ../port/user.c:48 ../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "ლოკალური მომხმარებელი ID-ით %d არ არსებობს" - #: ../port/win32security.c:62 #, c-format msgid "could not get SID for Administrators group: error code %lu\n" @@ -745,47 +744,47 @@ msgstr "ვერ მივიღე SID PowerUsers ჯგუფისთვი msgid "could not check access token membership: error code %lu\n" msgstr "კოდის წევრობის წვდომის შემოწმების შეცდომა: შეცდომის კოდი %lu\n" -#: access/brin/brin.c:405 +#: access/brin/brin.c:414 #, c-format msgid "request for BRIN range summarization for index \"%s\" page %u was not recorded" msgstr "\"BRIN\" შეჯამების დიაპაზონის ინდექსისთვის \"%s\" გვერდი %u ჩაწერილი არაა" -#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 +#: access/brin/brin.c:1397 access/brin/brin.c:1504 access/gin/ginfast.c:1040 access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:242 access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 access/transam/xlogfuncs.c:323 access/transam/xlogfuncs.c:389 access/transam/xlogfuncs.c:447 statistics/attribute_stats.c:190 statistics/attribute_stats.c:931 statistics/relation_stats.c:97 #, c-format msgid "recovery is in progress" msgstr "აღდგენა მიმდინარეობს" -#: access/brin/brin.c:1386 access/brin/brin.c:1494 +#: access/brin/brin.c:1398 access/brin/brin.c:1505 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "აღდგენის დროს BRIN კონტროლის ფუნქციების შესრულება შეუძლებელია." -#: access/brin/brin.c:1391 access/brin/brin.c:1499 +#: access/brin/brin.c:1403 access/brin/brin.c:1510 #, c-format -msgid "block number out of range: %lld" -msgstr "ბლოკების რაოდენობა დიაპაზონს გარეთაა: %lld" +msgid "block number out of range: %" +msgstr "ბლოკების რაოდენობა დიაპაზონს გარეთაა: %" -#: access/brin/brin.c:1436 access/brin/brin.c:1525 +#: access/brin/brin.c:1447 access/brin/brin.c:1536 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\" BRIN ინდექსი არაა" -#: access/brin/brin.c:1452 access/brin/brin.c:1541 +#: access/brin/brin.c:1463 access/brin/brin.c:1552 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "ინდექსის \"%s\" მშობელი ცხრილის გახსნის შეცდომა" -#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 parser/parse_utilcmd.c:2252 +#: access/brin/brin.c:1472 access/brin/brin.c:1568 access/gin/ginfast.c:1085 parser/parse_utilcmd.c:2433 #, c-format msgid "index \"%s\" is not valid" msgstr "ინდექსი არასწორია: \"%s\"" -#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 statistics/dependencies.c:661 statistics/dependencies.c:714 statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 +#: access/brin/brin_bloom.c:784 access/brin/brin_bloom.c:826 access/brin/brin_minmax_multi.c:2984 access/brin/brin_minmax_multi.c:3121 statistics/dependencies.c:661 statistics/dependencies.c:714 statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format msgid "cannot accept a value of type %s" msgstr "მნიშვნელობის ეს ტიპი მიუღებელია: %s" -#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 access/spgist/spgdoinsert.c:2278 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 access/gist/gist.c:1475 access/spgist/spgdoinsert.c:2001 access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "ინდექსის მწკრივის ზომა %zu მაქსიმუმზე (%zu) მეტია ინდექსისთვის \"%s\"" @@ -800,77 +799,77 @@ msgstr "დაზიანებული BRIN ინდექსი: დია msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "გვერდის მოულოდნელი ტიპი 0x%04X BRIN ინდექსში \"%s\" ბლოკში %u" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 +#: access/brin/brin_validate.c:111 access/gin/ginvalidate.c:142 access/gist/gistvalidate.c:150 access/hash/hashvalidate.c:112 access/nbtree/nbtvalidate.c:116 access/spgist/spgvalidate.c:181 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with invalid support number %d" msgstr "ოპერატორის ოჯახი \"%s\" წვდომის მეთოდიდან %s შეიცავს ფუნქციას %s არასწორი მხარდაჭერის ნომრით %d" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 +#: access/brin/brin_validate.c:127 access/gin/ginvalidate.c:154 access/gist/gistvalidate.c:162 access/hash/hashvalidate.c:124 access/nbtree/nbtvalidate.c:128 access/spgist/spgvalidate.c:193 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d" msgstr "ოპერატორის ოჯახი (\"%s\") (წვდომის მეთოდისგან %s) შეიცავს ფუნქციას %s, რომელსაც არასწორი ხელმოწერა აქვს მხარდაჭერის ნომრით %d" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 +#: access/brin/brin_validate.c:149 access/gin/ginvalidate.c:173 access/gist/gistvalidate.c:182 access/hash/hashvalidate.c:150 access/nbtree/nbtvalidate.c:148 access/spgist/spgvalidate.c:213 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d" msgstr "ოპერატორის ოჯახი \"%s\" წვდომის მეთოდის %s შეიცავს ოპერატორს %s არასწორი სტრატეგიის ნომრით %d" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 access/spgist/spgvalidate.c:237 +#: access/brin/brin_validate.c:178 access/gin/ginvalidate.c:186 access/hash/hashvalidate.c:163 access/nbtree/nbtvalidate.c:161 access/spgist/spgvalidate.c:229 #, c-format msgid "operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s" msgstr "ოპერატორის ოჯახი \"%s\" წვდომის მეთოდის %s შეიცავს არასწორი ORDER BY სპეციფიკაციას ოპერატორისთვის %s" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 +#: access/brin/brin_validate.c:191 access/gin/ginvalidate.c:199 access/gist/gistvalidate.c:230 access/hash/hashvalidate.c:176 access/nbtree/nbtvalidate.c:174 access/spgist/spgvalidate.c:245 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with wrong signature" msgstr "წვდომის მეთოდის %s ოპერატორის ოჯახი \"%s\" შეიცავს ოპერატორს %s არასწორი ხელმოწერით" -#: access/brin/brin_validate.c:236 access/hash/hashvalidate.c:226 access/nbtree/nbtvalidate.c:236 access/spgist/spgvalidate.c:280 +#: access/brin/brin_validate.c:229 access/hash/hashvalidate.c:216 access/nbtree/nbtvalidate.c:232 access/spgist/spgvalidate.c:272 #, c-format msgid "operator family \"%s\" of access method %s is missing operator(s) for types %s and %s" msgstr "ოპერატორის ოჯახს \"%s\" ( წვდომის მეთოდისგან \"%s\") აკლია ოპერატორი ტიპებისთვის %s და %s" -#: access/brin/brin_validate.c:246 +#: access/brin/brin_validate.c:239 #, c-format msgid "operator family \"%s\" of access method %s is missing support function(s) for types %s and %s" msgstr "ოპერატორის ოჯახს \"%s\" ( წვდომის მეთოდისგან \"%s\") აკლია ოპერატორი ტიპებისთვის %s და %s" -#: access/brin/brin_validate.c:259 access/hash/hashvalidate.c:240 access/nbtree/nbtvalidate.c:260 access/spgist/spgvalidate.c:315 +#: access/brin/brin_validate.c:252 access/hash/hashvalidate.c:230 access/nbtree/nbtvalidate.c:256 access/spgist/spgvalidate.c:307 #, c-format msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "ოპერატორის კლასს \"%s\" (წვდომის მეთოდიდან %s) ოპერატორები აკლია" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 access/gist/gistvalidate.c:273 +#: access/brin/brin_validate.c:263 access/gin/ginvalidate.c:241 access/gist/gistvalidate.c:272 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d" msgstr "ოპერატორის კლასს \"%s\" წვდომის მეთოდიდან %s აკლია მხარდაჭერის ფუნქცია %d" -#: access/common/attmap.c:121 +#: access/common/attmap.c:118 #, c-format -msgid "Returned type %s does not match expected type %s in column %d." -msgstr "დაბრუნებული ტიპი %s არ ემთხვევა მოსალოდნელ ტიპს %s სვეტისთვის %d." +msgid "Returned type %s does not match expected type %s in column \"%s\" (position %d)." +msgstr "დაბრუნებული ტიპი %s არ ემთხვევა მოსალოდნელ ტიპს %s სვეტში \"%s\" (მდებარეობა %d)." -#: access/common/attmap.c:149 +#: access/common/attmap.c:147 #, c-format msgid "Number of returned columns (%d) does not match expected column count (%d)." msgstr "სვეტების დაბრუნებული რაოდენობა (%d) არ ემთხვევა მოსალოდნელს (%d) არ ემთხვევა." -#: access/common/attmap.c:233 access/common/attmap.c:245 +#: access/common/attmap.c:231 access/common/attmap.c:243 #, c-format msgid "could not convert row type" msgstr "მწკრივის ტიპის გადაყვანის შეცდომა" -#: access/common/attmap.c:234 +#: access/common/attmap.c:232 #, c-format msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s." msgstr "ატრიბუტი %s ტიპისთვის %s ტიპის(%s) შესაბამის ატრიბუტს არ ემთხვევა." -#: access/common/attmap.c:246 +#: access/common/attmap.c:244 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "ატრიბუტი \"%s\" ტიპისთვის \"%s\" არ არსებობს ტიპში \"%s\"." -#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 +#: access/common/heaptuple.c:1133 access/common/heaptuple.c:1472 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "სვეტების რაოდენობა (%d) აღემატება ლიმიტს (%d)" @@ -880,95 +879,95 @@ msgstr "სვეტების რაოდენობა (%d) აღემ msgid "number of index columns (%d) exceeds limit (%d)" msgstr "ინდექსის სვეტების რაოდენობა (%d) აღემატება ლიმიტს (%d)" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:959 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:978 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "ინდექსის მწკრივი მოითხოვს %zu ბაიტს, მაქსიმალური ზომა %zu" -#: access/common/printtup.c:291 commands/explain.c:5375 tcop/fastpath.c:107 tcop/fastpath.c:454 tcop/postgres.c:1940 +#: access/common/printtup.c:292 commands/explain_dr.c:94 tcop/fastpath.c:106 tcop/fastpath.c:453 tcop/postgres.c:1951 #, c-format msgid "unsupported format code: %d" msgstr "ფორმატის მხარდაუჭერელი კოდი: %d" -#: access/common/reloptions.c:519 access/common/reloptions.c:530 +#: access/common/reloptions.c:530 access/common/reloptions.c:541 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "სწორი მნიშვნელობებია \"on\", \"off\" და \"auto\"." -#: access/common/reloptions.c:541 +#: access/common/reloptions.c:552 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "სწორი მნიშვნელობებია \"local\" და \"cascaded\"." -#: access/common/reloptions.c:689 +#: access/common/reloptions.c:700 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "მომხმარებლის მიერ განსაზღვრული ურთიერთობის პარამეტრის ტიპებმა ლიმიტს გადააჭარბა" -#: access/common/reloptions.c:1231 +#: access/common/reloptions.c:1242 #, c-format msgid "RESET must not include values for parameters" msgstr "RESET პარამეტრების მნიშვნელობებს არ უნდა შეიცავდეს" -#: access/common/reloptions.c:1263 +#: access/common/reloptions.c:1274 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "პარამეტრების სახელების უცნობი სივრცე: \"%s\"" -#: access/common/reloptions.c:1300 commands/variable.c:1191 +#: access/common/reloptions.c:1311 commands/variable.c:1242 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "ცხრილები, აღწერილი WITH OIDS-ით, მხარდაუჭერელია" -#: access/common/reloptions.c:1468 +#: access/common/reloptions.c:1479 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "უცნობი პარამეტრი\"%s\"" -#: access/common/reloptions.c:1580 +#: access/common/reloptions.c:1591 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "პარამეტრი \"%s\" ერთზე მეტჯერაა მითთებული" -#: access/common/reloptions.c:1596 +#: access/common/reloptions.c:1607 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "არასწორი მნიშვნელობა ლოგიკური პარამეტრისთვის \"%s\": %s" -#: access/common/reloptions.c:1608 +#: access/common/reloptions.c:1619 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "არასწორი მნიშვნელობა მთელი რიცხვის პარამეტრისთვის \"%s\": %s" -#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 +#: access/common/reloptions.c:1625 access/common/reloptions.c:1645 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "მნიშვნელობა %s პარამეტრისთვის \"%s\" საზღვრებს გარეთაა" -#: access/common/reloptions.c:1616 +#: access/common/reloptions.c:1627 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "სწორი მნიშვნელობები \"%d\"-სა და \"%d\"-ს შორისაა." -#: access/common/reloptions.c:1628 +#: access/common/reloptions.c:1639 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "წილადი პარამეტრის (\"%s\") არასწორი მნიშვნელობა: %s" -#: access/common/reloptions.c:1636 +#: access/common/reloptions.c:1647 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "სწორი მნიშვნელობების დიაპაზონია \"%f\"-სა და \"%f\"-ს შორის." -#: access/common/reloptions.c:1658 +#: access/common/reloptions.c:1669 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "ჩამონათვალი პარამეტრის \"%s\" არასწორი მნიშვნელობა: %s" -#: access/common/reloptions.c:1989 +#: access/common/reloptions.c:2016 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "დაყოფილი ცხრილისთვის საცავის პარამეტრების მითითება შეუძლებელია" -#: access/common/reloptions.c:1990 +#: access/common/reloptions.c:2017 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "" @@ -1013,52 +1012,52 @@ msgstr "სხვა სესიების დროებით ინდე msgid "failed to re-find tuple within index \"%s\"" msgstr "კორტეჟის თავიდან პოვნის შეცდომა ინდექსში \"%s\"" -#: access/gin/ginscan.c:431 +#: access/gin/gininsert.c:1283 access/gin/ginutil.c:152 executor/execExpr.c:2244 utils/adt/array_userfuncs.c:1963 utils/adt/arrayfuncs.c:4028 utils/adt/arrayfuncs.c:6726 utils/adt/rowtypes.c:974 +#, c-format +msgid "could not identify a comparison function for type %s" +msgstr "ტიპისთვის \"%s\" შედარების ფუნქცია ვერ ვიპოვე" + +#: access/gin/ginscan.c:437 #, c-format msgid "old GIN indexes do not support whole-index scans nor searches for nulls" msgstr "ძველ GIN ინდექსებს არც ინდექსების სრული სკანირების მხარდაჭერა აქვს, არც ნულების ძებნის" -#: access/gin/ginscan.c:432 +#: access/gin/ginscan.c:438 #, c-format msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "გასასწორებლად გაუშვით REINDEX INDEX \"%s\"." -#: access/gin/ginutil.c:147 executor/execExpr.c:2191 utils/adt/arrayfuncs.c:4009 utils/adt/arrayfuncs.c:6705 utils/adt/rowtypes.c:974 -#, c-format -msgid "could not identify a comparison function for type %s" -msgstr "ტიპისთვის \"%s\" შედარების ფუნქცია ვერ ვიპოვე" - -#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 +#: access/gin/ginvalidate.c:83 access/gist/gistvalidate.c:84 access/hash/hashvalidate.c:89 access/spgist/spgvalidate.c:94 #, c-format msgid "operator family \"%s\" of access method %s contains support function %s with different left and right input types" msgstr "ოპერატორის ოჯახი \"%s\" (წვდომის მეთოდიდან %s) შეიცავს მხარდაჭერის ფუნქციას %s, რომელსაც სხვადასხვა მარცხენა და მარჯვენა შეყვანები გააჩნია" -#: access/gin/ginvalidate.c:258 +#: access/gin/ginvalidate.c:251 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d or %d" msgstr "ოპერატორის ოჯახი \"%s\" (წვდომის მეთოდიდან %s) აკლია მხარდაჭერის ფუნქია %d ან %d" -#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 access/spgist/spgvalidate.c:387 +#: access/gin/ginvalidate.c:323 access/gist/gistvalidate.c:348 access/spgist/spgvalidate.c:378 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "მხარდაჭერის ფუნქცია ნომრით %d არასწორია წვდომის მეთოდისთვის: %s" -#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:765 access/gist/gistvacuum.c:462 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "ინდექსი (\"%s\") შეიცავს შიდა კორტეჟს, რომელიც მონიშნულია, როგორც არასწორი" -#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:767 access/gist/gistvacuum.c:464 #, c-format msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1." msgstr "გამოწვეულია ავარიის აღდგენისას გვერდის არასწორი დაყოფისგან, PostgreSQL 9.1-მდე განახლებამდე." -#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 access/hash/hashutil.c:237 access/hash/hashutil.c:249 access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 access/nbtree/nbtpage.c:824 +#: access/gist/gist.c:768 access/gist/gistutil.c:801 access/gist/gistutil.c:812 access/gist/gistvacuum.c:465 access/hash/hashutil.c:226 access/hash/hashutil.c:237 access/hash/hashutil.c:249 access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "გადაატარეთ REINDEX." -#: access/gist/gist.c:1196 +#: access/gist/gist.c:1208 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "ინდექსის (%s) არასწორი დაყოფის გასწორება. ბლოკი %u" @@ -1073,33 +1072,33 @@ msgstr "picksplit მეთოდის შეცდომა სვეტის msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command." msgstr "ინდექსი ოპტიმალური არაა. ოპტიმიზაციისთვის დაუკავშირდით დეველოპერს ან სცადეთ ეს სვეტი CREATE INDEX ბრძანებაში, როგორც მეორე, ისე გამოიყენოთ." -#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 access/nbtree/nbtpage.c:810 +#: access/gist/gistutil.c:798 access/hash/hashutil.c:223 access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "ინდექსი \"%s\" ბლოკ %u-სთან მოულოდნელ ნულოვან გვერდს შეიცავს" -#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:809 access/hash/hashutil.c:234 access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "ინდექსი \"%s\" შეიცავს გაფუჭებულ გვერდს ბლოკთან %u" -#: access/gist/gistvalidate.c:202 +#: access/gist/gistvalidate.c:200 #, c-format msgid "operator family \"%s\" of access method %s contains unsupported ORDER BY specification for operator %s" msgstr "ოპერატორის ოჯახი \"%s\" (წვდომის მეთოდიდან %s) ოპერატორისთვის %s მხარდაუჭერელ ORDER BY-ის სპეფიციკაციას შეიცავს" -#: access/gist/gistvalidate.c:213 +#: access/gist/gistvalidate.c:211 #, c-format msgid "operator family \"%s\" of access method %s contains incorrect ORDER BY opfamily specification for operator %s" msgstr "ოპერატორის ოჯახი \"%s\" (წვდომის მეთოდიდან %s) ოპერატორისთვის %s არასწორ ORDER BY-ის სპეფიციკაციას შეიცავს" -#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:331 utils/adt/varchar.c:1008 utils/adt/varchar.c:1063 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:332 utils/adt/varchar.c:1000 utils/adt/varchar.c:1056 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "სტრიქონების ჰეშირებისთვის საჭირო კოლაციის გარკვევა შეუძლებელია" -#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:332 catalog/heap.c:672 catalog/heap.c:678 commands/createas.c:201 commands/createas.c:510 commands/indexcmds.c:2045 commands/tablecmds.c:18071 commands/view.c:81 regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 utils/adt/like_support.c:1024 utils/adt/varchar.c:738 utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 -#: utils/adt/varlena.c:1521 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:333 catalog/heap.c:679 catalog/heap.c:685 commands/createas.c:203 commands/createas.c:516 commands/indexcmds.c:2090 commands/tablecmds.c:19910 commands/view.c:80 regex/regc_pg_locale.c:242 utils/adt/formatting.c:1655 utils/adt/formatting.c:1719 utils/adt/formatting.c:1783 utils/adt/formatting.c:1847 utils/adt/like.c:163 utils/adt/like.c:194 utils/adt/like_support.c:1020 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1001 utils/adt/varchar.c:1057 utils/adt/varlena.c:1592 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "კოლაციის ხელით მისათითებლად გამოიყენეთ COLLATE." @@ -1109,7 +1108,7 @@ msgstr "კოლაციის ხელით მისათითებლ msgid "index row size %zu exceeds hash maximum %zu" msgstr "ინდექსის მწკრივის ზომა %zu აჭარბებს ჰეშის მაქსიმუმს %zu" -#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1020 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1039 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "ბაფერის გვერდზე დიდი მნიშვნელობების დაინდექსება შეუძლებელია." @@ -1124,7 +1123,7 @@ msgstr "გადავსებული ბლოკის არასწო msgid "out of overflow pages in hash index \"%s\"" msgstr "ჰეშ-ინდექსში \"%s\" გადავსების გვერდები საკმარისი არაა" -#: access/hash/hashsearch.c:311 +#: access/hash/hashsearch.c:313 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "ჰეშის ინდექსებს სრული ინდექსების სკანირების მხარდაჭერა არ გააჩნიათ" @@ -1139,47 +1138,52 @@ msgstr "ინდექსი \"%s\" ჰეშ ინდექსი არა msgid "index \"%s\" has wrong hash version" msgstr "ინდექსს \"%s\" ჰეშის არასწორი ვერსია აქვს" -#: access/hash/hashvalidate.c:198 +#: access/hash/hashvalidate.c:188 #, c-format msgid "operator family \"%s\" of access method %s lacks support function for operator %s" msgstr "ოპერატორის ოჯახს \"%s\" (წვდომის მეთოდიდან \"%s\") აკლია მხარდაჭერის ფუნქცია ოპერატორისთვის %s" -#: access/hash/hashvalidate.c:256 access/nbtree/nbtvalidate.c:276 +#: access/hash/hashvalidate.c:246 access/nbtree/nbtvalidate.c:272 #, c-format msgid "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "ოპერატორის ოჯახს \"%s\" წვდომის მეთოდში %s ჯვარედინი ტიპის ოპერატორები აკლია" -#: access/heap/heapam.c:2194 +#: access/heap/heapam.c:2257 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "პარალელურ დამხმარე პროცესში კორტეჟებს ვერ ჩასვამთ" -#: access/heap/heapam.c:2713 +#: access/heap/heapam.c:2776 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "პარალელური ოპერაციის დროს კორტეჟის წაშლა შეუძლებელია" -#: access/heap/heapam.c:2760 +#: access/heap/heapam.c:2823 #, c-format msgid "attempted to delete invisible tuple" msgstr "უხილავი კორტეჟის წაშლის მცდელობა" -#: access/heap/heapam.c:3208 access/heap/heapam.c:6081 +#: access/heap/heapam.c:3271 access/index/genam.c:829 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "პარალელური ოპერაციის დროს კორტეჟის განახლება შეუძლებელია" -#: access/heap/heapam.c:3336 +#: access/heap/heapam.c:3448 #, c-format msgid "attempted to update invisible tuple" msgstr "უხილავი კორტეჟის განახლების მცდელობა" -#: access/heap/heapam.c:4725 access/heap/heapam.c:4763 access/heap/heapam.c:5028 access/heap/heapam_handler.c:468 +#: access/heap/heapam.c:4959 access/heap/heapam.c:4997 access/heap/heapam.c:5262 access/heap/heapam_handler.c:470 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "ურთიერთობაში \"%s\" მწკრივის დაბლოკვის შეცდომა" -#: access/heap/heapam_handler.c:413 +#: access/heap/heapam.c:6376 commands/trigger.c:3350 executor/nodeModifyTable.c:2565 executor/nodeModifyTable.c:2655 +#, c-format +msgid "tuple to be updated was already modified by an operation triggered by the current command" +msgstr "" + +#: access/heap/heapam_handler.c:415 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update" msgstr "დასაბლოკი კორტეჟი პარალელური განახლების გამო უკვე სხვა დანაყოფშია გადატანილი" @@ -1194,8 +1198,8 @@ msgstr "მწკრივი ძალიან დიდია: ზომა % msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "ფაილში \"%s\" ჩაწერა შეუძლებელია. ჩაწერილია %d %d-დან: %m" -#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 access/transam/timeline.c:329 access/transam/timeline.c:481 access/transam/xlog.c:3249 access/transam/xlog.c:3440 access/transam/xlog.c:4277 access/transam/xlog.c:9199 access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 backup/basebackup_server.c:242 commands/dbcommands.c:494 postmaster/launch_backend.c:328 postmaster/postmaster.c:4112 postmaster/walsummarizer.c:1067 -#: replication/logical/origin.c:603 replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 utils/time/snapmgr.c:1234 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 access/transam/timeline.c:329 access/transam/timeline.c:481 access/transam/xlog.c:3382 access/transam/xlog.c:3590 access/transam/xlog.c:4454 access/transam/xlog.c:9456 access/transam/xlogfuncs.c:693 backup/basebackup_server.c:149 backup/basebackup_server.c:242 commands/dbcommands.c:495 postmaster/launch_backend.c:354 postmaster/postmaster.c:4085 postmaster/walsummarizer.c:1219 +#: replication/logical/origin.c:603 replication/slot.c:2252 storage/file/copydir.c:173 storage/file/copydir.c:261 storage/smgr/md.c:252 utils/time/snapmgr.c:1241 #, c-format msgid "could not create file \"%s\": %m" msgstr "ფაილის (%s) შექმნის შეცდომა: %m" @@ -1205,154 +1209,169 @@ msgstr "ფაილის (%s) შექმნის შეცდომა: %m" msgid "could not truncate file \"%s\" to %u: %m" msgstr "ფაილის (%s) %u-მდე მოკვეთის შეცდომა: %m" -#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 access/transam/timeline.c:424 access/transam/timeline.c:498 access/transam/xlog.c:3299 access/transam/xlog.c:3496 access/transam/xlog.c:4289 commands/dbcommands.c:506 postmaster/launch_backend.c:339 postmaster/launch_backend.c:351 replication/logical/origin.c:615 replication/logical/origin.c:657 replication/logical/origin.c:676 replication/logical/snapbuild.c:1771 replication/slot.c:2094 -#: storage/file/buffile.c:545 storage/file/copydir.c:197 utils/init/miscinit.c:1601 utils/init/miscinit.c:1612 utils/init/miscinit.c:1620 utils/misc/guc.c:4441 utils/misc/guc.c:4472 utils/misc/guc.c:5625 utils/misc/guc.c:5643 utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 access/transam/timeline.c:424 access/transam/timeline.c:498 access/transam/xlog.c:3443 access/transam/xlog.c:3646 access/transam/xlog.c:4466 commands/dbcommands.c:507 postmaster/launch_backend.c:365 postmaster/launch_backend.c:377 replication/logical/origin.c:615 replication/logical/origin.c:657 replication/logical/origin.c:676 replication/logical/snapbuild.c:1657 replication/slot.c:2287 +#: storage/file/buffile.c:545 storage/file/copydir.c:213 utils/init/miscinit.c:1660 utils/init/miscinit.c:1671 utils/init/miscinit.c:1679 utils/misc/guc.c:4488 utils/misc/guc.c:4519 utils/misc/guc.c:5673 utils/misc/guc.c:5691 utils/time/snapmgr.c:1246 utils/time/snapmgr.c:1253 #, c-format msgid "could not write to file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: access/heap/vacuumlazy.c:473 +#: access/heap/vacuumlazy.c:814 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "აგრესიული დამტვერსასრუტება \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:478 +#: access/heap/vacuumlazy.c:819 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "დამტვერსასრუტება \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:626 +#: access/heap/vacuumlazy.c:987 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "მომტვერსასრუტება დასრულებულია \"%s.%s.%s\": დასკანერებული ინდექსები: %d\n" -#: access/heap/vacuumlazy.c:637 +#: access/heap/vacuumlazy.c:998 #, c-format msgid "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "ჩაციკვლის თავიდან ასაცილებლად ავტომატური აგრესიული მომტვერსასრუტება ცხრილისთვის \"%s.%s.%s\": ინდექსის სკანირების რიცხვი: %d\n" -#: access/heap/vacuumlazy.c:639 +#: access/heap/vacuumlazy.c:1000 #, c-format msgid "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "ჩაციკვლის თავიდან ასაცილებლად ავტომატური მომტვერსასრუტება ცხრილისთვის \"%s.%s.%s\": ინდექსის სკანირების რიცხვი: %d\n" -#: access/heap/vacuumlazy.c:644 +#: access/heap/vacuumlazy.c:1005 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "ცხრილის (\"%s.%s.%s\") ავტომატური აგრესიული მომტვერსასრუტება: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:1007 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "ცხრილის (\"%s.%s.%s\") ავტომატური მომტვერსასრუტება: ინდექსების სკანირება: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:1014 #, c-format -msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" -msgstr "გვერდები: %u წაშლილი, %u რჩება, %u დასკანერებული (სულ %.2f%%)\n" +msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total), %u eagerly scanned\n" +msgstr "გვერდები: %u წაშლილი, %u რჩება, %u დასკანერებული (სულ %.2f%%), %u სასწრაფოდ სკანირებული\n" -#: access/heap/vacuumlazy.c:660 +#: access/heap/vacuumlazy.c:1023 #, c-format -msgid "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" -msgstr "კორტეჟები: %lld წაიშალა, %lld დარჩა, %lld მკვდარია, მაგრამ ჯერ ვერ წავშლი\n" +msgid "tuples: % removed, % remain, % are dead but not yet removable\n" +msgstr "კორტეჟები: % წაიშალა, % დარჩა, % მკვდარია, მაგრამ ჯერ ვერ წავშლი\n" -#: access/heap/vacuumlazy.c:666 +#: access/heap/vacuumlazy.c:1029 #, c-format -msgid "tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n" -msgstr "გასუფთავების ბლოკირების კონფლიქტის გამო გამოტოვებული სტრიქონების ვერსიები: %lld, %u გვერდიდან\n" +msgid "tuples missed: % dead from %u pages not removed due to cleanup lock contention\n" +msgstr "აცდენილი კორტეჟები: % მკვდრები არ წაშლილა %u გვერდიდან გასუფთავების ბლოკის დაბლოკვის გამო\n" -#: access/heap/vacuumlazy.c:672 +#: access/heap/vacuumlazy.c:1035 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "წაშლადი ამოჭრილი: %u, რომელიც იყო %d XID ასაკის, როცა ოპერაცია დასრულდა\n" -#: access/heap/vacuumlazy.c:679 +#: access/heap/vacuumlazy.c:1042 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "ახალი relfrozenxid: %u, რომელიც წინა მნიშვნელობაზე %d XID-ით წინაა\n" -#: access/heap/vacuumlazy.c:687 +#: access/heap/vacuumlazy.c:1050 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "ახალი relminmxid: %u, რომელიც წინა მნიშვნელობაზე %d MXID-ით წინაა\n" -#: access/heap/vacuumlazy.c:690 +#: access/heap/vacuumlazy.c:1053 +#, c-format +msgid "frozen: %u pages from table (%.2f%% of total) had % tuples frozen\n" +msgstr "გაყინული : %u გვერდს ცხრილიდან (%.2f%% სრული რაოდენობიდან) % კორტეჟი აქვს გაყინული\n" + +#: access/heap/vacuumlazy.c:1061 #, c-format -msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" -msgstr "გაყინული : %u გვერდს ცხრილიდან (%.2f%% სრული რაოდენობიდან) %lld კორტეჟი აქვს გაყინული\n" +msgid "visibility map: %u pages set all-visible, %u pages set all-frozen (%u were all-visible)\n" +msgstr "" -#: access/heap/vacuumlazy.c:698 +#: access/heap/vacuumlazy.c:1069 msgid "index scan not needed: " msgstr "ინდექსების სკანირება საჭირო არაა: " -#: access/heap/vacuumlazy.c:700 +#: access/heap/vacuumlazy.c:1071 msgid "index scan needed: " msgstr "ინდექსების სკანირება საჭიროა: " -#: access/heap/vacuumlazy.c:702 +#: access/heap/vacuumlazy.c:1073 #, c-format -msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" -msgstr "ცხრილის %u გვერდიდან (სულ %.2f%%) წაშლილია %lld ჩანაწერის მკვდარი იდენტიფიკატორი\n" +msgid "%u pages from table (%.2f%% of total) had % dead item identifiers removed\n" +msgstr "ცხრილის %u გვერდიდან (სულ %.2f%%) წაშლილია % ჩანაწერის მკვდარი იდენტიფიკატორი\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:1078 msgid "index scan bypassed: " msgstr "სკანირებისას გამოტოვებული ინდექსები: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:1080 msgid "index scan bypassed by failsafe: " msgstr "სკანირებისას უსაფრთხოების გამო გამოტოვებული ინდექსები: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:1082 #, c-format -msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" -msgstr "ცხრილის %u გვერდზე (სულ %.2f%%) ნაპოვნია %lld ჩანაწერის მკვდარი იდენტიფიკატორი\n" +msgid "%u pages from table (%.2f%% of total) have % dead item identifiers\n" +msgstr "ცხრილის %u გვერდზე (სულ %.2f%%) ნაპოვნია % ჩანაწერის მკვდარი იდენტიფიკატორი\n" -#: access/heap/vacuumlazy.c:726 +#: access/heap/vacuumlazy.c:1097 #, c-format msgid "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u reusable\n" msgstr "ინდექსი \"%s\": გვერდები: %u ჯამში %u ახლად წაშლილი, %u ამჟამად წაშლილი, %u მრავალჯერადი\n" -#: access/heap/vacuumlazy.c:738 commands/analyze.c:789 +#: access/heap/vacuumlazy.c:1112 commands/analyze.c:817 +#, c-format +msgid "delay time: %.3f ms\n" +msgstr "დაყოვნების დრო: %.3f მწმ\n" + +#: access/heap/vacuumlazy.c:1120 commands/analyze.c:825 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "I/O დროები: კითხვა: %.3f მწმ, ჩაწერა: %.3f მწმ\n" -#: access/heap/vacuumlazy.c:748 commands/analyze.c:792 +#: access/heap/vacuumlazy.c:1130 commands/analyze.c:828 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "კითხვის საშ. სიჩქარე: %.3f მბ/წმ, ჩაწერის საშ. სიჩქარე: %.3f მბ/წმ\n" -#: access/heap/vacuumlazy.c:751 commands/analyze.c:794 +#: access/heap/vacuumlazy.c:1133 commands/analyze.c:830 #, c-format -msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" -msgstr "ბაფერის გამოყენება: %lld მოხვედრა, %lld აცდენა, %lld ტურტლიანი\n" +msgid "buffer usage: % hits, % reads, % dirtied\n" +msgstr "ბუფერის გამოყენება: % მოხვედრა, % წაკითხვა, % ტურტლიანი\n" -#: access/heap/vacuumlazy.c:756 +#: access/heap/vacuumlazy.c:1138 commands/analyze.c:835 #, c-format -msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" -msgstr "WAL გამოყენება: %lld ჩანაწერი, %lld სრული გვერდის ასლი, %llu ბაიტი\n" +msgid "WAL usage: % records, % full page images, % bytes, % buffers full\n" +msgstr "WAL გამოყენება: % ჩანაწერი, % სრული გვერდის ასლი, % ბაიტი, % ბუფერი სავსეა\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:798 +#: access/heap/vacuumlazy.c:1143 commands/analyze.c:840 #, c-format msgid "system usage: %s" msgstr "სისტემური გამოყენება: %s" -#: access/heap/vacuumlazy.c:2172 +#: access/heap/vacuumlazy.c:1431 #, c-format -msgid "table \"%s\": removed %lld dead item identifiers in %u pages" -msgstr "ცხრილი \"%s\": წაიშალა %lld მკვდარი ჩანაწერის იდენტიფიკატორი %u გვერდზე" +msgid "disabling eager scanning after freezing %u eagerly scanned blocks of \"%s.%s.%s\"" +msgstr "" + +#: access/heap/vacuumlazy.c:2820 +#, c-format +msgid "table \"%s\": removed % dead item identifiers in %u pages" +msgstr "ცხრილი \"%s\": წაიშალა % მკვდარი ჩანაწერის იდენტიფიკატორი %u გვერდზე" -#: access/heap/vacuumlazy.c:2326 +#: access/heap/vacuumlazy.c:2992 #, c-format msgid "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans" msgstr "ცხრილის \"%s.%s.%s\" უმნიშვნელო ოპერაციის გამოტოვება დაცვის მიზნით %d ინდექსის სკანირების შემდეგ" -#: access/heap/vacuumlazy.c:2329 +#: access/heap/vacuumlazy.c:2995 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "ცხრილის relfrozenxid -ის და relminmxid -ის მნიშვნელობები ძალიან უკანაა წარშულში." -#: access/heap/vacuumlazy.c:2330 +#: access/heap/vacuumlazy.c:2996 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" @@ -1361,67 +1380,67 @@ msgstr "" "მხედველობაში იქონიეთ, რომ საჭიროა კონფიგურაციის პარამეტრის \"maintenance_work_mem\" ან \"autovacuum_work_mem\" გაზრდა.\n" "ასევე შეიძლება დაგჭირდეთ განიხილოთ მომტვერსასრუტების სხვა გზები, რომ დაეწიოთ ტრანზაქცების ID-ების გამოყოფას." -#: access/heap/vacuumlazy.c:2592 +#: access/heap/vacuumlazy.c:3258 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "%s: წაკვეთის შეჩერება ბლოკირების კონფლიქტური მოთხოვნის გამო" -#: access/heap/vacuumlazy.c:2662 +#: access/heap/vacuumlazy.c:3328 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "ცხრილი \"%s\": წაიკვეთა %u-დან %u გვერდზე" -#: access/heap/vacuumlazy.c:2724 +#: access/heap/vacuumlazy.c:3390 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "ცხრილი %s: წაკვეთის შეჩერება ბლოკირების კონფლიქტური მოთხოვნის გამო" -#: access/heap/vacuumlazy.c:2843 +#: access/heap/vacuumlazy.c:3509 #, c-format msgid "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary tables in parallel" msgstr "%s-ზე პარალელური მომტვერსასრუტების გამორთვა --- დროებითი ცხრილების პარალელური მომტვერსასრუტება შეუძლებელია" -#: access/heap/vacuumlazy.c:3113 +#: access/heap/vacuumlazy.c:3776 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "ურთიერთობის(%3$s.%4$s) წანაცვლების(%2$u) ბლოკის(%1$u) სკანირებისას" -#: access/heap/vacuumlazy.c:3116 +#: access/heap/vacuumlazy.c:3779 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "%u ბლოკის (ურთიერთობის %s.%s) სკანირებისას" -#: access/heap/vacuumlazy.c:3120 +#: access/heap/vacuumlazy.c:3783 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "ურთიერთობის სკანირებისას \"%s.%s\"" -#: access/heap/vacuumlazy.c:3128 +#: access/heap/vacuumlazy.c:3791 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "ბლოკის %u, წანაცვლება %u (ურთიერთობის \"%s.%s\") მომტვერსასრუტებისას" -#: access/heap/vacuumlazy.c:3131 +#: access/heap/vacuumlazy.c:3794 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "ბლოკის (%u) მომტვერსასრუტებისას (ურთიერთობიდან \"%s.%s\")" -#: access/heap/vacuumlazy.c:3135 +#: access/heap/vacuumlazy.c:3798 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "ურთერთობის დამტვერსასრუტებისას \"%s.%s\"" -#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1113 +#: access/heap/vacuumlazy.c:3803 commands/vacuumparallel.c:1126 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "ინდექსის (%s) მომტვერსასრუტებისას (ურთიერთობიდან \"%s.%s\")" -#: access/heap/vacuumlazy.c:3145 commands/vacuumparallel.c:1119 +#: access/heap/vacuumlazy.c:3808 commands/vacuumparallel.c:1132 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "ინდექსის \"%s\" მოსუფთავებისას, რომელიც ეკუთვნის ურთიერთობას \"%s.%s\"" -#: access/heap/vacuumlazy.c:3151 +#: access/heap/vacuumlazy.c:3814 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "ურთიერთობის \"%s.%s\" %u ბლოკამდე მოკვეთისას" @@ -1436,22 +1455,22 @@ msgstr "წვდომის მეთოდი \"%s\" არ არის ტ msgid "index access method \"%s\" does not have a handler" msgstr "ინდექსის წვდომის მეთოდს \"%s\" დამმუშავებელი არ აქვს" -#: access/index/genam.c:487 +#: access/index/genam.c:498 #, c-format msgid "transaction aborted during system catalog scan" msgstr "ტრანზაქცია გაუქმდა სისტემური კატალოგის სკანირებისას" -#: access/index/genam.c:655 access/index/indexam.c:82 +#: access/index/genam.c:663 access/index/indexam.c:82 #, c-format msgid "cannot access index \"%s\" while it is being reindexed" msgstr "ინდექსთან \"%s\" წვდომა მაშინ, როცა მისი რეინდექსი მიმდინარეობს, შეუძლებელია" -#: access/index/indexam.c:203 catalog/objectaddress.c:1356 commands/indexcmds.c:2873 commands/tablecmds.c:281 commands/tablecmds.c:305 commands/tablecmds.c:17766 commands/tablecmds.c:19584 +#: access/index/indexam.c:203 catalog/objectaddress.c:1361 commands/indexcmds.c:2982 commands/tablecmds.c:284 commands/tablecmds.c:308 commands/tablecmds.c:19599 commands/tablecmds.c:21519 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\" ინდექსი არაა" -#: access/index/indexam.c:1028 +#: access/index/indexam.c:1075 #, c-format msgid "operator class %s has no options" msgstr "ოპერატორის კლასს %s პარამეტრები არ გააჩნია" @@ -1471,7 +1490,7 @@ msgstr "გასაღები უკვე არსებობს: %s." msgid "This may be because of a non-immutable index expression." msgstr "შეიძლებa ინდექსის გამოსახულების შეცვლადობის ბრალი იყოს." -#: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 parser/parse_utilcmd.c:2298 +#: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 parser/parse_utilcmd.c:2483 #, c-format msgid "index \"%s\" is not a btree" msgstr "ინდექსი \"%s\" ორობითი ხე არაა" @@ -1491,17 +1510,17 @@ msgstr "ინდექსი (\"%s\") ნახევრად მკვდა msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it." msgstr "შესაძლებელია გამოწვეული იყოს შეწყვეტილი მომტვერსასრუტების მიერ 9.3 ან უფრო ძველ ვერსიაში. განახლებამდე საჭიროა REINDEX-ის გადატარება." -#: access/nbtree/nbtutils.c:5112 +#: access/nbtree/nbtutils.c:4247 #, c-format msgid "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" msgstr "ინდექსის სტრიქონის ზომა %zu btree-ის ვერსიის (%u) მაქსიმალურ (%zu) მნიშვნელობაზე მეტია, ინდექსისთვის \"%s\"" -#: access/nbtree/nbtutils.c:5118 +#: access/nbtree/nbtutils.c:4252 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "ინდექსის მწკრივები გადაბმულია კორტეჟზე (%u, %u) ურთიერთობაში \"%s\"." -#: access/nbtree/nbtutils.c:5122 +#: access/nbtree/nbtutils.c:4256 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1510,57 +1529,57 @@ msgstr "" "ბუფერის გვერდის 1/3-ზე მეტი მნიშვნელობების ინდექსირება შეუძლებელია.\n" "სჯობს დააყენოთ ამ მნიშვნელობის MD5 ჰეშის ფუნქციის ინდექსი ან სრული ტექსტური ინდექსირება გამოიყენეთ." -#: access/nbtree/nbtvalidate.c:246 +#: access/nbtree/nbtvalidate.c:242 #, c-format msgid "operator family \"%s\" of access method %s is missing support function for types %s and %s" msgstr "ოპერატორის ოჯახი \"%s\" წვდომის მეთოდის %s აკლია მხარდაჭერის ფუნქცია ტიპებისთვის %s და %s" -#: access/sequence/sequence.c:75 access/table/table.c:145 optimizer/util/plancat.c:143 +#: access/sequence/sequence.c:75 access/table/table.c:145 optimizer/util/plancat.c:144 #, c-format msgid "cannot open relation \"%s\"" msgstr "ურთიერთობის (\"%s\") გახსნა შეუძლებელია" -#: access/spgist/spgutils.c:245 +#: access/spgist/spgutils.c:251 #, c-format msgid "compress method must be defined when leaf type is different from input type" msgstr "როდესაც ფოთლის ტიპი შეყვანის ტიპისგან განსხვავდება, შეკუმშვის მეთოდის მითითება აუცილებელია" -#: access/spgist/spgutils.c:1017 +#: access/spgist/spgutils.c:1036 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "SP-GiST-ის შიდა კორტეჟის ზომა%zu მაქსიმუმს %zu აჭარბებს" -#: access/spgist/spgvalidate.c:136 +#: access/spgist/spgvalidate.c:128 #, c-format msgid "SP-GiST leaf data type %s does not match declared type %s" msgstr "SP-GiST ფოთლის მონაცემების ტიპი %s არ ემთხვევა აღწერილ ტიპს: %s" -#: access/spgist/spgvalidate.c:302 +#: access/spgist/spgvalidate.c:294 #, c-format msgid "operator family \"%s\" of access method %s is missing support function %d for type %s" msgstr "ოპერატორის ოჯახს \"%s\" ( წვდომის მეთოდისგან \"%s\") აკლია მხარდაჭერის ფუნქცია (%d) ტიპისთვის: %s" -#: access/table/tableam.c:255 +#: access/table/tableam.c:256 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "კორტეჟის იდენტიფიკატორი (%u, %u) არასწორია ურთიერთობისთვის: \"%s\"" -#: access/table/tableamapi.c:109 +#: access/table/tableamapi.c:106 #, c-format msgid "\"%s\" cannot be empty." msgstr "\"%s\" ცარიელი არ შეიძლება იყოს." -#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4858 +#: access/table/tableamapi.c:113 access/transam/xlogrecovery.c:4879 #, c-format msgid "\"%s\" is too long (maximum %d characters)." msgstr "\"%s\" ძალიან გრძელია (მაქს %d სიმბოლო)" -#: access/table/tableamapi.c:139 +#: access/table/tableamapi.c:136 #, c-format msgid "table access method \"%s\" does not exist" msgstr "ცხრილის წვდომის მეთოდი \"%s\" არ არსებობს" -#: access/table/tableamapi.c:144 +#: access/table/tableamapi.c:141 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "ცხრილის წვდომის მეთოდი \"%s\" არ არსებობს." @@ -1590,12 +1609,12 @@ msgstr "დარწმუნდით, რომ ძირითად სე msgid "Make sure the configuration parameter \"%s\" is set." msgstr "დარწმუნდით, რომ კონფიგურაციის პარამეტრი \"%s\" დაყენებულია." -#: access/transam/multixact.c:1050 +#: access/transam/multixact.c:1097 #, c-format msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"" msgstr "ბაზაში (\"%s\") მონაცემების ჩაციკვლის თავიდან ასაცილებლად მონაცემთა ბაზა ბრძანებებს, რომლებიც ახალ მულტიტრანზაქციებს ანიჭებენ, არ იღებს" -#: access/transam/multixact.c:1052 access/transam/multixact.c:1059 access/transam/multixact.c:1083 access/transam/multixact.c:1092 access/transam/varsup.c:158 access/transam/varsup.c:165 +#: access/transam/multixact.c:1099 access/transam/multixact.c:1106 access/transam/multixact.c:1130 access/transam/multixact.c:1139 access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" @@ -1604,65 +1623,65 @@ msgstr "" "გაუშვით მთელი ბაზის მომტვერსასრუტება.\n" "ასევე შეიძლება დაგჭირდეთ ძველი მომზადებული ტრანზაქციების გადაცემა ან გაუქმება, ან წაშალეთ გაჭედილი რეპლიკაციის სლოტები." -#: access/transam/multixact.c:1057 +#: access/transam/multixact.c:1104 #, c-format msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u" msgstr "ბაზაში (OID-ით \"%u\") მონაცემების გადატანის თავიდან ასაცილებლად მონაცემთა ბაზა ბრძანებებს, რომლებიც ახალ მულტიტრანზაქციებს ანიჭებენ, არ იღებს" -#: access/transam/multixact.c:1078 access/transam/multixact.c:2433 +#: access/transam/multixact.c:1125 access/transam/multixact.c:2482 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used" msgstr[0] "კიდევ %2$u მულტიტრანზაქციის გამოსაყენებლად ბაზის (%1$s) მომტვერსასრუტებაა საჭირო" msgstr[1] "კიდევ %2$u მულტიტრანზაქციის გამოსაყენებლად ბაზის (%1$s) მომტვერსასრუტებაა საჭირო" -#: access/transam/multixact.c:1087 access/transam/multixact.c:2442 +#: access/transam/multixact.c:1134 access/transam/multixact.c:2491 #, c-format msgid "database with OID %u must be vacuumed before %u more MultiXactId is used" msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used" msgstr[0] "კიდევ %2$u მულტიტრანზაქციის გამოსაყენებლად OID-ი %1$u -ის მქონე ბაზა ჯერ უნდა დამტვერსასრუტდეს" msgstr[1] "კიდევ %2$u მულტიტრანზაქციის გამოსაყენებლად OID-ი %1$u -ის მქონე ბაზა ჯერ უნდა დამტვერსასრუტდეს" -#: access/transam/multixact.c:1148 +#: access/transam/multixact.c:1195 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "მულტიტრანზაქციული \"წევრების\" ლიმიტი გადაჭარბებულია" -#: access/transam/multixact.c:1149 +#: access/transam/multixact.c:1196 #, c-format msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member." msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members." msgstr[0] "ბრძანება კი შექმნიდა %u-წევრიან მულტიტრანზაქციას, მაგრამ დარჩენილი ადგილი მხოლოდ %u წევრს ეყოფა." msgstr[1] "ბრძანება კი შექმნიდა %u-წევრიან მულტიტრანზაქციას, მაგრამ დარჩენილი ადგილი მხოლოდ %u წევრს ეყოფა." -#: access/transam/multixact.c:1154 +#: access/transam/multixact.c:1201 #, c-format msgid "Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." msgstr "მთელ ბაზაზე მომტვერსასრუტების შესრულება ბაზაში OID-ით %u შემცირებული \"vacuum_multixact_freeze_min_age\" და \"vacuum_multixact_freeze_table_age\" პარამეტრებით." -#: access/transam/multixact.c:1185 +#: access/transam/multixact.c:1232 #, c-format msgid "database with OID %u must be vacuumed before %d more multixact member is used" msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used" msgstr[0] "ბაზა OID-ით %u უნდა მომტვერსასრუტდეს მანამდე, სანამ კიდევ %d მულტიტრანზაქციული წევრი იქნება გამოყენებული" msgstr[1] "ბაზა OID-ით %u უნდა მომტვერსასრუტდეს მანამდე, სანამ კიდევ %d მულტიტრანზაქციული წევრი იქნება გამოყენებული" -#: access/transam/multixact.c:1190 +#: access/transam/multixact.c:1237 #, c-format msgid "Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." msgstr "მთელ ბაზაზე მომტვერსასრუტების შესრულება მითითებულ ბაზაში შემცირებული \"vacuum_multixact_freeze_min_age\" და \"vacuum_multixact_freeze_table_age\" პარამეტრებით." -#: access/transam/multixact.c:1330 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "MultiXactId %u აღარ არსებობს - აშკარა გადატანა" -#: access/transam/multixact.c:1336 +#: access/transam/multixact.c:1383 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "MultiXactId %u ჯერ არ არის შექმნილი - აშკარა გადატანა" -#: access/transam/multixact.c:2438 access/transam/multixact.c:2447 +#: access/transam/multixact.c:2487 access/transam/multixact.c:2496 #, c-format msgid "" "To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" @@ -1671,61 +1690,61 @@ msgstr "" "მულტიტრანზაქციების მინიჭებების თავიდან ასაცილებლად გაუშვით VACUUM მთელ ბაზაზე იმ მონაცემთა ბაზისთვის.\n" "შეიძლება, ასევე, დაგჭირდეთ ძველი მომზადებული ტრანზაქციების კომიტი ან დაბრუნება, ან გამოუყენებელი რეპლიკაციის სლოტების წაშლა." -#: access/transam/multixact.c:2726 +#: access/transam/multixact.c:2775 #, c-format msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" msgstr "მულტიტრანზაქციული წევრის გადატანის დაცვის ფუნქციები გათიშულია, რადგან უძველესი საკონტროლო წერტილის მქონე მულტიტრანზაქცია %u დისკზე არ არსებობს" -#: access/transam/multixact.c:2748 +#: access/transam/multixact.c:2797 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "მულტიტრანზაქციების ჩაციკვლისგან დაცვის მექანიზმები ახლა ჩართულია" -#: access/transam/multixact.c:3138 +#: access/transam/multixact.c:3188 #, c-format msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "უძველესი მულტიტრანზაქცია %u ვერ ვიპოვე. უახლესი მულტიტრანზაქციაა %u. წაკვეთა გამოტოვებული იქნება" -#: access/transam/multixact.c:3156 +#: access/transam/multixact.c:3206 #, c-format msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation" msgstr "მულტიტრანზაქციამდე %u მოკვეთა შეუძლებელია, რადგან ის დისკზე არ არსებობს. მოკვეთა გამოტოვებული იქნება" -#: access/transam/multixact.c:3475 +#: access/transam/multixact.c:3525 #, c-format msgid "invalid MultiXactId: %u" msgstr "არასწორი MultiXactId: %u" -#: access/transam/parallel.c:731 access/transam/parallel.c:850 +#: access/transam/parallel.c:752 access/transam/parallel.c:871 #, c-format msgid "parallel worker failed to initialize" msgstr "პარალელური დამხმარე პროცესის ინიციალიზაციის შეცდომა" -#: access/transam/parallel.c:732 access/transam/parallel.c:851 +#: access/transam/parallel.c:753 access/transam/parallel.c:872 #, c-format msgid "More details may be available in the server log." msgstr "მეტი დეტალები შეიძლება სერვერის ჟურნალში იყოს ხელმისაწვდომი." -#: access/transam/parallel.c:912 +#: access/transam/parallel.c:933 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "postmaster-ი დასრულდა პარალელური ტრანზაქციისას" -#: access/transam/parallel.c:1099 +#: access/transam/parallel.c:1120 #, c-format msgid "lost connection to parallel worker" msgstr "პარალელური დამხმარე პროცესთან კავშირი დაკარგულია" -#: access/transam/parallel.c:1155 access/transam/parallel.c:1157 +#: access/transam/parallel.c:1176 access/transam/parallel.c:1178 msgid "parallel worker" msgstr "პარალელური დამხმარე პროცესი" -#: access/transam/parallel.c:1327 replication/logical/applyparallelworker.c:890 +#: access/transam/parallel.c:1348 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "დინამიური გაზიარებული მეხსიერების სეგმენტის მიბმის შეცდომა" -#: access/transam/parallel.c:1332 replication/logical/applyparallelworker.c:896 +#: access/transam/parallel.c:1353 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "დინამიური გაზიარებული მეხსიერების სეგმენტის არასწორი მაგიური რიცხვი" @@ -1785,62 +1804,62 @@ msgstr "რესურსის მმართველს ID-ით %d იგ msgid "registered custom resource manager \"%s\" with ID %d" msgstr "რეგისტრირებულია მორგებული რესურსის მმართველი \"%s\" ID-ით %d" -#: access/transam/slru.c:346 +#: access/transam/slru.c:360 #, c-format -msgid "\"%s\" must be a multiple of %d" -msgstr "\"%s\" %d-ის ნამრავლი უნდა იყოს" +msgid "\"%s\" must be a multiple of %d." +msgstr "\"%s\" %d-ის ნამრავლი უნდა იყოს." -#: access/transam/slru.c:815 +#: access/transam/slru.c:832 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "ფაილი \"%s\" არ არსებობს. წაკითხული იქნება, როგორც ნულებ" -#: access/transam/slru.c:1044 access/transam/slru.c:1050 access/transam/slru.c:1058 access/transam/slru.c:1063 access/transam/slru.c:1070 access/transam/slru.c:1075 access/transam/slru.c:1082 access/transam/slru.c:1089 +#: access/transam/slru.c:1061 access/transam/slru.c:1067 access/transam/slru.c:1075 access/transam/slru.c:1080 access/transam/slru.c:1087 access/transam/slru.c:1092 access/transam/slru.c:1099 access/transam/slru.c:1106 #, c-format msgid "could not access status of transaction %u" msgstr "ტრანზაქციის %u სტატუსის წვდომის შეცდომა" -#: access/transam/slru.c:1045 +#: access/transam/slru.c:1062 #, c-format msgid "Could not open file \"%s\": %m." msgstr "ფაილის (%s) გახსნის შეცდომა: %m." -#: access/transam/slru.c:1051 +#: access/transam/slru.c:1068 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "ფაილში \"%s\" წანაცვლებაზე %d გადახვევის შეცდომა: %m." -#: access/transam/slru.c:1059 +#: access/transam/slru.c:1076 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "კითხვის შეცდომა ფაილიდან \"%s\" წანაცვლებასთან %d: %m." -#: access/transam/slru.c:1064 +#: access/transam/slru.c:1081 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "კითხვის შეცდომა ფაილიდან \"%s\" წანაცვლებასთან %d: ყველა ბაიტის წაკითხვა შეუძლებელია." -#: access/transam/slru.c:1071 +#: access/transam/slru.c:1088 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "ფაილში (\"%s\") ჩაწერის შეცდომა წანაცვლებასთან %d: %m." -#: access/transam/slru.c:1076 +#: access/transam/slru.c:1093 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "ფაილში (\"%s\") ჩაწერის შეცდომა წანაცვლებასთან %d: ყველა ბაიტის ჩაწერა შეუძლებელია." -#: access/transam/slru.c:1083 +#: access/transam/slru.c:1100 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "ფაილის (%s) fsync-ის შეცდომა: %m." -#: access/transam/slru.c:1090 +#: access/transam/slru.c:1107 #, c-format msgid "Could not close file \"%s\": %m." msgstr "ფაილის (%s) დახურვის შეცდომა: %m." -#: access/transam/slru.c:1416 +#: access/transam/slru.c:1433 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "საქაღალდის გასუფთავების შეცდომა: \"%s\" აშკარა ჩაციკვლა" @@ -1905,12 +1924,12 @@ msgstr "საჭიროა \"max_prepared_tranzactions\"-ის არან msgid "transaction identifier \"%s\" is already in use" msgstr "ტრანზაქციის იდენტიფიკატორი \"%s\" უკვე გამოიყენება" -#: access/transam/twophase.c:404 access/transam/twophase.c:2541 +#: access/transam/twophase.c:404 access/transam/twophase.c:2530 #, c-format msgid "maximum number of prepared transactions reached" msgstr "მიღწეულია მომზადებული ტრანზაქციების მაქსიმალური რაოდენობა" -#: access/transam/twophase.c:405 access/transam/twophase.c:2542 +#: access/transam/twophase.c:405 access/transam/twophase.c:2531 #, c-format msgid "Increase \"max_prepared_transactions\" (currently %d)." msgstr "გაზარდეთ \"max_prepared_transactions\" (ამჟამად %d)." @@ -1945,147 +1964,147 @@ msgstr "ტრანზაქციის დასამთავრებლ msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "მომზადებული ტრანზაქცია იდენტიფიკატორით \"%s\" არ არსებობს" -#: access/transam/twophase.c:1190 +#: access/transam/twophase.c:1174 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "ორფაზიანი მდგომარეობის ფაილის მაქსიმალური სიგრძე გადაჭარბებულია" -#: access/transam/twophase.c:1345 +#: access/transam/twophase.c:1329 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" msgstr[0] "ფაილის არასწორი ზომა \"%s\": %lld ბაიტი" msgstr[1] "ფაილის არასწორი ზომა \"%s\": %lld ბაიტი" -#: access/transam/twophase.c:1354 +#: access/transam/twophase.c:1338 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "ფაილისთვის \"%s\" CRC-ს წანაცვლების არასწორი სწორება" -#: access/transam/twophase.c:1372 +#: access/transam/twophase.c:1356 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "ფაილის \"%s\" წაკითხვა შეუძლებელია: წაკითხულია %d %lld-დან" -#: access/transam/twophase.c:1387 +#: access/transam/twophase.c:1371 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "ფაილში (\"%s\") დამახსოვრებული მაგიური რიცხვი არასწორია" -#: access/transam/twophase.c:1393 +#: access/transam/twophase.c:1377 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "ფაილში (\"%s\") დამახსოვრებული ზომა არასწორია" -#: access/transam/twophase.c:1405 +#: access/transam/twophase.c:1389 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "გამოთვლილი CRC საკონტროლო ჯამი არ ემთხვევა მნიშვნელობას, რომელიც ფაილში \"%s\" წერია" -#: access/transam/twophase.c:1435 access/transam/xlogrecovery.c:565 postmaster/walsummarizer.c:821 replication/logical/logical.c:210 replication/walsender.c:836 +#: access/transam/twophase.c:1419 access/transam/xlogrecovery.c:571 postmaster/walsummarizer.c:943 replication/logical/logical.c:211 replication/walsender.c:812 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "შეცდომა WAL კითხვის პროცესორის გამოყოფისას." -#: access/transam/twophase.c:1445 +#: access/transam/twophase.c:1429 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "\"WAL\"-დან 2ფაზიანი მდგომარეობის წაკითხვის შეცდომა მისამართზე %X/%X: %s" -#: access/transam/twophase.c:1450 +#: access/transam/twophase.c:1434 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "\"WAL\"-დან 2ფაზიანი მდგომარეობის წაკითხვის შეცდომა მისამართზე %X/%X" -#: access/transam/twophase.c:1458 +#: access/transam/twophase.c:1442 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "\"WAL\"-ში მოსალოდნელი ორფაზიანი მდგომარეობის მონაცემები მისამართზე %X/%X არ არსებობს" -#: access/transam/twophase.c:1754 +#: access/transam/twophase.c:1744 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "ფაილის (\"%s\") თავიდან შექმნის შეცდომა: %m" -#: access/transam/twophase.c:1881 +#: access/transam/twophase.c:1871 #, c-format msgid "%u two-phase state file was written for a long-running prepared transaction" msgid_plural "%u two-phase state files were written for long-running prepared transactions" msgstr[0] "დიდხანს-გაშვებული მომზადებული ტრანზაქციებისთვის %u ორფაზიანი მდგომარეობის ფაილი ჩაიწერა" msgstr[1] "დიდხანს-გაშვებული მომზადებული ტრანზაქციებისთვის %u ორფაზიანი მდგომარეობის ფაილი ჩაიწერა" -#: access/transam/twophase.c:2117 +#: access/transam/twophase.c:2106 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "მიმდინარეობს გაზიარებული მეხსიერებიდან წინასწარ მომზადებული ტრანზაქციის აღდგენა: %u" -#: access/transam/twophase.c:2210 +#: access/transam/twophase.c:2199 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "ორფაზიანი მდგომარეობის გაჭედილი ფაილის მოცილება ტრანზაქციისთვის %u" -#: access/transam/twophase.c:2217 +#: access/transam/twophase.c:2206 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "ორფაზიანი მდგომარეობის გაჭედილი მდგომარეობის წაშლა ტრანზაქციისთვის: %u" -#: access/transam/twophase.c:2230 +#: access/transam/twophase.c:2219 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "მომავალი ორფაზიანი მდგომარეობის ფაილის წაშლა ტრანზაქციისთვის %u" -#: access/transam/twophase.c:2237 +#: access/transam/twophase.c:2226 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "მომავალი ორფაზიანი მდგომარეობის მეხსიერებიდან წაშლა ტრანზაქციისთვის %u" -#: access/transam/twophase.c:2262 +#: access/transam/twophase.c:2251 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "ორფაზიანი მდგომარეობის დაზიანებული ფაილი ტრანზაქციისთვის %u" -#: access/transam/twophase.c:2267 +#: access/transam/twophase.c:2256 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "ორფაზიანი მდგომარეობის დაზიანებული მეხსიერება ტრანზაქციისთვის %u" -#: access/transam/twophase.c:2524 +#: access/transam/twophase.c:2513 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "ორფაზიანი მდგომარეობის ფაილის აღდგენა ტრანზაქციისთვის %u შეუძლებელია" -#: access/transam/twophase.c:2526 +#: access/transam/twophase.c:2515 #, c-format msgid "Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk." msgstr "" -#: access/transam/twophase.c:2534 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 +#: access/transam/twophase.c:2523 storage/file/fd.c:514 utils/fmgr/dfmgr.c:199 #, c-format msgid "could not access file \"%s\": %m" msgstr "ფაილის (%s) წვდომის შეცდომა: %m" #: access/transam/varsup.c:156 #, c-format -msgid "database is not accepting commands that assign new XIDs to avoid wraparound data loss in database \"%s\"" -msgstr "ბაზაში (\"%s\") მონაცემების ჩაციკვლის თავიდან ასაცილებლად მონაცემთა ბაზა ბრძანებებს, რომლებიც ახალ XID-ებს ანიჭებენ, არ იღებს" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"" +msgstr "" #: access/transam/varsup.c:163 #, c-format -msgid "database is not accepting commands that assign new XIDs to avoid wraparound data loss in database with OID %u" -msgstr "ბაზაში (OID-ით \"%u\") მონაცემების გადატანის თავიდან ასაცილებლად მონაცემთა ბაზა ბრძანებებს, რომლებიც ახალ XID-ებს ანიჭებენ, არ იღებს" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u" +msgstr "" #: access/transam/varsup.c:175 access/transam/varsup.c:490 #, c-format msgid "database \"%s\" must be vacuumed within %u transactions" msgstr "ბაზა \"%s\" ტრანზაქციაში %u უნდა მომტვერსასრუტდეს" -#: access/transam/varsup.c:178 access/transam/varsup.c:185 access/transam/varsup.c:493 access/transam/varsup.c:500 +#: access/transam/varsup.c:178 #, c-format msgid "" -"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"XID-ების მინიჭებების თავიდან ასაცილებლად გაუშვით VACUUM მთელ ბაზაზე იმ მონაცემთა ბაზისთვის.\n" +"ტრანზაქციის ID-ების მინიჭებების თავიდან ასაცილებლად გაუშვით VACUUM მთელ ბაზაზე იმ მონაცემთა ბაზისთვის.\n" "შეიძლება, ასევე, დაგჭირდეთ ძველი მომზადებული ტრანზაქციების კომიტი ან დაბრუნება, ან გამოუყენებელი რეპლიკაციის სლოტების წაშლა." #: access/transam/varsup.c:182 access/transam/varsup.c:497 @@ -2093,561 +2112,516 @@ msgstr "" msgid "database with OID %u must be vacuumed within %u transactions" msgstr "ბაზა \"%u\" %u ტრანზაქციის განმავლობაში უნდა მომტვერსასრუტდეს" -#: access/transam/xact.c:649 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 access/transam/varsup.c:500 +#, c-format +msgid "" +"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "" +"XID-ების მინიჭებების თავიდან ასაცილებლად გაუშვით VACUUM მთელ ბაზაზე იმ მონაცემთა ბაზისთვის.\n" +"შეიძლება, ასევე, დაგჭირდეთ ძველი მომზადებული ტრანზაქციების კომიტი ან დაბრუნება, ან გამოუყენებელი რეპლიკაციის სლოტების წაშლა." + +#: access/transam/xact.c:652 #, c-format -msgid "cannot assign XIDs during a parallel operation" -msgstr "პარალელური ოპერაციის დროს XID-ების მინიჭება შეუძლებელია" +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "პარალელური ოპერაციის დროს ტრანზაქციის ID-ების მინიჭება შეუძლებელია" -#: access/transam/xact.c:840 +#: access/transam/xact.c:843 #, c-format msgid "cannot modify data in a parallel worker" msgstr "პარალელურ დამხმარე პროცესში მონაცემების შეცვლა შეუძლებელია" -#: access/transam/xact.c:1115 +#: access/transam/xact.c:1118 #, c-format msgid "cannot start commands during a parallel operation" msgstr "პარალელური ოპერაციის დროს ბრძანებების გაშვება შეუძლებელია" -#: access/transam/xact.c:1123 +#: access/transam/xact.c:1126 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "ტრანზაქციაში 2^32-2 ბრძანებაზე მეტი ვერ იქნება" -#: access/transam/xact.c:1664 +#: access/transam/xact.c:1695 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "გადაცილებულია გადაცემული ქვეტრანზაქციების მაქსიმალური რაოდენობა: %d" -#: access/transam/xact.c:2561 +#: access/transam/xact.c:2616 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "ტრანზაქციაზე, რომელიც დროებით ობიექტებზე მუშაობდა, PREPARE-ს ვერ იზამთ" -#: access/transam/xact.c:2571 +#: access/transam/xact.c:2626 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "ტრანზაქციაზე, რომლიდანაც სწრაფი ასლები გაიტანეს, PREPARE-ს ვერ გაუშვებთ" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3593 +#: access/transam/xact.c:3657 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s ქვეტრანზაქციის ბლოკის შიგნით ვერ გაეშვება" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3603 +#: access/transam/xact.c:3667 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%s ქვეტრანზაქციაში ვერ გაეშვება" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3613 -#, c-format -msgid "%s cannot be executed within a pipeline" -msgstr "%s ფუნქციიდან ვერ გაეშვება" - -#. translator: %s represents an SQL statement name -#: access/transam/xact.c:3623 +#: access/transam/xact.c:3677 #, c-format msgid "%s cannot be executed from a function" msgstr "%s ფუნქციიდან ვერ გაეშვება" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3694 access/transam/xact.c:4019 access/transam/xact.c:4098 access/transam/xact.c:4221 access/transam/xact.c:4372 access/transam/xact.c:4441 access/transam/xact.c:4552 +#: access/transam/xact.c:3748 access/transam/xact.c:4070 access/transam/xact.c:4149 access/transam/xact.c:4272 access/transam/xact.c:4423 access/transam/xact.c:4492 access/transam/xact.c:4603 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%s მხოლოდ ტრანზაქციის ბლოკში შეიძლება იყოს გამოყენებული" -#: access/transam/xact.c:3905 +#: access/transam/xact.c:3956 #, c-format msgid "there is already a transaction in progress" msgstr "ტრანზაქცია უკვე მიმდინარეობს" -#: access/transam/xact.c:4024 access/transam/xact.c:4103 access/transam/xact.c:4226 +#: access/transam/xact.c:4075 access/transam/xact.c:4154 access/transam/xact.c:4277 #, c-format msgid "there is no transaction in progress" msgstr "ტრანზაქცია გაშვებული არაა" -#: access/transam/xact.c:4114 +#: access/transam/xact.c:4165 #, c-format msgid "cannot commit during a parallel operation" msgstr "პარალელური ოპერაციის დროს გადაცემა შეუძლებელია" -#: access/transam/xact.c:4237 +#: access/transam/xact.c:4288 #, c-format msgid "cannot abort during a parallel operation" msgstr "პარალელური ოპერაციის დროს გაუქმება შეუძლებელია" -#: access/transam/xact.c:4336 +#: access/transam/xact.c:4387 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "პარალელური ოპერაციის დროს შესანახი წერტილების აღწერა შეუძლებელია" -#: access/transam/xact.c:4423 +#: access/transam/xact.c:4474 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "პარალელური ოპერაციის დროს შესანახი წერტილების წაშლა შეუძლებელია" -#: access/transam/xact.c:4433 access/transam/xact.c:4484 access/transam/xact.c:4544 access/transam/xact.c:4593 +#: access/transam/xact.c:4484 access/transam/xact.c:4535 access/transam/xact.c:4595 access/transam/xact.c:4644 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "შესანახი წერტილი არ არსებობს: %s" -#: access/transam/xact.c:4490 access/transam/xact.c:4599 +#: access/transam/xact.c:4541 access/transam/xact.c:4650 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "შესანახი წერტილების მიმდინარე დონეზე შესანახი წერტილი არ არსებობს: %s" -#: access/transam/xact.c:4532 +#: access/transam/xact.c:4583 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "პარალელური ოპერაციის დროს შენახულ წერტილზე დაბრუნება შეუძლებელია" -#: access/transam/xact.c:5376 +#: access/transam/xact.c:5438 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "ტრანზაქციაში 2^32-1 ქვეტრანზაქციაზე მეტი ვერ იქნება" -#: access/transam/xlog.c:1536 +#: access/transam/xlog.c:1552 #, c-format msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" msgstr "" -#: access/transam/xlog.c:1763 +#: access/transam/xlog.c:1779 #, c-format msgid "cannot read past end of generated WAL: requested %X/%X, current position %X/%X" msgstr "" -#: access/transam/xlog.c:2204 access/transam/xlog.c:4495 +#: access/transam/xlog.c:2342 access/transam/xlog.c:4690 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WAL სეგმენტის ზომა ორის ხარისხი უნდა იყოს, შუალედიდან 1მბ-1გბ." -#: access/transam/xlog.c:2222 +#: access/transam/xlog.c:2360 #, c-format msgid "\"%s\" must be set to -1 during binary upgrade mode." msgstr "ბინარული განახლების რეჟიმისას \"%s\"-ის მნიშვნელობა -1-ზე უნდა დააყენოთ." -#: access/transam/xlog.c:2471 +#: access/transam/xlog.c:2597 #, c-format msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" msgstr "ჟურნალის ფაილში \"%s\" ჩაწერის შეცდომა წანაცვლება %u, სიგრძე %zu: %m" -#: access/transam/xlog.c:3733 access/transam/xlogutils.c:831 replication/walsender.c:3045 +#: access/transam/xlog.c:3883 access/transam/xlogutils.c:820 replication/walsender.c:3050 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "მოთხოვნილი WAL სეგმენტი %s უკვე წაშლილია" -#: access/transam/xlog.c:4055 +#: access/transam/xlog.c:4205 #, c-format msgid "could not rename file \"%s\": %m" msgstr "ფაილის გადარქმევის შეცდომა %s: %m" -#: access/transam/xlog.c:4098 access/transam/xlog.c:4109 access/transam/xlog.c:4130 +#: access/transam/xlog.c:4248 access/transam/xlog.c:4259 access/transam/xlog.c:4280 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "wal-ის აუცილებელი საქაღალდე \"%s\" არ არსებობს" -#: access/transam/xlog.c:4115 access/transam/xlog.c:4136 +#: access/transam/xlog.c:4265 access/transam/xlog.c:4286 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "ნაკლული WAL საქაღალდის შექმნა: \"%s\"" -#: access/transam/xlog.c:4119 access/transam/xlog.c:4139 commands/dbcommands.c:3242 +#: access/transam/xlog.c:4269 access/transam/xlog.c:4289 commands/dbcommands.c:3276 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "ნაკლული საქაღალდის (\"%s\") შექმნის შეცდომა: %m" -#: access/transam/xlog.c:4206 +#: access/transam/xlog.c:4356 #, c-format msgid "could not generate secret authorization token" msgstr "ავთენტიკაციისთვის ერთჯერადი კოდის გენერაციის შეცდომა" -#: access/transam/xlog.c:4357 access/transam/xlog.c:4367 access/transam/xlog.c:4393 access/transam/xlog.c:4401 access/transam/xlog.c:4409 access/transam/xlog.c:4415 access/transam/xlog.c:4423 access/transam/xlog.c:4431 access/transam/xlog.c:4439 access/transam/xlog.c:4447 access/transam/xlog.c:4455 access/transam/xlog.c:4463 access/transam/xlog.c:4473 access/transam/xlog.c:4481 utils/init/miscinit.c:1758 +#: access/transam/xlog.c:4534 access/transam/xlog.c:4544 access/transam/xlog.c:4570 access/transam/xlog.c:4580 access/transam/xlog.c:4590 access/transam/xlog.c:4596 access/transam/xlog.c:4606 access/transam/xlog.c:4616 access/transam/xlog.c:4626 access/transam/xlog.c:4636 access/transam/xlog.c:4646 access/transam/xlog.c:4656 access/transam/xlog.c:4668 access/transam/xlog.c:4676 utils/init/miscinit.c:1817 #, c-format msgid "database files are incompatible with server" msgstr "ბაზის ფაილები სერვერთან თავსებადი არაა" -#: access/transam/xlog.c:4358 +#: access/transam/xlog.c:4535 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)." msgstr "ბაზის კლასტერის ინიციალიზაცია მოხდა PG_CONTROL_VERSION %d (0x%08x)-ით, მაგრამ სერვერის აგებისას PG_CONTROL_VERSION %d (0x%08x)." -#: access/transam/xlog.c:4362 +#: access/transam/xlog.c:4539 #, c-format msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb." msgstr "ეს შეიძლება ბაიტების არასწორი დალაგების პრობლემაც იყოს. როგორც ჩანს, initdb გჭირდებათ." -#: access/transam/xlog.c:4368 +#: access/transam/xlog.c:4545 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "ბაზის კლასტერის ინიციალიზაცია მოხდა PG_CONTROL_VERSION %d, მაგრამ სერვერის აგებისას PG_CONTROL_VERSION %d." -#: access/transam/xlog.c:4371 access/transam/xlog.c:4397 access/transam/xlog.c:4405 access/transam/xlog.c:4411 +#: access/transam/xlog.c:4548 access/transam/xlog.c:4576 access/transam/xlog.c:4586 access/transam/xlog.c:4592 #, c-format msgid "It looks like you need to initdb." msgstr "როგორც ჩანს, initdb გჭირდებათ." -#: access/transam/xlog.c:4383 +#: access/transam/xlog.c:4560 #, c-format msgid "incorrect checksum in control file" msgstr "არასწორი საკონტროლო ჯამი pg_control-ის ფაილში" -#: access/transam/xlog.c:4394 -#, c-format -msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა CATALOG_VERSION_NO %d -ით, მაგრამ სერვერი აგებულია CATALOG_VERSION_NO %d-ით." - -#: access/transam/xlog.c:4402 +#. translator: %s is a variable name and %d is its value +#: access/transam/xlog.c:4572 access/transam/xlog.c:4582 access/transam/xlog.c:4598 access/transam/xlog.c:4608 access/transam/xlog.c:4618 access/transam/xlog.c:4628 access/transam/xlog.c:4638 access/transam/xlog.c:4648 access/transam/xlog.c:4658 #, c-format -msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა MAXALIGN %d -ით, მაგრამ სერვერი აგებულია MAXALIGN %d-ით." +msgid "The database cluster was initialized with %s %d, but the server was compiled with %s %d." +msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა %s %d -ით, მაგრამ სერვერი აგებულია %s %d-ით." -#: access/transam/xlog.c:4410 +#: access/transam/xlog.c:4591 #, c-format msgid "The database cluster appears to use a different floating-point number format than the server executable." msgstr "როგორც ჩანს, ბაზის კლასტერი წილადი რიცხვების სხვა ფორმატს იყენებს, ვიდრე სერვერის გამშვები ფაილი." -#: access/transam/xlog.c:4416 -#, c-format -msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა BLCKSZ %d -ით, მაგრამ სერვერი აგებულია BLCKSZ %d-ით." - -#: access/transam/xlog.c:4419 access/transam/xlog.c:4427 access/transam/xlog.c:4435 access/transam/xlog.c:4443 access/transam/xlog.c:4451 access/transam/xlog.c:4459 access/transam/xlog.c:4467 access/transam/xlog.c:4476 access/transam/xlog.c:4484 +#: access/transam/xlog.c:4602 access/transam/xlog.c:4612 access/transam/xlog.c:4622 access/transam/xlog.c:4632 access/transam/xlog.c:4642 access/transam/xlog.c:4652 access/transam/xlog.c:4662 access/transam/xlog.c:4671 access/transam/xlog.c:4679 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "როგორც ჩანს, გჭირდებათ თავიდან ააგოთ პროდუქტი, ან initdb." -#: access/transam/xlog.c:4424 -#, c-format -msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა RELSEG_SIZE%d -ით, მაგრამ სერვერი აგებულია RELSEG_SIZE %d-ით." - -#: access/transam/xlog.c:4432 -#, c-format -msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა XLOG_BLCKSZ%d -ით, მაგრამ სერვერი აგებულია XLOG_BLCKSZ%d-ით." - -#: access/transam/xlog.c:4440 -#, c-format -msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა NAMEDATALEN %d -ით, მაგრამ სერვერი აგებულია NAMEDATALEN %d-ით." - -#: access/transam/xlog.c:4448 -#, c-format -msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა INDEX_MAX_KEYS %d -ით, მაგრამ სერვერი აგებულია INDEX_MAX_KEYS %d-ით." - -#: access/transam/xlog.c:4456 -#, c-format -msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა TOAST_MAX_CHUNK_SIZE %d -ით, მაგრამ სერვერი აგებულია TOAST_MAX_CHUNK_SIZE %d-ით." - -#: access/transam/xlog.c:4464 -#, c-format -msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." -msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა LOBLKSIZE %d -ით, მაგრამ სერვერი აგებულია LOBLKSIZE %d-ით." - -#: access/transam/xlog.c:4474 +#: access/transam/xlog.c:4669 #, c-format msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL." msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა USE_FLOAT8_BYVAL-ის გარეშე, მაგრამ სერვერი აგებულია USE_FLOAT8_BYVAL-ით." -#: access/transam/xlog.c:4482 +#: access/transam/xlog.c:4677 #, c-format msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL." msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა USE_FLOAT8_BYVA -ის გარეშე, მაგრამ სერვერი აგებულია USE_FLOAT8_BYVAL-ით." -#: access/transam/xlog.c:4491 +#: access/transam/xlog.c:4686 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" msgstr[1] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" -#: access/transam/xlog.c:4504 -#, c-format -msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" -msgstr "\"min_wal_size\"-ი \"wal_segment_size\"-ზე მინიმუმ ორჯერ მეტი უნდა იყოს" - -#: access/transam/xlog.c:4508 +#. translator: both %s are GUC names +#: access/transam/xlog.c:4700 access/transam/xlog.c:4706 #, c-format -msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" -msgstr "\"max_wal_size\"-ი \"wal_segment_size\"-ზე, მინიმუმ, ორჯერ მეტი უნდა იყოს" +msgid "\"%s\" must be at least twice \"%s\"" +msgstr "\"%s\", სულ ცოტა, ორჯერ მეტი უნდა იყოს \"%s\"-ზე" -#: access/transam/xlog.c:4656 catalog/namespace.c:4681 commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 replication/slot.c:2429 utils/error/elog.c:2214 +#: access/transam/xlog.c:4868 catalog/namespace.c:4696 commands/tablespace.c:1210 commands/user.c:2542 commands/variable.c:72 replication/slot.c:2655 tcop/postgres.c:3631 utils/error/elog.c:2274 #, c-format msgid "List syntax is invalid." msgstr "სია სინტაქსი არასწორია." -#: access/transam/xlog.c:4702 commands/user.c:2545 commands/variable.c:173 utils/error/elog.c:2240 +#: access/transam/xlog.c:4914 commands/user.c:2558 commands/variable.c:173 tcop/postgres.c:3647 utils/error/elog.c:2300 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "უცნობი საკვანძო სიტყვა: \"%s\"." -#: access/transam/xlog.c:5122 +#: access/transam/xlog.c:5341 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "ფაილში წინასწარ-ჩაწერადი ჟურნალის ფაილის დასაწყისის ჩაწერის შეცდომა: %m" -#: access/transam/xlog.c:5130 +#: access/transam/xlog.c:5349 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "ფაილში წინასწარ-ჩაწერადი ჟურნალის ფაილის დასაწყისის fsync-ის შეცდომა: %m" -#: access/transam/xlog.c:5136 +#: access/transam/xlog.c:5355 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "ფაილში წინასწარ-ჩაწერადი ჟურნალის ფაილის დასაწყისის დახურვის შეცდომა: %m" -#: access/transam/xlog.c:5354 +#: access/transam/xlog.c:5580 #, c-format msgid "WAL was generated with \"wal_level=minimal\", cannot continue recovering" msgstr "WAL-ი გენერირებული იყო \"wal_level=minimal\"-ით. აღდგენა ვერ გაგრძელდება" -#: access/transam/xlog.c:5355 +#: access/transam/xlog.c:5581 #, c-format msgid "This happens if you temporarily set \"wal_level=minimal\" on the server." msgstr "ეს ხდება, თუ სერვერზე დროებით \"wal_level=minimal\"-ს დააყენებთ." -#: access/transam/xlog.c:5356 +#: access/transam/xlog.c:5582 #, c-format msgid "Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." msgstr "გამოიყენეთ მარქაფი, რომელიც \"wal_level\"-ის \"minimal\"-ზე მეტზე დაყენების შემდეგ აიღეთ." -#: access/transam/xlog.c:5421 +#: access/transam/xlog.c:5647 #, c-format msgid "control file contains invalid checkpoint location" msgstr "საკონტროლო ფაილი საკონტროლო წერტილის არასწორ მდებარეობას შეიცავს" -#: access/transam/xlog.c:5432 +#: access/transam/xlog.c:5658 #, c-format msgid "database system was shut down at %s" msgstr "მონაცემთა ბაზის სისტემის გათიშვის დრო: %s" -#: access/transam/xlog.c:5438 +#: access/transam/xlog.c:5664 #, c-format msgid "database system was shut down in recovery at %s" msgstr "მონაცემთა ბაზის სისტემის აღდგენისას გათიშვის დრო: %s" -#: access/transam/xlog.c:5444 +#: access/transam/xlog.c:5670 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "მონაცემთა ბაზა შეწყვეტილია; ბოლოს ჩართული იყო: %s" -#: access/transam/xlog.c:5450 +#: access/transam/xlog.c:5676 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "მონაცემთა ბაზის სისტემის აღდგენისას გათიშვის დრო: %s" -#: access/transam/xlog.c:5452 +#: access/transam/xlog.c:5678 #, c-format msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "ეს ალბათ ნიშნავს, რომ ზოგიერთი მონაცემი დაზიანებულია და აღდგენისთვის ბოლო მარქაფის გამოყენება მოგიწევთ." -#: access/transam/xlog.c:5458 +#: access/transam/xlog.c:5684 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "მონაცემთა ბაზის სისტემა გაითიშა აღდგენისას ჟურნალის დროს %s" -#: access/transam/xlog.c:5460 +#: access/transam/xlog.c:5686 #, c-format msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target." msgstr "თუ ეს კიდევ ერთხელ მაინც მოხდა, ეს ნიშნავს, რომ მონაცემები დაზიანებულია და უფრო ძველი აღდგენის სამიზნე უნდა აირჩიოთ." -#: access/transam/xlog.c:5466 +#: access/transam/xlog.c:5692 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "მონაცემთა ბაზა შეწყვეტილია; ბოლოს ჩართული იყო: %s" -#: access/transam/xlog.c:5473 +#: access/transam/xlog.c:5699 #, c-format msgid "control file contains invalid database cluster state" msgstr "კონტროლის ფაილი ბაზის კლასტერის არასწორ მდგომარეობას შეიცავს" -#: access/transam/xlog.c:5860 +#: access/transam/xlog.c:6087 #, c-format msgid "WAL ends before end of online backup" msgstr "WAL ონლაინ მარქაფის დასასრულამდე მთავრდება" -#: access/transam/xlog.c:5861 +#: access/transam/xlog.c:6088 #, c-format msgid "All WAL generated while online backup was taken must be available at recovery." msgstr "აღდგენისას ონლაინ მარქაფის აღებისას გენერირებული ყველა WAL-ი ხელმისაწვდომი უნდა იყოს." -#: access/transam/xlog.c:5865 +#: access/transam/xlog.c:6092 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL აღდგენის შეთანხმებულ წერტილამდე მთავრდება" -#: access/transam/xlog.c:5911 +#: access/transam/xlog.c:6138 #, c-format msgid "selected new timeline ID: %u" msgstr "დროის ახალი ხაზის არჩეული ID: %u" -#: access/transam/xlog.c:5944 +#: access/transam/xlog.c:6171 #, c-format msgid "archive recovery complete" msgstr "არქივიდან აღდგენა დასრულდა" -#: access/transam/xlog.c:6552 +#: access/transam/xlog.c:6803 #, c-format msgid "shutting down" msgstr "მიმდინარეობს გამორთვა" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6591 +#: access/transam/xlog.c:6842 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "გადატვირთვის წერტილი დაიწყო:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6603 +#: access/transam/xlog.c:6854 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "საკონტროლო წერტილი იწყება:%s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6668 +#: access/transam/xlog.c:6919 #, c-format -msgid "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" +msgid "restartpoint complete: wrote %d buffers (%.1f%%), wrote %d SLRU buffers; %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "" -#: access/transam/xlog.c:6691 +#: access/transam/xlog.c:6943 #, c-format -msgid "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" +msgid "checkpoint complete: wrote %d buffers (%.1f%%), wrote %d SLRU buffers; %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "" -#: access/transam/xlog.c:7165 +#: access/transam/xlog.c:7429 #, c-format msgid "concurrent write-ahead log activity while database system is shutting down" msgstr "კონკურენტული წინასწარ-ჩაწერადი ჟურნალის აქტივობა, სანამ მონაცემთა ბაზა მუშაობას ასრულებს" -#: access/transam/xlog.c:7749 +#: access/transam/xlog.c:8016 #, c-format msgid "recovery restart point at %X/%X" msgstr "აღდგენის გადატვირთვის წერტილი: %X/%X" -#: access/transam/xlog.c:7751 +#: access/transam/xlog.c:8018 #, c-format msgid "Last completed transaction was at log time %s." msgstr "უკანასკნელად დასრულებული ტრანზაქცია მოხდა ჟურნალის დროით %s." -#: access/transam/xlog.c:8013 +#: access/transam/xlog.c:8280 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "აღდგენის წერტილი \"%s\" შექმნილია %X/%X -სთან" -#: access/transam/xlog.c:8220 +#: access/transam/xlog.c:8487 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "ონლაინ მარქაფი გაუქმდა. აღდგენა ვერ გაგრძელდება" -#: access/transam/xlog.c:8277 +#: access/transam/xlog.c:8545 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "გამორთვის საკონტროლო წერტილში ნაპოვნია დროის ხაზი %u მოულოდნელია (უნდა იყოს %u)" -#: access/transam/xlog.c:8335 +#: access/transam/xlog.c:8603 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "ჩართვის საკონტროლო წერტილში ნაპოვნია დროის ხაზი %u მოულოდნელია (უნდა იყოს %u)" -#: access/transam/xlog.c:8364 +#: access/transam/xlog.c:8632 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "აღდგენის ბოლო საკონტროლო წერტილში ნაპოვნია დროის ხაზი %u მოულოდნელია (უნდა იყოს %u)" -#: access/transam/xlog.c:8635 +#: access/transam/xlog.c:8902 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "გამჭოლად-ჩაწერადი ფაილის (%s) fsync-ის შეცდომა: %m" -#: access/transam/xlog.c:8640 +#: access/transam/xlog.c:8907 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "ფაილის \"%s\" fdatasync შეუძლებელია: %m" -#: access/transam/xlog.c:8727 access/transam/xlog.c:9063 +#: access/transam/xlog.c:8984 access/transam/xlog.c:9320 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "ონლაინ მარქაფისთვის WAL-ის მიმდინარე დონე საკმარისი არაა" -#: access/transam/xlog.c:8728 access/transam/xlogfuncs.c:248 +#: access/transam/xlog.c:8985 access/transam/xlog.c:9321 access/transam/xlogfuncs.c:249 #, c-format msgid "\"wal_level\" must be set to \"replica\" or \"logical\" at server start." msgstr "სერვისის გაშვებისას \"wal_level\"-ის მნიშვნელობა უნდა იყოს \"replica\" ან \"logical\"." -#: access/transam/xlog.c:8733 +#: access/transam/xlog.c:8990 #, c-format msgid "backup label too long (max %d bytes)" msgstr "მარქაფის ჭდე ძალიან გრძელია (max %d ბაიტი)" -#: access/transam/xlog.c:8854 +#: access/transam/xlog.c:9111 #, c-format msgid "WAL generated with \"full_page_writes=off\" was replayed since last restartpoint" msgstr "" -#: access/transam/xlog.c:8856 access/transam/xlog.c:9152 +#: access/transam/xlog.c:9113 access/transam/xlog.c:9409 #, c-format msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, and then try an online backup again." msgstr "ეს ნიშნავს, რომ უქმეზე აღებული მარქაფი დაზიანებულია და არ უნდა გამოიყენოთ. ჩართეთ ძირითად სერვერზე \"full_page_writes\" და გაუშვით CHECKPOINT და მხოლოდ შემდეგ სცადეთ ონლაინ აღდგენა." -#: access/transam/xlog.c:8936 backup/basebackup.c:1417 utils/adt/misc.c:354 +#: access/transam/xlog.c:9193 backup/basebackup.c:1419 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "სიმბოლური ბმის \"%s\" წაკითხვის შეცდომა: %m" -#: access/transam/xlog.c:8943 backup/basebackup.c:1422 utils/adt/misc.c:359 +#: access/transam/xlog.c:9200 backup/basebackup.c:1424 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "%s: სიმბმული ძალიან გრძელია" -#: access/transam/xlog.c:9064 -#, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "სერვისის გაშვებისას wal_level -ის მნიშვნელობა უნდა იყოს \"replica\" ან \"logical\"." - -#: access/transam/xlog.c:9102 backup/basebackup.c:1281 +#: access/transam/xlog.c:9359 backup/basebackup.c:1283 #, c-format msgid "the standby was promoted during online backup" msgstr "უქმე წახალისდა ონლაინ მარქაფის მიმდინარეობის დროს" -#: access/transam/xlog.c:9103 backup/basebackup.c:1282 +#: access/transam/xlog.c:9360 backup/basebackup.c:1284 #, c-format msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup." msgstr "ეს ნიშნავს, რომ მარქაფი, რომლის აღებაც მიმდინარეობს, დაზიანებულია და არ უნდა გამოიყენოთ. სცადეთ, სხვა ონლაინ მარქაფი აიღოთ." -#: access/transam/xlog.c:9150 +#: access/transam/xlog.c:9407 #, c-format msgid "WAL generated with \"full_page_writes=off\" was replayed during online backup" msgstr "" -#: access/transam/xlog.c:9266 +#: access/transam/xlog.c:9523 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "ძირითადი მარქაფი დასრულდა. ველოდები აუცილებელი WAL-ის სეგმენტების დაარქივებას" -#: access/transam/xlog.c:9280 +#: access/transam/xlog.c:9537 #, c-format msgid "still waiting for all required WAL segments to be archived (%d seconds elapsed)" msgstr "ჯერ კიდევ ველოდები ყველა აუცილებელი WAL სეგმენტის დაარქივებას (გასულია %d წამი)" -#: access/transam/xlog.c:9282 +#: access/transam/xlog.c:9539 #, c-format msgid "Check that your \"archive_command\" is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." msgstr "" -#: access/transam/xlog.c:9289 +#: access/transam/xlog.c:9546 #, c-format msgid "all required WAL segments have been archived" msgstr "ყველა საჭირო WAL სეგმენტი დაარქივებულია" -#: access/transam/xlog.c:9293 +#: access/transam/xlog.c:9550 #, c-format msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup" msgstr "" -#: access/transam/xlog.c:9332 +#: access/transam/xlog.c:9589 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "მარქაფი გაუქმდა, რადგან უკანაბოლომ მუშაობა pg_backup_stop-ის გამოძახებამდე დაასრულა" @@ -2690,269 +2664,269 @@ msgstr "არქივის სტატუსის ფაილის (%s) msgid "could not write archive status file \"%s\": %m" msgstr "არქივის სტატუსის ფაილის (%s) ჩაწერის შეცდომა: %m" -#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 +#: access/transam/xlogfuncs.c:70 backup/basebackup.c:999 #, c-format msgid "a backup is already in progress in this session" msgstr "ამ სესიაში მარქაფი უკვე მიმდინარეობს" -#: access/transam/xlogfuncs.c:140 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "backup is not in progress" msgstr "მარქაფი არ მიმდინარეობს" -#: access/transam/xlogfuncs.c:141 +#: access/transam/xlogfuncs.c:142 #, c-format msgid "Did you call pg_backup_start()?" msgstr "თქვენ გამოიძახეთ pg_backup_start()?" -#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 access/transam/xlogfuncs.c:323 +#: access/transam/xlogfuncs.c:185 access/transam/xlogfuncs.c:243 access/transam/xlogfuncs.c:282 access/transam/xlogfuncs.c:303 access/transam/xlogfuncs.c:324 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "WAL კონტროლის ფუნქციების შესრულება აღდგენის დროს შეუძლებელია." -#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 access/transam/xlogfuncs.c:447 +#: access/transam/xlogfuncs.c:210 access/transam/xlogfuncs.c:390 access/transam/xlogfuncs.c:448 #, c-format msgid "%s cannot be executed during recovery." msgstr "%s არ შეიძლება შესრულდეს აღდგენის დროს." -#: access/transam/xlogfuncs.c:215 +#: access/transam/xlogfuncs.c:216 #, c-format msgid "pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" msgstr "pg_log_standby_snapshot()-ის გამოყენება შესაძლებელია, მხოლოდ, მაშინ, როცა \"wal_level\" >= \"replica\"" -#: access/transam/xlogfuncs.c:247 +#: access/transam/xlogfuncs.c:248 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "WAL დონე არ არის საკმარისი აღდგენის წერტილის შესაქმნელად" -#: access/transam/xlogfuncs.c:255 +#: access/transam/xlogfuncs.c:256 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "აღდგენის წერტილისთვის მნიშვნელობა ძალიან გრძელია (მაქს. %d სიმბოლო)" -#: access/transam/xlogfuncs.c:486 +#: access/transam/xlogfuncs.c:487 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "არასწორი WAL ფაილის სახელი \"%s\"" -#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 access/transam/xlogfuncs.c:679 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 access/transam/xlogfuncs.c:680 #, c-format msgid "recovery is not in progress" msgstr "აღდგენა არ მიმდინარეობს" -#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 access/transam/xlogfuncs.c:680 +#: access/transam/xlogfuncs.c:524 access/transam/xlogfuncs.c:554 access/transam/xlogfuncs.c:578 access/transam/xlogfuncs.c:601 access/transam/xlogfuncs.c:681 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "აღდგენის კონტროლის ფუნქციების შესრულება მხოლოდ აღდგენის დროს შეიძლება." -#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "standby promotion is ongoing" msgstr "მინდინარეობს უქმობის დაწინაურება" -#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 +#: access/transam/xlogfuncs.c:530 access/transam/xlogfuncs.c:560 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "წახალისების დაწყების შემდეგ %s-ის შესრულება შეუძლებელია." -#: access/transam/xlogfuncs.c:685 +#: access/transam/xlogfuncs.c:686 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "\"wait_seconds\" უარყოფითი ან ნულოვანი არ უნდა იყოს" -#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 +#: access/transam/xlogfuncs.c:708 storage/ipc/signalfuncs.c:293 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "postmaster-ისთვის სიგნალის გაგზავნის შეცდომა: %m" -#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#: access/transam/xlogfuncs.c:740 libpq/be-secure.c:241 libpq/be-secure.c:350 #, c-format msgid "terminating connection due to unexpected postmaster exit" msgstr "მიერთების შეწყვეტა postmaster-ის მოულოდნელი გასვლის გამო" -#: access/transam/xlogfuncs.c:740 +#: access/transam/xlogfuncs.c:741 #, c-format msgid "while waiting on promotion" msgstr "წახალისების მოლოდინისას" -#: access/transam/xlogfuncs.c:744 +#: access/transam/xlogfuncs.c:745 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" msgstr[0] "სერვერი არ წახალისდა %d წამში" msgstr[1] "სერვერი არ წახალისდა %d წამში" -#: access/transam/xlogprefetcher.c:1088 +#: access/transam/xlogprefetcher.c:1086 #, c-format -msgid "\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()." -msgstr "\"recovery_prefetch\" პლატფორმებზე, რომლებსაც posix_fadvise() არ აქვთ, მხარდაჭერილი არაა." +msgid "\"recovery_prefetch\" is not supported on platforms that lack support for issuing read-ahead advice." +msgstr "\"recovery_prefetch\" პლატფორმებზე, რომლებსაც წინასწარ-წაკითხვის მითითება არ აქვთ, მხარდაჭერილი არაა." -#: access/transam/xlogreader.c:619 +#: access/transam/xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი წანაცვლება მისამართზე %X/%X: მოველოდი მინიმუმ %u, მივიღე %u" -#: access/transam/xlogreader.c:628 +#: access/transam/xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord მოთხოვნილია %X/%X-ის მიერ" -#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 +#: access/transam/xlogreader.c:670 access/transam/xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი სიგრძე მისამართზე %X/%X: მოველოდი მინიმუმ %u, მივიღე %u" -#: access/transam/xlogreader.c:758 +#: access/transam/xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "მისამართზე %X/%X contrecord ალამი არ არსებობს" -#: access/transam/xlogreader.c:771 +#: access/transam/xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "contrecord -ის არასწორი სიგრძე %u (მოველოდი %lld) მისამართზე %X/%X" -#: access/transam/xlogreader.c:1142 +#: access/transam/xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "რესურსის მმართველის არასწორი ID %u მისამართზე %X/%X" -#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 +#: access/transam/xlogreader.c:1156 access/transam/xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "ჩანაწერი არასწორი წინა ბმულით %X/%X მისამართზე %X/%X" -#: access/transam/xlogreader.c:1209 +#: access/transam/xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "რესურსის მმართველის მონაცემების არასწორი საკონტროლო რიცხვი ჩანაწერში მისამართზე %X/%X" -#: access/transam/xlogreader.c:1243 +#: access/transam/xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი მაგიური რიცხვი %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 +#: access/transam/xlogreader.c:1259 access/transam/xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი საინფორმაციო ბიტები %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: access/transam/xlogreader.c:1274 +#: access/transam/xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: WAL ფაილის ბაზის სისტემის იდენტიფიკატორია %llu, pg_control-ის ბაზის სისტემის იდენტიფიკატორია %llu" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: WAL ფაილის ბაზის სისტემის იდენტიფიკატორია %, pg_control-ის ბაზის სისტემის იდენტიფიკატორია %" -#: access/transam/xlogreader.c:1282 +#: access/transam/xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: გვერდის თავსართში მითითებული სეგმენტის ზომა არასწორია" -#: access/transam/xlogreader.c:1288 +#: access/transam/xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: გვერდის თავსართში მითითებული XLOG_BLKSZ არასწორია" -#: access/transam/xlogreader.c:1320 +#: access/transam/xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "მოულოდნელი pageaddr %X/%X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: access/transam/xlogreader.c:1346 +#: access/transam/xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "მიმდევრობის-გარე დროის ხაზის ID %u (%u-ის შემდეგ) ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: access/transam/xlogreader.c:1749 +#: access/transam/xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ურიგო block_id %u მისამართზე %X/%X" -#: access/transam/xlogreader.c:1773 +#: access/transam/xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ მონაცემები მისამართზე %X/%X არ არსებობს" -#: access/transam/xlogreader.c:1780 +#: access/transam/xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ არსებობს მონაცემები სიგრძით %u მისამართზე %X/%X" -#: access/transam/xlogreader.c:1816 +#: access/transam/xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებულია, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u ბლოკის ასლის სიგრძე %u მისამართზე %X/%X" -#: access/transam/xlogreader.c:1832 +#: access/transam/xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებული არაა, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u მისანართზე %X/%X" -#: access/transam/xlogreader.c:1846 +#: access/transam/xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED დაყენებულია, მაგრამ ბლოკის ასლის სიგრძეა %u მისამართზე %X/%X" -#: access/transam/xlogreader.c:1861 +#: access/transam/xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "არც BKPIMAGE_HAS_HOLE და არც BKPIMAGE_COMPRESSED დაყენებული არაა, მაგრამ ბლოკის ასლის სიგრძე %u-ა, მისამართზე %X/%X" -#: access/transam/xlogreader.c:1877 +#: access/transam/xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL დაყენებულია, მაგრამ წინა მნიშვნელობა მითითებული არაა მისამართზე %X/%X" -#: access/transam/xlogreader.c:1889 +#: access/transam/xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "არასწორი block_id %u %X/%X" -#: access/transam/xlogreader.c:1956 +#: access/transam/xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "ჩანაწერი არასწორი სიგრძით მისამართზე %X/%X" -#: access/transam/xlogreader.c:1982 +#: access/transam/xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "შეცდომა WAL ჩანაწერში მარქაფი ბლოკის, ID-ით %d, მოძებნისას" -#: access/transam/xlogreader.c:2066 +#: access/transam/xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X, როცა მითითებულია არასწორი ბლოკი %d" -#: access/transam/xlogreader.c:2073 +#: access/transam/xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "არასწორად შეკუმშული ასლი მისამართზე %X/%X, ბლოკი %d" -#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 +#: access/transam/xlogreader.c:2110 access/transam/xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "%3$s მეთოდით შეკუმშული ასლი მისამართზე %1$X/%2$X, ბლოკი %4$d მხარდაუჭერელია ამ აგების მიერ" -#: access/transam/xlogreader.c:2126 +#: access/transam/xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "ასლის აღდგენის შეცდომა მისამართზე %X/%X შეკუმშული უცნობი მეთოდით, ბლოკი %d" -#: access/transam/xlogreader.c:2134 +#: access/transam/xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "არასწორად შეკუმშული ასლი მისამართზე %X/%X, ბლოკი %d" -#: access/transam/xlogrecovery.c:617 +#: access/transam/xlogrecovery.c:623 #, c-format msgid "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u" msgstr "იწყება მარქაფის აღდგენა გამეორების LSN-ით %X/%X საკონტროლო წერტილზე %X/%X დროის ხაზზე ID-ით %u" -#: access/transam/xlogrecovery.c:649 +#: access/transam/xlogrecovery.c:655 #, c-format msgid "could not find redo location %X/%X referenced by checkpoint record at %X/%X" msgstr "ვერ ვიპოვე გამეორების მდებარეობა %X/%X, რომელსაც მიმართავს საკონტროლო წერტილის ჩანაწერი მისამართზე %X/%X" -#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 +#: access/transam/xlogrecovery.c:657 access/transam/xlogrecovery.c:668 #, c-format msgid "" "If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" @@ -2960,463 +2934,464 @@ msgid "" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup." msgstr "" -#: access/transam/xlogrecovery.c:660 +#: access/transam/xlogrecovery.c:666 #, c-format msgid "could not locate required checkpoint record at %X/%X" msgstr "აუცილებელი საკონტროლო წერტილის მოძებნა შეუძლებელია მისამართზე %X/%X" -#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 +#: access/transam/xlogrecovery.c:696 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "სიმბმულის შექმნის შეცდომა %s: %m" -#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 +#: access/transam/xlogrecovery.c:729 access/transam/xlogrecovery.c:735 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "ფაილის (\"%s\") იგნორირება იმიტომ, რომ ფაილი \"%s\" არ არსებობს" -#: access/transam/xlogrecovery.c:725 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "სახელშეცვლილია '%s' -დან '%s'-ზე." -#: access/transam/xlogrecovery.c:731 +#: access/transam/xlogrecovery.c:737 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "გადარქმევის შეცდომა %s - %s: %m." -#: access/transam/xlogrecovery.c:770 +#: access/transam/xlogrecovery.c:776 #, c-format msgid "restarting backup recovery with redo LSN %X/%X" msgstr "მარქაფის აღდგენის თავიდან გაშვება გამეორების LSN-ით %X/%X" -#: access/transam/xlogrecovery.c:795 +#: access/transam/xlogrecovery.c:801 #, c-format msgid "could not locate a valid checkpoint record at %X/%X" msgstr "სწორი საკონტროლო წერტილის ჩანაწერის მოძებნა შეუძლებელია მისამართზე %X/%X" -#: access/transam/xlogrecovery.c:806 +#: access/transam/xlogrecovery.c:812 #, c-format msgid "entering standby mode" msgstr "უქმე რეჟიმზე გადართვა" -#: access/transam/xlogrecovery.c:809 +#: access/transam/xlogrecovery.c:815 #, c-format msgid "starting point-in-time recovery to XID %u" msgstr "დროში-მითითებული-წერტილით აღდგენის დასაწყისი XID-მდე %u" -#: access/transam/xlogrecovery.c:813 +#: access/transam/xlogrecovery.c:819 #, c-format msgid "starting point-in-time recovery to %s" msgstr "დროში-მითითებული-წერტილით აღდგენის დასაწყისი %s" -#: access/transam/xlogrecovery.c:817 +#: access/transam/xlogrecovery.c:823 #, c-format msgid "starting point-in-time recovery to \"%s\"" msgstr "დროში-მითითებული-წერტილით აღდგენის დასაწყისი \"%s\"" -#: access/transam/xlogrecovery.c:821 +#: access/transam/xlogrecovery.c:827 #, c-format msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" msgstr "" -#: access/transam/xlogrecovery.c:825 +#: access/transam/xlogrecovery.c:831 #, c-format msgid "starting point-in-time recovery to earliest consistent point" msgstr "უახლოეს თანმიმდევრულ წერტილამდე დროში-მითითებული-წერტილით აღდგენის დასაწყისი" -#: access/transam/xlogrecovery.c:828 +#: access/transam/xlogrecovery.c:834 #, c-format msgid "starting archive recovery" msgstr "არქივიდან აღდგენა დაიწყო" -#: access/transam/xlogrecovery.c:849 +#: access/transam/xlogrecovery.c:855 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "მოთხოვნილი დროის ხაზი %u სერვერის ისტორიის შვილი არაა" -#: access/transam/xlogrecovery.c:851 +#. translator: %s is a backup_label file or a pg_control file +#: access/transam/xlogrecovery.c:858 #, c-format -msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." +msgid "Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." msgstr "" -#: access/transam/xlogrecovery.c:865 +#: access/transam/xlogrecovery.c:873 #, c-format msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u" msgstr "" -#: access/transam/xlogrecovery.c:893 +#: access/transam/xlogrecovery.c:901 #, c-format msgid "invalid next transaction ID" msgstr "შემდეგი ტრანზაქციის არასწორი ID" -#: access/transam/xlogrecovery.c:898 +#: access/transam/xlogrecovery.c:906 #, c-format msgid "invalid redo in checkpoint record" msgstr "არასწორი გამეორება საკონტროლო წერტილის ჩანაწერში" -#: access/transam/xlogrecovery.c:909 +#: access/transam/xlogrecovery.c:917 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "გამეორების არასწორი ჩანაწერი გამორთვის საკონტროლო წერტილში" -#: access/transam/xlogrecovery.c:938 +#: access/transam/xlogrecovery.c:946 #, c-format msgid "database system was not properly shut down; automatic recovery in progress" msgstr "მონაცემთა ბაზა არასწორად გამოირთო; მიმდინარეობს ავტომატური აღდეგენა" -#: access/transam/xlogrecovery.c:942 +#: access/transam/xlogrecovery.c:950 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "ავარიიდან აღდგენა იწყება დროის ხაზზე %u და სამიზნედ დროის ხაზი %u აქვს" -#: access/transam/xlogrecovery.c:985 +#: access/transam/xlogrecovery.c:993 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label შეიცავს მონაცემებს, რომელიც კონტროლის ფაილს არ შეესაბამება" -#: access/transam/xlogrecovery.c:986 +#: access/transam/xlogrecovery.c:994 #, c-format msgid "This means that the backup is corrupted and you will have to use another backup for recovery." msgstr "ეს ნიშნავს, რომ მარქაფი დაზიანებულია და აღდგენისთვის სხვა მარქაფის გამოყენება მოგიწევთ." -#: access/transam/xlogrecovery.c:1040 +#: access/transam/xlogrecovery.c:1048 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "აღდგენის ბრძანების ფაილი \"%s\" მხარდაუჭერელია" -#: access/transam/xlogrecovery.c:1105 +#: access/transam/xlogrecovery.c:1113 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "ერთმომხმარებლიან სერვერებს უქმე რეჟიმი არ გააჩნიათ" -#: access/transam/xlogrecovery.c:1122 +#: access/transam/xlogrecovery.c:1130 #, c-format msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" msgstr "მითითებულია არც\" primary_conninfo\" და არც \"restore_command\"" -#: access/transam/xlogrecovery.c:1123 +#: access/transam/xlogrecovery.c:1131 #, c-format msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there." msgstr "" -#: access/transam/xlogrecovery.c:1131 +#: access/transam/xlogrecovery.c:1139 #, c-format msgid "must specify \"restore_command\" when standby mode is not enabled" msgstr "როცა უქმე რეჟიმი ჩართული არაა, \"restore_command\" პარამეტრის მითითება აუცილებელია" -#: access/transam/xlogrecovery.c:1169 +#: access/transam/xlogrecovery.c:1177 #, c-format msgid "recovery target timeline %u does not exist" msgstr "აღდგენის სამიზნე დროის ხაზი არ არსებობს: %u" -#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 +#: access/transam/xlogrecovery.c:1260 access/transam/xlogrecovery.c:1267 access/transam/xlogrecovery.c:1326 access/transam/xlogrecovery.c:1414 access/transam/xlogrecovery.c:1423 access/transam/xlogrecovery.c:1443 #, c-format msgid "invalid data in file \"%s\"" msgstr "არასწორი მონაცემები ფაილში \"%s\"" -#: access/transam/xlogrecovery.c:1319 +#: access/transam/xlogrecovery.c:1327 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "დროის დამუშავებული ID %u-ა. მოველოდი მნშვნელობას %u." -#: access/transam/xlogrecovery.c:1330 +#: access/transam/xlogrecovery.c:1338 #, c-format msgid "this is an incremental backup, not a data directory" msgstr "ეს ინკრემენტული მარქაფია და არა მონაცემების საქაღალდე" -#: access/transam/xlogrecovery.c:1331 +#: access/transam/xlogrecovery.c:1339 #, c-format msgid "Use pg_combinebackup to reconstruct a valid data directory." msgstr "სწორი მონაცემების საქაღალდის თავიდან ასაგებად გამოიყენეთ ბრძანება pg_combinebackup." -#: access/transam/xlogrecovery.c:1717 +#: access/transam/xlogrecovery.c:1725 #, c-format msgid "unexpected record type found at redo point %X/%X" msgstr "აღმოჩენილია მოულოდნელი ჩანაწერის ტიპი გამეორების წერტილზე %X/%X" -#: access/transam/xlogrecovery.c:1740 +#: access/transam/xlogrecovery.c:1748 #, c-format msgid "redo starts at %X/%X" msgstr "გამეორება დაიწყება მისამართიდან %X/%X" -#: access/transam/xlogrecovery.c:1753 +#: access/transam/xlogrecovery.c:1761 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "მიმდინარეობს გამეორება. გასული დრო: %ld.%02d მიმდინარე LSN: %X/%X" -#: access/transam/xlogrecovery.c:1843 +#: access/transam/xlogrecovery.c:1851 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "მოთხოვნილი აღდგენის წერტილი მუდმივი აღდგენის წერტილამდეა" -#: access/transam/xlogrecovery.c:1875 +#: access/transam/xlogrecovery.c:1883 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "გამეორება დასრულდა %X/%X -სთან. სისტემის დატვირთვა: %s" -#: access/transam/xlogrecovery.c:1881 +#: access/transam/xlogrecovery.c:1889 #, c-format msgid "last completed transaction was at log time %s" msgstr "უკანასკნელად დასრულებული ტრანზაქცია მოხდა ჟურნალის დროით %s" -#: access/transam/xlogrecovery.c:1890 +#: access/transam/xlogrecovery.c:1898 #, c-format msgid "redo is not required" msgstr "გამეორება საჭირო არაა" -#: access/transam/xlogrecovery.c:1901 +#: access/transam/xlogrecovery.c:1910 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "აღდგენა მითითებული აღდგენის სამიზნის მიღწევამდე დასრულდა" -#: access/transam/xlogrecovery.c:2095 +#: access/transam/xlogrecovery.c:2104 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "" -#: access/transam/xlogrecovery.c:2162 +#: access/transam/xlogrecovery.c:2171 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "%2$s-ში ნაპოვნია მოულოდნელი საქაღალდის ჩანაწერი \"%1$s\"" -#: access/transam/xlogrecovery.c:2164 +#: access/transam/xlogrecovery.c:2173 #, c-format -msgid "All directory entries in pg_tblspc/ should be symbolic links." -msgstr "ყველა საქაღალდის ტიპის ელემენტი ph_tblspc/-ში სიმბმულს უნდა წარმოადგენდეს." +msgid "All directory entries in %s/ should be symbolic links." +msgstr "ყველა საქაღალდის ტიპის ელემენტი \"%s/-ში სიმბმულს უნდა წარმოადგენდეს." -#: access/transam/xlogrecovery.c:2165 +#: access/transam/xlogrecovery.c:2175 #, c-format msgid "Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete." msgstr "" -#: access/transam/xlogrecovery.c:2217 +#: access/transam/xlogrecovery.c:2227 #, c-format msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" msgstr "" -#: access/transam/xlogrecovery.c:2247 +#: access/transam/xlogrecovery.c:2258 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "თანმიმდევრული აღდგენის მდგომარეობა მიღწეულია მისამართზე %X/%X" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2285 +#: access/transam/xlogrecovery.c:2296 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "WAL გამეორება %X/%X %s-სთვის" -#: access/transam/xlogrecovery.c:2383 +#: access/transam/xlogrecovery.c:2394 #, c-format msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record" msgstr "მოულოდნელი წინა დროის ხაზის ID %u (მიმდინარე დროის ხაზის ID %u) საკონტროლო წერტილის ჩანაწერში" -#: access/transam/xlogrecovery.c:2392 +#: access/transam/xlogrecovery.c:2403 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "მოულოდნელი დროის ხაზის ID %u (%u-ის შემდეგ) საკონტროლო წერტილის ჩანაწერში" -#: access/transam/xlogrecovery.c:2408 +#: access/transam/xlogrecovery.c:2419 #, c-format msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u" msgstr "" -#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 +#: access/transam/xlogrecovery.c:2603 access/transam/xlogrecovery.c:2879 #, c-format msgid "recovery stopping after reaching consistency" msgstr "აღდგენა შეთანხმებული მდგომარეობის მიღწევისას დასრულდება" -#: access/transam/xlogrecovery.c:2613 +#: access/transam/xlogrecovery.c:2624 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "აღდგენა შეწყდა WAL-ის მდებარეობამდე (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2703 +#: access/transam/xlogrecovery.c:2714 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "აღდგენა შეწყდა ტრანზაქციის (%u) გადაცემამდე. დრო %s" -#: access/transam/xlogrecovery.c:2710 +#: access/transam/xlogrecovery.c:2721 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "აღდგენა შეწყდა ტრანზაქციის (%u) გაუქმებამდე. დრო %s" -#: access/transam/xlogrecovery.c:2763 +#: access/transam/xlogrecovery.c:2774 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "აღდგენა შეწყდა აღდგენის წერტილთან \"%s\". დრო %s" -#: access/transam/xlogrecovery.c:2781 +#: access/transam/xlogrecovery.c:2792 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "აღდგენა შეწყდა WAL-ის მდებარეობამდე (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2848 +#: access/transam/xlogrecovery.c:2859 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "აღდგენა შეწყდა ტრანზაქციის (%u) გადაცემამდე. დრო %s" -#: access/transam/xlogrecovery.c:2856 +#: access/transam/xlogrecovery.c:2867 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "აღდგენა ტრანზაქციის (%u) გაუქმების შემდეგ შეწყდა. დრო %s" -#: access/transam/xlogrecovery.c:2937 +#: access/transam/xlogrecovery.c:2948 #, c-format msgid "pausing at the end of recovery" msgstr "შეჩერება აღდგენის ბოლოს" -#: access/transam/xlogrecovery.c:2938 +#: access/transam/xlogrecovery.c:2949 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "წასახალისებლად გაუშვით pg_wal_replay_resume()." -#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4678 +#: access/transam/xlogrecovery.c:2952 access/transam/xlogrecovery.c:4698 #, c-format msgid "recovery has paused" msgstr "აღდგენა შეჩერდა" -#: access/transam/xlogrecovery.c:2942 +#: access/transam/xlogrecovery.c:2953 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "გასაგრძელებლად გაუშვით pg_wal_replay_resume()." -#: access/transam/xlogrecovery.c:3205 +#: access/transam/xlogrecovery.c:3216 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "მოულოდნელი დროის ხაზის ID %u WAL სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: access/transam/xlogrecovery.c:3413 +#: access/transam/xlogrecovery.c:3432 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "ჟურნალის სეგმენტიდან (%s, LSN %X/%X, წანაცვლება %u) წაკითხვის შეცდომა: %m" -#: access/transam/xlogrecovery.c:3420 +#: access/transam/xlogrecovery.c:3439 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" msgstr "ჟურნალის სეგმენტიდან (%s, LSN %X/%X, წანაცვლება %u) წაკითხვის შეცდომა: წავიკითხე %d %zu-დან" -#: access/transam/xlogrecovery.c:4060 +#: access/transam/xlogrecovery.c:4082 #, c-format msgid "invalid checkpoint location" msgstr "საკონტროლო წერტილის არასწორი მდებარეობა" -#: access/transam/xlogrecovery.c:4070 +#: access/transam/xlogrecovery.c:4092 #, c-format msgid "invalid checkpoint record" msgstr "საკონტროლო წერტილის არასწორი ჩანაწერი" -#: access/transam/xlogrecovery.c:4076 +#: access/transam/xlogrecovery.c:4098 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "რესურსის მმართველის არასწორი ID საკონტროლო წერტილის ჩანაწერში" -#: access/transam/xlogrecovery.c:4084 +#: access/transam/xlogrecovery.c:4106 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "საკონტროლო წერტილის არასწორი xl_info" -#: access/transam/xlogrecovery.c:4090 +#: access/transam/xlogrecovery.c:4112 #, c-format msgid "invalid length of checkpoint record" msgstr "საკონტროლო წერტილის ჩანაწერის არასწორი სიგრძე" -#: access/transam/xlogrecovery.c:4144 +#: access/transam/xlogrecovery.c:4166 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "ახალი დროის ხაზი %u ბაზის სისტემის დროის ხაზის %u შვილი არაა" -#: access/transam/xlogrecovery.c:4158 +#: access/transam/xlogrecovery.c:4180 #, c-format msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X" msgstr "" -#: access/transam/xlogrecovery.c:4177 +#: access/transam/xlogrecovery.c:4199 #, c-format msgid "new target timeline is %u" msgstr "ახალი სამიზნის დროის ხაზია %u" -#: access/transam/xlogrecovery.c:4380 +#: access/transam/xlogrecovery.c:4400 #, c-format msgid "WAL receiver process shutdown requested" msgstr "მოთხოვნილია WAL-ის მიმღები პროცესის გამორთვა" -#: access/transam/xlogrecovery.c:4440 +#: access/transam/xlogrecovery.c:4460 #, c-format msgid "received promote request" msgstr "მიღებულა დაწინაურების მოთხოვნა" -#: access/transam/xlogrecovery.c:4669 +#: access/transam/xlogrecovery.c:4689 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "ცხელი მომლოდინე სერვერის არსებობა შეუძლებელია არასაკმარისი პარამეტრის მნიშვნელობების გამო" -#: access/transam/xlogrecovery.c:4670 access/transam/xlogrecovery.c:4697 access/transam/xlogrecovery.c:4727 +#: access/transam/xlogrecovery.c:4690 access/transam/xlogrecovery.c:4717 access/transam/xlogrecovery.c:4747 #, c-format msgid "%s = %d is a lower setting than on the primary server, where its value was %d." msgstr "%s = %d ნაკლებია, ვიდრე ძირითად სერვერზე, სადაც მისი მნიშვნელობაა %d." -#: access/transam/xlogrecovery.c:4679 +#: access/transam/xlogrecovery.c:4699 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "თუ აღდგენა გაგრძელდება, სერვერი გამოირთვება." -#: access/transam/xlogrecovery.c:4680 +#: access/transam/xlogrecovery.c:4700 #, c-format msgid "You can then restart the server after making the necessary configuration changes." msgstr "კონფიგურაციაში საჭირო ცვლილებების შეტანის შემდეგ შეგიძლიათ სერვერი დაარესტარტოთ." -#: access/transam/xlogrecovery.c:4691 +#: access/transam/xlogrecovery.c:4711 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "დაწინაურება შეუძლებელია არასაკმარისი პარამეტრების მნიშვნელობების გამო" -#: access/transam/xlogrecovery.c:4701 +#: access/transam/xlogrecovery.c:4721 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "კონფიგურაციაში საჭირო ცვლილებების შეტანის შემდეგ გადატვირთეთ სერვერი." -#: access/transam/xlogrecovery.c:4725 +#: access/transam/xlogrecovery.c:4745 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "აღდგენა შეწყვეტილია არასაკმარისი პარამეტრების მნიშვნელობების გამო" -#: access/transam/xlogrecovery.c:4731 +#: access/transam/xlogrecovery.c:4751 #, c-format msgid "You can restart the server after making the necessary configuration changes." msgstr "კონფიგურაციაში საჭირო ცვლილებების შეტანის შემდეგ შეგიძლიათ სერვერი დაარესტარტოთ." -#: access/transam/xlogrecovery.c:4773 +#: access/transam/xlogrecovery.c:4792 #, c-format msgid "multiple recovery targets specified" msgstr "მითითებულია აღდგენის მრავალი სამიზნე" -#: access/transam/xlogrecovery.c:4774 +#: access/transam/xlogrecovery.c:4793 #, c-format msgid "At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set." msgstr "პარამეტრებიდან \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\" და \"recovery_target_xid\" მხოლოდ ერთის დაყენება შეგიძლიათ." -#: access/transam/xlogrecovery.c:4785 +#: access/transam/xlogrecovery.c:4804 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "დაშვებულია მხოლოდ ერთი მნიშვნელობა: \"immediate\"." -#: access/transam/xlogrecovery.c:4937 utils/adt/timestamp.c:202 utils/adt/timestamp.c:455 +#: access/transam/xlogrecovery.c:4958 #, c-format -msgid "timestamp out of range: \"%s\"" -msgstr "დროის შტამპი დიაპაზონს გარეთაა: \"%s\"" +msgid "Timestamp out of range: \"%s\"." +msgstr "დროის შტამპი დიაპაზონს გარეთაა: \"%s\"." -#: access/transam/xlogrecovery.c:4982 +#: access/transam/xlogrecovery.c:5003 #, c-format msgid "\"recovery_target_timeline\" is not a valid number." msgstr "\"recovery_target_timeline\" სწორი რიცხვი არაა." -#: access/transam/xlogutils.c:1032 +#: access/transam/xlogutils.c:1023 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "'WAL'-ის სეგმენტიდან წაკითხვის შეცდომა %s, წანაცვლება %d: %m" -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1030 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "'WAL'-ის სეგმენტიდან წაკითხვის შეცდომა %s, წანაცვლება %d: წაკითხულია %d %d-დან" @@ -3436,7 +3411,7 @@ msgstr "არქივირების წარუმატებლად msgid "archive command was terminated by exception 0x%X" msgstr "არქივაციის ბრძანება დასრულდა გამონაკლისით 0x%X" -#: archive/shell_archive.c:109 postmaster/postmaster.c:3094 +#: archive/shell_archive.c:109 postmaster/postmaster.c:2843 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "თექვსმეტობითი მნიშვნელობის აღწერისთვის იხილეთ C-ის ჩასასმელი ფაილი \"ntstatus.h\"." @@ -3451,161 +3426,161 @@ msgstr "არქივაციის ბრძანება დასრუ msgid "archive command exited with unrecognized status %d" msgstr "არქივის ბრძანება უცნობი სტატუსით დასრულდა: %d" -#: backup/backup_manifest.c:254 +#: backup/backup_manifest.c:255 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "მოველოდი დროის ხაზის (%u) ბოლოს, მაგრამ ნაპოვნია დროის ხაზი %u" -#: backup/backup_manifest.c:278 +#: backup/backup_manifest.c:279 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "მოველოდი დროის ხაზის (%u) დასაწყისს, მაგრამ ნაპოვნია დროის ხაზი %u" -#: backup/backup_manifest.c:305 +#: backup/backup_manifest.c:306 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "დროის ხაზის %u დასაწყისი დროის ხაზის %u ისტორიაში აღმოჩენილი არაა" -#: backup/backup_manifest.c:356 +#: backup/backup_manifest.c:357 #, c-format msgid "could not rewind temporary file" msgstr "დროებითი ფაილის გადახვევის შეცდომა" -#: backup/basebackup.c:479 +#: backup/basebackup.c:481 #, c-format msgid "could not find any WAL files" msgstr "ვერცერთი WAL ფაილი ვერ ვიპოვე" -#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 +#: backup/basebackup.c:496 backup/basebackup.c:511 backup/basebackup.c:520 #, c-format msgid "could not find WAL file \"%s\"" msgstr "\"WAL\" ფაილის (\"%s\") მოძებნა შეუძლებელია" -#: backup/basebackup.c:560 backup/basebackup.c:585 +#: backup/basebackup.c:562 backup/basebackup.c:587 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "მოულოდნელი WAL ფაილის ზომა \"%s\"" -#: backup/basebackup.c:656 +#: backup/basebackup.c:658 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" msgstr[0] "ჯამში %lld საკონტროლო ჯამის გადამოწმების შეცდომა" msgstr[1] "ჯამში %lld საკონტროლო ჯამის გადამოწმების შეცდომა" -#: backup/basebackup.c:663 +#: backup/basebackup.c:665 #, c-format msgid "checksum verification failure during base backup" msgstr "ბაზის მარქაფისას საკონტროლო ჯამის შემოწმების შეცდომა" -#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 +#: backup/basebackup.c:735 backup/basebackup.c:744 backup/basebackup.c:755 backup/basebackup.c:772 backup/basebackup.c:781 backup/basebackup.c:790 backup/basebackup.c:805 backup/basebackup.c:822 backup/basebackup.c:831 backup/basebackup.c:843 backup/basebackup.c:867 backup/basebackup.c:881 backup/basebackup.c:892 backup/basebackup.c:903 backup/basebackup.c:916 #, c-format msgid "duplicate option \"%s\"" msgstr "დუბლიკატი პარამეტრი \"%s\"" -#: backup/basebackup.c:761 +#: backup/basebackup.c:763 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "საკონტროლო წერტილის უცნობი ტიპი: \"%s\"" -#: backup/basebackup.c:793 +#: backup/basebackup.c:795 #, c-format msgid "incremental backups cannot be taken unless WAL summarization is enabled" msgstr "ინკრემენტული მარქაფების აღება შეუძლებელია, სანამ WAL შეჯამებას არ ჩართავთ" -#: backup/basebackup.c:809 +#: backup/basebackup.c:811 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%d პარამეტრისთვის \"%s\" დასაშვებ დიაპაზონს (%d .. %d) გარეთაა" -#: backup/basebackup.c:854 +#: backup/basebackup.c:856 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "მანიფესტის უცნობი პარამეტრი: \"%s\"" -#: backup/basebackup.c:905 +#: backup/basebackup.c:907 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "შეკუმშვის უცხო ალგორითმი: \"%s\"" -#: backup/basebackup.c:921 +#: backup/basebackup.c:923 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "ბაზის მარქაფის უცნობი პარამეტრი: \"%s\"" -#: backup/basebackup.c:932 +#: backup/basebackup.c:934 #, c-format msgid "manifest checksums require a backup manifest" msgstr "მანიფესტის საკონტროლო ჯამებს მარქაფი მანიფესტი ესაჭიროება" -#: backup/basebackup.c:941 +#: backup/basebackup.c:943 #, c-format msgid "target detail cannot be used without target" msgstr "სამიზნის დეტალს სამიზნის გარეშე ვერ გამოიყენებთ" -#: backup/basebackup.c:950 backup/basebackup_target.c:218 +#: backup/basebackup.c:952 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "სამიზნეს \"%s\" სამიზნის დეტალების მხარდაჭერა არ გააჩნია" -#: backup/basebackup.c:961 +#: backup/basebackup.c:963 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "შეკუმშვის დეტალებს ვერ დააყენებთ, სანამ შეკუმშვა ჩართული არაა" -#: backup/basebackup.c:974 +#: backup/basebackup.c:976 #, c-format msgid "invalid compression specification: %s" msgstr "შეკუმშვის არასწორი სპეციფიკაცია: %s" -#: backup/basebackup.c:1024 +#: backup/basebackup.c:1026 #, c-format msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" msgstr "ინკრემენტული BASE_BACKUP-ის შესრულებამდე აუცილებელია UPLOAD_MANIFEST" -#: backup/basebackup.c:1157 backup/basebackup.c:1358 +#: backup/basebackup.c:1159 backup/basebackup.c:1360 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "ფაილის ან საქაღალდის \"%s\" პოვნა შეუძლებელია: %m" -#: backup/basebackup.c:1544 +#: backup/basebackup.c:1546 #, c-format msgid "skipping special file \"%s\"" msgstr "სპეციალური ფაილის გამოტოვება \"%s\"" -#: backup/basebackup.c:1751 +#: backup/basebackup.c:1753 #, c-format msgid "could not verify checksum in file \"%s\", block %u: read buffer size %d and page size %d differ" msgstr "საკონტროლო ჯამის გადამოწმება შეუძლებელია ფაილში \"%s\", ბლოკი %u: წაკითხვის ბუფერის ზომა %d და გვერდის ზომა %d განსხვავდება" -#: backup/basebackup.c:1813 +#: backup/basebackup.c:1815 #, c-format msgid "file \"%s\" has a total of %d checksum verification failure" msgid_plural "file \"%s\" has a total of %d checksum verification failures" msgstr[0] "ფაილს \"%s\" სულ %d საკონტროლო ჯამის გადამოწმების ჩავარდნა აღმოაჩნდა" msgstr[1] "ფაილს \"%s\" სულ %d საკონტროლო ჯამის გადამოწმების ჩავარდნა აღმოაჩნდა" -#: backup/basebackup.c:1917 +#: backup/basebackup.c:1920 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" msgstr "საკონტროლო ჯამის გამოთვლის შეცდომა ფაილში \"%s\", ბლოკი \"%u\": გამოთვლილი საკონტროლო ჯამია %X, მაგრამ მოველოდი: %X" -#: backup/basebackup.c:1924 +#: backup/basebackup.c:1927 #, c-format msgid "further checksum verification failures in file \"%s\" will not be reported" msgstr "ამის შემდეგ ფაილში \"%s\" შეხვედრილი საკონტროლო ჯამის გადამოწმების ჩავარდნები ანგარიშში აღარ გამოჩნდება" -#: backup/basebackup.c:2048 +#: backup/basebackup.c:2052 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "ფაილის სახელი ძალიან გრძელია tar ფორმატისთვის: \"%s\"" -#: backup/basebackup.c:2053 +#: backup/basebackup.c:2058 #, c-format msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "სიმბოლური ბმულის სამიზნე ძალიან გრძელია tar ფორმატისთვის: ფაილის სახელი '%s', სამიზნე '%s'" -#: backup/basebackup.c:2127 +#: backup/basebackup.c:2132 #, c-format msgid "could not read file \"%s\": read %zd of %zu" msgstr "ფაილი \"%s\" ვერ წავიკითხე: წაკითხულია %zd %zu-დან" @@ -3620,80 +3595,65 @@ msgstr "ამ აგებაში gzip შეკუმშვის მხა msgid "could not initialize compression library" msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზაციის შეცდომა" -#: backup/basebackup_incremental.c:300 +#: backup/basebackup_incremental.c:292 #, c-format msgid "manifest contains no required WAL ranges" msgstr "მანიფესტი აუცილებელ WAL შუალედებს არ შეიცავს" -#: backup/basebackup_incremental.c:355 +#: backup/basebackup_incremental.c:347 #, c-format msgid "timeline %u found in manifest, but not in this server's history" msgstr "დროის ხაზი %u ვიპოვე მანიფესტში, სერვერის ისტორიაში კი - ვერა" -#: backup/basebackup_incremental.c:420 +#: backup/basebackup_incremental.c:412 #, c-format msgid "manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X" msgstr "მანიფესტი მოითხოვს WAL-ს საწყისი დროის ხაზიდან %u საწყისი წერტილით %X/%X, მაგრამ დროის ხაზი იწყება მნიშვნელობაზე %X/%X" -#: backup/basebackup_incremental.c:430 +#: backup/basebackup_incremental.c:422 #, c-format msgid "manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X" msgstr "მანიფესტი მოითხოვს WAL-ს გაგრძელების დროის ხაზიდან %u საწყისი წერტილით %X/%X, მაგრამ დროის ხაზი იწყება მნიშვნელობაზე %X/%X" -#: backup/basebackup_incremental.c:441 +#: backup/basebackup_incremental.c:433 #, c-format msgid "manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X" msgstr "მანიფესტი მოითხოვს WAL-ს ფინალური დროის ხაზიდან %u საბოლოო წერტილით %X/%X, მაგრამ ეს მარქაფი იწყება მისამართზე %X/%X" -#: backup/basebackup_incremental.c:451 -#, c-format -msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" -msgstr "მანიფესტი მოითხოვს WAL-ს არაფინალური დროის ხაზიდან %u საბოლოო წერტილით %X/%X, მაგრამ ამ სერვერმა გადართო დროის ხაზები მისამართზე %X/%X" - -#: backup/basebackup_incremental.c:518 -#, c-format -msgid "WAL summarization is not progressing" -msgstr "" - -#: backup/basebackup_incremental.c:519 -#, c-format -msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." -msgstr "" - -#: backup/basebackup_incremental.c:532 +#: backup/basebackup_incremental.c:437 #, c-format -msgid "still waiting for WAL summarization through %X/%X after %ld seconds" +msgid "This can happen for incremental backups on a standby if there was little activity since the previous backup." msgstr "" -#: backup/basebackup_incremental.c:535 +#: backup/basebackup_incremental.c:444 #, c-format -msgid "Summarization has reached %X/%X on disk and %X/%X in memory." -msgstr "" +msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" +msgstr "მანიფესტი მოითხოვს WAL-ს არაფინალური დროის ხაზიდან %u საბოლოო წერტილით %X/%X, მაგრამ ამ სერვერმა გადართო დროის ხაზები მისამართზე %X/%X" -#: backup/basebackup_incremental.c:604 +#: backup/basebackup_incremental.c:525 #, c-format msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist" msgstr "" -#: backup/basebackup_incremental.c:611 +#: backup/basebackup_incremental.c:532 #, c-format msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete" msgstr "" -#: backup/basebackup_incremental.c:615 +#: backup/basebackup_incremental.c:536 #, c-format msgid "The first unsummarized LSN in this range is %X/%X." msgstr "" -#: backup/basebackup_incremental.c:1015 +#: backup/basebackup_incremental.c:934 #, c-format msgid "backup manifest version 1 does not support incremental backup" msgstr "მარქაფის მანიფესტის ვერსიას 1 ინკრემენტული მარქაფების მხარდაჭერა არ გააჩნია" -#: backup/basebackup_incremental.c:1033 +#: backup/basebackup_incremental.c:952 #, c-format -msgid "manifest system identifier is %llu, but database system identifier is %llu" -msgstr "მანიფესტის სისტემის იდენტიფიკატორია %llu, მაგრამ კონტროლის ფაილიs მნიშვნელობაა %llu" +msgid "system identifier in backup manifest is %, but database system identifier is %" +msgstr "სისტემის იდენტიფიკატორი სარეზერვო მანიფესტში არის %, მაგრამ მონაცემთა ბაზის სისტემის იდენტიფიკატორია %" #: backup/basebackup_lz4.c:67 #, c-format @@ -3715,7 +3675,7 @@ msgstr "სერვერზე შენახული მარქაფი msgid "relative path not allowed for backup stored on server" msgstr "სერვერზე დამახსოვრებული მარქაფისთვის ფარდობითი ბილიკი დაშვებული არაა" -#: backup/basebackup_server.c:102 commands/dbcommands.c:477 commands/tablespace.c:157 commands/tablespace.c:173 commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 storage/file/copydir.c:47 +#: backup/basebackup_server.c:102 commands/dbcommands.c:478 commands/tablespace.c:157 commands/tablespace.c:173 commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:2179 storage/file/copydir.c:58 #, c-format msgid "could not create directory \"%s\": %m" msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" @@ -3725,12 +3685,12 @@ msgstr "საქაღალდის (%s) შექმნის შეცდ msgid "directory \"%s\" exists but is not empty" msgstr "საქაღალდე \"%s\" არსებობს, მაგრამ ცარიელი არაა" -#: backup/basebackup_server.c:123 utils/init/postinit.c:1177 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1171 #, c-format msgid "could not access directory \"%s\": %m" msgstr "საქაღალდის (%s) წვდომის შეცდომა: %m" -#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 backup/basebackup_server.c:268 backup/basebackup_server.c:275 backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 backup/basebackup_server.c:268 backup/basebackup_server.c:275 backup/walsummary.c:312 storage/smgr/md.c:519 storage/smgr/md.c:526 storage/smgr/md.c:608 storage/smgr/md.c:630 storage/smgr/md.c:1123 #, c-format msgid "Check free disk space." msgstr "შეამოწმეთ, დისკზე ადგილი დარჩა, თუ არა." @@ -3767,671 +3727,671 @@ msgstr "long-distance რეჟიმი ვერ ჩავრთე: %s" #: backup/walsummaryfuncs.c:95 #, c-format -msgid "invalid timeline %lld" -msgstr "არასწორი დროის ხაზი %lld" +msgid "invalid timeline %" +msgstr "არასწორი დროის ხაზი %" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:626 tcop/postgres.c:3863 +#, c-format +msgid "--%s must be first argument" +msgstr "--%s პირველი არგუმენტი უნდა იყოს" -#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3859 +#: bootstrap/bootstrap.c:253 postmaster/postmaster.c:640 tcop/postgres.c:3877 #, c-format msgid "--%s requires a value" msgstr "--%s მნიშვნელობა სჭირდება" -#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3864 +#: bootstrap/bootstrap.c:258 postmaster/postmaster.c:645 tcop/postgres.c:3882 #, c-format msgid "-c %s requires a value" msgstr "-c %s მნიშვნელობა სჭირდება" -#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 postmaster/postmaster.c:759 +#: bootstrap/bootstrap.c:296 postmaster/postmaster.c:763 postmaster/postmaster.c:776 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'.\n" -#: bootstrap/bootstrap.c:291 +#: bootstrap/bootstrap.c:305 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: არასწორი ბრძანების სტრიქონის არგუმენტები\n" -#: catalog/aclchk.c:210 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "უფლებების უფლების მიცემა მხოლოდ როლებზეა შესაძლებელი" -#: catalog/aclchk.c:332 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "ურთიერთობის %2$s სვეტის %1$s პრივილეგიები მინიჭებული არაა" -#: catalog/aclchk.c:337 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "ობიექტს \"%s\" პრივილეგიები მინიჭებული არ აქვს" -#: catalog/aclchk.c:345 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "ურთიერთობის %2$s სვეტის %1$s ყველა პრივილეგია მინიჭებული არაა" -#: catalog/aclchk.c:350 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "\"%s\"-სთვის საჭირო ყველა უფლება მინიჭებული არ ყოფილა" -#: catalog/aclchk.c:361 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "ურთიერთობის %2$s სვეტის %1$s მოსახსნელი პრივილეგიები არ არსებობს" -#: catalog/aclchk.c:366 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "%s-სთვის უფლებები არ გაუქმდება" -#: catalog/aclchk.c:374 +#: catalog/aclchk.c:375 #, c-format msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "ურთიერთობის %2$s სვეტს %1$s ყველა პრივილეგიას ვერ მოხსნით" -#: catalog/aclchk.c:379 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "\"%s\"-ზე ყველა პრივილეგიის გაუქმება შეუძლებელია" -#: catalog/aclchk.c:411 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "მიმნიჭებელი მიმდინარე მომხმარებელი უნდა იყოს" -#: catalog/aclchk.c:479 catalog/aclchk.c:1054 +#: catalog/aclchk.c:480 catalog/aclchk.c:982 #, c-format msgid "invalid privilege type %s for relation" msgstr "ურთიერთობის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:483 catalog/aclchk.c:1058 +#: catalog/aclchk.c:484 catalog/aclchk.c:986 #, c-format msgid "invalid privilege type %s for sequence" msgstr "მიმდევრობის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:487 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "ბაზის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:491 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "დომენის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:495 catalog/aclchk.c:1062 +#: catalog/aclchk.c:496 catalog/aclchk.c:990 #, c-format msgid "invalid privilege type %s for function" msgstr "ფუნქციის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:499 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "ენის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:503 +#: catalog/aclchk.c:504 catalog/aclchk.c:1010 #, c-format msgid "invalid privilege type %s for large object" msgstr "დიდი ობიექტის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:507 catalog/aclchk.c:1078 +#: catalog/aclchk.c:508 catalog/aclchk.c:1006 #, c-format msgid "invalid privilege type %s for schema" msgstr "სქემის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:511 catalog/aclchk.c:1066 +#: catalog/aclchk.c:512 catalog/aclchk.c:994 #, c-format msgid "invalid privilege type %s for procedure" msgstr "პროცედურის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:515 catalog/aclchk.c:1070 +#: catalog/aclchk.c:516 catalog/aclchk.c:998 #, c-format msgid "invalid privilege type %s for routine" msgstr "ქვეპროგრამის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:519 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "ცხრილის სივრცის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:523 catalog/aclchk.c:1074 +#: catalog/aclchk.c:524 catalog/aclchk.c:1002 #, c-format msgid "invalid privilege type %s for type" msgstr "ტიპის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:527 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "გარე მონაცემების გადამტანის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:531 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "გარე სერვერის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:535 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "პარამეტრის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:574 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "სვეტის პრივილეგიები მხოლოდ ურთიერთობებისთვის მოქმედებს" -#: catalog/aclchk.c:737 catalog/aclchk.c:3626 catalog/objectaddress.c:1054 catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 -#, c-format -msgid "large object %u does not exist" -msgstr "დიდი ობიექტი %u არ არსებობს" - -#: catalog/aclchk.c:1111 +#: catalog/aclchk.c:1043 #, c-format msgid "default privileges cannot be set for columns" msgstr "სვეტებისთვის ნაგულისხმევი პრივილეგიების დაყენება შეუძლებელია" -#: catalog/aclchk.c:1147 +#: catalog/aclchk.c:1079 #, c-format msgid "permission denied to change default privileges" msgstr "ნაგულისხმევი პრივილეგიების შეცვლის წვდომა აკრძალულია" -#: catalog/aclchk.c:1265 +#: catalog/aclchk.c:1197 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "'IN SCHEMA' პირობის გამოყენება GRANT/REVOKE ON SCHEMAS-ის გამოყენებისას შეუძლებელია" -#: catalog/aclchk.c:1616 catalog/catalog.c:629 catalog/objectaddress.c:1523 catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:913 commands/sequence.c:1645 commands/tablecmds.c:7549 commands/tablecmds.c:7703 commands/tablecmds.c:7753 commands/tablecmds.c:7827 commands/tablecmds.c:7897 commands/tablecmds.c:8027 commands/tablecmds.c:8156 commands/tablecmds.c:8250 commands/tablecmds.c:8351 commands/tablecmds.c:8478 commands/tablecmds.c:8508 -#: commands/tablecmds.c:8650 commands/tablecmds.c:8743 commands/tablecmds.c:8877 commands/tablecmds.c:8989 commands/tablecmds.c:12709 commands/tablecmds.c:12890 commands/tablecmds.c:13051 commands/tablecmds.c:14240 commands/tablecmds.c:16866 commands/trigger.c:942 parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 parser/parse_type.c:144 parser/parse_utilcmd.c:3538 parser/parse_utilcmd.c:3578 parser/parse_utilcmd.c:3620 utils/adt/acl.c:2917 -#: utils/adt/ruleutils.c:2811 +#: catalog/aclchk.c:1207 +#, c-format +msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON LARGE OBJECTS" +msgstr "'IN SCHEMA' პირობის გამოყენება GRANT/REVOKE ON LARGE OBJECT-ის გამოყენებისას შეუძლებელია" + +#: catalog/aclchk.c:1561 catalog/catalog.c:686 catalog/heap.c:2611 catalog/heap.c:2930 catalog/objectaddress.c:1528 catalog/pg_publication.c:570 commands/analyze.c:388 commands/copy.c:1000 commands/sequence.c:1655 commands/tablecmds.c:7751 commands/tablecmds.c:7929 commands/tablecmds.c:8130 commands/tablecmds.c:8259 commands/tablecmds.c:8388 commands/tablecmds.c:8482 commands/tablecmds.c:8585 commands/tablecmds.c:8751 commands/tablecmds.c:8781 +#: commands/tablecmds.c:8936 commands/tablecmds.c:9039 commands/tablecmds.c:9173 commands/tablecmds.c:9286 commands/tablecmds.c:14356 commands/tablecmds.c:14556 commands/tablecmds.c:14717 commands/tablecmds.c:15922 commands/tablecmds.c:18689 commands/trigger.c:947 parser/analyze.c:2660 parser/parse_relation.c:749 parser/parse_target.c:1070 parser/parse_type.c:144 parser/parse_utilcmd.c:3641 parser/parse_utilcmd.c:3681 parser/parse_utilcmd.c:3723 +#: statistics/attribute_stats.c:209 statistics/attribute_stats.c:948 utils/adt/acl.c:2921 utils/adt/ruleutils.c:2858 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "სვეტი \"%s\" ურთიერთობაში %s არ არსებობს" -#: catalog/aclchk.c:1861 +#: catalog/aclchk.c:1806 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" ინდექსია" -#: catalog/aclchk.c:1868 commands/tablecmds.c:14397 commands/tablecmds.c:17775 +#: catalog/aclchk.c:1813 commands/tablecmds.c:16079 commands/tablecmds.c:19608 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\" კომპოზიტური ტიპია" -#: catalog/aclchk.c:1876 catalog/objectaddress.c:1363 commands/tablecmds.c:263 commands/tablecmds.c:17739 utils/adt/acl.c:2101 utils/adt/acl.c:2131 utils/adt/acl.c:2164 utils/adt/acl.c:2200 utils/adt/acl.c:2231 utils/adt/acl.c:2262 +#: catalog/aclchk.c:1821 catalog/objectaddress.c:1368 commands/tablecmds.c:266 commands/tablecmds.c:19572 utils/adt/acl.c:2105 utils/adt/acl.c:2135 utils/adt/acl.c:2168 utils/adt/acl.c:2204 utils/adt/acl.c:2235 utils/adt/acl.c:2266 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\" მიმდევრობა არაა" -#: catalog/aclchk.c:1914 +#: catalog/aclchk.c:1859 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "მიმდევრობა \"%s\"-ს მხოლოდ USAGE, SELECT და UPDATE პრივილეგიების მხარდაჭერა გააჩნიათ" -#: catalog/aclchk.c:1931 +#: catalog/aclchk.c:1876 #, c-format msgid "invalid privilege type %s for table" msgstr "ცხრილის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:2094 +#: catalog/aclchk.c:2041 #, c-format msgid "invalid privilege type %s for column" msgstr "სვეტის პრივილეგიის არასწორი ტიპი: %s" -#: catalog/aclchk.c:2107 +#: catalog/aclchk.c:2054 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "მიმდევრობა \"%s\"-ს მხოლოდ SELECT სვეტის პრივილეგიების მხარდაჭერა გააჩნია" -#: catalog/aclchk.c:2297 +#: catalog/aclchk.c:2245 #, c-format msgid "language \"%s\" is not trusted" msgstr "ენა \"%s\" სანდო არაა" -#: catalog/aclchk.c:2299 +#: catalog/aclchk.c:2247 #, c-format msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages." msgstr "GRANT და REVOKE არასანდო ენებზე დაშვებული არაა, რადგან არასანდო ენების გამოყენება მხოლოდ ზემომხმარებლებს შეუძლიათ." -#: catalog/aclchk.c:2451 +#: catalog/aclchk.c:2398 #, c-format msgid "cannot set privileges of array types" msgstr "მასივის ტიპების პრივილეგიის დაყენება შეუძლებელია" -#: catalog/aclchk.c:2452 +#: catalog/aclchk.c:2399 #, c-format msgid "Set the privileges of the element type instead." msgstr "ნაცვლად დააყენეთ ელემენტის ტიპის პრივილეგიები." -#: catalog/aclchk.c:2456 +#: catalog/aclchk.c:2403 #, c-format msgid "cannot set privileges of multirange types" msgstr "მრავალშუალედიანი ტიპების პრივილეგიების დაყენება შეუძლებელია" -#: catalog/aclchk.c:2457 +#: catalog/aclchk.c:2404 #, c-format msgid "Set the privileges of the range type instead." msgstr "სანაცვლოდ შუალედის ტიპის პრივილეგიების დაყენება." -#: catalog/aclchk.c:2464 catalog/objectaddress.c:1629 -#, c-format -msgid "\"%s\" is not a domain" -msgstr "\"%s\" დომენი არაა" - -#: catalog/aclchk.c:2650 +#: catalog/aclchk.c:2587 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "პრივილეგიის უცნობი ტიპი \"%s\"" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2654 #, c-format msgid "permission denied for aggregate %s" msgstr "წვდომა აკრძალულია აგრეგატზე: \"%s\"" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2657 #, c-format msgid "permission denied for collation %s" msgstr "წვდომა აკრძალულია კოლაციაზე: \"%s\"" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2660 #, c-format msgid "permission denied for column %s" msgstr "წვდომა აკრძალულია სვეტზე: \"%s\"" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2663 #, c-format msgid "permission denied for conversion %s" msgstr "წვდომა აკრძალულია გადაყვანაზე: \"%s\"" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2666 #, c-format msgid "permission denied for database %s" msgstr "წვდომა აკრძალულია აგრეგატზე: \"%s\"" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2669 #, c-format msgid "permission denied for domain %s" msgstr "წვდომა აკრძალულია დომენზე: \"%s\"" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2672 #, c-format msgid "permission denied for event trigger %s" msgstr "წვდომა აკრძალულია მოვლენის ტრიგერზე: \"%s\"" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2675 #, c-format msgid "permission denied for extension %s" msgstr "წვდომა აკრძალულია გაფართოებაზე: \"%s\"" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2678 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "წვდომა აკრძალულია გარე მონაცემების გადამტანზე: \"%s\"" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2681 #, c-format msgid "permission denied for foreign server %s" msgstr "წვდომა აკრძალულია გარე სერვერზე: \"%s\"" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2684 #, c-format msgid "permission denied for foreign table %s" msgstr "წვდომა აკრძალულია გარე ცხრილზე: \"%s\"" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2687 #, c-format msgid "permission denied for function %s" msgstr "წვდომა აკრძალულია ფუნქციაზე: \"%s\"" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2690 #, c-format msgid "permission denied for index %s" msgstr "წვდომა აკრძალულია ინდექზე: \"%s\"" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2693 #, c-format msgid "permission denied for language %s" msgstr "წვდომა აკრძალულია ენაზე: \"%s\"" -#: catalog/aclchk.c:2759 +#: catalog/aclchk.c:2696 #, c-format msgid "permission denied for large object %s" msgstr "წვდომა აკრძალულია დიდ ობიექტზე: \"%s\"" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2699 #, c-format msgid "permission denied for materialized view %s" msgstr "წვდომა აკრძალულია მატერიალიზებულ ხედზე: \"%s\"" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2702 #, c-format msgid "permission denied for operator class %s" msgstr "წვდომა აკრძალულია ოპერატორის კლასზე: \"%s\"" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2705 #, c-format msgid "permission denied for operator %s" msgstr "წვდომა აკრძალულია ოპერატორზე: \"%s\"" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2708 #, c-format msgid "permission denied for operator family %s" msgstr "წვდომა აკრძალულია ოპერატორის ოჯახზე: \"%s\"" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2711 #, c-format msgid "permission denied for parameter %s" msgstr "წვდომა აკრძალულია პარამეტრზე: \"%s\"" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2714 #, c-format msgid "permission denied for policy %s" msgstr "წვდომა აკრძალულია წესზე: \"%s\"" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2717 #, c-format msgid "permission denied for procedure %s" msgstr "წვდომა აკრძალულია პროცედურაზე: \"%s\"" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for publication %s" msgstr "წვდომა აკრძალულია პუბლიკაციაზე: \"%s\"" -#: catalog/aclchk.c:2786 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for routine %s" msgstr "წვდომა აკრძალულია ქვეპროგრამაზე: \"%s\"" -#: catalog/aclchk.c:2789 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for schema %s" msgstr "წვდომა აკრძალულია სქემაზე: \"%s\"" -#: catalog/aclchk.c:2792 commands/sequence.c:647 commands/sequence.c:873 commands/sequence.c:915 commands/sequence.c:956 commands/sequence.c:1743 commands/sequence.c:1789 +#: catalog/aclchk.c:2729 commands/sequence.c:654 commands/sequence.c:880 commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 #, c-format msgid "permission denied for sequence %s" msgstr "წვდომა აკრძალულია მიმდევრობაზე: \"%s\"" -#: catalog/aclchk.c:2795 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for statistics object %s" msgstr "წვდომა აკრძალულია სტატისტიკის ობიექტზე: \"%s\"" -#: catalog/aclchk.c:2798 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for subscription %s" msgstr "წვდომა აკრძალულია გამოწერაზე: \"%s\"" -#: catalog/aclchk.c:2801 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for table %s" msgstr "წვდომა აკრძალულია ცხრილზე: \"%s\"" -#: catalog/aclchk.c:2804 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for tablespace %s" msgstr "წვდომა აკრძალულია ცხრილების სივრცეზე: \"%s\"" -#: catalog/aclchk.c:2807 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for text search configuration %s" msgstr "წვდომა აკრძალულია ტექსტის ძებნის კონფიგურაციაზე: \"%s\"" -#: catalog/aclchk.c:2810 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for text search dictionary %s" msgstr "წვდომა აკრძალულია ტექსტის ძებნის ლექსიკონზე: \"%s\"" -#: catalog/aclchk.c:2813 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for type %s" msgstr "წვდომა აკრძალულია ტიპტზე: \"%s\"" -#: catalog/aclchk.c:2816 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for view %s" msgstr "წვდომა აკრძალულია ხედზე: \"%s\"" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2789 #, c-format msgid "must be owner of aggregate %s" msgstr "უნდა ბრძანდებოდეთ აგრეგატის მფლობელი: %s" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2792 #, c-format msgid "must be owner of collation %s" msgstr "უნდა ბრძანდებოდეთ კოლაციის მფლობელი: %s" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2795 #, c-format msgid "must be owner of conversion %s" msgstr "უნდა ბრძანდებოდეთ გადაყვანის მფლობელი: %s" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2798 #, c-format msgid "must be owner of database %s" msgstr "უნდა ბრძანდებოდეთ ბაზის მფლობელი: %s" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2801 #, c-format msgid "must be owner of domain %s" msgstr "უნდა ბრძანდებოდეთ დომენის მფლობელი: %s" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2804 #, c-format msgid "must be owner of event trigger %s" msgstr "უნდა ბრძანდებოდეთ მოვლენის ტრიგერის მფლობელი: %s" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2807 #, c-format msgid "must be owner of extension %s" msgstr "უნდა ბრძანდებოდეთ გაფართოების მფლობელი: %s" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2810 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "უნდა ბრძანდებოდეთ გარე ინფორმაციის გადამტანის მფლობელი: %s" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2813 #, c-format msgid "must be owner of foreign server %s" msgstr "უნდა ბრძანდებოდეთ გარე სერვერის მფლობელი: %s" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2816 #, c-format msgid "must be owner of foreign table %s" msgstr "უნდა ბრძანდებოდეთ გარე ცხრილის მფლობელი: %s" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2819 #, c-format msgid "must be owner of function %s" msgstr "უნდა ბრძანდებოდეთ ფუნქციის მფლობელი: %s" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2822 #, c-format msgid "must be owner of index %s" msgstr "უნდა ბრძანდებოდეთ ინდექსის მფლობელი: %s" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2825 #, c-format msgid "must be owner of language %s" msgstr "უნდა ბრძანდებოდეთ ენის მფლობელი: %s" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2828 #, c-format msgid "must be owner of large object %s" msgstr "უნდა ბრძანდებოდეთ დიდი ობიექტის მფლობელი: %s" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2831 #, c-format msgid "must be owner of materialized view %s" msgstr "უნდა ბრძანდებოდეთ მატერიალიზებული ხედის მფლობელი: %s" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2834 #, c-format msgid "must be owner of operator class %s" msgstr "უნდა ბრძანდებოდეთ ოპერატორის კლასის მფლობელი: %s" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2837 #, c-format msgid "must be owner of operator %s" msgstr "უნდა ბრძანდებოდეთ ოპერატორის მფლობელი: %s" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2840 #, c-format msgid "must be owner of operator family %s" msgstr "უნდა ბრძანდებოდეთ ოპერატორის ოჯახის მფლობელი: %s" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2843 #, c-format msgid "must be owner of procedure %s" msgstr "უნდა ბრძანდებოდეთ პროცედურის მფლობელი: %s" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2846 #, c-format msgid "must be owner of publication %s" msgstr "უნდა ბრძანდებოდეთ პუბლიკაციისმფლობელი: %s" -#: catalog/aclchk.c:2912 +#: catalog/aclchk.c:2849 #, c-format msgid "must be owner of routine %s" msgstr "უნდა ბრძანდებოდეთ ქვეპროგრამის მფლობელი: %s" -#: catalog/aclchk.c:2915 +#: catalog/aclchk.c:2852 #, c-format msgid "must be owner of sequence %s" msgstr "უნდა ბრძანდებოდეთ მიმდევრობის მფლობელი: %s" -#: catalog/aclchk.c:2918 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of subscription %s" msgstr "უნდა ბრძანდებოდეთ გამოწერის მფლობელი: %s" -#: catalog/aclchk.c:2921 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of table %s" msgstr "უნდა ბრძანდებოდეთ ცხრილის მფლობელი: %s" -#: catalog/aclchk.c:2924 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of type %s" msgstr "უნდა ბრძანდებოდეთ ტიპის მფლობელი: %s" -#: catalog/aclchk.c:2927 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of view %s" msgstr "უნდა ბრძანდებოდეთ ხედის მფლობელი: %s" -#: catalog/aclchk.c:2930 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of schema %s" msgstr "უნდა ბრძანდებოდეთ სქემის მფლობელი: %s" -#: catalog/aclchk.c:2933 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of statistics object %s" msgstr "უნდა ბრძანდებოდეთ სტატისტიკის ობიექტის მფლობელი: %s" -#: catalog/aclchk.c:2936 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of tablespace %s" msgstr "უნდა ბრძანდებოდეთ ცხრილების სივრცის მფლობელი: %s" -#: catalog/aclchk.c:2939 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of text search configuration %s" msgstr "უნდა ბრძანდებოდეთ ტექსტის ძებნის კონფიგურაციის მფლობელი: %s" -#: catalog/aclchk.c:2942 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of text search dictionary %s" msgstr "უნდა ბრძანდებოდეთ ტექსტის ძებნის ლექსიკონის მფლობელი: %s" -#: catalog/aclchk.c:2956 +#: catalog/aclchk.c:2893 #, c-format msgid "must be owner of relation %s" msgstr "უნდა ბრძანდებოდეთ ურთიერთობის მფლობელი: %s" -#: catalog/aclchk.c:3002 +#: catalog/aclchk.c:2939 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "რელაციის (%2$s) სვეტზე (%1$s) წვდომა აკრძალულია" -#: catalog/aclchk.c:3159 catalog/aclchk.c:4167 catalog/aclchk.c:4198 -#, c-format -msgid "%s with OID %u does not exist" -msgstr "%s OID-ით %u არ არსებობს" - -#: catalog/aclchk.c:3242 catalog/aclchk.c:3261 +#: catalog/aclchk.c:3173 catalog/aclchk.c:3192 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "ურთერთობის (OID-ით %2$u) ატრიბუტი არ არსებობს: %1$d" -#: catalog/aclchk.c:3299 catalog/aclchk.c:3362 catalog/aclchk.c:4001 +#: catalog/aclchk.c:3230 catalog/aclchk.c:3293 catalog/aclchk.c:3932 #, c-format msgid "relation with OID %u does not exist" msgstr "ურთიერთობა OID-ით %u არ არსებობს" -#: catalog/aclchk.c:3547 +#: catalog/aclchk.c:3478 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "პარამეტრის ACL OID-ით %u არ არსებობს" -#: catalog/aclchk.c:3720 commands/collationcmds.c:853 commands/publicationcmds.c:1739 +#: catalog/aclchk.c:3557 catalog/objectaddress.c:1055 catalog/pg_largeobject.c:125 libpq/be-fsstubs.c:323 storage/large_object/inv_api.c:247 +#, c-format +msgid "large object %u does not exist" +msgstr "დიდი ობიექტი %u არ არსებობს" + +#: catalog/aclchk.c:3651 commands/collationcmds.c:849 commands/publicationcmds.c:1846 #, c-format msgid "schema with OID %u does not exist" msgstr "სქემა OID-ით %u არ არსებობს" -#: catalog/aclchk.c:3794 catalog/aclchk.c:3821 catalog/aclchk.c:3850 utils/cache/typcache.c:392 utils/cache/typcache.c:447 +#: catalog/aclchk.c:3725 catalog/aclchk.c:3752 catalog/aclchk.c:3781 utils/cache/typcache.c:473 utils/cache/typcache.c:528 #, c-format msgid "type with OID %u does not exist" msgstr "ტიპი OID-ით %u არ არსებობს" -#: catalog/catalog.c:447 +#: catalog/catalog.c:506 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "ურთიერთობაში \"%s\" გამოუყენებელი OID-ების ძებნა ჯერ კიდევ მიმდინარეობს" -#: catalog/catalog.c:449 +#: catalog/catalog.c:508 #, c-format -msgid "OID candidates have been checked %llu time, but no unused OID has been found yet." -msgid_plural "OID candidates have been checked %llu times, but no unused OID has been found yet." -msgstr[0] "OID-ის კანდიდატები %llu-ჯერ შემოწმდა, მაგრამ გამოუყენებელი OID-ი ნაპოვნი არაა." -msgstr[1] "OID-ის კანდიდატები %llu-ჯერ შემოწმდა, მაგრამ გამოუყენებელი OID-ი ნაპოვნი არაა." +msgid "OID candidates have been checked % time, but no unused OID has been found yet." +msgid_plural "OID candidates have been checked % times, but no unused OID has been found yet." +msgstr[0] "OID-ის კანდიდატები %-ჯერ შემოწმდა, მაგრამ გამოუყენებელი OID-ი ნაპოვნი არაა." +msgstr[1] "OID-ის კანდიდატები %-ჯერ შემოწმდა, მაგრამ გამოუყენებელი OID-ი ნაპოვნი არაა." -#: catalog/catalog.c:474 +#: catalog/catalog.c:533 #, c-format -msgid "new OID has been assigned in relation \"%s\" after %llu retry" -msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" -msgstr[0] "ახალი OID მინიჭებულია ურთიერთობაში \"%s\" %llu ცდის შემდეგ" -msgstr[1] "ახალი OID მინიჭებულია ურთიერთობაში \"%s\" %llu ცდის შემდეგ" +msgid "new OID has been assigned in relation \"%s\" after % retry" +msgid_plural "new OID has been assigned in relation \"%s\" after % retries" +msgstr[0] "ახალი OID მინიჭებულია ურთიერთობაში \"%s\" % ცდის შემდეგ" +msgstr[1] "ახალი OID მინიჭებულია ურთიერთობაში \"%s\" % ცდის შემდეგ" -#: catalog/catalog.c:607 catalog/catalog.c:674 +#: catalog/catalog.c:664 catalog/catalog.c:731 #, c-format msgid "must be superuser to call %s()" msgstr "%s()-ის გამოსაძახებლად ზემომხმარებელი უნდა იყოთ" -#: catalog/catalog.c:616 +#: catalog/catalog.c:673 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() მხოლოდ სისტემურ კატალოგებზე შეიძლება იყოს გამოყენებული" -#: catalog/catalog.c:621 parser/parse_utilcmd.c:2245 +#: catalog/catalog.c:678 parser/parse_utilcmd.c:2426 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "ინდექსი %s ცხრილს \"%s\" არ მიეკუთვნება" -#: catalog/catalog.c:638 +#: catalog/catalog.c:695 #, c-format msgid "column \"%s\" is not of type oid" msgstr "სვეტი \"%s\" oild-ის ტიპი არაა" -#: catalog/catalog.c:645 +#: catalog/catalog.c:702 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "ინდექსი \"%s\" სვეტის \"%s\" ინდექსი არაა" -#: catalog/dependency.c:497 catalog/pg_shdepend.c:695 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "%s-ის წაშლა შეუძლებელია. საჭიროა ბაზის სისტემისთვის" @@ -4456,7 +4416,7 @@ msgstr "%s დამოკიდებულია %s -ზე" msgid "drop cascades to %s" msgstr "წაშლა %s-ზეც ვრცელდება" -#: catalog/dependency.c:1138 catalog/pg_shdepend.c:860 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -4476,8 +4436,8 @@ msgstr[1] "" msgid "cannot drop %s because other objects depend on it" msgstr "%s-ის წაშლა შეუძლებელია, რადგან არის ობიექტები, რომლებიც მას ეყრდნობა" -#: catalog/dependency.c:1153 catalog/dependency.c:1160 catalog/dependency.c:1171 commands/tablecmds.c:1447 commands/tablecmds.c:14989 commands/tablespace.c:460 commands/user.c:1302 commands/vacuum.c:211 commands/view.c:441 libpq/auth.c:324 replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1427 utils/misc/guc.c:3169 utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6781 -#: utils/misc/guc.c:6815 utils/misc/guc.c:6849 utils/misc/guc.c:6892 utils/misc/guc.c:6934 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 catalog/dependency.c:1171 commands/tablecmds.c:1519 commands/tablecmds.c:16673 commands/tablespace.c:460 commands/user.c:1302 commands/vacuum.c:224 commands/view.c:441 executor/execExprInterp.c:5211 executor/execExprInterp.c:5219 libpq/auth.c:312 replication/logical/applyparallelworker.c:1041 replication/slot.c:1594 replication/syncrep.c:1079 storage/aio/method_io_uring.c:191 storage/lmgr/deadlock.c:1137 +#: storage/lmgr/proc.c:1526 utils/misc/guc.c:3166 utils/misc/guc.c:3207 utils/misc/guc.c:3282 utils/misc/guc.c:6823 utils/misc/guc.c:6857 utils/misc/guc.c:6891 utils/misc/guc.c:6934 utils/misc/guc.c:6976 #, c-format msgid "%s" msgstr "%s" @@ -4499,647 +4459,692 @@ msgid_plural "drop cascades to %d other objects" msgstr[0] "წაშლა გავრცელდება %d სხვა ობიექტზე" msgstr[1] "წაშლა გავრცელდება %d სხვა ობიექტზე" -#: catalog/dependency.c:1848 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "%s ტიპის კონსტანტის აქ გამოყენება არ შეიძლება" -#: catalog/dependency.c:2373 parser/parse_relation.c:3407 parser/parse_relation.c:3417 +#: catalog/dependency.c:2205 +#, c-format +msgid "transition table \"%s\" cannot be referenced in a persistent object" +msgstr "გარდასვლის ცხრილზე \"%s\" მიმართვა შეუძლებელია მუდმივი ობიექტიდან" + +#: catalog/dependency.c:2390 parser/parse_relation.c:3513 parser/parse_relation.c:3523 statistics/attribute_stats.c:221 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "სვეტი \"%d\" ურთიერთობაში %s არ არსებობს" -#: catalog/heap.c:325 +#: catalog/heap.c:321 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "\"%s.%s\"-ის შექმნის წვდომა აკრძალულია" -#: catalog/heap.c:327 +#: catalog/heap.c:323 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "სისტემური კატალოგების შეცვლა ამჟამად აკრძალულია." -#: catalog/heap.c:467 commands/tablecmds.c:2483 commands/tablecmds.c:2905 commands/tablecmds.c:7171 +#: catalog/heap.c:463 commands/tablecmds.c:2562 commands/tablecmds.c:3014 commands/tablecmds.c:7361 #, c-format msgid "tables can have at most %d columns" msgstr "ცხრილებს მაქსიმუმ %d სვეტი შეიძლება ჰქონდეს" -#: catalog/heap.c:485 commands/tablecmds.c:7440 +#: catalog/heap.c:481 commands/tablecmds.c:7663 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "სვეტის სახელი კონფლიქტშია სისტემური სვეტის სახელთან: \"%s\"" -#: catalog/heap.c:501 +#: catalog/heap.c:497 #, c-format msgid "column name \"%s\" specified more than once" msgstr "სვეტის სახელი ერთზე მეტჯერაა მითითებული: %s" #. translator: first %s is an integer not a name -#: catalog/heap.c:579 +#: catalog/heap.c:575 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "დანაყოფის საკვანძო სვეტის %s ფსევდო ტიპია %s" -#: catalog/heap.c:584 +#: catalog/heap.c:580 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "სვეტს \"%s\" გააჩნია ფსევდო ტიპი \"%s\"" -#: catalog/heap.c:615 +#: catalog/heap.c:595 +#, c-format +msgid "virtual generated column \"%s\" cannot have a domain type" +msgstr "ვირტუალურ გენერირებულ სვეტს \"%s\" დომენის ტიპი ვერ ექნება" + +#: catalog/heap.c:622 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "კომპოზიტური ტიპი %s საკუთარი თავის წევრი არ შეიძლება გახდეს" #. translator: first %s is an integer not a name -#: catalog/heap.c:670 +#: catalog/heap.c:677 #, c-format msgid "no collation was derived for partition key column %s with collatable type %s" msgstr "" -#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:507 +#: catalog/heap.c:683 commands/createas.c:200 commands/createas.c:513 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "" -#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:403 commands/tablecmds.c:4142 commands/tablecmds.c:20463 commands/tablecmds.c:20725 +#: catalog/heap.c:1169 catalog/index.c:901 commands/createas.c:409 commands/tablecmds.c:4296 #, c-format msgid "relation \"%s\" already exists" msgstr "ურთიერთობა \"%s\" უკვე არსებობს" -#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 commands/typecmds.c:1585 commands/typecmds.c:2556 +#: catalog/heap.c:1185 catalog/pg_type.c:434 catalog/pg_type.c:805 catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 commands/typecmds.c:758 commands/typecmds.c:1205 commands/typecmds.c:1431 commands/typecmds.c:1611 commands/typecmds.c:2586 #, c-format msgid "type \"%s\" already exists" msgstr "ტიპი \"%s\" უკვე არსებობს" -#: catalog/heap.c:1178 +#: catalog/heap.c:1186 #, c-format msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type." msgstr "ურთიერთობას იგივე სახელის მქონე ტიპი აქვს ასოცირებული, ასე რომ თქვენ უნდა გამოიყენოთ სახელი, რომელიც არც ერთ არსებულ ტიპთან კონფლიქტში არ შედის." -#: catalog/heap.c:1218 +#: catalog/heap.c:1226 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "toast relfilenumber-ის მნიშვნელობა ბინარული განახლების დროს დაყენებული არაა" -#: catalog/heap.c:1229 +#: catalog/heap.c:1237 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_class-ის დროებითი მეხსიერების OID-ის მნიშვნელობა დაყენებული არაა" -#: catalog/heap.c:1239 +#: catalog/heap.c:1247 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "relfilenumber-ის მნიშვნელობა ბინარული განახლების დროს დაყენებული არაა" -#: catalog/heap.c:2121 +#: catalog/heap.c:2192 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "დაყოფილი ცხრილს (\"%s\") NO INHERIT შეზღუდვას ვერ დაამატებთ" -#: catalog/heap.c:2393 +#: catalog/heap.c:2515 #, c-format msgid "check constraint \"%s\" already exists" msgstr "შეზღუდვის შემმოწმებელი \"%s\" უკვე არსებობს" -#: catalog/heap.c:2565 catalog/index.c:913 catalog/pg_constraint.c:724 commands/tablecmds.c:9364 +#: catalog/heap.c:2616 catalog/heap.c:2936 +#, c-format +msgid "cannot add not-null constraint on system column \"%s\"" +msgstr "არანულოვანი შეზღუდვის დამატება შეუძლებელია სისტემურ სვეტზე \"%s\"" + +#: catalog/heap.c:2643 catalog/heap.c:2769 catalog/heap.c:3020 catalog/index.c:915 catalog/pg_constraint.c:1003 commands/tablecmds.c:9796 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "შეზღუდვა \"%s\" ურთიერთობისთვის \"%s\" უკვე არსებობს" -#: catalog/heap.c:2572 +#: catalog/heap.c:2776 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "შეზღუდვა \"%s\" კონფლიქტშია არა-მემკვიდრეობით მიღებულ შეზღუდვასთან ურთიერთობაზე \"%s\"" -#: catalog/heap.c:2583 +#: catalog/heap.c:2787 #, c-format msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "შეზღუდვა \"%s\" კონფლიქტშია მემკვიდრეობით მიღებულ შეზღუდვასთან ურთიერთობაზე \"%s\"" -#: catalog/heap.c:2593 +#: catalog/heap.c:2797 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "შეზღუდვა \"%s\" კონფლიქტშია შეზღუდვასთან NOT VALID ურთიერთობაზე \"%s\"" -#: catalog/heap.c:2598 +#: catalog/heap.c:2809 +#, c-format +msgid "constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"" +msgstr "შეზღუდვა \"%s\" კონფლიქტშია შეზღუდვასთან NOT ENFORCED ურთიერთობაზე \"%s\"" + +#: catalog/heap.c:2814 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "შეზღუდვის (\"%s\") შერწყმა მემკვიდრეობითი აღწერით" -#: catalog/heap.c:2624 catalog/pg_constraint.c:853 commands/tablecmds.c:3062 commands/tablecmds.c:3365 commands/tablecmds.c:7097 commands/tablecmds.c:15807 commands/tablecmds.c:15938 +#: catalog/heap.c:2838 catalog/pg_constraint.c:781 catalog/pg_constraint.c:1132 commands/tablecmds.c:3179 commands/tablecmds.c:3499 commands/tablecmds.c:7286 commands/tablecmds.c:7967 commands/tablecmds.c:17516 commands/tablecmds.c:17698 #, c-format msgid "too many inheritance parents" msgstr "მეტისმეტად ბევრი მემკვიდრეობის მშობლები" -#: catalog/heap.c:2708 +#: catalog/heap.c:2955 parser/parse_utilcmd.c:2634 +#, c-format +msgid "conflicting NO INHERIT declaration for not-null constraint on column \"%s\"" +msgstr "" + +#: catalog/heap.c:2969 +#, c-format +msgid "conflicting not-null constraint names \"%s\" and \"%s\"" +msgstr "ურთიერთგამომრიცხავი არანულოვანი შეზღუდვის სახელები \"%s\" და \"%s\"" + +#: catalog/heap.c:2999 +#, c-format +msgid "cannot define not-null constraint on column \"%s\" with NO INHERIT" +msgstr "არანულოვანი შეზღუდვების აღწერა სვეტზე \"%s\" შეუძლებელია NO INHERIT-თან ერთად" + +#: catalog/heap.c:3001 +#, c-format +msgid "The column has an inherited not-null constraint." +msgstr "სვეტს მემკვიდრეობით მიღებული არანულოვანი შეზღუდვა გააჩნია." + +#: catalog/heap.c:3191 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "სვეტის გენერაციის გამოსახულებაში გენერირებული სვეტის (%s) გამოყენება შეუძლებელია" -#: catalog/heap.c:2710 +#: catalog/heap.c:3193 #, c-format msgid "A generated column cannot reference another generated column." msgstr "გენერირებული სვეტი სხვა გენერირებული სვეტის მიმართვა ვერ იქნება." -#: catalog/heap.c:2716 +#: catalog/heap.c:3199 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "" -#: catalog/heap.c:2717 +#: catalog/heap.c:3200 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "ამან შეიძლება დაგენერირებული სვეტის თავის საკუთარ მნიშვნელობაზე დამოკიდებულება გამოიწვიოს." -#: catalog/heap.c:2772 +#: catalog/heap.c:3255 #, c-format msgid "generation expression is not immutable" msgstr "თაობის გამოსახულება უცვლელი არაა" -#: catalog/heap.c:2800 rewrite/rewriteHandler.c:1281 +#: catalog/heap.c:3283 rewrite/rewriteHandler.c:1285 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "სვეტის \"%s\" ტიპია %s, მაგრამ ნაგულისხმევი გამოსახულების ტიპია %s" -#: catalog/heap.c:2805 commands/prepare.c:331 parser/analyze.c:2758 parser/parse_target.c:592 parser/parse_target.c:882 parser/parse_target.c:892 rewrite/rewriteHandler.c:1286 +#: catalog/heap.c:3288 commands/prepare.c:335 parser/analyze.c:2991 parser/parse_target.c:595 parser/parse_target.c:885 parser/parse_target.c:895 rewrite/rewriteHandler.c:1290 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "საჭიროა გამოსახულების გარდაქმნა ან გადაყვანა." -#: catalog/heap.c:2852 +#: catalog/heap.c:3335 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "შემოწმების შეზღუდვაში მხოლოდ %s ცხრილზე მიმართვა შეიძლება" -#: catalog/heap.c:3158 +#: catalog/heap.c:3641 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "\"ON COMMIT\"-ისა და გარე გასაღების წყვილი მხარდაუჭერელია" -#: catalog/heap.c:3159 +#: catalog/heap.c:3642 #, c-format msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting." msgstr "ცხრილი \"%s\", მითითება \"%s\", მაგრამ მათ იგივე ON COMMIT პარამეტრი არ აქვთ." -#: catalog/heap.c:3164 +#: catalog/heap.c:3647 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "გარე გასაღების შეზღუდვაში მიმართული ცხრილის შემცველობის დაცარიელება შეუძლებელია" -#: catalog/heap.c:3165 +#: catalog/heap.c:3648 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "ცხრილი \"%s\" მიუთითებს \"%s\"." -#: catalog/heap.c:3167 +#: catalog/heap.c:3650 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "წაშალეთ შემცველობა ცხრილისთვის \"%s\" პარალელურად, ან გამოიყენეთ TRUNCATE ... CASCADE." -#: catalog/index.c:219 parser/parse_utilcmd.c:2151 +#: catalog/index.c:220 parser/parse_utilcmd.c:2331 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "ცხრილისთვის \"%s\" ერთზე მეტი ძირითადი გასაღები დაუშვებელია" -#: catalog/index.c:233 +#: catalog/index.c:234 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "ძირითად გასაღებებს NULLS NOT DISTINCT ინდექსების გამოყენება არ შეუძლიათ" -#: catalog/index.c:250 +#: catalog/index.c:251 #, c-format msgid "primary keys cannot be expressions" msgstr "ძირითადი გასაღები გამოსახულება არ შეიძლება იყოს" -#: catalog/index.c:267 +#: catalog/index.c:268 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "ძირითადის გასაღების ტიპის სვეტი \"%s\" არაა აღწერილი, როგორც NOT NULL" -#: catalog/index.c:798 catalog/index.c:1914 +#: catalog/index.c:800 catalog/index.c:1921 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "სისტემური კატალოგების ცხრილებზე მომხმარებლის მიერ აღწერილი ინდექსების დადება შეუძლებელია" -#: catalog/index.c:838 +#: catalog/index.c:840 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "არადეტერმინისტული კოლაციები ოპერატორის კლასისთვის \"%s\" მხარდაჭერილი არაა" -#: catalog/index.c:853 +#: catalog/index.c:855 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "სისტემური კატალოგების ცხრილებზე ინდექსების პარალელური შექმნა მხარდაუჭერელია" -#: catalog/index.c:862 catalog/index.c:1330 +#: catalog/index.c:864 catalog/index.c:1333 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "პარალელური ინდექსის შექმნა გამორიცხვის შეზღუდვებისთვის მხარდაჭერილი არაა" -#: catalog/index.c:871 +#: catalog/index.c:873 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "გაზიარებული ინდექსების შექმნა შეუძლებელია initdb-ის შემდეგ" -#: catalog/index.c:891 commands/createas.c:418 commands/sequence.c:159 parser/parse_utilcmd.c:212 +#: catalog/index.c:893 commands/createas.c:424 commands/sequence.c:159 parser/parse_utilcmd.c:210 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "შეერთება \"%s\" უკვე არსებობს, გამოტოვება" -#: catalog/index.c:941 +#: catalog/index.c:943 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_class-ის ინდექსის OID-ის მნიშვნელობა დაყენებული არაა" -#: catalog/index.c:951 utils/cache/relcache.c:3787 +#: catalog/index.c:953 utils/cache/relcache.c:3795 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "index relfilenumber-ის მნიშვნელობა ბინარული განახლების დროს დაყენებული არაა" -#: catalog/index.c:2213 +#: catalog/index.c:2222 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY ტრანზაქციის პირველი ქმედება უნდა იყოს" -#: catalog/index.c:3669 +#: catalog/index.c:3729 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილების რეინდექსი შეუძლებელია" -#: catalog/index.c:3680 commands/indexcmds.c:3648 +#: catalog/index.c:3740 commands/indexcmds.c:3757 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "\"TOAST\" ცხრილზე არასწორი ინდექსის რეინდექსი შეუძლებელია" -#: catalog/index.c:3696 commands/indexcmds.c:3526 commands/indexcmds.c:3672 commands/tablecmds.c:3557 +#: catalog/index.c:3756 commands/indexcmds.c:3635 commands/indexcmds.c:3781 commands/tablecmds.c:3703 #, c-format msgid "cannot move system relation \"%s\"" msgstr "სისტემური ურთიერთობის გაადაადგილება არ შეიძლება: \"%s\"" -#: catalog/index.c:3833 +#: catalog/index.c:3893 #, c-format msgid "index \"%s\" was reindexed" msgstr "\"%s\"-ის რეინდექსი დასრულდა" -#: catalog/index.c:3999 +#: catalog/index.c:4059 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "'TOAST' ცხრილზე მდებარე არასწორი ინდექსის \"%s.%s\" რეინდექსი შეუძლებელია. გამოტოვება" -#: catalog/namespace.c:447 catalog/namespace.c:651 catalog/namespace.c:743 commands/trigger.c:5729 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 commands/trigger.c:5780 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "ბაზებს შორის ბმულები განხორციელებული არაა: \"%s.%s.%s\"" -#: catalog/namespace.c:504 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "დროებით ცხრილებს სქემის სახელი არ მიეთითებათ" -#: catalog/namespace.c:585 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "ბლოკის მიღების შეცდომა ურთიერთობაზე %s.%s\"" -#: catalog/namespace.c:590 commands/lockcmds.c:143 commands/lockcmds.c:223 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "ბლოკის მიღების შეცდომა ურთიერთობაზე %s\"" -#: catalog/namespace.c:618 parser/parse_relation.c:1430 +#: catalog/namespace.c:633 parser/parse_relation.c:1447 statistics/stat_utils.c:231 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "ურთიერთობა \"%s.%s\" არ არსებობს" -#: catalog/namespace.c:623 parser/parse_relation.c:1443 parser/parse_relation.c:1451 utils/adt/regproc.c:913 +#: catalog/namespace.c:638 parser/parse_relation.c:1460 parser/parse_relation.c:1468 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "ურთიერთობა \"%s\" არ არსებობს" -#: catalog/namespace.c:689 catalog/namespace.c:3507 commands/extension.c:1607 commands/extension.c:1613 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1804 commands/extension.c:1810 #, c-format msgid "no schema has been selected to create in" msgstr "შიგნით შესაქმნელი სქემა მონიშნული არაა" -#: catalog/namespace.c:841 catalog/namespace.c:854 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "სხვა სესიების დროებით სქემებთან ურთიერთობის შექმნა შეუძლებელია" -#: catalog/namespace.c:845 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "დროებითი ურთიერთობების შექმნა არა-დროებით სქემაში შეუძლებელია" -#: catalog/namespace.c:860 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "დროებით სქემებში მხოლოდ დროებითი ურთიერთობების შექმნა შეიძლება" -#: catalog/namespace.c:2604 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "სტატისტიკის ობიექტი \"%s\" არ არსებობს" -#: catalog/namespace.c:2746 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "ტექსტის ძებნის დამმუშავებელი \"%s\" არ არსებობს" -#: catalog/namespace.c:2891 utils/adt/regproc.c:1459 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "ტექსტის ძებნის ლექსიკონი \"%s\" არ არსებობს" -#: catalog/namespace.c:3037 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "ტექსტის ძებნის შაბლონი \"%s\" არ არსებობს" -#: catalog/namespace.c:3182 commands/tsearchcmds.c:1168 utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "ტექსტის ძებნის კონფიგურაცია \"%s\" არ არსებობს" -#: catalog/namespace.c:3314 parser/parse_expr.c:869 parser/parse_target.c:1259 +#: catalog/namespace.c:3329 parser/parse_expr.c:866 parser/parse_target.c:1262 #, c-format msgid "cross-database references are not implemented: %s" msgstr "ბაზებს შორის ბმულები განხორციელებული არაა: %s" -#: catalog/namespace.c:3320 gram.y:19230 gram.y:19270 parser/parse_expr.c:876 parser/parse_target.c:1266 +#: catalog/namespace.c:3335 gram.y:19418 gram.y:19458 parser/parse_expr.c:873 parser/parse_target.c:1269 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "არასწორი სრული სახელი (ძალიან ბევრი წერტილიანი სახელი): %s" -#: catalog/namespace.c:3450 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "ობიექტის დროებითი სქემიდან გამოტანა ან სქემაში შეტანა შეუძლებელია" -#: catalog/namespace.c:3456 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "\"TOAST\" სქემიდან ობიექტს ვერც გამოიტანთ, ვერც შეიტანთ" -#: catalog/namespace.c:3529 commands/schemacmds.c:264 commands/schemacmds.c:344 commands/tablecmds.c:1392 utils/adt/regproc.c:1688 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 commands/tablecmds.c:1464 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "სქემა \"%s\" არ არსებობს" -#: catalog/namespace.c:3560 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "ურთიერთობის არასწორი სახელი (ძალიან ბევრი წერტილიანი სახელი): %s" -#: catalog/namespace.c:4001 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "კოლაცია \"%s\" კოდირებისთვის \"%s\" არ არსებობს" -#: catalog/namespace.c:4056 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "გადაყვანა \"%s\" არ არსებობს" -#: catalog/namespace.c:4397 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "ბაზაში \"%s\" დროებითი ცხრილების შექმნის წვდომა აკრძალულია" -#: catalog/namespace.c:4413 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "აღდგენისას დროებითი ცხრილების შექმნა შეუძლებელია" -#: catalog/namespace.c:4419 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "პარალელური ოპერაციის მიმდინარეობისას დროებითი ცხრილების შექმნა შეუძლებელია" -#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2315 commands/tablecmds.c:12826 parser/parse_utilcmd.c:3249 +#: catalog/objectaddress.c:1376 commands/policy.c:93 commands/policy.c:373 commands/tablecmds.c:260 commands/tablecmds.c:302 commands/tablecmds.c:2387 commands/tablecmds.c:14491 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\" ცხრილი არაა" -#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 commands/tablecmds.c:17744 commands/view.c:114 +#: catalog/objectaddress.c:1383 commands/tablecmds.c:272 commands/tablecmds.c:19577 commands/view.c:113 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\" ხედი არაა" -#: catalog/objectaddress.c:1385 commands/matview.c:183 commands/tablecmds.c:275 commands/tablecmds.c:17749 +#: catalog/objectaddress.c:1390 commands/matview.c:201 commands/tablecmds.c:278 commands/tablecmds.c:19582 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\" არ არის მატერიალიზებული ხედი" -#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 commands/tablecmds.c:17754 +#: catalog/objectaddress.c:1397 commands/tablecmds.c:296 commands/tablecmds.c:19587 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\" გარე ცხრილი არაა" -#: catalog/objectaddress.c:1433 +#: catalog/objectaddress.c:1438 #, c-format msgid "must specify relation and object name" msgstr "ურთიერთობის და ობიექტის სახელის მითითება აუცილებელია" -#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 +#: catalog/objectaddress.c:1514 catalog/objectaddress.c:1567 #, c-format msgid "column name must be qualified" msgstr "სვეტს სახელი სრულად უნდა მიუთითოთ" -#: catalog/objectaddress.c:1581 +#: catalog/objectaddress.c:1586 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "ურთიერთობის (%2$s) სვეტის (%1$s) ნაგულისხმევი მნიშვნელობა არ არსებობს" -#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 utils/adt/acl.c:4554 +#: catalog/objectaddress.c:1623 commands/functioncmds.c:132 commands/tablecmds.c:288 commands/typecmds.c:278 commands/typecmds.c:3834 parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 utils/adt/acl.c:4558 #, c-format msgid "type \"%s\" does not exist" msgstr "ტიპი \"%s\" არ არსებობს" -#: catalog/objectaddress.c:1737 +#: catalog/objectaddress.c:1634 +#, c-format +msgid "\"%s\" is not a domain" +msgstr "\"%s\" დომენი არაა" + +#: catalog/objectaddress.c:1742 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "ოპერატორი %d (%s, %s) %s-დან არ არსებობს" -#: catalog/objectaddress.c:1768 +#: catalog/objectaddress.c:1773 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "ფუნქცია %d (%s, %s) %s-დან არ არსებობს" -#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 +#: catalog/objectaddress.c:1824 catalog/objectaddress.c:1850 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "სერვერზე (%2$s) მომხმარებლის ბმა %1$s-სთვის არ არსებობს" -#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:703 +#: catalog/objectaddress.c:1839 commands/foreigncmds.c:430 commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "სერვერი \"%s\" არ არსებობს" -#: catalog/objectaddress.c:1901 +#: catalog/objectaddress.c:1906 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "პუბლიკაციის ურთიერთობა %s პუბლიკაციაში %s არ არსებობ" -#: catalog/objectaddress.c:1948 +#: catalog/objectaddress.c:1953 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "პუბლიკაციის სქემა %s პუბლიკაციაში %s არ არსებობს" -#: catalog/objectaddress.c:2006 +#: catalog/objectaddress.c:2014 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "ნაგულისხმევი ACL ობიექტის უცნობი ტიპი \"%c\"" -#: catalog/objectaddress.c:2007 +#: catalog/objectaddress.c:2015 #, c-format -msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -msgstr "ობიექტის სწორი ტიპებია \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." +msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." +msgstr "ობიექტის სწორი ტიპებია \"%c\", \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -#: catalog/objectaddress.c:2058 +#: catalog/objectaddress.c:2067 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "ნაგულისხმევი ACL მომხმარებლისთვის %s სქემაში %s %s-ზე არ არსებობს" -#: catalog/objectaddress.c:2063 +#: catalog/objectaddress.c:2072 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "ნაგულისხმევი ACL მომხმარებლისთვის \"%s\" \"%s\"-ზე არ არსებობს" -#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2098 catalog/objectaddress.c:2155 catalog/objectaddress.c:2210 #, c-format msgid "name or argument lists may not contain nulls" msgstr "სახელი ან არგუმენტი არ შეიძლება ნულოვან სიმბოლოს შეიცავდეს" -#: catalog/objectaddress.c:2123 +#: catalog/objectaddress.c:2132 #, c-format msgid "unsupported object type \"%s\"" msgstr "ობიექტის მხარდაუჭერელი ტიპი: \"%s\"" -#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 +#: catalog/objectaddress.c:2151 catalog/objectaddress.c:2168 catalog/objectaddress.c:2233 catalog/objectaddress.c:2317 #, c-format msgid "name list length must be exactly %d" msgstr "სახელების სიის სიგრძე ზუსტად %d უნდა იყოს" -#: catalog/objectaddress.c:2163 +#: catalog/objectaddress.c:2172 #, c-format msgid "large object OID may not be null" msgstr "დიდი ობიექტის OID ნულის ტოლი არ შეიძლება იყოს" -#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 catalog/objectaddress.c:2249 +#: catalog/objectaddress.c:2181 catalog/objectaddress.c:2251 catalog/objectaddress.c:2258 #, c-format msgid "name list length must be at least %d" msgstr "სახელების სიის სიგრძე ყველაზე ცოტა %d უნდა იყოს" -#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 +#: catalog/objectaddress.c:2244 catalog/objectaddress.c:2265 #, c-format msgid "argument list length must be exactly %d" msgstr "არგუმენტების სიის სიგრძე ზუსტად %d უნდა იყოს" -#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2479 libpq/be-fsstubs.c:334 #, c-format msgid "must be owner of large object %u" msgstr "უნდა ბრძანდებოდეთ დიდი ობიექტის მფლობელი: %u" -#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 +#: catalog/objectaddress.c:2494 commands/functioncmds.c:1578 #, c-format msgid "must be owner of type %s or type %s" msgstr "უნდა ბრძანდებოდეთ მფლობელი ტიპისა %s ან %s" -#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 catalog/objectaddress.c:2527 +#: catalog/objectaddress.c:2521 catalog/objectaddress.c:2530 catalog/objectaddress.c:2536 #, c-format msgid "permission denied" msgstr "წვდომა აკრძალულია" -#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 +#: catalog/objectaddress.c:2522 catalog/objectaddress.c:2531 #, c-format msgid "The current user must have the %s attribute." msgstr "მიმდინარე მომხმარებელს %s ატრიბუტი აუცილებლად უნდა ჰქონდეს." -#: catalog/objectaddress.c:2528 +#: catalog/objectaddress.c:2537 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "მიმდინარე მომხმარებელს უნდა ჰქონდეს %s პარამეტრი როლზე \"%s\"." -#: catalog/objectaddress.c:2542 +#: catalog/objectaddress.c:2551 #, c-format msgid "must be superuser" msgstr "უნდა იყოს ზემომხმარებელი" -#: catalog/objectaddress.c:2611 +#: catalog/objectaddress.c:2620 #, c-format msgid "unrecognized object type \"%s\"" msgstr "ობიექტის უცნობი ტიპი: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2903 +#: catalog/objectaddress.c:2937 #, c-format msgid "column %s of %s" msgstr "სვეტი %s %s-ზე" -#: catalog/objectaddress.c:2918 +#: catalog/objectaddress.c:2952 #, c-format msgid "function %s" msgstr "ფუნქცია %s" -#: catalog/objectaddress.c:2931 +#: catalog/objectaddress.c:2965 #, c-format msgid "type %s" msgstr "ტიპი %s" -#: catalog/objectaddress.c:2968 +#: catalog/objectaddress.c:3002 #, c-format msgid "cast from %s to %s" msgstr "%s-დან %s" -#: catalog/objectaddress.c:3001 +#: catalog/objectaddress.c:3035 #, c-format msgid "collation %s" msgstr "კოლაცია %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3032 +#: catalog/objectaddress.c:3066 #, c-format msgid "constraint %s on %s" msgstr "%s-ის შეზღუდვა %s-ზე" -#: catalog/objectaddress.c:3038 +#: catalog/objectaddress.c:3072 #, c-format msgid "constraint %s" msgstr "შეზღუდვა %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3104 #, c-format msgid "conversion %s" msgstr "გარდაქმნა: %s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3092 +#: catalog/objectaddress.c:3126 #, c-format msgid "default value for %s" msgstr "%s-ის ნაგულისხმევი მნიშვნელობა" -#: catalog/objectaddress.c:3103 +#: catalog/objectaddress.c:3137 #, c-format msgid "language %s" msgstr "ენა %s" -#: catalog/objectaddress.c:3111 +#: catalog/objectaddress.c:3145 #, c-format msgid "large object %u" msgstr "დიდი ობიექტი %u" -#: catalog/objectaddress.c:3124 +#: catalog/objectaddress.c:3158 #, c-format msgid "operator %s" msgstr "ოპერატორი %s" -#: catalog/objectaddress.c:3161 +#: catalog/objectaddress.c:3195 #, c-format msgid "operator class %s for access method %s" msgstr "ოპერატორის კლასის %s წვდომის მეთოდისთვის %s" -#: catalog/objectaddress.c:3189 +#: catalog/objectaddress.c:3223 #, c-format msgid "access method %s" msgstr "წვდომის მეთოდი: %s" @@ -5148,7 +5153,7 @@ msgstr "წვდომის მეთოდი: %s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3238 +#: catalog/objectaddress.c:3278 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "ოპერატორი %d (%s, %s) of %s: %s" @@ -5157,236 +5162,241 @@ msgstr "ოპერატორი %d (%s, %s) of %s: %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3295 +#: catalog/objectaddress.c:3343 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "ფუნქცია %d (%s, %s) of %s: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3347 +#: catalog/objectaddress.c:3397 #, c-format msgid "rule %s on %s" msgstr "წესი %s %s-ზე" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3393 +#: catalog/objectaddress.c:3443 #, c-format msgid "trigger %s on %s" msgstr "ტრიგერი %s %s-ზე" -#: catalog/objectaddress.c:3413 +#: catalog/objectaddress.c:3463 #, c-format msgid "schema %s" msgstr "სქემა %s" -#: catalog/objectaddress.c:3441 +#: catalog/objectaddress.c:3491 #, c-format msgid "statistics object %s" msgstr "სტატისტიკის ობიექტი %s" -#: catalog/objectaddress.c:3472 +#: catalog/objectaddress.c:3522 #, c-format msgid "text search parser %s" msgstr "ტექსტის ძებნის დამმუშავებელი \"%s\"" -#: catalog/objectaddress.c:3503 +#: catalog/objectaddress.c:3553 #, c-format msgid "text search dictionary %s" msgstr "ტექსტის ძებნის ლექსიკონი %s" -#: catalog/objectaddress.c:3534 +#: catalog/objectaddress.c:3584 #, c-format msgid "text search template %s" msgstr "ტექსტის ძებნის შაბლონი %s" -#: catalog/objectaddress.c:3565 +#: catalog/objectaddress.c:3615 #, c-format msgid "text search configuration %s" msgstr "ტექსტის ძებნის კონფიგურაცია \"%s\"" -#: catalog/objectaddress.c:3578 +#: catalog/objectaddress.c:3628 #, c-format msgid "role %s" msgstr "როლი %s" -#: catalog/objectaddress.c:3615 catalog/objectaddress.c:5464 +#: catalog/objectaddress.c:3665 catalog/objectaddress.c:5589 #, c-format msgid "membership of role %s in role %s" msgstr "როლის (%s) წევრობა როლში %s" -#: catalog/objectaddress.c:3636 +#: catalog/objectaddress.c:3686 #, c-format msgid "database %s" msgstr "ბაზა: %s" -#: catalog/objectaddress.c:3652 +#: catalog/objectaddress.c:3702 #, c-format msgid "tablespace %s" msgstr "ცხრილების სივრცე %s" -#: catalog/objectaddress.c:3663 +#: catalog/objectaddress.c:3713 #, c-format msgid "foreign-data wrapper %s" msgstr "გარე-მონაცემების გადამტანი %s" -#: catalog/objectaddress.c:3673 +#: catalog/objectaddress.c:3723 #, c-format msgid "server %s" msgstr "სერვერი %s" -#: catalog/objectaddress.c:3706 +#: catalog/objectaddress.c:3756 #, c-format msgid "user mapping for %s on server %s" msgstr "მომხმარებლის ბმა %s-სთვის სერვერზე %s" -#: catalog/objectaddress.c:3758 +#: catalog/objectaddress.c:3808 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ ურთიერთობებზე, რომელიც ეკუთვნის როლს %s, სქემაში %s" -#: catalog/objectaddress.c:3762 +#: catalog/objectaddress.c:3812 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ ურთიერთობებზე, რომელიც ეკუთვნის როლს %s" -#: catalog/objectaddress.c:3768 +#: catalog/objectaddress.c:3818 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ მიმდევრობებზე, რომელიც ეკუთვნის როლს %s სქემაში %s" -#: catalog/objectaddress.c:3772 +#: catalog/objectaddress.c:3822 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ მიმდევრობებზე, რომელიც ეკუთვნის როლს %s" -#: catalog/objectaddress.c:3778 +#: catalog/objectaddress.c:3828 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ ფუნქციებზე, რომელიც ეკუთვნის როლს %s სქემაში %s" -#: catalog/objectaddress.c:3782 +#: catalog/objectaddress.c:3832 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ ფუნქციებზე, რომელიც ეკუთვნის როლს %s" -#: catalog/objectaddress.c:3788 +#: catalog/objectaddress.c:3838 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ სქემაზე, რომელიც ეკუთვნის როლს %s სქემაში %s" -#: catalog/objectaddress.c:3792 +#: catalog/objectaddress.c:3842 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ ტიპებზე, რომელიც ეკუთვნის როლს %s" -#: catalog/objectaddress.c:3798 +#: catalog/objectaddress.c:3848 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "ნაგულისხმევი პრივილეგიები ახალ სქემაზე, რომელიც ეკუთვნის როლს %s" -#: catalog/objectaddress.c:3805 +#: catalog/objectaddress.c:3854 +#, c-format +msgid "default privileges on new large objects belonging to role %s" +msgstr "ნაგულისხმევი პრივილეგიები ახალ დიდ ურთიერთობებზე, რომელიც ეკუთვნის როლს %s" + +#: catalog/objectaddress.c:3861 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "სქემაში (%s) როლის (%s) ნაგულისხმევი პრივილეგიები" -#: catalog/objectaddress.c:3809 +#: catalog/objectaddress.c:3865 #, c-format msgid "default privileges belonging to role %s" msgstr "როლის (%s) ნაგულისხმევი პრივილეგიები" -#: catalog/objectaddress.c:3831 +#: catalog/objectaddress.c:3887 #, c-format msgid "extension %s" msgstr "გაფართოებa %s" -#: catalog/objectaddress.c:3848 +#: catalog/objectaddress.c:3904 #, c-format msgid "event trigger %s" msgstr "მოვლენის ტრიგერი %s" -#: catalog/objectaddress.c:3872 +#: catalog/objectaddress.c:3928 #, c-format msgid "parameter %s" msgstr "პარამეტრი %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3915 +#: catalog/objectaddress.c:3971 #, c-format msgid "policy %s on %s" msgstr "წესი %s %s-ზე" -#: catalog/objectaddress.c:3929 +#: catalog/objectaddress.c:3985 #, c-format msgid "publication %s" msgstr "პუბლიკაცია %s" -#: catalog/objectaddress.c:3942 +#: catalog/objectaddress.c:3998 #, c-format msgid "publication of schema %s in publication %s" msgstr "სქემის (%s) პუბლიკაცია პუბლიკაციაში %s" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:3973 +#: catalog/objectaddress.c:4029 #, c-format msgid "publication of %s in publication %s" msgstr "%s-ის პუბლიკაცია პუბლიკაციაში %s" -#: catalog/objectaddress.c:3986 +#: catalog/objectaddress.c:4042 #, c-format msgid "subscription %s" msgstr "გამოწერა %s" -#: catalog/objectaddress.c:4007 +#: catalog/objectaddress.c:4063 #, c-format msgid "transform for %s language %s" msgstr "გარდაქმნა %s-სთვის, ენისთვის %s" -#: catalog/objectaddress.c:4076 +#: catalog/objectaddress.c:4132 #, c-format msgid "table %s" msgstr "ცხრილი %s" -#: catalog/objectaddress.c:4081 +#: catalog/objectaddress.c:4137 #, c-format msgid "index %s" msgstr "ინდექსი %s" -#: catalog/objectaddress.c:4085 +#: catalog/objectaddress.c:4141 #, c-format msgid "sequence %s" msgstr "თანმიმდევრობა %s" -#: catalog/objectaddress.c:4089 +#: catalog/objectaddress.c:4145 #, c-format msgid "toast table %s" msgstr "toast ცხრილი \"%s\"" -#: catalog/objectaddress.c:4093 +#: catalog/objectaddress.c:4149 #, c-format msgid "view %s" msgstr "%s-ის ხედი" -#: catalog/objectaddress.c:4097 +#: catalog/objectaddress.c:4153 #, c-format msgid "materialized view %s" msgstr "მატერიალიზებული ხედი %s" -#: catalog/objectaddress.c:4101 +#: catalog/objectaddress.c:4157 #, c-format msgid "composite type %s" msgstr "კომპოზიტის ტიპი \"%s\"" -#: catalog/objectaddress.c:4105 +#: catalog/objectaddress.c:4161 #, c-format msgid "foreign table %s" msgstr "გარე ცხრილი \"%s\"" -#: catalog/objectaddress.c:4110 +#: catalog/objectaddress.c:4166 #, c-format msgid "relation %s" msgstr "ურთიერთობა %s" -#: catalog/objectaddress.c:4151 +#: catalog/objectaddress.c:4207 #, c-format msgid "operator family %s for access method %s" msgstr "ოპერატორის ოჯახი %s წვდომის მეთოდისთვის %s" @@ -5428,7 +5438,7 @@ msgstr "" msgid "return type of inverse transition function %s is not %s" msgstr "ინვერსიული გარდამავალი ფუნქციის (\"%s\") დაბრუნების ტიპი %s არაა" -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2992 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3057 #, c-format msgid "strictness of aggregate's forward and inverse transition functions must match" msgstr "" @@ -5443,7 +5453,7 @@ msgstr "დამატებითი არგუმენტებს მქ msgid "return type of combine function %s is not %s" msgstr "ტიპი, რომელსაც კომბინირებული ფუნქცია %s-ი აბრუნებს, %s არაა" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:4005 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "კომბინირებული ფუნქცია გარდასვლის ტიპით %s არ შეიძლება აღწერილი იყოს, როგორც STRICT" @@ -5458,12 +5468,12 @@ msgstr "სერიალიზაციის ფუნქციის (%s) msgid "return type of deserialization function %s is not %s" msgstr "დესერიალიზაციის ფუნქციის (%s) დაბრუნების ტიპი %s არაა" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:217 catalog/pg_proc.c:251 #, c-format msgid "cannot determine result data type" msgstr "შედეგის მონაცემების ტიპის დადგენა შეუძლებელია" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:230 catalog/pg_proc.c:259 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "ფსევდო-ტიპი \"internal\" არაუსაფრთხოდ გამოიყენება" @@ -5478,48 +5488,48 @@ msgstr "" msgid "sort operator can only be specified for single-argument aggregates" msgstr "" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 +#: catalog/pg_aggregate.c:707 catalog/pg_proc.c:412 #, c-format msgid "cannot change routine kind" msgstr "ქვეპროგრამის ტიპის შეცვლა შეუძლებელია" -#: catalog/pg_aggregate.c:708 +#: catalog/pg_aggregate.c:709 #, c-format msgid "\"%s\" is an ordinary aggregate function." msgstr "\"%s\" ჩვეულებრივი აგრეგატული ფუნქციაა." -#: catalog/pg_aggregate.c:710 +#: catalog/pg_aggregate.c:711 #, c-format msgid "\"%s\" is an ordered-set aggregate." msgstr "\"%s\" დალაგებული-სეტის აგრეგატია." -#: catalog/pg_aggregate.c:712 +#: catalog/pg_aggregate.c:713 #, c-format msgid "\"%s\" is a hypothetical-set aggregate." msgstr "\"%s\" ჰიპოთეტიკური-სეტის აგრეგატია." -#: catalog/pg_aggregate.c:717 +#: catalog/pg_aggregate.c:718 #, c-format msgid "cannot change number of direct arguments of an aggregate function" msgstr "" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 parser/parse_func.c:631 +#: catalog/pg_aggregate.c:859 commands/functioncmds.c:701 commands/typecmds.c:2015 commands/typecmds.c:2061 commands/typecmds.c:2113 commands/typecmds.c:2150 commands/typecmds.c:2184 commands/typecmds.c:2218 commands/typecmds.c:2252 commands/typecmds.c:2281 commands/typecmds.c:2368 commands/typecmds.c:2410 parser/parse_func.c:417 parser/parse_func.c:448 parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 parser/parse_func.c:631 #: parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "ფუნქცია %s არ არსებობს" -#: catalog/pg_aggregate.c:864 +#: catalog/pg_aggregate.c:865 #, c-format msgid "function %s returns a set" msgstr "ფუნქცია %s სეტს აბრუნებს" -#: catalog/pg_aggregate.c:879 +#: catalog/pg_aggregate.c:880 #, c-format msgid "function %s must accept VARIADIC ANY to be used in this aggregate" msgstr "ამ აგრეგატში გამოსაყენებლად ფუნქცია (%s) VARIADIC ANY-ს უნდა იღებდეს" -#: catalog/pg_aggregate.c:903 +#: catalog/pg_aggregate.c:904 #, c-format msgid "function %s requires run-time type coercion" msgstr "" @@ -5599,21 +5609,51 @@ msgstr "კოლაცია \"%s\" უკვე არსებობს" msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "კოლაცია \"%s\" კოდირებისთვის \"%s\" უკვე არსებობს" -#: catalog/pg_constraint.c:732 +#: catalog/pg_constraint.c:758 commands/tablecmds.c:7952 +#, c-format +msgid "cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"" +msgstr "ურთიერთობაზე \"%2$s\" NOT NULL შეზღუდვის \"%1$s\" NO INHERIT სტატუსს ვერ შეცვლით" + +#: catalog/pg_constraint.c:760 commands/tablecmds.c:9559 +#, c-format +msgid "You might need to make the existing constraint inheritable using %s." +msgstr "" + +#: catalog/pg_constraint.c:770 +#, c-format +msgid "incompatible NOT VALID constraint \"%s\" on relation \"%s\"" +msgstr "შეუთავსებელი NOT VALID შეზღუდვა \"%s\" ურთიერთობაზე \"%s\"" + +#: catalog/pg_constraint.c:772 commands/tablecmds.c:9571 +#, c-format +msgid "You might need to validate it using %s." +msgstr "როგორც ჩანს, საჭიროა მისი სისწორე %s-ით დაამოწმოთ." + +#: catalog/pg_constraint.c:1011 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "შეზღუდვა \"%s\" დომენისთვის %s უკვე არსებობს" -#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 +#: catalog/pg_constraint.c:1212 catalog/pg_constraint.c:1305 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "ცხრილის (%2$s) შეზღუდვა (%1$s) არ არსებობს" -#: catalog/pg_constraint.c:1125 +#: catalog/pg_constraint.c:1405 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "დომენის (%2$s) შეზღუდვა (%1$s) არ არსებობს" +#: catalog/pg_constraint.c:1659 +#, c-format +msgid "invalid type for PERIOD part of foreign key" +msgstr "გარე გასაღების PRIOD ნაწილის ტიპი არასწორია" + +#: catalog/pg_constraint.c:1660 +#, c-format +msgid "Only range and multirange are supported." +msgstr "მხარდაჭერილია, მხოლოდ, შუალედი და მრავალი შუალედი." + #: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" @@ -5624,27 +5664,27 @@ msgstr "გადაყვანა უკვე არსებობს: \"%s\ msgid "default conversion for %s to %s already exists" msgstr "%s-დან %s-ზე ნაგულისხმევი გადაყვანა უკვე არსებობს" -#: catalog/pg_depend.c:224 commands/extension.c:3397 +#: catalog/pg_depend.c:223 commands/extension.c:3665 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "%s გაფართოების (\"%s\") წევრს უკვე წარმოადგენს" -#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 +#: catalog/pg_depend.c:230 catalog/pg_depend.c:281 commands/extension.c:3705 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "%s გაფართოების \"%s\"წევრი არაა" -#: catalog/pg_depend.c:234 +#: catalog/pg_depend.c:233 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "გაფართოებას უფლება, ჩაანაცვლოს ობიექტი, რომელიც მას არ ეკუთვნის, არ გააჩნია." -#: catalog/pg_depend.c:285 +#: catalog/pg_depend.c:284 #, c-format msgid "An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns." msgstr "გაფართოებას CREATE … IF NOT EXISTS-ის გამოყენება მხოლოდ იმისთვის შეუძლიათ, რომ გამოტოვონ ობიექტის შექმნა, თუ კონფლიქტური ობიექტი მას უკვე ეკუთვნის." -#: catalog/pg_depend.c:648 +#: catalog/pg_depend.c:647 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "%s-ზე დამოკიდებულებას ვერ მოაცილებთ. ის სისტემური ობიექტია" @@ -5694,7 +5734,7 @@ msgstr "დანაყოფის \"%s\" მოხსნის შეცდო msgid "The partition is being detached concurrently or has an unfinished detach." msgstr "ხდება დანაყოფის პარალელური მოხსნა ან მოხსნა დაუმთავრებელია." -#: catalog/pg_inherits.c:595 commands/tablecmds.c:4778 commands/tablecmds.c:16053 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4916 commands/tablecmds.c:17824 #, c-format msgid "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation." msgstr "მოხსნის ოპერაციის დასასრულებლად გამოიყენეთ ALTER TABLE ... DETACH PARTITION ... FINALIZE ." @@ -5799,44 +5839,44 @@ msgstr "" msgid "parameter ACL \"%s\" does not exist" msgstr "პარამეტრი ACL \"%s\" არ არსებობს" -#: catalog/pg_proc.c:130 parser/parse_func.c:2234 +#: catalog/pg_proc.c:158 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" msgstr[0] "ფუნქციებს %d-ზე მეტი არგუმენტი არ შეიძლება ჰქონდეთ" msgstr[1] "ფუნქციებს %d-ზე მეტი არგუმენტი არ შეიძლება ჰქონდეთ" -#: catalog/pg_proc.c:374 +#: catalog/pg_proc.c:402 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "ფუნქცია \"%s\" უკვე არსებობს იგივე არგუმენტის ტიპებით" -#: catalog/pg_proc.c:386 +#: catalog/pg_proc.c:414 #, c-format msgid "\"%s\" is an aggregate function." msgstr "\"%s\" აგრეგატული ფუნქციაა." -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:416 #, c-format msgid "\"%s\" is a function." msgstr "\"%s\" ფუნქციაა." -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:418 #, c-format msgid "\"%s\" is a procedure." msgstr "\"%s\" პროცედურაა." -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:420 #, c-format msgid "\"%s\" is a window function." msgstr "\"%s\" ფანჯრის ფუნქციაა." -#: catalog/pg_proc.c:412 +#: catalog/pg_proc.c:440 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "ფაქტს, აქვს თუ არა პროცედურას გამოტანის პარამეტრები, ვერ შეცვლით" -#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 +#: catalog/pg_proc.c:441 catalog/pg_proc.c:471 #, c-format msgid "cannot change return type of existing function" msgstr "არსებული ფუნქციის მნიშვნელობის დაბრუნების ტიპს ვერ შეცვლით" @@ -5845,112 +5885,112 @@ msgstr "არსებული ფუნქციის მნიშვნე #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 catalog/pg_proc.c:517 catalog/pg_proc.c:541 +#: catalog/pg_proc.c:447 catalog/pg_proc.c:474 catalog/pg_proc.c:519 catalog/pg_proc.c:545 catalog/pg_proc.c:569 #, c-format msgid "Use %s %s first." msgstr "ჯერ შეასრულეთ %s %s." -#: catalog/pg_proc.c:444 +#: catalog/pg_proc.c:472 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "OUT პარამეტრების მიერ აღწერილი მწკრივის ტიპი განსხვავებულია." -#: catalog/pg_proc.c:488 +#: catalog/pg_proc.c:516 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "შეყვანის პარამეტრის სახელის შეცვლა შეუძლებელია: \"%s\"" -#: catalog/pg_proc.c:515 +#: catalog/pg_proc.c:543 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "არსებული ფუნქციიდან პარამეტრის ნაგულისხმევი მნიშვნელობების წაშლა შეუძლებელია" -#: catalog/pg_proc.c:539 +#: catalog/pg_proc.c:567 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "არსებული პარამეტრის ნაგულისხმევი მნიშვნელობის მონაცემის ტიპს ვერ შეცვლით" -#: catalog/pg_proc.c:750 +#: catalog/pg_proc.c:771 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "ჩაშენებული ფუნქცია სახელით \"%s\" არ არსებობს" -#: catalog/pg_proc.c:843 +#: catalog/pg_proc.c:864 #, c-format msgid "SQL functions cannot return type %s" msgstr "SQL ფუნქციებს %s ტიპის დაბრუნება არ შეუძლიათ" -#: catalog/pg_proc.c:858 +#: catalog/pg_proc.c:879 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "SQL ფუნქციებს \"%s\" ტიპის არგუმენტები ვერ იქნება" -#: catalog/pg_proc.c:986 executor/functions.c:1467 +#: catalog/pg_proc.c:1007 #, c-format msgid "SQL function \"%s\"" msgstr "SQL ფუნქცია \"%s\"" -#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 catalog/pg_publication.c:82 catalog/pg_publication.c:88 +#: catalog/pg_publication.c:63 catalog/pg_publication.c:71 catalog/pg_publication.c:79 catalog/pg_publication.c:85 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "პუბლიკაციისთვის ურთიერთობის დამატება შეუძლებელია: %s" -#: catalog/pg_publication.c:76 +#: catalog/pg_publication.c:73 #, c-format msgid "This operation is not supported for system tables." msgstr "ეს ოპერაცია სისტემური ცხრილებისთვის მხარდაჭერილი არაა." -#: catalog/pg_publication.c:84 +#: catalog/pg_publication.c:81 #, c-format msgid "This operation is not supported for temporary tables." msgstr "ეს ოპერაცია დროებითი ცხრილებისთვის მხარდაჭერილი არაა." -#: catalog/pg_publication.c:90 +#: catalog/pg_publication.c:87 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "ეს ოპერაცია არაჟურნალირებადი ცხრილებისთვის მხარდაჭერილი არაა." -#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 +#: catalog/pg_publication.c:101 catalog/pg_publication.c:109 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "პუბლიკაციისთვის სქემის დამატება შეუძლებელია: %s" -#: catalog/pg_publication.c:106 +#: catalog/pg_publication.c:103 #, c-format msgid "This operation is not supported for system schemas." msgstr "ეს ოპერაცია სისტემური სქემებისთვის მხარდაჭერილი არაა." -#: catalog/pg_publication.c:114 +#: catalog/pg_publication.c:111 #, c-format msgid "Temporary schemas cannot be replicated." msgstr "დროებითი სქემების რეპლიკაცია შეუძლებელია." -#: catalog/pg_publication.c:392 +#: catalog/pg_publication.c:462 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "სქემა %s პუბლიკაციის (%s) ნაწილს უკვე წარმოადგენს" -#: catalog/pg_publication.c:534 +#: catalog/pg_publication.c:576 #, c-format msgid "cannot use system column \"%s\" in publication column list" msgstr "პუბლიკაციის სვეტების სიაში სისტემური სვეტის (\"%s\") გამოყენება შეუძლებელია" -#: catalog/pg_publication.c:540 +#: catalog/pg_publication.c:582 #, c-format -msgid "cannot use generated column \"%s\" in publication column list" -msgstr "პუბლიკაციის სვეტების სიაში გენერირებული სვეტის (\"%s\") გამოყენება შეუძლებელია" +msgid "cannot use virtual generated column \"%s\" in publication column list" +msgstr "ვირტუალურ გენერირებულ სვეტს \"%s\" გამოცემის სვეტების სიაში ვერ გამოიყენებთ" -#: catalog/pg_publication.c:546 +#: catalog/pg_publication.c:588 #, c-format msgid "duplicate column \"%s\" in publication column list" msgstr "პუბლიკაციის სვეტების სიაში დუბლიკატია: %s" -#: catalog/pg_publication.c:636 +#: catalog/pg_publication.c:700 #, c-format msgid "schema \"%s\" is already member of publication \"%s\"" msgstr "სქემა %s პუბლიკაციის (%s) ნაწილს უკვე წარმოადგენს" -#: catalog/pg_shdepend.c:867 +#: catalog/pg_shdepend.c:875 #, c-format msgid "" "\n" @@ -5965,70 +6005,70 @@ msgstr[1] "" "\n" "და ობიექტები %d სხვა ბაზაში (სიისთვის იხილეთ სერვერის ჟურნალი)" -#: catalog/pg_shdepend.c:1214 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "როლი %u სხვა პროცესის მიერ წაიშალა" -#: catalog/pg_shdepend.c:1226 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "ცხრილების სივრცე %u სხვა პროცესის მიერ წაიშალა" -#: catalog/pg_shdepend.c:1240 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "ბაზა %u სხვა პროცესის მიერ წაიშალა" -#: catalog/pg_shdepend.c:1291 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "%s -ის მფლობელი" -#: catalog/pg_shdepend.c:1293 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" msgstr "პრივილეგიები %s-სთვის" -#: catalog/pg_shdepend.c:1295 +#: catalog/pg_shdepend.c:1303 #, c-format msgid "initial privileges for %s" msgstr "საწყისი პრივილეგიები %s-სთვის" -#: catalog/pg_shdepend.c:1297 +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "%s-ის სამიზნე" -#: catalog/pg_shdepend.c:1299 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "ცხრილების სივრცე %s-სთვის" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1307 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" msgstr[0] "%d ობიექტი %s-ში" msgstr[1] "%d ობიექტი %s-ში" -#: catalog/pg_shdepend.c:1371 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "cannot drop objects owned by %s because they are required by the database system" msgstr "%s-ის წაშლა შეუძლებელია. საჭიროა ბაზის სისტემისთვის" -#: catalog/pg_shdepend.c:1545 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "cannot reassign ownership of objects owned by %s because they are required by the database system" msgstr "%s-ის მფლობელობაში მყოფი ობიექტების წვდომების თავიდან მინიჭება შეუძლებელია, რადგან ისინი ბაზის სისტემისთვისაა საჭირო" -#: catalog/pg_subscription.c:438 +#: catalog/pg_subscription.c:469 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "გამოწერისთვის \"%s\" ურთიერთობის მიბმის წაშლა შეუძლებელია" -#: catalog/pg_subscription.c:440 +#: catalog/pg_subscription.c:471 #, c-format msgid "Table synchronization for relation \"%s\" is in progress and is in state \"%c\"." msgstr "მიმდინარეობს ცხრილის სინქრონიზაცია ურთიერთობისთვის \"%s\" და მისი მდგომარეობაა \"%c\"." @@ -6036,7 +6076,7 @@ msgstr "მიმდინარეობს ცხრილის სინქ #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:447 +#: catalog/pg_subscription.c:478 #, c-format msgid "Use %s to enable subscription if not already enabled or use %s to drop the subscription." msgstr "გამოწერის ჩასართავად, თუ ის უკვე ჩართული არაა, %s გამოიყენეთ, ან, %s, გამოწერის წასაშლელად." @@ -6066,7 +6106,7 @@ msgstr "შიდა ზომა %d მნიშვნელობით-გა msgid "alignment \"%c\" is invalid for variable-length type" msgstr "სწორება \"%c\" არასწორია ცვლადი-სიგრძის ტიპისთვის" -#: catalog/pg_type.c:325 commands/typecmds.c:4363 +#: catalog/pg_type.c:325 commands/typecmds.c:4354 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "ფიქსირებული ზომის ტიპებს უნდა PLAIN ტიპის საცავი უნდა ჰქონდეთ" @@ -6081,7 +6121,7 @@ msgstr "შეცდომა მრავალდიაპაზონია msgid "You can manually specify a multirange type name using the \"multirange_type_name\" attribute." msgstr "მრავალდიაპაზონიანი ტიპის სახელი ხელით, \"multirange_type_name\" ატრიბუტით უნდა მიუთითოთ." -#: catalog/storage.c:508 storage/buffer/bufmgr.c:1540 +#: catalog/storage.c:549 storage/buffer/bufmgr.c:7339 #, c-format msgid "invalid page in block %u of relation %s" msgstr "ურთიერთობის (%2$s) ბლოკის (%1$u) არასწორ გვერდი" @@ -6166,7 +6206,7 @@ msgstr "სერიალიზაციის ფუნქციების msgid "must specify both or neither of serialization and deserialization functions" msgstr "აუცილებელია მიუთითოთ ან ორივე, სერიალიზაციის და დესერიალიზაციის ფუნქციები, ან არც ერთი" -#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:649 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "პარამეტრი \"parallel\" SAFE, RESTRICTED ან UNSAFE -ს შეიძლება უდრიდეს" @@ -6176,82 +6216,82 @@ msgstr "პარამეტრი \"parallel\" SAFE, RESTRICTED ან UNSAFE msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "პარამეტრი \"%s\" READ_ONLY, SHAREABLE, ან READ_WRITE უნდა იყოს" -#: commands/alter.c:82 commands/event_trigger.c:191 +#: commands/alter.c:83 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" msgstr "მოვლენის ტრიგერი უკვე არსებობს: %s" -#: commands/alter.c:85 commands/foreigncmds.c:593 +#: commands/alter.c:86 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "გარე მონაცემების გადამტანი უკვე არსებობს: %s" -#: commands/alter.c:88 commands/foreigncmds.c:884 +#: commands/alter.c:89 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "სერვერი \"%s\" უკვე არსებობს" -#: commands/alter.c:91 commands/proclang.c:131 +#: commands/alter.c:92 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "ენა \"%s\" უკვე არსებობს" -#: commands/alter.c:94 commands/publicationcmds.c:764 +#: commands/alter.c:95 commands/publicationcmds.c:865 #, c-format msgid "publication \"%s\" already exists" msgstr "პუბლიკაცია \"%s\" უკვე არსებობს" -#: commands/alter.c:97 commands/subscriptioncmds.c:669 +#: commands/alter.c:98 commands/subscriptioncmds.c:629 #, c-format msgid "subscription \"%s\" already exists" msgstr "გამოწერა \"%s\" უკვე არსებობს" -#: commands/alter.c:120 +#: commands/alter.c:121 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "გადაყვანა \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:124 +#: commands/alter.c:125 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "სტატისტიკის ობიექტი \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:128 +#: commands/alter.c:129 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "ტექსტის ძებნის დამმუშავებელი \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:132 +#: commands/alter.c:133 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "ტექსტის ძებნის ლექსიკონი \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:136 +#: commands/alter.c:137 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "ტექსტის ძიების შაბლონი \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:140 +#: commands/alter.c:141 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "ტექსტის ძიების კონფიგურაცია \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/alter.c:213 +#: commands/alter.c:214 #, c-format msgid "must be superuser to rename %s" msgstr "%s -ის სახელის გადარქმევისთვის საჭიროა ზემომხმარებლის უფლებები" -#: commands/alter.c:255 commands/subscriptioncmds.c:648 commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 commands/subscriptioncmds.c:1918 +#: commands/alter.c:256 commands/subscriptioncmds.c:608 commands/subscriptioncmds.c:1147 commands/subscriptioncmds.c:1231 commands/subscriptioncmds.c:1989 #, c-format msgid "password_required=false is superuser-only" msgstr "password_required=false მხოლოდ superuser-only-სთვისაა" -#: commands/alter.c:256 commands/subscriptioncmds.c:649 commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 commands/subscriptioncmds.c:1919 +#: commands/alter.c:257 commands/subscriptioncmds.c:609 commands/subscriptioncmds.c:1148 commands/subscriptioncmds.c:1232 commands/subscriptioncmds.c:1990 #, c-format msgid "Subscriptions with the password_required option set to false may only be created or modified by the superuser." msgstr "გამოწერები, რომლის password_required პარამეტრი ჭეშმარიტი არაა, მხოლოდ ზემომხმარებლის მიერ შეიძლება შეიქმნას და შეიცვალოს." -#: commands/alter.c:734 +#: commands/alter.c:746 #, c-format msgid "must be superuser to set schema of %s" msgstr "%s-ის სქემის დასაყენებლად საჭიროა ზემომხმარებლის უფლებები" @@ -6271,7 +6311,7 @@ msgstr "წვდომის მეთოდის შესაქმნელ msgid "access method \"%s\" already exists" msgstr "წვდომის მეთოდი \"%s\" უკვე არსებობს" -#: commands/amcmds.c:154 commands/indexcmds.c:221 commands/indexcmds.c:841 commands/opclasscmds.c:374 commands/opclasscmds.c:832 +#: commands/amcmds.c:154 commands/indexcmds.c:226 commands/indexcmds.c:859 commands/opclasscmds.c:375 commands/opclasscmds.c:833 #, c-format msgid "access method \"%s\" does not exist" msgstr "წვდომის მეთოდი \"%s\" არ არსებობს" @@ -6281,52 +6321,57 @@ msgstr "წვდომის მეთოდი \"%s\" არ არსებ msgid "handler function is not specified" msgstr "დამმუშავებელი ფუნქცია მითითებული არაა" -#: commands/amcmds.c:264 commands/event_trigger.c:200 commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 parser/parse_clause.c:943 +#: commands/amcmds.c:264 commands/event_trigger.c:200 commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:705 parser/parse_clause.c:941 #, c-format msgid "function %s must return type %s" msgstr "ფუნქციამ (%s) აუცილებლად უნდა დააბრუნოს ტიპი %s" -#: commands/analyze.c:217 +#: commands/analyze.c:215 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "%s-ის გამოტოვება --- გარე ცხრილის ანალიზი შეუძლებელია" -#: commands/analyze.c:234 +#: commands/analyze.c:232 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "%s-ის გამოტოვება --- არაცხრილების და სპეციალური სისტემური ცხრილების ანალიზი შეუძლებელია" -#: commands/analyze.c:314 +#: commands/analyze.c:317 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "\"%s.%s\" -ის მემკვიდრეობითი ხის ანალიზი" -#: commands/analyze.c:319 +#: commands/analyze.c:322 #, c-format msgid "analyzing \"%s.%s\"" msgstr "\"%s.%s\"-ის ანალიზი" -#: commands/analyze.c:385 +#: commands/analyze.c:393 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "ურთიერთობის (%2$s) სვეტი (%1$s) ერთზე მეტჯერ ჩნდება" -#: commands/analyze.c:780 +#: commands/analyze.c:803 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "ცხრილის ავტომატური ანალიზი \"%s.%s.%s\"\n" -#: commands/analyze.c:1295 +#: commands/analyze.c:805 +#, c-format +msgid "finished analyzing table \"%s.%s.%s\"\n" +msgstr "დასრულდა ანალიზი ცხრილისთვის \"%s.%s.%s\"\n" + +#: commands/analyze.c:1346 #, c-format msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows" msgstr "\"%s\": სკანირებული %d გვერდი %u-დან, შეიცავს %.0f ცოცხალ მწკრივს და %.0f მკვდარ მწკრივს; %d მწკრივს სემპლში, %.0f დაახლოებით მწკრივები სულ" -#: commands/analyze.c:1379 +#: commands/analyze.c:1430 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables" msgstr "\"%s.%s\"-ის მემკვიდრეობის ხის ანალიზის გამოტოვება --- მემკვიდრეობითობის ხე შვილ ცხრილებს არ შეიცავს" -#: commands/analyze.c:1477 +#: commands/analyze.c:1528 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables" msgstr "\"%s.%s\"-ის მემკვიდრეობის ხის ანალიზის გამოტოვება --- მემკვიდრეობითობის ხე გაანალიზებად შვილ ცხრილებს არ შეიცავს" @@ -6371,82 +6416,82 @@ msgstr "სერვერის პროცესი PID-ით %d უძვ msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction." msgstr "რიგის NOTIFY დაცარიელება პროცესის მიერ მიმდინარე ტრანზაქციის დასრულებამდე შეუძლებელია." -#: commands/cluster.c:128 +#: commands/cluster.c:127 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "\"CLUSTER\"-ის უცნობი პარამეტრი \"%s\"" -#: commands/cluster.c:159 commands/cluster.c:433 +#: commands/cluster.c:158 commands/cluster.c:421 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "სხვა სესიების დროებით ცხრილების დაკლასტერება შეუძლებელია" -#: commands/cluster.c:177 +#: commands/cluster.c:176 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "ცხრილისთვის \"%s\" წინასწარ დაკლასტერებული ინდექსი არ არსებობს" -#: commands/cluster.c:191 commands/tablecmds.c:14698 commands/tablecmds.c:16629 +#: commands/cluster.c:190 commands/tablecmds.c:16380 commands/tablecmds.c:18446 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "ინდექსი %s ცხრილისთვის %s არ არსებობს" -#: commands/cluster.c:422 +#: commands/cluster.c:410 #, c-format msgid "cannot cluster a shared catalog" msgstr "გაზიარებული კატალოგის დაკლასტერება შეუძლებელია" -#: commands/cluster.c:437 +#: commands/cluster.c:425 #, c-format msgid "cannot vacuum temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილების მომტვერსასრუტება შეუძლებელია" -#: commands/cluster.c:513 commands/tablecmds.c:16639 +#: commands/cluster.c:507 commands/tablecmds.c:18456 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "\"%s\" არ წარმოადგენს ინდექსს ცხრილისთვის \"%s\"" -#: commands/cluster.c:521 +#: commands/cluster.c:515 #, c-format msgid "cannot cluster on index \"%s\" because access method does not support clustering" msgstr "" -#: commands/cluster.c:533 +#: commands/cluster.c:527 #, c-format msgid "cannot cluster on partial index \"%s\"" msgstr "ნაწილობრივი ინდექსის (\"%s\") დაკლასტერება შეუძლებელია" -#: commands/cluster.c:547 +#: commands/cluster.c:541 #, c-format msgid "cannot cluster on invalid index \"%s\"" msgstr "არასწორი ინდექსის (\"%s\") დაკლასტერება შეუძლებელია" -#: commands/cluster.c:571 +#: commands/cluster.c:565 #, c-format msgid "cannot mark index clustered in partitioned table" msgstr "დაყოფილ ცხრილში ინდექსის დაკლასტერებულად მონიშვნა შეუძლებელია" -#: commands/cluster.c:956 +#: commands/cluster.c:961 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr "\"%s.%s\"-ის დაკლასტერება ინდექსის სკანირების გამოყენებით \"%s\"" -#: commands/cluster.c:962 +#: commands/cluster.c:967 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "\"%s.%s\"-ის დაკლასტერება თანმიმდევრული სკანირების და დახარისხების გამოყენებით" -#: commands/cluster.c:967 +#: commands/cluster.c:972 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "დამტვერსასრუტება \"%s.%s\"" -#: commands/cluster.c:994 +#: commands/cluster.c:999 #, c-format msgid "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" msgstr "\"%s.%s\": აღმოჩენილია %.0f წაშლადი და %.0f არაწაშლადი მწკრივის ვერსია %u გვერდში" -#: commands/cluster.c:999 +#: commands/cluster.c:1004 #, c-format msgid "" "%.0f dead row versions cannot be removed yet.\n" @@ -6455,7 +6500,7 @@ msgstr "" "%.0f მკვდარი მწკრივის ვერსების წაშლა ჯერჯერობით შეუძლებელია.\n" "%s." -#: commands/cluster.c:1744 +#: commands/cluster.c:1751 #, c-format msgid "permission denied to cluster \"%s\", skipping it" msgstr "კლასტერისთვის \"%s\" წვდომა აკრძალულია. გამოტოვება" @@ -6465,8 +6510,8 @@ msgstr "კლასტერისთვის \"%s\" წვდომა აკ msgid "collation attribute \"%s\" not recognized" msgstr "კოლაციის უცნობი ატრიბუტი: \"%s\"" -#: commands/collationcmds.c:123 commands/collationcmds.c:129 commands/define.c:388 commands/tablecmds.c:8137 replication/pgoutput/pgoutput.c:307 replication/pgoutput/pgoutput.c:330 replication/pgoutput/pgoutput.c:344 replication/pgoutput/pgoutput.c:354 replication/pgoutput/pgoutput.c:364 replication/pgoutput/pgoutput.c:374 replication/pgoutput/pgoutput.c:386 replication/walsender.c:1146 replication/walsender.c:1168 replication/walsender.c:1178 -#: replication/walsender.c:1187 replication/walsender.c:1426 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 commands/define.c:375 commands/tablecmds.c:8369 replication/pgoutput/pgoutput.c:320 replication/pgoutput/pgoutput.c:343 replication/pgoutput/pgoutput.c:357 replication/pgoutput/pgoutput.c:367 replication/pgoutput/pgoutput.c:377 replication/pgoutput/pgoutput.c:387 replication/pgoutput/pgoutput.c:399 replication/walsender.c:1123 replication/walsender.c:1145 replication/walsender.c:1155 +#: replication/walsender.c:1164 replication/walsender.c:1406 replication/walsender.c:1415 #, c-format msgid "conflicting or redundant options" msgstr "კონფლიქტური ან ზედმეტი პარამეტრები" @@ -6496,7 +6541,7 @@ msgstr "კოლაციის უცნობი მომწოდებე msgid "parameter \"%s\" must be specified" msgstr "პარამეტრის \"%s\" მითითება აუცილებელია" -#: commands/collationcmds.c:293 commands/dbcommands.c:1134 +#: commands/collationcmds.c:293 commands/dbcommands.c:1148 #, c-format msgid "using standard form \"%s\" for ICU locale \"%s\"" msgstr "ვიყენებ სტანდარტულ ფორმას \"%s\" ICU ლოკალისთვის \"%s\"" @@ -6506,7 +6551,7 @@ msgstr "ვიყენებ სტანდარტულ ფორმას msgid "nondeterministic collations not supported with this provider" msgstr "არადემინისტური კოლაციები, რომლებიც არ არის მხარდაჭერილი ამ მომწოდებელთან" -#: commands/collationcmds.c:317 commands/dbcommands.c:1087 +#: commands/collationcmds.c:317 commands/dbcommands.c:1101 #, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" msgstr "ICU-ის წესების მითითება მანამდე, სანამ ლოკალის მომწოდებელი ICU არაა, შეუძლებელია" @@ -6516,59 +6561,59 @@ msgstr "ICU-ის წესების მითითება მანა msgid "current database's encoding is not supported with this provider" msgstr "მონაცემთა ბაზის კოდირება არ არის მხარდაჭერილი ამ მომწოდებელთან" -#: commands/collationcmds.c:409 +#: commands/collationcmds.c:405 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "კოლაცია \"%s\" კოდირებისთვის \"%s\" სქემაში \"%s\" უკვე არსებობს" -#: commands/collationcmds.c:420 +#: commands/collationcmds.c:416 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "კოლაცია \"%s\" უკვე არსებობს სქემაში \"%s\"" -#: commands/collationcmds.c:445 +#: commands/collationcmds.c:441 #, c-format msgid "cannot refresh version of default collation" msgstr "ნაგულისხმევი კოლაციის ვერსიის განახლება შეუძლებელია" #. translator: %s is an SQL command #. translator: %s is an SQL ALTER command -#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 commands/tablecmds.c:7913 commands/tablecmds.c:7923 commands/tablecmds.c:7925 commands/tablecmds.c:14400 commands/tablecmds.c:17777 commands/tablecmds.c:17798 commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 +#: commands/collationcmds.c:443 commands/subscriptioncmds.c:1445 commands/tablecmds.c:8146 commands/tablecmds.c:8156 commands/tablecmds.c:8158 commands/tablecmds.c:16082 commands/tablecmds.c:19610 commands/tablecmds.c:19631 commands/typecmds.c:3778 commands/typecmds.c:3863 commands/typecmds.c:4217 #, c-format msgid "Use %s instead." msgstr "ამის ნაცვლად %s გამოიყენეთ." -#: commands/collationcmds.c:480 commands/dbcommands.c:2550 +#: commands/collationcmds.c:476 commands/dbcommands.c:2580 #, c-format msgid "changing version from %s to %s" msgstr "ვერსიის შეცვლა %s-დან %s-ზე" -#: commands/collationcmds.c:495 commands/dbcommands.c:2563 +#: commands/collationcmds.c:491 commands/dbcommands.c:2593 #, c-format msgid "version has not changed" msgstr "ვერსია არ შეცვლილა" -#: commands/collationcmds.c:528 commands/dbcommands.c:2729 +#: commands/collationcmds.c:524 commands/dbcommands.c:2763 utils/adt/dbsize.c:180 #, c-format msgid "database with OID %u does not exist" msgstr "ბაზა OID-ით %u არ არსებობს" -#: commands/collationcmds.c:554 +#: commands/collationcmds.c:550 #, c-format msgid "collation with OID %u does not exist" msgstr "კოლაცია OID-ით %u არ არსებობს" -#: commands/collationcmds.c:848 +#: commands/collationcmds.c:844 #, c-format msgid "must be superuser to import system collations" msgstr "სისტემური კოლაციების შემოსატანად საჭიროა ზემომხმარებლის უფლებები" -#: commands/collationcmds.c:968 commands/collationcmds.c:1053 +#: commands/collationcmds.c:964 commands/collationcmds.c:1049 #, c-format msgid "no usable system locales were found" msgstr "გამოყენებადი სისტემური ენები ნაპოვნი არაა" -#: commands/comment.c:61 commands/dbcommands.c:1663 commands/dbcommands.c:1875 commands/dbcommands.c:1985 commands/dbcommands.c:2183 commands/dbcommands.c:2421 commands/dbcommands.c:2512 commands/dbcommands.c:2633 commands/dbcommands.c:3141 utils/init/postinit.c:1033 utils/init/postinit.c:1097 utils/init/postinit.c:1170 +#: commands/comment.c:61 commands/dbcommands.c:1679 commands/dbcommands.c:1897 commands/dbcommands.c:2009 commands/dbcommands.c:2207 commands/dbcommands.c:2447 commands/dbcommands.c:2540 commands/dbcommands.c:2664 commands/dbcommands.c:3175 utils/init/postinit.c:1027 utils/init/postinit.c:1091 utils/init/postinit.c:1164 #, c-format msgid "database \"%s\" does not exist" msgstr "მონაცემთა ბაზა \"%s\" არ არსებობს" @@ -6578,12 +6623,12 @@ msgstr "მონაცემთა ბაზა \"%s\" არ არსებ msgid "cannot set comment on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" კომენტარის დადება შეუძლებელია" -#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2175 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "ფუნქცია ტრიგერის მმართველის მიერ არ გამოძახებულა: %s" -#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2184 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "ფუნქცია %s AFTER-ის ტრიგერით უნდა გაეშვას" @@ -6673,309 +6718,265 @@ msgstr "\"COPY TO\"-ში %s-ის HEADER-თან ერთად გამ msgid "%s requires a Boolean value or \"match\"" msgstr "%s -ს ლოგიკური მნიშვნელობა უნდა ჰქონდეს, ან \"match\"" -#: commands/copy.c:400 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:818 commands/copy.c:834 commands/copy.c:851 commands/copy.c:877 commands/copy.c:887 +#, c-format +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s-ს %s-სთან ერთად ვერ გამოიყენებთ" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:474 #, c-format -msgid "COPY ON_ERROR cannot be used with COPY TO" -msgstr "COPY ON_ERROR-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" +msgid "COPY %s \"%s\" not recognized" +msgstr "COPY %s \"%s\" უცნობია" -#: commands/copy.c:413 +#: commands/copy.c:436 commands/define.c:73 commands/define.c:84 commands/define.c:178 commands/define.c:196 commands/define.c:211 commands/define.c:229 #, c-format -msgid "COPY ON_ERROR \"%s\" not recognized" -msgstr "COPY ON_ERROR \"%s\" უცნობია" +msgid "%s requires a numeric value" +msgstr "%s მოითხოვს რიცხვით მნიშვნელობას" -#: commands/copy.c:437 +#: commands/copy.c:446 #, c-format -msgid "COPY LOG_VERBOSITY \"%s\" not recognized" -msgstr "COPY LOG_VERBOSITY \"%s\" უცნობია" +msgid "REJECT_LIMIT (%) must be greater than zero" +msgstr "REJECT_LIMIT (%) ნულზე მეტი უნდა იყოს" -#: commands/copy.c:498 +#: commands/copy.c:536 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "COPY-ის უცნობი ფორმატი: \"%s\"" -#: commands/copy.c:556 commands/copy.c:571 commands/copy.c:586 commands/copy.c:605 +#: commands/copy.c:594 commands/copy.c:609 commands/copy.c:624 commands/copy.c:643 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "პარამეტრის (%s) არგუმენტი სვეტების სახელების სია უნდა იყოს" -#: commands/copy.c:617 +#: commands/copy.c:655 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "პარამეტრის (%s) არგუმენტი კოდირების სწორი სახელი უნდა იყოს" -#: commands/copy.c:638 commands/dbcommands.c:866 commands/dbcommands.c:2369 +#: commands/copy.c:683 commands/dbcommands.c:880 commands/dbcommands.c:2395 #, c-format msgid "option \"%s\" not recognized" msgstr "უცნობი პარამეტრი: %s" -#: commands/copy.c:650 -#, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "რეჟიმში BINARY \"DELIMITER\"-ს ვერ მიუთითებთ" - -#: commands/copy.c:655 -#, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "რეჟიმში BINARY \"NULL\"-ს ვერ მიუთითებთ" - -#: commands/copy.c:660 -#, c-format -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "'BINARY' რეჟიმში DEFAULT-ს ვერ მიუთითებთ" - -#: commands/copy.c:665 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:696 commands/copy.c:701 commands/copy.c:706 commands/copy.c:776 #, c-format -msgid "only ON_ERROR STOP is allowed in BINARY mode" -msgstr "" +msgid "cannot specify %s in BINARY mode" +msgstr "რეჟიმში BINARY \"%s\"-ს ვერ მიუთითებთ" -#: commands/copy.c:687 +#: commands/copy.c:728 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "COPY-ის გამყოფი ერთბაიტიანი სიმბოლო უნდა იყოს" -#: commands/copy.c:694 +#: commands/copy.c:735 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "COPY-ის გამყოფი ხაზის გადატანა ან კარეტის დაბრუნება არ უნდა იყოს" -#: commands/copy.c:700 +#: commands/copy.c:741 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "COPY-ის ნულოვან რეპრეზენტაციას ახალი ხაზის ან კარეტის დაბრუნება გამოყენება არ შეუძლია" -#: commands/copy.c:710 +#: commands/copy.c:751 #, c-format msgid "COPY default representation cannot use newline or carriage return" msgstr "COPY-ის ნაგულისხმევ რეპრეზენტაციას ახალი ხაზის ან კარეტის დაბრუნება გამოყენება არ შეუძლია" -#: commands/copy.c:728 +#: commands/copy.c:769 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "COPY-ის გამყოფი \"%s\" არ შეიძლება იყოს" -#: commands/copy.c:734 -#, c-format -msgid "cannot specify HEADER in BINARY mode" -msgstr "რეჟიმში BINARY \"HEADER\"-ს ვერ მიუთითებთ" - -#: commands/copy.c:740 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:783 commands/copy.c:800 commands/copy.c:812 commands/copy.c:827 commands/copy.c:843 #, c-format -msgid "COPY QUOTE requires CSV mode" -msgstr "COPY QUOTE-ს CSV რეჟიმი სჭირდება" +msgid "COPY %s requires CSV mode" +msgstr "COPY %s-ს CSV რეჟიმი სჭირდება" -#: commands/copy.c:745 +#: commands/copy.c:788 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "COPY-ის ბრჭყალი ერთბაიტიანი სიმბოლო უნდა იყოს" -#: commands/copy.c:750 +#: commands/copy.c:793 #, c-format msgid "COPY delimiter and quote must be different" msgstr "COPY-ის გამყოფი და ბრჭყალი სხვადასხვა სიმბოლო უნდა იყოს" -#: commands/copy.c:756 -#, c-format -msgid "COPY ESCAPE requires CSV mode" -msgstr "COPY ESCAPE-ს CSV რეჟიმი სჭირდება" - -#: commands/copy.c:761 +#: commands/copy.c:805 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "COPY-ის სპეცსიმბოლო ერთბაიტიანი სიმბოლო უნდა იყოს" -#: commands/copy.c:767 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:859 commands/copy.c:895 #, c-format -msgid "COPY FORCE_QUOTE requires CSV mode" -msgstr "COPY FORCE_QUOTE-ს CSV რეჟიმი სჭირდება" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "COPY-ის გამყოფი სიმბოლო %s-ის სპეციფიკაციაში არ უნდა ჩანდეს" -#: commands/copy.c:771 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:868 commands/copy.c:904 #, c-format -msgid "COPY FORCE_QUOTE cannot be used with COPY FROM" -msgstr "COPY FORCE_QUOTE-ს COPY FROM-სთან ერთად ვერ გამოიყენებთ" +msgid "CSV quote character must not appear in the %s specification" +msgstr "CSV-ის ბრჭყალის სიმბოლო %s-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" -#: commands/copy.c:777 +#: commands/copy.c:913 #, c-format -msgid "COPY FORCE_NOT_NULL requires CSV mode" -msgstr "COPY FORCE_NOT_NULL-ს CSV რეჟიმი სჭირდება" +msgid "NULL specification and DEFAULT specification cannot be the same" +msgstr "NULL-ის სპეციფიკაცია და DEFAULT-ის სპეციფიკაცია ერთი და იგივე ვერ იქნება" -#: commands/copy.c:781 +#: commands/copy.c:919 #, c-format -msgid "COPY FORCE_NOT_NULL cannot be used with COPY TO" -msgstr "COPY FORCE_NOT_NULL-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "" -#: commands/copy.c:787 +#. translator: first and second %s are the names of COPY option, e.g. +#. * ON_ERROR, third is the value of the COPY option, e.g. IGNORE +#: commands/copy.c:926 #, c-format -msgid "COPY FORCE_NULL requires CSV mode" -msgstr "COPY FORCE_NULL-ს CSV რეჟიმი სჭირდება" +msgid "COPY %s requires %s to be set to %s" +msgstr "COPY %s-ს სჭირდება %s დაყენებული იყოს მნიშვნელობაზე %s" -#: commands/copy.c:792 +#: commands/copy.c:988 #, c-format -msgid "COPY FORCE_NULL cannot be used with COPY TO" -msgstr "COPY FORCE_NULL-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" +msgid "column \"%s\" is a generated column" +msgstr "სვეტი \"%s\" გენერირებული სვეტია" -#: commands/copy.c:798 -#, c-format -msgid "COPY delimiter character must not appear in the NULL specification" -msgstr "COPY-ის გამყოფი სიმბოლო NULL-ის სპეციფიკაციაში არ ჩანდეს" - -#: commands/copy.c:805 -#, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "CSV-ის ბრჭყალის სიმბოლო NULL-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" - -#: commands/copy.c:811 -#, c-format -msgid "COPY FREEZE cannot be used with COPY TO" -msgstr "COPY FREEZE-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" - -#: commands/copy.c:818 -#, c-format -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "COPY DEFAULT მხოლოდ COPY FROM-ის გამოყენების დროსაა ხელმისაწვდომი" - -#: commands/copy.c:824 -#, c-format -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "COPY-ის გამყოფი DEFAULT-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" - -#: commands/copy.c:831 -#, c-format -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "CSV-ის ბრჭყალის სიმბოლო DEFAULT-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" - -#: commands/copy.c:839 -#, c-format -msgid "NULL specification and DEFAULT specification cannot be the same" -msgstr "NULL-ის სპეციფიკაცია და DEFAULT-ის სპეციფიკაცია ერთი და იგივე ვერ იქნება" - -#: commands/copy.c:901 -#, c-format -msgid "column \"%s\" is a generated column" -msgstr "სვეტი \"%s\" გენერირებული სვეტია" - -#: commands/copy.c:903 +#: commands/copy.c:990 #, c-format msgid "Generated columns cannot be used in COPY." msgstr "გენერირებული სვეტები COPY-ში არ გამოიყენება." -#: commands/copy.c:918 commands/indexcmds.c:1915 commands/statscmds.c:239 commands/tablecmds.c:2514 commands/tablecmds.c:2985 commands/tablecmds.c:3781 parser/parse_relation.c:3692 parser/parse_relation.c:3702 parser/parse_relation.c:3720 parser/parse_relation.c:3727 parser/parse_relation.c:3741 utils/adt/tsvector_op.c:2853 +#: commands/copy.c:1005 commands/indexcmds.c:1959 commands/statscmds.c:239 commands/tablecmds.c:2593 commands/tablecmds.c:3101 commands/tablecmds.c:3930 parser/parse_relation.c:3798 parser/parse_relation.c:3808 parser/parse_relation.c:3826 parser/parse_relation.c:3833 parser/parse_relation.c:3847 utils/adt/tsvector_op.c:2853 #, c-format msgid "column \"%s\" does not exist" msgstr "სვეტი არ არსებობს: \"%s\"" -#: commands/copy.c:925 commands/tablecmds.c:2540 commands/trigger.c:951 parser/parse_target.c:1083 parser/parse_target.c:1094 +#: commands/copy.c:1012 commands/tablecmds.c:2619 commands/trigger.c:956 parser/parse_target.c:1086 parser/parse_target.c:1097 #, c-format msgid "column \"%s\" specified more than once" msgstr "სვეტი ერთზე მეტჯერაა მითითებული: \"%s\"" -#: commands/copyfrom.c:118 +#: commands/copyfrom.c:260 #, c-format msgid "COPY %s" msgstr "COPY %s" -#: commands/copyfrom.c:126 +#: commands/copyfrom.c:268 #, c-format -msgid "COPY %s, line %llu, column %s" -msgstr "COPY %s, ხაზი %llu, სვეტი %s" +msgid "COPY %s, line %, column %s" +msgstr "COPY %s, ხაზი %, სვეტი %s" -#: commands/copyfrom.c:131 commands/copyfrom.c:177 +#: commands/copyfrom.c:273 commands/copyfrom.c:319 #, c-format -msgid "COPY %s, line %llu" -msgstr "COPY %s, ხაზი %llu" +msgid "COPY %s, line %" +msgstr "COPY %s, ხაზი %" -#: commands/copyfrom.c:143 +#: commands/copyfrom.c:285 #, c-format -msgid "COPY %s, line %llu, column %s: \"%s\"" -msgstr "COPY %s, ხაზი %llu, სვეტი %s: \"%s\"" +msgid "COPY %s, line %, column %s: \"%s\"" +msgstr "COPY %s, ხაზი %, სვეტი %s: \"%s\"" -#: commands/copyfrom.c:153 +#: commands/copyfrom.c:295 #, c-format -msgid "COPY %s, line %llu, column %s: null input" -msgstr "COPY %s, ხაზი %llu, სვეტი %s: ნულოვანი შეყვანა" +msgid "COPY %s, line %, column %s: null input" +msgstr "COPY %s, ხაზი %, სვეტი %s: ნულოვანი შეყვანა" -#: commands/copyfrom.c:170 +#: commands/copyfrom.c:312 #, c-format -msgid "COPY %s, line %llu: \"%s\"" -msgstr "COPY %s, ხაზი %llu: \"%s\"" +msgid "COPY %s, line %: \"%s\"" +msgstr "COPY %s, ხაზი %: \"%s\"" -#: commands/copyfrom.c:673 +#: commands/copyfrom.c:823 #, c-format msgid "cannot copy to view \"%s\"" msgstr "ხედზე კოპირების შეცდომა: \"%s\"" -#: commands/copyfrom.c:675 +#: commands/copyfrom.c:825 #, c-format msgid "To enable copying to a view, provide an INSTEAD OF INSERT trigger." msgstr "ხედში კოპირებისთვის INSTEAD OF INSERT ტრიგერი წარმოადგინეთ." -#: commands/copyfrom.c:679 +#: commands/copyfrom.c:829 #, c-format msgid "cannot copy to materialized view \"%s\"" msgstr "მატერიალიზებულ ხედში კოპირების შეცდომა: %s" -#: commands/copyfrom.c:684 +#: commands/copyfrom.c:834 #, c-format msgid "cannot copy to sequence \"%s\"" msgstr "მიმდევრობაში (%s) კოპირების შეცდომა" -#: commands/copyfrom.c:689 +#: commands/copyfrom.c:839 #, c-format msgid "cannot copy to non-table relation \"%s\"" msgstr "არა-ცხრილოვან ურთიერთობაში კოპირების შეცდომა: %s" -#: commands/copyfrom.c:729 +#: commands/copyfrom.c:879 #, c-format msgid "cannot perform COPY FREEZE on a partitioned table" msgstr "\"COPY FREEZE\"-ის გამოყენება დაყოფილ ცხრილზე შეუძლებელია" -#: commands/copyfrom.c:744 +#: commands/copyfrom.c:886 +#, c-format +msgid "cannot perform COPY FREEZE on a foreign table" +msgstr "\"COPY FREEZE\"-ის გამოყენება გარე ცხრილზე შეუძლებელია" + +#: commands/copyfrom.c:900 #, c-format msgid "cannot perform COPY FREEZE because of prior transaction activity" msgstr "\"COPY FREEZE\"-ის გამოყენება შეუძლებელია წინა ტრანზაქციის აქტივობის გამო" -#: commands/copyfrom.c:750 +#: commands/copyfrom.c:906 #, c-format msgid "cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction" msgstr "'COPY FREEZE'-ის განხორციელება შეუძლებელია, რადგან ცხრილი მიმდინარე ქვეტრანზაქციაში არც შექმნილა და არც მოკვეთილა" -#: commands/copyfrom.c:1313 +#: commands/copyfrom.c:1171 #, c-format -msgid "%llu row was skipped due to data type incompatibility" -msgid_plural "%llu rows were skipped due to data type incompatibility" -msgstr[0] "გამოტოვებულია %llu მწკრივი მონაცემების ტიპის შეუთავსებლობის გამო" -msgstr[1] "გამოტოვებულია %llu მწკრივი მონაცემების ტიპის შეუთავსებლობის გამო" +msgid "skipped more than REJECT_LIMIT (%) rows due to data type incompatibility" +msgstr "გამოტოვებულია REJECT_LIMIT-ზე მეტი (%) მწკრივი მონაცემების ტიპის შეუთავსებლობის გამო" -#: commands/copyfrom.c:1447 +#: commands/copyfrom.c:1474 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "FORCE_NOT_NULL სვეტი \"%s\" COPY-ის მიერ მითითებული არაა" +msgid "% row was skipped due to data type incompatibility" +msgid_plural "% rows were skipped due to data type incompatibility" +msgstr[0] "გამოტოვებულია % მწკრივი მონაცემების ტიპის შეუთავსებლობის გამო" +msgstr[1] "გამოტოვებულია % მწკრივი მონაცემების ტიპის შეუთავსებლობის გამო" -#: commands/copyfrom.c:1489 +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1611 commands/copyfrom.c:1654 commands/copyto.c:881 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "FORCE_NULL სვეტი \"%s\" COPY-ის მიერ მითითებული არაა" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "%s-ის სვეტი \"%s\"-ს COPY არ მიმართავს" -#: commands/copyfrom.c:1542 utils/mb/mbutils.c:385 +#: commands/copyfrom.c:1707 utils/mb/mbutils.c:385 #, c-format msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" msgstr "ნაგულისხმევი გადაყვანის ფუნქცია კოდირებისთვის \"%s\"-დან %s-ზე არ არსებობს" -#: commands/copyfrom.c:1740 +#: commands/copyfrom.c:1882 #, c-format msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy." msgstr "ინსტრუქცია 'COPY TO' PostgreSQL-ის სერვერის პროცესს ფაილიდან წაკითხვას უბრძანებს. შეიძლება გნებავთ კლიენტის მხარე, როგორიცაა psql-ის \\copy." -#: commands/copyfrom.c:1753 commands/copyto.c:701 +#: commands/copyfrom.c:1895 commands/copyto.c:986 #, c-format msgid "\"%s\" is a directory" msgstr "\"%s\" საქაღალდეა" -#: commands/copyfrom.c:1821 commands/copyto.c:299 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1953 commands/copyto.c:572 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "გარე ბრძანებამდე ფაიფის დახურვის შეცდომა: %m" -#: commands/copyfrom.c:1836 commands/copyto.c:304 +#: commands/copyfrom.c:1968 commands/copyto.c:577 #, c-format msgid "program \"%s\" failed" msgstr "პროგრამის (\"%s\") შეცდომა" @@ -7015,665 +7016,665 @@ msgstr "\"COPY\"-ის ფაილის არასწორი თავს msgid "could not read from COPY file: %m" msgstr "\"COPY\" ფაილიდან წაკითხვის შეცდომა: %m" -#: commands/copyfromparse.c:278 commands/copyfromparse.c:303 replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:377 +#: commands/copyfromparse.c:278 commands/copyfromparse.c:303 replication/walsender.c:732 replication/walsender.c:758 tcop/postgres.c:369 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "მოულოდნელი EOF ღია ტრანზაქციის მქონე კლიენტის შეერთებაზე" -#: commands/copyfromparse.c:294 replication/walsender.c:772 +#: commands/copyfromparse.c:294 replication/walsender.c:748 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "stdin-დან COPY ოპერაციისას მიღებულია მოულოდნელი შეტყობინების ტიპი 0x%02X" -#: commands/copyfromparse.c:317 replication/walsender.c:803 +#: commands/copyfromparse.c:317 replication/walsender.c:779 #, c-format msgid "COPY from stdin failed: %s" msgstr "COPY-ი stdin-დან წარუმატებელია: %s" -#: commands/copyfromparse.c:785 +#: commands/copyfromparse.c:802 #, c-format msgid "wrong number of fields in header line: got %d, expected %d" msgstr "ველების არასწორი რაოდენობა თავსართის ხაზში: მივიღე %d, მოველოდი %d" -#: commands/copyfromparse.c:801 +#: commands/copyfromparse.c:818 #, c-format msgid "column name mismatch in header line field %d: got null value (\"%s\"), expected \"%s\"" msgstr "სვეტი სახელი არ ემთხვევა თავსართის %d ხაზის ველზე: მიღებულია ნულოვანი მნიშვნელობა (\"%s\"). მოველოდი: \"%s\"" -#: commands/copyfromparse.c:808 +#: commands/copyfromparse.c:825 #, c-format msgid "column name mismatch in header line field %d: got \"%s\", expected \"%s\"" msgstr "სვეტი სახელი არ ემთხვევა თავსართის %d ხაზის ველზე: მიღებულია მნიშვნელობა: \"%s\". მოველოდი: \"%s\"" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 commands/copyfromparse.c:1810 +#: commands/copyfromparse.c:962 commands/copyfromparse.c:1581 commands/copyfromparse.c:1837 #, c-format msgid "extra data after last expected column" msgstr "დამატებითი მონაცემები ბოლო მოსალოდნელი სვეტის შემდეგ" -#: commands/copyfromparse.c:906 +#: commands/copyfromparse.c:976 #, c-format msgid "missing data for column \"%s\"" msgstr "არ არსებობს მონაცემები სვეტისთვის \"%s\"" -#: commands/copyfromparse.c:990 +#: commands/copyfromparse.c:1056 #, c-format -msgid "skipping row due to data type incompatibility at line %llu for column %s: \"%s\"" +msgid "skipping row due to data type incompatibility at line % for column \"%s\": \"%s\"" msgstr "" -#: commands/copyfromparse.c:998 +#: commands/copyfromparse.c:1064 #, c-format -msgid "skipping row due to data type incompatibility at line %llu for column %s: null input" +msgid "skipping row due to data type incompatibility at line % for column \"%s\": null input" msgstr "" -#: commands/copyfromparse.c:1044 +#: commands/copyfromparse.c:1122 #, c-format msgid "received copy data after EOF marker" msgstr "მიღებულია კოპირების მონაცემები EOF ნიშნის შემდეგ" -#: commands/copyfromparse.c:1051 +#: commands/copyfromparse.c:1129 #, c-format msgid "row field count is %d, expected %d" msgstr "მწკრივების ველის რაოდენობაა %d. ველოდებოდი %d" -#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 +#: commands/copyfromparse.c:1394 commands/copyfromparse.c:1411 #, c-format msgid "literal carriage return found in data" msgstr "მონაცემებში აღმოჩენილია აშკარა ხაზის გადატანის სიმბოლო" -#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 +#: commands/copyfromparse.c:1395 commands/copyfromparse.c:1412 #, c-format msgid "unquoted carriage return found in data" msgstr "მონაცემებში აღმოჩენილია ხაზის გადატანის სიმბოლო ბრჭყალების გარეშე" -#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 +#: commands/copyfromparse.c:1397 commands/copyfromparse.c:1414 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "კარეტის დაბრუნების სიმბოლოსთვის გამოიყენეთ \"\\r\"." -#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 +#: commands/copyfromparse.c:1398 commands/copyfromparse.c:1415 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "CSV-ის ველში კარეტის დაბრუნების სიმბოლოს ბრჭყალებში ჩასმა." -#: commands/copyfromparse.c:1369 +#: commands/copyfromparse.c:1427 #, c-format msgid "literal newline found in data" msgstr "მონაცემებში აღმოჩენილია ხაზის გადატანის სიმბოლო" -#: commands/copyfromparse.c:1370 +#: commands/copyfromparse.c:1428 #, c-format msgid "unquoted newline found in data" msgstr "მონაცემებში აღმოჩენილია ხაზის გადატანის სიმბოლო ბრჭყალების გარეშე" -#: commands/copyfromparse.c:1372 +#: commands/copyfromparse.c:1430 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "ახალი ხაზს წარმოსადგენად გამოიყენეთ \"\\n\"." -#: commands/copyfromparse.c:1373 +#: commands/copyfromparse.c:1431 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "CSV-ის ველში ახალი ხაზის სიმბოლოს ბრჭყალებში ჩასმა." -#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 +#: commands/copyfromparse.c:1469 commands/copyfromparse.c:1491 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "კოპირების-დასასრულის მარკერი წინა ახალი ხაზის სტილს არ ემთხვევა" -#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 +#: commands/copyfromparse.c:1473 commands/copyfromparse.c:1484 commands/copyfromparse.c:1500 #, c-format -msgid "end-of-copy marker corrupt" -msgstr "კოპირების-დასასრულის სანიშნი დაზიანებულია" +msgid "end-of-copy marker is not alone on its line" +msgstr "კოპირების-დასასრულის მარკერი მის ხაზზე მარტო არაა" -#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 +#: commands/copyfromparse.c:1773 commands/copyfromparse.c:1988 #, c-format msgid "unexpected default marker in COPY data" msgstr "მოულოდნელი ნაგულისხმევი მარკერი COPY-ის მონაცემებში" -#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 +#: commands/copyfromparse.c:1774 commands/copyfromparse.c:1989 #, c-format msgid "Column \"%s\" has no default value." msgstr "სვეტს \"%s\" DEFAULT მნიშვნელობა არ გააჩნია." -#: commands/copyfromparse.c:1894 +#: commands/copyfromparse.c:1921 #, c-format msgid "unterminated CSV quoted field" msgstr "\"CSV\"-ის ველის დამხურავი ბრჭყალი არ არსებობს" -#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 +#: commands/copyfromparse.c:2023 commands/copyfromparse.c:2042 #, c-format msgid "unexpected EOF in COPY data" msgstr "\"COPY\"-ის მონაცემებში ნაპოვნია მოულოდნელი EOF" -#: commands/copyfromparse.c:2005 +#: commands/copyfromparse.c:2032 #, c-format msgid "invalid field size" msgstr "ველის არასწორი ზომა" -#: commands/copyfromparse.c:2028 +#: commands/copyfromparse.c:2055 #, c-format msgid "incorrect binary data format" msgstr "ბინარულ მონაცემების არასწორი ფორმატი" -#: commands/copyto.c:229 +#: commands/copyto.c:477 #, c-format msgid "could not write to COPY program: %m" msgstr "\"COPY\"-ის პროგრამაში ჩაწერის შეცდომა: %m" -#: commands/copyto.c:234 +#: commands/copyto.c:482 #, c-format msgid "could not write to COPY file: %m" msgstr "\"COPY\"-ის ფაილში ჩაწერის შეცდომა: %m" -#: commands/copyto.c:379 +#: commands/copyto.c:652 #, c-format msgid "cannot copy from view \"%s\"" msgstr "ხედიდან კოპირების შეცდომა: \"%s\"" -#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 commands/copyto.c:404 +#: commands/copyto.c:654 commands/copyto.c:669 commands/copyto.c:680 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "სცადეთ COPY (SELECT ...) TO ვარიანტი." -#: commands/copyto.c:385 +#: commands/copyto.c:660 +#, c-format +msgid "cannot copy from unpopulated materialized view \"%s\"" +msgstr "არაშევსებული მატერიალიზებული ხედიდან კოპირების შეცდომა: %s" + +#: commands/copyto.c:662 executor/execUtils.c:761 #, c-format -msgid "cannot copy from materialized view \"%s\"" -msgstr "მატერიალიზებული ხედიდან კოპირების შეცდომა: %s" +msgid "Use the REFRESH MATERIALIZED VIEW command." +msgstr "გამოიყენეთ ბრძანება REFRESH MATERIALIZED VIEW." -#: commands/copyto.c:391 +#: commands/copyto.c:667 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "გარე ცხრილიდან კოპირების შეცდომა: %s" -#: commands/copyto.c:397 +#: commands/copyto.c:673 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "მიმდევრობიდან კოპირების შეცდომა: %s" -#: commands/copyto.c:402 +#: commands/copyto.c:678 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "დაყოფილი ცხრილიდან კოპირების შეცდომა: %s" -#: commands/copyto.c:408 +#: commands/copyto.c:684 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "არა-ცხრილოვანი ურთიერთობიდან კოპირების შეცდომა: %s" -#: commands/copyto.c:460 +#: commands/copyto.c:739 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "DO INSTEAD NOTHING -ის წესები COPY-სთვის მხარდაუჭერელია" -#: commands/copyto.c:474 +#: commands/copyto.c:753 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "\"DO INSTEAD\" -ის პირობითი წესები COPY-სთვის მხარდაუჭერელია" -#: commands/copyto.c:478 +#: commands/copyto.c:757 #, c-format -msgid "DO ALSO rules are not supported for the COPY" -msgstr "DO ALSO -ის წესები COPY-სთვის მხარდაუჭერელია" +msgid "DO ALSO rules are not supported for COPY" +msgstr "DO ALSO -ის წესები COPY-სთვის მხარდაჭერილი არაა" -#: commands/copyto.c:483 +#: commands/copyto.c:762 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "ერთზე მეტი გამოსახულების მქონე DO INSTEAD-ის წესები COPY-ისთვის მხარდაუჭერელია" -#: commands/copyto.c:493 +#: commands/copyto.c:772 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO) მხარდაუჭერელია" -#: commands/copyto.c:511 +#: commands/copyto.c:778 +#, c-format +msgid "COPY query must not be a utility command" +msgstr "" + +#: commands/copyto.c:794 #, c-format msgid "COPY query must have a RETURNING clause" msgstr "COPY მოთხოვნას RETURNING პირობა აუცილებლად უნდა გააჩნდეს" -#: commands/copyto.c:540 +#: commands/copyto.c:823 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "" -#: commands/copyto.c:596 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "FORCE_QUOTE სვეტი \"%s\" COPY-ის მიერ მითითებული არაა" - -#: commands/copyto.c:666 +#: commands/copyto.c:951 #, c-format msgid "relative path not allowed for COPY to file" msgstr "ფაილში COPY-სთვის შედარებითი ბილიკის მითითება დაუშვებელია" -#: commands/copyto.c:685 +#: commands/copyto.c:970 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "ფაილის (\"%s\") ჩასაწერად გახსნა შეუძლებელია: %m" -#: commands/copyto.c:688 +#: commands/copyto.c:973 #, c-format msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy." msgstr "ინსტრუქცია 'COPY TO' PostgreSQL-ის სერვერის პროცესს ფაილში ჩაწერას უბრძანებს. შეიძლება გნებავთ კლიენტის მხარე, როგორიცაა psql-ის \\copy." -#: commands/createas.c:210 commands/createas.c:518 +#: commands/createas.c:212 commands/createas.c:524 #, c-format msgid "too many column names were specified" msgstr "მითითებულია მეტისმეტად ბევრი სვეტის სახელი" -#: commands/createas.c:541 +#: commands/createas.c:547 #, c-format msgid "policies not yet implemented for this command" msgstr "ამ ბრძანებისთვის წესები ჯერ არ არსებობს" -#: commands/dbcommands.c:829 +#: commands/dbcommands.c:843 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATION მხარდაჭერილი აღარაა" -#: commands/dbcommands.c:830 +#: commands/dbcommands.c:844 #, c-format msgid "Consider using tablespaces instead." msgstr "მის მაგიერ სჯობს ცხრილის სივრცეები გამოიყენოთ." -#: commands/dbcommands.c:855 +#: commands/dbcommands.c:869 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "%u-ზე მცირე OID-ები დაცულია სისტემური ობიექტებისთვის" -#: commands/dbcommands.c:886 utils/adt/ascii.c:146 +#: commands/dbcommands.c:900 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "\"%d\" კოდირების სწორ კოდს არ წარმოადგენს" -#: commands/dbcommands.c:897 utils/adt/ascii.c:128 +#: commands/dbcommands.c:911 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "\"%s\" კოდირების სწორ სახელს არ წარმოადგენს" -#: commands/dbcommands.c:931 +#: commands/dbcommands.c:945 #, c-format msgid "unrecognized locale provider: %s" msgstr "ენის უცნობი მომწოდებელი: %s" -#: commands/dbcommands.c:944 commands/dbcommands.c:2402 commands/user.c:299 commands/user.c:739 +#: commands/dbcommands.c:958 commands/dbcommands.c:2428 commands/user.c:300 commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "კავშირის არასწორი ლიმიტი: %d" -#: commands/dbcommands.c:965 +#: commands/dbcommands.c:979 #, c-format msgid "permission denied to create database" msgstr "ბაზის შექმნის წვდომა აკრძალულია" -#: commands/dbcommands.c:989 +#: commands/dbcommands.c:1003 #, c-format msgid "template database \"%s\" does not exist" msgstr "შაბლონური ბაზა \"%s\" არ არსებობს" -#: commands/dbcommands.c:999 +#: commands/dbcommands.c:1013 #, c-format msgid "cannot use invalid database \"%s\" as template" msgstr "არასწორი მონაცემთა ბაზის \"%s\" შაბლონად გამოყენება შეუძლებელია" -#: commands/dbcommands.c:1000 commands/dbcommands.c:2431 utils/init/postinit.c:1112 +#: commands/dbcommands.c:1014 commands/dbcommands.c:2458 utils/init/postinit.c:1106 #, c-format msgid "Use DROP DATABASE to drop invalid databases." msgstr "არასწორი მონაცემთა ბაზების წასაშლელად გამოიყენეთ ბრძანება DROP DATABASE." -#: commands/dbcommands.c:1011 +#: commands/dbcommands.c:1025 #, c-format msgid "permission denied to copy database \"%s\"" msgstr "ბაზის (\"%s\") კოპირების წვდომა აკრძალულია" -#: commands/dbcommands.c:1028 +#: commands/dbcommands.c:1042 #, c-format msgid "invalid create database strategy \"%s\"" msgstr "ბაზის შექმნის არასწორი სტრატეგია \"%s\"" -#: commands/dbcommands.c:1029 +#: commands/dbcommands.c:1043 #, c-format msgid "Valid strategies are \"wal_log\" and \"file_copy\"." msgstr "სწორი სტრატეგიებია \"wal_log\" და \"file_copy\"." -#: commands/dbcommands.c:1050 +#: commands/dbcommands.c:1064 #, c-format msgid "invalid server encoding %d" msgstr "სერვერის არასწორი კოდირება %d" -#: commands/dbcommands.c:1056 +#: commands/dbcommands.c:1070 #, c-format msgid "invalid LC_COLLATE locale name: \"%s\"" msgstr "არასწორი LC_COLLATE ლოკალის სახელი: \"%s\"" -#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 +#: commands/dbcommands.c:1071 commands/dbcommands.c:1077 #, c-format msgid "If the locale name is specific to ICU, use ICU_LOCALE." msgstr "თუ ლოკალის სახელი მხოლოდ ICU-სთვისა დამახასიათებელი, ICU_LOCALE გამოიყენეთ." -#: commands/dbcommands.c:1062 +#: commands/dbcommands.c:1076 #, c-format msgid "invalid LC_CTYPE locale name: \"%s\"" msgstr "არასწორი LC_TYPE ლოკალის სახელი: \"%s\"" -#: commands/dbcommands.c:1074 +#: commands/dbcommands.c:1088 #, c-format msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" msgstr "BUILTIN_LOCALE-ის მითითება შეუძლებელია, სანამ ლოკალის მომწოდებელი builtin არაა" -#: commands/dbcommands.c:1082 +#: commands/dbcommands.c:1096 #, c-format msgid "ICU locale cannot be specified unless locale provider is ICU" msgstr "ICU-ის ენის მითითება მანამდე, სანამ ლოკალის მომწოდებელი ICU არაა, შეუძლებელია" -#: commands/dbcommands.c:1100 +#: commands/dbcommands.c:1114 #, c-format msgid "LOCALE or BUILTIN_LOCALE must be specified" msgstr "LOCALE-ის ან BUILTIN_LOCALE-ის მითითება აუცილებელია" -#: commands/dbcommands.c:1109 +#: commands/dbcommands.c:1123 #, c-format msgid "encoding \"%s\" is not supported with ICU provider" msgstr "მონაცემთა ბაზის კოდირება \"%s\" ICU მომწოდებელთან ერთად მხარდაჭერილი არაა" -#: commands/dbcommands.c:1119 +#: commands/dbcommands.c:1133 #, c-format msgid "LOCALE or ICU_LOCALE must be specified" msgstr "LOCALE-ის ან ICU_LOCALE-ის მითითება აუცილებელია" -#: commands/dbcommands.c:1163 +#: commands/dbcommands.c:1177 #, c-format msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)" msgstr "ახალი კოდირება (%s) შაბლონის ბაზის (%s) კოდირებასთან თავსებადი არაა" -#: commands/dbcommands.c:1166 +#: commands/dbcommands.c:1180 #, c-format msgid "Use the same encoding as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე კოდირება, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1171 +#: commands/dbcommands.c:1185 #, c-format msgid "new collation (%s) is incompatible with the collation of the template database (%s)" msgstr "ახალი კოლაცია (%s) შაბლონის ბაზის (%s) კოლაციასთან თავსებადი არაა" -#: commands/dbcommands.c:1173 +#: commands/dbcommands.c:1187 #, c-format msgid "Use the same collation as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე კოლაცია, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1178 +#: commands/dbcommands.c:1192 #, c-format msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)" msgstr "ახალი LC_TYPE (%s) შაბლონის ბაზის (%s) LC_TYPE-სთან თავსებადი არაა" -#: commands/dbcommands.c:1180 +#: commands/dbcommands.c:1194 #, c-format msgid "Use the same LC_CTYPE as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე LC_CTYPE, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1185 +#: commands/dbcommands.c:1199 #, c-format msgid "new locale provider (%s) does not match locale provider of the template database (%s)" msgstr "ახალი ლოკალის მომწოდებელი (%s) შაბლონის ბაზის (%s) ლოკალის მომწოდებელს არ ემთხვევა" -#: commands/dbcommands.c:1187 +#: commands/dbcommands.c:1201 #, c-format msgid "Use the same locale provider as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე ლოკალის მომწოდებელი, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1199 +#: commands/dbcommands.c:1213 #, c-format msgid "new ICU locale (%s) is incompatible with the ICU locale of the template database (%s)" msgstr "ახალი ICU ლოკალი (%s) შაბლონის ბაზის (%s) ICU ლოკალთან თავსებადი არაა" -#: commands/dbcommands.c:1201 +#: commands/dbcommands.c:1215 #, c-format msgid "Use the same ICU locale as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე ICU ლოკალი, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1212 +#: commands/dbcommands.c:1226 #, c-format msgid "new ICU collation rules (%s) are incompatible with the ICU collation rules of the template database (%s)" msgstr "ახალი ICU კოლაციის წესები (%s) შაბლონის ბაზის (%s) ICU კოლაციის წესებთან თავსებადი არაა" -#: commands/dbcommands.c:1214 +#: commands/dbcommands.c:1228 #, c-format msgid "Use the same ICU collation rules as in the template database, or use template0 as template." msgstr "გამოიყენეთ იგივე ICU კოლაციის წესები, რაც შაბლონის ბაზას გააჩნია, ან შაბლონად template0 გამოიყენეთ." -#: commands/dbcommands.c:1243 +#: commands/dbcommands.c:1257 #, c-format msgid "template database \"%s\" has a collation version, but no actual collation version could be determined" msgstr "შაბლონის ბაზას \"%s\" კოლაცია გააჩნია, მაგრამ ნამდვილი კოლაციის ვერსიის დადგენა შეუძლებელია" -#: commands/dbcommands.c:1248 +#: commands/dbcommands.c:1262 #, c-format msgid "template database \"%s\" has a collation version mismatch" msgstr "შაბლონული ბაზის (%s) კოლაციის ვერსია არ ემთხვევა" -#: commands/dbcommands.c:1250 +#: commands/dbcommands.c:1264 #, c-format msgid "The template database was created using collation version %s, but the operating system provides version %s." msgstr "ნიმუში ბაზა შეიქმნა კოლაციის ვერსიით %s, მაგრამ ოპერაციული სისტემის ვერსიაა %s." -#: commands/dbcommands.c:1253 +#: commands/dbcommands.c:1267 #, c-format msgid "Rebuild all objects in the template database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "სანიმუშე ბაზაში ყველა ობიექტი, რომლებიც ნაგულისხმევ კოლაციას იყენებს, თავიან ააგეთ და გაუშვით ALTER DATABASE %s REFRESH COLLATION VERSION, ან PostgreSQL სწორი ბიბლიოთეკის ვერსიით ააგეთ." -#: commands/dbcommands.c:1298 commands/dbcommands.c:2031 +#: commands/dbcommands.c:1312 commands/dbcommands.c:2055 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "pg_global არ შეიძლება გამოყენებულ იქნას როგორც ნაგულისხმევი ცხრილის სივრცე" -#: commands/dbcommands.c:1324 +#: commands/dbcommands.c:1338 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "ცხრილების ახალი ნაგულისხმევი სივრცის \"%s\" მინიჭება შეუძლებელია" -#: commands/dbcommands.c:1326 +#: commands/dbcommands.c:1340 #, c-format msgid "There is a conflict because database \"%s\" already has some tables in this tablespace." msgstr "არსებობს კონფლიქტი, რადგან მონაცემთა ბაზას \"%s\" ამ ცხრილების სივრცეში ცხრილები უკვე გააჩნია." -#: commands/dbcommands.c:1356 commands/dbcommands.c:1904 +#: commands/dbcommands.c:1370 commands/dbcommands.c:1926 #, c-format msgid "database \"%s\" already exists" msgstr "ბაზა \"%s\" უკვე არსებობს" -#: commands/dbcommands.c:1370 +#: commands/dbcommands.c:1384 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "საწყის ბაზა %s-სთან ამჟამად სხვა მომხმარებლებიცაა მიერთებული" -#: commands/dbcommands.c:1392 +#: commands/dbcommands.c:1406 #, c-format msgid "database OID %u is already in use by database \"%s\"" msgstr "ბაზის OID %u უკვე გამოიყენება ბაზის \"%s\" მიერ" -#: commands/dbcommands.c:1398 +#: commands/dbcommands.c:1412 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "მონაცემების საქაღალდე მითითებული OID-ით (%u) უკვე არსებობს" -#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 utils/adt/pg_locale.c:2565 +#: commands/dbcommands.c:1585 commands/dbcommands.c:1600 utils/adt/pg_locale.c:1517 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "კოდირება (%s) ენას (%s) არ ემთხვევა" -#: commands/dbcommands.c:1574 +#: commands/dbcommands.c:1588 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "\"LC_CTYPE\"-ის არჩეულ პარამეტრს სჭირდება კოდირება: \"%s\"." -#: commands/dbcommands.c:1589 +#: commands/dbcommands.c:1603 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "\"LC_COLLATE\"-ის არჩეულ პარამეტრს სჭირდება კოდირება: \"%s\"." -#: commands/dbcommands.c:1670 +#: commands/dbcommands.c:1686 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "მონაცემთა ბაზა \"%s\" არ არსებობს, გამოტოვება" -#: commands/dbcommands.c:1694 +#: commands/dbcommands.c:1710 #, c-format msgid "cannot drop a template database" msgstr "შაბლონური ბაზის წაშლა შეუძლებელია" -#: commands/dbcommands.c:1700 +#: commands/dbcommands.c:1716 #, c-format msgid "cannot drop the currently open database" msgstr "ღია ბაზის წაშლა შეუძლებელია" -#: commands/dbcommands.c:1713 +#: commands/dbcommands.c:1729 #, c-format msgid "database \"%s\" is used by an active logical replication slot" msgstr "ბაზა %s აქტიური ლოგიკური რეპლიკაციის სლოტის მიერ გამოიყენება" -#: commands/dbcommands.c:1715 +#: commands/dbcommands.c:1731 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." msgstr[0] "ხელმისაწვდომია %d აქტიური სლოტი." msgstr[1] "ხელმისაწვდომია %d აქტიური სლოტი." -#: commands/dbcommands.c:1729 +#: commands/dbcommands.c:1745 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "ბაზა %s ლოგიკური რეპლიკაციის გამოწერის მიერ გამოიყენება" -#: commands/dbcommands.c:1731 +#: commands/dbcommands.c:1747 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." msgstr[0] "აღმოჩენილია %d გამოწერა." msgstr[1] "აღმოჩენილია %d გამოწერა." -#: commands/dbcommands.c:1752 commands/dbcommands.c:1926 commands/dbcommands.c:2053 +#: commands/dbcommands.c:1768 commands/dbcommands.c:1948 commands/dbcommands.c:2077 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "ბაზა %s-სთან ამჟამად სხვა მომხმარებლებიცაა მიერთებული" -#: commands/dbcommands.c:1886 +#: commands/dbcommands.c:1908 #, c-format msgid "permission denied to rename database" msgstr "ბაზის სახელის გადარქმევის წვდომა აკრძალულია" -#: commands/dbcommands.c:1915 +#: commands/dbcommands.c:1937 #, c-format msgid "current database cannot be renamed" msgstr "მიმდინარე ბაზის სახელის გადარქმევა შეუძლებელია" -#: commands/dbcommands.c:2009 +#: commands/dbcommands.c:2033 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "ღია ბაზის ცხრილების სივრცის შეცვლა შეუძლებელია" -#: commands/dbcommands.c:2115 +#: commands/dbcommands.c:2139 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "ბაზის (%s) ზოგიერთი ურთიერთობა ცხრილების სივრცეში \"%s\" უკვე იმყოფება" -#: commands/dbcommands.c:2117 +#: commands/dbcommands.c:2141 #, c-format msgid "You must move them back to the database's default tablespace before using this command." msgstr "ამ ბრძანების გამოყენებამდე ბაზის ნაგულისხმევ ცხრილების სივრცეში უნდა დაბრუნდეთ." -#: commands/dbcommands.c:2244 commands/dbcommands.c:2979 commands/dbcommands.c:3279 commands/dbcommands.c:3392 +#: commands/dbcommands.c:2270 commands/dbcommands.c:3013 commands/dbcommands.c:3313 commands/dbcommands.c:3426 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "ძველი ბაზის საქაღალდეში \"%s\" შეიძლება რამდენიმე გამოუსადეგარი ფაილი დარჩა" -#: commands/dbcommands.c:2305 +#: commands/dbcommands.c:2331 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "\"DROP DATABASE\"-ის უცნობი პარამეტრი \"%s\"" -#: commands/dbcommands.c:2383 +#: commands/dbcommands.c:2409 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "პარამეტრის \"%s\" მითითება სხვა პარამეტრებთან ერთად აკრძალულია" -#: commands/dbcommands.c:2430 +#: commands/dbcommands.c:2457 #, c-format msgid "cannot alter invalid database \"%s\"" msgstr "არასწორი ბაზის (\"%s\") შეცვლა შეუძლებელია" -#: commands/dbcommands.c:2447 +#: commands/dbcommands.c:2474 #, c-format msgid "cannot disallow connections for current database" msgstr "მიმდინარე ბაზასთან დაკავშირების უარყოფა შეუძლებელია" -#: commands/dbcommands.c:2673 +#: commands/dbcommands.c:2704 #, c-format msgid "permission denied to change owner of database" msgstr "ბაზის მფლობელის შეცვლის წვდომა აკრძალულია" -#: commands/dbcommands.c:3085 +#: commands/dbcommands.c:3119 #, c-format msgid "There are %d other session(s) and %d prepared transaction(s) using the database." msgstr "ამ ბაზას %d სხვა სესია და %d მომზადებული ტრანზაქცია იყენებს." -#: commands/dbcommands.c:3088 +#: commands/dbcommands.c:3122 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." msgstr[0] "%d სხვა სესია, რომელიც ბაზას იყენებს." msgstr[1] "%d სხვა სესია, რომელიც ბაზას იყენებს." -#: commands/dbcommands.c:3093 storage/ipc/procarray.c:3847 +#: commands/dbcommands.c:3127 storage/ipc/procarray.c:3860 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." msgstr[0] "ბაზას %d მომზადებული ტრანზაქცია იყენებს." msgstr[1] "ბაზას %d მომზადებული ტრანზაქცია იყენებს." -#: commands/dbcommands.c:3235 +#: commands/dbcommands.c:3269 #, c-format msgid "missing directory \"%s\"" msgstr "ნაკლული საქაღალდე \"%s\"" -#: commands/dbcommands.c:3293 commands/tablespace.c:184 commands/tablespace.c:633 +#: commands/dbcommands.c:3327 commands/tablespace.c:184 commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "საქაღალდის \"%s\" პოვნა შეუძლებელია: %m" -#: commands/define.c:53 commands/define.c:257 commands/define.c:289 commands/define.c:317 commands/define.c:363 +#: commands/define.c:40 commands/define.c:244 commands/define.c:276 commands/define.c:304 commands/define.c:350 #, c-format msgid "%s requires a parameter" msgstr "%s მოითხოვს პარამეტრს" -#: commands/define.c:86 commands/define.c:97 commands/define.c:191 commands/define.c:209 commands/define.c:224 commands/define.c:242 -#, c-format -msgid "%s requires a numeric value" -msgstr "%s მოითხოვს რიცხვით მნიშვნელობას" - -#: commands/define.c:153 +#: commands/define.c:140 #, c-format msgid "%s requires a Boolean value" msgstr "%s მოითხოვს ლოგიკურ მნიშვნელობას" -#: commands/define.c:167 commands/define.c:176 commands/define.c:326 +#: commands/define.c:154 commands/define.c:163 commands/define.c:313 #, c-format msgid "%s requires an integer value" msgstr "%s-ის მნიშვნელობა მთელი რიცხვი უნდა იყოს" -#: commands/define.c:271 +#: commands/define.c:258 #, c-format msgid "argument of %s must be a name" msgstr "%s-ის არგუმენტი სახელი უნდა იყოს" -#: commands/define.c:301 +#: commands/define.c:288 #, c-format msgid "argument of %s must be a type name" msgstr "%s-ის არგუმენტი ტიპის სახელი უნდა იყოს" -#: commands/define.c:347 +#: commands/define.c:334 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "%s-ის არასწორი არგუმენტი: \"%s\"" -#: commands/dropcmds.c:96 commands/functioncmds.c:1382 utils/adt/ruleutils.c:2909 +#: commands/dropcmds.c:96 commands/functioncmds.c:1400 utils/adt/ruleutils.c:2956 #, c-format msgid "\"%s\" is an aggregate function" msgstr "\"%s\" აგრეგატული ფუნქციაა" @@ -7683,17 +7684,17 @@ msgstr "\"%s\" აგრეგატული ფუნქციაა" msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "აგრეგირებული ფუნქციების წასაშლელად გამოიყენეთ DROP AGGREGATE." -#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3865 commands/tablecmds.c:4023 commands/tablecmds.c:4075 commands/tablecmds.c:17061 tcop/utility.c:1325 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:4014 commands/tablecmds.c:4175 commands/tablecmds.c:4227 commands/tablecmds.c:18887 tcop/utility.c:1328 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "ურთიერთობა \"%s\" არ არსებობს, გამოტოვებს" -#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1397 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1469 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "სქემა \"%s\" არ არსებობს, გამოტოვება" -#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:289 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "ტიპი \"%s\" არ არსებობს, გამოტოვება" @@ -7713,7 +7714,7 @@ msgstr "კოლაცია \"%s\" არ არსებობს, გამ msgid "conversion \"%s\" does not exist, skipping" msgstr "გადაყვანა\"%s\" არ არსებობს, გამოტოვება" -#: commands/dropcmds.c:288 commands/statscmds.c:664 +#: commands/dropcmds.c:288 commands/statscmds.c:682 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "სტატისტიკის ობიექტი \"%s\" არ არსებობს, გამოტოვება" @@ -7869,347 +7870,347 @@ msgstr "მოვლენის ტრიგერები %s-ისთვი msgid "filter variable \"%s\" specified more than once" msgstr "ფილტრის ცვლადი ერთზე მეტჯერაა მითითებული: %s" -#: commands/event_trigger.c:435 commands/event_trigger.c:487 commands/event_trigger.c:581 +#: commands/event_trigger.c:438 commands/event_trigger.c:490 commands/event_trigger.c:584 #, c-format msgid "event trigger \"%s\" does not exist" msgstr "მოვლენის ტრიგერი არ არსებობს: \"%s\"" -#: commands/event_trigger.c:519 +#: commands/event_trigger.c:522 #, c-format msgid "event trigger with OID %u does not exist" msgstr "მოვლენის ტრიგერი OID-ით %u არ არსებობს" -#: commands/event_trigger.c:549 +#: commands/event_trigger.c:552 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" msgstr "მოვლენის ტრიგერის მფლობელის შეცვლის წვდომა აკრძალულია: %s" -#: commands/event_trigger.c:551 +#: commands/event_trigger.c:554 #, c-format msgid "The owner of an event trigger must be a superuser." msgstr "მოვლენის ტრიგერის მფლობელი ზემომხმარებელი უნდა იყოს." -#: commands/event_trigger.c:1411 +#: commands/event_trigger.c:1404 #, c-format msgid "%s can only be called in a sql_drop event trigger function" msgstr "%s-ის გამოძახება sql_drop მოვლენის ტრიგერიდან შეგიძლიათ" -#: commands/event_trigger.c:1504 commands/event_trigger.c:1525 +#: commands/event_trigger.c:1497 commands/event_trigger.c:1518 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" msgstr "%s-ის გამოძახება table_rewrite მოვლენის ტრიგერიდან შეგიძლიათ" -#: commands/event_trigger.c:1938 +#: commands/event_trigger.c:1931 #, c-format msgid "%s can only be called in an event trigger function" msgstr "%s-ის გამოძახება მხოლოდ მოვლენის ტრიგერის ფუნქციიდან შეგიძლიათ" -#: commands/explain.c:240 commands/explain.c:265 +#: commands/explain_state.c:133 commands/explain_state.c:158 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "\"EXPLAIN\"-ის უცნობი პარამეტრი \"%s\": \"%s\"" -#: commands/explain.c:272 +#: commands/explain_state.c:165 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "\"EXPLAIN\"-ის უცნობი პარამეტრი \"%s\"" -#: commands/explain.c:281 -#, c-format -msgid "EXPLAIN option WAL requires ANALYZE" -msgstr "EXPLAIN -ის პარამეტრ WAL-ს ANALYZE სჭირდება" - -#: commands/explain.c:290 +#: commands/explain_state.c:174 commands/explain_state.c:186 commands/explain_state.c:192 #, c-format -msgid "EXPLAIN option TIMING requires ANALYZE" -msgstr "EXPLAIN -ის პარამეტრ TIMING-ს ANALYZE სჭირდება" +msgid "EXPLAIN option %s requires ANALYZE" +msgstr "EXPLAIN -ის პარამეტრს %s ANALYZE სჭირდება" -#: commands/explain.c:296 -#, c-format -msgid "EXPLAIN option SERIALIZE requires ANALYZE" -msgstr "EXPLAIN-ის პარამეტრს SERIALIZE 'ANALYZE' სჭირდება" - -#: commands/explain.c:302 +#: commands/explain_state.c:198 #, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" msgstr "EXPLAIN-ის პარამეტრები ANALYZE და GENERIC_PLAN ერთად არ შეიძლება, გამოიყენოთ" -#: commands/extension.c:178 commands/extension.c:3031 +#: commands/extension.c:174 commands/extension.c:3299 #, c-format msgid "extension \"%s\" does not exist" msgstr "გაფართოება %s არ არსებობს" -#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 commands/extension.c:308 +#: commands/extension.c:239 commands/extension.c:248 commands/extension.c:260 commands/extension.c:270 #, c-format msgid "invalid extension name: \"%s\"" msgstr "გაფართოების არასწორი სახელი: \"%s\"" -#: commands/extension.c:278 +#: commands/extension.c:240 #, c-format msgid "Extension names must not be empty." msgstr "გაფართოების სახელები ცარიელი არ უნდა იყოს." -#: commands/extension.c:287 +#: commands/extension.c:249 #, c-format msgid "Extension names must not contain \"--\"." msgstr "გაფართოების სახელები არ უნდა შეიცავდეს \"---\"." -#: commands/extension.c:299 +#: commands/extension.c:261 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "გაფართოების სახელები არ უნდა დაიწყოს ან დასრულდეს \"-\"." -#: commands/extension.c:309 +#: commands/extension.c:271 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "გაფართოების სახელები არ უნდა შეიცავდეს საქაღალდის გამყოფი სიმბოლოს." -#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 commands/extension.c:352 +#: commands/extension.c:286 commands/extension.c:295 commands/extension.c:304 commands/extension.c:314 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "გაფართოების არასწორი ვერსია: \"%s\"" -#: commands/extension.c:325 +#: commands/extension.c:287 #, c-format msgid "Version names must not be empty." msgstr "ვერსიის სახელები არ უნდა იყოს ცარიელი." -#: commands/extension.c:334 +#: commands/extension.c:296 #, c-format msgid "Version names must not contain \"--\"." msgstr "ვერსიის სახელები არ უნდა შეიცავდეს \"---\"." -#: commands/extension.c:343 +#: commands/extension.c:305 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "ვერსიის სახელები არ უნდა დაიწყოს ან დასრულდეს \"-\"." -#: commands/extension.c:353 +#: commands/extension.c:315 #, c-format msgid "Version names must not contain directory separator characters." msgstr "ვერსიის სახელები არ უნდა შეიცავდეს საქაღალდის გამყოფ სიმბოლოებს." -#: commands/extension.c:507 +#: commands/extension.c:549 #, c-format msgid "extension \"%s\" is not available" msgstr "გაფართოება \"%s\" ხელმიუწვდომელია" -#: commands/extension.c:508 -#, c-format -msgid "Could not open extension control file \"%s\": %m." -msgstr "გაფართოების კონტროლის ფაილის (\"%s\") გახსნის შეცდომა: %m." - -#: commands/extension.c:510 +#: commands/extension.c:550 #, c-format msgid "The extension must first be installed on the system where PostgreSQL is running." msgstr "ჯერ გაფართოება უნდა დააყენოთ სისტემაზე, სადაც PostgreSQL-ია გაშვებული." -#: commands/extension.c:514 +#: commands/extension.c:564 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "გაფართოების კონტროლის ფაილის (\"%s\") გახსნის შეცდომა: %m" -#: commands/extension.c:537 commands/extension.c:547 +#: commands/extension.c:587 commands/extension.c:597 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "პარამეტრს \"%s\" მეორადი გაფართოების კონტროლის ფაილში ვერ დააყენებთ" -#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 utils/misc/guc.c:3147 +#: commands/extension.c:619 commands/extension.c:627 commands/extension.c:635 utils/misc/guc.c:3144 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "პარამეტრს %s ლოგიკური მნიშვნელობა სჭირდება" -#: commands/extension.c:594 +#: commands/extension.c:644 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" კოდირების სწორ სახელს არ წარმოადგენს" -#: commands/extension.c:608 commands/extension.c:623 +#: commands/extension.c:658 commands/extension.c:673 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "პარამეტრი \"%s\" გაფართოებების სახელების სიას უნდა შეიცავდეს" -#: commands/extension.c:630 +#: commands/extension.c:680 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "უცნობი პარამეტრი \"%s\" ფაილში \"%s\"" -#: commands/extension.c:639 +#: commands/extension.c:689 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "როცა \"relocatable\" ჭეშმარიტია, პარამეტრს \"schema\" ვერ მიუთითებთ" -#: commands/extension.c:817 +#: commands/extension.c:865 +#, c-format +msgid "SQL statement \"%.*s\"" +msgstr "SQL ოპერატორი \"%.*s\"" + +#: commands/extension.c:894 +#, c-format +msgid "extension script file \"%s\", near line %d" +msgstr "გაფართოების სკრიპტის ფაილი \"%s\" ხაზთან %d" + +#: commands/extension.c:898 +#, c-format +msgid "extension script file \"%s\"" +msgstr "გაფართოების სკრიპტის ფაილი \"%s\"" + +#: commands/extension.c:1012 #, c-format msgid "transaction control statements are not allowed within an extension script" msgstr "გაფართოების სკრიპტში ტრანზაქციის კონტროლის გამოსახულებები დაშვებული არაა" -#: commands/extension.c:897 +#: commands/extension.c:1094 #, c-format msgid "permission denied to create extension \"%s\"" msgstr "გაფართოების (\"%s\") შექმნის წვდომა აკრძალულა" -#: commands/extension.c:900 +#: commands/extension.c:1097 #, c-format msgid "Must have CREATE privilege on current database to create this extension." msgstr "ამ გაფართოების შესაქმნელად აუცილებელია მიმდინარე ბაზაზე პრივილეგია CREATE-ის ქონა." -#: commands/extension.c:901 +#: commands/extension.c:1098 #, c-format msgid "Must be superuser to create this extension." msgstr "გაფართოების შესაქმნელად საჭიროა ზემომხმარებლის უფლებები." -#: commands/extension.c:905 +#: commands/extension.c:1102 #, c-format msgid "permission denied to update extension \"%s\"" msgstr "გაფართოების (\"%s\") განახლების წვდომა აკრძალულია" -#: commands/extension.c:908 +#: commands/extension.c:1105 #, c-format msgid "Must have CREATE privilege on current database to update this extension." msgstr "ამ გაფართოების განახლებისთვის აუცილებელია მიმდინარე ბაზაზე პრივილეგია CREATE-ის ქონა." -#: commands/extension.c:909 +#: commands/extension.c:1106 #, c-format msgid "Must be superuser to update this extension." msgstr "გაფართოების გასაახლებლად საჭიროა ზემომხმარებლის უფლებები." -#: commands/extension.c:1042 +#: commands/extension.c:1239 #, c-format msgid "invalid character in extension owner: must not contain any of \"%s\"" msgstr "არასწორი სიმბოლო გაფართოების მფლობელში: არ უნდა შეიცავდეს სიმბოლოებს სიიდან \"%s\"" -#: commands/extension.c:1066 commands/extension.c:1093 +#: commands/extension.c:1263 commands/extension.c:1290 #, c-format msgid "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" msgstr "არასწორი სიმბოლო გაფართოებაში \"%s\": სქემა: არ უნდა შეიცავდეს სიმბოლოებს სიიდან \"%s\"" -#: commands/extension.c:1288 +#: commands/extension.c:1485 #, c-format msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" msgstr "გაფართოებას \"%s\" ვერსიიდან \"%s\" ვერსიამდე \"%s\" განახლების ბილიკი არ გააჩნია" -#: commands/extension.c:1496 commands/extension.c:3089 +#: commands/extension.c:1693 commands/extension.c:3357 #, c-format msgid "version to install must be specified" msgstr "საჭიროა დასაყენებელი ვერსიის მითითება" -#: commands/extension.c:1533 +#: commands/extension.c:1730 #, c-format msgid "extension \"%s\" has no installation script nor update path for version \"%s\"" msgstr "გაფართოებას \"%s\" ვერსიისთვის \"%s\" არც დაყენების სკრიპტი გააჩნია, არც განახლების ბილიკი" -#: commands/extension.c:1567 +#: commands/extension.c:1764 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "გაფართოება \"%s\" დაყენებული უნდა იყოს სქემაში \"%s\"" -#: commands/extension.c:1727 +#: commands/extension.c:1924 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "აღმოჩენილია ციკლური დამოკიდებულებები \"%s\" და \"%s\" გაფართოებებს შორის" -#: commands/extension.c:1732 +#: commands/extension.c:1929 #, c-format msgid "installing required extension \"%s\"" msgstr "მოთხოვნილი გაფართოების დაყენება: \"%s\"" -#: commands/extension.c:1755 +#: commands/extension.c:1952 #, c-format msgid "required extension \"%s\" is not installed" msgstr "მოთხოვნილი გაფართოება დაყენებული არაა: %s" -#: commands/extension.c:1758 +#: commands/extension.c:1955 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "საჭირო გაფართოებების დასაყენებლად გამოიყენეთ CREATE EXTENSION ... CASCADE." -#: commands/extension.c:1793 +#: commands/extension.c:1990 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "გაფართოება \"%s\" უკვე არსებობს, გამოტოვება" -#: commands/extension.c:1800 +#: commands/extension.c:1997 #, c-format msgid "extension \"%s\" already exists" msgstr "გაფართოება \"%s\" უკვე არსებობს" -#: commands/extension.c:1811 +#: commands/extension.c:2008 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "ჩადგმული CREATE EXTENSION მხარდაუჭერელია" -#: commands/extension.c:1975 +#: commands/extension.c:2172 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "გაფართოების \"%s\" წაშლა შეუძლებელია, რადგან მიმდინარეობს მისი ჩასწორება" -#: commands/extension.c:2450 +#: commands/extension.c:2665 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "%s-ის გამოძახება მხოლოდ CREATE EXTENSION-ის მიერ შესრულებულ SQL სკრიპტიდან შეგიძლიათ" -#: commands/extension.c:2462 +#: commands/extension.c:2677 #, c-format msgid "OID %u does not refer to a table" msgstr "OID %u ცხრილს არ ეხება" -#: commands/extension.c:2467 +#: commands/extension.c:2682 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "ცხრილი (%s) არ წარმოადგენს იმ გაფართოების წევრს, რომლის შექმნაც მიმდინარეობს" -#: commands/extension.c:2813 +#: commands/extension.c:3081 #, c-format msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema" msgstr "გაფართოების (\"%s\") სქემაში (\"%s\") გადატანა შეუძლებელია იმიტომ, რომ გაფართოება სქემას შეიცავს" -#: commands/extension.c:2854 commands/extension.c:2948 +#: commands/extension.c:3122 commands/extension.c:3216 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "გაფართოებას SET SCHEMA-ის მხარდაჭერა არ გააჩნია: %s" -#: commands/extension.c:2911 +#: commands/extension.c:3179 #, c-format msgid "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" msgstr "გაფართოება \"%s\"-ის SET SCHEMA შეუძლებელია, რადგან ეს იკრძალება სხვა გაფართოებების მიერ" -#: commands/extension.c:2913 +#: commands/extension.c:3181 #, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." msgstr "გაფართოება \"%s\" გაფართოების \"%s\" გადაადგილებას არ მოითხოვს." -#: commands/extension.c:2950 +#: commands/extension.c:3218 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "%s არ წარმოადგენს გაფართოების სქემას \"%s\"" -#: commands/extension.c:3011 +#: commands/extension.c:3279 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "ჩადგმული ALTER EXTENSION მხარდაუჭერელია" -#: commands/extension.c:3100 +#: commands/extension.c:3368 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "გაფართოების %2$s ვერსია %1$s უკვე დაყენებულია" -#: commands/extension.c:3311 +#: commands/extension.c:3579 #, c-format msgid "cannot add an object of this type to an extension" msgstr "ამ ტიპის ობიექტის გაფართოებაზე დამატება შეუძლებელია" -#: commands/extension.c:3409 +#: commands/extension.c:3677 #, c-format msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension" msgstr "სქემის (\"%s\") გაფართოებაში (\"%s\") ჩამატება შეუძლებელია, რადგან სქემა გაფართოებას შეიცავს" -#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#: commands/extension.c:3759 commands/typecmds.c:4033 utils/fmgr/funcapi.c:725 #, c-format msgid "could not find multirange type for data type %s" msgstr "მონაცემების ტიპისთვის %s მრავალდიაპაზონიანი ტიპი ვერ ვიპოვე" -#: commands/extension.c:3532 +#: commands/extension.c:3801 #, c-format msgid "file \"%s\" is too large" msgstr "%s: ფაილი ძალიან დიდია" @@ -8239,7 +8240,7 @@ msgstr "გარე მონაცემების გადამტან msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "გარე მონაცემების გადამტანის მფლობელი ზემომხმარებელი უნდა იყოს." -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:681 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "გარე მონაცემების გადამტანი არ არსებობს: %s" @@ -8309,7 +8310,7 @@ msgstr "მომხმარებლის ბმა %s სერვერი msgid "user mapping for \"%s\" does not exist for server \"%s\", skipping" msgstr "მომხმარებლის ბმა %s სერვერისთვის %s არ არსებობს, გამოტოვება" -#: commands/foreigncmds.c:1507 foreign/foreign.c:394 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "გარე-მონაცემების გადამტანს დამმუშავებელი არ გააჩნია: %s" @@ -8354,629 +8355,674 @@ msgstr "გარსის ტიპის აღწერის შექმნ msgid "SQL function cannot accept shell type %s" msgstr "SQL ფუნქციებს %s გარსის ტიპის მიღება არ შეუძლიათ" -#: commands/functioncmds.c:250 +#: commands/functioncmds.c:251 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "აგრეგატს არ შეუძლია ცარიელი ტიპის მიღება: %s" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:257 #, c-format msgid "argument type %s is only a shell" msgstr "არგუმენტის ტიპი %s მხოლოდ გარსია" -#: commands/functioncmds.c:265 +#: commands/functioncmds.c:268 #, c-format msgid "type %s does not exist" msgstr "ტიპი \"%s\" არ არსებობს" -#: commands/functioncmds.c:279 +#: commands/functioncmds.c:283 #, c-format msgid "aggregates cannot accept set arguments" msgstr "აგრეგატებს არგუმენტების სეტის მიღება არ შეუძლიათ" -#: commands/functioncmds.c:283 +#: commands/functioncmds.c:288 #, c-format msgid "procedures cannot accept set arguments" msgstr "პროცედურებს არგუმენტების სეტის მიღება არ შეუძლიათ" -#: commands/functioncmds.c:287 +#: commands/functioncmds.c:293 #, c-format msgid "functions cannot accept set arguments" msgstr "ფუნქციებს არგუმენტების სეტის მიღება არ შეუძლიათ" -#: commands/functioncmds.c:297 +#: commands/functioncmds.c:304 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "VARIADIC პარამეტრი ბოლო შეყვანის პარამეტრი უნდა იყოს" -#: commands/functioncmds.c:317 +#: commands/functioncmds.c:325 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "VARIADIC პარამეტრი ბოლო უნდა იყოს" -#: commands/functioncmds.c:342 +#: commands/functioncmds.c:351 #, c-format msgid "VARIADIC parameter must be an array" msgstr "VARIADIC პარამეტრი მასივი უნდა იყოს" -#: commands/functioncmds.c:387 +#: commands/functioncmds.c:397 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "პარამეტრის სახელი \"%s\" ერთზე მეტჯერ გამოიყენება" -#: commands/functioncmds.c:405 +#: commands/functioncmds.c:416 #, c-format msgid "only input parameters can have default values" msgstr "ნაგულისხმევი მნიშვნელობების დაყენება მხოლოდ შემომავალ პარამეტრებზეა შესაძლებელი" -#: commands/functioncmds.c:420 +#: commands/functioncmds.c:432 #, c-format msgid "cannot use table references in parameter default value" msgstr "ცხრილის ბმის პარამეტრის ნაგულისხმევ მნიშვნელობად გამოყენება შეუძლებელია" -#: commands/functioncmds.c:444 +#: commands/functioncmds.c:457 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "შეყვანის პარამეტრებში, მას შემდეგ, რაც ერთს აქვს ნაგულისხმევი მნიშვნელობა, ის სხვებსაც უნდა ჰქონდეთ" -#: commands/functioncmds.c:454 +#: commands/functioncmds.c:468 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "პროცედური OUT პარამეტრები ვერ გამოჩნდება ერთის შემდეგ, რომელსაც ნაგულისხმევი მნიშვნელობა გააჩნია" -#: commands/functioncmds.c:596 commands/functioncmds.c:775 +#: commands/functioncmds.c:611 commands/functioncmds.c:790 #, c-format msgid "invalid attribute in procedure definition" msgstr "პროცედურის აღწერაში ნაპოვნია არასწორი ატრიბუტი" -#: commands/functioncmds.c:692 +#: commands/functioncmds.c:707 #, c-format msgid "support function %s must return type %s" msgstr "მხარდაჭერის ფუნქციამ (%s) უნდა დააბრუნოს ტიპი %s" -#: commands/functioncmds.c:703 +#: commands/functioncmds.c:718 #, c-format msgid "must be superuser to specify a support function" msgstr "მხარდაჭერის ფუნქციის მისათითებლად ზემომხმარებლის წვდომელია საჭირო" -#: commands/functioncmds.c:824 commands/functioncmds.c:1427 +#: commands/functioncmds.c:839 commands/functioncmds.c:1445 #, c-format msgid "COST must be positive" msgstr "COST დადებითი უნდა იყოს" -#: commands/functioncmds.c:832 commands/functioncmds.c:1435 +#: commands/functioncmds.c:847 commands/functioncmds.c:1453 #, c-format msgid "ROWS must be positive" msgstr "ROWS დადებითი უნდა იყოს" -#: commands/functioncmds.c:861 +#: commands/functioncmds.c:876 #, c-format msgid "no function body specified" msgstr "ფუნქციის ტანი მითითებული არაა" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:881 #, c-format msgid "duplicate function body specified" msgstr "მითითებულია ფუნქციის დუბლირებული ტანი" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:886 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "" -#: commands/functioncmds.c:913 +#: commands/functioncmds.c:928 #, c-format msgid "SQL function with unquoted function body cannot have polymorphic arguments" msgstr "ბრჭყალების არმქონე ტანის მატარებელ SQL ფუნქციას პოლიმორფული არგუმენტები არ შეიძლება ჰქონდეს" -#: commands/functioncmds.c:939 commands/functioncmds.c:958 +#: commands/functioncmds.c:954 commands/functioncmds.c:973 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "%s ბრჭყალგარეშე SQL ფუნქციის სხეულში ჯერ მხარდაჭერილი არაა" -#: commands/functioncmds.c:986 +#: commands/functioncmds.c:1001 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "ენისთვის მხოლოდ ერთი AS არის საჭირო: %s" -#: commands/functioncmds.c:1091 +#: commands/functioncmds.c:1107 #, c-format msgid "no language specified" msgstr "ენა არ არის მითითებული" -#: commands/functioncmds.c:1099 commands/functioncmds.c:2104 commands/proclang.c:235 +#: commands/functioncmds.c:1115 commands/functioncmds.c:2135 commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "ენა \"%s\" არ არსებობს" -#: commands/functioncmds.c:1101 commands/functioncmds.c:2106 +#: commands/functioncmds.c:1117 commands/functioncmds.c:2137 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "ენის ბაზაში შესატვირთად გამოიყენეთ CREATE EXTENSION." -#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 +#: commands/functioncmds.c:1150 commands/functioncmds.c:1437 #, c-format msgid "only superuser can define a leakproof function" msgstr "leakproof ატრიბუტის მქონე ფუნქციის აღწერა მხოლოდ ზემომხმარებელს შეუძლია" -#: commands/functioncmds.c:1185 +#: commands/functioncmds.c:1202 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "\"OUT\" პარამეტრების გამო ფუნქციის შედეგის ტიპი %s უნდა იყოს" -#: commands/functioncmds.c:1198 +#: commands/functioncmds.c:1215 #, c-format msgid "function result type must be specified" msgstr "ფუნქციის შედეგის ტიპის მითითება აუცილებელია" -#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 +#: commands/functioncmds.c:1268 commands/functioncmds.c:1457 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "ROWS შესაფერისი არაა, როცა ფუნქცია სეტს არ აბრუნებს" -#: commands/functioncmds.c:1546 +#: commands/functioncmds.c:1564 #, c-format msgid "source data type %s is a pseudo-type" msgstr "საწყისი მონაცემთა ტიპი %s ფსევდო ტიპია" -#: commands/functioncmds.c:1552 +#: commands/functioncmds.c:1570 #, c-format msgid "target data type %s is a pseudo-type" msgstr "საბოლოო მონაცემთა ტიპი %s ფსევდო ტიპია" -#: commands/functioncmds.c:1576 +#: commands/functioncmds.c:1594 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "მოხდება გარდაქმნის დაიგნორება იმის გამო, რომ მონაცემების საწყისი ტიპი დომენს წარმოადგენს" -#: commands/functioncmds.c:1581 +#: commands/functioncmds.c:1599 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "მოხდება გარდაქმნის დაიგნორება იმის გამო, რომ მონაცემების სამიზნე ტიპი დომენს წარმოადგენს" -#: commands/functioncmds.c:1606 +#: commands/functioncmds.c:1624 #, c-format msgid "cast function must take one to three arguments" msgstr "გარდაქმნის ფუნქციამ ერთიდან სამ არგუმენტამდე უნდა მიიღოს" -#: commands/functioncmds.c:1612 +#: commands/functioncmds.c:1630 #, c-format msgid "argument of cast function must match or be binary-coercible from source data type" msgstr "" -#: commands/functioncmds.c:1616 +#: commands/functioncmds.c:1634 #, c-format msgid "second argument of cast function must be type %s" msgstr "გარდაქმნის ფუნქციის მეორე არგუმენტის ტიპი %s უნდა იყოს" -#: commands/functioncmds.c:1621 +#: commands/functioncmds.c:1639 #, c-format msgid "third argument of cast function must be type %s" msgstr "გარდაქმნის ფუნქციის მესამე არგუმენტის ტიპი %s უნდა იყოს" -#: commands/functioncmds.c:1628 +#: commands/functioncmds.c:1646 #, c-format msgid "return data type of cast function must match or be binary-coercible to target data type" msgstr "" -#: commands/functioncmds.c:1639 +#: commands/functioncmds.c:1657 #, c-format msgid "cast function must not be volatile" msgstr "გარდაქმნის ფუნქცია ცვალებადი არ უნდა იყოს" -#: commands/functioncmds.c:1644 +#: commands/functioncmds.c:1662 #, c-format msgid "cast function must be a normal function" msgstr "გარდაქმნის ფუნქცია ნორმალური ფუნქცია უნდა იყოს" -#: commands/functioncmds.c:1648 +#: commands/functioncmds.c:1666 #, c-format msgid "cast function must not return a set" msgstr "გარდაქმნის ფუნქციამ სეტი არ უნდა დააბრუნოს" -#: commands/functioncmds.c:1674 +#: commands/functioncmds.c:1692 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "\"WITHOUT FUNCTION\"-ის გარდაქმნის შესაქმნელად ზეომხმარებელი უნდა ბრძანდებოდეთ" -#: commands/functioncmds.c:1689 +#: commands/functioncmds.c:1707 #, c-format msgid "source and target data types are not physically compatible" msgstr "საწყისი და სამიზნე მონაცემის ტიპები ფიზიკურად შეუთავსებელია" -#: commands/functioncmds.c:1704 +#: commands/functioncmds.c:1727 #, c-format msgid "composite data types are not binary-compatible" msgstr "მონაცემების კომპოზიტური ტიპები შეუთავსებელია ორობით დონეზე" -#: commands/functioncmds.c:1710 -#, c-format -msgid "enum data types are not binary-compatible" -msgstr "მონაცემების ჩამონათვალის ტიპები შეუთავსებელია ორობით დონეზე" - -#: commands/functioncmds.c:1716 +#: commands/functioncmds.c:1733 #, c-format msgid "array data types are not binary-compatible" msgstr "მასივის მონაცემების ტიპები შეუთავსებელია ორობით დონეზე" -#: commands/functioncmds.c:1733 +#: commands/functioncmds.c:1741 +#, c-format +msgid "range data types are not binary-compatible" +msgstr "შუალედის მონაცემის ტიპები შეუთავსებელია ორობით დონეზე" + +#: commands/functioncmds.c:1747 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "მონაცემების ჩამონათვალის ტიპები შეუთავსებელია ორობით დონეზე" + +#: commands/functioncmds.c:1764 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "დომენის მონაცემების ტიპები შეუთავსებელია ორობით დონეზე" -#: commands/functioncmds.c:1743 +#: commands/functioncmds.c:1774 #, c-format msgid "source data type and target data type are the same" msgstr "საწყისი და სამიზნე მონაცემების ტიპები ერთი და იგივეა" -#: commands/functioncmds.c:1776 +#: commands/functioncmds.c:1807 #, c-format msgid "transform function must not be volatile" msgstr "გარდაქმნის ფუნქცია ცვალებადი არ უნდა იყოს" -#: commands/functioncmds.c:1780 +#: commands/functioncmds.c:1811 #, c-format msgid "transform function must be a normal function" msgstr "გარდაქმნის ფუნქცია ნორმალური ფუნქცია უნდა იყოს" -#: commands/functioncmds.c:1784 +#: commands/functioncmds.c:1815 #, c-format msgid "transform function must not return a set" msgstr "გარდაქმნის ფუნქციამ სეტი არ უნდა დააბრუნოს" -#: commands/functioncmds.c:1788 +#: commands/functioncmds.c:1819 #, c-format msgid "transform function must take one argument" msgstr "გარდაქმნის ფუნქციამ ერთი არგუმენტი უნდა მიიღოს" -#: commands/functioncmds.c:1792 +#: commands/functioncmds.c:1823 #, c-format msgid "first argument of transform function must be type %s" msgstr "გარდაქმნის ფუნქციის პირველი არგუმენტის ტიპი %s უნდა იყოს" -#: commands/functioncmds.c:1831 +#: commands/functioncmds.c:1862 #, c-format msgid "data type %s is a pseudo-type" msgstr "მონაცემთა ტიპი %s ფსევდო ტიპია" -#: commands/functioncmds.c:1837 +#: commands/functioncmds.c:1868 #, c-format msgid "data type %s is a domain" msgstr "მონაცემების ტიპი %s დომენია" -#: commands/functioncmds.c:1877 +#: commands/functioncmds.c:1908 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "\"FROM SQL\" ფუნქციის დაბრუნებული მონაცემები აუცილებლად უნდა იყოს: %s" -#: commands/functioncmds.c:1903 +#: commands/functioncmds.c:1934 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "" -#: commands/functioncmds.c:1930 +#: commands/functioncmds.c:1961 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "გადაყვანა ტიპისთვის %s ენა \"%s\" უკვე არსებობს" -#: commands/functioncmds.c:2016 +#: commands/functioncmds.c:2047 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "გადაყვანა ტიპისთვის %s ენა \"%s\" არ არსებობს" -#: commands/functioncmds.c:2040 +#: commands/functioncmds.c:2071 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "ფუნქცია (%s) სქემაში (%s) უკვე არსებობს" -#: commands/functioncmds.c:2091 +#: commands/functioncmds.c:2122 #, c-format msgid "no inline code specified" msgstr "ჩადგმული კოდი მითითებული არაა" -#: commands/functioncmds.c:2137 +#: commands/functioncmds.c:2168 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "" -#: commands/functioncmds.c:2232 +#: commands/functioncmds.c:2263 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" msgstr[0] "პროცედურისთვის %d-ზე მეტი არგუმენტის გადაცემა შეუძლებელია" msgstr[1] "პროცედურისთვის %d-ზე მეტი არგუმენტის გადაცემა შეუძლებელია" -#: commands/indexcmds.c:647 +#: commands/indexcmds.c:659 #, c-format msgid "must specify at least one column" msgstr "უნდა მიეთითოს მინიმუმ ერთი სვეტი" -#: commands/indexcmds.c:651 +#: commands/indexcmds.c:663 #, c-format msgid "cannot use more than %d columns in an index" msgstr "ინდექსში %d სვეტზე მეტს ვერ გამოიყენებთ" -#: commands/indexcmds.c:694 +#: commands/indexcmds.c:712 #, c-format msgid "cannot create index on relation \"%s\"" msgstr "ურთიერთბაზე \"%s\" ინდექსის შექმნა შეიძლებელია" -#: commands/indexcmds.c:720 +#: commands/indexcmds.c:738 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "ინდექსს დაყოფილ ცხრილზე %s პარალელურად ვერ შექმნით" -#: commands/indexcmds.c:730 +#: commands/indexcmds.c:748 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილებზე ინდექსების შექმნა შეუძლებელია" -#: commands/indexcmds.c:768 commands/tablecmds.c:806 commands/tablespace.c:1178 +#: commands/indexcmds.c:786 commands/tablecmds.c:892 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "დაყოფილი ურთიერთობებისთვის ნაგულისხმევი ცხრილის სივრცეების მითითება შეუძლებელია" -#: commands/indexcmds.c:800 commands/tablecmds.c:837 commands/tablecmds.c:3564 +#: commands/indexcmds.c:818 commands/tablecmds.c:923 commands/tablecmds.c:3710 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "pg_global ცხრილის სივრცეში მხოლოდ გაზიარებული ურთიერთობების მოთავსება შეგიძლიათ" -#: commands/indexcmds.c:833 +#: commands/indexcmds.c:851 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "მოძველებული მეთოდი \"rtree\" წვდომის მეთოდით \"gist\" ჩანაცვლდება" -#: commands/indexcmds.c:854 +#: commands/indexcmds.c:872 #, c-format msgid "access method \"%s\" does not support unique indexes" msgstr "სწვდომის მეთოდს (%s) უნიკალური ინდექსების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:859 +#: commands/indexcmds.c:877 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "სწვდომის მეთოდს (%s) ჩასმული სვეტების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:864 +#: commands/indexcmds.c:882 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "სწვდომის მეთოდს (%s) მრავალსვეტიანი ინდექსების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:869 +#: commands/indexcmds.c:887 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "სწვდომის მეთოდს (%s) გამორიცხვის შეზღუდვების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:998 +#: commands/indexcmds.c:892 #, c-format -msgid "cannot match partition key to an index using access method \"%s\"" -msgstr "წვდომის მეთოდით \"%s\" დანაყოფის გასაღების ინდექსთან დამთხვევა შეუძლებელია" +msgid "access method \"%s\" does not support WITHOUT OVERLAPS constraints" +msgstr "სწვდომის მეთოდს (%s) WITHOUT OVERLAPS შეზღუდვების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:1008 +#: commands/indexcmds.c:1019 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "მხარდაუჭერელი %s შეზღუდვა დანაყოფის გასაღების აღწერით" -#: commands/indexcmds.c:1010 +#: commands/indexcmds.c:1021 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "" -#: commands/indexcmds.c:1060 +#: commands/indexcmds.c:1056 commands/indexcmds.c:2469 commands/indexcmds.c:2488 executor/execReplication.c:329 parser/parse_cte.c:303 parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1410 utils/adt/array_userfuncs.c:1553 utils/adt/arrayfuncs.c:3864 utils/adt/arrayfuncs.c:4419 utils/adt/arrayfuncs.c:6440 utils/adt/rowtypes.c:1220 +#, c-format +msgid "could not identify an equality operator for type %s" +msgstr "ტიპისთვის \"%s\" ტოლობის ფუნქცია ვერ ვიპოვე" + +#: commands/indexcmds.c:1057 commands/indexcmds.c:2491 +#, c-format +msgid "There is no suitable operator in operator family \"%s\" for access method \"%s\"." +msgstr "ვერ ვიპოვე შესაბამისი ოპერატორი ოპერატორების ოჯახში \"%s\" წვდომის მეთოდისთვის \"%s\"." + +#: commands/indexcmds.c:1077 #, c-format msgid "cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"" msgstr "დანაყოფის გასაღების დამთხვევა სვეტზე \"%s\" მდებარე ინდექსთან უტოლობის ოპერატორით \"%s\" შეუძლებელია" -#: commands/indexcmds.c:1076 +#: commands/indexcmds.c:1093 #, c-format msgid "unique constraint on partitioned table must include all partitioning columns" msgstr "დაყოფილ ცხრილზე არსებული უნიკალური შეზღუდვა ყველა დაყოფის სვეტს უნდა შეიცავდეს" -#: commands/indexcmds.c:1077 +#: commands/indexcmds.c:1094 #, c-format msgid "%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key." msgstr "" -#: commands/indexcmds.c:1096 commands/indexcmds.c:1115 +#: commands/indexcmds.c:1116 commands/indexcmds.c:1147 #, c-format msgid "index creation on system columns is not supported" msgstr "სისტემური სვეტებზე ინდექსების შექმნა მხარდაუჭერელია" -#: commands/indexcmds.c:1344 tcop/utility.c:1515 +#: commands/indexcmds.c:1123 +#, c-format +msgid "primary keys on virtual generated columns are not supported" +msgstr "ვირტუალურ გენერირებულ სვეტებზე ძირითადი გასაღებები მხარდაჭერილი არაა" + +#: commands/indexcmds.c:1125 commands/indexcmds.c:1164 +#, c-format +msgid "unique constraints on virtual generated columns are not supported" +msgstr "ვირტუალურ გენერირებულ სვეტებზე უნიკალური შეზღუდვები მხარდაჭერილი არაა" + +#: commands/indexcmds.c:1126 commands/indexcmds.c:1165 +#, c-format +msgid "indexes on virtual generated columns are not supported" +msgstr "ვირტუალურ გენერირებულ სვეტებზე ინდექსების შექმნა მხარდაჭერილი არაა" + +#: commands/indexcmds.c:1397 tcop/utility.c:1518 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "დაყოფილ ცხრილზე (%s) უნიკალური ინდექსის შექმნა შეუძლებელია" -#: commands/indexcmds.c:1346 tcop/utility.c:1517 +#: commands/indexcmds.c:1399 tcop/utility.c:1520 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "ცხრილი (%s) შეიცავს დანაყოფებს, რომლებც გარე ცხრილებია." -#: commands/indexcmds.c:1831 +#: commands/indexcmds.c:1857 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "ფუნქციები ინდექსის პრედიკატში მონიშნეთ, როგორც IMMUTABLE" -#: commands/indexcmds.c:1910 parser/parse_utilcmd.c:2494 parser/parse_utilcmd.c:2629 +#: commands/indexcmds.c:1954 parser/parse_utilcmd.c:2714 parser/parse_utilcmd.c:2897 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "გასაღებში დასახელებული სვეტი არ არსებობს: %s" -#: commands/indexcmds.c:1934 parser/parse_utilcmd.c:1782 +#: commands/indexcmds.c:1978 parser/parse_utilcmd.c:1967 #, c-format msgid "expressions are not supported in included columns" msgstr "ჩასმულ სვეტებში გამოსახულებები მხარდაჭერილი არაა" -#: commands/indexcmds.c:1975 +#: commands/indexcmds.c:2019 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "ფუნქციები ინდექსის გამოსახულებაში მონიშნეთ, როგორც IMMUTABLE" -#: commands/indexcmds.c:1990 +#: commands/indexcmds.c:2034 #, c-format msgid "including column does not support a collation" msgstr "ჩასმულ სვეტს კოლაციის მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:1994 +#: commands/indexcmds.c:2038 #, c-format msgid "including column does not support an operator class" msgstr "ჩასმულ სვეტს ოპერატორის კლასის მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:1998 +#: commands/indexcmds.c:2042 #, c-format msgid "including column does not support ASC/DESC options" msgstr "ჩასმულ სვეტს ASC/DESC პარამეტრების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:2002 +#: commands/indexcmds.c:2046 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "ჩასმულ სვეტს NULLS FIRST/LAST მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:2044 +#: commands/indexcmds.c:2089 #, c-format msgid "could not determine which collation to use for index expression" msgstr "ინდექსის გამოსახულებისთვის გამოსაყენებელი კოლაციის გამოცნობა შეუძლებელია" -#: commands/indexcmds.c:2052 commands/tablecmds.c:18078 commands/typecmds.c:811 parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3918 utils/adt/misc.c:630 +#: commands/indexcmds.c:2097 commands/tablecmds.c:19917 commands/typecmds.c:812 parser/parse_expr.c:2801 parser/parse_type.c:568 parser/parse_utilcmd.c:4043 utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "ტიპს \"%s\" კოლაციების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:2117 +#: commands/indexcmds.c:2164 #, c-format msgid "operator %s is not commutative" msgstr "ოპერატორი %s არაკომუტაციურია" -#: commands/indexcmds.c:2119 +#: commands/indexcmds.c:2166 #, c-format msgid "Only commutative operators can be used in exclusion constraints." msgstr "გამორიცხვის შეზღუდვებში მხოლოდ კომუტაციური ოპერატორების გამოყენება შეგიძლიათ." -#: commands/indexcmds.c:2145 +#: commands/indexcmds.c:2176 #, c-format msgid "operator %s is not a member of operator family \"%s\"" msgstr "ოპერატორი (%s) ოპერატორის ოჯახის (%s) წევრი არაა" -#: commands/indexcmds.c:2148 +#: commands/indexcmds.c:2179 #, c-format msgid "The exclusion operator must be related to the index operator class for the constraint." msgstr "" -#: commands/indexcmds.c:2183 +#: commands/indexcmds.c:2228 #, c-format msgid "access method \"%s\" does not support ASC/DESC options" msgstr "წვდომის მეთოდს \"%s\" ASC/DESC პარამეტრების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:2188 +#: commands/indexcmds.c:2233 #, c-format msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "წვდომის მეთოდს \"%s\" 'NULLS FIRST/LAST' პარამეტრების მხარდაჭერა არ გააჩნია" -#: commands/indexcmds.c:2232 commands/tablecmds.c:18103 commands/tablecmds.c:18109 commands/typecmds.c:2311 +#: commands/indexcmds.c:2277 commands/tablecmds.c:19942 commands/tablecmds.c:19948 commands/typecmds.c:2341 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "მონაცემის ტიპს %s წვდომის მეთოდისთვის \"%s\" ნაგულისხმევი ოპერატორის კლასი არ გააჩნია" -#: commands/indexcmds.c:2234 +#: commands/indexcmds.c:2279 #, c-format msgid "You must specify an operator class for the index or define a default operator class for the data type." msgstr "აუცილებელია მიუთითოთ ოპერატორის კლასი ინდექსისთვის ან აღწეროთ ნაგულისხმევი ოპერატორის კლასი მონაცემის ტიპისთვის." -#: commands/indexcmds.c:2263 commands/indexcmds.c:2271 commands/opclasscmds.c:204 +#: commands/indexcmds.c:2308 commands/indexcmds.c:2316 commands/opclasscmds.c:205 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "ოპერატორის კლასი \"%s\" წვდომის მეთოდისთვის \"%s\" არ არსებობს" -#: commands/indexcmds.c:2285 commands/typecmds.c:2299 +#: commands/indexcmds.c:2330 commands/typecmds.c:2329 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "ოპერატორის კლასი \"%s\" მონაცემების ტიპს %s არ იღებს" -#: commands/indexcmds.c:2375 +#: commands/indexcmds.c:2420 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "მონაცემის ტიპისთვის %s ერთზე მეტი ნაგულისხმევი ოპერატორის კლასი არსებობს" -#: commands/indexcmds.c:2703 +#: commands/indexcmds.c:2470 commands/indexcmds.c:2489 +#, c-format +msgid "could not identify an overlaps operator for type %s" +msgstr "ვერ აღმოვაჩინე გადაფარვების ოპერატორი ტიპისთვის %s" + +#: commands/indexcmds.c:2471 commands/indexcmds.c:2490 +#, c-format +msgid "could not identify a contained-by operator for type %s" +msgstr "ტიპისთვის \"%s\" ოპერატორი constained-by ვერ ვიპოვე" + +#: commands/indexcmds.c:2472 commands/tablecmds.c:10333 +#, c-format +msgid "Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\"." +msgstr "ვერ ვთარგმნე შედარების ტიპი %d ოპერატორის ოჯახისთვის \"%s\". შეყვანის ტიპი %s, წვდომის მეთოდი \"%s\"." + +#: commands/indexcmds.c:2812 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "\"REINDEX\"-ის უცნობი პარამეტრი \"%s\"" -#: commands/indexcmds.c:2935 +#: commands/indexcmds.c:3044 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "ცხრილს \"%s\" არ გააჩნია ინდექსები, რომლების პარალელური რეინდექსიც შესაძლებელია" -#: commands/indexcmds.c:2949 +#: commands/indexcmds.c:3058 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "ცხრილს \"%s\" რეინდექსისთვის ცხრილები არ არ გააჩნია" -#: commands/indexcmds.c:2996 commands/indexcmds.c:3507 commands/indexcmds.c:3637 +#: commands/indexcmds.c:3105 commands/indexcmds.c:3616 commands/indexcmds.c:3746 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "სისტემური კატალოგების ერთდროული რეინდექსი შეუძლებელია" -#: commands/indexcmds.c:3020 +#: commands/indexcmds.c:3129 #, c-format msgid "can only reindex the currently open database" msgstr "შესაძლებელია მხოლოდ ამჟამად ღია ბაზის რეინდექსი" -#: commands/indexcmds.c:3112 +#: commands/indexcmds.c:3221 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "სისტემური კატალოგების ერთდროული რეინდექსი შეუძლებელია. ყველას გამოტოვება" -#: commands/indexcmds.c:3145 +#: commands/indexcmds.c:3254 #, c-format msgid "cannot move system relations, skipping all" msgstr "სისტემური დანაყოფების გადაადგილება შეუძლებელია. ყველას გამოტოვება" -#: commands/indexcmds.c:3191 +#: commands/indexcmds.c:3300 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "დაყოფილი ცხრილის რეინდექსისას: \"%s.%s\"" -#: commands/indexcmds.c:3194 +#: commands/indexcmds.c:3303 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "დაყოფილი ინდექსის რეინდექსისას: \"%s.%s\"" -#: commands/indexcmds.c:3387 commands/indexcmds.c:4255 +#: commands/indexcmds.c:3496 commands/indexcmds.c:4388 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "\"%s.%s\"-ის რეინდექსი დასრულდა" -#: commands/indexcmds.c:3539 commands/indexcmds.c:3592 +#: commands/indexcmds.c:3648 commands/indexcmds.c:3701 #, c-format msgid "skipping reindex of invalid index \"%s.%s\"" msgstr "რეინდექსის გამოტოვება არასწორი ინდექსისთვის \"%s.%s\"" -#: commands/indexcmds.c:3542 commands/indexcmds.c:3595 +#: commands/indexcmds.c:3651 commands/indexcmds.c:3704 #, c-format msgid "Use DROP INDEX or REINDEX INDEX." msgstr "გამოიყენეთ DROP INDEX ან REINDEX INDEX." -#: commands/indexcmds.c:3546 +#: commands/indexcmds.c:3655 #, c-format msgid "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" msgstr "გამორიცხვის შეზღუდვის ინდექსის \"%s.%s\" პარალელური რეინდექსი შეუძლებელია. გამოტოვება" -#: commands/indexcmds.c:3702 +#: commands/indexcmds.c:3811 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "ამ ტიპის ურთიერთობის პარალელური რეინდექსი შეუძლებელია" -#: commands/indexcmds.c:3720 +#: commands/indexcmds.c:3829 #, c-format msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "არაგაზიარებული ურთიერთობის ცხრილების სივრცეში \"%s\" გადატანა შეუძლებელია" -#: commands/indexcmds.c:4236 commands/indexcmds.c:4248 +#: commands/indexcmds.c:4369 commands/indexcmds.c:4381 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr "\"%s.%s\"-ის რეინდექსი დასრულდა" -#: commands/indexcmds.c:4238 commands/indexcmds.c:4257 +#: commands/indexcmds.c:4371 commands/indexcmds.c:4390 #, c-format msgid "%s." msgstr "%s." @@ -8986,252 +9032,272 @@ msgstr "%s." msgid "cannot lock relation \"%s\"" msgstr "ურთიერთობის დაბლოკვა (\"%s\") შეუძლებელია" -#: commands/matview.c:190 +#: commands/matview.c:208 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "CONCURRENTLY-ის გამოყენება შეუძლებელია, როცა მატერიალიზებული ხედი შევსებული არაა" -#: commands/matview.c:196 gram.y:18967 +#: commands/matview.c:214 gram.y:19148 #, c-format msgid "%s and %s options cannot be used together" msgstr "პარამეტრები %s და %s შეუთავსებლებია" -#: commands/matview.c:253 +#: commands/matview.c:273 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "მატერიალიზებული ხედის (%s) პარალელური განახლება შეუძლებელია" -#: commands/matview.c:256 +#: commands/matview.c:276 #, c-format msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view." msgstr "" -#: commands/matview.c:650 +#: commands/matview.c:683 #, c-format msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns" msgstr "ახალი მონაცემები მატერიალიზებულ ხედისთვის \"%s\" დუბლირებულ მწკრივებს შეიცავს, ნულოვანი მწკრივების გარეშე" -#: commands/matview.c:652 +#: commands/matview.c:685 #, c-format msgid "Row: %s" msgstr "მწკრივი: %s" -#: commands/opclasscmds.c:123 +#: commands/matview.c:839 +#, c-format +msgid "could not find suitable unique index on materialized view" +msgstr "მატერიალიზებულ ხედზე შესაბამისი უნიკალური ინდექსი ვერ ვიპოვე" + +#: commands/opclasscmds.c:124 #, c-format msgid "operator family \"%s\" does not exist for access method \"%s\"" msgstr "წვდომის მეთოდისთვის (%2$s) ოპერატორის ოჯახი (%1$s) არ არსებობს" -#: commands/opclasscmds.c:266 +#: commands/opclasscmds.c:267 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists" msgstr "წვდომის მეთოდისთვის (%2$s) ოპერატორის ოჯახი (%1$s) უკვე არსებობს" -#: commands/opclasscmds.c:415 +#: commands/opclasscmds.c:416 #, c-format msgid "must be superuser to create an operator class" msgstr "ოპერატორის კლასის შესაქმნელად ზემომხმარებლის უფლებება საჭირო" -#: commands/opclasscmds.c:492 commands/opclasscmds.c:909 commands/opclasscmds.c:1055 +#: commands/opclasscmds.c:493 commands/opclasscmds.c:910 commands/opclasscmds.c:1056 #, c-format msgid "invalid operator number %d, must be between 1 and %d" msgstr "ოპერატორის არასწორი ნომერი: %d. უნდა იყოს დიაპაზონში 1..%d" -#: commands/opclasscmds.c:537 commands/opclasscmds.c:959 commands/opclasscmds.c:1071 +#: commands/opclasscmds.c:538 commands/opclasscmds.c:960 commands/opclasscmds.c:1072 #, c-format msgid "invalid function number %d, must be between 1 and %d" msgstr "ფუნქციის არასწორი ნომერი: %d. უნდა იყოს დიაპაზონში 1..%d" -#: commands/opclasscmds.c:566 +#: commands/opclasscmds.c:567 #, c-format msgid "storage type specified more than once" msgstr "საცავის ტიპი ერთზე მეტჯერაა მითითებული" -#: commands/opclasscmds.c:593 +#: commands/opclasscmds.c:594 #, c-format msgid "storage type cannot be different from data type for access method \"%s\"" msgstr "წვდომის მეთოდისთვის \"%s\" საცავის ტიპი არ შეიძლება, მონაცემის ტიპისგან განსხვავდებოდეს" -#: commands/opclasscmds.c:609 +#: commands/opclasscmds.c:610 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists" msgstr "ოპერატორის კლასი \"%s\" წვდომის მეთოდისთვის \"%s\" უკვე არსებობს" -#: commands/opclasscmds.c:637 +#: commands/opclasscmds.c:638 #, c-format msgid "could not make operator class \"%s\" be default for type %s" msgstr "ოპერატორის კლასის \"%s\" ტიპისთვის %s ნაგულისხმევად დაყენება შეუძლებელია" -#: commands/opclasscmds.c:640 +#: commands/opclasscmds.c:641 #, c-format msgid "Operator class \"%s\" already is the default." msgstr "ოპერატორის კლასი \"%s\" უკვე ნაგულისხმევია." -#: commands/opclasscmds.c:800 +#: commands/opclasscmds.c:801 #, c-format msgid "must be superuser to create an operator family" msgstr "ოპერატორის ოჯახის შესაქმნელად საჭიროა ზემომხმარებლის უფლებები" -#: commands/opclasscmds.c:860 +#: commands/opclasscmds.c:861 #, c-format msgid "must be superuser to alter an operator family" msgstr "ოპერატორის ოჯახის შესაცვლელად საჭიროა ზემომხმარებლის უფლებები" -#: commands/opclasscmds.c:918 +#: commands/opclasscmds.c:919 #, c-format msgid "operator argument types must be specified in ALTER OPERATOR FAMILY" msgstr "'ALTER OPERATOR FAMILY'-ში ოპერატორის არგუმენის ტიპების მითითება აუცილებელია" -#: commands/opclasscmds.c:993 +#: commands/opclasscmds.c:994 #, c-format msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY" msgstr "ALTER OPERATOR FAMILY-ში STORAGE-ს ვერ მიუთითებთ" -#: commands/opclasscmds.c:1127 +#: commands/opclasscmds.c:1128 #, c-format msgid "one or two argument types must be specified" msgstr "უნდა იყოს მითითებული ერთი ან ორი არგუმენტის ტიპი" -#: commands/opclasscmds.c:1153 +#: commands/opclasscmds.c:1154 #, c-format msgid "index operators must be binary" msgstr "ინდექსის ოპერატორები ბინარული უნდა იყოს" -#: commands/opclasscmds.c:1172 +#: commands/opclasscmds.c:1173 #, c-format msgid "access method \"%s\" does not support ordering operators" msgstr "სწვდომის მეთოდს (%s) ოპერატორების დალაგების მხარდაჭერა არ გააჩნია" -#: commands/opclasscmds.c:1183 +#: commands/opclasscmds.c:1184 #, c-format msgid "index search operators must return boolean" msgstr "ინდექსის ძებნის ოპერატორებმა ლოგიკური მნიშვნელობა უნდა დააბრუნონ" -#: commands/opclasscmds.c:1223 +#: commands/opclasscmds.c:1224 #, c-format msgid "associated data types for operator class options parsing functions must match opclass input type" msgstr "ოპერატორის კლასის პარამეტრების დამუშავების ფუნქციებისთვის ასოცირებული მონაცემის ტიპები opclass-ის შეყვანის ტიპებს უნდა ემთხვეოდეს" -#: commands/opclasscmds.c:1230 +#: commands/opclasscmds.c:1231 #, c-format msgid "left and right associated data types for operator class options parsing functions must match" msgstr "" -#: commands/opclasscmds.c:1238 +#: commands/opclasscmds.c:1239 #, c-format msgid "invalid operator class options parsing function" msgstr "კლასის კლასის პარამეტრების დამუშავების ფუნქციის არასწორი ოპერატორი" -#: commands/opclasscmds.c:1239 +#: commands/opclasscmds.c:1240 #, c-format msgid "Valid signature of operator class options parsing function is %s." msgstr "ოპერატორის კლასის პარამეტრების დამმუშავებელი ფუნქციის სწორი სიგნატურაა %s." -#: commands/opclasscmds.c:1258 +#: commands/opclasscmds.c:1259 #, c-format -msgid "btree comparison functions must have two arguments" -msgstr "ორობითი ხის შედარებით ფუნქციებს ორი არგუმენტი უნდა ჰქონდეთ" +msgid "ordering comparison functions must have two arguments" +msgstr "დალაგების მნიშვნელობის ფუნქციებს ორი არგუმენტი უნდა ჰქონდეს" -#: commands/opclasscmds.c:1262 +#: commands/opclasscmds.c:1263 #, c-format -msgid "btree comparison functions must return integer" -msgstr "ორობითი ხის შედარებით ფუნქციებმა ორი მთელი რიცხვი უნდა დააბრუნოს" +msgid "ordering comparison functions must return integer" +msgstr "დალაგების მნიშვნელობის ფუნქციები მთელ რიცხვს უნდა აბრუნდებდეს" -#: commands/opclasscmds.c:1279 +#: commands/opclasscmds.c:1280 #, c-format -msgid "btree sort support functions must accept type \"internal\"" -msgstr "ორობითი ხის დალაგების ფუნქციები უნდა იღებდნენ ტიპს \"internal\"" +msgid "ordering sort support functions must accept type \"internal\"" +msgstr "დალაგების მხარდაჭერის ფუნქციების დალაგებას \"internal\" ტიპის ცვლადის მიღება უნდა შეეძლოს" -#: commands/opclasscmds.c:1283 +#: commands/opclasscmds.c:1284 #, c-format -msgid "btree sort support functions must return void" -msgstr "ორობითი ხის დალაგების ფუნქციებმა არაფერი უნდა დააბრუნონ" +msgid "ordering sort support functions must return void" +msgstr "დალაგების მხარდაჭერის ფუნქციების დალაგება მნიშვნელობას არ უნდა აბრუნებდეს" -#: commands/opclasscmds.c:1294 +#: commands/opclasscmds.c:1295 #, c-format -msgid "btree in_range functions must have five arguments" -msgstr "btree in_range ფუნქციებს 5 არგუმენტი უნდა ჰქონდეთ" +msgid "ordering in_range functions must have five arguments" +msgstr "in_range ფუნქციების დალაგებას ორი არგუმენტი უნდა ჰქონდეს" -#: commands/opclasscmds.c:1298 +#: commands/opclasscmds.c:1299 #, c-format -msgid "btree in_range functions must return boolean" -msgstr "ორობითი ხის in_range ფუნქციები ლოგიკურ მნიშვნელობებს უნდა აბრუნებდნენ" +msgid "ordering in_range functions must return boolean" +msgstr "in_range ფუნქციების დალაგება ბულევურ მნიშვნელობას უნდა აბრუნებდეს" -#: commands/opclasscmds.c:1314 +#: commands/opclasscmds.c:1315 #, c-format -msgid "btree equal image functions must have one argument" -msgstr "ორობითი ტოლობის ასლის ფუნქციებს ერთი არგუმენტი უნდა ჰქონდეთ" +msgid "ordering equal image functions must have one argument" +msgstr "ტოლი ასლი ფუნქციების დალაგებას ერთი არგუმენტი უნდა ჰქონდეს" -#: commands/opclasscmds.c:1318 +#: commands/opclasscmds.c:1319 #, c-format -msgid "btree equal image functions must return boolean" -msgstr "ორობითი ტოლობის ასლის ფუნქციებმა ლოგიკური მნიშვნელობა უნდა დააბრუნონ" +msgid "ordering equal image functions must return boolean" +msgstr "ტოლი ასლი ფუნქციების დალაგება ბულევურ მნიშვნელობას უნდა აბრუნებდეს" -#: commands/opclasscmds.c:1331 +#: commands/opclasscmds.c:1332 #, c-format -msgid "btree equal image functions must not be cross-type" -msgstr "ორობითი ტოლობის ასლის ფუნქციები ჯვარედინი ტიპის არ უნდა იყოს" +msgid "ordering equal image functions must not be cross-type" +msgstr "ტოლი ასლი ფუნქციების დალაგება ჯვარედინი ტიპის არ უნდა იყოს" -#: commands/opclasscmds.c:1341 +#: commands/opclasscmds.c:1340 +#, c-format +msgid "btree skip support functions must accept type \"internal\"" +msgstr "btree-ის გამოტოვების მხარდაჭერის ფუნქცია უნდა იღებდეს ტიპს \"internal\"" + +#: commands/opclasscmds.c:1344 +#, c-format +msgid "btree skip support functions must return void" +msgstr "btree-ის გამოტოვების მხარდაჭერის ფუნქცია ცარიელ მნიშვნელობას უნდა აბრუნებდეს" + +#: commands/opclasscmds.c:1357 +#, c-format +msgid "btree skip support functions must not be cross-type" +msgstr "btree-ის გამოტოვების მხარდაჭერის ფუნქციები ჯვარედინი ტიპის არ უნდა იყოს" + +#: commands/opclasscmds.c:1367 #, c-format msgid "hash function 1 must have one argument" msgstr "ჰეშის ფუნქცია 1-ს ერთი არგუმენტი უნდა ჰქონდეს" -#: commands/opclasscmds.c:1345 +#: commands/opclasscmds.c:1371 #, c-format msgid "hash function 1 must return integer" msgstr "ჰეშის ფუნქცია 1-მა მთელი რიცხვი უნდა დააბრუნოს" -#: commands/opclasscmds.c:1352 +#: commands/opclasscmds.c:1378 #, c-format msgid "hash function 2 must have two arguments" msgstr "ჰეშის ფუნქცია 2-ს ორი არგუმენტი უნდა ჰქონდეს" -#: commands/opclasscmds.c:1356 +#: commands/opclasscmds.c:1382 #, c-format msgid "hash function 2 must return bigint" msgstr "ჰეშის ფუნქცია 2-მა bigint უნდა დააბრინოს" -#: commands/opclasscmds.c:1381 +#: commands/opclasscmds.c:1407 #, c-format msgid "associated data types must be specified for index support function" msgstr "ინდექსის მხარდაჭერის ფუნქციისთვის ასოცირებული მონაცემის ტიპების მითითება აუცილებელია" -#: commands/opclasscmds.c:1406 +#: commands/opclasscmds.c:1432 #, c-format msgid "function number %d for (%s,%s) appears more than once" msgstr "ფუნქციის ნომერი %d (%s,%s)-სთვის ერთზე მეტჯერ ჩნდება" -#: commands/opclasscmds.c:1413 +#: commands/opclasscmds.c:1439 #, c-format msgid "operator number %d for (%s,%s) appears more than once" msgstr "ოპერატორის ნომერი %d (%s,%s)-სთვის ერთზე მეტჯერ ჩნდება" -#: commands/opclasscmds.c:1459 +#: commands/opclasscmds.c:1485 #, c-format msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "ოპერატორი %d(%s,%s) ოპერატორის ოჯახში \"%s\" უკვე არსებობს" -#: commands/opclasscmds.c:1565 +#: commands/opclasscmds.c:1614 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "ფუნქცია %d(%s,%s) ოპერატორის ოჯახში \"%s\" უკვე არსებობს" -#: commands/opclasscmds.c:1646 +#: commands/opclasscmds.c:1769 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "ოპერატორი %d(%s,%s) ოპერატორის ოჯახში \"%s\" არ არსებობს" -#: commands/opclasscmds.c:1686 +#: commands/opclasscmds.c:1809 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "ფუნქცია %d(%s,%s) ოპერატორის ოჯახში \"%s\" არ არსებობს" -#: commands/opclasscmds.c:1717 +#: commands/opclasscmds.c:1840 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "ოპერატორის კლასი \"%s\" წვდომის მეთოდისთვის \"%s\" სქემაში \"%s\" უკვე არსებობს" -#: commands/opclasscmds.c:1740 +#: commands/opclasscmds.c:1863 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "ოპერატორის ოჯახი \"%s\" წვდომის მეთოდისთვის \"%s\" სქემაში \"%s\" უკვე არსებობს" @@ -9301,7 +9367,7 @@ msgstr "ოპერატორის ატრიბუტის შეცვ msgid "operator attribute \"%s\" cannot be changed if it has already been set" msgstr "ოპერატორის ატრიბუტს \"%s\", თუ ის უკვე დაყენებულია, ვერ შეცვლით" -#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 commands/tablecmds.c:1728 commands/tablecmds.c:2328 commands/tablecmds.c:3675 commands/tablecmds.c:6613 commands/tablecmds.c:9645 commands/tablecmds.c:17665 commands/tablecmds.c:17700 commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1442 rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 commands/tablecmds.c:1800 commands/tablecmds.c:2400 commands/tablecmds.c:3824 commands/tablecmds.c:6793 commands/tablecmds.c:10089 commands/tablecmds.c:19498 commands/tablecmds.c:19533 commands/trigger.c:318 commands/trigger.c:1337 commands/trigger.c:1447 rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "წვდომა აკრძალულია: '%s\" სისტემური კატალოგია" @@ -9341,52 +9407,52 @@ msgstr "წესი \"%s\" ცხრილისთვის \"%s\" არ ა msgid "only USING expression allowed for SELECT, DELETE" msgstr "\"SELECT\" და DELETE-სთვის მხოლოდ USING გამოსახულებაა ნებადართული" -#: commands/portalcmds.c:60 commands/portalcmds.c:181 commands/portalcmds.c:232 +#: commands/portalcmds.c:63 commands/portalcmds.c:192 commands/portalcmds.c:243 #, c-format msgid "invalid cursor name: must not be empty" msgstr "კურსორის არასწორი სახელი. ცარიელი არ უნდა იყოს" -#: commands/portalcmds.c:72 +#: commands/portalcmds.c:75 #, c-format msgid "cannot create a cursor WITH HOLD within security-restricted operation" msgstr "უსაფრთხოებაზე-შეზღუდული ოპერაციის შიგნით კურსორს WITH HOLD ვერ შექმნით" -#: commands/portalcmds.c:189 commands/portalcmds.c:242 executor/execCurrent.c:70 utils/adt/xml.c:2873 utils/adt/xml.c:3043 +#: commands/portalcmds.c:200 commands/portalcmds.c:253 executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "კურსორი \"%s\" არ არსებობს" -#: commands/prepare.c:72 +#: commands/prepare.c:75 #, c-format msgid "invalid statement name: must not be empty" msgstr "ოეპრატორის არასწორი სახელი: ცარიელი არ უნდა იყოს" -#: commands/prepare.c:227 commands/prepare.c:232 +#: commands/prepare.c:231 commands/prepare.c:236 #, c-format msgid "prepared statement is not a SELECT" msgstr "მომზადებული ოპერატორი SELECT არაა" -#: commands/prepare.c:292 +#: commands/prepare.c:296 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "პარამეტრების არასწორი რაოდენობა მომზადებული გამოსახულებისთვის \"%s\"" -#: commands/prepare.c:294 +#: commands/prepare.c:298 #, c-format msgid "Expected %d parameters but got %d." msgstr "მოსალოდნელი %d პარამეტრის მაგიერ მივიღე %d." -#: commands/prepare.c:327 +#: commands/prepare.c:331 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "" -#: commands/prepare.c:411 +#: commands/prepare.c:415 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "მომზადებული ოპერატორი \"%s\" უკვე არსებობს" -#: commands/prepare.c:450 +#: commands/prepare.c:454 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "მომზადებული ოპერატორი \"%s\" არ არსებობს" @@ -9396,200 +9462,205 @@ msgstr "მომზადებული ოპერატორი \"%s\" ა msgid "must be superuser to create custom procedural language" msgstr "პროცედურული ენის ხელით მისათითებლად ზემომხმარებლის პრივილეგიებია საჭირო" -#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 postmaster/postmaster.c:1210 utils/init/miscinit.c:1811 +#: commands/publicationcmds.c:130 libpq/auth-oauth.c:850 postmaster/postmaster.c:1130 postmaster/postmaster.c:1232 utils/init/miscinit.c:1870 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "არასწორი სიის სინტაქსი პარამეტრში \"%s\"" -#: commands/publicationcmds.c:143 +#: commands/publicationcmds.c:149 #, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" msgstr "პუბლიკაციის პარამეტრის (\"%s\") უცნობი მნიშვნელობა: \"%s\"" -#: commands/publicationcmds.c:157 +#: commands/publicationcmds.c:170 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "პუბლიკაციის უცნობი პარამეტრი: \"%s\"" -#: commands/publicationcmds.c:198 +#: commands/publicationcmds.c:211 #, c-format msgid "no schema has been selected for CURRENT_SCHEMA" msgstr "'CURRENT_SCHEMA'-სთვის სქემა არჩეული არაა" -#: commands/publicationcmds.c:495 +#: commands/publicationcmds.c:592 msgid "System columns are not allowed." msgstr "სისტემური სვეტები დაუშვებელია." -#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 commands/publicationcmds.c:524 +#: commands/publicationcmds.c:599 commands/publicationcmds.c:604 commands/publicationcmds.c:621 msgid "User-defined operators are not allowed." msgstr "მომხმარებლის მიერ აღწერილი ოპერატორები დაშვებული არაა." -#: commands/publicationcmds.c:548 +#: commands/publicationcmds.c:645 msgid "Only columns, constants, built-in operators, built-in data types, built-in collations, and immutable built-in functions are allowed." msgstr "დაშვებულია მხოლოდ სვეტები, მუდმივები, ჩაშენებული ოპერატორები, ჩაშენებული მონაცემის ტიპები, ჩაშენებული კოლაციები და არადადუმებადი ჩაშენებული ფუნქციები." -#: commands/publicationcmds.c:560 +#: commands/publicationcmds.c:657 msgid "User-defined types are not allowed." msgstr "მომხმარებლის მიერ განსაზღვრული ტიპები დაშვებული არაა." -#: commands/publicationcmds.c:563 +#: commands/publicationcmds.c:660 msgid "User-defined or built-in mutable functions are not allowed." msgstr "მომხმარებლის-მიერ-აღწერილი ან ჩაშენებული დადუმებადი ფუნქციები დაშვებული არაა." -#: commands/publicationcmds.c:566 +#: commands/publicationcmds.c:663 msgid "User-defined collations are not allowed." msgstr "მომხმარებლის მიერ განსაზღვრული კოლაციები დაუშვებელია." -#: commands/publicationcmds.c:576 +#: commands/publicationcmds.c:673 #, c-format msgid "invalid publication WHERE expression" msgstr "პუბლიკაციის არასწორი WHERE გამოსახულება" -#: commands/publicationcmds.c:629 +#: commands/publicationcmds.c:726 #, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" msgstr "ურთიერთობისთვის \"%s\"გამოცემის პირობას WHERE ვერ გამოიყენებთ" -#: commands/publicationcmds.c:631 +#: commands/publicationcmds.c:728 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." msgstr "დაყოფილ ცხრილზე პირობის WHERE გამოყენება შეუძლებელია, როცა %s ჭეშმარიტი არაა." -#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 +#: commands/publicationcmds.c:801 commands/publicationcmds.c:815 #, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" msgstr "შეუძლებელია სვეტების სიის გამოყენება ურთიერთობისთვის \"%s.%s\" პუბლიკაციაში \"%s\"" -#: commands/publicationcmds.c:705 +#: commands/publicationcmds.c:804 #, c-format msgid "Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements." msgstr "გამოცემებში რომლებიც ელემენტებს FOR TABLES IN SCHEMA შეიცავენ, სვეტების სიას ვერ მიუთითებთ." -#: commands/publicationcmds.c:719 +#: commands/publicationcmds.c:818 #, c-format msgid "Column lists cannot be specified for partitioned tables when %s is false." msgstr "სვეტების სია შეუძლებელია მიუთითოთ დაყოფილ ცხრილს, როცა %s false-ა." -#: commands/publicationcmds.c:754 +#: commands/publicationcmds.c:855 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "'FOR ALL TABLES' პუბლიკაციის შექმნისთვის ზემომხმარებლის უფლებები აუცილებელია" -#: commands/publicationcmds.c:825 +#: commands/publicationcmds.c:930 #, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" msgstr "\"FOR TABLES IN SCHEMA\" პუბლიკაციის შესაქმნელად ზემომხმარებელი უნდა ბრძანდებოდეთ" -#: commands/publicationcmds.c:861 +#: commands/publicationcmds.c:966 #, c-format msgid "\"wal_level\" is insufficient to publish logical changes" msgstr "\"wal_level\" არასაკმარისია ლოგიკური ცვლილებების გამოსაქვეყნებლად" -#: commands/publicationcmds.c:862 +#: commands/publicationcmds.c:967 #, c-format msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." msgstr "გამოწერების შექმნამდე საჭიროა \"wal_level\" -ის \"logical\" (ლოგიკურზე) დაყენება." -#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 +#: commands/publicationcmds.c:1067 commands/publicationcmds.c:1075 #, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" msgstr "პარამეტრის (\"%s\") false-ზე დაყენება პუბლიკაციისთვის \"%s\" შეუძლებელია" -#: commands/publicationcmds.c:961 +#: commands/publicationcmds.c:1070 #, c-format msgid "The publication contains a WHERE clause for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "გამოცემა შეიცავს პირობას WHERE დაყოფილი ცხრილისთვის \"%s\", რაც, მაშინ, როცა \"%s\" ჭეშმარიტი არა, დაშვებული არაა." -#: commands/publicationcmds.c:969 +#: commands/publicationcmds.c:1078 #, c-format msgid "The publication contains a column list for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "გამოცემა შეიცავს სვეტების სიას დაყოფილი ცხრილისთვის \"%s\", რაც მაშინ, როცა \"%s\" ჭეშმარიტი არაა, დაუშვებელია." -#: commands/publicationcmds.c:1292 +#: commands/publicationcmds.c:1399 #, c-format msgid "cannot add schema to publication \"%s\"" msgstr "პუბლიკაციისთვის (%s) სქემის დამატება შეუძლებელია" -#: commands/publicationcmds.c:1294 +#: commands/publicationcmds.c:1401 #, c-format msgid "Schemas cannot be added if any tables that specify a column list are already part of the publication." msgstr "სქემების დამატება შეუძლებელია, თუ ნებისმიერი ცხრილი, რომელიც შეიცავს სვეტების სიას, რომელიც უკვე გამოცემის ნაწილია." -#: commands/publicationcmds.c:1342 +#: commands/publicationcmds.c:1449 #, c-format msgid "must be superuser to add or set schemas" msgstr "სქემის დამატების ან დაყენებისთვის ზემომხმარებლის უფლებებია საჭირო" -#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 +#: commands/publicationcmds.c:1458 commands/publicationcmds.c:1466 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "პუბლიკაცია %s აღწერილია, როგორც FOR ALL TABLES" -#: commands/publicationcmds.c:1353 +#: commands/publicationcmds.c:1460 #, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." msgstr "სქემების FOR ALL TABLES გამოცემებიდან წაშლა ან მასში ჩამატება შეუძლებელია." -#: commands/publicationcmds.c:1361 +#: commands/publicationcmds.c:1468 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "FOR ALL TABLES გამოცემებში ცხრილების ჩამატება ან მათი წაშლა შეუძლებელია." -#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 +#: commands/publicationcmds.c:1492 commands/publicationcmds.c:1531 commands/publicationcmds.c:2068 utils/cache/lsyscache.c:3774 #, c-format msgid "publication \"%s\" does not exist" msgstr "პუბლიკაცია \"%s\" არ არსებობს" -#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 +#: commands/publicationcmds.c:1694 commands/publicationcmds.c:1757 #, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" msgstr "კონფლიქტური ან ზედმეტი WHERE პირობები ცხრილისთვის \"%s\"" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 +#: commands/publicationcmds.c:1701 commands/publicationcmds.c:1769 #, c-format msgid "conflicting or redundant column lists for table \"%s\"" msgstr "კონფლიქტური ან ზედმეტი სვეტის სიები ცხრილისთვის \"%s\"" -#: commands/publicationcmds.c:1796 +#: commands/publicationcmds.c:1903 #, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" msgstr "column list must not be specified in ALTER PUBLICATION ... DROP" -#: commands/publicationcmds.c:1808 +#: commands/publicationcmds.c:1915 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "ურთიერთობა (%s) პუბლიკაციის ნაწილს არ წარმოადგენს" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1922 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "გამოცემის ცხრილიდან წაშლისას პირობას WHERE ვერ გამოიყენებთ" -#: commands/publicationcmds.c:1875 +#: commands/publicationcmds.c:1982 #, c-format msgid "tables from schema \"%s\" are not part of the publication" msgstr "ცხრილი სქემიდან \"%s\" პუბლიკაციის ნაწილს არ წარმოადგენს" -#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 +#: commands/publicationcmds.c:2025 commands/publicationcmds.c:2032 #, c-format msgid "permission denied to change owner of publication \"%s\"" msgstr "პუბლიკაციის (%s) მფლობელის შეცვლის წვდომა აკრძალულია" -#: commands/publicationcmds.c:1920 +#: commands/publicationcmds.c:2027 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "FOR ALL TABLES გამოცემის მფლობელი ზემომხმარებელი უნდა იყოს." -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:2034 #, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." msgstr "FOR TABLES IN SCHEMA პუბლიკაციის მფლობელი ზემომხმარებელი უნდა იყოს." -#: commands/publicationcmds.c:1993 +#: commands/publicationcmds.c:2100 #, c-format msgid "publication with OID %u does not exist" msgstr "პუბლიკაცია OID-ით %u არ არსებობს" +#: commands/publicationcmds.c:2133 +#, c-format +msgid "%s requires a \"none\" or \"stored\" value" +msgstr "%s მოითხოვს მნიშვნელობას \"none' ან \"stored\"" + #: commands/schemacmds.c:109 commands/schemacmds.c:289 #, c-format msgid "unacceptable schema name \"%s\"" @@ -9630,127 +9701,127 @@ msgstr "ამ ტიპის ობიექტისთვის უსაფ msgid "cannot set security label on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" უსაფრთხოების ჭდის დადება შეუძლებელია" -#: commands/sequence.c:741 +#: commands/sequence.c:748 #, c-format -msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" -msgstr "nextval: მიღწეულია მაქსიმალური მნიშვნელობა მიმდევრობისთვის \"%s\" (%lld)" +msgid "nextval: reached maximum value of sequence \"%s\" (%)" +msgstr "nextval: მიღწეულია მაქსიმალური მნიშვნელობა მიმდევრობისთვის \"%s\" (%)" -#: commands/sequence.c:760 +#: commands/sequence.c:767 #, c-format -msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" -msgstr "nextval: მიღწეულია მინიმალური მნიშვნელობა მიმდევრობისთვის \"%s\" (%lld)" +msgid "nextval: reached minimum value of sequence \"%s\" (%)" +msgstr "nextval: მიღწეულია მინიმალური მნიშვნელობა მიმდევრობისთვის \"%s\" (%)" -#: commands/sequence.c:879 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "მიმდევრობის \"%s\" მიმდინარე მნიშვნელობა ამ სესიაში ჯერ აღწერილი არაა" -#: commands/sequence.c:898 commands/sequence.c:904 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "ამ სესიაში lastval ჯერ აღწერილი არაა" -#: commands/sequence.c:984 +#: commands/sequence.c:991 #, c-format -msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" -msgstr "setval: მნიშვნელობა %lld საზღვრებს გარეთაა მიმდევრობისთვის \"%s\" (%lld..%lld)" +msgid "setval: value % is out of bounds for sequence \"%s\" (%..%)" +msgstr "setval: მნიშვნელობა % საზღვრებს გარეთაა მიმდევრობისთვის \"%s\" (%..%)" -#: commands/sequence.c:1347 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "მიმდევრობის არასწორი პარამეტრი SEQUENCE NAME" -#: commands/sequence.c:1373 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "იდენტიფიკაციის სვეტის ტიპი smallint, integer ან bigint უნდა იყოს" -#: commands/sequence.c:1374 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "მიმდევრობის ტიპი smallint, integer ან bigint უნდა იყოს" -#: commands/sequence.c:1408 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENT ნული არ უნდა იყოს" -#: commands/sequence.c:1456 +#: commands/sequence.c:1466 #, c-format -msgid "MAXVALUE (%lld) is out of range for sequence data type %s" -msgstr "MAXVALUE (%lld) მიმდევრობის მონაცემის ტიპის დიაპაზონს გარეთაა %s" +msgid "MAXVALUE (%) is out of range for sequence data type %s" +msgstr "MAXVALUE (%) მიმდევრობის მონაცემის ტიპის დიაპაზონს გარეთაა %s" -#: commands/sequence.c:1488 +#: commands/sequence.c:1498 #, c-format -msgid "MINVALUE (%lld) is out of range for sequence data type %s" -msgstr "MINVALUE (%lld) მიმდევრობის მონაცემის ტიპის დიაპაზონს გარეთაა %s" +msgid "MINVALUE (%) is out of range for sequence data type %s" +msgstr "MINVALUE (%) მიმდევრობის მონაცემის ტიპის დიაპაზონს გარეთაა %s" -#: commands/sequence.c:1496 +#: commands/sequence.c:1506 #, c-format -msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" -msgstr "MINVALUE (%lld)-ი MAXVALUE (%lld)-ზე ნაკლები არ უნდა იყოს" +msgid "MINVALUE (%) must be less than MAXVALUE (%)" +msgstr "MINVALUE (%)-ი MAXVALUE (%)-ზე ნაკლები არ უნდა იყოს" -#: commands/sequence.c:1517 +#: commands/sequence.c:1527 #, c-format -msgid "START value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "START -ის მნიშვნელობა (%lld)-ი MINVALUE (%lld)-ზე ნაკლები არ უნდა იყოს" +msgid "START value (%) cannot be less than MINVALUE (%)" +msgstr "START -ის მნიშვნელობა (%)-ი MINVALUE (%)-ზე ნაკლები არ უნდა იყოს" -#: commands/sequence.c:1523 +#: commands/sequence.c:1533 #, c-format -msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "START -ის მნიშვნელობა (%lld)-ი MAXVALUE (%lld)-ზე მეტი არ უნდა იყოს" +msgid "START value (%) cannot be greater than MAXVALUE (%)" +msgstr "START -ის მნიშვნელობა (%)-ი MAXVALUE (%)-ზე მეტი არ უნდა იყოს" -#: commands/sequence.c:1547 +#: commands/sequence.c:1557 #, c-format -msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" -msgstr "RESTART -ის მნიშვნელობა (%lld) MINVALUE (%lld)-ზე ნაკლები არ უნდა იყოს" +msgid "RESTART value (%) cannot be less than MINVALUE (%)" +msgstr "RESTART -ის მნიშვნელობა (%) MINVALUE (%)-ზე ნაკლები არ უნდა იყოს" -#: commands/sequence.c:1553 +#: commands/sequence.c:1563 #, c-format -msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" -msgstr "RESTART -ის მნიშვნელობა (%lld) MAXVALUE (%lld)-ზე დიდი არ უნდა იყოს" +msgid "RESTART value (%) cannot be greater than MAXVALUE (%)" +msgstr "RESTART -ის მნიშვნელობა (%) MAXVALUE (%)-ზე დიდი არ უნდა იყოს" -#: commands/sequence.c:1564 +#: commands/sequence.c:1574 #, c-format -msgid "CACHE (%lld) must be greater than zero" -msgstr "CACHE (%lld) ნულზე მეტი უნდა იყოს" +msgid "CACHE (%) must be greater than zero" +msgstr "CACHE (%) ნულზე მეტი უნდა იყოს" -#: commands/sequence.c:1600 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "არასწორი პარამეტრი OWNED BY" -#: commands/sequence.c:1601 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "მიუთითეთ OWNED BY ცხრილი.სვეტი ან OWNED BY NONE." -#: commands/sequence.c:1626 +#: commands/sequence.c:1636 #, c-format msgid "sequence cannot be owned by relation \"%s\"" msgstr "მიმდევრობის მფლობელი ურთიერთობა %s ვერ იქნება" -#: commands/sequence.c:1634 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "მიმდევრობას იგივე მფლობელი უნდა ჰყავდეს, რაც ცხრილს, რომელზედაც ის მიბმულია" -#: commands/sequence.c:1638 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "მიმდევრობას იგივე სქემა უნდა ჰქონდეს, რაც ცხრილს, რომელზედაც ის მიბმულია" -#: commands/sequence.c:1660 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "იდენტიფიკაციის მიმდევრობის მფლობელის შეცვლა შეუძლებელია" -#: commands/sequence.c:1661 commands/tablecmds.c:14387 commands/tablecmds.c:17081 +#: commands/sequence.c:1671 commands/tablecmds.c:16069 commands/tablecmds.c:18907 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "მიმდევრობა %s მიბმულია ცხრილზე \"%s\"." -#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1886 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "'CREATE STATISTICS'-ში მხოლოდ ერთი ურთიერთობაა დაშვებული" @@ -9775,1756 +9846,1912 @@ msgstr "სტატისტიკის ობიექტი უკვე ა msgid "cannot have more than %d columns in statistics" msgstr "სტატისტიკაში %d-ზე მეტი სვეტი ვერ გექნებათ" -#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 +#: commands/statscmds.c:247 commands/statscmds.c:276 commands/statscmds.c:316 #, c-format msgid "statistics creation on system columns is not supported" msgstr "სისტემურ სვეტებზე სტატისტიკის შექმნა შეუძლებელია" -#: commands/statscmds.c:254 commands/statscmds.c:277 +#: commands/statscmds.c:253 commands/statscmds.c:282 commands/statscmds.c:322 +#, c-format +msgid "statistics creation on virtual generated columns is not supported" +msgstr "ვირტუალურ გენერირებულ სვეტებზე სტატისტიკის შექმნა მხარდაჭერილი არაა" + +#: commands/statscmds.c:260 commands/statscmds.c:289 #, c-format msgid "column \"%s\" cannot be used in statistics because its type %s has no default btree operator class" msgstr "სვეტს \"%s\" სტატისტიკაში ვერ გამოიყენებთ, რადგან მის ტიპს (\"%s\") ნაგულისხმევი ორობითი ხის ოპერატორის კლასი არ გააჩნია" -#: commands/statscmds.c:321 +#: commands/statscmds.c:339 #, c-format msgid "expression cannot be used in multivariate statistics because its type %s has no default btree operator class" msgstr "" -#: commands/statscmds.c:342 +#: commands/statscmds.c:360 #, c-format msgid "when building statistics on a single expression, statistics kinds may not be specified" msgstr "როცა სტატისტიკის აგება ერთ გამოსახულებაზე მიმდინარეობს, სტატისტიკის ტიპის მითითება შეუძლებელია" -#: commands/statscmds.c:371 +#: commands/statscmds.c:389 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "სტატისტიკის უცნობი ტიპი: \"%s\"" -#: commands/statscmds.c:400 +#: commands/statscmds.c:418 #, c-format msgid "extended statistics require at least 2 columns" msgstr "გაფართოებულ სტატისტიკას მინიმუმ 2 სვეტი სჭირდება" -#: commands/statscmds.c:418 +#: commands/statscmds.c:436 #, c-format msgid "duplicate column name in statistics definition" msgstr "სვეტის დუბლირებული სახელი სტატისტიკის აღწერაში" -#: commands/statscmds.c:453 +#: commands/statscmds.c:471 #, c-format msgid "duplicate expression in statistics definition" msgstr "დუბლირებული გამოსახულება სტატისტიკის აღწერაში" -#: commands/statscmds.c:628 commands/tablecmds.c:8628 +#: commands/statscmds.c:646 commands/tablecmds.c:8914 #, c-format msgid "statistics target %d is too low" msgstr "სტატისტიკის სამიზნე %d ძალიან დაბალია" -#: commands/statscmds.c:636 commands/tablecmds.c:8636 +#: commands/statscmds.c:654 commands/tablecmds.c:8922 #, c-format msgid "lowering statistics target to %d" msgstr "სტატისტიკის სამიზნის ჩამოწევა %d-მდე" -#: commands/statscmds.c:660 +#: commands/statscmds.c:678 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "სტატისტიკის ობიექტი \"%s.%s\" არ არსებობს, გამოტოვება" -#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 -#, c-format -msgid "unrecognized subscription parameter: \"%s\"" -msgstr "უცნობი გამოწერის პარამეტრი: \"%s\"" - -#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:397 +#: commands/subscriptioncmds.c:331 replication/pgoutput/pgoutput.c:410 #, c-format msgid "unrecognized origin value: \"%s\"" msgstr "\"origin\"-ის უცნობი მნიშვნელობა: \"%s\"" -#: commands/subscriptioncmds.c:363 +#: commands/subscriptioncmds.c:354 #, c-format msgid "invalid WAL location (LSN): %s" msgstr "\"WAL\"-ის არასწორი მდებარეობა (LSN): %s" +#: commands/subscriptioncmds.c:363 +#, c-format +msgid "unrecognized subscription parameter: \"%s\"" +msgstr "უცნობი გამოწერის პარამეტრი: \"%s\"" + #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 commands/subscriptioncmds.c:439 +#: commands/subscriptioncmds.c:378 commands/subscriptioncmds.c:385 commands/subscriptioncmds.c:392 commands/subscriptioncmds.c:414 commands/subscriptioncmds.c:430 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "%s და %s ურთიერთგამომრიცხავი პარამეტრებია" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 +#: commands/subscriptioncmds.c:420 commands/subscriptioncmds.c:436 #, c-format msgid "subscription with %s must also set %s" msgstr "%s-ის გამოწერამ %s-იც უნდა დააყენოს" -#: commands/subscriptioncmds.c:506 +#: commands/subscriptioncmds.c:466 #, c-format msgid "could not receive list of publications from the publisher: %s" msgstr "გამომცემლისგან პუბლიკაციების სიის მიღება შეუძლებელია: %s" -#: commands/subscriptioncmds.c:538 +#: commands/subscriptioncmds.c:498 #, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" msgstr[0] "პუბლიკაცია \"%s\" არ არსებობს" msgstr[1] "პუბლიკაცია \"%s\" არ არსებობს" -#: commands/subscriptioncmds.c:626 +#: commands/subscriptioncmds.c:586 #, c-format msgid "permission denied to create subscription" msgstr "გამოწერის შექმნის წვდომა აკრძალულია" -#: commands/subscriptioncmds.c:627 +#: commands/subscriptioncmds.c:587 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." msgstr "გამოწერების შექმნა მხოლოდ \"%s\" როლის პრივილეგიების მქონეებს შეუძლიათ." -#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 replication/logical/worker.c:4503 +#: commands/subscriptioncmds.c:718 commands/subscriptioncmds.c:852 commands/subscriptioncmds.c:1594 #, c-format -msgid "could not connect to the publisher: %s" -msgstr "პუბლიკაციის სერვერთან მიერთების პრობლემა: %s" +msgid "subscription \"%s\" could not connect to the publisher: %s" +msgstr "გამოწერა \"%s\" ვერ უერთდება გამომცემელს: %s" -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:790 #, c-format msgid "created replication slot \"%s\" on publisher" msgstr "გამომცემელზე შექმნილია რეპლიკაციის სეტი \"%s\"" -#: commands/subscriptioncmds.c:841 +#: commands/subscriptioncmds.c:802 #, c-format msgid "subscription was created, but is not connected" msgstr "გამოწერა შეიქმნა, მაგრამ მიერთებული არაა" -#: commands/subscriptioncmds.c:842 +#: commands/subscriptioncmds.c:803 #, c-format msgid "To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription." msgstr "რეპლიკაციის დასაწყებად ხელით უნდა შექმნათ რეპლიკაციის სლოტი, ჩართოთ გამოწერა და განაახლოთ გამოწერა." -#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 +#: commands/subscriptioncmds.c:1070 +#, c-format +msgid "cannot set option \"%s\" for enabled subscription" +msgstr "ჩართული გამოწერისთვის პარამეტრის \"%s\" დაყენება შეუძლებელია" + +#: commands/subscriptioncmds.c:1084 +#, c-format +msgid "cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "გამოწერებისთვის, რომლებსაც სლოტის სახელი არ აქვთ, პარამეტრს %s ვერ დავაყენებ" + +#: commands/subscriptioncmds.c:1127 commands/subscriptioncmds.c:1663 commands/subscriptioncmds.c:2044 utils/cache/lsyscache.c:3824 #, c-format msgid "subscription \"%s\" does not exist" msgstr "გამოწერა \"%s\" არ არსებობს" -#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 +#: commands/subscriptioncmds.c:1185 #, c-format msgid "cannot set %s for enabled subscription" msgstr "ჩართული გამოწერისთვის %s-ის დაყენება შეუძლებელია" -#: commands/subscriptioncmds.c:1233 +#: commands/subscriptioncmds.c:1270 +#, c-format +msgid "slot_name and two_phase cannot be altered at the same time" +msgstr "slot_name და two_phase ერთდროულად ვერ შეიცვლება" + +#: commands/subscriptioncmds.c:1286 +#, c-format +msgid "cannot alter two_phase when logical replication worker is still running" +msgstr "two_phase-ის შეცვლა შეუძლებელია, როცა ლოგიკური რეპლიკაციის დამხმარე პროცესი ჯერ კიდევ გაშვებულია" + +#: commands/subscriptioncmds.c:1287 +#, c-format +msgid "Try again after some time." +msgstr "სცადეთ კიდევ ერთხელ რაღაც დროის შემდეგ." + +#: commands/subscriptioncmds.c:1300 #, c-format -msgid "cannot set %s for a subscription that does not have a slot name" -msgstr "გამოწერებისთვის, რომლებსაც სლოტის სახელი არ აქვთ, %s-ს ვერ დავაყენებ" +msgid "cannot disable two_phase when prepared transactions are present" +msgstr "" + +#: commands/subscriptioncmds.c:1301 +#, c-format +msgid "Resolve these transactions and try again." +msgstr "გადაწყვიტეთ ეს ტრანზაქციები და თავიდან სცადეთ." -#: commands/subscriptioncmds.c:1279 +#: commands/subscriptioncmds.c:1348 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "გამოწერების, რომლებსაც სლოტის სახელი არ აქვთ, ჩართვა შეუძლებელია" -#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 +#: commands/subscriptioncmds.c:1392 commands/subscriptioncmds.c:1443 #, c-format msgid "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION განახლებით დაუშვებელია გათიშული გამოწერებისთვის" -#: commands/subscriptioncmds.c:1324 +#: commands/subscriptioncmds.c:1393 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "გამოიყენეთ ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (განახლება = გამორთულია)." -#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 +#: commands/subscriptioncmds.c:1402 commands/subscriptioncmds.c:1457 #, c-format msgid "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase is enabled" msgstr "ALTER SUBSCRIPTION ... განახლებით და copy_data-ით დაუშვებელია, როცა two_phase ჩართულია" -#: commands/subscriptioncmds.c:1334 +#: commands/subscriptioncmds.c:1403 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "გამოიყენეთ ALTER SUBSCRIPTION ... SET PUBLICATION refresh = false-ით, copy_data = false-ით ან გამოიყენეთ DROP/CREATE SUBSCRIPTION." #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1390 +#: commands/subscriptioncmds.c:1459 #, c-format msgid "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "გამოიყენეთ %s 'refresh = false'-ით ან 'copy_data = false'-ით ან გამოიყენეთ DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1412 +#: commands/subscriptioncmds.c:1481 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION ... REFRESH დაუშვებელია გათიშული გამოწერებისთვის" -#: commands/subscriptioncmds.c:1437 +#: commands/subscriptioncmds.c:1506 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase is enabled" msgstr "ALTER SUBSCRIPTION ... REFRESH -ი copy_data-ით დაუშვებელია, როცა two_phase ჩართულია" -#: commands/subscriptioncmds.c:1438 +#: commands/subscriptioncmds.c:1507 #, c-format msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "გამოიყენეთ ALTER SUBSCRIPTION ... REFRESH 'copy_data = false'-ით ან DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1473 +#: commands/subscriptioncmds.c:1542 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "გამოტოვება WAL-ის მდებარეობა (LSN %X/%X) საწყის LSN-ზე %X/%X დიდი უნდა იყოს" -#: commands/subscriptioncmds.c:1594 +#: commands/subscriptioncmds.c:1667 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "გამოწერა \"%s\" არ არსებობს. გამოტოვება" -#: commands/subscriptioncmds.c:1863 +#: commands/subscriptioncmds.c:1934 #, c-format msgid "dropped replication slot \"%s\" on publisher" msgstr "გამომცემელზე რეპლიკაციის სეტი \"%s\" წაშლილია" -#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 +#: commands/subscriptioncmds.c:1943 commands/subscriptioncmds.c:1951 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" msgstr "შეუძლებელია რეპლიკაციის სლოტის \"%s\" წაშლა გამომცემელზე: %s" -#: commands/subscriptioncmds.c:2005 +#: commands/subscriptioncmds.c:2076 #, c-format msgid "subscription with OID %u does not exist" msgstr "გამოწერა OID-ით %u არ არსებობს" -#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 +#: commands/subscriptioncmds.c:2150 commands/subscriptioncmds.c:2274 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" msgstr "შეცდომა რეპლიცირებული ცხრილების სიის მიგება გამომცემლისგან: %s" -#: commands/subscriptioncmds.c:2112 +#: commands/subscriptioncmds.c:2186 #, c-format msgid "subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin" msgstr "" -#: commands/subscriptioncmds.c:2114 +#: commands/subscriptioncmds.c:2188 #, c-format msgid "The subscription being created subscribes to a publication (%s) that contains tables that are written to by other subscriptions." msgid_plural "The subscription being created subscribes to publications (%s) that contain tables that are written to by other subscriptions." msgstr[0] "" msgstr[1] "" -#: commands/subscriptioncmds.c:2117 +#: commands/subscriptioncmds.c:2191 #, c-format msgid "Verify that initial data copied from the publisher tables did not come from other origins." msgstr "" -#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 replication/pgoutput/pgoutput.c:1117 +#: commands/subscriptioncmds.c:2296 replication/logical/tablesync.c:904 replication/pgoutput/pgoutput.c:1162 #, c-format msgid "cannot use different column lists for table \"%s.%s\" in different publications" msgstr "" -#: commands/subscriptioncmds.c:2273 +#: commands/subscriptioncmds.c:2346 #, c-format msgid "could not connect to publisher when attempting to drop replication slot \"%s\": %s" msgstr "რეპლიკაციის სლოტის \"%s\" წაშლის მცდელობისას გამომცემელთან მიერთება შეუძლებელია: %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2276 +#: commands/subscriptioncmds.c:2349 #, c-format msgid "Use %s to disable the subscription, and then use %s to disassociate it from the slot." msgstr "გამოწერის გასათიშად გამოიყენეთ %s, შემდეგ კი, სლოტთან ასოცირების მოსახსნელად, %s გამოიყენეთ." -#: commands/subscriptioncmds.c:2307 +#: commands/subscriptioncmds.c:2380 #, c-format msgid "publication name \"%s\" used more than once" msgstr "პუბლიკაციის სახელი \"%s\" ერთზე მეტჯერ გამოიყენება" -#: commands/subscriptioncmds.c:2351 +#: commands/subscriptioncmds.c:2424 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "პუბლიკაცია \"%s\" უკვე \"%s\" გამოწერაშია" -#: commands/subscriptioncmds.c:2365 +#: commands/subscriptioncmds.c:2438 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "პუბლიკაცია \"%s\" \"%s\" გამოწერაში არაა" -#: commands/subscriptioncmds.c:2376 +#: commands/subscriptioncmds.c:2449 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "გამოწერიდან ყველა პუბლიკაციას ვერ წაშლით" -#: commands/subscriptioncmds.c:2433 +#: commands/subscriptioncmds.c:2506 #, c-format msgid "%s requires a Boolean value or \"parallel\"" msgstr "%s -ს ლოგიკური მნიშვნელობა უნდა ჰქონდეს, ან \"parallel\"" -#: commands/tablecmds.c:255 commands/tablecmds.c:297 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 #, c-format msgid "table \"%s\" does not exist" msgstr "ცხრილი არ არსებობს: %s" -#: commands/tablecmds.c:256 commands/tablecmds.c:298 +#: commands/tablecmds.c:259 commands/tablecmds.c:301 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "ცხრილი \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:258 commands/tablecmds.c:300 +#: commands/tablecmds.c:261 commands/tablecmds.c:303 msgid "Use DROP TABLE to remove a table." msgstr "ცხრილის წასაშლელად გამოიყენეთ DROP TABLE." -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:264 #, c-format msgid "sequence \"%s\" does not exist" msgstr "მიმდევრობა \"%s\" არ არსებობს" -#: commands/tablecmds.c:262 +#: commands/tablecmds.c:265 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "მიმდევრობა \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:267 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "მიმდევრობის წასაშლელად გამოიყენეთ DROP SEQUENCE." -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:270 #, c-format msgid "view \"%s\" does not exist" msgstr "ხედი \"%s\" არ არსებობს" -#: commands/tablecmds.c:268 +#: commands/tablecmds.c:271 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "ხედი \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:270 +#: commands/tablecmds.c:273 msgid "Use DROP VIEW to remove a view." msgstr "ხედის წასაშლელად გამოიყენეთ DROP VIEW." -#: commands/tablecmds.c:273 +#: commands/tablecmds.c:276 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "მატერიალიზებული ხედი \"%s\" არ არსებობს" -#: commands/tablecmds.c:274 +#: commands/tablecmds.c:277 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "მატერიალიზებული ხედი \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:276 +#: commands/tablecmds.c:279 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "მატერიალიზებული ხედის წასაშლელად გამოიყენეთ DROP MATERIALIZED VIEW." -#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19627 parser/parse_utilcmd.c:2226 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 commands/tablecmds.c:21562 parser/parse_utilcmd.c:2407 #, c-format msgid "index \"%s\" does not exist" msgstr "ინდექსი \"%s\" არ არსებობს" -#: commands/tablecmds.c:280 commands/tablecmds.c:304 +#: commands/tablecmds.c:283 commands/tablecmds.c:307 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "ინდექსი \"%s\" არ არსებობს, გამოტოვება" -#: commands/tablecmds.c:282 commands/tablecmds.c:306 +#: commands/tablecmds.c:285 commands/tablecmds.c:309 msgid "Use DROP INDEX to remove an index." msgstr "ინდექსის წასაშლელად გამოიყენეთ DROP INDEX." -#: commands/tablecmds.c:287 +#: commands/tablecmds.c:290 #, c-format msgid "\"%s\" is not a type" msgstr "\"%s\" ტიპი არაა" -#: commands/tablecmds.c:288 +#: commands/tablecmds.c:291 msgid "Use DROP TYPE to remove a type." msgstr "ტიპის წასაშლელად გამოიყენეთ DROP TYPE." -#: commands/tablecmds.c:291 commands/tablecmds.c:14226 commands/tablecmds.c:16786 +#: commands/tablecmds.c:294 commands/tablecmds.c:15908 commands/tablecmds.c:18609 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "გარე ცხრილი \"%s\" არ არსებობს" -#: commands/tablecmds.c:292 +#: commands/tablecmds.c:295 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "გარე ცხრილი \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:294 +#: commands/tablecmds.c:297 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "გარე ცხრილის წასაშლელად DROP FOREIGN TABLE გამოიყენეთ." -#: commands/tablecmds.c:722 +#: commands/tablecmds.c:802 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMIT მხოლოდ დროებით ცხრილებზე გამოიყენება" -#: commands/tablecmds.c:753 +#: commands/tablecmds.c:819 +#, c-format +msgid "partitioned tables cannot be unlogged" +msgstr "დაყოფილი ცხრილების ჟურნალის გამორთვა შეუძლებელია" + +#: commands/tablecmds.c:839 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "უსაფრთხოებაზე-შეზღუდული ოპერაციის შიგნით დროებითი ცხრილის შექმნა შეუძლებელია" -#: commands/tablecmds.c:789 commands/tablecmds.c:15645 +#: commands/tablecmds.c:875 commands/tablecmds.c:17333 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "ურთიერთობა \"%s\" მემკვირდრეობით ერზე მეტჯერ იქნებოდა მიღებული" -#: commands/tablecmds.c:1055 +#: commands/tablecmds.c:1133 #, c-format msgid "\"%s\" is not partitioned" msgstr "\"%s\" დაყოფილი არაა" -#: commands/tablecmds.c:1149 +#: commands/tablecmds.c:1227 #, c-format msgid "cannot partition using more than %d columns" msgstr "%d-ზე მეტი სვეტის გამოყენებით დაყოფა შეუძლებელია" -#: commands/tablecmds.c:1205 +#: commands/tablecmds.c:1283 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "დაყოფილი ცხრილის (%s) გარე დანაყოფს ვერ შექმნით" -#: commands/tablecmds.c:1207 +#: commands/tablecmds.c:1285 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "ცხრილი %s შეიცავს სვეტებს, რომლებიც უნიკალურია." -#: commands/tablecmds.c:1326 commands/tablecmds.c:13242 +#: commands/tablecmds.c:1415 commands/tablecmds.c:14908 #, c-format msgid "too many array dimensions" msgstr "მასივის მეტისმეტად ბევრი განზომილება" -#: commands/tablecmds.c:1331 parser/parse_clause.c:774 parser/parse_relation.c:1912 +#: commands/tablecmds.c:1420 parser/parse_clause.c:772 parser/parse_relation.c:1929 #, c-format msgid "column \"%s\" cannot be declared SETOF" msgstr "სვეტი \"%s\" არ შეიძლება გამოცხადდეს SETOF" -#: commands/tablecmds.c:1477 +#: commands/tablecmds.c:1549 #, c-format msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" msgstr "DROP INDEX CONCURRENTLY-ს ერთზე მეტი ობიექტის წაშლის მხარდაჭერა არ გააჩნია" -#: commands/tablecmds.c:1481 +#: commands/tablecmds.c:1553 #, c-format msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLY-ს CASCADE-ის მხარდაჭერა არ გააჩნია" -#: commands/tablecmds.c:1585 +#: commands/tablecmds.c:1657 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "დაყოფილ ინდექსს \"%s\" პარალელურად ვერ წაშლით" -#: commands/tablecmds.c:1873 +#: commands/tablecmds.c:1945 #, c-format msgid "cannot truncate only a partitioned table" msgstr "თვითონ დაყოფილი ცხრილის დაცარიელება შეუძლებელია" -#: commands/tablecmds.c:1874 +#: commands/tablecmds.c:1946 #, c-format msgid "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly." msgstr "არ მიუთითოთ საკვანძო სიტყვა ONLY, ან პირდაპირ დანაყოფებზე გამოიყენეთ TRUNCATE ONLY." -#: commands/tablecmds.c:1947 +#: commands/tablecmds.c:2019 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "მოკვეთა გადაეცემა ცხრილამდე %s" -#: commands/tablecmds.c:2308 +#: commands/tablecmds.c:2380 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "გარე ცხრილის (\"%s\") მოკვეთის შეცდომა" -#: commands/tablecmds.c:2365 +#: commands/tablecmds.c:2437 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილების მოკვეთის შეცდომა" -#: commands/tablecmds.c:2594 commands/tablecmds.c:15542 +#: commands/tablecmds.c:2675 commands/tablecmds.c:17230 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "დაყოფილი ცხრილიდან \"%s\" მემკვიდრეობის მიღება შეუძლებელია" -#: commands/tablecmds.c:2599 +#: commands/tablecmds.c:2680 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "დანაყოფიდან \"%s\" მემკვიდრეობის მიღება შეუძლებელია" -#: commands/tablecmds.c:2607 parser/parse_utilcmd.c:2456 parser/parse_utilcmd.c:2598 +#: commands/tablecmds.c:2688 parser/parse_utilcmd.c:2678 parser/parse_utilcmd.c:2866 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "მემკვიდრეობით მიღებული ურთიერთობა \"%s\" ცხრილს ან გარე ცხრილს არ წარმოადგენს" -#: commands/tablecmds.c:2619 commands/tablecmds.c:20391 +#: commands/tablecmds.c:2700 #, c-format msgid "cannot create a temporary relation as partition of permanent relation \"%s\"" msgstr "შეუძლებელია შექმნათ დროებით ურთიერთობა, რომელიც მუდმივი ურთიერთობის \"%s\" დანაყოფი იქნება" -#: commands/tablecmds.c:2628 commands/tablecmds.c:15521 +#: commands/tablecmds.c:2709 commands/tablecmds.c:17209 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "დროებითი ურთიერთობიდან (%s) მემკვიდრეობითობა შეუძლებელია" -#: commands/tablecmds.c:2638 commands/tablecmds.c:15529 +#: commands/tablecmds.c:2719 commands/tablecmds.c:17217 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "სხვა სესიის დროებითი ურთიერთობიდან მემკვიდრეობითობა შეუძლებელია" -#: commands/tablecmds.c:2779 commands/tablecmds.c:2833 commands/tablecmds.c:12925 parser/parse_utilcmd.c:1240 parser/parse_utilcmd.c:1283 parser/parse_utilcmd.c:1710 parser/parse_utilcmd.c:1818 +#: commands/tablecmds.c:2874 commands/tablecmds.c:2928 commands/tablecmds.c:14591 parser/parse_utilcmd.c:1418 parser/parse_utilcmd.c:1463 parser/parse_utilcmd.c:1895 parser/parse_utilcmd.c:2003 #, c-format msgid "cannot convert whole-row table reference" msgstr "" -#: commands/tablecmds.c:2780 parser/parse_utilcmd.c:1241 +#: commands/tablecmds.c:2875 parser/parse_utilcmd.c:1419 #, c-format msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." msgstr "" -#: commands/tablecmds.c:2834 parser/parse_utilcmd.c:1284 +#: commands/tablecmds.c:2929 parser/parse_utilcmd.c:1464 #, c-format msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." msgstr "" -#: commands/tablecmds.c:2944 commands/tablecmds.c:3215 +#: commands/tablecmds.c:3051 commands/tablecmds.c:3345 #, c-format msgid "column \"%s\" inherits from generated column but specifies default" msgstr "ცხრილი \"%s\" მემკვიდრეობით იღებს გენერირებული ცხრილიდან, მაგრამ ნაგულისხმევიც მითითებულია" -#: commands/tablecmds.c:2949 commands/tablecmds.c:3220 +#: commands/tablecmds.c:3056 commands/tablecmds.c:3350 #, c-format msgid "column \"%s\" inherits from generated column but specifies identity" msgstr "ცხრილი \"%s\" მემკვიდრეობით იღებს გენერირებული ცხრილიდან, მაგრამ იდენტიფიკაციაც მითითებულია" -#: commands/tablecmds.c:2957 commands/tablecmds.c:3228 +#: commands/tablecmds.c:3064 commands/tablecmds.c:3358 #, c-format msgid "child column \"%s\" specifies generation expression" msgstr "შვილი სვეტისთვის \"%s\" მითითებულია გენერაციის გამოსახულება" -#: commands/tablecmds.c:2959 commands/tablecmds.c:3230 +#: commands/tablecmds.c:3066 commands/tablecmds.c:3360 #, c-format msgid "A child table column cannot be generated unless its parent column is." msgstr "შვილი ცხრილის სვეტი არ შეიძლება, გენერირებული იყოს, თუ მისი მშობელიც არაა." -#: commands/tablecmds.c:3005 +#: commands/tablecmds.c:3072 commands/tablecmds.c:3366 commands/tablecmds.c:17495 +#, c-format +msgid "column \"%s\" inherits from generated column of different kind" +msgstr "ცხრილი \"%s\" მემკვიდრეობით იღებს სხვა ტიპის გენერირებული სვეტიდან" + +#: commands/tablecmds.c:3074 commands/tablecmds.c:3368 commands/tablecmds.c:17496 +#, c-format +msgid "Parent column is %s, child column is %s." +msgstr "მშობელი სვეტია %s, შვილი სვეტია %s." + +#: commands/tablecmds.c:3121 #, c-format msgid "column \"%s\" inherits conflicting generation expressions" msgstr "სვეტი \"%s\" მემკვიდრეობით კონფლიქტის მქონე გენერაციის გამოსახულებას იღებს" -#: commands/tablecmds.c:3007 +#: commands/tablecmds.c:3123 #, c-format msgid "To resolve the conflict, specify a generation expression explicitly." msgstr "კონფლიქტის გადასაჭრელად გენერაციის გამოსახულება აშკარად მიუთითეთ." -#: commands/tablecmds.c:3011 +#: commands/tablecmds.c:3127 #, c-format msgid "column \"%s\" inherits conflicting default values" msgstr "სვეტი \"%s\" მემკვიდრეობით ურთიერთგამომრიცხავ ნაგულისხმევ მნიშვნელობებს იღებს" -#: commands/tablecmds.c:3013 +#: commands/tablecmds.c:3129 #, c-format msgid "To resolve the conflict, specify a default explicitly." msgstr "კონფლიქტის გადასაჭრელად ნაგულისხმევი აშკარად მიუთითეთ." -#: commands/tablecmds.c:3068 +#: commands/tablecmds.c:3196 #, c-format msgid "check constraint name \"%s\" appears multiple times but with different expressions" msgstr "შემოწმების შეზღუდვის სახელი \"%s\" ბევრჯერ გამოჩნდა, მაგრამ სხვადასხვა გამოსახულებებთან ერთად" -#: commands/tablecmds.c:3119 +#: commands/tablecmds.c:3249 #, c-format msgid "merging column \"%s\" with inherited definition" msgstr "სვეტის (\"%s\") შერწყმა მემკვიდრეობითი აღწერით" -#: commands/tablecmds.c:3123 +#: commands/tablecmds.c:3253 #, c-format msgid "moving and merging column \"%s\" with inherited definition" msgstr "" -#: commands/tablecmds.c:3124 +#: commands/tablecmds.c:3254 #, c-format msgid "User-specified column moved to the position of the inherited column." msgstr "" -#: commands/tablecmds.c:3136 +#: commands/tablecmds.c:3266 #, c-format msgid "column \"%s\" has a type conflict" msgstr "ტიპის კონფლიქტი სვეტში \"%s\"" -#: commands/tablecmds.c:3138 commands/tablecmds.c:3172 commands/tablecmds.c:3188 commands/tablecmds.c:3295 commands/tablecmds.c:3328 commands/tablecmds.c:3344 parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 parser/parse_param.c:223 +#: commands/tablecmds.c:3268 commands/tablecmds.c:3302 commands/tablecmds.c:3318 commands/tablecmds.c:3434 commands/tablecmds.c:3462 commands/tablecmds.c:3478 parser/parse_coerce.c:2190 parser/parse_coerce.c:2210 parser/parse_coerce.c:2230 parser/parse_coerce.c:2251 parser/parse_coerce.c:2306 parser/parse_coerce.c:2340 parser/parse_coerce.c:2416 parser/parse_coerce.c:2447 parser/parse_coerce.c:2486 parser/parse_coerce.c:2553 parser/parse_param.c:224 #, c-format msgid "%s versus %s" msgstr "%s-ი %s-ის წინააღმდეგ" -#: commands/tablecmds.c:3150 +#: commands/tablecmds.c:3280 #, c-format msgid "column \"%s\" has a collation conflict" msgstr "კოლაციის კონფლიქტი სვეტში \"%s\"" -#: commands/tablecmds.c:3152 commands/tablecmds.c:3314 commands/tablecmds.c:7088 +#: commands/tablecmds.c:3282 commands/tablecmds.c:3448 commands/tablecmds.c:7277 #, c-format msgid "\"%s\" versus \"%s\"" msgstr "'%s\" -ი \"%s\"-ის წინააღმდეგ" -#: commands/tablecmds.c:3170 +#: commands/tablecmds.c:3300 #, c-format msgid "column \"%s\" has a storage parameter conflict" msgstr "საცავის პარამეტრის კონფლიქტი სვეტში \"%s\"" -#: commands/tablecmds.c:3186 commands/tablecmds.c:3342 +#: commands/tablecmds.c:3316 commands/tablecmds.c:3476 #, c-format msgid "column \"%s\" has a compression method conflict" msgstr "სვეტის (%s) შეკუმშვის მეთოდის კონფლიქტი" -#: commands/tablecmds.c:3281 +#: commands/tablecmds.c:3420 #, c-format msgid "merging multiple inherited definitions of column \"%s\"" msgstr "მიმდინარეობს სვეტის (\"%s\") მიერ მემკვიდრეობით მიღებული აღწერების შერწყმა" -#: commands/tablecmds.c:3293 +#: commands/tablecmds.c:3432 #, c-format msgid "inherited column \"%s\" has a type conflict" msgstr "მემკივდრეობითი სვეტის \"%s\" ტიპის კონფლიქტი" -#: commands/tablecmds.c:3312 +#: commands/tablecmds.c:3446 #, c-format msgid "inherited column \"%s\" has a collation conflict" msgstr "მემკივდრეობითი სვეტის \"%s\" კოლაციის კონფლიქტი" -#: commands/tablecmds.c:3326 +#: commands/tablecmds.c:3460 #, c-format msgid "inherited column \"%s\" has a storage parameter conflict" msgstr "მემკივდრეობითი სვეტის \"%s\" საცავის პარამეტრის კონფლიქტი" -#: commands/tablecmds.c:3354 +#: commands/tablecmds.c:3488 #, c-format msgid "inherited column \"%s\" has a generation conflict" msgstr "მემკივდრეობითი სვეტის \"%s\" თაობის კონფლიქტი" -#: commands/tablecmds.c:3573 +#: commands/tablecmds.c:3719 #, c-format msgid "cannot move temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილების გადაადგილება შეუძლებელია" -#: commands/tablecmds.c:3643 +#: commands/tablecmds.c:3792 #, c-format msgid "cannot rename column of typed table" msgstr "ტიპიზირებული ცხრილის სვეტის გარდაქმნა შეუძლებელია" -#: commands/tablecmds.c:3662 +#: commands/tablecmds.c:3811 #, c-format msgid "cannot rename columns of relation \"%s\"" msgstr "ურთიერთობის (\"%s\") სვეტების სახელის გადარქმევა შეუძლებელია" -#: commands/tablecmds.c:3757 +#: commands/tablecmds.c:3906 #, c-format msgid "inherited column \"%s\" must be renamed in child tables too" msgstr "მემკვიდრეობით მიღებული სვეტს (\"%s\") სახელი შვილ ცხრილებშიც უნდა გადაერქვას" -#: commands/tablecmds.c:3789 +#: commands/tablecmds.c:3938 #, c-format msgid "cannot rename system column \"%s\"" msgstr "სისტემური სვეტის \"%s\" გადარქმევა შეუძლებელია" -#: commands/tablecmds.c:3804 +#: commands/tablecmds.c:3953 #, c-format msgid "cannot rename inherited column \"%s\"" msgstr "მემკვიდრეობითი სვეტის (\"%s\") სახელის გადარქმევა შეუძლებელია" -#: commands/tablecmds.c:3956 +#: commands/tablecmds.c:4108 #, c-format msgid "inherited constraint \"%s\" must be renamed in child tables too" msgstr "მემკვიდრეობით მიღებული შეზღუდვას (\"%s\") სახელი შვილ ცხრილებშიც უნდა გადაერქვას" -#: commands/tablecmds.c:3963 +#: commands/tablecmds.c:4115 #, c-format msgid "cannot rename inherited constraint \"%s\"" msgstr "მემკვიდრეობითი შეზღუდვის (\"%s\") სახელის გადარქმევა შეუძლებელია" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4260 +#: commands/tablecmds.c:4415 #, c-format msgid "cannot %s \"%s\" because it is being used by active queries in this session" msgstr "%s-ის \"%s\" შეუძლებელია, რადგან ის ამ სესიაში აქტიური მოთხოვნების მიერ გამოიყენება" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4269 +#: commands/tablecmds.c:4424 #, c-format msgid "cannot %s \"%s\" because it has pending trigger events" msgstr "%s-ის \"%s\" შეუძლებელია, რადგან მას დარჩენილი ტრიგერის მოვლენები გააჩნია" -#: commands/tablecmds.c:4295 +#: commands/tablecmds.c:4450 #, c-format msgid "cannot alter temporary tables of other sessions" msgstr "სხვა სესიების დროებითი ცხრილების შეცვლა შეუძლებელია" -#: commands/tablecmds.c:4776 +#: commands/tablecmds.c:4914 #, c-format msgid "cannot alter partition \"%s\" with an incomplete detach" msgstr "არასრული მოხსნის მქონე დანაყოფის \"%s\" შეცვლა შეუძლებელია" -#: commands/tablecmds.c:4980 commands/tablecmds.c:4995 +#: commands/tablecmds.c:5143 #, c-format msgid "cannot change persistence setting twice" msgstr "შენახვის პარამეტრების ორჯერ შეცვლა შეუძლებელია" -#: commands/tablecmds.c:5016 +#: commands/tablecmds.c:5160 #, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" msgstr "ერთზე მეტი SET ACCESS METHOD ქვებრძანება ვერ გექნებათ" -#: commands/tablecmds.c:5772 +#: commands/tablecmds.c:5894 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "სისტემური შეერთების \"%s\" გადაწერა შეუძლებელია" -#: commands/tablecmds.c:5778 +#: commands/tablecmds.c:5900 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "კატალოგის ცხრილად გამოყენებული ცხრილის \"%s\" თავიდან ჩაწერა შეუძლებელია" -#: commands/tablecmds.c:5790 +#: commands/tablecmds.c:5912 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "სხვა სესიების დროებით ცხრილებს ვერ გადააწერთ" -#: commands/tablecmds.c:6285 +#: commands/tablecmds.c:6448 commands/tablecmds.c:6468 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "ურთიერთობის %2$s სვეტი %1$s ნულოვან მნიშვნელობებს შეიცავს" -#: commands/tablecmds.c:6302 +#: commands/tablecmds.c:6485 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "ურთიერთობის (\"%2$s\") შემოწმების შეზღუდვა \"%1$s\" რომელიღაც მწკრივის მიერ ირღვევა" -#: commands/tablecmds.c:6321 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6505 partitioning/partbounds.c:3387 #, c-format msgid "updated partition constraint for default partition \"%s\" would be violated by some row" msgstr "განახებული დანაყოფის შეზღუდვა ნაგულისხმევი დანაყოფისთვის \"%s\" რომელიღაც მწკრივის მიერ დაირღვეოდა" -#: commands/tablecmds.c:6327 +#: commands/tablecmds.c:6511 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "ურთიერთობის (\"%s\") დანაყოფის შეზღუდვა რომელიღაც მწკრივის მიერ ირღვევა" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6596 +#: commands/tablecmds.c:6776 #, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" msgstr "ALTER-ის ქმედებას %s ურთიერთობაზე \"%s\" ვერ შეასრულებთ" -#: commands/tablecmds.c:6851 commands/tablecmds.c:6858 +#: commands/tablecmds.c:7031 commands/tablecmds.c:7038 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" msgstr "ტიპის \"%s\" შეცვლა შეუძლებელია, რადგან მას სვეტი \"%s.%s\" იყენებს" -#: commands/tablecmds.c:6865 +#: commands/tablecmds.c:7045 #, c-format msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" msgstr "გარე ცხრილის \"%s\" შეცვლა შეუძლებელია, რადგან სვეტი \"%s.%s\" თავისი მწკრივის ტიპს იყენებს" -#: commands/tablecmds.c:6872 +#: commands/tablecmds.c:7052 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "ცხრილის \"%s\" შეცვლა შეუძლებელია, რადგან სვეტი \"%s.%s\" თავისი მწკრივის ტიპს იყენებს" -#: commands/tablecmds.c:6928 +#: commands/tablecmds.c:7108 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "ტიპის \"%s\" შეცვლა შეუძლებელია, რადგან ის ტიპიზირებული ცხრილის ტიპისაა" -#: commands/tablecmds.c:6930 +#: commands/tablecmds.c:7110 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "ტიპიზირებული ცხრილების ჩასასწორებლად გამოიყენეთ ALTER ... CASCADE." -#: commands/tablecmds.c:6976 +#: commands/tablecmds.c:7156 +#, c-format +msgid "type %s is the row type of another table" +msgstr "ტიპი %s სხვა ცხრილის მწკრივის ტიპია" + +#: commands/tablecmds.c:7158 +#, c-format +msgid "A typed table must use a stand-alone composite type created with CREATE TYPE." +msgstr "" + +#: commands/tablecmds.c:7163 #, c-format msgid "type %s is not a composite type" msgstr "ტიპი %s კომპოზიტური არაა" -#: commands/tablecmds.c:7003 +#: commands/tablecmds.c:7190 #, c-format msgid "cannot add column to typed table" msgstr "ტიპიზირებულ ცხრილში სვეტების ჩამატება შეუძლებელია" -#: commands/tablecmds.c:7051 +#: commands/tablecmds.c:7240 #, c-format msgid "cannot add column to a partition" msgstr "დანაყოფს სვეტს ვერ დაუმატებთ" -#: commands/tablecmds.c:7080 commands/tablecmds.c:15760 +#: commands/tablecmds.c:7269 commands/tablecmds.c:17451 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "შვილ ცხრილს \"%s\" სვეტისთვის \"%s\" სხვა ტიპი გააჩნია" -#: commands/tablecmds.c:7086 commands/tablecmds.c:15766 +#: commands/tablecmds.c:7275 commands/tablecmds.c:17457 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "შვილ ცხრილს \"%s\" სვეტისთვის \"%s\" სხვა კოლაცია გააჩნია" -#: commands/tablecmds.c:7104 +#: commands/tablecmds.c:7293 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "მიმდინარეობს აღწერის შერწყმა სვეტისთვის \"%s\" შვილისთვის \"%s\"" -#: commands/tablecmds.c:7157 +#: commands/tablecmds.c:7346 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "ცხრილისთვის, რომელსაც შვილი ცხრილები გააჩნია, იდენტიფიკაციის სვეტის რეკურსიული დამატება შეუძლებელია" -#: commands/tablecmds.c:7370 +#: commands/tablecmds.c:7593 #, c-format msgid "column must be added to child tables too" msgstr "სვეტი შვილ ცხრილებსაც უნდა დაემატოთ" -#: commands/tablecmds.c:7448 +#: commands/tablecmds.c:7671 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "ურთიერთობის (%2$s) სვეტი %1$s უკვე რსებობს. გამოტოვება" -#: commands/tablecmds.c:7455 +#: commands/tablecmds.c:7678 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "ურთიერთობის (%2$s) სვეტი %1$s უკვე რსებობს" -#: commands/tablecmds.c:7521 commands/tablecmds.c:12564 -#, c-format -msgid "cannot remove constraint from only the partitioned table when partitions exist" -msgstr "შეზღუდვის წაშლა მხოლოდ დაყოფილი ცხრილიდან მაშინ, როცა დანაყოფები არსებობს, შეუძლებელია" - -#: commands/tablecmds.c:7522 commands/tablecmds.c:7836 commands/tablecmds.c:8014 commands/tablecmds.c:8121 commands/tablecmds.c:8238 commands/tablecmds.c:9057 commands/tablecmds.c:12565 -#, c-format -msgid "Do not specify the ONLY keyword." -msgstr "ONLY არ მიუთითოთ." - -#: commands/tablecmds.c:7558 commands/tablecmds.c:7762 commands/tablecmds.c:7904 commands/tablecmds.c:8036 commands/tablecmds.c:8165 commands/tablecmds.c:8259 commands/tablecmds.c:8360 commands/tablecmds.c:8517 commands/tablecmds.c:8670 commands/tablecmds.c:8751 commands/tablecmds.c:8885 commands/tablecmds.c:12718 commands/tablecmds.c:14249 commands/tablecmds.c:16875 +#: commands/tablecmds.c:7769 commands/tablecmds.c:7936 commands/tablecmds.c:8137 commands/tablecmds.c:8268 commands/tablecmds.c:8397 commands/tablecmds.c:8491 commands/tablecmds.c:8594 commands/tablecmds.c:8790 commands/tablecmds.c:8956 commands/tablecmds.c:9047 commands/tablecmds.c:9181 commands/tablecmds.c:14366 commands/tablecmds.c:15931 commands/tablecmds.c:18698 #, c-format msgid "cannot alter system column \"%s\"" msgstr "სისტემური სვეტის \"%s\" შეცვლა შეუძლებელია" -#: commands/tablecmds.c:7564 commands/tablecmds.c:7910 +#: commands/tablecmds.c:7775 commands/tablecmds.c:8143 commands/tablecmds.c:14127 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" იდენტიფიკატორი სვეტია" -#: commands/tablecmds.c:7605 -#, c-format -msgid "column \"%s\" is in a primary key" -msgstr "სვეტი \"%s\" პირველადი გასაღებია" - -#: commands/tablecmds.c:7610 -#, c-format -msgid "column \"%s\" is in index used as replica identity" -msgstr "სვეტი \"%s\" რეპლიკის იდენტიფიკატორად გამოყენებული ინდექსია" - -#: commands/tablecmds.c:7633 +#: commands/tablecmds.c:7792 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "სვეტი \"%s\" მშობელ ცხრილში NOT NULL-ით დანიშნული არაა" -#: commands/tablecmds.c:7833 commands/tablecmds.c:9541 +#: commands/tablecmds.c:8014 commands/tablecmds.c:9988 #, c-format msgid "constraint must be added to child tables too" msgstr "შეზღუდვა შვილ ცხრილებსაც უნდა დაემატოთ" -#: commands/tablecmds.c:7834 +#: commands/tablecmds.c:8015 commands/tablecmds.c:8246 commands/tablecmds.c:8353 commands/tablecmds.c:8470 commands/tablecmds.c:9354 commands/tablecmds.c:12190 #, c-format -msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." -msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" უკვე NOT NULL არაა." +msgid "Do not specify the ONLY keyword." +msgstr "ONLY არ მიუთითოთ." -#: commands/tablecmds.c:7919 +#: commands/tablecmds.c:8152 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" გენერირებული სვეტია" -#: commands/tablecmds.c:8013 +#: commands/tablecmds.c:8245 #, c-format msgid "cannot add identity to a column of only the partitioned table" msgstr "მხოლოდ, დაყოფილი ცხრილში იდენტიფიკაციას სვეტს ვერ დაამატებთ" -#: commands/tablecmds.c:8019 +#: commands/tablecmds.c:8251 #, c-format msgid "cannot add identity to a column of a partition" msgstr "დანაყოფს სვეტს იდენტიფიკატორს ვერ დაუმატებთ" -#: commands/tablecmds.c:8047 +#: commands/tablecmds.c:8279 #, c-format msgid "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" უნდა აღწეროთ როგორც NOT NULL მანამდე, სანამ იდენტიფიკაციას დაამატებთ" -#: commands/tablecmds.c:8053 +#: commands/tablecmds.c:8285 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" უკვე იდენტიფიკატორი სვეტია" -#: commands/tablecmds.c:8059 +#: commands/tablecmds.c:8291 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "ურთიერთობის \"%2$s\" სვეტს \"%1$s\" ნაგულისხმევი მნიშვნელობა უკვე გააჩნია" -#: commands/tablecmds.c:8120 +#: commands/tablecmds.c:8352 #, c-format msgid "cannot change identity column of only the partitioned table" msgstr "მხოლოდ, დაყოფილი ცხრილის იდენტიფიკაციის სვეტს ვერ შეცვლით" -#: commands/tablecmds.c:8126 +#: commands/tablecmds.c:8358 #, c-format msgid "cannot change identity column of a partition" msgstr "დანაყოფის იდენტიფიკაციის სვეტს ვერ შეცვლით" -#: commands/tablecmds.c:8171 commands/tablecmds.c:8267 +#: commands/tablecmds.c:8403 commands/tablecmds.c:8499 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" იდენტიფიკატორი სვეტი არაა" -#: commands/tablecmds.c:8237 +#: commands/tablecmds.c:8469 #, c-format msgid "cannot drop identity from a column of only the partitioned table" msgstr "მხოლოდ, დაყოფილი ცხრილში სვეტიდან იდენტიფიკაციას ვერ წაშლით" -#: commands/tablecmds.c:8243 +#: commands/tablecmds.c:8475 #, c-format msgid "cannot drop identity from a column of a partition" msgstr "დანაყოფს სვეტიდან იდენტიფიკატორს ვერ წაშლით" -#: commands/tablecmds.c:8272 +#: commands/tablecmds.c:8504 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" იდენტიფიკატორი სვეტი არაა. გამოტოვება" -#: commands/tablecmds.c:8366 +#: commands/tablecmds.c:8601 commands/tablecmds.c:8811 #, c-format msgid "column \"%s\" of relation \"%s\" is not a generated column" msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" გენერირებული სვეტი არაა" -#: commands/tablecmds.c:8464 +#: commands/tablecmds.c:8612 +#, c-format +msgid "ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables with check constraints" +msgstr "ALTER TABLE / SET EXPRESSION მხარდაჭერილი არაა შემოწმების შეზღუდვების მქონე ვირტუალური გენერირებული სვეტებისთვის" + +#: commands/tablecmds.c:8613 commands/tablecmds.c:8631 commands/tablecmds.c:8803 +#, c-format +msgid "Column \"%s\" of relation \"%s\" is a virtual generated column." +msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" ვირტუალური გენერირებული სვეტია." + +#: commands/tablecmds.c:8630 +#, c-format +msgid "ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables that are part of a publication" +msgstr "ALTER TABLE / SET EXPRESSION მხარდაჭერილი არაა ვირტუალურ გენერირებულ სვეტებზე ცხრილებზე, რომლებიც გამოცემის ნაწილი არიან" + +#: commands/tablecmds.c:8737 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "ALTER TABLE / DROP EXPRESSION შვილ ცხრილებზეც უნდა გადატარდეს" -#: commands/tablecmds.c:8486 +#: commands/tablecmds.c:8759 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "მემკვიდრეობითი სვეტიდან გენერაციის გამოსახულების წაშლა შეუძლებელია" -#: commands/tablecmds.c:8525 +#: commands/tablecmds.c:8802 #, c-format -msgid "column \"%s\" of relation \"%s\" is not a stored generated column" -msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" დამახსოვრებული გენერირებული სვეტი არაა" +msgid "ALTER TABLE / DROP EXPRESSION is not supported for virtual generated columns" +msgstr "ALTER TABLE / DROP EXPRESSION ვირტუალურ გენერირებულ სვეტებზე მხარდაჭერილი არაა" -#: commands/tablecmds.c:8530 +#: commands/tablecmds.c:8816 #, c-format -msgid "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" -msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" დამახსოვრებული გენერირებული სვეტი არაა. გამოტოვება" +msgid "column \"%s\" of relation \"%s\" is not a generated column, skipping" +msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" გენერირებული სვეტი არაა. გამოტოვება" -#: commands/tablecmds.c:8608 +#: commands/tablecmds.c:8894 #, c-format msgid "cannot refer to non-index column by number" msgstr "არა-ინდექსი სვეტის ნომრით მიმართვა შეუძლებელია" -#: commands/tablecmds.c:8660 +#: commands/tablecmds.c:8946 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "ურთიერთობის (%2$s) სვეტი (%1$d) არ არსებობს" -#: commands/tablecmds.c:8679 +#: commands/tablecmds.c:8966 +#, c-format +msgid "cannot alter statistics on virtual generated column \"%s\"" +msgstr "შეუძლებელია სტატისტიკის შეცვლა ვირტუალურ გენერირებულ სვეტზე \"%s\"" + +#: commands/tablecmds.c:8975 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "ინდექსის \"%2$s\" ჩასმული სვეტის \"%1$s\" სტატისტიკის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:8684 +#: commands/tablecmds.c:8980 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "" -#: commands/tablecmds.c:8686 +#: commands/tablecmds.c:8982 #, c-format msgid "Alter statistics on table column instead." msgstr "ამის ნაცვლად ცხრილის სვეტის სტატისტიკა შეცვალეთ." -#: commands/tablecmds.c:8932 +#: commands/tablecmds.c:9228 #, c-format msgid "cannot drop column from typed table" msgstr "ტიპიზირებული ცხრილის სვეტის წაშლა შეუძლებელია" -#: commands/tablecmds.c:8995 +#: commands/tablecmds.c:9292 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "სვეტი \"%s\" ურთიერთობაში \"%s\" არ არსებობს. გამოტოვება" -#: commands/tablecmds.c:9008 +#: commands/tablecmds.c:9305 #, c-format msgid "cannot drop system column \"%s\"" msgstr "სისტემური სვეტის \"%s\" წაშლა შეუძლებელია" -#: commands/tablecmds.c:9018 +#: commands/tablecmds.c:9315 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "მემკვიდრეობით მიღებული სვეტის \"%s\" წაშლა შეუძლებელია" -#: commands/tablecmds.c:9031 +#: commands/tablecmds.c:9328 #, c-format msgid "cannot drop column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "" -#: commands/tablecmds.c:9056 +#: commands/tablecmds.c:9353 #, c-format msgid "cannot drop column from only the partitioned table when partitions exist" msgstr "" -#: commands/tablecmds.c:9261 +#: commands/tablecmds.c:9518 +#, c-format +msgid "column \"%s\" of table \"%s\" is not marked NOT NULL" +msgstr "ცხრილის \"%2$s\" სვეტი \"%1$s\" არაა დანიშნული, როგორც NOT NULL" + +#: commands/tablecmds.c:9554 commands/tablecmds.c:9566 +#, c-format +msgid "cannot create primary key on column \"%s\"" +msgstr "ძირითადი გასაღების შექმნა სვეტზე \"%s\" შეუძლებელია" + +#. translator: fourth %s is a constraint characteristic such as NOT VALID +#: commands/tablecmds.c:9556 commands/tablecmds.c:9568 +#, c-format +msgid "The constraint \"%s\" on column \"%s\" of table \"%s\", marked %s, is incompatible with a primary key." +msgstr "" + +#: commands/tablecmds.c:9692 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX დაყოფილ ცხრილებზე მხარდაუჭერელია" -#: commands/tablecmds.c:9286 +#: commands/tablecmds.c:9717 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX ინდექსის სახელს \"%s\"-დან \"%s\"-ზე გადაარქმევს" -#: commands/tablecmds.c:9623 +#: commands/tablecmds.c:10075 #, c-format msgid "cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "" -#: commands/tablecmds.c:9629 -#, c-format -msgid "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"" -msgstr "" - -#: commands/tablecmds.c:9632 -#, c-format -msgid "This feature is not yet supported on partitioned tables." -msgstr "ეს ოპერაცია დაყოფილი ცხრილებისთვის ჯერჯერობით მხარდაჭერილი არაა." - -#: commands/tablecmds.c:9639 commands/tablecmds.c:10095 +#: commands/tablecmds.c:10083 commands/tablecmds.c:10710 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "მითითებული ურთიერთობა \"%s\" ცხრილი არაა" -#: commands/tablecmds.c:9662 +#: commands/tablecmds.c:10106 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "მუდმივ ცხრილებზე არსებული შეზღუდვები მხოლოდ მუდმივ ცხრილებზე შეიძლება, მიუთითებდეს" -#: commands/tablecmds.c:9669 +#: commands/tablecmds.c:10113 #, c-format msgid "constraints on unlogged tables may reference only permanent or unlogged tables" msgstr "ჟურნალის გარეშე მყოფი ცხრილების შეზღუდვები მხოლოდ მუდმივ ან ჟურნალის გარეშე მყოფ ცხრილებზე შეიძლება, მიუთითებდეს" -#: commands/tablecmds.c:9675 +#: commands/tablecmds.c:10119 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "დროებით ცხრილებზე არსებული შეზღუდვები მხოლოდ დროებით ცხრილებზე შეიძლება, მიუთითებდეს" -#: commands/tablecmds.c:9679 +#: commands/tablecmds.c:10123 #, c-format msgid "constraints on temporary tables must involve temporary tables of this session" msgstr "დროებითი ცხრილის შეზღუდვები მიმდინარე სესიის დროებით ცხრილებს უნდა მიმართავდეს" -#: commands/tablecmds.c:9743 commands/tablecmds.c:9749 +#: commands/tablecmds.c:10138 commands/tablecmds.c:10166 +#, c-format +msgid "foreign key uses PERIOD on the referenced table but not the referencing table" +msgstr "" + +#: commands/tablecmds.c:10178 +#, c-format +msgid "foreign key uses PERIOD on the referencing table but not the referenced table" +msgstr "" + +#: commands/tablecmds.c:10192 +#, c-format +msgid "foreign key must use PERIOD when referencing a primary using WITHOUT OVERLAPS" +msgstr "" + +#: commands/tablecmds.c:10216 commands/tablecmds.c:10222 #, c-format msgid "invalid %s action for foreign key constraint containing generated column" msgstr "არასწორი ქმედება %s გარე გასაღების შეზღუდვის შემცველი გენერირებული სვეტისთვის" -#: commands/tablecmds.c:9765 +#: commands/tablecmds.c:10237 +#, c-format +msgid "foreign key constraints on virtual generated columns are not supported" +msgstr "ვირტუალურ გენერირებულ სვეტებზე გარე გასაღების შეზღუდვები მხარდაჭერილი არაა" + +#: commands/tablecmds.c:10251 commands/tablecmds.c:10260 +#, c-format +msgid "unsupported %s action for foreign key constraint using PERIOD" +msgstr "მხარდაუჭერელი %s ქმედება გარე გასაღების შეზღუდვისთვის, რომელიც PERIOD-ს იყენებს" + +#: commands/tablecmds.c:10275 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "" -#: commands/tablecmds.c:9872 +#: commands/tablecmds.c:10331 +#, c-format +msgid "could not identify an overlaps operator for foreign key" +msgstr "ვერ აღმოვაჩინე გადაფარვების ოპერატორი გარე გასაღებისთვის" + +#: commands/tablecmds.c:10332 +#, c-format +msgid "could not identify an equality operator for foreign key" +msgstr "გარე გასაღებისთვის ტოლობის ოპერატორი ვერ ვიპოვე" + +#: commands/tablecmds.c:10397 commands/tablecmds.c:10431 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "გარე გასაღების შეზღუდვის \"%s\" განხორციელება შეუძლებელია" -#: commands/tablecmds.c:9874 +#: commands/tablecmds.c:10399 +#, c-format +msgid "Key columns \"%s\" of the referencing table and \"%s\" of the referenced table are of incompatible types: %s and %s." +msgstr "მიმმართველი ცხრილის გასაღების სვეტები \"%s\" და მიმართვადი ცხრილის გასაღების სვეტები \"%s\" შეუთავსებელი ტიპისაა: %s და %s." + +#: commands/tablecmds.c:10432 #, c-format -msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." -msgstr "გასაღების სვეტები \"%s\" და \"%s\" შეუთავსებელი ტიპებისაა: %s და %s." +msgid "Key columns \"%s\" of the referencing table and \"%s\" of the referenced table have incompatible collations: \"%s\" and \"%s\". If either collation is nondeterministic, then both collations have to be the same." +msgstr "" -#: commands/tablecmds.c:10031 +#: commands/tablecmds.c:10638 #, c-format msgid "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" msgstr "" -#: commands/tablecmds.c:10305 commands/tablecmds.c:10775 parser/parse_utilcmd.c:797 parser/parse_utilcmd.c:920 +#: commands/tablecmds.c:11020 commands/tablecmds.c:11466 parser/parse_utilcmd.c:941 parser/parse_utilcmd.c:1086 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "გარე გასაღების შეზღუდვები გარე ცხრილებზე მხარდაჭერილი არაა" -#: commands/tablecmds.c:11328 commands/tablecmds.c:11609 commands/tablecmds.c:12521 commands/tablecmds.c:12595 +#: commands/tablecmds.c:11449 +#, c-format +msgid "cannot attach table \"%s\" as a partition because it is referenced by foreign key \"%s\"" +msgstr "ცხრილს \"%s\" ვერ მივამაგრებ დანაყოფს, რომელსაც მიმართავს გარე გარე გასაღები \"%s\"" + +#: commands/tablecmds.c:11730 +#, c-format +msgid "constraint \"%s\" enforceability conflicts with constraint \"%s\" on relation \"%s\"" +msgstr "შეზღუდვის \"%s\" ნაძალადევობა კონფლიქტშია შეზღუდვასთან \"%s\" ურთიერთობაზე \"%s\"" + +#: commands/tablecmds.c:12189 +#, c-format +msgid "constraint must be altered in child tables too" +msgstr "შეზღუდვა შვილ ცხრილებშიც უნდა შეიცვალოს" + +#: commands/tablecmds.c:12218 commands/tablecmds.c:12912 commands/tablecmds.c:14006 commands/tablecmds.c:14235 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "ურთიერთობის \"%2$s\" შეზღუდვა \"%1$s\" არ არსებობს" -#: commands/tablecmds.c:11335 +#: commands/tablecmds.c:12225 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "ურთიერთობის (\"%2$s\") შეზღუდვა \"%1$s\" გარე გასაღების შეზღუდვა არაა" -#: commands/tablecmds.c:11373 +#: commands/tablecmds.c:12230 +#, c-format +msgid "cannot alter enforceability of constraint \"%s\" of relation \"%s\"" +msgstr "ურთიერთობაზე \"%2$s\" შეზღუდვის \"%1$s\" ძალით დაყენებადობის შეცვლა შეუძლებელია" + +#: commands/tablecmds.c:12236 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" is not a not-null constraint" +msgstr "ურთიერთობის \"%2$s\" შეზღუდვა \"%1$s\" არანულოვანი შეზღუდვა არაა" + +#: commands/tablecmds.c:12244 +#, c-format +msgid "cannot alter inherited constraint \"%s\" on relation \"%s\"" +msgstr "ურთიერთობაზე \"%2$s\" მემკვიდრეობით მიღებული შეზღუდვის \"%1$s\" წაშლა შეუძლებელია" + +#: commands/tablecmds.c:12284 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" msgstr "ურთიერთობაზე \"%2$s\" შეზღუდვის \"%1$s\" შეცვლა შეუძლებელია" -#: commands/tablecmds.c:11376 +#: commands/tablecmds.c:12287 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "შეზღუდვა \"%1$s\" ურთიერთობის \"%3$s\" შეზღუდვიდანა \"%2$s\"-ია ნაწარმოები." -#: commands/tablecmds.c:11378 +#: commands/tablecmds.c:12289 #, c-format msgid "You may alter the constraint it derives from instead." -msgstr "" +msgstr "ამის მაგიერ, შეიგძლიათ, შეცვალოთ შეზღუდვა, რომლიდანაც ის მიღებულია." + +#: commands/tablecmds.c:12921 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" is not a foreign key, check, or not-null constraint" +msgstr "შეზღუდვა \"%s\" ურთიერთობისთვის \"%s\" გარე გასაღებს, შემოწმებას, ან არანულოვან შეზღუდვას არ წარმოადგენს" -#: commands/tablecmds.c:11617 +#: commands/tablecmds.c:12927 #, c-format -msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" -msgstr "ურთიერთობის (\"%2$s\") შეზღუდვა \"%1$s\" გარე გასაღები ან შემოწმების შეზღუდვა არაა" +msgid "cannot validate NOT ENFORCED constraint" +msgstr "შეზღუდვის NOT ENFORCED დადასტურება შეუძლებელია" -#: commands/tablecmds.c:11694 +#: commands/tablecmds.c:13116 commands/tablecmds.c:13216 #, c-format msgid "constraint must be validated on child tables too" msgstr "შეზღუდვა შვილ ცხრილებზეც უნდა გადამოწმდეს" -#: commands/tablecmds.c:11781 +#: commands/tablecmds.c:13293 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "გარე გასაღების შეზღუდვაში მითითებული სვეტი \"%s\" არ არსებობს" -#: commands/tablecmds.c:11787 +#: commands/tablecmds.c:13299 #, c-format msgid "system columns cannot be used in foreign keys" msgstr "უცხო გასაღებებში სისტემურ სვეტებს ვერ გამოიყენებთ" -#: commands/tablecmds.c:11791 +#: commands/tablecmds.c:13303 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "გარე გასაღებში %d გასაღებზე მეტი ვერ გექნებათ" -#: commands/tablecmds.c:11856 +#: commands/tablecmds.c:13371 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "" -#: commands/tablecmds.c:11873 +#: commands/tablecmds.c:13388 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "მითითებული ცხრილისთვის \"%s\" ძირითადი გასაღები არ არსებობს" -#: commands/tablecmds.c:11941 +#: commands/tablecmds.c:13461 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "" -#: commands/tablecmds.c:12033 +#: commands/tablecmds.c:13564 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "" -#: commands/tablecmds.c:12038 +#: commands/tablecmds.c:13569 #, c-format msgid "there is no unique constraint matching given keys for referenced table \"%s\"" msgstr "" -#: commands/tablecmds.c:12477 +#: commands/tablecmds.c:14010 +#, c-format +msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" +msgstr "ურთიერთობის (\"%2$s\") შეზღუდვა (\"%1$s\") არ არსებობს. გამოტოვება" + +#: commands/tablecmds.c:14055 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "მემკვიდრეობით მიღებული ურთიერთობის \"%2$s\" შეზღუდვის \"%1$s\" წაშლა შეუძლებელია" -#: commands/tablecmds.c:12527 +#: commands/tablecmds.c:14107 #, c-format -msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" -msgstr "ურთიერთობის (\"%2$s\") შეზღუდვა (\"%1$s\") არ არსებობს. გამოტოვება" +msgid "column \"%s\" is in a primary key" +msgstr "სვეტი \"%s\" პირველადი გასაღებია" + +#: commands/tablecmds.c:14115 +#, c-format +msgid "column \"%s\" is in index used as replica identity" +msgstr "სვეტი \"%s\" რეპლიკის იდენტიფიკატორად გამოყენებული ინდექსია" -#: commands/tablecmds.c:12702 +#: commands/tablecmds.c:14348 #, c-format msgid "cannot alter column type of typed table" msgstr "ტიპიზირებული ცხრილის სვეტის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:12729 +#: commands/tablecmds.c:14376 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "გენერირებული სვეტის ტიპის შეცვლისას USING-ს ვერ მიუთითებთ" + +#: commands/tablecmds.c:14377 commands/tablecmds.c:19757 commands/tablecmds.c:19850 commands/trigger.c:659 rewrite/rewriteHandler.c:949 rewrite/rewriteHandler.c:984 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "სვეტი \"%s\" გენერირებული სვეტია." + +#: commands/tablecmds.c:14388 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "მემკვიდრეობით მიღებული სვეტის \"%s\" შეცვლა შეუძლებელია" -#: commands/tablecmds.c:12738 +#: commands/tablecmds.c:14397 #, c-format msgid "cannot alter column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "სვეტის \"%s\" შეცვლა შეუძლებელია, რადგან ის ურთიერთობის \"%s\" დანაყოფის გასაღების ნაწილია" -#: commands/tablecmds.c:12788 +#: commands/tablecmds.c:14452 #, c-format msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s" msgstr "" -#: commands/tablecmds.c:12791 +#: commands/tablecmds.c:14455 #, c-format msgid "You might need to add an explicit cast." msgstr "შეიძლება აშკარა დაკასტვა უნდა დაამატოთ." -#: commands/tablecmds.c:12795 +#: commands/tablecmds.c:14459 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "სვეტის \"%s\" ავტომატური დაკასტვა ტიპამდე %s შეუძლებელია" #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12798 +#: commands/tablecmds.c:14463 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "შეიძლება, გჭირდებათ, მიუთითოთ \"USING %s::%s\"." -#: commands/tablecmds.c:12897 +#: commands/tablecmds.c:14563 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "ურთიერთობის \"%2$s\" სვეტის \"%1$s\" შეცვლა შეუძლებელია" -#: commands/tablecmds.c:12926 +#: commands/tablecmds.c:14592 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "" -#: commands/tablecmds.c:12937 +#: commands/tablecmds.c:14603 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "" -#: commands/tablecmds.c:13062 +#: commands/tablecmds.c:14728 #, c-format msgid "cannot alter type of column \"%s\" twice" msgstr "სვეტის (\"%s\") ტიპის ორჯერ შეცვლა შეუძლებელია" -#: commands/tablecmds.c:13100 +#: commands/tablecmds.c:14766 #, c-format msgid "generation expression for column \"%s\" cannot be cast automatically to type %s" msgstr "" -#: commands/tablecmds.c:13105 +#: commands/tablecmds.c:14771 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "" -#: commands/tablecmds.c:13409 +#: commands/tablecmds.c:15075 #, c-format msgid "cannot alter type of a column used by a function or procedure" msgstr "ფუნქციის ან პროცედურის მიერ გამოყენებული სვეტის ტიპის შექმნა შეუძლებელია" -#: commands/tablecmds.c:13410 commands/tablecmds.c:13425 commands/tablecmds.c:13445 commands/tablecmds.c:13464 commands/tablecmds.c:13523 +#: commands/tablecmds.c:15076 commands/tablecmds.c:15091 commands/tablecmds.c:15111 commands/tablecmds.c:15130 commands/tablecmds.c:15189 #, c-format msgid "%s depends on column \"%s\"" msgstr "%s ეყრდნობა სვეტს \"%s\"" -#: commands/tablecmds.c:13424 +#: commands/tablecmds.c:15090 #, c-format msgid "cannot alter type of a column used by a view or rule" msgstr "ხედის ან წესის მიერ გამოყენებული სვეტის ტიპის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:13444 +#: commands/tablecmds.c:15110 #, c-format msgid "cannot alter type of a column used in a trigger definition" msgstr "ტრიგერის აღწერაში გამოყენებული სვეტის ტიპის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:13463 +#: commands/tablecmds.c:15129 #, c-format msgid "cannot alter type of a column used in a policy definition" msgstr "პოლიტიკის აღწერაში გამოყენებული სვეტის ტიპის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:13494 +#: commands/tablecmds.c:15160 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "გენერირებული სვეტის მიერ გამოყენებული სვეტის ტიპის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:13495 +#: commands/tablecmds.c:15161 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "სვეტი (%s\") გენერირებული სვეტის (%s) მიერ გამოიყენება." -#: commands/tablecmds.c:13522 +#: commands/tablecmds.c:15188 #, c-format msgid "cannot alter type of a column used by a publication WHERE clause" msgstr "გამოცემის WHERE პირობის მიერ გამოყენებული სვეტის ტიპის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:14357 commands/tablecmds.c:14369 +#: commands/tablecmds.c:16039 commands/tablecmds.c:16051 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "ინდექსის \"%s\" მფლობელის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:14359 commands/tablecmds.c:14371 +#: commands/tablecmds.c:16041 commands/tablecmds.c:16053 #, c-format msgid "Change the ownership of the index's table instead." msgstr "ამის მაგიერ ინდექსის ცხრილის მფლობელი შეცვალეთ." -#: commands/tablecmds.c:14385 +#: commands/tablecmds.c:16067 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "მიმდევრობის \"%s\" მფლობელის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:14410 +#: commands/tablecmds.c:16092 #, c-format msgid "cannot change owner of relation \"%s\"" msgstr "ურთიერთობის \"%s\" მფლობელის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:14877 +#: commands/tablecmds.c:16559 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "ერთზე მეტი SET TABLESPACE ქვებრძანება ვერ გექნებათ" -#: commands/tablecmds.c:14954 +#: commands/tablecmds.c:16638 #, c-format msgid "cannot set options for relation \"%s\"" msgstr "ურთიერთობის (%s) პარამეტრების დაყენება შეუძლებელია" -#: commands/tablecmds.c:14988 commands/view.c:440 +#: commands/tablecmds.c:16672 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "WITH CHECK OPTION მხოლოდ ავტომატურად განახლებად ხედებზეა მხარდაჭერილი" -#: commands/tablecmds.c:15238 +#: commands/tablecmds.c:16925 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "ცხრილის სივრცეში მხოლოდ ცხრილები, ინდექსები და მატერიალიზებული ხედები შეიძლება არსებობდეს" -#: commands/tablecmds.c:15250 +#: commands/tablecmds.c:16937 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "ცხრილების სივრცეში pg_globl ურთიერთობების შეტანა/გამოტანა შეუძლებელია" -#: commands/tablecmds.c:15342 +#: commands/tablecmds.c:17029 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "შეწყვეტა, რადგან ბლოკი ურთიერთობაზე \"%s.%s\" ხელმისაწვდომი არაა" -#: commands/tablecmds.c:15358 +#: commands/tablecmds.c:17045 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr "ცხრილების სივრცეში \"%s\" ურთიერთობა, რომელიც ემთხვევა, ვერ ვიპოვე" -#: commands/tablecmds.c:15480 +#: commands/tablecmds.c:17167 #, c-format msgid "cannot change inheritance of typed table" msgstr "ტიპიზირებული ცხრილის მემკვიდრეობითობის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:15485 commands/tablecmds.c:15985 +#: commands/tablecmds.c:17172 commands/tablecmds.c:17756 #, c-format msgid "cannot change inheritance of a partition" msgstr "დანაყოფის მემკვიდრეობითობის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:15490 +#: commands/tablecmds.c:17177 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "დაყოფილი ცხრილის მემკვიდრეობითობის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:15536 +#: commands/tablecmds.c:17224 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "სხვა სესიის დროებითი ურთიერთობის მემკვიდრეობით მიღება შეუძლებელია" -#: commands/tablecmds.c:15549 +#: commands/tablecmds.c:17237 #, c-format msgid "cannot inherit from a partition" msgstr "დანაყოფიდან მემკვიდრეობითობა შეუძლებელია" -#: commands/tablecmds.c:15571 commands/tablecmds.c:18453 +#: commands/tablecmds.c:17259 commands/tablecmds.c:20270 #, c-format msgid "circular inheritance not allowed" msgstr "წრიული მემკვიდრეობითობა დაუშვებელია" -#: commands/tablecmds.c:15572 commands/tablecmds.c:18454 +#: commands/tablecmds.c:17260 commands/tablecmds.c:20271 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "\"%s\" უკვე \"%s\"-ის შვილია." -#: commands/tablecmds.c:15585 +#: commands/tablecmds.c:17273 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "ტრიგერი \"%s\" ხელს უშლის ცხრილს \"%s\" მემკვიდრეობის შვილად გადაიქცეს" -#: commands/tablecmds.c:15587 +#: commands/tablecmds.c:17275 #, c-format msgid "ROW triggers with transition tables are not supported in inheritance hierarchies." msgstr "ROW ტრიგერები, რომლებსაც გარდამავალი ცხრილები გააჩნიათ, მემკვიდრეობითობის იერარქიებში მხარდაჭერილი არაა." -#: commands/tablecmds.c:15776 +#: commands/tablecmds.c:17476 commands/tablecmds.c:17725 #, c-format -msgid "column \"%s\" in child table must be marked NOT NULL" -msgstr "სვეტი \"%s\" შვილ ცხრილში NOT NULL-ით უნდა იყოს დანიშნული" +msgid "column \"%s\" in child table \"%s\" must be marked NOT NULL" +msgstr "სვეტი \"%s\" შვილ ცხრილში \"%s\" NOT NULL-ით უნდა იყოს დანიშნული" -#: commands/tablecmds.c:15785 +#: commands/tablecmds.c:17486 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "შვილ ცხრილში სვეტი \"%s\" გენერირებული სვეტი არ უნდა იყოს" -#: commands/tablecmds.c:15789 +#: commands/tablecmds.c:17490 #, c-format msgid "column \"%s\" in child table must not be a generated column" msgstr "შვილ ცხრილში სვეტი \"%s\" გენერირებული სვეტი არ უნდა იყოს" -#: commands/tablecmds.c:15827 +#: commands/tablecmds.c:17536 #, c-format msgid "child table is missing column \"%s\"" msgstr "შვილ ცხრილს აკლია სვეტი \"%s\"" -#: commands/tablecmds.c:15908 +#: commands/tablecmds.c:17653 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "შვილ ცხრილს \"%s\" შემოწმების შეზღუდვისთვის \"%s\" სხვა განსაზღვრება გააჩნია" -#: commands/tablecmds.c:15915 +#: commands/tablecmds.c:17662 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"" msgstr "შეზღუდვა \"%s\" კონფლიქტშია არა-მემკვიდრეობით მიღებულ შეზღუდვასთან შვილ ცხრილზე \"%s\"" -#: commands/tablecmds.c:15925 +#: commands/tablecmds.c:17673 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" msgstr "შეზღუდვა \"%s\" კონფლიქტშია შეზღუდვასთან NOT VALID შვილ ცხრილზე \"%s\"" -#: commands/tablecmds.c:15963 +#: commands/tablecmds.c:17684 +#, c-format +msgid "constraint \"%s\" conflicts with NOT ENFORCED constraint on child table \"%s\"" +msgstr "შეზღუდვა \"%s\" კონფლიქტშია შეზღუდვასთან NOT ENFORCED შვილ ცხრილზე \"%s\"" + +#: commands/tablecmds.c:17733 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "შვილ ცხრილს აკლია შეზღუდვა \"%s\"" -#: commands/tablecmds.c:16049 +#: commands/tablecmds.c:17820 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "დანაყოფი \"%s\" უკვე დაყოფილი ცხრილიდან \"%s.%s\" მოხსნის რიგშია" -#: commands/tablecmds.c:16078 commands/tablecmds.c:16124 parser/parse_utilcmd.c:3261 +#: commands/tablecmds.c:17849 commands/tablecmds.c:17897 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "ურთიერთობა \"%s\" ურთიერთობის \"%s\" დანაყოფს არ წარმოადგენს" -#: commands/tablecmds.c:16130 +#: commands/tablecmds.c:17903 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "ურთიერთობა \"%s\" ურთიერთობის \"%s\" მშობელს არ წარმოადგენს" -#: commands/tablecmds.c:16357 +#: commands/tablecmds.c:18174 #, c-format msgid "typed tables cannot inherit" msgstr "ტიპიზირებულ ცხრილებს მემკვიდრეობითობა არ შეუძლიათ" -#: commands/tablecmds.c:16387 +#: commands/tablecmds.c:18204 #, c-format msgid "table is missing column \"%s\"" msgstr "ცხრილს აკლია სვეტი \"%s\"" -#: commands/tablecmds.c:16398 +#: commands/tablecmds.c:18215 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "ცხრილს აქვს სვეტი \"%s\" მაშინ, როცა ტიპი \"%s\"-ს მოითხოვს" -#: commands/tablecmds.c:16407 +#: commands/tablecmds.c:18224 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "ცხრილს \"%s\" სვეტისთვის \"%s\" სხვა ტიპი აქვს" -#: commands/tablecmds.c:16421 +#: commands/tablecmds.c:18238 #, c-format msgid "table has extra column \"%s\"" msgstr "ცხრილს აქვს დამატებითი სვეტი \"%s\"" -#: commands/tablecmds.c:16473 +#: commands/tablecmds.c:18290 #, c-format msgid "\"%s\" is not a typed table" msgstr "\"%s\" ტიპიზირებული ცხრილი არაა" -#: commands/tablecmds.c:16647 +#: commands/tablecmds.c:18470 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "არაუნიკალურ ინდექსს \"%s\" რეპლიკის იდენტიფიკაციისთვის ვერ გამოიყენებთ" -#: commands/tablecmds.c:16653 +#: commands/tablecmds.c:18476 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "არასაუყოვნებლივ ინდექსს \"%s\" რეპლიკის იდენფიტიკაციისთვის ვერ გამოიყენებთ" -#: commands/tablecmds.c:16659 +#: commands/tablecmds.c:18482 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "გამოსახულების ინდექსს \"%s\" რეპლიკის იდენტიფიკაციისთვის ვერ გამოიყენებთ" -#: commands/tablecmds.c:16665 +#: commands/tablecmds.c:18488 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "ნაწილობრივი ინდექსის (\"%s\") რეპლიკის იდენტიფიკატორად გამოყენება შეუძლებელია" -#: commands/tablecmds.c:16682 +#: commands/tablecmds.c:18505 #, c-format msgid "index \"%s\" cannot be used as replica identity because column %d is a system column" msgstr "ინდექსს \"%s\" რეპლიკის იდენტიფიკაციისთვის ვერ გამოიყენებთ, რადგან სვეტი %d სისტემური სვეტია" -#: commands/tablecmds.c:16689 +#: commands/tablecmds.c:18512 #, c-format msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable" msgstr "ინდექსს \"%s\" რეპლიკის იდენტიფიკაციისთვის ვერ გამოიყენებთ, რადგან სვეტი %s განულებადია" -#: commands/tablecmds.c:16941 +#: commands/tablecmds.c:18761 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "ცხრილის \"%s\" ჟურნალში ჩაწერის სტატუსის შეცვლა შეუძლებელია, რადგან ის დროებითია" -#: commands/tablecmds.c:16965 +#: commands/tablecmds.c:18785 #, c-format msgid "cannot change table \"%s\" to unlogged because it is part of a publication" msgstr "" -#: commands/tablecmds.c:16967 +#: commands/tablecmds.c:18787 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "უჟურნალო ურთიერთობების რეპლიკაცია შეუძლებელია." -#: commands/tablecmds.c:17012 +#: commands/tablecmds.c:18832 #, c-format msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\"" msgstr "" -#: commands/tablecmds.c:17022 +#: commands/tablecmds.c:18842 #, c-format msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\"" msgstr "" -#: commands/tablecmds.c:17080 +#: commands/tablecmds.c:18906 #, c-format msgid "cannot move an owned sequence into another schema" -msgstr "" +msgstr "მფლობელობაში არსებული მიმდევრობის სხვა სქემაში გადატანა შეუძლებელია" -#: commands/tablecmds.c:17185 +#: commands/tablecmds.c:19014 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "სქემაში (%2$s) ურთიერთობა (%1$s) უკვე არსებობს" -#: commands/tablecmds.c:17606 +#: commands/tablecmds.c:19439 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "\"%s\" ცხრილი ან მატერიალიზებული ხედი არაა" -#: commands/tablecmds.c:17759 +#: commands/tablecmds.c:19592 #, c-format msgid "\"%s\" is not a composite type" msgstr "ტიპი %s კომპოზიტური არაა" -#: commands/tablecmds.c:17789 +#: commands/tablecmds.c:19622 #, c-format msgid "cannot change schema of index \"%s\"" msgstr "ინდექსის (%s) სქემის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:17791 commands/tablecmds.c:17805 +#: commands/tablecmds.c:19624 commands/tablecmds.c:19638 #, c-format msgid "Change the schema of the table instead." msgstr "ამის მაგიერ ცხრილის სქემა შეცვლათ." -#: commands/tablecmds.c:17795 +#: commands/tablecmds.c:19628 #, c-format msgid "cannot change schema of composite type \"%s\"" msgstr "კომპოზიტური ტიპის (%s) სქემის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:17803 +#: commands/tablecmds.c:19636 #, c-format msgid "cannot change schema of TOAST table \"%s\"" msgstr "\"TOAST\" ცხრილის (%s) სქემის შეცვლა შეუძლებელია" -#: commands/tablecmds.c:17835 +#: commands/tablecmds.c:19668 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "ერთზე მეტ სვეტთან ერთად დაყოფის სტრატეგიას \"list\" ვერ გამოიყენებთ" -#: commands/tablecmds.c:17901 +#: commands/tablecmds.c:19734 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "დანაყოფის გასაღებში დასახელებული სვეტი \"%s\" არ არსებობს" -#: commands/tablecmds.c:17909 +#: commands/tablecmds.c:19742 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "დანაყოფის გასაღებში სისტემური სვეტის (%s) გამოყენება შეუძლებელია" -#: commands/tablecmds.c:17920 commands/tablecmds.c:18010 +#: commands/tablecmds.c:19756 commands/tablecmds.c:19849 #, c-format msgid "cannot use generated column in partition key" msgstr "გენერირებულ სვეტს დანაყოფის გასაღებში ვერ გამოიყენებთ" -#: commands/tablecmds.c:17921 commands/tablecmds.c:18011 commands/trigger.c:656 rewrite/rewriteHandler.c:934 rewrite/rewriteHandler.c:969 -#, c-format -msgid "Column \"%s\" is a generated column." -msgstr "სვეტი \"%s\" გენერირებული სვეტია." - -#: commands/tablecmds.c:17993 +#: commands/tablecmds.c:19829 #, c-format msgid "partition key expressions cannot contain system column references" msgstr "დანაყოფის გასაღების გამოსახულებები, არ შეიძლება, სისტემურ სვეტზე მითითებებს შეიცავდნენ" -#: commands/tablecmds.c:18040 +#: commands/tablecmds.c:19879 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "ფუნქცია დანაყოფის გასაღების გამოსახულებაში აუცილებლად უნდა იყოს მონიშნული, როგორც IMMUTABLE" -#: commands/tablecmds.c:18049 +#: commands/tablecmds.c:19888 #, c-format msgid "cannot use constant expression as partition key" msgstr "დაყოფის გასაღების გამოსახულებაში მუდმივ გამოსახულებას ვერ გამოიყენებთ" -#: commands/tablecmds.c:18070 +#: commands/tablecmds.c:19909 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "დანაყოფის გამოსახულებისათვის კოლაციის დადგენა შეუძლებელია" -#: commands/tablecmds.c:18105 +#: commands/tablecmds.c:19944 #, c-format msgid "You must specify a hash operator class or define a default hash operator class for the data type." msgstr "" -#: commands/tablecmds.c:18111 +#: commands/tablecmds.c:19950 #, c-format msgid "You must specify a btree operator class or define a default btree operator class for the data type." msgstr "" -#: commands/tablecmds.c:18393 +#: commands/tablecmds.c:20210 #, c-format msgid "\"%s\" is already a partition" msgstr "\"%s\" უკვე დანაყოფია" -#: commands/tablecmds.c:18399 +#: commands/tablecmds.c:20216 #, c-format msgid "cannot attach a typed table as partition" msgstr "ტიპიზირებული ცხრილის, როგორც დანაყოფის მიბმა შეუძლებელია" -#: commands/tablecmds.c:18415 +#: commands/tablecmds.c:20232 #, c-format msgid "cannot attach inheritance child as partition" msgstr "მემკვიდრეობის შვილის დანაყოფად მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18429 +#: commands/tablecmds.c:20246 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "მემკვიდრეობის მშობლის დანაყოფად მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18463 +#: commands/tablecmds.c:20280 #, c-format msgid "cannot attach a temporary relation as partition of permanent relation \"%s\"" msgstr "დროებითი ურითერთობის, როგორც მუდმივი ურთიერთობის (\"%s\") დანაყოფის მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18471 +#: commands/tablecmds.c:20288 #, c-format msgid "cannot attach a permanent relation as partition of temporary relation \"%s\"" msgstr "მუდმივი ურთიერთობის, როგორც დროებითი ურთიერთობის (%s) დანაყოფის მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18479 +#: commands/tablecmds.c:20296 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "სხვა სესიის დროებითი ურთიერთობის დანაყოფის მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18486 +#: commands/tablecmds.c:20303 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "სხვა სესიის დროებითი ურთიერთობის დანაყოფად მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18506 +#: commands/tablecmds.c:20323 #, c-format msgid "table \"%s\" being attached contains an identity column \"%s\"" msgstr "ცხრილი \"%s\", რომლის მიმაგრებაც მიმდინარეობს, შეიცავს იდენტიფიკაციის სვეტს \"%s\"" -#: commands/tablecmds.c:18508 +#: commands/tablecmds.c:20325 #, c-format msgid "The new partition may not contain an identity column." msgstr "ახალი დანაყოფი არ შეიძლება, იდენტიფიკატორის სვეტს შეიცავდეს." -#: commands/tablecmds.c:18516 +#: commands/tablecmds.c:20333 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "ცხრილი \"%s\" შეიცავს სვეტს \"%s\", რომელიც მშობელში \"%s\" აღმოჩენილი არაა" -#: commands/tablecmds.c:18519 +#: commands/tablecmds.c:20336 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "ახალი დანაყოფი მხოლოდ მშობელში არსებულ სვეტებს შეიძლება, შეიცავდეს." -#: commands/tablecmds.c:18531 +#: commands/tablecmds.c:20348 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "ტრიგერი \"%s\" ხელს უშლის ცხრილს \"%s\" დანაყოფად გადაიქცეს" -#: commands/tablecmds.c:18533 +#: commands/tablecmds.c:20350 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "დანაყოფებზე იდენტიფიკაციის სვეტები მხარდაჭერილი არაა." -#: commands/tablecmds.c:18694 +#: commands/tablecmds.c:20532 #, c-format msgid "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "გარე ცხრილის \"%s\" დაყოფილი ცხრილის (\"%s\") დანაყოფის სახით მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:18697 +#: commands/tablecmds.c:20535 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "დაყოფილი ცხრილი \"%s\" უნიკალურ ცხრილებს შეიცავს." -#: commands/tablecmds.c:19019 +#: commands/tablecmds.c:20858 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "ნაგულისხმევი დანაყოფის არსებობის შემთხვევაში დანაყოფების ერთდროული მოხსნა შეუძლებელია" -#: commands/tablecmds.c:19128 +#: commands/tablecmds.c:20967 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "დაყოფილი ცხრილი \"%s\" ერთდროულად წაიშალა" -#: commands/tablecmds.c:19134 +#: commands/tablecmds.c:20973 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "დანაყოფი \"%s\" ერთდროულად წაიშალა" -#: commands/tablecmds.c:19661 commands/tablecmds.c:19681 commands/tablecmds.c:19702 commands/tablecmds.c:19721 commands/tablecmds.c:19763 +#: commands/tablecmds.c:21596 commands/tablecmds.c:21616 commands/tablecmds.c:21637 commands/tablecmds.c:21656 commands/tablecmds.c:21705 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "ერთი ინდექსის ინდექსის (%s) მეორე ინდექსის (\"%s) დანაყოფად მიმაგრება შეუძლებელია" -#: commands/tablecmds.c:19664 +#: commands/tablecmds.c:21599 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "ინდექსი %s სხვა ინდექსზეა უკვე მიმაგრებული." -#: commands/tablecmds.c:19684 +#: commands/tablecmds.c:21619 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "ინდექსი %s ცხრილის (%s) არცერთი დანაყოფის ინდექსი არაა." -#: commands/tablecmds.c:19705 +#: commands/tablecmds.c:21640 #, c-format msgid "The index definitions do not match." msgstr "ინდექსის აღწერები არ ემთხვევა." -#: commands/tablecmds.c:19724 +#: commands/tablecmds.c:21659 #, c-format msgid "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint exists for index \"%s\"." msgstr "" -#: commands/tablecmds.c:19766 +#: commands/tablecmds.c:21708 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "ცხრილისთვის %s სხვა ინდექსი უკვე მიმაგრებულია." -#: commands/tablecmds.c:20002 +#: commands/tablecmds.c:21831 +#, c-format +msgid "invalid primary key definition" +msgstr "არასწორი ძირითადი გასაღების აღწერა" + +#: commands/tablecmds.c:21832 +#, c-format +msgid "Column \"%s\" of relation \"%s\" is not marked NOT NULL." +msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" არაა დანიშნული, როგორც NOT NULL." + +#: commands/tablecmds.c:21967 #, c-format msgid "column data type %s does not support compression" msgstr "სვეტის მონაცემის ტიპს (%s) შეკუმშვის მხარდაჭერა არ გააჩნია" -#: commands/tablecmds.c:20009 +#: commands/tablecmds.c:21974 #, c-format msgid "invalid compression method \"%s\"" msgstr "შეკუმშვის არასწორი მეთოდი \"%s\"" -#: commands/tablecmds.c:20035 +#: commands/tablecmds.c:22000 #, c-format msgid "invalid storage type \"%s\"" msgstr "საცავის არასწორი ტიპი \"%s\"" -#: commands/tablecmds.c:20045 +#: commands/tablecmds.c:22010 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "სვეტის მონაცემების ტიპს %s საცავის ტიპად მხოლოდ PLAIN შეიძლება, ჰქონდეს" -#: commands/tablecmds.c:20242 -#, c-format -msgid "can not find partition for split partition row" -msgstr "დაყოფილი დანაყოფის მწკრივისთვის დანაყოფი ვერ ვიპოვე" - -#: commands/tablecmds.c:20328 -#, c-format -msgid "cannot create as partition of temporary relation of another session" -msgstr "სხვა სესის დროებითი ურთიერთობის დანაყოფის სახით ვერ შექმნით" - -#: commands/tablecmds.c:20399 -#, c-format -msgid "cannot create a permanent relation as partition of temporary relation \"%s\"" -msgstr "მუდმივ ურთიერთობას დროებითი ურთიერთობის \"%s\" დანაყოფის სახით ვერ შექმნით" - #: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" @@ -11645,277 +11872,272 @@ msgstr "ცხრილების სივრცის (%u) საქაღ msgid "You can remove the directories manually if necessary." msgstr "თუ გჭირდებათ, საქაღალდეები შეგიძლიათ ხელითაც წაშალოთ." -#: commands/trigger.c:225 commands/trigger.c:236 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "\"%s\" is a table" msgstr "\"%s\" ცხრილია" -#: commands/trigger.c:227 commands/trigger.c:238 +#: commands/trigger.c:229 commands/trigger.c:240 #, c-format msgid "Tables cannot have INSTEAD OF triggers." msgstr "ცხრილებს INSTEAD OF ტიპის ტრიგერები ვერ ექნებათ." -#: commands/trigger.c:259 +#: commands/trigger.c:261 #, c-format msgid "\"%s\" is a partitioned table" msgstr "\"%s\" დაყოფილი ცხრილია" -#: commands/trigger.c:261 +#: commands/trigger.c:263 #, c-format msgid "ROW triggers with transition tables are not supported on partitioned tables." msgstr "დანაყოფებზე იდენტიფიკაციის სვეტები მხარდაჭერილი არაა." -#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 +#: commands/trigger.c:275 commands/trigger.c:282 commands/trigger.c:446 #, c-format msgid "\"%s\" is a view" msgstr "\"%s\" ხედია" -#: commands/trigger.c:275 +#: commands/trigger.c:277 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." msgstr "ხედებს მწკრივის დონის BEFORE და AFTER ტრიგერები ვერ ექნებათ." -#: commands/trigger.c:282 +#: commands/trigger.c:284 #, c-format msgid "Views cannot have TRUNCATE triggers." msgstr "ხედებს TRUNCATE ტიპის ტრიგერები ვერ ექნებათ." -#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 +#: commands/trigger.c:292 commands/trigger.c:304 commands/trigger.c:439 #, c-format msgid "\"%s\" is a foreign table" msgstr "\"%s\" გარე ცხრილია" -#: commands/trigger.c:292 +#: commands/trigger.c:294 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." msgstr "გარე ცხრილებს INSTEAD OF ტრიგერები ვერ ექნებათ." -#: commands/trigger.c:304 +#: commands/trigger.c:306 #, c-format msgid "Foreign tables cannot have constraint triggers." msgstr "გარე ცხრილებს შეზღუდვის ტრიგერები ვერ ექნებათ." -#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 +#: commands/trigger.c:311 commands/trigger.c:1330 commands/trigger.c:1437 #, c-format msgid "relation \"%s\" cannot have triggers" msgstr "ურთიერთობას \"%s\" ტრიგერები არ შეიძლება ჰქონდეთ" -#: commands/trigger.c:380 +#: commands/trigger.c:382 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" msgstr "TRUNCATE FOR EACH ROW ტრიგერები მხარდაუჭერელია" -#: commands/trigger.c:388 +#: commands/trigger.c:390 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" msgstr "INSTEAD OF ტრიგერები უნდა იყოს FOR EACH ROW" -#: commands/trigger.c:392 +#: commands/trigger.c:394 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" msgstr "INSTEAD OF ტრიგერებს WHEN პირობები არ შეიძლება ჰქონდეს" -#: commands/trigger.c:396 +#: commands/trigger.c:398 #, c-format msgid "INSTEAD OF triggers cannot have column lists" msgstr "INSTEAD OF ტრიგერებს სვეტების სიები არ შეიძლება ჰქონდეთ" -#: commands/trigger.c:425 +#: commands/trigger.c:427 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "" -#: commands/trigger.c:426 +#: commands/trigger.c:428 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "გარდამავალი ცხრილების სახელებისთვის OLD TABLE ან NEW TABLE გამოიყენეთ." -#: commands/trigger.c:439 +#: commands/trigger.c:441 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "გარე ცხრილებზე არსებულ ტრიგერებს გარდამავალი ცხრილები ვერ ექნებათ." -#: commands/trigger.c:446 +#: commands/trigger.c:448 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "ხედებზე არსებულ ტრიგერებს გარდამავალი ცხრილები ვერ ექნებათ." -#: commands/trigger.c:462 +#: commands/trigger.c:464 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "ROW ტრიგერები გარდამავალი ცხრილებით დანაყოფებზე მხარდაჭერილი არაა" -#: commands/trigger.c:466 +#: commands/trigger.c:468 #, c-format msgid "ROW triggers with transition tables are not supported on inheritance children" msgstr "ROW ტრიგერები გარდამავალი ცხრილებით მემკვიდრეობის შვილებზე მხარდაჭერილი არაა" -#: commands/trigger.c:472 +#: commands/trigger.c:474 #, c-format msgid "transition table name can only be specified for an AFTER trigger" msgstr "გარდამავალი ცხრილის სახელი მხოლოდ ტრიგერისთვის AFTER შეგიძლიათ, მიუთითოთ" -#: commands/trigger.c:477 +#: commands/trigger.c:479 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "ტრიგერები TRUNCATE გარდამავალი ცხრილებით მხარდაჭერილი არაა" -#: commands/trigger.c:494 +#: commands/trigger.c:496 #, c-format msgid "transition tables cannot be specified for triggers with more than one event" msgstr "გარდამავალი ცხრილების მითითება ტრიგერებისთვის, რომლებსაც ერთზე მეტი მოვლენა გააჩნიათ, შეუძლებელია" -#: commands/trigger.c:505 +#: commands/trigger.c:507 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "გარდამავალი ცხრილების მითითება ტრიგერებისთვის, რომლებსაც სვეტების სიები გააჩნიათ, შეუძლებელია" -#: commands/trigger.c:522 +#: commands/trigger.c:524 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" msgstr "NEW TABLE მხოლოდ INSERT ან UPDATE ტრიგერისთვის შეგიძლიათ, მიუთითოთ" -#: commands/trigger.c:527 +#: commands/trigger.c:529 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE -ის რამდენჯერმე მითითება აკრძალულია" -#: commands/trigger.c:537 +#: commands/trigger.c:539 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" msgstr "OLD TABLE მხოლოდ DELETE ან UPDATE ტრიგერისთვის შეგიძლიათ, მიუთითოთ" -#: commands/trigger.c:542 +#: commands/trigger.c:544 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE -ის რამდენჯერმე მითითება აკრძალულია" -#: commands/trigger.c:552 +#: commands/trigger.c:554 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "OLD TABLE-ის და NEW TABLE-ის სახელები ერთი და იგივე ვერ იქნება" -#: commands/trigger.c:616 commands/trigger.c:629 +#: commands/trigger.c:618 commands/trigger.c:631 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" msgstr "გამოსახულების ტრიგერის WHEN პირობა არ შეუძლება, სვეტის მნიშვნელობებზე მიუთითებდეს" -#: commands/trigger.c:621 +#: commands/trigger.c:623 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" msgstr "INSERT-ის ტრიგერის WHEN პირობა არ შეიძლება, OLD მნიშვნელობებზე მიუთითებდეს" -#: commands/trigger.c:634 +#: commands/trigger.c:636 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" msgstr "DELETE-ის ტრიგერის WHEN პირობა არ შეიძლება, NEW მნიშვნელობებზე მიუთითებდეს" -#: commands/trigger.c:639 +#: commands/trigger.c:641 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" msgstr "BEFORE-ის ტრიგერის WHEN პირობა არ შეიძლება, NEW სისტემურ სვეტებზე მიუთითებდეს" -#: commands/trigger.c:647 commands/trigger.c:655 +#: commands/trigger.c:650 commands/trigger.c:658 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "BEFORE-ის ტრიგერის WHEN პირობა არ შეიძლება, NEW გენერირებულ სვეტებზე მიუთითებდეს" -#: commands/trigger.c:648 +#: commands/trigger.c:651 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "" -#: commands/trigger.c:763 commands/trigger.c:1607 +#: commands/trigger.c:766 commands/trigger.c:1613 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "ტრიგერი \"%s\" ურთიერთობისთვის \"%s\" უკვე არსებობს" -#: commands/trigger.c:776 +#: commands/trigger.c:779 #, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" msgstr "ტრიგერი \"%s\" ურთიერთობისთვის \"%s\" შიდა ან შვილი ტრიგერია" -#: commands/trigger.c:795 +#: commands/trigger.c:798 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" msgstr "ტრიგერი \"%s\" ურთიერთობისთვის \"%s\", შეზღუდვის ტრიგერია" -#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 +#: commands/trigger.c:1402 commands/trigger.c:1556 commands/trigger.c:1837 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "ტრიგერი \"%s\" ცხრილისთვის \"%s\" არ არსებობს" -#: commands/trigger.c:1522 +#: commands/trigger.c:1528 #, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" msgstr "ტრიგერის (%s) (ცხრილზე %s) სახელის გადარქმევა შეუძლებელია" -#: commands/trigger.c:1524 +#: commands/trigger.c:1530 #, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." msgstr "ამის მაგიერ დაყოფილ ცხრილზე ('%s\") ტრიგერს გადაარქვით სახელი." -#: commands/trigger.c:1624 +#: commands/trigger.c:1630 #, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" msgstr "ურთიერთობაზე \"%2$s\" ტრიგერს \"%1$s\" სახელი გადაერქვა" -#: commands/trigger.c:1770 +#: commands/trigger.c:1776 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "წვდომა აკრძალულია: %s სისტემური ტრიგერია" -#: commands/trigger.c:2379 +#: commands/trigger.c:2385 #, c-format msgid "trigger function %u returned null value" msgstr "ტრიგერის ფუნქციამ %u ნულოვანი მნიშვნელობა დააბრუნა" -#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 commands/trigger.c:3263 +#: commands/trigger.c:2445 commands/trigger.c:2665 commands/trigger.c:2918 commands/trigger.c:3273 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "BEFORE STATEMENT ტრიგერს მნიშვნელობის დაბრუნება არ შეუძლია" -#: commands/trigger.c:2515 +#: commands/trigger.c:2523 #, c-format msgid "moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported" msgstr "მწკრივის სხვა დანაყოფში გადატანა BEFORE FOR EACH ROW ტრიგერის დროს მხარდაჭერილი არაა" -#: commands/trigger.c:2516 +#: commands/trigger.c:2524 #, c-format msgid "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." msgstr "ტრიგერის \"%s\" შესრულებამდე სვეტი დანაყოფში \"%s.%s\" უნდა ყოფილიყო." -#: commands/trigger.c:3340 executor/nodeModifyTable.c:2363 executor/nodeModifyTable.c:2446 -#, c-format -msgid "tuple to be updated was already modified by an operation triggered by the current command" -msgstr "" - -#: commands/trigger.c:3341 executor/nodeModifyTable.c:1532 executor/nodeModifyTable.c:1606 executor/nodeModifyTable.c:2364 executor/nodeModifyTable.c:2447 executor/nodeModifyTable.c:3075 executor/nodeModifyTable.c:3236 +#: commands/trigger.c:3351 executor/nodeModifyTable.c:1685 executor/nodeModifyTable.c:1759 executor/nodeModifyTable.c:2566 executor/nodeModifyTable.c:2656 executor/nodeModifyTable.c:3328 executor/nodeModifyTable.c:3498 #, c-format msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows." msgstr "" -#: commands/trigger.c:3382 executor/nodeLockRows.c:228 executor/nodeLockRows.c:237 executor/nodeModifyTable.c:305 executor/nodeModifyTable.c:1548 executor/nodeModifyTable.c:2381 executor/nodeModifyTable.c:2589 +#: commands/trigger.c:3392 executor/nodeLockRows.c:228 executor/nodeLockRows.c:237 executor/nodeModifyTable.c:388 executor/nodeModifyTable.c:1701 executor/nodeModifyTable.c:2582 executor/nodeModifyTable.c:2807 #, c-format msgid "could not serialize access due to concurrent update" msgstr "ერთდროული განახლების გამო წვდომის სერიალიზაცია შეუძლებელია" -#: commands/trigger.c:3390 executor/nodeModifyTable.c:1638 executor/nodeModifyTable.c:2464 executor/nodeModifyTable.c:2613 executor/nodeModifyTable.c:3093 +#: commands/trigger.c:3400 executor/nodeModifyTable.c:1791 executor/nodeModifyTable.c:2673 executor/nodeModifyTable.c:2831 executor/nodeModifyTable.c:3346 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "ერთდროული წაშლის გამო წვდომის სერიალიზაცია შეუძლებელია" -#: commands/trigger.c:4597 +#: commands/trigger.c:4635 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" msgstr "" -#: commands/trigger.c:5780 +#: commands/trigger.c:5831 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "შეზღუდვა გადადებადი არაა %s" -#: commands/trigger.c:5803 +#: commands/trigger.c:5854 #, c-format msgid "constraint \"%s\" does not exist" msgstr "შეზღუდვა \"%s\" არ არსებობს" @@ -11953,7 +12175,7 @@ msgstr "ტექსტის ძებნის დამმუშავებ #: commands/tsearchcmds.c:278 #, c-format msgid "text search parser lextypes method is required" -msgstr "" +msgstr "აუცილებელია ტექსტური ძებნის დამმუშაევებლის lextypes-ის მეთოდი" #: commands/tsearchcmds.c:372 #, c-format @@ -12025,7 +12247,7 @@ msgstr "საბაზისო ტიპის შესაცვლელა msgid "Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE." msgstr "" -#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 +#: commands/typecmds.c:331 commands/typecmds.c:1486 commands/typecmds.c:4471 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "ტიპის უცნობი ატრიბუტი: %s" @@ -12045,7 +12267,7 @@ msgstr "%s მასივის ელემენტის ტიპი არ msgid "alignment \"%s\" not recognized" msgstr "სწორება \"%s\" უცნობია" -#: commands/typecmds.c:454 commands/typecmds.c:4354 +#: commands/typecmds.c:454 commands/typecmds.c:4345 #, c-format msgid "storage \"%s\" not recognized" msgstr "საცავი \"%s\" უცნობია" @@ -12075,332 +12297,347 @@ msgstr "ელემენტის ტიპის მითითება გ msgid "\"%s\" is not a valid base type for a domain" msgstr "%s დომენისთვის სწორ ბაზისურ ტიპს არ წარმოადგენს" -#: commands/typecmds.c:883 +#: commands/typecmds.c:885 #, c-format msgid "multiple default expressions" msgstr "ერთზე მეტი ნაგულისხმევი გამოსახულება" -#: commands/typecmds.c:946 commands/typecmds.c:955 +#: commands/typecmds.c:945 commands/typecmds.c:960 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "კონფლიქტური NULL/NOT NULL შეზღუდვები" -#: commands/typecmds.c:971 +#: commands/typecmds.c:950 +#, c-format +msgid "not-null constraints for domains cannot be marked NO INHERIT" +msgstr "არანულოვანი შეზღუდვები დომენებისთვის არ შეიძლება, NO INHERIT-ით მონიშნოთ" + +#: commands/typecmds.c:977 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "დომენის შემოწმების შეზღუდვების, როგორც NO INHERIT, მონიშვნა შეუძლებელია" -#: commands/typecmds.c:980 commands/typecmds.c:2940 +#: commands/typecmds.c:988 #, c-format msgid "unique constraints not possible for domains" msgstr "უნიკალური შეზღუდვები დომენებისთვის შეუძლებელია" -#: commands/typecmds.c:986 commands/typecmds.c:2946 +#: commands/typecmds.c:995 #, c-format msgid "primary key constraints not possible for domains" msgstr "ძირითადი გასაღების შეზღუდვა დომენებისთვის შეუძლებელია" -#: commands/typecmds.c:992 commands/typecmds.c:2952 +#: commands/typecmds.c:1002 #, c-format msgid "exclusion constraints not possible for domains" msgstr "გაშვების შეზღუდვა დომენებისთვის შეუძლებელია" -#: commands/typecmds.c:998 commands/typecmds.c:2958 +#: commands/typecmds.c:1009 #, c-format msgid "foreign key constraints not possible for domains" msgstr "გარე გასაღების შეზღუდვა დომენებისთვის შეუძლებელია" -#: commands/typecmds.c:1007 commands/typecmds.c:2967 +#: commands/typecmds.c:1019 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "" -#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 +#: commands/typecmds.c:1027 +#, c-format +msgid "specifying GENERATED not supported for domains" +msgstr "დომენებისთვის GENERATED-ის მითითება მხარდაჭერილი არაა" + +#: commands/typecmds.c:1035 +#, c-format +msgid "specifying constraint enforceability not supported for domains" +msgstr "შეზღუდვის ნაძალადევობის მითითება დომენებისთვის მხარდაჭერილი არაა" + +#: commands/typecmds.c:1353 utils/cache/typcache.c:2745 #, c-format msgid "%s is not an enum" msgstr "%s ჩამონათვალი არაა" -#: commands/typecmds.c:1468 +#: commands/typecmds.c:1494 #, c-format msgid "type attribute \"subtype\" is required" msgstr "ტიპის ატრიბუტი \"subtype\" აუცილებელია" -#: commands/typecmds.c:1473 +#: commands/typecmds.c:1499 #, c-format msgid "range subtype cannot be %s" msgstr "%s დიაპაზონის ქვეტიპი ვერ იქნება" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1518 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "" -#: commands/typecmds.c:1502 +#: commands/typecmds.c:1528 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "" -#: commands/typecmds.c:1503 +#: commands/typecmds.c:1529 #, c-format msgid "Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE." msgstr "" -#: commands/typecmds.c:1975 +#: commands/typecmds.c:2005 #, c-format msgid "type input function %s has multiple matches" msgstr "ტიპის შეყვანის ფუნქციის (%s) რამდენიმე ასლი არსებობს" -#: commands/typecmds.c:1993 +#: commands/typecmds.c:2023 #, c-format msgid "type input function %s must return type %s" msgstr "ტიპის შეყვანის ფუნქციამ (\"%s\") უნდა დააბრუნოს ტიპი \"%s\"" -#: commands/typecmds.c:2009 +#: commands/typecmds.c:2039 #, c-format msgid "type input function %s should not be volatile" msgstr "ტიპის შეყვანის ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2037 +#: commands/typecmds.c:2067 #, c-format msgid "type output function %s must return type %s" msgstr "ტიპის გამოტანის ფუნქციამ (%s) უნდა დააბრუნოს ტიპი \"%s\"" -#: commands/typecmds.c:2044 +#: commands/typecmds.c:2074 #, c-format msgid "type output function %s should not be volatile" msgstr "ტიპის გამოტანის ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2073 +#: commands/typecmds.c:2103 #, c-format msgid "type receive function %s has multiple matches" msgstr "ტიპის მიღების ფუქნციის (%s) რამდენიმე ასლი არსებობს" -#: commands/typecmds.c:2091 +#: commands/typecmds.c:2121 #, c-format msgid "type receive function %s must return type %s" msgstr "ტიპის მიღების ფუნქციამ (%s) უნდა დააბრუნოს ტიპი %s" -#: commands/typecmds.c:2098 +#: commands/typecmds.c:2128 #, c-format msgid "type receive function %s should not be volatile" msgstr "ტიპის მიღების ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2126 +#: commands/typecmds.c:2156 #, c-format msgid "type send function %s must return type %s" msgstr "ტიპის გაგზავნის ფუნქციამ (%s) უნდა დააბრუნოს ტიპი \"%s\"" -#: commands/typecmds.c:2133 +#: commands/typecmds.c:2163 #, c-format msgid "type send function %s should not be volatile" msgstr "ტიპის გაგზავნის ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2160 +#: commands/typecmds.c:2190 #, c-format msgid "typmod_in function %s must return type %s" msgstr "typmod_in ფუნქციამ (%s) უნდა დააბრუნოს ტიპი %s" -#: commands/typecmds.c:2167 +#: commands/typecmds.c:2197 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "ტიპის მოდიფიკატორის შეყვანის ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2194 +#: commands/typecmds.c:2224 #, c-format msgid "typmod_out function %s must return type %s" msgstr "typmod_out ფუნქციამ (%s) უნდა დააბრუნოს ტიპი %s" -#: commands/typecmds.c:2201 +#: commands/typecmds.c:2231 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "ტიპის მოდიფიკატორის გამოტანის ფუნქცია (%s) ცვალებადი არ უნდა იყოს" -#: commands/typecmds.c:2228 +#: commands/typecmds.c:2258 #, c-format msgid "type analyze function %s must return type %s" msgstr "ტიპის ანალიზის ფუნქციამ (%s) უნდა დააბრუნოს ტიპი %s" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2287 #, c-format msgid "type subscripting function %s must return type %s" msgstr "" -#: commands/typecmds.c:2267 +#: commands/typecmds.c:2297 #, c-format msgid "user-defined types cannot use subscripting function %s" -msgstr "" +msgstr "მომხმარებლის აღწერილ ტიპებს არ შეუძლიათ, გამოიყენონ გამოწერის ფუნქცია %s" -#: commands/typecmds.c:2313 +#: commands/typecmds.c:2343 #, c-format msgid "You must specify an operator class for the range type or define a default operator class for the subtype." msgstr "" -#: commands/typecmds.c:2344 +#: commands/typecmds.c:2374 #, c-format msgid "range canonical function %s must return range type" msgstr "კანონიკური დიაპაზონის ფუნქციამ (%s) დიაპაზონის ტიპი უნდა დააბრუნოს" -#: commands/typecmds.c:2350 +#: commands/typecmds.c:2380 #, c-format msgid "range canonical function %s must be immutable" msgstr "კანონიკური დიაპაზონის ფუნქცია (%s) მუდმივი უნდა იყოს" -#: commands/typecmds.c:2386 +#: commands/typecmds.c:2416 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "დიაპაზონის ქვეტიპის განსხვავების ფუნქციამ (%s) უნდა დააბრუნოს ტიპი: %s" -#: commands/typecmds.c:2393 +#: commands/typecmds.c:2423 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "დიაპაზონის ქვეტიპის განსხვავების ფუნქცია (%s) უცვლელი უნდა იყოს" -#: commands/typecmds.c:2420 +#: commands/typecmds.c:2450 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_type-ის მასივის OID-ის მნიშვნელობა დაყენებული არაა" -#: commands/typecmds.c:2453 +#: commands/typecmds.c:2483 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_type-ის მრავალდიაპაზონიანი OID-ის მნიშვნელობა დაყენებული არაა" -#: commands/typecmds.c:2486 +#: commands/typecmds.c:2516 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_type-ის მრავალდიაპაზონიანი მასივის OID-ის მნიშვნელობა დაყენებული არაა" -#: commands/typecmds.c:2868 commands/typecmds.c:3093 +#: commands/typecmds.c:2898 commands/typecmds.c:3080 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "დომენის (\"%2$s\") შეზღუდვა (\"%1$s\") არ არსებობს" -#: commands/typecmds.c:2872 +#: commands/typecmds.c:2902 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "დომენის (\"%2$s\") შეზღუდვა (\"%1$s\") არ არსებობს. გამოტოვება" -#: commands/typecmds.c:3100 +#: commands/typecmds.c:3087 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "დომენის (\"%2$s\") შეზღუდვა (\"%1$s\") შეზღუდვის შემოწმება არაა" -#: commands/typecmds.c:3180 +#: commands/typecmds.c:3167 #, c-format msgid "column \"%s\" of table \"%s\" contains null values" msgstr "სვეტი \"%s\" (ცხრილში %s) ნულოვან მნიშვნელობებს შეიცავს" -#: commands/typecmds.c:3269 +#: commands/typecmds.c:3256 #, c-format msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint" msgstr "სვეტი \"%s\" ცხრილიდან \"%s\" შეიცავს მნიშვნელობებს, რომელიც ახალ შეზღუდვას არღვევს" -#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 commands/typecmds.c:4073 +#: commands/typecmds.c:3485 commands/typecmds.c:3763 commands/typecmds.c:3848 commands/typecmds.c:4064 #, c-format msgid "%s is not a domain" msgstr "\"%s\" დომენი არაა" -#: commands/typecmds.c:3532 commands/typecmds.c:3686 +#: commands/typecmds.c:3519 commands/typecmds.c:3675 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "შეზღუდვა \"%s\" დომენისთვის %s უკვე არსებობს" -#: commands/typecmds.c:3583 +#: commands/typecmds.c:3570 #, c-format msgid "cannot use table references in domain check constraint" msgstr "" -#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 +#: commands/typecmds.c:3775 commands/typecmds.c:3860 commands/typecmds.c:4214 #, c-format msgid "%s is a table's row type" msgstr "%s ცხრილის მწკრივის ტიპია" -#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 +#: commands/typecmds.c:3785 commands/typecmds.c:3870 commands/typecmds.c:4112 #, c-format msgid "cannot alter array type %s" msgstr "მასივის ტიპის (\"%s\") შეცვლა შეუძლებელია" -#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4114 #, c-format msgid "You can alter type %s, which will alter the array type as well." msgstr "ტიპი %s შეგიძლიათ, შეცვალოთ, რაც მასივის ტიპსაც შეცვლის." -#: commands/typecmds.c:3892 +#: commands/typecmds.c:3883 #, c-format msgid "cannot alter multirange type %s" msgstr "მრავალშუალედანი ტიპის %s შეცვლა შეუძლებელია" -#: commands/typecmds.c:3895 +#: commands/typecmds.c:3886 #, c-format msgid "You can alter type %s, which will alter the multirange type as well." msgstr "შეგიძლიათ შეცვალოთ ტიპი %s, რომელიც მრავალშუალედიან ტიპსაც შეცვლის." -#: commands/typecmds.c:4202 +#: commands/typecmds.c:4193 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "ტიპი \"%s\" სქემაში \"%s\" უკვე არსებობს" -#: commands/typecmds.c:4382 +#: commands/typecmds.c:4373 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "ტიპის საცავს PLAIN-ზე ვერ შეცვლით" -#: commands/typecmds.c:4475 +#: commands/typecmds.c:4466 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "ტიპის ატრიბუტის შეცვლა შეუძლებელია: %s" -#: commands/typecmds.c:4493 +#: commands/typecmds.c:4484 #, c-format msgid "must be superuser to alter a type" msgstr "ტიპის შესაცვლელად ზემომხმარებლის უფლებებია საჭირო" -#: commands/typecmds.c:4514 commands/typecmds.c:4523 +#: commands/typecmds.c:4505 commands/typecmds.c:4514 #, c-format msgid "%s is not a base type" msgstr "%s საბაზისო ტიპი არაა" -#: commands/user.c:200 +#: commands/user.c:201 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSID-ის შეცვლა ახლა უკვე შეუძლებელია" -#: commands/user.c:318 commands/user.c:324 commands/user.c:330 commands/user.c:336 commands/user.c:342 +#: commands/user.c:319 commands/user.c:325 commands/user.c:331 commands/user.c:337 commands/user.c:343 #, c-format msgid "permission denied to create role" msgstr "როლის შექმნის წვდომა აკრძალულია" -#: commands/user.c:319 +#: commands/user.c:320 #, c-format msgid "Only roles with the %s attribute may create roles." msgstr "როლების შექმნა მხოლოდ %s ატრიბუტის მქონე როლებს შეუძლიათ." -#: commands/user.c:325 commands/user.c:331 commands/user.c:337 commands/user.c:343 +#: commands/user.c:326 commands/user.c:332 commands/user.c:338 commands/user.c:344 #, c-format msgid "Only roles with the %s attribute may create roles with the %s attribute." msgstr "მხოლოდ როლებს, რომლებსაც %s ატრიბუტი გააჩნიათ, შეუძლიათ როლის შექმნა, რომელსაც აქვს ატრიბუტი %s." -#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 gram.y:17355 gram.y:17401 utils/adt/acl.c:5568 utils/adt/acl.c:5574 +#: commands/user.c:355 commands/user.c:1386 commands/user.c:1393 gram.y:17493 gram.y:17539 utils/adt/acl.c:5690 utils/adt/acl.c:5696 #, c-format msgid "role name \"%s\" is reserved" msgstr "როლის სახელი \"%s\" დაცულია" -#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 +#: commands/user.c:357 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "როლის სახელები, რომლებიც \"pg_\"-ით იწყება, დაცულია." -#: commands/user.c:377 commands/user.c:1410 +#: commands/user.c:378 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "როლი \"%s\" უკვე არსებობს" -#: commands/user.c:439 commands/user.c:924 +#: commands/user.c:440 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "ცარიელი სტრიქონი არ არის სწორი პაროლი, პაროლის გაწმენდა" -#: commands/user.c:468 +#: commands/user.c:469 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "ბინარული განახლების რეჟიმში pg_authid-ის OID-ის მნიშვნელობა დაყენებული არაა" @@ -12436,8 +12673,8 @@ msgstr "სხვა როლის პაროლის შესაცვლ #: commands/user.c:825 #, c-format -msgid "Only roles with the %s option on role \"%s\" may add members." -msgstr "წევრების დამატება მხოლოდ \"%2$s\" როლზე %1$s პარამეტრის მქონე როლებს შეუძლიათ." +msgid "Only roles with the %s option on role \"%s\" may add or drop members." +msgstr "წევრების დამატება, ან წაშლა, მხოლოდ, \"%2$s\" როლზე %1$s პარამეტრის მქონე როლებს შეუძლიათ." #: commands/user.c:870 #, c-format @@ -12469,7 +12706,7 @@ msgstr "როლების წაშლა მხოლოდ სამიზ msgid "cannot use special role specifier in DROP ROLE" msgstr "სპეციალური როლის მიმთითებლის გამოყენება DROP ROLE-ში შეუძლებელია" -#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:838 commands/variable.c:841 commands/variable.c:947 commands/variable.c:950 utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5423 utils/adt/acl.c:5471 utils/adt/acl.c:5499 utils/adt/acl.c:5518 utils/adt/regproc.c:1571 utils/init/miscinit.c:762 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:864 commands/variable.c:867 commands/variable.c:983 commands/variable.c:986 utils/adt/acl.c:366 utils/adt/acl.c:386 utils/adt/acl.c:5545 utils/adt/acl.c:5593 utils/adt/acl.c:5621 utils/adt/acl.c:5640 utils/adt/regproc.c:1571 utils/init/miscinit.c:804 #, c-format msgid "role \"%s\" does not exist" msgstr "როლი არ არსებობს: \"%s\"" @@ -12534,7 +12771,7 @@ msgstr "ამ როლის სახელის გადარქმევ msgid "MD5 password cleared because of role rename" msgstr "MD5 პაროლი გასუფთავდა როლის სახელის შეცვლის გამო" -#: commands/user.c:1518 gram.y:1297 +#: commands/user.c:1518 gram.y:1286 #, c-format msgid "unrecognized role option \"%s\"" msgstr "როლის უცნობი პარამეტრი: \"%s\"" @@ -12574,244 +12811,249 @@ msgstr "მხოლოდ როლებს, რომლებსაც რ msgid "Only roles with privileges of role \"%s\" may reassign objects to it." msgstr "მხოლოდ როლებს, რომლებსაც როლის, '%s' პრივილეგიები გააჩნია, შეუძლია, ობიექტები თავიდან მიანიჭოს." -#: commands/user.c:1733 +#: commands/user.c:1734 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "როლი \"%s\" სხვა როლის წევრი ვერ იქნება" -#: commands/user.c:1746 +#: commands/user.c:1747 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "როლი \"%s\" როლის \"%s\" წევრია" -#: commands/user.c:1786 commands/user.c:1812 +#: commands/user.c:1787 commands/user.c:1813 #, c-format msgid "%s option cannot be granted back to your own grantor" msgstr "%s პარამეტრს მომნიჭებელს ვერ მიანიჭებთ" -#: commands/user.c:1889 +#: commands/user.c:1890 #, c-format msgid "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" msgstr "როლი \"%s\" უკვე გაწევრდა როლში \"%s\" \"%s\" როლის მიერ" -#: commands/user.c:2024 +#: commands/user.c:2036 #, c-format msgid "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" msgstr "როლს \"%s\" უარი ეთქვა როლში \"%s\" გაწევრებაზე \"%s\" როლის მიერ" -#: commands/user.c:2124 +#: commands/user.c:2137 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "როლი \"%s\" არ შეიძლება, აშკარა წევრებს შეიცავდეს" -#: commands/user.c:2135 commands/user.c:2158 +#: commands/user.c:2148 commands/user.c:2171 #, c-format msgid "permission denied to grant role \"%s\"" msgstr "როლის (\"%s\") დაყენების წვდომა აკრძალულია" -#: commands/user.c:2137 +#: commands/user.c:2150 #, c-format msgid "Only roles with the %s attribute may grant roles with the %s attribute." msgstr "მხოლოდ როლებს, რომლებსაც %s ატრიბუტი გააჩნიათ, შეუძლიათ, როლებს %s ატრიბუტი მიანიჭონ." -#: commands/user.c:2142 commands/user.c:2165 +#: commands/user.c:2155 commands/user.c:2178 #, c-format msgid "permission denied to revoke role \"%s\"" msgstr "როლის (\"%s\") გაუქმების წვდომა აკრძალულია" -#: commands/user.c:2144 +#: commands/user.c:2157 #, c-format msgid "Only roles with the %s attribute may revoke roles with the %s attribute." msgstr "მხოლოდ როლებს, რომლებსაც %s ატრიბუტი გააჩნიათ, შეუძლიათ, როლებს %s ატრიბუტი მოაცილონ." -#: commands/user.c:2160 +#: commands/user.c:2173 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." msgstr "მხოლოდ როლებს, რომლებსაც როლზე \"%2$s\" პარამეტრი \"%1$s\" გააჩნიათ, შეუძლიათ, მიანიჭონ ეს როლი." -#: commands/user.c:2167 +#: commands/user.c:2180 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." msgstr "მხოლოდ როლებს, რომლებსაც როლზე \"%2$s\" პარამეტრი \"%1$s\" გააჩნიათ, შეუძლიათ, მოაცილონ ეს როლი." -#: commands/user.c:2247 commands/user.c:2256 +#: commands/user.c:2260 commands/user.c:2269 #, c-format msgid "permission denied to grant privileges as role \"%s\"" msgstr "როლის (\"%s\") მინიჭების წვდომა აკრძალულია" -#: commands/user.c:2249 +#: commands/user.c:2262 #, c-format msgid "Only roles with privileges of role \"%s\" may grant privileges as this role." msgstr "მხოლოდ როლებს, რომლებსაც როლის \"%s\" პრივილეგიები გააჩნიათ, შეუძლიათ პრივილეგიები, როგორც, ამ როლმა, მიანიჭონ." -#: commands/user.c:2258 +#: commands/user.c:2271 #, c-format msgid "The grantor must have the %s option on role \"%s\"." msgstr "მიმნიჭებელს უნდა ჰქონდეს %s პარამეტრი როლზე \"%s\"." -#: commands/user.c:2266 +#: commands/user.c:2279 #, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" msgstr "როლის (\"%s\") მიერ მინიჭებული პრივილეგიების გაუქმების წვდომა აკრძალულია" -#: commands/user.c:2268 +#: commands/user.c:2281 #, c-format msgid "Only roles with privileges of role \"%s\" may revoke privileges granted by this role." msgstr "მხოლოდ როლებს, რომლებსაც როლის \"%s\" პრივილეგიები გააჩნიათ, შეუძლიათ ამ როლის მიერ მინიჭებული პრივილეგიები მოაცილონ." -#: commands/user.c:2491 utils/adt/acl.c:1318 +#: commands/user.c:2504 utils/adt/acl.c:1325 #, c-format msgid "dependent privileges exist" msgstr "დამოკიდებული პრივილეგიები არსებობს" -#: commands/user.c:2492 utils/adt/acl.c:1319 +#: commands/user.c:2505 utils/adt/acl.c:1326 #, c-format msgid "Use CASCADE to revoke them too." msgstr "მათ გასაუქმებლადაც CASCADE გამოიყენეთ." -#: commands/vacuum.c:134 +#: commands/vacuum.c:146 #, c-format -msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" -msgstr "\"vacuum_buffer_usage_limit\"-ის მნიშვნელობა 0 ან %d კბ-სა და %d კბ-ს შორის უნდა იყოს" +msgid "\"%s\" must be 0 or between %d kB and %d kB." +msgstr "\"%s\"-ის მნიშვნელობა 0 ან %d კბ-სა და %d კბ-ს შორის უნდა იყოს." -#: commands/vacuum.c:209 +#: commands/vacuum.c:222 #, c-format msgid "BUFFER_USAGE_LIMIT option must be 0 or between %d kB and %d kB" msgstr "BUFFER_USAGE_LIMIT პარამეტრი 0 ან %d კბ-სა და %d კბ-ს შორის უნდა იყოს" -#: commands/vacuum.c:219 +#: commands/vacuum.c:232 #, c-format msgid "unrecognized ANALYZE option \"%s\"" msgstr "\"ANALYZE\"-ის უცნობი პარამეტრი: %s" -#: commands/vacuum.c:259 +#: commands/vacuum.c:272 #, c-format msgid "parallel option requires a value between 0 and %d" msgstr "პარალელურ პარამეტრს ესაჭიროება მნიშვნელობა 0-სა და %d-ს შორის" -#: commands/vacuum.c:271 +#: commands/vacuum.c:284 #, c-format msgid "parallel workers for vacuum must be between 0 and %d" msgstr "პარალელური დამხმარე პროცესების რაოდენობა მომტვერსასრუტებისთვის 0-სა და %d-ს შორის უნდა იყოს" -#: commands/vacuum.c:292 +#: commands/vacuum.c:305 #, c-format msgid "unrecognized VACUUM option \"%s\"" msgstr "\"VACUUM\"-ის უცნობი პარამეტრი: %s" -#: commands/vacuum.c:318 +#: commands/vacuum.c:331 #, c-format msgid "VACUUM FULL cannot be performed in parallel" msgstr "VACUUM FULL პარალელურად ვერ შესრულდება" -#: commands/vacuum.c:329 +#: commands/vacuum.c:342 #, c-format msgid "BUFFER_USAGE_LIMIT cannot be specified for VACUUM FULL" msgstr "VACUUM FULL-სთვის BUFFER_USAGE_LIMIT-ს ვერ მიუთითებთ" -#: commands/vacuum.c:343 +#: commands/vacuum.c:356 #, c-format msgid "ANALYZE option must be specified when a column list is provided" msgstr "როცა მიწოდებულია სვეტების სია, პარამეტრის ANALYZE მითითება აუცილებელია" -#: commands/vacuum.c:355 +#: commands/vacuum.c:368 #, c-format msgid "VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL" msgstr "VACUUM-ის პარამეტრს 'DISABLE_PAGE_SKIPPING' FULL-თან ერთად ვერ გამოიყენებთ" -#: commands/vacuum.c:362 +#: commands/vacuum.c:375 #, c-format msgid "PROCESS_TOAST required with VACUUM FULL" msgstr "VACUUM FULL-თან ერთად PROCESS_TOAST აუცილებელია" -#: commands/vacuum.c:371 +#: commands/vacuum.c:384 #, c-format msgid "ONLY_DATABASE_STATS cannot be specified with a list of tables" msgstr "ONLY_DATABASE_STATS -ის მითითება ცხრილების სიასთან ერთად შეუძლებელია" -#: commands/vacuum.c:380 +#: commands/vacuum.c:393 #, c-format msgid "ONLY_DATABASE_STATS cannot be specified with other VACUUM options" msgstr "ONLY_DATABASE_STAT-ის მითითება სხვა VACUMM პარამეტრებთან ერთად შეუძლებელია" -#: commands/vacuum.c:515 +#: commands/vacuum.c:533 #, c-format msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%s-ს VACUUM-დან ან ANALYZE-დან ვერ შეასარულებთ" -#: commands/vacuum.c:730 +#: commands/vacuum.c:745 #, c-format msgid "permission denied to vacuum \"%s\", skipping it" msgstr "\"%s\"-ის მომტვერსასრუტების წვდომა აკრძალულია. გამოტოვება" -#: commands/vacuum.c:743 +#: commands/vacuum.c:758 #, c-format msgid "permission denied to analyze \"%s\", skipping it" msgstr "\"%s\"-ის ანალიზისთვის წვდომა აკრძალულია. გამოტოვება" -#: commands/vacuum.c:821 commands/vacuum.c:918 +#: commands/vacuum.c:836 commands/vacuum.c:937 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" msgstr "\"%s\"-ის მომტვერსასრუტება გამოტოვებულია -- ბლოკი ხელმისაწვდომი არაა" -#: commands/vacuum.c:826 +#: commands/vacuum.c:841 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "\"%s\"-ის მომტვერსასრუტება გამოტოვებულია -- ურთიერთობა აღარ არსებობს" -#: commands/vacuum.c:842 commands/vacuum.c:923 +#: commands/vacuum.c:857 commands/vacuum.c:942 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" msgstr "\"%s\"-ის ანალიზი გამოტოვებულია -- ბლოკი ხელმისაწვდომი არაა" -#: commands/vacuum.c:847 +#: commands/vacuum.c:862 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "\"%s\"-ის ანალიზი გამოტოვებულია -- ურთიერთობა აღარ არსებობს" -#: commands/vacuum.c:1139 +#: commands/vacuum.c:978 +#, c-format +msgid "VACUUM ONLY of partitioned table \"%s\" has no effect" +msgstr "დაყოფილ ცხრილზე \"%s\" ბრძანებას VACUUM ONLY გავლენა არ აქვს" + +#: commands/vacuum.c:1169 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" msgstr "" -#: commands/vacuum.c:1140 commands/vacuum.c:1145 +#: commands/vacuum.c:1170 commands/vacuum.c:1175 #, c-format msgid "" "Close open transactions soon to avoid wraparound problems.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -#: commands/vacuum.c:1144 +#: commands/vacuum.c:1174 #, c-format msgid "cutoff for freezing multixacts is far in the past" msgstr "" -#: commands/vacuum.c:1890 +#: commands/vacuum.c:1936 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "ზოგიერთი ბაზა 2 მილიარდ ტრანზაქციაზე მეტია, რაც არ მომტვერსასრუტებულა" -#: commands/vacuum.c:1891 +#: commands/vacuum.c:1937 #, c-format msgid "You might have already suffered transaction-wraparound data loss." msgstr "" -#: commands/vacuum.c:2070 +#: commands/vacuum.c:2116 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "" -#: commands/vacuum.c:2502 +#: commands/vacuum.c:2617 #, c-format -msgid "scanned index \"%s\" to remove %lld row versions" -msgstr "სკანირებული ინდექსი \"%s\" %lld მწკრივის ვერსიის წაშლას აპირებს" +msgid "scanned index \"%s\" to remove % row versions" +msgstr "სკანირებული ინდექსი \"%s\" % მწკრივის ვერსიის წაშლას აპირებს" -#: commands/vacuum.c:2521 +#: commands/vacuum.c:2636 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "ინდექსი \"%s\" ახლა %.0f მწკრივის ვერსიას შეიცავს, %u გვერდში" -#: commands/vacuum.c:2525 +#: commands/vacuum.c:2640 #, c-format msgid "" "%.0f index row versions were removed.\n" @@ -12819,14 +13061,14 @@ msgid "" "%u index pages are currently deleted, of which %u are currently reusable." msgstr "" -#: commands/vacuumparallel.c:708 +#: commands/vacuumparallel.c:709 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index vacuuming (planned: %d)" msgstr[0] "ინდექსის მომტვერსასრუტებისთვის გაშვებულია %d პარალელური მომტვერსასრუტების დამხმარე პროცესი (დაგეგმილია: %d)" msgstr[1] "ინდექსის მომტვერსასრუტებისთვის გაშვებულია %d პარალელური მომტვერსასრუტების დამხმარე პროცესი (დაგეგმილია: %d)" -#: commands/vacuumparallel.c:714 +#: commands/vacuumparallel.c:715 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index cleanup (planned: %d)" @@ -12835,8 +13077,8 @@ msgstr[1] "ინდექსის გასუფთავებისთვ #: commands/variable.c:185 #, c-format -msgid "Conflicting \"datestyle\" specifications." -msgstr "კონფლიქტური \"datestyle\"-ის სპეციფიკაციები." +msgid "Conflicting \"DateStyle\" specifications." +msgstr "კონფლიქტური \"DateStyle\"-ის სპეციფიკაციები." #: commands/variable.c:307 #, c-format @@ -12848,12 +13090,12 @@ msgstr "დროის სარტყელის ინტერვალშ msgid "Cannot specify days in time zone interval." msgstr "დროის სარტყელის ინტერვალში დღეებს ვერ მიუთითებთ." -#: commands/variable.c:351 commands/variable.c:433 +#: commands/variable.c:351 commands/variable.c:435 #, c-format msgid "time zone \"%s\" appears to use leap seconds" msgstr "დროის სარტყელი \"%s\", როგორც ჩანს, დამატებით წამებს იყენებს" -#: commands/variable.c:353 commands/variable.c:435 +#: commands/variable.c:353 commands/variable.c:437 #, c-format msgid "PostgreSQL does not support leap seconds." msgstr "PostgreSQL-ს დამატებითი წამების მხარდაჭერა არ გააჩნია." @@ -12863,107 +13105,97 @@ msgstr "PostgreSQL-ს დამატებითი წამების მ msgid "UTC timezone offset is out of range." msgstr "UTC დროის სარტყელი ზღვარს მიღმაა." -#: commands/variable.c:552 +#: commands/variable.c:554 #, c-format msgid "cannot set transaction read-write mode inside a read-only transaction" msgstr "მხოლოდ-კითხვადი ტრანზაქციის შიგნით ტრანზაქციის რეჟიმის ჩაწერა-წაკითხვის რეჟიმზე გადართვა შეუძლებელია" -#: commands/variable.c:559 +#: commands/variable.c:561 #, c-format msgid "transaction read-write mode must be set before any query" msgstr "ტრანზაქცის ჩაწერა-წაკითხვის რეჟიმი ყველა მოთხოვნის წინ უნდა იქნეს დაყენებული" -#: commands/variable.c:566 +#: commands/variable.c:568 #, c-format msgid "cannot set transaction read-write mode during recovery" msgstr "აღდგენისას ტრანზაქციის ჩაწერა-წაკითხვის რეჟიმის დაყენება შეუძლებელია" -#: commands/variable.c:592 +#: commands/variable.c:596 #, c-format msgid "SET TRANSACTION ISOLATION LEVEL must be called before any query" msgstr "SET TRANSACTION ISOLATION LEVEL ყველა მოთხოვნაზე ადრე უნდა გამოიძახოთ" -#: commands/variable.c:599 +#: commands/variable.c:603 #, c-format msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "SET TRANSACTION ISOLATION LEVEL ქვემოთხოვნაში არ უნდა გამოიძახოთ" -#: commands/variable.c:606 storage/lmgr/predicate.c:1680 +#: commands/variable.c:610 storage/lmgr/predicate.c:1695 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "ცხელი მოლოდინში სერიალიზებადი რეჟიმის გამოყენება შეუძლებელია" -#: commands/variable.c:607 +#: commands/variable.c:611 #, c-format msgid "You can use REPEATABLE READ instead." msgstr "სამაგიეროდ, შეგიძლიათ, REPEATABLE READ გამოიყენოთ." -#: commands/variable.c:625 +#: commands/variable.c:633 #, c-format msgid "SET TRANSACTION [NOT] DEFERRABLE cannot be called within a subtransaction" msgstr "SET TRANSACTION [NOT] DEFERRABLE-ს ქვეტრანზაქციაში ვერ გამოიძახებთ" -#: commands/variable.c:631 +#: commands/variable.c:639 #, c-format msgid "SET TRANSACTION [NOT] DEFERRABLE must be called before any query" msgstr "SET TRANSACTION [NOT] DEFERRABLE ყველა მოთხოვნაზე ადრე უნდა გამოიძახოთ" -#: commands/variable.c:713 +#: commands/variable.c:715 +#, c-format +msgid "Cannot change \"client_encoding\" during a parallel operation." +msgstr "პარალელური ოპერაციის დროს \"client_encoding\" პარამეტრს ვერ შეცვლით." + +#: commands/variable.c:743 #, c-format msgid "Conversion between %s and %s is not supported." msgstr "%s-დან %s-ზე გადაყვანა მხარდაჭერილი არაა." -#: commands/variable.c:720 +#: commands/variable.c:750 #, c-format msgid "Cannot change \"client_encoding\" now." msgstr "ახლა \"client_encoding\"-ს ვერ შეცვლით." -#: commands/variable.c:781 -#, c-format -msgid "cannot change \"client_encoding\" during a parallel operation" -msgstr "პარალელური ოპერაციის დროს \"client_encoding\" პარამეტრს ვერ შეცვლით" - -#: commands/variable.c:863 +#: commands/variable.c:889 #, c-format msgid "permission will be denied to set session authorization \"%s\"" msgstr "სესიის ავტორიზაციის \"%s\" დასაყენებლად წვდომა აკრძალული იქნება" -#: commands/variable.c:868 +#: commands/variable.c:894 #, c-format msgid "permission denied to set session authorization \"%s\"" msgstr "სესიის ავტორიზაციის \"%s\" დასაყენებლად წვდომა აკრძალულია" -#: commands/variable.c:972 +#: commands/variable.c:1003 #, c-format msgid "permission will be denied to set role \"%s\"" msgstr "როლის (\"%s\") დაყენების წვდომა აკრძალული იქნება" -#: commands/variable.c:977 +#: commands/variable.c:1008 #, c-format msgid "permission denied to set role \"%s\"" msgstr "როლის (\"%s\") დაყენების წვდომა აკრძალულია" -#: commands/variable.c:1177 +#: commands/variable.c:1228 #, c-format msgid "Bonjour is not supported by this build" msgstr "ამ აგებაში Bonjour -ის მხარდაჭერა არ არსებბს" -#: commands/variable.c:1205 -#, c-format -msgid "\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." -msgstr "პლატფორმებზე, რომლებზეც posix_fadvise() ხელმისაწვდომი არაა, \"effective_io_concurrency\"-ის მნიშვნელობა 0-ის ტოლი უნდა ყოს." - -#: commands/variable.c:1218 -#, c-format -msgid "\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." -msgstr "პლატფორმებზე, რომლებზეც posix_fadvise() ხელმისაწვდომი არაა, \"maintenance_io_concurrency\"-ის მნიშვნელობა 0-ის ტოლი უნდა ყოს." - -#: commands/variable.c:1231 +#: commands/variable.c:1256 #, c-format msgid "SSL is not supported by this build" msgstr "ამ აგებაში SSL-ის მხარდაჭერა არ არსებბს" -#: commands/view.c:79 +#: commands/view.c:78 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "კოლაციის გამოცნობის შეცდომა ხედის სვეტისთვის \"%s\"" @@ -13048,402 +13280,413 @@ msgstr "კურსორი \"%s\" მწკრივზე არ მდე msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "კურსორი \"%s\" ცხრილის (\"%s\") მარტივადი განახლებადი სკანირებას არ წარმოადგენს" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2543 +#: executor/execCurrent.c:280 executor/execExprInterp.c:3093 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "პარამეტრის %d (%s) ტიპი არ ემთხვევა იმას, რომლითაც გეგმა მზადდებოდა (%s)" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2555 +#: executor/execCurrent.c:292 executor/execExprInterp.c:3105 #, c-format msgid "no value found for parameter %d" msgstr "პარამეტრისთვის მნიშვნელობების პოვნა შეუძლებელია: %d" -#: executor/execExpr.c:641 executor/execExpr.c:648 executor/execExpr.c:654 executor/execExprInterp.c:4741 executor/execExprInterp.c:4758 executor/execExprInterp.c:4857 executor/nodeModifyTable.c:194 executor/nodeModifyTable.c:205 executor/nodeModifyTable.c:222 executor/nodeModifyTable.c:230 +#: executor/execExpr.c:667 executor/execExpr.c:674 executor/execExpr.c:680 executor/execExprInterp.c:5440 executor/execExprInterp.c:5457 executor/execExprInterp.c:5556 executor/nodeModifyTable.c:210 executor/nodeModifyTable.c:229 executor/nodeModifyTable.c:246 executor/nodeModifyTable.c:256 executor/nodeModifyTable.c:266 #, c-format msgid "table row type and query-specified row type do not match" msgstr "" -#: executor/execExpr.c:642 executor/nodeModifyTable.c:195 +#: executor/execExpr.c:668 executor/nodeModifyTable.c:211 #, c-format msgid "Query has too many columns." msgstr "მოთხოვნას მეტისმეტად ბევრი სვეტ აქვს." -#: executor/execExpr.c:649 executor/nodeModifyTable.c:223 +#: executor/execExpr.c:675 executor/nodeModifyTable.c:230 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "" -#: executor/execExpr.c:655 executor/execExprInterp.c:4759 executor/nodeModifyTable.c:206 +#: executor/execExpr.c:681 executor/execExprInterp.c:5458 executor/nodeModifyTable.c:257 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "" -#: executor/execExpr.c:1103 parser/parse_agg.c:840 +#: executor/execExpr.c:1157 parser/parse_agg.c:843 #, c-format msgid "window function calls cannot be nested" msgstr "ფანჯრის ფუნქციის გამოძახებებს ერთმანეთში ვერ ჩადგამთ" -#: executor/execExpr.c:1640 +#: executor/execExpr.c:1689 #, c-format msgid "target type is not an array" msgstr "სამიზნე ტიპი მასივი არაა" -#: executor/execExpr.c:1980 +#: executor/execExpr.c:2033 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "ROW() სვეტს %s ტიპის მაგიერ %s აქვს" -#: executor/execExpr.c:2642 executor/execSRF.c:718 parser/parse_func.c:138 parser/parse_func.c:655 parser/parse_func.c:1033 +#: executor/execExpr.c:2729 executor/execSRF.c:718 parser/parse_func.c:138 parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" msgstr[0] "ფუნქციისთვის %d -ზე მეტი არგუმენტის გადაცემა შეუძლებელია" msgstr[1] "ფუნქციისთვის %d -ზე მეტი არგუმენტის გადაცემა შეუძლებელია" -#: executor/execExpr.c:2669 executor/execSRF.c:738 executor/functions.c:1067 utils/adt/jsonfuncs.c:4032 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2756 executor/execSRF.c:738 executor/functions.c:1558 utils/adt/jsonfuncs.c:4056 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "ფუნქცია, რომელიც სეტს აბრუნებს, გამოძახებულია კონტექსტში, რომელიც სეტებს ვერ იღებს" -#: executor/execExpr.c:3075 parser/parse_node.c:272 parser/parse_node.c:322 +#: executor/execExpr.c:3262 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "" -#: executor/execExpr.c:3203 executor/execExpr.c:3225 +#: executor/execExpr.c:3390 executor/execExpr.c:3412 #, c-format msgid "type %s does not support subscripted assignment" msgstr "" -#: executor/execExprInterp.c:2007 +#: executor/execExprInterp.c:2415 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "%2$s ტიპის ატრიბუტი %1$d წაიშალა" -#: executor/execExprInterp.c:2013 +#: executor/execExprInterp.c:2421 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "%2$s ტიპის ატრიბუტის %1$d ტიპი არასწორია" -#: executor/execExprInterp.c:2015 executor/execExprInterp.c:3214 executor/execExprInterp.c:3260 +#: executor/execExprInterp.c:2423 executor/execExprInterp.c:3782 executor/execExprInterp.c:3828 #, c-format msgid "Table has type %s, but query expects %s." msgstr "ცხრილის ტიპია %s, მოთხოვნა კი %s-ს მოელოდა." -#: executor/execExprInterp.c:2095 utils/adt/expandedrecord.c:99 utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 utils/fmgr/funcapi.c:569 +#: executor/execExprInterp.c:2503 utils/adt/expandedrecord.c:99 utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1841 utils/cache/typcache.c:2000 utils/cache/typcache.c:2147 utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "ტიპი %s კომპოზიტური არაა" -#: executor/execExprInterp.c:2698 +#: executor/execExprInterp.c:3266 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "WHERE CURRENT OF ამ ტიპის ცხრილისთვის მხარდაუჭერელია" -#: executor/execExprInterp.c:2911 +#: executor/execExprInterp.c:3479 #, c-format msgid "cannot merge incompatible arrays" msgstr "შეუთავსებელი მასივების შერწყმა შეუძლებელია" -#: executor/execExprInterp.c:2912 +#: executor/execExprInterp.c:3480 #, c-format msgid "Array with element type %s cannot be included in ARRAY construct with element type %s." msgstr "" -#: executor/execExprInterp.c:2933 utils/adt/arrayfuncs.c:1305 utils/adt/arrayfuncs.c:3496 utils/adt/arrayfuncs.c:5586 utils/adt/arrayfuncs.c:6103 utils/adt/arraysubs.c:150 utils/adt/arraysubs.c:488 +#: executor/execExprInterp.c:3501 utils/adt/arrayfuncs.c:1305 utils/adt/arrayfuncs.c:3515 utils/adt/arrayfuncs.c:5605 utils/adt/arrayfuncs.c:6124 utils/adt/arraysubs.c:151 utils/adt/arraysubs.c:489 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "მასივის ზომების რაოდენობა (%d) მაქსიმუმ დასაშვებზე (%d) დიდია" -#: executor/execExprInterp.c:2953 executor/execExprInterp.c:2988 +#: executor/execExprInterp.c:3521 executor/execExprInterp.c:3556 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "მრავალგანზომილებიან მასივებს უნდა ჰქონდეთ მასივის გამოსახულებები შესაბამისი ზომებით" -#: executor/execExprInterp.c:2965 utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 utils/adt/arrayfuncs.c:2942 utils/adt/arrayfuncs.c:2957 utils/adt/arrayfuncs.c:3298 utils/adt/arrayfuncs.c:3526 utils/adt/arrayfuncs.c:5358 utils/adt/arrayfuncs.c:6195 -#: utils/adt/arrayfuncs.c:6539 utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 utils/adt/arrayutils.c:99 +#: executor/execExprInterp.c:3533 utils/adt/array_expanded.c:274 utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 utils/adt/arrayfuncs.c:3545 utils/adt/arrayfuncs.c:5377 +#: utils/adt/arrayfuncs.c:6216 utils/adt/arrayfuncs.c:6560 utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "მასივის ზომა მაქსიმალურ დასაშვებს(%d) აჭარბებს" -#: executor/execExprInterp.c:3213 executor/execExprInterp.c:3259 +#: executor/execExprInterp.c:3781 executor/execExprInterp.c:3827 #, c-format msgid "attribute %d has wrong type" msgstr "ატრიბუტის არასწორი ტიპი: %d" -#: executor/execExprInterp.c:3845 utils/adt/domains.c:158 +#: executor/execExprInterp.c:4413 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "დომენ %s-ს ნულოვანი მნიშვნელობების მხარდაჭერა არ გააჩნია" -#: executor/execExprInterp.c:3860 utils/adt/domains.c:196 +#: executor/execExprInterp.c:4428 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "მნიშვნელობა დომენისთვის %s არღვევს შემოწმების შეზღუდვას \"%s\"" -#: executor/execExprInterp.c:4433 +#: executor/execExprInterp.c:5003 #, c-format msgid "no SQL/JSON item found for specified path of column \"%s\"" -msgstr "" +msgstr "სვეტის \"%s\" მითითებულ ბილიკზე SQL/JSON ელემენტი აღმოჩენილი არაა" -#: executor/execExprInterp.c:4438 +#: executor/execExprInterp.c:5008 #, c-format msgid "no SQL/JSON item found for specified path" -msgstr "" +msgstr "მითითებულ ბილიკზე SQL/JSON ელემენტი აღმოჩენილი არაა" -#: executor/execExprInterp.c:4742 +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:5208 executor/execExprInterp.c:5216 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "ვერ შევაკავე %s გამოსახულება (%s) ტპზე RETURNING" + +#: executor/execExprInterp.c:5441 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." msgstr[0] "ცხრილის მწკრივი %d ატრიბუტს შეიცავს, მოთხოვნა კი %d-ს მოელოდა." msgstr[1] "ცხრილის მწკრივი %d ატრიბუტს შეიცავს, მოთხოვნა კი %d-ს მოელოდა." -#: executor/execExprInterp.c:4858 executor/execSRF.c:977 +#: executor/execExprInterp.c:5557 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "" -#: executor/execIndexing.c:593 +#: executor/execIndexing.c:608 #, c-format msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters" msgstr "" -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:911 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "გამორიცხვის შეზღუდვის (\"%s\") შექმნა შეუძლებელია" -#: executor/execIndexing.c:873 +#: executor/execIndexing.c:914 #, c-format msgid "Key %s conflicts with key %s." msgstr "გასაღები %s კონფლიქტობს გასაღებ %s-სთან." -#: executor/execIndexing.c:875 +#: executor/execIndexing.c:916 #, c-format msgid "Key conflicts exist." msgstr "აღმოჩენილია გასაღებების კონფლიქტი." -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:922 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "კონფლიქტის მქონე გასაღების მნიშვნელობა არღვევს უნიკალურ შეზღუდვას \"%s\"" -#: executor/execIndexing.c:884 +#: executor/execIndexing.c:925 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "გასაღები %s კონფლიქტობს არსებულ გასაღებ %s-სთან." -#: executor/execIndexing.c:886 +#: executor/execIndexing.c:927 #, c-format msgid "Key conflicts with existing key." msgstr "გასაღები აქტიურ გასაღებთან კონფლიქტობს." -#: executor/execMain.c:1041 +#: executor/execIndexing.c:1172 +#, c-format +msgid "empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"" +msgstr "" + +#: executor/execMain.c:1171 #, c-format msgid "cannot change sequence \"%s\"" msgstr "მიმდევრობის შეცვლა შეუძლებელია: \"%s\"" -#: executor/execMain.c:1047 +#: executor/execMain.c:1177 #, c-format msgid "cannot change TOAST relation \"%s\"" msgstr "'TOAST' ტიპის ურთიერთობის \"%s\" შეცვლა შეუძლებელია" -#: executor/execMain.c:1066 +#: executor/execMain.c:1196 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "მატერიალიზებული ხედის შეცვლა შეუძლებელია: %s" -#: executor/execMain.c:1078 +#: executor/execMain.c:1208 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "გარე ცხრილში ჩამატების შეცდომა: %s" -#: executor/execMain.c:1084 +#: executor/execMain.c:1214 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "გარე ცხრილი ჩამატების საშუალებას არ იძლევა: %s" -#: executor/execMain.c:1091 +#: executor/execMain.c:1221 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "გარე ცხრილის განახლების შეცდომა: %s" -#: executor/execMain.c:1097 +#: executor/execMain.c:1227 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "გარე ცხრილი განახლებების საშუალებას არ იძლევა: %s" -#: executor/execMain.c:1104 +#: executor/execMain.c:1234 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "გარე ცხრილიდან წაშლის შეცდომა: %s" -#: executor/execMain.c:1110 +#: executor/execMain.c:1240 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "გარე ცხრილი წაშლის საშუალებას არ იძლევა: %s" -#: executor/execMain.c:1121 +#: executor/execMain.c:1251 #, c-format msgid "cannot change relation \"%s\"" msgstr "ურთიერთობის შეცვლის შეცდომა: %s" -#: executor/execMain.c:1148 +#: executor/execMain.c:1278 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "მიმდევრობაში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1155 +#: executor/execMain.c:1285 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "\"TOAST\" ურთიერთობაში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1162 +#: executor/execMain.c:1292 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "ხედში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1170 +#: executor/execMain.c:1300 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "მატერიალიზებულ ხედში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1179 executor/execMain.c:2684 executor/nodeLockRows.c:135 +#: executor/execMain.c:1309 executor/execMain.c:2941 executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "გარე ცხრილში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1185 +#: executor/execMain.c:1315 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "ურთიერთობაში მწკრივების ჩაკეტვა შეუძლებელია: %s" -#: executor/execMain.c:1898 +#: executor/execMain.c:2038 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "ახალი მწკრივი ურთიერთობისთვის \"%s\" დანაყოფის შეზღუდვას არღვევს" -#: executor/execMain.c:1900 executor/execMain.c:1984 executor/execMain.c:2035 executor/execMain.c:2145 +#: executor/execMain.c:2040 executor/execMain.c:2152 executor/execMain.c:2290 executor/execMain.c:2398 #, c-format msgid "Failing row contains %s." msgstr "შეცდომიანი მწკრივი \"%s\"-ს შეიცავს." -#: executor/execMain.c:1981 -#, c-format -msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" -msgstr "ნულოვანი მნიშვნელობა სვეტში \"%s\" ურთიერთობისთვის \"%s\" არანულოვან შეზღუდვას არღვევს" - -#: executor/execMain.c:2033 +#: executor/execMain.c:2150 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "ახალი მწკრივი ურთიერთობისთვის \"%s\" არღვევს შემოწმების შეზღუდვას \"%s\"" -#: executor/execMain.c:2143 +#: executor/execMain.c:2287 +#, c-format +msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" +msgstr "ნულოვანი მნიშვნელობა სვეტში \"%s\" ურთიერთობისთვის \"%s\" არანულოვან შეზღუდვას არღვევს" + +#: executor/execMain.c:2396 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "ახალი მწკრივი არღვევს შემოწმების პარამეტრს ხედისთვის \"%s\"" -#: executor/execMain.c:2153 +#: executor/execMain.c:2406 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "ახალი მწკრივი არღვევს მწკრივის-დონის უსაფრთხოების პოლიტიკას \"%s\" ცხრილისთვის \"%s\"" -#: executor/execMain.c:2158 +#: executor/execMain.c:2411 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "ახალი მწკრივი ცხრილისთვის \"%s\" მწკრივის-დონის უსაფრთხოების პოლიტიკა არღვევს" -#: executor/execMain.c:2166 +#: executor/execMain.c:2419 #, c-format msgid "target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "" -#: executor/execMain.c:2171 +#: executor/execMain.c:2424 #, c-format msgid "target row violates row-level security policy (USING expression) for table \"%s\"" msgstr "" -#: executor/execMain.c:2178 +#: executor/execMain.c:2431 #, c-format msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "" -#: executor/execMain.c:2183 +#: executor/execMain.c:2436 #, c-format msgid "new row violates row-level security policy (USING expression) for table \"%s\"" msgstr "" -#: executor/execPartition.c:327 +#: executor/execPartition.c:331 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "მწკრივისთვის ურთიერთობის \"%s\" დანაყოფი ვერ ვიპოვე" -#: executor/execPartition.c:330 +#: executor/execPartition.c:334 #, c-format msgid "Partition key of the failing row contains %s." msgstr "შეცდომიანი მწკრივის დანაყოფის გასაღები \"%s\"-ს შეიცავს." -#: executor/execReplication.c:272 executor/execReplication.c:456 +#: executor/execReplication.c:147 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update, retrying" msgstr "დასაბლოკი კორტეჟი პარალელური განახლების გამო უკვე სხვა დანაყოფშია გადატანილი. თავიდან ვცდი" -#: executor/execReplication.c:276 executor/execReplication.c:460 +#: executor/execReplication.c:151 #, c-format msgid "concurrent update, retrying" msgstr "ერთდროული განახლება. თავიდან ვცდი" -#: executor/execReplication.c:282 executor/execReplication.c:466 +#: executor/execReplication.c:158 #, c-format msgid "concurrent delete, retrying" msgstr "ერთდროული წაშლა. თავიდან ვცდი" -#: executor/execReplication.c:352 parser/parse_cte.c:302 parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3845 utils/adt/arrayfuncs.c:4400 utils/adt/arrayfuncs.c:6419 utils/adt/rowtypes.c:1220 -#, c-format -msgid "could not identify an equality operator for type %s" -msgstr "ტიპისთვის \"%s\" ტოლობის ფუნქცია ვერ ვიპოვე" - -#: executor/execReplication.c:683 executor/execReplication.c:689 +#: executor/execReplication.c:809 executor/execReplication.c:815 executor/execReplication.c:821 #, c-format msgid "cannot update table \"%s\"" msgstr "ცხრილის განახლების შეცდომა: %s" -#: executor/execReplication.c:685 executor/execReplication.c:697 +#: executor/execReplication.c:811 executor/execReplication.c:829 #, c-format msgid "Column used in the publication WHERE expression is not part of the replica identity." msgstr "გამოცემის WHERE გამოსახულებაში გამოყენებული სვეტი რეპლიკის იდენტიფიკაციის ნაწილს არ წარმოადგენს." -#: executor/execReplication.c:691 executor/execReplication.c:703 +#: executor/execReplication.c:817 executor/execReplication.c:835 #, c-format msgid "Column list used by the publication does not cover the replica identity." msgstr "გამოცემის მიერ გამოყენებული სვეტების სია რეპლიკის იდენტიფიკაციას არ ფარავს." -#: executor/execReplication.c:695 executor/execReplication.c:701 +#: executor/execReplication.c:823 executor/execReplication.c:841 +#, c-format +msgid "Replica identity must not contain unpublished generated columns." +msgstr "" + +#: executor/execReplication.c:827 executor/execReplication.c:833 executor/execReplication.c:839 #, c-format msgid "cannot delete from table \"%s\"" msgstr "ცხრილიდან წაშლის შეცდომა: %s" -#: executor/execReplication.c:721 +#: executor/execReplication.c:859 #, c-format msgid "cannot update table \"%s\" because it does not have a replica identity and publishes updates" msgstr "ცხრილის \"%s\" განახლება შეუძლებელია, რადგან მას რეპლიკის იდენტიფიკაცია არ გააჩნია და განახლებებს აქვეყნებს" -#: executor/execReplication.c:723 +#: executor/execReplication.c:861 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "ცხრილის განახლების ჩასართავად ALTER TABLE-ით REPLICA IDENTITY დააყენეთ." -#: executor/execReplication.c:727 +#: executor/execReplication.c:865 #, c-format msgid "cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes" msgstr "ცხრილიდან \"%s\" წაშლა შეუძლებელია, რადგან მას რეპლიკის იდენტიფიკაცია არ გააჩნია და წაშლებს აქვეყნებს" -#: executor/execReplication.c:729 +#: executor/execReplication.c:867 #, c-format msgid "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "ცხრილიდან წაშლის ჩასართავად ALTER TABLE-ის გამოყენებით REPLICA IDENTITY დააყენეთ." -#: executor/execReplication.c:745 +#: executor/execReplication.c:883 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "ურთიერთობას \"%s.%s\" ლოგიკური რეპლიკაციის სამიზნედ ვერ გამოიყენებთ" @@ -13490,114 +13733,114 @@ msgstr[1] "" msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "" -#: executor/execTuples.c:147 executor/execTuples.c:368 executor/execTuples.c:563 executor/execTuples.c:772 +#: executor/execTuples.c:147 executor/execTuples.c:369 executor/execTuples.c:564 executor/execTuples.c:774 #, c-format msgid "cannot retrieve a system column in this context" msgstr "ამ კონტექსტში სისტემური სვეტის მიღება შეუძლებელია" -#: executor/execTuples.c:163 executor/execTuples.c:580 +#: executor/execTuples.c:163 executor/execTuples.c:581 #, c-format msgid "don't have transaction information for this type of tuple" msgstr "" -#: executor/execTuples.c:390 executor/execTuples.c:794 +#: executor/execTuples.c:391 executor/execTuples.c:796 #, c-format msgid "don't have a storage tuple in this context" msgstr "ამ კონტექსტში საცავის კორტეჟი არ აქვს" -#: executor/execUtils.c:713 +#: executor/execUtils.c:759 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "მატერიალიზებული ხედი \"%s\" შევსებული არაა" -#: executor/execUtils.c:715 -#, c-format -msgid "Use the REFRESH MATERIALIZED VIEW command." -msgstr "გამოიყენეთ ბრძანება REFRESH MATERIALIZED VIEW." - -#: executor/functions.c:217 +#: executor/functions.c:288 #, c-format msgid "could not determine actual type of argument declared %s" msgstr "არგუმენტის, აღწერილის, როგორც '%s' ტიპის დადგენა შეუძლებელია" -#: executor/functions.c:512 +#: executor/functions.c:711 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "'SQL' ფუნქციაში კლიენტიდან/კლიენტამდე COPY შეუძლებელია" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:717 #, c-format msgid "%s is not allowed in an SQL function" msgstr "%s SQL ფუნქციაში დაშვებული არაა" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1741 executor/spi.c:2649 +#: executor/functions.c:725 executor/spi.c:1746 executor/spi.c:2660 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "%s-ის გამოყენება არააქროლად ფუნქციაში დაუშვებელია" -#: executor/functions.c:1451 +#: executor/functions.c:1159 executor/functions.c:2182 executor/functions.c:2220 executor/functions.c:2234 executor/functions.c:2324 executor/functions.c:2357 executor/functions.c:2371 #, c-format -msgid "SQL function \"%s\" statement %d" -msgstr "SQL ფუნქცია \"%s\" გამოსახულება %d" +msgid "return type mismatch in function declared to return %s" +msgstr "დაბრუნების ტიპის შეცდომა ფუნქციაში, რომელსაც აღწერილი აქვს, დააბრუნოს %s" -#: executor/functions.c:1477 +#: executor/functions.c:1161 executor/functions.c:2184 #, c-format -msgid "SQL function \"%s\" during startup" -msgstr "SQL ფუნქცია \"%s\" გაშვებისას" +msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." +msgstr "ფუნქციის ბოლო გამოსახულება SELECT ან INSERT/UPDATE/DELETE/MERGE RETURNING უნდა იყოს." -#: executor/functions.c:1562 +#: executor/functions.c:1244 utils/cache/plancache.c:869 #, c-format -msgid "calling procedures with output arguments is not supported in SQL functions" -msgstr "გამოტანის არგუმენტების მქონე პროცედურების გამოძახება SQL-ის ფუნქციებში მხარდაჭერილი არაა" +msgid "cached plan must not change result type" +msgstr "დაკეშილი გეგმა შედეგის ტიპს არ უნდა ცვლიდეს" -#: executor/functions.c:1697 executor/functions.c:1735 executor/functions.c:1749 executor/functions.c:1844 executor/functions.c:1877 executor/functions.c:1891 +#: executor/functions.c:1880 executor/functions.c:1911 #, c-format -msgid "return type mismatch in function declared to return %s" -msgstr "დაბრუნების ტიპის შეცდომა ფუნქციაში, რომელსაც აღწერილი აქვს, დააბრუნოს %s" +msgid "SQL function \"%s\" during startup" +msgstr "SQL ფუნქცია \"%s\" გაშვებისას" -#: executor/functions.c:1699 +#: executor/functions.c:1908 #, c-format -msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." -msgstr "ფუნქციის ბოლო გამოსახულება SELECT ან INSERT/UPDATE/DELETE/MERGE RETURNING უნდა იყოს." +msgid "SQL function \"%s\" statement %d" +msgstr "SQL ფუნქცია \"%s\" გამოსახულება %d" -#: executor/functions.c:1737 +#: executor/functions.c:2033 +#, c-format +msgid "calling procedures with output arguments is not supported in SQL functions" +msgstr "გამოტანის არგუმენტების მქონე პროცედურების გამოძახება SQL-ის ფუნქციებში მხარდაჭერილი არაა" + +#: executor/functions.c:2222 #, c-format msgid "Final statement must return exactly one column." msgstr "პირველი გამოსახულება ზუსტად ერთ სვეტს უნდა აბრუნებდეს." -#: executor/functions.c:1751 +#: executor/functions.c:2236 #, c-format msgid "Actual return type is %s." msgstr "დაბრუნების ნამდვილი ტიპია %s." -#: executor/functions.c:1846 +#: executor/functions.c:2326 #, c-format msgid "Final statement returns too many columns." msgstr "პირველი გამოსახულება მეტისმეტად ბევრ სვეტს აბრუნებს." -#: executor/functions.c:1879 +#: executor/functions.c:2359 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "" -#: executor/functions.c:1893 +#: executor/functions.c:2373 #, c-format msgid "Final statement returns too few columns." msgstr "ბოლო გამოსახულება მეტისმეტად ცოტა სვეტს აბრუნებს." -#: executor/functions.c:1921 +#: executor/functions.c:2401 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "დაბრუნების ტიპი %s SQL ფუნქციებში მხარდაჭერილი არაა" -#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2976 +#: executor/nodeAgg.c:4039 executor/nodeWindowAgg.c:3041 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "" -#: executor/nodeAgg.c:3966 parser/parse_agg.c:682 parser/parse_agg.c:710 +#: executor/nodeAgg.c:4062 parser/parse_agg.c:685 parser/parse_agg.c:713 #, c-format msgid "aggregate function calls cannot be nested" msgstr "აგრეგატულ ფუნქციებს ერთანეთში ვერ ჩადგამთ" @@ -13607,12 +13850,12 @@ msgstr "აგრეგატულ ფუნქციებს ერთან msgid "custom scan \"%s\" does not support MarkPos" msgstr "" -#: executor/nodeHashjoin.c:1130 executor/nodeHashjoin.c:1160 +#: executor/nodeHashjoin.c:1230 executor/nodeHashjoin.c:1260 #, c-format msgid "could not rewind hash-join temporary file" msgstr "" -#: executor/nodeIndexonlyscan.c:239 +#: executor/nodeIndexonlyscan.c:240 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "" @@ -13627,73 +13870,78 @@ msgstr "OFFSET უარყოფითი უნდა იყოს" msgid "LIMIT must not be negative" msgstr "LIMIT უარყოფითი არ უნდა იყოს" -#: executor/nodeMergejoin.c:1578 +#: executor/nodeMergejoin.c:1574 #, c-format msgid "RIGHT JOIN is only supported with merge-joinable join conditions" msgstr "" -#: executor/nodeMergejoin.c:1596 +#: executor/nodeMergejoin.c:1592 #, c-format msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "" -#: executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:247 +#, c-format +msgid "Query provides a value for a generated column at ordinal position %d." +msgstr "" + +#: executor/nodeModifyTable.c:267 #, c-format msgid "Query has too few columns." msgstr "მოთხოვნას ძალიან ცოტა სვეტი აქვს." -#: executor/nodeModifyTable.c:1531 executor/nodeModifyTable.c:1605 +#: executor/nodeModifyTable.c:1684 executor/nodeModifyTable.c:1758 #, c-format msgid "tuple to be deleted was already modified by an operation triggered by the current command" msgstr "" -#: executor/nodeModifyTable.c:1760 +#: executor/nodeModifyTable.c:1957 #, c-format msgid "invalid ON UPDATE specification" msgstr "\"ON UPDATE\"-ის არასწორი სპეციფიკაცია" -#: executor/nodeModifyTable.c:1761 +#: executor/nodeModifyTable.c:1958 #, c-format msgid "The result tuple would appear in a different partition than the original tuple." msgstr "" -#: executor/nodeModifyTable.c:2217 +#: executor/nodeModifyTable.c:2414 #, c-format msgid "cannot move tuple across partitions when a non-root ancestor of the source partition is directly referenced in a foreign key" msgstr "" -#: executor/nodeModifyTable.c:2218 +#: executor/nodeModifyTable.c:2415 #, c-format msgid "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." msgstr "" -#: executor/nodeModifyTable.c:2221 +#: executor/nodeModifyTable.c:2418 #, c-format msgid "Consider defining the foreign key on table \"%s\"." msgstr "განიხილეთ გარე გასაღების აღწერა ცხრილზე \"%s\"." #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2567 executor/nodeModifyTable.c:3081 executor/nodeModifyTable.c:3242 +#: executor/nodeModifyTable.c:2785 executor/nodeModifyTable.c:3334 executor/nodeModifyTable.c:3504 #, c-format msgid "%s command cannot affect row a second time" msgstr "ბრძანებას %s მწკრივის მეორედ შეცვლა არ შეუძლია" -#: executor/nodeModifyTable.c:2569 +#: executor/nodeModifyTable.c:2787 #, c-format msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values." msgstr "" -#: executor/nodeModifyTable.c:3074 executor/nodeModifyTable.c:3235 +#: executor/nodeModifyTable.c:3327 executor/nodeModifyTable.c:3497 #, c-format msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" msgstr "გასაახლებელი ან წასაშლელ კორტეჟი მიმდინარე ბრძანების მიერ დატრიგერებულმა ოპერაციამ უკვე შეცვალა" -#: executor/nodeModifyTable.c:3083 executor/nodeModifyTable.c:3244 +#: executor/nodeModifyTable.c:3336 executor/nodeModifyTable.c:3506 #, c-format msgid "Ensure that not more than one source row matches any one target row." msgstr "" -#: executor/nodeModifyTable.c:3152 +#: executor/nodeModifyTable.c:3405 #, c-format msgid "tuple to be merged was already moved to another partition due to concurrent update" msgstr "შესარწყმელი კორტეჟები პარალელური განახლების გამო უკვე სხვა დანაყოფშია გადატანილი" @@ -13708,7 +13956,7 @@ msgstr "TABLESAMPLE პარამეტრი ნულოვანი ვე msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "TABLESAMPLE REPEATABLE პარამეტრი ნულოვანი ვერ იქნება" -#: executor/nodeSubplan.c:325 executor/nodeSubplan.c:351 executor/nodeSubplan.c:405 executor/nodeSubplan.c:1174 +#: executor/nodeSubplan.c:317 executor/nodeSubplan.c:343 executor/nodeSubplan.c:397 executor/nodeSubplan.c:1182 #, c-format msgid "more than one row returned by a subquery used as an expression" msgstr "" @@ -13743,104 +13991,104 @@ msgstr "სვეტში \"%s\" ნულოვანი მნიშვნე msgid "moving-aggregate transition function must not return null" msgstr "" -#: executor/nodeWindowAgg.c:2083 +#: executor/nodeWindowAgg.c:2106 #, c-format msgid "frame starting offset must not be null" msgstr "ჩარჩოს საწყისი წანაცვლება ნულის ტოლი ვერ იქნება" -#: executor/nodeWindowAgg.c:2096 +#: executor/nodeWindowAgg.c:2120 #, c-format msgid "frame starting offset must not be negative" msgstr "ჩარჩოს საწყისი წანაცვლება უარყოფითი ვერ იქნება" -#: executor/nodeWindowAgg.c:2108 +#: executor/nodeWindowAgg.c:2133 #, c-format msgid "frame ending offset must not be null" msgstr "ჩარჩოს ბოლოს წანაცვლება ნულის ტოლი ვერ იქნება" -#: executor/nodeWindowAgg.c:2121 +#: executor/nodeWindowAgg.c:2147 #, c-format msgid "frame ending offset must not be negative" msgstr "ჩარჩოს ბოლოს წანაცვლება უარყოფითი ვერ იქნება" -#: executor/nodeWindowAgg.c:2892 +#: executor/nodeWindowAgg.c:2957 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "აგრეგატულ ფუნქციას %s ფანჯრის ფუნქციად გაშვების მხარდაჭერა არ გააჩნია" -#: executor/spi.c:241 executor/spi.c:341 +#: executor/spi.c:242 executor/spi.c:342 #, c-format msgid "invalid transaction termination" msgstr "ტრანზაქციის არასწორი დასასრული" -#: executor/spi.c:256 +#: executor/spi.c:257 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "როცა ქვეტრანზაქცია აქტიურია, კომიტი შეუძლებელია" -#: executor/spi.c:347 +#: executor/spi.c:348 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "როცა ქვეტრანზაქცია აქტიურია, ტრანზაქციის გაუქმება შეუძლებელია" -#: executor/spi.c:471 +#: executor/spi.c:472 #, c-format msgid "transaction left non-empty SPI stack" msgstr "ტრანზაქცის შემდეგ დარჩენილი SPI სტეკი ცარიელი არაა" -#: executor/spi.c:472 executor/spi.c:532 +#: executor/spi.c:473 executor/spi.c:533 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "ნაკლულ \"SPI_finish\" გამოძახებებზე შემოწმება." -#: executor/spi.c:531 +#: executor/spi.c:532 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "ქვეტრანზაქცის შემდეგ დარჩენილი SPI სტეკი ცარიელი არაა" -#: executor/spi.c:1599 +#: executor/spi.c:1603 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "მრავალმოთხოვნიანი გეგმის კურსორის სახით გახსნა შეუძლებელია" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1609 +#: executor/spi.c:1613 #, c-format msgid "cannot open %s query as cursor" msgstr "%s გამოსახულების კურსორის სახით გახნა შეუძლებელია" -#: executor/spi.c:1715 +#: executor/spi.c:1720 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE მხარდაჭერილი არაა" -#: executor/spi.c:1716 parser/analyze.c:2928 +#: executor/spi.c:1721 parser/analyze.c:3161 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "გადახვევადი კურსორები READ ONLY უნდა იყოს." -#: executor/spi.c:2488 +#: executor/spi.c:2498 #, c-format msgid "empty query does not return tuples" msgstr "ცარიელი მოთხოვნა კორტეჟებს არ აბრუნებს" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2562 +#: executor/spi.c:2573 #, c-format msgid "%s query does not return tuples" msgstr "მოთხოვნა %s კორტეჟებს არ აბრუნებს" -#: executor/spi.c:2979 +#: executor/spi.c:3004 #, c-format -msgid "SQL expression \"%s\"" -msgstr "SQL გამოსახულება \"%s\"" +msgid "PL/pgSQL expression \"%s\"" +msgstr "PL/pgSQL გამოსახულება \"%s\"" -#: executor/spi.c:2984 +#: executor/spi.c:3009 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "PL/pgSQL მინიჭება \"%s\"" -#: executor/spi.c:2987 +#: executor/spi.c:3012 #, c-format msgid "SQL statement \"%s\"" msgstr "SQL ოპერატორი \"%s\"" @@ -13850,478 +14098,480 @@ msgstr "SQL ოპერატორი \"%s\"" msgid "could not send tuple to shared-memory queue" msgstr "გაზიარებული-მეხსიერების მქონე რიგში კორტეჟის გაგზავნა შეუძლებელია" -#: foreign/foreign.c:224 +#: foreign/foreign.c:225 #, c-format msgid "user mapping not found for user \"%s\", server \"%s\"" msgstr "\"%s\"-სთვის მომხმარებლის ასახვა ვერ ვიპოვე. სერვერი \"%s\"" -#: foreign/foreign.c:650 +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7228 optimizer/util/plancat.c:538 +#, c-format +msgid "access to non-system foreign table is restricted" +msgstr "" + +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "არასწორი პარამეტრი \"%s\"" -#: foreign/foreign.c:652 +#: foreign/foreign.c:662 #, c-format msgid "Perhaps you meant the option \"%s\"." msgstr "შესაძლოა, გულისხმობდით პარამეტრს \"%s\"." -#: foreign/foreign.c:654 +#: foreign/foreign.c:664 #, c-format msgid "There are no valid options in this context." msgstr "ამ კონტექსტში სწორი პარამეტრები არ არსებობს." -#: gram.y:1234 +#: gram.y:1223 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "UNENCRYPTED PASSWORD მხარდაჭერილი აღარაა" -#: gram.y:1235 +#: gram.y:1224 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." msgstr "პაროლის დაშიფრულ ფორმაში დასამახსოვრებლად წაშალეთ UNENCRYPTED." -#: gram.y:1562 gram.y:1578 +#: gram.y:1551 gram.y:1567 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "CREATE SCHEMA IF NOT EXISTS არ შეიძლება, სქემის ელემენტებს შეიცავდეს" -#: gram.y:1730 +#: gram.y:1728 #, c-format msgid "current database cannot be changed" msgstr "მიმდინარე ბაზის შეცვლა შეუძლებელია" -#: gram.y:1863 +#: gram.y:1869 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "დროის სარტყლის ინტერვალი HOUR ან HOUR TO MINUTE უნდა იყოს" -#: gram.y:2539 +#: gram.y:2501 #, c-format msgid "column number must be in range from 1 to %d" msgstr "სვეტის ნომერი უნდა იყოს 1-დან %d-მდე" -#: gram.y:3135 +#: gram.y:3120 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "მიმდევრობის პარამეტრი \"%s\" აქ მხარდაჭერილი არაა" -#: gram.y:3174 +#: gram.y:3159 #, c-format msgid "modulus for hash partition provided more than once" msgstr "ჰეშ-დანაყოფის მოდული ერთზე მეტჯერაა მითითებული" -#: gram.y:3183 +#: gram.y:3168 #, c-format msgid "remainder for hash partition provided more than once" msgstr "დარჩენილი ნაწილი ჰეშ-დანაყოფისთვის ერთზე მეტჯერაა მითითებული" -#: gram.y:3190 +#: gram.y:3175 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "" -#: gram.y:3198 +#: gram.y:3183 #, c-format msgid "modulus for hash partition must be specified" msgstr "საჭიროა ჰეშ დანაყოფის მოდულის მითითება" -#: gram.y:3202 +#: gram.y:3188 #, c-format msgid "remainder for hash partition must be specified" msgstr "საჭიროა ჰეშ დანაყოფის ნაშთის მითითება" -#: gram.y:3410 gram.y:3444 +#: gram.y:3397 gram.y:3432 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "STDIN/STDOUT-ი PROGRAM-თან ერთად დაშვებული არაა" -#: gram.y:3416 +#: gram.y:3403 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "პირობა 'WHERE' 'COPY TO'-სთან ერთად დაშვებული არაა" -#: gram.y:3764 gram.y:3771 gram.y:13068 gram.y:13076 +#: gram.y:3752 gram.y:3759 gram.y:13184 gram.y:13192 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "დროებითი ცხრილის შექმნაში GLOBAL-ი მოძველებულია" -#: gram.y:4047 +#: gram.y:4041 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" msgstr "გენერირებული სვეტისთვის GENERATED ALWAYS-ის მითითება აუცილებელია" -#: gram.y:4392 utils/adt/ri_triggers.c:2103 +#: gram.y:4450 utils/adt/ri_triggers.c:2259 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "MATCH PARTIAL ჯერ განხორციელებული არაა" -#: gram.y:4484 +#: gram.y:4542 #, c-format msgid "a column list with %s is only supported for ON DELETE actions" msgstr "" -#: gram.y:5196 +#: gram.y:5261 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM უკვე მხარდაუჭერელია" -#: gram.y:5894 +#: gram.y:5959 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "მწკრივის უსაფრთხოების უცნობი პარამეტრი:\"%s\"" -#: gram.y:5895 +#: gram.y:5960 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." msgstr "" -#: gram.y:5980 +#: gram.y:6045 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGER მხარდაუჭერელია" -#: gram.y:6017 +#: gram.y:6083 msgid "duplicate trigger events specified" msgstr "მითითებულია ტრიგერი მეორდება" -#: gram.y:6159 parser/parse_utilcmd.c:3839 parser/parse_utilcmd.c:3865 +#: gram.y:6225 parser/parse_utilcmd.c:3925 parser/parse_utilcmd.c:3951 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" -msgstr "" +msgstr "შეზღუდვა, რომელიც აღწერილია, როგორც 'INITIALLY DEFERRED' DEFERRABLE ტიპის უნდა იყოს" -#: gram.y:6166 +#: gram.y:6233 #, c-format msgid "conflicting constraint properties" msgstr "ერთმანეთთან შეუთავსებელი შეზღუდვის თვისებები" -#: gram.y:6265 +#: gram.y:6334 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "CREATE ASSERTION ჯერ განუხორცელებია" -#: gram.y:6582 +#: gram.y:6652 #, c-format msgid "dropping an enum value is not implemented" msgstr "ჩამონათვლის მნიშვნელობის მოცილება განხორციელებული არაა" -#: gram.y:6700 -#, c-format -msgid "RECHECK is no longer required" -msgstr "RECHECK საჭირო აღარაა" - -#: gram.y:6701 -#, c-format -msgid "Update your data type." -msgstr "განაახლეთ თქვენი მონაცემთა ტიპი." - -#: gram.y:8574 +#: gram.y:8632 #, c-format msgid "aggregates cannot have output arguments" msgstr "აგრეგატებს გამოტანის არგუმენტები ვერ ექნება" -#: gram.y:9037 utils/adt/regproc.c:670 +#: gram.y:9096 utils/adt/regproc.c:670 #, c-format msgid "missing argument" msgstr "ნაკლული არგუმენტი" -#: gram.y:9038 utils/adt/regproc.c:671 +#: gram.y:9097 utils/adt/regproc.c:671 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "" -#: gram.y:11266 gram.y:11285 +#: gram.y:11325 gram.y:11344 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "WITH CHECK OPTION რეკურსიულ ხედებზე მხარდაუჭერელია" -#: gram.y:13207 +#: gram.y:13331 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "LIMIT #,# სინტაქსი მხარდაჭერილი არაა" -#: gram.y:13208 +#: gram.y:13332 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "გამოიყენეთ განცალკევებული LIMIT და OFFSET პირობები." -#: gram.y:14083 +#: gram.y:14220 #, c-format msgid "only one DEFAULT value is allowed" msgstr "დასაშვებია DEFAULT_ის მხოლოდ ერთი მნიშვნელობა" -#: gram.y:14092 +#: gram.y:14229 #, c-format msgid "only one PATH value per column is allowed" msgstr "ყოველ სვეტზე PATH-ის მხოლოდ ერთი მნიშვნელობაა დასაშვები" -#: gram.y:14101 +#: gram.y:14238 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "" -#: gram.y:14110 +#: gram.y:14247 #, c-format msgid "unrecognized column option \"%s\"" msgstr "სვეტის უცნობი პარამეტრი %s" -#: gram.y:14192 +#: gram.y:14329 #, c-format msgid "only string constants are supported in JSON_TABLE path specification" msgstr "" -#: gram.y:14514 +#: gram.y:14651 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "წილადი რიცხვების სიზუსტე 1 ბიტი მაინც უნდა იყოს" -#: gram.y:14523 +#: gram.y:14660 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "წილადი რიცხვების სიზუსტე 54 ბიტზე მეტი ვერ იქნება" -#: gram.y:15040 +#: gram.y:15177 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "" -#: gram.y:15045 +#: gram.y:15182 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "" -#: gram.y:15222 +#: gram.y:15359 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "პრედიკატი UNIQUE ჯერ განხორციელებული არაა" -#: gram.y:15636 +#: gram.y:15773 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "'WITHIN GROUP'-თან ერთად ერთზე მეტი ORDER BY პირობის გამოყენება შეუძლებელია" -#: gram.y:15641 +#: gram.y:15778 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "\"DISTINCT\"-ს \"WITHIN GROUP\"-თან ერთად ვერ გამოიყენებთ" -#: gram.y:15646 +#: gram.y:15783 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "\"VARIADIC\"-ს \"WITHIN GROUP\"-თან ერთად ვერ გამოიყენებთ" -#: gram.y:16373 gram.y:16397 +#: gram.y:16510 gram.y:16534 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "ჩარჩოს დასაწყისი UNBOUNDED FOLLOWING ვერ იქნება" -#: gram.y:16378 +#: gram.y:16515 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "ჩარჩო, რომელიც შემდეგი მწკრივიდან იწყება, მიმდინარე მწკრივზე ვერ დასრულდება" -#: gram.y:16402 +#: gram.y:16539 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "ჩარჩოს დასასრული UNBOUNDED PRECEDING ვერ იქნება" -#: gram.y:16408 +#: gram.y:16545 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "ჩარჩოს, რომელიც მიმდინარე მწკრივიდან იწყება, წინა ჩარჩოები ვერ ექნება" -#: gram.y:16415 +#: gram.y:16552 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "ჩარჩოს, რომელიც შემდეგი მწკრივიდან იწყება, წინა ჩარჩოები ვერ ექნება" -#: gram.y:16964 +#: gram.y:17101 #, c-format msgid "unrecognized JSON encoding: %s" msgstr "უცნობი JSON კოდირება \"%s\"" -#: gram.y:17288 +#: gram.y:17426 #, c-format msgid "type modifier cannot have parameter name" msgstr "ტიპის მოდიფიკატორს პარამეტრის სახელი ვერ ექნება" -#: gram.y:17294 +#: gram.y:17432 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "ტიპის მოდიფიკატორს ORDER BY ვერ ექნება" -#: gram.y:17362 gram.y:17369 gram.y:17376 +#: gram.y:17500 gram.y:17507 gram.y:17514 #, c-format msgid "%s cannot be used as a role name here" msgstr "%s აქ როგორც როლის სახელს ვერ გამოიყენებთ" -#: gram.y:17466 gram.y:18955 +#: gram.y:17604 gram.y:19135 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" msgstr "WITH TIES-ს ORDER BY პირობის გარეშე ვერ მიუთითებთ" -#: gram.y:18646 gram.y:18821 +#: gram.y:18828 gram.y:19003 msgid "improper use of \"*\"" msgstr "\"*\"-ის არასათანადო გამოყენება" -#: gram.y:18784 gram.y:18801 tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 tsearch/spell.c:1014 tsearch/spell.c:1079 +#: gram.y:18966 gram.y:18983 tsearch/spell.c:965 tsearch/spell.c:982 tsearch/spell.c:999 tsearch/spell.c:1016 tsearch/spell.c:1082 #, c-format msgid "syntax error" msgstr "სინტაქსის შეცდომა" -#: gram.y:18885 +#: gram.y:19067 #, c-format msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type" msgstr "" -#: gram.y:18922 +#: gram.y:19104 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "\"ORDER BY\"-ის გამოყენება მხოლოდ ერთხელ შეგიძლიათ" -#: gram.y:18933 +#: gram.y:19115 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "\"OFFSET\"-ის გამოყენება მხოლოდ ერთხელ შეგიძლიათ" -#: gram.y:18942 +#: gram.y:19124 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "\"LIMIT\"-ის გამოყენება მხოლოდ ერთხელ შეგიძლიათ" -#: gram.y:18951 -#, c-format -msgid "multiple limit options not allowed" -msgstr "ლიმიტის პარამეტრების მითითება მხოლოდ ერთხელ შეგიძლიათ" - -#: gram.y:18978 +#: gram.y:19160 #, c-format msgid "multiple WITH clauses not allowed" msgstr "\"WITH\"-ის გამოყენება მხოლოდ ერთხელ შეგიძლიათ" -#: gram.y:19171 +#: gram.y:19358 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "" -#: gram.y:19304 +#: gram.y:19492 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "\"COLLATE\"-ის გამოყენება მხოლოდ ერთხელ შეგიძლიათ" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19342 gram.y:19355 +#: gram.y:19532 gram.y:19545 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "%s -ის შეზღუდვებიs, როგორც DEFERRABLE, მონიშვნა შეუძლებელია" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19368 +#: gram.y:19558 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "%s -ის შეზღუდვებიs, როგორც NOT VALID, მონიშვნა შეუძლებელია" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:19381 +#: gram.y:19571 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "%s -ის შეზღუდვებიs, როგორც NO INHERIT, მონიშვნა შეუძლებელია" -#: gram.y:19403 +#. translator: %s is CHECK, UNIQUE, or similar +#: gram.y:19584 +#, c-format +msgid "%s constraints cannot be marked NOT ENFORCED" +msgstr "%s -ის შეზღუდვების, როგორც NOT ENFORCED, მონიშვნა შეუძლებელია" + +#. translator: %s is CHECK, UNIQUE, or similar +#: gram.y:19606 +#, c-format +msgid "%s constraints cannot be marked ENFORCED" +msgstr "%s -ის შეზღუდვებიs, როგორც ENFORCED, მონიშვნა შეუძლებელია" + +#: gram.y:19628 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "დაყოფის უცნობი სტრატეგია: %s" -#: gram.y:19427 +#: gram.y:19652 #, c-format msgid "invalid publication object list" msgstr "პუბლიკაციების ობიექტების არასწორი სია" -#: gram.y:19428 +#: gram.y:19653 #, c-format msgid "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name." msgstr "" -#: gram.y:19444 +#: gram.y:19669 #, c-format msgid "invalid table name" msgstr "არასწორი ცხრილის სახელი" -#: gram.y:19465 +#: gram.y:19690 #, c-format msgid "WHERE clause not allowed for schema" msgstr "WHERE პირობა სქემისთვის დაშვებული არაა" -#: gram.y:19472 +#: gram.y:19697 #, c-format msgid "column specification not allowed for schema" msgstr "სქემისთვის სვეტის მითითება დაშვებული არაა" -#: gram.y:19486 +#: gram.y:19711 #, c-format msgid "invalid schema name" msgstr "არასწორი სქემის სახელი" -#: guc-file.l:192 +#: guc-file.l:193 #, c-format msgid "empty configuration file name: \"%s\"" msgstr "კონფიგურაციის ფაილის ცარიელი სახელი: \"%s\"" -#: guc-file.l:209 +#: guc-file.l:210 #, c-format msgid "could not open configuration file \"%s\": maximum nesting depth exceeded" msgstr "კონფიგურაციის ფაილის (\"%s\") გახსნა შეუძლებელია: ჩალაგების სიღრმე გადაცილებულია" -#: guc-file.l:229 +#: guc-file.l:230 #, c-format msgid "configuration file recursion in \"%s\"" msgstr "კონფიგურაციის ფაილის რეკურსია \"%s\"-ში" -#: guc-file.l:245 +#: guc-file.l:246 #, c-format msgid "could not open configuration file \"%s\": %m" msgstr "კონფიგურაციის ფაილის ('%s') გახსნის შეცდომა: %m" -#: guc-file.l:256 +#: guc-file.l:257 #, c-format msgid "skipping missing configuration file \"%s\"" msgstr "კონფიგურაციის ფაილის გამოტოვება \"%s\"" -#: guc-file.l:511 +#: guc-file.l:518 #, c-format msgid "syntax error in file \"%s\" line %u, near end of line" msgstr "სინტაქსის შეცდომა ფაილში \"%s\" ხაზზე %u, ხაზის ბოლოსთან ახლოს" -#: guc-file.l:521 +#: guc-file.l:528 #, c-format msgid "syntax error in file \"%s\" line %u, near token \"%s\"" msgstr "სინტაქსის შეცდომა ფაილში \"%s\" ხაზზე %u, ახლოს კოდთან \"%s\"" -#: guc-file.l:541 +#: guc-file.l:548 #, c-format msgid "too many syntax errors found, abandoning file \"%s\"" msgstr "აღმოჩენილია მეტისმეტად ბევრი შეცდომა. ფაილი \"%s\" მიტოვებულია" -#: jsonpath_gram.y:266 jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 jsonpath_scan.l:661 jsonpath_scan.l:712 utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:658 utils/adt/varlena.c:333 utils/adt/varlena.c:374 +#: jsonpath_gram.y:268 jsonpath_gram.y:600 jsonpath_scan.l:617 jsonpath_scan.l:628 jsonpath_scan.l:638 jsonpath_scan.l:690 utils/adt/encode.c:513 utils/adt/encode.c:578 utils/adt/jsonfuncs.c:661 utils/adt/varlena.c:341 utils/adt/varlena.c:382 #, c-format msgid "invalid input syntax for type %s" msgstr "არასწორი შეყვანის სინტაქსი ტიპისთვის %s" -#: jsonpath_gram.y:267 +#: jsonpath_gram.y:269 #, c-format msgid ".decimal() can only have an optional precision[,scale]." msgstr "" -#: jsonpath_gram.y:599 +#: jsonpath_gram.y:601 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." msgstr "უცნობი ალმის სიმბოლო \"%.*s\" LIKE_REGEX პრედიკატში." -#: jsonpath_gram.y:629 tsearch/spell.c:749 utils/adt/regexp.c:223 +#: jsonpath_gram.y:631 tsearch/spell.c:751 utils/adt/regexp.c:223 #, c-format msgid "invalid regular expression: %s" msgstr "არასწორი რეგულარული გამოსახულება: %s" -#: jsonpath_gram.y:677 +#: jsonpath_gram.y:679 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "ენის XQuery ალამი \"x\" (გაფართოებული რეგულარული გამოსახულებები) განხორციელებული არაა" @@ -14338,48 +14588,48 @@ msgstr "არასწორი თექვსმეტობითი სი msgid "unexpected end after backslash" msgstr "მოულოდნელი დასასრული '\\' სიმბოლოს შემდეგ" -#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:742 +#: jsonpath_scan.l:201 repl_scanner.l:217 scan.l:742 msgid "unterminated quoted string" msgstr "ბრჭყალებში ჩასმული ციტატის დაუსრულებელი სტრიქონი" -#: jsonpath_scan.l:228 +#: jsonpath_scan.l:227 msgid "unexpected end of comment" msgstr "კომენტარის მოულოდნელი დასასრული" -#: jsonpath_scan.l:319 +#: jsonpath_scan.l:317 msgid "invalid numeric literal" msgstr "არასწორი რიცხვითი მუდმივა" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1050 scan.l:1054 scan.l:1058 scan.l:1062 scan.l:1066 scan.l:1070 scan.l:1074 +#: jsonpath_scan.l:322 jsonpath_scan.l:327 jsonpath_scan.l:332 scan.l:1056 scan.l:1060 scan.l:1064 scan.l:1068 msgid "trailing junk after numeric literal" msgstr "რიცხვითი მნიშვნელობის შემდეგ მონაცემები ნაგავია" #. translator: %s is typically "syntax error" -#: jsonpath_scan.l:375 +#: jsonpath_scan.l:378 #, c-format msgid "%s at end of jsonpath input" msgstr "%s jsonpath-ის შეყვანის ბოლოში" #. translator: first %s is typically "syntax error" -#: jsonpath_scan.l:382 +#: jsonpath_scan.l:385 #, c-format msgid "%s at or near \"%s\" of jsonpath input" -msgstr "" +msgstr "%s ზუსტად ან ახლოს jsonpath შეყვანის \"%s\"-სთან" -#: jsonpath_scan.l:568 +#: jsonpath_scan.l:545 msgid "invalid input" msgstr "არასწორი შეყვანა" -#: jsonpath_scan.l:594 +#: jsonpath_scan.l:571 msgid "invalid hexadecimal digit" msgstr "არასწორი თექვსმეტობითი ციფრი" -#: jsonpath_scan.l:607 utils/adt/jsonfuncs.c:646 +#: jsonpath_scan.l:584 utils/adt/jsonfuncs.c:649 #, c-format msgid "unsupported Unicode escape sequence" msgstr "უნიკოდის სპეცკოდის მხარდაუჭერელი მიმდევრობა" -#: jsonpath_scan.l:625 +#: jsonpath_scan.l:602 #, c-format msgid "could not convert Unicode to server encoding" msgstr "უნიკოდის სერვერის კოდირებაში გადაყვანა შეუძლებელია" @@ -14389,685 +14639,852 @@ msgstr "უნიკოდის სერვერის კოდირებ msgid "Failed on DSA request of size %zu." msgstr "შეცდომა DSA მეხსიერების გამოთხოვისას (ზომა %zu ბაიტი)." -#: libpq/auth-sasl.c:97 -#, c-format -msgid "expected SASL response, got message type %d" -msgstr "მოველოდი SASL პასუხს. მიღებული შეტყობინების ტიპია %d" - -#: libpq/auth-scram.c:263 +#: libpq/auth-oauth.c:109 libpq/auth-scram.c:267 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "კლიენტის არჩეული SASL ავთენტიკაციის მექანიზმი არასწორია" -#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 +#: libpq/auth-oauth.c:169 libpq/auth-oauth.c:174 libpq/auth-oauth.c:192 libpq/auth-oauth.c:220 libpq/auth-oauth.c:230 libpq/auth-oauth.c:239 libpq/auth-oauth.c:254 libpq/auth-oauth.c:263 libpq/auth-oauth.c:272 libpq/auth-oauth.c:279 libpq/auth-oauth.c:342 libpq/auth-oauth.c:349 libpq/auth-oauth.c:375 libpq/auth-oauth.c:420 libpq/auth-oauth.c:438 libpq/auth-oauth.c:452 libpq/auth-oauth.c:472 +#, c-format +msgid "malformed OAUTHBEARER message" +msgstr "დამახინჯებული OAUTHBEARER-ის შეტყობინება" + +#: libpq/auth-oauth.c:170 libpq/auth-scram.c:383 +#, c-format +msgid "The message is empty." +msgstr "შეტყობინება ცარიელია." + +#: libpq/auth-oauth.c:175 libpq/auth-scram.c:388 +#, c-format +msgid "Message length does not match input length." +msgstr "შეტყობინების სიგრძე შეყვანის სიგრძეს არემთხვევა." + +#: libpq/auth-oauth.c:193 +#, c-format +msgid "Client did not send a kvsep response." +msgstr "კლიენტმა kvsep პასუხი არ გამოაგზავნა." + +#: libpq/auth-oauth.c:221 +#, c-format +msgid "The server does not support channel binding for OAuth, but the client message includes channel binding data." +msgstr "სერვერს არ აქვს არხის მიბმის მხარდაჭერა OAuth-სთვის, მაგრამ კლიენტის შეტყობინება არხის მიბმის მონაცემებს შეიცავს." + +#: libpq/auth-oauth.c:231 libpq/auth-scram.c:1003 libpq/auth-scram.c:1033 +#, c-format +msgid "Comma expected, but found character \"%s\"." +msgstr "მოველოდი მძიმეს, მაგრამ აღმოჩენილია სიმბოლო \"%s\"." + +#: libpq/auth-oauth.c:240 libpq/auth-scram.c:1065 +#, c-format +msgid "Unexpected channel-binding flag \"%s\"." +msgstr "არხზე მიბმის მოულოდნელი ალამი: \"%s\"." + +#: libpq/auth-oauth.c:250 libpq/auth-scram.c:1075 +#, c-format +msgid "client uses authorization identity, but it is not supported" +msgstr "კლიენტი იყენებს ავტორიზაციის იდენტიფიკაციას, მაგრამ ის მხარდაჭერილი არაა" + +#: libpq/auth-oauth.c:255 libpq/auth-scram.c:1080 +#, c-format +msgid "Unexpected attribute \"%s\" in client-first-message." +msgstr "" + +#: libpq/auth-oauth.c:264 +#, c-format +msgid "Key-value separator expected, but found character \"%s\"." +msgstr "მოველოდი გასაღები-მნიშვნელობის წყვილს, მაგრამ აღმოჩენილია სიმბოლო \"%s\"." + +#: libpq/auth-oauth.c:273 +#, c-format +msgid "Message does not contain an auth value." +msgstr "შეტყობინება ავტორიზაციის მნიშვნელობას არ შეიცავს." + +#: libpq/auth-oauth.c:280 +#, c-format +msgid "Message contains additional data after the final terminator." +msgstr "შეტყობინება დასრულების სიმბოლოს შემდეგ მონაცემებს კიდევ შეიცავს." + +#: libpq/auth-oauth.c:343 +#, c-format +msgid "Message contains an empty key name." +msgstr "შეტყობინება ცარიელი გასაღების სახელს შეიცავს." + +#: libpq/auth-oauth.c:350 +#, c-format +msgid "Message contains an invalid key name." +msgstr "შეტყობინება არასწორი გასაღების სახელს შეიცავს." + +#: libpq/auth-oauth.c:376 +#, c-format +msgid "Message contains an invalid value." +msgstr "შეტყობინება არასწორ მნიშვნელობას შეიცავს." + +#: libpq/auth-oauth.c:421 +#, c-format +msgid "Message contains an unterminated key/value pair." +msgstr "შეტყობინება დასრულების სიმბოლოს გარეშე მითითებულ გასაღები/მნიშვნელობის წყვილს შეიცავს." + +#: libpq/auth-oauth.c:439 +#, c-format +msgid "Message contains a key without a value." +msgstr "შეტყობინება შეიცავს გასაღებს მნიშვნელობის გარეშე." + +#: libpq/auth-oauth.c:453 +#, c-format +msgid "Message contains multiple auth values." +msgstr "შეტყობინება ერთზე მეტ ავთენტიკაციის მნიშვნელობას შეიცავს." + +#: libpq/auth-oauth.c:473 +#, c-format +msgid "Message did not contain a final terminator." +msgstr "შეტყობინება საბოლოო დასასრულის სიმბოლოს არ შეიცავს." + +#: libpq/auth-oauth.c:499 +#, c-format +msgid "OAuth is not properly configured for this user" +msgstr "ამ მომხმარებლისთვის OAuth სწორად არაა მორგებული" + +#: libpq/auth-oauth.c:500 +#, c-format +msgid "The issuer and scope parameters must be set in pg_hba.conf." +msgstr "" + +#: libpq/auth-oauth.c:585 libpq/auth-oauth.c:602 libpq/auth-oauth.c:624 +#, c-format +msgid "malformed OAuth bearer token" +msgstr "დამახინჯებული OAuth-ის წარმდგენის ტოკენი" + +#: libpq/auth-oauth.c:586 +#, c-format +msgid "Client response indicated a non-Bearer authentication scheme." +msgstr "კლიენტის პასუხი მიუთითებს არა-წარმდგენ ავთენტიკაციის სქემაზე." + +#: libpq/auth-oauth.c:603 +#, c-format +msgid "Bearer token is empty." +msgstr "წარმდგენის ტოკენი ცარიელია." + +#: libpq/auth-oauth.c:625 +#, c-format +msgid "Bearer token is not in the correct format." +msgstr "" + +#: libpq/auth-oauth.c:656 +#, c-format +msgid "validation of OAuth token requested without a validator loaded" +msgstr "" + +#: libpq/auth-oauth.c:665 +#, c-format +msgid "internal error in OAuth validator module" +msgstr "" + +#: libpq/auth-oauth.c:679 libpq/auth-oauth.c:703 libpq/auth.c:294 +#, c-format +msgid "OAuth bearer authentication failed for user \"%s\"" +msgstr "OAuth-ის წარმდგენის ავთენტიკაცია ჩავარდა მომხმარებლისთვის \"%s\"" + +#: libpq/auth-oauth.c:681 +#, c-format +msgid "Validator failed to authorize the provided token." +msgstr "" + +#: libpq/auth-oauth.c:705 +#, c-format +msgid "Validator provided no identity." +msgstr "" + +#: libpq/auth-oauth.c:760 +#, c-format +msgid "%s module \"%s\" must define the symbol %s" +msgstr "" + +#: libpq/auth-oauth.c:773 +#, c-format +msgid "%s module \"%s\": magic number mismatch" +msgstr "%s-ის მოდული \"%s\": ჯადოსნური რიცხვი არ ემთხვევა" + +#: libpq/auth-oauth.c:775 +#, c-format +msgid "Server has magic number 0x%08X, module has 0x%08X." +msgstr "" + +#: libpq/auth-oauth.c:784 +#, c-format +msgid "%s module \"%s\" must provide a %s callback" +msgstr "" + +#: libpq/auth-oauth.c:833 +#, c-format +msgid "oauth_validator_libraries must be set for authentication method %s" +msgstr "oauth_validator_libraries დაყენებული უნდა იყოს ავთენტიკაციის მეთოდისთვის %s" + +#: libpq/auth-oauth.c:835 libpq/auth-oauth.c:868 libpq/auth-oauth.c:884 libpq/hba.c:331 libpq/hba.c:666 libpq/hba.c:1251 libpq/hba.c:1271 libpq/hba.c:1294 libpq/hba.c:1307 libpq/hba.c:1360 libpq/hba.c:1388 libpq/hba.c:1396 libpq/hba.c:1408 libpq/hba.c:1429 libpq/hba.c:1442 libpq/hba.c:1467 libpq/hba.c:1494 libpq/hba.c:1506 libpq/hba.c:1565 libpq/hba.c:1585 libpq/hba.c:1599 libpq/hba.c:1619 libpq/hba.c:1630 libpq/hba.c:1645 libpq/hba.c:1664 libpq/hba.c:1680 +#: libpq/hba.c:1692 libpq/hba.c:1760 libpq/hba.c:1773 libpq/hba.c:1795 libpq/hba.c:1807 libpq/hba.c:1825 libpq/hba.c:1875 libpq/hba.c:1919 libpq/hba.c:1930 libpq/hba.c:1946 libpq/hba.c:1963 libpq/hba.c:1974 libpq/hba.c:1993 libpq/hba.c:2009 libpq/hba.c:2025 libpq/hba.c:2069 libpq/hba.c:2115 libpq/hba.c:2132 libpq/hba.c:2145 libpq/hba.c:2157 libpq/hba.c:2176 libpq/hba.c:2262 libpq/hba.c:2280 libpq/hba.c:2374 libpq/hba.c:2393 libpq/hba.c:2422 libpq/hba.c:2435 +#: libpq/hba.c:2458 libpq/hba.c:2480 libpq/hba.c:2517 tsearch/ts_locale.c:196 +#, c-format +msgid "line %d of configuration file \"%s\"" +msgstr "კონფიგურაციის ფაილის \"%2$s\" ხაზზე %1$d" + +#: libpq/auth-oauth.c:867 +#, c-format +msgid "authentication method \"oauth\" requires argument \"validator\" to be set when oauth_validator_libraries contains multiple options" +msgstr "ავთენტიკაციის მეთოდს \"oauth\" სჭირდება, რომ არგუმენტი \"validator\" დაყენებული იყოს, როცა oauth_validator_libraries ერთზე მეტ პარამეტრს შეიცავს" + +#: libpq/auth-oauth.c:882 +#, c-format +msgid "validator \"%s\" is not permitted by %s" +msgstr "ვალიდატორი \"%s\" აკრძალულია %s\"-ის მიერ" + +#: libpq/auth-sasl.c:89 +#, c-format +msgid "expected SASL response, got message type %d" +msgstr "მოველოდი SASL პასუხს. მიღებული შეტყობინების ტიპია %d" + +#: libpq/auth-scram.c:291 libpq/auth-scram.c:547 libpq/auth-scram.c:558 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "არასწორი SCRAM საიდუმლო მომხმარებლისთვის \"%s\"" -#: libpq/auth-scram.c:298 +#: libpq/auth-scram.c:302 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "მომხმარებელს \"%s\" სწორი SCRAM საიდუმლო არ გააჩნია." -#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:382 libpq/auth-scram.c:387 libpq/auth-scram.c:751 libpq/auth-scram.c:759 libpq/auth-scram.c:864 libpq/auth-scram.c:877 libpq/auth-scram.c:887 libpq/auth-scram.c:995 libpq/auth-scram.c:1002 libpq/auth-scram.c:1017 libpq/auth-scram.c:1032 libpq/auth-scram.c:1046 libpq/auth-scram.c:1064 libpq/auth-scram.c:1079 libpq/auth-scram.c:1392 libpq/auth-scram.c:1400 #, c-format msgid "malformed SCRAM message" msgstr "დამახინჯებული SCRAM-ის შეტყობინება" -#: libpq/auth-scram.c:379 -#, c-format -msgid "The message is empty." -msgstr "შეტყობინება ცარიელია." - -#: libpq/auth-scram.c:384 -#, c-format -msgid "Message length does not match input length." -msgstr "შეტყობინების სიგრძე შეყვანის სიგრძეს არემთხვევა." - -#: libpq/auth-scram.c:416 +#: libpq/auth-scram.c:420 #, c-format msgid "invalid SCRAM response" msgstr "არასწორი SCRAM პასუხი" -#: libpq/auth-scram.c:417 +#: libpq/auth-scram.c:421 #, c-format msgid "Nonce does not match." msgstr "ერთჯერადი რიცხვები არ ემთხვევა." -#: libpq/auth-scram.c:493 +#: libpq/auth-scram.c:504 #, c-format msgid "could not generate random salt" msgstr "შემთხვევითი მარილის გენერაციის შეცდომა" -#: libpq/auth-scram.c:738 +#: libpq/auth-scram.c:752 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "მოველოდი ატრიბუტს \"%c\" მაგრამ მივიღე \"%s\"." -#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 +#: libpq/auth-scram.c:760 libpq/auth-scram.c:888 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "მოველოდი სიმბოლოს \"=\" ატრიბუტისთვის \"%c\"." -#: libpq/auth-scram.c:851 +#: libpq/auth-scram.c:865 #, c-format msgid "Attribute expected, but found end of string." msgstr "მოველოდი ატრიბუტს, მაგრამ სტრიქონის ბოლო მივიღე." -#: libpq/auth-scram.c:864 +#: libpq/auth-scram.c:878 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "მოველოდი ატრიბუტს, მაგრამ მივიღე არასწორი სიმბოლო \"%s\"." -#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 +#: libpq/auth-scram.c:996 libpq/auth-scram.c:1018 #, c-format msgid "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data." msgstr "კლიენტმა აირჩია SCRAM-SHA-256-PLUS, მაგრამ SCRAM შეტყობინება არხზე მიბმის მონაცემებს არ შეიცავს." -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 -#, c-format -msgid "Comma expected, but found character \"%s\"." -msgstr "მოველოდი მძიმეს, მაგრამ აღმოჩენილია სიმბოლო \"%s\"." - -#: libpq/auth-scram.c:1010 +#: libpq/auth-scram.c:1024 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "SCRAM არხზე მიბმის მოლაპარაკების შეცდომა" -#: libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:1025 #, c-format msgid "The client supports SCRAM channel binding but thinks the server does not. However, this server does support channel binding." msgstr "კლიენტს აქვს SCRAM არხზე მიბმის მხარდაჭერა, მაგრამ ფიქრობს, რომ სერვერს - არა. მაგრამ სერვერს აქვს არხზე მიბმის მხარდაჭერა." -#: libpq/auth-scram.c:1033 +#: libpq/auth-scram.c:1047 #, c-format msgid "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data." msgstr "კლიენტმა SCRAM-SHA-256 არხზე მიბმის გარეშე აირჩია, მაგრამ SCRAM შეტყობინება არხზე მიბმის მონაცემებს შეიცავს." -#: libpq/auth-scram.c:1044 +#: libpq/auth-scram.c:1058 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "მხარდაუჭერელი SCRAM-ის არხზე მიბმის ტიპი \"%s\"" -#: libpq/auth-scram.c:1051 -#, c-format -msgid "Unexpected channel-binding flag \"%s\"." -msgstr "არხზე მიბმის მოულოდნელი ალამი: \"%s\"." - -#: libpq/auth-scram.c:1061 -#, c-format -msgid "client uses authorization identity, but it is not supported" -msgstr "კლიენტი იყენებს ავტორიზაციის იდენტიფიკაციას, მაგრამ ის მხარდაჭერილი არაა" - -#: libpq/auth-scram.c:1066 -#, c-format -msgid "Unexpected attribute \"%s\" in client-first-message." -msgstr "" - -#: libpq/auth-scram.c:1082 +#: libpq/auth-scram.c:1096 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "კლიენტი მოითხოვს SCRAM გაფართოებას, რომელიც მხარდაჭერილი არაა" -#: libpq/auth-scram.c:1096 +#: libpq/auth-scram.c:1110 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "" -#: libpq/auth-scram.c:1227 +#: libpq/auth-scram.c:1240 #, c-format msgid "could not generate random nonce" msgstr "ერთჯერადი კოდის გენერაციის შეცდომა" -#: libpq/auth-scram.c:1237 +#: libpq/auth-scram.c:1250 #, c-format msgid "could not encode random nonce" msgstr "ერთჯერადი კოდის კოდირების შეცდომა" -#: libpq/auth-scram.c:1343 +#: libpq/auth-scram.c:1356 #, c-format msgid "SCRAM channel binding check failed" msgstr "SCRAM არხზე მიბმის შემოწმების შეცდომა" -#: libpq/auth-scram.c:1361 +#: libpq/auth-scram.c:1374 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "" -#: libpq/auth-scram.c:1380 +#: libpq/auth-scram.c:1393 #, c-format msgid "Malformed proof in client-final-message." msgstr "" -#: libpq/auth-scram.c:1388 +#: libpq/auth-scram.c:1401 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "კლიენტის-საბოლოო-შეტყობინების ბოლოში აღმოჩენილია ნაგავი." -#: libpq/auth.c:269 +#: libpq/auth.c:254 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "ავთენტიკაციის შეცდომა მომხმარებლისთვის \"%s\": ჰოსტმა ის უარყო" -#: libpq/auth.c:272 +#: libpq/auth.c:257 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "\"ნდობით\" ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:275 +#: libpq/auth.c:260 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "იდენტიფიკაციით ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:278 +#: libpq/auth.c:263 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "პარტნიორის ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:283 +#: libpq/auth.c:268 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "პაროლით ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:288 +#: libpq/auth.c:273 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "GSSAPI ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:291 +#: libpq/auth.c:276 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "SSPI ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:294 +#: libpq/auth.c:279 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "PAM ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:297 +#: libpq/auth.c:282 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "BSD ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:300 +#: libpq/auth.c:285 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "LDAP ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:303 +#: libpq/auth.c:288 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "სერტიფიკატით ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:306 +#: libpq/auth.c:291 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "რადიუსით ავთენტიფიკაცია მომხმარებლისთვის \"%s\" ვერ მოხერხდა" -#: libpq/auth.c:309 +#: libpq/auth.c:297 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "ავთენტიკაციის შეცდომა მომხმარებლისთვის \"%s\": არასწორი ავთენტიკაციის მეთოდი" -#: libpq/auth.c:313 +#: libpq/auth.c:301 #, c-format msgid "Connection matched file \"%s\" line %d: \"%s\"" msgstr "მიერთება დაემთხვა ფაილ %s-ს ხაზზე %d: \"%s\"" -#: libpq/auth.c:357 +#: libpq/auth.c:346 #, c-format msgid "authentication identifier set more than once" msgstr "ავთენტიფიკაციის იდენტიფიკატორი ერთზე მეტჯერაა დაყენებული" -#: libpq/auth.c:358 +#: libpq/auth.c:347 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "წინა იდენტიფიკატორი: \"%s\"; ახალი იდენტიფიკატორი: \"%s\"" -#: libpq/auth.c:368 +#: libpq/auth.c:357 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "მიერთება ავთენტიფიცირებულია: იდენტიფიკატორი=\"%s\" მეთოდი=%s (%s:%d)" -#: libpq/auth.c:408 +#: libpq/auth.c:397 #, c-format msgid "client certificates can only be checked if a root certificate store is available" msgstr "კლიენტის სერტიფიკატების შემოწმება მხოლოდ მაშინაა შესაძლებელი, როცა ხელმისაწვდომია ძირითადი სერტიფიკატების საცავი" -#: libpq/auth.c:419 +#: libpq/auth.c:408 #, c-format msgid "connection requires a valid client certificate" msgstr "მიერთების მცდელობას კლიენტის სწორი სერტიფიკატი ესაჭიროება" -#: libpq/auth.c:450 libpq/auth.c:496 +#: libpq/auth.c:439 libpq/auth.c:485 msgid "GSS encryption" msgstr "GSS დაშიფვრა" -#: libpq/auth.c:453 libpq/auth.c:499 +#: libpq/auth.c:442 libpq/auth.c:488 msgid "SSL encryption" msgstr "SSL დაშიფვრა" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:444 libpq/auth.c:490 msgid "no encryption" msgstr "დაშიფვრის გარეშე" #. translator: last %s describes encryption state -#: libpq/auth.c:461 +#: libpq/auth.c:450 #, c-format msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf უარყოფს რეპლიკაციის მიერთებას ჰოსტისთვის \"%s\", მომხმარებელი \"%s\", %s" #. translator: last %s describes encryption state -#: libpq/auth.c:468 +#: libpq/auth.c:457 #, c-format msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf უარყოფს მიერთებას ჰოსტისთვის \"%s\", მომხმარებელი \"%s\", ბაზა \"%s\", %s" -#: libpq/auth.c:506 +#: libpq/auth.c:495 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "კლიენტის IP მისამართი იხსნება \"%s\" პირდაპირი DNS ემთხვევა." -#: libpq/auth.c:509 +#: libpq/auth.c:498 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "კლიენტის IP მისამართი იხსნება \"%s\" პირდაპირი DNS არ შემოწმებულა." -#: libpq/auth.c:512 +#: libpq/auth.c:501 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "კლიენტის IP მისამართი იხსნება \"%s\" პირდაპირი DNS არ ემთხვევა." -#: libpq/auth.c:515 +#: libpq/auth.c:504 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "კლიენტის ჰოსტის სახელის (\"%s\") IP მისამართში თარგმნის შეცდომა: %s." -#: libpq/auth.c:520 +#: libpq/auth.c:509 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "კლიენტის IP მისამართიდან ჰოსტის სახელის ამოხსნის შეცდომა: %s." #. translator: last %s describes encryption state -#: libpq/auth.c:528 +#: libpq/auth.c:517 #, c-format msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf-ში ჩანაწერი რეპლიკაციის შეერთების შესახებ ჰოსტიდან \"%s\" მომხმარებელი \"%s\", %s აღმოჩენილი არაა" #. translator: last %s describes encryption state -#: libpq/auth.c:536 +#: libpq/auth.c:525 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf-ში ჩანაწერი ჰოსტისთვის \"%s\" მომხმარებელი \"%s\", ბაზა \"%s\", %s აღმოჩენილი არაა" -#: libpq/auth.c:656 +#: libpq/auth.c:649 #, c-format msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" msgstr "მიერთება ავთენტიფიცირებულია: მომხმარებელი =\"%s\" მეთოდი=%s (%s:%d)" -#: libpq/auth.c:725 +#: libpq/auth.c:718 #, c-format msgid "expected password response, got message type %d" msgstr "მოველოდი პაროლის პასუხს, მივიღე შეტყობინების ტიპი %d" -#: libpq/auth.c:746 +#: libpq/auth.c:739 #, c-format msgid "invalid password packet size" msgstr "პაროლის პაკეტის არასწორი ზომა" -#: libpq/auth.c:764 +#: libpq/auth.c:757 #, c-format msgid "empty password returned by client" msgstr "კლიენტმა ცარიელი პაროლი დააბრუნა" -#: libpq/auth.c:892 +#: libpq/auth.c:885 #, c-format msgid "could not generate random MD5 salt" msgstr "შემთხვევითი MD5 მარილის გენერაციის შეცდომა" -#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:936 libpq/be-secure-gssapi.c:543 #, c-format msgid "could not set environment: %m" msgstr "გარემოს მორგების შეცდომა: %m" -#: libpq/auth.c:982 +#: libpq/auth.c:975 #, c-format msgid "expected GSS response, got message type %d" msgstr "მოველოდი GSS პასუხს, მივიღე შეტყობინების ტიპი %d" -#: libpq/auth.c:1048 +#: libpq/auth.c:1041 msgid "accepting GSS security context failed" msgstr "'GSS'-ის უსაფრთხოების კონტექსტის მიღების შეცდომა" -#: libpq/auth.c:1089 +#: libpq/auth.c:1082 msgid "retrieving GSS user name failed" msgstr "'GSS'-ის მომხმარებლის სახელის მიღების შეცდომა" -#: libpq/auth.c:1235 +#: libpq/auth.c:1228 msgid "could not acquire SSPI credentials" msgstr "შეცდომა SSPI-ის მომხმ./პაროლის მიღებისას" -#: libpq/auth.c:1260 +#: libpq/auth.c:1253 #, c-format msgid "expected SSPI response, got message type %d" msgstr "მოველოდი SSPI პასუხს, მივიღე შეტყობინების ტიპი %d" -#: libpq/auth.c:1338 +#: libpq/auth.c:1331 msgid "could not accept SSPI security context" msgstr "'SSPI'-ის უსაფრთხოების კონტექსტის მიღების შეცდომა" -#: libpq/auth.c:1379 +#: libpq/auth.c:1372 msgid "could not get token from SSPI security context" msgstr "'SSPI'-ის უსაფრთხოების კონტექსტიდან კოდის მიღების შეცდომა" -#: libpq/auth.c:1515 libpq/auth.c:1534 +#: libpq/auth.c:1508 libpq/auth.c:1527 #, c-format msgid "could not translate name" msgstr "სახელის თარგმნა შეუძლებელია" -#: libpq/auth.c:1547 +#: libpq/auth.c:1540 #, c-format msgid "realm name too long" msgstr "რეალმის სახელი ძალიან გრძელია" -#: libpq/auth.c:1562 +#: libpq/auth.c:1555 #, c-format msgid "translated account name too long" msgstr "ანგარიშის ნათარგმნი სახელი ძალიან გრძელია" -#: libpq/auth.c:1741 +#: libpq/auth.c:1734 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "ident მიერთებისთვის სოკეტის შექმნა შეუძლებელია: %m" -#: libpq/auth.c:1756 +#: libpq/auth.c:1749 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "ლოკალურ მისამართზე \"%s\" მიბმის შეცდომა: %m" -#: libpq/auth.c:1768 +#: libpq/auth.c:1761 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "შეცდომა LDAP სერვერთან მიერთებისას. მისამართი - \"%s\",პორტი - %s: %m" -#: libpq/auth.c:1790 +#: libpq/auth.c:1783 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "შეცდომა LDAP სერვერზე მოთხოვნის გაგზავნისას. მისამართი - \"%s\", პორტი - %s: %m" -#: libpq/auth.c:1807 +#: libpq/auth.c:1800 #, c-format msgid "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "პასუხი Ident-ის სერვერიდან მისამართით \"%s\" პორტზე %s ვერ მივიღე: %m" -#: libpq/auth.c:1817 +#: libpq/auth.c:1810 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "არასწორად დაფორმატებული პასუხი Ident სერვერიდან: \"%s\"" -#: libpq/auth.c:1870 +#: libpq/auth.c:1866 #, c-format msgid "peer authentication is not supported on this platform" msgstr "ამ პლატფორმაზე პარტნიორის ავთენტიკაცია მხარდაჭერილი არაა" -#: libpq/auth.c:1874 +#: libpq/auth.c:1870 #, c-format msgid "could not get peer credentials: %m" msgstr "პარტნიორის ავტორიზაციის დეტალების მიღების შეცდომა: %m" +#: libpq/auth.c:1880 +#, c-format +msgid "could not look up local user ID %ld: %m" +msgstr "ლოკალური მომხმარებლის ID-ით %ld მოძებნა შეუძლებელია: %m" + #: libpq/auth.c:1886 #, c-format -msgid "could not look up local user ID %ld: %s" -msgstr "ლოკალური მომხმარებლის ID-ით %ld მოძებნა შეუძლებელია: %s" +msgid "local user with ID %ld does not exist" +msgstr "ლოკალური მომხმარებელი ID-ით %ld არ არსებობს" -#: libpq/auth.c:1988 +#: libpq/auth.c:1986 #, c-format msgid "error from underlying PAM layer: %s" msgstr "შეცდომა ქვედა PAM ფენიდან: %s" -#: libpq/auth.c:1999 +#: libpq/auth.c:1997 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "მხარდაუჭერელი PAM საუბარი %d/\"%s\"" -#: libpq/auth.c:2056 +#: libpq/auth.c:2054 #, c-format msgid "could not create PAM authenticator: %s" msgstr "შეცდომა PAM ავთენტიკატორის შექმნისას: %s" -#: libpq/auth.c:2067 +#: libpq/auth.c:2065 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "pam_set_item(PAM_USER) -ის შეცდომა: %s" -#: libpq/auth.c:2099 +#: libpq/auth.c:2097 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "pam_set_item(PAM_RHOST) -ის შეცდომა: %s" -#: libpq/auth.c:2111 +#: libpq/auth.c:2109 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "pam_set_item(PAM_CONV) -ის შეცდომა: %s" -#: libpq/auth.c:2124 +#: libpq/auth.c:2122 #, c-format msgid "pam_authenticate failed: %s" msgstr "pam_authenticate -ის შეცდომა: %s" -#: libpq/auth.c:2137 +#: libpq/auth.c:2135 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "pam_acct_mgmt-ის შეცდომა: %s" -#: libpq/auth.c:2148 +#: libpq/auth.c:2146 #, c-format msgid "could not release PAM authenticator: %s" msgstr "შეცდომა PAM ავთენტიკატორის მოხსნისას: %s" -#: libpq/auth.c:2228 +#: libpq/auth.c:2226 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "შეცდომა LDAP-ის ინიციალიზაციისას: შეცდომის კოდი %d" -#: libpq/auth.c:2265 +#: libpq/auth.c:2263 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "ldapbasedn-დან დომენის სახელის გამოღება შეუძლებელია" -#: libpq/auth.c:2273 +#: libpq/auth.c:2271 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "LDAP ავთენტიკაციამ \"%s\"-სთვის DNS SRV ჩანაწერები ვერ იპოვა" -#: libpq/auth.c:2275 +#: libpq/auth.c:2273 #, c-format msgid "Set an LDAP server name explicitly." msgstr "LDAP სერვერის სახელი აშკარად უნდა დააყენოთ." -#: libpq/auth.c:2327 +#: libpq/auth.c:2325 #, c-format msgid "could not initialize LDAP: %s" msgstr "\"LDAP\"-ის ინიციალიზაციის შეცდომა: %s" -#: libpq/auth.c:2337 +#: libpq/auth.c:2335 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "ამ LDAP ბიბლიოთეკას ldaps-ის მხარდაჭერა არ გააჩნია" -#: libpq/auth.c:2345 +#: libpq/auth.c:2343 #, c-format msgid "could not initialize LDAP: %m" msgstr "\"LDAP\"-ის ინიციალიზაციის შეცდომა: %m" -#: libpq/auth.c:2355 +#: libpq/auth.c:2353 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "\"LDAP\"-ის ვერსიის დაყენების შეცდომა: %s" -#: libpq/auth.c:2371 +#: libpq/auth.c:2369 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "\"LDAP TLS\" სესიის დაწყების შეცდომა: %s" -#: libpq/auth.c:2448 +#: libpq/auth.c:2446 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "LDAP სერვერი და ldapbasedn მითითებული არაა" -#: libpq/auth.c:2455 +#: libpq/auth.c:2453 #, c-format msgid "LDAP server not specified" msgstr "LDAP სერვერი მითითებული არაა" -#: libpq/auth.c:2517 +#: libpq/auth.c:2515 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "არასწორი სიმბოლო მომხმარებლის სახელში LDAP-ით ავთენტიკაციისას" -#: libpq/auth.c:2534 +#: libpq/auth.c:2532 #, c-format msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s" msgstr "ldapbinddn \"%s\"-სთვის სერვერზე \"%s\" საწყისი LDAP მიბმა ვერ განვახორციელე: %s" -#: libpq/auth.c:2564 +#: libpq/auth.c:2562 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "ფილტრისთვის \"%s\" სერვერზე \"%s\" LDAP ძებნის გაშვება შეუძლებელია: %s" -#: libpq/auth.c:2580 +#: libpq/auth.c:2578 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "LDAP-ის მომხმარებელი \"%s\" არ არსებობს" -#: libpq/auth.c:2581 +#: libpq/auth.c:2579 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "LDAP ძებნამ ფილტრისთვის \"%s\" სერვერზე \"%s\" ჩანაწერები არ დააბრუნა." -#: libpq/auth.c:2585 +#: libpq/auth.c:2583 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "LDAP-ის მომხმარებელი \"%s\" უნიკალური არაა" -#: libpq/auth.c:2586 +#: libpq/auth.c:2584 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries." msgstr[0] "LDAP ძებნამ ფილტრისთვის \"%s\" სერვერზე \"%s\" %d ჩანაწერი დააბრუნა." msgstr[1] "LDAP ძებნამ ფილტრისთვის \"%s\" სერვერზე \"%s\" %d ჩანაწერი დააბრუნა." -#: libpq/auth.c:2606 +#: libpq/auth.c:2604 #, c-format msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" msgstr "" -#: libpq/auth.c:2633 +#: libpq/auth.c:2631 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "LDAP-ით შესვლის შეცდომა მომხმარებლისთვის \"%s\" სერვერზე \"%s\": %s" -#: libpq/auth.c:2665 +#: libpq/auth.c:2663 #, c-format msgid "LDAP diagnostics: %s" msgstr "LDAP-ის დიაგნოსტიკა: %s" -#: libpq/auth.c:2703 +#: libpq/auth.c:2701 #, c-format msgid "certificate authentication failed for user \"%s\": client certificate contains no user name" msgstr "სერტიფიკატით ავთენტიკაციის შეცდომა მომხმარებლისთვის \"%s\": კლიენტის სერტიფიკატი მომხმარებლის სახელს არ შეიცავს" -#: libpq/auth.c:2724 +#: libpq/auth.c:2722 #, c-format msgid "certificate authentication failed for user \"%s\": unable to retrieve subject DN" msgstr "სერტიფიკატით ავთენტიკაცია ჩავარდა მომხმარებლისთვის \"%s\": სათაურის DN-ის მიღება შეუძლებელა" -#: libpq/auth.c:2747 +#: libpq/auth.c:2745 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch" msgstr "სერტიფიკატის გადამოწმების (clientcert=verify-full) შეცდომა მომხმარებლისთვის \"%s\": DN არ ემთხვევა" -#: libpq/auth.c:2752 +#: libpq/auth.c:2750 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch" msgstr "სერტიფიკატის გადამოწმების (clientcert=verify-full) შეცდომა მომხმარებლისთვის \"%s\": CN არ ემთხვევა" -#: libpq/auth.c:2854 +#: libpq/auth.c:2852 #, c-format msgid "RADIUS server not specified" msgstr "RADIUS სერვერი მითითებული არაა" -#: libpq/auth.c:2861 +#: libpq/auth.c:2859 #, c-format msgid "RADIUS secret not specified" msgstr "RADIUS-ის პაროლი მითითებული არაა" -#: libpq/auth.c:2875 +#: libpq/auth.c:2873 #, c-format msgid "RADIUS authentication does not support passwords longer than %d characters" msgstr "RADIUS-ით ავთენტიკაციისას %d სიმბოლოზე გრძელი პაროლები მხარდაჭერილი არაა" -#: libpq/auth.c:2977 libpq/hba.c:2352 +#: libpq/auth.c:2975 libpq/hba.c:2391 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "შეცდომა RADIUS სერვერის სახელის \"%s\" მისამართში თარგმნისას: %s" -#: libpq/auth.c:2991 +#: libpq/auth.c:2989 #, c-format msgid "could not generate random encryption vector" msgstr "შემთხვევითი დაშიფვრის ვექტორის გენერაციის შეცდომა" -#: libpq/auth.c:3028 +#: libpq/auth.c:3026 #, c-format msgid "could not perform MD5 encryption of password: %s" msgstr "პაროლის MD5-ით დაშიფვრა შეუძლებელია: %s" -#: libpq/auth.c:3055 +#: libpq/auth.c:3053 #, c-format msgid "could not create RADIUS socket: %m" msgstr "შეცდომა RADIUS სოკეტის შექმნისას: %m" -#: libpq/auth.c:3071 +#: libpq/auth.c:3069 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "ლოკალურ RADIUS სოკეტზე მიბმის შეცდომა: %m" -#: libpq/auth.c:3081 +#: libpq/auth.c:3079 #, c-format msgid "could not send RADIUS packet: %m" msgstr "შეცდომა RADIUS პაკეტის გაგზავნისას: %m" -#: libpq/auth.c:3115 libpq/auth.c:3141 +#: libpq/auth.c:3113 libpq/auth.c:3139 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "%s-დან RADIUS პასუხის მოლოდინის ვადა ამოიწურა" -#: libpq/auth.c:3134 +#: libpq/auth.c:3132 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "შეცდომა RADIUS სოკეტის სტატუსის შემოწმებისას: %m" -#: libpq/auth.c:3164 +#: libpq/auth.c:3162 #, c-format msgid "could not read RADIUS response: %m" msgstr "შეცდომა RADIUS პასუხის წაკითხვისას: %m" -#: libpq/auth.c:3172 +#: libpq/auth.c:3170 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "RADIUS პასუხი \"%s\" გამოგზავნილია არასწორი პორტიდან: %d" -#: libpq/auth.c:3180 +#: libpq/auth.c:3178 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "RADIUS პასუხი %s-დან მეტისმეტად მოკლეა: %d" -#: libpq/auth.c:3187 +#: libpq/auth.c:3185 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "RADIUS პასუხს %s-დან დაზიანებული სიგრძე გააჩნია: %d (რეალური სიგრძე %d)" -#: libpq/auth.c:3195 +#: libpq/auth.c:3193 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "RADIUS პასუხი %s-დან სხვა მოთხოვნას ეკუთვნის: %d (უნდა იყოს %d)" @@ -15087,7 +15504,7 @@ msgstr "%s-დან მიღებული RADIUS პასუხის MD5 msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "%s-დან მიღებულ RADIUS-ს პასუხს არასწორი კოდი (%d) გააჩნია მომხმარებლისთვის \"%s\"" -#: libpq/be-fsstubs.c:133 libpq/be-fsstubs.c:162 libpq/be-fsstubs.c:190 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:241 libpq/be-fsstubs.c:283 libpq/be-fsstubs.c:306 libpq/be-fsstubs.c:560 +#: libpq/be-fsstubs.c:133 libpq/be-fsstubs.c:162 libpq/be-fsstubs.c:190 libpq/be-fsstubs.c:216 libpq/be-fsstubs.c:241 libpq/be-fsstubs.c:283 libpq/be-fsstubs.c:306 libpq/be-fsstubs.c:565 #, c-format msgid "invalid large-object descriptor: %d" msgstr "დიდი ობიექტის არასწორი დესკრიპტორი: %d" @@ -15097,7 +15514,7 @@ msgstr "დიდი ობიექტის არასწორი დეს msgid "large object descriptor %d was not opened for reading" msgstr "დიდი ობიექტის დესკრიპტორი %d წაკითხვისთვის არ გახსნილა" -#: libpq/be-fsstubs.c:197 libpq/be-fsstubs.c:567 +#: libpq/be-fsstubs.c:197 libpq/be-fsstubs.c:572 #, c-format msgid "large object descriptor %d was not opened for writing" msgstr "დიდი ობიექტის დესკრიპტორი %d ჩაწერისთვის არ გახსნილა" @@ -15112,32 +15529,32 @@ msgstr "lo_lseek-ის შედეგი დიაპაზონს გარ msgid "lo_tell result out of range for large-object descriptor %d" msgstr "lo_tell-ის შედეგი დიაპაზონს გარეთაა დიდი-ობიექტის დესკრიპტორისთვის %d" -#: libpq/be-fsstubs.c:439 +#: libpq/be-fsstubs.c:444 #, c-format msgid "could not open server file \"%s\": %m" msgstr "სერვერის ფაილის (\"%s\") გახსნის შეცდომა: %m" -#: libpq/be-fsstubs.c:462 +#: libpq/be-fsstubs.c:467 #, c-format msgid "could not read server file \"%s\": %m" msgstr "სერვერის ფაილის (\"%s\") წაკითხვის შეცდომა: %m" -#: libpq/be-fsstubs.c:521 +#: libpq/be-fsstubs.c:526 #, c-format msgid "could not create server file \"%s\": %m" msgstr "სერვერის ფაილის (\"%s\") შექმნის შეცდომა: %m" -#: libpq/be-fsstubs.c:533 +#: libpq/be-fsstubs.c:538 #, c-format msgid "could not write server file \"%s\": %m" msgstr "სერვერის ფაილში (\"%s\") ჩაწერის შეცდომა: %m" -#: libpq/be-fsstubs.c:774 +#: libpq/be-fsstubs.c:779 #, c-format msgid "large object read request is too large" msgstr "დიდი ობიექტის წაკითხვის მოთხოვნა მეტისმეტად დიდია" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 +#: libpq/be-fsstubs.c:821 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "მოთხოვნილი სიგრძე არ შეიძლება, უარყოფითი იყოს" @@ -15172,803 +15589,838 @@ msgstr "პირადი გასაღების ფაილზე \"%s\" msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root." msgstr "ფაილებს u=rw (0600) ან ნაკლები წვდომები უნდა ჰქონდეს, თუ მათი მფლობელი ბაზის მომხმარებელია, ან წვდომები u=rw,g=r (0640), თუ მფლობელი root-ია." -#: libpq/be-secure-gssapi.c:201 +#: libpq/be-secure-gssapi.c:202 msgid "GSSAPI wrap error" msgstr "GSSAPI -ის გადატანის შეცდომა" -#: libpq/be-secure-gssapi.c:208 +#: libpq/be-secure-gssapi.c:209 #, c-format msgid "outgoing GSSAPI message would not use confidentiality" msgstr "გამავალი GSSAPI შეტყობინება კონფიდენციალობას ვერ იყენებს" -#: libpq/be-secure-gssapi.c:215 libpq/be-secure-gssapi.c:634 +#: libpq/be-secure-gssapi.c:216 libpq/be-secure-gssapi.c:637 #, c-format msgid "server tried to send oversize GSSAPI packet (%zu > %zu)" msgstr "სერვერმა ძალიან დიდი GSSAPI პაკეტის გამოგზავნა სცადა (%zu > %zu)" -#: libpq/be-secure-gssapi.c:351 +#: libpq/be-secure-gssapi.c:352 #, c-format msgid "oversize GSSAPI packet sent by the client (%zu > %zu)" msgstr "კლიენტის მიერ გამოგზავნილი GSSAPI-ის პაკეტი ძალიან დიდია (%zu > %zu)" -#: libpq/be-secure-gssapi.c:389 +#: libpq/be-secure-gssapi.c:390 msgid "GSSAPI unwrap error" msgstr "GSSAPI-ის გადატანის მოხსნის შეცდომა" -#: libpq/be-secure-gssapi.c:396 +#: libpq/be-secure-gssapi.c:397 #, c-format msgid "incoming GSSAPI message did not use confidentiality" msgstr "შემომავალი GSSAPI შეტყობინება კონფიდენციალობას ვერ იყენებს" -#: libpq/be-secure-gssapi.c:575 +#: libpq/be-secure-gssapi.c:578 #, c-format msgid "oversize GSSAPI packet sent by the client (%zu > %d)" msgstr "კლიენტის მიერ გამოგზავნილი GSSAPI-ის პაკეტი ძალიან დიდია (%zu > %d)" -#: libpq/be-secure-gssapi.c:600 +#: libpq/be-secure-gssapi.c:603 msgid "could not accept GSSAPI security context" msgstr "\"GSSAPI\"-ის უსაფრთხოების კონტექსტის მიღების შეცდომა" -#: libpq/be-secure-gssapi.c:701 +#: libpq/be-secure-gssapi.c:704 msgid "GSSAPI size check error" msgstr "GSSAPI-ის ზომის შემოწმების შეცდომა" -#: libpq/be-secure-openssl.c:131 +#: libpq/be-secure-openssl.c:118 #, c-format msgid "could not create SSL context: %s" msgstr "შეცდომა SSL კონტექსტის შექმნისას: %s" -#: libpq/be-secure-openssl.c:157 +#: libpq/be-secure-openssl.c:144 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "სერვერის სერტიფიკატის ფაილის ჩატვირთვის შეცდომა \"%s\": %s" -#: libpq/be-secure-openssl.c:177 +#: libpq/be-secure-openssl.c:164 #, c-format msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "პირადი გასაღების ფაილის \"%s\" თავიდან ჩატვირთვა შეუძლებელია, რადგან მას საკვანძო ფრაზა ესაჭიროება" -#: libpq/be-secure-openssl.c:182 +#: libpq/be-secure-openssl.c:169 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "პირადი გასაღების ფაილის \"%s\" ჩატვირთვის შეცდომა: %s" -#: libpq/be-secure-openssl.c:191 +#: libpq/be-secure-openssl.c:178 #, c-format msgid "check of private key failed: %s" msgstr "პირადი გასაღების ფაილის შემოწმების შეცდომა: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 +#: libpq/be-secure-openssl.c:191 libpq/be-secure-openssl.c:214 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "\"%s\"-ის პარამეტრი \"%s\" ამ პროგრამის აგებისას ჩართული არ იყო" -#: libpq/be-secure-openssl.c:214 +#: libpq/be-secure-openssl.c:201 #, c-format msgid "could not set minimum SSL protocol version" msgstr "'SSL' პროტოკოლის ვერსიის მინიმალური მნიშვნელობის დაყენების შეცდომა" -#: libpq/be-secure-openssl.c:237 +#: libpq/be-secure-openssl.c:224 #, c-format msgid "could not set maximum SSL protocol version" msgstr "'SSL' პროტოკოლის ვერსიის მაქსიმალური მნიშვნელობის დაყენების შეცდომა" -#: libpq/be-secure-openssl.c:253 +#: libpq/be-secure-openssl.c:241 #, c-format msgid "could not set SSL protocol version range" msgstr "'SSL' პროტოკოლის ვერსიის დიაპაზონის დაყენების შეცდომა" -#: libpq/be-secure-openssl.c:254 +#: libpq/be-secure-openssl.c:242 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "\"%s\"-ი \"%s\"-ზე მაღალი ვერ იქნება" -#: libpq/be-secure-openssl.c:296 +#: libpq/be-secure-openssl.c:295 +#, c-format +msgid "could not set the TLSv1.2 cipher list (no valid ciphers available)" +msgstr "ვერ დავაყენე TLSv1.2-ის შიფრების სია (სწორი შიფრები ხელმისაწვდომი არაა)" + +#: libpq/be-secure-openssl.c:310 #, c-format -msgid "could not set the cipher list (no valid ciphers available)" -msgstr "შიფრების სიის დაყენება შეუძლებელია (სწორი შიფრები ხელმისაწვდომი არაა)" +msgid "could not set the TLSv1.3 cipher suites (no valid ciphers available)" +msgstr "ვერ დავაყენე TLSv1.3-ის შიფრების სია (სწორი შიფრები ხელმისაწვდომი არაა)" -#: libpq/be-secure-openssl.c:316 +#: libpq/be-secure-openssl.c:331 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "root სერტიფიკატის ფაილის (\"%s\") წაკითხვის შეცდომა: %s" -#: libpq/be-secure-openssl.c:365 +#: libpq/be-secure-openssl.c:380 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "" -#: libpq/be-secure-openssl.c:373 +#: libpq/be-secure-openssl.c:388 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "" -#: libpq/be-secure-openssl.c:381 +#: libpq/be-secure-openssl.c:396 #, c-format msgid "could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s" msgstr "" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:454 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "" -#: libpq/be-secure-openssl.c:453 +#: libpq/be-secure-openssl.c:468 #, c-format msgid "could not initialize SSL connection: %s" msgstr "\"SSL\" შეერთების ინიციალიზაციის შეცდომა: %s" -#: libpq/be-secure-openssl.c:461 +#: libpq/be-secure-openssl.c:476 #, c-format msgid "could not set SSL socket: %s" msgstr "\"SSL\" სოკეტის დაყენების შეცდომა: %s" -#: libpq/be-secure-openssl.c:517 +#: libpq/be-secure-openssl.c:532 #, c-format msgid "could not accept SSL connection: %m" msgstr "'SSL' შეერთების მიღების შეცდომა: %m" -#: libpq/be-secure-openssl.c:521 libpq/be-secure-openssl.c:578 +#: libpq/be-secure-openssl.c:536 libpq/be-secure-openssl.c:593 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "'SSL' შეერთების მიღების შეცდომა: აღმოჩენილია EOF" -#: libpq/be-secure-openssl.c:562 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "could not accept SSL connection: %s" msgstr "'SSL' შეერთების მიღების შეცდომა: %s" -#: libpq/be-secure-openssl.c:566 +#: libpq/be-secure-openssl.c:581 #, c-format msgid "This may indicate that the client does not support any SSL protocol version between %s and %s." msgstr "" -#: libpq/be-secure-openssl.c:583 libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:868 +#: libpq/be-secure-openssl.c:598 libpq/be-secure-openssl.c:813 libpq/be-secure-openssl.c:883 #, c-format msgid "unrecognized SSL error code: %d" msgstr "უცნობი SSL-ის შეცდომის კოდი: %d" -#: libpq/be-secure-openssl.c:611 +#: libpq/be-secure-openssl.c:626 #, c-format msgid "received SSL connection request with unexpected ALPN protocol" msgstr "" -#: libpq/be-secure-openssl.c:655 +#: libpq/be-secure-openssl.c:670 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "SSL სერტიფიკატის საერთო სახელი ჩადგმულ ნულოვანს შეიცავს" -#: libpq/be-secure-openssl.c:701 +#: libpq/be-secure-openssl.c:716 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "SSL სერტიფიკატის გამორჩეული სახელი ჩადგმულ ნულოვანს შეიცავს" -#: libpq/be-secure-openssl.c:787 libpq/be-secure-openssl.c:852 +#: libpq/be-secure-openssl.c:802 libpq/be-secure-openssl.c:867 #, c-format msgid "SSL error: %s" msgstr "SSL-ის შეცდომა: %s" -#: libpq/be-secure-openssl.c:1027 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "dh პარამეტრების ფაილის (\"%s\") გახსნის შეცდომა: %m" -#: libpq/be-secure-openssl.c:1039 +#: libpq/be-secure-openssl.c:1062 #, c-format msgid "could not load DH parameters file: %s" msgstr "dh პარამეტრების ფაილის ჩატვირთვის შეცდომა: %s" -#: libpq/be-secure-openssl.c:1049 +#: libpq/be-secure-openssl.c:1072 #, c-format msgid "invalid DH parameters: %s" msgstr "არასწორი DH-ის პარამეტრები: %s" -#: libpq/be-secure-openssl.c:1058 +#: libpq/be-secure-openssl.c:1081 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "არასწორი DH-ის პარამეტრები: p მარტივი რიცხვი არაა" -#: libpq/be-secure-openssl.c:1067 +#: libpq/be-secure-openssl.c:1090 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "" -#: libpq/be-secure-openssl.c:1203 +#: libpq/be-secure-openssl.c:1226 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "კლიენტის სერტიფიკატის გადამოწმების შეცდომა სიღრმეზე %d: %s." -#: libpq/be-secure-openssl.c:1240 +#: libpq/be-secure-openssl.c:1263 #, c-format msgid "Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"." msgstr "შეცდომის მქონე სერტიფიკატის მონაცემების (გადაუმოწმებელი): სათაური \"%s\", სერიული ნომერი %s, გამომცემელი \"%s\"." -#: libpq/be-secure-openssl.c:1241 +#: libpq/be-secure-openssl.c:1264 msgid "unknown" msgstr "უცნობი" -#: libpq/be-secure-openssl.c:1378 +#: libpq/be-secure-openssl.c:1401 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: DH-ის პარამეტრების ჩატვირთვის შეცდომა" -#: libpq/be-secure-openssl.c:1386 +#: libpq/be-secure-openssl.c:1409 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: DH-ის პარამეტრების დაყენების შეცდომა: %s" -#: libpq/be-secure-openssl.c:1413 +#: libpq/be-secure-openssl.c:1439 #, c-format -msgid "ECDH: unrecognized curve name: %s" -msgstr "ECDH: მრუდის უცნობი სახელი: %s" +msgid "failed to set group names specified in ssl_groups: %s" +msgstr "" -#: libpq/be-secure-openssl.c:1422 +#: libpq/be-secure-openssl.c:1441 +msgid "No valid groups found" +msgstr "სწორი ჯგუფები აღმოჩენილი არაა" + +#: libpq/be-secure-openssl.c:1442 #, c-format -msgid "ECDH: could not create key" -msgstr "ECDH: გასაღების შექნის შეცდომა" +msgid "Ensure that each group name is spelled correctly and supported by the installed version of OpenSSL" +msgstr "დარწმუნდით, რომ თითოეული ჯგუფის სახელის მართლწერა სწორია და მხარდაჭერილია OpenSSL-ის დაყენებული ვერსიის მიერ" -#: libpq/be-secure-openssl.c:1450 +#: libpq/be-secure-openssl.c:1488 msgid "no SSL error reported" msgstr "შეცდომა SSL-ში არ დაფიქსირებულა" -#: libpq/be-secure-openssl.c:1467 +#: libpq/be-secure-openssl.c:1506 #, c-format msgid "SSL error code %lu" msgstr "SSL-ის შეცდომის კოდი %lu" -#: libpq/be-secure-openssl.c:1624 +#: libpq/be-secure-openssl.c:1663 #, c-format msgid "could not create BIO" msgstr "\"BIO\"-ს შექმნის შეცდომა" -#: libpq/be-secure-openssl.c:1634 +#: libpq/be-secure-openssl.c:1673 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "'ASN1_OBJECT' ტიპის ობიექტისთვის NID-ის მიღება შეუძლებელია" -#: libpq/be-secure-openssl.c:1642 +#: libpq/be-secure-openssl.c:1681 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "'NID %d'-ის ASN1_OBJECT ტიპის სტრუქტურად გარდაქნა შეუძლებელია" -#: libpq/crypt.c:48 +#: libpq/crypt.c:50 #, c-format msgid "Role \"%s\" does not exist." msgstr "როლი არ არსებობს: \"%s\"." -#: libpq/crypt.c:58 +#: libpq/crypt.c:60 #, c-format msgid "User \"%s\" has no password assigned." msgstr "მომხმარებელს პაროლი მინიჭებული არ აქვს: %s." -#: libpq/crypt.c:76 +#: libpq/crypt.c:78 #, c-format msgid "User \"%s\" has an expired password." msgstr "მომხმარებლის პაროლის ვადა გასულია: %s." -#: libpq/crypt.c:182 +#: libpq/crypt.c:174 +#, c-format +msgid "encrypted password is too long" +msgstr "დაშიფრული პაროლი მეტისმეტად გრძელია" + +#: libpq/crypt.c:175 +#, c-format +msgid "Encrypted passwords must be no longer than %d bytes." +msgstr "დაშიფრული ბაიტები %d ბაიტზე დიდი არ უნდა იყოს." + +#: libpq/crypt.c:183 +#, c-format +msgid "setting an MD5-encrypted password" +msgstr "მიმდინარეობს MD5-ით დაშიფრული პაროლის დაყენება" + +#: libpq/crypt.c:184 +#, c-format +msgid "MD5 password support is deprecated and will be removed in a future release of PostgreSQL." +msgstr "" + +#: libpq/crypt.c:185 +#, c-format +msgid "Refer to the PostgreSQL documentation for details about migrating to another password type." +msgstr "" + +#: libpq/crypt.c:216 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "მომხმარებლის (\"%s\") პაროლის გამოყენება MD5-ით ავთენტიკაციისთვის შეუძლებელია." -#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 +#: libpq/crypt.c:237 libpq/crypt.c:279 libpq/crypt.c:299 #, c-format msgid "Password does not match for user \"%s\"." msgstr "პაროლი არ ემთხვევა მომხმარებელს \"%s." -#: libpq/crypt.c:284 +#: libpq/crypt.c:318 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "მომხმარებლის (\"%s\") პაროლის უცნობი ფორმატი." -#: libpq/hba.c:327 +#: libpq/hba.c:329 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "არასწორი რეგულარული გამოსახულება (%s): %s" -#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 -#: libpq/hba.c:1799 libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 tsearch/ts_locale.c:241 -#, c-format -msgid "line %d of configuration file \"%s\"" -msgstr "კონფიგურაციის ფაილის \"%2$s\" ხაზზე %1$d" - -#: libpq/hba.c:457 +#: libpq/hba.c:459 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "ნაკლული ავთენტიკაციის ფაილის გამოტოვება \"%s\"" -#: libpq/hba.c:609 +#: libpq/hba.c:611 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "ფაილის (\"%s\") გახსნა შეუძლებელია: გადაცილებულია ჩალაგების სიღრმე" -#: libpq/hba.c:1216 +#: libpq/hba.c:1222 #, c-format msgid "error enumerating network interfaces: %m" msgstr "ქსელის ინტერფეისების ჩამონათვალის მიღების შეცდომა: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1243 +#: libpq/hba.c:1249 #, c-format msgid "authentication option \"%s\" is only valid for authentication methods %s" msgstr "ავთენტიკაციის პარამეტრი \"%s\" მხოლოდ ავთენტიკაციის მეთოდებისთვის %s შეგიძლიათ, გამოიყენოთ" -#: libpq/hba.c:1263 +#: libpq/hba.c:1269 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "ავთენტიკაციის მეთოდს \"%s\" არგუმენტის (\"%s\") დაყენება სჭირდება" -#: libpq/hba.c:1287 +#: libpq/hba.c:1293 #, c-format msgid "missing entry at end of line" msgstr "ხაზის ბოლოში ჩანაწერი აღმოჩენილი არაა" -#: libpq/hba.c:1300 +#: libpq/hba.c:1306 #, c-format msgid "multiple values in ident field" msgstr "ერთზე მეტი მნიშვნელობა ველში ident" -#: libpq/hba.c:1352 +#: libpq/hba.c:1358 #, c-format msgid "multiple values specified for connection type" msgstr "მიერთების ტიპში მითითებულია ერთზე მეტი მნიშვნელობა" -#: libpq/hba.c:1353 +#: libpq/hba.c:1359 #, c-format msgid "Specify exactly one connection type per line." msgstr "ერთ ხაზზე ზუსტად ერთი მიერთების ტიპი უნდა მიუთითოთ." -#: libpq/hba.c:1380 +#: libpq/hba.c:1386 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "hostssl-ის ჩანაწერის დამთხვევა შეუძლებელია, რადგან SSL გათიშულია" -#: libpq/hba.c:1381 +#: libpq/hba.c:1387 #, c-format msgid "Set \"ssl = on\" in postgresql.conf." msgstr "დააყენეთ \"ssl = on\" postgresql.conf-ში." -#: libpq/hba.c:1389 +#: libpq/hba.c:1395 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "hostssl-ის ჩანაწერის დამთხვევა შეუძლებელია, რადგან SSL-ის მხარდაჭერა ამ აგებისას ჩართული არ იყო" -#: libpq/hba.c:1401 +#: libpq/hba.c:1407 #, c-format msgid "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "hostgssenc-ის ჩანაწერის დამთხვევა შეუძლებელია, რადგან GSSAPI -ის მხარდაჭერა ამ აგებისას ჩართული არ იყო" -#: libpq/hba.c:1421 +#: libpq/hba.c:1427 #, c-format msgid "invalid connection type \"%s\"" msgstr "შეერთების არასწორი ტიპი: %s" -#: libpq/hba.c:1435 +#: libpq/hba.c:1441 #, c-format msgid "end-of-line before database specification" msgstr "ხაზის-დასასრული ბაზის მითითებამდე" -#: libpq/hba.c:1460 +#: libpq/hba.c:1466 #, c-format msgid "end-of-line before role specification" msgstr "ხაზის-დასასრული როლის მითითებამდე" -#: libpq/hba.c:1487 +#: libpq/hba.c:1493 #, c-format msgid "end-of-line before IP address specification" msgstr "ხაზის-დასასრული IP მისამართის მითითებამდე" -#: libpq/hba.c:1498 +#: libpq/hba.c:1504 #, c-format msgid "multiple values specified for host address" msgstr "მითითებულია ჰოსტის მისამართის ერთზე მეტი მნიშვნელობა" -#: libpq/hba.c:1499 +#: libpq/hba.c:1505 #, c-format msgid "Specify one address range per line." msgstr "ერთ ხაზზე ერთი მისამართების დიაპაზონი მიუთითეთ." -#: libpq/hba.c:1557 +#: libpq/hba.c:1563 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "არასწორი IP მისამართი \"%s\": %s" -#: libpq/hba.c:1577 +#: libpq/hba.c:1583 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "ორივეს, ჰოსტის სახელის და CIDR-ის ნიღბის მითითება არასწორია: \"%s\"" -#: libpq/hba.c:1591 +#: libpq/hba.c:1597 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "არასწორი CIDR ნიღაბი მისამართში \"%s\"" -#: libpq/hba.c:1611 +#: libpq/hba.c:1617 #, c-format msgid "end-of-line before netmask specification" msgstr "ხაზის-დასასრული ქსელური ნიღბის მითითებამდე" -#: libpq/hba.c:1612 +#: libpq/hba.c:1618 #, c-format msgid "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "" -#: libpq/hba.c:1623 +#: libpq/hba.c:1629 #, c-format msgid "multiple values specified for netmask" msgstr "მითითებულია ქსელის ნიღბის ერთზე მეტი მნიშვნელობა" -#: libpq/hba.c:1637 +#: libpq/hba.c:1643 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "არასწორი IP ნიღაბი \"%s\": %s" -#: libpq/hba.c:1657 +#: libpq/hba.c:1663 #, c-format msgid "IP address and mask do not match" msgstr "IP მისამართი და ნიღაბი არ ემთხვევა" -#: libpq/hba.c:1673 +#: libpq/hba.c:1679 #, c-format msgid "end-of-line before authentication method" msgstr "ხაზის-დასასრული ავთენტიკაციის მეთოდამდე" -#: libpq/hba.c:1684 +#: libpq/hba.c:1690 #, c-format msgid "multiple values specified for authentication type" msgstr "ავთენტიკაციის ტიპში მითითებულია ერთზე მეტი მნიშვნელობა" -#: libpq/hba.c:1685 +#: libpq/hba.c:1691 #, c-format msgid "Specify exactly one authentication type per line." msgstr "ერთ ხაზზე ზუსტად ერთი ავთენტიკაციის ტიპი უნდა მიუთითოთ." -#: libpq/hba.c:1750 +#: libpq/hba.c:1758 #, c-format msgid "invalid authentication method \"%s\"" msgstr "არასწორი ავთენტიკაციის მეთოდი \"%s\"" -#: libpq/hba.c:1763 +#: libpq/hba.c:1771 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "არასწორი ავთენტიკაციის მეთოდი \"%s\": მხარდაუჭერელია ამ ვერსიის მიერ" -#: libpq/hba.c:1786 +#: libpq/hba.c:1794 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "gssapi ავთენტიკაცია ლოკალურ სოკეტებზე მხარდაუჭერელია" -#: libpq/hba.c:1798 +#: libpq/hba.c:1806 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "პარტნიორის ავთენტიკაცია მხოლოდ ლოკალურ სოკეტებზეა მხარდაჭერილი" -#: libpq/hba.c:1816 +#: libpq/hba.c:1824 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "სერტიფიკატით ავთენტიკაცია მხოლოდ hostssl მიერთებებზეა მხარდაჭერილი" -#: libpq/hba.c:1866 +#: libpq/hba.c:1874 #, c-format msgid "authentication option not in name=value format: %s" msgstr "ავთენტიკაციის პარამეტრი სახელი=მნიშვნელობა ფორმატში არაა: %s" -#: libpq/hba.c:1910 +#: libpq/hba.c:1918 #, c-format -msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" -msgstr "ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, ან ldapurl-ის ldapprefix-სთან ერთად გამოყენება შეუძლებელია" +msgid "cannot mix options for simple bind and search+bind modes" +msgstr "" -#: libpq/hba.c:1921 +#: libpq/hba.c:1929 #, c-format msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "ავთენტიკაციის მეთოდს \"ldap\" არგუმენტების \"ldapbasedn\", \"ldapprefix\", ან \"ldapsuffix\" დაყენება სჭირდება" -#: libpq/hba.c:1937 +#: libpq/hba.c:1945 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "ldapsearchattribute-ს და ldapsearchfilter-ს ერთად ვერ გამოიყენებთ" -#: libpq/hba.c:1954 +#: libpq/hba.c:1962 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "'RADIUS' სერვერების სია არ შეიძლება, ცარიელი იყოს" -#: libpq/hba.c:1965 +#: libpq/hba.c:1973 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "'RADIUS' საიდუმლოების სია არ შეიძლება, ცარიელი იყოს" -#: libpq/hba.c:1982 +#: libpq/hba.c:1990 #, c-format msgid "the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "" -#: libpq/hba.c:1998 +#: libpq/hba.c:2006 #, c-format msgid "the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "" -#: libpq/hba.c:2014 +#: libpq/hba.c:2022 #, c-format msgid "the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "" -#: libpq/hba.c:2066 -msgid "ident, peer, gssapi, sspi, and cert" -msgstr "ident, peer, gssapi, sspi, და cert" +#. translator: strings are replaced with hba options +#: libpq/hba.c:2067 +#, c-format +msgid "%s cannot be used in combination with %s" +msgstr "%s-ს %s-სთან ერთად ვერ გამოიყენებთ" + +#: libpq/hba.c:2105 +msgid "ident, peer, gssapi, sspi, cert, and oauth" +msgstr "ident, peer, gssapi, sspi, cert და oauth" -#: libpq/hba.c:2075 +#: libpq/hba.c:2114 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert-ის მორგება მხოლოდ \"hostssl\" ხაზებისთვის შეგიძლიათ" -#: libpq/hba.c:2092 +#: libpq/hba.c:2131 #, c-format msgid "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "\"cert\" ტიპის ავთენტიკაციის გამოყენებისას clientcert-ს მხოლოდ \"verify-full\" შეგიძლიათ, მიუთითოთ" -#: libpq/hba.c:2105 +#: libpq/hba.c:2144 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "invalid value for clientcert: \"%s\"" -#: libpq/hba.c:2117 +#: libpq/hba.c:2156 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname-ის მორგება მხოლოდ \"hostssl\" ხაზებისთვის შეგიძლიათ" -#: libpq/hba.c:2136 +#: libpq/hba.c:2175 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "არასწორი მნიშვნელობა კლიენტის სახელისთვის: \"%s\"" -#: libpq/hba.c:2169 +#: libpq/hba.c:2208 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "\"LDAP URL\"-ის (%s) დამუშავების შეცდომა: %s" -#: libpq/hba.c:2180 +#: libpq/hba.c:2219 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "\"LDAP URL\"-ის მხარდაუჭერელი სქემა: %s" -#: libpq/hba.c:2204 +#: libpq/hba.c:2243 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "ამ პლატფორმაზე LDAP URL მხარდაჭერილი არაა" -#: libpq/hba.c:2222 +#: libpq/hba.c:2261 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "ldapscheme -ის არასწორი მნიშვნელობა: \"%s\"" -#: libpq/hba.c:2240 +#: libpq/hba.c:2279 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "\"LDAP\"-ის პორტის არასწორი ნომერი: %s" -#: libpq/hba.c:2286 libpq/hba.c:2293 +#: libpq/hba.c:2325 libpq/hba.c:2332 msgid "gssapi and sspi" msgstr "gssapi და sspi" -#: libpq/hba.c:2302 libpq/hba.c:2311 +#: libpq/hba.c:2341 libpq/hba.c:2350 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2333 +#: libpq/hba.c:2372 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "\"RADIUS\"-ის სერვერების სიის დამუშავება შეუძლებელია: %s" -#: libpq/hba.c:2381 +#: libpq/hba.c:2420 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "\"RADIUS\"-ის პორტების სიის დამუშავება შეუძლებელია: %s" -#: libpq/hba.c:2395 +#: libpq/hba.c:2434 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "\"RADIUS\"-ის არასწორი პორტი: \"%s\"" -#: libpq/hba.c:2417 +#: libpq/hba.c:2456 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "'RADIUS'-ის საიდუმლოების სიის დამუშავება შეუძლებელია: %s" -#: libpq/hba.c:2439 +#: libpq/hba.c:2478 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "'RADIUS'-ის იდენტიფიკატორების ჩამონათვალის \"%s\" დამუშავება შეუძლებელია" -#: libpq/hba.c:2453 +#: libpq/hba.c:2515 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "უცნობი ავთნტიკაციის პარამეტრის სახელი: \"%s\"" -#: libpq/hba.c:2645 +#: libpq/hba.c:2707 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "კონფიგურაციის ფაილი \"%s\" ჩანაწერებს არ შეიცავს" -#: libpq/hba.c:2798 +#: libpq/hba.c:2860 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "რეგულარული გამოსახულების დამთხვევა \"%s\"-სთვის ჩავარდა: %s" -#: libpq/hba.c:2822 +#: libpq/hba.c:2884 #, c-format msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"" msgstr "" -#: libpq/hba.c:2925 +#: libpq/hba.c:2987 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "" -#: libpq/hba.c:2945 +#: libpq/hba.c:3007 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "" -#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#: libpq/pqcomm.c:212 libpq/pqcomm.c:220 libpq/pqcomm.c:251 libpq/pqcomm.c:260 libpq/pqcomm.c:1652 libpq/pqcomm.c:1697 libpq/pqcomm.c:1737 libpq/pqcomm.c:1781 libpq/pqcomm.c:1820 libpq/pqcomm.c:1859 libpq/pqcomm.c:1895 libpq/pqcomm.c:1934 #, c-format msgid "%s(%s) failed: %m" msgstr "%s(%s)-ის შეცდომა: %m" -#: libpq/pqcomm.c:296 +#: libpq/pqcomm.c:297 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "სოკეტის არაბლოკირებული რეჟიმის დაყენების შეცდომა: %m" -#: libpq/pqcomm.c:456 +#: libpq/pqcomm.c:457 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Unix-დომენის სოკეტის მისამართი \"%s\" ძალიან გრძელია (დასაშვებია %d ბაიტი)" -#: libpq/pqcomm.c:476 +#: libpq/pqcomm.c:477 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "ჰოსტის სახელის \"%s\" და სერვისის სახელის \"%s\" მისამართში თარგმნა შეუძლებელია: %s" -#: libpq/pqcomm.c:480 +#: libpq/pqcomm.c:481 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "სერვისის \"%s\" მისამართში თარგმნა შეუძლებელია: %s" -#: libpq/pqcomm.c:502 +#: libpq/pqcomm.c:503 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "ყველა მოთხოვნილ მისამართზე მიმაგრება შეუძლებელია: MAXLISTEN (%d) გადაცილებულია" -#: libpq/pqcomm.c:511 +#: libpq/pqcomm.c:512 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:514 +#: libpq/pqcomm.c:515 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:517 +#: libpq/pqcomm.c:518 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:521 +#: libpq/pqcomm.c:522 #, c-format msgid "unrecognized address family %d" msgstr "მისამართის არასწორი ოჯახი %d" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:545 +#: libpq/pqcomm.c:546 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "%s სოკეტის შექმნის შეცდომა მისამართისთვის \"%s\": %m" -#. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 +#. translator: third %s is IPv4 or IPv6 +#. translator: third %s is IPv6 +#: libpq/pqcomm.c:575 libpq/pqcomm.c:593 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%s(%s)-ის შეცდომა %s-სთვის მისამართი \"%s\": %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:615 +#: libpq/pqcomm.c:616 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "%s მისამართზე \"%s\" მიბმის შეცდომა: %m" -#: libpq/pqcomm.c:619 +#: libpq/pqcomm.c:620 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "იქნებ პორტზე %d სხვა postmaster პროცესი უკვე უსმენს?" -#: libpq/pqcomm.c:621 +#: libpq/pqcomm.c:622 #, c-format msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry." msgstr "იქნებ პორტზე %d სხვა postmaster პროცესი უკვე უსმენს? თუ არა, დაიცადეთ რამდენიმე წამი და თავიდან სცადეთ." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:650 +#: libpq/pqcomm.c:651 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "%s მისამართზე \"%s\" მოსმენა შეუძლებელია: %m" -#: libpq/pqcomm.c:658 +#: libpq/pqcomm.c:659 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "ვუსმენ Unix სოკეტს \"%s\"" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:663 +#: libpq/pqcomm.c:664 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "ვუსმენ %s მისამართი \"%s\", პორტი %d" -#: libpq/pqcomm.c:753 +#: libpq/pqcomm.c:754 #, c-format msgid "group \"%s\" does not exist" msgstr "ჯგუფი \"%s\" არ არსებობს" -#: libpq/pqcomm.c:763 +#: libpq/pqcomm.c:764 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "ფაილის \"%s\" ჯგუფის დაყენება შეუძლებელია: %m" -#: libpq/pqcomm.c:774 +#: libpq/pqcomm.c:775 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "ფაილზე \"%s\" წვდომების დაყენების შეცდომა: %m" -#: libpq/pqcomm.c:803 +#: libpq/pqcomm.c:804 #, c-format msgid "could not accept new connection: %m" msgstr "ახალი მიერთების მიღება შეუძლებელია: %m" -#: libpq/pqcomm.c:885 +#: libpq/pqcomm.c:886 #, c-format msgid "there is no client connection" msgstr "კლიენტის მიერთება არ არსებობს" -#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 +#: libpq/pqcomm.c:942 libpq/pqcomm.c:1043 #, c-format msgid "could not receive data from client: %m" msgstr "კლიენტიდან მონაცემების მიღების შეცდომა: %m" -#: libpq/pqcomm.c:1149 tcop/postgres.c:4446 +#: libpq/pqcomm.c:1151 tcop/postgres.c:4505 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "მიერთება შეწყდება, რადგან პროტოკოლის სინქრონიზაცია დაიკარგა" -#: libpq/pqcomm.c:1215 +#: libpq/pqcomm.c:1217 #, c-format msgid "unexpected EOF within message length word" msgstr "მოულოდნელი EOF შეტყობინების სიგრძის სიტყვაში" -#: libpq/pqcomm.c:1225 +#: libpq/pqcomm.c:1227 #, c-format msgid "invalid message length" msgstr "შეტყობინების არასწორი სიგრძე" -#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 +#: libpq/pqcomm.c:1249 libpq/pqcomm.c:1262 #, c-format msgid "incomplete message from client" msgstr "კლიენტიდან მიღებული შეტყობინება დაუსრულებელია" -#: libpq/pqcomm.c:1401 +#: libpq/pqcomm.c:1405 #, c-format msgid "could not send data to client: %m" msgstr "კლიენტისთვის მონაცემების გაგზავნის შეცდომა: %m" -#: libpq/pqcomm.c:1616 +#: libpq/pqcomm.c:1620 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) -ის შეცდომა: შეცდომის კოდი %d" -#: libpq/pqcomm.c:1705 +#: libpq/pqcomm.c:1709 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "" -#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 +#: libpq/pqcomm.c:1793 libpq/pqcomm.c:1868 libpq/pqcomm.c:1943 #, c-format msgid "%s(%s) not supported" msgstr "%s (%s) მხარდაუჭერელია" @@ -15978,7 +16430,7 @@ msgstr "%s (%s) მხარდაუჭერელია" msgid "no data left in message" msgstr "შეტყობინებაში მონაცემები აღარ დარჩა" -#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 utils/adt/rowtypes.c:613 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 utils/adt/array_userfuncs.c:873 utils/adt/arrayfuncs.c:1481 utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "შეტყობინებაში დარჩენილი მონაცემები არასაკმარისია" @@ -15993,12 +16445,12 @@ msgstr "არასწორი სტრიქონი შეტყობი msgid "invalid message format" msgstr "არასწორი შეტყობინების ფორმატი" -#: main/main.c:234 +#: main/main.c:298 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: WSAStartup-ის შეცდომა: %d\n" -#: main/main.c:322 +#: main/main.c:386 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -16007,7 +16459,7 @@ msgstr "" "%s PostgreSQL სერვერია.\n" "\n" -#: main/main.c:323 +#: main/main.c:387 #, c-format msgid "" "Usage:\n" @@ -16019,107 +16471,107 @@ msgstr "" "\n" "\n" -#: main/main.c:324 +#: main/main.c:388 #, c-format msgid "Options:\n" msgstr "პარამეტრები:\n" -#: main/main.c:325 +#: main/main.c:389 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS გაზიარებული ბაფერების რაოდენობა\n" -#: main/main.c:326 +#: main/main.c:390 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c სახელი=მნიშვნელობა გაშვებული პროცესის პარამეტრის დაყენება\n" -#: main/main.c:327 +#: main/main.c:391 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C სახელი გაშვებული პროცესის პარამეტრის გამოტანა და გასვლა\n" -#: main/main.c:328 +#: main/main.c:392 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 გამართვის დონე\n" -#: main/main.c:329 +#: main/main.c:393 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR მონაცემთა ბაზის დირექტორია\n" -#: main/main.c:330 +#: main/main.c:394 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e ევროპული თარიღის შეყვანის ფორმატის (DMY) გამოყენება\n" -#: main/main.c:331 +#: main/main.c:395 #, c-format msgid " -F turn fsync off\n" msgstr " -F fsync-ის გამორთვა\n" -#: main/main.c:332 +#: main/main.c:396 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h ჰოსტის სახელი ჰოსტის სახელი ან IP მისამართი, რომელზეც უნდა მოვუსმინო\n" -#: main/main.c:333 +#: main/main.c:397 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr " -i TCP/IP-ის ჩართვა (მოძველებული)\n" -#: main/main.c:334 +#: main/main.c:398 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k საქაღალდე Unix-დომენის სოკეტის მდებარეობა\n" -#: main/main.c:336 +#: main/main.c:400 #, c-format msgid " -l enable SSL connections\n" msgstr " -l SSL-ის ჩართვა\n" -#: main/main.c:338 +#: main/main.c:402 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N მაქს-მიერთ მიერთებების დაშვებული მაქსიმალური რაოდენობა\n" -#: main/main.c:339 +#: main/main.c:403 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p პორტი მოსასმენი პორტის ნომერი\n" -#: main/main.c:340 +#: main/main.c:404 #, c-format msgid " -s show statistics after each query\n" msgstr " -s ყოველი მოთხოვნის შემდეგ სტატისტიკსი ჩვენება\n" -#: main/main.c:341 +#: main/main.c:405 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S სამუშ-მეხს დალაგებისთვის გამოყოფილი მეხსიერების დაყენება (კილობაიტებში)\n" -#: main/main.c:342 +#: main/main.c:406 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: main/main.c:343 +#: main/main.c:407 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --სახელი=მნიშვნელობა გაშვებული პროცესის პარამეტრის დაყენება\n" -#: main/main.c:344 +#: main/main.c:408 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config კონფიგურაციის პარამეტრის ახსნის გამოტანა და გასვლა\n" -#: main/main.c:345 +#: main/main.c:409 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: main/main.c:347 +#: main/main.c:411 #, c-format msgid "" "\n" @@ -16128,37 +16580,37 @@ msgstr "" "\n" "პროგრამისტის პარამეტრები:\n" -#: main/main.c:348 +#: main/main.c:412 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h ზოგიერთი გეგმის ტიპის გამოყენების აკრძალვა\n" -#: main/main.c:349 +#: main/main.c:413 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O სისტემური ცხრილის სტრუქტურის შეცვლის დაშვება\n" -#: main/main.c:350 +#: main/main.c:414 #, c-format msgid " -P disable system indexes\n" msgstr " -P სისტემური ინდექსების გამორთვა\n" -#: main/main.c:351 +#: main/main.c:415 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex ყოველი მოთხოვნის დროის მნიშვნელობების ჩვენება\n" -#: main/main.c:352 +#: main/main.c:416 #, c-format msgid " -T send SIGABRT to all backend processes if one dies\n" msgstr " -T ერთის სიკვდილის შემთხვევაში ყველა უკანაბოლოს პროცესისთვის SIGABRT სიგნალის გაგზავნა\n" -#: main/main.c:353 +#: main/main.c:417 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr " -W რიცხვი გამმართველისგან მიმაგრებისას მითითებული რაოდენობის წამების დაცდა\n" -#: main/main.c:355 +#: main/main.c:419 #, c-format msgid "" "\n" @@ -16167,37 +16619,37 @@ msgstr "" "\n" "ერთმომხმარებლიანი რეჟიმის პარამეტრები:\n" -#: main/main.c:356 +#: main/main.c:420 #, c-format msgid " --single selects single-user mode (must be first argument)\n" msgstr " --single ერთმომხმარებლიანი რეჟიმი (უნდა იყოს პირველი არგუმენტი)\n" -#: main/main.c:357 +#: main/main.c:421 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAME ბაზის სახელი (ნაგულისხმევი მნიშვნელობა მომხმარებლის სახელია)\n" -#: main/main.c:358 +#: main/main.c:422 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 პროგრამის გამართვის დონის მითითება\n" -#: main/main.c:359 +#: main/main.c:423 #, c-format msgid " -E echo statement before execution\n" msgstr " -E ოპერატორის გამოტანა მის შესრულებამდე\n" -#: main/main.c:360 +#: main/main.c:424 #, c-format msgid " -j do not use newline as interactive query delimiter\n" msgstr " -j ახალ ხაზზე გადატანა ინტერაქტიური მოთხოვნის გამყოფად გამოყენებული არ იქნება\n" -#: main/main.c:361 main/main.c:367 +#: main/main.c:425 main/main.c:431 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r FILENAME stdout-ის და stderr-ის მითითებულ ფაილში გაგზავნა\n" -#: main/main.c:363 +#: main/main.c:427 #, c-format msgid "" "\n" @@ -16206,22 +16658,22 @@ msgstr "" "\n" "სამუშაოდ მომზადების პარამეტრები\n" -#: main/main.c:364 +#: main/main.c:428 #, c-format msgid " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot სამუშაოდ მომზადების რეჟიმი (უნდა იყოს პირველი არგუმენტი)\n" -#: main/main.c:365 +#: main/main.c:429 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr " --check შემოწმების რეჟიმი (უნდა იყოს პირველი არგუმენტი)\n" -#: main/main.c:366 +#: main/main.c:430 #, c-format msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n" msgstr " DBNAME ბაზის სახელი (აუცილებელი არგუმენტი სამუშაოდ მომზადებისას)\n" -#: main/main.c:369 +#: main/main.c:433 #, c-format msgid "" "\n" @@ -16232,12 +16684,12 @@ msgid "" "Report bugs to <%s>.\n" msgstr "" -#: main/main.c:373 +#: main/main.c:437 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: main/main.c:384 +#: main/main.c:448 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -16246,12 +16698,12 @@ msgid "" "more information on how to properly start the server.\n" msgstr "" -#: main/main.c:401 +#: main/main.c:465 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: რეალური და მიმდინარე მომხმარებლის ID-ები უნდა ემთხვეოდეს\n" -#: main/main.c:408 +#: main/main.c:472 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -16271,12 +16723,12 @@ msgstr "გაფართოებადი კვანძის ტიპი msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "ExtensibleNodeMethods \"%s\" რეგისტრირებული არ იყო" -#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 +#: nodes/makefuncs.c:154 nodes/makefuncs.c:180 statistics/extended_stats.c:2306 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "ურთიერთობას \"%s\" კომპოზიტური ტიპი არ გააჩნია" -#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2567 parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 utils/fmgr/funcapi.c:669 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2602 parser/parse_coerce.c:2740 parser/parse_coerce.c:2787 parser/parse_expr.c:2118 parser/parse_func.c:710 parser/parse_oper.c:869 utils/adt/array_userfuncs.c:1950 utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "მონაცემების ტიპისთვის %s მასივის ტიპი ვერ ვიპოვე" @@ -16291,765 +16743,786 @@ msgstr "პორტალი \"%s\" პარამეტრებით: %s" msgid "unnamed portal with parameters: %s" msgstr "უსახელო პორტალი პარამეტრებით: %s" -#: optimizer/path/joinrels.c:972 +#: optimizer/path/joinrels.c:973 #, c-format msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions" msgstr "" -#: optimizer/plan/createplan.c:7162 parser/parse_merge.c:203 rewrite/rewriteHandler.c:1695 +#: optimizer/plan/createplan.c:7250 parser/parse_merge.c:203 rewrite/rewriteHandler.c:1689 #, c-format msgid "cannot execute MERGE on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" MERGE-ს ვერ გაუშვებთ" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1407 +#: optimizer/plan/initsplan.c:1755 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 parser/analyze.c:3247 +#: optimizer/plan/planner.c:1459 parser/analyze.c:1900 parser/analyze.c:2159 parser/analyze.c:3480 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s აკრძალულია UNION/INTERSECT/EXCEPT-სთან ერთად" -#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4107 +#: optimizer/plan/planner.c:2202 optimizer/plan/planner.c:4045 #, c-format msgid "could not implement GROUP BY" msgstr "\"GROUP BY\"-ის განხორციელება შეუძლებელია" -#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4108 optimizer/plan/planner.c:4789 optimizer/prep/prepunion.c:1320 +#: optimizer/plan/planner.c:2203 optimizer/plan/planner.c:4046 optimizer/plan/planner.c:4727 optimizer/prep/prepunion.c:1073 #, c-format msgid "Some of the datatypes only support hashing, while others only support sorting." msgstr "ზოგიერთ მონაცემის ტიპს მხოლოდ ჰეშირების მხარდაჭერა გააჩნია, მაშინ, როცა სხვებს მხოლოდ დალაგება შეუძლიათ." -#: optimizer/plan/planner.c:4788 +#: optimizer/plan/planner.c:4726 #, c-format msgid "could not implement DISTINCT" msgstr "\"DISTINCT\"-ის განხორციელება შეუძლებელია" -#: optimizer/plan/planner.c:6133 +#: optimizer/plan/planner.c:6188 #, c-format msgid "could not implement window PARTITION BY" msgstr "ფანჯრის, \"PARTITION BY\" განხორციელება შეუძლებელია" -#: optimizer/plan/planner.c:6134 +#: optimizer/plan/planner.c:6189 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "ფანჯრის დამყოფი სვეტები დალაგებადი მონაცემის ტიპის უნდა იყოს." -#: optimizer/plan/planner.c:6138 +#: optimizer/plan/planner.c:6193 #, c-format msgid "could not implement window ORDER BY" msgstr "ფანჯრის, \"ORDER BY\" განხორციელება შეუძლებელია" -#: optimizer/plan/planner.c:6139 +#: optimizer/plan/planner.c:6194 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "ფანჯრის დამლაგებელი სვეტები დალაგებადი მონაცემის ტიპის უნდა იყოს." -#: optimizer/prep/prepunion.c:467 +#: optimizer/prep/prepunion.c:440 #, c-format msgid "could not implement recursive UNION" msgstr "რეკურსიული UNION_ის განხორციელება შეუძლებელია" -#: optimizer/prep/prepunion.c:468 +#: optimizer/prep/prepunion.c:441 #, c-format msgid "All column datatypes must be hashable." msgstr "ყველა სვეტის მონაცემის ტიპი ჰეშირებადი უნდა იყოს." -#. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1319 +#. translator: %s is INTERSECT or EXCEPT +#: optimizer/prep/prepunion.c:1071 #, c-format msgid "could not implement %s" msgstr "ვერ განხორციელდა %s" -#: optimizer/util/clauses.c:4951 +#: optimizer/util/appendinfo.c:165 +#, c-format +msgid "attribute \"%s\" of relation \"%s\" does not match parent's type" +msgstr "ურთიერთობის \"%2$s\" ატრიბუტი \"%1$s\" მშობლის ტიპს არ ემთხვევა" + +#: optimizer/util/appendinfo.c:170 +#, c-format +msgid "attribute \"%s\" of relation \"%s\" does not match parent's collation" +msgstr "ურთიერთობის \"%2$s\" ატრიბუტი \"%1$s\" მშობლის კოლაციას არ ემთხვევა" + +#: optimizer/util/clauses.c:4966 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "SQL ფუნქცია \"%s\" ხაზში ჩასმისას" -#: optimizer/util/plancat.c:152 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "აღდგენისას დროებით ან უჟურნალო ურთიერთობებთან წვდომა შეუძლებელია" -#: optimizer/util/plancat.c:756 +#: optimizer/util/plancat.c:770 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "" -#: optimizer/util/plancat.c:773 +#: optimizer/util/plancat.c:787 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "შეზღუდვას ON CONFLICT პირობაში ასოცირებული ინდექსი არ გააჩნია" -#: optimizer/util/plancat.c:823 +#: optimizer/util/plancat.c:837 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATE გამორიცხვის შეზღუდვებთან ერთად მხარდაჭერილი არაა" -#: optimizer/util/plancat.c:933 +#: optimizer/util/plancat.c:954 #, c-format msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification" msgstr "უნიკალური ან გამორიცხვის შეზღუდვა, რომელიც ON CONFLICT-ის აღწერას ემთხვევა, არ არსებობს" -#: parser/analyze.c:824 parser/analyze.c:1550 +#: parser/analyze.c:954 parser/analyze.c:1679 #, c-format msgid "VALUES lists must all be the same length" msgstr "VALUES-ის სიები ყველა ტოლი სიგრძის უნდა იყოს" -#: parser/analyze.c:1027 +#: parser/analyze.c:1156 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT-ს მეტი გამოსახულება გააჩნია, ვიდრე სამიზნე სვეტი" -#: parser/analyze.c:1045 +#: parser/analyze.c:1174 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERT-ს მეტი სამიზნე სვეტი გააჩნია, ვიდრე გამოსახულება" -#: parser/analyze.c:1049 +#: parser/analyze.c:1178 #, c-format msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?" msgstr "" -#: parser/analyze.c:1357 parser/analyze.c:1744 +#: parser/analyze.c:1486 parser/analyze.c:1873 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO აქ დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1673 parser/analyze.c:3479 +#: parser/analyze.c:1802 parser/analyze.c:3712 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s-ს VALUES-ზე ვერ გამოიყენებთ" -#: parser/analyze.c:1911 +#: parser/analyze.c:2040 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "არასწორი UNION/INTERSECT/EXCEPT ORDER BY პირობა" -#: parser/analyze.c:1912 +#: parser/analyze.c:2041 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "" -#: parser/analyze.c:1913 +#: parser/analyze.c:2042 #, c-format msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause." msgstr "" -#: parser/analyze.c:2019 +#: parser/analyze.c:2149 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "" -#: parser/analyze.c:2091 +#: parser/analyze.c:2221 #, c-format msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level" msgstr "" -#: parser/analyze.c:2178 +#: parser/analyze.c:2308 #, c-format msgid "each %s query must have the same number of columns" msgstr "ყოველ %s მოთხოვნას სვეტების ტოლი რაოდენობა უნდა ჰქონდეს" -#: parser/analyze.c:2535 +#: parser/analyze.c:2665 #, c-format msgid "SET target columns cannot be qualified with the relation name." msgstr "" -#: parser/analyze.c:2589 +#. translator: %s is OLD or NEW +#: parser/analyze.c:2753 parser/analyze.c:2763 +#, c-format +msgid "%s cannot be specified multiple times" +msgstr "%s-ის რამდენჯერმე მითითება აკრძალულია" + +#: parser/analyze.c:2775 parser/parse_relation.c:473 +#, c-format +msgid "table name \"%s\" specified more than once" +msgstr "" + +#: parser/analyze.c:2823 #, c-format msgid "RETURNING must have at least one column" msgstr "RETURNING-ს ერთი სვეტი მაინც უნდა ჰქონდეს" -#: parser/analyze.c:2692 +#: parser/analyze.c:2925 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" msgstr[0] "მინიჭების წყარომ %d სვეტი დააბრუნა" msgstr[1] "მინიჭების წყარომ %d სვეტი დააბრუნა" -#: parser/analyze.c:2753 +#: parser/analyze.c:2986 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "\"%s\" ცვლადის ტიპია \"%s\", მაგრამ გამოსახულება %s ტიპისაა" #. translator: %s is a SQL keyword -#: parser/analyze.c:2878 parser/analyze.c:2886 +#: parser/analyze.c:3111 parser/analyze.c:3119 #, c-format msgid "cannot specify both %s and %s" msgstr "ორივე, %s და %s ერთად მითითება შეუძლებელია" -#: parser/analyze.c:2906 +#: parser/analyze.c:3139 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR-ი WITH-ში მონაცემების შემცვლელ გამოსახულებებს არ უნდა შეიცავდეს" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2914 +#: parser/analyze.c:3147 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s მხარდაჭერილი არაა" -#: parser/analyze.c:2917 +#: parser/analyze.c:3150 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "შენახვადი კურსორები READ ONLY ტიპის უნდა იყოს." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2925 +#: parser/analyze.c:3158 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s მხარდაჭერილი არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2936 +#: parser/analyze.c:3169 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s არასწორია" -#: parser/analyze.c:2939 +#: parser/analyze.c:3172 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "დამოუკიდებელი კურსორები READ ONLY ტიპის უნდა იყოს." -#: parser/analyze.c:3033 +#: parser/analyze.c:3266 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "მატერიალიზებულმა ხედებმა WITH-ში მონაცემების-შემცვლელი გამოსახულებები არ უნდა გამოიყენონ" -#: parser/analyze.c:3043 +#: parser/analyze.c:3276 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "მატერიალიზებულმა ხედებმა დროებითი ცხრილები ან ხედები არ უნდა გამოიყენონ" -#: parser/analyze.c:3053 +#: parser/analyze.c:3286 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "მატერიალიზებული ხედის აღწერა მიმაგრებული პარამეტრების გამოყენებით შეუძლებელია" -#: parser/analyze.c:3065 +#: parser/analyze.c:3298 #, c-format msgid "materialized views cannot be unlogged" msgstr "მატერიალიზებული ხედების ჟურნალის გამორთვა შეუძლებელია" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3254 +#: parser/analyze.c:3487 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s-ი DISTINCT პირობასთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3261 +#: parser/analyze.c:3494 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s-ი GROUP BY პირობასთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3268 +#: parser/analyze.c:3501 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s-ი HAVING პირობასთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3275 +#: parser/analyze.c:3508 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s აგრეგატულ ფუნქციებთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3282 +#: parser/analyze.c:3515 #, c-format msgid "%s is not allowed with window functions" msgstr "%s ფანჯრულ ფუნქციებთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3289 +#: parser/analyze.c:3522 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "%s სამიზნეების სიაში სეტების-დამბრუნებელ ფუნქციებთან ერთად დაშვებული არაა" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3388 +#: parser/analyze.c:3621 #, c-format msgid "%s must specify unqualified relation names" msgstr "" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3452 +#: parser/analyze.c:3685 #, c-format msgid "%s cannot be applied to a join" msgstr "%s join-ზე ვერ გადატარდება" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3461 +#: parser/analyze.c:3694 #, c-format msgid "%s cannot be applied to a function" msgstr "%s ფუნქციაზე ვერ გადატარდება" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3470 +#: parser/analyze.c:3703 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s ცხრილის ფუნქციაზე ვერ გადატარდება" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3488 +#: parser/analyze.c:3721 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s WITH მოთხოვნაზე ვერ გადატარდება" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3497 +#: parser/analyze.c:3730 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3517 +#: parser/analyze.c:3750 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "" -#: parser/parse_agg.c:210 parser/parse_oper.c:215 +#: parser/parse_agg.c:215 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "ტიპისთვის %s დალაგების ოპერატორის იდენტიფიკაცია შეუძლებელია" -#: parser/parse_agg.c:212 +#: parser/parse_agg.c:217 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "DISTINCT-ის მქონე აგრეგატებს შეყვანილი ინფორმაციის დალაგება თვითონ უნდა შეეძლოთ." -#: parser/parse_agg.c:270 +#: parser/parse_agg.c:275 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPING-ის არგუმენტების რიცხვი 32-ზე ნაკლები უნდა იყოს" -#: parser/parse_agg.c:373 +#: parser/parse_agg.c:378 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "აგრეგატულ ფუნქციებს JOIN-ის პირობებში ვერ გამოიყენებთ" -#: parser/parse_agg.c:375 +#: parser/parse_agg.c:380 msgid "grouping operations are not allowed in JOIN conditions" msgstr "დაჯგუფების ოპერაციებს JOIN-ის პირობებში ვერ გამოიყენებთ" -#: parser/parse_agg.c:387 +#: parser/parse_agg.c:390 msgid "aggregate functions are not allowed in FROM clause of their own query level" msgstr "აგრეგატული ფუნქციები მათი საკუთარი მოთხოვნის დონის FROM პირობაში დაშვებული არაა" -#: parser/parse_agg.c:389 +#: parser/parse_agg.c:392 msgid "grouping operations are not allowed in FROM clause of their own query level" msgstr "დაჯგუფების ფუნქციები მათი საკუთარი მოთხოვნის დონის FROM პირობაში დაშვებული არაა" -#: parser/parse_agg.c:394 +#: parser/parse_agg.c:397 msgid "aggregate functions are not allowed in functions in FROM" msgstr "აგრეგატულ ფუნქციებს FROM-ში ვერ გამოიყენებთ" -#: parser/parse_agg.c:396 +#: parser/parse_agg.c:399 msgid "grouping operations are not allowed in functions in FROM" msgstr "დაჯგუფების ოპერაციებს FROM-ში ვერ გამოიყენებთ" -#: parser/parse_agg.c:404 +#: parser/parse_agg.c:407 msgid "aggregate functions are not allowed in policy expressions" msgstr "წესის გამოსახულებებში აგრეგატული ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:406 +#: parser/parse_agg.c:409 msgid "grouping operations are not allowed in policy expressions" msgstr "წესის გამოსახულებებში დაჯგუფების ოპერაციები დაუშვებელია" -#: parser/parse_agg.c:423 +#: parser/parse_agg.c:426 msgid "aggregate functions are not allowed in window RANGE" msgstr "ფანჯრის RANGE-ში აგრეგატული ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:425 +#: parser/parse_agg.c:428 msgid "grouping operations are not allowed in window RANGE" msgstr "ფანჯრის RANGE-ში დაჯგუფების ოპერაციები დაუშვებელია" -#: parser/parse_agg.c:430 +#: parser/parse_agg.c:433 msgid "aggregate functions are not allowed in window ROWS" msgstr "ფანჯრის ROWS-ში აგრეგატული ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:432 +#: parser/parse_agg.c:435 msgid "grouping operations are not allowed in window ROWS" msgstr "ფანჯრის ROWS_ში დაჯგუფების ოპერაციები დაუშვებელია" -#: parser/parse_agg.c:437 +#: parser/parse_agg.c:440 msgid "aggregate functions are not allowed in window GROUPS" msgstr "აგრეგატული ფუნქციები ფანჯრის GROUPS-ში დაშვებული არაა" -#: parser/parse_agg.c:439 +#: parser/parse_agg.c:442 msgid "grouping operations are not allowed in window GROUPS" msgstr "დაჯგუფების ფუნქციები ფანჯრის GROUPS-ში დაშვებული არაა" -#: parser/parse_agg.c:452 +#: parser/parse_agg.c:455 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "აგრეგატული ფუნქციები MERGE WHEN-ის პირობებში დაშვებული არაა" -#: parser/parse_agg.c:454 +#: parser/parse_agg.c:457 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "დაჯგუფების ფუნქციები MERGE WHEN-ის პირობებში დაშვებული არაა" -#: parser/parse_agg.c:481 +#: parser/parse_agg.c:484 msgid "aggregate functions are not allowed in check constraints" msgstr "აგრეგატული ფუნქციები შეზღუდვის შემოწმებებში დაშვებული არაა" -#: parser/parse_agg.c:483 +#: parser/parse_agg.c:486 msgid "grouping operations are not allowed in check constraints" msgstr "დაჯგუფების ფუნქციები შეზღუდვის შემოწმებებში დაშვებული არაა" -#: parser/parse_agg.c:490 +#: parser/parse_agg.c:493 msgid "aggregate functions are not allowed in DEFAULT expressions" msgstr "აგრეგატული ფუნქციები DEFAULT გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:492 +#: parser/parse_agg.c:495 msgid "grouping operations are not allowed in DEFAULT expressions" msgstr "დაჯგუფების ფუნქციები DEFAULT გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:497 +#: parser/parse_agg.c:500 msgid "aggregate functions are not allowed in index expressions" msgstr "აგრეგატული ფუნქციები ინდექსის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:499 +#: parser/parse_agg.c:502 msgid "grouping operations are not allowed in index expressions" msgstr "დაჯგუფების ფუნქციები ინდექსის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:504 +#: parser/parse_agg.c:507 msgid "aggregate functions are not allowed in index predicates" msgstr "აგრეგატული ფუნქციები ინდექსის პრედიკატებში დაშვებული არაა" -#: parser/parse_agg.c:506 +#: parser/parse_agg.c:509 msgid "grouping operations are not allowed in index predicates" msgstr "დაშვებული ფუნქციები ინდექსის პრედიკატებში დაშვებული არაა" -#: parser/parse_agg.c:511 +#: parser/parse_agg.c:514 msgid "aggregate functions are not allowed in statistics expressions" msgstr "აგრეგატული ფუნქციები სტატისტიკის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:513 +#: parser/parse_agg.c:516 msgid "grouping operations are not allowed in statistics expressions" msgstr "დაჯგუფების ფუნქციები სტატისტიკის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:518 +#: parser/parse_agg.c:521 msgid "aggregate functions are not allowed in transform expressions" msgstr "აგრეგატული ფუნქციები გადაყვანის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:520 +#: parser/parse_agg.c:523 msgid "grouping operations are not allowed in transform expressions" msgstr "დაჯგუფების ფუნქციები გადაყვანის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:525 +#: parser/parse_agg.c:528 msgid "aggregate functions are not allowed in EXECUTE parameters" msgstr "აგრეგატული ფუნქციები EXECUTE-ის პარამეტრებში დაშვებული არაა" -#: parser/parse_agg.c:527 +#: parser/parse_agg.c:530 msgid "grouping operations are not allowed in EXECUTE parameters" msgstr "დაჯგუფების ფუნქციები EXECUTE-ის პარამეტრებში დაშვებული არაა" -#: parser/parse_agg.c:532 +#: parser/parse_agg.c:535 msgid "aggregate functions are not allowed in trigger WHEN conditions" msgstr "აგრეგატული ფუნქციები WHEN-ის ტრიგერის პირობებში დაშვებული არაა" -#: parser/parse_agg.c:534 +#: parser/parse_agg.c:537 msgid "grouping operations are not allowed in trigger WHEN conditions" msgstr "დაჯგუფების ფუნქციები WHEN-ის ტრიგერის პირობებში დაშვებული არაა" -#: parser/parse_agg.c:539 +#: parser/parse_agg.c:542 msgid "aggregate functions are not allowed in partition bound" msgstr "აგრეგატული ფუნქციები დანაყოფის საზღვარში დაშვებული არაა" -#: parser/parse_agg.c:541 +#: parser/parse_agg.c:544 msgid "grouping operations are not allowed in partition bound" msgstr "დაჯგუფების ფუნქციები დანაყოფის საზღვარში დაშვებული არაა" -#: parser/parse_agg.c:546 +#: parser/parse_agg.c:549 msgid "aggregate functions are not allowed in partition key expressions" msgstr "აგრეგატული ფუნქციები დანაყოფის გასაღების გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:548 +#: parser/parse_agg.c:551 msgid "grouping operations are not allowed in partition key expressions" msgstr "დაჯგუფების ფუნქციები დანაყოფის გასაღების გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:554 +#: parser/parse_agg.c:557 msgid "aggregate functions are not allowed in column generation expressions" msgstr "აგრეგატული ფუნქციები სვეტის გენერაციის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:556 +#: parser/parse_agg.c:559 msgid "grouping operations are not allowed in column generation expressions" msgstr "დაჯგუფების ფუნქციები სვეტის გენერაციის გამოსახულებებში დაშვებული არაა" -#: parser/parse_agg.c:562 +#: parser/parse_agg.c:565 msgid "aggregate functions are not allowed in CALL arguments" msgstr "აგრეგატული ფუნქციები CALL-ის არგუმენტებში დაშვებული არაა" -#: parser/parse_agg.c:564 +#: parser/parse_agg.c:567 msgid "grouping operations are not allowed in CALL arguments" msgstr "დაჯგუფების ფუნქციები CALL-ის არგუმენტებში დაშვებული არაა" -#: parser/parse_agg.c:570 +#: parser/parse_agg.c:573 msgid "aggregate functions are not allowed in COPY FROM WHERE conditions" msgstr "აგრეგატული ფუნქციები COPY FROM WHERE პირობებში დაშვებული არაა" -#: parser/parse_agg.c:572 +#: parser/parse_agg.c:575 msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "დაჯგუფების ფუნქციები COPY FROM WHERE პირობებში დაშვებული არაა" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:599 parser/parse_clause.c:1962 +#: parser/parse_agg.c:602 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "აგრეგატული ფუნქციები %s-ში დაშვებული არაა" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:602 +#: parser/parse_agg.c:605 #, c-format msgid "grouping operations are not allowed in %s" msgstr "დაჯგუფების ფუნქციები %s-ში დაშვებული არაა" -#: parser/parse_agg.c:703 +#: parser/parse_agg.c:706 #, c-format msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments" msgstr "" -#: parser/parse_agg.c:781 +#: parser/parse_agg.c:784 #, c-format msgid "aggregate function calls cannot contain set-returning function calls" msgstr "აგრეგატული ფუნქციის გამოძახებები არ შეძლება, სეტების დამბრუნებელი ფუნქციის გამოძახებებს შეიცავდეს" -#: parser/parse_agg.c:782 parser/parse_expr.c:1762 parser/parse_expr.c:2245 parser/parse_func.c:885 +#: parser/parse_agg.c:785 parser/parse_expr.c:1760 parser/parse_expr.c:2251 parser/parse_func.c:885 #, c-format msgid "You might be able to move the set-returning function into a LATERAL FROM item." msgstr "" -#: parser/parse_agg.c:787 +#: parser/parse_agg.c:790 #, c-format msgid "aggregate function calls cannot contain window function calls" msgstr "აგრეგატული ფუნქციის გამოძახებები არ შეიძლება, ფანჯრის ფუნქციის გამოძახებებს შეიცავდეს" -#: parser/parse_agg.c:866 +#: parser/parse_agg.c:869 msgid "window functions are not allowed in JOIN conditions" msgstr "\"JOIN\"-ის პირობებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:873 +#: parser/parse_agg.c:876 msgid "window functions are not allowed in functions in FROM" msgstr "\"FROM\"-ის ფუნქციებში ფანჯრების ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:879 +#: parser/parse_agg.c:882 msgid "window functions are not allowed in policy expressions" msgstr "წესების გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:892 +#: parser/parse_agg.c:895 msgid "window functions are not allowed in window definitions" msgstr "ფანჯრის აღწერებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:903 +#: parser/parse_agg.c:906 msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "\"MERGE WHEN\" პირობებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:928 +#: parser/parse_agg.c:931 msgid "window functions are not allowed in check constraints" msgstr "შეზღუდვის შემოწმებაში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:932 +#: parser/parse_agg.c:935 msgid "window functions are not allowed in DEFAULT expressions" msgstr "ნაგულისხმევ გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:935 +#: parser/parse_agg.c:938 msgid "window functions are not allowed in index expressions" msgstr "ინდექსის გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:938 +#: parser/parse_agg.c:941 msgid "window functions are not allowed in statistics expressions" msgstr "სტატისტიკის გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:941 +#: parser/parse_agg.c:944 msgid "window functions are not allowed in index predicates" msgstr "ინდექსის პრედიკატებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:944 +#: parser/parse_agg.c:947 msgid "window functions are not allowed in transform expressions" msgstr "გადაყვანის გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:947 +#: parser/parse_agg.c:950 msgid "window functions are not allowed in EXECUTE parameters" msgstr "\"EXECUTE\"-ის პარამეტრებში ფანჯრის ფუნქციები დაუშვებელია\"" -#: parser/parse_agg.c:950 +#: parser/parse_agg.c:953 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "\"WHEN\"-ის პირობების ტრიგერში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:953 +#: parser/parse_agg.c:956 msgid "window functions are not allowed in partition bound" msgstr "დანაყოფის საზღვარში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:956 +#: parser/parse_agg.c:959 msgid "window functions are not allowed in partition key expressions" msgstr "დანაყოფის გასაღების გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:959 +#: parser/parse_agg.c:962 msgid "window functions are not allowed in CALL arguments" msgstr "\"CALL\"-ის არგუმენტებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:962 +#: parser/parse_agg.c:965 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "\"COPY FROM WHERE\"-ის პირობებში ფანჯრის ფუნქციები დაუშვებელია" -#: parser/parse_agg.c:965 +#: parser/parse_agg.c:968 msgid "window functions are not allowed in column generation expressions" msgstr "სვეტის გენერაციის გამოსახულებებში ფანჯრის ფუნქციები დაუშვებელია" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:988 parser/parse_clause.c:1971 +#: parser/parse_agg.c:991 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "ფანჯრის ფუნქციები არ არის დაშვებული %s-ში" -#: parser/parse_agg.c:1022 parser/parse_clause.c:2804 +#: parser/parse_agg.c:1025 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "ფანჯარა \"%s\" არ არსებობს" -#: parser/parse_agg.c:1110 +#: parser/parse_agg.c:1115 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "ძალიან ბევრი დაჯგუფების ნაკრებია (მაქსიმუმ 4096)" -#: parser/parse_agg.c:1250 +#: parser/parse_agg.c:1276 #, c-format msgid "aggregate functions are not allowed in a recursive query's recursive term" msgstr "" -#: parser/parse_agg.c:1443 +#: parser/parse_agg.c:1499 #, c-format msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function" msgstr "" -#: parser/parse_agg.c:1446 +#: parser/parse_agg.c:1502 #, c-format msgid "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "" -#: parser/parse_agg.c:1451 +#: parser/parse_agg.c:1507 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "ქვემოთხოვნა outer მოთხოვნიდან დაუჯგუფებელ სვეტს \"%s.%s\" იყენებს" -#: parser/parse_agg.c:1615 +#: parser/parse_agg.c:1672 #, c-format msgid "arguments to GROUPING must be grouping expressions of the associated query level" msgstr "" -#: parser/parse_clause.c:193 +#: parser/parse_clause.c:191 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "ურთიერთობა \"%s\" არ შეიძლება, შემცვლელი გამოსახულების სამიზნეს წარმოადგენდეს" -#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 +#: parser/parse_clause.c:567 parser/parse_clause.c:595 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "სეტების დამბრუნებელი ფუნქციები FROM-ის ზედა დონეზე უნდა გამოჩნდნენ" -#: parser/parse_clause.c:609 +#: parser/parse_clause.c:607 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "იგივე ფუნქციისთვის ერთზე მეტი სვეტის აღწერის სიები დაშვებული არაა" -#: parser/parse_clause.c:642 +#: parser/parse_clause.c:640 #, c-format msgid "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "ერთზე მეტი ფუნქციის მქონე ROW FROM ()-ს არ შეიძლება, სვეტის აღწერების სია ჰქონდეს" -#: parser/parse_clause.c:643 +#: parser/parse_clause.c:641 #, c-format msgid "Put a separate column definition list for each function inside ROWS FROM()." msgstr "" -#: parser/parse_clause.c:649 +#: parser/parse_clause.c:647 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "" -#: parser/parse_clause.c:650 +#: parser/parse_clause.c:648 #, c-format msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one." msgstr "" -#: parser/parse_clause.c:657 +#: parser/parse_clause.c:655 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY სვეტების აღწერის სიასთან ერთად არ უნდა გამოიყენოთ" -#: parser/parse_clause.c:658 +#: parser/parse_clause.c:656 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "სვეტის აღწერის სია ROWS FROM()-ის შიგნით გადაიტანეთ." -#: parser/parse_clause.c:762 +#: parser/parse_clause.c:760 parser/parse_jsontable.c:293 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "დაშვებულია მხოლოდ FOR ORDINALITY სვეტი" -#: parser/parse_clause.c:823 +#: parser/parse_clause.c:821 #, c-format msgid "column name \"%s\" is not unique" msgstr "სვეტის სახელი \"%s\" არ არის უნიკალური" -#: parser/parse_clause.c:865 +#: parser/parse_clause.c:863 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "სახელების სივრცის სახელი \"%s\" უნიკალური არაა" -#: parser/parse_clause.c:875 +#: parser/parse_clause.c:873 #, c-format msgid "only one default namespace is allowed" msgstr "დასაშვებია მხოლოდ ერთი ნაგულისხმევი სახელის სივრცე" -#: parser/parse_clause.c:935 +#: parser/parse_clause.c:933 #, c-format msgid "tablesample method %s does not exist" msgstr "" -#: parser/parse_clause.c:957 +#: parser/parse_clause.c:955 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" msgstr[0] "" msgstr[1] "" -#: parser/parse_clause.c:991 +#: parser/parse_clause.c:989 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "" -#: parser/parse_clause.c:1144 +#: parser/parse_clause.c:1142 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "" -#: parser/parse_clause.c:1331 +#: parser/parse_clause.c:1329 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "პირობაში USIN სვეტის სახელი \"%s\" ერთზე მეტჯერ გამოჩნდა" -#: parser/parse_clause.c:1346 +#: parser/parse_clause.c:1344 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "საერთო სვეტის სახელი \"%s\" ერთხელ, მარცხენა ცხრილში გამოჩნდა" -#: parser/parse_clause.c:1355 +#: parser/parse_clause.c:1353 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "სვეტი \"%s\", რომელიც USING პირობაშია მითითებული, მარცხენა ცხრილში არ არსებობს" -#: parser/parse_clause.c:1370 +#: parser/parse_clause.c:1368 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "საერთო სვეტის სახელი \"%s\" ერთხელ, მარჯვენა ცხრილში გამოჩნდა" -#: parser/parse_clause.c:1379 +#: parser/parse_clause.c:1377 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "სვეტი \"%s\", რომელიც USING პირობაშია მითითებული, მარჯვენა ცხრილში არ არსებობს" @@ -17188,173 +17661,173 @@ msgstr "ოპერატორი %s სწორი დამლაგებ msgid "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "" -#: parser/parse_clause.c:3775 +#: parser/parse_clause.c:3778 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "" -#: parser/parse_clause.c:3781 +#: parser/parse_clause.c:3784 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s and offset type %s" msgstr "" -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3787 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "წანაცვლების მნიშვნელობის დამაკმაყოფილებელ ტიპში დაკასტვა." -#: parser/parse_clause.c:3789 +#: parser/parse_clause.c:3792 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for column type %s and offset type %s" msgstr "" -#: parser/parse_clause.c:3792 +#: parser/parse_clause.c:3795 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "წანაცვლების მნიშვნელობის ზუსტად განსაზღვრულ ტიპში დაკასტვა." -#: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3403 parser/parse_expr.c:3624 parser/parse_expr.c:4388 parser/parse_target.c:998 +#: parser/parse_coerce.c:1048 parser/parse_coerce.c:1086 parser/parse_coerce.c:1104 parser/parse_coerce.c:1119 parser/parse_expr.c:2152 parser/parse_expr.c:2770 parser/parse_expr.c:3421 parser/parse_expr.c:3650 parser/parse_target.c:1001 #, c-format msgid "cannot cast type %s to %s" msgstr "%s ტიპის %s-ში გადაყვანა შეუძლებელია" -#: parser/parse_coerce.c:1091 +#: parser/parse_coerce.c:1089 #, c-format msgid "Input has too few columns." msgstr "შეყვანას ძალიან ცოტა სვეტი აქვს." -#: parser/parse_coerce.c:1109 +#: parser/parse_coerce.c:1107 #, c-format msgid "Cannot cast type %s to %s in column %d." msgstr "%3$d სვეტში %1$s ტიპის დაკასტვა ტიპამდე %2$s შეუძლებელია." -#: parser/parse_coerce.c:1124 +#: parser/parse_coerce.c:1122 #, c-format msgid "Input has too many columns." msgstr "შეყვანას ძალიან ბევრი სვეტი აქვს." #. translator: first %s is name of a SQL construct, eg WHERE #. translator: first %s is name of a SQL construct, eg LIMIT -#: parser/parse_coerce.c:1179 parser/parse_coerce.c:1227 +#: parser/parse_coerce.c:1177 parser/parse_coerce.c:1225 #, c-format msgid "argument of %s must be type %s, not type %s" msgstr "%s-ის არგუმენტის ტიპი %s უნდა იყოს და არა %s" #. translator: %s is name of a SQL construct, eg WHERE #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_coerce.c:1190 parser/parse_coerce.c:1239 +#: parser/parse_coerce.c:1188 parser/parse_coerce.c:1237 #, c-format msgid "argument of %s must not return a set" msgstr "%s-ის არგუმენტმა სეტი არ უნდა დააბრუნოს" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1383 +#: parser/parse_coerce.c:1418 #, c-format msgid "%s types %s and %s cannot be matched" msgstr "%s-ის ტიპები %s და %s არ შეიძლება, ერთმანეთს ემთხვეოდეს" -#: parser/parse_coerce.c:1499 +#: parser/parse_coerce.c:1534 #, c-format msgid "argument types %s and %s cannot be matched" msgstr "არგუმენტის ტიპებს %s და %s საერთო არაფერი გააჩნიათ" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1551 +#: parser/parse_coerce.c:1586 #, c-format msgid "%s could not convert type %s to %s" msgstr "%s-მა ტიპი %s-დან %s-ში ვერ გადაიყვანა" -#: parser/parse_coerce.c:2154 parser/parse_coerce.c:2174 parser/parse_coerce.c:2194 parser/parse_coerce.c:2215 parser/parse_coerce.c:2270 parser/parse_coerce.c:2304 +#: parser/parse_coerce.c:2189 parser/parse_coerce.c:2209 parser/parse_coerce.c:2229 parser/parse_coerce.c:2250 parser/parse_coerce.c:2305 parser/parse_coerce.c:2339 #, c-format msgid "arguments declared \"%s\" are not all alike" msgstr "\"%s\"-ად აღწერილი არგუმენტები ყველა ერთნაირი არაა" -#: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 utils/fmgr/funcapi.c:600 +#: parser/parse_coerce.c:2284 parser/parse_coerce.c:2397 utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "\"%s\"-ად აღწერილი არგუმენტი მასივი არაა, მაგრამ მისი ტიპია %s" -#: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 utils/fmgr/funcapi.c:614 +#: parser/parse_coerce.c:2317 parser/parse_coerce.c:2467 utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "\"%s\"-ად აღწერილი არგუმენტი დიაპაზონის მაგიერ არის %s" -#: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 +#: parser/parse_coerce.c:2351 parser/parse_coerce.c:2431 parser/parse_coerce.c:2564 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "\"%s\"-ად აღწერილი არგუმენტი მრავალდიაპაზონის მაგიერ არის %s" -#: parser/parse_coerce.c:2353 +#: parser/parse_coerce.c:2388 #, c-format msgid "cannot determine element type of \"anyarray\" argument" msgstr "\"anyarray\" არგუმენტის ტიპის დადგენა შეუძლებელია" -#: parser/parse_coerce.c:2379 parser/parse_coerce.c:2410 parser/parse_coerce.c:2449 parser/parse_coerce.c:2515 +#: parser/parse_coerce.c:2414 parser/parse_coerce.c:2445 parser/parse_coerce.c:2484 parser/parse_coerce.c:2550 #, c-format msgid "argument declared %s is not consistent with argument declared %s" msgstr "" -#: parser/parse_coerce.c:2474 +#: parser/parse_coerce.c:2509 #, c-format msgid "could not determine polymorphic type because input has type %s" msgstr "" -#: parser/parse_coerce.c:2488 +#: parser/parse_coerce.c:2523 #, c-format msgid "type matched to anynonarray is an array type: %s" msgstr "ტიპი, რომელიც anytoarray-ს ემთხვევა, მასივის ტიპისაა: %s" -#: parser/parse_coerce.c:2498 +#: parser/parse_coerce.c:2533 #, c-format msgid "type matched to anyenum is not an enum type: %s" msgstr "ტიპი, რომელიც anytoenum-ს ემთხვევა, ჩამონათვალის ტიპის არაა: %s" -#: parser/parse_coerce.c:2559 +#: parser/parse_coerce.c:2594 #, c-format msgid "arguments of anycompatible family cannot be cast to a common type" msgstr "" -#: parser/parse_coerce.c:2577 parser/parse_coerce.c:2598 parser/parse_coerce.c:2648 parser/parse_coerce.c:2653 parser/parse_coerce.c:2717 parser/parse_coerce.c:2729 +#: parser/parse_coerce.c:2612 parser/parse_coerce.c:2633 parser/parse_coerce.c:2683 parser/parse_coerce.c:2688 parser/parse_coerce.c:2752 parser/parse_coerce.c:2764 #, c-format msgid "could not determine polymorphic type %s because input has type %s" msgstr "" -#: parser/parse_coerce.c:2587 +#: parser/parse_coerce.c:2622 #, c-format msgid "anycompatiblerange type %s does not match anycompatible type %s" msgstr "" -#: parser/parse_coerce.c:2608 +#: parser/parse_coerce.c:2643 #, c-format msgid "anycompatiblemultirange type %s does not match anycompatible type %s" msgstr "" -#: parser/parse_coerce.c:2622 +#: parser/parse_coerce.c:2657 #, c-format msgid "type matched to anycompatiblenonarray is an array type: %s" msgstr "" -#: parser/parse_coerce.c:2857 +#: parser/parse_coerce.c:2892 #, c-format msgid "A result of type %s requires at least one input of type anyrange or anymultirange." msgstr "" -#: parser/parse_coerce.c:2874 +#: parser/parse_coerce.c:2909 #, c-format msgid "A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange." msgstr "" -#: parser/parse_coerce.c:2886 +#: parser/parse_coerce.c:2921 #, c-format msgid "A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange." msgstr "" -#: parser/parse_coerce.c:2898 +#: parser/parse_coerce.c:2933 #, c-format msgid "A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange." msgstr "" -#: parser/parse_coerce.c:2928 +#: parser/parse_coerce.c:2963 msgid "A result of type internal requires at least one input of type internal." msgstr "" @@ -17398,488 +17871,545 @@ msgstr "" msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "" -#: parser/parse_cte.c:136 +#: parser/parse_cte.c:137 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "WITH მოთხოვნის სახელი \"%s\" ერთზე მეტჯერაა მითითებული" -#: parser/parse_cte.c:308 +#: parser/parse_cte.c:309 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "" -#: parser/parse_cte.c:335 +#: parser/parse_cte.c:336 #, c-format msgid "WITH clause containing a data-modifying statement must be at the top level" msgstr "WITH პირობის შემცველი მონაცემების-შემცვლელი გამოსახულება უმაღლეს დონეზე უნდა იიყოს" -#: parser/parse_cte.c:384 +#: parser/parse_cte.c:385 #, c-format msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall" msgstr "" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:391 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "" -#: parser/parse_cte.c:395 +#: parser/parse_cte.c:396 #, c-format msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall" msgstr "" -#: parser/parse_cte.c:399 +#: parser/parse_cte.c:400 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "" -#: parser/parse_cte.c:420 +#: parser/parse_cte.c:421 #, c-format msgid "WITH query is not recursive" msgstr "WITH მოთხოვნა რეკურსიული არაა" -#: parser/parse_cte.c:451 +#: parser/parse_cte.c:452 #, c-format msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "" -#: parser/parse_cte.c:456 +#: parser/parse_cte.c:457 #, c-format msgid "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "" -#: parser/parse_cte.c:471 +#: parser/parse_cte.c:472 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "ძებნის სვეტი \"%s\" WITH მოთხოვნის სვეტების სიაში არაა" -#: parser/parse_cte.c:478 +#: parser/parse_cte.c:479 #, c-format msgid "search column \"%s\" specified more than once" msgstr "ძებნის სვეტი \"%s\" ერთზე მეტჯერაა მითითებული" -#: parser/parse_cte.c:487 +#: parser/parse_cte.c:488 #, c-format msgid "search sequence column name \"%s\" already used in WITH query column list" msgstr "" -#: parser/parse_cte.c:504 +#: parser/parse_cte.c:505 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "ციკლის სვეტი \"%s\" WITH მოთხოვნის სვეტების სიაში არაა" -#: parser/parse_cte.c:511 +#: parser/parse_cte.c:512 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "ციკლის სვეტი \"%s\" ერთზემეტჯერაა მითითებული" -#: parser/parse_cte.c:520 +#: parser/parse_cte.c:521 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "" -#: parser/parse_cte.c:527 +#: parser/parse_cte.c:528 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "" -#: parser/parse_cte.c:535 +#: parser/parse_cte.c:536 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "" -#: parser/parse_cte.c:545 +#: parser/parse_cte.c:546 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "" -#: parser/parse_cte.c:552 +#: parser/parse_cte.c:553 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "" -#: parser/parse_cte.c:636 +#: parser/parse_cte.c:637 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "" -#: parser/parse_cte.c:816 +#: parser/parse_cte.c:882 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "\"WITH\"-ის ჩანაწერებს შორის ურთიერთრეკურსია მხარდაჭერილი არაა" -#: parser/parse_cte.c:868 +#: parser/parse_cte.c:934 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "" -#: parser/parse_cte.c:876 +#: parser/parse_cte.c:942 #, c-format msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term" msgstr "" -#: parser/parse_cte.c:920 +#: parser/parse_cte.c:977 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "რეკურსიულ მოთხოვნაში ORDER BY განხორციელებული არაა" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:983 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "რეკურსიულ მოთხოვნაში OFFSET განხორციელებული არაა" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:989 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "რეკურსიულ მოთხოვნაში LIMIT განხორციელებული არაა" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:995 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "რეკურსიულ მოთხოვნაში FOR UPDATE/SHARE განხორციელებული არაა" -#: parser/parse_cte.c:995 +#: parser/parse_cte.c:1074 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "" -#: parser/parse_expr.c:314 +#: parser/parse_expr.c:311 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "ამ კონტექსტში ნაგულისხმევს ვერ გამოიყენებთ" -#: parser/parse_expr.c:407 parser/parse_relation.c:3691 parser/parse_relation.c:3701 parser/parse_relation.c:3719 parser/parse_relation.c:3726 parser/parse_relation.c:3740 +#: parser/parse_expr.c:404 parser/parse_relation.c:3797 parser/parse_relation.c:3807 parser/parse_relation.c:3825 parser/parse_relation.c:3832 parser/parse_relation.c:3846 #, c-format msgid "column %s.%s does not exist" msgstr "სვეტი %s.%s არ არსებობს" -#: parser/parse_expr.c:419 +#: parser/parse_expr.c:416 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "სვეტი \"%s\" მონაცემის ტიპში %s აღმოჩენილი არაა" -#: parser/parse_expr.c:425 +#: parser/parse_expr.c:422 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "ჩანაწერის მონაცემის ტიპში სვეტის \"%s\" იდენტიფიკაცია შეუძლებელია" -#: parser/parse_expr.c:431 +#: parser/parse_expr.c:428 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "" -#: parser/parse_expr.c:462 parser/parse_target.c:732 +#: parser/parse_expr.c:459 parser/parse_target.c:735 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "" -#: parser/parse_expr.c:585 +#: parser/parse_expr.c:582 msgid "cannot use column reference in DEFAULT expression" msgstr "" -#: parser/parse_expr.c:588 +#: parser/parse_expr.c:585 msgid "cannot use column reference in partition bound expression" msgstr "" -#: parser/parse_expr.c:847 parser/parse_relation.c:833 parser/parse_relation.c:915 parser/parse_target.c:1238 +#: parser/parse_expr.c:844 parser/parse_relation.c:848 parser/parse_relation.c:930 parser/parse_target.c:1241 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "სვეტის მითითება \"%s\" ორაზროვანია" -#: parser/parse_expr.c:903 parser/parse_param.c:110 parser/parse_param.c:142 parser/parse_param.c:204 parser/parse_param.c:303 +#: parser/parse_expr.c:900 parser/parse_param.c:111 parser/parse_param.c:143 parser/parse_param.c:205 parser/parse_param.c:304 #, c-format msgid "there is no parameter $%d" msgstr "პარამეტრი $%d არ არსებობს" -#: parser/parse_expr.c:1103 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1101 parser/parse_expr.c:3081 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "" +msgid "%s requires = operator to yield boolean" +msgstr "%s-სთვის აუცილებელია = ოპერატორი, რომ ლოგიკური მნიშვნელობა დააბრუნოს" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1109 parser/parse_expr.c:3070 +#: parser/parse_expr.c:1107 parser/parse_expr.c:3088 #, c-format msgid "%s must not return a set" msgstr "%s -მა სეტი არ უნდა დააბრუნოს" -#: parser/parse_expr.c:1395 +#: parser/parse_expr.c:1393 #, c-format msgid "MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" msgstr "" -#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 +#: parser/parse_expr.c:1517 parser/parse_expr.c:1549 #, c-format msgid "number of columns does not match number of values" msgstr "" -#: parser/parse_expr.c:1565 +#: parser/parse_expr.c:1563 #, c-format msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" msgstr "" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 +#: parser/parse_expr.c:1758 parser/parse_expr.c:2249 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "%s-ში სეტის-დამბრუნებელი ფუნქციები დაშვებული არაა" -#: parser/parse_expr.c:1824 +#: parser/parse_expr.c:1822 msgid "cannot use subquery in check constraint" msgstr "შეზღუდვის შემმოწმებელში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1828 +#: parser/parse_expr.c:1826 msgid "cannot use subquery in DEFAULT expression" msgstr "ნაგულისხმევ გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1831 +#: parser/parse_expr.c:1829 msgid "cannot use subquery in index expression" msgstr "ინდექსის გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1834 +#: parser/parse_expr.c:1832 msgid "cannot use subquery in index predicate" msgstr "ინდექსის პრედიკატში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1837 +#: parser/parse_expr.c:1835 msgid "cannot use subquery in statistics expression" msgstr "სტატისტიკის გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1840 +#: parser/parse_expr.c:1838 msgid "cannot use subquery in transform expression" msgstr "გარდაქმნის გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1843 +#: parser/parse_expr.c:1841 msgid "cannot use subquery in EXECUTE parameter" msgstr "პარამეტრში \"EXECUTE\" ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1846 +#: parser/parse_expr.c:1844 msgid "cannot use subquery in trigger WHEN condition" msgstr "\"WHEN\" პირობის ტრიგერში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1849 +#: parser/parse_expr.c:1847 msgid "cannot use subquery in partition bound" msgstr "დანაყოფის საზღვარში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1852 +#: parser/parse_expr.c:1850 msgid "cannot use subquery in partition key expression" msgstr "დანაყოფის გასაღების გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1855 +#: parser/parse_expr.c:1853 msgid "cannot use subquery in CALL argument" msgstr "\"CALL\"-ის არგუმენტში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1858 +#: parser/parse_expr.c:1856 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "\"COPY FROM WHERE\" პირობაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1861 +#: parser/parse_expr.c:1859 msgid "cannot use subquery in column generation expression" msgstr "სვეტების გენერაციის გამოსახულებაში ქვემოთხოვნას ვერ გამოიყენებთ" -#: parser/parse_expr.c:1914 parser/parse_expr.c:3756 +#: parser/parse_expr.c:1912 parser/parse_expr.c:3780 #, c-format msgid "subquery must return only one column" msgstr "ქვემოთხოვნამ მხოლოდ ერთი სვეტი უნდა დააბრუნოს" -#: parser/parse_expr.c:1985 +#: parser/parse_expr.c:1983 #, c-format msgid "subquery has too many columns" msgstr "ქვემოთხოვნას ძალიან ბევრი სვეტი აქვს" -#: parser/parse_expr.c:1990 +#: parser/parse_expr.c:1988 #, c-format msgid "subquery has too few columns" msgstr "ქვემოთხოვნას ძალიან ცოტა სვეტი აქვს" -#: parser/parse_expr.c:2086 +#: parser/parse_expr.c:2092 #, c-format msgid "cannot determine type of empty array" msgstr "ცარიელი მასივის ტიპის დადგენა შეუძლებელია" -#: parser/parse_expr.c:2087 +#: parser/parse_expr.c:2093 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "" -#: parser/parse_expr.c:2101 +#: parser/parse_expr.c:2107 #, c-format msgid "could not find element type for data type %s" msgstr "" -#: parser/parse_expr.c:2184 +#: parser/parse_expr.c:2190 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "ROW გამოსახულებებს მაქსიმუმ %d ელემენტი შეიძლება ჰქონდეს" -#: parser/parse_expr.c:2389 +#: parser/parse_expr.c:2395 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "უსახელო XML ატრიბუტის მნიშვნელობა სვეტის მიმართვას უნდა წარმოადგენდეს" -#: parser/parse_expr.c:2390 +#: parser/parse_expr.c:2396 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "უსახელო XML ელემენტის მნიშვნელობა სვეტის მიმართვას უნდა წარმოადგენდეს" -#: parser/parse_expr.c:2405 +#: parser/parse_expr.c:2411 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "XML ატრიბუტის სახელი \"%s\" ერთზე მეტჯერ გამოჩნდა" -#: parser/parse_expr.c:2513 +#: parser/parse_expr.c:2519 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "'XMLSERIALIZE'-ის შედეგის %s-ში დაკასტვა შეუძლებელია" -#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 +#: parser/parse_expr.c:2843 parser/parse_expr.c:3039 #, c-format msgid "unequal number of entries in row expressions" msgstr "მწკრივის გამოსახულებებში ჩანაწერების რაოდენობა ტოლი არაა" -#: parser/parse_expr.c:2837 +#: parser/parse_expr.c:2853 #, c-format msgid "cannot compare rows of zero length" msgstr "ნულოვანი სიგრძის მწკრივების შედარება შეუძლებელია" -#: parser/parse_expr.c:2862 +#: parser/parse_expr.c:2878 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "მწკრივის შედარების ოპერატორმა ლოგიკური მნიშვნელობა უნდა დააბრუნოს და არა ტიპი %s" -#: parser/parse_expr.c:2869 +#: parser/parse_expr.c:2885 #, c-format msgid "row comparison operator must not return a set" msgstr "მწკრივის შედარების ოპერატორმა სეტი არ უნდა დააბრუნოს" -#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 +#: parser/parse_expr.c:2944 parser/parse_expr.c:2985 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "მწკრივის შედარების ოპერატორის %s ინტერპრეტაციის დადგენა შეუძლებელია" -#: parser/parse_expr.c:2930 +#: parser/parse_expr.c:2946 #, c-format msgid "Row comparison operators must be associated with btree operator families." msgstr "მწკრივის შედარების ოპერატორები ბინარული ხის ოპერატორის ოჯახებთან უნდა იყოს ასოცირებული." -#: parser/parse_expr.c:2971 +#: parser/parse_expr.c:2987 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "" -#: parser/parse_expr.c:3064 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "IS DISTINCT FROM-ს სჭირდება, რომ ოპერატორი '=' ლოგიკურ მნიშვნელობას აბრუნებდეს" - -#: parser/parse_expr.c:3304 +#: parser/parse_expr.c:3322 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "" -#: parser/parse_expr.c:3368 +#: parser/parse_expr.c:3386 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "" -#: parser/parse_expr.c:3369 +#: parser/parse_expr.c:3387 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "" -#: parser/parse_expr.c:3458 +#: parser/parse_expr.c:3476 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "'JSON' ფორმატის არა-სტრიქონის გამოტანის ტიპებთან ერთად გამოყენება შეუძლებელია" -#: parser/parse_expr.c:3471 +#: parser/parse_expr.c:3489 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "" -#: parser/parse_expr.c:3476 +#: parser/parse_expr.c:3494 #, c-format msgid "unsupported JSON encoding" msgstr "\"JSON\"-ის არასწორი კოდირება" -#: parser/parse_expr.c:3477 +#: parser/parse_expr.c:3495 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "მხარდაჭერილია მხოლოდ UTF8 JSON კოდირება." -#: parser/parse_expr.c:3514 +#: parser/parse_expr.c:3532 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "" -#: parser/parse_expr.c:3519 +#: parser/parse_expr.c:3537 #, c-format msgid "returning pseudo-types is not supported in SQL/JSON functions" msgstr "ფსევდოტიპების დაბრუნება SQL/JSON ფუნქციებში მხარდაჭერილი არაა" -#: parser/parse_expr.c:3841 parser/parse_func.c:866 +#: parser/parse_expr.c:3865 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "ფანჯრის ფუნქციებისთვის აგრეგატული ORDER BY განხორციელებული არაა" -#: parser/parse_expr.c:4063 +#: parser/parse_expr.c:4088 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "" -#: parser/parse_expr.c:4083 +#: parser/parse_expr.c:4108 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "%s ტიპის IS JSON პრედიკატში გამოყენება შეუძლებელია" -#: parser/parse_expr.c:4109 parser/parse_expr.c:4229 +#: parser/parse_expr.c:4134 parser/parse_expr.c:4255 +#, c-format +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "%s ტიპის გამოყენება %s-ის RETURNING პირობაში შეუძლებელია" + +#: parser/parse_expr.c:4136 #, c-format -msgid "cannot use RETURNING type %s in %s" -msgstr "'RETURNING'-ის ტიპს '%s' %s-ში ვერ გამოიყენებთ" +msgid "Try returning json or jsonb." +msgstr "" -#: parser/parse_expr.c:4158 +#: parser/parse_expr.c:4184 #, c-format msgid "cannot use non-string types with WITH UNIQUE KEYS clause" msgstr "" -#: parser/parse_expr.c:4232 +#: parser/parse_expr.c:4258 #, c-format msgid "Try returning a string type or bytea." msgstr "" -#: parser/parse_expr.c:4297 +#: parser/parse_expr.c:4323 #, c-format msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" msgstr "" -#: parser/parse_expr.c:4309 +#: parser/parse_expr.c:4336 #, c-format msgid "SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" msgstr "" -#: parser/parse_expr.c:4336 +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4350 parser/parse_expr.c:4379 parser/parse_expr.c:4410 parser/parse_expr.c:4436 parser/parse_expr.c:4462 parser/parse_jsontable.c:92 +#, c-format +msgid "invalid %s behavior" +msgstr "%s-ის არასწორი ქცევა" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4353 parser/parse_expr.c:4382 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s." +msgstr "" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4360 parser/parse_expr.c:4389 parser/parse_expr.c:4418 parser/parse_expr.c:4446 parser/parse_expr.c:4472 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "%s-ის არასწორი ქცევა სვეტისთვის \"%s\"" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4363 parser/parse_expr.c:4392 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns." +msgstr "" + +#: parser/parse_expr.c:4411 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4421 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4439 parser/parse_expr.c:4465 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4449 parser/parse_expr.c:4475 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "" + +#: parser/parse_expr.c:4505 #, c-format msgid "JSON path expression must be of type %s, not of type %s" msgstr "JSON ბილიკის გამოსახულების ტიპი %s უნდა იყოს და არა %s" -#: parser/parse_expr.c:4677 +#: parser/parse_expr.c:4723 #, c-format msgid "can only specify a constant, non-aggregate function, or operator expression for DEFAULT" msgstr "" -#: parser/parse_expr.c:4682 +#: parser/parse_expr.c:4728 #, c-format msgid "DEFAULT expression must not contain column references" msgstr "DEFAULT გამოსახულება სვეტზე მიმართვებს არ უნდა შეიცავდეს" -#: parser/parse_expr.c:4687 +#: parser/parse_expr.c:4733 #, c-format msgid "DEFAULT expression must not return a set" msgstr "DEFAULT გამოსახულებამ სეტი არ უნდა დააბრუნოს" -#: parser/parse_expr.c:4721 +#: parser/parse_expr.c:4809 parser/parse_expr.c:4818 #, c-format msgid "cannot cast behavior expression of type %s to %s" msgstr "%s ქცევის გამოსახულების ტიპის %s-ში გადაყვანა შეუძლებელია" +#: parser/parse_expr.c:4812 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "დაგჭირდებათ გამოსახულების აშკარად გადაყვანა ტიპში %s." + #: parser/parse_func.c:194 #, c-format msgid "argument name \"%s\" used more than once" @@ -18214,26 +18744,16 @@ msgstr "სეტების დამბრუნებელი ფუნქ msgid "set-returning functions are not allowed in column generation expressions" msgstr "სეტების დამბრუნებელი ფუნქციების სვეტების გენერაციის გამოსახულებებში გამოყენება აკრძალულია" -#: parser/parse_jsontable.c:94 -#, c-format -msgid "invalid ON ERROR behavior" -msgstr "\"ON UPDATE\"-ის არასწორი ქცევა" - -#: parser/parse_jsontable.c:95 +#: parser/parse_jsontable.c:93 #, c-format -msgid "Only EMPTY or ERROR is allowed in the top-level ON ERROR clause." +msgid "Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." msgstr "" -#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#: parser/parse_jsontable.c:187 parser/parse_jsontable.c:201 #, c-format msgid "duplicate JSON_TABLE column or path name: %s" msgstr "დუბლირებული JSON_TABLE სვეტის ან ბილიკის სახელი: %s" -#: parser/parse_jsontable.c:295 -#, c-format -msgid "cannot use more than one FOR ORDINALITY column" -msgstr "ერთზე მეტ FOR ORDINALITY სვეტს ვერ გამოიყენებთ" - #: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" @@ -18309,227 +18829,222 @@ msgstr "" msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "" -#: parser/parse_param.c:221 +#: parser/parse_param.c:222 #, c-format msgid "inconsistent types deduced for parameter $%d" msgstr "" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:310 tcop/postgres.c:734 #, c-format msgid "could not determine data type of parameter $%d" msgstr "პარამეტრისთვის $%d მონაცემის ტიპის განსაზღვრა შეუძლებელია" -#: parser/parse_relation.c:221 +#: parser/parse_relation.c:226 #, c-format msgid "table reference \"%s\" is ambiguous" msgstr "" -#: parser/parse_relation.c:265 +#: parser/parse_relation.c:273 #, c-format msgid "table reference %u is ambiguous" msgstr "" -#: parser/parse_relation.c:465 -#, c-format -msgid "table name \"%s\" specified more than once" -msgstr "" - -#: parser/parse_relation.c:494 parser/parse_relation.c:3633 parser/parse_relation.c:3642 +#: parser/parse_relation.c:502 parser/parse_relation.c:3739 parser/parse_relation.c:3748 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "" -#: parser/parse_relation.c:498 parser/parse_relation.c:3644 +#: parser/parse_relation.c:506 parser/parse_relation.c:3750 #, c-format msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query." msgstr "" -#: parser/parse_relation.c:500 +#: parser/parse_relation.c:508 #, c-format msgid "The combining JOIN type must be INNER or LEFT for a LATERAL reference." msgstr "" -#: parser/parse_relation.c:703 +#: parser/parse_relation.c:711 #, c-format msgid "system column \"%s\" reference in check constraint is invalid" msgstr "" -#: parser/parse_relation.c:712 +#: parser/parse_relation.c:724 #, c-format msgid "cannot use system column \"%s\" in column generation expression" msgstr "სვეტის გენერაციის გამოსახულებაში სისტემურ სვეტს \"%s\" ვერ გამოიყენებთ" -#: parser/parse_relation.c:723 +#: parser/parse_relation.c:735 #, c-format msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "'MERGE WHEN' პირობაში სისტემურ სვეტს \"%s\" ვერ გამოიყენებთ" -#: parser/parse_relation.c:1236 parser/parse_relation.c:1691 parser/parse_relation.c:2384 +#: parser/parse_relation.c:1251 parser/parse_relation.c:1708 parser/parse_relation.c:2402 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "" -#: parser/parse_relation.c:1445 +#: parser/parse_relation.c:1462 #, c-format msgid "There is a WITH item named \"%s\", but it cannot be referenced from this part of the query." msgstr "" -#: parser/parse_relation.c:1447 +#: parser/parse_relation.c:1464 #, c-format msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references." msgstr "" -#: parser/parse_relation.c:1833 +#: parser/parse_relation.c:1850 #, c-format msgid "a column definition list is redundant for a function with OUT parameters" msgstr "" -#: parser/parse_relation.c:1839 +#: parser/parse_relation.c:1856 #, c-format msgid "a column definition list is redundant for a function returning a named composite type" msgstr "" -#: parser/parse_relation.c:1846 +#: parser/parse_relation.c:1863 #, c-format msgid "a column definition list is only allowed for functions returning \"record\"" msgstr "" -#: parser/parse_relation.c:1857 +#: parser/parse_relation.c:1874 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "" -#: parser/parse_relation.c:1894 +#: parser/parse_relation.c:1911 #, c-format msgid "column definition lists can have at most %d entries" msgstr "სვეტის აღწერის სიებს მაქსიმუმ %d ჩანაწერი შეიძლება ჰქონდეს" -#: parser/parse_relation.c:1954 +#: parser/parse_relation.c:1971 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "" -#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 +#: parser/parse_relation.c:1998 parser/parse_relation.c:2083 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "ფუნქციებს FROM-შ მაქსიმუმ %d სვეტის დაბრუნება შეუძლიათ" -#: parser/parse_relation.c:2096 +#: parser/parse_relation.c:2113 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "ფუნქციას %s %d სვეტი ჰქონდა ხელმისაწვდომი, მითითებული კი %d" -#: parser/parse_relation.c:2177 +#: parser/parse_relation.c:2194 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "" -#: parser/parse_relation.c:2242 +#: parser/parse_relation.c:2259 #, c-format msgid "joins can have at most %d columns" msgstr "შეერთებებს მაქსიმუმ %d სვეტი შეიძლება, ჰქონდეთ" -#: parser/parse_relation.c:2267 +#: parser/parse_relation.c:2284 #, c-format msgid "join expression \"%s\" has %d columns available but %d columns specified" msgstr "" -#: parser/parse_relation.c:2357 +#: parser/parse_relation.c:2375 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "WITH მოთხოვნას \"%s\" RETURNING პირობა არ გააჩნია" -#: parser/parse_relation.c:3635 +#: parser/parse_relation.c:3741 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "" -#: parser/parse_relation.c:3647 +#: parser/parse_relation.c:3753 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "" -#: parser/parse_relation.c:3653 +#: parser/parse_relation.c:3759 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "" -#: parser/parse_relation.c:3693 +#: parser/parse_relation.c:3799 #, c-format msgid "There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query." msgstr "" -#: parser/parse_relation.c:3695 +#: parser/parse_relation.c:3801 #, c-format msgid "Try using a table-qualified name." msgstr "" -#: parser/parse_relation.c:3703 +#: parser/parse_relation.c:3809 #, c-format msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." msgstr "" -#: parser/parse_relation.c:3706 +#: parser/parse_relation.c:3812 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "" -#: parser/parse_relation.c:3708 +#: parser/parse_relation.c:3814 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "" -#: parser/parse_relation.c:3728 +#: parser/parse_relation.c:3834 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "" -#: parser/parse_relation.c:3742 +#: parser/parse_relation.c:3848 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "" -#: parser/parse_target.c:480 parser/parse_target.c:795 +#: parser/parse_target.c:483 parser/parse_target.c:798 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "სისტემური სვეტზე (%s) მინიჭება შეუძლებელია" -#: parser/parse_target.c:508 +#: parser/parse_target.c:511 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "მასივის ელემენტების DEFAULT-ზე დაყენება შეუძლებელია" -#: parser/parse_target.c:513 +#: parser/parse_target.c:516 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "ქვეველის DEFAULT მნიშვნელობის დაყენების შეცდომა" -#: parser/parse_target.c:587 +#: parser/parse_target.c:590 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "" -#: parser/parse_target.c:779 +#: parser/parse_target.c:782 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type" msgstr "" -#: parser/parse_target.c:788 +#: parser/parse_target.c:791 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s" msgstr "" -#: parser/parse_target.c:877 +#: parser/parse_target.c:880 #, c-format msgid "subscripted assignment to \"%s\" requires type %s but expression is of type %s" msgstr "" -#: parser/parse_target.c:887 +#: parser/parse_target.c:890 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "" -#: parser/parse_target.c:1327 +#: parser/parse_target.c:1330 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "" @@ -18549,7 +19064,7 @@ msgstr "" msgid "type reference %s converted to %s" msgstr "ტიპის მიმართვა %s გადაყვანილია %s-ში" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 utils/cache/typcache.c:452 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:478 utils/cache/typcache.c:533 #, c-format msgid "type \"%s\" is only a shell" msgstr "ტიპი \"%s\" მხოლოდ გარსია" @@ -18569,337 +19084,352 @@ msgstr "ტიპის მოდიფიკატორების მარ msgid "invalid type name \"%s\"" msgstr "ტიპის არასწორი სახელი: \"%s\"" -#: parser/parse_utilcmd.c:266 +#: parser/parse_utilcmd.c:265 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "" -#: parser/parse_utilcmd.c:586 +#: parser/parse_utilcmd.c:504 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "დროებითი თანმიმდევრობის სტატუსის დადგენა შეუძლებელია" + +#: parser/parse_utilcmd.c:642 #, c-format msgid "array of serial is not implemented" msgstr "სერიალების მასივი განხორციელებული არაა" -#: parser/parse_utilcmd.c:665 parser/parse_utilcmd.c:677 parser/parse_utilcmd.c:736 +#: parser/parse_utilcmd.c:747 parser/parse_utilcmd.c:765 parser/parse_utilcmd.c:873 parser/parse_utilcmd.c:906 #, c-format msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:689 +#: parser/parse_utilcmd.c:759 parser/parse_utilcmd.c:1077 +#, c-format +msgid "not-null constraints on partitioned tables cannot be NO INHERIT" +msgstr "არანულოვანი შეზღუდვები დაყოფილ ცხრილზე NO INHERIT ვერ იქნება" + +#: parser/parse_utilcmd.c:773 parser/parse_utilcmd.c:808 +#, c-format +msgid "conflicting NO INHERIT declarations for not-null constraints on column \"%s\"" +msgstr "ურთიერთგამომრიცხავი NO INHERIT აღწერები არანულოვანი შეზღუდვებისთვის სვეტზე \"%s\"" + +#: parser/parse_utilcmd.c:821 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:706 +#: parser/parse_utilcmd.c:838 #, c-format msgid "identity columns are not supported on typed tables" msgstr "ტიპიზირებულ ცხრილებზე იდენტიფიკაციის სვეტები მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:710 +#: parser/parse_utilcmd.c:842 #, c-format msgid "identity columns are not supported on partitions" msgstr "დანაყოფებზე იდენტიფიკაციის სვეტები მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:719 +#: parser/parse_utilcmd.c:851 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:749 +#: parser/parse_utilcmd.c:884 #, c-format msgid "generated columns are not supported on typed tables" msgstr "ტიპიზირებულ ცხრილებზე გენერირებული სვეტები მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:753 +#: parser/parse_utilcmd.c:888 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:771 parser/parse_utilcmd.c:886 +#: parser/parse_utilcmd.c:915 parser/parse_utilcmd.c:1043 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "ძირითადი გასაღების შეზღუდვები გარე ცხრილებზე მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:780 parser/parse_utilcmd.c:896 +#: parser/parse_utilcmd.c:924 parser/parse_utilcmd.c:1053 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "გარე ცხრილებზე უნიკალური შეზღუდვები მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:825 +#: parser/parse_utilcmd.c:971 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:833 +#: parser/parse_utilcmd.c:979 #, c-format msgid "both default and generation expression specified for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:841 +#: parser/parse_utilcmd.c:987 #, c-format msgid "both identity and generation expression specified for column \"%s\" of table \"%s\"" msgstr "" -#: parser/parse_utilcmd.c:906 +#: parser/parse_utilcmd.c:1063 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "" -#: parser/parse_utilcmd.c:971 -#, c-format -msgid "LIKE is not supported for creating foreign tables" -msgstr "გარე ცხრილების შექმნისთვის LIKE მხარდაჭერილი არაა" - -#: parser/parse_utilcmd.c:984 +#: parser/parse_utilcmd.c:1149 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "პირობაში LIKE ურთიერთობა \"%s\" არასწორია" -#: parser/parse_utilcmd.c:1711 parser/parse_utilcmd.c:1819 +#: parser/parse_utilcmd.c:1896 parser/parse_utilcmd.c:2004 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "" -#: parser/parse_utilcmd.c:2217 +#: parser/parse_utilcmd.c:2398 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "'CREATE TABLE'-ში არსებულ ინდექსს ვერ გამოიყენებთ" -#: parser/parse_utilcmd.c:2237 +#: parser/parse_utilcmd.c:2418 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "ინდექსი \"%s\" შეზღუდვასთან უკვე ასოცირებულია" -#: parser/parse_utilcmd.c:2258 +#: parser/parse_utilcmd.c:2444 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\" უნიკალური ინდექსი არაა" -#: parser/parse_utilcmd.c:2259 parser/parse_utilcmd.c:2266 parser/parse_utilcmd.c:2273 parser/parse_utilcmd.c:2350 +#: parser/parse_utilcmd.c:2445 parser/parse_utilcmd.c:2452 parser/parse_utilcmd.c:2459 parser/parse_utilcmd.c:2535 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "" -#: parser/parse_utilcmd.c:2265 +#: parser/parse_utilcmd.c:2451 #, c-format msgid "index \"%s\" contains expressions" msgstr "ინდექსი \"%s\" გამოსახულებებს შეიცავს" -#: parser/parse_utilcmd.c:2272 +#: parser/parse_utilcmd.c:2458 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\" ნაწილობრივი ინდექსია" -#: parser/parse_utilcmd.c:2284 +#: parser/parse_utilcmd.c:2470 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\" გადადებადი ინდექსია" -#: parser/parse_utilcmd.c:2285 +#: parser/parse_utilcmd.c:2471 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "" -#: parser/parse_utilcmd.c:2349 +#: parser/parse_utilcmd.c:2534 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "" -#: parser/parse_utilcmd.c:2506 +#: parser/parse_utilcmd.c:2726 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "" -#: parser/parse_utilcmd.c:2512 +#: parser/parse_utilcmd.c:2732 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "" -#: parser/parse_utilcmd.c:2846 +#: parser/parse_utilcmd.c:2777 +#, c-format +msgid "column \"%s\" in WITHOUT OVERLAPS is not a range or multirange type" +msgstr "" + +#: parser/parse_utilcmd.c:2805 +#, c-format +msgid "constraint using WITHOUT OVERLAPS needs at least two columns" +msgstr "" + +#: parser/parse_utilcmd.c:3102 #, c-format msgid "index expressions and predicates can refer only to the table being indexed" msgstr "" -#: parser/parse_utilcmd.c:2918 +#: parser/parse_utilcmd.c:3174 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "" -#: parser/parse_utilcmd.c:2961 +#: parser/parse_utilcmd.c:3217 #, c-format msgid "rules on materialized views are not supported" msgstr "მატერიალიზებულ ხედებზე წესები მხარდაჭერილი არაა" -#: parser/parse_utilcmd.c:3021 +#: parser/parse_utilcmd.c:3277 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "" -#: parser/parse_utilcmd.c:3093 +#: parser/parse_utilcmd.c:3349 #, c-format msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions" msgstr "" -#: parser/parse_utilcmd.c:3111 parser/parse_utilcmd.c:3212 rewrite/rewriteHandler.c:537 rewrite/rewriteManip.c:1095 +#: parser/parse_utilcmd.c:3367 parser/parse_utilcmd.c:3468 rewrite/rewriteHandler.c:546 rewrite/rewriteManip.c:1234 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "პირობითი UNION/INTERSECT/EXCEPT ოპერატორები განხორციელებული არაა" -#: parser/parse_utilcmd.c:3129 +#: parser/parse_utilcmd.c:3385 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "ON SELECT წესში OLD-ს ვერ გამოიყენებთ" -#: parser/parse_utilcmd.c:3133 +#: parser/parse_utilcmd.c:3389 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "ON SELECT წესში NEW-ს ვერ გამოიყენებთ" -#: parser/parse_utilcmd.c:3142 +#: parser/parse_utilcmd.c:3398 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "ON INSERT წესში OLD-ს ვერ გამოიყენებთ" -#: parser/parse_utilcmd.c:3148 +#: parser/parse_utilcmd.c:3404 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "ON DELETE წესში NEW-ს ვერ გამოიყენებთ" -#: parser/parse_utilcmd.c:3176 +#: parser/parse_utilcmd.c:3432 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "'WITH' მოთხოვნაში OLD-ზე მიმართვა შეუძლებელია" -#: parser/parse_utilcmd.c:3183 +#: parser/parse_utilcmd.c:3439 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "'WITH' მოთხოვნაში NEW-ზე მიმართვა შეუძლებელია" -#: parser/parse_utilcmd.c:3255 -#, c-format -msgid "\"%s\" is not a partition" -msgstr "\"%s\" დანაყოფი არაა" - -#: parser/parse_utilcmd.c:3290 parser/parse_utilcmd.c:3335 parser/parse_utilcmd.c:4101 -#, c-format -msgid "\"%s\" is not a partitioned table" -msgstr "\"%s\" დაყოფილი ცხრილი არაა" - -#: parser/parse_utilcmd.c:3343 -#, c-format -msgid "partition of hash-partitioned table cannot be merged" -msgstr "ჰეშით დაყოფილი ცხრილის დანაყოფების შერწყმა შეუძლებელია" - -#: parser/parse_utilcmd.c:3361 -#, c-format -msgid "partition with name \"%s\" is already used" -msgstr "დანაყოფი სახელით \"%s\" უკვე გამოყენებულია" - -#: parser/parse_utilcmd.c:3673 -#, c-format -msgid "list of new partitions should contain at least two items" -msgstr "" - -#: parser/parse_utilcmd.c:3811 +#: parser/parse_utilcmd.c:3897 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "არასწორ ადგილას დასმული DEFERRABLE პირობა" -#: parser/parse_utilcmd.c:3816 parser/parse_utilcmd.c:3831 +#: parser/parse_utilcmd.c:3902 parser/parse_utilcmd.c:3917 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "ერთზე მეტი DEFERRABLE/NOT DEFERRABLE პირობა დაშვებული არაა" -#: parser/parse_utilcmd.c:3826 +#: parser/parse_utilcmd.c:3912 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "არასწორ ადგილას დასმული NOT DEFERRABLE პირობა" -#: parser/parse_utilcmd.c:3847 +#: parser/parse_utilcmd.c:3933 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "არასწორ ადგილას დასმული INITIALLY DEFERRABLE პირობა" -#: parser/parse_utilcmd.c:3852 parser/parse_utilcmd.c:3878 +#: parser/parse_utilcmd.c:3938 parser/parse_utilcmd.c:3964 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "ერთზე მეტი INITIALLY IMMEDIATE/DEFERRED დაშვებული არაა" -#: parser/parse_utilcmd.c:3873 +#: parser/parse_utilcmd.c:3959 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "არასწორ ადგილას დასმული INITIALLY IMMEDIATE პირობა" -#: parser/parse_utilcmd.c:4066 +#: parser/parse_utilcmd.c:3976 +#, c-format +msgid "misplaced ENFORCED clause" +msgstr "არასწორ ადგილას დასმული ENFORCED პირობა" + +#: parser/parse_utilcmd.c:3981 parser/parse_utilcmd.c:3998 +#, c-format +msgid "multiple ENFORCED/NOT ENFORCED clauses not allowed" +msgstr "ერთზე მეტი ENFORCED/NOT ENFORCED პირობა დაშვებული არაა" + +#: parser/parse_utilcmd.c:3993 +#, c-format +msgid "misplaced NOT ENFORCED clause" +msgstr "არასწორ ადგილას დასმული NOT ENFORCED პირობა" + +#: parser/parse_utilcmd.c:4191 #, c-format msgid "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "" -#: parser/parse_utilcmd.c:4108 +#: parser/parse_utilcmd.c:4226 +#, c-format +msgid "\"%s\" is not a partitioned table" +msgstr "\"%s\" დაყოფილი ცხრილი არაა" + +#: parser/parse_utilcmd.c:4233 #, c-format msgid "table \"%s\" is not partitioned" msgstr "ცხრილი \"%s\" დაყოფილი არაა" -#: parser/parse_utilcmd.c:4115 +#: parser/parse_utilcmd.c:4240 #, c-format msgid "index \"%s\" is not partitioned" msgstr "ინდექსი \"%s\" დაყოფილი არაა" -#: parser/parse_utilcmd.c:4155 +#: parser/parse_utilcmd.c:4280 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "" -#: parser/parse_utilcmd.c:4172 +#: parser/parse_utilcmd.c:4297 #, c-format msgid "invalid bound specification for a hash partition" msgstr "" -#: parser/parse_utilcmd.c:4178 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4303 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "" -#: parser/parse_utilcmd.c:4185 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4310 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "" -#: parser/parse_utilcmd.c:4198 +#: parser/parse_utilcmd.c:4323 #, c-format msgid "invalid bound specification for a list partition" msgstr "" -#: parser/parse_utilcmd.c:4251 +#: parser/parse_utilcmd.c:4376 #, c-format msgid "invalid bound specification for a range partition" msgstr "" -#: parser/parse_utilcmd.c:4257 +#: parser/parse_utilcmd.c:4382 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "" -#: parser/parse_utilcmd.c:4261 +#: parser/parse_utilcmd.c:4386 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "" -#: parser/parse_utilcmd.c:4375 +#: parser/parse_utilcmd.c:4500 #, c-format msgid "cannot specify NULL in range bound" msgstr "დიაპაზონის საზღვრებში NULL-ის მითითება შეუძლებელია" -#: parser/parse_utilcmd.c:4424 +#: parser/parse_utilcmd.c:4549 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "ყოველი MAXVALUE საზღვის შემდეგ ყველა MAXVALUE უნდა იყოს" -#: parser/parse_utilcmd.c:4431 +#: parser/parse_utilcmd.c:4556 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "ყოველი MINVALUE საზღვის შემდეგ ყველა MINVALUE უნდა იყოს" -#: parser/parse_utilcmd.c:4474 +#: parser/parse_utilcmd.c:4599 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "" @@ -18912,12 +19442,12 @@ msgstr "" msgid "invalid Unicode escape character" msgstr "უნიკოდის სპეცკოდის არასწორი სიმბოლო" -#: parser/parser.c:347 scan.l:1391 +#: parser/parser.c:347 scan.l:1385 #, c-format msgid "invalid Unicode escape value" msgstr "უნიკოდის სპეცკოდის არასწორი მნიშვნელობა" -#: parser/parser.c:494 scan.l:702 utils/adt/varlena.c:6640 +#: parser/parser.c:494 scan.l:702 utils/adt/varlena.c:6842 #, c-format msgid "invalid Unicode escape" msgstr "უნიკოდის არასწორი სპეცკოდი" @@ -18927,7 +19457,7 @@ msgstr "უნიკოდის არასწორი სპეცკოდ msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "უნიკოდის სპეცკოდების შესაძლო ვარიანტებია \\XXXX და \\+XXXXXXXX." -#: parser/parser.c:523 scan.l:663 scan.l:679 scan.l:695 utils/adt/varlena.c:6665 +#: parser/parser.c:523 scan.l:663 scan.l:679 scan.l:695 utils/adt/varlena.c:6867 #, c-format msgid "invalid Unicode surrogate pair" msgstr "უნკოდის არასწორი სუროგატული წყვილი" @@ -18957,127 +19487,52 @@ msgstr "" msgid "The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\"." msgstr "" -#: partitioning/partbounds.c:3127 partitioning/partbounds.c:5202 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "" -#: partitioning/partbounds.c:3129 partitioning/partbounds.c:5204 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "" -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "დანაყოფი \"%s\" გადაფარავდა დანაყოფს \"%s\"" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"" msgstr "" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "remainder for hash partition must be an integer value greater than or equal to zero" msgstr "" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\" ჰეშით დაყოფილი ცხრილია" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" msgstr "დამყოფი სვეტების რაოდენობა (%d) მოწოდებული დაყოფის გასაღებების რაოდენობას (%d) არ ემთხვევა" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"" msgstr "" -#: partitioning/partbounds.c:5038 -#, c-format -msgid "lower bound of partition \"%s\" conflicts with upper bound of previous partition \"%s\"" -msgstr "დანაყოფის \"%s\" ქვედა ზღვარი კონფლიქტშია ზედა ზღვართან წინა დანაყოფისთვის \"%s\"" - -#: partitioning/partbounds.c:5092 -#, c-format -msgid "new partition \"%s\" would overlap with another new partition \"%s\"" -msgstr "ახალი დანაყოფი \"%s\" გადაფარავდა სხვა ახალ დანაყოფს \"%s\"" - -#: partitioning/partbounds.c:5239 -#, c-format -msgid "lower bound of partition \"%s\" is not equal to lower bound of split partition" -msgstr "ქვედა ზღვარი დანაყოფისთვის \"%s\" არ უდრის დაყოფილი დანაყოფის ქვედა საზღვარს" - -#: partitioning/partbounds.c:5251 -#, c-format -msgid "lower bound of partition \"%s\" is less than lower bound of split partition" -msgstr "ქვედა ზღვარი დანაყოფისთვის \"%s\" დაყოფილი დანაყოფის ქვედა საზღვარზე ნაკლებია" - -#: partitioning/partbounds.c:5280 -#, c-format -msgid "upper bound of partition \"%s\" is not equal to upper bound of split partition" -msgstr "ზედა ზღვარი დანაყოფისთვის \"%s\" არ უდრის დაყოფილი დანაყოფის ზედა საზღვარს" - -#: partitioning/partbounds.c:5292 -#, c-format -msgid "upper bound of partition \"%s\" is greater than upper bound of split partition" -msgstr "ზედა ზღვარი დანაყოფისთვის \"%s\" დაყოფილი დანაყოფის ზედა საზღვარზე მეტია" - -#: partitioning/partbounds.c:5364 -#, c-format -msgid "new partition \"%s\" cannot have this value because split partition does not have" -msgstr "" - -#: partitioning/partbounds.c:5380 -#, c-format -msgid "new partition \"%s\" cannot have NULL value because split partition does not have" -msgstr "" - -#: partitioning/partbounds.c:5390 -#, c-format -msgid "new partition \"%s\" would overlap with another (not split) partition \"%s\"" -msgstr "ახალი დანაყოფი \"%s\" გადაფარავდა სხვა (არა დაყოფილ) დანაყოფს \"%s\"" - -#: partitioning/partbounds.c:5530 -#, c-format -msgid "new partitions do not have value %s but split partition does" -msgstr "ახალ დანაყოფს არ აქვს მნიშვნელობა %s, მაგრამ გაყოფილ დანაყოფს აქვს" - -#: partitioning/partbounds.c:5607 -#, c-format -msgid "DEFAULT partition should be one" -msgstr "" - -#: partitioning/partbounds.c:5623 -#, c-format -msgid "partition of hash-partitioned table cannot be split" -msgstr "ჰეშით დაყოფილი ცხრილის დანაყოფების დაყოფა შეუძლებელია" - -#: partitioning/partbounds.c:5677 -#, c-format -msgid "one partition in the list should be DEFAULT because split partition is DEFAULT" -msgstr "" - -#: partitioning/partbounds.c:5687 -#, c-format -msgid "new partition cannot be DEFAULT because DEFAULT partition already exists" -msgstr "" - -#: partitioning/partbounds.c:5746 -#, c-format -msgid "name \"%s\" is already used" -msgstr "სახელი \"%s\" უკვე გამოყენებულია" - -#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 port/sysv_sema.c:323 port/sysv_shmem.c:717 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "მონაცემების საქაღალდის (%s) პოვნა შეუძლებელია: %m" @@ -19138,34 +19593,34 @@ msgstr "ამ პლატფორმაზე უზარმაზარი msgid "huge pages not supported with the current \"shared_memory_type\" setting" msgstr "\"shared_memory_type\" პარამეტრთან ერთად უზარმაზარი გვერდები მხარდაჭერილი არაა" -#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1347 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1406 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "უკვე არსებული გაზიარებული მეხსიერების ბლოკი (გასაღები %lu, ID %lu) ჯერ კიდევ გამოიყენება" -#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1349 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1408 #, c-format msgid "Terminate any old server processes associated with data directory \"%s\"." msgstr "" -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "სემაფორების შექმნის შეცდომა: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "ავარიული სისტემური ფუნქცია იყო semget(%lu, %d, 0%o)." -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its \"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring your system for PostgreSQL." msgstr "" -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details." msgstr "" @@ -19287,387 +19742,402 @@ msgstr "წარუმატებლად გამოძახებულ msgid "Failed system call was MapViewOfFileEx." msgstr "წარუმატებლად გამოძახებული სისტემური ფუნქცია: MapViewOfFileEx." -#: postmaster/autovacuum.c:686 +#: postmaster/autovacuum.c:693 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "ავტომომტვერსასრუტების დამხმარე პროცესის გაშვებას მეტისმეტად დიდი დრო მოუნდა. ის გაუქმდა" -#: postmaster/autovacuum.c:2199 +#: postmaster/autovacuum.c:2221 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "ავტომომტვერსასრუტება: წაიშლება მიტოვებული დროებითი ცხრილი \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2435 +#: postmaster/autovacuum.c:2457 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "ცხრილის ავტოდამტვერსასრუტება: \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2438 +#: postmaster/autovacuum.c:2460 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "ცხრილის ავტოანალიზი: \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2632 +#: postmaster/autovacuum.c:2654 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "" -#: postmaster/autovacuum.c:3250 +#: postmaster/autovacuum.c:3312 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "ავტომომტვერსასრუტება არ გაშვებულა კონფიგურაციის შეცდომის გამო" -#: postmaster/autovacuum.c:3251 +#: postmaster/autovacuum.c:3313 #, c-format msgid "Enable the \"track_counts\" option." msgstr "ჩართეთ \"track_counts\" პარამეტრი." +#: postmaster/autovacuum.c:3435 +#, c-format +msgid "\"autovacuum_max_workers\" (%d) should be less than or equal to \"autovacuum_worker_slots\" (%d)" +msgstr "" + +#: postmaster/autovacuum.c:3437 +#, c-format +msgid "The server will only start up to \"autovacuum_worker_slots\" (%d) autovacuum workers at a given time." +msgstr "" + #: postmaster/bgworker.c:260 #, c-format -msgid "inconsistent background worker state (max_worker_processes=%d, total_slots=%d)" +msgid "inconsistent background worker state (\"max_worker_processes\"=%d, total slots=%d)" msgstr "" -#: postmaster/bgworker.c:651 +#: postmaster/bgworker.c:645 #, c-format msgid "background worker \"%s\": background workers without shared memory access are not supported" msgstr "" -#: postmaster/bgworker.c:662 +#: postmaster/bgworker.c:656 #, c-format msgid "background worker \"%s\": cannot request database access if starting at postmaster start" msgstr "" -#: postmaster/bgworker.c:676 +#: postmaster/bgworker.c:670 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "ფონური დამხმარე პროცესი \"%s\": არასწორი გადატვირთვის ინტერვალი" -#: postmaster/bgworker.c:691 +#: postmaster/bgworker.c:685 #, c-format msgid "background worker \"%s\": parallel workers may not be configured for restart" msgstr "" -#: postmaster/bgworker.c:715 tcop/postgres.c:3285 +#: postmaster/bgworker.c:709 tcop/postgres.c:3345 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "" -#: postmaster/bgworker.c:888 +#: postmaster/bgworker.c:868 postmaster/bgworker.c:902 +#, c-format +msgid "database connection requirement not indicated during registration" +msgstr "" + +#: postmaster/bgworker.c:878 postmaster/bgworker.c:912 +#, c-format +msgid "invalid processing mode in background worker" +msgstr "არასწორი დამუშავების რეჟიმი ფონურ დამხმარე პროცესში" + +#: postmaster/bgworker.c:965 #, c-format msgid "background worker \"%s\": must be registered in \"shared_preload_libraries\"" msgstr "ფონური დამხმარე პროცესი \"%s\": \"shared_preload_libraries\"-ში დარეგისტრირებული უნდა იყოს" -#: postmaster/bgworker.c:911 +#: postmaster/bgworker.c:988 #, c-format msgid "background worker \"%s\": only dynamic background workers can request notification" msgstr "ფონური დახმამრე პროცესი \"%s\": გაფრთხილების მოთხოვნა მხოლოდ დინამიკურ ფონურ დამხმარე პროცესებს შეუძლიათ" -#: postmaster/bgworker.c:926 +#: postmaster/bgworker.c:1003 #, c-format msgid "too many background workers" msgstr "მეტისმეტად ბევრი ფონური დამხმარე პროცესი" -#: postmaster/bgworker.c:927 +#: postmaster/bgworker.c:1004 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "Up to %d background workers can be registered with the current settings." msgstr[0] "" msgstr[1] "" -#: postmaster/bgworker.c:931 +#: postmaster/bgworker.c:1008 postmaster/checkpointer.c:459 #, c-format -msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "გაითვალისწინეთ, რომ შეიძლება კონფიგურაციის პარამეტრის \"max_worker_processes\" გაზრდა გჭირდებათ." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "გაითვალისწინეთ, რომ შეიძლება კონფიგურაციის პარამეტრის \"%s\" გაზრდა გჭირდებათ." -#: postmaster/checkpointer.c:441 +#: postmaster/checkpointer.c:455 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" msgstr[0] "საკონტროლო წერტილები მეტისმეტად ხშირად ხდება (%d წამიანი შუალედით)" msgstr[1] "საკონტროლო წერტილები მეტისმეტად ხშირად ხდება (%d წამიანი შუალედით)" -#: postmaster/checkpointer.c:445 -#, c-format -msgid "Consider increasing the configuration parameter \"%s\"." -msgstr "გაითვალისწინეთ, რომ შეიძლება კონფიგურაციის პარამეტრის \"%s\" გაზრდა გჭირდებათ." - -#: postmaster/checkpointer.c:1067 +#: postmaster/checkpointer.c:1125 #, c-format msgid "checkpoint request failed" msgstr "საკონტროლო წერტილის მოთხოვნის შეცდომა" -#: postmaster/checkpointer.c:1068 +#: postmaster/checkpointer.c:1126 #, c-format msgid "Consult recent messages in the server log for details." msgstr "დეტალებისთვის იხილეთ სერვერის ჟურნალის უახლესი შეტყობინებები." -#: postmaster/launch_backend.c:369 +#: postmaster/launch_backend.c:395 #, c-format msgid "could not execute server process \"%s\": %m" msgstr "სერვერის პროცესის (\"%s\") შესრულების შეცდომა: %m" -#: postmaster/launch_backend.c:422 +#: postmaster/launch_backend.c:449 #, c-format msgid "could not create backend parameter file mapping: error code %lu" msgstr "უკანაბოლოს პარამეტრის ფაილის მიბმის შექმნის შეცდომა. შეცდომის კოდი: %lu" -#: postmaster/launch_backend.c:430 +#: postmaster/launch_backend.c:457 #, c-format msgid "could not map backend parameter memory: error code %lu" msgstr "უკანაბოლოს პარამეტრის მეხსიერების მიმაგრების პრობლემა: შეცდომის კოდი %lu" -#: postmaster/launch_backend.c:447 +#: postmaster/launch_backend.c:474 #, c-format msgid "subprocess command line too long" msgstr "ქვეპროექტების ბრძანების სტრიქონი ძალიან გრძელია" -#: postmaster/launch_backend.c:465 +#: postmaster/launch_backend.c:492 #, c-format msgid "CreateProcess() call failed: %m (error code %lu)" msgstr "გამოძახების შეცდომა: CreateProcess(): %m (შეცდომის კოდი %lu)" -#: postmaster/launch_backend.c:492 +#: postmaster/launch_backend.c:521 #, c-format msgid "could not unmap view of backend parameter file: error code %lu" msgstr "უკანაბოლოს პარამეტრის ფაილის ხედის მოხსნის შეცდომა. შეცდომის კოდი: %lu" -#: postmaster/launch_backend.c:496 +#: postmaster/launch_backend.c:525 #, c-format msgid "could not close handle to backend parameter file: error code %lu" msgstr "უკანაბოლოს პარამეტრის ფაილის დამმუშავებლის დახურვა შეუძლებელია. შეცდომის კოდი: %lu" -#: postmaster/launch_backend.c:518 +#: postmaster/launch_backend.c:547 #, c-format msgid "giving up after too many tries to reserve shared memory" msgstr "გაზიარებული მეხსიერების გამოყოფის მეტისმეტად ბევრი ცდის შემდეგ შევეშვი ცდას" -#: postmaster/launch_backend.c:519 +#: postmaster/launch_backend.c:548 #, c-format msgid "This might be caused by ASLR or antivirus software." msgstr "ეს შეიძლება გამოწვეული იყოს ASLR ან ანტივირუსული პროგრამული უზრუნველყოფის მიერ." -#: postmaster/launch_backend.c:817 +#: postmaster/launch_backend.c:854 #, c-format msgid "could not duplicate socket %d for use in backend: error code %d" msgstr "" -#: postmaster/launch_backend.c:849 +#: postmaster/launch_backend.c:886 #, c-format msgid "could not create inherited socket: error code %d\n" msgstr "მემკვიდრეობით მიღებული სოკეტის შექმნა შეუძლებელია: შეცდომის კოდი %d\n" -#: postmaster/launch_backend.c:878 +#: postmaster/launch_backend.c:915 #, c-format msgid "could not open backend variables file \"%s\": %m\n" msgstr "უკანაბოლოს ცვლადების ფაილის \"%s\" გახსნა შეუძლებელია: %m\n" -#: postmaster/launch_backend.c:884 +#: postmaster/launch_backend.c:921 #, c-format msgid "could not read from backend variables file \"%s\": %m\n" msgstr "უკანაბოლოს ცვლადების ფაილიდან \"%s\" წაკითხვა შეუძლებელია: %m\n" -#: postmaster/launch_backend.c:895 +#: postmaster/launch_backend.c:932 #, c-format msgid "could not read startup data from backend variables file \"%s\": %m\n" msgstr "უკანაბოლოს ცვლადების ფაილიდან \"%s\" გაშვების მონაცემების წაკითხვა შეუძლებელია: %m\n" -#: postmaster/launch_backend.c:907 +#: postmaster/launch_backend.c:944 #, c-format msgid "could not remove file \"%s\": %m\n" msgstr "ფაილის წაშლის შეცდომა \"%s\": %m\n" -#: postmaster/launch_backend.c:923 +#: postmaster/launch_backend.c:960 #, c-format msgid "could not map view of backend variables: error code %lu\n" msgstr "უკანაბოლოს ცვლადების ხედის მიბმა შეუძლებელია: შეცდომის კოდი %lu\n" -#: postmaster/launch_backend.c:942 +#: postmaster/launch_backend.c:979 #, c-format msgid "could not unmap view of backend variables: error code %lu\n" msgstr "უკანაბოლოს ცვლადების ხედის მოხსნა შეუძლებელია: შეცდომის კოდი %lu\n" -#: postmaster/launch_backend.c:949 +#: postmaster/launch_backend.c:986 #, c-format msgid "could not close handle to backend parameter variables: error code %lu\n" msgstr "უკანაბოლოს პარამეტრის ცვლადების დამმუშავებლის დახურვა შეუძლებელია. შეცდომის კოდი: %lu\n" -#: postmaster/pgarch.c:428 +#: postmaster/pgarch.c:429 #, c-format msgid "\"archive_mode\" enabled, yet archiving is not configured" msgstr "\"archive_mode\" ჩართულია, მაგრამ დაარქივება ჯერ მორგებული არაა" -#: postmaster/pgarch.c:452 +#: postmaster/pgarch.c:453 #, c-format msgid "removed orphan archive status file \"%s\"" msgstr "წაიშალა მიტოვებული არქივის სტატუსის ფაილი \"%s\"" -#: postmaster/pgarch.c:462 +#: postmaster/pgarch.c:463 #, c-format msgid "removal of orphan archive status file \"%s\" failed too many times, will try again later" msgstr "" -#: postmaster/pgarch.c:498 +#: postmaster/pgarch.c:499 #, c-format msgid "archiving write-ahead log file \"%s\" failed too many times, will try again later" msgstr "" -#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 +#: postmaster/pgarch.c:885 postmaster/pgarch.c:924 #, c-format msgid "both \"archive_command\" and \"archive_library\" set" msgstr "დაყენებულია ორივე, \"archive_command\" და \"archive_library\"" -#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 +#: postmaster/pgarch.c:886 postmaster/pgarch.c:925 #, c-format msgid "Only one of \"archive_command\", \"archive_library\" may be set." msgstr "\"archive_command\"-დან და \"archive_library\"-დან, მხოლოდ, ერთ-ერთი შეგიძლიათ, დააყენოთ." -#: postmaster/pgarch.c:897 +#: postmaster/pgarch.c:903 #, c-format msgid "restarting archiver process because value of \"archive_library\" was changed" msgstr "" -#: postmaster/pgarch.c:934 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules have to define the symbol %s" msgstr "" -#: postmaster/pgarch.c:940 +#: postmaster/pgarch.c:946 #, c-format msgid "archive modules must register an archive callback" msgstr "" -#: postmaster/postmaster.c:661 +#: postmaster/postmaster.c:678 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: -f პარამეტრის არასწორი არგუმენტი: \"%s\"\n" -#: postmaster/postmaster.c:734 +#: postmaster/postmaster.c:751 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: -t პარამეტრის არასწორი არგუმენტი: \"%s\"\n" -#: postmaster/postmaster.c:757 +#: postmaster/postmaster.c:774 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: არასწორი არგუმენტი: \"%s\"\n" -#: postmaster/postmaster.c:825 +#: postmaster/postmaster.c:842 #, c-format msgid "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" msgstr "" -#: postmaster/postmaster.c:833 +#: postmaster/postmaster.c:850 #, c-format msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" msgstr "" -#: postmaster/postmaster.c:836 +#: postmaster/postmaster.c:853 #, c-format msgid "WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be \"replica\" or \"logical\"" msgstr "" -#: postmaster/postmaster.c:839 +#: postmaster/postmaster.c:856 #, c-format msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" msgstr "" -#: postmaster/postmaster.c:847 +#: postmaster/postmaster.c:864 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "" -#: postmaster/postmaster.c:1004 +#: postmaster/postmaster.c:1025 #, c-format msgid "could not create I/O completion port for child queue" msgstr "" -#: postmaster/postmaster.c:1069 +#: postmaster/postmaster.c:1091 #, c-format msgid "ending log output to stderr" msgstr "ჟურნალის stderr-ზე გამოტანის დასრულება" -#: postmaster/postmaster.c:1070 +#: postmaster/postmaster.c:1092 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "" -#: postmaster/postmaster.c:1081 +#: postmaster/postmaster.c:1103 #, c-format msgid "starting %s" msgstr "\"%s\"-ის გაშვება" -#: postmaster/postmaster.c:1143 +#: postmaster/postmaster.c:1165 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "მოსმენის სოკეტის შექმნა \"%s\"-სთვის შეუძლებელია" -#: postmaster/postmaster.c:1149 +#: postmaster/postmaster.c:1171 #, c-format msgid "could not create any TCP/IP sockets" msgstr "\"TCP/IP\" სოკეტების შექმნის შეცდომა" -#: postmaster/postmaster.c:1181 +#: postmaster/postmaster.c:1203 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "DNSServiceRegister()-ის შეცდომა: შეცდომის კოდი %ld" -#: postmaster/postmaster.c:1234 +#: postmaster/postmaster.c:1256 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "შეცდომა Unix სოკეტის შექმნისას საქაღალდეში \"%s\"" -#: postmaster/postmaster.c:1240 +#: postmaster/postmaster.c:1262 #, c-format msgid "could not create any Unix-domain sockets" msgstr "\"Unix-domain\" სოკეტების შექმნის შეცდომა" -#: postmaster/postmaster.c:1251 +#: postmaster/postmaster.c:1273 #, c-format msgid "no socket created for listening" msgstr "მოსასმენი სოკეტი არ შექმნილა" -#: postmaster/postmaster.c:1282 +#: postmaster/postmaster.c:1304 #, c-format msgid "%s: could not change permissions of external PID file \"%s\": %m\n" msgstr "%s: გარე PID ფაილის \"%s\" წვდომების შეცვლა შეუძლებელია: %m\n" -#: postmaster/postmaster.c:1286 +#: postmaster/postmaster.c:1308 #, c-format msgid "%s: could not write external PID file \"%s\": %m\n" msgstr "%s: გარე PID ფაილის ჩაწერის შეცდომა \"%s\": %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1336 utils/init/postinit.c:225 #, c-format msgid "could not load %s" msgstr "%s-ის ჩატვირთვა შეუძლებელია" -#: postmaster/postmaster.c:1340 +#: postmaster/postmaster.c:1364 #, c-format msgid "postmaster became multithreaded during startup" msgstr "პროცესი postmaster გაშვებისას მრავალნაკადიანი გახდა" -#: postmaster/postmaster.c:1341 +#: postmaster/postmaster.c:1365 postmaster/postmaster.c:3661 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "დააყენეთ LC_ALL გარემოს ცვლადი სწორ ლოკალზე." -#: postmaster/postmaster.c:1440 +#: postmaster/postmaster.c:1468 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: ჩემი საკუთარი გამშვები ფაილის ბილიკის მოძებნა შეუძლებელია" -#: postmaster/postmaster.c:1447 +#: postmaster/postmaster.c:1475 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: გამშვები ფაილი postgres ვერ ვიპოვე" -#: postmaster/postmaster.c:1470 utils/misc/tzparser.c:341 +#: postmaster/postmaster.c:1498 utils/misc/tzparser.c:342 #, c-format msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location." msgstr "" -#: postmaster/postmaster.c:1497 +#: postmaster/postmaster.c:1525 #, c-format msgid "" "%s: could not find the database system\n" @@ -19676,324 +20146,320 @@ msgid "" msgstr "" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1787 +#: postmaster/postmaster.c:1762 #, c-format msgid "issuing %s to recalcitrant children" msgstr "" -#: postmaster/postmaster.c:1809 +#: postmaster/postmaster.c:1784 #, c-format msgid "performing immediate shutdown because data directory lock file is invalid" msgstr "" -#: postmaster/postmaster.c:1872 -#, c-format -msgid "wrong key in cancel request for process %d" -msgstr "არასწორი გასაღები გაუქმების მოთხოვნაში პროცესისთვის %d" - -#: postmaster/postmaster.c:1884 -#, c-format -msgid "PID %d in cancel request did not match any process" -msgstr "PID %d, მოთხოვნილი გაუქმების მოთხოვნაში, არც ერთ პროცესს არ ემთხვევა" - -#: postmaster/postmaster.c:2105 +#: postmaster/postmaster.c:2004 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "მიღებულია SIGHUP, მიმდინარეობს კონფიგურაციის ფაილების თავიდან ჩატვირთვა" #. translator: %s is a configuration file -#: postmaster/postmaster.c:2133 postmaster/postmaster.c:2137 +#: postmaster/postmaster.c:2012 postmaster/postmaster.c:2016 #, c-format msgid "%s was not reloaded" msgstr "%s არ გადატვირთულა" -#: postmaster/postmaster.c:2147 +#: postmaster/postmaster.c:2026 #, c-format msgid "SSL configuration was not reloaded" msgstr "SSL კონფიგურაცია არ იყო გადატვირთული" -#: postmaster/postmaster.c:2233 +#: postmaster/postmaster.c:2112 #, c-format msgid "received smart shutdown request" msgstr "მიღებულია ჭკვიანი გამორთვის მოთხოვნა" -#: postmaster/postmaster.c:2274 +#: postmaster/postmaster.c:2153 #, c-format msgid "received fast shutdown request" msgstr "მიღებულია სწრაფი გამორთვის მოთხოვნა" -#: postmaster/postmaster.c:2292 +#: postmaster/postmaster.c:2171 #, c-format msgid "aborting any active transactions" msgstr "ყველა აქტიური ტრანზაქციის შეწყვეტა" -#: postmaster/postmaster.c:2316 +#: postmaster/postmaster.c:2195 #, c-format msgid "received immediate shutdown request" msgstr "მიღებულია დაუყოვნებლივი გამორთვის მოთხოვნა" -#: postmaster/postmaster.c:2388 +#: postmaster/postmaster.c:2270 #, c-format msgid "shutdown at recovery target" msgstr "გამორთვა აღდგენის სამიზნეზე" -#: postmaster/postmaster.c:2406 postmaster/postmaster.c:2442 +#: postmaster/postmaster.c:2288 postmaster/postmaster.c:2324 msgid "startup process" msgstr "გაშვების პროცესი" -#: postmaster/postmaster.c:2409 +#: postmaster/postmaster.c:2291 #, c-format msgid "aborting startup due to startup process failure" msgstr "გაშვების გაუქმება გაშვების პროცესის შეცდომის გამო" -#: postmaster/postmaster.c:2484 +#: postmaster/postmaster.c:2347 #, c-format msgid "database system is ready to accept connections" msgstr "მონაცემთა ბაზის სისტემა მზადაა შეერთებების მისაღებად" -#: postmaster/postmaster.c:2505 +#: postmaster/postmaster.c:2369 msgid "background writer process" msgstr "ფონური ჩამწერი პროცესი" -#: postmaster/postmaster.c:2552 +#: postmaster/postmaster.c:2402 msgid "checkpointer process" msgstr "საკონტროლო წერტილის პროცესი" -#: postmaster/postmaster.c:2568 +#: postmaster/postmaster.c:2419 msgid "WAL writer process" msgstr "WAL-ის ჩამწერი პროცესი" -#: postmaster/postmaster.c:2583 +#: postmaster/postmaster.c:2435 msgid "WAL receiver process" msgstr "WAL-ის მიმღები პროცესი" -#: postmaster/postmaster.c:2597 +#: postmaster/postmaster.c:2450 msgid "WAL summarizer process" msgstr "WAL-ის შეჯამების პროცესი" -#: postmaster/postmaster.c:2612 +#: postmaster/postmaster.c:2466 msgid "autovacuum launcher process" msgstr "ავტომომტვერსასრუტების გამშვები პროცესი" -#: postmaster/postmaster.c:2630 +#: postmaster/postmaster.c:2482 msgid "archiver process" msgstr "არქივის პროცესი" -#: postmaster/postmaster.c:2643 +#: postmaster/postmaster.c:2497 msgid "system logger process" msgstr "სისტემური ჟურნალის პროცესი" -#: postmaster/postmaster.c:2660 +#: postmaster/postmaster.c:2515 msgid "slot sync worker process" msgstr "სლოტის სინქრონიზაციის დამხმარე პროცესი" -#: postmaster/postmaster.c:2716 +#: postmaster/postmaster.c:2523 utils/init/miscinit.c:297 +msgid "io worker" +msgstr "შეტანა/გამოტანის დამხმარე პროცესი" + +#: postmaster/postmaster.c:2545 postmaster/postmaster.c:2547 +msgid "untracked child process" +msgstr "შვილი პროცესი ტრეკინგის გარეშე" + +#: postmaster/postmaster.c:2580 #, c-format msgid "background worker \"%s\"" msgstr "ფონური დამხმარე პროცესი \"%s\"" -#: postmaster/postmaster.c:2795 postmaster/postmaster.c:2815 postmaster/postmaster.c:2822 postmaster/postmaster.c:2840 -msgid "server process" -msgstr "სერვერის პროცესი" - -#: postmaster/postmaster.c:2894 +#: postmaster/postmaster.c:2797 #, c-format msgid "terminating any other active server processes" msgstr "სერვერის სხვა დანარჩენი აქტიური პროცესები შეჩერდება" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3081 +#: postmaster/postmaster.c:2830 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) დასრულდა სტატუსით %d" -#: postmaster/postmaster.c:3083 postmaster/postmaster.c:3095 postmaster/postmaster.c:3105 postmaster/postmaster.c:3116 +#: postmaster/postmaster.c:2832 postmaster/postmaster.c:2844 postmaster/postmaster.c:2854 postmaster/postmaster.c:2865 #, c-format msgid "Failed process was running: %s" msgstr "შეცდომის მქონე პროცესს გაშვებული ჰქონდა: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3092 +#: postmaster/postmaster.c:2841 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) დასრულდა შეცდომის კოდით 0x%X" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3102 +#: postmaster/postmaster.c:2851 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) დასრულდა სიგნალით: %d: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3114 +#: postmaster/postmaster.c:2863 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d) დასრულდა უცნობი სტატუსით %d" -#: postmaster/postmaster.c:3330 +#: postmaster/postmaster.c:3154 #, c-format msgid "abnormal database system shutdown" msgstr "მონაცემთა ბაზის სისტემის არანორმალური გამორთვა" -#: postmaster/postmaster.c:3356 +#: postmaster/postmaster.c:3180 #, c-format msgid "shutting down due to startup process failure" msgstr "მუშაობის დასრულება გამშვები პროცესის შეცდომის გამო" -#: postmaster/postmaster.c:3362 +#: postmaster/postmaster.c:3186 #, c-format msgid "shutting down because \"restart_after_crash\" is off" msgstr "მუშაობა დასრულდება. რადგან \"restart_after_crash\" გამორთულია" -#: postmaster/postmaster.c:3374 +#: postmaster/postmaster.c:3198 #, c-format msgid "all server processes terminated; reinitializing" msgstr "სერვერის ყველა პროცესი დასრულდა; მიმდინარეობს რეინიციალიზაცია" -#: postmaster/postmaster.c:3573 postmaster/postmaster.c:3983 postmaster/postmaster.c:4372 -#, c-format -msgid "could not generate random cancel key" -msgstr "შემთხვევითი გაუქმების გასაღების გენერაცია შეუძლებელია" - -#: postmaster/postmaster.c:3606 +#: postmaster/postmaster.c:3591 #, c-format msgid "could not fork new process for connection: %m" msgstr "ახალი პროცესის ფორკის შეცდომა შეერთებისთვის: %m" -#: postmaster/postmaster.c:3648 +#: postmaster/postmaster.c:3626 msgid "could not fork new process for connection: " msgstr "ახალი პროცესის ფორკის შეცდომა შეერთებისთვის: " -#: postmaster/postmaster.c:3682 +#: postmaster/postmaster.c:3660 #, c-format -msgid "Please report this to <%s>." -msgstr "გთხოვთ, შეატყობინოთ <%s>." +msgid "postmaster became multithreaded" +msgstr "postmaster მრავალნაკადიანი გახდა" -#: postmaster/postmaster.c:3750 +#: postmaster/postmaster.c:3738 #, c-format msgid "database system is ready to accept read-only connections" msgstr "მონაცემთა ბაზის სისტემა მზადაა მხოლოდ-კითხვადი შეერთებების მისაღებად" -#: postmaster/postmaster.c:3933 -#, c-format -msgid "could not fork \"%s\" process: %m" -msgstr "\"%s\" პროცესის ფორკის შეცდომა: %m" - -#: postmaster/postmaster.c:4171 postmaster/postmaster.c:4205 +#: postmaster/postmaster.c:3839 #, c-format -msgid "database connection requirement not indicated during registration" -msgstr "" +msgid "WAL was shut down unexpectedly" +msgstr "WAL მოულოდნელად გაითიშა" -#: postmaster/postmaster.c:4181 postmaster/postmaster.c:4215 +#: postmaster/postmaster.c:3964 #, c-format -msgid "invalid processing mode in background worker" -msgstr "არასწორი დამუშავების რეჟიმი ფონურ დამხმარე პროცესში" +msgid "no slot available for new autovacuum worker process" +msgstr "ავტომომტვერსასრუტების ფონური დამხმარე პროცესისთვის სლოტი ხელმისაწვდომი არაა" -#: postmaster/postmaster.c:4275 +#: postmaster/postmaster.c:3979 #, c-format -msgid "could not fork background worker process: %m" -msgstr "ფონური დამხმარე პროცესის ფორკის შეცდომა: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "\"%s\" პროცესის ფორკის შეცდომა: %m" -#: postmaster/postmaster.c:4358 +#: postmaster/postmaster.c:4138 #, c-format msgid "no slot available for new background worker process" msgstr "ახალი ფონური დამხმარე პროცესისთვის სლოტი ხელმისაწვდომი არაა" -#: postmaster/postmaster.c:4621 +#: postmaster/postmaster.c:4156 +#, c-format +msgid "could not fork background worker process: %m" +msgstr "ფონური დამხმარე პროცესის ფორკის შეცდომა: %m" + +#: postmaster/postmaster.c:4489 #, c-format msgid "could not read exit code for process\n" msgstr "პროცესის გამოსვლის კოდის წაკითხვის შეცდომა\n" -#: postmaster/postmaster.c:4663 +#: postmaster/postmaster.c:4531 #, c-format msgid "could not post child completion status\n" msgstr "შვილი პროცესის დასრულების სტატუსის წაკითხვის შეცდომა\n" -#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 +#: postmaster/syslogger.c:527 postmaster/syslogger.c:1172 #, c-format msgid "could not read from logger pipe: %m" msgstr "ჟურნალის ფაიფიდან წაკითხვა შეუძლებელია: %m" -#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 +#: postmaster/syslogger.c:626 postmaster/syslogger.c:640 #, c-format msgid "could not create pipe for syslog: %m" msgstr "სისტემური ჟურნალისთვის ფაიფის შექმნა შეუძლებელია: %m" -#: postmaster/syslogger.c:712 +#: postmaster/syslogger.c:711 #, c-format msgid "could not fork system logger: %m" msgstr "სისტემის ჟურნალის ფორკის შეცდომა: %m" -#: postmaster/syslogger.c:731 +#: postmaster/syslogger.c:730 #, c-format msgid "redirecting log output to logging collector process" msgstr "ჟურნალის გამოტანის გადამისამართება ჟურნალის შემგროვებლის პროცესისკენ" -#: postmaster/syslogger.c:732 +#: postmaster/syslogger.c:731 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "" -#: postmaster/syslogger.c:740 +#: postmaster/syslogger.c:739 #, c-format msgid "could not redirect stdout: %m" msgstr "stdout-ის გადამისამართების შეცდომა: %m" -#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 +#: postmaster/syslogger.c:744 postmaster/syslogger.c:761 #, c-format msgid "could not redirect stderr: %m" msgstr "stderr-ის გადამისამართების შეცდომა: %m" -#: postmaster/syslogger.c:1128 +#: postmaster/syslogger.c:1127 #, c-format msgid "could not write to log file: %m\n" msgstr "ჟურნალის ფაილში ჩაწერის შეცდომა: %m\n" -#: postmaster/syslogger.c:1246 +#: postmaster/syslogger.c:1247 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ჟურნალის ფაილის გახსნის შეცდომა \"%s\": %m" -#: postmaster/syslogger.c:1336 +#: postmaster/syslogger.c:1337 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "" -#: postmaster/walsummarizer.c:384 +#: postmaster/walsummarizer.c:743 #, c-format -msgid "switch point from TLI %u to TLI %u is at %X/%X" +msgid "WAL summarization is not progressing" msgstr "" -#: postmaster/walsummarizer.c:885 +#: postmaster/walsummarizer.c:744 #, c-format -msgid "could not find a valid record after %X/%X" +msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." +msgstr "" + +#: postmaster/walsummarizer.c:758 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "" +msgstr[1] "" + +#: postmaster/walsummarizer.c:763 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "" + +#: postmaster/walsummarizer.c:1007 +#, c-format +msgid "could not find a valid record after %X/%X" msgstr "%X/%X -ის შემდეგ სწორი ჩანაწერი არ არსებობს" -#: postmaster/walsummarizer.c:930 +#: postmaster/walsummarizer.c:1052 #, c-format msgid "could not read WAL from timeline %u at %X/%X: %s" msgstr "ვერ წავიკითხე WAL დროის ხაზიდან %u მისამართზე %X/%X: %s" -#: postmaster/walsummarizer.c:936 +#: postmaster/walsummarizer.c:1058 #, c-format msgid "could not read WAL from timeline %u at %X/%X" msgstr "ვერ წავიკითხე WAL დროის ხაზიდან %u მისამართზე %X/%X" -#: postmaster/walsummarizer.c:1077 -#, c-format -msgid "summarized WAL on TLI %u from %X/%X to %X/%X" -msgstr "" - -#: postmaster/walsummarizer.c:1385 -#, c-format -msgid "timeline %u became historic, can read up to %X/%X" -msgstr "" - -#: regex/regc_pg_locale.c:244 +#: regex/regc_pg_locale.c:241 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "" @@ -20003,145 +20469,145 @@ msgstr "" msgid "nondeterministic collations are not supported for regular expressions" msgstr "" -#: repl_gram.y:318 repl_gram.y:359 +#: repl_gram.y:322 repl_gram.y:363 #, c-format msgid "invalid timeline %u" msgstr "დროის არასწორი ხაზი: %u" -#: repl_scanner.l:154 +#: repl_scanner.l:160 msgid "invalid streaming start location" msgstr "ნაკადის დასაწყისის არასწორი მდებარეობა" -#: replication/libpqwalreceiver/libpqwalreceiver.c:267 replication/libpqwalreceiver/libpqwalreceiver.c:358 +#: replication/libpqwalreceiver/libpqwalreceiver.c:230 replication/libpqwalreceiver/libpqwalreceiver.c:322 #, c-format msgid "password is required" msgstr "პაროლი სავალდებულოა" -#: replication/libpqwalreceiver/libpqwalreceiver.c:268 +#: replication/libpqwalreceiver/libpqwalreceiver.c:231 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:269 +#: replication/libpqwalreceiver/libpqwalreceiver.c:232 #, c-format msgid "Target server's authentication method must be changed, or set password_required=false in the subscription parameters." msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:285 +#: replication/libpqwalreceiver/libpqwalreceiver.c:249 #, c-format msgid "could not clear search path: %s" msgstr "ძებნის ბილიკების გასუფთავების შეცდომა: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:331 replication/libpqwalreceiver/libpqwalreceiver.c:517 +#: replication/libpqwalreceiver/libpqwalreceiver.c:295 replication/libpqwalreceiver/libpqwalreceiver.c:483 #, c-format msgid "invalid connection string syntax: %s" msgstr "შეერთების სტრიქონის არასწორი სინტაქსი: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:359 +#: replication/libpqwalreceiver/libpqwalreceiver.c:323 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:386 +#: replication/libpqwalreceiver/libpqwalreceiver.c:350 #, c-format msgid "could not parse connection string: %s" msgstr "შეერთების სტრიქონის დამუშავების შეცდომა: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:459 +#: replication/libpqwalreceiver/libpqwalreceiver.c:425 #, c-format msgid "could not receive database system identifier and timeline ID from the primary server: %s" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:476 replication/libpqwalreceiver/libpqwalreceiver.c:763 +#: replication/libpqwalreceiver/libpqwalreceiver.c:442 replication/libpqwalreceiver/libpqwalreceiver.c:737 #, c-format msgid "invalid response from primary server" msgstr "ძირითადი სერვერის არასწორი პასუხი" -#: replication/libpqwalreceiver/libpqwalreceiver.c:477 +#: replication/libpqwalreceiver/libpqwalreceiver.c:443 #, c-format msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields." msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:606 replication/libpqwalreceiver/libpqwalreceiver.c:613 replication/libpqwalreceiver/libpqwalreceiver.c:643 +#: replication/libpqwalreceiver/libpqwalreceiver.c:572 replication/libpqwalreceiver/libpqwalreceiver.c:579 replication/libpqwalreceiver/libpqwalreceiver.c:611 #, c-format msgid "could not start WAL streaming: %s" msgstr "wal ნაკადის დაწყების შეცდომა: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:667 +#: replication/libpqwalreceiver/libpqwalreceiver.c:635 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:690 +#: replication/libpqwalreceiver/libpqwalreceiver.c:659 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:705 +#: replication/libpqwalreceiver/libpqwalreceiver.c:675 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:715 +#: replication/libpqwalreceiver/libpqwalreceiver.c:686 #, c-format msgid "error reading result of streaming command: %s" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:724 replication/libpqwalreceiver/libpqwalreceiver.c:957 +#: replication/libpqwalreceiver/libpqwalreceiver.c:696 replication/libpqwalreceiver/libpqwalreceiver.c:832 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "მოულოდნელი შედეგი CommandComplete-ის შემდეგ: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:751 +#: replication/libpqwalreceiver/libpqwalreceiver.c:725 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:764 +#: replication/libpqwalreceiver/libpqwalreceiver.c:738 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "" -#: replication/libpqwalreceiver/libpqwalreceiver.c:920 replication/libpqwalreceiver/libpqwalreceiver.c:973 replication/libpqwalreceiver/libpqwalreceiver.c:980 +#: replication/libpqwalreceiver/libpqwalreceiver.c:793 replication/libpqwalreceiver/libpqwalreceiver.c:848 replication/libpqwalreceiver/libpqwalreceiver.c:855 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "\"WAL\" ნაკადიდან მონაცემების მიღების შეცდომა: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 +#: replication/libpqwalreceiver/libpqwalreceiver.c:875 #, c-format msgid "could not send data to WAL stream: %s" msgstr "'WAL' ნაკადისთვის მონაცემების გაგზავნა შეუძლებელია: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 +#: replication/libpqwalreceiver/libpqwalreceiver.c:978 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "რეპლიკაციის სლოტის \"%s\" შექმნის შეცდომა: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1030 #, c-format msgid "could not alter replication slot \"%s\": %s" msgstr "რეპლიკაციის სლოტის \"%s\" შეცვლა შეუძლებელია: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1064 #, c-format msgid "invalid query response" msgstr "მოთხოვნის არასწორი პასუხი" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1065 #, c-format msgid "Expected %d fields, got %d fields." msgstr "მოველოდი %d ველს. მივიღე %d." -#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1135 #, c-format msgid "the query interface requires a database connection" msgstr "მოთხოვნის ინტერფეისს ბაზასთან მიერთება სჭირდება" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1169 msgid "empty query" msgstr "ცარიელი მოთხოვნა" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 msgid "unexpected pipeline mode" msgstr "არხის მოულოდნელი რეჟიმი" @@ -20179,37 +20645,146 @@ msgstr "გაზიარებული-მეხსიერების მ msgid "logical replication apply worker will serialize the remaining changes of remote transaction %u to a file" msgstr "" +#: replication/logical/conflict.c:126 +#, c-format +msgid "conflict detected on relation \"%s.%s\": conflict=%s" +msgstr "აღმოჩენილია კონფლიქტი ურთიერთობაზე \"%s.%s\": კონფლიქტი=%s" + +#: replication/logical/conflict.c:223 +#, c-format +msgid "Key already exists in unique index \"%s\", modified locally in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:227 +#, c-format +msgid "Key already exists in unique index \"%s\", modified by origin \"%s\" in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:239 +#, c-format +msgid "Key already exists in unique index \"%s\", modified by a non-existent origin in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:244 +#, c-format +msgid "Key already exists in unique index \"%s\", modified in transaction %u." +msgstr "" + +#: replication/logical/conflict.c:251 +#, c-format +msgid "Updating the row that was modified locally in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:254 +#, c-format +msgid "Updating the row that was modified by a different origin \"%s\" in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:259 +#, c-format +msgid "Updating the row that was modified by a non-existent origin in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:265 +msgid "Could not find the row to be updated." +msgstr "გასაახლებელი მწკრივის აღმოჩენა შეუძლებელია." + +#: replication/logical/conflict.c:270 +#, c-format +msgid "Deleting the row that was modified locally in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:273 +#, c-format +msgid "Deleting the row that was modified by a different origin \"%s\" in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:278 +#, c-format +msgid "Deleting the row that was modified by a non-existent origin in transaction %u at %s." +msgstr "" + +#: replication/logical/conflict.c:284 +msgid "Could not find the row to be deleted." +msgstr "წასაშლელი მწკრივის აღმოჩენა შეუძლებელია." + +#: replication/logical/conflict.c:347 +#, c-format +msgid "Key %s" +msgstr "" + +#: replication/logical/conflict.c:364 +#, c-format +msgid "existing local tuple %s" +msgstr "" + +#: replication/logical/conflict.c:369 +#, c-format +msgid "Existing local tuple %s" +msgstr "" + +#: replication/logical/conflict.c:396 +#, c-format +msgid "remote tuple %s" +msgstr "დაშორებული კორტეჟი %s" + +#: replication/logical/conflict.c:400 +#, c-format +msgid "Remote tuple %s" +msgstr "დაშორებული კორტეჟი %s" + +#: replication/logical/conflict.c:434 +#, c-format +msgid "replica identity %s" +msgstr "რეპლიკის იდენტიფიკატორი %s" + +#: replication/logical/conflict.c:435 +#, c-format +msgid "replica identity full %s" +msgstr "რეპლიკის იდენტიფიკატორი სრული %s" + +#: replication/logical/conflict.c:440 +#, c-format +msgid "Replica identity %s" +msgstr "რეპლიკის იდენტიფიკატორი %s" + +#: replication/logical/conflict.c:441 +#, c-format +msgid "Replica identity full %s" +msgstr "რეპლიკის იდენტიფიკატორი სრული %s" + #: replication/logical/decode.c:177 replication/logical/logical.c:141 #, c-format msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" msgstr "ლოგიკურ გაშიფვრას უქმეზე ძირითად სერვერზე \"wal_level\" >= \"logical\" ესაჭიროება" -#: replication/logical/launcher.c:334 +#: replication/logical/launcher.c:331 #, c-format -msgid "cannot start logical replication workers when max_replication_slots = 0" -msgstr "" +msgid "cannot start logical replication workers when \"max_active_replication_origins\"=0" +msgstr "შეუძლებელია ლოგიკური რეპლიკაციის დამხმარე პროცესების გაშვება, როცა \"max_active_replication_origins\"=0" -#: replication/logical/launcher.c:427 +#: replication/logical/launcher.c:424 #, c-format msgid "out of logical replication worker slots" msgstr "ლოგიკური რეპლიკაციის დამხმარე პროგრამის სლოტები არასაკმარისია" -#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 replication/slot.c:1524 storage/lmgr/lock.c:963 storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2804 storage/lmgr/lock.c:4189 storage/lmgr/lock.c:4254 storage/lmgr/lock.c:4604 storage/lmgr/predicate.c:2464 storage/lmgr/predicate.c:2479 storage/lmgr/predicate.c:3876 +#. translator: %s is a GUC variable name +#: replication/logical/launcher.c:425 replication/logical/launcher.c:511 replication/slot.c:1556 replication/slot.c:1579 storage/lmgr/lock.c:1039 storage/lmgr/lock.c:1077 storage/lmgr/lock.c:2966 storage/lmgr/lock.c:4371 storage/lmgr/lock.c:4436 storage/lmgr/lock.c:4786 storage/lmgr/predicate.c:2479 storage/lmgr/predicate.c:2494 storage/lmgr/predicate.c:3891 #, c-format msgid "You might need to increase \"%s\"." msgstr "როგორც ჩანს, გჭირდებათ, \"%s\" გაზარდოთ." -#: replication/logical/launcher.c:513 +#: replication/logical/launcher.c:510 #, c-format msgid "out of background worker slots" msgstr "ფონური დამხმარე პროცესების სლოტები არასაკმარისია" -#: replication/logical/launcher.c:720 +#: replication/logical/launcher.c:717 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "" -#: replication/logical/launcher.c:729 +#: replication/logical/launcher.c:726 #, c-format msgid "logical replication worker slot %d is already used by another worker, cannot attach" msgstr "" @@ -20224,82 +20799,67 @@ msgstr "ლოგიკურ გაშიფვრას \"wal_level\" >= \"log msgid "logical decoding requires a database connection" msgstr "ლოგიკურ გაშიფვრას ბაზასთან მიერთება ესაჭიროება" -#: replication/logical/logical.c:364 replication/logical/logical.c:518 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "ლოგიკური გაშიფვრისთვის ფიზიკური რეპლიკაციის სლოტის გამოყენება შეუძლებელია" -#: replication/logical/logical.c:369 replication/logical/logical.c:528 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "რეპლიკაციის სლოტი \"%s\" ამ ბაზაში არ შექმნილა" -#: replication/logical/logical.c:376 +#: replication/logical/logical.c:377 #, c-format msgid "cannot create logical replication slot in transaction that has performed writes" msgstr "შეუძლებელია ლოგიკური რეპლიკაციის სლოტის შექმნა ტრანზაქციაში, რომელიც ჩაწერებს ახორციელებს" -#: replication/logical/logical.c:539 +#: replication/logical/logical.c:540 #, c-format msgid "cannot use replication slot \"%s\" for logical decoding" msgstr "ლოგიკური გაშიფვრისთვის რეპლიკაციის სლოტის \"%s\" გამოყენება შეუძლებელია" -#: replication/logical/logical.c:541 +#: replication/logical/logical.c:542 replication/slot.c:828 replication/slot.c:863 #, c-format -msgid "This slot is being synchronized from the primary server." -msgstr "მიმდინარეობს ამ სლოტის სინქრონიზაცია ძირითადი სერვერიდან." +msgid "This replication slot is being synchronized from the primary server." +msgstr "მიმდინარეობს ამ რეპლიკაციის სლოტის სინქრონიზაცია ძირითადი სერვერიდან." -#: replication/logical/logical.c:542 +#: replication/logical/logical.c:543 #, c-format msgid "Specify another replication slot." msgstr "მიუთითეთ სხვა რეპლიკაციის სლოტი." -#: replication/logical/logical.c:553 replication/logical/logical.c:560 -#, c-format -msgid "can no longer get changes from replication slot \"%s\"" -msgstr "რეპლიკაციის სლოტიდან \"%s\" ცვლილებების მიღება უკვე შეუძლებელია" - -#: replication/logical/logical.c:555 -#, c-format -msgid "This slot has been invalidated because it exceeded the maximum reserved size." -msgstr "" - -#: replication/logical/logical.c:562 -#, c-format -msgid "This slot has been invalidated because it was conflicting with recovery." -msgstr "" - -#: replication/logical/logical.c:627 +#: replication/logical/logical.c:609 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "იწყება ლოგიკური გაშიფვრა სლოტისთვის \"%s\"" -#: replication/logical/logical.c:629 +#: replication/logical/logical.c:611 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "" -#: replication/logical/logical.c:777 +#: replication/logical/logical.c:759 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "" -#: replication/logical/logical.c:783 +#: replication/logical/logical.c:765 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "" -#: replication/logical/logical.c:954 replication/logical/logical.c:999 replication/logical/logical.c:1044 replication/logical/logical.c:1090 +#: replication/logical/logical.c:936 replication/logical/logical.c:981 replication/logical/logical.c:1026 replication/logical/logical.c:1072 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "" -#: replication/logical/logical.c:1322 replication/logical/logical.c:1371 replication/logical/logical.c:1412 replication/logical/logical.c:1498 replication/logical/logical.c:1547 +#: replication/logical/logical.c:1304 replication/logical/logical.c:1353 replication/logical/logical.c:1394 replication/logical/logical.c:1480 replication/logical/logical.c:1529 #, c-format msgid "logical streaming requires a %s callback" msgstr "" -#: replication/logical/logical.c:1457 +#: replication/logical/logical.c:1439 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "" @@ -20324,7 +20884,7 @@ msgstr "მასივი ერთგანზომილებიანი msgid "array must not contain nulls" msgstr "მასივი ნულოვან მნიშვნელობებს არ უნდა შეიცავდეს" -#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1406 utils/adt/jsonb.c:1304 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1428 utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "მასივს ლუწი რაოდენობის ელემენტები უნდა ჰქონდეს" @@ -20334,32 +20894,32 @@ msgstr "მასივს ლუწი რაოდენობის ელე msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data" msgstr "" -#: replication/logical/origin.c:190 +#: replication/logical/origin.c:195 #, c-format -msgid "cannot query or manipulate replication origin when \"max_replication_slots\" is 0" -msgstr "რეპლიკაციის წყაროდან გამოთხოვა ან მისით მანიპულაცია შეუძლებელია, როცა \"max_replicaion_slots\" ნულს უდრის" +msgid "cannot query or manipulate replication origin when \"max_active_replication_origins\" is 0" +msgstr "რეპლიკაციის წყაროდან გამოთხოვა ან მისით მანიპულაცია შეუძლებელია, როცა \"max_active_replication_origins\" ნულს უდრის" -#: replication/logical/origin.c:195 +#: replication/logical/origin.c:200 #, c-format msgid "cannot manipulate replication origins during recovery" msgstr "აღდგენისა რეპლიკაციის წყაროებს ვერ შეცვლით" -#: replication/logical/origin.c:240 +#: replication/logical/origin.c:245 #, c-format msgid "replication origin \"%s\" does not exist" msgstr "რეპლიკაციის წყარო \"%s\" არ არსებობს" -#: replication/logical/origin.c:331 +#: replication/logical/origin.c:336 #, c-format msgid "could not find free replication origin ID" msgstr "თავისუფალი რეპლიკაციის წყაროს ID-ის პოვნა შეუძლებელია" -#: replication/logical/origin.c:365 +#: replication/logical/origin.c:370 #, c-format msgid "could not drop replication origin with ID %d, in use by PID %d" msgstr "რეპლიკაციის წყაროს, ID-ით %d გადაგდების შეცდომა. გამოიყენება PID-ის მიერ %d" -#: replication/logical/origin.c:492 +#: replication/logical/origin.c:497 #, c-format msgid "replication origin with ID %d does not exist" msgstr "რეპლიკაციის წყარო ID-ით %d არ არსებობს" @@ -20371,8 +20931,8 @@ msgstr "" #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase \"max_replication_slots\"" -msgstr "თავისუფალი რეპლიკაციის მდგომარეობის პოვნა შეუძლებელია. გაზარდეთ \"max_replication_slots\"" +msgid "could not find free replication state, increase \"max_active_replication_origins\"" +msgstr "თავისუფალი რეპლიკაციის მდგომარეობის პოვნა შეუძლებელია. გაზარდეთ \"max_active_replication_origins\"" #: replication/logical/origin.c:806 #, c-format @@ -20394,10 +20954,10 @@ msgstr "რეპლიკაციის წყარო ID-ით %d უკვ msgid "could not find free replication state slot for replication origin with ID %d" msgstr "" -#: replication/logical/origin.c:957 replication/logical/origin.c:1158 replication/slot.c:2384 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 #, c-format -msgid "Increase \"max_replication_slots\" and try again." -msgstr "გაზარდეთ \"max_replication_slots\"-ის მნიშვნელობა და თავიდან სცადეთ." +msgid "Increase \"max_active_replication_origins\" and try again." +msgstr "გაზარდეთ \"max_active_replication_origins\"-ის მნიშვნელობა და თავიდან სცადეთ." #: replication/logical/origin.c:1114 #, c-format @@ -20419,1055 +20979,1137 @@ msgstr "რეპლიკაციის წყაროს სახელი msgid "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." msgstr "საწყისი სახელები, \"%s\", \"%s\" და სახელები, რომლებიც \"pg_\"-ით იწყება, დარეზერვებულია." -#: replication/logical/relation.c:242 +#: replication/logical/relation.c:241 +msgid ", " +msgstr ", " + +#: replication/logical/relation.c:243 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:245 -#, c-format -msgid ", \"%s\"" -msgstr ", \"%s\"" - -#: replication/logical/relation.c:251 +#: replication/logical/relation.c:262 #, c-format msgid "logical replication target relation \"%s.%s\" is missing replicated column: %s" msgid_plural "logical replication target relation \"%s.%s\" is missing replicated columns: %s" msgstr[0] "" msgstr[1] "" -#: replication/logical/relation.c:306 +#: replication/logical/relation.c:273 +#, c-format +msgid "logical replication target relation \"%s.%s\" has incompatible generated column: %s" +msgid_plural "logical replication target relation \"%s.%s\" has incompatible generated columns: %s" +msgstr[0] "ლოგიკური რეპლიკაციის სამიზნე ურთიერთობას \"%s.%s\" აქვს არათავსებადი გენერირებული სვეტი: %s" +msgstr[1] "ლოგიკური რეპლიკაციის სამიზნე ურთიერთობას \"%s.%s\" აქვს არათავსებადი გენერირებული სვეტი: %s" + +#: replication/logical/relation.c:328 #, c-format msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index" msgstr "" -#: replication/logical/relation.c:398 +#: replication/logical/relation.c:421 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "" -#: replication/logical/reorderbuffer.c:3970 +#: replication/logical/reorderbuffer.c:4122 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "შეცდომა მონაცემის ფაილში ჩაწერისას XID-სთვის %u: %m" -#: replication/logical/reorderbuffer.c:4316 replication/logical/reorderbuffer.c:4341 +#: replication/logical/reorderbuffer.c:4468 replication/logical/reorderbuffer.c:4493 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "" -#: replication/logical/reorderbuffer.c:4320 replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4472 replication/logical/reorderbuffer.c:4497 #, c-format msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "" -#: replication/logical/reorderbuffer.c:4595 +#: replication/logical/reorderbuffer.c:4746 #, c-format -msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" -msgstr "" +msgid "could not remove file \"%s\" during removal of %s/%s/xid*: %m" +msgstr "ვერ წავშალე ფაილი \"%s\" %s/%s/xid*-ის წაშლისას: %m" -#: replication/logical/reorderbuffer.c:5091 +#: replication/logical/reorderbuffer.c:5243 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "" -#: replication/logical/slotsync.c:215 +#: replication/logical/slotsync.c:214 #, c-format -msgid "could not sync slot \"%s\" as remote slot precedes local slot" -msgstr "" +msgid "could not synchronize replication slot \"%s\" because remote slot precedes local slot" +msgstr "რეპლიკაციის სლოტის სინქრონიზაცია \"%s\" შეუძლებელია, რადგან დაშორებული სლოტი წინ უსწრებს ლოკალურ სლოტს" -#: replication/logical/slotsync.c:217 +#: replication/logical/slotsync.c:216 #, c-format -msgid "Remote slot has LSN %X/%X and catalog xmin %u, but local slot has LSN %X/%X and catalog xmin %u." +msgid "The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u." msgstr "" -#: replication/logical/slotsync.c:459 +#: replication/logical/slotsync.c:460 #, c-format -msgid "dropped replication slot \"%s\" of dbid %u" -msgstr "წაიშალა რეპლიკაციის სლოტი \"%s\" dbid-სთვის %u" +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "წაიშალა რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზიდან OID-ით %u" -#: replication/logical/slotsync.c:579 +#: replication/logical/slotsync.c:580 #, c-format -msgid "could not sync slot \"%s\"" -msgstr "სლოტის \"%s\" სინქრონიზაცია შეუძლებელია" +msgid "could not synchronize replication slot \"%s\"" +msgstr "რეპლიკაციის სლოტის \"%s\" სინქრონიზაცია შეუძლებელია" -#: replication/logical/slotsync.c:580 +#: replication/logical/slotsync.c:581 #, c-format -msgid "Logical decoding cannot find consistent point from local slot's LSN %X/%X." +msgid "Logical decoding could not find consistent point from local slot's LSN %X/%X." msgstr "" -#: replication/logical/slotsync.c:589 +#: replication/logical/slotsync.c:590 #, c-format -msgid "newly created slot \"%s\" is sync-ready now" -msgstr "" +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "ახლად შექმნილი რეპლიკაციის სლოტი \"%s\" ახლა სინქრონიზებულია" -#: replication/logical/slotsync.c:628 +#: replication/logical/slotsync.c:629 #, c-format -msgid "skipping slot synchronization as the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" +msgid "skipping slot synchronization because the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" msgstr "" -#: replication/logical/slotsync.c:650 +#: replication/logical/slotsync.c:651 #, c-format msgid "exiting from slot synchronization because same name slot \"%s\" already exists on the standby" msgstr "" -#: replication/logical/slotsync.c:819 +#: replication/logical/slotsync.c:820 #, c-format msgid "could not fetch failover logical slots info from the primary server: %s" msgstr "ვერ გამოვითხოვე გადართვის ლოგიკური სლოტების ინფორმაცია ძირითადი სერვერიდან: %s" -#: replication/logical/slotsync.c:965 +#: replication/logical/slotsync.c:969 #, c-format -msgid "could not fetch primary_slot_name \"%s\" info from the primary server: %s" -msgstr "ვერ გამოვითხოვე prmary_slot_name \"%s\"-ის ინფორმაცია ძირითადი სერვერიდან: %s" +msgid "could not fetch primary slot name \"%s\" info from the primary server: %s" +msgstr "ვერ გამოვითხოვე ძირითადი სლოტის სახელის \"%s\" ინფორმაცია ძირითადი სერვერიდან: %s" -#: replication/logical/slotsync.c:967 +#: replication/logical/slotsync.c:971 #, c-format -msgid "Check if primary_slot_name is configured correctly." +msgid "Check if \"primary_slot_name\" is configured correctly." msgstr "" -#: replication/logical/slotsync.c:987 +#: replication/logical/slotsync.c:991 #, c-format msgid "cannot synchronize replication slots from a standby server" msgstr "უქმე სერვერიდან რეპლიკაციის სლოტების სინქრონიზაცია შეუძლებელია" -#: replication/logical/slotsync.c:995 -#, c-format -msgid "slot synchronization requires valid primary_slot_name" -msgstr "" - #. translator: second %s is a GUC variable name -#: replication/logical/slotsync.c:997 +#: replication/logical/slotsync.c:1000 #, c-format -msgid "The replication slot \"%s\" specified by %s does not exist on the primary server." -msgstr "რეპლიკაციის სლოტი \"%s\", რომელიც %s-მა მიუთითა, არ არსებობს ძირითად სერვერზე." +msgid "replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "რეპლიკაციის სლოტი \"%s\", რომელიც \"%s\"-მა მიუთითა, არ არსებობს ძირითად სერვერზე" -#: replication/logical/slotsync.c:1029 +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1033 #, c-format -msgid "slot synchronization requires dbname to be specified in %s" -msgstr "სლოტის სინქრონიზაციას \"%s\"-ში ბაზის სახელის მითითება სჭირდება" +msgid "replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "რეპლიკაციის სლოტის სინქრონიზაციას სჭირდება, რომ \"%s\" მითითებული იყოს \"%s\"-ში" -#: replication/logical/slotsync.c:1050 +#: replication/logical/slotsync.c:1054 #, c-format -msgid "slot synchronization requires \"wal_level\" >= \"logical\"" -msgstr "სლოტის სინქრონიზაციას \"wal_level\" >= \"logical\" ესაჭიროება" +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "რეპლიკაციის სლოტის სინქრონიზაციას \"wal_level\" >= \"logical\" ესაჭიროება" -#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1067 replication/logical/slotsync.c:1095 #, c-format -msgid "slot synchronization requires %s to be defined" -msgstr "სლოტის სინქრონიზაციას %s-ის აღწერა სჭირდება" +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "რეპლიკაციის სლოტის სინქრონიზაციას \"%s\"-ის დაყენება სჭირდება" -#: replication/logical/slotsync.c:1077 +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1081 #, c-format -msgid "slot synchronization requires %s to be enabled" -msgstr "სლოტის სინქრონიზაციას %s-ის ჩართვა სჭირდება" +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "რეპლიკაციის სლოტის სინქრონიზაციას \"%s\"-ის ჩართვა სჭირდება" #. translator: %s is a GUC variable name -#: replication/logical/slotsync.c:1129 +#: replication/logical/slotsync.c:1133 #, c-format -msgid "slot sync worker will shutdown because %s is disabled" +msgid "replication slot synchronization worker will shut down because \"%s\" is disabled" msgstr "" -#: replication/logical/slotsync.c:1138 +#: replication/logical/slotsync.c:1142 #, c-format -msgid "slot sync worker will restart because of a parameter change" +msgid "replication slot synchronization worker will restart because of a parameter change" msgstr "" -#: replication/logical/slotsync.c:1162 +#: replication/logical/slotsync.c:1166 #, c-format -msgid "slot sync worker is shutting down on receiving SIGINT" +msgid "replication slot synchronization worker is shutting down on receiving SIGINT" msgstr "" -#: replication/logical/slotsync.c:1287 +#: replication/logical/slotsync.c:1291 #, c-format msgid "cannot synchronize replication slots when standby promotion is ongoing" msgstr "რეპლიკაციის სლოტების სინქრონიზაცია შეუძლებელია უქმეს წახალისების მიმდინარეობისას" -#: replication/logical/slotsync.c:1295 +#: replication/logical/slotsync.c:1299 #, c-format msgid "cannot synchronize replication slots concurrently" msgstr "რეპლიკაციის სლოტების ერთდროული სინქრონიზაცია შეუძლებელია" -#: replication/logical/slotsync.c:1403 +#: replication/logical/slotsync.c:1407 #, c-format msgid "slot sync worker started" msgstr "სლოტის სინქრონიზაციის დამხმარე პროცესი გაეშვა" -#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 replication/walreceiver.c:307 +#: replication/logical/slotsync.c:1470 replication/slotfuncs.c:929 #, c-format -msgid "could not connect to the primary server: %s" -msgstr "შეუძლებელია მიერთება ძირითად სერვერთან: %s" +msgid "synchronization worker \"%s\" could not connect to the primary server: %s" +msgstr "სინქრონიზაციის დამხმარე პროცესი \"%s\" ვერ მიუერთდა ძირითად სერვერს: %s" -#: replication/logical/snapbuild.c:643 +#: replication/logical/snapbuild.c:514 #, c-format msgid "initial slot snapshot too large" msgstr "საწყისი სლოტის სწრაფი ასლი ძალიან დიდია" -#: replication/logical/snapbuild.c:697 +#: replication/logical/snapbuild.c:568 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs" msgstr[0] "" msgstr[1] "" -#: replication/logical/snapbuild.c:1392 replication/logical/snapbuild.c:1484 replication/logical/snapbuild.c:2000 +#: replication/logical/snapbuild.c:1305 replication/logical/snapbuild.c:1402 replication/logical/snapbuild.c:1908 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "" -#: replication/logical/snapbuild.c:1394 +#: replication/logical/snapbuild.c:1307 #, c-format msgid "There are no running transactions." msgstr "გაშვებული ტრანზაქციების გარეშე." -#: replication/logical/snapbuild.c:1436 +#: replication/logical/snapbuild.c:1354 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "" -#: replication/logical/snapbuild.c:1438 replication/logical/snapbuild.c:1462 +#: replication/logical/snapbuild.c:1356 replication/logical/snapbuild.c:1380 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "" -#: replication/logical/snapbuild.c:1460 +#: replication/logical/snapbuild.c:1378 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "" -#: replication/logical/snapbuild.c:1486 +#: replication/logical/snapbuild.c:1404 #, c-format msgid "There are no old transactions anymore." msgstr "ძველი ტრანზაქციები აღარ დარჩა." -#: replication/logical/snapbuild.c:1887 +#: replication/logical/snapbuild.c:1775 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "" -#: replication/logical/snapbuild.c:1893 +#: replication/logical/snapbuild.c:1781 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "" -#: replication/logical/snapbuild.c:1934 +#: replication/logical/snapbuild.c:1822 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "" -#: replication/logical/snapbuild.c:2002 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "ლოგიკური გაშიფვრა შენახული სწრაფი ასლის გამოყენებას დაიწყებს." -#: replication/logical/snapbuild.c:2109 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "could not parse file name \"%s\"" msgstr "ფაილის სახელის დამუშავების შეცდომა: \"%s\"" -#: replication/logical/tablesync.c:161 +#: replication/logical/tablesync.c:160 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" msgstr "" -#: replication/logical/tablesync.c:641 +#: replication/logical/tablesync.c:640 #, c-format msgid "logical replication apply worker for subscription \"%s\" will restart so that two_phase can be enabled" msgstr "" -#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 +#: replication/logical/tablesync.c:830 replication/logical/tablesync.c:971 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "" -#: replication/logical/tablesync.c:834 +#: replication/logical/tablesync.c:837 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr "ცხრილი \"%s.%s\" გამომცემელზე ნაპოვნი არაა" -#: replication/logical/tablesync.c:892 +#: replication/logical/tablesync.c:890 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "" -#: replication/logical/tablesync.c:1071 +#: replication/logical/tablesync.c:1069 #, c-format msgid "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: %s" msgstr "" -#: replication/logical/tablesync.c:1230 +#: replication/logical/tablesync.c:1236 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "" -#: replication/logical/tablesync.c:1429 +#: replication/logical/tablesync.c:1351 +#, c-format +msgid "table synchronization worker for subscription \"%s\" could not connect to the publisher: %s" +msgstr "" + +#: replication/logical/tablesync.c:1436 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "ცხრილის კოპირებამ ვერ გაუშვა ტრანზაქცია გამომცემელზე: %s" -#: replication/logical/tablesync.c:1472 +#: replication/logical/tablesync.c:1479 #, c-format msgid "replication origin \"%s\" already exists" msgstr "რეპლიკაციის წყარო \"%s\" უკვე არსებობს" -#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 +#: replication/logical/tablesync.c:1512 replication/logical/worker.c:2383 #, c-format msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" msgstr "" -#: replication/logical/tablesync.c:1518 +#: replication/logical/tablesync.c:1525 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "ცხრილის კოპირებამ ვერ დაასრულა ტრანზაქცია გამომცემელზე: %s" -#: replication/logical/worker.c:481 +#: replication/logical/worker.c:479 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop" msgstr "" -#: replication/logical/worker.c:483 +#: replication/logical/worker.c:481 #, c-format msgid "Cannot handle streamed replication transactions using parallel apply workers until all tables have been synchronized." msgstr "" -#: replication/logical/worker.c:852 replication/logical/worker.c:967 +#: replication/logical/worker.c:851 replication/logical/worker.c:966 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "" -#: replication/logical/worker.c:2500 +#: replication/logical/worker.c:2530 #, c-format msgid "publisher did not send replica identity column expected by the logical replication target relation \"%s.%s\"" msgstr "" -#: replication/logical/worker.c:2507 +#: replication/logical/worker.c:2537 #, c-format msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL" msgstr "" -#: replication/logical/worker.c:3371 +#: replication/logical/worker.c:3472 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "არასწორი ლოგიკური რეპლიკაციის შეტყობინების ტიპი \"??? (%d)\"" -#: replication/logical/worker.c:3543 +#: replication/logical/worker.c:3644 #, c-format msgid "data stream from publisher has ended" msgstr "გამომცემლის მონაცემების ნაკადი დასრულდა" -#: replication/logical/worker.c:3697 +#: replication/logical/worker.c:3798 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "ლოგიკური რეპლიკაციის დამხმარე პროცესის შეწყვეტა მოლოდინის ვადის ამოწურვის გამო" -#: replication/logical/worker.c:3891 +#: replication/logical/worker.c:3995 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed" msgstr "" -#: replication/logical/worker.c:3905 +#: replication/logical/worker.c:4009 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled" msgstr "" -#: replication/logical/worker.c:3936 +#: replication/logical/worker.c:4040 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because of a parameter change" msgstr "" -#: replication/logical/worker.c:3940 +#: replication/logical/worker.c:4044 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because of a parameter change" msgstr "" -#: replication/logical/worker.c:3954 +#: replication/logical/worker.c:4058 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because the subscription owner's superuser privileges have been revoked" msgstr "ლოგიკური რეპლიკაციის პარალელური გადატარების დამხმარე პროცესი გამოწერისთვის \"%s\" გაჩერდება, რადგან გამოწერის მფლობელის ზემომხმარებლის პრივილეგიები გაუქმდა" -#: replication/logical/worker.c:3958 +#: replication/logical/worker.c:4062 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because the subscription owner's superuser privileges have been revoked" msgstr "" -#: replication/logical/worker.c:4478 +#: replication/logical/worker.c:4564 #, c-format msgid "subscription has no replication slot set" msgstr "გამოწერას რეპლიკაციის სლოტი დაყენებული არ აქვს" -#: replication/logical/worker.c:4591 +#: replication/logical/worker.c:4589 +#, c-format +msgid "apply worker for subscription \"%s\" could not connect to the publisher: %s" +msgstr "დამხმარე პროცესის გამოყენება გამოწერისთვის \"%s\" ვერ მიუერთდა გამომცემელს: %s" + +#: replication/logical/worker.c:4678 #, c-format msgid "logical replication worker for subscription %u will not start because the subscription was removed during startup" msgstr "" -#: replication/logical/worker.c:4607 +#: replication/logical/worker.c:4694 #, c-format msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup" msgstr "" -#: replication/logical/worker.c:4631 +#: replication/logical/worker.c:4718 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" msgstr "" -#: replication/logical/worker.c:4636 +#: replication/logical/worker.c:4723 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "გაეშვა ლოგიკური რეპლიკაციის გადატარების დამხმარე პროცესი გამოწერისთვის \"%s\"" -#: replication/logical/worker.c:4734 +#: replication/logical/worker.c:4845 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "გამოწერა \"%s\" გაითიშა შეცდომის გამო" -#: replication/logical/worker.c:4782 +#: replication/logical/worker.c:4893 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "ლოგიკური რეპლიკაცია იწყებს ტრანზაქციის გამოტოვებას მისამართზე LSN %X/%X" -#: replication/logical/worker.c:4796 +#: replication/logical/worker.c:4907 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "ლოგიკურმა რეპლიკაციამ დაასრულა ტრანზაქციის გამოტოვება მისამართზე LSN %X/%X" -#: replication/logical/worker.c:4878 +#: replication/logical/worker.c:4989 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "skip-LSN გამოწერისთვის \"%s\" გასუფთავებულია" -#: replication/logical/worker.c:4879 +#: replication/logical/worker.c:4990 #, c-format msgid "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X." msgstr "" -#: replication/logical/worker.c:4905 +#: replication/logical/worker.c:5027 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\"" msgstr "" -#: replication/logical/worker.c:4909 +#: replication/logical/worker.c:5031 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u" msgstr "" -#: replication/logical/worker.c:4914 +#: replication/logical/worker.c:5036 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X" msgstr "" -#: replication/logical/worker.c:4925 +#: replication/logical/worker.c:5047 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u" msgstr "" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:5054 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X" msgstr "" -#: replication/logical/worker.c:4943 +#: replication/logical/worker.c:5065 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" msgstr "" -#: replication/logical/worker.c:4951 +#: replication/logical/worker.c:5073 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X" msgstr "" -#: replication/pgoutput/pgoutput.c:315 +#: replication/pgoutput/pgoutput.c:328 #, c-format msgid "invalid proto_version" msgstr "არასწორი proto_version" -#: replication/pgoutput/pgoutput.c:320 +#: replication/pgoutput/pgoutput.c:333 #, c-format msgid "proto_version \"%s\" out of range" msgstr "proto_version \"%s\" დიაპაზონს გარეთაა" -#: replication/pgoutput/pgoutput.c:337 +#: replication/pgoutput/pgoutput.c:350 #, c-format msgid "invalid publication_names syntax" msgstr "არასწორი publication_names syntax" -#: replication/pgoutput/pgoutput.c:407 -#, c-format -msgid "proto_version option missing" -msgstr "პარამეტრი proto_version მითითებული არაა" - -#: replication/pgoutput/pgoutput.c:411 +#: replication/pgoutput/pgoutput.c:420 replication/pgoutput/pgoutput.c:424 #, c-format -msgid "publication_names option missing" -msgstr "აკლა პარამეტრი publication_names" +msgid "option \"%s\" missing" +msgstr "პარამეტრი \"%s\" აკლია" -#: replication/pgoutput/pgoutput.c:452 +#: replication/pgoutput/pgoutput.c:469 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or lower" msgstr "კლიენტმა გამოაგზავნა proto_version=%d მაგრამ სერვერს მხოლოდ %d პროტოკოლის და ქვემოთ გააჩნია მხარდაჭერა" -#: replication/pgoutput/pgoutput.c:458 +#: replication/pgoutput/pgoutput.c:475 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or higher" msgstr "კლიენტმა გამოაგზავნა proto_version=%d მაგრამ სერვერს მხოლოდ %d პროტოკოლის და ზემოთ გააჩნია მხარდაჭერა" -#: replication/pgoutput/pgoutput.c:473 +#: replication/pgoutput/pgoutput.c:490 #, c-format msgid "requested proto_version=%d does not support streaming, need %d or higher" msgstr "" -#: replication/pgoutput/pgoutput.c:479 +#: replication/pgoutput/pgoutput.c:496 #, c-format msgid "requested proto_version=%d does not support parallel streaming, need %d or higher" msgstr "" -#: replication/pgoutput/pgoutput.c:484 +#: replication/pgoutput/pgoutput.c:501 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "" -#: replication/pgoutput/pgoutput.c:498 +#: replication/pgoutput/pgoutput.c:515 #, c-format msgid "requested proto_version=%d does not support two-phase commit, need %d or higher" msgstr "" -#: replication/pgoutput/pgoutput.c:503 +#: replication/pgoutput/pgoutput.c:520 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "" -#: replication/slot.c:260 +#: replication/pgoutput/pgoutput.c:1085 +#, c-format +msgid "cannot use different values of publish_generated_columns for table \"%s.%s\" in different publications" +msgstr "" + +#: replication/pgoutput/pgoutput.c:1792 +#, c-format +msgid "skipped loading publication: %s" +msgstr "გამოტოვებულია ჩატვირთვა პუბლიკაციისთვის: %s" + +#: replication/pgoutput/pgoutput.c:1793 +#, c-format +msgid "The publication does not exist at this point in the WAL." +msgstr "WAL-ში ამ წერტილთან პუბლიკაცია არ არსებობს." + +#: replication/pgoutput/pgoutput.c:1794 +#, c-format +msgid "Create the publication if it does not exist." +msgstr "პუბლიკაციის შექმნა, თუ ის არ არსებობს." + +#: replication/slot.c:275 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "რეპლიკაციის სლოტის სახელი \"%s\" ძალიან მოკლეა" -#: replication/slot.c:269 +#: replication/slot.c:284 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "რეპლიკაციის სლოტის სახელი \"%s\" ძალიან გრძელია" -#: replication/slot.c:282 +#: replication/slot.c:297 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "რეპლიკაციის სლოტის სახელი \"%s\" არასწორ სიმბოლოს შეიცავს" -#: replication/slot.c:284 +#: replication/slot.c:299 #, c-format msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character." msgstr "" -#: replication/slot.c:333 +#: replication/slot.c:348 #, c-format msgid "cannot enable failover for a replication slot created on the standby" msgstr "" -#: replication/slot.c:345 replication/slot.c:849 +#: replication/slot.c:360 replication/slot.c:885 #, c-format msgid "cannot enable failover for a temporary replication slot" msgstr "დროებითი რეპლიკაციის სლოტისთვის გადართვის ჩართვა შეუძლებელია" -#: replication/slot.c:370 +#: replication/slot.c:385 #, c-format msgid "replication slot \"%s\" already exists" msgstr "რეპლიკაციის სლოტი \"%s\" უკვე არსებობს" -#: replication/slot.c:380 +#: replication/slot.c:395 #, c-format msgid "all replication slots are in use" msgstr "ყველა რეპლიკაციის სლოტი გამოიყენება" -#: replication/slot.c:381 +#: replication/slot.c:396 #, c-format msgid "Free one or increase \"max_replication_slots\"." msgstr "გაათავისუფლეთ ერთი მაინც ან გაზარდეთ \"max_replication_slots\"." -#: replication/slot.c:560 replication/slot.c:2453 replication/slotfuncs.c:661 utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 +#: replication/slot.c:579 replication/slotfuncs.c:664 utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:739 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "რეპლიკაციის სლოტი არ არსებობს: %s" -#: replication/slot.c:606 replication/slot.c:1337 +#: replication/slot.c:634 replication/slot.c:1388 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "რეპლიკაციის სლოტი (%s) აქტიურია PID-ისთვის %d" -#: replication/slot.c:638 +#: replication/slot.c:651 +#, c-format +msgid "can no longer access replication slot \"%s\"" +msgstr "რეპლიკაციის სლოტთან \"%s\" წვდომა აღარ მაქვს" + +#: replication/slot.c:653 +#, c-format +msgid "This replication slot has been invalidated due to \"%s\"." +msgstr "ეს რეპლიკაციის სლოტი მონიშნულია, როგორც არასწორი \"%s\"-ის გამო." + +#: replication/slot.c:672 #, c-format msgid "acquired logical replication slot \"%s\"" msgstr "მივიღე ლოგიკური რეპლიკაციის სლოტი \"%s\"" -#: replication/slot.c:640 +#: replication/slot.c:674 #, c-format msgid "acquired physical replication slot \"%s\"" msgstr "მივიღე ფიზიკური რეპლიკაციის სლოტი \"%s\"" -#: replication/slot.c:729 +#: replication/slot.c:759 #, c-format msgid "released logical replication slot \"%s\"" msgstr "გათავისუფლდა ლოგიკური რეპლიკაციის სლოტი \"%s\"" -#: replication/slot.c:731 +#: replication/slot.c:761 #, c-format msgid "released physical replication slot \"%s\"" msgstr "გათავისუფლდა ფიზიკური რეპლიკაციის სლოტი \"%s\"" -#: replication/slot.c:797 +#: replication/slot.c:827 #, c-format msgid "cannot drop replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის \"%s\" წაშლის შეცდომა" -#: replication/slot.c:798 replication/slot.c:829 -#, c-format -msgid "This slot is being synced from the primary server." -msgstr "მიმდინარეობს ამ სლოტის სინქრონიზაცია ძირითადი სერვერიდან." - -#: replication/slot.c:816 +#: replication/slot.c:850 #, c-format msgid "cannot use %s with a physical replication slot" msgstr "%s-ის გამოყენება ფიზიკური რეპლიკაციის სლოტთან ერთად შეუძლებელია" -#: replication/slot.c:828 +#: replication/slot.c:862 #, c-format msgid "cannot alter replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის \"%s\" შეცვლა შეუძლებელია" -#: replication/slot.c:838 +#: replication/slot.c:872 #, c-format msgid "cannot enable failover for a replication slot on the standby" msgstr "" -#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 +#: replication/slot.c:1020 replication/slot.c:2120 replication/slot.c:2505 #, c-format msgid "could not remove directory \"%s\"" msgstr "საქაღალდის (\"%s\") წაშლის შეცდომა" -#: replication/slot.c:1372 +#: replication/slot.c:1423 #, c-format msgid "replication slots can only be used if \"max_replication_slots\" > 0" msgstr "რეპლიკაციის სლოტების გამოყენება შესაძლებელია, მხოლოდ, როცა \"max_replication_slots\" > 0" -#: replication/slot.c:1377 +#: replication/slot.c:1428 #, c-format msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" msgstr "რეპლიკაციის სლოტების გამოყენება შესაძლებელია, მხოლოდ, როცა \"wal_level\" >= \"replica\"" -#: replication/slot.c:1389 +#: replication/slot.c:1440 #, c-format msgid "permission denied to use replication slots" msgstr "რეპლიკაციის სლოტების გამოყენების წვდომა აკრძალულია" -#: replication/slot.c:1390 +#: replication/slot.c:1441 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "" -#: replication/slot.c:1498 +#: replication/slot.c:1550 #, c-format -msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." -msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." +msgid "The slot's restart_lsn %X/%X exceeds the limit by % byte." +msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by % bytes." msgstr[0] "" msgstr[1] "" -#: replication/slot.c:1506 +#: replication/slot.c:1561 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "სლოტი კონფლიქტშია XID-ის ჰორიზონტთან %u." -#: replication/slot.c:1511 +#: replication/slot.c:1566 msgid "Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server." msgstr "ლოგიკურ გაშიფვრას უქმეზე ძირითად სერვერზე \"wal_level\" >= \"logical\" ესაჭიროება." -#: replication/slot.c:1519 +#. translator: %s is a GUC variable name +#: replication/slot.c:1575 +#, c-format +msgid "The slot's idle time of %dmin %02ds exceeds the configured \"%s\" duration of %dmin." +msgstr "" + +#: replication/slot.c:1589 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის (%2$s) გასათავისუფლებლად მოხდება პროცესის მოკვლა: %1$d" -#: replication/slot.c:1521 +#: replication/slot.c:1591 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "მოძველებული რეპლიკაციის სლოტის (\"%s\") არასწორად გამოცხადება" -#: replication/slot.c:2249 +#: replication/slot.c:2443 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "რეპლიკაციის სლოტის (%s) ფაილის არასწორი მაგიური რიცხვი: %u (უნდა იყოს %u)" -#: replication/slot.c:2256 +#: replication/slot.c:2450 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "რეპლიკაციის სლოტის ფაილის (%s) მხარდაუჭერელი ვერსია %u" -#: replication/slot.c:2263 +#: replication/slot.c:2457 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "რეპლიკაციის სლოტის ფაილის (%s) დაზიანებული სიგრძე: %u" -#: replication/slot.c:2299 +#: replication/slot.c:2493 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "" -#: replication/slot.c:2333 +#: replication/slot.c:2529 #, c-format msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" msgstr "ლოგიკური რეპლიკაციის სლოტი\"%s\" არსებობს, მაგრამ \"wal_level\" < \"logical\"" -#: replication/slot.c:2335 +#: replication/slot.c:2531 #, c-format msgid "Change \"wal_level\" to be \"logical\" or higher." msgstr "შეცვალეთ \"wal_level\" \"logical\"-ზე ან უფრო მაღალზე." -#: replication/slot.c:2339 +#: replication/slot.c:2543 +#, c-format +msgid "logical replication slot \"%s\" exists on the standby, but \"hot_standby\" = \"off\"" +msgstr "ლოგიკური რეპლიკაციის სლოტი\"%s\" არსებობს, მაგრამ \"hot_standby\" = \"off\"" + +#: replication/slot.c:2545 +#, c-format +msgid "Change \"hot_standby\" to be \"on\"." +msgstr "" + +#: replication/slot.c:2550 #, c-format msgid "physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" msgstr "ფიზიკური რეპლიკაციის სლოტი\"%s\" არსებობს, მაგრამ \"wal_level\" < \"replica\"" -#: replication/slot.c:2341 +#: replication/slot.c:2552 #, c-format msgid "Change \"wal_level\" to be \"replica\" or higher." msgstr "შეცვალეთ \"wal_level\" \"replica\"-ზე ან ზემოთ." -#: replication/slot.c:2383 +#: replication/slot.c:2598 #, c-format msgid "too many replication slots active before shutdown" msgstr "გამორთვამდე მეტისმეტად ბევრი რეპლიკაციის სლოტი იყო აქტიური" -#: replication/slot.c:2461 +#: replication/slot.c:2599 #, c-format -msgid "\"%s\" is not a physical replication slot" -msgstr "\"%s\" ფიზიკური რეპლიკაციის სლოტი არაა" +msgid "Increase \"max_replication_slots\" and try again." +msgstr "გაზარდეთ \"max_replication_slots\"-ის მნიშვნელობა და თავიდან სცადეთ." -#: replication/slot.c:2637 +#: replication/slot.c:2676 #, c-format -msgid "replication slot \"%s\" specified in parameter %s does not exist" -msgstr "რეპლიკაციის სლოტმა \"%s\" მიუთითა პარამეტრი %s, რომელიც არ არსებობს" +msgid "Replication slot \"%s\" does not exist." +msgstr "რეპლიკაციის სლოტი \"%s\" არ არსებობს." -#: replication/slot.c:2639 replication/slot.c:2680 replication/slot.c:2695 +#: replication/slot.c:2684 #, c-format -msgid "Logical replication is waiting on the standby associated with \"%s\"." -msgstr "ლოგიკური რეპლიკაცია \"%s\"-სთან ასოცირებულ უქმეს ელოდება." +msgid "\"%s\" is not a physical replication slot." +msgstr "\"%s\" ფიზიკური რეპლიკაციის სლოტი არაა." -#: replication/slot.c:2641 +#: replication/slot.c:2863 #, c-format -msgid "Consider creating the slot \"%s\" or amend parameter %s." -msgstr "განიხილეთ, შექმნათ სლოტი \"%s\", ან მიაწერეთ პარამეტრი %s." +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "რეპლიკაციის სლოტი \"%s\", მითითებული პარამეტრში %s, არ არსებობს" -#: replication/slot.c:2658 +#: replication/slot.c:2865 replication/slot.c:2899 replication/slot.c:2914 #, c-format -msgid "cannot have logical replication slot \"%s\" in parameter %s" -msgstr "ვერ გექნებათ ლოგიკური რეპლიკაციის სლოტი \"%s\" პარამეტრში %s" +msgid "Logical replication is waiting on the standby associated with replication slot \"%s\"." +msgstr "ლოგიკური რეპლიკაცია ელოდება უქმე სლოტს, რომელიც დაკავშირებულია რეპლიკაციის სლოტთან \"%s\"." -#: replication/slot.c:2660 +#: replication/slot.c:2867 #, c-format -msgid "Logical replication is waiting for correction on \"%s\"." -msgstr "ლოგიკური რეპლიკაციის სლოტი ელოდება გასწორებას \"%s\"-ზე." +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "შექმენით რეპლიკაციის სლოტი \"%s\" ან შეცვალეთ პარამეტრი \"%s\"." -#: replication/slot.c:2662 +#: replication/slot.c:2877 #, c-format -msgid "Consider removing logical slot \"%s\" from parameter %s." -msgstr "" +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "ვერ მიუთითებთ ლოგიკური რეპლიკაციის სლოტს \"%s\" პარამეტრში \"%s\"" -#: replication/slot.c:2678 +#: replication/slot.c:2879 #, c-format -msgid "physical slot \"%s\" specified in parameter %s has been invalidated" -msgstr "" +msgid "Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "ლოგიკური რეპლიკაცია ელოდება კორექტირებას რეპლიკაციის სლოტზე \"%s\"." -#: replication/slot.c:2682 +#: replication/slot.c:2881 #, c-format -msgid "Consider dropping and recreating the slot \"%s\" or amend parameter %s." -msgstr "განიხილეთ მოცილება ან თავიდან შექმნა სლოტისთვის \"%s\" ან მიაწერეთ პარამეტრი %s." +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "წაშალეთ ლოგიკური რეპლიკაციის სლოტი \"%s\" პარამეტრიდან \"%s\"." -#: replication/slot.c:2693 +#: replication/slot.c:2897 #, c-format -msgid "replication slot \"%s\" specified in parameter %s does not have active_pid" -msgstr "რეპლიკაციის სლოტს \"%s\", რომელიც მითითებულია პარამეტრში %s, active_pid არ გააჩნია" +msgid "physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated" +msgstr "ფიზიკური რეპლიკაციის სლოტი \"%s\", მითითებული პარამეტრში \"%s\", გაუქმებულია" -#: replication/slot.c:2697 +#: replication/slot.c:2901 #, c-format -msgid "Consider starting standby associated with \"%s\" or amend parameter %s." -msgstr "" +msgid "Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "განიხილეთ მოცილება ან თავიდან შექმნა სლოტისთვის \"%s\" ან მიაწერეთ პარამეტრი \"%s\"." + +#: replication/slot.c:2912 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not have active_pid" +msgstr "რეპლიკაციის სლოტი \"%s\", რომელიც მითითებულია პარამეტრში \"%s\", active_pid არ გააჩნია" + +#: replication/slot.c:2916 +#, c-format +msgid "Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "გაუშვით უქმე, ასოცირებული რეპლიკაციის სლოტთან \"%s\", ან მიაწერეთ პარამეტრი \"%s\"." + +#: replication/slot.c:3008 +#, c-format +msgid "\"%s\" must be set to 0 during binary upgrade mode." +msgstr "ბინარული განახლების რეჟიმისას \"%s\"-ის მნიშვნელობა 0-ზე უნდა დააყენოთ." -#: replication/slotfuncs.c:526 +#: replication/slotfuncs.c:529 #, c-format msgid "invalid target WAL LSN" msgstr "არასწორი სამიზნე WAL LSN" -#: replication/slotfuncs.c:548 +#: replication/slotfuncs.c:551 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "რეპლიკაციის სლოტის (%s) წინ წაწევა შეუძლებელია" -#: replication/slotfuncs.c:550 +#: replication/slotfuncs.c:553 #, c-format msgid "This slot has never previously reserved WAL, or it has been invalidated." msgstr "" -#: replication/slotfuncs.c:566 +#: replication/slotfuncs.c:569 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "" -#: replication/slotfuncs.c:673 +#: replication/slotfuncs.c:676 #, c-format msgid "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "ფიზიკური რეპლიკაციის სლოტის (%s) ლოგიკურ სლოტად კოპირება შეუძლებელია" -#: replication/slotfuncs.c:675 +#: replication/slotfuncs.c:678 #, c-format msgid "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "ლოგიკური რეპლიკაციის სლოტის (%s) ფიზიკურ სლოტად კოპირება შეუძლებელია" -#: replication/slotfuncs.c:682 +#: replication/slotfuncs.c:685 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "რეპლიკაციის სლოტის, რომელიც WAL რეზერვაციას არ აკეთებს, კოპირება შეუძლებელია" -#: replication/slotfuncs.c:768 +#: replication/slotfuncs.c:691 +#, c-format +msgid "cannot copy invalidated replication slot \"%s\"" +msgstr "არასწორად გამოცხადებული რეპლიკაციის სლოტის \"%s\" კოპირება შეუძლებელია" + +#: replication/slotfuncs.c:783 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის კოპირების შეცდომა: %s" -#: replication/slotfuncs.c:770 +#: replication/slotfuncs.c:785 #, c-format msgid "The source replication slot was modified incompatibly during the copy operation." msgstr "კოპირების ოპერაციისას საწყისი რეპლიკაციის სლოტი შეუთავსებლად შეიცვალა." -#: replication/slotfuncs.c:776 +#: replication/slotfuncs.c:791 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "დაუმთავრებელი ლოგიკური რეპლიკაციის სლოტის კოპირება შეუძლებელია: %s" -#: replication/slotfuncs.c:778 +#: replication/slotfuncs.c:793 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "" -#: replication/slotfuncs.c:877 +#: replication/slotfuncs.c:805 +#, c-format +msgid "cannot copy replication slot \"%s\"" +msgstr "რეპლიკაციის სლოტის \"%s\" კოპირება შეუძლებელია" + +#: replication/slotfuncs.c:807 +#, c-format +msgid "The source replication slot was invalidated during the copy operation." +msgstr "კოპირების ოპერაციისას საწყისი რეპლიკაციის სლოტი არასწორად გამოცხადდა." + +#: replication/slotfuncs.c:906 #, c-format msgid "replication slots can only be synchronized to a standby server" msgstr "რეპლიკაციის სლოტების სინქრონიზაცია, მხოლოდ, უქმე სერვერთანაა შესაძლებელი" -#: replication/syncrep.c:261 +#: replication/syncrep.c:304 #, c-format msgid "canceling the wait for synchronous replication and terminating connection due to administrator command" msgstr "" -#: replication/syncrep.c:262 replication/syncrep.c:279 +#: replication/syncrep.c:305 replication/syncrep.c:322 #, c-format msgid "The transaction has already committed locally, but might not have been replicated to the standby." msgstr "ტრანზაქცია უკვე გადაცემულია ლოკალურად, მაგრამ შეიძლება მომლოდინეზე ჯერ რეპლიცირებული არაა." -#: replication/syncrep.c:278 +#: replication/syncrep.c:321 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "სინქრონული რეპლიკაციის მოლოდინის გაუქმება მომხმარებლის მოთხოვნის გამო" -#: replication/syncrep.c:485 +#: replication/syncrep.c:528 #, c-format msgid "standby \"%s\" is now a synchronous standby with priority %d" msgstr "" -#: replication/syncrep.c:489 +#: replication/syncrep.c:532 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "" -#: replication/syncrep.c:1013 +#: replication/syncrep.c:1081 #, c-format -msgid "\"synchronous_standby_names\" parser failed" -msgstr "\"synchronous_standby_names\"-ის დამმუშავებლის შეცდომა" +msgid "\"%s\" parser failed." +msgstr "\"%s\"-ის დამმუშავებლის შეცდომა." -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1088 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "სინქრონული მომლოდინეების რაოდენობა (%d) ნულზე მეტი უნდა იყოს" -#: replication/walreceiver.c:176 +#: replication/walreceiver.c:276 #, c-format -msgid "terminating walreceiver process due to administrator command" -msgstr "walreceiver პროგრამის შეწყვეტა ადმინისტრატორის ბრძანების გამო" +msgid "streaming replication receiver \"%s\" could not connect to the primary server: %s" +msgstr "სტრიმინგის რეპლიკაციის მიმღები \"%s\" ვერ დაუკავშირდა ძირითად სერვერს: %s" -#: replication/walreceiver.c:354 +#: replication/walreceiver.c:324 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "ბაზის სისტემის იდენტიფიკატორი განსხვავდება ძირითადსა და მომლოდინეს შორის" -#: replication/walreceiver.c:355 +#: replication/walreceiver.c:325 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "ძირითადი სერვერის იდენტიფიკატორია %s, მომლოდინესი კი %s." -#: replication/walreceiver.c:366 +#: replication/walreceiver.c:336 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "" -#: replication/walreceiver.c:419 +#: replication/walreceiver.c:389 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "" -#: replication/walreceiver.c:423 +#: replication/walreceiver.c:393 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "" -#: replication/walreceiver.c:458 +#: replication/walreceiver.c:428 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:472 #, c-format msgid "replication terminated by primary server" msgstr "რეპლიკაცია შეწყვეტილია ძირითადი სერვერის მიერ" -#: replication/walreceiver.c:503 +#: replication/walreceiver.c:473 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "" -#: replication/walreceiver.c:593 +#: replication/walreceiver.c:573 #, c-format msgid "terminating walreceiver due to timeout" msgstr "walreceiver პროგრამის შეწყვეტა მოლოდინის ვადის ამოწურვის გამო" -#: replication/walreceiver.c:625 +#: replication/walreceiver.c:605 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "" -#: replication/walreceiver.c:641 replication/walreceiver.c:1071 +#: replication/walreceiver.c:621 replication/walreceiver.c:1063 #, c-format msgid "could not close WAL segment %s: %m" msgstr "'WAL' სეგმენტის %s დახურვის შეცდომა: %m" -#: replication/walreceiver.c:760 +#: replication/walreceiver.c:740 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "" -#: replication/walreceiver.c:959 +#: replication/walreceiver.c:951 #, c-format msgid "could not write to WAL segment %s at offset %d, length %lu: %m" msgstr "'WAL'-ის სეგმენტში (%s) ჩაწერის შეცდომა. წანაცვლება %d, სიგრძე %lu: %m" -#: replication/walsender.c:531 +#: replication/walsender.c:505 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "%s-ის გამოყენება ლოგიკური რეპლიკაციის სლოტთან ერთად შეუძლებელია" -#: replication/walsender.c:635 storage/smgr/md.c:1723 +#: replication/walsender.c:609 storage/smgr/md.c:1867 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "ფაილის (\"%s\") ბოლოში გადახვევის პრობლემა: %m" -#: replication/walsender.c:639 +#: replication/walsender.c:613 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "ფაილის (\"%s\") დასაწყისში გადახვევის პრობლემა: %m" -#: replication/walsender.c:853 +#: replication/walsender.c:829 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "" -#: replication/walsender.c:919 +#: replication/walsender.c:895 #, c-format msgid "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "" -#: replication/walsender.c:922 +#: replication/walsender.c:898 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "" -#: replication/walsender.c:966 +#: replication/walsender.c:942 #, c-format msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X" msgstr "" -#: replication/walsender.c:1160 +#: replication/walsender.c:1137 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "უცნობი მნიშვნელობა CREATE_REPLICATION_SLOT-ის პარამეტრისთვის \"%s\": \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1266 +#: replication/walsender.c:1243 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s ტრანზაქცის შიგნიდან არ უნდა გამოიძახოთ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1276 +#: replication/walsender.c:1253 #, c-format msgid "%s must be called inside a transaction" msgstr "%s ტრანზაქციის შიგნიდან უნდა გამოიძახოთ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1282 +#: replication/walsender.c:1259 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1287 +#: replication/walsender.c:1264 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%s მხოლოდ-წაკითხვად ტრანზაქციაში უნდა გამოიძახოთ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1293 +#: replication/walsender.c:1270 #, c-format msgid "%s must be called before any query" msgstr "%s ყველა მოთხოვნაზე ადრე უნდა გამოიძახოთ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1299 +#: replication/walsender.c:1276 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s ქვეტრანზაქციაში არ უნდა გამოიძახოთ" -#: replication/walsender.c:1472 +#: replication/walsender.c:1453 #, c-format msgid "terminating walsender process after promotion" msgstr "walsender პროცესის შეწყვეტა დაწინაურების შემდეგ" -#: replication/walsender.c:2000 +#: replication/walsender.c:1994 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "'WAL'-გამგზავნის გაჩერების რეჟიმში ყოფნის დროს ახალი ბრძანებების შესრულება შეუძლებელია" -#: replication/walsender.c:2035 +#: replication/walsender.c:2029 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "ფიზიკური რეპლიკაციისთვის WAL-ის გამგზავნში SQL ბრძანებების შესრულება შეუძლებელია" -#: replication/walsender.c:2068 +#: replication/walsender.c:2060 #, c-format msgid "received replication command: %s" msgstr "მიღებულია რეპლიკაციის ბრძანება: %s" -#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1138 tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2206 tcop/postgres.c:2644 tcop/postgres.c:2722 +#: replication/walsender.c:2068 tcop/fastpath.c:208 tcop/postgres.c:1137 tcop/postgres.c:1495 tcop/postgres.c:1747 tcop/postgres.c:2253 tcop/postgres.c:2690 tcop/postgres.c:2767 #, c-format msgid "current transaction is aborted, commands ignored until end of transaction block" msgstr "" -#: replication/walsender.c:2233 replication/walsender.c:2268 +#: replication/walsender.c:2225 replication/walsender.c:2260 #, c-format msgid "unexpected EOF on standby connection" msgstr "მოულოდნელი EOF მომლოდინის მიერთებაზე" -#: replication/walsender.c:2256 +#: replication/walsender.c:2248 #, c-format msgid "invalid standby message type \"%c\"" msgstr "არასწორი მომლოდინის შეტყობინების ტიპი \"%c\"" -#: replication/walsender.c:2345 +#: replication/walsender.c:2337 #, c-format msgid "unexpected message type \"%c\"" msgstr "შეტყობინების მოულოდნელი ტიპი: \"%c\"" -#: replication/walsender.c:2759 +#: replication/walsender.c:2751 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "walsender პროცესის შეწყვეტა რეპლიკაციის მოლოდინის ვადის ამოწურვის გამო" @@ -21647,280 +22289,285 @@ msgstr "წესი %s ურთიერთობისთვის \"%s\" ა msgid "renaming an ON SELECT rule is not allowed" msgstr "'ON SELECT' წესზე სახელის გადარქმევა დაუშვებელია" -#: rewrite/rewriteHandler.c:581 +#: rewrite/rewriteHandler.c:590 #, c-format msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten" msgstr "" -#: rewrite/rewriteHandler.c:608 +#: rewrite/rewriteHandler.c:617 #, c-format msgid "INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH" msgstr "INSERT … SELECT წესის ქმედებები მხარდაუჭერელია მოთხოვნებისთვის, რომლებსაც WITH-ის შემცველი მონაცემების შემცვლელი გამოსახულებები გააჩნიათ" -#: rewrite/rewriteHandler.c:661 +#: rewrite/rewriteHandler.c:671 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "" -#: rewrite/rewriteHandler.c:893 rewrite/rewriteHandler.c:932 +#: rewrite/rewriteHandler.c:908 rewrite/rewriteHandler.c:947 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:961 +#: rewrite/rewriteHandler.c:910 rewrite/rewriteHandler.c:976 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "" -#: rewrite/rewriteHandler.c:897 +#: rewrite/rewriteHandler.c:912 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "გადასაფარად გამოიყენეთ OVERRIDING SYSTEM VALUE." -#: rewrite/rewriteHandler.c:959 rewrite/rewriteHandler.c:967 +#: rewrite/rewriteHandler.c:974 rewrite/rewriteHandler.c:982 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "სვეტი \"%s\" მხოლოდ DEFAULT-მდე შეიძლება, განახლდეს" -#: rewrite/rewriteHandler.c:1114 rewrite/rewriteHandler.c:1132 +#: rewrite/rewriteHandler.c:1118 rewrite/rewriteHandler.c:1136 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "" -#: rewrite/rewriteHandler.c:1697 +#: rewrite/rewriteHandler.c:1691 #, c-format msgid "MERGE is not supported for relations with rules." msgstr "წესების მქონე ურთიერთობებისთვის MERGE მხარდაჭერილი არაა." -#: rewrite/rewriteHandler.c:2110 rewrite/rewriteHandler.c:4197 +#: rewrite/rewriteHandler.c:1731 rewrite/rewriteHandler.c:3271 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "" + +#: rewrite/rewriteHandler.c:2130 rewrite/rewriteHandler.c:4265 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "" -#: rewrite/rewriteHandler.c:2195 +#: rewrite/rewriteHandler.c:2235 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "" -#: rewrite/rewriteHandler.c:2547 +#: rewrite/rewriteHandler.c:2598 msgid "Junk view columns are not updatable." msgstr "ნაგვის ნახვის სვეტები განახლებადი არაა." -#: rewrite/rewriteHandler.c:2552 +#: rewrite/rewriteHandler.c:2603 msgid "View columns that are not columns of their base relation are not updatable." msgstr "ხედის სვეტები, რომლებიც მათი საბაზისო ურთიერთობის სვეტები არიან, განახლებადი არაა." -#: rewrite/rewriteHandler.c:2555 +#: rewrite/rewriteHandler.c:2606 msgid "View columns that refer to system columns are not updatable." msgstr "ხედის სვეტები, რომლებიც სისტემურ სვეტებზეა მიბმული, განახლებადი არაა." -#: rewrite/rewriteHandler.c:2558 +#: rewrite/rewriteHandler.c:2609 msgid "View columns that return whole-row references are not updatable." msgstr "ხედის სვეტები, რომლებიც მთელ-მწკრივიან ბმებზე მიუთითებენ, განახლებადი არაა." -#: rewrite/rewriteHandler.c:2619 +#: rewrite/rewriteHandler.c:2670 msgid "Views containing DISTINCT are not automatically updatable." msgstr "\"DISTINCT\"-ის შემცველი ხედები განახლებადი არაა." -#: rewrite/rewriteHandler.c:2622 +#: rewrite/rewriteHandler.c:2673 msgid "Views containing GROUP BY are not automatically updatable." msgstr "\"GROUP BY\"-ის შემცველი ხედები თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2625 +#: rewrite/rewriteHandler.c:2676 msgid "Views containing HAVING are not automatically updatable." msgstr "\"HAVING\"-ის შემცველი ხედები თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2628 +#: rewrite/rewriteHandler.c:2679 msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "\"UNION\"-ის, \"INTERSECT\"-ის და \"EXCEPT\"-ის შემცველი ხედები თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2631 +#: rewrite/rewriteHandler.c:2682 msgid "Views containing WITH are not automatically updatable." msgstr "\"WITH\"-ის შემცველი ხედები თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2634 +#: rewrite/rewriteHandler.c:2685 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "\"LIMIT\"-ის და \"OFFSET\"-ის შემცველი ხედები თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2646 +#: rewrite/rewriteHandler.c:2697 msgid "Views that return aggregate functions are not automatically updatable." msgstr "ხედები, რომლებიც აგრეგატულ ფუნქციებს აბრუნებენ, თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2649 +#: rewrite/rewriteHandler.c:2700 msgid "Views that return window functions are not automatically updatable." msgstr "ხედები, რომლებიც ფანჯრის ფუნქციებს აბრუნებენ, თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2652 +#: rewrite/rewriteHandler.c:2703 msgid "Views that return set-returning functions are not automatically updatable." msgstr "ხედები, რომლებიც აბრუნებენ ფუნქციებს, რომლებიც სეტებს აბრუნებენ, თვითგანახლებადი არაა." -#: rewrite/rewriteHandler.c:2659 rewrite/rewriteHandler.c:2663 rewrite/rewriteHandler.c:2671 +#: rewrite/rewriteHandler.c:2710 rewrite/rewriteHandler.c:2714 rewrite/rewriteHandler.c:2722 msgid "Views that do not select from a single table or view are not automatically updatable." msgstr "" -#: rewrite/rewriteHandler.c:2674 +#: rewrite/rewriteHandler.c:2725 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "" -#: rewrite/rewriteHandler.c:2698 +#: rewrite/rewriteHandler.c:2749 msgid "Views that have no updatable columns are not automatically updatable." msgstr "ხედები, რომლებსაც განახლებადი ცხრილები არ გააჩნია, ავტომატურად განახლებადები არ არიან." -#: rewrite/rewriteHandler.c:3079 rewrite/rewriteHandler.c:3114 +#: rewrite/rewriteHandler.c:3130 rewrite/rewriteHandler.c:3165 #, c-format msgid "cannot insert into view \"%s\"" msgstr "ხედში ჩამატება შეუძლებელია: %s" -#: rewrite/rewriteHandler.c:3082 +#: rewrite/rewriteHandler.c:3133 #, c-format msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." msgstr "" -#: rewrite/rewriteHandler.c:3087 rewrite/rewriteHandler.c:3123 +#: rewrite/rewriteHandler.c:3138 rewrite/rewriteHandler.c:3174 #, c-format msgid "cannot update view \"%s\"" msgstr "ხედის განახლება შეუძლებელია: %s" -#: rewrite/rewriteHandler.c:3090 +#: rewrite/rewriteHandler.c:3141 #, c-format msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." msgstr "" -#: rewrite/rewriteHandler.c:3095 rewrite/rewriteHandler.c:3132 +#: rewrite/rewriteHandler.c:3146 rewrite/rewriteHandler.c:3183 #, c-format msgid "cannot delete from view \"%s\"" msgstr "ხედიდან წაშლა შეუძლებელია: %s" -#: rewrite/rewriteHandler.c:3098 +#: rewrite/rewriteHandler.c:3149 #, c-format msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." msgstr "" -#: rewrite/rewriteHandler.c:3117 +#: rewrite/rewriteHandler.c:3168 #, c-format msgid "To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger." msgstr "ხედში MERGE-ით ჩასმის ჩასართავად მიუთითეთ INSTEAD OF INSERT ტრიგერი." -#: rewrite/rewriteHandler.c:3126 +#: rewrite/rewriteHandler.c:3177 #, c-format msgid "To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger." msgstr "ხედის MERGE-ით განახლების ჩასართავად მიუთითეთ INSTEAD OF UPDATE ტრიგერი." -#: rewrite/rewriteHandler.c:3135 +#: rewrite/rewriteHandler.c:3186 #, c-format msgid "To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger." msgstr "ამ ხედიდან MERGE-ის საშუალებით წაშლის ჩასართავად მიუთითეთ INSTEAD OF DELETE ტრიგერი." -#: rewrite/rewriteHandler.c:3289 +#: rewrite/rewriteHandler.c:3361 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "ხედის (\"%2$s\") სვეტში \"%1$s\" მონაცემის ჩასმა შეუძლებელია" -#: rewrite/rewriteHandler.c:3297 +#: rewrite/rewriteHandler.c:3369 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "ხედის (\"%2$s\") სვეტის \"%1$s\" განახლება შეუძლებელია" -#: rewrite/rewriteHandler.c:3305 +#: rewrite/rewriteHandler.c:3377 #, c-format msgid "cannot merge into column \"%s\" of view \"%s\"" msgstr "ხედის (\"%2$s\") სვეტთან \"%1$s\" შერწყმა შეუძლებელია" -#: rewrite/rewriteHandler.c:3333 +#: rewrite/rewriteHandler.c:3405 #, c-format msgid "cannot merge into view \"%s\"" msgstr "შეუძლებელია შერწყმა ხედში \"%s\"" -#: rewrite/rewriteHandler.c:3335 +#: rewrite/rewriteHandler.c:3407 #, c-format -msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions, but not others." +msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions but not all." msgstr "" -#: rewrite/rewriteHandler.c:3336 +#: rewrite/rewriteHandler.c:3408 #, c-format msgid "To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers." msgstr "ამ ხედში შერწყმის ჩასართავად, ან შეიყვანეთ INSTEAD OF ტრიგერების სრული სია, ან წაშალეთ არსებული INSTEAD OF ტრიგერები." -#: rewrite/rewriteHandler.c:3855 +#: rewrite/rewriteHandler.c:3923 #, c-format msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" msgstr "" -#: rewrite/rewriteHandler.c:3866 +#: rewrite/rewriteHandler.c:3934 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" msgstr "" -#: rewrite/rewriteHandler.c:3880 +#: rewrite/rewriteHandler.c:3948 #, c-format msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "" -#: rewrite/rewriteHandler.c:3884 +#: rewrite/rewriteHandler.c:3952 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "" -#: rewrite/rewriteHandler.c:3889 +#: rewrite/rewriteHandler.c:3957 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "" -#: rewrite/rewriteHandler.c:4149 +#: rewrite/rewriteHandler.c:4217 msgid "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "" -#: rewrite/rewriteHandler.c:4246 +#: rewrite/rewriteHandler.c:4314 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" 'INSERT RETURNING'-ის განხორციელება შეუძლებელია" -#: rewrite/rewriteHandler.c:4248 +#: rewrite/rewriteHandler.c:4316 #, c-format msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "" -#: rewrite/rewriteHandler.c:4253 +#: rewrite/rewriteHandler.c:4321 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" 'UPDATE RETURNING'-ის განხორციელება შეუძლებელია" -#: rewrite/rewriteHandler.c:4255 +#: rewrite/rewriteHandler.c:4323 #, c-format msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "" -#: rewrite/rewriteHandler.c:4260 +#: rewrite/rewriteHandler.c:4328 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "ურთიერთობაზე \"%s\" 'DELETE RETURNING'-ის განხორციელება შეუძლებელია" -#: rewrite/rewriteHandler.c:4262 +#: rewrite/rewriteHandler.c:4330 #, c-format msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "" -#: rewrite/rewriteHandler.c:4280 +#: rewrite/rewriteHandler.c:4348 #, c-format msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" msgstr "" -#: rewrite/rewriteHandler.c:4337 +#: rewrite/rewriteHandler.c:4405 #, c-format msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries" msgstr "" -#: rewrite/rewriteManip.c:1083 +#: rewrite/rewriteManip.c:1222 #, c-format msgid "conditional utility statements are not implemented" msgstr "პირობითი სამსახურეობრივი გამოსახულებები განხორციელებული არაა" -#: rewrite/rewriteManip.c:1427 +#: rewrite/rewriteManip.c:1567 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "WHERE CURRENT OF ხედზე განხორციელებული არაა" -#: rewrite/rewriteManip.c:1762 +#: rewrite/rewriteManip.c:1970 #, c-format msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command" msgstr "" @@ -21979,7 +22626,7 @@ msgstr "$-ით დაწყებული სტრიქონ დაუმ msgid "zero-length delimited identifier" msgstr "გამყოფის ნულოვანი სიგრძის იდენტიფიკატორი" -#: scan.l:825 syncrep_scanner.l:101 +#: scan.l:825 syncrep_scanner.l:114 msgid "unterminated quoted identifier" msgstr "დაუსრულებელი იდენტიფიკატორი ბრჭყალებში" @@ -21988,317 +22635,549 @@ msgid "operator too long" msgstr "ოპერატორი ძალიან გრძელია" #: scan.l:1001 +msgid "parameter number too large" +msgstr "პარამეტრების რაოდენობა მეტისმეტად დიდია" + +#: scan.l:1007 msgid "trailing junk after parameter" msgstr "პარამეტრის შემდეგ მოყოლილი მონაცემები ნაგავია" -#: scan.l:1022 +#: scan.l:1028 msgid "invalid hexadecimal integer" msgstr "არასწორი თექვსმეტობითი მთელი რიცხვი" -#: scan.l:1026 +#: scan.l:1032 msgid "invalid octal integer" msgstr "არასწორი რვაობითი მთელი რიცხვი" -#: scan.l:1030 +#: scan.l:1036 msgid "invalid binary integer" msgstr "არასწორი ბინარული მთელი რიცხვი" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1237 +#: scan.l:1231 #, c-format msgid "%s at end of input" msgstr "%s შეყვანის ბოლოს" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1245 +#: scan.l:1239 #, c-format msgid "%s at or near \"%s\"" msgstr "%s \"%s\"-სთან ან ახლოს" -#: scan.l:1437 +#: scan.l:1431 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "სტრიქონში \\' არასტანდარტულადაა გამოყენებული" -#: scan.l:1438 +#: scan.l:1432 #, c-format msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "" -#: scan.l:1447 +#: scan.l:1441 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "სტრიქონში \\\\ არასტანდარტულადაა გამოყენებული" -#: scan.l:1448 +#: scan.l:1442 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "" -#: scan.l:1462 +#: scan.l:1456 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "" -#: scan.l:1463 +#: scan.l:1457 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "" -#: snowball/dict_snowball.c:215 +#: snowball/dict_snowball.c:220 #, c-format msgid "no Snowball stemmer available for language \"%s\" and encoding \"%s\"" msgstr "" -#: snowball/dict_snowball.c:238 tsearch/dict_ispell.c:74 tsearch/dict_simple.c:49 +#: snowball/dict_snowball.c:243 tsearch/dict_ispell.c:75 tsearch/dict_simple.c:50 #, c-format msgid "multiple StopWords parameters" msgstr "გამეორებადი StopWords პარამეტრი" -#: snowball/dict_snowball.c:247 +#: snowball/dict_snowball.c:252 #, c-format msgid "multiple Language parameters" msgstr "გამეორებადი Language პარამეტრი" -#: snowball/dict_snowball.c:254 +#: snowball/dict_snowball.c:259 #, c-format msgid "unrecognized Snowball parameter: \"%s\"" msgstr "" -#: snowball/dict_snowball.c:262 +#: snowball/dict_snowball.c:267 #, c-format msgid "missing Language parameter" msgstr "აკლია პარამეტრი Language" -#: statistics/extended_stats.c:176 -#, c-format -msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" -msgstr "" - -#: statistics/mcv.c:1368 +#: statistics/attribute_stats.c:191 statistics/attribute_stats.c:932 statistics/relation_stats.c:98 #, c-format -msgid "function returning record called in context that cannot accept type record" -msgstr "ფუნქცია, რომელიც ჩანაწერს აბრუნებს, გამოძახებულია კონტექსტში, რომელსაც ჩანაწერის მიღება არ შეუძლია" +msgid "Statistics cannot be modified during recovery." +msgstr "აღდგენის დროს სტატისტიკას ვერ შეცვლით." -#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 +#: statistics/attribute_stats.c:202 #, c-format -msgid "cannot access temporary tables of other sessions" -msgstr "სხვა სესიების დროებით ცხრილებთან წვდომა შეუძლებელია" +msgid "cannot specify both attname and attnum" +msgstr "ორივეს attname და attnum ვერ მიუთითებთ" -#: storage/buffer/bufmgr.c:1532 +#: statistics/attribute_stats.c:228 #, c-format -msgid "invalid page in block %u of relation %s; zeroing out page" -msgstr "" +msgid "must specify either attname or attnum" +msgstr "აუცილებელია, მიუთითოთ attname ან attnum" -#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 +#: statistics/attribute_stats.c:236 #, c-format -msgid "cannot extend relation %s beyond %u blocks" -msgstr "" +msgid "cannot modify statistics on system column \"%s\"" +msgstr "სტატისტიკის შეცვლა შეუძლებელია სისტემურ სვეტზე \"%s\"" -#: storage/buffer/bufmgr.c:2348 +#: statistics/attribute_stats.c:300 #, c-format -msgid "unexpected data beyond EOF in block %u of relation %s" -msgstr "" +msgid "unable to determine element type of attribute \"%s\"" +msgstr "ატრიბუტის \"%s\" ელემენტის დადგენა შეუძლებელია" -#: storage/buffer/bufmgr.c:2350 +#: statistics/attribute_stats.c:301 #, c-format -msgid "This has been seen to occur with buggy kernels; consider updating your system." +msgid "Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST." msgstr "" -#: storage/buffer/bufmgr.c:5653 -#, c-format -msgid "could not write block %u of %s" -msgstr "%2$s-ის %1$u ბლოკის ჩაწერა შეუძლებელია" - -#: storage/buffer/bufmgr.c:5655 +#: statistics/attribute_stats.c:316 #, c-format -msgid "Multiple failures --- write error might be permanent." -msgstr "ბევრი შეცდომა --- ჩაწერის შეცდომა შეიძლება მუდმივი იყოს." +msgid "could not determine less-than operator for attribute \"%s\"" +msgstr "შეუძლებელია ნაკლებია ვიდრე ოპერატორის დადგენა ატრიბუტისთვის \"%s\"" -#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 +#: statistics/attribute_stats.c:317 #, c-format -msgid "writing block %u of relation %s" +msgid "Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION." msgstr "" -#: storage/buffer/localbuf.c:220 +#: statistics/attribute_stats.c:330 #, c-format -msgid "no empty local buffer available" -msgstr "ცარიელი ლოკალური ბაფერები მიუწვდომელია" +msgid "attribute \"%s\" is not a range type" +msgstr "ატრიბუტი \"%s\" შუალედის ტიპი არაა" -#: storage/buffer/localbuf.c:597 +#: statistics/attribute_stats.c:331 #, c-format -msgid "cannot access temporary tables during a parallel operation" +msgid "Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM." msgstr "" -#: storage/buffer/localbuf.c:712 +#: statistics/attribute_stats.c:590 statistics/attribute_stats.c:598 #, c-format -msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." -msgstr "" +msgid "attribute %d of relation \"%s\" does not exist" +msgstr "ატრიბუტი %d ურთიერთობისთვის \"%s\" არ არსებობს" -#: storage/file/buffile.c:338 +#: statistics/attribute_stats.c:732 statistics/stat_utils.c:80 #, c-format -msgid "could not open temporary file \"%s\" from BufFile \"%s\": %m" -msgstr "" +msgid "\"%s\" array cannot contain NULL values" +msgstr "\"%s\" მასივი, არ შეიძლება, NULL მნიშვნელობებს შეიცავდეს" -#: storage/file/buffile.c:632 +#: statistics/attribute_stats.c:775 #, c-format -msgid "could not read from file set \"%s\": read only %zu of %zu bytes" -msgstr "ფაილების სეტიდან (\"%s\") წაკითხვის შეცდომა: წავიკითხე მხოლოდ %zu ბაიტი %zu-დან" +msgid "maximum number of statistics slots exceeded: %d" +msgstr "გადაცილებულია სტატისტიკის სლოტების მაქსიმალური რაოდენობა: %d" -#: storage/file/buffile.c:634 +#: statistics/attribute_stats.c:942 #, c-format -msgid "could not read from temporary file: read only %zu of %zu bytes" -msgstr "დროებით ფაილიდან წაკითხვის შეცდომა: წავიკითხე მხოლოდ %zu ბაიტი %zu-დან" +msgid "cannot clear statistics on system column \"%s\"" +msgstr "სტატისტიკის გასუფთავება შეუძლებელია სისტემურ სვეტზე \"%s\"" -#: storage/file/buffile.c:774 storage/file/buffile.c:877 +#: statistics/extended_stats.c:175 #, c-format -msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" +msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "" -#: storage/file/buffile.c:956 +#: statistics/mcv.c:1368 #, c-format -msgid "could not delete fileset \"%s\": %m" -msgstr "ფაილების სეტის (\"%s\") წაშლის შეცდომა: %m" +msgid "function returning record called in context that cannot accept type record" +msgstr "ფუნქცია, რომელიც ჩანაწერს აბრუნებს, გამოძახებულია კონტექსტში, რომელსაც ჩანაწერის მიღება არ შეუძლია" -#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1192 +#: statistics/relation_stats.c:115 #, c-format -msgid "could not truncate file \"%s\": %m" -msgstr "ფაილის (%s) მოკვეთის შეცდომა: %m" +msgid "reltuples cannot be < -1.0" +msgstr "reltuples ვერ იქნება < -1.0" -#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 +#: statistics/stat_utils.c:44 #, c-format -msgid "could not flush dirty data: %m" -msgstr "" +msgid "\"%s\" cannot be NULL" +msgstr "\"%s\" არ შეიძლება, NULL იყოს" -#: storage/file/fd.c:613 +#: statistics/stat_utils.c:71 #, c-format -msgid "could not determine dirty data size: %m" -msgstr "" +msgid "\"%s\" cannot be a multidimensional array" +msgstr "\"%s\" მრავალგანზომილებიანი მასივი ვერ იქნება" -#: storage/file/fd.c:665 +#: statistics/stat_utils.c:111 #, c-format -msgid "could not munmap() while flushing data: %m" -msgstr "" +msgid "\"%s\" must be specified when \"%s\" is specified" +msgstr "\"%s\"-ის მითითება აუცილებელია, როცა მიუთითებთ \"%s\"-ს" -#: storage/file/fd.c:983 +#: statistics/stat_utils.c:178 #, c-format -msgid "getrlimit failed: %m" -msgstr "getrlimit-ის შეცდომა: %m" +msgid "cannot modify statistics for relation \"%s\"" +msgstr "სტატისტიკის შეცვლა ურთიერთობისთვის \"%s\" შეუძლებელია" -#: storage/file/fd.c:1073 +#: statistics/stat_utils.c:199 #, c-format -msgid "insufficient file descriptors available to start server process" -msgstr "სერვერის პროცესის გასაშვებად საკმარისი ფაილის დესკრიპტორების ხელმისაწვდომი არაა" +msgid "cannot modify statistics for shared relation" +msgstr "გაზიარებული ურთიერთობისთვის სტატისტიკის შეცვლა შეუძლებელია" -#: storage/file/fd.c:1074 +#: statistics/stat_utils.c:252 #, c-format -msgid "System allows %d, server needs at least %d." -msgstr "სისტემა გვიშვებს %d, სერვერს კი სჭირდება %d." +msgid "unrecognized argument name: \"%s\"" +msgstr "უცნობი არგუმენტის სახელი: \"%s\"" -#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 storage/file/fd.c:2878 +#: statistics/stat_utils.c:266 #, c-format -msgid "out of file descriptors: %m; release and retry" -msgstr "ფაილების დესკრიპტორების საკმარისი არაა: %m. გაათავისუფლეთ და თავიდან სცადეთ" +msgid "argument \"%s\" has type \"%s\", expected type \"%s\"" +msgstr "არგუმენტს \"%s\" აქვს ტიპი \"%s\". მოველოდი ტიპს \"%s\"" -#: storage/file/fd.c:1536 +#: statistics/stat_utils.c:307 #, c-format -msgid "temporary file: path \"%s\", size %lu" -msgstr "დროებითი ფაილი: ბილიკი \"%s\", ზომა %lu" +msgid "variadic arguments must be name/value pairs" +msgstr "variadic არგუმენტები სახელი/მნიშვნელობის წყვილები უნდა იყოს" -#: storage/file/fd.c:1675 +#: statistics/stat_utils.c:308 #, c-format -msgid "cannot create temporary directory \"%s\": %m" -msgstr "დროებითი საქაღალდის (%s) შექმნის შეცდომა: %m" +msgid "Provide an even number of variadic arguments that can be divided into pairs." +msgstr "" -#: storage/file/fd.c:1682 +#: statistics/stat_utils.c:322 #, c-format -msgid "cannot create temporary subdirectory \"%s\": %m" -msgstr "დროებითი ქვესაქაღალდის (%s) შექმნის შეცდომა: %m" +msgid "name at variadic position %d is NULL" +msgstr "სახელი variadic მდებარეობაზე %d NULL-ს უდრის" -#: storage/file/fd.c:1879 +#: statistics/stat_utils.c:326 #, c-format -msgid "could not create temporary file \"%s\": %m" -msgstr "დროებითი ფაილის (%s) შექმნის შეცდომა: %m" +msgid "name at variadic position %d has type \"%s\", expected type \"%s\"" +msgstr "" -#: storage/file/fd.c:1915 +#: storage/aio/aio.c:1222 #, c-format -msgid "could not open temporary file \"%s\": %m" -msgstr "დროებითი ფაილის (\"%s\") გახსნის შეცდომა: %m" +msgid "Only -1 or values bigger than 0 are valid." +msgstr "" -#: storage/file/fd.c:1956 -#, c-format -msgid "could not unlink temporary file \"%s\": %m" -msgstr "დროებითი ფაილის (%s) ბმულის მოხსნის შეცდომა: %m" +#: storage/aio/method_io_uring.c:171 +msgid "Check if io_uring is disabled via /proc/sys/kernel/io_uring_disabled." +msgstr "" -#: storage/file/fd.c:2044 +#: storage/aio/method_io_uring.c:176 #, c-format -msgid "could not delete file \"%s\": %m" -msgstr "ფაილის (\"%s\") წაშლის შეცდომა: %m" +msgid "Consider increasing \"ulimit -n\" to at least %d." +msgstr "განიხილეთ 'ulimit -n'-ის გაზრდა მინიმუმ %d-მდე." -#: storage/file/fd.c:2234 +#: storage/aio/method_io_uring.c:182 +msgid "Kernel does not support io_uring." +msgstr "ბირთვს io_uring_ის მხარდაჭერა არ გააჩნია." + +#: storage/aio/method_io_uring.c:190 #, c-format -msgid "temporary file size exceeds temp_file_limit (%dkB)" -msgstr "დროებითი ფაილის ზომა temp_file_limit-ს (%dკბ) აჭარბებს" +msgid "could not setup io_uring queue: %m" +msgstr "io_uring რიგის მორგება შეუძლებელია: %m" -#: storage/file/fd.c:2594 storage/file/fd.c:2653 +#: storage/aio/method_io_uring.c:324 #, c-format -msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" -msgstr "გადაცილებულია maxAllocatedDescs (%d) როცა ვცდილობდი, გამეხსნა ფაილი \"%s\"" +msgid "completing I/O on behalf of process %d" +msgstr "" -#: storage/file/fd.c:2698 +#: storage/aio/method_worker.c:379 #, c-format -msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" -msgstr "გადაცილებულია maxAllocatedDescs (%d) როცა ვცდილობდი, გამეშვა ბრძანება \"%s\"" +msgid "I/O worker executing I/O on behalf of process %d" +msgstr "" -#: storage/file/fd.c:2854 +#: storage/buffer/bufmgr.c:662 storage/buffer/bufmgr.c:818 #, c-format -msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" +msgid "cannot access temporary tables of other sessions" +msgstr "სხვა სესიების დროებით ცხრილებთან წვდომა შეუძლებელია" + +#: storage/buffer/bufmgr.c:2708 storage/buffer/localbuf.c:393 +#, c-format +msgid "cannot extend relation %s beyond %u blocks" +msgstr "" + +#: storage/buffer/bufmgr.c:2779 +#, c-format +msgid "unexpected data beyond EOF in block %u of relation %s" +msgstr "" + +#: storage/buffer/bufmgr.c:2782 +#, c-format +msgid "This has been seen to occur with buggy kernels; consider updating your system." +msgstr "" + +#: storage/buffer/bufmgr.c:6185 +#, c-format +msgid "could not write block %u of %s" +msgstr "%2$s-ის %1$u ბლოკის ჩაწერა შეუძლებელია" + +#: storage/buffer/bufmgr.c:6189 +#, c-format +msgid "Multiple failures --- write error might be permanent." +msgstr "ბევრი შეცდომა --- ჩაწერის შეცდომა შეიძლება მუდმივი იყოს." + +#: storage/buffer/bufmgr.c:6206 storage/buffer/bufmgr.c:6221 +#, c-format +msgid "writing block %u of relation %s" +msgstr "" + +#: storage/buffer/bufmgr.c:7320 +#, c-format +msgid "zeroing %u page(s) and ignoring %u checksum failure(s) among blocks %u..%u of relation %s" +msgstr "" + +#: storage/buffer/bufmgr.c:7323 storage/buffer/bufmgr.c:7349 +#, c-format +msgid "Block %u held first zeroed page." +msgstr "" + +#: storage/buffer/bufmgr.c:7325 +#, c-format +msgid "See server log for details about the other %u invalid block(s)." +msgstr "" + +#: storage/buffer/bufmgr.c:7340 +#, c-format +msgid "%u invalid pages among blocks %u..%u of relation %s" +msgstr "%u არასწორი გვერდი ბლოკების %u..%u გასწვრივ ურთიერთობისთვის %s" + +#: storage/buffer/bufmgr.c:7341 +#, c-format +msgid "Block %u held first invalid page." +msgstr "" + +#: storage/buffer/bufmgr.c:7342 +#, c-format +msgid "See server log for the other %u invalid block(s)." +msgstr "დარჩენილი %u არასწორი ბლოკისთვის იხილეთ სერვერის ჟურნალი." + +#: storage/buffer/bufmgr.c:7347 +#, c-format +msgid "invalid page in block %u of relation %s; zeroing out page" +msgstr "" + +#: storage/buffer/bufmgr.c:7348 +#, c-format +msgid "zeroing out %u invalid pages among blocks %u..%u of relation %s" +msgstr "მიმდინარეობს %u არასწორი გვერდის განულება ბლოკების %u..%u გასწვრივ ურთიერთობისთვის %s" + +#: storage/buffer/bufmgr.c:7350 +#, c-format +msgid "See server log for the other %u zeroed block(s)." +msgstr "დარჩენილი %u განულებული ბლოკისთვის იხილეთ სერვერის ჟურნალი." + +#: storage/buffer/bufmgr.c:7355 +#, c-format +msgid "ignoring checksum failure in block %u of relation %s" +msgstr "ურთიერთობის (%2$s) ბლოკის (%1$u) საკონტროლო ჯამის გამოთვლის ჩავარდნა გამოტოვებული იქნება" + +#: storage/buffer/bufmgr.c:7356 +#, c-format +msgid "ignoring %u checksum failures among blocks %u..%u of relation %s" +msgstr "გამოტოვებული იქნება %u საკონტროლო ჯამის გამოთვლის ჩავარდნა ბლოკების %u..%u გასწვრივ ურთიერთობისთვის %s" + +#: storage/buffer/bufmgr.c:7357 +#, c-format +msgid "Block %u held first ignored page." +msgstr "" + +#: storage/buffer/bufmgr.c:7358 +#, c-format +msgid "See server log for the other %u ignored block(s)." +msgstr "დარჩენილი %u გამოტოვებული ბლოკისთვის იხილეთ სერვერის ჟურნალი." + +#: storage/buffer/localbuf.c:272 +#, c-format +msgid "no empty local buffer available" +msgstr "ცარიელი ლოკალური ბაფერები მიუწვდომელია" + +#: storage/buffer/localbuf.c:736 +#, c-format +msgid "cannot access temporary tables during a parallel operation" +msgstr "" + +#: storage/buffer/localbuf.c:876 +#, c-format +msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." +msgstr "" + +#: storage/file/buffile.c:338 +#, c-format +msgid "could not open temporary file \"%s\" from BufFile \"%s\": %m" +msgstr "" + +#: storage/file/buffile.c:632 +#, c-format +msgid "could not read from file set \"%s\": read only %zu of %zu bytes" +msgstr "ფაილების სეტიდან (\"%s\") წაკითხვის შეცდომა: წავიკითხე მხოლოდ %zu ბაიტი %zu-დან" + +#: storage/file/buffile.c:634 +#, c-format +msgid "could not read from temporary file: read only %zu of %zu bytes" +msgstr "დროებით ფაილიდან წაკითხვის შეცდომა: წავიკითხე მხოლოდ %zu ბაიტი %zu-დან" + +#: storage/file/buffile.c:774 storage/file/buffile.c:875 +#, c-format +msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" +msgstr "" + +#: storage/file/buffile.c:951 +#, c-format +msgid "could not delete fileset \"%s\": %m" +msgstr "ფაილების სეტის (\"%s\") წაშლის შეცდომა: %m" + +#: storage/file/buffile.c:969 storage/smgr/md.c:356 storage/smgr/md.c:1318 +#, c-format +msgid "could not truncate file \"%s\": %m" +msgstr "ფაილის (%s) მოკვეთის შეცდომა: %m" + +#: storage/file/copydir.c:244 storage/file/copydir.c:275 +#, c-format +msgid "could not clone file \"%s\" to \"%s\": %m" +msgstr "ფაილის \"%s\"-დან \"%s\"-ში დაკლონვა შეუძლებელია: %m" + +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 +#, c-format +msgid "could not flush dirty data: %m" +msgstr "" + +#: storage/file/fd.c:613 +#, c-format +msgid "could not determine dirty data size: %m" +msgstr "" + +#: storage/file/fd.c:665 +#, c-format +msgid "could not munmap() while flushing data: %m" +msgstr "" + +#: storage/file/fd.c:983 +#, c-format +msgid "getrlimit failed: %m" +msgstr "getrlimit-ის შეცდომა: %m" + +#: storage/file/fd.c:1074 +#, c-format +msgid "insufficient file descriptors available to start server process" +msgstr "სერვერის პროცესის გასაშვებად საკმარისი ფაილის დესკრიპტორების ხელმისაწვდომი არაა" + +#: storage/file/fd.c:1075 +#, c-format +msgid "System allows %d, server needs at least %d, %d files are already open." +msgstr "სისტემა გვიშვებს %d, სერვერს კი სჭირდება %d. უკვე ღიაა %d ფაილი." + +#: storage/file/fd.c:1164 storage/file/fd.c:2679 storage/file/fd.c:2788 storage/file/fd.c:2942 +#, c-format +msgid "out of file descriptors: %m; release and retry" +msgstr "ფაილების დესკრიპტორების საკმარისი არაა: %m. გაათავისუფლეთ და თავიდან სცადეთ" + +#: storage/file/fd.c:1540 +#, c-format +msgid "temporary file: path \"%s\", size %lu" +msgstr "დროებითი ფაილი: ბილიკი \"%s\", ზომა %lu" + +#: storage/file/fd.c:1679 +#, c-format +msgid "cannot create temporary directory \"%s\": %m" +msgstr "დროებითი საქაღალდის (%s) შექმნის შეცდომა: %m" + +#: storage/file/fd.c:1686 +#, c-format +msgid "cannot create temporary subdirectory \"%s\": %m" +msgstr "დროებითი ქვესაქაღალდის (%s) შექმნის შეცდომა: %m" + +#: storage/file/fd.c:1883 +#, c-format +msgid "could not create temporary file \"%s\": %m" +msgstr "დროებითი ფაილის (%s) შექმნის შეცდომა: %m" + +#: storage/file/fd.c:1919 +#, c-format +msgid "could not open temporary file \"%s\": %m" +msgstr "დროებითი ფაილის (\"%s\") გახსნის შეცდომა: %m" + +#: storage/file/fd.c:1960 +#, c-format +msgid "could not unlink temporary file \"%s\": %m" +msgstr "დროებითი ფაილის (%s) ბმულის მოხსნის შეცდომა: %m" + +#: storage/file/fd.c:2050 +#, c-format +msgid "could not delete file \"%s\": %m" +msgstr "ფაილის (\"%s\") წაშლის შეცდომა: %m" + +#: storage/file/fd.c:2289 +#, c-format +msgid "temporary file size exceeds \"temp_file_limit\" (%dkB)" +msgstr "დროებითი ფაილის ზომა 'temp_file_limit\"-ს (%dკბ) აჭარბებს" + +#: storage/file/fd.c:2655 storage/file/fd.c:2714 +#, c-format +msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" +msgstr "გადაცილებულია maxAllocatedDescs (%d) როცა ვცდილობდი, გამეხსნა ფაილი \"%s\"" + +#: storage/file/fd.c:2759 +#, c-format +msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" +msgstr "გადაცილებულია maxAllocatedDescs (%d) როცა ვცდილობდი, გამეშვა ბრძანება \"%s\"" + +#: storage/file/fd.c:2918 +#, c-format +msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "გადაცილებულია maxAllocatedDescs (%d) როცა ვცდილობდი, გამეხსნა საქაღალდე \"%s\"" -#: storage/file/fd.c:3384 +#: storage/file/fd.c:3449 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "დროებითი ფაილების საქაღალდეში აღმოჩენილია მოულოდნელი ფაილი: \"%s\"" -#: storage/file/fd.c:3502 +#: storage/file/fd.c:3567 #, c-format msgid "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "" -#: storage/file/fd.c:3729 +#: storage/file/fd.c:3794 #, c-format msgid "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "" -#: storage/file/fd.c:3761 +#: storage/file/fd.c:3826 #, c-format msgid "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "" -#: storage/file/fd.c:3950 +#: storage/file/fd.c:4015 #, c-format -msgid "\"debug_io_direct\" is not supported on this platform." -msgstr "\"debug_io_direct\" ამ პლატფორმაზე მხარდაჭერილი არაა." +msgid "\"%s\" is not supported on this platform." +msgstr "ამ პლატფორმაზე \"%s\" მხარდაჭერილი არაა." -#: storage/file/fd.c:3964 +#: storage/file/fd.c:4030 #, c-format -msgid "Invalid list syntax in parameter \"%s\"" -msgstr "არასწორი სიის სინტაქსი პარამეტრში \"%s\"" +msgid "Invalid list syntax in parameter \"%s\"." +msgstr "არასწორი სიის სინტაქსი პარამეტრში \"%s\"." -#: storage/file/fd.c:3984 +#: storage/file/fd.c:4050 tcop/backend_startup.c:1054 #, c-format -msgid "Invalid option \"%s\"" -msgstr "არასწორი პარამეტრი \"%s\"" +msgid "Invalid option \"%s\"." +msgstr "არასწორი პარამეტრი \"%s\"." -#: storage/file/fd.c:3997 +#: storage/file/fd.c:4063 #, c-format -msgid "\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" -msgstr "\"debug_io_direct\" მხარდაჭერილი არაა WAL-სთვის, რადგან XLOG_BLCKSZ ძალიან პატარაა" +msgid "\"%s\" is not supported for WAL because %s is too small." +msgstr "\"%s\" მხარდაჭერილი არაა WAL-სთვის, რადგან %s ძალიან პატარაა." -#: storage/file/fd.c:4004 +#: storage/file/fd.c:4071 #, c-format -msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" -msgstr "\"debug_io_direct\" მონაცემებისთვის მხარდაჭერილი არაა, რადგან BLCKSZ ძალიან პატარაა" +msgid "\"%s\" is not supported for data because %s is too small." +msgstr "\"%s\" მხარდაჭერილი არაა მონაცემებისთვის, რადგან %s ძალიან პატარაა." #: storage/file/reinit.c:145 #, c-format @@ -22400,36 +23279,46 @@ msgstr "DSM სეგმენტის ზომა არანულოვა msgid "requested DSM segment size does not match size of existing segment" msgstr "" -#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:352 tcop/backend_startup.c:304 +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:458 tcop/backend_startup.c:343 #, c-format msgid "sorry, too many clients already" msgstr "უკაცრავად, უკვე მეტისმეტად ბევრი კლიენტია" -#: storage/ipc/procarray.c:3845 +#: storage/ipc/procarray.c:3858 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "მონაცემთა ბაზა \"%s\" მომზადებული ტრანზაქციების მიერ გამოიყენება" -#: storage/ipc/procarray.c:3881 storage/ipc/procarray.c:3889 storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 +#: storage/ipc/procarray.c:3894 storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:256 storage/ipc/signalfuncs.c:263 storage/ipc/signalfuncs.c:270 #, c-format msgid "permission denied to terminate process" msgstr "პროცესის შეწყვეტის წვდომა აკრძალულია" -#: storage/ipc/procarray.c:3882 storage/ipc/signalfuncs.c:236 +#: storage/ipc/procarray.c:3895 storage/ipc/signalfuncs.c:257 #, c-format msgid "Only roles with the %s attribute may terminate processes of roles with the %s attribute." msgstr "" -#: storage/ipc/procarray.c:3890 storage/ipc/signalfuncs.c:243 +#: storage/ipc/procarray.c:3903 storage/ipc/signalfuncs.c:271 #, c-format msgid "Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process." msgstr "" -#: storage/ipc/procsignal.c:416 +#: storage/ipc/procsignal.c:450 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "" +#: storage/ipc/procsignal.c:786 +#, c-format +msgid "wrong key in cancel request for process %d" +msgstr "არასწორი გასაღები გაუქმების მოთხოვნაში პროცესისთვის %d" + +#: storage/ipc/procsignal.c:795 +#, c-format +msgid "PID %d in cancel request did not match any process" +msgstr "PID %d, მოთხოვნილი გაუქმების მოთხოვნაში, არც ერთ პროცესს არ ემთხვევა" + #: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" @@ -22440,7 +23329,7 @@ msgstr "გაზიარებული მეხსიერების რ msgid "invalid message size %zu in shared memory queue" msgstr "გაზიარებული მეხსიერების რიგში არსებული შეტყობინების ზომა %zu არასწორია" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:962 storage/lmgr/lock.c:1000 storage/lmgr/lock.c:2803 storage/lmgr/lock.c:4188 storage/lmgr/lock.c:4253 storage/lmgr/lock.c:4603 storage/lmgr/predicate.c:2463 storage/lmgr/predicate.c:2478 storage/lmgr/predicate.c:3875 storage/lmgr/predicate.c:4922 utils/hash/dynahash.c:1095 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:1038 storage/lmgr/lock.c:1076 storage/lmgr/lock.c:2965 storage/lmgr/lock.c:4370 storage/lmgr/lock.c:4435 storage/lmgr/lock.c:4785 storage/lmgr/predicate.c:2478 storage/lmgr/predicate.c:2493 storage/lmgr/predicate.c:3890 storage/lmgr/predicate.c:4937 utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "არასაკმარისი გაზიარებული მეხსიერება" @@ -22470,186 +23359,196 @@ msgstr "" msgid "requested shared memory size overflows size_t" msgstr "მოთხოვნილი გაზიარებული მეხსიერების ზომა site_t-ის გადავსებას იწვევს" -#: storage/ipc/signalfuncs.c:72 +#: storage/ipc/signalfuncs.c:74 #, c-format msgid "PID %d is not a PostgreSQL backend process" msgstr "პროცესი PID-ით %d PostgreSQL-ის უკანაბოლოს პროცესს არ წარმოადგენს" -#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1448 utils/adt/mcxtfuncs.c:182 +#: storage/ipc/signalfuncs.c:123 storage/lmgr/proc.c:1547 utils/adt/mcxtfuncs.c:314 utils/adt/mcxtfuncs.c:412 #, c-format msgid "could not send signal to process %d: %m" msgstr "პროცესისთვის %d სიგნალის გაგზავნა შეუძლებელია: %m" -#: storage/ipc/signalfuncs.c:129 storage/ipc/signalfuncs.c:136 +#: storage/ipc/signalfuncs.c:143 storage/ipc/signalfuncs.c:150 storage/ipc/signalfuncs.c:157 #, c-format msgid "permission denied to cancel query" msgstr "მოთხოვნის გაუქმების წვდომა აკრძალულია" -#: storage/ipc/signalfuncs.c:130 +#: storage/ipc/signalfuncs.c:144 #, c-format msgid "Only roles with the %s attribute may cancel queries of roles with the %s attribute." msgstr "" -#: storage/ipc/signalfuncs.c:137 +#: storage/ipc/signalfuncs.c:151 +#, c-format +msgid "Only roles with privileges of the \"%s\" role may cancel autovacuum workers." +msgstr "ავტომომტვერსასრუტებლის დამხმარე პროცესების გაუქმება, მხოლოდ, \"%s\" პრივილეგიის მქონე როლებს შეუძლიათ." + +#: storage/ipc/signalfuncs.c:158 #, c-format msgid "Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query." msgstr "" -#: storage/ipc/signalfuncs.c:179 +#: storage/ipc/signalfuncs.c:200 #, c-format msgid "could not check the existence of the backend with PID %d: %m" msgstr "" -#: storage/ipc/signalfuncs.c:197 +#: storage/ipc/signalfuncs.c:218 #, c-format -msgid "backend with PID %d did not terminate within %lld millisecond" -msgid_plural "backend with PID %d did not terminate within %lld milliseconds" +msgid "backend with PID %d did not terminate within % millisecond" +msgid_plural "backend with PID %d did not terminate within % milliseconds" msgstr[0] "" msgstr[1] "" -#: storage/ipc/signalfuncs.c:228 +#: storage/ipc/signalfuncs.c:249 #, c-format msgid "\"timeout\" must not be negative" msgstr "\"timeout\" უარყოფითი არ შეიძლება, იყოს" -#: storage/ipc/signalfuncs.c:285 +#: storage/ipc/signalfuncs.c:264 +#, c-format +msgid "Only roles with privileges of the \"%s\" role may terminate autovacuum workers." +msgstr "ავტომომტვერსასრუტების დამხმარე პროცესების შეწყვეტა, მხოლოდ, \"%s\" პრივილეგიების მქონე როლებს შეუძლიათ." + +#: storage/ipc/signalfuncs.c:313 #, c-format msgid "rotation not possible because log collection not active" msgstr "" -#: storage/ipc/standby.c:329 +#: storage/ipc/standby.c:330 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "" -#: storage/ipc/standby.c:338 +#: storage/ipc/standby.c:339 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "" -#: storage/ipc/standby.c:920 tcop/postgres.c:3169 +#: storage/ipc/standby.c:921 tcop/postgres.c:3225 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "გამოსახულების გაუქმება აღდგენასთან კონფლიქტის გამო" -#: storage/ipc/standby.c:921 tcop/postgres.c:2529 +#: storage/ipc/standby.c:922 tcop/postgres.c:2575 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "" -#: storage/ipc/standby.c:1486 +#: storage/ipc/standby.c:1494 msgid "unknown reason" msgstr "უცნობი მიზეზი" -#: storage/ipc/standby.c:1491 +#: storage/ipc/standby.c:1499 msgid "recovery conflict on buffer pin" msgstr "აღდგენის კონფლიქტი ბაფერის მიმაგრებისას" -#: storage/ipc/standby.c:1494 +#: storage/ipc/standby.c:1502 msgid "recovery conflict on lock" msgstr "აღდგენის კონფლიქტი ბლოკირებისას" -#: storage/ipc/standby.c:1497 +#: storage/ipc/standby.c:1505 msgid "recovery conflict on tablespace" msgstr "აღდგენის კონფლიქტი ცხრილების სივრცეზე" -#: storage/ipc/standby.c:1500 +#: storage/ipc/standby.c:1508 msgid "recovery conflict on snapshot" msgstr "აღდგენის კონფლიქტი სწრაფ ასლზე" -#: storage/ipc/standby.c:1503 +#: storage/ipc/standby.c:1511 msgid "recovery conflict on replication slot" msgstr "აღდგენის კონფლიქტი რეპლიკაციის სლოტზე" -#: storage/ipc/standby.c:1506 +#: storage/ipc/standby.c:1514 msgid "recovery conflict on buffer deadlock" msgstr "აღდგენის კონფლიქტი ბაფერის ურთერთბლოკირებისას" -#: storage/ipc/standby.c:1509 +#: storage/ipc/standby.c:1517 msgid "recovery conflict on database" msgstr "აღდგენის კონფლიქტი მონაცემთა ბაზაზე" -#: storage/large_object/inv_api.c:190 +#: storage/large_object/inv_api.c:152 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "" -#: storage/large_object/inv_api.c:272 +#: storage/large_object/inv_api.c:234 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "დიდი ობიექტის არასწორი ალმები: %d" -#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 storage/large_object/inv_api.c:807 +#: storage/large_object/inv_api.c:259 storage/large_object/inv_api.c:271 storage/large_object/inv_api.c:468 storage/large_object/inv_api.c:579 storage/large_object/inv_api.c:769 #, c-format msgid "permission denied for large object %u" msgstr "წვდომა აკრძალულია დიდ ობიექტზე: \"%u\"" -#: storage/large_object/inv_api.c:455 +#: storage/large_object/inv_api.c:417 #, c-format msgid "invalid whence setting: %d" msgstr "არასწორი ორიენტირის პარამეტრი: %d" -#: storage/large_object/inv_api.c:627 +#: storage/large_object/inv_api.c:589 #, c-format msgid "invalid large object write request size: %d" msgstr "არასწორი დიდი ობიექტის ჩაწერის ზომა: %d" -#: storage/lmgr/deadlock.c:1104 +#: storage/lmgr/deadlock.c:1107 #, c-format msgid "Process %d waits for %s on %s; blocked by process %d." msgstr "" -#: storage/lmgr/deadlock.c:1123 +#: storage/lmgr/deadlock.c:1126 #, c-format msgid "Process %d: %s" msgstr "პროცესი %d: %s" -#: storage/lmgr/deadlock.c:1132 +#: storage/lmgr/deadlock.c:1135 #, c-format msgid "deadlock detected" msgstr "ნაპოვნია ურთიერთბლოკირება" -#: storage/lmgr/deadlock.c:1135 +#: storage/lmgr/deadlock.c:1138 #, c-format msgid "See server log for query details." msgstr "მოთხოვნის დეტალებისთვის იხილეთ სერვერის ჟურნალი." -#: storage/lmgr/lmgr.c:858 +#: storage/lmgr/lmgr.c:856 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "კორტეჟის (%u,%u) განახლებისას ურთიერთობაში \"%s\"" -#: storage/lmgr/lmgr.c:861 +#: storage/lmgr/lmgr.c:859 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "კორტეჟის (%u,%u) წაშლისას ურთიერთობაში \"%s\"" -#: storage/lmgr/lmgr.c:864 +#: storage/lmgr/lmgr.c:862 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "კორტეჟის (%u,%u) დაბლოკვისას ურთიერთობაში \"%s\"" -#: storage/lmgr/lmgr.c:867 +#: storage/lmgr/lmgr.c:865 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "კორტეჟის (%u,%u) განახლებული ვერსიის დაბლოკვისას ურთიერთობაში \"%s\"" -#: storage/lmgr/lmgr.c:870 +#: storage/lmgr/lmgr.c:868 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "" -#: storage/lmgr/lmgr.c:873 +#: storage/lmgr/lmgr.c:871 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "" -#: storage/lmgr/lmgr.c:876 +#: storage/lmgr/lmgr.c:874 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "" -#: storage/lmgr/lmgr.c:879 +#: storage/lmgr/lmgr.c:877 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "" @@ -22719,17 +23618,22 @@ msgstr "დაშორებული ტრანზაქცია %u გა msgid "unrecognized locktag type %d" msgstr "locktag-ის უცნობი ტიპი %d" -#: storage/lmgr/lock.c:790 +#: storage/lmgr/lock.c:866 #, c-format msgid "cannot acquire lock mode %s on database objects while recovery is in progress" msgstr "" -#: storage/lmgr/lock.c:792 +#: storage/lmgr/lock.c:868 #, c-format msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery." msgstr "" -#: storage/lmgr/lock.c:3252 storage/lmgr/lock.c:3320 storage/lmgr/lock.c:3436 +#: storage/lmgr/lock.c:1182 +#, c-format +msgid "process %d could not obtain %s on %s" +msgstr "პროცესმა %d ვერ მიიღო %s %s-ზე" + +#: storage/lmgr/lock.c:3423 storage/lmgr/lock.c:3491 storage/lmgr/lock.c:3607 #, c-format msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object" msgstr "" @@ -22749,665 +23653,710 @@ msgstr "" msgid "not enough elements in RWConflictPool to record a potential read/write conflict" msgstr "" -#: storage/lmgr/predicate.c:1681 +#: storage/lmgr/predicate.c:1696 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "\"default_transaction_isolation\"-ი \"serializable\"-ზეა დაყენებული." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1697 #, c-format msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default." msgstr "" -#: storage/lmgr/predicate.c:1733 +#: storage/lmgr/predicate.c:1748 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "" -#: storage/lmgr/predicate.c:1812 utils/time/snapmgr.c:535 utils/time/snapmgr.c:541 +#: storage/lmgr/predicate.c:1827 utils/time/snapmgr.c:556 utils/time/snapmgr.c:562 #, c-format msgid "could not import the requested snapshot" msgstr "მოთხოვნილი სწრაფი ასლის შემოტანა შეუძლებელია" -#: storage/lmgr/predicate.c:1813 utils/time/snapmgr.c:542 +#: storage/lmgr/predicate.c:1828 utils/time/snapmgr.c:563 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "საწყისი პროცესი PID-ით %d გაშვებული აღარაა." -#: storage/lmgr/predicate.c:3986 storage/lmgr/predicate.c:4022 storage/lmgr/predicate.c:4055 storage/lmgr/predicate.c:4063 storage/lmgr/predicate.c:4102 storage/lmgr/predicate.c:4332 storage/lmgr/predicate.c:4651 storage/lmgr/predicate.c:4663 storage/lmgr/predicate.c:4710 storage/lmgr/predicate.c:4746 +#: storage/lmgr/predicate.c:4001 storage/lmgr/predicate.c:4037 storage/lmgr/predicate.c:4070 storage/lmgr/predicate.c:4078 storage/lmgr/predicate.c:4117 storage/lmgr/predicate.c:4347 storage/lmgr/predicate.c:4666 storage/lmgr/predicate.c:4678 storage/lmgr/predicate.c:4725 storage/lmgr/predicate.c:4761 #, c-format msgid "could not serialize access due to read/write dependencies among transactions" msgstr "" -#: storage/lmgr/predicate.c:3988 storage/lmgr/predicate.c:4024 storage/lmgr/predicate.c:4057 storage/lmgr/predicate.c:4065 storage/lmgr/predicate.c:4104 storage/lmgr/predicate.c:4334 storage/lmgr/predicate.c:4653 storage/lmgr/predicate.c:4665 storage/lmgr/predicate.c:4712 storage/lmgr/predicate.c:4748 +#: storage/lmgr/predicate.c:4003 storage/lmgr/predicate.c:4039 storage/lmgr/predicate.c:4072 storage/lmgr/predicate.c:4080 storage/lmgr/predicate.c:4119 storage/lmgr/predicate.c:4349 storage/lmgr/predicate.c:4668 storage/lmgr/predicate.c:4680 storage/lmgr/predicate.c:4727 storage/lmgr/predicate.c:4763 #, c-format msgid "The transaction might succeed if retried." msgstr "ტრანზაქცია შეიძლება გაიტანოს, თუ გაიმეორებთ." -#: storage/lmgr/proc.c:348 +#: storage/lmgr/proc.c:454 #, c-format msgid "number of requested standby connections exceeds \"max_wal_senders\" (currently %d)" msgstr "" -#: storage/lmgr/proc.c:1541 +#: storage/lmgr/proc.c:1592 #, c-format msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" msgstr "" -#: storage/lmgr/proc.c:1556 +#: storage/lmgr/proc.c:1607 #, c-format msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "" -#: storage/lmgr/proc.c:1565 +#: storage/lmgr/proc.c:1616 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "" -#: storage/lmgr/proc.c:1572 +#: storage/lmgr/proc.c:1623 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "" -#: storage/lmgr/proc.c:1589 +#: storage/lmgr/proc.c:1640 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "" -#: storage/page/bufpage.c:152 +#: storage/page/bufpage.c:154 #, c-format msgid "page verification failed, calculated checksum %u but expected %u" msgstr "" -#: storage/page/bufpage.c:217 storage/page/bufpage.c:730 storage/page/bufpage.c:1073 storage/page/bufpage.c:1208 storage/page/bufpage.c:1314 storage/page/bufpage.c:1426 +#: storage/page/bufpage.c:216 storage/page/bufpage.c:729 storage/page/bufpage.c:1072 storage/page/bufpage.c:1207 storage/page/bufpage.c:1313 storage/page/bufpage.c:1425 #, c-format msgid "corrupted page pointers: lower = %u, upper = %u, special = %u" msgstr "" -#: storage/page/bufpage.c:759 +#: storage/page/bufpage.c:758 #, c-format msgid "corrupted line pointer: %u" msgstr "ხაზის დაზიანებული მაჩვენებელი: %u" -#: storage/page/bufpage.c:789 storage/page/bufpage.c:1266 +#: storage/page/bufpage.c:788 storage/page/bufpage.c:1265 #, c-format msgid "corrupted item lengths: total %u, available space %u" msgstr "" -#: storage/page/bufpage.c:1092 storage/page/bufpage.c:1233 storage/page/bufpage.c:1330 storage/page/bufpage.c:1442 +#: storage/page/bufpage.c:1091 storage/page/bufpage.c:1232 storage/page/bufpage.c:1329 storage/page/bufpage.c:1441 #, c-format msgid "corrupted line pointer: offset = %u, size = %u" msgstr "" -#: storage/smgr/md.c:485 storage/smgr/md.c:547 +#: storage/smgr/md.c:502 storage/smgr/md.c:564 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "" -#: storage/smgr/md.c:500 storage/smgr/md.c:611 +#: storage/smgr/md.c:517 storage/smgr/md.c:628 #, c-format msgid "could not extend file \"%s\": %m" msgstr "ფაილის გაფართოების შეცდომა \"%s\": %m" -#: storage/smgr/md.c:506 +#: storage/smgr/md.c:523 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "" -#: storage/smgr/md.c:589 +#: storage/smgr/md.c:606 #, c-format msgid "could not extend file \"%s\" with FileFallocate(): %m" msgstr "ფაილის (\"%s\") FileFallocate()-ით გაფართოების შეცდომა: %m" -#: storage/smgr/md.c:869 +#: storage/smgr/md.c:899 storage/smgr/md.c:2047 #, c-format msgid "could not read blocks %u..%u in file \"%s\": %m" msgstr "ბლოკების %u..%u წაკითხვის შეცდომა ფაილში \"%s\": %m" -#: storage/smgr/md.c:895 +#: storage/smgr/md.c:946 storage/smgr/md.c:2060 #, c-format msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" msgstr "ვერ წავიკითხე ბლოკები %u..%u ფაილში \"%s\": წავიკითხე, მხოლოდ, %zu ბაიტი %zu-დან" -#: storage/smgr/md.c:995 +#: storage/smgr/md.c:1023 +#, c-format +msgid "could not start reading blocks %u..%u in file \"%s\": %m" +msgstr "ბლოკების %u..%u წაკითხვის დაწყების შეცდომა ფაილში \"%s\": %m" + +#: storage/smgr/md.c:1119 #, c-format msgid "could not write blocks %u..%u in file \"%s\": %m" msgstr "ბლოკის %u..%u ჩაწერის შეცდომა ფაილში \"%s\": %m" -#: storage/smgr/md.c:1163 +#: storage/smgr/md.c:1289 #, c-format msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" msgstr "" -#: storage/smgr/md.c:1218 +#: storage/smgr/md.c:1344 #, c-format msgid "could not truncate file \"%s\" to %u blocks: %m" msgstr "" -#: storage/smgr/md.c:1688 +#: storage/smgr/md.c:1832 #, c-format msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" msgstr "" -#: storage/smgr/md.c:1702 +#: storage/smgr/md.c:1846 #, c-format msgid "could not open file \"%s\" (target block %u): %m" msgstr "" -#: tcop/backend_startup.c:85 +#: storage/smgr/smgr.c:1106 +#, c-format +msgid "file \"%s\"" +msgstr "ფაილი \"%s\"" + +#: storage/smgr/smgr.c:1108 +#, c-format +msgid "block %u in file \"%s\"" +msgstr "ბლოკი %u ფაილში \"%s\"" + +#: storage/smgr/smgr.c:1112 +#, c-format +msgid "blocks %u..%u in file \"%s\"" +msgstr "ბლოკები %u..%u ფაილში \"%s\"" + +#: tcop/backend_startup.c:104 #, c-format msgid "SSL configuration could not be loaded in child process" msgstr "SSL კონფიგურაციის შვილ პროცესში შეტვირთვის შეცდომა" -#: tcop/backend_startup.c:208 +#: tcop/backend_startup.c:226 #, c-format msgid "connection received: host=%s port=%s" msgstr "შემოსული დაკავშირება: ჰოსტი=%s პორტი=%s" -#: tcop/backend_startup.c:213 +#: tcop/backend_startup.c:231 #, c-format msgid "connection received: host=%s" msgstr "შემოსული დაკავშირება: ჰოსტი=%s" -#: tcop/backend_startup.c:277 +#: tcop/backend_startup.c:309 #, c-format msgid "the database system is starting up" msgstr "მიმდინარეობს მონაცემთა ბაზის სისტემის გაშვება" -#: tcop/backend_startup.c:283 +#: tcop/backend_startup.c:315 +#, c-format +msgid "the database system is not accepting connections" +msgstr "მონაცემთა ბაზის სისტემა მიერთებებს არ იღებს" + +#: tcop/backend_startup.c:316 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "ცხელი ლოდინის რეჟიმი გამორთულია." + +#: tcop/backend_startup.c:320 tcop/backend_startup.c:327 #, c-format msgid "the database system is not yet accepting connections" msgstr "მონაცემთა ბაზის სისტემა ჯერ მიერთებებს არ იღებს" -#: tcop/backend_startup.c:284 +#: tcop/backend_startup.c:321 #, c-format -msgid "Consistent recovery state has not been yet reached." +msgid "Recovery snapshot is not yet ready for hot standby." msgstr "" -#: tcop/backend_startup.c:288 +#: tcop/backend_startup.c:322 #, c-format -msgid "the database system is not accepting connections" -msgstr "მონაცემთა ბაზის სისტემა მიერთებებს არ იღებს" +msgid "To enable hot standby, close write transactions with more than %d subtransactions on the primary server." +msgstr "" -#: tcop/backend_startup.c:289 +#: tcop/backend_startup.c:328 #, c-format -msgid "Hot standby mode is disabled." -msgstr "ცხელი ლოდინის რეჟიმი გამორთულია." +msgid "Consistent recovery state has not been yet reached." +msgstr "" -#: tcop/backend_startup.c:294 +#: tcop/backend_startup.c:333 #, c-format msgid "the database system is shutting down" msgstr "მონაცემთა ბაზის სისტემა ითიშება" -#: tcop/backend_startup.c:299 +#: tcop/backend_startup.c:338 #, c-format msgid "the database system is in recovery mode" msgstr "მონაცემთა ბაზის სისტემა აღდგენის რეჟიმშია" -#: tcop/backend_startup.c:414 +#: tcop/backend_startup.c:453 #, c-format msgid "received direct SSL connection request without ALPN protocol negotiation extension" msgstr "" -#: tcop/backend_startup.c:420 +#: tcop/backend_startup.c:459 #, c-format msgid "direct SSL connection accepted" msgstr "პირდაპირი SSL მიერთება მიღებულია" -#: tcop/backend_startup.c:430 +#: tcop/backend_startup.c:469 #, c-format msgid "direct SSL connection rejected" msgstr "პირდაპირი SSL მიერთება უარყოფილია" -#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#: tcop/backend_startup.c:528 tcop/backend_startup.c:556 #, c-format msgid "incomplete startup packet" msgstr "გაშვების დაუსრულებელი პაკეტი" -#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#: tcop/backend_startup.c:540 #, c-format msgid "invalid length of startup packet" msgstr "გაშვების პაკეტის არასწორი სიგრძე" -#: tcop/backend_startup.c:573 +#: tcop/backend_startup.c:597 #, c-format msgid "SSLRequest accepted" msgstr "" -#: tcop/backend_startup.c:576 +#: tcop/backend_startup.c:600 #, c-format msgid "SSLRequest rejected" msgstr "" -#: tcop/backend_startup.c:585 +#: tcop/backend_startup.c:609 #, c-format msgid "failed to send SSL negotiation response: %m" msgstr "შეცდომა SSL მოლაპარაკების პასუხის გაგზავნისას: %m" -#: tcop/backend_startup.c:603 +#: tcop/backend_startup.c:627 #, c-format msgid "received unencrypted data after SSL request" msgstr "'SSL'-ის მოთხოვნის შემდეგ მიღებულია დაუშიფრავი მონაცემები" -#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#: tcop/backend_startup.c:628 tcop/backend_startup.c:682 #, c-format msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." msgstr "" -#: tcop/backend_startup.c:627 +#: tcop/backend_startup.c:651 #, c-format msgid "GSSENCRequest accepted" msgstr "" -#: tcop/backend_startup.c:630 +#: tcop/backend_startup.c:654 #, c-format msgid "GSSENCRequest rejected" msgstr "" -#: tcop/backend_startup.c:639 +#: tcop/backend_startup.c:663 #, c-format msgid "failed to send GSSAPI negotiation response: %m" msgstr "შეცდომა GSSAPI მოლაპარაკების პასუხის გაგზავნისას: %m" -#: tcop/backend_startup.c:657 +#: tcop/backend_startup.c:681 #, c-format msgid "received unencrypted data after GSSAPI encryption request" msgstr "'GSSAPI' დაშიფვრის მოთხოვნის შემდეგ მიღებული მონაცემები დაუშიფრავია" -#: tcop/backend_startup.c:681 +#: tcop/backend_startup.c:709 #, c-format msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" msgstr "" -#: tcop/backend_startup.c:744 +#: tcop/backend_startup.c:772 #, c-format msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." msgstr "სწორი მნიშვნელობებია: \"false\", 0, \"true\", 1, \"database\"." -#: tcop/backend_startup.c:785 +#: tcop/backend_startup.c:813 #, c-format msgid "invalid startup packet layout: expected terminator as last byte" msgstr "" -#: tcop/backend_startup.c:802 +#: tcop/backend_startup.c:830 #, c-format msgid "no PostgreSQL user name specified in startup packet" msgstr "გაშვების პაკეტში PostgreSQL-ის მომხმარებლის სახელი მითითებული არაა" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 +#: tcop/backend_startup.c:884 +#, c-format +msgid "invalid length of query cancel packet" +msgstr "მოთხოვნის გაუქმების პაკეტის სიგრძე არასწორია" + +#: tcop/backend_startup.c:892 +#, c-format +msgid "invalid length of query cancel key" +msgstr "მოთხოვნის გაუქმების გასაღების სიგრძე არასწორია" + +#: tcop/backend_startup.c:1022 +#, c-format +msgid "Cannot specify log_connections option \"%s\" in a list with other options." +msgstr "ვერ მიუთითებთ log_connections-ის პარამეტრს \"%s\" სიაში, სადაც სხვა პარამეტრებიცაა." + +#: tcop/backend_startup.c:1080 +#, c-format +msgid "Invalid list syntax in parameter \"log_connections\"." +msgstr "არასწორი სიის სინტაქსი პარამეტრში \"log_connections\"." + +#: tcop/fastpath.c:141 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "ფუნქცია OID-ით %u არ არსებობს" -#: tcop/fastpath.c:149 +#: tcop/fastpath.c:148 #, c-format msgid "cannot call function \"%s\" via fastpath interface" msgstr "" -#: tcop/fastpath.c:234 +#: tcop/fastpath.c:233 #, c-format msgid "fastpath function call: \"%s\" (OID %u)" msgstr "" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 tcop/postgres.c:2055 tcop/postgres.c:2305 +#: tcop/fastpath.c:312 tcop/postgres.c:1364 tcop/postgres.c:1600 tcop/postgres.c:2079 tcop/postgres.c:2351 #, c-format msgid "duration: %s ms" msgstr "ხანგრძლივობა: %s მწმ" -#: tcop/fastpath.c:317 +#: tcop/fastpath.c:316 #, c-format msgid "duration: %s ms fastpath function call: \"%s\" (OID %u)" msgstr "" -#: tcop/fastpath.c:353 +#: tcop/fastpath.c:352 #, c-format msgid "function call message contains %d arguments but function requires %d" msgstr "" -#: tcop/fastpath.c:361 +#: tcop/fastpath.c:360 #, c-format msgid "function call message contains %d argument formats but %d arguments" msgstr "" -#: tcop/fastpath.c:385 +#: tcop/fastpath.c:384 #, c-format msgid "invalid argument size %d in function call message" msgstr "" -#: tcop/fastpath.c:448 +#: tcop/fastpath.c:447 #, c-format msgid "incorrect binary data format in function argument %d" msgstr "" -#: tcop/postgres.c:463 tcop/postgres.c:4925 +#: tcop/postgres.c:455 tcop/postgres.c:5023 #, c-format msgid "invalid frontend message type %d" msgstr "არასწორი წინაბოლოს შეტყობინების ტიპი %d" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1070 #, c-format msgid "statement: %s" msgstr "ოპერატორი: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1369 #, c-format msgid "duration: %s ms statement: %s" msgstr "ხანგრძლივობა: %s მწმ გამოსახულება: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1475 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1605 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "ხანგრძლივობა: %s მწმ %s-ის დამუშავება: %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2625 +#: tcop/postgres.c:1672 tcop/postgres.c:2671 #, c-format msgid "unnamed prepared statement does not exist" msgstr "" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1724 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1730 #, c-format msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d" msgstr "" -#: tcop/postgres.c:1933 +#: tcop/postgres.c:1944 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "" -#: tcop/postgres.c:2060 +#: tcop/postgres.c:2084 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "ხანგრძლივობა: %s მწმ მიბმა %s%s%s: %s" -#: tcop/postgres.c:2114 tcop/postgres.c:2708 +#: tcop/postgres.c:2139 tcop/postgres.c:2753 #, c-format msgid "portal \"%s\" does not exist" msgstr "პორტალი \"%s\" არ არსებობს" -#: tcop/postgres.c:2185 +#: tcop/postgres.c:2232 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2187 tcop/postgres.c:2313 +#: tcop/postgres.c:2234 tcop/postgres.c:2359 msgid "execute fetch from" msgstr "" -#: tcop/postgres.c:2188 tcop/postgres.c:2314 +#: tcop/postgres.c:2235 tcop/postgres.c:2360 msgid "execute" msgstr "გაშვება" -#: tcop/postgres.c:2310 +#: tcop/postgres.c:2356 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "ხანგრძლივობა: %s მწმs %s %s%s%s: %s" -#: tcop/postgres.c:2458 +#: tcop/postgres.c:2504 #, c-format msgid "prepare: %s" msgstr "მომზადება: %s" -#: tcop/postgres.c:2483 +#: tcop/postgres.c:2529 #, c-format msgid "Parameters: %s" msgstr "პარამეტრები: %s" -#: tcop/postgres.c:2498 +#: tcop/postgres.c:2544 #, c-format msgid "Abort reason: recovery conflict" msgstr "გაუქმების მიზეზი: აღდგენის კონფლიქტი" -#: tcop/postgres.c:2514 +#: tcop/postgres.c:2560 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "" -#: tcop/postgres.c:2517 +#: tcop/postgres.c:2563 #, c-format msgid "User was holding a relation lock for too long." msgstr "" -#: tcop/postgres.c:2520 +#: tcop/postgres.c:2566 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "" -#: tcop/postgres.c:2523 +#: tcop/postgres.c:2569 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "" -#: tcop/postgres.c:2526 +#: tcop/postgres.c:2572 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "" -#: tcop/postgres.c:2532 +#: tcop/postgres.c:2578 #, c-format msgid "User was connected to a database that must be dropped." msgstr "" -#: tcop/postgres.c:2571 +#: tcop/postgres.c:2617 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "პორტალის \"%s\" პარამეტრი $%d = %s" -#: tcop/postgres.c:2574 +#: tcop/postgres.c:2620 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "პორტალის \"%s\" პარამეტრი $%d" -#: tcop/postgres.c:2580 +#: tcop/postgres.c:2626 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "უსახელო პორტალის პარამეტრი $%d = %s" -#: tcop/postgres.c:2583 +#: tcop/postgres.c:2629 #, c-format msgid "unnamed portal parameter $%d" msgstr "უსახელო პორტალის პარამეტრი $%d" -#: tcop/postgres.c:2928 +#: tcop/postgres.c:2984 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "" -#: tcop/postgres.c:2934 +#: tcop/postgres.c:2990 #, c-format msgid "terminating connection because of crash of another server process" msgstr "" -#: tcop/postgres.c:2935 +#: tcop/postgres.c:2991 #, c-format msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory." msgstr "" -#: tcop/postgres.c:2939 tcop/postgres.c:3192 +#: tcop/postgres.c:2995 tcop/postgres.c:3248 #, c-format msgid "In a moment you should be able to reconnect to the database and repeat your command." msgstr "" -#: tcop/postgres.c:2946 +#: tcop/postgres.c:3002 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "მიერთების შეწყვეტა დაუყოვნებლივი გამორთვის ბრძანების გამო" -#: tcop/postgres.c:3024 +#: tcop/postgres.c:3080 #, c-format msgid "floating-point exception" msgstr "წილადი რიცხვების ანგარიშის შეცდომა" -#: tcop/postgres.c:3025 +#: tcop/postgres.c:3081 #, c-format msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero." msgstr "" -#: tcop/postgres.c:3190 +#: tcop/postgres.c:3246 #, c-format msgid "terminating connection due to conflict with recovery" msgstr "მიერთების შეწყვეტა აღდგენასთან კონფლიქტის გამო" -#: tcop/postgres.c:3262 +#: tcop/postgres.c:3318 #, c-format msgid "canceling authentication due to timeout" msgstr "ავთენტიკაცია გაუქმდა მოლოდინის ვადის ამოწურვის გამო" -#: tcop/postgres.c:3266 +#: tcop/postgres.c:3322 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "ავტომომტვერსასრუტების პროცესის შეწყვეტა ადმინისტრატორის ბრძანების გამო" -#: tcop/postgres.c:3270 +#: tcop/postgres.c:3326 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "ლოგიკური რეპლიკაციის დამხმარე პროცესის შეწყვეტა ადმინისტრატორის ბრძანების გამო" -#: tcop/postgres.c:3290 +#: tcop/postgres.c:3341 +#, c-format +msgid "terminating walreceiver process due to administrator command" +msgstr "walreceiver პროგრამის შეწყვეტა ადმინისტრატორის ბრძანების გამო" + +#: tcop/postgres.c:3357 #, c-format msgid "terminating connection due to administrator command" msgstr "მიერთების შეწყვეტა ადმინისტრატორის ბრძანების გამო" -#: tcop/postgres.c:3321 +#: tcop/postgres.c:3388 #, c-format msgid "connection to client lost" msgstr "კლიენტთან შეერთების შეცდომა" -#: tcop/postgres.c:3373 +#: tcop/postgres.c:3440 #, c-format msgid "canceling statement due to lock timeout" msgstr "გამოსახულება გაუქმდება ბლოკის მოლოდინის ვადის ამოწურვის გამო" -#: tcop/postgres.c:3380 +#: tcop/postgres.c:3447 #, c-format msgid "canceling statement due to statement timeout" msgstr "" -#: tcop/postgres.c:3387 +#: tcop/postgres.c:3454 #, c-format msgid "canceling autovacuum task" msgstr "ავტომომტვერსასრუტების ამოცანის გაუქმება" -#: tcop/postgres.c:3400 +#: tcop/postgres.c:3467 #, c-format msgid "canceling statement due to user request" msgstr "" -#: tcop/postgres.c:3421 +#: tcop/postgres.c:3488 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "" -#: tcop/postgres.c:3434 +#: tcop/postgres.c:3501 #, c-format msgid "terminating connection due to transaction timeout" msgstr "მიერთების შეწყვეტა ტრანზაქციის მოლოდინის ვადის ამოწურვის გამო" -#: tcop/postgres.c:3447 +#: tcop/postgres.c:3514 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "" -#: tcop/postgres.c:3537 -#, c-format -msgid "stack depth limit exceeded" -msgstr "გადაცილებულია სტეკის სიღრმის ლიმიტი" - -#: tcop/postgres.c:3538 -#, c-format -msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." -msgstr "" - -#: tcop/postgres.c:3585 -#, c-format -msgid "\"max_stack_depth\" must not exceed %ldkB." -msgstr "\"max_stack_depth\" %ldკბ-ს არ უნდა ზცდებოდეს." - -#: tcop/postgres.c:3587 -#, c-format -msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." -msgstr "" - -#: tcop/postgres.c:3610 +#: tcop/postgres.c:3553 #, c-format msgid "\"client_connection_check_interval\" must be set to 0 on this platform." msgstr "ამ პლატფორმაზე \"client_connection_check_interval\" 0 უნდა იყოს." -#: tcop/postgres.c:3631 +#: tcop/postgres.c:3574 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "პარამეტრის ჩართვა მაშინ, როცა \"log_statement_stats\" ჩართულია, შეუძლებელია." -#: tcop/postgres.c:3646 +#: tcop/postgres.c:3589 #, c-format msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true." msgstr "ვერ ჩართავთ \"log_statement_stats\"-ს, როცა \"when log_parser_stats\", \"log_planner_stats\", ან \"log_executor_stats\" ჭეშმარიტია." -#: tcop/postgres.c:4011 +#: tcop/postgres.c:4029 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "" -#: tcop/postgres.c:4012 tcop/postgres.c:4018 +#: tcop/postgres.c:4030 tcop/postgres.c:4036 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: tcop/postgres.c:4016 +#: tcop/postgres.c:4034 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: არასწორი ბრძანების სტრიქონის არგუმენტი: %s" -#: tcop/postgres.c:4069 +#: tcop/postgres.c:4087 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: არც ბაზა, არც მომხმარებელი მითითებული არაა" -#: tcop/postgres.c:4822 +#: tcop/postgres.c:4280 +#, c-format +msgid "could not generate random cancel key" +msgstr "შემთხვევითი გაუქმების გასაღების გენერაცია შეუძლებელია" + +#: tcop/postgres.c:4682 +#, c-format +msgid "connection ready: setup total=%.3f ms, fork=%.3f ms, authentication=%.3f ms" +msgstr "" + +#: tcop/postgres.c:4913 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "არასწორი CLOSE შეტყობინების ქვეტიპი %d" -#: tcop/postgres.c:4859 +#: tcop/postgres.c:4950 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "არასწორი DESCRIBE შეტყობინების ქვეტიპი %d" -#: tcop/postgres.c:4946 +#: tcop/postgres.c:5044 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "" -#: tcop/postgres.c:4950 +#: tcop/postgres.c:5048 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "" -#: tcop/postgres.c:5130 +#: tcop/postgres.c:5194 #, c-format msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s" msgstr "" -#: tcop/pquery.c:641 +#: tcop/pquery.c:674 #, c-format msgid "bind message has %d result formats but query has %d columns" msgstr "" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:972 tcop/pquery.c:1734 #, c-format msgid "cursor can only scan forward" msgstr "კურსორს მხოლოდ წინ სკანირება შეუძლია" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:973 tcop/pquery.c:1735 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "" @@ -23437,68 +24386,68 @@ msgid "cannot execute %s within security-restricted operation" msgstr "" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:821 +#: tcop/utility.c:824 #, c-format msgid "cannot execute %s within a background process" msgstr "ფონის პროცესში %s-ის შესრულება შეუძლებელია" #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:947 +#: tcop/utility.c:950 #, c-format msgid "permission denied to execute %s command" msgstr "ბრძანების შესრულების წვდომა აკრძალულია: %s" -#: tcop/utility.c:949 +#: tcop/utility.c:952 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "ამ ბრძანების შესრულება მხოლოდ \"%s\" როლის პრივილეგიების მქონეებს შეუძლიათ." -#: tsearch/dict_ispell.c:52 tsearch/dict_thesaurus.c:616 +#: tsearch/dict_ispell.c:53 tsearch/dict_thesaurus.c:616 #, c-format msgid "multiple DictFile parameters" msgstr "გამეორებადი DictFile პარამეტრი" -#: tsearch/dict_ispell.c:63 +#: tsearch/dict_ispell.c:64 #, c-format msgid "multiple AffFile parameters" msgstr "გამეორებადი AffFile პარამეტრი" -#: tsearch/dict_ispell.c:82 +#: tsearch/dict_ispell.c:83 #, c-format msgid "unrecognized Ispell parameter: \"%s\"" msgstr "უცნობი lspell-ის პარამეტრი: \"%s\"" -#: tsearch/dict_ispell.c:96 +#: tsearch/dict_ispell.c:97 #, c-format msgid "missing AffFile parameter" msgstr "აკლია პარამეტრი AffFile" -#: tsearch/dict_ispell.c:102 tsearch/dict_thesaurus.c:640 +#: tsearch/dict_ispell.c:103 tsearch/dict_thesaurus.c:640 #, c-format msgid "missing DictFile parameter" msgstr "აკლია პარამეტრი DictFile" -#: tsearch/dict_simple.c:58 +#: tsearch/dict_simple.c:59 #, c-format msgid "multiple Accept parameters" msgstr "გამეორებადი Accept პარამეტრი" -#: tsearch/dict_simple.c:66 +#: tsearch/dict_simple.c:67 #, c-format msgid "unrecognized simple dictionary parameter: \"%s\"" msgstr "უცნობი მარტივი ლექსიკონის პარამეტრი: \"%s\"" -#: tsearch/dict_synonym.c:118 +#: tsearch/dict_synonym.c:120 #, c-format msgid "unrecognized synonym parameter: \"%s\"" msgstr "უცნობი სინონიმის პარამეტრი: \"%s\"" -#: tsearch/dict_synonym.c:125 +#: tsearch/dict_synonym.c:127 #, c-format msgid "missing Synonyms parameter" msgstr "აკლია პარამეტრი Synonyms" -#: tsearch/dict_synonym.c:132 +#: tsearch/dict_synonym.c:134 #, c-format msgid "could not open synonym file \"%s\": %m" msgstr "სინონიმს ფაილი \"%s\" ვერ გავხსენი: %m" @@ -23573,76 +24522,71 @@ msgstr "გამოუცნობი განმარტებითი ლ msgid "missing Dictionary parameter" msgstr "აკლია პარამეტრი Dictionary" -#: tsearch/spell.c:381 tsearch/spell.c:398 tsearch/spell.c:407 tsearch/spell.c:1043 +#: tsearch/spell.c:383 tsearch/spell.c:400 tsearch/spell.c:409 tsearch/spell.c:1046 #, c-format msgid "invalid affix flag \"%s\"" msgstr "აფიქსის არასწორი ალამი: %s" -#: tsearch/spell.c:385 tsearch/spell.c:1047 +#: tsearch/spell.c:387 tsearch/spell.c:1050 #, c-format msgid "affix flag \"%s\" is out of range" msgstr "აფიქსის ალამი დიაპაზონს გარეთაა: %s" -#: tsearch/spell.c:415 +#: tsearch/spell.c:417 #, c-format msgid "invalid character in affix flag \"%s\"" msgstr "არასწორი სიმბოლო აფიქსის ალამში: %s" -#: tsearch/spell.c:435 +#: tsearch/spell.c:437 #, c-format msgid "invalid affix flag \"%s\" with \"long\" flag value" msgstr "აფიქსის არასწორი ალამი \"%s\" ალამის მნიშვნელობით \"long\"" -#: tsearch/spell.c:525 +#: tsearch/spell.c:527 #, c-format msgid "could not open dictionary file \"%s\": %m" msgstr "ლექსიკონის ფაილის (%s) გახსნის შეცდომა: %m" -#: tsearch/spell.c:1170 tsearch/spell.c:1182 tsearch/spell.c:1742 tsearch/spell.c:1747 tsearch/spell.c:1752 +#: tsearch/spell.c:1174 tsearch/spell.c:1186 tsearch/spell.c:1751 tsearch/spell.c:1756 tsearch/spell.c:1761 #, c-format msgid "invalid affix alias \"%s\"" msgstr "აფისქსის არასწორი მეტსახელი: %s" -#: tsearch/spell.c:1223 tsearch/spell.c:1294 tsearch/spell.c:1443 +#: tsearch/spell.c:1227 tsearch/spell.c:1298 tsearch/spell.c:1447 #, c-format msgid "could not open affix file \"%s\": %m" msgstr "აფიქსის ფაილის (%s) გახსნის შეცდომა: %m" -#: tsearch/spell.c:1277 +#: tsearch/spell.c:1281 #, c-format msgid "Ispell dictionary supports only \"default\", \"long\", and \"num\" flag values" msgstr "" -#: tsearch/spell.c:1321 +#: tsearch/spell.c:1325 #, c-format msgid "invalid number of flag vector aliases" msgstr "ალმის ვექტორის მეტსახელების არასწორი რიცხვი" -#: tsearch/spell.c:1344 +#: tsearch/spell.c:1348 #, c-format msgid "number of aliases exceeds specified number %d" msgstr "მეტსახელების რიცხვი მითითებულ მნიშვნელობაზე მეტია: %d" -#: tsearch/spell.c:1559 +#: tsearch/spell.c:1563 #, c-format msgid "affix file contains both old-style and new-style commands" msgstr "აფიქსის ფაილი ორივე, ახალი და ძველი სტილის ბრძანებებს შეიცავს" -#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:274 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "სტრიქონი tsvector-ისთვის ძალიანგრძელია (%d ბაიტი, მაქს %d ბაიტი)" -#: tsearch/ts_locale.c:236 +#: tsearch/ts_locale.c:191 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "კონფიგურაციის ფაილის \"%2$s\" %1$d-ე ხაზზე: \"%3$s\"" -#: tsearch/ts_locale.c:315 -#, c-format -msgid "conversion from wchar_t to server encoding failed: %m" -msgstr "" - #: tsearch/ts_parse.c:387 tsearch/ts_parse.c:394 tsearch/ts_parse.c:573 tsearch/ts_parse.c:580 #, c-format msgid "word is too long to be indexed" @@ -23653,12 +24597,12 @@ msgstr "სიტყვა ძალიან გრძელია, რომ msgid "Words longer than %d characters are ignored." msgstr "%d სიმბოლოზე გრძელი სიტყვები იგნორირდება." -#: tsearch/ts_utils.c:51 +#: tsearch/ts_utils.c:52 #, c-format msgid "invalid text search configuration file name \"%s\"" msgstr "ტექსტის ძებნის კონფიგურაციის ფაილის არასწორი სახელი: \"%s\"" -#: tsearch/ts_utils.c:83 +#: tsearch/ts_utils.c:84 #, c-format msgid "could not open stop-word file \"%s\": %m" msgstr "" @@ -23675,60 +24619,105 @@ msgstr "" #: tsearch/wparser_def.c:2674 #, c-format -msgid "MinWords should be less than MaxWords" -msgstr "MinWords MaxWords-ზე ნაკლები უნდა იყოს" +msgid "%s must be less than %s" +msgstr "%s უნდა იყოს %s-ზე ნაკლები" #: tsearch/wparser_def.c:2678 #, c-format -msgid "MinWords should be positive" -msgstr "MinWords დადებით უნდა იყოს" - -#: tsearch/wparser_def.c:2682 -#, c-format -msgid "ShortWord should be >= 0" -msgstr "ShortWord >= 0 უნდა იყოს" +msgid "%s must be positive" +msgstr "%s დადებითი უნდა იყოს" -#: tsearch/wparser_def.c:2686 +#: tsearch/wparser_def.c:2682 tsearch/wparser_def.c:2686 #, c-format -msgid "MaxFragments should be >= 0" -msgstr "MaxFragments >= 0 უნდა იყოს" +msgid "%s must be >= 0" +msgstr "" -#: utils/activity/pgstat.c:435 +#: utils/activity/pgstat.c:533 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "" -#: utils/activity/pgstat.c:1252 +#: utils/activity/pgstat.c:1443 #, c-format msgid "invalid statistics kind: \"%s\"" msgstr "სტატისტიკის არასწორი ტიპი: \"%s\"" -#: utils/activity/pgstat.c:1332 +#: utils/activity/pgstat.c:1488 +#, c-format +msgid "custom cumulative statistics name is invalid" +msgstr "კუმულატიური სტატისტიკის ხელით მითითებული სახელი არასწორია" + +#: utils/activity/pgstat.c:1489 +#, c-format +msgid "Provide a non-empty name for the custom cumulative statistics." +msgstr "მიუთითეთ არაცარიელი სახელი მორგებული დაგროვებადი სტატისტიკისთვის." + +#: utils/activity/pgstat.c:1492 +#, c-format +msgid "custom cumulative statistics ID %u is out of range" +msgstr "კუმულატიური სტატისტიკის ხელით მითითებული ID %u დიაპაზონს გარეთაა" + +#: utils/activity/pgstat.c:1493 +#, c-format +msgid "Provide a custom cumulative statistics ID between %u and %u." +msgstr "შეიყვანეთ რესურსების ხელით მითითებული კუმულაციური სტატისტიკის ID %u-დან %u-მდე შუალედიდან." + +#: utils/activity/pgstat.c:1498 utils/activity/pgstat.c:1525 utils/activity/pgstat.c:1538 +#, c-format +msgid "failed to register custom cumulative statistics \"%s\" with ID %u" +msgstr "ვერ დარეგისტრირდა მორგებული დაგროვებითი სტატისტიკა \"%s\" ID-ით %u" + +#: utils/activity/pgstat.c:1499 +#, c-format +msgid "Custom cumulative statistics must be registered while initializing modules in \"shared_preload_libraries\"." +msgstr "მომხმარებლის კუმულაციური სტატისტიკის რეგისტრაცია \"shared_preload_libraries\"-ში მოდულების ინიციალიზაციისას უნდა მოხდეს." + +#: utils/activity/pgstat.c:1508 +#, c-format +msgid "custom cumulative statistics property is invalid" +msgstr "" + +#: utils/activity/pgstat.c:1509 +#, c-format +msgid "Custom cumulative statistics require a shared memory size for fixed-numbered objects." +msgstr "" + +#: utils/activity/pgstat.c:1526 +#, c-format +msgid "Custom cumulative statistics \"%s\" already registered with the same ID." +msgstr "მორგებული კუმულაციური სტატისტიკა \"%s\" უკვე რეგისტრირებულია, იგივე ID-ით." + +#: utils/activity/pgstat.c:1539 +#, c-format +msgid "Existing cumulative statistics with ID %u has the same name." +msgstr "არსებულ კუმულატიურ სტატისტიკას ID-ით %u იგივე სახელი აქვს." + +#: utils/activity/pgstat.c:1545 +#, c-format +msgid "registered custom cumulative statistics \"%s\" with ID %u" +msgstr "რეგისტრირებულია მორგებული კუმულაციური სტატისტიკა \"%s\" ID-ით %u" + +#: utils/activity/pgstat.c:1614 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "სტატისტიკის დროებითი ფაილის (\"%s\") გახსნა შეუძლებელია: %m" -#: utils/activity/pgstat.c:1444 +#: utils/activity/pgstat.c:1735 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "სტატისტიკის დროებითი ფაილში (\"%s\") ჩაწერა შეუძლებელია: %m" -#: utils/activity/pgstat.c:1453 +#: utils/activity/pgstat.c:1744 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "სტატისტიკის დროებითი ფაილის (\"%s\") დახურვა შეუძლებელია: %m" -#: utils/activity/pgstat.c:1461 -#, c-format -msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" -msgstr "სტატისტიკის დროებითი ფაილის \"%s\"-დან \"%s\" -მდე სახელის გადარქმევა შეუძლებელია: %m" - -#: utils/activity/pgstat.c:1510 +#: utils/activity/pgstat.c:1798 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "სტატისტიკის ფაილის (\"%s\") გახსნა შეუძლებელია: %m" -#: utils/activity/pgstat.c:1672 +#: utils/activity/pgstat.c:2030 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "სტატისტიკის დაზიანებული ფაილი \"%s\"" @@ -23738,178 +24727,183 @@ msgstr "სტატისტიკის დაზიანებული ფ msgid "function call to dropped function" msgstr "ფუნქცია წაშლილ ფუნქციას იძახებს" -#: utils/activity/pgstat_xact.c:362 +#: utils/activity/pgstat_xact.c:366 #, c-format -msgid "resetting existing statistics for kind %s, db=%u, oid=%u" +msgid "resetting existing statistics for kind %s, db=%u, oid=%" msgstr "" -#: utils/activity/wait_event.c:210 +#: utils/activity/wait_event.c:206 utils/activity/wait_event.c:231 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "მოცდის მოვლენა \"%s\" უკვე არსებობს ტიპში \"%s\"" + +#: utils/activity/wait_event.c:245 #, c-format -msgid "too many wait events for extensions" -msgstr "მეტისმეტად ბევრი მოცდის მოვლენა გაფართოებებისთვის" +msgid "too many custom wait events" +msgstr "მეტისმეტად ბევრი მორგებული მოცდის მოვლენა" -#: utils/adt/acl.c:183 utils/adt/name.c:93 +#: utils/adt/acl.c:187 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "იდენტიფიკატორი ძალიან გრძელია" -#: utils/adt/acl.c:184 utils/adt/name.c:94 +#: utils/adt/acl.c:188 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "" -#: utils/adt/acl.c:272 +#: utils/adt/acl.c:276 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "უცნობი საკვანძო სიტყვა: \"%s\"" -#: utils/adt/acl.c:273 +#: utils/adt/acl.c:277 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "ACL-ის საკვანძო სიტყვა უნდა იყოს \"group\" ან \"user\"." -#: utils/adt/acl.c:281 +#: utils/adt/acl.c:285 #, c-format msgid "missing name" msgstr "სახელი აკლია" -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:286 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "" -#: utils/adt/acl.c:288 +#: utils/adt/acl.c:292 #, c-format msgid "missing \"=\" sign" msgstr "აკლია \"=\" ნიშანი" -#: utils/adt/acl.c:350 +#: utils/adt/acl.c:351 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "არასწორი რეჟიმის სიმბოლო: უნდა იყოს ერთ-ერთი სიიდან \"%s\"" -#: utils/adt/acl.c:380 +#: utils/adt/acl.c:381 #, c-format msgid "a name must follow the \"/\" sign" msgstr "\"/\" სიმბოლოს სახელი უნდა მოჰყვებოდეს" -#: utils/adt/acl.c:392 +#: utils/adt/acl.c:393 #, c-format msgid "defaulting grantor to user ID %u" msgstr "" -#: utils/adt/acl.c:578 +#: utils/adt/acl.c:579 #, c-format msgid "ACL array contains wrong data type" msgstr "ACL-ის მასივი მონაცემების არასწორ ტიპს შეიცავს" -#: utils/adt/acl.c:582 +#: utils/adt/acl.c:583 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "ACL-ის მასივები ერთგანზომილებიანი უნდა იყოს" -#: utils/adt/acl.c:586 +#: utils/adt/acl.c:587 #, c-format msgid "ACL arrays must not contain null values" msgstr "ACL-ის მასივები ნულოვან მნიშვნელობებს არ უნდა შეიცავდეს" -#: utils/adt/acl.c:615 +#: utils/adt/acl.c:616 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "" -#: utils/adt/acl.c:1257 +#: utils/adt/acl.c:1264 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "" -#: utils/adt/acl.c:1573 +#: utils/adt/acl.c:1580 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert მხარდაჭერილი აღარაა" -#: utils/adt/acl.c:1583 +#: utils/adt/acl.c:1590 #, c-format msgid "aclremove is no longer supported" msgstr "aclremove მხარდაჭერილი აღარაა" -#: utils/adt/acl.c:1703 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "პრივილეგიის უცნობი ტიპი \"%s\"" -#: utils/adt/acl.c:3544 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3548 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "ფუნქცია არ არსებობს: \"%s\"" -#: utils/adt/acl.c:5190 +#: utils/adt/acl.c:5330 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "უნდა შეეძლოს SET ROLE \"%s\"" -#: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 +#: utils/adt/array_userfuncs.c:118 utils/adt/array_userfuncs.c:565 utils/adt/array_userfuncs.c:942 utils/adt/json.c:611 utils/adt/json.c:749 utils/adt/json.c:799 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "შეყვანილი მონაცემების ტიპის განსაზღვრა შეუძლებელია" -#: utils/adt/array_userfuncs.c:107 +#: utils/adt/array_userfuncs.c:123 #, c-format msgid "input data type is not an array" msgstr "შემოტანის მონაცემების ტიპი მასივი არაა" -#: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 utils/adt/int.c:1263 -#: utils/adt/int.c:1331 utils/adt/int.c:1337 utils/adt/int8.c:1256 utils/adt/numeric.c:1902 utils/adt/numeric.c:4439 utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 utils/adt/varlena.c:3137 +#: utils/adt/array_userfuncs.c:167 utils/adt/array_userfuncs.c:249 utils/adt/float.c:1229 utils/adt/float.c:1303 utils/adt/float.c:4107 utils/adt/float.c:4145 utils/adt/int.c:778 utils/adt/int.c:800 utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 utils/adt/int.c:1263 +#: utils/adt/int.c:1331 utils/adt/int.c:1337 utils/adt/int8.c:1256 utils/adt/numeric.c:2039 utils/adt/numeric.c:4557 utils/adt/rangetypes.c:1552 utils/adt/rangetypes.c:1565 utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1143 utils/adt/varlena.c:3184 utils/adt/varlena.c:4118 #, c-format msgid "integer out of range" msgstr "მთელი მნიშვნელობა დიაპაზონს გარეთაა" -#: utils/adt/array_userfuncs.c:158 utils/adt/array_userfuncs.c:213 +#: utils/adt/array_userfuncs.c:174 utils/adt/array_userfuncs.c:259 #, c-format msgid "argument must be empty or one-dimensional array" msgstr "არგუმენტი ცარიელი ან ერთგანზომილებიანი მასივი უნდა იყოს" -#: utils/adt/array_userfuncs.c:295 utils/adt/array_userfuncs.c:334 utils/adt/array_userfuncs.c:371 utils/adt/array_userfuncs.c:400 utils/adt/array_userfuncs.c:428 +#: utils/adt/array_userfuncs.c:371 utils/adt/array_userfuncs.c:410 utils/adt/array_userfuncs.c:447 utils/adt/array_userfuncs.c:476 utils/adt/array_userfuncs.c:504 #, c-format msgid "cannot concatenate incompatible arrays" msgstr "შეუთავსებელი მასივების შერწყმა შეუძლებელია" -#: utils/adt/array_userfuncs.c:296 +#: utils/adt/array_userfuncs.c:372 #, c-format msgid "Arrays with element types %s and %s are not compatible for concatenation." msgstr "%s და %s ტიპის ელემენტების მქონე მასივები შერწყმისთვის თავსებადები არ არიან." -#: utils/adt/array_userfuncs.c:335 +#: utils/adt/array_userfuncs.c:411 #, c-format msgid "Arrays of %d and %d dimensions are not compatible for concatenation." msgstr "" -#: utils/adt/array_userfuncs.c:372 +#: utils/adt/array_userfuncs.c:448 #, c-format msgid "Arrays with differing element dimensions are not compatible for concatenation." msgstr "" -#: utils/adt/array_userfuncs.c:401 utils/adt/array_userfuncs.c:429 +#: utils/adt/array_userfuncs.c:477 utils/adt/array_userfuncs.c:505 #, c-format msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "" -#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 utils/adt/arrayfuncs.c:5609 utils/adt/arrayfuncs.c:5615 +#: utils/adt/array_userfuncs.c:1051 utils/adt/array_userfuncs.c:1059 utils/adt/arrayfuncs.c:5628 utils/adt/arrayfuncs.c:5634 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "სხვადასხვა განსაზღვრების მქონე მასივების შეგროვება შეუძლებელია" -#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 +#: utils/adt/array_userfuncs.c:1348 utils/adt/array_userfuncs.c:1502 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "" -#: utils/adt/array_userfuncs.c:1301 +#: utils/adt/array_userfuncs.c:1377 #, c-format msgid "initial position must not be null" msgstr "საწყისი მდებარეობა ნულოვან ვერ იქნება" -#: utils/adt/array_userfuncs.c:1674 +#: utils/adt/array_userfuncs.c:1750 #, c-format msgid "sample size must be between 0 and %d" msgstr "სემპლის ზომა 0-სა და %d-ს შორის უნდა იყოს" @@ -23954,7 +24948,7 @@ msgstr "" msgid "Missing array dimension value." msgstr "აკლია მასივის განზომილების მნიშვნელობა." -#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2933 utils/adt/arrayfuncs.c:2978 utils/adt/arrayfuncs.c:2993 +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 #, c-format msgid "upper bound cannot be less than lower bound" msgstr "" @@ -23984,7 +24978,7 @@ msgstr "მასივის მოულოდნელი ელემენ msgid "Specified array dimensions do not match array contents." msgstr "მითითებული მასივის ზომები მასივის შემცველობას არ ემთხვევა." -#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2597 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2600 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "მრავალგანზომილებიან მასივებს უნდა ჰქონდეთ ქვე-მასივები იგივე ზომებით." @@ -23994,12 +24988,12 @@ msgstr "მრავალგანზომილებიან მასი msgid "Incorrectly quoted array element." msgstr "არასწორად ციტირებული მასივის ელემენტი." -#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 utils/adt/rangetypes.c:2528 utils/adt/rangetypes.c:2536 utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 #, c-format msgid "Unexpected end of input." msgstr "შეყვანის მოულოდნელი დასასრული." -#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3492 utils/adt/arrayfuncs.c:6099 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3511 utils/adt/arrayfuncs.c:6120 #, c-format msgid "invalid number of dimensions: %d" msgstr "განზომილებების არასწორი რაოდენობა: %d" @@ -24014,7 +25008,7 @@ msgstr "მასივის არასწორი ალმები" msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "" -#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 utils/adt/rangetypes.c:353 utils/cache/lsyscache.c:3098 #, c-format msgid "no binary input function available for type %s" msgstr "" @@ -24024,7 +25018,7 @@ msgstr "" msgid "improper binary format in array element %d" msgstr "" -#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 utils/adt/rangetypes.c:358 utils/cache/lsyscache.c:3131 #, c-format msgid "no binary output function available for type %s" msgstr "" @@ -24034,12 +25028,12 @@ msgstr "" msgid "slices of fixed-length arrays not implemented" msgstr "" -#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 utils/adt/arrayfuncs.c:2908 utils/adt/arrayfuncs.c:6085 utils/adt/arrayfuncs.c:6111 utils/adt/arrayfuncs.c:6122 utils/adt/json.c:1419 utils/adt/json.c:1491 utils/adt/jsonb.c:1317 utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4688 utils/adt/jsonfuncs.c:4841 utils/adt/jsonfuncs.c:4952 utils/adt/jsonfuncs.c:5000 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6106 utils/adt/arrayfuncs.c:6132 utils/adt/arrayfuncs.c:6143 utils/adt/json.c:1441 utils/adt/json.c:1509 utils/adt/jsonb.c:1317 utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4734 utils/adt/jsonfuncs.c:4887 utils/adt/jsonfuncs.c:4998 utils/adt/jsonfuncs.c:5046 #, c-format msgid "wrong number of array subscripts" msgstr "მასივის ქვესკრიპტების არასწორი რაოდენობა" -#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2983 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "მასივის ინდექსი დიაპაზონს გარეთაა" @@ -24064,92 +25058,92 @@ msgstr "" msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified." msgstr "" -#: utils/adt/arrayfuncs.c:2898 utils/adt/arrayfuncs.c:3010 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "საწყისი მასივი ძალიან პატარაა" -#: utils/adt/arrayfuncs.c:3650 +#: utils/adt/arrayfuncs.c:3669 #, c-format msgid "null array element not allowed in this context" msgstr "ნულოვანი მასივის ელემენტი ამ კონტექსტში დაშვებული არაა" -#: utils/adt/arrayfuncs.c:3821 utils/adt/arrayfuncs.c:3992 utils/adt/arrayfuncs.c:4383 +#: utils/adt/arrayfuncs.c:3840 utils/adt/arrayfuncs.c:4011 utils/adt/arrayfuncs.c:4402 #, c-format msgid "cannot compare arrays of different element types" msgstr "განსხვავებული ელემენტის ტიპების მქონე მასივების შედარება შეუძლებელია" -#: utils/adt/arrayfuncs.c:4170 utils/adt/multirangetypes.c:2805 utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 +#: utils/adt/arrayfuncs.c:4189 utils/adt/multirangetypes.c:2805 utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1425 utils/adt/rangetypes.c:1489 utils/adt/rowtypes.c:1893 #, c-format msgid "could not identify a hash function for type %s" msgstr "ტიპისთვის \"%s\" ჰეშის ფუნქცია ვერ ვიპოვე" -#: utils/adt/arrayfuncs.c:4298 utils/adt/rowtypes.c:1996 +#: utils/adt/arrayfuncs.c:4317 utils/adt/rowtypes.c:2014 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "ტიპისთვის \"%s\" გაფართოებული ჰეშის ფუნქცია ვერ ვიპოვე" -#: utils/adt/arrayfuncs.c:5499 +#: utils/adt/arrayfuncs.c:5518 #, c-format msgid "data type %s is not an array type" msgstr "მონაცემის ტიპი %s მასივის ტიპი არაა" -#: utils/adt/arrayfuncs.c:5554 +#: utils/adt/arrayfuncs.c:5573 #, c-format msgid "cannot accumulate null arrays" msgstr "ნულოვანი მასივების დაგროვება შეუძლებელია" -#: utils/adt/arrayfuncs.c:5582 +#: utils/adt/arrayfuncs.c:5601 #, c-format msgid "cannot accumulate empty arrays" msgstr "ცარიელი მასივების დაგროვება შეუძლებელია" -#: utils/adt/arrayfuncs.c:5983 utils/adt/arrayfuncs.c:6023 +#: utils/adt/arrayfuncs.c:6004 utils/adt/arrayfuncs.c:6044 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "" -#: utils/adt/arrayfuncs.c:6086 utils/adt/arrayfuncs.c:6112 +#: utils/adt/arrayfuncs.c:6107 utils/adt/arrayfuncs.c:6133 #, c-format msgid "Dimension array must be one dimensional." msgstr "განზომილების მასივი ერთგანზომილებიანი უნდა იყოს." -#: utils/adt/arrayfuncs.c:6091 utils/adt/arrayfuncs.c:6117 +#: utils/adt/arrayfuncs.c:6112 utils/adt/arrayfuncs.c:6138 #, c-format msgid "dimension values cannot be null" msgstr "განზომილების მნიშვნელობები ნულოვანი ვერ იქნება" -#: utils/adt/arrayfuncs.c:6123 +#: utils/adt/arrayfuncs.c:6144 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "" -#: utils/adt/arrayfuncs.c:6404 +#: utils/adt/arrayfuncs.c:6425 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "" -#: utils/adt/arrayfuncs.c:6681 +#: utils/adt/arrayfuncs.c:6702 #, c-format msgid "thresholds must be one-dimensional array" msgstr "" -#: utils/adt/arrayfuncs.c:6686 +#: utils/adt/arrayfuncs.c:6707 #, c-format msgid "thresholds array must not contain NULLs" msgstr "" -#: utils/adt/arrayfuncs.c:6919 +#: utils/adt/arrayfuncs.c:6940 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "" -#: utils/adt/arraysubs.c:93 utils/adt/arraysubs.c:130 +#: utils/adt/arraysubs.c:94 utils/adt/arraysubs.c:131 #, c-format msgid "array subscript must have type integer" msgstr "მასივის ქვესკრიპტის ტიპი integer უნდა ჰქონდეს" -#: utils/adt/arraysubs.c:198 utils/adt/arraysubs.c:217 +#: utils/adt/arraysubs.c:199 utils/adt/arraysubs.c:218 #, c-format msgid "array subscript in assignment must not be null" msgstr "" @@ -24180,24 +25174,29 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:149 utils/adt/cash.c:277 utils/adt/datetime.c:4142 utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 utils/adt/geo_ops.c:4672 utils/adt/int.c:174 -#: utils/adt/int.c:186 utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 utils/adt/network.c:99 utils/adt/numeric.c:796 utils/adt/numeric.c:7206 utils/adt/numeric.c:7409 utils/adt/numeric.c:8356 utils/adt/numutils.c:356 utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 utils/adt/tid.c:94 -#: utils/adt/tid.c:103 utils/adt/timestamp.c:510 utils/adt/uuid.c:140 utils/adt/xid8funcs.c:360 +#: utils/adt/bool.c:150 utils/adt/cash.c:354 utils/adt/datetime.c:4258 utils/adt/float.c:207 utils/adt/float.c:294 utils/adt/float.c:308 utils/adt/float.c:413 utils/adt/float.c:496 utils/adt/float.c:510 utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 utils/adt/geo_ops.c:4672 utils/adt/int.c:174 +#: utils/adt/int.c:186 utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 utils/adt/network.c:99 utils/adt/numeric.c:805 utils/adt/numeric.c:7324 utils/adt/numeric.c:7527 utils/adt/numeric.c:8474 utils/adt/numutils.c:356 utils/adt/numutils.c:617 utils/adt/numutils.c:878 utils/adt/numutils.c:917 utils/adt/numutils.c:939 utils/adt/numutils.c:1003 utils/adt/numutils.c:1025 utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 utils/adt/tid.c:94 +#: utils/adt/tid.c:103 utils/adt/timestamp.c:512 utils/adt/uuid.c:176 utils/adt/xid8funcs.c:323 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "არასწორი შეყვანის სინტაქსი ტიპისთვის %s: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:350 utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "" +msgid "money out of range" +msgstr "ფული შუალედს გარეთაა" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 utils/adt/float.c:99 utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 utils/adt/numeric.c:3176 utils/adt/numeric.c:3199 -#: utils/adt/numeric.c:3284 utils/adt/numeric.c:3302 utils/adt/numeric.c:3398 utils/adt/numeric.c:8905 utils/adt/numeric.c:9218 utils/adt/numeric.c:9566 utils/adt/numeric.c:9682 utils/adt/numeric.c:11192 utils/adt/timestamp.c:3713 +#: utils/adt/cash.c:161 utils/adt/cash.c:725 utils/adt/float.c:106 utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 utils/adt/numeric.c:3294 utils/adt/numeric.c:3317 utils/adt/numeric.c:3402 utils/adt/numeric.c:3420 utils/adt/numeric.c:3516 utils/adt/numeric.c:9399 +#: utils/adt/numeric.c:9923 utils/adt/numeric.c:10039 utils/adt/numeric.c:11550 utils/adt/timestamp.c:3772 #, c-format msgid "division by zero" msgstr "ნულზე გაყოფა" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 utils/adt/numutils.c:611 utils/adt/numutils.c:872 utils/adt/numutils.c:923 utils/adt/numutils.c:962 utils/adt/numutils.c:1009 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -24208,140 +25207,140 @@ msgstr "\"char\" დიაპაზონს გარეთაა" msgid "could not compute %s hash: %s" msgstr "%s ჰეშის გამოთვლა შეუძლებელია: %s" -#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 utils/adt/varchar.c:48 +#: utils/adt/date.c:65 utils/adt/timestamp.c:118 utils/adt/varbit.c:105 utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "ტიპის არასწორი მოდიფიკატორი" -#: utils/adt/date.c:76 +#: utils/adt/date.c:77 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "TIME(%d)%s-ის სიზუსტე უარყოფით არ უნდა იყოს" -#: utils/adt/date.c:82 +#: utils/adt/date.c:83 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "" -#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 utils/adt/formatting.c:4548 +#: utils/adt/date.c:168 utils/adt/date.c:176 utils/adt/formatting.c:4171 utils/adt/formatting.c:4180 utils/adt/formatting.c:4285 utils/adt/formatting.c:4295 #, c-format msgid "date out of range: \"%s\"" msgstr "თარიღი დიაპაზონს გარეთაა: \"%s\"" -#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2489 +#: utils/adt/date.c:223 utils/adt/date.c:585 utils/adt/date.c:609 utils/adt/rangetypes.c:1648 utils/adt/rangetypes.c:1663 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "თარიღი დიაპაზონს გარეთაა" -#: utils/adt/date.c:268 utils/adt/timestamp.c:598 +#: utils/adt/date.c:266 utils/adt/date.c:276 utils/adt/timestamp.c:600 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "მონაცემის ველის მნიშვნელობა დიაპაზონს გარეთაა: %d-%02d-%02d" -#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 +#: utils/adt/date.c:283 utils/adt/date.c:292 utils/adt/timestamp.c:606 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "თარიღი დიაპაზონს გარეთაა: %d-%02d-%02d" -#: utils/adt/date.c:495 +#: utils/adt/date.c:560 #, c-format msgid "cannot subtract infinite dates" msgstr "უსასრულო თარიღების გამოკლება შეუძლებელია" -#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 utils/adt/date.c:2906 utils/adt/date.c:2916 +#: utils/adt/date.c:658 utils/adt/date.c:721 utils/adt/date.c:757 utils/adt/date.c:2971 utils/adt/date.c:2981 #, c-format msgid "date out of range for timestamp" msgstr "თარიღი დროის შტამპის დიაპაზონს მიღმაა" -#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 utils/adt/timestamp.c:6070 +#: utils/adt/date.c:1187 utils/adt/date.c:1270 utils/adt/date.c:1286 utils/adt/date.c:2280 utils/adt/date.c:3076 utils/adt/timestamp.c:4724 utils/adt/timestamp.c:4815 utils/adt/timestamp.c:4963 utils/adt/timestamp.c:5064 utils/adt/timestamp.c:5179 utils/adt/timestamp.c:5231 utils/adt/timestamp.c:5488 utils/adt/timestamp.c:5689 utils/adt/timestamp.c:5736 utils/adt/timestamp.c:5960 utils/adt/timestamp.c:6007 utils/adt/timestamp.c:6088 utils/adt/timestamp.c:6232 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "ერთეული \"%s\" ტიპისთვის %s მხარდაუჭერელია" -#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 +#: utils/adt/date.c:1295 utils/adt/date.c:2296 utils/adt/date.c:3096 utils/adt/timestamp.c:4829 utils/adt/timestamp.c:5081 utils/adt/timestamp.c:5245 utils/adt/timestamp.c:5448 utils/adt/timestamp.c:5745 utils/adt/timestamp.c:6016 utils/adt/timestamp.c:6057 utils/adt/timestamp.c:6293 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "ერთეული \"%s\" ტიპისთვის %s შეუძლებელია" -#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 -#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 utils/adt/timestamp.c:3266 -#: utils/adt/timestamp.c:3279 utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 -#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2511 utils/adt/xml.c:2518 utils/adt/xml.c:2538 utils/adt/xml.c:2545 +#: utils/adt/date.c:1379 utils/adt/date.c:1425 utils/adt/date.c:1984 utils/adt/date.c:2015 utils/adt/date.c:2044 utils/adt/date.c:2934 utils/adt/date.c:3166 utils/adt/datetime.c:432 utils/adt/datetime.c:1817 utils/adt/formatting.c:4016 utils/adt/formatting.c:4052 utils/adt/formatting.c:4139 utils/adt/formatting.c:4261 utils/adt/json.c:375 utils/adt/json.c:414 utils/adt/timestamp.c:250 utils/adt/timestamp.c:282 utils/adt/timestamp.c:707 utils/adt/timestamp.c:716 +#: utils/adt/timestamp.c:794 utils/adt/timestamp.c:827 utils/adt/timestamp.c:3125 utils/adt/timestamp.c:3134 utils/adt/timestamp.c:3151 utils/adt/timestamp.c:3156 utils/adt/timestamp.c:3175 utils/adt/timestamp.c:3188 utils/adt/timestamp.c:3199 utils/adt/timestamp.c:3205 utils/adt/timestamp.c:3211 utils/adt/timestamp.c:3216 utils/adt/timestamp.c:3269 utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3299 utils/adt/timestamp.c:3304 utils/adt/timestamp.c:3325 +#: utils/adt/timestamp.c:3338 utils/adt/timestamp.c:3352 utils/adt/timestamp.c:3360 utils/adt/timestamp.c:3366 utils/adt/timestamp.c:3371 utils/adt/timestamp.c:4439 utils/adt/timestamp.c:4591 utils/adt/timestamp.c:4667 utils/adt/timestamp.c:4733 utils/adt/timestamp.c:4823 utils/adt/timestamp.c:4902 utils/adt/timestamp.c:4972 utils/adt/timestamp.c:5075 utils/adt/timestamp.c:5553 utils/adt/timestamp.c:5827 utils/adt/timestamp.c:6361 utils/adt/timestamp.c:6371 +#: utils/adt/timestamp.c:6376 utils/adt/timestamp.c:6382 utils/adt/timestamp.c:6422 utils/adt/timestamp.c:6509 utils/adt/timestamp.c:6550 utils/adt/timestamp.c:6554 utils/adt/timestamp.c:6608 utils/adt/timestamp.c:6612 utils/adt/timestamp.c:6618 utils/adt/timestamp.c:6659 utils/adt/xml.c:2574 utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "დროის შტამპი დიაპაზონს გარეთაა" -#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 +#: utils/adt/date.c:1601 utils/adt/date.c:2417 utils/adt/formatting.c:4344 #, c-format msgid "time out of range" msgstr "დროის მნიშვნელობა დიაპაზონს გარეთაა" -#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 +#: utils/adt/date.c:1653 utils/adt/timestamp.c:615 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "დროის ველის მნიშვნელობა დიაპაზონს გარეთაა: %d:%02d:%02g" -#: utils/adt/date.c:2020 +#: utils/adt/date.c:2085 #, c-format msgid "cannot convert infinite interval to time" msgstr "უსასრულო ინტერვალის დროში გადაყვანა შეუძლებელია" -#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#: utils/adt/date.c:2126 utils/adt/date.c:2670 #, c-format msgid "cannot add infinite interval to time" msgstr "დროისთვის უსასრულო ინტერვალების დამატება შეუძლებელია" -#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#: utils/adt/date.c:2149 utils/adt/date.c:2697 #, c-format msgid "cannot subtract infinite interval from time" msgstr "დროისთვის უსასრულო ინტერვალების გამოკლება შეუძლებელია" -#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2580 utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 utils/adt/timestamp.c:3888 +#: utils/adt/date.c:2180 utils/adt/date.c:2732 utils/adt/float.c:1043 utils/adt/float.c:1119 utils/adt/int.c:635 utils/adt/int.c:682 utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2698 utils/adt/timestamp.c:3869 utils/adt/timestamp.c:3906 utils/adt/timestamp.c:3947 #, c-format msgid "invalid preceding or following size in window function" msgstr "" -#: utils/adt/date.c:2360 +#: utils/adt/date.c:2425 #, c-format msgid "time zone displacement out of range" msgstr "დროის სარტყლის წანაცვლება დიაპაზონს გარეთაა" -#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#: utils/adt/date.c:3197 utils/adt/timestamp.c:6404 utils/adt/timestamp.c:6641 #, c-format msgid "interval time zone \"%s\" must be finite" msgstr "ინტერვალის დროის სარტყელი \"%s\" სასრული უნდა იყოს" -#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 +#: utils/adt/date.c:3204 utils/adt/timestamp.c:6411 utils/adt/timestamp.c:6648 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "ინტერვალის დროის სარტყელი \"%s\" თვეებს ან დღეებს არ უნდა შეიცავდეს" -#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 +#: utils/adt/datetime.c:3324 utils/adt/datetime.c:4243 utils/adt/datetime.c:4249 utils/adt/timestamp.c:530 #, c-format msgid "time zone \"%s\" not recognized" msgstr "უცნობი დროის სარტყელი: %s" -#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 +#: utils/adt/datetime.c:4217 utils/adt/datetime.c:4224 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "დროის/თარიღის ველის მნიშვნელობა დიაპაზონს გარეთაა: \"%s\"" -#: utils/adt/datetime.c:4110 +#: utils/adt/datetime.c:4226 #, c-format -msgid "Perhaps you need a different \"datestyle\" setting." +msgid "Perhaps you need a different \"DateStyle\" setting." msgstr "" -#: utils/adt/datetime.c:4115 +#: utils/adt/datetime.c:4231 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "ინტერვალის ველის მნიშვნელობა დიაპაზონს გარეთაა: \"%s\"" -#: utils/adt/datetime.c:4121 +#: utils/adt/datetime.c:4237 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "" -#: utils/adt/datetime.c:4135 +#: utils/adt/datetime.c:4251 #, c-format msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"." msgstr "" @@ -24351,17 +25350,22 @@ msgstr "" msgid "invalid Datum pointer" msgstr "არასწორი მაჩვენებელი: Datum" -#: utils/adt/dbsize.c:760 utils/adt/dbsize.c:836 +#: utils/adt/dbsize.c:293 utils/adt/genfile.c:656 +#, c-format +msgid "tablespace with OID %u does not exist" +msgstr "ცხრილების სივრცე OID-ით %u არ არსებობს" + +#: utils/adt/dbsize.c:782 utils/adt/dbsize.c:858 #, c-format msgid "invalid size: \"%s\"" msgstr "არასწორი ზომა: %s" -#: utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:859 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "ერთეულის არასწორი ზომა: \"%s\"." -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:860 #, c-format msgid "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." msgstr "პარამეტრის სწორი ერთეულებია \"ბ\", \"კბ\", \"მბ\", \"გბ\", \"ტბ\" და \"პბ\"." @@ -24386,32 +25390,32 @@ msgstr "დაშიფვრის შედეგი ძალიან დი msgid "result of decoding conversion is too large" msgstr "გაშიფვრის შედეგი ძალიან დიდია" -#: utils/adt/encode.c:217 utils/adt/encode.c:227 +#: utils/adt/encode.c:238 utils/adt/encode.c:248 #, c-format msgid "invalid hexadecimal digit: \"%.*s\"" msgstr "არასწორი თექვსმეტობითი რიცხვი: \"%.*s\"" -#: utils/adt/encode.c:223 +#: utils/adt/encode.c:244 #, c-format msgid "invalid hexadecimal data: odd number of digits" msgstr "არასწორი თექვსმეტობითი მონაცემები: ციფრების კენტი რაოდენობა" -#: utils/adt/encode.c:344 +#: utils/adt/encode.c:365 #, c-format msgid "unexpected \"=\" while decoding base64 sequence" msgstr "base64 მიმდევრობის გაშიფვრისას აღმოჩენილია მოულოდნელი \"=\"" -#: utils/adt/encode.c:356 +#: utils/adt/encode.c:377 #, c-format msgid "invalid symbol \"%.*s\" found while decoding base64 sequence" msgstr "base64 მიმდევრობის გაშიფვრისას აღმოჩენილია არასწორი სიმბოლო \"%.*s\"" -#: utils/adt/encode.c:377 +#: utils/adt/encode.c:398 #, c-format msgid "invalid base64 end sequence" msgstr "base64-ის არასწორი დასრულების მიმდევრობა" -#: utils/adt/encode.c:378 +#: utils/adt/encode.c:399 #, c-format msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "" @@ -24446,335 +25450,355 @@ msgstr "ჩამონათვალის მიმდინარე ტი msgid "enum %s contains no values" msgstr "ჩამონათვალი %s მნიშვნელობებს არ შეიცავს" -#: utils/adt/float.c:83 +#: utils/adt/float.c:90 #, c-format msgid "value out of range: overflow" msgstr "მნიშვნელობა დიაპაზონს გარეთაა: გადავსება" -#: utils/adt/float.c:91 +#: utils/adt/float.c:98 #, c-format msgid "value out of range: underflow" msgstr "მნიშვნელობა დიაპაზონს გარეთაა: არშევსება" -#: utils/adt/float.c:280 +#: utils/adt/float.c:287 #, c-format msgid "\"%s\" is out of range for type real" msgstr "%s დიაპაზონს გარეთაა ტიპისთვის: real" -#: utils/adt/float.c:482 +#: utils/adt/float.c:489 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "%s დიაპაზონს გარეთაა ტიპისთვის: double precision" -#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 utils/adt/int8.c:1277 utils/adt/numeric.c:4578 utils/adt/numeric.c:4583 +#: utils/adt/float.c:1254 utils/adt/float.c:1328 utils/adt/int.c:355 utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 utils/adt/int8.c:1277 utils/adt/numeric.c:4696 utils/adt/numeric.c:4701 utils/adt/varlena.c:4093 #, c-format msgid "smallint out of range" msgstr "smallint დიაპაზონს გარეთაა" -#: utils/adt/float.c:1447 utils/adt/numeric.c:3694 utils/adt/numeric.c:10097 +#: utils/adt/float.c:1454 utils/adt/numeric.c:3812 utils/adt/numeric.c:10454 #, c-format msgid "cannot take square root of a negative number" msgstr "უარყოფითი რიცხვიდან ფესვის ამოღება შეუძლებელია" -#: utils/adt/float.c:1515 utils/adt/numeric.c:3982 utils/adt/numeric.c:4094 +#: utils/adt/float.c:1522 utils/adt/numeric.c:4100 utils/adt/numeric.c:4212 #, c-format msgid "zero raised to a negative power is undefined" msgstr "ნული უარყოფით ხარისხში განუსაზღვრელია" -#: utils/adt/float.c:1519 utils/adt/numeric.c:3986 utils/adt/numeric.c:10988 +#: utils/adt/float.c:1526 utils/adt/numeric.c:4104 utils/adt/numeric.c:11345 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "" -#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3894 utils/adt/numeric.c:10768 +#: utils/adt/float.c:1702 utils/adt/float.c:1735 utils/adt/numeric.c:4012 utils/adt/numeric.c:11125 #, c-format msgid "cannot take logarithm of zero" msgstr "ნულის ლოგარითმის აღება შეუძლებელია" -#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3832 utils/adt/numeric.c:3889 utils/adt/numeric.c:10772 +#: utils/adt/float.c:1706 utils/adt/float.c:1739 utils/adt/numeric.c:3950 utils/adt/numeric.c:4007 utils/adt/numeric.c:11129 #, c-format msgid "cannot take logarithm of a negative number" msgstr "უარყოფითი რიცხვის ლოგარითმის აღება შეუძლებელია" -#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 utils/adt/float.c:2696 utils/adt/float.c:2720 +#: utils/adt/float.c:1772 utils/adt/float.c:1803 utils/adt/float.c:1898 utils/adt/float.c:1925 utils/adt/float.c:1953 utils/adt/float.c:1980 utils/adt/float.c:2127 utils/adt/float.c:2164 utils/adt/float.c:2334 utils/adt/float.c:2390 utils/adt/float.c:2455 utils/adt/float.c:2512 utils/adt/float.c:2703 utils/adt/float.c:2727 #, c-format msgid "input is out of range" msgstr "შეყვანილი მნიშვნელობა დიაპაზონის გარეთაა" -#: utils/adt/float.c:4000 utils/adt/numeric.c:1842 +#: utils/adt/float.c:4085 utils/adt/numeric.c:1979 #, c-format msgid "count must be greater than zero" msgstr "რაოდენობა ნულზე მეტი უნდა იყოს" -#: utils/adt/float.c:4005 utils/adt/numeric.c:1853 +#: utils/adt/float.c:4090 utils/adt/numeric.c:1990 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "" -#: utils/adt/float.c:4011 utils/adt/numeric.c:1858 +#: utils/adt/float.c:4096 utils/adt/numeric.c:1995 #, c-format msgid "lower and upper bounds must be finite" msgstr "ქვედა და ზედა ზღვრები სასრული უნდა ყოს" -#: utils/adt/float.c:4077 utils/adt/numeric.c:1872 +#: utils/adt/float.c:4162 utils/adt/numeric.c:2009 #, c-format msgid "lower bound cannot equal upper bound" msgstr "ქვედა ზღვარი ზედა ზღვარის ტოლი ვერ იქნება" -#: utils/adt/formatting.c:530 +#: utils/adt/formatting.c:556 #, c-format msgid "invalid format specification for an interval value" msgstr "ინტერვალის მნიშვნელობის ფორმატის არასწორი სპეციფიკაცია" -#: utils/adt/formatting.c:531 +#: utils/adt/formatting.c:557 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "" -#: utils/adt/formatting.c:1161 +#: utils/adt/formatting.c:1197 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\" ბოლო გამოყენებული შაბლონი უნდა იყოს" -#: utils/adt/formatting.c:1169 +#: utils/adt/formatting.c:1205 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\" \"PR\"-ზე წინ უნდა იყოს" -#: utils/adt/formatting.c:1185 +#: utils/adt/formatting.c:1221 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\" \"PR\"-ზე წინ უნდა იყოს" -#: utils/adt/formatting.c:1212 +#: utils/adt/formatting.c:1248 #, c-format msgid "multiple decimal points" msgstr "ბევრი ათობითი წერტილი" -#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 +#: utils/adt/formatting.c:1252 utils/adt/formatting.c:1339 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "\"V\"-ს და ათობით წერტილს ერთად ვერ გამოიყენებთ" -#: utils/adt/formatting.c:1228 +#: utils/adt/formatting.c:1264 #, c-format msgid "cannot use \"S\" twice" msgstr "\"S\"-ს ორჯერ ვერ გამოიყენებთ" -#: utils/adt/formatting.c:1232 +#: utils/adt/formatting.c:1268 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "\"S\"-ის და \"PL\"/\"MI\"/\"SG\"/\"PR\"-ის ერთად გამოყენება შეუძლებელია" -#: utils/adt/formatting.c:1252 +#: utils/adt/formatting.c:1288 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "\"S\"-ის და \"MI\"-ის ერთად გამოყენება შეუძლებელია" -#: utils/adt/formatting.c:1262 +#: utils/adt/formatting.c:1298 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "\"S\"-ის და \"PL\"-ის ერთად გამოყენება შეუძლებელია" -#: utils/adt/formatting.c:1272 +#: utils/adt/formatting.c:1308 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "\"S\"-ის და \"SG\"-ის ერთად გამოყენება შეუძლებელია" -#: utils/adt/formatting.c:1281 +#: utils/adt/formatting.c:1317 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "\"PR\"-ის და \"S\"/\"PL\"/\"MI\"/\"SG\"-ის ერთად გამოყენება შეუძლებელია" -#: utils/adt/formatting.c:1307 +#: utils/adt/formatting.c:1326 +#, c-format +msgid "cannot use \"RN\" twice" +msgstr "\"RN\"-ს ორჯერ ვერ გამოიყენებთ" + +#: utils/adt/formatting.c:1347 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "\"EEEE\"-ს ორჯერ ვერ გამოყენებთ" -#: utils/adt/formatting.c:1313 +#: utils/adt/formatting.c:1353 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "\"EEEE\" სხვა ფორმატებთან შეუთავსებელია" -#: utils/adt/formatting.c:1314 +#: utils/adt/formatting.c:1354 #, c-format msgid "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "" -#: utils/adt/formatting.c:1398 +#: utils/adt/formatting.c:1363 +#, c-format +msgid "\"RN\" is incompatible with other formats" +msgstr "\"RN\" სხვა ფორმატებთან შეუთავსებელია" + +#: utils/adt/formatting.c:1364 +#, c-format +msgid "\"RN\" may only be used together with \"FM\"." +msgstr "" + +#: utils/adt/formatting.c:1445 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "თარიღი/დროის არასწორი გამყოფი: \"%s\"" -#: utils/adt/formatting.c:1525 +#: utils/adt/formatting.c:1572 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\" რიცხვი არაა" -#: utils/adt/formatting.c:1603 -#, c-format -msgid "case conversion failed: %s" -msgstr "სიმბოლოების ზომის გარდაქმნის შეცდომა: %s" - -#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 utils/adt/formatting.c:1989 +#: utils/adt/formatting.c:1653 utils/adt/formatting.c:1717 utils/adt/formatting.c:1781 utils/adt/formatting.c:1845 #, c-format msgid "could not determine which collation to use for %s function" msgstr "" -#: utils/adt/formatting.c:2410 +#: utils/adt/formatting.c:1853 +#, c-format +msgid "Unicode case folding can only be performed if server encoding is UTF8" +msgstr "უნიკოდის რეგისტრის მოკეცვა, მხოლოდ, მაშინაა შესაძლებელი, როცა სერვერის კოდირებაა UTF8" + +#: utils/adt/formatting.c:2150 #, c-format msgid "invalid combination of date conventions" msgstr "თარიღის გარდაქმნის არასწორი კომბინაცია" -#: utils/adt/formatting.c:2411 +#: utils/adt/formatting.c:2151 #, c-format msgid "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr "" -#: utils/adt/formatting.c:2433 +#: utils/adt/formatting.c:2173 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "" -#: utils/adt/formatting.c:2435 +#: utils/adt/formatting.c:2175 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "ეს მნიშვნელობა იგივე ველის ტიპისთვის წინა პარამეტრს ეწინააღმდეგება." -#: utils/adt/formatting.c:2502 +#: utils/adt/formatting.c:2242 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "" -#: utils/adt/formatting.c:2504 +#: utils/adt/formatting.c:2244 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "ველს %d სიმბოლო სჭირდება, მაგრამ მხოლოდ %d-ღაა დარჩენილი." -#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 +#: utils/adt/formatting.c:2246 utils/adt/formatting.c:2260 #, c-format msgid "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "" -#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 +#: utils/adt/formatting.c:2256 utils/adt/formatting.c:2269 utils/adt/formatting.c:2490 utils/adt/formatting.c:3390 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "მნიშვნელობა \"%s\" \"%s\"-თვის არასწორია" -#: utils/adt/formatting.c:2518 +#: utils/adt/formatting.c:2258 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "" -#: utils/adt/formatting.c:2531 +#: utils/adt/formatting.c:2271 #, c-format msgid "Value must be an integer." msgstr "მნიშვნელობა მთელი რიცხვი უნდა იყოს." -#: utils/adt/formatting.c:2536 +#: utils/adt/formatting.c:2276 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "საწყის სტრიქონში \"%s\"-ის მნიშვნელობა დიაპაზონს გარეთაა" -#: utils/adt/formatting.c:2538 +#: utils/adt/formatting.c:2278 #, c-format msgid "Value must be in the range %d to %d." msgstr "მნიშვნელობა უნდა იყოს დიაპაზონიდან %d-%d." -#: utils/adt/formatting.c:2752 +#: utils/adt/formatting.c:2492 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "" -#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 +#: utils/adt/formatting.c:2708 utils/adt/formatting.c:2728 utils/adt/formatting.c:2748 utils/adt/formatting.c:2768 utils/adt/formatting.c:2787 utils/adt/formatting.c:2806 utils/adt/formatting.c:2830 utils/adt/formatting.c:2848 utils/adt/formatting.c:2866 utils/adt/formatting.c:2884 utils/adt/formatting.c:2901 utils/adt/formatting.c:2918 #, c-format msgid "localized string format value too long" msgstr "ლოკალიზებული სტრიქონის ფორმატის მნიშვნელობა მეტისმეტად გრძელია" -#: utils/adt/formatting.c:3458 +#: utils/adt/formatting.c:3198 #, c-format msgid "unmatched format separator \"%c\"" msgstr "" -#: utils/adt/formatting.c:3519 +#: utils/adt/formatting.c:3259 #, c-format msgid "unmatched format character \"%s\"" msgstr "" -#: utils/adt/formatting.c:3652 +#: utils/adt/formatting.c:3392 #, c-format msgid "Time zone abbreviation is not recognized." msgstr "დროის სარტყელის აბრევიატურა უცნობია." -#: utils/adt/formatting.c:3853 +#: utils/adt/formatting.c:3593 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "არასწორი შეყვანილი სტრიქონი \"Y,YYY\"-სთვის" -#: utils/adt/formatting.c:3942 +#: utils/adt/formatting.c:3600 +#, c-format +msgid "value for \"Y,YYY\" in source string is out of range" +msgstr "წყარო სტრიქონში \"Y,YYY\"-ის მნიშვნელობები დიაპაზონს გარეთაა" + +#: utils/adt/formatting.c:3689 #, c-format msgid "input string is too short for datetime format" msgstr "შეყვანილი სტრიქონი datetime ფორმატისთვის მეტისმეტად მოკლეა" -#: utils/adt/formatting.c:3950 +#: utils/adt/formatting.c:3697 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "" -#: utils/adt/formatting.c:4494 +#: utils/adt/formatting.c:4241 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "" -#: utils/adt/formatting.c:4500 +#: utils/adt/formatting.c:4247 #, c-format msgid "timestamptz out of range" msgstr "timestamptz დიაპაზონს გარეთაა" -#: utils/adt/formatting.c:4528 +#: utils/adt/formatting.c:4275 #, c-format msgid "datetime format is zoned but not timed" msgstr "" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4324 #, c-format msgid "missing time zone in input string for type timetz" msgstr "" -#: utils/adt/formatting.c:4583 +#: utils/adt/formatting.c:4330 #, c-format msgid "timetz out of range" msgstr "timetz დიაპაზონს გარეთაა" -#: utils/adt/formatting.c:4609 +#: utils/adt/formatting.c:4356 #, c-format msgid "datetime format is not dated and not timed" msgstr "" -#: utils/adt/formatting.c:4786 +#: utils/adt/formatting.c:4533 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "საათი \"%d\" არასწორია 12-საათიანი ათვლისთვის" -#: utils/adt/formatting.c:4788 +#: utils/adt/formatting.c:4535 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "გამოიყენეთ 24-საათიანი ათვლა ან მიუთითეთ საათი დიაპაზონიდან 1-12." -#: utils/adt/formatting.c:4900 +#: utils/adt/formatting.c:4712 #, c-format msgid "cannot calculate day of year without year information" msgstr "წლის დღის გამოთვლა წლის მითითების გარეშე შეუძლებელია" -#: utils/adt/formatting.c:5852 +#: utils/adt/formatting.c:5833 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\" შეყვანისთვის მხარდაჭერილი არაა" -#: utils/adt/formatting.c:5864 +#: utils/adt/formatting.c:6110 #, c-format -msgid "\"RN\" not supported for input" -msgstr "\"RN\" შეყვანისთვის მხარდაჭერილი არაა" +msgid "invalid Roman numeral" +msgstr "არასწორი რომაული რიცხვი" #: utils/adt/genfile.c:84 #, c-format @@ -24786,7 +25810,7 @@ msgstr "აბსოლუტური ბილიკი დაშვებუ msgid "path must be in or below the data directory" msgstr "ბილიკი მონაცემების საქაღალდეში ან უფრო ქვემოთ უნდა იყოს" -#: utils/adt/genfile.c:114 utils/adt/oracle_compat.c:190 utils/adt/oracle_compat.c:288 utils/adt/oracle_compat.c:839 utils/adt/oracle_compat.c:1142 +#: utils/adt/genfile.c:114 utils/adt/oracle_compat.c:206 utils/adt/oracle_compat.c:304 utils/adt/oracle_compat.c:855 utils/adt/oracle_compat.c:1158 #, c-format msgid "requested length too large" msgstr "მოთხოვნილი სიგრძე ძალიან დიდია" @@ -24801,11 +25825,6 @@ msgstr "ფაილში (%s) გადახვევის პრობლ msgid "file length too large" msgstr "ფალის სიგრძე მეტისმეად დიდია" -#: utils/adt/genfile.c:656 -#, c-format -msgid "tablespace with OID %u does not exist" -msgstr "ცხრილების სივრცე OID-ით %u არ არსებობს" - #: utils/adt/geo_ops.c:998 utils/adt/geo_ops.c:1052 #, c-format msgid "invalid line specification: A and B cannot both be zero" @@ -24856,13 +25875,13 @@ msgstr "უნდა მოითხოვოთ სულ ცოტა 2 წე msgid "invalid int2vector data" msgstr "int2vector -ის არასწორი მონაცემები" -#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1750 utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1767 utils/adt/timestamp.c:6708 utils/adt/timestamp.c:6794 #, c-format msgid "step size cannot equal zero" msgstr "ბიჯის ზომა ნულის ტოლი ვერ იქნება" #: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 utils/adt/int8.c:1055 -#: utils/adt/int8.c:1069 utils/adt/int8.c:1100 utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4527 utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 utils/adt/varbit.c:1676 +#: utils/adt/int8.c:1069 utils/adt/int8.c:1100 utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4645 utils/adt/rangetypes.c:1599 utils/adt/rangetypes.c:1612 utils/adt/varbit.c:1676 utils/adt/varlena.c:4143 #, c-format msgid "bigint out of range" msgstr "bigint დიაპაზონს გარეთაა" @@ -24872,48 +25891,48 @@ msgstr "bigint დიაპაზონს გარეთაა" msgid "OID out of range" msgstr "OID დიაპაზონს გარეთაა" -#: utils/adt/json.c:202 utils/adt/jsonb.c:664 +#: utils/adt/json.c:204 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "" -#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 +#: utils/adt/json.c:1043 utils/adt/json.c:1053 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "არგუმენტისთვის %d მონაცემების ტიპის განსაზღვრა შეუძლებელია" -#: utils/adt/json.c:1067 utils/adt/json.c:1259 utils/adt/json.c:1435 utils/adt/json.c:1513 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 +#: utils/adt/json.c:1076 utils/adt/json.c:1275 utils/adt/json.c:1457 utils/adt/json.c:1531 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "ობიექტის გასაღებისთვის ნულოვანი მნიშვნელობა დაშვებული არაა" -#: utils/adt/json.c:1110 utils/adt/json.c:1274 +#: utils/adt/json.c:1126 utils/adt/json.c:1297 #, c-format msgid "duplicate JSON object key value: %s" msgstr "დუბლირებული JSON ობიექტის გასაღების მნიშვნელობა: %s" -#: utils/adt/json.c:1219 utils/adt/jsonb.c:1134 +#: utils/adt/json.c:1235 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "არგუმენტების სიას ლუწი რაოდენობის ელემენტები უნდა ჰქონდეს" #. translator: %s is a SQL function name -#: utils/adt/json.c:1221 utils/adt/jsonb.c:1136 +#: utils/adt/json.c:1237 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "%s-ის არგუმენტები პარამეტრებისა და მნიშვნელობების მონაცვლეობით სიას უნდა წარმოადგენდეს." -#: utils/adt/json.c:1413 utils/adt/jsonb.c:1311 +#: utils/adt/json.c:1435 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "მასივს ორი სვეტი უნდა ჰქონდეს" -#: utils/adt/json.c:1502 utils/adt/jsonb.c:1412 +#: utils/adt/json.c:1520 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "მასივის ზომები არ ემთხვევა" -#: utils/adt/json.c:1688 utils/adt/jsonb_util.c:1956 +#: utils/adt/json.c:1850 utils/adt/jsonb_util.c:1963 #, c-format msgid "duplicate JSON object key value" msgstr "დუბლირებული JSON ობიექტის გასაღების მნიშვნელობა" @@ -24978,22 +25997,22 @@ msgstr "jsonb ობიექტის %s-ის ტიპში გადაყ msgid "cannot cast jsonb array or object to type %s" msgstr "jsonb ობიექტის ან მასივის %s-ის ტიპში გადაყვანა შეუძლებელია" -#: utils/adt/jsonb_util.c:756 +#: utils/adt/jsonb_util.c:763 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "" -#: utils/adt/jsonb_util.c:797 +#: utils/adt/jsonb_util.c:804 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "" -#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 +#: utils/adt/jsonb_util.c:1678 utils/adt/jsonb_util.c:1698 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "jsonb მასივის ელემენტების სრული ზომება მაქსიმუმ დასაშვებზე (%d ბაიტი) დიდია" -#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 utils/adt/jsonb_util.c:1807 +#: utils/adt/jsonb_util.c:1759 utils/adt/jsonb_util.c:1794 utils/adt/jsonb_util.c:1814 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "" @@ -25028,204 +26047,204 @@ msgstr "jsonb ქვესკრიპტს ტექსტური ტიპ msgid "jsonb subscript in assignment must not be null" msgstr "" -#: utils/adt/jsonfuncs.c:582 utils/adt/jsonfuncs.c:829 utils/adt/jsonfuncs.c:2438 utils/adt/jsonfuncs.c:3013 utils/adt/jsonfuncs.c:3926 utils/adt/jsonfuncs.c:4273 +#: utils/adt/jsonfuncs.c:585 utils/adt/jsonfuncs.c:832 utils/adt/jsonfuncs.c:2441 utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3950 utils/adt/jsonfuncs.c:4297 #, c-format msgid "cannot call %s on a scalar" msgstr "%s-ის გამოძახება სკალარზე შეუძლებელია" -#: utils/adt/jsonfuncs.c:587 utils/adt/jsonfuncs.c:814 utils/adt/jsonfuncs.c:3015 utils/adt/jsonfuncs.c:3913 +#: utils/adt/jsonfuncs.c:590 utils/adt/jsonfuncs.c:817 utils/adt/jsonfuncs.c:3019 utils/adt/jsonfuncs.c:3937 #, c-format msgid "cannot call %s on an array" msgstr "%s-ის გამოძახება მასივზე შეუძლებელია" -#: utils/adt/jsonfuncs.c:723 +#: utils/adt/jsonfuncs.c:726 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "JSON მონაცემი, ხაზი %d: %s%s%s" -#: utils/adt/jsonfuncs.c:1882 utils/adt/jsonfuncs.c:1919 +#: utils/adt/jsonfuncs.c:1885 utils/adt/jsonfuncs.c:1922 #, c-format msgid "cannot get array length of a scalar" msgstr "სკალარის მასივის სიგრძის მიღება შეუძლებელია" -#: utils/adt/jsonfuncs.c:1886 utils/adt/jsonfuncs.c:1905 +#: utils/adt/jsonfuncs.c:1889 utils/adt/jsonfuncs.c:1908 #, c-format msgid "cannot get array length of a non-array" msgstr "არა-მასივის მასივის სიგრძის მიღება შეუძლებელია" -#: utils/adt/jsonfuncs.c:1985 +#: utils/adt/jsonfuncs.c:1988 #, c-format msgid "cannot call %s on a non-object" msgstr "არა-ობიექტზე %s-ის გამოძახება შეუძლებელია" -#: utils/adt/jsonfuncs.c:2173 +#: utils/adt/jsonfuncs.c:2176 #, c-format msgid "cannot deconstruct an array as an object" msgstr "მასივის დეკონსტრუქცია ობიექტად შეუძლებელია" -#: utils/adt/jsonfuncs.c:2187 +#: utils/adt/jsonfuncs.c:2190 #, c-format msgid "cannot deconstruct a scalar" msgstr "სკალარის დეკონსტრუქცია შეუძლებელია" -#: utils/adt/jsonfuncs.c:2232 +#: utils/adt/jsonfuncs.c:2235 #, c-format msgid "cannot extract elements from a scalar" msgstr "სკალარიდან ელემენტების გამოღება შეუძლებელია" -#: utils/adt/jsonfuncs.c:2236 +#: utils/adt/jsonfuncs.c:2239 #, c-format msgid "cannot extract elements from an object" msgstr "ობიექტიდან ელემენტების გამოღება შეუძლებელია" -#: utils/adt/jsonfuncs.c:2423 utils/adt/jsonfuncs.c:4151 +#: utils/adt/jsonfuncs.c:2426 utils/adt/jsonfuncs.c:4175 #, c-format msgid "cannot call %s on a non-array" msgstr "არა-მასივზე %s-ს ვერ გამოიძახებთ" -#: utils/adt/jsonfuncs.c:2514 utils/adt/jsonfuncs.c:2519 utils/adt/jsonfuncs.c:2537 utils/adt/jsonfuncs.c:2543 +#: utils/adt/jsonfuncs.c:2517 utils/adt/jsonfuncs.c:2522 utils/adt/jsonfuncs.c:2540 utils/adt/jsonfuncs.c:2546 #, c-format msgid "expected JSON array" msgstr "მოველოდი JSON მასივს" -#: utils/adt/jsonfuncs.c:2515 +#: utils/adt/jsonfuncs.c:2518 #, c-format msgid "See the value of key \"%s\"." msgstr "იხილეთ მასივის ელემენტი \"%s\"." -#: utils/adt/jsonfuncs.c:2538 +#: utils/adt/jsonfuncs.c:2541 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "იხილეთ მასივის ელემენტი %s გასაღებიდან \"%s\"." -#: utils/adt/jsonfuncs.c:2544 +#: utils/adt/jsonfuncs.c:2547 #, c-format msgid "See the array element %s." msgstr "იხილეთ მასივის ელემენტი %s." -#: utils/adt/jsonfuncs.c:2596 +#: utils/adt/jsonfuncs.c:2599 #, c-format msgid "malformed JSON array" msgstr "დამახინჯებული JSON მასივი" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3625 +#: utils/adt/jsonfuncs.c:3649 #, c-format msgid "first argument of %s must be a row type" msgstr "%s-ის პირველი არგუმენტი მწკრივის ტიპის უნდა იყოს" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3649 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "could not determine row type for result of %s" msgstr "%s-ის შედეგის მწკრივის ტიპის დადგენა შეუძლებელია" -#: utils/adt/jsonfuncs.c:3651 +#: utils/adt/jsonfuncs.c:3675 #, c-format msgid "Provide a non-null record argument, or call the function in the FROM clause using a column definition list." msgstr "" -#: utils/adt/jsonfuncs.c:4037 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4061 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "საჭიროა მატერიალიზებული რეჟიმი, მაგრამ ამ კონტექსტში ეს დაუშვებელია" -#: utils/adt/jsonfuncs.c:4168 utils/adt/jsonfuncs.c:4252 +#: utils/adt/jsonfuncs.c:4192 utils/adt/jsonfuncs.c:4276 #, c-format msgid "argument of %s must be an array of objects" msgstr "%s-ის არგუმენტი ობიექტების მასივს უნდა წარმოადგენდეს" -#: utils/adt/jsonfuncs.c:4201 +#: utils/adt/jsonfuncs.c:4225 #, c-format msgid "cannot call %s on an object" msgstr "%s-ს ობიექტზე ვერ გამოიძახებთ" -#: utils/adt/jsonfuncs.c:4634 utils/adt/jsonfuncs.c:4693 utils/adt/jsonfuncs.c:4773 +#: utils/adt/jsonfuncs.c:4680 utils/adt/jsonfuncs.c:4739 utils/adt/jsonfuncs.c:4819 #, c-format msgid "cannot delete from scalar" msgstr "სკალარიდან წაშლა შეუძლებელია" -#: utils/adt/jsonfuncs.c:4778 +#: utils/adt/jsonfuncs.c:4824 #, c-format msgid "cannot delete from object using integer index" msgstr "ობიექტიდან წაშლა მთელი რიცხვის ინდექსის გამოყენებით შეუძლებელია" -#: utils/adt/jsonfuncs.c:4846 utils/adt/jsonfuncs.c:5005 +#: utils/adt/jsonfuncs.c:4892 utils/adt/jsonfuncs.c:5051 #, c-format msgid "cannot set path in scalar" msgstr "სკალარში ბილიკის დაყენება შეუძლებელია" -#: utils/adt/jsonfuncs.c:4887 utils/adt/jsonfuncs.c:4929 +#: utils/adt/jsonfuncs.c:4933 utils/adt/jsonfuncs.c:4975 #, c-format msgid "null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"" msgstr "" -#: utils/adt/jsonfuncs.c:4900 +#: utils/adt/jsonfuncs.c:4946 #, c-format msgid "JSON value must not be null" msgstr "JSON მნიშვნელობა ნულოვანი ვერ იქნება" -#: utils/adt/jsonfuncs.c:4901 +#: utils/adt/jsonfuncs.c:4947 #, c-format msgid "Exception was raised because null_value_treatment is \"raise_exception\"." msgstr "" -#: utils/adt/jsonfuncs.c:4902 +#: utils/adt/jsonfuncs.c:4948 #, c-format msgid "To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed." msgstr "" -#: utils/adt/jsonfuncs.c:4957 +#: utils/adt/jsonfuncs.c:5003 #, c-format msgid "cannot delete path in scalar" msgstr "სკალარში ბილიკის წაშლა შეუძლებელია" -#: utils/adt/jsonfuncs.c:5171 +#: utils/adt/jsonfuncs.c:5217 #, c-format msgid "path element at position %d is null" msgstr "ბილიკის ელემენტი პოზიციაზე %d ნულოვანია" -#: utils/adt/jsonfuncs.c:5190 utils/adt/jsonfuncs.c:5221 utils/adt/jsonfuncs.c:5294 +#: utils/adt/jsonfuncs.c:5236 utils/adt/jsonfuncs.c:5267 utils/adt/jsonfuncs.c:5340 #, c-format msgid "cannot replace existing key" msgstr "არსებული გასაღების ჩანაცვლება შეუძლებელია" -#: utils/adt/jsonfuncs.c:5191 utils/adt/jsonfuncs.c:5222 +#: utils/adt/jsonfuncs.c:5237 utils/adt/jsonfuncs.c:5268 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "" -#: utils/adt/jsonfuncs.c:5295 +#: utils/adt/jsonfuncs.c:5341 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "" -#: utils/adt/jsonfuncs.c:5399 +#: utils/adt/jsonfuncs.c:5445 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "" -#: utils/adt/jsonfuncs.c:5416 +#: utils/adt/jsonfuncs.c:5462 #, c-format msgid "path element at position %d is out of range: %d" msgstr "" -#: utils/adt/jsonfuncs.c:5568 +#: utils/adt/jsonfuncs.c:5614 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "არასწორი ალმის ტიპი. დაშვებულია მხოლოდ მასივები და სკალარები" -#: utils/adt/jsonfuncs.c:5575 +#: utils/adt/jsonfuncs.c:5621 #, c-format msgid "flag array element is not a string" msgstr "ალმის მასივის ელემენტი სტრიქონი არაა" -#: utils/adt/jsonfuncs.c:5576 utils/adt/jsonfuncs.c:5598 +#: utils/adt/jsonfuncs.c:5622 utils/adt/jsonfuncs.c:5644 #, c-format msgid "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\"." msgstr "" -#: utils/adt/jsonfuncs.c:5596 +#: utils/adt/jsonfuncs.c:5642 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "არასწორი ალამი ალმების მასივში: \"%s\"" @@ -25240,79 +26259,64 @@ msgstr "" msgid "LAST is allowed only in array subscripts" msgstr "" -#: utils/adt/jsonpath_exec.c:490 +#: utils/adt/jsonpath_exec.c:489 #, c-format msgid "single boolean result is expected" msgstr "მოველოდი ერთ ლოგიკურ შედეგს" -#: utils/adt/jsonpath_exec.c:850 +#: utils/adt/jsonpath_exec.c:849 #, c-format msgid "jsonpath wildcard array accessor can only be applied to an array" msgstr "" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:872 #, c-format msgid "jsonpath wildcard member accessor can only be applied to an object" msgstr "" -#: utils/adt/jsonpath_exec.c:922 +#: utils/adt/jsonpath_exec.c:921 #, c-format msgid "jsonpath array subscript is out of bounds" msgstr "" -#: utils/adt/jsonpath_exec.c:979 +#: utils/adt/jsonpath_exec.c:978 #, c-format msgid "jsonpath array accessor can only be applied to an array" msgstr "" -#: utils/adt/jsonpath_exec.c:1043 +#: utils/adt/jsonpath_exec.c:1042 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "JSON ობიექტი არ შეიცავს გასაღებს \"%s\"" -#: utils/adt/jsonpath_exec.c:1055 +#: utils/adt/jsonpath_exec.c:1054 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "" -#: utils/adt/jsonpath_exec.c:1113 +#: utils/adt/jsonpath_exec.c:1112 #, c-format msgid "jsonpath item method .%s() can only be applied to an array" msgstr "" -#: utils/adt/jsonpath_exec.c:1166 utils/adt/jsonpath_exec.c:1192 +#: utils/adt/jsonpath_exec.c:1165 utils/adt/jsonpath_exec.c:1191 utils/adt/jsonpath_exec.c:1279 utils/adt/jsonpath_exec.c:1304 utils/adt/jsonpath_exec.c:1356 utils/adt/jsonpath_exec.c:1376 utils/adt/jsonpath_exec.c:1438 utils/adt/jsonpath_exec.c:1527 utils/adt/jsonpath_exec.c:1560 utils/adt/jsonpath_exec.c:1584 #, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type double precision" -msgstr "არგუმენტი \"%s\" jsonpath-ის ელემენტის მეთოდისთვის .%s() არასწორია ტიპისთვის double precision" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type %s" +msgstr "არგუმენტი \"%s\" jsonpath-ის ელემენტის მეთოდისთვის .%s() არასწორია ტიპისთვის %s" -#: utils/adt/jsonpath_exec.c:1171 utils/adt/jsonpath_exec.c:1197 utils/adt/jsonpath_exec.c:1413 utils/adt/jsonpath_exec.c:1445 +#: utils/adt/jsonpath_exec.c:1170 utils/adt/jsonpath_exec.c:1196 utils/adt/jsonpath_exec.c:1413 utils/adt/jsonpath_exec.c:1445 #, c-format msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" msgstr "" -#: utils/adt/jsonpath_exec.c:1210 utils/adt/jsonpath_exec.c:1312 utils/adt/jsonpath_exec.c:1454 utils/adt/jsonpath_exec.c:1592 +#: utils/adt/jsonpath_exec.c:1209 utils/adt/jsonpath_exec.c:1312 utils/adt/jsonpath_exec.c:1454 utils/adt/jsonpath_exec.c:1592 #, c-format msgid "jsonpath item method .%s() can only be applied to a string or numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:1280 utils/adt/jsonpath_exec.c:1304 -#, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" -msgstr "" - -#: utils/adt/jsonpath_exec.c:1356 utils/adt/jsonpath_exec.c:1376 -#, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" -msgstr "" - #: utils/adt/jsonpath_exec.c:1385 #, c-format -msgid "jsonpath item method .%s() can only be applied to a bool, string, or numeric value" -msgstr "" - -#: utils/adt/jsonpath_exec.c:1438 utils/adt/jsonpath_exec.c:1527 -#, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, or numeric value" msgstr "" #: utils/adt/jsonpath_exec.c:1486 @@ -25325,129 +26329,124 @@ msgstr "" msgid "scale of jsonpath item method .%s() is out of range for type integer" msgstr "" -#: utils/adt/jsonpath_exec.c:1560 utils/adt/jsonpath_exec.c:1584 +#: utils/adt/jsonpath_exec.c:1647 #, c-format -msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type integer" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value" msgstr "" -#: utils/adt/jsonpath_exec.c:1663 -#, c-format -msgid "jsonpath item method .%s() can only be applied to a bool, string, numeric, or datetime value" -msgstr "" - -#: utils/adt/jsonpath_exec.c:2152 +#: utils/adt/jsonpath_exec.c:2136 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:2159 +#: utils/adt/jsonpath_exec.c:2143 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:2227 +#: utils/adt/jsonpath_exec.c:2211 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:2326 +#: utils/adt/jsonpath_exec.c:2310 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:2372 +#: utils/adt/jsonpath_exec.c:2356 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "" -#: utils/adt/jsonpath_exec.c:2465 +#: utils/adt/jsonpath_exec.c:2449 #, c-format msgid "time precision of jsonpath item method .%s() is out of range for type integer" msgstr "" -#: utils/adt/jsonpath_exec.c:2499 utils/adt/jsonpath_exec.c:2505 utils/adt/jsonpath_exec.c:2532 utils/adt/jsonpath_exec.c:2560 utils/adt/jsonpath_exec.c:2613 utils/adt/jsonpath_exec.c:2664 utils/adt/jsonpath_exec.c:2720 +#: utils/adt/jsonpath_exec.c:2483 utils/adt/jsonpath_exec.c:2489 utils/adt/jsonpath_exec.c:2516 utils/adt/jsonpath_exec.c:2544 utils/adt/jsonpath_exec.c:2597 utils/adt/jsonpath_exec.c:2648 utils/adt/jsonpath_exec.c:2719 #, c-format msgid "%s format is not recognized: \"%s\"" msgstr "%s-ის ფორმატი უცნობია: \"%s\"" -#: utils/adt/jsonpath_exec.c:2501 +#: utils/adt/jsonpath_exec.c:2485 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "" -#: utils/adt/jsonpath_exec.c:2694 utils/adt/jsonpath_exec.c:2750 +#: utils/adt/jsonpath_exec.c:2678 utils/adt/jsonpath_exec.c:2759 #, c-format msgid "time precision of jsonpath item method .%s() is invalid" msgstr "" -#: utils/adt/jsonpath_exec.c:2830 +#: utils/adt/jsonpath_exec.c:2839 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "" -#: utils/adt/jsonpath_exec.c:3113 +#: utils/adt/jsonpath_exec.c:3123 #, c-format msgid "could not convert value of type %s to jsonpath" msgstr "%s ტიპის მნიშვნელობის jsonpath-ში გადაყვანა ვერ შევძელი" -#: utils/adt/jsonpath_exec.c:3147 +#: utils/adt/jsonpath_exec.c:3157 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "" -#: utils/adt/jsonpath_exec.c:3200 +#: utils/adt/jsonpath_exec.c:3210 #, c-format msgid "\"vars\" argument is not an object" msgstr "არგუმენტი \"vars\" ობიექტი არაა" -#: utils/adt/jsonpath_exec.c:3201 +#: utils/adt/jsonpath_exec.c:3211 #, c-format msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." msgstr "" -#: utils/adt/jsonpath_exec.c:3464 +#: utils/adt/jsonpath_exec.c:3474 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "" -#: utils/adt/jsonpath_exec.c:3476 +#: utils/adt/jsonpath_exec.c:3486 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "" -#: utils/adt/jsonpath_exec.c:3660 +#: utils/adt/jsonpath_exec.c:3670 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "" -#: utils/adt/jsonpath_exec.c:3662 +#: utils/adt/jsonpath_exec.c:3672 #, c-format msgid "Use *_tz() function for time zone support." msgstr "" -#: utils/adt/jsonpath_exec.c:3956 +#: utils/adt/jsonpath_exec.c:3980 #, c-format -msgid "JSON path expression for column \"%s\" should return single item without wrapper" +msgid "JSON path expression for column \"%s\" must return single item when no wrapper is requested" msgstr "" -#: utils/adt/jsonpath_exec.c:3958 utils/adt/jsonpath_exec.c:3963 +#: utils/adt/jsonpath_exec.c:3982 utils/adt/jsonpath_exec.c:3987 #, c-format -msgid "Use WITH WRAPPER clause to wrap SQL/JSON items into array." +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." msgstr "" -#: utils/adt/jsonpath_exec.c:3962 +#: utils/adt/jsonpath_exec.c:3986 #, c-format -msgid "JSON path expression in JSON_QUERY should return single item without wrapper" +msgid "JSON path expression in JSON_QUERY must return single item when no wrapper is requested" msgstr "" -#: utils/adt/jsonpath_exec.c:4020 utils/adt/jsonpath_exec.c:4044 +#: utils/adt/jsonpath_exec.c:4044 utils/adt/jsonpath_exec.c:4068 #, c-format -msgid "JSON path expression for column \"%s\" should return single scalar item" +msgid "JSON path expression for column \"%s\" must return single scalar item" msgstr "" -#: utils/adt/jsonpath_exec.c:4025 utils/adt/jsonpath_exec.c:4049 +#: utils/adt/jsonpath_exec.c:4049 utils/adt/jsonpath_exec.c:4073 #, c-format -msgid "JSON path expression in JSON_VALUE should return single scalar item" +msgid "JSON path expression in JSON_VALUE must return single scalar item" msgstr "" #: utils/adt/levenshtein.c:132 @@ -25455,42 +26454,42 @@ msgstr "" msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "" -#: utils/adt/like.c:159 +#: utils/adt/like.c:162 #, c-format -msgid "nondeterministic collations are not supported for LIKE" -msgstr "" +msgid "could not determine which collation to use for LIKE" +msgstr "შეუძლებელია დადგება, რომელი კოლაცია გამოვიყენო ოპერატორისთვის LIKE" -#: utils/adt/like.c:188 utils/adt/like_support.c:1023 +#: utils/adt/like.c:193 utils/adt/like_support.c:1019 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "" -#: utils/adt/like.c:200 +#: utils/adt/like.c:202 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "" -#: utils/adt/like_match.c:108 utils/adt/like_match.c:168 +#: utils/adt/like_match.c:107 utils/adt/like_match.c:169 utils/adt/like_match.c:237 #, c-format msgid "LIKE pattern must not end with escape character" msgstr "" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 +#: utils/adt/like_match.c:437 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "არასწორი სპეციალური სიმბოლო" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:438 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "" -#: utils/adt/like_support.c:1013 +#: utils/adt/like_support.c:1009 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "" -#: utils/adt/like_support.c:1114 +#: utils/adt/like_support.c:1106 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "" @@ -25510,11 +26509,16 @@ msgstr "" msgid "Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr." msgstr "" -#: utils/adt/mcxtfuncs.c:173 +#: utils/adt/mcxtfuncs.c:305 utils/adt/mcxtfuncs.c:391 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "პროცესი PID-ით %d PostgreSQL-ის სერვერის პროცესს არ წარმოადგენს" +#: utils/adt/mcxtfuncs.c:480 +#, c-format +msgid "PID %d is no longer a PostgreSQL server process" +msgstr "პროცესი PID-ით %d PostgreSQL-ის სერვერის პროცესს აღარ წარმოადგენს" + #: utils/adt/misc.c:237 #, c-format msgid "global tablespace never has databases" @@ -25624,7 +26628,7 @@ msgstr "cidr-ის არასწორი მნიშვნელობა: msgid "Value has bits set to right of mask." msgstr "" -#: utils/adt/network.c:152 utils/adt/network.c:1184 utils/adt/network.c:1209 utils/adt/network.c:1234 +#: utils/adt/network.c:152 utils/adt/network.c:1149 utils/adt/network.c:1174 utils/adt/network.c:1199 #, c-format msgid "could not format inet value: %m" msgstr "inet-ის მნიშვნელობის ფორმატის შეცდომა: %m" @@ -25652,162 +26656,162 @@ msgstr "არასწორი სიგრძე გარე \"%s\"-ის msgid "invalid external \"cidr\" value" msgstr "გარე cidr-ს არასწორი მნიშვნელობა" -#: utils/adt/network.c:336 utils/adt/network.c:359 +#: utils/adt/network.c:334 utils/adt/network.c:357 #, c-format msgid "invalid mask length: %d" msgstr "ნიღბის არასწორი სიგრძე: %d" -#: utils/adt/network.c:1252 +#: utils/adt/network.c:1217 #, c-format msgid "could not format cidr value: %m" msgstr "cird-ის მნიშვნელობის ფორმატის შეცდომა: %m" -#: utils/adt/network.c:1485 +#: utils/adt/network.c:1450 #, c-format msgid "cannot merge addresses from different families" msgstr "სხვადასხვა ოჯახის მისამართების შერწყმა შეუძლებელია" -#: utils/adt/network.c:1893 +#: utils/adt/network.c:1858 #, c-format msgid "cannot AND inet values of different sizes" msgstr "განსხვავებული ზომის მქონე inet-ის მნიშვნელობების AND შეუძლებელია" -#: utils/adt/network.c:1925 +#: utils/adt/network.c:1890 #, c-format msgid "cannot OR inet values of different sizes" msgstr "განსხვავებული ზომის მქონე inet-ის მნიშვნელობების OR შეუძლებელია" -#: utils/adt/network.c:1986 utils/adt/network.c:2062 +#: utils/adt/network.c:1951 utils/adt/network.c:2027 #, c-format msgid "result is out of range" msgstr "შედეგი დიაპაზონს გარეთაა" -#: utils/adt/network.c:2027 +#: utils/adt/network.c:1992 #, c-format msgid "cannot subtract inet values of different sizes" msgstr "" -#: utils/adt/numeric.c:786 utils/adt/numeric.c:3644 utils/adt/numeric.c:7201 utils/adt/numeric.c:7404 utils/adt/numeric.c:7876 utils/adt/numeric.c:10571 utils/adt/numeric.c:11045 utils/adt/numeric.c:11139 utils/adt/numeric.c:11273 +#: utils/adt/numeric.c:795 utils/adt/numeric.c:3762 utils/adt/numeric.c:7319 utils/adt/numeric.c:7522 utils/adt/numeric.c:7994 utils/adt/numeric.c:10928 utils/adt/numeric.c:11403 utils/adt/numeric.c:11497 utils/adt/numeric.c:11632 #, c-format msgid "value overflows numeric format" msgstr "მნიშვნელობა გადაავსებს რიცხვის ფორმატს" -#: utils/adt/numeric.c:1099 +#: utils/adt/numeric.c:1108 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "" -#: utils/adt/numeric.c:1105 +#: utils/adt/numeric.c:1114 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "" -#: utils/adt/numeric.c:1114 +#: utils/adt/numeric.c:1123 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "" -#: utils/adt/numeric.c:1329 utils/adt/numeric.c:1343 +#: utils/adt/numeric.c:1338 utils/adt/numeric.c:1352 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "" -#: utils/adt/numeric.c:1334 +#: utils/adt/numeric.c:1343 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "" -#: utils/adt/numeric.c:1352 +#: utils/adt/numeric.c:1361 #, c-format msgid "invalid NUMERIC type modifier" msgstr "არასწორი NUMERIC ტიპის მოდიფიკატორი" -#: utils/adt/numeric.c:1710 +#: utils/adt/numeric.c:1727 #, c-format msgid "start value cannot be NaN" msgstr "საწყისი მნიშვნელობა NaN ვერ იქნება" -#: utils/adt/numeric.c:1714 +#: utils/adt/numeric.c:1731 #, c-format msgid "start value cannot be infinity" msgstr "საწყისი მნიშვნელობა უსასრულო ვერ იქნება" -#: utils/adt/numeric.c:1721 +#: utils/adt/numeric.c:1738 #, c-format msgid "stop value cannot be NaN" msgstr "საბოლოო მნიშვნელობა NaN ვერ იქნება" -#: utils/adt/numeric.c:1725 +#: utils/adt/numeric.c:1742 #, c-format msgid "stop value cannot be infinity" msgstr "საბოლოო მნიშვნელობა უსასრულო ვერ იქნება" -#: utils/adt/numeric.c:1738 +#: utils/adt/numeric.c:1755 #, c-format msgid "step size cannot be NaN" msgstr "ბიჯის ზომა NaN ვერ იქნება" -#: utils/adt/numeric.c:1742 +#: utils/adt/numeric.c:1759 #, c-format msgid "step size cannot be infinity" msgstr "ბიჯის ზომა უსასრულო ვერ იქნება" -#: utils/adt/numeric.c:3634 +#: utils/adt/numeric.c:3752 #, c-format msgid "factorial of a negative number is undefined" msgstr "უასრყოფითი რიცხვის ფაქტორიალი გაურკვეველია" -#: utils/adt/numeric.c:4241 +#: utils/adt/numeric.c:4359 #, c-format msgid "lower bound cannot be NaN" msgstr "ქვედა ზღვარი ნულოვანი ვერ იქნება" -#: utils/adt/numeric.c:4245 +#: utils/adt/numeric.c:4363 #, c-format msgid "lower bound cannot be infinity" msgstr "ქვედა ზღვარი უსასრულობა ვერ იქნება" -#: utils/adt/numeric.c:4252 +#: utils/adt/numeric.c:4370 #, c-format msgid "upper bound cannot be NaN" msgstr "ზედა ზღვარი ნულოვანი ვერ იქნება" -#: utils/adt/numeric.c:4256 +#: utils/adt/numeric.c:4374 #, c-format msgid "upper bound cannot be infinity" msgstr "ზედა ზღვარი უსასრულობა ვერ იქნება" -#: utils/adt/numeric.c:4417 utils/adt/numeric.c:4505 utils/adt/numeric.c:4565 utils/adt/numeric.c:4761 +#: utils/adt/numeric.c:4535 utils/adt/numeric.c:4623 utils/adt/numeric.c:4683 utils/adt/numeric.c:4879 #, c-format msgid "cannot convert NaN to %s" msgstr "\"NaN\"-ის %s-ში გადაყვანა შეუძლებელია" -#: utils/adt/numeric.c:4421 utils/adt/numeric.c:4509 utils/adt/numeric.c:4569 utils/adt/numeric.c:4765 +#: utils/adt/numeric.c:4539 utils/adt/numeric.c:4627 utils/adt/numeric.c:4687 utils/adt/numeric.c:4883 #, c-format msgid "cannot convert infinity to %s" msgstr "უსასრულობის %s-ში გადაყვანა შეუძლებელია" -#: utils/adt/numeric.c:4774 +#: utils/adt/numeric.c:4892 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn დიაპაზონს გარეთაა" -#: utils/adt/numeric.c:7966 utils/adt/numeric.c:8017 +#: utils/adt/numeric.c:8084 utils/adt/numeric.c:8135 #, c-format msgid "numeric field overflow" msgstr "რიცხვითი ველის გადავსება" -#: utils/adt/numeric.c:7967 +#: utils/adt/numeric.c:8085 #, c-format msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d." msgstr "" -#: utils/adt/numeric.c:8018 +#: utils/adt/numeric.c:8136 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "" -#: utils/adt/numeric.c:11342 utils/adt/pseudorandomfuncs.c:135 utils/adt/pseudorandomfuncs.c:159 +#: utils/adt/numeric.c:11701 utils/adt/pseudorandomfuncs.c:135 utils/adt/pseudorandomfuncs.c:159 #, c-format msgid "lower bound must be less than or equal to upper bound" msgstr "ქვედა ზღვარი ზედა ზღვარზე ნაკლები ან ტოლი უნდა იყოს" @@ -25817,27 +26821,27 @@ msgstr "ქვედა ზღვარი ზედა ზღვარზე msgid "invalid oidvector data" msgstr "oidvevtor-ის არასწორი მონაცემები" -#: utils/adt/oracle_compat.c:976 +#: utils/adt/oracle_compat.c:992 #, c-format msgid "requested character too large" msgstr "მოთხოვნილი სიმბოლო ძალიან დიდია" -#: utils/adt/oracle_compat.c:1020 +#: utils/adt/oracle_compat.c:1036 #, c-format msgid "character number must be positive" msgstr "cost დადებით უნდა იყოს" -#: utils/adt/oracle_compat.c:1024 +#: utils/adt/oracle_compat.c:1040 #, c-format msgid "null character not permitted" msgstr "ნულოვანი სიმბოლო ადუშვებელია" -#: utils/adt/oracle_compat.c:1042 utils/adt/oracle_compat.c:1095 +#: utils/adt/oracle_compat.c:1058 utils/adt/oracle_compat.c:1111 #, c-format msgid "requested character too large for encoding: %u" msgstr "მოთხოვნილი სიმბოლო ძალიან დიდია კოდირებისთვის: %u" -#: utils/adt/oracle_compat.c:1083 +#: utils/adt/oracle_compat.c:1099 #, c-format msgid "requested character not valid for encoding: %u" msgstr "მოთხოვნილი სიმბოლო არასწორია კოდირებისთვის: %u" @@ -25847,137 +26851,147 @@ msgstr "მოთხოვნილი სიმბოლო არასწო msgid "percentile value %g is not between 0 and 1" msgstr "" -#: utils/adt/pg_locale.c:1484 -#, c-format -msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" -msgstr "ლოკალისთვის \"%s\" წესებით \"%s\" კოლატორის გახსნის შეცდომა: %s" - -#: utils/adt/pg_locale.c:1495 utils/adt/pg_locale.c:2969 utils/adt/pg_locale.c:3042 -#, c-format -msgid "ICU is not supported in this build" -msgstr "ამ აგებაში ICU-ის მხარდაჭერა არ არსებბს" - -#: utils/adt/pg_locale.c:1523 +#: utils/adt/pg_locale.c:303 utils/adt/pg_locale.c:335 #, c-format -msgid "could not create locale \"%s\": %m" -msgstr "ლოკალის \"%s\" შექმნა შეუძლებელია: %m" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "ლოკალის სახელი \"%s\" არა-ASCII სიმბოლოებს შეიცავს" -#: utils/adt/pg_locale.c:1526 -#, c-format -msgid "The operating system could not find any locale data for the locale name \"%s\"." -msgstr "" - -#: utils/adt/pg_locale.c:1647 -#, c-format -msgid "collations with different collate and ctype values are not supported on this platform" -msgstr "" - -#: utils/adt/pg_locale.c:1694 +#: utils/adt/pg_locale.c:1119 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "" -#: utils/adt/pg_locale.c:1700 +#: utils/adt/pg_locale.c:1125 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "კოლაციის ვერსია არ ემთხვევა: %s" -#: utils/adt/pg_locale.c:1702 +#: utils/adt/pg_locale.c:1127 #, c-format msgid "The collation in the database was created using version %s, but the operating system provides version %s." msgstr "" -#: utils/adt/pg_locale.c:1705 +#: utils/adt/pg_locale.c:1130 #, c-format msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." msgstr "" -#: utils/adt/pg_locale.c:1749 utils/adt/pg_locale.c:2533 utils/adt/pg_locale.c:2558 +#: utils/adt/pg_locale.c:1483 utils/adt/pg_locale.c:1510 utils/adt/pg_locale_builtin.c:186 #, c-format msgid "invalid locale name \"%s\" for builtin provider" msgstr "არასწორი ლოკალის სახელი \"%s\" ჩაშენებული მომწოდებლისთვის" -#: utils/adt/pg_locale.c:1791 +#: utils/adt/pg_locale.c:1575 #, c-format -msgid "could not load locale \"%s\"" -msgstr "ენის ჩატვირთვის შეცდომა: %s" +msgid "could not convert locale name \"%s\" to language tag: %s" +msgstr "მდებარეობის კოდის \"%s\" ენის ჭდეში (%s) გადაყვანის შეცდომა" -#: utils/adt/pg_locale.c:1816 +#: utils/adt/pg_locale.c:1584 utils/adt/pg_locale.c:1659 utils/adt/pg_locale_icu.c:215 #, c-format -msgid "could not get collation version for locale \"%s\": error code %lu" -msgstr "" +msgid "ICU is not supported in this build" +msgstr "ამ აგებაში ICU-ის მხარდაჭერა არ არსებბს" -#: utils/adt/pg_locale.c:1872 utils/adt/pg_locale.c:1885 +#: utils/adt/pg_locale.c:1617 #, c-format -msgid "could not convert string to UTF-16: error code %lu" +msgid "could not get language from ICU locale \"%s\": %s" +msgstr "'ICU' ლოკალიდან \"%s\" ენის მიღების შეცდომა: %s" + +#: utils/adt/pg_locale.c:1619 utils/adt/pg_locale.c:1649 +#, c-format +msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." +msgstr "ICU ლოკალის გადამოწმების გასათიშად პარამეტრი \"%s\" დააყენეთ მნიშვნელობაზე \"%s\"." + +#: utils/adt/pg_locale.c:1647 +#, c-format +msgid "ICU locale \"%s\" has unknown language \"%s\"" +msgstr "ICU ლოკალს \"%s\" გააჩნია უცნობი ენა \"%s\"" + +#: utils/adt/pg_locale_icu.c:264 +#, c-format +msgid "could not get language from locale \"%s\": %s" +msgstr "ლოკალიდან \"%s\" ენის მიღების შეცდომა: %s" + +#: utils/adt/pg_locale_icu.c:286 utils/adt/pg_locale_icu.c:303 +#, c-format +msgid "could not open collator for locale \"%s\": %s" msgstr "" -#: utils/adt/pg_locale.c:1897 +#: utils/adt/pg_locale_icu.c:374 #, c-format -msgid "could not compare Unicode strings: %m" -msgstr "უნიკოდის სტრიქონების შედარება შეუძლებელია: %m" +msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" +msgstr "ლოკალისთვის \"%s\" წესებით \"%s\" კოლატორის გახსნის შეცდომა: %s" -#: utils/adt/pg_locale.c:2071 +#: utils/adt/pg_locale_icu.c:488 #, c-format msgid "collation failed: %s" msgstr "კოლაციის შეცდომა: %s" -#: utils/adt/pg_locale.c:2290 utils/adt/pg_locale.c:2322 +#: utils/adt/pg_locale_icu.c:567 utils/adt/pg_locale_icu.c:831 #, c-format msgid "sort key generation failed: %s" msgstr "დალაგების გასაღების გენერაციის შეცდომა: %s" -#: utils/adt/pg_locale.c:2612 +#: utils/adt/pg_locale_icu.c:641 utils/adt/pg_locale_icu.c:653 utils/adt/pg_locale_icu.c:878 utils/adt/pg_locale_icu.c:899 #, c-format -msgid "could not get language from locale \"%s\": %s" -msgstr "ლოკალიდან \"%s\" ენის მიღების შეცდომა: %s" +msgid "%s failed: %s" +msgstr "%s ვერ მოხერხდა: %s" -#: utils/adt/pg_locale.c:2633 utils/adt/pg_locale.c:2649 +#: utils/adt/pg_locale_icu.c:682 #, c-format -msgid "could not open collator for locale \"%s\": %s" -msgstr "" +msgid "case conversion failed: %s" +msgstr "სიმბოლოების ზომის გარდაქმნის შეცდომა: %s" -#: utils/adt/pg_locale.c:2674 +#: utils/adt/pg_locale_icu.c:851 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "კოდირება \"%s\" ICU-ის მიერ მხარდაჭერილი არაა" -#: utils/adt/pg_locale.c:2681 +#: utils/adt/pg_locale_icu.c:858 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "შეცდომა ICU გარდამქმნელის გახსნისას კოდირებისთვის \"%s\": %s" -#: utils/adt/pg_locale.c:2699 utils/adt/pg_locale.c:2718 utils/adt/pg_locale.c:2774 utils/adt/pg_locale.c:2785 +#: utils/adt/pg_locale_libc.c:553 #, c-format -msgid "%s failed: %s" -msgstr "%s ვერ მოხერხდა: %s" +msgid "collations with different collate and ctype values are not supported on this platform" +msgstr "" -#: utils/adt/pg_locale.c:2960 +#: utils/adt/pg_locale_libc.c:683 #, c-format -msgid "could not convert locale name \"%s\" to language tag: %s" -msgstr "მდებარეობის კოდის \"%s\" ენის ჭდეში (%s) გადაყვანის შეცდომა" +msgid "could not load locale \"%s\"" +msgstr "ენის ჩატვირთვის შეცდომა: %s" -#: utils/adt/pg_locale.c:3001 +#: utils/adt/pg_locale_libc.c:708 #, c-format -msgid "could not get language from ICU locale \"%s\": %s" -msgstr "'ICU' ლოკალიდან \"%s\" ენის მიღების შეცდომა: %s" +msgid "could not get collation version for locale \"%s\": error code %lu" +msgstr "" -#: utils/adt/pg_locale.c:3003 utils/adt/pg_locale.c:3032 +#: utils/adt/pg_locale_libc.c:771 utils/adt/pg_locale_libc.c:784 #, c-format -msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." -msgstr "ICU ლოკალის გადამოწმების გასათიშად პარამეტრი \"%s\" დააყენეთ მნიშვნელობაზე \"%s\"." +msgid "could not convert string to UTF-16: error code %lu" +msgstr "" -#: utils/adt/pg_locale.c:3030 +#: utils/adt/pg_locale_libc.c:793 #, c-format -msgid "ICU locale \"%s\" has unknown language \"%s\"" -msgstr "ICU ლოკალს \"%s\" გააჩნია უცნობი ენა \"%s\"" +msgid "could not compare Unicode strings: %m" +msgstr "უნიკოდის სტრიქონების შედარება შეუძლებელია: %m" -#: utils/adt/pg_locale.c:3181 +#: utils/adt/pg_locale_libc.c:825 +#, c-format +msgid "could not create locale \"%s\": %m" +msgstr "ლოკალის \"%s\" შექმნა შეუძლებელია: %m" + +#: utils/adt/pg_locale_libc.c:828 +#, c-format +msgid "The operating system could not find any locale data for the locale name \"%s\"." +msgstr "" + +#: utils/adt/pg_locale_libc.c:1000 #, c-format msgid "invalid multibyte character for locale" msgstr "არასწორი მრავალბაიტიანი სიმბოლო ლოკალისთვის" -#: utils/adt/pg_locale.c:3182 +#: utils/adt/pg_locale_libc.c:1001 #, c-format msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding." msgstr "" @@ -25992,27 +27006,27 @@ msgstr "pg_lsn-ში NaN-ის დამატება შეუძლებ msgid "cannot subtract NaN from pg_lsn" msgstr "pg_lsn-დან NaN-ის გამოკლება შეუძლებელია" -#: utils/adt/pg_upgrade_support.c:39 +#: utils/adt/pg_upgrade_support.c:38 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "" -#: utils/adt/pgstatfuncs.c:252 +#: utils/adt/pgstatfuncs.c:280 #, c-format msgid "invalid command name: \"%s\"" msgstr "არასწორი ბრძანების სახელი: \"%s\"" -#: utils/adt/pgstatfuncs.c:1739 +#: utils/adt/pgstatfuncs.c:1909 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "მოთხოვნილია უცნობი მთვლელის განულება: %s" -#: utils/adt/pgstatfuncs.c:1740 +#: utils/adt/pgstatfuncs.c:1910 #, c-format msgid "Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"." msgstr "სამიზნე უნდა იყოს ერთ-ერთი სიიდან: \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", ან \"wal\"." -#: utils/adt/pgstatfuncs.c:1822 +#: utils/adt/pgstatfuncs.c:2027 #, c-format msgid "invalid subscription OID %u" msgstr "არასწორი გამოწერის OID %u" @@ -26037,67 +27051,67 @@ msgstr "გარსის ტიპის მნიშვნელობის msgid "cannot display a value of a shell type" msgstr "გარსის ტიპის მნიშვნელობის ჩვენება შეუძლებელია" -#: utils/adt/rangetypes.c:422 +#: utils/adt/rangetypes.c:424 #, c-format msgid "range constructor flags argument must not be null" msgstr "" -#: utils/adt/rangetypes.c:1021 +#: utils/adt/rangetypes.c:1023 #, c-format msgid "result of range difference would not be contiguous" msgstr "" -#: utils/adt/rangetypes.c:1082 +#: utils/adt/rangetypes.c:1084 #, c-format msgid "result of range union would not be contiguous" msgstr "" -#: utils/adt/rangetypes.c:1757 +#: utils/adt/rangetypes.c:1821 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "" -#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 utils/adt/rangetypes.c:2283 +#: utils/adt/rangetypes.c:2320 utils/adt/rangetypes.c:2333 utils/adt/rangetypes.c:2347 #, c-format msgid "invalid range bound flags" msgstr "" -#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 utils/adt/rangetypes.c:2284 +#: utils/adt/rangetypes.c:2321 utils/adt/rangetypes.c:2334 utils/adt/rangetypes.c:2348 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "სწორი მნიშვნელობებია \"[]\", \"[)\", \"(]\" და \"()\"." -#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 utils/adt/rangetypes.c:2470 +#: utils/adt/rangetypes.c:2416 utils/adt/rangetypes.c:2433 utils/adt/rangetypes.c:2448 utils/adt/rangetypes.c:2468 utils/adt/rangetypes.c:2479 utils/adt/rangetypes.c:2526 utils/adt/rangetypes.c:2534 #, c-format msgid "malformed range literal: \"%s\"" msgstr "დიაპაზონის არასწორი სტრიქონი: %s" -#: utils/adt/rangetypes.c:2354 +#: utils/adt/rangetypes.c:2418 #, c-format msgid "Junk after \"empty\" key word." msgstr "ნაგავი საკვანძო სიტყვა \"empty\"-ის შემდეგ." -#: utils/adt/rangetypes.c:2371 +#: utils/adt/rangetypes.c:2435 #, c-format msgid "Missing left parenthesis or bracket." msgstr "აკლია მარცხენა ფრჩხილი ან მრგვალი ფრჩხილი." -#: utils/adt/rangetypes.c:2386 +#: utils/adt/rangetypes.c:2450 #, c-format msgid "Missing comma after lower bound." msgstr "ქვედა ზღვარის შემდეგ მძიმე აკლია." -#: utils/adt/rangetypes.c:2406 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "Too many commas." msgstr "ძალიან ბევრი მძიმე." -#: utils/adt/rangetypes.c:2417 +#: utils/adt/rangetypes.c:2481 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "ნაგავი მარჯვენა ფრჩხილის ან მრგვალი ფრჩხილის შემდეგ." -#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4475 #, c-format msgid "regular expression failed: %s" msgstr "რეგულარული გამოსახულების შეცდომა: %s" @@ -26112,7 +27126,7 @@ msgstr "რეგულარული გამოსახულების msgid "If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly." msgstr "" -#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 utils/adt/regexp.c:1871 utils/misc/guc.c:6776 utils/misc/guc.c:6810 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 utils/adt/regexp.c:1871 utils/misc/guc.c:6818 utils/misc/guc.c:6852 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "არასწორი მნიშვნელობა პარამეტრისთვის \"%s\": %d" @@ -26148,7 +27162,7 @@ msgstr "ერთზე მეტი ფუნქცია სახელწო msgid "more than one operator named %s" msgstr "ერთზე მეტი ოპერატორი, სახელად %s" -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10424 utils/adt/ruleutils.c:10637 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10826 utils/adt/ruleutils.c:11039 #, c-format msgid "too many arguments" msgstr "მეტისმეტად ბევრი არგუმენტი" @@ -26158,7 +27172,7 @@ msgstr "მეტისმეტად ბევრი არგუმენტ msgid "Provide two argument types for operator." msgstr "ოპერატორისთვის ორი არგუმენტის ტიპი მიაწოდეთ." -#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 utils/adt/regproc.c:1815 utils/adt/varlena.c:3481 utils/adt/varlena.c:3486 #, c-format msgid "invalid name syntax" msgstr "სახელის არასწორი სინტაქსი" @@ -26183,77 +27197,92 @@ msgstr "მოველოდი ტიპის სახელს" msgid "improper type name" msgstr "არასწორი ტიპის სახელი" -#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 utils/adt/ri_triggers.c:2601 +#: utils/adt/ri_triggers.c:314 utils/adt/ri_triggers.c:1775 utils/adt/ri_triggers.c:2774 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 +#: utils/adt/ri_triggers.c:317 utils/adt/ri_triggers.c:1778 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "" -#: utils/adt/ri_triggers.c:2036 +#: utils/adt/ri_triggers.c:2192 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "\"INSERT\"-ისთვის საჭიროა %s ფუნქციის გაშვება" -#: utils/adt/ri_triggers.c:2042 +#: utils/adt/ri_triggers.c:2198 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "\"UPDATE\"-ისთვის საჭიროა %s ფუნქციის გაშვება" -#: utils/adt/ri_triggers.c:2048 +#: utils/adt/ri_triggers.c:2204 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "\"DELETE\"-ისთვის საჭიროა %s ფუნქციის გაშვება" -#: utils/adt/ri_triggers.c:2071 +#: utils/adt/ri_triggers.c:2227 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "" -#: utils/adt/ri_triggers.c:2073 +#: utils/adt/ri_triggers.c:2229 #, c-format msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT." msgstr "" -#: utils/adt/ri_triggers.c:2426 +#: utils/adt/ri_triggers.c:2599 #, c-format msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result" msgstr "" -#: utils/adt/ri_triggers.c:2430 +#: utils/adt/ri_triggers.c:2603 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "დიდი შანსია, ეს გამოიწვია წესმა, რომელმაც მოთხოვნა თავიდან დაწერა." -#: utils/adt/ri_triggers.c:2591 +#: utils/adt/ri_triggers.c:2764 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "" -#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 +#: utils/adt/ri_triggers.c:2767 utils/adt/ri_triggers.c:2806 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "" -#: utils/adt/ri_triggers.c:2605 +#: utils/adt/ri_triggers.c:2778 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." -msgstr "" +msgstr "გასაღები (%s)=(%s) არაა წარმოდგენილი ცხრილში \"%s\"." -#: utils/adt/ri_triggers.c:2608 +#: utils/adt/ri_triggers.c:2781 #, c-format msgid "Key is not present in table \"%s\"." msgstr "ცხრილში \"%s\" გასაღები არ არსებობს." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2787 +#, c-format +msgid "update or delete on table \"%s\" violates RESTRICT setting of foreign key constraint \"%s\" on table \"%s\"" +msgstr "" + +#: utils/adt/ri_triggers.c:2792 +#, c-format +msgid "Key (%s)=(%s) is referenced from table \"%s\"." +msgstr "გასაღებს (%s)=(%s) მიმართავენ ცხრილიდან \"%s\"." + +#: utils/adt/ri_triggers.c:2795 +#, c-format +msgid "Key is referenced from table \"%s\"." +msgstr "გასაღებს მიმართავენ ცხრილიდან \"%s\"." + +#: utils/adt/ri_triggers.c:2801 #, c-format msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"" msgstr "" -#: utils/adt/ri_triggers.c:2622 +#: utils/adt/ri_triggers.c:2809 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "" @@ -26303,133 +27332,158 @@ msgstr "" msgid "improper binary format in record column %d" msgstr "" -#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 utils/adt/rowtypes.c:1699 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1471 utils/adt/rowtypes.c:1717 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "" -#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 utils/adt/rowtypes.c:1568 utils/adt/rowtypes.c:1753 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "" -#: utils/adt/ruleutils.c:2693 +#: utils/adt/ruleutils.c:2740 #, c-format msgid "input is a query, not an expression" msgstr "შეყვანა არის მოთხოვნა და არა გამოსახულება" -#: utils/adt/ruleutils.c:2705 +#: utils/adt/ruleutils.c:2752 #, c-format msgid "expression contains variables of more than one relation" msgstr "" -#: utils/adt/ruleutils.c:2712 +#: utils/adt/ruleutils.c:2759 #, c-format msgid "expression contains variables" msgstr "გამოხატულება შეიცავს ცვლადებს" -#: utils/adt/ruleutils.c:5242 +#: utils/adt/ruleutils.c:5433 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "წესს \"%s\" გააჩნია მხარდაუჭერელი მოვლენის ტიპი %d" -#: utils/adt/timestamp.c:128 +#: utils/adt/tid.c:317 +#, c-format +msgid "cannot look at latest visible tid for relation \"%s.%s\"" +msgstr "უკანასკნელ ხილული tid-ზე შეხედვა შეუძლებელია ურთიერთობისთვის \"%s.%s\"" + +#: utils/adt/tid.c:356 +#, c-format +msgid "ctid isn't of type TID" +msgstr "" + +#: utils/adt/tid.c:364 +#, c-format +msgid "currtid cannot handle views with no CTID" +msgstr "" + +#: utils/adt/tid.c:369 +#, c-format +msgid "the view has no rules" +msgstr "" + +#: utils/adt/tid.c:381 +#, c-format +msgid "only one select rule is allowed in views" +msgstr "ხედებში დაშვებულია, მხოლოდ, ერთი select-ის წესი" + +#: utils/adt/timestamp.c:130 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "TIMESTAMP(%d)%s-ის სიზუსტე უარყოფით არ უნდა იყოს" -#: utils/adt/timestamp.c:134 +#: utils/adt/timestamp.c:136 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "" -#: utils/adt/timestamp.c:394 +#: utils/adt/timestamp.c:204 utils/adt/timestamp.c:457 +#, c-format +msgid "timestamp out of range: \"%s\"" +msgstr "დროის შტამპი დიაპაზონს გარეთაა: \"%s\"" + +#: utils/adt/timestamp.c:396 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "" -#: utils/adt/timestamp.c:512 +#: utils/adt/timestamp.c:514 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "" -#: utils/adt/timestamp.c:524 +#: utils/adt/timestamp.c:526 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "რიცხვითი დროის სარტყელი \"%s\" დიაპაზონს გარეთაა" -#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 utils/adt/timestamp.c:643 +#: utils/adt/timestamp.c:626 utils/adt/timestamp.c:634 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "დროის შტამპი დიაპაზონს გარეთაა: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:744 +#: utils/adt/timestamp.c:735 #, c-format msgid "timestamp cannot be NaN" msgstr "დროის შტამპი NaN ვერ იქნება" -#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 +#: utils/adt/timestamp.c:753 utils/adt/timestamp.c:765 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "დროის შტამპი დიაპაზონს გარეთაა: \"%g\"" -#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 utils/adt/timestamp.c:3537 -#: utils/adt/timestamp.c:3546 utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 utils/adt/timestamp.c:5097 +#: utils/adt/timestamp.c:948 utils/adt/timestamp.c:1507 utils/adt/timestamp.c:1517 utils/adt/timestamp.c:1578 utils/adt/timestamp.c:2866 utils/adt/timestamp.c:2875 utils/adt/timestamp.c:2890 utils/adt/timestamp.c:2964 utils/adt/timestamp.c:2981 utils/adt/timestamp.c:3038 utils/adt/timestamp.c:3081 utils/adt/timestamp.c:3459 utils/adt/timestamp.c:3517 utils/adt/timestamp.c:3540 utils/adt/timestamp.c:3549 utils/adt/timestamp.c:3573 utils/adt/timestamp.c:3596 +#: utils/adt/timestamp.c:3605 utils/adt/timestamp.c:3740 utils/adt/timestamp.c:3841 utils/adt/timestamp.c:4248 utils/adt/timestamp.c:4285 utils/adt/timestamp.c:4333 utils/adt/timestamp.c:4342 utils/adt/timestamp.c:4434 utils/adt/timestamp.c:4481 utils/adt/timestamp.c:4490 utils/adt/timestamp.c:4586 utils/adt/timestamp.c:4639 utils/adt/timestamp.c:4649 utils/adt/timestamp.c:4874 utils/adt/timestamp.c:4884 utils/adt/timestamp.c:5239 #, c-format msgid "interval out of range" msgstr "ინტერვალი საზღვრებს გარეთაა" -#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 +#: utils/adt/timestamp.c:1085 utils/adt/timestamp.c:1118 #, c-format msgid "invalid INTERVAL type modifier" msgstr "\"INTERVAL\" ტიპის არასწორი მოდიფიკატორი" -#: utils/adt/timestamp.c:1110 +#: utils/adt/timestamp.c:1101 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d)-ის სიზუსტე უარყოფით არ უნდა იყოს" -#: utils/adt/timestamp.c:1116 +#: utils/adt/timestamp.c:1107 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "" -#: utils/adt/timestamp.c:1506 +#: utils/adt/timestamp.c:1497 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "" -#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 -#, c-format -msgid "interval out of range." -msgstr "ინტერვალი დაშვებული შუალედის გარეთაა." - -#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 +#: utils/adt/timestamp.c:4623 utils/adt/timestamp.c:4858 #, c-format msgid "origin out of range" msgstr "წყარო დიაპაზონს გარეთაა" -#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#: utils/adt/timestamp.c:4628 utils/adt/timestamp.c:4863 #, c-format msgid "timestamps cannot be binned into infinite intervals" msgstr "" -#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 +#: utils/adt/timestamp.c:4633 utils/adt/timestamp.c:4868 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "" -#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 +#: utils/adt/timestamp.c:4644 utils/adt/timestamp.c:4879 #, c-format msgid "stride must be greater than zero" msgstr "ბიჯი ნულზე მეტი უნდა იყოს" -#: utils/adt/timestamp.c:5091 +#: utils/adt/timestamp.c:5181 utils/adt/timestamp.c:5233 #, c-format msgid "Months usually have fractional weeks." msgstr "თვეში როგორც წესი გაყოფადი რაოდენობის კვირებია." -#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#: utils/adt/timestamp.c:6713 utils/adt/timestamp.c:6799 #, c-format msgid "step size cannot be infinite" msgstr "ბიჯის ზომა უსასრულო ვერ იქნება" @@ -26504,32 +27558,32 @@ msgstr "" msgid "ts_rewrite query must return two tsquery columns" msgstr "ts_rewrite მოთხოვნამ ორი tsquery სვეტი უნდა დააბრუნოს" -#: utils/adt/tsrank.c:412 +#: utils/adt/tsrank.c:415 #, c-format msgid "array of weight must be one-dimensional" msgstr "წონის მასივი ერთგანზომილებიანი უნდა იყოს" -#: utils/adt/tsrank.c:417 +#: utils/adt/tsrank.c:420 #, c-format msgid "array of weight is too short" msgstr "წონის მასივი ძალიან მოკლეა" -#: utils/adt/tsrank.c:422 +#: utils/adt/tsrank.c:425 #, c-format msgid "array of weight must not contain nulls" msgstr "წონის მასივი არ შეიძლება, ნულოვან მნიშვნელობებს შეიცავდეს" -#: utils/adt/tsrank.c:431 utils/adt/tsrank.c:871 +#: utils/adt/tsrank.c:434 utils/adt/tsrank.c:876 #, c-format msgid "weight out of range" msgstr "სიმძიმე დიაპაზონს გარეთაა" -#: utils/adt/tsvector.c:216 +#: utils/adt/tsvector.c:213 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "სიტყვა მეტისმეტად მოკლეა (%ld ბაიტი, მაქს %ld ბაიტი)" -#: utils/adt/tsvector.c:223 +#: utils/adt/tsvector.c:220 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "" @@ -26609,7 +27663,7 @@ msgstr "სპეციალური სიმბოლო \"%s\" ვერ msgid "wrong position info in tsvector: \"%s\"" msgstr "" -#: utils/adt/uuid.c:418 +#: utils/adt/uuid.c:535 utils/adt/uuid.c:632 #, c-format msgid "could not generate random values" msgstr "შემთხვევითი რიცხვების გენერაციის შეცდომა" @@ -26654,7 +27708,7 @@ msgstr "გარე ბიტური სტრიქონის არას msgid "bit string too long for type bit varying(%d)" msgstr "" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 utils/adt/varlena.c:3133 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:919 utils/adt/varlena.c:982 utils/adt/varlena.c:1139 utils/adt/varlena.c:3102 utils/adt/varlena.c:3180 #, c-format msgid "negative substring length not allowed" msgstr "ქვესტრიქონის სიგრძე უარყოფითი არ შეიძლება იყოს" @@ -26679,7 +27733,7 @@ msgstr "განსხვავებული სიგრძის სტრ msgid "bit index %d out of valid range (0..%d)" msgstr "" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3384 #, c-format msgid "new bit must be 0 or 1" msgstr "ახალი ბიტი უნდა იყოს 0 ან 1" @@ -26694,92 +27748,92 @@ msgstr "მნიშვნელობა სიმბოლოს ტიპი msgid "value too long for type character varying(%d)" msgstr "" -#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1591 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "" -#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 +#: utils/adt/varlena.c:1864 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "" -#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 +#: utils/adt/varlena.c:3268 utils/adt/varlena.c:3335 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "ინდექსი %d დასაშვებ დიაპაზონს (0..%d) გარეთაა" -#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 +#: utils/adt/varlena.c:3299 utils/adt/varlena.c:3371 #, c-format -msgid "index %lld out of valid range, 0..%lld" -msgstr "ინდექსი %lld დასაშვებ დიაპაზონს (0..%lld) გარეთაა" +msgid "index % out of valid range, 0..%" +msgstr "ინდექსი % დასაშვებ დიაპაზონს (0..%) გარეთაა" -#: utils/adt/varlena.c:4385 +#: utils/adt/varlena.c:4587 #, c-format msgid "field position must not be zero" msgstr "ველის მდებარეობა ნულოვანი ვერ იქნება" -#: utils/adt/varlena.c:5630 +#: utils/adt/varlena.c:5832 #, c-format msgid "unterminated format() type specifier" msgstr "" -#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 +#: utils/adt/varlena.c:5833 utils/adt/varlena.c:5967 utils/adt/varlena.c:6088 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "ერთი \"%%\"-სთვის გამოიყენეთ \"%%%%\"." -#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 +#: utils/adt/varlena.c:5965 utils/adt/varlena.c:6086 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "" -#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 +#: utils/adt/varlena.c:5978 utils/adt/varlena.c:6035 #, c-format msgid "too few arguments for format()" msgstr "format()-ის არგუმენტები საკმარისი არაა" -#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 +#: utils/adt/varlena.c:6131 utils/adt/varlena.c:6313 #, c-format msgid "number is out of range" msgstr "რიცხვი დიაპაზონს გარეთაა" -#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 +#: utils/adt/varlena.c:6194 utils/adt/varlena.c:6222 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "" -#: utils/adt/varlena.c:6013 +#: utils/adt/varlena.c:6215 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "" -#: utils/adt/varlena.c:6058 +#: utils/adt/varlena.c:6260 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "" -#: utils/adt/varlena.c:6266 +#: utils/adt/varlena.c:6468 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "" -#: utils/adt/varlena.c:6279 +#: utils/adt/varlena.c:6481 #, c-format msgid "invalid normalization form: %s" msgstr "ნორმალიზაციის არასწორი ფორმა: %s" -#: utils/adt/varlena.c:6324 +#: utils/adt/varlena.c:6526 #, c-format msgid "Unicode categorization can only be performed if server encoding is UTF8" msgstr "" -#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 +#: utils/adt/varlena.c:6743 utils/adt/varlena.c:6778 utils/adt/varlena.c:6813 #, c-format msgid "invalid Unicode code point: %04X" msgstr "უნიკოდის კოდის არასწორი წერტილი: %04X" -#: utils/adt/varlena.c:6641 +#: utils/adt/varlena.c:6843 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "" @@ -26794,12 +27848,12 @@ msgstr "ntile -ის არგუმენტი ნულზე მეტი msgid "argument of nth_value must be greater than zero" msgstr "nth_value-ის არგუმენტი ნულზე მეტი უნდა იყოს" -#: utils/adt/xid8funcs.c:124 +#: utils/adt/xid8funcs.c:120 #, c-format -msgid "transaction ID %llu is in the future" -msgstr "ტრანზაქციის ID მომავალშია: %llu" +msgid "transaction ID % is in the future" +msgstr "ტრანზაქციის ID მომავალშია: %" -#: utils/adt/xid8funcs.c:553 +#: utils/adt/xid8funcs.c:522 #, c-format msgid "invalid external pg_snapshot data" msgstr "pg_snapshot-ის არასწორი გარე მონაცემები" @@ -26824,161 +27878,166 @@ msgstr "კოდირების არასწორი სახელი: msgid "invalid XML comment" msgstr "არასწორი XML კომენტარი" -#: utils/adt/xml.c:691 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "არ არის XML დოკუმენტი" -#: utils/adt/xml.c:987 utils/adt/xml.c:1010 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "xml-ის დამუშავების არასწორი ინსტრუქცია" -#: utils/adt/xml.c:988 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "" -#: utils/adt/xml.c:1011 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "" -#: utils/adt/xml.c:1090 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "xmlvalidate განხორციელებული არაა" -#: utils/adt/xml.c:1146 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "xml ბიბლიოთეკის ინიციალიზება ვერ მოხერხდა" -#: utils/adt/xml.c:1147 +#: utils/adt/xml.c:1168 #, c-format msgid "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." msgstr "libxml2 აქვს შეუთავსებელი char ტიპის: ზომა (char)=%zu, sizeof(xmlChar)=%zu." -#: utils/adt/xml.c:1233 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "\"XML\" შეცდომების დამმუშავებლის მორგების შეცდომა" -#: utils/adt/xml.c:1234 +#: utils/adt/xml.c:1255 #, c-format msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with." msgstr "" -#: utils/adt/xml.c:2218 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "სტრიქონის არასწორი მნშვნელობა." -#: utils/adt/xml.c:2221 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "საჭიროა გამოტოვება." -#: utils/adt/xml.c:2224 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "standalone-ის მნიშვნელობა შეიძლება იყოს \"yes\"(დიახ) ან \"no\"(არა)." -#: utils/adt/xml.c:2227 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "არასწორი აღწერა: ვერსია მითითებული არაა." -#: utils/adt/xml.c:2230 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "ტექსტის აღწერაში კოდირება მითითებული არაა." -#: utils/adt/xml.c:2233 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "" -#: utils/adt/xml.c:2236 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "Libxml-ის შეცდომის უცნობი კოდი: %d." -#: utils/adt/xml.c:2490 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML-ს უსასრულო თარიღის მნიშვნელობების მხარდაჭერა არ გააჩნია." -#: utils/adt/xml.c:2512 utils/adt/xml.c:2539 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML-ს უსასრულო დროის შტამპის მნიშვნელობების მხარდაჭერა არ გააჩნია." -#: utils/adt/xml.c:2955 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "არასწორი მოთხოვნა" -#: utils/adt/xml.c:3047 +#: utils/adt/xml.c:3110 #, c-format msgid "portal \"%s\" does not return tuples" msgstr "პორტალი \"%s\" კორტეჟებს არ აბრუნებს" -#: utils/adt/xml.c:4299 +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "" -#: utils/adt/xml.c:4300 +#: utils/adt/xml.c:4363 #, c-format msgid "The array must be two-dimensional with length of the second axis equal to 2." msgstr "" -#: utils/adt/xml.c:4324 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "ცარიელი XPath გამოხატულება" -#: utils/adt/xml.c:4376 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "სახელების სივრცის სახელი და URI ნულოვანი არ შეიძლება, იყოს" -#: utils/adt/xml.c:4383 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "" -#: utils/adt/xml.c:4726 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "სახელების სივრცე DEFAULT მხარდაუჭერელია" -#: utils/adt/xml.c:4755 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "მწკრივის ბილიკის ფილტრი ცარიელი სტრიქონი არ შეიძლება იყოს" -#: utils/adt/xml.c:4786 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "სვეტის ბილიკის ფილტრი ცარიელი სტრიქონი არ შეიძლება იყოს" -#: utils/adt/xml.c:4930 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "" -#: utils/cache/lsyscache.c:1017 +#: utils/cache/funccache.c:364 +#, c-format +msgid "could not determine actual argument type for polymorphic function \"%s\"" +msgstr "პოლიმორფული ფუნქციისთვის (%s) მიმდინარე არგუმენტის ტიპის დადგენა შეუძლებელია" + +#: utils/cache/lsyscache.c:1109 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "" -#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 +#: utils/cache/lsyscache.c:3027 utils/cache/lsyscache.c:3060 utils/cache/lsyscache.c:3093 utils/cache/lsyscache.c:3126 #, c-format msgid "type %s is only a shell" msgstr "ტიპი %s ცარიელია" -#: utils/cache/lsyscache.c:2892 +#: utils/cache/lsyscache.c:3032 #, c-format msgid "no input function available for type %s" msgstr "ტიპისთვის %s შეყვანის ფუნქცია არ არ ასებობს" -#: utils/cache/lsyscache.c:2925 +#: utils/cache/lsyscache.c:3065 #, c-format msgid "no output function available for type %s" msgstr "ტიპისთვის %s გამოტანის ფუნქცია არ არ ასებობს" @@ -26988,32 +28047,27 @@ msgstr "ტიპისთვის %s გამოტანის ფუნქ msgid "operator class \"%s\" of access method %s is missing support function %d for type %s" msgstr "" -#: utils/cache/plancache.c:747 -#, c-format -msgid "cached plan must not change result type" -msgstr "დაკეშილი გეგმა შედეგის ტიპს არ უნდა ცვლიდეს" - -#: utils/cache/relcache.c:3797 +#: utils/cache/relcache.c:3805 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "heap relfilenumber-ის მნიშვნელობა ბინარული განახლების დროს დაყენებული არაა" -#: utils/cache/relcache.c:3805 +#: utils/cache/relcache.c:3813 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "ახალი relfilenumber-ის მოულოდნელი მოთხოვნა ბინარული განახლების რეჟიმში" -#: utils/cache/relcache.c:6533 +#: utils/cache/relcache.c:6630 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "" -#: utils/cache/relcache.c:6535 +#: utils/cache/relcache.c:6632 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "მაინც ვაგრძელებ, მაგრამ რაღაც ცუდი ხდება." -#: utils/cache/relcache.c:6865 +#: utils/cache/relcache.c:6962 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "კეშის ფაილის \"%s\" წაშლის შეცდომა: %m" @@ -27033,7 +28087,7 @@ msgstr "ურთიერთობის მიბმის ფაილი \"% msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "ურთიერთობის მიბმის ფაილი \"%s\" არასწორ საკონტროლო ჯამს შეიცავს" -#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 +#: utils/cache/typcache.c:1901 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "ჩანაწერის ტიპი რეგისტრირებული არ არის" @@ -27048,193 +28102,185 @@ msgstr "" msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "ხაფანგი: გამოთხოვის შეცდომა (\"%s\"), ფაილი: \"%s\", ხაზი: %d, PID: %d\n" -#: utils/error/elog.c:415 +#: utils/error/elog.c:412 #, c-format msgid "error occurred before error message processing is available\n" msgstr "აღმოჩენილია შეცდომა მანამდე, სანამ შეცდომის შეტყობინებების დამუშავება ხელმისაწვდომი გახდებოდა\n" -#: utils/error/elog.c:2101 +#: utils/error/elog.c:2159 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "" -#: utils/error/elog.c:2114 +#: utils/error/elog.c:2172 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "" -#: utils/error/elog.c:2150 +#: utils/error/elog.c:2208 #, c-format -msgid "Invalid character" -msgstr "არასწორი სიმბოლო" +msgid "Invalid character." +msgstr "არასწორი სიმბოლო." -#: utils/error/elog.c:2856 utils/error/elog.c:2883 utils/error/elog.c:2899 +#: utils/error/elog.c:2918 utils/error/elog.c:2945 utils/error/elog.c:2961 msgid "[unknown]" msgstr "[უცნობი]" -#: utils/error/elog.c:3169 utils/error/elog.c:3493 utils/error/elog.c:3600 +#: utils/error/elog.c:3263 utils/error/elog.c:3587 utils/error/elog.c:3694 msgid "missing error text" msgstr "შეცდომის ტექსტი ხელმიუწვდომელია" -#: utils/error/elog.c:3172 utils/error/elog.c:3175 +#: utils/error/elog.c:3266 utils/error/elog.c:3269 #, c-format msgid " at character %d" msgstr " სიმბოლოსთან %d" -#: utils/error/elog.c:3185 utils/error/elog.c:3192 +#: utils/error/elog.c:3279 utils/error/elog.c:3286 msgid "DETAIL: " msgstr "დეტალები: " -#: utils/error/elog.c:3199 +#: utils/error/elog.c:3293 msgid "HINT: " msgstr "მინიშნება: " -#: utils/error/elog.c:3206 +#: utils/error/elog.c:3300 msgid "QUERY: " msgstr "მოთხოვნა: " -#: utils/error/elog.c:3213 +#: utils/error/elog.c:3307 msgid "CONTEXT: " msgstr "კონტექსტი: " -#: utils/error/elog.c:3223 +#: utils/error/elog.c:3317 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "მდებარეობა: %s, %s:%d\n" -#: utils/error/elog.c:3230 +#: utils/error/elog.c:3324 #, c-format msgid "LOCATION: %s:%d\n" msgstr "მდებარეობა: %s:%d\n" -#: utils/error/elog.c:3237 +#: utils/error/elog.c:3331 msgid "BACKTRACE: " msgstr "სტეკი: " -#: utils/error/elog.c:3249 +#: utils/error/elog.c:3343 msgid "STATEMENT: " msgstr "ოპერატორი: " -#: utils/error/elog.c:3645 +#: utils/error/elog.c:3739 msgid "DEBUG" msgstr "გამართვა" -#: utils/error/elog.c:3649 +#: utils/error/elog.c:3743 msgid "LOG" msgstr "ჟურნალი" -#: utils/error/elog.c:3652 +#: utils/error/elog.c:3746 msgid "INFO" msgstr "ინფორმაცია" -#: utils/error/elog.c:3655 +#: utils/error/elog.c:3749 msgid "NOTICE" msgstr "გაფრთხილება" -#: utils/error/elog.c:3659 +#: utils/error/elog.c:3753 msgid "WARNING" msgstr "გაფრთხილება" -#: utils/error/elog.c:3662 +#: utils/error/elog.c:3756 msgid "ERROR" msgstr "შეცდომა" -#: utils/error/elog.c:3665 +#: utils/error/elog.c:3759 msgid "FATAL" msgstr "ფატალური" -#: utils/error/elog.c:3668 +#: utils/error/elog.c:3762 msgid "PANIC" msgstr "პანიკა" -#: utils/fmgr/dfmgr.c:128 +#: utils/fmgr/dfmgr.c:118 #, c-format msgid "could not find function \"%s\" in file \"%s\"" msgstr "ფაილში \"%1$s\" ფუნქცია \"%2$s\" არ არსებობს" -#: utils/fmgr/dfmgr.c:247 +#: utils/fmgr/dfmgr.c:237 #, c-format msgid "could not load library \"%s\": %s" msgstr "ბიბლიოთეკის (\"%s\") ჩატვირთვის შეცდომა: %s" -#: utils/fmgr/dfmgr.c:279 +#: utils/fmgr/dfmgr.c:274 #, c-format msgid "incompatible library \"%s\": missing magic block" msgstr "არათავსებადი ბიბლიოთეკა \"%s\": მაგიური ბლოკი აღმოჩენილი არაა" -#: utils/fmgr/dfmgr.c:281 +#: utils/fmgr/dfmgr.c:276 #, c-format msgid "Extension libraries are required to use the PG_MODULE_MAGIC macro." msgstr "გაფართოების ბიბლიოთეკების მიერ PG_MODULE_MAGIC მაკროს გამოყენება აუცილებელია." -#: utils/fmgr/dfmgr.c:327 +#: utils/fmgr/dfmgr.c:322 #, c-format msgid "incompatible library \"%s\": version mismatch" msgstr "არათავსებადი ბიბლიოთეკა \"%s\": შეუსაბამო ვერსია" -#: utils/fmgr/dfmgr.c:329 +#: utils/fmgr/dfmgr.c:324 #, c-format msgid "Server is version %d, library is version %s." msgstr "სერვერის ვერსიაა %d. ბიბლიოთეკის კი %s." -#: utils/fmgr/dfmgr.c:341 +#: utils/fmgr/dfmgr.c:336 #, c-format msgid "incompatible library \"%s\": ABI mismatch" msgstr "არათავსებადი ბიბლიოთეკა \"%s\": ABI არ ემთხვევა" -#: utils/fmgr/dfmgr.c:343 +#: utils/fmgr/dfmgr.c:338 #, c-format msgid "Server has ABI \"%s\", library has \"%s\"." msgstr "სერვერის ABI \"%s\"-ა, ბიბლიოთეკის კი \"%s\"." -#: utils/fmgr/dfmgr.c:361 -#, c-format -msgid "Server has FUNC_MAX_ARGS = %d, library has %d." -msgstr "სერვერის FUNC_MAX_ARGS = %d, ბიბლიოთეკას კი %d." - -#: utils/fmgr/dfmgr.c:370 +#. translator: %s is a variable name and %d its values +#: utils/fmgr/dfmgr.c:357 utils/fmgr/dfmgr.c:367 utils/fmgr/dfmgr.c:377 #, c-format -msgid "Server has INDEX_MAX_KEYS = %d, library has %d." -msgstr "სერვერის INDEX_MAX_KEYS = %d, ბიბლიოთეკას კი %d." +msgid "Server has %s = %d, library has %d." +msgstr "სერვერს აქვს %s = %d, ბიბლიოთეკას აქვს %d." -#: utils/fmgr/dfmgr.c:379 +#. translator: %s is a variable name and %d its values +#: utils/fmgr/dfmgr.c:387 #, c-format -msgid "Server has NAMEDATALEN = %d, library has %d." -msgstr "სერვერის NAMEDATALEN = %d, ბიბლიოთეკას კი %d." +msgid "Server has %s = %s, library has %s." +msgstr "სერვერს აქვს %s = %s, ბიბლიოთეკას აქვს %s." -#: utils/fmgr/dfmgr.c:388 -#, c-format -msgid "Server has FLOAT8PASSBYVAL = %s, library has %s." -msgstr "სერვერის FLOAT8PASSBYVAL = %s, ბიბლიოთეკას კი %s." - -#: utils/fmgr/dfmgr.c:395 +#: utils/fmgr/dfmgr.c:394 msgid "Magic block has unexpected length or padding difference." msgstr "" -#: utils/fmgr/dfmgr.c:398 +#: utils/fmgr/dfmgr.c:397 #, c-format msgid "incompatible library \"%s\": magic block mismatch" msgstr "არათავსებადი ბიბლიოთეკა \"%s\": მაგიური ბლოკი არ ემთხვევა" -#: utils/fmgr/dfmgr.c:475 +#: utils/fmgr/dfmgr.c:520 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "წვდომა ბიბლიოთეკასთან \"%s\"" -#: utils/fmgr/dfmgr.c:501 +#: utils/fmgr/dfmgr.c:547 #, c-format -msgid "invalid macro name in dynamic library path: %s" -msgstr "მაკროს არასწორი სახელი დინამიკური ბიბლიოთეკის ბილიკში: %s" +msgid "invalid macro name in path: %s" +msgstr "მაკროს არასწორი სახელი ბილიკში: %s" -#: utils/fmgr/dfmgr.c:541 +#: utils/fmgr/dfmgr.c:599 #, c-format -msgid "zero-length component in parameter \"dynamic_library_path\"" -msgstr "ნულოვანი სიგრძის კომპონენტი პარამეტრში \"dynamic_library_path\"" +msgid "zero-length component in parameter \"%s\"" +msgstr "ნულოვანი სიგრძის კომპონენტი პარამეტრში \"%s\"" -#: utils/fmgr/dfmgr.c:560 +#: utils/fmgr/dfmgr.c:618 #, c-format -msgid "component in parameter \"dynamic_library_path\" is not an absolute path" -msgstr "პარამეტრში \"dynamic_library_path\" კომპონენტი აბსოლუტური ბილიკი არაა" +msgid "component in parameter \"%s\" is not an absolute path" +msgstr "პარამეტრში \"%s\" კომპონენტი აბსოლუტური ბილიკი არაა" #: utils/fmgr/fmgr.c:236 #, c-format @@ -27281,350 +28327,432 @@ msgstr "" msgid "number of aliases does not match number of columns" msgstr "მეტსახელების რიცხვი სვეტების რაოდენობას არ ემთხვევა" -#: utils/fmgr/funcapi.c:1955 -#, c-format -msgid "no column alias was provided" -msgstr "სვეტის მეტსახელი მითითებული არაა" +#: utils/fmgr/funcapi.c:1955 +#, c-format +msgid "no column alias was provided" +msgstr "სვეტის მეტსახელი მითითებული არაა" + +#: utils/fmgr/funcapi.c:1979 +#, c-format +msgid "could not determine row description for function returning record" +msgstr "ჩანაწერის დამბრუნებელი ფუნქციისთვის მწკრივის აღწერის დადგენა შეუძლებელია" + +#: utils/init/miscinit.c:265 +msgid "unknown process type" +msgstr "უცნობი პროცესის ტიპი" + +#: utils/init/miscinit.c:270 +msgid "not initialized" +msgstr "ინიციალიზებული არაა" + +#: utils/init/miscinit.c:273 +msgid "archiver" +msgstr "არქივატორი" + +#: utils/init/miscinit.c:276 +msgid "autovacuum launcher" +msgstr "ავტომომტვერსასრუტების გამშვები" + +#: utils/init/miscinit.c:279 +msgid "autovacuum worker" +msgstr "ავტომომტვერსასრუტების დამხმარე პროცესი" + +#: utils/init/miscinit.c:282 +msgid "client backend" +msgstr "კლიენტის უკანაბოლო" + +#: utils/init/miscinit.c:285 +msgid "dead-end client backend" +msgstr "ჩიხის კლიენტის უკანაბოლო" + +#: utils/init/miscinit.c:288 +msgid "background worker" +msgstr "ფონური დამხმარე პროცესი" + +#: utils/init/miscinit.c:291 +msgid "background writer" +msgstr "ფონური ჩამწერი" + +#: utils/init/miscinit.c:294 +msgid "checkpointer" +msgstr "საკონტროლო წერტილი" + +#: utils/init/miscinit.c:300 +msgid "logger" +msgstr "ჟურნალის პროცესი" + +#: utils/init/miscinit.c:303 +msgid "slotsync worker" +msgstr "სლოტის სინქრონიზაციის დამხმარე პროცესი" + +#: utils/init/miscinit.c:306 +msgid "standalone backend" +msgstr "დამოუკიდებელი უკანაბოლო" + +#: utils/init/miscinit.c:309 +msgid "startup" +msgstr "გაშვება" + +#: utils/init/miscinit.c:312 +msgid "walreceiver" +msgstr "walreceiver" -#: utils/fmgr/funcapi.c:1979 -#, c-format -msgid "could not determine row description for function returning record" -msgstr "ჩანაწერის დამბრუნებელი ფუნქციისთვის მწკრივის აღწერის დადგენა შეუძლებელია" +#: utils/init/miscinit.c:315 +msgid "walsender" +msgstr "walsender" + +#: utils/init/miscinit.c:318 +msgid "walsummarizer" +msgstr "walsummarizer" -#: utils/init/miscinit.c:352 +#: utils/init/miscinit.c:321 +msgid "walwriter" +msgstr "walwriter" + +#: utils/init/miscinit.c:358 #, c-format msgid "data directory \"%s\" does not exist" msgstr "მონაცემების საქაღალდე არ არსებობს: \"%s\"" -#: utils/init/miscinit.c:357 +#: utils/init/miscinit.c:363 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "საქაღალდის წვდომების წაკითხვა შეუძლებელია \"%s\": %m" -#: utils/init/miscinit.c:365 +#: utils/init/miscinit.c:371 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "მონაცემების მითითებული საქაღალდე \"%s\" საქაღალდე არაა" -#: utils/init/miscinit.c:381 +#: utils/init/miscinit.c:387 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "მონაცემების მითითებული საქაღალდის (\"%s\") მფლობელი არასწორია" -#: utils/init/miscinit.c:383 +#: utils/init/miscinit.c:389 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "სერვერი იმ მომხმარებლით უნდა გაეშვას, რომელიც მონაცემების საქაღალდის მფლობელია." -#: utils/init/miscinit.c:401 +#: utils/init/miscinit.c:407 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "მონაცემების საქაღალდის \"%s\" წვდომები არასწორია" -#: utils/init/miscinit.c:403 +#: utils/init/miscinit.c:409 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "წვდომები უნდა იყოს u=rwx (0700) ან u=rwx,g=rx (0750)." -#: utils/init/miscinit.c:461 +#: utils/init/miscinit.c:467 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "საქაღალდის %s-ზე შეცვლის შეცდომა: %m" -#: utils/init/miscinit.c:697 utils/misc/guc.c:3641 +#: utils/init/miscinit.c:725 utils/misc/guc.c:3647 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "" -#: utils/init/miscinit.c:770 +#: utils/init/miscinit.c:812 #, c-format msgid "role with OID %u does not exist" msgstr "როლი OID-ით %u არ არსებობს" -#: utils/init/miscinit.c:800 +#: utils/init/miscinit.c:858 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "როლს შესვლის უფლება არ აქვს: %s" -#: utils/init/miscinit.c:818 +#: utils/init/miscinit.c:879 #, c-format msgid "too many connections for role \"%s\"" msgstr "მეტისმეტად ბევრი კავშირი როლისთვის \"%s\"" -#: utils/init/miscinit.c:991 +#: utils/init/miscinit.c:1050 #, c-format msgid "invalid role OID: %u" msgstr "როლის არასწორი OID: %u" -#: utils/init/miscinit.c:1138 +#: utils/init/miscinit.c:1197 #, c-format msgid "database system is shut down" msgstr "მონაცემთა ბაზის სისტემა გათიშულია" -#: utils/init/miscinit.c:1225 +#: utils/init/miscinit.c:1284 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "ბლოკის ფაილის (%s) შექმნის შეცდომა: %m" -#: utils/init/miscinit.c:1239 +#: utils/init/miscinit.c:1298 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "ბლოკის ფაილის (%s) გახსნის შეცდომა: %m" -#: utils/init/miscinit.c:1246 +#: utils/init/miscinit.c:1305 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "ბლოკის ფაილის (%s) წაკითხვის შეცდომა: %m" -#: utils/init/miscinit.c:1255 +#: utils/init/miscinit.c:1314 #, c-format msgid "lock file \"%s\" is empty" msgstr "ბლოკის ფაილი (\"%s\") ცარიელია" -#: utils/init/miscinit.c:1256 +#: utils/init/miscinit.c:1315 #, c-format msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash." msgstr "" -#: utils/init/miscinit.c:1300 +#: utils/init/miscinit.c:1359 #, c-format msgid "lock file \"%s\" already exists" msgstr "ბლოკის ფაილი (\"%s\") უკვე არსებობს" -#: utils/init/miscinit.c:1304 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "არის სხვა postgres (PID %d) გაშვებული მონაცემების საქაღალდეში \"%s\"?" -#: utils/init/miscinit.c:1306 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "არის სხვა postmaster (PID %d) გაშვებული მონაცემების საქაღლდეში \"%s\"?" -#: utils/init/miscinit.c:1309 +#: utils/init/miscinit.c:1368 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "იყენებს სხვა postgres (PID %d) სოკეტის ფაილს \"%s\"?" -#: utils/init/miscinit.c:1311 +#: utils/init/miscinit.c:1370 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "იყენებს სხვა postmaster (PID %d) სოკეტის ფაილს \"%s\"?" -#: utils/init/miscinit.c:1362 +#: utils/init/miscinit.c:1421 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "ბლოკის ძველი ფაილის წაშლის შეცდომა \"%s\": %m" -#: utils/init/miscinit.c:1364 +#: utils/init/miscinit.c:1423 #, c-format msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again." msgstr "" -#: utils/init/miscinit.c:1401 utils/init/miscinit.c:1415 utils/init/miscinit.c:1426 +#: utils/init/miscinit.c:1460 utils/init/miscinit.c:1474 utils/init/miscinit.c:1485 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "ბლოკის ფაილში (%s) ჩაწერის შეცდომა: %m" -#: utils/init/miscinit.c:1537 utils/init/miscinit.c:1679 utils/misc/guc.c:5715 +#: utils/init/miscinit.c:1596 utils/init/miscinit.c:1738 utils/misc/guc.c:5763 #, c-format msgid "could not read from file \"%s\": %m" msgstr "ფაილიდან (\"%s\") წაკითხვის შეცდომა: %m" -#: utils/init/miscinit.c:1667 +#: utils/init/miscinit.c:1726 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "შეცდომა ფაილის (\"%s\") გახსნისას: %m; მაინც ვაგრძელებ" -#: utils/init/miscinit.c:1692 +#: utils/init/miscinit.c:1751 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "ბლოკის ფაილი \"%s\" შეიცავს არასწორ PID-ს: %ld-ს %ld-ის მაგიერ" -#: utils/init/miscinit.c:1731 utils/init/miscinit.c:1747 +#: utils/init/miscinit.c:1790 utils/init/miscinit.c:1806 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "%s მონაცემების არასწორი საქაღალდეა" -#: utils/init/miscinit.c:1733 +#: utils/init/miscinit.c:1792 #, c-format msgid "File \"%s\" is missing." msgstr "ფაილი \"%s\" აკლია." -#: utils/init/miscinit.c:1749 +#: utils/init/miscinit.c:1808 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "ფაილი \"%s\" სწორ მონაცემებს არ შეიცავს." -#: utils/init/miscinit.c:1751 +#: utils/init/miscinit.c:1810 #, c-format msgid "You might need to initdb." msgstr "როგორც ჩანს, initdb გჭირდებათ." -#: utils/init/miscinit.c:1759 +#: utils/init/miscinit.c:1818 #, c-format msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s." msgstr "მონაცემის საქაღალდე ინიციალიზებული იყო PostgreSQL-ის %s ვერსიით, რომელიც ამ ვერსიასთან, %s, თავსებადი არაა." -#: utils/init/postinit.c:259 +#: utils/init/postinit.c:269 #, c-format msgid "replication connection authorized: user=%s" msgstr "რეპლიკაციის შეერთება ავტორიზებულია: მომხმარებელი=%s" -#: utils/init/postinit.c:262 +#: utils/init/postinit.c:272 #, c-format msgid "connection authorized: user=%s" msgstr "შეერთება ავტორიზებულია: მომხმარებელი=%s" -#: utils/init/postinit.c:265 +#: utils/init/postinit.c:275 #, c-format msgid " database=%s" msgstr " ბაზა=%s" -#: utils/init/postinit.c:268 +#: utils/init/postinit.c:278 #, c-format msgid " application_name=%s" msgstr " აპლიკაციის_სახელი=%s" -#: utils/init/postinit.c:273 +#: utils/init/postinit.c:283 #, c-format msgid " SSL enabled (protocol=%s, cipher=%s, bits=%d)" msgstr " SSL ჩართულია (პროტოკოლი=%s, შიფრი=%s, ბიტები=%d)" -#: utils/init/postinit.c:285 +#: utils/init/postinit.c:295 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s, principal=%s)" msgstr " GSS (ავთენტიფიცირებული=%s, დაშიფრული=%s, delegated_credentials=%s, პრინციპალი=%s)" -#: utils/init/postinit.c:286 utils/init/postinit.c:287 utils/init/postinit.c:288 utils/init/postinit.c:293 utils/init/postinit.c:294 utils/init/postinit.c:295 +#: utils/init/postinit.c:296 utils/init/postinit.c:297 utils/init/postinit.c:298 utils/init/postinit.c:303 utils/init/postinit.c:304 utils/init/postinit.c:305 msgid "no" msgstr "არა" -#: utils/init/postinit.c:286 utils/init/postinit.c:287 utils/init/postinit.c:288 utils/init/postinit.c:293 utils/init/postinit.c:294 utils/init/postinit.c:295 +#: utils/init/postinit.c:296 utils/init/postinit.c:297 utils/init/postinit.c:298 utils/init/postinit.c:303 utils/init/postinit.c:304 utils/init/postinit.c:305 msgid "yes" msgstr "დიახ" -#: utils/init/postinit.c:292 +#: utils/init/postinit.c:302 #, c-format msgid " GSS (authenticated=%s, encrypted=%s, delegated_credentials=%s)" msgstr " GSS (ავთენტიფიცირებული=%s, დაშიფრული=%s, delegated_credentials=%s)" -#: utils/init/postinit.c:333 +#: utils/init/postinit.c:342 #, c-format msgid "database \"%s\" has disappeared from pg_database" msgstr "ბაზა \"%s\" pg_database-დან გაქრა" -#: utils/init/postinit.c:335 +#: utils/init/postinit.c:344 #, c-format msgid "Database OID %u now seems to belong to \"%s\"." msgstr "ბაზის OID %u, როგორც ჩანს, ახლა \"%s\"-ს ეკუთვნის." -#: utils/init/postinit.c:355 +#: utils/init/postinit.c:364 #, c-format msgid "database \"%s\" is not currently accepting connections" msgstr "ბაზა \"%s\" ამჟამად მიერთებებს არ იღებს" -#: utils/init/postinit.c:368 +#: utils/init/postinit.c:377 #, c-format msgid "permission denied for database \"%s\"" msgstr "წვდომა აკრძალულია ბაზაზე: \"%s\"" -#: utils/init/postinit.c:369 +#: utils/init/postinit.c:378 #, c-format msgid "User does not have CONNECT privilege." msgstr "მომხმარებელს CONNECT პრივილეგია არ გააჩნია." -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:398 #, c-format msgid "too many connections for database \"%s\"" msgstr "ძალიან ბევრი კავშირი ბაზისთვის \"%s\"" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:422 utils/init/postinit.c:429 #, c-format msgid "database locale is incompatible with operating system" msgstr "ბაზის ენა ოპერაციულ სისტემასთან შეუთავსებელია" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:423 #, c-format msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()." msgstr "ბაზა ინიციალიზებული იყო LC_COLLATE \"%s\"-ით, რომელსაც setlocale() ვერ ცნობს." -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:425 utils/init/postinit.c:432 #, c-format msgid "Recreate the database with another locale or install the missing locale." msgstr "თავიდან შექმენით ბაზა სხვა ლოკალით ან დააყენეთ ლოკალი, რომელიც ვერ ვიპოვე." -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:430 #, c-format msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "ბაზა ინიციალიზებული იყო LC_CTYPE \"%s\"-ით, რომელსაც setlocale() ვერ ცნობს." -#: utils/init/postinit.c:491 +#: utils/init/postinit.c:471 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "ბაზის \"%s\" კოლაციის ვერსია არ ემთხვევა" -#: utils/init/postinit.c:493 +#: utils/init/postinit.c:473 #, c-format msgid "The database was created using collation version %s, but the operating system provides version %s." msgstr "" -#: utils/init/postinit.c:496 +#: utils/init/postinit.c:476 #, c-format msgid "Rebuild all objects in this database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "" -#: utils/init/postinit.c:902 +#: utils/init/postinit.c:566 +#, c-format +msgid "too many server processes configured" +msgstr "მორგებულია მეტისმეტად ბევრი სერვერის პროცესი" + +#: utils/init/postinit.c:567 +#, c-format +msgid "\"max_connections\" (%d) plus \"autovacuum_worker_slots\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d." +msgstr "" + +#: utils/init/postinit.c:889 #, c-format msgid "no roles are defined in this database system" msgstr "ამ მონაცემთა ბაზაში როლები აღწერილი არაა" -#: utils/init/postinit.c:903 +#: utils/init/postinit.c:890 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "მაშინვე უნდა გაუშვათ CREATE USER \"%s\" SUPERUSER;." -#: utils/init/postinit.c:940 +#: utils/init/postinit.c:935 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "ორობითი განახლებისას მისაერთებლად ზემომხმარებელი უნდა ბრძანდებოდეთ" -#: utils/init/postinit.c:961 +#: utils/init/postinit.c:955 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "დარჩენილი მიერთების სლოტები დაცულია %s ატრიბუტის მქონე როლებისთვის" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:961 #, c-format msgid "remaining connection slots are reserved for roles with privileges of the \"%s\" role" msgstr "დარჩენილი მიერთების სლოტები დაცულია %s როლის პრივილეგიების მქონე როლებისთვის" -#: utils/init/postinit.c:979 +#: utils/init/postinit.c:973 #, c-format msgid "permission denied to start WAL sender" msgstr "'WAL' გამგზავნის გაშვების წვდომა აკრძალულია" -#: utils/init/postinit.c:980 +#: utils/init/postinit.c:974 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "" -#: utils/init/postinit.c:1098 +#: utils/init/postinit.c:1092 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "როგორც ჩანს, ახლახანს წაიშალა ან სახელი გადაერქვა." -#: utils/init/postinit.c:1102 +#: utils/init/postinit.c:1096 #, c-format msgid "database %u does not exist" msgstr "ბაზა არ არსებობს: %u" -#: utils/init/postinit.c:1111 +#: utils/init/postinit.c:1105 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "არასწორ მონაცემთა ბაზასთან \"%s\" დაკავშირება ვერ მოხერხდა" -#: utils/init/postinit.c:1172 +#: utils/init/postinit.c:1166 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "ბაზის ქვესაქაღალდე არ არსებობს: %s." @@ -27639,12 +28767,12 @@ msgstr "როლს \"%s\" \"%s\"-ზე SET ROLE არ შეუძლია" msgid "invalid encoding number: %d" msgstr "კოდირების არასწორი ნომერი: %d" -#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:129 utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:165 +#: utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:132 utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c:168 #, c-format msgid "unexpected encoding ID %d for ISO 8859 character sets" msgstr "მოულოდნელი დაშიფვრის ID %d 'ISO 8859' სიმბოლოების ნაკრებებისთვის" -#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:110 utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:146 +#: utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:113 utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c:149 #, c-format msgid "unexpected encoding ID %d for WIN character sets" msgstr "მოულოდნელი დაშიფვრის ID %d WIN სიმბოლოების ნაკრებებისთვის" @@ -27704,92 +28832,92 @@ msgstr "კონფიგურაციის საქაღალდის msgid "could not open configuration directory \"%s\": %m" msgstr "კონფიგურაციის საქაღალდის (\"%s\") გახსნის შეცდომა: %m" -#: utils/misc/guc.c:122 +#: utils/misc/guc.c:119 msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "პარამეტრის სწორი ერთეულებია \"ბ\", \"კბ\", \"მბ\", \"გბ\" და \"ტბ\"." -#: utils/misc/guc.c:159 +#: utils/misc/guc.c:156 msgid "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\"." msgstr "პარამეტრის სწორი ერთეულებია \"მკწმ\", \"მწმ\", \"წმ\", \"წთ\", \"სთ\" და \"დღე\"." -#: utils/misc/guc.c:430 +#: utils/misc/guc.c:428 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "უცნობი კონფიგურაციის პარამეტრი \"%s\" ფაილში \"%s\" ხაზზე %d" -#: utils/misc/guc.c:470 utils/misc/guc.c:3495 utils/misc/guc.c:3739 utils/misc/guc.c:3837 utils/misc/guc.c:3935 utils/misc/guc.c:4059 utils/misc/guc.c:4162 +#: utils/misc/guc.c:468 utils/misc/guc.c:3501 utils/misc/guc.c:3745 utils/misc/guc.c:3843 utils/misc/guc.c:3941 utils/misc/guc.c:4068 utils/misc/guc.c:4209 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "პარამეტრი \"%s\" -ის შეცვლა სერვერის გადატვირთვის გარეშე შეუძლებელია" -#: utils/misc/guc.c:506 +#: utils/misc/guc.c:504 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "პარამეტრი \"%s\" წაიშალა კონფიგურაციის ფაილიდან. დაბრუნდა ნაგულისხმევ მნიშვნელობაზე" -#: utils/misc/guc.c:571 +#: utils/misc/guc.c:569 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "პარამეტრი \"%s\" შეიცვალა \"%s\"-ზე" -#: utils/misc/guc.c:613 +#: utils/misc/guc.c:611 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "კონფიგურაციის ფაილი \"%s\" შეცდომებს შეიცავს" -#: utils/misc/guc.c:618 +#: utils/misc/guc.c:616 #, c-format msgid "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "კონფიგურაციის ფაილი \"%s\" შეცდომებს შეიცავს; გამოყენებული იქნება მხოლოდ სწორი ნაწილი" -#: utils/misc/guc.c:623 +#: utils/misc/guc.c:621 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "კონფიგურაციის ფაილი \"%s\" შეცდომებს შეიცავს; ცვლილებები არ მოხდება" -#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 +#: utils/misc/guc.c:1137 utils/misc/guc.c:1153 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "კონფიგურაციის პარამეტრის არასწორი სახელი: %s" -#: utils/misc/guc.c:1141 +#: utils/misc/guc.c:1139 #, c-format msgid "Custom parameter names must be two or more simple identifiers separated by dots." msgstr "მომხმარებლის პარამეტრის სახელები ორი ან მეტი მარტივი, წერტილებით გამოყოფილი იდენტიფიკატორი უნდა იყოს." -#: utils/misc/guc.c:1157 +#: utils/misc/guc.c:1155 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\" დაცული პრეფიქსია." -#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 +#: utils/misc/guc.c:1168 utils/misc/guc.c:1278 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "კონფიგურაციის უცნობი პარამეტრი: \"%s\"" -#: utils/misc/guc.c:1802 +#: utils/misc/guc.c:1800 #, c-format msgid "%s: could not access directory \"%s\": %m\n" msgstr "%s საქაღალდესთან %s წვდომის უფლება არ გაქვთ: %m\n" -#: utils/misc/guc.c:1806 +#: utils/misc/guc.c:1804 #, c-format msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" msgstr "PostgreSQL-ის მონაცემების საქაღალდის ინიციალიზაციისთვის initdb ან pg_basebackup გაუშვით.\n" -#: utils/misc/guc.c:1830 +#: utils/misc/guc.c:1828 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" "You must specify the --config-file or -D invocation option or set the PGDATA environment variable.\n" msgstr "" -#: utils/misc/guc.c:1853 +#: utils/misc/guc.c:1851 #, c-format msgid "%s: could not access the server configuration file \"%s\": %m\n" msgstr "%s: სერვერის კონფიგურაციის ფაილთან ('%s') წვდომა აკრძალულია: %m\n" -#: utils/misc/guc.c:1881 +#: utils/misc/guc.c:1879 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -27798,139 +28926,144 @@ msgstr "" "%s-მა არ იცის, სად იპოვოს მონაცემთა ბაზის სისტემური მონაცემები.\n" "ამის მითითება \"%s\"-ში \"data_directory\" პარამეტრით შეგიძლიათ, ან -D გაშვების პარამეტრით, ან PGDATA გარემოს ცვლადით.\n" -#: utils/misc/guc.c:1933 +#: utils/misc/guc.c:1931 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" "This can be specified as \"hba_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n" msgstr "" -#: utils/misc/guc.c:1964 +#: utils/misc/guc.c:1962 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" "This can be specified as \"ident_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n" msgstr "" -#: utils/misc/guc.c:2943 +#: utils/misc/guc.c:2941 msgid "Value exceeds integer range." msgstr "\"lo_write\" -ის არგუმენტიმთელი რიცხვის დასაშვებ საზღვრებს სცდება." -#: utils/misc/guc.c:3185 +#: utils/misc/guc.c:3182 #, c-format msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" msgstr "%d%s%s დაშვებულ დიაპაზონს გარეთაა პარამეტრისთვის \"%s\" (%d%s%s .. %d%s%s)" -#: utils/misc/guc.c:3226 +#: utils/misc/guc.c:3223 #, c-format msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" msgstr "%g%s%s დაშვებულ დიაპაზონს გარეთაა პარამეტრისთვის \"%s\" (%g%s%s .. %g%s%s)" -#: utils/misc/guc.c:3447 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3462 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "პარალელური ოპერაციის დროს პარამეტრების დაყენება შეუძლებელია" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "პარამეტრს \"%s\" ვერ დააყენებთ პარალელური ოპერაციის დროს" -#: utils/misc/guc.c:3472 utils/misc/guc.c:4646 +#: utils/misc/guc.c:3478 utils/misc/guc.c:4693 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "პარამეტრი \"%s\" არ შეიძლება შეიცვალოს" -#: utils/misc/guc.c:3505 +#: utils/misc/guc.c:3511 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "პარამეტრი \"%s\" ახლა არ შეიძლება შეიცვალოს" -#: utils/misc/guc.c:3532 utils/misc/guc.c:3594 utils/misc/guc.c:4621 utils/misc/guc.c:6712 +#: utils/misc/guc.c:3538 utils/misc/guc.c:3600 utils/misc/guc.c:4668 utils/misc/guc.c:6754 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "პარამეტრის (\"%s\") დაყენების წვდომა აკრძალულია" -#: utils/misc/guc.c:3574 +#: utils/misc/guc.c:3580 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "პარამეტრი \"%s\"-ის დაყენება კავშირის დამყარების შემდეგ შეუძლებელია" -#: utils/misc/guc.c:3633 +#: utils/misc/guc.c:3639 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "უსაფრთხოების აღმწერ ფუნქციაში პარამეტრ \"%s\"-ს ვერ გამოიყენებთ" -#: utils/misc/guc.c:3654 +#: utils/misc/guc.c:3660 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "პარამეტრის საწყის მნიშვნელობაზე დაბრუნების შეცდომა: \"%s\"" -#: utils/misc/guc.c:3661 +#: utils/misc/guc.c:3667 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "პარამეტრი \"%s\"-ის ფუნქციებში ლოკალურად დაყენება შეუძლებელია" -#: utils/misc/guc.c:4320 utils/misc/guc.c:4368 utils/misc/guc.c:5400 +#: utils/misc/guc.c:4367 utils/misc/guc.c:4415 utils/misc/guc.c:5448 #, c-format msgid "permission denied to examine \"%s\"" msgstr "\"%s\"-ის მოსინჯვის წვდომა აკრძალულია" -#: utils/misc/guc.c:4321 utils/misc/guc.c:4369 utils/misc/guc.c:5401 +#: utils/misc/guc.c:4368 utils/misc/guc.c:4416 utils/misc/guc.c:5449 #, c-format msgid "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "ამ პარამეტრის შემოწმება მხოლოდ \"%s\" პრივილეგიის მქონე როლებს შეუძლიათ." -#: utils/misc/guc.c:4579 +#: utils/misc/guc.c:4626 #, c-format msgid "ALTER SYSTEM is not allowed in this environment" msgstr "ამ გარემოში ALTER SYSTEM დაშვებული არაა" -#: utils/misc/guc.c:4611 +#: utils/misc/guc.c:4658 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "\"ALTER SYSTEM RESET ALL\"-ის შესრულების წვდომა აკრძალულია" -#: utils/misc/guc.c:4690 +#: utils/misc/guc.c:4737 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "პარამეტრის მნიშვნელობა ALTER SYSTEM-სთვის არ შეიძლება, ახალი ხაზის სიმბოლოს შეიცავდეს" -#: utils/misc/guc.c:4735 +#: utils/misc/guc.c:4782 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "ფაილის დშემცველობის ამუშავების შეცდომა \"%s\"" -#: utils/misc/guc.c:4917 +#: utils/misc/guc.c:4965 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "პარამეტრის თავიდან აღწერის მცდელობა: \"%s\"" -#: utils/misc/guc.c:5256 +#: utils/misc/guc.c:5304 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "კონფიგურაციის პარამეტრის არასწორი სახელი: \"%s\". წაიშლება" -#: utils/misc/guc.c:5258 +#: utils/misc/guc.c:5306 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "\"%s\" ახლა დაცული პრეფიქსია." -#: utils/misc/guc.c:6135 +#: utils/misc/guc.c:6177 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "პარამეტრის \"%s\" \"%s\"-ზე დაყენებისას" -#: utils/misc/guc.c:6304 +#: utils/misc/guc.c:6346 #, c-format msgid "parameter \"%s\" could not be set" msgstr "პარამეტრის დაყენების შეცდომა: \"%s\"" -#: utils/misc/guc.c:6394 +#: utils/misc/guc.c:6436 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "პარამეტრის მნიშვნელობის დამუშავების შეცდომა: %s" -#: utils/misc/guc.c:6844 +#: utils/misc/guc.c:6886 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "არასწორი მნიშვნელობა პარამეტრისთვის \"%s\": %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "პარალელური ოპერაციის დროს პარამეტრების დაყენება შეუძლებელია" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -27946,2054 +29079,2262 @@ msgstr "SET %s მხოლოდ ერთ არგუმენტს იღ msgid "SET requires parameter name" msgstr "SET მოითხოვს პარამეტრის სახელს" -#: utils/misc/guc_tables.c:675 +#: utils/misc/guc_tables.c:692 msgid "Ungrouped" msgstr "დაჯგუფება მოხსნილია" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:693 msgid "File Locations" msgstr "ფაილის მდებარეობები" -#: utils/misc/guc_tables.c:677 +#: utils/misc/guc_tables.c:694 msgid "Connections and Authentication / Connection Settings" msgstr "დაკავშირება და ავთენტიკაცია / შეერთების პარამეტრები" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:695 msgid "Connections and Authentication / TCP Settings" msgstr "დაკავშირება და ავთენტიკაცია / TCP-ის პარამეტრები" -#: utils/misc/guc_tables.c:679 +#: utils/misc/guc_tables.c:696 msgid "Connections and Authentication / Authentication" msgstr "დაკავშირება და ავთენტიკაცია / ავთენტიკაცია" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:697 msgid "Connections and Authentication / SSL" msgstr "დაკავშირება და ავთენტიკაცია / SSL" -#: utils/misc/guc_tables.c:681 +#: utils/misc/guc_tables.c:698 msgid "Resource Usage / Memory" msgstr "რესურსების გამოყენება / მეხსიერება" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:699 msgid "Resource Usage / Disk" msgstr "რესურსების გამოყენება / დისკი" -#: utils/misc/guc_tables.c:683 +#: utils/misc/guc_tables.c:700 msgid "Resource Usage / Kernel Resources" msgstr "რესურსების გამოყენება / ბირთვის რესურსები" -#: utils/misc/guc_tables.c:684 -msgid "Resource Usage / Cost-Based Vacuum Delay" -msgstr "რესურსების გამოყენება / ფასზე-დამოკიდებული დამტვერსასრუტების დაყოვნება" - -#: utils/misc/guc_tables.c:685 +#: utils/misc/guc_tables.c:701 msgid "Resource Usage / Background Writer" msgstr "რესურსების გამოყენება / ფონური ჩამწერი" -#: utils/misc/guc_tables.c:686 -msgid "Resource Usage / Asynchronous Behavior" -msgstr "რესურსების გამოყენება / ასინქრონული ქცევა" +#: utils/misc/guc_tables.c:702 +msgid "Resource Usage / I/O" +msgstr "რესურსების გამოყენება / შეტ/გამოტ" + +#: utils/misc/guc_tables.c:703 +msgid "Resource Usage / Worker Processes" +msgstr "რესურსების გამოყენება / დამხმარე პროცესის რესურსები" -#: utils/misc/guc_tables.c:687 +#: utils/misc/guc_tables.c:704 msgid "Write-Ahead Log / Settings" msgstr "წინასწარ-ჩაწერი ჟურნალი / მორგება" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:705 msgid "Write-Ahead Log / Checkpoints" msgstr "წინასწარ-ჩაწერი ჟურნალი / საკონტროლო წერტილები" -#: utils/misc/guc_tables.c:689 +#: utils/misc/guc_tables.c:706 msgid "Write-Ahead Log / Archiving" msgstr "წინასწარ-ჩაწერი ჟურნალი / არქივირება" -#: utils/misc/guc_tables.c:690 +#: utils/misc/guc_tables.c:707 msgid "Write-Ahead Log / Recovery" msgstr "წინასწარ-ჩაწერი ჟურნალი / აღდგენა" -#: utils/misc/guc_tables.c:691 +#: utils/misc/guc_tables.c:708 msgid "Write-Ahead Log / Archive Recovery" msgstr "წინასწარ-ჩაწერი ჟურნალი / არქივის აღდგენა" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:709 msgid "Write-Ahead Log / Recovery Target" msgstr "წინასწარ-ჩაწერი ჟურნალი / სამიზნის აღდგენა" -#: utils/misc/guc_tables.c:693 +#: utils/misc/guc_tables.c:710 msgid "Write-Ahead Log / Summarization" msgstr "წინასწარ-ჩაწერი ჟურნალი / შეჯამება" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:711 msgid "Replication / Sending Servers" msgstr "რეპლიკაცია / სერვერების გაგზავნა" -#: utils/misc/guc_tables.c:695 +#: utils/misc/guc_tables.c:712 msgid "Replication / Primary Server" msgstr "რეპლიკაცია / ძირითადი სერვერი" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:713 msgid "Replication / Standby Servers" msgstr "რეპლიკაცია / უქმე სერვერები" -#: utils/misc/guc_tables.c:697 +#: utils/misc/guc_tables.c:714 msgid "Replication / Subscribers" msgstr "რეპლიკაცია / გამომწერები" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:715 msgid "Query Tuning / Planner Method Configuration" msgstr "მოთხოვნის მორგება / დამგეგმავის მეთოდის კონფიგურაცია" -#: utils/misc/guc_tables.c:699 +#: utils/misc/guc_tables.c:716 msgid "Query Tuning / Planner Cost Constants" msgstr "მოთხოვნის მორგება / დამგეგმავის ფასის შეზღუდვები" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:717 msgid "Query Tuning / Genetic Query Optimizer" msgstr "მოთხოვნის მორგება / მოთხოვნის ზოგადი ოპტიმიზატორი" -#: utils/misc/guc_tables.c:701 +#: utils/misc/guc_tables.c:718 msgid "Query Tuning / Other Planner Options" msgstr "მოთხოვნის მორგება / დამგეგმავის სხვა პარამეტრები" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:719 msgid "Reporting and Logging / Where to Log" msgstr "ანგარიშები და ჟურნალი / სად ჩავწერო ჟურნალი" -#: utils/misc/guc_tables.c:703 +#: utils/misc/guc_tables.c:720 msgid "Reporting and Logging / When to Log" msgstr "ანგარიშები და ჟურნალი / როდის ჩავწერო ჟურნალი" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:721 msgid "Reporting and Logging / What to Log" msgstr "ანგარიშები და ჟურნალი / რა ჩავწერო ჟურნალში" -#: utils/misc/guc_tables.c:705 +#: utils/misc/guc_tables.c:722 msgid "Reporting and Logging / Process Title" msgstr "ანგარიშები და ჟურნალი / პროცესის სათაური" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:723 msgid "Statistics / Monitoring" msgstr "სტატისტიკა / მონიტორინგი" -#: utils/misc/guc_tables.c:707 +#: utils/misc/guc_tables.c:724 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "სტატისტიკა / კუმულაციური მოთხოვნისა და ინდექსის სტატისტიკა" -#: utils/misc/guc_tables.c:708 -msgid "Autovacuum" -msgstr "ავტომომტვერსასრუტება" +#: utils/misc/guc_tables.c:725 +msgid "Vacuuming / Automatic Vacuuming" +msgstr "მომტვერსასრუტება / ავტომატური მომტვერსასრუტება" -#: utils/misc/guc_tables.c:709 +#: utils/misc/guc_tables.c:726 +msgid "Vacuuming / Cost-Based Vacuum Delay" +msgstr "მომტვერსასრუტება / ფასზე-დამოკიდებული მომტვერსასრუტების დაყოვნება" + +#: utils/misc/guc_tables.c:727 +msgid "Vacuuming / Default Behavior" +msgstr "მომტვერსასრუტება / ნაგულისხმევი ქცევა" + +#: utils/misc/guc_tables.c:728 +msgid "Vacuuming / Freezing" +msgstr "მომტვერსასრუტება / გაყინვა" + +#: utils/misc/guc_tables.c:729 msgid "Client Connection Defaults / Statement Behavior" msgstr "კლიენტის შეერთების ნაგულისხმევი პარამეტრები / ბრძანების ქცევა" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:730 msgid "Client Connection Defaults / Locale and Formatting" msgstr "კლიენტის შეერთების ნაგულისხმევი პარამეტრები / ენა და ფორმატირება" -#: utils/misc/guc_tables.c:711 +#: utils/misc/guc_tables.c:731 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "კლიენტის შეერთების ნაგულისხმევი პარამეტრები / გაზიარებული ბიბლიოთეკის წინასწარი ჩატვირთვა" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:732 msgid "Client Connection Defaults / Other Defaults" msgstr "კლიენტის შეერთების ნაგულისხმევი პარამეტრები / სხვა ნაგულისხმევი პარამეტრები" -#: utils/misc/guc_tables.c:713 +#: utils/misc/guc_tables.c:733 msgid "Lock Management" msgstr "ბლოკის მართვა" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:734 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "ვერსიისა და პლატფორმის თავსებადობა / PostgreSQL-ის წინა ვერსიები" -#: utils/misc/guc_tables.c:715 +#: utils/misc/guc_tables.c:735 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "ვერსიისა და პლატფორმის თავსებადობა / სხვა პლატფორმები და კლიენტები" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:736 msgid "Error Handling" msgstr "შეცდომების დამუშავება" -#: utils/misc/guc_tables.c:717 +#: utils/misc/guc_tables.c:737 msgid "Preset Options" msgstr "პრესეტის მორგება" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:738 msgid "Customized Options" msgstr "ხელით მითითებული პარამეტრები" -#: utils/misc/guc_tables.c:719 +#: utils/misc/guc_tables.c:739 msgid "Developer Options" msgstr "პროგრამისტის პარამეტრები" -#: utils/misc/guc_tables.c:774 +#: utils/misc/guc_tables.c:794 msgid "Enables the planner's use of sequential-scan plans." msgstr "დამგეგმავისთვის მიმდევრობითი სკანირების გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:784 +#: utils/misc/guc_tables.c:804 msgid "Enables the planner's use of index-scan plans." msgstr "დამგეგმავისთვის ინდექსის სკანირების გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:794 +#: utils/misc/guc_tables.c:814 msgid "Enables the planner's use of index-only-scan plans." msgstr "დამგეგმავისთვის მხოლოდ ინდექსის სკანირების გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:804 +#: utils/misc/guc_tables.c:824 msgid "Enables the planner's use of bitmap-scan plans." msgstr "დამგეგმავისთვის ბიტური რუკების სკანირების გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:814 +#: utils/misc/guc_tables.c:834 msgid "Enables the planner's use of TID scan plans." msgstr "დამგეგმავისთვის TID-ის სკანირების გეგმების გამოყენების უფლები მიცემა." -#: utils/misc/guc_tables.c:824 +#: utils/misc/guc_tables.c:844 msgid "Enables the planner's use of explicit sort steps." msgstr "დამგეგმავისთვის აშკარა დალაგების ნაბიჯების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:834 +#: utils/misc/guc_tables.c:854 msgid "Enables the planner's use of incremental sort steps." msgstr "დამგეგმავისთვის ინკრემენტული დალაგების ნაბიჯების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:844 +#: utils/misc/guc_tables.c:864 msgid "Enables the planner's use of hashed aggregation plans." msgstr "დამგეგმავისთვის დაჰეშიილი აგრეგაციის გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:854 +#: utils/misc/guc_tables.c:874 msgid "Enables the planner's use of materialization." msgstr "დამგეგმავისთვის მატერიალიზაციის გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:864 +#: utils/misc/guc_tables.c:884 msgid "Enables the planner's use of memoization." msgstr "დამგეგმავისთვის მემოიზაციის გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:874 +#: utils/misc/guc_tables.c:894 msgid "Enables the planner's use of nested-loop join plans." msgstr "დამგეგმავისთვის ერთმანეთში ჩალაგებული მარყუჟი შერწყმის გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:884 +#: utils/misc/guc_tables.c:904 msgid "Enables the planner's use of merge join plans." msgstr "დამგეგმავისთვის შეერთების გეგმების შერწყმის გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:894 +#: utils/misc/guc_tables.c:914 msgid "Enables the planner's use of hash join plans." msgstr "დამგეგმავისთვის ჰეშის შეერთების გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:904 +#: utils/misc/guc_tables.c:924 msgid "Enables the planner's use of gather merge plans." msgstr "დამგეგმავისთვის შერწყმის გეგმების შეგროვების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:914 +#: utils/misc/guc_tables.c:934 msgid "Enables partitionwise join." msgstr "დანაყოფის გათვალისწინებით შეერთების ჩართვა." -#: utils/misc/guc_tables.c:924 +#: utils/misc/guc_tables.c:944 msgid "Enables partitionwise aggregation and grouping." msgstr "დანაყოფის გათვალისწინებით აგრეგაციისა და დაჯგუფებს ჩართვა." -#: utils/misc/guc_tables.c:934 +#: utils/misc/guc_tables.c:954 msgid "Enables the planner's use of parallel append plans." msgstr "დამგეგმავისთვის პარალელური ბოლოში მიწერის გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:944 +#: utils/misc/guc_tables.c:964 msgid "Enables the planner's use of parallel hash plans." msgstr "დამგეგმავისთვის პარალელური ჰეშის გეგმების გამოყენების უფლების მიცემა." -#: utils/misc/guc_tables.c:954 +#: utils/misc/guc_tables.c:974 msgid "Enables plan-time and execution-time partition pruning." msgstr "" -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:975 msgid "Allows the query planner and executor to compare partition bounds to conditions in the query to determine which partitions must be scanned." msgstr "" -#: utils/misc/guc_tables.c:966 +#: utils/misc/guc_tables.c:986 msgid "Enables the planner's ability to produce plans that provide presorted input for ORDER BY / DISTINCT aggregate functions." msgstr "" -#: utils/misc/guc_tables.c:969 +#: utils/misc/guc_tables.c:989 msgid "Allows the query planner to build plans that provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." msgstr "" -#: utils/misc/guc_tables.c:981 +#: utils/misc/guc_tables.c:1001 msgid "Enables the planner's use of async append plans." msgstr "" -#: utils/misc/guc_tables.c:991 +#: utils/misc/guc_tables.c:1011 +msgid "Enables removal of unique self-joins." +msgstr "უნიკალური თვითშერწყმების წაშლის ჩართვა." + +#: utils/misc/guc_tables.c:1021 msgid "Enables reordering of GROUP BY keys." msgstr "გასაღების (GROUP BY) გადალაგების ჩართვა." -#: utils/misc/guc_tables.c:1001 +#: utils/misc/guc_tables.c:1031 +msgid "Enables reordering of DISTINCT pathkeys." +msgstr "ჩართავს DISTINCT ბილიკის გასაღებების გადალაგებას." + +#: utils/misc/guc_tables.c:1041 msgid "Enables genetic query optimization." msgstr "მოთხოვნების ზოგადი ოპტიმიზაციის ჩართვა." -#: utils/misc/guc_tables.c:1002 +#: utils/misc/guc_tables.c:1042 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "" -#: utils/misc/guc_tables.c:1016 +#: utils/misc/guc_tables.c:1056 msgid "Shows whether the current user is a superuser." msgstr "აჩვენებს, არის მიმდინარე მომხმარებელი ზემომხმარებელი, თუ არა." -#: utils/misc/guc_tables.c:1031 +#: utils/misc/guc_tables.c:1071 msgid "Allows running the ALTER SYSTEM command." -msgstr "" +msgstr "ALTER SYSTEM ბრძანების გაშვების დაშვება." -#: utils/misc/guc_tables.c:1032 +#: utils/misc/guc_tables.c:1072 msgid "Can be set to off for environments where global configuration changes should be made using a different method." msgstr "" -#: utils/misc/guc_tables.c:1042 +#: utils/misc/guc_tables.c:1082 msgid "Enables advertising the server via Bonjour." msgstr "სერვისის Bonjour-ით გამოქვეყნების ჩართვა." -#: utils/misc/guc_tables.c:1051 +#: utils/misc/guc_tables.c:1091 msgid "Collects transaction commit time." msgstr "აგროვებს ტრანზაქციის გადაცემის დროს." -#: utils/misc/guc_tables.c:1060 +#: utils/misc/guc_tables.c:1100 msgid "Enables SSL connections." msgstr "SSL შეერთებების ჩართვა." -#: utils/misc/guc_tables.c:1069 +#: utils/misc/guc_tables.c:1109 msgid "Controls whether \"ssl_passphrase_command\" is called during server reload." msgstr "" -#: utils/misc/guc_tables.c:1078 +#: utils/misc/guc_tables.c:1118 msgid "Give priority to server ciphersuite order." msgstr "" -#: utils/misc/guc_tables.c:1087 +#: utils/misc/guc_tables.c:1127 msgid "Forces synchronization of updates to disk." msgstr "დისკის განახლებების ნაძალადევი სინქრონიზაცია." -#: utils/misc/guc_tables.c:1088 +#: utils/misc/guc_tables.c:1128 msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This ensures that a database cluster will recover to a consistent state after an operating system or hardware crash." msgstr "" -#: utils/misc/guc_tables.c:1099 +#: utils/misc/guc_tables.c:1139 msgid "Continues processing after a checksum failure." msgstr "აგრძელებს დამუშავებას საკონტროლო ჯამის ჩავარდნის შემდეგ." -#: utils/misc/guc_tables.c:1100 +#: utils/misc/guc_tables.c:1140 msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled." msgstr "" -#: utils/misc/guc_tables.c:1114 +#: utils/misc/guc_tables.c:1154 msgid "Continues processing past damaged page headers." msgstr "აგრძელებს დამუშავებას დაზიანებული გვერდის თავსართების შემდეგ." -#: utils/misc/guc_tables.c:1115 +#: utils/misc/guc_tables.c:1155 msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting \"zero_damaged_pages\" to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." msgstr "" -#: utils/misc/guc_tables.c:1128 +#: utils/misc/guc_tables.c:1168 msgid "Continues recovery after an invalid pages failure." msgstr "აგრძელებს აღდგენას არასწორი გვერდის ჩავარდნების შემდეგ." -#: utils/misc/guc_tables.c:1129 +#: utils/misc/guc_tables.c:1169 msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." msgstr "" -#: utils/misc/guc_tables.c:1147 +#: utils/misc/guc_tables.c:1187 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "" -#: utils/misc/guc_tables.c:1148 +#: utils/misc/guc_tables.c:1188 msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible." msgstr "" -#: utils/misc/guc_tables.c:1161 +#: utils/misc/guc_tables.c:1201 msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification." msgstr "" -#: utils/misc/guc_tables.c:1171 +#: utils/misc/guc_tables.c:1211 msgid "Writes zeroes to new WAL files before first use." msgstr "ახალ WAL-ის ფაილებში მათ პირველ გამოყენებამდე ნულიანების ჩაწერა." -#: utils/misc/guc_tables.c:1181 +#: utils/misc/guc_tables.c:1221 msgid "Recycles WAL files by renaming them." msgstr "WAL-ის ფაილების თავიდან გამოყენება მათი სახელის გადარქმევით." -#: utils/misc/guc_tables.c:1191 +#: utils/misc/guc_tables.c:1231 msgid "Logs each checkpoint." msgstr "საკონტროლო წერტილების ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:1200 -msgid "Logs each successful connection." -msgstr "ყოველი წარმატებული შესვლის ჟურნალში ჩაწერა." - -#: utils/misc/guc_tables.c:1209 +#: utils/misc/guc_tables.c:1240 msgid "Logs details of pre-authentication connection handshake." msgstr "ჩაიწერს ავთენტიკაციამდე მიერთების ხელის ჩამორთმევის დეტალებს." -#: utils/misc/guc_tables.c:1219 +#: utils/misc/guc_tables.c:1250 msgid "Logs end of a session, including duration." msgstr "სესიის დასრულების ჟურნალში ჩაწერა, ხანგრძლივობის ჩართვლით." -#: utils/misc/guc_tables.c:1228 +#: utils/misc/guc_tables.c:1259 msgid "Logs each replication command." msgstr "რეპლიკაციის ყოველი ბრძანების ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:1237 +#: utils/misc/guc_tables.c:1268 msgid "Shows whether the running server has assertion checks enabled." msgstr "" -#: utils/misc/guc_tables.c:1248 +#: utils/misc/guc_tables.c:1279 msgid "Terminate session on any error." msgstr "სესიის დასრულება ნებისმიერი შეცდომის შემთხვევაში." -#: utils/misc/guc_tables.c:1257 +#: utils/misc/guc_tables.c:1288 msgid "Reinitialize server after backend crash." msgstr "უკანაბოლოს ავარიის შემდეგ სერვერის თავიდან ინიციალიზაცია." -#: utils/misc/guc_tables.c:1266 +#: utils/misc/guc_tables.c:1297 msgid "Remove temporary files after backend crash." msgstr "უკანაბოლოს ავარიის შემდეგ დროებითი ფაილების წაშლა." -#: utils/misc/guc_tables.c:1276 +#: utils/misc/guc_tables.c:1307 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "უკანაბოლოს ავარიის შემდეგ შვილი პროცესებისთვის SIGQUIT-ის მაგიერ SIGABRT-ის გაგზავნა." -#: utils/misc/guc_tables.c:1286 +#: utils/misc/guc_tables.c:1317 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "გაჭედილი შვილი პროცესებისთვის SIGKILL-ის მაგიერ SIGABRT-ის გაგზავნა." -#: utils/misc/guc_tables.c:1297 +#: utils/misc/guc_tables.c:1328 msgid "Logs the duration of each completed SQL statement." msgstr "თითოეული დასრულებული SQL გამოსახულების ხანგრძლივობის ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:1306 +#: utils/misc/guc_tables.c:1338 +msgid "Set this to force all parse and plan trees to be passed through copyObject(), to facilitate catching errors and omissions in copyObject()." +msgstr "" + +#: utils/misc/guc_tables.c:1355 +msgid "Set this to force all parse and plan trees to be passed through outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in those modules." +msgstr "" + +#: utils/misc/guc_tables.c:1372 +msgid "Set this to force all raw parse trees for DML statements to be scanned by raw_expression_tree_walker(), to facilitate catching errors and omissions in that function." +msgstr "" + +#: utils/misc/guc_tables.c:1390 msgid "Logs each query's parse tree." msgstr "ჟურნალში თითოეული მოთხოვნის დამუშავების ხის ჩაწერა." -#: utils/misc/guc_tables.c:1315 +#: utils/misc/guc_tables.c:1399 msgid "Logs each query's rewritten parse tree." msgstr "ჟურნალში თითოეული მოთხოვნის გადაწერილი დამუშავების ხის ჩაწერა." -#: utils/misc/guc_tables.c:1324 +#: utils/misc/guc_tables.c:1408 msgid "Logs each query's execution plan." msgstr "ჟურნალში თითოეული მოთხოვნის შესრულების გეგმის ჩაწერა." -#: utils/misc/guc_tables.c:1333 +#: utils/misc/guc_tables.c:1417 msgid "Indents parse and plan tree displays." msgstr "" -#: utils/misc/guc_tables.c:1342 +#: utils/misc/guc_tables.c:1426 msgid "Writes parser performance statistics to the server log." msgstr "დამმუშავებლის წარმადობის სტატისტიკას სერვერის ჟურნალში ჩაწერს." -#: utils/misc/guc_tables.c:1351 +#: utils/misc/guc_tables.c:1435 msgid "Writes planner performance statistics to the server log." msgstr "დამგეგმავის წარმადობის სტატისტიკას სერვერის ჟურნალში ჩაწერს." -#: utils/misc/guc_tables.c:1360 +#: utils/misc/guc_tables.c:1444 msgid "Writes executor performance statistics to the server log." msgstr "შემსრულებლის წარმადობის სტატისტიკას სერვერის ჟურნალში ჩაწერს." -#: utils/misc/guc_tables.c:1369 +#: utils/misc/guc_tables.c:1453 msgid "Writes cumulative performance statistics to the server log." msgstr "საერთო წარმადობის სტატისტიკას სერვერის ჟურნალში ჩაწერს." -#: utils/misc/guc_tables.c:1379 +#: utils/misc/guc_tables.c:1463 msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations." msgstr "" -#: utils/misc/guc_tables.c:1391 +#: utils/misc/guc_tables.c:1475 msgid "Collects information about executing commands." msgstr "აგროვებს ინფორმაციას ბრძანებების შესრულების შესახებ." -#: utils/misc/guc_tables.c:1392 +#: utils/misc/guc_tables.c:1476 msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution." msgstr "" -#: utils/misc/guc_tables.c:1402 +#: utils/misc/guc_tables.c:1486 msgid "Collects statistics on database activity." msgstr "აგროვებს სტატისტიკას ბაზის აქტივობების შესახებ." -#: utils/misc/guc_tables.c:1411 +#: utils/misc/guc_tables.c:1495 +msgid "Collects timing statistics for cost-based vacuum delay." +msgstr "აგროვებს დროის სტატისტიკას ფასზე დამყარებული მომტვერსასრუტების დაყოვნებისთვის." + +#: utils/misc/guc_tables.c:1504 msgid "Collects timing statistics for database I/O activity." msgstr "აგროვებს ბაზის შეყვანა/გამოტანის აქტივობების დროით სტატისტიკას." -#: utils/misc/guc_tables.c:1420 +#: utils/misc/guc_tables.c:1513 msgid "Collects timing statistics for WAL I/O activity." msgstr "აგროვებს WAL-ის შეყვანა/გამოტანის აქტივობების დროით სტატისტიკას." -#: utils/misc/guc_tables.c:1430 +#: utils/misc/guc_tables.c:1523 msgid "Updates the process title to show the active SQL command." msgstr "განახლებს პროცესის სათაურს, რათა მან აქტიური SQL ბრძანება აჩვენოს." -#: utils/misc/guc_tables.c:1431 +#: utils/misc/guc_tables.c:1524 msgid "Enables updating of the process title every time a new SQL command is received by the server." msgstr "" -#: utils/misc/guc_tables.c:1440 +#: utils/misc/guc_tables.c:1533 msgid "Starts the autovacuum subprocess." msgstr "ავტომომტვერსასრუტების ქვეპროცესის გაშვება." -#: utils/misc/guc_tables.c:1450 +#: utils/misc/guc_tables.c:1543 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "LISTEN-ის და NOTIFY-ის გამართვის შეტყობინებების გენერაცია." -#: utils/misc/guc_tables.c:1462 +#: utils/misc/guc_tables.c:1555 msgid "Emits information about lock usage." msgstr "ბლოკის გამოყენების შესახებ ინფორმაციის გამოტანა." -#: utils/misc/guc_tables.c:1472 +#: utils/misc/guc_tables.c:1565 msgid "Emits information about user lock usage." msgstr "მომხმარებლის ბლოკის გამოყენების შესახებ ინფორმაციის გამოტანა." -#: utils/misc/guc_tables.c:1482 +#: utils/misc/guc_tables.c:1575 msgid "Emits information about lightweight lock usage." msgstr "მსუბუქი ბლოკის გამოყენების შესახებ ინფორმაციის გამოტანა." -#: utils/misc/guc_tables.c:1492 +#: utils/misc/guc_tables.c:1585 msgid "Dumps information about all current locks when a deadlock timeout occurs." msgstr "" -#: utils/misc/guc_tables.c:1504 +#: utils/misc/guc_tables.c:1597 msgid "Logs long lock waits." msgstr "ბლოკირების დიდხნიანია ლოდინის ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:1513 +#: utils/misc/guc_tables.c:1606 +msgid "Logs lock failures." +msgstr "ჩაწერს ჟურნალში დაბლოკვის ჩავარდნებს." + +#: utils/misc/guc_tables.c:1615 msgid "Logs standby recovery conflict waits." msgstr "მომლოდინის აღდგენის კონფლიქტის ლოდინების ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:1522 +#: utils/misc/guc_tables.c:1624 msgid "Logs the host name in the connection logs." msgstr "ჟურნალში ჰოსტის სახელის ჩაწერა." -#: utils/misc/guc_tables.c:1523 +#: utils/misc/guc_tables.c:1625 msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty." msgstr "" -#: utils/misc/guc_tables.c:1534 +#: utils/misc/guc_tables.c:1636 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "\"expr=NULL\" მიღებული იქნება, როგორც \"expr IS NULL\"." -#: utils/misc/guc_tables.c:1535 +#: utils/misc/guc_tables.c:1637 msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)." msgstr "" -#: utils/misc/guc_tables.c:1547 +#: utils/misc/guc_tables.c:1649 msgid "Sets the default read-only status of new transactions." msgstr "ახალი ტრანზაქციების მხოლოდ კითხვადობის სტატუსის ნაგულისხმევად დაყენება." -#: utils/misc/guc_tables.c:1557 +#: utils/misc/guc_tables.c:1659 msgid "Sets the current transaction's read-only status." msgstr "მიმდინარე ტრანზაქციის მხოლოდ-კითხვადობის სტატუსის დაყენება." -#: utils/misc/guc_tables.c:1567 +#: utils/misc/guc_tables.c:1669 msgid "Sets the default deferrable status of new transactions." msgstr "" -#: utils/misc/guc_tables.c:1576 +#: utils/misc/guc_tables.c:1678 msgid "Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures." msgstr "" -#: utils/misc/guc_tables.c:1586 -msgid "Enable row security." -msgstr "მწკრივების უსაფრთხოების ჩართვა." +#: utils/misc/guc_tables.c:1688 +msgid "Enables row security." +msgstr "ჩართავს მწკრივების უსაფრთხოებას." -#: utils/misc/guc_tables.c:1587 +#: utils/misc/guc_tables.c:1689 msgid "When enabled, row security will be applied to all users." msgstr "თუ ჩართავთ, მწკრივის უსაფრთხოება ყველა მომხმარებელზე გადატარდება." -#: utils/misc/guc_tables.c:1595 +#: utils/misc/guc_tables.c:1697 msgid "Check routine bodies during CREATE FUNCTION and CREATE PROCEDURE." msgstr "ქვეპროგრამის სხეულების შემოწმება CREATE FUNCTION-ის და CREATE PROCEDURE-ის დროს." -#: utils/misc/guc_tables.c:1604 -msgid "Enable input of NULL elements in arrays." +#: utils/misc/guc_tables.c:1706 +msgid "Enables input of NULL elements in arrays." msgstr "მასივებში NULL ტიპის ელემენტების შეყვანის ჩართვა." -#: utils/misc/guc_tables.c:1605 +#: utils/misc/guc_tables.c:1707 msgid "When turned on, unquoted NULL in an array input value means a null value; otherwise it is taken literally." msgstr "" -#: utils/misc/guc_tables.c:1621 +#: utils/misc/guc_tables.c:1723 msgid "WITH OIDS is no longer supported; this can only be false." msgstr "WITH OIDS მხარდაჭერილი აღარაა. ის ყოველთვის ნულის ტოლია." -#: utils/misc/guc_tables.c:1631 -msgid "Start a subprocess to capture stderr output and/or csvlogs into log files." +#: utils/misc/guc_tables.c:1733 +msgid "Start a subprocess to capture stderr, csvlog and/or jsonlog into log files." msgstr "" -#: utils/misc/guc_tables.c:1640 +#: utils/misc/guc_tables.c:1742 msgid "Truncate existing log files of same name during log rotation." msgstr "" -#: utils/misc/guc_tables.c:1651 +#: utils/misc/guc_tables.c:1752 msgid "Emit information about resource usage in sorting." msgstr "ინფორმაციის გამოტანა დალაგების მიერ რესურსების გამოყენების შესახებ." -#: utils/misc/guc_tables.c:1665 +#: utils/misc/guc_tables.c:1765 msgid "Generate debugging output for synchronized scanning." msgstr "სინქრონიზებული სკანირების შესახებ გამართვის ინფორმაციის გამოტანა." -#: utils/misc/guc_tables.c:1680 -msgid "Enable bounded sorting using heap sort." +#: utils/misc/guc_tables.c:1780 +msgid "Enables bounded sorting using heap sort." msgstr "" -#: utils/misc/guc_tables.c:1693 +#: utils/misc/guc_tables.c:1793 msgid "Emit WAL-related debugging output." msgstr "'WAL'-თან დაკავშირებული გამართვის ინფორმაციის გამოტანა." -#: utils/misc/guc_tables.c:1705 +#: utils/misc/guc_tables.c:1805 msgid "Shows whether datetimes are integer based." msgstr "აჩვენებს, არის თუ არა თარიღი და დრო მთელი რიცხვი." -#: utils/misc/guc_tables.c:1716 +#: utils/misc/guc_tables.c:1816 msgid "Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive." msgstr "იქნება Kerberos-ის და GSSAPI-ის მომხმარებლის სახელები რეგისტრზე-დამოკიდებული, თუ არა." -#: utils/misc/guc_tables.c:1726 +#: utils/misc/guc_tables.c:1826 msgid "Sets whether GSSAPI delegation should be accepted from the client." msgstr "მივიღებთ კლიენტიდან GSSAPI-ის დელეგაციას, თუ არა." -#: utils/misc/guc_tables.c:1736 +#: utils/misc/guc_tables.c:1836 msgid "Warn about backslash escapes in ordinary string literals." msgstr "" -#: utils/misc/guc_tables.c:1746 +#: utils/misc/guc_tables.c:1846 msgid "Causes '...' strings to treat backslashes literally." msgstr "" -#: utils/misc/guc_tables.c:1757 -msgid "Enable synchronized sequential scans." -msgstr "სინქრონული მიმდევრობითი სკანირებების ჩართვა." +#: utils/misc/guc_tables.c:1857 +msgid "Enables synchronized sequential scans." +msgstr "ჩართავს სინქრონული მიმდევრობითი სკანირებებს." -#: utils/misc/guc_tables.c:1767 +#: utils/misc/guc_tables.c:1867 msgid "Sets whether to include or exclude transaction with recovery target." msgstr "აყენებს იქნება ჩასმული ტრანზაქცია აღდგენის სამიზნესთან ერთად, თუ არა." -#: utils/misc/guc_tables.c:1777 +#: utils/misc/guc_tables.c:1877 msgid "Starts the WAL summarizer process to enable incremental backup." msgstr "" -#: utils/misc/guc_tables.c:1787 +#: utils/misc/guc_tables.c:1887 msgid "Allows connections and queries during recovery." msgstr "აღდგენისას მიერთებების და მოთხოვნების დაშვება." -#: utils/misc/guc_tables.c:1797 +#: utils/misc/guc_tables.c:1897 msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts." msgstr "" -#: utils/misc/guc_tables.c:1807 +#: utils/misc/guc_tables.c:1907 msgid "Shows whether hot standby is currently active." msgstr "აჩვენებს, ამჟამად ცხელი მომლოდინე აქტიურია, თუ არა." -#: utils/misc/guc_tables.c:1818 +#: utils/misc/guc_tables.c:1918 msgid "Allows modifications of the structure of system tables." msgstr "სისტემური ცხრილების სტრუქტურის ცვლილების დაშვება." -#: utils/misc/guc_tables.c:1829 +#: utils/misc/guc_tables.c:1929 msgid "Disables reading from system indexes." msgstr "სისტემური ინდექსებიდან კითხვის გამორთვა." -#: utils/misc/guc_tables.c:1830 +#: utils/misc/guc_tables.c:1930 msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness." msgstr "ის ინდექსების განახლებას ხელს არ უშლის, ასე რომ, გამოსაყენებლად უსაფრთხოა. ყველაზე ცუდი, რაც სჭირს, ნელია." -#: utils/misc/guc_tables.c:1841 +#: utils/misc/guc_tables.c:1941 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "გამოსაცდელად ცხრილის სივრცეების პირდაპირ ph_tblspc-ში დაშვება." -#: utils/misc/guc_tables.c:1852 +#: utils/misc/guc_tables.c:1952 msgid "Enables backward compatibility mode for privilege checks on large objects." msgstr "დიდი ობიექტების პრივილეგიების შემოწმების წინა ვერსიებთან თავსებადი რეჟიმის ჩართვა." -#: utils/misc/guc_tables.c:1853 +#: utils/misc/guc_tables.c:1953 msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0." msgstr "PostgreSQL-ის 9.0 და უფრო ძველ ვერსიებთან თავსებადობისთვის პრივილეგიების შემოწმების გამოტოვება, დიდი ობიექტების კითხვისა და შეცვლისას." -#: utils/misc/guc_tables.c:1863 +#: utils/misc/guc_tables.c:1963 msgid "When generating SQL fragments, quote all identifiers." msgstr "SQL ფრაგმენტების გენერაციისას ყველა იდენტიფიკატორის ბრჭყალებში ჩასმა." -#: utils/misc/guc_tables.c:1873 +#: utils/misc/guc_tables.c:1973 msgid "Shows whether data checksums are turned on for this cluster." msgstr "აჩვენებს, ამ კლასტერზე მონაცემების საკონტროლო ჯამები ჩართულია, თუ არა." -#: utils/misc/guc_tables.c:1884 +#: utils/misc/guc_tables.c:1984 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "დუბლირებული შეტყობინებების შეკვეცის თავიდან ასაცილებლად ჟურნალში გაგზავნილი შეტყობინებებისთვის მიმდევრობის ნომრის დამატება." -#: utils/misc/guc_tables.c:1894 +#: utils/misc/guc_tables.c:1994 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "Syslog-ისთვის გაგზავნილი შეტყობინებების დაჭრა და 1024 ბაიტში ჩატევა." -#: utils/misc/guc_tables.c:1904 +#: utils/misc/guc_tables.c:2004 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "" -#: utils/misc/guc_tables.c:1905 +#: utils/misc/guc_tables.c:2005 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "" -#: utils/misc/guc_tables.c:1915 +#: utils/misc/guc_tables.c:2015 msgid "Allow JIT compilation." msgstr "JIT კომპილაციის ჩართვა." -#: utils/misc/guc_tables.c:1926 +#: utils/misc/guc_tables.c:2026 msgid "Register JIT-compiled functions with debugger." msgstr "JIT-ით კომპილირებული ფუნქციების გამმართველთან რეგისტრაცია." -#: utils/misc/guc_tables.c:1943 +#: utils/misc/guc_tables.c:2043 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "" -#: utils/misc/guc_tables.c:1954 +#: utils/misc/guc_tables.c:2054 msgid "Allow JIT compilation of expressions." msgstr "გამოსახულებების JIT კომპილაციის დაშვება." -#: utils/misc/guc_tables.c:1965 +#: utils/misc/guc_tables.c:2065 msgid "Register JIT-compiled functions with perf profiler." msgstr "" -#: utils/misc/guc_tables.c:1982 +#: utils/misc/guc_tables.c:2082 msgid "Allow JIT compilation of tuple deforming." msgstr "კორტეჟის დეფორმაციის JIT კომპილაციის დაშვება." -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2093 msgid "Whether to continue running after a failure to sync data files." msgstr "გაგრძელდება მუშაობა მონაცემის ფაილების სინქრონიზაციის ჩავარდნის შემდეგ, თუ არა." -#: utils/misc/guc_tables.c:2002 +#: utils/misc/guc_tables.c:2102 msgid "Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured." msgstr "" -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2111 msgid "Enables event triggers." msgstr "ჩართავს მოვლენის ტრიგერებს." -#: utils/misc/guc_tables.c:2012 +#: utils/misc/guc_tables.c:2112 msgid "When enabled, event triggers will fire for all applicable statements." msgstr "" -#: utils/misc/guc_tables.c:2021 -msgid "Enables a physical standby to synchronize logical failover slots from the primary server." -msgstr "" +#: utils/misc/guc_tables.c:2121 +msgid "Enables a physical standby to synchronize logical failover replication slots from the primary server." +msgstr "საშუალებას აძლევს ფიზიკურ უქმეს სინქრონიზაციას ლოგიკური წარუმატებლობის რეპლიკაციის სლოტები პირველადი სერვერიდან." -#: utils/misc/guc_tables.c:2039 +#: utils/misc/guc_tables.c:2130 +msgid "Enables deprecation warnings for MD5 passwords." +msgstr "მოძველებულობის გაფრთხილებების ჩართვა MD5 პაროლებისთვის." + +#: utils/misc/guc_tables.c:2139 +msgid "Enables vacuum to truncate empty pages at the end of the table." +msgstr "უფლებას აძლევს მომტვერსასრუტებას, მოკვეთოს ცარიელი გვერდები ცხრილის ბოლოში." + +#: utils/misc/guc_tables.c:2157 msgid "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "" -#: utils/misc/guc_tables.c:2050 +#: utils/misc/guc_tables.c:2159 utils/misc/guc_tables.c:2313 utils/misc/guc_tables.c:2732 utils/misc/guc_tables.c:2743 utils/misc/guc_tables.c:2754 utils/misc/guc_tables.c:2765 utils/misc/guc_tables.c:2776 +msgid "0 disables the timeout." +msgstr "0 გამორთავს მოლოდინის ვადას." + +#: utils/misc/guc_tables.c:2168 msgid "Sets the amount of time to wait after authentication on connection startup." msgstr "" -#: utils/misc/guc_tables.c:2052 utils/misc/guc_tables.c:2774 +#: utils/misc/guc_tables.c:2170 utils/misc/guc_tables.c:2908 msgid "This allows attaching a debugger to the process." msgstr "პროცესისთვის გამმართველის მიბმის უფლების მიცემა." -#: utils/misc/guc_tables.c:2061 +#: utils/misc/guc_tables.c:2179 msgid "Sets the default statistics target." msgstr "სტატისტიკის ნაგულისხმევი სამიზნის დაყენება." -#: utils/misc/guc_tables.c:2062 +#: utils/misc/guc_tables.c:2180 msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS." msgstr "" -#: utils/misc/guc_tables.c:2071 +#: utils/misc/guc_tables.c:2189 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "" -#: utils/misc/guc_tables.c:2073 +#: utils/misc/guc_tables.c:2191 msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items." msgstr "" -#: utils/misc/guc_tables.c:2084 +#: utils/misc/guc_tables.c:2202 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "" -#: utils/misc/guc_tables.c:2086 +#: utils/misc/guc_tables.c:2204 msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result." msgstr "" -#: utils/misc/guc_tables.c:2097 +#: utils/misc/guc_tables.c:2215 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "" -#: utils/misc/guc_tables.c:2107 +#: utils/misc/guc_tables.c:2225 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "" -#: utils/misc/guc_tables.c:2117 +#: utils/misc/guc_tables.c:2235 msgid "GEQO: number of individuals in the population." msgstr "GEQO: ინდივიდების რაოდენობა პოპულაციაში." -#: utils/misc/guc_tables.c:2118 utils/misc/guc_tables.c:2128 -msgid "Zero selects a suitable default value." -msgstr "ნული შესაბამის ნაგულისხმევ მნიშვნელობას აირჩევს." +#: utils/misc/guc_tables.c:2236 utils/misc/guc_tables.c:2246 +msgid "0 means use a suitable default value." +msgstr "0 ნიშნავს შესაბამისი ნაგულისხმევი მნიშვნელობის გამოყენებას." -#: utils/misc/guc_tables.c:2127 +#: utils/misc/guc_tables.c:2245 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: ალგორითმის იტერაციების რაოდენობა." -#: utils/misc/guc_tables.c:2139 +#: utils/misc/guc_tables.c:2257 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "" -#: utils/misc/guc_tables.c:2150 +#: utils/misc/guc_tables.c:2268 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data." msgstr "" -#: utils/misc/guc_tables.c:2161 +#: utils/misc/guc_tables.c:2269 utils/misc/guc_tables.c:2280 +msgid "-1 means wait forever." +msgstr "-1 ნიშნავს უსაზღვროდ ლოდინს." + +#: utils/misc/guc_tables.c:2279 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data." msgstr "" -#: utils/misc/guc_tables.c:2172 +#: utils/misc/guc_tables.c:2290 msgid "Sets the minimum delay for applying changes during recovery." msgstr "აღდგენისას ცვლილებების გადატარების მინიმალური დაყოვნების დაყენება." -#: utils/misc/guc_tables.c:2183 +#: utils/misc/guc_tables.c:2301 msgid "Sets the maximum interval between WAL receiver status reports to the sending server." msgstr "" -#: utils/misc/guc_tables.c:2194 +#: utils/misc/guc_tables.c:2312 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "" -#: utils/misc/guc_tables.c:2205 +#: utils/misc/guc_tables.c:2323 msgid "Sets the maximum number of concurrent connections." msgstr "აყენებს ერთდროული შეერთებების მაქსიმალურ რაოდენობას." -#: utils/misc/guc_tables.c:2216 +#: utils/misc/guc_tables.c:2334 msgid "Sets the number of connection slots reserved for superusers." msgstr "აყენებს ზემომხმარებლებისთვის რეზერვირებული შეერთების სლოტებს." -#: utils/misc/guc_tables.c:2226 +#: utils/misc/guc_tables.c:2344 msgid "Sets the number of connection slots reserved for roles with privileges of pg_use_reserved_connections." msgstr "" -#: utils/misc/guc_tables.c:2237 +#: utils/misc/guc_tables.c:2355 msgid "Amount of dynamic shared memory reserved at startup." msgstr "გაშვებისას დარეზერვებული დინამიური გაზიარებული მეხსიერების რაოდენობა." -#: utils/misc/guc_tables.c:2252 +#: utils/misc/guc_tables.c:2370 msgid "Sets the number of shared memory buffers used by the server." msgstr "სერვერის მიერ გამოყენებული გაზიარებული მეხსიერების ბაფერების რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2263 +#: utils/misc/guc_tables.c:2381 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "ბუფერი პულის ზომა VACUUM, ANALYZE და ავტომომტვერსასრუტებისთვის." -#: utils/misc/guc_tables.c:2274 +#: utils/misc/guc_tables.c:2392 msgid "Shows the size of the server's main shared memory area (rounded up to the nearest MB)." msgstr "" -#: utils/misc/guc_tables.c:2285 +#: utils/misc/guc_tables.c:2403 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "" -#: utils/misc/guc_tables.c:2286 -msgid "-1 indicates that the value could not be determined." -msgstr "-1 ნიშნავს, რომ მნიშვნელობა ვერ განისაზღვრა." +#: utils/misc/guc_tables.c:2404 +msgid "-1 means huge pages are not supported." +msgstr "-1 ნიშნავს, რომ უზარმაზარი გვერდები მხარდაჭერილი არაა." -#: utils/misc/guc_tables.c:2296 +#: utils/misc/guc_tables.c:2414 +msgid "Shows the number of semaphores required for the server." +msgstr "აჩვენებს სერვერის მიერ გამოყენებული სემაფორების რაოდენობას." + +#: utils/misc/guc_tables.c:2425 msgid "Sets the size of the dedicated buffer pool used for the commit timestamp cache." msgstr "" -#: utils/misc/guc_tables.c:2297 utils/misc/guc_tables.c:2352 utils/misc/guc_tables.c:2363 -msgid "Specify 0 to have this value determined as a fraction of shared_buffers." -msgstr "" +#: utils/misc/guc_tables.c:2426 utils/misc/guc_tables.c:2481 utils/misc/guc_tables.c:2492 +msgid "0 means use a fraction of \"shared_buffers\"." +msgstr "0 ნიშნავს \"shared_buffers\"-ის ნაწილის გამოყენებას." -#: utils/misc/guc_tables.c:2307 +#: utils/misc/guc_tables.c:2436 msgid "Sets the size of the dedicated buffer pool used for the MultiXact member cache." msgstr "" -#: utils/misc/guc_tables.c:2318 +#: utils/misc/guc_tables.c:2447 msgid "Sets the size of the dedicated buffer pool used for the MultiXact offset cache." msgstr "" -#: utils/misc/guc_tables.c:2329 +#: utils/misc/guc_tables.c:2458 msgid "Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY message cache." msgstr "" -#: utils/misc/guc_tables.c:2340 +#: utils/misc/guc_tables.c:2469 msgid "Sets the size of the dedicated buffer pool used for the serializable transaction cache." msgstr "" -#: utils/misc/guc_tables.c:2351 -msgid "Sets the size of the dedicated buffer pool used for the sub-transaction cache." +#: utils/misc/guc_tables.c:2480 +msgid "Sets the size of the dedicated buffer pool used for the subtransaction cache." msgstr "" -#: utils/misc/guc_tables.c:2362 +#: utils/misc/guc_tables.c:2491 msgid "Sets the size of the dedicated buffer pool used for the transaction status cache." msgstr "" -#: utils/misc/guc_tables.c:2373 +#: utils/misc/guc_tables.c:2502 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "" -#: utils/misc/guc_tables.c:2384 +#: utils/misc/guc_tables.c:2513 msgid "Sets the TCP port the server listens on." msgstr "TCP პორტის მითითება, რომელზეც სერვერი უსმენს." -#: utils/misc/guc_tables.c:2394 +#: utils/misc/guc_tables.c:2523 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Unix-დომენის სოკეტზე წვდომის უფლებების დაყენება." -#: utils/misc/guc_tables.c:2395 +#: utils/misc/guc_tables.c:2524 msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "" -#: utils/misc/guc_tables.c:2409 +#: utils/misc/guc_tables.c:2538 msgid "Sets the file permissions for log files." msgstr "ჟურნალის ფაილების წვდომების დაყენება." -#: utils/misc/guc_tables.c:2410 +#: utils/misc/guc_tables.c:2539 msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "" -#: utils/misc/guc_tables.c:2424 +#: utils/misc/guc_tables.c:2553 msgid "Shows the mode of the data directory." msgstr "მონაცემების საქაღალდის წვდომის ჩვენება." -#: utils/misc/guc_tables.c:2425 +#: utils/misc/guc_tables.c:2554 msgid "The parameter value is a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "" -#: utils/misc/guc_tables.c:2438 +#: utils/misc/guc_tables.c:2567 msgid "Sets the maximum memory to be used for query workspaces." msgstr "მოთხოვნის სამუშაო სივრცის მიერ გამოყენებული მეხსიერების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2439 +#: utils/misc/guc_tables.c:2568 msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files." msgstr "" -#: utils/misc/guc_tables.c:2451 +#: utils/misc/guc_tables.c:2585 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "ტექნიკური ოპერაციებისთვის გამოყენებული მეხსიერების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2452 +#: utils/misc/guc_tables.c:2586 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "მოიცავს ისეთ ოპერაციებს, როგორებიცაა VACUUM და CREATE INDEX." -#: utils/misc/guc_tables.c:2462 +#: utils/misc/guc_tables.c:2596 msgid "Sets the maximum memory to be used for logical decoding." msgstr "ლოგიკური გაშიფვრისთვის გამოყენებული მეხსიერების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2463 +#: utils/misc/guc_tables.c:2597 msgid "This much memory can be used by each internal reorder buffer before spilling to disk." msgstr "" -#: utils/misc/guc_tables.c:2479 +#: utils/misc/guc_tables.c:2613 msgid "Sets the maximum stack depth, in kilobytes." msgstr "სტეკის მაქსიმალური სიღრმე კილობაიტებში." -#: utils/misc/guc_tables.c:2490 +#: utils/misc/guc_tables.c:2624 msgid "Limits the total size of all temporary files used by each process." msgstr "" -#: utils/misc/guc_tables.c:2491 +#: utils/misc/guc_tables.c:2625 msgid "-1 means no limit." msgstr "-1 ნიშნავს ლიმიტის გარეშე." -#: utils/misc/guc_tables.c:2501 +#: utils/misc/guc_tables.c:2635 msgid "Vacuum cost for a page found in the buffer cache." msgstr "ბაფერის ქეშში ნაპოვნი გვერდის მომტვერსასრუტების ფასი." -#: utils/misc/guc_tables.c:2511 +#: utils/misc/guc_tables.c:2645 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "ბაფერის ქეშში გვერდის მომტვერსასრუტების ფასი ნაპოვნი არაა." -#: utils/misc/guc_tables.c:2521 +#: utils/misc/guc_tables.c:2655 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "" -#: utils/misc/guc_tables.c:2531 +#: utils/misc/guc_tables.c:2665 msgid "Vacuum cost amount available before napping." msgstr "" -#: utils/misc/guc_tables.c:2541 +#: utils/misc/guc_tables.c:2675 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "" -#: utils/misc/guc_tables.c:2551 -msgid "Sets the maximum number of simultaneously open files for each server process." -msgstr "" +#: utils/misc/guc_tables.c:2676 +msgid "-1 means use \"vacuum_cost_limit\"." +msgstr "-1 ნიშნავს \"vacuum_cost_limit\"-ის გამოყენებას." + +#: utils/misc/guc_tables.c:2685 +msgid "Sets the maximum number of files each server process is allowed to open simultaneously." +msgstr "თითოეული სერვერის პროცესისთვის ერთდროულად გახსნილი ფაილების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2564 +#: utils/misc/guc_tables.c:2698 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "" -#: utils/misc/guc_tables.c:2575 +#: utils/misc/guc_tables.c:2709 msgid "Sets the minimum OID of tables for tracking locks." msgstr "" -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2710 msgid "Is used to avoid output on system tables." msgstr "გამოიყენება სისტემურ ცხრილებზე გამოტანის თავიდან ასაცილებლად." -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2719 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "" -#: utils/misc/guc_tables.c:2597 +#: utils/misc/guc_tables.c:2731 msgid "Sets the maximum allowed duration of any statement." msgstr "აყენებს ნებისმიერი გამოსახულების დაშვებულ მაქსიმალურ ხანგრძლივობას." -#: utils/misc/guc_tables.c:2598 utils/misc/guc_tables.c:2609 utils/misc/guc_tables.c:2620 utils/misc/guc_tables.c:2631 utils/misc/guc_tables.c:2642 -msgid "A value of 0 turns off the timeout." -msgstr "0 მოლოდინის ვადას გამორთავს." - -#: utils/misc/guc_tables.c:2608 +#: utils/misc/guc_tables.c:2742 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "აყენებს ბლოკირების ნებისმიერი მოლოდინისთვის დაშვებულ მაქსიმალურ ხანგრძლივობას." -#: utils/misc/guc_tables.c:2619 +#: utils/misc/guc_tables.c:2753 msgid "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "აყენებს მაქსიმალურ დაყოვნებას მოთხოვნებს შორის, როცა ის ტრანზაქციაშია." -#: utils/misc/guc_tables.c:2630 +#: utils/misc/guc_tables.c:2764 msgid "Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)." msgstr "აყენებს მაქსიმალურ დაშვებულ ხანგრძლივობას ნებისმიერი ტრანზაქციისთვის სესიის შიგნით (მომზადებული ტრანზაქცია არაა)." -#: utils/misc/guc_tables.c:2641 +#: utils/misc/guc_tables.c:2775 msgid "Sets the maximum allowed idle time between queries, when not in a transaction." msgstr "აყენებს მაქსიმალურ დაყოვნებას მოთხოვნებს შორის, როცა ის ტრანზაქციაში არაა." -#: utils/misc/guc_tables.c:2652 +#: utils/misc/guc_tables.c:2786 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "" -#: utils/misc/guc_tables.c:2662 +#: utils/misc/guc_tables.c:2796 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "" -#: utils/misc/guc_tables.c:2672 +#: utils/misc/guc_tables.c:2806 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "" -#: utils/misc/guc_tables.c:2682 +#: utils/misc/guc_tables.c:2816 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "" -#: utils/misc/guc_tables.c:2692 +#: utils/misc/guc_tables.c:2826 msgid "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "" -#: utils/misc/guc_tables.c:2701 +#: utils/misc/guc_tables.c:2835 msgid "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "" -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2848 msgid "Sets the maximum number of locks per transaction." msgstr "ტრანზაქციაში ბლოკების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:2715 +#: utils/misc/guc_tables.c:2849 msgid "The shared lock table is sized on the assumption that at most \"max_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." msgstr "" -#: utils/misc/guc_tables.c:2726 +#: utils/misc/guc_tables.c:2860 msgid "Sets the maximum number of predicate locks per transaction." msgstr "" -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2861 msgid "The shared predicate lock table is sized on the assumption that at most \"max_pred_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." msgstr "" -#: utils/misc/guc_tables.c:2738 +#: utils/misc/guc_tables.c:2872 msgid "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "" -#: utils/misc/guc_tables.c:2739 +#: utils/misc/guc_tables.c:2873 msgid "If more than this total of pages and tuples in the same relation are locked by a connection, those locks are replaced by a relation-level lock." msgstr "" -#: utils/misc/guc_tables.c:2749 +#: utils/misc/guc_tables.c:2883 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "" -#: utils/misc/guc_tables.c:2750 +#: utils/misc/guc_tables.c:2884 msgid "If more than this number of tuples on the same page are locked by a connection, those locks are replaced by a page-level lock." msgstr "" -#: utils/misc/guc_tables.c:2760 +#: utils/misc/guc_tables.c:2894 msgid "Sets the maximum allowed time to complete client authentication." msgstr "კლიენტის ავთენტიკაციის დასრულებისთვის დაშვებული მაქსიმალური დროის დაყენება." -#: utils/misc/guc_tables.c:2772 +#: utils/misc/guc_tables.c:2906 msgid "Sets the amount of time to wait before authentication on connection startup." msgstr "" -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2918 msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." msgstr "აყენებს გამოყოფილი გვერდების მაქსიმალურ რაოდენობას NOTIFY / LISTEN რიგისთვის." -#: utils/misc/guc_tables.c:2794 +#: utils/misc/guc_tables.c:2928 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "აღდგენისას WAL-ში წინასწარ-კითხვის ბაფერის ზომა." -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2929 msgid "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "" -#: utils/misc/guc_tables.c:2805 +#: utils/misc/guc_tables.c:2939 msgid "Sets the size of WAL files held for standby servers." msgstr "მომლოდინე სერვერებისთვის WAL ფაილებისთვის შენახული ზომის დაყენება." -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2950 msgid "Sets the minimum size to shrink the WAL to." msgstr "WAL-ის შემცირების მინიმალური ზომის დაყენება." -#: utils/misc/guc_tables.c:2828 +#: utils/misc/guc_tables.c:2962 msgid "Sets the WAL size that triggers a checkpoint." msgstr "აყენებს WAL-ის ზომას, რომელიც საკონტროლო წერტილს ატრიგერებს." -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2974 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "ავტომატური WAL საკონტროლო წერტილებს შორის მაქსიმალური დროის დაყენება." -#: utils/misc/guc_tables.c:2851 +#: utils/misc/guc_tables.c:2985 msgid "Sets the maximum time before warning if checkpoints triggered by WAL volume happen too frequently." msgstr "" -#: utils/misc/guc_tables.c:2853 -msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. Zero turns off the warning." +#: utils/misc/guc_tables.c:2987 +msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. 0 disables the warning." msgstr "" -#: utils/misc/guc_tables.c:2866 utils/misc/guc_tables.c:3084 utils/misc/guc_tables.c:3138 +#: utils/misc/guc_tables.c:3000 utils/misc/guc_tables.c:3230 utils/misc/guc_tables.c:3322 msgid "Number of pages after which previously performed writes are flushed to disk." msgstr "" -#: utils/misc/guc_tables.c:2877 -msgid "Sets the number of disk-page buffers in shared memory for WAL." +#: utils/misc/guc_tables.c:3001 utils/misc/guc_tables.c:3231 utils/misc/guc_tables.c:3323 +msgid "0 disables forced writeback." msgstr "" -#: utils/misc/guc_tables.c:2878 -msgid "Specify -1 to have this value determined as a fraction of shared_buffers." +#: utils/misc/guc_tables.c:3011 +msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "" -#: utils/misc/guc_tables.c:2888 +#: utils/misc/guc_tables.c:3012 +msgid "-1 means use a fraction of \"shared_buffers\"." +msgstr "-1 ნიშნავს \"shared_buffers\"-ის ნაწილის გამოყენებას." + +#: utils/misc/guc_tables.c:3022 msgid "Time between WAL flushes performed in the WAL writer." msgstr "" -#: utils/misc/guc_tables.c:2899 +#: utils/misc/guc_tables.c:3033 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "" -#: utils/misc/guc_tables.c:2910 +#: utils/misc/guc_tables.c:3044 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "" -#: utils/misc/guc_tables.c:2921 +#: utils/misc/guc_tables.c:3055 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "" -#: utils/misc/guc_tables.c:2932 +#: utils/misc/guc_tables.c:3066 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "" -#: utils/misc/guc_tables.c:2942 +#: utils/misc/guc_tables.c:3076 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "" -#: utils/misc/guc_tables.c:2943 -msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk." +#: utils/misc/guc_tables.c:3077 +msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk. -1 means no maximum." msgstr "" -#: utils/misc/guc_tables.c:2955 +#: utils/misc/guc_tables.c:3089 msgid "Sets the maximum time to wait for WAL replication." msgstr "WAL რეპლიკაციის მოლოდინის მაქსიმალური ვადის დაყენება." -#: utils/misc/guc_tables.c:2966 +#: utils/misc/guc_tables.c:3100 +msgid "Sets the duration a replication slot can remain idle before it is invalidated." +msgstr "" + +#: utils/misc/guc_tables.c:3112 msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk." msgstr "" -#: utils/misc/guc_tables.c:2978 +#: utils/misc/guc_tables.c:3124 msgid "Sets the minimum number of concurrent open transactions required before performing \"commit_delay\"." msgstr "დააყენებს \"commit_delay\"-ის შესრულებამდე საჭირო ერთდროული ღია ტრანზაქციების მინიმალურ რაოდენობას." -#: utils/misc/guc_tables.c:2989 +#: utils/misc/guc_tables.c:3135 msgid "Sets the number of digits displayed for floating-point values." msgstr "" -#: utils/misc/guc_tables.c:2990 +#: utils/misc/guc_tables.c:3136 msgid "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than zero selects precise output mode." msgstr "" -#: utils/misc/guc_tables.c:3002 -msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by log_statement_sample_rate." +#: utils/misc/guc_tables.c:3148 +msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by \"log_statement_sample_rate\"." msgstr "" -#: utils/misc/guc_tables.c:3005 -msgid "Zero logs a sample of all queries. -1 turns this feature off." +#: utils/misc/guc_tables.c:3151 +msgid "-1 disables sampling. 0 means sample all statements." msgstr "" -#: utils/misc/guc_tables.c:3015 +#: utils/misc/guc_tables.c:3161 msgid "Sets the minimum execution time above which all statements will be logged." msgstr "" -#: utils/misc/guc_tables.c:3017 -msgid "Zero prints all queries. -1 turns this feature off." -msgstr "0-ს ყველა მოთხოვნა გამოაქვს, -1 გამორთავს ამ ფუნქციას." +#: utils/misc/guc_tables.c:3163 +msgid "-1 disables logging statement durations. 0 means log all statement durations." +msgstr "" -#: utils/misc/guc_tables.c:3027 +#: utils/misc/guc_tables.c:3173 msgid "Sets the minimum execution time above which autovacuum actions will be logged." msgstr "" -#: utils/misc/guc_tables.c:3029 -msgid "Zero prints all actions. -1 turns autovacuum logging off." -msgstr "0-ს ყველა ქმედება გამოაქვს. -1 გამორთავს ავტომომტვერსასრუტებას." +#: utils/misc/guc_tables.c:3175 +msgid "-1 disables logging autovacuum actions. 0 means log all autovacuum actions." +msgstr "" -#: utils/misc/guc_tables.c:3039 +#: utils/misc/guc_tables.c:3185 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements." msgstr "" -#: utils/misc/guc_tables.c:3041 utils/misc/guc_tables.c:3053 -msgid "-1 to print values in full." -msgstr "-1 მნიშვნელობების სრულად გამოსატანად." +#: utils/misc/guc_tables.c:3187 utils/misc/guc_tables.c:3199 +msgid "-1 means log values in full." +msgstr "-1 მნიშვნელობების ჟურნალში სრულად ჩაწერას." -#: utils/misc/guc_tables.c:3051 +#: utils/misc/guc_tables.c:3197 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements, on error." msgstr "" -#: utils/misc/guc_tables.c:3063 +#: utils/misc/guc_tables.c:3209 msgid "Background writer sleep time between rounds." msgstr "" -#: utils/misc/guc_tables.c:3074 +#: utils/misc/guc_tables.c:3220 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "" -#: utils/misc/guc_tables.c:3097 +#: utils/misc/guc_tables.c:3221 +msgid "0 disables background writing." +msgstr "0 გამორთავს ფონურ ჩაწერას." + +#: utils/misc/guc_tables.c:3243 msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem." msgstr "" -#: utils/misc/guc_tables.c:3111 +#: utils/misc/guc_tables.c:3244 utils/misc/guc_tables.c:3258 +msgid "0 disables simultaneous requests." +msgstr "0 გამორთავს ერთდროულ მოთხოვნებს." + +#: utils/misc/guc_tables.c:3257 msgid "A variant of \"effective_io_concurrency\" that is used for maintenance work." +msgstr "\"effective_io_concurency\"-ის ვარიანტი, რომელიც სარემონტო სამუშაოებისთვის გამოიყენება." + +#: utils/misc/guc_tables.c:3272 +msgid "Server-wide limit that clamps io_combine_limit." msgstr "" -#: utils/misc/guc_tables.c:3126 +#: utils/misc/guc_tables.c:3286 msgid "Limit on the size of data reads and writes." msgstr "" -#: utils/misc/guc_tables.c:3151 +#: utils/misc/guc_tables.c:3300 +msgid "Max number of IOs that one process can execute simultaneously." +msgstr "" + +#: utils/misc/guc_tables.c:3312 +msgid "Number of IO worker processes, for io_method=worker." +msgstr "" + +#: utils/misc/guc_tables.c:3335 msgid "Maximum number of concurrent worker processes." msgstr "ერთდროულად გაშვებული დამხმარე პროცესების მაქსიმალური რაოდენობა." -#: utils/misc/guc_tables.c:3163 +#: utils/misc/guc_tables.c:3347 msgid "Maximum number of logical replication worker processes." msgstr "ლოგიკური რეპლიკაციის დამხმარე პროცესების მაქსიმალური რაოდენობა." -#: utils/misc/guc_tables.c:3175 +#: utils/misc/guc_tables.c:3359 msgid "Maximum number of table synchronization workers per subscription." msgstr "თითოეული გამოწერის ცხრილის სინქრონიზაციის დამხმარე პროცესების მაქსიმალური რაოდენობა." -#: utils/misc/guc_tables.c:3187 +#: utils/misc/guc_tables.c:3371 msgid "Maximum number of parallel apply workers per subscription." msgstr "თითოეული გამოწერის პარალელური გადატარების დამხმარე პროცესების მაქსიმალური რაოდენობა." -#: utils/misc/guc_tables.c:3197 +#: utils/misc/guc_tables.c:3383 +msgid "Sets the maximum number of active replication origins." +msgstr "აყენებს აქტიური რეპლიკაციის ძრავების მაქსიმალურ რაოდენობას." + +#: utils/misc/guc_tables.c:3393 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "" -#: utils/misc/guc_tables.c:3209 +#: utils/misc/guc_tables.c:3395 +msgid "0 disables time-based creation of new log files." +msgstr "" + +#: utils/misc/guc_tables.c:3405 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "" -#: utils/misc/guc_tables.c:3221 +#: utils/misc/guc_tables.c:3407 +msgid "0 disables size-based creation of new log files." +msgstr "" + +#: utils/misc/guc_tables.c:3417 msgid "Shows the maximum number of function arguments." msgstr "ფუნქციის არგუმენტების მაქსიმალური რაოდენობის ჩვენება." -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3428 msgid "Shows the maximum number of index keys." msgstr "ინდექსის გასაღებების მაქსიმალური რაოდენობის ჩვენება." -#: utils/misc/guc_tables.c:3243 +#: utils/misc/guc_tables.c:3439 msgid "Shows the maximum identifier length." msgstr "იდენტიფიკატორის მაქსიმალური სიგრძის ჩვენება." -#: utils/misc/guc_tables.c:3254 +#: utils/misc/guc_tables.c:3450 msgid "Shows the size of a disk block." msgstr "დისკის ბლოკის ზომის ჩვენება." -#: utils/misc/guc_tables.c:3265 +#: utils/misc/guc_tables.c:3461 msgid "Shows the number of pages per disk file." msgstr "ფაილში არსებული გვერდების რაოდენობის ჩვენება." -#: utils/misc/guc_tables.c:3276 +#: utils/misc/guc_tables.c:3472 msgid "Shows the block size in the write ahead log." msgstr "წინასწარ-ჩაწერადი ჟურნალის ბლოკის ზომის ჩვენება." -#: utils/misc/guc_tables.c:3287 +#: utils/misc/guc_tables.c:3483 msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "" -#: utils/misc/guc_tables.c:3299 +#: utils/misc/guc_tables.c:3495 msgid "Shows the size of write ahead log segments." msgstr "წინასწარ-ჩაწერადი ჟურნალის სეგმენტების ზომის ჩვენება." -#: utils/misc/guc_tables.c:3312 +#: utils/misc/guc_tables.c:3508 msgid "Time for which WAL summary files should be kept." msgstr "" -#: utils/misc/guc_tables.c:3325 +#: utils/misc/guc_tables.c:3509 +msgid "0 disables automatic summary file deletion." +msgstr "" + +#: utils/misc/guc_tables.c:3521 msgid "Time to sleep between autovacuum runs." msgstr "ძილის დრო ავტომომტვერსასრუტებების გაშვებებს შორის." -#: utils/misc/guc_tables.c:3335 +#: utils/misc/guc_tables.c:3531 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "" -#: utils/misc/guc_tables.c:3344 -msgid "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums." +#: utils/misc/guc_tables.c:3540 +msgid "Maximum number of tuple updates or deletes prior to vacuum." +msgstr "" + +#: utils/misc/guc_tables.c:3541 +msgid "-1 disables the maximum threshold." +msgstr "-1 გამორთავს მაქსიმალურ ზღვარს." + +#: utils/misc/guc_tables.c:3549 +msgid "Minimum number of tuple inserts prior to vacuum." msgstr "" -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3550 +msgid "-1 disables insert vacuums." +msgstr "-1 გამორთავს ვაკუუმების ჩასმას." + +#: utils/misc/guc_tables.c:3558 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "" -#: utils/misc/guc_tables.c:3363 +#: utils/misc/guc_tables.c:3568 msgid "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "" -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3580 msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "" -#: utils/misc/guc_tables.c:3385 +#: utils/misc/guc_tables.c:3590 +msgid "Sets the number of backend slots to allocate for autovacuum workers." +msgstr "აყენებს უკანაბოლოს სლოტების რაოდენობას გამოსაყოფად ავტომომტვერსასრუტების დამხმარე პროცესებისთვის." + +#: utils/misc/guc_tables.c:3599 msgid "Sets the maximum number of simultaneously running autovacuum worker processes." msgstr "ერთდროულად გაშვებული ავტომომტვერსასრუტების დამხმარე პროცესების რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:3395 +#: utils/misc/guc_tables.c:3609 msgid "Sets the maximum number of parallel processes per maintenance operation." msgstr "თითოეული რემონტის ოპერაციისთვის პარალელური პროცესების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:3405 +#: utils/misc/guc_tables.c:3619 msgid "Sets the maximum number of parallel processes per executor node." msgstr "თითოეული შემსრულებელი კვანძისთვის პარალელურად გაშვებული პროცესების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:3416 +#: utils/misc/guc_tables.c:3630 msgid "Sets the maximum number of parallel workers that can be active at one time." msgstr "ერთდროულად აქტიური პარალელური დამხმარე პროცესების მაქსიმალური რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:3427 +#: utils/misc/guc_tables.c:3641 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "თითოეული ავტომომტვერსასრუტების დამხმარე პროცესის მიერ გამოყენებული მაქსიმალური მეხსიერების რაოდენობის დაყენება." -#: utils/misc/guc_tables.c:3438 +#: utils/misc/guc_tables.c:3642 +msgid "-1 means use \"maintenance_work_mem\"." +msgstr "-1 ნიშნავს \"maintenance_work_mem\"-ის გამოყენებას." + +#: utils/misc/guc_tables.c:3652 msgid "Time between issuing TCP keepalives." msgstr "დაყოვნება TCP keepalive პაკეტებს შორის." -#: utils/misc/guc_tables.c:3439 utils/misc/guc_tables.c:3450 utils/misc/guc_tables.c:3574 -msgid "A value of 0 uses the system default." -msgstr "სისტემური ნაგულისხმევი მნიშვნელობის გამოსაყენებლად მიუთითეთ 0." +#: utils/misc/guc_tables.c:3653 utils/misc/guc_tables.c:3664 utils/misc/guc_tables.c:3787 utils/misc/guc_tables.c:3798 +msgid "0 means use the system default." +msgstr "0 ნიშნავს სისტემის ნაგულისხმევის გამოყენებას." -#: utils/misc/guc_tables.c:3449 +#: utils/misc/guc_tables.c:3663 msgid "Time between TCP keepalive retransmits." msgstr "დაყოვნება TCP keepalive პაკეტების გადაგზავნებს შორის." -#: utils/misc/guc_tables.c:3460 +#: utils/misc/guc_tables.c:3674 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "SSL-ის თავიდან დაყენება უკვე მხარდაუჭერელია. შეგიძლიათ დააყენოთ მხოლოდ 0." -#: utils/misc/guc_tables.c:3471 +#: utils/misc/guc_tables.c:3685 msgid "Maximum number of TCP keepalive retransmits." msgstr "TCP Keepalive-ების გადაგზავნის მაქსიმალური რაოდენობა." -#: utils/misc/guc_tables.c:3472 -msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default." +#: utils/misc/guc_tables.c:3686 +msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. 0 means use the system default." msgstr "" -#: utils/misc/guc_tables.c:3483 +#: utils/misc/guc_tables.c:3697 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "" -#: utils/misc/guc_tables.c:3494 +#: utils/misc/guc_tables.c:3698 +msgid "0 means no limit." +msgstr "0 ნიშნავს უსაზღვროს." + +#: utils/misc/guc_tables.c:3707 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "" -#: utils/misc/guc_tables.c:3495 +#: utils/misc/guc_tables.c:3708 msgid "That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each." msgstr "" -#: utils/misc/guc_tables.c:3506 +#: utils/misc/guc_tables.c:3719 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "ცხრილის მონაცემების მინიმალური რაოდენობა პარალელური სკანირებისთვის." -#: utils/misc/guc_tables.c:3507 +#: utils/misc/guc_tables.c:3720 msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered." msgstr "" -#: utils/misc/guc_tables.c:3517 +#: utils/misc/guc_tables.c:3730 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "" -#: utils/misc/guc_tables.c:3518 +#: utils/misc/guc_tables.c:3731 msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered." msgstr "" -#: utils/misc/guc_tables.c:3529 +#: utils/misc/guc_tables.c:3742 msgid "Shows the server version as an integer." msgstr "სერვერის ვერსიას, როგორც მთელ რიცხვს, ისე აჩვენებს." -#: utils/misc/guc_tables.c:3540 +#: utils/misc/guc_tables.c:3753 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "მითითებული რაოდენობა კილობაიტზე უფრო დიდი დროებითი ფაილების გამოყენების ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:3541 -msgid "Zero logs all files. The default is -1 (turning this feature off)." -msgstr "" +#: utils/misc/guc_tables.c:3754 +msgid "-1 disables logging temporary files. 0 means log all temporary files." +msgstr "-1 გათიშავს დროებით ფაილების ჟურნალში ჩაწერას. 0 ნიშნავს ყველა დროებითი ფაილის ჟურნალში ჩაწერას." -#: utils/misc/guc_tables.c:3551 +#: utils/misc/guc_tables.c:3764 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "'pg_stat_activity.query'-სთვის დაცული მეხსიერების ზომის დაყნება, ბაიტებში." -#: utils/misc/guc_tables.c:3562 +#: utils/misc/guc_tables.c:3775 msgid "Sets the maximum size of the pending list for GIN index." msgstr "" -#: utils/misc/guc_tables.c:3573 +#: utils/misc/guc_tables.c:3786 msgid "TCP user timeout." msgstr "TCP მომხმარებლის ლოდინის ვადა." -#: utils/misc/guc_tables.c:3584 +#: utils/misc/guc_tables.c:3797 msgid "The size of huge page that should be requested." msgstr "მოსათხოვი უზარმაზარი გვერდების (hugepages) ზომა." -#: utils/misc/guc_tables.c:3595 +#: utils/misc/guc_tables.c:3808 msgid "Aggressively flush system caches for debugging purposes." msgstr "" -#: utils/misc/guc_tables.c:3618 +#: utils/misc/guc_tables.c:3809 +msgid "0 means use normal caching behavior." +msgstr "" + +#: utils/misc/guc_tables.c:3831 msgid "Sets the time interval between checks for disconnection while running queries." msgstr "" -#: utils/misc/guc_tables.c:3629 +#: utils/misc/guc_tables.c:3832 +msgid "0 disables connection checks." +msgstr "0 კავშირის შემოწმებას გამორთავს." + +#: utils/misc/guc_tables.c:3842 msgid "Time between progress updates for long-running startup operations." msgstr "" -#: utils/misc/guc_tables.c:3631 -msgid "0 turns this feature off." -msgstr "0 გამორთავს ამ ფუნქციას." +#: utils/misc/guc_tables.c:3844 +msgid "0 disables progress updates." +msgstr "" -#: utils/misc/guc_tables.c:3641 +#: utils/misc/guc_tables.c:3854 msgid "Sets the iteration count for SCRAM secret generation." msgstr "აყენებს იტერაციების რიცხვს SCRAM-ის პაროლის გენერაციისთვის." -#: utils/misc/guc_tables.c:3661 +#: utils/misc/guc_tables.c:3874 msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "" -#: utils/misc/guc_tables.c:3672 +#: utils/misc/guc_tables.c:3885 msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page." msgstr "" -#: utils/misc/guc_tables.c:3683 +#: utils/misc/guc_tables.c:3896 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "" -#: utils/misc/guc_tables.c:3694 +#: utils/misc/guc_tables.c:3907 msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan." msgstr "" -#: utils/misc/guc_tables.c:3705 +#: utils/misc/guc_tables.c:3918 msgid "Sets the planner's estimate of the cost of processing each operator or function call." msgstr "" -#: utils/misc/guc_tables.c:3716 +#: utils/misc/guc_tables.c:3929 msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to leader backend." msgstr "" -#: utils/misc/guc_tables.c:3727 +#: utils/misc/guc_tables.c:3940 msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query." msgstr "" -#: utils/misc/guc_tables.c:3739 +#: utils/misc/guc_tables.c:3952 msgid "Perform JIT compilation if query is more expensive." msgstr "თუ მოთხოვნა უფრო ძვირია, JIT კომპილაციის შესრულება." -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3953 msgid "-1 disables JIT compilation." msgstr "-1 JIT კომპილაციას გამორთავს." -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3963 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "" -#: utils/misc/guc_tables.c:3751 +#: utils/misc/guc_tables.c:3964 msgid "-1 disables optimization." msgstr "-1 ოპტიმიზაციას გამორთავს." -#: utils/misc/guc_tables.c:3761 +#: utils/misc/guc_tables.c:3974 msgid "Perform JIT inlining if query is more expensive." msgstr "" -#: utils/misc/guc_tables.c:3762 +#: utils/misc/guc_tables.c:3975 msgid "-1 disables inlining." msgstr "-1 გამორთავს კოდის ჩადგმას." -#: utils/misc/guc_tables.c:3772 +#: utils/misc/guc_tables.c:3985 msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." msgstr "" -#: utils/misc/guc_tables.c:3784 +#: utils/misc/guc_tables.c:3997 msgid "Sets the planner's estimate of the average size of a recursive query's working table." msgstr "" -#: utils/misc/guc_tables.c:3796 +#: utils/misc/guc_tables.c:4009 msgid "GEQO: selective pressure within the population." msgstr "GEQO: შერჩევითი ზეწოლა პოპულაციაში." -#: utils/misc/guc_tables.c:3807 +#: utils/misc/guc_tables.c:4020 msgid "GEQO: seed for random path selection." msgstr "" -#: utils/misc/guc_tables.c:3818 +#: utils/misc/guc_tables.c:4031 msgid "Multiple of \"work_mem\" to use for hash tables." msgstr "" -#: utils/misc/guc_tables.c:3829 +#: utils/misc/guc_tables.c:4042 msgid "Multiple of the average buffer usage to free per round." msgstr "" -#: utils/misc/guc_tables.c:3839 +#: utils/misc/guc_tables.c:4052 msgid "Sets the seed for random-number generation." -msgstr "" +msgstr "აყენებს თესლს შემთხვევითი რიცხვების გენერაციისთვის." -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:4063 msgid "Vacuum cost delay in milliseconds." msgstr "დამტვერსასრუტების დაყოვნება მილიწამებში." -#: utils/misc/guc_tables.c:3861 +#: utils/misc/guc_tables.c:4074 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "დამტვერსასრუტების დაყოვნება მილიწამებში, ავტოდამტვერსასრუტებისთვის." -#: utils/misc/guc_tables.c:3872 +#: utils/misc/guc_tables.c:4075 +msgid "-1 means use \"vacuum_cost_delay\"." +msgstr "-1 ნიშნავს \"vacuum_cost_delay\"-ის გამოყენებას." + +#: utils/misc/guc_tables.c:4085 msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples." msgstr "" -#: utils/misc/guc_tables.c:3882 +#: utils/misc/guc_tables.c:4095 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "" -#: utils/misc/guc_tables.c:3892 +#: utils/misc/guc_tables.c:4105 msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples." msgstr "" -#: utils/misc/guc_tables.c:3902 +#: utils/misc/guc_tables.c:4115 msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval." msgstr "" -#: utils/misc/guc_tables.c:3912 +#: utils/misc/guc_tables.c:4125 msgid "Fraction of statements exceeding \"log_min_duration_sample\" to be logged." msgstr "" -#: utils/misc/guc_tables.c:3913 +#: utils/misc/guc_tables.c:4126 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "გამოიყენეთ მნიშვნელობები 0.0-დან (არასოდეს ჩაწერო ჟურნალში) და 1.0-ს (ჟურნალში ყოველთვის ჩაწერა) შუა." -#: utils/misc/guc_tables.c:3922 +#: utils/misc/guc_tables.c:4135 msgid "Sets the fraction of transactions from which to log all statements." msgstr "ადგენს ტრანზაქციის ნაწილს, რომლის შემდეგაც ყველა ოპერატორი ჟურნალში ჩაიწერება." -#: utils/misc/guc_tables.c:3923 +#: utils/misc/guc_tables.c:4136 msgid "Use a value between 0.0 (never log) and 1.0 (log all statements for all transactions)." msgstr "" -#: utils/misc/guc_tables.c:3942 +#: utils/misc/guc_tables.c:4146 +msgid "Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning." +msgstr "" + +#: utils/misc/guc_tables.c:4147 +msgid "A value of 0.0 disables eager scanning and a value of 1.0 will eagerly scan up to 100 percent of the all-visible pages in the relation. If vacuum successfully freezes these pages, the cap is lower than 100 percent, because the goal is to amortize page freezing across multiple vacuums." +msgstr "" + +#: utils/misc/guc_tables.c:4165 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "" -#: utils/misc/guc_tables.c:3943 -msgid "This is used only if \"archive_library\" is not set." +#: utils/misc/guc_tables.c:4166 +msgid "An empty string means use \"archive_library\"." msgstr "" -#: utils/misc/guc_tables.c:3952 +#: utils/misc/guc_tables.c:4175 msgid "Sets the library that will be called to archive a WAL file." msgstr "" -#: utils/misc/guc_tables.c:3953 -msgid "An empty string indicates that \"archive_command\" should be used." -msgstr "" +#: utils/misc/guc_tables.c:4176 +msgid "An empty string means use \"archive_command\"." +msgstr "ცარიელი სტრიქონი ნიშნავს \"archive_command\"-ის გამოყენებას." -#: utils/misc/guc_tables.c:3962 +#: utils/misc/guc_tables.c:4185 msgid "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "არქივირებული WAL ფაილის მისაღებად გამოსაძახებელი გარსის ბრძანების დაყენება." -#: utils/misc/guc_tables.c:3972 +#: utils/misc/guc_tables.c:4195 msgid "Sets the shell command that will be executed at every restart point." msgstr "ყოველ გადატვირთვის წერტილზე გასაშვები გარსის ბრძანების დაყენება." -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4205 msgid "Sets the shell command that will be executed once at the end of recovery." msgstr "" -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4215 msgid "Specifies the timeline to recover into." msgstr "აღდგენისთვის დროის მითითება." -#: utils/misc/guc_tables.c:4002 +#: utils/misc/guc_tables.c:4225 msgid "Set to \"immediate\" to end recovery as soon as a consistent state is reached." msgstr "" -#: utils/misc/guc_tables.c:4011 +#: utils/misc/guc_tables.c:4234 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "ტრანზაქციის ID, რომლამდეც აღდგენა მოხდება." -#: utils/misc/guc_tables.c:4020 +#: utils/misc/guc_tables.c:4243 msgid "Sets the time stamp up to which recovery will proceed." msgstr "" -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4252 msgid "Sets the named restore point up to which recovery will proceed." msgstr "" -#: utils/misc/guc_tables.c:4038 +#: utils/misc/guc_tables.c:4261 msgid "Sets the LSN of the write-ahead log location up to which recovery will proceed." msgstr "" -#: utils/misc/guc_tables.c:4048 +#: utils/misc/guc_tables.c:4271 msgid "Sets the connection string to be used to connect to the sending server." msgstr "" -#: utils/misc/guc_tables.c:4059 +#: utils/misc/guc_tables.c:4282 msgid "Sets the name of the replication slot to use on the sending server." msgstr "" -#: utils/misc/guc_tables.c:4069 +#: utils/misc/guc_tables.c:4292 msgid "Sets the client's character set encoding." msgstr "კლიენტის სიმბოლოების კოდირების დაყენება." -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4303 msgid "Controls information prefixed to each log line." msgstr "ჟურნალის თითოეული ჩანაწერის პრეფიქსის კონტროლი." -#: utils/misc/guc_tables.c:4081 -msgid "If blank, no prefix is used." -msgstr "თუ ცარიელია, პრეფიქსი არ გამოიყენება." +#: utils/misc/guc_tables.c:4304 +msgid "An empty string means no prefix." +msgstr "" -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4313 msgid "Sets the time zone to use in log messages." msgstr "ჟურნალის შეტყობინებების დასამახსოვრებლად გამოყენებული დროის სარტყლის დაყენება." -#: utils/misc/guc_tables.c:4100 +#: utils/misc/guc_tables.c:4323 msgid "Sets the display format for date and time values." msgstr "თარიღისა და დროის მნიშვნელობების ფორმატის დაყენება." -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4324 msgid "Also controls interpretation of ambiguous date inputs." msgstr "" -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4335 msgid "Sets the default table access method for new tables." msgstr "ახალი ცხრილების ნაგულისხმევი წვდომის უფლებების მითითება." -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4346 msgid "Sets the default tablespace to create tables and indexes in." msgstr "" -#: utils/misc/guc_tables.c:4124 -msgid "An empty string selects the database's default tablespace." -msgstr "ცარიელი სტრიქონი ბაზის ნაგულისხმევ ცხრილების სივრცეს აირჩევს." +#: utils/misc/guc_tables.c:4347 utils/misc/guc_tables.c:4358 +msgid "An empty string means use the database's default tablespace." +msgstr "ცარიელი სტრიქონი ბაზის ნაგულისხმევ ცხრილების სივრცეს ნიშნავს." -#: utils/misc/guc_tables.c:4134 +#: utils/misc/guc_tables.c:4357 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "" -#: utils/misc/guc_tables.c:4145 +#: utils/misc/guc_tables.c:4368 msgid "Sets whether a CREATEROLE user automatically grants the role to themselves, and with which options." msgstr "" -#: utils/misc/guc_tables.c:4157 +#: utils/misc/guc_tables.c:4370 +msgid "An empty string disables automatic self grants." +msgstr "" + +#: utils/misc/guc_tables.c:4380 msgid "Sets the path for dynamically loadable modules." msgstr "დინამიურად ჩატვირთული მოდულების ბილიკის დაყენება." -#: utils/misc/guc_tables.c:4158 +#: utils/misc/guc_tables.c:4381 msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file." msgstr "თუ საჭიროა დინამიურად ჩატვირთვადი მოდულის გახსნა და მითითებულ სახელს არ გააჩნია საქაღალდის კომპონენტი (ანუ სახელი არ შეიცავს დახრილ ხაზს), სისტემა მითითებულ ფაილს ამ ბილიკებში მოძებნის." -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4394 +msgid "Sets the path for extension control files." +msgstr "დააყენეთ ბილიკი გაფართოების კონტროლის ფაილებისთვის." + +#: utils/misc/guc_tables.c:4395 +msgid "The remaining extension script and secondary control files are then loaded from the same directory where the primary control file was found." +msgstr "" + +#: utils/misc/guc_tables.c:4406 msgid "Sets the location of the Kerberos server key file." msgstr "Kerberos-ის სერვერის გასაღების ფაილის მდებარეობის მითითება." -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4417 msgid "Sets the Bonjour service name." msgstr "Bonjour-ის სერვისის სახელის დაყენება." -#: utils/misc/guc_tables.c:4192 +#: utils/misc/guc_tables.c:4418 +msgid "An empty string means use the computer name." +msgstr "" + +#: utils/misc/guc_tables.c:4427 msgid "Sets the language in which messages are displayed." msgstr "შეტყობინებების საჩვენებელი ენის მითითება." -#: utils/misc/guc_tables.c:4202 +#: utils/misc/guc_tables.c:4428 utils/misc/guc_tables.c:4438 utils/misc/guc_tables.c:4448 utils/misc/guc_tables.c:4458 +msgid "An empty string means use the operating system setting." +msgstr "" + +#: utils/misc/guc_tables.c:4437 msgid "Sets the locale for formatting monetary amounts." msgstr "თანხის რიცხვების ფორმატირების სტანდარტის დაყენება." -#: utils/misc/guc_tables.c:4212 +#: utils/misc/guc_tables.c:4447 msgid "Sets the locale for formatting numbers." msgstr "რიცხვების ფორმატირების ენის დაყენება." -#: utils/misc/guc_tables.c:4222 +#: utils/misc/guc_tables.c:4457 msgid "Sets the locale for formatting date and time values." msgstr "თარიღისა და დროის ფორმატირების ენის დაყენება." -#: utils/misc/guc_tables.c:4232 +#: utils/misc/guc_tables.c:4467 msgid "Lists shared libraries to preload into each backend." msgstr "თითოეული უკანაბოლოსთვის გაშვებამდე ჩასატვირთი გაზიარებული ბიბლიოთეკების სია." -#: utils/misc/guc_tables.c:4243 +#: utils/misc/guc_tables.c:4478 msgid "Lists shared libraries to preload into server." msgstr "სერვერის გაშვებამდე ჩასატვირთი გაზიარებული ბიბლიოთეკების სია." -#: utils/misc/guc_tables.c:4254 +#: utils/misc/guc_tables.c:4489 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "თითოეული უკანაბოლოსთვის გაშვებამდე ჩასატვირთი არაპრივილეგირებული გაზიარებული ბიბლიოთეკების სია." -#: utils/misc/guc_tables.c:4265 +#: utils/misc/guc_tables.c:4500 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "" -#: utils/misc/guc_tables.c:4277 +#: utils/misc/guc_tables.c:4512 msgid "Shows the server (database) character set encoding." msgstr "სერვერის (ბაზის) სიმბოლოების კოდირების ჩვენება." -#: utils/misc/guc_tables.c:4289 +#: utils/misc/guc_tables.c:4524 msgid "Shows the server version." msgstr "სერვერის ვერსიის ჩვენება." -#: utils/misc/guc_tables.c:4301 +#: utils/misc/guc_tables.c:4536 msgid "Sets the current role." msgstr "მიმდინარე როლის დაყენება." -#: utils/misc/guc_tables.c:4313 +#: utils/misc/guc_tables.c:4548 msgid "Sets the session user name." msgstr "სესიის მომხმარებლი სახელის დაყენება." -#: utils/misc/guc_tables.c:4324 +#: utils/misc/guc_tables.c:4559 msgid "Sets the destination for server log output." msgstr "სერვერის ჟურნალის გამოტანის სამიზნის დაყენება." -#: utils/misc/guc_tables.c:4325 +#: utils/misc/guc_tables.c:4560 msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", and \"eventlog\", depending on the platform." msgstr "" -#: utils/misc/guc_tables.c:4336 +#: utils/misc/guc_tables.c:4571 msgid "Sets the destination directory for log files." msgstr "ჟურნალის ფაილების საქაღალდის დაყენება." -#: utils/misc/guc_tables.c:4337 +#: utils/misc/guc_tables.c:4572 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "" -#: utils/misc/guc_tables.c:4347 +#: utils/misc/guc_tables.c:4582 msgid "Sets the file name pattern for log files." msgstr "ჟურნალის ფაილების სახელის შაბლონის დაყენება." -#: utils/misc/guc_tables.c:4358 +#: utils/misc/guc_tables.c:4593 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "Syslog-ში PostgreSQL-ის შეტყობინებების იდენტიფიკატორი პროგრამის სახელის დაყენება." -#: utils/misc/guc_tables.c:4369 +#: utils/misc/guc_tables.c:4604 msgid "Sets the application name used to identify PostgreSQL messages in the event log." msgstr "მოვლენების ჟურნალში PostgreSQL-ის შეტყობინებების იდენტიფიკატორი აპლიკაციის სახელის დაყენება." -#: utils/misc/guc_tables.c:4380 +#: utils/misc/guc_tables.c:4615 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "" -#: utils/misc/guc_tables.c:4390 +#: utils/misc/guc_tables.c:4625 msgid "Selects a file of time zone abbreviations." msgstr "დროის სარტყლების აბრევიატურების ფაილის მითითება." -#: utils/misc/guc_tables.c:4400 +#: utils/misc/guc_tables.c:4635 msgid "Sets the owning group of the Unix-domain socket." msgstr "Unix-დომენის სოკეტის მფლობლის ჯგუფის დაყენება." -#: utils/misc/guc_tables.c:4401 -msgid "The owning user of the socket is always the user that starts the server." -msgstr "სოკეტის მფლობელი მომხმარებელი ყოველთვის იგივე მომხმარებელია, ვინც სერვერი გაუშვა." +#: utils/misc/guc_tables.c:4636 +msgid "The owning user of the socket is always the user that starts the server. An empty string means use the user's default group." +msgstr "სოკეტის მფლობელი მომხმარებელი ყოველთვის იგივე მომხმარებელია, ვინც სერვერი გაუშვა. ცარიელი სტრიქონი მომხმარებლის ნაგულისხმევ ჯგუფს ნიშნავს." -#: utils/misc/guc_tables.c:4411 +#: utils/misc/guc_tables.c:4646 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "აყენებს საქაღალდეებს, სადაც Unix-ის სოკეტები შეიქმნება." -#: utils/misc/guc_tables.c:4422 +#: utils/misc/guc_tables.c:4657 msgid "Sets the host name or IP address(es) to listen to." msgstr "მოსასმენი IP მისამართი ან ჰოსტის სახელი." -#: utils/misc/guc_tables.c:4437 +#: utils/misc/guc_tables.c:4672 msgid "Sets the server's data directory." msgstr "სერვერის მონაცმების საქაღალდის დაყენება." -#: utils/misc/guc_tables.c:4448 +#: utils/misc/guc_tables.c:4683 msgid "Sets the server's main configuration file." msgstr "სერვერის კონფიგურაციის მთავარი ფაილის დაყენება." -#: utils/misc/guc_tables.c:4459 +#: utils/misc/guc_tables.c:4694 msgid "Sets the server's \"hba\" configuration file." msgstr "სერვერის hba კონფიგურაციის ფაილის დაყენება." -#: utils/misc/guc_tables.c:4470 +#: utils/misc/guc_tables.c:4705 msgid "Sets the server's \"ident\" configuration file." msgstr "სერვერის ident კონფიგურაციის ფაილის დაყენება." -#: utils/misc/guc_tables.c:4481 +#: utils/misc/guc_tables.c:4716 msgid "Writes the postmaster PID to the specified file." msgstr "Postmaster-ის PID-ის მითითებულ ფაილში ჩაწერა." -#: utils/misc/guc_tables.c:4492 +#: utils/misc/guc_tables.c:4727 msgid "Shows the name of the SSL library." msgstr "SSL ბიბლიოთეკის სახელის ჩვენება." -#: utils/misc/guc_tables.c:4507 +#: utils/misc/guc_tables.c:4742 msgid "Location of the SSL server certificate file." msgstr "SSL სერვერის სერტიფიკატის ფაილის მდებარეობა." -#: utils/misc/guc_tables.c:4517 +#: utils/misc/guc_tables.c:4752 msgid "Location of the SSL server private key file." msgstr "SSL სერვერის პირადი გასაღების ფაილის მდებარეობა." -#: utils/misc/guc_tables.c:4527 +#: utils/misc/guc_tables.c:4762 msgid "Location of the SSL certificate authority file." msgstr "SSL სერვერის CA ფაილის მდებარეობა." -#: utils/misc/guc_tables.c:4537 +#: utils/misc/guc_tables.c:4772 msgid "Location of the SSL certificate revocation list file." msgstr "SSL სერვერის გაუქმებული სერტიფიკატების სიის ფაილის მდებარეობა." -#: utils/misc/guc_tables.c:4547 +#: utils/misc/guc_tables.c:4782 msgid "Location of the SSL certificate revocation list directory." msgstr "SSL სერვერის გაუქმებული სერტიფიკატების სიის საქაღალდის მდებარეობა." -#: utils/misc/guc_tables.c:4557 +#: utils/misc/guc_tables.c:4792 msgid "Number of synchronous standbys and list of names of potential synchronous ones." msgstr "" -#: utils/misc/guc_tables.c:4568 +#: utils/misc/guc_tables.c:4803 msgid "Sets default text search configuration." msgstr "ტექსტის ძებნის ნაგულისხმევი კონფიგურაციის დაყენება." -#: utils/misc/guc_tables.c:4578 -msgid "Sets the list of allowed SSL ciphers." -msgstr "ჩართული SSL შიფრაციების სიის დაყენება." +#: utils/misc/guc_tables.c:4813 +msgid "Sets the list of allowed TLSv1.3 cipher suites." +msgstr "აყენებს TLSv1.3-ის დაშვებულ შიფრების ნაკრებებს." -#: utils/misc/guc_tables.c:4593 -msgid "Sets the curve to use for ECDH." -msgstr "ECDH-სთვის გამოყენებული მრუდის დაყენება." +#: utils/misc/guc_tables.c:4814 +msgid "An empty string means use the default cipher suites." +msgstr "ცარიელი სტრიქონი ნაგულისხმევი შიფრების ნაკრების გამოყენებას ნიშნავს." + +#: utils/misc/guc_tables.c:4824 +msgid "Sets the list of allowed TLSv1.2 (and lower) ciphers." +msgstr "აყენებს TLSv1.2-ის (და უფრო ძველი) დაშვებულ შიფრების ნაკრებებს." + +#: utils/misc/guc_tables.c:4839 +msgid "Sets the group(s) to use for Diffie-Hellman key exchange." +msgstr "" + +#: utils/misc/guc_tables.c:4840 +msgid "Multiple groups can be specified using colon-separated list." +msgstr "" -#: utils/misc/guc_tables.c:4608 +#: utils/misc/guc_tables.c:4854 msgid "Location of the SSL DH parameters file." msgstr "SSH DH პარამეტრების ფაილის მდებარეობა." -#: utils/misc/guc_tables.c:4619 +#: utils/misc/guc_tables.c:4855 +msgid "An empty string means use compiled-in default parameters." +msgstr "ცარიელი სტრიქონი კომპილაციის დროს მითითებული ნაგულისხმევი პარამეტრების გამოყენებას ნიშნავს." + +#: utils/misc/guc_tables.c:4865 msgid "Command to obtain passphrases for SSL." msgstr "SSL-ის საკვანძო ფრაზების მისაღები ბრძანება." -#: utils/misc/guc_tables.c:4630 +#: utils/misc/guc_tables.c:4866 +msgid "An empty string means use the built-in prompting mechanism." +msgstr "" + +#: utils/misc/guc_tables.c:4876 msgid "Sets the application name to be reported in statistics and logs." msgstr "" -#: utils/misc/guc_tables.c:4641 +#: utils/misc/guc_tables.c:4887 msgid "Sets the name of the cluster, which is included in the process title." msgstr "" -#: utils/misc/guc_tables.c:4652 +#: utils/misc/guc_tables.c:4898 msgid "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "" -#: utils/misc/guc_tables.c:4653 +#: utils/misc/guc_tables.c:4899 msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay." msgstr "" -#: utils/misc/guc_tables.c:4663 +#: utils/misc/guc_tables.c:4909 msgid "JIT provider to use." msgstr "JIT სერვისის მომწოდებელი." -#: utils/misc/guc_tables.c:4674 +#: utils/misc/guc_tables.c:4920 msgid "Log backtrace for errors in these functions." msgstr "მითითებულ ფუნქციებში შეცდომის შემთხვევაში სტეკის ჟურნალში ჩაწერა." -#: utils/misc/guc_tables.c:4685 +#: utils/misc/guc_tables.c:4931 msgid "Use direct I/O for file access." msgstr "ფაილებთან წვდომისთვის პირდაპირი შეტანა/გამოტანის გამოყენება." -#: utils/misc/guc_tables.c:4696 -msgid "Lists streaming replication standby server slot names that logical WAL sender processes will wait for." +#: utils/misc/guc_tables.c:4932 +msgid "An empty string disables direct I/O." +msgstr "ცარიელი სტრიქონი გამორთავს პირდაპირ I/O-ს." + +#: utils/misc/guc_tables.c:4942 +msgid "Lists streaming replication standby server replication slot names that logical WAL sender processes will wait for." +msgstr "" + +#: utils/misc/guc_tables.c:4944 +msgid "Logical WAL sender processes will send decoded changes to output plugins only after the specified replication slots have confirmed receiving WAL." msgstr "" -#: utils/misc/guc_tables.c:4698 -msgid "Logical WAL sender processes will send decoded changes to plugins only after the specified replication slots confirm receiving WAL." +#: utils/misc/guc_tables.c:4956 +msgid "Prohibits access to non-system relations of specified kinds." msgstr "" -#: utils/misc/guc_tables.c:4719 +#: utils/misc/guc_tables.c:4967 +msgid "Lists libraries that may be called to validate OAuth v2 bearer tokens." +msgstr "" + +#: utils/misc/guc_tables.c:4978 +msgid "Logs specified aspects of connection establishment and setup." +msgstr "" + +#: utils/misc/guc_tables.c:4999 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "შეიძლება თუ არა ტექსტურ სტრიქონებში \"\\\" სიმბოლოს გამოყენება." -#: utils/misc/guc_tables.c:4729 +#: utils/misc/guc_tables.c:5009 msgid "Sets the output format for bytea." msgstr "\"bytea\"-ის გამოსატანი ფორმატის დაყენება." -#: utils/misc/guc_tables.c:4739 +#: utils/misc/guc_tables.c:5019 msgid "Sets the message levels that are sent to the client." msgstr "კლიენტთან გაგზავნილი შეტყობინების დონეების დაყენება." -#: utils/misc/guc_tables.c:4740 utils/misc/guc_tables.c:4836 utils/misc/guc_tables.c:4847 +#: utils/misc/guc_tables.c:5020 utils/misc/guc_tables.c:5116 utils/misc/guc_tables.c:5127 msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent." msgstr "" -#: utils/misc/guc_tables.c:4750 +#: utils/misc/guc_tables.c:5030 msgid "Enables in-core computation of query identifiers." msgstr "მოთხოვნის იდენტიფიკატორის ბირთვის-შიდა გამოთვლის ჩართვა." -#: utils/misc/guc_tables.c:4760 +#: utils/misc/guc_tables.c:5040 msgid "Enables the planner to use constraints to optimize queries." msgstr "მგეგმავისთვის შეზღუდვების ჩართვა, მოთხოვნების ოპტიმიზაციისთვის." -#: utils/misc/guc_tables.c:4761 +#: utils/misc/guc_tables.c:5041 msgid "Table scans will be skipped if their constraints guarantee that no rows match the query." msgstr "" -#: utils/misc/guc_tables.c:4772 +#: utils/misc/guc_tables.c:5052 msgid "Sets the default compression method for compressible values." msgstr "შეკუმშვადი მნიშვნელობების ნაგულისხმევი შეკუმშვის მეთოდის დაყენება." -#: utils/misc/guc_tables.c:4783 +#: utils/misc/guc_tables.c:5063 msgid "Sets the transaction isolation level of each new transaction." msgstr "ახალი ტრანზაქციების იზოლაციის დონის დაყენება." -#: utils/misc/guc_tables.c:4793 +#: utils/misc/guc_tables.c:5073 msgid "Sets the current transaction's isolation level." msgstr "მიმდინარე ტრანზაქციის იზოლაციის დონის დაყენება." -#: utils/misc/guc_tables.c:4804 +#: utils/misc/guc_tables.c:5084 msgid "Sets the display format for interval values." msgstr "ინტერვალის მნიშვნელობების საჩვენებელი ფორმატის დაყენება." -#: utils/misc/guc_tables.c:4815 +#: utils/misc/guc_tables.c:5095 msgid "Log level for reporting invalid ICU locale strings." msgstr "ჟურნალის დონე არასწორი ICU ლოკალის სტრიქონების ანგარიშისთვის." -#: utils/misc/guc_tables.c:4825 +#: utils/misc/guc_tables.c:5105 msgid "Sets the verbosity of logged messages." msgstr "ჟურნალში ჩაწერილი შეტყობინებების დეტალურობის დაყენება." -#: utils/misc/guc_tables.c:4835 +#: utils/misc/guc_tables.c:5115 msgid "Sets the message levels that are logged." msgstr "ჟურნალში ჩასაწერი შეტყობინების დონეების დაყენება." -#: utils/misc/guc_tables.c:4846 +#: utils/misc/guc_tables.c:5126 msgid "Causes all statements generating error at or above this level to be logged." msgstr "შეცდომის მითითებული ან უფრო ზედა კოდების ჟურნალში ჩაწერის მითითება." -#: utils/misc/guc_tables.c:4857 +#: utils/misc/guc_tables.c:5137 msgid "Sets the type of statements logged." msgstr "ჟურნალში ჩასაწერი ოპერატორის ტიპების დაყენება." -#: utils/misc/guc_tables.c:4867 +#: utils/misc/guc_tables.c:5147 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "თუ სისტემურ ჟურნალში ჩაწერა ჩართულია, მიუთითებს syslog-ის \"facility\"-ის." -#: utils/misc/guc_tables.c:4878 +#: utils/misc/guc_tables.c:5158 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "სესიის ქცევის დაყენება ტრიგერებისა და გადაწერის წესებისთვის." -#: utils/misc/guc_tables.c:4888 +#: utils/misc/guc_tables.c:5168 msgid "Sets the current transaction's synchronization level." msgstr "მიმდინარე ტრანზაქციის სინქრონიზაციის დონის დაყენება." -#: utils/misc/guc_tables.c:4898 +#: utils/misc/guc_tables.c:5178 msgid "Allows archiving of WAL files using \"archive_command\"." msgstr "'WAL' ფაილების დაარქივების დაშვება 'archive_command'-ის გამოყენებით." -#: utils/misc/guc_tables.c:4908 +#: utils/misc/guc_tables.c:5188 msgid "Sets the action to perform upon reaching the recovery target." msgstr "" -#: utils/misc/guc_tables.c:4918 +#: utils/misc/guc_tables.c:5198 msgid "Collects function-level statistics on database activity." msgstr "აგროვებს ფუნქციის დონის სტატისტიკას ბაზის აქტივობების შესახებ." -#: utils/misc/guc_tables.c:4929 +#: utils/misc/guc_tables.c:5209 msgid "Sets the consistency of accesses to statistics data." msgstr "სტატისტიკის მონაცემებთან წვდომის მიმდევრობის დაყენება." -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5219 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "'WAL' ფაილში მითითებული მეთოდით ჩაწერილი სრული გვერდის ჩაწერების შეკუმშვა." -#: utils/misc/guc_tables.c:4949 +#: utils/misc/guc_tables.c:5229 msgid "Sets the level of information written to the WAL." msgstr "WAL-ში ჩაწერილი ინფორმაციის დონის დაყენება." -#: utils/misc/guc_tables.c:4959 +#: utils/misc/guc_tables.c:5239 msgid "Selects the dynamic shared memory implementation used." msgstr "გამოყენებული გაზიარებული მეხსიერების განხორციელების არჩევა." -#: utils/misc/guc_tables.c:4969 +#: utils/misc/guc_tables.c:5249 msgid "Selects the shared memory implementation used for the main shared memory region." msgstr "" -#: utils/misc/guc_tables.c:4979 +#: utils/misc/guc_tables.c:5259 +msgid "Selects the file copy method." +msgstr "" + +#: utils/misc/guc_tables.c:5269 msgid "Selects the method used for forcing WAL updates to disk." msgstr "WAL-ისთვის დისკზე განახლებების ნაძალადევად ჩაწერის მეთოდის დაყენება." -#: utils/misc/guc_tables.c:4989 +#: utils/misc/guc_tables.c:5279 msgid "Sets how binary values are to be encoded in XML." msgstr "XML-ში ბინარული მნიშვნელობების კოდირების ტიპის დაყენება." -#: utils/misc/guc_tables.c:4999 +#: utils/misc/guc_tables.c:5289 msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments." msgstr "" -#: utils/misc/guc_tables.c:5010 +#: utils/misc/guc_tables.c:5300 msgid "Use of huge pages on Linux or Windows." msgstr "Linux-ზე და Windows-ზე უზარმაზარი გვერდების გამოყენება." -#: utils/misc/guc_tables.c:5020 +#: utils/misc/guc_tables.c:5310 msgid "Indicates the status of huge pages." -msgstr "" +msgstr "აჩვენებს უზარმაზარი გვერდების სტატუსს." -#: utils/misc/guc_tables.c:5031 +#: utils/misc/guc_tables.c:5321 msgid "Prefetch referenced blocks during recovery." msgstr "აღდგენისას მიბმული ბლოკების წინასწარ გამოთხოვა." -#: utils/misc/guc_tables.c:5032 +#: utils/misc/guc_tables.c:5322 msgid "Look ahead in the WAL to find references to uncached data." msgstr "" -#: utils/misc/guc_tables.c:5041 +#: utils/misc/guc_tables.c:5331 msgid "Forces the planner's use parallel query nodes." msgstr "დამგეგმავის მიერ პარალელური მოთხოვნის კვანძების ნაძალადევი გამოყენების ჩართვა." -#: utils/misc/guc_tables.c:5042 +#: utils/misc/guc_tables.c:5332 msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans that contain nodes that perform tuple communication between workers and the main process." msgstr "" -#: utils/misc/guc_tables.c:5054 +#: utils/misc/guc_tables.c:5344 msgid "Chooses the algorithm for encrypting passwords." msgstr "აირჩიეთ პაროლების დასაშიფრად გამოყენებული ალგორითმი." -#: utils/misc/guc_tables.c:5064 +#: utils/misc/guc_tables.c:5354 msgid "Controls the planner's selection of custom or generic plan." msgstr "" -#: utils/misc/guc_tables.c:5065 +#: utils/misc/guc_tables.c:5355 msgid "Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior." msgstr "" -#: utils/misc/guc_tables.c:5077 +#: utils/misc/guc_tables.c:5367 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "SSL/TLS-ის პროტოკოლის მინიმალური ვერსიის დაყენება." -#: utils/misc/guc_tables.c:5089 +#: utils/misc/guc_tables.c:5379 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "SSL/TLS-ის პროტოკოლის მაქსიმალური ვერსიის დაყენება." -#: utils/misc/guc_tables.c:5101 +#: utils/misc/guc_tables.c:5391 msgid "Sets the method for synchronizing the data directory before crash recovery." msgstr "" -#: utils/misc/guc_tables.c:5110 +#: utils/misc/guc_tables.c:5400 msgid "Forces immediate streaming or serialization of changes in large transactions." msgstr "" -#: utils/misc/guc_tables.c:5111 +#: utils/misc/guc_tables.c:5401 msgid "On the publisher, it allows streaming or serializing each change in logical decoding. On the subscriber, it allows serialization of all changes to files and notifies the parallel apply workers to read and apply them at the end of the transaction." msgstr "" +#: utils/misc/guc_tables.c:5413 +msgid "Selects the method for executing asynchronous I/O." +msgstr "აირჩიეთ მეთოდი ასინქრონული შეყვანა/გამოყვანის შესასრულებლად." + #: utils/misc/help_config.c:129 #, c-format msgid "internal error: unrecognized run-time parameter type\n" @@ -30019,6 +31360,26 @@ msgstr "" msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." msgstr "" +#: utils/misc/stack_depth.c:101 +#, c-format +msgid "stack depth limit exceeded" +msgstr "გადაცილებულია სტეკის სიღრმის ლიმიტი" + +#: utils/misc/stack_depth.c:102 +#, c-format +msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." +msgstr "" + +#: utils/misc/stack_depth.c:149 +#, c-format +msgid "\"max_stack_depth\" must not exceed %zdkB." +msgstr "\"max_stack_depth\" %zdკბ-ს არ უნდა სცდებოდეს." + +#: utils/misc/stack_depth.c:151 +#, c-format +msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." +msgstr "" + #: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" @@ -30034,57 +31395,57 @@ msgstr "" msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "" -#: utils/misc/tzparser.c:112 +#: utils/misc/tzparser.c:113 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "" -#: utils/misc/tzparser.c:121 +#: utils/misc/tzparser.c:122 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "" -#: utils/misc/tzparser.c:133 +#: utils/misc/tzparser.c:134 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "" -#: utils/misc/tzparser.c:169 +#: utils/misc/tzparser.c:170 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "დროის სარტყელის ფაილის (\"%s\") არასწორი სინტაქსი ხაზზე %d" -#: utils/misc/tzparser.c:237 +#: utils/misc/tzparser.c:238 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "დროის სარტყელის აბრევიატურა ერთზე მეტჯერაა აღწერილი: %s" -#: utils/misc/tzparser.c:239 +#: utils/misc/tzparser.c:240 #, c-format msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d." msgstr "" -#: utils/misc/tzparser.c:301 +#: utils/misc/tzparser.c:302 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "დროის სარტყელის ფაილის არასწორი ფაილი\"%s\"" -#: utils/misc/tzparser.c:314 +#: utils/misc/tzparser.c:315 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "დროის სარტყლის ფაილის რეკურსიის ლიმიტი გადაცილებულია ფაილში \"%s\"" -#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 +#: utils/misc/tzparser.c:354 utils/misc/tzparser.c:367 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "დროის სარტყელის ფაილის წაკითხვის შეცდომა \"%s\": %m" -#: utils/misc/tzparser.c:377 +#: utils/misc/tzparser.c:378 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "დროის სარტყელის ფაილის (\"%s\") ძალიან გრძელი ხაზი (\"%d\")" -#: utils/misc/tzparser.c:401 +#: utils/misc/tzparser.c:403 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "" @@ -30099,12 +31460,12 @@ msgstr "შეცდომა მეხსიერების კონტე msgid "could not attach to dynamic shared area" msgstr "დინამიური გაზიარებული მეხსიერების მიმაგრების შეცდომა" -#: utils/mmgr/mcxt.c:1155 +#: utils/mmgr/mcxt.c:1231 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "%zu ზომის მეხსიერების კონტექსტიდან \"%s\" გამოთხოვა ჩავარდა." -#: utils/mmgr/mcxt.c:1299 +#: utils/mmgr/mcxt.c:1391 #, c-format msgid "logging memory contexts of PID %d" msgstr "პროცესის, PID-ით %d მეხსიერების კონტექსტები ჟურნალში ჩაიწერება" @@ -30119,35 +31480,35 @@ msgstr "კურსორი \"%s\" უკვე არსებობს" msgid "closing existing cursor \"%s\"" msgstr "არსებული კურსორის დახურვა \"%s\"" -#: utils/mmgr/portalmem.c:401 +#: utils/mmgr/portalmem.c:403 #, c-format msgid "portal \"%s\" cannot be run" msgstr "პორტალის \"%s\" გაშვება შეუძლებელია" -#: utils/mmgr/portalmem.c:479 +#: utils/mmgr/portalmem.c:481 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "მიჭიკარტებული პორტალის წაშლა შეუძლებელია:\"%s\"" -#: utils/mmgr/portalmem.c:487 +#: utils/mmgr/portalmem.c:489 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "აქტიური პორტალის წაშლა სეუძლებელია: %s" -#: utils/mmgr/portalmem.c:738 +#: utils/mmgr/portalmem.c:740 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "" -#: utils/mmgr/portalmem.c:1229 +#: utils/mmgr/portalmem.c:1234 #, c-format msgid "cannot perform transaction commands inside a cursor loop that is not read-only" msgstr "" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %lld of temporary file" -msgstr "დროებითი ფაილის %lld-ე ბლოკზე გადახვევა შეუძლებელია" +msgid "could not seek to block % of temporary file" +msgstr "დროებითი ფაილის %-ე ბლოკზე გადახვევა შეუძლებელია" #: utils/sort/sharedtuplestore.c:466 #, c-format @@ -30159,77 +31520,77 @@ msgstr "" msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "" -#: utils/sort/tuplesort.c:2372 +#: utils/sort/tuplesort.c:2340 #, c-format msgid "cannot have more than %d runs for an external sort" msgstr "" -#: utils/sort/tuplesortvariants.c:1552 +#: utils/sort/tuplesortvariants.c:1671 #, c-format msgid "could not create unique index \"%s\"" msgstr "უნიკალური ინდექსის შექმნა შეუძლებელია: \"%s\"" -#: utils/sort/tuplesortvariants.c:1554 +#: utils/sort/tuplesortvariants.c:1673 #, c-format msgid "Key %s is duplicated." msgstr "გასაღები %s დუბლირებულია." -#: utils/sort/tuplesortvariants.c:1555 +#: utils/sort/tuplesortvariants.c:1674 #, c-format msgid "Duplicate keys exist." msgstr "არსებობს დუბლიკატი გასაღებები." -#: utils/sort/tuplestore.c:518 utils/sort/tuplestore.c:528 utils/sort/tuplestore.c:869 utils/sort/tuplestore.c:973 utils/sort/tuplestore.c:1037 utils/sort/tuplestore.c:1054 utils/sort/tuplestore.c:1256 utils/sort/tuplestore.c:1321 utils/sort/tuplestore.c:1330 +#: utils/sort/tuplestore.c:552 utils/sort/tuplestore.c:562 utils/sort/tuplestore.c:921 utils/sort/tuplestore.c:1025 utils/sort/tuplestore.c:1089 utils/sort/tuplestore.c:1106 utils/sort/tuplestore.c:1308 utils/sort/tuplestore.c:1373 utils/sort/tuplestore.c:1382 #, c-format msgid "could not seek in tuplestore temporary file" msgstr "კორტეჟების საცავი დროებითი ფაილის გადახვევა შეუძლებელია" -#: utils/time/snapmgr.c:536 +#: utils/time/snapmgr.c:557 #, c-format msgid "The source transaction is not running anymore." msgstr "საწყისი ტრანზაქცია გაშვებული აღარაა." -#: utils/time/snapmgr.c:1136 +#: utils/time/snapmgr.c:1143 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "ქვეტრანზაქციიდან სწრაფი ასლის გამოტანა შეუძლებელია" -#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 +#: utils/time/snapmgr.c:1303 utils/time/snapmgr.c:1308 utils/time/snapmgr.c:1313 utils/time/snapmgr.c:1328 utils/time/snapmgr.c:1333 utils/time/snapmgr.c:1338 utils/time/snapmgr.c:1353 utils/time/snapmgr.c:1358 utils/time/snapmgr.c:1363 utils/time/snapmgr.c:1477 utils/time/snapmgr.c:1493 utils/time/snapmgr.c:1518 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "სწრაფი ასლის არასწორი მონაცემები ფაილში \"%s\"" -#: utils/time/snapmgr.c:1393 +#: utils/time/snapmgr.c:1400 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "SET TRANSACTION SNAPSHOT ყველა მოთხოვნაზე ადრე უნდა გამოიძახოთ" -#: utils/time/snapmgr.c:1402 +#: utils/time/snapmgr.c:1409 #, c-format msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ" msgstr "" -#: utils/time/snapmgr.c:1411 +#: utils/time/snapmgr.c:1418 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "სწრაფი ასლის არასწორი იდენტიფიკატორი: \"%s\"" -#: utils/time/snapmgr.c:1426 +#: utils/time/snapmgr.c:1433 #, c-format msgid "snapshot \"%s\" does not exist" msgstr "სწრაფი ასლი \"%s\" არ არსებობს" -#: utils/time/snapmgr.c:1524 +#: utils/time/snapmgr.c:1531 #, c-format msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction" msgstr "" -#: utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1535 #, c-format msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction" msgstr "" -#: utils/time/snapmgr.c:1543 +#: utils/time/snapmgr.c:1550 #, c-format msgid "cannot import a snapshot from a different database" msgstr "სხვა ბაზიდან სწრაფი ასლის შემოტანა შეუძლებელია" @@ -30238,13 +31599,114 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid " GSS (authenticated=%s, encrypted=%s)" #~ msgstr " GSS (ავთენტიფიცირებული=%s, დაშიფრული=%s)" +#, c-format +#~ msgid "\"%s\" is not a partition" +#~ msgstr "\"%s\" დანაყოფი არაა" + +#, c-format +#~ msgid "\"%s\" must be set to 0 on platforms that lack support for issuing read-ahead advice." +#~ msgstr "\"%s\" უნდა იყოს 0 პლატფორმებზე, რომლებსაც წინასწარ-წაკითხვის მითითების მხარდაჭერა არ გააჩნიათ." + +#, c-format +#~ msgid "\"RN\" not supported for input" +#~ msgstr "\"RN\" შეყვანისთვის მხარდაჭერილი არაა" + +#, c-format +#~ msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" +#~ msgstr "\"debug_io_direct\" მონაცემებისთვის მხარდაჭერილი არაა, რადგან BLCKSZ ძალიან პატარაა" + +#, c-format +#~ msgid "\"debug_io_direct\" is not supported on this platform." +#~ msgstr "\"debug_io_direct\" ამ პლატფორმაზე მხარდაჭერილი არაა." + +#, c-format +#~ msgid "\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." +#~ msgstr "პლატფორმებზე, რომლებზეც posix_fadvise() ხელმისაწვდომი არაა, \"maintenance_io_concurrency\"-ის მნიშვნელობა 0-ის ტოლი უნდა ყოს." + +#, c-format +#~ msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" +#~ msgstr "\"max_wal_size\"-ი \"wal_segment_size\"-ზე, მინიმუმ, ორჯერ მეტი უნდა იყოს" + +#, c-format +#~ msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" +#~ msgstr "\"min_wal_size\"-ი \"wal_segment_size\"-ზე მინიმუმ ორჯერ მეტი უნდა იყოს" + +#, c-format +#~ msgid "\"synchronous_standby_names\" parser failed" +#~ msgstr "\"synchronous_standby_names\"-ის დამმუშავებლის შეცდომა" + +#, c-format +#~ msgid "%s cannot be executed within a pipeline" +#~ msgstr "%s ფუნქციიდან ვერ გაეშვება" + +#, c-format +#~ msgid "%s with OID %u does not exist" +#~ msgstr "%s OID-ით %u არ არსებობს" + +#~ msgid "-1 indicates that the value could not be determined." +#~ msgstr "-1 ნიშნავს, რომ მნიშვნელობა ვერ განისაზღვრა." + #, c-format #~ msgid "-X requires a power of two value between 1 MB and 1 GB" #~ msgstr "-X მოითხოვს მნიშვნელობას, რომელიც ორის ხარისხია და არის 1 მბ-სა და 1გბ-ს შორის" +#~ msgid "0 turns this feature off." +#~ msgstr "0 გამორთავს ამ ფუნქციას." + #~ msgid "A value of -1 disables this feature." #~ msgstr "მნიშვნელობა -1 გამორთავს ამ ფუნქციას." +#~ msgid "A value of 0 turns off the timeout." +#~ msgstr "0 მოლოდინის ვადას გამორთავს." + +#, c-format +#~ msgid "COPY DEFAULT only available using COPY FROM" +#~ msgstr "COPY DEFAULT მხოლოდ COPY FROM-ის გამოყენების დროსაა ხელმისაწვდომი" + +#, c-format +#~ msgid "COPY ESCAPE requires CSV mode" +#~ msgstr "COPY ESCAPE-ს CSV რეჟიმი სჭირდება" + +#, c-format +#~ msgid "COPY FORCE_NOT_NULL cannot be used with COPY TO" +#~ msgstr "COPY FORCE_NOT_NULL-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" + +#, c-format +#~ msgid "COPY FORCE_NOT_NULL requires CSV mode" +#~ msgstr "COPY FORCE_NOT_NULL-ს CSV რეჟიმი სჭირდება" + +#, c-format +#~ msgid "COPY FORCE_NULL cannot be used with COPY TO" +#~ msgstr "COPY FORCE_NULL-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" + +#, c-format +#~ msgid "COPY FORCE_NULL requires CSV mode" +#~ msgstr "COPY FORCE_NULL-ს CSV რეჟიმი სჭირდება" + +#, c-format +#~ msgid "COPY FORCE_QUOTE cannot be used with COPY FROM" +#~ msgstr "COPY FORCE_QUOTE-ს COPY FROM-სთან ერთად ვერ გამოიყენებთ" + +#, c-format +#~ msgid "COPY FORCE_QUOTE requires CSV mode" +#~ msgstr "COPY FORCE_QUOTE-ს CSV რეჟიმი სჭირდება" + +#, c-format +#~ msgid "COPY LOG_VERBOSITY \"%s\" not recognized" +#~ msgstr "COPY LOG_VERBOSITY \"%s\" უცნობია" + +#, c-format +#~ msgid "COPY ON_ERROR \"%s\" not recognized" +#~ msgstr "COPY ON_ERROR \"%s\" უცნობია" + +#, c-format +#~ msgid "COPY ON_ERROR cannot be used with COPY TO" +#~ msgstr "COPY ON_ERROR-ს COPY TO-სთან ერთად ვერ გამოიყენებთ" + +#, c-format +#~ msgid "COPY delimiter must not appear in the DEFAULT specification" +#~ msgstr "COPY-ის გამყოფი DEFAULT-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" + #, c-format #~ msgid "COPY escape available only in CSV mode" #~ msgstr "COPY-ის სპეცსიმბოლო მხოლოდ CSV -ის რეჟიმშია ხელმისაწვდომი" @@ -30277,12 +31739,40 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "COPY quote available only in CSV mode" #~ msgstr "COPY-ის ბრჭყალი მხოლოდ CSV -ის რეჟიმშია ხელმისაწვდომი" +#, c-format +#~ msgid "CSV quote character must not appear in the DEFAULT specification" +#~ msgstr "CSV-ის ბრჭყალის სიმბოლო DEFAULT-ის სპეციფიკაციაში არ უნდა გამოჩნდეს" + +#, c-format +#~ msgid "Consider creating the slot \"%s\" or amend parameter %s." +#~ msgstr "განიხილეთ, შექმნათ სლოტი \"%s\", ან მიაწერეთ პარამეტრი %s." + +#, c-format +#~ msgid "Consider increasing the configuration parameter \"max_worker_processes\"." +#~ msgstr "გაითვალისწინეთ, რომ შეიძლება კონფიგურაციის პარამეტრის \"max_worker_processes\" გაზრდა გჭირდებათ." + #~ msgid "Controls when to replicate or apply each change." #~ msgstr "აკონტროლებს, როდის მოხდება თითოეული ცვლილების რეპლიკაცია ან გადატარება." #, c-format -#~ msgid "Could not translate strategy number %d for operator class \"%s\" for access method \"%s\"." -#~ msgstr "ვერ ვთარგმნე სტრატეგიის ნომერი %d ოპერატორის კლასისთვის \"%s\" წვდომის მეთოდისთვის \"%s\"." +#~ msgid "Could not open extension control file \"%s\": %m." +#~ msgstr "გაფართოების კონტროლის ფაილის (\"%s\") გახსნის შეცდომა: %m." + +#, c-format +#~ msgid "ECDH: could not create key" +#~ msgstr "ECDH: გასაღების შექნის შეცდომა" + +#, c-format +#~ msgid "ECDH: unrecognized curve name: %s" +#~ msgstr "ECDH: მრუდის უცნობი სახელი: %s" + +#, c-format +#~ msgid "EXPLAIN option SERIALIZE requires ANALYZE" +#~ msgstr "EXPLAIN-ის პარამეტრს SERIALIZE 'ANALYZE' სჭირდება" + +#, c-format +#~ msgid "EXPLAIN option TIMING requires ANALYZE" +#~ msgstr "EXPLAIN -ის პარამეტრ TIMING-ს ANALYZE სჭირდება" #~ msgid "Enables logging of recovery-related debugging information." #~ msgstr "აღდგენასთან კავშირში მყოფი გამართვის ინფორმაციის ჟურნალში ჩაწერის ჩართვა." @@ -30294,6 +31784,14 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "Existing constraint \"%s\" is marked NO INHERIT." #~ msgstr "არსებული შეზღუდვა \"%s\" დანიშნულია, როგორც NO INHERIT." +#, c-format +#~ msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" +#~ msgstr "FORCE_NOT_NULL სვეტი \"%s\" COPY-ის მიერ მითითებული არაა" + +#, c-format +#~ msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" +#~ msgstr "FORCE_QUOTE სვეტი \"%s\" COPY-ის მიერ მითითებული არაა" + #, c-format #~ msgid "For example, FROM (SELECT ...) [AS] foo." #~ msgstr "მაგალითად, FROM (SELECT ...) [AS] foo." @@ -30306,6 +31804,9 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "Foreign tables cannot have TRUNCATE triggers." #~ msgstr "გარე ცხრილებს TRUNCATE ტრიგერები ვერ ექნებათ." +#~ msgid "If blank, no prefix is used." +#~ msgstr "თუ ცარიელია, პრეფიქსი არ გამოიყენება." + #~ msgid "Incremental parser requires incremental lexer" #~ msgstr "ინკრემენტულ დამმუშავებელს ინკრემენტული lexer სჭირდება" @@ -30320,9 +31821,16 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "JSON_TABLE column names must be distinct from one another" #~ msgstr "JSON_TABLE-ის სვეტის სახელები ერთმანეთისგან უნდა განსხვავდებოდნენ" +#, c-format +#~ msgid "LIKE is not supported for creating foreign tables" +#~ msgstr "გარე ცხრილების შექმნისთვის LIKE მხარდაჭერილი არაა" + #~ msgid "Log backtrace for any error with error code XX000 (internal error)." #~ msgstr "ნებისმიერი შეცდომის უკუტრეისის ჩაწერა ჟურნალში შეცდომის კოდით XX000 (შიდა შეცდომა)." +#~ msgid "Logs each successful connection." +#~ msgstr "ყოველი წარმატებული შესვლის ჟურნალში ჩაწერა." + #, c-format #~ msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled" #~ msgstr "MD5 ავთენტიკაცია მაშინ, როცა \"db_user_namespace\" ჩართულია, მხარდაჭერილი არაა" @@ -30335,21 +31843,59 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "MERGE not supported in WITH query" #~ msgstr "\"MERGE\"-ი \"WITH\" მოთხოვნაში მხარდაუჭერელია" +#, c-format +#~ msgid "MaxFragments should be >= 0" +#~ msgstr "MaxFragments >= 0 უნდა იყოს" + +#, c-format +#~ msgid "MinWords should be less than MaxWords" +#~ msgstr "MinWords MaxWords-ზე ნაკლები უნდა იყოს" + +#, c-format +#~ msgid "MinWords should be positive" +#~ msgstr "MinWords დადებით უნდა იყოს" + #, c-format #~ msgid "Object keys should be text." #~ msgstr "ობიექტის გასაღებები ტექსტი უნდა იყოს." #, c-format -#~ msgid "Only range and multirange are supported." -#~ msgstr "მხარდაჭერილია, მხოლოდ, შუალედი და მრავალი შუალედი." +#~ msgid "Please report this to <%s>." +#~ msgstr "გთხოვთ, შეატყობინოთ <%s>." + +#, c-format +#~ msgid "RECHECK is no longer required" +#~ msgstr "RECHECK საჭირო აღარაა" #~ msgid "Recursive descent parser cannot use incremental lexer" #~ msgstr "რეკურსიულ დაღმავალ დამმუშავებელს ინკრემენტული lexer-ის გამოყენება არ შეუძლია" +#~ msgid "Resource Usage / Asynchronous Behavior" +#~ msgstr "რესურსების გამოყენება / ასინქრონული ქცევა" + #, c-format #~ msgid "SQL/JSON item cannot be cast to target type" #~ msgstr "SQL/JSON ჩანაწერი მითითებულ ტიპში ვერ გადავა" +#, c-format +#~ msgid "Server has FLOAT8PASSBYVAL = %s, library has %s." +#~ msgstr "სერვერის FLOAT8PASSBYVAL = %s, ბიბლიოთეკას კი %s." + +#, c-format +#~ msgid "Server has FUNC_MAX_ARGS = %d, library has %d." +#~ msgstr "სერვერის FUNC_MAX_ARGS = %d, ბიბლიოთეკას კი %d." + +#, c-format +#~ msgid "Server has INDEX_MAX_KEYS = %d, library has %d." +#~ msgstr "სერვერის INDEX_MAX_KEYS = %d, ბიბლიოთეკას კი %d." + +#~ msgid "Sets the curve to use for ECDH." +#~ msgstr "ECDH-სთვის გამოყენებული მრუდის დაყენება." + +#, c-format +#~ msgid "ShortWord should be >= 0" +#~ msgstr "ShortWord >= 0 უნდა იყოს" + #~ msgid "Shows the character classification and case conversion locale." #~ msgstr "სიმბოლოების ზომის გადაყვანისა და სიმბოლოების კლასიფიკაციის ენის ჩვენება." @@ -30363,17 +31909,53 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgstr[1] "გამოწერილი პუბლიკაცია %s სხვა პუბლიკაციებს იწერს." #, c-format -#~ msgid "The column has an inherited not-null constraint." -#~ msgstr "სვეტს მემკვიდრეობით მიღებული არანულოვანი შეზღუდვა გააჩნია." +#~ msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა CATALOG_VERSION_NO %d -ით, მაგრამ სერვერი აგებულია CATALOG_VERSION_NO %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა INDEX_MAX_KEYS %d -ით, მაგრამ სერვერი აგებულია INDEX_MAX_KEYS %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა LOBLKSIZE %d -ით, მაგრამ სერვერი აგებულია LOBLKSIZE %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა MAXALIGN %d -ით, მაგრამ სერვერი აგებულია MAXALIGN %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა NAMEDATALEN %d -ით, მაგრამ სერვერი აგებულია NAMEDATALEN %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა RELSEG_SIZE%d -ით, მაგრამ სერვერი აგებულია RELSEG_SIZE %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა TOAST_MAX_CHUNK_SIZE %d -ით, მაგრამ სერვერი აგებულია TOAST_MAX_CHUNK_SIZE %d-ით." + +#, c-format +#~ msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." +#~ msgstr "მონაცემთა ბაზის კლასტერის ინიციალიზაცია მოხდა XLOG_BLCKSZ%d -ით, მაგრამ სერვერი აგებულია XLOG_BLCKSZ%d-ით." + +#, c-format +#~ msgid "This feature is not yet supported on partitioned tables." +#~ msgstr "ეს ოპერაცია დაყოფილი ცხრილებისთვის ჯერჯერობით მხარდაჭერილი არაა." #, c-format -#~ msgid "There is no suitable operator in operator family \"%s\" for access method \"%s\"." -#~ msgstr "ვერ ვიპოვე შესაბამისი ოპერატორი ოპერატორების ოჯახში \"%s\" წვდომის მეთოდისთვის \"%s\"." +#~ msgid "This slot is being synced from the primary server." +#~ msgstr "მიმდინარეობს ამ სლოტის სინქრონიზაცია ძირითადი სერვერიდან." #, c-format #~ msgid "Unmatched \"%c\" character." #~ msgstr "სიმბოლო \"%c\" არ ემთხვევა." +#, c-format +#~ msgid "Update your data type." +#~ msgstr "განაახლეთ თქვენი მონაცემთა ტიპი." + #, c-format #~ msgid "Use ALTER DATABASE ... REFRESH COLLATION VERSION instead." #~ msgstr "სანაცვლოდ გამოიყენეთ ALTER DATABASE ... REFRESH COLLATION VERSION." @@ -30408,6 +31990,12 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "Waiting for LSN can only be executed during recovery." #~ msgstr "LSN-ის მოლოდინი, მხოლოდ, აღდგენისას შეიძლება, შესრულდეს." +#~ msgid "Zero prints all actions. -1 turns autovacuum logging off." +#~ msgstr "0-ს ყველა ქმედება გამოაქვს. -1 გამორთავს ავტომომტვერსასრუტებას." + +#~ msgid "Zero prints all queries. -1 turns this feature off." +#~ msgstr "0-ს ყველა მოთხოვნა გამოაქვს, -1 გამორთავს ამ ფუნქციას." + #, c-format #~ msgid "argument %d cannot be null" #~ msgstr "არგუმენტი %d ნულოვანი ვერ იქნება" @@ -30423,6 +32011,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "bogus input" #~ msgstr "საეჭვო შეყვანა" +#, c-format +#~ msgid "can not find partition for split partition row" +#~ msgstr "დაყოფილი დანაყოფის მწკრივისთვის დანაყოფი ვერ ვიპოვე" + #, c-format #~ msgid "cannot add NOT NULL constraint to column \"%s\" of relation \"%s\" with inheritance children" #~ msgstr "ვერ დავამატე NOT NULL შეზღუდვა სვეტს \"%s\" ურთიერთობაზე \"%s\" რომელსაც მემკვიდრეობითი შვილები გააჩნია" @@ -30431,10 +32023,6 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "cannot change NO INHERIT status of NOT NULL constraint \"%s\" in relation \"%s\"" #~ msgstr "ურთიერთობაზე \"%2$s\" NOT NULL შეზღუდვის \"%1$s\" NO INHERIT სტატუსს ვერ შეცვლით" -#, c-format -#~ msgid "cannot change NO INHERIT status of NOT NULL constraint \"%s\" on relation \"%s\"" -#~ msgstr "ურთიერთობაზე \"%2$s\" NOT NULL შეზღუდვის \"%1$s\" NO INHERIT სტატუსს ვერ შეცვლით" - #, c-format #~ msgid "cannot change access method of a partitioned table" #~ msgstr "დაყოფილი ცხრილის წვდომის მეთოდის შეცვლა შეუძლებელია" @@ -30443,6 +32031,14 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "cannot commit subtransactions during a parallel operation" #~ msgstr "პარალელური ოპერაციის დროს ქვეტრანსაქციების გადაგზავნა შეუძლებელია" +#, c-format +#~ msgid "cannot create a permanent relation as partition of temporary relation \"%s\"" +#~ msgstr "მუდმივ ურთიერთობას დროებითი ურთიერთობის \"%s\" დანაყოფის სახით ვერ შექმნით" + +#, c-format +#~ msgid "cannot create as partition of temporary relation of another session" +#~ msgstr "სხვა სესის დროებითი ურთიერთობის დანაყოფის სახით ვერ შექმნით" + #, c-format #~ msgid "cannot create exclusion constraints on partitioned table \"%s\"" #~ msgstr "დაყოფილ ცხრილზე (\"%s\") ექსკლუზიური შეზღუდვების შექმნა შეუძლებელია" @@ -30451,6 +32047,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "cannot create restricted tokens on this platform: error code %lu" #~ msgstr "ამ პლატფორმაზე შეზღუდული კოდების შექმნა შეუძლებელია: შეცდომის კოდი %lu" +#, c-format +#~ msgid "cannot match partition key to an index using access method \"%s\"" +#~ msgstr "წვდომის მეთოდით \"%s\" დანაყოფის გასაღების ინდექსთან დამთხვევა შეუძლებელია" + #, c-format #~ msgid "cannot move table \"%s\" to schema \"%s\"" #~ msgstr "ცხრილის (%s) სქემაში (%s) გადატანა შეუძლებელია" @@ -30459,6 +32059,22 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" #~ msgstr "არასწორი ინდექსის \"%s.%s\" პარალელური რეინდექსი შეუძლებელია. გამოტოვება" +#, c-format +#~ msgid "cannot remove constraint from only the partitioned table when partitions exist" +#~ msgstr "შეზღუდვის წაშლა მხოლოდ დაყოფილი ცხრილიდან მაშინ, როცა დანაყოფები არსებობს, შეუძლებელია" + +#, c-format +#~ msgid "cannot specify DEFAULT in BINARY mode" +#~ msgstr "'BINARY' რეჟიმში DEFAULT-ს ვერ მიუთითებთ" + +#, c-format +#~ msgid "cannot specify DELIMITER in BINARY mode" +#~ msgstr "რეჟიმში BINARY \"DELIMITER\"-ს ვერ მიუთითებთ" + +#, c-format +#~ msgid "cannot specify HEADER in BINARY mode" +#~ msgstr "რეჟიმში BINARY \"HEADER\"-ს ვერ მიუთითებთ" + #, c-format #~ msgid "cannot start subtransactions during a parallel operation" #~ msgstr "პარალელური ოპერაციის დროს ქვეტრანსაქციების დაწყება შეუძლებელია" @@ -30467,10 +32083,26 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "cannot subtract infinite timestamps" #~ msgstr "უსასრულო დროის შტამპების გამოკლება შეუძლებელია" +#, c-format +#~ msgid "cannot use RETURNING type %s in %s" +#~ msgstr "'RETURNING'-ის ტიპს '%s' %s-ში ვერ გამოიყენებთ" + +#, c-format +#~ msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" +#~ msgstr "ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, ან ldapurl-ის ldapprefix-სთან ერთად გამოყენება შეუძლებელია" + +#, c-format +#~ msgid "cannot use more than one FOR ORDINALITY column" +#~ msgstr "ერთზე მეტ FOR ORDINALITY სვეტს ვერ გამოიყენებთ" + #, c-format #~ msgid "collation provider LIBC is not supported on this platform" #~ msgstr "კოლაციის მომწოდებელი LIBC ამ პლატფორმაზე მხარდაჭერილი არაა" +#, c-format +#~ msgid "column \"%s\" of relation \"%s\" is not a stored generated column" +#~ msgstr "ურთიერთობის \"%2$s\" სვეტი \"%1$s\" დამახსოვრებული გენერირებული სვეტი არაა" + #, c-format #~ msgid "conversion with OID %u does not exist" #~ msgstr "გადაყვანა OID-ით %u არ არსებობს" @@ -30523,22 +32155,6 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "could not form array type name for type \"%s\"" #~ msgstr "ტიპისთვის (%s) მასივის ტიპის სახელის ფორმირება შეუძლებელია" -#, c-format -#~ msgid "could not identify a contained-by operator for type %s" -#~ msgstr "ტიპისთვის \"%s\" ოპერატორი constained-by ვერ ვიპოვე" - -#, c-format -#~ msgid "could not identify an equality operator for foreign key" -#~ msgstr "გარე გასაღებისთვის ტოლობის ოპერატორი ვერ ვიპოვე" - -#, c-format -#~ msgid "could not identify an overlaps operator for foreign key" -#~ msgstr "ვერ აღმოვაჩინე გადაფარვების ოპერატორი გარე გასაღებისთვის" - -#, c-format -#~ msgid "could not identify an overlaps operator for type %s" -#~ msgstr "ვერ აღმოვაჩინე გადაფარვების ოპერატორი ტიპისთვის %s" - #, c-format #~ msgid "could not identify current directory: %m" #~ msgstr "მიმდინარე საქაღალდის იდენტიფიკაციის პრობლემა: %m" @@ -30551,6 +32167,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "could not load pg_hba.conf" #~ msgstr "pg_hba.conf -ის ჩატვირთვის სეცდომა" +#, c-format +#~ msgid "could not look up local user ID %d: %s" +#~ msgstr "ლოკალური მომხმარებლის ID-ის (%d) ამოხსნა შეუძლებელია: %s" + #, c-format #~ msgid "could not read from streaming transaction's changes file \"%s\": read only %zu of %zu bytes" #~ msgstr "შეკუმშული ფაილის (\"%s\") წაკითხვის შეცდომა: წაკითხულია %zu %zu-დან" @@ -30564,8 +32184,8 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgstr "ფაილის წაშლის შეცდომა \"%s\": %s\n" #, c-format -#~ msgid "could not remove file or directory \"%s\": %m" -#~ msgstr "ფაილის ან საქაღალდე „%s“ ვერ წაიშალა: %m" +#~ msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" +#~ msgstr "სტატისტიკის დროებითი ფაილის \"%s\"-დან \"%s\" -მდე სახელის გადარქმევა შეუძლებელია: %m" #, c-format #~ msgid "could not set compression flag for %s: %s" @@ -30575,6 +32195,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "could not stat promote trigger file \"%s\": %m" #~ msgstr "წახალისების ტრიგერის ფაილი (\"%s\") არ არსებობს: %m" +#, c-format +#~ msgid "could not sync slot \"%s\"" +#~ msgstr "სლოტის \"%s\" სინქრონიზაცია შეუძლებელია" + #, c-format #~ msgid "could not unlink file \"%s\": %m" #~ msgstr "ფაილის (%s) ბმულის მოხსნის შეცდომა: %m" @@ -30603,6 +32227,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "duplicate JSON object key" #~ msgstr "დუბლირებული JSON ობიექტის გასაღები" +#, c-format +#~ msgid "end-of-copy marker corrupt" +#~ msgstr "კოპირების-დასასრულის სანიშნი დაზიანებულია" + #, c-format #~ msgid "extension with OID %u does not exist" #~ msgstr "გაფართოება OID-ით %u არ არსებობს" @@ -30611,10 +32239,18 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "gtsvector_in not implemented" #~ msgstr "gtsvector_in განხორციელებული არაა" +#, c-format +#~ msgid "index %lld out of valid range, 0..%lld" +#~ msgstr "ინდექსი %lld დასაშვებ დიაპაზონს (0..%lld) გარეთაა" + #, c-format #~ msgid "int2vector has too many elements" #~ msgstr "int2vector -ს მეტისმეტად ბევრი ელემენტი აქვს" +#, c-format +#~ msgid "interval out of range." +#~ msgstr "ინტერვალი დაშვებული შუალედის გარეთაა." + #, c-format #~ msgid "invalid JSON_TABLE expression" #~ msgstr "\"JSON_TABLE\"-ის არასწორი გამოსახულება" @@ -30623,6 +32259,14 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "invalid JSON_TABLE plan" #~ msgstr "\"JSON_TABLE\"-ის არასწორი გეგმა" +#, c-format +#~ msgid "invalid ON ERROR behavior" +#~ msgstr "\"ON UPDATE\"-ის არასწორი ქცევა" + +#, c-format +#~ msgid "invalid ON ERROR behavior for column \"%s\"" +#~ msgstr "\"ON ERROR\"-ის არასწორი ქცევა სვეტისთვის \"%s\"" + #, c-format #~ msgid "invalid checkpoint link in backup_label file" #~ msgstr "backup_label ფაილში არსებული საკონტროლო წერტილი არასწორია" @@ -30635,10 +32279,6 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "invalid parameter name \"%s\"" #~ msgstr "პარამეტრის არასწორი სახელი \"%s\"" -#, c-format -#~ msgid "invalid primary key definition" -#~ msgstr "არასწორი ძირითადი გასაღების აღწერა" - #, c-format #~ msgid "invalid record offset at %X/%X" #~ msgstr "ჩანაწერის არასწორი წანაცვლება მისამართზე %X/%X" @@ -30668,10 +32308,29 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "logical replication table synchronization worker" #~ msgstr "ლოგიკური რეპლიკაციის ცხრილის სინქრონიზაციის დამხმარე პროცესი" +#, c-format +#~ msgid "lower bound of partition \"%s\" conflicts with upper bound of previous partition \"%s\"" +#~ msgstr "დანაყოფის \"%s\" ქვედა ზღვარი კონფლიქტშია ზედა ზღვართან წინა დანაყოფისთვის \"%s\"" + +#, c-format +#~ msgid "lower bound of partition \"%s\" is less than lower bound of split partition" +#~ msgstr "ქვედა ზღვარი დანაყოფისთვის \"%s\" დაყოფილი დანაყოფის ქვედა საზღვარზე ნაკლებია" + +#, c-format +#~ msgid "lower bound of partition \"%s\" is not equal to lower bound of split partition" +#~ msgstr "ქვედა ზღვარი დანაყოფისთვის \"%s\" არ უდრის დაყოფილი დანაყოფის ქვედა საზღვარს" + +#~ msgid "manifest system identifier not an integer" +#~ msgstr "მანიფესტის სისტემის იდენფიტიკატორი მთელი რიცხვი არაა" + #, c-format #~ msgid "missing contrecord at %X/%X" #~ msgstr "მისამართზე %X/%X contrecord ალამი არ არსებობს" +#, c-format +#~ msgid "multiple limit options not allowed" +#~ msgstr "ლიმიტის პარამეტრების მითითება მხოლოდ ერთხელ შეგიძლიათ" + #, c-format #~ msgid "must be a superuser to terminate superuser process" #~ msgstr "ზემომხმარებლის პროცესის დასასრულებლად ზემომხმარებელი უნდა ბრძანდებოდეთ" @@ -30724,6 +32383,22 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "must have privileges of pg_create_subscription to create subscriptions" #~ msgstr "გამოწერების შესაქმნელად pg_create_subscription-ის პრივილეგიები გჭიდებათ" +#, c-format +#~ msgid "name \"%s\" is already used" +#~ msgstr "სახელი \"%s\" უკვე გამოყენებულია" + +#, c-format +#~ msgid "new partition \"%s\" would overlap with another (not split) partition \"%s\"" +#~ msgstr "ახალი დანაყოფი \"%s\" გადაფარავდა სხვა (არა დაყოფილ) დანაყოფს \"%s\"" + +#, c-format +#~ msgid "new partition \"%s\" would overlap with another new partition \"%s\"" +#~ msgstr "ახალი დანაყოფი \"%s\" გადაფარავდა სხვა ახალ დანაყოფს \"%s\"" + +#, c-format +#~ msgid "new partitions do not have value %s but split partition does" +#~ msgstr "ახალ დანაყოფს არ აქვს მნიშვნელობა %s, მაგრამ გაყოფილ დანაყოფს აქვს" + #, c-format #~ msgid "no SQL/JSON item" #~ msgstr "\"SQL/JSON\" ჩანაწერების გარეშე" @@ -30733,8 +32408,8 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgstr "არანულოვანი შეზღუდვა სვეტზე \"%s\" შვილ ცხრილებშიც უნდა წაიშალოს" #, c-format -#~ msgid "not-null constraints on partitioned tables cannot be NO INHERIT" -#~ msgstr "არანულოვანი შეზღუდვები დაყოფილ ცხრილზე NO INHERIT ვერ იქნება" +#~ msgid "not-null constraints are not supported on virtual generated columns" +#~ msgstr "ვირტუალურ დაგენერირებულ სვეტებზე არანულოვანი შეზღუდვები მხარდაჭერილი არაა" #, c-format #~ msgid "oidvector has too many elements" @@ -30752,6 +32427,16 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "operator with OID %u does not exist" #~ msgstr "ოპერატორი OID-ით %u არ არსებობს" +#, c-format +#~ msgid "" +#~ "out of memory\n" +#~ "\n" +#~ "Cannot enlarge string buffer containing %d bytes by %d more bytes.\n" +#~ msgstr "" +#~ "არასაკმარისი მეხსიერება\n" +#~ "\n" +#~ "შეუძლებელია სტრიქონის ბუფერის (%d ბაიტი) გაფართოება %d ბაიტით.\n" + #, c-format #~ msgid "out of memory while trying to decode a record of length %u" #~ msgstr "%u სიგრძის მქონე ჩანაწერის დეკოდირებისთვის მეხსიერება საკმარისი არაა" @@ -30764,14 +32449,37 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "parameter \"lc_ctype\" must be specified" #~ msgstr "უნდა იყოს მითითებული პარამეტრი \"lc_ctype\"" +#, c-format +#~ msgid "partition of hash-partitioned table cannot be merged" +#~ msgstr "ჰეშით დაყოფილი ცხრილის დანაყოფების შერწყმა შეუძლებელია" + +#, c-format +#~ msgid "partition of hash-partitioned table cannot be split" +#~ msgstr "ჰეშით დაყოფილი ცხრილის დანაყოფების დაყოფა შეუძლებელია" + +#, c-format +#~ msgid "partition with name \"%s\" is already used" +#~ msgstr "დანაყოფი სახელით \"%s\" უკვე გამოყენებულია" + #, c-format #~ msgid "promote trigger file found: %s" #~ msgstr "ნაპოვნია წახალისების ტრიგერის ფაილი: %s" +#, c-format +#~ msgid "proto_version option missing" +#~ msgstr "პარამეტრი proto_version მითითებული არაა" + +#, c-format +#~ msgid "publication_names option missing" +#~ msgstr "აკლა პარამეტრი publication_names" + #, c-format #~ msgid "record length %u at %X/%X too long" #~ msgstr "ჩანაწერის სიგრძე %u მისამართზე %X/%X ძალიან გრძელია" +#~ msgid "server process" +#~ msgstr "სერვერის პროცესი" + #, c-format #~ msgid "snapshot too old" #~ msgstr "სწრაფი ასლი ძალიან ძველია" @@ -30816,6 +32524,10 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgid "timestamp_tz format is not recognized: \"%s\"" #~ msgstr "timestamp_tz-ის ფორმატი უცნობია: \"%s\"" +#, c-format +#~ msgid "too many wait events for extensions" +#~ msgstr "მეტისმეტად ბევრი მოცდის მოვლენა გაფართოებებისთვის" + #, c-format #~ msgid "unable to map dynamic shared memory segment" #~ msgstr "დინამიური გაზიარებული მეხსიერების სეგმენტის მიბმის შეცდომა" @@ -30840,5 +32552,13 @@ msgstr "სხვა ბაზიდან სწრაფი ასლის #~ msgstr "სტატისტიკის მუდმივი ფაილი მოხსნილია: %s" #, c-format -#~ msgid "unsupported %s action for foreign key constraint using PERIOD" -#~ msgstr "მხარდაუჭერელი %s ქმედება გარე გასაღების შეზღუდვისთვის, რომელიც PERIOD-ს იყენებს" +#~ msgid "upper bound of partition \"%s\" is greater than upper bound of split partition" +#~ msgstr "ზედა ზღვარი დანაყოფისთვის \"%s\" დაყოფილი დანაყოფის ზედა საზღვარზე მეტია" + +#, c-format +#~ msgid "upper bound of partition \"%s\" is not equal to upper bound of split partition" +#~ msgstr "ზედა ზღვარი დანაყოფისთვის \"%s\" არ უდრის დაყოფილი დანაყოფის ზედა საზღვარს" + +#, c-format +#~ msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +#~ msgstr "სერვისის გაშვებისას wal_level -ის მნიშვნელობა უნდა იყოს \"replica\" ან \"logical\"." diff --git a/src/backend/po/ko.po b/src/backend/po/ko.po index b367ff4dcdeab..d71eed4b6c0eb 100644 --- a/src/backend/po/ko.po +++ b/src/backend/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: postgres (PostgreSQL) 16\n" +"Project-Id-Version: postgres (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:40+0000\n" -"PO-Revision-Date: 2023-09-08 16:12+0900\n" +"POT-Creation-Date: 2025-01-17 04:41+0000\n" +"PO-Revision-Date: 2025-01-20 16:44+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -15,6 +15,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +#: ../common/binaryheap.c:121 ../common/binaryheap.c:159 +#, c-format +msgid "out of binary heap slots" +msgstr "바이너리 힙 슬롯수 초과" + #: ../common/compression.c:132 ../common/compression.c:141 #: ../common/compression.c:150 #, c-format @@ -75,64 +80,66 @@ msgstr "\"%s\" 압축 알고리즘은 long-distance mode를 지원하지 않음" msgid "not recorded" msgstr "기록되어 있지 않음" -#: ../common/controldata_utils.c:69 ../common/controldata_utils.c:73 -#: commands/copyfrom.c:1670 commands/extension.c:3480 utils/adt/genfile.c:123 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 +#: commands/copyfrom.c:1739 commands/extension.c:3538 utils/adt/genfile.c:123 +#: utils/time/snapmgr.c:1430 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" -#: ../common/controldata_utils.c:84 ../common/controldata_utils.c:86 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 #: access/transam/timeline.c:143 access/transam/timeline.c:362 -#: access/transam/twophase.c:1347 access/transam/xlog.c:3193 -#: access/transam/xlog.c:3996 access/transam/xlogrecovery.c:1199 -#: access/transam/xlogrecovery.c:1291 access/transam/xlogrecovery.c:1328 -#: access/transam/xlogrecovery.c:1388 backup/basebackup.c:1842 -#: commands/extension.c:3490 libpq/hba.c:769 replication/logical/origin.c:745 -#: replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5050 -#: replication/logical/snapbuild.c:2031 replication/slot.c:1953 -#: replication/slot.c:1994 replication/walsender.c:643 +#: access/transam/twophase.c:1369 access/transam/xlog.c:3477 +#: access/transam/xlog.c:4341 access/transam/xlogrecovery.c:1238 +#: access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 +#: access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 +#: backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 +#: replication/logical/reorderbuffer.c:5113 +#: replication/logical/snapbuild.c:2052 replication/slot.c:2236 +#: replication/slot.c:2277 replication/walsender.c:655 #: storage/file/buffile.c:470 storage/file/copydir.c:185 -#: utils/adt/genfile.c:197 utils/adt/misc.c:984 utils/cache/relmapper.c:827 +#: utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "\"%s\" 파일을 읽을 수 없음: %m" -#: ../common/controldata_utils.c:92 ../common/controldata_utils.c:95 -#: access/transam/xlog.c:3198 access/transam/xlog.c:4001 -#: backup/basebackup.c:1846 replication/logical/origin.c:750 -#: replication/logical/origin.c:789 replication/logical/snapbuild.c:2036 -#: replication/slot.c:1957 replication/slot.c:1998 replication/walsender.c:648 -#: utils/cache/relmapper.c:831 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 +#: access/transam/xlog.c:3482 access/transam/xlog.c:4346 +#: replication/logical/origin.c:750 replication/logical/origin.c:789 +#: replication/logical/snapbuild.c:2057 replication/slot.c:2240 +#: replication/slot.c:2281 replication/walsender.c:660 +#: utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" -#: ../common/controldata_utils.c:104 ../common/controldata_utils.c:108 -#: ../common/controldata_utils.c:233 ../common/controldata_utils.c:236 -#: access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1280 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 +#: ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 +#: access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 #: access/transam/timeline.c:392 access/transam/timeline.c:438 -#: access/transam/timeline.c:512 access/transam/twophase.c:1359 -#: access/transam/twophase.c:1771 access/transam/xlog.c:3039 -#: access/transam/xlog.c:3233 access/transam/xlog.c:3238 -#: access/transam/xlog.c:3374 access/transam/xlog.c:3966 -#: access/transam/xlog.c:4885 commands/copyfrom.c:1730 commands/copyto.c:332 +#: access/transam/timeline.c:512 access/transam/twophase.c:1381 +#: access/transam/twophase.c:1800 access/transam/xlog.c:3323 +#: access/transam/xlog.c:3517 access/transam/xlog.c:3522 +#: access/transam/xlog.c:3658 access/transam/xlog.c:4311 +#: access/transam/xlog.c:5246 commands/copyfrom.c:1799 commands/copyto.c:325 #: libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 #: replication/logical/origin.c:683 replication/logical/origin.c:822 -#: replication/logical/reorderbuffer.c:5102 -#: replication/logical/snapbuild.c:1798 replication/logical/snapbuild.c:1922 -#: replication/slot.c:1844 replication/slot.c:2005 replication/walsender.c:658 -#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:782 -#: storage/file/fd.c:3700 storage/file/fd.c:3806 utils/cache/relmapper.c:839 -#: utils/cache/relmapper.c:945 +#: replication/logical/reorderbuffer.c:5165 +#: replication/logical/snapbuild.c:1819 replication/logical/snapbuild.c:1943 +#: replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 +#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:828 +#: storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 +#: utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "\"%s\" 파일을 닫을 수 없음: %m" -#: ../common/controldata_utils.c:124 +#: ../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "바이트 순서 불일치" -#: ../common/controldata_utils.c:126 +#: ../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -147,142 +154,158 @@ msgstr "" "지 않으며\n" "현재 PostgreSQL 설치본과 이 데이터 디렉터리가 호환하지 않습니다." -#: ../common/controldata_utils.c:181 ../common/controldata_utils.c:186 -#: ../common/file_utils.c:228 ../common/file_utils.c:287 -#: ../common/file_utils.c:361 access/heap/rewriteheap.c:1263 -#: access/transam/timeline.c:111 access/transam/timeline.c:251 -#: access/transam/timeline.c:348 access/transam/twophase.c:1303 -#: access/transam/xlog.c:2946 access/transam/xlog.c:3109 -#: access/transam/xlog.c:3148 access/transam/xlog.c:3341 -#: access/transam/xlog.c:3986 access/transam/xlogrecovery.c:4179 -#: access/transam/xlogrecovery.c:4282 access/transam/xlogutils.c:838 -#: backup/basebackup.c:538 backup/basebackup.c:1512 libpq/hba.c:629 -#: postmaster/syslogger.c:1560 replication/logical/origin.c:735 -#: replication/logical/reorderbuffer.c:3706 -#: replication/logical/reorderbuffer.c:4257 -#: replication/logical/reorderbuffer.c:5030 -#: replication/logical/snapbuild.c:1753 replication/logical/snapbuild.c:1863 -#: replication/slot.c:1925 replication/walsender.c:616 -#: replication/walsender.c:2731 storage/file/copydir.c:151 -#: storage/file/fd.c:757 storage/file/fd.c:3457 storage/file/fd.c:3687 -#: storage/file/fd.c:3777 storage/smgr/md.c:663 utils/cache/relmapper.c:816 -#: utils/cache/relmapper.c:924 utils/error/elog.c:2082 -#: utils/init/miscinit.c:1530 utils/init/miscinit.c:1664 -#: utils/init/miscinit.c:1741 utils/misc/guc.c:4600 utils/misc/guc.c:4650 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 +#: ../common/file_utils.c:70 ../common/file_utils.c:347 +#: ../common/file_utils.c:406 ../common/file_utils.c:480 +#: access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 +#: access/transam/timeline.c:251 access/transam/timeline.c:348 +#: access/transam/twophase.c:1325 access/transam/xlog.c:3230 +#: access/transam/xlog.c:3393 access/transam/xlog.c:3432 +#: access/transam/xlog.c:3625 access/transam/xlog.c:4331 +#: access/transam/xlogrecovery.c:4263 access/transam/xlogrecovery.c:4366 +#: access/transam/xlogutils.c:836 backup/basebackup.c:547 +#: backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 +#: postmaster/syslogger.c:1511 replication/logical/origin.c:735 +#: replication/logical/reorderbuffer.c:3766 +#: replication/logical/reorderbuffer.c:4320 +#: replication/logical/reorderbuffer.c:5093 +#: replication/logical/snapbuild.c:1774 replication/logical/snapbuild.c:1884 +#: replication/slot.c:2208 replication/walsender.c:628 +#: replication/walsender.c:3051 storage/file/copydir.c:151 +#: storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 +#: storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 +#: utils/cache/relmapper.c:935 utils/error/elog.c:2124 +#: utils/init/miscinit.c:1580 utils/init/miscinit.c:1714 +#: utils/init/miscinit.c:1791 utils/misc/guc.c:4777 utils/misc/guc.c:4827 #, c-format msgid "could not open file \"%s\": %m" msgstr "\"%s\" 파일을 열 수 없음: %m" -#: ../common/controldata_utils.c:202 ../common/controldata_utils.c:205 -#: access/transam/twophase.c:1744 access/transam/twophase.c:1753 -#: access/transam/xlog.c:8755 access/transam/xlogfuncs.c:708 -#: backup/basebackup_server.c:175 backup/basebackup_server.c:268 -#: postmaster/postmaster.c:5573 postmaster/syslogger.c:1571 -#: postmaster/syslogger.c:1584 postmaster/syslogger.c:1597 -#: utils/cache/relmapper.c:936 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 +#: access/transam/twophase.c:1773 access/transam/twophase.c:1782 +#: access/transam/xlog.c:9280 access/transam/xlogfuncs.c:698 +#: backup/basebackup_server.c:173 backup/basebackup_server.c:266 +#: backup/walsummary.c:304 postmaster/postmaster.c:4124 +#: postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 +#: postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "\"%s\" 파일 쓰기 실패: %m" -#: ../common/controldata_utils.c:219 ../common/controldata_utils.c:224 -#: ../common/file_utils.c:299 ../common/file_utils.c:369 -#: access/heap/rewriteheap.c:959 access/heap/rewriteheap.c:1169 -#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:432 -#: access/transam/timeline.c:506 access/transam/twophase.c:1765 -#: access/transam/xlog.c:3032 access/transam/xlog.c:3227 -#: access/transam/xlog.c:3959 access/transam/xlog.c:8145 -#: access/transam/xlog.c:8190 backup/basebackup_server.c:209 -#: replication/logical/snapbuild.c:1791 replication/slot.c:1830 -#: replication/slot.c:1935 storage/file/fd.c:774 storage/file/fd.c:3798 -#: storage/smgr/md.c:1135 storage/smgr/md.c:1180 storage/sync/sync.c:451 -#: utils/misc/guc.c:4370 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 +#: ../common/file_utils.c:418 ../common/file_utils.c:488 +#: access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 +#: access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 +#: access/transam/timeline.c:506 access/transam/twophase.c:1794 +#: access/transam/xlog.c:3316 access/transam/xlog.c:3511 +#: access/transam/xlog.c:4304 access/transam/xlog.c:8655 +#: access/transam/xlog.c:8700 backup/basebackup_server.c:207 +#: commands/dbcommands.c:514 replication/logical/snapbuild.c:1812 +#: replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 +#: storage/file/fd.c:3851 storage/smgr/md.c:1331 storage/smgr/md.c:1376 +#: storage/sync/sync.c:446 utils/misc/guc.c:4530 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "\"%s\" 파일 fsync 실패: %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:133 -#: ../common/cryptohash_openssl.c:332 ../common/exec.c:550 ../common/exec.c:595 -#: ../common/exec.c:687 ../common/hmac.c:309 ../common/hmac.c:325 -#: ../common/hmac_openssl.c:132 ../common/hmac_openssl.c:327 -#: ../common/md5_common.c:155 ../common/psprintf.c:143 -#: ../common/scram-common.c:258 ../common/stringinfo.c:305 ../port/path.c:751 -#: ../port/path.c:789 ../port/path.c:806 access/transam/twophase.c:1412 -#: access/transam/xlogrecovery.c:589 lib/dshash.c:253 libpq/auth.c:1345 -#: libpq/auth.c:1389 libpq/auth.c:1946 libpq/be-secure-gssapi.c:524 -#: postmaster/bgworker.c:352 postmaster/bgworker.c:934 -#: postmaster/postmaster.c:2537 postmaster/postmaster.c:4130 -#: postmaster/postmaster.c:5498 postmaster/postmaster.c:5869 -#: replication/libpqwalreceiver/libpqwalreceiver.c:308 -#: replication/logical/logical.c:208 replication/walsender.c:686 -#: storage/buffer/localbuf.c:601 storage/file/fd.c:866 storage/file/fd.c:1397 -#: storage/file/fd.c:1558 storage/file/fd.c:2478 storage/ipc/procarray.c:1449 -#: storage/ipc/procarray.c:2232 storage/ipc/procarray.c:2239 -#: storage/ipc/procarray.c:2738 storage/ipc/procarray.c:3374 -#: utils/adt/formatting.c:1690 utils/adt/formatting.c:1812 -#: utils/adt/formatting.c:1935 utils/adt/pg_locale.c:469 -#: utils/adt/pg_locale.c:633 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:514 -#: utils/hash/dynahash.c:614 utils/hash/dynahash.c:1111 utils/mb/mbutils.c:402 -#: utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 utils/mb/mbutils.c:842 -#: utils/misc/guc.c:640 utils/misc/guc.c:665 utils/misc/guc.c:1053 -#: utils/misc/guc.c:4348 utils/misc/tzparser.c:476 utils/mmgr/aset.c:445 -#: utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:736 utils/mmgr/dsa.c:817 -#: utils/mmgr/generation.c:205 utils/mmgr/mcxt.c:1046 utils/mmgr/mcxt.c:1082 -#: utils/mmgr/mcxt.c:1120 utils/mmgr/mcxt.c:1158 utils/mmgr/mcxt.c:1246 -#: utils/mmgr/mcxt.c:1277 utils/mmgr/mcxt.c:1313 utils/mmgr/mcxt.c:1502 -#: utils/mmgr/mcxt.c:1547 utils/mmgr/mcxt.c:1604 utils/mmgr/slab.c:366 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 +#: ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 +#: ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 +#: ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 +#: ../common/md5_common.c:156 ../common/parse_manifest.c:157 +#: ../common/parse_manifest.c:852 ../common/psprintf.c:143 +#: ../common/scram-common.c:268 ../common/stringinfo.c:314 ../port/path.c:751 +#: ../port/path.c:788 ../port/path.c:805 access/transam/twophase.c:1434 +#: access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 +#: libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 +#: postmaster/bgworker.c:355 postmaster/bgworker.c:945 +#: postmaster/postmaster.c:3558 postmaster/postmaster.c:4018 +#: postmaster/postmaster.c:4380 postmaster/walsummarizer.c:935 +#: replication/libpqwalreceiver/libpqwalreceiver.c:387 +#: replication/logical/logical.c:210 replication/walsender.c:835 +#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 +#: storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1465 +#: storage/ipc/procarray.c:2219 storage/ipc/procarray.c:2226 +#: storage/ipc/procarray.c:2731 storage/ipc/procarray.c:3435 +#: utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 +#: utils/adt/formatting.c:2075 utils/adt/pg_locale.c:532 +#: utils/adt/pg_locale.c:696 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 +#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 +#: utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 +#: utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 +#: utils/misc/guc.c:4508 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 +#: utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 +#: utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 +#: utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "메모리 부족" #: ../common/cryptohash.c:266 ../common/cryptohash.c:272 -#: ../common/cryptohash_openssl.c:344 ../common/cryptohash_openssl.c:352 -#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:339 -#: ../common/hmac_openssl.c:347 +#: ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 +#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 +#: ../common/hmac_openssl.c:377 msgid "success" msgstr "성공" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:346 -#: ../common/hmac_openssl.c:341 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 +#: ../common/hmac_openssl.c:371 msgid "destination buffer too small" msgstr "대상 버퍼가 너무 작습니다." -#: ../common/cryptohash_openssl.c:348 ../common/hmac_openssl.c:343 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 msgid "OpenSSL failure" msgstr "OpenSSL 실패" -#: ../common/exec.c:172 +#: ../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일임: %m" -#: ../common/exec.c:215 +#: ../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" # translator: %s is IPv4, IPv6, or Unix -#: ../common/exec.c:223 +#: ../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "\"%s\" 실행 파일을 찾을 수 없음" -#: ../common/exec.c:250 +#: ../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 상대 경로를 절대 경로로 바꿀 수 없음: %m" -#: ../common/exec.c:412 libpq/pqcomm.c:728 storage/ipc/latch.c:1128 -#: storage/ipc/latch.c:1308 storage/ipc/latch.c:1541 storage/ipc/latch.c:1703 -#: storage/ipc/latch.c:1829 +#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1723 +#: commands/copyto.c:654 libpq/be-secure-common.c:59 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령에서 읽을 수 없음: %m" + +#: ../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령은 아무런 데이터도 반환하지 않았음" + +#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 +#: storage/ipc/latch.c:1349 storage/ipc/latch.c:1582 storage/ipc/latch.c:1744 +#: storage/ipc/latch.c:1870 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" #: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 #: ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 -#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:791 -#: ../port/path.c:808 utils/misc/ps_status.c:168 utils/misc/ps_status.c:176 -#: utils/misc/ps_status.c:203 utils/misc/ps_status.c:211 +#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:790 +#: ../port/path.c:807 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 +#: utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 #, c-format msgid "out of memory\n" msgstr "메모리 부족\n" @@ -292,39 +315,51 @@ msgstr "메모리 부족\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" -#: ../common/file_utils.c:87 ../common/file_utils.c:447 -#: ../common/file_utils.c:451 access/transam/twophase.c:1315 -#: access/transam/xlogarchive.c:112 access/transam/xlogarchive.c:229 -#: backup/basebackup.c:346 backup/basebackup.c:544 backup/basebackup.c:615 -#: commands/copyfrom.c:1680 commands/copyto.c:702 commands/extension.c:3469 -#: commands/tablespace.c:810 commands/tablespace.c:899 postmaster/pgarch.c:590 -#: replication/logical/snapbuild.c:1649 storage/file/fd.c:1922 -#: storage/file/fd.c:2008 storage/file/fd.c:3511 utils/adt/dbsize.c:106 -#: utils/adt/dbsize.c:258 utils/adt/dbsize.c:338 utils/adt/genfile.c:483 -#: utils/adt/genfile.c:658 utils/adt/misc.c:340 +#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일 대상으로 파일 시스템 동기화를 할 수 없습니다: %m" + +#: ../common/file_utils.c:120 ../common/file_utils.c:566 +#: ../common/file_utils.c:570 access/transam/twophase.c:1337 +#: access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 +#: backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 +#: backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1749 +#: commands/copyto.c:700 commands/extension.c:3527 commands/tablespace.c:804 +#: commands/tablespace.c:893 postmaster/pgarch.c:680 +#: replication/logical/snapbuild.c:1670 replication/logical/snapbuild.c:2173 +#: storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 +#: utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 +#: utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" -#: ../common/file_utils.c:162 ../common/pgfnames.c:48 ../common/rmtree.c:63 -#: commands/tablespace.c:734 commands/tablespace.c:744 -#: postmaster/postmaster.c:1564 storage/file/fd.c:2880 -#: storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:338 +#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../common/file_utils.c:151 ../common/file_utils.c:281 +#: ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 +#: commands/tablespace.c:738 postmaster/postmaster.c:1468 +#: storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 +#: utils/misc/tzparser.c:339 #, c-format msgid "could not open directory \"%s\": %m" msgstr "\"%s\" 디렉터리 열 수 없음: %m" -#: ../common/file_utils.c:196 ../common/pgfnames.c:69 ../common/rmtree.c:104 -#: storage/file/fd.c:2892 +#: ../common/file_utils.c:169 ../common/file_utils.c:315 +#: ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 #, c-format msgid "could not read directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" -#: ../common/file_utils.c:379 access/transam/xlogarchive.c:383 -#: postmaster/pgarch.c:746 postmaster/syslogger.c:1608 -#: replication/logical/snapbuild.c:1810 replication/slot.c:723 -#: replication/slot.c:1716 replication/slot.c:1858 storage/file/fd.c:792 -#: utils/time/snapmgr.c:1284 +#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 +#: postmaster/pgarch.c:834 postmaster/syslogger.c:1559 +#: replication/logical/snapbuild.c:1831 replication/slot.c:936 +#: replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 +#: utils/time/snapmgr.c:1255 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" @@ -333,75 +368,87 @@ msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" msgid "internal error" msgstr "내부 오류" -#: ../common/jsonapi.c:1144 +#: ../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "재귀적 하향 구문분석기는 증분 토큰분석기을 사용할 수 없습니다." + +#: ../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "증분 구문분석기는 증분 토큰분석기를 필요로 합니다." + +#: ../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON 계층이 너무 깊음, 허용하는 최대 깊이는 6400입니다." + +#: ../common/jsonapi.c:2127 #, c-format -msgid "Escape sequence \"\\%s\" is invalid." -msgstr "잘못된 이스케이프 조합: \"\\%s\"" +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "잘못된 이스케이프 조합: \"\\%.*s\"" -#: ../common/jsonapi.c:1147 +#: ../common/jsonapi.c:2131 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "0x%02x 값의 문자는 이스케이프 처리를 해야함." -#: ../common/jsonapi.c:1150 +#: ../common/jsonapi.c:2135 #, c-format -msgid "Expected end of input, but found \"%s\"." -msgstr "입력 자료의 끝을 기대했는데, \"%s\" 값이 더 있음." +msgid "Expected end of input, but found \"%.*s\"." +msgstr "입력 자료의 끝을 기대했는데, \"%.*s\" 값이 더 있음." -#: ../common/jsonapi.c:1153 +#: ../common/jsonapi.c:2138 #, c-format -msgid "Expected array element or \"]\", but found \"%s\"." -msgstr "\"]\" 가 필요한데 \"%s\"이(가) 있음" +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "배열 요소나 \"]\" 가 필요한데 \"%.*s\"이(가) 있음" -#: ../common/jsonapi.c:1156 +#: ../common/jsonapi.c:2141 #, c-format -msgid "Expected \",\" or \"]\", but found \"%s\"." -msgstr "\",\" 또는 \"]\"가 필요한데 \"%s\"이(가) 있음" +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "\",\" 또는 \"]\"가 필요한데 \"%.*s\"이(가) 있음" -#: ../common/jsonapi.c:1159 +#: ../common/jsonapi.c:2144 #, c-format -msgid "Expected \":\", but found \"%s\"." -msgstr "\":\"가 필요한데 \"%s\"이(가) 있음" +msgid "Expected \":\", but found \"%.*s\"." +msgstr "\":\"가 필요한데 \"%.*s\"이(가) 있음" -#: ../common/jsonapi.c:1162 +#: ../common/jsonapi.c:2147 #, c-format -msgid "Expected JSON value, but found \"%s\"." -msgstr "JSON 값을 기대했는데, \"%s\" 값임" +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "JSON 값을 기대했는데, \"%.*s\" 값임" -#: ../common/jsonapi.c:1165 +#: ../common/jsonapi.c:2150 msgid "The input string ended unexpectedly." msgstr "입력 문자열이 예상치 않게 끝났음." -#: ../common/jsonapi.c:1167 +#: ../common/jsonapi.c:2152 #, c-format -msgid "Expected string or \"}\", but found \"%s\"." -msgstr "\"}\"가 필요한데 \"%s\"이(가) 있음" +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "문자열이나 \"}\"가 필요한데 \"%.*s\"이(가) 있음" -#: ../common/jsonapi.c:1170 +#: ../common/jsonapi.c:2155 #, c-format -msgid "Expected \",\" or \"}\", but found \"%s\"." -msgstr "\",\" 또는 \"}\"가 필요한데 \"%s\"이(가) 있음" +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "\",\" 또는 \"}\"가 필요한데 \"%.*s\"이(가) 있음" -#: ../common/jsonapi.c:1173 +#: ../common/jsonapi.c:2158 #, c-format -msgid "Expected string, but found \"%s\"." -msgstr "문자열 값을 기대했는데, \"%s\" 값임" +msgid "Expected string, but found \"%.*s\"." +msgstr "문자열 값을 기대했는데, \"%.*s\" 값임" -#: ../common/jsonapi.c:1176 +#: ../common/jsonapi.c:2161 #, c-format -msgid "Token \"%s\" is invalid." -msgstr "잘못된 토큰: \"%s\"" +msgid "Token \"%.*s\" is invalid." +msgstr "잘못된 토큰: \"%.*s\"" -#: ../common/jsonapi.c:1179 jsonpath_scan.l:597 +#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 값은 text 형으로 변환할 수 없음." -#: ../common/jsonapi.c:1181 +#: ../common/jsonapi.c:2166 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\" 표기법은 뒤에 4개의 16진수가 와야 합니다." -#: ../common/jsonapi.c:1184 +#: ../common/jsonapi.c:2169 msgid "" "Unicode escape values cannot be used for code point values above 007F when " "the encoding is not UTF8." @@ -409,19 +456,19 @@ msgstr "" "서버 인코딩이 UTF8이 아닌 경우 007F보다 큰 코드 지점 값에는 유니코드 이스케이" "프 값을 사용할 수 없음" -#: ../common/jsonapi.c:1187 +#: ../common/jsonapi.c:2178 #, c-format msgid "" "Unicode escape value could not be translated to the server's encoding %s." msgstr "유니코드 이스케이프 값을 %s 서버 인코딩으로 변환할 수 없음." -#: ../common/jsonapi.c:1190 jsonpath_scan.l:630 +#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "유니코드 상위 surrogate(딸림 코드)는 상위 딸림 코드 뒤에 오면 안됨." -#: ../common/jsonapi.c:1192 jsonpath_scan.l:641 jsonpath_scan.l:651 -#: jsonpath_scan.l:702 +#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 +#: jsonpath_scan.l:713 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "유니코드 상위 surrogate(딸림 코드) 뒤에는 하위 딸림 코드가 있어야 함." @@ -446,11 +493,168 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "매니페스트의 체크섬을 초기화할 수 없음" + +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "매니페스트가 예상치 않게 끝났음." + +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "매니페스트의 체크섬을 갱신할 수 없음" + +#: ../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "예상치 않은 객체 시작" + +#: ../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "예상치 않은 객체 끝" + +#: ../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "예상치 않은 배열 시작" + +#: ../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "예상치 않은 배열 끝" + +#: ../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "예상치 않은 버전 지시자" + +#: ../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "알 수 없는 최상위 수준 필드" + +#: ../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "예기치 않은 파일 필드" + +#: ../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "예상치 않은 WAL 범위 필드" + +#: ../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "예기치 않은 객체 필드" + +#: ../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "예기치 않은 스칼라" + +#: ../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "매니페스트 버전이 정수가 아님" + +#: ../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "예기치 않은 매니페스트 버전" + +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "매니페스트에 있는 시스템 식별 번호가 정수가 아님" + +#: ../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "경로 이름이 빠졌음" + +#: ../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "경로 이름과 인코딩된 경로 이름 모두" + +#: ../common/parse_manifest.c:666 +msgid "missing size" +msgstr "크기가 빠졌음" + +#: ../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "알고리즘 생략된 체크섬" + +#: ../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "파일 이름을 디코딩할 수 없음" + +#: ../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "파일 크기가 정수가 아님" + +#: ../common/parse_manifest.c:699 backup/basebackup.c:870 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "알 수 없는 체크섬 알고리즘: \"%s\"" + +#: ../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "\"%s\" 파일의 잘못된 체크섬: \"%s\"" + +#: ../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "타임라인 없음" + +#: ../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "시작 LSN 없음" + +#: ../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "마침 LSN 없음" + +#: ../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "타림라인 값이 숫자가 아님" + +#: ../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "시작 LSN 구문 오류" + +#: ../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "마침 LSN 구문 오류" + +#: ../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "최소 두 줄이 필요함" + +#: ../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "마지막 줄에 줄바꿈 문자 없음" + +#: ../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "매니페스트 체크섬 최종 정리를 못했음" + +#: ../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "매니페스트에 체크섬 없음" + +#: ../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "잘못된 매니페스트 체크섬: \"%s\"" + +#: ../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "매니페스트 체크섬 불일치" + +#: ../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "백업 매니페스트 분석 실패: %s" + #: ../common/percentrepl.c:79 ../common/percentrepl.c:85 #: ../common/percentrepl.c:118 ../common/percentrepl.c:124 -#: postmaster/postmaster.c:2211 utils/misc/guc.c:3118 utils/misc/guc.c:3154 -#: utils/misc/guc.c:3224 utils/misc/guc.c:4547 utils/misc/guc.c:6721 -#: utils/misc/guc.c:6762 +#: tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 +#: utils/misc/guc.c:3283 utils/misc/guc.c:4712 utils/misc/guc.c:6931 +#: utils/misc/guc.c:6972 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "잘못된 \"%s\" 매개 변수의 값: \"%s\"" @@ -510,45 +714,45 @@ msgstr "restricted 토큰으로 재실행할 수 없음: 오류 코드 %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu" -#: ../common/rmtree.c:95 access/heap/rewriteheap.c:1248 -#: access/transam/twophase.c:1704 access/transam/xlogarchive.c:120 -#: access/transam/xlogarchive.c:393 postmaster/postmaster.c:1143 -#: postmaster/syslogger.c:1537 replication/logical/origin.c:591 -#: replication/logical/reorderbuffer.c:4526 -#: replication/logical/snapbuild.c:1691 replication/logical/snapbuild.c:2125 -#: replication/slot.c:1909 storage/file/fd.c:832 storage/file/fd.c:3325 -#: storage/file/fd.c:3387 storage/file/reinit.c:262 storage/ipc/dsm.c:316 -#: storage/smgr/md.c:383 storage/smgr/md.c:442 storage/sync/sync.c:248 -#: utils/time/snapmgr.c:1608 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 +#: access/transam/twophase.c:1733 access/transam/xlogarchive.c:119 +#: access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 +#: postmaster/syslogger.c:1488 replication/logical/origin.c:591 +#: replication/logical/reorderbuffer.c:4589 +#: replication/logical/snapbuild.c:1712 replication/logical/snapbuild.c:2146 +#: replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 +#: storage/file/fd.c:3440 storage/file/reinit.c:261 storage/ipc/dsm.c:343 +#: storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 +#: utils/time/snapmgr.c:1591 #, c-format msgid "could not remove file \"%s\": %m" msgstr "\"%s\" 파일을 삭제할 수 없음: %m" -#: ../common/rmtree.c:122 commands/tablespace.c:773 commands/tablespace.c:786 -#: commands/tablespace.c:821 commands/tablespace.c:911 storage/file/fd.c:3317 -#: storage/file/fd.c:3726 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 +#: commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 +#: storage/file/fd.c:3779 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 삭제할 수 없음: %m" -#: ../common/scram-common.c:271 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "salt를 인코드할 수 없음" -#: ../common/scram-common.c:287 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "저장 키를 인코드할 수 없음" -#: ../common/scram-common.c:304 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "서버 키를 인코드할 수 없음" -#: ../common/stringinfo.c:306 +#: ../common/stringinfo.c:315 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "%d바이트가 포함된 문자열 버퍼를 %d바이트 더 확장할 수 없습니다." -#: ../common/stringinfo.c:310 +#: ../common/stringinfo.c:319 #, c-format msgid "" "out of memory\n" @@ -564,7 +768,7 @@ msgstr "" msgid "could not look up effective user ID %ld: %s" msgstr "%ld UID를 찾을 수 없음: %s" -#: ../common/username.c:45 libpq/auth.c:1881 +#: ../common/username.c:45 libpq/auth.c:1888 msgid "user does not exist" msgstr "사용자 없음" @@ -663,20 +867,20 @@ msgstr "" #: ../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "현재 작업 디렉터리를 알 수 없음: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "현재 작업 디렉터리를 알 수 없음: %m\n" #: ../port/strerror.c:72 #, c-format msgid "operating system error %d" msgstr "운영체제 오류 %d" -#: ../port/thread.c:50 ../port/thread.c:86 +#: ../port/user.c:43 ../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "UID %d에 해당하는 로컬 사용자를 찾을 수 없음: %s" -#: ../port/thread.c:55 ../port/thread.c:91 +#: ../port/user.c:48 ../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "%d OID에 해당하는 로컬 사용자가 없음" @@ -696,89 +900,78 @@ msgstr "PowerUsers 그룹의 SID를 가져올 수 없음: 오류 코드 %lu\n" msgid "could not check access token membership: error code %lu\n" msgstr "토큰 맴버쉽 접근을 확인 할 수 없음: 오류 코드 %lu\n" -#: access/brin/brin.c:216 +#: access/brin/brin.c:405 #, c-format msgid "" "request for BRIN range summarization for index \"%s\" page %u was not " "recorded" msgstr "\"%s\" 인덱스에서 BRIN 범위 요약 요청이 기록되지 못함, 해당 페이지: %u" -#: access/brin/brin.c:1036 access/brin/brin.c:1137 access/gin/ginfast.c:1040 -#: access/transam/xlogfuncs.c:189 access/transam/xlogfuncs.c:214 -#: access/transam/xlogfuncs.c:247 access/transam/xlogfuncs.c:286 -#: access/transam/xlogfuncs.c:307 access/transam/xlogfuncs.c:328 -#: access/transam/xlogfuncs.c:398 access/transam/xlogfuncs.c:456 +#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 +#: access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 +#: access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 +#: access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 +#: access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 #, c-format msgid "recovery is in progress" msgstr "복구 작업 진행 중" -#: access/brin/brin.c:1037 access/brin/brin.c:1138 +#: access/brin/brin.c:1386 access/brin/brin.c:1494 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "BRIN 제어 함수는 복구 작업 중에는 실행 될 수 없음" -#: access/brin/brin.c:1042 access/brin/brin.c:1143 +#: access/brin/brin.c:1391 access/brin/brin.c:1499 #, c-format msgid "block number out of range: %lld" msgstr "블록 번호가 범위를 벗어남: %lld" -#: access/brin/brin.c:1086 access/brin/brin.c:1169 +#: access/brin/brin.c:1436 access/brin/brin.c:1525 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\" 개체는 BRIN 인덱스가 아닙니다" -#: access/brin/brin.c:1102 access/brin/brin.c:1185 +#: access/brin/brin.c:1452 access/brin/brin.c:1541 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "\"%s\" 인덱스에 대한 파티션 테이블을 열 수 없음" -#: access/brin/brin_bloom.c:750 access/brin/brin_bloom.c:792 -#: access/brin/brin_minmax_multi.c:3011 access/brin/brin_minmax_multi.c:3148 -#: statistics/dependencies.c:663 statistics/dependencies.c:716 -#: statistics/mcv.c:1484 statistics/mcv.c:1515 statistics/mvdistinct.c:344 -#: statistics/mvdistinct.c:397 utils/adt/pseudotypes.c:43 -#: utils/adt/pseudotypes.c:77 utils/adt/tsgistidx.c:93 +#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 +#: parser/parse_utilcmd.c:2277 #, c-format -msgid "cannot accept a value of type %s" -msgstr "%s 형식의 값은 사용할 수 없음" +msgid "index \"%s\" is not valid" +msgstr "\"%s\" 인덱스는 사용가능 상태가 아님" -#: access/brin/brin_minmax_multi.c:2171 access/brin/brin_minmax_multi.c:2178 -#: access/brin/brin_minmax_multi.c:2185 utils/adt/timestamp.c:941 -#: utils/adt/timestamp.c:1518 utils/adt/timestamp.c:2708 -#: utils/adt/timestamp.c:2778 utils/adt/timestamp.c:2795 -#: utils/adt/timestamp.c:2848 utils/adt/timestamp.c:2887 -#: utils/adt/timestamp.c:3184 utils/adt/timestamp.c:3189 -#: utils/adt/timestamp.c:3194 utils/adt/timestamp.c:3244 -#: utils/adt/timestamp.c:3251 utils/adt/timestamp.c:3258 -#: utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3285 -#: utils/adt/timestamp.c:3292 utils/adt/timestamp.c:3322 -#: utils/adt/timestamp.c:3330 utils/adt/timestamp.c:3374 -#: utils/adt/timestamp.c:3796 utils/adt/timestamp.c:3920 -#: utils/adt/timestamp.c:4440 +#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 +#: access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 +#: statistics/dependencies.c:661 statistics/dependencies.c:714 +#: statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 +#: statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 +#: utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format -msgid "interval out of range" -msgstr "간격이 범위를 벗어남" +msgid "cannot accept a value of type %s" +msgstr "%s 형식의 값은 사용할 수 없음" -#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 -#: access/brin/brin_pageops.c:852 access/gin/ginentrypage.c:110 -#: access/gist/gist.c:1442 access/spgist/spgdoinsert.c:2002 -#: access/spgist/spgdoinsert.c:2279 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 +#: access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 +#: access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 +#: access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "인덱스 행 크기 %zu이(가) 최대값 %zu(\"%s\" 인덱스)을(를) 초과함" -#: access/brin/brin_revmap.c:393 access/brin/brin_revmap.c:399 +#: access/brin/brin_revmap.c:383 access/brin/brin_revmap.c:389 #, c-format msgid "corrupted BRIN index: inconsistent range map" msgstr "BRIN 인덱스 속상: 범위 지도가 연결되지 않음" -#: access/brin/brin_revmap.c:593 +#: access/brin/brin_revmap.c:583 #, c-format msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "예상치 못한 0x%04X 페이지 타입: \"%s\" BRIN 인덱스 %u 블록" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:151 -#: access/gist/gistvalidate.c:153 access/hash/hashvalidate.c:139 +#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 +#: access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 #: access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 #, c-format msgid "" @@ -788,8 +981,8 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 포함된 %s 함수가 잘못된 지원 번호 %d " "로 지정되었습니다." -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:163 -#: access/gist/gistvalidate.c:165 access/hash/hashvalidate.c:118 +#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 +#: access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 #: access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 #, c-format msgid "" @@ -799,8 +992,8 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 포함된 %s 함수가 잘못된 signature 지원 " "번호 %d 로 지정되었습니다." -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:182 -#: access/gist/gistvalidate.c:185 access/hash/hashvalidate.c:160 +#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 +#: access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 #: access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 #, c-format msgid "" @@ -810,7 +1003,7 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 포함된 %s 연산자의 %d 번 전략 번호가 잘" "못되었습니다." -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:195 +#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 #: access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 #: access/spgist/spgvalidate.c:237 #, c-format @@ -821,8 +1014,8 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 %s 연산자가 잘못된 ORDER BY 명세를 사용" "합니다." -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:208 -#: access/gist/gistvalidate.c:233 access/hash/hashvalidate.c:186 +#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 +#: access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 #: access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 #, c-format msgid "" @@ -855,32 +1048,32 @@ msgstr "" msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "\"%s\" 연산자 클래스(접근 방법: %s)에 연산자가 빠졌습니다" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:250 -#: access/gist/gistvalidate.c:274 +#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 +#: access/gist/gistvalidate.c:273 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d" msgstr "\"%s\" 연산자 클래스(접근 방법: %s)에 %d 지원 함수가 빠졌습니다." -#: access/common/attmap.c:122 +#: access/common/attmap.c:121 #, c-format msgid "Returned type %s does not match expected type %s in column %d." msgstr "" "반환 자료형으로 %s 형을 지정했지만, 칼럼은 %s 자료형입니다. 해당 칼럼: %d 번" "째 칼럼" -#: access/common/attmap.c:150 +#: access/common/attmap.c:149 #, c-format msgid "" "Number of returned columns (%d) does not match expected column count (%d)." msgstr "반환할 칼럼 수(%d)와 예상되는 칼럼수(%d)가 다릅니다." -#: access/common/attmap.c:234 access/common/attmap.c:246 +#: access/common/attmap.c:233 access/common/attmap.c:245 #, c-format msgid "could not convert row type" msgstr "로우 자료형을 변환 할 수 없음" -#: access/common/attmap.c:235 +#: access/common/attmap.c:234 #, c-format msgid "" "Attribute \"%s\" of type %s does not match corresponding attribute of type " @@ -888,12 +1081,12 @@ msgid "" msgstr "" " \"%s\" 속성(대상 자료형 %s)이 %s 자료형의 속성 가운데 관련된 것이 없습니다" -#: access/common/attmap.c:247 +#: access/common/attmap.c:246 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "\"%s\" 속성(대상 자료형 %s)이 %s 자료형에는 없습니다." -#: access/common/heaptuple.c:1124 access/common/heaptuple.c:1459 +#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "칼럼 개수(%d)가 최대값(%d)을 초과했습니다" @@ -903,123 +1096,111 @@ msgstr "칼럼 개수(%d)가 최대값(%d)을 초과했습니다" msgid "number of index columns (%d) exceeds limit (%d)" msgstr "인덱스 칼럼 개수(%d)가 최대값(%d)을 초과했습니다" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:950 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:970 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "인덱스 행(row)은 %zu 바이트를 필요로 함, 최대 크기는 %zu" -#: access/common/printtup.c:292 tcop/fastpath.c:107 tcop/fastpath.c:454 -#: tcop/postgres.c:1944 +#: access/common/printtup.c:292 commands/explain.c:5376 tcop/fastpath.c:107 +#: tcop/fastpath.c:454 tcop/postgres.c:1956 #, c-format msgid "unsupported format code: %d" msgstr "지원하지 않는 포맷 코드: %d" -#: access/common/reloptions.c:521 access/common/reloptions.c:532 +#: access/common/reloptions.c:519 access/common/reloptions.c:530 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "유효한 값: \"on\", \"off\", \"auto\"" -#: access/common/reloptions.c:543 +#: access/common/reloptions.c:541 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "사용할 수 있는 값은 \"local\" 또는 \"cascaded\" 입니다" -#: access/common/reloptions.c:691 +#: access/common/reloptions.c:689 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "사용자 정의 관계 매개 변수 형식 제한을 초과함" -#: access/common/reloptions.c:1233 +#: access/common/reloptions.c:1231 #, c-format msgid "RESET must not include values for parameters" msgstr "매개 변수의 값으로 RESET은 올 수 없음" -#: access/common/reloptions.c:1265 +#: access/common/reloptions.c:1263 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "\"%s\" 매개 변수 네임스페이스를 인식할 수 없음" -#: access/common/reloptions.c:1302 commands/variable.c:1167 +#: access/common/reloptions.c:1300 commands/variable.c:1214 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "WITH OIDS 테이블을 지원하지 않음" -#: access/common/reloptions.c:1470 +#: access/common/reloptions.c:1468 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "알 수 없는 환경 설정 이름입니다 \"%s\"" -#: access/common/reloptions.c:1582 +#: access/common/reloptions.c:1580 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "\"%s\" 매개 변수가 여러 번 지정됨" -#: access/common/reloptions.c:1598 +#: access/common/reloptions.c:1596 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "\"%s\" 불리언 옵션 값이 잘못됨: %s" -#: access/common/reloptions.c:1610 +#: access/common/reloptions.c:1608 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "\"%s\" 정수 옵션 값이 잘못됨: %s" -#: access/common/reloptions.c:1616 access/common/reloptions.c:1636 +#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "값 %s은(는) \"%s\" 옵션 범위를 벗어남" -#: access/common/reloptions.c:1618 +#: access/common/reloptions.c:1616 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "유효한 값은 \"%d\"에서 \"%d\" 사이입니다." -#: access/common/reloptions.c:1630 +#: access/common/reloptions.c:1628 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "\"%s\" 부동 소수점 옵션 값이 잘못됨: %s" -#: access/common/reloptions.c:1638 +#: access/common/reloptions.c:1636 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "유효한 값은 \"%f\"에서 \"%f\" 사이입니다." -#: access/common/reloptions.c:1660 +#: access/common/reloptions.c:1658 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "\"%s\" enum 옵션 값이 잘못됨: %s" -#: access/common/reloptions.c:1991 +#: access/common/reloptions.c:1989 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "파티션 상위 테이블 대상으로는 스토리지 매개 변수를 지정할 수 없음" -#: access/common/reloptions.c:1992 +#: access/common/reloptions.c:1990 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "" "대신에 각 하위 파티션 테이블 대상으로 각각 스토리지 매개 변수를 지정하세요." -#: access/common/toast_compression.c:33 +#: access/common/toast_compression.c:31 #, c-format msgid "compression method lz4 not supported" msgstr "lz4 압축 방법을 지원하지 않습니다" -#: access/common/toast_compression.c:34 +#: access/common/toast_compression.c:32 #, c-format msgid "This functionality requires the server to be built with lz4 support." msgstr "이 기능을 사용하려면 lz4 지원으로 서버를 빌드해야 합니다." -#: access/common/tupdesc.c:837 commands/tablecmds.c:6953 -#: commands/tablecmds.c:12973 -#, c-format -msgid "too many array dimensions" -msgstr "너무 많은 배열 차수" - -#: access/common/tupdesc.c:842 parser/parse_clause.c:772 -#: parser/parse_relation.c:1913 -#, c-format -msgid "column \"%s\" cannot be declared SETOF" -msgstr "\"%s\" 칼럼은 SETOF를 지정할 수 없습니다" - #: access/gin/ginbulk.c:44 #, c-format msgid "posting list is too long" @@ -1027,8 +1208,8 @@ msgstr "포스팅 목록이 너무 깁니다" #: access/gin/ginbulk.c:45 #, c-format -msgid "Reduce maintenance_work_mem." -msgstr "maintenance_work_mem 설정값을 줄이세요." +msgid "Reduce \"maintenance_work_mem\"." +msgstr "\"maintenance_work_mem\" 설정값을 줄이세요." #: access/gin/ginfast.c:1041 #, c-format @@ -1045,7 +1226,7 @@ msgstr "\"%s\" 개체는 GIN 인덱스가 아닙니다" msgid "cannot access temporary indexes of other sessions" msgstr "다른 세션의 임시 인덱스는 접근할 수 없음" -#: access/gin/ginget.c:273 access/nbtree/nbtinsert.c:762 +#: access/gin/ginget.c:271 access/nbtree/nbtinsert.c:762 #, c-format msgid "failed to re-find tuple within index \"%s\"" msgstr "\"%s\" 인덱스에서 튜플 재검색 실패" @@ -1062,14 +1243,14 @@ msgstr "" msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "이 문제를 고치려면, 다음 명령을 수행하세요: REINDEX INDEX \"%s\"" -#: access/gin/ginutil.c:146 executor/execExpr.c:2169 -#: utils/adt/arrayfuncs.c:3996 utils/adt/arrayfuncs.c:6683 -#: utils/adt/rowtypes.c:984 +#: access/gin/ginutil.c:147 executor/execExpr.c:2200 +#: utils/adt/arrayfuncs.c:4016 utils/adt/arrayfuncs.c:6712 +#: utils/adt/rowtypes.c:974 #, c-format msgid "could not identify a comparison function for type %s" msgstr "%s 자료형에서 사용할 비교함수를 찾을 수 없습니다." -#: access/gin/ginvalidate.c:92 access/gist/gistvalidate.c:93 +#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 #: access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 #, c-format msgid "" @@ -1079,7 +1260,7 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 서로 다른 양쪽 입력 자료형 인자를 사용" "할 수 있는 %s 지원 함수가 포함되어 있음" -#: access/gin/ginvalidate.c:260 +#: access/gin/ginvalidate.c:258 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d or " @@ -1087,18 +1268,18 @@ msgid "" msgstr "" "\"%s\" 연산자 클래스(접근 방법: %s)에는 %d 또는 %d 지원 함수가 빠졌습니다" -#: access/gin/ginvalidate.c:333 access/gist/gistvalidate.c:350 +#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 #: access/spgist/spgvalidate.c:387 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "지원 함수 번호 %d 잘못됨, 대상 접근 방법: %s" -#: access/gist/gist.c:759 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "\"%s\" 인덱스에 잘못된 내부 튜플이 있다고 확인되었습니다." -#: access/gist/gist.c:761 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 #, c-format msgid "" "This is caused by an incomplete page split at crash recovery before " @@ -1107,16 +1288,16 @@ msgstr "" "이 문제는 PostgreSQL 9.1 버전으로 업그레이드 하기 전에 장애 복구 처리에서 잘" "못된 페이지 분리 때문에 발생했습니다." -#: access/gist/gist.c:762 access/gist/gistutil.c:801 access/gist/gistutil.c:812 -#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:227 -#: access/hash/hashutil.c:238 access/hash/hashutil.c:250 -#: access/hash/hashutil.c:271 access/nbtree/nbtpage.c:813 +#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 +#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 +#: access/hash/hashutil.c:237 access/hash/hashutil.c:249 +#: access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 #: access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "REINDEX 명령으로 다시 인덱스를 만드세요" -#: access/gist/gist.c:1176 +#: access/gist/gist.c:1196 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "\"%s\" 인덱스의 불완전한 분기 수정중, 블록번호: %u" @@ -1135,19 +1316,19 @@ msgstr "" "인덱스가 최적화되지 않았습니다. 최적화하려면 개발자에게 문의하거나, CREATE " "INDEX 명령에서 해당 칼럼을 두 번째 인덱스로 사용하십시오." -#: access/gist/gistutil.c:798 access/hash/hashutil.c:224 +#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 #: access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "\"%s\" 인덱스의 %u번째 블럭에서 예상치 않은 zero page가 있습니다" -#: access/gist/gistutil.c:809 access/hash/hashutil.c:235 -#: access/hash/hashutil.c:247 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 +#: access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "\"%s\" 인덱스트 %u번째 블럭이 속상되었습니다" -#: access/gist/gistvalidate.c:203 +#: access/gist/gistvalidate.c:202 #, c-format msgid "" "operator family \"%s\" of access method %s contains unsupported ORDER BY " @@ -1156,7 +1337,7 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 %s 연산자가 지원하지 않는 ORDER BY 명세" "를 사용합니다." -#: access/gist/gistvalidate.c:214 +#: access/gist/gistvalidate.c:213 #, c-format msgid "" "operator family \"%s\" of access method %s contains incorrect ORDER BY " @@ -1165,30 +1346,30 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 %s 연산자가 잘못된 ORDER BY 명세를 사용" "합니다." -#: access/hash/hashfunc.c:279 access/hash/hashfunc.c:333 -#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:333 +#: utils/adt/varchar.c:1008 utils/adt/varchar.c:1065 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "문자열 해시 작업에 사용할 정렬규칙(collation)을 결정할 수 없음" -#: access/hash/hashfunc.c:280 access/hash/hashfunc.c:334 catalog/heap.c:668 -#: catalog/heap.c:674 commands/createas.c:206 commands/createas.c:515 -#: commands/indexcmds.c:2039 commands/tablecmds.c:17462 commands/view.c:86 -#: regex/regc_pg_locale.c:243 utils/adt/formatting.c:1648 -#: utils/adt/formatting.c:1770 utils/adt/formatting.c:1893 utils/adt/like.c:191 -#: utils/adt/like_support.c:1025 utils/adt/varchar.c:739 -#: utils/adt/varchar.c:1010 utils/adt/varchar.c:1065 utils/adt/varlena.c:1518 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:334 catalog/heap.c:672 +#: catalog/heap.c:678 commands/createas.c:201 commands/createas.c:508 +#: commands/indexcmds.c:2021 commands/tablecmds.c:18178 commands/view.c:81 +#: regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 +#: utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 +#: utils/adt/like_support.c:1024 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1066 utils/adt/varlena.c:1521 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "명시적으로 정렬 규칙을 지정하려면 COLLATE 절을 사용하세요." -#: access/hash/hashinsert.c:86 +#: access/hash/hashinsert.c:84 #, c-format msgid "index row size %zu exceeds hash maximum %zu" msgstr "인덱스 행 크기가 초과됨: 현재값 %zu, 최대값 %zu" -#: access/hash/hashinsert.c:88 access/spgist/spgdoinsert.c:2006 -#: access/spgist/spgdoinsert.c:2283 access/spgist/spgutils.c:1011 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 +#: access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1031 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "버퍼 페이지보다 큰 값은 인덱싱할 수 없습니다." @@ -1203,17 +1384,17 @@ msgstr "잘못된 오버플로우 블록 번호: %u" msgid "out of overflow pages in hash index \"%s\"" msgstr "\"%s\" 해시 인덱스에서 오버플로우 페이지 초과" -#: access/hash/hashsearch.c:315 +#: access/hash/hashsearch.c:311 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "해시 인덱스는 whole-index scan을 지원하지 않음" -#: access/hash/hashutil.c:263 +#: access/hash/hashutil.c:262 #, c-format msgid "index \"%s\" is not a hash index" msgstr "\"%s\" 인덱스는 해시 인덱스가 아님" -#: access/hash/hashutil.c:269 +#: access/hash/hashutil.c:268 #, c-format msgid "index \"%s\" has wrong hash version" msgstr "\"%s\" 인덱스는 잘못된 해시 버전임" @@ -1231,104 +1412,114 @@ msgid "" "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "%s 연산자 패밀리(접근 방법: %s)에 cross-type 연산자가 빠졌음" -#: access/heap/heapam.c:2027 +#: access/heap/heapam.c:2204 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "병렬 작업자는 튜플을 추가 할 수 없음" -#: access/heap/heapam.c:2546 +#: access/heap/heapam.c:2723 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "병렬 작업 중에는 튜플을 지울 수 없음" -#: access/heap/heapam.c:2593 +#: access/heap/heapam.c:2770 #, c-format msgid "attempted to delete invisible tuple" msgstr "볼 수 없는 튜플을 삭제 하려고 함" -#: access/heap/heapam.c:3036 access/heap/heapam.c:5903 +#: access/heap/heapam.c:3218 access/heap/heapam.c:6454 access/index/genam.c:818 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "병렬 작업 중에 튜플 갱신은 할 수 없음" -#: access/heap/heapam.c:3164 +#: access/heap/heapam.c:3350 #, c-format msgid "attempted to update invisible tuple" msgstr "볼 수 없는 튜플을 변경하려고 함" -#: access/heap/heapam.c:4551 access/heap/heapam.c:4589 -#: access/heap/heapam.c:4854 access/heap/heapam_handler.c:467 +#: access/heap/heapam.c:4861 access/heap/heapam.c:4899 +#: access/heap/heapam.c:5164 access/heap/heapam_handler.c:468 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "\"%s\" 릴레이션의 잠금 정보를 구할 수 없음" -#: access/heap/heapam_handler.c:412 +#: access/heap/heapam.c:6267 commands/trigger.c:3340 +#: executor/nodeModifyTable.c:2376 executor/nodeModifyTable.c:2467 +#, c-format +msgid "" +"tuple to be updated was already modified by an operation triggered by the " +"current command" +msgstr "" +"현재 명령으로 실행된 트리거 작업으로 변경해야할 자료가 이미 바뀌었습니다." + +#: access/heap/heapam_handler.c:413 #, c-format msgid "" "tuple to be locked was already moved to another partition due to concurrent " "update" msgstr "잠글 튜플은 동시 업데이트로 다른 파티션으로 이미 옮겨졌음" -#: access/heap/hio.c:536 access/heap/rewriteheap.c:659 +#: access/heap/hio.c:535 access/heap/rewriteheap.c:640 #, c-format msgid "row is too big: size %zu, maximum size %zu" msgstr "로우가 너무 큽니다: 크기 %zu, 최대값 %zu" -#: access/heap/rewriteheap.c:919 +#: access/heap/rewriteheap.c:885 #, c-format msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "\"%s\" 파일 쓰기 실패, %d / %d 기록함: %m." -#: access/heap/rewriteheap.c:1011 access/heap/rewriteheap.c:1128 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 #: access/transam/timeline.c:329 access/transam/timeline.c:481 -#: access/transam/xlog.c:2971 access/transam/xlog.c:3162 -#: access/transam/xlog.c:3938 access/transam/xlog.c:8744 -#: access/transam/xlogfuncs.c:702 backup/basebackup_server.c:151 -#: backup/basebackup_server.c:244 commands/dbcommands.c:518 -#: postmaster/postmaster.c:4557 postmaster/postmaster.c:5560 -#: replication/logical/origin.c:603 replication/slot.c:1777 -#: storage/file/copydir.c:157 storage/smgr/md.c:232 utils/time/snapmgr.c:1263 +#: access/transam/xlog.c:3255 access/transam/xlog.c:3446 +#: access/transam/xlog.c:4283 access/transam/xlog.c:9269 +#: access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 +#: backup/basebackup_server.c:242 commands/dbcommands.c:494 +#: postmaster/launch_backend.c:340 postmaster/postmaster.c:4111 +#: postmaster/walsummarizer.c:1212 replication/logical/origin.c:603 +#: replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 +#: utils/time/snapmgr.c:1234 #, c-format msgid "could not create file \"%s\": %m" msgstr "\"%s\" 파일을 만들 수 없음: %m" -#: access/heap/rewriteheap.c:1138 +#: access/heap/rewriteheap.c:1104 #, c-format msgid "could not truncate file \"%s\" to %u: %m" msgstr "\"%s\" 파일을 %u 크기로 정리할 수 없음: %m" -#: access/heap/rewriteheap.c:1156 access/transam/timeline.c:384 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 #: access/transam/timeline.c:424 access/transam/timeline.c:498 -#: access/transam/xlog.c:3021 access/transam/xlog.c:3218 -#: access/transam/xlog.c:3950 commands/dbcommands.c:530 -#: postmaster/postmaster.c:4567 postmaster/postmaster.c:4577 +#: access/transam/xlog.c:3305 access/transam/xlog.c:3502 +#: access/transam/xlog.c:4295 commands/dbcommands.c:506 +#: postmaster/launch_backend.c:351 postmaster/launch_backend.c:363 #: replication/logical/origin.c:615 replication/logical/origin.c:657 -#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1767 -#: replication/slot.c:1812 storage/file/buffile.c:545 -#: storage/file/copydir.c:197 utils/init/miscinit.c:1605 -#: utils/init/miscinit.c:1616 utils/init/miscinit.c:1624 utils/misc/guc.c:4331 -#: utils/misc/guc.c:4362 utils/misc/guc.c:5490 utils/misc/guc.c:5508 -#: utils/time/snapmgr.c:1268 utils/time/snapmgr.c:1275 +#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1788 +#: replication/slot.c:2094 storage/file/buffile.c:545 +#: storage/file/copydir.c:197 utils/init/miscinit.c:1655 +#: utils/init/miscinit.c:1666 utils/init/miscinit.c:1674 utils/misc/guc.c:4491 +#: utils/misc/guc.c:4522 utils/misc/guc.c:5675 utils/misc/guc.c:5693 +#: utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 #, c-format msgid "could not write to file \"%s\": %m" msgstr "\"%s\" 파일 쓰기 실패: %m" -#: access/heap/vacuumlazy.c:482 +#: access/heap/vacuumlazy.c:473 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "적극적으로 \"%s.%s.%s\" 청소 중" -#: access/heap/vacuumlazy.c:487 +#: access/heap/vacuumlazy.c:478 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "\"%s.%s.%s\" 청소 중" -#: access/heap/vacuumlazy.c:635 +#: access/heap/vacuumlazy.c:626 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "\"%s.%s.%s\" 테이블 청소 끝남: 인덱스 탐색: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:637 #, c-format msgid "" "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": " @@ -1337,7 +1528,7 @@ msgstr "" "트랙젝션 ID 겹침 방지를 위한 적극적인 \"%s.%s.%s\" 테이블 자동 청소: 인덱스 " "탐색: %d\n" -#: access/heap/vacuumlazy.c:648 +#: access/heap/vacuumlazy.c:639 #, c-format msgid "" "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: " @@ -1345,29 +1536,29 @@ msgid "" msgstr "" "트랙젝션 ID 겹침 방지를 위한 \"%s.%s.%s\" 테이블 자동 청소: 인덱스 탐색: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:644 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "적극적인 \"%s.%s.%s\" 테이블 자동 청소: 인덱스 탐색: %d\n" -#: access/heap/vacuumlazy.c:655 +#: access/heap/vacuumlazy.c:646 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "\"%s.%s.%s\" 테이블 자동 청소: 인덱스 탐색: %d\n" -#: access/heap/vacuumlazy.c:662 +#: access/heap/vacuumlazy.c:653 #, c-format msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" msgstr "페이지: %u 삭제됨, %u 남음, %u 검사됨 (전체의 %.2f%%)\n" -#: access/heap/vacuumlazy.c:669 +#: access/heap/vacuumlazy.c:660 #, c-format msgid "" "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" msgstr "" "튜플: %.lld 삭제됨, %lld 남음, 아직 %lld 개의 튜플을 지워야하지만 못지웠음\n" -#: access/heap/vacuumlazy.c:675 +#: access/heap/vacuumlazy.c:666 #, c-format msgid "" "tuples missed: %lld dead from %u pages not removed due to cleanup lock " @@ -1376,37 +1567,37 @@ msgstr "" "놓친 튜플: %lld 개의 죽은 튜플이 %u 개의 페이지 안에 있음: cleanup 잠금 연결 " "때문\n" -#: access/heap/vacuumlazy.c:681 +#: access/heap/vacuumlazy.c:672 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "삭제 가능한 컷오프: %u, which was %d XIDs old when operation ended\n" -#: access/heap/vacuumlazy.c:688 +#: access/heap/vacuumlazy.c:679 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "새 relfrozenxid: %u, which is %d XIDs ahead of previous value\n" -#: access/heap/vacuumlazy.c:696 +#: access/heap/vacuumlazy.c:687 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "새 relminmxid: %u, which is %d MXIDs ahead of previous value\n" -#: access/heap/vacuumlazy.c:699 +#: access/heap/vacuumlazy.c:690 #, c-format msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" msgstr "" "영구보관: 테이블의 %u개 페이지(전체의 %.2f%%)에서 %lld 개의 튜플을 영구 보관" "함\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:698 msgid "index scan not needed: " msgstr "인덱스 검사 필요 없음: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:700 msgid "index scan needed: " msgstr "인덱스 검사 필요함: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:702 #, c-format msgid "" "%u pages from table (%.2f%% of total) had %lld dead item identifiers " @@ -1414,21 +1605,21 @@ msgid "" msgstr "" "테이블의 %u개 페이지(전체의 %.2f%%)에서 %lld 개의 죽은 항목 식별자를 지웠음\n" -#: access/heap/vacuumlazy.c:716 +#: access/heap/vacuumlazy.c:707 msgid "index scan bypassed: " msgstr "인덱스 검사 통과됨: " -#: access/heap/vacuumlazy.c:718 +#: access/heap/vacuumlazy.c:709 msgid "index scan bypassed by failsafe: " msgstr "failsafe의 의해 인덱스 검사 통과됨: " -#: access/heap/vacuumlazy.c:720 +#: access/heap/vacuumlazy.c:711 #, c-format msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" msgstr "" "테이블의 %u 개 페이지(전체의 %.2f%%)에서 %lld 개의 죽은 항목 식별자가 있음\n" -#: access/heap/vacuumlazy.c:735 +#: access/heap/vacuumlazy.c:726 #, c-format msgid "" "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u " @@ -1437,38 +1628,38 @@ msgstr "" "\"%s\" 인덱스: 페이지: 전체 가운데 %u, 새롭게 지운거 %u, 현재 지운거 %u, 재사" "용한 것 %u\n" -#: access/heap/vacuumlazy.c:747 commands/analyze.c:796 +#: access/heap/vacuumlazy.c:738 commands/analyze.c:794 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "I/O 속도: 읽기: %.3f ms, 쓰기: %.3f ms\n" -#: access/heap/vacuumlazy.c:757 commands/analyze.c:799 +#: access/heap/vacuumlazy.c:748 commands/analyze.c:797 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "평균 읽기 속도: %.3f MB/s, 평균 쓰기 속도: %.3f MB/s\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:801 +#: access/heap/vacuumlazy.c:751 commands/analyze.c:799 #, c-format msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" msgstr "버퍼 사용량: %lld 조회, %lld 놓침, %lld 변경됨\n" -#: access/heap/vacuumlazy.c:765 +#: access/heap/vacuumlazy.c:756 #, c-format msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" msgstr "WAL 사용량: %lld 레코드, %lld full page 이미지, %llu 바이트\n" -#: access/heap/vacuumlazy.c:769 commands/analyze.c:805 +#: access/heap/vacuumlazy.c:760 commands/analyze.c:803 #, c-format msgid "system usage: %s" msgstr "시스템 사용량: %s" -#: access/heap/vacuumlazy.c:2482 +#: access/heap/vacuumlazy.c:2170 #, c-format msgid "table \"%s\": removed %lld dead item identifiers in %u pages" msgstr "" "\"%s\" 테이블: %lld 개의 죽은 항목 실별자를 %u 개의 페이지에서 삭제했음" -#: access/heap/vacuumlazy.c:2642 +#: access/heap/vacuumlazy.c:2324 #, c-format msgid "" "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after " @@ -1477,12 +1668,12 @@ msgstr "" "\"%s.%s.%s\" 테이블의 불필요한 관리 작업은 통과했음, %d 번의 인덱스 검사로 굳" "이 필요 없음" -#: access/heap/vacuumlazy.c:2645 +#: access/heap/vacuumlazy.c:2327 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "해당 테이블의 relfrozenxid 나 relminmxid 값이 너무 오래 된 것입니다." -#: access/heap/vacuumlazy.c:2646 +#: access/heap/vacuumlazy.c:2328 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or " @@ -1495,22 +1686,22 @@ msgstr "" "VACUUM 작업이 트랜잭션 ID가 증가하는 것을 따라 잡을 있는 다른 방법도 해 봐야 " "할 것 같습니다." -#: access/heap/vacuumlazy.c:2891 +#: access/heap/vacuumlazy.c:2590 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "\"%s\": 잠금 요청 충돌로 자료 비우기 작업을 중지합니다" -#: access/heap/vacuumlazy.c:2961 +#: access/heap/vacuumlazy.c:2660 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "\"%s\" 테이블: %u 에서 %u 페이지로 정리했음" -#: access/heap/vacuumlazy.c:3023 +#: access/heap/vacuumlazy.c:2722 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "\"%s\" 테이블: 잠금 요청 충돌로 자료 비우기 작업이 지연되고 있음" -#: access/heap/vacuumlazy.c:3183 +#: access/heap/vacuumlazy.c:2841 #, c-format msgid "" "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary " @@ -1519,47 +1710,47 @@ msgstr "" "\"%s\" 청소 작업에서의 병렬 옵션은 무시함 --- 임시 테이블은 병렬 처리로 청소 " "할 수 없음" -#: access/heap/vacuumlazy.c:3399 +#: access/heap/vacuumlazy.c:3108 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "%u 블록 %u 오프셋 탐색 중 (해당 릴레이션: \"%s.%s\")" -#: access/heap/vacuumlazy.c:3402 +#: access/heap/vacuumlazy.c:3111 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "%u 블록(해당 릴레이션: \"%s.%s\")을 탐색 중" -#: access/heap/vacuumlazy.c:3406 +#: access/heap/vacuumlazy.c:3115 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "\"%s.%s\" 릴레이션을 탐색 중" -#: access/heap/vacuumlazy.c:3414 +#: access/heap/vacuumlazy.c:3123 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "%u 블록 %u 오프셋 청소 중 (해당 릴레이션: \"%s.%s\")" -#: access/heap/vacuumlazy.c:3417 +#: access/heap/vacuumlazy.c:3126 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "%u 블록(해당 릴레이션: \"%s.%s\")을 청소 중" -#: access/heap/vacuumlazy.c:3421 +#: access/heap/vacuumlazy.c:3130 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "\"%s.%s\" 릴레이션 청소 중" -#: access/heap/vacuumlazy.c:3426 commands/vacuumparallel.c:1074 +#: access/heap/vacuumlazy.c:3135 commands/vacuumparallel.c:1112 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "\"%s\" 인덱스(해당 릴레이션 \"%s.%s\") 청소 중" -#: access/heap/vacuumlazy.c:3431 commands/vacuumparallel.c:1080 +#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1118 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "\"%s\" 인덱스 (해당 릴레이션 \"%s.%s\")을 정돈(clean up) 중" -#: access/heap/vacuumlazy.c:3437 +#: access/heap/vacuumlazy.c:3146 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "\"%s.%s\" 릴레이션을 %u 블럭으로 줄이는 중" @@ -1574,19 +1765,24 @@ msgstr "\"%s\" 접근 방법은 %s 자료형에는 쓸 수 없음" msgid "index access method \"%s\" does not have a handler" msgstr "\"%s\" 인덱스 접근 방법에 대한 핸들러가 없음" -#: access/index/genam.c:490 +#: access/index/genam.c:489 #, c-format msgid "transaction aborted during system catalog scan" msgstr "시스템 카탈로그 탐색 중 트랜잭션 중지됨" -#: access/index/indexam.c:142 catalog/objectaddress.c:1394 -#: commands/indexcmds.c:2867 commands/tablecmds.c:272 commands/tablecmds.c:296 -#: commands/tablecmds.c:17163 commands/tablecmds.c:18935 +#: access/index/genam.c:657 access/index/indexam.c:82 +#, c-format +msgid "cannot access index \"%s\" while it is being reindexed" +msgstr "reindex 시작할 때는 \"%s\" 인덱스를 접근할 없음" + +#: access/index/indexam.c:203 catalog/objectaddress.c:1356 +#: commands/indexcmds.c:2851 commands/tablecmds.c:281 commands/tablecmds.c:305 +#: commands/tablecmds.c:17873 commands/tablecmds.c:19740 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\" 개체는 인덱스가 아닙니다" -#: access/index/indexam.c:979 +#: access/index/indexam.c:1028 #, c-format msgid "operator class %s has no options" msgstr "%s 연산자 클래스는 옵션이 없습니다" @@ -1607,7 +1803,7 @@ msgid "This may be because of a non-immutable index expression." msgstr "이 문제는 non-immutable 인덱스 표현식 때문인듯 합니다." #: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 -#: parser/parse_utilcmd.c:2317 +#: parser/parse_utilcmd.c:2323 #, c-format msgid "index \"%s\" is not a btree" msgstr "\"%s\" 인덱스는 btree 인덱스가 아닙니다" @@ -1621,12 +1817,12 @@ msgstr "" "\"%s\" 인덱스의 버전이 틀립니다: 파일 버전 %d, 현재 버전 %d, 최소 지원 버전 " "%d" -#: access/nbtree/nbtpage.c:1866 +#: access/nbtree/nbtpage.c:1861 #, c-format msgid "index \"%s\" contains a half-dead internal page" msgstr "\"%s\" 인덱스에 반쯤 죽은(half-dead) 내부 페이지가 있음" -#: access/nbtree/nbtpage.c:1868 +#: access/nbtree/nbtpage.c:1863 #, c-format msgid "" "This can be caused by an interrupted VACUUM in version 9.3 or older, before " @@ -1635,7 +1831,7 @@ msgstr "" "이 문제는 9.3 버전 이하 환경에서 VACUUM 작업이 중지되고, 그 상태로 업그레이드" "되었을 가능성이 큽니다. 해당 인덱스를 다시 만드십시오." -#: access/nbtree/nbtutils.c:2662 +#: access/nbtree/nbtutils.c:5108 #, c-format msgid "" "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" @@ -1643,12 +1839,12 @@ msgstr "" "인덱스 행 크기(%zu)가 btree(%u 버전)의 최대값(%zu)을 초과함 (해당 인덱스: " "\"%s\")" -#: access/nbtree/nbtutils.c:2668 +#: access/nbtree/nbtutils.c:5114 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "인덱스 로우가 %u,%u 튜플(해당 릴레이션 \"%s\")을 참조함." -#: access/nbtree/nbtutils.c:2672 +#: access/nbtree/nbtutils.c:5118 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1667,13 +1863,19 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에는 %s 자료형과 %s 자료형용 지원 함수가 " "빠졌음" +#: access/sequence/sequence.c:75 access/table/table.c:145 +#: optimizer/util/plancat.c:144 +#, c-format +msgid "cannot open relation \"%s\"" +msgstr "\"%s\" 릴레이션을 열 수 없음" + #: access/spgist/spgutils.c:245 #, c-format msgid "" "compress method must be defined when leaf type is different from input type" msgstr "입력 자료형에서 리프 유형이 다를 때 압축 방법은 반드시 정의해야 함" -#: access/spgist/spgutils.c:1008 +#: access/spgist/spgutils.c:1028 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "SP-GiST 내부 튜플 크기가 초과됨: 현재값 %zu, 최대값 %zu" @@ -1692,73 +1894,69 @@ msgstr "" "\"%s\" 연산자 패밀리(접근 방법: %s)에 %d 지원 함수가 %s 자료형용으로 없습니" "다." -#: access/table/table.c:145 optimizer/util/plancat.c:145 -#, c-format -msgid "cannot open relation \"%s\"" -msgstr "\"%s\" 릴레이션을 열 수 없음" - -#: access/table/tableam.c:265 +#: access/table/tableam.c:255 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "tid (%u, %u)가 바르지 않음, 해당 릴레이션: \"%s\"" -#: access/table/tableamapi.c:116 +#: access/table/tableamapi.c:109 #, c-format -msgid "%s cannot be empty." -msgstr "%s 값은 비워 둘 수 없음" +msgid "\"%s\" cannot be empty." +msgstr "\"%s\" 값은 비워 둘 수 없음" -#: access/table/tableamapi.c:123 access/transam/xlogrecovery.c:4774 +#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4858 #, c-format -msgid "%s is too long (maximum %d characters)." -msgstr "%s 설정값이 너무 깁니다 (최대 %d 문자)" +msgid "\"%s\" is too long (maximum %d characters)." +msgstr "\"%s\" 설정값이 너무 깁니다 (최대 %d 문자)" -#: access/table/tableamapi.c:146 +#: access/table/tableamapi.c:139 #, c-format msgid "table access method \"%s\" does not exist" msgstr "\"%s\" 테이블 접근 방법이 없습니다" -#: access/table/tableamapi.c:151 +#: access/table/tableamapi.c:144 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "\"%s\" 테이블 접근 방법이 없습니다." -#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:152 +#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:151 #, c-format msgid "sample percentage must be between 0 and 100" msgstr "샘플 퍼센트 값은 0에서 100 사이여야 함" -#: access/transam/commit_ts.c:279 +#: access/transam/commit_ts.c:287 #, c-format msgid "cannot retrieve commit timestamp for transaction %u" msgstr "%u 트랜잭션의 커밋 타임스탬프를 알 수 없음" -#: access/transam/commit_ts.c:377 +#: access/transam/commit_ts.c:385 #, c-format msgid "could not get commit timestamp data" msgstr "커밋 타임스탬프 자료를 찾을 수 없음" -#: access/transam/commit_ts.c:379 +#: access/transam/commit_ts.c:387 #, c-format msgid "" "Make sure the configuration parameter \"%s\" is set on the primary server." msgstr "운영 서버에서 \"%s\" 환경 설정 매개 변수를 설정했는지 확인하세요." -#: access/transam/commit_ts.c:381 +#: access/transam/commit_ts.c:389 #, c-format msgid "Make sure the configuration parameter \"%s\" is set." msgstr "\"%s\" 환경 설정 매개 변수를 지정하세요." -#: access/transam/multixact.c:1023 +#: access/transam/multixact.c:1091 #, c-format msgid "" -"database is not accepting commands that generate new MultiXactIds to avoid " +"database is not accepting commands that assign new MultiXactIds to avoid " "wraparound data loss in database \"%s\"" msgstr "" "\"%s\" 데이터베이스 자료 손실을 막기 위해 새로운 MultiXactId 만드는 작업을 " "더 이상 할 수 없습니다." -#: access/transam/multixact.c:1025 access/transam/multixact.c:1032 -#: access/transam/multixact.c:1056 access/transam/multixact.c:1065 +#: access/transam/multixact.c:1093 access/transam/multixact.c:1100 +#: access/transam/multixact.c:1124 access/transam/multixact.c:1133 +#: access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" @@ -1766,19 +1964,19 @@ msgid "" "drop stale replication slots." msgstr "" "해당 데이터베이스 단위로 VACUUM 작업을 진행하십시오.\n" -"또한 오래된 트랜잭션을 커밋또는 롤백하거나 잠긴 복제 슬롯을 지울 필요가 있습" +"또한 오래된 트랜잭션을 커밋 또는 롤백하거나 잠긴 복제 슬롯을 지울 필요가 있습" "니다." -#: access/transam/multixact.c:1030 +#: access/transam/multixact.c:1098 #, c-format msgid "" -"database is not accepting commands that generate new MultiXactIds to avoid " +"database is not accepting commands that assign new MultiXactIds to avoid " "wraparound data loss in database with OID %u" msgstr "" "%u OID 데이터베이스 자료 손실을 막기 위해 새로운 MultiXactId 만드는 작업을 " "더 이상 할 수 없습니다." -#: access/transam/multixact.c:1051 access/transam/multixact.c:2333 +#: access/transam/multixact.c:1119 access/transam/multixact.c:2474 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "" @@ -1787,7 +1985,7 @@ msgstr[0] "" "\"%s\" 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 VACUUM 작업을 해야 합니" "다." -#: access/transam/multixact.c:1060 access/transam/multixact.c:2342 +#: access/transam/multixact.c:1128 access/transam/multixact.c:2483 #, c-format msgid "" "database with OID %u must be vacuumed before %u more MultiXactId is used" @@ -1797,12 +1995,12 @@ msgstr[0] "" "%u OID 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 VACUUM 작업을 해야 합니" "다." -#: access/transam/multixact.c:1121 +#: access/transam/multixact.c:1189 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "multixact \"회수\" 초과" -#: access/transam/multixact.c:1122 +#: access/transam/multixact.c:1190 #, c-format msgid "" "This command would create a multixact with %u members, but the remaining " @@ -1813,17 +2011,17 @@ msgid_plural "" msgstr[0] "" "이 명령은 %u 개의 multixact를 써야하는데, 쓸 수 있는 공간은 %u 개 뿐입니다." -#: access/transam/multixact.c:1127 +#: access/transam/multixact.c:1195 #, c-format msgid "" "Execute a database-wide VACUUM in database with OID %u with reduced " -"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age " -"settings." +"\"vacuum_multixact_freeze_min_age\" and " +"\"vacuum_multixact_freeze_table_age\" settings." msgstr "" -"vacuum_multixact_freeze_min_age, vacuum_multixact_freeze_table_age 값을 조정" -"하고, %u OID 데이터베이스 대상으로 VACUUM 작업을 하십시오." +"\"vacuum_multixact_freeze_min_age\", \"vacuum_multixact_freeze_table_age\" 값" +"을 조정하고, %u OID 데이터베이스 대상으로 VACUUM 작업을 하십시오." -#: access/transam/multixact.c:1158 +#: access/transam/multixact.c:1226 #, c-format msgid "" "database with OID %u must be vacuumed before %d more multixact member is used" @@ -1834,42 +2032,41 @@ msgstr[0] "" "%u OID 데이터베이스는 %d 개의 멀티트랜잭션을 사용하기 전에 vacuum 작업을 해" "야 합니다." -#: access/transam/multixact.c:1163 +#: access/transam/multixact.c:1231 #, c-format msgid "" "Execute a database-wide VACUUM in that database with reduced " -"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age " -"settings." +"\"vacuum_multixact_freeze_min_age\" and " +"\"vacuum_multixact_freeze_table_age\" settings." msgstr "" -"vacuum_multixact_freeze_min_age 설정값과 vacuum_multixact_freeze_table_age 값" -"을 줄여서 데이터베이스 단위로 VACUUM 작업을 진행하세요." +"\"vacuum_multixact_freeze_min_age\" 설정값과 " +"\"vacuum_multixact_freeze_table_age\" 값을 줄여서 데이터베이스 단위로 VACUUM " +"작업을 진행하세요." -#: access/transam/multixact.c:1302 +#: access/transam/multixact.c:1371 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "%u번 MultiXactId 더이상 없음 -- 번호 겹침 현상 발생" -#: access/transam/multixact.c:1308 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "%u번 MultiXactId를 만들 수 없음 -- 번호 겹침 현상 발생" -#: access/transam/multixact.c:2338 access/transam/multixact.c:2347 -#: access/transam/varsup.c:151 access/transam/varsup.c:158 -#: access/transam/varsup.c:466 access/transam/varsup.c:473 +#: access/transam/multixact.c:2479 access/transam/multixact.c:2488 #, c-format msgid "" -"To avoid a database shutdown, execute a database-wide VACUUM in that " -"database.\n" +"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in " +"that database.\n" "You might also need to commit or roll back old prepared transactions, or " "drop stale replication slots." msgstr "" -"데이터베이스가 종료되지 않도록 하려면 데이터베이스 수준의 VACUUM을 실행하십시" +"MultiXactId 할당 실패를 피하려면, 데이터베이스 수준의 VACUUM을 실행하십시" "오.\n" -"또한 오래된 트랜잭션을 커밋또는 롤백 하거나, 잠긴 복제 슬롯을 지울 필요가 있" +"또한 오래된 트랜잭션을 커밋 또는 롤백 하거나, 잠긴 복제 슬롯을 지울 필요가 있" "습니다." -#: access/transam/multixact.c:2622 +#: access/transam/multixact.c:2767 #, c-format msgid "" "MultiXact member wraparound protections are disabled because oldest " @@ -1878,19 +2075,19 @@ msgstr "" "가장 오래된 체크포인트 작업이 완료된 %u 멀티 트랜잭션 번호가 디스크에 없기 때" "문에, 멀티 트랜잭션 번호 겹침 방지 기능이 비활성화 되어 있습니다." -#: access/transam/multixact.c:2644 +#: access/transam/multixact.c:2789 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "멀티 트랜잭션 번호 겹침 방지 기능이 활성화 되었음" -#: access/transam/multixact.c:3027 +#: access/transam/multixact.c:3180 #, c-format msgid "" "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "" "가장 오래된 멀티 트랜잭션 번호는 %u, 가장 최신 것은 %u, truncate 작업 건너뜀" -#: access/transam/multixact.c:3045 +#: access/transam/multixact.c:3198 #, c-format msgid "" "cannot truncate up to MultiXact %u because it does not exist on disk, " @@ -1899,163 +2096,168 @@ msgstr "" "디스크에 해당 멀티 트랜잭션 번호가 없어, %u 멀티 트랜잭션 번호로 truncate 못" "함, truncate 작업 건너뜀" -#: access/transam/multixact.c:3359 +#: access/transam/multixact.c:3517 #, c-format msgid "invalid MultiXactId: %u" msgstr "잘못된 MultiXactId: %u" -#: access/transam/parallel.c:729 access/transam/parallel.c:848 +#: access/transam/parallel.c:748 access/transam/parallel.c:867 #, c-format msgid "parallel worker failed to initialize" msgstr "병렬 작업자 초기화 실패" -#: access/transam/parallel.c:730 access/transam/parallel.c:849 +#: access/transam/parallel.c:749 access/transam/parallel.c:868 #, c-format msgid "More details may be available in the server log." msgstr "보다 자세한 내용은 서버 로그에 남겨졌을 수 있습니다." -#: access/transam/parallel.c:910 +#: access/transam/parallel.c:929 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "병렬 트랜잭션 처리 중 postmaster 종료됨" -#: access/transam/parallel.c:1097 +#: access/transam/parallel.c:1116 #, c-format msgid "lost connection to parallel worker" msgstr "병렬 처리 작업자 프로세스 연결 끊김" -#: access/transam/parallel.c:1163 access/transam/parallel.c:1165 +#: access/transam/parallel.c:1172 access/transam/parallel.c:1174 msgid "parallel worker" msgstr "병렬 처리 작업자" -#: access/transam/parallel.c:1319 replication/logical/applyparallelworker.c:893 +#: access/transam/parallel.c:1344 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "동적 공유 메모리 세그먼트를 할당할 수 없음" -#: access/transam/parallel.c:1324 replication/logical/applyparallelworker.c:899 +#: access/transam/parallel.c:1349 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "동적 공유 메모리 세그먼트에 잘못된 매직 번호가 있음" -#: access/transam/rmgr.c:84 +#: access/transam/rmgr.c:93 #, c-format msgid "resource manager with ID %d not registered" msgstr "%d ID의 자원 관리자가 등록되어 있지 않음" -#: access/transam/rmgr.c:85 +#: access/transam/rmgr.c:94 #, c-format msgid "" "Include the extension module that implements this resource manager in " -"shared_preload_libraries." +"\"shared_preload_libraries\"." msgstr "" -"이 자원 관리자 확장 모듈 라이브러리를 shared_preload_libraries 설정값으로 추" -"가해주세요." +"이 자원 관리자 구현하는 그 확장 모듈을 \"shared_preload_libraries\" 설정값으" +"로 추가해주세요." -#: access/transam/rmgr.c:101 +#: access/transam/rmgr.c:110 #, c-format msgid "custom resource manager name is invalid" msgstr "사용자 정의 자원 관리자 이름이 바르지 않음" -#: access/transam/rmgr.c:102 +#: access/transam/rmgr.c:111 #, c-format msgid "Provide a non-empty name for the custom resource manager." msgstr "사용자 정의 자원 관리자 이름은 비워둘 수 없습니다." -#: access/transam/rmgr.c:105 +#: access/transam/rmgr.c:114 #, c-format msgid "custom resource manager ID %d is out of range" msgstr "사용자 정의 자원 관리자 %d ID 번호의 범위가 벗어남" -#: access/transam/rmgr.c:106 +#: access/transam/rmgr.c:115 #, c-format msgid "Provide a custom resource manager ID between %d and %d." msgstr "사용자 정의 자원 관리자 ID는 %d 에서 %d 까지만 지정할 수 있음." -#: access/transam/rmgr.c:111 access/transam/rmgr.c:116 -#: access/transam/rmgr.c:128 +#: access/transam/rmgr.c:120 access/transam/rmgr.c:125 +#: access/transam/rmgr.c:137 #, c-format msgid "failed to register custom resource manager \"%s\" with ID %d" msgstr "\"%s\" 사용자 정의 자원 관리자를 %d ID로 등록할 수 없음" -#: access/transam/rmgr.c:112 +#: access/transam/rmgr.c:121 #, c-format msgid "" "Custom resource manager must be registered while initializing modules in " -"shared_preload_libraries." +"\"shared_preload_libraries\"." msgstr "" -"사용자 정의 자원 관리자를 사용하려면 먼저 shared_preload_libraries 설정값으" -"로 등록되어야 합니다." +"사용자 정의 자원 관리자를 사용하려면 먼저 \"shared_preload_libraries\" 설정값" +"으로 등록되어야 합니다." -#: access/transam/rmgr.c:117 +#: access/transam/rmgr.c:126 #, c-format msgid "Custom resource manager \"%s\" already registered with the same ID." msgstr "\"%s\" 사용자 정의 자원 관리자 ID가 이미 등록되어 있습니다." -#: access/transam/rmgr.c:129 +#: access/transam/rmgr.c:138 #, c-format msgid "Existing resource manager with ID %d has the same name." msgstr "%d ID 자원 관리자가 같은 이름입니다." -#: access/transam/rmgr.c:135 +#: access/transam/rmgr.c:144 #, c-format msgid "registered custom resource manager \"%s\" with ID %d" msgstr "\"%s\" 사용자 정의 자원 관리자가 %d ID로 등록됨" -#: access/transam/slru.c:714 +#: access/transam/slru.c:361 +#, c-format +msgid "\"%s\" must be a multiple of %d" +msgstr "\"%s\" 값은 %d의 배수여야 함" + +#: access/transam/slru.c:830 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "\"%s\" 파일 없음, 0으로 읽음" -#: access/transam/slru.c:946 access/transam/slru.c:952 -#: access/transam/slru.c:960 access/transam/slru.c:965 -#: access/transam/slru.c:972 access/transam/slru.c:977 -#: access/transam/slru.c:984 access/transam/slru.c:991 +#: access/transam/slru.c:1059 access/transam/slru.c:1065 +#: access/transam/slru.c:1073 access/transam/slru.c:1078 +#: access/transam/slru.c:1085 access/transam/slru.c:1090 +#: access/transam/slru.c:1097 access/transam/slru.c:1104 #, c-format msgid "could not access status of transaction %u" msgstr "%u 트랜잭션의 상태를 액세스할 수 없음" -#: access/transam/slru.c:947 +#: access/transam/slru.c:1060 #, c-format msgid "Could not open file \"%s\": %m." msgstr "\"%s\" 파일을 열 수 없음: %m." -#: access/transam/slru.c:953 +#: access/transam/slru.c:1066 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "\"%s\" 파일에서 %d 위치를 찾을 수 없음: %m." -#: access/transam/slru.c:961 +#: access/transam/slru.c:1074 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "\"%s\" 파일에서 %d 위치를 읽을 수 없음: %m." -#: access/transam/slru.c:966 +#: access/transam/slru.c:1079 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "\"%s\" 파일에서 %d 위치를 읽을 수 없음: 너무 적은 바이트를 읽음." -#: access/transam/slru.c:973 +#: access/transam/slru.c:1086 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "\"%s\" 파일에서 %d 위치에 쓸 수 없음: %m." -#: access/transam/slru.c:978 +#: access/transam/slru.c:1091 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "\"%s\" 파일에서 %d 위치에 쓸 수 없음: 너무 적은 바이트를 씀." -#: access/transam/slru.c:985 +#: access/transam/slru.c:1098 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "\"%s\" 파일 fsync 실패: %m." -#: access/transam/slru.c:992 +#: access/transam/slru.c:1105 #, c-format msgid "Could not close file \"%s\": %m." msgstr "\"%s\" 파일을 닫을 수 없음: %m." -#: access/transam/slru.c:1253 +#: access/transam/slru.c:1431 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "\"%s\" 디렉터리를 비울 수 없음: 랩어라운드 발생" @@ -2100,130 +2302,131 @@ msgstr "타임라인 ID는 하위 타임라인 ID보다 작아야 합니다." msgid "requested timeline %u is not in this server's history" msgstr "요청한 %u 타이라인이 이 서버 내역에는 없음" -#: access/transam/twophase.c:386 +#: access/transam/twophase.c:368 #, c-format msgid "transaction identifier \"%s\" is too long" msgstr "\"%s\" 트랜잭션 식별자가 너무 깁니다" -#: access/transam/twophase.c:393 +#: access/transam/twophase.c:375 #, c-format msgid "prepared transactions are disabled" msgstr "준비된 트랜잭션이 비활성화됨" -#: access/transam/twophase.c:394 +#: access/transam/twophase.c:376 #, c-format -msgid "Set max_prepared_transactions to a nonzero value." -msgstr "max_prepared_transactions 설정값을 0이 아닌 값으로 설정하십시오." +msgid "Set \"max_prepared_transactions\" to a nonzero value." +msgstr "\"max_prepared_transactions\" 설정값을 0이 아닌 값으로 설정하십시오." -#: access/transam/twophase.c:413 +#: access/transam/twophase.c:395 #, c-format msgid "transaction identifier \"%s\" is already in use" msgstr "\"%s\" 이름의 트랜잭션 식별자가 이미 사용 중입니다" -#: access/transam/twophase.c:422 access/transam/twophase.c:2517 +#: access/transam/twophase.c:404 access/transam/twophase.c:2547 #, c-format msgid "maximum number of prepared transactions reached" msgstr "준비된 트랜잭션의 최대 개수를 모두 사용했습니다" -#: access/transam/twophase.c:423 access/transam/twophase.c:2518 +#: access/transam/twophase.c:405 access/transam/twophase.c:2548 #, c-format -msgid "Increase max_prepared_transactions (currently %d)." -msgstr "max_prepared_transactions 값을 늘려주세요 (현재 %d)." +msgid "Increase \"max_prepared_transactions\" (currently %d)." +msgstr "\"max_prepared_transactions\" 값을 늘려주세요 (현재 %d)." -#: access/transam/twophase.c:599 +#: access/transam/twophase.c:580 #, c-format msgid "prepared transaction with identifier \"%s\" is busy" msgstr "\"%s\" 이름의 준비된 트랜잭션 식별자가 여러 곳에서 쓰이고 있습니다" -#: access/transam/twophase.c:605 +#: access/transam/twophase.c:586 #, c-format msgid "permission denied to finish prepared transaction" msgstr "준비된 트랜잭션 끝내기 작업 권한 없음" -#: access/transam/twophase.c:606 +#: access/transam/twophase.c:587 #, c-format msgid "Must be superuser or the user that prepared the transaction." msgstr "해당 준비된 트랜잭션의 소유주이거나 superuser여야 합니다" -#: access/transam/twophase.c:617 +#: access/transam/twophase.c:598 #, c-format msgid "prepared transaction belongs to another database" msgstr "준비된 트랜잭션이 다른 데이터베이스에 속해 있음" -#: access/transam/twophase.c:618 +#: access/transam/twophase.c:599 #, c-format msgid "" "Connect to the database where the transaction was prepared to finish it." msgstr "작업을 마치려면 그 준비된 트랜잭션이 있는 데이터베이스에 연결하십시오." -#: access/transam/twophase.c:633 +#: access/transam/twophase.c:614 #, c-format msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "\"%s\" 이름의 준비된 트랜잭션이 없습니다" -#: access/transam/twophase.c:1168 +#: access/transam/twophase.c:1190 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "2단계 상태 파일 최대 길이를 초과함" -#: access/transam/twophase.c:1323 +#: access/transam/twophase.c:1345 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" msgstr[0] "\"%s\" 파일 크기가 이상함: %lld 바이트" -#: access/transam/twophase.c:1332 +#: access/transam/twophase.c:1354 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "\"%s\" 파일의 CRC 값 맞춤 실패" -#: access/transam/twophase.c:1350 +#: access/transam/twophase.c:1372 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %lld" -#: access/transam/twophase.c:1365 +#: access/transam/twophase.c:1387 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "\"%s\" 파일에 잘못된 매직 번호가 저장되어 있음" -#: access/transam/twophase.c:1371 +#: access/transam/twophase.c:1393 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "\"%s\" 파일 크기가 이상함" -#: access/transam/twophase.c:1383 +#: access/transam/twophase.c:1405 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "계산된 CRC 체크섬 값이 파일에 \"%s\" 파일에 저장된 값과 다름" -#: access/transam/twophase.c:1413 access/transam/xlogrecovery.c:590 -#: replication/logical/logical.c:209 replication/walsender.c:687 +#: access/transam/twophase.c:1435 access/transam/xlogrecovery.c:565 +#: postmaster/walsummarizer.c:936 replication/logical/logical.c:211 +#: replication/walsender.c:836 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "WAL 읽기 프로세서를 할당하는 중에 오류 발생" -#: access/transam/twophase.c:1423 +#: access/transam/twophase.c:1445 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "two-phase 상태정보을 읽을 수 없음 WAL 위치: %X/%X, %s" -#: access/transam/twophase.c:1428 +#: access/transam/twophase.c:1450 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "two-phase 상태정보을 읽을 수 없음 WAL 위치: %X/%X" -#: access/transam/twophase.c:1436 +#: access/transam/twophase.c:1458 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "WAL %X/%X 위치에 2단계 커밋 상태 자료가 없습니다" -#: access/transam/twophase.c:1732 +#: access/transam/twophase.c:1761 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "\"%s\" 파일을 다시 만들 수 없음: %m" -#: access/transam/twophase.c:1859 +#: access/transam/twophase.c:1888 #, c-format msgid "" "%u two-phase state file was written for a long-running prepared transaction" @@ -2232,48 +2435,48 @@ msgid_plural "" msgstr[0] "" "긴 실행 미리 준비된 트랜잭션 용 %u 개의 2단계 상태 파일이 저장되었음" -#: access/transam/twophase.c:2093 +#: access/transam/twophase.c:2123 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "공유 메모리에서 %u 준비된 트랜잭션을 복구함" -#: access/transam/twophase.c:2186 +#: access/transam/twophase.c:2216 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "%u 트랜잭션에서 사용하는 오래된 two-phase 상태정보 파일을 삭제함" -#: access/transam/twophase.c:2193 +#: access/transam/twophase.c:2223 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "" "%u 트랜잭션에서 사용하는 오래된 two-phase 상태정보를 공유 메모리에서 삭제함" -#: access/transam/twophase.c:2206 +#: access/transam/twophase.c:2236 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "%u 트랜잭션에서 사용하는 future two-phase 상태정보 파일을 삭제함" -#: access/transam/twophase.c:2213 +#: access/transam/twophase.c:2243 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "%u 트랜잭션에서 사용하는 future two-phase 상태정보를 메모리에서 삭제함" -#: access/transam/twophase.c:2238 +#: access/transam/twophase.c:2268 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "%u 트랜잭션에서 사용하는 two-phase 상태정보 파일이 손상되었음" -#: access/transam/twophase.c:2243 +#: access/transam/twophase.c:2273 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "%u 트랜잭션에서 사용하는 메모리에 있는 two-phase 상태정보가 손상되었음" -#: access/transam/twophase.c:2500 +#: access/transam/twophase.c:2530 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "%u 트랜잭션에서 사용하는 two-phase 상태정보 파일을 복구할 없음" -#: access/transam/twophase.c:2502 +#: access/transam/twophase.c:2532 #, c-format msgid "" "Two-phase state file has been found in WAL record %X/%X, but this " @@ -2282,223 +2485,261 @@ msgstr "" "WAL 레코드 %X/%X 에서 2PC 상태 파일을 찾았지만, 그 트랜잭션은 이미 디스크에 " "기록한 상태입니다." -#: access/transam/twophase.c:2510 jit/jit.c:205 utils/fmgr/dfmgr.c:209 -#: utils/fmgr/dfmgr.c:415 +#: access/transam/twophase.c:2540 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 #, c-format msgid "could not access file \"%s\": %m" msgstr "\"%s\" 파일에 액세스할 수 없음: %m" -#: access/transam/varsup.c:129 +#: access/transam/varsup.c:156 #, c-format msgid "" -"database is not accepting commands to avoid wraparound data loss in database " -"\"%s\"" +"database is not accepting commands that assign new transaction IDs to avoid " +"wraparound data loss in database \"%s\"" +msgstr "" +"\"%s\" 데이터베이스 자료 손실을 막기 위해 새로운 트랜잭션 ID 만드는 작업을 " +"더 이상 할 수 없습니다." + +#: access/transam/varsup.c:163 +#, c-format +msgid "" +"database is not accepting commands that assign new transaction IDs to avoid " +"wraparound data loss in database with OID %u" msgstr "" -"\"%s\" 데이터베이스 트랜잭션 ID 겹침에 의한 자료 손실을 방지하기 위해 더 이" -"상 자료 조작 작업을 허용하지 않습니다" +"%u OID 데이터베이스 자료 손실을 막기 위해 새로운 트랜잭션 ID 만드는 작업을 " +"더 이상 할 수 없습니다." + +#: access/transam/varsup.c:175 access/transam/varsup.c:490 +#, c-format +msgid "database \"%s\" must be vacuumed within %u transactions" +msgstr "\"%s\" 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다" -#: access/transam/varsup.c:131 access/transam/varsup.c:138 +#: access/transam/varsup.c:178 #, c-format msgid "" -"Stop the postmaster and vacuum that database in single-user mode.\n" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM " +"in that database.\n" "You might also need to commit or roll back old prepared transactions, or " "drop stale replication slots." msgstr "" -"postmaster를 중지하고 단일 사용자 모드로 서버를 실행한 뒤 VACUUM 작업을 하십" -"시오.\n" -"또한 오래된 트랜잭션을 커밋 또는 롤백하거나, 잠긴 복제 슬롯을 지울 필요가 있" +"트랜잭션 ID를 계속 할당할 수 있게 하려면 데이터베이스 수준의 VACUUM을 실행하" +"십시오.\n" +"또한 오래된 트랜잭션을 커밋 또는 롤백 하거나, 잠긴 복제 슬롯을 지울 필요가 있" "습니다." -#: access/transam/varsup.c:136 +#: access/transam/varsup.c:182 access/transam/varsup.c:497 +#, c-format +msgid "database with OID %u must be vacuumed within %u transactions" +msgstr "%u OID 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다" + +#: access/transam/varsup.c:185 access/transam/varsup.c:493 +#: access/transam/varsup.c:500 #, c-format msgid "" -"database is not accepting commands to avoid wraparound data loss in database " -"with OID %u" +"To avoid XID assignment failures, execute a database-wide VACUUM in that " +"database.\n" +"You might also need to commit or roll back old prepared transactions, or " +"drop stale replication slots." msgstr "" -"%u OID 데이터베이스에서 자료 겹침으로 발생할 수 있는 자료 손실을 방지하기 위" -"해 명령을 수락하지 않음" +"XID 할당 실패를 피하려면 데이터베이스 수준의 VACUUM을 실행하십시오.\n" +"또한 오래된 트랜잭션을 커밋 또는 롤백 하거나, 잠긴 복제 슬롯을 지울 필요가 있" +"습니다." -#: access/transam/varsup.c:148 access/transam/varsup.c:463 +#: access/transam/xact.c:649 #, c-format -msgid "database \"%s\" must be vacuumed within %u transactions" -msgstr "\"%s\" 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다" +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "병렬 처리 중에는 트랜잭션 ID를 지정할 수 없음" -#: access/transam/varsup.c:155 access/transam/varsup.c:470 +#: access/transam/xact.c:840 #, c-format -msgid "database with OID %u must be vacuumed within %u transactions" -msgstr "%u OID 데이터베이스는 %u번의 트랜잭션이 발생되기 전에 청소해야 합니다" +msgid "cannot modify data in a parallel worker" +msgstr "병렬 작업자는 자료 변경을 할 수 없음" + +#: access/transam/xact.c:1115 +#, c-format +msgid "cannot start commands during a parallel operation" +msgstr "병렬 처리 중에는 명령을 시작할 수 없음" -#: access/transam/xact.c:1102 +#: access/transam/xact.c:1123 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "하나의 트랜잭션 안에서는 2^32-2 개의 명령을 초과할 수 없음" -#: access/transam/xact.c:1643 +#: access/transam/xact.c:1664 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "커밋된 하위 트랜잭션 수(%d)가 최대치를 초과함" -#: access/transam/xact.c:2513 +#: access/transam/xact.c:2561 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "임시 개체 대해 실행된 트랜잭션을 PREPARE할 수 없음" -#: access/transam/xact.c:2523 +#: access/transam/xact.c:2571 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "스냅샷으로 내보낸 트랜잭션은 PREPARE 작업을 할 수 없음" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3489 +#: access/transam/xact.c:3593 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s 명령은 트랜잭션 블럭안에서 실행할 수 없음" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3499 +#: access/transam/xact.c:3603 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%s 명령은 서브트랜잭션 블럭안에서 실행할 수 없음" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3509 +#: access/transam/xact.c:3613 #, c-format msgid "%s cannot be executed within a pipeline" msgstr "%s 절은 파이프라인에서 실행될 수 없음" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3519 +#: access/transam/xact.c:3623 #, c-format msgid "%s cannot be executed from a function" msgstr "%s 절은 함수에서 실행될 수 없음" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3590 access/transam/xact.c:3915 -#: access/transam/xact.c:3994 access/transam/xact.c:4117 -#: access/transam/xact.c:4268 access/transam/xact.c:4337 -#: access/transam/xact.c:4448 +#: access/transam/xact.c:3694 access/transam/xact.c:4019 +#: access/transam/xact.c:4098 access/transam/xact.c:4221 +#: access/transam/xact.c:4372 access/transam/xact.c:4441 +#: access/transam/xact.c:4552 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%s 명령은 트랜잭션 블럭에서만 사용될 수 있음" -#: access/transam/xact.c:3801 +#: access/transam/xact.c:3905 #, c-format msgid "there is already a transaction in progress" msgstr "이미 트랜잭션 작업이 진행 중입니다" -#: access/transam/xact.c:3920 access/transam/xact.c:3999 -#: access/transam/xact.c:4122 +#: access/transam/xact.c:4024 access/transam/xact.c:4103 +#: access/transam/xact.c:4226 #, c-format msgid "there is no transaction in progress" msgstr "현재 트랜잭션 작업을 하지 않고 있습니다" -#: access/transam/xact.c:4010 +#: access/transam/xact.c:4114 #, c-format msgid "cannot commit during a parallel operation" msgstr "데이터베이스 트랜잭션을 commit 할 수 없음" -#: access/transam/xact.c:4133 +#: access/transam/xact.c:4237 #, c-format msgid "cannot abort during a parallel operation" msgstr "병렬 작업 중에는 중지 할 수 없음" -#: access/transam/xact.c:4232 +#: access/transam/xact.c:4336 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "병렬 작업 중에는 savepoint 지정을 할 수 없음" -#: access/transam/xact.c:4319 +#: access/transam/xact.c:4423 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "병렬 작업 중에는 savepoint를 지울 수 없음" -#: access/transam/xact.c:4329 access/transam/xact.c:4380 -#: access/transam/xact.c:4440 access/transam/xact.c:4489 +#: access/transam/xact.c:4433 access/transam/xact.c:4484 +#: access/transam/xact.c:4544 access/transam/xact.c:4593 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "\"%s\" 이름의 저장위치가 없음" -#: access/transam/xact.c:4386 access/transam/xact.c:4495 +#: access/transam/xact.c:4490 access/transam/xact.c:4599 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "현재 저장위치 수준에서 \"%s\" 이름의 저장위치가 없음" -#: access/transam/xact.c:4428 +#: access/transam/xact.c:4532 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "병렬 작업 중에는 savepoint 지정 취소 작업을 할 수 없음" -#: access/transam/xact.c:4556 -#, c-format -msgid "cannot start subtransactions during a parallel operation" -msgstr "병렬 처리 중에는 하위트랜잭션을 시작할 수 없음" - -#: access/transam/xact.c:4624 -#, c-format -msgid "cannot commit subtransactions during a parallel operation" -msgstr "병렬 처리 중에는 하위트랜잭션을 커밋할 수 없음" - -#: access/transam/xact.c:5270 +#: access/transam/xact.c:5376 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "하나의 트랜잭션 안에서는 2^32-1 개의 하위트랜잭션을 초과할 수 없음" -#: access/transam/xlog.c:1466 +#: access/transam/xlog.c:1542 #, c-format msgid "" "request to flush past end of generated WAL; request %X/%X, current position " "%X/%X" msgstr "생성된 WAL의 끝을 지난 flush 요청, 요청위치: %X/%X, 현재위치: %X/%X" +#: access/transam/xlog.c:1769 +#, c-format +msgid "" +"cannot read past end of generated WAL: requested %X/%X, current position %X/" +"%X" +msgstr "" +"생성된 WAL의 끝을 지나서 읽을 수 없음: 요청위치: %X/%X, 현재위치: %X/%X" + +#: access/transam/xlog.c:2210 access/transam/xlog.c:4501 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL 조각 파일은 1MB부터 1GB 사이 2^n 크기여야 합니다." + #: access/transam/xlog.c:2228 #, c-format -msgid "could not write to log file %s at offset %u, length %zu: %m" -msgstr "%s 로그 파일 쓰기 실패, 위치 %u, 길이 %zu: %m" +msgid "\"%s\" must be set to -1 during binary upgrade mode." +msgstr "바이너리 업그레이드 모드 중는 \"%s\" 값은 -1이어야 합니다." + +#: access/transam/xlog.c:2477 +#, c-format +msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" +msgstr "\"%s\" 로그 파일 쓰기 실패, 위치 %u, 길이 %zu: %m" -#: access/transam/xlog.c:3455 access/transam/xlogutils.c:833 -#: replication/walsender.c:2725 +#: access/transam/xlog.c:3739 access/transam/xlogutils.c:831 +#: replication/walsender.c:3045 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "요청한 %s WAL 조각 파일은 이미 지워졌음" -#: access/transam/xlog.c:3739 +#: access/transam/xlog.c:4061 #, c-format msgid "could not rename file \"%s\": %m" msgstr "\"%s\" 파일의 이름을 바꿀 수 없음: %m" -#: access/transam/xlog.c:3781 access/transam/xlog.c:3791 +#: access/transam/xlog.c:4104 access/transam/xlog.c:4115 +#: access/transam/xlog.c:4136 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "필요한 WAL 디렉터리 \"%s\"이(가) 없음" -#: access/transam/xlog.c:3797 +#: access/transam/xlog.c:4121 access/transam/xlog.c:4142 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "누락된 WAL 디렉터리 \"%s\"을(를) 만드는 중" -#: access/transam/xlog.c:3800 commands/dbcommands.c:3172 +#: access/transam/xlog.c:4125 access/transam/xlog.c:4145 +#: commands/dbcommands.c:3262 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "누락된 \"%s\" 디렉터리를 만들 수 없음: %m" -#: access/transam/xlog.c:3867 +#: access/transam/xlog.c:4212 #, c-format msgid "could not generate secret authorization token" msgstr "비밀 인증 토큰을 만들 수 없음" -#: access/transam/xlog.c:4017 access/transam/xlog.c:4026 -#: access/transam/xlog.c:4050 access/transam/xlog.c:4057 -#: access/transam/xlog.c:4064 access/transam/xlog.c:4069 -#: access/transam/xlog.c:4076 access/transam/xlog.c:4083 -#: access/transam/xlog.c:4090 access/transam/xlog.c:4097 -#: access/transam/xlog.c:4104 access/transam/xlog.c:4111 -#: access/transam/xlog.c:4120 access/transam/xlog.c:4127 -#: utils/init/miscinit.c:1762 +#: access/transam/xlog.c:4363 access/transam/xlog.c:4373 +#: access/transam/xlog.c:4399 access/transam/xlog.c:4407 +#: access/transam/xlog.c:4415 access/transam/xlog.c:4421 +#: access/transam/xlog.c:4429 access/transam/xlog.c:4437 +#: access/transam/xlog.c:4445 access/transam/xlog.c:4453 +#: access/transam/xlog.c:4461 access/transam/xlog.c:4469 +#: access/transam/xlog.c:4479 access/transam/xlog.c:4487 +#: utils/init/miscinit.c:1812 #, c-format msgid "database files are incompatible with server" msgstr "데이터베이스 파일들이 서버와 호환성이 없습니다" -#: access/transam/xlog.c:4018 +#: access/transam/xlog.c:4364 #, c-format msgid "" "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), " @@ -2507,7 +2748,7 @@ msgstr "" "데이터베이스 클러스터는 PG_CONTROL_VERSION %d (0x%08x)(으)로 초기화되었지만 " "서버는 PG_CONTROL_VERSION %d (0x%08x)(으)로 컴파일되었습니다." -#: access/transam/xlog.c:4022 +#: access/transam/xlog.c:4368 #, c-format msgid "" "This could be a problem of mismatched byte ordering. It looks like you need " @@ -2515,7 +2756,7 @@ msgid "" msgstr "" "이것은 바이트 순서 불일치 문제일 수 있습니다. initdb 작업이 필요해 보입니다." -#: access/transam/xlog.c:4027 +#: access/transam/xlog.c:4374 #, c-format msgid "" "The database cluster was initialized with PG_CONTROL_VERSION %d, but the " @@ -2524,18 +2765,18 @@ msgstr "" "이 데이터베이스 클러스터는 PG_CONTROL_VERSION %d 버전으로 초기화 되었지만, 서" "버는 PG_CONTROL_VERSION %d 버전으로 컴파일 되어있습니다." -#: access/transam/xlog.c:4030 access/transam/xlog.c:4054 -#: access/transam/xlog.c:4061 access/transam/xlog.c:4066 +#: access/transam/xlog.c:4377 access/transam/xlog.c:4403 +#: access/transam/xlog.c:4411 access/transam/xlog.c:4417 #, c-format msgid "It looks like you need to initdb." msgstr "initdb 명령이 필요한 듯 합니다" -#: access/transam/xlog.c:4041 +#: access/transam/xlog.c:4389 #, c-format msgid "incorrect checksum in control file" msgstr "컨트롤 파일에 잘못된 체크섬 값이 있습니다" -#: access/transam/xlog.c:4051 +#: access/transam/xlog.c:4400 #, c-format msgid "" "The database cluster was initialized with CATALOG_VERSION_NO %d, but the " @@ -2544,7 +2785,7 @@ msgstr "" "이 데이터베이스 클러스터는 CATALOG_VERSION_NO %d 버전으로 초기화 되었지만, 서" "버는 CATALOG_VERSION_NO %d 버전으로 컴파일 되어있습니다." -#: access/transam/xlog.c:4058 +#: access/transam/xlog.c:4408 #, c-format msgid "" "The database cluster was initialized with MAXALIGN %d, but the server was " @@ -2553,7 +2794,7 @@ msgstr "" "이 데이터베이스 클러스터는 MAXALIGN %d (으)로 초기화 되었지만, 서버는 " "MAXALIGN %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4065 +#: access/transam/xlog.c:4416 #, c-format msgid "" "The database cluster appears to use a different floating-point number format " @@ -2562,7 +2803,7 @@ msgstr "" "데이터베이스 클러스터와 서버 실행 파일이 서로 다른 부동 소수점 숫자 형식을 사" "용하고 있습니다." -#: access/transam/xlog.c:4070 +#: access/transam/xlog.c:4422 #, c-format msgid "" "The database cluster was initialized with BLCKSZ %d, but the server was " @@ -2571,18 +2812,18 @@ msgstr "" "이 데이터베이스 클러스터는 BLCKSZ %d (으)로 초기화 되었지만, 서버는 BLCKSZ " "%d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4073 access/transam/xlog.c:4080 -#: access/transam/xlog.c:4087 access/transam/xlog.c:4094 -#: access/transam/xlog.c:4101 access/transam/xlog.c:4108 -#: access/transam/xlog.c:4115 access/transam/xlog.c:4123 -#: access/transam/xlog.c:4130 +#: access/transam/xlog.c:4425 access/transam/xlog.c:4433 +#: access/transam/xlog.c:4441 access/transam/xlog.c:4449 +#: access/transam/xlog.c:4457 access/transam/xlog.c:4465 +#: access/transam/xlog.c:4473 access/transam/xlog.c:4482 +#: access/transam/xlog.c:4490 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "" "서버를 새로 컴파일 하거나 initdb 명령을 사용해 새로 데이터베이스 클러스터를 " "다시 만들거나 해야할 것 같습니다." -#: access/transam/xlog.c:4077 +#: access/transam/xlog.c:4430 #, c-format msgid "" "The database cluster was initialized with RELSEG_SIZE %d, but the server was " @@ -2591,7 +2832,7 @@ msgstr "" "이 데이터베이스 클러스터는 RELSEG_SIZE %d (으)로 초기화 되었지만, 서버는 " "RELSEG_SIZE %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4084 +#: access/transam/xlog.c:4438 #, c-format msgid "" "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was " @@ -2600,7 +2841,7 @@ msgstr "" "이 데이터베이스 클러스터는 XLOG_BLCKSZ %d (으)로 초기화 되었지만, 서버는 " "XLOG_BLCKSZ %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4091 +#: access/transam/xlog.c:4446 #, c-format msgid "" "The database cluster was initialized with NAMEDATALEN %d, but the server was " @@ -2609,7 +2850,7 @@ msgstr "" "이 데이터베이스 클러스터는 NAMEDATALEN %d (으)로 초기화 되었지만, 서버는 " "NAMEDATALEN %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4098 +#: access/transam/xlog.c:4454 #, c-format msgid "" "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server " @@ -2618,7 +2859,7 @@ msgstr "" "이 데이터베이스 클러스터는 INDEX_MAX_KEYS %d (으)로 초기화 되었지만, 서버는 " "INDEX_MAX_KEYS %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4105 +#: access/transam/xlog.c:4462 #, c-format msgid "" "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the " @@ -2627,7 +2868,7 @@ msgstr "" "데이터베이스 클러스터는 TOAST_MAX_CHUNK_SIZE %d(으)로 초기화되었지만 서버는 " "TOAST_MAX_CHUNK_SIZE %d(으)로 컴파일 되었습니다." -#: access/transam/xlog.c:4112 +#: access/transam/xlog.c:4470 #, c-format msgid "" "The database cluster was initialized with LOBLKSIZE %d, but the server was " @@ -2636,7 +2877,7 @@ msgstr "" "이 데이터베이스 클러스터는 LOBLKSIZE %d(으)로 초기화 되었지만, 서버는 " "LOBLKSIZE %d (으)로 컴파일 되어있습니다." -#: access/transam/xlog.c:4121 +#: access/transam/xlog.c:4480 #, c-format msgid "" "The database cluster was initialized without USE_FLOAT8_BYVAL but the server " @@ -2645,7 +2886,7 @@ msgstr "" "데이터베이스 클러스터는 USE_FLOAT8_BYVAL 없이 초기화되었지만, 서버는 " "USE_FLOAT8_BYVAL을 사용하여 컴파일되었습니다." -#: access/transam/xlog.c:4128 +#: access/transam/xlog.c:4488 #, c-format msgid "" "The database cluster was initialized with USE_FLOAT8_BYVAL but the server " @@ -2654,103 +2895,100 @@ msgstr "" "데이터베이스 클러스터는 USE_FLOAT8_BYVAL을 사용하여 초기화되었지만, 서버는 " "USE_FLOAT8_BYVAL 없이 컴파일되었습니다." -#: access/transam/xlog.c:4137 +#: access/transam/xlog.c:4497 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d bytes" -msgstr[0] "" -"WAL 조각 파일은 1MB부터 1GB 사이 2^n 크기여야 하지만, 컨트롤 파일에는 %d 바이" -"트로 지정되었음" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "컨트롤 파일 안 잘못된 WAL 조각 크기 (%d 바이트)" -#: access/transam/xlog.c:4149 +#: access/transam/xlog.c:4510 #, c-format msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"min_wal_size\" 값은 \"wal_segment_size\" 값의 최소 2배 이상이어야 함" -#: access/transam/xlog.c:4153 +#: access/transam/xlog.c:4514 #, c-format msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"max_wal_size\" 값은 \"wal_segment_size\" 값의 최소 2배 이상이어야 함" -#: access/transam/xlog.c:4308 catalog/namespace.c:4335 -#: commands/tablespace.c:1216 commands/user.c:2536 commands/variable.c:72 -#: utils/error/elog.c:2205 +#: access/transam/xlog.c:4662 catalog/namespace.c:4696 +#: commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 +#: replication/slot.c:2429 tcop/postgres.c:3715 utils/error/elog.c:2247 #, c-format msgid "List syntax is invalid." msgstr "목록 문법이 틀렸습니다." -#: access/transam/xlog.c:4354 commands/user.c:2552 commands/variable.c:173 -#: utils/error/elog.c:2231 +#: access/transam/xlog.c:4708 commands/user.c:2545 commands/variable.c:173 +#: tcop/postgres.c:3731 utils/error/elog.c:2273 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "알 수 없는 키워드: \"%s\"" -#: access/transam/xlog.c:4768 +#: access/transam/xlog.c:5129 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "bootstrap 트랜잭션 로그 파일을 쓸 수 없음: %m" -#: access/transam/xlog.c:4776 +#: access/transam/xlog.c:5137 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "bootstrap 트랜잭션 로그 파일을 fsync할 수 없음: %m" -#: access/transam/xlog.c:4782 +#: access/transam/xlog.c:5143 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "bootstrap 트랜잭션 로그 파일을 닫을 수 없음: %m" -#: access/transam/xlog.c:4999 +#: access/transam/xlog.c:5368 #, c-format -msgid "WAL was generated with wal_level=minimal, cannot continue recovering" +msgid "" +"WAL was generated with \"wal_level=minimal\", cannot continue recovering" msgstr "" -"WAL 내용이 wal_level=minimal 설정으로 만들여졌습니다. 복원 작업을 계속 할 수 " -"없음" +"WAL 내용이 \"wal_level=minimal\" 설정으로 만들여졌습니다. 복구 작업을 계속 " +"할 수 없음" -#: access/transam/xlog.c:5000 +#: access/transam/xlog.c:5369 #, c-format -msgid "This happens if you temporarily set wal_level=minimal on the server." +msgid "" +"This happens if you temporarily set \"wal_level=minimal\" on the server." msgstr "" -"이 문제는 서버가 일시적으로 wal_level=minimal 설정으로 운영된 적이 있다면 발" -"생합니다." +"이 문제는 서버가 일시적으로 \"wal_level=minimal\" 설정으로 운영된 적이 있다" +"면 발생합니다." -#: access/transam/xlog.c:5001 +#: access/transam/xlog.c:5370 #, c-format -msgid "Use a backup taken after setting wal_level to higher than minimal." -msgstr "wal_level 값을 minimal 보다 높은 것으로 설정해서 백업하세요." +msgid "" +"Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." +msgstr "\"wal_level\" 값을 \"minimal\" 보다 높은 것으로 설정해서 백업하세요." -#: access/transam/xlog.c:5065 +#: access/transam/xlog.c:5435 #, c-format msgid "control file contains invalid checkpoint location" msgstr "컨트롤 파일에 잘못된 체크포인트 위치가 있습니다" -#: access/transam/xlog.c:5076 +#: access/transam/xlog.c:5446 #, c-format msgid "database system was shut down at %s" msgstr "데이터베이스 시스템 마지막 가동 중지 시각: %s" -#: access/transam/xlog.c:5082 +#: access/transam/xlog.c:5452 #, c-format msgid "database system was shut down in recovery at %s" msgstr "복구 중 데이터베이스 시스템 마지막 가동 중지 시각: %s" -#: access/transam/xlog.c:5088 +#: access/transam/xlog.c:5458 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "" "데이터베이스 시스템 셧다운 작업이 비정상적으로 종료되었음; 마지막 운영시간: " "%s" -#: access/transam/xlog.c:5094 +#: access/transam/xlog.c:5464 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "데이터베이스 시스템 복구하는 도중 비정상적으로 가동 중지된 시각: %s" -#: access/transam/xlog.c:5096 +#: access/transam/xlog.c:5466 #, c-format msgid "" "This probably means that some data is corrupted and you will have to use the " @@ -2759,12 +2997,12 @@ msgstr "" "이 사태는 몇몇 데이터가 손상되었을 의미할 수도 있습니다. 확인해 보고, 필요하" "다면, 마지막 백업 자료로 복구해서 사용하세요." -#: access/transam/xlog.c:5102 +#: access/transam/xlog.c:5472 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "데이터베이스 시스템이 로그 시간 %s에 복구 도중 중지 되었음" -#: access/transam/xlog.c:5104 +#: access/transam/xlog.c:5474 #, c-format msgid "" "If this has occurred more than once some data might be corrupted and you " @@ -2773,22 +3011,22 @@ msgstr "" "이 사태로 몇몇 자료가 손상되었을 수도 있는데, 이런 경우라면,확인해 보고, 필요" "하다면, 마지막 백업 자료로 복구해서 사용하세요." -#: access/transam/xlog.c:5110 +#: access/transam/xlog.c:5480 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "데이터베이스 시스템이 비정상적으로 종료되었음; 마지막 운영시간: %s" -#: access/transam/xlog.c:5116 +#: access/transam/xlog.c:5487 #, c-format msgid "control file contains invalid database cluster state" msgstr "컨트롤 파일에 잘못된 데이터베이스 클러스터 상태값이 있습니다" -#: access/transam/xlog.c:5500 +#: access/transam/xlog.c:5875 #, c-format msgid "WAL ends before end of online backup" msgstr "온라인 백업 작업 끝나기전에 WAL 작업 종료됨" -#: access/transam/xlog.c:5501 +#: access/transam/xlog.c:5876 #, c-format msgid "" "All WAL generated while online backup was taken must be available at " @@ -2797,39 +3035,39 @@ msgstr "" "온라인 백업 중 만들어진 WAL 조각 파일은 복구 작업에서 반드시 모두 있어야 합니" "다." -#: access/transam/xlog.c:5504 +#: access/transam/xlog.c:5880 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL이 일치하는 복구 지점 앞에서 종료됨" -#: access/transam/xlog.c:5550 +#: access/transam/xlog.c:5926 #, c-format msgid "selected new timeline ID: %u" msgstr "지정한 새 타임라인 ID: %u" -#: access/transam/xlog.c:5583 +#: access/transam/xlog.c:5959 #, c-format msgid "archive recovery complete" msgstr "아카이브 복구 완료" -#: access/transam/xlog.c:6189 +#: access/transam/xlog.c:6612 #, c-format msgid "shutting down" msgstr "서비스를 멈추고 있습니다" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6228 +#: access/transam/xlog.c:6651 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "restartpoint 시작:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6240 +#: access/transam/xlog.c:6663 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "체크포인트 시작:%s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6305 +#: access/transam/xlog.c:6728 #, c-format msgid "" "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d " @@ -2842,7 +3080,7 @@ msgstr "" "%03d s; 동기화 파일 개수: %d, 최장시간: %ld.%03d s, 평균시간: %ld.%03d s; 실" "제작업량: %d kB, 예상한작업량: %d kB; lsn=%X/%X, redo lsn=%X/%X" -#: access/transam/xlog.c:6328 +#: access/transam/xlog.c:6751 #, c-format msgid "" "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d " @@ -2855,109 +3093,117 @@ msgstr "" "%03d s; 동기화 파일 개수: %d, 최장시간: %ld.%03d s, 평균시간: %ld.%03d s; 실" "제작업량: %d kB, 예상한작업량: %d kB; lsn=%X/%X, redo lsn=%X/%X" -#: access/transam/xlog.c:6766 +#: access/transam/xlog.c:7233 #, c-format msgid "" "concurrent write-ahead log activity while database system is shutting down" msgstr "데이터베이스 시스템이 중지되는 동안 동시 트랜잭션 로그가 활성화 되었음" -#: access/transam/xlog.c:7327 +#: access/transam/xlog.c:7818 #, c-format msgid "recovery restart point at %X/%X" msgstr "%X/%X에서 복구 작업 시작함" -#: access/transam/xlog.c:7329 +#: access/transam/xlog.c:7820 #, c-format msgid "Last completed transaction was at log time %s." msgstr "마지막 완료된 트랜잭션 기록 시간은 %s 입니다." -#: access/transam/xlog.c:7577 +#: access/transam/xlog.c:8082 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "\"%s\" 이름의 복구 위치는 %X/%X에 만들었음" -#: access/transam/xlog.c:7784 +#: access/transam/xlog.c:8289 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "온라인 백어이 취소되었음, 복구를 계속 할 수 없음" -#: access/transam/xlog.c:7841 +#: access/transam/xlog.c:8347 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "셧다운 체크포인트 레코드에 잘못된 타임라인 ID 값: %u (기대값: %u)" -#: access/transam/xlog.c:7899 +#: access/transam/xlog.c:8405 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "온라인 체크포인트 레코드에 잘못된 타임라인 ID 값: %u (기대값: %u)" -#: access/transam/xlog.c:7928 +#: access/transam/xlog.c:8434 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" -msgstr "복원끝 레코드에 잘못된 타임라인 ID 값: %u (기대값: %u)" +msgstr "복구끝 레코드에 잘못된 타임라인 ID 값: %u (기대값: %u)" -#: access/transam/xlog.c:8195 +#: access/transam/xlog.c:8705 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "\"%s\" write-through 파일을 fsync할 수 없음: %m" -#: access/transam/xlog.c:8200 +#: access/transam/xlog.c:8710 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "\"%s\" 파일 fdatasync 실패: %m" -#: access/transam/xlog.c:8285 access/transam/xlog.c:8608 +#: access/transam/xlog.c:8797 access/transam/xlog.c:9133 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "온라인 백업 작업을 하기 위한 WAL 수준이 충분치 않습니다." -#: access/transam/xlog.c:8286 access/transam/xlog.c:8609 -#: access/transam/xlogfuncs.c:254 +#: access/transam/xlog.c:8798 access/transam/xlogfuncs.c:248 #, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgid "" +"\"wal_level\" must be set to \"replica\" or \"logical\" at server start." msgstr "" -"wal_level 값을 \"replica\" 또는 \"logical\"로 지정하고 서버를 실행하십시오." +"\"wal_level\" 값을 \"replica\" 또는 \"logical\"로 지정하고 서버를 실행하십시" +"오." -#: access/transam/xlog.c:8291 +#: access/transam/xlog.c:8803 #, c-format msgid "backup label too long (max %d bytes)" msgstr "백업 라벨 이름이 너무 긺(최대 %d 바이트)" -#: access/transam/xlog.c:8412 +#: access/transam/xlog.c:8924 #, c-format msgid "" -"WAL generated with full_page_writes=off was replayed since last restartpoint" +"WAL generated with \"full_page_writes=off\" was replayed since last " +"restartpoint" msgstr "" -"마지막 재시작 위치부터 재반영된 WAL 내용이 full_page_writes=off 설정으로 만들" -"어진 내용입니다." +"마지막 재시작 위치부터 재반영된 WAL 내용이 \"full_page_writes=off\" 설정으로 " +"만들어진 내용입니다." -#: access/transam/xlog.c:8414 access/transam/xlog.c:8697 +#: access/transam/xlog.c:8926 access/transam/xlog.c:9222 #, c-format msgid "" "This means that the backup being taken on the standby is corrupt and should " -"not be used. Enable full_page_writes and run CHECKPOINT on the primary, and " -"then try an online backup again." +"not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, " +"and then try an online backup again." msgstr "" "이런 경우는 대기 서버용으로 쓸 백업이 손상되어 사용할 수 없습니다. " -"full_page_writes 설정을 활성화 하고, 주 서버에서 CHECKPOINT 명령을 실행하고, " -"온라인 백업을 다시 해서 사용하세요." +"\"full_page_writes\" 설정을 활성화 하고, 주 서버에서 CHECKPOINT 명령을 실행하" +"고, 온라인 백업을 다시 해서 사용하세요." -#: access/transam/xlog.c:8481 backup/basebackup.c:1351 utils/adt/misc.c:354 +#: access/transam/xlog.c:9006 backup/basebackup.c:1417 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m" -#: access/transam/xlog.c:8488 backup/basebackup.c:1356 utils/adt/misc.c:359 +#: access/transam/xlog.c:9013 backup/basebackup.c:1422 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "\"%s\" 심볼릭 링크의 대상이 너무 긺" -#: access/transam/xlog.c:8647 backup/basebackup.c:1217 +#: access/transam/xlog.c:9134 +#, c-format +msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgstr "" +"wal_level 값을 \"replica\" 또는 \"logical\"로 지정하고 서버를 실행하십시오." + +#: access/transam/xlog.c:9172 backup/basebackup.c:1281 #, c-format msgid "the standby was promoted during online backup" msgstr "대기 서버가 온라인 백업 중 주 서버로 전환되었습니다" -#: access/transam/xlog.c:8648 backup/basebackup.c:1218 +#: access/transam/xlog.c:9173 backup/basebackup.c:1282 #, c-format msgid "" "This means that the backup being taken is corrupt and should not be used. " @@ -2966,22 +3212,22 @@ msgstr "" "이런 경우, 해당 백업 자료가 손상되었을 가능성이 있습니다. 다른 백업본을 이용" "하세요." -#: access/transam/xlog.c:8695 +#: access/transam/xlog.c:9220 #, c-format msgid "" -"WAL generated with full_page_writes=off was replayed during online backup" +"WAL generated with \"full_page_writes=off\" was replayed during online backup" msgstr "" -"온라인 백업 도중 full_page_writes=off 설정으로 만들어진 WAL 내용이 재반영되었" -"습니다." +"온라인 백업 도중 \"full_page_writes=off\" 설정으로 만들어진 WAL 내용이 재반영" +"되었습니다." -#: access/transam/xlog.c:8811 +#: access/transam/xlog.c:9336 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "" "베이스 백업이 끝났습니다. 필요한 WAL 조각 파일이 아카이브 되길 기다리고 있습" "니다." -#: access/transam/xlog.c:8825 +#: access/transam/xlog.c:9350 #, c-format msgid "" "still waiting for all required WAL segments to be archived (%d seconds " @@ -2989,22 +3235,22 @@ msgid "" msgstr "" "필요한 WAL 조각 파일 아카이빙이 완료되기를 계속 기다리고 있음 (%d초 경과)" -#: access/transam/xlog.c:8827 +#: access/transam/xlog.c:9352 #, c-format msgid "" -"Check that your archive_command is executing properly. You can safely " +"Check that your \"archive_command\" is executing properly. You can safely " "cancel this backup, but the database backup will not be usable without all " "the WAL segments." msgstr "" -"archive_command 설정을 살펴보세요. 이 백업 작업은 안전하게 취소 할 수 있지" -"만, 데이터베이스 백업은 모든 WAL 조각 없이는 사용될 수 없습니다." +"\"archive_command\" 설정을 살펴보세요. 이 백업 작업은 안전하게 취소 할 수 있" +"지만, 데이터베이스 백업은 모든 WAL 조각 없이는 사용될 수 없습니다." -#: access/transam/xlog.c:8834 +#: access/transam/xlog.c:9359 #, c-format msgid "all required WAL segments have been archived" msgstr "모든 필요한 WAL 조각들이 아카이브 되었습니다." -#: access/transam/xlog.c:8838 +#: access/transam/xlog.c:9363 #, c-format msgid "" "WAL archiving is not enabled; you must ensure that all required WAL segments " @@ -3014,28 +3260,28 @@ msgstr "" "모든 WAL 조각 파일들을 직접 찾아서 따로 보관해 두어야 바르게 복구 할 수 있습" "니다." -#: access/transam/xlog.c:8877 +#: access/transam/xlog.c:9402 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "" "pg_backup_stop 작업이 호출되기 전에 백엔드가 종료되어 백업을 중지합니다." -#: access/transam/xlogarchive.c:207 +#: access/transam/xlogarchive.c:213 #, c-format msgid "archive file \"%s\" has wrong size: %lld instead of %lld" msgstr "\"%s\" 아카이브 파일의 크기가 이상합니다: 현재값 %lld, 기대값 %lld" -#: access/transam/xlogarchive.c:216 +#: access/transam/xlogarchive.c:222 #, c-format msgid "restored log file \"%s\" from archive" msgstr "아카이브에서 \"%s\" 로그파일을 복구했음" -#: access/transam/xlogarchive.c:230 +#: access/transam/xlogarchive.c:236 #, c-format -msgid "restore_command returned a zero exit status, but stat() failed." -msgstr "restore_command 작업이 0을 반환했지만, stat() 작업 실패." +msgid "\"restore_command\" returned a zero exit status, but stat() failed." +msgstr "\"restore_command\" 작업이 0을 반환했지만, stat() 작업 실패." -#: access/transam/xlogarchive.c:262 +#: access/transam/xlogarchive.c:268 #, c-format msgid "could not restore file \"%s\" from archive: %s" msgstr "아카이브에서 \"%s\" 파일 복원 실패: %s" @@ -3043,180 +3289,182 @@ msgstr "아카이브에서 \"%s\" 파일 복원 실패: %s" #. translator: First %s represents a postgresql.conf parameter name like #. "recovery_end_command", the 2nd is the value of that parameter, the #. third an already translated error message. -#: access/transam/xlogarchive.c:340 +#: access/transam/xlogarchive.c:346 #, c-format msgid "%s \"%s\": %s" msgstr "%s \"%s\": %s" -#: access/transam/xlogarchive.c:450 access/transam/xlogarchive.c:530 +#: access/transam/xlogarchive.c:456 access/transam/xlogarchive.c:536 #, c-format msgid "could not create archive status file \"%s\": %m" msgstr "\"%s\" archive status 파일을 만들 수 없습니다: %m" -#: access/transam/xlogarchive.c:458 access/transam/xlogarchive.c:538 +#: access/transam/xlogarchive.c:464 access/transam/xlogarchive.c:544 #, c-format msgid "could not write archive status file \"%s\": %m" msgstr "\"%s\" archive status 파일에 쓸 수 없습니다: %m" -#: access/transam/xlogfuncs.c:75 backup/basebackup.c:973 +#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 #, c-format msgid "a backup is already in progress in this session" msgstr "이미 이 세션에서 백업 작업이 진행 중입니다" -#: access/transam/xlogfuncs.c:146 +#: access/transam/xlogfuncs.c:140 #, c-format msgid "backup is not in progress" msgstr "현재 백업 작업을 하지 않고 있습니다" -#: access/transam/xlogfuncs.c:147 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "Did you call pg_backup_start()?" msgstr "pg_backup_start() 함수를 호출했나요?" -#: access/transam/xlogfuncs.c:190 access/transam/xlogfuncs.c:248 -#: access/transam/xlogfuncs.c:287 access/transam/xlogfuncs.c:308 -#: access/transam/xlogfuncs.c:329 +#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 +#: access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 +#: access/transam/xlogfuncs.c:323 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "WAL 제어 함수는 복구 작업 중에는 실행 될 수 없음" -#: access/transam/xlogfuncs.c:215 access/transam/xlogfuncs.c:399 -#: access/transam/xlogfuncs.c:457 +#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 +#: access/transam/xlogfuncs.c:447 #, c-format msgid "%s cannot be executed during recovery." msgstr "복구 작업 중에는 %s 명령을 실행할 수 없습니다." -#: access/transam/xlogfuncs.c:221 +#: access/transam/xlogfuncs.c:215 #, c-format -msgid "pg_log_standby_snapshot() can only be used if wal_level >= replica" +msgid "" +"pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" msgstr "" -"pg_log_standby_snapshot() 함수는 wal_level >= replica 상태에서 사용될 수 있습" -"니다." +"pg_log_standby_snapshot() 함수는 \"wal_level\" >= \"replica\" 상태에서 사용" +"될 수 있습니다." -#: access/transam/xlogfuncs.c:253 +#: access/transam/xlogfuncs.c:247 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "WAL 수준이 복원 위치를 만들 수 없는 수준입니다" -#: access/transam/xlogfuncs.c:261 +#: access/transam/xlogfuncs.c:255 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "복원 위치 이름이 너무 깁니다. (최대값, %d 글자)" -#: access/transam/xlogfuncs.c:496 +#: access/transam/xlogfuncs.c:486 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "잘못된 WAL 파일 이름: \"%s\"" -#: access/transam/xlogfuncs.c:532 access/transam/xlogfuncs.c:562 -#: access/transam/xlogfuncs.c:586 access/transam/xlogfuncs.c:609 -#: access/transam/xlogfuncs.c:689 +#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 +#: access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 +#: access/transam/xlogfuncs.c:679 #, c-format msgid "recovery is not in progress" msgstr "현재 복구 작업 상태가 아닙니다" -#: access/transam/xlogfuncs.c:533 access/transam/xlogfuncs.c:563 -#: access/transam/xlogfuncs.c:587 access/transam/xlogfuncs.c:610 -#: access/transam/xlogfuncs.c:690 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 +#: access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 +#: access/transam/xlogfuncs.c:680 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "복구 제어 함수는 복구 작업일 때만 실행할 수 있습니다." -#: access/transam/xlogfuncs.c:538 access/transam/xlogfuncs.c:568 +#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 #, c-format msgid "standby promotion is ongoing" msgstr "대기 서버가 운영 서버로 전환 중입니다." -#: access/transam/xlogfuncs.c:539 access/transam/xlogfuncs.c:569 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%s 함수는 운영 전환 중에는 실행될 수 없음." -#: access/transam/xlogfuncs.c:695 +#: access/transam/xlogfuncs.c:685 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "\"wait_seconds\" 값은 음수나 0을 사용할 수 없음" -#: access/transam/xlogfuncs.c:715 storage/ipc/signalfuncs.c:260 +#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "postmaster로 시그널 보내기 실패: %m" -#: access/transam/xlogfuncs.c:751 +#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#, c-format +msgid "terminating connection due to unexpected postmaster exit" +msgstr "postmaster의 예상치 못한 종료로 연결을 종료합니다" + +#: access/transam/xlogfuncs.c:740 +#, c-format +msgid "while waiting on promotion" +msgstr "주 서버로 전환하는 것을 기다리는 중" + +#: access/transam/xlogfuncs.c:744 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" msgstr[0] "%d 초 이내에 운영 전환을 하지 못했습니다." -#: access/transam/xlogprefetcher.c:1092 +#: access/transam/xlogprefetcher.c:1088 #, c-format msgid "" -"recovery_prefetch is not supported on platforms that lack posix_fadvise()." +"\"recovery_prefetch\" is not supported on platforms that lack " +"posix_fadvise()." msgstr "" -"이 OS는 posix_fadvise() 함수를 지원하지 않아, recovery_prefetch 설정을 지원하" -"지 않습니다." +"이 OS는 posix_fadvise() 함수를 지원하지 않아, \"recovery_prefetch\" 설정을 지" +"원하지 않습니다." -#: access/transam/xlogreader.c:626 +#: access/transam/xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 오프셋: 위치 %X/%X, 기대값 %u, 실재값 %u" -#: access/transam/xlogreader.c:635 +#: access/transam/xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "%X/%X에서 contrecord를 필요로 함" -#: access/transam/xlogreader.c:676 access/transam/xlogreader.c:1119 +#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 길이: 위치 %X/%X, 기대값 %u, 실재값 %u" -#: access/transam/xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "%u 길이의 레코드를 디코딩하는 중 메모리 부족" - -#: access/transam/xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음" - -#: access/transam/xlogreader.c:776 +#: access/transam/xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "%X/%X 위치에 contrecord 플래그가 없음" -#: access/transam/xlogreader.c:789 +#: access/transam/xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "잘못된 contrecord 길이 %u (기대값: %lld), 위치 %X/%X" -#: access/transam/xlogreader.c:1127 +#: access/transam/xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "잘못된 자원 관리 ID %u, 위치: %X/%X" -#: access/transam/xlogreader.c:1140 access/transam/xlogreader.c:1156 +#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "레코드의 잘못된 프리링크 %X/%X, 해당 레코드 %X/%X" -#: access/transam/xlogreader.c:1192 +#: access/transam/xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "잘못된 자원관리자 데이터 체크섬, 위치: %X/%X 레코드" -#: access/transam/xlogreader.c:1226 +#: access/transam/xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "%04X 매직 번호가 잘못됨, WAL 조각 파일 %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1241 access/transam/xlogreader.c:1283 +#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 정보 비트 %04X, WAL 조각 파일 %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1257 +#: access/transam/xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -3225,7 +3473,7 @@ msgstr "" "WAL 파일이 다른 시스템의 것입니다. WAL 파일의 시스템 식별자는 %llu, " "pg_control 의 식별자는 %llu" -#: access/transam/xlogreader.c:1265 +#: access/transam/xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -3234,7 +3482,7 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더에 지정된 값이 잘" "못된 조각 크기임" -#: access/transam/xlogreader.c:1271 +#: access/transam/xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -3243,12 +3491,12 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_BLCKSZ 값" "이 바르지 않음" -#: access/transam/xlogreader.c:1303 +#: access/transam/xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 페이지 주소 %X/%X, WAL 조각 파일 %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1329 +#: access/transam/xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -3257,22 +3505,22 @@ msgstr "" "타임라인 범위 벗어남 %u (이전 번호 %u), WAL 조각 파일 %s, LSN %X/%X, offset " "%u" -#: access/transam/xlogreader.c:1735 +#: access/transam/xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "%u block_id는 범위를 벗어남, 위치 %X/%X" -#: access/transam/xlogreader.c:1759 +#: access/transam/xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정했지만, %X/%X 에 자료가 없음" -#: access/transam/xlogreader.c:1766 +#: access/transam/xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정 않았지만, %u 길이의 자료가 있음, 위치 %X/%X" -#: access/transam/xlogreader.c:1802 +#: access/transam/xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -3281,19 +3529,19 @@ msgstr "" "BKPIMAGE_HAS_HOLE 설정이 되어 있지만, 옵셋: %u, 길이: %u, 블록 이미지 길이: " "%u, 대상: %X/%X" -#: access/transam/xlogreader.c:1818 +#: access/transam/xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE 설정이 안되어 있지만, 옵셋: %u, 길이: %u, 대상: %X/%X" -#: access/transam/xlogreader.c:1832 +#: access/transam/xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED 설정이 되어 있지만, 블록 이미지 길이: %u, 대상: %X/%X" -#: access/transam/xlogreader.c:1847 +#: access/transam/xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -3302,147 +3550,160 @@ msgstr "" "BKPIMAGE_HAS_HOLE, BKPIMAGE_COMPRESSED 지정 안되어 있으나, 블록 이미지 길이" "는 %u, 대상: %X/%X" -#: access/transam/xlogreader.c:1863 +#: access/transam/xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL 설정이 되어 있지만, %X/%X 에 이전 릴레이션 없음" -#: access/transam/xlogreader.c:1875 +#: access/transam/xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "잘못된 block_id %u, 위치 %X/%X" -#: access/transam/xlogreader.c:1942 +#: access/transam/xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "잘못된 레코드 길이, 위치 %X/%X" -#: access/transam/xlogreader.c:1968 +#: access/transam/xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "WAL 레코드에서 %d ID의 백업 블록을 찾을 수 없음" -#: access/transam/xlogreader.c:2052 +#: access/transam/xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "%X/%X 위치에 이미지를 복원할 수 없음 %d 블록이 잘못 지정됨" -#: access/transam/xlogreader.c:2059 +#: access/transam/xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "%X/%X 위치에 이미지를 복원할 수 없음, %d 블록의 상태가 이상함" -#: access/transam/xlogreader.c:2086 access/transam/xlogreader.c:2103 +#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " "block %d" msgstr "%X/%X 위치에 압축된 이미지 복원 실패, %s 지원 하지 않음, 해당 블록: %d" -#: access/transam/xlogreader.c:2112 +#: access/transam/xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "알 수 없는 방법으로 이미지 압축 복원 실패: 위치 %X/%X, 블록 %d" -#: access/transam/xlogreader.c:2120 +#: access/transam/xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "이미지 압축 풀기 실패, 위치 %X/%X, 블록 %d" -#: access/transam/xlogrecovery.c:547 -#, c-format -msgid "entering standby mode" -msgstr "대기 모드로 전환합니다" - -#: access/transam/xlogrecovery.c:550 -#, c-format -msgid "starting point-in-time recovery to XID %u" -msgstr "%u XID까지 시점 기반 복구 작업을 시작합니다" - -#: access/transam/xlogrecovery.c:554 -#, c-format -msgid "starting point-in-time recovery to %s" -msgstr "%s 까지 시점 복구 작업을 시작합니다" - -#: access/transam/xlogrecovery.c:558 -#, c-format -msgid "starting point-in-time recovery to \"%s\"" -msgstr "\"%s\" 복구 대상 이름까지 시점 복구 작업을 시작합니다" - -#: access/transam/xlogrecovery.c:562 -#, c-format -msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" -msgstr "\"%X/%X\" 위치(LSN)까지 시점 복구 작업을 시작합니다" - -#: access/transam/xlogrecovery.c:566 -#, c-format -msgid "starting point-in-time recovery to earliest consistent point" -msgstr "동기화 할 수 있는 마지막 지점까지 시점 복구 작업을 시작합니다" - -#: access/transam/xlogrecovery.c:569 +#: access/transam/xlogrecovery.c:617 #, c-format -msgid "starting archive recovery" -msgstr "아카이브 복구 작업을 시작합니다" +msgid "" +"starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on " +"timeline ID %u" +msgstr "백업 복구 시작: 리두LSN=%X/%X, 체크포인트LSN=%X/%X, 타임라인ID=%u" -#: access/transam/xlogrecovery.c:653 +#: access/transam/xlogrecovery.c:649 #, c-format -msgid "could not find redo location referenced by checkpoint record" -msgstr "체크포인트 기록으로 참조하는 재실행 위치를 찾을 수 없음" +msgid "" +"could not find redo location %X/%X referenced by checkpoint record at %X/%X" +msgstr "%X/%X 위치의 redo lsn을 찾을 수 없음: 참조하는 체크포인트 레코드=%X/%X" -#: access/transam/xlogrecovery.c:654 access/transam/xlogrecovery.c:664 +#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 #, c-format msgid "" -"If you are restoring from a backup, touch \"%s/recovery.signal\" and add " -"required recovery options.\n" +"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/" +"standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/" "backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if " "restoring from a backup." msgstr "" -"백업을 복원하려면, \"%s/recovery.signal\" 파일을 만들고, 복구 관련 옵션을 지" -"정하세요.\n" +"백업을 복원하려면, \"%s/recovery.signal\" 또는 \"%s/standby.signal\" 파일을 " +"만들고, 복구 관련 옵션을 지정하세요.\n" "백업 복원을 하는게 아니라면, \"%s/backup_label\" 파일을 지우고 사용할 수 있" "습니다.\n" "주의: 백업 복원 작업을 하는데, \"%s/backup_label\" 파일을 지운다면, 클러스터" "가 손상 될 수 있습니다." -#: access/transam/xlogrecovery.c:663 +#: access/transam/xlogrecovery.c:660 #, c-format -msgid "could not locate required checkpoint record" -msgstr "요청된 체크포인트 레코드의 위치를 바르게 잡을 수 없음" +msgid "could not locate required checkpoint record at %X/%X" +msgstr "요청된 체크포인트 레코드의 위치(%X/%X)를 잡을 수 없음" -#: access/transam/xlogrecovery.c:692 commands/tablespace.c:670 +#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "\"%s\" 심벌릭 링크를 만들 수 없음: %m" -#: access/transam/xlogrecovery.c:724 access/transam/xlogrecovery.c:730 +#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "\"%s\" 파일 무시함, \"%s\" 파일 없음" -#: access/transam/xlogrecovery.c:726 +#: access/transam/xlogrecovery.c:725 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿨습니다." -#: access/transam/xlogrecovery.c:732 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" -#: access/transam/xlogrecovery.c:786 +#: access/transam/xlogrecovery.c:770 +#, c-format +msgid "restarting backup recovery with redo LSN %X/%X" +msgstr "\"%X/%X\" redo LSN에서 백업 복구 작업을 다시 시작합니다" + +#: access/transam/xlogrecovery.c:795 +#, c-format +msgid "could not locate a valid checkpoint record at %X/%X" +msgstr "%X/%X에서 바른 체크포인트 레코드를 잡을 수 없음" + +#: access/transam/xlogrecovery.c:806 +#, c-format +msgid "entering standby mode" +msgstr "대기 모드로 전환합니다" + +#: access/transam/xlogrecovery.c:809 +#, c-format +msgid "starting point-in-time recovery to XID %u" +msgstr "%u XID까지 시점 기반 복구 작업을 시작합니다" + +#: access/transam/xlogrecovery.c:813 +#, c-format +msgid "starting point-in-time recovery to %s" +msgstr "%s 까지 시점 복구 작업을 시작합니다" + +#: access/transam/xlogrecovery.c:817 +#, c-format +msgid "starting point-in-time recovery to \"%s\"" +msgstr "\"%s\" 복구 대상 이름까지 시점 복구 작업을 시작합니다" + +#: access/transam/xlogrecovery.c:821 +#, c-format +msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" +msgstr "\"%X/%X\" 위치(LSN)까지 시점 복구 작업을 시작합니다" + +#: access/transam/xlogrecovery.c:825 +#, c-format +msgid "starting point-in-time recovery to earliest consistent point" +msgstr "동기화 할 수 있는 마지막 지점까지 시점 복구 작업을 시작합니다" + +#: access/transam/xlogrecovery.c:828 #, c-format -msgid "could not locate a valid checkpoint record" -msgstr "체크포인트 레코드의 위치를 바르게 잡을 수 없음" +msgid "starting archive recovery" +msgstr "아카이브 복구 작업을 시작합니다" -#: access/transam/xlogrecovery.c:810 +#: access/transam/xlogrecovery.c:849 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "요청한 %u 타임라인은 서버 타임라인의 하위가 아님" -#: access/transam/xlogrecovery.c:812 +#: access/transam/xlogrecovery.c:851 #, c-format msgid "" "Latest checkpoint is at %X/%X on timeline %u, but in the history of the " @@ -3451,7 +3712,7 @@ msgstr "" "마지막 체크포인트 위치는 %X/%X (%u 타임라인)입니다. 하지만, 요청받은 타임라" "인 내역파일에는 그 타임라인 %X/%X 위치에서 분기되었습니다." -#: access/transam/xlogrecovery.c:826 +#: access/transam/xlogrecovery.c:865 #, c-format msgid "" "requested timeline %u does not contain minimum recovery point %X/%X on " @@ -3459,22 +3720,22 @@ msgid "" msgstr "" "요청한 %u 타임라인은 %X/%X 최소 복구 위치가 없습니다, 기존 타임라인: %u" -#: access/transam/xlogrecovery.c:854 +#: access/transam/xlogrecovery.c:893 #, c-format msgid "invalid next transaction ID" msgstr "잘못된 다음 트랜잭션 ID" -#: access/transam/xlogrecovery.c:859 +#: access/transam/xlogrecovery.c:898 #, c-format msgid "invalid redo in checkpoint record" msgstr "체크포인트 레코드 안에 잘못된 redo 정보가 있음" -#: access/transam/xlogrecovery.c:870 +#: access/transam/xlogrecovery.c:909 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "운영 중지 체크포인트에서 잘못된 재실행 정보 발견" -#: access/transam/xlogrecovery.c:899 +#: access/transam/xlogrecovery.c:938 #, c-format msgid "" "database system was not properly shut down; automatic recovery in progress" @@ -3482,18 +3743,18 @@ msgstr "" "데이터베이스 시스템이 정상적으로 종료되지 못했습니다, 자동 복구 작업을 진행합" "니다" -#: access/transam/xlogrecovery.c:903 +#: access/transam/xlogrecovery.c:942 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "" "%u 타임라인으로 비정상 중지에 대한 복구작업을 시작함, 기존 타임라인: %u" -#: access/transam/xlogrecovery.c:946 +#: access/transam/xlogrecovery.c:985 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label 파일 안에 컨트롤 파일과 일관성이 맞지 않는 자료가 있음" -#: access/transam/xlogrecovery.c:947 +#: access/transam/xlogrecovery.c:986 #, c-format msgid "" "This means that the backup is corrupted and you will have to use another " @@ -3502,22 +3763,22 @@ msgstr "" "이 문제는 백업 자료 자체가 손상 되었음을 말합니다. 다른 백업본으로 복구 작업" "을 진행해야 합니다." -#: access/transam/xlogrecovery.c:1001 +#: access/transam/xlogrecovery.c:1040 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "\"%s\" 복구 명령 파일을 사용하는 것을 지원하지 않습니다" -#: access/transam/xlogrecovery.c:1066 +#: access/transam/xlogrecovery.c:1105 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "단일 사용자 서버를 대상으로 대기 모드를 사용할 수 없습니다." -#: access/transam/xlogrecovery.c:1083 +#: access/transam/xlogrecovery.c:1122 #, c-format -msgid "specified neither primary_conninfo nor restore_command" -msgstr "primary_conninfo 설정도, restore_command 설정도 없음" +msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" +msgstr "\"primary_conninfo\" 설정도, \"restore_command\" 설정도 없음" -#: access/transam/xlogrecovery.c:1084 +#: access/transam/xlogrecovery.c:1123 #, c-format msgid "" "The database server will regularly poll the pg_wal subdirectory to check for " @@ -3526,101 +3787,122 @@ msgstr "" "데이터베이스 서버는 일반적으로 주 서버에서 발생한 트랜잭션 로그를 반영하기 위" "해 pg_wal 하위 디렉터리를 조사할 것입니다." -#: access/transam/xlogrecovery.c:1092 +#: access/transam/xlogrecovery.c:1131 #, c-format -msgid "must specify restore_command when standby mode is not enabled" +msgid "must specify \"restore_command\" when standby mode is not enabled" msgstr "" -"대기 모드를 활성화 하지 않았다면(standby_mode = off), restore_command 설정은 " -"반드시 있어야 함" +"대기 모드를 활성화 하지 않았다면(standby_mode = off), \"restore_command\" 설" +"정은 반드시 있어야 함" -#: access/transam/xlogrecovery.c:1130 +#: access/transam/xlogrecovery.c:1169 #, c-format msgid "recovery target timeline %u does not exist" msgstr "%u 복구 대상 타임라인이 없음" -#: access/transam/xlogrecovery.c:1213 access/transam/xlogrecovery.c:1220 -#: access/transam/xlogrecovery.c:1279 access/transam/xlogrecovery.c:1359 -#: access/transam/xlogrecovery.c:1383 +#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 +#: access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 +#: access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 #, c-format msgid "invalid data in file \"%s\"" msgstr "\"%s\" 파일에 유효하지 않은 자료가 있습니다" -#: access/transam/xlogrecovery.c:1280 +#: access/transam/xlogrecovery.c:1319 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "타임라인 ID가 %u 값으로 분석했지만, 기대값은 %u 임" -#: access/transam/xlogrecovery.c:1662 +#: access/transam/xlogrecovery.c:1330 #, c-format -msgid "redo starts at %X/%X" -msgstr "%X/%X에서 redo 작업 시작됨" +msgid "this is an incremental backup, not a data directory" +msgstr "이것은 증분 백업 디렉터리로 데이터 디렉터리가 아님" -#: access/transam/xlogrecovery.c:1675 +#: access/transam/xlogrecovery.c:1331 #, c-format -msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" +msgid "Use pg_combinebackup to reconstruct a valid data directory." +msgstr "" +"바른 데이터 디렉터리로 재구축하려면 pg_combinebackup 명령을 이용하세요." + +#: access/transam/xlogrecovery.c:1717 +#, c-format +msgid "unexpected record type found at redo point %X/%X" +msgstr "%X/%X redo 위치에 잘못된 레크드 형태가 발견됨" + +#: access/transam/xlogrecovery.c:1740 +#, c-format +msgid "redo starts at %X/%X" +msgstr "%X/%X에서 redo 작업 시작됨" + +#: access/transam/xlogrecovery.c:1753 +#, c-format +msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "redo 진행 중, 예상시간: %ld.%02d s, 현재 LSN: %X/%X" -#: access/transam/xlogrecovery.c:1767 +#: access/transam/xlogrecovery.c:1843 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "요청한 복구 중지 지점이 일치하는 복구 지점 앞에 있음" -#: access/transam/xlogrecovery.c:1799 +#: access/transam/xlogrecovery.c:1875 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "%X/%X에서 redo 작업 완료, 시스템 사용량: %s" -#: access/transam/xlogrecovery.c:1805 +#: access/transam/xlogrecovery.c:1881 #, c-format msgid "last completed transaction was at log time %s" msgstr "마지막 완료된 트랜잭션 기록 시간: %s" -#: access/transam/xlogrecovery.c:1814 +#: access/transam/xlogrecovery.c:1890 #, c-format msgid "redo is not required" msgstr "재반영해야 할 트랜잭션이 없음" -#: access/transam/xlogrecovery.c:1825 +#: access/transam/xlogrecovery.c:1901 #, c-format msgid "recovery ended before configured recovery target was reached" -msgstr "지정한 recovery target 도달 전에 복원 끝남" +msgstr "지정한 recovery target 도달 전에 복구 끝남" -#: access/transam/xlogrecovery.c:2019 +#: access/transam/xlogrecovery.c:2095 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "%X/%X에 빠진 contrecord를 건너뜀, %s에 덮어씀" -#: access/transam/xlogrecovery.c:2086 +#: access/transam/xlogrecovery.c:2162 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "잘못된 디렉터리 엔트리 \"%s\", 위치: %s" -#: access/transam/xlogrecovery.c:2088 +#: access/transam/xlogrecovery.c:2164 #, c-format msgid "All directory entries in pg_tblspc/ should be symbolic links." msgstr "pg_tblspc/ 안 모든 디렉터리 엔트리는 심볼릭 링크여야 함" -#: access/transam/xlogrecovery.c:2089 +#: access/transam/xlogrecovery.c:2165 #, c-format msgid "" -"Remove those directories, or set allow_in_place_tablespaces to ON " +"Remove those directories, or set \"allow_in_place_tablespaces\" to ON " "transiently to let recovery complete." msgstr "" -"그 디렉터리를 지우든가, allow_in_place_tablespaces 설정을 ON으로 바꿔 임시로 " -"복원 작업을 완료하든가 하세요." +"그 디렉터리를 지우든가, \"allow_in_place_tablespaces\" 설정을 ON으로 바꿔 임" +"시로 복구 작업을 완료하든가 하세요." + +#: access/transam/xlogrecovery.c:2217 +#, c-format +msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" +msgstr "redo LSN %X/%X 부터 end LSN %X/%X 까지 백업 복구 완료" -#: access/transam/xlogrecovery.c:2163 +#: access/transam/xlogrecovery.c:2247 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "%X/%X 위치에서 복구 일관성을 맞춤" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2201 +#: access/transam/xlogrecovery.c:2285 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "WAL redo 위치: %X/%X, 대상: %s" -#: access/transam/xlogrecovery.c:2299 +#: access/transam/xlogrecovery.c:2383 #, c-format msgid "" "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint " @@ -3628,12 +3910,12 @@ msgid "" msgstr "" "체크포인트 레코드에 예기치 않은 이전 타임라인ID %u(현재 타임라인ID: %u)" -#: access/transam/xlogrecovery.c:2308 +#: access/transam/xlogrecovery.c:2392 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "체크포인트 레코드에 예기치 않은 타임라인 ID %u이(가) 있음(%u 뒤)" -#: access/transam/xlogrecovery.c:2324 +#: access/transam/xlogrecovery.c:2408 #, c-format msgid "" "unexpected timeline ID %u in checkpoint record, before reaching minimum " @@ -3642,113 +3924,113 @@ msgstr "" "체크포인트 내역 안에 %u 타임라인 ID가 기대한 것과 다릅니다. 발생 위치: %X/%X " "(타임라인: %u) 최소 복구 위치 이전" -#: access/transam/xlogrecovery.c:2508 access/transam/xlogrecovery.c:2784 +#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 #, c-format msgid "recovery stopping after reaching consistency" msgstr "일관성을 다 맞추어 복구 작업을 중지합니다." -#: access/transam/xlogrecovery.c:2529 +#: access/transam/xlogrecovery.c:2613 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "복구 중지 위치(LSN): \"%X/%X\" 이전" -#: access/transam/xlogrecovery.c:2619 +#: access/transam/xlogrecovery.c:2703 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "%u 트랜잭션 커밋 전 복구 중지함, 시간 %s" -#: access/transam/xlogrecovery.c:2626 +#: access/transam/xlogrecovery.c:2710 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "%u 트랜잭션 중단 전 복구 중지함, 시간 %s" -#: access/transam/xlogrecovery.c:2679 +#: access/transam/xlogrecovery.c:2763 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "복구 중지함, 복구 위치 \"%s\", 시간 %s" -#: access/transam/xlogrecovery.c:2697 +#: access/transam/xlogrecovery.c:2781 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "복구 중지 위치(LSN): \"%X/%X\" 이후" -#: access/transam/xlogrecovery.c:2764 +#: access/transam/xlogrecovery.c:2848 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "%u 트랜잭션 커밋 후 복구 중지함, 시간 %s" -#: access/transam/xlogrecovery.c:2772 +#: access/transam/xlogrecovery.c:2856 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "%u 트랜잭션 중단 후 복구 중지함, 시간 %s" -#: access/transam/xlogrecovery.c:2853 +#: access/transam/xlogrecovery.c:2937 #, c-format msgid "pausing at the end of recovery" msgstr "복구 끝에 기다리는 중" -#: access/transam/xlogrecovery.c:2854 +#: access/transam/xlogrecovery.c:2938 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "운영 서버로 바꾸려면, pg_wal_replay_resume() 함수를 호출하세요." -#: access/transam/xlogrecovery.c:2857 access/transam/xlogrecovery.c:4594 +#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4678 #, c-format msgid "recovery has paused" msgstr "복구 작업이 일시 중지 됨" -#: access/transam/xlogrecovery.c:2858 +#: access/transam/xlogrecovery.c:2942 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "계속 진행하려면, pg_wal_replay_resume() 함수를 호출하세요." -#: access/transam/xlogrecovery.c:3121 +#: access/transam/xlogrecovery.c:3205 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "예상치 못한 타임라인 ID %u, WAL 조각 파일: %s, LSN %X/%X, offset %u" -#: access/transam/xlogrecovery.c:3329 +#: access/transam/xlogrecovery.c:3413 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "%s WAL 조각에서 읽기 실패, LSN %X/%X, offset %u: %m" -#: access/transam/xlogrecovery.c:3336 +#: access/transam/xlogrecovery.c:3420 #, c-format msgid "" "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" msgstr "%s WAL 조각에서 읽기 실패, LSN %X/%X, offset %u: read %d / %zu" -#: access/transam/xlogrecovery.c:3976 +#: access/transam/xlogrecovery.c:4060 #, c-format msgid "invalid checkpoint location" msgstr "잘못된 checkpoint 위치" -#: access/transam/xlogrecovery.c:3986 +#: access/transam/xlogrecovery.c:4070 #, c-format msgid "invalid checkpoint record" msgstr "잘못된 checkpoint 레코드" -#: access/transam/xlogrecovery.c:3992 +#: access/transam/xlogrecovery.c:4076 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "checkpoint 레코드에서 잘못된 자원 관리자 ID 발견" -#: access/transam/xlogrecovery.c:4000 +#: access/transam/xlogrecovery.c:4084 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "checkpoint 레코드에서 잘못된 xl_info 발견" -#: access/transam/xlogrecovery.c:4006 +#: access/transam/xlogrecovery.c:4090 #, c-format msgid "invalid length of checkpoint record" msgstr "checkpoint 레코드 길이가 잘못되었음" -#: access/transam/xlogrecovery.c:4060 +#: access/transam/xlogrecovery.c:4144 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "요청한 %u 타임라인은 %u 데이터베이스 시스템 타임라인의 하위가 아님" -#: access/transam/xlogrecovery.c:4074 +#: access/transam/xlogrecovery.c:4158 #, c-format msgid "" "new timeline %u forked off current database system timeline %u before " @@ -3757,28 +4039,28 @@ msgstr "" "복구 위치까지 복구하기 전에 새 타임라인 %u번으로 분기됨, 기존 데이터베이스 타" "임라인: %u, 기대한 복구 위치 %X/%X" -#: access/transam/xlogrecovery.c:4093 +#: access/transam/xlogrecovery.c:4177 #, c-format msgid "new target timeline is %u" msgstr "새 대상 타임라인: %u" -#: access/transam/xlogrecovery.c:4296 +#: access/transam/xlogrecovery.c:4380 #, c-format msgid "WAL receiver process shutdown requested" msgstr "WAL receiver 프로세스가 중지 요청을 받았습니다." -#: access/transam/xlogrecovery.c:4356 +#: access/transam/xlogrecovery.c:4440 #, c-format msgid "received promote request" msgstr "운영 전환 신호를 받았습니다." -#: access/transam/xlogrecovery.c:4585 +#: access/transam/xlogrecovery.c:4669 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "불충분한 서버 설정으로 hot standby 서버를 운영할 수 없음" -#: access/transam/xlogrecovery.c:4586 access/transam/xlogrecovery.c:4613 -#: access/transam/xlogrecovery.c:4643 +#: access/transam/xlogrecovery.c:4670 access/transam/xlogrecovery.c:4697 +#: access/transam/xlogrecovery.c:4727 #, c-format msgid "" "%s = %d is a lower setting than on the primary server, where its value was " @@ -3787,238 +4069,240 @@ msgstr "" "이 서버의 현재 %s = %d 설정은 주 서버의 설정값(%d)보다 낮게 설정 되어 있기 때" "문입니다." -#: access/transam/xlogrecovery.c:4595 +#: access/transam/xlogrecovery.c:4679 #, c-format msgid "If recovery is unpaused, the server will shut down." -msgstr "복원 후 멈춰 있을 수 없으면 서버는 종료될 것입니다." +msgstr "복구 후 멈춰 있을 수 없으면 서버는 종료될 것입니다." -#: access/transam/xlogrecovery.c:4596 +#: access/transam/xlogrecovery.c:4680 #, c-format msgid "" "You can then restart the server after making the necessary configuration " "changes." msgstr "환경 설정을 바꾸어 서버를 다시 시작할 수 있습니다." -#: access/transam/xlogrecovery.c:4607 +#: access/transam/xlogrecovery.c:4691 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "운영 서버로 전환할 수 없습니다. 설정이 불충분합니다." -#: access/transam/xlogrecovery.c:4617 +#: access/transam/xlogrecovery.c:4701 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "필요한 설정을 바꾸어 서버를 다시 시작하세요." -#: access/transam/xlogrecovery.c:4641 +#: access/transam/xlogrecovery.c:4725 #, c-format msgid "recovery aborted because of insufficient parameter settings" -msgstr "복원 작업이 불충분한 설정으로 중지 되었습니다." +msgstr "복구 작업이 불충분한 설정으로 중지 되었습니다." -#: access/transam/xlogrecovery.c:4647 +#: access/transam/xlogrecovery.c:4731 #, c-format msgid "" "You can restart the server after making the necessary configuration changes." msgstr "필요한 설정을 바꾸어 서버를 다시 시작할 수 있습니다." -#: access/transam/xlogrecovery.c:4689 +#: access/transam/xlogrecovery.c:4773 #, c-format msgid "multiple recovery targets specified" msgstr "복구 대상을 다중 지정했음" -#: access/transam/xlogrecovery.c:4690 +#: access/transam/xlogrecovery.c:4774 #, c-format msgid "" -"At most one of recovery_target, recovery_target_lsn, recovery_target_name, " -"recovery_target_time, recovery_target_xid may be set." +"At most one of \"recovery_target\", \"recovery_target_lsn\", " +"\"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" " +"may be set." msgstr "" -"recovery_target, recovery_target_lsn, recovery_target_name, " -"recovery_target_time, recovery_target_xid 이들 중 하나는 지정해야합니다." +"\"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", " +"\"recovery_target_time\", \"recovery_target_xid\" 이들 중 하나는 지정해야합니" +"다." -#: access/transam/xlogrecovery.c:4701 +#: access/transam/xlogrecovery.c:4785 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "이 값으로는 \"immediate\" 만 허용합니다." -#: access/transam/xlogrecovery.c:4853 utils/adt/timestamp.c:186 -#: utils/adt/timestamp.c:439 +#: access/transam/xlogrecovery.c:4937 utils/adt/timestamp.c:202 +#: utils/adt/timestamp.c:455 #, c-format msgid "timestamp out of range: \"%s\"" msgstr "타임스탬프 값이 범위를 벗어났음: \"%s\"" -#: access/transam/xlogrecovery.c:4898 +#: access/transam/xlogrecovery.c:4982 #, c-format -msgid "recovery_target_timeline is not a valid number." -msgstr "recovery_target_timeline 값으로 잘못된 숫자입니다." +msgid "\"recovery_target_timeline\" is not a valid number." +msgstr "\"recovery_target_timeline\" 값으로 잘못된 숫자입니다." -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1032 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "%s WAL 조각에서 읽기 실패, offset %d: %m" -#: access/transam/xlogutils.c:1046 +#: access/transam/xlogutils.c:1039 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "%s WAL 조각에서 읽기 실패, 위치: %d, %d 읽음(전체: %d)" -#: archive/shell_archive.c:96 +#: archive/shell_archive.c:98 #, c-format msgid "archive command failed with exit code %d" msgstr "아카이브 명령 실패, 종료 코드: %d" -#: archive/shell_archive.c:98 archive/shell_archive.c:108 -#: archive/shell_archive.c:114 archive/shell_archive.c:123 +#: archive/shell_archive.c:100 archive/shell_archive.c:110 +#: archive/shell_archive.c:116 archive/shell_archive.c:125 #, c-format msgid "The failed archive command was: %s" msgstr "실패한 아카이브 명령: %s" -#: archive/shell_archive.c:105 +#: archive/shell_archive.c:107 #, c-format msgid "archive command was terminated by exception 0x%X" msgstr "0x%X 예외로 인해 아카이브 명령이 종료됨" -#: archive/shell_archive.c:107 postmaster/postmaster.c:3678 +#: archive/shell_archive.c:109 postmaster/postmaster.c:3093 #, c-format msgid "" "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "16진수 값에 대한 설명은 C 포함 파일 \"ntstatus.h\"를 참조하십시오." -#: archive/shell_archive.c:112 +#: archive/shell_archive.c:114 #, c-format msgid "archive command was terminated by signal %d: %s" msgstr "%d번 시그널로 인해 아카이브 명령이 종료됨: %s" -#: archive/shell_archive.c:121 +#: archive/shell_archive.c:123 #, c-format msgid "archive command exited with unrecognized status %d" msgstr "아카이브 명령이 인식할 수 없는 %d 상태로 종료됨" -#: backup/backup_manifest.c:253 +#: backup/backup_manifest.c:254 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "%u 타임라인이 끝이어야하는데, %u 타임라인임" -#: backup/backup_manifest.c:277 +#: backup/backup_manifest.c:278 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "시작 타임라인이 %u 여야하는데, %u 타임라인임" -#: backup/backup_manifest.c:304 +#: backup/backup_manifest.c:305 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "%u 시작 타임라인이 %u 타임라인 내역안에 없음" -#: backup/backup_manifest.c:355 +#: backup/backup_manifest.c:356 #, c-format msgid "could not rewind temporary file" msgstr "임시 파일을 되감을 수 없음" -#: backup/basebackup.c:470 +#: backup/basebackup.c:479 #, c-format msgid "could not find any WAL files" msgstr "어떤 WAL 파일도 찾을 수 없음" -#: backup/basebackup.c:485 backup/basebackup.c:500 backup/basebackup.c:509 +#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 #, c-format msgid "could not find WAL file \"%s\"" msgstr "\"%s\" WAL 파일 찾기 실패" -#: backup/basebackup.c:551 backup/basebackup.c:576 +#: backup/basebackup.c:560 backup/basebackup.c:585 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "\"%s\" WAL 파일의 크기가 알맞지 않음" -#: backup/basebackup.c:646 +#: backup/basebackup.c:656 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" msgstr[0] "%lld 전체 체크섬 검사 실패" -#: backup/basebackup.c:653 +#: backup/basebackup.c:663 #, c-format msgid "checksum verification failure during base backup" msgstr "베이스 백업 중 체크섬 검사 실패" -#: backup/basebackup.c:722 backup/basebackup.c:731 backup/basebackup.c:742 -#: backup/basebackup.c:759 backup/basebackup.c:768 backup/basebackup.c:779 -#: backup/basebackup.c:796 backup/basebackup.c:805 backup/basebackup.c:817 -#: backup/basebackup.c:841 backup/basebackup.c:855 backup/basebackup.c:866 -#: backup/basebackup.c:877 backup/basebackup.c:890 +#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 +#: backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 +#: backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 +#: backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 +#: backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 #, c-format msgid "duplicate option \"%s\"" msgstr "\"%s\" 옵션을 두 번 지정했습니다" -#: backup/basebackup.c:750 +#: backup/basebackup.c:761 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "알 수 없는 체크포인트 종류: \"%s\"" -#: backup/basebackup.c:785 +#: backup/basebackup.c:793 +#, c-format +msgid "incremental backups cannot be taken unless WAL summarization is enabled" +msgstr "증분 백업은 summarize_wal=on 상태에서만 가능함" + +#: backup/basebackup.c:809 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "" "%d 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%d .. %d)를 벗어났습니다." -#: backup/basebackup.c:830 +#: backup/basebackup.c:854 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "인식할 수 없는 메니페스트 옵션 \"%s\"" -#: backup/basebackup.c:846 -#, c-format -msgid "unrecognized checksum algorithm: \"%s\"" -msgstr "알 수 없는 체크섬 알고리즘: \"%s\"" - -#: backup/basebackup.c:881 +#: backup/basebackup.c:905 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "알 수 없는 압축 알고리즘: \"%s\"" -#: backup/basebackup.c:897 +#: backup/basebackup.c:921 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "인식할 수 없는 베이스 백업 옵션: \"%s\"" -#: backup/basebackup.c:908 +#: backup/basebackup.c:932 #, c-format msgid "manifest checksums require a backup manifest" msgstr "매니페스트 체크섬은 하나의 백업 메니페스트를 필요로 함" -#: backup/basebackup.c:917 +#: backup/basebackup.c:941 #, c-format msgid "target detail cannot be used without target" msgstr "타켓 지정 없이 타켓 세부정보를 지정할 수 없음" -#: backup/basebackup.c:926 backup/basebackup_target.c:218 +#: backup/basebackup.c:950 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "\"%s\" 타켓은 타켓 세부정보를 지정할 수 없음" -#: backup/basebackup.c:937 +#: backup/basebackup.c:961 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "압축을 사용하지 않으면 압축 세부 정보를 지정할 수 없음" -#: backup/basebackup.c:950 +#: backup/basebackup.c:974 #, c-format msgid "invalid compression specification: %s" msgstr "잘못된 압축 명세: %s" -#: backup/basebackup.c:1116 backup/basebackup.c:1294 +#: backup/basebackup.c:1024 +#, c-format +msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" +msgstr "증북 BASE_BACKUP 수행 전에 UPLOAD_MANIFEST 있어야 함" + +#: backup/basebackup.c:1157 backup/basebackup.c:1358 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "파일 또는 디렉터리 \"%s\"의 상태를 확인할 수 없음: %m" -#: backup/basebackup.c:1430 +#: backup/basebackup.c:1544 #, c-format msgid "skipping special file \"%s\"" msgstr "\"%s\" 특수 파일을 건너뜀" -#: backup/basebackup.c:1542 -#, c-format -msgid "invalid segment number %d in file \"%s\"" -msgstr "잘못된 조각 번호 %d, 해당 파일: \"%s\"" - -#: backup/basebackup.c:1574 +#: backup/basebackup.c:1751 #, c-format msgid "" "could not verify checksum in file \"%s\", block %u: read buffer size %d and " @@ -4027,7 +4311,13 @@ msgstr "" "\"%s\" 파일(%u 블록)에서 체크섬 검사 실패: 읽기 버퍼(%d)와 페이지 크기(%d)가 " "서로 다름" -#: backup/basebackup.c:1658 +#: backup/basebackup.c:1813 +#, c-format +msgid "file \"%s\" has a total of %d checksum verification failure" +msgid_plural "file \"%s\" has a total of %d checksum verification failures" +msgstr[0] "\"%s\" 파일에서 전체 %d 건 체크섬 검사 실패" + +#: backup/basebackup.c:1917 #, c-format msgid "" "checksum verification failed in file \"%s\", block %u: calculated %X but " @@ -4035,7 +4325,7 @@ msgid "" msgstr "" "\"%s\" 파일 체크섬 검사 실패(해당 블럭 %u): 계산된 체크섬 %X (기대값 %X)" -#: backup/basebackup.c:1665 +#: backup/basebackup.c:1924 #, c-format msgid "" "further checksum verification failures in file \"%s\" will not be reported" @@ -4043,24 +4333,23 @@ msgstr "" "계속해서 발생하는 \"%s\"에서의 체크섬 검사 실패는 더 이상 보고하지 않을 것입" "니다." -#: backup/basebackup.c:1721 -#, c-format -msgid "file \"%s\" has a total of %d checksum verification failure" -msgid_plural "file \"%s\" has a total of %d checksum verification failures" -msgstr[0] "\"%s\" 파일에서 전체 %d 건 체크섬 검사 실패" - -#: backup/basebackup.c:1767 +#: backup/basebackup.c:2048 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "tar 파일로 묶기에는 파일 이름이 너무 긺: \"%s\"" -#: backup/basebackup.c:1772 +#: backup/basebackup.c:2053 #, c-format msgid "" "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "" -"tar 포멧을 사용하기에는 심볼릭 링크의 대상 경로가 너무 깁니다: 파일 이름 \"%s" -"\", 대상 \"%s\"" +"tar 포멧을 사용하기에는 심볼릭 링크의 대상 경로가 너무 깁니다: 파일 이름 " +"\"%s\", 대상 \"%s\"" + +#: backup/basebackup.c:2127 +#, c-format +msgid "could not read file \"%s\": read %zd of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %zd 읽음, 전체 %zu" #: backup/basebackup_gzip.c:67 #, c-format @@ -4072,55 +4361,148 @@ msgstr "gzip 압축 기능을 뺀 채로 서버가 만들어졌습니다." msgid "could not initialize compression library" msgstr "압축 라이브러리를 초기화할 수 없음" +#: backup/basebackup_incremental.c:294 +#, c-format +msgid "manifest contains no required WAL ranges" +msgstr "매니페스트에 필요한 WAL 범위가 없음" + +#: backup/basebackup_incremental.c:349 +#, c-format +msgid "timeline %u found in manifest, but not in this server's history" +msgstr "매니페스트에 있는 타임라인 %u번이 이 서버 백업 이력 파일에는 없음" + +#: backup/basebackup_incremental.c:414 +#, c-format +msgid "" +"manifest requires WAL from initial timeline %u starting at %X/%X, but that " +"timeline begins at %X/%X" +msgstr "" +"매니페스트에는 시작 타임라인이 %u번으로 %X/%X에 있다고 해서 그 WAL 파일이 필요한데, " +"그 타임라인은 %X/%X에 있음" + +#: backup/basebackup_incremental.c:424 +#, c-format +msgid "" +"manifest requires WAL from continuation timeline %u starting at %X/%X, but " +"that timeline begins at %X/%X" +msgstr "" +"매니페스트에는 연결 타임라인이 %u번으로 %X/%X에 있다고 해서 그 WAL 파일이 필요한데, " +"그 타임라인은 %X/%X에 있음" + +#: backup/basebackup_incremental.c:435 +#, c-format +msgid "" +"manifest requires WAL from final timeline %u ending at %X/%X, but this " +"backup starts at %X/%X" +msgstr "" +"매니페스트에는 최종 타임라인이 %u번으로 %X/%X에 있다고 해서 그 WAL 파일이 필요한데, " +"이 백업은 %X/%X에서 시작됨" + +#: backup/basebackup_incremental.c:439 +#, c-format +msgid "" +"This can happen for incremental backups on a standby if there was little " +"activity since the previous backup." +msgstr "" +"이 현상은 이전 백업 이후 DB 사용이 거의 없었는데, 대기 서버에서 증분 백업을 " +"받는 경우 발생합니다." + +#: backup/basebackup_incremental.c:446 +#, c-format +msgid "" +"manifest requires WAL from non-final timeline %u ending at %X/%X, but this " +"server switched timelines at %X/%X" +msgstr "" +"매니페스트에는 %u 타임라인을 끝내는 것이 %X/%X에 있어 그 WAL 파일이 필요한데, " +"서버는 %X/%X에서 타임라인이 바뀌었음" + +#: backup/basebackup_incremental.c:527 +#, c-format +msgid "" +"WAL summaries are required on timeline %u from %X/%X to %X/%X, but no " +"summaries for that timeline and LSN range exist" +msgstr "" +"WAL 요약 정보에서는 %u번 타임라인은 %X/%X에서 %X/%X까지인데, " +"이 타임라인과 범위에 대한 요약을 못 찾음" + +#: backup/basebackup_incremental.c:534 +#, c-format +msgid "" +"WAL summaries are required on timeline %u from %X/%X to %X/%X, but the " +"summaries for that timeline and LSN range are incomplete" +msgstr "" +"WAL 요약 정보에서는 %u번 타임라인은 %X/%X에서 %X/%X까지인데, " +"이 타임라인과 범위에 대한 요약이 불완전함" + +#: backup/basebackup_incremental.c:538 +#, c-format +msgid "The first unsummarized LSN in this range is %X/%X." +msgstr "이 범위 안의 첫번째 요약푼 LSN은 %X/%X입니다." + +#: backup/basebackup_incremental.c:938 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "백업 매니페이스 버전이 1인데, 이것은 증분 백업을 지원하지 않음" + +#: backup/basebackup_incremental.c:956 +#, c-format +msgid "" +"system identifier in backup manifest is %llu, but database system identifier " +"is %llu" +msgstr "" +"백업 매니페스트에는 시스템 식별자 번호가 %llu인데, 데이터베이스 시스템 식별자는 " +"%llu임" + #: backup/basebackup_lz4.c:67 #, c-format msgid "lz4 compression is not supported by this build" msgstr "lz4 기능을 뺀 채로 서버가 만들어졌습니다." -#: backup/basebackup_server.c:75 +#: backup/basebackup_server.c:73 #, c-format msgid "permission denied to create backup stored on server" msgstr "서버에 백업본을 만들기 위한 권한 없음" -#: backup/basebackup_server.c:76 +#: backup/basebackup_server.c:74 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may create a backup stored on " "the server." msgstr "서버에 백업 결과를 파일로 저장하려면, \"%s\" 롤 구성원이어야 합니다." -#: backup/basebackup_server.c:91 +#: backup/basebackup_server.c:89 #, c-format msgid "relative path not allowed for backup stored on server" msgstr "백업을 서버에 저장할 경로 이름으로 상대경로는 사용할 수 없습니다" -#: backup/basebackup_server.c:104 commands/dbcommands.c:501 -#: commands/tablespace.c:163 commands/tablespace.c:179 -#: commands/tablespace.c:599 commands/tablespace.c:644 replication/slot.c:1704 +#: backup/basebackup_server.c:102 commands/dbcommands.c:477 +#: commands/tablespace.c:157 commands/tablespace.c:173 +#: commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 #: storage/file/copydir.c:47 #, c-format msgid "could not create directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" -#: backup/basebackup_server.c:117 +#: backup/basebackup_server.c:115 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "\"%s\" 디렉터리가 비어있지 않습니다." -#: backup/basebackup_server.c:125 utils/init/postinit.c:1164 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1178 #, c-format msgid "could not access directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" -#: backup/basebackup_server.c:177 backup/basebackup_server.c:184 -#: backup/basebackup_server.c:270 backup/basebackup_server.c:277 -#: storage/smgr/md.c:504 storage/smgr/md.c:511 storage/smgr/md.c:593 -#: storage/smgr/md.c:615 storage/smgr/md.c:865 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 +#: backup/basebackup_server.c:268 backup/basebackup_server.c:275 +#: backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 +#: storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 #, c-format msgid "Check free disk space." msgstr "디스크 여유 공간을 확인해 주십시오." -#: backup/basebackup_server.c:181 backup/basebackup_server.c:274 +#: backup/basebackup_server.c:179 backup/basebackup_server.c:272 +#: backup/walsummary.c:309 #, c-format msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" msgstr "\"%s\" 파일 쓰기 실패: %d 바이트만 썼음(전체: %d), 해당 블록: %u" @@ -4150,248 +4532,248 @@ msgstr "압축 작업자 수를 %d 값으로 지정할 수 없음: %s" msgid "could not enable long-distance mode: %s" msgstr "long-distance 모드를 활성화 할 수 없음: %s" -#: bootstrap/bootstrap.c:243 postmaster/postmaster.c:721 tcop/postgres.c:3819 +#: backup/walsummaryfuncs.c:95 +#, c-format +msgid "invalid timeline %lld" +msgstr "잘못된 타임라인 번호 %lld" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3946 #, c-format msgid "--%s requires a value" msgstr "--%s 옵션은 해당 값을 지정해야 합니다" -#: bootstrap/bootstrap.c:248 postmaster/postmaster.c:726 tcop/postgres.c:3824 +#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3951 #, c-format msgid "-c %s requires a value" msgstr "-c %s 옵션은 해당 값을 지정해야 합니다" -#: bootstrap/bootstrap.c:289 -#, c-format -msgid "-X requires a power of two value between 1 MB and 1 GB" -msgstr "-X 값은 1 MB ~ 1 GB 사이 2^n 값이어야 함" - -#: bootstrap/bootstrap.c:295 postmaster/postmaster.c:844 -#: postmaster/postmaster.c:857 +#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 +#: postmaster/postmaster.c:759 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "자제한 사항은 \"%s --help\" 명령으로 살펴보십시오.\n" -#: bootstrap/bootstrap.c:304 +#: bootstrap/bootstrap.c:291 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: 잘못된 명령행 인자\n" -#: catalog/aclchk.c:201 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "grant 옵션들은 롤에서만 지정될 수 있습니다" -#: catalog/aclchk.c:323 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 권한이 부여되지 않았음" -#: catalog/aclchk.c:328 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "\"%s\"에 대한 권한이 부여되지 않았음" -#: catalog/aclchk.c:336 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 일부 권한이 부여되지 않았음" -#: catalog/aclchk.c:341 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "\"%s\"에 대한 일부 권한이 부여되지 않았음" -#: catalog/aclchk.c:352 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")에 대한 권한을 취소할 수 없음" -#: catalog/aclchk.c:357 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "\"%s\"에 대한 권한을 취소할 수 없음" -#: catalog/aclchk.c:365 +#: catalog/aclchk.c:375 #, c-format msgid "" "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")의 일부 권한을 박탈할 수 없음" -#: catalog/aclchk.c:370 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "\"%s\"에 대한 일부 권한을 취소할 수 없음" -#: catalog/aclchk.c:402 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "권한 수여자는 현재 사용자여야합니다" -#: catalog/aclchk.c:470 catalog/aclchk.c:1045 +#: catalog/aclchk.c:480 catalog/aclchk.c:1055 #, c-format msgid "invalid privilege type %s for relation" msgstr "릴레이션의 %s 권한은 잘못된 종류임" -#: catalog/aclchk.c:474 catalog/aclchk.c:1049 +#: catalog/aclchk.c:484 catalog/aclchk.c:1059 #, c-format msgid "invalid privilege type %s for sequence" msgstr "시퀀스의 %s 권한은 잘못된 종류임" -#: catalog/aclchk.c:478 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "%s 권한은 데이터베이스에는 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:482 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "%s 권한은 도메인에서 유효하지 않음" -#: catalog/aclchk.c:486 catalog/aclchk.c:1053 +#: catalog/aclchk.c:496 catalog/aclchk.c:1063 #, c-format msgid "invalid privilege type %s for function" msgstr "%s 권한은 함수에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:490 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "%s 권한은 프로시주얼 언어에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:494 +#: catalog/aclchk.c:504 #, c-format msgid "invalid privilege type %s for large object" msgstr "%s 권한은 대형 개체에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:498 catalog/aclchk.c:1069 +#: catalog/aclchk.c:508 catalog/aclchk.c:1079 #, c-format msgid "invalid privilege type %s for schema" msgstr "%s 권한은 스키마(schema)에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:502 catalog/aclchk.c:1057 +#: catalog/aclchk.c:512 catalog/aclchk.c:1067 #, c-format msgid "invalid privilege type %s for procedure" msgstr "프로시져용 %s 권한 종류가 잘못됨" -#: catalog/aclchk.c:506 catalog/aclchk.c:1061 +#: catalog/aclchk.c:516 catalog/aclchk.c:1071 #, c-format msgid "invalid privilege type %s for routine" msgstr "루틴용 %s 권한 종류가 잘못됨" -#: catalog/aclchk.c:510 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "%s 권한은 테이블스페이스에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:514 catalog/aclchk.c:1065 +#: catalog/aclchk.c:524 catalog/aclchk.c:1075 #, c-format msgid "invalid privilege type %s for type" msgstr "%s 권한은 자료형에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:518 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "%s 권한 형식은 외부 데이터 래퍼에 유효하지 않음" -#: catalog/aclchk.c:522 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "%s 권한 형식은 외부 서버에 유효하지 않음" -#: catalog/aclchk.c:526 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "잘못된 환경 설정 매개 변수용 권한 형태: %s" -#: catalog/aclchk.c:565 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "칼럼 권한은 릴레이션에서만 유효함" -#: catalog/aclchk.c:728 catalog/aclchk.c:3555 catalog/objectaddress.c:1092 -#: catalog/pg_largeobject.c:116 storage/large_object/inv_api.c:287 +#: catalog/aclchk.c:738 catalog/aclchk.c:3629 catalog/objectaddress.c:1054 +#: catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 #, c-format msgid "large object %u does not exist" msgstr "%u large object 없음" -#: catalog/aclchk.c:1102 +#: catalog/aclchk.c:1112 #, c-format msgid "default privileges cannot be set for columns" msgstr "default privileges 설정은 칼럼 대상으로 할 수 없음" -#: catalog/aclchk.c:1138 +#: catalog/aclchk.c:1148 #, c-format msgid "permission denied to change default privileges" msgstr "default privileges 변경 권한 없음" -#: catalog/aclchk.c:1256 +#: catalog/aclchk.c:1266 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "GRANT/REVOKE ON SCHEMAS 구문을 쓸 때는 IN SCHEMA 구문을 쓸 수 없음" -#: catalog/aclchk.c:1595 catalog/catalog.c:631 catalog/objectaddress.c:1561 -#: catalog/pg_publication.c:533 commands/analyze.c:390 commands/copy.c:837 -#: commands/sequence.c:1663 commands/tablecmds.c:7339 commands/tablecmds.c:7495 -#: commands/tablecmds.c:7545 commands/tablecmds.c:7619 -#: commands/tablecmds.c:7689 commands/tablecmds.c:7801 -#: commands/tablecmds.c:7895 commands/tablecmds.c:7954 -#: commands/tablecmds.c:8043 commands/tablecmds.c:8073 -#: commands/tablecmds.c:8201 commands/tablecmds.c:8283 -#: commands/tablecmds.c:8417 commands/tablecmds.c:8525 -#: commands/tablecmds.c:12240 commands/tablecmds.c:12421 -#: commands/tablecmds.c:12582 commands/tablecmds.c:13744 -#: commands/tablecmds.c:16273 commands/trigger.c:949 parser/analyze.c:2518 -#: parser/parse_relation.c:737 parser/parse_target.c:1054 -#: parser/parse_type.c:144 parser/parse_utilcmd.c:3413 -#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2876 -#: utils/adt/ruleutils.c:2799 +#: catalog/aclchk.c:1617 catalog/catalog.c:659 catalog/objectaddress.c:1523 +#: catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:951 +#: commands/sequence.c:1655 commands/tablecmds.c:7541 commands/tablecmds.c:7695 +#: commands/tablecmds.c:7745 commands/tablecmds.c:7819 +#: commands/tablecmds.c:7889 commands/tablecmds.c:8019 +#: commands/tablecmds.c:8148 commands/tablecmds.c:8242 +#: commands/tablecmds.c:8343 commands/tablecmds.c:8470 +#: commands/tablecmds.c:8500 commands/tablecmds.c:8642 +#: commands/tablecmds.c:8735 commands/tablecmds.c:8869 +#: commands/tablecmds.c:8981 commands/tablecmds.c:12797 +#: commands/tablecmds.c:12989 commands/tablecmds.c:13150 +#: commands/tablecmds.c:14339 commands/tablecmds.c:16966 commands/trigger.c:942 +#: parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 +#: parser/parse_type.c:144 parser/parse_utilcmd.c:3409 +#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2923 +#: utils/adt/ruleutils.c:2812 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "\"%s\" 칼럼은 \"%s\" 릴레이션(relation)에 없음" -#: catalog/aclchk.c:1840 +#: catalog/aclchk.c:1862 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" 개체는 인덱스임" -#: catalog/aclchk.c:1847 commands/tablecmds.c:13901 commands/tablecmds.c:17172 +#: catalog/aclchk.c:1869 commands/tablecmds.c:14496 commands/tablecmds.c:17882 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\" 개체는 복합 자료형입니다" -#: catalog/aclchk.c:1855 catalog/objectaddress.c:1401 commands/sequence.c:1171 -#: commands/tablecmds.c:254 commands/tablecmds.c:17136 utils/adt/acl.c:2084 -#: utils/adt/acl.c:2114 utils/adt/acl.c:2146 utils/adt/acl.c:2178 -#: utils/adt/acl.c:2206 utils/adt/acl.c:2236 +#: catalog/aclchk.c:1877 catalog/objectaddress.c:1363 commands/tablecmds.c:263 +#: commands/tablecmds.c:17846 utils/adt/acl.c:2107 utils/adt/acl.c:2137 +#: utils/adt/acl.c:2170 utils/adt/acl.c:2206 utils/adt/acl.c:2237 +#: utils/adt/acl.c:2268 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\" 시퀀스가 아님" -#: catalog/aclchk.c:1893 +#: catalog/aclchk.c:1915 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "\"%s\" 시퀀스는 USAGE, SELECT 및 UPDATE 권한만 지원함" -#: catalog/aclchk.c:1910 +#: catalog/aclchk.c:1932 #, c-format msgid "invalid privilege type %s for table" msgstr "%s 권한은 테이블에서 사용할 수 없은 권한 형태임" -#: catalog/aclchk.c:2072 +#: catalog/aclchk.c:2097 #, c-format msgid "invalid privilege type %s for column" msgstr "%s 권한 형식은 칼럼에서 유효하지 않음" -#: catalog/aclchk.c:2085 +#: catalog/aclchk.c:2110 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "\"%s\" 시퀀스는 SELECT 열 권한만 지원함" -#: catalog/aclchk.c:2275 +#: catalog/aclchk.c:2301 #, c-format msgid "language \"%s\" is not trusted" msgstr "\"%s\" 프로시주얼 언어는 안전하지 못합니다" -#: catalog/aclchk.c:2277 +#: catalog/aclchk.c:2303 #, c-format msgid "" "GRANT and REVOKE are not allowed on untrusted languages, because only " @@ -4400,400 +4782,411 @@ msgstr "" "안전하지 않은 프로시져 언어에 대해서는 GRANT 또는 REVOKE 작업을 허용하지 않습" "니다, 안전하지 않은 프로시져 언어는 슈퍼유저만 사용할 수 있기 때문입니다." -#: catalog/aclchk.c:2427 +#: catalog/aclchk.c:2454 #, c-format msgid "cannot set privileges of array types" msgstr "배열형 자료형에 권한 설정을 할 수 없음" -#: catalog/aclchk.c:2428 +#: catalog/aclchk.c:2455 #, c-format msgid "Set the privileges of the element type instead." msgstr "그 배열 요소에 해당하는 자료형에 대해서 접근 권한 설정을 하세요." -#: catalog/aclchk.c:2435 catalog/objectaddress.c:1667 +#: catalog/aclchk.c:2459 +#, c-format +msgid "cannot set privileges of multirange types" +msgstr "다중 범위 자료형에 권한 설정을 할 수 없음" + +#: catalog/aclchk.c:2460 +#, c-format +msgid "Set the privileges of the range type instead." +msgstr "해당하는 범위 자료형에 대해서 접근 권한 설정을 하세요." + +#: catalog/aclchk.c:2467 catalog/objectaddress.c:1629 #, c-format msgid "\"%s\" is not a domain" msgstr "\"%s\" 이름의 개체는 도메인이 아닙니다" -#: catalog/aclchk.c:2619 +#: catalog/aclchk.c:2653 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "알 수 없는 권한 타입 \"%s\"" -#: catalog/aclchk.c:2684 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for aggregate %s" msgstr "%s 집계함수에 대한 접근 권한 없음" -#: catalog/aclchk.c:2687 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for collation %s" msgstr "%s 정렬정의(collation) 접근 권한 없음" -#: catalog/aclchk.c:2690 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for column %s" msgstr "%s 칼럼에 대한 접근 권한 없음" -#: catalog/aclchk.c:2693 +#: catalog/aclchk.c:2729 #, c-format msgid "permission denied for conversion %s" msgstr "%s 문자코드변환규칙(conversion) 접근 권한 없음" -#: catalog/aclchk.c:2696 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for database %s" msgstr "%s 데이터베이스 접근 권한 없음" -#: catalog/aclchk.c:2699 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for domain %s" msgstr "%s 도메인에 대한 접근 권한 없음" -#: catalog/aclchk.c:2702 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for event trigger %s" msgstr "%s 이벤트 트리거 접근 권한 없음" -#: catalog/aclchk.c:2705 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for extension %s" msgstr "%s 확장 모듈 접근 권한 없음" -#: catalog/aclchk.c:2708 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "%s 외부 데이터 래퍼 접근 권한 없음" -#: catalog/aclchk.c:2711 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for foreign server %s" msgstr "%s 외부 서버 접근 권한 없음" -#: catalog/aclchk.c:2714 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for foreign table %s" msgstr "%s 외부 테이블 접근 권한 없음" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for function %s" msgstr "%s 함수 접근 권한 없음" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2756 #, c-format msgid "permission denied for index %s" msgstr "%s 인덱스 접근 권한 없음" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2759 #, c-format msgid "permission denied for language %s" msgstr "%s 프로시주얼 언어 접근 권한 없음" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2762 #, c-format msgid "permission denied for large object %s" msgstr "%s 대형 개체 접근 권한 없음" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2765 #, c-format msgid "permission denied for materialized view %s" msgstr "%s 구체화된 뷰에 대한 접근 권한 없음" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2768 #, c-format msgid "permission denied for operator class %s" msgstr "%s 연산자 클래스 접근 권한 없음" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2771 #, c-format msgid "permission denied for operator %s" msgstr "%s 연산자 접근 권한 없음" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2774 #, c-format msgid "permission denied for operator family %s" msgstr "%s 연산자 패밀리 접근 권한 없음" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2777 #, c-format msgid "permission denied for parameter %s" msgstr "%s 환경 설정 매개 변수 접근 권한 없음" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2780 #, c-format msgid "permission denied for policy %s" msgstr "%s 정책에 대한 접근 권한 없음" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2783 #, c-format msgid "permission denied for procedure %s" msgstr "%s 프로시져에 대한 접근 권한 없음" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2786 #, c-format msgid "permission denied for publication %s" msgstr "%s 발행 접근 권한 없음" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2789 #, c-format msgid "permission denied for routine %s" msgstr "%s 루틴에 대한 접근 권한 없음" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2792 #, c-format msgid "permission denied for schema %s" msgstr "%s 스키마(schema) 접근 권한 없음" -#: catalog/aclchk.c:2759 commands/sequence.c:659 commands/sequence.c:885 -#: commands/sequence.c:927 commands/sequence.c:968 commands/sequence.c:1761 -#: commands/sequence.c:1810 +#: catalog/aclchk.c:2795 commands/sequence.c:654 commands/sequence.c:880 +#: commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 +#: commands/sequence.c:1799 #, c-format msgid "permission denied for sequence %s" msgstr "%s 시퀀스 접근 권한 없음" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2798 #, c-format msgid "permission denied for statistics object %s" msgstr "%s 개체 통계정보 접근 권한 없음" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2801 #, c-format msgid "permission denied for subscription %s" msgstr "%s 구독 접근 권한 없음" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2804 #, c-format msgid "permission denied for table %s" msgstr "%s 테이블에 대한 접근 권한 없음" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2807 #, c-format msgid "permission denied for tablespace %s" msgstr "%s 테이블스페이스 접근 권한 없음" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2810 #, c-format msgid "permission denied for text search configuration %s" msgstr "%s 전문 검색 구성 접근 권한 없음" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2813 #, c-format msgid "permission denied for text search dictionary %s" msgstr "%s 전문 검색 사전 접근 권한 없음" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2816 #, c-format msgid "permission denied for type %s" msgstr "%s 자료형 접근 권한 없음" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2819 #, c-format msgid "permission denied for view %s" msgstr "%s 뷰에 대한 접근 권한 없음" -#: catalog/aclchk.c:2819 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of aggregate %s" msgstr "%s 집계함수의 소유주여야만 합니다" -#: catalog/aclchk.c:2822 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of collation %s" msgstr "%s 정렬정의(collation)의 소유주여야만 합니다" -#: catalog/aclchk.c:2825 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of conversion %s" msgstr "%s 문자코드변환규칙(conversion)의 소유주여야만 합니다" -#: catalog/aclchk.c:2828 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of database %s" msgstr "%s 데이터베이스의 소유주여야만 합니다" -#: catalog/aclchk.c:2831 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of domain %s" msgstr "%s 도메인의 소유주여야만 합니다" -#: catalog/aclchk.c:2834 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of event trigger %s" msgstr "%s 이벤트 트리거의 소유주여야만 합니다" -#: catalog/aclchk.c:2837 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of extension %s" msgstr "%s 확장 모듈의 소유주여야만 합니다" -#: catalog/aclchk.c:2840 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "%s 외부 데이터 래퍼의 소유주여야 함" -#: catalog/aclchk.c:2843 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of foreign server %s" msgstr "%s 외부 서버의 소유주여야 함" -#: catalog/aclchk.c:2846 +#: catalog/aclchk.c:2882 #, c-format msgid "must be owner of foreign table %s" msgstr "%s 외부 테이블의 소유주여야 함" -#: catalog/aclchk.c:2849 +#: catalog/aclchk.c:2885 #, c-format msgid "must be owner of function %s" msgstr "%s 함수의 소유주여야만 합니다" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2888 #, c-format msgid "must be owner of index %s" msgstr "%s 인덱스의 소유주여야만 합니다" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2891 #, c-format msgid "must be owner of language %s" msgstr "%s 프로시주얼 언어의 소유주여야만 합니다" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2894 #, c-format msgid "must be owner of large object %s" msgstr "%s 대형 개체의 소유주여야만 합니다" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2897 #, c-format msgid "must be owner of materialized view %s" msgstr "%s 구체화된 뷰의 소유주여야만 합니다" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2900 #, c-format msgid "must be owner of operator class %s" msgstr "%s 연산자 클래스의 소유주여야만 합니다" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2903 #, c-format msgid "must be owner of operator %s" msgstr "%s 연산자의 소유주여야만 합니다" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2906 #, c-format msgid "must be owner of operator family %s" msgstr "%s 연산자 패밀리의 소유주여야 함" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2909 #, c-format msgid "must be owner of procedure %s" msgstr "%s 프로시져의 소유주여야만 합니다" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2912 #, c-format msgid "must be owner of publication %s" msgstr "%s 발행의 소유주여야만 합니다" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2915 #, c-format msgid "must be owner of routine %s" msgstr "%s 루틴의 소유주여야만 합니다" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2918 #, c-format msgid "must be owner of sequence %s" msgstr "%s 시퀀스의 소유주여야만 합니다" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2921 #, c-format msgid "must be owner of subscription %s" msgstr "%s 구독의 소유주여야만 합니다" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2924 #, c-format msgid "must be owner of table %s" msgstr "%s 테이블의 소유주여야만 합니다" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2927 #, c-format msgid "must be owner of type %s" msgstr "%s 자료형의 소유주여야만 합니다" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2930 #, c-format msgid "must be owner of view %s" msgstr "%s 뷰의 소유주여야만 합니다" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2933 #, c-format msgid "must be owner of schema %s" msgstr "%s 스키마(schema)의 소유주여야만 합니다" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2936 #, c-format msgid "must be owner of statistics object %s" msgstr "%s 통계정보 개체의 소유주여야만 합니다" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2939 #, c-format msgid "must be owner of tablespace %s" msgstr "%s 테이블스페이스의 소유주여야만 합니다" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2942 #, c-format msgid "must be owner of text search configuration %s" msgstr "%s 전문 검색 구성의 소유주여야 함" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2945 #, c-format msgid "must be owner of text search dictionary %s" msgstr "%s 전문 검색 사전의 소유주여야 함" -#: catalog/aclchk.c:2923 +#: catalog/aclchk.c:2959 #, c-format msgid "must be owner of relation %s" msgstr "%s 릴레이션(relation)의 소유주여야만 합니다" -#: catalog/aclchk.c:2969 +#: catalog/aclchk.c:3005 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\") 접근 권한 없음" -#: catalog/aclchk.c:3104 catalog/aclchk.c:3979 catalog/aclchk.c:4011 +#: catalog/aclchk.c:3162 catalog/aclchk.c:4170 catalog/aclchk.c:4201 #, c-format msgid "%s with OID %u does not exist" msgstr "%s (해당 OID %u) 없음" -#: catalog/aclchk.c:3188 catalog/aclchk.c:3207 +#: catalog/aclchk.c:3245 catalog/aclchk.c:3264 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "%d번째 속성(해당 릴레이션 OID: %u)이 없음" -#: catalog/aclchk.c:3302 +#: catalog/aclchk.c:3302 catalog/aclchk.c:3365 catalog/aclchk.c:4004 #, c-format msgid "relation with OID %u does not exist" msgstr "OID %u 릴레이션(relation) 없음" -#: catalog/aclchk.c:3476 +#: catalog/aclchk.c:3550 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "OID %u 환경 설정 매개 변수 ACL이 없음" -#: catalog/aclchk.c:3640 commands/collationcmds.c:808 -#: commands/publicationcmds.c:1746 +#: catalog/aclchk.c:3723 commands/collationcmds.c:853 +#: commands/publicationcmds.c:1739 #, c-format msgid "schema with OID %u does not exist" msgstr "OID %u 스키마 없음" -#: catalog/aclchk.c:3705 utils/cache/typcache.c:385 utils/cache/typcache.c:440 +#: catalog/aclchk.c:3797 catalog/aclchk.c:3824 catalog/aclchk.c:3853 +#: utils/cache/typcache.c:392 utils/cache/typcache.c:447 #, c-format msgid "type with OID %u does not exist" msgstr "OID %u 자료형 없음" -#: catalog/catalog.c:449 +#: catalog/catalog.c:477 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "\"%s\" 릴레이션에서 사용되지 않는 OID를 여전히 찾는 중" -#: catalog/catalog.c:451 +#: catalog/catalog.c:479 #, c-format msgid "" "OID candidates have been checked %llu time, but no unused OID has been found " @@ -4804,63 +5197,63 @@ msgid_plural "" msgstr[0] "" "OID 후보를 뽑기 위해 %llu 번 시도했지만, 아직 사용되지 않는 OID를 찾지 못함" -#: catalog/catalog.c:476 +#: catalog/catalog.c:504 #, c-format msgid "new OID has been assigned in relation \"%s\" after %llu retry" msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" msgstr[0] "\"%s\" 릴레이션의 새 OID를 %llu 시도 끝에 배정함" -#: catalog/catalog.c:609 catalog/catalog.c:676 +#: catalog/catalog.c:637 catalog/catalog.c:704 #, c-format msgid "must be superuser to call %s()" msgstr "%s() 호출은 슈퍼유저만 할 수 있음" -#: catalog/catalog.c:618 +#: catalog/catalog.c:646 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() 함수는 시스템 카탈로그 대상 전용임" -#: catalog/catalog.c:623 parser/parse_utilcmd.c:2264 +#: catalog/catalog.c:651 parser/parse_utilcmd.c:2270 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "\"%s\" 인덱스가 \"%s\" 테이블용이 아님" -#: catalog/catalog.c:640 +#: catalog/catalog.c:668 #, c-format msgid "column \"%s\" is not of type oid" msgstr "\"%s\" 칼럼은 oid 자료형이 아님" -#: catalog/catalog.c:647 +#: catalog/catalog.c:675 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "\"%s\" 인덱스는 \"%s\" 칼럼용 인덱스가 아님" -#: catalog/dependency.c:546 catalog/pg_shdepend.c:658 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "%s 개체는 데이터베이스 시스템에서 필요하기 때문에 삭제 될 수 없음" -#: catalog/dependency.c:838 catalog/dependency.c:1065 +#: catalog/dependency.c:789 catalog/dependency.c:1016 #, c-format msgid "cannot drop %s because %s requires it" msgstr "%s 삭제할 수 없음, %s에서 필요로함" -#: catalog/dependency.c:840 catalog/dependency.c:1067 +#: catalog/dependency.c:791 catalog/dependency.c:1018 #, c-format msgid "You can drop %s instead." msgstr "대신에, drop %s 명령을 사용할 수 있음." -#: catalog/dependency.c:1146 catalog/dependency.c:1155 +#: catalog/dependency.c:1097 catalog/dependency.c:1106 #, c-format msgid "%s depends on %s" msgstr "%s 의존대상: %s" -#: catalog/dependency.c:1170 catalog/dependency.c:1179 +#: catalog/dependency.c:1121 catalog/dependency.c:1130 #, c-format msgid "drop cascades to %s" msgstr "%s 개체가 덩달아 삭제됨" -#: catalog/dependency.c:1187 catalog/pg_shdepend.c:823 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -4872,97 +5265,98 @@ msgstr[0] "" "\n" "%d 개의 기타 개체들도 함께 처리함 (목록은 서버 로그에 기록됨)" -#: catalog/dependency.c:1199 +#: catalog/dependency.c:1150 #, c-format msgid "cannot drop %s because other objects depend on it" msgstr "기타 다른 개체들이 이 개체에 의존하고 있어, %s 삭제할 수 없음" -#: catalog/dependency.c:1202 catalog/dependency.c:1209 -#: catalog/dependency.c:1220 commands/tablecmds.c:1335 -#: commands/tablecmds.c:14386 commands/tablespace.c:466 commands/user.c:1309 -#: commands/vacuum.c:211 commands/view.c:446 libpq/auth.c:326 -#: replication/logical/applyparallelworker.c:1044 replication/syncrep.c:1017 -#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1358 utils/misc/guc.c:3120 -#: utils/misc/guc.c:3156 utils/misc/guc.c:3226 utils/misc/guc.c:6615 -#: utils/misc/guc.c:6649 utils/misc/guc.c:6683 utils/misc/guc.c:6726 -#: utils/misc/guc.c:6768 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 +#: catalog/dependency.c:1171 commands/tablecmds.c:1459 +#: commands/tablecmds.c:15088 commands/tablespace.c:460 commands/user.c:1302 +#: commands/vacuum.c:211 commands/view.c:441 executor/execExprInterp.c:4655 +#: executor/execExprInterp.c:4663 libpq/auth.c:324 +#: replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 +#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1432 utils/misc/guc.c:3169 +#: utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6825 +#: utils/misc/guc.c:6859 utils/misc/guc.c:6893 utils/misc/guc.c:6936 +#: utils/misc/guc.c:6978 #, c-format msgid "%s" msgstr "%s" -#: catalog/dependency.c:1203 catalog/dependency.c:1210 +#: catalog/dependency.c:1154 catalog/dependency.c:1161 #, c-format msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "" "이 개체와 관계된 모든 개체들을 함께 삭제하려면 DROP ... CASCADE 명령을 사용하" "십시오" -#: catalog/dependency.c:1207 +#: catalog/dependency.c:1158 #, c-format msgid "cannot drop desired object(s) because other objects depend on them" msgstr "다른 개체가 원하는 개체를 사용하고 있으므로 해당 개체를 삭제할 수 없음" -#: catalog/dependency.c:1215 +#: catalog/dependency.c:1166 #, c-format msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" msgstr[0] "%d개의 다른 개체에 대한 관련 항목 삭제" -#: catalog/dependency.c:1899 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "%s 자료형은 여기서 사용할 수 없음" -#: catalog/dependency.c:2420 parser/parse_relation.c:3404 -#: parser/parse_relation.c:3414 +#: catalog/dependency.c:2375 parser/parse_relation.c:3407 +#: parser/parse_relation.c:3417 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "%d번째 칼럼이 없습니다. 해당 릴레이션: \"%s\"" -#: catalog/heap.c:324 +#: catalog/heap.c:325 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "\"%s.%s\" 만들 권한이 없음" -#: catalog/heap.c:326 +#: catalog/heap.c:327 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "시스템 카탈로그 변경은 현재 허용하지 않습니다." -#: catalog/heap.c:466 commands/tablecmds.c:2374 commands/tablecmds.c:3047 -#: commands/tablecmds.c:6922 +#: catalog/heap.c:467 commands/tablecmds.c:2495 commands/tablecmds.c:2917 +#: commands/tablecmds.c:7163 #, c-format msgid "tables can have at most %d columns" msgstr "한 테이블에 지정할 수 있는 최대 열 수는 %d입니다" -#: catalog/heap.c:484 commands/tablecmds.c:7229 +#: catalog/heap.c:485 commands/tablecmds.c:7432 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "\"%s\" 열 이름은 시스템 열 이름과 충돌합니다" -#: catalog/heap.c:500 +#: catalog/heap.c:501 #, c-format msgid "column name \"%s\" specified more than once" msgstr "\"%s\" 칼럼 이름이 여러 번 지정됨" #. translator: first %s is an integer not a name -#: catalog/heap.c:575 +#: catalog/heap.c:579 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "\"%s\" 파티션 키 칼럼은 %s 의사 자료형(pseudo-type)을 사용합니다" -#: catalog/heap.c:580 +#: catalog/heap.c:584 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "\"%s\" 칼럼은 %s 의사 자료형(pseudo-type)을 사용합니다" -#: catalog/heap.c:611 +#: catalog/heap.c:615 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "%s 복합 자료형은 자기 자신의 구성원으로 만들 수 없음" #. translator: first %s is an integer not a name -#: catalog/heap.c:666 +#: catalog/heap.c:670 #, c-format msgid "" "no collation was derived for partition key column %s with collatable type %s" @@ -4970,27 +5364,27 @@ msgstr "" "\"%s\" 파티션 키 칼럼에 사용하는 %s 자료형에서 사용할 정렬규칙을 결정할 수없" "습니다." -#: catalog/heap.c:672 commands/createas.c:203 commands/createas.c:512 +#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:505 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "" "\"%s\" 칼럼에 사용하는 %s 자료형에서 사용할 정렬규칙을 결정할 수 없습니다." -#: catalog/heap.c:1148 catalog/index.c:887 commands/createas.c:408 -#: commands/tablecmds.c:3987 +#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:401 +#: commands/tablecmds.c:4171 #, c-format msgid "relation \"%s\" already exists" msgstr "\"%s\" 이름의 릴레이션(relation)이 이미 있습니다" -#: catalog/heap.c:1164 catalog/pg_type.c:434 catalog/pg_type.c:782 -#: catalog/pg_type.c:954 commands/typecmds.c:249 commands/typecmds.c:261 -#: commands/typecmds.c:754 commands/typecmds.c:1169 commands/typecmds.c:1395 -#: commands/typecmds.c:1575 commands/typecmds.c:2546 +#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 +#: catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 +#: commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 +#: commands/typecmds.c:1585 commands/typecmds.c:2556 #, c-format msgid "type \"%s\" already exists" msgstr "\"%s\" 자료형이 이미 있습니다" -#: catalog/heap.c:1165 +#: catalog/heap.c:1178 #, c-format msgid "" "A relation has an associated type of the same name, so you must use a name " @@ -4999,119 +5393,119 @@ msgstr "" "하나의 릴레이션은 그 이름과 같은 자료형과 관계합니다. 그래서, 이미 같은 이름" "의 자료형이 있다면 해당 릴레이션을 만들 수 없습니다. 다른 이름을 사용하세요." -#: catalog/heap.c:1205 +#: catalog/heap.c:1218 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, toast relfilenumber 값이 지정되지 않았습니다" -#: catalog/heap.c:1216 +#: catalog/heap.c:1229 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, pg_class 자료 OID 값이 지정되지 않았습니다" -#: catalog/heap.c:1226 +#: catalog/heap.c:1239 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, relfilenumber 값이 지정되지 않았습니다" -#: catalog/heap.c:2119 +#: catalog/heap.c:2130 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "\"%s\" 파티션 테이블에는 NO INHERIT 조건을 사용할 수 없음" -#: catalog/heap.c:2393 +#: catalog/heap.c:2402 #, c-format msgid "check constraint \"%s\" already exists" msgstr "\"%s\" 이름의 체크 제약 조건이 이미 있습니다" -#: catalog/heap.c:2563 catalog/index.c:901 catalog/pg_constraint.c:682 -#: commands/tablecmds.c:8900 +#: catalog/heap.c:2574 catalog/index.c:913 catalog/pg_constraint.c:724 +#: commands/tablecmds.c:9356 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "" "\"%s\" 제약 조건이 이미 \"%s\" 릴레이션(relation)에서 사용되고 있습니다" -#: catalog/heap.c:2570 +#: catalog/heap.c:2581 #, c-format msgid "" "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "" "\"%s\" 제약 조건이 비상속 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\"" -#: catalog/heap.c:2581 +#: catalog/heap.c:2592 #, c-format msgid "" "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "\"%s\" 제약 조건이 상속 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\"" -#: catalog/heap.c:2591 +#: catalog/heap.c:2602 #, c-format msgid "" "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "" "\"%s\" 제약 조건이 NOT VALID 제약 조건과 충돌합니다, 해당 릴레이션: \"%s\"" -#: catalog/heap.c:2596 +#: catalog/heap.c:2607 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "\"%s\" 제약 조건을 상속된 정의와 병합하는 중" -#: catalog/heap.c:2622 catalog/pg_constraint.c:811 commands/tablecmds.c:2672 -#: commands/tablecmds.c:3199 commands/tablecmds.c:6858 -#: commands/tablecmds.c:15208 commands/tablecmds.c:15349 +#: catalog/heap.c:2633 catalog/pg_constraint.c:853 commands/tablecmds.c:3074 +#: commands/tablecmds.c:3377 commands/tablecmds.c:7089 +#: commands/tablecmds.c:15907 commands/tablecmds.c:16038 #, c-format msgid "too many inheritance parents" msgstr "너무 많은 상속 부모" -#: catalog/heap.c:2706 +#: catalog/heap.c:2717 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "\"%s\" 계산된 칼럼은 칼럼 생성 표현식에서는 사용될 수 없음" -#: catalog/heap.c:2708 +#: catalog/heap.c:2719 #, c-format msgid "A generated column cannot reference another generated column." msgstr "계산된 칼럼은 다른 계산된 칼럼을 참조할 수 없음" -#: catalog/heap.c:2714 +#: catalog/heap.c:2725 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "미리 계산된 칼럼 생성 표현식에 row 전체 변수는 사용할 수 없음" -#: catalog/heap.c:2715 +#: catalog/heap.c:2726 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "이 오류는 미리 계산된 칼럼 자체를 그 칼럼 값으로 지정할 때 발생합니다." -#: catalog/heap.c:2768 +#: catalog/heap.c:2781 #, c-format msgid "generation expression is not immutable" msgstr "미리 계산되는 생성 표현식 결과가 immutable이 아님" -#: catalog/heap.c:2796 rewrite/rewriteHandler.c:1297 +#: catalog/heap.c:2809 rewrite/rewriteHandler.c:1288 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "" "\"%s\" 칼럼의 자료형은 %s 인데, default 표현식에서는 %s 자료형을 사용했습니다" -#: catalog/heap.c:2801 commands/prepare.c:334 parser/analyze.c:2742 -#: parser/parse_target.c:593 parser/parse_target.c:874 -#: parser/parse_target.c:884 rewrite/rewriteHandler.c:1302 +#: catalog/heap.c:2814 commands/prepare.c:331 parser/analyze.c:2758 +#: parser/parse_target.c:592 parser/parse_target.c:882 +#: parser/parse_target.c:892 rewrite/rewriteHandler.c:1293 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "다시 정의하거나 형변환자를 사용해보십시오" -#: catalog/heap.c:2848 +#: catalog/heap.c:2861 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "\"%s\" 테이블만이 체크 제약 조건에서 참조될 수 있습니다" -#: catalog/heap.c:3154 +#: catalog/heap.c:3167 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "ON COMMIT 및 외래 키 조합이 지원되지 않음" -#: catalog/heap.c:3155 +#: catalog/heap.c:3168 #, c-format msgid "" "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT " @@ -5119,493 +5513,493 @@ msgid "" msgstr "" "\"%s\" 테이블에서 \"%s\" 테이블을 참조하는데 ON COMMIT 설정이 같지 않습니다." -#: catalog/heap.c:3160 +#: catalog/heap.c:3173 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "" "_^_ 테이블 내용을 모두 삭제할 수 없음, 참조키(foreign key) 제약 조건 안에서" -#: catalog/heap.c:3161 +#: catalog/heap.c:3174 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "\"%s\" 테이블은 \"%s\" 개체를 참조합니다." -#: catalog/heap.c:3163 +#: catalog/heap.c:3176 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "" "\"%s\" 테이블도 함께 자료를 지우거나, TRUNCATE ... CASCADE 구문을 사용하세요." -#: catalog/index.c:225 parser/parse_utilcmd.c:2170 +#: catalog/index.c:219 parser/parse_utilcmd.c:2176 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "\"%s\" 테이블에는 이미 기본키가 있습니다" -#: catalog/index.c:239 +#: catalog/index.c:233 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "기본키(primary key)는 NULLS NOT DISTINCT 인덱스를 사용할 수 없음" -#: catalog/index.c:256 +#: catalog/index.c:250 #, c-format msgid "primary keys cannot be expressions" msgstr "기본키(primary key)를 표현할 수 없음" -#: catalog/index.c:273 +#: catalog/index.c:267 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "\"%s\" 파티션 키 칼럼에 NOT NULL 속성을 지정해야 함" -#: catalog/index.c:786 catalog/index.c:1942 +#: catalog/index.c:798 catalog/index.c:1915 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "시스템 카탈로그 테이블에는 사용자 정의 인덱스를 지정할 수 없습니다" -#: catalog/index.c:826 +#: catalog/index.c:838 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "\"%s\" 연산자 클래스용으로 자동 결정 가능한 정렬 규칙은 지원하지 않음" -#: catalog/index.c:841 +#: catalog/index.c:853 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "시스템 카탈로그 테이블은 잠금 없는 인덱스 만들기는 지원하지 않습니다" -#: catalog/index.c:850 catalog/index.c:1318 +#: catalog/index.c:862 catalog/index.c:1331 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "exclusion 제약 조건용 잠금 없는 인덱스 만들기는 지원하지 않습니다" -#: catalog/index.c:859 +#: catalog/index.c:871 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "" "공유되는 인덱스들은 initdb 명령으로 데이터베이스 클러스터를 만든 다음에는 만" "들 수 없습니다" -#: catalog/index.c:879 commands/createas.c:423 commands/sequence.c:158 +#: catalog/index.c:891 commands/createas.c:416 commands/sequence.c:159 #: parser/parse_utilcmd.c:209 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "\"%s\" 이름의 릴레이션(relation)이 이미 있습니다, 건너뜀" -#: catalog/index.c:929 +#: catalog/index.c:941 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, pg_class 인덱스 OID 값이 지정되지 않았습니다" -#: catalog/index.c:939 utils/cache/relcache.c:3731 +#: catalog/index.c:951 utils/cache/relcache.c:3791 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, 인덱스 relfilenumber 값이 지정되지 않았습니다" -#: catalog/index.c:2241 +#: catalog/index.c:2214 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY 명령은 트랜잭션 내 가장 처음에 있어야 합니다" -#: catalog/index.c:3649 +#: catalog/index.c:3668 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "임시 테이블의 인덱스 재생성 작업은 다른 세션에서 할 수 없음" -#: catalog/index.c:3660 commands/indexcmds.c:3631 +#: catalog/index.c:3679 commands/indexcmds.c:3626 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "TOAST 테이블에 딸린 잘못된 인덱스에 대해 재색인 작업을 할 수 없음" -#: catalog/index.c:3676 commands/indexcmds.c:3511 commands/indexcmds.c:3655 -#: commands/tablecmds.c:3402 +#: catalog/index.c:3695 commands/indexcmds.c:3504 commands/indexcmds.c:3650 +#: commands/tablecmds.c:3581 #, c-format msgid "cannot move system relation \"%s\"" msgstr "\"%s\" 시스템 릴레이션입니다. 이동할 수 없습니다" -#: catalog/index.c:3820 +#: catalog/index.c:3832 #, c-format msgid "index \"%s\" was reindexed" msgstr "\"%s\" 인덱스가 다시 만들어졌음" -#: catalog/index.c:3957 +#: catalog/index.c:3998 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "" "TOAST 테이블에 지정된 유효하지 않은 \"%s.%s\" 인덱스는 재색인 작업을 할 수 없" "음, 건너뜀" -#: catalog/namespace.c:260 catalog/namespace.c:464 catalog/namespace.c:556 -#: commands/trigger.c:5718 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 +#: commands/trigger.c:5731 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: \"%s.%s.%s\"" -#: catalog/namespace.c:317 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "임시 테이블은 스키마 이름을 지정할 수 없음" -#: catalog/namespace.c:398 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "\"%s.%s\" 릴레이션의 잠금 정보를 구할 수 없음" -#: catalog/namespace.c:403 commands/lockcmds.c:144 commands/lockcmds.c:224 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "\"%s\" 릴레이션의 잠금 정보를 구할 수 없음" -#: catalog/namespace.c:431 parser/parse_relation.c:1430 +#: catalog/namespace.c:633 parser/parse_relation.c:1430 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "\"%s.%s\" 이름의 릴레이션(relation)이 없습니다" -#: catalog/namespace.c:436 parser/parse_relation.c:1443 +#: catalog/namespace.c:638 parser/parse_relation.c:1443 #: parser/parse_relation.c:1451 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "\"%s\" 이름의 릴레이션(relation)이 없습니다" -#: catalog/namespace.c:502 catalog/namespace.c:3073 commands/extension.c:1611 -#: commands/extension.c:1617 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1607 +#: commands/extension.c:1613 #, c-format msgid "no schema has been selected to create in" msgstr "선택된 스키마 없음, 대상:" -#: catalog/namespace.c:654 catalog/namespace.c:667 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "다른 세션의 임시 스키마 안에는 릴레이션을 만들 수 없음" -#: catalog/namespace.c:658 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "임시 스키마가 아닌 스키마에 임시 릴레이션을 만들 수 없음" -#: catalog/namespace.c:673 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "임시 스키마 안에는 임시 릴레이션만 만들 수 있음" -#: catalog/namespace.c:2265 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "\"%s\" 통계정보 개체가 없음" -#: catalog/namespace.c:2388 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "\"%s\" 전문 검색 파서가 없음" -#: catalog/namespace.c:2514 utils/adt/regproc.c:1439 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "\"%s\" 전문 검색 사전이 없음" -#: catalog/namespace.c:2641 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "\"%s\" 전문 검색 템플릿이 없음" -#: catalog/namespace.c:2767 commands/tsearchcmds.c:1162 -#: utils/adt/regproc.c:1329 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 +#: utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "\"%s\" 전문 검색 구성이 없음" -#: catalog/namespace.c:2880 parser/parse_expr.c:832 parser/parse_target.c:1246 +#: catalog/namespace.c:3329 parser/parse_expr.c:868 parser/parse_target.c:1259 #, c-format msgid "cross-database references are not implemented: %s" msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: %s" -#: catalog/namespace.c:2886 parser/parse_expr.c:839 parser/parse_target.c:1253 -#: gram.y:18569 gram.y:18609 +#: catalog/namespace.c:3335 parser/parse_expr.c:875 parser/parse_target.c:1266 +#: gram.y:19181 gram.y:19221 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "적당하지 않은 qualified 이름 입니다 (너무 많은 점이 있네요): %s" -#: catalog/namespace.c:3016 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "임시 스키마로(에서) 개체를 이동할 수 없습니다" -#: catalog/namespace.c:3022 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "TOAST 스키마로(에서) 개체를 이동할 수 없습니다" -#: catalog/namespace.c:3095 commands/schemacmds.c:264 commands/schemacmds.c:344 -#: commands/tablecmds.c:1280 utils/adt/regproc.c:1668 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 +#: commands/tablecmds.c:1404 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "\"%s\" 스키마(schema) 없음" -#: catalog/namespace.c:3126 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "" "적당하지 않은 릴레이션(relation) 이름 입니다 (너무 많은 점이 있네요): %s" -#: catalog/namespace.c:3693 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "\"%s\" 정렬정의(collation)가 \"%s\" 인코딩에서는 쓸 수 없음" -#: catalog/namespace.c:3748 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "\"%s\" 문자코드변환규칙(conversion) 없음" -#: catalog/namespace.c:4012 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "\"%s\" 데이터베이스에서 임시 파일을 만들 권한이 없음" -#: catalog/namespace.c:4028 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "복구 작업 중에는 임시 테이블을 만들 수 없음" -#: catalog/namespace.c:4034 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "병렬 작업 중에 임시 테이블을 만들 수 없음" -#: catalog/objectaddress.c:1409 commands/policy.c:96 commands/policy.c:376 -#: commands/tablecmds.c:248 commands/tablecmds.c:290 commands/tablecmds.c:2206 -#: commands/tablecmds.c:12357 +#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 +#: commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2327 +#: commands/tablecmds.c:12925 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\" 개체는 테이블이 아님" -#: catalog/objectaddress.c:1416 commands/tablecmds.c:260 -#: commands/tablecmds.c:17141 commands/view.c:119 +#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 +#: commands/tablecmds.c:17851 commands/view.c:114 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\" 개체는 뷰가 아님" -#: catalog/objectaddress.c:1423 commands/matview.c:186 commands/tablecmds.c:266 -#: commands/tablecmds.c:17146 +#: catalog/objectaddress.c:1385 commands/matview.c:199 commands/tablecmds.c:275 +#: commands/tablecmds.c:17856 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\" 개체는 구체화된 뷰(materialized view)가 아닙니다" -#: catalog/objectaddress.c:1430 commands/tablecmds.c:284 -#: commands/tablecmds.c:17151 +#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 +#: commands/tablecmds.c:17861 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\" 개체는 외부 테이블이 아님" -#: catalog/objectaddress.c:1471 +#: catalog/objectaddress.c:1433 #, c-format msgid "must specify relation and object name" msgstr "릴레이션과 개체 이름을 지정해야 합니다" -#: catalog/objectaddress.c:1547 catalog/objectaddress.c:1600 +#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 #, c-format msgid "column name must be qualified" msgstr "칼럼 이름으로 적당하지 않습니다" -#: catalog/objectaddress.c:1619 +#: catalog/objectaddress.c:1581 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")의 기본값을 지정하지 않았음" -#: catalog/objectaddress.c:1656 commands/functioncmds.c:137 -#: commands/tablecmds.c:276 commands/typecmds.c:274 commands/typecmds.c:3689 +#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 +#: commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 #: parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 -#: utils/adt/acl.c:4441 +#: utils/adt/acl.c:4560 #, c-format msgid "type \"%s\" does not exist" msgstr "\"%s\" 자료형 없음" -#: catalog/objectaddress.c:1775 +#: catalog/objectaddress.c:1737 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "%d (%s, %s) 연산자(대상 %s) 없음" -#: catalog/objectaddress.c:1806 +#: catalog/objectaddress.c:1768 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "%d (%s, %s) 함수(대상 %s) 없음" -#: catalog/objectaddress.c:1857 catalog/objectaddress.c:1883 +#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "\"%s\" 사용자에 대한 사용자 맵핑 정보(대상 서버: \"%s\")가 없음" -#: catalog/objectaddress.c:1872 commands/foreigncmds.c:430 -#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:700 +#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 +#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "\"%s\" 이름의 서버가 없음" -#: catalog/objectaddress.c:1939 +#: catalog/objectaddress.c:1901 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "\"%s\" 발행 릴레이션은 \"%s\" 발행에 없습니다." -#: catalog/objectaddress.c:1986 +#: catalog/objectaddress.c:1948 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "\"%s\" 발행 스키마는 \"%s\" 발행에 없습니다." -#: catalog/objectaddress.c:2044 +#: catalog/objectaddress.c:2006 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "알 수 없는 기본 ACL 개체 타입 \"%c\"" -#: catalog/objectaddress.c:2045 +#: catalog/objectaddress.c:2007 #, c-format msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." msgstr "유효한 개체 형태는 \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -#: catalog/objectaddress.c:2096 +#: catalog/objectaddress.c:2058 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "\"%s\" 사용자용 기본 ACL 없음. (해당 스키마: \"%s\", 해당 개체: %s)" -#: catalog/objectaddress.c:2101 +#: catalog/objectaddress.c:2063 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "\"%s\" 사용자용 기본 ACL 없음. (해당 개체: %s)" -#: catalog/objectaddress.c:2127 catalog/objectaddress.c:2184 -#: catalog/objectaddress.c:2239 +#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 +#: catalog/objectaddress.c:2201 #, c-format msgid "name or argument lists may not contain nulls" msgstr "이름이나 인자 목록에는 null이 포함되지 않아야 함" -#: catalog/objectaddress.c:2161 +#: catalog/objectaddress.c:2123 #, c-format msgid "unsupported object type \"%s\"" msgstr "\"%s\" 형 지원하지 않음" -#: catalog/objectaddress.c:2180 catalog/objectaddress.c:2197 -#: catalog/objectaddress.c:2262 catalog/objectaddress.c:2346 +#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 +#: catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 #, c-format msgid "name list length must be exactly %d" msgstr "이름 목록 길이는 %d 이어야 합니다." -#: catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2163 #, c-format msgid "large object OID may not be null" msgstr "대형 개체 OID는 null 값을 사용할 수 없음" -#: catalog/objectaddress.c:2210 catalog/objectaddress.c:2280 -#: catalog/objectaddress.c:2287 +#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 +#: catalog/objectaddress.c:2249 #, c-format msgid "name list length must be at least %d" msgstr "이름 목록 길이는 적어도 %d 개 이상이어야 함" -#: catalog/objectaddress.c:2273 catalog/objectaddress.c:2294 +#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 #, c-format msgid "argument list length must be exactly %d" msgstr "인자 목록은 %d 개여야 함" -#: catalog/objectaddress.c:2508 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 #, c-format msgid "must be owner of large object %u" msgstr "%u 대경 개체의 소유주여야만 합니다" -#: catalog/objectaddress.c:2523 commands/functioncmds.c:1561 +#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 #, c-format msgid "must be owner of type %s or type %s" msgstr "%s, %s 자료형의 소유주여야 합니다" -#: catalog/objectaddress.c:2550 catalog/objectaddress.c:2559 -#: catalog/objectaddress.c:2565 +#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 +#: catalog/objectaddress.c:2527 #, c-format msgid "permission denied" msgstr "권한 없음" -#: catalog/objectaddress.c:2551 catalog/objectaddress.c:2560 +#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 #, c-format msgid "The current user must have the %s attribute." msgstr "현재 사용자는 %s 속성이 있어야합니다." -#: catalog/objectaddress.c:2566 +#: catalog/objectaddress.c:2528 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "현재 사용자는 %s 옵션을 지정해야함, 해당 롤: \"%s\"" -#: catalog/objectaddress.c:2580 +#: catalog/objectaddress.c:2542 #, c-format msgid "must be superuser" msgstr "슈퍼유져여야함" -#: catalog/objectaddress.c:2649 +#: catalog/objectaddress.c:2611 #, c-format msgid "unrecognized object type \"%s\"" msgstr "알 수 없는 개체 형태 \"%s\"" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2941 +#: catalog/objectaddress.c:2928 #, c-format msgid "column %s of %s" msgstr " %s 칼럼(%s 의)" -#: catalog/objectaddress.c:2956 +#: catalog/objectaddress.c:2943 #, c-format msgid "function %s" msgstr "%s 함수" -#: catalog/objectaddress.c:2969 +#: catalog/objectaddress.c:2956 #, c-format msgid "type %s" msgstr "%s 자료형" -#: catalog/objectaddress.c:3006 +#: catalog/objectaddress.c:2993 #, c-format msgid "cast from %s to %s" msgstr "%s 자료형을 %s 자료형으로 바꾸는 작업" -#: catalog/objectaddress.c:3039 +#: catalog/objectaddress.c:3026 #, c-format msgid "collation %s" msgstr "collation %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3057 #, c-format msgid "constraint %s on %s" msgstr "%s 제약 조건(해당 개체: %s)" -#: catalog/objectaddress.c:3076 +#: catalog/objectaddress.c:3063 #, c-format msgid "constraint %s" msgstr "%s 제약 조건" -#: catalog/objectaddress.c:3108 +#: catalog/objectaddress.c:3095 #, c-format msgid "conversion %s" msgstr "%s 문자코드변환규칙" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3130 +#: catalog/objectaddress.c:3117 #, c-format msgid "default value for %s" msgstr "%s 용 기본값" -#: catalog/objectaddress.c:3141 +#: catalog/objectaddress.c:3128 #, c-format msgid "language %s" msgstr "프로시주얼 언어 %s" -#: catalog/objectaddress.c:3149 +#: catalog/objectaddress.c:3136 #, c-format msgid "large object %u" msgstr "%u 대형 개체" -#: catalog/objectaddress.c:3162 +#: catalog/objectaddress.c:3149 #, c-format msgid "operator %s" msgstr "%s 연산자" -#: catalog/objectaddress.c:3199 +#: catalog/objectaddress.c:3186 #, c-format msgid "operator class %s for access method %s" msgstr "%s 연산자 클래스, %s 인덱스 액세스 방법" -#: catalog/objectaddress.c:3227 +#: catalog/objectaddress.c:3214 #, c-format msgid "access method %s" msgstr "%s 접근 방법" @@ -5614,7 +6008,7 @@ msgstr "%s 접근 방법" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3276 +#: catalog/objectaddress.c:3269 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "%d (%s, %s) 연산자 (연산자 패밀리: %s): %s" @@ -5623,239 +6017,239 @@ msgstr "%d (%s, %s) 연산자 (연산자 패밀리: %s): %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3333 +#: catalog/objectaddress.c:3334 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "%d (%s, %s) 함수 (연산자 패밀리: %s): %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3385 +#: catalog/objectaddress.c:3388 #, c-format msgid "rule %s on %s" msgstr "%s 룰(rule), 해당 테이블: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3431 +#: catalog/objectaddress.c:3434 #, c-format msgid "trigger %s on %s" msgstr "%s 트리거, 해당 테이블: %s" -#: catalog/objectaddress.c:3451 +#: catalog/objectaddress.c:3454 #, c-format msgid "schema %s" msgstr "%s 스키마" -#: catalog/objectaddress.c:3479 +#: catalog/objectaddress.c:3482 #, c-format msgid "statistics object %s" msgstr "%s 통계정보 개체" -#: catalog/objectaddress.c:3510 +#: catalog/objectaddress.c:3513 #, c-format msgid "text search parser %s" msgstr "%s 전문 검색 파서" -#: catalog/objectaddress.c:3541 +#: catalog/objectaddress.c:3544 #, c-format msgid "text search dictionary %s" msgstr "%s 전문 검색 사전" -#: catalog/objectaddress.c:3572 +#: catalog/objectaddress.c:3575 #, c-format msgid "text search template %s" msgstr "%s 전문 검색 템플릿" -#: catalog/objectaddress.c:3603 +#: catalog/objectaddress.c:3606 #, c-format msgid "text search configuration %s" msgstr "%s 전문 검색 구성" -#: catalog/objectaddress.c:3616 +#: catalog/objectaddress.c:3619 #, c-format msgid "role %s" msgstr "%s 롤" -#: catalog/objectaddress.c:3653 catalog/objectaddress.c:5505 +#: catalog/objectaddress.c:3656 catalog/objectaddress.c:5505 #, c-format msgid "membership of role %s in role %s" msgstr "%s 롤 구성원(해당 롤: %s)" -#: catalog/objectaddress.c:3674 +#: catalog/objectaddress.c:3677 #, c-format msgid "database %s" msgstr "%s 데이터베이스" -#: catalog/objectaddress.c:3690 +#: catalog/objectaddress.c:3693 #, c-format msgid "tablespace %s" msgstr "%s 테이블스페이스" -#: catalog/objectaddress.c:3701 +#: catalog/objectaddress.c:3704 #, c-format msgid "foreign-data wrapper %s" msgstr "%s 외부 데이터 래퍼" -#: catalog/objectaddress.c:3711 +#: catalog/objectaddress.c:3714 #, c-format msgid "server %s" msgstr "%s 서버" -#: catalog/objectaddress.c:3744 +#: catalog/objectaddress.c:3747 #, c-format msgid "user mapping for %s on server %s" msgstr "%s에 대한 사용자 매핑, 해당 서버: %s" -#: catalog/objectaddress.c:3796 +#: catalog/objectaddress.c:3799 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "" "%s 롤(해당 스키마: %s)이 새 테이블을 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3800 +#: catalog/objectaddress.c:3803 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "%s 롤이 새 테이블을 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3806 +#: catalog/objectaddress.c:3809 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "" "%s 롤(해당 스키마: %s)이 새 시퀀스를 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3810 +#: catalog/objectaddress.c:3813 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "%s 롤이 새 시퀀스를 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3816 +#: catalog/objectaddress.c:3819 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "%s 롤(해당 스키마: %s)이 새 함수를 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3820 +#: catalog/objectaddress.c:3823 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "%s 롤이 새 함수를 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3826 +#: catalog/objectaddress.c:3829 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "" "%s 롤(해당 스키마: %s)이 새 자료형을 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3830 +#: catalog/objectaddress.c:3833 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "%s 롤이 새 자료형을 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3836 +#: catalog/objectaddress.c:3839 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "%s 롤이 새 시퀀스를 만들 때 기본적으로 지정할 접근 권한" -#: catalog/objectaddress.c:3843 +#: catalog/objectaddress.c:3846 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "%s 롤(해당 스키마: %s)의 기본 접근 권한" -#: catalog/objectaddress.c:3847 +#: catalog/objectaddress.c:3850 #, c-format msgid "default privileges belonging to role %s" msgstr "%s 롤의 기본 접근 권한" -#: catalog/objectaddress.c:3869 +#: catalog/objectaddress.c:3872 #, c-format msgid "extension %s" msgstr "%s 확장 모듈" -#: catalog/objectaddress.c:3886 +#: catalog/objectaddress.c:3889 #, c-format msgid "event trigger %s" msgstr "%s 이벤트 트리거" -#: catalog/objectaddress.c:3910 +#: catalog/objectaddress.c:3913 #, c-format msgid "parameter %s" msgstr "매개 변수 %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3953 +#: catalog/objectaddress.c:3956 #, c-format msgid "policy %s on %s" msgstr "%s 정책(%s 의)" -#: catalog/objectaddress.c:3967 +#: catalog/objectaddress.c:3970 #, c-format msgid "publication %s" msgstr "%s 발행" -#: catalog/objectaddress.c:3980 +#: catalog/objectaddress.c:3983 #, c-format msgid "publication of schema %s in publication %s" msgstr "%s 스키마 발행 (해당 발행이름: %s)" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:4011 +#: catalog/objectaddress.c:4014 #, c-format msgid "publication of %s in publication %s" msgstr "%s 발행 (해당 발행이름: %s)" -#: catalog/objectaddress.c:4024 +#: catalog/objectaddress.c:4027 #, c-format msgid "subscription %s" msgstr "%s 구독" -#: catalog/objectaddress.c:4045 +#: catalog/objectaddress.c:4048 #, c-format msgid "transform for %s language %s" msgstr "%s 형 변환자, 대상언어: %s" -#: catalog/objectaddress.c:4116 +#: catalog/objectaddress.c:4117 #, c-format msgid "table %s" msgstr "%s 테이블" -#: catalog/objectaddress.c:4121 +#: catalog/objectaddress.c:4122 #, c-format msgid "index %s" msgstr "%s 인덱스" -#: catalog/objectaddress.c:4125 +#: catalog/objectaddress.c:4126 #, c-format msgid "sequence %s" msgstr "%s 시퀀스" -#: catalog/objectaddress.c:4129 +#: catalog/objectaddress.c:4130 #, c-format msgid "toast table %s" msgstr "%s 토스트 테이블" -#: catalog/objectaddress.c:4133 +#: catalog/objectaddress.c:4134 #, c-format msgid "view %s" msgstr "%s 뷰" -#: catalog/objectaddress.c:4137 +#: catalog/objectaddress.c:4138 #, c-format msgid "materialized view %s" msgstr "%s 구체화된 뷰" -#: catalog/objectaddress.c:4141 +#: catalog/objectaddress.c:4142 #, c-format msgid "composite type %s" msgstr "%s 복합 자료형" -#: catalog/objectaddress.c:4145 +#: catalog/objectaddress.c:4146 #, c-format msgid "foreign table %s" msgstr "%s 외부 테이블" -#: catalog/objectaddress.c:4150 +#: catalog/objectaddress.c:4151 #, c-format msgid "relation %s" msgstr "%s 릴레이션" -#: catalog/objectaddress.c:4191 +#: catalog/objectaddress.c:4192 #, c-format msgid "operator family %s for access method %s" msgstr "%s 연산자 페밀리, 접근 방법: %s" @@ -5904,7 +6298,7 @@ msgstr "" msgid "return type of inverse transition function %s is not %s" msgstr "%s inverse transition 함수의 반환 자료형이 %s 형이 아닙니다." -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3009 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2991 #, c-format msgid "" "strictness of aggregate's forward and inverse transition functions must match" @@ -5920,7 +6314,7 @@ msgstr "부가 인자를 쓰는 마침 함수는 STRICT 옵션이 없어야 함" msgid "return type of combine function %s is not %s" msgstr "%s combine 함수의 반환 자료형이 %s 형이 아닙니다" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3903 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "" @@ -5936,12 +6330,12 @@ msgstr "%s serialization 함수의 반환 자료형이 %s 형이 아닙니다." msgid "return type of deserialization function %s is not %s" msgstr "%s deserialization 함수의 반환 자료형이 %s 형이 아닙니다" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:191 catalog/pg_proc.c:225 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 #, c-format msgid "cannot determine result data type" msgstr "결과 자료형을 결정할 수 없음" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:204 catalog/pg_proc.c:233 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "\"internal\" 의사-자료형의 사용이 안전하지 않습니다" @@ -5960,7 +6354,7 @@ msgstr "" msgid "sort operator can only be specified for single-argument aggregates" msgstr "정렬 연산자는 단일 인자 집계에만 지정할 수 있음" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:386 +#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 #, c-format msgid "cannot change routine kind" msgstr "루틴 종류를 바꿀 수 없음" @@ -5985,13 +6379,13 @@ msgstr "\"%s\" 함수는 가상 집합 집계 함수입니다." msgid "cannot change number of direct arguments of an aggregate function" msgstr "집계 함수의 direct 인자 번호는 바꿀 수 없음" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:691 -#: commands/typecmds.c:1975 commands/typecmds.c:2021 commands/typecmds.c:2073 -#: commands/typecmds.c:2110 commands/typecmds.c:2144 commands/typecmds.c:2178 -#: commands/typecmds.c:2212 commands/typecmds.c:2241 commands/typecmds.c:2328 -#: commands/typecmds.c:2370 parser/parse_func.c:417 parser/parse_func.c:448 +#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 +#: commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 +#: commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 +#: commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 +#: commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 #: parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 -#: parser/parse_func.c:631 parser/parse_func.c:2171 parser/parse_func.c:2444 +#: parser/parse_func.c:631 parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "%s 이름의 함수가 없음" @@ -6066,67 +6460,67 @@ msgstr "이 작업은 파티션 된 테이블 대상으로 지원하지 않습 msgid "This operation is not supported for partitioned indexes." msgstr "이 작업은 파티션 된 인덱스 대상으로 지원하지 않습니다." -#: catalog/pg_collation.c:102 catalog/pg_collation.c:160 +#: catalog/pg_collation.c:101 catalog/pg_collation.c:159 #, c-format msgid "collation \"%s\" already exists, skipping" msgstr "\"%s\" 이름의 정렬규칙이 이미 있습니다, 건너뜀" -#: catalog/pg_collation.c:104 +#: catalog/pg_collation.c:103 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists, skipping" msgstr "\"%s\" 정렬규칙이 \"%s\" 인코딩에 이미 지정되어 있습니다, 건너뜀" -#: catalog/pg_collation.c:112 catalog/pg_collation.c:167 +#: catalog/pg_collation.c:111 catalog/pg_collation.c:166 #, c-format msgid "collation \"%s\" already exists" msgstr "\"%s\" 정렬규칙이 이미 있습니다" -#: catalog/pg_collation.c:114 +#: catalog/pg_collation.c:113 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "\"%s\" 정렬규칙이 \"%s\" 인코딩에 이미 지정되어 있습니다" -#: catalog/pg_constraint.c:690 +#: catalog/pg_constraint.c:732 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "\"%s\" 제약 조건이 %s 도메인에 이미 지정되어 있습니다" -#: catalog/pg_constraint.c:890 catalog/pg_constraint.c:983 +#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "\"%s\" 제약 조건은 \"%s\" 테이블에 없음" -#: catalog/pg_constraint.c:1083 +#: catalog/pg_constraint.c:1125 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "\"%s\" 제약 조건은 %s 도메인에 없음" -#: catalog/pg_conversion.c:67 +#: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" msgstr "\"%s\" 이름의 변환규칙(conversion)이 이미 있음" -#: catalog/pg_conversion.c:80 +#: catalog/pg_conversion.c:77 #, c-format msgid "default conversion for %s to %s already exists" msgstr "%s 코드에서 %s 코드로 변환하는 기본 변환규칙(conversion)은 이미 있음" -#: catalog/pg_depend.c:222 commands/extension.c:3368 +#: catalog/pg_depend.c:224 commands/extension.c:3397 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "%s 개체는 \"%s\" 확장모듈에 이미 구성원입니다" -#: catalog/pg_depend.c:229 catalog/pg_depend.c:280 commands/extension.c:3408 +#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "\"%s\" 개체는 \"%s\" 확장 모듈의 구성 요소가 아닙니다" -#: catalog/pg_depend.c:232 +#: catalog/pg_depend.c:234 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "확장 모듈이 자기 소유 객체가 아닌 객체를 덮어 쓸 수는 없습니다." -#: catalog/pg_depend.c:283 +#: catalog/pg_depend.c:285 #, c-format msgid "" "An extension may only use CREATE ... IF NOT EXISTS to skip object creation " @@ -6135,53 +6529,53 @@ msgstr "" "이미 있는 객체와 충돌을 피하기 위해 이미 있는 객체 생성을 건너뛰려면, 확장 모" "듈에서 CREATE ... IF NOT EXISTS 구문을 사용해야합니다." -#: catalog/pg_depend.c:646 +#: catalog/pg_depend.c:648 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "%s 객체가 시스템 객체이기 때문에 의존성을 없앨 수 없습니다." -#: catalog/pg_enum.c:137 catalog/pg_enum.c:259 catalog/pg_enum.c:554 +#: catalog/pg_enum.c:175 catalog/pg_enum.c:314 catalog/pg_enum.c:624 #, c-format msgid "invalid enum label \"%s\"" msgstr "\"%s\" 열거형 라벨이 잘못됨" -#: catalog/pg_enum.c:138 catalog/pg_enum.c:260 catalog/pg_enum.c:555 +#: catalog/pg_enum.c:176 catalog/pg_enum.c:315 catalog/pg_enum.c:625 #, c-format msgid "Labels must be %d bytes or less." msgstr "라벨은 %d 바이트 이하여야 합니다." -#: catalog/pg_enum.c:288 +#: catalog/pg_enum.c:343 #, c-format msgid "enum label \"%s\" already exists, skipping" msgstr "\"%s\" 이름의 열거형 라벨이 이미 있음, 건너뜀" -#: catalog/pg_enum.c:295 catalog/pg_enum.c:598 +#: catalog/pg_enum.c:350 catalog/pg_enum.c:668 #, c-format msgid "enum label \"%s\" already exists" msgstr "\"%s\" 이름의 열거형 라벨이 이미 있음" -#: catalog/pg_enum.c:350 catalog/pg_enum.c:593 +#: catalog/pg_enum.c:405 catalog/pg_enum.c:663 #, c-format msgid "\"%s\" is not an existing enum label" msgstr "\"%s\" 열거형 라벨이 없음" -#: catalog/pg_enum.c:408 +#: catalog/pg_enum.c:463 #, c-format msgid "pg_enum OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때 pg_enum OID 값이 지정되지 않았습니다" -#: catalog/pg_enum.c:418 +#: catalog/pg_enum.c:473 #, c-format msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade" msgstr "" "ALTER TYPE ADD BEFORE/AFTER 구문은 이진 업그레이드 작업에서 호환하지 않습니다" -#: catalog/pg_inherits.c:593 +#: catalog/pg_inherits.c:592 #, c-format msgid "cannot detach partition \"%s\"" msgstr "\"%s\" 하위 파티션 테이블을 뗄 수 없음" -#: catalog/pg_inherits.c:595 +#: catalog/pg_inherits.c:594 #, c-format msgid "" "The partition is being detached concurrently or has an unfinished detach." @@ -6189,8 +6583,8 @@ msgstr "" "이 파티션은 이미 concurrently 옵션을 사용해서 떼기 작업을 했거나, 아직 떼기" "가 안 끝났습니다." -#: catalog/pg_inherits.c:596 commands/tablecmds.c:4583 -#: commands/tablecmds.c:15464 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4800 +#: commands/tablecmds.c:16153 #, c-format msgid "" "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending " @@ -6199,12 +6593,12 @@ msgstr "" "보류 중인 떼기를 마치려면, ALTER TABLE ... DETACH PARTITION ... FINALIZE 명령" "을 사용하세요." -#: catalog/pg_inherits.c:600 +#: catalog/pg_inherits.c:599 #, c-format msgid "cannot complete detaching partition \"%s\"" msgstr "\"%s\" 파티션 떼기를 끝낼 수 없습니다" -#: catalog/pg_inherits.c:602 +#: catalog/pg_inherits.c:601 #, c-format msgid "There's no pending concurrent detach." msgstr "현재 보류 중인 떼기 작업이 없습니다." @@ -6214,113 +6608,128 @@ msgstr "현재 보류 중인 떼기 작업이 없습니다." msgid "schema \"%s\" already exists" msgstr "\"%s\" 이름의 스키마(schema)가 이미 있음" -#: catalog/pg_operator.c:219 catalog/pg_operator.c:361 +#: catalog/pg_operator.c:213 catalog/pg_operator.c:355 #, c-format msgid "\"%s\" is not a valid operator name" msgstr "\"%s\" 타당한 연산자 이름이 아님" -#: catalog/pg_operator.c:370 +#: catalog/pg_operator.c:379 +#, c-format +msgid "operator %s already exists" +msgstr "%s 연산자가 이미 있음" + +#: catalog/pg_operator.c:445 commands/operatorcmds.c:600 +#, c-format +msgid "operator cannot be its own negator" +msgstr "연산자는 자신의 negator 연산자가 될 수 없음" + +#: catalog/pg_operator.c:572 #, c-format msgid "only binary operators can have commutators" msgstr "바이너리 연산자만이 commutator를 가질 수 있음" -#: catalog/pg_operator.c:374 commands/operatorcmds.c:509 +#: catalog/pg_operator.c:576 #, c-format msgid "only binary operators can have join selectivity" msgstr "바이너리 연산자만이 join selectivity를 가질 수 있음" -#: catalog/pg_operator.c:378 +#: catalog/pg_operator.c:580 #, c-format msgid "only binary operators can merge join" msgstr "바이너리 연산자만이 merge join할 수 있음" -#: catalog/pg_operator.c:382 +#: catalog/pg_operator.c:584 #, c-format msgid "only binary operators can hash" msgstr "바이너리 연산자만이 해시할 수 있음" -#: catalog/pg_operator.c:393 +#: catalog/pg_operator.c:593 #, c-format msgid "only boolean operators can have negators" msgstr "불리언 연산자만 부정어를 포함할 수 있음" -#: catalog/pg_operator.c:397 commands/operatorcmds.c:517 +#: catalog/pg_operator.c:597 #, c-format msgid "only boolean operators can have restriction selectivity" msgstr "불리언 연산자만 제한 선택을 포함할 수 있음" -#: catalog/pg_operator.c:401 commands/operatorcmds.c:521 +#: catalog/pg_operator.c:601 #, c-format msgid "only boolean operators can have join selectivity" msgstr "불리언 연산자만 조인 선택을 포함할 수 있음" -#: catalog/pg_operator.c:405 +#: catalog/pg_operator.c:605 #, c-format msgid "only boolean operators can merge join" msgstr "불리언 연산자만 머지 조인을 지정할 수 있음" -#: catalog/pg_operator.c:409 +#: catalog/pg_operator.c:609 #, c-format msgid "only boolean operators can hash" msgstr "불리언 연산자만 해시를 지정할 수 있음" -#: catalog/pg_operator.c:421 +#: catalog/pg_operator.c:739 #, c-format -msgid "operator %s already exists" -msgstr "%s 연산자가 이미 있음" +msgid "commutator operator %s is already the commutator of operator %s" +msgstr "%s commutator 연산자는 이미 %s 연산자의 commutator임" -#: catalog/pg_operator.c:621 +#: catalog/pg_operator.c:744 #, c-format -msgid "operator cannot be its own negator or sort operator" -msgstr "연산자는 자신의 negator나 sort 연산자가 될 수 없습니다" +msgid "commutator operator %s is already the commutator of operator %u" +msgstr "%s commutator 연산자는 이미 %u 연산자의 commutator임" -#: catalog/pg_parameter_acl.c:53 +#: catalog/pg_operator.c:807 #, c-format -msgid "parameter ACL \"%s\" does not exist" -msgstr "\"%s\" 매개 변수 ACL이 없음" +msgid "negator operator %s is already the negator of operator %s" +msgstr "%s negator 연산자는 이미 %s 연산자의 negator임" + +#: catalog/pg_operator.c:812 +#, c-format +msgid "negator operator %s is already the negator of operator %u" +msgstr "%s negator 연산자는 이미 %u 연산자의 negator임" -#: catalog/pg_parameter_acl.c:88 +#: catalog/pg_parameter_acl.c:50 #, c-format -msgid "invalid parameter name \"%s\"" -msgstr "\"%s\" 이름은 잘못된 매개 변수 이름입니다." +msgid "parameter ACL \"%s\" does not exist" +msgstr "\"%s\" 매개 변수 ACL이 없음" -#: catalog/pg_proc.c:132 parser/parse_func.c:2233 +#: catalog/pg_proc.c:130 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" msgstr[0] "함수는 %d개 이상의 인자를 사용할 수 없음" -#: catalog/pg_proc.c:376 +#: catalog/pg_proc.c:374 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "이미 같은 인자 자료형을 사용하는 \"%s\" 함수가 있습니다" -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:386 #, c-format msgid "\"%s\" is an aggregate function." msgstr "\"%s\" 개체는 집계 함수입니다" -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:388 #, c-format msgid "\"%s\" is a function." msgstr "\"%s\" 개체는 함수입니다." -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:390 #, c-format msgid "\"%s\" is a procedure." msgstr "\"%s\" 개체는 프로시져입니다." -#: catalog/pg_proc.c:394 +#: catalog/pg_proc.c:392 #, c-format msgid "\"%s\" is a window function." msgstr "\"%s\" 개체는 윈도우 함수입니다." -#: catalog/pg_proc.c:414 +#: catalog/pg_proc.c:412 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "프로시져는 출력 매개 변수를 사용하도록 변경 할 수 없음" -#: catalog/pg_proc.c:415 catalog/pg_proc.c:445 +#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 #, c-format msgid "cannot change return type of existing function" msgstr "이미 있는 함수의 리턴 자료형은 바꿀 수 없습니다" @@ -6329,115 +6738,115 @@ msgstr "이미 있는 함수의 리턴 자료형은 바꿀 수 없습니다" #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:421 catalog/pg_proc.c:448 catalog/pg_proc.c:493 -#: catalog/pg_proc.c:519 catalog/pg_proc.c:543 +#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 +#: catalog/pg_proc.c:517 catalog/pg_proc.c:541 #, c-format msgid "Use %s %s first." msgstr "먼저 %s %s 명령을 사용하세요." -#: catalog/pg_proc.c:446 +#: catalog/pg_proc.c:444 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "OUT 매개 변수에 정의된 행 형식이 다릅니다." -#: catalog/pg_proc.c:490 +#: catalog/pg_proc.c:488 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "\"%s\" 입력 매개 변수 이름을 바꿀 수 없음" -#: catalog/pg_proc.c:517 +#: catalog/pg_proc.c:515 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "기존 함수에서 매개 변수 기본 값을 제거할 수 없음" -#: catalog/pg_proc.c:541 +#: catalog/pg_proc.c:539 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "기존 매개 변수 기본 값의 데이터 형식을 바꿀 수 없음" -#: catalog/pg_proc.c:752 +#: catalog/pg_proc.c:750 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "\"%s\" 이름의 내장 함수가 없음" -#: catalog/pg_proc.c:845 +#: catalog/pg_proc.c:843 #, c-format msgid "SQL functions cannot return type %s" msgstr "SQL 함수는 %s 자료형을 리턴할 수 없음" -#: catalog/pg_proc.c:860 +#: catalog/pg_proc.c:858 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "SQL 함수의 인자로 %s 자료형은 사용될 수 없습니다" -#: catalog/pg_proc.c:987 executor/functions.c:1466 +#: catalog/pg_proc.c:986 executor/functions.c:1468 #, c-format msgid "SQL function \"%s\"" msgstr "\"%s\" SQL 함수" -#: catalog/pg_publication.c:71 catalog/pg_publication.c:79 -#: catalog/pg_publication.c:87 catalog/pg_publication.c:93 +#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 +#: catalog/pg_publication.c:82 catalog/pg_publication.c:88 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "\"%s\" 릴레이션을 발행에 추가할 수 없음" -#: catalog/pg_publication.c:81 +#: catalog/pg_publication.c:76 #, c-format msgid "This operation is not supported for system tables." msgstr "이 작업은 시스템 테이블 대상으로 지원하지 않습니다." -#: catalog/pg_publication.c:89 +#: catalog/pg_publication.c:84 #, c-format msgid "This operation is not supported for temporary tables." msgstr "이 작업은 임시 테이블 대상으로 지원하지 않습니다." -#: catalog/pg_publication.c:95 +#: catalog/pg_publication.c:90 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "이 작업은 언로그드 테이블 대상으로 지원하지 않습니다." -#: catalog/pg_publication.c:109 catalog/pg_publication.c:117 +#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "\"%s\" 스키마를 발행에 추가할 수 없음" -#: catalog/pg_publication.c:111 +#: catalog/pg_publication.c:106 #, c-format msgid "This operation is not supported for system schemas." msgstr "이 작업은 시스템 스키마 대상으로 지원하지 않습니다." -#: catalog/pg_publication.c:119 +#: catalog/pg_publication.c:114 #, c-format msgid "Temporary schemas cannot be replicated." msgstr "임시 스키마는 복제할 수 없습니다." -#: catalog/pg_publication.c:397 +#: catalog/pg_publication.c:392 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "\"%s\" 릴레이션은 이미 \"%s\" 발행에 포함되어 있습니다" -#: catalog/pg_publication.c:539 +#: catalog/pg_publication.c:534 #, c-format msgid "cannot use system column \"%s\" in publication column list" msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. 발행 칼럼 목록에 포함될 수 없습니다." -#: catalog/pg_publication.c:545 +#: catalog/pg_publication.c:540 #, c-format msgid "cannot use generated column \"%s\" in publication column list" msgstr "" "\"%s\" 칼럼은 미리 계산된 칼럼으로 발행 칼럼 목록에 포함될 수 없습니다." -#: catalog/pg_publication.c:551 +#: catalog/pg_publication.c:546 #, c-format msgid "duplicate column \"%s\" in publication column list" msgstr "\"%s\" 칼럼이 발행 칼럼 목록에 중복 되었습니다." -#: catalog/pg_publication.c:641 +#: catalog/pg_publication.c:636 #, c-format msgid "schema \"%s\" is already member of publication \"%s\"" msgstr "\"%s\" 스키마는 이미 \"%s\" 발행에 포함되어 있습니다" -#: catalog/pg_shdepend.c:830 +#: catalog/pg_shdepend.c:875 #, c-format msgid "" "\n" @@ -6446,50 +6855,57 @@ msgid_plural "" "\n" "and objects in %d other databases (see server log for list)" msgstr[0] "" +"\n" +", %d개의 다른 데이터테이스 소속 객체들 (목록은 서버 로그 참조)" -#: catalog/pg_shdepend.c:1177 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "%u 롤이 동시에 삭제되었음" -#: catalog/pg_shdepend.c:1189 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "%u 테이블스페이스는 현재 삭제되었습니다" -#: catalog/pg_shdepend.c:1203 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "%u 데이터베이스는 현재 삭제되었습니다" -#: catalog/pg_shdepend.c:1254 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "%s 개체의 소유주" -#: catalog/pg_shdepend.c:1256 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" -msgstr "\"%s\"에 대한 권한" +msgstr "%s에 대한 권한" + +#: catalog/pg_shdepend.c:1303 +#, c-format +msgid "initial privileges for %s" +msgstr "%s에 대한 초기 권한" -#: catalog/pg_shdepend.c:1258 +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "%s 개체 대상" -#: catalog/pg_shdepend.c:1260 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "%s 용 테이블스페이스" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1268 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" msgstr[0] "%d 개체(데이터베이스: %s)" -#: catalog/pg_shdepend.c:1332 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "" "cannot drop objects owned by %s because they are required by the database " @@ -6498,7 +6914,7 @@ msgstr "" "%s 소유주의 개체 삭제는 그 데이터베이스 시스템에서 필요하기 때문에 삭제 될 " "수 없음" -#: catalog/pg_shdepend.c:1498 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "" "cannot reassign ownership of objects owned by %s because they are required " @@ -6507,22 +6923,22 @@ msgstr "" "%s 소유주의 개체 삭제는 그 데이터베이스 시스템에서 필요하기 때문에 삭제 될 " "수 없음" -#: catalog/pg_subscription.c:424 +#: catalog/pg_subscription.c:438 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "\"%s\" 구독용 릴레이션 맵핑 삭제 실패" -#: catalog/pg_subscription.c:426 +#: catalog/pg_subscription.c:440 #, c-format msgid "" -"Table synchronization for relation \"%s\" is in progress and is in state \"%c" -"\"." +"Table synchronization for relation \"%s\" is in progress and is in state " +"\"%c\"." msgstr "\"%s\" 릴레이션의 동기화 작업은 현재 진행중이고, 상태가 \"%c\" 임." #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:433 +#: catalog/pg_subscription.c:447 #, c-format msgid "" "Use %s to enable subscription if not already enabled or use %s to drop the " @@ -6531,43 +6947,43 @@ msgstr "" "아직 활성화되지 않은 구독을 활성화 하기위해 %s 명령을 이용하거나, 해당 구독" "을 지우려면 %s 명령을 이용하세요." -#: catalog/pg_type.c:134 catalog/pg_type.c:474 +#: catalog/pg_type.c:133 catalog/pg_type.c:474 #, c-format msgid "pg_type OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때 pg_type OID 값이 지정되지 않았습니다" -#: catalog/pg_type.c:254 +#: catalog/pg_type.c:253 #, c-format msgid "invalid type internal size %d" msgstr "잘못된 자료형의 내부 크기 %d" -#: catalog/pg_type.c:270 catalog/pg_type.c:278 catalog/pg_type.c:286 -#: catalog/pg_type.c:295 +#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285 +#: catalog/pg_type.c:294 #, c-format msgid "alignment \"%c\" is invalid for passed-by-value type of size %d" msgstr "\"%c\" 정렬은 크기가 %d인 전달 값 형식에 유효하지 않음" -#: catalog/pg_type.c:302 +#: catalog/pg_type.c:301 #, c-format msgid "internal size %d is invalid for passed-by-value type" msgstr "내부 크기 %d은(는) 전달 값 형식에 유효하지 않음" -#: catalog/pg_type.c:312 catalog/pg_type.c:318 +#: catalog/pg_type.c:311 catalog/pg_type.c:317 #, c-format msgid "alignment \"%c\" is invalid for variable-length type" msgstr "\"%c\" 정렬은 가변 길이 형식에 유효하지 않음" -#: catalog/pg_type.c:326 commands/typecmds.c:4140 +#: catalog/pg_type.c:325 commands/typecmds.c:4363 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "_^_ 고정크기 자료형은 PLAIN 저장방법을 가져야만 합니다" -#: catalog/pg_type.c:955 +#: catalog/pg_type.c:978 #, c-format msgid "Failed while creating a multirange type for type \"%s\"." msgstr "\"%s\" 자료형용 다중 범위 자료형를 만들기 실패." -#: catalog/pg_type.c:956 +#: catalog/pg_type.c:979 #, c-format msgid "" "You can manually specify a multirange type name using the " @@ -6576,180 +6992,180 @@ msgstr "" "\"multirange_type_name\" 속성을 사용해서 이 다중 범위 자료형 이름을 직접 지정" "하세요." -#: catalog/storage.c:505 storage/buffer/bufmgr.c:1145 +#: catalog/storage.c:533 storage/buffer/bufmgr.c:1540 #, c-format msgid "invalid page in block %u of relation %s" msgstr "%u 블록(해당 릴레이션: %s)에 잘못된 페이지가 있음" -#: commands/aggregatecmds.c:171 +#: commands/aggregatecmds.c:167 #, c-format msgid "only ordered-set aggregates can be hypothetical" msgstr "순서 있는 집합 집계함수만 가상 집합 집계 함수로 쓸 수 있습니다." -#: commands/aggregatecmds.c:196 +#: commands/aggregatecmds.c:192 #, c-format msgid "aggregate attribute \"%s\" not recognized" msgstr "\"%s\" 속성을 aggregate에서 알 수 없음" -#: commands/aggregatecmds.c:206 +#: commands/aggregatecmds.c:202 #, c-format msgid "aggregate stype must be specified" msgstr "aggregate stype 값을 지정하셔야 합니다" -#: commands/aggregatecmds.c:210 +#: commands/aggregatecmds.c:206 #, c-format msgid "aggregate sfunc must be specified" msgstr "aggregate sfunc 값을 지정하셔야 합니다" -#: commands/aggregatecmds.c:222 +#: commands/aggregatecmds.c:218 #, c-format msgid "aggregate msfunc must be specified when mstype is specified" msgstr "mstype 옵션을 사용하면 msfunc 옵션도 함께 지정 해야 함" -#: commands/aggregatecmds.c:226 +#: commands/aggregatecmds.c:222 #, c-format msgid "aggregate minvfunc must be specified when mstype is specified" msgstr "mstype 옵션을 사용하면 minvfunc 옵션도 함께 지정 해야 함" -#: commands/aggregatecmds.c:233 +#: commands/aggregatecmds.c:229 #, c-format msgid "aggregate msfunc must not be specified without mstype" msgstr "msfunc 옵션은 mstype 옵션과 함께 사용해야 함" -#: commands/aggregatecmds.c:237 +#: commands/aggregatecmds.c:233 #, c-format msgid "aggregate minvfunc must not be specified without mstype" msgstr "minvfunc 옵션은 mstype 옵션과 함께 사용해야 함" -#: commands/aggregatecmds.c:241 +#: commands/aggregatecmds.c:237 #, c-format msgid "aggregate mfinalfunc must not be specified without mstype" msgstr "mfinalfunc 옵션은 mstype 옵션과 함께 사용해야 함" -#: commands/aggregatecmds.c:245 +#: commands/aggregatecmds.c:241 #, c-format msgid "aggregate msspace must not be specified without mstype" msgstr "msspace 옵션은 mstype 옵션과 함께 사용해야 함" -#: commands/aggregatecmds.c:249 +#: commands/aggregatecmds.c:245 #, c-format msgid "aggregate minitcond must not be specified without mstype" msgstr "minitcond 옵션은 mstype 옵션과 함께 사용해야 함" -#: commands/aggregatecmds.c:278 +#: commands/aggregatecmds.c:274 #, c-format msgid "aggregate input type must be specified" msgstr "aggregate 입력 자료형을 지정해야 합니다" -#: commands/aggregatecmds.c:308 +#: commands/aggregatecmds.c:304 #, c-format msgid "basetype is redundant with aggregate input type specification" msgstr "집계 입력 형식 지정에서 basetype이 중복됨" -#: commands/aggregatecmds.c:351 commands/aggregatecmds.c:392 +#: commands/aggregatecmds.c:347 commands/aggregatecmds.c:388 #, c-format msgid "aggregate transition data type cannot be %s" msgstr "%s 자료형은 STYPE 자료형으로 사용할 수 없습니다" -#: commands/aggregatecmds.c:363 +#: commands/aggregatecmds.c:359 #, c-format msgid "" "serialization functions may be specified only when the aggregate transition " "data type is %s" msgstr "SERIALFUNC 함수는 STYPE 자료형이 %s 형일때만 지정할 수 있습니다." -#: commands/aggregatecmds.c:373 +#: commands/aggregatecmds.c:369 #, c-format msgid "" "must specify both or neither of serialization and deserialization functions" msgstr "" "SERIALFUNC, DESERIALFUNC 함수를 모두 지정하거나 모두 지정하지 않거나 하세요." -#: commands/aggregatecmds.c:438 commands/functioncmds.c:639 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "\"parallel\" 옵션 값은 SAFE, RESTRICTED, UNSAFE 만 지정할 수 있음" -#: commands/aggregatecmds.c:494 +#: commands/aggregatecmds.c:490 #, c-format msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "\"%s\" 인자값은 READ_ONLY, SHAREABLE, READ_WRITE 셋 중 하나여야 함" -#: commands/alter.c:86 commands/event_trigger.c:174 +#: commands/alter.c:83 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" msgstr "\"%s\" 이름의 이벤트 트리거가 이미 있음" -#: commands/alter.c:89 commands/foreigncmds.c:593 +#: commands/alter.c:86 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "\"%s\" 이름의 외부 자료 래퍼가 이미 있음" -#: commands/alter.c:92 commands/foreigncmds.c:884 +#: commands/alter.c:89 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "\"%s\" 이름의 서버가 이미 있음" -#: commands/alter.c:95 commands/proclang.c:133 +#: commands/alter.c:92 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "\"%s\" 이름의 프로시주얼 언어가 이미 있습니다" -#: commands/alter.c:98 commands/publicationcmds.c:771 +#: commands/alter.c:95 commands/publicationcmds.c:764 #, c-format msgid "publication \"%s\" already exists" msgstr "\"%s\" 이름의 발행이 이미 있습니다" -#: commands/alter.c:101 commands/subscriptioncmds.c:657 +#: commands/alter.c:98 commands/subscriptioncmds.c:669 #, c-format msgid "subscription \"%s\" already exists" msgstr "\"%s\" 이름의 구독이 이미 있습니다" -#: commands/alter.c:124 +#: commands/alter.c:121 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 이름의 변환규칙(conversin)이 \"%s\" 스키마에 이미 있습니다" -#: commands/alter.c:128 +#: commands/alter.c:125 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 이름의 통계정보 개체는 \"%s\" 스키마에 이미 있습니다" -#: commands/alter.c:132 +#: commands/alter.c:129 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 전문 검색 파서가 \"%s\" 스키마 안에 이미 있음" -#: commands/alter.c:136 +#: commands/alter.c:133 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 전문 검색 사전이 \"%s\" 스키마 안에 이미 있음" -#: commands/alter.c:140 +#: commands/alter.c:137 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 전문 검색 템플릿이 \"%s\" 스키마 안에 이미 있음" -#: commands/alter.c:144 +#: commands/alter.c:141 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 전문 검색 구성이 \"%s\" 스키마 안에 이미 있음" -#: commands/alter.c:217 +#: commands/alter.c:214 #, c-format msgid "must be superuser to rename %s" msgstr "%s 이름 변경 작업은 슈퍼유저만 할 수 있음" -#: commands/alter.c:259 commands/subscriptioncmds.c:636 -#: commands/subscriptioncmds.c:1116 commands/subscriptioncmds.c:1198 -#: commands/subscriptioncmds.c:1830 +#: commands/alter.c:256 commands/subscriptioncmds.c:648 +#: commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 +#: commands/subscriptioncmds.c:1918 #, c-format msgid "password_required=false is superuser-only" msgstr "password_required=false 는 슈퍼유저 전용임" -#: commands/alter.c:260 commands/subscriptioncmds.c:637 -#: commands/subscriptioncmds.c:1117 commands/subscriptioncmds.c:1199 -#: commands/subscriptioncmds.c:1831 +#: commands/alter.c:257 commands/subscriptioncmds.c:649 +#: commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 +#: commands/subscriptioncmds.c:1919 #, c-format msgid "" "Subscriptions with the password_required option set to false may only be " @@ -6758,7 +7174,7 @@ msgstr "" "구독 옵션으로 password_required 옵션값을 false 지정하거나 변경하는 것은 슈퍼" "유저만 할 수 있습니다." -#: commands/alter.c:775 +#: commands/alter.c:735 #, c-format msgid "must be superuser to set schema of %s" msgstr "%s의 스키마 지정은 슈퍼유져여야 합니다" @@ -6778,7 +7194,7 @@ msgstr "슈퍼유저만 접근 방법을 만들 수 있습니다." msgid "access method \"%s\" already exists" msgstr "\"%s\" 이름의 인덱스 접근 방법이 이미 있습니다." -#: commands/amcmds.c:154 commands/indexcmds.c:216 commands/indexcmds.c:839 +#: commands/amcmds.c:154 commands/indexcmds.c:224 commands/indexcmds.c:850 #: commands/opclasscmds.c:375 commands/opclasscmds.c:833 #, c-format msgid "access method \"%s\" does not exist" @@ -6789,45 +7205,45 @@ msgstr "\"%s\" 인덱스 접근 방법이 없습니다" msgid "handler function is not specified" msgstr "핸들러 함수 부분이 빠졌습니다" -#: commands/amcmds.c:264 commands/event_trigger.c:183 -#: commands/foreigncmds.c:489 commands/proclang.c:80 commands/trigger.c:709 -#: parser/parse_clause.c:941 +#: commands/amcmds.c:264 commands/event_trigger.c:200 +#: commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 +#: parser/parse_clause.c:943 #, c-format msgid "function %s must return type %s" msgstr "%s 함수는 %s 자료형을 반환해야 함" -#: commands/analyze.c:228 +#: commands/analyze.c:217 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "\"%s\" 건너뜀 --- 외부 테이블은 분석할 수 없음" -#: commands/analyze.c:245 +#: commands/analyze.c:234 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "" "\"%s\" 건너뜀 --- 테이블이 아니거나, 특수 시스템 테이블들은 분석할 수 없음" -#: commands/analyze.c:325 +#: commands/analyze.c:314 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "\"%s.%s\" 상속 관계 분석중" -#: commands/analyze.c:330 +#: commands/analyze.c:319 #, c-format msgid "analyzing \"%s.%s\"" msgstr "\"%s.%s\" 자료 통계 수집 중" -#: commands/analyze.c:395 +#: commands/analyze.c:385 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "\"%s\" 칼럼이 \"%s\" 릴레이션에서 두 번 이상 사용되었음" -#: commands/analyze.c:787 +#: commands/analyze.c:785 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "\"%s.%s.%s\" 테이블 자동 분석\n" -#: commands/analyze.c:1334 +#: commands/analyze.c:1300 #, c-format msgid "" "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead " @@ -6836,7 +7252,7 @@ msgstr "" "\"%s\": 탐색한 페이지: %d, 전체페이지: %u, 실자료: %.0f개, 쓰레기자료: %.0f" "개; 표본 추출 자료: %d개, 예상한 총 자료: %.0f개" -#: commands/analyze.c:1418 +#: commands/analyze.c:1384 #, c-format msgid "" "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree " @@ -6845,7 +7261,7 @@ msgstr "" "\"%s.%s\" 상속 나무의 통계 수집 건너뜀 --- 이 상속 나무에는 하위 테이블이 없" "음" -#: commands/analyze.c:1516 +#: commands/analyze.c:1482 #, c-format msgid "" "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree " @@ -6854,46 +7270,46 @@ msgstr "" "\"%s.%s\" 상속 나무의 통계 수집 건너뜀 --- 이 상속 나무에는 통계 수집할 하위 " "테이블이 없음" -#: commands/async.c:646 +#: commands/async.c:612 #, c-format msgid "channel name cannot be empty" msgstr "채널 이름은 비워둘 수 없음" -#: commands/async.c:652 +#: commands/async.c:618 #, c-format msgid "channel name too long" msgstr "채널 이름이 너무 긺" # # nonun 부분 begin -#: commands/async.c:657 +#: commands/async.c:623 #, c-format msgid "payload string too long" msgstr "payload 문자열이 너무 긺" -#: commands/async.c:876 +#: commands/async.c:842 #, c-format msgid "" "cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY" msgstr "" "LISTEN, UNLISTEN 또는 NOTIFY 옵션으로 실행된 트랜잭션을 PREPARE할 수 없음" -#: commands/async.c:980 +#: commands/async.c:946 #, c-format msgid "too many notifications in the NOTIFY queue" msgstr "NOTIFY 큐에 너무 많은 알림이 있습니다" -#: commands/async.c:1602 +#: commands/async.c:1553 #, c-format msgid "NOTIFY queue is %.0f%% full" msgstr "NOTIFY 큐 사용률: %.0f%%" -#: commands/async.c:1604 +#: commands/async.c:1555 #, c-format msgid "" "The server process with PID %d is among those with the oldest transactions." msgstr "%d PID 서버 프로세스가 가장 오래된 트랜잭션을 사용하고 있습니다." -#: commands/async.c:1607 +#: commands/async.c:1558 #, c-format msgid "" "The NOTIFY queue cannot be emptied until that process ends its current " @@ -6901,22 +7317,22 @@ msgid "" msgstr "" "이 프로세스의 현재 트랜잭션을 종료하지 않으면, NOTIFY 큐를 비울 수 없습니다" -#: commands/cluster.c:130 +#: commands/cluster.c:128 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "알 수 없는 CLUSTER 옵션 \"%s\"" -#: commands/cluster.c:160 commands/cluster.c:433 +#: commands/cluster.c:159 commands/cluster.c:433 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "다른 세션의 임시 테이블은 cluster 작업을 할 수 없습니다" -#: commands/cluster.c:178 +#: commands/cluster.c:177 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "\"%s\" 테이블을 위한 previously clustered 인덱스가 없음" -#: commands/cluster.c:192 commands/tablecmds.c:14200 commands/tablecmds.c:16043 +#: commands/cluster.c:191 commands/tablecmds.c:14797 commands/tablecmds.c:16729 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "\"%s\" 인덱스는 \"%s\" 테이블에 없음" @@ -6931,7 +7347,7 @@ msgstr "공유된 카탈로그는 클러스터 작업을 할 수 없음" msgid "cannot vacuum temporary tables of other sessions" msgstr "다른 세션의 임시 테이블은 vacuum 작업을 할 수 없음" -#: commands/cluster.c:513 commands/tablecmds.c:16053 +#: commands/cluster.c:513 commands/tablecmds.c:16739 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "\"%s\" 개체는 \"%s\" 테이블을 위한 인덱스가 아님" @@ -6960,22 +7376,22 @@ msgstr "잘못된 \"%s\" 인덱스에 대해 클러스터링할 수 없음" msgid "cannot mark index clustered in partitioned table" msgstr "파티션된 테이블 대상으로 인덱스 클러스터 표시를 할 수 없음" -#: commands/cluster.c:950 +#: commands/cluster.c:956 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr " \"%s.%s\" 클러스터링 중 (사용 인덱스: \"%s\")" -#: commands/cluster.c:956 +#: commands/cluster.c:962 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "순차 탐색과 정렬을 이용해서 \"%s.%s\" 개체 클러스터링 중" -#: commands/cluster.c:961 +#: commands/cluster.c:967 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "\"%s.%s\" 청소 중" -#: commands/cluster.c:988 +#: commands/cluster.c:994 #, c-format msgid "" "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" @@ -6983,7 +7399,7 @@ msgstr "" "\"%s.%s\": 삭제가능한 %.0f개, 삭제불가능한 %.0f개의 행 버전을 %u 페이지에서 " "발견했음." -#: commands/cluster.c:993 +#: commands/cluster.c:999 #, c-format msgid "" "%.0f dead row versions cannot be removed yet.\n" @@ -6992,33 +7408,39 @@ msgstr "" "%.0f 개의 사용하지 않는 로우 버전을 아직 지우지 못했음.\n" "%s." -#: commands/collationcmds.c:112 +#: commands/cluster.c:1744 +#, c-format +msgid "permission denied to cluster \"%s\", skipping it" +msgstr "\"%s\" 클러스터 권한 없음, 건너뜀" + +#: commands/collationcmds.c:110 #, c-format msgid "collation attribute \"%s\" not recognized" msgstr "\"%s\" 연산자 속성을 처리할 수 없음" -#: commands/collationcmds.c:125 commands/collationcmds.c:131 -#: commands/define.c:389 commands/tablecmds.c:7876 -#: replication/pgoutput/pgoutput.c:310 replication/pgoutput/pgoutput.c:333 -#: replication/pgoutput/pgoutput.c:347 replication/pgoutput/pgoutput.c:357 -#: replication/pgoutput/pgoutput.c:367 replication/pgoutput/pgoutput.c:377 -#: replication/pgoutput/pgoutput.c:387 replication/walsender.c:996 -#: replication/walsender.c:1018 replication/walsender.c:1028 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 +#: commands/define.c:388 commands/tablecmds.c:8129 +#: replication/pgoutput/pgoutput.c:314 replication/pgoutput/pgoutput.c:337 +#: replication/pgoutput/pgoutput.c:351 replication/pgoutput/pgoutput.c:361 +#: replication/pgoutput/pgoutput.c:371 replication/pgoutput/pgoutput.c:381 +#: replication/pgoutput/pgoutput.c:393 replication/walsender.c:1146 +#: replication/walsender.c:1168 replication/walsender.c:1178 +#: replication/walsender.c:1187 replication/walsender.c:1426 #, c-format msgid "conflicting or redundant options" msgstr "상충하거나 중복된 옵션들" -#: commands/collationcmds.c:126 +#: commands/collationcmds.c:124 #, c-format msgid "LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE." msgstr "LOCALE 값은 LC_COLLATE 또는 LC_CTYPE 값과 함께 지정할 수 없음" -#: commands/collationcmds.c:132 +#: commands/collationcmds.c:130 #, c-format msgid "FROM cannot be specified together with any other options." msgstr "FROM 구문은 다른 옵션들과 함께 사용될 수 없습니다." -#: commands/collationcmds.c:191 +#: commands/collationcmds.c:189 #, c-format msgid "collation \"default\" cannot be copied" msgstr "\"default\" 정렬규칙은 복사될 수 없음" @@ -7028,104 +7450,94 @@ msgstr "\"default\" 정렬규칙은 복사될 수 없음" msgid "unrecognized collation provider: %s" msgstr "알 수 없는 정렬규칙 제공자 이름: %s" -#: commands/collationcmds.c:253 -#, c-format -msgid "parameter \"lc_collate\" must be specified" -msgstr "\"lc_collate\" 옵션을 지정해야 함" - -#: commands/collationcmds.c:258 -#, c-format -msgid "parameter \"lc_ctype\" must be specified" -msgstr "\"lc_ctype\" 옵션을 지정해야 함" - -#: commands/collationcmds.c:265 +#: commands/collationcmds.c:253 commands/collationcmds.c:264 +#: commands/collationcmds.c:270 commands/collationcmds.c:278 #, c-format -msgid "parameter \"locale\" must be specified" -msgstr "\"locale\" 매개 변수를 지정해야 함" +msgid "parameter \"%s\" must be specified" +msgstr "\"%s\" 매개 변수를 지정해야 함" -#: commands/collationcmds.c:279 commands/dbcommands.c:1091 +#: commands/collationcmds.c:293 commands/dbcommands.c:1134 #, c-format msgid "using standard form \"%s\" for ICU locale \"%s\"" msgstr "\"%s\"에서 표준을 사용함(해당 ICU 로케일: \"%s\")" -#: commands/collationcmds.c:298 +#: commands/collationcmds.c:312 #, c-format msgid "nondeterministic collations not supported with this provider" msgstr "이 제공자는 DETERMINISTIC = false 옵션을 지원하지 않음" -#: commands/collationcmds.c:303 commands/dbcommands.c:1110 +#: commands/collationcmds.c:317 commands/dbcommands.c:1087 #, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" msgstr "ICU 규칙은 로케일 제공자로 ICU로 지정했을 때만 사용할 수 있습니다." -#: commands/collationcmds.c:322 +#: commands/collationcmds.c:340 #, c-format msgid "current database's encoding is not supported with this provider" msgstr "이 제공자는 현재 데이터베이스 인코딩을 지원하지 않음" -#: commands/collationcmds.c:382 +#: commands/collationcmds.c:409 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 정렬규칙(대상 인코딩: \"%s\")이 \"%s\" 스키마 안에 이미 있음" -#: commands/collationcmds.c:393 +#: commands/collationcmds.c:420 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 정렬규칙이 \"%s\" 스키마에 이미 있습니다" -#: commands/collationcmds.c:418 +#: commands/collationcmds.c:445 #, c-format msgid "cannot refresh version of default collation" msgstr "기본 문자 정렬의 버전을 갱신할 수 없음" -#: commands/collationcmds.c:419 +#. translator: %s is an SQL command +#. translator: %s is an SQL ALTER command +#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 +#: commands/tablecmds.c:7905 commands/tablecmds.c:7915 +#: commands/tablecmds.c:7917 commands/tablecmds.c:14499 +#: commands/tablecmds.c:17884 commands/tablecmds.c:17905 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 #, c-format -msgid "Use ALTER DATABASE ... REFRESH COLLATION VERSION instead." -msgstr "" -"대신에, ALTER DATABASE ... REFRESH COLLATION VERSION 명령을 사용하세요." +msgid "Use %s instead." +msgstr "대신에 %s 명령을 사용하십시오." -#: commands/collationcmds.c:446 commands/dbcommands.c:2488 +#: commands/collationcmds.c:480 commands/dbcommands.c:2566 #, c-format msgid "changing version from %s to %s" msgstr "%s에서 %s 버전으로 바꿉니다" -#: commands/collationcmds.c:461 commands/dbcommands.c:2501 +#: commands/collationcmds.c:495 commands/dbcommands.c:2579 #, c-format msgid "version has not changed" msgstr "버전이 바뀌지 않았습니다" -#: commands/collationcmds.c:494 commands/dbcommands.c:2667 +#: commands/collationcmds.c:528 commands/dbcommands.c:2749 #, c-format msgid "database with OID %u does not exist" msgstr "OID %u 데이터베이스 없음" -#: commands/collationcmds.c:515 +#: commands/collationcmds.c:554 #, c-format msgid "collation with OID %u does not exist" msgstr "OID %u 정렬정의(collation) 없음" -#: commands/collationcmds.c:803 +#: commands/collationcmds.c:848 #, c-format msgid "must be superuser to import system collations" msgstr "시스템 정렬규칙을 가져오려면 슈퍼유저여야함" -#: commands/collationcmds.c:831 commands/copyfrom.c:1654 commands/copyto.c:656 -#: libpq/be-secure-common.c:59 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "\"%s\" 명령을 실행할 수 없음: %m" - -#: commands/collationcmds.c:923 commands/collationcmds.c:1008 +#: commands/collationcmds.c:968 commands/collationcmds.c:1053 #, c-format msgid "no usable system locales were found" msgstr "사용할 수 있는 시스템 로케일이 없음" -#: commands/comment.c:61 commands/dbcommands.c:1612 commands/dbcommands.c:1824 -#: commands/dbcommands.c:1934 commands/dbcommands.c:2132 -#: commands/dbcommands.c:2370 commands/dbcommands.c:2461 -#: commands/dbcommands.c:2571 commands/dbcommands.c:3071 -#: utils/init/postinit.c:1021 utils/init/postinit.c:1085 -#: utils/init/postinit.c:1157 +#: commands/comment.c:61 commands/dbcommands.c:1665 commands/dbcommands.c:1883 +#: commands/dbcommands.c:1995 commands/dbcommands.c:2193 +#: commands/dbcommands.c:2433 commands/dbcommands.c:2526 +#: commands/dbcommands.c:2650 commands/dbcommands.c:3161 +#: utils/init/postinit.c:1034 utils/init/postinit.c:1098 +#: utils/init/postinit.c:1171 #, c-format msgid "database \"%s\" does not exist" msgstr "\"%s\" 데이터베이스 없음" @@ -7135,315 +7547,270 @@ msgstr "\"%s\" 데이터베이스 없음" msgid "cannot set comment on relation \"%s\"" msgstr "\"%s\" 릴레이션에 주석을 달 수 없음" -#: commands/constraint.c:63 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "\"%s\" 함수가 트리거 관리자에서 호출되지 않았음" -#: commands/constraint.c:70 utils/adt/ri_triggers.c:2037 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "AFTER ROW에서 \"%s\" 함수를 실행해야 함" -#: commands/constraint.c:84 +#: commands/constraint.c:82 #, c-format msgid "function \"%s\" must be fired for INSERT or UPDATE" msgstr "INSERT 또는 UPDATE에 대해 \"%s\" 함수를 실행해야 함" -#: commands/conversioncmds.c:69 +#: commands/conversioncmds.c:62 #, c-format msgid "source encoding \"%s\" does not exist" msgstr "\"%s\" 원본 인코딩 없음" -#: commands/conversioncmds.c:76 +#: commands/conversioncmds.c:69 #, c-format msgid "destination encoding \"%s\" does not exist" msgstr "\"%s\" 대상 인코딩 없음" -#: commands/conversioncmds.c:89 +#: commands/conversioncmds.c:82 #, c-format msgid "encoding conversion to or from \"SQL_ASCII\" is not supported" msgstr "\"SQL_ASCII\" 인코딩 변환은 지원하지 않습니다." -#: commands/conversioncmds.c:102 +#: commands/conversioncmds.c:95 #, c-format msgid "encoding conversion function %s must return type %s" msgstr "%s 인코딩 변환 함수는 %s 형을 반환해야 함" -#: commands/conversioncmds.c:132 +#: commands/conversioncmds.c:125 #, c-format msgid "" "encoding conversion function %s returned incorrect result for empty input" msgstr "빈 입력으로 %s 인코딩 변환 함수가 잘못된 결과를 반환했음" -#: commands/copy.c:86 +#: commands/copy.c:84 #, c-format msgid "permission denied to COPY to or from an external program" msgstr "외부 프로그램을 이용한 COPY to/from 작업 권한 없음" -#: commands/copy.c:87 +#: commands/copy.c:85 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may COPY to or from an " "external program." msgstr "외부 프로그램을 이용하는 COPY 작업은 \"%s\" 롤 소속원만 허용합니다." -#: commands/copy.c:89 commands/copy.c:100 commands/copy.c:109 +#: commands/copy.c:87 commands/copy.c:98 commands/copy.c:107 #, c-format msgid "" "Anyone can COPY to stdout or from stdin. psql's \\copy command also works " "for anyone." msgstr "일반 사용자인데, 이 작업이 필요하면, psql의 \\copy 명령을 이용하세요" -#: commands/copy.c:97 +#: commands/copy.c:95 #, c-format msgid "permission denied to COPY from a file" msgstr "파일 내용 가져오는 COPY 작업 권한 없음" -#: commands/copy.c:98 +#: commands/copy.c:96 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY from a file." msgstr "" "파일을 읽어 COPY 명령으로 자료를 저장하려면, \"%s\" 롤 소속원이어야 합니다." -#: commands/copy.c:106 +#: commands/copy.c:104 #, c-format msgid "permission denied to COPY to a file" msgstr "파일로 저장하는 COPY 작업 권한 없음" -#: commands/copy.c:107 +#: commands/copy.c:105 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to a file." msgstr "COPY 명령 결과를 파일로 저장하려면, \"%s\" 롤 소속원이어야 합니다." -#: commands/copy.c:195 +#: commands/copy.c:193 #, c-format msgid "COPY FROM not supported with row-level security" msgstr "로우 단위 보안 기능으로 COPY FROM 명령을 사용할 수 없음" -#: commands/copy.c:196 +#: commands/copy.c:194 #, c-format msgid "Use INSERT statements instead." msgstr "대신에 INSERT 구문을 사용하십시오." -#: commands/copy.c:290 -#, c-format -msgid "MERGE not supported in COPY" -msgstr "COPY에서는 MERGE 구문을 지원하지 않습니다" - -#: commands/copy.c:383 +#: commands/copy.c:375 #, c-format msgid "cannot use \"%s\" with HEADER in COPY TO" msgstr "COPY TO 명령에서는 HEADER 값으로 \"%s\" 값을 사용할 수 없음" -#: commands/copy.c:392 +#: commands/copy.c:384 #, c-format msgid "%s requires a Boolean value or \"match\"" msgstr "%s 값은 불리언 값 또는 \"match\" 이어야 합니다." -#: commands/copy.c:451 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:782 commands/copy.c:798 +#: commands/copy.c:815 commands/copy.c:841 commands/copy.c:851 +#, c-format +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s 옵션은 %s 옵션과 함께 쓸 수 없음" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:441 +#, c-format +msgid "COPY %s \"%s\" not recognized" +msgstr "COPY %s \"%s\" 구문은 지원하지 않음" + +#: commands/copy.c:502 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "\"%s\" COPY 양식은 지원하지 않음" -#: commands/copy.c:509 commands/copy.c:522 commands/copy.c:535 -#: commands/copy.c:554 +#: commands/copy.c:560 commands/copy.c:575 commands/copy.c:590 +#: commands/copy.c:609 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "\"%s\" 옵션에 대한 인자는 칼럼 이름 목록이어야 합니다." -#: commands/copy.c:566 +#: commands/copy.c:621 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "\"%s\" 옵션에 대한 인자는 인코딩 이름이어야 합니다." -#: commands/copy.c:573 commands/dbcommands.c:859 commands/dbcommands.c:2318 +#: commands/copy.c:642 commands/dbcommands.c:866 commands/dbcommands.c:2381 #, c-format msgid "option \"%s\" not recognized" msgstr "\"%s\" 옵션은 타당하지 않습니다." -#: commands/copy.c:585 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:655 commands/copy.c:660 commands/copy.c:665 +#: commands/copy.c:740 #, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "BINARY 모드에서는 DELIMITER 값을 지정할 수 없음" +msgid "cannot specify %s in BINARY mode" +msgstr "BINARY 모드에서는 %s 값을 지정할 수 없음" -#: commands/copy.c:590 -#, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "BINARY 모드에서는 NULL 값을 지정할 수 없음" - -#: commands/copy.c:595 +#: commands/copy.c:670 #, c-format -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "BINARY 모드에서는 DEFAULT 지정할 수 없음" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "BINARY 모드에서는 ON_ERROR STOP만 허용함" -#: commands/copy.c:617 +#: commands/copy.c:692 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "COPY 구분자는 1바이트의 단일 문자여야 함" -#: commands/copy.c:624 +#: commands/copy.c:699 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "COPY 명령에서 사용할 칼럼 구분자로 줄바꿈 문자들을 사용할 수 없습니다" -#: commands/copy.c:630 +#: commands/copy.c:705 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "COPY null 표현에서 줄바꿈 또는 캐리지 리턴을 사용할 수 없음" -#: commands/copy.c:640 +#: commands/copy.c:715 #, c-format msgid "COPY default representation cannot use newline or carriage return" msgstr "COPY 기본 동작에서는 줄바꿈 또는 캐리지 리턴을 사용할 수 없음" -#: commands/copy.c:658 +#: commands/copy.c:733 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "COPY 구분자는 \"%s\"일 수 없음" -#: commands/copy.c:664 -#, c-format -msgid "cannot specify HEADER in BINARY mode" -msgstr "BINARY 모드에서는 HEADER 옵션을 지정할 수 없음" - -#: commands/copy.c:670 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:747 commands/copy.c:764 commands/copy.c:776 +#: commands/copy.c:791 commands/copy.c:807 #, c-format -msgid "COPY quote available only in CSV mode" -msgstr "COPY 따옴표는 CSV 모드에서만 사용할 수 있음" +msgid "COPY %s requires CSV mode" +msgstr "%s COPY 명령 옵션은 CSV 모드가 필요함" -#: commands/copy.c:675 +#: commands/copy.c:752 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "COPY 따옴표는 1바이트의 단일 문자여야 함" -#: commands/copy.c:680 +#: commands/copy.c:757 #, c-format msgid "COPY delimiter and quote must be different" msgstr "COPY 구분자 및 따옴표는 서로 달라야 함" -#: commands/copy.c:686 -#, c-format -msgid "COPY escape available only in CSV mode" -msgstr "COPY 이스케이프는 CSV 모드에서만 사용할 수 있음" - -#: commands/copy.c:691 +#: commands/copy.c:769 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "COPY 이스케이프는 1바이트의 단일 문자여야 함" -#: commands/copy.c:697 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:823 commands/copy.c:859 #, c-format -msgid "COPY force quote available only in CSV mode" -msgstr "COPY force quote는 CSV 모드에서만 사용할 수 있음" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "COPY 구분자는 %s 정의에 없어야 함" -#: commands/copy.c:701 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:832 commands/copy.c:868 #, c-format -msgid "COPY force quote only available using COPY TO" -msgstr "COPY force quote는 COPY TO에서만 사용할 수 있음" +msgid "CSV quote character must not appear in the %s specification" +msgstr "CSV 인용 문자는 %s 정의에 없어야 함" -#: commands/copy.c:707 +#: commands/copy.c:877 #, c-format -msgid "COPY force not null available only in CSV mode" -msgstr "COPY force not null은 CSV 모드에서만 사용할 수 있음" +msgid "NULL specification and DEFAULT specification cannot be the same" +msgstr "NULL 지정과 DEFAULT 지정이 같을 수는 없음" -#: commands/copy.c:711 +#: commands/copy.c:939 #, c-format -msgid "COPY force not null only available using COPY FROM" -msgstr "COPY force not null은 COPY FROM에서만 사용할 수 있음" +msgid "column \"%s\" is a generated column" +msgstr "\"%s\" 칼럼은 미리 계산된 칼럼임" -#: commands/copy.c:717 +#: commands/copy.c:941 #, c-format -msgid "COPY force null available only in CSV mode" -msgstr "COPY force null은 CSV 모드에서만 사용할 수 있음" +msgid "Generated columns cannot be used in COPY." +msgstr "미리 계산된 칼럼은 COPY 작업 대상이 아님" -#: commands/copy.c:722 +#: commands/copy.c:956 commands/indexcmds.c:1890 commands/statscmds.c:239 +#: commands/tablecmds.c:2526 commands/tablecmds.c:2997 +#: commands/tablecmds.c:3808 parser/parse_relation.c:3692 +#: parser/parse_relation.c:3702 parser/parse_relation.c:3720 +#: parser/parse_relation.c:3727 parser/parse_relation.c:3741 +#: utils/adt/tsvector_op.c:2853 #, c-format -msgid "COPY force null only available using COPY FROM" -msgstr "COPY force null은 COPY FROM에서만 사용할 수 있음" +msgid "column \"%s\" does not exist" +msgstr "\"%s\" 이름의 칼럼은 없습니다" -#: commands/copy.c:728 -#, c-format -msgid "COPY delimiter must not appear in the NULL specification" -msgstr "COPY 구분자는 NULL 지정에 표시되지 않아야 함" - -#: commands/copy.c:735 -#, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "CSV 따옴표는 NULL 지정에 표시되지 않아야 함" - -#: commands/copy.c:742 -#, c-format -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "COPY DEFAULT는 COPY FROM에서만 사용할 수 있음" - -#: commands/copy.c:748 -#, c-format -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "COPY 구분자는 DEFAULT 지정에 표시되지 않아야 함" - -#: commands/copy.c:755 -#, c-format -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "CSV 따옴표는 DEFAULT 지정에 표시되지 않아야 함" - -#: commands/copy.c:763 -#, c-format -msgid "NULL specification and DEFAULT specification cannot be the same" -msgstr "NULL 지정과 DEFAULT 지정이 같을 수는 없음" - -#: commands/copy.c:825 -#, c-format -msgid "column \"%s\" is a generated column" -msgstr "\"%s\" 칼럼은 미리 계산된 칼럼임" - -#: commands/copy.c:827 -#, c-format -msgid "Generated columns cannot be used in COPY." -msgstr "미리 계산된 칼럼은 COPY 작업 대상이 아님" - -#: commands/copy.c:842 commands/indexcmds.c:1910 commands/statscmds.c:242 -#: commands/tablecmds.c:2405 commands/tablecmds.c:3127 -#: commands/tablecmds.c:3626 parser/parse_relation.c:3689 -#: parser/parse_relation.c:3699 parser/parse_relation.c:3717 -#: parser/parse_relation.c:3724 parser/parse_relation.c:3738 -#: utils/adt/tsvector_op.c:2855 -#, c-format -msgid "column \"%s\" does not exist" -msgstr "\"%s\" 이름의 칼럼은 없습니다" - -#: commands/copy.c:849 commands/tablecmds.c:2431 commands/trigger.c:958 -#: parser/parse_target.c:1070 parser/parse_target.c:1081 +#: commands/copy.c:963 commands/tablecmds.c:2552 commands/trigger.c:951 +#: parser/parse_target.c:1083 parser/parse_target.c:1094 #, c-format msgid "column \"%s\" specified more than once" msgstr "\"%s\" 칼럼을 하나 이상 지정했음" -#: commands/copyfrom.c:122 +#: commands/copyfrom.c:118 #, c-format msgid "COPY %s" msgstr "COPY %s" -#: commands/copyfrom.c:130 +#: commands/copyfrom.c:126 #, c-format msgid "COPY %s, line %llu, column %s" msgstr "COPY %s, %llu번째 줄, %s 열" -#: commands/copyfrom.c:135 commands/copyfrom.c:181 +#: commands/copyfrom.c:131 commands/copyfrom.c:177 #, c-format msgid "COPY %s, line %llu" msgstr "COPY %s, %llu번째 줄" -#: commands/copyfrom.c:147 +#: commands/copyfrom.c:143 #, c-format msgid "COPY %s, line %llu, column %s: \"%s\"" msgstr "COPY %s, %llu번째 줄, %s 열: \"%s\"" -#: commands/copyfrom.c:157 +#: commands/copyfrom.c:153 #, c-format msgid "COPY %s, line %llu, column %s: null input" msgstr "COPY %s, %llu행, %s 열: null 입력" -#: commands/copyfrom.c:174 +#: commands/copyfrom.c:170 #, c-format msgid "COPY %s, line %llu: \"%s\"" msgstr "COPY %s, %llu번째 줄: \"%s\"" @@ -7494,17 +7861,27 @@ msgstr "" "현재 하위 트랜잭션에서 만들어지거나 비워진 테이블이 아니기 때문에 COPY " "FREEZE 작업을 할 수 없음" -#: commands/copyfrom.c:1411 +#: commands/copyfrom.c:1313 +#, c-format +msgid "%llu row was skipped due to data type incompatibility" +msgid_plural "%llu rows were skipped due to data type incompatibility" +msgstr[0] "%llu개의 로우가 자료형이 호환되지 않아 건너뜀" + +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1448 commands/copyfrom.c:1491 commands/copyto.c:601 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "\"%s\" FORCE_NOT_NULL 칼럼은 COPY에서 참조되지 않음" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "%s 옵션(해당 칼럼: \"%s\")은 COPY에서 참조되지 않음" -#: commands/copyfrom.c:1434 +#: commands/copyfrom.c:1544 utils/mb/mbutils.c:385 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "\"%s\" FORCE_NULL 칼럼은 COPY에서 참조되지 않음" +msgid "" +"default conversion function for encoding \"%s\" to \"%s\" does not exist" +msgstr "" +"\"%s\" 인코딩을 \"%s\" 인코딩으로 변환할 기본 변환규칙(conversion)이 없음" -#: commands/copyfrom.c:1673 +#: commands/copyfrom.c:1742 #, c-format msgid "" "COPY FROM instructs the PostgreSQL server process to read a file. You may " @@ -7514,17 +7891,17 @@ msgstr "" "언트 쪽에 있는 파일을 읽어 처리 하려면, psql의 \\copy 내장 명령어를 사용하세" "요." -#: commands/copyfrom.c:1686 commands/copyto.c:708 +#: commands/copyfrom.c:1755 commands/copyto.c:706 #, c-format msgid "\"%s\" is a directory" msgstr "\"%s\" 디렉터리임" -#: commands/copyfrom.c:1754 commands/copyto.c:306 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1823 commands/copyto.c:299 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "외부 명령으로 파이프를 닫을 수 없음: %m" -#: commands/copyfrom.c:1769 commands/copyto.c:311 +#: commands/copyfrom.c:1838 commands/copyto.c:304 #, c-format msgid "program \"%s\" failed" msgstr "\"%s\" 프로그램 실패" @@ -7565,19 +7942,19 @@ msgid "could not read from COPY file: %m" msgstr "COPY 명령에 사용할 파일을 읽을 수 없습니다: %m" #: commands/copyfromparse.c:278 commands/copyfromparse.c:303 -#: tcop/postgres.c:377 +#: replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:381 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "열린 트랜잭션과 함께 클라이언트 연결에서 예상치 않은 EOF 발견됨" -#: commands/copyfromparse.c:294 +#: commands/copyfromparse.c:294 replication/walsender.c:772 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "" "COPY 명령으로 stdin으로 자료를 가져오는 동안 예상치 않은 메시지 타입 0x%02X " "발견됨" -#: commands/copyfromparse.c:317 +#: commands/copyfromparse.c:317 replication/walsender.c:803 #, c-format msgid "COPY from stdin failed: %s" msgstr "COPY 명령에서 stdin으로 자료 가져오기 실패: %s" @@ -7593,19 +7970,19 @@ msgid "" "column name mismatch in header line field %d: got null value (\"%s\"), " "expected \"%s\"" msgstr "" -"헤더 %d 번째 필드의 칼럼 이름이 일치하지 않음: null 값 발견(\"%s\"), 기대값=" -"\"%s\"" +"헤더 %d 번째 필드의 칼럼 이름이 일치하지 않음: null 값 발견(\"%s\"), 기대값" +"=\"%s\"" #: commands/copyfromparse.c:808 #, c-format msgid "" "column name mismatch in header line field %d: got \"%s\", expected \"%s\"" msgstr "" -"헤더 줄 %d 번째 필드의 칼럼 이름이 일치하지 않음: 해당이름=\"%s\", 기대값=" -"\"%s\"" +"헤더 줄 %d 번째 필드의 칼럼 이름이 일치하지 않음: 해당이름=\"%s\", 기대값" +"=\"%s\"" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1512 -#: commands/copyfromparse.c:1768 +#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 +#: commands/copyfromparse.c:1810 #, c-format msgid "extra data after last expected column" msgstr "마지막 칼럼을 초과해서 또 다른 데이터가 있음" @@ -7615,196 +7992,212 @@ msgstr "마지막 칼럼을 초과해서 또 다른 데이터가 있음" msgid "missing data for column \"%s\"" msgstr "\"%s\" 칼럼의 자료가 빠졌음" -#: commands/copyfromparse.c:999 +#: commands/copyfromparse.c:990 +#, c-format +msgid "" +"skipping row due to data type incompatibility at line %llu for column " +"\"%s\": \"%s\"" +msgstr "" +"%llu 줄에서 자료형이 호환되지 않아, 로우를 건너 뜀(해당 칼럼: \"%s\"): \"%s\"" + +#: commands/copyfromparse.c:998 +#, c-format +msgid "" +"skipping row due to data type incompatibility at line %llu for column " +"\"%s\": null input" +msgstr "" +"%llu 줄에서 자료형이 호환되지 않아, 로우를 건너 뜀(해당 칼럼: \"%s\"): null 입력" + +#: commands/copyfromparse.c:1044 #, c-format msgid "received copy data after EOF marker" msgstr "EOF 표시 뒤에도 복사 데이터를 받았음" -#: commands/copyfromparse.c:1006 +#: commands/copyfromparse.c:1051 #, c-format msgid "row field count is %d, expected %d" msgstr "행(row) 필드 갯수가 %d 임, 예상값은 %d" -#: commands/copyfromparse.c:1294 commands/copyfromparse.c:1311 +#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 #, c-format msgid "literal carriage return found in data" msgstr "데이터에 carriage return 값이 잘못되었음" -#: commands/copyfromparse.c:1295 commands/copyfromparse.c:1312 +#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 #, c-format msgid "unquoted carriage return found in data" msgstr "데이터에 carriage return 값 표기가 잘못 되었음" -#: commands/copyfromparse.c:1297 commands/copyfromparse.c:1314 +#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "carriage return값으로 \"\\r\" 문자를 사용하세요" -#: commands/copyfromparse.c:1298 commands/copyfromparse.c:1315 +#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "" "carriage return 문자를 그대로 적용하려면, quoted CSV 필드를 사용하세요." -#: commands/copyfromparse.c:1327 +#: commands/copyfromparse.c:1369 #, c-format msgid "literal newline found in data" msgstr "데이터에 newline 값이 잘못되었음" -#: commands/copyfromparse.c:1328 +#: commands/copyfromparse.c:1370 #, c-format msgid "unquoted newline found in data" msgstr "데이터에 newline 값이 잘못 되었음" -#: commands/copyfromparse.c:1330 +#: commands/copyfromparse.c:1372 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "newline 값으로 \"\\n\" 문자를 사용하세요" -#: commands/copyfromparse.c:1331 +#: commands/copyfromparse.c:1373 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "newline 문자를 그대로 적용하려면, quoted CSV 필드를 사용하세요." -#: commands/copyfromparse.c:1377 commands/copyfromparse.c:1413 +#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "end-of-copy 마크는 이전 newline 모양가 틀립니다" -#: commands/copyfromparse.c:1386 commands/copyfromparse.c:1402 +#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 #, c-format msgid "end-of-copy marker corrupt" msgstr "end-of-copy 마크가 잘못되었음" -#: commands/copyfromparse.c:1704 commands/copyfromparse.c:1919 +#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 #, c-format msgid "unexpected default marker in COPY data" msgstr "COPY 자료 안에 예상치 않은 기본 마커" -#: commands/copyfromparse.c:1705 commands/copyfromparse.c:1920 +#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 #, c-format msgid "Column \"%s\" has no default value." msgstr "\"%s\" 칼럼은 DEFAULT 값이 없음." -#: commands/copyfromparse.c:1852 +#: commands/copyfromparse.c:1894 #, c-format msgid "unterminated CSV quoted field" msgstr "종료되지 않은 CSV 따옴표 필드" -#: commands/copyfromparse.c:1954 commands/copyfromparse.c:1973 +#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 #, c-format msgid "unexpected EOF in COPY data" msgstr "복사 자료 안에 예상치 않은 EOF 발견" -#: commands/copyfromparse.c:1963 +#: commands/copyfromparse.c:2005 #, c-format msgid "invalid field size" msgstr "잘못된 필드 크기" -#: commands/copyfromparse.c:1986 +#: commands/copyfromparse.c:2028 #, c-format msgid "incorrect binary data format" msgstr "잘못된 바이너리 자료 포맷" -#: commands/copyto.c:236 +#: commands/copyto.c:229 #, c-format msgid "could not write to COPY program: %m" msgstr "COPY 프로그램으로 파일을 쓸 수 없습니다: %m" -#: commands/copyto.c:241 +#: commands/copyto.c:234 #, c-format msgid "could not write to COPY file: %m" msgstr "COPY 파일로로 파일을 쓸 수 없습니다: %m" -#: commands/copyto.c:386 +#: commands/copyto.c:379 #, c-format msgid "cannot copy from view \"%s\"" msgstr "\"%s\" 이름의 개체는 뷰(view)입니다. 자료를 내보낼 수 없습니다" -#: commands/copyto.c:388 commands/copyto.c:394 commands/copyto.c:400 -#: commands/copyto.c:411 +#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 +#: commands/copyto.c:404 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "COPY (SELECT ...) TO 변형을 시도하십시오." -#: commands/copyto.c:392 +#: commands/copyto.c:385 #, c-format msgid "cannot copy from materialized view \"%s\"" msgstr "\"%s\" 이름의 개체는 구체화된 뷰입니다. 자료를 내보낼 수 없습니다" -#: commands/copyto.c:398 +#: commands/copyto.c:391 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "\"%s\" 이름의 개체는 외부 테이블입니다. 자료를 내보낼 수 없습니다" -#: commands/copyto.c:404 +#: commands/copyto.c:397 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "\"%s\" 이름의 개체는 시퀀스입니다. 자료를 내보낼 수 없습니다" -#: commands/copyto.c:409 +#: commands/copyto.c:402 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "\"%s\" 파티션 된 테이블에서 복사할 수 없음" -#: commands/copyto.c:415 +#: commands/copyto.c:408 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "" "\"%s\" 개체는 테이블이 아닌 릴레이션(relation)이기에 자료를 내보낼 수 없습니" "다" -#: commands/copyto.c:467 +#: commands/copyto.c:460 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "DO INSTEAD NOTHING 룰(rule)은 COPY 구문에서 지원하지 않습니다." -#: commands/copyto.c:481 +#: commands/copyto.c:474 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "선택적 DO INSTEAD 룰은 COPY 구문에서 지원하지 않음" -#: commands/copyto.c:485 +#: commands/copyto.c:478 #, c-format -msgid "DO ALSO rules are not supported for the COPY" -msgstr "DO ALSO 룰(rule)은 COPY 구문에서 지원하지 않습니다." +msgid "DO ALSO rules are not supported for COPY" +msgstr "DO ALSO 룰은 COPY 구문에서 지원하지 않음" -#: commands/copyto.c:490 +#: commands/copyto.c:483 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "다중 구문 DO INSTEAD 룰은 COPY 구문에서 지원하지 않음" -#: commands/copyto.c:500 +#: commands/copyto.c:493 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO) 지원하지 않음" -#: commands/copyto.c:517 +#: commands/copyto.c:499 +#, c-format +msgid "COPY query must not be a utility command" +msgstr "COPY 쿼리는 DDL, DCL 명령이 아니여야 함" + +#: commands/copyto.c:515 #, c-format msgid "COPY query must have a RETURNING clause" -msgstr "COPY 쿼리는 RETURNING 절이 있어야 합니다" +msgstr "COPY 쿼리는 RETURNING 절이 있어야 함" -#: commands/copyto.c:546 +#: commands/copyto.c:544 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "COPY 문에 의해 참조된 릴레이션이 변경 되었음" -#: commands/copyto.c:605 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "\"%s\" FORCE_QUOTE 칼럼은 COPY에서 참조되지 않음" - -#: commands/copyto.c:673 +#: commands/copyto.c:671 #, c-format msgid "relative path not allowed for COPY to file" -msgstr "COPY 명령에 사용할 파일 이름으로 상대경로는 사용할 수 없습니다" +msgstr "COPY 명령에 사용할 파일 이름으로 상대경로는 사용할 수 없음" -#: commands/copyto.c:692 +#: commands/copyto.c:690 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "\"%s\" 파일 열기 실패: %m" -#: commands/copyto.c:695 +#: commands/copyto.c:693 #, c-format msgid "" "COPY TO instructs the PostgreSQL server process to write a file. You may " @@ -7814,132 +8207,142 @@ msgstr "" "저장된다. 클라이언트 쪽에서 그 결과를 저장하려면, psql \\copy 명령으로 처리" "할 수 있다." -#: commands/createas.c:215 commands/createas.c:523 +#: commands/createas.c:210 commands/createas.c:516 #, c-format msgid "too many column names were specified" msgstr "너무 많은 칼럼 이름을 지정했습니다." -#: commands/createas.c:546 +#: commands/createas.c:539 #, c-format msgid "policies not yet implemented for this command" msgstr "이 명령을 위한 정책은 아직 구현되어 있지 않습니다" -#: commands/dbcommands.c:822 +#: commands/dbcommands.c:829 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATION 예약어는 이제 더이상 지원하지 않습니다" -#: commands/dbcommands.c:823 +#: commands/dbcommands.c:830 #, c-format msgid "Consider using tablespaces instead." msgstr "대신에 테이블스페이스를 이용하세요." -#: commands/dbcommands.c:848 +#: commands/dbcommands.c:855 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "시스템 객체용으로 사용할 미리 예약된 최대 %u OID 보다 작을 수는 없음" -#: commands/dbcommands.c:879 utils/adt/ascii.c:146 +#: commands/dbcommands.c:886 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "%d 값은 잘못된 인코딩 코드임" -#: commands/dbcommands.c:890 utils/adt/ascii.c:128 +#: commands/dbcommands.c:897 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "%s 이름은 잘못된 인코딩 이름임" -#: commands/dbcommands.c:919 +#: commands/dbcommands.c:931 #, c-format msgid "unrecognized locale provider: %s" msgstr "알 수 없는 로케일 제공자 이름: %s" -#: commands/dbcommands.c:932 commands/dbcommands.c:2351 commands/user.c:300 -#: commands/user.c:740 +#: commands/dbcommands.c:944 commands/dbcommands.c:2414 commands/user.c:299 +#: commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "잘못된 연결 제한: %d" -#: commands/dbcommands.c:953 +#: commands/dbcommands.c:965 #, c-format msgid "permission denied to create database" msgstr "데이터베이스를 만들 권한이 없음" -#: commands/dbcommands.c:977 +#: commands/dbcommands.c:989 #, c-format msgid "template database \"%s\" does not exist" msgstr "\"%s\" 템플릿 데이터베이스 없음" -#: commands/dbcommands.c:987 +#: commands/dbcommands.c:999 #, c-format msgid "cannot use invalid database \"%s\" as template" msgstr "\"%s\" 데이터베이스 잘못된 것으로 템플릿으로 사용할 수 없음" -#: commands/dbcommands.c:988 commands/dbcommands.c:2380 -#: utils/init/postinit.c:1100 +#: commands/dbcommands.c:1000 commands/dbcommands.c:2444 +#: utils/init/postinit.c:1113 #, c-format msgid "Use DROP DATABASE to drop invalid databases." msgstr "" "바르지 않은 데이터베이스를 삭제하려면, DROP DATABASE 명령을 사용하세요." -#: commands/dbcommands.c:999 +#: commands/dbcommands.c:1011 #, c-format msgid "permission denied to copy database \"%s\"" msgstr "\"%s\" 데이터베이스를 복사할 권한이 없음" -#: commands/dbcommands.c:1016 +#: commands/dbcommands.c:1028 #, c-format msgid "invalid create database strategy \"%s\"" msgstr "잘못된 데이터베이스 만들기 전략: \"%s\"" -#: commands/dbcommands.c:1017 +#: commands/dbcommands.c:1029 #, c-format -msgid "Valid strategies are \"wal_log\", and \"file_copy\"." -msgstr "사용할 수 있는 값은 \"wal_log\" 또는 \"file_copy\" 입니다." +msgid "Valid strategies are \"wal_log\" and \"file_copy\"." +msgstr "사용할 수 있는 전략값은 \"wal_log\" 또는 \"file_copy\"" -#: commands/dbcommands.c:1043 +#: commands/dbcommands.c:1050 #, c-format msgid "invalid server encoding %d" msgstr "잘못된 서버 인코딩 %d" -#: commands/dbcommands.c:1049 +#: commands/dbcommands.c:1056 #, c-format msgid "invalid LC_COLLATE locale name: \"%s\"" msgstr "LC_COLLATE 로케일 이름이 잘못됨: \"%s\"" -#: commands/dbcommands.c:1050 commands/dbcommands.c:1056 +#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 #, c-format msgid "If the locale name is specific to ICU, use ICU_LOCALE." msgstr "ICU 로케일 이름을 사용하려면, ICU_LOCALE을 사용하세요." -#: commands/dbcommands.c:1055 +#: commands/dbcommands.c:1062 #, c-format msgid "invalid LC_CTYPE locale name: \"%s\"" msgstr "LC_CTYPE 로케일 이름이 잘못됨: \"%s\"" -#: commands/dbcommands.c:1066 +#: commands/dbcommands.c:1074 +#, c-format +msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" +msgstr "BUILTIN_LOCALE 옵션은 로케일 제공자 중에 빌트인이 있어야 쓸 수 있음" + +#: commands/dbcommands.c:1082 +#, c-format +msgid "ICU locale cannot be specified unless locale provider is ICU" +msgstr "ICU 로케일은 ICU 로케일 제공자를 지정해야만 쓸 수 있습니다." + +#: commands/dbcommands.c:1100 +#, c-format +msgid "LOCALE or BUILTIN_LOCALE must be specified" +msgstr "LOCALE 또는 BUILTIN_LOCALE을 지정해야 합니다." + +#: commands/dbcommands.c:1109 #, c-format msgid "encoding \"%s\" is not supported with ICU provider" msgstr "\"%s\" 인코딩은 ICU 제공자에서 지원하지 않음" -#: commands/dbcommands.c:1076 +#: commands/dbcommands.c:1119 #, c-format msgid "LOCALE or ICU_LOCALE must be specified" msgstr "LOCALE 또는 ICU_LOCALE을 지정해야 합니다." -#: commands/dbcommands.c:1105 -#, c-format -msgid "ICU locale cannot be specified unless locale provider is ICU" -msgstr "ICU 로케일은 ICU 로케일 제공자를 지정해야만 쓸 수 있습니다." - -#: commands/dbcommands.c:1128 +#: commands/dbcommands.c:1163 #, c-format msgid "" "new encoding (%s) is incompatible with the encoding of the template database " "(%s)" msgstr "새 인코딩(%s)이 템플릿 데이터베이스의 인코딩(%s)과 호환되지 않음" -#: commands/dbcommands.c:1131 +#: commands/dbcommands.c:1166 #, c-format msgid "" "Use the same encoding as in the template database, or use template0 as " @@ -7948,7 +8351,7 @@ msgstr "" "템플릿 데이터베이스와 동일한 인코딩을 사용하거나 template0을 템플릿으로 사용" "하십시오." -#: commands/dbcommands.c:1136 +#: commands/dbcommands.c:1171 #, c-format msgid "" "new collation (%s) is incompatible with the collation of the template " @@ -7957,7 +8360,7 @@ msgstr "" "새 데이터 정렬 규칙 (%s)이 템플릿 데이터베이스의 데이터 정렬 규칙(%s)과 호환" "되지 않음" -#: commands/dbcommands.c:1138 +#: commands/dbcommands.c:1173 #, c-format msgid "" "Use the same collation as in the template database, or use template0 as " @@ -7966,14 +8369,14 @@ msgstr "" "템플릿 데이터베이스와 동일한 데이터 정렬 규칙을 사용하거나 template0을 템플릿" "으로 사용하십시오." -#: commands/dbcommands.c:1143 +#: commands/dbcommands.c:1178 #, c-format msgid "" "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database " "(%s)" msgstr "새 LC_CTYPE (%s)이 템플릿 데이터베이스의 LC_CTYPE (%s)과 호환되지 않음" -#: commands/dbcommands.c:1145 +#: commands/dbcommands.c:1180 #, c-format msgid "" "Use the same LC_CTYPE as in the template database, or use template0 as " @@ -7982,7 +8385,7 @@ msgstr "" "템플릿 데이터베이스와 동일한 LC_CTYPE을 사용하거나 template0을 템플릿으로 사" "용하십시오." -#: commands/dbcommands.c:1150 +#: commands/dbcommands.c:1185 #, c-format msgid "" "new locale provider (%s) does not match locale provider of the template " @@ -7990,7 +8393,7 @@ msgid "" msgstr "" "새 로케일 제공자(%s)는 템플릿 데이터베이스의 로케일 제공자(%s)와 같지 않음" -#: commands/dbcommands.c:1152 +#: commands/dbcommands.c:1187 #, c-format msgid "" "Use the same locale provider as in the template database, or use template0 " @@ -7999,7 +8402,7 @@ msgstr "" "템플릿 데이터베이스와 동일한 로케일 제공자를 사용하거나 template0을 템플릿으" "로 사용하십시오." -#: commands/dbcommands.c:1164 +#: commands/dbcommands.c:1199 #, c-format msgid "" "new ICU locale (%s) is incompatible with the ICU locale of the template " @@ -8007,7 +8410,7 @@ msgid "" msgstr "" "새 ICU 로케일(%s)이 템플릿 데이터베이스의 ICU 로케일(%s)과 호환되지 않음" -#: commands/dbcommands.c:1166 +#: commands/dbcommands.c:1201 #, c-format msgid "" "Use the same ICU locale as in the template database, or use template0 as " @@ -8016,7 +8419,7 @@ msgstr "" "템플릿 데이터베이스와 동일한 ICU 로케일을 사용하거나 template0을 템플릿으로 " "사용하십시오." -#: commands/dbcommands.c:1177 +#: commands/dbcommands.c:1212 #, c-format msgid "" "new ICU collation rules (%s) are incompatible with the ICU collation rules " @@ -8025,7 +8428,7 @@ msgstr "" "새 ICU 문자열 정렬 규칙 (%s)이 템플릿 데이터베이스의 ICU 문자열 정렬 규칙(%s)" "과 호환되지 않음" -#: commands/dbcommands.c:1179 +#: commands/dbcommands.c:1214 #, c-format msgid "" "Use the same ICU collation rules as in the template database, or use " @@ -8034,7 +8437,7 @@ msgstr "" "템플릿 데이터베이스와 동일한 ICU 문자열 정렬 규칙을 사용하거나 template0을 템" "플릿으로 사용하십시오." -#: commands/dbcommands.c:1202 +#: commands/dbcommands.c:1243 #, c-format msgid "" "template database \"%s\" has a collation version, but no actual collation " @@ -8043,12 +8446,12 @@ msgstr "" "\"%s\" 템플릿 데이터베이스에는 문자 정렬 규칙 버전이 있는데, 그 실제 버전을 " "알 수 없음" -#: commands/dbcommands.c:1207 +#: commands/dbcommands.c:1248 #, c-format msgid "template database \"%s\" has a collation version mismatch" msgstr "\"%s\" 템플릿 데이터베이스의 문자 정렬 규칙 버전이 바르지 않음" -#: commands/dbcommands.c:1209 +#: commands/dbcommands.c:1250 #, c-format msgid "" "The template database was created using collation version %s, but the " @@ -8057,7 +8460,7 @@ msgstr "" "템플릿 데이터베이스는 문자 정렬 규칙 버전이 %s 이고, 운영체제는 %s 버전을 지" "원합니다." -#: commands/dbcommands.c:1212 +#: commands/dbcommands.c:1253 #, c-format msgid "" "Rebuild all objects in the template database that use the default collation " @@ -8068,17 +8471,17 @@ msgstr "" "고, ALTER DATABASE %s REFRESH COLLATION VERSION 명령을 실행하거나, 바른 버전" "의 라이브러리를 사용해서 PostgreSQL 엔진을 다시 만드십시오." -#: commands/dbcommands.c:1248 commands/dbcommands.c:1980 +#: commands/dbcommands.c:1298 commands/dbcommands.c:2041 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "pg_global을 기본 테이블스페이스로 사용할 수 없음" -#: commands/dbcommands.c:1274 +#: commands/dbcommands.c:1324 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "새 \"%s\" 테이블스페이스를 지정할 수 없습니다." -#: commands/dbcommands.c:1276 +#: commands/dbcommands.c:1326 #, c-format msgid "" "There is a conflict because database \"%s\" already has some tables in this " @@ -8087,106 +8490,107 @@ msgstr "" "\"%s\" 데이터베이스 소속 몇몇 테이블들이 이 테이블스페이스안에 있어서 충돌이 " "일어납니다." -#: commands/dbcommands.c:1306 commands/dbcommands.c:1853 +#: commands/dbcommands.c:1356 commands/dbcommands.c:1912 #, c-format msgid "database \"%s\" already exists" msgstr "\"%s\" 이름의 데이터베이스는 이미 있음" -#: commands/dbcommands.c:1320 +#: commands/dbcommands.c:1370 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "\"%s\" 원본 데이터베이스를 다른 사용자가 액세스하기 시작했습니다" -#: commands/dbcommands.c:1342 +#: commands/dbcommands.c:1392 #, c-format msgid "database OID %u is already in use by database \"%s\"" msgstr "%u OID 데이터베이스는 이미 \"%s\" 데이터베이스가 쓰고 있음" -#: commands/dbcommands.c:1348 +#: commands/dbcommands.c:1398 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "%u OID에 해당하는 데이터 디렉터리가 이미 있습니다." -#: commands/dbcommands.c:1520 commands/dbcommands.c:1535 +#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 +#: utils/adt/pg_locale.c:2588 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "\"%s\" 인코딩은 \"%s\" 로케일과 일치하지 않음" -#: commands/dbcommands.c:1523 +#: commands/dbcommands.c:1574 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "선택한 LC_CTYPE 설정에는 \"%s\" 인코딩이 필요합니다." -#: commands/dbcommands.c:1538 +#: commands/dbcommands.c:1589 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "선택한 LC_COLLATE 설정에는 \"%s\" 인코딩이 필요합니다." -#: commands/dbcommands.c:1619 +#: commands/dbcommands.c:1672 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "\"%s\" 데이터베이스 없음, 건너 뜀" -#: commands/dbcommands.c:1643 +#: commands/dbcommands.c:1696 #, c-format msgid "cannot drop a template database" msgstr "템플릿 데이터베이스는 삭제할 수 없습니다" -#: commands/dbcommands.c:1649 +#: commands/dbcommands.c:1702 #, c-format msgid "cannot drop the currently open database" msgstr "현재 열려 있는 데이터베이스는 삭제할 수 없습니다" -#: commands/dbcommands.c:1662 +#: commands/dbcommands.c:1715 #, c-format msgid "database \"%s\" is used by an active logical replication slot" msgstr "\"%s\" 데이터베이스는 논리 복제 슬롯이 활성화 되어 있습니다" -#: commands/dbcommands.c:1664 +#: commands/dbcommands.c:1717 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." msgstr[0] "%d 개의 활성 슬롯이 있습니다." -#: commands/dbcommands.c:1678 +#: commands/dbcommands.c:1731 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "\"%s\" 데이터베이스가 논리 복제 구독으로 사용되었음" -#: commands/dbcommands.c:1680 +#: commands/dbcommands.c:1733 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." msgstr[0] "%d 개의 구독이 있습니다." -#: commands/dbcommands.c:1701 commands/dbcommands.c:1875 -#: commands/dbcommands.c:2002 +#: commands/dbcommands.c:1754 commands/dbcommands.c:1934 +#: commands/dbcommands.c:2063 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "\"%s\" 데이터베이스를 다른 사용자가 액세스하기 시작했습니다" -#: commands/dbcommands.c:1835 +#: commands/dbcommands.c:1894 #, c-format msgid "permission denied to rename database" msgstr "데이터베이스 이름을 바꿀 권한이 없습니다" -#: commands/dbcommands.c:1864 +#: commands/dbcommands.c:1923 #, c-format msgid "current database cannot be renamed" msgstr "현재 데이터베이스의 이름을 바꿀 수 없음" -#: commands/dbcommands.c:1958 +#: commands/dbcommands.c:2019 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "현재 열려 있는 데이터베이스의 테이블스페이스를 바꿀 수 없음" -#: commands/dbcommands.c:2064 +#: commands/dbcommands.c:2125 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "" "\"%s\" 데이터베이스의 일부 릴레이션들이 \"%s\" 테이블스페이스에 이미 있음" -#: commands/dbcommands.c:2066 +#: commands/dbcommands.c:2127 #, c-format msgid "" "You must move them back to the database's default tablespace before using " @@ -8195,39 +8599,39 @@ msgstr "" "이 명령을 사용하기 전에 데이터베이스의 기본 테이블스페이스로 다시 이동해야 합" "니다." -#: commands/dbcommands.c:2193 commands/dbcommands.c:2909 -#: commands/dbcommands.c:3209 commands/dbcommands.c:3322 +#: commands/dbcommands.c:2256 commands/dbcommands.c:2999 +#: commands/dbcommands.c:3299 commands/dbcommands.c:3412 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "" "불필요한 일부 파일이 이전 데이터베이스 디렉터리 \"%s\"에 남아 있을 수 있음" -#: commands/dbcommands.c:2254 +#: commands/dbcommands.c:2317 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "알 수 없는 DROP DATABASE 옵션: \"%s\"" -#: commands/dbcommands.c:2332 +#: commands/dbcommands.c:2395 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "\"%s\" 옵션은 다른 옵션들과 함께 사용할 수 없습니다." -#: commands/dbcommands.c:2379 +#: commands/dbcommands.c:2443 #, c-format msgid "cannot alter invalid database \"%s\"" msgstr "잘못된 \"%s\" 데이터베이스에 대해 변경 작업을 할 수 없음" -#: commands/dbcommands.c:2396 +#: commands/dbcommands.c:2460 #, c-format msgid "cannot disallow connections for current database" msgstr "현재 데이터베이스 연결을 허용하지 않습니다." -#: commands/dbcommands.c:2611 +#: commands/dbcommands.c:2690 #, c-format msgid "permission denied to change owner of database" msgstr "데이터베이스 소유주를 바꿀 권한이 없습니다" -#: commands/dbcommands.c:3015 +#: commands/dbcommands.c:3105 #, c-format msgid "" "There are %d other session(s) and %d prepared transaction(s) using the " @@ -8235,448 +8639,458 @@ msgid "" msgstr "" "데이터베이스를 사용하는 %d개의 다른 세션과 %d개의 준비된 트랜잭션이 있습니다." -#: commands/dbcommands.c:3018 +#: commands/dbcommands.c:3108 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." msgstr[0] "데이터베이스를 사용하는 %d개의 다른 세션이 있습니다." -#: commands/dbcommands.c:3023 storage/ipc/procarray.c:3798 +#: commands/dbcommands.c:3113 storage/ipc/procarray.c:3859 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." msgstr[0] "데이터베이스를 사용하는 %d개의 준비된 트랜잭션이 있습니다." -#: commands/dbcommands.c:3165 +#: commands/dbcommands.c:3255 #, c-format msgid "missing directory \"%s\"" msgstr "\"%s\" 디렉터리가 빠졌음" -#: commands/dbcommands.c:3223 commands/tablespace.c:190 -#: commands/tablespace.c:639 +#: commands/dbcommands.c:3313 commands/tablespace.c:184 +#: commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "\"%s\" 디렉터리 상태를 파악할 수 없음: %m" -#: commands/define.c:54 commands/define.c:258 commands/define.c:290 -#: commands/define.c:318 commands/define.c:364 +#: commands/define.c:53 commands/define.c:257 commands/define.c:289 +#: commands/define.c:317 commands/define.c:363 #, c-format msgid "%s requires a parameter" msgstr "%s 매개 변수를 필요로 함" -#: commands/define.c:87 commands/define.c:98 commands/define.c:192 -#: commands/define.c:210 commands/define.c:225 commands/define.c:243 +#: commands/define.c:86 commands/define.c:97 commands/define.c:191 +#: commands/define.c:209 commands/define.c:224 commands/define.c:242 #, c-format msgid "%s requires a numeric value" msgstr "%s 숫자값을 필요로 함" -#: commands/define.c:154 +#: commands/define.c:153 #, c-format msgid "%s requires a Boolean value" msgstr "%s 값은 불리언 값이어야 합니다." -#: commands/define.c:168 commands/define.c:177 commands/define.c:327 +#: commands/define.c:167 commands/define.c:176 commands/define.c:326 #, c-format msgid "%s requires an integer value" msgstr "%s 하나의 정수값이 필요함" -#: commands/define.c:272 +#: commands/define.c:271 #, c-format msgid "argument of %s must be a name" msgstr "%s의 인자는 이름이어야 합니다" -#: commands/define.c:302 +#: commands/define.c:301 #, c-format msgid "argument of %s must be a type name" msgstr "%s의 인자는 자료형 이름이어야 합니다" -#: commands/define.c:348 +#: commands/define.c:347 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "%s의 잘못된 인자: \"%s\"" -#: commands/dropcmds.c:101 commands/functioncmds.c:1387 -#: utils/adt/ruleutils.c:2897 +#: commands/dropcmds.c:96 commands/functioncmds.c:1382 +#: utils/adt/ruleutils.c:2910 #, c-format msgid "\"%s\" is an aggregate function" msgstr "\"%s\" 함수는 집계 함수입니다" -#: commands/dropcmds.c:103 +#: commands/dropcmds.c:98 #, c-format msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "집계 함수는 DROP AGGREGATE 명령으로 삭제할 수 있습니다" -#: commands/dropcmds.c:158 commands/sequence.c:474 commands/tablecmds.c:3710 -#: commands/tablecmds.c:3868 commands/tablecmds.c:3920 -#: commands/tablecmds.c:16468 tcop/utility.c:1336 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3892 +#: commands/tablecmds.c:4050 commands/tablecmds.c:4102 +#: commands/tablecmds.c:17161 tcop/utility.c:1325 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "\"%s\" 릴레이션 없음, 건너뜀" -#: commands/dropcmds.c:188 commands/dropcmds.c:287 commands/tablecmds.c:1285 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1409 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "\"%s\" 스키마(schema) 없음, 건너뜀" -#: commands/dropcmds.c:228 commands/dropcmds.c:267 commands/tablecmds.c:277 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "\"%s\" 자료형 없음, 건너뜀" -#: commands/dropcmds.c:257 +#: commands/dropcmds.c:252 #, c-format msgid "access method \"%s\" does not exist, skipping" msgstr "\"%s\" 인덱스 접근 방법 없음, 건너뜀" -#: commands/dropcmds.c:275 +#: commands/dropcmds.c:270 #, c-format msgid "collation \"%s\" does not exist, skipping" msgstr "\"%s\" 정렬규칙 없음, 건너뜀" -#: commands/dropcmds.c:282 +#: commands/dropcmds.c:277 #, c-format msgid "conversion \"%s\" does not exist, skipping" msgstr "\"%s\" 문자코드변환규칙(conversion) 없음, 건너뜀" -#: commands/dropcmds.c:293 commands/statscmds.c:654 +#: commands/dropcmds.c:288 commands/statscmds.c:664 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "\"%s\" 통계정보 개체 없음, 무시함" -#: commands/dropcmds.c:300 +#: commands/dropcmds.c:295 #, c-format msgid "text search parser \"%s\" does not exist, skipping" msgstr "\"%s\" 전문 검색 파서가 없음, 건너뜀" -#: commands/dropcmds.c:307 +#: commands/dropcmds.c:302 #, c-format msgid "text search dictionary \"%s\" does not exist, skipping" msgstr "\"%s\" 전문 검색 사전이 없음, 건너뜀" -#: commands/dropcmds.c:314 +#: commands/dropcmds.c:309 #, c-format msgid "text search template \"%s\" does not exist, skipping" msgstr "\"%s\" 전문 검색 템플릿이 없음, 건너뜀" -#: commands/dropcmds.c:321 +#: commands/dropcmds.c:316 #, c-format msgid "text search configuration \"%s\" does not exist, skipping" msgstr "\"%s\" 전문 검색 구성이 없음, 건너뜀" -#: commands/dropcmds.c:326 +#: commands/dropcmds.c:321 #, c-format msgid "extension \"%s\" does not exist, skipping" msgstr "\"%s\" 확장 모듈 없음, 건너 뜀" -#: commands/dropcmds.c:336 +#: commands/dropcmds.c:331 #, c-format msgid "function %s(%s) does not exist, skipping" msgstr "%s(%s) 함수가 없음, 건너뜀" -#: commands/dropcmds.c:349 +#: commands/dropcmds.c:344 #, c-format msgid "procedure %s(%s) does not exist, skipping" msgstr "%s(%s) 프로시져 없음, 건너뜀" -#: commands/dropcmds.c:362 +#: commands/dropcmds.c:357 #, c-format msgid "routine %s(%s) does not exist, skipping" msgstr "%s(%s) 루틴 없음, 건너뜀" -#: commands/dropcmds.c:375 +#: commands/dropcmds.c:370 #, c-format msgid "aggregate %s(%s) does not exist, skipping" msgstr "%s(%s) 집계 함수 없음, 건너뜀" -#: commands/dropcmds.c:388 +#: commands/dropcmds.c:383 #, c-format msgid "operator %s does not exist, skipping" msgstr "%s 연산자가 없음, 건너뜀" -#: commands/dropcmds.c:394 +#: commands/dropcmds.c:389 #, c-format msgid "language \"%s\" does not exist, skipping" msgstr "\"%s\" 프로시주얼 언어 없음, 건너뜀" -#: commands/dropcmds.c:403 +#: commands/dropcmds.c:398 #, c-format msgid "cast from type %s to type %s does not exist, skipping" msgstr "%s 형에서 %s 형으로 바꾸는 형변환 규칙(cast)이 없음, 건너뜀" -#: commands/dropcmds.c:412 +#: commands/dropcmds.c:407 #, c-format msgid "transform for type %s language \"%s\" does not exist, skipping" msgstr "%s 형변환자 (사용언어 \"%s\") 없음, 건너뜀" -#: commands/dropcmds.c:420 +#: commands/dropcmds.c:415 #, c-format msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping" msgstr " \"%s\" 트리거가 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀" -#: commands/dropcmds.c:429 +#: commands/dropcmds.c:424 #, c-format msgid "policy \"%s\" for relation \"%s\" does not exist, skipping" msgstr " \"%s\" 정책이 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀" -#: commands/dropcmds.c:436 +#: commands/dropcmds.c:431 #, c-format msgid "event trigger \"%s\" does not exist, skipping" msgstr "\"%s\" 이벤트 트리거 없음, 건너뜀" -#: commands/dropcmds.c:442 +#: commands/dropcmds.c:437 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist, skipping" msgstr " \"%s\" 룰(rule)이 \"%s\" 릴레이션에 지정된 것이 없음, 건너뜀" -#: commands/dropcmds.c:449 +#: commands/dropcmds.c:444 #, c-format msgid "foreign-data wrapper \"%s\" does not exist, skipping" msgstr "\"%s\" 외부 자료 래퍼가 없음, 건너뜀" -#: commands/dropcmds.c:453 commands/foreigncmds.c:1360 +#: commands/dropcmds.c:448 commands/foreigncmds.c:1360 #, c-format msgid "server \"%s\" does not exist, skipping" msgstr "\"%s\" 서버가 없음, 건너뜀" -#: commands/dropcmds.c:462 +#: commands/dropcmds.c:457 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\", skipping" msgstr "" "\"%s\" 연산자 클래스는 \"%s\" 인덱스 접근 방법에서 사용할 수 없음, 건너뜀" -#: commands/dropcmds.c:474 +#: commands/dropcmds.c:469 #, c-format msgid "" "operator family \"%s\" does not exist for access method \"%s\", skipping" msgstr "\"%s\" 연산자 패밀리(\"%s\" 접근 방법)가 없음, 건너뜀" -#: commands/dropcmds.c:481 +#: commands/dropcmds.c:476 #, c-format msgid "publication \"%s\" does not exist, skipping" msgstr "\"%s\" 발행 없음, 건너뜀" -#: commands/event_trigger.c:125 +#: commands/event_trigger.c:137 #, c-format msgid "permission denied to create event trigger \"%s\"" msgstr "\"%s\" 이벤트 트리거를 만들 권한이 없음" -#: commands/event_trigger.c:127 +#: commands/event_trigger.c:139 #, c-format msgid "Must be superuser to create an event trigger." msgstr "슈퍼유저만 이벤트 트리거를 만들 수 있습니다." -#: commands/event_trigger.c:136 +#: commands/event_trigger.c:149 #, c-format msgid "unrecognized event name \"%s\"" msgstr "알 수 없는 이벤트 이름: \"%s\"" -#: commands/event_trigger.c:153 +#: commands/event_trigger.c:166 #, c-format msgid "unrecognized filter variable \"%s\"" msgstr "알 수 없는 필터 변수: \"%s\"" -#: commands/event_trigger.c:207 +#: commands/event_trigger.c:181 +#, c-format +msgid "tag filtering is not supported for login event triggers" +msgstr "태그 필터링은 로그인 이벤트 트리거용으로 쓸 수 없음" + +#: commands/event_trigger.c:224 #, c-format msgid "filter value \"%s\" not recognized for filter variable \"%s\"" msgstr "\"%s\" 필터값은 \"%s\" 필터 변수으로 쓸 수 없음" #. translator: %s represents an SQL statement name -#: commands/event_trigger.c:213 commands/event_trigger.c:235 +#: commands/event_trigger.c:230 commands/event_trigger.c:252 #, c-format msgid "event triggers are not supported for %s" msgstr "%s 용 이벤트 트리거는 지원하지 않음" -#: commands/event_trigger.c:248 +#: commands/event_trigger.c:265 #, c-format msgid "filter variable \"%s\" specified more than once" msgstr "\"%s\" 필터 변수가 한 번 이상 사용되었습니다." -#: commands/event_trigger.c:376 commands/event_trigger.c:420 -#: commands/event_trigger.c:514 +#: commands/event_trigger.c:438 commands/event_trigger.c:490 +#: commands/event_trigger.c:584 #, c-format msgid "event trigger \"%s\" does not exist" msgstr "\"%s\" 이벤트 트리거 없음" -#: commands/event_trigger.c:452 +#: commands/event_trigger.c:522 #, c-format msgid "event trigger with OID %u does not exist" msgstr "OID %u 이벤트 트리거가 없음" -#: commands/event_trigger.c:482 +#: commands/event_trigger.c:552 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" msgstr "\"%s\" 이벤트 트리거 소유주를 변경할 권한이 없음" -#: commands/event_trigger.c:484 +#: commands/event_trigger.c:554 #, c-format msgid "The owner of an event trigger must be a superuser." msgstr "이벤트 트리거 소유주는 슈퍼유저여야 합니다." -#: commands/event_trigger.c:1304 +#: commands/event_trigger.c:1409 #, c-format msgid "%s can only be called in a sql_drop event trigger function" msgstr "%s 개체는 sql_drop 이벤트 트리거 함수 안에서만 호출 되어야 합니다." -#: commands/event_trigger.c:1397 commands/event_trigger.c:1418 +#: commands/event_trigger.c:1502 commands/event_trigger.c:1523 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" msgstr "" "%s 개체는 table_rewrite 이벤트 트리거 함수 안에서만 호출 되어야 합니다." -#: commands/event_trigger.c:1831 +#: commands/event_trigger.c:1936 #, c-format msgid "%s can only be called in an event trigger function" msgstr "%s 개체는 이벤트 트리거 함수 안에서만 호출 되어야 합니다." -#: commands/explain.c:220 +#: commands/explain.c:241 commands/explain.c:266 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "\"%s\" EXPLAIN 옵션에서 쓸 수 없는 값: \"%s\"" -#: commands/explain.c:227 +#: commands/explain.c:273 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "잘못된 EXPLAIN 옵션: \"%s\"" -#: commands/explain.c:236 +#: commands/explain.c:282 #, c-format msgid "EXPLAIN option WAL requires ANALYZE" msgstr "WAL 옵션은 EXPLAIN ANALYZE에서만 쓸 수 있습니다." -#: commands/explain.c:245 +#: commands/explain.c:291 #, c-format msgid "EXPLAIN option TIMING requires ANALYZE" msgstr "TIMING 옵션은 EXPLAIN ANALYZE에서만 쓸 수 있습니다." -#: commands/explain.c:251 +#: commands/explain.c:297 +#, c-format +msgid "EXPLAIN option SERIALIZE requires ANALYZE" +msgstr "SERIALIZE 옵션은 EXPLAIN ANALYZE에서만 쓸 수 있습니다." + +#: commands/explain.c:303 #, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" msgstr "" "EXPLAIN 옵션으로 ANALYZE 옵션과 GENERIC_PLAN 옵션을 함께 사용할 수 없습니다." -#: commands/extension.c:177 commands/extension.c:3033 +#: commands/extension.c:178 commands/extension.c:3031 #, c-format msgid "extension \"%s\" does not exist" msgstr "\"%s\" 이름의 확장 모듈이 없습니다" -#: commands/extension.c:276 commands/extension.c:285 commands/extension.c:297 -#: commands/extension.c:307 +#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 +#: commands/extension.c:308 #, c-format msgid "invalid extension name: \"%s\"" msgstr "잘못된 확장 모듈 이름: \"%s\"" -#: commands/extension.c:277 +#: commands/extension.c:278 #, c-format msgid "Extension names must not be empty." msgstr "확장 모듈 이름을 지정하세요." -#: commands/extension.c:286 +#: commands/extension.c:287 #, c-format msgid "Extension names must not contain \"--\"." msgstr "확장 모듈 이름에 \"--\" 문자가 포함될 수 없습니다." -#: commands/extension.c:298 +#: commands/extension.c:299 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "확장 모듈 이름의 시작과 끝에는 \"-\" 문자를 사용할 수 없습니다." -#: commands/extension.c:308 +#: commands/extension.c:309 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "확장 모듈 이름에는 디렉터리 구분 문자를 사용할 수 없습니다." -#: commands/extension.c:323 commands/extension.c:332 commands/extension.c:341 -#: commands/extension.c:351 +#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 +#: commands/extension.c:352 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "잘못된 확장 모듈 버전 이름: \"%s\"" -#: commands/extension.c:324 +#: commands/extension.c:325 #, c-format msgid "Version names must not be empty." msgstr "버전 이름은 비어있으면 안됩니다" -#: commands/extension.c:333 +#: commands/extension.c:334 #, c-format msgid "Version names must not contain \"--\"." msgstr "버전 이름에 \"--\" 문자가 포함될 수 없습니다." -#: commands/extension.c:342 +#: commands/extension.c:343 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "버전 이름의 앞 뒤에 \"-\" 문자를 쓸 수 없습니다." -#: commands/extension.c:352 +#: commands/extension.c:353 #, c-format msgid "Version names must not contain directory separator characters." msgstr "버전 이름에는 디렉터리 분리 문자를 쓸 수 없습니다." -#: commands/extension.c:506 +#: commands/extension.c:507 #, c-format msgid "extension \"%s\" is not available" msgstr "\"%s\" 이름의 확장 모듈을 사용할 수 없습니다" -#: commands/extension.c:507 +#: commands/extension.c:508 #, c-format msgid "Could not open extension control file \"%s\": %m." msgstr "\"%s\" 확장 모듈 제어 파일 열기 실패: %m." -#: commands/extension.c:509 +#: commands/extension.c:510 #, c-format msgid "" "The extension must first be installed on the system where PostgreSQL is " "running." msgstr "해당 확장 모듈은 PostgreSQL 시작 전에 먼저 설치 되어 있어야합니다." -#: commands/extension.c:513 +#: commands/extension.c:514 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "\"%s\" 확장 모듈 제어 파일 열기 실패: %m" -#: commands/extension.c:536 commands/extension.c:546 +#: commands/extension.c:537 commands/extension.c:547 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "\"%s\" 매개 변수는 이차 확장 모듈 제어 파일에서는 사용할 수 없습니다." -#: commands/extension.c:568 commands/extension.c:576 commands/extension.c:584 -#: utils/misc/guc.c:3098 +#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 +#: utils/misc/guc.c:3147 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "\"%s\" 매개 변수의 값은 불리언 값이어야 합니다." -#: commands/extension.c:593 +#: commands/extension.c:594 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" 이름은 잘못된 인코딩 이름임" -#: commands/extension.c:607 commands/extension.c:622 +#: commands/extension.c:608 commands/extension.c:623 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "\"%s\" 매개 변수는 확장 모듈 이름 목록이어야 함" -#: commands/extension.c:629 +#: commands/extension.c:630 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "알 수 없는 \"%s\" 매개 변수가 \"%s\" 파일 안에 있습니다." -#: commands/extension.c:638 +#: commands/extension.c:639 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "" "\"relocatable\" 값이 true 인 경우 \"schema\" 매개 변수는 사용할 수 없습니다." -#: commands/extension.c:816 +#: commands/extension.c:817 #, c-format msgid "" "transaction control statements are not allowed within an extension script" msgstr "확장 모듈 스크립트 안에서는 트랜잭션 제어 구문은 사용할 수 없습니다." -#: commands/extension.c:896 +#: commands/extension.c:897 #, c-format msgid "permission denied to create extension \"%s\"" msgstr "\"%s\" 확장 모듈을 만들 권한이 없습니다" -#: commands/extension.c:899 +#: commands/extension.c:900 #, c-format msgid "" "Must have CREATE privilege on current database to create this extension." @@ -8684,17 +9098,17 @@ msgstr "" "이 확장 모듈을 설치하려면 현재 데이터베이스에 대해서 CREATE 권한이 있어야 합" "니다." -#: commands/extension.c:900 +#: commands/extension.c:901 #, c-format msgid "Must be superuser to create this extension." msgstr "확장 모듈은 슈퍼유저만 만들 수 있습니다." -#: commands/extension.c:904 +#: commands/extension.c:905 #, c-format msgid "permission denied to update extension \"%s\"" msgstr "\"%s\" 확장 모듈을 업데이트할 권한이 없습니다." -#: commands/extension.c:907 +#: commands/extension.c:908 #, c-format msgid "" "Must have CREATE privilege on current database to update this extension." @@ -8702,24 +9116,24 @@ msgstr "" "이 확장 모듈을 업데이트 하려면 현재 데이터베이스에 대해서 CREATE 권한이 있어" "야 합니다." -#: commands/extension.c:908 +#: commands/extension.c:909 #, c-format msgid "Must be superuser to update this extension." msgstr "슈퍼유저만 해당 모듈을 업데이트 할 수 있습니다." -#: commands/extension.c:1046 +#: commands/extension.c:1042 #, c-format msgid "invalid character in extension owner: must not contain any of \"%s\"" msgstr "해당 모듈 소유주 이름에 잘못된 문자: \"%s\" 문자는 허용하지 않음" -#: commands/extension.c:1070 commands/extension.c:1097 +#: commands/extension.c:1066 commands/extension.c:1093 #, c-format msgid "" "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" msgstr "" "확장 모듈 \"%s\" 스키마 이름에 잘못된 문자: \"%s\" 문자는 허용하지 않음" -#: commands/extension.c:1292 +#: commands/extension.c:1288 #, c-format msgid "" "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" @@ -8727,96 +9141,96 @@ msgstr "" "\"%s\" 확장 모듈을 \"%s\" 버전에서 \"%s\" 버전으로 업데이트할 방법이 없습니" "다." -#: commands/extension.c:1500 commands/extension.c:3091 +#: commands/extension.c:1496 commands/extension.c:3089 #, c-format msgid "version to install must be specified" msgstr "설치할 버전을 지정해야 합니다." -#: commands/extension.c:1537 +#: commands/extension.c:1533 #, c-format msgid "" -"extension \"%s\" has no installation script nor update path for version \"%s" -"\"" +"extension \"%s\" has no installation script nor update path for version " +"\"%s\"" msgstr "" "\"%s\" 확장 모듈에는 \"%s\" 버전용 설치나 업데이트 스크립트가 없습니다." -#: commands/extension.c:1571 +#: commands/extension.c:1567 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "\"%s\" 확장 모듈은 \"%s\" 스키마 안에 설치되어야 합니다." -#: commands/extension.c:1731 +#: commands/extension.c:1727 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "\"%s\" 확장 모듈과 \"%s\" 확장 모듈이 서로 의존 관계입니다" -#: commands/extension.c:1736 +#: commands/extension.c:1732 #, c-format msgid "installing required extension \"%s\"" msgstr "\"%s\" 확장 모듈이 필요해서 실치 하는 중" -#: commands/extension.c:1759 +#: commands/extension.c:1755 #, c-format msgid "required extension \"%s\" is not installed" msgstr "\"%s\" 확장 모듈이 필요한데, 설치되어 있지 않습니다." -#: commands/extension.c:1762 +#: commands/extension.c:1758 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "" "필요한 모듈을 함께 설치하려면, CREATE EXTENSION ... CASCADE 구문을 사용하세" "요." -#: commands/extension.c:1797 +#: commands/extension.c:1793 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "\"%s\" 확장 모듈이 이미 있음, 건너뜀" -#: commands/extension.c:1804 +#: commands/extension.c:1800 #, c-format msgid "extension \"%s\" already exists" msgstr "\"%s\" 이름의 확장 모듈이 이미 있습니다" -#: commands/extension.c:1815 +#: commands/extension.c:1811 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "중첩된 CREATE EXTENSION 구문은 지원하지 않습니다." -#: commands/extension.c:1979 +#: commands/extension.c:1975 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "%s 의존개체들은 시스템 개체이기 때문에 삭제 될 수 없습니다" -#: commands/extension.c:2454 +#: commands/extension.c:2450 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "" "%s 함수는 CREATE EXTENSION 명령에서 내부적으로 사용하는 SQL 스크립트 내에서" "만 사용할 수 있습니다." -#: commands/extension.c:2466 +#: commands/extension.c:2462 #, c-format msgid "OID %u does not refer to a table" msgstr "%u OID 자료가 테이블에 없습니다" -#: commands/extension.c:2471 +#: commands/extension.c:2467 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "\"%s\" 테이블은 만들려고 하는 확장 모듈의 구성 요소가 아닙니다." -#: commands/extension.c:2817 +#: commands/extension.c:2813 #, c-format msgid "" "cannot move extension \"%s\" into schema \"%s\" because the extension " "contains the schema" msgstr "\"%s\" 확장 모듈이 \"%s\" 스키마에 이미 있어 옮길 수 없습니다." -#: commands/extension.c:2858 commands/extension.c:2952 +#: commands/extension.c:2854 commands/extension.c:2948 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "\"%s\" 확장 모듈은 SET SCHEMA 구문을 지원하지 않음" -#: commands/extension.c:2915 +#: commands/extension.c:2911 #, c-format msgid "" "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" @@ -8824,32 +9238,32 @@ msgstr "" "다른 확장 모듈이 해당 스키마를 선점하고 있어, \"%s\" 확장 모듈은 SET SCHEMA " "작업을 할 수 없음." -#: commands/extension.c:2917 +#: commands/extension.c:2913 #, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." msgstr "\"%s\" 확장 모듈은 \"%s\" 확장모듈의 위치 변경을 금지합니다." -#: commands/extension.c:2954 +#: commands/extension.c:2950 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "%s 개체가 확장 모듈 스키마인 \"%s\" 안에 없음" -#: commands/extension.c:3013 +#: commands/extension.c:3011 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "중첩된 ALTER EXTENSION 구문을 지원하지 않음" -#: commands/extension.c:3102 +#: commands/extension.c:3100 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "\"%s\" 버전의 \"%s\" 확장 모듈이 이미 설치 되어 있음" -#: commands/extension.c:3314 +#: commands/extension.c:3311 #, c-format msgid "cannot add an object of this type to an extension" msgstr "해당 확장 모듈에 이런 형태의 객체는 추가 할 수 없음" -#: commands/extension.c:3380 +#: commands/extension.c:3409 #, c-format msgid "" "cannot add schema \"%s\" to extension \"%s\" because the schema contains the " @@ -8858,7 +9272,12 @@ msgstr "" "\"%s\" 스키마에 \"%s\" 확장 모듈을 추가할 수 없음, 이미 해당 스키마 안에 포" "함되어 있음" -#: commands/extension.c:3474 +#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#, c-format +msgid "could not find multirange type for data type %s" +msgstr "%s 자료형용 multirange 형을 찾을 수 없음" + +#: commands/extension.c:3532 #, c-format msgid "file \"%s\" is too large" msgstr "\"%s\" 파일이 너무 큽니다." @@ -8888,7 +9307,7 @@ msgstr "슈퍼유저만 외부 자료 래퍼의 소유주를 바꿀 수 있습 msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "외부 자료 래퍼의 소유주는 슈퍼유저여야 합니다." -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:678 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "\"%s\" 외부 자료 래퍼가 없음" @@ -8921,7 +9340,7 @@ msgstr "\"%s\" 외부 자료 래퍼를 변경할 권한이 없음" #: commands/foreigncmds.c:699 #, c-format msgid "Must be superuser to alter a foreign-data wrapper." -msgstr "슈퍼유저만 외부 자료 래퍼를 변경할 수 있습니다." +msgstr "슈퍼유저만 외부 자료 래퍼를 바꿀 수 있습니다." #: commands/foreigncmds.c:730 #, c-format @@ -8966,7 +9385,7 @@ msgstr "\"%s\" 사용자 매핑이 \"%s\" 서버용으로 없음" msgid "user mapping for \"%s\" does not exist for server \"%s\", skipping" msgstr "\"%s\" 사용자 매핑이 \"%s\" 서버용으로 없음, 건너뜀" -#: commands/foreigncmds.c:1507 foreign/foreign.c:391 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "\"%s\" 외부 자료 래퍼용 핸들러가 없음" @@ -8981,229 +9400,229 @@ msgstr "\"%s\" 외부 자료 래퍼는 IMPORT FOREIGN SCHEMA 구문을 지원하 msgid "importing foreign table \"%s\"" msgstr "\"%s\" 외부 테이블 가져 오는 중" -#: commands/functioncmds.c:109 +#: commands/functioncmds.c:104 #, c-format msgid "SQL function cannot return shell type %s" msgstr "SQL 함수는 shell type %s 리턴할 수 없음" -#: commands/functioncmds.c:114 +#: commands/functioncmds.c:109 #, c-format msgid "return type %s is only a shell" msgstr "_^_ %s 리턴 자료형은 하나의 shell만 있습니다" -#: commands/functioncmds.c:143 parser/parse_type.c:354 +#: commands/functioncmds.c:138 parser/parse_type.c:354 #, c-format msgid "type modifier cannot be specified for shell type \"%s\"" msgstr "\"%s\" 셸 형식에 대해 형식 한정자를 지정할 수 없음" -#: commands/functioncmds.c:149 +#: commands/functioncmds.c:144 #, c-format msgid "type \"%s\" is not yet defined" msgstr "\"%s\" 자료형이 아직 정의되지 않았음" -#: commands/functioncmds.c:150 +#: commands/functioncmds.c:145 #, c-format msgid "Creating a shell type definition." msgstr "셸 타입 정의를 만들고 있습니다" -#: commands/functioncmds.c:249 +#: commands/functioncmds.c:244 #, c-format msgid "SQL function cannot accept shell type %s" msgstr "SQL 함수는 셸 타입 %s 수용할 수 없음" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:250 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "집계 함수는 셸 타입 %s 수용할 수 없음" -#: commands/functioncmds.c:260 +#: commands/functioncmds.c:255 #, c-format msgid "argument type %s is only a shell" msgstr "%s 인자 자료형은 단지 셸입니다" -#: commands/functioncmds.c:270 +#: commands/functioncmds.c:265 #, c-format msgid "type %s does not exist" msgstr "%s 자료형 없음" -#: commands/functioncmds.c:284 +#: commands/functioncmds.c:279 #, c-format msgid "aggregates cannot accept set arguments" msgstr "집계 함수는 세트 인자를 입력 인자로 쓸 수 없음" -#: commands/functioncmds.c:288 +#: commands/functioncmds.c:283 #, c-format msgid "procedures cannot accept set arguments" msgstr "프로시져에서는 집합 인자를 입력 인자로 쓸 수 없음" -#: commands/functioncmds.c:292 +#: commands/functioncmds.c:287 #, c-format msgid "functions cannot accept set arguments" msgstr "함수는 세트 인자를 쓸 수 없음" -#: commands/functioncmds.c:302 +#: commands/functioncmds.c:297 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "VARIADIC 매개 변수는 마지막 입력 매개 변수여야 함" -#: commands/functioncmds.c:322 +#: commands/functioncmds.c:317 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "VARIADIC 매개 변수는 마지막 매개 변수여야 함" -#: commands/functioncmds.c:347 +#: commands/functioncmds.c:342 #, c-format msgid "VARIADIC parameter must be an array" msgstr "VARIADIC 매개 변수는 배열이어야 함" -#: commands/functioncmds.c:392 +#: commands/functioncmds.c:387 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "\"%s\" 매개 변수가 여러 번 사용 됨" -#: commands/functioncmds.c:410 +#: commands/functioncmds.c:405 #, c-format msgid "only input parameters can have default values" msgstr "입력 매개 변수에서만 기본값을 사용할 수 있음" -#: commands/functioncmds.c:425 +#: commands/functioncmds.c:420 #, c-format msgid "cannot use table references in parameter default value" msgstr "입력 매개 변수 초기값으로 테이블 참조형은 사용할 수 없음" -#: commands/functioncmds.c:449 +#: commands/functioncmds.c:444 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "" "기본 값이 있는 입력 매개 변수 뒤에 오는 입력 매개 변수에도 기본 값이 있어야 " "함" -#: commands/functioncmds.c:459 +#: commands/functioncmds.c:454 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "프로시지 OUT 매개 변수는 기본값이 있는 매개 변수 뒤에 지정하면 안됨" -#: commands/functioncmds.c:601 commands/functioncmds.c:780 +#: commands/functioncmds.c:596 commands/functioncmds.c:775 #, c-format msgid "invalid attribute in procedure definition" msgstr "프로시져 정의에 잘못된 속성이 있음" -#: commands/functioncmds.c:697 +#: commands/functioncmds.c:692 #, c-format msgid "support function %s must return type %s" msgstr "%s support 함수는 %s 자료형을 반환해야 함" -#: commands/functioncmds.c:708 +#: commands/functioncmds.c:703 #, c-format msgid "must be superuser to specify a support function" msgstr "support 함수를 지정하려면 슈퍼유져여야 합니다" -#: commands/functioncmds.c:829 commands/functioncmds.c:1432 +#: commands/functioncmds.c:824 commands/functioncmds.c:1427 #, c-format msgid "COST must be positive" msgstr "COST는 양수여야 함" -#: commands/functioncmds.c:837 commands/functioncmds.c:1440 +#: commands/functioncmds.c:832 commands/functioncmds.c:1435 #, c-format msgid "ROWS must be positive" msgstr "ROWS는 양수여야 함" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:861 #, c-format msgid "no function body specified" msgstr "함수 본문(body) 부분이 빠졌습니다" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:866 #, c-format msgid "duplicate function body specified" msgstr "함수 본문(body) 부분을 중복 지정했습니다" -#: commands/functioncmds.c:876 +#: commands/functioncmds.c:871 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "함수의 language 값이 SQL일 때만 인라인 SQL 함수 본문을 쓸 수 있음" -#: commands/functioncmds.c:918 +#: commands/functioncmds.c:913 #, c-format msgid "" "SQL function with unquoted function body cannot have polymorphic arguments" msgstr "" "따옴표 없는 함수 본문을 사용하는 SQL 함수는 다형 자료형 인자를 쓸 수 없음" -#: commands/functioncmds.c:944 commands/functioncmds.c:963 +#: commands/functioncmds.c:939 commands/functioncmds.c:958 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "%s 구문은 따옴표 없는 SQL 함수 본문 안에서 지원하지 않음" -#: commands/functioncmds.c:991 +#: commands/functioncmds.c:986 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "\"%s\" 언어에는 하나의 AS 항목만 필요함" -#: commands/functioncmds.c:1096 +#: commands/functioncmds.c:1091 #, c-format msgid "no language specified" msgstr "처리할 프로시주얼 언어를 지정하지 않았습니다" -#: commands/functioncmds.c:1104 commands/functioncmds.c:2105 -#: commands/proclang.c:237 +#: commands/functioncmds.c:1099 commands/functioncmds.c:2117 +#: commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "\"%s\" 프로시주얼 언어 없음" -#: commands/functioncmds.c:1106 commands/functioncmds.c:2107 +#: commands/functioncmds.c:1101 commands/functioncmds.c:2119 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "" "데이터베이스 내에서 프로시주얼 언어를 사용하려면 먼저 CREATE EXTENSION 명령으" "로 사용할 언어를 등록하세요." -#: commands/functioncmds.c:1139 commands/functioncmds.c:1424 +#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 #, c-format msgid "only superuser can define a leakproof function" msgstr "슈퍼유저만 leakproof 함수를 만들 수 있습니다" -#: commands/functioncmds.c:1190 +#: commands/functioncmds.c:1185 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "OUT 매개 변수로 인해 함수 결과 형식은 %s이어야 함" -#: commands/functioncmds.c:1203 +#: commands/functioncmds.c:1198 #, c-format msgid "function result type must be specified" msgstr "함수의 리턴 자료형을 지정해야 합니다" -#: commands/functioncmds.c:1256 commands/functioncmds.c:1444 +#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "함수에서 세트를 반환하지 않는 경우 ROWS를 적용할 수 없음" -#: commands/functioncmds.c:1547 +#: commands/functioncmds.c:1546 #, c-format msgid "source data type %s is a pseudo-type" msgstr "%s 원본 자료형이 의사자료형(pseudo-type) 입니다" -#: commands/functioncmds.c:1553 +#: commands/functioncmds.c:1552 #, c-format msgid "target data type %s is a pseudo-type" msgstr "%s 대상 자료형이 의사자료형(pseudo-type) 입니다" -#: commands/functioncmds.c:1577 +#: commands/functioncmds.c:1576 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "원본 자료형이 도메인이어서 자료형 변환을 무시합니다." -#: commands/functioncmds.c:1582 +#: commands/functioncmds.c:1581 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "대상 자료형이 도메인이어서 자료형 변환을 무시합니다." -#: commands/functioncmds.c:1607 +#: commands/functioncmds.c:1606 #, c-format msgid "cast function must take one to three arguments" msgstr "형변환 함수는 1-3개의 인자만 지정할 수 있습니다" -#: commands/functioncmds.c:1613 +#: commands/functioncmds.c:1612 #, c-format msgid "" "argument of cast function must match or be binary-coercible from source data " @@ -9212,17 +9631,17 @@ msgstr "" "형변환 함수의 인자로 쓸 자료형은 원본 자료형과 일치하거나 바이너리 차원으로 " "같은 자료형이어야 함" -#: commands/functioncmds.c:1617 +#: commands/functioncmds.c:1616 #, c-format msgid "second argument of cast function must be type %s" msgstr "형변화 함수의 두번째 인자 자료형은 반드시 %s 형이여야 합니다" -#: commands/functioncmds.c:1622 +#: commands/functioncmds.c:1621 #, c-format msgid "third argument of cast function must be type %s" msgstr "형변화 함수의 세번째 인자 자료형은 반드시 %s 형이여야 합니다" -#: commands/functioncmds.c:1629 +#: commands/functioncmds.c:1628 #, c-format msgid "" "return data type of cast function must match or be binary-coercible to " @@ -9231,219 +9650,228 @@ msgstr "" "형변환 함수의 반환 자료형은 대상 자료형과 일치하거나 바이너리 차원으로 같은 " "자료형이어야 함" -#: commands/functioncmds.c:1640 +#: commands/functioncmds.c:1639 #, c-format msgid "cast function must not be volatile" msgstr "형변환 함수는 volatile 특성이 없어야 합니다" -#: commands/functioncmds.c:1645 +#: commands/functioncmds.c:1644 #, c-format msgid "cast function must be a normal function" msgstr "형변환 함수는 일반 함수여야 합니다" -#: commands/functioncmds.c:1649 +#: commands/functioncmds.c:1648 #, c-format msgid "cast function must not return a set" msgstr "형변환 함수는 세트(set)를 리턴할 수 없습니다" -#: commands/functioncmds.c:1675 +#: commands/functioncmds.c:1674 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "CREATE CAST ... WITHOUT FUNCTION 명령은 슈퍼유저만 실행할 수 있습니다" -#: commands/functioncmds.c:1690 +#: commands/functioncmds.c:1689 #, c-format msgid "source and target data types are not physically compatible" msgstr "원본 자료형과 대상 자료형이 서로 논리적인 호환성이 없습니다" -#: commands/functioncmds.c:1705 +#: commands/functioncmds.c:1709 #, c-format msgid "composite data types are not binary-compatible" msgstr "복합 자료형은 바이너리와 호환되지 않음" -#: commands/functioncmds.c:1711 -#, c-format -msgid "enum data types are not binary-compatible" -msgstr "열거 자료형은 바이너리와 호환되지 않음" - -#: commands/functioncmds.c:1717 +#: commands/functioncmds.c:1715 #, c-format msgid "array data types are not binary-compatible" msgstr "배열 자료형은 바이너리와 호환되지 않음" -#: commands/functioncmds.c:1734 +#: commands/functioncmds.c:1723 +#, c-format +msgid "range data types are not binary-compatible" +msgstr "범위 자료형은 바이너리와 호환되지 않음" + +#: commands/functioncmds.c:1729 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "열거 자료형은 바이너리와 호환되지 않음" + +#: commands/functioncmds.c:1746 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "도메인 자료형은 바이너리와 호환되지 않음" -#: commands/functioncmds.c:1744 +#: commands/functioncmds.c:1756 #, c-format msgid "source data type and target data type are the same" msgstr "원본 자료형과 대상 자료형의 형태가 같습니다" -#: commands/functioncmds.c:1777 +#: commands/functioncmds.c:1789 #, c-format msgid "transform function must not be volatile" msgstr "형변환 함수는 volatile 특성이 없어야 합니다" -#: commands/functioncmds.c:1781 +#: commands/functioncmds.c:1793 #, c-format msgid "transform function must be a normal function" msgstr "형변환 함수는 일반 함수여야 합니다." -#: commands/functioncmds.c:1785 +#: commands/functioncmds.c:1797 #, c-format msgid "transform function must not return a set" msgstr "형변환 함수는 세트(set)를 리턴할 수 없습니다" -#: commands/functioncmds.c:1789 +#: commands/functioncmds.c:1801 #, c-format msgid "transform function must take one argument" msgstr "형변환 함수는 1개의 인자만 지정할 수 있습니다" -#: commands/functioncmds.c:1793 +#: commands/functioncmds.c:1805 #, c-format msgid "first argument of transform function must be type %s" msgstr "형변화 함수의 첫번째 인자 자료형은 반드시 %s 형이여야 합니다" -#: commands/functioncmds.c:1832 +#: commands/functioncmds.c:1844 #, c-format msgid "data type %s is a pseudo-type" msgstr "%s 자료형은 의사자료형(pseudo-type) 입니다" -#: commands/functioncmds.c:1838 +#: commands/functioncmds.c:1850 #, c-format msgid "data type %s is a domain" msgstr "%s 자료형은 도메인입니다" -#: commands/functioncmds.c:1878 +#: commands/functioncmds.c:1890 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "FROM SQL 함수의 반환 자료형은 %s 형이어야 함" -#: commands/functioncmds.c:1904 +#: commands/functioncmds.c:1916 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "TO SQL 함수의 반환 자료형은 변환 자료형이어야 함" -#: commands/functioncmds.c:1931 +#: commands/functioncmds.c:1943 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "%s 자료형(대상 언어: \"%s\")을 위한 형변환 규칙은 이미 있습니다." -#: commands/functioncmds.c:2017 +#: commands/functioncmds.c:2029 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "%s 자료형(대상 언어: \"%s\")을 위한 형변환 규칙은 없습니다." -#: commands/functioncmds.c:2041 +#: commands/functioncmds.c:2053 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "%s 함수는 이미 \"%s\" 스키마안에 있습니다" -#: commands/functioncmds.c:2092 +#: commands/functioncmds.c:2104 #, c-format msgid "no inline code specified" msgstr "내장 코드가 빠졌습니다" -#: commands/functioncmds.c:2138 +#: commands/functioncmds.c:2150 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "\"%s\" 프로시주얼 언어는 내장 코드 실행 기능을 지원하지 않습니다" -#: commands/functioncmds.c:2233 +#: commands/functioncmds.c:2245 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" msgstr[0] "프로시져에 %d개의 인자 이상을 전달할 수 없음" -#: commands/indexcmds.c:640 +#: commands/indexcmds.c:656 #, c-format msgid "must specify at least one column" msgstr "적어도 하나 이상의 칼럼을 지정해 주십시오" -#: commands/indexcmds.c:644 +#: commands/indexcmds.c:660 #, c-format msgid "cannot use more than %d columns in an index" msgstr "하나의 인덱스에서는 %d개보다 많은 칼럼을 사용할 수 없습니다" -#: commands/indexcmds.c:687 +#: commands/indexcmds.c:703 #, c-format msgid "cannot create index on relation \"%s\"" msgstr "\"%s\" 릴레이션 대상으로 인덱스를 만들 수 없음" -#: commands/indexcmds.c:713 +#: commands/indexcmds.c:729 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "\"%s\" 파티션된 테이블 대상으로 동시에 인덱스를 만들 수 없음" -#: commands/indexcmds.c:718 -#, c-format -msgid "cannot create exclusion constraints on partitioned table \"%s\"" -msgstr "\"%s\" 파티션된 테이블 대상으로 제외 제약조건을 만들 수 없음" - -#: commands/indexcmds.c:728 +#: commands/indexcmds.c:739 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "다른 세션의 임시 테이블에 인덱스를 만들 수는 없습니다" -#: commands/indexcmds.c:766 commands/tablecmds.c:784 commands/tablespace.c:1184 +#: commands/indexcmds.c:777 commands/tablecmds.c:818 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "파티션 테이블용 기본 테이블스페이스를 지정할 수 없습니다." -#: commands/indexcmds.c:798 commands/tablecmds.c:819 commands/tablecmds.c:3409 +#: commands/indexcmds.c:809 commands/tablecmds.c:849 commands/tablecmds.c:3588 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "공유 관계만 pg_global 테이블스페이스에 배치할 수 있음" -#: commands/indexcmds.c:831 +#: commands/indexcmds.c:842 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "사용하지 않는 \"rtree\" 방법을 \"gist\" 액세스 방법으로 대체하는 중" -#: commands/indexcmds.c:852 +#: commands/indexcmds.c:863 #, c-format msgid "access method \"%s\" does not support unique indexes" msgstr "\"%s\" 인덱스 접근 방법은 고유 인덱스를 지원하지 않습니다" -#: commands/indexcmds.c:857 +#: commands/indexcmds.c:868 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "\"%s\" 인덱스 접근 방법은 포함된 칼럼을 지원하지 않습니다" -#: commands/indexcmds.c:862 +#: commands/indexcmds.c:873 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "\"%s\" 인덱스 접근 방법은 다중 열 인덱스를 지원하지 않습니다" -#: commands/indexcmds.c:867 +#: commands/indexcmds.c:878 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "\"%s\" 인덱스 접근 방법은 제외 제약 조건을 지원하지 않습니다" -#: commands/indexcmds.c:994 +#: commands/indexcmds.c:1007 #, c-format msgid "cannot match partition key to an index using access method \"%s\"" msgstr "\"%s\" 접근 방법을 사용하는 인덱스와 파티션 키가 일치하지 않습니다" -#: commands/indexcmds.c:1004 +#: commands/indexcmds.c:1017 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "파티션 키 정의에는 %s 제약조건을 지원하지 않음" -#: commands/indexcmds.c:1006 +#: commands/indexcmds.c:1019 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "%s 제약조건은 파티션 키 포함 표현식에 사용할 수 없습니다" -#: commands/indexcmds.c:1045 +#: commands/indexcmds.c:1069 +#, c-format +msgid "" +"cannot match partition key to index on column \"%s\" using non-equal " +"operator \"%s\"" +msgstr "" +"\"%s\" 컬럼에서 같지 않음 연산자(\"%s\")를 사용하는데 이것을 파티션 키와 매치" +"할 수 없음" + +#: commands/indexcmds.c:1085 #, c-format msgid "" "unique constraint on partitioned table must include all partitioning columns" msgstr "하위 테이블 용 유니크 제약조건에는 모든 파티션 칼럼이 포함되어야 함" -#: commands/indexcmds.c:1046 +#: commands/indexcmds.c:1086 #, c-format msgid "" "%s constraint on table \"%s\" lacks column \"%s\" which is part of the " @@ -9452,93 +9880,93 @@ msgstr "" "%s 제약조건(해당 테이블: \"%s\")에 기본키의 한 부분인 \"%s\" 칼럼이 빠져있습" "니다." -#: commands/indexcmds.c:1065 commands/indexcmds.c:1084 +#: commands/indexcmds.c:1105 commands/indexcmds.c:1124 #, c-format msgid "index creation on system columns is not supported" msgstr "시스템 카탈로그 테이블에 대한 인덱스 만들기는 지원하지 않습니다" -#: commands/indexcmds.c:1313 tcop/utility.c:1526 +#: commands/indexcmds.c:1354 tcop/utility.c:1515 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "\"%s\" 파티션된 테이블 대상으로 유니크 인덱스를 만들 수 없음" -#: commands/indexcmds.c:1315 tcop/utility.c:1528 +#: commands/indexcmds.c:1356 tcop/utility.c:1517 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "\"%s\" 테이블은 하위 테이블로 외부 테이블을 사용함." -#: commands/indexcmds.c:1827 +#: commands/indexcmds.c:1806 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "" "인덱스 술어(predicate)에서 사용하는 함수는 IMMUTABLE 특성이 있어야 합니다" -#: commands/indexcmds.c:1905 parser/parse_utilcmd.c:2513 -#: parser/parse_utilcmd.c:2648 +#: commands/indexcmds.c:1885 parser/parse_utilcmd.c:2519 +#: parser/parse_utilcmd.c:2654 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "키에서 지정한 \"%s\" 칼럼이 없습니다" -#: commands/indexcmds.c:1929 parser/parse_utilcmd.c:1812 +#: commands/indexcmds.c:1909 parser/parse_utilcmd.c:1807 #, c-format msgid "expressions are not supported in included columns" msgstr "포함된 칼럼에 쓰인 표현식을 지원하지 않음" -#: commands/indexcmds.c:1970 +#: commands/indexcmds.c:1950 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "인덱스 식(expression)에 사용하는 함수는 IMMUTABLE 특성이 있어야 합니다" -#: commands/indexcmds.c:1985 +#: commands/indexcmds.c:1965 #, c-format msgid "including column does not support a collation" msgstr "포함된 칼럼은 문자정렬규칙을 지원하지 않음" -#: commands/indexcmds.c:1989 +#: commands/indexcmds.c:1969 #, c-format msgid "including column does not support an operator class" msgstr "포함된 칼럼은 연산자 클래스를 지원하지 않음" -#: commands/indexcmds.c:1993 +#: commands/indexcmds.c:1973 #, c-format msgid "including column does not support ASC/DESC options" msgstr "포함된 칼럼은 ASC/DESC 옵션을 지원하지 않음" -#: commands/indexcmds.c:1997 +#: commands/indexcmds.c:1977 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "포함된 칼럼은 NULLS FIRST/LAST 옵션을 지원하지 않음" -#: commands/indexcmds.c:2038 +#: commands/indexcmds.c:2020 #, c-format msgid "could not determine which collation to use for index expression" msgstr "해당 인덱스에서 사용할 정렬규칙(collation)을 결정할 수 없습니다." -#: commands/indexcmds.c:2046 commands/tablecmds.c:17469 commands/typecmds.c:807 -#: parser/parse_expr.c:2722 parser/parse_type.c:568 parser/parse_utilcmd.c:3774 -#: utils/adt/misc.c:586 +#: commands/indexcmds.c:2028 commands/tablecmds.c:18185 commands/typecmds.c:811 +#: parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3771 +#: utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "%s 자료형은 collation 지원 안함" -#: commands/indexcmds.c:2111 +#: commands/indexcmds.c:2095 #, c-format msgid "operator %s is not commutative" msgstr "%s 연산자는 교환법칙이 성립하지 않습니다" -#: commands/indexcmds.c:2113 +#: commands/indexcmds.c:2097 #, c-format msgid "Only commutative operators can be used in exclusion constraints." msgstr "" "exclude 제약조건용 인덱스를 만들 때는 교환법칙이 성립하는 연산자만 사용할 수 " "있습니다." -#: commands/indexcmds.c:2139 +#: commands/indexcmds.c:2123 #, c-format msgid "operator %s is not a member of operator family \"%s\"" msgstr "%s 연산자는 \"%s\" 연산자 패밀리 구성원이 아닙니다." -#: commands/indexcmds.c:2142 +#: commands/indexcmds.c:2126 #, c-format msgid "" "The exclusion operator must be related to the index operator class for the " @@ -9546,25 +9974,25 @@ msgid "" msgstr "" "제외 연산자는 해당 제약 조건용 인덱스 연산자 클래스의 소속이어야 합니다." -#: commands/indexcmds.c:2177 +#: commands/indexcmds.c:2161 #, c-format msgid "access method \"%s\" does not support ASC/DESC options" msgstr "\"%s\" 접근 방법은 ASC/DESC 옵션을 지원하지 않음" -#: commands/indexcmds.c:2182 +#: commands/indexcmds.c:2166 #, c-format msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "\"%s\" 접근 방법은 NULLS FIRST/LAST 옵션을 지원하지 않음" -#: commands/indexcmds.c:2228 commands/tablecmds.c:17494 -#: commands/tablecmds.c:17500 commands/typecmds.c:2301 +#: commands/indexcmds.c:2210 commands/tablecmds.c:18210 +#: commands/tablecmds.c:18216 commands/typecmds.c:2311 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "" "%s 자료형은 \"%s\" 인덱스 액세스 방법을 위한 기본 연산자 클래스(operator " "class)가 없습니다. " -#: commands/indexcmds.c:2230 +#: commands/indexcmds.c:2212 #, c-format msgid "" "You must specify an operator class for the index or define a default " @@ -9573,83 +10001,87 @@ msgstr "" "이 인덱스를 위한 연산자 클래스를 지정하거나 먼저 이 자료형을 위한 기본 연산" "자 클래스를 정의해 두어야 합니다" -#: commands/indexcmds.c:2259 commands/indexcmds.c:2267 +#: commands/indexcmds.c:2241 commands/indexcmds.c:2249 #: commands/opclasscmds.c:205 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "" "\"%s\" 연산자 클래스는 \"%s\" 인덱스 액세스 방법에서 사용할 수 없습니다" -#: commands/indexcmds.c:2281 commands/typecmds.c:2289 +#: commands/indexcmds.c:2263 commands/typecmds.c:2299 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "\"%s\" 연산자 클래스는 %s 자료형을 사용할 수 없습니다" -#: commands/indexcmds.c:2371 +#: commands/indexcmds.c:2353 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "%s 자료형을 위한 기본 연산자 클래스가 여러개 있습니다" -#: commands/indexcmds.c:2699 +#: commands/indexcmds.c:2681 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "알 수 없는 REINDEX 옵션: \"%s\"" -#: commands/indexcmds.c:2923 +#: commands/indexcmds.c:2913 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "\"%s\" 테이블에는 잠금 없는 재색인 작업을 할 대상 인덱스가 없음" -#: commands/indexcmds.c:2937 +#: commands/indexcmds.c:2927 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "\"%s\" 테이블에는 재색인 작업을 할 인덱스가 없습니다" -#: commands/indexcmds.c:2982 commands/indexcmds.c:3492 -#: commands/indexcmds.c:3620 +#: commands/indexcmds.c:2974 commands/indexcmds.c:3485 +#: commands/indexcmds.c:3615 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "시스템 카탈로그 테이블 대상으로 잠금 없는 인덱스를 만들 수 없음" -#: commands/indexcmds.c:3005 +#: commands/indexcmds.c:2998 #, c-format msgid "can only reindex the currently open database" msgstr "열려있는 현재 데이터베이스에서만 reindex 명령을 사용할 수 있습니다" -#: commands/indexcmds.c:3099 +#: commands/indexcmds.c:3090 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "" "시스템 카탈로그 테이블 대상으로 잠금 없는 재색인 작업을 할 수 없음, 모두 건너" "뜀" -#: commands/indexcmds.c:3132 +#: commands/indexcmds.c:3123 #, c-format msgid "cannot move system relations, skipping all" msgstr "시스템 릴레이션은 이동할 수 없습니다, 모두 건너뜀" -#: commands/indexcmds.c:3178 +#: commands/indexcmds.c:3169 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "\"%s.%s\" 파티션된 테이블 대상으로 인덱스 다시 만드는 중" -#: commands/indexcmds.c:3181 +#: commands/indexcmds.c:3172 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "\"%s.%s\" 파티션된 인덱스를 다시 만드는 중" -#: commands/indexcmds.c:3372 commands/indexcmds.c:4228 +#: commands/indexcmds.c:3365 commands/indexcmds.c:4241 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "\"%s.%s\" 테이블의 인덱스들을 다시 만들었습니다." -#: commands/indexcmds.c:3524 commands/indexcmds.c:3576 +#: commands/indexcmds.c:3517 commands/indexcmds.c:3570 #, c-format -msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" -msgstr "" -"유효하지 않은 \"%s.%s\" 인덱스는 잠금 없는 재색인 작업을 할 수 없음, 건너뜀" +msgid "skipping reindex of invalid index \"%s.%s\"" +msgstr "\"%s.%s\" 인덱스가 정상적이지 않아 인덱스 다시 만들기를 건너뜀" + +#: commands/indexcmds.c:3520 commands/indexcmds.c:3573 +#, c-format +msgid "Use DROP INDEX or REINDEX INDEX." +msgstr "DROP INDEX 또는 REINDEX INDEX 명령을 사용하세요." -#: commands/indexcmds.c:3530 +#: commands/indexcmds.c:3524 #, c-format msgid "" "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" @@ -9657,49 +10089,49 @@ msgstr "" "\"%s.%s\" exclusion 제약조건을 대상으로 잠금 없는 재색인 작업을 할 수 없음, " "건너뜀" -#: commands/indexcmds.c:3685 +#: commands/indexcmds.c:3680 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "해당 개체에 대해서는 잠금 없는 재색인 작업을 할 수 없음" -#: commands/indexcmds.c:3706 +#: commands/indexcmds.c:3698 #, c-format msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "비공유 릴레이션은 \"%s\" 테이블스페이스로 이동할 수 없습니다" -#: commands/indexcmds.c:4209 commands/indexcmds.c:4221 +#: commands/indexcmds.c:4222 commands/indexcmds.c:4234 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr "\"%s.%s\" 인덱스가 다시 만들어졌음" -#: commands/indexcmds.c:4211 commands/indexcmds.c:4230 +#: commands/indexcmds.c:4224 commands/indexcmds.c:4243 #, c-format msgid "%s." msgstr "%s." -#: commands/lockcmds.c:92 +#: commands/lockcmds.c:91 #, c-format msgid "cannot lock relation \"%s\"" msgstr "\"%s\" 릴레이션 잠그기 실패" -#: commands/matview.c:193 +#: commands/matview.c:206 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "" "구체화된 뷰의 자료가 정리되고 있을 때는 CONCURRENTLY 옵션을 사용할 수 없습니" "다." -#: commands/matview.c:199 gram.y:18306 +#: commands/matview.c:212 gram.y:18918 #, c-format msgid "%s and %s options cannot be used together" msgstr "%s 옵션과, %s 옵션을 함께 사용할 수 없습니다." -#: commands/matview.c:256 +#: commands/matview.c:269 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "\"%s\" 구체화된 뷰를 동시에 재갱신 할 수 없습니다." -#: commands/matview.c:259 +#: commands/matview.c:272 #, c-format msgid "" "Create a unique index with no WHERE clause on one or more columns of the " @@ -9708,7 +10140,7 @@ msgstr "" "구체화된 뷰의 하나 또는 하나 이상의 칼럼에 대한 WHERE 절 없는 고유 인덱스를 " "만드세요." -#: commands/matview.c:653 +#: commands/matview.c:666 #, c-format msgid "" "new data for materialized view \"%s\" contains duplicate rows without any " @@ -9717,7 +10149,7 @@ msgstr "" "\"%s\" 구체화된 뷰의 새 자료에 아무런 null 칼럼 없이 중복된 로우를 포함하고 " "있습니다" -#: commands/matview.c:655 +#: commands/matview.c:668 #, c-format msgid "Row: %s" msgstr "로우: %s" @@ -9783,7 +10215,7 @@ msgstr "슈퍼유저만 연산자 패밀리를 만들 수 있음" #: commands/opclasscmds.c:861 #, c-format msgid "must be superuser to alter an operator family" -msgstr "슈퍼유저만 연산자 패밀리를 변경할 수 있음" +msgstr "슈퍼유저만 연산자 패밀리를 바꿀 수 있음" #: commands/opclasscmds.c:919 #, c-format @@ -9929,35 +10361,35 @@ msgstr "연산자 번호 %d이(가) (%s,%s)에 대해 여러 번 표시됨" msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "%d(%s,%s) 연산자가 \"%s\" 연산자 패밀리에 이미 있음" -#: commands/opclasscmds.c:1566 +#: commands/opclasscmds.c:1589 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "%d(%s,%s) 함수가 \"%s\" 연산자 패밀리에 이미 있음" -#: commands/opclasscmds.c:1647 +#: commands/opclasscmds.c:1744 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "%d(%s,%s) 연산자가 \"%s\" 연산자 패밀리에 없음" -#: commands/opclasscmds.c:1687 +#: commands/opclasscmds.c:1784 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "%d(%s,%s) 함수가 \"%s\" 연산자 패밀리에 없음" -#: commands/opclasscmds.c:1718 +#: commands/opclasscmds.c:1815 #, c-format msgid "" -"operator class \"%s\" for access method \"%s\" already exists in schema \"%s" -"\"" +"operator class \"%s\" for access method \"%s\" already exists in schema " +"\"%s\"" msgstr "" "\"%s\" 연산자 클래스(\"%s\" 액세스 방법을 사용하는)는 이미 \"%s\" 스키마 안" "에 있습니다" -#: commands/opclasscmds.c:1741 +#: commands/opclasscmds.c:1838 #, c-format msgid "" -"operator family \"%s\" for access method \"%s\" already exists in schema \"%s" -"\"" +"operator family \"%s\" for access method \"%s\" already exists in schema " +"\"%s\"" msgstr "\"%s\" 연산자 패밀리(접근 방법: \"%s\")가 \"%s\" 스키마에 이미 있음" #: commands/operatorcmds.c:113 commands/operatorcmds.c:121 @@ -9965,7 +10397,7 @@ msgstr "\"%s\" 연산자 패밀리(접근 방법: \"%s\")가 \"%s\" 스키마에 msgid "SETOF type not allowed for operator argument" msgstr "SETOF 형식은 연산자 인자에 허용되지 않음" -#: commands/operatorcmds.c:154 commands/operatorcmds.c:481 +#: commands/operatorcmds.c:154 commands/operatorcmds.c:554 #, c-format msgid "operator attribute \"%s\" not recognized" msgstr "\"%s\" 연산자 속성을 처리할 수 없음" @@ -10005,53 +10437,70 @@ msgstr "%s 조인 예상 함수가 여러개 있습니다" msgid "join estimator function %s must return type %s" msgstr "%s 조인 예상 함수는 %s 자료형을 반환해야 함" -#: commands/operatorcmds.c:475 +#: commands/operatorcmds.c:388 parser/parse_oper.c:119 parser/parse_oper.c:637 +#: utils/adt/regproc.c:509 utils/adt/regproc.c:683 +#, c-format +msgid "operator does not exist: %s" +msgstr "연산자 없음: %s" + +#: commands/operatorcmds.c:396 parser/parse_oper.c:702 parser/parse_oper.c:815 +#, c-format +msgid "operator is only a shell: %s" +msgstr "연산자는 셸일 뿐임: %s" + +#: commands/operatorcmds.c:548 #, c-format msgid "operator attribute \"%s\" cannot be changed" msgstr "\"%s\" 연산자 속성 바꿀 수 없음" -#: commands/policy.c:89 commands/policy.c:382 commands/statscmds.c:149 -#: commands/tablecmds.c:1616 commands/tablecmds.c:2219 -#: commands/tablecmds.c:3520 commands/tablecmds.c:6369 -#: commands/tablecmds.c:9181 commands/tablecmds.c:17062 -#: commands/tablecmds.c:17097 commands/trigger.c:323 commands/trigger.c:1339 -#: commands/trigger.c:1449 rewrite/rewriteDefine.c:275 -#: rewrite/rewriteDefine.c:786 rewrite/rewriteRemove.c:80 +#: commands/operatorcmds.c:615 commands/operatorcmds.c:622 +#: commands/operatorcmds.c:628 commands/operatorcmds.c:634 +#, c-format +msgid "operator attribute \"%s\" cannot be changed if it has already been set" +msgstr "이미 설정 되어 \"%s\" 연산자 속성 바꿀 수 없음" + +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 +#: commands/tablecmds.c:1740 commands/tablecmds.c:2340 +#: commands/tablecmds.c:3702 commands/tablecmds.c:6605 +#: commands/tablecmds.c:9637 commands/tablecmds.c:17772 +#: commands/tablecmds.c:17807 commands/trigger.c:316 commands/trigger.c:1332 +#: commands/trigger.c:1442 rewrite/rewriteDefine.c:268 +#: rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "액세스 권한 없음: \"%s\" 시스템 카탈로그임" -#: commands/policy.c:172 +#: commands/policy.c:169 #, c-format msgid "ignoring specified roles other than PUBLIC" msgstr "PUBLIC 아닌 지정한 모든 롤 무시함" -#: commands/policy.c:173 +#: commands/policy.c:170 #, c-format msgid "All roles are members of the PUBLIC role." msgstr "모든 롤이 PUBLIC 롤의 소속입니다." -#: commands/policy.c:606 +#: commands/policy.c:603 #, c-format msgid "WITH CHECK cannot be applied to SELECT or DELETE" msgstr "WITH CHECK 옵션은 SELECT나 DELETE 작업에 적용 될 수 없음" -#: commands/policy.c:615 commands/policy.c:918 +#: commands/policy.c:612 commands/policy.c:915 #, c-format msgid "only WITH CHECK expression allowed for INSERT" msgstr "INSERT 구문에 대해서만 WITH CHECK 옵션을 허용합니다" -#: commands/policy.c:689 commands/policy.c:1141 +#: commands/policy.c:686 commands/policy.c:1138 #, c-format msgid "policy \"%s\" for table \"%s\" already exists" msgstr "\"%s\" 정책이 \"%s\" 테이블에 이미 지정되어있습니다" -#: commands/policy.c:890 commands/policy.c:1169 commands/policy.c:1240 +#: commands/policy.c:887 commands/policy.c:1166 commands/policy.c:1237 #, c-format msgid "policy \"%s\" for table \"%s\" does not exist" msgstr "\"%s\" 정책이 \"%s\" 테이블에 없음" -#: commands/policy.c:908 +#: commands/policy.c:905 #, c-format msgid "only USING expression allowed for SELECT, DELETE" msgstr "USING 구문만 SELECT, DELETE 작업에 쓸 수 있음" @@ -10068,83 +10517,82 @@ msgstr "" "엄격한 보안 제한 작업 내에서 WITH HOLD 옵션을 사용하는 커서는 만들 수 없음" #: commands/portalcmds.c:189 commands/portalcmds.c:242 -#: executor/execCurrent.c:70 utils/adt/xml.c:2844 utils/adt/xml.c:3014 +#: executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "\"%s\" 이름의 커서가 없음" -#: commands/prepare.c:75 +#: commands/prepare.c:72 #, c-format msgid "invalid statement name: must not be empty" msgstr "잘못된 명령문 이름: 비어있으면 안됩니다" -#: commands/prepare.c:230 commands/prepare.c:235 +#: commands/prepare.c:227 commands/prepare.c:232 #, c-format msgid "prepared statement is not a SELECT" msgstr "준비된 명령문이 SELECT 구문이 아닙니다." -#: commands/prepare.c:295 +#: commands/prepare.c:292 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "prepared statement \"%s\"에 매개 변수 수가 틀렸습니다" -#: commands/prepare.c:297 +#: commands/prepare.c:294 #, c-format msgid "Expected %d parameters but got %d." msgstr "%d 개의 매개 변수가 요구되는데 %d 개만이 존재합니다" -#: commands/prepare.c:330 +#: commands/prepare.c:327 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "??? parameter $%d of type %s 는 expected type %s 로 강요할 수 없다" -#: commands/prepare.c:414 +#: commands/prepare.c:411 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "\"%s\" 이름의 준비된 명령문(prepared statement)이 이미 있습니다" -#: commands/prepare.c:453 +#: commands/prepare.c:450 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "\"%s\" 이름의 준비된 명령문(prepared statement) 없음" -#: commands/proclang.c:68 +#: commands/proclang.c:66 #, c-format msgid "must be superuser to create custom procedural language" msgstr "슈퍼유저만 사용자 지정 프로시저 언어를 만들 수 있음" -#: commands/publicationcmds.c:131 postmaster/postmaster.c:1208 -#: postmaster/postmaster.c:1306 storage/file/fd.c:3911 -#: utils/init/miscinit.c:1815 +#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 +#: postmaster/postmaster.c:1210 utils/init/miscinit.c:1865 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "\"%s\" 매개 변수 구문이 잘못 되었습니다" -#: commands/publicationcmds.c:150 +#: commands/publicationcmds.c:143 #, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" msgstr "발행용 \"%s\" 옵션에서 쓸 수 없는 값: \"%s\"" -#: commands/publicationcmds.c:164 +#: commands/publicationcmds.c:157 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "인식할 수 없는 발행 매개 변수: \"%s\"" -#: commands/publicationcmds.c:205 +#: commands/publicationcmds.c:198 #, c-format msgid "no schema has been selected for CURRENT_SCHEMA" msgstr "CURRENT_SCHEMA 용 실제 스키마 없음" -#: commands/publicationcmds.c:502 +#: commands/publicationcmds.c:495 msgid "System columns are not allowed." msgstr "시스템 칼럼은 허용하지 않음." -#: commands/publicationcmds.c:509 commands/publicationcmds.c:514 -#: commands/publicationcmds.c:531 +#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 +#: commands/publicationcmds.c:524 msgid "User-defined operators are not allowed." msgstr "사용자 정의 연산자는 허용하지 않음." -#: commands/publicationcmds.c:555 +#: commands/publicationcmds.c:548 msgid "" "Only columns, constants, built-in operators, built-in data types, built-in " "collations, and immutable built-in functions are allowed." @@ -10152,39 +10600,39 @@ msgstr "" "칼럼, 상수, 내장 연산자, 내장 자료형, 내장 문자 정렬 규칙, 불변형 내장 함수" "만 허용합니다." -#: commands/publicationcmds.c:567 +#: commands/publicationcmds.c:560 msgid "User-defined types are not allowed." msgstr "사용자 정의 자료형은 허용하지 않음." -#: commands/publicationcmds.c:570 +#: commands/publicationcmds.c:563 msgid "User-defined or built-in mutable functions are not allowed." msgstr "사용자 정의나 내장 함수가 mutable 인 경우 허용하지 않음." -#: commands/publicationcmds.c:573 +#: commands/publicationcmds.c:566 msgid "User-defined collations are not allowed." msgstr "사용자 정의 문자 정렬 규칙은 허용하지 않음." -#: commands/publicationcmds.c:583 +#: commands/publicationcmds.c:576 #, c-format msgid "invalid publication WHERE expression" msgstr "잘못된 구독 WHERE 절 구문" -#: commands/publicationcmds.c:636 +#: commands/publicationcmds.c:629 #, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" msgstr "\"%s\" 릴레이션용 구독 WHERE 절은 사용할 수 없음" -#: commands/publicationcmds.c:638 +#: commands/publicationcmds.c:631 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." msgstr "%s 값이 false 일때, 파티션 된 테이블에서는 WHERE 절을 사용할 수 없음." -#: commands/publicationcmds.c:709 commands/publicationcmds.c:723 +#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 #, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" msgstr "\"%s.%s\" 릴레이션용 칼럼 목록을 사용할 수 없음(해당 구독: \"%s\")" -#: commands/publicationcmds.c:712 +#: commands/publicationcmds.c:705 #, c-format msgid "" "Column lists cannot be specified in publications containing FOR TABLES IN " @@ -10193,39 +10641,39 @@ msgstr "" "FOR TABLES IN SCHEMA 구문을 이용해서 구독을 만들 때는 칼럼 목록을 지정할 수 " "없습니다." -#: commands/publicationcmds.c:726 +#: commands/publicationcmds.c:719 #, c-format msgid "" "Column lists cannot be specified for partitioned tables when %s is false." msgstr "" "%s 값이 false 일때, 파티션 상위 테이블을 위한 칼럼 목록은 지정할 수 없습니다." -#: commands/publicationcmds.c:761 +#: commands/publicationcmds.c:754 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "FOR ALL TABLES 옵션의 발행을 만드려면 슈퍼유저여야만 합니다" -#: commands/publicationcmds.c:832 +#: commands/publicationcmds.c:825 #, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" msgstr "FOR TABLES IN SCHEMA 구문을 사용하는 구독은 슈퍼 유저만 쓸 수 있음" -#: commands/publicationcmds.c:868 +#: commands/publicationcmds.c:861 #, c-format -msgid "wal_level is insufficient to publish logical changes" -msgstr "wal_level 수준이 논리 변경 사항 발행을 하기에는 부족합니다" +msgid "\"wal_level\" is insufficient to publish logical changes" +msgstr "\"wal_level\" 수준이 논리 변경 사항 발행을 하기에는 부족합니다" -#: commands/publicationcmds.c:869 +#: commands/publicationcmds.c:862 #, c-format -msgid "Set wal_level to \"logical\" before creating subscriptions." -msgstr "wal_level 값을 \"logical\"로 바꾸고 구독을 만들세요" +msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." +msgstr "\"wal_level\" 값을 \"logical\"로 바꾸고 구독을 만들세요" -#: commands/publicationcmds.c:965 commands/publicationcmds.c:973 +#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 #, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" msgstr "\"%s\" 매개 변수 값으로 false를 지정할 수 없음, 해당 구독: \"%s\"" -#: commands/publicationcmds.c:968 +#: commands/publicationcmds.c:961 #, c-format msgid "" "The publication contains a WHERE clause for partitioned table \"%s\", which " @@ -10234,21 +10682,21 @@ msgstr "" "이 구독은 \"%s\" 파티션 상위테이블 대상 WHERE 절을 포함하고 있습니다. \"%s\" " "값이 false 때는 이 조건을 허용하지 않습니다." -#: commands/publicationcmds.c:976 +#: commands/publicationcmds.c:969 #, c-format msgid "" "The publication contains a column list for partitioned table \"%s\", which " "is not allowed when \"%s\" is false." msgstr "" -"이 구독은 \"%s\" 파티션 상위테이블 대상 칼럼 목록을 포함하고 있습니다. \"%s" -"\" 값이 false 때는 이런 사용을 허용하지 않습니다." +"이 구독은 \"%s\" 파티션 상위테이블 대상 칼럼 목록을 포함하고 있습니다. " +"\"%s\" 값이 false 때는 이런 사용을 허용하지 않습니다." -#: commands/publicationcmds.c:1299 +#: commands/publicationcmds.c:1292 #, c-format msgid "cannot add schema to publication \"%s\"" msgstr "\"%s\" 구독에 스키마는 추가 할 수 없음" -#: commands/publicationcmds.c:1301 +#: commands/publicationcmds.c:1294 #, c-format msgid "" "Schemas cannot be added if any tables that specify a column list are already " @@ -10257,79 +10705,79 @@ msgstr "" "이미 해당 발행에 한 부분으로 어떤 테이블의 칼럼 목록을 사용하고 있다면, 그 테" "이블이 있는 그 스키마는 스키마 단위로 발행에 추가 할 수 없습니다." -#: commands/publicationcmds.c:1349 +#: commands/publicationcmds.c:1342 #, c-format msgid "must be superuser to add or set schemas" msgstr "스키마 지정은 슈퍼유져여야 합니다" -#: commands/publicationcmds.c:1358 commands/publicationcmds.c:1366 +#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "\"%s\" 발행은 FOR ALL TABLES 옵션으로 정의되어 있습니다." -#: commands/publicationcmds.c:1360 +#: commands/publicationcmds.c:1353 #, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." msgstr "FOR ALL TABLES 발행에 스키마를 추가하거나 뺄 수 없습니다." -#: commands/publicationcmds.c:1368 +#: commands/publicationcmds.c:1361 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "" "FOR ALL TABLES 발행에 새 테이블을 추가하거나 한 테이블을 뺄 수 없습니다." -#: commands/publicationcmds.c:1392 commands/publicationcmds.c:1431 -#: commands/publicationcmds.c:1968 utils/cache/lsyscache.c:3592 +#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 +#: commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 #, c-format msgid "publication \"%s\" does not exist" msgstr "\"%s\" 이름의 발행은 없습니다" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1657 +#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 #, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" msgstr "\"%s\" 테이블 용 WHERE 절이 충돌나거나, 중복되었음" -#: commands/publicationcmds.c:1601 commands/publicationcmds.c:1669 +#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 #, c-format msgid "conflicting or redundant column lists for table \"%s\"" msgstr "\"%s\" 테이블 용 칼럼 목록이 충돌나거나, 중복되었음" -#: commands/publicationcmds.c:1803 +#: commands/publicationcmds.c:1796 #, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" msgstr "ALTER PUBLICATION ... DROP 구문에서는 칼럼 목록을 지정하지 말아야함" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1808 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "\"%s\" 릴레이션은 해당 발행에 포함되어 있지 않습니다" -#: commands/publicationcmds.c:1822 +#: commands/publicationcmds.c:1815 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "발행에서 테이블을 뺄 때, WHERE 절은 사용할 수 없습니다." -#: commands/publicationcmds.c:1882 +#: commands/publicationcmds.c:1875 #, c-format msgid "tables from schema \"%s\" are not part of the publication" msgstr "\"%s\" 스키마의 테이블들은 해당 발행에 포함되어 있지 않습니다" -#: commands/publicationcmds.c:1925 commands/publicationcmds.c:1932 +#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 #, c-format msgid "permission denied to change owner of publication \"%s\"" msgstr "\"%s\" 발행의 소유주를 바꿀 권한이 없습니다" -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:1920 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "FOR ALL TABLES 옵션용 발행의 소유주는 슈퍼유저여야만 합니다" -#: commands/publicationcmds.c:1934 +#: commands/publicationcmds.c:1927 #, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." msgstr "FOR ALL TABLES IN SCHEMA 구독의 소유주는 슈퍼유저여야만 합니다" -#: commands/publicationcmds.c:2000 +#: commands/publicationcmds.c:1993 #, c-format msgid "publication with OID %u does not exist" msgstr "OID %u 발행 없음" @@ -10376,158 +10824,158 @@ msgstr "이 객체 형태는 보안 라벨을 지원하지 않음" msgid "cannot set security label on relation \"%s\"" msgstr "\"%s\" 릴레이션에 보안 라벨을 지정할 수 없음" -#: commands/sequence.c:754 +#: commands/sequence.c:748 #, c-format msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" msgstr "nextval: \"%s\" 시퀀스의 최대값(%lld)이 되었습니다" -#: commands/sequence.c:773 +#: commands/sequence.c:767 #, c-format msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" msgstr "nextval: \"%s\" 시퀀스의 최소값(%lld)이 되었습니다" -#: commands/sequence.c:891 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "\"%s\" 시퀀스의 currval 값이 현재 세션에 지정되어 있지 않습니다" -#: commands/sequence.c:910 commands/sequence.c:916 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "이 세션에는 lastval 값이 아직까지 지정되지 않았습니다" -#: commands/sequence.c:996 +#: commands/sequence.c:991 #, c-format msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" msgstr "setval: %lld 값은 \"%s\" 시퀀스의 범위(%lld..%lld)를 벗어났습니다" -#: commands/sequence.c:1365 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "잘못된 SEQUENCE NAME 시퀀스 옵션" -#: commands/sequence.c:1391 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "식별 칼럼에 쓸 자료형은 smallint, integer, bigint 자료형만 쓸 수 있음" -#: commands/sequence.c:1392 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "시퀀스에 쓸 자료형은 smallint, integer, bigint 자료형만 쓸 수 있음" -#: commands/sequence.c:1426 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENT 값은 0(zero)이 될 수 없습니다" -#: commands/sequence.c:1474 +#: commands/sequence.c:1466 #, c-format msgid "MAXVALUE (%lld) is out of range for sequence data type %s" msgstr "MAXVALUE (%lld) 값이 허용 범위 밖임, 해당 시퀀스 자료형: %s" -#: commands/sequence.c:1506 +#: commands/sequence.c:1498 #, c-format msgid "MINVALUE (%lld) is out of range for sequence data type %s" msgstr "MAXVALUE (%lld) 값이 허용 범위 밖임, 해당 시퀀스 자료형: %s" -#: commands/sequence.c:1514 +#: commands/sequence.c:1506 #, c-format msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" msgstr "MINVALUE (%lld) 값은 MAXVALUE (%lld) 값보다 작아야 합니다" -#: commands/sequence.c:1535 +#: commands/sequence.c:1527 #, c-format msgid "START value (%lld) cannot be less than MINVALUE (%lld)" msgstr "START 값(%lld)은 MINVALUE(%lld)보다 작을 수 없음" -#: commands/sequence.c:1541 +#: commands/sequence.c:1533 #, c-format msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "START 값(%lld)은 MAXVALUE(%lld)보다 클 수 없음" -#: commands/sequence.c:1565 +#: commands/sequence.c:1557 #, c-format msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" msgstr "RESTART 값(%lld)은 MINVALUE(%lld)보다 작을 수 없음" -#: commands/sequence.c:1571 +#: commands/sequence.c:1563 #, c-format msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "RESTART 값(%lld)은 MAXVALUE(%lld)보다 클 수 없음" -#: commands/sequence.c:1582 +#: commands/sequence.c:1574 #, c-format msgid "CACHE (%lld) must be greater than zero" msgstr "CACHE (%lld) 값은 0(zero)보다 커야 합니다" -#: commands/sequence.c:1618 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "잘못된 OWNED BY 옵션" -#: commands/sequence.c:1619 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "OWNED BY 테이블.열 또는 OWNED BY NONE을 지정하십시오." -#: commands/sequence.c:1644 +#: commands/sequence.c:1636 #, c-format msgid "sequence cannot be owned by relation \"%s\"" msgstr "\"%s\" 릴레이션의 소속 시퀀스가 될 수 없음" -#: commands/sequence.c:1652 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "시퀀스 및 이 시퀀스가 연결된 테이블의 소유주가 같아야 함" -#: commands/sequence.c:1656 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "시퀀스 및 이 시퀀스가 연결된 테이블이 같은 스키마에 있어야 함" -#: commands/sequence.c:1678 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "식별 시퀀스의 소유주는 바꿀 수 없음" -#: commands/sequence.c:1679 commands/tablecmds.c:13891 -#: commands/tablecmds.c:16488 +#: commands/sequence.c:1671 commands/tablecmds.c:14486 +#: commands/tablecmds.c:17181 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "\"%s\" 시퀀스는 \"%s\" 테이블에 종속되어 있습니다." -#: commands/statscmds.c:109 commands/statscmds.c:118 tcop/utility.c:1887 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "CREATE STATISTICS 명령에서는 하나의 릴레이션만 사용할 수 있음" -#: commands/statscmds.c:136 +#: commands/statscmds.c:133 #, c-format msgid "cannot define statistics for relation \"%s\"" msgstr "\"%s\" 릴레이션용 통계정보를 정의할 수 없음" -#: commands/statscmds.c:190 +#: commands/statscmds.c:187 #, c-format msgid "statistics object \"%s\" already exists, skipping" msgstr "\"%s\" 이름의 통계정보 개체가 이미 있습니다, 건너뜀" -#: commands/statscmds.c:198 +#: commands/statscmds.c:195 #, c-format msgid "statistics object \"%s\" already exists" msgstr "\"%s\" 이름의 통계정보 개체가 이미 있음" -#: commands/statscmds.c:209 +#: commands/statscmds.c:206 #, c-format msgid "cannot have more than %d columns in statistics" msgstr "통계정보 개체에서는 %d개보다 많은 칼럼을 사용할 수 없습니다" -#: commands/statscmds.c:250 commands/statscmds.c:273 commands/statscmds.c:307 +#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 #, c-format msgid "statistics creation on system columns is not supported" msgstr "시스템 칼럼에 대한 통계정보 개체 만들기는 지원하지 않습니다" -#: commands/statscmds.c:257 commands/statscmds.c:280 +#: commands/statscmds.c:254 commands/statscmds.c:277 #, c-format msgid "" "column \"%s\" cannot be used in statistics because its type %s has no " @@ -10536,7 +10984,7 @@ msgstr "" "\"%s\" 칼럼은 사용자 통계정보 수집이 불가능합니다. %s 자료형은 기본 btree 연" "산자 클래스를 정의하지 않았습니다" -#: commands/statscmds.c:324 +#: commands/statscmds.c:321 #, c-format msgid "" "expression cannot be used in multivariate statistics because its type %s has " @@ -10545,7 +10993,7 @@ msgstr "" "%s 자료형에는 기본 btree 연산자 클래스가 없어서, 표현식은 다변적인 통계 정보" "에서 사용될 수 없음" -#: commands/statscmds.c:345 +#: commands/statscmds.c:342 #, c-format msgid "" "when building statistics on a single expression, statistics kinds may not be " @@ -10553,108 +11001,109 @@ msgid "" msgstr "" "단일 표현식으로 통계 정보를 만들 때, 통계 정보 종류는 지정할 수 없습니다." -#: commands/statscmds.c:374 +#: commands/statscmds.c:371 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "알 수 없는 통계정보 종류 \"%s\"" -#: commands/statscmds.c:403 +#: commands/statscmds.c:400 #, c-format msgid "extended statistics require at least 2 columns" msgstr "확장된 통계정보는 두 개 이상의 칼럼이 필요합니다." -#: commands/statscmds.c:421 +#: commands/statscmds.c:418 #, c-format msgid "duplicate column name in statistics definition" msgstr "통계정보 정의에서 사용하는 칼럼이 중복되었습니다" -#: commands/statscmds.c:456 +#: commands/statscmds.c:453 #, c-format msgid "duplicate expression in statistics definition" msgstr "통계정보 정의에서 표현식이 중복되었습니다" -#: commands/statscmds.c:619 commands/tablecmds.c:8180 +#: commands/statscmds.c:628 commands/tablecmds.c:8620 #, c-format msgid "statistics target %d is too low" msgstr "대상 통계값(%d)이 너무 낮습니다" -#: commands/statscmds.c:627 commands/tablecmds.c:8188 +#: commands/statscmds.c:636 commands/tablecmds.c:8628 #, c-format msgid "lowering statistics target to %d" msgstr "%d 값으로 대상 통계값을 낮춥니다" -#: commands/statscmds.c:650 +#: commands/statscmds.c:660 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "\"%s.%s\" 통계정보 개체 없음, 무시함" -#: commands/subscriptioncmds.c:271 commands/subscriptioncmds.c:359 +#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 #, c-format msgid "unrecognized subscription parameter: \"%s\"" msgstr "알 수 없는 구독 매개 변수: \"%s\"" -#: commands/subscriptioncmds.c:327 replication/pgoutput/pgoutput.c:398 +#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:404 #, c-format msgid "unrecognized origin value: \"%s\"" msgstr "알 수 없는 오리진 값: \"%s\"" -#: commands/subscriptioncmds.c:350 +#: commands/subscriptioncmds.c:363 #, c-format msgid "invalid WAL location (LSN): %s" msgstr "잘못된 WAL 위치 (LSN): %s" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:374 commands/subscriptioncmds.c:381 -#: commands/subscriptioncmds.c:388 commands/subscriptioncmds.c:410 -#: commands/subscriptioncmds.c:426 +#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 +#: commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 +#: commands/subscriptioncmds.c:439 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "%s 옵션과 %s 옵션은 함께 사용할 수 없음" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:416 commands/subscriptioncmds.c:432 +#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 #, c-format msgid "subscription with %s must also set %s" msgstr "%s 구독하려면, %s 설정이 필요함" -#: commands/subscriptioncmds.c:494 +#: commands/subscriptioncmds.c:506 #, c-format msgid "could not receive list of publications from the publisher: %s" msgstr "발행자에게서 발행 목록을 받을 수 없음: %s" -#: commands/subscriptioncmds.c:526 +#: commands/subscriptioncmds.c:538 #, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" msgstr[0] "해당 발행자에게는 \"%s\" 이름의 발행은 없습니다" -#: commands/subscriptioncmds.c:614 +#: commands/subscriptioncmds.c:626 #, c-format msgid "permission denied to create subscription" msgstr "구독을 만들기 위한 권한 없음" -#: commands/subscriptioncmds.c:615 +#: commands/subscriptioncmds.c:627 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." msgstr "\"%s\" 롤이 부여된 사용자만 구독을 만들 수 있습니다." -#: commands/subscriptioncmds.c:745 commands/subscriptioncmds.c:878 -#: replication/logical/tablesync.c:1309 replication/logical/worker.c:4616 +#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 +#: commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 +#: replication/logical/worker.c:4503 #, c-format msgid "could not connect to the publisher: %s" msgstr "발행 서버에 연결 할 수 없음: %s" -#: commands/subscriptioncmds.c:816 +#: commands/subscriptioncmds.c:829 #, c-format msgid "created replication slot \"%s\" on publisher" msgstr "\"%s\" 이름의 복제 슬롯이 없습니다" -#: commands/subscriptioncmds.c:828 +#: commands/subscriptioncmds.c:841 #, c-format msgid "subscription was created, but is not connected" msgstr "구독을 만들었지만, 발행 서버로 접속은 안했습니다." -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:842 #, c-format msgid "" "To initiate replication, you must manually create the replication slot, " @@ -10663,23 +11112,29 @@ msgstr "" "복제 초기화 작업은 먼저 수동으로 복제 슬롯을 만들고, 구독을 활성화하고, 해당 " "구독을 새로고침 하는 순서로 진행합니다." -#: commands/subscriptioncmds.c:1096 commands/subscriptioncmds.c:1502 -#: commands/subscriptioncmds.c:1885 utils/cache/lsyscache.c:3642 +#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 +#: commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 #, c-format msgid "subscription \"%s\" does not exist" msgstr "\"%s\" 이름의 구독은 없습니다." -#: commands/subscriptioncmds.c:1152 +#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 #, c-format msgid "cannot set %s for enabled subscription" msgstr "구독 활성화를 위해서는 %s 설정은 할 수 없음" -#: commands/subscriptioncmds.c:1227 +#: commands/subscriptioncmds.c:1233 +#, c-format +msgid "" +"cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "슬롯 이름 없이는 구독에 \"%s\" 옵션을 지정할 수 없음" + +#: commands/subscriptioncmds.c:1279 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "슬롯 이름 없이는 구독을 활성화 할 수 없음" -#: commands/subscriptioncmds.c:1271 commands/subscriptioncmds.c:1322 +#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 #, c-format msgid "" "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" @@ -10687,14 +11142,14 @@ msgstr "" "비활성화 상태인 구독에 대해서는 ALTER SUBSCRIPTION 명령으로 갱신할 수 없습니" "다" -#: commands/subscriptioncmds.c:1272 +#: commands/subscriptioncmds.c:1324 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "" "ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false) 명령을 사용" "하세요." -#: commands/subscriptioncmds.c:1281 commands/subscriptioncmds.c:1336 +#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 #, c-format msgid "" "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase " @@ -10703,7 +11158,7 @@ msgstr "" "two_phase 값이 true인 상태에서는 ALTER SUBSCRIPTION 명령에서 refresh나 " "copy_data 옵션을 사용할 수 없습니다." -#: commands/subscriptioncmds.c:1282 +#: commands/subscriptioncmds.c:1334 #, c-format msgid "" "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with " @@ -10713,13 +11168,7 @@ msgstr "" "copy_data = false 구문을 추가하거나 DROP/CREATE SUBSCRIPTION 작업을 하세요." #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1324 -#, c-format -msgid "Use %s instead." -msgstr "대신에 %s 명령을 사용하십시오." - -#. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1338 +#: commands/subscriptioncmds.c:1390 #, c-format msgid "" "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE " @@ -10728,7 +11177,7 @@ msgstr "" "%s 명령에서 refresh = false 또는 copy_data = false 옵션을 추가하거나, DROP/" "CREATE SUBSCRIPTION 작업을 하세요." -#: commands/subscriptioncmds.c:1360 +#: commands/subscriptioncmds.c:1412 #, c-format msgid "" "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" @@ -10736,7 +11185,7 @@ msgstr "" "비활성화 상태인 구독에 대해서는 ALTER SUBSCRIPTION ... REFRESH 명령을 허용하" "지 않습니다." -#: commands/subscriptioncmds.c:1385 +#: commands/subscriptioncmds.c:1437 #, c-format msgid "" "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase " @@ -10745,7 +11194,7 @@ msgstr "" "two_phase 값이 true인 상태에서는 ALTER SUBSCRIPTION 명령에서 copy_data 옵션" "을 사용할 수 없습니다." -#: commands/subscriptioncmds.c:1386 +#: commands/subscriptioncmds.c:1438 #, c-format msgid "" "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/" @@ -10754,38 +11203,38 @@ msgstr "" "ALTER SUBSCRIPTION ... REFRESH 다음 copy_data = false 구문을 추가하거나 DROP/" "CREATE SUBSCRIPTION 작업을 하세요." -#: commands/subscriptioncmds.c:1421 +#: commands/subscriptioncmds.c:1473 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "" "WAL 위치 (LSN %X/%X)를 건너뛰려면, 그 값이 원본 LSN %X/%X 보다 커야합니다" -#: commands/subscriptioncmds.c:1506 +#: commands/subscriptioncmds.c:1594 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "\"%s\" 구독 없음, 건너뜀" -#: commands/subscriptioncmds.c:1775 +#: commands/subscriptioncmds.c:1863 #, c-format msgid "dropped replication slot \"%s\" on publisher" msgstr "발행에서 \"%s\" 복제 슬롯을 삭제했음" -#: commands/subscriptioncmds.c:1784 commands/subscriptioncmds.c:1792 +#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" msgstr "발행용 \"%s\" 복제 슬롯을 삭제 할 수 없음: %s" -#: commands/subscriptioncmds.c:1917 +#: commands/subscriptioncmds.c:2005 #, c-format msgid "subscription with OID %u does not exist" msgstr "OID %u 구독 없음" -#: commands/subscriptioncmds.c:1988 commands/subscriptioncmds.c:2113 +#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" msgstr "해당 발행자로부터 복제 테이블 목록을 구할 수 없음: %s" -#: commands/subscriptioncmds.c:2024 +#: commands/subscriptioncmds.c:2112 #, c-format msgid "" "subscription \"%s\" requested copy_data with origin = NONE but might copy " @@ -10794,7 +11243,7 @@ msgstr "" "\"%s\" 구독이 copy_data 옵션과 origin = NONE 설정을 요구했지만, copy 자료가 " "다른 오리진 것입니다." -#: commands/subscriptioncmds.c:2026 +#: commands/subscriptioncmds.c:2114 #, c-format msgid "" "The subscription being created subscribes to a publication (%s) that " @@ -10803,8 +11252,9 @@ msgid_plural "" "The subscription being created subscribes to publications (%s) that contain " "tables that are written to by other subscriptions." msgstr[0] "" +"만들어질 구독은 다른 구독에 의해 쓰여진 테이블이 포함된 발행(%s)을 구독합니다." -#: commands/subscriptioncmds.c:2029 +#: commands/subscriptioncmds.c:2117 #, c-format msgid "" "Verify that initial data copied from the publisher tables did not come from " @@ -10812,8 +11262,8 @@ msgid "" msgstr "" "복사된 초기 자료가 해당 발행의 다른 오리진에서 복사되었는지 확인하세요." -#: commands/subscriptioncmds.c:2135 replication/logical/tablesync.c:876 -#: replication/pgoutput/pgoutput.c:1115 +#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 +#: replication/pgoutput/pgoutput.c:1143 #, c-format msgid "" "cannot use different column lists for table \"%s.%s\" in different " @@ -10822,15 +11272,15 @@ msgstr "" "서로 다른 발행에서 \"%s.%s\" 테이블에 대한 서로 다른 칼럼 목록을 사용할 수 없" "음." -#: commands/subscriptioncmds.c:2185 +#: commands/subscriptioncmds.c:2273 #, c-format msgid "" -"could not connect to publisher when attempting to drop replication slot \"%s" -"\": %s" +"could not connect to publisher when attempting to drop replication slot " +"\"%s\": %s" msgstr "\"%s\" 복제 슬롯을 삭제하는 중에는 발행 서버로 접속할 수 없음: %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2188 +#: commands/subscriptioncmds.c:2276 #, c-format msgid "" "Use %s to disable the subscription, and then use %s to disassociate it from " @@ -10839,189 +11289,194 @@ msgstr "" "구독을 중지하려면 %s 명령을 한 뒤, 슬롯 관계를 끊기 위해 %s 명령을 사용하세" "요." -#: commands/subscriptioncmds.c:2219 +#: commands/subscriptioncmds.c:2307 #, c-format msgid "publication name \"%s\" used more than once" msgstr "\"%s\" 발행 이름이 여러 번 사용 됨" -#: commands/subscriptioncmds.c:2263 +#: commands/subscriptioncmds.c:2351 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "\"%s\" 이름의 발행이 \"%s\" 구독 안에 이미 있습니다" -#: commands/subscriptioncmds.c:2277 +#: commands/subscriptioncmds.c:2365 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "\"%s\" 발행이 \"%s\" 구독 안에 없습니다" -#: commands/subscriptioncmds.c:2288 +#: commands/subscriptioncmds.c:2376 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "한 구독안에 있는 모든 발행은 지울 수 없음" -#: commands/subscriptioncmds.c:2345 +#: commands/subscriptioncmds.c:2433 #, c-format msgid "%s requires a Boolean value or \"parallel\"" msgstr "%s 값은 불리언 값 또는 \"parallel\" 이어야 합니다." -#: commands/tablecmds.c:246 commands/tablecmds.c:288 +#: commands/tablecmds.c:255 commands/tablecmds.c:297 #, c-format msgid "table \"%s\" does not exist" msgstr "\"%s\" 테이블 없음" -#: commands/tablecmds.c:247 commands/tablecmds.c:289 +#: commands/tablecmds.c:256 commands/tablecmds.c:298 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "\"%s\" 테이블 없음, 무시함" -#: commands/tablecmds.c:249 commands/tablecmds.c:291 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 msgid "Use DROP TABLE to remove a table." msgstr "테이블을 삭제하려면, DROP TABLE 명령을 사용하세요." -#: commands/tablecmds.c:252 +#: commands/tablecmds.c:261 #, c-format msgid "sequence \"%s\" does not exist" msgstr "\"%s\" 시퀀스 없음" -#: commands/tablecmds.c:253 +#: commands/tablecmds.c:262 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "\"%s\" 시퀀스 없음, 무시함" -#: commands/tablecmds.c:255 +#: commands/tablecmds.c:264 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "시퀀스를 삭제하려면 DROP SEQUENCE 명령을 사용하세요." -#: commands/tablecmds.c:258 +#: commands/tablecmds.c:267 #, c-format msgid "view \"%s\" does not exist" msgstr "\"%s\" 뷰(view) 없음" -#: commands/tablecmds.c:259 +#: commands/tablecmds.c:268 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "\"%s\" 뷰(view) 없음, 무시함" -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:270 msgid "Use DROP VIEW to remove a view." msgstr "뷰를 삭제하려면, DROP VIEW 명령을 사용하세요." -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:273 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "\"%s\" 이름의 구체화된 뷰가 없음" -#: commands/tablecmds.c:265 +#: commands/tablecmds.c:274 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "\"%s\" 구체화된 뷰 없음, 건너뜀" -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:276 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "구체화된 뷰를 삭제하려면, DROP MATERIALIZED VIEW 명령을 사용하세요." -#: commands/tablecmds.c:270 commands/tablecmds.c:294 commands/tablecmds.c:18978 -#: parser/parse_utilcmd.c:2245 +#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19783 +#: parser/parse_utilcmd.c:2251 #, c-format msgid "index \"%s\" does not exist" msgstr "\"%s\" 인덱스 없음" -#: commands/tablecmds.c:271 commands/tablecmds.c:295 +#: commands/tablecmds.c:280 commands/tablecmds.c:304 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "\"%s\" 인덱스 없음, 무시함" -#: commands/tablecmds.c:273 commands/tablecmds.c:297 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 msgid "Use DROP INDEX to remove an index." msgstr "인덱스를 삭제하려면, DROP INDEX 명령을 사용하세요." -#: commands/tablecmds.c:278 +#: commands/tablecmds.c:287 #, c-format msgid "\"%s\" is not a type" msgstr "\"%s\" 개체는 자료형이 아님" -#: commands/tablecmds.c:279 +#: commands/tablecmds.c:288 msgid "Use DROP TYPE to remove a type." msgstr "자료형을 삭제하려면 DROP TYPE 명령을 사용하세요." -#: commands/tablecmds.c:282 commands/tablecmds.c:13730 -#: commands/tablecmds.c:16193 +#: commands/tablecmds.c:291 commands/tablecmds.c:14325 +#: commands/tablecmds.c:16886 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "\"%s\" 외부 테이블 없음" -#: commands/tablecmds.c:283 +#: commands/tablecmds.c:292 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "\"%s\" 외부 테이블 없음, 건너뜀" -#: commands/tablecmds.c:285 +#: commands/tablecmds.c:294 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "외부 테이블을 삭제하려면, DROP FOREIGN TABLE 명령을 사용하세요." -#: commands/tablecmds.c:700 +#: commands/tablecmds.c:734 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMIT 옵션은 임시 테이블에서만 사용될 수 있습니다" -#: commands/tablecmds.c:731 +#: commands/tablecmds.c:765 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "보안 제한 작업 내에서 임시 테이블을 만들 수 없음" -#: commands/tablecmds.c:767 commands/tablecmds.c:15038 +#: commands/tablecmds.c:801 commands/tablecmds.c:15745 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "\"%s\" 테이블이 여러 번 상속됨" -#: commands/tablecmds.c:955 -#, c-format -msgid "" -"specifying a table access method is not supported on a partitioned table" -msgstr "테이블 접근 방법은 파티션된 테이블에서는 사용할 수 없음" - -#: commands/tablecmds.c:1048 +#: commands/tablecmds.c:1067 #, c-format msgid "\"%s\" is not partitioned" msgstr "\"%s\" 파티션 된 테이블 아님" -#: commands/tablecmds.c:1142 +#: commands/tablecmds.c:1161 #, c-format msgid "cannot partition using more than %d columns" msgstr "%d개보다 많은 칼럼을 이용해서 파티션할 수 없음" -#: commands/tablecmds.c:1198 +#: commands/tablecmds.c:1217 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "\"%s\" 파티션된 테이블의 외부 파티션을 만들 수 없음" -#: commands/tablecmds.c:1200 +#: commands/tablecmds.c:1219 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "\"%s\" 테이블은 유니크 인덱스를 포함 하고 있음." -#: commands/tablecmds.c:1365 +#: commands/tablecmds.c:1338 commands/tablecmds.c:13341 +#, c-format +msgid "too many array dimensions" +msgstr "너무 많은 배열 차수" + +#: commands/tablecmds.c:1343 parser/parse_clause.c:774 +#: parser/parse_relation.c:1912 +#, c-format +msgid "column \"%s\" cannot be declared SETOF" +msgstr "\"%s\" 칼럼은 SETOF를 지정할 수 없습니다" + +#: commands/tablecmds.c:1489 #, c-format msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" msgstr "DROP INDEX CONCURRENTLY 명령은 하나의 인덱스만 지울 수 있습니다" -#: commands/tablecmds.c:1369 +#: commands/tablecmds.c:1493 #, c-format msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLY 명령에서는 CASCADE 옵션을 사용할 수 없음" -#: commands/tablecmds.c:1473 +#: commands/tablecmds.c:1597 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "" "\"%s\" 파티션된 테이블의 인덱스에 대해서는 CONCURRENTLY 옵션을 사용할 수 없음" -#: commands/tablecmds.c:1761 +#: commands/tablecmds.c:1885 #, c-format msgid "cannot truncate only a partitioned table" msgstr "파티션 된 테이블만 truncate 할 수 없음" -#: commands/tablecmds.c:1762 +#: commands/tablecmds.c:1886 #, c-format msgid "" "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions " @@ -11030,38 +11485,38 @@ msgstr "" "ONLY 옵션을 빼고 사용하거나, 하위 파티션 테이블을 대상으로 직접 TRUNCATE " "ONLY 명령을 사용하세요." -#: commands/tablecmds.c:1835 +#: commands/tablecmds.c:1959 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "\"%s\" 개체의 자료도 함께 삭제됨" -#: commands/tablecmds.c:2199 +#: commands/tablecmds.c:2320 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "\"%s\" 외부 테이블에 자료를 비울 수 없음" -#: commands/tablecmds.c:2256 +#: commands/tablecmds.c:2377 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "다른 세션의 임시 테이블 자료는 비울(truncate) 수 없습니다" -#: commands/tablecmds.c:2488 commands/tablecmds.c:14935 +#: commands/tablecmds.c:2606 commands/tablecmds.c:15642 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "\"%s\" 파티션 된 테이블로부터 상속할 수 없습니다" -#: commands/tablecmds.c:2493 +#: commands/tablecmds.c:2611 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "\"%s\" 파티션 테이블입니다, 그래서 상속 대상이 될 수 없습니다" -#: commands/tablecmds.c:2501 parser/parse_utilcmd.c:2475 -#: parser/parse_utilcmd.c:2617 +#: commands/tablecmds.c:2619 parser/parse_utilcmd.c:2481 +#: parser/parse_utilcmd.c:2623 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "상속할 \"%s\" 릴레이션(relation)은 테이블도, 외부 테이블도 아닙니다" -#: commands/tablecmds.c:2513 +#: commands/tablecmds.c:2631 #, c-format msgid "" "cannot create a temporary relation as partition of permanent relation \"%s\"" @@ -11069,74 +11524,25 @@ msgstr "" "\"%s\" 테이블은 일반 테이블입니다. 임시 테이블을 이것의 파티션 테이블로 만들 " "수 없습니다" -#: commands/tablecmds.c:2522 commands/tablecmds.c:14914 +#: commands/tablecmds.c:2640 commands/tablecmds.c:15621 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "\"%s\" 임시 테이블입니다, 그래서 상속 대상이 될 수 없습니다" -#: commands/tablecmds.c:2532 commands/tablecmds.c:14922 +#: commands/tablecmds.c:2650 commands/tablecmds.c:15629 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "다른 세션의 임시 테이블입니다, 그래서 상속 대상이 될 수 없습니다" -#: commands/tablecmds.c:2585 -#, c-format -msgid "merging multiple inherited definitions of column \"%s\"" -msgstr "\"%s\" 칼럼이 중복되어 상속됩니다." - -#: commands/tablecmds.c:2597 -#, c-format -msgid "inherited column \"%s\" has a type conflict" -msgstr "상위 테이블에서 지정한 \"%s\" 칼럼의 자료형들이 일치하지 않습니다" - -#: commands/tablecmds.c:2599 commands/tablecmds.c:2628 -#: commands/tablecmds.c:2647 commands/tablecmds.c:2919 -#: commands/tablecmds.c:2955 commands/tablecmds.c:2971 -#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 -#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 -#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 -#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 -#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 -#: parser/parse_param.c:223 -#, c-format -msgid "%s versus %s" -msgstr "%s 형과 %s 형" - -#: commands/tablecmds.c:2612 -#, c-format -msgid "inherited column \"%s\" has a collation conflict" -msgstr "상속 받은 \"%s\" 칼럼의 정렬규칙에서 충돌합니다." - -#: commands/tablecmds.c:2614 commands/tablecmds.c:2935 -#: commands/tablecmds.c:6849 -#, c-format -msgid "\"%s\" versus \"%s\"" -msgstr "\"%s\" 형과 \"%s\" 형" - -#: commands/tablecmds.c:2626 -#, c-format -msgid "inherited column \"%s\" has a storage parameter conflict" -msgstr "상속 받은 \"%s\" 칼럼의 스토리지 설정값에서 충돌합니다" - -#: commands/tablecmds.c:2645 commands/tablecmds.c:2969 -#, c-format -msgid "column \"%s\" has a compression method conflict" -msgstr "\"%s\" 칼럼의 압축 방법이 충돌합니다" - -#: commands/tablecmds.c:2661 -#, c-format -msgid "inherited column \"%s\" has a generation conflict" -msgstr "상속된 \"%s\" 칼럼에 대한 생성 충돌 발생" - -#: commands/tablecmds.c:2767 commands/tablecmds.c:2822 -#: commands/tablecmds.c:12456 parser/parse_utilcmd.c:1298 -#: parser/parse_utilcmd.c:1341 parser/parse_utilcmd.c:1740 -#: parser/parse_utilcmd.c:1848 +#: commands/tablecmds.c:2791 commands/tablecmds.c:2845 +#: commands/tablecmds.c:13024 parser/parse_utilcmd.c:1265 +#: parser/parse_utilcmd.c:1308 parser/parse_utilcmd.c:1735 +#: parser/parse_utilcmd.c:1843 #, c-format msgid "cannot convert whole-row table reference" msgstr "전체 로우 테이블 참조형으로 변환할 수 없음" -#: commands/tablecmds.c:2768 parser/parse_utilcmd.c:1299 +#: commands/tablecmds.c:2792 parser/parse_utilcmd.c:1266 #, c-format msgid "" "Generation expression for column \"%s\" contains a whole-row reference to " @@ -11145,85 +11551,55 @@ msgstr "" "\"%s\" 칼럼용 미리 계산된 칼럼 생성식에 \"%s\" 테이블 전체 로우 참조가 있습니" "다" -#: commands/tablecmds.c:2823 parser/parse_utilcmd.c:1342 +#: commands/tablecmds.c:2846 parser/parse_utilcmd.c:1309 #, c-format msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." msgstr "\"%s\" 제약조건에 \"%s\" 테이블 전체 로우 참조가 있습니다" -#: commands/tablecmds.c:2901 -#, c-format -msgid "merging column \"%s\" with inherited definition" -msgstr "\"%s\" 칼럼을 상속된 정의와 병합하는 중" - -#: commands/tablecmds.c:2905 -#, c-format -msgid "moving and merging column \"%s\" with inherited definition" -msgstr "\"%s\" 칼럼을 상속된 정의와 이동, 병합하는 중" - -#: commands/tablecmds.c:2906 -#, c-format -msgid "User-specified column moved to the position of the inherited column." -msgstr "사용자 지정 칼럼이 상속된 칼럼의 위치로 이동되었습니다" - -#: commands/tablecmds.c:2917 -#, c-format -msgid "column \"%s\" has a type conflict" -msgstr "\"%s\" 칼럼의 자료형이 충돌합니다" - -#: commands/tablecmds.c:2933 -#, c-format -msgid "column \"%s\" has a collation conflict" -msgstr "\"%s\" 칼럼의 정렬규칙이 충돌합니다" - -#: commands/tablecmds.c:2953 -#, c-format -msgid "column \"%s\" has a storage parameter conflict" -msgstr "\"%s\" 칼럼의 스토리지 설정값이 충돌합니다" - -#: commands/tablecmds.c:2999 commands/tablecmds.c:3086 +#: commands/tablecmds.c:2956 commands/tablecmds.c:3227 #, c-format msgid "column \"%s\" inherits from generated column but specifies default" msgstr "상속 받은 \"%s\" 칼럼은 미리 계산된 칼럼인데, 기본값이 설정되어 있음" -#: commands/tablecmds.c:3004 commands/tablecmds.c:3091 +#: commands/tablecmds.c:2961 commands/tablecmds.c:3232 #, c-format msgid "column \"%s\" inherits from generated column but specifies identity" msgstr "" "상속 받은 \"%s\" 칼럼은 미리 계산된 칼럼인데, 일련번호 식별 옵션이 있음" -#: commands/tablecmds.c:3012 commands/tablecmds.c:3099 +#: commands/tablecmds.c:2969 commands/tablecmds.c:3240 #, c-format msgid "child column \"%s\" specifies generation expression" msgstr "" "\"%s\" 칼럼은 상속 받은 칼럼임. 미리 계산된 칼럼의 생성식을 사용할 수 없음" -#: commands/tablecmds.c:3014 commands/tablecmds.c:3101 +#: commands/tablecmds.c:2971 commands/tablecmds.c:3242 #, c-format msgid "A child table column cannot be generated unless its parent column is." msgstr "" "하위 테이블의 계산된 칼럼은 상위 테이블에서 이미 계산된 칼럼이어야 합니다." -#: commands/tablecmds.c:3147 +#: commands/tablecmds.c:3017 #, c-format msgid "column \"%s\" inherits conflicting generation expressions" msgstr "상속 받는 \"%s\" 칼럼에 지정된 미리 계산된 생성식이 충돌합니다" -#: commands/tablecmds.c:3149 +#: commands/tablecmds.c:3019 #, c-format msgid "To resolve the conflict, specify a generation expression explicitly." msgstr "이 충돌을 피하려면, 명시적으로 미리 계산된 생성식을 지정하십시오." -#: commands/tablecmds.c:3153 +#: commands/tablecmds.c:3023 #, c-format msgid "column \"%s\" inherits conflicting default values" msgstr "상속 받는 \"%s\" 칼럼의 default 값이 충돌함" -#: commands/tablecmds.c:3155 +#: commands/tablecmds.c:3025 #, c-format msgid "To resolve the conflict, specify a default explicitly." msgstr "이 충돌을 피하려면, default 값을 바르게 지정하십시오." -#: commands/tablecmds.c:3205 +#: commands/tablecmds.c:3080 #, c-format msgid "" "check constraint name \"%s\" appears multiple times but with different " @@ -11231,109 +11607,188 @@ msgid "" msgstr "" "\"%s\" 체크 제약 조건 이름이 여러 번 나타나지만, 각각 다른 식으로 되어있음" -#: commands/tablecmds.c:3418 +#: commands/tablecmds.c:3131 #, c-format -msgid "cannot move temporary tables of other sessions" -msgstr "다른 세션의 임시 테이블들은 이동할 수 없습니다" +msgid "merging column \"%s\" with inherited definition" +msgstr "\"%s\" 칼럼을 상속된 정의와 병합하는 중" -#: commands/tablecmds.c:3488 +#: commands/tablecmds.c:3135 #, c-format -msgid "cannot rename column of typed table" -msgstr "칼럼 이름을 바꿀 수 없음" +msgid "moving and merging column \"%s\" with inherited definition" +msgstr "\"%s\" 칼럼을 상속된 정의와 이동, 병합하는 중" -#: commands/tablecmds.c:3507 +#: commands/tablecmds.c:3136 #, c-format -msgid "cannot rename columns of relation \"%s\"" -msgstr "\"%s\" 릴레이션의 칼럼 이름을 바꿀 수 없음" +msgid "User-specified column moved to the position of the inherited column." +msgstr "사용자 지정 칼럼이 상속된 칼럼의 위치로 이동되었습니다" -#: commands/tablecmds.c:3602 +#: commands/tablecmds.c:3148 #, c-format -msgid "inherited column \"%s\" must be renamed in child tables too" -msgstr "하위 테이블에서도 상속된 \"%s\" 칼럼의 이름을 바꾸어야 함" +msgid "column \"%s\" has a type conflict" +msgstr "\"%s\" 칼럼의 자료형이 충돌합니다" -#: commands/tablecmds.c:3634 +#: commands/tablecmds.c:3150 commands/tablecmds.c:3184 +#: commands/tablecmds.c:3200 commands/tablecmds.c:3307 +#: commands/tablecmds.c:3340 commands/tablecmds.c:3356 +#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 +#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 +#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 +#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 +#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 +#: parser/parse_param.c:223 #, c-format -msgid "cannot rename system column \"%s\"" -msgstr "\"%s\" 이름의 칼럼은 시스템 칼럼입니다, 이름을 바꿀 수 없습니다" +msgid "%s versus %s" +msgstr "%s 형과 %s 형" -#: commands/tablecmds.c:3649 +#: commands/tablecmds.c:3162 +#, c-format +msgid "column \"%s\" has a collation conflict" +msgstr "\"%s\" 칼럼의 정렬규칙이 충돌합니다" + +#: commands/tablecmds.c:3164 commands/tablecmds.c:3326 +#: commands/tablecmds.c:7080 +#, c-format +msgid "\"%s\" versus \"%s\"" +msgstr "\"%s\" 형과 \"%s\" 형" + +#: commands/tablecmds.c:3182 +#, c-format +msgid "column \"%s\" has a storage parameter conflict" +msgstr "\"%s\" 칼럼의 스토리지 설정값이 충돌합니다" + +#: commands/tablecmds.c:3198 commands/tablecmds.c:3354 +#, c-format +msgid "column \"%s\" has a compression method conflict" +msgstr "\"%s\" 칼럼의 압축 방법이 충돌합니다" + +#: commands/tablecmds.c:3293 +#, c-format +msgid "merging multiple inherited definitions of column \"%s\"" +msgstr "\"%s\" 칼럼이 중복되어 상속됩니다." + +#: commands/tablecmds.c:3305 +#, c-format +msgid "inherited column \"%s\" has a type conflict" +msgstr "상위 테이블에서 지정한 \"%s\" 칼럼의 자료형들이 일치하지 않습니다" + +#: commands/tablecmds.c:3324 +#, c-format +msgid "inherited column \"%s\" has a collation conflict" +msgstr "상속 받은 \"%s\" 칼럼의 정렬규칙에서 충돌합니다." + +#: commands/tablecmds.c:3338 +#, c-format +msgid "inherited column \"%s\" has a storage parameter conflict" +msgstr "상속 받은 \"%s\" 칼럼의 스토리지 설정값에서 충돌합니다" + +#: commands/tablecmds.c:3366 +#, c-format +msgid "inherited column \"%s\" has a generation conflict" +msgstr "상속된 \"%s\" 칼럼에 대한 생성 충돌 발생" + +#: commands/tablecmds.c:3597 +#, c-format +msgid "cannot move temporary tables of other sessions" +msgstr "다른 세션의 임시 테이블들은 이동할 수 없습니다" + +#: commands/tablecmds.c:3670 +#, c-format +msgid "cannot rename column of typed table" +msgstr "칼럼 이름을 바꿀 수 없음" + +#: commands/tablecmds.c:3689 +#, c-format +msgid "cannot rename columns of relation \"%s\"" +msgstr "\"%s\" 릴레이션의 칼럼 이름을 바꿀 수 없음" + +#: commands/tablecmds.c:3784 +#, c-format +msgid "inherited column \"%s\" must be renamed in child tables too" +msgstr "하위 테이블에서도 상속된 \"%s\" 칼럼의 이름을 바꾸어야 함" + +#: commands/tablecmds.c:3816 +#, c-format +msgid "cannot rename system column \"%s\"" +msgstr "\"%s\" 이름의 칼럼은 시스템 칼럼입니다, 이름을 바꿀 수 없습니다" + +#: commands/tablecmds.c:3831 #, c-format msgid "cannot rename inherited column \"%s\"" msgstr "\"%s\" 이름의 칼럼은 상속 받은 칼럼입니다, 이름을 바꿀 수 없습니다" -#: commands/tablecmds.c:3801 +#: commands/tablecmds.c:3983 #, c-format msgid "inherited constraint \"%s\" must be renamed in child tables too" msgstr "" "하위 테이블에서도 상속된 \"%s\" 제약조건은 하위 테이블에서도 이름이 바뀌어야 " "함" -#: commands/tablecmds.c:3808 +#: commands/tablecmds.c:3990 #, c-format msgid "cannot rename inherited constraint \"%s\"" msgstr "\"%s\" 상속된 제약조건은 이름을 바꿀 수 없습니다" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4105 +#: commands/tablecmds.c:4290 #, c-format msgid "" "cannot %s \"%s\" because it is being used by active queries in this session" msgstr "이 세션의 활성 쿼리에서 사용 중이므로 %s \"%s\" 작업을 할 수 없음" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4114 +#: commands/tablecmds.c:4299 #, c-format msgid "cannot %s \"%s\" because it has pending trigger events" msgstr "보류 중인 트리거 이벤트가 있으므로 %s \"%s\" 작업을 할 수 없음" -#: commands/tablecmds.c:4581 +#: commands/tablecmds.c:4325 +#, c-format +msgid "cannot alter temporary tables of other sessions" +msgstr "다른 세션의 임시 테이블에 대해서는 alter 작업을 할 수 없음" + +#: commands/tablecmds.c:4798 #, c-format msgid "cannot alter partition \"%s\" with an incomplete detach" msgstr "" "\"%s\" 파티션 테이블은 불완전한 detach 상태이기에 alter 작업을 할 수 없음" -#: commands/tablecmds.c:4774 commands/tablecmds.c:4789 +#: commands/tablecmds.c:5002 commands/tablecmds.c:5017 #, c-format msgid "cannot change persistence setting twice" msgstr "로그 사용/미사용 옵션을 중복 해서 지정했음" -#: commands/tablecmds.c:4810 -#, c-format -msgid "cannot change access method of a partitioned table" -msgstr "파티션 된 테이블의 접근 방법은 바꿀 수 없음" - -#: commands/tablecmds.c:4816 +#: commands/tablecmds.c:5038 #, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" msgstr "다중 SET ACCESS METHOD 구문은 사용할 수 없음" -#: commands/tablecmds.c:5537 +#: commands/tablecmds.c:5768 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "\"%s\" 시스템 릴레이션을 다시 쓰기(rewrite) 할 수 없음" -#: commands/tablecmds.c:5543 +#: commands/tablecmds.c:5774 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "카탈로그 테이블로 사용되어 \"%s\" 테이블을 rewrite 못함" -#: commands/tablecmds.c:5553 +#: commands/tablecmds.c:5786 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "다른 세션의 임시 테이블을 다시 쓰기(rewrite) 할 수 없음" -#: commands/tablecmds.c:6048 +#: commands/tablecmds.c:6281 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "\"%s\" 열(해당 릴레이션 \"%s\")의 자료 가운데 null 값이 있습니다" -#: commands/tablecmds.c:6065 +#: commands/tablecmds.c:6298 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "" "\"%s\" 체크 제약 조건(해당 릴레이션 \"%s\")을 위반하는 몇몇 자료가 있습니다" -#: commands/tablecmds.c:6084 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6317 partitioning/partbounds.c:3387 #, c-format msgid "" "updated partition constraint for default partition \"%s\" would be violated " @@ -11341,173 +11796,173 @@ msgid "" msgstr "" "몇몇 자료가 \"%s\" 기본 파티션용에서 변경된 파티션 제약조건을 위배한 것 같음" -#: commands/tablecmds.c:6090 +#: commands/tablecmds.c:6323 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "\"%s\" 릴레이션의 파티션 제약 조건을 위반하는 몇몇 자료가 있습니다" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6352 +#: commands/tablecmds.c:6588 #, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" msgstr "%s ALTER 작업은 \"%s\" 릴레이션 대상으로 수행할 수 없음" -#: commands/tablecmds.c:6607 commands/tablecmds.c:6614 +#: commands/tablecmds.c:6843 commands/tablecmds.c:6850 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" -msgstr "\"%s\" 자료형 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 형식을 사용함)" +msgstr "\"%s\" 자료형 바꿀 수 없음(\"%s.%s\" 칼럼에서 해당 형식을 사용함)" -#: commands/tablecmds.c:6621 +#: commands/tablecmds.c:6857 #, c-format msgid "" "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" msgstr "" -"\"%s\" 외부 테이블을 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형을 사용함)" +"\"%s\" 외부 테이블을 바꿀 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형을 사용함)" -#: commands/tablecmds.c:6628 +#: commands/tablecmds.c:6864 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "" -"\"%s\" 테이블을 변경할 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형식을 사용함)" +"\"%s\" 테이블을 바꿀 수 없음(\"%s.%s\" 칼럼에서 해당 로우 형식을 사용함)" -#: commands/tablecmds.c:6684 +#: commands/tablecmds.c:6920 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "" -"\"%s\" 자료형을 변경할 수 없음, 이 자료형은 typed 테이블의 자료형이기 때문" +"\"%s\" 자료형을 바꿀 수 없음, 이 자료형은 typed 테이블의 자료형이기 때문" -#: commands/tablecmds.c:6686 +#: commands/tablecmds.c:6922 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "" "이 개체와 관계된 모든 개체들을 함께 변경하려면 ALTER ... CASCADE 명령을 사용" "하십시오" -#: commands/tablecmds.c:6732 +#: commands/tablecmds.c:6968 #, c-format msgid "type %s is not a composite type" msgstr "%s 자료형은 복합 자료형이 아닙니다" -#: commands/tablecmds.c:6759 +#: commands/tablecmds.c:6995 #, c-format msgid "cannot add column to typed table" msgstr "typed 테이블에는 칼럼을 추가 할 수 없음" -#: commands/tablecmds.c:6812 +#: commands/tablecmds.c:7043 #, c-format msgid "cannot add column to a partition" msgstr "파티션 테이블에는 칼럼을 추가 할 수 없습니다" -#: commands/tablecmds.c:6841 commands/tablecmds.c:15165 +#: commands/tablecmds.c:7072 commands/tablecmds.c:15860 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "" "\"%s\" 상속된 테이블의 \"%s\" 열 자료형이 상위 테이블의 자료형과 틀립니다" -#: commands/tablecmds.c:6847 commands/tablecmds.c:15172 +#: commands/tablecmds.c:7078 commands/tablecmds.c:15866 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "" "\"%s\" 상속된 테이블의 \"%s\" 칼럼 정렬규칙이 상위 테이블의 정렬규칙과 틀립니" "다" -#: commands/tablecmds.c:6865 +#: commands/tablecmds.c:7096 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "\"%s\" 열(\"%s\" 하위)의 정의를 병합하는 중" -#: commands/tablecmds.c:6908 +#: commands/tablecmds.c:7149 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "하위 테이블에 재귀적으로 식별 칼럼을 추가할 수는 없음" -#: commands/tablecmds.c:7159 +#: commands/tablecmds.c:7362 #, c-format msgid "column must be added to child tables too" msgstr "하위 테이블에도 칼럼을 추가해야 함" -#: commands/tablecmds.c:7237 +#: commands/tablecmds.c:7440 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "\"%s\" 이름의 칼럼이 \"%s\" 릴레이션에 이미 있습니다, 건너뜀" -#: commands/tablecmds.c:7244 +#: commands/tablecmds.c:7447 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "\"%s\" 이름의 칼럼은 \"%s\" 릴레이션에 이미 있습니다" -#: commands/tablecmds.c:7310 commands/tablecmds.c:12094 +#: commands/tablecmds.c:7513 commands/tablecmds.c:12652 #, c-format msgid "" "cannot remove constraint from only the partitioned table when partitions " "exist" msgstr "하위 테이블이 있는 경우, 상위 테이블의 제약조건만 지울 수는 없음" -#: commands/tablecmds.c:7311 commands/tablecmds.c:7628 -#: commands/tablecmds.c:8593 commands/tablecmds.c:12095 +#: commands/tablecmds.c:7514 commands/tablecmds.c:7828 +#: commands/tablecmds.c:8006 commands/tablecmds.c:8113 +#: commands/tablecmds.c:8230 commands/tablecmds.c:9049 +#: commands/tablecmds.c:12653 #, c-format msgid "Do not specify the ONLY keyword." msgstr "ONLY 옵션을 빼고 사용하세요." -#: commands/tablecmds.c:7348 commands/tablecmds.c:7554 -#: commands/tablecmds.c:7696 commands/tablecmds.c:7810 -#: commands/tablecmds.c:7904 commands/tablecmds.c:7963 -#: commands/tablecmds.c:8082 commands/tablecmds.c:8221 -#: commands/tablecmds.c:8291 commands/tablecmds.c:8425 -#: commands/tablecmds.c:12249 commands/tablecmds.c:13753 -#: commands/tablecmds.c:16282 +#: commands/tablecmds.c:7550 commands/tablecmds.c:7754 +#: commands/tablecmds.c:7896 commands/tablecmds.c:8028 +#: commands/tablecmds.c:8157 commands/tablecmds.c:8251 +#: commands/tablecmds.c:8352 commands/tablecmds.c:8509 +#: commands/tablecmds.c:8662 commands/tablecmds.c:8743 +#: commands/tablecmds.c:8877 commands/tablecmds.c:12806 +#: commands/tablecmds.c:14348 commands/tablecmds.c:16975 #, c-format msgid "cannot alter system column \"%s\"" -msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. 그래서 변경될 수 없습니다" +msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. 그래서 바꿀 수 없습니다" -#: commands/tablecmds.c:7354 commands/tablecmds.c:7702 +#: commands/tablecmds.c:7556 commands/tablecmds.c:7902 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "\"%s\" 칼럼(해당 테이블: \"%s\")은 식별 칼럼입니다." -#: commands/tablecmds.c:7397 +#: commands/tablecmds.c:7597 #, c-format msgid "column \"%s\" is in a primary key" msgstr "\"%s\" 칼럼은 기본키 칼럼입니다" -#: commands/tablecmds.c:7402 +#: commands/tablecmds.c:7602 #, c-format msgid "column \"%s\" is in index used as replica identity" msgstr "\"%s\" 칼럼 대상 인덱스는 복제 식별자로 사용 됨" -#: commands/tablecmds.c:7425 +#: commands/tablecmds.c:7625 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "파티션 테이블에서 \"%s\" 칼럼은 NOT NULL 속성으로 되어 있습니다" -#: commands/tablecmds.c:7625 commands/tablecmds.c:9077 +#: commands/tablecmds.c:7825 commands/tablecmds.c:9533 #, c-format msgid "constraint must be added to child tables too" msgstr "하위 테이블에도 제약 조건을 추가해야 함" -#: commands/tablecmds.c:7626 +#: commands/tablecmds.c:7826 #, c-format msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")은 이미 NOT NULL 속성이 없습니다." -#: commands/tablecmds.c:7704 -#, c-format -msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead." -msgstr "" -"대신에, ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY 명령을 사용하세요." - -#: commands/tablecmds.c:7709 +#: commands/tablecmds.c:7911 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "\"%s\" 칼럼(해당 테이블: \"%s\")은 계산된 칼럼입니다." -#: commands/tablecmds.c:7712 +#: commands/tablecmds.c:8005 #, c-format -msgid "Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION instead." -msgstr "" -"대신에, ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION 명령을 사용하세요." +msgid "cannot add identity to a column of only the partitioned table" +msgstr "상위 파티션 테이블 단독으로 식별자 속성의 칼럼을 지정할 수 없음" + +#: commands/tablecmds.c:8011 +#, c-format +msgid "cannot add identity to a column of a partition" +msgstr "한 하위 테이블에 식별자 속성의 칼럼을 지정할 수는 없음" -#: commands/tablecmds.c:7821 +#: commands/tablecmds.c:8039 #, c-format msgid "" "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity " @@ -11516,95 +11971,120 @@ msgstr "" "식별자 옵션을 사용하려면, \"%s\" 칼럼(해당 릴레이션: \"%s\")에 NOT NULL 옵션" "이 있어야 합니다." -#: commands/tablecmds.c:7827 +#: commands/tablecmds.c:8045 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "\"%s\" 이름의 칼럼(해당 릴레이션: \"%s\")은 이미 식별 칼럼입니다" -#: commands/tablecmds.c:7833 +#: commands/tablecmds.c:8051 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "\"%s\" 이름의 칼럼(해당 릴레이션: \"%s\")은 이미 default 입니다" -#: commands/tablecmds.c:7910 commands/tablecmds.c:7971 +#: commands/tablecmds.c:8112 +#, c-format +msgid "cannot change identity column of only the partitioned table" +msgstr "상위 파티션 테이블만 대상으로 식별자 속성 칼럼을 바꿀 수는 없음" + +#: commands/tablecmds.c:8118 +#, c-format +msgid "cannot change identity column of a partition" +msgstr "한 하위 파티션 테이블만 대상으로 식별자 속성 칼럼을 바꿀 수는 없음" + +#: commands/tablecmds.c:8163 commands/tablecmds.c:8259 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "\"%s\" 이름의 칼럼(해당 릴레이션: \"%s\")은 식별 칼럼이 아닙니다" -#: commands/tablecmds.c:7976 +#: commands/tablecmds.c:8229 +#, c-format +msgid "cannot drop identity from a column of only the partitioned table" +msgstr "상위 파티션 테이블만 대상으로 식별자 속성 칼럼을 삭제할 수는 없음" + +#: commands/tablecmds.c:8235 +#, c-format +msgid "cannot drop identity from a column of a partition" +msgstr "한 하위 파티션 테이블만 대상으로 식별자 속성 칼럼을 삭제할 수는 없음" + +#: commands/tablecmds.c:8264 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "\"%s\" 이름의 칼럼(해당 릴레이션: \"%s\")은 식별 칼럼이 아님, 건너뜀" -#: commands/tablecmds.c:8029 +#: commands/tablecmds.c:8358 +#, c-format +msgid "column \"%s\" of relation \"%s\" is not a generated column" +msgstr "\"%s\" 칼럼(해당 테이블: \"%s\")은 계산된 칼럼이 아님" + +#: commands/tablecmds.c:8456 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "ALTER TABLE / DROP EXPRESSION 작업은 하위 테이블에도 적용되어야함" -#: commands/tablecmds.c:8051 +#: commands/tablecmds.c:8478 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "상속 받은 칼럼에서는 미리 계산된 표현식을 못 없앰" -#: commands/tablecmds.c:8090 +#: commands/tablecmds.c:8517 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")은 미리 계산된 칼럼이 아님" -#: commands/tablecmds.c:8095 +#: commands/tablecmds.c:8522 #, c-format msgid "" "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" msgstr "\"%s\" 칼럼(해당 릴레이션: \"%s\")은 미리 계산된 칼럼이 아님, 건너뜀" -#: commands/tablecmds.c:8168 +#: commands/tablecmds.c:8600 #, c-format msgid "cannot refer to non-index column by number" msgstr "숫자로 인덱스 사용하지 않는 칼럼을 참조할 수 없음" -#: commands/tablecmds.c:8211 +#: commands/tablecmds.c:8652 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "%d번째 칼럼이 없습니다. 해당 릴레이션: \"%s\"" -#: commands/tablecmds.c:8230 +#: commands/tablecmds.c:8671 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "" "\"%s\" 포함된 칼럼 (해당 인덱스: \"%s\") 관련 통계정보를 수정할 수 없음" -#: commands/tablecmds.c:8235 +#: commands/tablecmds.c:8676 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "" "\"%s\" 비표현식 칼럼 (해당 인덱스: \"%s\") 관련 통계정보를 수정할 수 없음" -#: commands/tablecmds.c:8237 +#: commands/tablecmds.c:8678 #, c-format msgid "Alter statistics on table column instead." msgstr "대신에 테이블 칼럼 대상으로 통계정보를 수정하세요." -#: commands/tablecmds.c:8472 +#: commands/tablecmds.c:8924 #, c-format msgid "cannot drop column from typed table" msgstr "typed 테이블에서 칼럼을 삭제할 수 없음" -#: commands/tablecmds.c:8531 +#: commands/tablecmds.c:8987 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "\"%s\" 칼럼은 \"%s\" 릴레이션에 없음, 건너뜀" -#: commands/tablecmds.c:8544 +#: commands/tablecmds.c:9000 #, c-format msgid "cannot drop system column \"%s\"" msgstr "\"%s\" 칼럼은 시스템 칼럼입니다, 삭제될 수 없습니다" -#: commands/tablecmds.c:8554 +#: commands/tablecmds.c:9010 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "\"%s\" 칼럼은 상속받은 칼럼입니다, 삭제될 수 없습니다" -#: commands/tablecmds.c:8567 +#: commands/tablecmds.c:9023 #, c-format msgid "" "cannot drop column \"%s\" because it is part of the partition key of " @@ -11612,14 +12092,14 @@ msgid "" msgstr "" "\"%s\" 칼럼은 \"%s\" 릴레이션의 파티션 키로 사용되고 있어 삭제 될 수 없음" -#: commands/tablecmds.c:8592 +#: commands/tablecmds.c:9048 #, c-format msgid "" "cannot drop column from only the partitioned table when partitions exist" msgstr "" "파티션 테이블이 있는 파티션된 테이블에서 그 테이블만 칼럼을 삭제 할 수 없음" -#: commands/tablecmds.c:8797 +#: commands/tablecmds.c:9253 #, c-format msgid "" "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned " @@ -11628,7 +12108,7 @@ msgstr "" "ALTER TABLE / ADD CONSTRAINT USING INDEX 작업은 파티션 된 테이블 대상으로는 " "지원하지 않음" -#: commands/tablecmds.c:8822 +#: commands/tablecmds.c:9278 #, c-format msgid "" "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" @@ -11636,7 +12116,7 @@ msgstr "" "ALTER TABLE / ADD CONSTRAINT USING INDEX 작업은 \"%s\" 인덱스를 \"%s\" 이름으" "로 바꿀 것입니다." -#: commands/tablecmds.c:9159 +#: commands/tablecmds.c:9615 #, c-format msgid "" "cannot use ONLY for foreign key on partitioned table \"%s\" referencing " @@ -11645,7 +12125,7 @@ msgstr "" "\"%s\" 파티션 상위 테이블의 참조키에는 ONLY 옵션을 사용할 수 없음. 이 테이블" "은 \"%s\" 릴레이션을 참조 함" -#: commands/tablecmds.c:9165 +#: commands/tablecmds.c:9621 #, c-format msgid "" "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing " @@ -11654,22 +12134,22 @@ msgstr "" "\"%s\" 파타션된 테이블에 NOT VALID 참조키를 추가할 수 없음 (참조 하는 테이" "블: \"%s\")" -#: commands/tablecmds.c:9168 +#: commands/tablecmds.c:9624 #, c-format msgid "This feature is not yet supported on partitioned tables." msgstr "이 기능은 파티션 된 테이블 대상으로는 아직 지원하지 않습니다." -#: commands/tablecmds.c:9175 commands/tablecmds.c:9631 +#: commands/tablecmds.c:9631 commands/tablecmds.c:10092 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "참조된 \"%s\" 릴레이션은 테이블이 아닙니다" -#: commands/tablecmds.c:9198 +#: commands/tablecmds.c:9654 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "영구 저장용 테이블의 제약 조건은 영구 저장용 테이블을 참조 합니다." -#: commands/tablecmds.c:9205 +#: commands/tablecmds.c:9661 #, c-format msgid "" "constraints on unlogged tables may reference only permanent or unlogged " @@ -11678,155 +12158,176 @@ msgstr "" "unlogged 테이블의 제약 조건은 영구 저장용 테이블 또는 unlogged 테이블을 참조" "합니다." -#: commands/tablecmds.c:9211 +#: commands/tablecmds.c:9667 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "임시 테이블의 제약 조건은 임시 테이블에 대해서만 참조할 것입니다." -#: commands/tablecmds.c:9215 +#: commands/tablecmds.c:9671 #, c-format msgid "" "constraints on temporary tables must involve temporary tables of this session" msgstr "" "임시 테이블의 제약 조건은 이 세션용 임시 테이블에 대해서만 적용 됩니다." -#: commands/tablecmds.c:9279 commands/tablecmds.c:9285 +#: commands/tablecmds.c:9735 commands/tablecmds.c:9741 #, c-format msgid "" "invalid %s action for foreign key constraint containing generated column" msgstr "계산된 칼럼을 포함하는 참조키 제약조건용 %s 액션은 잘못 되었음" -#: commands/tablecmds.c:9301 +#: commands/tablecmds.c:9757 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "참조키(foreign key) disagree를 위한 참조하는, 또는 참조되는 열 수" -#: commands/tablecmds.c:9408 +#: commands/tablecmds.c:9864 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "\"%s\" 참조키(foreign key) 제약 조건은 구현되어질 수 없습니다" -#: commands/tablecmds.c:9410 +#: commands/tablecmds.c:9866 #, c-format msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." msgstr "" "\"%s\" 열과 \"%s\" 열 인덱스는 함께 사용할 수 없는 자료형입니다: %s and %s." -#: commands/tablecmds.c:9567 +#: commands/tablecmds.c:10035 #, c-format msgid "" "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" msgstr "" "ON DELETE SET 동작을 지정하려는 \"%s\" 칼럼은 참조키의 한 부분이어야 합니다." -#: commands/tablecmds.c:9841 commands/tablecmds.c:10311 -#: parser/parse_utilcmd.c:791 parser/parse_utilcmd.c:920 +#: commands/tablecmds.c:10392 commands/tablecmds.c:10832 +#: parser/parse_utilcmd.c:822 parser/parse_utilcmd.c:945 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "참조키 제약 조건은 외부 테이블에서는 사용할 수 없음" -#: commands/tablecmds.c:10864 commands/tablecmds.c:11142 -#: commands/tablecmds.c:12051 commands/tablecmds.c:12126 +#: commands/tablecmds.c:10815 +#, c-format +msgid "" +"cannot attach table \"%s\" as a partition because it is referenced by " +"foreign key \"%s\"" +msgstr "" +"\"%s\" 테이블은 하위 테이블로 추가 될 수 없음, 이 테이블은 \"%s\" 참조키의 대" +"상이기 때문" + +#: commands/tablecmds.c:11416 commands/tablecmds.c:11697 +#: commands/tablecmds.c:12609 commands/tablecmds.c:12683 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "\"%s\" 제약 조건이 \"%s\" 릴레이션에 없습니다." -#: commands/tablecmds.c:10871 +#: commands/tablecmds.c:11423 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")은 참조키 제약조건이 아닙니다." -#: commands/tablecmds.c:10909 +#: commands/tablecmds.c:11461 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" -msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")을 변경할 수 없음" +msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")을 바꿀 수 없음" -#: commands/tablecmds.c:10912 +#: commands/tablecmds.c:11464 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "" "\"%s\" 제약 조건은 \"%s\" 제약 조건에서 파생되었음, 해당 릴레이션: \"%s\"" -#: commands/tablecmds.c:10914 +#: commands/tablecmds.c:11466 #, c-format msgid "You may alter the constraint it derives from instead." msgstr "대신에, 원 제약 조건을 변경 하세요." -#: commands/tablecmds.c:11150 +#: commands/tablecmds.c:11705 #, c-format msgid "" "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" msgstr "" "\"%s\" 제약 조건(해당 테이블: \"%s\")은 참조키도 체크 제약 조건도 아닙니다." -#: commands/tablecmds.c:11227 +#: commands/tablecmds.c:11782 #, c-format msgid "constraint must be validated on child tables too" msgstr "하위 테이블에도 제약 조건이 유효해야 함" -#: commands/tablecmds.c:11314 +#: commands/tablecmds.c:11869 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "참조키(foreign key) 제약 조건에서 참조하는 \"%s\" 칼럼이 없음" -#: commands/tablecmds.c:11320 +#: commands/tablecmds.c:11875 #, c-format msgid "system columns cannot be used in foreign keys" msgstr "시스템 칼럼은 참조키로 사용될 수 없음" -#: commands/tablecmds.c:11324 +#: commands/tablecmds.c:11879 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "참조키(foreign key)에서 %d 키 개수보다 많이 가질 수 없음" -#: commands/tablecmds.c:11389 +#: commands/tablecmds.c:11944 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "참조되는 \"%s\" 테이블의 지연 가능한 기본키를 사용할 수 없음" -#: commands/tablecmds.c:11406 +#: commands/tablecmds.c:11961 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "참조되는 \"%s\" 테이블에는 기본키(primary key)가 없습니다" -#: commands/tablecmds.c:11470 +#: commands/tablecmds.c:12029 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "참조키의 참조 칼럼 목록에 칼럼이 중복되면 안됩니다" -#: commands/tablecmds.c:11562 +#: commands/tablecmds.c:12121 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "참조되는 \"%s\" 테이블의 지연 가능한 유니크 제약 조건을 사용할 수 없음" -#: commands/tablecmds.c:11567 +#: commands/tablecmds.c:12126 #, c-format msgid "" "there is no unique constraint matching given keys for referenced table \"%s\"" msgstr "" "참조되는 \"%s\" 테이블을 위한 주워진 키와 일치하는 고유 제약 조건이 없습니다" -#: commands/tablecmds.c:12007 +#: commands/tablecmds.c:12565 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "상속된 \"%s\" 제약 조건(해당 테이블: \"%s\")을 삭제할 수 없음" -#: commands/tablecmds.c:12057 +#: commands/tablecmds.c:12615 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" msgstr "\"%s\" 제약 조건(해당 테이블: \"%s\")이 없음, 건너뜀" -#: commands/tablecmds.c:12233 +#: commands/tablecmds.c:12790 #, c-format msgid "cannot alter column type of typed table" -msgstr "typed 테이블의 칼럼 자료형은 변경할 수 없음" +msgstr "typed 테이블의 칼럼 자료형은 바꿀 수 없음" + +#: commands/tablecmds.c:12816 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "미리 계산된 칼럼의 자료형을 바꿀 때는 USING 구문을 지정할 수 없음" + +#: commands/tablecmds.c:12817 commands/tablecmds.c:18028 +#: commands/tablecmds.c:18118 commands/trigger.c:656 +#: rewrite/rewriteHandler.c:941 rewrite/rewriteHandler.c:976 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "\"%s\" 칼럼은 미리 계산된 칼럼입니다." -#: commands/tablecmds.c:12260 +#: commands/tablecmds.c:12827 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "\"%s\" 이름의 칼럼은 상속 받은 칼럼입니다, 이름을 바꿀 수 없습니다" -#: commands/tablecmds.c:12269 +#: commands/tablecmds.c:12836 #, c-format msgid "" "cannot alter column \"%s\" because it is part of the partition key of " @@ -11835,7 +12336,7 @@ msgstr "" "\"%s\" 칼럼은 \"%s\" 테이블의 파티션 키 가운데 하나이기 때문에, alter 작업" "을 할 수 없음" -#: commands/tablecmds.c:12319 +#: commands/tablecmds.c:12886 #, c-format msgid "" "result of USING clause for column \"%s\" cannot be cast automatically to " @@ -11843,192 +12344,197 @@ msgid "" msgstr "" "\"%s\" 칼럼에서 쓰인 USING 절의 결과가 %s 자료형으로 자동 형변환을 할 수 없음" -#: commands/tablecmds.c:12322 +#: commands/tablecmds.c:12889 #, c-format msgid "You might need to add an explicit cast." msgstr "명시적 형변환을 해야할 것 같습니다." -#: commands/tablecmds.c:12326 +#: commands/tablecmds.c:12893 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "\"%s\" 칼럼의 자료형을 %s 형으로 형변환할 수 없음" #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12329 +#: commands/tablecmds.c:12897 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "\"USING %s::%s\" 구문을 추가해야 할 것 같습니다." -#: commands/tablecmds.c:12428 +#: commands/tablecmds.c:12996 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "" "\"%s\" 칼럼은 \"%s\" 테이블의 상속된 칼럼이기에 alter 작업을 할 수 없음" -#: commands/tablecmds.c:12457 +#: commands/tablecmds.c:13025 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "USING 표현식에서 전체 로우 테이블 참조를 포함하고 있습니다." -#: commands/tablecmds.c:12468 +#: commands/tablecmds.c:13036 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "하위 테이블에서도 상속된 \"%s\" 칼럼의 형식을 바꾸어야 함" -#: commands/tablecmds.c:12593 +#: commands/tablecmds.c:13161 #, c-format msgid "cannot alter type of column \"%s\" twice" -msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. 그래서 변경될 수 없습니다" +msgstr "\"%s\" 칼럼의 자료형을 중복해서 바꿀 수는 없음" -#: commands/tablecmds.c:12631 +#: commands/tablecmds.c:13199 #, c-format msgid "" "generation expression for column \"%s\" cannot be cast automatically to type " "%s" msgstr "\"%s\" 칼럼의 생성 구문은 %s 형으로 자동 형변환할 수 없음" -#: commands/tablecmds.c:12636 +#: commands/tablecmds.c:13204 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "\"%s\" 칼럼의 기본 값을 %s 형으로 형변환할 수 없음" -#: commands/tablecmds.c:12717 +#: commands/tablecmds.c:13508 #, c-format -msgid "cannot alter type of a column used by a view or rule" -msgstr "뷰 또는 규칙에서 사용하는 칼럼의 형식을 변경할 수 없음" +msgid "cannot alter type of a column used by a function or procedure" +msgstr "함수나 프로시져에서 사용하는 칼럼의 자료형 변경은 할 수 없음" -#: commands/tablecmds.c:12718 commands/tablecmds.c:12737 -#: commands/tablecmds.c:12755 +#: commands/tablecmds.c:13509 commands/tablecmds.c:13524 +#: commands/tablecmds.c:13544 commands/tablecmds.c:13563 +#: commands/tablecmds.c:13622 #, c-format msgid "%s depends on column \"%s\"" msgstr "%s 의존대상 열: \"%s\"" -#: commands/tablecmds.c:12736 +#: commands/tablecmds.c:13523 +#, c-format +msgid "cannot alter type of a column used by a view or rule" +msgstr "뷰 또는 규칙에서 사용하는 칼럼의 형식을 바꿀 수 없음" + +#: commands/tablecmds.c:13543 #, c-format msgid "cannot alter type of a column used in a trigger definition" -msgstr "트리거 정의에서 사용하는 칼럼의 자료형을 변경할 수 없음" +msgstr "트리거 정의에서 사용하는 칼럼의 자료형을 바꿀 수 없음" -#: commands/tablecmds.c:12754 +#: commands/tablecmds.c:13562 #, c-format msgid "cannot alter type of a column used in a policy definition" -msgstr "정책 정의에서 사용하는 칼럼의 자료형을 변경할 수 없음" +msgstr "정책 정의에서 사용하는 칼럼의 자료형을 바꿀 수 없음" -#: commands/tablecmds.c:12785 +#: commands/tablecmds.c:13593 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "미리 계산된 칼럼의 자료형을 바꿀 수 없음" -#: commands/tablecmds.c:12786 +#: commands/tablecmds.c:13594 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "\"%s\" 칼럼은 미리 계산된 칼럼인 \"%s\"에서 사용되고 있음." -#: commands/tablecmds.c:13861 commands/tablecmds.c:13873 +#: commands/tablecmds.c:13621 +#, c-format +msgid "cannot alter type of a column used by a publication WHERE clause" +msgstr "WHERE절이 있는 발행에서 사용되는 칼럼은 자료형을 바꿀 수 없음" + +#: commands/tablecmds.c:14456 commands/tablecmds.c:14468 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "\"%s\" 인덱스의 소유주를 바꿀 수 없음" -#: commands/tablecmds.c:13863 commands/tablecmds.c:13875 +#: commands/tablecmds.c:14458 commands/tablecmds.c:14470 #, c-format msgid "Change the ownership of the index's table instead." msgstr "대신에 그 인덱스의 해당 테이블 소유자을 변경하세요." -#: commands/tablecmds.c:13889 +#: commands/tablecmds.c:14484 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "\"%s\" 시퀀스의 소유주를 바꿀 수 없음" -#: commands/tablecmds.c:13903 commands/tablecmds.c:17173 -#: commands/tablecmds.c:17192 -#, c-format -msgid "Use ALTER TYPE instead." -msgstr "대신 ALTER TYPE을 사용하십시오." - -#: commands/tablecmds.c:13912 +#: commands/tablecmds.c:14509 #, c-format msgid "cannot change owner of relation \"%s\"" msgstr "\"%s\" 릴레이션의 소유주를 바꿀 수 없음" -#: commands/tablecmds.c:14274 +#: commands/tablecmds.c:14976 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "SET TABLESPACE 구문이 중복 사용되었습니다" -#: commands/tablecmds.c:14351 +#: commands/tablecmds.c:15053 #, c-format msgid "cannot set options for relation \"%s\"" msgstr "\"%s\" 릴레이션용 옵션을 지정할 수 없음" -#: commands/tablecmds.c:14385 commands/view.c:445 +#: commands/tablecmds.c:15087 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "" "WITH CHECK OPTION 옵션은 자동 갱신 가능한 뷰에 대해서만 사용할 수 있습니다" -#: commands/tablecmds.c:14635 +#: commands/tablecmds.c:15338 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "테이블스페이스에 테이블과 인덱스와 구체화된 뷰만 있습니다." -#: commands/tablecmds.c:14647 +#: commands/tablecmds.c:15350 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "" "해당 개체를 pg_global 테이블스페이스로 옮기거나 그 반대로 작업할 수 없음" -#: commands/tablecmds.c:14739 +#: commands/tablecmds.c:15442 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "\"%s.%s\" 릴레이션을 잠글 수 없어 중지 중입니다" -#: commands/tablecmds.c:14755 +#: commands/tablecmds.c:15458 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr "검색조건에 일치하는 릴레이션이 \"%s\" 테이블스페이스에 없음" -#: commands/tablecmds.c:14873 +#: commands/tablecmds.c:15580 #, c-format msgid "cannot change inheritance of typed table" -msgstr "typed 테이블의 상속 정보는 변경할 수 없음" +msgstr "typed 테이블의 상속 정보는 바꿀 수 없음" -#: commands/tablecmds.c:14878 commands/tablecmds.c:15396 +#: commands/tablecmds.c:15585 commands/tablecmds.c:16085 #, c-format msgid "cannot change inheritance of a partition" msgstr "파티션 테이블의 상속 정보는 바꿀 수 없음" -#: commands/tablecmds.c:14883 +#: commands/tablecmds.c:15590 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "파티션된 테이블의 상속 정보는 바꿀 수 없음" -#: commands/tablecmds.c:14929 +#: commands/tablecmds.c:15636 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "다른 세션의 임시 테이블을 상속할 수 없음" -#: commands/tablecmds.c:14942 +#: commands/tablecmds.c:15649 #, c-format msgid "cannot inherit from a partition" msgstr "파티션 테이블에서 상속 할 수 없음" -#: commands/tablecmds.c:14964 commands/tablecmds.c:17813 +#: commands/tablecmds.c:15671 commands/tablecmds.c:18529 #, c-format msgid "circular inheritance not allowed" msgstr "순환 되는 상속은 허용하지 않습니다" -#: commands/tablecmds.c:14965 commands/tablecmds.c:17814 +#: commands/tablecmds.c:15672 commands/tablecmds.c:18530 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "\"%s\" 개체는 이미 \"%s\" 개체로부터 상속받은 상태입니다." -#: commands/tablecmds.c:14978 +#: commands/tablecmds.c:15685 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "" "\"%s\" 트리거(해당 테이블 \"%s\")은 하위테이블 상속과 관련되어 보호되고 있습" "니다." -#: commands/tablecmds.c:14980 +#: commands/tablecmds.c:15687 #, c-format msgid "" "ROW triggers with transition tables are not supported in inheritance " @@ -12036,119 +12542,119 @@ msgid "" msgstr "" "transition 테이블의 ROW 트리거들은 계층적 상속 테이블에서는 지원하지 않음" -#: commands/tablecmds.c:15183 +#: commands/tablecmds.c:15876 #, c-format msgid "column \"%s\" in child table must be marked NOT NULL" msgstr "자식 테이블의 \"%s\" 칼럼은 NOT NULL 속성이 있어야 합니다" -#: commands/tablecmds.c:15192 +#: commands/tablecmds.c:15885 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "자식 테이블의 \"%s\" 칼럼은 미리 계산된 칼럼이어야 함" -#: commands/tablecmds.c:15197 +#: commands/tablecmds.c:15889 #, c-format msgid "column \"%s\" in child table must not be a generated column" msgstr "자식 테이블의 \"%s\" 칼럼은 미리 계산된 칼럼이 아니여야 합니다." -#: commands/tablecmds.c:15228 +#: commands/tablecmds.c:15927 #, c-format msgid "child table is missing column \"%s\"" msgstr "자식 테이블에는 \"%s\" 칼럼이 없습니다" -#: commands/tablecmds.c:15316 +#: commands/tablecmds.c:16008 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "\"%s\" 하위 테이블에 \"%s\" 체크 제약 조건에 대한 다른 정의가 있음" -#: commands/tablecmds.c:15324 +#: commands/tablecmds.c:16015 #, c-format msgid "" -"constraint \"%s\" conflicts with non-inherited constraint on child table \"%s" -"\"" +"constraint \"%s\" conflicts with non-inherited constraint on child table " +"\"%s\"" msgstr "" "\"%s\" 제약 조건이 \"%s\" 하위 테이블에 있는 비 상속 제약 조건과 충돌합니다" -#: commands/tablecmds.c:15335 +#: commands/tablecmds.c:16025 #, c-format msgid "" "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" msgstr "" "\"%s\" 제약 조건이 \"%s\" 하위 테이블에 있는 NOT VALID 제약 조건과 충돌합니다" -#: commands/tablecmds.c:15374 +#: commands/tablecmds.c:16063 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "자식 테이블에 \"%s\" 제약 조건이 없습니다" -#: commands/tablecmds.c:15460 +#: commands/tablecmds.c:16149 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "" "\"%s\" 하위 파티션과 \"%s.%s\" 상위 파티션 테이블과 분리 작업을 이미 진행, 지" "연 되고 있습니다." -#: commands/tablecmds.c:15489 commands/tablecmds.c:15537 +#: commands/tablecmds.c:16178 commands/tablecmds.c:16224 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "\"%s\" 릴레이션은 \"%s\" 릴레이션의 파티션이 아닙니다" -#: commands/tablecmds.c:15543 +#: commands/tablecmds.c:16230 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "\"%s\" 릴레이션은 \"%s\" 릴레이션의 부모가 아닙니다" -#: commands/tablecmds.c:15771 +#: commands/tablecmds.c:16457 #, c-format msgid "typed tables cannot inherit" msgstr "typed 테이블은 상속할 수 없음" -#: commands/tablecmds.c:15801 +#: commands/tablecmds.c:16487 #, c-format msgid "table is missing column \"%s\"" msgstr "테이블에는 \"%s\" 칼럼이 없습니다" -#: commands/tablecmds.c:15812 +#: commands/tablecmds.c:16498 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "\"%s\" 칼럼은 \"%s\" 자료형입니다." -#: commands/tablecmds.c:15821 +#: commands/tablecmds.c:16507 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "\"%s\" 테이블의 \"%s\" 칼럼 자료형 틀립니다" -#: commands/tablecmds.c:15835 +#: commands/tablecmds.c:16521 #, c-format msgid "table has extra column \"%s\"" msgstr "\"%s\" 칼럼은 확장형입니다" -#: commands/tablecmds.c:15887 +#: commands/tablecmds.c:16573 #, c-format msgid "\"%s\" is not a typed table" msgstr "\"%s\" 테이블은 typed 테이블이 아닙니다" -#: commands/tablecmds.c:16061 +#: commands/tablecmds.c:16747 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "\"%s\" 인덱스는 유니크 인덱스가 아니여서, 복제 식별자로 사용할 수 없음" -#: commands/tablecmds.c:16067 +#: commands/tablecmds.c:16753 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "\"%s\" non-immediate 인덱스는 복제 식별자로 사용할 수 없음" -#: commands/tablecmds.c:16073 +#: commands/tablecmds.c:16759 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "\"%s\" 인덱스는 expression 인덱스여서, 복제 식별자로 사용할 수 없음" -#: commands/tablecmds.c:16079 +#: commands/tablecmds.c:16765 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "\"%s\" 인덱스가 부분인덱스여서, 복제 식별자로 사용할 수 없음" -#: commands/tablecmds.c:16096 +#: commands/tablecmds.c:16782 #, c-format msgid "" "index \"%s\" cannot be used as replica identity because column %d is a " @@ -12156,7 +12662,7 @@ msgid "" msgstr "" "\"%s\" 인덱스는 복제 식별자로 사용할 수 없음, %d 번째 칼럼이 시스템 칼럼임" -#: commands/tablecmds.c:16103 +#: commands/tablecmds.c:16789 #, c-format msgid "" "index \"%s\" cannot be used as replica identity because column \"%s\" is " @@ -12165,23 +12671,23 @@ msgstr "" "\"%s\" 인덱스는 복제 식별자로 사용할 수 없음, \"%s\" 칼럼이 null 값 사용가능 " "속성임" -#: commands/tablecmds.c:16348 +#: commands/tablecmds.c:17041 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "\"%s\" 테이블은 임시 테이블이기에, 통계 정보를 변경 할 수 없음" -#: commands/tablecmds.c:16372 +#: commands/tablecmds.c:17065 #, c-format msgid "" "cannot change table \"%s\" to unlogged because it is part of a publication" msgstr "\"%s\" 테이블은 발생에 사용하고 있어, unlogged 속성으로 바꿀 수 없음" -#: commands/tablecmds.c:16374 +#: commands/tablecmds.c:17067 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "unlogged 릴레이션 복제할 수 없습니다." -#: commands/tablecmds.c:16419 +#: commands/tablecmds.c:17112 #, c-format msgid "" "could not change table \"%s\" to logged because it references unlogged table " @@ -12190,7 +12696,7 @@ msgstr "" "\"%s\" 테이블이 \"%s\" unlogged 테이블을 참조하고 있어 logged 속성으로 바꿀 " "수 없음" -#: commands/tablecmds.c:16429 +#: commands/tablecmds.c:17122 #, c-format msgid "" "could not change table \"%s\" to unlogged because it references logged table " @@ -12199,93 +12705,87 @@ msgstr "" "\"%s\" 테이블이 \"%s\" logged 테이블을 참조하고 있어 unlogged 속성으로 바꿀 " "수 없음" -#: commands/tablecmds.c:16487 +#: commands/tablecmds.c:17180 #, c-format msgid "cannot move an owned sequence into another schema" msgstr "소유된 시퀀스를 다른 스키마로 이동할 수 없음" -#: commands/tablecmds.c:16594 +#: commands/tablecmds.c:17288 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "\"%s\" 릴레이션이 \"%s\" 스키마에 이미 있습니다" -#: commands/tablecmds.c:17006 +#: commands/tablecmds.c:17713 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "\"%s\" 개체는 테이블도 구체화된 뷰도 아닙니다" -#: commands/tablecmds.c:17156 +#: commands/tablecmds.c:17866 #, c-format msgid "\"%s\" is not a composite type" msgstr "\"%s\" 개체는 복합 자료형입니다" -#: commands/tablecmds.c:17184 +#: commands/tablecmds.c:17896 #, c-format msgid "cannot change schema of index \"%s\"" msgstr "\"%s\" 인덱스의 스키마를 바꿀 수 없음" -#: commands/tablecmds.c:17186 commands/tablecmds.c:17198 +#: commands/tablecmds.c:17898 commands/tablecmds.c:17912 #, c-format msgid "Change the schema of the table instead." msgstr "대신에 그 인덱스의 해당 테이블 스키마를 변경하세요." -#: commands/tablecmds.c:17190 +#: commands/tablecmds.c:17902 #, c-format msgid "cannot change schema of composite type \"%s\"" msgstr "\"%s\" 복합 자료형의 스키마를 바꿀 수 없음" -#: commands/tablecmds.c:17196 +#: commands/tablecmds.c:17910 #, c-format msgid "cannot change schema of TOAST table \"%s\"" msgstr "\"%s\" TOAST 테이블의 스키마를 바꿀 수 없음" -#: commands/tablecmds.c:17228 +#: commands/tablecmds.c:17942 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "둘 이상의 칼럼을 사용할 \"list\" 파티션은 사용할 수 없습니다" -#: commands/tablecmds.c:17294 +#: commands/tablecmds.c:18008 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "\"%s\" 칼럼이 파티션 키로 사용되고 있지 않습니다" -#: commands/tablecmds.c:17302 +#: commands/tablecmds.c:18016 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. 그래서 파티션 키로 사용될 수 없습니다" -#: commands/tablecmds.c:17313 commands/tablecmds.c:17427 +#: commands/tablecmds.c:18027 commands/tablecmds.c:18117 #, c-format msgid "cannot use generated column in partition key" msgstr "미리 계산된 칼럼은 파티션 키로 사용할 수 없음" -#: commands/tablecmds.c:17314 commands/tablecmds.c:17428 commands/trigger.c:663 -#: rewrite/rewriteHandler.c:936 rewrite/rewriteHandler.c:971 +#: commands/tablecmds.c:18100 #, c-format -msgid "Column \"%s\" is a generated column." -msgstr "\"%s\" 칼럼은 미리 계산된 칼럼입니다." +msgid "partition key expressions cannot contain system column references" +msgstr "파티션 키 표현식에서는 시스템 칼럼 참조를 포함할 수 없습니다" -#: commands/tablecmds.c:17390 +#: commands/tablecmds.c:18147 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "파티션 키로 사용할 함수는 IMMUTABLE 특성이 있어야 합니다" -#: commands/tablecmds.c:17410 -#, c-format -msgid "partition key expressions cannot contain system column references" -msgstr "파티션 키 표현식에서는 시스템 칼럼 참조를 포함할 수 없습니다" - -#: commands/tablecmds.c:17440 +#: commands/tablecmds.c:18156 #, c-format msgid "cannot use constant expression as partition key" msgstr "파티션 키로 상수는 쓸 수 없습니다" -#: commands/tablecmds.c:17461 +#: commands/tablecmds.c:18177 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "파티션 표현식에 쓸 문자 정렬 규칙을 결정할 수 없습니다" -#: commands/tablecmds.c:17496 +#: commands/tablecmds.c:18212 #, c-format msgid "" "You must specify a hash operator class or define a default hash operator " @@ -12294,7 +12794,7 @@ msgstr "" "해당 자료형을 위한 해시 연산자 클래스를 지정하거나 기본 해시 연산자 클래스를 " "정의해 두어야 합니다" -#: commands/tablecmds.c:17502 +#: commands/tablecmds.c:18218 #, c-format msgid "" "You must specify a btree operator class or define a default btree operator " @@ -12303,121 +12803,134 @@ msgstr "" "해당 자료형을 위한 btree 연산자 클래스를 지정하거나 기본 btree 연산자 클래스" "를 정의해 두어야 합니다" -#: commands/tablecmds.c:17753 +#: commands/tablecmds.c:18469 #, c-format msgid "\"%s\" is already a partition" msgstr "\"%s\" 이름의 파티션 테이블이 이미 있습니다" -#: commands/tablecmds.c:17759 +#: commands/tablecmds.c:18475 #, c-format msgid "cannot attach a typed table as partition" msgstr "파티션 테이블로 typed 테이블을 추가할 수 없음" -#: commands/tablecmds.c:17775 +#: commands/tablecmds.c:18491 #, c-format msgid "cannot attach inheritance child as partition" msgstr "파티션 테이블로 상속을 이용한 하위 테이블을 추가할 수 없음" -#: commands/tablecmds.c:17789 +#: commands/tablecmds.c:18505 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "파티션 테이블로 상속용 상위 테이블을 추가할 수 없음" -#: commands/tablecmds.c:17823 +#: commands/tablecmds.c:18539 #, c-format msgid "" "cannot attach a temporary relation as partition of permanent relation \"%s\"" msgstr "" "\"%s\" 테이블은 일반 테이블입니다, 임시 파티션 테이블을 추가할 수 없습니다" -#: commands/tablecmds.c:17831 +#: commands/tablecmds.c:18547 #, c-format msgid "" "cannot attach a permanent relation as partition of temporary relation \"%s\"" msgstr "" "\"%s\" 테이블은 임시 테이블입니다, 일반 파티션 테이블을 추가할 수 없습니다" -#: commands/tablecmds.c:17839 +#: commands/tablecmds.c:18555 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "다른 세션의 임시 테이블을 파티션 테이블로 추가할 수 없습니다" -#: commands/tablecmds.c:17846 +#: commands/tablecmds.c:18562 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "다른 세션의 임시 테이블을 파티션 테이블로 추가할 수 없습니다" -#: commands/tablecmds.c:17866 +#: commands/tablecmds.c:18582 +#, c-format +msgid "table \"%s\" being attached contains an identity column \"%s\"" +msgstr "" +"\"%s\" 테이블의 \"%s\" 칼럼에 식별자 속성이 있는데 하위 테이블이 되려고 합니" +"다." + +#: commands/tablecmds.c:18584 +#, c-format +msgid "The new partition may not contain an identity column." +msgstr "" +"새로 만들어지는 하위 테이블에는 해당 칼럼에 식별자 속성이 없을 수 있습니다." + +#: commands/tablecmds.c:18592 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "\"%s\" 테이블의 \"%s\" 칼럼이 상위 테이블인 \"%s\"에 없음" -#: commands/tablecmds.c:17869 +#: commands/tablecmds.c:18595 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "새 파티션 테이블은 상위 테이블의 칼럼과 동일해야 합니다." -#: commands/tablecmds.c:17881 +#: commands/tablecmds.c:18607 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "" "\"%s\" 트리거가 \"%s\" 테이블에 있어 파티션 테이블로 포함 될 수 없습니다" -#: commands/tablecmds.c:17883 +#: commands/tablecmds.c:18609 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "" "transition 테이블의 ROW 트리거들은 파티션 하위 테이블에서는 쓸 수 없습니다." -#: commands/tablecmds.c:18062 +#: commands/tablecmds.c:18785 #, c-format msgid "" "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "\"%s\" 외부 테이블을 파티션된 \"%s\" 테이블의 부분으로 추가 할 수 없음" -#: commands/tablecmds.c:18065 +#: commands/tablecmds.c:18788 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "\"%s\" 파티션 상위 테이블에 유니크 인덱스가 있습니다." -#: commands/tablecmds.c:18382 +#: commands/tablecmds.c:19110 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "기본 하위 파티션이 있을 때는 하위 파티션 테이블 분리 작업을 할 수 없음" -#: commands/tablecmds.c:18491 +#: commands/tablecmds.c:19219 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "\"%s\" 파티션 상위 테이블이 온라인 모드로 삭제 되었음" -#: commands/tablecmds.c:18497 +#: commands/tablecmds.c:19225 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "\"%s\" 파티션 하위 테이블이 온라인 모드로 삭제 되었음" -#: commands/tablecmds.c:19012 commands/tablecmds.c:19032 -#: commands/tablecmds.c:19053 commands/tablecmds.c:19072 -#: commands/tablecmds.c:19114 +#: commands/tablecmds.c:19817 commands/tablecmds.c:19837 +#: commands/tablecmds.c:19858 commands/tablecmds.c:19877 +#: commands/tablecmds.c:19919 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "\"%s\" 인덱스를 \"%s\" 인덱스의 파티션으로 추가할 수 없음" -#: commands/tablecmds.c:19015 +#: commands/tablecmds.c:19820 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "\"%s\" 인덱스는 이미 다른 인덱스에 추가되어 있음." -#: commands/tablecmds.c:19035 +#: commands/tablecmds.c:19840 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "\"%s\" 인덱스는 \"%s\" 테이블의 하위 파티션 대상 인덱스가 아닙니다." -#: commands/tablecmds.c:19056 +#: commands/tablecmds.c:19861 #, c-format msgid "The index definitions do not match." msgstr "인덱스 정의가 일치하지 않습니다." -#: commands/tablecmds.c:19075 +#: commands/tablecmds.c:19880 #, c-format msgid "" "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint " @@ -12426,393 +12939,393 @@ msgstr "" "\"%s\" 인덱스는 \"%s\" 테이블의 제약조건과 연결되어 있는데, \"%s\" 인덱스를 " "위한 제약조건이 없습니다." -#: commands/tablecmds.c:19117 +#: commands/tablecmds.c:19922 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "\"%s\" 파티션 용으로 다른 인덱스가 추가되어 있습니다." -#: commands/tablecmds.c:19353 +#: commands/tablecmds.c:20158 #, c-format msgid "column data type %s does not support compression" msgstr "%s 형의 칼럼 자료형은 압축을 지원하지 않음" -#: commands/tablecmds.c:19360 +#: commands/tablecmds.c:20165 #, c-format msgid "invalid compression method \"%s\"" msgstr "잘못된 압축 방법: \"%s\"" -#: commands/tablecmds.c:19386 +#: commands/tablecmds.c:20191 #, c-format msgid "invalid storage type \"%s\"" msgstr "잘못된 STORAGE 값: \"%s\"" -#: commands/tablecmds.c:19396 +#: commands/tablecmds.c:20201 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "%s 자료형의 column의 STORAGE 값은 반드시 PLAIN 이어야 합니다" -#: commands/tablespace.c:199 commands/tablespace.c:650 +#: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" msgstr "\"%s\" 파일이 존재하지만 디렉터리가 아닙니다" -#: commands/tablespace.c:230 +#: commands/tablespace.c:224 #, c-format msgid "permission denied to create tablespace \"%s\"" msgstr "\"%s\" 테이블스페이스를 만들 권한이 없습니다" -#: commands/tablespace.c:232 +#: commands/tablespace.c:226 #, c-format msgid "Must be superuser to create a tablespace." msgstr "테이블스페이스는 슈퍼유저만 만들 수 있습니다." -#: commands/tablespace.c:248 +#: commands/tablespace.c:242 #, c-format msgid "tablespace location cannot contain single quotes" msgstr "테이블스페이스 위치에는 작은 따옴표를 사용할 수 없음" -#: commands/tablespace.c:261 +#: commands/tablespace.c:255 #, c-format msgid "tablespace location must be an absolute path" msgstr "테이블스페이스 경로는 절대경로여야 합니다" -#: commands/tablespace.c:273 +#: commands/tablespace.c:267 #, c-format msgid "tablespace location \"%s\" is too long" msgstr "테이블스페이스 경로가 너무 깁니다: \"%s\"" -#: commands/tablespace.c:280 +#: commands/tablespace.c:274 #, c-format msgid "tablespace location should not be inside the data directory" msgstr "테이블스페이스 경로는 데이터 디렉터리 안에 있으면 안됩니다" -#: commands/tablespace.c:289 commands/tablespace.c:976 +#: commands/tablespace.c:283 commands/tablespace.c:970 #, c-format msgid "unacceptable tablespace name \"%s\"" msgstr "\"%s\" 테이블스페이스 이름은 적당치 않습니다" -#: commands/tablespace.c:291 commands/tablespace.c:977 +#: commands/tablespace.c:285 commands/tablespace.c:971 #, c-format msgid "The prefix \"pg_\" is reserved for system tablespaces." msgstr "\"pg_\" 문자로 시작하는 테이블스페이스는 시스템 테이블스페이스입니다." -#: commands/tablespace.c:310 commands/tablespace.c:998 +#: commands/tablespace.c:304 commands/tablespace.c:992 #, c-format msgid "tablespace \"%s\" already exists" msgstr "\"%s\" 이름의 테이블스페이스는 이미 있음" -#: commands/tablespace.c:326 +#: commands/tablespace.c:320 #, c-format msgid "pg_tablespace OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때 pg_tablespace OID 값이 지정되지 않음" -#: commands/tablespace.c:431 commands/tablespace.c:959 -#: commands/tablespace.c:1048 commands/tablespace.c:1117 -#: commands/tablespace.c:1263 commands/tablespace.c:1466 +#: commands/tablespace.c:425 commands/tablespace.c:953 +#: commands/tablespace.c:1042 commands/tablespace.c:1111 +#: commands/tablespace.c:1257 commands/tablespace.c:1460 #, c-format msgid "tablespace \"%s\" does not exist" msgstr "\"%s\" 테이블스페이스 없음" -#: commands/tablespace.c:437 +#: commands/tablespace.c:431 #, c-format msgid "tablespace \"%s\" does not exist, skipping" msgstr "\"%s\" 테이블스페이스 없음, 건너 뜀" -#: commands/tablespace.c:463 +#: commands/tablespace.c:457 #, c-format msgid "tablespace \"%s\" cannot be dropped because some objects depend on it" msgstr "몇 객체들이 의존관계를 가져 \"%s\" 테이블스페이스를 삭제할 수 없음" -#: commands/tablespace.c:530 +#: commands/tablespace.c:524 #, c-format msgid "tablespace \"%s\" is not empty" msgstr "\"%s\" 테이블스페이스는 비어있지 않음" -#: commands/tablespace.c:617 +#: commands/tablespace.c:611 #, c-format msgid "directory \"%s\" does not exist" msgstr "\"%s\" 디렉터리 없음" -#: commands/tablespace.c:618 +#: commands/tablespace.c:612 #, c-format msgid "Create this directory for the tablespace before restarting the server." msgstr "이 서버를 재시작하기 전에 이 테이블스페이스 용 디렉터리를 만드세요." -#: commands/tablespace.c:623 +#: commands/tablespace.c:617 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "\"%s\" 디렉터리 액세스 권한을 지정할 수 없음: %m" -#: commands/tablespace.c:655 +#: commands/tablespace.c:649 #, c-format msgid "directory \"%s\" already in use as a tablespace" msgstr "\"%s\" 디렉터리는 이미 테이블스페이스로 사용 중임" -#: commands/tablespace.c:833 commands/tablespace.c:919 +#: commands/tablespace.c:827 commands/tablespace.c:913 #, c-format msgid "could not remove symbolic link \"%s\": %m" msgstr "\"%s\" 심벌릭 링크를 삭제할 수 없음: %m" -#: commands/tablespace.c:842 commands/tablespace.c:927 +#: commands/tablespace.c:836 commands/tablespace.c:921 #, c-format msgid "\"%s\" is not a directory or symbolic link" msgstr "\"%s\" 디렉터리도, 심볼릭 링크도 아님" -#: commands/tablespace.c:1122 +#: commands/tablespace.c:1116 #, c-format msgid "Tablespace \"%s\" does not exist." msgstr "\"%s\" 테이블스페이스 없음" -#: commands/tablespace.c:1568 +#: commands/tablespace.c:1562 #, c-format msgid "directories for tablespace %u could not be removed" msgstr "%u OID 테이블스페이스용 디렉터리는 삭제될 수 없음" -#: commands/tablespace.c:1570 +#: commands/tablespace.c:1564 #, c-format msgid "You can remove the directories manually if necessary." msgstr "필요하다면 OS 작업으로 그 디레터리를 삭제하세요" -#: commands/trigger.c:232 commands/trigger.c:243 +#: commands/trigger.c:225 commands/trigger.c:236 #, c-format msgid "\"%s\" is a table" msgstr "\"%s\" 개체는 테이블임" -#: commands/trigger.c:234 commands/trigger.c:245 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "Tables cannot have INSTEAD OF triggers." msgstr "테이블에 INSTEAD OF 트리거는 설정할 수 없음" -#: commands/trigger.c:266 +#: commands/trigger.c:259 #, c-format msgid "\"%s\" is a partitioned table" msgstr "\"%s\" 개체는 파티션 상위 테이블임" -#: commands/trigger.c:268 +#: commands/trigger.c:261 #, c-format msgid "" "ROW triggers with transition tables are not supported on partitioned tables." msgstr "" "transition 테이블의 ROW 트리거들은 파티션 상위 테이블에서 지원하지 않음." -#: commands/trigger.c:280 commands/trigger.c:287 commands/trigger.c:451 +#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 #, c-format msgid "\"%s\" is a view" msgstr "\"%s\" 개체는 뷰임" -#: commands/trigger.c:282 +#: commands/trigger.c:275 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." msgstr "뷰에 로우 단위 BEFORE, AFTER 트리거는 설정할 수 없음" -#: commands/trigger.c:289 +#: commands/trigger.c:282 #, c-format msgid "Views cannot have TRUNCATE triggers." msgstr "뷰에 TRUNCATE 트리거는 설정할 수 없음" -#: commands/trigger.c:297 commands/trigger.c:309 commands/trigger.c:444 +#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 #, c-format msgid "\"%s\" is a foreign table" msgstr "\"%s\" 개체는 외부 테이블임" -#: commands/trigger.c:299 +#: commands/trigger.c:292 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." msgstr "외부테이블에 INSTEAD OF 트리거는 설정할 수 없음" -#: commands/trigger.c:311 +#: commands/trigger.c:304 #, c-format msgid "Foreign tables cannot have constraint triggers." msgstr "외부 테이블에 제약 조건 트리거는 설정할 수 없음" -#: commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1439 +#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 #, c-format msgid "relation \"%s\" cannot have triggers" msgstr "\"%s\" 릴레이션에는 트리거를 지정할 수 없음" -#: commands/trigger.c:387 +#: commands/trigger.c:380 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" msgstr "TRUNCATE FOR EACH ROW 트리거는 지원되지 않음" -#: commands/trigger.c:395 +#: commands/trigger.c:388 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" msgstr "INSTEAD OF 트리거는 FOR EACH ROW 옵션으로 설정해야 함" -#: commands/trigger.c:399 +#: commands/trigger.c:392 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" msgstr "INSTEAD OF 트리거는 WHEN 조건을 사용할 수 없음" -#: commands/trigger.c:403 +#: commands/trigger.c:396 #, c-format msgid "INSTEAD OF triggers cannot have column lists" msgstr "INSTEAD OF 트리거는 칼럼 목록을 사용할 수 없음" -#: commands/trigger.c:432 +#: commands/trigger.c:425 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "REFERENCING 절에 ROW 변수 이름 붙이기를 지원하지 않습니다." -#: commands/trigger.c:433 +#: commands/trigger.c:426 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "이름 기반 전환 테이블은 OLD TABLE 또는 NEW TABLE 을 사용하세요." -#: commands/trigger.c:446 +#: commands/trigger.c:439 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "외부 테이블의 트리거들은 전환 테이블을 가질 수 없음." -#: commands/trigger.c:453 +#: commands/trigger.c:446 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "뷰에 정의한 트리거들은 전환 테이블을 가질 수 없음." -#: commands/trigger.c:469 +#: commands/trigger.c:462 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "" "ROW 트리거들이 있는 테이블을 파티션 테이블로 포함하는 기능은 지원하지 않습니" "다" -#: commands/trigger.c:473 +#: commands/trigger.c:466 #, c-format msgid "" "ROW triggers with transition tables are not supported on inheritance children" msgstr "전환 테이블용 ROW 트리거는 하위 상속 테이블에서는 지정할 수 없습니다." -#: commands/trigger.c:479 +#: commands/trigger.c:472 #, c-format msgid "transition table name can only be specified for an AFTER trigger" msgstr "전환 테이블 이름은 AFTER 트리거에서만 사용할 수 있습니다." -#: commands/trigger.c:484 +#: commands/trigger.c:477 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "전환 테이블에서 TRUNCATE 트리거는 지원하지 않습니다" -#: commands/trigger.c:501 +#: commands/trigger.c:494 #, c-format msgid "" "transition tables cannot be specified for triggers with more than one event" msgstr "전환 테이블은 하나 이상의 이벤트에 대한 트리거를 지정할 수 없습니다" -#: commands/trigger.c:512 +#: commands/trigger.c:505 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "전환 테이블은 칼럼 목록들에 대한 트리거를 지정할 수 없습니다" -#: commands/trigger.c:529 +#: commands/trigger.c:522 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" msgstr "NEW TABLE 옵션은 INSERT 또는 UPDATE 트리거에서만 사용할 수 있습니다." -#: commands/trigger.c:534 +#: commands/trigger.c:527 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE 옵션은 중복해서 사용할 수 없음" -#: commands/trigger.c:544 +#: commands/trigger.c:537 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" msgstr "OLD TABLE 옵션은 DELETE 또는 UPDATE 트리거에서만 사용할 수 있습니다." -#: commands/trigger.c:549 +#: commands/trigger.c:542 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE 옵션은 중복해서 사용할 수 없음" -#: commands/trigger.c:559 +#: commands/trigger.c:552 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "OLD TABLE 과 NEW TABLE 뒤에 오는 이름이 같을 수는 없습니다." -#: commands/trigger.c:623 commands/trigger.c:636 +#: commands/trigger.c:616 commands/trigger.c:629 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" msgstr "트리거의 WHEN 조건에는 칼럼 값을 참조할 수는 없음" -#: commands/trigger.c:628 +#: commands/trigger.c:621 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" msgstr "INSERT 트리거에서의 WHEN 조건에는 OLD 값을 참조할 수 없음" -#: commands/trigger.c:641 +#: commands/trigger.c:634 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" msgstr "DELETE 트리거에서의 WHEN 조건에는 NEW 값을 참조할 수 없음" -#: commands/trigger.c:646 +#: commands/trigger.c:639 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" msgstr "WHEN 조건절이 있는 BEFORE 트리거는 NEW 시스템 칼럼을 참조할 수 없음" -#: commands/trigger.c:654 commands/trigger.c:662 +#: commands/trigger.c:647 commands/trigger.c:655 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "" "WHEN 조건절이 있는 BEFORE 트리거는 NEW 미리 계산된 칼럼을 참조할 수 없음" -#: commands/trigger.c:655 +#: commands/trigger.c:648 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "" "로우 전체 참조가 사용되었고, 그 테이블에는 미리 계산된 칼럼이 있습니다." -#: commands/trigger.c:770 commands/trigger.c:1614 +#: commands/trigger.c:763 commands/trigger.c:1607 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "\"%s\" 이름의 트리거가 \"%s\" 테이블에 이미 있습니다" -#: commands/trigger.c:783 +#: commands/trigger.c:776 #, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" msgstr "\"%s\" 트리거가 \"%s\" 테이블에 내장 또는 하위 트리거로 있음" -#: commands/trigger.c:802 +#: commands/trigger.c:795 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" msgstr " \"%s\" 트리거가 \"%s\" 릴레이션에 제약 조건 트리거로 있음" -#: commands/trigger.c:1404 commands/trigger.c:1557 commands/trigger.c:1838 +#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "\"%s\" 트리거는 \"%s\" 테이블에 없음" -#: commands/trigger.c:1529 +#: commands/trigger.c:1522 #, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" msgstr "\"%s\" 트리거(해당 테이블: \"%s\") 이름을 바꿀 수 없음" -#: commands/trigger.c:1531 +#: commands/trigger.c:1524 #, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." msgstr "대신에 상위 파티션 테이블인 \"%s\" 테이블의 트리거 이름을 바꾸세요." -#: commands/trigger.c:1631 +#: commands/trigger.c:1624 #, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" msgstr "\"%s\" 트리거(해당 테이블: \"%s\") 이름을 바꿨음" -#: commands/trigger.c:1777 +#: commands/trigger.c:1770 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "액세스 권한 없음: \"%s\" 개체는 시스템 트리거임" -#: commands/trigger.c:2386 +#: commands/trigger.c:2379 #, c-format msgid "trigger function %u returned null value" msgstr "%u 트리거 함수가 null 값을 리턴했습니다" -#: commands/trigger.c:2446 commands/trigger.c:2664 commands/trigger.c:2917 -#: commands/trigger.c:3252 +#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 +#: commands/trigger.c:3263 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "BEFORE STATEMENT 트리거는 리턴값이 있으면 안됩니다" -#: commands/trigger.c:2522 +#: commands/trigger.c:2515 #, c-format msgid "" "moving row to another partition during a BEFORE FOR EACH ROW trigger is not " @@ -12821,25 +13334,17 @@ msgstr "" "BEFORE FOR EACH ROW 트리거가 실행 중일 때 다른 파티션으로 로우는 옮기는 것은 " "지원 하지 않습니다." -#: commands/trigger.c:2523 +#: commands/trigger.c:2516 #, c-format msgid "" "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." msgstr "" "\"%s\" 트리거가 실행되기 전에, 그 로우는 \"%s.%s\" 파티션에 있었습니다." -#: commands/trigger.c:3329 executor/nodeModifyTable.c:2363 -#: executor/nodeModifyTable.c:2446 -#, c-format -msgid "" -"tuple to be updated was already modified by an operation triggered by the " -"current command" -msgstr "" -"현재 명령으로 실행된 트리거 작업으로 변경해야할 자료가 이미 바뀌었습니다." - -#: commands/trigger.c:3330 executor/nodeModifyTable.c:1531 -#: executor/nodeModifyTable.c:1605 executor/nodeModifyTable.c:2364 -#: executor/nodeModifyTable.c:2447 executor/nodeModifyTable.c:3078 +#: commands/trigger.c:3341 executor/nodeModifyTable.c:1541 +#: executor/nodeModifyTable.c:1615 executor/nodeModifyTable.c:2377 +#: executor/nodeModifyTable.c:2468 executor/nodeModifyTable.c:3132 +#: executor/nodeModifyTable.c:3302 #, c-format msgid "" "Consider using an AFTER trigger instead of a BEFORE trigger to propagate " @@ -12848,137 +13353,137 @@ msgstr "" "다른 로우를 변경하는 일을 BEFORE 트리거 대신에 AFTER 트리거 사용을 고려해 보" "십시오" -#: commands/trigger.c:3371 executor/nodeLockRows.c:228 -#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:308 -#: executor/nodeModifyTable.c:1547 executor/nodeModifyTable.c:2381 -#: executor/nodeModifyTable.c:2589 +#: commands/trigger.c:3382 executor/nodeLockRows.c:228 +#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:314 +#: executor/nodeModifyTable.c:1557 executor/nodeModifyTable.c:2394 +#: executor/nodeModifyTable.c:2618 #, c-format msgid "could not serialize access due to concurrent update" msgstr "동시 업데이트 때문에 순차적 액세스가 불가능합니다" -#: commands/trigger.c:3379 executor/nodeModifyTable.c:1637 -#: executor/nodeModifyTable.c:2464 executor/nodeModifyTable.c:2613 -#: executor/nodeModifyTable.c:2966 +#: commands/trigger.c:3390 executor/nodeModifyTable.c:1647 +#: executor/nodeModifyTable.c:2485 executor/nodeModifyTable.c:2642 +#: executor/nodeModifyTable.c:3150 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "동시 삭제 작업 때문에 순차적 액세스가 불가능합니다" -#: commands/trigger.c:4586 +#: commands/trigger.c:4601 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" msgstr "보안 제한 작업 내에서는 지연 속성 트리거를 실행할 수 없음" -#: commands/trigger.c:5769 +#: commands/trigger.c:5782 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "\"%s\" 제약 조건은 DEFERRABLE 속성으로 만들어지지 않았습니다" -#: commands/trigger.c:5792 +#: commands/trigger.c:5805 #, c-format msgid "constraint \"%s\" does not exist" msgstr "\"%s\" 이름의 제약 조건이 없음" -#: commands/tsearchcmds.c:118 commands/tsearchcmds.c:635 +#: commands/tsearchcmds.c:124 commands/tsearchcmds.c:641 #, c-format msgid "function %s should return type %s" msgstr "%s 함수는 %s 자료형을 반환해야 함" -#: commands/tsearchcmds.c:194 +#: commands/tsearchcmds.c:200 #, c-format msgid "must be superuser to create text search parsers" msgstr "슈퍼유저만 전문 검색 파서를 만들 수 있음" -#: commands/tsearchcmds.c:247 +#: commands/tsearchcmds.c:253 #, c-format msgid "text search parser parameter \"%s\" not recognized" msgstr "\"%s\" 전문 검색 파서 매개 변수를 인식할 수 없음" -#: commands/tsearchcmds.c:257 +#: commands/tsearchcmds.c:263 #, c-format msgid "text search parser start method is required" msgstr "텍스트 검색 파서 start 메서드가 필요함" -#: commands/tsearchcmds.c:262 +#: commands/tsearchcmds.c:268 #, c-format msgid "text search parser gettoken method is required" msgstr "텍스트 검색 파서 gettoken 메서드가 필요함" -#: commands/tsearchcmds.c:267 +#: commands/tsearchcmds.c:273 #, c-format msgid "text search parser end method is required" msgstr "텍스트 검색 파서 end 메서드가 필요함" -#: commands/tsearchcmds.c:272 +#: commands/tsearchcmds.c:278 #, c-format msgid "text search parser lextypes method is required" msgstr "텍스트 검색 파서 lextypes 메서드가 필요함" -#: commands/tsearchcmds.c:366 +#: commands/tsearchcmds.c:372 #, c-format msgid "text search template \"%s\" does not accept options" msgstr "\"%s\" 전문 검색 템플릿이 옵션을 수락하지 않음" -#: commands/tsearchcmds.c:440 +#: commands/tsearchcmds.c:446 #, c-format msgid "text search template is required" msgstr "전문 검색 템플릿이 필요함" -#: commands/tsearchcmds.c:701 +#: commands/tsearchcmds.c:707 #, c-format msgid "must be superuser to create text search templates" msgstr "슈퍼유저만 전문 검색 템플릿을 만들 수 있음" -#: commands/tsearchcmds.c:743 +#: commands/tsearchcmds.c:749 #, c-format msgid "text search template parameter \"%s\" not recognized" msgstr "\"%s\" 전문 검색 템플릿 매개 변수를 인식할 수 없음" -#: commands/tsearchcmds.c:753 +#: commands/tsearchcmds.c:759 #, c-format msgid "text search template lexize method is required" msgstr "전문 검색 템플릿 lexize 메서드가 필요함" -#: commands/tsearchcmds.c:933 +#: commands/tsearchcmds.c:939 #, c-format msgid "text search configuration parameter \"%s\" not recognized" msgstr "\"%s\" 전문 검색 구성 매개 변수를 인식할 수 없음" -#: commands/tsearchcmds.c:940 +#: commands/tsearchcmds.c:946 #, c-format msgid "cannot specify both PARSER and COPY options" msgstr "PARSER 옵션과 COPY 옵션을 모두 지정할 수 없음" -#: commands/tsearchcmds.c:976 +#: commands/tsearchcmds.c:982 #, c-format msgid "text search parser is required" msgstr "전문 검색 파서가 필요함" -#: commands/tsearchcmds.c:1241 +#: commands/tsearchcmds.c:1277 #, c-format msgid "token type \"%s\" does not exist" msgstr "\"%s\" 토큰 형식이 없음" -#: commands/tsearchcmds.c:1501 +#: commands/tsearchcmds.c:1540 #, c-format msgid "mapping for token type \"%s\" does not exist" msgstr "\"%s\" 토큰 형식에 대한 매핑이 없음" -#: commands/tsearchcmds.c:1507 +#: commands/tsearchcmds.c:1546 #, c-format msgid "mapping for token type \"%s\" does not exist, skipping" msgstr "\"%s\" 토큰 형식에 대한 매핑이 없음, 건너뜀" -#: commands/tsearchcmds.c:1670 commands/tsearchcmds.c:1785 +#: commands/tsearchcmds.c:1707 commands/tsearchcmds.c:1822 #, c-format msgid "invalid parameter list format: \"%s\"" msgstr "잘못된 매개 변수 목록 형식: \"%s\"" -#: commands/typecmds.c:217 +#: commands/typecmds.c:221 #, c-format msgid "must be superuser to create a base type" msgstr "슈퍼유저만 기본 형식을 만들 수 있음" -#: commands/typecmds.c:275 +#: commands/typecmds.c:279 #, c-format msgid "" "Create the type as a shell type, then create its I/O functions, then do a " @@ -12987,127 +13492,127 @@ msgstr "" "쉘 타입으로 그 자료형을 만들고, 그것을 쓰기 위한 I/O 함수를 만들고, 끝으로 " "CREATE TYPE 명령을 사용해서 자료형을 만드세요." -#: commands/typecmds.c:327 commands/typecmds.c:1450 commands/typecmds.c:4257 +#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "잘못된 \"%s\" 속성의 자료형" -#: commands/typecmds.c:382 +#: commands/typecmds.c:386 #, c-format msgid "invalid type category \"%s\": must be simple ASCII" msgstr "\"%s\" 형식 범주가 잘못됨: 단순 ASCII여야 함" -#: commands/typecmds.c:401 +#: commands/typecmds.c:405 #, c-format msgid "array element type cannot be %s" msgstr "배열 요소의 자료형으로 %s 자료형을 사용할 수 없습니다" -#: commands/typecmds.c:433 +#: commands/typecmds.c:437 #, c-format msgid "alignment \"%s\" not recognized" msgstr "잘못된 ALIGNMENT 값: \"%s\"" -#: commands/typecmds.c:450 commands/typecmds.c:4131 +#: commands/typecmds.c:454 commands/typecmds.c:4354 #, c-format msgid "storage \"%s\" not recognized" msgstr "잘못된 STORAGE 값: \"%s\"" -#: commands/typecmds.c:461 +#: commands/typecmds.c:465 #, c-format msgid "type input function must be specified" msgstr "자료형 입력 함수를 지정하십시오" -#: commands/typecmds.c:465 +#: commands/typecmds.c:469 #, c-format msgid "type output function must be specified" msgstr "자료형 출력 함수를 지정하십시오" -#: commands/typecmds.c:470 +#: commands/typecmds.c:474 #, c-format msgid "" "type modifier output function is useless without a type modifier input " "function" msgstr "형식 한정자 입력 함수가 없으면 형식 한정자 출력 함수는 의미가 없음" -#: commands/typecmds.c:512 +#: commands/typecmds.c:516 #, c-format msgid "element type cannot be specified without a subscripting function" msgstr "" "요소 자료형은 하위요소 지정 함수(subscripting function) 없이 정의할 수 없음" -#: commands/typecmds.c:781 +#: commands/typecmds.c:785 #, c-format msgid "\"%s\" is not a valid base type for a domain" msgstr "\"%s\" 자료형은 도메인의 기반 자료형이 아닙니다" -#: commands/typecmds.c:879 +#: commands/typecmds.c:883 #, c-format msgid "multiple default expressions" msgstr "default 표현식 여러개 있음" -#: commands/typecmds.c:942 commands/typecmds.c:951 +#: commands/typecmds.c:946 commands/typecmds.c:955 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "NULL/NOT NULL 조건이 함께 있음" -#: commands/typecmds.c:967 +#: commands/typecmds.c:971 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "도메인용 체크 제약 조건에는 NO INHERIT 옵션을 사용할 수 없음" -#: commands/typecmds.c:976 commands/typecmds.c:2956 +#: commands/typecmds.c:980 commands/typecmds.c:2940 #, c-format msgid "unique constraints not possible for domains" msgstr "고유 제약 조건은 도메인 정의에 사용할 수 없음" -#: commands/typecmds.c:982 commands/typecmds.c:2962 +#: commands/typecmds.c:986 commands/typecmds.c:2946 #, c-format msgid "primary key constraints not possible for domains" msgstr "기본키 제약 조건을 도메인 정의에 사용할 수 없음" -#: commands/typecmds.c:988 commands/typecmds.c:2968 +#: commands/typecmds.c:992 commands/typecmds.c:2952 #, c-format msgid "exclusion constraints not possible for domains" msgstr "exclusion 제약 조건은 도메인에는 사용할 수 없음" -#: commands/typecmds.c:994 commands/typecmds.c:2974 +#: commands/typecmds.c:998 commands/typecmds.c:2958 #, c-format msgid "foreign key constraints not possible for domains" msgstr "참조키(foreign key) 제약 조건은 도메인(domain) 정의에 사용할 수 없음" -#: commands/typecmds.c:1003 commands/typecmds.c:2983 +#: commands/typecmds.c:1007 commands/typecmds.c:2967 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "도메인에 대해 제약 조건 지연을 지정할 수 없음" -#: commands/typecmds.c:1317 utils/cache/typcache.c:2561 +#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 #, c-format msgid "%s is not an enum" msgstr "%s 개체는 나열형이 아님" -#: commands/typecmds.c:1458 +#: commands/typecmds.c:1468 #, c-format msgid "type attribute \"subtype\" is required" msgstr "\"subtype\" 속성이 필요함" -#: commands/typecmds.c:1463 +#: commands/typecmds.c:1473 #, c-format msgid "range subtype cannot be %s" msgstr "range subtype은 %s 아니여야 함" -#: commands/typecmds.c:1482 +#: commands/typecmds.c:1492 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "" "range 형에 정렬 규칙을 지정했지만, 소속 자료형이 그 정렬 규칙을 지원하지 않습" "니다" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1502 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "미리 만들어진 쉘 타입 없는 canonical 함수를 지정할 수 없음" -#: commands/typecmds.c:1493 +#: commands/typecmds.c:1503 #, c-format msgid "" "Create the type as a shell type, then create its canonicalization function, " @@ -13116,92 +13621,92 @@ msgstr "" "먼저 쉘 타입 자료형을 만들고, canonical 함수를 만든 다음 CREATE TYPE 명령으" "로 해당 자료형을 만드세요." -#: commands/typecmds.c:1965 +#: commands/typecmds.c:1975 #, c-format msgid "type input function %s has multiple matches" msgstr "자료형 %s 입력 함수가 여러 개 있습니다" -#: commands/typecmds.c:1983 +#: commands/typecmds.c:1993 #, c-format msgid "type input function %s must return type %s" msgstr "자료형 %s 입력 함수의 %s 자료형을 반환해야 합니다" -#: commands/typecmds.c:1999 +#: commands/typecmds.c:2009 #, c-format msgid "type input function %s should not be volatile" msgstr "%s 자료형 입력 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2027 +#: commands/typecmds.c:2037 #, c-format msgid "type output function %s must return type %s" msgstr "%s 자료형 출력 함수는 %s 자료형을 반환해야 합니다" -#: commands/typecmds.c:2034 +#: commands/typecmds.c:2044 #, c-format msgid "type output function %s should not be volatile" msgstr "%s 자료형 출력 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2063 +#: commands/typecmds.c:2073 #, c-format msgid "type receive function %s has multiple matches" msgstr "%s 자료형 receive 함수가 여러 개 있습니다" -#: commands/typecmds.c:2081 +#: commands/typecmds.c:2091 #, c-format msgid "type receive function %s must return type %s" msgstr "%s 자료형 receive 함수는 %s 자료형을 반환해야 합니다" -#: commands/typecmds.c:2088 +#: commands/typecmds.c:2098 #, c-format msgid "type receive function %s should not be volatile" msgstr "%s 자료형 수신 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2116 +#: commands/typecmds.c:2126 #, c-format msgid "type send function %s must return type %s" msgstr "%s 자료형 전송 함수는 %s 자료형을 반환해야 합니다" -#: commands/typecmds.c:2123 +#: commands/typecmds.c:2133 #, c-format msgid "type send function %s should not be volatile" msgstr "%s 자료형 송신 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2150 +#: commands/typecmds.c:2160 #, c-format msgid "typmod_in function %s must return type %s" msgstr "%s typmod_in 함수는 %s 자료형을 반환해야 함" -#: commands/typecmds.c:2157 +#: commands/typecmds.c:2167 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "%s 자료형 형변환 입력 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2184 +#: commands/typecmds.c:2194 #, c-format msgid "typmod_out function %s must return type %s" msgstr "%s typmod_out 함수는 %s 자료형을 반환해야 함" -#: commands/typecmds.c:2191 +#: commands/typecmds.c:2201 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "%s 자료형 형변환 출력 함수는 volatile 특성이 없어야 합니다" -#: commands/typecmds.c:2218 +#: commands/typecmds.c:2228 #, c-format msgid "type analyze function %s must return type %s" msgstr "%s 자료형 분석 함수는 %s 자료형을 반환해야 함" -#: commands/typecmds.c:2247 +#: commands/typecmds.c:2257 #, c-format msgid "type subscripting function %s must return type %s" msgstr "%s subscripting 함수의 반환값 자료형은 %s 형이어야 함" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2267 #, c-format msgid "user-defined types cannot use subscripting function %s" msgstr "사용자 정의 자료형은 %s subscripting 함수에서 쓸 수 없음" -#: commands/typecmds.c:2303 +#: commands/typecmds.c:2313 #, c-format msgid "" "You must specify an operator class for the range type or define a default " @@ -13210,64 +13715,64 @@ msgstr "" "subtype을 위한 기본 연산자 클래스나 range 자료형을 위한 하나의 연산자 클래스" "를 지정해야 합니다" -#: commands/typecmds.c:2334 +#: commands/typecmds.c:2344 #, c-format msgid "range canonical function %s must return range type" msgstr "%s 범위 기준 함수는 range 자료형을 반환해야 합니다" -#: commands/typecmds.c:2340 +#: commands/typecmds.c:2350 #, c-format msgid "range canonical function %s must be immutable" msgstr "%s 범위 기준 함수는 immutable 속성이어야 합니다" -#: commands/typecmds.c:2376 +#: commands/typecmds.c:2386 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "%s 범위 하위 자료 비교 함수는 %s 자료형을 반환해야 합니다" -#: commands/typecmds.c:2383 +#: commands/typecmds.c:2393 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "%s 범위 하위 자료 비교 함수는 immutable 속성이어야 합니다" -#: commands/typecmds.c:2410 +#: commands/typecmds.c:2420 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때 pg_type 배열 OID 값이 지정되지 않았습니다" -#: commands/typecmds.c:2443 +#: commands/typecmds.c:2453 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "" "이진 업그레이드 작업 때 pg_type multirange OID 값이 지정되지 않았습니다" -#: commands/typecmds.c:2476 +#: commands/typecmds.c:2486 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" msgstr "" "이진 업그레이드 작업 때 pg_type multirange 배열 OID 값이 지정되지 않았습니다" -#: commands/typecmds.c:2772 -#, c-format -msgid "column \"%s\" of table \"%s\" contains null values" -msgstr "\"%s\" 열(해당 테이블 \"%s\")의 자료 가운데 null 값이 있습니다" - -#: commands/typecmds.c:2885 commands/typecmds.c:3086 +#: commands/typecmds.c:2868 commands/typecmds.c:3093 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "\"%s\" 제약 조건 \"%s\" 도메인에 포함되어 있지 않습니다." -#: commands/typecmds.c:2889 +#: commands/typecmds.c:2872 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "\"%s\" 제약 조건 \"%s\" 도메인에 포함되어 있지 않음, 건너뜀" -#: commands/typecmds.c:3093 +#: commands/typecmds.c:3100 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "\"%s\" 제약 조건(해당 도메인: \"%s\")은 check 제약조건이 아님" -#: commands/typecmds.c:3194 +#: commands/typecmds.c:3180 +#, c-format +msgid "column \"%s\" of table \"%s\" contains null values" +msgstr "\"%s\" 열(해당 테이블 \"%s\")의 자료 가운데 null 값이 있습니다" + +#: commands/typecmds.c:3269 #, c-format msgid "" "column \"%s\" of table \"%s\" contains values that violate the new constraint" @@ -13275,140 +13780,147 @@ msgstr "" "\"%s\" 열(해당 테이블 \"%s\")의 자료 중에, 새 제약 조건을 위반하는 자료가 있" "습니다" -#: commands/typecmds.c:3423 commands/typecmds.c:3622 commands/typecmds.c:3703 -#: commands/typecmds.c:3889 +#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 +#: commands/typecmds.c:4073 #, c-format msgid "%s is not a domain" msgstr "\"%s\" 이름의 개체는 도메인이 아닙니다" -#: commands/typecmds.c:3455 +#: commands/typecmds.c:3532 commands/typecmds.c:3686 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "\"%s\" 제약 조건이 \"%s\" 도메인에 이미 지정되어 있습니다" -#: commands/typecmds.c:3506 +#: commands/typecmds.c:3583 #, c-format msgid "cannot use table references in domain check constraint" msgstr "도메인 용 체크 제약 조건에서는 테이블 참조를 사용할 수 없습니다" -#: commands/typecmds.c:3634 commands/typecmds.c:3715 commands/typecmds.c:4006 +#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 #, c-format msgid "%s is a table's row type" msgstr "%s 자료형은 테이블의 행 자료형(row type)입니다" -#: commands/typecmds.c:3636 commands/typecmds.c:3717 commands/typecmds.c:4008 -#, c-format -msgid "Use ALTER TABLE instead." -msgstr "대신 ALTER TABLE을 사용하십시오." - -#: commands/typecmds.c:3642 commands/typecmds.c:3723 commands/typecmds.c:3921 +#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 #, c-format msgid "cannot alter array type %s" -msgstr "%s 배열 형식을 변경할 수 없음" +msgstr "%s 배열 자료형을 바꿀 수 없음" -#: commands/typecmds.c:3644 commands/typecmds.c:3725 commands/typecmds.c:3923 +#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 #, c-format msgid "You can alter type %s, which will alter the array type as well." -msgstr "%s 형식을 변경할 수 있으며, 이렇게 하면 배열 형식도 변경됩니다." +msgstr "" +"%s 자료형을 바꿀 수 있으며, 이렇게 하면 해당 자료형 배열의 자료형도 변경됩니" +"다." -#: commands/typecmds.c:3991 +#: commands/typecmds.c:3892 +#, c-format +msgid "cannot alter multirange type %s" +msgstr "%s 다중 범위 자료형은 바꿀 수 없음" + +#: commands/typecmds.c:3895 +#, c-format +msgid "You can alter type %s, which will alter the multirange type as well." +msgstr "%s 자료형을 바꿀 수 있으며, 이렇게 하면 다중 범위 자료형도 변경됩니다." + +#: commands/typecmds.c:4202 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "%s 자료형이 이미 \"%s\" 스키마 안에 있습니다" -#: commands/typecmds.c:4159 +#: commands/typecmds.c:4382 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "저장 옵션을 PLAIN으로 바꿀 수 없음" -#: commands/typecmds.c:4252 +#: commands/typecmds.c:4475 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "\"%s\" 자료형 속성 바꿀 수 없음" -#: commands/typecmds.c:4270 +#: commands/typecmds.c:4493 #, c-format msgid "must be superuser to alter a type" msgstr "슈퍼유저만 자료형 속성을 바꿀 수 있음" -#: commands/typecmds.c:4291 commands/typecmds.c:4300 +#: commands/typecmds.c:4514 commands/typecmds.c:4523 #, c-format msgid "%s is not a base type" msgstr "\"%s\" 개체는 기본 자료형이 아님" -#: commands/user.c:201 +#: commands/user.c:200 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSID는 더 이상 지정할 수 없음" -#: commands/user.c:319 commands/user.c:325 commands/user.c:331 -#: commands/user.c:337 commands/user.c:343 +#: commands/user.c:318 commands/user.c:324 commands/user.c:330 +#: commands/user.c:336 commands/user.c:342 #, c-format msgid "permission denied to create role" msgstr "롤 만들 권한 없음" -#: commands/user.c:320 +#: commands/user.c:319 #, c-format msgid "Only roles with the %s attribute may create roles." msgstr "%s 속성을 가지고 있는 롤만이 롤을 만들 수 있습니다." -#: commands/user.c:326 commands/user.c:332 commands/user.c:338 -#: commands/user.c:344 +#: commands/user.c:325 commands/user.c:331 commands/user.c:337 +#: commands/user.c:343 #, c-format msgid "" "Only roles with the %s attribute may create roles with the %s attribute." msgstr "%s 속성을 가지고 있는 롤만 %s 속성을 가진 롤을 만들 수 있습니다." -#: commands/user.c:355 commands/user.c:1393 commands/user.c:1400 -#: utils/adt/acl.c:5401 utils/adt/acl.c:5407 gram.y:16726 gram.y:16772 +#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 +#: utils/adt/acl.c:5574 utils/adt/acl.c:5580 gram.y:17310 gram.y:17356 #, c-format msgid "role name \"%s\" is reserved" msgstr "\"%s\" 롤 이름은 내부적으로 사용되고 있습니다" -#: commands/user.c:357 commands/user.c:1395 commands/user.c:1402 +#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "\"pg_\"로 시작하는 롤 이름은 사용할 수 없습니다." -#: commands/user.c:378 commands/user.c:1417 +#: commands/user.c:377 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "\"%s\" 롤 이름이 이미 있습니다" -#: commands/user.c:440 commands/user.c:925 +#: commands/user.c:439 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "비밀번호로 빈 문자열을 사용할 수 없습니다. 비밀번호를 없앱니다" -#: commands/user.c:469 +#: commands/user.c:468 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때 pg_authid OID 값이 지정되지 않았습니다" -#: commands/user.c:653 commands/user.c:1011 +#: commands/user.c:652 commands/user.c:1010 msgid "Cannot alter reserved roles." msgstr "예약된 롤은 수정할 수 없습니다." -#: commands/user.c:760 commands/user.c:766 commands/user.c:782 -#: commands/user.c:790 commands/user.c:804 commands/user.c:810 -#: commands/user.c:816 commands/user.c:825 commands/user.c:870 -#: commands/user.c:1033 commands/user.c:1044 +#: commands/user.c:759 commands/user.c:765 commands/user.c:781 +#: commands/user.c:789 commands/user.c:803 commands/user.c:809 +#: commands/user.c:815 commands/user.c:824 commands/user.c:869 +#: commands/user.c:1032 commands/user.c:1043 #, c-format msgid "permission denied to alter role" msgstr "롤 변경 권한 없음" -#: commands/user.c:761 commands/user.c:1034 +#: commands/user.c:760 commands/user.c:1033 #, c-format msgid "Only roles with the %s attribute may alter roles with the %s attribute." msgstr "%s 속성이 있는 롤만 %s 속성을 가진 롤을 바꿀 수 있습니다." -#: commands/user.c:767 commands/user.c:805 commands/user.c:811 -#: commands/user.c:817 +#: commands/user.c:766 commands/user.c:804 commands/user.c:810 +#: commands/user.c:816 #, c-format msgid "Only roles with the %s attribute may change the %s attribute." msgstr "%s 속성이 있는 롤만 %s 속성을 바꿀 수 있습니다." -#: commands/user.c:783 commands/user.c:1045 +#: commands/user.c:782 commands/user.c:1044 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may alter " @@ -13416,7 +13928,7 @@ msgid "" msgstr "" "%s 속성과 %s 옵션을 지정한 롤(해당 롤: \"%s\")만 이 롤을 수정할 수 있습니다." -#: commands/user.c:791 +#: commands/user.c:790 #, c-format msgid "" "To change another role's password, the current user must have the %s " @@ -13425,32 +13937,32 @@ msgstr "" "다른 롤의 비밀번호를 바꾸려면, 현재 사용자는 %s 속성과 %s 옵션이 지정된 롤이" "어야 합니다." -#: commands/user.c:826 +#: commands/user.c:825 #, c-format -msgid "Only roles with the %s option on role \"%s\" may add members." +msgid "Only roles with the %s option on role \"%s\" may add or drop members." msgstr "%s 옵션 (해당 롤: \"%s\")이 있는 롤만 구성원을 추가할 수 있습니다." -#: commands/user.c:871 +#: commands/user.c:870 #, c-format -msgid "The bootstrap user must have the %s attribute." -msgstr "부트스트랩 사용자는 %s 속성을 가지고 있어야 합니다." +msgid "The bootstrap superuser must have the %s attribute." +msgstr "부트스트랩 슈퍼유저는 %s 속성을 가지고 있어야 합니다." -#: commands/user.c:1076 +#: commands/user.c:1075 #, c-format msgid "permission denied to alter setting" msgstr "설정 변경 권한 없음" -#: commands/user.c:1077 +#: commands/user.c:1076 #, c-format msgid "Only roles with the %s attribute may alter settings globally." msgstr "%s 속성이 부여된 롤만 전역 환경 설정을 바꿀 수 있습니다." -#: commands/user.c:1101 commands/user.c:1173 commands/user.c:1179 +#: commands/user.c:1100 commands/user.c:1171 commands/user.c:1177 #, c-format msgid "permission denied to drop role" msgstr "롤을 삭제할 권한이 없습니다" -#: commands/user.c:1102 +#: commands/user.c:1101 #, c-format msgid "" "Only roles with the %s attribute and the %s option on the target roles may " @@ -13459,41 +13971,41 @@ msgstr "" "작업 롤은 %s 속성이 있어야하고, 삭제할 대상 롤을 %s 옵션이 있는 경우만 롤을 " "삭제 할 수 있음" -#: commands/user.c:1127 +#: commands/user.c:1125 #, c-format msgid "cannot use special role specifier in DROP ROLE" msgstr "DROP ROLE 명령으로 삭제할 수 없는 특별한 롤입니다" -#: commands/user.c:1137 commands/user.c:1364 commands/variable.c:836 -#: commands/variable.c:839 commands/variable.c:923 commands/variable.c:926 -#: utils/adt/acl.c:356 utils/adt/acl.c:376 utils/adt/acl.c:5256 -#: utils/adt/acl.c:5304 utils/adt/acl.c:5332 utils/adt/acl.c:5351 -#: utils/adt/regproc.c:1551 utils/init/miscinit.c:757 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:851 +#: commands/variable.c:854 commands/variable.c:971 commands/variable.c:974 +#: utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5429 +#: utils/adt/acl.c:5477 utils/adt/acl.c:5505 utils/adt/acl.c:5524 +#: utils/adt/regproc.c:1571 utils/init/miscinit.c:799 #, c-format msgid "role \"%s\" does not exist" msgstr "\"%s\" 롤(role) 없음" -#: commands/user.c:1142 +#: commands/user.c:1140 #, c-format msgid "role \"%s\" does not exist, skipping" msgstr "\"%s\" 룰(rule) 없음, 건너 뜀" -#: commands/user.c:1155 commands/user.c:1159 +#: commands/user.c:1153 commands/user.c:1157 #, c-format msgid "current user cannot be dropped" msgstr "현재 사용자는 삭제 될 수 없습니다" -#: commands/user.c:1163 +#: commands/user.c:1161 #, c-format msgid "session user cannot be dropped" msgstr "세션 사용자는 삭제 될 수 없습니다" -#: commands/user.c:1174 +#: commands/user.c:1172 #, c-format msgid "Only roles with the %s attribute may drop roles with the %s attribute." msgstr "%s 속성이 있는 롤만 %s 속성을 가진 롤을 지울 수 있습니다." -#: commands/user.c:1180 +#: commands/user.c:1178 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may drop " @@ -13501,33 +14013,33 @@ msgid "" msgstr "" "%s 속성과 %s 옵션을 지정한 롤(해당 롤: \"%s\")만 이 롤을 지울 수 있습니다." -#: commands/user.c:1306 +#: commands/user.c:1299 #, c-format msgid "role \"%s\" cannot be dropped because some objects depend on it" msgstr "기타 다른 개체들이 이 롤에 의존하고 있어, \"%s\" 롤을 삭제할 수 없음" -#: commands/user.c:1380 +#: commands/user.c:1373 #, c-format msgid "session user cannot be renamed" msgstr "세션 사용자의 이름은 바꿀 수 없습니다" -#: commands/user.c:1384 +#: commands/user.c:1377 #, c-format msgid "current user cannot be renamed" msgstr "현재 사용자의 이름은 바꿀 수 없습니다" -#: commands/user.c:1428 commands/user.c:1438 +#: commands/user.c:1421 commands/user.c:1431 #, c-format msgid "permission denied to rename role" msgstr "롤 이름 바꾸기 권한 없음" -#: commands/user.c:1429 +#: commands/user.c:1422 #, c-format msgid "" "Only roles with the %s attribute may rename roles with the %s attribute." msgstr "%s 속성을 가지고 있는 롤만 %s 속성을 가진 롤 이름을 바꿀 수 있습니다." -#: commands/user.c:1439 +#: commands/user.c:1432 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may rename " @@ -13535,137 +14047,137 @@ msgid "" msgstr "" "%s 속성과 %s 옵션을 가진 롤(해당 롤: \"%s\")만 이 롤 이름을 바꿀 수 있습니다." -#: commands/user.c:1461 +#: commands/user.c:1454 #, c-format msgid "MD5 password cleared because of role rename" msgstr "롤 이름이 변경 되어 MD5 암호를 지웠습니다" -#: commands/user.c:1525 gram.y:1260 +#: commands/user.c:1518 gram.y:1294 #, c-format msgid "unrecognized role option \"%s\"" msgstr "인식할 수 없는 롤 옵션 \"%s\"" -#: commands/user.c:1530 +#: commands/user.c:1523 #, c-format msgid "unrecognized value for role option \"%s\": \"%s\"" msgstr "\"%s\" 롤 옵션에서 쓸 수 없는 값: \"%s\"" -#: commands/user.c:1563 +#: commands/user.c:1556 #, c-format msgid "column names cannot be included in GRANT/REVOKE ROLE" msgstr "GRANT/REVOKE ROLE에 열 이름을 포함할 수 없음" -#: commands/user.c:1603 +#: commands/user.c:1596 #, c-format msgid "permission denied to drop objects" msgstr "개체를 삭제할 권한이 없음" -#: commands/user.c:1604 +#: commands/user.c:1597 #, c-format msgid "Only roles with privileges of role \"%s\" may drop objects owned by it." msgstr "\"%s\" 롤의 권한을 가진 롤만 해당 객체를 삭제할 수 있습니다." -#: commands/user.c:1632 commands/user.c:1643 +#: commands/user.c:1625 commands/user.c:1636 #, c-format msgid "permission denied to reassign objects" msgstr "개체 권한을 재 지정할 권한이 없음" -#: commands/user.c:1633 +#: commands/user.c:1626 #, c-format msgid "" "Only roles with privileges of role \"%s\" may reassign objects owned by it." msgstr "\"%s\" 롤의 권한을 가진 롤만 해당 객체의 소유주를 바꿀 수 있습니다." -#: commands/user.c:1644 +#: commands/user.c:1637 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects to it." msgstr "\"%s\" 롤의 권한을 가진 롤만 해당 객체를 다시 지정 할 수 있습니다." -#: commands/user.c:1740 +#: commands/user.c:1733 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "\"%s\" 롤은 다른 롤의 맴버가 될 수 없음" -#: commands/user.c:1753 +#: commands/user.c:1746 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "\"%s\" 롤은 \"%s\" 롤의 구성원입니다" -#: commands/user.c:1793 commands/user.c:1819 +#: commands/user.c:1786 commands/user.c:1812 #, c-format msgid "%s option cannot be granted back to your own grantor" msgstr "%s 옵션은 이 롤에 권한 부여한 롤에게 다시 부여될 수 없습니다." -#: commands/user.c:1896 +#: commands/user.c:1889 #, c-format msgid "" "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" msgstr "\"%s\" 롤은 \"%s\"롤의 구성원입니다, 해당 작업 롤: \"%s\"" -#: commands/user.c:2031 +#: commands/user.c:2024 #, c-format msgid "" "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" msgstr "\"%s\" 롤은 \"%s\"롤의 구성원이 아닙니다, 해당 작업 롤: \"%s\"" -#: commands/user.c:2131 +#: commands/user.c:2124 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "\"%s\" 롤은 명시적 맴버를 가질 수 없음" -#: commands/user.c:2142 commands/user.c:2165 +#: commands/user.c:2135 commands/user.c:2158 #, c-format msgid "permission denied to grant role \"%s\"" msgstr "\"%s\" 롤 권한을 지정할 수 없음" -#: commands/user.c:2144 +#: commands/user.c:2137 #, c-format msgid "Only roles with the %s attribute may grant roles with the %s attribute." msgstr "%s 속성이 있는 롤만 %s 속성 권한을 부여할 수 있음." -#: commands/user.c:2149 commands/user.c:2172 +#: commands/user.c:2142 commands/user.c:2165 #, c-format msgid "permission denied to revoke role \"%s\"" msgstr "\"%s\" 롤 권한 회수할 수 없음" -#: commands/user.c:2151 +#: commands/user.c:2144 #, c-format msgid "" "Only roles with the %s attribute may revoke roles with the %s attribute." msgstr "%s 속성이 있는 롤만이 %s 속성 권한을 회수할 수 있음." -#: commands/user.c:2167 +#: commands/user.c:2160 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." msgstr "%s 옵션을 롤(해당 롤: \"%s\")만이 이 롤 권한을 부여할 수 있음." -#: commands/user.c:2174 +#: commands/user.c:2167 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." msgstr "%s 옵션을 롤(해당 롤: \"%s\")만이 이 롤 권한을 회수할 수 있음." -#: commands/user.c:2254 commands/user.c:2263 +#: commands/user.c:2247 commands/user.c:2256 #, c-format msgid "permission denied to grant privileges as role \"%s\"" msgstr "\"%s\" 롤 권한을 부여할 수 없음" -#: commands/user.c:2256 +#: commands/user.c:2249 #, c-format msgid "" "Only roles with privileges of role \"%s\" may grant privileges as this role." msgstr "\"%s\" 롤 권한이 있는 롤만이 이 롤 권한을 부여할 수 있음." -#: commands/user.c:2265 +#: commands/user.c:2258 #, c-format msgid "The grantor must have the %s option on role \"%s\"." msgstr "권한 부여자는 %s 옵션(해당 롤: \"%s\")이 있어야 함" -#: commands/user.c:2273 +#: commands/user.c:2266 #, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" msgstr "\"%s\" 롤이 부여한 권한을 회수 할 수 있는 권한 없음" -#: commands/user.c:2275 +#: commands/user.c:2268 #, c-format msgid "" "Only roles with privileges of role \"%s\" may revoke privileges granted by " @@ -13673,17 +14185,17 @@ msgid "" msgstr "" "\"%s\" 롤 권한이 있는 롤만이 이 롤에 의해 부여한 권한을 회수할 수 있음." -#: commands/user.c:2498 utils/adt/acl.c:1309 +#: commands/user.c:2491 utils/adt/acl.c:1324 #, c-format msgid "dependent privileges exist" msgstr "의존적인 권한이 존재합니다" -#: commands/user.c:2499 utils/adt/acl.c:1310 +#: commands/user.c:2492 utils/adt/acl.c:1325 #, c-format msgid "Use CASCADE to revoke them too." msgstr "그것들을 취소하려면 \"CASCADE\"를 사용하세요." -#: commands/vacuum.c:137 +#: commands/vacuum.c:134 #, c-format msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" msgstr "" @@ -13757,42 +14269,42 @@ msgstr "" msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%s 명령은 VACUUM, ANALYZE 명령에서 실행 될 수 없음" -#: commands/vacuum.c:733 +#: commands/vacuum.c:730 #, c-format msgid "permission denied to vacuum \"%s\", skipping it" msgstr "\"%s\" 청소할 접근 권한 없음, 건너 뜀" -#: commands/vacuum.c:746 +#: commands/vacuum.c:743 #, c-format msgid "permission denied to analyze \"%s\", skipping it" msgstr "\"%s\" 통계정보 수집할 권한 없음, 건너 뜀" -#: commands/vacuum.c:824 commands/vacuum.c:921 +#: commands/vacuum.c:821 commands/vacuum.c:918 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" msgstr "\"%s\" 개체 vacuum 건너뜀 --- 사용 가능한 잠금이 없음" -#: commands/vacuum.c:829 +#: commands/vacuum.c:826 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "\"%s\" 개체 vacuum 건너뜀 --- 해당 릴레이션 없음" -#: commands/vacuum.c:845 commands/vacuum.c:926 +#: commands/vacuum.c:842 commands/vacuum.c:923 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" msgstr "\"%s\" 분석 건너뜀 --- 잠글 수 없음" -#: commands/vacuum.c:850 +#: commands/vacuum.c:847 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "\"%s\" 분석 건너뜀 --- 릴레이션어 없음" -#: commands/vacuum.c:1161 +#: commands/vacuum.c:1139 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" msgstr "튜플을 지우고, 얼려버려기 위한 시작점이 너무 옛날 시점입니다." -#: commands/vacuum.c:1162 commands/vacuum.c:1167 +#: commands/vacuum.c:1140 commands/vacuum.c:1145 #, c-format msgid "" "Close open transactions soon to avoid wraparound problems.\n" @@ -13805,41 +14317,41 @@ msgstr "" "합니다." # # search5 부분 -#: commands/vacuum.c:1166 +#: commands/vacuum.c:1144 #, c-format msgid "cutoff for freezing multixacts is far in the past" msgstr "영구 보관 처리할 multixact 값이 너무 옛날 것입니다." -#: commands/vacuum.c:1908 +#: commands/vacuum.c:1900 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "" "몇몇 데이터베이스가 20억 이상의 트랜잭션을 처리했음에도 불구하고 청소가되지 " "않았습니다" -#: commands/vacuum.c:1909 +#: commands/vacuum.c:1901 #, c-format msgid "You might have already suffered transaction-wraparound data loss." msgstr "이미 트래잭션 ID 겹침 현상으로 자료 손실이 발생했을 수도 있습니다." -#: commands/vacuum.c:2078 +#: commands/vacuum.c:2080 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "" "\"%s\" 건너뜀 --- 테이블이 아닌 것 또는 특별 시스템 테이블 등은 청소할 수 없" "음" -#: commands/vacuum.c:2503 +#: commands/vacuum.c:2512 #, c-format -msgid "scanned index \"%s\" to remove %d row versions" -msgstr "\"%s\" 인덱스를 스캔해서 %d개의 행 버전들을 지웠습니다" +msgid "scanned index \"%s\" to remove %lld row versions" +msgstr "\"%s\" 인덱스를 스캔해서 %lld개의 행 버전을 지웠음" -#: commands/vacuum.c:2522 +#: commands/vacuum.c:2531 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "\"%s\" 인덱스는 %.0f 행 버전을 %u 페이지에서 포함하고 있습니다." -#: commands/vacuum.c:2526 +#: commands/vacuum.c:2535 #, c-format msgid "" "%.0f index row versions were removed.\n" @@ -13850,14 +14362,14 @@ msgstr "" "%u개 인덱스 페이지를 새롭게 삭제했습니다.\n" "%u개 인덱스 페이지를 현재 삭제해서, %u개 페이지를 다시 사용합니다." -#: commands/vacuumparallel.c:677 +#: commands/vacuumparallel.c:707 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "" "launched %d parallel vacuum workers for index vacuuming (planned: %d)" msgstr[0] "인덱스 청소를 위해 %d 개의 병렬 청소 작업자가 실행됨 (예상값: %d)" -#: commands/vacuumparallel.c:683 +#: commands/vacuumparallel.c:713 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "" @@ -13920,7 +14432,7 @@ msgstr "쿼리보다 먼저 SET TRANSACTION ISOLATION LEVEL을 호출해야 함" msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "하위 트랜잭션에서 SET TRANSACTION ISOLATION LEVEL을 호출하지 않아야 함" -#: commands/variable.c:606 storage/lmgr/predicate.c:1629 +#: commands/variable.c:606 storage/lmgr/predicate.c:1685 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "읽기 전용 보조 서버 상태에서는 serializable 모드를 사용할 수 없음" @@ -13954,63 +14466,73 @@ msgstr "\"client_encoding\" 값을 지금은 바꿀 수 없음" #: commands/variable.c:781 #, c-format -msgid "cannot change client_encoding during a parallel operation" -msgstr "병렬 작업 중에는 client_encoding 설정을 할 수 없음" +msgid "cannot change \"client_encoding\" during a parallel operation" +msgstr "병렬 작업 중에는 \"client_encoding\" 설정을 할 수 없음" + +#: commands/variable.c:876 +#, c-format +msgid "permission will be denied to set session authorization \"%s\"" +msgstr "set session authorization \"%s\" 작업 권한 거부될 것임" + +#: commands/variable.c:881 +#, c-format +msgid "permission denied to set session authorization \"%s\"" +msgstr "set session authorization \"%s\" 작업 권한 없음" -#: commands/variable.c:948 +#: commands/variable.c:991 #, c-format msgid "permission will be denied to set role \"%s\"" -msgstr "권한이 \"%s\" 롤 권한 지정을 거부할 것입니다" +msgstr "set role \"%s\" 작업 권한 거부될 것임" -#: commands/variable.c:953 +#: commands/variable.c:996 #, c-format msgid "permission denied to set role \"%s\"" -msgstr "\"%s\" 롤 권한을 지정할 수 없음" +msgstr "set role \"%s\" 작업 권한 없음" -#: commands/variable.c:1153 +#: commands/variable.c:1200 #, c-format msgid "Bonjour is not supported by this build" msgstr "Bonjour 기능을 뺀 채로 서버가 만들어졌습니다." -#: commands/variable.c:1181 +#: commands/variable.c:1228 #, c-format msgid "" -"effective_io_concurrency must be set to 0 on platforms that lack " +"\"effective_io_concurrency\" must be set to 0 on platforms that lack " "posix_fadvise()." msgstr "" -"posix_fadvise() 함수에 문제가 있는 플랫폼에서는 effective_io_concurrency 설정" -"값이 0 이어야 합니다." +"posix_fadvise() 함수에 문제가 있는 플랫폼에서는 \"effective_io_concurrency\" " +"설정값이 0 이어야 합니다." -#: commands/variable.c:1194 +#: commands/variable.c:1241 #, c-format msgid "" -"maintenance_io_concurrency must be set to 0 on platforms that lack " +"\"maintenance_io_concurrency\" must be set to 0 on platforms that lack " "posix_fadvise()." msgstr "" -"posix_fadvise() 함수에 문제가 있는 플랫폼에서는 maintenance_io_concurrency 설" -"정값이 0 이어야 합니다." +"posix_fadvise() 함수에 문제가 있는 플랫폼에서는 " +"\"maintenance_io_concurrency\" 설정값이 0 이어야 합니다." -#: commands/variable.c:1207 +#: commands/variable.c:1254 #, c-format msgid "SSL is not supported by this build" msgstr "SSL 접속 기능을 뺀 채로 서버가 만들어졌습니다." -#: commands/view.c:84 +#: commands/view.c:79 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "\"%s\" 칼럼 자료 처리를 위한 정렬 규칙을 결정할 수 없음" -#: commands/view.c:279 commands/view.c:290 +#: commands/view.c:274 commands/view.c:285 #, c-format msgid "cannot drop columns from view" msgstr "뷰에서 칼럼을 삭제할 수 없음" -#: commands/view.c:295 +#: commands/view.c:290 #, c-format msgid "cannot change name of view column \"%s\" to \"%s\"" msgstr "뷰에서 \"%s\" 칼럼 이름을 \"%s\"(으)로 바꿀 수 없음" -#: commands/view.c:298 +#: commands/view.c:293 #, c-format msgid "" "Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead." @@ -14018,40 +14540,40 @@ msgstr "" "대신에 ALTER VIEW ... RENAME COLUMN ... 구문을 이용해서 뷰 칼럼 이름을 바꾸" "세요." -#: commands/view.c:309 +#: commands/view.c:304 #, c-format msgid "cannot change data type of view column \"%s\" from %s to %s" msgstr "뷰에서 \"%s\" 칼럼 자료형을을 %s에서 %s(으)로 바꿀 수 없음" -#: commands/view.c:323 +#: commands/view.c:318 #, c-format msgid "cannot change collation of view column \"%s\" from \"%s\" to \"%s\"" msgstr "" "뷰에서 \"%s\" 칼럼 자료형의 문자 정렬 규칙을 \"%s\"에서 \"%s\"(으)로 바꿀 수 " "없음" -#: commands/view.c:392 +#: commands/view.c:387 #, c-format msgid "views must not contain SELECT INTO" msgstr "뷰에는 SELECT INTO 구문을 포함할 수 없음" -#: commands/view.c:404 +#: commands/view.c:399 #, c-format msgid "views must not contain data-modifying statements in WITH" msgstr "뷰로 사용될 쿼리의 WITH 절에는 자료 변경 구문이 있으면 안됩니다." -#: commands/view.c:474 +#: commands/view.c:469 #, c-format msgid "CREATE VIEW specifies more column names than columns" msgstr "CREATE VIEW 는 columns 보다는 좀더 많은 열 이름을 명시해야 한다" -#: commands/view.c:482 +#: commands/view.c:477 #, c-format msgid "views cannot be unlogged because they do not have storage" msgstr "" "뷰는 저장 공간을 사용하지 않기 때문에 unlogged 속성을 지정할 수 없습니다." -#: commands/view.c:496 +#: commands/view.c:491 #, c-format msgid "view \"%s\" will be a temporary view" msgstr "\"%s\" 뷰는 임시적인 뷰로 만들어집니다" @@ -14089,121 +14611,121 @@ msgstr "\"%s\" 커서가 로우에 놓여 있지 않음" msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "\"%s\" 커서는 \"%s\" 테이블의 단순 업데이트 가능한 스캔이 아님" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2498 +#: executor/execCurrent.c:280 executor/execExprInterp.c:2555 #, c-format msgid "" "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "" "%d번째 매개 변수의 자료형(%s)이 미리 준비된 실행계획의 자료형(%s)과 다릅니다" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2510 +#: executor/execCurrent.c:292 executor/execExprInterp.c:2567 #, c-format msgid "no value found for parameter %d" msgstr "%d번째 매개 변수 값이 없습니다" -#: executor/execExpr.c:637 executor/execExpr.c:644 executor/execExpr.c:650 -#: executor/execExprInterp.c:4234 executor/execExprInterp.c:4251 -#: executor/execExprInterp.c:4350 executor/nodeModifyTable.c:197 -#: executor/nodeModifyTable.c:208 executor/nodeModifyTable.c:225 -#: executor/nodeModifyTable.c:233 +#: executor/execExpr.c:642 executor/execExpr.c:649 executor/execExpr.c:655 +#: executor/execExprInterp.c:4852 executor/execExprInterp.c:4869 +#: executor/execExprInterp.c:4968 executor/nodeModifyTable.c:203 +#: executor/nodeModifyTable.c:214 executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:239 #, c-format msgid "table row type and query-specified row type do not match" msgstr "테이블 행 형식과 쿼리 지정 행 형식이 일치하지 않음" -#: executor/execExpr.c:638 executor/nodeModifyTable.c:198 +#: executor/execExpr.c:643 executor/nodeModifyTable.c:204 #, c-format msgid "Query has too many columns." msgstr "쿼리에 칼럼이 너무 많습니다." -#: executor/execExpr.c:645 executor/nodeModifyTable.c:226 +#: executor/execExpr.c:650 executor/nodeModifyTable.c:232 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "쿼리에서 서수 위치 %d에 있는 삭제된 칼럼의 값을 제공합니다." -#: executor/execExpr.c:651 executor/execExprInterp.c:4252 -#: executor/nodeModifyTable.c:209 +#: executor/execExpr.c:656 executor/execExprInterp.c:4870 +#: executor/nodeModifyTable.c:215 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "" "테이블에는 %s 형식이 있는데(서수 위치 %d) 쿼리에는 %s이(가) 필요합니다." -#: executor/execExpr.c:1099 parser/parse_agg.c:827 +#: executor/execExpr.c:1104 parser/parse_agg.c:838 #, c-format msgid "window function calls cannot be nested" msgstr "윈도우 함수 호출을 중첩할 수 없음" -#: executor/execExpr.c:1618 +#: executor/execExpr.c:1649 #, c-format msgid "target type is not an array" msgstr "대상 자료형이 배열이 아닙니다." -#: executor/execExpr.c:1958 +#: executor/execExpr.c:1989 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "ROW() 칼럼은 %s 자료형을 가집니다. %s 자료형 대신에" -#: executor/execExpr.c:2574 executor/execSRF.c:719 parser/parse_func.c:138 -#: parser/parse_func.c:655 parser/parse_func.c:1032 +#: executor/execExpr.c:2653 executor/execSRF.c:718 parser/parse_func.c:138 +#: parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" msgstr[0] "함수에 최대 %d개의 인자를 전달할 수 있음" -#: executor/execExpr.c:2601 executor/execSRF.c:739 executor/functions.c:1066 -#: utils/adt/jsonfuncs.c:3780 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2680 executor/execSRF.c:738 executor/functions.c:1068 +#: utils/adt/jsonfuncs.c:4054 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "" "set-values 함수(테이블 리턴 함수)가 set 정의 없이 사용되었습니다 (테이블과 해" "당 열 alias 지정하세요)" -#: executor/execExpr.c:3007 parser/parse_node.c:277 parser/parse_node.c:327 +#: executor/execExpr.c:3086 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "" "이 자료형은 subscript 형을 지원하지 않기 때문에, %s subscript 자료형을 사용" "할 수 없음" -#: executor/execExpr.c:3135 executor/execExpr.c:3157 +#: executor/execExpr.c:3214 executor/execExpr.c:3236 #, c-format msgid "type %s does not support subscripted assignment" msgstr "%s 자료형은 subscript 지정을 지원하지 않음" -#: executor/execExprInterp.c:1962 +#: executor/execExprInterp.c:2019 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "%d 번째 속성(대상 자료형 %s)이 삭제되었음" -#: executor/execExprInterp.c:1968 +#: executor/execExprInterp.c:2025 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "%d 번째 속성(대상 자료형 %s)의 자료형이 잘못되었음" -#: executor/execExprInterp.c:1970 executor/execExprInterp.c:3104 -#: executor/execExprInterp.c:3150 +#: executor/execExprInterp.c:2027 executor/execExprInterp.c:3226 +#: executor/execExprInterp.c:3272 #, c-format msgid "Table has type %s, but query expects %s." msgstr "테이블에는 %s 자료형이지만, 쿼리에서는 %s 자료형입니다." -#: executor/execExprInterp.c:2050 utils/adt/expandedrecord.c:99 -#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1743 -#: utils/cache/typcache.c:1902 utils/cache/typcache.c:2049 -#: utils/fmgr/funcapi.c:561 +#: executor/execExprInterp.c:2107 utils/adt/expandedrecord.c:99 +#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 +#: utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 +#: utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "%s 자료형은 복합 자료형이 아닙니다" -#: executor/execExprInterp.c:2588 +#: executor/execExprInterp.c:2710 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "WHERE CURRENT OF 구문은 이 테이블 형 대상으로 지원하지 않습니다." -#: executor/execExprInterp.c:2801 +#: executor/execExprInterp.c:2923 #, c-format msgid "cannot merge incompatible arrays" msgstr "배열 형태가 서로 틀려 병합할 수 없습니다" -#: executor/execExprInterp.c:2802 +#: executor/execExprInterp.c:2924 #, c-format msgid "" "Array with element type %s cannot be included in ARRAY construct with " @@ -14212,59 +14734,79 @@ msgstr "" "%s 자료형의 요소로 구성된 배열은 %s 자료형의 요소로 구성된 ARRAY 구문에 포함" "될 수 없습니다." -#: executor/execExprInterp.c:2823 utils/adt/arrayfuncs.c:265 -#: utils/adt/arrayfuncs.c:575 utils/adt/arrayfuncs.c:1329 -#: utils/adt/arrayfuncs.c:3483 utils/adt/arrayfuncs.c:5567 -#: utils/adt/arrayfuncs.c:6084 utils/adt/arraysubs.c:150 +#: executor/execExprInterp.c:2945 utils/adt/arrayfuncs.c:1305 +#: utils/adt/arrayfuncs.c:3503 utils/adt/arrayfuncs.c:5593 +#: utils/adt/arrayfuncs.c:6110 utils/adt/arraysubs.c:150 #: utils/adt/arraysubs.c:488 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "지정한 배열 크기(%d)가 최대치(%d)를 초과했습니다" -#: executor/execExprInterp.c:2843 executor/execExprInterp.c:2878 +#: executor/execExprInterp.c:2965 executor/execExprInterp.c:3000 #, c-format msgid "" "multidimensional arrays must have array expressions with matching dimensions" msgstr "다차원 배열에는 일치하는 차원이 포함된 배열 식이 있어야 함" -#: executor/execExprInterp.c:2855 utils/adt/array_expanded.c:274 -#: utils/adt/arrayfuncs.c:959 utils/adt/arrayfuncs.c:1568 -#: utils/adt/arrayfuncs.c:3285 utils/adt/arrayfuncs.c:3513 -#: utils/adt/arrayfuncs.c:6176 utils/adt/arrayfuncs.c:6517 -#: utils/adt/arrayutils.c:104 utils/adt/arrayutils.c:113 -#: utils/adt/arrayutils.c:120 +#: executor/execExprInterp.c:2977 utils/adt/array_expanded.c:274 +#: utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 +#: utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 +#: utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 +#: utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 +#: utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 +#: utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 +#: utils/adt/arrayfuncs.c:3533 utils/adt/arrayfuncs.c:5365 +#: utils/adt/arrayfuncs.c:6202 utils/adt/arrayfuncs.c:6546 +#: utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 +#: utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "배열 크기가 최대치 (%d)를 초과했습니다" -#: executor/execExprInterp.c:3103 executor/execExprInterp.c:3149 +#: executor/execExprInterp.c:3225 executor/execExprInterp.c:3271 #, c-format msgid "attribute %d has wrong type" msgstr "%d 속성의 형식이 잘못됨" -#: executor/execExprInterp.c:3735 utils/adt/domains.c:155 +#: executor/execExprInterp.c:3857 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "%s 도메인에서는 null 값을 허용하지 않습니다" -#: executor/execExprInterp.c:3750 utils/adt/domains.c:193 +#: executor/execExprInterp.c:3872 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "%s 도메인용 값이 \"%s\" 체크 제약 조건을 위반했습니다" -#: executor/execExprInterp.c:4235 +#: executor/execExprInterp.c:4447 +#, c-format +msgid "no SQL/JSON item found for specified path of column \"%s\"" +msgstr "\"%s\" 칼럼에 지정한 패스에서는 SQL/JSON 아이템을 찾을 수 없음" + +#: executor/execExprInterp.c:4452 +#, c-format +msgid "no SQL/JSON item found for specified path" +msgstr "지정한 패스에서는 SQL/JSON 아이템을 찾을 수 없음" + +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:4652 executor/execExprInterp.c:4660 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "%s 표현식 (%s)은 RETURNING 형식으로 바꿀 수 없음" + +#: executor/execExprInterp.c:4853 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." msgstr[0] "" "테이블 행에는 %d개 속성이 포함되어 있는데 쿼리에는 %d개가 필요합니다." -#: executor/execExprInterp.c:4351 executor/execSRF.c:978 +#: executor/execExprInterp.c:4969 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "서수 위치 %d의 삭제된 속성에서 실제 스토리지 불일치가 발생합니다." -#: executor/execIndexing.c:588 +#: executor/execIndexing.c:593 #, c-format msgid "" "ON CONFLICT does not support deferrable unique constraints/exclusion " @@ -14273,32 +14815,32 @@ msgstr "" "지연 가능한 고유 제약조건이나 제외 제약 조건은 ON CONFLICT 판별자로 사용할 " "수 없습니다." -#: executor/execIndexing.c:865 +#: executor/execIndexing.c:870 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "\"%s\" exclusion 제약 조건을 만들 수 없음" -#: executor/execIndexing.c:868 +#: executor/execIndexing.c:873 #, c-format msgid "Key %s conflicts with key %s." msgstr "%s 키와 %s 가 충돌함" -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:875 #, c-format msgid "Key conflicts exist." msgstr "키 충돌 발생" -#: executor/execIndexing.c:876 +#: executor/execIndexing.c:881 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "\"%s\" exclusion 제약 조건에 따라 키 값 충돌이 발생했습니다." -#: executor/execIndexing.c:879 +#: executor/execIndexing.c:884 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "%s 키가 이미 있는 %s 키와 충돌합니다." -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:886 #, c-format msgid "Key conflicts with existing key." msgstr "키가 기존 키와 충돌함" @@ -14313,137 +14855,89 @@ msgstr "\"%s\" 시퀀스를 바꿀 수 없음" msgid "cannot change TOAST relation \"%s\"" msgstr "\"%s\" TOAST 릴레이션을 바꿀 수 없음" -#: executor/execMain.c:1063 rewrite/rewriteHandler.c:3079 -#: rewrite/rewriteHandler.c:3966 -#, c-format -msgid "cannot insert into view \"%s\"" -msgstr "\"%s\" 뷰에 자료를 입력할 수 없습니다" - -#: executor/execMain.c:1065 rewrite/rewriteHandler.c:3082 -#: rewrite/rewriteHandler.c:3969 -#, c-format -msgid "" -"To enable inserting into the view, provide an INSTEAD OF INSERT trigger or " -"an unconditional ON INSERT DO INSTEAD rule." -msgstr "" -"뷰를 통해 자료를 입력하려면, INSTEAD OF INSERT 트리거나 ON INSERT DO INSTEAD " -"룰을 사용하세요" - -#: executor/execMain.c:1071 rewrite/rewriteHandler.c:3087 -#: rewrite/rewriteHandler.c:3974 -#, c-format -msgid "cannot update view \"%s\"" -msgstr "\"%s\" 뷰로는 자료를 갱신할 수 없습니다" - -#: executor/execMain.c:1073 rewrite/rewriteHandler.c:3090 -#: rewrite/rewriteHandler.c:3977 -#, c-format -msgid "" -"To enable updating the view, provide an INSTEAD OF UPDATE trigger or an " -"unconditional ON UPDATE DO INSTEAD rule." -msgstr "" -"뷰 자료 갱신 기능은 INSTEAD OF UPDATE 트리거를 사용하거나, ON UPDATE DO " -"INSTEAD 속성으로 룰을 만들어서 사용해 보세요." - -#: executor/execMain.c:1079 rewrite/rewriteHandler.c:3095 -#: rewrite/rewriteHandler.c:3982 -#, c-format -msgid "cannot delete from view \"%s\"" -msgstr "\"%s\" 뷰로는 자료를 삭제할 수 없습니다" - -#: executor/execMain.c:1081 rewrite/rewriteHandler.c:3098 -#: rewrite/rewriteHandler.c:3985 -#, c-format -msgid "" -"To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an " -"unconditional ON DELETE DO INSTEAD rule." -msgstr "" -"뷰 자료 삭제 기능은 INSTEAD OF DELETE 트리거를 사용하거나, ON DELETE DO " -"INSTEAD 속성으로 룰을 만들어서 사용해 보세요." - -#: executor/execMain.c:1092 +#: executor/execMain.c:1064 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "\"%s\" 구체화된 뷰를 바꿀 수 없음" -#: executor/execMain.c:1104 +#: executor/execMain.c:1076 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "\"%s\" 외부 테이블에 자료를 입력할 수 없음" -#: executor/execMain.c:1110 +#: executor/execMain.c:1082 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "\"%s\" 외부 테이블은 자료 입력을 허용하지 않음" -#: executor/execMain.c:1117 +#: executor/execMain.c:1089 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "\"%s\" 외부 테이블에 자료를 변경 할 수 없음" -#: executor/execMain.c:1123 +#: executor/execMain.c:1095 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "\"%s\" 외부 테이블은 자료 변경을 허용하지 않음" -#: executor/execMain.c:1130 +#: executor/execMain.c:1102 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "\"%s\" 외부 테이블에 자료를 삭제 할 수 없음" -#: executor/execMain.c:1136 +#: executor/execMain.c:1108 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "\"%s\" 외부 테이블은 자료 삭제를 허용하지 않음" -#: executor/execMain.c:1147 +#: executor/execMain.c:1119 #, c-format msgid "cannot change relation \"%s\"" msgstr "\"%s\" 릴레이션을 바꿀 수 없음" -#: executor/execMain.c:1174 +#: executor/execMain.c:1146 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "\"%s\" 시퀀스에서 로우를 잠글 수 없음" -#: executor/execMain.c:1181 +#: executor/execMain.c:1153 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "\"%s\" TOAST 릴레이션에서 로우를 잠글 수 없음" -#: executor/execMain.c:1188 +#: executor/execMain.c:1160 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "\"%s\" 뷰에서 로우를 잠글 수 없음" -#: executor/execMain.c:1196 +#: executor/execMain.c:1168 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "\"%s\" 구체화된 뷰에서 로우를 잠글 수 없음" -#: executor/execMain.c:1205 executor/execMain.c:2708 +#: executor/execMain.c:1177 executor/execMain.c:2687 #: executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "\"%s\" 외부 테이블에서 로우를 잠글 수 없음" -#: executor/execMain.c:1211 +#: executor/execMain.c:1183 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "\"%s\" 릴레이션에서 로우를 잠글 수 없음" -#: executor/execMain.c:1922 +#: executor/execMain.c:1901 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "새 자료가 \"%s\" 릴레이션의 파티션 제약 조건을 위반했습니다" -#: executor/execMain.c:1924 executor/execMain.c:2008 executor/execMain.c:2059 -#: executor/execMain.c:2169 +#: executor/execMain.c:1903 executor/execMain.c:1987 executor/execMain.c:2038 +#: executor/execMain.c:2148 #, c-format msgid "Failing row contains %s." msgstr "실패한 자료: %s" -#: executor/execMain.c:2005 +#: executor/execMain.c:1984 #, c-format msgid "" "null value in column \"%s\" of relation \"%s\" violates not-null constraint" @@ -14451,28 +14945,28 @@ msgstr "" "\"%s\" 칼럼(해당 릴레이션 \"%s\")의 null 값이 not null 제약조건을 위반했습니" "다." -#: executor/execMain.c:2057 +#: executor/execMain.c:2036 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "새 자료가 \"%s\" 릴레이션의 \"%s\" 체크 제약 조건을 위반했습니다" -#: executor/execMain.c:2167 +#: executor/execMain.c:2146 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "새 자료가 \"%s\" 뷰의 체크 제약 조건을 위반했습니다" -#: executor/execMain.c:2177 +#: executor/execMain.c:2156 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "" "새 자료가 \"%s\" 로우 단위 보안 정책을 위반했습니다, 해당 테이블: \"%s\"" -#: executor/execMain.c:2182 +#: executor/execMain.c:2161 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "새 자료가 \"%s\" 테이블의 로우 단위 보안 정책을 위반했습니다." -#: executor/execMain.c:2190 +#: executor/execMain.c:2169 #, c-format msgid "" "target row violates row-level security policy \"%s\" (USING expression) for " @@ -14481,7 +14975,7 @@ msgstr "" "대상 로우가 \"%s\" 로우 단위 보안 정책(USING 절 사용)을 위반했습니다, 해당 테" "이블: \"%s\"" -#: executor/execMain.c:2195 +#: executor/execMain.c:2174 #, c-format msgid "" "target row violates row-level security policy (USING expression) for table " @@ -14490,7 +14984,7 @@ msgstr "" "대상 로우가 \"%s\" 테이블의 로우 단위 보안 정책(USING 절 사용)을 위반했습니" "다." -#: executor/execMain.c:2202 +#: executor/execMain.c:2181 #, c-format msgid "" "new row violates row-level security policy \"%s\" (USING expression) for " @@ -14499,25 +14993,25 @@ msgstr "" "새 자료가 \"%s\" 로우 단위 보안 정책(USING 절 사용)을 위반했습니다, 해당 테이" "블: \"%s\"" -#: executor/execMain.c:2207 +#: executor/execMain.c:2186 #, c-format msgid "" -"new row violates row-level security policy (USING expression) for table \"%s" -"\"" +"new row violates row-level security policy (USING expression) for table " +"\"%s\"" msgstr "" "새 자료가 \"%s\" 테이블의 로우 단위 보안 정책(USING 절 사용)을 위반했습니다." -#: executor/execPartition.c:330 +#: executor/execPartition.c:327 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "해당 로우를 위한 \"%s\" 릴레이션용 파티션이 없음" -#: executor/execPartition.c:333 +#: executor/execPartition.c:330 #, c-format msgid "Partition key of the failing row contains %s." msgstr "실패한 로우의 파티션 키 값: %s" -#: executor/execReplication.c:231 executor/execReplication.c:415 +#: executor/execReplication.c:272 executor/execReplication.c:456 #, c-format msgid "" "tuple to be locked was already moved to another partition due to concurrent " @@ -14525,50 +15019,50 @@ msgid "" msgstr "" "다른 업데이트 작업으로 잠굴 튜플이 이미 다른 파티션으로 이동되었음, 재시도함" -#: executor/execReplication.c:235 executor/execReplication.c:419 +#: executor/execReplication.c:276 executor/execReplication.c:460 #, c-format msgid "concurrent update, retrying" msgstr "동시 업데이트, 다시 시도 중" -#: executor/execReplication.c:241 executor/execReplication.c:425 +#: executor/execReplication.c:282 executor/execReplication.c:466 #, c-format msgid "concurrent delete, retrying" msgstr "동시 삭제, 다시 시도 중" -#: executor/execReplication.c:311 parser/parse_cte.c:308 -#: parser/parse_oper.c:233 utils/adt/array_userfuncs.c:1348 -#: utils/adt/array_userfuncs.c:1491 utils/adt/arrayfuncs.c:3832 -#: utils/adt/arrayfuncs.c:4387 utils/adt/arrayfuncs.c:6397 -#: utils/adt/rowtypes.c:1230 +#: executor/execReplication.c:352 parser/parse_cte.c:302 +#: parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 +#: utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3852 +#: utils/adt/arrayfuncs.c:4407 utils/adt/arrayfuncs.c:6426 +#: utils/adt/rowtypes.c:1220 #, c-format msgid "could not identify an equality operator for type %s" msgstr "" "%s 자료형에서 사용할 동등 연산자(equality operator)를 찾을 수 없습니다." -#: executor/execReplication.c:642 executor/execReplication.c:648 +#: executor/execReplication.c:687 executor/execReplication.c:693 #, c-format msgid "cannot update table \"%s\"" msgstr "\"%s\" 테이블에 자료를 변경 할 수 없음" -#: executor/execReplication.c:644 executor/execReplication.c:656 +#: executor/execReplication.c:689 executor/execReplication.c:701 #, c-format msgid "" "Column used in the publication WHERE expression is not part of the replica " "identity." msgstr "발행의 WHERE 절에서 사용한 칼럼이 복제 식별자의 한 부분이 아닙니다." -#: executor/execReplication.c:650 executor/execReplication.c:662 +#: executor/execReplication.c:695 executor/execReplication.c:707 #, c-format msgid "" "Column list used by the publication does not cover the replica identity." msgstr "발행에서 사용되는 칼럼 목록이 복제 식별자를 모두 포함하지 못했습니다." -#: executor/execReplication.c:654 executor/execReplication.c:660 +#: executor/execReplication.c:699 executor/execReplication.c:705 #, c-format msgid "cannot delete from table \"%s\"" msgstr "\"%s\" 테이블에 자료를 삭제 할 수 없음" -#: executor/execReplication.c:680 +#: executor/execReplication.c:725 #, c-format msgid "" "cannot update table \"%s\" because it does not have a replica identity and " @@ -14577,52 +15071,52 @@ msgstr "" "\"%s\" 테이블 업데이트 실패, 이 테이블에는 복제용 식별자를 지정하지 않았거" "나, updates 옵션 없이 발행했습니다" -#: executor/execReplication.c:682 +#: executor/execReplication.c:727 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "" "업데이트를 하려면, ALTER TABLE 명령어에서 REPLICA IDENTITY 옵션을 사용하세요" -#: executor/execReplication.c:686 +#: executor/execReplication.c:731 #, c-format msgid "" "cannot delete from table \"%s\" because it does not have a replica identity " "and publishes deletes" msgstr "\"%s\" 테이블 자료 삭제 실패, 복제 식별자와 deletes 발행을 안함" -#: executor/execReplication.c:688 +#: executor/execReplication.c:733 #, c-format msgid "" "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "삭제 하려면, ALTER TABLE 명령어에서 REPLICA IDENTITY 옵션을 사용하세요" -#: executor/execReplication.c:704 +#: executor/execReplication.c:749 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "\"%s.%s\" 릴레이션은 논리 복제 대상이 될 수 없음" -#: executor/execSRF.c:316 +#: executor/execSRF.c:315 #, c-format msgid "rows returned by function are not all of the same row type" msgstr "함수 호출로 반환되는 로우가 같은 로우형의 전부가 아닙니다" -#: executor/execSRF.c:366 +#: executor/execSRF.c:365 #, c-format msgid "table-function protocol for value-per-call mode was not followed" msgstr "" "value-per-call 모드를 위한 테이블 함수 프로토콜이 뒤이어 오지 않았습니다" -#: executor/execSRF.c:374 executor/execSRF.c:668 +#: executor/execSRF.c:373 executor/execSRF.c:667 #, c-format msgid "table-function protocol for materialize mode was not followed" msgstr "materialize 모드를 위한 테이블 함수 프로토콜이 뒤이어 오지 않았습니다" -#: executor/execSRF.c:381 executor/execSRF.c:686 +#: executor/execSRF.c:380 executor/execSRF.c:685 #, c-format msgid "unrecognized table-function returnMode: %d" msgstr "알 수 없는 테이블-함수 리턴모드: %d" -#: executor/execSRF.c:895 +#: executor/execSRF.c:894 #, c-format msgid "" "function returning setof record called in context that cannot accept type " @@ -14630,35 +15124,45 @@ msgid "" msgstr "" "setof 레코드 반환 함수가 type 레코드를 허용하지 않는 컨텍스트에서 호출됨" -#: executor/execSRF.c:951 executor/execSRF.c:967 executor/execSRF.c:977 +#: executor/execSRF.c:950 executor/execSRF.c:966 executor/execSRF.c:976 #, c-format msgid "function return row and query-specified return row do not match" msgstr "함수 반환 행과 쿼리 지정 반환 행이 일치하지 않음" -#: executor/execSRF.c:952 +#: executor/execSRF.c:951 #, c-format msgid "Returned row contains %d attribute, but query expects %d." msgid_plural "Returned row contains %d attributes, but query expects %d." msgstr[0] "" "반환된 행에는 %d개 속성이 포함되어 있는데 쿼리에는 %d개가 필요합니다." -#: executor/execSRF.c:968 +#: executor/execSRF.c:967 #, c-format msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "반환된 형식은 %s인데(서수 위치 %d) 쿼리에는 %s이(가) 필요합니다." -#: executor/execTuples.c:146 executor/execTuples.c:353 -#: executor/execTuples.c:521 executor/execTuples.c:713 +#: executor/execTuples.c:147 executor/execTuples.c:368 +#: executor/execTuples.c:563 executor/execTuples.c:772 #, c-format msgid "cannot retrieve a system column in this context" msgstr "이 컨텍스트에는 시스템 칼럼을 찾을 수 없음" -#: executor/execUtils.c:744 +#: executor/execTuples.c:163 executor/execTuples.c:580 +#, c-format +msgid "don't have transaction information for this type of tuple" +msgstr "튜플의 이런 형태에 대한 트랜잭션 정보가 없음" + +#: executor/execTuples.c:390 executor/execTuples.c:794 +#, c-format +msgid "don't have a storage tuple in this context" +msgstr "이 컨텍스트에는 a storage tuple 을 가질 수 없음." + +#: executor/execUtils.c:713 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "\"%s\" 구체화된 뷰가 아직 구체화되지 못했습니다." -#: executor/execUtils.c:746 +#: executor/execUtils.c:715 #, c-format msgid "Use the REFRESH MATERIALIZED VIEW command." msgstr "REFRESH MATERIALIZED VIEW 명령을 사용하세요." @@ -14668,117 +15172,118 @@ msgstr "REFRESH MATERIALIZED VIEW 명령을 사용하세요." msgid "could not determine actual type of argument declared %s" msgstr "%s 인자의 자료형으로 지정한 자료형의 기본 자료형을 찾을 수 없습니다" -#: executor/functions.c:512 +#: executor/functions.c:513 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "SQL 함수에서 클라이언트 대상 COPY to/from 작업을 할 수 없음" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:519 #, c-format msgid "%s is not allowed in an SQL function" msgstr "SQL 함수에서는 %s 구문을 허용하지 않음" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1742 executor/spi.c:2635 +#: executor/functions.c:527 executor/spi.c:1744 executor/spi.c:2657 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "%s 구문은 비휘발성 함수(non-volatile function)에서 허용하지 않습니다" -#: executor/functions.c:1450 +#: executor/functions.c:1452 #, c-format msgid "SQL function \"%s\" statement %d" msgstr "SQL 함수 \"%s\"의 문 %d" -#: executor/functions.c:1476 +#: executor/functions.c:1478 #, c-format msgid "SQL function \"%s\" during startup" msgstr "시작 중 SQL 함수 \"%s\"" -#: executor/functions.c:1561 +#: executor/functions.c:1563 #, c-format msgid "" "calling procedures with output arguments is not supported in SQL functions" msgstr "출력 인자를 포함한 프로시져 호출은 SQL 함수에서 지원하지 않습니다." -#: executor/functions.c:1694 executor/functions.c:1732 -#: executor/functions.c:1746 executor/functions.c:1836 -#: executor/functions.c:1869 executor/functions.c:1883 +#: executor/functions.c:1698 executor/functions.c:1736 +#: executor/functions.c:1750 executor/functions.c:1845 +#: executor/functions.c:1878 executor/functions.c:1892 #, c-format msgid "return type mismatch in function declared to return %s" msgstr "리턴 자료형이 함수 정의에서 지정한 %s 리턴 자료형과 틀립니다" -#: executor/functions.c:1696 +#: executor/functions.c:1700 #, c-format msgid "" -"Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING." +"Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE " +"RETURNING." msgstr "" -"함수 내용의 맨 마지막 구문은 SELECT 또는 INSERT/UPDATE/DELETE RETURNING이어" -"야 합니다." +"함수 내용의 맨 마지막 구문은 SELECT 또는 INSERT/UPDATE/DELETE/MERGE RETURNING" +"이어야 합니다." -#: executor/functions.c:1734 +#: executor/functions.c:1738 #, c-format msgid "Final statement must return exactly one column." msgstr "맨 마지막 구문은 정확히 하나의 칼럼만 반환해야 합니다." -#: executor/functions.c:1748 +#: executor/functions.c:1752 #, c-format msgid "Actual return type is %s." msgstr "실재 반환 자료형은 %s" -#: executor/functions.c:1838 +#: executor/functions.c:1847 #, c-format msgid "Final statement returns too many columns." msgstr "맨 마지막 구문이 너무 많은 칼럼을 반환합니다." -#: executor/functions.c:1871 +#: executor/functions.c:1880 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "" "맨 마지막 구문이 %s(기대되는 자료형: %s) 자료형을 %d 번째 칼럼에서 반환합니" "다." -#: executor/functions.c:1885 +#: executor/functions.c:1894 #, c-format msgid "Final statement returns too few columns." msgstr "맨 마지막 구문이 너무 적은 칼럼을 반환합니다." -#: executor/functions.c:1913 +#: executor/functions.c:1922 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "반환 자료형인 %s 자료형은 SQL 함수에서 지원되지 않음" -#: executor/nodeAgg.c:3937 executor/nodeWindowAgg.c:2993 +#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2975 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "%u OID 집계함수에 호환 가능한 입력 형식과 변환 형식이 있어야 함" -#: executor/nodeAgg.c:3967 parser/parse_agg.c:669 parser/parse_agg.c:697 +#: executor/nodeAgg.c:3966 parser/parse_agg.c:680 parser/parse_agg.c:708 #, c-format msgid "aggregate function calls cannot be nested" msgstr "집계 함수는 중첩되어 호출 할 수 없음" -#: executor/nodeCustom.c:154 executor/nodeCustom.c:165 +#: executor/nodeCustom.c:144 executor/nodeCustom.c:155 #, c-format msgid "custom scan \"%s\" does not support MarkPos" msgstr "\"%s\" 이름의 칼럼 탐색은 MarkPos 기능을 지원하지 않음" -#: executor/nodeHashjoin.c:1143 executor/nodeHashjoin.c:1173 +#: executor/nodeHashjoin.c:1131 executor/nodeHashjoin.c:1161 #, c-format msgid "could not rewind hash-join temporary file" msgstr "해시-조인 임시 파일을 되감을 수 없음" -#: executor/nodeIndexonlyscan.c:238 +#: executor/nodeIndexonlyscan.c:239 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "lossy distance 함수들은 인덱스 단독 탐색을 지원하지 않음" -#: executor/nodeLimit.c:374 +#: executor/nodeLimit.c:373 #, c-format msgid "OFFSET must not be negative" msgstr "OFFSET은 음수가 아니어야 함" -#: executor/nodeLimit.c:400 +#: executor/nodeLimit.c:399 #, c-format msgid "LIMIT must not be negative" msgstr "LIMIT는 음수가 아니어야 함" @@ -14793,31 +15298,31 @@ msgstr "RIGHT JOIN은 병합-조인 가능 조인 조건에서만 지원됨" msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "FULL JOIN은 병합-조인 가능 조인 조건에서만 지원됨" -#: executor/nodeModifyTable.c:234 +#: executor/nodeModifyTable.c:240 #, c-format msgid "Query has too few columns." msgstr "쿼리에 칼럼이 너무 적습니다." -#: executor/nodeModifyTable.c:1530 executor/nodeModifyTable.c:1604 +#: executor/nodeModifyTable.c:1540 executor/nodeModifyTable.c:1614 #, c-format msgid "" "tuple to be deleted was already modified by an operation triggered by the " "current command" msgstr "현재 명령으로 실행된 트리거 작업으로 지울 자료가 이미 바뀌었습니다." -#: executor/nodeModifyTable.c:1758 +#: executor/nodeModifyTable.c:1769 #, c-format msgid "invalid ON UPDATE specification" msgstr "잘못된 ON UPDATE 옵션" -#: executor/nodeModifyTable.c:1759 +#: executor/nodeModifyTable.c:1770 #, c-format msgid "" "The result tuple would appear in a different partition than the original " "tuple." msgstr "결과 튜플이 원래 튜플이 아닌 다른 파티션에서 나타날 것입니다." -#: executor/nodeModifyTable.c:2217 +#: executor/nodeModifyTable.c:2226 #, c-format msgid "" "cannot move tuple across partitions when a non-root ancestor of the source " @@ -14826,7 +15331,7 @@ msgstr "" "참조키가 바로 해당 하위 파티션 테이블을 참조하는 경우 파티션 간 자료 이동은 " "할 수 없습니다." -#: executor/nodeModifyTable.c:2218 +#: executor/nodeModifyTable.c:2227 #, c-format msgid "" "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." @@ -14834,18 +15339,19 @@ msgstr "" "참조키가 \"%s\" 하위 파티션 테이블을 대상으로 합니다. 상위 파티션 테이블은 " "\"%s\" 테이블입니다." -#: executor/nodeModifyTable.c:2221 +#: executor/nodeModifyTable.c:2230 #, c-format msgid "Consider defining the foreign key on table \"%s\"." msgstr "\"%s\" 테이블에 참조키 정의를 고려하세요." #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2567 executor/nodeModifyTable.c:2955 +#: executor/nodeModifyTable.c:2596 executor/nodeModifyTable.c:3138 +#: executor/nodeModifyTable.c:3308 #, c-format msgid "%s command cannot affect row a second time" msgstr "%s 명령은 두번째 작업에는 아무런 영향을 주 않음" -#: executor/nodeModifyTable.c:2569 +#: executor/nodeModifyTable.c:2598 #, c-format msgid "" "Ensure that no rows proposed for insertion within the same command have " @@ -14854,19 +15360,7 @@ msgstr "" "동일한 명령 내에서 삽입하도록 제안된 행에 중복된 제한 값이 없는지 확인하십시" "오." -#: executor/nodeModifyTable.c:2957 -#, c-format -msgid "Ensure that not more than one source row matches any one target row." -msgstr "둘 이상의 소스 행이 하나의 대상 행과 일치하지 않는지 확인하십시오." - -#: executor/nodeModifyTable.c:3038 -#, c-format -msgid "" -"tuple to be deleted was already moved to another partition due to concurrent " -"update" -msgstr "동시 업데이트로 삭제할 튜플이 이미 다른 파티션으로 옮겨졌음" - -#: executor/nodeModifyTable.c:3077 +#: executor/nodeModifyTable.c:3131 executor/nodeModifyTable.c:3301 #, c-format msgid "" "tuple to be updated or deleted was already modified by an operation " @@ -14875,12 +15369,24 @@ msgstr "" "현재 명령으로 실행된 트리거 작업으로 변경하거나 지울 자료가 이미 바뀌었습니" "다." -#: executor/nodeSamplescan.c:260 +#: executor/nodeModifyTable.c:3140 executor/nodeModifyTable.c:3310 +#, c-format +msgid "Ensure that not more than one source row matches any one target row." +msgstr "둘 이상의 소스 행이 하나의 대상 행과 일치하지 않는지 확인하십시오." + +#: executor/nodeModifyTable.c:3209 +#, c-format +msgid "" +"tuple to be merged was already moved to another partition due to concurrent " +"update" +msgstr "합병될 튜플이 동시 업데이트로 이미 다른 파티션으로 옮겨졌음" + +#: executor/nodeSamplescan.c:244 #, c-format msgid "TABLESAMPLE parameter cannot be null" msgstr "TABLESAMPLE 절에는 반드시 부가 옵션값들이 있어야 합니다" -#: executor/nodeSamplescan.c:272 +#: executor/nodeSamplescan.c:256 #, c-format msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "TABLESAMPLE REPEATABLE 절은 더 이상의 부가 옵션을 쓰면 안됩니다." @@ -14891,7 +15397,7 @@ msgstr "TABLESAMPLE REPEATABLE 절은 더 이상의 부가 옵션을 쓰면 안 msgid "more than one row returned by a subquery used as an expression" msgstr "표현식에 사용된 서브쿼리 결과가 하나 이상의 행을 리턴했습니다" -#: executor/nodeTableFuncscan.c:375 +#: executor/nodeTableFuncscan.c:370 #, c-format msgid "namespace URI must not be null" msgstr "네임스페이스 URI 값은 null 일 수 없습니다." @@ -14901,17 +15407,17 @@ msgstr "네임스페이스 URI 값은 null 일 수 없습니다." msgid "row filter expression must not be null" msgstr "로우 필터 표현식은 null값이 아니여야 함" -#: executor/nodeTableFuncscan.c:415 +#: executor/nodeTableFuncscan.c:416 #, c-format msgid "column filter expression must not be null" msgstr "칼럼 필터 표현식은 null값이 아니여야 함" -#: executor/nodeTableFuncscan.c:416 +#: executor/nodeTableFuncscan.c:417 #, c-format msgid "Filter for column \"%s\" is null." msgstr "\"%s\" 칼럼용 필터가 null입니다." -#: executor/nodeTableFuncscan.c:506 +#: executor/nodeTableFuncscan.c:507 #, c-format msgid "null is not allowed in column \"%s\"" msgstr "\"%s\" 칼럼은 null 값을 허용하지 않습니다" @@ -14941,84 +15447,84 @@ msgstr "프래임 끝 위치값으로 null 값을 사용할 수 없습니다." msgid "frame ending offset must not be negative" msgstr "프래임 끝 위치값으로 음수 값을 사용할 수 없습니다." -#: executor/nodeWindowAgg.c:2909 +#: executor/nodeWindowAgg.c:2891 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "%s 집계 함수는 윈도우 함수로 사용될 수 없습니다" -#: executor/spi.c:242 executor/spi.c:342 +#: executor/spi.c:241 executor/spi.c:341 #, c-format msgid "invalid transaction termination" msgstr "잘못된 트랜잭션 마침" -#: executor/spi.c:257 +#: executor/spi.c:256 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "하위트랜잭션이 활성화 된 상태에서는 커밋 할 수 없음" -#: executor/spi.c:348 +#: executor/spi.c:347 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "하위트랜잭션이 활성화 된 상태에서는 롤백 할 수 없음" -#: executor/spi.c:472 +#: executor/spi.c:471 #, c-format msgid "transaction left non-empty SPI stack" msgstr "트랜잭션이 비어있지 않은 SPI 스택을 남겼습니다" -#: executor/spi.c:473 executor/spi.c:533 +#: executor/spi.c:472 executor/spi.c:532 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "\"SPI_finish\" 호출이 빠졌는지 확인하세요" -#: executor/spi.c:532 +#: executor/spi.c:531 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "하위 트랜잭션이 비어있지 않은 SPI 스택을 남겼습니다" -#: executor/spi.c:1600 +#: executor/spi.c:1602 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "멀티 쿼리를 커서로 열 수는 없습니다" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1610 +#: executor/spi.c:1612 #, c-format msgid "cannot open %s query as cursor" msgstr "%s 쿼리로 커서를 열 수 없음." -#: executor/spi.c:1716 +#: executor/spi.c:1718 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE는 지원되지 않음" -#: executor/spi.c:1717 parser/analyze.c:2912 +#: executor/spi.c:1719 parser/analyze.c:2928 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "스크롤 가능 커서는 READ ONLY여야 합니다." -#: executor/spi.c:2474 +#: executor/spi.c:2496 #, c-format msgid "empty query does not return tuples" msgstr "빈 쿼리는 튜플을 반환하지 않습니다." #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2548 +#: executor/spi.c:2570 #, c-format msgid "%s query does not return tuples" msgstr "%s 쿼리는 집합을 반환할 수 없습니다." -#: executor/spi.c:2963 +#: executor/spi.c:2987 #, c-format msgid "SQL expression \"%s\"" msgstr "SQL 표현식: \"%s\"" -#: executor/spi.c:2968 +#: executor/spi.c:2992 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "PL/pgSQL 지정: \"%s\"" -#: executor/spi.c:2971 +#: executor/spi.c:2995 #, c-format msgid "SQL statement \"%s\"" msgstr "SQL 구문: \"%s\"" @@ -15028,28 +15534,34 @@ msgstr "SQL 구문: \"%s\"" msgid "could not send tuple to shared-memory queue" msgstr "공유 메모리 큐로 튜플을 보낼 수 없음" -#: foreign/foreign.c:222 +#: foreign/foreign.c:225 #, c-format -msgid "user mapping not found for \"%s\"" -msgstr "\"%s\"에 대한 사용자 매핑을 찾을 수 없음" +msgid "user mapping not found for user \"%s\", server \"%s\"" +msgstr "\"%s\"에 대한 사용자 매핑을 \"%s\" 서버에서 찾을 수 없음" -#: foreign/foreign.c:647 storage/file/fd.c:3931 +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7153 +#: optimizer/util/plancat.c:540 +#, c-format +msgid "access to non-system foreign table is restricted" +msgstr "non-system 외부 테이블을 접근하는 것은 제한되었음" + +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "\"%s\" 옵션이 잘못됨" -#: foreign/foreign.c:649 +#: foreign/foreign.c:662 #, c-format msgid "Perhaps you meant the option \"%s\"." msgstr "아마 \"%s\" 옵션을 뜻하는 것 같습니다." -#: foreign/foreign.c:651 +#: foreign/foreign.c:664 #, c-format msgid "There are no valid options in this context." msgstr "이 컨텍스트에서 유효한 옵션이 없음." -#: lib/dshash.c:254 utils/mmgr/dsa.c:715 utils/mmgr/dsa.c:737 -#: utils/mmgr/dsa.c:818 +#: lib/dshash.c:254 utils/mmgr/dsa.c:708 utils/mmgr/dsa.c:730 +#: utils/mmgr/dsa.c:811 #, c-format msgid "Failed on DSA request of size %zu." msgstr "크기가 %zu인 DSA 요청에서 오류가 발생했습니다." @@ -15059,77 +15571,77 @@ msgstr "크기가 %zu인 DSA 요청에서 오류가 발생했습니다." msgid "expected SASL response, got message type %d" msgstr "SASL 응답이 필요한데 메시지 형식 %d을(를) 받음" -#: libpq/auth-scram.c:270 +#: libpq/auth-scram.c:263 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "클라이언트가 잘못된 SASL 인증 메카니즘을 선택했음" -#: libpq/auth-scram.c:294 libpq/auth-scram.c:543 libpq/auth-scram.c:554 +#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "\"%s\" 사용자에 대한 잘못된 SCRAM secret" -#: libpq/auth-scram.c:305 +#: libpq/auth-scram.c:298 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "\"%s\" 사용자용 바른 SCRAM secret이 없습니다." -#: libpq/auth-scram.c:385 libpq/auth-scram.c:390 libpq/auth-scram.c:744 -#: libpq/auth-scram.c:752 libpq/auth-scram.c:857 libpq/auth-scram.c:870 -#: libpq/auth-scram.c:880 libpq/auth-scram.c:988 libpq/auth-scram.c:995 -#: libpq/auth-scram.c:1010 libpq/auth-scram.c:1025 libpq/auth-scram.c:1039 -#: libpq/auth-scram.c:1057 libpq/auth-scram.c:1072 libpq/auth-scram.c:1386 -#: libpq/auth-scram.c:1394 +#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 +#: libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 +#: libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 +#: libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 +#: libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 +#: libpq/auth-scram.c:1387 #, c-format msgid "malformed SCRAM message" msgstr "SCRAM 메시지가 형식에 맞지 않습니다" -#: libpq/auth-scram.c:386 +#: libpq/auth-scram.c:379 #, c-format msgid "The message is empty." msgstr "메시지가 비었습니다." -#: libpq/auth-scram.c:391 +#: libpq/auth-scram.c:384 #, c-format msgid "Message length does not match input length." msgstr "메시지 길이가 입력 길이와 같지 않습니다." -#: libpq/auth-scram.c:423 +#: libpq/auth-scram.c:416 #, c-format msgid "invalid SCRAM response" msgstr "잘못된 SCRAM 응답" -#: libpq/auth-scram.c:424 +#: libpq/auth-scram.c:417 #, c-format msgid "Nonce does not match." msgstr "토큰 불일치" -#: libpq/auth-scram.c:500 +#: libpq/auth-scram.c:493 #, c-format msgid "could not generate random salt" msgstr "무작위 솔트 생성 실패" -#: libpq/auth-scram.c:745 +#: libpq/auth-scram.c:738 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "\"%c\" 속성이어야 하는데, \"%s\" 임." -#: libpq/auth-scram.c:753 libpq/auth-scram.c:881 +#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "\"%c\" 속성에는 \"=\" 문자가 와야 합니다." -#: libpq/auth-scram.c:858 +#: libpq/auth-scram.c:851 #, c-format msgid "Attribute expected, but found end of string." msgstr "속성값이 와야하는데, 문자열 끝이 발견되었음." -#: libpq/auth-scram.c:871 +#: libpq/auth-scram.c:864 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "속성값이 와야하는데, \"%s\" 잘못된 문자가 발견되었음." -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 #, c-format msgid "" "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not " @@ -15138,17 +15650,17 @@ msgstr "" "해당 클라이언트가 SCRAM-SHA-256-PLUS 규약을 선택했는데, SCRAM 메시지에 채널 " "바인딩 데이터가 없습니다." -#: libpq/auth-scram.c:996 libpq/auth-scram.c:1026 +#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 #, c-format msgid "Comma expected, but found character \"%s\"." msgstr "쉼표가 와야하는데, \"%s\" 문자가 발견되었음." -#: libpq/auth-scram.c:1017 +#: libpq/auth-scram.c:1010 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "SCRAM 채널 바인딩 협상 오류" -#: libpq/auth-scram.c:1018 +#: libpq/auth-scram.c:1011 #, c-format msgid "" "The client supports SCRAM channel binding but thinks the server does not. " @@ -15157,7 +15669,7 @@ msgstr "" "해당 클라이언트는 SCRAM 채널 바인딩을 지원하지만, 서버는 그렇지 않은 것 같습" "니다. 그런데, 이 서버는 채널 바인딩을 지원합니다." -#: libpq/auth-scram.c:1040 +#: libpq/auth-scram.c:1033 #, c-format msgid "" "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM " @@ -15166,153 +15678,153 @@ msgstr "" "해당 클라이언트가 채널 바인딩을 하지 않는 SCRAM-SHA-256 규약을 선택했는데, " "SCRAM 메시지에 채널 바인딩 데이터가 있습니다." -#: libpq/auth-scram.c:1051 +#: libpq/auth-scram.c:1044 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "지원하지 않는 SCRAM 채널 바인드 종류 \"%s\"" -#: libpq/auth-scram.c:1058 +#: libpq/auth-scram.c:1051 #, c-format msgid "Unexpected channel-binding flag \"%s\"." msgstr "예상치 못한 채널 바인딩 플래그 \"%s\"." -#: libpq/auth-scram.c:1068 +#: libpq/auth-scram.c:1061 #, c-format msgid "client uses authorization identity, but it is not supported" msgstr "" "클라이언트는 authorization identity를 사용하지만, 이것을 지원하지 않습니다." -#: libpq/auth-scram.c:1073 +#: libpq/auth-scram.c:1066 #, c-format msgid "Unexpected attribute \"%s\" in client-first-message." msgstr "client-first-message 안에 \"%s\" 속성이 잘못됨" -#: libpq/auth-scram.c:1089 +#: libpq/auth-scram.c:1082 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "클라이언트가 지원하지 않는 SCRAM 확장을 요구합니다." -#: libpq/auth-scram.c:1103 +#: libpq/auth-scram.c:1096 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "SCRAM 토큰에 인쇄할 수 없는 문자가 있음" -#: libpq/auth-scram.c:1234 +#: libpq/auth-scram.c:1227 #, c-format msgid "could not generate random nonce" msgstr "무작위 토큰을 만들 수 없음" -#: libpq/auth-scram.c:1244 +#: libpq/auth-scram.c:1237 #, c-format msgid "could not encode random nonce" msgstr "임의 nonce를 인코드할 수 없음" -#: libpq/auth-scram.c:1350 +#: libpq/auth-scram.c:1343 #, c-format msgid "SCRAM channel binding check failed" msgstr "SCRAM 채널 바인딩 검사 실패" -#: libpq/auth-scram.c:1368 +#: libpq/auth-scram.c:1361 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "client-final-message 안에 예상치 못한 SCRAM 채널 바인딩 속성이 있음" -#: libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:1380 #, c-format msgid "Malformed proof in client-final-message." msgstr "client-final-message 안에 잘못된 증명" -#: libpq/auth-scram.c:1395 +#: libpq/auth-scram.c:1388 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "client-final-message 끝에 추가로 쓸모 없는 값이 있음" -#: libpq/auth.c:271 +#: libpq/auth.c:269 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "사용자 \"%s\"의 인증을 실패했습니다: 호스트 거부됨" -#: libpq/auth.c:274 +#: libpq/auth.c:272 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 \"trust\" 인증을 실패했습니다." -#: libpq/auth.c:277 +#: libpq/auth.c:275 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 Ident 인증을 실패했습니다." -#: libpq/auth.c:280 +#: libpq/auth.c:278 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 peer 인증을 실패했습니다." -#: libpq/auth.c:285 +#: libpq/auth.c:283 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 password 인증을 실패했습니다" -#: libpq/auth.c:290 +#: libpq/auth.c:288 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "\"%s\" 사용자에 대한 GSSAPI 인증을 실패했습니다." -#: libpq/auth.c:293 +#: libpq/auth.c:291 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "\"%s\" 사용자에 대한 SSPI 인증을 실패했습니다." -#: libpq/auth.c:296 +#: libpq/auth.c:294 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 PAM 인증을 실패했습니다." -#: libpq/auth.c:299 +#: libpq/auth.c:297 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "\"%s\" 사용자에 대한 BSD 인증을 실패했습니다." -#: libpq/auth.c:302 +#: libpq/auth.c:300 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "\"%s\" 사용자의 LDAP 인증을 실패했습니다." -#: libpq/auth.c:305 +#: libpq/auth.c:303 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 인증서 인증을 실패했습니다" -#: libpq/auth.c:308 +#: libpq/auth.c:306 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "사용자 \"%s\"의 RADIUS 인증을 실패했습니다." -#: libpq/auth.c:311 +#: libpq/auth.c:309 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "사용자 \"%s\"의 인증을 실패했습니다: 잘못된 인증 방법" -#: libpq/auth.c:315 +#: libpq/auth.c:313 #, c-format msgid "Connection matched file \"%s\" line %d: \"%s\"" msgstr "\"%s\" 파일의 %d번째 줄에 지정한 인증 설정이 사용됨: \"%s\"" -#: libpq/auth.c:359 +#: libpq/auth.c:357 #, c-format msgid "authentication identifier set more than once" msgstr "인증 식별자가 여러 번 사용 됨" -#: libpq/auth.c:360 +#: libpq/auth.c:358 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "이전 식별자: \"%s\"; 새 식별자: \"%s\"" -#: libpq/auth.c:370 +#: libpq/auth.c:368 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "연결 인증됨: 식별자=\"%s\" 인증방법=%s (%s:%d)" -#: libpq/auth.c:410 +#: libpq/auth.c:408 #, c-format msgid "" "client certificates can only be checked if a root certificate store is " @@ -15320,25 +15832,25 @@ msgid "" msgstr "" "루트 인증서 저장소가 사용 가능한 경우에만 클라이언트 인증서를 검사할 수 있음" -#: libpq/auth.c:421 +#: libpq/auth.c:419 #, c-format msgid "connection requires a valid client certificate" msgstr "연결에 유효한 클라이언트 인증서가 필요함" -#: libpq/auth.c:452 libpq/auth.c:498 +#: libpq/auth.c:450 libpq/auth.c:496 msgid "GSS encryption" msgstr "GSS 암호화" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:453 libpq/auth.c:499 msgid "SSL encryption" msgstr "SSL 암호화" -#: libpq/auth.c:457 libpq/auth.c:503 +#: libpq/auth.c:455 libpq/auth.c:501 msgid "no encryption" msgstr "암호화 안함" #. translator: last %s describes encryption state -#: libpq/auth.c:463 +#: libpq/auth.c:461 #, c-format msgid "" "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" @@ -15347,289 +15859,288 @@ msgstr "" "에 따라 거부됩니다" #. translator: last %s describes encryption state -#: libpq/auth.c:470 +#: libpq/auth.c:468 #, c-format msgid "" -"pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s" -"\", %s" +"pg_hba.conf rejects connection for host \"%s\", user \"%s\", database " +"\"%s\", %s" msgstr "" "호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\", %s 연결이 pg_hba.conf 파" "일 설정에 따라 거부됩니다" -#: libpq/auth.c:508 +#: libpq/auth.c:506 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "" "클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능으로 맞음" -#: libpq/auth.c:511 +#: libpq/auth.c:509 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "" "클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능 사용안함" -#: libpq/auth.c:514 +#: libpq/auth.c:512 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "" "클라이언트 IP 주소가 \"%s\" 이름으로 확인됨, 호스트 이름 확인 기능으로 틀림" -#: libpq/auth.c:517 +#: libpq/auth.c:515 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "\"%s\" 클라이언트 호스트 이름을 %s IP 주소로 전환할 수 없음." -#: libpq/auth.c:522 +#: libpq/auth.c:520 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "클라이언트 IP 주소를 파악할 수 없음: 대상 호스트 이름: %s" #. translator: last %s describes encryption state -#: libpq/auth.c:530 +#: libpq/auth.c:528 #, c-format msgid "" -"no pg_hba.conf entry for replication connection from host \"%s\", user \"%s" -"\", %s" +"no pg_hba.conf entry for replication connection from host \"%s\", user " +"\"%s\", %s" msgstr "" "호스트 \"%s\", 사용자 \"%s\", %s 연결이 복제용 연결로 pg_hba.conf 파일에 설정" "되어 있지 않습니다" #. translator: last %s describes encryption state -#: libpq/auth.c:538 +#: libpq/auth.c:536 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "" "호스트 \"%s\", 사용자 \"%s\", 데이터베이스 \"%s\", %s 연결에 대한 설정이 " "pg_hba.conf 파일에 없습니다." -#: libpq/auth.c:711 +#: libpq/auth.c:656 +#, c-format +msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" +msgstr "연결 인증됨: 사용자=\"%s\" 인증방법=%s (%s:%d)" + +#: libpq/auth.c:725 #, c-format msgid "expected password response, got message type %d" msgstr "메시지 타입 %d를 얻는 예상된 암호 응답" -#: libpq/auth.c:732 +#: libpq/auth.c:746 #, c-format msgid "invalid password packet size" msgstr "유효하지 않은 암호 패킷 사이즈" -#: libpq/auth.c:750 +#: libpq/auth.c:764 #, c-format msgid "empty password returned by client" msgstr "비어있는 암호는 클라이언트에 의해 돌려보냈습니다" -#: libpq/auth.c:879 libpq/hba.c:1727 -#, c-format -msgid "" -"MD5 authentication is not supported when \"db_user_namespace\" is enabled" -msgstr "\"db_user_namespace\"가 사용 가능한 경우 MD5 인증은 지원되지 않음" - -#: libpq/auth.c:885 +#: libpq/auth.c:892 #, c-format msgid "could not generate random MD5 salt" msgstr "무작위 MD5 솔트 생성 실패" -#: libpq/auth.c:936 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 #, c-format msgid "could not set environment: %m" msgstr "환경변수를 지정할 수 없음: %m" -#: libpq/auth.c:975 +#: libpq/auth.c:982 #, c-format msgid "expected GSS response, got message type %d" msgstr "GSS 응답이 필요한데 메시지 형식 %d을(를) 받음" -#: libpq/auth.c:1041 +#: libpq/auth.c:1048 msgid "accepting GSS security context failed" msgstr "GSS 보안 컨텍스트를 수락하지 못함" -#: libpq/auth.c:1082 +#: libpq/auth.c:1089 msgid "retrieving GSS user name failed" msgstr "GSS 사용자 이름을 검색하지 못함" -#: libpq/auth.c:1228 +#: libpq/auth.c:1235 msgid "could not acquire SSPI credentials" msgstr "SSPI 자격 증명을 가져올 수 없음" -#: libpq/auth.c:1253 +#: libpq/auth.c:1260 #, c-format msgid "expected SSPI response, got message type %d" msgstr "SSPI 응답이 필요한데 메시지 형식 %d을(를) 받음" -#: libpq/auth.c:1331 +#: libpq/auth.c:1338 msgid "could not accept SSPI security context" msgstr "SSPI 보안 컨텍스트를 수락할 수 없음" -#: libpq/auth.c:1372 +#: libpq/auth.c:1379 msgid "could not get token from SSPI security context" msgstr "SSPI 보안 컨텍스트에서 토큰을 가져올 수 없음" -#: libpq/auth.c:1508 libpq/auth.c:1527 +#: libpq/auth.c:1515 libpq/auth.c:1534 #, c-format msgid "could not translate name" msgstr "이름을 변환할 수 없음" -#: libpq/auth.c:1540 +#: libpq/auth.c:1547 #, c-format msgid "realm name too long" msgstr "realm 이름이 너무 긺" -#: libpq/auth.c:1555 +#: libpq/auth.c:1562 #, c-format msgid "translated account name too long" msgstr "변환된 접속자 이름이 너무 깁니다" -#: libpq/auth.c:1734 +#: libpq/auth.c:1741 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "Ident 연결에 소켓을 생성할 수 없습니다: %m" -#: libpq/auth.c:1749 +#: libpq/auth.c:1756 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "로컬 주소 \"%s\"에 바인드할 수 없습니다: %m" -#: libpq/auth.c:1761 +#: libpq/auth.c:1768 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "주소 \"%s\", 포트 %s의 Ident 서버에게 연결할 수 없습니다: %m" -#: libpq/auth.c:1783 +#: libpq/auth.c:1790 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "주소 \"%s\", 포트 %s의 Ident 서버에게 질의를 보낼 수 없습니다: %m" -#: libpq/auth.c:1800 +#: libpq/auth.c:1807 #, c-format msgid "" "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "주소 \"%s\", 포트 %s의 Ident 서버로부터 응답을 받지 못했습니다: %m" -#: libpq/auth.c:1810 +#: libpq/auth.c:1817 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "Ident 서버로부터 잘못된 형태의 응답를 보냈습니다: \"%s\"" -#: libpq/auth.c:1863 +#: libpq/auth.c:1870 #, c-format msgid "peer authentication is not supported on this platform" msgstr "이 플랫폼에서는 peer 인증이 지원되지 않음" -#: libpq/auth.c:1867 +#: libpq/auth.c:1874 #, c-format msgid "could not get peer credentials: %m" msgstr "신뢰성 피어를 얻을 수 없습니다: %m" -#: libpq/auth.c:1879 +#: libpq/auth.c:1886 #, c-format msgid "could not look up local user ID %ld: %s" msgstr "UID %ld 해당하는 사용자를 찾을 수 없음: %s" -#: libpq/auth.c:1981 +#: libpq/auth.c:1988 #, c-format msgid "error from underlying PAM layer: %s" msgstr "잠재적인 PAM 레이어에서의 에러: %s" -#: libpq/auth.c:1992 +#: libpq/auth.c:1999 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "지원하지 않는 PAM conversation %d/\"%s\"" -#: libpq/auth.c:2049 +#: libpq/auth.c:2056 #, c-format msgid "could not create PAM authenticator: %s" msgstr "PAM 인증자를 생성할 수 없습니다: %s" -#: libpq/auth.c:2060 +#: libpq/auth.c:2067 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "pam_set_item(PAM_USER) 실패: %s" -#: libpq/auth.c:2092 +#: libpq/auth.c:2099 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "pam_set_item(PAM_RHOST) 실패: %s" -#: libpq/auth.c:2104 +#: libpq/auth.c:2111 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "pam_set_item(PAM_CONV) 실패: %s" -#: libpq/auth.c:2117 +#: libpq/auth.c:2124 #, c-format msgid "pam_authenticate failed: %s" msgstr "PAM 인증 실패: %s" -#: libpq/auth.c:2130 +#: libpq/auth.c:2137 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "pam_acct_mgmt 실패: %s" -#: libpq/auth.c:2141 +#: libpq/auth.c:2148 #, c-format msgid "could not release PAM authenticator: %s" msgstr "PAM 인증자를 릴리즈할 수 없습니다: %s" -#: libpq/auth.c:2221 +#: libpq/auth.c:2228 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "LDAP 초기화 실패: 오류번호 %d" -#: libpq/auth.c:2258 +#: libpq/auth.c:2265 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "ldapbasedn에서 도메인 이름을 뽑을 수 없음" -#: libpq/auth.c:2266 +#: libpq/auth.c:2273 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "\"%s\"용 LDAP 인증 작업에서 DNS SRV 레코드를 찾을 수 없음" -#: libpq/auth.c:2268 +#: libpq/auth.c:2275 #, c-format msgid "Set an LDAP server name explicitly." msgstr "명시적으로 LDAP 서버 이름을 지정하세요." -#: libpq/auth.c:2320 +#: libpq/auth.c:2327 #, c-format msgid "could not initialize LDAP: %s" msgstr "LDAP 초기화 실패: %s" -#: libpq/auth.c:2330 +#: libpq/auth.c:2337 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "ldap 인증으로 사용할 수 없는 LDAP 라이브러리" -#: libpq/auth.c:2338 +#: libpq/auth.c:2345 #, c-format msgid "could not initialize LDAP: %m" msgstr "LDAP 초기화 실패: %m" -#: libpq/auth.c:2348 +#: libpq/auth.c:2355 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "LDAP 프로토콜 버전을 지정할 수 없음: %s" -#: libpq/auth.c:2364 +#: libpq/auth.c:2371 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "LDAP TLS 세션을 시작할 수 없음: %s" -#: libpq/auth.c:2441 +#: libpq/auth.c:2448 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "LDAP 서버도 ldapbasedn도 지정하지 않았음" -#: libpq/auth.c:2448 +#: libpq/auth.c:2455 #, c-format msgid "LDAP server not specified" msgstr "LDAP 서버가 지정되지 않음" -#: libpq/auth.c:2510 +#: libpq/auth.c:2517 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "LDAP 인증을 위한 사용자 이름에 사용할 수 없는 문자가 있습니다" -#: libpq/auth.c:2527 +#: libpq/auth.c:2534 #, c-format msgid "" "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": " @@ -15638,55 +16149,50 @@ msgstr "" "\"%s\" ldapbinddn (해당 서버: \"%s\") 설정에 대한 LDAP 바인드 초기화를 할 수 " "없음: %s" -#: libpq/auth.c:2557 +#: libpq/auth.c:2564 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "\"%s\" 필터로 LDAP 검색 실패함, 대상 서버: \"%s\": %s" -#: libpq/auth.c:2573 +#: libpq/auth.c:2580 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "\"%s\" LDAP 사용자가 없음" -#: libpq/auth.c:2574 +#: libpq/auth.c:2581 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "\"%s\" 필터로 \"%s\" 서버에서 LDAP 검색을 했으나, 해당 자료가 없음" -#: libpq/auth.c:2578 +#: libpq/auth.c:2585 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "\"%s\" LDAP 사용자가 유일하지 않습니다" -#: libpq/auth.c:2579 +#: libpq/auth.c:2586 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "" "LDAP search for filter \"%s\" on server \"%s\" returned %d entries." msgstr[0] "\"%s\" 필터로 \"%s\" 서버에서 LDAP 검색 결과 %d 항목을 반환함" -#: libpq/auth.c:2599 +#: libpq/auth.c:2606 #, c-format msgid "" "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" msgstr "\"%s\" 첫번째 항목 조회용 dn 값을 \"%s\" 서버에서 찾을 수 없음: %s" -#: libpq/auth.c:2620 -#, c-format -msgid "could not unbind after searching for user \"%s\" on server \"%s\"" -msgstr "\"%s\" 사용자 검색 후 unbind 작업을 \"%s\" 서버에서 할 수 없음" - -#: libpq/auth.c:2651 +#: libpq/auth.c:2633 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "\"%s\" 사용자의 \"%s\" LDAP 서버 로그인 실패: %s" -#: libpq/auth.c:2683 +#: libpq/auth.c:2665 #, c-format msgid "LDAP diagnostics: %s" msgstr "LDAP 진단: %s" -#: libpq/auth.c:2721 +#: libpq/auth.c:2703 #, c-format msgid "" "certificate authentication failed for user \"%s\": client certificate " @@ -15695,14 +16201,14 @@ msgstr "" "\"%s\" 사용자에 대한 인증서 로그인 실패: 클라이언트 인증서에 사용자 이름이 없" "음" -#: libpq/auth.c:2742 +#: libpq/auth.c:2724 #, c-format msgid "" "certificate authentication failed for user \"%s\": unable to retrieve " "subject DN" msgstr "사용자 \"%s\"의 인증서 인증을 실패했습니다: DN 주체가 없음" -#: libpq/auth.c:2765 +#: libpq/auth.c:2747 #, c-format msgid "" "certificate validation (clientcert=verify-full) failed for user \"%s\": DN " @@ -15711,108 +16217,108 @@ msgstr "" "\"%s\" 사용자를 위한 인증서 유효성 검사(clientcert=verify-full)를 실패 함: " "DN 같지 않음" -#: libpq/auth.c:2770 +#: libpq/auth.c:2752 #, c-format msgid "" "certificate validation (clientcert=verify-full) failed for user \"%s\": CN " "mismatch" msgstr "\"%s\" 사용자를 위한 인증서 유효성 검사를 실패 함: CN 같지 않음" -#: libpq/auth.c:2872 +#: libpq/auth.c:2854 #, c-format msgid "RADIUS server not specified" msgstr "RADIUS 서버가 지정되지 않음" -#: libpq/auth.c:2879 +#: libpq/auth.c:2861 #, c-format msgid "RADIUS secret not specified" msgstr "RADIUS 비밀키가 지정되지 않음" -#: libpq/auth.c:2893 +#: libpq/auth.c:2875 #, c-format msgid "" "RADIUS authentication does not support passwords longer than %d characters" msgstr "RADIUS 인증은 %d 글자 보다 큰 비밀번호 인증을 지원하지 않습니다" -#: libpq/auth.c:2995 libpq/hba.c:2369 +#: libpq/auth.c:2977 libpq/hba.c:2352 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "\"%s\" RADIUS 서버 이름을 주소로 바꿀 수 없음: %s" -#: libpq/auth.c:3009 +#: libpq/auth.c:2991 #, c-format msgid "could not generate random encryption vector" msgstr "무작위 암호화 벡터를 만들 수 없음" -#: libpq/auth.c:3046 +#: libpq/auth.c:3028 #, c-format msgid "could not perform MD5 encryption of password: %s" msgstr "비밀번호의 MD5 암호를 만들 수 없음: %s" # translator: %s is IPv4, IPv6, or Unix -#: libpq/auth.c:3073 +#: libpq/auth.c:3055 #, c-format msgid "could not create RADIUS socket: %m" msgstr "RADIUS 소켓을 생성할 수 없습니다: %m" # translator: %s is IPv4, IPv6, or Unix -#: libpq/auth.c:3089 +#: libpq/auth.c:3071 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "RADIUS 소켓에 바인드할 수 없습니다: %m" -#: libpq/auth.c:3099 +#: libpq/auth.c:3081 #, c-format msgid "could not send RADIUS packet: %m" msgstr "RADIUS 패킷을 보낼 수 없음: %m" -#: libpq/auth.c:3133 libpq/auth.c:3159 +#: libpq/auth.c:3115 libpq/auth.c:3141 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "%s 에서 RADIUS 응답 대기 시간 초과" # translator: %s is IPv4, IPv6, or Unix -#: libpq/auth.c:3152 +#: libpq/auth.c:3134 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "RADIUS 소켓 상태를 확인할 수 없음: %m" -#: libpq/auth.c:3182 +#: libpq/auth.c:3164 #, c-format msgid "could not read RADIUS response: %m" msgstr "RADIUS 응답을 읽을 수 없음: %m" -#: libpq/auth.c:3190 +#: libpq/auth.c:3172 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "%s에서 RADIUS 응답이 바르지 않은 포트로부터 보내졌음: %d" -#: libpq/auth.c:3198 +#: libpq/auth.c:3180 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "%s에서 RADIUS 응답이 너무 짧음: %d" -#: libpq/auth.c:3205 +#: libpq/auth.c:3187 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "%s에서 RADIUS 응답 길이가 이상함: %d (실재 길이: %d)" -#: libpq/auth.c:3213 +#: libpq/auth.c:3195 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "%s에서 RADIUS 응답이 요청과 다름: %d (기대값: %d)" -#: libpq/auth.c:3238 +#: libpq/auth.c:3220 #, c-format msgid "could not perform MD5 encryption of received packet: %s" msgstr "받은 패킷을 대상으로 MD5 암호화 작업할 수 없음: %s" -#: libpq/auth.c:3248 +#: libpq/auth.c:3230 #, c-format msgid "RADIUS response from %s has incorrect MD5 signature" msgstr "%s에서 RADIUS 응답의 MD5 값이 이상함" -#: libpq/auth.c:3266 +#: libpq/auth.c:3248 #, c-format msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "%s에서 RADIUS 응답이 바르지 않은 값임 (%d), 대상 사용자: \"%s\"" @@ -15869,51 +16375,38 @@ msgstr "서버 파일 \"%s\"에 쓸 수 없습니다: %m" msgid "large object read request is too large" msgstr "대형 개체 읽기 요청이 너무 큽니다" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:262 utils/adt/genfile.c:294 -#: utils/adt/genfile.c:315 +#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "요청한 길이는 음수일 수 없음" -#: libpq/be-fsstubs.c:871 storage/large_object/inv_api.c:299 -#: storage/large_object/inv_api.c:311 storage/large_object/inv_api.c:508 -#: storage/large_object/inv_api.c:619 storage/large_object/inv_api.c:809 -#, c-format -msgid "permission denied for large object %u" -msgstr "%u 대형 개체에 대한 접근 권한 없음" - -#: libpq/be-secure-common.c:71 -#, c-format -msgid "could not read from command \"%s\": %m" -msgstr "\"%s\" 명령에서 읽을 수 없음: %m" - -#: libpq/be-secure-common.c:91 +#: libpq/be-secure-common.c:94 #, c-format msgid "command \"%s\" failed" msgstr "\"%s\" 명령 실패" -#: libpq/be-secure-common.c:119 +#: libpq/be-secure-common.c:123 #, c-format msgid "could not access private key file \"%s\": %m" msgstr "비밀키 \"%s\"에 액세스할 수 없습니다: %m" -#: libpq/be-secure-common.c:129 +#: libpq/be-secure-common.c:133 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "\"%s\" 개인 키 파일은 일반 파일이 아님" -#: libpq/be-secure-common.c:155 +#: libpq/be-secure-common.c:159 #, c-format msgid "private key file \"%s\" must be owned by the database user or root" msgstr "" "\"%s\" 개인 키 파일의 소유주는 데이터베이스 사용자이거나 root 여야 합니다." -#: libpq/be-secure-common.c:165 +#: libpq/be-secure-common.c:169 #, c-format msgid "private key file \"%s\" has group or world access" msgstr "\"%s\" 개인 키 파일에 그룹 또는 익명 액세스 권한이 있음" -#: libpq/be-secure-common.c:167 +#: libpq/be-secure-common.c:171 #, c-format msgid "" "File must have permissions u=rw (0600) or less if owned by the database " @@ -15923,16 +16416,16 @@ msgstr "" "(0600) 또는 더 작게 설정하고, root가 소유주라면 u=rw,g=r (0640) 권한으로 지정" "하세요" -#: libpq/be-secure-gssapi.c:204 +#: libpq/be-secure-gssapi.c:201 msgid "GSSAPI wrap error" msgstr "GSSAPI 감싸기 오류" -#: libpq/be-secure-gssapi.c:211 +#: libpq/be-secure-gssapi.c:208 #, c-format msgid "outgoing GSSAPI message would not use confidentiality" msgstr "GSSAPI 출력 메시지는 기밀성을 유지하면 안됩니다." -#: libpq/be-secure-gssapi.c:218 libpq/be-secure-gssapi.c:634 +#: libpq/be-secure-gssapi.c:215 libpq/be-secure-gssapi.c:634 #, c-format msgid "server tried to send oversize GSSAPI packet (%zu > %zu)" msgstr "서버가 너무 큰 GSSAPI 패킷을 보내려고 합니다(%zu > %zu)." @@ -15964,17 +16457,17 @@ msgstr "GSSAPI 보안 내용을 받아드릴 수 없음" msgid "GSSAPI size check error" msgstr "GSSAPI 크기 검사 오류" -#: libpq/be-secure-openssl.c:125 +#: libpq/be-secure-openssl.c:131 #, c-format msgid "could not create SSL context: %s" msgstr "SSL 컨텍스트 정보를 생성할 수 없습니다: %s" -#: libpq/be-secure-openssl.c:151 +#: libpq/be-secure-openssl.c:157 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "서버 인증서 파일 \"%s\"을 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:171 +#: libpq/be-secure-openssl.c:177 #, c-format msgid "" "private key file \"%s\" cannot be reloaded because it requires a passphrase" @@ -15982,102 +16475,102 @@ msgstr "" "\"%s\" 개인 키 파일은 비밀번호를 입력해야 해서 자동으로 다시 불러올 수 없습니" "다." -#: libpq/be-secure-openssl.c:176 +#: libpq/be-secure-openssl.c:182 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "비밀키 파일 \"%s\"을 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:185 +#: libpq/be-secure-openssl.c:191 #, c-format msgid "check of private key failed: %s" msgstr "비밀키의 확인 실패: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:198 libpq/be-secure-openssl.c:221 +#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "\"%s\" 의 \"%s\" 설정 기능을 빼고 빌드 되었음" -#: libpq/be-secure-openssl.c:208 +#: libpq/be-secure-openssl.c:214 #, c-format msgid "could not set minimum SSL protocol version" msgstr "최소 SSL 프로토콜 버전을 설정할 수 없음" -#: libpq/be-secure-openssl.c:231 +#: libpq/be-secure-openssl.c:237 #, c-format msgid "could not set maximum SSL protocol version" msgstr "최대 SSL 프로토콜 버전을 설정할 수 없음" -#: libpq/be-secure-openssl.c:247 +#: libpq/be-secure-openssl.c:253 #, c-format msgid "could not set SSL protocol version range" msgstr "SSL 프로토콜 버전 범위를 지정할 수 없음" -#: libpq/be-secure-openssl.c:248 +#: libpq/be-secure-openssl.c:254 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "\"%s\" 값은 \"%s\" 보다 높을 수 없음" -#: libpq/be-secure-openssl.c:285 +#: libpq/be-secure-openssl.c:307 #, c-format msgid "could not set the cipher list (no valid ciphers available)" msgstr "cipher 목록을 설정할 수 없음 (유요한 cipher가 없음)" -#: libpq/be-secure-openssl.c:305 +#: libpq/be-secure-openssl.c:327 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "root 인증서 파일 \"%s\"을 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:354 +#: libpq/be-secure-openssl.c:376 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "\"%s\" SSL 인증서 회수 목록 파일을 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:362 +#: libpq/be-secure-openssl.c:384 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "\"%s\" SSL 인증서 회수 목록 디렉터리를 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:370 +#: libpq/be-secure-openssl.c:392 #, c-format msgid "" -"could not load SSL certificate revocation list file \"%s\" or directory \"%s" -"\": %s" +"could not load SSL certificate revocation list file \"%s\" or directory " +"\"%s\": %s" msgstr "" "\"%s\" SSL 인증서 회수 목록 파일이나 \"%s\" 디렉터리를 불러들일 수 없습니다: " "%s" -#: libpq/be-secure-openssl.c:428 +#: libpq/be-secure-openssl.c:450 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "SSL연결을 초기화할 수 없습니다: SSL 컨텍스트를 설정 못함" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:464 #, c-format msgid "could not initialize SSL connection: %s" msgstr "SSL연결을 초기화할 수 없습니다: %s" -#: libpq/be-secure-openssl.c:447 +#: libpq/be-secure-openssl.c:472 #, c-format msgid "could not set SSL socket: %s" msgstr "SSL 소켓을 지정할 수 없습니다: %s" -#: libpq/be-secure-openssl.c:502 +#: libpq/be-secure-openssl.c:528 #, c-format msgid "could not accept SSL connection: %m" msgstr "SSL 연결을 받아드릴 수 없습니다: %m" -#: libpq/be-secure-openssl.c:506 libpq/be-secure-openssl.c:561 +#: libpq/be-secure-openssl.c:532 libpq/be-secure-openssl.c:589 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "SSL 연결을 받아드릴 수 없습니다: EOF 감지됨" -#: libpq/be-secure-openssl.c:545 +#: libpq/be-secure-openssl.c:573 #, c-format msgid "could not accept SSL connection: %s" msgstr "SSL 연결을 받아드릴 수 없습니다: %s" -#: libpq/be-secure-openssl.c:549 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "" "This may indicate that the client does not support any SSL protocol version " @@ -16086,359 +16579,359 @@ msgstr "" "이런 경우는 클라이언트가 %s부터 %s까지 SSL 프로토콜 버전을 지원하지 않는 경우" "에 발생하기도 합니다." -#: libpq/be-secure-openssl.c:566 libpq/be-secure-openssl.c:746 -#: libpq/be-secure-openssl.c:810 +#: libpq/be-secure-openssl.c:594 libpq/be-secure-openssl.c:809 +#: libpq/be-secure-openssl.c:879 #, c-format msgid "unrecognized SSL error code: %d" msgstr "인식되지 않은 SSL 에러 코드 %d" -#: libpq/be-secure-openssl.c:612 +#: libpq/be-secure-openssl.c:622 +#, c-format +msgid "received SSL connection request with unexpected ALPN protocol" +msgstr "수신된 SSL 연결은 예상치 않은 ALPN 프로토콜을 요구함" + +#: libpq/be-secure-openssl.c:666 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "SSL 인증서의 일반 이름에 포함된 null이 있음" -#: libpq/be-secure-openssl.c:652 +#: libpq/be-secure-openssl.c:712 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "SSL 인증서의 식별자 이름에 포함된 null이 있음" -#: libpq/be-secure-openssl.c:735 libpq/be-secure-openssl.c:794 +#: libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:863 #, c-format msgid "SSL error: %s" msgstr "SSL 에러: %s" -#: libpq/be-secure-openssl.c:976 +#: libpq/be-secure-openssl.c:1038 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "\"%s\" DH 매개 변수 파일을 열 수 없습니다: %m" -#: libpq/be-secure-openssl.c:988 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not load DH parameters file: %s" msgstr "DH 매개 변수 파일을 불러들일 수 없습니다: %s" -#: libpq/be-secure-openssl.c:998 +#: libpq/be-secure-openssl.c:1060 #, c-format msgid "invalid DH parameters: %s" msgstr "잘못된 DH 매개 변수: %s" -#: libpq/be-secure-openssl.c:1007 +#: libpq/be-secure-openssl.c:1069 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "잘못된 DH 매개 변수값: p는 prime 아님" -#: libpq/be-secure-openssl.c:1016 +#: libpq/be-secure-openssl.c:1078 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "잘못된 DH 매개 변수값: 타당한 생성자도 아니고, 안전한 prime도 아님" -#: libpq/be-secure-openssl.c:1152 +#: libpq/be-secure-openssl.c:1214 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "%d 번째 깊이에서 클라이언트 인증서 유효성 검사 실패: %s." -#: libpq/be-secure-openssl.c:1189 +#: libpq/be-secure-openssl.c:1251 #, c-format msgid "" "Failed certificate data (unverified): subject \"%s\", serial number %s, " "issuer \"%s\"." msgstr "" -"데이터 인증 실패 (검증 안됨): subject \"%s\", serial number %s, issuer \"%s" -"\"." +"데이터 인증 실패 (검증 안됨): subject \"%s\", serial number %s, issuer " +"\"%s\"." -#: libpq/be-secure-openssl.c:1190 +#: libpq/be-secure-openssl.c:1252 msgid "unknown" msgstr "알수없음" -#: libpq/be-secure-openssl.c:1281 +#: libpq/be-secure-openssl.c:1389 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: DH 매개 변수 불러오기 실패" -#: libpq/be-secure-openssl.c:1289 +#: libpq/be-secure-openssl.c:1397 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: DH 매개 변수 설정 실패: %s" -#: libpq/be-secure-openssl.c:1316 +#: libpq/be-secure-openssl.c:1424 #, c-format msgid "ECDH: unrecognized curve name: %s" msgstr "ECDH: 알 수 없는 curve 이름: %s" -#: libpq/be-secure-openssl.c:1325 +#: libpq/be-secure-openssl.c:1433 #, c-format msgid "ECDH: could not create key" msgstr "ECDH: 키 생성 실패" -#: libpq/be-secure-openssl.c:1353 +#: libpq/be-secure-openssl.c:1461 msgid "no SSL error reported" msgstr "SSL 오류 없음" -#: libpq/be-secure-openssl.c:1357 +#: libpq/be-secure-openssl.c:1479 #, c-format msgid "SSL error code %lu" msgstr "SSL 오류 번호 %lu" -#: libpq/be-secure-openssl.c:1516 +#: libpq/be-secure-openssl.c:1636 #, c-format msgid "could not create BIO" msgstr "BIO 만들기 실패" -#: libpq/be-secure-openssl.c:1526 +#: libpq/be-secure-openssl.c:1646 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "ASN1_OBJECT 객체용 NID 구할 수 없음" -#: libpq/be-secure-openssl.c:1534 +#: libpq/be-secure-openssl.c:1654 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "ASN1_OBJECT 구조체에서 %d NID를 변환할 수 없음" -#: libpq/be-secure.c:207 libpq/be-secure.c:303 -#, c-format -msgid "terminating connection due to unexpected postmaster exit" -msgstr "postmaster의 예상치 못한 종료로 연결을 종료합니다" - -#: libpq/crypt.c:49 +#: libpq/crypt.c:48 #, c-format msgid "Role \"%s\" does not exist." msgstr "\"%s\" 롤 없음" -#: libpq/crypt.c:59 +#: libpq/crypt.c:58 #, c-format msgid "User \"%s\" has no password assigned." msgstr "\"%s\" 사용자 비밀번호가 아직 할당되지 않음" -#: libpq/crypt.c:77 +#: libpq/crypt.c:76 #, c-format msgid "User \"%s\" has an expired password." msgstr "\"%s\" 사용자 비밀번호가 기한 만료되었습니다." -#: libpq/crypt.c:183 +#: libpq/crypt.c:182 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "\"%s\" 사용자의 비밀번호는 MD5 인증용이 아닙니다." -#: libpq/crypt.c:204 libpq/crypt.c:246 libpq/crypt.c:266 +#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 #, c-format msgid "Password does not match for user \"%s\"." msgstr "\"%s\" 사용자의 비밀번호가 틀립니다." -#: libpq/crypt.c:285 +#: libpq/crypt.c:284 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "\"%s\" 사용자의 비밀번호 암호화 기법을 알 수 없습니다." -#: libpq/hba.c:332 +#: libpq/hba.c:327 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "\"%s\" 정규식이 잘못됨: %s" -#: libpq/hba.c:334 libpq/hba.c:666 libpq/hba.c:1250 libpq/hba.c:1270 -#: libpq/hba.c:1293 libpq/hba.c:1306 libpq/hba.c:1359 libpq/hba.c:1387 -#: libpq/hba.c:1395 libpq/hba.c:1407 libpq/hba.c:1428 libpq/hba.c:1441 -#: libpq/hba.c:1466 libpq/hba.c:1493 libpq/hba.c:1505 libpq/hba.c:1564 -#: libpq/hba.c:1584 libpq/hba.c:1598 libpq/hba.c:1618 libpq/hba.c:1629 -#: libpq/hba.c:1644 libpq/hba.c:1663 libpq/hba.c:1679 libpq/hba.c:1691 -#: libpq/hba.c:1728 libpq/hba.c:1769 libpq/hba.c:1782 libpq/hba.c:1804 -#: libpq/hba.c:1816 libpq/hba.c:1834 libpq/hba.c:1884 libpq/hba.c:1928 -#: libpq/hba.c:1939 libpq/hba.c:1955 libpq/hba.c:1972 libpq/hba.c:1983 -#: libpq/hba.c:2002 libpq/hba.c:2018 libpq/hba.c:2034 libpq/hba.c:2093 -#: libpq/hba.c:2110 libpq/hba.c:2123 libpq/hba.c:2135 libpq/hba.c:2154 -#: libpq/hba.c:2240 libpq/hba.c:2258 libpq/hba.c:2352 libpq/hba.c:2371 -#: libpq/hba.c:2400 libpq/hba.c:2413 libpq/hba.c:2436 libpq/hba.c:2458 -#: libpq/hba.c:2472 tsearch/ts_locale.c:243 +#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 +#: libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 +#: libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 +#: libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 +#: libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 +#: libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 +#: libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 libpq/hba.c:1799 +#: libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 +#: libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 +#: libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 +#: libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 +#: libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 +#: libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 +#: tsearch/ts_locale.c:241 #, c-format msgid "line %d of configuration file \"%s\"" msgstr "%d번째 줄(\"%s\" 환경 설정 파일)" -#: libpq/hba.c:462 +#: libpq/hba.c:457 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "\"%s\" 인증 설정파일이 없으나 건너뜀" -#: libpq/hba.c:614 +#: libpq/hba.c:609 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "\"%s\" 파일을 열 수 없습니다: 최대 디렉터리 깊이를 초과했음" -#: libpq/hba.c:1221 +#: libpq/hba.c:1216 #, c-format msgid "error enumerating network interfaces: %m" msgstr "네트워크 인터페이스 이뮬레이트 하기 실패: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1248 +#: libpq/hba.c:1243 #, c-format msgid "" "authentication option \"%s\" is only valid for authentication methods %s" msgstr "\"%s\" 인증 옵션은 %s 인증 방법에만 유효함" -#: libpq/hba.c:1268 +#: libpq/hba.c:1263 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "\"%s\" 인증 방법의 경우 \"%s\" 인자를 설정해야 함" -#: libpq/hba.c:1292 +#: libpq/hba.c:1287 #, c-format msgid "missing entry at end of line" msgstr "줄의 끝 라인에 빠진 엔트리가 있음" -#: libpq/hba.c:1305 +#: libpq/hba.c:1300 #, c-format msgid "multiple values in ident field" msgstr "ident 자리에 여러 값이 있음" -#: libpq/hba.c:1357 +#: libpq/hba.c:1352 #, c-format msgid "multiple values specified for connection type" msgstr "연결 형식 자리에 여러 값이 있음" -#: libpq/hba.c:1358 +#: libpq/hba.c:1353 #, c-format msgid "Specify exactly one connection type per line." msgstr "한 줄에 하나의 연결 형태만 지정해야 합니다" -#: libpq/hba.c:1385 +#: libpq/hba.c:1380 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "SSL 기능이 꺼져있어 hostssl 설정을 사용할 수 없습니다" -#: libpq/hba.c:1386 +#: libpq/hba.c:1381 #, c-format -msgid "Set ssl = on in postgresql.conf." -msgstr "postgresql.conf 파일에 ssl = on 설정을 하세요." +msgid "Set \"ssl = on\" in postgresql.conf." +msgstr "postgresql.conf 파일에 \"ssl = on\" 설정을 하세요." -#: libpq/hba.c:1394 +#: libpq/hba.c:1389 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "" "이 서버는 ssl 접속 기능을 지원하지 않아 hostssl 인증을 지원하지 않습니다." -#: libpq/hba.c:1406 +#: libpq/hba.c:1401 #, c-format msgid "" "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "" "이 서버는 GSSAPI 접속 기능을 지원하지 않아 hostgssenc 레코드가 적당하지 않음" -#: libpq/hba.c:1426 +#: libpq/hba.c:1421 #, c-format msgid "invalid connection type \"%s\"" msgstr "\"%s\" 값은 잘못된 연결 형식입니다" -#: libpq/hba.c:1440 +#: libpq/hba.c:1435 #, c-format msgid "end-of-line before database specification" msgstr "데이터베이스 지정 전에 줄 끝에 도달함" -#: libpq/hba.c:1465 +#: libpq/hba.c:1460 #, c-format msgid "end-of-line before role specification" msgstr "롤 지정 전에 줄 끝에 도달함" -#: libpq/hba.c:1492 +#: libpq/hba.c:1487 #, c-format msgid "end-of-line before IP address specification" msgstr "IP 주소 지정 전에 줄 끝에 도달함" -#: libpq/hba.c:1503 +#: libpq/hba.c:1498 #, c-format msgid "multiple values specified for host address" msgstr "호스트 주소 부분에 여러 값이 지정됨" -#: libpq/hba.c:1504 +#: libpq/hba.c:1499 #, c-format msgid "Specify one address range per line." msgstr "한 줄에 하나의 주소 범위가 있어야 합니다." -#: libpq/hba.c:1562 +#: libpq/hba.c:1557 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "\"%s\" 형태는 잘못된 IP 주소 형태입니다: %s" -#: libpq/hba.c:1582 +#: libpq/hba.c:1577 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "호스트 이름과 CIDR 마스크는 함께 쓸 수 없습니다: \"%s\"" -#: libpq/hba.c:1596 +#: libpq/hba.c:1591 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "\"%s\" 주소에 잘못된 CIDR 마스크가 있음" -#: libpq/hba.c:1616 +#: libpq/hba.c:1611 #, c-format msgid "end-of-line before netmask specification" msgstr "넷마스크 지정 전에 줄 끝에 도달함" -#: libpq/hba.c:1617 +#: libpq/hba.c:1612 #, c-format msgid "" "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "주소 범위는 CIDR 표기법을 쓰거나 넷마스크 표기법을 쓰세요" -#: libpq/hba.c:1628 +#: libpq/hba.c:1623 #, c-format msgid "multiple values specified for netmask" msgstr "넷마스크 부분에 여러 값이 지정됨" -#: libpq/hba.c:1642 +#: libpq/hba.c:1637 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "잘못된 IP 마스크, \"%s\": %s" -#: libpq/hba.c:1662 +#: libpq/hba.c:1657 #, c-format msgid "IP address and mask do not match" msgstr "IP 주소와 마스크가 맞지 않습니다" -#: libpq/hba.c:1678 +#: libpq/hba.c:1673 #, c-format msgid "end-of-line before authentication method" msgstr "인증 방법 전에 줄 끝에 도달함" -#: libpq/hba.c:1689 +#: libpq/hba.c:1684 #, c-format msgid "multiple values specified for authentication type" msgstr "인증 방법 부분에 여러 값이 지정됨" -#: libpq/hba.c:1690 +#: libpq/hba.c:1685 #, c-format msgid "Specify exactly one authentication type per line." msgstr "하나의 인증 방법에 대해서 한 줄씩 지정해야 합니다" -#: libpq/hba.c:1767 +#: libpq/hba.c:1750 #, c-format msgid "invalid authentication method \"%s\"" msgstr "\"%s\" 인증 방법이 잘못됨" -#: libpq/hba.c:1780 +#: libpq/hba.c:1763 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "\"%s\" 인증 방법이 잘못됨: 이 서버에서 지원되지 않음" -#: libpq/hba.c:1803 +#: libpq/hba.c:1786 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "gssapi 인증은 로컬 소켓에서 지원되지 않음" -#: libpq/hba.c:1815 +#: libpq/hba.c:1798 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "peer 인증은 로컬 소켓에서만 지원함" -#: libpq/hba.c:1833 +#: libpq/hba.c:1816 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "cert 인증은 hostssl 연결에서만 지원됨" -#: libpq/hba.c:1883 +#: libpq/hba.c:1866 #, c-format msgid "authentication option not in name=value format: %s" msgstr "인증 옵션이 이름=값 형태가 아님: %s" -#: libpq/hba.c:1927 +#: libpq/hba.c:1910 #, c-format msgid "" "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, " @@ -16447,31 +16940,31 @@ msgstr "" "ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, " "ldapsearchfilter, ldapurl 옵션은 ldapprefix 옵션과 함께 사용할 수 없음" -#: libpq/hba.c:1938 +#: libpq/hba.c:1921 #, c-format msgid "" -"authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix" -"\", or \"ldapsuffix\" to be set" +"authentication method \"ldap\" requires argument \"ldapbasedn\", " +"\"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "" "\"ldap\" 인증 방법의 경우 \"ldapbasedn\", \"ldapprefix\", \"ldapsuffix\"옵션" "이 있어야 함" -#: libpq/hba.c:1954 +#: libpq/hba.c:1937 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "ldapsearchattribute 옵션은 ldapsearchfilter 옵션과 함께 사용할 수 없음" -#: libpq/hba.c:1971 +#: libpq/hba.c:1954 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "RADIUS 서버 목록은 비어 있을 수 없음" -#: libpq/hba.c:1982 +#: libpq/hba.c:1965 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "RADIUS 비밀키 목록은 비어 있을 수 없음" -#: libpq/hba.c:1999 +#: libpq/hba.c:1982 #, c-format msgid "" "the number of RADIUS secrets (%d) must be 1 or the same as the number of " @@ -16479,209 +16972,217 @@ msgid "" msgstr "" "RADIUS 비밀번호 개수(%d)는 하나이거나, RADIUS 서버 개수(%d)와 같아야 함" -#: libpq/hba.c:2015 +#: libpq/hba.c:1998 #, c-format msgid "" "the number of RADIUS ports (%d) must be 1 or the same as the number of " "RADIUS servers (%d)" msgstr "RADIUS 포트 개수(%d)는 하나이거나, RADIUS 서버 개수(%d)와 같아야 함" -#: libpq/hba.c:2031 +#: libpq/hba.c:2014 #, c-format msgid "" "the number of RADIUS identifiers (%d) must be 1 or the same as the number of " "RADIUS servers (%d)" msgstr "RADIUS 계정 개수(%d)는 하나이거나, RADIUS 서버 개수(%d)와 같아야 함" -#: libpq/hba.c:2083 +#: libpq/hba.c:2066 msgid "ident, peer, gssapi, sspi, and cert" msgstr "ident, peer, gssapi, sspi 및 cert" -#: libpq/hba.c:2092 +#: libpq/hba.c:2075 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert는 \"hostssl\" 행에 대해서만 구성할 수 있음" -#: libpq/hba.c:2109 +#: libpq/hba.c:2092 #, c-format msgid "" "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "" "\"cert\" 인증을 사용하는 경우 clientcert 값은 \"verify-full\" 만 허용함" -#: libpq/hba.c:2122 +#: libpq/hba.c:2105 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "잘못된 clientcert 값: \"%s\"" -#: libpq/hba.c:2134 +#: libpq/hba.c:2117 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname 설정은 \"hostssl\" 줄에만 지정할 수 있음" -#: libpq/hba.c:2153 +#: libpq/hba.c:2136 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "잘못된 clientname 값: \"%s\"" -#: libpq/hba.c:2186 +#: libpq/hba.c:2169 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "\"%s\" LDAP URL을 분석할 수 없음: %s" -#: libpq/hba.c:2197 +#: libpq/hba.c:2180 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "지원하지 않는 LDAP URL 스킴: %s" -#: libpq/hba.c:2221 +#: libpq/hba.c:2204 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "이 플랫폼에서는 LDAP URL 기능을 지원하지 않음." -#: libpq/hba.c:2239 +#: libpq/hba.c:2222 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "잘못된 ldapscheme 값: \"%s\"" -#: libpq/hba.c:2257 +#: libpq/hba.c:2240 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "LDAP 포트 번호가 잘못됨: \"%s\"" -#: libpq/hba.c:2303 libpq/hba.c:2310 +#: libpq/hba.c:2286 libpq/hba.c:2293 msgid "gssapi and sspi" msgstr "gssapi 및 sspi" -#: libpq/hba.c:2319 libpq/hba.c:2328 +#: libpq/hba.c:2302 libpq/hba.c:2311 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2350 +#: libpq/hba.c:2333 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "RADIUS 서버 목록 분석 실패: \"%s\"" -#: libpq/hba.c:2398 +#: libpq/hba.c:2381 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "RADIUS 서버 포트 목록 분석 실패: \"%s\"" -#: libpq/hba.c:2412 +#: libpq/hba.c:2395 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "RADIUS 포트 번호가 잘못됨: \"%s\"" # translator: %s is IPv4, IPv6, or Unix -#: libpq/hba.c:2434 +#: libpq/hba.c:2417 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "RADIUS 서버 비밀키 목록 분석 실패: \"%s\"" -#: libpq/hba.c:2456 +#: libpq/hba.c:2439 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "RADIUS 서버 식별자 목록 분석 실패: \"%s\"" -#: libpq/hba.c:2470 +#: libpq/hba.c:2453 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "알 수 없는 인증 옵션 이름: \"%s\"" -#: libpq/hba.c:2662 +#: libpq/hba.c:2645 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "\"%s\" 설정 파일에 구성 항목이 없음" -#: libpq/hba.c:2815 +#: libpq/hba.c:2798 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "\"%s\"에 대한 정규식 일치 실패: %s" -#: libpq/hba.c:2839 +#: libpq/hba.c:2822 #, c-format msgid "" "regular expression \"%s\" has no subexpressions as requested by " "backreference in \"%s\"" msgstr "\"%s\" 정규식에는 \"%s\"의 backreference에서 요청된 하위 식이 없음" -#: libpq/hba.c:2942 +#: libpq/hba.c:2925 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "제공된 사용자 이름(%s) 및 인증된 사용자 이름(%s)이 일치하지 않음" -#: libpq/hba.c:2962 +#: libpq/hba.c:2945 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "" "\"%s\" 사용자맵 파일에 \"%s\" 사용자를 \"%s\" 사용자로 인증할 설정이 없음" -#: libpq/pqcomm.c:200 +#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 +#: libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 +#: libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 +#: libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#, c-format +msgid "%s(%s) failed: %m" +msgstr "%s(%s) 실패: %m" + +#: libpq/pqcomm.c:296 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "소켓을 nonblocking 모드로 지정할 수 없음: %m" -#: libpq/pqcomm.c:361 +#: libpq/pqcomm.c:456 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "\"%s\" 유닉스 도메인 소켓 경로가 너무 깁니다 (최대 %d 바이트)" -#: libpq/pqcomm.c:381 +#: libpq/pqcomm.c:476 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "호스트 이름 \"%s\", 서비스 \"%s\"를 변환할 수 없습니다. 주소 : %s" -#: libpq/pqcomm.c:385 +#: libpq/pqcomm.c:480 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "서비스 \"%s\"를 변환할 수 없습니다. 주소 : %s" -#: libpq/pqcomm.c:412 +#: libpq/pqcomm.c:502 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "최대 접속자 수 MAXLISTEN (%d) 초과로 더 이상 접속이 불가능합니다" -#: libpq/pqcomm.c:421 +#: libpq/pqcomm.c:511 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:424 +#: libpq/pqcomm.c:514 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:427 +#: libpq/pqcomm.c:517 msgid "Unix" msgstr "유닉스" -#: libpq/pqcomm.c:431 +#: libpq/pqcomm.c:521 #, c-format msgid "unrecognized address family %d" msgstr "%d는 인식되지 않는 가족 주소입니다" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:455 +#: libpq/pqcomm.c:545 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "%s 소켓 만들기 실패, 대상 주소: \"%s\": %m" #. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:481 libpq/pqcomm.c:499 +#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%s(%s) 실패, 연결 종류: %s, 대상 주소: \"%s\": %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:522 +#: libpq/pqcomm.c:615 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "%s 바인드 실패, 대상 주소: \"%s\": %m" -#: libpq/pqcomm.c:526 +#: libpq/pqcomm.c:619 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "다른 postmaster 가 포트 %d에서 이미 실행중인것 같습니다?" -#: libpq/pqcomm.c:528 +#: libpq/pqcomm.c:621 #, c-format msgid "" "Is another postmaster already running on port %d? If not, wait a few seconds " @@ -16691,131 +17192,123 @@ msgstr "" "를 기다렸다가 다시 시도해보십시오." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:557 +#: libpq/pqcomm.c:650 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "%s 리슨 실패, 대상 주소: \"%s\": %m" # translator: %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:565 +#: libpq/pqcomm.c:658 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "\"%s\" 유닉스 도메인 소켓으로 접속을 허용합니다" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:570 +#: libpq/pqcomm.c:663 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "%s, 주소: \"%s\", 포트 %d 번으로 접속을 허용합니다" -#: libpq/pqcomm.c:659 +#: libpq/pqcomm.c:753 #, c-format msgid "group \"%s\" does not exist" msgstr "\"%s\" 그룹 없음" -#: libpq/pqcomm.c:669 +#: libpq/pqcomm.c:763 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "파일 \"%s\" 의 그룹을 세팅할 수 없습니다: %m" -#: libpq/pqcomm.c:680 +#: libpq/pqcomm.c:774 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "파일 \"%s\" 의 퍼미션을 세팅할 수 없습니다: %m" -#: libpq/pqcomm.c:708 +#: libpq/pqcomm.c:803 #, c-format msgid "could not accept new connection: %m" msgstr "새로운 연결을 생성할 수 없습니다: %m" -#: libpq/pqcomm.c:748 libpq/pqcomm.c:757 libpq/pqcomm.c:789 libpq/pqcomm.c:799 -#: libpq/pqcomm.c:1624 libpq/pqcomm.c:1669 libpq/pqcomm.c:1709 -#: libpq/pqcomm.c:1753 libpq/pqcomm.c:1792 libpq/pqcomm.c:1831 -#: libpq/pqcomm.c:1867 libpq/pqcomm.c:1906 -#, c-format -msgid "%s(%s) failed: %m" -msgstr "%s(%s) 실패: %m" - -#: libpq/pqcomm.c:903 +#: libpq/pqcomm.c:885 #, c-format msgid "there is no client connection" msgstr "클라이언트 연결이 없음" -#: libpq/pqcomm.c:954 libpq/pqcomm.c:1050 +#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 #, c-format msgid "could not receive data from client: %m" msgstr "클라이언트에게 데이터를 받을 수 없습니다: %m" -#: libpq/pqcomm.c:1155 tcop/postgres.c:4405 +#: libpq/pqcomm.c:1149 tcop/postgres.c:4533 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "프로토콜 동기화 작업 실패로 연결을 종료합니다" -#: libpq/pqcomm.c:1221 +#: libpq/pqcomm.c:1215 #, c-format msgid "unexpected EOF within message length word" msgstr "예상치 못한 EOF가 메시지의 길이 워드안에서 발생했습니다." -#: libpq/pqcomm.c:1231 +#: libpq/pqcomm.c:1225 #, c-format msgid "invalid message length" msgstr "메시지의 길이가 유효하지 않습니다" -#: libpq/pqcomm.c:1253 libpq/pqcomm.c:1266 +#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 #, c-format msgid "incomplete message from client" msgstr "클라이언트으로부터의 완전하지 못한 메시지입니다" -#: libpq/pqcomm.c:1377 +#: libpq/pqcomm.c:1401 #, c-format msgid "could not send data to client: %m" msgstr "클라이언트에게 데이터를 보낼 수 없습니다: %m" -#: libpq/pqcomm.c:1592 +#: libpq/pqcomm.c:1616 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) 실패: 오류 코드 %d" -#: libpq/pqcomm.c:1681 +#: libpq/pqcomm.c:1705 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "keepalive idle time 지정하는 것은 지원하지 않음" -#: libpq/pqcomm.c:1765 libpq/pqcomm.c:1840 libpq/pqcomm.c:1915 +#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s) 지원하지 않음" -#: libpq/pqformat.c:407 +#: libpq/pqformat.c:404 #, c-format msgid "no data left in message" msgstr "메시지에 아무런 데이터가 없습니다" -#: libpq/pqformat.c:518 libpq/pqformat.c:536 libpq/pqformat.c:557 -#: utils/adt/array_userfuncs.c:799 utils/adt/arrayfuncs.c:1506 -#: utils/adt/rowtypes.c:615 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 +#: utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 +#: utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "부족한 데이터는 메시지 안에 넣어져 있습니다" -#: libpq/pqformat.c:598 libpq/pqformat.c:627 +#: libpq/pqformat.c:595 libpq/pqformat.c:624 #, c-format msgid "invalid string in message" msgstr "메시지안에 유효하지 않은 문자열이 있습니다" -#: libpq/pqformat.c:643 +#: libpq/pqformat.c:640 #, c-format msgid "invalid message format" msgstr "메시지 포맷이 유효하지 않습니다." # # search5 끝 # # advance 부분 -#: main/main.c:235 +#: main/main.c:236 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: WSAStartup 작업 실패: %d\n" -#: main/main.c:329 +#: main/main.c:324 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -16824,7 +17317,7 @@ msgstr "" "%s 프로그램은 PostgreSQL 서버입니다.\n" "\n" -#: main/main.c:330 +#: main/main.c:325 #, c-format msgid "" "Usage:\n" @@ -16835,107 +17328,107 @@ msgstr "" " %s [옵션]...\n" "\n" -#: main/main.c:331 +#: main/main.c:326 #, c-format msgid "Options:\n" msgstr "옵션들:\n" -#: main/main.c:332 +#: main/main.c:327 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS 공유 버퍼 개수\n" -#: main/main.c:333 +#: main/main.c:328 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c NAME=VALUE 실시간 매개 변수 지정\n" -#: main/main.c:334 +#: main/main.c:329 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C NAME 실시간 매개 변수 값을 보여주고 마침\n" -#: main/main.c:335 +#: main/main.c:330 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 디버깅 수준\n" -#: main/main.c:336 +#: main/main.c:331 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR 데이터 디렉터리\n" -#: main/main.c:337 +#: main/main.c:332 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e 날짜 입력 양식이 유럽형(DMY)을 사용함\n" -#: main/main.c:338 +#: main/main.c:333 #, c-format msgid " -F turn fsync off\n" msgstr " -F fsync 기능 끔\n" -#: main/main.c:339 +#: main/main.c:334 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h HOSTNAME 서버로 사용할 호스트 이름 또는 IP\n" -#: main/main.c:340 +#: main/main.c:335 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr " -i TCP/IP 연결 사용함 (옛 버전 호환용)\n" -#: main/main.c:341 +#: main/main.c:336 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k DIRECTORY 유닉스 도메인 소켓 위치\n" -#: main/main.c:343 +#: main/main.c:338 #, c-format msgid " -l enable SSL connections\n" msgstr " -l SSL 연결 기능 사용함\n" -#: main/main.c:345 +#: main/main.c:340 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N MAX-CONNECT 최대 동시 연결 개수\n" -#: main/main.c:346 +#: main/main.c:341 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p PORT 서버 포트 번호\n" -#: main/main.c:347 +#: main/main.c:342 #, c-format msgid " -s show statistics after each query\n" msgstr " -s 각 쿼리 뒤에 통계정보를 보여줌\n" -#: main/main.c:348 +#: main/main.c:343 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S WORK-MEM 정렬작업에 사용할 메모리 크기(kb 단위)를 지정\n" -#: main/main.c:349 +#: main/main.c:344 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보 보여주고 마침\n" -#: main/main.c:350 +#: main/main.c:345 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --NAME=VALUE 실시간 매개 변수 지정\n" -#: main/main.c:351 +#: main/main.c:346 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config 서버 환경 설정값에 대한 설명을 보여주고 마침\n" -#: main/main.c:352 +#: main/main.c:347 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: main/main.c:354 +#: main/main.c:349 #, c-format msgid "" "\n" @@ -16944,27 +17437,27 @@ msgstr "" "\n" "개발자 옵션들:\n" -#: main/main.c:355 +#: main/main.c:350 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h 쿼리최적화기의 기능을 제한 함\n" -#: main/main.c:356 +#: main/main.c:351 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O 시스템 테이블의 구조를 바꿀 수 있도록 함\n" -#: main/main.c:357 +#: main/main.c:352 #, c-format msgid " -P disable system indexes\n" msgstr " -P 시스템 인덱스들을 사용하지 않음\n" -#: main/main.c:358 +#: main/main.c:353 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex 각 쿼리 다음 작업시간을 보여줌\n" -#: main/main.c:359 +#: main/main.c:354 #, c-format msgid "" " -T send SIGABRT to all backend processes if one dies\n" @@ -16972,13 +17465,13 @@ msgstr "" " -T 하나의 하위 서버 프로세스가 비정상으로 마치며 모든\n" " 다른 백엔드 프로세스에게 SIGABRT 신호를 보냄\n" -#: main/main.c:360 +#: main/main.c:355 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr "" " -W NUM 디버그 작업을 위해 지정한 숫자의 초만큼 기다린다\n" -#: main/main.c:362 +#: main/main.c:357 #, c-format msgid "" "\n" @@ -16987,28 +17480,28 @@ msgstr "" "\n" "단일사용자 모드에서 사용할 수 있는 옵션들:\n" -#: main/main.c:363 +#: main/main.c:358 #, c-format msgid "" " --single selects single-user mode (must be first argument)\n" msgstr " --single 단일 사용자 모드 선택 (인자의 첫번째로 와야함)\n" -#: main/main.c:364 +#: main/main.c:359 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAME 데이터베이스 이름 (초기값: 사용자이름)\n" -#: main/main.c:365 +#: main/main.c:360 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 디버깅 수준\n" -#: main/main.c:366 +#: main/main.c:361 #, c-format msgid " -E echo statement before execution\n" msgstr " -E 실행하기 전에 작업명령을 출력함\n" -#: main/main.c:367 +#: main/main.c:362 #, c-format msgid "" " -j do not use newline as interactive query delimiter\n" @@ -17016,14 +17509,14 @@ msgstr "" " -j 대화형 쿼리의 명령 실행 구분 문자로 줄바꿈문자를 쓰지 않" "음\n" -#: main/main.c:368 main/main.c:374 +#: main/main.c:363 main/main.c:369 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr "" " -r FILENAME stdout, stderr 쪽으로 보내는 내용을 FILENAME 파일로 저장" "함\n" -#: main/main.c:370 +#: main/main.c:365 #, c-format msgid "" "\n" @@ -17032,25 +17525,25 @@ msgstr "" "\n" "부트스트랩 모드에서 사용할 수 있는 옵션들:\n" -#: main/main.c:371 +#: main/main.c:366 #, c-format msgid "" " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot 부트스트랩 모드로 실행 (첫번째 인자로 와야함)\n" -#: main/main.c:372 +#: main/main.c:367 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr " --check 체크 모드 선택 (첫번째 인자로 와야함)\n" -#: main/main.c:373 +#: main/main.c:368 #, c-format msgid "" " DBNAME database name (mandatory argument in bootstrapping " "mode)\n" msgstr " DBNAME 데이터베이스 이름 (부트스트랩 모드에서 필수)\n" -#: main/main.c:376 +#: main/main.c:371 #, c-format msgid "" "\n" @@ -17067,12 +17560,12 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: main/main.c:380 +#: main/main.c:375 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: main/main.c:391 +#: main/main.c:386 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -17085,12 +17578,12 @@ msgstr "" "반드시 일반 사용자 ID(시스템 관리자 권한이 없는 ID)로 서버를 실행하십시오.\n" "Server를 어떻게 안전하게 기동하는가 하는 것은 문서를 참조하시기 바랍니다.\n" -#: main/main.c:408 +#: main/main.c:403 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: real 또는 effective user ID 들은 반드시 일치되어야 한다.\n" -#: main/main.c:415 +#: main/main.c:410 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -17114,20 +17607,15 @@ msgstr "\"%s\" 이름의 확장가능한 노드 형이 이미 있습니다" msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "\"%s\" ExtensibleNodeMethods가 등록되어 있지 않음" -#: nodes/makefuncs.c:153 statistics/extended_stats.c:2335 +#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "\"%s\" 릴레이션에 해당하는 복합 자료형이 없음" -#: nodes/makefuncs.c:879 -#, c-format -msgid "unrecognized JSON encoding: %s" -msgstr "알 수 없는 JSON 인코딩: %s" - -#: nodes/nodeFuncs.c:116 nodes/nodeFuncs.c:147 parser/parse_coerce.c:2567 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2567 #: parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 -#: parser/parse_expr.c:2049 parser/parse_func.c:710 parser/parse_oper.c:883 -#: utils/fmgr/funcapi.c:661 +#: parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 +#: utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "자료형 %s 에 대해서는 배열 자료형을 사용할 수 없습니다" @@ -17142,7 +17630,7 @@ msgstr "\"%s\" 포탈의 매개 변수: %s" msgid "unnamed portal with parameters: %s" msgstr "이름 없는 포탈의 매개 변수: %s" -#: optimizer/path/joinrels.c:973 +#: optimizer/path/joinrels.c:972 #, c-format msgid "" "FULL JOIN is only supported with merge-joinable or hash-joinable join " @@ -17151,14 +17639,14 @@ msgstr "" "FULL JOIN 구문은 머지 조인이나, 해시 조인이 가능한 상황에서만 사용할 수 있습" "니다" -#: optimizer/plan/createplan.c:7111 parser/parse_merge.c:182 -#: parser/parse_merge.c:189 +#: optimizer/plan/createplan.c:7175 parser/parse_merge.c:203 +#: rewrite/rewriteHandler.c:1702 #, c-format msgid "cannot execute MERGE on relation \"%s\"" msgstr "\"%s\" 릴레이션에서 MERGE 명령을 실행할 수 없음" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1408 +#: optimizer/plan/initsplan.c:1407 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "" @@ -17166,92 +17654,92 @@ msgstr "" "다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1361 parser/analyze.c:1761 parser/analyze.c:2018 -#: parser/analyze.c:3231 +#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 +#: parser/analyze.c:3247 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s 구문은 UNION/INTERSECT/EXCEPT 예약어들과 함께 사용할 수 없습니다." -#: optimizer/plan/planner.c:2082 optimizer/plan/planner.c:4040 +#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4108 #, c-format msgid "could not implement GROUP BY" msgstr "GROUP BY를 구현할 수 없음" -#: optimizer/plan/planner.c:2083 optimizer/plan/planner.c:4041 -#: optimizer/plan/planner.c:4681 optimizer/prep/prepunion.c:1053 +#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4109 +#: optimizer/plan/planner.c:4790 optimizer/prep/prepunion.c:1320 #, c-format msgid "" "Some of the datatypes only support hashing, while others only support " "sorting." msgstr "해싱만 지원하는 자료형도 있고, 정렬만 지원하는 자료형도 있습니다." -#: optimizer/plan/planner.c:4680 +#: optimizer/plan/planner.c:4789 #, c-format msgid "could not implement DISTINCT" msgstr "DISTINCT를 구현할 수 없음" -#: optimizer/plan/planner.c:6019 +#: optimizer/plan/planner.c:6134 #, c-format msgid "could not implement window PARTITION BY" msgstr "창 PARTITION BY를 구현할 수 없음" -#: optimizer/plan/planner.c:6020 +#: optimizer/plan/planner.c:6135 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "창 분할 칼럼은 정렬 가능한 데이터 형식이어야 합니다." -#: optimizer/plan/planner.c:6024 +#: optimizer/plan/planner.c:6139 #, c-format msgid "could not implement window ORDER BY" msgstr "창 ORDER BY를 구현할 수 없음" -#: optimizer/plan/planner.c:6025 +#: optimizer/plan/planner.c:6140 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "창 순서 지정 칼럼은 정렬 가능한 데이터 형식이어야 합니다." -#: optimizer/prep/prepunion.c:516 +#: optimizer/prep/prepunion.c:467 #, c-format msgid "could not implement recursive UNION" msgstr "재귀 UNION을 구현할 수 없음" -#: optimizer/prep/prepunion.c:517 +#: optimizer/prep/prepunion.c:468 #, c-format msgid "All column datatypes must be hashable." msgstr "모든 열 데이터 형식은 해시 가능해야 합니다." #. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1052 +#: optimizer/prep/prepunion.c:1319 #, c-format msgid "could not implement %s" msgstr "%s 구문은 구현할 수 없음" -#: optimizer/util/clauses.c:4856 +#: optimizer/util/clauses.c:4963 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "\"%s\" SQL 함수를 인라인으로 바꾸는 중" -#: optimizer/util/plancat.c:154 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "복구 작업 중에는 임시 테이블이나, 언로그드 테이블을 접근할 수 없음" -#: optimizer/util/plancat.c:726 +#: optimizer/util/plancat.c:768 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "전체 로우 유니크 인덱스 인터페이스 규약은 지원하지 않습니다." -#: optimizer/util/plancat.c:743 +#: optimizer/util/plancat.c:785 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "ON CONFLICT 처리를 위해 관련된 인덱스가 없습니다" -#: optimizer/util/plancat.c:793 +#: optimizer/util/plancat.c:835 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "제외 제약 조건이 있어 ON CONFLICT DO UPDATE 작업은 할 수 없습니다" -#: optimizer/util/plancat.c:898 +#: optimizer/util/plancat.c:945 #, c-format msgid "" "there is no unique or exclusion constraint matching the ON CONFLICT " @@ -17259,23 +17747,23 @@ msgid "" msgstr "" "ON CONFLICT 절을 사용하는 경우, unique 나 exclude 제약 조건이 있어야 함" -#: parser/analyze.c:826 parser/analyze.c:1540 +#: parser/analyze.c:824 parser/analyze.c:1550 #, c-format msgid "VALUES lists must all be the same length" msgstr "VALUES 목록은 모두 같은 길이여야 함" -#: parser/analyze.c:1028 +#: parser/analyze.c:1027 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT 구문에 target columns 보다 더 많은 표현식이 존재하고 있다" -#: parser/analyze.c:1046 +#: parser/analyze.c:1045 #, c-format msgid "INSERT has more target columns than expressions" msgstr "" "INSERT 구문에 target columns 보다 더 많은 표현식(expressions)이 존재하고 있다" -#: parser/analyze.c:1050 +#: parser/analyze.c:1049 #, c-format msgid "" "The insertion source is a row expression containing the same number of " @@ -17284,40 +17772,40 @@ msgstr "" "삽입 소스는 INSERT 작업에서 기대하는 칼럼 수와 같은 로우 표현식입니다. 실수" "로 괄호를 추가한 것은 아닌지 확인하세요." -#: parser/analyze.c:1347 parser/analyze.c:1734 +#: parser/analyze.c:1357 parser/analyze.c:1744 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO 구문은 여기서는 사용할 수 없음" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1663 parser/analyze.c:3463 +#: parser/analyze.c:1673 parser/analyze.c:3479 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s 구문은 VALUES 에 적용할 수 없음" -#: parser/analyze.c:1900 +#: parser/analyze.c:1911 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "UNION/INTERSECT/EXCEPT ORDER BY 절이 잘못됨" -#: parser/analyze.c:1901 +#: parser/analyze.c:1912 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "결과 열 이름만 사용할 수 있고 식 또는 함수는 사용할 수 없습니다." -#: parser/analyze.c:1902 +#: parser/analyze.c:1913 #, c-format msgid "" "Add the expression/function to every SELECT, or move the UNION into a FROM " "clause." msgstr "모든 SELECT에 식/함수를 추가하거나 UNION을 FROM 절로 이동하십시오." -#: parser/analyze.c:2008 +#: parser/analyze.c:2019 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "INTO 는 UNION/INTERSECT/EXCEPT 의 첫번째 SELECT 에만 허용된다" -#: parser/analyze.c:2080 +#: parser/analyze.c:2091 #, c-format msgid "" "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of " @@ -17326,34 +17814,39 @@ msgstr "" "UNION/INTERSECT/EXCEPT 멤버 문에서 같은 쿼리 수준의 다른 관계를 참조할 수 없" "음" -#: parser/analyze.c:2167 +#: parser/analyze.c:2178 #, c-format msgid "each %s query must have the same number of columns" msgstr "각각의 %s query 는 같은 수의 columns 를 가져야 한다." -#: parser/analyze.c:2573 +#: parser/analyze.c:2535 +#, c-format +msgid "SET target columns cannot be qualified with the relation name." +msgstr "SET 대상 칼럼들은 해당 릴레이션 이름으로 한정할 수 없습니다." + +#: parser/analyze.c:2589 #, c-format msgid "RETURNING must have at least one column" msgstr "RETURNING 절에는 적어도 하나 이상의 칼럼이 있어야 합니다" -#: parser/analyze.c:2676 +#: parser/analyze.c:2692 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" -msgstr[0] "" +msgstr[0] "지정된 소스가 %d개의 칼럼을 반환했음" -#: parser/analyze.c:2737 +#: parser/analyze.c:2753 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "변수 \"%s\" 는 %s 자료형인데 표현식은 %s 자료형입니다." #. translator: %s is a SQL keyword -#: parser/analyze.c:2862 parser/analyze.c:2870 +#: parser/analyze.c:2878 parser/analyze.c:2886 #, c-format msgid "cannot specify both %s and %s" msgstr "%s, %s 둘다를 명시할 수 없다" -#: parser/analyze.c:2890 +#: parser/analyze.c:2906 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "" @@ -17361,331 +17854,331 @@ msgstr "" "다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2898 +#: parser/analyze.c:2914 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s 구문은 지원되지 않음" -#: parser/analyze.c:2901 +#: parser/analyze.c:2917 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "보류 가능 커서는 READ ONLY여야 합니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2909 +#: parser/analyze.c:2925 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s 구문은 지원되지 않음" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2920 +#: parser/analyze.c:2936 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s 구문이 잘못됨" -#: parser/analyze.c:2923 +#: parser/analyze.c:2939 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "민감하지 않은 커서는 READ ONLY여야 합니다." -#: parser/analyze.c:3017 +#: parser/analyze.c:3033 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "" "구체화된 뷰 정의에 사용한 WITH 절 안에는 자료 변경 구문이 없어야 합니다" -#: parser/analyze.c:3027 +#: parser/analyze.c:3043 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "구체화된 뷰는 임시 테이블이나 뷰를 사용할 수 없습니다" -#: parser/analyze.c:3037 +#: parser/analyze.c:3053 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "구체화딘 뷰는 바운드 매개 변수를 이용해서 정의할 수 없습니다" -#: parser/analyze.c:3049 +#: parser/analyze.c:3065 #, c-format msgid "materialized views cannot be unlogged" msgstr "구체화된 뷰는 UNLOGGED 옵션을 사용할 수 없습니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3238 +#: parser/analyze.c:3254 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s 절은 DISTINCT 절과 함께 사용할 수 없습니다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3245 +#: parser/analyze.c:3261 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s 절은 GROUP BY 절과 함께 사용할 수 없습니다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3252 +#: parser/analyze.c:3268 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s 절은 HAVING 절과 함께 사용할 수 없습니다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3259 +#: parser/analyze.c:3275 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s 절은 집계 함수와 함께 사용할 수 없습니다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3266 +#: parser/analyze.c:3282 #, c-format msgid "%s is not allowed with window functions" msgstr "%s 절은 윈도우 함수와 함께 사용할 수 없습니다" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3273 +#: parser/analyze.c:3289 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "%s 절은 대상 목록에서 세트 반환 함수와 함께 사용할 수 없습니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3372 +#: parser/analyze.c:3388 #, c-format msgid "%s must specify unqualified relation names" msgstr "%s 절에는 unqualified 릴레이션 이름을 지정해야 합니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3436 +#: parser/analyze.c:3452 #, c-format msgid "%s cannot be applied to a join" msgstr "%s 절은 조인을 적용할 수 없습니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3445 +#: parser/analyze.c:3461 #, c-format msgid "%s cannot be applied to a function" msgstr "%s 절은 함수에 적용할 수 없습니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3454 +#: parser/analyze.c:3470 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s 절은 테이블 함수에 적용할 수 없습니다." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3472 +#: parser/analyze.c:3488 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s 절은 WITH 쿼리에 적용할 수 없음" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3481 +#: parser/analyze.c:3497 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%s 절은 named tuplestore에 적용할 수 없음" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3501 +#: parser/analyze.c:3517 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "\"%s\" 릴레이션 (대상 구문: %s) 이 FROM 절 내에 없습니다" -#: parser/parse_agg.c:221 parser/parse_oper.c:227 +#: parser/parse_agg.c:210 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "%s 자료형에서 사용할 순서 정하는 연산자를 찾을 수 없습니다." -#: parser/parse_agg.c:223 +#: parser/parse_agg.c:212 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "" "DISTINCT와 함께 작업하는 집계 작업은 그 입력 자료가 정렬될 수 있어야 합니다" -#: parser/parse_agg.c:258 +#: parser/parse_agg.c:270 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPING 인자로는 32개 이내로 지정해야 합니다" -#: parser/parse_agg.c:361 +#: parser/parse_agg.c:373 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "JOIN 조건문에서는 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:363 +#: parser/parse_agg.c:375 msgid "grouping operations are not allowed in JOIN conditions" msgstr "JOIN 조건문에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:375 +#: parser/parse_agg.c:385 msgid "" "aggregate functions are not allowed in FROM clause of their own query level" msgstr "집계 함수는 자신의 쿼리 수준의 FROM 절에서는 사용할 수 없습니다." -#: parser/parse_agg.c:377 +#: parser/parse_agg.c:387 msgid "" "grouping operations are not allowed in FROM clause of their own query level" msgstr "자체 쿼리 수준의 FROM 절에는 그룹핑 작업을 허용하지 않습니다." -#: parser/parse_agg.c:382 +#: parser/parse_agg.c:392 msgid "aggregate functions are not allowed in functions in FROM" msgstr "FROM 절 내의 함수 표현식 내에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:384 +#: parser/parse_agg.c:394 msgid "grouping operations are not allowed in functions in FROM" msgstr "FROM 절 내의 함수 표현식 내에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:392 +#: parser/parse_agg.c:402 msgid "aggregate functions are not allowed in policy expressions" msgstr "정책 표현식에서는 집계 함수 사용을 허용하지 않습니다" -#: parser/parse_agg.c:394 +#: parser/parse_agg.c:404 msgid "grouping operations are not allowed in policy expressions" msgstr "정책 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:411 +#: parser/parse_agg.c:421 msgid "aggregate functions are not allowed in window RANGE" msgstr "윈도우 RANGE 안에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:413 +#: parser/parse_agg.c:423 msgid "grouping operations are not allowed in window RANGE" msgstr "윈도우 RANGE 안에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:418 +#: parser/parse_agg.c:428 msgid "aggregate functions are not allowed in window ROWS" msgstr "윈도우 ROWS 안에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:420 +#: parser/parse_agg.c:430 msgid "grouping operations are not allowed in window ROWS" msgstr "윈도우 ROWS 안에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:425 +#: parser/parse_agg.c:435 msgid "aggregate functions are not allowed in window GROUPS" msgstr "윈도우 GROUPS 안에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:427 +#: parser/parse_agg.c:437 msgid "grouping operations are not allowed in window GROUPS" msgstr "윈도우 GROUPS 안에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:440 +#: parser/parse_agg.c:450 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "MERGE WHEN 조건절에 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:442 +#: parser/parse_agg.c:452 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "MERGE WHEN 조건절에 그룹핑 작업이 허용되지 않습니다" -#: parser/parse_agg.c:468 +#: parser/parse_agg.c:479 msgid "aggregate functions are not allowed in check constraints" msgstr "체크 제약 조건에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:470 +#: parser/parse_agg.c:481 msgid "grouping operations are not allowed in check constraints" msgstr "체크 제약 조건에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:477 +#: parser/parse_agg.c:488 msgid "aggregate functions are not allowed in DEFAULT expressions" msgstr "DEFAULT 표현식에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:479 +#: parser/parse_agg.c:490 msgid "grouping operations are not allowed in DEFAULT expressions" msgstr "DEFAULT 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:484 +#: parser/parse_agg.c:495 msgid "aggregate functions are not allowed in index expressions" msgstr "인덱스 표현식에서는 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:486 +#: parser/parse_agg.c:497 msgid "grouping operations are not allowed in index expressions" msgstr "인덱스 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:491 +#: parser/parse_agg.c:502 msgid "aggregate functions are not allowed in index predicates" msgstr "집계 함수는 함수 기반 인덱스의 함수로 사용할 수 없습니다" -#: parser/parse_agg.c:493 +#: parser/parse_agg.c:504 msgid "grouping operations are not allowed in index predicates" msgstr "그룹핑 작업은 함수 기반 인덱스의 함수로 사용할 수 없습니다" -#: parser/parse_agg.c:498 +#: parser/parse_agg.c:509 msgid "aggregate functions are not allowed in statistics expressions" msgstr "정책 표현식에서는 집계 함수 사용을 허용하지 않습니다" -#: parser/parse_agg.c:500 +#: parser/parse_agg.c:511 msgid "grouping operations are not allowed in statistics expressions" msgstr "통계 정보 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:505 +#: parser/parse_agg.c:516 msgid "aggregate functions are not allowed in transform expressions" msgstr "transform 식(expression)에 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:507 +#: parser/parse_agg.c:518 msgid "grouping operations are not allowed in transform expressions" msgstr "transform 식(expression)에 그룹핑 작업를 사용할 수 없습니다" -#: parser/parse_agg.c:512 +#: parser/parse_agg.c:523 msgid "aggregate functions are not allowed in EXECUTE parameters" msgstr "EXECUTE 매개 변수로 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:514 +#: parser/parse_agg.c:525 msgid "grouping operations are not allowed in EXECUTE parameters" msgstr "EXECUTE 매개 변수로 그룹핑 작업을 사용할 수 없습니다" -#: parser/parse_agg.c:519 +#: parser/parse_agg.c:530 msgid "aggregate functions are not allowed in trigger WHEN conditions" msgstr "트리거의 WHEN 조건절에 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:521 +#: parser/parse_agg.c:532 msgid "grouping operations are not allowed in trigger WHEN conditions" msgstr "트리거의 WHEN 조건절에 그룹핑 작업이 허용되지 않습니다" -#: parser/parse_agg.c:526 +#: parser/parse_agg.c:537 msgid "aggregate functions are not allowed in partition bound" msgstr "파티션 범위 표현식에는 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:528 +#: parser/parse_agg.c:539 msgid "grouping operations are not allowed in partition bound" msgstr "파티션 범위 표현식에는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:533 +#: parser/parse_agg.c:544 msgid "aggregate functions are not allowed in partition key expressions" msgstr "파티션 키 표현식에서는 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:535 +#: parser/parse_agg.c:546 msgid "grouping operations are not allowed in partition key expressions" msgstr "파티션 키 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:541 +#: parser/parse_agg.c:552 msgid "aggregate functions are not allowed in column generation expressions" msgstr "미리 계산된 칼럼 표현식에서는 집계 함수 사용을 허용하지 않습니다" -#: parser/parse_agg.c:543 +#: parser/parse_agg.c:554 msgid "grouping operations are not allowed in column generation expressions" msgstr "미리 계산된 칼럼 표현식에서는 그룹핑 연산이 허용되지 않습니다" -#: parser/parse_agg.c:549 +#: parser/parse_agg.c:560 msgid "aggregate functions are not allowed in CALL arguments" msgstr "CALL 매개 변수로 집계 함수를 사용할 수 없습니다" -#: parser/parse_agg.c:551 +#: parser/parse_agg.c:562 msgid "grouping operations are not allowed in CALL arguments" msgstr "CALL 매개 변수로 그룹핑 연산을 사용할 수 없습니다" -#: parser/parse_agg.c:557 +#: parser/parse_agg.c:568 msgid "aggregate functions are not allowed in COPY FROM WHERE conditions" msgstr "COPY FROM WHERE 조건문에서는 집계 함수가 허용되지 않습니다" -#: parser/parse_agg.c:559 +#: parser/parse_agg.c:570 msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "COPY FROM WHERE 조건문에서는 그룹핑 연산이 허용되지 않습니다" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:586 parser/parse_clause.c:1956 +#: parser/parse_agg.c:597 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "집계 함수는 %s 절에서 사용할 수 없습니다." #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:589 +#: parser/parse_agg.c:600 #, c-format msgid "grouping operations are not allowed in %s" msgstr "그룹핑 작업은 %s 절에서 사용할 수 없습니다." -#: parser/parse_agg.c:690 +#: parser/parse_agg.c:701 #, c-format msgid "" "outer-level aggregate cannot contain a lower-level variable in its direct " @@ -17693,119 +18186,119 @@ msgid "" msgstr "" "출력 수준 집계는 그 직접적인 인자 안에 저수준 변수를 포함할 수 없습니다." -#: parser/parse_agg.c:768 +#: parser/parse_agg.c:779 #, c-format msgid "aggregate function calls cannot contain set-returning function calls" msgstr "집계 함수 호출은 집합 반환 함수 호출을 포함할 수 없음" -#: parser/parse_agg.c:769 parser/parse_expr.c:1700 parser/parse_expr.c:2182 -#: parser/parse_func.c:884 +#: parser/parse_agg.c:780 parser/parse_expr.c:1762 parser/parse_expr.c:2245 +#: parser/parse_func.c:885 #, c-format msgid "" "You might be able to move the set-returning function into a LATERAL FROM " "item." msgstr "집합 반환 함수를 LATERAL FROM 쪽으로 옮겨서 구현할 수도 있습니다." -#: parser/parse_agg.c:774 +#: parser/parse_agg.c:785 #, c-format msgid "aggregate function calls cannot contain window function calls" msgstr "집계 함수 호출은 윈도우 함수 호출을 포함할 수 없음" -#: parser/parse_agg.c:853 +#: parser/parse_agg.c:864 msgid "window functions are not allowed in JOIN conditions" msgstr "윈도우 함수는 JOIN 조건에 사용할 수 없음" -#: parser/parse_agg.c:860 +#: parser/parse_agg.c:871 msgid "window functions are not allowed in functions in FROM" msgstr "윈도우 함수는 FROM 절에 있는 함수로 사용할 수 없음" -#: parser/parse_agg.c:866 +#: parser/parse_agg.c:877 msgid "window functions are not allowed in policy expressions" msgstr "윈도우 함수는 정책 식에 사용할 수 없음" -#: parser/parse_agg.c:879 +#: parser/parse_agg.c:890 msgid "window functions are not allowed in window definitions" msgstr "윈도우 함수는 윈도우 함수 정의에 사용할 수 없음" -#: parser/parse_agg.c:890 +#: parser/parse_agg.c:901 msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "윈도우 함수는 MERGE WHEN 조건절에서 사용할 수 없음" -#: parser/parse_agg.c:914 +#: parser/parse_agg.c:926 msgid "window functions are not allowed in check constraints" msgstr "윈도우 함수는 check 제약조건에 사용할 수 없음" -#: parser/parse_agg.c:918 +#: parser/parse_agg.c:930 msgid "window functions are not allowed in DEFAULT expressions" msgstr "윈도우 함수는 DEFAULT 식에서 사용할 수 없음" -#: parser/parse_agg.c:921 +#: parser/parse_agg.c:933 msgid "window functions are not allowed in index expressions" msgstr "윈도우 함수는 인덱스 식에서 사용할 수 없음" -#: parser/parse_agg.c:924 +#: parser/parse_agg.c:936 msgid "window functions are not allowed in statistics expressions" msgstr "윈도우 함수는 통계 정보식에 사용할 수 없음" -#: parser/parse_agg.c:927 +#: parser/parse_agg.c:939 msgid "window functions are not allowed in index predicates" msgstr "윈도우 함수는 함수 기반 인덱스에서 사용할 수 없음" -#: parser/parse_agg.c:930 +#: parser/parse_agg.c:942 msgid "window functions are not allowed in transform expressions" msgstr "윈도우 함수는 transform 식에서 사용할 수 없음" -#: parser/parse_agg.c:933 +#: parser/parse_agg.c:945 msgid "window functions are not allowed in EXECUTE parameters" msgstr "윈도우 함수는 EXECUTE 매개 변수 설정 값으로 사용할 수 없음" -#: parser/parse_agg.c:936 +#: parser/parse_agg.c:948 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "윈도우 함수는 트리거의 WHEN 조건절에서 사용할 수 없음" -#: parser/parse_agg.c:939 +#: parser/parse_agg.c:951 msgid "window functions are not allowed in partition bound" msgstr "윈도우 함수는 파티션 범위 표현식에서 사용할 수 없음" -#: parser/parse_agg.c:942 +#: parser/parse_agg.c:954 msgid "window functions are not allowed in partition key expressions" msgstr "윈도우 함수는 파티션 키 표현식에서 사용할 수 없음" -#: parser/parse_agg.c:945 +#: parser/parse_agg.c:957 msgid "window functions are not allowed in CALL arguments" msgstr "윈도우 함수는 CALL 매개 변수 설정 값으로 사용할 수 없음" -#: parser/parse_agg.c:948 +#: parser/parse_agg.c:960 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "윈도우 함수는 COPY FROM WHERE 조건에 사용할 수 없음" -#: parser/parse_agg.c:951 +#: parser/parse_agg.c:963 msgid "window functions are not allowed in column generation expressions" msgstr "윈도우 함수는 미리 계산된 칼럼 생성 표현식에 사용할 수 없음" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:974 parser/parse_clause.c:1965 +#: parser/parse_agg.c:986 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "%s 안에서는 윈도우 함수를 사용할 수 없음" -#: parser/parse_agg.c:1008 parser/parse_clause.c:2798 +#: parser/parse_agg.c:1020 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "\"%s\" 윈도우 함수가 없음" -#: parser/parse_agg.c:1096 +#: parser/parse_agg.c:1108 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "너무 많은 그룹핑 세트가 있습니다 (최대값 4096)" -#: parser/parse_agg.c:1236 +#: parser/parse_agg.c:1248 #, c-format msgid "" "aggregate functions are not allowed in a recursive query's recursive term" msgstr "집계 함수는 재귀 쿼리의 재귀 조건에 사용할 수 없음" -#: parser/parse_agg.c:1429 +#: parser/parse_agg.c:1441 #, c-format msgid "" "column \"%s.%s\" must appear in the GROUP BY clause or be used in an " @@ -17814,60 +18307,60 @@ msgstr "" "column \"%s.%s\" 는 반드시 GROUP BY 절내에 있어야 하던지 또는 집계 함수 내에" "서 사용되어져야 한다" -#: parser/parse_agg.c:1432 +#: parser/parse_agg.c:1444 #, c-format msgid "" "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "순서있는 집합 집계 함수의 직접 인자는 그룹화된 칼럼만 사용해야합니다." -#: parser/parse_agg.c:1437 +#: parser/parse_agg.c:1449 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "" "subquery 가 outer query 에서 그룹화 되지 않은 열인 \"%s.%s\"를 사용합니다" -#: parser/parse_agg.c:1601 +#: parser/parse_agg.c:1613 #, c-format msgid "" "arguments to GROUPING must be grouping expressions of the associated query " "level" msgstr "GROUPING의 인자는 그 관련 쿼리 수준의 그룹핑 표현식이어야 합니다." -#: parser/parse_clause.c:195 +#: parser/parse_clause.c:193 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "\"%s\" 릴레이션은 자료 변경 구문의 대상이 될 수 없음" -#: parser/parse_clause.c:571 parser/parse_clause.c:599 parser/parse_func.c:2552 +#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "집합 변환 함수는 FROM 절의 최상위 수준에서만 사용할 수 있습니다." -#: parser/parse_clause.c:611 +#: parser/parse_clause.c:609 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "다중 칼럼 정의 목록은 같은 함수용으로 허용하지 않음" -#: parser/parse_clause.c:644 +#: parser/parse_clause.c:642 #, c-format msgid "" "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "" "여러 함수를 사용하는 ROWS FROM() 구문에는 칼럼 정의 목록을 지정하면 안됩니다." -#: parser/parse_clause.c:645 +#: parser/parse_clause.c:643 #, c-format msgid "" "Put a separate column definition list for each function inside ROWS FROM()." msgstr "ROWS FROM() 안 각 함수용 칼럼 정의 목록을 구분해 주세요." -#: parser/parse_clause.c:651 +#: parser/parse_clause.c:649 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "" "여러 인자를 사용하는 UNNEST()에서는 칼럼 정의 목록을 사용할 수 없습니다." -#: parser/parse_clause.c:652 +#: parser/parse_clause.c:650 #, c-format msgid "" "Use separate UNNEST() calls inside ROWS FROM(), and attach a column " @@ -17875,153 +18368,153 @@ msgid "" msgstr "" "ROWS FROM() 안에 UNNEST() 호출을 분리하고, 각각 칼럼 정의 목록을 추가하세요." -#: parser/parse_clause.c:659 +#: parser/parse_clause.c:657 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY 구문은 칼럼 정의 목록과 함께 쓸 수 없습니다." -#: parser/parse_clause.c:660 +#: parser/parse_clause.c:658 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "ROWS FROM() 안에 칼럼 정의 목록을 넣으세요." -#: parser/parse_clause.c:760 +#: parser/parse_clause.c:762 parser/parse_jsontable.c:295 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "하나의 FOR ORDINALITY 칼럼만 허용합니다." -#: parser/parse_clause.c:821 +#: parser/parse_clause.c:823 #, c-format msgid "column name \"%s\" is not unique" msgstr "\"%s\" 칼럼은 유일성을 가지지 못합니다(not unique)" -#: parser/parse_clause.c:863 +#: parser/parse_clause.c:865 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "\"%s\" 네임스페이스는 유일성을 가지지 못합니다(not unique)" -#: parser/parse_clause.c:873 +#: parser/parse_clause.c:875 #, c-format msgid "only one default namespace is allowed" msgstr "기본 네임스페이스는 하나만 허용합니다" -#: parser/parse_clause.c:933 +#: parser/parse_clause.c:935 #, c-format msgid "tablesample method %s does not exist" msgstr "\"%s\" 테이블 샘플링 방법이 없습니다" -#: parser/parse_clause.c:955 +#: parser/parse_clause.c:957 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" msgstr[0] "\"%s\" 테이블 샘플링 방법 %d개 인자를 지정해야함, (현재 %d개)" -#: parser/parse_clause.c:989 +#: parser/parse_clause.c:991 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "\"%s\" 테이블 샘플링 방법은 REPEATABLE 옵션을 지원하지 않음" -#: parser/parse_clause.c:1138 +#: parser/parse_clause.c:1144 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "TABLESAMPLE 절은 테이블과 구체화된 뷰에서만 사용할 수 있습니다" -#: parser/parse_clause.c:1325 +#: parser/parse_clause.c:1331 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "USING 절 내에 열 이름 \"%s\" 가 한번 이상 사용되었습니다" -#: parser/parse_clause.c:1340 +#: parser/parse_clause.c:1346 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "left table 내에 common column 이름 \"%s\" 가 한번 이상 사용되었다" -#: parser/parse_clause.c:1349 +#: parser/parse_clause.c:1355 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "USING 조건절에서 지정한 \"%s\" 칼럼이 왼쪽 테이블에 없음" -#: parser/parse_clause.c:1364 +#: parser/parse_clause.c:1370 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "common column name \"%s\"가 right table 에 한번 이상 사용되었다" -#: parser/parse_clause.c:1373 +#: parser/parse_clause.c:1379 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "USING 조건절에서 지정한 \"%s\" 칼럼이 오른쪽 테이블에 없음" -#: parser/parse_clause.c:1901 +#: parser/parse_clause.c:1907 #, c-format msgid "row count cannot be null in FETCH FIRST ... WITH TIES clause" msgstr "FETCH FIRST ... WITH TIES 절 안에 로우가 null 이면 안됩니다." #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_clause.c:1926 +#: parser/parse_clause.c:1932 #, c-format msgid "argument of %s must not contain variables" msgstr "%s 의 인자로 변수를 포함할 수 없습니다." #. translator: first %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2091 +#: parser/parse_clause.c:2097 #, c-format msgid "%s \"%s\" is ambiguous" msgstr "%s \"%s\" 가 명확하지 않은 표현입니다." #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2119 +#: parser/parse_clause.c:2125 #, c-format msgid "non-integer constant in %s" msgstr "정수가 아닌 상수가 %s 에 포함되어 있습니다" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2141 +#: parser/parse_clause.c:2147 #, c-format msgid "%s position %d is not in select list" msgstr "%s position %d 가 select list 에 포함되어 있지 않습니다" -#: parser/parse_clause.c:2580 +#: parser/parse_clause.c:2586 #, c-format msgid "CUBE is limited to 12 elements" msgstr "CUBE 인자로는 12개 이하의 인자만 허용합니다" -#: parser/parse_clause.c:2786 +#: parser/parse_clause.c:2792 #, c-format msgid "window \"%s\" is already defined" msgstr "\"%s\" 이름의 윈도우 함수가 이미 정의됨" -#: parser/parse_clause.c:2847 +#: parser/parse_clause.c:2853 #, c-format msgid "cannot override PARTITION BY clause of window \"%s\"" msgstr "\"%s\" 창의 PARTITION BY 절을 재정의할 수 없음" -#: parser/parse_clause.c:2859 +#: parser/parse_clause.c:2865 #, c-format msgid "cannot override ORDER BY clause of window \"%s\"" msgstr "\"%s\" 창의 ORDER BY 절을 재정의할 수 없음" -#: parser/parse_clause.c:2889 parser/parse_clause.c:2895 +#: parser/parse_clause.c:2895 parser/parse_clause.c:2901 #, c-format msgid "cannot copy window \"%s\" because it has a frame clause" msgstr "프래임 절이 있어, \"%s\" 윈도우를 복사할 수 없음." -#: parser/parse_clause.c:2897 +#: parser/parse_clause.c:2903 #, c-format msgid "Omit the parentheses in this OVER clause." msgstr "OVER 절에 괄호가 빠졌음" -#: parser/parse_clause.c:2917 +#: parser/parse_clause.c:2923 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column" msgstr "PRECEDING/FOLLOWING 옵셋용 RANGE는 하나의 ORDER BY 칼럼이 필요합니다." -#: parser/parse_clause.c:2940 +#: parser/parse_clause.c:2946 #, c-format msgid "GROUPS mode requires an ORDER BY clause" msgstr "GROUPS 모드는 ORDER BY 구문이 필요함" -#: parser/parse_clause.c:3011 +#: parser/parse_clause.c:3016 #, c-format msgid "" "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument " @@ -18030,75 +18523,75 @@ msgstr "" "DISTINCT, ORDER BY 표현식을 집계 함수와 쓸 때는, 반드시 select list 에 나타나" "야만 합니다" -#: parser/parse_clause.c:3012 +#: parser/parse_clause.c:3017 #, c-format msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list" msgstr "" "SELECT DISTINCT, ORDER BY 표현식을 위해서 반드시 select list 에 나타나야만 합" "니다" -#: parser/parse_clause.c:3044 +#: parser/parse_clause.c:3049 #, c-format msgid "an aggregate with DISTINCT must have at least one argument" msgstr "DISTINCT 예약어로 집계를 할 경우 적어도 하나의 인자는 있어야 함" -#: parser/parse_clause.c:3045 +#: parser/parse_clause.c:3050 #, c-format msgid "SELECT DISTINCT must have at least one column" msgstr "SELECT DISTINCT 구문은 적어도 한 개 이상의 칼럼이 있어야 합니다" -#: parser/parse_clause.c:3111 parser/parse_clause.c:3143 +#: parser/parse_clause.c:3116 parser/parse_clause.c:3148 #, c-format msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions" msgstr "" "SELECT DISTINCT ON 표현식은 반드시 초기 ORDER BY 표현식과 일치하여야 한다" -#: parser/parse_clause.c:3221 +#: parser/parse_clause.c:3226 #, c-format msgid "ASC/DESC is not allowed in ON CONFLICT clause" msgstr "ASC/DESC 예약어는 ON CONFLICT 절과 함께 사용할 수 없습니다." -#: parser/parse_clause.c:3227 +#: parser/parse_clause.c:3232 #, c-format msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause" msgstr "NULLS FIRST/LAST 절은 ON CONFLICT 절과 함께 사용할 수 없습니다." -#: parser/parse_clause.c:3306 +#: parser/parse_clause.c:3311 #, c-format msgid "" "ON CONFLICT DO UPDATE requires inference specification or constraint name" msgstr "ON CONFLICT DO UPDATE 구문에는 추론 명세나 제약조건 이름이 필요합니다." -#: parser/parse_clause.c:3307 +#: parser/parse_clause.c:3312 #, c-format msgid "For example, ON CONFLICT (column_name)." msgstr "사용예, ON CONFLICT (칼럼이름)." -#: parser/parse_clause.c:3318 +#: parser/parse_clause.c:3323 #, c-format msgid "ON CONFLICT is not supported with system catalog tables" msgstr "ON CONFLICT 절은 시스템 카탈로그 테이블에서는 사용할 수 없습니다" -#: parser/parse_clause.c:3326 +#: parser/parse_clause.c:3331 #, c-format msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table" msgstr "" "\"%s\" 테이블에는 ON CONFLICT 기능을 사용할 수 없습니다. 이 테이블은 카탈로" "그 테이블로 사용됩니다." -#: parser/parse_clause.c:3457 +#: parser/parse_clause.c:3462 #, c-format msgid "operator %s is not a valid ordering operator" msgstr "%s 연산자는 유효한 순서 지정 연산자가 아님" -#: parser/parse_clause.c:3459 +#: parser/parse_clause.c:3464 #, c-format msgid "" "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "" "순서 지정 연산자는 btree 연산자 패밀리의 \"<\" or \">\" 멤버여야 합니다." -#: parser/parse_clause.c:3770 +#: parser/parse_clause.c:3775 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" @@ -18106,7 +18599,7 @@ msgstr "" "PRECEDING/FOLLOWING 옵셋과 함께 쓰는 RANGE 구문은 칼럼의 %s 자로형을 지원하" "지 않습니다." -#: parser/parse_clause.c:3776 +#: parser/parse_clause.c:3781 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s " @@ -18115,12 +18608,12 @@ msgstr "" "PRECEDING/FOLLOWING 옵셋과 함께 쓰는 RANGE 구문은 %s 자료형 칼럼과 %s 옵셋 형" "식을 지원하지 않습니다." -#: parser/parse_clause.c:3779 +#: parser/parse_clause.c:3784 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "옵셋 값을 적당한 자료형으로 변환하세요." -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3789 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for " @@ -18129,15 +18622,15 @@ msgstr "" "PRECEDING/FOLLOWING 옵셋과 함께 쓰는 RANGE 구문이 %s 자료형 칼럼과 %s 옵셋 형" "식 계산에서 여러 가지로 해석될 수 있습니다." -#: parser/parse_clause.c:3787 +#: parser/parse_clause.c:3792 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "옵셋 값을 분명한 자료형으로 형변환 하세요." #: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 #: parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 -#: parser/parse_expr.c:2083 parser/parse_expr.c:2691 parser/parse_expr.c:3497 -#: parser/parse_target.c:985 +#: parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3405 +#: parser/parse_expr.c:3634 parser/parse_target.c:998 #, c-format msgid "cannot cast type %s to %s" msgstr "%s 자료형을 %s 자료형으로 형변환할 수 없습니다." @@ -18196,19 +18689,19 @@ msgid "arguments declared \"%s\" are not all alike" msgstr "\"%s\" 로 선언된 인자들이 모두 같지 않습니다." #: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 -#: utils/fmgr/funcapi.c:592 +#: utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "%s 이름으로 선언된 인자가 array가 아니고, %s 자료형입니다" #: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 -#: utils/fmgr/funcapi.c:606 +#: utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "%s 로 선언된 인자가 range 자료형이 아니고, %s 자료형입니다" #: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 -#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:624 utils/fmgr/funcapi.c:689 +#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "%s 로 선언된 인자가 multirange 자료형이 아니고, %s 자료형입니다" @@ -18365,28 +18858,23 @@ msgstr "\"%s\" 쿼리에 대한 재귀 참조가 INTERSECT 내에 표시되지 msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "\"%s\" 쿼리에 대한 재귀 참조가 EXCEPT 내에 표시되지 않아야 함" -#: parser/parse_cte.c:133 -#, c-format -msgid "MERGE not supported in WITH query" -msgstr "WITH 쿼리 안에 MERGE 구문은 쓸 수 없음" - -#: parser/parse_cte.c:143 +#: parser/parse_cte.c:136 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "\"%s\" WITH 쿼리 이름이 여러 번 지정됨" -#: parser/parse_cte.c:314 +#: parser/parse_cte.c:308 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "%s 자료형용 부등식 연산자를 알 수 없음" -#: parser/parse_cte.c:341 +#: parser/parse_cte.c:335 #, c-format msgid "" "WITH clause containing a data-modifying statement must be at the top level" msgstr "자료를 변경하는 구문이 있는 WITH 절은 최상위 수준에 있어야 합니다" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:384 #, c-format msgid "" "recursive query \"%s\" column %d has type %s in non-recursive term but type " @@ -18395,12 +18883,12 @@ msgstr "" "\"%s\" 재귀 쿼리의 %d 번째 칼럼은 비재귀 조건에 %s 자료형을 포함하는데 전체적" "으로는 %s 자료형임" -#: parser/parse_cte.c:396 +#: parser/parse_cte.c:390 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "비재귀 조건의 출력을 올바른 형식으로 형변환하십시오." -#: parser/parse_cte.c:401 +#: parser/parse_cte.c:395 #, c-format msgid "" "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term " @@ -18409,42 +18897,42 @@ msgstr "" "\"%s\" 재귀 쿼리의 %d 번째 칼럼은 비재귀 조건에 %s 자료형을 포함하는데 전체적" "으로는 %s 자료형임" -#: parser/parse_cte.c:405 +#: parser/parse_cte.c:399 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "" "비 재귀형 요소들의 문자 정렬 규칙을 지정할 때는 COLLATE 절을 추가하세요." -#: parser/parse_cte.c:426 +#: parser/parse_cte.c:420 #, c-format msgid "WITH query is not recursive" msgstr "WITH 쿼리가 재귀 쿼리 형식이 아님" -#: parser/parse_cte.c:457 +#: parser/parse_cte.c:451 #, c-format msgid "" "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "" "SEARCH 또는 CYCLE 절을 사용할 때는 UNION 왼쪽 구문은 SELECT 여야 합니다." -#: parser/parse_cte.c:462 +#: parser/parse_cte.c:456 #, c-format msgid "" "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "" "SEARCH 또는 CYCLE 절을 사용할 때는 UNION 오른쪽 구문은 SELECT 여야 합니다." -#: parser/parse_cte.c:477 +#: parser/parse_cte.c:471 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "\"%s\" search용 칼럼이 WITH 쿼리 칼럼 목록에 없음" -#: parser/parse_cte.c:484 +#: parser/parse_cte.c:478 #, c-format msgid "search column \"%s\" specified more than once" msgstr "\"%s\" search용 칼럼을 하나 이상 지정했음" -#: parser/parse_cte.c:493 +#: parser/parse_cte.c:487 #, c-format msgid "" "search sequence column name \"%s\" already used in WITH query column list" @@ -18452,163 +18940,171 @@ msgstr "" "\"%s\" 이름의 search sequence 칼럼 이름은 WITH 쿼리 칼럼 목록 안에서 이미 사" "용되고 있습니다." -#: parser/parse_cte.c:510 +#: parser/parse_cte.c:504 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "\"%s\" cycle용 칼럼이 WITH 쿼리 칼럼 목록에 없습니다" -#: parser/parse_cte.c:517 +#: parser/parse_cte.c:511 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "\"%s\" cycle용 칼럼을 하나 이상 지정했음" -#: parser/parse_cte.c:526 +#: parser/parse_cte.c:520 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "" "\"%s\" cycle mark 칼럼 이름이 WITH 쿼리 칼럼 목록 안에서 이미 사용되고 있습니" "다." -#: parser/parse_cte.c:533 +#: parser/parse_cte.c:527 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "" "\"%s\" cycle path 칼럼 이름이 WITH 쿼리 칼럼 목록 안에서 이미 사용되고 있습니" "다." -#: parser/parse_cte.c:541 +#: parser/parse_cte.c:535 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "cycle mark 칼럼 이름과 cycle path 칼럼 이름이 같습니다." -#: parser/parse_cte.c:551 +#: parser/parse_cte.c:545 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "search sequence 칼럼 이름과 cycle mark 칼럼 이름이 같습니다." -#: parser/parse_cte.c:558 +#: parser/parse_cte.c:552 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "search sequence 칼럼 이름과 cycle path 칼럼 이름이 같습니다." -#: parser/parse_cte.c:642 +#: parser/parse_cte.c:636 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "" "\"%s\" WITH 쿼리에는 %d개의 칼럼을 사용할 수 있는데 %d개의 칼럼이 지정됨" -#: parser/parse_cte.c:822 +#: parser/parse_cte.c:816 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "WITH 항목 간의 상호 재귀가 구현되지 않음" -#: parser/parse_cte.c:874 +#: parser/parse_cte.c:868 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "\"%s\" 재귀 쿼리에 자료 변경 구문이 포함될 수 없습니다." -#: parser/parse_cte.c:882 +#: parser/parse_cte.c:876 #, c-format msgid "" "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] " "recursive-term" msgstr "\"%s\" 재귀 쿼리에 비재귀 조건 형태의 UNION [ALL] 재귀 조건이 없음" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:911 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "재귀 쿼리의 ORDER BY가 구현되지 않음" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:917 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "재귀 쿼리의 OFFSET이 구현되지 않음" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:923 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "재귀 쿼리의 LIMIT가 구현되지 않음" -#: parser/parse_cte.c:944 +#: parser/parse_cte.c:929 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "재귀 쿼리의 FOR UPDATE/SHARE가 구현되지 않음" -#: parser/parse_cte.c:1001 +#: parser/parse_cte.c:1008 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "\"%s\" 쿼리에 대한 재귀 참조가 여러 번 표시되지 않아야 함" -#: parser/parse_expr.c:294 +#: parser/parse_expr.c:313 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "이 영역에서는 DEFAULT를 사용할 수 없습니다" -#: parser/parse_expr.c:371 parser/parse_relation.c:3688 -#: parser/parse_relation.c:3698 parser/parse_relation.c:3716 -#: parser/parse_relation.c:3723 parser/parse_relation.c:3737 +#: parser/parse_expr.c:406 parser/parse_relation.c:3691 +#: parser/parse_relation.c:3701 parser/parse_relation.c:3719 +#: parser/parse_relation.c:3726 parser/parse_relation.c:3740 #, c-format msgid "column %s.%s does not exist" msgstr "%s.%s 칼럼 없음" -#: parser/parse_expr.c:383 +#: parser/parse_expr.c:418 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "\"%s\" 칼럼은 %s 자료형을 찾을 수 없음" -#: parser/parse_expr.c:389 +#: parser/parse_expr.c:424 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "레코드 데이터 형식에서 \"%s\" 칼럼을 식별할 수 없음" -#: parser/parse_expr.c:395 +#: parser/parse_expr.c:430 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "" ".%s 표현이 %s 자료형 사용되었는데, 이는 복소수형 (complex type)이 아닙니다" -#: parser/parse_expr.c:426 parser/parse_target.c:733 +#: parser/parse_expr.c:461 parser/parse_target.c:732 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "\"*\"를 통한 칼럼 확장은 여기서 지원되지 않음" -#: parser/parse_expr.c:548 +#: parser/parse_expr.c:584 msgid "cannot use column reference in DEFAULT expression" msgstr "DEFAULT 표현식에서는 열 reference를 사용할 수 없음" -#: parser/parse_expr.c:551 +#: parser/parse_expr.c:587 msgid "cannot use column reference in partition bound expression" msgstr "파티션 범위 표현식에서 칼럼 참조를 사용할 수 없음" -#: parser/parse_expr.c:810 parser/parse_relation.c:833 -#: parser/parse_relation.c:915 parser/parse_target.c:1225 +#: parser/parse_expr.c:846 parser/parse_relation.c:833 +#: parser/parse_relation.c:915 parser/parse_target.c:1238 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "칼럼 참조 \"%s\" 가 모호합니다." -#: parser/parse_expr.c:866 parser/parse_param.c:110 parser/parse_param.c:142 +#: parser/parse_expr.c:902 parser/parse_param.c:110 parser/parse_param.c:142 #: parser/parse_param.c:204 parser/parse_param.c:303 #, c-format msgid "there is no parameter $%d" msgstr "$%d 매개 변수가 없습니다" -#: parser/parse_expr.c:1066 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1103 parser/parse_expr.c:3065 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "NULIF 절은 불리언 값을 얻기 위해서 = 연산자를 필요로 합니다" +msgid "%s requires = operator to yield boolean" +msgstr "%s 절은 불리언 값을 얻기 위해서 = 연산자를 필요로 합니다" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1072 parser/parse_expr.c:3007 +#: parser/parse_expr.c:1109 parser/parse_expr.c:3072 #, c-format msgid "%s must not return a set" msgstr "%s에서는 집합을 반환할 수 없습니다." -#: parser/parse_expr.c:1457 parser/parse_expr.c:1489 +#: parser/parse_expr.c:1395 +#, c-format +msgid "" +"MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" +msgstr "" +"MERGE_ACTION()은 MERGE 명령의 RETURNING 목록 안에서만 사용될 수 있음" + +#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 #, c-format msgid "number of columns does not match number of values" msgstr "칼럼의 개수와, values의 개수가 틀립니다" -#: parser/parse_expr.c:1503 +#: parser/parse_expr.c:1565 #, c-format msgid "" "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() " @@ -18617,222 +19113,350 @@ msgstr "" "다중 칼럼 UPDATE 요소를 위한 소스는 서브셀렉트나 ROW() 표현식이어야 합니다." #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1698 parser/parse_expr.c:2180 parser/parse_func.c:2677 +#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "%s 안에서는 집합 반환 함수를 사용할 수 없음" -#: parser/parse_expr.c:1761 +#: parser/parse_expr.c:1824 msgid "cannot use subquery in check constraint" msgstr "체크 제약 조건에서는 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1765 +#: parser/parse_expr.c:1828 msgid "cannot use subquery in DEFAULT expression" msgstr "DEFAULT 식에서는 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1768 +#: parser/parse_expr.c:1831 msgid "cannot use subquery in index expression" msgstr "인덱스 식(expression)에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1771 +#: parser/parse_expr.c:1834 msgid "cannot use subquery in index predicate" msgstr "인덱스 술어(predicate)에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1774 +#: parser/parse_expr.c:1837 msgid "cannot use subquery in statistics expression" msgstr "통계 정보 표현식에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1777 +#: parser/parse_expr.c:1840 msgid "cannot use subquery in transform expression" msgstr "transform 식(expression)에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1780 +#: parser/parse_expr.c:1843 msgid "cannot use subquery in EXECUTE parameter" msgstr "EXECUTE 매개 변수로 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1783 +#: parser/parse_expr.c:1846 msgid "cannot use subquery in trigger WHEN condition" msgstr "트리거 WHEN 조건절에서는 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1786 +#: parser/parse_expr.c:1849 msgid "cannot use subquery in partition bound" msgstr "파티션 범위 표현식에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1789 +#: parser/parse_expr.c:1852 msgid "cannot use subquery in partition key expression" msgstr "파티션 키 표현식에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1792 +#: parser/parse_expr.c:1855 msgid "cannot use subquery in CALL argument" msgstr "CALL 매개 변수로 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1795 +#: parser/parse_expr.c:1858 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "COPY FROM WHERE 조건절에서는 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1798 +#: parser/parse_expr.c:1861 msgid "cannot use subquery in column generation expression" msgstr "미리 계산된 칼럼 생성 표현식에 서브쿼리를 사용할 수 없습니다" -#: parser/parse_expr.c:1851 parser/parse_expr.c:3628 +#: parser/parse_expr.c:1914 parser/parse_expr.c:3764 #, c-format msgid "subquery must return only one column" msgstr "subquery는 오로지 한개의 열만을 돌려 주어야 합니다." -#: parser/parse_expr.c:1922 +#: parser/parse_expr.c:1985 #, c-format msgid "subquery has too many columns" msgstr "subquery 에가 너무 많은 칼럼을 가집니다" -#: parser/parse_expr.c:1927 +#: parser/parse_expr.c:1990 #, c-format msgid "subquery has too few columns" msgstr "subquery 에 명시된 열 수가 너무 적다" -#: parser/parse_expr.c:2023 +#: parser/parse_expr.c:2086 #, c-format msgid "cannot determine type of empty array" msgstr "빈 배열의 자료형을 확인할 수 없음" -#: parser/parse_expr.c:2024 +#: parser/parse_expr.c:2087 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "원하는 형식으로 명시적으로 형변환하십시오(예: ARRAY[]::integer[])." -#: parser/parse_expr.c:2038 +#: parser/parse_expr.c:2101 #, c-format msgid "could not find element type for data type %s" msgstr "%s 자료형의 요소 자료형을 찾을 수 없음" -#: parser/parse_expr.c:2121 +#: parser/parse_expr.c:2184 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "ROW 표현식은 최대 %d 개의 항목을 지정할 수 있습니다" -#: parser/parse_expr.c:2326 +#: parser/parse_expr.c:2389 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "이름이 지정되지 않은 XML 속성 값은 열 참조여야 함" -#: parser/parse_expr.c:2327 +#: parser/parse_expr.c:2390 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "이름이 지정되지 않은 XML 요소 값은 열 참조여야 함" -#: parser/parse_expr.c:2342 +#: parser/parse_expr.c:2405 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "\"%s\" XML 속성 이름이 여러 번 표시됨" -#: parser/parse_expr.c:2450 +#: parser/parse_expr.c:2513 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "XMLSERIALIZE 결과를 %s 형으로 바꿀 수 없음" -#: parser/parse_expr.c:2764 parser/parse_expr.c:2960 +#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 #, c-format msgid "unequal number of entries in row expressions" msgstr "행 표현식에서 항목 수가 일치하지 않습니다" -#: parser/parse_expr.c:2774 +#: parser/parse_expr.c:2837 #, c-format msgid "cannot compare rows of zero length" msgstr "길이가 영(0)인 행들은 비교할 수 없습니다" -#: parser/parse_expr.c:2799 +#: parser/parse_expr.c:2862 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "" "행 비교 연산자는 불리언형을 리턴해야 합니다. %s 자료형을 사용할 수 없습니다" -#: parser/parse_expr.c:2806 +#: parser/parse_expr.c:2869 #, c-format msgid "row comparison operator must not return a set" msgstr "행 비교 연산자는 set을 리턴할 수 없습니다" -#: parser/parse_expr.c:2865 parser/parse_expr.c:2906 +#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "%s 행 비교 연산자의 구문을 분석할 수 없습니다" -#: parser/parse_expr.c:2867 +#: parser/parse_expr.c:2930 #, c-format msgid "" "Row comparison operators must be associated with btree operator families." msgstr "로우 비교 연산자를 btree 연산자 패밀리와 연결해야 함" -#: parser/parse_expr.c:2908 +#: parser/parse_expr.c:2971 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "여러 가지 등식들이 성립할 수 있는 가능성이 있습니다" -#: parser/parse_expr.c:3001 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "" -"IS DISTINCT FROM 절에서 불리언 값을 얻기 위해서 = 연산자를 필요로 합니다" - -#: parser/parse_expr.c:3239 +#: parser/parse_expr.c:3306 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "JSON ENCODING 절은 입력 자료형이 bytea 일때만 허용합니다." -#: parser/parse_expr.c:3261 +#: parser/parse_expr.c:3370 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "" "FORMAT JSON 절과 관련된 자료형이 문자열이 아닌 자료형인 경우는 사용할 수 없습" "니다." -#: parser/parse_expr.c:3262 +#: parser/parse_expr.c:3371 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "" "FORMAT JSON 절과 관련된 자료형이 문자열이 아닌 자료형인 경우는 사용할 수 없습" "니다." -#: parser/parse_expr.c:3335 +#: parser/parse_expr.c:3460 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "비 문자열 출력 형으로 JSON 포멧을 사용할 수 없음" -#: parser/parse_expr.c:3348 +#: parser/parse_expr.c:3473 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "이진 자료형이 아닌 출력 자료형을 위한 JSON 인코딩을 지정할 수 없음" -#: parser/parse_expr.c:3353 +#: parser/parse_expr.c:3478 #, c-format msgid "unsupported JSON encoding" msgstr "지원하지 않는 JSON 인코딩" -#: parser/parse_expr.c:3354 +#: parser/parse_expr.c:3479 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "UTF8 JSON 인코딩만 지원합니다." -#: parser/parse_expr.c:3391 +#: parser/parse_expr.c:3516 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "SQL/JSON 함수들은 SETOF 반환 자료형을 지원하지 않음" -#: parser/parse_expr.c:3712 parser/parse_func.c:865 +#: parser/parse_expr.c:3521 +#, c-format +msgid "returning pseudo-types is not supported in SQL/JSON functions" +msgstr "SQL/JSON 함수들은 반환 자료형으로 의사 자료형을 지원하지 않음" + +#: parser/parse_expr.c:3849 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "윈도우 함수에 대해 집계용 ORDER BY가 구현되지 않음" -#: parser/parse_expr.c:3934 +#: parser/parse_expr.c:4072 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "" "이진 자료형이 아닌 입력 자료형을 위한 JSON FORMAT ENCODING 구문을 사용할 수 " "없음" -#: parser/parse_expr.c:3954 +#: parser/parse_expr.c:4092 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "IS JSON 술어(predicate)에 %s 자료형을 사용할 수 없음" +#: parser/parse_expr.c:4118 parser/parse_expr.c:4239 +#, c-format +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "%s 자료형은 %s RETURNING 절에서 사용할 수 없음" + +#: parser/parse_expr.c:4120 +#, c-format +msgid "Try returning json or jsonb." +msgstr "json 또는 jsonb 형을 반환하세요." + +#: parser/parse_expr.c:4168 +#, c-format +msgid "cannot use non-string types with WITH UNIQUE KEYS clause" +msgstr "문자열이 아닌 자료형은 WITH UNIQUE KEYS 절과 함께 사용할 수 없음" + +#: parser/parse_expr.c:4242 +#, c-format +msgid "Try returning a string type or bytea." +msgstr "문자열이나 bytea 자료형을 반환하도록 하세요." + +#: parser/parse_expr.c:4307 +#, c-format +msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgstr "%s()의 RETURNING 절안에는 FORMAT JSON 옵션을 지정할 수 없음" + +#: parser/parse_expr.c:4320 +#, c-format +msgid "" +"SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" +msgstr "WITH WRAPPER 옵션을 사용할 때는 SQL/JSON QUOTES 옵션을 지정하면 안됨" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4334 parser/parse_expr.c:4363 parser/parse_expr.c:4394 +#: parser/parse_expr.c:4420 parser/parse_expr.c:4446 +#: parser/parse_jsontable.c:94 +#, c-format +msgid "invalid %s behavior" +msgstr "%s 절은 바르지 않음" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4337 parser/parse_expr.c:4366 +#, c-format +msgid "" +"Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is " +"allowed in %s for %s." +msgstr "" +"%s 옵션(대상: %s)에는 ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, 또는 " +"DEFAULT 표현식만 쓸 수 있음" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4344 parser/parse_expr.c:4373 parser/parse_expr.c:4402 +#: parser/parse_expr.c:4430 parser/parse_expr.c:4456 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "%s 절은 \"%s\" 칼럼 대상으로는 사용할 수 없음" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4347 parser/parse_expr.c:4376 +#, c-format +msgid "" +"Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is " +"allowed in %s for formatted columns." +msgstr "" +"포멧된 칼럼용 %s 옵션에는 ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, 또는 " +"DEFAULT 표현식만 쓸 수 있음" + +#: parser/parse_expr.c:4395 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "%s 옵션 값으로는 ERROR, TRUE, FALSE, 또는 UNKNOWN 만 쓸 수 있음: 대상=%s" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4405 +#, c-format +msgid "" +"Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "EXISTS 칼럼용 %s 옵션에는 ERROR, TRUE, FALSE, 또는 UNKNOWN 만 쓸 수 있음." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4423 parser/parse_expr.c:4449 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "%s 옵션 값으로는 ERROR, NULL, 또는 DEFAULT 만 쓸 수 있음: 대상=%s" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4433 parser/parse_expr.c:4459 +#, c-format +msgid "" +"Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "스칼라 칼럼용 %s 옵션에는 ERROR, NULL, 또는 DEFAULT 만 쓸 수 있음." + + +#: parser/parse_expr.c:4489 +#, c-format +msgid "JSON path expression must be of type %s, not of type %s" +msgstr "JSON 패스 표현식은 %s 자료형이어야 함(%s 자료형이 아님)" + +#: parser/parse_expr.c:4707 +#, c-format +msgid "" +"can only specify a constant, non-aggregate function, or operator expression " +"for DEFAULT" +msgstr "" +"DEFAULT로는 상수, 비집계 함수, 또는 연산자 표현식만 쓸 수 있음" + +#: parser/parse_expr.c:4712 +#, c-format +msgid "DEFAULT expression must not contain column references" +msgstr "DEFAULT 표현식에서는 칼럼 참조를 포함할 수 없습니다" + +#: parser/parse_expr.c:4717 +#, c-format +msgid "DEFAULT expression must not return a set" +msgstr "DEFAULT 표현식에서는 집합을 반환할 수 없습니다." + +#: parser/parse_expr.c:4793 parser/parse_expr.c:4802 +#, c-format +msgid "cannot cast behavior expression of type %s to %s" +msgstr "%s 자료형을 %s 자료형으로 형변환할 수 없습니다." + +#: parser/parse_expr.c:4796 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "%s형으로 변환하는 형변환자를 사용해보십시오" + #: parser/parse_func.c:194 #, c-format msgid "argument name \"%s\" used more than once" @@ -18843,7 +19467,7 @@ msgstr "\"%s\" 이름의 매개 변수가 여러 번 사용 됨" msgid "positional argument cannot follow named argument" msgstr "위치 기반 인자 뒤에 이름 기반 인자를 쓸 수 없습니다." -#: parser/parse_func.c:287 parser/parse_func.c:2367 +#: parser/parse_func.c:287 parser/parse_func.c:2368 #, c-format msgid "%s is not a procedure" msgstr "%s 개체는 프로시져가 아님" @@ -18992,7 +19616,7 @@ msgstr "" "른 위치에 쓰지 않은 것 같습니다. ORDER BY 절은 모든 집계용 인자들 맨 뒤에 있" "어야 합니다." -#: parser/parse_func.c:622 parser/parse_func.c:2410 +#: parser/parse_func.c:622 parser/parse_func.c:2411 #, c-format msgid "procedure %s does not exist" msgstr "\"%s\" 프로시져 없음" @@ -19020,7 +19644,7 @@ msgstr "" msgid "VARIADIC argument must be an array" msgstr "VARIADIC 매개 변수는 배열이어야 함" -#: parser/parse_func.c:791 parser/parse_func.c:855 +#: parser/parse_func.c:791 parser/parse_func.c:856 #, c-format msgid "%s(*) must be used to call a parameterless aggregate function" msgstr "%s(*) 사용할 때는 이 함수가 매개 변수 없는 집계 함수여야 합니다" @@ -19035,237 +19659,238 @@ msgstr "집계 함수는 세트를 반환할 수 없음" msgid "aggregates cannot use named arguments" msgstr "집계 함수는 인자 이름을 사용할 수 없음" -#: parser/parse_func.c:845 +#: parser/parse_func.c:846 #, c-format msgid "DISTINCT is not implemented for window functions" msgstr "윈도우 함수에 대해 DISTINCT가 구현되지 않음" -#: parser/parse_func.c:874 +#: parser/parse_func.c:875 #, c-format msgid "FILTER is not implemented for non-aggregate window functions" msgstr "비집계 윈도우 함수에 대해 FILTER가 구현되지 않음" -#: parser/parse_func.c:883 +#: parser/parse_func.c:884 #, c-format msgid "window function calls cannot contain set-returning function calls" msgstr "윈도우 함수 호출에 집합 반환 함수 호출을 포함할 수 없음" -#: parser/parse_func.c:891 +#: parser/parse_func.c:892 #, c-format msgid "window functions cannot return sets" msgstr "윈도우 함수는 세트를 반환할 수 없음" -#: parser/parse_func.c:2166 parser/parse_func.c:2439 +#: parser/parse_func.c:2167 parser/parse_func.c:2440 #, c-format msgid "could not find a function named \"%s\"" msgstr "\"%s\" 함수를 찾을 수 없음" -#: parser/parse_func.c:2180 parser/parse_func.c:2457 +#: parser/parse_func.c:2181 parser/parse_func.c:2458 #, c-format msgid "function name \"%s\" is not unique" msgstr "\"%s\" 함수 이름은 유일성을 가지지 못합니다(not unique)" -#: parser/parse_func.c:2182 parser/parse_func.c:2460 +#: parser/parse_func.c:2183 parser/parse_func.c:2461 #, c-format msgid "Specify the argument list to select the function unambiguously." msgstr "입력 인자를 다르게 해서 이 모호함을 피하세요." -#: parser/parse_func.c:2226 +#: parser/parse_func.c:2227 #, c-format msgid "procedures cannot have more than %d argument" msgid_plural "procedures cannot have more than %d arguments" msgstr[0] "프로시져는 %d개 이상의 인자를 사용할 수 없음" -#: parser/parse_func.c:2357 +#: parser/parse_func.c:2358 #, c-format msgid "%s is not a function" msgstr "%s 이름의 개체는 함수가 아닙니다" -#: parser/parse_func.c:2377 +#: parser/parse_func.c:2378 #, c-format msgid "function %s is not an aggregate" msgstr "%s 함수는 집계 함수가 아닙니다" -#: parser/parse_func.c:2405 +#: parser/parse_func.c:2406 #, c-format msgid "could not find a procedure named \"%s\"" msgstr "\"%s\" 이름의 프로시져를 찾을 수 없음" -#: parser/parse_func.c:2419 +#: parser/parse_func.c:2420 #, c-format msgid "could not find an aggregate named \"%s\"" msgstr "\"%s\" 이름의 집계 함수를 찾을 수 없음" -#: parser/parse_func.c:2424 +#: parser/parse_func.c:2425 #, c-format msgid "aggregate %s(*) does not exist" msgstr "%s(*) 집계 함수 없음" -#: parser/parse_func.c:2429 +#: parser/parse_func.c:2430 #, c-format msgid "aggregate %s does not exist" msgstr "%s 집계 함수 없음" -#: parser/parse_func.c:2465 +#: parser/parse_func.c:2466 #, c-format msgid "procedure name \"%s\" is not unique" msgstr "\"%s\" 프로시져는 유일성을 가지지 못합니다(not unique)" -#: parser/parse_func.c:2468 +#: parser/parse_func.c:2469 #, c-format msgid "Specify the argument list to select the procedure unambiguously." msgstr "해당 프로시져의 입력 인자를 다르게 해서 이 모호함을 피하세요." -#: parser/parse_func.c:2473 +#: parser/parse_func.c:2474 #, c-format msgid "aggregate name \"%s\" is not unique" msgstr "\"%s\" 집계 함수가 유일성을 가지지 못합니다(not unique)" -#: parser/parse_func.c:2476 +#: parser/parse_func.c:2477 #, c-format msgid "Specify the argument list to select the aggregate unambiguously." msgstr "해당 집계 함수의 입력 인자를 다르게 해서 이 모호함을 피하세요." -#: parser/parse_func.c:2481 +#: parser/parse_func.c:2482 #, c-format msgid "routine name \"%s\" is not unique" msgstr "\"%s\" 루틴 이름은 유일성을 가지지 못합니다(not unique)" -#: parser/parse_func.c:2484 +#: parser/parse_func.c:2485 #, c-format msgid "Specify the argument list to select the routine unambiguously." msgstr "해당 루틴의 입력 인자를 다르게 해서 이 모호함을 피하세요." -#: parser/parse_func.c:2539 +#: parser/parse_func.c:2540 msgid "set-returning functions are not allowed in JOIN conditions" msgstr "집합 반환 함수는 JOIN 조건에 사용할 수 없음" -#: parser/parse_func.c:2560 +#: parser/parse_func.c:2561 msgid "set-returning functions are not allowed in policy expressions" msgstr "집합 반환 함수는 정책 식에 사용할 수 없음" -#: parser/parse_func.c:2576 +#: parser/parse_func.c:2577 msgid "set-returning functions are not allowed in window definitions" msgstr "집합 반환 함수는 윈도우 함수 정의에 사용할 수 없음" -#: parser/parse_func.c:2613 +#: parser/parse_func.c:2615 msgid "set-returning functions are not allowed in MERGE WHEN conditions" msgstr "집합 반환 함수는 MERGE WHEN 조건절에서 사용할 수 없음" -#: parser/parse_func.c:2617 +#: parser/parse_func.c:2619 msgid "set-returning functions are not allowed in check constraints" msgstr "집합 반환 함수는 check 제약조건에 사용할 수 없음" -#: parser/parse_func.c:2621 +#: parser/parse_func.c:2623 msgid "set-returning functions are not allowed in DEFAULT expressions" msgstr "집합 반환 함수는 DEFAULT 식에서 사용할 수 없음" -#: parser/parse_func.c:2624 +#: parser/parse_func.c:2626 msgid "set-returning functions are not allowed in index expressions" msgstr "집합 반환 함수는 인덱스 식에서 사용할 수 없음" -#: parser/parse_func.c:2627 +#: parser/parse_func.c:2629 msgid "set-returning functions are not allowed in index predicates" msgstr "집합 반환 함수는 함수 기반 인덱스에서 사용할 수 없음" -#: parser/parse_func.c:2630 +#: parser/parse_func.c:2632 msgid "set-returning functions are not allowed in statistics expressions" msgstr "집합 반환 함수는 통계 정보 식에 사용할 수 없음" -#: parser/parse_func.c:2633 +#: parser/parse_func.c:2635 msgid "set-returning functions are not allowed in transform expressions" msgstr "집합 반환 함수는 transform 식에서 사용할 수 없음" -#: parser/parse_func.c:2636 +#: parser/parse_func.c:2638 msgid "set-returning functions are not allowed in EXECUTE parameters" msgstr "집합 반환 함수는 EXECUTE 매개 변수 설정 값으로 사용할 수 없음" -#: parser/parse_func.c:2639 +#: parser/parse_func.c:2641 msgid "set-returning functions are not allowed in trigger WHEN conditions" msgstr "집합 반환 함수는 트리거의 WHEN 조건절에서 사용할 수 없음" -#: parser/parse_func.c:2642 +#: parser/parse_func.c:2644 msgid "set-returning functions are not allowed in partition bound" msgstr "집합 반환 함수는 파티션 범위 식에서 사용할 수 없음" -#: parser/parse_func.c:2645 +#: parser/parse_func.c:2647 msgid "set-returning functions are not allowed in partition key expressions" msgstr "집합 반환 함수는 인덱스 식에서 사용할 수 없음" -#: parser/parse_func.c:2648 +#: parser/parse_func.c:2650 msgid "set-returning functions are not allowed in CALL arguments" msgstr "집합 반환 함수는 CALL 명령의 인자로 사용할 수 없음" -#: parser/parse_func.c:2651 +#: parser/parse_func.c:2653 msgid "set-returning functions are not allowed in COPY FROM WHERE conditions" msgstr "집합 반환 함수는 COPY FROM WHERE 조건절에 사용할 수 없음" -#: parser/parse_func.c:2654 +#: parser/parse_func.c:2656 msgid "" "set-returning functions are not allowed in column generation expressions" msgstr "집합 반환 함수는 미리 계산된 칼럼의 생성식에 사용할 수 없음" -#: parser/parse_merge.c:119 +#: parser/parse_jsontable.c:95 +#, c-format +msgid "" +"Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "" +"EMPTY [ ARRAY ] 또는 ERROR는 최상위 수준 ON ERROR 절에서만 쓸 수 있음" + +#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#, c-format +msgid "duplicate JSON_TABLE column or path name: %s" +msgstr "JSON_TABLE 칼럼이나 패스 이름이 중복됨: %s" + +#: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" msgstr "MERGE 명령에서는 WITH RECURSIVE 구문을 지원하지 않습니다." -#: parser/parse_merge.c:161 +#: parser/parse_merge.c:176 #, c-format msgid "unreachable WHEN clause specified after unconditional WHEN clause" msgstr "" "WHEN 조건절 판단을 하지 못하는 상황에서 그 뒤에 오는 조건 검사는 할 수 없습니" "다." -#: parser/parse_merge.c:191 -#, c-format -msgid "MERGE is not supported for relations with rules." -msgstr "MERGE 명령은 룰을 사용하는 릴레이션에서 사용할 수 없습니다." - -#: parser/parse_merge.c:208 +#: parser/parse_merge.c:222 #, c-format msgid "name \"%s\" specified more than once" msgstr "\"%s\" 이름이 한번 이상 명시되어 있습니다." -#: parser/parse_merge.c:210 +#: parser/parse_merge.c:224 #, c-format msgid "The name is used both as MERGE target table and data source." msgstr "이 이름이 MERGE 타켓 테이블과 데이터 소스 두 곳 모두 사용되었습니다." -#: parser/parse_node.c:87 +#: parser/parse_node.c:82 #, c-format msgid "target lists can have at most %d entries" msgstr "대상 목록은 최대 %d 개의 항목을 지정할 수 있습니다" -#: parser/parse_oper.c:123 parser/parse_oper.c:690 +#: parser/parse_oper.c:114 parser/parse_oper.c:678 #, c-format msgid "postfix operators are not supported" msgstr "postfix 연산자는 지원하지 않습니다" -#: parser/parse_oper.c:130 parser/parse_oper.c:649 utils/adt/regproc.c:509 -#: utils/adt/regproc.c:683 -#, c-format -msgid "operator does not exist: %s" -msgstr "연산자 없음: %s" - -#: parser/parse_oper.c:229 +#: parser/parse_oper.c:217 #, c-format msgid "Use an explicit ordering operator or modify the query." msgstr "" "명시적으로 순차연산자(ordering operator) 를 사용하던지, 또는 query 를 수정하" "도록 하세요." -#: parser/parse_oper.c:485 +#: parser/parse_oper.c:473 #, c-format msgid "operator requires run-time type coercion: %s" msgstr "이 연산자는 실행시에 형 강제전화이 필요합니다: %s" -#: parser/parse_oper.c:641 +#: parser/parse_oper.c:629 #, c-format msgid "operator is not unique: %s" msgstr "연산자가 고유하지 않습니다: %s" -#: parser/parse_oper.c:643 +#: parser/parse_oper.c:631 #, c-format msgid "" "Could not choose a best candidate operator. You might need to add explicit " @@ -19274,7 +19899,7 @@ msgstr "" "가장 적당한 연산자를 선택할 수 없습니다. 명시적 형변환자를 추가해야 할 수도 " "있습니다." -#: parser/parse_oper.c:652 +#: parser/parse_oper.c:640 #, c-format msgid "" "No operator matches the given name and argument type. You might need to add " @@ -19283,7 +19908,7 @@ msgstr "" "지정된 이름 및 인자 형식과 일치하는 연산자가 없습니다. 명시적 형변환자를 추가" "해야 할 수도 있습니다." -#: parser/parse_oper.c:654 +#: parser/parse_oper.c:642 #, c-format msgid "" "No operator matches the given name and argument types. You might need to add " @@ -19292,22 +19917,17 @@ msgstr "" "지정된 이름 및 인자 형식과 일치하는 연산자가 없습니다. 명시적 형변환자를 추가" "해야 할 수도 있습니다." -#: parser/parse_oper.c:714 parser/parse_oper.c:828 -#, c-format -msgid "operator is only a shell: %s" -msgstr "연산자는 셸일 뿐임: %s" - -#: parser/parse_oper.c:816 +#: parser/parse_oper.c:803 #, c-format msgid "op ANY/ALL (array) requires array on right side" msgstr "op ANY/ALL (array) 는 우측에 배열이 있어야 합니다." -#: parser/parse_oper.c:858 +#: parser/parse_oper.c:844 #, c-format msgid "op ANY/ALL (array) requires operator to yield boolean" msgstr "op ANY/ALL (array) 는 불리언을 얻기 위한 연산자가 필요합니다." -#: parser/parse_oper.c:863 +#: parser/parse_oper.c:849 #, c-format msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "op ANY/ALL (array) 는 set 을 return 하지 않는 연산자가 요구 됩니다." @@ -19317,7 +19937,7 @@ msgstr "op ANY/ALL (array) 는 set 을 return 하지 않는 연산자가 요구 msgid "inconsistent types deduced for parameter $%d" msgstr "inconsistent types deduced for parameter $%d" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:309 tcop/postgres.c:744 #, c-format msgid "could not determine data type of parameter $%d" msgstr "$%d 매개 변수의 자료형을 알수가 없습니다." @@ -19337,13 +19957,13 @@ msgstr "테이블 참조 %u 가 명확하지 않습니다 (ambiguous)." msgid "table name \"%s\" specified more than once" msgstr "테이블 이름 \"%s\" 가 한번 이상 명시되어 있습니다." -#: parser/parse_relation.c:494 parser/parse_relation.c:3630 -#: parser/parse_relation.c:3639 +#: parser/parse_relation.c:494 parser/parse_relation.c:3633 +#: parser/parse_relation.c:3642 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "\"%s\" 테이블을 사용하는 FROM 절에 대한 참조가 잘못 되었습니다." -#: parser/parse_relation.c:498 parser/parse_relation.c:3641 +#: parser/parse_relation.c:498 parser/parse_relation.c:3644 #, c-format msgid "" "There is an entry for table \"%s\", but it cannot be referenced from this " @@ -19373,7 +19993,7 @@ msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "\"%s\" 칼럼은 시스템 칼럼입니다. MERGE WHEN 조건절에서 사용될 수 없음" #: parser/parse_relation.c:1236 parser/parse_relation.c:1691 -#: parser/parse_relation.c:2388 +#: parser/parse_relation.c:2384 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "" @@ -19394,92 +20014,92 @@ msgstr "" "WITH RECURSIVE를 사용하거나 WITH 항목의 순서를 변경하여 정방향 참조를 제거하" "십시오." -#: parser/parse_relation.c:1834 +#: parser/parse_relation.c:1833 #, c-format msgid "" "a column definition list is redundant for a function with OUT parameters" msgstr "칼럼 정의 목록이 OUT 매개 변수를 사용하는 함수에서 중복되었음" -#: parser/parse_relation.c:1840 +#: parser/parse_relation.c:1839 #, c-format msgid "" "a column definition list is redundant for a function returning a named " "composite type" msgstr "칼럼 정의 목록이 이름 기반 복합 자료형을 반환하는 함수에서 중복되었음" -#: parser/parse_relation.c:1847 +#: parser/parse_relation.c:1846 #, c-format msgid "" "a column definition list is only allowed for functions returning \"record\"" msgstr "" "칼럼 정의 목록는 오로지 \"record\" 를 리턴하는 함수 내에서만 허용됩니다." -#: parser/parse_relation.c:1858 +#: parser/parse_relation.c:1857 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "칼럼 정의 목록은 \"record\" 를 리턴하는 함수를 필요로 합니다" -#: parser/parse_relation.c:1895 +#: parser/parse_relation.c:1894 #, c-format msgid "column definition lists can have at most %d entries" msgstr "칼럼 정의 목록은 최대 %d 개의 항목을 지정할 수 있습니다" -#: parser/parse_relation.c:1955 +#: parser/parse_relation.c:1954 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "" "FROM 절 내의 함수 \"%s\" 에 지원되지 않는 return 자료형 %s 이 있습니다." -#: parser/parse_relation.c:1982 parser/parse_relation.c:2068 +#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "FROM 절에 쓰는 함수는 최대 %d개의 칼럼을 반환하는 것이여야 함" -#: parser/parse_relation.c:2098 +#: parser/parse_relation.c:2096 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "%s 함수는 %d 개의 칼럼을 반환하는데, %d 개의 칼럼만 명시되었습니다." -#: parser/parse_relation.c:2180 +#: parser/parse_relation.c:2177 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "" "VALUES 뒤에 오는 \"%s\" 구문에는 %d개의 칼럼이 있는데, 지정한 칼럼은 %d개 입" "니다" -#: parser/parse_relation.c:2246 +#: parser/parse_relation.c:2242 #, c-format msgid "joins can have at most %d columns" msgstr "조인에는 최대 %d개의 칼럼을 포함할 수 있음" -#: parser/parse_relation.c:2271 +#: parser/parse_relation.c:2267 #, c-format msgid "" "join expression \"%s\" has %d columns available but %d columns specified" msgstr "" "\"%s\" 조인식에는 %d 개의 칼럼이 있는데, %d 개의 칼럼만 명시되었습니다." -#: parser/parse_relation.c:2361 +#: parser/parse_relation.c:2357 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "\"%s\" WITH 쿼리에 RETURNING 절이 없습니다." -#: parser/parse_relation.c:3632 +#: parser/parse_relation.c:3635 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "아 \"%s\" alias를 참조해야 할 것 같습니다." -#: parser/parse_relation.c:3644 +#: parser/parse_relation.c:3647 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "그 테이블을 참조하려면, 서브쿼리에 LATERAL 예약어를 사용하세요." -#: parser/parse_relation.c:3650 +#: parser/parse_relation.c:3653 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "테이블 \"%s\"에 FROM 절이 빠져 있습니다." -#: parser/parse_relation.c:3690 +#: parser/parse_relation.c:3693 #, c-format msgid "" "There are columns named \"%s\", but they are in tables that cannot be " @@ -19488,12 +20108,12 @@ msgstr "" "\"%s\" 이름의 칼럼이 테이블에 있지만, 이 쿼리의 이 부분에서는 참조될 수 없습" "니다." -#: parser/parse_relation.c:3692 +#: parser/parse_relation.c:3695 #, c-format msgid "Try using a table-qualified name." msgstr "테이블을 지정할 수 있는 이름을 사용하세요." -#: parser/parse_relation.c:3700 +#: parser/parse_relation.c:3703 #, c-format msgid "" "There is a column named \"%s\" in table \"%s\", but it cannot be referenced " @@ -19502,48 +20122,48 @@ msgstr "" "\"%s\" 이름의 칼럼이 \"%s\" 테이블에 있지만, 이 쿼리의 이 부분에서는 참조될 " "수 없습니다." -#: parser/parse_relation.c:3703 +#: parser/parse_relation.c:3706 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "해당 칼럼을 참조하려면, LATERAL 옵션이 있는 서브쿼리를 사용하세요." -#: parser/parse_relation.c:3705 +#: parser/parse_relation.c:3708 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "해당 칼럼을 참조하려면, 테이블 지정 이름을 사용하세요." -#: parser/parse_relation.c:3725 +#: parser/parse_relation.c:3728 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "아마 \"%s.%s\" 칼럼을 참조하는 것 같습니다." -#: parser/parse_relation.c:3739 +#: parser/parse_relation.c:3742 #, c-format msgid "" "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "아마 \"%s.%s\" 칼럼이나 \"%s.%s\" 칼럼을 참조하는 것 같습니다." -#: parser/parse_target.c:481 parser/parse_target.c:796 +#: parser/parse_target.c:480 parser/parse_target.c:795 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "시스템 열 \"%s\"에 할당할 수 없습니다." -#: parser/parse_target.c:509 +#: parser/parse_target.c:508 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "배열 요소를 DEFAULT 로 설정할 수 없습니다." -#: parser/parse_target.c:514 +#: parser/parse_target.c:513 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "하위필드를 DEFAULT로 설정할 수 없습니다." -#: parser/parse_target.c:588 +#: parser/parse_target.c:587 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "열 \"%s\"은(는) %s 자료형인데 표현식은 %s 자료형입니다." -#: parser/parse_target.c:780 +#: parser/parse_target.c:779 #, c-format msgid "" "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a " @@ -19552,7 +20172,7 @@ msgstr "" "\"%s\" 필드 (대상 열 \"%s\")를 지정할 수 없음, %s 자료형은 복합자료형이 아니" "기 때문" -#: parser/parse_target.c:789 +#: parser/parse_target.c:788 #, c-format msgid "" "cannot assign to field \"%s\" of column \"%s\" because there is no such " @@ -19561,7 +20181,7 @@ msgstr "" "\"%s\" 필드 (대상 열 \"%s\")를 지정할 수 없음, %s 자료형에서 그런 칼럼을 찾" "을 수 없음" -#: parser/parse_target.c:869 +#: parser/parse_target.c:877 #, c-format msgid "" "subscripted assignment to \"%s\" requires type %s but expression is of type " @@ -19569,12 +20189,12 @@ msgid "" msgstr "" "\"%s\" subscript 자료형은 %s 형이 필요하지만, 현재 표현식은 %s 자료형입니다" -#: parser/parse_target.c:879 +#: parser/parse_target.c:887 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "하위필드 \"%s\" 는 %s 자료형인데 표현식은 %s 자료형입니다." -#: parser/parse_target.c:1314 +#: parser/parse_target.c:1327 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "테이블이 명시되지 않은 SELECT * 구문은 유효하지 않습니다." @@ -19596,8 +20216,8 @@ msgstr "" msgid "type reference %s converted to %s" msgstr "ype reference %s 가 %s 로 변환되었습니다." -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:390 -#: utils/cache/typcache.c:445 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 +#: utils/cache/typcache.c:452 #, c-format msgid "type \"%s\" is only a shell" msgstr "자료형 \"%s\" 는 오로지 shell 에만 있습니다. " @@ -19617,72 +20237,77 @@ msgstr "자료형 한정자는 단순 상수 또는 식별자여야 함" msgid "invalid type name \"%s\"" msgstr "\"%s\" 자료형 이름은 유효하지 않은 자료형입니다." -#: parser/parse_utilcmd.c:264 +#: parser/parse_utilcmd.c:263 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "상속 하위 테이블로 파티션된 테이블을 만들 수 없음" -#: parser/parse_utilcmd.c:580 +#: parser/parse_utilcmd.c:475 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "임시 시퀀스의 기록된 상태를 지정할 수 없음" + +#: parser/parse_utilcmd.c:611 #, c-format msgid "array of serial is not implemented" msgstr "serial 배열이 구현되지 않음" -#: parser/parse_utilcmd.c:659 parser/parse_utilcmd.c:671 -#: parser/parse_utilcmd.c:730 +#: parser/parse_utilcmd.c:690 parser/parse_utilcmd.c:702 +#: parser/parse_utilcmd.c:761 #, c-format msgid "" "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "NULL/NOT NULL 선언이 서로 충돌합니다 : column \"%s\" of table \"%s\"" -#: parser/parse_utilcmd.c:683 +#: parser/parse_utilcmd.c:714 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "\"%s\" 칼럼(\"%s\" 테이블)에 대해 여러 개의 기본 값이 지정됨" -#: parser/parse_utilcmd.c:700 +#: parser/parse_utilcmd.c:731 #, c-format msgid "identity columns are not supported on typed tables" msgstr "" "식별 칼럼은 타입드 테이블(typed table - 자료형으로써 테이블)에서는 쓸 수 없음" -#: parser/parse_utilcmd.c:704 +#: parser/parse_utilcmd.c:735 #, c-format msgid "identity columns are not supported on partitions" msgstr "식별 칼럼은 파티션된 테이블에서는 사용할 수 없음" -#: parser/parse_utilcmd.c:713 +#: parser/parse_utilcmd.c:744 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "\"%s\" 칼럼(\"%s\" 테이블)에 대해 여러 개의 식별자 지정이 사용되었음" -#: parser/parse_utilcmd.c:743 +#: parser/parse_utilcmd.c:774 #, c-format msgid "generated columns are not supported on typed tables" msgstr "" "미리 계산된 칼럼은 타입드 테이블(typed table - 자료형으로써 테이블)에서는 쓸 " "수 없음" -#: parser/parse_utilcmd.c:747 +#: parser/parse_utilcmd.c:778 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "\"%s\" 칼럼(\"%s\" 테이블)에 대해 여러 개의 생성식이 지정됨" -#: parser/parse_utilcmd.c:765 parser/parse_utilcmd.c:880 +#: parser/parse_utilcmd.c:796 parser/parse_utilcmd.c:911 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "기본키 제약 조건을 외부 테이블에서는 사용할 수 없음" -#: parser/parse_utilcmd.c:774 parser/parse_utilcmd.c:890 +#: parser/parse_utilcmd.c:805 parser/parse_utilcmd.c:921 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "유니크 제약 조건은 외부 테이블에서는 사용할 수 없음" -#: parser/parse_utilcmd.c:819 +#: parser/parse_utilcmd.c:850 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "\"%s\" 칼럼(\"%s\" 테이블)에 대해 default와 식별자 정의가 함께 있음" -#: parser/parse_utilcmd.c:827 +#: parser/parse_utilcmd.c:858 #, c-format msgid "" "both default and generation expression specified for column \"%s\" of table " @@ -19691,7 +20316,7 @@ msgstr "" "\"%s\" 칼럼(해당 테이블 \"%s\")에 대해 default 정의와 미리 계산된 표현식이 함" "께 있음" -#: parser/parse_utilcmd.c:835 +#: parser/parse_utilcmd.c:866 #, c-format msgid "" "both identity and generation expression specified for column \"%s\" of table " @@ -19700,115 +20325,105 @@ msgstr "" "\"%s\" 칼럼(해당 테이블 \"%s\")에 대해 identity 정의와 미리 계산된 표현식이 " "함께 있음" -#: parser/parse_utilcmd.c:900 +#: parser/parse_utilcmd.c:931 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "제외 제약 조건은 외부 테이블에서는 사용할 수 없음" -#: parser/parse_utilcmd.c:906 -#, c-format -msgid "exclusion constraints are not supported on partitioned tables" -msgstr "제외 제약 조건은 파티션된 테이블에서는 사용할 수 없음" - -#: parser/parse_utilcmd.c:971 +#: parser/parse_utilcmd.c:996 #, c-format msgid "LIKE is not supported for creating foreign tables" msgstr "외부 테이블을 만들 때는 LIKE 옵션을 쓸 수 없음" -#: parser/parse_utilcmd.c:984 +#: parser/parse_utilcmd.c:1009 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "\"%s\" 릴레이션은 LIKE 절에서 바르지 않음" -#: parser/parse_utilcmd.c:1741 parser/parse_utilcmd.c:1849 +#: parser/parse_utilcmd.c:1736 parser/parse_utilcmd.c:1844 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "\"%s\" 인덱스는 전체 로우 테이블 참조를 포함하고 있습니다." -#: parser/parse_utilcmd.c:2236 +#: parser/parse_utilcmd.c:2242 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "CREATE TABLE 명령에서 이미 있는 인덱스는 사용할 수 없습니다." -#: parser/parse_utilcmd.c:2256 +#: parser/parse_utilcmd.c:2262 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "\"%s\" 인덱스는 이미 한 제약 조건에서 사용 중입니다." -#: parser/parse_utilcmd.c:2271 -#, c-format -msgid "index \"%s\" is not valid" -msgstr "\"%s\" 인덱스는 사용가능 상태가 아님" - -#: parser/parse_utilcmd.c:2277 +#: parser/parse_utilcmd.c:2283 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\" 개체는 유니크 인덱스가 아닙니다" -#: parser/parse_utilcmd.c:2278 parser/parse_utilcmd.c:2285 -#: parser/parse_utilcmd.c:2292 parser/parse_utilcmd.c:2369 +#: parser/parse_utilcmd.c:2284 parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2298 parser/parse_utilcmd.c:2375 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "이 인덱스를 이용하는 기본키나 유니크 제약조건은 만들 수 없습니다." -#: parser/parse_utilcmd.c:2284 +#: parser/parse_utilcmd.c:2290 #, c-format msgid "index \"%s\" contains expressions" msgstr "\"%s\" 인덱스에 표현식이 포함되어 있음" -#: parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2297 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\" 개체는 부분 인덱스임" -#: parser/parse_utilcmd.c:2303 +#: parser/parse_utilcmd.c:2309 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\" 개체는 지연가능한 인덱스임" -#: parser/parse_utilcmd.c:2304 +#: parser/parse_utilcmd.c:2310 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "" "지연 가능한 인덱스를 사용해서 지연 불가능한 제약 조건은 만들 수 없습니다." -#: parser/parse_utilcmd.c:2368 +#: parser/parse_utilcmd.c:2374 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "\"%s\" 인덱스 %d 번째 칼럼의 기본 정렬 방법이 없음" -#: parser/parse_utilcmd.c:2525 +#: parser/parse_utilcmd.c:2531 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "기본키 제약 조건에서 \"%s\" 칼럼이 두 번 지정되었습니다" -#: parser/parse_utilcmd.c:2531 +#: parser/parse_utilcmd.c:2537 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "고유 제약 조건에서 \"%s\" 칼럼이 두 번 지정되었습니다" -#: parser/parse_utilcmd.c:2878 +#: parser/parse_utilcmd.c:2871 #, c-format msgid "" "index expressions and predicates can refer only to the table being indexed" msgstr "인덱스 식 및 술어는 인덱싱되는 테이블만 참조할 수 있음" -#: parser/parse_utilcmd.c:2950 +#: parser/parse_utilcmd.c:2943 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "통계 정보 식은 참조되는 테이블만 대상이어야 함" -#: parser/parse_utilcmd.c:2993 +#: parser/parse_utilcmd.c:2986 #, c-format msgid "rules on materialized views are not supported" msgstr "구체화된 뷰에서의 룰은 지원하지 않음" -#: parser/parse_utilcmd.c:3053 +#: parser/parse_utilcmd.c:3046 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "룰에서 지정한 WHERE 조건에 다른 릴레이션에 대한 참조를 포함할 수 없음" -#: parser/parse_utilcmd.c:3125 +#: parser/parse_utilcmd.c:3118 #, c-format msgid "" "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE " @@ -19817,154 +20432,154 @@ msgstr "" "룰에서 지정한 WHERE 조건이 있는 규칙에는 SELECT, INSERT, UPDATE 또는 DELETE " "작업만 포함할 수 있음" -#: parser/parse_utilcmd.c:3143 parser/parse_utilcmd.c:3244 -#: rewrite/rewriteHandler.c:539 rewrite/rewriteManip.c:1087 +#: parser/parse_utilcmd.c:3136 parser/parse_utilcmd.c:3237 +#: rewrite/rewriteHandler.c:544 rewrite/rewriteManip.c:1095 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "conditional UNION/INTERSECT/EXCEPT 구문은 구현되어 있지 않다" -#: parser/parse_utilcmd.c:3161 +#: parser/parse_utilcmd.c:3154 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "ON SELECT 룰은 OLD를 사용할 수 없음" -#: parser/parse_utilcmd.c:3165 +#: parser/parse_utilcmd.c:3158 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "ON SELECT 룰은 NEW를 사용할 수 없음" -#: parser/parse_utilcmd.c:3174 +#: parser/parse_utilcmd.c:3167 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "ON INSERT 룰은 OLD를 사용할 수 없음" -#: parser/parse_utilcmd.c:3180 +#: parser/parse_utilcmd.c:3173 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "ON DELETE 룰은 NEW를 사용할 수 없음" -#: parser/parse_utilcmd.c:3208 +#: parser/parse_utilcmd.c:3201 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "WITH 쿼리 안에서 OLD 예약어를 참조할 수 없습니다." -#: parser/parse_utilcmd.c:3215 +#: parser/parse_utilcmd.c:3208 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "WITH 쿼리 안에서 NEW 예약어를 참조할 수 없습니다." -#: parser/parse_utilcmd.c:3667 +#: parser/parse_utilcmd.c:3664 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "DEFERABLE 절이 잘못 놓여져 있습니다" -#: parser/parse_utilcmd.c:3672 parser/parse_utilcmd.c:3687 +#: parser/parse_utilcmd.c:3669 parser/parse_utilcmd.c:3684 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "여러 개의 DEFERRABLE/NOT DEFERRABLE절은 사용할 수 없습니다" -#: parser/parse_utilcmd.c:3682 +#: parser/parse_utilcmd.c:3679 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "NOT DEFERABLE 절이 잘못 놓여 있습니다" -#: parser/parse_utilcmd.c:3695 parser/parse_utilcmd.c:3721 gram.y:5990 +#: parser/parse_utilcmd.c:3692 parser/parse_utilcmd.c:3718 gram.y:6114 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" msgstr "INITIALLY DEFERRED 로 선언된 조건문은 반드시 DEFERABLE 여야만 한다" -#: parser/parse_utilcmd.c:3703 +#: parser/parse_utilcmd.c:3700 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "INITIALLY DEFERRED 절이 잘못 놓여 있습니다" -#: parser/parse_utilcmd.c:3708 parser/parse_utilcmd.c:3734 +#: parser/parse_utilcmd.c:3705 parser/parse_utilcmd.c:3731 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "여러 개의 INITIALLY IMMEDIATE/DEFERRED 절은 허용되지 않습니다" -#: parser/parse_utilcmd.c:3729 +#: parser/parse_utilcmd.c:3726 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "INITIALLY IMMEDIATE 절이 잘못 놓여 있습니다" -#: parser/parse_utilcmd.c:3922 +#: parser/parse_utilcmd.c:3919 #, c-format msgid "" "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "CREATE 구문에 명시된 schema (%s) 가 생성된 (%s) 의 것과 다릅니다" -#: parser/parse_utilcmd.c:3957 +#: parser/parse_utilcmd.c:3954 #, c-format msgid "\"%s\" is not a partitioned table" msgstr "\"%s\" 개체는 파티션된 테이블이 아님" -#: parser/parse_utilcmd.c:3964 +#: parser/parse_utilcmd.c:3961 #, c-format msgid "table \"%s\" is not partitioned" msgstr "\"%s\" 테이블은 파티션되어 있지 않음" -#: parser/parse_utilcmd.c:3971 +#: parser/parse_utilcmd.c:3968 #, c-format msgid "index \"%s\" is not partitioned" msgstr "\"%s\" 인덱스는 파티션 된 인덱스가 아님" -#: parser/parse_utilcmd.c:4011 +#: parser/parse_utilcmd.c:4008 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "해시 파티션된 테이블은 기본 파티션을 가질 수 없음" -#: parser/parse_utilcmd.c:4028 +#: parser/parse_utilcmd.c:4025 #, c-format msgid "invalid bound specification for a hash partition" msgstr "해시 파티션용 범위 명세가 잘못됨" -#: parser/parse_utilcmd.c:4034 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4031 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "해시 파티션용 모듈은 영(0)보다 큰 정수 값이어야 함" -#: parser/parse_utilcmd.c:4041 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4038 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "해시 파티션용 나머지 처리기는 modulus 보다 작아야 함" -#: parser/parse_utilcmd.c:4054 +#: parser/parse_utilcmd.c:4051 #, c-format msgid "invalid bound specification for a list partition" msgstr "list 파티션을 위한 범위 설정이 잘못됨" -#: parser/parse_utilcmd.c:4107 +#: parser/parse_utilcmd.c:4104 #, c-format msgid "invalid bound specification for a range partition" msgstr "range 파티션을 위한 범위 설정이 잘못됨" -#: parser/parse_utilcmd.c:4113 +#: parser/parse_utilcmd.c:4110 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "FROM에는 파티션 칼럼 당 딱 하나의 값만 지정해야 함" -#: parser/parse_utilcmd.c:4117 +#: parser/parse_utilcmd.c:4114 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "TO에는 파티션 칼럼 당 딱 하나의 값만 지정해야 함" -#: parser/parse_utilcmd.c:4231 +#: parser/parse_utilcmd.c:4228 #, c-format msgid "cannot specify NULL in range bound" msgstr "range 범위에는 NULL 값을 사용할 수 없음" -#: parser/parse_utilcmd.c:4280 +#: parser/parse_utilcmd.c:4277 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "MAXVALUE 뒤에 오는 모든 범위는 MAXVALUE 여야합니다." -#: parser/parse_utilcmd.c:4287 +#: parser/parse_utilcmd.c:4284 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "MINVALUE 뒤에 오는 모든 범위는 MINVALUE 여야합니다." -#: parser/parse_utilcmd.c:4330 +#: parser/parse_utilcmd.c:4327 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "지정된 값은 %s 형으로 형변환 할 수 없음, 해당 칼럼: \"%s\"" @@ -19977,12 +20592,12 @@ msgstr "UESCAPE 표현식은 앞에 한글자만 있어야합니다." msgid "invalid Unicode escape character" msgstr "잘못된 유니코드 이스케이프 문자" -#: parser/parser.c:347 scan.l:1390 +#: parser/parser.c:347 scan.l:1393 #, c-format msgid "invalid Unicode escape value" msgstr "잘못된 유니코드 이스케이프 값" -#: parser/parser.c:494 utils/adt/varlena.c:6505 scan.l:701 +#: parser/parser.c:494 utils/adt/varlena.c:6640 scan.l:716 #, c-format msgid "invalid Unicode escape" msgstr "잘못된 유니코드 이스케이프 값" @@ -19992,8 +20607,8 @@ msgstr "잘못된 유니코드 이스케이프 값" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "유니코드 이스케이프는 \\XXXX 또는 \\+XXXXXX 형태여야 합니다." -#: parser/parser.c:523 utils/adt/varlena.c:6530 scan.l:662 scan.l:678 -#: scan.l:694 +#: parser/parser.c:523 utils/adt/varlena.c:6665 scan.l:677 scan.l:693 +#: scan.l:709 #, c-format msgid "invalid Unicode surrogate pair" msgstr "잘못된 유니코드 대리 쌍" @@ -20003,28 +20618,28 @@ msgstr "잘못된 유니코드 대리 쌍" msgid "identifier \"%s\" will be truncated to \"%.*s\"" msgstr "\"%s\" 식별자는 \"%.*s\"(으)로 잘림" -#: partitioning/partbounds.c:2921 +#: partitioning/partbounds.c:2920 #, c-format msgid "partition \"%s\" conflicts with existing default partition \"%s\"" msgstr "\"%s\" 파티션이 \"%s\" 기본 파티션과 겹칩니다." -#: partitioning/partbounds.c:2973 partitioning/partbounds.c:2992 -#: partitioning/partbounds.c:3014 +#: partitioning/partbounds.c:2972 partitioning/partbounds.c:2991 +#: partitioning/partbounds.c:3013 #, c-format msgid "" "every hash partition modulus must be a factor of the next larger modulus" msgstr "모든 해시 파티션 구분값은 최대값보다 작아야합니다." -#: partitioning/partbounds.c:2974 partitioning/partbounds.c:3015 +#: partitioning/partbounds.c:2973 partitioning/partbounds.c:3014 #, c-format msgid "" "The new modulus %d is not a factor of %d, the modulus of existing partition " "\"%s\"." msgstr "" -"새 해시 파티션 구분값(나머지값) %d 값은 %d의 인수가 아닙니다. 이미 있는 \"%s" -"\" 하위 파티션은 이 값을 구분값으로 사용합니다." +"새 해시 파티션 구분값(나머지값) %d 값은 %d의 인수가 아닙니다. 이미 있는 " +"\"%s\" 하위 파티션은 이 값을 구분값으로 사용합니다." -#: partitioning/partbounds.c:2993 +#: partitioning/partbounds.c:2992 #, c-format msgid "" "The new modulus %d is not divisible by %d, the modulus of existing partition " @@ -20033,22 +20648,22 @@ msgstr "" "새 해시 구분값 %d 값은 %d 값으로 나눌 수 없습니다. 이미 있는 \"%s\" 하위 파티" "션은 이 값을 나누기 값으로 사용합니다." -#: partitioning/partbounds.c:3128 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "\"%s\" 파티션용 범위 지정이 비어있습니다." -#: partitioning/partbounds.c:3130 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "하한값(%s)은 상한값(%s)과 같거나 커야 합니다" -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "\"%s\" 파티션이 \"%s\" 파티션과 겹칩니다." -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "" "skipped scanning foreign table \"%s\" which is a partition of default " @@ -20057,32 +20672,32 @@ msgstr "" "\"%s\" 외부 테이블 탐색은 생략함, 이 테이블은 \"%s\" 기본 파티션 테이블의 파" "티션이기 때문" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "" "remainder for hash partition must be an integer value greater than or equal " "to zero" msgstr "해시 파티션용 나머지 구분값은 0보다 크거나 같은 정수값이어야 함" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\" 개체는 해시 파티션된 테이블이 아님" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "" "number of partitioning columns (%d) does not match number of partition keys " "provided (%d)" msgstr "파티션 칼럼 수: %d, 제공된 파티션 키 수: %d 서로 다름" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "" "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "파티션 키의 %d 번째 칼럼 자료형은 %s 형이지만, %s 형의 값이 지정되었음" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "" "column %d of the partition key has type \"%s\", but supplied value is of " @@ -20091,23 +20706,23 @@ msgstr "" "파티션 키로 사용하는 %d 번째 칼럼의 자료형은 \"%s\" 형이지만, 지정한 값은 " "\"%s\" 자료형을 사용했습니다." -#: port/pg_sema.c:209 port/pg_shmem.c:708 port/posix_sema.c:209 -#: port/sysv_sema.c:323 port/sysv_shmem.c:708 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 +#: port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "\"%s\" 데이터 디렉터리 상태를 파악할 수 없음: %m" -#: port/pg_shmem.c:223 port/sysv_shmem.c:223 +#: port/pg_shmem.c:224 port/sysv_shmem.c:224 #, c-format msgid "could not create shared memory segment: %m" msgstr "공유 메모리 세그먼트를 만들 수 없음: %m" -#: port/pg_shmem.c:224 port/sysv_shmem.c:224 +#: port/pg_shmem.c:225 port/sysv_shmem.c:225 #, c-format msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)." msgstr "shmget(키=%lu, 크기=%zu, 0%o) 시스템 콜 실패" -#: port/pg_shmem.c:228 port/sysv_shmem.c:228 +#: port/pg_shmem.c:229 port/sysv_shmem.c:229 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " @@ -20120,7 +20735,7 @@ msgstr "" "값보다 크거나, SHMMIN 값보다 적은 경우 발생합니다.\n" "공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오." -#: port/pg_shmem.c:235 port/sysv_shmem.c:235 +#: port/pg_shmem.c:236 port/sysv_shmem.c:236 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " @@ -20133,7 +20748,7 @@ msgstr "" "큰 경우 발생합니다. 커널 환경 변수인 SHMALL 값을 좀 더 크게 설정하세요.\n" "공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오." -#: port/pg_shmem.c:241 port/sysv_shmem.c:241 +#: port/pg_shmem.c:242 port/sysv_shmem.c:242 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs " @@ -20149,62 +20764,63 @@ msgstr "" "확보하세요.\n" "공유 메모리 설정에 대한 보다 자세한 내용은 PostgreSQL 문서를 참조하십시오." -#: port/pg_shmem.c:583 port/sysv_shmem.c:583 port/win32_shmem.c:641 +#: port/pg_shmem.c:584 port/sysv_shmem.c:584 port/win32_shmem.c:646 #, c-format -msgid "huge_page_size must be 0 on this platform." -msgstr "huge_page_size 값은 이 플랫폼에서는 0이어야 합니다." +msgid "\"huge_page_size\" must be 0 on this platform." +msgstr "\"huge_page_size\" 값은 이 플랫폼에서는 0이어야 합니다." -#: port/pg_shmem.c:646 port/sysv_shmem.c:646 +#: port/pg_shmem.c:655 port/sysv_shmem.c:655 #, c-format msgid "could not map anonymous shared memory: %m" msgstr "가용 공유 메모리 확보 실패: %m" -#: port/pg_shmem.c:648 port/sysv_shmem.c:648 +#: port/pg_shmem.c:657 port/sysv_shmem.c:657 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " "segment exceeded available memory, swap space, or huge pages. To reduce the " "request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, " -"perhaps by reducing shared_buffers or max_connections." +"perhaps by reducing \"shared_buffers\" or \"max_connections\"." msgstr "" "이 오류는 일반적으로 PostgreSQL에서 사용할 공유 메모리를 확보하지 못 했을 때 " "발생합니다(물리 메모리, 스왑, huge page). 현재 요구 크기(%zu 바이트)를 좀 줄" -"여 보십시오. 줄이는 방법은, shared_buffers 값을 줄이거나 max_connections 값" +"여 보십시오. 줄이는 방법은, \"shared_buffers\"나 \"max_connections\" 값" "을 줄여 보십시오." -#: port/pg_shmem.c:716 port/sysv_shmem.c:716 +#: port/pg_shmem.c:725 port/sysv_shmem.c:725 #, c-format msgid "huge pages not supported on this platform" msgstr "huge page 기능은 이 플랫폼에서 지원되지 않음" -#: port/pg_shmem.c:723 port/sysv_shmem.c:723 +#: port/pg_shmem.c:732 port/sysv_shmem.c:732 #, c-format -msgid "huge pages not supported with the current shared_memory_type setting" -msgstr "현재 shared_memory_type 설정은 huge page 사용을 지원하지 않습니다." +msgid "" +"huge pages not supported with the current \"shared_memory_type\" setting" +msgstr "현재 \"shared_memory_type\" 설정은 huge page 사용을 지원하지 않습니다." -#: port/pg_shmem.c:783 port/sysv_shmem.c:783 utils/init/miscinit.c:1351 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1401 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "미리 확보된 공유 메모리 영역 (%lu 키, %lu ID)이 여전히 사용중입니다" -#: port/pg_shmem.c:786 port/sysv_shmem.c:786 utils/init/miscinit.c:1353 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1403 #, c-format msgid "" "Terminate any old server processes associated with data directory \"%s\"." msgstr "" "\"%s\" 데이터 디렉터리를 사용하는 옛 서버 프로세스들을 모두 중지시키세요." -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "세마포어를 만들 수 없음: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "semget(%lu, %d, 0%o) 호출에 의한 시스템 콜 실패" -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs " @@ -20212,7 +20828,7 @@ msgid "" "(SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be " "exceeded. You need to raise the respective kernel parameter. " "Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its " -"max_connections parameter.\n" +"\"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring " "your system for PostgreSQL." msgstr "" @@ -20221,11 +20837,11 @@ msgstr "" "이 오류는 시스템에서 지정한 최소 세마포어 수(SEMMNI)가 너무 크거나, 최대 세마" "포어 수(SEMMNS)가 너무 적어서 서버를 실행할 수 없을 때 발생합니다. 이에 따" "라, 정상적으로 서버가 실행되려면, 시스템 값들을 조정할 필요가 있습니다. 아니" -"면, 다른 방법으로, PostgreSQL의 환경 설정에서 max_connections 값을 줄여서 세" +"면, 다른 방법으로, PostgreSQL의 환경 설정에서 \"max_connections\" 값을 줄여서 세" "마포어 사용 수를 줄여보십시오.\n" "보다 자세한 내용은 PostgreSQL 관리자 메뉴얼을 참조 하십시오." -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "" "You possibly need to raise your kernel's SEMVMX value to be at least %d. " @@ -20360,62 +20976,52 @@ msgstr "실패한 시스템 호출은 DuplicateHandle입니다." msgid "Failed system call was MapViewOfFileEx." msgstr "실패한 시스템 호출은 MapViewOfFileEx입니다." -#: postmaster/autovacuum.c:417 -#, c-format -msgid "could not fork autovacuum launcher process: %m" -msgstr "autovacuum 실행기 프로세스를 실행할 수 없음: %m" - -#: postmaster/autovacuum.c:764 +#: postmaster/autovacuum.c:686 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "autovacuum 작업자가 너무 오래전에 시작되어 중지됨" -#: postmaster/autovacuum.c:1489 -#, c-format -msgid "could not fork autovacuum worker process: %m" -msgstr "autovacuum 작업자 프로세스를 실행할 수 없음: %m" - -#: postmaster/autovacuum.c:2334 +#: postmaster/autovacuum.c:2203 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "" "autovacuum: 더 이상 사용하지 않는 \"%s.%s.%s\" 임시 테이블을 삭제하는 중" -#: postmaster/autovacuum.c:2570 +#: postmaster/autovacuum.c:2439 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "\"%s.%s.%s\" 테이블 대상으로 자동 vacuum 작업 함" -#: postmaster/autovacuum.c:2573 +#: postmaster/autovacuum.c:2442 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "\"%s.%s.%s\" 테이블 자동 분석" -#: postmaster/autovacuum.c:2767 +#: postmaster/autovacuum.c:2636 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "\"%s.%s.%s\" 릴레이션 작업 항목 작업 중" -#: postmaster/autovacuum.c:3381 +#: postmaster/autovacuum.c:3254 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "서버 설정 정보가 잘못되어 자동 청소 작업이 실행되지 못했습니다." -#: postmaster/autovacuum.c:3382 +#: postmaster/autovacuum.c:3255 #, c-format msgid "Enable the \"track_counts\" option." msgstr "\"track_counts\" 옵션을 사용하십시오." -#: postmaster/bgworker.c:259 +#: postmaster/bgworker.c:260 #, c-format msgid "" -"inconsistent background worker state (max_worker_processes=%d, total_slots=" -"%d)" +"inconsistent background worker state (max_worker_processes=%d, " +"total_slots=%d)" msgstr "" -"백그라운드 작업자의 정합성이 맞지 않음 (max_worker_processes=%d, total_slots=" -"%d)" +"백그라운드 작업자의 정합성이 맞지 않음 (max_worker_processes=%d, " +"total_slots=%d)" -#: postmaster/bgworker.c:669 +#: postmaster/bgworker.c:651 #, c-format msgid "" "background worker \"%s\": background workers without shared memory access " @@ -20424,7 +21030,7 @@ msgstr "" "\"%s\" 백그라운드 작업자: 공유 메모리 접근 않는 백그라운드 작업자를 지원하지 " "않음" -#: postmaster/bgworker.c:680 +#: postmaster/bgworker.c:662 #, c-format msgid "" "background worker \"%s\": cannot request database access if starting at " @@ -20433,31 +21039,31 @@ msgstr "" "\"%s\" 백그라운드 작업자: postmaster 시작 중인 상태라면, 데이터베이스 접근을 " "요청할 수 없음" -#: postmaster/bgworker.c:694 +#: postmaster/bgworker.c:676 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "\"%s\" 백그라운드 작업자: 잘못된 재실행 간격" -#: postmaster/bgworker.c:709 +#: postmaster/bgworker.c:691 #, c-format msgid "" "background worker \"%s\": parallel workers may not be configured for restart" msgstr "\"%s\" 백그라운드 작업자: 이 병렬 작업자는 재실행 설정이 없음" -#: postmaster/bgworker.c:733 tcop/postgres.c:3255 +#: postmaster/bgworker.c:715 tcop/postgres.c:3312 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "관리자 명령에 의해 \"%s\" 백그라운드 작업자를 종료합니다." -#: postmaster/bgworker.c:890 +#: postmaster/bgworker.c:888 #, c-format msgid "" -"background worker \"%s\": must be registered in shared_preload_libraries" +"background worker \"%s\": must be registered in \"shared_preload_libraries\"" msgstr "" -"\"%s\" 백그라운드 작업자: 먼저 shared_preload_libraries 설정값으로 등록되어" +"\"%s\" 백그라운드 작업자: 먼저 \"shared_preload_libraries\" 설정값으로 등록되어" "야 합니다." -#: postmaster/bgworker.c:902 +#: postmaster/bgworker.c:911 #, c-format msgid "" "background worker \"%s\": only dynamic background workers can request " @@ -20465,230 +21071,319 @@ msgid "" msgstr "" "\"%s\" 백그라운드 작업자: 동적 백그라운드 작업자만 알림을 요청할 수 있음" -#: postmaster/bgworker.c:917 +#: postmaster/bgworker.c:926 #, c-format msgid "too many background workers" msgstr "백그라운드 작업자가 너무 많음" -#: postmaster/bgworker.c:918 +#: postmaster/bgworker.c:927 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "" "Up to %d background workers can be registered with the current settings." msgstr[0] "현재 설정으로는 %d개의 백그라운드 작업자를 사용할 수 있습니다." -#: postmaster/bgworker.c:922 +#: postmaster/bgworker.c:931 postmaster/checkpointer.c:445 #, c-format -msgid "" -"Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "\"max_worker_processes\" 환경 매개 변수 값을 좀 느려보십시오." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "\"%s\" 환경 매개 변수 값을 좀 늘려보십시오." -#: postmaster/checkpointer.c:431 +#: postmaster/checkpointer.c:441 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" msgstr[0] "체크포인트가 너무 자주 발생함 (%d초 간격)" -#: postmaster/checkpointer.c:435 -#, c-format -msgid "Consider increasing the configuration parameter \"max_wal_size\"." -msgstr "\"max_wal_size\" 환경 매개 변수 값을 좀 느려보십시오." - -#: postmaster/checkpointer.c:1059 +#: postmaster/checkpointer.c:1067 #, c-format msgid "checkpoint request failed" msgstr "체크포인트 요청 실패" -#: postmaster/checkpointer.c:1060 +#: postmaster/checkpointer.c:1068 #, c-format msgid "Consult recent messages in the server log for details." msgstr "더 자세한 것은 서버 로그 파일을 살펴보십시오." -#: postmaster/pgarch.c:416 +#: postmaster/launch_backend.c:381 #, c-format -msgid "archive_mode enabled, yet archiving is not configured" -msgstr "archive_mode가 활성화 되었는데 아카이브 관련 세부 설정이 되어있지 않음" +msgid "could not execute server process \"%s\": %m" +msgstr "\"%s\" 서버 프로세스를 실행할 수 없음: %m" -#: postmaster/pgarch.c:438 +#: postmaster/launch_backend.c:434 #, c-format -msgid "removed orphan archive status file \"%s\"" -msgstr "필요 없는 \"%s\" 아카이브 상태 파일이 삭제됨" +msgid "could not create backend parameter file mapping: error code %lu" +msgstr "백엔드 매개 변수 맵핑 파일을 만들 수 없음: 오류 코드 %lu" -#: postmaster/pgarch.c:448 +#: postmaster/launch_backend.c:442 #, c-format -msgid "" -"removal of orphan archive status file \"%s\" failed too many times, will try " -"again later" -msgstr "" -"필요 없는 \"%s\" 아카이브 상태 파일 삭제 작업이 계속 실패하고 있습니다. 다음" -"에 또 시도할 것입니다." +msgid "could not map backend parameter memory: error code %lu" +msgstr "백엔드 매개 변수 메모리를 맵핑할 수 없음: 오류 코드 %lu" -#: postmaster/pgarch.c:484 +#: postmaster/launch_backend.c:459 #, c-format -msgid "" +msgid "subprocess command line too long" +msgstr "서브프로세스 명령행이 너무 깁니다." + +#: postmaster/launch_backend.c:477 +#, c-format +msgid "CreateProcess() call failed: %m (error code %lu)" +msgstr "CreateProcess() 호출 실패: %m (오류 코드 %lu)" + +#: postmaster/launch_backend.c:504 +#, c-format +msgid "could not unmap view of backend parameter file: error code %lu" +msgstr "백엔드 매개 변수 파일의 view를 unmap할 수 없음: 오류 코드 %lu" + +#: postmaster/launch_backend.c:508 +#, c-format +msgid "could not close handle to backend parameter file: error code %lu" +msgstr "백엔드 매개 변수 파일을 닫을 수 없음: 오류 코드 %lun" + +#: postmaster/launch_backend.c:530 +#, c-format +msgid "giving up after too many tries to reserve shared memory" +msgstr "공유 메모리 확보 작업을 여러 번 시도했으나 실패 함" + +#: postmaster/launch_backend.c:531 +#, c-format +msgid "This might be caused by ASLR or antivirus software." +msgstr "이 현상은 ASLR 또는 바이러스 검사 소프트웨어 때문일 수 있습니다." + +#: postmaster/launch_backend.c:834 +#, c-format +msgid "could not duplicate socket %d for use in backend: error code %d" +msgstr "백엔드에서 사용하기 위해 %d 소켓을 복사할 수 없음: 오류 코드 %d" + +#: postmaster/launch_backend.c:866 +#, c-format +msgid "could not create inherited socket: error code %d\n" +msgstr "상속된 소켓을 만들 수 없음: 오류 코드 %d\n" + +#: postmaster/launch_backend.c:895 +#, c-format +msgid "could not open backend variables file \"%s\": %m\n" +msgstr "\"%s\" 백엔드 변수 파일을 열 수 없음: %m\n" + +#: postmaster/launch_backend.c:901 +#, c-format +msgid "could not read from backend variables file \"%s\": %m\n" +msgstr "\"%s\" 백엔드 변수 파일을 읽을 수 없음: %m\n" + +#: postmaster/launch_backend.c:912 +#, c-format +msgid "could not read startup data from backend variables file \"%s\": %m\n" +msgstr "\"%s\" 백엔드 변수 파일에서 시작 데이터를 읽을 수 없음: %m\n" + +#: postmaster/launch_backend.c:924 +#, c-format +msgid "could not remove file \"%s\": %m\n" +msgstr "\"%s\" 파일을 삭제할 수 없음: %m\n" + +#: postmaster/launch_backend.c:940 +#, c-format +msgid "could not map view of backend variables: error code %lu\n" +msgstr "백엔드 변수 파일의 view를 map할 수 없음: 오류 코드 %lu\n" + +#: postmaster/launch_backend.c:959 +#, c-format +msgid "could not unmap view of backend variables: error code %lu\n" +msgstr "백엔드 변수 파일의 view를 unmap할 수 없음: 오류 코드 %lu\n" + +#: postmaster/launch_backend.c:966 +#, c-format +msgid "could not close handle to backend parameter variables: error code %lu\n" +msgstr "백엔드 변수 파일을 닫을 수 없음: 오류 코드 %lu\n" + +#: postmaster/pgarch.c:428 +#, c-format +msgid "\"archive_mode\" enabled, yet archiving is not configured" +msgstr "\"archive_mode\"가 활성화 되었지만 아카이브 관련 세부 설정이 되어있지 않음" + +#: postmaster/pgarch.c:452 +#, c-format +msgid "removed orphan archive status file \"%s\"" +msgstr "필요 없는 \"%s\" 아카이브 상태 파일이 삭제됨" + +#: postmaster/pgarch.c:462 +#, c-format +msgid "" +"removal of orphan archive status file \"%s\" failed too many times, will try " +"again later" +msgstr "" +"필요 없는 \"%s\" 아카이브 상태 파일 삭제 작업이 계속 실패하고 있습니다. 다음" +"에 또 시도할 것입니다." + +#: postmaster/pgarch.c:498 +#, c-format +msgid "" "archiving write-ahead log file \"%s\" failed too many times, will try again " "later" msgstr "" "\"%s\" 트랜잭션 로그 파일 아카이브 작업이 계속 실패하고 있습니다. 다음에 또 " "시도할 것입니다." -#: postmaster/pgarch.c:791 postmaster/pgarch.c:830 +#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 #, c-format -msgid "both archive_command and archive_library set" -msgstr "archive_command, archive_library 두 설정 모두 값을 지정했습니다." +msgid "both \"archive_command\" and \"archive_library\" set" +msgstr "\"archive_command\", \"archive_library\" 두 설정 모두 값을 지정했습니다." -#: postmaster/pgarch.c:792 postmaster/pgarch.c:831 +#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 #, c-format -msgid "Only one of archive_command, archive_library may be set." -msgstr "archive_command, archive_library 둘 중 하나만 지정하세요." +msgid "Only one of \"archive_command\", \"archive_library\" may be set." +msgstr "\"archive_command\", \"archive_library\" 둘 중 하나만 지정하세요." -#: postmaster/pgarch.c:809 +#: postmaster/pgarch.c:897 #, c-format msgid "" "restarting archiver process because value of \"archive_library\" was changed" msgstr "" "\"archive_library\" 설정값이 바뀌어서 archiver 프로세스를 다시 시작 합니다." -#: postmaster/pgarch.c:846 +#: postmaster/pgarch.c:934 #, c-format msgid "archive modules have to define the symbol %s" msgstr "아카이브 모듈은 %s 심볼을 정의해야합니다." -#: postmaster/pgarch.c:852 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules must register an archive callback" msgstr "아카이브 모듈은 아카이브 콜백 함수를 등록해야합니다." -#: postmaster/postmaster.c:759 +#: postmaster/postmaster.c:661 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: -f 옵션의 잘못된 인자: \"%s\"\n" -#: postmaster/postmaster.c:832 +#: postmaster/postmaster.c:734 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: -t 옵션의 잘못된 인자: \"%s\"\n" -#: postmaster/postmaster.c:855 +#: postmaster/postmaster.c:757 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: 잘못된 인자: \"%s\"\n" -#: postmaster/postmaster.c:923 +#: postmaster/postmaster.c:825 #, c-format msgid "" -"%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must " -"be less than max_connections (%d)\n" +"%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" " +"(%d) must be less than \"max_connections\" (%d)\n" msgstr "" -"%s: superuser_reserved_connections (%d) 값 + reserved_connections (%d) 값은 " -"max_connections(%d) 값보다 작아야함\n" +"%s: \"superuser_reserved_connections\" (%d) 값 + \"reserved_connections\" (%d) 값은 " +"\"max_connections\" (%d) 값보다 작아야함\n" -#: postmaster/postmaster.c:931 +#: postmaster/postmaster.c:833 #, c-format -msgid "WAL archival cannot be enabled when wal_level is \"minimal\"" -msgstr "wal_level 값이 \"minimal\"일 때는 아카이브 작업을 할 수 없습니다." +msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" +msgstr "\"wal_level\" 값이 \"minimal\"일 때는 아카이브 작업을 할 수 없습니다." -#: postmaster/postmaster.c:934 +#: postmaster/postmaster.c:836 #, c-format msgid "" -"WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or " -"\"logical\"" +"WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be " +"\"replica\" or \"logical\"" msgstr "" -"WAL 스트리밍 작업(max_wal_senders > 0 인경우)은 wal_level 값이 \"replica\" 또" +"WAL 스트리밍 작업(\"max_wal_senders\" > 0 인경우)은 \"wal_level\" 값이 \"replica\" 또" "는 \"logical\" 이어야 합니다." -#: postmaster/postmaster.c:942 +#: postmaster/postmaster.c:839 +#, c-format +msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" +msgstr "\"wal_level\" 값이 \"minimal\"일 때는 아카이브 작업을 할 수 없습니다." + +#: postmaster/postmaster.c:847 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "%s: 잘못된 datetoken 테이블들, 복구하십시오.\n" -#: postmaster/postmaster.c:1099 +#: postmaster/postmaster.c:1004 #, c-format msgid "could not create I/O completion port for child queue" msgstr "하위 대기열에 대해 I/O 완료 포트를 만들 수 없음" -#: postmaster/postmaster.c:1175 +#: postmaster/postmaster.c:1069 #, c-format msgid "ending log output to stderr" msgstr "stderr 쪽 로그 출력을 중지합니다." -#: postmaster/postmaster.c:1176 +#: postmaster/postmaster.c:1070 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "자세한 로그는 \"%s\" 쪽으로 기록됩니다." -#: postmaster/postmaster.c:1187 +#: postmaster/postmaster.c:1081 #, c-format msgid "starting %s" msgstr "%s 서버를 시작합니다." -#: postmaster/postmaster.c:1239 +#: postmaster/postmaster.c:1143 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "\"%s\" 응당 소켓을 만들 수 없습니다" -#: postmaster/postmaster.c:1245 +#: postmaster/postmaster.c:1149 #, c-format msgid "could not create any TCP/IP sockets" msgstr "TCP/IP 소켓을 만들 수 없습니다." -#: postmaster/postmaster.c:1277 +#: postmaster/postmaster.c:1181 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "DNSServiceRegister() 실패: 오류 코드 %ld" -#: postmaster/postmaster.c:1328 +#: postmaster/postmaster.c:1234 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "\"%s\" 디렉터리에 유닉스 도메인 소켓을 만들 수 없습니다" -#: postmaster/postmaster.c:1334 +#: postmaster/postmaster.c:1240 #, c-format msgid "could not create any Unix-domain sockets" msgstr "유닉스 도메인 소켓을 만들 수 없습니다" -#: postmaster/postmaster.c:1345 +#: postmaster/postmaster.c:1251 #, c-format msgid "no socket created for listening" msgstr "서버 접속 대기 작업을 위한 소켓을 만들 수 없음" -#: postmaster/postmaster.c:1376 +#: postmaster/postmaster.c:1282 #, c-format -msgid "%s: could not change permissions of external PID file \"%s\": %s\n" -msgstr "%s: \"%s\" 외부 PID 파일의 접근 권한을 바꿀 수 없음: %s\n" +msgid "%s: could not change permissions of external PID file \"%s\": %m\n" +msgstr "%s: \"%s\" 외부 PID 파일의 접근 권한을 바꿀 수 없음: %m\n" -#: postmaster/postmaster.c:1380 +#: postmaster/postmaster.c:1286 #, c-format -msgid "%s: could not write external PID file \"%s\": %s\n" -msgstr "%s: 외부 pid 파일 \"%s\" 를 쓸 수 없음: %s\n" +msgid "%s: could not write external PID file \"%s\": %m\n" +msgstr "%s: 외부 pid 파일 \"%s\" 를 쓸 수 없음: %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1408 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 #, c-format msgid "could not load %s" msgstr "%s 파일을 로드 할 수 없음" -#: postmaster/postmaster.c:1434 +#: postmaster/postmaster.c:1340 #, c-format msgid "postmaster became multithreaded during startup" msgstr "포스트마스터가 시작하면서 멀티쓰레드 환경이 되었습니다." -#: postmaster/postmaster.c:1435 +#: postmaster/postmaster.c:1341 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "LC_ALL 환경 설정값으로 알맞은 로케일 이름을 지정하세요." -#: postmaster/postmaster.c:1536 +#: postmaster/postmaster.c:1440 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: 실행 가능 경로를 확정할 수 없음" -#: postmaster/postmaster.c:1543 +#: postmaster/postmaster.c:1447 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: 실행가능한 postgres 프로그램을 찾을 수 없습니다" -#: postmaster/postmaster.c:1566 utils/misc/tzparser.c:340 +#: postmaster/postmaster.c:1470 utils/misc/tzparser.c:341 #, c-format msgid "" "This may indicate an incomplete PostgreSQL installation, or that the file " @@ -20697,558 +21392,375 @@ msgstr "" "이 문제는 PostgreSQL 설치가 불완전하게 되었거나, \"%s\" 파일이 올바른 위치에 " "있지 않아서 발생했습니다." -#: postmaster/postmaster.c:1593 +#: postmaster/postmaster.c:1497 #, c-format msgid "" "%s: could not find the database system\n" "Expected to find it in the directory \"%s\",\n" -"but could not open file \"%s\": %s\n" +"but could not open file \"%s\": %m\n" msgstr "" "%s: 데이터베이스 시스템을 찾을 수 없습니다\n" "\"%s\" 디렉터리 안에 해당 자료가 있기를 기대했는데,\n" -"\"%s\" 파일을 열 수가 없었습니다: %s\n" +"\"%s\" 파일을 열 수가 없었습니다: %m\n" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1890 +#: postmaster/postmaster.c:1787 #, c-format msgid "issuing %s to recalcitrant children" msgstr "하위 프로세스 정리를 위해 %s 신호 보냄" -#: postmaster/postmaster.c:1912 +#: postmaster/postmaster.c:1809 #, c-format msgid "" "performing immediate shutdown because data directory lock file is invalid" msgstr "데이터 디렉터리 잠금 파일이 잘못되어 즉시 종료 작업을 진행합니다." -#: postmaster/postmaster.c:1987 postmaster/postmaster.c:2015 -#, c-format -msgid "incomplete startup packet" -msgstr "아직 완료되지 않은 시작 패킷" - -#: postmaster/postmaster.c:1999 postmaster/postmaster.c:2032 -#, c-format -msgid "invalid length of startup packet" -msgstr "시작 패킷의 길이가 잘못 되었습니다" - -#: postmaster/postmaster.c:2061 -#, c-format -msgid "failed to send SSL negotiation response: %m" -msgstr "SSL 연결 작업에 오류가 발생했습니다: %m" - -#: postmaster/postmaster.c:2079 -#, c-format -msgid "received unencrypted data after SSL request" -msgstr "SSL 요청 뒤에 암호화 되지 않은 데이터를 받았음" - -#: postmaster/postmaster.c:2080 postmaster/postmaster.c:2124 -#, c-format -msgid "" -"This could be either a client-software bug or evidence of an attempted man-" -"in-the-middle attack." -msgstr "" -"이 현상은 클라이언트 소프트웨어 버그이거나, 중간자 공격으로 발생했을 것입니" -"다." - -#: postmaster/postmaster.c:2105 -#, c-format -msgid "failed to send GSSAPI negotiation response: %m" -msgstr "GSSAPI 협상 응답을 보내지 못했습니다: %m" - -#: postmaster/postmaster.c:2123 -#, c-format -msgid "received unencrypted data after GSSAPI encryption request" -msgstr "GSSAPI 암호화 요청 뒤에 암호화 되지 않은 데이터를 받았습니다." - -#: postmaster/postmaster.c:2147 -#, c-format -msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" -msgstr "" -"지원하지 않는 frontend 프로토콜 %u.%u: 서버에서 지원하는 프로토콜 %u.0 .. %u." -"%u" - -#: postmaster/postmaster.c:2214 -#, c-format -msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." -msgstr "사용할 수 있는 값: \"false\", 0, \"true\", 1, \"database\"." - -#: postmaster/postmaster.c:2255 -#, c-format -msgid "invalid startup packet layout: expected terminator as last byte" -msgstr "잘못된 시작 패킷 레이아웃: 마지막 바이트로 종결문자가 발견되었음" - -#: postmaster/postmaster.c:2272 -#, c-format -msgid "no PostgreSQL user name specified in startup packet" -msgstr "시작 패킷에서 지정한 사용자는 PostgreSQL 사용자 이름이 아닙니다" - -#: postmaster/postmaster.c:2336 -#, c-format -msgid "the database system is starting up" -msgstr "데이터베이스 시스템이 새로 가동 중입니다." - -#: postmaster/postmaster.c:2342 -#, c-format -msgid "the database system is not yet accepting connections" -msgstr "해당 데이터베이스 시스템은 아직 접속을 허용하지 않습니다." - -#: postmaster/postmaster.c:2343 -#, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "일관성 복원 작업을 아직 끝내지 못했습니다." - -#: postmaster/postmaster.c:2347 -#, c-format -msgid "the database system is not accepting connections" -msgstr "해당 데이터베이스 시스템은 접속을 허용하지 않습니다." - -#: postmaster/postmaster.c:2348 -#, c-format -msgid "Hot standby mode is disabled." -msgstr "Hot standby 모드가 비활성화 되었습니다." - -#: postmaster/postmaster.c:2353 -#, c-format -msgid "the database system is shutting down" -msgstr "데이터베이스 시스템이 중지 중입니다" - -#: postmaster/postmaster.c:2358 -#, c-format -msgid "the database system is in recovery mode" -msgstr "데이터베이스 시스템이 자동 복구 작업 중입니다." - -#: postmaster/postmaster.c:2363 storage/ipc/procarray.c:491 -#: storage/ipc/sinvaladt.c:306 storage/lmgr/proc.c:353 -#, c-format -msgid "sorry, too many clients already" -msgstr "최대 동시 접속자 수를 초과했습니다." - -#: postmaster/postmaster.c:2450 +#: postmaster/postmaster.c:1872 #, c-format msgid "wrong key in cancel request for process %d" msgstr "프로세스 %d에 대한 취소 요청에 잘못된 키가 있음" -#: postmaster/postmaster.c:2462 +#: postmaster/postmaster.c:1884 #, c-format msgid "PID %d in cancel request did not match any process" msgstr "취소 요청의 PID %d과(와) 일치하는 프로세스가 없음" -#: postmaster/postmaster.c:2729 +#: postmaster/postmaster.c:2104 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "SIGHUP 신호를 받아서, 환경설정파일을 다시 읽고 있습니다." #. translator: %s is a configuration file -#: postmaster/postmaster.c:2753 postmaster/postmaster.c:2757 +#: postmaster/postmaster.c:2132 postmaster/postmaster.c:2136 #, c-format msgid "%s was not reloaded" msgstr "%s 파일을 다시 불러오지 않았음" -#: postmaster/postmaster.c:2767 +#: postmaster/postmaster.c:2146 #, c-format msgid "SSL configuration was not reloaded" msgstr "SSL 설정이 다시 로드되지 않았음" -#: postmaster/postmaster.c:2857 +#: postmaster/postmaster.c:2232 #, c-format msgid "received smart shutdown request" msgstr "smart 중지 요청을 받았습니다." -#: postmaster/postmaster.c:2898 +#: postmaster/postmaster.c:2273 #, c-format msgid "received fast shutdown request" msgstr "fast 중지 요청을 받았습니다." -#: postmaster/postmaster.c:2916 +#: postmaster/postmaster.c:2291 #, c-format msgid "aborting any active transactions" msgstr "모든 활성화 되어있는 트랜잭션을 중지하고 있습니다." -#: postmaster/postmaster.c:2940 +#: postmaster/postmaster.c:2315 #, c-format msgid "received immediate shutdown request" msgstr "immediate 중지 요청을 받았습니다." -#: postmaster/postmaster.c:3016 +#: postmaster/postmaster.c:2387 #, c-format msgid "shutdown at recovery target" msgstr "복구 타겟에서 중지함" -#: postmaster/postmaster.c:3034 postmaster/postmaster.c:3070 +#: postmaster/postmaster.c:2405 postmaster/postmaster.c:2441 msgid "startup process" msgstr "시작 프로세스" -#: postmaster/postmaster.c:3037 +#: postmaster/postmaster.c:2408 #, c-format msgid "aborting startup due to startup process failure" msgstr "시작 프로세스 실패 때문에 서버 시작이 중지 되었습니다" -#: postmaster/postmaster.c:3110 +#: postmaster/postmaster.c:2483 #, c-format msgid "database system is ready to accept connections" msgstr "이제 데이터베이스 서버로 접속할 수 있습니다" -#: postmaster/postmaster.c:3131 +#: postmaster/postmaster.c:2504 msgid "background writer process" msgstr "백그라운드 writer 프로세스" -#: postmaster/postmaster.c:3178 +#: postmaster/postmaster.c:2551 msgid "checkpointer process" msgstr "체크포인트 프로세스" -#: postmaster/postmaster.c:3194 +#: postmaster/postmaster.c:2567 msgid "WAL writer process" msgstr "WAL 쓰기 프로세스" -#: postmaster/postmaster.c:3209 +#: postmaster/postmaster.c:2582 msgid "WAL receiver process" msgstr "WAL 수신 프로세스" -#: postmaster/postmaster.c:3224 +#: postmaster/postmaster.c:2596 +msgid "WAL summarizer process" +msgstr "WAL 요약 프로세스" + +#: postmaster/postmaster.c:2611 msgid "autovacuum launcher process" msgstr "autovacuum 실행기 프로세스" -#: postmaster/postmaster.c:3242 +#: postmaster/postmaster.c:2629 msgid "archiver process" msgstr "archiver 프로세스" -#: postmaster/postmaster.c:3255 +#: postmaster/postmaster.c:2642 msgid "system logger process" msgstr "시스템 로그 프로세스" -#: postmaster/postmaster.c:3312 +#: postmaster/postmaster.c:2659 +msgid "slot sync worker process" +msgstr "슬롯 동기화 작업 프로세스" + +#: postmaster/postmaster.c:2715 #, c-format msgid "background worker \"%s\"" msgstr "백그라운드 작업자 \"%s\"" -#: postmaster/postmaster.c:3391 postmaster/postmaster.c:3411 -#: postmaster/postmaster.c:3418 postmaster/postmaster.c:3436 +#: postmaster/postmaster.c:2794 postmaster/postmaster.c:2814 +#: postmaster/postmaster.c:2821 postmaster/postmaster.c:2839 msgid "server process" msgstr "서버 프로세스" -#: postmaster/postmaster.c:3490 +#: postmaster/postmaster.c:2893 #, c-format msgid "terminating any other active server processes" msgstr "다른 활성화 되어있는 서버 프로세스를 마치고 있는 중입니다" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3665 +#: postmaster/postmaster.c:3080 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) 프로그램은 %d 코드로 마쳤습니다" -#: postmaster/postmaster.c:3667 postmaster/postmaster.c:3679 -#: postmaster/postmaster.c:3689 postmaster/postmaster.c:3700 +#: postmaster/postmaster.c:3082 postmaster/postmaster.c:3094 +#: postmaster/postmaster.c:3104 postmaster/postmaster.c:3115 #, c-format msgid "Failed process was running: %s" msgstr "프로세스 실행 실패: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3676 +#: postmaster/postmaster.c:3091 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) 프로세스가 0x%X 예외로 인해 종료됨" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3686 +#: postmaster/postmaster.c:3101 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) 프로세스가 %d번 시그널을 받아 종료됨: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3698 +#: postmaster/postmaster.c:3113 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d) 프로세스가 인식할 수 없는 %d 상태로 종료됨" -#: postmaster/postmaster.c:3906 +#: postmaster/postmaster.c:3329 #, c-format msgid "abnormal database system shutdown" msgstr "비정상적인 데이터베이스 시스템 서비스를 중지" -#: postmaster/postmaster.c:3932 +#: postmaster/postmaster.c:3355 #, c-format msgid "shutting down due to startup process failure" msgstr "시작 작업 실패로 중지합니다." -#: postmaster/postmaster.c:3938 +#: postmaster/postmaster.c:3361 #, c-format -msgid "shutting down because restart_after_crash is off" -msgstr "restart_after_crash 값이 off 로 지정되어 중지합니다." +msgid "shutting down because \"restart_after_crash\" is off" +msgstr "\"restart_after_crash\" 값이 off 로 지정되어 중지합니다." -#: postmaster/postmaster.c:3950 +#: postmaster/postmaster.c:3373 #, c-format msgid "all server processes terminated; reinitializing" msgstr "모든 서버 프로세스가 중지 되었습니다; 재 초기화 중" -#: postmaster/postmaster.c:4144 postmaster/postmaster.c:5462 -#: postmaster/postmaster.c:5860 +#: postmaster/postmaster.c:3572 postmaster/postmaster.c:3982 +#: postmaster/postmaster.c:4371 #, c-format msgid "could not generate random cancel key" msgstr "무작위 취소 키를 만들 수 없음" -#: postmaster/postmaster.c:4206 +#: postmaster/postmaster.c:3605 #, c-format msgid "could not fork new process for connection: %m" msgstr "연결을 위한 새 프로세스 할당(fork) 실패: %m" -#: postmaster/postmaster.c:4248 +#: postmaster/postmaster.c:3647 msgid "could not fork new process for connection: " msgstr "연결을 위한 새 프로세스 할당(fork) 실패: " -#: postmaster/postmaster.c:4354 -#, c-format -msgid "connection received: host=%s port=%s" -msgstr "접속 수락: host=%s port=%s" - -#: postmaster/postmaster.c:4359 -#, c-format -msgid "connection received: host=%s" -msgstr "접속 수락: host=%s" - -#: postmaster/postmaster.c:4596 -#, c-format -msgid "could not execute server process \"%s\": %m" -msgstr "\"%s\" 서버 프로세스를 실행할 수 없음: %m" - -#: postmaster/postmaster.c:4654 -#, c-format -msgid "could not create backend parameter file mapping: error code %lu" -msgstr "백엔드 매개 변수 맵핑 파일을 만들 수 없음: 오류 코드 %lu" - -#: postmaster/postmaster.c:4663 -#, c-format -msgid "could not map backend parameter memory: error code %lu" -msgstr "백엔드 매개 변수 메모리를 맵핑할 수 없음: 오류 코드 %lu" - -#: postmaster/postmaster.c:4690 -#, c-format -msgid "subprocess command line too long" -msgstr "서브프로세스 명령행이 너무 깁니다." - -#: postmaster/postmaster.c:4708 -#, c-format -msgid "CreateProcess() call failed: %m (error code %lu)" -msgstr "CreateProcess() 호출 실패: %m (오류 코드 %lu)" - -#: postmaster/postmaster.c:4735 -#, c-format -msgid "could not unmap view of backend parameter file: error code %lu" -msgstr "백엔드 매개 변수 파일의 view를 unmap할 수 없음: 오류 코드 %lu" - -#: postmaster/postmaster.c:4739 -#, c-format -msgid "could not close handle to backend parameter file: error code %lu" -msgstr "백엔드 매개 변수 파일을 닫을 수 없음: 오류 코드 %lun" - -#: postmaster/postmaster.c:4761 -#, c-format -msgid "giving up after too many tries to reserve shared memory" -msgstr "공유 메모리 확보 작업을 여러 번 시도했으나 실패 함" - -#: postmaster/postmaster.c:4762 -#, c-format -msgid "This might be caused by ASLR or antivirus software." -msgstr "이 현상은 ASLR 또는 바이러스 검사 소프트웨어 때문일 수 있습니다." - -#: postmaster/postmaster.c:4935 -#, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "하위 프로세스에서 SSL 환경 설정을 못했음" - -#: postmaster/postmaster.c:5060 +#: postmaster/postmaster.c:3681 #, c-format msgid "Please report this to <%s>." msgstr "이 내용을 <%s> 주소로 보고하십시오." -#: postmaster/postmaster.c:5128 +#: postmaster/postmaster.c:3749 #, c-format msgid "database system is ready to accept read-only connections" msgstr "데이터베이스 시스템이 읽기 전용으로 연결을 수락할 준비가 되었습니다." -#: postmaster/postmaster.c:5386 -#, c-format -msgid "could not fork startup process: %m" -msgstr "시작 프로세스 할당(fork) 실패: %m" - -#: postmaster/postmaster.c:5390 -#, c-format -msgid "could not fork archiver process: %m" -msgstr "archiver 프로세스를 할당(fork)할 수 없음: %m" - -#: postmaster/postmaster.c:5394 -#, c-format -msgid "could not fork background writer process: %m" -msgstr "background writer 프로세스를 할당(fork)할 수 없습니다: %m" - -#: postmaster/postmaster.c:5398 -#, c-format -msgid "could not fork checkpointer process: %m" -msgstr "checkpointer 프로세스를 할당(fork)할 수 없습니다: %m" - -#: postmaster/postmaster.c:5402 -#, c-format -msgid "could not fork WAL writer process: %m" -msgstr "WAL writer 프로세스를 할당(fork)할 수 없음: %m" - -#: postmaster/postmaster.c:5406 -#, c-format -msgid "could not fork WAL receiver process: %m" -msgstr "WAL 수신 프로세스를 할당(fork)할 수 없음: %m" - -#: postmaster/postmaster.c:5410 +#: postmaster/postmaster.c:3932 #, c-format -msgid "could not fork process: %m" -msgstr "프로세스 할당(fork) 실패: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "\"%s\" 프로세스 할당(fork) 실패: %m" -#: postmaster/postmaster.c:5611 postmaster/postmaster.c:5638 +#: postmaster/postmaster.c:4170 postmaster/postmaster.c:4204 #, c-format msgid "database connection requirement not indicated during registration" msgstr "" "백그라운드 프로세스 초기화 중에 데이터베이스 연결 요구 사항이 충족되지 않았습" "니다." -#: postmaster/postmaster.c:5622 postmaster/postmaster.c:5649 +#: postmaster/postmaster.c:4180 postmaster/postmaster.c:4214 #, c-format msgid "invalid processing mode in background worker" msgstr "백그라운드 작업자에서 잘못된 프로세싱 모드가 사용됨" -#: postmaster/postmaster.c:5734 +#: postmaster/postmaster.c:4274 #, c-format -msgid "could not fork worker process: %m" -msgstr "작업자 프로세스를 할당(fork)할 수 없음: %m" +msgid "could not fork background worker process: %m" +msgstr "백그라운드 작업자 프로세스를 할당(fork)할 수 없습니다: %m" -#: postmaster/postmaster.c:5846 +#: postmaster/postmaster.c:4357 #, c-format -msgid "no slot available for new worker process" -msgstr "새 작업자 프로세스에서 쓸 슬롯이 없음" +msgid "no slot available for new background worker process" +msgstr "새 백그라운드 작업자 프로세스에서 쓸 슬롯이 없음" -#: postmaster/postmaster.c:6177 -#, c-format -msgid "could not duplicate socket %d for use in backend: error code %d" -msgstr "백엔드에서 사용하기 위해 %d 소켓을 복사할 수 없음: 오류 코드 %d" - -#: postmaster/postmaster.c:6209 -#, c-format -msgid "could not create inherited socket: error code %d\n" -msgstr "상속된 소켓을 만들 수 없음: 오류 코드 %d\n" - -#: postmaster/postmaster.c:6238 -#, c-format -msgid "could not open backend variables file \"%s\": %s\n" -msgstr "\"%s\" 백엔드 변수 파일을 열 수 없음: %s\n" - -#: postmaster/postmaster.c:6245 -#, c-format -msgid "could not read from backend variables file \"%s\": %s\n" -msgstr "\"%s\" 백엔드 변수 파일을 읽을 수 없음: %s\n" - -#: postmaster/postmaster.c:6254 -#, c-format -msgid "could not remove file \"%s\": %s\n" -msgstr "\"%s\" 파일을 삭제할 수 없음: %s\n" - -#: postmaster/postmaster.c:6271 -#, c-format -msgid "could not map view of backend variables: error code %lu\n" -msgstr "백엔드 변수 파일의 view를 map할 수 없음: 오류 코드 %lu\n" - -#: postmaster/postmaster.c:6280 -#, c-format -msgid "could not unmap view of backend variables: error code %lu\n" -msgstr "백엔드 변수 파일의 view를 unmap할 수 없음: 오류 코드 %lu\n" - -#: postmaster/postmaster.c:6287 -#, c-format -msgid "could not close handle to backend parameter variables: error code %lu\n" -msgstr "백엔드 변수 파일을 닫을 수 없음: 오류 코드 %lu\n" - -#: postmaster/postmaster.c:6446 +#: postmaster/postmaster.c:4620 #, c-format msgid "could not read exit code for process\n" msgstr "프로세스의 종료 코드를 읽을 수 없음\n" -#: postmaster/postmaster.c:6488 +#: postmaster/postmaster.c:4662 #, c-format msgid "could not post child completion status\n" msgstr "하위 완료 상태를 게시할 수 없음\n" -#: postmaster/syslogger.c:501 postmaster/syslogger.c:1222 +#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 #, c-format msgid "could not read from logger pipe: %m" msgstr "로그 파이프에서 읽기 실패: %m" -#: postmaster/syslogger.c:598 postmaster/syslogger.c:612 +#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 #, c-format msgid "could not create pipe for syslog: %m" msgstr "syslog에서 사용할 파이프를 만들 수 없습니다: %m" -#: postmaster/syslogger.c:677 +#: postmaster/syslogger.c:712 #, c-format msgid "could not fork system logger: %m" msgstr "시스템 로거(logger)를 확보하질 못 했습니다: %m" -#: postmaster/syslogger.c:713 +#: postmaster/syslogger.c:731 #, c-format msgid "redirecting log output to logging collector process" msgstr "서버 로그를 로그 수집 프로세스로 보냅니다." -#: postmaster/syslogger.c:714 +#: postmaster/syslogger.c:732 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "이제부터 서버 로그는 \"%s\" 디렉터리에 보관됩니다." -#: postmaster/syslogger.c:722 +#: postmaster/syslogger.c:740 #, c-format msgid "could not redirect stdout: %m" msgstr "표준출력을 redirect 하지 못했습니다: %m" -#: postmaster/syslogger.c:727 postmaster/syslogger.c:744 +#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 #, c-format msgid "could not redirect stderr: %m" msgstr "표준오류(stderr)를 redirect 하지 못했습니다: %m" -#: postmaster/syslogger.c:1177 +#: postmaster/syslogger.c:1128 #, c-format -msgid "could not write to log file: %s\n" -msgstr "로그파일 쓰기 실패: %s\n" +msgid "could not write to log file: %m\n" +msgstr "로그파일 쓰기 실패: %m\n" -#: postmaster/syslogger.c:1295 +#: postmaster/syslogger.c:1246 #, c-format msgid "could not open log file \"%s\": %m" msgstr "\"%s\" 잠금파일을 열 수 없음: %m" -#: postmaster/syslogger.c:1385 +#: postmaster/syslogger.c:1336 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "" "로그파일 자동 교체 기능을 금지합니다(교체하려면 SIGHUP 시그널을 사용함)" -#: regex/regc_pg_locale.c:242 +#: postmaster/walsummarizer.c:740 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "WAL 요약정보 처리 작업이 진행 중이지 않음" + +#: postmaster/walsummarizer.c:741 +#, c-format +msgid "" +"Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/" +"%X in memory." +msgstr "" +"요약정보 처리 작업은 %X/%X에서 필요한데, 디스크의 %X/%X, 메모리의 %X/%X에서 멈추어 있음" + +#: postmaster/walsummarizer.c:755 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "" +"still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "" +"%X/%X에서 여전히 %ld초 동안 WAL 요약정보 처리 작업이 멈춰 있음" + +#: postmaster/walsummarizer.c:760 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "요약정보 처리 작업이 디스크의 %X/%X에, 메모리의 %X/%X에 다달았음" + +#: postmaster/walsummarizer.c:1000 +#, c-format +msgid "could not find a valid record after %X/%X" +msgstr "%X/%X 뒤에 올바른 레코드를 찾을 수 없음" + +#: postmaster/walsummarizer.c:1045 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X: %s" +msgstr "%u번 타임라인의 %X/%X에서 WAL를 읽을 수 없음: %s" + +#: postmaster/walsummarizer.c:1051 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X" +msgstr "타임라인 %u, 위치 %X/%X 에서 WAL를 읽을 없음" + +#: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "정규식 처리에 쓰일 정렬규칙(collation)을 찾을 수 없음" -#: regex/regc_pg_locale.c:265 +#: regex/regc_pg_locale.c:262 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "정규식 처리에 쓰일 비결정 정렬규칙(collation)을 지원하지 않음" -#: replication/libpqwalreceiver/libpqwalreceiver.c:197 -#: replication/libpqwalreceiver/libpqwalreceiver.c:280 +#: replication/libpqwalreceiver/libpqwalreceiver.c:267 +#: replication/libpqwalreceiver/libpqwalreceiver.c:358 #, c-format msgid "password is required" msgstr "비밀번호가 필요함" -#: replication/libpqwalreceiver/libpqwalreceiver.c:198 +#: replication/libpqwalreceiver/libpqwalreceiver.c:268 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "해당 서버로 비밀번호 없이 접속한다며, 일반 사용자는 접속할 수 없음" -#: replication/libpqwalreceiver/libpqwalreceiver.c:199 +#: replication/libpqwalreceiver/libpqwalreceiver.c:269 #, c-format msgid "" "Target server's authentication method must be changed, or set " @@ -21257,27 +21769,28 @@ msgstr "" "대상 서버의 인증 방법을 바꾸거나, 또는 구독 속성으로 password_required=false " "로 지정하세요." -#: replication/libpqwalreceiver/libpqwalreceiver.c:211 +#: replication/libpqwalreceiver/libpqwalreceiver.c:285 #, c-format msgid "could not clear search path: %s" msgstr "search path를 지울 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:257 +#: replication/libpqwalreceiver/libpqwalreceiver.c:331 +#: replication/libpqwalreceiver/libpqwalreceiver.c:517 #, c-format msgid "invalid connection string syntax: %s" msgstr "잘못된 연결 문자열 구문: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:281 +#: replication/libpqwalreceiver/libpqwalreceiver.c:359 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "일반 사용자로 접속한다면, 연결 문자열에 비밀번호를 지정하세요." -#: replication/libpqwalreceiver/libpqwalreceiver.c:307 +#: replication/libpqwalreceiver/libpqwalreceiver.c:386 #, c-format msgid "could not parse connection string: %s" msgstr "접속 문자열을 분석할 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:380 +#: replication/libpqwalreceiver/libpqwalreceiver.c:459 #, c-format msgid "" "could not receive database system identifier and timeline ID from the " @@ -21285,13 +21798,13 @@ msgid "" msgstr "" "주 서버에서 데이터베이스 시스템 식별번호와 타임라인 번호를 받을 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:392 -#: replication/libpqwalreceiver/libpqwalreceiver.c:635 +#: replication/libpqwalreceiver/libpqwalreceiver.c:476 +#: replication/libpqwalreceiver/libpqwalreceiver.c:763 #, c-format msgid "invalid response from primary server" msgstr "주 서버에서 잘못된 응답이 왔음" -#: replication/libpqwalreceiver/libpqwalreceiver.c:393 +#: replication/libpqwalreceiver/libpqwalreceiver.c:477 #, c-format msgid "" "Could not identify system: got %d rows and %d fields, expected %d rows and " @@ -21300,86 +21813,91 @@ msgstr "" "시스템을 식별할 수 없음: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, 필드수 %d " "이상" -#: replication/libpqwalreceiver/libpqwalreceiver.c:478 -#: replication/libpqwalreceiver/libpqwalreceiver.c:485 -#: replication/libpqwalreceiver/libpqwalreceiver.c:515 +#: replication/libpqwalreceiver/libpqwalreceiver.c:606 +#: replication/libpqwalreceiver/libpqwalreceiver.c:613 +#: replication/libpqwalreceiver/libpqwalreceiver.c:643 #, c-format msgid "could not start WAL streaming: %s" msgstr "WAL 스트리밍 작업을 시작할 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:539 +#: replication/libpqwalreceiver/libpqwalreceiver.c:667 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "주 서버로 스트리밍 종료 메시지를 보낼 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:562 +#: replication/libpqwalreceiver/libpqwalreceiver.c:690 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "스트리밍 종료 요청에 대한 잘못된 응답을 받음" -#: replication/libpqwalreceiver/libpqwalreceiver.c:577 +#: replication/libpqwalreceiver/libpqwalreceiver.c:705 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "COPY 스트리밍 종료 중 오류 발생: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:587 +#: replication/libpqwalreceiver/libpqwalreceiver.c:715 #, c-format msgid "error reading result of streaming command: %s" msgstr "스트리밍 명령에 대한 결과 처리에서 오류 발생: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:596 -#: replication/libpqwalreceiver/libpqwalreceiver.c:832 +#: replication/libpqwalreceiver/libpqwalreceiver.c:724 +#: replication/libpqwalreceiver/libpqwalreceiver.c:957 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "CommandComplete 작업 후 예상치 못한 결과를 받음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:623 +#: replication/libpqwalreceiver/libpqwalreceiver.c:751 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "주 서버에서 타임라인 내역 파일을 받을 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:636 +#: replication/libpqwalreceiver/libpqwalreceiver.c:764 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "2개의 칼럼으로 된 하나의 튜플을 예상하지만, %d 튜플 (%d 칼럼)을 수신함" -#: replication/libpqwalreceiver/libpqwalreceiver.c:795 -#: replication/libpqwalreceiver/libpqwalreceiver.c:848 -#: replication/libpqwalreceiver/libpqwalreceiver.c:855 +#: replication/libpqwalreceiver/libpqwalreceiver.c:920 +#: replication/libpqwalreceiver/libpqwalreceiver.c:973 +#: replication/libpqwalreceiver/libpqwalreceiver.c:980 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "WAL 스트림에서 자료 받기 실패: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:875 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 #, c-format msgid "could not send data to WAL stream: %s" msgstr "WAL 스트림에 데이터를 보낼 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:967 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "\"%s\" 복제 슬롯을 만들 수 없음: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1013 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#, c-format +msgid "could not alter replication slot \"%s\": %s" +msgstr "\"%s\" 복제 슬롯을 변경할 수 없음: %s" + +#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 #, c-format msgid "invalid query response" msgstr "잘못된 쿼리 응답" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1014 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 #, c-format msgid "Expected %d fields, got %d fields." msgstr "%d개의 칼럼을 예상하지만, %d개의 칼럼을 수신함" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1084 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 #, c-format msgid "the query interface requires a database connection" msgstr "이 쿼리 인터페이스는 데이터베이스 연결이 필요합니다" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1115 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 msgid "empty query" msgstr "빈 쿼리" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1121 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 msgid "unexpected pipeline mode" msgstr "예기치 않은 파이프라인 모드" @@ -21390,33 +21908,33 @@ msgid "" "finished" msgstr "\"%s\" 구독을 위한 논리 복제 병렬 반영 작업자가 일을 끝냄" -#: replication/logical/applyparallelworker.c:825 +#: replication/logical/applyparallelworker.c:822 #, c-format msgid "lost connection to the logical replication apply worker" msgstr "논리 복제 반영 작업자 연결 끊김" -#: replication/logical/applyparallelworker.c:1027 -#: replication/logical/applyparallelworker.c:1029 +#: replication/logical/applyparallelworker.c:1024 +#: replication/logical/applyparallelworker.c:1026 msgid "logical replication parallel apply worker" msgstr "논리 복제 병렬 반영 작업자" -#: replication/logical/applyparallelworker.c:1043 +#: replication/logical/applyparallelworker.c:1040 #, c-format msgid "logical replication parallel apply worker exited due to error" msgstr "논리 복제 병렬 반영 작업자가 오류로 종료되었음" -#: replication/logical/applyparallelworker.c:1130 -#: replication/logical/applyparallelworker.c:1303 +#: replication/logical/applyparallelworker.c:1127 +#: replication/logical/applyparallelworker.c:1300 #, c-format msgid "lost connection to the logical replication parallel apply worker" msgstr "논리 복제 병렬 반영 작업자 연결 끊김" -#: replication/logical/applyparallelworker.c:1183 +#: replication/logical/applyparallelworker.c:1180 #, c-format msgid "could not send data to shared-memory queue" msgstr "공유 메모리 큐로 데이터를 보낼 수 없음" -#: replication/logical/applyparallelworker.c:1218 +#: replication/logical/applyparallelworker.c:1215 #, c-format msgid "" "logical replication apply worker will serialize the remaining changes of " @@ -21425,44 +21943,45 @@ msgstr "" "논리 복제 반영 작업자는 %u 원격 트랜잭션의 남아 있는 변경 사항을 파일로 직렬" "화 할 것입니다." -#: replication/logical/decode.c:180 replication/logical/logical.c:140 +#: replication/logical/decode.c:177 replication/logical/logical.c:141 #, c-format msgid "" -"logical decoding on standby requires wal_level >= logical on the primary" +"logical decoding on standby requires \"wal_level\" >= \"logical\" on the " +"primary" msgstr "" -"대기 서버에서 논리적 디코딩은 주서버 설정이 wal_level >= logical 이어야 함" +"대기 서버에서 논리적 디코딩은 주서버 설정이 \"wal_level\" >= \"logical\" 이어야 함" -#: replication/logical/launcher.c:331 +#: replication/logical/launcher.c:334 #, c-format msgid "cannot start logical replication workers when max_replication_slots = 0" msgstr "" "max_replication_slots = 0 설정 때문에 논리 복제 작업자를 시작 할 수 없습니다" -#: replication/logical/launcher.c:424 +#: replication/logical/launcher.c:427 #, c-format msgid "out of logical replication worker slots" msgstr "더 이상의 논리 복제 작업자용 슬롯이 없습니다" -#: replication/logical/launcher.c:425 replication/logical/launcher.c:499 -#: replication/slot.c:1297 storage/lmgr/lock.c:964 storage/lmgr/lock.c:1002 -#: storage/lmgr/lock.c:2787 storage/lmgr/lock.c:4172 storage/lmgr/lock.c:4237 -#: storage/lmgr/lock.c:4587 storage/lmgr/predicate.c:2413 -#: storage/lmgr/predicate.c:2428 storage/lmgr/predicate.c:3825 +#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 +#: replication/slot.c:1524 storage/lmgr/lock.c:985 storage/lmgr/lock.c:1023 +#: storage/lmgr/lock.c:2836 storage/lmgr/lock.c:4221 storage/lmgr/lock.c:4286 +#: storage/lmgr/lock.c:4636 storage/lmgr/predicate.c:2469 +#: storage/lmgr/predicate.c:2484 storage/lmgr/predicate.c:3881 #, c-format -msgid "You might need to increase %s." -msgstr "%s 설정값을 늘릴 필요가 있습니다." +msgid "You might need to increase \"%s\"." +msgstr "\"%s\" 설정값을 늘릴 필요가 있습니다." -#: replication/logical/launcher.c:498 +#: replication/logical/launcher.c:513 #, c-format msgid "out of background worker slots" msgstr "백그라운 작업자 슬롯이 모자랍니다" -#: replication/logical/launcher.c:705 +#: replication/logical/launcher.c:720 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "%d 번 논리 복제 작업자 슬롯이 비어있습니다, 붙일 수 없습니다." -#: replication/logical/launcher.c:714 +#: replication/logical/launcher.c:729 #, c-format msgid "" "logical replication worker slot %d is already used by another worker, cannot " @@ -21471,27 +21990,27 @@ msgstr "" "%d 번 논리 복제 작업자 슬롯을 이미 다른 작업자가 쓰고 있습니다. 붙일 수 없습" "니다." -#: replication/logical/logical.c:120 +#: replication/logical/logical.c:121 #, c-format -msgid "logical decoding requires wal_level >= logical" -msgstr "논리적 디코딩 기능은 wal_level 값이 logical 이상이어야 함" +msgid "logical decoding requires \"wal_level\" >= \"logical\"" +msgstr "논리적 디코딩 기능은 \"wal_level\" 값이 \"logical\" 이상이어야 함" -#: replication/logical/logical.c:125 +#: replication/logical/logical.c:126 #, c-format msgid "logical decoding requires a database connection" msgstr "논리적 디코딩 기능은 데이터베이스 연결이 필요합니다" -#: replication/logical/logical.c:363 replication/logical/logical.c:517 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "논리적 디코딩에서는 물리적 복제 슬롯을 사용할 수 없음" -#: replication/logical/logical.c:368 replication/logical/logical.c:522 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "\"%s\" 복제 슬롯이 이 데이터베이스 만들어져있지 않음" -#: replication/logical/logical.c:375 +#: replication/logical/logical.c:377 #, c-format msgid "" "cannot create logical replication slot in transaction that has performed " @@ -21499,92 +22018,108 @@ msgid "" msgstr "" "자료 변경 작업이 있는 트랜잭션 안에서는 논리적 복제 슬롯을 만들 수 없음" -#: replication/logical/logical.c:534 replication/logical/logical.c:541 +#: replication/logical/logical.c:540 +#, c-format +msgid "cannot use replication slot \"%s\" for logical decoding" +msgstr "논리적 디코딩에서는 \"%s\" 슬롯을 사용할 수 없음" + +#: replication/logical/logical.c:542 replication/slot.c:798 +#: replication/slot.c:829 +#, c-format +msgid "This replication slot is being synchronized from the primary server." +msgstr "이 복제 슬롯은 해당 주 서버로부터 동기화 되었습니다." + +#: replication/logical/logical.c:543 +#, c-format +msgid "Specify another replication slot." +msgstr "다른 복제 슬롯을 지정하세요." + +#: replication/logical/logical.c:554 replication/logical/logical.c:561 #, c-format msgid "can no longer get changes from replication slot \"%s\"" msgstr "\"%s\" 복제 슬롯에서 변경 사항을 더 찾을 수 없음" -#: replication/logical/logical.c:536 +#: replication/logical/logical.c:556 #, c-format msgid "" "This slot has been invalidated because it exceeded the maximum reserved size." msgstr "최대 예약 크기를 초과해서 이 슬롯은 정상적이지 않은 것으로 바꿨습니다." -#: replication/logical/logical.c:543 +#: replication/logical/logical.c:563 #, c-format msgid "" "This slot has been invalidated because it was conflicting with recovery." msgstr "" -"이 슬롯은 복원 작업으로 충돌이 일어나 사용할 수 없는 것으로 처리했습니다." +"이 슬롯은 복구 작업으로 충돌이 일어나 사용할 수 없는 것으로 처리했습니다." -#: replication/logical/logical.c:608 +#: replication/logical/logical.c:628 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "\"%s\" 이름의 논리적 복제 슬롯을 만드는 중" -#: replication/logical/logical.c:610 +#: replication/logical/logical.c:630 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "" "%X/%X 이후 트랜잭션 커밋 정보를 스트리밍 하는 중, %X/%X 위치부터 WAL 읽는 중" -#: replication/logical/logical.c:758 +#: replication/logical/logical.c:778 #, c-format msgid "" "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "" "슬롯: \"%s\", 출력 플러그인: \"%s\", 해당 콜백함수: %s, 관련 LSN: %X/%X" -#: replication/logical/logical.c:764 +#: replication/logical/logical.c:784 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "슬롯: \"%s\", 출력 플러그인: \"%s\", 해당 콜백함수: %s" -#: replication/logical/logical.c:935 replication/logical/logical.c:980 -#: replication/logical/logical.c:1025 replication/logical/logical.c:1071 +#: replication/logical/logical.c:955 replication/logical/logical.c:1000 +#: replication/logical/logical.c:1045 replication/logical/logical.c:1091 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "준비 시간에 논리 복제가 %s 콜백을 필요로 합니다." -#: replication/logical/logical.c:1303 replication/logical/logical.c:1352 -#: replication/logical/logical.c:1393 replication/logical/logical.c:1479 -#: replication/logical/logical.c:1528 +#: replication/logical/logical.c:1323 replication/logical/logical.c:1372 +#: replication/logical/logical.c:1413 replication/logical/logical.c:1499 +#: replication/logical/logical.c:1548 #, c-format msgid "logical streaming requires a %s callback" msgstr "논리적 스트리밍이 %s 콜백을 필요로 합니다" -#: replication/logical/logical.c:1438 +#: replication/logical/logical.c:1458 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "준비 시간에 논리적 스트리밍이 %s 콜백을 필요로 합니다" -#: replication/logical/logicalfuncs.c:126 +#: replication/logical/logicalfuncs.c:123 #, c-format msgid "slot name must not be null" msgstr "슬롯 이름으로 null 값을 사용할 수 없습니다" -#: replication/logical/logicalfuncs.c:142 +#: replication/logical/logicalfuncs.c:139 #, c-format msgid "options array must not be null" msgstr "옵션 배열은 null 값을 사용할 수 없습니다." -#: replication/logical/logicalfuncs.c:159 +#: replication/logical/logicalfuncs.c:156 #, c-format msgid "array must be one-dimensional" msgstr "배열은 일차원 배열이어야 합니다" -#: replication/logical/logicalfuncs.c:165 +#: replication/logical/logicalfuncs.c:162 #, c-format msgid "array must not contain nulls" msgstr "배열에는 null 값을 포함할 수 없습니다" -#: replication/logical/logicalfuncs.c:180 utils/adt/json.c:1484 -#: utils/adt/jsonb.c:1403 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1420 +#: utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "배열은 그 요소의 개수가 짝수여야 함" -#: replication/logical/logicalfuncs.c:227 +#: replication/logical/logicalfuncs.c:224 #, c-format msgid "" "logical decoding output plugin \"%s\" produces binary output, but function " @@ -21596,9 +22131,10 @@ msgstr "" #: replication/logical/origin.c:190 #, c-format msgid "" -"cannot query or manipulate replication origin when max_replication_slots = 0" +"cannot query or manipulate replication origin when \"max_replication_slots\" " +"is 0" msgstr "" -"max_replication_slots = 0 상황에서는 복제 오리진을 질의하거나 관리할 수 없음" +"\"max_replication_slots\" = 0 상황에서는 복제 오리진을 질의하거나 관리할 수 없음" #: replication/logical/origin.c:195 #, c-format @@ -21632,9 +22168,10 @@ msgstr "복제 체크포인트의 잘못된 매직 번호: %u, 기대값: %u" #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase max_replication_slots" +msgid "" +"could not find free replication state, increase \"max_replication_slots\"" msgstr "" -"사용 가능한 복제 슬롯이 부족합니다. max_replication_slots 값을 늘리세요" +"사용 가능한 복제 슬롯이 부족합니다. \"max_replication_slots\" 값을 늘리세요" #: replication/logical/origin.c:806 #, c-format @@ -21646,57 +22183,57 @@ msgstr "%d 노드 %X/%X 위치로 복제 상태가 복구됨" msgid "replication slot checkpoint has wrong checksum %u, expected %u" msgstr "복제 슬롯 체크포인트의 체크섬 값이 잘못됨: %u, 기대값 %u" -#: replication/logical/origin.c:944 replication/logical/origin.c:1141 +#: replication/logical/origin.c:944 replication/logical/origin.c:1143 #, c-format msgid "replication origin with ID %d is already active for PID %d" msgstr "%d ID의 복제 오리진이 %d PID 프로세스가 사용중입니다." -#: replication/logical/origin.c:955 replication/logical/origin.c:1153 +#: replication/logical/origin.c:955 replication/logical/origin.c:1156 #, c-format msgid "" "could not find free replication state slot for replication origin with ID %d" msgstr "%d ID 복제 오리진을 위한 여유 복제 슬롯을 찾을 수 없음" -#: replication/logical/origin.c:957 replication/logical/origin.c:1155 -#: replication/slot.c:2093 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 +#: replication/slot.c:2384 #, c-format -msgid "Increase max_replication_slots and try again." -msgstr "max_replication_slots 값을 늘린 후 다시 시도해 보세요" +msgid "Increase \"max_replication_slots\" and try again." +msgstr "\"max_replication_slots\" 값을 늘린 후 다시 시도해 보세요" -#: replication/logical/origin.c:1112 +#: replication/logical/origin.c:1114 #, c-format msgid "cannot setup replication origin when one is already setup" msgstr "하나가 이미 설정되어 더 이상 복제 오리진 설정을 할 수 없음" -#: replication/logical/origin.c:1196 replication/logical/origin.c:1412 -#: replication/logical/origin.c:1432 +#: replication/logical/origin.c:1199 replication/logical/origin.c:1415 +#: replication/logical/origin.c:1435 #, c-format msgid "no replication origin is configured" msgstr "복제 오리진 설정이 없습니다" -#: replication/logical/origin.c:1282 +#: replication/logical/origin.c:1285 #, c-format msgid "replication origin name \"%s\" is reserved" msgstr "\"%s\" 복제 오리진 이름은 사용할 수 없음" -#: replication/logical/origin.c:1284 +#: replication/logical/origin.c:1287 #, c-format msgid "" "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." msgstr "" "\"%s\", \"%s\", \"pg_\"로 시작하는 오리진 이름은 미리 예약된 이름입니다." -#: replication/logical/relation.c:240 +#: replication/logical/relation.c:242 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:243 +#: replication/logical/relation.c:245 #, c-format msgid ", \"%s\"" msgstr ", \"%s\"" -#: replication/logical/relation.c:249 +#: replication/logical/relation.c:251 #, c-format msgid "" "logical replication target relation \"%s.%s\" is missing replicated column: " @@ -21706,7 +22243,7 @@ msgid_plural "" "%s" msgstr[0] "\"%s.%s\" 이름의 논리 복제 대상 릴레이션에 관련된 칼럼이 빠졌음: %s" -#: replication/logical/relation.c:304 +#: replication/logical/relation.c:306 #, c-format msgid "" "logical replication target relation \"%s.%s\" uses system columns in REPLICA " @@ -21715,117 +22252,272 @@ msgstr "" "\"%s.%s\" 논리 복제 대상 릴레이션이 REPLICA IDENTITY 인덱스에서 시스템 칼럼" "을 사용하고 있습니다." -#: replication/logical/relation.c:396 +#: replication/logical/relation.c:398 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "\"%s.%s\" 이름의 논리 복제 대상 릴레이션이 없습니다." -#: replication/logical/reorderbuffer.c:3936 +#: replication/logical/reorderbuffer.c:3999 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "%u XID 내용을 데이터 파일에 쓸 수 없음: %m" -#: replication/logical/reorderbuffer.c:4282 -#: replication/logical/reorderbuffer.c:4307 +#: replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4370 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "reorderbuffer 처리용 파일에서 읽기 실패: %m" -#: replication/logical/reorderbuffer.c:4286 -#: replication/logical/reorderbuffer.c:4311 +#: replication/logical/reorderbuffer.c:4349 +#: replication/logical/reorderbuffer.c:4374 #, c-format msgid "" "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "" "reorderbuffer 처리용 파일에서 읽기 실패: %d 바이트 읽음, 기대값 %u 바이트" -#: replication/logical/reorderbuffer.c:4561 +#: replication/logical/reorderbuffer.c:4624 #, c-format msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" msgstr "\"%s\" 파일을 지울 수 없음, pg_replslot/%s/xid* 삭제 작업 중: %m" -#: replication/logical/reorderbuffer.c:5057 +#: replication/logical/reorderbuffer.c:5120 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "\"%s\" 파일에서 읽기 실패: %d 바이트 읽음, 기대값 %d 바이트" -#: replication/logical/snapbuild.c:639 +#: replication/logical/slotsync.c:215 +#, c-format +msgid "" +"could not synchronize replication slot \"%s\" because remote slot precedes " +"local slot" +msgstr "원격 슬롯이 로컬 슬롯 보다 우선이어서 복제 슬롯(\"%s\")을 동기화 할 수 없음" + +#: replication/logical/slotsync.c:217 +#, c-format +msgid "" +"The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has " +"LSN %X/%X and catalog xmin %u." +msgstr "" +"원격 슬롯에는 LSN %X/%X, catalog xmin %u 정보가 있지만, " +"로컬 슬롯은 LSN %X/%X, catalog xmin %u 상태입니다." + +#: replication/logical/slotsync.c:459 +#, c-format +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "\"%s\" 복제 슬롯을 %u OID 데이터베이스에서 삭제했음" + +#: replication/logical/slotsync.c:579 +#, c-format +msgid "could not synchronize replication slot \"%s\"" +msgstr "\"%s\" 복제 슬롯을 동기화 할 수 없음" + +#: replication/logical/slotsync.c:580 +#, c-format +msgid "" +"Logical decoding could not find consistent point from local slot's LSN %X/%X." +msgstr "논리적 디코딩이 로컬 슬롯 %X/%X에서 일관성 위치를 찾지 못함" + +#: replication/logical/slotsync.c:589 +#, c-format +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "새롭게 만들어진 \"%s\" 복제 슬롯은 이제 동기화 준비 상태임" + +#: replication/logical/slotsync.c:628 +#, c-format +msgid "" +"skipping slot synchronization because the received slot sync LSN %X/%X for " +"slot \"%s\" is ahead of the standby position %X/%X" +msgstr "" +"슬롯 동기화가 건너뜀, 수신된 슬롯 동기화 LSN은 %X/%X(해당 슬롯: \"%s\")인데 " +"이는 대기 서버 위치인 %X/%X 보다 앞섭니다." + +#: replication/logical/slotsync.c:650 +#, c-format +msgid "" +"exiting from slot synchronization because same name slot \"%s\" already " +"exists on the standby" +msgstr "" +"\"%s\" 이름의 슬롯이 대기 서버에도 이미 있어, 슬롯 동기화 작업이 이미 있음" + +#: replication/logical/slotsync.c:819 +#, c-format +msgid "could not fetch failover logical slots info from the primary server: %s" +msgstr "주 서버에서 failover 논리 복제 슬롯을 찾지 못했음: %s" + +#: replication/logical/slotsync.c:965 +#, c-format +msgid "" +"could not fetch primary_slot_name \"%s\" info from the primary server: %s" +msgstr "주 서버에서 \"%s\" primary_slot_name을 찾지 못했음: %s" + +#: replication/logical/slotsync.c:967 +#, c-format +msgid "Check if primary_slot_name is configured correctly." +msgstr "primary_slot_name 설정값을 확인하세요." + +#: replication/logical/slotsync.c:987 +#, c-format +msgid "cannot synchronize replication slots from a standby server" +msgstr "대기 서버에서 복제 슬롯을 동기화 할 수 없음" + +#. translator: second %s is a GUC variable name +#: replication/logical/slotsync.c:996 +#, c-format +msgid "" +"replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "\"%s\" 이름의 복제 슬롯(\"%s\" 설정에 지정된)이 주 서버에 없음" + +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1029 +#, c-format +msgid "" +"replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "" +"복제 슬롯 동기화는 \"%s\" 설정을 필요로 합니다. 해당 환경 설정 변수: \"%s\"" + +#: replication/logical/slotsync.c:1050 +#, c-format +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "복제 슬롯 동기화는 \"wal_level\" >= \"logical\" 설정이 필요함" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "복제 슬롯 동기화는 \"%s\" 설정이 필요함" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1077 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "복제 슬롯 동기화는 \"%s\" 설정이 활성화 되어야 함" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1129 +#, c-format +msgid "" +"replication slot synchronization worker will shut down because \"%s\" is " +"disabled" +msgstr "" +"\"%s\" 설정이 비활성화되어 복제 슬롯 동기화 작업이 중지될 것임" + +#: replication/logical/slotsync.c:1138 +#, c-format +msgid "" +"replication slot synchronization worker will restart because of a parameter " +"change" +msgstr "" +"매개 변수가 바뀌어서 복제 슬롯 동기화 작업이 중지될 것임" + +#: replication/logical/slotsync.c:1162 +#, c-format +msgid "" +"replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "" +"SIGINT 신호를 받아 복제 슬롯 동기화 작업자를 종료함" + +#: replication/logical/slotsync.c:1287 +#, c-format +msgid "cannot synchronize replication slots when standby promotion is ongoing" +msgstr "대기 서버가 주 서버로 전환 중이여서 복제 슬롯 동기화를 할 수 없음" + +#: replication/logical/slotsync.c:1295 +#, c-format +msgid "cannot synchronize replication slots concurrently" +msgstr "복제 슬롯을 동시에 동기화 할 수 없음" + +#: replication/logical/slotsync.c:1403 +#, c-format +msgid "slot sync worker started" +msgstr "슬롯 동기화 작업자 시작됨" + +#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 +#: replication/walreceiver.c:307 +#, c-format +msgid "could not connect to the primary server: %s" +msgstr "주 서버에 연결 할 수 없음: %s" + +#: replication/logical/snapbuild.c:653 #, c-format msgid "initial slot snapshot too large" msgstr "초기 슬롯 스냅샷이 너무 큽니다." -#: replication/logical/snapbuild.c:693 +#: replication/logical/snapbuild.c:707 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "" "exported logical decoding snapshot: \"%s\" with %u transaction IDs" msgstr[0] "" +"추출된 논리 디코딩 스냅샷: \"%s\" 스냅샷, %u개 트랜잭션 ID" -#: replication/logical/snapbuild.c:1388 replication/logical/snapbuild.c:1480 -#: replication/logical/snapbuild.c:1996 +#: replication/logical/snapbuild.c:1404 replication/logical/snapbuild.c:1501 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "논리적 디코딩 이어서 시작할 위치: %X/%X" -#: replication/logical/snapbuild.c:1390 +#: replication/logical/snapbuild.c:1406 #, c-format msgid "There are no running transactions." msgstr "실행할 트랜잭션이 없음" -#: replication/logical/snapbuild.c:1432 +#: replication/logical/snapbuild.c:1453 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "논리적 디코딩 시작 위치: %X/%X" -#: replication/logical/snapbuild.c:1434 replication/logical/snapbuild.c:1458 +#: replication/logical/snapbuild.c:1455 replication/logical/snapbuild.c:1479 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "(대략 %d개) %u 보다 오래된 트랜잭션이 종료되길 기다리고 있습니다." -#: replication/logical/snapbuild.c:1456 +#: replication/logical/snapbuild.c:1477 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "논리적 디코딩을 이어서 시작할 위치: %X/%X" -#: replication/logical/snapbuild.c:1482 +#: replication/logical/snapbuild.c:1503 #, c-format msgid "There are no old transactions anymore." msgstr "더이상 오래된 트랜잭션이 없습니다." -#: replication/logical/snapbuild.c:1883 +#: replication/logical/snapbuild.c:1904 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "\"%s\" snapbuild 상태 파일의 매직 번호가 이상함: 현재값 %u, 기대값 %u" -#: replication/logical/snapbuild.c:1889 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "\"%s\" snapbuild 상태 파일의 버전이 이상함: 현재값 %u, 기대값 %u" -#: replication/logical/snapbuild.c:1930 +#: replication/logical/snapbuild.c:1951 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "" "\"%s\" snapbuild 상태 파일의 체크섬이 일치하지 않음: 조회값 %u, 기대값 %u" -#: replication/logical/snapbuild.c:1998 +#: replication/logical/snapbuild.c:2019 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "저장된 스냅샷을 이용해서 논리적 디코딩을 시작할 것입니다." -#: replication/logical/snapbuild.c:2105 +#: replication/logical/snapbuild.c:2126 #, c-format msgid "could not parse file name \"%s\"" msgstr "\"%s\" 파일 이름을 분석할 수 없음" -#: replication/logical/tablesync.c:153 +#: replication/logical/tablesync.c:161 #, c-format msgid "" "logical replication table synchronization worker for subscription \"%s\", " "table \"%s\" has finished" msgstr "\"%s\" 구독용 논리 복제 테이블 동기화 작업자가, \"%s\" 테이블 완료함" -#: replication/logical/tablesync.c:622 +#: replication/logical/tablesync.c:641 #, c-format msgid "" "logical replication apply worker for subscription \"%s\" will restart so " @@ -21834,44 +22526,44 @@ msgstr "" "two_phase 활성화를 위해 \"%s\" 구독을 위해 논리 복제 적용 작업자가 다시 시작" "됩니다." -#: replication/logical/tablesync.c:797 replication/logical/tablesync.c:939 +#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "\"%s.%s\" 테이블용 테이블 정보를 구할 수 없습니다, 해당 발행: %s" -#: replication/logical/tablesync.c:804 +#: replication/logical/tablesync.c:834 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr " \"%s.%s\" 테이블이 발행 안에 없습니다." -#: replication/logical/tablesync.c:862 +#: replication/logical/tablesync.c:892 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "\"%s.%s\" 테이블용 칼럼 목록 정보를 구할 수 없습니다, 해당 발행: %s" -#: replication/logical/tablesync.c:1041 +#: replication/logical/tablesync.c:1071 #, c-format msgid "" "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: " "%s" msgstr "\"%s.%s\" 테이블용 WHERE 절을 구할 수 없습니다, 해당 발행: %s" -#: replication/logical/tablesync.c:1192 +#: replication/logical/tablesync.c:1230 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "\"%s.%s\" 테이블용 초기 자료 복사를 시작할 수 없습니다: %s" -#: replication/logical/tablesync.c:1393 +#: replication/logical/tablesync.c:1429 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "발행 서버에서는 테이블 복사 트랜잭션을 시작할 수 없음: %s" -#: replication/logical/tablesync.c:1435 +#: replication/logical/tablesync.c:1472 #, c-format msgid "replication origin \"%s\" already exists" msgstr "\"%s\" 이름의 복제 오리진이 이미 있습니다." -#: replication/logical/tablesync.c:1468 replication/logical/worker.c:2374 +#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 #, c-format msgid "" "user \"%s\" cannot replicate into relation with row-level security enabled: " @@ -21880,18 +22572,18 @@ msgstr "" "\"%s\" 사용자는 로우 수준 보안 활성화 상태에서 릴레이션으로 복제할 수 없음: " "\"%s\"" -#: replication/logical/tablesync.c:1481 +#: replication/logical/tablesync.c:1518 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "발행 서버에서 테이블 복사 트랜잭션을 마칠 수 없음: %s" -#: replication/logical/worker.c:499 +#: replication/logical/worker.c:481 #, c-format msgid "" "logical replication parallel apply worker for subscription \"%s\" will stop" msgstr "\"%s\" 구독을 위한 논리 복제 병렬 반영 작업자가 중지됩니다." -#: replication/logical/worker.c:501 +#: replication/logical/worker.c:483 #, c-format msgid "" "Cannot handle streamed replication transactions using parallel apply workers " @@ -21900,12 +22592,12 @@ msgstr "" "모든 테이블 동기화 끝나기 전까지는 병렬 반영 작업자를 사용하는 스트리밍 복제 " "트랜잭셕은 처리할 수 없습니다." -#: replication/logical/worker.c:863 replication/logical/worker.c:978 +#: replication/logical/worker.c:852 replication/logical/worker.c:967 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "%d 번째 논리 복제 칼럼 안에 잘못된 바이너리 자료 형식 발견됨" -#: replication/logical/worker.c:2513 +#: replication/logical/worker.c:2500 #, c-format msgid "" "publisher did not send replica identity column expected by the logical " @@ -21914,7 +22606,7 @@ msgstr "" "발행 서버에서 \"%s.%s\" 논리 복제 대상 릴레이션의 복제 식별자 칼럼을 보내지 " "않았습니다." -#: replication/logical/worker.c:2520 +#: replication/logical/worker.c:2507 #, c-format msgid "" "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY " @@ -21925,22 +22617,22 @@ msgstr "" "KEY 도 없고, 발행 쪽 해당 테이블에 REPLICA IDENTITY FULL 속성 칼럼도 없습니" "다." -#: replication/logical/worker.c:3384 +#: replication/logical/worker.c:3371 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "잘못된 논리 복제 메시지 형태 \"??? (%d)\"" -#: replication/logical/worker.c:3556 +#: replication/logical/worker.c:3543 #, c-format msgid "data stream from publisher has ended" msgstr "발행 서버로부터의 데이터 스트림이 끝났습니다" -#: replication/logical/worker.c:3713 +#: replication/logical/worker.c:3697 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "시간 제한으로 논리 복제 작업자를 중지합니다." -#: replication/logical/worker.c:3907 +#: replication/logical/worker.c:3891 #, c-format msgid "" "logical replication worker for subscription \"%s\" will stop because the " @@ -21949,7 +22641,7 @@ msgstr "" "\"%s\" 구독이 지워졌기 때문에, 해당 구독용 논리 복제 작업자가 중지 될 것입니" "다." -#: replication/logical/worker.c:3920 +#: replication/logical/worker.c:3905 #, c-format msgid "" "logical replication worker for subscription \"%s\" will stop because the " @@ -21958,7 +22650,7 @@ msgstr "" "\"%s\" 구독이 비활성화 되었기 때문에, 해당 구독용 논리 복제 작업자가 중지 될 " "것입니다." -#: replication/logical/worker.c:3951 +#: replication/logical/worker.c:3936 #, c-format msgid "" "logical replication parallel apply worker for subscription \"%s\" will stop " @@ -21967,7 +22659,7 @@ msgstr "" "매개 변수가 바뀌어서 \"%s\" 구독을 위해 논리 복제 병렬 반영 작업자가 중지 될 " "것입니다." -#: replication/logical/worker.c:3955 +#: replication/logical/worker.c:3940 #, c-format msgid "" "logical replication worker for subscription \"%s\" will restart because of a " @@ -21975,8 +22667,31 @@ msgid "" msgstr "" "매개 변수가 바뀌어서 \"%s\" 구독을 위해 논리 복제 작업자가 중지 될 것입니다." +#: replication/logical/worker.c:3954 +#, c-format +msgid "" +"logical replication parallel apply worker for subscription \"%s\" will stop " +"because the subscription owner's superuser privileges have been revoked" +msgstr "" +"구독 소유주의 슈퍼유저 권한이 회수되어 \"%s\" 구독용 논리 복제 병렬 반영 " +"작업자가 중지 될 것임" + +#: replication/logical/worker.c:3958 +#, c-format +msgid "" +"logical replication worker for subscription \"%s\" will restart because the " +"subscription owner's superuser privileges have been revoked" +msgstr "" +"구독 소유주의 슈퍼유저 권한이 회수되어 \"%s\" 구독용 논리 복제 병렬 반영 " +"작업자가 재실행 될 것임" + #: replication/logical/worker.c:4478 #, c-format +msgid "subscription has no replication slot set" +msgstr "구독에서 사용할 복제 슬롯 세트가 없습니다." + +#: replication/logical/worker.c:4591 +#, c-format msgid "" "logical replication worker for subscription %u will not start because the " "subscription was removed during startup" @@ -21984,7 +22699,7 @@ msgstr "" "해당 구독이 시작하는 사이 지워져서 구독번호 %u 번용 논리 복제 작업자가 작동되" "지 못했습니다." -#: replication/logical/worker.c:4493 +#: replication/logical/worker.c:4607 #, c-format msgid "" "logical replication worker for subscription \"%s\" will not start because " @@ -21992,7 +22707,7 @@ msgid "" msgstr "" "\"%s\" 구독이 시작되는 사이 지워져서 논리 복제 작업자가 작동되지 못했습니다." -#: replication/logical/worker.c:4510 +#: replication/logical/worker.c:4631 #, c-format msgid "" "logical replication table synchronization worker for subscription \"%s\", " @@ -22001,124 +22716,125 @@ msgstr "" "\"%s\" 구독, \"%s\" 테이블을 위한 논리 복제 테이블 동기화 작업자가 시작되었습" "니다." -#: replication/logical/worker.c:4515 +#: replication/logical/worker.c:4636 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "\"%s\" 구독을 위한 논리 복제 반영 작업자가 시작되었습니다." -#: replication/logical/worker.c:4590 -#, c-format -msgid "subscription has no replication slot set" -msgstr "구독에서 사용할 복제 슬롯 세트가 없습니다." - -#: replication/logical/worker.c:4757 +#: replication/logical/worker.c:4758 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "\"%s\" 구독이 오류로 비활성화 되었습니다." -#: replication/logical/worker.c:4805 +#: replication/logical/worker.c:4806 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "%X/%X LSN 에서 트랜잭션 건너 뛰어 논리 복제를 시작함" -#: replication/logical/worker.c:4819 +#: replication/logical/worker.c:4820 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "논리 복제가 %X/%X LSN까지 트랜잭션을 건너뛰었습니다." -#: replication/logical/worker.c:4901 +#: replication/logical/worker.c:4902 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "\"%s\" 이름의 구독의 LSN 건너뛰기 완료함" -#: replication/logical/worker.c:4902 +#: replication/logical/worker.c:4903 #, c-format msgid "" "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN " "%X/%X." msgstr "원력 트랜잭션 마침 WAL 위치 %X/%X LSN이 skip-LSN %X/%X와 같지 않음" -#: replication/logical/worker.c:4928 +#: replication/logical/worker.c:4940 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\"" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\"" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\"" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:4944 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" in transaction %u" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" in transaction %u" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 트랜잭션: %u" -#: replication/logical/worker.c:4937 +#: replication/logical/worker.c:4949 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" in transaction %u, finished at %X/%X" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" in transaction %u, finished at %X/%X" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 트랜잭션: %u, 마침 위치: %X/%X" -#: replication/logical/worker.c:4948 +#: replication/logical/worker.c:4960 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" for replication target relation \"%s.%s\" in transaction %u" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" for replication target relation \"%s.%s\" in transaction %u" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 복제 대상 릴레이션: \"%s.%s\", 해당 트랜잭션: %u" -#: replication/logical/worker.c:4955 +#: replication/logical/worker.c:4967 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" for replication target relation \"%s.%s\" in transaction %u, finished at " -"%X/%X" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" for replication target relation \"%s.%s\" in transaction %u, finished " +"at %X/%X" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 복제 대상 릴레이션: \"%s.%s\", 해당 트랜잭션: %u, 마침 위치: %X/%X" -#: replication/logical/worker.c:4966 +#: replication/logical/worker.c:4978 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" for replication target relation \"%s.%s\" column \"%s\" in " +"transaction %u" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 복제 대상 릴레이션: \"%s.%s\", 해당 칼럼 \"%s\", 해당 트랜잭션: %u" -#: replication/logical/worker.c:4974 +#: replication/logical/worker.c:4986 #, c-format msgid "" -"processing remote data for replication origin \"%s\" during message type \"%s" -"\" for replication target relation \"%s.%s\" column \"%s\" in transaction " -"%u, finished at %X/%X" +"processing remote data for replication origin \"%s\" during message type " +"\"%s\" for replication target relation \"%s.%s\" column \"%s\" in " +"transaction %u, finished at %X/%X" msgstr "" "\"%s\" 복제 오리진용 원격 데이터를 처리합니다. 해당 메시지 유형: \"%s\", 해" "당 복제 대상 릴레이션: \"%s.%s\", 해당 칼럼 \"%s\", 해당 트랜잭션: %u, 마침 " "위치: %X/%X" -#: replication/pgoutput/pgoutput.c:318 +#: replication/pgoutput/pgoutput.c:322 #, c-format msgid "invalid proto_version" msgstr "잘못된 proto_version" -#: replication/pgoutput/pgoutput.c:323 +#: replication/pgoutput/pgoutput.c:327 #, c-format msgid "proto_version \"%s\" out of range" msgstr "proto_verson \"%s\" 범위 벗어남" -#: replication/pgoutput/pgoutput.c:340 +#: replication/pgoutput/pgoutput.c:344 #, c-format msgid "invalid publication_names syntax" msgstr "잘못된 publication_names 구문" -#: replication/pgoutput/pgoutput.c:443 +#: replication/pgoutput/pgoutput.c:414 replication/pgoutput/pgoutput.c:418 +#, c-format +msgid "option \"%s\" missing" +msgstr "\"%s\" 옵션 빠졌음" + +#: replication/pgoutput/pgoutput.c:478 #, c-format msgid "" "client sent proto_version=%d but server only supports protocol %d or lower" @@ -22126,7 +22842,7 @@ msgstr "" "클라이언트가 proto_version=%d 값을 보냈지만, %d 버전 또는 그 이하 버전 프로토" "콜만 지원합니다." -#: replication/pgoutput/pgoutput.c:449 +#: replication/pgoutput/pgoutput.c:484 #, c-format msgid "" "client sent proto_version=%d but server only supports protocol %d or higher" @@ -22134,12 +22850,7 @@ msgstr "" "클라이언트가 proto_version=%d 값을 보냈지만, %d 버전 또는 그 이상 버전 프로토" "콜만 지원합니다." -#: replication/pgoutput/pgoutput.c:455 -#, c-format -msgid "publication_names parameter missing" -msgstr "publication_names 매개 변수가 빠졌음" - -#: replication/pgoutput/pgoutput.c:469 +#: replication/pgoutput/pgoutput.c:499 #, c-format msgid "" "requested proto_version=%d does not support streaming, need %d or higher" @@ -22147,7 +22858,7 @@ msgstr "" "요청한 %d 버전 proto_version은 스트리밍을 지원하지 않습니다. %d 또는 그 이상 " "버전이 필요합니다." -#: replication/pgoutput/pgoutput.c:475 +#: replication/pgoutput/pgoutput.c:505 #, c-format msgid "" "requested proto_version=%d does not support parallel streaming, need %d or " @@ -22156,12 +22867,12 @@ msgstr "" "요청한 proto_version=%d 값은 스트리밍을 지원하지 않습니다. %d 또는 그 이상 버" "전이 필요합니다." -#: replication/pgoutput/pgoutput.c:480 +#: replication/pgoutput/pgoutput.c:510 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "스트리밍을 요청했지만, 출력 플러그인이 지원하지 않습니다." -#: replication/pgoutput/pgoutput.c:497 +#: replication/pgoutput/pgoutput.c:524 #, c-format msgid "" "requested proto_version=%d does not support two-phase commit, need %d or " @@ -22170,27 +22881,27 @@ msgstr "" "요청한 proto_version=%d 값은 2PC를 지원하지 않습니다. %d 또는 그 이상 버전이 " "필요합니다." -#: replication/pgoutput/pgoutput.c:502 +#: replication/pgoutput/pgoutput.c:529 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "2PC를 요청했지만, 출력 플러그인이 지원하지 않습니다." -#: replication/slot.c:207 +#: replication/slot.c:260 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "\"%s\" 복제 슬롯 이름이 너무 짧음" -#: replication/slot.c:216 +#: replication/slot.c:269 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "\"%s\" 복제 슬롯 이름이 너무 긺" -#: replication/slot.c:229 +#: replication/slot.c:282 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "\"%s\" 복제 슬롯 이름에 사용할 수 없는 문자가 있음" -#: replication/slot.c:231 +#: replication/slot.c:284 #, c-format msgid "" "Replication slot names may only contain lower case letters, numbers, and the " @@ -22199,193 +22910,314 @@ msgstr "" "복제 슬롯 이름으로 사용할 수 있는 문자는 영문 소문자, 숫자, 밑줄(_) 문자입니" "다." -#: replication/slot.c:285 +#: replication/slot.c:333 +#, c-format +msgid "cannot enable failover for a replication slot created on the standby" +msgstr "대기 서버에서 만들어진 복제 슬롯에는 failover 설정을 활성화 할 수 없음" + +#: replication/slot.c:345 replication/slot.c:849 +#, c-format +msgid "cannot enable failover for a temporary replication slot" +msgstr "임시 복제 슬롯에는 failover 설정을 활성화 할 수 없음" + +#: replication/slot.c:370 #, c-format msgid "replication slot \"%s\" already exists" msgstr "\"%s\" 이름의 복제 슬롯이 이미 있습니다." -#: replication/slot.c:295 +#: replication/slot.c:380 #, c-format msgid "all replication slots are in use" msgstr "모든 복제 슬롯이 사용 중입니다." -#: replication/slot.c:296 +#: replication/slot.c:381 #, c-format -msgid "Free one or increase max_replication_slots." -msgstr "하나를 비우든지, max_replication_slots 설정값을 늘리세요." +msgid "Free one or increase \"max_replication_slots\"." +msgstr "하나를 비우든지, \"max_replication_slots\" 설정값을 늘리세요." -#: replication/slot.c:474 replication/slotfuncs.c:736 -#: utils/activity/pgstat_replslot.c:55 utils/adt/genfile.c:774 +#: replication/slot.c:560 replication/slot.c:2450 replication/slotfuncs.c:661 +#: utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "\"%s\" 이름의 복제 슬롯이 없습니다" -#: replication/slot.c:520 replication/slot.c:1110 +#: replication/slot.c:606 replication/slot.c:1337 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "\"%s\" 이름의 복제 슬롯을 %d PID 프로세스가 사용중입니다." -#: replication/slot.c:756 replication/slot.c:1645 replication/slot.c:2028 +#: replication/slot.c:638 +#, c-format +msgid "acquired logical replication slot \"%s\"" +msgstr "\"%s\" 논리 복제 슬롯을 획득함" + +#: replication/slot.c:640 +#, c-format +msgid "acquired physical replication slot \"%s\"" +msgstr "\"%s\" 물리 복제 슬롯을 획득함" + +#: replication/slot.c:729 +#, c-format +msgid "released logical replication slot \"%s\"" +msgstr "\"%s\" 논리 복제 슬롯을 반환함" + +#: replication/slot.c:731 +#, c-format +msgid "released physical replication slot \"%s\"" +msgstr "\"%s\" 물리 복제 슬롯을 반환함" + +#: replication/slot.c:797 +#, c-format +msgid "cannot drop replication slot \"%s\"" +msgstr "\"%s\" 복제 슬롯을 삭제할 수 없음" + +#: replication/slot.c:816 +#, c-format +msgid "cannot use %s with a physical replication slot" +msgstr "물리 복제 슬롯과 함께 %s 사용할 수 없음" + +#: replication/slot.c:828 +#, c-format +msgid "cannot alter replication slot \"%s\"" +msgstr "\"%s\" 복제 슬롯을 변경 할 수 없음" + +#: replication/slot.c:838 +#, c-format +msgid "cannot enable failover for a replication slot on the standby" +msgstr "대기 서버의 복제 슬롯에는 failover 설정을 활성화 할 수 없음" + +#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 #, c-format msgid "could not remove directory \"%s\"" msgstr "\"%s\" 디렉터리를 삭제할 수 없음" -#: replication/slot.c:1145 +#: replication/slot.c:1372 #, c-format -msgid "replication slots can only be used if max_replication_slots > 0" -msgstr "복제 슬롯은 max_replication_slots > 0 상태에서 사용될 수 있습니다." +msgid "replication slots can only be used if \"max_replication_slots\" > 0" +msgstr "복제 슬롯은 \"max_replication_slots\" > 0 상태에서만 사용할 수 있음" -#: replication/slot.c:1150 +#: replication/slot.c:1377 #, c-format -msgid "replication slots can only be used if wal_level >= replica" -msgstr "복제 슬롯은 wal_level >= replica 상태에서 사용될 수 있습니다." +msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" +msgstr "복제 슬롯은 \"wal_level\" >= \"replica\" 상태에서만 사용할 수 있음" -#: replication/slot.c:1162 +#: replication/slot.c:1389 #, c-format msgid "permission denied to use replication slots" msgstr "복제 슬롯을 사용할 권한 없음" -#: replication/slot.c:1163 +#: replication/slot.c:1390 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "복제 슬롯은 %s 속성을 가진 롤만 사용할 수 있습니다." -#: replication/slot.c:1271 +#: replication/slot.c:1498 #, c-format msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." msgstr[0] "" "해당 슬롯 restart_lsn %X/%X 값은 %llu 바이트로 그 크기를 초과했습니다." -#: replication/slot.c:1279 +#: replication/slot.c:1506 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "해당 슬롯이 xid horizon %u 값으로 충돌합니다." -#: replication/slot.c:1284 +#: replication/slot.c:1511 msgid "" -"Logical decoding on standby requires wal_level >= logical on the primary " -"server." +"Logical decoding on standby requires \"wal_level\" >= \"logical\" on the " +"primary server." msgstr "" -"대기 서버의 논리적 디코딩 기능은 주서버의 wal_level >= logical 설정이 필요합" +"대기 서버의 논리적 디코딩 기능은 주서버의 \"wal_level\" >= \"logical\" 설정이 필요합" "니다." -#: replication/slot.c:1292 +#: replication/slot.c:1519 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "%d번 프로세스를 중지합니다. \"%s\" 복제 슬롯이 삭제될 것입니다." -#: replication/slot.c:1294 +#: replication/slot.c:1521 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "\"%s\" 복제 슬롯이 사용되지 않아 삭제될 것입니다." -#: replication/slot.c:1966 +#: replication/slot.c:2249 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "\"%s\" 복제 슬롯 파일의 매직 번호가 이상합니다: 현재값 %u, 기대값 %u" -#: replication/slot.c:1973 +#: replication/slot.c:2256 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "\"%s\" 복제 슬롯 파일은 지원하지 않는 %u 버전 파일입니다" -#: replication/slot.c:1980 +#: replication/slot.c:2263 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "\"%s\" 복제 슬롯 파일이 %u 길이로 손상되었습니다." -#: replication/slot.c:2016 +#: replication/slot.c:2299 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "\"%s\" 복제 슬롯 파일의 체크섬 값이 이상합니다: 현재값 %u, 기대값 %u" -#: replication/slot.c:2050 +#: replication/slot.c:2333 #, c-format -msgid "logical replication slot \"%s\" exists, but wal_level < logical" -msgstr "\"%s\" 논리 복제 슬롯이 있지만, wal_level < logical" +msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" +msgstr "\"%s\" 논리 복제 슬롯이 있지만, \"wal_level\" < \"logical\" 설정임" -#: replication/slot.c:2052 +#: replication/slot.c:2335 #, c-format -msgid "Change wal_level to be logical or higher." -msgstr "wal_level 값을 logical 또는 그 이상으로 지정하세요." +msgid "Change \"wal_level\" to be \"logical\" or higher." +msgstr "\"wal_level\" 값을 \"logical\" 또는 그 이상으로 지정하세요." -#: replication/slot.c:2056 +#: replication/slot.c:2339 #, c-format -msgid "physical replication slot \"%s\" exists, but wal_level < replica" -msgstr "\"%s\" 물리 복제 슬롯이 있지만, wal_level < replica" +msgid "" +"physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" +msgstr "\"%s\" 물리 복제 슬롯이 있지만, \"wal_level\" < \"replica\" 설정임" -#: replication/slot.c:2058 +#: replication/slot.c:2341 #, c-format -msgid "Change wal_level to be replica or higher." -msgstr "wal_level 값을 replica 또는 그 이상으로 지정하세요." +msgid "Change \"wal_level\" to be \"replica\" or higher." +msgstr "\"wal_level\" 값을 \"replica\" 또는 그 이상으로 지정하세요." -#: replication/slot.c:2092 +#: replication/slot.c:2383 #, c-format msgid "too many replication slots active before shutdown" msgstr "서버 중지 전에 너무 많은 복제 슬롯이 활성화 상태입니다" -#: replication/slotfuncs.c:601 +#: replication/slot.c:2458 +#, c-format +msgid "\"%s\" is not a physical replication slot" +msgstr "\"%s\" 슬롯은 물리 복제 슬롯이 아님" + +#: replication/slot.c:2635 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "\"%s\" 복제 슬롯에는 \"%s\" 매개 변수 설정이 없음" + +#: replication/slot.c:2637 replication/slot.c:2671 replication/slot.c:2686 +#, c-format +msgid "" +"Logical replication is waiting on the standby associated with replication " +"slot \"%s\"." +msgstr "논리 복제가 \"%s\" 복제 슬롯과 연결된 대기 서버에서 대기 중" + +#: replication/slot.c:2639 +#, c-format +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "\"%s\" 이름의 복제 슬롯을 만들든가, \"%s\" 설정을 바꾸세요." + +#: replication/slot.c:2649 +#, c-format +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "\"%s\" 논리 복제 슬롯을 \"%s\" 설정에 지정할 수 없음" + +#: replication/slot.c:2651 +#, c-format +msgid "" +"Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "논리 복제가 \"%s\" 복제 슬롯 수정을 기다리고 있습니다." + +#: replication/slot.c:2653 +#, c-format +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "\"%s\" 논리 복제 슬롯을 \"%s\" 설정에서 빼세요." + +#: replication/slot.c:2669 +#, c-format +msgid "" +"physical replication slot \"%s\" specified in parameter \"%s\" has been " +"invalidated" +msgstr "\"%s\" 물리 복제 슬롯이 \"%s\" 설정에서 invalid 상태가 되었음" + +#: replication/slot.c:2673 +#, c-format +msgid "" +"Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "\"%s\" 복제 슬롯을 삭제하고 다시 만들거나, \"%s\" 설정을 바꾸세요." + +#: replication/slot.c:2684 +#, c-format +msgid "" +"replication slot \"%s\" specified in parameter \"%s\" does not have " +"active_pid" +msgstr "\"%s\" 복제 슬롯(\"%s\" 설정에 지정된)에 대응하는 active_pid가 없음" + +#: replication/slot.c:2688 +#, c-format +msgid "" +"Start the standby associated with the replication slot \"%s\", or amend " +"parameter \"%s\"." +msgstr "\"%s\" 복제 슬롯과 관계된 대기 서버를 시작하거나, \"%s\" 설정을 바꾸세요." + +#: replication/slotfuncs.c:526 #, c-format msgid "invalid target WAL LSN" msgstr "잘못된 대상 WAL LSN" -#: replication/slotfuncs.c:623 +#: replication/slotfuncs.c:548 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "\"%s\" 이름의 복제 슬롯은 사용할 수 없음" -#: replication/slotfuncs.c:625 +#: replication/slotfuncs.c:550 #, c-format msgid "" "This slot has never previously reserved WAL, or it has been invalidated." msgstr "이 슬롯은 한 번도 WAL를 예약한 적이 없거나, 잘못된 것임" -#: replication/slotfuncs.c:641 +#: replication/slotfuncs.c:566 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "복제 슬롯 위치를 %X/%X 로 바꿀 수 없습니다. 최소값은 %X/%X" -#: replication/slotfuncs.c:748 +#: replication/slotfuncs.c:673 #, c-format msgid "" "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "물리 복제 슬롯(\"%s\")을 논리 복제 슬롯으로 복사할 수 없음" -#: replication/slotfuncs.c:750 +#: replication/slotfuncs.c:675 #, c-format msgid "" "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "논리 복제 슬롯(\"%s\")을 물리 복제 슬롯으로 복사할 수 없음" -#: replication/slotfuncs.c:757 +#: replication/slotfuncs.c:682 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "WAL을 확보하지 않은 복제 슬롯은 복사할 수 없음" -#: replication/slotfuncs.c:834 +#: replication/slotfuncs.c:768 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "\"%s\" 복제 슬롯을 복사할 수 없음" -#: replication/slotfuncs.c:836 +#: replication/slotfuncs.c:770 #, c-format msgid "" "The source replication slot was modified incompatibly during the copy " "operation." msgstr "복사 작업 중 원본 복제 슬롯이 비정상적으로 변경되었습니다." -#: replication/slotfuncs.c:842 +#: replication/slotfuncs.c:776 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "논리 복제가 끝나지 않은 \"%s\" 슬롯은 복사할 수 없음" -#: replication/slotfuncs.c:844 +#: replication/slotfuncs.c:778 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "원본 복제 슬롯의 confirmed_flush_lsn 값이 타당할 때 다시 시도하세요." -#: replication/syncrep.c:262 +#: replication/slotfuncs.c:877 +#, c-format +msgid "replication slots can only be synchronized to a standby server" +msgstr "복제 슬롯은 대기 서버에만 동기화 될 수 있음" + +#: replication/syncrep.c:261 #, c-format msgid "" "canceling the wait for synchronous replication and terminating connection " @@ -22393,7 +23225,7 @@ msgid "" msgstr "" "관리자 명령에 의해 동기식 복제의 대기 작업과 접속 끊기 작업을 취소합니다." -#: replication/syncrep.c:263 replication/syncrep.c:280 +#: replication/syncrep.c:262 replication/syncrep.c:279 #, c-format msgid "" "The transaction has already committed locally, but might not have been " @@ -22402,209 +23234,204 @@ msgstr "" "주 서버에서는 이 트랜잭션이 커밋되었지만, 복제용 대기 서버에서는 아직 커밋 되" "지 않았을 가능성이 있습니다." -#: replication/syncrep.c:279 +#: replication/syncrep.c:278 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "사용자 요청에 의해 동기식 복제 작업을 취소합니다." -#: replication/syncrep.c:486 +#: replication/syncrep.c:485 #, c-format -msgid "standby \"%s\" is now a synchronous standby with priority %u" -msgstr "\"%s\" 대기 서버의 동기식 복제 우선순위가 %u 로 변경되었습니다." +msgid "standby \"%s\" is now a synchronous standby with priority %d" +msgstr "\"%s\" 대기 서버의 동기식 복제 우선순위가 %d 순위로 변경되었음" -#: replication/syncrep.c:490 +#: replication/syncrep.c:489 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "\"%s\" 대기 서버가 동기식 대기 서버 후보가 되었습니다" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1013 #, c-format -msgid "synchronous_standby_names parser failed" -msgstr "synchronous_standby_names 값을 분석할 수 없음" +msgid "\"synchronous_standby_names\" parser failed" +msgstr "\"synchronous_standby_names\" 값을 분석할 수 없음" -#: replication/syncrep.c:1025 +#: replication/syncrep.c:1019 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "동기식 대기 서버 수 (%d)는 0보다 커야 합니다." -#: replication/walreceiver.c:180 +#: replication/walreceiver.c:176 #, c-format msgid "terminating walreceiver process due to administrator command" msgstr "관리자 명령으로 인해 WAL 수신기를 종료합니다." -#: replication/walreceiver.c:305 -#, c-format -msgid "could not connect to the primary server: %s" -msgstr "주 서버에 연결 할 수 없음: %s" - -#: replication/walreceiver.c:352 +#: replication/walreceiver.c:354 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "데이터베이스 시스템 식별번호가 주 서버와 대기 서버가 서로 다름" -#: replication/walreceiver.c:353 +#: replication/walreceiver.c:355 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "주 서버: %s, 대기 서버: %s." -#: replication/walreceiver.c:364 +#: replication/walreceiver.c:366 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "" "주 서버의 제일 최신의 타임라인은 %u 인데, 복구 타임라인 %u 보다 옛것입니다" -#: replication/walreceiver.c:417 +#: replication/walreceiver.c:419 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "주 서버의 WAL 스트리밍 시작 위치: %X/%X (타임라인 %u)" -#: replication/walreceiver.c:421 +#: replication/walreceiver.c:423 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "WAL 스트리밍 재시작 위치: %X/%X (타임라인 %u)" -#: replication/walreceiver.c:457 +#: replication/walreceiver.c:458 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "WAL 스트리밍 계속할 수 없음, 복구가 이미 종료됨" -#: replication/walreceiver.c:501 +#: replication/walreceiver.c:502 #, c-format msgid "replication terminated by primary server" msgstr "주 서버에 의해서 복제가 끝남" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:503 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "타임라인 %u, 위치 %X/%X 에서 WAL 끝에 도달함" -#: replication/walreceiver.c:592 +#: replication/walreceiver.c:593 #, c-format msgid "terminating walreceiver due to timeout" msgstr "시간 제한으로 wal 수신기를 중지합니다." -#: replication/walreceiver.c:624 +#: replication/walreceiver.c:625 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "주 서버에는 요청 받은 %u 타임라인의 WAL가 더 이상 없습니다." -#: replication/walreceiver.c:640 replication/walreceiver.c:1066 +#: replication/walreceiver.c:641 replication/walreceiver.c:1071 #, c-format msgid "could not close WAL segment %s: %m" msgstr "%s WAL 조각 파일을 닫을 수 없음: %m" -#: replication/walreceiver.c:759 +#: replication/walreceiver.c:760 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "주 서버에서 %u 타임라인용 타임라인 내역 파일을 가져옵니다." -#: replication/walreceiver.c:954 +#: replication/walreceiver.c:959 #, c-format -msgid "could not write to WAL segment %s at offset %u, length %lu: %m" -msgstr "%s WAL 조각 파일 쓰기 실패: 위치 %u, 길이 %lu: %m" +msgid "could not write to WAL segment %s at offset %d, length %lu: %m" +msgstr "%s WAL 조각 파일 쓰기 실패: 위치 %d, 길이 %lu: %m" -#: replication/walsender.c:519 +#: replication/walsender.c:531 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "논리 복제 슬롯으로 %s 사용할 수 없음" -#: replication/walsender.c:623 storage/smgr/md.c:1529 +#: replication/walsender.c:635 storage/smgr/md.c:1735 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "\"%s\" 파일의 끝을 찾을 수 없음: %m" -#: replication/walsender.c:627 +#: replication/walsender.c:639 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "\"%s\" 파일에서 시작 위치를 찾을 수 없음: %m" -#: replication/walsender.c:704 +#: replication/walsender.c:853 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "물리적 복제에서 논리적 복제 슬롯을 사용할 수 없음" -#: replication/walsender.c:770 +#: replication/walsender.c:919 #, c-format msgid "" "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "요청된 %X/%X 시작 위치(타임라인 %u)가 이 서버 내역에 없습니다." -#: replication/walsender.c:773 +#: replication/walsender.c:922 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "이 서버의 시작 위치: 타임라인 %u, 위치 %X/%X" -#: replication/walsender.c:817 +#: replication/walsender.c:966 #, c-format msgid "" "requested starting point %X/%X is ahead of the WAL flush position of this " "server %X/%X" msgstr "%X/%X 위치는 서버의 %X/%X 보다 미래의 것입니다." -#: replication/walsender.c:1010 +#: replication/walsender.c:1160 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "\"%s\" CREATE_REPLICATION_SLOT 옵션에서 쓸 수 없는 값: \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1095 +#: replication/walsender.c:1266 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s 명령은 트랜잭션 블럭안에서 실행할 수 없음" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1105 +#: replication/walsender.c:1276 #, c-format msgid "%s must be called inside a transaction" msgstr "%s 명령은 트랜잭션 블럭안에서 실행할 수 있음" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1111 +#: replication/walsender.c:1282 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s 구문은 격리 수준이 REPEATABLE READ 일때만 사용할 수 있습니다." #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1116 +#: replication/walsender.c:1287 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%s 명령은 읽기 전용 트랜잭션 블럭안에서만 실행할 수 있음" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1122 +#: replication/walsender.c:1293 #, c-format msgid "%s must be called before any query" msgstr "어떤 쿼리보다 먼저 %s 명령을 호출해야 함" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1128 +#: replication/walsender.c:1299 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s 명령은 서브트랜잭션 블럭안에서 실행할 수 없음" -#: replication/walsender.c:1275 +#: replication/walsender.c:1472 #, c-format msgid "terminating walsender process after promotion" msgstr "운영전환 뒤 wal 송신기 프로세스를 중지합니다." -#: replication/walsender.c:1696 +#: replication/walsender.c:2000 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "WAL 송신기가 중지 중일 때는 새 명령을 실행할 수 없습니다." -#: replication/walsender.c:1731 +#: replication/walsender.c:2035 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "물리적 복제를 위한 WAL 송신기에서 SQL 명령을 실행할 수 없음" -#: replication/walsender.c:1764 +#: replication/walsender.c:2068 #, c-format msgid "received replication command: %s" msgstr "수신된 복제 명령: %s" -#: replication/walsender.c:1772 tcop/fastpath.c:209 tcop/postgres.c:1138 -#: tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2210 -#: tcop/postgres.c:2648 tcop/postgres.c:2726 +#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1142 +#: tcop/postgres.c:1500 tcop/postgres.c:1752 tcop/postgres.c:2234 +#: tcop/postgres.c:2672 tcop/postgres.c:2749 #, c-format msgid "" "current transaction is aborted, commands ignored until end of transaction " @@ -22613,215 +23440,215 @@ msgstr "" "현재 트랜잭션은 중지되어 있습니다. 이 트랜잭션을 종료하기 전까지는 모든 명령" "이 무시될 것입니다" -#: replication/walsender.c:1914 replication/walsender.c:1949 +#: replication/walsender.c:2233 replication/walsender.c:2268 #, c-format msgid "unexpected EOF on standby connection" msgstr "대기 서버 연결에서 예상치 못한 EOF 발견함" -#: replication/walsender.c:1937 +#: replication/walsender.c:2256 #, c-format msgid "invalid standby message type \"%c\"" msgstr "잘못된 대기 서버 메시지 형태 \"%c\"" -#: replication/walsender.c:2026 +#: replication/walsender.c:2345 #, c-format msgid "unexpected message type \"%c\"" msgstr "예상치 못한 메시지 형태: \"%c\"" -#: replication/walsender.c:2439 +#: replication/walsender.c:2759 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "복제 시간 제한으로 wal 송신기 프로세스를 종료합니다." -#: rewrite/rewriteDefine.c:111 rewrite/rewriteDefine.c:842 +#: rewrite/rewriteDefine.c:104 rewrite/rewriteDefine.c:835 #, c-format msgid "rule \"%s\" for relation \"%s\" already exists" msgstr "\"%s\" 이름의 룰(rule)이 \"%s\" 테이블에 이미 지정되어있습니다" -#: rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:780 +#: rewrite/rewriteDefine.c:261 rewrite/rewriteDefine.c:773 #, c-format msgid "relation \"%s\" cannot have rules" msgstr "\"%s\" 릴레이션은 룰을 지정할 수 없음" -#: rewrite/rewriteDefine.c:299 +#: rewrite/rewriteDefine.c:292 #, c-format msgid "rule actions on OLD are not implemented" msgstr "OLD에 대한 실행 룰(rule)은 아직 구현되지 않았습니다" -#: rewrite/rewriteDefine.c:300 +#: rewrite/rewriteDefine.c:293 #, c-format msgid "Use views or triggers instead." msgstr "대신에 뷰나 트리거를 사용하십시오." -#: rewrite/rewriteDefine.c:304 +#: rewrite/rewriteDefine.c:297 #, c-format msgid "rule actions on NEW are not implemented" msgstr "NEW에 대한 실행 룰(rule)은 아직 구현되지 않았습니다" -#: rewrite/rewriteDefine.c:305 +#: rewrite/rewriteDefine.c:298 #, c-format msgid "Use triggers instead." msgstr "대신에 트리거를 사용하십시오." -#: rewrite/rewriteDefine.c:319 +#: rewrite/rewriteDefine.c:312 #, c-format msgid "relation \"%s\" cannot have ON SELECT rules" msgstr "\"%s\" 릴레이션은 ON SELECT 룰을 지정할 수 없음" -#: rewrite/rewriteDefine.c:329 +#: rewrite/rewriteDefine.c:322 #, c-format msgid "INSTEAD NOTHING rules on SELECT are not implemented" msgstr "SELECT 에서 INSTEAD NOTHING 룰(rule)은 구현되지 않았습니다" -#: rewrite/rewriteDefine.c:330 +#: rewrite/rewriteDefine.c:323 #, c-format msgid "Use views instead." msgstr "대신에 뷰를 사용하십시오." -#: rewrite/rewriteDefine.c:338 +#: rewrite/rewriteDefine.c:331 #, c-format msgid "multiple actions for rules on SELECT are not implemented" msgstr "SELECT에 대한 다중 실행 룰(rule)은 구현되지 않았습니다" -#: rewrite/rewriteDefine.c:348 +#: rewrite/rewriteDefine.c:341 #, c-format msgid "rules on SELECT must have action INSTEAD SELECT" msgstr "" "SELECT에 대한 룰(rule)은 그 지정에 INSTEAD SELECT 실행규칙을 지정해야만합니다" -#: rewrite/rewriteDefine.c:356 +#: rewrite/rewriteDefine.c:349 #, c-format msgid "rules on SELECT must not contain data-modifying statements in WITH" msgstr "SELECT 룰에는 WITH 절 안에 자료 변경 구문을 포함할 수 없습니다." -#: rewrite/rewriteDefine.c:364 +#: rewrite/rewriteDefine.c:357 #, c-format msgid "event qualifications are not implemented for rules on SELECT" msgstr "" "이벤트 자격(event qualifications)은 SELECT 룰(rule)에서 구현되지 않았습니다" -#: rewrite/rewriteDefine.c:391 +#: rewrite/rewriteDefine.c:384 #, c-format msgid "\"%s\" is already a view" msgstr "\"%s\" 이름의 뷰가 이미 있습니다" -#: rewrite/rewriteDefine.c:415 +#: rewrite/rewriteDefine.c:408 #, c-format msgid "view rule for \"%s\" must be named \"%s\"" msgstr "\"%s\" 위한 뷰 룰(view rule)의 이름은 \"%s\" 여야만합니다" -#: rewrite/rewriteDefine.c:442 +#: rewrite/rewriteDefine.c:435 #, c-format msgid "cannot have multiple RETURNING lists in a rule" msgstr "하나의 rule에서 여러개의 RETURNING 목록을 지정할 수 없습니다" -#: rewrite/rewriteDefine.c:447 +#: rewrite/rewriteDefine.c:440 #, c-format msgid "RETURNING lists are not supported in conditional rules" msgstr "RETURNING 목록은 conditional rule에서는 지원하지 않습니다" -#: rewrite/rewriteDefine.c:451 +#: rewrite/rewriteDefine.c:444 #, c-format msgid "RETURNING lists are not supported in non-INSTEAD rules" msgstr "RETURNING 목록은 non-INSTEAD rule에서는 지원하지 않습니다" -#: rewrite/rewriteDefine.c:465 +#: rewrite/rewriteDefine.c:458 #, c-format msgid "non-view rule for \"%s\" must not be named \"%s\"" msgstr "\"%s\" 위한 뷰가 아닌 룰 이름은 \"%s\" 아니여야 합니다." -#: rewrite/rewriteDefine.c:539 +#: rewrite/rewriteDefine.c:532 #, c-format msgid "SELECT rule's target list has too many entries" msgstr "SELECT 룰(rule)의 대상 목록이 너무 많은 엔트리를 가지고 있습니다" -#: rewrite/rewriteDefine.c:540 +#: rewrite/rewriteDefine.c:533 #, c-format msgid "RETURNING list has too many entries" msgstr "RETURNING 목록이 너무 많은 항목를 가지고 있습니다" -#: rewrite/rewriteDefine.c:567 +#: rewrite/rewriteDefine.c:560 #, c-format msgid "cannot convert relation containing dropped columns to view" msgstr "뷰에서 삭제된 칼럼을 포함하고 있는 릴레이션을 변환할 수 없습니다" -#: rewrite/rewriteDefine.c:568 +#: rewrite/rewriteDefine.c:561 #, c-format msgid "" "cannot create a RETURNING list for a relation containing dropped columns" msgstr "" "릴레이션에 삭제된 칼럼을 포함하고 있는 RETURNING 목록을 만들 수 없습니다." -#: rewrite/rewriteDefine.c:574 +#: rewrite/rewriteDefine.c:567 #, c-format msgid "" "SELECT rule's target entry %d has different column name from column \"%s\"" msgstr "SELECT 룰(rule)의 대상 엔트리 번호가(%d)가 \"%s\" 칼럼 이름과 틀립니다" -#: rewrite/rewriteDefine.c:576 +#: rewrite/rewriteDefine.c:569 #, c-format msgid "SELECT target entry is named \"%s\"." msgstr "SELECT 대상 엔트리 이름은 \"%s\" 입니다." -#: rewrite/rewriteDefine.c:585 +#: rewrite/rewriteDefine.c:578 #, c-format msgid "SELECT rule's target entry %d has different type from column \"%s\"" msgstr "SELECT 룰(rule)의 대상 엔트리 번호(%d)가 \"%s\" 칼럼 자료형과 틀립니다" -#: rewrite/rewriteDefine.c:587 +#: rewrite/rewriteDefine.c:580 #, c-format msgid "RETURNING list's entry %d has different type from column \"%s\"" msgstr "RETURNING 목록의 %d번째 항목의 자료형이 \"%s\" 칼럼 자료형과 틀립니다" -#: rewrite/rewriteDefine.c:590 rewrite/rewriteDefine.c:614 +#: rewrite/rewriteDefine.c:583 rewrite/rewriteDefine.c:607 #, c-format msgid "SELECT target entry has type %s, but column has type %s." msgstr "SELECT 대상 엔트리 자료형은 %s 형이지만, 칼럼 자료형은 %s 형입니다." -#: rewrite/rewriteDefine.c:593 rewrite/rewriteDefine.c:618 +#: rewrite/rewriteDefine.c:586 rewrite/rewriteDefine.c:611 #, c-format msgid "RETURNING list entry has type %s, but column has type %s." msgstr "RETURNING 목록은 %s 자료형이지만, 칼럼 자료형은 %s 형입니다." -#: rewrite/rewriteDefine.c:609 +#: rewrite/rewriteDefine.c:602 #, c-format msgid "SELECT rule's target entry %d has different size from column \"%s\"" msgstr "SELECT 룰(rule)의 대상 엔트리 번호(%d)가 \"%s\" 칼럼 크기와 틀립니다" -#: rewrite/rewriteDefine.c:611 +#: rewrite/rewriteDefine.c:604 #, c-format msgid "RETURNING list's entry %d has different size from column \"%s\"" msgstr "RETURNING 목록의 %d번째 항목의 크기가 \"%s\" 칼럼 크기와 틀립니다" -#: rewrite/rewriteDefine.c:628 +#: rewrite/rewriteDefine.c:621 #, c-format msgid "SELECT rule's target list has too few entries" msgstr "SELECT 룰(rule)의 대상 목록이 너무 적은 엔트리를 가지고 있습니다" -#: rewrite/rewriteDefine.c:629 +#: rewrite/rewriteDefine.c:622 #, c-format msgid "RETURNING list has too few entries" msgstr "RETURNING 목록에 너무 적은 항목이 있습니다" -#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:833 -#: rewrite/rewriteSupport.c:109 +#: rewrite/rewriteDefine.c:711 rewrite/rewriteDefine.c:826 +#: rewrite/rewriteSupport.c:108 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist" msgstr " \"%s\" 룰(rule)이 \"%s\" 관계(relation)에 지정된 것이 없음" -#: rewrite/rewriteDefine.c:852 +#: rewrite/rewriteDefine.c:845 #, c-format msgid "renaming an ON SELECT rule is not allowed" msgstr "ON SELECT 룰의 이름 바꾸기는 허용하지 않습니다" -#: rewrite/rewriteHandler.c:583 +#: rewrite/rewriteHandler.c:588 #, c-format msgid "" "WITH query name \"%s\" appears in both a rule action and the query being " "rewritten" msgstr "\"%s\" 이름의 WITH 쿼리가 룰 동작과 쿼리 재작성 두 곳 모두에 보입니다." -#: rewrite/rewriteHandler.c:610 +#: rewrite/rewriteHandler.c:615 #, c-format msgid "" "INSERT ... SELECT rule actions are not supported for queries having data-" @@ -22829,107 +23656,117 @@ msgid "" msgstr "" "INSERT...SELECT 룰 액션에는 WITH 절 안에 자료 변경 구문을 지원하지 않습니다." -#: rewrite/rewriteHandler.c:663 +#: rewrite/rewriteHandler.c:668 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "multiple rule에 RETURNING 목록을 지정할 수 없습니다" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:934 +#: rewrite/rewriteHandler.c:900 rewrite/rewriteHandler.c:939 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "\"%s\" 칼럼에 non-DEFAULT 값을 입력할 수 없습니다" -#: rewrite/rewriteHandler.c:897 rewrite/rewriteHandler.c:963 +#: rewrite/rewriteHandler.c:902 rewrite/rewriteHandler.c:968 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "\"%s\" 칼럼은 GENERATED ALWAYS 속성의 식별자 칼럼입니다." -#: rewrite/rewriteHandler.c:899 +#: rewrite/rewriteHandler.c:904 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "이 속성을 무시하려면, OVERRIDING SYSTEM VALUE 옵션을 사용하세요." -#: rewrite/rewriteHandler.c:961 rewrite/rewriteHandler.c:969 +#: rewrite/rewriteHandler.c:966 rewrite/rewriteHandler.c:974 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "\"%s\" 칼럼은 DEFAULT 로만 업데이트 가능합니다" -#: rewrite/rewriteHandler.c:1116 rewrite/rewriteHandler.c:1134 +#: rewrite/rewriteHandler.c:1121 rewrite/rewriteHandler.c:1139 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "같은 \"%s\" 열에 지정값(assignment)이 중복되었습니다" -#: rewrite/rewriteHandler.c:2119 rewrite/rewriteHandler.c:4040 +#: rewrite/rewriteHandler.c:1704 +#, c-format +msgid "MERGE is not supported for relations with rules." +msgstr "MERGE 명령은 룰을 사용하는 릴레이션에서 사용할 수 없습니다." + +#: rewrite/rewriteHandler.c:1744 rewrite/rewriteHandler.c:3284 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "\"%s\"는 non-system 뷰로 접근이 제한됨" + +#: rewrite/rewriteHandler.c:2144 rewrite/rewriteHandler.c:4276 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "" "\"%s\" 릴레이션(relation)에서 지정된 룰에서 잘못된 재귀호출이 발견되었습니다" -#: rewrite/rewriteHandler.c:2204 +#: rewrite/rewriteHandler.c:2249 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "\"%s\" 릴레이션의 정책에서 무한 재귀 호출이 발견 됨" -#: rewrite/rewriteHandler.c:2524 +#: rewrite/rewriteHandler.c:2611 msgid "Junk view columns are not updatable." msgstr "정크 뷰 칼럼은 업데이트할 수 없습니다." -#: rewrite/rewriteHandler.c:2529 +#: rewrite/rewriteHandler.c:2616 msgid "" "View columns that are not columns of their base relation are not updatable." msgstr "" "뷰의 바탕이 되는 릴레이션의 칼럼이 아닌 뷰 칼럼은 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2532 +#: rewrite/rewriteHandler.c:2619 msgid "View columns that refer to system columns are not updatable." msgstr "시스템 칼럼이 원본인 뷰 칼럼은 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2535 +#: rewrite/rewriteHandler.c:2622 msgid "View columns that return whole-row references are not updatable." msgstr "로우 전체를 참조하는 뷰 칼럼은 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2596 +#: rewrite/rewriteHandler.c:2683 msgid "Views containing DISTINCT are not automatically updatable." msgstr "DISTINCT 조건이 있는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2599 +#: rewrite/rewriteHandler.c:2686 msgid "Views containing GROUP BY are not automatically updatable." msgstr "GROUP BY 절이 있는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2602 +#: rewrite/rewriteHandler.c:2689 msgid "Views containing HAVING are not automatically updatable." msgstr "HAVING 절이 있는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2605 +#: rewrite/rewriteHandler.c:2692 msgid "" "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "" "UNION, INTERSECT, EXCEPT를 포함하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2608 +#: rewrite/rewriteHandler.c:2695 msgid "Views containing WITH are not automatically updatable." msgstr "WITH 절을 포함하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2611 +#: rewrite/rewriteHandler.c:2698 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "" "LIMIT 또는 OFFSET 구문을 포함하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2623 +#: rewrite/rewriteHandler.c:2710 msgid "Views that return aggregate functions are not automatically updatable." msgstr "집계 함수를 반환하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2626 +#: rewrite/rewriteHandler.c:2713 msgid "Views that return window functions are not automatically updatable." msgstr "윈도우 함수를 반환하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2629 +#: rewrite/rewriteHandler.c:2716 msgid "" "Views that return set-returning functions are not automatically updatable." msgstr "집합 반환 함수를 반환하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2636 rewrite/rewriteHandler.c:2640 -#: rewrite/rewriteHandler.c:2648 +#: rewrite/rewriteHandler.c:2723 rewrite/rewriteHandler.c:2727 +#: rewrite/rewriteHandler.c:2735 msgid "" "Views that do not select from a single table or view are not automatically " "updatable." @@ -22937,32 +23774,122 @@ msgstr "" "단일 테이블 또는 단일 뷰를 SELECT 하지 않는 뷰는 자동으로 업데이트 될 수 없습" "니다." -#: rewrite/rewriteHandler.c:2651 +#: rewrite/rewriteHandler.c:2738 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "TABLESAMPLE 구문을 포함하는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:2675 +#: rewrite/rewriteHandler.c:2762 msgid "Views that have no updatable columns are not automatically updatable." msgstr "업데이트 가능한 칼럼이 없는 뷰는 자동으로 업데이트 될 수 없습니다." -#: rewrite/rewriteHandler.c:3155 +#: rewrite/rewriteHandler.c:3143 rewrite/rewriteHandler.c:3178 +#, c-format +msgid "cannot insert into view \"%s\"" +msgstr "\"%s\" 뷰에 자료를 입력할 수 없습니다" + +#: rewrite/rewriteHandler.c:3146 +#, c-format +msgid "" +"To enable inserting into the view, provide an INSTEAD OF INSERT trigger or " +"an unconditional ON INSERT DO INSTEAD rule." +msgstr "" +"뷰를 통해 자료를 입력하려면, INSTEAD OF INSERT 트리거나 ON INSERT DO INSTEAD " +"룰을 사용하세요" + +#: rewrite/rewriteHandler.c:3151 rewrite/rewriteHandler.c:3187 +#, c-format +msgid "cannot update view \"%s\"" +msgstr "\"%s\" 뷰로는 자료를 갱신할 수 없습니다" + +#: rewrite/rewriteHandler.c:3154 +#, c-format +msgid "" +"To enable updating the view, provide an INSTEAD OF UPDATE trigger or an " +"unconditional ON UPDATE DO INSTEAD rule." +msgstr "" +"뷰 자료 갱신 기능은 INSTEAD OF UPDATE 트리거를 사용하거나, ON UPDATE DO " +"INSTEAD 속성으로 룰을 만들어서 사용해 보세요." + +#: rewrite/rewriteHandler.c:3159 rewrite/rewriteHandler.c:3196 +#, c-format +msgid "cannot delete from view \"%s\"" +msgstr "\"%s\" 뷰로는 자료를 삭제할 수 없습니다" + +#: rewrite/rewriteHandler.c:3162 +#, c-format +msgid "" +"To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an " +"unconditional ON DELETE DO INSTEAD rule." +msgstr "" +"뷰 자료 삭제 기능은 INSTEAD OF DELETE 트리거를 사용하거나, ON DELETE DO " +"INSTEAD 속성으로 룰을 만들어서 사용해 보세요." + +#: rewrite/rewriteHandler.c:3181 +#, c-format +msgid "" +"To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT " +"trigger." +msgstr "뷰를 통해 자료를 입력하려면, MERGE나 INSTEAD OF INSERT 트리거를 사용하세요" + +#: rewrite/rewriteHandler.c:3190 +#, c-format +msgid "" +"To enable updating the view using MERGE, provide an INSTEAD OF UPDATE " +"trigger." +msgstr "뷰를 통해 자료를 변경하려면, MERGE나 INSTEAD OF INSERT 트리거를 사용하세요" + +#: rewrite/rewriteHandler.c:3199 +#, c-format +msgid "" +"To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE " +"trigger." +msgstr "뷰를 통해 자료를 삭제하려면, MERGE나 INSTEAD OF INSERT 트리거를 사용하세요" + +#: rewrite/rewriteHandler.c:3374 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "\"%s\" 칼럼 (해당 뷰: \"%s\")에 자료를 입력할 수 없습니다" -#: rewrite/rewriteHandler.c:3163 +#: rewrite/rewriteHandler.c:3382 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "\"%s\" 칼럼 (해당 뷰: \"%s\")에 자료를 갱신할 수 없습니다" -#: rewrite/rewriteHandler.c:3667 +#: rewrite/rewriteHandler.c:3390 +#, c-format +msgid "cannot merge into column \"%s\" of view \"%s\"" +msgstr "\"%s\" 칼럼 (해당 뷰: \"%s\")에 병합할 수 없음" + +#: rewrite/rewriteHandler.c:3418 +#, c-format +msgid "cannot merge into view \"%s\"" +msgstr "\"%s\" 뷰에 병합할 수 없음" + +#: rewrite/rewriteHandler.c:3420 +#, c-format +msgid "" +"MERGE is not supported for views with INSTEAD OF triggers for some actions " +"but not all." +msgstr "" +"MERGE 명령은 몇몇 action용 INSTEAD OF 트리거가 있는 뷰를 지원하지 않음" + +#: rewrite/rewriteHandler.c:3421 +#, c-format +msgid "" +"To enable merging into the view, either provide a full set of INSTEAD OF " +"triggers or drop the existing INSTEAD OF triggers." +msgstr "" +"뷰에 병합을 활성화하려면 INSTEAD OF 트리거의 전체 세트를 제공하거나 " +"기존 INSTEAD OF 트리거를 삭제하세요" + +#: rewrite/rewriteHandler.c:3934 #, c-format msgid "" "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in " "WITH" msgstr "DO INSTEAD NOTIFY 룰에서는 WITH 절 안에 자료 변경 구문이 없어야 합니다" -#: rewrite/rewriteHandler.c:3678 +#: rewrite/rewriteHandler.c:3945 #, c-format msgid "" "DO INSTEAD NOTHING rules are not supported for data-modifying statements in " @@ -22970,19 +23897,19 @@ msgid "" msgstr "" "DO INSTEAD NOTHING 룰에서는 WITH 절 안에 자료 변경 구문이 없어야 합니다" -#: rewrite/rewriteHandler.c:3692 +#: rewrite/rewriteHandler.c:3959 #, c-format msgid "" "conditional DO INSTEAD rules are not supported for data-modifying statements " "in WITH" msgstr "선택적 DO INSTEAD 룰에서는 WITH 절 안에 자료 변경 구문이 없어야 합니다" -#: rewrite/rewriteHandler.c:3696 +#: rewrite/rewriteHandler.c:3963 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "DO ALSO 룰에서는 WITH 절 안에 자료 변경 구문이 없어야 합니다" -#: rewrite/rewriteHandler.c:3701 +#: rewrite/rewriteHandler.c:3968 #, c-format msgid "" "multi-statement DO INSTEAD rules are not supported for data-modifying " @@ -22991,20 +23918,18 @@ msgstr "" "여러 구문으로 구성된 DO INSTEAD 룰에서는 WITH 절 안에 자료 변경 구문이 없어" "야 합니다" -#: rewrite/rewriteHandler.c:3968 rewrite/rewriteHandler.c:3976 -#: rewrite/rewriteHandler.c:3984 -#, c-format +#: rewrite/rewriteHandler.c:4228 msgid "" "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "" "선택적 DO INSTEAD 룰을 포함한 뷰는 자동 업데이트 기능을 사용할 수 없습니다." -#: rewrite/rewriteHandler.c:4089 +#: rewrite/rewriteHandler.c:4325 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "\"%s\" 릴레이션에서 INSERT RETURNING 관련을 구성할 수 없음" -#: rewrite/rewriteHandler.c:4091 +#: rewrite/rewriteHandler.c:4327 #, c-format msgid "" "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." @@ -23012,12 +23937,12 @@ msgstr "" "RETURNING 절에서는 무조건 ON INSERT DO INSTEAD 속성으로 rule이 사용되어야 합" "니다." -#: rewrite/rewriteHandler.c:4096 +#: rewrite/rewriteHandler.c:4332 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "\"%s\" 릴레이션에서 UPDATE RETURNING 관련을 구성할 수 없습니다." -#: rewrite/rewriteHandler.c:4098 +#: rewrite/rewriteHandler.c:4334 #, c-format msgid "" "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." @@ -23025,12 +23950,12 @@ msgstr "" "RETURNING 절에서는 무조건 ON UPDATE DO INSTEAD 속성으로 rule이 사용되어야 합" "니다." -#: rewrite/rewriteHandler.c:4103 +#: rewrite/rewriteHandler.c:4339 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "\"%s\" 릴레이션에서 DELETE RETURNING 관련을 구성할 수 없습니다." -#: rewrite/rewriteHandler.c:4105 +#: rewrite/rewriteHandler.c:4341 #, c-format msgid "" "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." @@ -23038,7 +23963,7 @@ msgstr "" "TURNING 절에서는 무조건 ON DELETE DO INSTEAD 속성으로 rule이 사용되어야 합니" "다" -#: rewrite/rewriteHandler.c:4123 +#: rewrite/rewriteHandler.c:4359 #, c-format msgid "" "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or " @@ -23047,7 +23972,7 @@ msgstr "" "INSERT 또는 UPDATE 룰이 지정된 테이블을 대상으로 INSERT ... ON CONFLICT 구문" "은 사용할 수 없습니다." -#: rewrite/rewriteHandler.c:4180 +#: rewrite/rewriteHandler.c:4416 #, c-format msgid "" "WITH cannot be used in a query that is rewritten by rules into multiple " @@ -23056,19 +23981,19 @@ msgstr "" "WITH 절은 다중 쿼리 작업을 하는 룰로 재작성되는 쿼리 안에서는 사용할 수 없습" "니다." -#: rewrite/rewriteManip.c:1075 +#: rewrite/rewriteManip.c:1083 #, c-format msgid "conditional utility statements are not implemented" msgstr "" "조건 유틸리티 명령 구문(conditional utility statement)은 구현되어있지 않습니" "다" -#: rewrite/rewriteManip.c:1419 +#: rewrite/rewriteManip.c:1430 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "뷰에 대한 WHERE CURRENT OF 구문이 구현되지 않음" -#: rewrite/rewriteManip.c:1754 +#: rewrite/rewriteManip.c:1765 #, c-format msgid "" "NEW variables in ON UPDATE rules cannot reference columns that are part of a " @@ -23112,84 +24037,79 @@ msgstr "인식할 수 없는 Snowball 매개 변수: \"%s\"" msgid "missing Language parameter" msgstr "Language 매개 변수가 누락됨" -#: statistics/extended_stats.c:179 +#: statistics/extended_stats.c:176 #, c-format msgid "" "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "\"%s.%s\" 통계정보 개체를 계산 할 수 없음: 대상 릴레이션: \"%s.%s\"" -#: statistics/mcv.c:1372 +#: statistics/mcv.c:1368 #, c-format msgid "" "function returning record called in context that cannot accept type record" msgstr "반환 자료형이 record인데 함수가 그 자료형으로 반환하지 않음" -#: storage/buffer/bufmgr.c:612 storage/buffer/bufmgr.c:769 +#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 #, c-format msgid "cannot access temporary tables of other sessions" msgstr "다른 세션의 임시 테이블에 액세스할 수 없음" -#: storage/buffer/bufmgr.c:1137 +#: storage/buffer/bufmgr.c:1532 #, c-format msgid "invalid page in block %u of relation %s; zeroing out page" msgstr "" "%u 블록(해당 릴레이션: %s)에 잘못된 페이지 헤더가 있음, 페이지를 삭제하는 중" -#: storage/buffer/bufmgr.c:1931 storage/buffer/localbuf.c:359 +#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "%s 릴레이션은 %u개 블록을 초과하여 확장할 수 없음" -#: storage/buffer/bufmgr.c:1998 +#: storage/buffer/bufmgr.c:2348 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "%u 블록(해당 릴레이션: %s)에 EOF 범위를 넘는 예기치 않은 데이터가 있음" -#: storage/buffer/bufmgr.c:2000 +#: storage/buffer/bufmgr.c:2350 #, c-format msgid "" "This has been seen to occur with buggy kernels; consider updating your " "system." msgstr "이 문제는 커널의 문제로 알려졌습니다. 시스템을 업데이트하십시오." -#: storage/buffer/bufmgr.c:5219 +#: storage/buffer/bufmgr.c:5653 #, c-format msgid "could not write block %u of %s" msgstr "%u/%s 블록을 쓸 수 없음" -#: storage/buffer/bufmgr.c:5221 +#: storage/buffer/bufmgr.c:5655 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "여러 번 실패 --- 쓰기 오류가 영구적일 수 있습니다." -#: storage/buffer/bufmgr.c:5243 storage/buffer/bufmgr.c:5263 +#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 #, c-format msgid "writing block %u of relation %s" msgstr "%u 블록(해당 릴레이션: %s)을 쓰는 중" -#: storage/buffer/bufmgr.c:5593 -#, c-format -msgid "snapshot too old" -msgstr "스냅샷 너무 오래됨" - -#: storage/buffer/localbuf.c:219 +#: storage/buffer/localbuf.c:220 #, c-format msgid "no empty local buffer available" msgstr "비어 있는 로컬 버퍼가 없습니다" -#: storage/buffer/localbuf.c:592 +#: storage/buffer/localbuf.c:597 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "병렬 작업 중에 임시 테이블에 액세스할 수 없음" -#: storage/buffer/localbuf.c:699 +#: storage/buffer/localbuf.c:712 #, c-format msgid "" "\"temp_buffers\" cannot be changed after any temporary tables have been " "accessed in the session." msgstr "" "해당 세션에서 어떤 임시 테이블도 사용하고 있지 않아야 \"temp_buffers\" 설정" -"을 변경할 수 있습니다." +"을 바꿀 수 있습니다." #: storage/file/buffile.c:338 #, c-format @@ -23206,43 +24126,43 @@ msgstr "\"%s\" 파일 세트를 읽을 수 없음: %zu 바이트만 읽음 (전 msgid "could not read from temporary file: read only %zu of %zu bytes" msgstr "임시 파일을 읽을 수 없음: %zu 바이트만 읽음 (전체: %zu)" -#: storage/file/buffile.c:774 storage/file/buffile.c:895 +#: storage/file/buffile.c:774 storage/file/buffile.c:877 #, c-format msgid "" "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" msgstr "\"%s\" 임시 파일의 크기를 알 수 없음, 버퍼파일: \"%s\": %m" -#: storage/file/buffile.c:974 +#: storage/file/buffile.c:956 #, c-format msgid "could not delete fileset \"%s\": %m" msgstr "\"%s\" 파일 세트를 지울 수 없음: %m" -#: storage/file/buffile.c:992 storage/smgr/md.c:338 storage/smgr/md.c:1041 +#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1194 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "\"%s\" 파일을 비울 수 없음: %m" -#: storage/file/fd.c:537 storage/file/fd.c:609 storage/file/fd.c:645 +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" msgstr "dirty 자료를 flush 할 수 없음: %m" -#: storage/file/fd.c:567 +#: storage/file/fd.c:613 #, c-format msgid "could not determine dirty data size: %m" msgstr "dirty 자료 크기를 확인할 수 없음: %m" -#: storage/file/fd.c:619 +#: storage/file/fd.c:665 #, c-format msgid "could not munmap() while flushing data: %m" msgstr "자료 flush 작업 도중 munmap() 호출 실패: %m" -#: storage/file/fd.c:937 +#: storage/file/fd.c:983 #, c-format msgid "getrlimit failed: %m" msgstr "getrlimit 실패: %m" -#: storage/file/fd.c:1027 +#: storage/file/fd.c:1073 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "" @@ -23250,91 +24170,86 @@ msgstr "" "그램에서 너무 많은 파일을 열어 두고 있습니다. 다른 프로그램들을 좀 닫고 다시 " "시도해 보십시오" -#: storage/file/fd.c:1028 +#: storage/file/fd.c:1074 #, c-format msgid "System allows %d, server needs at least %d." msgstr "시스템 허용치 %d, 서버 최소 허용치 %d." -#: storage/file/fd.c:1116 storage/file/fd.c:2565 storage/file/fd.c:2674 -#: storage/file/fd.c:2825 +#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 +#: storage/file/fd.c:2878 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "" "열려 있는 파일이 너무 많습니다: %m; 다른 프로그램들을 좀 닫고 다시 시도해 보" "십시오" -#: storage/file/fd.c:1490 +#: storage/file/fd.c:1536 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "임시 파일: 경로 \"%s\", 크기 %lu" -#: storage/file/fd.c:1629 +#: storage/file/fd.c:1675 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "\"%s\" 임시 디렉터리를 만들 수 없음: %m" -#: storage/file/fd.c:1636 +#: storage/file/fd.c:1682 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "\"%s\" 임시 하위 디렉터리를 만들 수 없음: %m" -#: storage/file/fd.c:1833 +#: storage/file/fd.c:1879 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "\"%s\" 임시 파일을 만들 수 없습니다: %m" -#: storage/file/fd.c:1869 +#: storage/file/fd.c:1915 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "\"%s\" 임시 파일을 열 수 없음: %m" -#: storage/file/fd.c:1910 +#: storage/file/fd.c:1956 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "\"%s\" 임시 파일을 지울 수 없음: %m" -#: storage/file/fd.c:1998 +#: storage/file/fd.c:2044 #, c-format msgid "could not delete file \"%s\": %m" msgstr "\"%s\" 파일을 지울 수 없음: %m" -#: storage/file/fd.c:2185 +#: storage/file/fd.c:2234 #, c-format msgid "temporary file size exceeds temp_file_limit (%dkB)" msgstr "임시 파일 크기가 temp_file_limit (%dkB)를 초과했습니다" -#: storage/file/fd.c:2541 storage/file/fd.c:2600 +#: storage/file/fd.c:2594 storage/file/fd.c:2653 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "maxAllocatedDescs (%d) 초과됨, \"%s\" 파일 열기 시도 중에." -#: storage/file/fd.c:2645 +#: storage/file/fd.c:2698 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "maxAllocatedDescs (%d) 초과됨, \"%s\" 명령을 시도 중에." -#: storage/file/fd.c:2801 +#: storage/file/fd.c:2854 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "maxAllocatedDescs (%d) 초과됨, \"%s\" 디렉터리 열기 시도 중에." -#: storage/file/fd.c:3331 +#: storage/file/fd.c:3384 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "임시 디렉터리에서 예상치 못한 파일 발견: \"%s\"" -#: storage/file/fd.c:3449 +#: storage/file/fd.c:3502 #, c-format msgid "" "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "데이터 디렉터리 동기화(syncfs), 소요 시간: %ld.%02d s, 현재 경로: %s" -#: storage/file/fd.c:3463 -#, c-format -msgid "could not synchronize file system for file \"%s\": %m" -msgstr "\"%s\" 파일 대상으로 파일 시스템 동기화를 할 수 없습니다: %m" - -#: storage/file/fd.c:3676 +#: storage/file/fd.c:3729 #, c-format msgid "" "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: " @@ -23342,29 +24257,40 @@ msgid "" msgstr "" "데이터 디렉터리 동기화(pre-fsync), 소요 시간: %ld.%02d s, 현재 경로: %s" -#: storage/file/fd.c:3708 +#: storage/file/fd.c:3761 #, c-format msgid "" "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "데이터 디렉터리 동기화(fsync), 소요 시간: %ld.%02d s, 현재 경로: %s" -#: storage/file/fd.c:3897 +#: storage/file/fd.c:3950 +#, c-format +msgid "\"debug_io_direct\" is not supported on this platform." +msgstr "\"debug_io_direct\" 설정은 이 플랫폼에서 지원되지 않음" + +#: storage/file/fd.c:3964 +#, c-format +msgid "Invalid list syntax in parameter \"%s\"" +msgstr "\"%s\" 매개 변수의 값으로 목록 문법이 잘못됨" + +#: storage/file/fd.c:3984 #, c-format -msgid "debug_io_direct is not supported on this platform." -msgstr "debug_io_direct 설정은 이 플랫폼에서 지원되지 않음" +msgid "Invalid option \"%s\"" +msgstr "\"%s\" 옵션이 잘못됨" -#: storage/file/fd.c:3944 +#: storage/file/fd.c:3997 #, c-format msgid "" -"debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small" +"\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" msgstr "" -"XLOG_BLCKSZ 값이 너무 작은 WAL을 사용하고 있어 debug_io_direct 기능을 지원하" +"XLOG_BLCKSZ 값이 너무 작은 WAL을 사용하고 있어 \"debug_io_direct\" 기능을 지원하" "지 않습니다." -#: storage/file/fd.c:3951 +#: storage/file/fd.c:4004 #, c-format -msgid "debug_io_direct is not supported for data because BLCKSZ is too small" -msgstr "BLCKSZ 값이 너무 작아 debug_io_direct 기능을 지원하지 않습니다." +msgid "" +"\"debug_io_direct\" is not supported for data because BLCKSZ is too small" +msgstr "BLCKSZ 값이 너무 작아 \"debug_io_direct\" 기능을 지원하지 않습니다." #: storage/file/reinit.c:145 #, c-format @@ -23382,22 +24308,22 @@ msgid "" msgstr "" "로그 안남기는 릴레이션 재설정 (cleanup), 소요 시간: %ld.%02d s, 현재 경로: %s" -#: storage/file/sharedfileset.c:79 +#: storage/file/sharedfileset.c:73 #, c-format msgid "could not attach to a SharedFileSet that is already destroyed" msgstr "SharedFileSet 확보 실패, 이미 삭제되었음" -#: storage/ipc/dsm.c:352 +#: storage/ipc/dsm.c:379 #, c-format msgid "dynamic shared memory control segment is corrupt" msgstr "동적 공유 메모리 제어 조각이 손상되었음" -#: storage/ipc/dsm.c:417 +#: storage/ipc/dsm.c:444 #, c-format msgid "dynamic shared memory control segment is not valid" msgstr "동적 공유 메모리 제어 조각이 타당하지 않음" -#: storage/ipc/dsm.c:599 +#: storage/ipc/dsm.c:626 #, c-format msgid "too many dynamic shared memory segments" msgstr "너무 많은 동적 공유 메모리 조각이 있음" @@ -23457,18 +24383,44 @@ msgstr "\"%s\" 공유 메모리 조각을 닫을 수 없음: %m" msgid "could not duplicate handle for \"%s\": %m" msgstr "\"%s\" 용 헨들러를 이중화 할 수 없음: %m" -#: storage/ipc/procarray.c:3796 +#: storage/ipc/dsm_registry.c:142 +#, c-format +msgid "DSM segment name cannot be empty" +msgstr "DSM 조각 이름은 비워둘 수 없음" + +#: storage/ipc/dsm_registry.c:146 +#, c-format +msgid "DSM segment name too long" +msgstr "DSM 조각 이름이 너무 긺" + +#: storage/ipc/dsm_registry.c:150 +#, c-format +msgid "DSM segment size must be nonzero" +msgstr "DSM 조각 크기는 0이 아니여야 함" + +#: storage/ipc/dsm_registry.c:176 +#, c-format +msgid "requested DSM segment size does not match size of existing segment" +msgstr "요청된 DSM 조각 크기는 기존 조각 크기와 맞지 않음" + +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:357 +#: tcop/backend_startup.c:304 +#, c-format +msgid "sorry, too many clients already" +msgstr "최대 동시 접속자 수를 초과했습니다." + +#: storage/ipc/procarray.c:3857 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "\"%s\" 데이터베이스가 미리 준비된 트랜잭션에서 사용중임" -#: storage/ipc/procarray.c:3828 storage/ipc/procarray.c:3837 -#: storage/ipc/signalfuncs.c:230 storage/ipc/signalfuncs.c:237 +#: storage/ipc/procarray.c:3893 storage/ipc/procarray.c:3901 +#: storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 #, c-format msgid "permission denied to terminate process" msgstr "프로세스 종료 권한 없음" -#: storage/ipc/procarray.c:3829 storage/ipc/signalfuncs.c:231 +#: storage/ipc/procarray.c:3894 storage/ipc/signalfuncs.c:236 #, c-format msgid "" "Only roles with the %s attribute may terminate processes of roles with the " @@ -23476,50 +24428,50 @@ msgid "" msgstr "" "%s 속성이 있는 롤만이 %s 속성을 가진 롤이 실행한 쿼리를 중지 할 수 있습니다." -#: storage/ipc/procarray.c:3838 storage/ipc/signalfuncs.c:238 +#: storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:243 #, c-format msgid "" "Only roles with privileges of the role whose process is being terminated or " "with privileges of the \"%s\" role may terminate this process." msgstr "\"%s\" 롤 권한이 있는 롤만 프로세스를 종료할 수 있습니다." -#: storage/ipc/procsignal.c:420 +#: storage/ipc/procsignal.c:416 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "" "%d PID 백엔드 프로세스가 ProcSignalBarrier 작업을 수락하기를 기다리고 있음" -#: storage/ipc/shm_mq.c:384 +#: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" msgstr "공유 메모리 큐를 통해 %zu 크기의 메시지를 보낼 수 없음" -#: storage/ipc/shm_mq.c:719 +#: storage/ipc/shm_mq.c:718 #, c-format msgid "invalid message size %zu in shared memory queue" msgstr "동적 공유 메모리 큐에 메시지 길이(%zu)가 잘못됨" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:963 -#: storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2786 storage/lmgr/lock.c:4171 -#: storage/lmgr/lock.c:4236 storage/lmgr/lock.c:4586 -#: storage/lmgr/predicate.c:2412 storage/lmgr/predicate.c:2427 -#: storage/lmgr/predicate.c:3824 storage/lmgr/predicate.c:4871 -#: utils/hash/dynahash.c:1107 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:984 +#: storage/lmgr/lock.c:1022 storage/lmgr/lock.c:2835 storage/lmgr/lock.c:4220 +#: storage/lmgr/lock.c:4285 storage/lmgr/lock.c:4635 +#: storage/lmgr/predicate.c:2468 storage/lmgr/predicate.c:2483 +#: storage/lmgr/predicate.c:3880 storage/lmgr/predicate.c:4927 +#: utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "공유 메모리 부족" -#: storage/ipc/shmem.c:170 storage/ipc/shmem.c:266 +#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "공유 메모리가 부족함 (%zu 바이트가 필요함)" -#: storage/ipc/shmem.c:445 +#: storage/ipc/shmem.c:436 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "\"%s\" 자료 구조체용 ShmemIndex 항목을 만들 수 없음" -#: storage/ipc/shmem.c:460 +#: storage/ipc/shmem.c:451 #, c-format msgid "" "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, " @@ -23527,13 +24479,13 @@ msgid "" msgstr "" "\"%s\" 자료 구조체용 ShmemIndex 항목 크기가 잘못됨: 기대값 %zu, 현재값 %zu" -#: storage/ipc/shmem.c:479 +#: storage/ipc/shmem.c:470 #, c-format msgid "" "not enough shared memory for data structure \"%s\" (%zu bytes requested)" msgstr "\"%s\" 자료 구조체용 공유 메모리가 부족함 (%zu 바이트가 필요함)" -#: storage/ipc/shmem.c:511 storage/ipc/shmem.c:530 +#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 #, c-format msgid "requested shared memory size overflows size_t" msgstr "지정한 공유 메모리 사이즈가 size_t 크기를 초과했습니다" @@ -23543,18 +24495,18 @@ msgstr "지정한 공유 메모리 사이즈가 size_t 크기를 초과했습니 msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %d 프로그램은 PostgreSQL 백엔드 프로세스가 아닙니다" -#: storage/ipc/signalfuncs.c:104 storage/lmgr/proc.c:1379 -#: utils/adt/mcxtfuncs.c:190 +#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1453 +#: utils/adt/mcxtfuncs.c:182 #, c-format msgid "could not send signal to process %d: %m" msgstr "%d 프로세스로 시스템신호(signal)를 보낼 수 없습니다: %m" -#: storage/ipc/signalfuncs.c:124 storage/ipc/signalfuncs.c:131 +#: storage/ipc/signalfuncs.c:129 storage/ipc/signalfuncs.c:136 #, c-format msgid "permission denied to cancel query" msgstr "쿼리 중지 권한 없음" -#: storage/ipc/signalfuncs.c:125 +#: storage/ipc/signalfuncs.c:130 #, c-format msgid "" "Only roles with the %s attribute may cancel queries of roles with the %s " @@ -23562,115 +24514,111 @@ msgid "" msgstr "" "%s 속성이 있는 롤만이 %s 속성이 있는 롤이 실행한 쿼리를 중지 할 수 있습니다." -#: storage/ipc/signalfuncs.c:132 +#: storage/ipc/signalfuncs.c:137 #, c-format msgid "" "Only roles with privileges of the role whose query is being canceled or with " "privileges of the \"%s\" role may cancel this query." msgstr "쿼리 실행 중지 작업은 \"%s\" 롤 권한이 부여된 롤만 할 수 있습니다." -#: storage/ipc/signalfuncs.c:174 +#: storage/ipc/signalfuncs.c:179 #, c-format msgid "could not check the existence of the backend with PID %d: %m" msgstr "%d PID 백엔드 프로세스의 존재를 확인할 수 없음: %m" -#: storage/ipc/signalfuncs.c:192 +#: storage/ipc/signalfuncs.c:197 #, c-format msgid "backend with PID %d did not terminate within %lld millisecond" msgid_plural "backend with PID %d did not terminate within %lld milliseconds" msgstr[0] "%d PID 백엔드 프로세스를 %lld ms 내에 종료하지 못했음" -#: storage/ipc/signalfuncs.c:223 +#: storage/ipc/signalfuncs.c:228 #, c-format msgid "\"timeout\" must not be negative" msgstr "\"timeout\" 값은 음수가 아니어야 함" -#: storage/ipc/signalfuncs.c:279 -#, c-format -msgid "must be superuser to rotate log files with adminpack 1.0" -msgstr "adminpack 1.0 확장 모듈로 로그 전환하려면 슈퍼유저여야 합니다." - -#. translator: %s is a SQL function name -#: storage/ipc/signalfuncs.c:281 utils/adt/genfile.c:250 -#, c-format -msgid "Consider using %s, which is part of core, instead." -msgstr "대신에 %s 내장 함수를 사용할 것을 권고합니다." - -#: storage/ipc/signalfuncs.c:287 storage/ipc/signalfuncs.c:307 +#: storage/ipc/signalfuncs.c:285 #, c-format msgid "rotation not possible because log collection not active" msgstr "로그 수집이 활성 상태가 아니므로 회전할 수 없음" -#: storage/ipc/standby.c:330 +#: storage/ipc/standby.c:329 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "%ld.%03d ms 기다린 뒤에도 여전히 복구 중: %s" -#: storage/ipc/standby.c:339 +#: storage/ipc/standby.c:338 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "%ld.%03d ms 기다려서 복구 완료: %s" -#: storage/ipc/standby.c:921 tcop/postgres.c:3384 +#: storage/ipc/standby.c:920 tcop/postgres.c:3196 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "복구 작업 중 충돌이 발생해 작업을 중지합니다." -#: storage/ipc/standby.c:922 tcop/postgres.c:2533 +#: storage/ipc/standby.c:921 tcop/postgres.c:2557 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "복구 작업 중 사용자 트랜잭션이 버퍼 데드락을 만들었습니다." -#: storage/ipc/standby.c:1488 +#: storage/ipc/standby.c:1486 msgid "unknown reason" msgstr "알 수 없는 이유" -#: storage/ipc/standby.c:1493 +#: storage/ipc/standby.c:1491 msgid "recovery conflict on buffer pin" msgstr "버퍼 핀에서 복구 충돌" -#: storage/ipc/standby.c:1496 +#: storage/ipc/standby.c:1494 msgid "recovery conflict on lock" msgstr "잠금에서 복구 충돌" -#: storage/ipc/standby.c:1499 +#: storage/ipc/standby.c:1497 msgid "recovery conflict on tablespace" msgstr "테이블스페이스에서 복구 충돌" -#: storage/ipc/standby.c:1502 +#: storage/ipc/standby.c:1500 msgid "recovery conflict on snapshot" msgstr "스냅샷에서 복구 충돌" -#: storage/ipc/standby.c:1505 +#: storage/ipc/standby.c:1503 msgid "recovery conflict on replication slot" msgstr "복제 슬롯에서 복구 충돌" -#: storage/ipc/standby.c:1508 +#: storage/ipc/standby.c:1506 msgid "recovery conflict on buffer deadlock" msgstr "버퍼 데드락에서 복구 충돌" -#: storage/ipc/standby.c:1511 +#: storage/ipc/standby.c:1509 msgid "recovery conflict on database" msgstr "데이터베이스에서 복구 충돌" -#: storage/large_object/inv_api.c:191 +#: storage/large_object/inv_api.c:190 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "" "OID %u (해당 페이지 %d) 를 위한 pg_largeobject 항목의 %d 크기의 데이터 필드" "가 잘못되었음" -#: storage/large_object/inv_api.c:274 +#: storage/large_object/inv_api.c:272 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "대형 개체를 열기 위한 플래그가 잘못 됨: %d" -#: storage/large_object/inv_api.c:457 +#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 +#: storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 +#: storage/large_object/inv_api.c:807 +#, c-format +msgid "permission denied for large object %u" +msgstr "%u 대형 개체에 대한 접근 권한 없음" + +#: storage/large_object/inv_api.c:455 #, c-format msgid "invalid whence setting: %d" msgstr "잘못된 이동 위치: %d" -#: storage/large_object/inv_api.c:629 +#: storage/large_object/inv_api.c:627 #, c-format msgid "invalid large object write request size: %d" msgstr "유효하지 않은 대형 개체의 쓰기 요청된 크기: %d" @@ -23697,119 +24645,119 @@ msgstr "deadlock 발생했음" msgid "See server log for query details." msgstr "쿼리 상세 정보는 서버 로그를 참조하십시오." -#: storage/lmgr/lmgr.c:859 +#: storage/lmgr/lmgr.c:848 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 튜플(해당 릴레이션 \"%s\")을 갱신하는 중에 발생" -#: storage/lmgr/lmgr.c:862 +#: storage/lmgr/lmgr.c:851 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 튜플(해당 릴레이션 \"%s\")을 삭제하는 중에 발생" -#: storage/lmgr/lmgr.c:865 +#: storage/lmgr/lmgr.c:854 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 튜플을 \"%s\" 릴레이션에서 잠그는 중에 발생" -#: storage/lmgr/lmgr.c:868 +#: storage/lmgr/lmgr.c:857 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "%u,%u 업데이트된 버전 튜플(해당 릴레이션 \"%s\")을 잠그는 중에 발생" -#: storage/lmgr/lmgr.c:871 +#: storage/lmgr/lmgr.c:860 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 튜플 인덱스(해당 릴레이션 \"%s\")를 삽입하는 중에 발생" -#: storage/lmgr/lmgr.c:874 +#: storage/lmgr/lmgr.c:863 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 튜플(해당 릴레이션: \"%s\")의 고유성을 검사하는 중에 발생" -#: storage/lmgr/lmgr.c:877 +#: storage/lmgr/lmgr.c:866 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "%u,%u 갱신된 튜플(해당 릴레이션: \"%s\")을 재확인하는 중에 발생" -#: storage/lmgr/lmgr.c:880 +#: storage/lmgr/lmgr.c:869 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "" "%u,%u 튜플(해당 릴레이션: \"%s\")의 제외 제약 조건을 검사하는 중에 발생" -#: storage/lmgr/lmgr.c:1174 +#: storage/lmgr/lmgr.c:1239 #, c-format msgid "relation %u of database %u" msgstr "릴레이션 %u, 데이터베이스 %u" -#: storage/lmgr/lmgr.c:1180 +#: storage/lmgr/lmgr.c:1245 #, c-format msgid "extension of relation %u of database %u" msgstr "%u 관계(%u 데이터베이스) 확장" -#: storage/lmgr/lmgr.c:1186 +#: storage/lmgr/lmgr.c:1251 #, c-format msgid "pg_database.datfrozenxid of database %u" msgstr "데이터베이스 %u의 pg_database.datfrozenxid" -#: storage/lmgr/lmgr.c:1191 +#: storage/lmgr/lmgr.c:1256 #, c-format msgid "page %u of relation %u of database %u" msgstr "페이지 %u, 릴레이션 %u, 데이터베이스 %u" -#: storage/lmgr/lmgr.c:1198 +#: storage/lmgr/lmgr.c:1263 #, c-format msgid "tuple (%u,%u) of relation %u of database %u" msgstr "튜플 (%u,%u), 릴레이션 %u, 데이터베이스 %u" -#: storage/lmgr/lmgr.c:1206 +#: storage/lmgr/lmgr.c:1271 #, c-format msgid "transaction %u" msgstr "트랜잭션 %u" -#: storage/lmgr/lmgr.c:1211 +#: storage/lmgr/lmgr.c:1276 #, c-format msgid "virtual transaction %d/%u" msgstr "가상 트랜잭션 %d/%u" -#: storage/lmgr/lmgr.c:1217 +#: storage/lmgr/lmgr.c:1282 #, c-format msgid "speculative token %u of transaction %u" msgstr "%u 위험한 토큰, 대상 트랜잭션 %u" -#: storage/lmgr/lmgr.c:1223 +#: storage/lmgr/lmgr.c:1288 #, c-format msgid "object %u of class %u of database %u" msgstr "개체 %u, 클래스 %u, 데이터베이스 %u" -#: storage/lmgr/lmgr.c:1231 +#: storage/lmgr/lmgr.c:1296 #, c-format msgid "user lock [%u,%u,%u]" msgstr "user lock [%u,%u,%u]" -#: storage/lmgr/lmgr.c:1238 +#: storage/lmgr/lmgr.c:1303 #, c-format msgid "advisory lock [%u,%u,%u,%u]" msgstr "advisory lock [%u,%u,%u,%u]" -#: storage/lmgr/lmgr.c:1246 +#: storage/lmgr/lmgr.c:1311 #, c-format msgid "remote transaction %u of subscription %u of database %u" msgstr "원격 트랜잭션: %u, 해당 구독: %u, 해당 데이터베이스 %u" -#: storage/lmgr/lmgr.c:1253 +#: storage/lmgr/lmgr.c:1318 #, c-format msgid "unrecognized locktag type %d" msgstr "알 수 없는 locktag 형태 %d" -#: storage/lmgr/lock.c:791 +#: storage/lmgr/lock.c:812 #, c-format msgid "" "cannot acquire lock mode %s on database objects while recovery is in progress" msgstr "복구 작업 중 데이터베이스 객체 대상 %s 잠금 상태 취득 실패" -#: storage/lmgr/lock.c:793 +#: storage/lmgr/lock.c:814 #, c-format msgid "" "Only RowExclusiveLock or less can be acquired on database objects during " @@ -23818,7 +24766,7 @@ msgstr "" "복구 중에는 해당 객체를 RowExclusiveLock 또는 그 보다 낮은 수준의 잠금만 할 " "수 있습니다." -#: storage/lmgr/lock.c:3235 storage/lmgr/lock.c:3303 storage/lmgr/lock.c:3419 +#: storage/lmgr/lock.c:3284 storage/lmgr/lock.c:3352 storage/lmgr/lock.c:3468 #, c-format msgid "" "cannot PREPARE while holding both session-level and transaction-level locks " @@ -23827,19 +24775,19 @@ msgstr "" "세션 수준과 트랜잭션 수준, 이 두 수준의 잠금을 같은 객체 대상으로 할 경우 " "PREPARE 작업은 할 수 없습니다." -#: storage/lmgr/predicate.c:649 +#: storage/lmgr/predicate.c:653 #, c-format msgid "not enough elements in RWConflictPool to record a read/write conflict" msgstr "읽기/쓰기 충돌을 기록하기 위한 RWConflictPool 안에 충분한 요소가 없음" -#: storage/lmgr/predicate.c:650 storage/lmgr/predicate.c:675 +#: storage/lmgr/predicate.c:654 storage/lmgr/predicate.c:679 #, c-format msgid "" "You might need to run fewer transactions at a time or increase " -"max_connections." -msgstr "동시 발생하는 트랜잭션 수를 줄이든가, max_connections 값을 늘리세요." +"\"max_connections\"." +msgstr "동시 발생하는 트랜잭션 수를 줄이든가, \"max_connections\" 값을 늘리세요." -#: storage/lmgr/predicate.c:674 +#: storage/lmgr/predicate.c:678 #, c-format msgid "" "not enough elements in RWConflictPool to record a potential read/write " @@ -23848,13 +24796,13 @@ msgstr "" "필수적인 읽기/쓰기 충돌을 기록하기 위한 RWConflictPool 안에 충분한 요소가 없" "음" -#: storage/lmgr/predicate.c:1630 +#: storage/lmgr/predicate.c:1686 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "" "\"default_transaction_isolation\" 설정값이 \"serializable\"로 지정되었습니다." -#: storage/lmgr/predicate.c:1631 +#: storage/lmgr/predicate.c:1687 #, c-format msgid "" "You can use \"SET default_transaction_isolation = 'repeatable read'\" to " @@ -23863,50 +24811,50 @@ msgstr "" "이 기본값은 \"SET default_transaction_isolation = 'repeatable read'\" 명령으" "로 바꿀 수 있습니다." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1738 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "" "스냅샷 가져오기 트랜잭션은 READ ONLY DEFERRABLE 속성이 아니여야 합니다." -#: storage/lmgr/predicate.c:1761 utils/time/snapmgr.c:570 -#: utils/time/snapmgr.c:576 +#: storage/lmgr/predicate.c:1817 utils/time/snapmgr.c:535 +#: utils/time/snapmgr.c:541 #, c-format msgid "could not import the requested snapshot" msgstr "요청한 스냅샷 가지오기 실패" -#: storage/lmgr/predicate.c:1762 utils/time/snapmgr.c:577 +#: storage/lmgr/predicate.c:1818 utils/time/snapmgr.c:542 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "%d PID 소스 프로세스는 더이상 실행 중이지 않습니다." -#: storage/lmgr/predicate.c:3935 storage/lmgr/predicate.c:3971 -#: storage/lmgr/predicate.c:4004 storage/lmgr/predicate.c:4012 -#: storage/lmgr/predicate.c:4051 storage/lmgr/predicate.c:4281 -#: storage/lmgr/predicate.c:4600 storage/lmgr/predicate.c:4612 -#: storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4695 +#: storage/lmgr/predicate.c:3991 storage/lmgr/predicate.c:4027 +#: storage/lmgr/predicate.c:4060 storage/lmgr/predicate.c:4068 +#: storage/lmgr/predicate.c:4107 storage/lmgr/predicate.c:4337 +#: storage/lmgr/predicate.c:4656 storage/lmgr/predicate.c:4668 +#: storage/lmgr/predicate.c:4715 storage/lmgr/predicate.c:4751 #, c-format msgid "" "could not serialize access due to read/write dependencies among transactions" msgstr "트랜잭션간 읽기/쓰기 의존성 때문에 serialize 접근을 할 수 없음" -#: storage/lmgr/predicate.c:3937 storage/lmgr/predicate.c:3973 -#: storage/lmgr/predicate.c:4006 storage/lmgr/predicate.c:4014 -#: storage/lmgr/predicate.c:4053 storage/lmgr/predicate.c:4283 -#: storage/lmgr/predicate.c:4602 storage/lmgr/predicate.c:4614 -#: storage/lmgr/predicate.c:4661 storage/lmgr/predicate.c:4697 +#: storage/lmgr/predicate.c:3993 storage/lmgr/predicate.c:4029 +#: storage/lmgr/predicate.c:4062 storage/lmgr/predicate.c:4070 +#: storage/lmgr/predicate.c:4109 storage/lmgr/predicate.c:4339 +#: storage/lmgr/predicate.c:4658 storage/lmgr/predicate.c:4670 +#: storage/lmgr/predicate.c:4717 storage/lmgr/predicate.c:4753 #, c-format msgid "The transaction might succeed if retried." msgstr "재시도하면 그 트랜잭션이 성공할 것입니다." -#: storage/lmgr/proc.c:349 +#: storage/lmgr/proc.c:353 #, c-format msgid "" -"number of requested standby connections exceeds max_wal_senders (currently " -"%d)" -msgstr "대기 서버 연결 수가 max_wal_senders 설정값(현재 %d)을 초과했습니다" +"number of requested standby connections exceeds \"max_wal_senders\" " +"(currently %d)" +msgstr "대기 서버 연결 수가 \"max_wal_senders\" 설정값(현재 %d)을 초과했습니다" -#: storage/lmgr/proc.c:1472 +#: storage/lmgr/proc.c:1546 #, c-format msgid "" "process %d avoided deadlock for %s on %s by rearranging queue order after " @@ -23915,23 +24863,23 @@ msgstr "" "%d PID 프로세스는 %s(%s)에 대해 교착 상태가 발생하지 않도록 %ld.%03dms 후에 " "대기열 순서를 다시 조정함" -#: storage/lmgr/proc.c:1487 +#: storage/lmgr/proc.c:1561 #, c-format msgid "" "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "%d PID 프로세스에서 %s(%s) 대기중 %ld.%03dms 후에 교착 상태를 감지함" -#: storage/lmgr/proc.c:1496 +#: storage/lmgr/proc.c:1570 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "%d PID 프로세스에서 여전히 %s(%s) 작업을 기다리고 있음(%ld.%03dms 후)" -#: storage/lmgr/proc.c:1503 +#: storage/lmgr/proc.c:1577 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "%d PID 프로세스가 %s(%s) 작업을 위해 잠금 취득함(%ld.%03dms 후)" -#: storage/lmgr/proc.c:1520 +#: storage/lmgr/proc.c:1594 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "프로세스 %d에서 %s(%s)을(를) 취득하지 못함(%ld.%03dms 후)" @@ -23964,69 +24912,213 @@ msgstr "손상된 아이템 길이: 전체 %u, 사용가능한 공간 %u" msgid "corrupted line pointer: offset = %u, size = %u" msgstr "손상된 줄 위치: 오프셋 = %u, 크기 = %u" -#: storage/smgr/md.c:487 storage/smgr/md.c:549 +#: storage/smgr/md.c:485 storage/smgr/md.c:547 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "\"%s\" 파일을 %u개 블록을 초과하여 확장할 수 없음" -#: storage/smgr/md.c:502 storage/smgr/md.c:613 +#: storage/smgr/md.c:500 storage/smgr/md.c:611 #, c-format msgid "could not extend file \"%s\": %m" msgstr "\"%s\" 파일을 확장할 수 없음: %m" -#: storage/smgr/md.c:508 +#: storage/smgr/md.c:506 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "\"%s\" 파일을 확장할 수 없음: %d/%d바이트만 %u 블록에 썼음" -#: storage/smgr/md.c:591 +#: storage/smgr/md.c:589 #, c-format msgid "could not extend file \"%s\" with FileFallocate(): %m" msgstr "FileFallocate() 함수로 \"%s\" 파일을 확장할 수 없음: %m" -#: storage/smgr/md.c:782 -#, c-format -msgid "could not read block %u in file \"%s\": %m" -msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %m" - -#: storage/smgr/md.c:798 +#: storage/smgr/md.c:869 #, c-format -msgid "could not read block %u in file \"%s\": read only %d of %d bytes" -msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %d / %d 바이트만 읽음" +msgid "could not read blocks %u..%u in file \"%s\": %m" +msgstr "%u..%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %m" -#: storage/smgr/md.c:856 +#: storage/smgr/md.c:895 #, c-format -msgid "could not write block %u in file \"%s\": %m" -msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %m" +msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" +msgstr "%u..%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %zu / %zu 바이트만 읽음" -#: storage/smgr/md.c:861 +#: storage/smgr/md.c:995 #, c-format -msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" -msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %d / %d 바이트만 씀" +msgid "could not write blocks %u..%u in file \"%s\": %m" +msgstr "%u..%u 블럭을 \"%s\" 파일에 쓸 수 없음: %m" -#: storage/smgr/md.c:1012 +#: storage/smgr/md.c:1165 #, c-format msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" msgstr "\"%s\" 파일을 %u 블럭으로 비울 수 없음: 현재 %u 블럭 뿐 임" -#: storage/smgr/md.c:1067 +#: storage/smgr/md.c:1220 #, c-format msgid "could not truncate file \"%s\" to %u blocks: %m" msgstr "\"%s\" 파일을 %u 블럭으로 정리할 수 없음: %m" -#: storage/smgr/md.c:1494 +#: storage/smgr/md.c:1700 #, c-format msgid "" "could not open file \"%s\" (target block %u): previous segment is only %u " "blocks" msgstr "\"%s\" 파일을 열기 실패(대상 블록: %u): 이전 조각은 %u 블럭 뿐임" -#: storage/smgr/md.c:1508 +#: storage/smgr/md.c:1714 #, c-format msgid "could not open file \"%s\" (target block %u): %m" msgstr "\"%s\" 파일을 열기 실패(대상 블록: %u): %m" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2132 +#: tcop/backend_startup.c:85 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "하위 프로세스에서 SSL 환경 설정을 못했음" + +#: tcop/backend_startup.c:208 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "접속 수락: host=%s port=%s" + +#: tcop/backend_startup.c:213 +#, c-format +msgid "connection received: host=%s" +msgstr "접속 수락: host=%s" + +#: tcop/backend_startup.c:277 +#, c-format +msgid "the database system is starting up" +msgstr "데이터베이스 시스템이 새로 가동 중입니다." + +#: tcop/backend_startup.c:283 +#, c-format +msgid "the database system is not yet accepting connections" +msgstr "해당 데이터베이스 시스템은 아직 접속을 허용하지 않습니다." + +#: tcop/backend_startup.c:284 +#, c-format +msgid "Consistent recovery state has not been yet reached." +msgstr "일관성 복구 작업을 아직 끝내지 못했습니다." + +#: tcop/backend_startup.c:288 +#, c-format +msgid "the database system is not accepting connections" +msgstr "해당 데이터베이스 시스템은 접속을 허용하지 않습니다." + +#: tcop/backend_startup.c:289 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "Hot standby 모드가 비활성화 되었습니다." + +#: tcop/backend_startup.c:294 +#, c-format +msgid "the database system is shutting down" +msgstr "데이터베이스 시스템이 중지 중입니다" + +#: tcop/backend_startup.c:299 +#, c-format +msgid "the database system is in recovery mode" +msgstr "데이터베이스 시스템이 자동 복구 작업 중입니다." + +#: tcop/backend_startup.c:414 +#, c-format +msgid "" +"received direct SSL connection request without ALPN protocol negotiation " +"extension" +msgstr "" +"수신된 직접 SSL 연결은 ALPN 프로토콜 채결 확장 없이 요청되었음" + +#: tcop/backend_startup.c:420 +#, c-format +msgid "direct SSL connection accepted" +msgstr "직접 SSL 연결 수락됨" + +#: tcop/backend_startup.c:430 +#, c-format +msgid "direct SSL connection rejected" +msgstr "직접 SSL 연결 거절됨" + +#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#, c-format +msgid "incomplete startup packet" +msgstr "아직 완료되지 않은 시작 패킷" + +#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#, c-format +msgid "invalid length of startup packet" +msgstr "시작 패킷의 길이가 잘못 되었습니다" + +#: tcop/backend_startup.c:573 +#, c-format +msgid "SSLRequest accepted" +msgstr "SSLRequest 수락됨" + +#: tcop/backend_startup.c:576 +#, c-format +msgid "SSLRequest rejected" +msgstr "SSLRequest 거절됨" + +#: tcop/backend_startup.c:585 +#, c-format +msgid "failed to send SSL negotiation response: %m" +msgstr "SSL 연결 작업에 오류가 발생했습니다: %m" + +#: tcop/backend_startup.c:603 +#, c-format +msgid "received unencrypted data after SSL request" +msgstr "SSL 요청 뒤에 암호화 되지 않은 데이터를 받았음" + +#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#, c-format +msgid "" +"This could be either a client-software bug or evidence of an attempted man-" +"in-the-middle attack." +msgstr "" +"이 현상은 클라이언트 소프트웨어 버그이거나, 중간자 공격으로 발생했을 것입니" +"다." + +#: tcop/backend_startup.c:627 +#, c-format +msgid "GSSENCRequest accepted" +msgstr "GSSENCRequest 수락됨" + +#: tcop/backend_startup.c:630 +#, c-format +msgid "GSSENCRequest rejected" +msgstr "GSSENCRequest 거절됨" + +#: tcop/backend_startup.c:639 +#, c-format +msgid "failed to send GSSAPI negotiation response: %m" +msgstr "GSSAPI 협상 응답을 보내지 못했습니다: %m" + +#: tcop/backend_startup.c:657 +#, c-format +msgid "received unencrypted data after GSSAPI encryption request" +msgstr "GSSAPI 암호화 요청 뒤에 암호화 되지 않은 데이터를 받았습니다." + +#: tcop/backend_startup.c:681 +#, c-format +msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" +msgstr "" +"지원하지 않는 frontend 프로토콜 %u.%u: 서버에서 지원하는 프로토콜 %u.0 .. %u." +"%u" + +#: tcop/backend_startup.c:744 +#, c-format +msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." +msgstr "사용할 수 있는 값: \"false\", 0, \"true\", 1, \"database\"." + +#: tcop/backend_startup.c:785 +#, c-format +msgid "invalid startup packet layout: expected terminator as last byte" +msgstr "잘못된 시작 패킷 레이아웃: 마지막 바이트로 종결문자가 발견되었음" + +#: tcop/backend_startup.c:802 +#, c-format +msgid "no PostgreSQL user name specified in startup packet" +msgstr "시작 패킷에서 지정한 사용자는 PostgreSQL 사용자 이름이 아닙니다" + +#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "OID %u 함수 없음" @@ -24041,8 +25133,8 @@ msgstr "fastpath 인터페이스를 이용한 \"%s\" 함수 호출 실패" msgid "fastpath function call: \"%s\" (OID %u)" msgstr "fastpath 함수 호출: \"%s\" (OID %u)" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 -#: tcop/postgres.c:2059 tcop/postgres.c:2309 +#: tcop/fastpath.c:313 tcop/postgres.c:1369 tcop/postgres.c:1605 +#: tcop/postgres.c:2071 tcop/postgres.c:2333 #, c-format msgid "duration: %s ms" msgstr "실행시간: %s ms" @@ -24072,42 +25164,42 @@ msgstr "함수 호출 메시지 안에 있는 잘못된 %d 인자 크기" msgid "incorrect binary data format in function argument %d" msgstr "함수 인자 %d 안에 잘못된 바이너리 자료 형식 발견됨" -#: tcop/postgres.c:463 tcop/postgres.c:4882 +#: tcop/postgres.c:467 tcop/postgres.c:5012 #, c-format msgid "invalid frontend message type %d" msgstr "잘못된 frontend 메시지 형태 %d" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1076 #, c-format msgid "statement: %s" msgstr "명령 구문: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1374 #, c-format msgid "duration: %s ms statement: %s" msgstr "실행시간: %s ms 명령 구문: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1480 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "준비된 명령 구문에는 다중 명령을 삽입할 수 없습니다" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1610 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "실행시간: %s ms %s 구문분석: %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2629 +#: tcop/postgres.c:1677 tcop/postgres.c:2653 #, c-format msgid "unnamed prepared statement does not exist" msgstr "이름없는 준비된 명령 구문(unnamed prepared statement) 없음" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1729 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "바인드 메시지는 %d 매개 변수 형태지만, %d 매개 변수여야함" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1735 #, c-format msgid "" "bind message supplies %d parameters, but prepared statement \"%s\" requires " @@ -24116,115 +25208,115 @@ msgstr "" "바인드 메시지는 %d개의 매개 변수를 지원하지만, \"%s\" 준비된 명령 구문" "(prepared statement)에서는%d 개의 매개 변수가 필요합니다" -#: tcop/postgres.c:1937 +#: tcop/postgres.c:1949 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "바인드 매개 변수 %d 안에 잘못된 바이너리 자료 형태가 있음" -#: tcop/postgres.c:2064 +#: tcop/postgres.c:2076 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "실행시간: %s ms %s%s%s 접속: %s" -#: tcop/postgres.c:2118 tcop/postgres.c:2712 +#: tcop/postgres.c:2131 tcop/postgres.c:2735 #, c-format msgid "portal \"%s\" does not exist" msgstr "\"%s\" portal 없음" -#: tcop/postgres.c:2189 +#: tcop/postgres.c:2213 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2191 tcop/postgres.c:2317 +#: tcop/postgres.c:2215 tcop/postgres.c:2341 msgid "execute fetch from" msgstr "자료뽑기" -#: tcop/postgres.c:2192 tcop/postgres.c:2318 +#: tcop/postgres.c:2216 tcop/postgres.c:2342 msgid "execute" msgstr "쿼리실행" -#: tcop/postgres.c:2314 +#: tcop/postgres.c:2338 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "수행시간: %s ms %s %s%s%s: %s" -#: tcop/postgres.c:2462 +#: tcop/postgres.c:2486 #, c-format msgid "prepare: %s" msgstr "prepare: %s" -#: tcop/postgres.c:2487 +#: tcop/postgres.c:2511 #, c-format -msgid "parameters: %s" +msgid "Parameters: %s" msgstr "매개 변수: %s" -#: tcop/postgres.c:2502 +#: tcop/postgres.c:2526 #, c-format -msgid "abort reason: recovery conflict" +msgid "Abort reason: recovery conflict" msgstr "중지 이유: 복구 충돌" -#: tcop/postgres.c:2518 +#: tcop/postgres.c:2542 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "사용자가 너무 오랫동안 공유 버퍼 핀을 붙잡고 있습니다." -#: tcop/postgres.c:2521 +#: tcop/postgres.c:2545 #, c-format msgid "User was holding a relation lock for too long." msgstr "사용자가 너무 오랫동안 릴레이션 잠금을 하고 있습니다." -#: tcop/postgres.c:2524 +#: tcop/postgres.c:2548 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "삭제할 테이블스페이스를 사용자가 사용했거나, 사용하고 있습니다." -#: tcop/postgres.c:2527 +#: tcop/postgres.c:2551 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "사용자 쿼리가 삭제해야할 로우 버전를 볼 필요가 있는 것 같습니다." -#: tcop/postgres.c:2530 +#: tcop/postgres.c:2554 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "사용자가 잘못된 논리 복제 슬롯을 사용했습니다." -#: tcop/postgres.c:2536 +#: tcop/postgres.c:2560 #, c-format msgid "User was connected to a database that must be dropped." msgstr "삭제 되어져야할 데이터베이스에 사용자가 접속해 있습니다." -#: tcop/postgres.c:2575 +#: tcop/postgres.c:2599 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "\"%s\" 포탈 $%d 매개 변수 = %s" -#: tcop/postgres.c:2578 +#: tcop/postgres.c:2602 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "\"%s\" 포탈 $%d 매개 변수" -#: tcop/postgres.c:2584 +#: tcop/postgres.c:2608 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "이름없는 포탈 $%d 매개 변수 = %s" -#: tcop/postgres.c:2587 +#: tcop/postgres.c:2611 #, c-format msgid "unnamed portal parameter $%d" msgstr "이름없는 포탈 $%d 매개 변수" -#: tcop/postgres.c:2932 +#: tcop/postgres.c:2955 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "예상치 못한 SIGQUIT 신호로 연결을 끝냅니다" -#: tcop/postgres.c:2938 +#: tcop/postgres.c:2961 #, c-format msgid "terminating connection because of crash of another server process" msgstr "다른 서버 프로세스가 손상을 입어 현재 연결을 중지합니다" -#: tcop/postgres.c:2939 +#: tcop/postgres.c:2962 #, c-format msgid "" "The postmaster has commanded this server process to roll back the current " @@ -24235,24 +25327,24 @@ msgstr "" "와의 연결을 끊으라는 명령을 보냈습니다. 왜냐하면, 다른 서버 프로세스가 비정상" "적으로 중지되어 공유 메모리가 손상되었을 가능성이 있기 때문입니다" -#: tcop/postgres.c:2943 tcop/postgres.c:3310 +#: tcop/postgres.c:2966 tcop/postgres.c:3219 #, c-format msgid "" "In a moment you should be able to reconnect to the database and repeat your " "command." msgstr "잠시 뒤에 다시 연결 해서 작업을 계속 하십시오" -#: tcop/postgres.c:2950 +#: tcop/postgres.c:2973 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "immediate 종료 명령으로 연결을 끝냅니다" -#: tcop/postgres.c:3036 +#: tcop/postgres.c:3051 #, c-format msgid "floating-point exception" msgstr "부동소수점 예외발생" -#: tcop/postgres.c:3037 +#: tcop/postgres.c:3052 #, c-format msgid "" "An invalid floating-point operation was signaled. This probably means an out-" @@ -24261,72 +25353,77 @@ msgstr "" "잘못된 부동소수점 작업이 감지 되었습니다. 이것은 아마도 결과값 범위초과나 0으" "로 나누는 작업과 같은 잘못된 연산 때문에 발생한 것 같습니다" -#: tcop/postgres.c:3214 +#: tcop/postgres.c:3217 +#, c-format +msgid "terminating connection due to conflict with recovery" +msgstr "복구 작업 중 충돌로 연결을 끝냅니다" + +#: tcop/postgres.c:3289 #, c-format msgid "canceling authentication due to timeout" msgstr "시간 초과로 인증 작업을 취소합니다." -#: tcop/postgres.c:3218 +#: tcop/postgres.c:3293 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "관리자 명령으로 인해 자동 청소 프로세스를 끝냅니다" -#: tcop/postgres.c:3222 +#: tcop/postgres.c:3297 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "관리자 요청에 의해서 논리 복제 작업자를 끝냅니다" -#: tcop/postgres.c:3239 tcop/postgres.c:3249 tcop/postgres.c:3308 -#, c-format -msgid "terminating connection due to conflict with recovery" -msgstr "복구 작업 중 충돌로 연결을 끝냅니다" - -#: tcop/postgres.c:3260 +#: tcop/postgres.c:3317 #, c-format msgid "terminating connection due to administrator command" msgstr "관리자 요청에 의해서 연결을 끝냅니다" -#: tcop/postgres.c:3291 +#: tcop/postgres.c:3348 #, c-format msgid "connection to client lost" msgstr "서버로부터 연결이 끊어졌습니다." -#: tcop/postgres.c:3361 +#: tcop/postgres.c:3400 #, c-format msgid "canceling statement due to lock timeout" msgstr "잠금 대기 시간 초과로 작업을 취소합니다." -#: tcop/postgres.c:3368 +#: tcop/postgres.c:3407 #, c-format msgid "canceling statement due to statement timeout" msgstr "명령실행시간 초과로 작업을 취소합니다." -#: tcop/postgres.c:3375 +#: tcop/postgres.c:3414 #, c-format msgid "canceling autovacuum task" msgstr "자동 청소 작업을 취소하는 중" -#: tcop/postgres.c:3398 +#: tcop/postgres.c:3427 #, c-format msgid "canceling statement due to user request" msgstr "사용자 요청에 의해 작업을 취소합니다." -#: tcop/postgres.c:3412 +#: tcop/postgres.c:3448 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "idle-in-transaction 시간 초과로 연결을 끝냅니다" -#: tcop/postgres.c:3423 +#: tcop/postgres.c:3461 +#, c-format +msgid "terminating connection due to transaction timeout" +msgstr "트랜잭션 시간(transaction_timeout) 초과로 연결을 끝냅니다" + +#: tcop/postgres.c:3474 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "idle-session 시간 초과로 연결을 끝냅니다" -#: tcop/postgres.c:3514 +#: tcop/postgres.c:3564 #, c-format msgid "stack depth limit exceeded" msgstr "스택 깊이를 초과했습니다" -#: tcop/postgres.c:3515 +#: tcop/postgres.c:3565 #, c-format msgid "" "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), " @@ -24335,29 +25432,29 @@ msgstr "" "먼저 OS에서 지원하는 스택 depth 최대값을 확인한 뒤, 허용범위 안에서 " "\"max_stack_depth\" (현재값: %dkB) 매개 변수 값의 설정치를 증가시키세요." -#: tcop/postgres.c:3562 +#: tcop/postgres.c:3612 #, c-format msgid "\"max_stack_depth\" must not exceed %ldkB." msgstr "\"max_stack_depth\" 값은 %ldkB를 초과할 수 없습니다" -#: tcop/postgres.c:3564 +#: tcop/postgres.c:3614 #, c-format msgid "" "Increase the platform's stack depth limit via \"ulimit -s\" or local " "equivalent." msgstr "OS의 \"ulimit -s\" 명령과 같은 것으로 스택 깊이를 늘려주십시오." -#: tcop/postgres.c:3587 +#: tcop/postgres.c:3637 #, c-format -msgid "client_connection_check_interval must be set to 0 on this platform." -msgstr "이 플랫폼에서는 client_connection_check_interval 값은 0 이어야 합니다." +msgid "\"client_connection_check_interval\" must be set to 0 on this platform." +msgstr "이 플랫폼에서는 \"client_connection_check_interval\" 값은 0 이어야 합니다." -#: tcop/postgres.c:3608 +#: tcop/postgres.c:3658 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "\"log_statement_stats\" 값이 true 일 때는 이 값을 활성화할 수 없습니다" -#: tcop/postgres.c:3623 +#: tcop/postgres.c:3673 #, c-format msgid "" "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", " @@ -24366,54 +25463,54 @@ msgstr "" "\"log_parser_stats\", \"log_planner_stats\", \"log_executor_stats\" 설정값들 " "중 하나가 true 일 때는 \"log_statement_stats\" 설정을 활성화할 수 없습니다" -#: tcop/postgres.c:3971 +#: tcop/postgres.c:4098 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "서버 프로세스의 명령행 인자가 잘못되었습니다: %s" -#: tcop/postgres.c:3972 tcop/postgres.c:3978 +#: tcop/postgres.c:4099 tcop/postgres.c:4105 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: tcop/postgres.c:3976 +#: tcop/postgres.c:4103 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: 잘못된 명령행 인자: %s" -#: tcop/postgres.c:4029 +#: tcop/postgres.c:4156 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: 데이터베이스와 사용자를 지정하지 않았습니다" -#: tcop/postgres.c:4779 +#: tcop/postgres.c:4909 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "잘못된 CLOSE 메시지 서브타입 %d" -#: tcop/postgres.c:4816 +#: tcop/postgres.c:4946 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "잘못된 DESCRIBE 메시지 서브타입 %d" -#: tcop/postgres.c:4903 +#: tcop/postgres.c:5033 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "복제 연결에서는 fastpath 함수 호출을 지원하지 않습니다" -#: tcop/postgres.c:4907 +#: tcop/postgres.c:5037 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "복제 연결에서는 확장된 쿼리 프로토콜을 지원하지 않습니다" -#: tcop/postgres.c:5087 +#: tcop/postgres.c:5217 #, c-format msgid "" -"disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s" -"%s" +"disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s " +"host=%s%s%s" msgstr "" -"연결종료: 세션 시간: %d:%02d:%02d.%03d 사용자=%s 데이터베이스=%s 호스트=%s%s" -"%s" +"연결종료: 세션 시간: %d:%02d:%02d.%03d 사용자=%s 데이터베이스=%s 호스트" +"=%s%s%s" #: tcop/pquery.c:641 #, c-format @@ -24421,54 +25518,54 @@ msgid "bind message has %d result formats but query has %d columns" msgstr "" "바인드 메시지는 %d 결과 포멧을 가지고 있고, 쿼리는 %d 칼럼을 가지고 있습니다" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:942 tcop/pquery.c:1696 #, c-format msgid "cursor can only scan forward" msgstr "이 커서는 앞으로 이동 전용입니다" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:943 tcop/pquery.c:1697 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "" "뒤로 이동 가능한 커서를 만드려면 SCROLL 옵션을 추가해서 커서를 만드세요." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:417 +#: tcop/utility.c:410 #, c-format msgid "cannot execute %s in a read-only transaction" msgstr "읽기 전용 트랜잭션에서는 %s 명령을 실행할 수 없습니다." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:435 +#: tcop/utility.c:428 #, c-format msgid "cannot execute %s during a parallel operation" msgstr "병렬 처리 작업에서는 %s 명령을 실행할 수 없습니다." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:454 +#: tcop/utility.c:447 #, c-format msgid "cannot execute %s during recovery" msgstr "복구 작업 중에는 %s 명령을 실행할 수 없습니다." #. translator: %s is name of a SQL command, eg PREPARE -#: tcop/utility.c:472 +#: tcop/utility.c:465 #, c-format msgid "cannot execute %s within security-restricted operation" msgstr "보안 제한 작업 내에서 %s을(를) 실행할 수 없음" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:828 +#: tcop/utility.c:821 #, c-format msgid "cannot execute %s within a background process" msgstr "백그라운드 프로세스에서는 %s 명령을 실행할 수 없습니다." #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:954 +#: tcop/utility.c:947 #, c-format msgid "permission denied to execute %s command" msgstr "%s 명령 실행 권한 없음" -#: tcop/utility.c:956 +#: tcop/utility.c:949 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "이 명령 실행은 \"%s\" 롤 권한이 있는 롤만 할 수 있습니다." @@ -24621,13 +25718,13 @@ msgstr "\"long\" 플래그 값을 포함하는 잘못된 affix 플래그: \"%s\" msgid "could not open dictionary file \"%s\": %m" msgstr "\"%s\" 사전 파일을 열 수 없음: %m" -#: tsearch/spell.c:749 utils/adt/regexp.c:224 jsonpath_gram.y:559 +#: tsearch/spell.c:749 utils/adt/regexp.c:223 jsonpath_gram.y:629 #, c-format msgid "invalid regular expression: %s" msgstr "잘못된 정규식: %s" #: tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 -#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18123 gram.y:18140 +#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18735 gram.y:18752 #, c-format msgid "syntax error" msgstr "구문 오류" @@ -24665,18 +25762,18 @@ msgstr "alias 수가 지정한 %d 개수를 초과함" msgid "affix file contains both old-style and new-style commands" msgstr "affix 파일에 옛방식과 새방식 명령이 함께 있습니다" -#: tsearch/to_tsany.c:195 utils/adt/tsvector.c:278 utils/adt/tsvector_op.c:1128 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "" "문자열이 너무 길어서 tsvector에 사용할 수 없음(%d바이트, 최대 %d바이트)" -#: tsearch/ts_locale.c:238 +#: tsearch/ts_locale.c:236 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "%d번째 줄(해당 파일: \"%s\"): \"%s\"" -#: tsearch/ts_locale.c:317 +#: tsearch/ts_locale.c:315 #, c-format msgid "conversion from wchar_t to server encoding failed: %m" msgstr "wchar_t에서 서버 인코딩으로 변환하지 못함: %m" @@ -24703,72 +25800,72 @@ msgstr "\"%s\" 전문 검색 구성 파일 이름이 잘못됨" msgid "could not open stop-word file \"%s\": %m" msgstr "\"%s\" 중지 단어 파일을 열 수 없음: %m" -#: tsearch/wparser.c:308 tsearch/wparser.c:396 tsearch/wparser.c:473 +#: tsearch/wparser.c:306 tsearch/wparser.c:394 tsearch/wparser.c:471 #, c-format msgid "text search parser does not support headline creation" msgstr "전문 검색 분석기에서 헤드라인 작성을 지원하지 않음" -#: tsearch/wparser_def.c:2663 +#: tsearch/wparser_def.c:2664 #, c-format msgid "unrecognized headline parameter: \"%s\"" msgstr "인식할 수 없는 headline 매개 변수: \"%s\"" -#: tsearch/wparser_def.c:2673 +#: tsearch/wparser_def.c:2674 #, c-format msgid "MinWords should be less than MaxWords" msgstr "MinWords는 MaxWords보다 작아야 함" -#: tsearch/wparser_def.c:2677 +#: tsearch/wparser_def.c:2678 #, c-format msgid "MinWords should be positive" msgstr "MinWords는 양수여야 함" -#: tsearch/wparser_def.c:2681 +#: tsearch/wparser_def.c:2682 #, c-format msgid "ShortWord should be >= 0" msgstr "ShortWord는 0보다 크거나 같아야 함" -#: tsearch/wparser_def.c:2685 +#: tsearch/wparser_def.c:2686 #, c-format msgid "MaxFragments should be >= 0" msgstr "MaxFragments는 0보다 크거나 같아야 함" -#: utils/activity/pgstat.c:438 +#: utils/activity/pgstat.c:435 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "\"%s\" 매개 변수 통계 파일을 지울 수 없음: %m" -#: utils/activity/pgstat.c:1252 +#: utils/activity/pgstat.c:1255 #, c-format msgid "invalid statistics kind: \"%s\"" msgstr "잘못된 통계정보 종류: \"%s\"" -#: utils/activity/pgstat.c:1332 +#: utils/activity/pgstat.c:1335 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "\"%s\" 임시 통계 파일을 열 수 없음: %m" -#: utils/activity/pgstat.c:1444 +#: utils/activity/pgstat.c:1455 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "\"%s\" 임시 통계 파일에 쓰기 실패: %m" -#: utils/activity/pgstat.c:1453 +#: utils/activity/pgstat.c:1464 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "\"%s\" 임시 통계 파일을 닫을 수 없습니다: %m" -#: utils/activity/pgstat.c:1461 +#: utils/activity/pgstat.c:1472 #, c-format msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" msgstr "\"%s\" 임시 통계 파일 이름을 \"%s\" (으)로 바꿀 수 없습니다: %m" -#: utils/activity/pgstat.c:1510 +#: utils/activity/pgstat.c:1521 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "\"%s\" 통계 파일을 열 수 없음: %m" -#: utils/activity/pgstat.c:1672 +#: utils/activity/pgstat.c:1683 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "\"%s\" 통계 파일이 손상되었음" @@ -24778,116 +25875,126 @@ msgstr "\"%s\" 통계 파일이 손상되었음" msgid "function call to dropped function" msgstr "삭제될 함수를 호출함" -#: utils/activity/pgstat_xact.c:363 +#: utils/activity/pgstat_xact.c:362 #, c-format msgid "resetting existing statistics for kind %s, db=%u, oid=%u" msgstr "%s 종류의 기존 통계 정보를 초기화합니다, db=%u, oid=%u" +#: utils/activity/wait_event.c:207 utils/activity/wait_event.c:232 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "\"%s\" 대기 이벤트는 이미 \"%s\" 자료형 안에 있음" + +#: utils/activity/wait_event.c:246 +#, c-format +msgid "too many custom wait events" +msgstr "너무 많은 사용자 대기 이벤트" + # # nonun 부분 begin -#: utils/adt/acl.c:177 utils/adt/name.c:93 +#: utils/adt/acl.c:183 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "식별자(identifier)가 너무 깁니다." -#: utils/adt/acl.c:178 utils/adt/name.c:94 +#: utils/adt/acl.c:184 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "식별자(Identifier)는 %d 글자 이상일 수 없습니다." -#: utils/adt/acl.c:266 +#: utils/adt/acl.c:272 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "알 수 없는 않은 키워드: \"%s\"" -#: utils/adt/acl.c:267 +#: utils/adt/acl.c:273 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "ACL 키워드는 \"group\" 또는 \"user\" 중에 하나여야 합니다." -#: utils/adt/acl.c:275 +#: utils/adt/acl.c:281 #, c-format msgid "missing name" msgstr "이름이 빠졌습니다." -#: utils/adt/acl.c:276 +#: utils/adt/acl.c:282 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "이름은 \"group\" 또는 \"user\" 키워드 뒤에 있어야 합니다." -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:288 #, c-format msgid "missing \"=\" sign" msgstr "\"=\" 기호가 빠졌습니다." -#: utils/adt/acl.c:341 +#: utils/adt/acl.c:350 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "잘못된 조건: \"%s\" 중에 한 가지여야 합니다." -#: utils/adt/acl.c:371 +#: utils/adt/acl.c:380 #, c-format msgid "a name must follow the \"/\" sign" msgstr "이름은 \"/\"기호 뒤에 있어야 합니다." -#: utils/adt/acl.c:383 +#: utils/adt/acl.c:392 #, c-format msgid "defaulting grantor to user ID %u" msgstr "%u 사용자 ID에서 기본 권한자로 할당하고 있습니다" -#: utils/adt/acl.c:569 +#: utils/adt/acl.c:578 #, c-format msgid "ACL array contains wrong data type" msgstr "ACL 배열에 잘못된 자료형을 사용하고 있습니다" -#: utils/adt/acl.c:573 +#: utils/adt/acl.c:582 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "ACL 배열은 일차원 배열이어야 합니다" -#: utils/adt/acl.c:577 +#: utils/adt/acl.c:586 #, c-format msgid "ACL arrays must not contain null values" msgstr "ACL 배열에는 null 값을 포함할 수 없습니다" -#: utils/adt/acl.c:606 +#: utils/adt/acl.c:615 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "ACL 설정 정보 끝에 끝에 쓸모 없는 내용들이 더 포함되어있습니다" -#: utils/adt/acl.c:1248 +#: utils/adt/acl.c:1263 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "부여 옵션을 해당 부여자에게 다시 부여할 수 없음" -#: utils/adt/acl.c:1564 +#: utils/adt/acl.c:1579 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert 더이상 지원하지 않음" -#: utils/adt/acl.c:1574 +#: utils/adt/acl.c:1589 #, c-format msgid "aclremove is no longer supported" msgstr "aclremovie 더이상 지원하지 않음" -#: utils/adt/acl.c:1693 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "알 수 없는 권한 타입: \"%s\"" -#: utils/adt/acl.c:3476 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3550 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "\"%s\" 함수가 없습니다." -#: utils/adt/acl.c:5023 +#: utils/adt/acl.c:5196 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "SET ROLE \"%s\" 작업이 있어야 함" #: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 -#: utils/adt/array_userfuncs.c:878 utils/adt/json.c:694 utils/adt/json.c:831 -#: utils/adt/json.c:869 utils/adt/jsonb.c:1139 utils/adt/jsonb.c:1211 -#: utils/adt/jsonb.c:1629 utils/adt/jsonb.c:1817 utils/adt/jsonb.c:1827 +#: utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 +#: utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 +#: utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "입력 자료형을 결정할 수 없음" @@ -24898,17 +26005,17 @@ msgid "input data type is not an array" msgstr "입력 자료형이 배열이 아닙니다." #: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 -#: utils/adt/float.c:1228 utils/adt/float.c:1302 utils/adt/float.c:4117 -#: utils/adt/float.c:4155 utils/adt/int.c:778 utils/adt/int.c:800 +#: utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 +#: utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 #: utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 #: utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 #: utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 #: utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 #: utils/adt/int.c:1263 utils/adt/int.c:1331 utils/adt/int.c:1337 -#: utils/adt/int8.c:1257 utils/adt/numeric.c:1901 utils/adt/numeric.c:4388 -#: utils/adt/rangetypes.c:1481 utils/adt/rangetypes.c:1494 -#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1132 -#: utils/adt/varlena.c:3134 +#: utils/adt/int8.c:1256 utils/adt/numeric.c:1917 utils/adt/numeric.c:4454 +#: utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 +#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 +#: utils/adt/varlena.c:3137 #, c-format msgid "integer out of range" msgstr "정수 범위를 벗어남" @@ -24948,269 +26055,280 @@ msgstr "차원(배열 깊이)이 다른 배열들을 서로 합칠 수 없습니 msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "차원(배열 깊이)이 다른 배열들을 서로 합칠 수 없습니다" -#: utils/adt/array_userfuncs.c:987 utils/adt/array_userfuncs.c:995 -#: utils/adt/arrayfuncs.c:5590 utils/adt/arrayfuncs.c:5596 +#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 +#: utils/adt/arrayfuncs.c:5616 utils/adt/arrayfuncs.c:5622 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "배열 차수가 서로 틀린 배열은 누적할 수 없음" -#: utils/adt/array_userfuncs.c:1286 utils/adt/array_userfuncs.c:1440 +#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "다차원 배열에서 요소 검색 기능은 지원하지 않음" -#: utils/adt/array_userfuncs.c:1315 +#: utils/adt/array_userfuncs.c:1301 #, c-format msgid "initial position must not be null" msgstr "초기 위치값은 null값이 아니여야 함" -#: utils/adt/array_userfuncs.c:1688 +#: utils/adt/array_userfuncs.c:1674 #, c-format msgid "sample size must be between 0 and %d" msgstr "샘플 크기는 0에서 %d 사이여야 함" -#: utils/adt/arrayfuncs.c:273 utils/adt/arrayfuncs.c:287 -#: utils/adt/arrayfuncs.c:298 utils/adt/arrayfuncs.c:320 -#: utils/adt/arrayfuncs.c:337 utils/adt/arrayfuncs.c:351 -#: utils/adt/arrayfuncs.c:359 utils/adt/arrayfuncs.c:366 -#: utils/adt/arrayfuncs.c:506 utils/adt/arrayfuncs.c:521 -#: utils/adt/arrayfuncs.c:532 utils/adt/arrayfuncs.c:547 -#: utils/adt/arrayfuncs.c:568 utils/adt/arrayfuncs.c:598 -#: utils/adt/arrayfuncs.c:605 utils/adt/arrayfuncs.c:613 -#: utils/adt/arrayfuncs.c:647 utils/adt/arrayfuncs.c:670 -#: utils/adt/arrayfuncs.c:690 utils/adt/arrayfuncs.c:807 -#: utils/adt/arrayfuncs.c:816 utils/adt/arrayfuncs.c:846 -#: utils/adt/arrayfuncs.c:861 utils/adt/arrayfuncs.c:914 +#: utils/adt/arrayfuncs.c:264 utils/adt/arrayfuncs.c:273 +#: utils/adt/arrayfuncs.c:284 utils/adt/arrayfuncs.c:307 +#: utils/adt/arrayfuncs.c:440 utils/adt/arrayfuncs.c:454 +#: utils/adt/arrayfuncs.c:466 utils/adt/arrayfuncs.c:636 +#: utils/adt/arrayfuncs.c:668 utils/adt/arrayfuncs.c:703 +#: utils/adt/arrayfuncs.c:718 utils/adt/arrayfuncs.c:777 +#: utils/adt/arrayfuncs.c:782 utils/adt/arrayfuncs.c:870 +#: utils/adt/arrayfuncs.c:897 utils/adt/arrayfuncs.c:904 +#: utils/adt/arrayfuncs.c:941 #, c-format msgid "malformed array literal: \"%s\"" msgstr "비정상적인 배열 문자: \"%s\"" -#: utils/adt/arrayfuncs.c:274 -#, c-format -msgid "\"[\" must introduce explicitly-specified array dimensions." -msgstr "배열 차원 정의는 \"[\" 문자로 시작해야 합니다." - -#: utils/adt/arrayfuncs.c:288 +#: utils/adt/arrayfuncs.c:265 #, c-format -msgid "Missing array dimension value." -msgstr "배열 차원(배열 깊이) 값이 빠졌습니다." +msgid "Array value must start with \"{\" or dimension information." +msgstr "배열값은 \"{\" 또는 배열 깊이 정보로 시작되어야 합니다" -#: utils/adt/arrayfuncs.c:299 utils/adt/arrayfuncs.c:338 +#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:467 #, c-format msgid "Missing \"%s\" after array dimensions." msgstr "배열 차원(배열 깊이) 표현에서 \"%s\" 문자가 빠졌습니다." -#: utils/adt/arrayfuncs.c:308 utils/adt/arrayfuncs.c:2933 -#: utils/adt/arrayfuncs.c:2965 utils/adt/arrayfuncs.c:2980 +#: utils/adt/arrayfuncs.c:285 #, c-format -msgid "upper bound cannot be less than lower bound" -msgstr "상한값은 하한값보다 작을 수 없습니다" +msgid "Array contents must start with \"{\"." +msgstr "배열형은 \"{\" 문자로 시작해야 합니다." -#: utils/adt/arrayfuncs.c:321 +#: utils/adt/arrayfuncs.c:308 utils/adt/multirangetypes.c:292 #, c-format -msgid "Array value must start with \"{\" or dimension information." -msgstr "배열값은 \"{\" 또는 배열 깊이 정보로 시작되어야 합니다" +msgid "Junk after closing right brace." +msgstr "오른쪽 닫기 괄호 뒤에 정크" -#: utils/adt/arrayfuncs.c:352 +#: utils/adt/arrayfuncs.c:431 utils/adt/arrayfuncs.c:643 #, c-format -msgid "Array contents must start with \"{\"." -msgstr "배열형은 \"{\" 문자로 시작해야 합니다." +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "배열 차원이 최대치(%d)를 초과했음" -#: utils/adt/arrayfuncs.c:360 utils/adt/arrayfuncs.c:367 +#: utils/adt/arrayfuncs.c:441 #, c-format -msgid "Specified array dimensions do not match array contents." -msgstr "지정한 배열 차원에 해당하는 배열이 없습니다." +msgid "\"[\" must introduce explicitly-specified array dimensions." +msgstr "배열 차원 정의는 \"[\" 문자로 시작해야 합니다." -#: utils/adt/arrayfuncs.c:507 utils/adt/arrayfuncs.c:533 -#: utils/adt/multirangetypes.c:166 utils/adt/rangetypes.c:2405 -#: utils/adt/rangetypes.c:2413 utils/adt/rowtypes.c:219 -#: utils/adt/rowtypes.c:230 +#: utils/adt/arrayfuncs.c:455 #, c-format -msgid "Unexpected end of input." -msgstr "입력의 예상치 못한 종료." +msgid "Missing array dimension value." +msgstr "배열 차원(배열 깊이) 값이 빠졌습니다." + +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 +#: utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 +#, c-format +msgid "upper bound cannot be less than lower bound" +msgstr "상한값은 하한값보다 작을 수 없습니다" + +#: utils/adt/arrayfuncs.c:487 +#, c-format +msgid "array upper bound is too large: %d" +msgstr "배열 upper bound가 너무 큽니다: %d" + +#: utils/adt/arrayfuncs.c:538 +#, c-format +msgid "array bound is out of integer range" +msgstr "배열 bound가 정수 범위를 초과했음" -#: utils/adt/arrayfuncs.c:522 utils/adt/arrayfuncs.c:569 -#: utils/adt/arrayfuncs.c:599 utils/adt/arrayfuncs.c:648 +#: utils/adt/arrayfuncs.c:637 utils/adt/arrayfuncs.c:669 +#: utils/adt/arrayfuncs.c:704 utils/adt/arrayfuncs.c:898 #, c-format msgid "Unexpected \"%c\" character." msgstr "예기치 않은 \"%c\" 문자" -#: utils/adt/arrayfuncs.c:548 utils/adt/arrayfuncs.c:671 +#: utils/adt/arrayfuncs.c:719 #, c-format msgid "Unexpected array element." msgstr "예기치 않은 배열 요소" -#: utils/adt/arrayfuncs.c:606 +#: utils/adt/arrayfuncs.c:778 #, c-format -msgid "Unmatched \"%c\" character." -msgstr "짝이 안 맞는 \"%c\" 문자" +msgid "Specified array dimensions do not match array contents." +msgstr "지정한 배열 차원에 해당하는 배열이 없습니다." -#: utils/adt/arrayfuncs.c:614 utils/adt/jsonfuncs.c:2553 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2598 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "다차원 배열에는 일치하는 차원이 포함된 배열 식이 있어야 함" -#: utils/adt/arrayfuncs.c:691 utils/adt/multirangetypes.c:293 +#: utils/adt/arrayfuncs.c:871 utils/adt/arrayfuncs.c:905 #, c-format -msgid "Junk after closing right brace." -msgstr "오른쪽 닫기 괄호 뒤에 정크" +msgid "Incorrectly quoted array element." +msgstr "바르지 않은 따옴표 배열 요소입니다." + +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 +#: utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 +#: utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#, c-format +msgid "Unexpected end of input." +msgstr "입력의 예상치 못한 종료." -#: utils/adt/arrayfuncs.c:1325 utils/adt/arrayfuncs.c:3479 -#: utils/adt/arrayfuncs.c:6080 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3499 +#: utils/adt/arrayfuncs.c:6106 #, c-format msgid "invalid number of dimensions: %d" msgstr "잘못된 배열 차원(배열 깊이): %d" -#: utils/adt/arrayfuncs.c:1336 +#: utils/adt/arrayfuncs.c:1312 #, c-format msgid "invalid array flags" msgstr "잘못된 배열 플래그" -#: utils/adt/arrayfuncs.c:1358 +#: utils/adt/arrayfuncs.c:1334 #, c-format msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "이진 자료에 있는 배열 요소 자료형이 %u (%s) 입니다. 기대값: %u (%s)" -#: utils/adt/arrayfuncs.c:1402 utils/adt/multirangetypes.c:451 -#: utils/adt/rangetypes.c:344 utils/cache/lsyscache.c:2916 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 +#: utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 #, c-format msgid "no binary input function available for type %s" msgstr "%s 자료형에서 사용할 바이너리 입력 함수가 없습니다." -#: utils/adt/arrayfuncs.c:1542 +#: utils/adt/arrayfuncs.c:1509 #, c-format msgid "improper binary format in array element %d" msgstr "%d 번째 배열 요소의 포맷이 부적절합니다." -#: utils/adt/arrayfuncs.c:1623 utils/adt/multirangetypes.c:456 -#: utils/adt/rangetypes.c:349 utils/cache/lsyscache.c:2949 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 +#: utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 #, c-format msgid "no binary output function available for type %s" msgstr "%s 자료형에서 사용할 바이너리 출력 함수가 없습니다." -#: utils/adt/arrayfuncs.c:2102 +#: utils/adt/arrayfuncs.c:2067 #, c-format msgid "slices of fixed-length arrays not implemented" msgstr "특정 크기로 배열을 절단하는 기능은 구현되지 않습니다." -#: utils/adt/arrayfuncs.c:2280 utils/adt/arrayfuncs.c:2302 -#: utils/adt/arrayfuncs.c:2351 utils/adt/arrayfuncs.c:2589 -#: utils/adt/arrayfuncs.c:2911 utils/adt/arrayfuncs.c:6066 -#: utils/adt/arrayfuncs.c:6092 utils/adt/arrayfuncs.c:6103 -#: utils/adt/json.c:1497 utils/adt/json.c:1569 utils/adt/jsonb.c:1416 -#: utils/adt/jsonb.c:1500 utils/adt/jsonfuncs.c:4434 utils/adt/jsonfuncs.c:4587 -#: utils/adt/jsonfuncs.c:4698 utils/adt/jsonfuncs.c:4746 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 +#: utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 +#: utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6092 +#: utils/adt/arrayfuncs.c:6118 utils/adt/arrayfuncs.c:6129 +#: utils/adt/json.c:1433 utils/adt/json.c:1505 utils/adt/jsonb.c:1317 +#: utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4710 utils/adt/jsonfuncs.c:4863 +#: utils/adt/jsonfuncs.c:4974 utils/adt/jsonfuncs.c:5022 #, c-format msgid "wrong number of array subscripts" msgstr "잘못된 배열 하위 스크립트(1,2...차원 배열 표시 문제)" -#: utils/adt/arrayfuncs.c:2285 utils/adt/arrayfuncs.c:2393 -#: utils/adt/arrayfuncs.c:2656 utils/adt/arrayfuncs.c:2970 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 +#: utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "배열 하위 스크립트 범위를 초과했습니다" -#: utils/adt/arrayfuncs.c:2290 +#: utils/adt/arrayfuncs.c:2255 #, c-format msgid "cannot assign null value to an element of a fixed-length array" msgstr "고정 길이 배열의 요소에 null 값을 지정할 수 없음" -#: utils/adt/arrayfuncs.c:2858 +#: utils/adt/arrayfuncs.c:2855 #, c-format msgid "updates on slices of fixed-length arrays not implemented" msgstr "고정된 크기의 배열의 조각을 업데이트 하는 기능은 구현되지 않았습니다." -#: utils/adt/arrayfuncs.c:2889 +#: utils/adt/arrayfuncs.c:2886 #, c-format msgid "array slice subscript must provide both boundaries" msgstr "배열 나누기 서브스크립트는 반드시 둘다 범위안에 있어야 합니다" -#: utils/adt/arrayfuncs.c:2890 +#: utils/adt/arrayfuncs.c:2887 #, c-format msgid "" "When assigning to a slice of an empty array value, slice boundaries must be " "fully specified." msgstr "빈 배열 대상으로 자르기를 할 때는 자르기 범위가 전체여야 합니다." -#: utils/adt/arrayfuncs.c:2901 utils/adt/arrayfuncs.c:2997 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "원본 배열이 너무 작습니다." -#: utils/adt/arrayfuncs.c:3637 +#: utils/adt/arrayfuncs.c:3657 #, c-format msgid "null array element not allowed in this context" msgstr "이 구문에서는 배열의 null 요소를 허용하지 않습니다" -#: utils/adt/arrayfuncs.c:3808 utils/adt/arrayfuncs.c:3979 -#: utils/adt/arrayfuncs.c:4370 +#: utils/adt/arrayfuncs.c:3828 utils/adt/arrayfuncs.c:3999 +#: utils/adt/arrayfuncs.c:4390 #, c-format msgid "cannot compare arrays of different element types" msgstr "배열 요소 자료형이 서로 틀린 배열은 비교할 수 없습니다." -#: utils/adt/arrayfuncs.c:4157 utils/adt/multirangetypes.c:2806 -#: utils/adt/multirangetypes.c:2878 utils/adt/rangetypes.c:1354 -#: utils/adt/rangetypes.c:1418 utils/adt/rowtypes.c:1885 +#: utils/adt/arrayfuncs.c:4177 utils/adt/multirangetypes.c:2805 +#: utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 +#: utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 #, c-format msgid "could not identify a hash function for type %s" msgstr "%s 자료형에서 사용할 해시 함수를 찾을 수 없습니다." -#: utils/adt/arrayfuncs.c:4285 utils/adt/rowtypes.c:2006 +#: utils/adt/arrayfuncs.c:4305 utils/adt/rowtypes.c:1996 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "%s 자료형에서 사용할 확장된 해시 함수를 찾을 수 없습니다." -#: utils/adt/arrayfuncs.c:5480 +#: utils/adt/arrayfuncs.c:5506 #, c-format msgid "data type %s is not an array type" msgstr "%s 자료형은 배열이 아닙니다." -#: utils/adt/arrayfuncs.c:5535 +#: utils/adt/arrayfuncs.c:5561 #, c-format msgid "cannot accumulate null arrays" msgstr "null 배열을 누적할 수 없음" -#: utils/adt/arrayfuncs.c:5563 +#: utils/adt/arrayfuncs.c:5589 #, c-format msgid "cannot accumulate empty arrays" msgstr "빈 배열을 누적할 수 없음" -#: utils/adt/arrayfuncs.c:5964 utils/adt/arrayfuncs.c:6004 +#: utils/adt/arrayfuncs.c:5990 utils/adt/arrayfuncs.c:6030 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "차원 배열 또는 하한 배열은 NULL일 수 없음" -#: utils/adt/arrayfuncs.c:6067 utils/adt/arrayfuncs.c:6093 +#: utils/adt/arrayfuncs.c:6093 utils/adt/arrayfuncs.c:6119 #, c-format msgid "Dimension array must be one dimensional." msgstr "차원 배열은 일차원 배열이어야 합니다." -#: utils/adt/arrayfuncs.c:6072 utils/adt/arrayfuncs.c:6098 +#: utils/adt/arrayfuncs.c:6098 utils/adt/arrayfuncs.c:6124 #, c-format msgid "dimension values cannot be null" msgstr "차원 값은 null일 수 없음" -#: utils/adt/arrayfuncs.c:6104 +#: utils/adt/arrayfuncs.c:6130 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "하한 배열의 크기가 차원 배열과 다릅니다." -#: utils/adt/arrayfuncs.c:6382 +#: utils/adt/arrayfuncs.c:6411 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "다차원 배열에서 요소 삭제기능은 지원되지 않음" -#: utils/adt/arrayfuncs.c:6659 +#: utils/adt/arrayfuncs.c:6688 #, c-format msgid "thresholds must be one-dimensional array" msgstr "threshold 값은 1차원 배열이어야 합니다." -#: utils/adt/arrayfuncs.c:6664 +#: utils/adt/arrayfuncs.c:6693 #, c-format msgid "thresholds array must not contain NULLs" msgstr "threshold 배열에는 null이 포함되지 않아야 함" -#: utils/adt/arrayfuncs.c:6897 +#: utils/adt/arrayfuncs.c:6926 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "요소 자름 수는 0부터 %d까지입니다" @@ -25225,22 +26343,22 @@ msgstr "배열 요소 번호는 정수형이어야 합니다." msgid "array subscript in assignment must not be null" msgstr "배열 요소 지정하는 번호값으로 null 값을 사용할 수 없습니다" -#: utils/adt/arrayutils.c:161 +#: utils/adt/arrayutils.c:140 #, c-format msgid "array lower bound is too large: %d" msgstr "배열 lower bound가 너무 큽니다: %d" -#: utils/adt/arrayutils.c:263 +#: utils/adt/arrayutils.c:242 #, c-format msgid "typmod array must be type cstring[]" msgstr "typmod 배열은 cstring[] 형식이어야 함" -#: utils/adt/arrayutils.c:268 +#: utils/adt/arrayutils.c:247 #, c-format msgid "typmod array must be one-dimensional" msgstr "typmod 배열은 일차원 배열이어야 함" -#: utils/adt/arrayutils.c:273 +#: utils/adt/arrayutils.c:252 #, c-format msgid "typmod array must not contain nulls" msgstr "typmod 배열에는 null이 포함되지 않아야 함" @@ -25251,48 +26369,52 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "%s 인코딩을 ASCII 인코딩으로의 변환은 지원하지 않습니다." #. translator: first %s is inet or cidr -#: utils/adt/bool.c:153 utils/adt/cash.c:277 utils/adt/datetime.c:4017 -#: utils/adt/float.c:206 utils/adt/float.c:293 utils/adt/float.c:307 -#: utils/adt/float.c:412 utils/adt/float.c:495 utils/adt/float.c:509 +#: utils/adt/bool.c:149 utils/adt/cash.c:354 utils/adt/datetime.c:4142 +#: utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 +#: utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 #: utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 #: utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 #: utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 #: utils/adt/geo_ops.c:4672 utils/adt/int.c:174 utils/adt/int.c:186 -#: utils/adt/jsonpath.c:183 utils/adt/mac.c:94 utils/adt/mac8.c:225 -#: utils/adt/network.c:99 utils/adt/numeric.c:795 utils/adt/numeric.c:7136 -#: utils/adt/numeric.c:7339 utils/adt/numeric.c:8286 utils/adt/numutils.c:357 -#: utils/adt/numutils.c:619 utils/adt/numutils.c:881 utils/adt/numutils.c:920 -#: utils/adt/numutils.c:942 utils/adt/numutils.c:1006 utils/adt/numutils.c:1028 -#: utils/adt/pg_lsn.c:74 utils/adt/tid.c:72 utils/adt/tid.c:80 -#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:494 -#: utils/adt/uuid.c:135 utils/adt/xid8funcs.c:354 +#: utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 +#: utils/adt/network.c:99 utils/adt/numeric.c:803 utils/adt/numeric.c:7221 +#: utils/adt/numeric.c:7424 utils/adt/numeric.c:8371 utils/adt/numutils.c:356 +#: utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 +#: utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 +#: utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 +#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:510 +#: utils/adt/uuid.c:140 utils/adt/xid8funcs.c:360 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "%s 자료형 대한 잘못된 입력: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 -#: utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:351 -#: utils/adt/numutils.c:613 utils/adt/numutils.c:875 utils/adt/numutils.c:926 -#: utils/adt/numutils.c:965 utils/adt/numutils.c:1012 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 +#: utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "입력한 \"%s\" 값은 %s 자료형 범위를 초과했습니다" +msgid "money out of range" +msgstr "money 자료형 값 범위를 벗어남" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 -#: utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 -#: utils/adt/float.c:105 utils/adt/int.c:843 utils/adt/int.c:959 -#: utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 -#: utils/adt/int.c:1167 utils/adt/int8.c:515 utils/adt/int8.c:573 -#: utils/adt/int8.c:943 utils/adt/int8.c:1023 utils/adt/int8.c:1085 -#: utils/adt/int8.c:1165 utils/adt/numeric.c:3175 utils/adt/numeric.c:3198 -#: utils/adt/numeric.c:3283 utils/adt/numeric.c:3301 utils/adt/numeric.c:3397 -#: utils/adt/numeric.c:8835 utils/adt/numeric.c:9148 utils/adt/numeric.c:9496 -#: utils/adt/numeric.c:9612 utils/adt/numeric.c:11122 -#: utils/adt/timestamp.c:3406 +#: utils/adt/cash.c:161 utils/adt/cash.c:723 utils/adt/float.c:99 +#: utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 +#: utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 +#: utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 +#: utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 +#: utils/adt/numeric.c:3191 utils/adt/numeric.c:3214 utils/adt/numeric.c:3299 +#: utils/adt/numeric.c:3317 utils/adt/numeric.c:3413 utils/adt/numeric.c:8920 +#: utils/adt/numeric.c:9233 utils/adt/numeric.c:9581 utils/adt/numeric.c:9697 +#: utils/adt/numeric.c:11208 utils/adt/timestamp.c:3713 #, c-format msgid "division by zero" msgstr "0으로는 나눌수 없습니다." +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 +#: utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 +#: utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 +#: utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "입력한 \"%s\" 값은 %s 자료형 범위를 초과했습니다" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -25303,161 +26425,189 @@ msgstr "\"char\" 범위를 벗어났습니다." msgid "could not compute %s hash: %s" msgstr "%s 해시 계산 실패: %s" -#: utils/adt/date.c:63 utils/adt/timestamp.c:100 utils/adt/varbit.c:105 -#: utils/adt/varchar.c:49 +#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 +#: utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "잘못된 자료형 한정자" -#: utils/adt/date.c:75 +#: utils/adt/date.c:76 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "TIME(%d)%s 정밀도로 음수를 사용할 수 없습니다" -#: utils/adt/date.c:81 +#: utils/adt/date.c:82 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "TIME(%d)%s 정밀도는 최대값(%d)으로 줄였습니다" -#: utils/adt/date.c:166 utils/adt/date.c:174 utils/adt/formatting.c:4241 -#: utils/adt/formatting.c:4250 utils/adt/formatting.c:4363 -#: utils/adt/formatting.c:4373 +#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 +#: utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 +#: utils/adt/formatting.c:4548 #, c-format msgid "date out of range: \"%s\"" msgstr "날짜 범위가 벗어났음: \"%s\"" -#: utils/adt/date.c:221 utils/adt/date.c:519 utils/adt/date.c:543 -#: utils/adt/rangetypes.c:1577 utils/adt/rangetypes.c:1592 utils/adt/xml.c:2460 +#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 +#: utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "날짜가 범위를 벗어남" -#: utils/adt/date.c:267 utils/adt/timestamp.c:582 +#: utils/adt/date.c:268 utils/adt/timestamp.c:598 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "날짜 필드의 값이 범위를 벗어남: %d-%02d-%02d" -#: utils/adt/date.c:274 utils/adt/date.c:283 utils/adt/timestamp.c:588 +#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "날짜 범위가 벗어났음: %d-%02d-%02d" -#: utils/adt/date.c:494 +#: utils/adt/date.c:495 #, c-format msgid "cannot subtract infinite dates" msgstr "무한 날짜를 뺄 수 없음" -#: utils/adt/date.c:592 utils/adt/date.c:655 utils/adt/date.c:691 -#: utils/adt/date.c:2885 utils/adt/date.c:2895 +#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 +#: utils/adt/date.c:2906 utils/adt/date.c:2916 #, c-format msgid "date out of range for timestamp" msgstr "날짜가 타임스탬프 범위를 벗어남" -#: utils/adt/date.c:1121 utils/adt/date.c:1204 utils/adt/date.c:1220 -#: utils/adt/date.c:2206 utils/adt/date.c:2990 utils/adt/timestamp.c:4097 -#: utils/adt/timestamp.c:4290 utils/adt/timestamp.c:4432 -#: utils/adt/timestamp.c:4685 utils/adt/timestamp.c:4886 -#: utils/adt/timestamp.c:4933 utils/adt/timestamp.c:5157 -#: utils/adt/timestamp.c:5204 utils/adt/timestamp.c:5334 +#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 +#: utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 +#: utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 +#: utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 +#: utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 +#: utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 +#: utils/adt/timestamp.c:6070 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "\"%s\" 단위는 %s 자료형의 값 단위로 지원하지 않음" -#: utils/adt/date.c:1229 utils/adt/date.c:2222 utils/adt/date.c:3010 -#: utils/adt/timestamp.c:4111 utils/adt/timestamp.c:4307 -#: utils/adt/timestamp.c:4446 utils/adt/timestamp.c:4645 -#: utils/adt/timestamp.c:4942 utils/adt/timestamp.c:5213 -#: utils/adt/timestamp.c:5395 +#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 +#: utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 +#: utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 +#: utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 +#: utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "\"%s\" 는 %s 자료형의 단위로 인식될 수 없음" -#: utils/adt/date.c:1313 utils/adt/date.c:1359 utils/adt/date.c:1918 -#: utils/adt/date.c:1949 utils/adt/date.c:1978 utils/adt/date.c:2848 -#: utils/adt/date.c:3080 utils/adt/datetime.c:424 utils/adt/datetime.c:1809 -#: utils/adt/formatting.c:4081 utils/adt/formatting.c:4117 -#: utils/adt/formatting.c:4210 utils/adt/formatting.c:4339 utils/adt/json.c:467 -#: utils/adt/json.c:506 utils/adt/timestamp.c:232 utils/adt/timestamp.c:264 -#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:709 -#: utils/adt/timestamp.c:787 utils/adt/timestamp.c:820 -#: utils/adt/timestamp.c:2933 utils/adt/timestamp.c:2954 -#: utils/adt/timestamp.c:2967 utils/adt/timestamp.c:2976 -#: utils/adt/timestamp.c:2984 utils/adt/timestamp.c:3045 -#: utils/adt/timestamp.c:3068 utils/adt/timestamp.c:3081 -#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3100 -#: utils/adt/timestamp.c:3801 utils/adt/timestamp.c:3925 -#: utils/adt/timestamp.c:4015 utils/adt/timestamp.c:4105 -#: utils/adt/timestamp.c:4198 utils/adt/timestamp.c:4301 -#: utils/adt/timestamp.c:4750 utils/adt/timestamp.c:5024 -#: utils/adt/timestamp.c:5463 utils/adt/timestamp.c:5473 -#: utils/adt/timestamp.c:5478 utils/adt/timestamp.c:5484 -#: utils/adt/timestamp.c:5517 utils/adt/timestamp.c:5604 -#: utils/adt/timestamp.c:5645 utils/adt/timestamp.c:5649 -#: utils/adt/timestamp.c:5703 utils/adt/timestamp.c:5707 -#: utils/adt/timestamp.c:5713 utils/adt/timestamp.c:5747 utils/adt/xml.c:2482 -#: utils/adt/xml.c:2489 utils/adt/xml.c:2509 utils/adt/xml.c:2516 +#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 +#: utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 +#: utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 +#: utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 +#: utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 +#: utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 +#: utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 +#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 +#: utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 +#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 +#: utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 +#: utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 +#: utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 +#: utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 +#: utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 +#: utils/adt/timestamp.c:3266 utils/adt/timestamp.c:3279 +#: utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 +#: utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 +#: utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 +#: utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 +#: utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 +#: utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 +#: utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 +#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 +#: utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 +#: utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 +#: utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 +#: utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2574 +#: utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "타임스탬프 범위를 벗어남" -#: utils/adt/date.c:1535 utils/adt/date.c:2343 utils/adt/formatting.c:4431 +#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 #, c-format msgid "time out of range" msgstr "시간 범위를 벗어남" -#: utils/adt/date.c:1587 utils/adt/timestamp.c:597 +#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "시간 필드의 값이 범위를 벗어남: %d:%02d:%02g" -#: utils/adt/date.c:2107 utils/adt/date.c:2647 utils/adt/float.c:1042 -#: utils/adt/float.c:1118 utils/adt/int.c:635 utils/adt/int.c:682 -#: utils/adt/int.c:717 utils/adt/int8.c:414 utils/adt/numeric.c:2579 -#: utils/adt/timestamp.c:3455 utils/adt/timestamp.c:3482 -#: utils/adt/timestamp.c:3513 +#: utils/adt/date.c:2020 +#, c-format +msgid "cannot convert infinite interval to time" +msgstr "infinite interval 자료형은 time 자료형으로 변환할 수 없음" + +#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#, c-format +msgid "cannot add infinite interval to time" +msgstr "infinite interval 자료형 + time 자료형 계산은 할 수 없음" + +#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#, c-format +msgid "cannot subtract infinite interval from time" +msgstr "infinite interval 자료형 - 시간 자료형 계산은 할 수 없음" + +#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 +#: utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 +#: utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2595 +#: utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 +#: utils/adt/timestamp.c:3888 #, c-format msgid "invalid preceding or following size in window function" msgstr "윈도우 함수에서 앞에 오거나 뒤에 따라오는 크기가 잘못됨" -#: utils/adt/date.c:2351 +#: utils/adt/date.c:2360 #, c-format msgid "time zone displacement out of range" msgstr "타임 존 변위가 범위를 벗어남" -#: utils/adt/date.c:3110 utils/adt/timestamp.c:5506 utils/adt/timestamp.c:5736 +#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#, c-format +msgid "interval time zone \"%s\" must be finite" +msgstr "" +"\"%s\" 시간대 간격(interval time zone) 값은 유한해야 함" + +#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "" "\"%s\" 시간대 간격(interval time zone) 값으로 달(month) 또는 일(day)을 포함" "할 수 없습니다" -#: utils/adt/datetime.c:3223 utils/adt/datetime.c:4002 -#: utils/adt/datetime.c:4008 utils/adt/timestamp.c:512 +#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 +#: utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 #, c-format msgid "time zone \"%s\" not recognized" msgstr "\"%s\" 이름의 시간대는 없습니다." -#: utils/adt/datetime.c:3976 utils/adt/datetime.c:3983 +#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "날짜/시간 필드의 값이 범위를 벗어남: \"%s\"" -#: utils/adt/datetime.c:3985 +#: utils/adt/datetime.c:4110 #, c-format msgid "Perhaps you need a different \"datestyle\" setting." msgstr "날짜 표현 방식(\"datestyle\")을 다른 것으로 사용하고 있는 듯 합니다." -#: utils/adt/datetime.c:3990 +#: utils/adt/datetime.c:4115 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "interval 필드의 값이 범위를 벗어남: \"%s\"" -#: utils/adt/datetime.c:3996 +#: utils/adt/datetime.c:4121 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "표준시간대 범위를 벗어남: \"%s\"" -#: utils/adt/datetime.c:4010 +#: utils/adt/datetime.c:4135 #, c-format msgid "" "This time zone name appears in the configuration file for time zone " @@ -25470,24 +26620,24 @@ msgstr "" msgid "invalid Datum pointer" msgstr "잘못된 Datum 포인터" -#: utils/adt/dbsize.c:761 utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:764 utils/adt/dbsize.c:840 #, c-format msgid "invalid size: \"%s\"" msgstr "잘못된 크기: \"%s\"" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:841 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "잘못된 크기 단위: \"%s\"" -#: utils/adt/dbsize.c:839 +#: utils/adt/dbsize.c:842 #, c-format msgid "" "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." msgstr "" "유효한 단위는 \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", \"PB\"입니다." -#: utils/adt/domains.c:92 +#: utils/adt/domains.c:95 #, c-format msgid "type %s is not a domain" msgstr "%s 자료형은 도메인이 아닙니다" @@ -25537,10 +26687,10 @@ msgstr "base64 마침 조합이 잘못되었음" msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "입력값에 여백 처리값이 빠졌거나, 자료가 손상되었습니다." -#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:648 -#: utils/adt/varlena.c:331 utils/adt/varlena.c:372 jsonpath_gram.y:528 -#: jsonpath_scan.l:629 jsonpath_scan.l:640 jsonpath_scan.l:650 -#: jsonpath_scan.l:701 +#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:659 +#: utils/adt/varlena.c:333 utils/adt/varlena.c:374 jsonpath_gram.y:266 +#: jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 +#: jsonpath_scan.l:661 jsonpath_scan.l:712 #, c-format msgid "invalid input syntax for type %s" msgstr "%s 자료형에 대한 잘못된 입력 구문" @@ -25577,357 +26727,352 @@ msgstr "실제 열거형의 자료형을 확인할 수 없음" msgid "enum %s contains no values" msgstr "\"%s\" 열거형 자료에 값이 없음" -#: utils/adt/float.c:89 +#: utils/adt/float.c:83 #, c-format msgid "value out of range: overflow" msgstr "값이 범위를 벗어남: 오버플로" -#: utils/adt/float.c:97 +#: utils/adt/float.c:91 #, c-format msgid "value out of range: underflow" msgstr "값이 범위를 벗어남: 언더플로" -#: utils/adt/float.c:286 +#: utils/adt/float.c:280 #, c-format msgid "\"%s\" is out of range for type real" msgstr "\"%s\"는 real 자료형의 범위를 벗어납니다." -#: utils/adt/float.c:488 +#: utils/adt/float.c:482 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "\"%s\"는 double precision 자료형의 범위를 벗어납니다." -#: utils/adt/float.c:1253 utils/adt/float.c:1327 utils/adt/int.c:355 +#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 #: utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 #: utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 -#: utils/adt/int8.c:1278 utils/adt/numeric.c:4500 utils/adt/numeric.c:4505 +#: utils/adt/int8.c:1277 utils/adt/numeric.c:4593 utils/adt/numeric.c:4598 #, c-format msgid "smallint out of range" msgstr "smallint의 범위를 벗어났습니다." -#: utils/adt/float.c:1453 utils/adt/numeric.c:3693 utils/adt/numeric.c:10027 +#: utils/adt/float.c:1447 utils/adt/numeric.c:3709 utils/adt/numeric.c:10112 #, c-format msgid "cannot take square root of a negative number" msgstr "음수의 제곱근을 구할 수 없습니다." -#: utils/adt/float.c:1521 utils/adt/numeric.c:3981 utils/adt/numeric.c:4093 +#: utils/adt/float.c:1515 utils/adt/numeric.c:3997 utils/adt/numeric.c:4109 #, c-format msgid "zero raised to a negative power is undefined" msgstr "0의 음수 거듭제곱이 정의되어 있지 않음" -#: utils/adt/float.c:1525 utils/adt/numeric.c:3985 utils/adt/numeric.c:10918 +#: utils/adt/float.c:1519 utils/adt/numeric.c:4001 utils/adt/numeric.c:11003 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "음수의 비정수 거듭제곱을 계산하면 복잡한 결과가 생성됨" -#: utils/adt/float.c:1701 utils/adt/float.c:1734 utils/adt/numeric.c:3893 -#: utils/adt/numeric.c:10698 +#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3909 +#: utils/adt/numeric.c:10783 #, c-format msgid "cannot take logarithm of zero" msgstr "0의 대수를 구할 수 없습니다." -#: utils/adt/float.c:1705 utils/adt/float.c:1738 utils/adt/numeric.c:3831 -#: utils/adt/numeric.c:3888 utils/adt/numeric.c:10702 +#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3847 +#: utils/adt/numeric.c:3904 utils/adt/numeric.c:10787 #, c-format msgid "cannot take logarithm of a negative number" msgstr "음수의 대수를 구할 수 없습니다." -#: utils/adt/float.c:1771 utils/adt/float.c:1802 utils/adt/float.c:1897 -#: utils/adt/float.c:1924 utils/adt/float.c:1952 utils/adt/float.c:1979 -#: utils/adt/float.c:2126 utils/adt/float.c:2163 utils/adt/float.c:2333 -#: utils/adt/float.c:2389 utils/adt/float.c:2454 utils/adt/float.c:2511 -#: utils/adt/float.c:2702 utils/adt/float.c:2726 +#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 +#: utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 +#: utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 +#: utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 +#: utils/adt/float.c:2696 utils/adt/float.c:2720 #, c-format msgid "input is out of range" msgstr "입력값이 범위를 벗어났습니다." -#: utils/adt/float.c:2867 -#, c-format -msgid "setseed parameter %g is out of allowed range [-1,1]" -msgstr "%g setseed 매개 변수가 [-1,1] 범위를 벗어났습니다." - -#: utils/adt/float.c:4095 utils/adt/numeric.c:1841 +#: utils/adt/float.c:4000 utils/adt/numeric.c:1857 #, c-format msgid "count must be greater than zero" msgstr "카운트 값은 0 보다 커야 합니다" -#: utils/adt/float.c:4100 utils/adt/numeric.c:1852 +#: utils/adt/float.c:4005 utils/adt/numeric.c:1868 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "피연산자, 하한 및 상한은 NaN일 수 없음" -#: utils/adt/float.c:4106 utils/adt/numeric.c:1857 +#: utils/adt/float.c:4011 utils/adt/numeric.c:1873 #, c-format msgid "lower and upper bounds must be finite" msgstr "하한 및 상한은 유한한 값이어야 함" -#: utils/adt/float.c:4172 utils/adt/numeric.c:1871 +#: utils/adt/float.c:4077 utils/adt/numeric.c:1887 #, c-format msgid "lower bound cannot equal upper bound" msgstr "하한값은 상한값과 같을 수 없습니다" -#: utils/adt/formatting.c:519 +#: utils/adt/formatting.c:530 #, c-format msgid "invalid format specification for an interval value" msgstr "간격 값에 대한 형식 지정이 잘못됨" -#: utils/adt/formatting.c:520 +#: utils/adt/formatting.c:531 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "간격이 특정 달력 날짜에 연결되어 있지 않습니다." -#: utils/adt/formatting.c:1150 +#: utils/adt/formatting.c:1161 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\"는 사용된 마지막 패턴이어야 합니다." -#: utils/adt/formatting.c:1158 +#: utils/adt/formatting.c:1169 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\"는 \"PR\" 앞에 있어야 합니다." -#: utils/adt/formatting.c:1174 +#: utils/adt/formatting.c:1185 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\"은 \"PR\" 앞에 있어야 합니다." -#: utils/adt/formatting.c:1201 +#: utils/adt/formatting.c:1212 #, c-format msgid "multiple decimal points" msgstr "소숫점이 여러개 있습니다." -#: utils/adt/formatting.c:1205 utils/adt/formatting.c:1288 +#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "\"V\" 와 소숫점을 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1217 +#: utils/adt/formatting.c:1228 #, c-format msgid "cannot use \"S\" twice" msgstr "\"S\"를 두 번 사용할 수 없음" -#: utils/adt/formatting.c:1221 +#: utils/adt/formatting.c:1232 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "\"S\" 와 \"PL\"/\"MI\"/\"SG\"/\"PR\" 를 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1241 +#: utils/adt/formatting.c:1252 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "\"S\" 와 \"MI\" 를 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1251 +#: utils/adt/formatting.c:1262 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "\"S\" 와 \"PL\" 를 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1261 +#: utils/adt/formatting.c:1272 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "\"S\" 와 \"SG\" 를 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1270 +#: utils/adt/formatting.c:1281 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "\"PR\" 와 \"S\"/\"PL\"/\"MI\"/\"SG\" 를 함께 쓸 수 없습니다." -#: utils/adt/formatting.c:1296 +#: utils/adt/formatting.c:1307 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "\"EEEE\"를 두 번 사용할 수 없음" -#: utils/adt/formatting.c:1302 +#: utils/adt/formatting.c:1313 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "\"EEEE\"는 다른 포맷과 호환하지 않습니다" -#: utils/adt/formatting.c:1303 +#: utils/adt/formatting.c:1314 #, c-format msgid "" "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "\"EEEE\"는 숫자와 소수점 패턴, 이 두 형식과 함께 사용되어야 합니다." -#: utils/adt/formatting.c:1387 +#: utils/adt/formatting.c:1398 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "잘못된 datetime 양식 구분자: \"%s\"" -#: utils/adt/formatting.c:1514 +#: utils/adt/formatting.c:1525 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\"는 숫자가 아닙니다." -#: utils/adt/formatting.c:1592 +#: utils/adt/formatting.c:1603 #, c-format msgid "case conversion failed: %s" msgstr "잘못된 형 변환 규칙: %s" -#: utils/adt/formatting.c:1646 utils/adt/formatting.c:1768 -#: utils/adt/formatting.c:1891 +#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 +#: utils/adt/formatting.c:1989 #, c-format msgid "could not determine which collation to use for %s function" msgstr "%s 함수에서 사용할 정렬규칙(collation)을 결정할 수 없음" -#: utils/adt/formatting.c:2274 +#: utils/adt/formatting.c:2410 #, c-format msgid "invalid combination of date conventions" msgstr "날짜 변환을 위한 잘못된 조합" -#: utils/adt/formatting.c:2275 +#: utils/adt/formatting.c:2411 #, c-format msgid "" "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr "" "형식 템플릿에 그레고리오력과 ISO week date 변환을 함께 사용하지 마십시오." -#: utils/adt/formatting.c:2297 +#: utils/adt/formatting.c:2433 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "형식 문자열에서 \"%s\" 필드의 값이 충돌함" -#: utils/adt/formatting.c:2299 +#: utils/adt/formatting.c:2435 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "이 값은 동일한 필드 형식의 이전 설정과 모순됩니다." -#: utils/adt/formatting.c:2366 +#: utils/adt/formatting.c:2502 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "소스 문자열이 너무 짧아서 \"%s\" 형식 필드에 사용할 수 없음" -#: utils/adt/formatting.c:2368 +#: utils/adt/formatting.c:2504 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "필드에 %d자가 필요한데 %d자만 남았습니다." -#: utils/adt/formatting.c:2370 utils/adt/formatting.c:2384 +#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 #, c-format msgid "" "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "소스 문자열이 고정 너비가 아닌 경우 \"FM\" 한정자를 사용해 보십시오." -#: utils/adt/formatting.c:2380 utils/adt/formatting.c:2393 -#: utils/adt/formatting.c:2614 +#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 +#: utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "\"%s\" 값은 \"%s\"에 유효하지 않음" -#: utils/adt/formatting.c:2382 +#: utils/adt/formatting.c:2518 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "필드에 %d자가 필요한데 %d자만 구문 분석할 수 있습니다." -#: utils/adt/formatting.c:2395 +#: utils/adt/formatting.c:2531 #, c-format msgid "Value must be an integer." msgstr "값은 정수여야 합니다." -#: utils/adt/formatting.c:2400 +#: utils/adt/formatting.c:2536 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "소스 문자열의 \"%s\" 값이 범위를 벗어남" -#: utils/adt/formatting.c:2402 +#: utils/adt/formatting.c:2538 #, c-format msgid "Value must be in the range %d to %d." msgstr "값은 %d에서 %d 사이의 범위에 있어야 합니다." -#: utils/adt/formatting.c:2616 +#: utils/adt/formatting.c:2752 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "지정된 값이 이 필드에 허용되는 값과 일치하지 않습니다." -#: utils/adt/formatting.c:2832 utils/adt/formatting.c:2852 -#: utils/adt/formatting.c:2872 utils/adt/formatting.c:2892 -#: utils/adt/formatting.c:2911 utils/adt/formatting.c:2930 -#: utils/adt/formatting.c:2954 utils/adt/formatting.c:2972 -#: utils/adt/formatting.c:2990 utils/adt/formatting.c:3008 -#: utils/adt/formatting.c:3025 utils/adt/formatting.c:3042 +#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 +#: utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 +#: utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 +#: utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 +#: utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 +#: utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 #, c-format msgid "localized string format value too long" msgstr "자국어화 문자열 포멧 값이 너무 깁니다" -#: utils/adt/formatting.c:3322 +#: utils/adt/formatting.c:3458 #, c-format msgid "unmatched format separator \"%c\"" msgstr "맞지 않는 구분자 포멧 \"%c\"" -#: utils/adt/formatting.c:3383 +#: utils/adt/formatting.c:3519 #, c-format msgid "unmatched format character \"%s\"" msgstr "짝이 안 맞는 \"%s\" 문자" -#: utils/adt/formatting.c:3491 +#: utils/adt/formatting.c:3652 #, c-format -msgid "formatting field \"%s\" is only supported in to_char" -msgstr "\"%s\" 필드 양식은 to_char 함수에서만 지원합니다." +msgid "Time zone abbreviation is not recognized." +msgstr "시간대 약어를 알 수 없습니다." -#: utils/adt/formatting.c:3665 +#: utils/adt/formatting.c:3853 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "\"Y,YYY\"에 대한 입력 문자열이 잘못됨" -#: utils/adt/formatting.c:3754 +#: utils/adt/formatting.c:3942 #, c-format msgid "input string is too short for datetime format" msgstr "입력 문자열이 datetime 양식용으로는 너무 짧습니다" -#: utils/adt/formatting.c:3762 +#: utils/adt/formatting.c:3950 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "날짜 및 시간 형식 후 입력 문자열에 남은 문자가 있습니다." -#: utils/adt/formatting.c:4319 +#: utils/adt/formatting.c:4494 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "timestamptz 자료형을 위한 입력 문자열에 시간대가 누락되었습니다." -#: utils/adt/formatting.c:4325 +#: utils/adt/formatting.c:4500 #, c-format msgid "timestamptz out of range" msgstr "timestamptz 범위를 벗어남" -#: utils/adt/formatting.c:4353 +#: utils/adt/formatting.c:4528 #, c-format msgid "datetime format is zoned but not timed" msgstr "datetime 양식이 지역시간대값이 있는데, 시간값이 아님" -#: utils/adt/formatting.c:4411 +#: utils/adt/formatting.c:4577 #, c-format msgid "missing time zone in input string for type timetz" msgstr "timetz 자료형을 위한 입력 문자열에 시간대가 누락되었습니다." -#: utils/adt/formatting.c:4417 +#: utils/adt/formatting.c:4583 #, c-format msgid "timetz out of range" msgstr "timetz 범위를 벗어남" -#: utils/adt/formatting.c:4443 +#: utils/adt/formatting.c:4609 #, c-format msgid "datetime format is not dated and not timed" msgstr "날짜시간 형식이 날짜도 아니고, 시간도 아닙니다." -#: utils/adt/formatting.c:4575 +#: utils/adt/formatting.c:4786 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "시간 \"%d\"은(는) 12시간제에 유효하지 않음" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4788 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "24시간제를 사용하거나 1에서 12 사이의 시간을 지정하십시오." -#: utils/adt/formatting.c:4689 +#: utils/adt/formatting.c:4900 #, c-format msgid "cannot calculate day of year without year information" msgstr "연도 정보 없이 몇번째 날(day of year) 인지 계산할 수 없습니다." -#: utils/adt/formatting.c:5621 +#: utils/adt/formatting.c:5852 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\" 입력 양식은 지원되지 않습니다." -#: utils/adt/formatting.c:5633 +#: utils/adt/formatting.c:5864 #, c-format msgid "\"RN\" not supported for input" msgstr "\"RN\" 입력 양식은 지원되지 않습니다." @@ -25959,12 +27104,7 @@ msgstr "\"%s\" 파일에서 seek 작업을 할 수 없음: %m" msgid "file length too large" msgstr "파일 길이가 너무 깁니다" -#: utils/adt/genfile.c:248 -#, c-format -msgid "must be superuser to read files with adminpack 1.0" -msgstr "adminpack 1.0 확장 모듈을 사용할 때는 파일을 읽으려면 슈퍼유져여야함" - -#: utils/adt/genfile.c:702 +#: utils/adt/genfile.c:656 #, c-format msgid "tablespace with OID %u does not exist" msgstr "OID %u 테이블스페이스 없음" @@ -26020,295 +27160,295 @@ msgstr "적어도 2개의 point들이 필요합니다." msgid "invalid int2vector data" msgstr "잘못된 int2vector 자료" -#: utils/adt/int.c:1529 utils/adt/int8.c:1404 utils/adt/numeric.c:1749 -#: utils/adt/timestamp.c:5797 utils/adt/timestamp.c:5879 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1765 +#: utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 #, c-format msgid "step size cannot equal zero" msgstr "단계 크기는 0일 수 없음" -#: utils/adt/int8.c:449 utils/adt/int8.c:472 utils/adt/int8.c:486 -#: utils/adt/int8.c:500 utils/adt/int8.c:531 utils/adt/int8.c:555 -#: utils/adt/int8.c:637 utils/adt/int8.c:705 utils/adt/int8.c:711 -#: utils/adt/int8.c:737 utils/adt/int8.c:751 utils/adt/int8.c:775 -#: utils/adt/int8.c:788 utils/adt/int8.c:900 utils/adt/int8.c:914 -#: utils/adt/int8.c:928 utils/adt/int8.c:959 utils/adt/int8.c:981 -#: utils/adt/int8.c:995 utils/adt/int8.c:1009 utils/adt/int8.c:1042 -#: utils/adt/int8.c:1056 utils/adt/int8.c:1070 utils/adt/int8.c:1101 -#: utils/adt/int8.c:1123 utils/adt/int8.c:1137 utils/adt/int8.c:1151 -#: utils/adt/int8.c:1313 utils/adt/int8.c:1348 utils/adt/numeric.c:4459 -#: utils/adt/rangetypes.c:1528 utils/adt/rangetypes.c:1541 +#: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 +#: utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 +#: utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 +#: utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 +#: utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 +#: utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 +#: utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 +#: utils/adt/int8.c:1055 utils/adt/int8.c:1069 utils/adt/int8.c:1100 +#: utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 +#: utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4542 +#: utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 #: utils/adt/varbit.c:1676 #, c-format msgid "bigint out of range" msgstr "bigint의 범위를 벗어났습니다." -#: utils/adt/int8.c:1361 +#: utils/adt/int8.c:1360 #, c-format msgid "OID out of range" msgstr "OID의 범위를 벗어났습니다." -#: utils/adt/json.c:320 utils/adt/jsonb.c:781 +#: utils/adt/json.c:202 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "" "키 값은 스칼라 형이어야 함. 배열, 복합 자료형, json 형은 사용할 수 없음" -#: utils/adt/json.c:1113 utils/adt/json.c:1123 utils/fmgr/funcapi.c:2082 +#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "%d번째 인자의 자료형을 알수가 없습니다." -#: utils/adt/json.c:1146 utils/adt/json.c:1337 utils/adt/json.c:1513 -#: utils/adt/json.c:1591 utils/adt/jsonb.c:1432 utils/adt/jsonb.c:1522 +#: utils/adt/json.c:1067 utils/adt/json.c:1266 utils/adt/json.c:1449 +#: utils/adt/json.c:1527 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "개체 키 값으로 null 을 허용하지 않음" -#: utils/adt/json.c:1189 utils/adt/json.c:1352 +#: utils/adt/json.c:1117 utils/adt/json.c:1288 #, c-format msgid "duplicate JSON object key value: %s" msgstr "JSON 객체 키 값 중복: %s" -#: utils/adt/json.c:1297 utils/adt/jsonb.c:1233 +#: utils/adt/json.c:1226 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "인자 목록은 요소수의 짝수개여야 합니다." #. translator: %s is a SQL function name -#: utils/adt/json.c:1299 utils/adt/jsonb.c:1235 +#: utils/adt/json.c:1228 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "%s 함수의 인자들은 각각 key, value 쌍으로 있어야 합니다." -#: utils/adt/json.c:1491 utils/adt/jsonb.c:1410 +#: utils/adt/json.c:1427 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "배열은 두개의 칼럼이어야 함" -#: utils/adt/json.c:1580 utils/adt/jsonb.c:1511 +#: utils/adt/json.c:1516 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "배열 차수가 안맞음" -#: utils/adt/json.c:1764 utils/adt/jsonb_util.c:1958 +#: utils/adt/json.c:1702 utils/adt/jsonb_util.c:1956 #, c-format msgid "duplicate JSON object key value" msgstr "JSON 객체 키 값 중복" -#: utils/adt/jsonb.c:294 +#: utils/adt/jsonb.c:282 #, c-format msgid "string too long to represent as jsonb string" msgstr "jsonb 문자열로 길이를 초과함" -#: utils/adt/jsonb.c:295 +#: utils/adt/jsonb.c:283 #, c-format msgid "" "Due to an implementation restriction, jsonb strings cannot exceed %d bytes." msgstr "구현상 제한으로 jsonb 문자열은 %d 바이트를 넘을 수 없습니다." -#: utils/adt/jsonb.c:1252 +#: utils/adt/jsonb.c:1153 #, c-format msgid "argument %d: key must not be null" msgstr "%d 번째 인자: 키 값은 null이면 안됩니다." -#: utils/adt/jsonb.c:1843 +#: utils/adt/jsonb.c:1744 #, c-format msgid "field name must not be null" msgstr "필드 이름이 null 이면 안됩니다" -#: utils/adt/jsonb.c:1905 +#: utils/adt/jsonb.c:1806 #, c-format msgid "object keys must be strings" msgstr "개체 키는 문자열이어야 합니다" -#: utils/adt/jsonb.c:2116 +#: utils/adt/jsonb.c:2017 #, c-format msgid "cannot cast jsonb null to type %s" msgstr "jsonb null 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2117 +#: utils/adt/jsonb.c:2018 #, c-format msgid "cannot cast jsonb string to type %s" msgstr "jsonb 문자열 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2118 +#: utils/adt/jsonb.c:2019 #, c-format msgid "cannot cast jsonb numeric to type %s" msgstr "jsonb 숫자 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2119 +#: utils/adt/jsonb.c:2020 #, c-format msgid "cannot cast jsonb boolean to type %s" msgstr "jsonb 불리언 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2120 +#: utils/adt/jsonb.c:2021 #, c-format msgid "cannot cast jsonb array to type %s" msgstr "jsonb 배열 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2121 +#: utils/adt/jsonb.c:2022 #, c-format msgid "cannot cast jsonb object to type %s" msgstr "jsonb object 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb.c:2122 +#: utils/adt/jsonb.c:2023 #, c-format msgid "cannot cast jsonb array or object to type %s" msgstr "jsonb object나 배열 값을 %s 자료형으로 형 변환 할 수 없음" -#: utils/adt/jsonb_util.c:758 +#: utils/adt/jsonb_util.c:756 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "jsonb 개체 쌍의 개수가 최대치를 초과함 (%zu)" -#: utils/adt/jsonb_util.c:799 +#: utils/adt/jsonb_util.c:797 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "jsonb 배열 요소 개수가 최대치를 초과함 (%zu)" -#: utils/adt/jsonb_util.c:1673 utils/adt/jsonb_util.c:1693 +#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "jsonb 배열 요소 총 크기가 최대치를 초과함 (%d 바이트)" -#: utils/adt/jsonb_util.c:1754 utils/adt/jsonb_util.c:1789 -#: utils/adt/jsonb_util.c:1809 +#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 +#: utils/adt/jsonb_util.c:1807 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "jsonb 개체 요소들의 총 크기가 최대치를 초과함 (%d 바이트)" -#: utils/adt/jsonbsubs.c:70 utils/adt/jsonbsubs.c:151 +#: utils/adt/jsonbsubs.c:67 utils/adt/jsonbsubs.c:148 #, c-format msgid "jsonb subscript does not support slices" msgstr "jsonb 서브스크립트가 slice를 지원하지 않음" -#: utils/adt/jsonbsubs.c:103 utils/adt/jsonbsubs.c:117 +#: utils/adt/jsonbsubs.c:100 utils/adt/jsonbsubs.c:114 #, c-format msgid "subscript type %s is not supported" msgstr "%s 자료형은 서브스크립트를 지원하지 않음" -#: utils/adt/jsonbsubs.c:104 +#: utils/adt/jsonbsubs.c:101 #, c-format msgid "jsonb subscript must be coercible to only one type, integer or text." msgstr "jsonb 서브스크립트로는 숫자 또는 문자열 중 하나만 쓸 수 있음" -#: utils/adt/jsonbsubs.c:118 +#: utils/adt/jsonbsubs.c:115 #, c-format msgid "jsonb subscript must be coercible to either integer or text." msgstr "jsonb 서브스크립트로는 숫자 또는 문자열 중 하나만 쓸 수 있음" -#: utils/adt/jsonbsubs.c:139 +#: utils/adt/jsonbsubs.c:136 #, c-format msgid "jsonb subscript must have text type" msgstr "배열 서브스크립트는 반드시 문자열이어야합니다." -#: utils/adt/jsonbsubs.c:207 +#: utils/adt/jsonbsubs.c:204 #, c-format msgid "jsonb subscript in assignment must not be null" msgstr "jsonb 서브스크립트로 null 값이 올 수 없음" -#: utils/adt/jsonfuncs.c:572 utils/adt/jsonfuncs.c:821 -#: utils/adt/jsonfuncs.c:2429 utils/adt/jsonfuncs.c:2881 -#: utils/adt/jsonfuncs.c:3676 utils/adt/jsonfuncs.c:4018 +#: utils/adt/jsonfuncs.c:583 utils/adt/jsonfuncs.c:830 +#: utils/adt/jsonfuncs.c:2439 utils/adt/jsonfuncs.c:3015 +#: utils/adt/jsonfuncs.c:3948 utils/adt/jsonfuncs.c:4295 #, c-format msgid "cannot call %s on a scalar" msgstr "스칼라형에서는 %s 호출 할 수 없음" -#: utils/adt/jsonfuncs.c:577 utils/adt/jsonfuncs.c:806 -#: utils/adt/jsonfuncs.c:2883 utils/adt/jsonfuncs.c:3663 +#: utils/adt/jsonfuncs.c:588 utils/adt/jsonfuncs.c:815 +#: utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3935 #, c-format msgid "cannot call %s on an array" msgstr "배열형에서는 %s 호출 할 수 없음" -#: utils/adt/jsonfuncs.c:636 jsonpath_scan.l:596 +#: utils/adt/jsonfuncs.c:647 jsonpath_scan.l:607 #, c-format msgid "unsupported Unicode escape sequence" msgstr "지원하지 않는 유니코드 이스케이프 조합" -#: utils/adt/jsonfuncs.c:713 +#: utils/adt/jsonfuncs.c:724 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "JSON 자료, %d 번째 줄: %s%s%s" -#: utils/adt/jsonfuncs.c:1875 utils/adt/jsonfuncs.c:1912 +#: utils/adt/jsonfuncs.c:1883 utils/adt/jsonfuncs.c:1920 #, c-format msgid "cannot get array length of a scalar" msgstr "스칼라형의 배열 길이를 구할 수 없음" -#: utils/adt/jsonfuncs.c:1879 utils/adt/jsonfuncs.c:1898 +#: utils/adt/jsonfuncs.c:1887 utils/adt/jsonfuncs.c:1906 #, c-format msgid "cannot get array length of a non-array" msgstr "비배열형 자료의 배열 길이를 구할 수 없음" -#: utils/adt/jsonfuncs.c:1978 +#: utils/adt/jsonfuncs.c:1986 #, c-format msgid "cannot call %s on a non-object" msgstr "비개체형에서 %s 호출 할 수 없음" -#: utils/adt/jsonfuncs.c:2166 +#: utils/adt/jsonfuncs.c:2174 #, c-format msgid "cannot deconstruct an array as an object" msgstr "배열을 객체로 해체할 수 없음" -#: utils/adt/jsonfuncs.c:2180 +#: utils/adt/jsonfuncs.c:2188 #, c-format msgid "cannot deconstruct a scalar" msgstr "스칼라형으로 재구축할 수 없음" -#: utils/adt/jsonfuncs.c:2225 +#: utils/adt/jsonfuncs.c:2233 #, c-format msgid "cannot extract elements from a scalar" msgstr "스칼라형에서 요소를 추출할 수 없음" -#: utils/adt/jsonfuncs.c:2229 +#: utils/adt/jsonfuncs.c:2237 #, c-format msgid "cannot extract elements from an object" msgstr "개체형에서 요소를 추출할 수 없음" -#: utils/adt/jsonfuncs.c:2414 utils/adt/jsonfuncs.c:3896 +#: utils/adt/jsonfuncs.c:2424 utils/adt/jsonfuncs.c:4173 #, c-format msgid "cannot call %s on a non-array" msgstr "비배열형에서 %s 호출 할 수 없음" -#: utils/adt/jsonfuncs.c:2488 utils/adt/jsonfuncs.c:2493 -#: utils/adt/jsonfuncs.c:2510 utils/adt/jsonfuncs.c:2516 +#: utils/adt/jsonfuncs.c:2515 utils/adt/jsonfuncs.c:2520 +#: utils/adt/jsonfuncs.c:2538 utils/adt/jsonfuncs.c:2544 #, c-format msgid "expected JSON array" msgstr "예기치 않은 json 배열" -#: utils/adt/jsonfuncs.c:2489 +#: utils/adt/jsonfuncs.c:2516 #, c-format msgid "See the value of key \"%s\"." msgstr "\"%s\" 키의 값을 지정하세요" -#: utils/adt/jsonfuncs.c:2511 +#: utils/adt/jsonfuncs.c:2539 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "%s 배열 요소, 해당 키: \"%s\" 참조" -#: utils/adt/jsonfuncs.c:2517 +#: utils/adt/jsonfuncs.c:2545 #, c-format msgid "See the array element %s." msgstr "배열 요소: %s 참조" -#: utils/adt/jsonfuncs.c:2552 +#: utils/adt/jsonfuncs.c:2597 #, c-format msgid "malformed JSON array" msgstr "잘못된 json 배열" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3389 +#: utils/adt/jsonfuncs.c:3647 #, c-format msgid "first argument of %s must be a row type" msgstr "%s의 첫번째 인자는 row 형이어야 합니다" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3413 +#: utils/adt/jsonfuncs.c:3671 #, c-format msgid "could not determine row type for result of %s" msgstr "%s 함수의 반환 로우 자료형을 알수가 없음" -#: utils/adt/jsonfuncs.c:3415 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "" "Provide a non-null record argument, or call the function in the FROM clause " @@ -26317,52 +27457,52 @@ msgstr "" "non-null 레코드 인자를 지정하거나, 함수를 호출 할 때 FROM 절에서 칼럼 정의 목" "록도 함께 지정해야 합니다." -#: utils/adt/jsonfuncs.c:3785 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4059 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialize 모드가 필요합니다만, 이 구문에서는 허용되지 않습니다" -#: utils/adt/jsonfuncs.c:3913 utils/adt/jsonfuncs.c:3997 +#: utils/adt/jsonfuncs.c:4190 utils/adt/jsonfuncs.c:4274 #, c-format msgid "argument of %s must be an array of objects" msgstr "%s의 인자는 개체의 배열이어야 합니다" -#: utils/adt/jsonfuncs.c:3946 +#: utils/adt/jsonfuncs.c:4223 #, c-format msgid "cannot call %s on an object" msgstr "개체에서 %s 호출할 수 없음" -#: utils/adt/jsonfuncs.c:4380 utils/adt/jsonfuncs.c:4439 -#: utils/adt/jsonfuncs.c:4519 +#: utils/adt/jsonfuncs.c:4656 utils/adt/jsonfuncs.c:4715 +#: utils/adt/jsonfuncs.c:4795 #, c-format msgid "cannot delete from scalar" msgstr "스칼라형에서 삭제 할 수 없음" -#: utils/adt/jsonfuncs.c:4524 +#: utils/adt/jsonfuncs.c:4800 #, c-format msgid "cannot delete from object using integer index" msgstr "인덱스 번호를 사용해서 개체에서 삭제 할 수 없음" -#: utils/adt/jsonfuncs.c:4592 utils/adt/jsonfuncs.c:4751 +#: utils/adt/jsonfuncs.c:4868 utils/adt/jsonfuncs.c:5027 #, c-format msgid "cannot set path in scalar" msgstr "스칼라형에는 path 를 지정할 수 없음" -#: utils/adt/jsonfuncs.c:4633 utils/adt/jsonfuncs.c:4675 +#: utils/adt/jsonfuncs.c:4909 utils/adt/jsonfuncs.c:4951 #, c-format msgid "" "null_value_treatment must be \"delete_key\", \"return_target\", " "\"use_json_null\", or \"raise_exception\"" msgstr "" -"null_value_treatment 값은 \"delete_key\", \"return_target\", \"use_json_null" -"\" 또는 \"raise_exception\" 이어야 합니다." +"null_value_treatment 값은 \"delete_key\", \"return_target\", " +"\"use_json_null\" 또는 \"raise_exception\" 이어야 합니다." -#: utils/adt/jsonfuncs.c:4646 +#: utils/adt/jsonfuncs.c:4922 #, c-format msgid "JSON value must not be null" msgstr "JSON 값으로 null을 사용할 수 없음" -#: utils/adt/jsonfuncs.c:4647 +#: utils/adt/jsonfuncs.c:4923 #, c-format msgid "" "Exception was raised because null_value_treatment is \"raise_exception\"." @@ -26370,7 +27510,7 @@ msgstr "" "null_value_treatment 설정값이 \"raise_exception\"으로 되어 있어 예외를 일으켰" "습니다." -#: utils/adt/jsonfuncs.c:4648 +#: utils/adt/jsonfuncs.c:4924 #, c-format msgid "" "To avoid, either change the null_value_treatment argument or ensure that an " @@ -26379,231 +27519,335 @@ msgstr "" "이 상황을 피하려면, null_value_treatment 설정을 바꾸든지, SQL NULL 값을 사용" "하지 않아야 합니다." -#: utils/adt/jsonfuncs.c:4703 +#: utils/adt/jsonfuncs.c:4979 #, c-format msgid "cannot delete path in scalar" msgstr "스칼라형에서 path를 지울 수 없음" -#: utils/adt/jsonfuncs.c:4917 +#: utils/adt/jsonfuncs.c:5193 #, c-format msgid "path element at position %d is null" msgstr "%d 위치의 path 요소는 null 입니다." -#: utils/adt/jsonfuncs.c:4936 utils/adt/jsonfuncs.c:4967 -#: utils/adt/jsonfuncs.c:5040 +#: utils/adt/jsonfuncs.c:5212 utils/adt/jsonfuncs.c:5243 +#: utils/adt/jsonfuncs.c:5316 #, c-format msgid "cannot replace existing key" msgstr "이미 있는 키로는 대체할 수 없음" -#: utils/adt/jsonfuncs.c:4937 utils/adt/jsonfuncs.c:4968 +#: utils/adt/jsonfuncs.c:5213 utils/adt/jsonfuncs.c:5244 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "path assumes key는 복합 자료형인데, 스칼라 값이 사용되고 있습니다." -#: utils/adt/jsonfuncs.c:5041 +#: utils/adt/jsonfuncs.c:5317 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "키 값을 변경하려면, jsonb_set 함수를 사용하세요." -#: utils/adt/jsonfuncs.c:5145 +#: utils/adt/jsonfuncs.c:5421 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "%d 번째 위치의 path 요소는 정수가 아님: \"%s\"" -#: utils/adt/jsonfuncs.c:5162 +#: utils/adt/jsonfuncs.c:5438 #, c-format msgid "path element at position %d is out of range: %d" msgstr "%d 번째 위치의 path 요소는 범위를 벗어남: %d" -#: utils/adt/jsonfuncs.c:5314 +#: utils/adt/jsonfuncs.c:5590 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "잘못된 플래그 자료형, 배열이나, 스칼라 형만 허용합니다." -#: utils/adt/jsonfuncs.c:5321 +#: utils/adt/jsonfuncs.c:5597 #, c-format msgid "flag array element is not a string" msgstr "플래그 배열 요소가 문자열이 아님" -#: utils/adt/jsonfuncs.c:5322 utils/adt/jsonfuncs.c:5344 +#: utils/adt/jsonfuncs.c:5598 utils/adt/jsonfuncs.c:5620 #, c-format msgid "" -"Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all" -"\"." +"Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and " +"\"all\"." msgstr "" "사용 가능한 값: \"string\", \"numeric\", \"boolean\", \"key\", \"all\"." -#: utils/adt/jsonfuncs.c:5342 +#: utils/adt/jsonfuncs.c:5618 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "플래그 배열 안에 잘못된 플래그: \"%s\"" -#: utils/adt/jsonpath.c:382 +#: utils/adt/jsonpath.c:389 #, c-format msgid "@ is not allowed in root expressions" msgstr "@ 기호는 루트 표현식에서는 사용할 수 없음" -#: utils/adt/jsonpath.c:388 +#: utils/adt/jsonpath.c:395 #, c-format msgid "LAST is allowed only in array subscripts" msgstr "LAST 키워드는 배열 하위 스크립트 전용임" -#: utils/adt/jsonpath_exec.c:361 +#: utils/adt/jsonpath_exec.c:491 #, c-format msgid "single boolean result is expected" msgstr "단일 불리언 반환값이 예상 됨" -#: utils/adt/jsonpath_exec.c:557 +#: utils/adt/jsonpath_exec.c:851 #, c-format -msgid "\"vars\" argument is not an object" -msgstr "\"vars\" 인자가 객체가 아닙니다." +msgid "jsonpath wildcard array accessor can only be applied to an array" +msgstr "jsonpath wildcard array accessor는 하나의 배열을 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:558 +#: utils/adt/jsonpath_exec.c:874 #, c-format -msgid "" -"Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." -msgstr "jsonpath 매개 변수는 \"vars\" 객체의 키-값 쌍으로 인코드 되어야합니다." +msgid "jsonpath wildcard member accessor can only be applied to an object" +msgstr "jsonpath wildcard member accessor는 하나의 객체를 대상으로 합니다." + +#: utils/adt/jsonpath_exec.c:923 +#, c-format +msgid "jsonpath array subscript is out of bounds" +msgstr "jsonpath 배열 하위 스크립트 범위를 초과했습니다" + +#: utils/adt/jsonpath_exec.c:980 +#, c-format +msgid "jsonpath array accessor can only be applied to an array" +msgstr "jsonpath array accessor는 하나의 배열을 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:675 +#: utils/adt/jsonpath_exec.c:1044 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "JSON 객체 안에 \"%s\" 이름의 키가 없습니다." -#: utils/adt/jsonpath_exec.c:687 +#: utils/adt/jsonpath_exec.c:1056 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "jsonpath member accessor는 하나의 객체를 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:716 +#: utils/adt/jsonpath_exec.c:1114 #, c-format -msgid "jsonpath wildcard array accessor can only be applied to an array" -msgstr "jsonpath wildcard array accessor는 하나의 배열을 대상으로 합니다." +msgid "jsonpath item method .%s() can only be applied to an array" +msgstr "jsonpath .%s() item method는 하나의 배열을 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:764 +#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 #, c-format -msgid "jsonpath array subscript is out of bounds" -msgstr "jsonpath 배열 하위 스크립트 범위를 초과했습니다" +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type double " +"precision" +msgstr "" +"\"%s\" 인자(대상 jsonpath 아이템 메서드: .%s())는 바르지 않은 double precision형임" -#: utils/adt/jsonpath_exec.c:821 +#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 +#: utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 #, c-format -msgid "jsonpath array accessor can only be applied to an array" -msgstr "jsonpath array accessor는 하나의 배열을 대상으로 합니다." +msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" +msgstr "jsonpath item method .%s()용으로 NaN 또는 Infinity는 허용하지 않음" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 +#: utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 #, c-format -msgid "jsonpath wildcard member accessor can only be applied to an object" -msgstr "jsonpath wildcard member accessor는 하나의 객체를 대상으로 합니다." +msgid "" +"jsonpath item method .%s() can only be applied to a string or numeric value" +msgstr "jsonpath item method .%s() 대상은 문자열이나, 숫자 값만 허용합니다." -#: utils/adt/jsonpath_exec.c:1007 +#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 #, c-format -msgid "jsonpath item method .%s() can only be applied to an array" -msgstr "jsonpath .%s() item method는 하나의 배열을 대상으로 합니다." +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" +msgstr "" +"\"%s\" 인자(대상 jsonpath 아이템 메서드: .%s())는 바르지 않은 bigint형임" -#: utils/adt/jsonpath_exec.c:1060 +#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 #, c-format msgid "" -"numeric argument of jsonpath item method .%s() is out of range for type " -"double precision" +"argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" msgstr "" -"jsonpath 아이템 메서드 .%s() 의 숫자 인자가 double precision 형의 범위를 벗어" -"남" +"\"%s\" 인자(대상 jsonpath 아이템 메서드: .%s())는 바르지 않은 boolean형임" + +#: utils/adt/jsonpath_exec.c:1386 +#, c-format +msgid "" +"jsonpath item method .%s() can only be applied to a boolean, string, or " +"numeric value" +msgstr "jsonpath item method .%s() 대상은 불리언, 문자열이나, 숫자 값만 허용합니다." -#: utils/adt/jsonpath_exec.c:1081 +#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 #, c-format msgid "" -"string argument of jsonpath item method .%s() is not a valid representation " -"of a double precision number" +"argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" msgstr "" -"jsonpath item method .%s()의 문자열 인자가 double precision 숫자로 표현되는 " -"형식이 아닙니다." +"\"%s\" 인자(대상 jsonpath 아이템 메서드: .%s())는 바르지 않은 numeric형임" -#: utils/adt/jsonpath_exec.c:1094 +#: utils/adt/jsonpath_exec.c:1487 #, c-format msgid "" -"jsonpath item method .%s() can only be applied to a string or numeric value" -msgstr "jsonpath item method .%s() 대상은 문자열이나, 숫자 값만 허용합니다." +"precision of jsonpath item method .%s() is out of range for type integer" +msgstr "" +"jsonpath 아이템 메서드 .%s() 의 precision이 정수 범위를 벗어남" + +#: utils/adt/jsonpath_exec.c:1501 +#, c-format +msgid "scale of jsonpath item method .%s() is out of range for type integer" +msgstr "" +"jsonpath 아이템 메서드 .%s() 의 스케일이 정수 범위를 벗어남" + +#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 +#, c-format +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type integer" +msgstr "" +"\"%s\" 인자(대상 jsonpath 아이템 메서드: .%s())는 바르지 않은 integer형임" + +#: utils/adt/jsonpath_exec.c:1648 +#, c-format +msgid "" +"jsonpath item method .%s() can only be applied to a boolean, string, " +"numeric, or datetime value" +msgstr "jsonpath item method .%s() 대상은 불리언, 문자열이나, 숫자 값만 허용합니다." -#: utils/adt/jsonpath_exec.c:1584 +#: utils/adt/jsonpath_exec.c:2137 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "jsonpath %s 연산자의 왼쪽 값이 단일 숫자값이 아닙니다." -#: utils/adt/jsonpath_exec.c:1591 +#: utils/adt/jsonpath_exec.c:2144 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "jsonpath %s 연산자의 오른쪽 값이 단일 숫자값이 아닙니다." -#: utils/adt/jsonpath_exec.c:1659 +#: utils/adt/jsonpath_exec.c:2212 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "jsonpath %s 단항 연산용 값이 숫자가 아닙니다." -#: utils/adt/jsonpath_exec.c:1758 +#: utils/adt/jsonpath_exec.c:2311 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "jsonpath .%s() 항목 메서드는 숫자값만 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:1798 +#: utils/adt/jsonpath_exec.c:2357 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "jsonpath .%s() 항목 메서드는 문자열만 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:1901 +#: utils/adt/jsonpath_exec.c:2450 +#, c-format +msgid "" +"time precision of jsonpath item method .%s() is out of range for type integer" +msgstr "" +"jsonpath 아이템 메서드 .%s()의 time precision이 정수 범위를 벗어남" + +#: utils/adt/jsonpath_exec.c:2484 utils/adt/jsonpath_exec.c:2490 +#: utils/adt/jsonpath_exec.c:2517 utils/adt/jsonpath_exec.c:2545 +#: utils/adt/jsonpath_exec.c:2598 utils/adt/jsonpath_exec.c:2649 +#: utils/adt/jsonpath_exec.c:2720 #, c-format -msgid "datetime format is not recognized: \"%s\"" -msgstr "알 수 없는 datetime 양식: \"%s\"" +msgid "%s format is not recognized: \"%s\"" +msgstr "%s 포멧은 알 수 없음: \"%s\"" -#: utils/adt/jsonpath_exec.c:1903 +#: utils/adt/jsonpath_exec.c:2486 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "입력 자료 형식을 지정하는 datetime 템플릿 인자를 사용하세요." -#: utils/adt/jsonpath_exec.c:1971 +#: utils/adt/jsonpath_exec.c:2679 utils/adt/jsonpath_exec.c:2760 +#, c-format +msgid "time precision of jsonpath item method .%s() is invalid" +msgstr "" +"jsonpath 아이템 메서드 .%s() 의 time precision이 잘못됨" +"남" + +#: utils/adt/jsonpath_exec.c:2840 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "jsonpath .%s() 항목 메서드는 객체만 대상으로 합니다." -#: utils/adt/jsonpath_exec.c:2153 +#: utils/adt/jsonpath_exec.c:3124 +#, c-format +msgid "could not convert value of type %s to jsonpath" +msgstr "%s 자료형의 값이 jsonpath 형으로 변환될 수 없음" + +#: utils/adt/jsonpath_exec.c:3158 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "\"%s\" jsonpath 변수 찾기 실패" -#: utils/adt/jsonpath_exec.c:2417 +#: utils/adt/jsonpath_exec.c:3211 +#, c-format +msgid "\"vars\" argument is not an object" +msgstr "\"vars\" 인자가 객체가 아닙니다." + +#: utils/adt/jsonpath_exec.c:3212 +#, c-format +msgid "" +"Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgstr "jsonpath 매개 변수는 \"vars\" 객체의 키-값 쌍으로 인코드 되어야합니다." + +#: utils/adt/jsonpath_exec.c:3475 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "jsonpath 배열 첨자가 단일 숫자값이 아닙니다." -#: utils/adt/jsonpath_exec.c:2429 +#: utils/adt/jsonpath_exec.c:3487 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "jsonpath 배열 하위 스크립트가 정수 범위를 초과했음" -#: utils/adt/jsonpath_exec.c:2606 +#: utils/adt/jsonpath_exec.c:3671 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "지역 시간대 지정 없이는 %s에서 %s로 값을 바꿀 수 없습니다." -#: utils/adt/jsonpath_exec.c:2608 +#: utils/adt/jsonpath_exec.c:3673 #, c-format msgid "Use *_tz() function for time zone support." msgstr "지역 시간대를 지정하려면, *_tz() 함수를 사용하세요." +#: utils/adt/jsonpath_exec.c:3981 +#, c-format +msgid "" +"JSON path expression for column \"%s\" should return single item without " +"wrapper" +msgstr "" +"\"%s\" 칼럼의 JSON 패스 표현식은 wrapper 없이 단일 아이템을 반환해야 함" + +#: utils/adt/jsonpath_exec.c:3983 utils/adt/jsonpath_exec.c:3988 +#, c-format +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." +msgstr "SQL/JSON 아이템을 배열로 만들려면, WITH WRAPPER 절을 사용하세요." + +#: utils/adt/jsonpath_exec.c:3987 +#, c-format +msgid "" +"JSON path expression in JSON_QUERY should return single item without wrapper" +msgstr "" +"JSON_QUERY 안 JSON 패스 표현식은 wrapper 없이 단일 아이템을 반환해야 함" + +#: utils/adt/jsonpath_exec.c:4045 utils/adt/jsonpath_exec.c:4069 +#, c-format +msgid "JSON path expression for column \"%s\" should return single scalar item" +msgstr "\"%s\" 칼럼을 위한 JSON 패스 표현식은 단일 스칼라 아이템을 반환해야 함" + +#: utils/adt/jsonpath_exec.c:4050 utils/adt/jsonpath_exec.c:4074 +#, c-format +msgid "JSON path expression in JSON_VALUE should return single scalar item" +msgstr "JSON_VALUE 안 JSON 패스 표현식은 단일 스칼라 아이템을 반환해야 함" + #: utils/adt/levenshtein.c:132 #, c-format msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "levenshtein 인자값으로 그 길이가 %d 문자의 최대 길이를 초과했음" -#: utils/adt/like.c:161 +#: utils/adt/like.c:159 #, c-format msgid "nondeterministic collations are not supported for LIKE" msgstr "LIKE 연산에서 사용할 비결정 정렬규칙(collation)은 지원하지 않음" -#: utils/adt/like.c:190 utils/adt/like_support.c:1024 +#: utils/adt/like.c:188 utils/adt/like_support.c:1023 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "ILIKE 연산에서 사용할 정렬규칙(collation)을 결정할 수 없음" -#: utils/adt/like.c:202 +#: utils/adt/like.c:200 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "ILIKE 연산에서 사용할 비결정 정렬규칙(collation)은 지원하지 않음" @@ -26613,22 +27857,22 @@ msgstr "ILIKE 연산에서 사용할 비결정 정렬규칙(collation)은 지원 msgid "LIKE pattern must not end with escape character" msgstr "LIKE 패턴은 이스케이프 문자로 끝나지 않아야 함" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "잘못된 이스케이프 문자열" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:802 +#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "이스케이프 문자열은 비어있거나 한개의 문자여야 합니다." -#: utils/adt/like_support.c:1014 +#: utils/adt/like_support.c:1013 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "bytea 형식에서는 대/소문자를 구분하지 않는 일치가 지원되지 않음" -#: utils/adt/like_support.c:1115 +#: utils/adt/like_support.c:1114 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "bytea 형식에서는 정규식 일치가 지원되지 않음" @@ -26638,12 +27882,12 @@ msgstr "bytea 형식에서는 정규식 일치가 지원되지 않음" msgid "invalid octet value in \"macaddr\" value: \"%s\"" msgstr "\"macaddr\"에 대한 잘못된 옥텟(octet) 값: \"%s\"" -#: utils/adt/mac8.c:554 +#: utils/adt/mac8.c:555 #, c-format msgid "macaddr8 data out of range to convert to macaddr" msgstr "macaddr8 자료가 macaddr 형으로 변환하기에는 그 범위가 너무 넓습니다." -#: utils/adt/mac8.c:555 +#: utils/adt/mac8.c:556 #, c-format msgid "" "Only addresses that have FF and FE as values in the 4th and 5th bytes from " @@ -26653,7 +27897,7 @@ msgstr "" "macaddr8에서 macaddr 형으로 변환 할 수 있는 값은 왼쪽에서 4번째, 5번째 바이트" "가 FF와 FE 값(예: xx:xx:xx:ff:fe:xx:xx:xx)인 경우일 때만입니다." -#: utils/adt/mcxtfuncs.c:182 +#: utils/adt/mcxtfuncs.c:173 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %d 프로그램은 PostgreSQL 서버 프로세스가 아닙니다" @@ -26686,76 +27930,76 @@ msgstr "예약됨" #: utils/adt/misc.c:477 msgid "can be bare label" -msgstr "" +msgstr "베어 라벨 가능" #: utils/adt/misc.c:482 msgid "requires AS" msgstr "AS 필요함" -#: utils/adt/misc.c:853 utils/adt/misc.c:867 utils/adt/misc.c:906 -#: utils/adt/misc.c:912 utils/adt/misc.c:918 utils/adt/misc.c:941 +#: utils/adt/misc.c:897 utils/adt/misc.c:911 utils/adt/misc.c:950 +#: utils/adt/misc.c:956 utils/adt/misc.c:962 utils/adt/misc.c:985 #, c-format msgid "string is not a valid identifier: \"%s\"" msgstr "문자열이 타당한 식별자가 아님: \"%s\"" -#: utils/adt/misc.c:855 +#: utils/adt/misc.c:899 #, c-format msgid "String has unclosed double quotes." msgstr "문자열 표기에서 큰따옴표 짝이 안맞습니다." -#: utils/adt/misc.c:869 +#: utils/adt/misc.c:913 #, c-format msgid "Quoted identifier must not be empty." msgstr "인용부호 있는 식별자: 비어있으면 안됩니다" -#: utils/adt/misc.c:908 +#: utils/adt/misc.c:952 #, c-format msgid "No valid identifier before \".\"." msgstr "\".\" 전에 타당한 식별자가 없음" -#: utils/adt/misc.c:914 +#: utils/adt/misc.c:958 #, c-format msgid "No valid identifier after \".\"." msgstr "\".\" 뒤에 타당한 식별자 없음" -#: utils/adt/misc.c:974 +#: utils/adt/misc.c:1018 #, c-format msgid "log format \"%s\" is not supported" msgstr "\"%s\" 양식의 로그는 지원하지 않습니다" -#: utils/adt/misc.c:975 +#: utils/adt/misc.c:1019 #, c-format msgid "The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\"." msgstr "사용할 수 있는 로그 양식은 \"stderr\", \"csvlog\", \"jsonlog\" 입니다." -#: utils/adt/multirangetypes.c:151 utils/adt/multirangetypes.c:164 -#: utils/adt/multirangetypes.c:193 utils/adt/multirangetypes.c:267 -#: utils/adt/multirangetypes.c:291 +#: utils/adt/multirangetypes.c:150 utils/adt/multirangetypes.c:163 +#: utils/adt/multirangetypes.c:192 utils/adt/multirangetypes.c:266 +#: utils/adt/multirangetypes.c:290 #, c-format msgid "malformed multirange literal: \"%s\"" msgstr "비정상적인 multirange 문자열: \"%s\"" -#: utils/adt/multirangetypes.c:153 +#: utils/adt/multirangetypes.c:152 #, c-format msgid "Missing left brace." msgstr "왼쪽 중괄호가 필요합니다." -#: utils/adt/multirangetypes.c:195 +#: utils/adt/multirangetypes.c:194 #, c-format msgid "Expected range start." msgstr "범위 시작값 없음" -#: utils/adt/multirangetypes.c:269 +#: utils/adt/multirangetypes.c:268 #, c-format msgid "Expected comma or end of multirange." msgstr "multirange 구분자(,) 또는 끝이 없습니다." -#: utils/adt/multirangetypes.c:982 +#: utils/adt/multirangetypes.c:981 #, c-format msgid "multiranges cannot be constructed from multidimensional arrays" msgstr "다중 차원 배열은 다중 범위 자료형으로 구성할 수 없습니다." -#: utils/adt/multirangetypes.c:1008 +#: utils/adt/multirangetypes.c:1007 #, c-format msgid "multirange values cannot contain null members" msgstr "multirange의 한 범위로 null 값이 올 수 없음" @@ -26834,102 +28078,122 @@ msgstr "결과가 범위를 벗어났습니다." msgid "cannot subtract inet values of different sizes" msgstr "inet 값에서 서로 크기가 틀리게 부분 추출(subtract)할 수 없음" -#: utils/adt/numeric.c:785 utils/adt/numeric.c:3643 utils/adt/numeric.c:7131 -#: utils/adt/numeric.c:7334 utils/adt/numeric.c:7806 utils/adt/numeric.c:10501 -#: utils/adt/numeric.c:10975 utils/adt/numeric.c:11069 -#: utils/adt/numeric.c:11203 +#: utils/adt/numeric.c:793 utils/adt/numeric.c:3659 utils/adt/numeric.c:7216 +#: utils/adt/numeric.c:7419 utils/adt/numeric.c:7891 utils/adt/numeric.c:10586 +#: utils/adt/numeric.c:11061 utils/adt/numeric.c:11155 +#: utils/adt/numeric.c:11290 #, c-format msgid "value overflows numeric format" msgstr "값이 수치 형식에 넘처남" -#: utils/adt/numeric.c:1098 +#: utils/adt/numeric.c:1106 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "외부 \"numeric\" 값의 부호가 잘못됨" -#: utils/adt/numeric.c:1104 +#: utils/adt/numeric.c:1112 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "외부 \"numeric\" 값의 잘못된 스케일" -#: utils/adt/numeric.c:1113 +#: utils/adt/numeric.c:1121 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "외부 \"numeric\" 값의 숫자가 잘못됨" -#: utils/adt/numeric.c:1328 utils/adt/numeric.c:1342 +#: utils/adt/numeric.c:1336 utils/adt/numeric.c:1350 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "NUMERIC 정밀도 %d 값은 범위(1 .. %d)를 벗어났습니다." -#: utils/adt/numeric.c:1333 +#: utils/adt/numeric.c:1341 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "NUMERIC 스케일 %d 값은 %d부터 %d까지 입니다." -#: utils/adt/numeric.c:1351 +#: utils/adt/numeric.c:1359 #, c-format msgid "invalid NUMERIC type modifier" msgstr "잘못된 NUMERIC 형식 한정자" -#: utils/adt/numeric.c:1709 +#: utils/adt/numeric.c:1725 #, c-format msgid "start value cannot be NaN" msgstr "시작값은 NaN 일 수 없음" -#: utils/adt/numeric.c:1713 +#: utils/adt/numeric.c:1729 #, c-format msgid "start value cannot be infinity" msgstr "시작 값은 무한일 수 없음" -#: utils/adt/numeric.c:1720 +#: utils/adt/numeric.c:1736 #, c-format msgid "stop value cannot be NaN" msgstr "종료값은 NaN 일 수 없음" -#: utils/adt/numeric.c:1724 +#: utils/adt/numeric.c:1740 #, c-format msgid "stop value cannot be infinity" msgstr "종료값은 무한일 수 없음" -#: utils/adt/numeric.c:1737 +#: utils/adt/numeric.c:1753 #, c-format msgid "step size cannot be NaN" msgstr "단계 크기는 NaN 일 수 없음" -#: utils/adt/numeric.c:1741 +#: utils/adt/numeric.c:1757 #, c-format msgid "step size cannot be infinity" msgstr "단계 크기는 무한일 수 없음" -#: utils/adt/numeric.c:3633 +#: utils/adt/numeric.c:3649 #, c-format msgid "factorial of a negative number is undefined" msgstr "음수 거듭제곱이 정의되어 있지 않음" -#: utils/adt/numeric.c:4366 utils/adt/numeric.c:4446 utils/adt/numeric.c:4487 -#: utils/adt/numeric.c:4683 +#: utils/adt/numeric.c:4256 +#, c-format +msgid "lower bound cannot be NaN" +msgstr "lower bound는 NaN 일 수 없음" + +#: utils/adt/numeric.c:4260 +#, c-format +msgid "lower bound cannot be infinity" +msgstr "lower bound는 무한일 수 없음" + +#: utils/adt/numeric.c:4267 +#, c-format +msgid "upper bound cannot be NaN" +msgstr "upper bound는 NaN 일 수 없음" + +#: utils/adt/numeric.c:4271 +#, c-format +msgid "upper bound cannot be infinity" +msgstr "upper bound는 무한일 수 없음" + +#: utils/adt/numeric.c:4432 utils/adt/numeric.c:4520 utils/adt/numeric.c:4580 +#: utils/adt/numeric.c:4776 #, c-format msgid "cannot convert NaN to %s" msgstr "NaN 값을 %s 형으로 변환할 수 없습니다" -#: utils/adt/numeric.c:4370 utils/adt/numeric.c:4450 utils/adt/numeric.c:4491 -#: utils/adt/numeric.c:4687 +#: utils/adt/numeric.c:4436 utils/adt/numeric.c:4524 utils/adt/numeric.c:4584 +#: utils/adt/numeric.c:4780 #, c-format msgid "cannot convert infinity to %s" msgstr "무한은 %s 형으로 변환할 수 없음" -#: utils/adt/numeric.c:4696 +#: utils/adt/numeric.c:4789 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn 값의 범위를 벗어났습니다." -#: utils/adt/numeric.c:7896 utils/adt/numeric.c:7947 +#: utils/adt/numeric.c:7981 utils/adt/numeric.c:8032 #, c-format msgid "numeric field overflow" msgstr "수치 필드 오버플로우" -#: utils/adt/numeric.c:7897 +#: utils/adt/numeric.c:7982 #, c-format msgid "" "A field with precision %d, scale %d must round to an absolute value less " @@ -26938,12 +28202,18 @@ msgstr "" "전체 자릿수 %d, 소수 자릿수 %d의 필드는 %s%d보다 작은 절대 값으로 반올림해야 " "합니다." -#: utils/adt/numeric.c:7948 +#: utils/adt/numeric.c:8033 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "전체 자릿수 %d, 소수 자릿수 %d의 필드는 무한 값을 처리할 수 없음." -#: utils/adt/oid.c:216 +#: utils/adt/numeric.c:11359 utils/adt/pseudorandomfuncs.c:135 +#: utils/adt/pseudorandomfuncs.c:159 +#, c-format +msgid "lower bound must be less than or equal to upper bound" +msgstr "lower bound는 upper bound보다 작거나 같아야 함" + +#: utils/adt/oid.c:217 #, c-format msgid "invalid oidvector data" msgstr "잘못된 oidvector 자료" @@ -26973,36 +28243,41 @@ msgstr "요청한 문자가 너무 커서 인코딩할 수 없음: %u" msgid "requested character not valid for encoding: %u" msgstr "요청한 문자가 인코딩용으로 타당치 않음: %u" -#: utils/adt/orderedsetaggs.c:448 utils/adt/orderedsetaggs.c:553 -#: utils/adt/orderedsetaggs.c:693 +#: utils/adt/orderedsetaggs.c:446 utils/adt/orderedsetaggs.c:551 +#: utils/adt/orderedsetaggs.c:691 #, c-format msgid "percentile value %g is not between 0 and 1" msgstr "%g 퍼센트 값이 0과 1사이가 아닙니다." -#: utils/adt/pg_locale.c:1406 +#: utils/adt/pg_locale.c:326 utils/adt/pg_locale.c:358 +#, c-format +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "\"%s\" 로케일 이름에 사용할 수 없는 문자(non-ASCII)가 있음" + +#: utils/adt/pg_locale.c:1507 #, c-format msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" msgstr "\"%s\" 로케일(해당 규칙 \"%s\")용 문자 정렬 규칙 열기 실패: %s" -#: utils/adt/pg_locale.c:1417 utils/adt/pg_locale.c:2831 -#: utils/adt/pg_locale.c:2904 +#: utils/adt/pg_locale.c:1518 utils/adt/pg_locale.c:2992 +#: utils/adt/pg_locale.c:3065 #, c-format msgid "ICU is not supported in this build" msgstr "ICU 지원 기능을 뺀 채로 서버가 만들어졌습니다." -#: utils/adt/pg_locale.c:1446 +#: utils/adt/pg_locale.c:1546 #, c-format msgid "could not create locale \"%s\": %m" msgstr "\"%s\" 로케일을 만들 수 없음: %m" -#: utils/adt/pg_locale.c:1449 +#: utils/adt/pg_locale.c:1549 #, c-format msgid "" -"The operating system could not find any locale data for the locale name \"%s" -"\"." +"The operating system could not find any locale data for the locale name " +"\"%s\"." msgstr "운영체제에서 \"%s\" 로케일 이름에 대한 로케일 파일을 찾을 수 없습니다." -#: utils/adt/pg_locale.c:1564 +#: utils/adt/pg_locale.c:1670 #, c-format msgid "" "collations with different collate and ctype values are not supported on this " @@ -27011,22 +28286,17 @@ msgstr "" "이 플랫폼에서는 서로 다른 정렬규칙(collation)과 문자집합(ctype)을 함께 쓸 수 " "없습니다." -#: utils/adt/pg_locale.c:1573 -#, c-format -msgid "collation provider LIBC is not supported on this platform" -msgstr "이 플랫폼에서는 LIBC 문자 정렬 제공자 기능(ICU)을 지원하지 않음." - -#: utils/adt/pg_locale.c:1614 +#: utils/adt/pg_locale.c:1717 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "\"%s\" 문자 정렬 규칙은 버전이 없는데 버전을 지정했음" -#: utils/adt/pg_locale.c:1620 +#: utils/adt/pg_locale.c:1723 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "\"%s\" 문자 정렬 규칙은 버전이 맞지 않음" -#: utils/adt/pg_locale.c:1622 +#: utils/adt/pg_locale.c:1725 #, c-format msgid "" "The collation in the database was created using version %s, but the " @@ -27035,7 +28305,7 @@ msgstr "" "데이터베이스를 만들때 %s 버전으로 문자 정렬 규칙을 만들었는데, 현재 OS는 %s " "버전을 제공하고 있습니다." -#: utils/adt/pg_locale.c:1625 +#: utils/adt/pg_locale.c:1728 #, c-format msgid "" "Rebuild all objects affected by this collation and run ALTER COLLATION %s " @@ -27045,224 +28315,235 @@ msgstr "" "VERSION 명령을 실행하거나, 바른 라이브러리 버전을 지정해서, PostgreSQL을 빌드" "하세요." -#: utils/adt/pg_locale.c:1691 +#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:2556 +#: utils/adt/pg_locale.c:2581 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "내장 제공자용 로케일 이름이 잘못됨: \"%s\"" + +#: utils/adt/pg_locale.c:1814 #, c-format msgid "could not load locale \"%s\"" -msgstr "\"%s\" 로케일을 만들 수 없음: %m" +msgstr "\"%s\" 로케일을 불러올 수 없음" -#: utils/adt/pg_locale.c:1716 +#: utils/adt/pg_locale.c:1839 #, c-format msgid "could not get collation version for locale \"%s\": error code %lu" msgstr "\"%s\" 로케일용 정렬 변환 규칙을 구할 수 없음: 오류 코드 %lu" -#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:1785 +#: utils/adt/pg_locale.c:1895 utils/adt/pg_locale.c:1908 #, c-format msgid "could not convert string to UTF-16: error code %lu" msgstr "UTF-16 인코딩으로 문자열을 변환할 수 없음: 오류번호 %lu" -#: utils/adt/pg_locale.c:1799 +#: utils/adt/pg_locale.c:1920 #, c-format msgid "could not compare Unicode strings: %m" msgstr "유니코드 문자열 비교 실패: %m" -#: utils/adt/pg_locale.c:1980 +#: utils/adt/pg_locale.c:2094 #, c-format msgid "collation failed: %s" msgstr "문자열 정렬: %s" -#: utils/adt/pg_locale.c:2201 utils/adt/pg_locale.c:2233 +#: utils/adt/pg_locale.c:2313 utils/adt/pg_locale.c:2345 #, c-format msgid "sort key generation failed: %s" msgstr "정렬 키 생성 실패: %s" -#: utils/adt/pg_locale.c:2474 +#: utils/adt/pg_locale.c:2635 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "\"%s\" 로케일에서 언어를 찾을 수 없음: %s" -#: utils/adt/pg_locale.c:2495 utils/adt/pg_locale.c:2511 +#: utils/adt/pg_locale.c:2656 utils/adt/pg_locale.c:2672 #, c-format msgid "could not open collator for locale \"%s\": %s" msgstr "\"%s\" 로케일용 문자 정렬 규칙 열기 실패: %s" -#: utils/adt/pg_locale.c:2536 +#: utils/adt/pg_locale.c:2697 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "\"%s\" 인코딩은 ICU 기능을 지원하지 않음" -#: utils/adt/pg_locale.c:2543 +#: utils/adt/pg_locale.c:2704 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "\"%s\" 인코딩용 ICU 변환기 열기 실패: %s" -#: utils/adt/pg_locale.c:2561 utils/adt/pg_locale.c:2580 -#: utils/adt/pg_locale.c:2636 utils/adt/pg_locale.c:2647 +#: utils/adt/pg_locale.c:2722 utils/adt/pg_locale.c:2741 +#: utils/adt/pg_locale.c:2797 utils/adt/pg_locale.c:2808 #, c-format msgid "%s failed: %s" msgstr "%s 실패: %s" -#: utils/adt/pg_locale.c:2822 +#: utils/adt/pg_locale.c:2983 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "\"%s\" 로케일 이름을 언어 태그로 변환할 수 없음: %s" -#: utils/adt/pg_locale.c:2863 +#: utils/adt/pg_locale.c:3024 #, c-format msgid "could not get language from ICU locale \"%s\": %s" msgstr "\"%s\" ICU 로케일에서 언어 찾기 실패: %s" -#: utils/adt/pg_locale.c:2865 utils/adt/pg_locale.c:2894 +#: utils/adt/pg_locale.c:3026 utils/adt/pg_locale.c:3055 #, c-format msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." msgstr "ICU 로케일 검사를 하지 않으려면, \"%s\" 값을 \"%s\"로 지정하세요." -#: utils/adt/pg_locale.c:2892 +#: utils/adt/pg_locale.c:3053 #, c-format msgid "ICU locale \"%s\" has unknown language \"%s\"" msgstr "\"%s\" ICU 로케일은 알 수 없는 \"%s\" 언어를 사용합니다." -#: utils/adt/pg_locale.c:3073 +#: utils/adt/pg_locale.c:3204 #, c-format msgid "invalid multibyte character for locale" msgstr "로케일을 위한 잘못된 멀티바이트 문자" -#: utils/adt/pg_locale.c:3074 +#: utils/adt/pg_locale.c:3205 #, c-format msgid "" "The server's LC_CTYPE locale is probably incompatible with the database " "encoding." msgstr "서버의 LC_CTYPE 로케일은 이 데이터베이스 인코딩과 호환되지 않습니다." -#: utils/adt/pg_lsn.c:263 +#: utils/adt/pg_lsn.c:262 #, c-format msgid "cannot add NaN to pg_lsn" msgstr "NaN 값을 pg_lsn 형으로 변환할 수 없습니다" -#: utils/adt/pg_lsn.c:297 +#: utils/adt/pg_lsn.c:296 #, c-format msgid "cannot subtract NaN from pg_lsn" msgstr "pg_lsn 에서는 NaN 형을 빼낼 수 없습니다" -#: utils/adt/pg_upgrade_support.c:29 +#: utils/adt/pg_upgrade_support.c:39 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "함수는 서버가 이진 업그레이드 상태에서만 호출 될 수 있습니다" -#: utils/adt/pgstatfuncs.c:254 +#: utils/adt/pgstatfuncs.c:252 #, c-format msgid "invalid command name: \"%s\"" msgstr "잘못된 명령어 이름: \"%s\"" -#: utils/adt/pgstatfuncs.c:1774 +#: utils/adt/pgstatfuncs.c:1739 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "알 수 없는 리셋 타겟: \"%s\"" -#: utils/adt/pgstatfuncs.c:1775 +#: utils/adt/pgstatfuncs.c:1740 #, c-format msgid "" -"Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or " -"\"wal\"." +"Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", " +"\"recovery_prefetch\", \"slru\", or \"wal\"." msgstr "" -"사용 가능한 타겟은 \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch" -"\", \"wal\" 입니다." +"사용 가능한 타겟은 \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", " +"\"recovery_prefetch\", \"slru\", \"wal\" 입니다." -#: utils/adt/pgstatfuncs.c:1857 +#: utils/adt/pgstatfuncs.c:1822 #, c-format msgid "invalid subscription OID %u" msgstr "잘못된 구독 OID %u" -#: utils/adt/pseudotypes.c:58 utils/adt/pseudotypes.c:92 +#: utils/adt/pseudorandomfuncs.c:69 +#, c-format +msgid "setseed parameter %g is out of allowed range [-1,1]" +msgstr "%g setseed 매개 변수가 [-1,1] 범위를 벗어났습니다." + +#: utils/adt/pseudotypes.c:55 utils/adt/pseudotypes.c:89 #, c-format msgid "cannot display a value of type %s" msgstr "%s 자료형의 값은 표시할 수 없음" -#: utils/adt/pseudotypes.c:310 +#: utils/adt/pseudotypes.c:307 #, c-format msgid "cannot accept a value of a shell type" msgstr "셸 형태 값은 사용할 수 없음" -#: utils/adt/pseudotypes.c:320 +#: utils/adt/pseudotypes.c:317 #, c-format msgid "cannot display a value of a shell type" msgstr "shell 형식의 값은 표시할 수 없음" -#: utils/adt/rangetypes.c:415 +#: utils/adt/rangetypes.c:422 #, c-format msgid "range constructor flags argument must not be null" msgstr "range 자료형 구성자 플래그 인자로 null을 사용할 수 없음" -#: utils/adt/rangetypes.c:1014 +#: utils/adt/rangetypes.c:1021 #, c-format msgid "result of range difference would not be contiguous" msgstr "범위 차이 결과가 연속적이지 않습니다." -#: utils/adt/rangetypes.c:1075 +#: utils/adt/rangetypes.c:1082 #, c-format msgid "result of range union would not be contiguous" msgstr "범위 결합 결과가 연속적이지 않습니다." -#: utils/adt/rangetypes.c:1750 +#: utils/adt/rangetypes.c:1757 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "range 자료형의 하한값은 상한값과 같거나 작아야 합니다" -#: utils/adt/rangetypes.c:2197 utils/adt/rangetypes.c:2210 -#: utils/adt/rangetypes.c:2224 +#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 +#: utils/adt/rangetypes.c:2283 #, c-format msgid "invalid range bound flags" msgstr "잘못된 range 구성 플래그" -#: utils/adt/rangetypes.c:2198 utils/adt/rangetypes.c:2211 -#: utils/adt/rangetypes.c:2225 +#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 +#: utils/adt/rangetypes.c:2284 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "유효한 값은 \"[]\", \"[)\", \"(]\", \"()\"." -#: utils/adt/rangetypes.c:2293 utils/adt/rangetypes.c:2310 -#: utils/adt/rangetypes.c:2325 utils/adt/rangetypes.c:2345 -#: utils/adt/rangetypes.c:2356 utils/adt/rangetypes.c:2403 -#: utils/adt/rangetypes.c:2411 +#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 +#: utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 +#: utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "malformed range literal: \"%s\"" msgstr "비정상적인 range 문자: \"%s\"" -#: utils/adt/rangetypes.c:2295 +#: utils/adt/rangetypes.c:2354 #, c-format msgid "Junk after \"empty\" key word." msgstr " \"empty\" 키워드 뒤에 정크가 있음" -#: utils/adt/rangetypes.c:2312 +#: utils/adt/rangetypes.c:2371 #, c-format msgid "Missing left parenthesis or bracket." msgstr "왼쪽 괄호가 빠졌음" -#: utils/adt/rangetypes.c:2327 +#: utils/adt/rangetypes.c:2386 #, c-format msgid "Missing comma after lower bound." msgstr "하한값 뒤에 쉼표가 빠졌음" -#: utils/adt/rangetypes.c:2347 +#: utils/adt/rangetypes.c:2406 #, c-format msgid "Too many commas." msgstr "칼럼이 너무 많습니다." -#: utils/adt/rangetypes.c:2358 +#: utils/adt/rangetypes.c:2417 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "오른쪽 괄호 다음에 정크가 있음" -#: utils/adt/regexp.c:305 utils/adt/regexp.c:1997 utils/adt/varlena.c:4270 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 #, c-format msgid "regular expression failed: %s" msgstr "잘못된 정규식: %s" -#: utils/adt/regexp.c:446 utils/adt/regexp.c:681 +#: utils/adt/regexp.c:445 utils/adt/regexp.c:680 #, c-format msgid "invalid regular expression option: \"%.*s\"" msgstr "잘못된 정규식 옵션: \"%.*s\"" -#: utils/adt/regexp.c:683 +#: utils/adt/regexp.c:682 #, c-format msgid "" "If you meant to use regexp_replace() with a start parameter, cast the fourth " @@ -27271,15 +28552,15 @@ msgstr "" "시작 위치를 지정하려는 regexp_replace() 함수 사용인 경우, 네번째 인자는 정수" "형을 지정해야합니다." -#: utils/adt/regexp.c:717 utils/adt/regexp.c:726 utils/adt/regexp.c:1083 -#: utils/adt/regexp.c:1147 utils/adt/regexp.c:1156 utils/adt/regexp.c:1165 -#: utils/adt/regexp.c:1174 utils/adt/regexp.c:1854 utils/adt/regexp.c:1863 -#: utils/adt/regexp.c:1872 utils/misc/guc.c:6610 utils/misc/guc.c:6644 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 +#: utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 +#: utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 +#: utils/adt/regexp.c:1871 utils/misc/guc.c:6820 utils/misc/guc.c:6854 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "잘못된 \"%s\" 매개 변수의 값: %d" -#: utils/adt/regexp.c:937 +#: utils/adt/regexp.c:936 #, c-format msgid "" "SQL regular expression may not contain more than two escape-double-quote " @@ -27288,19 +28569,19 @@ msgstr "" "SQL 정규 표현식에서는 두 개 이상의 이스케이프 큰 따옴표 구분자를 쓸 수 없음" #. translator: %s is a SQL function name -#: utils/adt/regexp.c:1094 utils/adt/regexp.c:1185 utils/adt/regexp.c:1272 -#: utils/adt/regexp.c:1311 utils/adt/regexp.c:1699 utils/adt/regexp.c:1754 -#: utils/adt/regexp.c:1883 +#: utils/adt/regexp.c:1093 utils/adt/regexp.c:1184 utils/adt/regexp.c:1271 +#: utils/adt/regexp.c:1310 utils/adt/regexp.c:1698 utils/adt/regexp.c:1753 +#: utils/adt/regexp.c:1882 #, c-format msgid "%s does not support the \"global\" option" msgstr "%s 함수는 \"global\" 옵션을 지원하지 않음" -#: utils/adt/regexp.c:1313 +#: utils/adt/regexp.c:1312 #, c-format msgid "Use the regexp_matches function instead." msgstr "대신에 regexp_matches 함수를 사용하세요." -#: utils/adt/regexp.c:1501 +#: utils/adt/regexp.c:1500 #, c-format msgid "too many regular expression matches" msgstr "너무 많음 정규식 매치" @@ -27315,18 +28596,18 @@ msgstr "\"%s\"(이)라는 함수가 두 개 이상 있음" msgid "more than one operator named %s" msgstr "%s(이)라는 연산자가 두 개 이상 있음" -#: utils/adt/regproc.c:670 gram.y:8841 +#: utils/adt/regproc.c:670 gram.y:8992 #, c-format msgid "missing argument" msgstr "인자가 빠졌음" -#: utils/adt/regproc.c:671 gram.y:8842 +#: utils/adt/regproc.c:671 gram.y:8993 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "단항 연산자에서 인자 없음을 표시할 때는 NONE 인자를 사용하세요." -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2009 utils/adt/ruleutils.c:10013 -#: utils/adt/ruleutils.c:10226 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10509 +#: utils/adt/ruleutils.c:10722 #, c-format msgid "too many arguments" msgstr "인자가 너무 많습니다" @@ -27336,66 +28617,66 @@ msgstr "인자가 너무 많습니다" msgid "Provide two argument types for operator." msgstr "연산자를 위해서는 두개의 인자 자료형을 지정하십시오." -#: utils/adt/regproc.c:1544 utils/adt/regproc.c:1661 utils/adt/regproc.c:1790 -#: utils/adt/regproc.c:1795 utils/adt/varlena.c:3410 utils/adt/varlena.c:3415 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 +#: utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 #, c-format msgid "invalid name syntax" msgstr "잘못된 이름 구문" -#: utils/adt/regproc.c:1904 +#: utils/adt/regproc.c:1924 #, c-format msgid "expected a left parenthesis" msgstr "왼쪽 괄호가 필요합니다." -#: utils/adt/regproc.c:1922 +#: utils/adt/regproc.c:1942 #, c-format msgid "expected a right parenthesis" msgstr "오른쪽 괄호가 필요합니다." -#: utils/adt/regproc.c:1941 +#: utils/adt/regproc.c:1961 #, c-format msgid "expected a type name" msgstr "자료형 이름을 지정하십시오" -#: utils/adt/regproc.c:1973 +#: utils/adt/regproc.c:1993 #, c-format msgid "improper type name" msgstr "부적절한 형식 이름" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1625 -#: utils/adt/ri_triggers.c:2610 +#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 +#: utils/adt/ri_triggers.c:2601 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "" "\"%s\" 테이블에서 자료 추가, 갱신 작업이 \"%s\" 참조키(foreign key) 제약 조건" "을 위배했습니다" -#: utils/adt/ri_triggers.c:309 utils/adt/ri_triggers.c:1628 +#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MATCH FULL에 null 키 값과 nonnull 키 값을 함께 사용할 수 없습니다." -#: utils/adt/ri_triggers.c:2045 +#: utils/adt/ri_triggers.c:2036 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "INSERT에 대해 \"%s\" 함수를 실행해야 함" -#: utils/adt/ri_triggers.c:2051 +#: utils/adt/ri_triggers.c:2042 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "UPDATE에 대해 \"%s\" 함수를 실행해야 함" -#: utils/adt/ri_triggers.c:2057 +#: utils/adt/ri_triggers.c:2048 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "DELETE에 대해 \"%s\" 함수를 실행해야 함" -#: utils/adt/ri_triggers.c:2080 +#: utils/adt/ri_triggers.c:2071 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "\"%s\" 트리거(해당 테이블: \"%s\")에 대한 pg_constraint 항목이 없음" -#: utils/adt/ri_triggers.c:2082 +#: utils/adt/ri_triggers.c:2073 #, c-format msgid "" "Remove this referential integrity trigger and its mates, then do ALTER TABLE " @@ -27404,12 +28685,12 @@ msgstr "" "해당 트리거 관련 개체를 제거한 후 ALTER TABLE ADD CONSTRAINT 명령으로 추가하" "세요" -#: utils/adt/ri_triggers.c:2112 gram.y:4223 +#: utils/adt/ri_triggers.c:2103 gram.y:4340 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "MATCH PARTIAL 기능은 아직 구현 안되었습니다" -#: utils/adt/ri_triggers.c:2435 +#: utils/adt/ri_triggers.c:2426 #, c-format msgid "" "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave " @@ -27418,32 +28699,32 @@ msgstr "" "\"%s\"에 대한 참조 무결성 쿼리(제약조건: \"%s\", 해당 릴레이션: \"%s\")를 실" "행하면 예기치 않은 결과가 발생함" -#: utils/adt/ri_triggers.c:2439 +#: utils/adt/ri_triggers.c:2430 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "이 문제는 주로 룰이 재작성 되었을 때 발생합니다." -#: utils/adt/ri_triggers.c:2600 +#: utils/adt/ri_triggers.c:2591 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "\"%s\" 파티션 지우기는 \"%s\" 참조키 제약조건을 위반함" -#: utils/adt/ri_triggers.c:2603 utils/adt/ri_triggers.c:2628 +#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "(%s)=(%s) 키가 \"%s\" 테이블에서 여전히 참조됩니다." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2605 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "(%s)=(%s) 키가 \"%s\" 테이블에 없습니다." -#: utils/adt/ri_triggers.c:2617 +#: utils/adt/ri_triggers.c:2608 #, c-format msgid "Key is not present in table \"%s\"." msgstr "\"%s\" 테이블에 키가 없습니다." -#: utils/adt/ri_triggers.c:2623 +#: utils/adt/ri_triggers.c:2614 #, c-format msgid "" "update or delete on table \"%s\" violates foreign key constraint \"%s\" on " @@ -27452,66 +28733,66 @@ msgstr "" "\"%s\" 테이블의 자료 갱신, 삭제 작업이 \"%s\" 참조키(foreign key) 제약 조건 " "- \"%s\" 테이블 - 을 위반했습니다" -#: utils/adt/ri_triggers.c:2631 +#: utils/adt/ri_triggers.c:2622 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "\"%s\" 테이블에서 키가 여전히 참조됩니다." -#: utils/adt/rowtypes.c:106 utils/adt/rowtypes.c:510 +#: utils/adt/rowtypes.c:105 utils/adt/rowtypes.c:509 #, c-format msgid "input of anonymous composite types is not implemented" msgstr "익명 복합 형식의 입력이 구현되어 있지 않음" -#: utils/adt/rowtypes.c:159 utils/adt/rowtypes.c:191 utils/adt/rowtypes.c:217 -#: utils/adt/rowtypes.c:228 utils/adt/rowtypes.c:286 utils/adt/rowtypes.c:297 +#: utils/adt/rowtypes.c:158 utils/adt/rowtypes.c:190 utils/adt/rowtypes.c:216 +#: utils/adt/rowtypes.c:227 utils/adt/rowtypes.c:285 utils/adt/rowtypes.c:296 #, c-format msgid "malformed record literal: \"%s\"" msgstr "비정상적인 레코드 문자: \"%s\"" -#: utils/adt/rowtypes.c:160 +#: utils/adt/rowtypes.c:159 #, c-format msgid "Missing left parenthesis." msgstr "왼쪽 괄호가 필요합니다." -#: utils/adt/rowtypes.c:192 +#: utils/adt/rowtypes.c:191 #, c-format msgid "Too few columns." msgstr "칼럼이 너무 적습니다." -#: utils/adt/rowtypes.c:287 +#: utils/adt/rowtypes.c:286 #, c-format msgid "Too many columns." msgstr "칼럼이 너무 많습니다." -#: utils/adt/rowtypes.c:298 +#: utils/adt/rowtypes.c:297 #, c-format msgid "Junk after right parenthesis." msgstr "오른쪽 괄호가 필요합니다." -#: utils/adt/rowtypes.c:559 +#: utils/adt/rowtypes.c:558 #, c-format msgid "wrong number of columns: %d, expected %d" msgstr "열 수(%d)가 최대값(%d)을 초과했습니다" -#: utils/adt/rowtypes.c:601 +#: utils/adt/rowtypes.c:599 #, c-format msgid "" "binary data has type %u (%s) instead of expected %u (%s) in record column %d" msgstr "바이너리 자료형이 %u (%s) 임. 기대 자료형: %u (%s), 해당 칼럼: %d" -#: utils/adt/rowtypes.c:668 +#: utils/adt/rowtypes.c:660 #, c-format msgid "improper binary format in record column %d" msgstr "%d 번째 레코드 열에서 잘못된 바이너리 포맷이 있습니다" -#: utils/adt/rowtypes.c:959 utils/adt/rowtypes.c:1205 utils/adt/rowtypes.c:1463 -#: utils/adt/rowtypes.c:1709 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 +#: utils/adt/rowtypes.c:1699 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "서로 다른 열 형식 %s과(와) %s(레코드 열 %d)을(를) 비교할 수 없음" -#: utils/adt/rowtypes.c:1050 utils/adt/rowtypes.c:1275 -#: utils/adt/rowtypes.c:1560 utils/adt/rowtypes.c:1745 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 +#: utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "칼럼 수가 서로 다른 레코드 자료형을 비교할 수 없음" @@ -27531,113 +28812,139 @@ msgstr "expression이 하나 이상의 릴레이션 변수를 포함하고 있 msgid "expression contains variables" msgstr "expression이 변수들을 포함하고 있음" -#: utils/adt/ruleutils.c:5227 +#: utils/adt/ruleutils.c:5246 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "\"%s\" 룰은 %d 이벤트 형태를 지원하지 않습니다" -#: utils/adt/timestamp.c:112 +#: utils/adt/timestamp.c:128 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "TIMESTAMP(%d)%s 정밀도로 음수를 사용할 수 없습니다" -#: utils/adt/timestamp.c:118 +#: utils/adt/timestamp.c:134 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "TIMESTAMP(%d)%s 정밀도는 최대값(%d)으로 줄였습니다" -#: utils/adt/timestamp.c:378 +#: utils/adt/timestamp.c:394 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "타임스탬프(%d) 정밀도는 %d에서 %d 사이여야 함" -#: utils/adt/timestamp.c:496 +#: utils/adt/timestamp.c:512 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "숫자형 타임 존 형식은 처음에 \"-\" 또는 \"+\" 문자가 있어야 합니다." -#: utils/adt/timestamp.c:508 +#: utils/adt/timestamp.c:524 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "\"%s\" 숫자형 타임 존 범위 벗어남" -#: utils/adt/timestamp.c:609 utils/adt/timestamp.c:619 -#: utils/adt/timestamp.c:627 +#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 +#: utils/adt/timestamp.c:643 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "타임스탬프 값이 범위를 벗어났음: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:728 +#: utils/adt/timestamp.c:744 #, c-format msgid "timestamp cannot be NaN" msgstr "타임스탬프 값으로 NaN 값을 지정할 수 없음" -#: utils/adt/timestamp.c:746 utils/adt/timestamp.c:758 +#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "타임스탬프 값이 범위를 벗어났음: \"%g\"" -#: utils/adt/timestamp.c:1065 utils/adt/timestamp.c:1098 +#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 +#: utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 +#: utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 +#: utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 +#: utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 +#: utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 +#: utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 +#: utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 +#: utils/adt/timestamp.c:3537 utils/adt/timestamp.c:3546 +#: utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 +#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 +#: utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 +#: utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 +#: utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 +#: utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 +#: utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 +#: utils/adt/timestamp.c:5097 +#, c-format +msgid "interval out of range" +msgstr "간격이 범위를 벗어남" + +#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 #, c-format msgid "invalid INTERVAL type modifier" msgstr "잘못된 INTERVAL 형식 한정자" -#: utils/adt/timestamp.c:1081 +#: utils/adt/timestamp.c:1110 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d) 정밀도로 음수값이 올 수 없습니다" -#: utils/adt/timestamp.c:1087 +#: utils/adt/timestamp.c:1116 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "INTERVAL(%d) 정밀도는 허용 최대치(%d)로 감소 되었습니다" -#: utils/adt/timestamp.c:1473 +#: utils/adt/timestamp.c:1506 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "간격(%d) 정밀도는 %d에서 %d 사이여야 함" -#: utils/adt/timestamp.c:2703 -#, c-format -msgid "cannot subtract infinite timestamps" -msgstr "타임스탬프 무한값을 추출 할 수 없음" - -#: utils/adt/timestamp.c:3956 utils/adt/timestamp.c:4139 +#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 #, c-format msgid "origin out of range" msgstr "오리진의 범위를 벗어났습니다." -#: utils/adt/timestamp.c:3961 utils/adt/timestamp.c:4144 +#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#, c-format +msgid "timestamps cannot be binned into infinite intervals" +msgstr "timestamp값은 무한 interval 형으로 바인드할 수 없음" + +#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "timestamp값은 월이나 년을 포함하는 interval 형으로 바인드할 수 없음" -#: utils/adt/timestamp.c:3968 utils/adt/timestamp.c:4151 +#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 #, c-format msgid "stride must be greater than zero" msgstr "stride 값은 0 보다 커야 합니다" -#: utils/adt/timestamp.c:4434 +#: utils/adt/timestamp.c:5091 #, c-format msgid "Months usually have fractional weeks." msgstr "달에는 보통 분수형태의 주간이 있습니다." -#: utils/adt/trigfuncs.c:42 +#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#, c-format +msgid "step size cannot be infinite" +msgstr "단계 크기는 무한일 수 없음" + +#: utils/adt/trigfuncs.c:41 #, c-format msgid "suppress_redundant_updates_trigger: must be called as trigger" msgstr "suppress_redundant_updates_trigger: 트리거로 호출되어야 함" -#: utils/adt/trigfuncs.c:48 +#: utils/adt/trigfuncs.c:47 #, c-format msgid "suppress_redundant_updates_trigger: must be called on update" msgstr "suppress_redundant_updates_trigger: 업데이트 시 호출되어야 함" -#: utils/adt/trigfuncs.c:54 +#: utils/adt/trigfuncs.c:53 #, c-format msgid "suppress_redundant_updates_trigger: must be called before update" msgstr "suppress_redundant_updates_trigger: 업데이트 전에 호출되어야 함" -#: utils/adt/trigfuncs.c:60 +#: utils/adt/trigfuncs.c:59 #, c-format msgid "suppress_redundant_updates_trigger: must be called for each row" msgstr "suppress_redundant_updates_trigger: 각 행에 대해 호출되어야 함" @@ -27654,32 +28961,32 @@ msgstr "분석 작업에서 사용한 거리값은 %d 보다 클 수 없습니 msgid "no operand in tsquery: \"%s\"" msgstr "tsquery에 피연산자가 없음: \"%s\"" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "tsquery의 값이 너무 큼: \"%s\"" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "tsquery의 피연산자가 너무 긺: \"%s\"" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "tsquery의 단어가 너무 긺: \"%s\"" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "tsquery에 구문 오류가 있음: \"%s\"" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "텍스트 검색 쿼리에 어휘소가 포함되어 있지 않음: \"%s\"" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "tsquery 길이가 너무 깁니다" @@ -27718,73 +29025,73 @@ msgstr "가중치 배열에는 null이 포함되지 않아야 함" msgid "weight out of range" msgstr "가중치가 범위를 벗어남" -#: utils/adt/tsvector.c:217 +#: utils/adt/tsvector.c:216 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "단어가 너무 긺(%ld바이트, 최대 %ld바이트)" -#: utils/adt/tsvector.c:224 +#: utils/adt/tsvector.c:223 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "" "문자열이 너무 길어서 tsvector에 사용할 수 없음(%ld바이트, 최대 %ld바이트)" -#: utils/adt/tsvector_op.c:773 +#: utils/adt/tsvector_op.c:771 #, c-format msgid "lexeme array may not contain nulls" msgstr "어휘소 배열에는 null이 포함되지 않아야 함" -#: utils/adt/tsvector_op.c:778 +#: utils/adt/tsvector_op.c:776 #, c-format msgid "lexeme array may not contain empty strings" msgstr "어휘소 배열에는 빈문자열이 포함되지 않아야 함" -#: utils/adt/tsvector_op.c:847 +#: utils/adt/tsvector_op.c:845 #, c-format msgid "weight array may not contain nulls" msgstr "가중치 배열에는 null이 포함되지 않아야 함" -#: utils/adt/tsvector_op.c:871 +#: utils/adt/tsvector_op.c:869 #, c-format msgid "unrecognized weight: \"%c\"" msgstr "알 수 없는 가중치: \"%c\"" -#: utils/adt/tsvector_op.c:2601 +#: utils/adt/tsvector_op.c:2599 #, c-format msgid "ts_stat query must return one tsvector column" msgstr "ts_stat 쿼리는 하나의 tsvector 칼럼을 반환해야 함" -#: utils/adt/tsvector_op.c:2790 +#: utils/adt/tsvector_op.c:2788 #, c-format msgid "tsvector column \"%s\" does not exist" msgstr "\"%s\" tsvector 칼럼이 없음" -#: utils/adt/tsvector_op.c:2797 +#: utils/adt/tsvector_op.c:2795 #, c-format msgid "column \"%s\" is not of tsvector type" msgstr "\"%s\" 칼럼은 tsvector 형식이 아님" -#: utils/adt/tsvector_op.c:2809 +#: utils/adt/tsvector_op.c:2807 #, c-format msgid "configuration column \"%s\" does not exist" msgstr "\"%s\" 구성 칼럼이 없음" -#: utils/adt/tsvector_op.c:2815 +#: utils/adt/tsvector_op.c:2813 #, c-format msgid "column \"%s\" is not of regconfig type" msgstr "\"%s\" 칼럼은 regconfig 형이 아님" -#: utils/adt/tsvector_op.c:2822 +#: utils/adt/tsvector_op.c:2820 #, c-format msgid "configuration column \"%s\" must not be null" msgstr "\"%s\" 구성 칼럼은 null이 아니어야 함" -#: utils/adt/tsvector_op.c:2835 +#: utils/adt/tsvector_op.c:2833 #, c-format msgid "text search configuration name \"%s\" must be schema-qualified" msgstr "\"%s\" 텍스트 검색 구성 이름이 스키마로 한정되어야 함" -#: utils/adt/tsvector_op.c:2860 +#: utils/adt/tsvector_op.c:2858 #, c-format msgid "column \"%s\" is not of a character type" msgstr "\"%s\" 칼럼은 문자형이 아님" @@ -27804,17 +29111,17 @@ msgstr "이스케이프 문자가 없음: \"%s\"" msgid "wrong position info in tsvector: \"%s\"" msgstr "tsvector에 잘못된 위치 정보가 있음: \"%s\"" -#: utils/adt/uuid.c:413 +#: utils/adt/uuid.c:418 #, c-format msgid "could not generate random values" msgstr "무작위 값 생성 실패" -#: utils/adt/varbit.c:110 utils/adt/varchar.c:54 +#: utils/adt/varbit.c:110 utils/adt/varchar.c:53 #, c-format msgid "length for type %s must be at least 1" msgstr "%s 자료형의 길이는 최소 1 이상이어야 합니다" -#: utils/adt/varbit.c:115 utils/adt/varchar.c:58 +#: utils/adt/varbit.c:115 utils/adt/varchar.c:57 #, c-format msgid "length for type %s cannot exceed %d" msgstr "%s 자료형의 길이는 최대 %d 이하여야 합니다" @@ -27850,9 +29157,9 @@ msgstr "외부 비트 문자열의 길이가 잘못되었습니다" msgid "bit string too long for type bit varying(%d)" msgstr "비트 문자열이 너무 깁니다(해당 자료형 bit varying(%d))" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:908 -#: utils/adt/varlena.c:971 utils/adt/varlena.c:1128 utils/adt/varlena.c:3052 -#: utils/adt/varlena.c:3130 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 +#: utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 +#: utils/adt/varlena.c:3133 #, c-format msgid "negative substring length not allowed" msgstr "substring에서 음수 길이는 허용하지 않음" @@ -27877,194 +29184,200 @@ msgstr "서로 크기가 틀린 비트 문자열은 XOR 연산을 할 수 없습 msgid "bit index %d out of valid range (0..%d)" msgstr "비트 %d 인덱스의 범위를 벗어남 (0..%d)" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3334 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 #, c-format msgid "new bit must be 0 or 1" msgstr "새 비트값은 0 또는 1 이어야 합니다" -#: utils/adt/varchar.c:162 utils/adt/varchar.c:313 +#: utils/adt/varchar.c:161 utils/adt/varchar.c:312 #, c-format msgid "value too long for type character(%d)" msgstr "character(%d) 자료형에 너무 긴 자료를 담으려고 합니다." -#: utils/adt/varchar.c:476 utils/adt/varchar.c:640 +#: utils/adt/varchar.c:475 utils/adt/varchar.c:639 #, c-format msgid "value too long for type character varying(%d)" msgstr "character varying(%d) 자료형에 너무 긴 자료를 담으려고 합니다." -#: utils/adt/varchar.c:738 utils/adt/varlena.c:1517 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "문자열 비교 작업에 사용할 정렬규칙(collation)을 결정할 수 없음" -#: utils/adt/varlena.c:1227 utils/adt/varlena.c:1806 +#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "문자열 검색 작업에 사용할 비결정 정렬규칙(collation)을 지원하지 않음" -#: utils/adt/varlena.c:3218 utils/adt/varlena.c:3285 +#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "%d 인덱스의 범위를 벗어남, 0..%d" -#: utils/adt/varlena.c:3249 utils/adt/varlena.c:3321 +#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 #, c-format msgid "index %lld out of valid range, 0..%lld" msgstr "%lld 인덱스의 범위를 벗어남, 0..%lld" -#: utils/adt/varlena.c:4382 +#: utils/adt/varlena.c:4385 #, c-format msgid "field position must not be zero" msgstr "필드 위치 값은 0 이 아니여야 함" -#: utils/adt/varlena.c:5554 +#: utils/adt/varlena.c:5630 #, c-format msgid "unterminated format() type specifier" msgstr "마무리 안된 format() 형 식별자" -#: utils/adt/varlena.c:5555 utils/adt/varlena.c:5689 utils/adt/varlena.c:5810 +#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "하나의 \"%%\" 문자를 표시하려면, \"%%%%\" 형태로 사용하세요" -#: utils/adt/varlena.c:5687 utils/adt/varlena.c:5808 +#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "인식할 수 없는 format() 형 식별자 \"%.*s\"" -#: utils/adt/varlena.c:5700 utils/adt/varlena.c:5757 +#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 #, c-format msgid "too few arguments for format()" msgstr "format() 작업을 위한 인자가 너무 적음" -#: utils/adt/varlena.c:5853 utils/adt/varlena.c:6035 +#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 #, c-format msgid "number is out of range" msgstr "수치 범위를 벗어남" -#: utils/adt/varlena.c:5916 utils/adt/varlena.c:5944 +#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "" "format 함수에서 사용할 수 있는 인자 위치 번호는 0이 아니라, 1부터 시작합니다" -#: utils/adt/varlena.c:5937 +#: utils/adt/varlena.c:6013 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "넓이 인자 위치값은 \"$\" 문자로 끝나야 합니다" -#: utils/adt/varlena.c:5982 +#: utils/adt/varlena.c:6058 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "null 값은 SQL 식별자로 포멧될 수 없음" -#: utils/adt/varlena.c:6190 +#: utils/adt/varlena.c:6266 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "" "유니코드 normalization 작업은 서버 인코딩이 UTF8 일때만 할 수 있습니다." -#: utils/adt/varlena.c:6203 +#: utils/adt/varlena.c:6279 #, c-format msgid "invalid normalization form: %s" msgstr "잘못된 normalization 형식: %s" -#: utils/adt/varlena.c:6406 utils/adt/varlena.c:6441 utils/adt/varlena.c:6476 +#: utils/adt/varlena.c:6324 +#, c-format +msgid "Unicode categorization can only be performed if server encoding is UTF8" +msgstr "" +"유니코드 분류 작업은 서버 인코딩이 UTF8 일때만 할 수 있습니다." + +#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 #, c-format msgid "invalid Unicode code point: %04X" msgstr "잘못된 유니코드 코드 포인트: %04X" -#: utils/adt/varlena.c:6506 +#: utils/adt/varlena.c:6641 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "" "유니코드 이스케이프는 \\XXXX, \\+XXXXXX, \\uXXXX, 또는 \\UXXXXXXXX 형태여야 " "합니다." -#: utils/adt/windowfuncs.c:442 +#: utils/adt/windowfuncs.c:443 #, c-format msgid "argument of ntile must be greater than zero" msgstr "ntile의 인자는 0보다 커야 함" -#: utils/adt/windowfuncs.c:706 +#: utils/adt/windowfuncs.c:707 #, c-format msgid "argument of nth_value must be greater than zero" msgstr "nth_value의 인자는 0보다 커야 함" -#: utils/adt/xid8funcs.c:125 +#: utils/adt/xid8funcs.c:124 #, c-format msgid "transaction ID %llu is in the future" msgstr "%llu 트랜잭션 ID는 미래의 것입니다" -#: utils/adt/xid8funcs.c:547 +#: utils/adt/xid8funcs.c:553 #, c-format msgid "invalid external pg_snapshot data" msgstr "외부 pg_snapshot 자료가 잘못됨" -#: utils/adt/xml.c:228 +#: utils/adt/xml.c:238 #, c-format msgid "unsupported XML feature" msgstr "지원되지 않는 XML 기능" -#: utils/adt/xml.c:229 +#: utils/adt/xml.c:239 #, c-format msgid "This functionality requires the server to be built with libxml support." msgstr "이 기능을 사용하려면 libxml 지원으로 서버를 빌드해야 합니다." -#: utils/adt/xml.c:248 utils/mb/mbutils.c:628 +#: utils/adt/xml.c:258 utils/mb/mbutils.c:627 #, c-format msgid "invalid encoding name \"%s\"" msgstr "\"%s\" 인코딩 이름이 잘못됨" -#: utils/adt/xml.c:496 utils/adt/xml.c:501 +#: utils/adt/xml.c:506 utils/adt/xml.c:511 #, c-format msgid "invalid XML comment" msgstr "잘못된 XML 주석" -#: utils/adt/xml.c:660 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "XML 문서가 아님" -#: utils/adt/xml.c:956 utils/adt/xml.c:979 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "잘못된 XML 처리 명령" -#: utils/adt/xml.c:957 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "XML 처리 명령 대상 이름은 \"%s\"일 수 없습니다." -#: utils/adt/xml.c:980 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "XML 처리 명령에는 \"?>\"를 포함할 수 없습니다." -#: utils/adt/xml.c:1059 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "xmlvalidate가 구현되어 있지 않음" -#: utils/adt/xml.c:1115 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "XML 라이브러리를 초기화할 수 없음" -#: utils/adt/xml.c:1116 +#: utils/adt/xml.c:1168 #, c-format msgid "" "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." msgstr "" -"libxml2에 호환되지 않는 문자 자료형 있음: sizeof(char)=%zu, sizeof(xmlChar)=" -"%zu" +"libxml2에 호환되지 않는 문자 자료형 있음: sizeof(char)=%zu, " +"sizeof(xmlChar)=%zu" -#: utils/adt/xml.c:1202 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "XML 오류 핸들러를 설정할 수 없음" -#: utils/adt/xml.c:1203 +#: utils/adt/xml.c:1255 #, c-format msgid "" "This probably indicates that the version of libxml2 being used is not " @@ -28073,121 +29386,126 @@ msgstr "" "이 문제는 PostgreSQL 서버를 만들 때 사용한 libxml2 헤더 파일이 호환성이 없는 " "것 같습니다." -#: utils/adt/xml.c:2189 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "잘못된 문자 값입니다." -#: utils/adt/xml.c:2192 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "공간이 필요합니다." -#: utils/adt/xml.c:2195 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "독립 실행형은 'yes' 또는 'no'만 허용합니다." -#: utils/adt/xml.c:2198 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "선언 형식이 잘못됨: 버전이 누락되었습니다." -#: utils/adt/xml.c:2201 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "텍스트 선언에서 인코딩이 누락되었습니다." -#: utils/adt/xml.c:2204 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "XML 선언 구문 분석 중: '?>'가 필요합니다." -#: utils/adt/xml.c:2207 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "인식할 수 없는 libxml 오류 코드: %d." -#: utils/adt/xml.c:2461 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML은 무한 날짜 값을 지원하지 않습니다." -#: utils/adt/xml.c:2483 utils/adt/xml.c:2510 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML은 무한 타임스탬프 값을 지원하지 않습니다." -#: utils/adt/xml.c:2926 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "잘못된 쿼리" -#: utils/adt/xml.c:4266 +#: utils/adt/xml.c:3110 +#, c-format +msgid "portal \"%s\" does not return tuples" +msgstr "\"%s\" 포털은 집합을 반환할 수 없습니다." + +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "XML 네임스페이스 매핑에 사용할 배열이 잘못됨" -#: utils/adt/xml.c:4267 +#: utils/adt/xml.c:4363 #, c-format msgid "" "The array must be two-dimensional with length of the second axis equal to 2." msgstr "" "이 배열은 key, value로 구성된 배열을 요소로 하는 2차원 배열이어야 합니다." -#: utils/adt/xml.c:4291 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "XPath 식이 비어 있음" -#: utils/adt/xml.c:4343 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "네임스페이스 이름 및 URI는 null일 수 없음" -#: utils/adt/xml.c:4350 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "" "이름 \"%s\" 및 URI \"%s\"을(를) 사용하여 XML 네임스페이스를 등록할 수 없음" -#: utils/adt/xml.c:4693 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "DEFAULT 네임스페이스는 지원하지 않습니다." -#: utils/adt/xml.c:4722 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "로우 경로 필터는 비어있으면 안됩니다" -#: utils/adt/xml.c:4753 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "칼럼 경로 필터는 비어있으면 안됩니다" -#: utils/adt/xml.c:4897 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "칼럼 XPath 표현식에 사용된 결과가 하나 이상의 값을 사용합니다" -#: utils/cache/lsyscache.c:1043 +#: utils/cache/lsyscache.c:1017 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "%s 형에서 %s 형으로 바꾸는 형변환 규칙(cast)가 없음" # # nonun 부분 end -#: utils/cache/lsyscache.c:2845 utils/cache/lsyscache.c:2878 -#: utils/cache/lsyscache.c:2911 utils/cache/lsyscache.c:2944 +#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 +#: utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 #, c-format msgid "type %s is only a shell" msgstr "%s 형식은 셸일 뿐임" -#: utils/cache/lsyscache.c:2850 +#: utils/cache/lsyscache.c:2892 #, c-format msgid "no input function available for type %s" msgstr "%s 자료형을 위한 입력 함수가 없습니다" -#: utils/cache/lsyscache.c:2883 +#: utils/cache/lsyscache.c:2925 #, c-format msgid "no output function available for type %s" msgstr "%s 자료형을 위한 출력 함수가 없습니다" -#: utils/cache/partcache.c:219 +#: utils/cache/partcache.c:216 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d for " @@ -28196,32 +29514,32 @@ msgstr "" "\"%s\" 연산자 클래스(접근 방법: %s)에는 %d 개의 지원 지원 함수(해당 자료형 " "%s)가 빠졌습니다" -#: utils/cache/plancache.c:724 +#: utils/cache/plancache.c:747 #, c-format msgid "cached plan must not change result type" msgstr "캐시된 계획에서 결과 형식을 바꾸지 않아야 함" -#: utils/cache/relcache.c:3741 +#: utils/cache/relcache.c:3801 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "이진 업그레이드 작업 때, 힙 relfilenumber 값이 지정되지 않았습니다" -#: utils/cache/relcache.c:3749 +#: utils/cache/relcache.c:3809 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "바이너리 업그레이드 모드 중에 새 relfilenumber 값 요청이 실패" -#: utils/cache/relcache.c:6495 +#: utils/cache/relcache.c:6539 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "\"%s\" 릴레이션-캐시 초기화 파일을 만들 수 없음: %m" -#: utils/cache/relcache.c:6497 +#: utils/cache/relcache.c:6541 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "어쨌든 계속하는데, 뭔가 잘못 된 것이 있습니다." -#: utils/cache/relcache.c:6819 +#: utils/cache/relcache.c:6871 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "\"%s\" 캐쉬 파일을 삭제할 수 없음: %m" @@ -28231,17 +29549,17 @@ msgstr "\"%s\" 캐쉬 파일을 삭제할 수 없음: %m" msgid "cannot PREPARE a transaction that modified relation mapping" msgstr "릴레이션 맵핑을 변경하는 트랜잭셜을 PREPARE할 수 없음" -#: utils/cache/relmapper.c:850 +#: utils/cache/relmapper.c:852 #, c-format msgid "relation mapping file \"%s\" contains invalid data" msgstr "\"%s\" 릴레이션 맵핑 파일에 잘못된 데이터가 있습니다" -#: utils/cache/relmapper.c:860 +#: utils/cache/relmapper.c:862 #, c-format msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "\"%s\" 릴레이션 맵핑 파일에 잘못된 checksum 값이 있음" -#: utils/cache/typcache.c:1803 utils/fmgr/funcapi.c:566 +#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "레코드 형식이 등록되지 않았음" @@ -28256,102 +29574,102 @@ msgstr "TRAP: ExceptionalCondition: %d PID 안에 잘못된 인자\n" msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "TRAP: Assert 실패(\"%s\"), 파일: \"%s\", 줄: %d, PID: %d\n" -#: utils/error/elog.c:416 +#: utils/error/elog.c:415 #, c-format msgid "error occurred before error message processing is available\n" msgstr "오류 메시지 처리가 활성화 되기 전에 오류가 발생했습니다\n" -#: utils/error/elog.c:2092 +#: utils/error/elog.c:2134 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "stderr 로 사용하기 위해 \"%s\" 파일 다시 열기 실패: %m" -#: utils/error/elog.c:2105 +#: utils/error/elog.c:2147 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "표준출력(stdout)으로 사용하기 위해 \"%s\" 파일 다시 열기 실패: %m" -#: utils/error/elog.c:2141 +#: utils/error/elog.c:2183 #, c-format -msgid "invalid character" +msgid "Invalid character" msgstr "잘못된 문자" -#: utils/error/elog.c:2847 utils/error/elog.c:2874 utils/error/elog.c:2890 +#: utils/error/elog.c:2889 utils/error/elog.c:2916 utils/error/elog.c:2932 msgid "[unknown]" msgstr "[알수없음]" -#: utils/error/elog.c:3163 utils/error/elog.c:3484 utils/error/elog.c:3591 +#: utils/error/elog.c:3202 utils/error/elog.c:3526 utils/error/elog.c:3633 msgid "missing error text" msgstr "오류 내용을 뺍니다" -#: utils/error/elog.c:3166 utils/error/elog.c:3169 +#: utils/error/elog.c:3205 utils/error/elog.c:3208 #, c-format msgid " at character %d" msgstr " %d 번째 문자 부근" -#: utils/error/elog.c:3179 utils/error/elog.c:3186 +#: utils/error/elog.c:3218 utils/error/elog.c:3225 msgid "DETAIL: " msgstr "상세정보: " -#: utils/error/elog.c:3193 +#: utils/error/elog.c:3232 msgid "HINT: " msgstr "힌트: " -#: utils/error/elog.c:3200 +#: utils/error/elog.c:3239 msgid "QUERY: " msgstr "쿼리:" -#: utils/error/elog.c:3207 +#: utils/error/elog.c:3246 msgid "CONTEXT: " msgstr "내용: " -#: utils/error/elog.c:3217 +#: utils/error/elog.c:3256 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "위치: %s, %s:%d\n" -#: utils/error/elog.c:3224 +#: utils/error/elog.c:3263 #, c-format msgid "LOCATION: %s:%d\n" msgstr "위치: %s:%d\n" -#: utils/error/elog.c:3231 +#: utils/error/elog.c:3270 msgid "BACKTRACE: " msgstr "역추적: " -#: utils/error/elog.c:3243 +#: utils/error/elog.c:3282 msgid "STATEMENT: " msgstr "명령 구문: " -#: utils/error/elog.c:3636 +#: utils/error/elog.c:3678 msgid "DEBUG" msgstr "디버그" -#: utils/error/elog.c:3640 +#: utils/error/elog.c:3682 msgid "LOG" msgstr "로그" -#: utils/error/elog.c:3643 +#: utils/error/elog.c:3685 msgid "INFO" msgstr "정보" -#: utils/error/elog.c:3646 +#: utils/error/elog.c:3688 msgid "NOTICE" msgstr "알림" -#: utils/error/elog.c:3650 +#: utils/error/elog.c:3692 msgid "WARNING" msgstr "경고" -#: utils/error/elog.c:3653 +#: utils/error/elog.c:3695 msgid "ERROR" msgstr "오류" -#: utils/error/elog.c:3656 +#: utils/error/elog.c:3698 msgid "FATAL" msgstr "치명적오류" -#: utils/error/elog.c:3659 +#: utils/error/elog.c:3701 msgid "PANIC" msgstr "손상" @@ -28424,22 +29742,22 @@ msgstr "매직 블록에 예기치 않은 길이 또는 여백 차이가 있습 msgid "incompatible library \"%s\": magic block mismatch" msgstr "\"%s\" 라이브러리는 사용할 수 없습니다: magic black 틀림" -#: utils/fmgr/dfmgr.c:492 +#: utils/fmgr/dfmgr.c:475 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "\"%s\" 라이브러리 사용이 금지되어있습니다" -#: utils/fmgr/dfmgr.c:518 +#: utils/fmgr/dfmgr.c:501 #, c-format msgid "invalid macro name in dynamic library path: %s" msgstr "동적 라이브러리 경로에서 잘못된 매크로 이름: %s" -#: utils/fmgr/dfmgr.c:558 +#: utils/fmgr/dfmgr.c:541 #, c-format msgid "zero-length component in parameter \"dynamic_library_path\"" msgstr "\"dynamic_library_path\" 매개 변수 값으로 길이가 0인 값을 사용했음" -#: utils/fmgr/dfmgr.c:577 +#: utils/fmgr/dfmgr.c:560 #, c-format msgid "component in parameter \"dynamic_library_path\" is not an absolute path" msgstr "\"dynamic_library_path\" 매개 변수 값으로 절대 경로를 사용할 수 없음" @@ -28465,146 +29783,136 @@ msgstr "SQL 호출 가능한 함수는 PG_FUNCTION_INFO_V1(함수명) 정의를 msgid "unrecognized API version %d reported by info function \"%s\"" msgstr "%d 알수 없는 API 버전이 \"%s\" 함수에 의해서 보고되었음" -#: utils/fmgr/fmgr.c:2080 +#: utils/fmgr/fmgr.c:2109 #, c-format msgid "operator class options info is absent in function call context" msgstr "연산자 클래스 옵션 정보가 함수 호출 컨텍스트에서 빠졌음" -#: utils/fmgr/fmgr.c:2147 +#: utils/fmgr/fmgr.c:2176 #, c-format msgid "language validation function %u called for language %u instead of %u" msgstr "" "%u OID 언어 유효성 검사 함수가 %u OID 프로시져 언어용으로 호출되었음, 원래 언" "어는 %u" -#: utils/fmgr/funcapi.c:489 +#: utils/fmgr/funcapi.c:496 #, c-format msgid "" "could not determine actual result type for function \"%s\" declared to " "return type %s" msgstr "\"%s\" 함수의 실재 리턴 자료형을 알 수 없음, 정의된 리턴 자료형: %s" -#: utils/fmgr/funcapi.c:634 +#: utils/fmgr/funcapi.c:642 #, c-format msgid "argument declared %s does not contain a range type but type %s" msgstr "%s 로 선언된 인자가 range 자료형이 아니고, %s 자료형입니다" -#: utils/fmgr/funcapi.c:717 -#, c-format -msgid "could not find multirange type for data type %s" -msgstr "%s 자료형용 multirange 형을 찾을 수 없음" - -#: utils/fmgr/funcapi.c:1921 utils/fmgr/funcapi.c:1953 +#: utils/fmgr/funcapi.c:1929 utils/fmgr/funcapi.c:1961 #, c-format msgid "number of aliases does not match number of columns" msgstr "alias 수가 열 수와 틀립니다" -#: utils/fmgr/funcapi.c:1947 +#: utils/fmgr/funcapi.c:1955 #, c-format msgid "no column alias was provided" msgstr "열 별칭이 제공되지 않았음" -#: utils/fmgr/funcapi.c:1971 +#: utils/fmgr/funcapi.c:1979 #, c-format msgid "could not determine row description for function returning record" msgstr "레코드를 리턴하는 함수를 위한 행(row) 구성 정보를 구할 수 없음" -#: utils/init/miscinit.c:347 +#: utils/init/miscinit.c:353 #, c-format msgid "data directory \"%s\" does not exist" msgstr "\"%s\" 데이터 디렉터리 없음" -#: utils/init/miscinit.c:352 +#: utils/init/miscinit.c:358 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "\"%s\" 디렉터리 읽기 권한 없음: %m" -#: utils/init/miscinit.c:360 +#: utils/init/miscinit.c:366 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "지정한 \"%s\" 데이터 디렉터리는 디렉터리가 아님" -#: utils/init/miscinit.c:376 +#: utils/init/miscinit.c:382 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "\"%s\" 데이터 디렉터리 소유주가 잘못 되었습니다." -#: utils/init/miscinit.c:378 +#: utils/init/miscinit.c:384 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "서버는 지정한 데이터 디렉터리의 소유주 권한으로 시작되어야 합니다." -#: utils/init/miscinit.c:396 +#: utils/init/miscinit.c:402 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "\"%s\" 데이터 디렉터리 접근 권한에 문제가 있습니다." -#: utils/init/miscinit.c:398 +#: utils/init/miscinit.c:404 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "액세스 권한은 u=rwx (0700) 또는 u=rwx,o=rx (0750) 값이어야 합니다." -#: utils/init/miscinit.c:456 +#: utils/init/miscinit.c:462 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "\"%s\" 이름의 디렉터리로 이동할 수 없습니다: %m" -#: utils/init/miscinit.c:693 utils/misc/guc.c:3548 +#: utils/init/miscinit.c:720 utils/misc/guc.c:3650 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "보안 제한 작업 내에서 \"%s\" 매개 변수를 설정할 수 없음" -#: utils/init/miscinit.c:765 +#: utils/init/miscinit.c:807 #, c-format msgid "role with OID %u does not exist" msgstr "%u OID 롤이 없음" -#: utils/init/miscinit.c:795 +#: utils/init/miscinit.c:853 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "\"%s\" 롤은 접속을 허용하지 않음" -#: utils/init/miscinit.c:813 +#: utils/init/miscinit.c:874 #, c-format msgid "too many connections for role \"%s\"" msgstr "\"%s\" 롤의 최대 동시 접속수를 초과했습니다" -#: utils/init/miscinit.c:912 -#, c-format -msgid "permission denied to set session authorization" -msgstr "세션 인증을 지정하기 위한 권한이 없음" - -#: utils/init/miscinit.c:995 +#: utils/init/miscinit.c:1045 #, c-format msgid "invalid role OID: %u" msgstr "잘못된 롤 OID: %u" -#: utils/init/miscinit.c:1142 +#: utils/init/miscinit.c:1192 #, c-format msgid "database system is shut down" msgstr "데이터베이스 시스템 서비스를 중지했습니다" -#: utils/init/miscinit.c:1229 +#: utils/init/miscinit.c:1279 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "\"%s\" 잠금 파일을 만들 수 없음: %m" -#: utils/init/miscinit.c:1243 +#: utils/init/miscinit.c:1293 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "\"%s\" 잠금파일을 열 수 없음: %m" -#: utils/init/miscinit.c:1250 +#: utils/init/miscinit.c:1300 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "\"%s\" 잠금 파일을 읽을 수 없음: %m" -#: utils/init/miscinit.c:1259 +#: utils/init/miscinit.c:1309 #, c-format msgid "lock file \"%s\" is empty" msgstr "\"%s\" 잠금 파일이 비었음" -#: utils/init/miscinit.c:1260 +#: utils/init/miscinit.c:1310 #, c-format msgid "" "Either another server is starting, or the lock file is the remnant of a " @@ -28613,43 +29921,43 @@ msgstr "" "다른 서버가 실행 중이거나, 이전 서버 시작 작업을 실패 해서 잠금 파일이 남아 " "있는 경우입니다." -#: utils/init/miscinit.c:1304 +#: utils/init/miscinit.c:1354 #, c-format msgid "lock file \"%s\" already exists" msgstr "\"%s\" 잠금 파일이 이미 있음" -#: utils/init/miscinit.c:1308 +#: utils/init/miscinit.c:1358 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "" "다른 postgres 프로그램(PID %d)이 \"%s\" 데이터 디렉터리를 사용해서 실행중입니" "까?" -#: utils/init/miscinit.c:1310 +#: utils/init/miscinit.c:1360 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "" "다른 postmaster 프로그램(PID %d)이 \"%s\" 데이터 디렉터리를 사용해서 실행중입" "니까?" -#: utils/init/miscinit.c:1313 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "" "다른 postgres 프로그램(PID %d)이 \"%s\" 소켓 파일을 사용해서 실행중입니까?" -#: utils/init/miscinit.c:1315 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "" "다른 postmaster 프로그램(PID %d)이 \"%s\" 소켓 파일을 사용해서 실행중입니까?" -#: utils/init/miscinit.c:1366 +#: utils/init/miscinit.c:1416 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "\"%s\" 옛 잠금 파일을 삭제할 수 없음: %m" -#: utils/init/miscinit.c:1368 +#: utils/init/miscinit.c:1418 #, c-format msgid "" "The file seems accidentally left over, but it could not be removed. Please " @@ -28659,48 +29967,48 @@ msgstr "" "셸 명령을 이용해서 파일을 삭제 하고 다시 시도해 보십시오. - 내용 참 거시기 하" "네" -#: utils/init/miscinit.c:1405 utils/init/miscinit.c:1419 -#: utils/init/miscinit.c:1430 +#: utils/init/miscinit.c:1455 utils/init/miscinit.c:1469 +#: utils/init/miscinit.c:1480 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "\"%s\" 잠금 파일에 쓸 수 없음: %m" -#: utils/init/miscinit.c:1541 utils/init/miscinit.c:1683 utils/misc/guc.c:5580 +#: utils/init/miscinit.c:1591 utils/init/miscinit.c:1733 utils/misc/guc.c:5765 #, c-format msgid "could not read from file \"%s\": %m" msgstr "\"%s\" 파일을 읽을 수 없음: %m" -#: utils/init/miscinit.c:1671 +#: utils/init/miscinit.c:1721 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "\"%s\" 파일을 열 수 없음: %m; 어째든 계속 진행함" -#: utils/init/miscinit.c:1696 +#: utils/init/miscinit.c:1746 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "\"%s\" 잠금 파일에 있는 PID 값이 이상합니다: 현재값 %ld, 원래값 %ld" -#: utils/init/miscinit.c:1735 utils/init/miscinit.c:1751 +#: utils/init/miscinit.c:1785 utils/init/miscinit.c:1801 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "\"%s\" 값은 바른 데이터디렉터리가 아닙니다" -#: utils/init/miscinit.c:1737 +#: utils/init/miscinit.c:1787 #, c-format msgid "File \"%s\" is missing." msgstr "\"%s\" 파일이 없습니다." -#: utils/init/miscinit.c:1753 +#: utils/init/miscinit.c:1803 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "\"%s\" 파일에 잘못된 자료가 기록되어 있습니다." -#: utils/init/miscinit.c:1755 +#: utils/init/miscinit.c:1805 #, c-format msgid "You might need to initdb." msgstr "initdb 명령을 실행해 새 클러스터를 만들어야 할 수도 있습니다." -#: utils/init/miscinit.c:1763 +#: utils/init/miscinit.c:1813 #, c-format msgid "" "The data directory was initialized by PostgreSQL version %s, which is not " @@ -28783,17 +30091,17 @@ msgstr "\"%s\" 데이터베이스 액세스 권한 없음" msgid "User does not have CONNECT privilege." msgstr "사용자에게 CONNECT 권한이 없습니다." -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:389 #, c-format msgid "too many connections for database \"%s\"" msgstr "\"%s\" 데이터베이스 최대 접속수를 초과했습니다" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:413 utils/init/postinit.c:420 #, c-format msgid "database locale is incompatible with operating system" msgstr "데이터베이스 로케일이 운영 체제와 호환되지 않음" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:414 #, c-format msgid "" "The database was initialized with LC_COLLATE \"%s\", which is not " @@ -28802,14 +30110,14 @@ msgstr "" "데이터베이스가 setlocale()에서 인식할 수 없는 LC_COLLATE \"%s\"(으)로 초기화" "되었습니다." -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:416 utils/init/postinit.c:423 #, c-format msgid "" "Recreate the database with another locale or install the missing locale." msgstr "" "다른 로케일로 데이터베이스를 다시 만들거나 누락된 로케일을 설치하십시오." -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:421 #, c-format msgid "" "The database was initialized with LC_CTYPE \"%s\", which is not recognized " @@ -28818,12 +30126,12 @@ msgstr "" "setlocale()에서 인식할 수 없는 \"%s\" LC_CTYPE 값으로 데이터베이스가 초기화되" "었습니다." -#: utils/init/postinit.c:475 +#: utils/init/postinit.c:493 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "\"%s\" 데이터베이스의 문자 정렬 규칙은 버전이 맞지 않음" -#: utils/init/postinit.c:477 +#: utils/init/postinit.c:495 #, c-format msgid "" "The database was created using collation version %s, but the operating " @@ -28832,7 +30140,7 @@ msgstr "" "데이터베이스를 만들때 %s 버전으로 문자 정렬 규칙을 만들었는데, 현재 OS는 %s " "버전을 제공하고 있습니다." -#: utils/init/postinit.c:480 +#: utils/init/postinit.c:498 #, c-format msgid "" "Rebuild all objects in this database that use the default collation and run " @@ -28843,59 +30151,59 @@ msgstr "" "VERSION 명령을 실행하거나, 바른 라이브러리 버전을 지정해서, PostgreSQL을 빌드" "하세요." -#: utils/init/postinit.c:891 +#: utils/init/postinit.c:904 #, c-format msgid "no roles are defined in this database system" msgstr "이 데이터베이스에는 어떠한 롤 정의도 없습니다" -#: utils/init/postinit.c:892 +#: utils/init/postinit.c:905 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "다음 명령을 먼저 실행하십시오: CREATE USER \"%s\" SUPERUSER;." -#: utils/init/postinit.c:928 +#: utils/init/postinit.c:942 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "슈퍼유저만 바이너리 업그레이드 모드 중에 연결 할 수 있음" -#: utils/init/postinit.c:949 +#: utils/init/postinit.c:962 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "남은 연결 슬롯은 %s 속성을 가진 롤용으로 남겨 놓았음" -#: utils/init/postinit.c:955 +#: utils/init/postinit.c:968 #, c-format msgid "" -"remaining connection slots are reserved for roles with privileges of the \"%s" -"\" role" +"remaining connection slots are reserved for roles with privileges of the " +"\"%s\" role" msgstr "남은 연결 슬롯은 \"%s\" 롤 권한이 있는 롤용으로 남겨 놓았음" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:980 #, c-format msgid "permission denied to start WAL sender" msgstr "WAL 송신기 시작할 권한 없음" -#: utils/init/postinit.c:968 +#: utils/init/postinit.c:981 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "WAL 송시기 시작은 %s 속성이 있는 롤만 할 수 있습니다." -#: utils/init/postinit.c:1086 +#: utils/init/postinit.c:1099 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "삭제되었거나 이름이 바뀐 것 같습니다." -#: utils/init/postinit.c:1090 +#: utils/init/postinit.c:1103 #, c-format msgid "database %u does not exist" msgstr "%u 데이터베이스가 없음" -#: utils/init/postinit.c:1099 +#: utils/init/postinit.c:1112 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "잘못된 \"%s\" 데이터베이스로 접속할 수 없음" -#: utils/init/postinit.c:1159 +#: utils/init/postinit.c:1173 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "데이터베이스 디렉터리에 \"%s\" 하위 디렉터리가 없습니다" @@ -28922,55 +30230,48 @@ msgstr "%d은(는) ISO 8859 문자 집합에 대한 예기치 않은 인코딩 I msgid "unexpected encoding ID %d for WIN character sets" msgstr "%d은(는) WIN 문자 집합에 대한 예기치 않은 인코딩 ID임" -#: utils/mb/mbutils.c:298 utils/mb/mbutils.c:901 +#: utils/mb/mbutils.c:297 utils/mb/mbutils.c:900 #, c-format msgid "conversion between %s and %s is not supported" msgstr "%s 인코딩과 %s 인코딩 사이의 변환은 지원하지 않습니다" -#: utils/mb/mbutils.c:386 -#, c-format -msgid "" -"default conversion function for encoding \"%s\" to \"%s\" does not exist" -msgstr "" -"\"%s\" 인코딩을 \"%s\" 인코딩으로 변환할 기본 변환규칙(conversion)이 없음" - -#: utils/mb/mbutils.c:403 utils/mb/mbutils.c:431 utils/mb/mbutils.c:816 -#: utils/mb/mbutils.c:843 +#: utils/mb/mbutils.c:402 utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 +#: utils/mb/mbutils.c:842 #, c-format msgid "String of %d bytes is too long for encoding conversion." msgstr "%d바이트의 문자열은 너무 길어서 인코딩 규칙에 맞지 않습니다." -#: utils/mb/mbutils.c:569 +#: utils/mb/mbutils.c:568 #, c-format msgid "invalid source encoding name \"%s\"" msgstr "\"%s\" 원본 인코딩 이름이 타당치 못함" -#: utils/mb/mbutils.c:574 +#: utils/mb/mbutils.c:573 #, c-format msgid "invalid destination encoding name \"%s\"" msgstr "\"%s\" 대상 인코딩 이름이 타당치 못함" -#: utils/mb/mbutils.c:714 +#: utils/mb/mbutils.c:713 #, c-format msgid "invalid byte value for encoding \"%s\": 0x%02x" msgstr "\"%s\" 인코딩에서 사용할 수 없는 바이트: 0x%02x" -#: utils/mb/mbutils.c:878 +#: utils/mb/mbutils.c:877 #, c-format msgid "invalid Unicode code point" msgstr "잘못된 유니코드 코드 포인트" -#: utils/mb/mbutils.c:1204 +#: utils/mb/mbutils.c:1201 #, c-format msgid "bind_textdomain_codeset failed" msgstr "bind_textdomain_codeset 실패" -#: utils/mb/mbutils.c:1725 +#: utils/mb/mbutils.c:1718 #, c-format msgid "invalid byte sequence for encoding \"%s\": %s" msgstr "\"%s\" 인코딩에서 사용할 수 없는 문자가 있음: %s" -#: utils/mb/mbutils.c:1758 +#: utils/mb/mbutils.c:1751 #, c-format msgid "" "character with byte sequence %s in encoding \"%s\" has no equivalent in " @@ -28989,13 +30290,13 @@ msgstr "비어 있는 환경 설정 디렉터리 이름: \"%s\"" msgid "could not open configuration directory \"%s\": %m" msgstr "\"%s\" 환경 설정 디렉터리를 열 수 없습니다: %m" -#: utils/misc/guc.c:115 +#: utils/misc/guc.c:122 msgid "" "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "" "이 매개 변수에 유효한 단위는 \"B\", \"kB\", \"MB\",\"GB\", \"TB\" 입니다." -#: utils/misc/guc.c:152 +#: utils/misc/guc.c:159 msgid "" "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", " "and \"d\"." @@ -29003,50 +30304,50 @@ msgstr "" "이 매개 변수에 유효한 단위는 \"us\", \"ms\", \"s\", \"min\", \"h\", \"d\" 입" "니다." -#: utils/misc/guc.c:421 +#: utils/misc/guc.c:430 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "알 수 없는 환경 매개 변수 이름 \"%s\", 해당 파일: \"%s\", 줄번호: %d" -#: utils/misc/guc.c:461 utils/misc/guc.c:3406 utils/misc/guc.c:3646 -#: utils/misc/guc.c:3744 utils/misc/guc.c:3842 utils/misc/guc.c:3966 -#: utils/misc/guc.c:4069 +#: utils/misc/guc.c:470 utils/misc/guc.c:3504 utils/misc/guc.c:3748 +#: utils/misc/guc.c:3846 utils/misc/guc.c:3944 utils/misc/guc.c:4071 +#: utils/misc/guc.c:4212 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "\"%s\" 매개 변수는 서버 재실행 없이 지금 변경 될 수 없음" -#: utils/misc/guc.c:497 +#: utils/misc/guc.c:506 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "환경설정 파일에 \"%s\" 매개 변수가 빠졌음, 초기값을 사용함" -#: utils/misc/guc.c:562 +#: utils/misc/guc.c:571 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "\"%s\" 매개 변수 값을 \"%s\"(으)로 바꿨음" -#: utils/misc/guc.c:604 +#: utils/misc/guc.c:613 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "\"%s\" 환경 설정파일에 오류가 있음" -#: utils/misc/guc.c:609 +#: utils/misc/guc.c:618 #, c-format msgid "" "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "\"%s\" 환경 설정 파일에 오류가 있어 새로 변경될 설정이 없습니다" -#: utils/misc/guc.c:614 +#: utils/misc/guc.c:623 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "\"%s\" 환경 설정 파일에 오류가 있어 아무 설정도 반영되지 않았습니다." -#: utils/misc/guc.c:1211 utils/misc/guc.c:1227 +#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "알 수 없는 환경 매개 변수 이름 \"%s\"" -#: utils/misc/guc.c:1213 +#: utils/misc/guc.c:1141 #, c-format msgid "" "Custom parameter names must be two or more simple identifiers separated by " @@ -29055,22 +30356,22 @@ msgstr "" "사용자 정의 환경 설정 변수 이름은 두 글자 이상의 식별자 이름과 점(.)을 구분자" "로 하는 이름이어야 합니다." -#: utils/misc/guc.c:1229 +#: utils/misc/guc.c:1157 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\" 이름은 예약된 접두사입니다." -#: utils/misc/guc.c:1243 +#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "알 수 없는 환경 매개 변수 이름: \"%s\"" -#: utils/misc/guc.c:1765 +#: utils/misc/guc.c:1802 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: \"%s\" 디렉터리에 액세스할 수 없음: %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: \"%s\" 디렉터리에 액세스할 수 없음: %m\n" -#: utils/misc/guc.c:1770 +#: utils/misc/guc.c:1806 #, c-format msgid "" "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" @@ -29078,7 +30379,7 @@ msgstr "" "initdb 명령이나, pg_basebackup 명령으로 PostgreSQL 데이터 디렉터리를 초기화 " "하세요.\n" -#: utils/misc/guc.c:1794 +#: utils/misc/guc.c:1830 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" @@ -29090,12 +30391,12 @@ msgstr "" "PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n" "이 프로그램을 다시 실행해 보십시오.\n" -#: utils/misc/guc.c:1817 +#: utils/misc/guc.c:1853 #, c-format -msgid "%s: could not access the server configuration file \"%s\": %s\n" -msgstr "%s: \"%s\" 환경 설정 파일을 접근할 수 없습니다: %s\n" +msgid "%s: could not access the server configuration file \"%s\": %m\n" +msgstr "%s: \"%s\" 환경 설정 파일을 접근할 수 없습니다: %m\n" -#: utils/misc/guc.c:1845 +#: utils/misc/guc.c:1881 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -29108,7 +30409,7 @@ msgstr "" "PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n" "이 프로그램을 다시 실행해 보십시오.\n" -#: utils/misc/guc.c:1897 +#: utils/misc/guc.c:1933 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" @@ -29121,7 +30422,7 @@ msgstr "" "PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n" "이 프로그램을 다시 실행해 보십시오.\n" -#: utils/misc/guc.c:1928 +#: utils/misc/guc.c:1964 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" @@ -29134,123 +30435,135 @@ msgstr "" "PGDATA 이름의 환경 변수를 만들고 그 값으로 해당 디렉터리를 지정한 뒤,\n" "이 프로그램을 다시 실행해 보십시오.\n" -#: utils/misc/guc.c:2894 +#: utils/misc/guc.c:2943 msgid "Value exceeds integer range." msgstr "값이 정수 범위를 초과합니다." -#: utils/misc/guc.c:3130 +#: utils/misc/guc.c:3185 #, c-format -msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)" -msgstr "%d%s%s 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%d .. %d)를 벗어남" +msgid "" +"%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" +msgstr "%d%s%s 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%d%s%s .. %d%s%s)를 벗어남" -#: utils/misc/guc.c:3166 +#: utils/misc/guc.c:3226 #, c-format -msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)" -msgstr "%g%s%s 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%g .. %g)를 벗어남" +msgid "" +"%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" +msgstr "%g%s%s 값은 \"%s\" 매개 변수의 값으로 타당한 범위(%g%s%s .. %g%s%s)를 벗어남" -#: utils/misc/guc.c:3366 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3465 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "병렬 작업 중에는 매개 변수를 설정할 수 없음" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "병렬 작업 중에는 \"%s\" 설정을 할 수 없음" -#: utils/misc/guc.c:3383 utils/misc/guc.c:4530 +#: utils/misc/guc.c:3481 utils/misc/guc.c:4696 #, c-format msgid "parameter \"%s\" cannot be changed" -msgstr "\"%s\" 매개 변수는 변경될 수 없음" +msgstr "\"%s\" 매개 변수는 바꿀 수 없음" -#: utils/misc/guc.c:3416 +#: utils/misc/guc.c:3514 #, c-format msgid "parameter \"%s\" cannot be changed now" -msgstr "\"%s\" 매개 변수는 지금 변경 될 수 없음" +msgstr "\"%s\" 매개 변수는 지금 바꿀 수 없음" -#: utils/misc/guc.c:3443 utils/misc/guc.c:3501 utils/misc/guc.c:4506 -#: utils/misc/guc.c:6546 +#: utils/misc/guc.c:3541 utils/misc/guc.c:3603 utils/misc/guc.c:4671 +#: utils/misc/guc.c:6756 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "\"%s\" 매개 변수를 지정할 권한이 없습니다." -#: utils/misc/guc.c:3481 +#: utils/misc/guc.c:3583 #, c-format msgid "parameter \"%s\" cannot be set after connection start" -msgstr "\"%s\" 매개 변수값은 연결 시작한 뒤에는 변경할 수 없습니다" +msgstr "\"%s\" 매개 변수값은 연결 시작한 뒤에는 바꿀 수 없습니다" -#: utils/misc/guc.c:3540 +#: utils/misc/guc.c:3642 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "보안 정의자 함수 내에서 \"%s\" 매개 변수를 설정할 수 없음" -#: utils/misc/guc.c:3561 +#: utils/misc/guc.c:3663 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "\"%s\" 매개 변수는 리셋할 수 없음" -#: utils/misc/guc.c:3568 +#: utils/misc/guc.c:3670 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "\"%s\" 매개 변수값은 함수 안에서 지역적으로 지정할 수 없습니다" -#: utils/misc/guc.c:4212 utils/misc/guc.c:4259 utils/misc/guc.c:5266 +#: utils/misc/guc.c:4370 utils/misc/guc.c:4418 utils/misc/guc.c:5450 #, c-format msgid "permission denied to examine \"%s\"" msgstr "\"%s\" 검사 권한 없음" -#: utils/misc/guc.c:4213 utils/misc/guc.c:4260 utils/misc/guc.c:5267 +#: utils/misc/guc.c:4371 utils/misc/guc.c:4419 utils/misc/guc.c:5451 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "이 매개 변수의 검사는 \"%s\" 롤 권한이 있는 롤만 할 수 있습니다." -#: utils/misc/guc.c:4496 +#: utils/misc/guc.c:4629 +#, c-format +msgid "ALTER SYSTEM is not allowed in this environment" +msgstr "ALTER SYSTEM 명령은 이 환경에서는 허용하지 않음" + +#: utils/misc/guc.c:4661 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "ALTER SYSTEM RESET ALL 실행 권한 없음" -#: utils/misc/guc.c:4562 +#: utils/misc/guc.c:4740 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "" "ALTER SYSTEM 명령으로 지정하는 매개 변수 값에는 줄바꿈 문자가 없어야 합니다" -#: utils/misc/guc.c:4608 +#: utils/misc/guc.c:4785 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "\"%s\" 파일의 내용을 분석할 수 없음" -#: utils/misc/guc.c:4790 +#: utils/misc/guc.c:4967 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "\"%s\" 매개 변수를 다시 정의하려고 함" -#: utils/misc/guc.c:5129 +#: utils/misc/guc.c:5306 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "알 수 없는 환경 매개 변수 이름 \"%s\", 이 설정은 지웁니다." -#: utils/misc/guc.c:5131 +#: utils/misc/guc.c:5308 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "\"%s\" 이름은 현재 예약된 접두사입니다." -#: utils/misc/guc.c:6000 +#: utils/misc/guc.c:6179 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "\"%s\" 매개 변수 값을 \"%s\" (으)로 바꾸는 중" -#: utils/misc/guc.c:6169 +#: utils/misc/guc.c:6348 #, c-format msgid "parameter \"%s\" could not be set" msgstr "\"%s\" 매개 변수는 설정할 수 없음" -#: utils/misc/guc.c:6259 +#: utils/misc/guc.c:6438 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "지정한 \"%s\" 매개 변수값의 구문분석을 실패했습니다." -#: utils/misc/guc.c:6678 +#: utils/misc/guc.c:6888 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "잘못된 \"%s\" 매개 변수의 값: %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "병렬 작업 중에는 매개 변수를 설정할 수 없음" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -29266,59 +30579,59 @@ msgstr "SET %s 명령은 하나의 값만 지정해야 합니다" msgid "SET requires parameter name" msgstr "SET 명령은 매개 변수 이름이 필요합니다" -#: utils/misc/guc_tables.c:662 +#: utils/misc/guc_tables.c:676 msgid "Ungrouped" msgstr "소속그룹없음" -#: utils/misc/guc_tables.c:664 +#: utils/misc/guc_tables.c:677 msgid "File Locations" msgstr "파일 위치" -#: utils/misc/guc_tables.c:666 +#: utils/misc/guc_tables.c:678 msgid "Connections and Authentication / Connection Settings" msgstr "연결과 인증 / 연결 설정" -#: utils/misc/guc_tables.c:668 +#: utils/misc/guc_tables.c:679 msgid "Connections and Authentication / TCP Settings" msgstr "연결과 인증 / TCP 설정" -#: utils/misc/guc_tables.c:670 +#: utils/misc/guc_tables.c:680 msgid "Connections and Authentication / Authentication" msgstr "연결과 인증 / 인증" -#: utils/misc/guc_tables.c:672 +#: utils/misc/guc_tables.c:681 msgid "Connections and Authentication / SSL" msgstr "연결과 인증 / SSL" -#: utils/misc/guc_tables.c:674 +#: utils/misc/guc_tables.c:682 msgid "Resource Usage / Memory" msgstr "자원 사용량 / 메모리" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:683 msgid "Resource Usage / Disk" msgstr "자원 사용량 / 디스크" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:684 msgid "Resource Usage / Kernel Resources" msgstr "자원 사용량 / 커널 자원" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:685 msgid "Resource Usage / Cost-Based Vacuum Delay" msgstr "자원 사용량 / 비용기반 청소 지연" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:686 msgid "Resource Usage / Background Writer" msgstr "자원 사용량 / 백그라운드 쓰기" -#: utils/misc/guc_tables.c:684 +#: utils/misc/guc_tables.c:687 msgid "Resource Usage / Asynchronous Behavior" msgstr "자원 사용량 / 비동기 기능" -#: utils/misc/guc_tables.c:686 +#: utils/misc/guc_tables.c:688 msgid "Write-Ahead Log / Settings" msgstr "Write-Ahead 로그 / 설정값" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:689 msgid "Write-Ahead Log / Checkpoints" msgstr "Write-Ahead 로그 / 체크포인트" @@ -29326,199 +30639,203 @@ msgstr "Write-Ahead 로그 / 체크포인트" msgid "Write-Ahead Log / Archiving" msgstr "Write-Ahead 로그 / 아카이브" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:691 msgid "Write-Ahead Log / Recovery" msgstr "Write-Ahead 로그 / 복구" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:692 msgid "Write-Ahead Log / Archive Recovery" msgstr "Write-Ahead 로그 / 아카이브 복구" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:693 msgid "Write-Ahead Log / Recovery Target" msgstr "Write-Ahead 로그 / 복구 대상" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:694 +msgid "Write-Ahead Log / Summarization" +msgstr "Write-Ahead 로그 / 요약" + +#: utils/misc/guc_tables.c:695 msgid "Replication / Sending Servers" msgstr "복제 / 보내기 서버" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:696 msgid "Replication / Primary Server" msgstr "복제 / 주 서버" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:697 msgid "Replication / Standby Servers" msgstr "복제 / 대기 서버" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:698 msgid "Replication / Subscribers" msgstr "복제 / 구독" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:699 msgid "Query Tuning / Planner Method Configuration" msgstr "쿼리 튜닝 / 실행계획기 메서드 설정" -#: utils/misc/guc_tables.c:708 +#: utils/misc/guc_tables.c:700 msgid "Query Tuning / Planner Cost Constants" msgstr "쿼리 튜닝 / 실행계획기 비용 상수" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:701 msgid "Query Tuning / Genetic Query Optimizer" msgstr "쿼리 튜닝 / 일반적인 쿼리 최적화기" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:702 msgid "Query Tuning / Other Planner Options" msgstr "쿼리 튜닝 / 기타 실행계획기 옵션들" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:703 msgid "Reporting and Logging / Where to Log" msgstr "보고와 로그 / 로그 위치" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:704 msgid "Reporting and Logging / When to Log" msgstr "보고와 로그 / 로그 시점" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:705 msgid "Reporting and Logging / What to Log" msgstr "보고와 로그 / 로그 내용" -#: utils/misc/guc_tables.c:720 +#: utils/misc/guc_tables.c:706 msgid "Reporting and Logging / Process Title" msgstr "보고와 로그 / 프로세스 타이틀" -#: utils/misc/guc_tables.c:722 +#: utils/misc/guc_tables.c:707 msgid "Statistics / Monitoring" msgstr "통계 / 모니터링" -#: utils/misc/guc_tables.c:724 +#: utils/misc/guc_tables.c:708 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "통계 / 쿼리 및 인덱스 누적 통계" -#: utils/misc/guc_tables.c:726 +#: utils/misc/guc_tables.c:709 msgid "Autovacuum" msgstr "Autovacuum" -#: utils/misc/guc_tables.c:728 +#: utils/misc/guc_tables.c:710 msgid "Client Connection Defaults / Statement Behavior" msgstr "클라이언트 연결 초기값 / 구문 특성" -#: utils/misc/guc_tables.c:730 +#: utils/misc/guc_tables.c:711 msgid "Client Connection Defaults / Locale and Formatting" msgstr "클라이언트 연결 초기값 / 로케일과 출력양식" -#: utils/misc/guc_tables.c:732 +#: utils/misc/guc_tables.c:712 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "클라이언트 연결 초기값 / 공유 라이브러리 미리 로딩" -#: utils/misc/guc_tables.c:734 +#: utils/misc/guc_tables.c:713 msgid "Client Connection Defaults / Other Defaults" msgstr "클라이언트 연결 초기값 / 기타 초기값" -#: utils/misc/guc_tables.c:736 +#: utils/misc/guc_tables.c:714 msgid "Lock Management" msgstr "잠금 관리" -#: utils/misc/guc_tables.c:738 +#: utils/misc/guc_tables.c:715 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "버전과 플랫폼 호환성 / 이전 PostgreSQL 버전" -#: utils/misc/guc_tables.c:740 +#: utils/misc/guc_tables.c:716 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "버전과 플랫폼 호환성 / 다른 플랫폼과 클라이언트" -#: utils/misc/guc_tables.c:742 +#: utils/misc/guc_tables.c:717 msgid "Error Handling" msgstr "오류 처리" -#: utils/misc/guc_tables.c:744 +#: utils/misc/guc_tables.c:718 msgid "Preset Options" msgstr "프리셋 옵션들" -#: utils/misc/guc_tables.c:746 +#: utils/misc/guc_tables.c:719 msgid "Customized Options" msgstr "사용자 정의 옵션들" -#: utils/misc/guc_tables.c:748 +#: utils/misc/guc_tables.c:720 msgid "Developer Options" msgstr "개발자 옵션들" -#: utils/misc/guc_tables.c:805 +#: utils/misc/guc_tables.c:775 msgid "Enables the planner's use of sequential-scan plans." msgstr "실행계획자가 순차적-스캔(sequential-sca) 계획을 사용함" -#: utils/misc/guc_tables.c:815 +#: utils/misc/guc_tables.c:785 msgid "Enables the planner's use of index-scan plans." msgstr "실행계획자가 인덱스-스캔 계획을 사용함." -#: utils/misc/guc_tables.c:825 +#: utils/misc/guc_tables.c:795 msgid "Enables the planner's use of index-only-scan plans." msgstr "실행계획자가 인덱스-전용-탐색 계획을 사용함." -#: utils/misc/guc_tables.c:835 +#: utils/misc/guc_tables.c:805 msgid "Enables the planner's use of bitmap-scan plans." msgstr "실행계획기가 bitmap-scan 계획을 사용하도록 함" -#: utils/misc/guc_tables.c:845 +#: utils/misc/guc_tables.c:815 msgid "Enables the planner's use of TID scan plans." msgstr "실행계획자가 TID 스캔 계획을 사용함" -#: utils/misc/guc_tables.c:855 +#: utils/misc/guc_tables.c:825 msgid "Enables the planner's use of explicit sort steps." msgstr "실행계획자가 명시 정렬 단계(explicit sort step)를 사용함" -#: utils/misc/guc_tables.c:865 +#: utils/misc/guc_tables.c:835 msgid "Enables the planner's use of incremental sort steps." msgstr "실행계획자가 증분 정렬 단계(incremental sort step)를 사용함" -#: utils/misc/guc_tables.c:875 +#: utils/misc/guc_tables.c:845 msgid "Enables the planner's use of hashed aggregation plans." msgstr "실행계획자가 해시된 집계 계획을 사용함" -#: utils/misc/guc_tables.c:885 +#: utils/misc/guc_tables.c:855 msgid "Enables the planner's use of materialization." msgstr "실행계획자가 materialization 계획을 사용함" -#: utils/misc/guc_tables.c:895 +#: utils/misc/guc_tables.c:865 msgid "Enables the planner's use of memoization." msgstr "실행계획자가 memoization 계획을 사용함" -#: utils/misc/guc_tables.c:905 +#: utils/misc/guc_tables.c:875 msgid "Enables the planner's use of nested-loop join plans." msgstr "실행계획자가 근접순환 조인(nested-loop join) 계획을 사용함" -#: utils/misc/guc_tables.c:915 +#: utils/misc/guc_tables.c:885 msgid "Enables the planner's use of merge join plans." msgstr "실행계획자가 병합 조인(merge join) 계획을 사용함" -#: utils/misc/guc_tables.c:925 +#: utils/misc/guc_tables.c:895 msgid "Enables the planner's use of hash join plans." msgstr "실행계획자가 해시 조인(hash join) 계획을 사용함" -#: utils/misc/guc_tables.c:935 +#: utils/misc/guc_tables.c:905 msgid "Enables the planner's use of gather merge plans." msgstr "실행계획자가 병합 수집(gather merge) 계획을 사용함" -#: utils/misc/guc_tables.c:945 +#: utils/misc/guc_tables.c:915 msgid "Enables partitionwise join." msgstr "partitionwise join 활성화" -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:925 msgid "Enables partitionwise aggregation and grouping." msgstr "partitionwise 집계 및 그룹핑 활성화" -#: utils/misc/guc_tables.c:965 +#: utils/misc/guc_tables.c:935 msgid "Enables the planner's use of parallel append plans." msgstr "실행계획자가 병렬 추가 계획을 사용함" -#: utils/misc/guc_tables.c:975 +#: utils/misc/guc_tables.c:945 msgid "Enables the planner's use of parallel hash plans." msgstr "실행계획자가 병렬 해시 계획을 사용함" -#: utils/misc/guc_tables.c:985 +#: utils/misc/guc_tables.c:955 msgid "Enables plan-time and execution-time partition pruning." msgstr "파티션 프루닝 계획수립 및 실행 시간 활성화" -#: utils/misc/guc_tables.c:986 +#: utils/misc/guc_tables.c:956 msgid "" "Allows the query planner and executor to compare partition bounds to " "conditions in the query to determine which partitions must be scanned." @@ -29526,7 +30843,7 @@ msgstr "" "쿼리 실행 계획기와 실행기가 조회해야할 파티션들이 어떤 것들인지 쿼리에서 범위" "를 판단하는 것을 허용함" -#: utils/misc/guc_tables.c:997 +#: utils/misc/guc_tables.c:967 msgid "" "Enables the planner's ability to produce plans that provide presorted input " "for ORDER BY / DISTINCT aggregate functions." @@ -29534,7 +30851,7 @@ msgstr "" "ORDER BY / DISTINCT 집계 함수 처리를 위해 미리 정렬된 입력을 제공하는 계획을 " "생성하는 실행 계획기 기능을 활성화함" -#: utils/misc/guc_tables.c:1000 +#: utils/misc/guc_tables.c:970 msgid "" "Allows the query planner to build plans that provide presorted input for " "aggregate functions with an ORDER BY / DISTINCT clause. When disabled, " @@ -29544,49 +30861,64 @@ msgstr "" "정렬된 입력을 제공하는 계획을 작성할 수 있습니다. 비활성화하면 쿼리 실행 중" "에 암묵적인 정렬을 항상 합니다." -#: utils/misc/guc_tables.c:1012 +#: utils/misc/guc_tables.c:982 msgid "Enables the planner's use of async append plans." msgstr "실행계획자가 비동기 추가 계획을 사용함" -#: utils/misc/guc_tables.c:1022 +#: utils/misc/guc_tables.c:992 +msgid "Enables reordering of GROUP BY keys." +msgstr "GROUP BY 키들의 재정렬 활성화" + +#: utils/misc/guc_tables.c:1002 msgid "Enables genetic query optimization." msgstr "유전적 쿼리 최적화(GEQO)를 사용함" -#: utils/misc/guc_tables.c:1023 +#: utils/misc/guc_tables.c:1003 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "이 알고리즘은 실행계획기의 과도한 작업 비용을 낮춥니다" -#: utils/misc/guc_tables.c:1034 +#: utils/misc/guc_tables.c:1017 msgid "Shows whether the current user is a superuser." msgstr "현재 사용자가 슈퍼유저인지 보여줍니다." -#: utils/misc/guc_tables.c:1044 +#: utils/misc/guc_tables.c:1032 +msgid "Allows running the ALTER SYSTEM command." +msgstr "ALTER SYSTEM 명령 실행 허용" + +#: utils/misc/guc_tables.c:1033 +msgid "" +"Can be set to off for environments where global configuration changes should " +"be made using a different method." +msgstr "다른 방법으로 전역 환경설정 값을 관리하는 환경에서는 off로 설정할 수 있습니다." + +#: utils/misc/guc_tables.c:1043 msgid "Enables advertising the server via Bonjour." msgstr "Bonjour 서버 사용" -#: utils/misc/guc_tables.c:1053 +#: utils/misc/guc_tables.c:1052 msgid "Collects transaction commit time." msgstr "트랜잭션 커밋 시간을 수집함" -#: utils/misc/guc_tables.c:1062 +#: utils/misc/guc_tables.c:1061 msgid "Enables SSL connections." msgstr "SSL 연결을 가능하게 함." -#: utils/misc/guc_tables.c:1071 -msgid "Controls whether ssl_passphrase_command is called during server reload." +#: utils/misc/guc_tables.c:1070 +msgid "" +"Controls whether \"ssl_passphrase_command\" is called during server reload." msgstr "" -"서버 reload 작업 중 ssl_passphrase_command 로 지정한 명령을 실행 할 것인지를 " +"서버 reload 작업 중 \"ssl_passphrase_command\" 로 지정한 명령을 실행 할 것인지를 " "제어함." -#: utils/misc/guc_tables.c:1080 +#: utils/misc/guc_tables.c:1079 msgid "Give priority to server ciphersuite order." msgstr "SSL 인증 알고리즘 우선 순위를 정함" -#: utils/misc/guc_tables.c:1089 +#: utils/misc/guc_tables.c:1088 msgid "Forces synchronization of updates to disk." msgstr "강제로 변경된 버퍼 자료를 디스크와 동기화 시킴." -#: utils/misc/guc_tables.c:1090 +#: utils/misc/guc_tables.c:1089 msgid "" "The server will use the fsync() system call in several places to make sure " "that updates are physically written to disk. This ensures that a database " @@ -29598,11 +30930,11 @@ msgstr "" "스템의 비정상적인 동작이나, 하드웨어에서 오류가 발생되었을 경우에도 자료를 안" "전하게 지킬 수 있도록 도와줄 것입니다." -#: utils/misc/guc_tables.c:1101 +#: utils/misc/guc_tables.c:1100 msgid "Continues processing after a checksum failure." msgstr "체크섬 실패 후 처리 계속 함" -#: utils/misc/guc_tables.c:1102 +#: utils/misc/guc_tables.c:1101 msgid "" "Detection of a checksum failure normally causes PostgreSQL to report an " "error, aborting the current transaction. Setting ignore_checksum_failure to " @@ -29617,51 +30949,51 @@ msgstr "" "니다. 이 설정은 데이터 클러스터에서 체크섬 기능이 활성화 되어 있는 경우에만 " "영향을 받습니다." -#: utils/misc/guc_tables.c:1116 +#: utils/misc/guc_tables.c:1115 msgid "Continues processing past damaged page headers." msgstr "손상된 자료 헤더 발견시 작업 진행 여부 선택" -#: utils/misc/guc_tables.c:1117 +#: utils/misc/guc_tables.c:1116 msgid "" "Detection of a damaged page header normally causes PostgreSQL to report an " -"error, aborting the current transaction. Setting zero_damaged_pages to true " -"causes the system to instead report a warning, zero out the damaged page, " -"and continue processing. This behavior will destroy data, namely all the " -"rows on the damaged page." +"error, aborting the current transaction. Setting \"zero_damaged_pages\" to " +"true causes the system to instead report a warning, zero out the damaged " +"page, and continue processing. This behavior will destroy data, namely all " +"the rows on the damaged page." msgstr "" "일반적으로 손상된 페이지 헤더를 발견하게 되면, PostgreSQL에서는 오류를 발생하" -"고, 현재 트랜잭션을 중지합니다. zero_damaged_pages 값을 true로 지정하면, 이" +"고, 현재 트랜잭션을 중지합니다. \"zero_damaged_pages\" 값을 true로 지정하면, 이" "런 손상된 페이지를 발견하면, 경고 메시지를 보여주고, 그 페이지의 크기를 0으" "로 만들고 작업을 계속 진행합니다. 이 기능을 사용한다 함은 손상된 자료를 없애" "겠다는 것을 의미합니다. 이것은 곧 저장되어있는 자료가 삭제 될 수도 있음을 의" "미하기도 합니다." -#: utils/misc/guc_tables.c:1130 +#: utils/misc/guc_tables.c:1129 msgid "Continues recovery after an invalid pages failure." msgstr "잘못된 페이지 실패 후 복구 계속 함" -#: utils/misc/guc_tables.c:1131 +#: utils/misc/guc_tables.c:1130 msgid "" "Detection of WAL records having references to invalid pages during recovery " "causes PostgreSQL to raise a PANIC-level error, aborting the recovery. " -"Setting ignore_invalid_pages to true causes the system to ignore invalid " +"Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid " "page references in WAL records (but still report a warning), and continue " "recovery. This behavior may cause crashes, data loss, propagate or hide " "corruption, or other serious problems. Only has an effect during recovery or " "in standby mode." msgstr "" "PostgreSQL은 WAL 기반 복구 작업에서 해당 페이지가 잘못되어 있으면, PANIC 오류" -"를 내고 복구 작업을 중지하고 멈춥니다. ignore_invalid_pages 값을 true로 지" +"를 내고 복구 작업을 중지하고 멈춥니다. \"ignore_invalid_pages\" 값을 true로 지" "정하면, 이런 손상된 페이지가 있을 때, 경고 메시지를 보여주고, 복구 작업 계속 " "진행합니다. 이 기능을 사용하면 서버 비정상 종료나 자료 손실 숨은 손상, 기타 " "심각한 문제가 일어 날 수 있습니다. 이 설정은 복구 작업 때나 대기 모드 상태에" "서만 작동합니다." -#: utils/misc/guc_tables.c:1149 +#: utils/misc/guc_tables.c:1148 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "체크포인트 후 처음 수정할 때 전체 페이지를 WAL에 씁니다." -#: utils/misc/guc_tables.c:1150 +#: utils/misc/guc_tables.c:1149 msgid "" "A page write in process during an operating system crash might be only " "partially written to disk. During recovery, the row changes stored in WAL " @@ -29673,7 +31005,7 @@ msgstr "" "없을 수도 있습니다. 이 옵션은 안전하게 복구가 가능하도록 체크포인트 후 처음 " "수정한 페이지는 그 페이지 전체를 WAL에 씁니다." -#: utils/misc/guc_tables.c:1163 +#: utils/misc/guc_tables.c:1162 msgid "" "Writes full pages to WAL when first modified after a checkpoint, even for a " "non-critical modification." @@ -29681,102 +31013,106 @@ msgstr "" "체크포인트 작업 후 자료 페이지에 첫 변경이 있는 경우, 치명적인 변경이 아닐지" "라도 해당 페이지 전체를 기록합니다." -#: utils/misc/guc_tables.c:1173 +#: utils/misc/guc_tables.c:1172 msgid "Writes zeroes to new WAL files before first use." msgstr "처음 사용 되기 전에 WAL 파일을 0으로 채웁니다." -#: utils/misc/guc_tables.c:1183 +#: utils/misc/guc_tables.c:1182 msgid "Recycles WAL files by renaming them." msgstr "파일 이름 변경으로 WAL 파일을 재사용합니다." -#: utils/misc/guc_tables.c:1193 +#: utils/misc/guc_tables.c:1192 msgid "Logs each checkpoint." msgstr "체크포인트 관련 정보를 기록합니다." -#: utils/misc/guc_tables.c:1202 +#: utils/misc/guc_tables.c:1201 msgid "Logs each successful connection." msgstr "연결 성공한 정보들 모두를 기록함" -#: utils/misc/guc_tables.c:1211 +#: utils/misc/guc_tables.c:1210 +msgid "Logs details of pre-authentication connection handshake." +msgstr "연결 맺기를 위한 사전 인증작업 관련 세부사항을 기록합니다." + +#: utils/misc/guc_tables.c:1220 msgid "Logs end of a session, including duration." msgstr "기간을 포함하여 세션의 끝을 기록합니다." -#: utils/misc/guc_tables.c:1220 +#: utils/misc/guc_tables.c:1229 msgid "Logs each replication command." msgstr "복제 관련 작업 내역을 기록합니다." -#: utils/misc/guc_tables.c:1229 +#: utils/misc/guc_tables.c:1238 msgid "Shows whether the running server has assertion checks enabled." msgstr "서버가 assertion 검사 기능이 활성화 되어 실행되는지 보여 줌" -#: utils/misc/guc_tables.c:1240 +#: utils/misc/guc_tables.c:1249 msgid "Terminate session on any error." msgstr "어떤 오류가 생기면 세션을 종료함" -#: utils/misc/guc_tables.c:1249 +#: utils/misc/guc_tables.c:1258 msgid "Reinitialize server after backend crash." msgstr "백엔드가 비정상 종료되면 서버를 재초기화함" -#: utils/misc/guc_tables.c:1258 +#: utils/misc/guc_tables.c:1267 msgid "Remove temporary files after backend crash." msgstr "백엔드 비정상 종료 뒤에는 임시 파일을 지웁니다." -#: utils/misc/guc_tables.c:1268 +#: utils/misc/guc_tables.c:1277 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "" "백엔드 비정상 종료 될 때 하위 프로세스에게 SIGQUIT 대신에 SIGABRT 신호를 보냄" -#: utils/misc/guc_tables.c:1278 +#: utils/misc/guc_tables.c:1287 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "멈춘 하위 프로세스에게 SIGKILL 대신에 SIGABRT 신호를 보냄" -#: utils/misc/guc_tables.c:1289 +#: utils/misc/guc_tables.c:1298 msgid "Logs the duration of each completed SQL statement." msgstr "SQL 명령 구문의 실행완료 시간을 기록함" -#: utils/misc/guc_tables.c:1298 +#: utils/misc/guc_tables.c:1307 msgid "Logs each query's parse tree." msgstr "각 쿼리의 구문 분석 트리를 기록합니다." -#: utils/misc/guc_tables.c:1307 +#: utils/misc/guc_tables.c:1316 msgid "Logs each query's rewritten parse tree." msgstr "각 쿼리의 재작성된 구문 분석 트리를 기록합니다." -#: utils/misc/guc_tables.c:1316 +#: utils/misc/guc_tables.c:1325 msgid "Logs each query's execution plan." msgstr "각 쿼리의 실행 계획을 기록합니다." -#: utils/misc/guc_tables.c:1325 +#: utils/misc/guc_tables.c:1334 msgid "Indents parse and plan tree displays." msgstr "구문과 실행계획을 보여 줄때, 들여쓰기를 함." -#: utils/misc/guc_tables.c:1334 +#: utils/misc/guc_tables.c:1343 msgid "Writes parser performance statistics to the server log." msgstr "구문분석 성능 통계를 서버 로그에 기록함." -#: utils/misc/guc_tables.c:1343 +#: utils/misc/guc_tables.c:1352 msgid "Writes planner performance statistics to the server log." msgstr "실행계획자 성능 통계를 서버 로그에 기록함." -#: utils/misc/guc_tables.c:1352 +#: utils/misc/guc_tables.c:1361 msgid "Writes executor performance statistics to the server log." msgstr "실행자 성능 통계를 서버 로그에 기록함." -#: utils/misc/guc_tables.c:1361 +#: utils/misc/guc_tables.c:1370 msgid "Writes cumulative performance statistics to the server log." msgstr "누적 성능 통계를 서버 로그에 기록함." -#: utils/misc/guc_tables.c:1371 +#: utils/misc/guc_tables.c:1380 msgid "" "Logs system resource usage statistics (memory and CPU) on various B-tree " "operations." msgstr "다양한 B트리 작업에 자원(메모리, CPU) 사용 통계를 기록에 남기" -#: utils/misc/guc_tables.c:1383 +#: utils/misc/guc_tables.c:1392 msgid "Collects information about executing commands." msgstr "명령 실행에 대한 정보를 수집함" -#: utils/misc/guc_tables.c:1384 +#: utils/misc/guc_tables.c:1393 msgid "" "Enables the collection of information on the currently executing command of " "each session, along with the time at which that command began execution." @@ -29784,67 +31120,67 @@ msgstr "" "각 세션에서 사용하고 있는 현재 실행 중인 명령의 수행 시간, 명령 내용등에 대" "한 정보를 수집하도록 함" -#: utils/misc/guc_tables.c:1394 +#: utils/misc/guc_tables.c:1403 msgid "Collects statistics on database activity." msgstr "데이터베이스 활동에 대한 통계를 수집합니다." -#: utils/misc/guc_tables.c:1403 +#: utils/misc/guc_tables.c:1412 msgid "Collects timing statistics for database I/O activity." msgstr "데이터베이스 I/O 활동에 대한 통계를 수집합니다." -#: utils/misc/guc_tables.c:1412 +#: utils/misc/guc_tables.c:1421 msgid "Collects timing statistics for WAL I/O activity." msgstr "WAL I/O 활동에 작업 시간 통계를 수집합니다." -#: utils/misc/guc_tables.c:1422 +#: utils/misc/guc_tables.c:1431 msgid "Updates the process title to show the active SQL command." msgstr "활성 SQL 명령을 표시하도록 프로세스 제목을 업데이트합니다." -#: utils/misc/guc_tables.c:1423 +#: utils/misc/guc_tables.c:1432 msgid "" "Enables updating of the process title every time a new SQL command is " "received by the server." msgstr "" "서버가 새 SQL 명령을 받을 때마다 프로세스 제목이 업데이트될 수 있도록 합니다." -#: utils/misc/guc_tables.c:1432 +#: utils/misc/guc_tables.c:1441 msgid "Starts the autovacuum subprocess." msgstr "자동 청소 하위 프로세스를 실행함" -#: utils/misc/guc_tables.c:1442 +#: utils/misc/guc_tables.c:1451 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "LISTEN, NOTIFY 명령 사용을 위한 디버깅 출력을 만듦." -#: utils/misc/guc_tables.c:1454 +#: utils/misc/guc_tables.c:1463 msgid "Emits information about lock usage." msgstr "잠금 사용 정보를 로그로 남김" -#: utils/misc/guc_tables.c:1464 +#: utils/misc/guc_tables.c:1473 msgid "Emits information about user lock usage." msgstr "사용자 잠금 사용 정보를 로그로 남김" -#: utils/misc/guc_tables.c:1474 +#: utils/misc/guc_tables.c:1483 msgid "Emits information about lightweight lock usage." msgstr "가벼운 잠금 사용 정보를 로그로 남김" -#: utils/misc/guc_tables.c:1484 +#: utils/misc/guc_tables.c:1493 msgid "" "Dumps information about all current locks when a deadlock timeout occurs." msgstr "교착 잠금 시간 제한 상황이 발생하면 그 때의 모든 잠금 정보를 보여줌" -#: utils/misc/guc_tables.c:1496 +#: utils/misc/guc_tables.c:1505 msgid "Logs long lock waits." msgstr "긴 잠금 대기를 기록합니다." -#: utils/misc/guc_tables.c:1505 +#: utils/misc/guc_tables.c:1514 msgid "Logs standby recovery conflict waits." msgstr "대기 서버 복구 충돌에 따른 대기 정보를 로그에 남깁니다." -#: utils/misc/guc_tables.c:1514 +#: utils/misc/guc_tables.c:1523 msgid "Logs the host name in the connection logs." msgstr "연결 기록에서 호스트 이름을 기록함." -#: utils/misc/guc_tables.c:1515 +#: utils/misc/guc_tables.c:1524 msgid "" "By default, connection logs only show the IP address of the connecting host. " "If you want them to show the host name you can turn this on, but depending " @@ -29855,11 +31191,11 @@ msgstr "" "true로 바꾼다면, 이 IP의 호스트 이름을 구해서 이 이름을 사용합니다 이것의 성" "능은 OS의 IP에서 이름구하기 성능과 관계됩니다." -#: utils/misc/guc_tables.c:1526 +#: utils/misc/guc_tables.c:1535 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "\"표현식=NULL\" 식을 \"표현식 IS NULL\"로 취급함." -#: utils/misc/guc_tables.c:1527 +#: utils/misc/guc_tables.c:1536 msgid "" "When turned on, expressions of the form expr = NULL (or NULL = expr) are " "treated as expr IS NULL, that is, they return true if expr evaluates to the " @@ -29870,10 +31206,6 @@ msgstr "" "표현식 = NULL 구문을 표현식 IS NULL 구문으로 바꾸어서 처리하도록 해서 계산에 " "따라 true, false를 반환합니다." -#: utils/misc/guc_tables.c:1539 -msgid "Enables per-database user names." -msgstr "per-database 사용자 이름 활성화." - #: utils/misc/guc_tables.c:1548 msgid "Sets the default read-only status of new transactions." msgstr "새로운 트랜잭션의 상태를 초기값으로 읽기전용으로 설정합니다." @@ -29984,29 +31316,33 @@ msgid "Sets whether to include or exclude transaction with recovery target." msgstr "복구 대상에서 트랜잭션을 포함할지 제외할지 선택합니다." #: utils/misc/guc_tables.c:1778 +msgid "Starts the WAL summarizer process to enable incremental backup." +msgstr "증분 백업을 허용하기 위해 WAL 요약 프로세스를 시작합니다." + +#: utils/misc/guc_tables.c:1788 msgid "Allows connections and queries during recovery." msgstr "복구 중에서도 접속과 쿼리 사용을 허용함" -#: utils/misc/guc_tables.c:1788 +#: utils/misc/guc_tables.c:1798 msgid "" "Allows feedback from a hot standby to the primary that will avoid query " "conflicts." msgstr "" "읽기 전용 보조 서버가 보내는 쿼리 충돌을 피하기 위한 피드백을 주 서버가 받음" -#: utils/misc/guc_tables.c:1798 +#: utils/misc/guc_tables.c:1808 msgid "Shows whether hot standby is currently active." msgstr "hot standby 가 활성화 되었는지 보여줌" -#: utils/misc/guc_tables.c:1809 +#: utils/misc/guc_tables.c:1819 msgid "Allows modifications of the structure of system tables." msgstr "시스템 테이블의 구조를 수정할 수 있도록 합니다." -#: utils/misc/guc_tables.c:1820 +#: utils/misc/guc_tables.c:1830 msgid "Disables reading from system indexes." msgstr "시스템 인덱스 읽기를 금지함" -#: utils/misc/guc_tables.c:1821 +#: utils/misc/guc_tables.c:1831 msgid "" "It does not prevent updating the indexes, so it is safe to use. The worst " "consequence is slowness." @@ -30014,16 +31350,16 @@ msgstr "" "이 설정이 활성화 되어도 그 인덱스는 갱신되어 사용하는데는 안전합니다. 하지" "만 서버가 전체적으로 늦어질 수 있습니다." -#: utils/misc/guc_tables.c:1832 +#: utils/misc/guc_tables.c:1842 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "테이블스페이스를 pg_tblspc 안에 바로 만듦, 테스팅용" -#: utils/misc/guc_tables.c:1843 +#: utils/misc/guc_tables.c:1853 msgid "" "Enables backward compatibility mode for privilege checks on large objects." msgstr "대형 개체에 대한 접근 권한 검사를 위한 하위 호환성이 있게 함" -#: utils/misc/guc_tables.c:1844 +#: utils/misc/guc_tables.c:1854 msgid "" "Skips privilege checks when reading or modifying large objects, for " "compatibility with PostgreSQL releases prior to 9.0." @@ -30031,84 +31367,99 @@ msgstr "" "PostgreSQL 9.0 이전 버전의 호환성을 위해 대형 개체에 대한 읽기, 변경 시 접근 " "권한 검사를 안 하도록 설정함" -#: utils/misc/guc_tables.c:1854 +#: utils/misc/guc_tables.c:1864 msgid "When generating SQL fragments, quote all identifiers." msgstr "SQL 구문을 만들 때, 모든 식별자는 따옴표를 사용함" -#: utils/misc/guc_tables.c:1864 +#: utils/misc/guc_tables.c:1874 msgid "Shows whether data checksums are turned on for this cluster." msgstr "이 클러스터에서 자료 체크섬 기능을 사용하는지 보여줌" -#: utils/misc/guc_tables.c:1875 +#: utils/misc/guc_tables.c:1885 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "syslog 사용시 메시지 중복을 방지하기 위해 일련 번호를 매깁니다." -#: utils/misc/guc_tables.c:1885 +#: utils/misc/guc_tables.c:1895 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "syslog 사용시 메시지를 한 줄에 1024 바이트만 쓰도록 나눕니다" -#: utils/misc/guc_tables.c:1895 +#: utils/misc/guc_tables.c:1905 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "Gather와 Gather Merge 작업을 서브플랜에서도 할지를 제어함." -#: utils/misc/guc_tables.c:1896 +#: utils/misc/guc_tables.c:1906 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "서브플랜에서 gather 노드를 실행할지, 단지 튜플만 모을지 지정" -#: utils/misc/guc_tables.c:1906 +#: utils/misc/guc_tables.c:1916 msgid "Allow JIT compilation." msgstr "JIT 짜깁기 허용" -#: utils/misc/guc_tables.c:1917 +#: utils/misc/guc_tables.c:1927 msgid "Register JIT-compiled functions with debugger." msgstr "디버거용 JIT 컴파일된 함수 등록" -#: utils/misc/guc_tables.c:1934 +#: utils/misc/guc_tables.c:1944 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "LLVM bitcode 출력에 JIT 디버깅 정보 함께 기록" -#: utils/misc/guc_tables.c:1945 +#: utils/misc/guc_tables.c:1955 msgid "Allow JIT compilation of expressions." msgstr "표현식의 JIT 짜깁기 허용" -#: utils/misc/guc_tables.c:1956 +#: utils/misc/guc_tables.c:1966 msgid "Register JIT-compiled functions with perf profiler." msgstr "perf 프로파일러용 JIT 컴파일된 함수 등록" -#: utils/misc/guc_tables.c:1973 +#: utils/misc/guc_tables.c:1983 msgid "Allow JIT compilation of tuple deforming." msgstr "튜플 deform에 JIT 짜깁기 허용" -#: utils/misc/guc_tables.c:1984 +#: utils/misc/guc_tables.c:1994 msgid "Whether to continue running after a failure to sync data files." msgstr "데이터 파일 동기화 작업 실패 뒤에도 실행을 계속할지 선택함" -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2003 msgid "" "Sets whether a WAL receiver should create a temporary replication slot if no " "permanent slot is configured." msgstr "" "WAL 수신기가 영구 슬롯 설정이 되어 있지 않을 때, 임시 복제 슬롯을 만들지 지정" -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2012 +msgid "Enables event triggers." +msgstr "이벤트 트리거 활성화합니다." + +#: utils/misc/guc_tables.c:2013 +msgid "When enabled, event triggers will fire for all applicable statements." +msgstr "활성화 되면, 구현 가능한 모든 구문에 대해서 이벤트 트리거가 실행됩니다." + +#: utils/misc/guc_tables.c:2022 +msgid "" +"Enables a physical standby to synchronize logical failover replication slots " +"from the primary server." +msgstr "" +"물리 복제 대기 서버가 주 서버로부터 논리 failover 복제 슬롯 동기화 하도록 합니다." + +#: utils/misc/guc_tables.c:2040 msgid "" "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "다음 WAL 파일로 강제 전환하기 전에 대기할 시간 지정" -#: utils/misc/guc_tables.c:2022 +#: utils/misc/guc_tables.c:2051 msgid "" "Sets the amount of time to wait after authentication on connection startup." msgstr "연결 작업시 인증이 끝난 뒤 대기 시간 지정" -#: utils/misc/guc_tables.c:2024 utils/misc/guc_tables.c:2658 +#: utils/misc/guc_tables.c:2053 utils/misc/guc_tables.c:2780 msgid "This allows attaching a debugger to the process." msgstr "이렇게 하면 디버거를 프로세스에 연결할 수 있습니다." -#: utils/misc/guc_tables.c:2033 +#: utils/misc/guc_tables.c:2062 msgid "Sets the default statistics target." msgstr "기본 통계 대상을 지정합니다." -#: utils/misc/guc_tables.c:2034 +#: utils/misc/guc_tables.c:2063 msgid "" "This applies to table columns that have not had a column-specific target set " "via ALTER TABLE SET STATISTICS." @@ -30116,12 +31467,12 @@ msgstr "" "특정 칼럼을 지정하지 않고 ALTER TABLE SET STATISTICS 명령을 사용했을 때, 통" "계 대상이 될 칼럼을 지정합니다." -#: utils/misc/guc_tables.c:2043 +#: utils/misc/guc_tables.c:2072 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "" "이 크기를 초과할 경우 하위 쿼리가 축소되지 않는 FROM 목록 크기를 설정합니다." -#: utils/misc/guc_tables.c:2045 +#: utils/misc/guc_tables.c:2074 msgid "" "The planner will merge subqueries into upper queries if the resulting FROM " "list would have no more than this many items." @@ -30129,12 +31480,12 @@ msgstr "" "결과 FROM 목록에 포함된 항목이 이 개수를 넘지 않는 경우 계획 관리자가 하" "위 쿼리를 상위 쿼리에 병합합니다." -#: utils/misc/guc_tables.c:2056 +#: utils/misc/guc_tables.c:2085 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "" "이 크기를 초과할 경우 JOIN 구문이 결합되지 않는 FROM 목록 크기를 설정합니다." -#: utils/misc/guc_tables.c:2058 +#: utils/misc/guc_tables.c:2087 msgid "" "The planner will flatten explicit JOIN constructs into lists of FROM items " "whenever a list of no more than this many items would result." @@ -30142,32 +31493,32 @@ msgstr "" "결과 목록에 포함된 항목이 이 개수를 넘지 않을 때마다 계획 관리자가 명시" "적 JOIN 구문을 FROM 항목 목록에 결합합니다." -#: utils/misc/guc_tables.c:2069 +#: utils/misc/guc_tables.c:2098 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "" "이 임계값을 초과할 경우 GEQO가 사용되는 FROM 항목의 임계값을 설정합니다." -#: utils/misc/guc_tables.c:2079 +#: utils/misc/guc_tables.c:2108 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "GEQO: 다른 GEQO 매개 변수의 기본 값을 설정하는 데 사용됩니다." -#: utils/misc/guc_tables.c:2089 +#: utils/misc/guc_tables.c:2118 msgid "GEQO: number of individuals in the population." msgstr "GEQO: 모집단의 개인 수입니다." -#: utils/misc/guc_tables.c:2090 utils/misc/guc_tables.c:2100 +#: utils/misc/guc_tables.c:2119 utils/misc/guc_tables.c:2129 msgid "Zero selects a suitable default value." msgstr "0을 지정하면 적절한 기본 값이 선택됩니다." -#: utils/misc/guc_tables.c:2099 +#: utils/misc/guc_tables.c:2128 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: 알고리즘의 반복 수입니다." -#: utils/misc/guc_tables.c:2111 +#: utils/misc/guc_tables.c:2140 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "교착 상태를 확인하기 전에 잠금을 기다릴 시간을 설정합니다." -#: utils/misc/guc_tables.c:2122 +#: utils/misc/guc_tables.c:2151 msgid "" "Sets the maximum delay before canceling queries when a hot standby server is " "processing archived WAL data." @@ -30175,38 +31526,38 @@ msgstr "" "읽기 전용 보조 서버가 아카이브된 WAL 자료를 처리할 때, 지연될 수 있는 최대 시" "간" -#: utils/misc/guc_tables.c:2133 +#: utils/misc/guc_tables.c:2162 msgid "" "Sets the maximum delay before canceling queries when a hot standby server is " "processing streamed WAL data." msgstr "" "읽기 전용 보조 서버가 스트림 WAL 자료를 처리할 때, 지연될 수 있는 최대 시간" -#: utils/misc/guc_tables.c:2144 +#: utils/misc/guc_tables.c:2173 msgid "Sets the minimum delay for applying changes during recovery." msgstr "변경 사항 반영을 위한 최소 지연 시간 지정" -#: utils/misc/guc_tables.c:2155 +#: utils/misc/guc_tables.c:2184 msgid "" "Sets the maximum interval between WAL receiver status reports to the sending " "server." msgstr "WAL 정보를 보내는 서버에게 WAL 수신기 상태를 보고하는 최대 간격" -#: utils/misc/guc_tables.c:2166 +#: utils/misc/guc_tables.c:2195 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "" "WAL 정보를 보내는 서버로부터 보낸 자료를 받기위해 기다릴 수 있는 최대 허용 시" "간을 설정합니다." -#: utils/misc/guc_tables.c:2177 +#: utils/misc/guc_tables.c:2206 msgid "Sets the maximum number of concurrent connections." msgstr "최대 동시 접속수를 지정합니다." -#: utils/misc/guc_tables.c:2188 +#: utils/misc/guc_tables.c:2217 msgid "Sets the number of connection slots reserved for superusers." msgstr "superuser 동시 접속수를 지정합니다." -#: utils/misc/guc_tables.c:2198 +#: utils/misc/guc_tables.c:2227 msgid "" "Sets the number of connection slots reserved for roles with privileges of " "pg_use_reserved_connections." @@ -30214,45 +31565,92 @@ msgstr "" "pg_use_reserved_connections 권한이 있는 롤의 예약된 연결 슬롯 수를 설정합니" "다." -#: utils/misc/guc_tables.c:2209 +#: utils/misc/guc_tables.c:2238 msgid "Amount of dynamic shared memory reserved at startup." msgstr "시작시 확보할 동적 공유 메모리 크기" -#: utils/misc/guc_tables.c:2224 +#: utils/misc/guc_tables.c:2253 msgid "Sets the number of shared memory buffers used by the server." msgstr "서버에서 사용할 공유 메모리 버퍼 개수를 지정함" -#: utils/misc/guc_tables.c:2235 +#: utils/misc/guc_tables.c:2264 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "VACUUM, ANALYZE, autovacuum 작업용 버퍼 풀 크기를 설정합니다." -#: utils/misc/guc_tables.c:2246 +#: utils/misc/guc_tables.c:2275 msgid "" "Shows the size of the server's main shared memory area (rounded up to the " "nearest MB)." msgstr "서버의 메인 공유 메모리 영역 크기를 보여줌(MB 단위로 근사값처리함)" -#: utils/misc/guc_tables.c:2257 +#: utils/misc/guc_tables.c:2286 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "메인 공유 메모리 영역용 huge 페이지 개수를 보여줌" -#: utils/misc/guc_tables.c:2258 +#: utils/misc/guc_tables.c:2287 msgid "-1 indicates that the value could not be determined." msgstr "-1 은 사용하지 않음을 뜻함" -#: utils/misc/guc_tables.c:2268 +#: utils/misc/guc_tables.c:2297 +msgid "" +"Sets the size of the dedicated buffer pool used for the commit timestamp " +"cache." +msgstr "커밋 시간 캐시용 버퍼 풀 크기 지정" + +#: utils/misc/guc_tables.c:2298 utils/misc/guc_tables.c:2353 +#: utils/misc/guc_tables.c:2364 +msgid "" +"Specify 0 to have this value determined as a fraction of shared_buffers." +msgstr "이 값을 shared_buffers의 일부로 하려면 0을 지정합니다." + +#: utils/misc/guc_tables.c:2308 +msgid "" +"Sets the size of the dedicated buffer pool used for the MultiXact member " +"cache." +msgstr "MultiXact 번호 캐시용 버퍼 풀 크기 지정" + +#: utils/misc/guc_tables.c:2319 +msgid "" +"Sets the size of the dedicated buffer pool used for the MultiXact offset " +"cache." +msgstr "MultiXact offset 캐시용 버퍼 풀 크기 지정" + +#: utils/misc/guc_tables.c:2330 +msgid "" +"Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY " +"message cache." +msgstr "LISTEN/NOTIFY 메시지 캐시용 버퍼 풀 크기 지정" + +#: utils/misc/guc_tables.c:2341 +msgid "" +"Sets the size of the dedicated buffer pool used for the serializable " +"transaction cache." +msgstr "직렬화 가능한 트랜잭션 캐시용 버퍼 풀 크기 지정" + +#: utils/misc/guc_tables.c:2352 +msgid "" +"Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "하위트랜잭션 캐시를 위한 버퍼 풀 크기를 지정합니다." + +#: utils/misc/guc_tables.c:2363 +msgid "" +"Sets the size of the dedicated buffer pool used for the transaction status " +"cache." +msgstr "트랜잭션 상태 캐시를 위한 버퍼 풀 크기를 지정합니다." + +#: utils/misc/guc_tables.c:2374 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "각 세션에서 사용하는 임시 버퍼의 최대 개수를 지정" -#: utils/misc/guc_tables.c:2279 +#: utils/misc/guc_tables.c:2385 msgid "Sets the TCP port the server listens on." msgstr "TCP 포트 번호를 지정함." -#: utils/misc/guc_tables.c:2289 +#: utils/misc/guc_tables.c:2395 msgid "Sets the access permissions of the Unix-domain socket." msgstr "유닉스 도메인 소켓 파일의 액세스 권한을 지정함" -#: utils/misc/guc_tables.c:2290 +#: utils/misc/guc_tables.c:2396 msgid "" "Unix-domain sockets use the usual Unix file system permission set. The " "parameter value is expected to be a numeric mode specification in the form " @@ -30263,11 +31661,11 @@ msgstr "" "수 값은 chmod 및 umask 시스템 호출에서 수락되는 형태의 숫자 모드 지정이어야 " "합니다. (일반적인 8진수 형식을 사용하려면 숫자가 0으로 시작해야 합니다.)" -#: utils/misc/guc_tables.c:2304 +#: utils/misc/guc_tables.c:2410 msgid "Sets the file permissions for log files." msgstr "로그 파일의 파일 접근 권한을 지정합니다." -#: utils/misc/guc_tables.c:2305 +#: utils/misc/guc_tables.c:2411 msgid "" "The parameter value is expected to be a numeric mode specification in the " "form accepted by the chmod and umask system calls. (To use the customary " @@ -30277,11 +31675,11 @@ msgstr "" "이어야 합니다. (일반적인 8진수 형식을 사용하려면 숫자가 0으로 시작해야 합니" "다.)" -#: utils/misc/guc_tables.c:2319 +#: utils/misc/guc_tables.c:2425 msgid "Shows the mode of the data directory." msgstr "데이터 디렉터리의 모드값을 보여줌" -#: utils/misc/guc_tables.c:2320 +#: utils/misc/guc_tables.c:2426 msgid "" "The parameter value is a numeric mode specification in the form accepted by " "the chmod and umask system calls. (To use the customary octal format the " @@ -30291,11 +31689,11 @@ msgstr "" "이어야 합니다. (일반적인 8진수 형식을 사용하려면 숫자가 0으로 시작해야 합니" "다.)" -#: utils/misc/guc_tables.c:2333 +#: utils/misc/guc_tables.c:2439 msgid "Sets the maximum memory to be used for query workspaces." msgstr "쿼리 작업공간을 위해 사용될 메모리의 최대값을 지정함." -#: utils/misc/guc_tables.c:2334 +#: utils/misc/guc_tables.c:2440 msgid "" "This much memory can be used by each internal sort operation and hash table " "before switching to temporary disk files." @@ -30303,128 +31701,136 @@ msgstr "" "임시 디스크 파일로 전환하기 전에 각 내부 정렬 작업과 해시 테이블에서 이 크기" "의 메모리를 사용할 수 있습니다." -#: utils/misc/guc_tables.c:2346 +#: utils/misc/guc_tables.c:2457 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "관리 작업을 위해 사용될 메모리의 최대값을 지정함." -#: utils/misc/guc_tables.c:2347 +#: utils/misc/guc_tables.c:2458 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "관리작업은 VACUUM, CREATE INDEX 같은 작업을 뜻합니다." -#: utils/misc/guc_tables.c:2357 +#: utils/misc/guc_tables.c:2468 msgid "Sets the maximum memory to be used for logical decoding." msgstr "논리 디코딩 작업을 위해 사용될 메모리의 최대값을 지정함." -#: utils/misc/guc_tables.c:2358 +#: utils/misc/guc_tables.c:2469 msgid "" "This much memory can be used by each internal reorder buffer before spilling " "to disk." msgstr "이 메모리는 디스크 기록 전에 각 내부 재정렬 버퍼로 사용될 수 있습니다." -#: utils/misc/guc_tables.c:2374 +#: utils/misc/guc_tables.c:2485 msgid "Sets the maximum stack depth, in kilobytes." msgstr "스택깊이(KB 단위) 최대값을 지정합니다." -#: utils/misc/guc_tables.c:2385 +#: utils/misc/guc_tables.c:2496 msgid "Limits the total size of all temporary files used by each process." msgstr "각 프로세스에서 사용하는 모든 임시 파일의 총 크기 제한" -#: utils/misc/guc_tables.c:2386 +#: utils/misc/guc_tables.c:2497 msgid "-1 means no limit." msgstr "-1은 제한 없음" -#: utils/misc/guc_tables.c:2396 +#: utils/misc/guc_tables.c:2507 msgid "Vacuum cost for a page found in the buffer cache." msgstr "버퍼 캐시에 있는 페이지의 청소 비용입니다." -#: utils/misc/guc_tables.c:2406 +#: utils/misc/guc_tables.c:2517 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "버퍼 캐시에 없는 페이지의 청소 비용입니다." -#: utils/misc/guc_tables.c:2416 +#: utils/misc/guc_tables.c:2527 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "청소로 페이지 변경 시 부과되는 비용입니다." -#: utils/misc/guc_tables.c:2426 +#: utils/misc/guc_tables.c:2537 msgid "Vacuum cost amount available before napping." msgstr "청소가 중지되는 청소 비용 합계입니다." -#: utils/misc/guc_tables.c:2436 +#: utils/misc/guc_tables.c:2547 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "자동 청소에 대한 청소가 중지되는 청소 비용 합계입니다." -#: utils/misc/guc_tables.c:2446 +#: utils/misc/guc_tables.c:2557 msgid "" "Sets the maximum number of simultaneously open files for each server process." msgstr "각각의 서버 프로세스에서 동시에 열릴 수 있는 최대 파일 갯수를 지정함." -#: utils/misc/guc_tables.c:2459 +#: utils/misc/guc_tables.c:2570 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "동시에 준비된 트랜잭션 최대 개수 지정" -#: utils/misc/guc_tables.c:2470 +#: utils/misc/guc_tables.c:2581 msgid "Sets the minimum OID of tables for tracking locks." msgstr "잠금 추적을 위한 테이블의 최소 OID 지정" -#: utils/misc/guc_tables.c:2471 +#: utils/misc/guc_tables.c:2582 msgid "Is used to avoid output on system tables." msgstr "시스템 테이블 출력 방지용" -#: utils/misc/guc_tables.c:2480 +#: utils/misc/guc_tables.c:2591 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "무조건 잠금 추적용 테이블 OID 지정" -#: utils/misc/guc_tables.c:2492 +#: utils/misc/guc_tables.c:2603 msgid "Sets the maximum allowed duration of any statement." msgstr "모든 쿼리문에 적용되는 허용되는 최대 수행시간" -#: utils/misc/guc_tables.c:2493 utils/misc/guc_tables.c:2504 -#: utils/misc/guc_tables.c:2515 utils/misc/guc_tables.c:2526 +#: utils/misc/guc_tables.c:2604 utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2626 utils/misc/guc_tables.c:2637 +#: utils/misc/guc_tables.c:2648 msgid "A value of 0 turns off the timeout." msgstr "이 값이 0이면 이런 제한이 없음." -#: utils/misc/guc_tables.c:2503 +#: utils/misc/guc_tables.c:2614 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "모든 잠금에 적용되는 기다리는 최대 대기 시간" -#: utils/misc/guc_tables.c:2514 +#: utils/misc/guc_tables.c:2625 msgid "" "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "idle-in-transaction 상태로 있을 수 있는 최대 시간 지정" -#: utils/misc/guc_tables.c:2525 +#: utils/misc/guc_tables.c:2636 +msgid "" +"Sets the maximum allowed duration of any transaction within a session (not a " +"prepared transaction)." +msgstr "한 세션에서 최대 유지할 수 있는 트랜잭션(미리 준비된 트랜잭션 아님) " +"시간을 지정합니다." + +#: utils/misc/guc_tables.c:2647 msgid "" "Sets the maximum allowed idle time between queries, when not in a " "transaction." msgstr "idle 상태로 있을 수 있는 최대 시간 지정" -#: utils/misc/guc_tables.c:2536 +#: utils/misc/guc_tables.c:2658 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "VACUUM에서 테이블 행을 동결할 때까지의 최소 기간입니다." -#: utils/misc/guc_tables.c:2546 +#: utils/misc/guc_tables.c:2668 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "" "VACUUM에서 튜플을 동결하기 위해 전체 테이블을 스캔할 때까지의 기간입니다." -#: utils/misc/guc_tables.c:2556 +#: utils/misc/guc_tables.c:2678 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "VACUUM에서 테이블 MultiXactId 동결할 때까지의 최소 기간입니다." -#: utils/misc/guc_tables.c:2566 +#: utils/misc/guc_tables.c:2688 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "" "VACUUM에서 튜플을 동결하기 위해 전체 테이블을 스캔할 때까지의 멀티트랜잭션 기" "간입니다." -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2698 msgid "" "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "" "VACUUM 작업에서 트랜잭션ID 겹침 방지를 피하기 위한 freeze 작업을 하는 테이블 " "나이" -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2707 msgid "" "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound " "outage." @@ -30432,40 +31838,40 @@ msgstr "" "VACUUM 작업에서 트랜잭션ID 겹침 방지를 피하기 위한 freeze 작업을 하는 멀티트" "랜잭션 나이" -#: utils/misc/guc_tables.c:2598 +#: utils/misc/guc_tables.c:2720 msgid "Sets the maximum number of locks per transaction." msgstr "하나의 트랜잭션에서 사용할 수 있는 최대 잠금 횟수를 지정함." -#: utils/misc/guc_tables.c:2599 +#: utils/misc/guc_tables.c:2721 msgid "" "The shared lock table is sized on the assumption that at most " -"max_locks_per_transaction objects per server process or prepared transaction " -"will need to be locked at any one time." +"\"max_locks_per_transaction\" objects per server process or prepared " +"transaction will need to be locked at any one time." msgstr "" "공유 잠금 테이블은 한 번에 잠궈야 할 고유 개체 수가 " -"max_locks_per_transaction * (max_connections 또는 미리 준비된 트랜잭션 수)를 " +"\"max_locks_per_transaction\" * (\"max_connections\" 또는 미리 준비된 트랜잭션 수)를 " "넘지 않는다는 가정 하에 크기가 지정됩니다." -#: utils/misc/guc_tables.c:2610 +#: utils/misc/guc_tables.c:2732 msgid "Sets the maximum number of predicate locks per transaction." msgstr "하나의 트랜잭션에서 사용할 수 있는 최대 잠금 횟수를 지정함." -#: utils/misc/guc_tables.c:2611 +#: utils/misc/guc_tables.c:2733 msgid "" "The shared predicate lock table is sized on the assumption that at most " -"max_pred_locks_per_transaction objects per server process or prepared " +"\"max_pred_locks_per_transaction\" objects per server process or prepared " "transaction will need to be locked at any one time." msgstr "" "공유 predicate 잠금 테이블은 한 번에 잠궈야 할 고유 개체 수가 " -"max_pred_locks_per_transaction * (max_connections 또는 미리 준비된 트랜잭션 " +"\"max_pred_locks_per_transaction\" * (\"max_connections\" 또는 미리 준비된 트랜잭션 " "수)를 넘지 않는다는 가정 하에 크기가 지정됩니다." -#: utils/misc/guc_tables.c:2622 +#: utils/misc/guc_tables.c:2744 msgid "" "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "릴레이션 당 최대 predicate-lock 페이지와 튜플 수 지정" -#: utils/misc/guc_tables.c:2623 +#: utils/misc/guc_tables.c:2745 msgid "" "If more than this total of pages and tuples in the same relation are locked " "by a connection, those locks are replaced by a relation-level lock." @@ -30473,11 +31879,11 @@ msgstr "" "한 연결에서 같은 릴레이션 대상으로 이 값보다 큰 페이지와 튜플을 잠근다면, 그 " "잠금은 릴레이션 수준 잠금으로 변경 된다." -#: utils/misc/guc_tables.c:2633 +#: utils/misc/guc_tables.c:2755 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "페이지당 predicate-lock 튜플 최대 수 지정." -#: utils/misc/guc_tables.c:2634 +#: utils/misc/guc_tables.c:2756 msgid "" "If more than this number of tuples on the same page are locked by a " "connection, those locks are replaced by a page-level lock." @@ -30485,49 +31891,53 @@ msgstr "" "한 연결에서 같은 페이지 대상으로 이 값보다 튜플을 잠근다면, 그 잠금은 페이지 " "수준 잠금으로 변경 된다." -#: utils/misc/guc_tables.c:2644 +#: utils/misc/guc_tables.c:2766 msgid "Sets the maximum allowed time to complete client authentication." msgstr "클라이언트 인증을 완료할 수 있는 최대 허용 시간을 설정합니다." -#: utils/misc/guc_tables.c:2656 +#: utils/misc/guc_tables.c:2778 msgid "" "Sets the amount of time to wait before authentication on connection startup." msgstr "연결 할 때 인증 전 기다리는 시간 지정" -#: utils/misc/guc_tables.c:2668 +#: utils/misc/guc_tables.c:2790 +msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." +msgstr "NOTIFY / LISTEN 큐용 할당된 페이지 최대치 지정" + +#: utils/misc/guc_tables.c:2800 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "복구에서 WAL 미리 읽을 버퍼 크기" -#: utils/misc/guc_tables.c:2669 +#: utils/misc/guc_tables.c:2801 msgid "" "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "" "참조된 데이터 블록을 미리 가져오기 위해 WAL에서 미리 읽을 수 있는 최대 거리." -#: utils/misc/guc_tables.c:2679 +#: utils/misc/guc_tables.c:2811 msgid "Sets the size of WAL files held for standby servers." msgstr "대기 서버를 위해 보관하고 있을 WAL 파일 크기를 지정" -#: utils/misc/guc_tables.c:2690 +#: utils/misc/guc_tables.c:2822 msgid "Sets the minimum size to shrink the WAL to." msgstr "WAL 최소 크기" -#: utils/misc/guc_tables.c:2702 +#: utils/misc/guc_tables.c:2834 msgid "Sets the WAL size that triggers a checkpoint." msgstr "체크포인트 작업을 할 WAL 크기 지정" -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2846 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "자동 WAL 체크포인트 사이의 최대 간격을 설정합니다." -#: utils/misc/guc_tables.c:2725 +#: utils/misc/guc_tables.c:2857 msgid "" "Sets the maximum time before warning if checkpoints triggered by WAL volume " "happen too frequently." msgstr "" "WAL 기록 때문에 자주 발생하는 체크포인트 경고를 보이지 않는 최대 시간 지정" -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2859 msgid "" "Write a message to the server log if checkpoints caused by the filling of " "WAL segment files happen more frequently than this amount of time. Zero " @@ -30537,69 +31947,76 @@ msgstr "" "용이 꽉 차는 사태가 발생하면 경고 메시지를 서버 로그에 남깁니다. 이 값을 0으" "로 지정하면 경고 남기지 않음" -#: utils/misc/guc_tables.c:2740 utils/misc/guc_tables.c:2958 -#: utils/misc/guc_tables.c:2998 +#: utils/misc/guc_tables.c:2872 utils/misc/guc_tables.c:3090 +#: utils/misc/guc_tables.c:3144 msgid "" "Number of pages after which previously performed writes are flushed to disk." msgstr "쓰기 작업 뒤 디스크 동기화를 수행할 페이지 수" -#: utils/misc/guc_tables.c:2751 +#: utils/misc/guc_tables.c:2883 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "" "WAL 기능을 위해 공유 메모리에서 사용할 디스크 페이지 버퍼 개수를 지정함." -#: utils/misc/guc_tables.c:2762 +#: utils/misc/guc_tables.c:2884 +msgid "" +"Specify -1 to have this value determined as a fraction of shared_buffers." +msgstr "shared_buffers 일부로 지정하려면 -1" + +#: utils/misc/guc_tables.c:2894 msgid "Time between WAL flushes performed in the WAL writer." msgstr "WAL 기록자가 지정 시간 만큼 쉬고 쓰기 작업을 반복함" -#: utils/misc/guc_tables.c:2773 +#: utils/misc/guc_tables.c:2905 msgid "Amount of WAL written out by WAL writer that triggers a flush." -msgstr "" +msgstr "WAL 쓰기 프로세스가 이 양만큼 쓰고 flush 합니다." -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2916 msgid "Minimum size of new file to fsync instead of writing WAL." -msgstr "" +msgstr "WAL 쓰기 대신해서 fsync할 새 파일의 최소 크기" -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2927 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "동시에 작동할 WAL 송신 프로세스 최대 수 지정" -#: utils/misc/guc_tables.c:2806 +#: utils/misc/guc_tables.c:2938 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "동시에 사용할 수 있는 복제 슬롯 최대 수 지정" -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2948 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "복제 슬롯을 위해 보관할 최대 WAL 크기 지정" -#: utils/misc/guc_tables.c:2817 +#: utils/misc/guc_tables.c:2949 msgid "" "Replication slots will be marked as failed, and segments released for " "deletion or recycling, if this much space is occupied by WAL on disk." msgstr "" +"디스크에서 WAL이 이 정도의 공간을 차지하면 복제 슬롯은 실패로 표시되고, " +"WAL 조각 파일들은 삭제 또는 재활용 됩니다." -#: utils/misc/guc_tables.c:2829 +#: utils/misc/guc_tables.c:2961 msgid "Sets the maximum time to wait for WAL replication." msgstr "WAL 복제를 위해 기다릴 최대 시간 설정" -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2972 msgid "" "Sets the delay in microseconds between transaction commit and flushing WAL " "to disk." msgstr "" "트랜잭션과 트랜잭션 로그의 적용 사이의 간격을 microsecond 단위로 지정함" -#: utils/misc/guc_tables.c:2852 +#: utils/misc/guc_tables.c:2984 msgid "" "Sets the minimum number of concurrent open transactions required before " -"performing commit_delay." -msgstr "commit_delay 처리하기 전에 있는 최소 동시 열려 있는 트랜잭션 개수." +"performing \"commit_delay\"." +msgstr "\"commit_delay\" 처리하기 전에 있는 최소 동시 열려 있는 트랜잭션 개수." -#: utils/misc/guc_tables.c:2863 +#: utils/misc/guc_tables.c:2995 msgid "Sets the number of digits displayed for floating-point values." msgstr "부동소수형 값을 표기할 때 " -#: utils/misc/guc_tables.c:2864 +#: utils/misc/guc_tables.c:2996 msgid "" "This affects real, double precision, and geometric data types. A zero or " "negative parameter value is added to the standard number of digits (FLT_DIG " @@ -30610,7 +32027,7 @@ msgstr "" "은 정수여야 합니다(FLT_DIG or DBL_DIG as appropriate - 무슨 말인지). 음수면 " "그 만큼 소숫점 자리를 더 많이 생략해서 정확도를 떨어뜨립니다." -#: utils/misc/guc_tables.c:2876 +#: utils/misc/guc_tables.c:3008 msgid "" "Sets the minimum execution time above which a sample of statements will be " "logged. Sampling is determined by log_statement_sample_rate." @@ -30618,20 +32035,20 @@ msgstr "" "log_statement_sample_rate 설정으로 수집할 로그 가운데, 기록할 최소 쿼리 수행 " "시간" -#: utils/misc/guc_tables.c:2879 +#: utils/misc/guc_tables.c:3011 msgid "Zero logs a sample of all queries. -1 turns this feature off." msgstr "0을 지정하면 모든 쿼리를 로깅하고, -1을 지정하면 이 기능이 해제됩니다." -#: utils/misc/guc_tables.c:2889 +#: utils/misc/guc_tables.c:3021 msgid "" "Sets the minimum execution time above which all statements will be logged." msgstr "모든 실행 쿼리문을 로그로 남길 최소 실행 시간을 설정합니다." -#: utils/misc/guc_tables.c:2891 +#: utils/misc/guc_tables.c:3023 msgid "Zero prints all queries. -1 turns this feature off." msgstr "0을 지정하면 모든 쿼리를 로깅하고, -1을 지정하면 이 기능이 해제됩니다." -#: utils/misc/guc_tables.c:2901 +#: utils/misc/guc_tables.c:3033 msgid "" "Sets the minimum execution time above which autovacuum actions will be " "logged." @@ -30639,192 +32056,192 @@ msgstr "" "이 시간을 초과할 경우 자동 청소 작업 로그를 남길 최소 실행 시간을 설정합니" "다." -#: utils/misc/guc_tables.c:2903 +#: utils/misc/guc_tables.c:3035 msgid "Zero prints all actions. -1 turns autovacuum logging off." msgstr "" "0을 지정하면 모든 작업을 로깅하고, -1을 지정하면 자동 청소관련 로그를 남기지 " "않음" -#: utils/misc/guc_tables.c:2913 +#: utils/misc/guc_tables.c:3045 msgid "" "Sets the maximum length in bytes of data logged for bind parameter values " "when logging statements." msgstr "쿼리문 로그 저장에 쓸 매개변수 값의 최대 길이 바이트" -#: utils/misc/guc_tables.c:2915 utils/misc/guc_tables.c:2927 +#: utils/misc/guc_tables.c:3047 utils/misc/guc_tables.c:3059 msgid "-1 to print values in full." msgstr "-1은 길이 제한 없이 전체" -#: utils/misc/guc_tables.c:2925 +#: utils/misc/guc_tables.c:3057 msgid "" "Sets the maximum length in bytes of data logged for bind parameter values " "when logging statements, on error." msgstr "쿼리 오류 시 쿼리문 로그 저장에 쓸 매개변수 값의 최대 길이 바이트" -#: utils/misc/guc_tables.c:2937 +#: utils/misc/guc_tables.c:3069 msgid "Background writer sleep time between rounds." msgstr "백그라운드 기록자의 잠자는 시간" -#: utils/misc/guc_tables.c:2948 +#: utils/misc/guc_tables.c:3080 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "라운드당 플러시할 백그라운드 작성기 최대 LRU 페이지 수입니다." -#: utils/misc/guc_tables.c:2971 +#: utils/misc/guc_tables.c:3103 msgid "" "Number of simultaneous requests that can be handled efficiently by the disk " "subsystem." msgstr "디스크 하위 시스템에서 효율적으로 처리할 수 있는 동시 요청 수입니다." -#: utils/misc/guc_tables.c:2985 +#: utils/misc/guc_tables.c:3117 msgid "" -"A variant of effective_io_concurrency that is used for maintenance work." +"A variant of \"effective_io_concurrency\" that is used for maintenance work." msgstr "" +"유지보수 작업에 사용되는 \"effective_io_concurrency\"의 변형입니다." -#: utils/misc/guc_tables.c:3011 +#: utils/misc/guc_tables.c:3132 +msgid "Limit on the size of data reads and writes." +msgstr "데이터 읽기 쓰기 크기의 제한을 겁니다." + +#: utils/misc/guc_tables.c:3157 msgid "Maximum number of concurrent worker processes." msgstr "동시 작업자 프로세스의 최대 수" -#: utils/misc/guc_tables.c:3023 +#: utils/misc/guc_tables.c:3169 msgid "Maximum number of logical replication worker processes." msgstr "논리 복제 작업자 프로세스의 최대 수" -#: utils/misc/guc_tables.c:3035 +#: utils/misc/guc_tables.c:3181 msgid "Maximum number of table synchronization workers per subscription." msgstr "구독을 위한 테이블 동기화 작업자의 최대 수" -#: utils/misc/guc_tables.c:3047 +#: utils/misc/guc_tables.c:3193 msgid "Maximum number of parallel apply workers per subscription." msgstr "구독을 위한 테이블 병렬 동기화 작업자의 최대 수" -#: utils/misc/guc_tables.c:3057 +#: utils/misc/guc_tables.c:3203 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "강제 로그 파일 바꾸기 전 대기 시간 지정" -#: utils/misc/guc_tables.c:3069 +#: utils/misc/guc_tables.c:3215 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "로그 파일 바꾸기 전 최대 로그 파일 크기 지정" -#: utils/misc/guc_tables.c:3081 +#: utils/misc/guc_tables.c:3227 msgid "Shows the maximum number of function arguments." msgstr "함수 인자의 최대 갯수를 보여줍니다" -#: utils/misc/guc_tables.c:3092 +#: utils/misc/guc_tables.c:3238 msgid "Shows the maximum number of index keys." msgstr "인덱스 키의 최대개수를 보여줍니다." -#: utils/misc/guc_tables.c:3103 +#: utils/misc/guc_tables.c:3249 msgid "Shows the maximum identifier length." msgstr "최대 식별자 길이를 표시합니다." -#: utils/misc/guc_tables.c:3114 +#: utils/misc/guc_tables.c:3260 msgid "Shows the size of a disk block." msgstr "디스크 블록의 크기를 표시합니다." -#: utils/misc/guc_tables.c:3125 +#: utils/misc/guc_tables.c:3271 msgid "Shows the number of pages per disk file." msgstr "디스크 파일당 페이지 수를 표시합니다." -#: utils/misc/guc_tables.c:3136 +#: utils/misc/guc_tables.c:3282 msgid "Shows the block size in the write ahead log." msgstr "미리 쓰기 로그의 블록 크기를 표시합니다." -#: utils/misc/guc_tables.c:3147 +#: utils/misc/guc_tables.c:3293 msgid "" "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "" +"실패한 시도 후 WAL 검색을 다시 시도하기 전에 기다리는 시간을 설정합니다." -#: utils/misc/guc_tables.c:3159 +#: utils/misc/guc_tables.c:3305 msgid "Shows the size of write ahead log segments." msgstr "미리 쓰기 로그 세그먼트당 페이지 크기를 표시합니다." -#: utils/misc/guc_tables.c:3172 +#: utils/misc/guc_tables.c:3318 +msgid "Time for which WAL summary files should be kept." +msgstr "WAL 요약 파일을 보관해야 하는 시간입니다." + +#: utils/misc/guc_tables.c:3331 msgid "Time to sleep between autovacuum runs." msgstr "자동 청소 실행 사이의 절전 모드 시간입니다." -#: utils/misc/guc_tables.c:3182 +#: utils/misc/guc_tables.c:3341 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "청소 전의 최소 튜플 업데이트 또는 삭제 수입니다." -#: utils/misc/guc_tables.c:3191 +#: utils/misc/guc_tables.c:3350 msgid "" "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert " "vacuums." msgstr "청소를 위한 최소 튜플 삽입 수입니다. -1은 insert는 vacuum에서 제외" -#: utils/misc/guc_tables.c:3200 +#: utils/misc/guc_tables.c:3359 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "통계 정보 수집을 위한 최소 튜플 삽입, 업데이트 또는 삭제 수입니다." -#: utils/misc/guc_tables.c:3210 +#: utils/misc/guc_tables.c:3369 msgid "" "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "" "트랜잭션 ID 겹침 방지를 위해 테이블에 대해 autovacuum 작업을 수행할 테이블 나" "이를 지정합니다." -#: utils/misc/guc_tables.c:3222 +#: utils/misc/guc_tables.c:3381 msgid "" "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "" "멀티 트랜잭션 ID 겹침 방지를 위해 테이블에 대해 autovacuum 작업을 수행할 트랜" "잭션 나이를 지정합니다." -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3391 msgid "" "Sets the maximum number of simultaneously running autovacuum worker " "processes." msgstr "동시에 작업할 수 있는 autovacuum 작업자 최대 수 지정" -#: utils/misc/guc_tables.c:3242 +#: utils/misc/guc_tables.c:3401 msgid "" "Sets the maximum number of parallel processes per maintenance operation." msgstr "유지보수 작업에서 사용할 병렬 프로세스 최대 수를 지정" -#: utils/misc/guc_tables.c:3252 +#: utils/misc/guc_tables.c:3411 msgid "Sets the maximum number of parallel processes per executor node." msgstr "실행 노드당 최대 병렬 처리 수 지정" -#: utils/misc/guc_tables.c:3263 +#: utils/misc/guc_tables.c:3422 msgid "" "Sets the maximum number of parallel workers that can be active at one time." msgstr "한번에 작업할 수 있는 병렬 작업자 최대 수 지정" -#: utils/misc/guc_tables.c:3274 +#: utils/misc/guc_tables.c:3433 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "각 autovacuum 작업자 프로세스가 사용할 메모리 최대치" -#: utils/misc/guc_tables.c:3285 -msgid "" -"Time before a snapshot is too old to read pages changed after the snapshot " -"was taken." -msgstr "" - -#: utils/misc/guc_tables.c:3286 -msgid "A value of -1 disables this feature." -msgstr "이 값이 -1 이면 이 기능 사용 안함" - -#: utils/misc/guc_tables.c:3296 +#: utils/misc/guc_tables.c:3444 msgid "Time between issuing TCP keepalives." msgstr "TCP 연결 유지 실행 간격입니다." -#: utils/misc/guc_tables.c:3297 utils/misc/guc_tables.c:3308 -#: utils/misc/guc_tables.c:3432 +#: utils/misc/guc_tables.c:3445 utils/misc/guc_tables.c:3456 +#: utils/misc/guc_tables.c:3580 msgid "A value of 0 uses the system default." msgstr "이 값이 0이면 시스템 기본 값" -#: utils/misc/guc_tables.c:3307 +#: utils/misc/guc_tables.c:3455 msgid "Time between TCP keepalive retransmits." msgstr "TCP keepalive 시간 설정" -#: utils/misc/guc_tables.c:3318 +#: utils/misc/guc_tables.c:3466 msgid "SSL renegotiation is no longer supported; this can only be 0." -msgstr "" +msgstr "SSL 재협상은 더 이상 지원되지 않습니다. 이 값은 0만 가능합니다." -#: utils/misc/guc_tables.c:3329 +#: utils/misc/guc_tables.c:3477 msgid "Maximum number of TCP keepalive retransmits." msgstr "TCP keepalive 확인 최대 횟수" -#: utils/misc/guc_tables.c:3330 +#: utils/misc/guc_tables.c:3478 msgid "" "Number of consecutive keepalive retransmits that can be lost before a " "connection is considered dead. A value of 0 uses the system default." @@ -30832,15 +32249,15 @@ msgstr "" "연결이 중단된 것으로 간주되기 전에 연결 유지 요청을 위한 연속적인 keepalive " "패킷 전송 수. 0을 지정하면 시스템 기본 값이 사용됩니다." -#: utils/misc/guc_tables.c:3341 +#: utils/misc/guc_tables.c:3489 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "정확한 GIN 기준 검색에 허용되는 최대 결과 수를 설정합니다." -#: utils/misc/guc_tables.c:3352 +#: utils/misc/guc_tables.c:3500 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "디스크 캐시 총 크기에 대한 계획 관리자의 가정을 설정합니다." -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3501 msgid "" "That is, the total size of the caches (kernel cache and shared buffers) used " "for PostgreSQL data files. This is measured in disk pages, which are " @@ -30849,85 +32266,89 @@ msgstr "" "즉, PostgreSQL에서 사용하는 총 캐시 크기입니다(커널 캐시와 공유 버퍼 모두 포" "함). 이 값은 디스크 페이지 단위로 측정되며, 일반적으로 각각 8kB입니다." -#: utils/misc/guc_tables.c:3364 +#: utils/misc/guc_tables.c:3512 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "병렬 조회를 위한 최소 테이블 자료량 지정" -#: utils/misc/guc_tables.c:3365 +#: utils/misc/guc_tables.c:3513 msgid "" "If the planner estimates that it will read a number of table pages too small " "to reach this limit, a parallel scan will not be considered." msgstr "" +"실행계획기가 이 한계에 도달하기에는 너무 작은 수의 테이블 페이지를 읽을 것으로 " +"추정하는 경우 병렬 스캔은 고려하지 않습니다." -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3523 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "병렬 조회를 위한 최소 인덱스 자료량 지정" -#: utils/misc/guc_tables.c:3376 +#: utils/misc/guc_tables.c:3524 msgid "" "If the planner estimates that it will read a number of index pages too small " "to reach this limit, a parallel scan will not be considered." msgstr "" +"실행계획기가 이 한계에 도달하기에는 너무 작은 수의 인덱스 페이지를 읽을 것으로 " +"추정하는 경우 병렬 스캔은 고려하지 않습니다." -#: utils/misc/guc_tables.c:3387 +#: utils/misc/guc_tables.c:3535 msgid "Shows the server version as an integer." msgstr "서버 버전을 정수형으로 보여줍니다" -#: utils/misc/guc_tables.c:3398 +#: utils/misc/guc_tables.c:3546 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "이 킬로바이트 수보다 큰 임시 파일의 사용을 기록합니다." -#: utils/misc/guc_tables.c:3399 +#: utils/misc/guc_tables.c:3547 msgid "Zero logs all files. The default is -1 (turning this feature off)." msgstr "" "0을 지정하면 모든 파일이 기록됩니다. 기본 값은 -1로, 이 기능이 해제됩니다." -#: utils/misc/guc_tables.c:3409 +#: utils/misc/guc_tables.c:3557 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "pg_stat_activity.query에 예약되는 크기(바이트)를 설정합니다." -#: utils/misc/guc_tables.c:3420 +#: utils/misc/guc_tables.c:3568 msgid "Sets the maximum size of the pending list for GIN index." msgstr "GIN 인덱스를 위한 팬딩(pending) 목록의 최대 크기 지정" -#: utils/misc/guc_tables.c:3431 +#: utils/misc/guc_tables.c:3579 msgid "TCP user timeout." -msgstr "" +msgstr "TCP 사용자 제한시간." -#: utils/misc/guc_tables.c:3442 +#: utils/misc/guc_tables.c:3590 msgid "The size of huge page that should be requested." -msgstr "" +msgstr "요청되는 huge page 크기" -#: utils/misc/guc_tables.c:3453 +#: utils/misc/guc_tables.c:3601 msgid "Aggressively flush system caches for debugging purposes." -msgstr "" +msgstr "디버킹 처리를 위해 적극적으로 시스템 캐시를 비웁니다." -#: utils/misc/guc_tables.c:3476 +#: utils/misc/guc_tables.c:3624 msgid "" "Sets the time interval between checks for disconnection while running " "queries." msgstr "쿼리 실행 중에 연결을 끊을지 검사하는 간격을 지정합니다." -#: utils/misc/guc_tables.c:3487 +#: utils/misc/guc_tables.c:3635 msgid "Time between progress updates for long-running startup operations." msgstr "연결 작업이 오래 진행되는 경우 진행 상태 갱신 주기" -#: utils/misc/guc_tables.c:3489 +#: utils/misc/guc_tables.c:3637 msgid "0 turns this feature off." msgstr "0을 지정하면 이 기능이 해제됩니다." -#: utils/misc/guc_tables.c:3499 +#: utils/misc/guc_tables.c:3647 msgid "Sets the iteration count for SCRAM secret generation." msgstr "SCRAM 비밀번호 생성용 이터레이션 수를 지정합니다." -#: utils/misc/guc_tables.c:3519 +#: utils/misc/guc_tables.c:3667 msgid "" "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "" "순차적으로 접근하는 디스크 페이지에 대한 계획 관리자의 예상 비용을 설정합니" "다." -#: utils/misc/guc_tables.c:3530 +#: utils/misc/guc_tables.c:3678 msgid "" "Sets the planner's estimate of the cost of a nonsequentially fetched disk " "page." @@ -30935,11 +32356,11 @@ msgstr "" "비순차적으로 접근하는 디스크 페이지에 대한 계획 관리자의 예상 비용을 설정합니" "다." -#: utils/misc/guc_tables.c:3541 +#: utils/misc/guc_tables.c:3689 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "각 튜플(행)에 대한 계획 관리자의 예상 처리 비용을 설정합니다." -#: utils/misc/guc_tables.c:3552 +#: utils/misc/guc_tables.c:3700 msgid "" "Sets the planner's estimate of the cost of processing each index entry " "during an index scan." @@ -30947,7 +32368,7 @@ msgstr "" "실행 계획기의 비용 계산에 사용될 인덱스 스캔으로 각 인덱스 항목을 처리하는 예" "상 처리 비용을 설정합니다." -#: utils/misc/guc_tables.c:3563 +#: utils/misc/guc_tables.c:3711 msgid "" "Sets the planner's estimate of the cost of processing each operator or " "function call." @@ -30955,7 +32376,7 @@ msgstr "" "실행 계획기의 비용 계산에 사용될 함수 호출이나 연산자 연산 처리하는 예상 처" "리 비용을 설정합니다." -#: utils/misc/guc_tables.c:3574 +#: utils/misc/guc_tables.c:3722 msgid "" "Sets the planner's estimate of the cost of passing each tuple (row) from " "worker to leader backend." @@ -30963,7 +32384,7 @@ msgstr "" "각 튜플(행)을 작업자에서 리더 백엔드로 보내는 예상 비용을 실행계획기에 설정합" "니다." -#: utils/misc/guc_tables.c:3585 +#: utils/misc/guc_tables.c:3733 msgid "" "Sets the planner's estimate of the cost of starting up worker processes for " "parallel query." @@ -30971,71 +32392,71 @@ msgstr "" "병렬 쿼리를 위해 작업자 프로세스 시작하는데 드는 예상 비용을 실행계획기에 설" "정합니다." -#: utils/misc/guc_tables.c:3597 +#: utils/misc/guc_tables.c:3745 msgid "Perform JIT compilation if query is more expensive." msgstr "쿼리 수행 예상 비용이 이 값보다 크면, JIT 짜깁기를 수행" -#: utils/misc/guc_tables.c:3598 +#: utils/misc/guc_tables.c:3746 msgid "-1 disables JIT compilation." msgstr "-1 = JIT 짜깁기 안함" -#: utils/misc/guc_tables.c:3608 +#: utils/misc/guc_tables.c:3756 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "쿼리 수행 예상 비용이 이 값보다 크면, JIT-컴파일된 함수 최적화 함" -#: utils/misc/guc_tables.c:3609 +#: utils/misc/guc_tables.c:3757 msgid "-1 disables optimization." msgstr "-1 = 최적화 비활성화" -#: utils/misc/guc_tables.c:3619 +#: utils/misc/guc_tables.c:3767 msgid "Perform JIT inlining if query is more expensive." msgstr "쿼리 수행 예상 비용이 이 값보다 크면, JIT 인라인 작업 수행" -#: utils/misc/guc_tables.c:3620 +#: utils/misc/guc_tables.c:3768 msgid "-1 disables inlining." msgstr "-1 = 인라인 기능 끔" -#: utils/misc/guc_tables.c:3630 +#: utils/misc/guc_tables.c:3778 msgid "" "Sets the planner's estimate of the fraction of a cursor's rows that will be " "retrieved." msgstr "검색될 커서 행에 대한 계획 관리자의 예상 분수 값을 설정합니다." -#: utils/misc/guc_tables.c:3642 +#: utils/misc/guc_tables.c:3790 msgid "" "Sets the planner's estimate of the average size of a recursive query's " "working table." msgstr "재귀 호출 쿼리 대상 테이블의 평균 크기를 실행 계획기에 설정 함" -#: utils/misc/guc_tables.c:3654 +#: utils/misc/guc_tables.c:3802 msgid "GEQO: selective pressure within the population." msgstr "GEQO: 모집단 내의 선택 압력입니다." -#: utils/misc/guc_tables.c:3665 +#: utils/misc/guc_tables.c:3813 msgid "GEQO: seed for random path selection." msgstr "GEQO: 무작위 경로 선택을 위한 씨드" -#: utils/misc/guc_tables.c:3676 -msgid "Multiple of work_mem to use for hash tables." -msgstr "테이블 해시 작업에서 쓸 work_mem 값의 배율" +#: utils/misc/guc_tables.c:3824 +msgid "Multiple of \"work_mem\" to use for hash tables." +msgstr "테이블 해시 작업에서 쓸 \"work_mem\" 값의 배율" -#: utils/misc/guc_tables.c:3687 +#: utils/misc/guc_tables.c:3835 msgid "Multiple of the average buffer usage to free per round." msgstr "라운드당 해제할 평균 버퍼 사용의 배수입니다." -#: utils/misc/guc_tables.c:3697 +#: utils/misc/guc_tables.c:3845 msgid "Sets the seed for random-number generation." msgstr "난수 생성 속도를 설정합니다." -#: utils/misc/guc_tables.c:3708 +#: utils/misc/guc_tables.c:3856 msgid "Vacuum cost delay in milliseconds." msgstr "청소 비용 지연(밀리초)입니다." -#: utils/misc/guc_tables.c:3719 +#: utils/misc/guc_tables.c:3867 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "자동 청소에 대한 청소 비용 지연(밀리초)입니다." -#: utils/misc/guc_tables.c:3730 +#: utils/misc/guc_tables.c:3878 msgid "" "Number of tuple updates or deletes prior to vacuum as a fraction of " "reltuples." @@ -31043,11 +32464,11 @@ msgstr "" "vacuum 작업을 진행할 update, delete 작업량을 전체 자료에 대한 분수값으로 지정" "합니다." -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3888 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." -msgstr "" +msgstr "vacuum을 위한 전체 튜플 대비 insert 튜플의 비율" -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3898 msgid "" "Number of tuple inserts, updates, or deletes prior to analyze as a fraction " "of reltuples." @@ -31055,147 +32476,148 @@ msgstr "" "통계 수집 작업을 진행할 insert, update, delete 작업량을 전체 자료에 대한 분수" "값으로 지정합니다." -#: utils/misc/guc_tables.c:3760 +#: utils/misc/guc_tables.c:3908 msgid "" "Time spent flushing dirty buffers during checkpoint, as fraction of " "checkpoint interval." msgstr "체크포인트 반복 주기 안에 작업을 완료할 분수값(1=100%)" -#: utils/misc/guc_tables.c:3770 -msgid "Fraction of statements exceeding log_min_duration_sample to be logged." -msgstr "" +#: utils/misc/guc_tables.c:3918 +msgid "" +"Fraction of statements exceeding \"log_min_duration_sample\" to be logged." +msgstr "\"log_min_duration_sample\" 로그의 비율" -#: utils/misc/guc_tables.c:3771 +#: utils/misc/guc_tables.c:3919 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "0.0 (로그 안남김)에서 1.0(모두 남김) 값을 지정할 수 있음" -#: utils/misc/guc_tables.c:3780 +#: utils/misc/guc_tables.c:3928 msgid "Sets the fraction of transactions from which to log all statements." msgstr "모든 구문을 로그로 남기려고 할 때, 그 남길 비율" -#: utils/misc/guc_tables.c:3781 +#: utils/misc/guc_tables.c:3929 msgid "" "Use a value between 0.0 (never log) and 1.0 (log all statements for all " "transactions)." msgstr "0.0(모두 안 남김) 부터 1.0 (모두 남김)까지 지정할 수 있습니다." -#: utils/misc/guc_tables.c:3800 +#: utils/misc/guc_tables.c:3948 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "WAL 파일을 아카이빙하기 위해 호출될 셸 명령을 설정합니다." -#: utils/misc/guc_tables.c:3801 +#: utils/misc/guc_tables.c:3949 msgid "This is used only if \"archive_library\" is not set." msgstr "이 설정은 \"archive_library\" 설정이 안되어 있을 때만 작동합니다." -#: utils/misc/guc_tables.c:3810 +#: utils/misc/guc_tables.c:3958 msgid "Sets the library that will be called to archive a WAL file." msgstr "WAL 파일을 아카이빙하기 위해 호출될 셸 명령을 설정합니다." -#: utils/misc/guc_tables.c:3811 +#: utils/misc/guc_tables.c:3959 msgid "An empty string indicates that \"archive_command\" should be used." msgstr "\"archive_command\" 설정값은 빈 문자열이어야 합니다." -#: utils/misc/guc_tables.c:3820 +#: utils/misc/guc_tables.c:3968 msgid "" "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "아카이브된 WAL 파일을 재 반영할 쉘 명령어를 설정합니다." -#: utils/misc/guc_tables.c:3830 +#: utils/misc/guc_tables.c:3978 msgid "Sets the shell command that will be executed at every restart point." msgstr "매 복구 작업이 끝난 다음 실행할 쉘 명령어를 설정합니다." -#: utils/misc/guc_tables.c:3840 +#: utils/misc/guc_tables.c:3988 msgid "" "Sets the shell command that will be executed once at the end of recovery." msgstr "복구 작업 끝에 한 번 실행될 쉘 명령어를 설정합니다." -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:3998 msgid "Specifies the timeline to recover into." msgstr "복구할 타임라인을 지정합니다." -#: utils/misc/guc_tables.c:3860 +#: utils/misc/guc_tables.c:4008 msgid "" "Set to \"immediate\" to end recovery as soon as a consistent state is " "reached." msgstr "복구를 끝내는 지점을 가장 최근으로 하려면, \"immediate\"로 지정하세요." -#: utils/misc/guc_tables.c:3869 +#: utils/misc/guc_tables.c:4017 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "복구를 끝낼 마지막 트랜잭션 ID 지정" -#: utils/misc/guc_tables.c:3878 +#: utils/misc/guc_tables.c:4026 msgid "Sets the time stamp up to which recovery will proceed." msgstr "복구를 끝낼 마지막 시간 지정" -#: utils/misc/guc_tables.c:3887 +#: utils/misc/guc_tables.c:4035 msgid "Sets the named restore point up to which recovery will proceed." -msgstr "복구를 끝낼 복원 지점 이름 지정" +msgstr "복구를 끝낼 복구 지점 이름 지정" -#: utils/misc/guc_tables.c:3896 +#: utils/misc/guc_tables.c:4044 msgid "" "Sets the LSN of the write-ahead log location up to which recovery will " "proceed." msgstr "복구용 미리 쓰기 로그의 복구 지점 LSN 지정" -#: utils/misc/guc_tables.c:3906 +#: utils/misc/guc_tables.c:4054 msgid "Sets the connection string to be used to connect to the sending server." msgstr "트랜잭션 로그를 보내는 서버로 접속하기 위한 접속 문자열 지정" -#: utils/misc/guc_tables.c:3917 +#: utils/misc/guc_tables.c:4065 msgid "Sets the name of the replication slot to use on the sending server." msgstr "복제 슬롯 이름을 지정합니다." -#: utils/misc/guc_tables.c:3927 +#: utils/misc/guc_tables.c:4075 msgid "Sets the client's character set encoding." msgstr "클라이언트 문자 세트 인코딩을 지정함" -#: utils/misc/guc_tables.c:3938 +#: utils/misc/guc_tables.c:4086 msgid "Controls information prefixed to each log line." msgstr "각 로그 줄 앞에 추가할 정보를 제어합니다." -#: utils/misc/guc_tables.c:3939 +#: utils/misc/guc_tables.c:4087 msgid "If blank, no prefix is used." msgstr "비워 두면 접두사가 사용되지 않습니다." -#: utils/misc/guc_tables.c:3948 +#: utils/misc/guc_tables.c:4096 msgid "Sets the time zone to use in log messages." msgstr "로그 메시지에 사용할 표준 시간대를 설정합니다." -#: utils/misc/guc_tables.c:3958 +#: utils/misc/guc_tables.c:4106 msgid "Sets the display format for date and time values." msgstr "날짜와 시간 값을 나타내는 모양을 지정합니다." -#: utils/misc/guc_tables.c:3959 +#: utils/misc/guc_tables.c:4107 msgid "Also controls interpretation of ambiguous date inputs." msgstr "또한 모호한 날짜 입력의 해석을 제어합니다." -#: utils/misc/guc_tables.c:3970 +#: utils/misc/guc_tables.c:4118 msgid "Sets the default table access method for new tables." msgstr "새 테이블에서 사용할 기본 테이블 접근 방법을 지정합니다." -#: utils/misc/guc_tables.c:3981 +#: utils/misc/guc_tables.c:4129 msgid "Sets the default tablespace to create tables and indexes in." msgstr "테이블 및 인덱스를 만들 기본 테이블스페이스를 설정합니다." -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4130 msgid "An empty string selects the database's default tablespace." msgstr "빈 문자열을 지정하면 데이터베이스의 기본 테이블스페이스가 선택됩니다." -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4140 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "임시 테이블 및 정렬 파일에 사용할 테이블스페이스를 설정합니다." -#: utils/misc/guc_tables.c:4003 +#: utils/misc/guc_tables.c:4151 msgid "" "Sets whether a CREATEROLE user automatically grants the role to themselves, " "and with which options." msgstr "CREATEROLE 권한이 있는 사용자가 자동으로 스스로에게 부여할 옵션 지정" -#: utils/misc/guc_tables.c:4015 +#: utils/misc/guc_tables.c:4163 msgid "Sets the path for dynamically loadable modules." msgstr "동적으로 불러올 수 있는 모듈들이 있는 경로를 지정함." -#: utils/misc/guc_tables.c:4016 +#: utils/misc/guc_tables.c:4164 msgid "" "If a dynamically loadable module needs to be opened and the specified name " "does not have a directory component (i.e., the name does not contain a " @@ -31205,68 +32627,68 @@ msgstr "" "가 없는 경우(즉, 이름에 슬래시 기호가 없는 경우) 시스템은 이 경로에서 지정한 " "파일을 검색합니다." -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4177 msgid "Sets the location of the Kerberos server key file." msgstr "Kerberos 서버 키 파일의 위치를 지정함." -#: utils/misc/guc_tables.c:4040 +#: utils/misc/guc_tables.c:4188 msgid "Sets the Bonjour service name." msgstr "Bonjour 서비스 이름을 지정" -#: utils/misc/guc_tables.c:4050 +#: utils/misc/guc_tables.c:4198 msgid "Sets the language in which messages are displayed." msgstr "보여질 메시지로 사용할 언어 지정." -#: utils/misc/guc_tables.c:4060 +#: utils/misc/guc_tables.c:4208 msgid "Sets the locale for formatting monetary amounts." msgstr "통화금액 표현 양식으로 사용할 로케일 지정." -#: utils/misc/guc_tables.c:4070 +#: utils/misc/guc_tables.c:4218 msgid "Sets the locale for formatting numbers." msgstr "숫자 표현 양식으로 사용할 로케일 지정." -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4228 msgid "Sets the locale for formatting date and time values." msgstr "날짜와 시간 값을 표현할 양식으로 사용할 로케일 지정." -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4238 msgid "Lists shared libraries to preload into each backend." msgstr "각각의 백엔드에 미리 불러올 공유 라이브러리들을 지정합니다" -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4249 msgid "Lists shared libraries to preload into server." msgstr "서버에 미리 불러올 공유 라이브러리들을 지정합니다" -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4260 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "" "각각의 백엔드에 미리 불러올 접근제한 없는 공유 라이브러리들을 지정합니다" -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4271 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "스키마로 한정되지 않은 이름의 스키마 검색 순서를 설정합니다." -#: utils/misc/guc_tables.c:4135 +#: utils/misc/guc_tables.c:4283 msgid "Shows the server (database) character set encoding." msgstr "서버 (데이터베이스) 문자 세트 인코딩 보여줌" -#: utils/misc/guc_tables.c:4147 +#: utils/misc/guc_tables.c:4295 msgid "Shows the server version." msgstr "서버 버전 보임." -#: utils/misc/guc_tables.c:4159 +#: utils/misc/guc_tables.c:4307 msgid "Sets the current role." msgstr "현재 롤을 지정" -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4319 msgid "Sets the session user name." msgstr "세션 사용자 이름 지정." -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4330 msgid "Sets the destination for server log output." msgstr "서버 로그 출력을 위한 대상을 지정합니다." -#: utils/misc/guc_tables.c:4183 +#: utils/misc/guc_tables.c:4331 msgid "" "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", " "\"jsonlog\", and \"eventlog\", depending on the platform." @@ -31274,138 +32696,138 @@ msgstr "" "유효한 값은 플랫폼에 따라 \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\" 및 " "\"eventlog\"의 조합입니다." -#: utils/misc/guc_tables.c:4194 +#: utils/misc/guc_tables.c:4342 msgid "Sets the destination directory for log files." msgstr "로그 파일의 대상 디렉터리를 설정합니다." -#: utils/misc/guc_tables.c:4195 +#: utils/misc/guc_tables.c:4343 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "데이터 디렉터리의 상대 경로 또는 절대 경로로 지정할 수 있습니다." -#: utils/misc/guc_tables.c:4205 +#: utils/misc/guc_tables.c:4353 msgid "Sets the file name pattern for log files." msgstr "로그 파일의 파일 이름 패턴을 설정합니다." -#: utils/misc/guc_tables.c:4216 +#: utils/misc/guc_tables.c:4364 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "syslog에서 구분할 PostgreSQL 메시지에 사용될 프로그램 이름을 지정." -#: utils/misc/guc_tables.c:4227 +#: utils/misc/guc_tables.c:4375 msgid "" "Sets the application name used to identify PostgreSQL messages in the event " "log." msgstr "" "이벤트 로그에서 PostgreSQL 메시지 식별자로 사용할 응용프로그램 이름 지정" -#: utils/misc/guc_tables.c:4238 +#: utils/misc/guc_tables.c:4386 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "시간대(time zone)를 지정함." -#: utils/misc/guc_tables.c:4248 +#: utils/misc/guc_tables.c:4396 msgid "Selects a file of time zone abbreviations." msgstr "표준 시간대 약어 파일을 선택합니다." -#: utils/misc/guc_tables.c:4258 +#: utils/misc/guc_tables.c:4406 msgid "Sets the owning group of the Unix-domain socket." msgstr "유닉스 도메인 소켓의 소유주를 지정" -#: utils/misc/guc_tables.c:4259 +#: utils/misc/guc_tables.c:4407 msgid "" "The owning user of the socket is always the user that starts the server." msgstr "소켓 소유자는 항상 서버를 시작하는 사용자입니다." -#: utils/misc/guc_tables.c:4269 +#: utils/misc/guc_tables.c:4417 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "유닉스 도메인 소켓을 만들 디렉터리를 지정합니다." -#: utils/misc/guc_tables.c:4280 +#: utils/misc/guc_tables.c:4428 msgid "Sets the host name or IP address(es) to listen to." msgstr "서비스할 호스트이름이나, IP를 지정함." -#: utils/misc/guc_tables.c:4295 +#: utils/misc/guc_tables.c:4443 msgid "Sets the server's data directory." msgstr "서버의 데이터 디렉터리 위치를 지정합니다." -#: utils/misc/guc_tables.c:4306 +#: utils/misc/guc_tables.c:4454 msgid "Sets the server's main configuration file." msgstr "서버의 기본 환경설정 파일 경로를 지정합니다." -#: utils/misc/guc_tables.c:4317 +#: utils/misc/guc_tables.c:4465 msgid "Sets the server's \"hba\" configuration file." msgstr "서버의 \"hba\" 구성 파일을 설정합니다." -#: utils/misc/guc_tables.c:4328 +#: utils/misc/guc_tables.c:4476 msgid "Sets the server's \"ident\" configuration file." msgstr "서버의 \"ident\" 구성 파일을 설정합니다." -#: utils/misc/guc_tables.c:4339 +#: utils/misc/guc_tables.c:4487 msgid "Writes the postmaster PID to the specified file." msgstr "postmaster PID가 기록된 파일의 경로를 지정합니다." -#: utils/misc/guc_tables.c:4350 +#: utils/misc/guc_tables.c:4498 msgid "Shows the name of the SSL library." msgstr "SSL 라이브러리 이름을 보여줌" -#: utils/misc/guc_tables.c:4365 +#: utils/misc/guc_tables.c:4513 msgid "Location of the SSL server certificate file." msgstr "서버 인증서 파일 위치를 지정함" -#: utils/misc/guc_tables.c:4375 +#: utils/misc/guc_tables.c:4523 msgid "Location of the SSL server private key file." msgstr "SSL 서버 개인 키 파일의 위치를 지정함." -#: utils/misc/guc_tables.c:4385 +#: utils/misc/guc_tables.c:4533 msgid "Location of the SSL certificate authority file." msgstr "SSL 인증 authority 파일 위치" -#: utils/misc/guc_tables.c:4395 +#: utils/misc/guc_tables.c:4543 msgid "Location of the SSL certificate revocation list file." msgstr "SSL 인증서 파기 목록 파일의 위치" -#: utils/misc/guc_tables.c:4405 +#: utils/misc/guc_tables.c:4553 msgid "Location of the SSL certificate revocation list directory." msgstr "SSL 인증서 파기 목록 디렉터리 위치" -#: utils/misc/guc_tables.c:4415 +#: utils/misc/guc_tables.c:4563 msgid "" "Number of synchronous standbys and list of names of potential synchronous " "ones." -msgstr "" +msgstr "동기식 복제용 대기 서버 수와 운영 서버 전환 대상이 되는 서버 이름 목록" -#: utils/misc/guc_tables.c:4426 +#: utils/misc/guc_tables.c:4574 msgid "Sets default text search configuration." msgstr "기본 텍스트 검색 구성을 설정합니다." -#: utils/misc/guc_tables.c:4436 +#: utils/misc/guc_tables.c:4584 msgid "Sets the list of allowed SSL ciphers." msgstr "허용되는 SSL 암호 목록을 설정합니다." -#: utils/misc/guc_tables.c:4451 +#: utils/misc/guc_tables.c:4599 msgid "Sets the curve to use for ECDH." msgstr "ECDH에 사용할 curve 설정" -#: utils/misc/guc_tables.c:4466 +#: utils/misc/guc_tables.c:4614 msgid "Location of the SSL DH parameters file." msgstr "SSL DH 매개 변수 파일의 위치." -#: utils/misc/guc_tables.c:4477 +#: utils/misc/guc_tables.c:4625 msgid "Command to obtain passphrases for SSL." msgstr "SSL 비밀번호 입력을 위한 명령" -#: utils/misc/guc_tables.c:4488 +#: utils/misc/guc_tables.c:4636 msgid "Sets the application name to be reported in statistics and logs." msgstr "통계정보와 로그에 포함될 응용프로그램 이름 지정" -#: utils/misc/guc_tables.c:4499 +#: utils/misc/guc_tables.c:4647 msgid "Sets the name of the cluster, which is included in the process title." msgstr "프로세스 타이틀에 포함될 클러스터 이름 지정" -#: utils/misc/guc_tables.c:4510 +#: utils/misc/guc_tables.c:4658 msgid "" "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "WAL 동시성 검사 완료용 WAL 자원 관리자 지정" -#: utils/misc/guc_tables.c:4511 +#: utils/misc/guc_tables.c:4659 msgid "" "Full-page images will be logged for all data blocks and cross-checked " "against the results of WAL replay." @@ -31413,32 +32835,51 @@ msgstr "" "풀페이지 이미지가 모든 데이터 블록을 위해 기록될 것이며 WAL 재반영 결과를 이" "중 검증을 합니다." -#: utils/misc/guc_tables.c:4521 +#: utils/misc/guc_tables.c:4669 msgid "JIT provider to use." msgstr "사용할 JIT 제공자" -#: utils/misc/guc_tables.c:4532 +#: utils/misc/guc_tables.c:4680 msgid "Log backtrace for errors in these functions." msgstr "이 함수들 안에 오류 추적용 로그를 남김" -#: utils/misc/guc_tables.c:4543 +#: utils/misc/guc_tables.c:4691 msgid "Use direct I/O for file access." msgstr "파일 접근을 위해 직접 I/O를 사용합니다." -#: utils/misc/guc_tables.c:4563 +#: utils/misc/guc_tables.c:4702 +msgid "" +"Lists streaming replication standby server replication slot names that " +"logical WAL sender processes will wait for." +msgstr "" +"논리 WAL 송신 프로세스가 기다릴 스트리밍 복제 대기 서버 복제 슬롯 이름 목록" + +#: utils/misc/guc_tables.c:4704 +msgid "" +"Logical WAL sender processes will send decoded changes to output plugins " +"only after the specified replication slots have confirmed receiving WAL." +msgstr "" +"논리 WAL 송신 프로세스는 지정된 복제 슬롯이 WAL 수신을 확인한 후에만 " +"디코딩된 변경 사항을 출력 플러그인으로 전송합니다." + +#: utils/misc/guc_tables.c:4716 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "지정된 종류의 non-system 릴레이션에 대한 접근을 금지합니다." + +#: utils/misc/guc_tables.c:4736 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "문자열에서 \"\\'\" 문자 사용을 허용할 것인지를 정하세요" -#: utils/misc/guc_tables.c:4573 +#: utils/misc/guc_tables.c:4746 msgid "Sets the output format for bytea." msgstr "bytea 값의 표시 형식을 설정합니다." -#: utils/misc/guc_tables.c:4583 +#: utils/misc/guc_tables.c:4756 msgid "Sets the message levels that are sent to the client." msgstr "클라이언트 측에 보여질 메시지 수준을 지정함." -#: utils/misc/guc_tables.c:4584 utils/misc/guc_tables.c:4680 -#: utils/misc/guc_tables.c:4691 utils/misc/guc_tables.c:4763 +#: utils/misc/guc_tables.c:4757 utils/misc/guc_tables.c:4853 +#: utils/misc/guc_tables.c:4864 msgid "" "Each level includes all the levels that follow it. The later the level, the " "fewer messages are sent." @@ -31446,118 +32887,114 @@ msgstr "" "각 수준은 이 수준 뒤에 있는 모든 수준이 포함됩니다. 수준이 뒤에 있을수록 전송" "되는 메시지 수가 적습니다." -#: utils/misc/guc_tables.c:4594 +#: utils/misc/guc_tables.c:4767 msgid "Enables in-core computation of query identifiers." msgstr "query_id를 내부적으로 사용함" -#: utils/misc/guc_tables.c:4604 +#: utils/misc/guc_tables.c:4777 msgid "Enables the planner to use constraints to optimize queries." msgstr "실행계획기가 쿼리 최적화 작업에서 제약 조건을 사용하도록 함" -#: utils/misc/guc_tables.c:4605 +#: utils/misc/guc_tables.c:4778 msgid "" "Table scans will be skipped if their constraints guarantee that no rows " "match the query." msgstr "" "제약 조건에 의해 쿼리와 일치하는 행이 없는 경우 테이블 스캔을 건너뜁니다." -#: utils/misc/guc_tables.c:4616 +#: utils/misc/guc_tables.c:4789 msgid "Sets the default compression method for compressible values." msgstr "압축 가능한 값을 압축하기 위한 기본 압축 방법을 지정합니다." -#: utils/misc/guc_tables.c:4627 +#: utils/misc/guc_tables.c:4800 msgid "Sets the transaction isolation level of each new transaction." msgstr "각 새 트랜잭션의 트랜잭션 격리 수준을 설정합니다." -#: utils/misc/guc_tables.c:4637 +#: utils/misc/guc_tables.c:4810 msgid "Sets the current transaction's isolation level." msgstr "현재 트랜잭션 독립성 수준(isolation level)을 지정함." -#: utils/misc/guc_tables.c:4648 +#: utils/misc/guc_tables.c:4821 msgid "Sets the display format for interval values." msgstr "간격 값의 표시 형식을 설정합니다." -#: utils/misc/guc_tables.c:4659 +#: utils/misc/guc_tables.c:4832 msgid "Log level for reporting invalid ICU locale strings." -msgstr "" +msgstr "잘못된 ICU 로케일 설정을 보고할 로그 수준" -#: utils/misc/guc_tables.c:4669 +#: utils/misc/guc_tables.c:4842 msgid "Sets the verbosity of logged messages." msgstr "기록되는 메시지의 상세 정도를 지정합니다." -#: utils/misc/guc_tables.c:4679 +#: utils/misc/guc_tables.c:4852 msgid "Sets the message levels that are logged." msgstr "서버 로그에 기록될 메시지 수준을 지정함." -#: utils/misc/guc_tables.c:4690 +#: utils/misc/guc_tables.c:4863 msgid "" "Causes all statements generating error at or above this level to be logged." msgstr "" "오류가 있는 모든 쿼리문이나 지정한 로그 레벨 이상의 쿼리문을 로그로 남김" -#: utils/misc/guc_tables.c:4701 +#: utils/misc/guc_tables.c:4874 msgid "Sets the type of statements logged." msgstr "서버로그에 기록될 구문 종류를 지정합니다." -#: utils/misc/guc_tables.c:4711 +#: utils/misc/guc_tables.c:4884 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "syslog 기능을 사용할 때, 사용할 syslog \"facility\" 값을 지정." -#: utils/misc/guc_tables.c:4722 +#: utils/misc/guc_tables.c:4895 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "트리거 및 다시 쓰기 규칙에 대한 세션의 동작을 설정합니다." -#: utils/misc/guc_tables.c:4732 +#: utils/misc/guc_tables.c:4905 msgid "Sets the current transaction's synchronization level." msgstr "현재 트랜잭션 격리 수준(isolation level)을 지정함." -#: utils/misc/guc_tables.c:4742 -msgid "Allows archiving of WAL files using archive_command." -msgstr "archive_command를 사용하여 WAL 파일을 따로 보관하도록 설정합니다." +#: utils/misc/guc_tables.c:4915 +msgid "Allows archiving of WAL files using \"archive_command\"." +msgstr "\"archive_command\"를 사용하여 WAL 파일을 따로 보관하도록 설정합니다." -#: utils/misc/guc_tables.c:4752 +#: utils/misc/guc_tables.c:4925 msgid "Sets the action to perform upon reaching the recovery target." -msgstr "" +msgstr "복구 타켓에 도달했을 때 수행할 액션을 지정합니다." -#: utils/misc/guc_tables.c:4762 -msgid "Enables logging of recovery-related debugging information." -msgstr "복구 작업과 관련된 디버깅 정보를 기록하도록 합니다." - -#: utils/misc/guc_tables.c:4779 +#: utils/misc/guc_tables.c:4935 msgid "Collects function-level statistics on database activity." msgstr "데이터베이스 활동에 대한 함수 수준 통계를 수집합니다." -#: utils/misc/guc_tables.c:4790 +#: utils/misc/guc_tables.c:4946 msgid "Sets the consistency of accesses to statistics data." msgstr "통계 자료 접근의 동시성을 지정합니다." -#: utils/misc/guc_tables.c:4800 +#: utils/misc/guc_tables.c:4956 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "WAL 파일에 페이지 전체를 기록할 때 사용할 압축 방법" -#: utils/misc/guc_tables.c:4810 +#: utils/misc/guc_tables.c:4966 msgid "Sets the level of information written to the WAL." msgstr "WAL에 저장할 내용 수준을 지정합니다." -#: utils/misc/guc_tables.c:4820 +#: utils/misc/guc_tables.c:4976 msgid "Selects the dynamic shared memory implementation used." msgstr "사용할 동적 공유 메모리 관리방식을 선택합니다." -#: utils/misc/guc_tables.c:4830 +#: utils/misc/guc_tables.c:4986 msgid "" "Selects the shared memory implementation used for the main shared memory " "region." msgstr "사용할 동적 공유 메모리 관리방식을 선택합니다." -#: utils/misc/guc_tables.c:4840 +#: utils/misc/guc_tables.c:4996 msgid "Selects the method used for forcing WAL updates to disk." msgstr "디스크에 대한 강제 WAL 업데이트에 사용되는 방법을 선택합니다." -#: utils/misc/guc_tables.c:4850 +#: utils/misc/guc_tables.c:5006 msgid "Sets how binary values are to be encoded in XML." msgstr "XML에서 바이너리 값이 인코딩되는 방식을 설정합니다." -#: utils/misc/guc_tables.c:4860 +#: utils/misc/guc_tables.c:5016 msgid "" "Sets whether XML data in implicit parsing and serialization operations is to " "be considered as documents or content fragments." @@ -31565,77 +33002,92 @@ msgstr "" "암시적 구문 분석 및 직렬화 작업의 XML 데이터를 문서 또는 내용 조각으로 간주할" "지 여부를 설정합니다." -#: utils/misc/guc_tables.c:4871 +#: utils/misc/guc_tables.c:5027 msgid "Use of huge pages on Linux or Windows." msgstr "리눅스 또는 Windows huge 페이지 사용 여부" -#: utils/misc/guc_tables.c:4881 +#: utils/misc/guc_tables.c:5037 +msgid "Indicates the status of huge pages." +msgstr "huge page 상태를 보고할지 지정" + +#: utils/misc/guc_tables.c:5048 msgid "Prefetch referenced blocks during recovery." msgstr "복구 작업 중에 참조하는 블록을 미리 준비하는 방법." -#: utils/misc/guc_tables.c:4882 +#: utils/misc/guc_tables.c:5049 msgid "Look ahead in the WAL to find references to uncached data." msgstr "따라잡지 못한 데이터를 WAL에서 미리 준비함" -#: utils/misc/guc_tables.c:4891 +#: utils/misc/guc_tables.c:5058 msgid "Forces the planner's use parallel query nodes." msgstr "병렬 쿼리를 강제로 사용하도록 지정합니다." -#: utils/misc/guc_tables.c:4892 +#: utils/misc/guc_tables.c:5059 msgid "" "This can be useful for testing the parallel query infrastructure by forcing " "the planner to generate plans that contain nodes that perform tuple " "communication between workers and the main process." msgstr "" +"이것은 실행계획기가 작업자와 메인 프로세스 간에 튜플 통신을 수행하는 " +"노드가 포함된 플랜을 생성하도록 강제하여 병렬 쿼리 환경을 테스트하는 " +"데 유용할 수 있습니다." -#: utils/misc/guc_tables.c:4904 +#: utils/misc/guc_tables.c:5071 msgid "Chooses the algorithm for encrypting passwords." -msgstr "" +msgstr "비밀번호 암호화 알고리즘 선택" -#: utils/misc/guc_tables.c:4914 +#: utils/misc/guc_tables.c:5081 msgid "Controls the planner's selection of custom or generic plan." -msgstr "" +msgstr "실행계획기가 사용자 정의 계획이나, 일반적 계획을 선택하는 것을 조정함" -#: utils/misc/guc_tables.c:4915 +#: utils/misc/guc_tables.c:5082 msgid "" "Prepared statements can have custom and generic plans, and the planner will " "attempt to choose which is better. This can be set to override the default " "behavior." msgstr "" +"미리 준비된 구문에는 사용자 정의 및 일반 계획이 있을 수 있으며, " +"실행계획기는 어느 것이 더 나은지 선택하려고 시도합니다. " +"이 설정은 기본 동작을 재정의하도록 설정할 수 있습니다." -#: utils/misc/guc_tables.c:4927 +#: utils/misc/guc_tables.c:5094 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "사용할 최소 SSL/TLS 프로토콜 버전을 지정합니다." -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5106 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "사용할 최대 SSL/TLS 프로토콜 버전을 지정합니다." -#: utils/misc/guc_tables.c:4951 +#: utils/misc/guc_tables.c:5118 msgid "" "Sets the method for synchronizing the data directory before crash recovery." msgstr "" +"충돌 복구 전에 데이터 디렉토리를 동기화하는 방법을 설정합니다." -#: utils/misc/guc_tables.c:4960 +#: utils/misc/guc_tables.c:5127 msgid "" "Forces immediate streaming or serialization of changes in large transactions." msgstr "" +"대량 트랜잭션에서 변경 사항을 강제로 즉시 스트리밍하거나 직렬화합니다." -#: utils/misc/guc_tables.c:4961 +#: utils/misc/guc_tables.c:5128 msgid "" "On the publisher, it allows streaming or serializing each change in logical " "decoding. On the subscriber, it allows serialization of all changes to files " "and notifies the parallel apply workers to read and apply them at the end of " "the transaction." msgstr "" +"발행 서버에서 논리 디코딩의 각 변경 사항을 스트리밍하거나 직렬화할 수 있습니다. " +"구독 서버에서 파일에 대한 모든 변경 사항을 직렬화할 수 있으며, " +"병렬 반영 작업자에게 트랜잭션이 끝날 때 읽고 적용하도록 알립니다." #: utils/misc/help_config.c:129 #, c-format msgid "internal error: unrecognized run-time parameter type\n" msgstr "내부 오류: 알 수 없는 실시간 서버 설정 변수\n" -#: utils/misc/pg_controldata.c:48 utils/misc/pg_controldata.c:86 -#: utils/misc/pg_controldata.c:175 utils/misc/pg_controldata.c:214 +#: utils/misc/pg_controldata.c:50 utils/misc/pg_controldata.c:90 +#: utils/misc/pg_controldata.c:181 utils/misc/pg_controldata.c:222 #, c-format msgid "calculated CRC checksum does not match value stored in file" msgstr "계산된 CRC 체크섬 값이 파일에 저장된 값과 다름" @@ -31643,7 +33095,7 @@ msgstr "계산된 CRC 체크섬 값이 파일에 저장된 값과 다름" #: utils/misc/pg_rusage.c:64 #, c-format msgid "CPU: user: %d.%02d s, system: %d.%02d s, elapsed: %d.%02d s" -msgstr "" +msgstr "CPU: user: %d.%02d s, system: %d.%02d s, elapsed: %d.%02d s" #: utils/misc/rls.c:127 #, c-format @@ -31659,12 +33111,12 @@ msgstr "" "테이블 소유주를 위해 정책을 비활성하려면, ALTER TABLE NO FORCE ROW LEVEL " "SECURITY 명령을 사용하세요" -#: utils/misc/timeout.c:524 +#: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" msgstr "시간 초과로 더이상 추가할 수 없음" -#: utils/misc/tzparser.c:60 +#: utils/misc/tzparser.c:61 #, c-format msgid "" "time zone abbreviation \"%s\" is too long (maximum %d characters) in time " @@ -31673,144 +33125,143 @@ msgstr "" "\"%s\" 타임 존 이름이 너무 깁니다(최대 %d자) (\"%s\" 타임 존 파일의 %d번째 줄" "에 있음)." -#: utils/misc/tzparser.c:72 +#: utils/misc/tzparser.c:73 #, c-format msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "" "%d 타임 존 오프셋 값이 범위를 벗어났습니다(\"%s\" 타임 존 파일의 %d번째 줄에 " "있음)." -#: utils/misc/tzparser.c:111 +#: utils/misc/tzparser.c:112 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "\"%s\" time zone 파일의 %d번째 줄에 time zone 생략형이 빠졌음" -#: utils/misc/tzparser.c:120 +#: utils/misc/tzparser.c:121 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "\"%s\" time zone 파일의 %d번째 줄에 time zone 옵셋이 빠졌음" -#: utils/misc/tzparser.c:132 +#: utils/misc/tzparser.c:133 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "" "\"%s\" 표준 시간대 파일의 %d번째 줄에서 표준 시간대 오프셋 숫자가 잘못됨" -#: utils/misc/tzparser.c:168 +#: utils/misc/tzparser.c:169 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "\"%s\" time zone 파일의 %d번째 줄에 구문 오류" -#: utils/misc/tzparser.c:236 +#: utils/misc/tzparser.c:237 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "표준 시간대 약어 \"%s\"은(는) 배수로 정의됨" -#: utils/misc/tzparser.c:238 +#: utils/misc/tzparser.c:239 #, c-format msgid "" -"Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s" -"\", line %d." +"Entry in time zone file \"%s\", line %d, conflicts with entry in file " +"\"%s\", line %d." msgstr "" "\"%s\" 타임 존 파일의 %d번째 줄에 있는 항목이 \"%s\" 파일의 %d번째 줄에 있는 " "항목과 충돌합니다." -#: utils/misc/tzparser.c:300 +#: utils/misc/tzparser.c:301 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "잘못된 time zone 파일 이름: \"%s\"" -#: utils/misc/tzparser.c:313 +#: utils/misc/tzparser.c:314 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "\"%s\" 파일에서 time zone 파일 재귀호출 최대치를 초과했음" -#: utils/misc/tzparser.c:352 utils/misc/tzparser.c:365 +#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "\"%s\" time zone 파일을 읽을 수 없음: %m" -#: utils/misc/tzparser.c:376 +#: utils/misc/tzparser.c:377 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "\"%s\" 표준 시간대 파일의 %d번째 줄이 너무 깁니다." -#: utils/misc/tzparser.c:400 +#: utils/misc/tzparser.c:401 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "\"%s\" 표준 시간대 파일의 %d번째 줄에 파일 이름이 없는 @INCLUDE가 있음" -#: utils/mmgr/aset.c:446 utils/mmgr/generation.c:206 utils/mmgr/slab.c:367 +#: utils/mmgr/aset.c:452 utils/mmgr/bump.c:184 utils/mmgr/generation.c:216 +#: utils/mmgr/slab.c:371 #, c-format msgid "Failed while creating memory context \"%s\"." msgstr "\"%s\" 메모리 컨텍스트를 만드는 동안 오류가 발생했습니다." -#: utils/mmgr/dsa.c:532 utils/mmgr/dsa.c:1346 +#: utils/mmgr/dsa.c:523 utils/mmgr/dsa.c:1364 #, c-format msgid "could not attach to dynamic shared area" msgstr "동적 공유 메모리 영역을 할당할 수 없음" -#: utils/mmgr/mcxt.c:1047 utils/mmgr/mcxt.c:1083 utils/mmgr/mcxt.c:1121 -#: utils/mmgr/mcxt.c:1159 utils/mmgr/mcxt.c:1247 utils/mmgr/mcxt.c:1278 -#: utils/mmgr/mcxt.c:1314 utils/mmgr/mcxt.c:1503 utils/mmgr/mcxt.c:1548 -#: utils/mmgr/mcxt.c:1605 +#: utils/mmgr/mcxt.c:1155 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "크기가 %zu인 요청에서 오류가 발생했습니다. 해당 메모리 컨텍스트 \"%s\"" -#: utils/mmgr/mcxt.c:1210 +#: utils/mmgr/mcxt.c:1299 #, c-format msgid "logging memory contexts of PID %d" -msgstr "" +msgstr "%d번 PID의 메모리 현황을 로깅함" -#: utils/mmgr/portalmem.c:188 +#: utils/mmgr/portalmem.c:187 #, c-format msgid "cursor \"%s\" already exists" msgstr "\"%s\" 이름의 커서가 이미 있음" -#: utils/mmgr/portalmem.c:192 +#: utils/mmgr/portalmem.c:191 #, c-format msgid "closing existing cursor \"%s\"" msgstr "이미 있는 \"%s\" 커서를 닫습니다" -#: utils/mmgr/portalmem.c:402 +#: utils/mmgr/portalmem.c:401 #, c-format msgid "portal \"%s\" cannot be run" msgstr "\"%s\" portal 실행할 수 없음" -#: utils/mmgr/portalmem.c:480 +#: utils/mmgr/portalmem.c:479 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "\"%s\" 선점된 포털을 삭제할 수 없음" -#: utils/mmgr/portalmem.c:488 +#: utils/mmgr/portalmem.c:487 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "\"%s\" 활성 포털을 삭제할 수 없음" -#: utils/mmgr/portalmem.c:739 +#: utils/mmgr/portalmem.c:738 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "WITH HOLD 옵션으로 커서를 만든 트랜잭션을 PREPARE할 수 없음" -#: utils/mmgr/portalmem.c:1230 +#: utils/mmgr/portalmem.c:1232 #, c-format msgid "" "cannot perform transaction commands inside a cursor loop that is not read-" "only" msgstr "" +"읽기 전용이 아닌 커서 루프 내에서 트랜잭션 명령을 수행할 수 없습니다" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %ld of temporary file" -msgstr "임시 파일의 %ld 블럭을 찾을 수 없음" +msgid "could not seek to block %lld of temporary file" +msgstr "임시 파일의 %lld 블럭을 찾을 수 없음" -#: utils/sort/sharedtuplestore.c:467 +#: utils/sort/sharedtuplestore.c:466 #, c-format msgid "unexpected chunk in shared tuplestore temporary file" msgstr "공유된 tuplestore 임시 파일에서 예상치 못한 청크" -#: utils/sort/sharedtuplestore.c:549 +#: utils/sort/sharedtuplestore.c:548 #, c-format msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "공유 tuplestore 임시 파일에서 %u 블록을 찾을 수 없음" @@ -31820,17 +33271,17 @@ msgstr "공유 tuplestore 임시 파일에서 %u 블록을 찾을 수 없음" msgid "cannot have more than %d runs for an external sort" msgstr "외부 정렬을 위해 %d 개 이상의 런을 만들 수 없음" -#: utils/sort/tuplesortvariants.c:1363 +#: utils/sort/tuplesortvariants.c:1552 #, c-format msgid "could not create unique index \"%s\"" msgstr "\"%s\" 고유 인덱스를 만들 수 없음" -#: utils/sort/tuplesortvariants.c:1365 +#: utils/sort/tuplesortvariants.c:1554 #, c-format msgid "Key %s is duplicated." msgstr "%s 키가 중복됨" -#: utils/sort/tuplesortvariants.c:1366 +#: utils/sort/tuplesortvariants.c:1555 #, c-format msgid "Duplicate keys exist." msgstr "중복된 키가 있음" @@ -31844,32 +33295,32 @@ msgstr "중복된 키가 있음" msgid "could not seek in tuplestore temporary file" msgstr "tuplestore 임시 파일에서 seek 작업을 할 수 없음" -#: utils/time/snapmgr.c:571 +#: utils/time/snapmgr.c:536 #, c-format msgid "The source transaction is not running anymore." msgstr "소스 트랜잭션이 더 이상 실행중이지 않음" -#: utils/time/snapmgr.c:1166 +#: utils/time/snapmgr.c:1136 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "서브트랜잭션에서 스냅샷을 내보낼 수 없음" -#: utils/time/snapmgr.c:1325 utils/time/snapmgr.c:1330 -#: utils/time/snapmgr.c:1335 utils/time/snapmgr.c:1350 -#: utils/time/snapmgr.c:1355 utils/time/snapmgr.c:1360 -#: utils/time/snapmgr.c:1375 utils/time/snapmgr.c:1380 -#: utils/time/snapmgr.c:1385 utils/time/snapmgr.c:1487 -#: utils/time/snapmgr.c:1503 utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 +#: utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 +#: utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 +#: utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 +#: utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 +#: utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "\"%s\" 파일에 유효하지 않은 스냅샷 자료가 있습니다" -#: utils/time/snapmgr.c:1422 +#: utils/time/snapmgr.c:1393 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "쿼리보다 먼저 SET TRANSACTION SNAPSHOP 명령을 호출해야 함" -#: utils/time/snapmgr.c:1431 +#: utils/time/snapmgr.c:1402 #, c-format msgid "" "a snapshot-importing transaction must have isolation level SERIALIZABLE or " @@ -31878,12 +33329,17 @@ msgstr "" "스냅샷 가져오기 트랜잭션은 그 격리 수준이 SERIALIZABLE 또는 REPEATABLE READ " "여야 함" -#: utils/time/snapmgr.c:1440 utils/time/snapmgr.c:1449 +#: utils/time/snapmgr.c:1411 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "잘못된 스냅샷 식별자: \"%s\"" -#: utils/time/snapmgr.c:1541 +#: utils/time/snapmgr.c:1426 +#, c-format +msgid "snapshot \"%s\" does not exist" +msgstr "\"%s\" 이름의 스냅샷이 없음" + +#: utils/time/snapmgr.c:1524 #, c-format msgid "" "a serializable transaction cannot import a snapshot from a non-serializable " @@ -31892,7 +33348,7 @@ msgstr "" "직렬화 가능한 트랜잭션은 직렬화 가능하지 않은 트랜잭션에서 스냅샷을 가져올 " "수 없음" -#: utils/time/snapmgr.c:1545 +#: utils/time/snapmgr.c:1528 #, c-format msgid "" "a non-read-only serializable transaction cannot import a snapshot from a " @@ -31900,365 +33356,383 @@ msgid "" msgstr "" "읽기-쓰기 직렬화된 트랜잭션이 읽기 전용 트랜잭션의 스냅샷을 가져올 수 없음" -#: utils/time/snapmgr.c:1560 +#: utils/time/snapmgr.c:1543 #, c-format msgid "cannot import a snapshot from a different database" msgstr "서로 다른 데이터베이스를 대상으로는 스냅샷을 가져올 수 없음" -#: gram.y:1197 +#: gram.y:1231 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "UNENCRYPTED PASSWORD 옵션은 더이상 지원하지 않음" -#: gram.y:1198 +#: gram.y:1232 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." -msgstr "" +msgstr "비밀번호를 암호화된 형태로 저장하려면 UNENCRYPTED를 빼세요." -#: gram.y:1525 gram.y:1541 +#: gram.y:1559 gram.y:1575 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "" "CREATE SCHEMA IF NOT EXISTS 구문에서는 스키마 요소들을 포함할 수 없습니다." -#: gram.y:1693 +#: gram.y:1727 #, c-format msgid "current database cannot be changed" msgstr "현재 데이터베이스를 바꿀 수 없음" -#: gram.y:1826 +#: gram.y:1860 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "" "지역시간대 간격(time zone interval) 값은 시(HOUR) 또는 시분(HOUR TO MINUTE) " "값이어야 합니다" -#: gram.y:2443 +#: gram.y:2487 #, c-format msgid "column number must be in range from 1 to %d" msgstr "칼럼 번호는 1 - %d 사이의 범위에 있어야 합니다." -#: gram.y:3039 +#: gram.y:3083 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "\"%s\" 시퀀스 옵션은 지원되지 않음" -#: gram.y:3068 +#: gram.y:3122 #, c-format msgid "modulus for hash partition provided more than once" msgstr "해시 파티션용 모듈을 한 번 이상 지정했습니다" -#: gram.y:3077 +#: gram.y:3131 #, c-format msgid "remainder for hash partition provided more than once" msgstr "해시 파티션용 나머지 처리기를 한 번 이상 지정했습니다" -#: gram.y:3084 +#: gram.y:3138 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "잘못된 해시 파티션 범위 명세 \"%s\"" -#: gram.y:3092 +#: gram.y:3146 #, c-format msgid "modulus for hash partition must be specified" msgstr "해시 파티션용 모듈을 지정하세요" -#: gram.y:3096 +#: gram.y:3150 #, c-format msgid "remainder for hash partition must be specified" msgstr "해시 파티션용 나머지 처리기를 지정하세요" -#: gram.y:3304 gram.y:3338 +#: gram.y:3358 gram.y:3392 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "PROGRAM 옵션과 STDIN/STDOUT 옵션은 함께 쓸 수 없습니다" -#: gram.y:3310 +#: gram.y:3364 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "WHERE 절은 COPY TO 구문을 허용하지 않음" -#: gram.y:3649 gram.y:3656 gram.y:12821 gram.y:12829 +#: gram.y:3712 gram.y:3719 gram.y:13023 gram.y:13031 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "GLOBAL 예약어는 임시 테이블 만들기에서 더 이상 사용하지 않습니다" -#: gram.y:3932 +#: gram.y:3995 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" -msgstr "" +msgstr "계산된 칼럼을 사용하려면, GENERATED ALWAYS 옵션이 있어야 함" -#: gram.y:4315 +#: gram.y:4432 #, c-format msgid "a column list with %s is only supported for ON DELETE actions" msgstr "%s의 칼럼 목록은 ON DELETE 액션용으로만 지원합니다." -#: gram.y:5027 +#: gram.y:5151 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM 구문은 지원하지 않습니다." -#: gram.y:5725 +#: gram.y:5849 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "인식할 수 없는 로우 단위 보안 옵션 \"%s\"" -#: gram.y:5726 +#: gram.y:5850 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." -msgstr "" +msgstr "PERMISSIVE 또는 RESTRICTIVE 정책만 현재 지원합니다." -#: gram.y:5811 +#: gram.y:5935 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGER 구문은 지원하지 않습니다." -#: gram.y:5848 +#: gram.y:5972 msgid "duplicate trigger events specified" msgstr "중복 트리거 이벤트가 지정됨" -#: gram.y:5997 +#: gram.y:6121 #, c-format msgid "conflicting constraint properties" msgstr "제약조건 속성이 충돌함" -#: gram.y:6096 +#: gram.y:6220 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "CREATE ASSERTION 명령은 아직 구현 되지 않았습니다" -#: gram.y:6504 +#: gram.y:6537 +#, c-format +msgid "dropping an enum value is not implemented" +msgstr "구현되지 않은 enum 값을 삭제 중" + +#: gram.y:6655 #, c-format msgid "RECHECK is no longer required" msgstr "RECHECK는 더 이상 필요하지 않음" -#: gram.y:6505 +#: gram.y:6656 #, c-format msgid "Update your data type." msgstr "자료형을 업데이트하십시오." -#: gram.y:8378 +#: gram.y:8529 #, c-format msgid "aggregates cannot have output arguments" msgstr "집계 함수는 output 인자를 지정할 수 없음" -#: gram.y:11054 gram.y:11073 +#: gram.y:11221 gram.y:11240 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "WITH CHECK OPTION 구문은 재귀적인 뷰에서 지원하지 않습니다" -#: gram.y:12960 +#: gram.y:13162 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "LIMIT #,# 구문은 지원하지 않습니다." -#: gram.y:12961 +#: gram.y:13163 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "LIMIT # OFFSET # 구문을 사용하세요." -#: gram.y:13821 +#: gram.y:14038 #, c-format msgid "only one DEFAULT value is allowed" -msgstr "" +msgstr "DEFAULT 값은 하나만 허용함" -#: gram.y:13830 +#: gram.y:14047 #, c-format msgid "only one PATH value per column is allowed" -msgstr "" +msgstr "PATH 값은 칼럼당 하나만 허용함" -#: gram.y:13839 +#: gram.y:14056 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "NULL/NOT NULL 선언이 서로 충돌합니다 : \"%s\" 칼럼" -#: gram.y:13848 +#: gram.y:14065 #, c-format msgid "unrecognized column option \"%s\"" msgstr "인식할 수 없는 칼럼 옵션 \"%s\"" -#: gram.y:14102 +#: gram.y:14147 +#, c-format +msgid "only string constants are supported in JSON_TABLE path specification" +msgstr "JSON_TABLE 경로 명세에서는 문자열 상수만 지원함" + +#: gram.y:14469 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "실수형 자료의 정밀도 값으로는 적어도 1 bit 이상을 지정해야 합니다." -#: gram.y:14111 +#: gram.y:14478 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "실수형 자료의 정밀도 값으로 최대 54 bit 까지입니다." -#: gram.y:14614 +#: gram.y:14995 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "OVERLAPS 식의 왼쪽에 있는 매개 변수 수가 잘못됨" -#: gram.y:14619 +#: gram.y:15000 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "OVERLAPS 식의 오른쪽에 있는 매개 변수 수가 잘못됨" -#: gram.y:14796 +#: gram.y:15177 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "UNIQUE 술어는 아직 구현되지 못했습니다" -#: gram.y:15212 +#: gram.y:15591 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "WITHIN GROUP 구문 안에서 중복된 ORDER BY 구문은 허용하지 않습니다" -#: gram.y:15217 +#: gram.y:15596 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "DISTINCT과 WITHIN GROUP을 함께 쓸 수 없습니다" -#: gram.y:15222 +#: gram.y:15601 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "VARIADIC과 WITHIN GROUP을 함께 쓸 수 없습니다" -#: gram.y:15856 gram.y:15880 +#: gram.y:16328 gram.y:16352 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "프레임 시작은 UNBOUNDED FOLLOWING일 수 없음" -#: gram.y:15861 +#: gram.y:16333 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "따라오는 로우의 프레임 시작은 현재 로우의 끝일 수 없습니다" -#: gram.y:15885 +#: gram.y:16357 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "프레임 끝은 UNBOUNDED PRECEDING일 수 없음" -#: gram.y:15891 +#: gram.y:16363 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "현재 로우의 프레임 시작은 선행하는 로우를 가질 수 없습니다" -#: gram.y:15898 +#: gram.y:16370 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "따라오는 로우의 프레임 시작은 선행하는 로우를 가질 수 없습니다" -#: gram.y:16659 +#: gram.y:16919 +#, c-format +msgid "unrecognized JSON encoding: %s" +msgstr "알 수 없는 JSON 인코딩: %s" + +#: gram.y:17243 #, c-format msgid "type modifier cannot have parameter name" msgstr "자료형 한정자는 매개 변수 이름을 사용할 수 없음" -#: gram.y:16665 +#: gram.y:17249 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "자료형 한정자는 ORDER BY 구문을 사용할 수 없음" -#: gram.y:16733 gram.y:16740 gram.y:16747 +#: gram.y:17317 gram.y:17324 gram.y:17331 #, c-format msgid "%s cannot be used as a role name here" msgstr "%s 이름은 여기서 롤 이름으로 사용할 수 없음" -#: gram.y:16837 gram.y:18294 +#: gram.y:17421 gram.y:18906 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" -msgstr "" +msgstr "WITH TIES 절은 ORDER BY 절과 함께 사용되어야 함" -#: gram.y:17973 gram.y:18160 +#: gram.y:18597 gram.y:18772 msgid "improper use of \"*\"" msgstr "\"*\" 사용이 잘못됨" -#: gram.y:18224 +#: gram.y:18836 #, c-format msgid "" "an ordered-set aggregate with a VARIADIC direct argument must have one " "VARIADIC aggregated argument of the same data type" msgstr "" +"VARIADIC 직접 인자가 있는 정렬된 집합 집계 함수는 동일한 자료형의 VARIADIC " +"집계된 인자가 하나 있어야 합니다." -#: gram.y:18261 +#: gram.y:18873 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "중복된 ORDER BY 구문은 허용하지 않습니다" -#: gram.y:18272 +#: gram.y:18884 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "중복된 OFFSET 구문은 허용하지 않습니다" -#: gram.y:18281 +#: gram.y:18893 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "중복된 LIMIT 구문은 허용하지 않습니다" -#: gram.y:18290 +#: gram.y:18902 #, c-format msgid "multiple limit options not allowed" msgstr "중복된 limit 옵션은 허용하지 않음" -#: gram.y:18317 +#: gram.y:18929 #, c-format msgid "multiple WITH clauses not allowed" msgstr "중복된 WITH 절은 허용하지 않음" -#: gram.y:18510 +#: gram.y:19122 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "OUT 및 INOUT 인자는 TABLE 함수에 사용할 수 없음" -#: gram.y:18643 +#: gram.y:19255 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "중복된 COLLATE 구문은 허용하지 않습니다" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18681 gram.y:18694 +#: gram.y:19293 gram.y:19306 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "%s 제약조건에는 DEFERRABLE 옵션을 쓸 수 없음" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18707 +#: gram.y:19319 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "%s 제약조건에는 NOT VALID 옵션을 쓸 수 없음" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18720 +#: gram.y:19332 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "%s 제약조건에는 NO INHERIT 옵션을 쓸 수 없음" -#: gram.y:18742 +#: gram.y:19354 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "알 수 없는 파티션 규칙 \"%s\"" -#: gram.y:18766 +#: gram.y:19378 #, c-format msgid "invalid publication object list" msgstr "잘못된 발행 객체 목록" -#: gram.y:18767 +#: gram.y:19379 #, c-format msgid "" "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table " "or schema name." msgstr "" +"TABLE이나 TABLES IN SCHEMA 중 하나가 독립 테이블이나 스키마 이름 앞에 있어야 합니다." -#: gram.y:18783 +#: gram.y:19395 #, c-format msgid "invalid table name" msgstr "잘못된 테이블 이름" -#: gram.y:18804 +#: gram.y:19416 #, c-format msgid "WHERE clause not allowed for schema" msgstr "WHERE 절은 스키마용으로 허용하지 않음" -#: gram.y:18811 +#: gram.y:19423 #, c-format msgid "column specification not allowed for schema" msgstr "칼럼 명세는 스키마용으로 허용하지 않음" -#: gram.y:18825 +#: gram.y:19437 #, c-format msgid "invalid schema name" msgstr "잘못된 스키마 이름" @@ -32304,12 +33778,17 @@ msgstr "\"%s\" 파일 %u 줄에서 구문 오류 있음, \"%s\" 토큰 부근" msgid "too many syntax errors found, abandoning file \"%s\"" msgstr "구문 오류가 너무 많습니다. \"%s\" 파일을 무시합니다" -#: jsonpath_gram.y:529 +#: jsonpath_gram.y:267 +#, c-format +msgid ".decimal() can only have an optional precision[,scale]." +msgstr ".decimal() 함수는 precision[,scale] 만 선택적으로 쓸 수 있음." + +#: jsonpath_gram.y:599 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." msgstr "LIKE_REGEX 구문에서 알 수 없는 플래그 문자: \"%.*s\"" -#: jsonpath_gram.y:607 +#: jsonpath_gram.y:677 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "XQuery \"x\" 플래그 (확장된 정규 표현식)는 구현되지 않았습니다." @@ -32326,7 +33805,7 @@ msgstr "잘못된 16진수 문자 순차연결" msgid "unexpected end after backslash" msgstr "백슬래시 뒤 예기치 않은 줄 끝" -#: jsonpath_scan.l:201 repl_scanner.l:209 scan.l:741 +#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:756 msgid "unterminated quoted string" msgstr "마무리 안된 따옴표 안의 문자열" @@ -32338,8 +33817,8 @@ msgstr "주석 뒤 예기치 않은 줄 끝" msgid "invalid numeric literal" msgstr "잘못된 숫자 문자열" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1049 -#: scan.l:1053 scan.l:1057 scan.l:1061 scan.l:1065 scan.l:1069 scan.l:1073 +#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1064 +#: scan.l:1068 scan.l:1072 scan.l:1076 msgid "trailing junk after numeric literal" msgstr "숫자 뒤에 쓸모 없는 값이 더 있음" @@ -32355,70 +33834,70 @@ msgstr "%s, jsonpath 입력 끝부분" msgid "%s at or near \"%s\" of jsonpath input" msgstr "%s, jsonpath 입력 \"%s\" 부근" -#: jsonpath_scan.l:557 +#: jsonpath_scan.l:568 msgid "invalid input" msgstr "잘못된 입력" -#: jsonpath_scan.l:583 +#: jsonpath_scan.l:594 msgid "invalid hexadecimal digit" msgstr "잘못된 16진수" -#: jsonpath_scan.l:614 +#: jsonpath_scan.l:625 #, c-format msgid "could not convert Unicode to server encoding" msgstr "유니코드를 서버 인코딩으로 바꿀 수 없음" -#: repl_gram.y:301 repl_gram.y:333 +#: repl_gram.y:318 repl_gram.y:359 #, c-format msgid "invalid timeline %u" msgstr "잘못된 타임라인: %u" -#: repl_scanner.l:152 +#: repl_scanner.l:154 msgid "invalid streaming start location" msgstr "잘못된 스트리밍 시작 위치" # # advance 끝 -#: scan.l:482 +#: scan.l:497 msgid "unterminated /* comment" msgstr "마무리 안된 /* 주석" -#: scan.l:502 +#: scan.l:517 msgid "unterminated bit string literal" msgstr "마무리 안된 비트 문자열 문자" -#: scan.l:516 +#: scan.l:531 msgid "unterminated hexadecimal string literal" msgstr "마무리 안된 16진수 문자열 문자" -#: scan.l:566 +#: scan.l:581 #, c-format msgid "unsafe use of string constant with Unicode escapes" msgstr "유니코드 이스케이프와 함께 문자열 상수를 사용하는 것은 안전하지 않음" -#: scan.l:567 +#: scan.l:582 #, c-format msgid "" "String constants with Unicode escapes cannot be used when " -"standard_conforming_strings is off." +"\"standard_conforming_strings\" is off." msgstr "" -"standard_conforming_strings = off 인 경우 문자열 상수 표기에서 유니코드 이스" +"\"standard_conforming_strings\" = off 인 경우 문자열 상수 표기에서 유니코드 이스" "케이프를 사용할 수 없습니다." -#: scan.l:628 +#: scan.l:643 msgid "unhandled previous state in xqs" msgstr "xqs 안에 처리할 수 없는 이전 상태" -#: scan.l:702 +#: scan.l:717 #, c-format msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX." msgstr "유니코드 이스케이프는 \\uXXXX 또는 \\UXXXXXXXX 형태여야 합니다." -#: scan.l:713 +#: scan.l:728 #, c-format msgid "unsafe use of \\' in a string literal" msgstr "문자열 안에 \\' 사용이 안전하지 않습니다" -#: scan.l:714 +#: scan.l:729 #, c-format msgid "" "Use '' to write quotes in strings. \\' is insecure in client-only encodings." @@ -32426,176 +33905,92 @@ msgstr "" "작은 따옴표는 '' 형태로 사용하십시오. \\' 표기법은 클라이언트 전용 인코딩에" "서 안전하지 않습니다." -#: scan.l:786 +#: scan.l:801 msgid "unterminated dollar-quoted string" msgstr "마무리 안된 달러-따옴표 안의 문자열" -#: scan.l:803 scan.l:813 +#: scan.l:818 scan.l:828 msgid "zero-length delimited identifier" msgstr "길이가 0인 구분 식별자" -#: scan.l:824 syncrep_scanner.l:101 +#: scan.l:839 syncrep_scanner.l:101 msgid "unterminated quoted identifier" msgstr "마무리 안된 따옴표 안의 식별자" # # nonun 부분 begin -#: scan.l:987 +#: scan.l:1002 msgid "operator too long" msgstr "연산자가 너무 깁니다." -#: scan.l:1000 +#: scan.l:1015 msgid "trailing junk after parameter" msgstr "매개 변수 뒤에 쓸모 없는 값이 더 있음" -#: scan.l:1021 +#: scan.l:1036 msgid "invalid hexadecimal integer" msgstr "잘못된 16진수" -#: scan.l:1025 +#: scan.l:1040 msgid "invalid octal integer" msgstr "잘못된 8진수" -#: scan.l:1029 +#: scan.l:1044 msgid "invalid binary integer" msgstr "잘못된 바이너리 숫자" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1236 +#: scan.l:1239 #, c-format msgid "%s at end of input" msgstr "%s, 입력 끝부분" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1244 +#: scan.l:1247 #, c-format msgid "%s at or near \"%s\"" msgstr "%s, \"%s\" 부근" -#: scan.l:1434 +#: scan.l:1439 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "문자열 안에 있는 \\' 문자는 표준이 아닙니다" -#: scan.l:1435 +#: scan.l:1440 #, c-format msgid "" "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "작은 따옴표는 '' 형태니, 인용부호 표기법(E'...') 형태로 사용하십시오." -#: scan.l:1444 +#: scan.l:1449 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "문자열 안에 있는 \\\\ 문자는 표준이 아닙니다" -#: scan.l:1445 +#: scan.l:1450 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "백슬래시 표기는 인용부호 표기법으로 사용하세요, 예, E'\\\\'." -#: scan.l:1459 +#: scan.l:1464 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "문자열 안에 비표준 escape 문자를 사용하고 있습니다" -#: scan.l:1460 +#: scan.l:1465 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "인용부호 표기법을 사용하세요, 예, E'\\r\\n'." #, c-format -#~ msgid "FORMAT JSON has no effect for json and jsonb types" +#~ msgid "removing future two-phase state file of epoch %u for transaction %u" #~ msgstr "" -#~ "json, jsonb 자료형에서는 FORMAT JSON 지정이 아무런 영향을 끼치지 못합니다." - -#, c-format -#~ msgid "Subscribed publication %s is subscribing to other publications." -#~ msgid_plural "" -#~ "Subscribed publications %s are subscribing to other publications." -#~ msgstr[0] "%s 구독은 이미 다른 발행을 구독하고 있습니다." - -#, c-format -#~ msgid "duplicate JSON key %s" -#~ msgstr "중복된 JSON 키 %s" - -#, c-format -#~ msgid "duplicate JSON object key" -#~ msgstr "JSON 객체 키 중복" - -#, c-format -#~ msgid "authentication file token too long, skipping: \"%s\"" -#~ msgstr "인증 파일의 토큰이 너무 길어서 건너뜁니다: \"%s\"" - -#~ msgid "logical replication table synchronization worker" -#~ msgstr "논리 복제 테이블 동기화 작업자" - -#~ msgid "logical replication apply worker" -#~ msgstr "논리 복제 반영 작업자" - -#, c-format -#~ msgid "" -#~ "%s for subscription \"%s\" will restart because of a parameter change" -#~ msgstr "매개 변수가 바뀌어서 %s(해당 구독: \"%s\")가 다시 시작됩니다." - -#, c-format -#~ msgid "%s for subscription \"%s\" has started" -#~ msgstr "%s가 \"%s\" 구독용으로 시작되었음" - -#, c-format -#~ msgid "could not set compression flag for %s: %s" -#~ msgstr "%s 용 압축 플래그를 지정할 수 없음: %s" - -#, c-format -#~ msgid "permission denied to cluster \"%s\", skipping it" -#~ msgstr "\"%s\" 클러스터 권한 없음, 건너뜀" - -#, c-format -#~ msgid "unexpected DEFAULT in COPY data" -#~ msgstr "COPY 자료 안에 예상치 못한 DEFAULT" - -#, c-format -#~ msgid "must be a superuser to terminate superuser process" -#~ msgstr "슈퍼유저의 세션을 정리하려면 슈퍼유저여야 합니다." - -#~ msgid "invalid unicode sequence" -#~ msgstr "잘못된 유니코드 이스케이프" - -#~ msgid "unexpected end of quoted string" -#~ msgstr "따옴표 뒤 예기치 않은 줄 끝" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "%X/%X 위치에 contrecord 없음" - -#, c-format -#~ msgid "unable to map dynamic shared memory segment" -#~ msgstr "동적 공유 메모리 세그먼트를 할당할 수 없음" - -#, c-format -#~ msgid "bad magic number in dynamic shared memory segment" -#~ msgstr "동적 공유 메모리 세그먼트에 잘못된 매직 번호가 있음" - -#, c-format -#~ msgid "You might need to increase max_logical_replication_workers." -#~ msgstr "max_logical_replication_workers 값을 늘리세요." - -#, c-format -#~ msgid "You might need to increase max_worker_processes." -#~ msgstr "max_worker_processes 값을 늘리세요." - -#, c-format -#~ msgid "You might need to increase max_slot_wal_keep_size." -#~ msgstr "max_slot_wal_keep_size 값을 늘리세요." +#~ "epoch %u의 future two-phase 상태정보 파일을 삭제함, 대상 트랜잭션: %u" #, c-format -#~ msgid "You might need to increase max_locks_per_transaction." -#~ msgstr "max_locks_per_transaction을 늘려야 할 수도 있습니다." +#~ msgid "removing past two-phase state file of epoch %u for transaction %u" +#~ msgstr "epoch %u의 past two-phase 상태정보 파일을 삭제함, 대상 트랜잭션: %u" #, c-format -#~ msgid "You might need to increase max_pred_locks_per_transaction." -#~ msgstr "max_pred_locks_per_transaction 값을 늘려야 할 수도 있습니다." - -#~ msgid "Shows the collation order locale." -#~ msgstr "데이터 정렬 순서 로케일을 표시합니다." - -#~ msgid "Shows the character classification and case conversion locale." -#~ msgstr "문자 분류 및 대/소문자 변환 로케일을 표시합니다." +#~ msgid "removing past two-phase state from memory for transaction %u" +#~ msgstr "" +#~ "%u 트랜잭션에서 사용하는 past two-phase 상태정보를 메모리에서 삭제함" diff --git a/src/backend/po/meson.build b/src/backend/po/meson.build index ff995b5d6a5be..94ee268564ddd 100644 --- a/src/backend/po/meson.build +++ b/src/backend/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('postgres-' + pg_version_major.to_string())] diff --git a/src/backend/po/ru.po b/src/backend/po/ru.po index 85d9a1535a411..f8e7152cd84f1 100644 --- a/src/backend/po/ru.po +++ b/src/backend/po/ru.po @@ -4,14 +4,14 @@ # Serguei A. Mokhov , 2001-2005. # Oleg Bartunov , 2004-2005. # Dmitriy Olshevskiy , 2014. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. -# Maxim Yablokov , 2021, 2022. +# Alexander Lakhin , 2012-2025. +# Maxim Yablokov , 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: postgres (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2024-05-04 10:47+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2025-02-08 08:50+0200\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -21,6 +21,11 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +#: ../common/binaryheap.c:121 ../common/binaryheap.c:159 +#, c-format +msgid "out of binary heap slots" +msgstr "недостаточно слотов в двоичной куче" + #: ../common/compression.c:132 ../common/compression.c:141 #: ../common/compression.c:150 #, c-format @@ -82,64 +87,66 @@ msgstr "алгоритм сжатия \"%s\" не поддерживает ре msgid "not recorded" msgstr "не записано" -#: ../common/controldata_utils.c:79 ../common/controldata_utils.c:83 -#: commands/copyfrom.c:1687 commands/extension.c:3480 utils/adt/genfile.c:123 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 +#: commands/copyfrom.c:1739 commands/extension.c:3538 utils/adt/genfile.c:123 +#: utils/time/snapmgr.c:1430 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не удалось открыть файл \"%s\" для чтения: %m" -#: ../common/controldata_utils.c:94 ../common/controldata_utils.c:96 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 #: access/transam/timeline.c:143 access/transam/timeline.c:362 -#: access/transam/twophase.c:1347 access/transam/xlog.c:3195 -#: access/transam/xlog.c:3998 access/transam/xlogrecovery.c:1225 -#: access/transam/xlogrecovery.c:1317 access/transam/xlogrecovery.c:1354 -#: access/transam/xlogrecovery.c:1414 backup/basebackup.c:1846 -#: commands/extension.c:3490 libpq/hba.c:769 replication/logical/origin.c:745 -#: replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5050 -#: replication/logical/snapbuild.c:2031 replication/slot.c:1980 -#: replication/slot.c:2021 replication/walsender.c:643 +#: access/transam/twophase.c:1353 access/transam/xlog.c:3477 +#: access/transam/xlog.c:4341 access/transam/xlogrecovery.c:1238 +#: access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 +#: access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 +#: backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 +#: replication/logical/reorderbuffer.c:5113 +#: replication/logical/snapbuild.c:2052 replication/slot.c:2236 +#: replication/slot.c:2277 replication/walsender.c:655 #: storage/file/buffile.c:470 storage/file/copydir.c:185 -#: utils/adt/genfile.c:197 utils/adt/misc.c:984 utils/cache/relmapper.c:830 +#: utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "не удалось прочитать файл \"%s\": %m" -#: ../common/controldata_utils.c:102 ../common/controldata_utils.c:105 -#: access/transam/xlog.c:3200 access/transam/xlog.c:4003 -#: backup/basebackup.c:1850 replication/logical/origin.c:750 -#: replication/logical/origin.c:789 replication/logical/snapbuild.c:2036 -#: replication/slot.c:1984 replication/slot.c:2025 replication/walsender.c:648 -#: utils/cache/relmapper.c:834 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 +#: access/transam/xlog.c:3482 access/transam/xlog.c:4346 +#: replication/logical/origin.c:750 replication/logical/origin.c:789 +#: replication/logical/snapbuild.c:2057 replication/slot.c:2240 +#: replication/slot.c:2281 replication/walsender.c:660 +#: utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" -#: ../common/controldata_utils.c:114 ../common/controldata_utils.c:118 -#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:266 -#: access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1280 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 +#: ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 +#: access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 #: access/transam/timeline.c:392 access/transam/timeline.c:438 -#: access/transam/timeline.c:512 access/transam/twophase.c:1359 -#: access/transam/twophase.c:1771 access/transam/xlog.c:3041 -#: access/transam/xlog.c:3235 access/transam/xlog.c:3240 -#: access/transam/xlog.c:3376 access/transam/xlog.c:3968 -#: access/transam/xlog.c:4887 commands/copyfrom.c:1747 commands/copyto.c:332 +#: access/transam/timeline.c:512 access/transam/twophase.c:1365 +#: access/transam/twophase.c:1784 access/transam/xlog.c:3323 +#: access/transam/xlog.c:3517 access/transam/xlog.c:3522 +#: access/transam/xlog.c:3658 access/transam/xlog.c:4311 +#: access/transam/xlog.c:5246 commands/copyfrom.c:1799 commands/copyto.c:325 #: libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 #: replication/logical/origin.c:683 replication/logical/origin.c:822 -#: replication/logical/reorderbuffer.c:5102 -#: replication/logical/snapbuild.c:1798 replication/logical/snapbuild.c:1922 -#: replication/slot.c:1871 replication/slot.c:2032 replication/walsender.c:658 -#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:782 -#: storage/file/fd.c:3700 storage/file/fd.c:3806 utils/cache/relmapper.c:842 -#: utils/cache/relmapper.c:957 +#: replication/logical/reorderbuffer.c:5165 +#: replication/logical/snapbuild.c:1819 replication/logical/snapbuild.c:1943 +#: replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 +#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:828 +#: storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 +#: utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "не удалось закрыть файл \"%s\": %m" -#: ../common/controldata_utils.c:154 +#: ../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "несоответствие порядка байт" -#: ../common/controldata_utils.c:156 +#: ../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -153,141 +160,157 @@ msgstr "" "этой программой. В этом случае результаты будут неверными и\n" "установленный PostgreSQL будет несовместим с этим каталогом данных." -#: ../common/controldata_utils.c:211 ../common/controldata_utils.c:216 -#: ../common/file_utils.c:228 ../common/file_utils.c:287 -#: ../common/file_utils.c:361 access/heap/rewriteheap.c:1263 -#: access/transam/timeline.c:111 access/transam/timeline.c:251 -#: access/transam/timeline.c:348 access/transam/twophase.c:1303 -#: access/transam/xlog.c:2948 access/transam/xlog.c:3111 -#: access/transam/xlog.c:3150 access/transam/xlog.c:3343 -#: access/transam/xlog.c:3988 access/transam/xlogrecovery.c:4213 -#: access/transam/xlogrecovery.c:4316 access/transam/xlogutils.c:838 -#: backup/basebackup.c:538 backup/basebackup.c:1516 libpq/hba.c:629 -#: postmaster/syslogger.c:1560 replication/logical/origin.c:735 -#: replication/logical/reorderbuffer.c:3706 -#: replication/logical/reorderbuffer.c:4257 -#: replication/logical/reorderbuffer.c:5030 -#: replication/logical/snapbuild.c:1753 replication/logical/snapbuild.c:1863 -#: replication/slot.c:1952 replication/walsender.c:616 -#: replication/walsender.c:2731 storage/file/copydir.c:151 -#: storage/file/fd.c:757 storage/file/fd.c:3457 storage/file/fd.c:3687 -#: storage/file/fd.c:3777 storage/smgr/md.c:663 utils/cache/relmapper.c:819 -#: utils/cache/relmapper.c:936 utils/error/elog.c:2086 -#: utils/init/miscinit.c:1537 utils/init/miscinit.c:1671 -#: utils/init/miscinit.c:1748 utils/misc/guc.c:4609 utils/misc/guc.c:4659 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 +#: ../common/file_utils.c:70 ../common/file_utils.c:347 +#: ../common/file_utils.c:406 ../common/file_utils.c:480 +#: access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 +#: access/transam/timeline.c:251 access/transam/timeline.c:348 +#: access/transam/twophase.c:1309 access/transam/xlog.c:3230 +#: access/transam/xlog.c:3393 access/transam/xlog.c:3432 +#: access/transam/xlog.c:3625 access/transam/xlog.c:4331 +#: access/transam/xlogrecovery.c:4264 access/transam/xlogrecovery.c:4367 +#: access/transam/xlogutils.c:836 backup/basebackup.c:547 +#: backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 +#: postmaster/syslogger.c:1511 replication/logical/origin.c:735 +#: replication/logical/reorderbuffer.c:3766 +#: replication/logical/reorderbuffer.c:4320 +#: replication/logical/reorderbuffer.c:5093 +#: replication/logical/snapbuild.c:1774 replication/logical/snapbuild.c:1884 +#: replication/slot.c:2208 replication/walsender.c:628 +#: replication/walsender.c:3051 storage/file/copydir.c:151 +#: storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 +#: storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 +#: utils/cache/relmapper.c:935 utils/error/elog.c:2124 +#: utils/init/miscinit.c:1580 utils/init/miscinit.c:1714 +#: utils/init/miscinit.c:1791 utils/misc/guc.c:4777 utils/misc/guc.c:4827 #, c-format msgid "could not open file \"%s\": %m" msgstr "не удалось открыть файл \"%s\": %m" -#: ../common/controldata_utils.c:232 ../common/controldata_utils.c:235 -#: access/transam/twophase.c:1744 access/transam/twophase.c:1753 -#: access/transam/xlog.c:8757 access/transam/xlogfuncs.c:708 -#: backup/basebackup_server.c:175 backup/basebackup_server.c:268 -#: postmaster/postmaster.c:5573 postmaster/syslogger.c:1571 -#: postmaster/syslogger.c:1584 postmaster/syslogger.c:1597 -#: utils/cache/relmapper.c:948 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 +#: access/transam/twophase.c:1757 access/transam/twophase.c:1766 +#: access/transam/xlog.c:9280 access/transam/xlogfuncs.c:698 +#: backup/basebackup_server.c:173 backup/basebackup_server.c:266 +#: backup/walsummary.c:304 postmaster/postmaster.c:4127 +#: postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 +#: postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "не удалось записать файл \"%s\": %m" -#: ../common/controldata_utils.c:249 ../common/controldata_utils.c:254 -#: ../common/file_utils.c:299 ../common/file_utils.c:369 -#: access/heap/rewriteheap.c:959 access/heap/rewriteheap.c:1169 -#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:432 -#: access/transam/timeline.c:506 access/transam/twophase.c:1765 -#: access/transam/xlog.c:3034 access/transam/xlog.c:3229 -#: access/transam/xlog.c:3961 access/transam/xlog.c:8147 -#: access/transam/xlog.c:8192 backup/basebackup_server.c:209 -#: commands/dbcommands.c:515 replication/logical/snapbuild.c:1791 -#: replication/slot.c:1857 replication/slot.c:1962 storage/file/fd.c:774 -#: storage/file/fd.c:3798 storage/smgr/md.c:1135 storage/smgr/md.c:1180 -#: storage/sync/sync.c:451 utils/misc/guc.c:4379 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 +#: ../common/file_utils.c:418 ../common/file_utils.c:488 +#: access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 +#: access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 +#: access/transam/timeline.c:506 access/transam/twophase.c:1778 +#: access/transam/xlog.c:3316 access/transam/xlog.c:3511 +#: access/transam/xlog.c:4304 access/transam/xlog.c:8655 +#: access/transam/xlog.c:8700 backup/basebackup_server.c:207 +#: commands/dbcommands.c:514 replication/logical/snapbuild.c:1812 +#: replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 +#: storage/file/fd.c:3851 storage/smgr/md.c:1331 storage/smgr/md.c:1376 +#: storage/sync/sync.c:446 utils/misc/guc.c:4530 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:133 -#: ../common/cryptohash_openssl.c:332 ../common/exec.c:550 ../common/exec.c:595 -#: ../common/exec.c:687 ../common/hmac.c:309 ../common/hmac.c:325 -#: ../common/hmac_openssl.c:132 ../common/hmac_openssl.c:327 -#: ../common/md5_common.c:155 ../common/psprintf.c:143 -#: ../common/scram-common.c:269 ../common/stringinfo.c:305 ../port/path.c:751 -#: ../port/path.c:789 ../port/path.c:806 access/transam/twophase.c:1412 -#: access/transam/xlogrecovery.c:589 lib/dshash.c:253 libpq/auth.c:1343 -#: libpq/auth.c:1387 libpq/auth.c:1944 libpq/be-secure-gssapi.c:524 -#: postmaster/bgworker.c:352 postmaster/bgworker.c:934 -#: postmaster/postmaster.c:2537 postmaster/postmaster.c:4130 -#: postmaster/postmaster.c:5498 postmaster/postmaster.c:5869 -#: replication/libpqwalreceiver/libpqwalreceiver.c:361 -#: replication/logical/logical.c:208 replication/walsender.c:686 -#: storage/buffer/localbuf.c:601 storage/file/fd.c:866 storage/file/fd.c:1397 -#: storage/file/fd.c:1558 storage/file/fd.c:2478 storage/ipc/procarray.c:1449 -#: storage/ipc/procarray.c:2231 storage/ipc/procarray.c:2238 -#: storage/ipc/procarray.c:2737 storage/ipc/procarray.c:3373 -#: utils/adt/formatting.c:1690 utils/adt/formatting.c:1812 -#: utils/adt/formatting.c:1935 utils/adt/pg_locale.c:473 -#: utils/adt/pg_locale.c:637 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:514 -#: utils/hash/dynahash.c:614 utils/hash/dynahash.c:1111 utils/mb/mbutils.c:402 -#: utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 utils/mb/mbutils.c:842 -#: utils/misc/guc.c:640 utils/misc/guc.c:665 utils/misc/guc.c:1053 -#: utils/misc/guc.c:4357 utils/misc/tzparser.c:476 utils/mmgr/aset.c:445 -#: utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:736 utils/mmgr/dsa.c:817 -#: utils/mmgr/generation.c:205 utils/mmgr/mcxt.c:1046 utils/mmgr/mcxt.c:1082 -#: utils/mmgr/mcxt.c:1120 utils/mmgr/mcxt.c:1158 utils/mmgr/mcxt.c:1246 -#: utils/mmgr/mcxt.c:1277 utils/mmgr/mcxt.c:1313 utils/mmgr/mcxt.c:1502 -#: utils/mmgr/mcxt.c:1547 utils/mmgr/mcxt.c:1604 utils/mmgr/slab.c:366 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 +#: ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 +#: ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 +#: ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 +#: ../common/md5_common.c:156 ../common/parse_manifest.c:157 +#: ../common/parse_manifest.c:852 ../common/psprintf.c:143 +#: ../common/scram-common.c:268 ../common/stringinfo.c:314 ../port/path.c:828 +#: ../port/path.c:865 ../port/path.c:882 access/transam/twophase.c:1418 +#: access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 +#: libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 +#: postmaster/bgworker.c:355 postmaster/bgworker.c:945 +#: postmaster/postmaster.c:3560 postmaster/postmaster.c:4021 +#: postmaster/postmaster.c:4383 postmaster/walsummarizer.c:935 +#: replication/libpqwalreceiver/libpqwalreceiver.c:387 +#: replication/logical/logical.c:210 replication/walsender.c:835 +#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 +#: storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1465 +#: storage/ipc/procarray.c:2219 storage/ipc/procarray.c:2226 +#: storage/ipc/procarray.c:2731 storage/ipc/procarray.c:3435 +#: utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 +#: utils/adt/formatting.c:2075 utils/adt/pg_locale.c:532 +#: utils/adt/pg_locale.c:696 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 +#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 +#: utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 +#: utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 +#: utils/misc/guc.c:4508 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 +#: utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 +#: utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 +#: utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "нехватка памяти" #: ../common/cryptohash.c:266 ../common/cryptohash.c:272 -#: ../common/cryptohash_openssl.c:344 ../common/cryptohash_openssl.c:352 -#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:339 -#: ../common/hmac_openssl.c:347 +#: ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 +#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 +#: ../common/hmac_openssl.c:377 msgid "success" msgstr "успех" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:346 -#: ../common/hmac_openssl.c:341 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 +#: ../common/hmac_openssl.c:371 msgid "destination buffer too small" msgstr "буфер назначения слишком мал" -#: ../common/cryptohash_openssl.c:348 ../common/hmac_openssl.c:343 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 msgid "OpenSSL failure" msgstr "ошибка OpenSSL" -#: ../common/exec.c:172 +#: ../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../common/exec.c:215 +#: ../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../common/exec.c:223 +#: ../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../common/exec.c:250 +#: ../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../common/exec.c:412 libpq/pqcomm.c:724 storage/ipc/latch.c:1134 -#: storage/ipc/latch.c:1314 storage/ipc/latch.c:1547 storage/ipc/latch.c:1709 -#: storage/ipc/latch.c:1835 +#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1723 +#: commands/copyto.c:654 libpq/be-secure-common.c:59 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 +#: storage/ipc/latch.c:1349 storage/ipc/latch.c:1589 storage/ipc/latch.c:1751 +#: storage/ipc/latch.c:1877 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" #: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 #: ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 -#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:791 -#: ../port/path.c:808 utils/misc/ps_status.c:195 utils/misc/ps_status.c:203 -#: utils/misc/ps_status.c:230 utils/misc/ps_status.c:238 +#: ../common/psprintf.c:145 ../port/path.c:830 ../port/path.c:867 +#: ../port/path.c:884 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 +#: utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 #, c-format msgid "out of memory\n" msgstr "нехватка памяти\n" @@ -297,39 +320,51 @@ msgstr "нехватка памяти\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" -#: ../common/file_utils.c:87 ../common/file_utils.c:447 -#: ../common/file_utils.c:451 access/transam/twophase.c:1315 -#: access/transam/xlogarchive.c:112 access/transam/xlogarchive.c:236 -#: backup/basebackup.c:346 backup/basebackup.c:544 backup/basebackup.c:615 -#: commands/copyfrom.c:1697 commands/copyto.c:702 commands/extension.c:3469 -#: commands/tablespace.c:810 commands/tablespace.c:899 postmaster/pgarch.c:590 -#: replication/logical/snapbuild.c:1649 storage/file/fd.c:1922 -#: storage/file/fd.c:2008 storage/file/fd.c:3511 utils/adt/dbsize.c:106 -#: utils/adt/dbsize.c:258 utils/adt/dbsize.c:338 utils/adt/genfile.c:483 -#: utils/adt/genfile.c:658 utils/adt/misc.c:340 +#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../common/file_utils.c:120 ../common/file_utils.c:566 +#: ../common/file_utils.c:570 access/transam/twophase.c:1321 +#: access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 +#: backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 +#: backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1749 +#: commands/copyto.c:700 commands/extension.c:3527 commands/tablespace.c:804 +#: commands/tablespace.c:893 postmaster/pgarch.c:680 +#: replication/logical/snapbuild.c:1670 replication/logical/snapbuild.c:2173 +#: storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 +#: utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 +#: utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не удалось получить информацию о файле \"%s\": %m" -#: ../common/file_utils.c:162 ../common/pgfnames.c:48 ../common/rmtree.c:63 -#: commands/tablespace.c:734 commands/tablespace.c:744 -#: postmaster/postmaster.c:1564 storage/file/fd.c:2880 -#: storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:338 +#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../common/file_utils.c:151 ../common/file_utils.c:281 +#: ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 +#: commands/tablespace.c:738 postmaster/postmaster.c:1470 +#: storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 +#: utils/misc/tzparser.c:339 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не удалось открыть каталог \"%s\": %m" -#: ../common/file_utils.c:196 ../common/pgfnames.c:69 ../common/rmtree.c:104 -#: storage/file/fd.c:2892 +#: ../common/file_utils.c:169 ../common/file_utils.c:315 +#: ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не удалось прочитать каталог \"%s\": %m" -#: ../common/file_utils.c:379 access/transam/xlogarchive.c:390 -#: postmaster/pgarch.c:746 postmaster/syslogger.c:1608 -#: replication/logical/snapbuild.c:1810 replication/slot.c:723 -#: replication/slot.c:1743 replication/slot.c:1885 storage/file/fd.c:792 -#: utils/time/snapmgr.c:1284 +#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 +#: postmaster/pgarch.c:834 postmaster/syslogger.c:1559 +#: replication/logical/snapbuild.c:1831 replication/slot.c:936 +#: replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 +#: utils/time/snapmgr.c:1255 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" @@ -338,75 +373,92 @@ msgstr "не удалось переименовать файл \"%s\" в \"%s\" msgid "internal error" msgstr "внутренняя ошибка" -#: ../common/jsonapi.c:1144 +#: ../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "" +"Инкрементальный лексический анализатор не подходит для нисходящего " +"рекурсивного разбора." + +#: ../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "" +"Для инкрементального разбора требуется инкрементальный лексический " +"анализатор." + +#: ../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "" +"Слишком большая вложенность JSON, максимальная допустимая глубина: 6400." + +#: ../common/jsonapi.c:2127 #, c-format -msgid "Escape sequence \"\\%s\" is invalid." -msgstr "Неверная спецпоследовательность: \"\\%s\"." +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Неверная спецпоследовательность: \"\\%.*s\"." -#: ../common/jsonapi.c:1147 +#: ../common/jsonapi.c:2131 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Символ с кодом 0x%02x необходимо экранировать." -#: ../common/jsonapi.c:1150 +#: ../common/jsonapi.c:2135 #, c-format -msgid "Expected end of input, but found \"%s\"." -msgstr "Ожидался конец текста, но обнаружено продолжение \"%s\"." +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Ожидался конец текста, но обнаружено продолжение \"%.*s\"." -#: ../common/jsonapi.c:1153 +#: ../common/jsonapi.c:2138 #, c-format -msgid "Expected array element or \"]\", but found \"%s\"." -msgstr "Ожидался элемент массива или \"]\", но обнаружено \"%s\"." +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Ожидался элемент массива или \"]\", но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1156 +#: ../common/jsonapi.c:2141 #, c-format -msgid "Expected \",\" or \"]\", but found \"%s\"." -msgstr "Ожидалась \",\" или \"]\", но обнаружено \"%s\"." +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Ожидалась \",\" или \"]\", но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1159 +#: ../common/jsonapi.c:2144 #, c-format -msgid "Expected \":\", but found \"%s\"." -msgstr "Ожидалось \":\", но обнаружено \"%s\"." +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Ожидалось \":\", но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1162 +#: ../common/jsonapi.c:2147 #, c-format -msgid "Expected JSON value, but found \"%s\"." -msgstr "Ожидалось значение JSON, но обнаружено \"%s\"." +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Ожидалось значение JSON, но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1165 +#: ../common/jsonapi.c:2150 msgid "The input string ended unexpectedly." msgstr "Неожиданный конец входной строки." -#: ../common/jsonapi.c:1167 +#: ../common/jsonapi.c:2152 #, c-format -msgid "Expected string or \"}\", but found \"%s\"." -msgstr "Ожидалась строка или \"}\", но обнаружено \"%s\"." +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Ожидалась строка или \"}\", но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1170 +#: ../common/jsonapi.c:2155 #, c-format -msgid "Expected \",\" or \"}\", but found \"%s\"." -msgstr "Ожидалась \",\" или \"}\", но обнаружено \"%s\"." +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Ожидалась \",\" или \"}\", но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1173 +#: ../common/jsonapi.c:2158 #, c-format -msgid "Expected string, but found \"%s\"." -msgstr "Ожидалась строка, но обнаружено \"%s\"." +msgid "Expected string, but found \"%.*s\"." +msgstr "Ожидалась строка, но обнаружено \"%.*s\"." -#: ../common/jsonapi.c:1176 +#: ../common/jsonapi.c:2161 #, c-format -msgid "Token \"%s\" is invalid." -msgstr "Ошибочный элемент текста \"%s\"." +msgid "Token \"%.*s\" is invalid." +msgstr "Ошибочный элемент \"%.*s\"." -#: ../common/jsonapi.c:1179 jsonpath_scan.l:597 +#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 нельзя преобразовать в текст." -#: ../common/jsonapi.c:1181 +#: ../common/jsonapi.c:2166 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "За \"\\u\" должны следовать четыре шестнадцатеричные цифры." -#: ../common/jsonapi.c:1184 +#: ../common/jsonapi.c:2169 msgid "" "Unicode escape values cannot be used for code point values above 007F when " "the encoding is not UTF8." @@ -414,20 +466,20 @@ msgstr "" "Спецкоды Unicode для значений выше 007F можно использовать только с " "кодировкой UTF8." -#: ../common/jsonapi.c:1187 +#: ../common/jsonapi.c:2178 #, c-format msgid "" "Unicode escape value could not be translated to the server's encoding %s." msgstr "Спецкод Unicode нельзя преобразовать в серверную кодировку %s." -#: ../common/jsonapi.c:1190 jsonpath_scan.l:630 +#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "" "Старшее слово суррогата Unicode не может следовать за другим старшим словом." -#: ../common/jsonapi.c:1192 jsonpath_scan.l:641 jsonpath_scan.l:651 -#: jsonpath_scan.l:702 +#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 +#: jsonpath_scan.l:713 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "Младшее слово суррогата Unicode должно следовать за старшим словом." @@ -452,11 +504,168 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "не удалось подготовить контекст контрольной суммы манифеста" + +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "неожиданный конец манифеста" + +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "не удалось изменить контекст контрольной суммы манифеста" + +#: ../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "неожиданное начало объекта" + +#: ../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "неожиданный конец объекта" + +#: ../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "неожиданное начало массива" + +#: ../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "неожиданный конец массива" + +#: ../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "ожидалось указание версии" + +#: ../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "нераспознанное поле на верхнем уровне" + +#: ../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "неизвестное поле для файла" + +#: ../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "неизвестное поле в указании диапазона WAL" + +#: ../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "неожиданное поле объекта" + +#: ../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "неожиданное скалярное значение" + +#: ../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "версия манифеста не является целым числом" + +#: ../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "неожиданная версия манифеста" + +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "идентификатор системы в манифесте не является целым числом" + +#: ../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "отсутствует указание пути" + +#: ../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "путь задан в обычном виде и в закодированном" + +#: ../common/parse_manifest.c:666 +msgid "missing size" +msgstr "отсутствует указание размера" + +#: ../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "не задан алгоритм расчёта контрольной суммы" + +#: ../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "не удалось декодировать имя файла" + +#: ../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "размер файла не является целочисленным" + +#: ../common/parse_manifest.c:699 backup/basebackup.c:870 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "нераспознанный алгоритм расчёта контрольных сумм: \"%s\"" + +#: ../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "неверная контрольная сумма для файла \"%s\": \"%s\"" + +#: ../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "отсутствует линия времени" + +#: ../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "отсутствует начальный LSN" + +#: ../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "отсутствует конечный LSN" + +#: ../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "линия времени задана не целым числом" + +#: ../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "не удалось разобрать начальный LSN" + +#: ../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "не удалось разобрать конечный LSN" + +#: ../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "ожидалось как минимум 2 строки" + +#: ../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "последняя строка не оканчивается символом новой строки" + +#: ../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "не удалось завершить расчёт контрольной суммы манифеста" + +#: ../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "в манифесте нет контрольной суммы" + +#: ../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "неверная контрольная сумма в манифесте: \"%s\"" + +#: ../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "ошибка контрольной суммы манифеста" + +#: ../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "не удалось разобрать манифест копии: %s" + #: ../common/percentrepl.c:79 ../common/percentrepl.c:85 #: ../common/percentrepl.c:118 ../common/percentrepl.c:124 -#: postmaster/postmaster.c:2211 utils/misc/guc.c:3120 utils/misc/guc.c:3156 -#: utils/misc/guc.c:3226 utils/misc/guc.c:4556 utils/misc/guc.c:6738 -#: utils/misc/guc.c:6779 +#: tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 +#: utils/misc/guc.c:3283 utils/misc/guc.c:4712 utils/misc/guc.c:6931 +#: utils/misc/guc.c:6972 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "неверное значение для параметра \"%s\": \"%s\"" @@ -517,46 +726,46 @@ msgstr "не удалось перезапуститься с ограничен msgid "could not get exit code from subprocess: error code %lu" msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)" -#: ../common/rmtree.c:95 access/heap/rewriteheap.c:1248 -#: access/transam/twophase.c:1704 access/transam/xlogarchive.c:120 -#: access/transam/xlogarchive.c:400 postmaster/postmaster.c:1143 -#: postmaster/syslogger.c:1537 replication/logical/origin.c:591 -#: replication/logical/reorderbuffer.c:4526 -#: replication/logical/snapbuild.c:1691 replication/logical/snapbuild.c:2125 -#: replication/slot.c:1936 storage/file/fd.c:832 storage/file/fd.c:3325 -#: storage/file/fd.c:3387 storage/file/reinit.c:262 storage/ipc/dsm.c:316 -#: storage/smgr/md.c:383 storage/smgr/md.c:442 storage/sync/sync.c:248 -#: utils/time/snapmgr.c:1608 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 +#: access/transam/twophase.c:1717 access/transam/xlogarchive.c:119 +#: access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 +#: postmaster/syslogger.c:1488 replication/logical/origin.c:591 +#: replication/logical/reorderbuffer.c:4589 +#: replication/logical/snapbuild.c:1712 replication/logical/snapbuild.c:2146 +#: replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 +#: storage/file/fd.c:3440 storage/file/reinit.c:261 storage/ipc/dsm.c:343 +#: storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 +#: utils/time/snapmgr.c:1591 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не удалось стереть файл \"%s\": %m" -#: ../common/rmtree.c:122 commands/tablespace.c:773 commands/tablespace.c:786 -#: commands/tablespace.c:821 commands/tablespace.c:911 storage/file/fd.c:3317 -#: storage/file/fd.c:3726 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 +#: commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 +#: storage/file/fd.c:3779 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "ошибка при удалении каталога \"%s\": %m" -#: ../common/scram-common.c:282 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "не удалось закодировать соль" -#: ../common/scram-common.c:298 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "не удалось закодировать сохранённый ключ" -#: ../common/scram-common.c:315 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "не удалось закодировать ключ сервера" -#: ../common/stringinfo.c:306 +#: ../common/stringinfo.c:315 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "" "Не удалось увеличить строковый буфер (в буфере байт: %d, требовалось ещё %d)." -#: ../common/stringinfo.c:310 +#: ../common/stringinfo.c:319 #, c-format msgid "" "out of memory\n" @@ -573,7 +782,7 @@ msgstr "" msgid "could not look up effective user ID %ld: %s" msgstr "выяснить эффективный идентификатор пользователя (%ld) не удалось: %s" -#: ../common/username.c:45 libpq/auth.c:1879 +#: ../common/username.c:45 libpq/auth.c:1888 msgid "user does not exist" msgstr "пользователь не существует" @@ -610,7 +819,7 @@ msgstr "дочерний процесс завершён по сигналу %d: #: ../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" -msgstr "дочерний процесс завершился с нераспознанным состоянием %d" +msgstr "дочерний процесс завершился с нераспознанным кодом состояния %d" #: ../port/chklocale.c:283 #, c-format @@ -670,22 +879,22 @@ msgstr "" "Возможно, работе СУБД мешает антивирус, программа резервного копирования или " "что-то подобное." -#: ../port/path.c:775 +#: ../port/path.c:852 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "не удалось определить текущий рабочий каталог: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "не удалось определить текущий рабочий каталог: %m\n" #: ../port/strerror.c:72 #, c-format msgid "operating system error %d" msgstr "ошибка ОС %d" -#: ../port/thread.c:50 ../port/thread.c:86 +#: ../port/user.c:43 ../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "найти локального пользователя по идентификатору (%d) не удалось: %s" -#: ../port/thread.c:55 ../port/thread.c:91 +#: ../port/user.c:48 ../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "локальный пользователь с ID %d не существует" @@ -707,7 +916,7 @@ msgid "could not check access token membership: error code %lu\n" msgstr "" "не удалось проверить вхождение в маркере безопасности (код ошибки: %lu)\n" -#: access/brin/brin.c:216 +#: access/brin/brin.c:405 #, c-format msgid "" "request for BRIN range summarization for index \"%s\" page %u was not " @@ -716,72 +925,72 @@ msgstr "" "запрос на расчёт сводки диапазона BRIN для индекса \"%s\" страницы %u не был " "записан" -#: access/brin/brin.c:1036 access/brin/brin.c:1143 access/gin/ginfast.c:1039 -#: access/transam/xlogfuncs.c:189 access/transam/xlogfuncs.c:214 -#: access/transam/xlogfuncs.c:247 access/transam/xlogfuncs.c:286 -#: access/transam/xlogfuncs.c:307 access/transam/xlogfuncs.c:328 -#: access/transam/xlogfuncs.c:398 access/transam/xlogfuncs.c:456 +#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 +#: access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 +#: access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 +#: access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 +#: access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 #, c-format msgid "recovery is in progress" msgstr "идёт процесс восстановления" -#: access/brin/brin.c:1037 access/brin/brin.c:1144 +#: access/brin/brin.c:1386 access/brin/brin.c:1494 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "Функции управления BRIN нельзя использовать в процессе восстановления." -#: access/brin/brin.c:1042 access/brin/brin.c:1149 +#: access/brin/brin.c:1391 access/brin/brin.c:1499 #, c-format msgid "block number out of range: %lld" msgstr "номер блока вне диапазона: %lld" -#: access/brin/brin.c:1086 access/brin/brin.c:1175 +#: access/brin/brin.c:1436 access/brin/brin.c:1525 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\" - это не индекс BRIN" -#: access/brin/brin.c:1102 access/brin/brin.c:1191 +#: access/brin/brin.c:1452 access/brin/brin.c:1541 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "не удалось открыть родительскую таблицу индекса \"%s\"" -#: access/brin/brin.c:1111 access/brin/brin.c:1207 access/gin/ginfast.c:1084 -#: parser/parse_utilcmd.c:2280 +#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 +#: parser/parse_utilcmd.c:2277 #, c-format msgid "index \"%s\" is not valid" msgstr "индекс \"%s\" - нерабочий" -#: access/brin/brin_bloom.c:752 access/brin/brin_bloom.c:794 -#: access/brin/brin_minmax_multi.c:2985 access/brin/brin_minmax_multi.c:3122 -#: statistics/dependencies.c:663 statistics/dependencies.c:716 -#: statistics/mcv.c:1484 statistics/mcv.c:1515 statistics/mvdistinct.c:344 -#: statistics/mvdistinct.c:397 utils/adt/pseudotypes.c:43 -#: utils/adt/pseudotypes.c:77 utils/adt/tsgistidx.c:93 +#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 +#: access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 +#: statistics/dependencies.c:661 statistics/dependencies.c:714 +#: statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 +#: statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 +#: utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format msgid "cannot accept a value of type %s" msgstr "значение типа %s нельзя ввести" -#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 -#: access/brin/brin_pageops.c:852 access/gin/ginentrypage.c:110 -#: access/gist/gist.c:1462 access/spgist/spgdoinsert.c:2002 -#: access/spgist/spgdoinsert.c:2279 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 +#: access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 +#: access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 +#: access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "" "размер строки индекса (%zu) больше предельного размера (%zu) (индекс \"%s\")" -#: access/brin/brin_revmap.c:393 access/brin/brin_revmap.c:399 +#: access/brin/brin_revmap.c:383 access/brin/brin_revmap.c:389 #, c-format msgid "corrupted BRIN index: inconsistent range map" msgstr "испорченный индекс BRIN: несогласованность в карте диапазонов" -#: access/brin/brin_revmap.c:593 +#: access/brin/brin_revmap.c:583 #, c-format msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "неожиданный тип страницы 0x%04X в BRIN-индексе \"%s\" (блок: %u)" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:151 -#: access/gist/gistvalidate.c:153 access/hash/hashvalidate.c:139 +#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 +#: access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 #: access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 #, c-format msgid "" @@ -791,8 +1000,8 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит функцию %s с " "неправильным опорным номером %d" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:163 -#: access/gist/gistvalidate.c:165 access/hash/hashvalidate.c:118 +#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 +#: access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 #: access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 #, c-format msgid "" @@ -802,8 +1011,8 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит функцию %s с " "неподходящим объявлением для опорного номера %d" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:182 -#: access/gist/gistvalidate.c:185 access/hash/hashvalidate.c:160 +#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 +#: access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 #: access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 #, c-format msgid "" @@ -813,7 +1022,7 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит оператор %s с " "неправильным номером стратегии %d" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:195 +#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 #: access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 #: access/spgist/spgvalidate.c:237 #, c-format @@ -824,8 +1033,8 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит некорректное " "определение ORDER BY для оператора %s" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:208 -#: access/gist/gistvalidate.c:233 access/hash/hashvalidate.c:186 +#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 +#: access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 #: access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 #, c-format msgid "" @@ -860,31 +1069,31 @@ msgstr "" msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "в классе операторов \"%s\" метода доступа %s нет оператора(ов)" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:250 -#: access/gist/gistvalidate.c:274 +#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 +#: access/gist/gistvalidate.c:273 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d" msgstr "в классе операторов \"%s\" метода доступа %s нет опорной функции %d" -#: access/common/attmap.c:122 +#: access/common/attmap.c:121 #, c-format msgid "Returned type %s does not match expected type %s in column %d." msgstr "Возвращаемый тип %s не соответствует ожидаемому типу %s в столбце %d." -#: access/common/attmap.c:150 +#: access/common/attmap.c:149 #, c-format msgid "" "Number of returned columns (%d) does not match expected column count (%d)." msgstr "" "Число возвращённых столбцов (%d) не соответствует ожидаемому числу (%d)." -#: access/common/attmap.c:234 access/common/attmap.c:246 +#: access/common/attmap.c:233 access/common/attmap.c:245 #, c-format msgid "could not convert row type" msgstr "не удалось преобразовать тип строки" -#: access/common/attmap.c:235 +#: access/common/attmap.c:234 #, c-format msgid "" "Attribute \"%s\" of type %s does not match corresponding attribute of type " @@ -892,12 +1101,12 @@ msgid "" msgstr "" "Атрибут \"%s\" типа %s несовместим с соответствующим атрибутом типа %s." -#: access/common/attmap.c:247 +#: access/common/attmap.c:246 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "Атрибут \"%s\" типа %s не существует в типе %s." -#: access/common/heaptuple.c:1133 access/common/heaptuple.c:1468 +#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "число столбцов (%d) превышает предел (%d)" @@ -907,122 +1116,110 @@ msgstr "число столбцов (%d) превышает предел (%d)" msgid "number of index columns (%d) exceeds limit (%d)" msgstr "число столбцов индекса (%d) превышает предел (%d)" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:957 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:970 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "строка индекса требует байт: %zu, при максимуме: %zu" -#: access/common/printtup.c:292 tcop/fastpath.c:107 tcop/fastpath.c:454 -#: tcop/postgres.c:1944 +#: access/common/printtup.c:292 commands/explain.c:5376 tcop/fastpath.c:107 +#: tcop/fastpath.c:454 tcop/postgres.c:1956 #, c-format msgid "unsupported format code: %d" msgstr "неподдерживаемый код формата: %d" -#: access/common/reloptions.c:521 access/common/reloptions.c:532 +#: access/common/reloptions.c:519 access/common/reloptions.c:530 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "Допускаются только значения \"on\", \"off\" и \"auto\"." -#: access/common/reloptions.c:543 +#: access/common/reloptions.c:541 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "Допускаются только значения \"local\" и \"cascaded\"." -#: access/common/reloptions.c:691 +#: access/common/reloptions.c:689 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "превышен предел пользовательских типов реляционных параметров" -#: access/common/reloptions.c:1233 +#: access/common/reloptions.c:1231 #, c-format msgid "RESET must not include values for parameters" msgstr "В RESET не должно передаваться значение параметров" -#: access/common/reloptions.c:1265 +#: access/common/reloptions.c:1263 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "нераспознанное пространство имён параметров \"%s\"" -#: access/common/reloptions.c:1302 commands/variable.c:1167 +#: access/common/reloptions.c:1300 commands/variable.c:1214 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "таблицы со свойством WITH OIDS не поддерживаются" -#: access/common/reloptions.c:1470 +#: access/common/reloptions.c:1468 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "нераспознанный параметр \"%s\"" -#: access/common/reloptions.c:1582 +#: access/common/reloptions.c:1580 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "параметр \"%s\" указан неоднократно" -#: access/common/reloptions.c:1598 +#: access/common/reloptions.c:1596 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "неверное значение для логического параметра \"%s\": %s" -#: access/common/reloptions.c:1610 +#: access/common/reloptions.c:1608 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "неверное значение для целочисленного параметра \"%s\": %s" -#: access/common/reloptions.c:1616 access/common/reloptions.c:1636 +#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "значение %s вне допустимых пределов параметра \"%s\"" -#: access/common/reloptions.c:1618 +#: access/common/reloptions.c:1616 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "Допускаются значения только от \"%d\" до \"%d\"." -#: access/common/reloptions.c:1630 +#: access/common/reloptions.c:1628 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "неверное значение для численного параметра \"%s\": %s" -#: access/common/reloptions.c:1638 +#: access/common/reloptions.c:1636 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "Допускаются значения только от \"%f\" до \"%f\"." -#: access/common/reloptions.c:1660 +#: access/common/reloptions.c:1658 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "неверное значение для параметра-перечисления \"%s\": %s" -#: access/common/reloptions.c:1991 +#: access/common/reloptions.c:1989 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "задать параметры хранения для секционированной таблицы нельзя" -#: access/common/reloptions.c:1992 +#: access/common/reloptions.c:1990 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "Задайте параметры хранения для её конечных секций." -#: access/common/toast_compression.c:33 +#: access/common/toast_compression.c:31 #, c-format msgid "compression method lz4 not supported" msgstr "метод сжатия lz4 не поддерживается" -#: access/common/toast_compression.c:34 +#: access/common/toast_compression.c:32 #, c-format msgid "This functionality requires the server to be built with lz4 support." msgstr "Для этой функциональности в сервере не хватает поддержки lz4." -#: access/common/tupdesc.c:837 commands/tablecmds.c:6956 -#: commands/tablecmds.c:13027 -#, c-format -msgid "too many array dimensions" -msgstr "слишком много размерностей массива" - -#: access/common/tupdesc.c:842 parser/parse_clause.c:772 -#: parser/parse_relation.c:1913 -#, c-format -msgid "column \"%s\" cannot be declared SETOF" -msgstr "столбец \"%s\" не может быть объявлен как SETOF" - #: access/gin/ginbulk.c:44 #, c-format msgid "posting list is too long" @@ -1030,25 +1227,25 @@ msgstr "слишком длинный список указателей" #: access/gin/ginbulk.c:45 #, c-format -msgid "Reduce maintenance_work_mem." -msgstr "Уменьшите maintenance_work_mem." +msgid "Reduce \"maintenance_work_mem\"." +msgstr "Уменьшите \"maintenance_work_mem\"." -#: access/gin/ginfast.c:1040 +#: access/gin/ginfast.c:1041 #, c-format msgid "GIN pending list cannot be cleaned up during recovery." msgstr "Очередь записей GIN нельзя очистить в процессе восстановления." -#: access/gin/ginfast.c:1047 +#: access/gin/ginfast.c:1048 #, c-format msgid "\"%s\" is not a GIN index" msgstr "\"%s\" - это не индекс GIN" -#: access/gin/ginfast.c:1058 +#: access/gin/ginfast.c:1059 #, c-format msgid "cannot access temporary indexes of other sessions" msgstr "обращаться к временным индексам других сеансов нельзя" -#: access/gin/ginget.c:273 access/nbtree/nbtinsert.c:762 +#: access/gin/ginget.c:271 access/nbtree/nbtinsert.c:762 #, c-format msgid "failed to re-find tuple within index \"%s\"" msgstr "не удалось повторно найти кортеж в индексе \"%s\"" @@ -1064,14 +1261,14 @@ msgstr "" msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "Для исправления выполните REINDEX INDEX \"%s\"." -#: access/gin/ginutil.c:146 executor/execExpr.c:2169 -#: utils/adt/arrayfuncs.c:4045 utils/adt/arrayfuncs.c:6732 -#: utils/adt/rowtypes.c:984 +#: access/gin/ginutil.c:147 executor/execExpr.c:2200 +#: utils/adt/arrayfuncs.c:4016 utils/adt/arrayfuncs.c:6712 +#: utils/adt/rowtypes.c:974 #, c-format msgid "could not identify a comparison function for type %s" msgstr "не удалось найти функцию сравнения для типа %s" -#: access/gin/ginvalidate.c:92 access/gist/gistvalidate.c:93 +#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 #: access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 #, c-format msgid "" @@ -1081,7 +1278,7 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит опорную функцию %s с " "межтиповой регистрацией" -#: access/gin/ginvalidate.c:260 +#: access/gin/ginvalidate.c:258 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d or " @@ -1089,18 +1286,18 @@ msgid "" msgstr "" "в классе операторов \"%s\" метода доступа %s нет опорной функции %d или %d" -#: access/gin/ginvalidate.c:333 access/gist/gistvalidate.c:350 +#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 #: access/spgist/spgvalidate.c:387 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "номер опорной функции %d не подходит для метода доступа %s" -#: access/gist/gist.c:759 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "индекс \"%s\" содержит внутренний кортеж, отмеченный как ошибочный" -#: access/gist/gist.c:761 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 #, c-format msgid "" "This is caused by an incomplete page split at crash recovery before " @@ -1109,16 +1306,16 @@ msgstr "" "Это вызвано неполным разделением страницы при восстановлении после сбоя в " "PostgreSQL до версии 9.1." -#: access/gist/gist.c:762 access/gist/gistutil.c:801 access/gist/gistutil.c:812 -#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:227 -#: access/hash/hashutil.c:238 access/hash/hashutil.c:250 -#: access/hash/hashutil.c:271 access/nbtree/nbtpage.c:813 +#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 +#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 +#: access/hash/hashutil.c:237 access/hash/hashutil.c:249 +#: access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 #: access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "Пожалуйста, выполните REINDEX для него." -#: access/gist/gist.c:1195 +#: access/gist/gist.c:1196 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "исправление неполного разделения в индексе \"%s\" (блок: %u)" @@ -1138,19 +1335,19 @@ msgstr "" "разработчиками или попробуйте указать этот столбец в команде CREATE INDEX " "вторым." -#: access/gist/gistutil.c:798 access/hash/hashutil.c:224 +#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 #: access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "в индексе \"%s\" неожиданно оказалась нулевая страница в блоке %u" -#: access/gist/gistutil.c:809 access/hash/hashutil.c:235 -#: access/hash/hashutil.c:247 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 +#: access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "индекс \"%s\" содержит испорченную страницу в блоке %u" -#: access/gist/gistvalidate.c:203 +#: access/gist/gistvalidate.c:202 #, c-format msgid "" "operator family \"%s\" of access method %s contains unsupported ORDER BY " @@ -1159,7 +1356,7 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит неподдерживаемое " "определение ORDER BY для оператора %s" -#: access/gist/gistvalidate.c:214 +#: access/gist/gistvalidate.c:213 #, c-format msgid "" "operator family \"%s\" of access method %s contains incorrect ORDER BY " @@ -1168,32 +1365,32 @@ msgstr "" "семейство операторов \"%s\" метода доступа %s содержит некорректное " "определение ORDER BY для оператора %s" -#: access/hash/hashfunc.c:279 access/hash/hashfunc.c:333 -#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:333 +#: utils/adt/varchar.c:1008 utils/adt/varchar.c:1065 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "" "не удалось определить, какое правило сортировки использовать для хеширования " "строк" -#: access/hash/hashfunc.c:280 access/hash/hashfunc.c:334 catalog/heap.c:671 -#: catalog/heap.c:677 commands/createas.c:206 commands/createas.c:515 -#: commands/indexcmds.c:2015 commands/tablecmds.c:17527 commands/view.c:86 -#: regex/regc_pg_locale.c:243 utils/adt/formatting.c:1648 -#: utils/adt/formatting.c:1770 utils/adt/formatting.c:1893 utils/adt/like.c:191 -#: utils/adt/like_support.c:1025 utils/adt/varchar.c:739 -#: utils/adt/varchar.c:1010 utils/adt/varchar.c:1065 utils/adt/varlena.c:1518 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:334 catalog/heap.c:672 +#: catalog/heap.c:678 commands/createas.c:201 commands/createas.c:508 +#: commands/indexcmds.c:2021 commands/tablecmds.c:18178 commands/view.c:81 +#: regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 +#: utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 +#: utils/adt/like_support.c:1024 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1066 utils/adt/varlena.c:1521 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "Задайте правило сортировки явно в предложении COLLATE." -#: access/hash/hashinsert.c:86 +#: access/hash/hashinsert.c:84 #, c-format msgid "index row size %zu exceeds hash maximum %zu" msgstr "размер строки индекса (%zu) больше предельного размера хеша (%zu)" -#: access/hash/hashinsert.c:88 access/spgist/spgdoinsert.c:2006 -#: access/spgist/spgdoinsert.c:2283 access/spgist/spgutils.c:1018 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 +#: access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1031 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "Значения, не умещающиеся в страницу буфера, нельзя проиндексировать." @@ -1208,17 +1405,17 @@ msgstr "неверный номер блока переполнения: %u" msgid "out of overflow pages in hash index \"%s\"" msgstr "в хеш-индексе \"%s\" не хватает страниц переполнения" -#: access/hash/hashsearch.c:315 +#: access/hash/hashsearch.c:311 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "хеш-индексы не поддерживают сканирование всего индекса" -#: access/hash/hashutil.c:263 +#: access/hash/hashutil.c:262 #, c-format msgid "index \"%s\" is not a hash index" msgstr "индекс \"%s\" не является хеш-индексом" -#: access/hash/hashutil.c:269 +#: access/hash/hashutil.c:268 #, c-format msgid "index \"%s\" has wrong hash version" msgstr "индекс \"%s\" имеет неправильную версию хеша" @@ -1239,38 +1436,48 @@ msgid "" msgstr "" "в семействе операторов \"%s\" метода доступа %s нет межтипового оператора(ов)" -#: access/heap/heapam.c:2038 +#: access/heap/heapam.c:2206 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "вставлять кортежи в параллельном исполнителе нельзя" -#: access/heap/heapam.c:2557 +#: access/heap/heapam.c:2725 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "удалять кортежи во время параллельных операций нельзя" -#: access/heap/heapam.c:2604 +#: access/heap/heapam.c:2772 #, c-format msgid "attempted to delete invisible tuple" msgstr "попытка удаления невидимого кортежа" -#: access/heap/heapam.c:3052 access/heap/heapam.c:5921 +#: access/heap/heapam.c:3220 access/heap/heapam.c:6501 access/index/genam.c:818 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "изменять кортежи во время параллельных операций нельзя" -#: access/heap/heapam.c:3180 +#: access/heap/heapam.c:3397 #, c-format msgid "attempted to update invisible tuple" msgstr "попытка изменения невидимого кортежа" -#: access/heap/heapam.c:4569 access/heap/heapam.c:4607 -#: access/heap/heapam.c:4872 access/heap/heapam_handler.c:467 +#: access/heap/heapam.c:4908 access/heap/heapam.c:4946 +#: access/heap/heapam.c:5211 access/heap/heapam_handler.c:468 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "не удалось получить блокировку строки в таблице \"%s\"" -#: access/heap/heapam_handler.c:412 +#: access/heap/heapam.c:6314 commands/trigger.c:3340 +#: executor/nodeModifyTable.c:2376 executor/nodeModifyTable.c:2467 +#, c-format +msgid "" +"tuple to be updated was already modified by an operation triggered by the " +"current command" +msgstr "" +"кортеж, который должен быть изменён, уже модифицирован в операции, вызванной " +"текущей командой" + +#: access/heap/heapam_handler.c:413 #, c-format msgid "" "tuple to be locked was already moved to another partition due to concurrent " @@ -1279,66 +1486,67 @@ msgstr "" "кортеж, подлежащий блокировке, был перемещён в другую секцию в результате " "параллельного изменения" -#: access/heap/hio.c:536 access/heap/rewriteheap.c:659 +#: access/heap/hio.c:535 access/heap/rewriteheap.c:640 #, c-format msgid "row is too big: size %zu, maximum size %zu" msgstr "размер строки (%zu) превышает предел (%zu)" -#: access/heap/rewriteheap.c:919 +#: access/heap/rewriteheap.c:885 #, c-format msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "не удалось записать в файл \"%s\" (записано байт: %d из %d): %m" -#: access/heap/rewriteheap.c:1011 access/heap/rewriteheap.c:1128 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 #: access/transam/timeline.c:329 access/transam/timeline.c:481 -#: access/transam/xlog.c:2973 access/transam/xlog.c:3164 -#: access/transam/xlog.c:3940 access/transam/xlog.c:8746 -#: access/transam/xlogfuncs.c:702 backup/basebackup_server.c:151 -#: backup/basebackup_server.c:244 commands/dbcommands.c:495 -#: postmaster/postmaster.c:4557 postmaster/postmaster.c:5560 -#: replication/logical/origin.c:603 replication/slot.c:1804 -#: storage/file/copydir.c:157 storage/smgr/md.c:232 utils/time/snapmgr.c:1263 +#: access/transam/xlog.c:3255 access/transam/xlog.c:3446 +#: access/transam/xlog.c:4283 access/transam/xlog.c:9269 +#: access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 +#: backup/basebackup_server.c:242 commands/dbcommands.c:494 +#: postmaster/launch_backend.c:340 postmaster/postmaster.c:4114 +#: postmaster/walsummarizer.c:1212 replication/logical/origin.c:603 +#: replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 +#: utils/time/snapmgr.c:1234 #, c-format msgid "could not create file \"%s\": %m" msgstr "не удалось создать файл \"%s\": %m" -#: access/heap/rewriteheap.c:1138 +#: access/heap/rewriteheap.c:1104 #, c-format msgid "could not truncate file \"%s\" to %u: %m" msgstr "не удалось обрезать файл \"%s\" до нужного размера (%u): %m" -#: access/heap/rewriteheap.c:1156 access/transam/timeline.c:384 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 #: access/transam/timeline.c:424 access/transam/timeline.c:498 -#: access/transam/xlog.c:3023 access/transam/xlog.c:3220 -#: access/transam/xlog.c:3952 commands/dbcommands.c:507 -#: postmaster/postmaster.c:4567 postmaster/postmaster.c:4577 +#: access/transam/xlog.c:3305 access/transam/xlog.c:3502 +#: access/transam/xlog.c:4295 commands/dbcommands.c:506 +#: postmaster/launch_backend.c:351 postmaster/launch_backend.c:363 #: replication/logical/origin.c:615 replication/logical/origin.c:657 -#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1767 -#: replication/slot.c:1839 storage/file/buffile.c:545 -#: storage/file/copydir.c:197 utils/init/miscinit.c:1612 -#: utils/init/miscinit.c:1623 utils/init/miscinit.c:1631 utils/misc/guc.c:4340 -#: utils/misc/guc.c:4371 utils/misc/guc.c:5507 utils/misc/guc.c:5525 -#: utils/time/snapmgr.c:1268 utils/time/snapmgr.c:1275 +#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1788 +#: replication/slot.c:2094 storage/file/buffile.c:545 +#: storage/file/copydir.c:197 utils/init/miscinit.c:1655 +#: utils/init/miscinit.c:1666 utils/init/miscinit.c:1674 utils/misc/guc.c:4491 +#: utils/misc/guc.c:4522 utils/misc/guc.c:5675 utils/misc/guc.c:5693 +#: utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 #, c-format msgid "could not write to file \"%s\": %m" msgstr "не удалось записать в файл \"%s\": %m" -#: access/heap/vacuumlazy.c:480 +#: access/heap/vacuumlazy.c:473 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "агрессивная очистка \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:485 +#: access/heap/vacuumlazy.c:478 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "очистка \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:633 +#: access/heap/vacuumlazy.c:626 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "закончена очистка \"%s.%s.%s\": сканирований индекса: %d\n" -#: access/heap/vacuumlazy.c:644 +#: access/heap/vacuumlazy.c:637 #, c-format msgid "" "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": " @@ -1347,7 +1555,7 @@ msgstr "" "автоматическая агрессивная очистка, предотвращающая зацикливание, таблицы " "\"%s.%s.%s\": сканирований индекса: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:639 #, c-format msgid "" "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: " @@ -1356,27 +1564,27 @@ msgstr "" "автоматическая очистка, предотвращающая зацикливание, таблицы \"%s.%s.%s\": " "сканирований индекса: %d\n" -#: access/heap/vacuumlazy.c:651 +#: access/heap/vacuumlazy.c:644 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "" "автоматическая агрессивная очистка таблицы \"%s.%s.%s\": сканирований " "индекса: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:646 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "" "автоматическая очистка таблицы \"%s.%s.%s\": сканирований индекса: %d\n" -#: access/heap/vacuumlazy.c:660 +#: access/heap/vacuumlazy.c:653 #, c-format msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" msgstr "" "страниц удалено: %u, осталось: %u, просканировано: %u (%.2f%% от общего " "числа)\n" -#: access/heap/vacuumlazy.c:667 +#: access/heap/vacuumlazy.c:660 #, c-format msgid "" "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" @@ -1384,7 +1592,7 @@ msgstr "" "версий строк: удалено: %lld, осталось: %lld, «мёртвых», но ещё не подлежащих " "удалению: %lld\n" -#: access/heap/vacuumlazy.c:673 +#: access/heap/vacuumlazy.c:666 #, c-format msgid "" "tuples missed: %lld dead from %u pages not removed due to cleanup lock " @@ -1393,43 +1601,43 @@ msgstr "" "из-за конфликта блокировки очистки пропущено версий строк: %lld, на " "страницах: %u\n" -#: access/heap/vacuumlazy.c:679 +#: access/heap/vacuumlazy.c:672 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "" "XID отсечки удаления: %u, на момент завершения операции он имел возраст: %d " "XID\n" -#: access/heap/vacuumlazy.c:686 +#: access/heap/vacuumlazy.c:679 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "" "новое значение relfrozenxid: %u, оно продвинулось вперёд от предыдущего " "значения на %d XID\n" -#: access/heap/vacuumlazy.c:694 +#: access/heap/vacuumlazy.c:687 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "" "новое значение relminmxid: %u, оно продвинулось вперёд от предыдущего " "значения на %d MXID\n" -#: access/heap/vacuumlazy.c:697 +#: access/heap/vacuumlazy.c:690 #, c-format msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" msgstr "" "замораживание: на страницах таблицы (%u, %.2f%% от общего числа) заморожено " "кортежей: %lld\n" -#: access/heap/vacuumlazy.c:705 +#: access/heap/vacuumlazy.c:698 msgid "index scan not needed: " msgstr "сканирование индекса не требуется: " -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:700 msgid "index scan needed: " msgstr "сканирование индекса требуется: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:702 #, c-format msgid "" "%u pages from table (%.2f%% of total) had %lld dead item identifiers " @@ -1438,22 +1646,22 @@ msgstr "" "на страницах таблицы (%u, %.2f%% от общего числа) удалено мёртвых " "идентификаторов элементов: %lld\n" -#: access/heap/vacuumlazy.c:714 +#: access/heap/vacuumlazy.c:707 msgid "index scan bypassed: " msgstr "сканирование индекса пропущено: " -#: access/heap/vacuumlazy.c:716 +#: access/heap/vacuumlazy.c:709 msgid "index scan bypassed by failsafe: " msgstr "сканирование индекса пропущено из-за защиты: " -#: access/heap/vacuumlazy.c:718 +#: access/heap/vacuumlazy.c:711 #, c-format msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" msgstr "" "на страницах таблицы (%u, %.2f%% от общего числа) находится мёртвых " "идентификаторов элементов: %lld\n" -#: access/heap/vacuumlazy.c:733 +#: access/heap/vacuumlazy.c:726 #, c-format msgid "" "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u " @@ -1462,43 +1670,43 @@ msgstr "" "индекс \"%s\": всего страниц: %u, сейчас удалено: %u, удалено на данный " "момент: %u, свободно: %u\n" -#: access/heap/vacuumlazy.c:745 commands/analyze.c:796 +#: access/heap/vacuumlazy.c:738 commands/analyze.c:794 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "время ввода/вывода: чтение: %.3f мс, запись: %.3f мс\n" -#: access/heap/vacuumlazy.c:755 commands/analyze.c:799 +#: access/heap/vacuumlazy.c:748 commands/analyze.c:797 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "" "средняя скорость чтения: %.3f МБ/с, средняя скорость записи: %.3f МБ/с\n" -#: access/heap/vacuumlazy.c:758 commands/analyze.c:801 +#: access/heap/vacuumlazy.c:751 commands/analyze.c:799 #, c-format msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" msgstr "" "использование буфера: попаданий: %lld, промахов: %lld, «грязных» записей: " "%lld\n" -#: access/heap/vacuumlazy.c:763 +#: access/heap/vacuumlazy.c:756 #, c-format msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" msgstr "" "использование WAL: записей: %lld, полных образов страниц: %lld, байт: %llu\n" -#: access/heap/vacuumlazy.c:767 commands/analyze.c:805 +#: access/heap/vacuumlazy.c:760 commands/analyze.c:803 #, c-format msgid "system usage: %s" msgstr "нагрузка системы: %s" -#: access/heap/vacuumlazy.c:2476 +#: access/heap/vacuumlazy.c:2170 #, c-format msgid "table \"%s\": removed %lld dead item identifiers in %u pages" msgstr "" "таблица \"%s\": удалено мёртвых идентификаторов элементов: %lld, на " "страницах: %u" -#: access/heap/vacuumlazy.c:2636 +#: access/heap/vacuumlazy.c:2324 #, c-format msgid "" "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after " @@ -1507,12 +1715,12 @@ msgstr "" "несущественная операция обслуживания таблицы \"%s.%s.%s\" пропускается в " "качестве меры защиты после %d сканирований индекса" -#: access/heap/vacuumlazy.c:2639 +#: access/heap/vacuumlazy.c:2327 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "Значение relfrozenxid или relminmxid таблицы слишком далеко в прошлом." -#: access/heap/vacuumlazy.c:2640 +#: access/heap/vacuumlazy.c:2328 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or " @@ -1525,23 +1733,23 @@ msgstr "" "Также можно рассмотреть другие способы обеспечения производительности " "VACUUM, соответствующей скорости выделения идентификаторов транзакций." -#: access/heap/vacuumlazy.c:2885 +#: access/heap/vacuumlazy.c:2590 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "\"%s\": остановка усечения из-за конфликтующего запроса блокировки" -#: access/heap/vacuumlazy.c:2955 +#: access/heap/vacuumlazy.c:2660 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "таблица \"%s\": усечение (было страниц: %u, стало: %u)" -#: access/heap/vacuumlazy.c:3017 +#: access/heap/vacuumlazy.c:2722 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "" "таблица \"%s\": приостановка усечения из-за конфликтующего запроса блокировки" -#: access/heap/vacuumlazy.c:3177 +#: access/heap/vacuumlazy.c:2841 #, c-format msgid "" "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary " @@ -1550,47 +1758,47 @@ msgstr "" "отключение параллельного режима очистки \"%s\" --- создавать временные " "таблицы в параллельном режиме нельзя" -#: access/heap/vacuumlazy.c:3393 +#: access/heap/vacuumlazy.c:3108 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "при сканировании блока %u (смещение %u) отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3396 +#: access/heap/vacuumlazy.c:3111 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "при сканировании блока %u отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3400 +#: access/heap/vacuumlazy.c:3115 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "при сканировании отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3408 +#: access/heap/vacuumlazy.c:3123 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "при очистке блока %u (смещение %u) отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3411 +#: access/heap/vacuumlazy.c:3126 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "при очистке блока %u отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3415 +#: access/heap/vacuumlazy.c:3130 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "при очистке отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3420 commands/vacuumparallel.c:1074 +#: access/heap/vacuumlazy.c:3135 commands/vacuumparallel.c:1112 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "при очистке индекса \"%s\" отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3425 commands/vacuumparallel.c:1080 +#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1118 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "при уборке индекса \"%s\" отношения \"%s.%s\"" -#: access/heap/vacuumlazy.c:3431 +#: access/heap/vacuumlazy.c:3146 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "при усечении отношения \"%s.%s\" до %u блок." @@ -1605,24 +1813,24 @@ msgstr "метод доступа \"%s\" имеет не тип %s" msgid "index access method \"%s\" does not have a handler" msgstr "для метода доступа индекса \"%s\" не задан обработчик" -#: access/index/genam.c:490 +#: access/index/genam.c:489 #, c-format msgid "transaction aborted during system catalog scan" msgstr "транзакция прервана во время сканирования системного каталога" -#: access/index/genam.c:658 access/index/indexam.c:87 +#: access/index/genam.c:657 access/index/indexam.c:82 #, c-format msgid "cannot access index \"%s\" while it is being reindexed" msgstr "индекс \"%s\" перестраивается, обращаться к нему нельзя" -#: access/index/indexam.c:208 catalog/objectaddress.c:1394 -#: commands/indexcmds.c:2843 commands/tablecmds.c:272 commands/tablecmds.c:296 -#: commands/tablecmds.c:17222 commands/tablecmds.c:19000 +#: access/index/indexam.c:203 catalog/objectaddress.c:1356 +#: commands/indexcmds.c:2851 commands/tablecmds.c:281 commands/tablecmds.c:305 +#: commands/tablecmds.c:17873 commands/tablecmds.c:19762 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\" - это не индекс" -#: access/index/indexam.c:1021 +#: access/index/indexam.c:1028 #, c-format msgid "operator class %s has no options" msgstr "у класса операторов %s нет параметров" @@ -1643,7 +1851,7 @@ msgid "This may be because of a non-immutable index expression." msgstr "Возможно, это вызвано переменной природой индексного выражения." #: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 -#: parser/parse_utilcmd.c:2326 +#: parser/parse_utilcmd.c:2323 #, c-format msgid "index \"%s\" is not a btree" msgstr "индекс \"%s\" не является b-деревом" @@ -1657,12 +1865,12 @@ msgstr "" "несовпадение версии в индексе \"%s\": версия файла: %d, версия кода: %d, " "минимальная поддерживаемая версия: %d" -#: access/nbtree/nbtpage.c:1866 +#: access/nbtree/nbtpage.c:1861 #, c-format msgid "index \"%s\" contains a half-dead internal page" msgstr "индекс \"%s\" содержит полумёртвую внутреннюю страницу" -#: access/nbtree/nbtpage.c:1868 +#: access/nbtree/nbtpage.c:1863 #, c-format msgid "" "This can be caused by an interrupted VACUUM in version 9.3 or older, before " @@ -1671,7 +1879,7 @@ msgstr "" "Причиной тому могло быть прерывание операции VACUUM в версии 9.3 или старее, " "до обновления. Этот индекс нужно перестроить (REINDEX)." -#: access/nbtree/nbtutils.c:2677 +#: access/nbtree/nbtutils.c:5108 #, c-format msgid "" "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" @@ -1679,12 +1887,12 @@ msgstr "" "размер строки индекса (%zu) больше предельного для btree версии %u размера " "(%zu) (индекс \"%s\")" -#: access/nbtree/nbtutils.c:2683 +#: access/nbtree/nbtutils.c:5114 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "Строка индекса ссылается на кортеж (%u,%u) в отношении \"%s\"." -#: access/nbtree/nbtutils.c:2687 +#: access/nbtree/nbtutils.c:5118 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1705,7 +1913,13 @@ msgstr "" "в семействе операторов \"%s\" метода доступа %s нет опорной функции для " "типов %s и %s" -#: access/spgist/spgutils.c:243 +#: access/sequence/sequence.c:75 access/table/table.c:145 +#: optimizer/util/plancat.c:144 +#, c-format +msgid "cannot open relation \"%s\"" +msgstr "открыть отношение \"%s\" нельзя" + +#: access/spgist/spgutils.c:245 #, c-format msgid "" "compress method must be defined when leaf type is different from input type" @@ -1713,7 +1927,7 @@ msgstr "" "метод сжатия должен быть определён, когда тип листьев отличается от входного " "типа" -#: access/spgist/spgutils.c:1015 +#: access/spgist/spgutils.c:1028 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "внутренний размер кортежа SP-GiST (%zu) превышает максимум (%zu)" @@ -1734,75 +1948,71 @@ msgstr "" "в семействе операторов \"%s\" метода доступа %s нет опорной функции %d для " "типа %s" -#: access/table/table.c:145 optimizer/util/plancat.c:145 -#, c-format -msgid "cannot open relation \"%s\"" -msgstr "открыть отношение \"%s\" нельзя" - -#: access/table/tableam.c:265 +#: access/table/tableam.c:255 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "идентификатор кортежа (%u, %u) недопустим для отношения \"%s\"" -#: access/table/tableamapi.c:116 +#: access/table/tableamapi.c:109 #, c-format -msgid "%s cannot be empty." -msgstr "Значение %s не может быть пустым." +msgid "\"%s\" cannot be empty." +msgstr "Значение \"%s\" не может быть пустым." # well-spelled: симв -#: access/table/tableamapi.c:123 access/transam/xlogrecovery.c:4808 +#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4859 #, c-format -msgid "%s is too long (maximum %d characters)." -msgstr "Длина %s превышает предел (%d симв.)." +msgid "\"%s\" is too long (maximum %d characters)." +msgstr "Длина \"%s\" превышает предел (%d симв.)." -#: access/table/tableamapi.c:146 +#: access/table/tableamapi.c:139 #, c-format msgid "table access method \"%s\" does not exist" msgstr "табличный метод доступа \"%s\" не существует" -#: access/table/tableamapi.c:151 +#: access/table/tableamapi.c:144 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "Табличный метод доступа \"%s\" не существует." -#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:152 +#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:151 #, c-format msgid "sample percentage must be between 0 and 100" msgstr "процент выборки должен задаваться числом от 0 до 100" -#: access/transam/commit_ts.c:279 +#: access/transam/commit_ts.c:287 #, c-format msgid "cannot retrieve commit timestamp for transaction %u" msgstr "не удалось получить метку времени фиксации транзакции %u" -#: access/transam/commit_ts.c:377 +#: access/transam/commit_ts.c:385 #, c-format msgid "could not get commit timestamp data" msgstr "не удалось получить отметку времени фиксации" -#: access/transam/commit_ts.c:379 +#: access/transam/commit_ts.c:387 #, c-format msgid "" "Make sure the configuration parameter \"%s\" is set on the primary server." msgstr "" "Убедитесь, что в конфигурации ведущего сервера установлен параметр \"%s\"." -#: access/transam/commit_ts.c:381 +#: access/transam/commit_ts.c:389 #, c-format msgid "Make sure the configuration parameter \"%s\" is set." msgstr "Убедитесь, что в конфигурации установлен параметр \"%s\"." -#: access/transam/multixact.c:1023 +#: access/transam/multixact.c:1091 #, c-format msgid "" -"database is not accepting commands that generate new MultiXactIds to avoid " +"database is not accepting commands that assign new MultiXactIds to avoid " "wraparound data loss in database \"%s\"" msgstr "" -"база данных не принимает команды, создающие новые MultiXactId, во избежание " -"потери данных из-за зацикливания в базе данных \"%s\"" +"база данных не принимает команды, назначающие новые MultiXactId, во " +"избежание потери данных из-за зацикливания в базе данных \"%s\"" -#: access/transam/multixact.c:1025 access/transam/multixact.c:1032 -#: access/transam/multixact.c:1056 access/transam/multixact.c:1065 +#: access/transam/multixact.c:1093 access/transam/multixact.c:1100 +#: access/transam/multixact.c:1124 access/transam/multixact.c:1133 +#: access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" @@ -1813,16 +2023,16 @@ msgstr "" "Возможно, вам также придётся зафиксировать или откатить старые " "подготовленные транзакции и удалить неиспользуемые слоты репликации." -#: access/transam/multixact.c:1030 +#: access/transam/multixact.c:1098 #, c-format msgid "" -"database is not accepting commands that generate new MultiXactIds to avoid " +"database is not accepting commands that assign new MultiXactIds to avoid " "wraparound data loss in database with OID %u" msgstr "" -"база данных не принимает команды, создающие новые MultiXactId, во избежание " -"потери данных из-за зацикливания в базе данных с OID %u" +"база данных не принимает команды, назначающие новые MultiXactId, во " +"избежание потери данных из-за зацикливания в базе данных с OID %u" -#: access/transam/multixact.c:1051 access/transam/multixact.c:2333 +#: access/transam/multixact.c:1119 access/transam/multixact.c:2474 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "" @@ -1837,7 +2047,7 @@ msgstr[2] "" "база данных \"%s\" должна быть очищена, прежде чем будут использованы " "оставшиеся MultiXactId (%u)" -#: access/transam/multixact.c:1060 access/transam/multixact.c:2342 +#: access/transam/multixact.c:1128 access/transam/multixact.c:2483 #, c-format msgid "" "database with OID %u must be vacuumed before %u more MultiXactId is used" @@ -1853,12 +2063,12 @@ msgstr[2] "" "база данных с OID %u должна быть очищена, прежде чем будут использованы " "оставшиеся MultiXactId (%u)" -#: access/transam/multixact.c:1121 +#: access/transam/multixact.c:1189 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "слишком много членов мультитранзакции" -#: access/transam/multixact.c:1122 +#: access/transam/multixact.c:1190 #, c-format msgid "" "This command would create a multixact with %u members, but the remaining " @@ -1876,17 +2086,17 @@ msgstr[2] "" "Мультитранзакция, создаваемая этой командой, должна включать членов: %u, но " "оставшегося места хватает только для %u." -#: access/transam/multixact.c:1127 +#: access/transam/multixact.c:1195 #, c-format msgid "" "Execute a database-wide VACUUM in database with OID %u with reduced " -"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age " -"settings." +"\"vacuum_multixact_freeze_min_age\" and " +"\"vacuum_multixact_freeze_table_age\" settings." msgstr "" "Выполните очистку (VACUUM) всей базы данных с OID %u, уменьшив значения " -"vacuum_multixact_freeze_min_age и vacuum_multixact_freeze_table_age." +"\"vacuum_multixact_freeze_min_age\" и \"vacuum_multixact_freeze_table_age\"." -#: access/transam/multixact.c:1158 +#: access/transam/multixact.c:1226 #, c-format msgid "" "database with OID %u must be vacuumed before %d more multixact member is used" @@ -1903,41 +2113,40 @@ msgstr[2] "" "база данных с OID %u должна быть очищена, пока не использованы оставшиеся " "члены мультитранзакций (%d)" -#: access/transam/multixact.c:1163 +#: access/transam/multixact.c:1231 #, c-format msgid "" "Execute a database-wide VACUUM in that database with reduced " -"vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age " -"settings." +"\"vacuum_multixact_freeze_min_age\" and " +"\"vacuum_multixact_freeze_table_age\" settings." msgstr "" "Выполните очистку (VACUUM) всей этой базы данных, уменьшив значения " -"vacuum_multixact_freeze_min_age и vacuum_multixact_freeze_table_age." +"\"vacuum_multixact_freeze_min_age\" и \"vacuum_multixact_freeze_table_age\"." -#: access/transam/multixact.c:1302 +#: access/transam/multixact.c:1371 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "MultiXactId %u прекратил существование: видимо, произошло зацикливание" -#: access/transam/multixact.c:1308 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "MultiXactId %u ещё не был создан: видимо, произошло зацикливание" -#: access/transam/multixact.c:2338 access/transam/multixact.c:2347 -#: access/transam/varsup.c:151 access/transam/varsup.c:158 -#: access/transam/varsup.c:466 access/transam/varsup.c:473 +#: access/transam/multixact.c:2479 access/transam/multixact.c:2488 #, c-format msgid "" -"To avoid a database shutdown, execute a database-wide VACUUM in that " -"database.\n" +"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in " +"that database.\n" "You might also need to commit or roll back old prepared transactions, or " "drop stale replication slots." msgstr "" -"Во избежание отключения базы данных выполните очистку (VACUUM) всей базы.\n" +"Во избежание сбоев при назначении MultiXactId, выполните очистку (VACUUM) " +"всей базы.\n" "Возможно, вам также придётся зафиксировать или откатить старые " "подготовленные транзакции и удалить неиспользуемые слоты репликации." -#: access/transam/multixact.c:2622 +#: access/transam/multixact.c:2767 #, c-format msgid "" "MultiXact member wraparound protections are disabled because oldest " @@ -1946,12 +2155,12 @@ msgstr "" "Защита от зацикливания членов мультитранзакций отключена, так как старейшая " "отмеченная мультитранзакция %u не найдена на диске" -#: access/transam/multixact.c:2644 +#: access/transam/multixact.c:2789 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "Защита от зацикливания мультитранзакций сейчас включена" -#: access/transam/multixact.c:3027 +#: access/transam/multixact.c:3180 #, c-format msgid "" "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" @@ -1959,7 +2168,7 @@ msgstr "" "старейшая мультитранзакция %u не найдена, новейшая мультитранзакция: %u, " "усечение пропускается" -#: access/transam/multixact.c:3045 +#: access/transam/multixact.c:3198 #, c-format msgid "" "cannot truncate up to MultiXact %u because it does not exist on disk, " @@ -1968,167 +2177,172 @@ msgstr "" "выполнить усечение до мультитранзакции %u нельзя ввиду её отсутствия на " "диске, усечение пропускается" -#: access/transam/multixact.c:3359 +#: access/transam/multixact.c:3517 #, c-format msgid "invalid MultiXactId: %u" msgstr "неверный MultiXactId: %u" -#: access/transam/parallel.c:729 access/transam/parallel.c:848 +#: access/transam/parallel.c:748 access/transam/parallel.c:867 #, c-format msgid "parallel worker failed to initialize" msgstr "не удалось инициализировать параллельный исполнитель" -#: access/transam/parallel.c:730 access/transam/parallel.c:849 +#: access/transam/parallel.c:749 access/transam/parallel.c:868 #, c-format msgid "More details may be available in the server log." msgstr "Дополнительная информация может быть в журнале сервера." -#: access/transam/parallel.c:910 +#: access/transam/parallel.c:929 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "postmaster завершился в процессе параллельной транзакции" -#: access/transam/parallel.c:1097 +#: access/transam/parallel.c:1116 #, c-format msgid "lost connection to parallel worker" msgstr "потеряно подключение к параллельному исполнителю" -#: access/transam/parallel.c:1163 access/transam/parallel.c:1165 +#: access/transam/parallel.c:1172 access/transam/parallel.c:1174 msgid "parallel worker" msgstr "параллельный исполнитель" -#: access/transam/parallel.c:1319 replication/logical/applyparallelworker.c:893 +#: access/transam/parallel.c:1344 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "не удалось отобразить динамический сегмент разделяемой памяти" -#: access/transam/parallel.c:1324 replication/logical/applyparallelworker.c:899 +#: access/transam/parallel.c:1349 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "неверное магическое число в динамическом сегменте разделяемой памяти" -#: access/transam/rmgr.c:84 +#: access/transam/rmgr.c:93 #, c-format msgid "resource manager with ID %d not registered" msgstr "менеджер ресурсов с ID %d не зарегистрирован" -#: access/transam/rmgr.c:85 +#: access/transam/rmgr.c:94 #, c-format msgid "" "Include the extension module that implements this resource manager in " -"shared_preload_libraries." +"\"shared_preload_libraries\"." msgstr "" -"Включите в shared_preload_libraries модуль расширения, в котором реализован " -"данный менеджер ресурсов." +"Включите в \"shared_preload_libraries\" модуль расширения, в котором " +"реализован данный менеджер ресурсов." -#: access/transam/rmgr.c:101 +#: access/transam/rmgr.c:110 #, c-format msgid "custom resource manager name is invalid" msgstr "неверное имя пользовательского менеджера ресурсов" -#: access/transam/rmgr.c:102 +#: access/transam/rmgr.c:111 #, c-format msgid "Provide a non-empty name for the custom resource manager." msgstr "Задайте непустое имя для менеджера ресурсов." -#: access/transam/rmgr.c:105 +#: access/transam/rmgr.c:114 #, c-format msgid "custom resource manager ID %d is out of range" msgstr "идентификатор пользовательского менеджера ресурсов %d вне диапазона" -#: access/transam/rmgr.c:106 +#: access/transam/rmgr.c:115 #, c-format msgid "Provide a custom resource manager ID between %d and %d." msgstr "Задайте идентификатор менеджера ресурсов от %d до %d." -#: access/transam/rmgr.c:111 access/transam/rmgr.c:116 -#: access/transam/rmgr.c:128 +#: access/transam/rmgr.c:120 access/transam/rmgr.c:125 +#: access/transam/rmgr.c:137 #, c-format msgid "failed to register custom resource manager \"%s\" with ID %d" msgstr "" "не удалось зарегистрировать пользовательский менеджер ресурсов \"%s\" с ID %d" -#: access/transam/rmgr.c:112 +#: access/transam/rmgr.c:121 #, c-format msgid "" "Custom resource manager must be registered while initializing modules in " -"shared_preload_libraries." +"\"shared_preload_libraries\"." msgstr "" "Пользовательский менеджер ресурсов должен быть зарегистрирован при " -"инициализации модулей в shared_preload_libraries." +"инициализации модулей в \"shared_preload_libraries\"." -#: access/transam/rmgr.c:117 +#: access/transam/rmgr.c:126 #, c-format msgid "Custom resource manager \"%s\" already registered with the same ID." msgstr "" "Пользовательский менеджер ресурсов \"%s\" уже зарегистрирован с тем же ID." -#: access/transam/rmgr.c:129 +#: access/transam/rmgr.c:138 #, c-format msgid "Existing resource manager with ID %d has the same name." msgstr "Существующий менеджер ресурсов с ID %d имеет то же имя." -#: access/transam/rmgr.c:135 +#: access/transam/rmgr.c:144 #, c-format msgid "registered custom resource manager \"%s\" with ID %d" msgstr "зарегистрирован пользовательский менеджер ресурсов \"%s\" с ID %d" -#: access/transam/slru.c:714 +#: access/transam/slru.c:361 +#, c-format +msgid "\"%s\" must be a multiple of %d" +msgstr "значение \"%s\" должно быть кратно %d" + +#: access/transam/slru.c:830 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "файл \"%s\" не существует, считается нулевым" -#: access/transam/slru.c:946 access/transam/slru.c:952 -#: access/transam/slru.c:960 access/transam/slru.c:965 -#: access/transam/slru.c:972 access/transam/slru.c:977 -#: access/transam/slru.c:984 access/transam/slru.c:991 +#: access/transam/slru.c:1059 access/transam/slru.c:1065 +#: access/transam/slru.c:1073 access/transam/slru.c:1078 +#: access/transam/slru.c:1085 access/transam/slru.c:1090 +#: access/transam/slru.c:1097 access/transam/slru.c:1104 #, c-format msgid "could not access status of transaction %u" msgstr "не удалось получить состояние транзакции %u" -#: access/transam/slru.c:947 +#: access/transam/slru.c:1060 #, c-format msgid "Could not open file \"%s\": %m." msgstr "Не удалось открыть файл \"%s\": %m." -#: access/transam/slru.c:953 +#: access/transam/slru.c:1066 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "Не удалось переместиться в файле \"%s\" к смещению %d: %m." -#: access/transam/slru.c:961 +#: access/transam/slru.c:1074 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "Не удалось прочитать файл \"%s\" (по смещению %d): %m." -#: access/transam/slru.c:966 +#: access/transam/slru.c:1079 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "" "Не удалось прочитать файл \"%s\" (по смещению %d): прочитаны не все байты." -#: access/transam/slru.c:973 +#: access/transam/slru.c:1086 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "Не удалось записать в файл \"%s\" (по смещению %d): %m." -#: access/transam/slru.c:978 +#: access/transam/slru.c:1091 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "" "Не удалось записать в файл \"%s\" (по смещению %d): записаны не все байты." -#: access/transam/slru.c:985 +#: access/transam/slru.c:1098 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "Не удалось синхронизировать с ФС файл \"%s\": %m." -#: access/transam/slru.c:992 +#: access/transam/slru.c:1105 #, c-format msgid "Could not close file \"%s\": %m." msgstr "Не удалось закрыть файл \"%s\": %m." -#: access/transam/slru.c:1253 +#: access/transam/slru.c:1431 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "не удалось очистить каталог \"%s\": видимо, произошло зацикливание" @@ -2174,59 +2388,60 @@ msgstr "" msgid "requested timeline %u is not in this server's history" msgstr "в истории сервера нет запрошенной линии времени %u" -#: access/transam/twophase.c:386 +#: access/transam/twophase.c:368 #, c-format msgid "transaction identifier \"%s\" is too long" msgstr "идентификатор транзакции \"%s\" слишком длинный" -#: access/transam/twophase.c:393 +#: access/transam/twophase.c:375 #, c-format msgid "prepared transactions are disabled" msgstr "подготовленные транзакции отключены" -#: access/transam/twophase.c:394 +#: access/transam/twophase.c:376 #, c-format -msgid "Set max_prepared_transactions to a nonzero value." -msgstr "Установите ненулевое значение параметра max_prepared_transactions." +msgid "Set \"max_prepared_transactions\" to a nonzero value." +msgstr "Установите ненулевое значение параметра \"max_prepared_transactions\"." -#: access/transam/twophase.c:413 +#: access/transam/twophase.c:395 #, c-format msgid "transaction identifier \"%s\" is already in use" msgstr "идентификатор транзакции \"%s\" уже используется" -#: access/transam/twophase.c:422 access/transam/twophase.c:2517 +#: access/transam/twophase.c:404 access/transam/twophase.c:2531 #, c-format msgid "maximum number of prepared transactions reached" msgstr "достигнут предел числа подготовленных транзакций" -#: access/transam/twophase.c:423 access/transam/twophase.c:2518 +#: access/transam/twophase.c:405 access/transam/twophase.c:2532 #, c-format -msgid "Increase max_prepared_transactions (currently %d)." -msgstr "Увеличьте параметр max_prepared_transactions (текущее значение %d)." +msgid "Increase \"max_prepared_transactions\" (currently %d)." +msgstr "" +"Увеличьте параметр \"max_prepared_transactions\" (текущее значение %d)." -#: access/transam/twophase.c:599 +#: access/transam/twophase.c:580 #, c-format msgid "prepared transaction with identifier \"%s\" is busy" msgstr "подготовленная транзакция с идентификатором \"%s\" занята" -#: access/transam/twophase.c:605 +#: access/transam/twophase.c:586 #, c-format msgid "permission denied to finish prepared transaction" -msgstr "нет доступа для завершения подготовленной транзакции" +msgstr "нет прав для завершения подготовленной транзакции" -#: access/transam/twophase.c:606 +#: access/transam/twophase.c:587 #, c-format msgid "Must be superuser or the user that prepared the transaction." msgstr "" "Это разрешено только суперпользователю и пользователю, подготовившему " "транзакцию." -#: access/transam/twophase.c:617 +#: access/transam/twophase.c:598 #, c-format msgid "prepared transaction belongs to another database" msgstr "подготовленная транзакция относится к другой базе данных" -#: access/transam/twophase.c:618 +#: access/transam/twophase.c:599 #, c-format msgid "" "Connect to the database where the transaction was prepared to finish it." @@ -2235,17 +2450,17 @@ msgstr "" "подготовлена." # [SM]: TO REVIEW -#: access/transam/twophase.c:633 +#: access/transam/twophase.c:614 #, c-format msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "подготовленной транзакции с идентификатором \"%s\" нет" -#: access/transam/twophase.c:1168 +#: access/transam/twophase.c:1174 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "превышен предельный размер файла состояния 2PC" -#: access/transam/twophase.c:1323 +#: access/transam/twophase.c:1329 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" @@ -2253,62 +2468,63 @@ msgstr[0] "некорректный размер файла \"%s\": %lld Б" msgstr[1] "некорректный размер файла \"%s\": %lld Б" msgstr[2] "некорректный размер файла \"%s\": %lld Б" -#: access/transam/twophase.c:1332 +#: access/transam/twophase.c:1338 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "некорректное выравнивание смещения CRC для файла \"%s\"" -#: access/transam/twophase.c:1350 +#: access/transam/twophase.c:1356 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %lld)" -#: access/transam/twophase.c:1365 +#: access/transam/twophase.c:1371 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "в файле \"%s\" содержится неверная сигнатура" -#: access/transam/twophase.c:1371 +#: access/transam/twophase.c:1377 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "в файле \"%s\" содержится неверный размер" -#: access/transam/twophase.c:1383 +#: access/transam/twophase.c:1389 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "" "вычисленная контрольная сумма (CRC) не соответствует значению, сохранённому " "в файле \"%s\"" -#: access/transam/twophase.c:1413 access/transam/xlogrecovery.c:590 -#: replication/logical/logical.c:209 replication/walsender.c:687 +#: access/transam/twophase.c:1419 access/transam/xlogrecovery.c:565 +#: postmaster/walsummarizer.c:936 replication/logical/logical.c:211 +#: replication/walsender.c:836 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "Не удалось разместить обработчик журнала транзакций." -#: access/transam/twophase.c:1423 +#: access/transam/twophase.c:1429 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "не удалось прочитать состояние 2PC из WAL в позиции %X/%X: %s" -#: access/transam/twophase.c:1428 +#: access/transam/twophase.c:1434 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "не удалось прочитать состояние 2PC из WAL в позиции %X/%X" -#: access/transam/twophase.c:1436 +#: access/transam/twophase.c:1442 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "" "ожидаемые данные состояния двухфазной фиксации отсутствуют в WAL в позиции " "%X/%X" -#: access/transam/twophase.c:1732 +#: access/transam/twophase.c:1745 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "пересоздать файл \"%s\" не удалось: %m" -#: access/transam/twophase.c:1859 +#: access/transam/twophase.c:1872 #, c-format msgid "" "%u two-phase state file was written for a long-running prepared transaction" @@ -2321,47 +2537,47 @@ msgstr[1] "" msgstr[2] "" "для длительных подготовленных транзакций записано файлов состояния 2PC: %u" -#: access/transam/twophase.c:2093 +#: access/transam/twophase.c:2107 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "восстановление подготовленной транзакции %u из разделяемой памяти" -#: access/transam/twophase.c:2186 +#: access/transam/twophase.c:2200 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "удаление устаревшего файла состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2193 +#: access/transam/twophase.c:2207 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "удаление из памяти устаревшего состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2206 +#: access/transam/twophase.c:2220 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "удаление файла будущего состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2213 +#: access/transam/twophase.c:2227 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "удаление из памяти будущего состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2238 +#: access/transam/twophase.c:2252 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "испорчен файл состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2243 +#: access/transam/twophase.c:2257 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "испорчено состояние 2PC в памяти для транзакции %u" -#: access/transam/twophase.c:2500 +#: access/transam/twophase.c:2514 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "не удалось восстановить файл состояния 2PC для транзакции %u" -#: access/transam/twophase.c:2502 +#: access/transam/twophase.c:2516 #, c-format msgid "" "Two-phase state file has been found in WAL record %X/%X, but this " @@ -2370,172 +2586,194 @@ msgstr "" "Для WAL-записи %X/%X найден файл состояния двухфазной фиксации, но эта " "транзакция уже была восстановлена с диска." -#: access/transam/twophase.c:2510 jit/jit.c:205 utils/fmgr/dfmgr.c:209 -#: utils/fmgr/dfmgr.c:415 +#: access/transam/twophase.c:2524 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 #, c-format msgid "could not access file \"%s\": %m" -msgstr "нет доступа к файлу \"%s\": %m" +msgstr "ошибка при обращении к файлу \"%s\": %m" -#: access/transam/varsup.c:129 +#: access/transam/varsup.c:156 #, c-format msgid "" -"database is not accepting commands to avoid wraparound data loss in database " +"database is not accepting commands that assign new transaction IDs to avoid " +"wraparound data loss in database \"%s\"" +msgstr "" +"база данных не принимает команды, назначающие новые идентификаторы " +"транзакций, во избежание потери данных из-за зацикливания в базе данных " "\"%s\"" + +#: access/transam/varsup.c:163 +#, c-format +msgid "" +"database is not accepting commands that assign new transaction IDs to avoid " +"wraparound data loss in database with OID %u" +msgstr "" +"база данных не принимает команды, назначающие новые идентификаторы " +"транзакций, во избежание потери данных из-за зацикливания в базе данных с " +"OID %u" + +#: access/transam/varsup.c:175 access/transam/varsup.c:490 +#, c-format +msgid "database \"%s\" must be vacuumed within %u transactions" msgstr "" -"база данных не принимает команды во избежание потери данных из-за " -"зацикливания транзакций в базе данных \"%s\"" +"база данных \"%s\" должна быть очищена (предельное число транзакций: %u)" -#: access/transam/varsup.c:131 access/transam/varsup.c:138 +#: access/transam/varsup.c:178 #, c-format msgid "" -"Stop the postmaster and vacuum that database in single-user mode.\n" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM " +"in that database.\n" "You might also need to commit or roll back old prepared transactions, or " "drop stale replication slots." msgstr "" -"Остановите управляющий процесс (postmaster) и выполните очистку (VACUUM) " -"базы данных в монопольном режиме.\n" +"Во избежание сбоев при назначении идентификаторов транзакций, выполните " +"очистку (VACUUM) всей базы.\n" "Возможно, вам также придётся зафиксировать или откатить старые " "подготовленные транзакции и удалить неиспользуемые слоты репликации." -#: access/transam/varsup.c:136 +#: access/transam/varsup.c:182 access/transam/varsup.c:497 #, c-format -msgid "" -"database is not accepting commands to avoid wraparound data loss in database " -"with OID %u" +msgid "database with OID %u must be vacuumed within %u transactions" msgstr "" -"база данных не принимает команды во избежание потери данных из-за " -"зацикливания транзакций в базе данных с OID %u" +"база данных с OID %u должна быть очищена (предельное число транзакций: %u)" -#: access/transam/varsup.c:148 access/transam/varsup.c:463 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 +#: access/transam/varsup.c:500 #, c-format -msgid "database \"%s\" must be vacuumed within %u transactions" +msgid "" +"To avoid XID assignment failures, execute a database-wide VACUUM in that " +"database.\n" +"You might also need to commit or roll back old prepared transactions, or " +"drop stale replication slots." msgstr "" -"база данных \"%s\" должна быть очищена (предельное число транзакций: %u)" +"Во избежание сбоев при назначении XID, выполните очистку (VACUUM) всей " +"базы.\n" +"Возможно, вам также придётся зафиксировать или откатить старые " +"подготовленные транзакции и удалить неиспользуемые слоты репликации." -#: access/transam/varsup.c:155 access/transam/varsup.c:470 +#: access/transam/xact.c:649 #, c-format -msgid "database with OID %u must be vacuumed within %u transactions" +msgid "cannot assign transaction IDs during a parallel operation" msgstr "" -"база данных с OID %u должна быть очищена (предельное число транзакций: %u)" +"идентификаторы транзакций не могут назначаться во время параллельных операций" + +#: access/transam/xact.c:840 +#, c-format +msgid "cannot modify data in a parallel worker" +msgstr "модифицировать данные в параллельном исполнителе нельзя" -#: access/transam/xact.c:1102 +#: access/transam/xact.c:1115 +#, c-format +msgid "cannot start commands during a parallel operation" +msgstr "начинать команды во время параллельной операции нельзя" + +#: access/transam/xact.c:1123 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "в одной транзакции не может быть больше 2^32-2 команд" -#: access/transam/xact.c:1643 +#: access/transam/xact.c:1664 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "превышен предел числа зафиксированных подтранзакций (%d)" -#: access/transam/xact.c:2513 +#: access/transam/xact.c:2561 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "" "нельзя выполнить PREPARE для транзакции, оперирующей с временными объектами" -#: access/transam/xact.c:2523 +#: access/transam/xact.c:2571 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "нельзя выполнить PREPARE для транзакции, снимки которой экспортированы" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3490 +#: access/transam/xact.c:3593 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s не может выполняться внутри блока транзакции" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3500 +#: access/transam/xact.c:3603 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%s не может выполняться внутри подтранзакции" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3510 +#: access/transam/xact.c:3613 #, c-format msgid "%s cannot be executed within a pipeline" msgstr "%s нельзя выполнять в конвейере" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3520 +#: access/transam/xact.c:3623 #, c-format msgid "%s cannot be executed from a function" msgstr "%s нельзя выполнять внутри функции" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3591 access/transam/xact.c:3916 -#: access/transam/xact.c:3995 access/transam/xact.c:4118 -#: access/transam/xact.c:4269 access/transam/xact.c:4338 -#: access/transam/xact.c:4449 +#: access/transam/xact.c:3694 access/transam/xact.c:4019 +#: access/transam/xact.c:4098 access/transam/xact.c:4221 +#: access/transam/xact.c:4372 access/transam/xact.c:4441 +#: access/transam/xact.c:4552 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%s может выполняться только внутри блоков транзакций" -#: access/transam/xact.c:3802 +#: access/transam/xact.c:3905 #, c-format msgid "there is already a transaction in progress" msgstr "транзакция уже выполняется" -#: access/transam/xact.c:3921 access/transam/xact.c:4000 -#: access/transam/xact.c:4123 +#: access/transam/xact.c:4024 access/transam/xact.c:4103 +#: access/transam/xact.c:4226 #, c-format msgid "there is no transaction in progress" msgstr "нет незавершённой транзакции" -#: access/transam/xact.c:4011 +#: access/transam/xact.c:4114 #, c-format msgid "cannot commit during a parallel operation" msgstr "фиксировать транзакции во время параллельных операций нельзя" -#: access/transam/xact.c:4134 +#: access/transam/xact.c:4237 #, c-format msgid "cannot abort during a parallel operation" msgstr "прерывание во время параллельных операций невозможно" -#: access/transam/xact.c:4233 +#: access/transam/xact.c:4336 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "определять точки сохранения во время параллельных операций нельзя" -#: access/transam/xact.c:4320 +#: access/transam/xact.c:4423 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "высвобождать точки сохранения во время параллельных операций нельзя" -#: access/transam/xact.c:4330 access/transam/xact.c:4381 -#: access/transam/xact.c:4441 access/transam/xact.c:4490 +#: access/transam/xact.c:4433 access/transam/xact.c:4484 +#: access/transam/xact.c:4544 access/transam/xact.c:4593 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "точка сохранения \"%s\" не существует" -#: access/transam/xact.c:4387 access/transam/xact.c:4496 +#: access/transam/xact.c:4490 access/transam/xact.c:4599 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "" "точка сохранения \"%s\" на текущем уровне точек сохранения не существует" -#: access/transam/xact.c:4429 +#: access/transam/xact.c:4532 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "откатиться к точке сохранения во время параллельных операций нельзя" -#: access/transam/xact.c:4557 -#, c-format -msgid "cannot start subtransactions during a parallel operation" -msgstr "запускать подтранзакции во время параллельных операций нельзя" - -#: access/transam/xact.c:4625 -#, c-format -msgid "cannot commit subtransactions during a parallel operation" -msgstr "фиксировать подтранзакции во время параллельных операций нельзя" - -#: access/transam/xact.c:5271 +#: access/transam/xact.c:5376 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "в одной транзакции не может быть больше 2^32-1 подтранзакций" -#: access/transam/xlog.c:1468 +#: access/transam/xlog.c:1542 #, c-format msgid "" "request to flush past end of generated WAL; request %X/%X, current position " @@ -2544,55 +2782,78 @@ msgstr "" "запрос на сброс данных за концом сгенерированного WAL; запрошена позиция %X/" "%X, текущая позиция %X/%X" -#: access/transam/xlog.c:2230 +#: access/transam/xlog.c:1769 +#, c-format +msgid "" +"cannot read past end of generated WAL: requested %X/%X, current position %X/" +"%X" +msgstr "" +"чтение за концом сгенерированного WAL невозможно: запрошена позиция %X/%X, " +"текущая позиция %X/%X" + +#: access/transam/xlog.c:2210 access/transam/xlog.c:4501 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "" +"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 ГБ." + +#: access/transam/xlog.c:2228 +#, c-format +msgid "\"%s\" must be set to -1 during binary upgrade mode." +msgstr "Параметр \"%s\" должен быть равен -1 в режиме двоичного обновления." + +#: access/transam/xlog.c:2477 #, c-format -msgid "could not write to log file %s at offset %u, length %zu: %m" -msgstr "не удалось записать в файл журнала %s (смещение: %u, длина: %zu): %m" +msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" +msgstr "" +"не удалось записать в файл журнала \"%s\" (смещение: %u, длина: %zu): %m" -#: access/transam/xlog.c:3457 access/transam/xlogutils.c:833 -#: replication/walsender.c:2725 +#: access/transam/xlog.c:3739 access/transam/xlogutils.c:831 +#: replication/walsender.c:3045 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "запрошенный сегмент WAL %s уже удалён" -#: access/transam/xlog.c:3741 +#: access/transam/xlog.c:4061 #, c-format msgid "could not rename file \"%s\": %m" msgstr "не удалось переименовать файл \"%s\": %m" -#: access/transam/xlog.c:3783 access/transam/xlog.c:3793 +#: access/transam/xlog.c:4104 access/transam/xlog.c:4115 +#: access/transam/xlog.c:4136 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "требуемый каталог WAL \"%s\" не существует" -#: access/transam/xlog.c:3799 +#: access/transam/xlog.c:4121 access/transam/xlog.c:4142 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "создаётся отсутствующий каталог WAL \"%s\"" -#: access/transam/xlog.c:3802 commands/dbcommands.c:3172 +#: access/transam/xlog.c:4125 access/transam/xlog.c:4145 +#: commands/dbcommands.c:3262 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "не удалось создать отсутствующий каталог \"%s\": %m" -#: access/transam/xlog.c:3869 +#: access/transam/xlog.c:4212 #, c-format msgid "could not generate secret authorization token" msgstr "не удалось сгенерировать случайное число для аутентификации" -#: access/transam/xlog.c:4019 access/transam/xlog.c:4028 -#: access/transam/xlog.c:4052 access/transam/xlog.c:4059 -#: access/transam/xlog.c:4066 access/transam/xlog.c:4071 -#: access/transam/xlog.c:4078 access/transam/xlog.c:4085 -#: access/transam/xlog.c:4092 access/transam/xlog.c:4099 -#: access/transam/xlog.c:4106 access/transam/xlog.c:4113 -#: access/transam/xlog.c:4122 access/transam/xlog.c:4129 -#: utils/init/miscinit.c:1769 +#: access/transam/xlog.c:4363 access/transam/xlog.c:4373 +#: access/transam/xlog.c:4399 access/transam/xlog.c:4407 +#: access/transam/xlog.c:4415 access/transam/xlog.c:4421 +#: access/transam/xlog.c:4429 access/transam/xlog.c:4437 +#: access/transam/xlog.c:4445 access/transam/xlog.c:4453 +#: access/transam/xlog.c:4461 access/transam/xlog.c:4469 +#: access/transam/xlog.c:4479 access/transam/xlog.c:4487 +#: utils/init/miscinit.c:1812 #, c-format msgid "database files are incompatible with server" msgstr "файлы базы данных несовместимы с сервером" -#: access/transam/xlog.c:4020 +#: access/transam/xlog.c:4364 #, c-format msgid "" "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), " @@ -2601,7 +2862,7 @@ msgstr "" "Кластер баз данных был инициализирован с PG_CONTROL_VERSION %d (0x%08x), но " "сервер скомпилирован с PG_CONTROL_VERSION %d (0x%08x)." -#: access/transam/xlog.c:4024 +#: access/transam/xlog.c:4368 #, c-format msgid "" "This could be a problem of mismatched byte ordering. It looks like you need " @@ -2610,7 +2871,7 @@ msgstr "" "Возможно, проблема вызвана разным порядком байт. Кажется, вам надо выполнить " "initdb." -#: access/transam/xlog.c:4029 +#: access/transam/xlog.c:4374 #, c-format msgid "" "The database cluster was initialized with PG_CONTROL_VERSION %d, but the " @@ -2619,18 +2880,18 @@ msgstr "" "Кластер баз данных был инициализирован с PG_CONTROL_VERSION %d, но сервер " "скомпилирован с PG_CONTROL_VERSION %d." -#: access/transam/xlog.c:4032 access/transam/xlog.c:4056 -#: access/transam/xlog.c:4063 access/transam/xlog.c:4068 +#: access/transam/xlog.c:4377 access/transam/xlog.c:4403 +#: access/transam/xlog.c:4411 access/transam/xlog.c:4417 #, c-format msgid "It looks like you need to initdb." msgstr "Кажется, вам надо выполнить initdb." -#: access/transam/xlog.c:4043 +#: access/transam/xlog.c:4389 #, c-format msgid "incorrect checksum in control file" msgstr "ошибка контрольной суммы в файле pg_control" -#: access/transam/xlog.c:4053 +#: access/transam/xlog.c:4400 #, c-format msgid "" "The database cluster was initialized with CATALOG_VERSION_NO %d, but the " @@ -2639,7 +2900,7 @@ msgstr "" "Кластер баз данных был инициализирован с CATALOG_VERSION_NO %d, но сервер " "скомпилирован с CATALOG_VERSION_NO %d." -#: access/transam/xlog.c:4060 +#: access/transam/xlog.c:4408 #, c-format msgid "" "The database cluster was initialized with MAXALIGN %d, but the server was " @@ -2648,7 +2909,7 @@ msgstr "" "Кластер баз данных был инициализирован с MAXALIGN %d, но сервер " "скомпилирован с MAXALIGN %d." -#: access/transam/xlog.c:4067 +#: access/transam/xlog.c:4416 #, c-format msgid "" "The database cluster appears to use a different floating-point number format " @@ -2657,7 +2918,7 @@ msgstr "" "Кажется, в кластере баз данных и в программе сервера используются разные " "форматы чисел с плавающей точкой." -#: access/transam/xlog.c:4072 +#: access/transam/xlog.c:4422 #, c-format msgid "" "The database cluster was initialized with BLCKSZ %d, but the server was " @@ -2666,16 +2927,16 @@ msgstr "" "Кластер баз данных был инициализирован с BLCKSZ %d, но сервер скомпилирован " "с BLCKSZ %d." -#: access/transam/xlog.c:4075 access/transam/xlog.c:4082 -#: access/transam/xlog.c:4089 access/transam/xlog.c:4096 -#: access/transam/xlog.c:4103 access/transam/xlog.c:4110 -#: access/transam/xlog.c:4117 access/transam/xlog.c:4125 -#: access/transam/xlog.c:4132 +#: access/transam/xlog.c:4425 access/transam/xlog.c:4433 +#: access/transam/xlog.c:4441 access/transam/xlog.c:4449 +#: access/transam/xlog.c:4457 access/transam/xlog.c:4465 +#: access/transam/xlog.c:4473 access/transam/xlog.c:4482 +#: access/transam/xlog.c:4490 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "Кажется, вам надо перекомпилировать сервер или выполнить initdb." -#: access/transam/xlog.c:4079 +#: access/transam/xlog.c:4430 #, c-format msgid "" "The database cluster was initialized with RELSEG_SIZE %d, but the server was " @@ -2684,7 +2945,7 @@ msgstr "" "Кластер баз данных был инициализирован с RELSEG_SIZE %d, но сервер " "скомпилирован с RELSEG_SIZE %d." -#: access/transam/xlog.c:4086 +#: access/transam/xlog.c:4438 #, c-format msgid "" "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was " @@ -2693,7 +2954,7 @@ msgstr "" "Кластер баз данных был инициализирован с XLOG_BLCKSZ %d, но сервер " "скомпилирован с XLOG_BLCKSZ %d." -#: access/transam/xlog.c:4093 +#: access/transam/xlog.c:4446 #, c-format msgid "" "The database cluster was initialized with NAMEDATALEN %d, but the server was " @@ -2702,7 +2963,7 @@ msgstr "" "Кластер баз данных был инициализирован с NAMEDATALEN %d, но сервер " "скомпилирован с NAMEDATALEN %d." -#: access/transam/xlog.c:4100 +#: access/transam/xlog.c:4454 #, c-format msgid "" "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server " @@ -2711,7 +2972,7 @@ msgstr "" "Кластер баз данных был инициализирован с INDEX_MAX_KEYS %d, но сервер " "скомпилирован с INDEX_MAX_KEYS %d." -#: access/transam/xlog.c:4107 +#: access/transam/xlog.c:4462 #, c-format msgid "" "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the " @@ -2720,7 +2981,7 @@ msgstr "" "Кластер баз данных был инициализирован с TOAST_MAX_CHUNK_SIZE %d, но сервер " "скомпилирован с TOAST_MAX_CHUNK_SIZE %d." -#: access/transam/xlog.c:4114 +#: access/transam/xlog.c:4470 #, c-format msgid "" "The database cluster was initialized with LOBLKSIZE %d, but the server was " @@ -2729,7 +2990,7 @@ msgstr "" "Кластер баз данных был инициализирован с LOBLKSIZE %d, но сервер " "скомпилирован с LOBLKSIZE %d." -#: access/transam/xlog.c:4123 +#: access/transam/xlog.c:4480 #, c-format msgid "" "The database cluster was initialized without USE_FLOAT8_BYVAL but the server " @@ -2738,7 +2999,7 @@ msgstr "" "Кластер баз данных был инициализирован без USE_FLOAT8_BYVAL, но сервер " "скомпилирован с USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4130 +#: access/transam/xlog.c:4488 #, c-format msgid "" "The database cluster was initialized with USE_FLOAT8_BYVAL but the server " @@ -2747,107 +3008,100 @@ msgstr "" "Кластер баз данных был инициализирован с USE_FLOAT8_BYVAL, но сервер был " "скомпилирован без USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4139 +#: access/transam/xlog.c:4497 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d bytes" -msgstr[0] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" -msgstr[1] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" -msgstr[2] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[1] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[2] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" -#: access/transam/xlog.c:4151 +#: access/transam/xlog.c:4510 #, c-format msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"min_wal_size\" должен быть минимум вдвое больше \"wal_segment_size\"" -#: access/transam/xlog.c:4155 +#: access/transam/xlog.c:4514 #, c-format msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"max_wal_size\" должен быть минимум вдвое больше \"wal_segment_size\"" -#: access/transam/xlog.c:4310 catalog/namespace.c:4335 -#: commands/tablespace.c:1216 commands/user.c:2530 commands/variable.c:72 -#: utils/error/elog.c:2209 +#: access/transam/xlog.c:4662 catalog/namespace.c:4696 +#: commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 +#: replication/slot.c:2429 tcop/postgres.c:3715 utils/error/elog.c:2247 #, c-format msgid "List syntax is invalid." msgstr "Ошибка синтаксиса в списке." -#: access/transam/xlog.c:4356 commands/user.c:2546 commands/variable.c:173 -#: utils/error/elog.c:2235 +#: access/transam/xlog.c:4708 commands/user.c:2545 commands/variable.c:173 +#: tcop/postgres.c:3731 utils/error/elog.c:2273 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "нераспознанное ключевое слово: \"%s\"." -#: access/transam/xlog.c:4770 +#: access/transam/xlog.c:5129 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "не удалось записать начальный файл журнала предзаписи: %m" -#: access/transam/xlog.c:4778 +#: access/transam/xlog.c:5137 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "не удалось сбросить на диск начальный файл журнала предзаписи: %m" -#: access/transam/xlog.c:4784 +#: access/transam/xlog.c:5143 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "не удалось закрыть начальный файл журнала предзаписи: %m" -#: access/transam/xlog.c:5001 +#: access/transam/xlog.c:5368 #, c-format -msgid "WAL was generated with wal_level=minimal, cannot continue recovering" +msgid "" +"WAL was generated with \"wal_level=minimal\", cannot continue recovering" msgstr "" -"WAL был создан с параметром wal_level=minimal, продолжение восстановления " -"невозможно" +"WAL был создан с параметром \"wal_level=minimal\", продолжение " +"восстановления невозможно" -#: access/transam/xlog.c:5002 +#: access/transam/xlog.c:5369 #, c-format -msgid "This happens if you temporarily set wal_level=minimal on the server." -msgstr "Это происходит, если вы на время устанавливали wal_level=minimal." +msgid "" +"This happens if you temporarily set \"wal_level=minimal\" on the server." +msgstr "Это происходит, если вы на время устанавливали \"wal_level=minimal\"." -#: access/transam/xlog.c:5003 +#: access/transam/xlog.c:5370 #, c-format -msgid "Use a backup taken after setting wal_level to higher than minimal." +msgid "" +"Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." msgstr "" -"Используйте резервную копию, сделанную после переключения wal_level на любой " -"уровень выше minimal." +"Используйте резервную копию, сделанную после переключения \"wal_level\" на " +"любой уровень выше \"minimal\"." -#: access/transam/xlog.c:5067 +#: access/transam/xlog.c:5435 #, c-format msgid "control file contains invalid checkpoint location" msgstr "файл pg_control содержит неправильную позицию контрольной точки" -#: access/transam/xlog.c:5078 +#: access/transam/xlog.c:5446 #, c-format msgid "database system was shut down at %s" msgstr "система БД была выключена: %s" -#: access/transam/xlog.c:5084 +#: access/transam/xlog.c:5452 #, c-format msgid "database system was shut down in recovery at %s" msgstr "система БД была выключена в процессе восстановления: %s" -#: access/transam/xlog.c:5090 +#: access/transam/xlog.c:5458 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "выключение системы БД было прервано; последний момент работы: %s" -#: access/transam/xlog.c:5096 +#: access/transam/xlog.c:5464 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "работа системы БД была прервана во время восстановления: %s" -#: access/transam/xlog.c:5098 +#: access/transam/xlog.c:5466 #, c-format msgid "" "This probably means that some data is corrupted and you will have to use the " @@ -2856,14 +3110,14 @@ msgstr "" "Это скорее всего означает, что некоторые данные повреждены и вам придётся " "восстановить БД из последней резервной копии." -#: access/transam/xlog.c:5104 +#: access/transam/xlog.c:5472 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "" "работа системы БД была прервана в процессе восстановления, время в журнале: " "%s" -#: access/transam/xlog.c:5106 +#: access/transam/xlog.c:5474 #, c-format msgid "" "If this has occurred more than once some data might be corrupted and you " @@ -2872,22 +3126,22 @@ msgstr "" "Если это происходит постоянно, возможно, какие-то данные были испорчены и " "для восстановления стоит выбрать более раннюю точку." -#: access/transam/xlog.c:5112 +#: access/transam/xlog.c:5480 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "работа системы БД была прервана; последний момент работы: %s" -#: access/transam/xlog.c:5118 +#: access/transam/xlog.c:5487 #, c-format msgid "control file contains invalid database cluster state" msgstr "файл pg_control содержит неверный код состояния кластера" -#: access/transam/xlog.c:5502 +#: access/transam/xlog.c:5875 #, c-format msgid "WAL ends before end of online backup" msgstr "WAL закончился без признака окончания копирования" -#: access/transam/xlog.c:5503 +#: access/transam/xlog.c:5876 #, c-format msgid "" "All WAL generated while online backup was taken must be available at " @@ -2896,40 +3150,40 @@ msgstr "" "Все журналы WAL, созданные во время резервного копирования \"на ходу\", " "должны быть в наличии для восстановления." -#: access/transam/xlog.c:5506 +#: access/transam/xlog.c:5880 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL закончился до согласованной точки восстановления" -#: access/transam/xlog.c:5552 +#: access/transam/xlog.c:5926 #, c-format msgid "selected new timeline ID: %u" msgstr "выбранный ID новой линии времени: %u" -#: access/transam/xlog.c:5585 +#: access/transam/xlog.c:5959 #, c-format msgid "archive recovery complete" msgstr "восстановление архива завершено" -#: access/transam/xlog.c:6191 +#: access/transam/xlog.c:6612 #, c-format msgid "shutting down" msgstr "выключение" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6230 +#: access/transam/xlog.c:6651 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "начата точка перезапуска:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6242 +#: access/transam/xlog.c:6663 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "начата контрольная точка:%s%s%s%s%s%s%s%s" # well-spelled: синхр -#: access/transam/xlog.c:6307 +#: access/transam/xlog.c:6728 #, c-format msgid "" "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d " @@ -2944,7 +3198,7 @@ msgstr "" "lsn=%X/%X, lsn redo=%X/%X" # well-spelled: синхр -#: access/transam/xlog.c:6330 +#: access/transam/xlog.c:6751 #, c-format msgid "" "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d " @@ -2958,7 +3212,7 @@ msgstr "" "=%ld.%03d сек., средняя=%ld.%03d сек.; расстояние=%d kB, ожидалось=%d kB; " "lsn=%X/%X, lsn redo=%X/%X" -#: access/transam/xlog.c:6768 +#: access/transam/xlog.c:7233 #, c-format msgid "" "concurrent write-ahead log activity while database system is shutting down" @@ -2966,111 +3220,119 @@ msgstr "" "во время выключения системы баз данных отмечена активность в журнале " "предзаписи" -#: access/transam/xlog.c:7329 +#: access/transam/xlog.c:7818 #, c-format msgid "recovery restart point at %X/%X" msgstr "точка перезапуска восстановления в позиции %X/%X" -#: access/transam/xlog.c:7331 +#: access/transam/xlog.c:7820 #, c-format msgid "Last completed transaction was at log time %s." msgstr "Последняя завершённая транзакция была выполнена в %s." -#: access/transam/xlog.c:7579 +#: access/transam/xlog.c:8082 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "точка восстановления \"%s\" создана в позиции %X/%X" -#: access/transam/xlog.c:7786 +#: access/transam/xlog.c:8289 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "" "резервное копирование \"на ходу\" было отменено, продолжить восстановление " "нельзя" -#: access/transam/xlog.c:7843 +#: access/transam/xlog.c:8347 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "" "неожиданный ID линии времени %u (должен быть %u) в записи точки выключения" -#: access/transam/xlog.c:7901 +#: access/transam/xlog.c:8405 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "" "неожиданный ID линии времени %u (должен быть %u) в записи точки активности" -#: access/transam/xlog.c:7930 +#: access/transam/xlog.c:8434 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "" "неожиданный ID линии времени %u (должен быть %u) в записи конец-" "восстановления" -#: access/transam/xlog.c:8197 +#: access/transam/xlog.c:8705 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "не удалось синхронизировать с ФС файл сквозной записи %s: %m" -#: access/transam/xlog.c:8202 +#: access/transam/xlog.c:8710 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "не удалось синхронизировать с ФС данные (fdatasync) файла \"%s\": %m" -#: access/transam/xlog.c:8287 access/transam/xlog.c:8610 +#: access/transam/xlog.c:8797 access/transam/xlog.c:9133 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "" "Выбранный уровень WAL недостаточен для резервного копирования \"на ходу\"" -#: access/transam/xlog.c:8288 access/transam/xlog.c:8611 -#: access/transam/xlogfuncs.c:254 +#: access/transam/xlog.c:8798 access/transam/xlogfuncs.c:248 #, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "Установите wal_level \"replica\" или \"logical\" при запуске сервера." +msgid "" +"\"wal_level\" must be set to \"replica\" or \"logical\" at server start." +msgstr "" +"Параметр \"wal_level\" должен иметь значение \"replica\" или \"logical\" при " +"запуске сервера." -#: access/transam/xlog.c:8293 +#: access/transam/xlog.c:8803 #, c-format msgid "backup label too long (max %d bytes)" msgstr "длина метки резервной копии превышает предел (%d байт)" -#: access/transam/xlog.c:8414 +#: access/transam/xlog.c:8924 #, c-format msgid "" -"WAL generated with full_page_writes=off was replayed since last restartpoint" +"WAL generated with \"full_page_writes=off\" was replayed since last " +"restartpoint" msgstr "" -"После последней точки перезапуска был воспроизведён WAL, созданный в режиме " -"full_page_writes=off." +"после последней точки перезапуска был воспроизведён WAL, созданный в режиме " +"\"full_page_writes=off\"" -#: access/transam/xlog.c:8416 access/transam/xlog.c:8699 +#: access/transam/xlog.c:8926 access/transam/xlog.c:9222 #, c-format msgid "" "This means that the backup being taken on the standby is corrupt and should " -"not be used. Enable full_page_writes and run CHECKPOINT on the primary, and " -"then try an online backup again." +"not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, " +"and then try an online backup again." msgstr "" -"Это означает, что резервная копия, сделанная на дежурном сервере, испорчена " -"и использовать её не следует. Включите режим full_page_writes и выполните " +"Это означает, что резервная копия, сделанная на ведомом сервере, испорчена и " +"использовать её не следует. Включите режим \"full_page_writes\" и выполните " "CHECKPOINT на ведущем сервере, а затем попробуйте резервное копирование \"на " "ходу\" ещё раз." -#: access/transam/xlog.c:8483 backup/basebackup.c:1355 utils/adt/misc.c:354 +#: access/transam/xlog.c:9006 backup/basebackup.c:1417 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "не удалось прочитать символическую ссылку \"%s\": %m" -#: access/transam/xlog.c:8490 backup/basebackup.c:1360 utils/adt/misc.c:359 +#: access/transam/xlog.c:9013 backup/basebackup.c:1422 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "целевой путь символической ссылки \"%s\" слишком длинный" -#: access/transam/xlog.c:8649 backup/basebackup.c:1221 +#: access/transam/xlog.c:9134 +#, c-format +msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgstr "Установите wal_level \"replica\" или \"logical\" при запуске сервера." + +#: access/transam/xlog.c:9172 backup/basebackup.c:1281 #, c-format msgid "the standby was promoted during online backup" msgstr "" -"дежурный сервер был повышен в процессе резервного копирования \"на ходу\"" +"ведомый сервер был повышен в процессе резервного копирования \"на ходу\"" -#: access/transam/xlog.c:8650 backup/basebackup.c:1222 +#: access/transam/xlog.c:9173 backup/basebackup.c:1282 #, c-format msgid "" "This means that the backup being taken is corrupt and should not be used. " @@ -3079,21 +3341,21 @@ msgstr "" "Это означает, что создаваемая резервная копия испорчена и использовать её не " "следует. Попробуйте резервное копирование \"на ходу\" ещё раз." -#: access/transam/xlog.c:8697 +#: access/transam/xlog.c:9220 #, c-format msgid "" -"WAL generated with full_page_writes=off was replayed during online backup" +"WAL generated with \"full_page_writes=off\" was replayed during online backup" msgstr "" -"В процессе резервного копирования \"на ходу\" был воспроизведён WAL, " -"созданный в режиме full_page_writes=off" +"в процессе резервного копирования \"на ходу\" был воспроизведён WAL, " +"созданный в режиме \"full_page_writes=off\"" -#: access/transam/xlog.c:8813 +#: access/transam/xlog.c:9336 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "" "базовое копирование выполнено, ожидается архивация нужных сегментов WAL" -#: access/transam/xlog.c:8827 +#: access/transam/xlog.c:9350 #, c-format msgid "" "still waiting for all required WAL segments to be archived (%d seconds " @@ -3101,23 +3363,23 @@ msgid "" msgstr "" "продолжается ожидание архивации всех нужных сегментов WAL (прошло %d сек.)" -#: access/transam/xlog.c:8829 +#: access/transam/xlog.c:9352 #, c-format msgid "" -"Check that your archive_command is executing properly. You can safely " +"Check that your \"archive_command\" is executing properly. You can safely " "cancel this backup, but the database backup will not be usable without all " "the WAL segments." msgstr "" -"Проверьте, правильно ли работает команда archive_command. Операцию " +"Проверьте, правильно ли работает команда \"archive_command\". Операцию " "копирования можно отменить безопасно, но резервная копия базы будет " "непригодна без всех сегментов WAL." -#: access/transam/xlog.c:8836 +#: access/transam/xlog.c:9359 #, c-format msgid "all required WAL segments have been archived" msgstr "все нужные сегменты WAL заархивированы" -#: access/transam/xlog.c:8840 +#: access/transam/xlog.c:9363 #, c-format msgid "" "WAL archiving is not enabled; you must ensure that all required WAL segments " @@ -3126,31 +3388,31 @@ msgstr "" "архивация WAL не настроена; вы должны обеспечить копирование всех требуемых " "сегментов WAL другими средствами для получения резервной копии" -#: access/transam/xlog.c:8879 +#: access/transam/xlog.c:9402 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "" "прерывание резервного копирования из-за завершения обслуживающего процесса " "до вызова pg_backup_stop" -#: access/transam/xlogarchive.c:214 +#: access/transam/xlogarchive.c:213 #, c-format msgid "archive file \"%s\" has wrong size: %lld instead of %lld" msgstr "файл архива \"%s\" имеет неправильный размер: %lld вместо %lld" -#: access/transam/xlogarchive.c:223 +#: access/transam/xlogarchive.c:222 #, c-format msgid "restored log file \"%s\" from archive" msgstr "файл журнала \"%s\" восстановлен из архива" -#: access/transam/xlogarchive.c:237 +#: access/transam/xlogarchive.c:236 #, c-format -msgid "restore_command returned a zero exit status, but stat() failed." +msgid "\"restore_command\" returned a zero exit status, but stat() failed." msgstr "" -"Команда restore_command возвратила нулевой код состояния, но stat() выдала " -"ошибку." +"Команда \"restore_command\" возвратила нулевой код состояния, но stat() " +"выдала ошибку." -#: access/transam/xlogarchive.c:269 +#: access/transam/xlogarchive.c:268 #, c-format msgid "could not restore file \"%s\" from archive: %s" msgstr "восстановить файл \"%s\" из архива не удалось: %s" @@ -3158,109 +3420,120 @@ msgstr "восстановить файл \"%s\" из архива не удал #. translator: First %s represents a postgresql.conf parameter name like #. "recovery_end_command", the 2nd is the value of that parameter, the #. third an already translated error message. -#: access/transam/xlogarchive.c:347 +#: access/transam/xlogarchive.c:346 #, c-format msgid "%s \"%s\": %s" msgstr "%s \"%s\": %s" -#: access/transam/xlogarchive.c:457 access/transam/xlogarchive.c:537 +#: access/transam/xlogarchive.c:456 access/transam/xlogarchive.c:536 #, c-format msgid "could not create archive status file \"%s\": %m" msgstr "не удалось создать файл состояния архива \"%s\": %m" -#: access/transam/xlogarchive.c:465 access/transam/xlogarchive.c:545 +#: access/transam/xlogarchive.c:464 access/transam/xlogarchive.c:544 #, c-format msgid "could not write archive status file \"%s\": %m" msgstr "не удалось записать файл состояния архива \"%s\": %m" -#: access/transam/xlogfuncs.c:75 backup/basebackup.c:973 +#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 #, c-format msgid "a backup is already in progress in this session" msgstr "резервное копирование уже выполняется в этом сеансе" -#: access/transam/xlogfuncs.c:146 +#: access/transam/xlogfuncs.c:140 #, c-format msgid "backup is not in progress" msgstr "резервное копирование не выполняется" -#: access/transam/xlogfuncs.c:147 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "Did you call pg_backup_start()?" msgstr "Вы вызывали pg_backup_start()?" -#: access/transam/xlogfuncs.c:190 access/transam/xlogfuncs.c:248 -#: access/transam/xlogfuncs.c:287 access/transam/xlogfuncs.c:308 -#: access/transam/xlogfuncs.c:329 +#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 +#: access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 +#: access/transam/xlogfuncs.c:323 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "Функции управления WAL нельзя использовать в процессе восстановления." -#: access/transam/xlogfuncs.c:215 access/transam/xlogfuncs.c:399 -#: access/transam/xlogfuncs.c:457 +#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 +#: access/transam/xlogfuncs.c:447 #, c-format msgid "%s cannot be executed during recovery." msgstr "выполнить %s во время восстановления нельзя." -#: access/transam/xlogfuncs.c:221 +#: access/transam/xlogfuncs.c:215 #, c-format -msgid "pg_log_standby_snapshot() can only be used if wal_level >= replica" +msgid "" +"pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" msgstr "" -"pg_log_standby_snapshot() можно использовать, только если wal_level >= " -"replica" +"pg_log_standby_snapshot() можно использовать, только если \"wal_level\" >= " +"\"replica\"" -#: access/transam/xlogfuncs.c:253 +#: access/transam/xlogfuncs.c:247 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "Выбранный уровень WAL не достаточен для создания точки восстановления" # well-spelled: симв -#: access/transam/xlogfuncs.c:261 +#: access/transam/xlogfuncs.c:255 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "значение для точки восстановления превышает предел (%d симв.)" -#: access/transam/xlogfuncs.c:496 +#: access/transam/xlogfuncs.c:486 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "неправильное имя файла WAL \"%s\"" -#: access/transam/xlogfuncs.c:532 access/transam/xlogfuncs.c:562 -#: access/transam/xlogfuncs.c:586 access/transam/xlogfuncs.c:609 -#: access/transam/xlogfuncs.c:689 +#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 +#: access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 +#: access/transam/xlogfuncs.c:679 #, c-format msgid "recovery is not in progress" msgstr "восстановление не выполняется" -#: access/transam/xlogfuncs.c:533 access/transam/xlogfuncs.c:563 -#: access/transam/xlogfuncs.c:587 access/transam/xlogfuncs.c:610 -#: access/transam/xlogfuncs.c:690 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 +#: access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 +#: access/transam/xlogfuncs.c:680 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "" "Функции управления восстановлением можно использовать только в процессе " "восстановления." -#: access/transam/xlogfuncs.c:538 access/transam/xlogfuncs.c:568 +#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 #, c-format msgid "standby promotion is ongoing" msgstr "производится повышение ведомого" -#: access/transam/xlogfuncs.c:539 access/transam/xlogfuncs.c:569 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%s нельзя выполнять, когда производится повышение." -#: access/transam/xlogfuncs.c:695 +#: access/transam/xlogfuncs.c:685 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "значение \"wait_seconds\" не должно быть отрицательным или нулевым" -#: access/transam/xlogfuncs.c:715 storage/ipc/signalfuncs.c:265 +#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "отправить сигнал процессу postmaster не удалось: %m" -#: access/transam/xlogfuncs.c:751 +#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#, c-format +msgid "terminating connection due to unexpected postmaster exit" +msgstr "закрытие подключения из-за неожиданного завершения главного процесса" + +#: access/transam/xlogfuncs.c:740 +#, c-format +msgid "while waiting on promotion" +msgstr "в процессе ожидания повышения" + +#: access/transam/xlogfuncs.c:744 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" @@ -3268,71 +3541,72 @@ msgstr[0] "повышение сервера не завершилось за %d msgstr[1] "повышение сервера не завершилось за %d секунды" msgstr[2] "повышение сервера не завершилось за %d секунд" -#: access/transam/xlogprefetcher.c:1092 +#: access/transam/xlogprefetcher.c:1088 #, c-format msgid "" -"recovery_prefetch is not supported on platforms that lack posix_fadvise()." +"\"recovery_prefetch\" is not supported on platforms that lack " +"posix_fadvise()." msgstr "" -"recovery_prefetch не поддерживается на платформах, где отсутствует " +"\"recovery_prefetch\" не поддерживается на платформах, где отсутствует " "posix_fadvise()." -#: access/transam/xlogreader.c:621 +#: access/transam/xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "" "неверное смещение записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: access/transam/xlogreader.c:630 +#: access/transam/xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "в позиции %X/%X запрошено продолжение записи" -#: access/transam/xlogreader.c:671 access/transam/xlogreader.c:1136 +#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "" "неверная длина записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: access/transam/xlogreader.c:760 +#: access/transam/xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "нет флага contrecord в позиции %X/%X" -#: access/transam/xlogreader.c:773 +#: access/transam/xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неверная длина contrecord: %u (ожидалась %lld) в позиции %X/%X" -#: access/transam/xlogreader.c:1144 +#: access/transam/xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "неверный ID менеджера ресурсов %u в позиции %X/%X" -#: access/transam/xlogreader.c:1157 access/transam/xlogreader.c:1173 +#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запись с неверной ссылкой назад %X/%X в позиции %X/%X" -#: access/transam/xlogreader.c:1211 +#: access/transam/xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "" "некорректная контрольная сумма данных менеджера ресурсов в записи в позиции " "%X/%X" -#: access/transam/xlogreader.c:1245 +#: access/transam/xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверное магическое число %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: access/transam/xlogreader.c:1260 access/transam/xlogreader.c:1302 +#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверные информационные биты %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: access/transam/xlogreader.c:1276 +#: access/transam/xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -3341,7 +3615,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: в нём указан идентификатор системы БД " "%llu, а идентификатор системы pg_control: %llu" -#: access/transam/xlogreader.c:1284 +#: access/transam/xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -3350,7 +3624,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный размер сегмента в заголовке " "страницы" -#: access/transam/xlogreader.c:1290 +#: access/transam/xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -3359,12 +3633,12 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный XLOG_BLCKSZ в заголовке " "страницы" -#: access/transam/xlogreader.c:1322 +#: access/transam/xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неожиданный pageaddr %X/%X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: access/transam/xlogreader.c:1348 +#: access/transam/xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -3373,23 +3647,23 @@ msgstr "" "нарушение последовательности ID линии времени %u (после %u) в сегменте WAL " "%s, LSN %X/%X, смещение %u" -#: access/transam/xlogreader.c:1754 +#: access/transam/xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "идентификатор блока %u идёт не по порядку в позиции %X/%X" -#: access/transam/xlogreader.c:1778 +#: access/transam/xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA установлен, но данных в позиции %X/%X нет" -#: access/transam/xlogreader.c:1785 +#: access/transam/xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "" "BKPBLOCK_HAS_DATA не установлен, но длина данных равна %u в позиции %X/%X" -#: access/transam/xlogreader.c:1821 +#: access/transam/xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -3398,21 +3672,21 @@ msgstr "" "BKPIMAGE_HAS_HOLE установлен, но для пропуска заданы смещение %u и длина %u " "при длине образа блока %u в позиции %X/%X" -#: access/transam/xlogreader.c:1837 +#: access/transam/xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE не установлен, но для пропуска заданы смещение %u и длина " "%u в позиции %X/%X" -#: access/transam/xlogreader.c:1851 +#: access/transam/xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED установлен, но длина образа блока равна %u в позиции %X/" "%X" -#: access/transam/xlogreader.c:1866 +#: access/transam/xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -3421,41 +3695,41 @@ msgstr "" "ни BKPIMAGE_HAS_HOLE, ни BKPIMAGE_COMPRESSED не установлены, но длина образа " "блока равна %u в позиции %X/%X" -#: access/transam/xlogreader.c:1882 +#: access/transam/xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "" "BKPBLOCK_SAME_REL установлен, но предыдущее значение не задано в позиции %X/" "%X" -#: access/transam/xlogreader.c:1894 +#: access/transam/xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "неверный идентификатор блока %u в позиции %X/%X" -#: access/transam/xlogreader.c:1961 +#: access/transam/xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запись с неверной длиной в позиции %X/%X" -#: access/transam/xlogreader.c:1987 +#: access/transam/xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не удалось найти копию блока с ID %d в записи журнала WAL" -#: access/transam/xlogreader.c:2071 +#: access/transam/xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "" "не удалось восстановить образ в позиции %X/%X с указанным неверным блоком %d" -#: access/transam/xlogreader.c:2078 +#: access/transam/xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "" "не удалось восстановить образ в позиции %X/%X с неверным состоянием, блок %d" -#: access/transam/xlogreader.c:2105 access/transam/xlogreader.c:2122 +#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " @@ -3464,7 +3738,7 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый методом %s, который не " "поддерживается этой сборкой, блок %d" -#: access/transam/xlogreader.c:2131 +#: access/transam/xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" @@ -3472,49 +3746,12 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый неизвестным методом, " "блок %d" -#: access/transam/xlogreader.c:2139 +#: access/transam/xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не удалось развернуть образ в позиции %X/%X, блок %d" -#: access/transam/xlogrecovery.c:547 -#, c-format -msgid "entering standby mode" -msgstr "переход в режим резервного сервера" - -#: access/transam/xlogrecovery.c:550 -#, c-format -msgid "starting point-in-time recovery to XID %u" -msgstr "начинается восстановление точки во времени до XID %u" - -#: access/transam/xlogrecovery.c:554 -#, c-format -msgid "starting point-in-time recovery to %s" -msgstr "начинается восстановление точки во времени до %s" - -#: access/transam/xlogrecovery.c:558 -#, c-format -msgid "starting point-in-time recovery to \"%s\"" -msgstr "начинается восстановление точки во времени до \"%s\"" - -#: access/transam/xlogrecovery.c:562 -#, c-format -msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" -msgstr "" -"начинается восстановление точки во времени до позиции в WAL (LSN) \"%X/%X\"" - -#: access/transam/xlogrecovery.c:566 -#, c-format -msgid "starting point-in-time recovery to earliest consistent point" -msgstr "" -"начинается восстановление точки во времени до первой точки согласованности" - -#: access/transam/xlogrecovery.c:569 -#, c-format -msgid "starting archive recovery" -msgstr "начинается восстановление архива" - -#: access/transam/xlogrecovery.c:637 +#: access/transam/xlogrecovery.c:617 #, c-format msgid "" "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on " @@ -3523,68 +3760,108 @@ msgstr "" "начинается восстановление копии с LSN redo %X/%X, LSN контрольной точки %X/" "%X, на линии времени %u" -#: access/transam/xlogrecovery.c:669 +#: access/transam/xlogrecovery.c:649 #, c-format -msgid "could not find redo location referenced by checkpoint record" -msgstr "не удалось найти положение REDO, указанное записью контрольной точки" +msgid "" +"could not find redo location %X/%X referenced by checkpoint record at %X/%X" +msgstr "" +"не удалось найти положение REDO %X/%X, указанное в записи контрольной точки " +"в %X/%X" -#: access/transam/xlogrecovery.c:670 access/transam/xlogrecovery.c:680 +#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 #, c-format msgid "" -"If you are restoring from a backup, touch \"%s/recovery.signal\" and add " -"required recovery options.\n" +"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/" +"standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/" "backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if " "restoring from a backup." msgstr "" -"Если вы восстанавливаете резервную копию, создайте \"%s/recovery.signal\" и " -"задайте обязательные параметры восстановления.\n" +"Если вы восстанавливаете резервную копию, создайте \"%s/recovery.signal\" " +"или \"%s/standby.signal\" и задайте обязательные параметры восстановления.\n" "В других случаях попытайтесь удалить файл \"%s/backup_label\".\n" "Будьте осторожны: при восстановлении резервной копии удаление \"%s/" "backup_label\" приведёт к повреждению кластера." -#: access/transam/xlogrecovery.c:679 +#: access/transam/xlogrecovery.c:660 #, c-format -msgid "could not locate required checkpoint record" -msgstr "не удалось считать нужную запись контрольной точки" +msgid "could not locate required checkpoint record at %X/%X" +msgstr "не удалось найти нужную запись контрольной точки в %X/%X" -#: access/transam/xlogrecovery.c:708 commands/tablespace.c:670 +#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не удалось создать символическую ссылку \"%s\": %m" -#: access/transam/xlogrecovery.c:740 access/transam/xlogrecovery.c:746 +#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "файл \"%s\" игнорируется ввиду отсутствия файла \"%s\"" -#: access/transam/xlogrecovery.c:742 +#: access/transam/xlogrecovery.c:725 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "Файл \"%s\" был переименован в \"%s\"." -#: access/transam/xlogrecovery.c:748 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "Не удалось переименовать файл \"%s\" в \"%s\" (%m)." -#: access/transam/xlogrecovery.c:787 +#: access/transam/xlogrecovery.c:770 #, c-format msgid "restarting backup recovery with redo LSN %X/%X" msgstr "перезапуск восстановления копии с LSN redo %X/%X" -#: access/transam/xlogrecovery.c:812 +#: access/transam/xlogrecovery.c:795 +#, c-format +msgid "could not locate a valid checkpoint record at %X/%X" +msgstr "не удалось найти корректную запись контрольной точки в %X/%X" + +#: access/transam/xlogrecovery.c:806 +#, c-format +msgid "entering standby mode" +msgstr "переход в режим резервного сервера" + +#: access/transam/xlogrecovery.c:809 +#, c-format +msgid "starting point-in-time recovery to XID %u" +msgstr "начинается восстановление точки во времени до XID %u" + +#: access/transam/xlogrecovery.c:813 +#, c-format +msgid "starting point-in-time recovery to %s" +msgstr "начинается восстановление точки во времени до %s" + +#: access/transam/xlogrecovery.c:817 +#, c-format +msgid "starting point-in-time recovery to \"%s\"" +msgstr "начинается восстановление точки во времени до \"%s\"" + +#: access/transam/xlogrecovery.c:821 +#, c-format +msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" +msgstr "" +"начинается восстановление точки во времени до позиции в WAL (LSN) \"%X/%X\"" + +#: access/transam/xlogrecovery.c:825 #, c-format -msgid "could not locate a valid checkpoint record" -msgstr "не удалось считать правильную запись контрольной точки" +msgid "starting point-in-time recovery to earliest consistent point" +msgstr "" +"начинается восстановление точки во времени до первой точки согласованности" + +#: access/transam/xlogrecovery.c:828 +#, c-format +msgid "starting archive recovery" +msgstr "начинается восстановление архива" -#: access/transam/xlogrecovery.c:836 +#: access/transam/xlogrecovery.c:849 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "в истории сервера нет ответвления запрошенной линии времени %u" -#: access/transam/xlogrecovery.c:838 +#: access/transam/xlogrecovery.c:851 #, c-format msgid "" "Latest checkpoint is at %X/%X on timeline %u, but in the history of the " @@ -3593,7 +3870,7 @@ msgstr "" "Последняя контрольная точка: %X/%X на линии времени %u, но в истории " "запрошенной линии времени сервер ответвился с этой линии в %X/%X." -#: access/transam/xlogrecovery.c:852 +#: access/transam/xlogrecovery.c:865 #, c-format msgid "" "requested timeline %u does not contain minimum recovery point %X/%X on " @@ -3602,22 +3879,22 @@ msgstr "" "запрошенная линия времени %u не содержит минимальную точку восстановления %X/" "%X на линии времени %u" -#: access/transam/xlogrecovery.c:880 +#: access/transam/xlogrecovery.c:893 #, c-format msgid "invalid next transaction ID" msgstr "неверный ID следующей транзакции" -#: access/transam/xlogrecovery.c:885 +#: access/transam/xlogrecovery.c:898 #, c-format msgid "invalid redo in checkpoint record" msgstr "неверная запись REDO в контрольной точке" -#: access/transam/xlogrecovery.c:896 +#: access/transam/xlogrecovery.c:909 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "неверная запись REDO в контрольной точке выключения" -#: access/transam/xlogrecovery.c:925 +#: access/transam/xlogrecovery.c:938 #, c-format msgid "" "database system was not properly shut down; automatic recovery in progress" @@ -3625,19 +3902,19 @@ msgstr "" "система БД была остановлена нештатно; производится автоматическое " "восстановление" -#: access/transam/xlogrecovery.c:929 +#: access/transam/xlogrecovery.c:942 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "" "восстановление после сбоя начинается на линии времени %u, целевая линия " "времени: %u" -#: access/transam/xlogrecovery.c:972 +#: access/transam/xlogrecovery.c:985 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label содержит данные, не согласованные с файлом pg_control" -#: access/transam/xlogrecovery.c:973 +#: access/transam/xlogrecovery.c:986 #, c-format msgid "" "This means that the backup is corrupted and you will have to use another " @@ -3646,24 +3923,24 @@ msgstr "" "Это означает, что резервная копия повреждена и для восстановления БД " "придётся использовать другую копию." -#: access/transam/xlogrecovery.c:1027 +#: access/transam/xlogrecovery.c:1040 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "" "использование файла с конфигурацией восстановления \"%s\" не поддерживается" -#: access/transam/xlogrecovery.c:1092 +#: access/transam/xlogrecovery.c:1105 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "" "режим резервного сервера не поддерживается однопользовательским сервером" -#: access/transam/xlogrecovery.c:1109 +#: access/transam/xlogrecovery.c:1122 #, c-format -msgid "specified neither primary_conninfo nor restore_command" -msgstr "не указано ни primary_conninfo, ни restore_command" +msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" +msgstr "не указано ни \"primary_conninfo\", ни \"restore_command\"" -#: access/transam/xlogrecovery.c:1110 +#: access/transam/xlogrecovery.c:1123 #, c-format msgid "" "The database server will regularly poll the pg_wal subdirectory to check for " @@ -3672,111 +3949,128 @@ msgstr "" "Сервер БД будет регулярно опрашивать подкаталог pg_wal и проверять " "содержащиеся в нём файлы." -#: access/transam/xlogrecovery.c:1118 +#: access/transam/xlogrecovery.c:1131 #, c-format -msgid "must specify restore_command when standby mode is not enabled" +msgid "must specify \"restore_command\" when standby mode is not enabled" msgstr "" -"необходимо задать restore_command, если не выбран режим резервного сервера" +"необходимо задать \"restore_command\", если не выбран режим резервного " +"сервера" -#: access/transam/xlogrecovery.c:1156 +#: access/transam/xlogrecovery.c:1169 #, c-format msgid "recovery target timeline %u does not exist" msgstr "целевая линия времени для восстановления %u не существует" -#: access/transam/xlogrecovery.c:1239 access/transam/xlogrecovery.c:1246 -#: access/transam/xlogrecovery.c:1305 access/transam/xlogrecovery.c:1385 -#: access/transam/xlogrecovery.c:1409 +#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 +#: access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 +#: access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 #, c-format msgid "invalid data in file \"%s\"" msgstr "неверные данные в файле \"%s\"" -#: access/transam/xlogrecovery.c:1306 +#: access/transam/xlogrecovery.c:1319 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "Получен идентификатор линии времени %u, но ожидался %u." -#: access/transam/xlogrecovery.c:1688 +#: access/transam/xlogrecovery.c:1330 +#, c-format +msgid "this is an incremental backup, not a data directory" +msgstr "это каталог инкрементальной копии, не каталог данных" + +#: access/transam/xlogrecovery.c:1331 +#, c-format +msgid "Use pg_combinebackup to reconstruct a valid data directory." +msgstr "" +"Реконструируйте полноценный каталог данных, используя pg_combinebackup." + +#: access/transam/xlogrecovery.c:1717 +#, c-format +msgid "unexpected record type found at redo point %X/%X" +msgstr "в точке redo %X/%X обнаружена запись неожиданного типа" + +#: access/transam/xlogrecovery.c:1740 #, c-format msgid "redo starts at %X/%X" msgstr "запись REDO начинается со смещения %X/%X" -#: access/transam/xlogrecovery.c:1701 +#: access/transam/xlogrecovery.c:1753 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "" "выполняется воспроизведение, прошло времени: %ld.%02d с, текущий LSN: %X/%X" -#: access/transam/xlogrecovery.c:1793 +#: access/transam/xlogrecovery.c:1843 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "" "запрошенная точка остановки восстановления предшествует согласованной точке " "восстановления" -#: access/transam/xlogrecovery.c:1825 +#: access/transam/xlogrecovery.c:1875 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "записи REDO обработаны до смещения %X/%X, нагрузка системы: %s" -#: access/transam/xlogrecovery.c:1831 +#: access/transam/xlogrecovery.c:1881 #, c-format msgid "last completed transaction was at log time %s" msgstr "последняя завершённая транзакция была выполнена в %s" -#: access/transam/xlogrecovery.c:1840 +#: access/transam/xlogrecovery.c:1890 #, c-format msgid "redo is not required" msgstr "данные REDO не требуются" -#: access/transam/xlogrecovery.c:1851 +#: access/transam/xlogrecovery.c:1901 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "восстановление окончилось до достижения заданной цели восстановления" -#: access/transam/xlogrecovery.c:2045 +#: access/transam/xlogrecovery.c:2095 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "" "успешно пропущена отсутствующая запись contrecord в %X/%X, перезаписанная в " "%s" -#: access/transam/xlogrecovery.c:2112 +#: access/transam/xlogrecovery.c:2162 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "в %2$s обнаружен недопустимый элемент-каталог \"%1$s\"" -#: access/transam/xlogrecovery.c:2114 +#: access/transam/xlogrecovery.c:2164 #, c-format msgid "All directory entries in pg_tblspc/ should be symbolic links." msgstr "" "Все элементы-каталоги в pg_tblspc/ должны быть символическими ссылками." -#: access/transam/xlogrecovery.c:2115 +#: access/transam/xlogrecovery.c:2165 #, c-format msgid "" -"Remove those directories, or set allow_in_place_tablespaces to ON " +"Remove those directories, or set \"allow_in_place_tablespaces\" to ON " "transiently to let recovery complete." msgstr "" -"Удалите эти каталоги или на время установите в allow_in_place_tablespaces " -"значение ON, чтобы восстановление завершилось." +"Удалите эти каталоги или на время установите в " +"\"allow_in_place_tablespaces\" значение ON, чтобы восстановление завершилось." -#: access/transam/xlogrecovery.c:2167 +#: access/transam/xlogrecovery.c:2217 #, c-format msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" msgstr "завершено восстановление копии с LSN redo %X/%X и конечным LSN %X/%X" -#: access/transam/xlogrecovery.c:2197 +#: access/transam/xlogrecovery.c:2247 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "согласованное состояние восстановления достигнуто в позиции %X/%X" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2235 +#: access/transam/xlogrecovery.c:2285 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "запись REDO в WAL в позиции %X/%X для %s" -#: access/transam/xlogrecovery.c:2333 +#: access/transam/xlogrecovery.c:2383 #, c-format msgid "" "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint " @@ -3785,13 +4079,13 @@ msgstr "" "неожиданный ID предыдущей линии времени %u (ID текущей линии времени %u) в " "записи контрольной точки" -#: access/transam/xlogrecovery.c:2342 +#: access/transam/xlogrecovery.c:2392 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "неожиданный ID линии времени %u (после %u) в записи контрольной точки" # skip-rule: capital-letter-first -#: access/transam/xlogrecovery.c:2358 +#: access/transam/xlogrecovery.c:2408 #, c-format msgid "" "unexpected timeline ID %u in checkpoint record, before reaching minimum " @@ -3800,83 +4094,83 @@ msgstr "" "неожиданный ID линии времени %u в записи контрольной точки, до достижения " "минимальной к. т. %X/%X на линии времени %u" -#: access/transam/xlogrecovery.c:2542 access/transam/xlogrecovery.c:2818 +#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 #, c-format msgid "recovery stopping after reaching consistency" msgstr "" "восстановление останавливается после достижения согласованного состояния" -#: access/transam/xlogrecovery.c:2563 +#: access/transam/xlogrecovery.c:2613 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "восстановление останавливается перед позицией в WAL (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2653 +#: access/transam/xlogrecovery.c:2703 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "" "восстановление останавливается перед фиксированием транзакции %u, время %s" -#: access/transam/xlogrecovery.c:2660 +#: access/transam/xlogrecovery.c:2710 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "" "восстановление останавливается перед прерыванием транзакции %u, время %s" -#: access/transam/xlogrecovery.c:2713 +#: access/transam/xlogrecovery.c:2763 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "восстановление останавливается в точке восстановления \"%s\", время %s" -#: access/transam/xlogrecovery.c:2731 +#: access/transam/xlogrecovery.c:2781 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "восстановление останавливается после позиции в WAL (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2798 +#: access/transam/xlogrecovery.c:2848 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "" "восстановление останавливается после фиксирования транзакции %u, время %s" -#: access/transam/xlogrecovery.c:2806 +#: access/transam/xlogrecovery.c:2856 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "" "восстановление останавливается после прерывания транзакции %u, время %s" -#: access/transam/xlogrecovery.c:2887 +#: access/transam/xlogrecovery.c:2937 #, c-format msgid "pausing at the end of recovery" msgstr "остановка в конце восстановления" -#: access/transam/xlogrecovery.c:2888 +#: access/transam/xlogrecovery.c:2938 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "Выполните pg_wal_replay_resume() для повышения." -#: access/transam/xlogrecovery.c:2891 access/transam/xlogrecovery.c:4628 +#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4679 #, c-format msgid "recovery has paused" msgstr "восстановление приостановлено" -#: access/transam/xlogrecovery.c:2892 +#: access/transam/xlogrecovery.c:2942 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "Выполните pg_wal_replay_resume() для продолжения." -#: access/transam/xlogrecovery.c:3155 +#: access/transam/xlogrecovery.c:3205 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неожиданный ID линии времени %u в сегменте WAL %s, LSN %X/%X, смещение %u" -#: access/transam/xlogrecovery.c:3363 +#: access/transam/xlogrecovery.c:3413 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "не удалось прочитать сегмент WAL %s, LSN %X/%X, смещение %u: %m" -#: access/transam/xlogrecovery.c:3370 +#: access/transam/xlogrecovery.c:3420 #, c-format msgid "" "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" @@ -3884,38 +4178,38 @@ msgstr "" "не удалось прочитать сегмент WAL %s, LSN %X/%X, смещение %u (прочитано байт: " "%d из %zu)" -#: access/transam/xlogrecovery.c:4010 +#: access/transam/xlogrecovery.c:4061 #, c-format msgid "invalid checkpoint location" msgstr "неверное положение контрольной точки" -#: access/transam/xlogrecovery.c:4020 +#: access/transam/xlogrecovery.c:4071 #, c-format msgid "invalid checkpoint record" msgstr "неверная запись контрольной точки" -#: access/transam/xlogrecovery.c:4026 +#: access/transam/xlogrecovery.c:4077 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "неверный ID менеджера ресурсов в записи контрольной точки" -#: access/transam/xlogrecovery.c:4034 +#: access/transam/xlogrecovery.c:4085 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "неверные флаги xl_info в записи контрольной точки" -#: access/transam/xlogrecovery.c:4040 +#: access/transam/xlogrecovery.c:4091 #, c-format msgid "invalid length of checkpoint record" msgstr "неверная длина записи контрольной точки" -#: access/transam/xlogrecovery.c:4094 +#: access/transam/xlogrecovery.c:4145 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "" "новая линия времени %u не является ответвлением линии времени системы БД %u" -#: access/transam/xlogrecovery.c:4108 +#: access/transam/xlogrecovery.c:4159 #, c-format msgid "" "new timeline %u forked off current database system timeline %u before " @@ -3924,30 +4218,30 @@ msgstr "" "новая линия времени %u ответвилась от текущей линии времени базы данных %u " "до текущей точки восстановления %X/%X" -#: access/transam/xlogrecovery.c:4127 +#: access/transam/xlogrecovery.c:4178 #, c-format msgid "new target timeline is %u" msgstr "новая целевая линия времени %u" -#: access/transam/xlogrecovery.c:4330 +#: access/transam/xlogrecovery.c:4381 #, c-format msgid "WAL receiver process shutdown requested" msgstr "получен запрос на выключение процесса приёмника WAL" -#: access/transam/xlogrecovery.c:4390 +#: access/transam/xlogrecovery.c:4441 #, c-format msgid "received promote request" msgstr "получен запрос повышения статуса" -#: access/transam/xlogrecovery.c:4619 +#: access/transam/xlogrecovery.c:4670 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "" "режим горячего резерва невозможен из-за отсутствия достаточных значений " "параметров" -#: access/transam/xlogrecovery.c:4620 access/transam/xlogrecovery.c:4647 -#: access/transam/xlogrecovery.c:4677 +#: access/transam/xlogrecovery.c:4671 access/transam/xlogrecovery.c:4698 +#: access/transam/xlogrecovery.c:4728 #, c-format msgid "" "%s = %d is a lower setting than on the primary server, where its value was " @@ -3955,12 +4249,12 @@ msgid "" msgstr "" "Параметр %s = %d меньше, чем на ведущем сервере, где его значение было %d." -#: access/transam/xlogrecovery.c:4629 +#: access/transam/xlogrecovery.c:4680 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "В случае возобновления восстановления сервер отключится." -#: access/transam/xlogrecovery.c:4630 +#: access/transam/xlogrecovery.c:4681 #, c-format msgid "" "You can then restart the server after making the necessary configuration " @@ -3969,24 +4263,24 @@ msgstr "" "Затем вы можете перезапустить сервер после внесения необходимых изменений " "конфигурации." -#: access/transam/xlogrecovery.c:4641 +#: access/transam/xlogrecovery.c:4692 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "повышение невозможно из-за отсутствия достаточных значений параметров" -#: access/transam/xlogrecovery.c:4651 +#: access/transam/xlogrecovery.c:4702 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "" "Перезапустите сервер после внесения необходимых изменений конфигурации." -#: access/transam/xlogrecovery.c:4675 +#: access/transam/xlogrecovery.c:4726 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "" "восстановление прервано из-за отсутствия достаточных значений параметров" -#: access/transam/xlogrecovery.c:4681 +#: access/transam/xlogrecovery.c:4732 #, c-format msgid "" "You can restart the server after making the necessary configuration changes." @@ -3994,66 +4288,67 @@ msgstr "" "Вы можете перезапустить сервер после внесения необходимых изменений " "конфигурации." -#: access/transam/xlogrecovery.c:4723 +#: access/transam/xlogrecovery.c:4774 #, c-format msgid "multiple recovery targets specified" msgstr "указано несколько целей восстановления" -#: access/transam/xlogrecovery.c:4724 +#: access/transam/xlogrecovery.c:4775 #, c-format msgid "" -"At most one of recovery_target, recovery_target_lsn, recovery_target_name, " -"recovery_target_time, recovery_target_xid may be set." +"At most one of \"recovery_target\", \"recovery_target_lsn\", " +"\"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" " +"may be set." msgstr "" -"Может быть указана только одна из целей: recovery_target, " -"recovery_target_lsn, recovery_target_name, recovery_target_time, " -"recovery_target_xid." +"Может быть указана только одна из целей: \"recovery_target\", " +"\"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", " +"\"recovery_target_xid\"." -#: access/transam/xlogrecovery.c:4735 +#: access/transam/xlogrecovery.c:4786 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "Единственное допустимое значение: \"immediate\"." -#: access/transam/xlogrecovery.c:4887 utils/adt/timestamp.c:186 -#: utils/adt/timestamp.c:439 +#: access/transam/xlogrecovery.c:4938 utils/adt/timestamp.c:202 +#: utils/adt/timestamp.c:455 #, c-format msgid "timestamp out of range: \"%s\"" msgstr "timestamp вне диапазона: \"%s\"" -#: access/transam/xlogrecovery.c:4932 +#: access/transam/xlogrecovery.c:4983 #, c-format -msgid "recovery_target_timeline is not a valid number." -msgstr "recovery_target_timeline не является допустимым числом." +msgid "\"recovery_target_timeline\" is not a valid number." +msgstr "Значение \"recovery_target_timeline\" не является допустимым числом." -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1032 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "не удалось прочитать из сегмента WAL %s по смещению %d: %m" -#: access/transam/xlogutils.c:1046 +#: access/transam/xlogutils.c:1039 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "" "не удалось прочитать из сегмента WAL %s по смещению %d (прочитано байт: %d " "из %d)" -#: archive/shell_archive.c:96 +#: archive/shell_archive.c:98 #, c-format msgid "archive command failed with exit code %d" msgstr "команда архивации завершилась ошибкой с кодом %d" -#: archive/shell_archive.c:98 archive/shell_archive.c:108 -#: archive/shell_archive.c:114 archive/shell_archive.c:123 +#: archive/shell_archive.c:100 archive/shell_archive.c:110 +#: archive/shell_archive.c:116 archive/shell_archive.c:125 #, c-format msgid "The failed archive command was: %s" msgstr "Команда архивации с ошибкой: %s" -#: archive/shell_archive.c:105 +#: archive/shell_archive.c:107 #, c-format msgid "archive command was terminated by exception 0x%X" msgstr "команда архивации была прервана исключением 0x%X" -#: archive/shell_archive.c:107 postmaster/postmaster.c:3678 +#: archive/shell_archive.c:109 postmaster/postmaster.c:3095 #, c-format msgid "" "See C include file \"ntstatus.h\" for a description of the hexadecimal value." @@ -4061,52 +4356,52 @@ msgstr "" "Описание этого шестнадцатеричного значения ищите во включаемом C-файле " "\"ntstatus.h\"" -#: archive/shell_archive.c:112 +#: archive/shell_archive.c:114 #, c-format msgid "archive command was terminated by signal %d: %s" msgstr "команда архивации завершена по сигналу %d: %s" -#: archive/shell_archive.c:121 +#: archive/shell_archive.c:123 #, c-format msgid "archive command exited with unrecognized status %d" -msgstr "команда архивации завершилась с неизвестным кодом состояния %d" +msgstr "команда архивации завершилась с нераспознанным кодом состояния %d" -#: backup/backup_manifest.c:253 +#: backup/backup_manifest.c:254 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "ожидался конец линии времени %u, но обнаружена линия времени %u" -#: backup/backup_manifest.c:277 +#: backup/backup_manifest.c:278 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "ожидалось начало линии времени %u, но обнаружена линия времени %u" -#: backup/backup_manifest.c:304 +#: backup/backup_manifest.c:305 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "начальная линия времени %u не найдена в истории линии времени %u" -#: backup/backup_manifest.c:355 +#: backup/backup_manifest.c:356 #, c-format msgid "could not rewind temporary file" msgstr "не удалось переместиться во временном файле" -#: backup/basebackup.c:470 +#: backup/basebackup.c:479 #, c-format msgid "could not find any WAL files" msgstr "не удалось найти ни одного файла WAL" -#: backup/basebackup.c:485 backup/basebackup.c:500 backup/basebackup.c:509 +#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 #, c-format msgid "could not find WAL file \"%s\"" msgstr "не удалось найти файл WAL \"%s\"" -#: backup/basebackup.c:551 backup/basebackup.c:576 +#: backup/basebackup.c:560 backup/basebackup.c:585 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "неприемлемый размер файла WAL \"%s\"" -#: backup/basebackup.c:646 +#: backup/basebackup.c:656 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" @@ -4114,93 +4409,95 @@ msgstr[0] "всего ошибок контрольных сумм: %lld" msgstr[1] "всего ошибок контрольных сумм: %lld" msgstr[2] "всего ошибок контрольных сумм: %lld" -#: backup/basebackup.c:653 +#: backup/basebackup.c:663 #, c-format msgid "checksum verification failure during base backup" msgstr "при базовом резервном копировании выявлены ошибки контрольных сумм" -#: backup/basebackup.c:722 backup/basebackup.c:731 backup/basebackup.c:742 -#: backup/basebackup.c:759 backup/basebackup.c:768 backup/basebackup.c:779 -#: backup/basebackup.c:796 backup/basebackup.c:805 backup/basebackup.c:817 -#: backup/basebackup.c:841 backup/basebackup.c:855 backup/basebackup.c:866 -#: backup/basebackup.c:877 backup/basebackup.c:890 +#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 +#: backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 +#: backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 +#: backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 +#: backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 #, c-format msgid "duplicate option \"%s\"" msgstr "повторяющийся параметр \"%s\"" -#: backup/basebackup.c:750 +#: backup/basebackup.c:761 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "нераспознанный тип контрольной точки: \"%s\"" -#: backup/basebackup.c:785 +#: backup/basebackup.c:793 +#, c-format +msgid "incremental backups cannot be taken unless WAL summarization is enabled" +msgstr "" +"сделать инкрементальную копию можно, только когда включено обобщение WAL" + +#: backup/basebackup.c:809 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%d вне диапазона, допустимого для параметра \"%s\" (%d .. %d)" -#: backup/basebackup.c:830 +#: backup/basebackup.c:854 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "нераспознанный параметр в манифесте: \"%s\"" -#: backup/basebackup.c:846 -#, c-format -msgid "unrecognized checksum algorithm: \"%s\"" -msgstr "нераспознанный алгоритм расчёта контрольных сумм: \"%s\"" - -#: backup/basebackup.c:881 +#: backup/basebackup.c:905 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "нераспознанный алгоритм сжатия: \"%s\"" -#: backup/basebackup.c:897 +#: backup/basebackup.c:921 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "нераспознанный параметр операции базового копирования: \"%s\"" -#: backup/basebackup.c:908 +#: backup/basebackup.c:932 #, c-format msgid "manifest checksums require a backup manifest" msgstr "контрольные суммы не могут рассчитываться без манифеста копии" # skip-rule: capital-letter-first -#: backup/basebackup.c:917 +#: backup/basebackup.c:941 #, c-format msgid "target detail cannot be used without target" msgstr "доп. информацию о получателе нельзя задать без указания получателя" # skip-rule: capital-letter-first -#: backup/basebackup.c:926 backup/basebackup_target.c:218 +#: backup/basebackup.c:950 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "получатель \"%s\" не принимает доп. информацию" -#: backup/basebackup.c:937 +#: backup/basebackup.c:961 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "параметры сжатия нельзя указывать, если не включено сжатие" -#: backup/basebackup.c:950 +#: backup/basebackup.c:974 #, c-format msgid "invalid compression specification: %s" msgstr "неправильное указание сжатия: %s" -#: backup/basebackup.c:1116 backup/basebackup.c:1298 +#: backup/basebackup.c:1024 +#, c-format +msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" +msgstr "" +"инкрементальной команде BASE_BACKUP должна предшествовать UPLOAD_MANIFEST" + +#: backup/basebackup.c:1157 backup/basebackup.c:1358 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "не удалось получить информацию о файле или каталоге \"%s\": %m" -#: backup/basebackup.c:1434 +#: backup/basebackup.c:1544 #, c-format msgid "skipping special file \"%s\"" msgstr "специальный файл \"%s\" пропускается" -#: backup/basebackup.c:1546 -#, c-format -msgid "invalid segment number %d in file \"%s\"" -msgstr "неверный номер сегмента %d в файле \"%s\"" - -#: backup/basebackup.c:1578 +#: backup/basebackup.c:1751 #, c-format msgid "" "could not verify checksum in file \"%s\", block %u: read buffer size %d and " @@ -4209,7 +4506,15 @@ msgstr "" "не удалось проверить контрольную сумму в файле \"%s\", блоке %u: размер " "прочитанного буфера (%d) отличается от размера страницы (%d)" -#: backup/basebackup.c:1662 +#: backup/basebackup.c:1813 +#, c-format +msgid "file \"%s\" has a total of %d checksum verification failure" +msgid_plural "file \"%s\" has a total of %d checksum verification failures" +msgstr[0] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" +msgstr[1] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" +msgstr[2] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" + +#: backup/basebackup.c:1917 #, c-format msgid "" "checksum verification failed in file \"%s\", block %u: calculated %X but " @@ -4218,27 +4523,19 @@ msgstr "" "ошибка контрольной суммы в файле \"%s\", блоке %u: вычислено значение %X, но " "ожидалось %X" -#: backup/basebackup.c:1669 +#: backup/basebackup.c:1924 #, c-format msgid "" "further checksum verification failures in file \"%s\" will not be reported" msgstr "" "о дальнейших ошибках контрольных сумм в файле \"%s\" сообщаться не будет" -#: backup/basebackup.c:1725 -#, c-format -msgid "file \"%s\" has a total of %d checksum verification failure" -msgid_plural "file \"%s\" has a total of %d checksum verification failures" -msgstr[0] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" -msgstr[1] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" -msgstr[2] "всего в файле \"%s\" обнаружено ошибок контрольных сумм: %d" - -#: backup/basebackup.c:1771 +#: backup/basebackup.c:2048 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "слишком длинное имя файла для формата tar: \"%s\"" -#: backup/basebackup.c:1776 +#: backup/basebackup.c:2053 #, c-format msgid "" "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" @@ -4246,6 +4543,11 @@ msgstr "" "цель символической ссылки слишком длинная для формата tar: имя файла \"%s\", " "цель \"%s\"" +#: backup/basebackup.c:2127 +#, c-format +msgid "could not read file \"%s\": read %zd of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %zd из %zu)" + #: backup/basebackup_gzip.c:67 #, c-format msgid "gzip compression is not supported by this build" @@ -4256,17 +4558,110 @@ msgstr "сжатие gzip не поддерживается в данной сб msgid "could not initialize compression library" msgstr "не удалось инициализировать библиотеку сжатия" +#: backup/basebackup_incremental.c:294 +#, c-format +msgid "manifest contains no required WAL ranges" +msgstr "в манифесте не указаны нужные диапазоны WAL" + +#: backup/basebackup_incremental.c:349 +#, c-format +msgid "timeline %u found in manifest, but not in this server's history" +msgstr "в манифесте найдена линия времени %u, но её нет в истории сервера" + +#: backup/basebackup_incremental.c:414 +#, c-format +msgid "" +"manifest requires WAL from initial timeline %u starting at %X/%X, but that " +"timeline begins at %X/%X" +msgstr "" +"манифест требует наличия WAL с изначальной линии времени %u, начиная с " +"позиции %X/%X, но эта линия времени начинается с %X/%X" + +#: backup/basebackup_incremental.c:424 +#, c-format +msgid "" +"manifest requires WAL from continuation timeline %u starting at %X/%X, but " +"that timeline begins at %X/%X" +msgstr "" +"манифест требует наличия WAL с последующей линии времени %u, начиная с " +"позиции %X/%X, но эта линия времени начинается с %X/%X" + +#: backup/basebackup_incremental.c:435 +#, c-format +msgid "" +"manifest requires WAL from final timeline %u ending at %X/%X, but this " +"backup starts at %X/%X" +msgstr "" +"манифест требует наличия WAL с последней линии времени %u, завершающейся в " +"%X/%X, но эта копия начинается с %X/%X" + +#: backup/basebackup_incremental.c:439 +#, c-format +msgid "" +"This can happen for incremental backups on a standby if there was little " +"activity since the previous backup." +msgstr "" +"Такая ситуация возможна, когда инкрементальная копия создаётся на резервном " +"сервере при незначительной активности после создания предыдущей копии." + +#: backup/basebackup_incremental.c:446 +#, c-format +msgid "" +"manifest requires WAL from non-final timeline %u ending at %X/%X, but this " +"server switched timelines at %X/%X" +msgstr "" +"манифест требует наличия WAL с промежуточной линии времени %u, завершающейся " +"в %X/%X, но этот сервер переключил линии времени в %X/%X" + +#: backup/basebackup_incremental.c:527 +#, c-format +msgid "" +"WAL summaries are required on timeline %u from %X/%X to %X/%X, but no " +"summaries for that timeline and LSN range exist" +msgstr "" +"требуются обобщения WAL для линии времени %u с позиции %X/%X по %X/%X, но " +"они не найдены" + +#: backup/basebackup_incremental.c:534 +#, c-format +msgid "" +"WAL summaries are required on timeline %u from %X/%X to %X/%X, but the " +"summaries for that timeline and LSN range are incomplete" +msgstr "" +"требуются обобщения WAL для линии времени %u с позиции %X/%X по %X/%X, но " +"обобщения для этой линии времени и этого диапазона LSN неполные" + +#: backup/basebackup_incremental.c:538 +#, c-format +msgid "The first unsummarized LSN in this range is %X/%X." +msgstr "Первый необобщённый LSN в этом диапазоне: %X/%X." + +#: backup/basebackup_incremental.c:938 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "" +"с версией 1 манифеста копии инкрементальное копирование не поддерживается" + +#: backup/basebackup_incremental.c:956 +#, c-format +msgid "" +"system identifier in backup manifest is %llu, but database system identifier " +"is %llu" +msgstr "" +"в манифесте копии указан идентификатор системы: %llu, но идентификатор " +"системы базы данных: %llu" + #: backup/basebackup_lz4.c:67 #, c-format msgid "lz4 compression is not supported by this build" msgstr "сжатие lz4 не поддерживается в данной сборке" -#: backup/basebackup_server.c:75 +#: backup/basebackup_server.c:73 #, c-format msgid "permission denied to create backup stored on server" msgstr "нет прав для создания копии, сохраняемой на сервере" -#: backup/basebackup_server.c:76 +#: backup/basebackup_server.c:74 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may create a backup stored on " @@ -4275,40 +4670,41 @@ msgstr "" "Создавать копии, сохраняемые на сервере, могут только роли с правами роли " "\"%s\"." -#: backup/basebackup_server.c:91 +#: backup/basebackup_server.c:89 #, c-format msgid "relative path not allowed for backup stored on server" msgstr "" "для копии, сохраняемой на стороне сервера, нельзя указывать относительный " "путь" -#: backup/basebackup_server.c:104 commands/dbcommands.c:478 -#: commands/tablespace.c:163 commands/tablespace.c:179 -#: commands/tablespace.c:599 commands/tablespace.c:644 replication/slot.c:1731 +#: backup/basebackup_server.c:102 commands/dbcommands.c:477 +#: commands/tablespace.c:157 commands/tablespace.c:173 +#: commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 #: storage/file/copydir.c:47 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не удалось создать каталог \"%s\": %m" -#: backup/basebackup_server.c:117 +#: backup/basebackup_server.c:115 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" существует, но он не пуст" -#: backup/basebackup_server.c:125 utils/init/postinit.c:1164 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1178 #, c-format msgid "could not access directory \"%s\": %m" -msgstr "ошибка доступа к каталогу \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" -#: backup/basebackup_server.c:177 backup/basebackup_server.c:184 -#: backup/basebackup_server.c:270 backup/basebackup_server.c:277 -#: storage/smgr/md.c:504 storage/smgr/md.c:511 storage/smgr/md.c:593 -#: storage/smgr/md.c:615 storage/smgr/md.c:865 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 +#: backup/basebackup_server.c:268 backup/basebackup_server.c:275 +#: backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 +#: storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 #, c-format msgid "Check free disk space." msgstr "Проверьте, есть ли место на диске." -#: backup/basebackup_server.c:181 backup/basebackup_server.c:274 +#: backup/basebackup_server.c:179 backup/basebackup_server.c:272 +#: backup/walsummary.c:309 #, c-format msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" msgstr "" @@ -4340,252 +4736,251 @@ msgstr "не удалось установить для zstd число пото msgid "could not enable long-distance mode: %s" msgstr "не удалось включить режим большой дистанции: %s" -#: bootstrap/bootstrap.c:243 postmaster/postmaster.c:721 tcop/postgres.c:3819 +#: backup/walsummaryfuncs.c:95 +#, c-format +msgid "invalid timeline %lld" +msgstr "неверная линия времени %lld" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3946 #, c-format msgid "--%s requires a value" msgstr "для --%s требуется значение" -#: bootstrap/bootstrap.c:248 postmaster/postmaster.c:726 tcop/postgres.c:3824 +#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3951 #, c-format msgid "-c %s requires a value" msgstr "для -c %s требуется значение" -#: bootstrap/bootstrap.c:289 -#, c-format -msgid "-X requires a power of two value between 1 MB and 1 GB" -msgstr "" -"для -X требуется число, равное степени двух, в интервале от 1 МБ до 1 ГБ" - -#: bootstrap/bootstrap.c:295 postmaster/postmaster.c:844 -#: postmaster/postmaster.c:857 +#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 +#: postmaster/postmaster.c:759 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Для дополнительной информации попробуйте \"%s --help\".\n" -#: bootstrap/bootstrap.c:304 +#: bootstrap/bootstrap.c:291 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: неверные аргументы командной строки\n" -#: catalog/aclchk.c:201 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "право назначения прав можно давать только ролям" -#: catalog/aclchk.c:323 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "для столбца \"%s\" отношения \"%s\" не были назначены никакие права" -#: catalog/aclchk.c:328 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "для объекта \"%s\" не были назначены никакие права" -#: catalog/aclchk.c:336 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "" "для столбца \"%s\" отношения \"%s\" были назначены не все запрошенные права" -#: catalog/aclchk.c:341 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "для объекта \"%s\" были назначены не все запрошенные права" -#: catalog/aclchk.c:352 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "для столбца \"%s\" отношения \"%s\" не были отозваны никакие права" -#: catalog/aclchk.c:357 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "для объекта \"%s\" не были отозваны никакие права" -#: catalog/aclchk.c:365 +#: catalog/aclchk.c:375 #, c-format msgid "" "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "для столбца \"%s\" отношения \"%s\" были отозваны не все права" -#: catalog/aclchk.c:370 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "для объекта \"%s\" были отозваны не все права" -#: catalog/aclchk.c:402 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "праводателем должен быть текущий пользователь" -#: catalog/aclchk.c:470 catalog/aclchk.c:1045 +#: catalog/aclchk.c:480 catalog/aclchk.c:1055 #, c-format msgid "invalid privilege type %s for relation" msgstr "право %s неприменимо для отношений" -#: catalog/aclchk.c:474 catalog/aclchk.c:1049 +#: catalog/aclchk.c:484 catalog/aclchk.c:1059 #, c-format msgid "invalid privilege type %s for sequence" msgstr "право %s неприменимо для последовательностей" -#: catalog/aclchk.c:478 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "право %s неприменимо для баз данных" -#: catalog/aclchk.c:482 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "право %s неприменимо для домена" -#: catalog/aclchk.c:486 catalog/aclchk.c:1053 +#: catalog/aclchk.c:496 catalog/aclchk.c:1063 #, c-format msgid "invalid privilege type %s for function" msgstr "право %s неприменимо для функций" -#: catalog/aclchk.c:490 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "право %s неприменимо для языков" -#: catalog/aclchk.c:494 +#: catalog/aclchk.c:504 #, c-format msgid "invalid privilege type %s for large object" msgstr "право %s неприменимо для больших объектов" -#: catalog/aclchk.c:498 catalog/aclchk.c:1069 +#: catalog/aclchk.c:508 catalog/aclchk.c:1079 #, c-format msgid "invalid privilege type %s for schema" msgstr "право %s неприменимо для схем" -#: catalog/aclchk.c:502 catalog/aclchk.c:1057 +#: catalog/aclchk.c:512 catalog/aclchk.c:1067 #, c-format msgid "invalid privilege type %s for procedure" msgstr "право %s неприменимо для процедур" -#: catalog/aclchk.c:506 catalog/aclchk.c:1061 +#: catalog/aclchk.c:516 catalog/aclchk.c:1071 #, c-format msgid "invalid privilege type %s for routine" msgstr "право %s неприменимо для подпрограмм" -#: catalog/aclchk.c:510 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "право %s неприменимо для табличных пространств" -#: catalog/aclchk.c:514 catalog/aclchk.c:1065 +#: catalog/aclchk.c:524 catalog/aclchk.c:1075 #, c-format msgid "invalid privilege type %s for type" msgstr "право %s неприменимо для типа" -#: catalog/aclchk.c:518 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "право %s неприменимо для обёрток сторонних данных" -#: catalog/aclchk.c:522 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "право %s неприменимо для сторонних серверов" -#: catalog/aclchk.c:526 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "неверный тип прав %s для параметра" -#: catalog/aclchk.c:565 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "права для столбцов применимы только к отношениям" -#: catalog/aclchk.c:728 catalog/aclchk.c:3555 catalog/objectaddress.c:1092 -#: catalog/pg_largeobject.c:116 storage/large_object/inv_api.c:286 +#: catalog/aclchk.c:738 catalog/aclchk.c:3629 catalog/objectaddress.c:1054 +#: catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 #, c-format msgid "large object %u does not exist" msgstr "большой объект %u не существует" -#: catalog/aclchk.c:1102 +#: catalog/aclchk.c:1112 #, c-format msgid "default privileges cannot be set for columns" msgstr "права по умолчанию нельзя определить для столбцов" -#: catalog/aclchk.c:1138 +#: catalog/aclchk.c:1148 #, c-format msgid "permission denied to change default privileges" msgstr "нет полномочий для изменения прав доступа по умолчанию" -#: catalog/aclchk.c:1256 +#: catalog/aclchk.c:1266 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "предложение IN SCHEMA нельзя использовать в GRANT/REVOKE ON SCHEMAS" -#: catalog/aclchk.c:1595 catalog/catalog.c:631 catalog/objectaddress.c:1561 -#: catalog/pg_publication.c:533 commands/analyze.c:390 commands/copy.c:837 -#: commands/sequence.c:1663 commands/tablecmds.c:7342 commands/tablecmds.c:7498 -#: commands/tablecmds.c:7548 commands/tablecmds.c:7622 -#: commands/tablecmds.c:7692 commands/tablecmds.c:7808 -#: commands/tablecmds.c:7902 commands/tablecmds.c:7961 -#: commands/tablecmds.c:8050 commands/tablecmds.c:8080 -#: commands/tablecmds.c:8208 commands/tablecmds.c:8290 -#: commands/tablecmds.c:8424 commands/tablecmds.c:8536 -#: commands/tablecmds.c:12261 commands/tablecmds.c:12442 -#: commands/tablecmds.c:12603 commands/tablecmds.c:13798 -#: commands/tablecmds.c:16329 commands/trigger.c:949 parser/analyze.c:2529 -#: parser/parse_relation.c:737 parser/parse_target.c:1068 -#: parser/parse_type.c:144 parser/parse_utilcmd.c:3422 -#: parser/parse_utilcmd.c:3458 parser/parse_utilcmd.c:3500 utils/adt/acl.c:2876 -#: utils/adt/ruleutils.c:2797 +#: catalog/aclchk.c:1617 catalog/catalog.c:659 catalog/objectaddress.c:1523 +#: catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:951 +#: commands/sequence.c:1655 commands/tablecmds.c:7541 commands/tablecmds.c:7695 +#: commands/tablecmds.c:7745 commands/tablecmds.c:7819 +#: commands/tablecmds.c:7889 commands/tablecmds.c:8019 +#: commands/tablecmds.c:8148 commands/tablecmds.c:8242 +#: commands/tablecmds.c:8343 commands/tablecmds.c:8470 +#: commands/tablecmds.c:8500 commands/tablecmds.c:8642 +#: commands/tablecmds.c:8735 commands/tablecmds.c:8869 +#: commands/tablecmds.c:8981 commands/tablecmds.c:12797 +#: commands/tablecmds.c:12989 commands/tablecmds.c:13150 +#: commands/tablecmds.c:14339 commands/tablecmds.c:16966 commands/trigger.c:942 +#: parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 +#: parser/parse_type.c:144 parser/parse_utilcmd.c:3409 +#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2923 +#: utils/adt/ruleutils.c:2812 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "столбец \"%s\" в таблице \"%s\" не существует" -#: catalog/aclchk.c:1840 +#: catalog/aclchk.c:1862 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" - это индекс" -#: catalog/aclchk.c:1847 commands/tablecmds.c:13955 commands/tablecmds.c:17231 +#: catalog/aclchk.c:1869 commands/tablecmds.c:14496 commands/tablecmds.c:17882 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\" - это составной тип" -#: catalog/aclchk.c:1855 catalog/objectaddress.c:1401 commands/sequence.c:1171 -#: commands/tablecmds.c:254 commands/tablecmds.c:17195 utils/adt/acl.c:2084 -#: utils/adt/acl.c:2114 utils/adt/acl.c:2146 utils/adt/acl.c:2178 -#: utils/adt/acl.c:2206 utils/adt/acl.c:2236 +#: catalog/aclchk.c:1877 catalog/objectaddress.c:1363 commands/tablecmds.c:263 +#: commands/tablecmds.c:17846 utils/adt/acl.c:2107 utils/adt/acl.c:2137 +#: utils/adt/acl.c:2170 utils/adt/acl.c:2206 utils/adt/acl.c:2237 +#: utils/adt/acl.c:2268 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\" - это не последовательность" -#: catalog/aclchk.c:1893 +#: catalog/aclchk.c:1915 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "" "для последовательности \"%s\" применимы только права USAGE, SELECT и UPDATE" -#: catalog/aclchk.c:1910 +#: catalog/aclchk.c:1932 #, c-format msgid "invalid privilege type %s for table" msgstr "право %s неприменимо для таблиц" -#: catalog/aclchk.c:2072 +#: catalog/aclchk.c:2097 #, c-format msgid "invalid privilege type %s for column" msgstr "право %s неприменимо для столбцов" -#: catalog/aclchk.c:2085 +#: catalog/aclchk.c:2110 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "для последовательности \"%s\" применимо только право SELECT" # TO REVIEW -#: catalog/aclchk.c:2275 +#: catalog/aclchk.c:2301 #, c-format msgid "language \"%s\" is not trusted" msgstr "язык \"%s\" не является доверенным" -#: catalog/aclchk.c:2277 +#: catalog/aclchk.c:2303 #, c-format msgid "" "GRANT and REVOKE are not allowed on untrusted languages, because only " @@ -4594,400 +4989,411 @@ msgstr "" "GRANT и REVOKE не допускаются для недоверенных языков, так как использовать " "такие языки могут только суперпользователи." -#: catalog/aclchk.c:2427 +#: catalog/aclchk.c:2454 #, c-format msgid "cannot set privileges of array types" msgstr "для типов массивов нельзя определить права" -#: catalog/aclchk.c:2428 +#: catalog/aclchk.c:2455 #, c-format msgid "Set the privileges of the element type instead." msgstr "Вместо этого установите права для типа элемента." -#: catalog/aclchk.c:2435 catalog/objectaddress.c:1667 +#: catalog/aclchk.c:2459 +#, c-format +msgid "cannot set privileges of multirange types" +msgstr "для мультидиапазонных типов нельзя определить права" + +#: catalog/aclchk.c:2460 +#, c-format +msgid "Set the privileges of the range type instead." +msgstr "Вместо этого установите права для диапазонного типа." + +#: catalog/aclchk.c:2467 catalog/objectaddress.c:1629 #, c-format msgid "\"%s\" is not a domain" msgstr "\"%s\" - это не домен" -#: catalog/aclchk.c:2619 +#: catalog/aclchk.c:2653 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "нераспознанное право: \"%s\"" -#: catalog/aclchk.c:2684 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for aggregate %s" msgstr "нет доступа к агрегату %s" -#: catalog/aclchk.c:2687 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for collation %s" msgstr "нет доступа к правилу сортировки %s" -#: catalog/aclchk.c:2690 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for column %s" msgstr "нет доступа к столбцу %s" -#: catalog/aclchk.c:2693 +#: catalog/aclchk.c:2729 #, c-format msgid "permission denied for conversion %s" msgstr "нет доступа к преобразованию %s" -#: catalog/aclchk.c:2696 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for database %s" msgstr "нет доступа к базе данных %s" -#: catalog/aclchk.c:2699 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for domain %s" msgstr "нет доступа к домену %s" -#: catalog/aclchk.c:2702 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for event trigger %s" msgstr "нет доступа к событийному триггеру %s" -#: catalog/aclchk.c:2705 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for extension %s" msgstr "нет доступа к расширению %s" -#: catalog/aclchk.c:2708 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "нет доступа к обёртке сторонних данных %s" -#: catalog/aclchk.c:2711 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for foreign server %s" msgstr "нет доступа к стороннему серверу %s" -#: catalog/aclchk.c:2714 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for foreign table %s" msgstr "нет доступа к сторонней таблице %s" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for function %s" msgstr "нет доступа к функции %s" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2756 #, c-format msgid "permission denied for index %s" msgstr "нет доступа к индексу %s" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2759 #, c-format msgid "permission denied for language %s" msgstr "нет доступа к языку %s" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2762 #, c-format msgid "permission denied for large object %s" msgstr "нет доступа к большому объекту %s" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2765 #, c-format msgid "permission denied for materialized view %s" msgstr "нет доступа к материализованному представлению %s" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2768 #, c-format msgid "permission denied for operator class %s" msgstr "нет доступа к классу операторов %s" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2771 #, c-format msgid "permission denied for operator %s" msgstr "нет доступа к оператору %s" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2774 #, c-format msgid "permission denied for operator family %s" msgstr "нет доступа к семейству операторов %s" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2777 #, c-format msgid "permission denied for parameter %s" msgstr "нет доступа к параметру %s" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2780 #, c-format msgid "permission denied for policy %s" msgstr "нет доступа к политике %s" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2783 #, c-format msgid "permission denied for procedure %s" msgstr "нет доступа к процедуре %s" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2786 #, c-format msgid "permission denied for publication %s" msgstr "нет доступа к публикации %s" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2789 #, c-format msgid "permission denied for routine %s" msgstr "нет доступа к подпрограмме %s" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2792 #, c-format msgid "permission denied for schema %s" msgstr "нет доступа к схеме %s" -#: catalog/aclchk.c:2759 commands/sequence.c:659 commands/sequence.c:885 -#: commands/sequence.c:927 commands/sequence.c:968 commands/sequence.c:1761 -#: commands/sequence.c:1810 +#: catalog/aclchk.c:2795 commands/sequence.c:654 commands/sequence.c:880 +#: commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 +#: commands/sequence.c:1799 #, c-format msgid "permission denied for sequence %s" msgstr "нет доступа к последовательности %s" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2798 #, c-format msgid "permission denied for statistics object %s" msgstr "нет доступа к объекту статистики %s" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2801 #, c-format msgid "permission denied for subscription %s" msgstr "нет доступа к подписке %s" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2804 #, c-format msgid "permission denied for table %s" msgstr "нет доступа к таблице %s" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2807 #, c-format msgid "permission denied for tablespace %s" msgstr "нет доступа к табличному пространству %s" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2810 #, c-format msgid "permission denied for text search configuration %s" msgstr "нет доступа к конфигурации текстового поиска %s" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2813 #, c-format msgid "permission denied for text search dictionary %s" msgstr "нет доступа к словарю текстового поиска %s" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2816 #, c-format msgid "permission denied for type %s" msgstr "нет доступа к типу %s" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2819 #, c-format msgid "permission denied for view %s" msgstr "нет доступа к представлению %s" -#: catalog/aclchk.c:2819 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of aggregate %s" msgstr "нужно быть владельцем агрегата %s" -#: catalog/aclchk.c:2822 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of collation %s" msgstr "нужно быть владельцем правила сортировки %s" -#: catalog/aclchk.c:2825 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of conversion %s" msgstr "нужно быть владельцем преобразования %s" -#: catalog/aclchk.c:2828 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of database %s" msgstr "нужно быть владельцем базы %s" -#: catalog/aclchk.c:2831 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of domain %s" msgstr "нужно быть владельцем домена %s" -#: catalog/aclchk.c:2834 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of event trigger %s" msgstr "нужно быть владельцем событийного триггера %s" -#: catalog/aclchk.c:2837 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of extension %s" msgstr "нужно быть владельцем расширения %s" -#: catalog/aclchk.c:2840 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "нужно быть владельцем обёртки сторонних данных %s" -#: catalog/aclchk.c:2843 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of foreign server %s" msgstr "нужно быть \"владельцем\" стороннего сервера %s" -#: catalog/aclchk.c:2846 +#: catalog/aclchk.c:2882 #, c-format msgid "must be owner of foreign table %s" msgstr "нужно быть владельцем сторонней таблицы %s" -#: catalog/aclchk.c:2849 +#: catalog/aclchk.c:2885 #, c-format msgid "must be owner of function %s" msgstr "нужно быть владельцем функции %s" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2888 #, c-format msgid "must be owner of index %s" msgstr "нужно быть владельцем индекса %s" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2891 #, c-format msgid "must be owner of language %s" msgstr "нужно быть владельцем языка %s" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2894 #, c-format msgid "must be owner of large object %s" msgstr "нужно быть владельцем большого объекта %s" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2897 #, c-format msgid "must be owner of materialized view %s" msgstr "нужно быть владельцем материализованного представления %s" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2900 #, c-format msgid "must be owner of operator class %s" msgstr "нужно быть владельцем класса операторов %s" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2903 #, c-format msgid "must be owner of operator %s" msgstr "нужно быть владельцем оператора %s" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2906 #, c-format msgid "must be owner of operator family %s" msgstr "нужно быть владельцем семейства операторов %s" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2909 #, c-format msgid "must be owner of procedure %s" msgstr "нужно быть владельцем процедуры %s" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2912 #, c-format msgid "must be owner of publication %s" msgstr "нужно быть владельцем публикации %s" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2915 #, c-format msgid "must be owner of routine %s" msgstr "нужно быть владельцем подпрограммы %s" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2918 #, c-format msgid "must be owner of sequence %s" msgstr "нужно быть владельцем последовательности %s" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2921 #, c-format msgid "must be owner of subscription %s" msgstr "нужно быть владельцем подписки %s" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2924 #, c-format msgid "must be owner of table %s" msgstr "нужно быть владельцем таблицы %s" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2927 #, c-format msgid "must be owner of type %s" msgstr "нужно быть владельцем типа %s" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2930 #, c-format msgid "must be owner of view %s" msgstr "нужно быть владельцем представления %s" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2933 #, c-format msgid "must be owner of schema %s" msgstr "нужно быть владельцем схемы %s" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2936 #, c-format msgid "must be owner of statistics object %s" msgstr "нужно быть владельцем объекта статистики %s" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2939 #, c-format msgid "must be owner of tablespace %s" msgstr "нужно быть владельцем табличного пространства %s" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2942 #, c-format msgid "must be owner of text search configuration %s" msgstr "нужно быть владельцем конфигурации текстового поиска %s" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2945 #, c-format msgid "must be owner of text search dictionary %s" msgstr "нужно быть владельцем словаря текстового поиска %s" -#: catalog/aclchk.c:2923 +#: catalog/aclchk.c:2959 #, c-format msgid "must be owner of relation %s" msgstr "нужно быть владельцем отношения %s" -#: catalog/aclchk.c:2969 +#: catalog/aclchk.c:3005 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "нет доступа к столбцу \"%s\" отношения \"%s\"" -#: catalog/aclchk.c:3104 catalog/aclchk.c:3984 catalog/aclchk.c:4015 +#: catalog/aclchk.c:3162 catalog/aclchk.c:4170 catalog/aclchk.c:4201 #, c-format msgid "%s with OID %u does not exist" msgstr "%s с OID %u не существует" -#: catalog/aclchk.c:3188 catalog/aclchk.c:3207 +#: catalog/aclchk.c:3245 catalog/aclchk.c:3264 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "атрибут %d отношения с OID %u не существует" -#: catalog/aclchk.c:3302 +#: catalog/aclchk.c:3302 catalog/aclchk.c:3365 catalog/aclchk.c:4004 #, c-format msgid "relation with OID %u does not exist" msgstr "отношение с OID %u не существует" -#: catalog/aclchk.c:3476 +#: catalog/aclchk.c:3550 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "ACL параметра с OID %u не существует" -#: catalog/aclchk.c:3640 commands/collationcmds.c:813 -#: commands/publicationcmds.c:1746 +#: catalog/aclchk.c:3723 commands/collationcmds.c:853 +#: commands/publicationcmds.c:1739 #, c-format msgid "schema with OID %u does not exist" msgstr "схема с OID %u не существует" -#: catalog/aclchk.c:3705 utils/cache/typcache.c:390 utils/cache/typcache.c:445 +#: catalog/aclchk.c:3797 catalog/aclchk.c:3824 catalog/aclchk.c:3853 +#: utils/cache/typcache.c:392 utils/cache/typcache.c:447 #, c-format msgid "type with OID %u does not exist" msgstr "тип с OID %u не существует" -#: catalog/catalog.c:449 +#: catalog/catalog.c:477 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "продолжается поиск неиспользованного OID в отношении \"%s\"" -#: catalog/catalog.c:451 +#: catalog/catalog.c:479 #, c-format msgid "" "OID candidates have been checked %llu time, but no unused OID has been found " @@ -5005,7 +5411,7 @@ msgstr[2] "" "Потенциальные OID были проверены %llu раз, но неиспользуемые OID ещё не были " "найдены." -#: catalog/catalog.c:476 +#: catalog/catalog.c:504 #, c-format msgid "new OID has been assigned in relation \"%s\" after %llu retry" msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" @@ -5013,57 +5419,57 @@ msgstr[0] "новый OID был назначен в отношении \"%s\" msgstr[1] "новый OID был назначен в отношении \"%s\" после %llu попыток" msgstr[2] "новый OID был назначен в отношении \"%s\" после %llu попыток" -#: catalog/catalog.c:609 catalog/catalog.c:676 +#: catalog/catalog.c:637 catalog/catalog.c:704 #, c-format msgid "must be superuser to call %s()" msgstr "вызывать %s() может только суперпользователь" -#: catalog/catalog.c:618 +#: catalog/catalog.c:646 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() можно использовать только для системных каталогов" -#: catalog/catalog.c:623 parser/parse_utilcmd.c:2273 +#: catalog/catalog.c:651 parser/parse_utilcmd.c:2270 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "индекс \"%s\" не принадлежит таблице \"%s\"" -#: catalog/catalog.c:640 +#: catalog/catalog.c:668 #, c-format msgid "column \"%s\" is not of type oid" msgstr "столбец \"%s\" имеет тип не oid" -#: catalog/catalog.c:647 +#: catalog/catalog.c:675 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "индекс \"%s\" не является индексом столбца \"%s\"" -#: catalog/dependency.c:553 catalog/pg_shdepend.c:658 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "удалить объект %s нельзя, так как он нужен системе баз данных" -#: catalog/dependency.c:845 catalog/dependency.c:1072 +#: catalog/dependency.c:789 catalog/dependency.c:1016 #, c-format msgid "cannot drop %s because %s requires it" msgstr "удалить объект %s нельзя, так как он нужен объекту %s" -#: catalog/dependency.c:847 catalog/dependency.c:1074 +#: catalog/dependency.c:791 catalog/dependency.c:1018 #, c-format msgid "You can drop %s instead." msgstr "Однако можно удалить %s." -#: catalog/dependency.c:1153 catalog/dependency.c:1162 +#: catalog/dependency.c:1097 catalog/dependency.c:1106 #, c-format msgid "%s depends on %s" msgstr "%s зависит от объекта %s" -#: catalog/dependency.c:1177 catalog/dependency.c:1186 +#: catalog/dependency.c:1121 catalog/dependency.c:1130 #, c-format msgid "drop cascades to %s" msgstr "удаление распространяется на объект %s" -#: catalog/dependency.c:1194 catalog/pg_shdepend.c:823 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -5081,36 +5487,37 @@ msgstr[2] "" "\n" "и ещё %d объектов (см. список в протоколе сервера)" -#: catalog/dependency.c:1206 +#: catalog/dependency.c:1150 #, c-format msgid "cannot drop %s because other objects depend on it" msgstr "удалить объект %s нельзя, так как от него зависят другие объекты" -#: catalog/dependency.c:1209 catalog/dependency.c:1216 -#: catalog/dependency.c:1227 commands/tablecmds.c:1331 -#: commands/tablecmds.c:14442 commands/tablespace.c:466 commands/user.c:1303 -#: commands/vacuum.c:211 commands/view.c:446 libpq/auth.c:326 -#: replication/logical/applyparallelworker.c:1044 replication/syncrep.c:1017 -#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1366 utils/misc/guc.c:3122 -#: utils/misc/guc.c:3158 utils/misc/guc.c:3228 utils/misc/guc.c:6632 -#: utils/misc/guc.c:6666 utils/misc/guc.c:6700 utils/misc/guc.c:6743 -#: utils/misc/guc.c:6785 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 +#: catalog/dependency.c:1171 commands/tablecmds.c:1459 +#: commands/tablecmds.c:15088 commands/tablespace.c:460 commands/user.c:1302 +#: commands/vacuum.c:211 commands/view.c:441 executor/execExprInterp.c:4655 +#: executor/execExprInterp.c:4663 libpq/auth.c:324 +#: replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 +#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1432 utils/misc/guc.c:3169 +#: utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6825 +#: utils/misc/guc.c:6859 utils/misc/guc.c:6893 utils/misc/guc.c:6936 +#: utils/misc/guc.c:6978 #, c-format msgid "%s" msgstr "%s" -#: catalog/dependency.c:1210 catalog/dependency.c:1217 +#: catalog/dependency.c:1154 catalog/dependency.c:1161 #, c-format msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "Для удаления зависимых объектов используйте DROP ... CASCADE." -#: catalog/dependency.c:1214 +#: catalog/dependency.c:1158 #, c-format msgid "cannot drop desired object(s) because other objects depend on them" msgstr "" "удалить запрошенные объекты нельзя, так как от них зависят другие объекты" -#: catalog/dependency.c:1222 +#: catalog/dependency.c:1166 #, c-format msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" @@ -5118,61 +5525,61 @@ msgstr[0] "удаление распространяется на ещё %d об msgstr[1] "удаление распространяется на ещё %d объекта" msgstr[2] "удаление распространяется на ещё %d объектов" -#: catalog/dependency.c:1906 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "константу типа %s здесь использовать нельзя" -#: catalog/dependency.c:2431 parser/parse_relation.c:3413 -#: parser/parse_relation.c:3423 +#: catalog/dependency.c:2375 parser/parse_relation.c:3407 +#: parser/parse_relation.c:3417 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "столбец %d отношения \"%s\" не существует" -#: catalog/heap.c:324 +#: catalog/heap.c:325 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "нет прав для создания отношения \"%s.%s\"" -#: catalog/heap.c:326 +#: catalog/heap.c:327 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "Изменение системного каталога в текущем состоянии запрещено." -#: catalog/heap.c:466 commands/tablecmds.c:2370 commands/tablecmds.c:3043 -#: commands/tablecmds.c:6925 +#: catalog/heap.c:467 commands/tablecmds.c:2495 commands/tablecmds.c:2917 +#: commands/tablecmds.c:7163 #, c-format msgid "tables can have at most %d columns" msgstr "максимальное число столбцов в таблице: %d" -#: catalog/heap.c:484 commands/tablecmds.c:7232 +#: catalog/heap.c:485 commands/tablecmds.c:7432 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "имя столбца \"%s\" конфликтует с системным столбцом" -#: catalog/heap.c:500 +#: catalog/heap.c:501 #, c-format msgid "column name \"%s\" specified more than once" msgstr "имя столбца \"%s\" указано неоднократно" #. translator: first %s is an integer not a name -#: catalog/heap.c:578 +#: catalog/heap.c:579 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "столбец \"%s\" ключа разбиения имеет псевдотип %s" -#: catalog/heap.c:583 +#: catalog/heap.c:584 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "столбец \"%s\" имеет псевдотип %s" -#: catalog/heap.c:614 +#: catalog/heap.c:615 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "составной тип %s не может содержать себя же" #. translator: first %s is an integer not a name -#: catalog/heap.c:669 +#: catalog/heap.c:670 #, c-format msgid "" "no collation was derived for partition key column %s with collatable type %s" @@ -5180,28 +5587,28 @@ msgstr "" "для входящего в ключ разбиения столбца \"%s\" с сортируемым типом %s не " "удалось получить правило сортировки" -#: catalog/heap.c:675 commands/createas.c:203 commands/createas.c:512 +#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:505 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "" "для столбца \"%s\" с сортируемым типом %s не удалось получить правило " "сортировки" -#: catalog/heap.c:1151 catalog/index.c:887 commands/createas.c:408 -#: commands/tablecmds.c:3983 +#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:401 +#: commands/tablecmds.c:4171 #, c-format msgid "relation \"%s\" already exists" msgstr "отношение \"%s\" уже существует" -#: catalog/heap.c:1167 catalog/pg_type.c:434 catalog/pg_type.c:782 -#: catalog/pg_type.c:954 commands/typecmds.c:249 commands/typecmds.c:261 -#: commands/typecmds.c:754 commands/typecmds.c:1169 commands/typecmds.c:1395 -#: commands/typecmds.c:1575 commands/typecmds.c:2546 +#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 +#: catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 +#: commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 +#: commands/typecmds.c:1585 commands/typecmds.c:2556 #, c-format msgid "type \"%s\" already exists" msgstr "тип \"%s\" уже существует" -#: catalog/heap.c:1168 +#: catalog/heap.c:1178 #, c-format msgid "" "A relation has an associated type of the same name, so you must use a name " @@ -5210,54 +5617,54 @@ msgstr "" "С отношением уже связан тип с таким же именем; выберите имя, не " "конфликтующее с существующими типами." -#: catalog/heap.c:1208 +#: catalog/heap.c:1218 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "" "значение relfilenumber для TOAST не задано в режиме двоичного обновления" -#: catalog/heap.c:1219 +#: catalog/heap.c:1229 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "значение OID кучи в pg_class не задано в режиме двоичного обновления" -#: catalog/heap.c:1229 +#: catalog/heap.c:1239 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "значение relfilenumber не задано в режиме двоичного обновления" -#: catalog/heap.c:2122 +#: catalog/heap.c:2130 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "" "добавить ограничение NO INHERIT к секционированной таблице \"%s\" нельзя" -#: catalog/heap.c:2397 +#: catalog/heap.c:2402 #, c-format msgid "check constraint \"%s\" already exists" msgstr "ограничение-проверка \"%s\" уже существует" -#: catalog/heap.c:2567 catalog/index.c:901 catalog/pg_constraint.c:682 -#: commands/tablecmds.c:8911 +#: catalog/heap.c:2574 catalog/index.c:913 catalog/pg_constraint.c:724 +#: commands/tablecmds.c:9356 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "ограничение \"%s\" для отношения \"%s\" уже существует" -#: catalog/heap.c:2574 +#: catalog/heap.c:2581 #, c-format msgid "" "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "" "ограничение \"%s\" конфликтует с ненаследуемым ограничением таблицы \"%s\"" -#: catalog/heap.c:2585 +#: catalog/heap.c:2592 #, c-format msgid "" "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "" "ограничение \"%s\" конфликтует с наследуемым ограничением таблицы \"%s\"" -#: catalog/heap.c:2595 +#: catalog/heap.c:2602 #, c-format msgid "" "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" @@ -5265,71 +5672,71 @@ msgstr "" "ограничение \"%s\" конфликтует с непроверенным (NOT VALID) ограничением " "таблицы \"%s\"" -#: catalog/heap.c:2600 +#: catalog/heap.c:2607 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "слияние ограничения \"%s\" с унаследованным определением" -#: catalog/heap.c:2626 catalog/pg_constraint.c:811 commands/tablecmds.c:2668 -#: commands/tablecmds.c:3195 commands/tablecmds.c:6857 -#: commands/tablecmds.c:15264 commands/tablecmds.c:15405 +#: catalog/heap.c:2633 catalog/pg_constraint.c:853 commands/tablecmds.c:3074 +#: commands/tablecmds.c:3377 commands/tablecmds.c:7089 +#: commands/tablecmds.c:15907 commands/tablecmds.c:16038 #, c-format msgid "too many inheritance parents" msgstr "слишком много родителей в иерархии наследования" -#: catalog/heap.c:2710 +#: catalog/heap.c:2717 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "" "использовать генерируемый столбец \"%s\" в выражении генерируемого столбца " "нельзя" -#: catalog/heap.c:2712 +#: catalog/heap.c:2719 #, c-format msgid "A generated column cannot reference another generated column." msgstr "" "Генерируемый столбец не может ссылаться на другой генерируемый столбец." -#: catalog/heap.c:2718 +#: catalog/heap.c:2725 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "" "в выражении генерируемого столбца нельзя использовать переменные «вся строка»" -#: catalog/heap.c:2719 +#: catalog/heap.c:2726 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "" "Это сделало бы генерируемый столбец зависимым от собственного значения." -#: catalog/heap.c:2774 +#: catalog/heap.c:2781 #, c-format msgid "generation expression is not immutable" msgstr "генерирующее выражение не является постоянным" -#: catalog/heap.c:2802 rewrite/rewriteHandler.c:1297 +#: catalog/heap.c:2809 rewrite/rewriteHandler.c:1276 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "столбец \"%s\" имеет тип %s, но тип выражения по умолчанию %s" -#: catalog/heap.c:2807 commands/prepare.c:334 parser/analyze.c:2753 -#: parser/parse_target.c:593 parser/parse_target.c:883 -#: parser/parse_target.c:893 rewrite/rewriteHandler.c:1302 +#: catalog/heap.c:2814 commands/prepare.c:331 parser/analyze.c:2758 +#: parser/parse_target.c:592 parser/parse_target.c:882 +#: parser/parse_target.c:892 rewrite/rewriteHandler.c:1281 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "Перепишите выражение или преобразуйте его тип." -#: catalog/heap.c:2854 +#: catalog/heap.c:2861 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "в ограничении-проверке можно ссылаться только на таблицу \"%s\"" -#: catalog/heap.c:3160 +#: catalog/heap.c:3167 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "неподдерживаемое сочетание внешнего ключа с ON COMMIT" -#: catalog/heap.c:3161 +#: catalog/heap.c:3168 #, c-format msgid "" "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT " @@ -5337,501 +5744,501 @@ msgid "" msgstr "" "Таблица \"%s\" ссылается на \"%s\", и для них задан разный режим ON COMMIT." -#: catalog/heap.c:3166 +#: catalog/heap.c:3173 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "опустошить таблицу, на которую ссылается внешний ключ, нельзя" -#: catalog/heap.c:3167 +#: catalog/heap.c:3174 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "Таблица \"%s\" ссылается на \"%s\"." -#: catalog/heap.c:3169 +#: catalog/heap.c:3176 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "" "Опустошите таблицу \"%s\" параллельно или используйте TRUNCATE ... CASCADE." -#: catalog/index.c:225 parser/parse_utilcmd.c:2179 +#: catalog/index.c:219 parser/parse_utilcmd.c:2176 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "таблица \"%s\" не может иметь несколько первичных ключей" -#: catalog/index.c:239 +#: catalog/index.c:233 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "для первичных ключей нельзя использовать индексы с NULLS NOT DISTINCT" -#: catalog/index.c:256 +#: catalog/index.c:250 #, c-format msgid "primary keys cannot be expressions" msgstr "первичные ключи не могут быть выражениями" -#: catalog/index.c:273 +#: catalog/index.c:267 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "столбец первичного ключа \"%s\" не помечен как NOT NULL" -#: catalog/index.c:786 catalog/index.c:1942 +#: catalog/index.c:798 catalog/index.c:1915 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "" "пользовательские индексы в таблицах системного каталога не поддерживаются" -#: catalog/index.c:826 +#: catalog/index.c:838 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "" "недетерминированные правила сортировки не поддерживаются для класса " "операторов \"%s\"" -#: catalog/index.c:841 +#: catalog/index.c:853 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "" "параллельное создание индекса в таблицах системного каталога не " "поддерживается" -#: catalog/index.c:850 catalog/index.c:1318 +#: catalog/index.c:862 catalog/index.c:1331 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "" "параллельное создание индекса для ограничений-исключений не поддерживается" -#: catalog/index.c:859 +#: catalog/index.c:871 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "нельзя создать разделяемые индексы после initdb" -#: catalog/index.c:879 commands/createas.c:423 commands/sequence.c:158 +#: catalog/index.c:891 commands/createas.c:416 commands/sequence.c:159 #: parser/parse_utilcmd.c:209 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "отношение \"%s\" уже существует, пропускается" -#: catalog/index.c:929 +#: catalog/index.c:941 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "" "значение OID индекса в pg_class не задано в режиме двоичного обновления" -#: catalog/index.c:939 utils/cache/relcache.c:3731 +#: catalog/index.c:951 utils/cache/relcache.c:3791 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "" "значение relfilenumber для индекса не задано в режиме двоичного обновления" -#: catalog/index.c:2241 +#: catalog/index.c:2214 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY должен быть первым действием в транзакции" -#: catalog/index.c:3675 +#: catalog/index.c:3668 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "переиндексировать временные таблицы других сеансов нельзя" -#: catalog/index.c:3686 commands/indexcmds.c:3607 +#: catalog/index.c:3679 commands/indexcmds.c:3626 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "перестроить нерабочий индекс в таблице TOAST нельзя" -#: catalog/index.c:3702 commands/indexcmds.c:3487 commands/indexcmds.c:3631 -#: commands/tablecmds.c:3398 +#: catalog/index.c:3695 commands/indexcmds.c:3504 commands/indexcmds.c:3650 +#: commands/tablecmds.c:3581 #, c-format msgid "cannot move system relation \"%s\"" msgstr "переместить системную таблицу \"%s\" нельзя" -#: catalog/index.c:3846 +#: catalog/index.c:3832 #, c-format msgid "index \"%s\" was reindexed" msgstr "индекс \"%s\" был перестроен" -#: catalog/index.c:3983 +#: catalog/index.c:3998 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "" "перестроить нерабочий индекс \"%s.%s\" в таблице TOAST нельзя, он " "пропускается" -#: catalog/namespace.c:260 catalog/namespace.c:464 catalog/namespace.c:556 -#: commands/trigger.c:5736 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 +#: commands/trigger.c:5729 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "ссылки между базами не реализованы: \"%s.%s.%s\"" -#: catalog/namespace.c:317 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "для временных таблиц имя схемы не указывается" -#: catalog/namespace.c:398 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "не удалось получить блокировку таблицы \"%s.%s\"" -#: catalog/namespace.c:403 commands/lockcmds.c:144 commands/lockcmds.c:224 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "не удалось получить блокировку таблицы \"%s\"" -#: catalog/namespace.c:431 parser/parse_relation.c:1430 +#: catalog/namespace.c:633 parser/parse_relation.c:1430 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "отношение \"%s.%s\" не существует" -#: catalog/namespace.c:436 parser/parse_relation.c:1443 +#: catalog/namespace.c:638 parser/parse_relation.c:1443 #: parser/parse_relation.c:1451 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "отношение \"%s\" не существует" -#: catalog/namespace.c:502 catalog/namespace.c:3073 commands/extension.c:1611 -#: commands/extension.c:1617 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1607 +#: commands/extension.c:1613 #, c-format msgid "no schema has been selected to create in" msgstr "схема для создания объектов не выбрана" -#: catalog/namespace.c:654 catalog/namespace.c:667 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "во временных схемах других сеансов нельзя создавать отношения" -#: catalog/namespace.c:658 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "создавать временные отношения можно только во временных схемах" -#: catalog/namespace.c:673 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "во временных схемах можно создавать только временные отношения" -#: catalog/namespace.c:2265 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "объект статистики \"%s\" не существует" -#: catalog/namespace.c:2388 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "анализатор текстового поиска \"%s\" не существует" -#: catalog/namespace.c:2514 utils/adt/regproc.c:1439 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "словарь текстового поиска \"%s\" не существует" -#: catalog/namespace.c:2641 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "шаблон текстового поиска \"%s\" не существует" -#: catalog/namespace.c:2767 commands/tsearchcmds.c:1168 -#: utils/adt/regproc.c:1329 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 +#: utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "конфигурация текстового поиска \"%s\" не существует" -#: catalog/namespace.c:2880 parser/parse_expr.c:832 parser/parse_target.c:1260 +#: catalog/namespace.c:3329 parser/parse_expr.c:868 parser/parse_target.c:1259 #, c-format msgid "cross-database references are not implemented: %s" msgstr "ссылки между базами не реализованы: %s" -#: catalog/namespace.c:2886 parser/parse_expr.c:839 parser/parse_target.c:1267 -#: gram.y:18569 gram.y:18609 +#: catalog/namespace.c:3335 parser/parse_expr.c:875 parser/parse_target.c:1266 +#: gram.y:19181 gram.y:19221 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неверное полное имя (слишком много компонентов): %s" -#: catalog/namespace.c:3016 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "перемещать объекты в/из внутренних схем нельзя" -#: catalog/namespace.c:3022 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "перемещать объекты в/из схем TOAST нельзя" -#: catalog/namespace.c:3095 commands/schemacmds.c:264 commands/schemacmds.c:344 -#: commands/tablecmds.c:1276 utils/adt/regproc.c:1668 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 +#: commands/tablecmds.c:1404 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "схема \"%s\" не существует" -#: catalog/namespace.c:3126 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неверное имя отношения (слишком много компонентов): %s" -#: catalog/namespace.c:3693 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "правило сортировки \"%s\" для кодировки \"%s\" не существует" -#: catalog/namespace.c:3748 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "преобразование \"%s\" не существует" -#: catalog/namespace.c:4012 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "нет прав для создания временных таблиц в базе \"%s\"" -#: catalog/namespace.c:4028 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "создавать временные таблицы в процессе восстановления нельзя" -#: catalog/namespace.c:4034 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "создавать временные таблицы во время параллельных операций нельзя" -#: catalog/objectaddress.c:1409 commands/policy.c:96 commands/policy.c:376 -#: commands/tablecmds.c:248 commands/tablecmds.c:290 commands/tablecmds.c:2202 -#: commands/tablecmds.c:12378 +#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 +#: commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2327 +#: commands/tablecmds.c:12925 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\" - это не таблица" -#: catalog/objectaddress.c:1416 commands/tablecmds.c:260 -#: commands/tablecmds.c:17200 commands/view.c:119 +#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 +#: commands/tablecmds.c:17851 commands/view.c:114 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\" - это не представление" -#: catalog/objectaddress.c:1423 commands/matview.c:186 commands/tablecmds.c:266 -#: commands/tablecmds.c:17205 +#: catalog/objectaddress.c:1385 commands/matview.c:199 commands/tablecmds.c:275 +#: commands/tablecmds.c:17856 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\" - это не материализованное представление" -#: catalog/objectaddress.c:1430 commands/tablecmds.c:284 -#: commands/tablecmds.c:17210 +#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 +#: commands/tablecmds.c:17861 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\" - это не сторонняя таблица" -#: catalog/objectaddress.c:1471 +#: catalog/objectaddress.c:1433 #, c-format msgid "must specify relation and object name" msgstr "необходимо указать имя отношения и объекта" -#: catalog/objectaddress.c:1547 catalog/objectaddress.c:1600 +#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 #, c-format msgid "column name must be qualified" msgstr "имя столбца нужно указать в полной форме" -#: catalog/objectaddress.c:1619 +#: catalog/objectaddress.c:1581 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "" "значение по умолчанию для столбца \"%s\" отношения \"%s\" не существует" -#: catalog/objectaddress.c:1656 commands/functioncmds.c:137 -#: commands/tablecmds.c:276 commands/typecmds.c:274 commands/typecmds.c:3691 +#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 +#: commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 #: parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 -#: utils/adt/acl.c:4441 +#: utils/adt/acl.c:4560 #, c-format msgid "type \"%s\" does not exist" msgstr "тип \"%s\" не существует" -#: catalog/objectaddress.c:1775 +#: catalog/objectaddress.c:1737 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "оператор %d (%s, %s) из семейства %s не существует" -#: catalog/objectaddress.c:1806 +#: catalog/objectaddress.c:1768 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "функция %d (%s, %s) из семейства %s не существует" -#: catalog/objectaddress.c:1857 catalog/objectaddress.c:1883 +#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "сопоставление для пользователя \"%s\" на сервере \"%s\" не существует" -#: catalog/objectaddress.c:1872 commands/foreigncmds.c:430 -#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:700 +#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 +#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "сервер \"%s\" не существует" -#: catalog/objectaddress.c:1939 +#: catalog/objectaddress.c:1901 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "публикуемое отношение \"%s\" в публикации \"%s\" не существует" -#: catalog/objectaddress.c:1986 +#: catalog/objectaddress.c:1948 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "публикуемая схема \"%s\" в публикации \"%s\" не существует" -#: catalog/objectaddress.c:2044 +#: catalog/objectaddress.c:2006 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "нераспознанный тип объекта ACL по умолчанию: \"%c\"" -#: catalog/objectaddress.c:2045 +#: catalog/objectaddress.c:2007 #, c-format msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." msgstr "Допустимые типы объектов: \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -#: catalog/objectaddress.c:2096 +#: catalog/objectaddress.c:2058 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "" "ACL по умолчанию для пользователя \"%s\" в схеме \"%s\" для объекта %s не " "существует" -#: catalog/objectaddress.c:2101 +#: catalog/objectaddress.c:2063 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "" "ACL по умолчанию для пользователя \"%s\" и для объекта %s не существует" -#: catalog/objectaddress.c:2127 catalog/objectaddress.c:2184 -#: catalog/objectaddress.c:2239 +#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 +#: catalog/objectaddress.c:2201 #, c-format msgid "name or argument lists may not contain nulls" msgstr "списки имён и аргументов не должны содержать NULL" -#: catalog/objectaddress.c:2161 +#: catalog/objectaddress.c:2123 #, c-format msgid "unsupported object type \"%s\"" msgstr "неподдерживаемый тип объекта: \"%s\"" -#: catalog/objectaddress.c:2180 catalog/objectaddress.c:2197 -#: catalog/objectaddress.c:2262 catalog/objectaddress.c:2346 +#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 +#: catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 #, c-format msgid "name list length must be exactly %d" msgstr "длина списка имён должна быть равна %d" -#: catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2163 #, c-format msgid "large object OID may not be null" msgstr "OID большого объекта не может быть NULL" -#: catalog/objectaddress.c:2210 catalog/objectaddress.c:2280 -#: catalog/objectaddress.c:2287 +#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 +#: catalog/objectaddress.c:2249 #, c-format msgid "name list length must be at least %d" msgstr "длина списка аргументов должна быть не меньше %d" -#: catalog/objectaddress.c:2273 catalog/objectaddress.c:2294 +#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 #, c-format msgid "argument list length must be exactly %d" msgstr "длина списка аргументов должна быть равна %d" -#: catalog/objectaddress.c:2508 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 #, c-format msgid "must be owner of large object %u" msgstr "нужно быть владельцем большого объекта %u" -#: catalog/objectaddress.c:2523 commands/functioncmds.c:1561 +#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 #, c-format msgid "must be owner of type %s or type %s" msgstr "это разрешено только владельцу типа %s или %s" -#: catalog/objectaddress.c:2550 catalog/objectaddress.c:2559 -#: catalog/objectaddress.c:2565 +#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 +#: catalog/objectaddress.c:2527 #, c-format msgid "permission denied" msgstr "нет доступа" -#: catalog/objectaddress.c:2551 catalog/objectaddress.c:2560 +#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 #, c-format msgid "The current user must have the %s attribute." msgstr "Текущий пользователь должен иметь атрибут %s." -#: catalog/objectaddress.c:2566 +#: catalog/objectaddress.c:2528 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "Текущий пользователь должен иметь привилегию %s для роли \"%s\"." -#: catalog/objectaddress.c:2580 +#: catalog/objectaddress.c:2542 #, c-format msgid "must be superuser" msgstr "требуются права суперпользователя" -#: catalog/objectaddress.c:2649 +#: catalog/objectaddress.c:2611 #, c-format msgid "unrecognized object type \"%s\"" msgstr "нераспознанный тип объекта \"%s\"" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2941 +#: catalog/objectaddress.c:2928 #, c-format msgid "column %s of %s" msgstr "столбец %s отношения %s" -#: catalog/objectaddress.c:2956 +#: catalog/objectaddress.c:2943 #, c-format msgid "function %s" msgstr "функция %s" -#: catalog/objectaddress.c:2969 +#: catalog/objectaddress.c:2956 #, c-format msgid "type %s" msgstr "тип %s" -#: catalog/objectaddress.c:3006 +#: catalog/objectaddress.c:2993 #, c-format msgid "cast from %s to %s" msgstr "приведение %s к %s" -#: catalog/objectaddress.c:3039 +#: catalog/objectaddress.c:3026 #, c-format msgid "collation %s" msgstr "правило сортировки %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3057 #, c-format msgid "constraint %s on %s" msgstr "ограничение %s в отношении %s" -#: catalog/objectaddress.c:3076 +#: catalog/objectaddress.c:3063 #, c-format msgid "constraint %s" msgstr "ограничение %s" -#: catalog/objectaddress.c:3108 +#: catalog/objectaddress.c:3095 #, c-format msgid "conversion %s" msgstr "преобразование %s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3130 +#: catalog/objectaddress.c:3117 #, c-format msgid "default value for %s" msgstr "значение по умолчанию для %s" -#: catalog/objectaddress.c:3141 +#: catalog/objectaddress.c:3128 #, c-format msgid "language %s" msgstr "язык %s" -#: catalog/objectaddress.c:3149 +#: catalog/objectaddress.c:3136 #, c-format msgid "large object %u" msgstr "большой объект %u" -#: catalog/objectaddress.c:3162 +#: catalog/objectaddress.c:3149 #, c-format msgid "operator %s" msgstr "оператор %s" -#: catalog/objectaddress.c:3199 +#: catalog/objectaddress.c:3186 #, c-format msgid "operator class %s for access method %s" msgstr "класс операторов %s для метода доступа %s" -#: catalog/objectaddress.c:3227 +#: catalog/objectaddress.c:3214 #, c-format msgid "access method %s" msgstr "метод доступа %s" @@ -5840,7 +6247,7 @@ msgstr "метод доступа %s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3276 +#: catalog/objectaddress.c:3269 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "оператор %d (%s, %s) из семейства \"%s\": %s" @@ -5849,241 +6256,241 @@ msgstr "оператор %d (%s, %s) из семейства \"%s\": %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3333 +#: catalog/objectaddress.c:3334 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "функция %d (%s, %s) из семейства \"%s\": %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3385 +#: catalog/objectaddress.c:3388 #, c-format msgid "rule %s on %s" msgstr "правило %s для отношения %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3431 +#: catalog/objectaddress.c:3434 #, c-format msgid "trigger %s on %s" msgstr "триггер %s в отношении %s" -#: catalog/objectaddress.c:3451 +#: catalog/objectaddress.c:3454 #, c-format msgid "schema %s" msgstr "схема %s" -#: catalog/objectaddress.c:3479 +#: catalog/objectaddress.c:3482 #, c-format msgid "statistics object %s" msgstr "объект статистики %s" -#: catalog/objectaddress.c:3510 +#: catalog/objectaddress.c:3513 #, c-format msgid "text search parser %s" msgstr "анализатор текстового поиска %s" -#: catalog/objectaddress.c:3541 +#: catalog/objectaddress.c:3544 #, c-format msgid "text search dictionary %s" msgstr "словарь текстового поиска %s" -#: catalog/objectaddress.c:3572 +#: catalog/objectaddress.c:3575 #, c-format msgid "text search template %s" msgstr "шаблон текстового поиска %s" -#: catalog/objectaddress.c:3603 +#: catalog/objectaddress.c:3606 #, c-format msgid "text search configuration %s" msgstr "конфигурация текстового поиска %s" -#: catalog/objectaddress.c:3616 +#: catalog/objectaddress.c:3619 #, c-format msgid "role %s" msgstr "роль %s" -#: catalog/objectaddress.c:3653 catalog/objectaddress.c:5505 +#: catalog/objectaddress.c:3656 catalog/objectaddress.c:5505 #, c-format msgid "membership of role %s in role %s" msgstr "членство роли %s в роли %s" -#: catalog/objectaddress.c:3674 +#: catalog/objectaddress.c:3677 #, c-format msgid "database %s" msgstr "база данных %s" -#: catalog/objectaddress.c:3690 +#: catalog/objectaddress.c:3693 #, c-format msgid "tablespace %s" msgstr "табличное пространство %s" -#: catalog/objectaddress.c:3701 +#: catalog/objectaddress.c:3704 #, c-format msgid "foreign-data wrapper %s" msgstr "обёртка сторонних данных %s" -#: catalog/objectaddress.c:3711 +#: catalog/objectaddress.c:3714 #, c-format msgid "server %s" msgstr "сервер %s" -#: catalog/objectaddress.c:3744 +#: catalog/objectaddress.c:3747 #, c-format msgid "user mapping for %s on server %s" msgstr "сопоставление для пользователя %s на сервере %s" -#: catalog/objectaddress.c:3796 +#: catalog/objectaddress.c:3799 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "" "права по умолчанию для новых отношений, принадлежащих роли %s в схеме %s" -#: catalog/objectaddress.c:3800 +#: catalog/objectaddress.c:3803 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "права по умолчанию для новых отношений, принадлежащих роли %s" -#: catalog/objectaddress.c:3806 +#: catalog/objectaddress.c:3809 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "" "права по умолчанию для новых последовательностей, принадлежащих роли %s в " "схеме %s" -#: catalog/objectaddress.c:3810 +#: catalog/objectaddress.c:3813 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "" "права по умолчанию для новых последовательностей, принадлежащих роли %s" -#: catalog/objectaddress.c:3816 +#: catalog/objectaddress.c:3819 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "права по умолчанию для новых функций, принадлежащих роли %s в схеме %s" -#: catalog/objectaddress.c:3820 +#: catalog/objectaddress.c:3823 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "права по умолчанию для новых функций, принадлежащих роли %s" -#: catalog/objectaddress.c:3826 +#: catalog/objectaddress.c:3829 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "права по умолчанию для новых типов, принадлежащих роли %s в схеме %s" -#: catalog/objectaddress.c:3830 +#: catalog/objectaddress.c:3833 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "права по умолчанию для новых типов, принадлежащих роли %s" -#: catalog/objectaddress.c:3836 +#: catalog/objectaddress.c:3839 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "права по умолчанию для новых схем, принадлежащих роли %s" -#: catalog/objectaddress.c:3843 +#: catalog/objectaddress.c:3846 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "" "права по умолчанию для новых объектов, принадлежащих роли %s в схеме %s" -#: catalog/objectaddress.c:3847 +#: catalog/objectaddress.c:3850 #, c-format msgid "default privileges belonging to role %s" msgstr "права по умолчанию для новых объектов, принадлежащих роли %s" -#: catalog/objectaddress.c:3869 +#: catalog/objectaddress.c:3872 #, c-format msgid "extension %s" msgstr "расширение %s" -#: catalog/objectaddress.c:3886 +#: catalog/objectaddress.c:3889 #, c-format msgid "event trigger %s" msgstr "событийный триггер %s" -#: catalog/objectaddress.c:3910 +#: catalog/objectaddress.c:3913 #, c-format msgid "parameter %s" msgstr "параметр %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3953 +#: catalog/objectaddress.c:3956 #, c-format msgid "policy %s on %s" msgstr "политика %s отношения %s" -#: catalog/objectaddress.c:3967 +#: catalog/objectaddress.c:3970 #, c-format msgid "publication %s" msgstr "публикация %s" -#: catalog/objectaddress.c:3980 +#: catalog/objectaddress.c:3983 #, c-format msgid "publication of schema %s in publication %s" msgstr "публикация схемы %s в публикации %s" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:4011 +#: catalog/objectaddress.c:4014 #, c-format msgid "publication of %s in publication %s" msgstr "публикуемое отношение %s в публикации %s" -#: catalog/objectaddress.c:4024 +#: catalog/objectaddress.c:4027 #, c-format msgid "subscription %s" msgstr "подписка %s" -#: catalog/objectaddress.c:4045 +#: catalog/objectaddress.c:4048 #, c-format msgid "transform for %s language %s" msgstr "преобразование для %s, языка %s" -#: catalog/objectaddress.c:4116 +#: catalog/objectaddress.c:4117 #, c-format msgid "table %s" msgstr "таблица %s" -#: catalog/objectaddress.c:4121 +#: catalog/objectaddress.c:4122 #, c-format msgid "index %s" msgstr "индекс %s" -#: catalog/objectaddress.c:4125 +#: catalog/objectaddress.c:4126 #, c-format msgid "sequence %s" msgstr "последовательность %s" -#: catalog/objectaddress.c:4129 +#: catalog/objectaddress.c:4130 #, c-format msgid "toast table %s" msgstr "TOAST-таблица %s" -#: catalog/objectaddress.c:4133 +#: catalog/objectaddress.c:4134 #, c-format msgid "view %s" msgstr "представление %s" -#: catalog/objectaddress.c:4137 +#: catalog/objectaddress.c:4138 #, c-format msgid "materialized view %s" msgstr "материализованное представление %s" -#: catalog/objectaddress.c:4141 +#: catalog/objectaddress.c:4142 #, c-format msgid "composite type %s" msgstr "составной тип %s" -#: catalog/objectaddress.c:4145 +#: catalog/objectaddress.c:4146 #, c-format msgid "foreign table %s" msgstr "сторонняя таблица %s" -#: catalog/objectaddress.c:4150 +#: catalog/objectaddress.c:4151 #, c-format msgid "relation %s" msgstr "отношение %s" -#: catalog/objectaddress.c:4191 +#: catalog/objectaddress.c:4192 #, c-format msgid "operator family %s for access method %s" msgstr "семейство операторов %s для метода доступа %s" @@ -6136,7 +6543,7 @@ msgstr "" msgid "return type of inverse transition function %s is not %s" msgstr "обратная функция перехода %s должна возвращать тип %s" -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3009 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2991 #, c-format msgid "" "strictness of aggregate's forward and inverse transition functions must match" @@ -6155,7 +6562,7 @@ msgstr "" msgid "return type of combine function %s is not %s" msgstr "комбинирующая функция %s должна возвращать тип %s" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3903 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "" @@ -6172,12 +6579,12 @@ msgstr "функция сериализации %s должна возвраща msgid "return type of deserialization function %s is not %s" msgstr "функция десериализации %s должна возвращать тип %s" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:191 catalog/pg_proc.c:225 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 #, c-format msgid "cannot determine result data type" msgstr "не удалось определить тип результата" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:204 catalog/pg_proc.c:233 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "небезопасное использование псевдотипа \"internal\"" @@ -6198,7 +6605,7 @@ msgstr "" "оператор сортировки можно указать только для агрегатных функций с одним " "аргументом" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:386 +#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 #, c-format msgid "cannot change routine kind" msgstr "тип подпрограммы изменить нельзя" @@ -6223,13 +6630,13 @@ msgstr "\"%s\" — гипотезирующая агрегатная функц msgid "cannot change number of direct arguments of an aggregate function" msgstr "изменить число непосредственных аргументов агрегатной функции нельзя" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:691 -#: commands/typecmds.c:1975 commands/typecmds.c:2021 commands/typecmds.c:2073 -#: commands/typecmds.c:2110 commands/typecmds.c:2144 commands/typecmds.c:2178 -#: commands/typecmds.c:2212 commands/typecmds.c:2241 commands/typecmds.c:2328 -#: commands/typecmds.c:2370 parser/parse_func.c:417 parser/parse_func.c:448 +#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 +#: commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 +#: commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 +#: commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 +#: commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 #: parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 -#: parser/parse_func.c:631 parser/parse_func.c:2171 parser/parse_func.c:2444 +#: parser/parse_func.c:631 parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "функция %s не существует" @@ -6306,69 +6713,69 @@ msgstr "Эта операция не поддерживается для сек msgid "This operation is not supported for partitioned indexes." msgstr "Эта операция не поддерживается для секционированных индексов." -#: catalog/pg_collation.c:102 catalog/pg_collation.c:160 +#: catalog/pg_collation.c:101 catalog/pg_collation.c:159 #, c-format msgid "collation \"%s\" already exists, skipping" msgstr "правило сортировки \"%s\" уже существует, пропускается" -#: catalog/pg_collation.c:104 +#: catalog/pg_collation.c:103 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists, skipping" msgstr "" "правило сортировки \"%s\" для кодировки \"%s\" уже существует, пропускается" -#: catalog/pg_collation.c:112 catalog/pg_collation.c:167 +#: catalog/pg_collation.c:111 catalog/pg_collation.c:166 #, c-format msgid "collation \"%s\" already exists" msgstr "правило сортировки \"%s\" уже существует" -#: catalog/pg_collation.c:114 +#: catalog/pg_collation.c:113 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "правило сортировки \"%s\" для кодировки \"%s\" уже существует" -#: catalog/pg_constraint.c:690 +#: catalog/pg_constraint.c:732 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "ограничение \"%s\" для домена %s уже существует" -#: catalog/pg_constraint.c:890 catalog/pg_constraint.c:983 +#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "ограничение \"%s\" для таблицы \"%s\" не существует" -#: catalog/pg_constraint.c:1083 +#: catalog/pg_constraint.c:1125 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "ограничение \"%s\" для домена %s не существует" -#: catalog/pg_conversion.c:67 +#: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" msgstr "преобразование \"%s\" уже существует" -#: catalog/pg_conversion.c:80 +#: catalog/pg_conversion.c:77 #, c-format msgid "default conversion for %s to %s already exists" msgstr "преобразование по умолчанию из %s в %s уже существует" -#: catalog/pg_depend.c:222 commands/extension.c:3368 +#: catalog/pg_depend.c:224 commands/extension.c:3397 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "%s уже относится к расширению \"%s\"" -#: catalog/pg_depend.c:229 catalog/pg_depend.c:280 commands/extension.c:3408 +#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "%s не относится к расширению \"%s\"" -#: catalog/pg_depend.c:232 +#: catalog/pg_depend.c:234 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "" "Расширениям не разрешается заменять объекты, которые им не принадлежат." -#: catalog/pg_depend.c:283 +#: catalog/pg_depend.c:285 #, c-format msgid "" "An extension may only use CREATE ... IF NOT EXISTS to skip object creation " @@ -6377,55 +6784,55 @@ msgstr "" "Расширение может выполнять CREATE ... IF NOT EXISTS только для того, чтобы " "не создавать объект, когда оно уже владеет конфликтующим объектом." -#: catalog/pg_depend.c:646 +#: catalog/pg_depend.c:648 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "" "ликвидировать зависимость от объекта %s нельзя, так как это системный объект" -#: catalog/pg_enum.c:137 catalog/pg_enum.c:259 catalog/pg_enum.c:554 +#: catalog/pg_enum.c:175 catalog/pg_enum.c:314 catalog/pg_enum.c:624 #, c-format msgid "invalid enum label \"%s\"" msgstr "неверная метка в перечислении \"%s\"" -#: catalog/pg_enum.c:138 catalog/pg_enum.c:260 catalog/pg_enum.c:555 +#: catalog/pg_enum.c:176 catalog/pg_enum.c:315 catalog/pg_enum.c:625 #, c-format msgid "Labels must be %d bytes or less." msgstr "Длина метки не должна превышать %d байт." -#: catalog/pg_enum.c:288 +#: catalog/pg_enum.c:343 #, c-format msgid "enum label \"%s\" already exists, skipping" msgstr "метка перечисления \"%s\" уже существует, пропускается" -#: catalog/pg_enum.c:295 catalog/pg_enum.c:598 +#: catalog/pg_enum.c:350 catalog/pg_enum.c:668 #, c-format msgid "enum label \"%s\" already exists" msgstr "метка перечисления \"%s\" уже существует" -#: catalog/pg_enum.c:350 catalog/pg_enum.c:593 +#: catalog/pg_enum.c:405 catalog/pg_enum.c:663 #, c-format msgid "\"%s\" is not an existing enum label" msgstr "в перечислении нет метки\"%s\"" -#: catalog/pg_enum.c:408 +#: catalog/pg_enum.c:463 #, c-format msgid "pg_enum OID value not set when in binary upgrade mode" msgstr "значение OID в pg_enum не задано в режиме двоичного обновления" -#: catalog/pg_enum.c:418 +#: catalog/pg_enum.c:473 #, c-format msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade" msgstr "" "конструкция ALTER TYPE ADD BEFORE/AFTER несовместима с двоичным обновлением " "данных" -#: catalog/pg_inherits.c:593 +#: catalog/pg_inherits.c:592 #, c-format msgid "cannot detach partition \"%s\"" msgstr "отсоединить секцию \"%s\" нельзя" -#: catalog/pg_inherits.c:595 +#: catalog/pg_inherits.c:594 #, c-format msgid "" "The partition is being detached concurrently or has an unfinished detach." @@ -6433,8 +6840,8 @@ msgstr "" "Эта секция отсоединяется параллельно или для неё не была завершена операция " "отсоединения." -#: catalog/pg_inherits.c:596 commands/tablecmds.c:4579 -#: commands/tablecmds.c:15520 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4800 +#: commands/tablecmds.c:16153 #, c-format msgid "" "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending " @@ -6443,12 +6850,12 @@ msgstr "" "Чтобы завершить неоконченную операцию отсоединения, выполните команду ALTER " "TABLE ... DETACH PARTITION ... FINALIZE." -#: catalog/pg_inherits.c:600 +#: catalog/pg_inherits.c:599 #, c-format msgid "cannot complete detaching partition \"%s\"" msgstr "завершить отсоединение секции \"%s\" нельзя" -#: catalog/pg_inherits.c:602 +#: catalog/pg_inherits.c:601 #, c-format msgid "There's no pending concurrent detach." msgstr "На данный момент все операции отсоединения завершены." @@ -6458,84 +6865,98 @@ msgstr "На данный момент все операции отсоедин msgid "schema \"%s\" already exists" msgstr "схема \"%s\" уже существует" -#: catalog/pg_operator.c:219 catalog/pg_operator.c:361 +#: catalog/pg_operator.c:213 catalog/pg_operator.c:355 #, c-format msgid "\"%s\" is not a valid operator name" msgstr "имя \"%s\" недопустимо для оператора" -#: catalog/pg_operator.c:370 +#: catalog/pg_operator.c:379 +#, c-format +msgid "operator %s already exists" +msgstr "оператор %s уже существует" + +#: catalog/pg_operator.c:445 commands/operatorcmds.c:600 +#, c-format +msgid "operator cannot be its own negator" +msgstr "оператор не может быть обратным к себе" + +#: catalog/pg_operator.c:572 #, c-format msgid "only binary operators can have commutators" msgstr "коммутативную операцию можно определить только для бинарных операторов" -#: catalog/pg_operator.c:374 commands/operatorcmds.c:509 +#: catalog/pg_operator.c:576 #, c-format msgid "only binary operators can have join selectivity" msgstr "" "функцию оценки соединения можно определить только для бинарных операторов" -#: catalog/pg_operator.c:378 +#: catalog/pg_operator.c:580 #, c-format msgid "only binary operators can merge join" msgstr "" "поддержку соединения слиянием можно обозначить только для бинарных операторов" -#: catalog/pg_operator.c:382 +#: catalog/pg_operator.c:584 #, c-format msgid "only binary operators can hash" msgstr "поддержку хеша можно обозначить только для бинарных операторов" -#: catalog/pg_operator.c:393 +#: catalog/pg_operator.c:593 #, c-format msgid "only boolean operators can have negators" msgstr "обратную операцию можно определить только для логических операторов" -#: catalog/pg_operator.c:397 commands/operatorcmds.c:517 +#: catalog/pg_operator.c:597 #, c-format msgid "only boolean operators can have restriction selectivity" msgstr "" "функцию оценки ограничения можно определить только для логических операторов" -#: catalog/pg_operator.c:401 commands/operatorcmds.c:521 +#: catalog/pg_operator.c:601 #, c-format msgid "only boolean operators can have join selectivity" msgstr "" "функцию оценки соединения можно определить только для логических операторов" -#: catalog/pg_operator.c:405 +#: catalog/pg_operator.c:605 #, c-format msgid "only boolean operators can merge join" msgstr "" "поддержку соединения слиянием можно обозначить только для логических " "операторов" -#: catalog/pg_operator.c:409 +#: catalog/pg_operator.c:609 #, c-format msgid "only boolean operators can hash" msgstr "поддержку хеша можно обозначить только для логических операторов" -#: catalog/pg_operator.c:421 +#: catalog/pg_operator.c:739 #, c-format -msgid "operator %s already exists" -msgstr "оператор %s уже существует" +msgid "commutator operator %s is already the commutator of operator %s" +msgstr "коммутирующий оператор %s уже является коммутирующим для оператора %s" -#: catalog/pg_operator.c:621 +#: catalog/pg_operator.c:744 #, c-format -msgid "operator cannot be its own negator or sort operator" -msgstr "" -"оператор не может быть обратным к себе или собственным оператором сортировки" +msgid "commutator operator %s is already the commutator of operator %u" +msgstr "коммутирующий оператор %s уже является коммутирующим для оператора %u" -#: catalog/pg_parameter_acl.c:53 +#: catalog/pg_operator.c:807 #, c-format -msgid "parameter ACL \"%s\" does not exist" -msgstr "ACL параметра \"%s\" не существует" +msgid "negator operator %s is already the negator of operator %s" +msgstr "обратный оператор %s уже является обратным для оператора %s" + +#: catalog/pg_operator.c:812 +#, c-format +msgid "negator operator %s is already the negator of operator %u" +msgstr "обратный оператор %s уже является обратным для оператора %u" -#: catalog/pg_parameter_acl.c:88 +#: catalog/pg_parameter_acl.c:50 #, c-format -msgid "invalid parameter name \"%s\"" -msgstr "неверное имя параметра \"%s\"" +msgid "parameter ACL \"%s\" does not exist" +msgstr "ACL параметра \"%s\" не существует" -#: catalog/pg_proc.c:132 parser/parse_func.c:2233 +#: catalog/pg_proc.c:130 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" @@ -6543,37 +6964,37 @@ msgstr[0] "функции не могут иметь больше %d аргум msgstr[1] "функции не могут иметь больше %d аргументов" msgstr[2] "функции не могут иметь больше %d аргументов" -#: catalog/pg_proc.c:376 +#: catalog/pg_proc.c:374 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "функция \"%s\" с аргументами таких типов уже существует" -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:386 #, c-format msgid "\"%s\" is an aggregate function." msgstr "\"%s\" — агрегатная функция." -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:388 #, c-format msgid "\"%s\" is a function." msgstr "\"%s\" — функция." -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:390 #, c-format msgid "\"%s\" is a procedure." msgstr "\"%s\" — процедура." -#: catalog/pg_proc.c:394 +#: catalog/pg_proc.c:392 #, c-format msgid "\"%s\" is a window function." msgstr "\"%s\" — оконная функция." -#: catalog/pg_proc.c:414 +#: catalog/pg_proc.c:412 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "определить выходные параметры для процедуры нельзя" -#: catalog/pg_proc.c:415 catalog/pg_proc.c:445 +#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 #, c-format msgid "cannot change return type of existing function" msgstr "изменить тип возврата существующей функции нельзя" @@ -6582,118 +7003,118 @@ msgstr "изменить тип возврата существующей фун #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:421 catalog/pg_proc.c:448 catalog/pg_proc.c:493 -#: catalog/pg_proc.c:519 catalog/pg_proc.c:543 +#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 +#: catalog/pg_proc.c:517 catalog/pg_proc.c:541 #, c-format msgid "Use %s %s first." msgstr "Сначала выполните %s %s." -#: catalog/pg_proc.c:446 +#: catalog/pg_proc.c:444 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "Параметры OUT определяют другой тип строки." -#: catalog/pg_proc.c:490 +#: catalog/pg_proc.c:488 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "изменить имя входного параметра \"%s\" нельзя" -#: catalog/pg_proc.c:517 +#: catalog/pg_proc.c:515 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "" "для существующей функции нельзя убрать значения параметров по умолчанию" -#: catalog/pg_proc.c:541 +#: catalog/pg_proc.c:539 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "" "для существующего значения параметра по умолчанию нельзя изменить тип данных" -#: catalog/pg_proc.c:752 +#: catalog/pg_proc.c:750 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "встроенной функции \"%s\" нет" -#: catalog/pg_proc.c:845 +#: catalog/pg_proc.c:843 #, c-format msgid "SQL functions cannot return type %s" msgstr "SQL-функции не могут возвращать тип %s" -#: catalog/pg_proc.c:860 +#: catalog/pg_proc.c:858 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "SQL-функции не могут иметь аргументы типа %s" -#: catalog/pg_proc.c:988 executor/functions.c:1467 +#: catalog/pg_proc.c:986 executor/functions.c:1468 #, c-format msgid "SQL function \"%s\"" msgstr "SQL-функция \"%s\"" -#: catalog/pg_publication.c:71 catalog/pg_publication.c:79 -#: catalog/pg_publication.c:87 catalog/pg_publication.c:93 +#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 +#: catalog/pg_publication.c:82 catalog/pg_publication.c:88 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "добавить отношение \"%s\" в публикацию нельзя" -#: catalog/pg_publication.c:81 +#: catalog/pg_publication.c:76 #, c-format msgid "This operation is not supported for system tables." msgstr "Эта операция не поддерживается для системных таблиц." -#: catalog/pg_publication.c:89 +#: catalog/pg_publication.c:84 #, c-format msgid "This operation is not supported for temporary tables." msgstr "Эта операция не поддерживается для временных таблиц." -#: catalog/pg_publication.c:95 +#: catalog/pg_publication.c:90 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "Эта операция не поддерживается для нежурналируемых таблиц." -#: catalog/pg_publication.c:109 catalog/pg_publication.c:117 +#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "добавить схему \"%s\" в публикацию нельзя" -#: catalog/pg_publication.c:111 +#: catalog/pg_publication.c:106 #, c-format msgid "This operation is not supported for system schemas." msgstr "Эта операция не поддерживается для системных схем." -#: catalog/pg_publication.c:119 +#: catalog/pg_publication.c:114 #, c-format msgid "Temporary schemas cannot be replicated." msgstr "Временные схемы нельзя реплицировать." -#: catalog/pg_publication.c:397 +#: catalog/pg_publication.c:392 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "отношение \"%s\" уже включено в публикацию \"%s\"" -#: catalog/pg_publication.c:539 +#: catalog/pg_publication.c:534 #, c-format msgid "cannot use system column \"%s\" in publication column list" msgstr "" "в списке публикуемых столбцов нельзя использовать системный столбец \"%s\"" -#: catalog/pg_publication.c:545 +#: catalog/pg_publication.c:540 #, c-format msgid "cannot use generated column \"%s\" in publication column list" msgstr "" "в списке публикуемых столбцов нельзя использовать генерируемый столбец \"%s\"" -#: catalog/pg_publication.c:551 +#: catalog/pg_publication.c:546 #, c-format msgid "duplicate column \"%s\" in publication column list" msgstr "в списке публикуемых столбцов повторяется столбец \"%s\"" -#: catalog/pg_publication.c:641 +#: catalog/pg_publication.c:636 #, c-format msgid "schema \"%s\" is already member of publication \"%s\"" msgstr "схема \"%s\" уже включена в публикацию \"%s\"" -#: catalog/pg_shdepend.c:830 +#: catalog/pg_shdepend.c:875 #, c-format msgid "" "\n" @@ -6711,43 +7132,48 @@ msgstr[2] "" "\n" "и объекты в %d других базах данных (см. список в протоколе сервера)" -#: catalog/pg_shdepend.c:1177 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "роль %u удалена другим процессом" -#: catalog/pg_shdepend.c:1189 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "табличное пространство %u удалено другим процессом" -#: catalog/pg_shdepend.c:1203 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "база данных %u удалена другим процессом" -#: catalog/pg_shdepend.c:1254 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "владелец объекта %s" -#: catalog/pg_shdepend.c:1256 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" msgstr "права доступа к объекту %s" -#: catalog/pg_shdepend.c:1258 +#: catalog/pg_shdepend.c:1303 +#, c-format +msgid "initial privileges for %s" +msgstr "начальные права для %s" + +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "субъект политики %s" -#: catalog/pg_shdepend.c:1260 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "табличное пространство для %s" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1268 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" @@ -6755,7 +7181,7 @@ msgstr[0] "%d объект (%s)" msgstr[1] "%d объекта (%s)" msgstr[2] "%d объектов (%s)" -#: catalog/pg_shdepend.c:1332 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "" "cannot drop objects owned by %s because they are required by the database " @@ -6764,7 +7190,7 @@ msgstr "" "удалить объекты, принадлежащие роли %s, нельзя, так как они нужны системе " "баз данных" -#: catalog/pg_shdepend.c:1498 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "" "cannot reassign ownership of objects owned by %s because they are required " @@ -6773,12 +7199,12 @@ msgstr "" "изменить владельца объектов, принадлежащих роли %s, нельзя, так как они " "нужны системе баз данных" -#: catalog/pg_subscription.c:424 +#: catalog/pg_subscription.c:438 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "удалить сопоставление отношений для подписки \"%s\" не получилось" -#: catalog/pg_subscription.c:426 +#: catalog/pg_subscription.c:440 #, c-format msgid "" "Table synchronization for relation \"%s\" is in progress and is in state " @@ -6788,7 +7214,7 @@ msgstr "Выполняется синхронизация отношения \"% #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:433 +#: catalog/pg_subscription.c:447 #, c-format msgid "" "Use %s to enable subscription if not already enabled or use %s to drop the " @@ -6797,45 +7223,45 @@ msgstr "" "Выполните %s, чтобы включить подписку, если она ещё не включена, либо %s, " "чтобы удалить её." -#: catalog/pg_type.c:134 catalog/pg_type.c:474 +#: catalog/pg_type.c:133 catalog/pg_type.c:474 #, c-format msgid "pg_type OID value not set when in binary upgrade mode" msgstr "значение OID в pg_type не задано в режиме двоичного обновления" -#: catalog/pg_type.c:254 +#: catalog/pg_type.c:253 #, c-format msgid "invalid type internal size %d" msgstr "неверный внутренний размер типа: %d" -#: catalog/pg_type.c:270 catalog/pg_type.c:278 catalog/pg_type.c:286 -#: catalog/pg_type.c:295 +#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285 +#: catalog/pg_type.c:294 #, c-format msgid "alignment \"%c\" is invalid for passed-by-value type of size %d" msgstr "" "выравнивание \"%c\" не подходит для типа, передаваемого по значению (с " "размером: %d)" -#: catalog/pg_type.c:302 +#: catalog/pg_type.c:301 #, c-format msgid "internal size %d is invalid for passed-by-value type" msgstr "внутренний размер %d не подходит для типа, передаваемого по значению" -#: catalog/pg_type.c:312 catalog/pg_type.c:318 +#: catalog/pg_type.c:311 catalog/pg_type.c:317 #, c-format msgid "alignment \"%c\" is invalid for variable-length type" msgstr "выравнивание \"%c\" не подходит для типа переменной длины" -#: catalog/pg_type.c:326 commands/typecmds.c:4146 +#: catalog/pg_type.c:325 commands/typecmds.c:4363 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "для типов постоянного размера применим только режим хранения PLAIN" -#: catalog/pg_type.c:955 +#: catalog/pg_type.c:978 #, c-format msgid "Failed while creating a multirange type for type \"%s\"." msgstr "Ошибка при создании мультидиапазонного типа для типа \"%s\"." -#: catalog/pg_type.c:956 +#: catalog/pg_type.c:979 #, c-format msgid "" "You can manually specify a multirange type name using the " @@ -6844,82 +7270,82 @@ msgstr "" "Имя мультидиапазонного типа можно указать вручную, воспользовавшись " "атрибутом \"multirange_type_name\"." -#: catalog/storage.c:505 storage/buffer/bufmgr.c:1145 +#: catalog/storage.c:533 storage/buffer/bufmgr.c:1540 #, c-format msgid "invalid page in block %u of relation %s" msgstr "неверная страница в блоке %u отношения %s" -#: commands/aggregatecmds.c:171 +#: commands/aggregatecmds.c:167 #, c-format msgid "only ordered-set aggregates can be hypothetical" msgstr "гипотезирующими могут быть только сортирующие агрегатные функции" -#: commands/aggregatecmds.c:196 +#: commands/aggregatecmds.c:192 #, c-format msgid "aggregate attribute \"%s\" not recognized" msgstr "нераспознанный атрибут \"%s\" в определении агрегатной функции" -#: commands/aggregatecmds.c:206 +#: commands/aggregatecmds.c:202 #, c-format msgid "aggregate stype must be specified" msgstr "в определении агрегата требуется stype" -#: commands/aggregatecmds.c:210 +#: commands/aggregatecmds.c:206 #, c-format msgid "aggregate sfunc must be specified" msgstr "в определении агрегата требуется sfunc" -#: commands/aggregatecmds.c:222 +#: commands/aggregatecmds.c:218 #, c-format msgid "aggregate msfunc must be specified when mstype is specified" msgstr "в определении агрегата требуется msfunc, если указан mstype" -#: commands/aggregatecmds.c:226 +#: commands/aggregatecmds.c:222 #, c-format msgid "aggregate minvfunc must be specified when mstype is specified" msgstr "в определении агрегата требуется minvfunc, если указан mstype" -#: commands/aggregatecmds.c:233 +#: commands/aggregatecmds.c:229 #, c-format msgid "aggregate msfunc must not be specified without mstype" msgstr "msfunc для агрегата не должна указываться без mstype" -#: commands/aggregatecmds.c:237 +#: commands/aggregatecmds.c:233 #, c-format msgid "aggregate minvfunc must not be specified without mstype" msgstr "minvfunc для агрегата не должна указываться без mstype" -#: commands/aggregatecmds.c:241 +#: commands/aggregatecmds.c:237 #, c-format msgid "aggregate mfinalfunc must not be specified without mstype" msgstr "mfinalfunc для агрегата не должна указываться без mstype" -#: commands/aggregatecmds.c:245 +#: commands/aggregatecmds.c:241 #, c-format msgid "aggregate msspace must not be specified without mstype" msgstr "msspace для агрегата не должна указываться без mstype" -#: commands/aggregatecmds.c:249 +#: commands/aggregatecmds.c:245 #, c-format msgid "aggregate minitcond must not be specified without mstype" msgstr "minitcond для агрегата не должна указываться без mstype" -#: commands/aggregatecmds.c:278 +#: commands/aggregatecmds.c:274 #, c-format msgid "aggregate input type must be specified" msgstr "в определении агрегата требуется входной тип" -#: commands/aggregatecmds.c:308 +#: commands/aggregatecmds.c:304 #, c-format msgid "basetype is redundant with aggregate input type specification" msgstr "в определении агрегата с указанием входного типа не нужен базовый тип" -#: commands/aggregatecmds.c:351 commands/aggregatecmds.c:392 +#: commands/aggregatecmds.c:347 commands/aggregatecmds.c:388 #, c-format msgid "aggregate transition data type cannot be %s" msgstr "переходным типом агрегата не может быть %s" -#: commands/aggregatecmds.c:363 +#: commands/aggregatecmds.c:359 #, c-format msgid "" "serialization functions may be specified only when the aggregate transition " @@ -6928,100 +7354,100 @@ msgstr "" "функции сериализации могут задаваться, только когда переходный тип данных " "агрегата - %s" -#: commands/aggregatecmds.c:373 +#: commands/aggregatecmds.c:369 #, c-format msgid "" "must specify both or neither of serialization and deserialization functions" msgstr "функции сериализации и десериализации должны задаваться совместно" -#: commands/aggregatecmds.c:438 commands/functioncmds.c:639 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "" "параметр \"parallel\" должен иметь значение SAFE, RESTRICTED или UNSAFE" -#: commands/aggregatecmds.c:494 +#: commands/aggregatecmds.c:490 #, c-format msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "" "параметр \"%s\" должен иметь характеристику READ_ONLY, SHAREABLE или " "READ_WRITE" -#: commands/alter.c:86 commands/event_trigger.c:174 +#: commands/alter.c:83 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" msgstr "событийный триггер \"%s\" уже существует" -#: commands/alter.c:89 commands/foreigncmds.c:593 +#: commands/alter.c:86 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "обёртка сторонних данных \"%s\" уже существует" -#: commands/alter.c:92 commands/foreigncmds.c:884 +#: commands/alter.c:89 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "сервер \"%s\" уже существует" -#: commands/alter.c:95 commands/proclang.c:133 +#: commands/alter.c:92 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "язык \"%s\" уже существует" -#: commands/alter.c:98 commands/publicationcmds.c:771 +#: commands/alter.c:95 commands/publicationcmds.c:764 #, c-format msgid "publication \"%s\" already exists" msgstr "публикация \"%s\" уже существует" -#: commands/alter.c:101 commands/subscriptioncmds.c:657 +#: commands/alter.c:98 commands/subscriptioncmds.c:669 #, c-format msgid "subscription \"%s\" already exists" msgstr "подписка \"%s\" уже существует" -#: commands/alter.c:124 +#: commands/alter.c:121 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "преобразование \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:128 +#: commands/alter.c:125 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "объект статистики \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:132 +#: commands/alter.c:129 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "анализатор текстового поиска \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:136 +#: commands/alter.c:133 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "словарь текстового поиска \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:140 +#: commands/alter.c:137 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "шаблон текстового поиска \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:144 +#: commands/alter.c:141 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "конфигурация текстового поиска \"%s\" уже существует в схеме \"%s\"" -#: commands/alter.c:217 +#: commands/alter.c:214 #, c-format msgid "must be superuser to rename %s" msgstr "переименовать \"%s\" может только суперпользователь" -#: commands/alter.c:259 commands/subscriptioncmds.c:636 -#: commands/subscriptioncmds.c:1116 commands/subscriptioncmds.c:1198 -#: commands/subscriptioncmds.c:1837 +#: commands/alter.c:256 commands/subscriptioncmds.c:648 +#: commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 +#: commands/subscriptioncmds.c:1918 #, c-format msgid "password_required=false is superuser-only" msgstr "задать password_required=false может только суперпользователь" -#: commands/alter.c:260 commands/subscriptioncmds.c:637 -#: commands/subscriptioncmds.c:1117 commands/subscriptioncmds.c:1199 -#: commands/subscriptioncmds.c:1838 +#: commands/alter.c:257 commands/subscriptioncmds.c:649 +#: commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 +#: commands/subscriptioncmds.c:1919 #, c-format msgid "" "Subscriptions with the password_required option set to false may only be " @@ -7030,7 +7456,7 @@ msgstr "" "Подписки с параметром password_required option, равным false, могут " "создавать или изменять только суперпользователи." -#: commands/alter.c:775 +#: commands/alter.c:735 #, c-format msgid "must be superuser to set schema of %s" msgstr "для назначения схемы объекта %s нужно быть суперпользователем" @@ -7038,7 +7464,7 @@ msgstr "для назначения схемы объекта %s нужно бы #: commands/amcmds.c:60 #, c-format msgid "permission denied to create access method \"%s\"" -msgstr "нет прав на создание метода доступа \"%s\"" +msgstr "нет прав для создания метода доступа \"%s\"" #: commands/amcmds.c:62 #, c-format @@ -7050,7 +7476,7 @@ msgstr "Для создания метода доступа нужно быть msgid "access method \"%s\" already exists" msgstr "метод доступа \"%s\" уже существует" -#: commands/amcmds.c:154 commands/indexcmds.c:216 commands/indexcmds.c:839 +#: commands/amcmds.c:154 commands/indexcmds.c:224 commands/indexcmds.c:850 #: commands/opclasscmds.c:375 commands/opclasscmds.c:833 #, c-format msgid "access method \"%s\" does not exist" @@ -7061,46 +7487,46 @@ msgstr "метод доступа \"%s\" не существует" msgid "handler function is not specified" msgstr "не указана функция-обработчик" -#: commands/amcmds.c:264 commands/event_trigger.c:183 -#: commands/foreigncmds.c:489 commands/proclang.c:80 commands/trigger.c:709 -#: parser/parse_clause.c:941 +#: commands/amcmds.c:264 commands/event_trigger.c:200 +#: commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 +#: parser/parse_clause.c:943 #, c-format msgid "function %s must return type %s" msgstr "функция %s должна возвращать тип %s" -#: commands/analyze.c:228 +#: commands/analyze.c:217 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "\"%s\" пропускается --- анализировать эту стороннюю таблицу нельзя" -#: commands/analyze.c:245 +#: commands/analyze.c:234 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "" "\"%s\" пропускается --- анализировать не таблицы или специальные системные " "таблицы нельзя" -#: commands/analyze.c:325 +#: commands/analyze.c:314 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "анализируется дерево наследования \"%s.%s\"" -#: commands/analyze.c:330 +#: commands/analyze.c:319 #, c-format msgid "analyzing \"%s.%s\"" msgstr "анализируется \"%s.%s\"" -#: commands/analyze.c:395 +#: commands/analyze.c:385 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "столбец \"%s\" отношения \"%s\" указан неоднократно" -#: commands/analyze.c:787 +#: commands/analyze.c:785 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "автоматический анализ таблицы \"%s.%s.%s\"\n" -#: commands/analyze.c:1334 +#: commands/analyze.c:1300 #, c-format msgid "" "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead " @@ -7110,7 +7536,7 @@ msgstr "" "%.0f, \"мёртвых\" строк: %.0f; строк в выборке: %d, примерное общее число " "строк: %.0f" -#: commands/analyze.c:1418 +#: commands/analyze.c:1384 #, c-format msgid "" "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree " @@ -7119,7 +7545,7 @@ msgstr "" "пропускается анализ дерева наследования \"%s.%s\" --- это дерево " "наследования не содержит дочерних таблиц" -#: commands/analyze.c:1516 +#: commands/analyze.c:1482 #, c-format msgid "" "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree " @@ -7128,22 +7554,22 @@ msgstr "" "пропускается анализ дерева наследования \"%s.%s\" --- это дерево " "наследования не содержит анализируемых дочерних таблиц" -#: commands/async.c:646 +#: commands/async.c:612 #, c-format msgid "channel name cannot be empty" msgstr "имя канала не может быть пустым" -#: commands/async.c:652 +#: commands/async.c:618 #, c-format msgid "channel name too long" msgstr "слишком длинное имя канала" -#: commands/async.c:657 +#: commands/async.c:623 #, c-format msgid "payload string too long" msgstr "слишком длинная строка сообщения-нагрузки" -#: commands/async.c:876 +#: commands/async.c:842 #, c-format msgid "" "cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY" @@ -7151,17 +7577,17 @@ msgstr "" "выполнить PREPARE для транзакции с командами LISTEN, UNLISTEN или NOTIFY " "нельзя" -#: commands/async.c:980 +#: commands/async.c:946 #, c-format msgid "too many notifications in the NOTIFY queue" msgstr "слишком много уведомлений в очереди NOTIFY" -#: commands/async.c:1602 +#: commands/async.c:1553 #, c-format msgid "NOTIFY queue is %.0f%% full" msgstr "очередь NOTIFY заполнена на %.0f%%" -#: commands/async.c:1604 +#: commands/async.c:1555 #, c-format msgid "" "The server process with PID %d is among those with the oldest transactions." @@ -7169,7 +7595,7 @@ msgstr "" "В число серверных процессов с самыми старыми транзакциями входит процесс с " "PID %d." -#: commands/async.c:1607 +#: commands/async.c:1558 #, c-format msgid "" "The NOTIFY queue cannot be emptied until that process ends its current " @@ -7178,22 +7604,22 @@ msgstr "" "Очередь NOTIFY можно будет освободить, только когда этот процесс завершит " "текущую транзакцию." -#: commands/cluster.c:130 +#: commands/cluster.c:128 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "нераспознанный параметр CLUSTER: \"%s\"" -#: commands/cluster.c:160 commands/cluster.c:433 +#: commands/cluster.c:159 commands/cluster.c:433 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "кластеризовать временные таблицы других сеансов нельзя" -#: commands/cluster.c:178 +#: commands/cluster.c:177 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "таблица \"%s\" ранее не кластеризовалась по какому-либо индексу" -#: commands/cluster.c:192 commands/tablecmds.c:14256 commands/tablecmds.c:16099 +#: commands/cluster.c:191 commands/tablecmds.c:14797 commands/tablecmds.c:16729 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "индекс \"%s\" для таблицы \"%s\" не существует" @@ -7208,7 +7634,7 @@ msgstr "кластеризовать разделяемый каталог не msgid "cannot vacuum temporary tables of other sessions" msgstr "очищать временные таблицы других сеансов нельзя" -#: commands/cluster.c:513 commands/tablecmds.c:16109 +#: commands/cluster.c:513 commands/tablecmds.c:16739 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "\"%s\" не является индексом таблицы \"%s\"" @@ -7236,23 +7662,23 @@ msgstr "нельзя кластеризовать таблицу по невер msgid "cannot mark index clustered in partitioned table" msgstr "пометить индекс как кластеризованный в секционированной таблице нельзя" -#: commands/cluster.c:950 +#: commands/cluster.c:956 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr "кластеризация \"%s.%s\" путём сканирования индекса \"%s\"" -#: commands/cluster.c:956 +#: commands/cluster.c:962 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "" "кластеризация \"%s.%s\" путём последовательного сканирования и сортировки" -#: commands/cluster.c:961 +#: commands/cluster.c:967 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "очистка \"%s.%s\"" -#: commands/cluster.c:988 +#: commands/cluster.c:994 #, c-format msgid "" "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" @@ -7260,7 +7686,7 @@ msgstr "" "\"%s.%s\": найдено удаляемых версий строк: %.0f, неудаляемых: %.0f, " "просмотрено страниц: %u" -#: commands/cluster.c:993 +#: commands/cluster.c:999 #, c-format msgid "" "%.0f dead row versions cannot be removed yet.\n" @@ -7269,33 +7695,39 @@ msgstr "" "В данный момент нельзя удалить \"мёртвых\" строк %.0f.\n" "%s." -#: commands/collationcmds.c:112 +#: commands/cluster.c:1744 +#, c-format +msgid "permission denied to cluster \"%s\", skipping it" +msgstr "нет прав для кластеризации отношения \"%s\", оно пропускается" + +#: commands/collationcmds.c:110 #, c-format msgid "collation attribute \"%s\" not recognized" msgstr "атрибут COLLATION \"%s\" не распознан" -#: commands/collationcmds.c:125 commands/collationcmds.c:131 -#: commands/define.c:389 commands/tablecmds.c:7883 -#: replication/pgoutput/pgoutput.c:309 replication/pgoutput/pgoutput.c:332 -#: replication/pgoutput/pgoutput.c:346 replication/pgoutput/pgoutput.c:356 -#: replication/pgoutput/pgoutput.c:366 replication/pgoutput/pgoutput.c:376 -#: replication/pgoutput/pgoutput.c:386 replication/walsender.c:996 -#: replication/walsender.c:1018 replication/walsender.c:1028 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 +#: commands/define.c:388 commands/tablecmds.c:8129 +#: replication/pgoutput/pgoutput.c:314 replication/pgoutput/pgoutput.c:337 +#: replication/pgoutput/pgoutput.c:351 replication/pgoutput/pgoutput.c:361 +#: replication/pgoutput/pgoutput.c:371 replication/pgoutput/pgoutput.c:381 +#: replication/pgoutput/pgoutput.c:393 replication/walsender.c:1146 +#: replication/walsender.c:1168 replication/walsender.c:1178 +#: replication/walsender.c:1187 replication/walsender.c:1426 #, c-format msgid "conflicting or redundant options" msgstr "конфликтующие или избыточные параметры" -#: commands/collationcmds.c:126 +#: commands/collationcmds.c:124 #, c-format msgid "LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE." msgstr "LOCALE нельзя указать вместе с LC_COLLATE или LC_CTYPE." -#: commands/collationcmds.c:132 +#: commands/collationcmds.c:130 #, c-format msgid "FROM cannot be specified together with any other options." msgstr "FROM нельзя задать вместе с каким-либо другим параметром." -#: commands/collationcmds.c:191 +#: commands/collationcmds.c:189 #, c-format msgid "collation \"default\" cannot be copied" msgstr "правило сортировки \"default\" нельзя скопировать" @@ -7305,103 +7737,97 @@ msgstr "правило сортировки \"default\" нельзя скопи msgid "unrecognized collation provider: %s" msgstr "нераспознанный провайдер правил сортировки: %s" -#: commands/collationcmds.c:253 commands/collationcmds.c:259 -#: commands/collationcmds.c:267 +#: commands/collationcmds.c:253 commands/collationcmds.c:264 +#: commands/collationcmds.c:270 commands/collationcmds.c:278 #, c-format msgid "parameter \"%s\" must be specified" msgstr "необходимо указать параметр \"%s\"" -#: commands/collationcmds.c:282 commands/dbcommands.c:1091 +#: commands/collationcmds.c:293 commands/dbcommands.c:1134 #, c-format msgid "using standard form \"%s\" for ICU locale \"%s\"" msgstr "используется стандартная форма \"%s\" локали ICU \"%s\"" -#: commands/collationcmds.c:301 +#: commands/collationcmds.c:312 #, c-format msgid "nondeterministic collations not supported with this provider" msgstr "" "недетерминированные правила сортировки не поддерживаются данным провайдером" -#: commands/collationcmds.c:306 commands/dbcommands.c:1110 +#: commands/collationcmds.c:317 commands/dbcommands.c:1087 #, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" msgstr "правила ICU можно указать, только если выбран провайдер локали ICU" -#: commands/collationcmds.c:325 +#: commands/collationcmds.c:340 #, c-format msgid "current database's encoding is not supported with this provider" msgstr "кодировка текущей БД не поддерживается данным провайдером" -#: commands/collationcmds.c:385 +#: commands/collationcmds.c:409 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "" "правило сортировки \"%s\" для кодировки \"%s\" уже существует в схеме \"%s\"" -#: commands/collationcmds.c:396 +#: commands/collationcmds.c:420 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "правило сортировки \"%s\" уже существует в схеме \"%s\"" -#: commands/collationcmds.c:421 +#: commands/collationcmds.c:445 #, c-format msgid "cannot refresh version of default collation" msgstr "нельзя обновить версию правила сортировки по умолчанию" #. translator: %s is an SQL command #. translator: %s is an SQL ALTER command -#: commands/collationcmds.c:423 commands/subscriptioncmds.c:1331 -#: commands/tablecmds.c:7708 commands/tablecmds.c:7718 -#: commands/tablecmds.c:13958 commands/tablecmds.c:17233 -#: commands/tablecmds.c:17254 commands/typecmds.c:3637 commands/typecmds.c:3720 -#: commands/typecmds.c:4013 +#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 +#: commands/tablecmds.c:7905 commands/tablecmds.c:7915 +#: commands/tablecmds.c:7917 commands/tablecmds.c:14499 +#: commands/tablecmds.c:17884 commands/tablecmds.c:17905 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 #, c-format msgid "Use %s instead." msgstr "Выполните %s." -#: commands/collationcmds.c:451 commands/dbcommands.c:2488 +#: commands/collationcmds.c:480 commands/dbcommands.c:2566 #, c-format msgid "changing version from %s to %s" msgstr "изменение версии с %s на %s" -#: commands/collationcmds.c:466 commands/dbcommands.c:2501 +#: commands/collationcmds.c:495 commands/dbcommands.c:2579 #, c-format msgid "version has not changed" msgstr "версия не была изменена" -#: commands/collationcmds.c:499 commands/dbcommands.c:2667 +#: commands/collationcmds.c:528 commands/dbcommands.c:2749 #, c-format msgid "database with OID %u does not exist" msgstr "база данных с OID %u не существует" -#: commands/collationcmds.c:520 +#: commands/collationcmds.c:554 #, c-format msgid "collation with OID %u does not exist" msgstr "правило сортировки с OID %u не существует" -#: commands/collationcmds.c:808 +#: commands/collationcmds.c:848 #, c-format msgid "must be superuser to import system collations" msgstr "" "импортировать системные правила сортировки может только суперпользователь" -#: commands/collationcmds.c:836 commands/copyfrom.c:1671 commands/copyto.c:656 -#: libpq/be-secure-common.c:59 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не удалось выполнить команду \"%s\": %m" - -#: commands/collationcmds.c:928 commands/collationcmds.c:1013 +#: commands/collationcmds.c:968 commands/collationcmds.c:1053 #, c-format msgid "no usable system locales were found" msgstr "пригодные системные локали не найдены" -#: commands/comment.c:61 commands/dbcommands.c:1612 commands/dbcommands.c:1824 -#: commands/dbcommands.c:1934 commands/dbcommands.c:2132 -#: commands/dbcommands.c:2370 commands/dbcommands.c:2461 -#: commands/dbcommands.c:2571 commands/dbcommands.c:3071 -#: utils/init/postinit.c:1021 utils/init/postinit.c:1085 -#: utils/init/postinit.c:1157 +#: commands/comment.c:61 commands/dbcommands.c:1665 commands/dbcommands.c:1883 +#: commands/dbcommands.c:1995 commands/dbcommands.c:2193 +#: commands/dbcommands.c:2433 commands/dbcommands.c:2526 +#: commands/dbcommands.c:2650 commands/dbcommands.c:3161 +#: utils/init/postinit.c:1034 utils/init/postinit.c:1098 +#: utils/init/postinit.c:1171 #, c-format msgid "database \"%s\" does not exist" msgstr "база данных \"%s\" не существует" @@ -7411,42 +7837,42 @@ msgstr "база данных \"%s\" не существует" msgid "cannot set comment on relation \"%s\"" msgstr "задать комментарий для отношения \"%s\" нельзя" -#: commands/constraint.c:63 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "функция \"%s\" была вызвана не менеджером триггеров" -#: commands/constraint.c:70 utils/adt/ri_triggers.c:2037 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "функция \"%s\" должна запускаться в триггере AFTER для строк" -#: commands/constraint.c:84 +#: commands/constraint.c:82 #, c-format msgid "function \"%s\" must be fired for INSERT or UPDATE" msgstr "функция \"%s\" должна запускаться для INSERT или UPDATE" -#: commands/conversioncmds.c:69 +#: commands/conversioncmds.c:62 #, c-format msgid "source encoding \"%s\" does not exist" msgstr "исходная кодировка \"%s\" не существует" -#: commands/conversioncmds.c:76 +#: commands/conversioncmds.c:69 #, c-format msgid "destination encoding \"%s\" does not exist" msgstr "целевая кодировка \"%s\" не существует" -#: commands/conversioncmds.c:89 +#: commands/conversioncmds.c:82 #, c-format msgid "encoding conversion to or from \"SQL_ASCII\" is not supported" msgstr "преобразование кодировки из/в \"SQL_ASCII\" не поддерживается" -#: commands/conversioncmds.c:102 +#: commands/conversioncmds.c:95 #, c-format msgid "encoding conversion function %s must return type %s" msgstr "функция преобразования кодировки %s должна возвращать тип %s" -#: commands/conversioncmds.c:132 +#: commands/conversioncmds.c:125 #, c-format msgid "" "encoding conversion function %s returned incorrect result for empty input" @@ -7454,12 +7880,12 @@ msgstr "" "функция преобразования кодировки %s возвратила некорректный результат для " "пустой строки" -#: commands/copy.c:86 +#: commands/copy.c:84 #, c-format msgid "permission denied to COPY to or from an external program" msgstr "нет прав для выполнения COPY с внешней программой" -#: commands/copy.c:87 +#: commands/copy.c:85 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may COPY to or from an " @@ -7468,7 +7894,7 @@ msgstr "" "Использовать COPY с внешними программами могут только роли с правами роли " "\"%s\"." -#: commands/copy.c:89 commands/copy.c:100 commands/copy.c:109 +#: commands/copy.c:87 commands/copy.c:98 commands/copy.c:107 #, c-format msgid "" "Anyone can COPY to stdout or from stdin. psql's \\copy command also works " @@ -7477,262 +7903,216 @@ msgstr "" "Не имея административных прав, можно использовать COPY с stdout и stdin (а " "также команду psql \\copy)." -#: commands/copy.c:97 +#: commands/copy.c:95 #, c-format msgid "permission denied to COPY from a file" msgstr "нет прав для выполнения COPY с чтением файла" -#: commands/copy.c:98 +#: commands/copy.c:96 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY from a file." msgstr "" "Выполнять COPY с чтением файла могут только роли с правами роли \"%s\"." -#: commands/copy.c:106 +#: commands/copy.c:104 #, c-format msgid "permission denied to COPY to a file" msgstr "нет прав для выполнения COPY с записью в файл" -#: commands/copy.c:107 +#: commands/copy.c:105 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to a file." msgstr "" "Выполнять COPY с записью в файл могут только роли с правами роли \"%s\"." -#: commands/copy.c:195 +#: commands/copy.c:193 #, c-format msgid "COPY FROM not supported with row-level security" msgstr "COPY FROM не поддерживается с защитой на уровне строк." -#: commands/copy.c:196 +#: commands/copy.c:194 #, c-format msgid "Use INSERT statements instead." msgstr "Используйте операторы INSERT." -#: commands/copy.c:290 -#, c-format -msgid "MERGE not supported in COPY" -msgstr "MERGE не поддерживается в COPY" - -#: commands/copy.c:383 +#: commands/copy.c:375 #, c-format msgid "cannot use \"%s\" with HEADER in COPY TO" msgstr "использовать \"%s\" с параметром HEADER в COPY TO нельзя" -#: commands/copy.c:392 +#: commands/copy.c:384 #, c-format msgid "%s requires a Boolean value or \"match\"" msgstr "%s требует логическое значение или \"match\"" -#: commands/copy.c:451 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:782 commands/copy.c:798 +#: commands/copy.c:815 commands/copy.c:841 commands/copy.c:851 +#, c-format +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s нельзя использовать с %s" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:441 +#, c-format +msgid "COPY %s \"%s\" not recognized" +msgstr "параметр COPY %s \"%s\" не распознан" + +#: commands/copy.c:502 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "формат \"%s\" для COPY не распознан" -#: commands/copy.c:509 commands/copy.c:522 commands/copy.c:535 -#: commands/copy.c:554 +#: commands/copy.c:560 commands/copy.c:575 commands/copy.c:590 +#: commands/copy.c:609 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "аргументом параметра \"%s\" должен быть список имён столбцов" -#: commands/copy.c:566 +#: commands/copy.c:621 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "аргументом параметра \"%s\" должно быть название допустимой кодировки" -#: commands/copy.c:573 commands/dbcommands.c:859 commands/dbcommands.c:2318 +#: commands/copy.c:642 commands/dbcommands.c:866 commands/dbcommands.c:2381 #, c-format msgid "option \"%s\" not recognized" msgstr "параметр \"%s\" не распознан" -#: commands/copy.c:585 -#, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "в режиме BINARY нельзя указывать DELIMITER" - -#: commands/copy.c:590 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:655 commands/copy.c:660 commands/copy.c:665 +#: commands/copy.c:740 #, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "в режиме BINARY нельзя указывать NULL" +msgid "cannot specify %s in BINARY mode" +msgstr "в режиме BINARY нельзя указывать %s" -#: commands/copy.c:595 +#: commands/copy.c:670 #, c-format -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "в режиме BINARY нельзя указывать DEFAULT" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "в режиме BINARY допускается только ON_ERROR STOP" -#: commands/copy.c:617 +#: commands/copy.c:692 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "разделитель для COPY должен быть однобайтным символом" -#: commands/copy.c:624 +#: commands/copy.c:699 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "" "разделителем для COPY не может быть символ новой строки или возврата каретки" -#: commands/copy.c:630 +#: commands/copy.c:705 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "" "представление NULL для COPY не может включать символ новой строки или " "возврата каретки" -#: commands/copy.c:640 +#: commands/copy.c:715 #, c-format msgid "COPY default representation cannot use newline or carriage return" msgstr "" "представление DEFAULT для COPY не может включать символ новой строки или " "возврата каретки" -#: commands/copy.c:658 +#: commands/copy.c:733 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "\"%s\" не может быть разделителем для COPY" -#: commands/copy.c:664 -#, c-format -msgid "cannot specify HEADER in BINARY mode" -msgstr "в режиме BINARY нельзя использовать HEADER" - -#: commands/copy.c:670 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:747 commands/copy.c:764 commands/copy.c:776 +#: commands/copy.c:791 commands/copy.c:807 #, c-format -msgid "COPY quote available only in CSV mode" -msgstr "определить кавычки для COPY можно только в режиме CSV" +msgid "COPY %s requires CSV mode" +msgstr "для COPY %s требуется режим CSV" -#: commands/copy.c:675 +#: commands/copy.c:752 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "символ кавычек для COPY должен быть однобайтным" -#: commands/copy.c:680 +#: commands/copy.c:757 #, c-format msgid "COPY delimiter and quote must be different" msgstr "символ кавычек для COPY должен отличаться от разделителя" -#: commands/copy.c:686 -#, c-format -msgid "COPY escape available only in CSV mode" -msgstr "определить спецсимвол для COPY можно только в режиме CSV" - -#: commands/copy.c:691 +#: commands/copy.c:769 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "спецсимвол для COPY должен быть однобайтным" -#: commands/copy.c:697 -#, c-format -msgid "COPY force quote available only in CSV mode" -msgstr "параметр force quote для COPY можно использовать только в режиме CSV" - -#: commands/copy.c:701 -#, c-format -msgid "COPY force quote only available using COPY TO" -msgstr "параметр force quote для COPY можно использовать только с COPY TO" - -#: commands/copy.c:707 -#, c-format -msgid "COPY force not null available only in CSV mode" -msgstr "" -"параметр force not null для COPY можно использовать только в режиме CSV" - -#: commands/copy.c:711 -#, c-format -msgid "COPY force not null only available using COPY FROM" -msgstr "параметр force not null для COPY можно использовать только с COPY FROM" - -#: commands/copy.c:717 -#, c-format -msgid "COPY force null available only in CSV mode" -msgstr "параметр force null для COPY можно использовать только в режиме CSV" - -#: commands/copy.c:722 -#, c-format -msgid "COPY force null only available using COPY FROM" -msgstr "параметр force null для COPY можно использовать только с COPY FROM" - -#: commands/copy.c:728 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:823 commands/copy.c:859 #, c-format -msgid "COPY delimiter must not appear in the NULL specification" -msgstr "разделитель для COPY не должен присутствовать в представлении NULL" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "символ разделителя для COPY не должен присутствовать в указании %s" -#: commands/copy.c:735 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:832 commands/copy.c:868 #, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "символ кавычек в CSV не должен присутствовать в представлении NULL" +msgid "CSV quote character must not appear in the %s specification" +msgstr "символ кавычек в CSV не должен присутствовать в указании %s" -#: commands/copy.c:742 -#, c-format -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "параметр DEFAULT для COPY можно использовать только с COPY FROM" - -#: commands/copy.c:748 -#, c-format -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "разделитель для COPY не должен присутствовать в представлении DEFAULT" - -#: commands/copy.c:755 -#, c-format -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "символ кавычек в CSV не должен присутствовать в представлении DEFAULT" - -#: commands/copy.c:763 +#: commands/copy.c:877 #, c-format msgid "NULL specification and DEFAULT specification cannot be the same" msgstr "представления NULL и DEFAULT не могут быть одинаковыми" -#: commands/copy.c:825 +#: commands/copy.c:939 #, c-format msgid "column \"%s\" is a generated column" msgstr "столбец \"%s\" — генерируемый" -#: commands/copy.c:827 +#: commands/copy.c:941 #, c-format msgid "Generated columns cannot be used in COPY." msgstr "Генерируемые столбцы нельзя использовать в COPY." -#: commands/copy.c:842 commands/indexcmds.c:1886 commands/statscmds.c:242 -#: commands/tablecmds.c:2401 commands/tablecmds.c:3123 -#: commands/tablecmds.c:3622 parser/parse_relation.c:3698 -#: parser/parse_relation.c:3708 parser/parse_relation.c:3726 -#: parser/parse_relation.c:3733 parser/parse_relation.c:3747 -#: utils/adt/tsvector_op.c:2855 +#: commands/copy.c:956 commands/indexcmds.c:1890 commands/statscmds.c:239 +#: commands/tablecmds.c:2526 commands/tablecmds.c:2997 +#: commands/tablecmds.c:3808 parser/parse_relation.c:3692 +#: parser/parse_relation.c:3702 parser/parse_relation.c:3720 +#: parser/parse_relation.c:3727 parser/parse_relation.c:3741 +#: utils/adt/tsvector_op.c:2853 #, c-format msgid "column \"%s\" does not exist" msgstr "столбец \"%s\" не существует" -#: commands/copy.c:849 commands/tablecmds.c:2427 commands/trigger.c:958 -#: parser/parse_target.c:1084 parser/parse_target.c:1095 +#: commands/copy.c:963 commands/tablecmds.c:2552 commands/trigger.c:951 +#: parser/parse_target.c:1083 parser/parse_target.c:1094 #, c-format msgid "column \"%s\" specified more than once" msgstr "столбец \"%s\" указан неоднократно" -#: commands/copyfrom.c:122 +#: commands/copyfrom.c:118 #, c-format msgid "COPY %s" msgstr "COPY %s" -#: commands/copyfrom.c:130 +#: commands/copyfrom.c:126 #, c-format msgid "COPY %s, line %llu, column %s" msgstr "COPY %s, строка %llu, столбец %s" -#: commands/copyfrom.c:135 commands/copyfrom.c:181 +#: commands/copyfrom.c:131 commands/copyfrom.c:177 #, c-format msgid "COPY %s, line %llu" msgstr "COPY %s, строка %llu" -#: commands/copyfrom.c:147 +#: commands/copyfrom.c:143 #, c-format msgid "COPY %s, line %llu, column %s: \"%s\"" msgstr "COPY %s, строка %llu, столбец %s: \"%s\"" -#: commands/copyfrom.c:157 +#: commands/copyfrom.c:153 #, c-format msgid "COPY %s, line %llu, column %s: null input" msgstr "COPY %s, строка %llu, столбец %s: значение NULL" -#: commands/copyfrom.c:174 +#: commands/copyfrom.c:170 #, c-format msgid "COPY %s, line %llu: \"%s\"" msgstr "COPY %s, строка %llu: \"%s\"" @@ -7783,24 +8163,29 @@ msgstr "" "выполнить COPY FREEZE нельзя, так как таблица не была создана или усечена в " "текущей подтранзакции" -#: commands/copyfrom.c:1414 +#: commands/copyfrom.c:1313 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "столбец FORCE_NOT_NULL \"%s\" не фигурирует в COPY" +msgid "%llu row was skipped due to data type incompatibility" +msgid_plural "%llu rows were skipped due to data type incompatibility" +msgstr[0] "из-за несовместимости типов данных пропущена %llu строка" +msgstr[1] "из-за несовместимости типов данных пропущены %llu строки" +msgstr[2] "из-за несовместимости типов данных пропущены %llu строк" -#: commands/copyfrom.c:1437 +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1448 commands/copyfrom.c:1491 commands/copyto.c:601 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "столбец FORCE_NULL \"%s\" не фигурирует в COPY" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "столбец %s \"%s\" не входит в список столбцов COPY" -#: commands/copyfrom.c:1490 utils/mb/mbutils.c:386 +#: commands/copyfrom.c:1544 utils/mb/mbutils.c:385 #, c-format msgid "" "default conversion function for encoding \"%s\" to \"%s\" does not exist" msgstr "" "стандартной функции преобразования из кодировки \"%s\" в \"%s\" не существует" -#: commands/copyfrom.c:1690 +#: commands/copyfrom.c:1742 #, c-format msgid "" "COPY FROM instructs the PostgreSQL server process to read a file. You may " @@ -7810,17 +8195,17 @@ msgstr "" "файла. Возможно, на самом деле вам нужно клиентское средство, например, " "\\copy в psql." -#: commands/copyfrom.c:1703 commands/copyto.c:708 +#: commands/copyfrom.c:1755 commands/copyto.c:706 #, c-format msgid "\"%s\" is a directory" msgstr "\"%s\" - это каталог" -#: commands/copyfrom.c:1771 commands/copyto.c:306 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1823 commands/copyto.c:299 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "не удалось закрыть канал сообщений с внешней командой: %m" -#: commands/copyfrom.c:1786 commands/copyto.c:311 +#: commands/copyfrom.c:1838 commands/copyto.c:304 #, c-format msgid "program \"%s\" failed" msgstr "сбой программы \"%s\"" @@ -7861,17 +8246,17 @@ msgid "could not read from COPY file: %m" msgstr "не удалось прочитать файл COPY: %m" #: commands/copyfromparse.c:278 commands/copyfromparse.c:303 -#: tcop/postgres.c:377 +#: replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:381 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "неожиданный обрыв соединения с клиентом при открытой транзакции" -#: commands/copyfromparse.c:294 +#: commands/copyfromparse.c:294 replication/walsender.c:772 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "неожиданный тип сообщения 0x%02X при вводе данных COPY из stdin" -#: commands/copyfromparse.c:317 +#: commands/copyfromparse.c:317 replication/walsender.c:803 #, c-format msgid "COPY from stdin failed: %s" msgstr "ошибка при вводе данных COPY из stdin: %s" @@ -7898,8 +8283,8 @@ msgstr "" "несоответствие имени столбца в поле %d строки заголовка: получено \"%s\", " "ожидалось \"%s\"" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1512 -#: commands/copyfromparse.c:1768 +#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 +#: commands/copyfromparse.c:1810 #, c-format msgid "extra data after last expected column" msgstr "лишние данные после содержимого последнего столбца" @@ -7909,193 +8294,211 @@ msgstr "лишние данные после содержимого послед msgid "missing data for column \"%s\"" msgstr "нет данных для столбца \"%s\"" -#: commands/copyfromparse.c:999 +#: commands/copyfromparse.c:990 #, c-format -msgid "received copy data after EOF marker" -msgstr "после маркера конца файла продолжаются данные COPY" +msgid "" +"skipping row due to data type incompatibility at line %llu for column " +"\"%s\": \"%s\"" +msgstr "" +"строка пропускается из-за несовместимости данных в строке %llu, столбце " +"\"%s\": \"%s\"" + +#: commands/copyfromparse.c:998 +#, c-format +msgid "" +"skipping row due to data type incompatibility at line %llu for column " +"\"%s\": null input" +msgstr "" +"строка пропускается из-за несовместимости данных в строке %llu, столбце " +"\"%s\": значение null" + +#: commands/copyfromparse.c:1044 +#, c-format +msgid "received copy data after EOF marker" +msgstr "после маркера конца файла продолжаются данные COPY" -#: commands/copyfromparse.c:1006 +#: commands/copyfromparse.c:1051 #, c-format msgid "row field count is %d, expected %d" msgstr "количество полей в строке: %d, ожидалось: %d" -#: commands/copyfromparse.c:1294 commands/copyfromparse.c:1311 +#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 #, c-format msgid "literal carriage return found in data" msgstr "в данных обнаружен явный возврат каретки" -#: commands/copyfromparse.c:1295 commands/copyfromparse.c:1312 +#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 #, c-format msgid "unquoted carriage return found in data" msgstr "в данных обнаружен возврат каретки не в кавычках" -#: commands/copyfromparse.c:1297 commands/copyfromparse.c:1314 +#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "Представьте возврат каретки как \"\\r\"." -#: commands/copyfromparse.c:1298 commands/copyfromparse.c:1315 +#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "Заключите возврат каретки в кавычки CSV." -#: commands/copyfromparse.c:1327 +#: commands/copyfromparse.c:1369 #, c-format msgid "literal newline found in data" msgstr "в данных обнаружен явный символ новой строки" -#: commands/copyfromparse.c:1328 +#: commands/copyfromparse.c:1370 #, c-format msgid "unquoted newline found in data" msgstr "в данных обнаружен явный символ новой строки не в кавычках" -#: commands/copyfromparse.c:1330 +#: commands/copyfromparse.c:1372 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "Представьте символ новой строки как \"\\n\"." -#: commands/copyfromparse.c:1331 +#: commands/copyfromparse.c:1373 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "Заключите символ новой строки в кавычки CSV." -#: commands/copyfromparse.c:1377 commands/copyfromparse.c:1413 +#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "маркер \"конец копии\" не соответствует предыдущему стилю новой строки" -#: commands/copyfromparse.c:1386 commands/copyfromparse.c:1402 +#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 #, c-format msgid "end-of-copy marker corrupt" msgstr "маркер \"конец копии\" испорчен" -#: commands/copyfromparse.c:1704 commands/copyfromparse.c:1919 +#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 #, c-format msgid "unexpected default marker in COPY data" msgstr "неожиданный маркер DEFAULT в данных COPY" -#: commands/copyfromparse.c:1705 commands/copyfromparse.c:1920 +#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 #, c-format msgid "Column \"%s\" has no default value." msgstr "Для столбца \"%s\" не определено значение по умолчанию." -#: commands/copyfromparse.c:1852 +#: commands/copyfromparse.c:1894 #, c-format msgid "unterminated CSV quoted field" msgstr "незавершённое поле в кавычках CSV" -#: commands/copyfromparse.c:1954 commands/copyfromparse.c:1973 +#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 #, c-format msgid "unexpected EOF in COPY data" msgstr "неожиданный конец данных COPY" -#: commands/copyfromparse.c:1963 +#: commands/copyfromparse.c:2005 #, c-format msgid "invalid field size" msgstr "неверный размер поля" -#: commands/copyfromparse.c:1986 +#: commands/copyfromparse.c:2028 #, c-format msgid "incorrect binary data format" msgstr "неверный двоичный формат данных" -#: commands/copyto.c:236 +#: commands/copyto.c:229 #, c-format msgid "could not write to COPY program: %m" msgstr "не удалось записать в канал программы COPY: %m" -#: commands/copyto.c:241 +#: commands/copyto.c:234 #, c-format msgid "could not write to COPY file: %m" msgstr "не удалось записать в файл COPY: %m" -#: commands/copyto.c:386 +#: commands/copyto.c:379 #, c-format msgid "cannot copy from view \"%s\"" msgstr "копировать из представления \"%s\" нельзя" -#: commands/copyto.c:388 commands/copyto.c:394 commands/copyto.c:400 -#: commands/copyto.c:411 +#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 +#: commands/copyto.c:404 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "Попробуйте вариацию COPY (SELECT ...) TO." -#: commands/copyto.c:392 +#: commands/copyto.c:385 #, c-format msgid "cannot copy from materialized view \"%s\"" msgstr "копировать из материализованного представления \"%s\" нельзя" -#: commands/copyto.c:398 +#: commands/copyto.c:391 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "копировать из сторонней таблицы \"%s\" нельзя" -#: commands/copyto.c:404 +#: commands/copyto.c:397 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "копировать из последовательности \"%s\" нельзя" -#: commands/copyto.c:409 +#: commands/copyto.c:402 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "копировать из секционированной таблицы \"%s\" нельзя" -#: commands/copyto.c:415 +#: commands/copyto.c:408 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "копировать из отношения \"%s\", не являющегося таблицей, нельзя" -#: commands/copyto.c:467 +#: commands/copyto.c:460 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "правила DO INSTEAD NOTHING не поддерживаются с COPY" -#: commands/copyto.c:481 +#: commands/copyto.c:474 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "условные правила DO INSTEAD не поддерживаются с COPY" -#: commands/copyto.c:485 +#: commands/copyto.c:478 #, c-format -msgid "DO ALSO rules are not supported for the COPY" +msgid "DO ALSO rules are not supported for COPY" msgstr "правила DO ALSO не поддерживаются с COPY" -#: commands/copyto.c:490 +#: commands/copyto.c:483 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "составные правила DO INSTEAD не поддерживаются с COPY" -#: commands/copyto.c:500 +#: commands/copyto.c:493 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO) не поддерживается" -#: commands/copyto.c:517 +#: commands/copyto.c:499 +#, c-format +msgid "COPY query must not be a utility command" +msgstr "служебная команда в запросе COPY не допускается" + +#: commands/copyto.c:515 #, c-format msgid "COPY query must have a RETURNING clause" msgstr "в запросе COPY должно быть предложение RETURNING" -#: commands/copyto.c:546 +#: commands/copyto.c:544 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "отношение, задействованное в операторе COPY, изменилось" -#: commands/copyto.c:605 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "столбец FORCE_QUOTE \"%s\" не фигурирует в COPY" - -#: commands/copyto.c:673 +#: commands/copyto.c:671 #, c-format msgid "relative path not allowed for COPY to file" msgstr "при выполнении COPY в файл нельзя указывать относительный путь" -#: commands/copyto.c:692 +#: commands/copyto.c:690 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "не удалось открыть файл \"%s\" для записи: %m" -#: commands/copyto.c:695 +#: commands/copyto.c:693 #, c-format msgid "" "COPY TO instructs the PostgreSQL server process to write a file. You may " @@ -8105,124 +8508,135 @@ msgstr "" "Возможно, на самом деле вам нужно клиентское средство, например, \\copy в " "psql." -#: commands/createas.c:215 commands/createas.c:523 +#: commands/createas.c:210 commands/createas.c:516 #, c-format msgid "too many column names were specified" msgstr "указано слишком много имён столбцов" -#: commands/createas.c:546 +#: commands/createas.c:539 #, c-format msgid "policies not yet implemented for this command" msgstr "политики для этой команды ещё не реализованы" -#: commands/dbcommands.c:822 +#: commands/dbcommands.c:829 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATION больше не поддерживается" -#: commands/dbcommands.c:823 +#: commands/dbcommands.c:830 #, c-format msgid "Consider using tablespaces instead." msgstr "Рассмотрите возможность использования табличных пространств." -#: commands/dbcommands.c:848 +#: commands/dbcommands.c:855 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "значения OID меньше %u зарезервированы для системных объектов" -#: commands/dbcommands.c:879 utils/adt/ascii.c:146 +#: commands/dbcommands.c:886 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "%d не является верным кодом кодировки" -#: commands/dbcommands.c:890 utils/adt/ascii.c:128 +#: commands/dbcommands.c:897 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "%s не является верным названием кодировки" -#: commands/dbcommands.c:919 +#: commands/dbcommands.c:931 #, c-format msgid "unrecognized locale provider: %s" msgstr "нераспознанный провайдер локали: %s" -#: commands/dbcommands.c:932 commands/dbcommands.c:2351 commands/user.c:300 -#: commands/user.c:740 +#: commands/dbcommands.c:944 commands/dbcommands.c:2414 commands/user.c:299 +#: commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "неверный предел подключений: %d" -#: commands/dbcommands.c:953 +#: commands/dbcommands.c:965 #, c-format msgid "permission denied to create database" -msgstr "нет прав на создание базы данных" +msgstr "нет прав для создания базы данных" -#: commands/dbcommands.c:977 +#: commands/dbcommands.c:989 #, c-format msgid "template database \"%s\" does not exist" msgstr "шаблон базы данных \"%s\" не существует" -#: commands/dbcommands.c:987 +#: commands/dbcommands.c:999 #, c-format msgid "cannot use invalid database \"%s\" as template" msgstr "использовать некорректную базу \"%s\" в качестве шаблона нельзя" -#: commands/dbcommands.c:988 commands/dbcommands.c:2380 -#: utils/init/postinit.c:1100 +#: commands/dbcommands.c:1000 commands/dbcommands.c:2444 +#: utils/init/postinit.c:1113 #, c-format msgid "Use DROP DATABASE to drop invalid databases." msgstr "Выполните DROP DATABASE для удаления некорректных баз данных." -#: commands/dbcommands.c:999 +#: commands/dbcommands.c:1011 #, c-format msgid "permission denied to copy database \"%s\"" -msgstr "нет прав на копирование базы данных \"%s\"" +msgstr "нет прав для копирования базы данных \"%s\"" -#: commands/dbcommands.c:1016 +#: commands/dbcommands.c:1028 #, c-format msgid "invalid create database strategy \"%s\"" msgstr "неверная стратегия создания БД \"%s\"" -#: commands/dbcommands.c:1017 +#: commands/dbcommands.c:1029 #, c-format msgid "Valid strategies are \"wal_log\" and \"file_copy\"." msgstr "Возможные стратегии: \"wal_log\" и \"file_copy\"." -#: commands/dbcommands.c:1043 +#: commands/dbcommands.c:1050 #, c-format msgid "invalid server encoding %d" msgstr "неверная кодировка для сервера: %d" -#: commands/dbcommands.c:1049 +#: commands/dbcommands.c:1056 #, c-format msgid "invalid LC_COLLATE locale name: \"%s\"" msgstr "неверное имя локали LC_COLLATE: \"%s\"" -#: commands/dbcommands.c:1050 commands/dbcommands.c:1056 +#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 #, c-format msgid "If the locale name is specific to ICU, use ICU_LOCALE." msgstr "Если эта локаль свойственна ICU, используйте ICU_LOCALE." -#: commands/dbcommands.c:1055 +#: commands/dbcommands.c:1062 #, c-format msgid "invalid LC_CTYPE locale name: \"%s\"" msgstr "неверное имя локали LC_CTYPE: \"%s\"" -#: commands/dbcommands.c:1066 +#: commands/dbcommands.c:1074 +#, c-format +msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" +msgstr "" +"BUILTIN_LOCALE можно указать, только если выбран встроенный провайдер локали" + +#: commands/dbcommands.c:1082 +#, c-format +msgid "ICU locale cannot be specified unless locale provider is ICU" +msgstr "локаль ICU можно указать, только если выбран провайдер локали ICU" + +#: commands/dbcommands.c:1100 +#, c-format +msgid "LOCALE or BUILTIN_LOCALE must be specified" +msgstr "необходимо указать LOCALE или BUILTIN_LOCALE" + +#: commands/dbcommands.c:1109 #, c-format msgid "encoding \"%s\" is not supported with ICU provider" msgstr "кодировка \"%s\" не поддерживается провайдером ICU" -#: commands/dbcommands.c:1076 +#: commands/dbcommands.c:1119 #, c-format msgid "LOCALE or ICU_LOCALE must be specified" msgstr "необходимо задать LOCALE или ICU_LOCALE" -#: commands/dbcommands.c:1105 -#, c-format -msgid "ICU locale cannot be specified unless locale provider is ICU" -msgstr "локаль ICU можно указать, только если выбран провайдер локали ICU" - -#: commands/dbcommands.c:1128 +#: commands/dbcommands.c:1163 #, c-format msgid "" "new encoding (%s) is incompatible with the encoding of the template database " @@ -8230,7 +8644,7 @@ msgid "" msgstr "" "новая кодировка (%s) несовместима с кодировкой шаблона базы данных (%s)" -#: commands/dbcommands.c:1131 +#: commands/dbcommands.c:1166 #, c-format msgid "" "Use the same encoding as in the template database, or use template0 as " @@ -8239,7 +8653,7 @@ msgstr "" "Используйте кодировку шаблона базы данных или выберите в качестве шаблона " "template0." -#: commands/dbcommands.c:1136 +#: commands/dbcommands.c:1171 #, c-format msgid "" "new collation (%s) is incompatible with the collation of the template " @@ -8248,7 +8662,7 @@ msgstr "" "новое правило сортировки (%s) несовместимо с правилом в шаблоне базы данных " "(%s)" -#: commands/dbcommands.c:1138 +#: commands/dbcommands.c:1173 #, c-format msgid "" "Use the same collation as in the template database, or use template0 as " @@ -8257,7 +8671,7 @@ msgstr "" "Используйте то же правило сортировки, что и в шаблоне базы данных, или " "выберите в качестве шаблона template0." -#: commands/dbcommands.c:1143 +#: commands/dbcommands.c:1178 #, c-format msgid "" "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database " @@ -8266,7 +8680,7 @@ msgstr "" "новый параметр LC_CTYPE (%s) несовместим с LC_CTYPE в шаблоне базы данных " "(%s)" -#: commands/dbcommands.c:1145 +#: commands/dbcommands.c:1180 #, c-format msgid "" "Use the same LC_CTYPE as in the template database, or use template0 as " @@ -8275,7 +8689,7 @@ msgstr "" "Используйте тот же LC_CTYPE, что и в шаблоне базы данных, или выберите в " "качестве шаблона template0." -#: commands/dbcommands.c:1150 +#: commands/dbcommands.c:1185 #, c-format msgid "" "new locale provider (%s) does not match locale provider of the template " @@ -8284,7 +8698,7 @@ msgstr "" "новый провайдер локали (%s) не соответствует провайдеру локали в базе-" "шаблоне (%s)" -#: commands/dbcommands.c:1152 +#: commands/dbcommands.c:1187 #, c-format msgid "" "Use the same locale provider as in the template database, or use template0 " @@ -8293,14 +8707,14 @@ msgstr "" "Используйте тот же провайдер локали, что и в базе-шаблоне, или выберите в " "качестве шаблона template0." -#: commands/dbcommands.c:1164 +#: commands/dbcommands.c:1199 #, c-format msgid "" "new ICU locale (%s) is incompatible with the ICU locale of the template " "database (%s)" msgstr "новая локаль ICU (%s) несовместима с локалью ICU в базе-шаблоне (%s)" -#: commands/dbcommands.c:1166 +#: commands/dbcommands.c:1201 #, c-format msgid "" "Use the same ICU locale as in the template database, or use template0 as " @@ -8309,7 +8723,7 @@ msgstr "" "Используйте ту же локаль ICU, что и в базе-шаблоне, или выберите в качестве " "шаблона template0." -#: commands/dbcommands.c:1177 +#: commands/dbcommands.c:1212 #, c-format msgid "" "new ICU collation rules (%s) are incompatible with the ICU collation rules " @@ -8318,7 +8732,7 @@ msgstr "" "новые правила сортировки ICU (%s) несовместимы с правилами сортировки в " "шаблоне базы данных (%s)" -#: commands/dbcommands.c:1179 +#: commands/dbcommands.c:1214 #, c-format msgid "" "Use the same ICU collation rules as in the template database, or use " @@ -8327,7 +8741,7 @@ msgstr "" "Используйте те же правила сортировки, что и в шаблоне базы данных, или " "выберите в качестве шаблона template0." -#: commands/dbcommands.c:1202 +#: commands/dbcommands.c:1243 #, c-format msgid "" "template database \"%s\" has a collation version, but no actual collation " @@ -8336,13 +8750,13 @@ msgstr "" "в шаблоне \"%s\" имеется версия правила сортировки, но фактическую версию " "правила сортировки определить нельзя" -#: commands/dbcommands.c:1207 +#: commands/dbcommands.c:1248 #, c-format msgid "template database \"%s\" has a collation version mismatch" msgstr "" "в базе-шаблоне \"%s\" обнаружено несоответствие версии правила сортировки" -#: commands/dbcommands.c:1209 +#: commands/dbcommands.c:1250 #, c-format msgid "" "The template database was created using collation version %s, but the " @@ -8351,7 +8765,7 @@ msgstr "" "База-шаблон была создана с версией правила сортировки %s, но операционная " "система предоставляет версию %s." -#: commands/dbcommands.c:1212 +#: commands/dbcommands.c:1253 #, c-format msgid "" "Rebuild all objects in the template database that use the default collation " @@ -8362,18 +8776,18 @@ msgstr "" "сортировки, и выполните ALTER DATABASE %s REFRESH COLLATION VERSION, либо " "соберите PostgreSQL с правильной версией библиотеки." -#: commands/dbcommands.c:1248 commands/dbcommands.c:1980 +#: commands/dbcommands.c:1298 commands/dbcommands.c:2041 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "" "pg_global нельзя использовать в качестве табличного пространства по умолчанию" -#: commands/dbcommands.c:1274 +#: commands/dbcommands.c:1324 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "не удалось назначить новое табличное пространство по умолчанию \"%s\"" -#: commands/dbcommands.c:1276 +#: commands/dbcommands.c:1326 #, c-format msgid "" "There is a conflict because database \"%s\" already has some tables in this " @@ -8382,62 +8796,63 @@ msgstr "" "База данных \"%s\" содержит таблицы, которые уже находятся в этом табличном " "пространстве." -#: commands/dbcommands.c:1306 commands/dbcommands.c:1853 +#: commands/dbcommands.c:1356 commands/dbcommands.c:1912 #, c-format msgid "database \"%s\" already exists" msgstr "база данных \"%s\" уже существует" -#: commands/dbcommands.c:1320 +#: commands/dbcommands.c:1370 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "исходная база \"%s\" занята другими пользователями" -#: commands/dbcommands.c:1342 +#: commands/dbcommands.c:1392 #, c-format msgid "database OID %u is already in use by database \"%s\"" msgstr "OID базы данных %u уже используется базой данных \"%s\"" -#: commands/dbcommands.c:1348 +#: commands/dbcommands.c:1398 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "каталог данных с указанным OID %u уже существует" -#: commands/dbcommands.c:1520 commands/dbcommands.c:1535 +#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 +#: utils/adt/pg_locale.c:2588 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "кодировка \"%s\" не соответствует локали \"%s\"" -#: commands/dbcommands.c:1523 +#: commands/dbcommands.c:1574 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "Для выбранного параметра LC_CTYPE требуется кодировка \"%s\"." -#: commands/dbcommands.c:1538 +#: commands/dbcommands.c:1589 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "Для выбранного параметра LC_COLLATE требуется кодировка \"%s\"." -#: commands/dbcommands.c:1619 +#: commands/dbcommands.c:1672 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "база данных \"%s\" не существует, пропускается" -#: commands/dbcommands.c:1643 +#: commands/dbcommands.c:1696 #, c-format msgid "cannot drop a template database" msgstr "удалить шаблон базы данных нельзя" -#: commands/dbcommands.c:1649 +#: commands/dbcommands.c:1702 #, c-format msgid "cannot drop the currently open database" msgstr "удалить базу данных, открытую в данный момент, нельзя" -#: commands/dbcommands.c:1662 +#: commands/dbcommands.c:1715 #, c-format msgid "database \"%s\" is used by an active logical replication slot" msgstr "база \"%s\" используется активным слотом логической репликации" -#: commands/dbcommands.c:1664 +#: commands/dbcommands.c:1717 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." @@ -8445,12 +8860,12 @@ msgstr[0] "Обнаружен %d активный слот." msgstr[1] "Обнаружены %d активных слота." msgstr[2] "Обнаружено %d активных слотов." -#: commands/dbcommands.c:1678 +#: commands/dbcommands.c:1731 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "база \"%s\" используется в подписке с логической репликацией" -#: commands/dbcommands.c:1680 +#: commands/dbcommands.c:1733 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." @@ -8458,36 +8873,36 @@ msgstr[0] "Обнаружена %d подписка." msgstr[1] "Обнаружены %d подписки." msgstr[2] "Обнаружено %d подписок." -#: commands/dbcommands.c:1701 commands/dbcommands.c:1875 -#: commands/dbcommands.c:2002 +#: commands/dbcommands.c:1754 commands/dbcommands.c:1934 +#: commands/dbcommands.c:2063 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "база данных \"%s\" занята другими пользователями" -#: commands/dbcommands.c:1835 +#: commands/dbcommands.c:1894 #, c-format msgid "permission denied to rename database" -msgstr "нет прав на переименование базы данных" +msgstr "нет прав для переименования базы данных" -#: commands/dbcommands.c:1864 +#: commands/dbcommands.c:1923 #, c-format msgid "current database cannot be renamed" msgstr "нельзя переименовать текущую базу данных" -#: commands/dbcommands.c:1958 +#: commands/dbcommands.c:2019 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "" "изменить табличное пространство открытой в данный момент базы данных нельзя" -#: commands/dbcommands.c:2064 +#: commands/dbcommands.c:2125 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "" "некоторые отношения базы данных \"%s\" уже находятся в табличном " "пространстве \"%s\"" -#: commands/dbcommands.c:2066 +#: commands/dbcommands.c:2127 #, c-format msgid "" "You must move them back to the database's default tablespace before using " @@ -8496,38 +8911,38 @@ msgstr "" "Прежде чем выполнять эту команду, вы должны вернуть их назад в табличное " "пространство по умолчанию для этой базы данных." -#: commands/dbcommands.c:2193 commands/dbcommands.c:2909 -#: commands/dbcommands.c:3209 commands/dbcommands.c:3322 +#: commands/dbcommands.c:2256 commands/dbcommands.c:2999 +#: commands/dbcommands.c:3299 commands/dbcommands.c:3412 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "в старом каталоге базы данных \"%s\" могли остаться ненужные файлы" -#: commands/dbcommands.c:2254 +#: commands/dbcommands.c:2317 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "нераспознанный параметр DROP DATABASE: \"%s\"" -#: commands/dbcommands.c:2332 +#: commands/dbcommands.c:2395 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "параметр \"%s\" нельзя задать с другими параметрами" -#: commands/dbcommands.c:2379 +#: commands/dbcommands.c:2443 #, c-format msgid "cannot alter invalid database \"%s\"" msgstr "изменить свойства некорректной базы \"%s\" нельзя" -#: commands/dbcommands.c:2396 +#: commands/dbcommands.c:2460 #, c-format msgid "cannot disallow connections for current database" msgstr "запретить подключения к текущей базе данных нельзя" -#: commands/dbcommands.c:2611 +#: commands/dbcommands.c:2690 #, c-format msgid "permission denied to change owner of database" -msgstr "нет прав на изменение владельца базы данных" +msgstr "нет прав для изменения владельца базы данных" -#: commands/dbcommands.c:3015 +#: commands/dbcommands.c:3105 #, c-format msgid "" "There are %d other session(s) and %d prepared transaction(s) using the " @@ -8536,7 +8951,7 @@ msgstr "" "С этой базой данных связаны другие сеансы (%d) и подготовленные транзакции " "(%d)." -#: commands/dbcommands.c:3018 +#: commands/dbcommands.c:3108 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." @@ -8544,7 +8959,7 @@ msgstr[0] "Эта база данных используется ещё в %d с msgstr[1] "Эта база данных используется ещё в %d сеансах." msgstr[2] "Эта база данных используется ещё в %d сеансах." -#: commands/dbcommands.c:3023 storage/ipc/procarray.c:3797 +#: commands/dbcommands.c:3113 storage/ipc/procarray.c:3859 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." @@ -8552,204 +8967,204 @@ msgstr[0] "С этой базой данных связана %d подгото msgstr[1] "С этой базой данных связаны %d подготовленные транзакции." msgstr[2] "С этой базой данных связаны %d подготовленных транзакций." -#: commands/dbcommands.c:3165 +#: commands/dbcommands.c:3255 #, c-format msgid "missing directory \"%s\"" msgstr "отсутствует каталог \"%s\"" -#: commands/dbcommands.c:3223 commands/tablespace.c:190 -#: commands/tablespace.c:639 +#: commands/dbcommands.c:3313 commands/tablespace.c:184 +#: commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "не удалось получить информацию о каталоге \"%s\": %m" -#: commands/define.c:54 commands/define.c:258 commands/define.c:290 -#: commands/define.c:318 commands/define.c:364 +#: commands/define.c:53 commands/define.c:257 commands/define.c:289 +#: commands/define.c:317 commands/define.c:363 #, c-format msgid "%s requires a parameter" msgstr "%s требует параметр" -#: commands/define.c:87 commands/define.c:98 commands/define.c:192 -#: commands/define.c:210 commands/define.c:225 commands/define.c:243 +#: commands/define.c:86 commands/define.c:97 commands/define.c:191 +#: commands/define.c:209 commands/define.c:224 commands/define.c:242 #, c-format msgid "%s requires a numeric value" msgstr "%s требует числовое значение" -#: commands/define.c:154 +#: commands/define.c:153 #, c-format msgid "%s requires a Boolean value" msgstr "%s требует логическое значение" -#: commands/define.c:168 commands/define.c:177 commands/define.c:327 +#: commands/define.c:167 commands/define.c:176 commands/define.c:326 #, c-format msgid "%s requires an integer value" msgstr "%s требует целое значение" -#: commands/define.c:272 +#: commands/define.c:271 #, c-format msgid "argument of %s must be a name" msgstr "аргументом %s должно быть имя" -#: commands/define.c:302 +#: commands/define.c:301 #, c-format msgid "argument of %s must be a type name" msgstr "аргументом %s должно быть имя типа" -#: commands/define.c:348 +#: commands/define.c:347 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "неверный аргумент для %s: \"%s\"" -#: commands/dropcmds.c:101 commands/functioncmds.c:1387 -#: utils/adt/ruleutils.c:2895 +#: commands/dropcmds.c:96 commands/functioncmds.c:1382 +#: utils/adt/ruleutils.c:2910 #, c-format msgid "\"%s\" is an aggregate function" msgstr "функция \"%s\" является агрегатной" -#: commands/dropcmds.c:103 +#: commands/dropcmds.c:98 #, c-format msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "Используйте DROP AGGREGATE для удаления агрегатных функций." -#: commands/dropcmds.c:158 commands/sequence.c:474 commands/tablecmds.c:3706 -#: commands/tablecmds.c:3864 commands/tablecmds.c:3916 -#: commands/tablecmds.c:16524 tcop/utility.c:1336 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3892 +#: commands/tablecmds.c:4050 commands/tablecmds.c:4102 +#: commands/tablecmds.c:17161 tcop/utility.c:1325 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "отношение \"%s\" не существует, пропускается" -#: commands/dropcmds.c:188 commands/dropcmds.c:287 commands/tablecmds.c:1281 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1409 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "схема \"%s\" не существует, пропускается" -#: commands/dropcmds.c:228 commands/dropcmds.c:267 commands/tablecmds.c:277 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "тип \"%s\" не существует, пропускается" -#: commands/dropcmds.c:257 +#: commands/dropcmds.c:252 #, c-format msgid "access method \"%s\" does not exist, skipping" msgstr "метод доступа \"%s\" не существует, пропускается" -#: commands/dropcmds.c:275 +#: commands/dropcmds.c:270 #, c-format msgid "collation \"%s\" does not exist, skipping" msgstr "правило сортировки \"%s\" не существует, пропускается" -#: commands/dropcmds.c:282 +#: commands/dropcmds.c:277 #, c-format msgid "conversion \"%s\" does not exist, skipping" msgstr "преобразование \"%s\" не существует, пропускается" -#: commands/dropcmds.c:293 commands/statscmds.c:654 +#: commands/dropcmds.c:288 commands/statscmds.c:664 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "объект статистики \"%s\" не существует, пропускается" -#: commands/dropcmds.c:300 +#: commands/dropcmds.c:295 #, c-format msgid "text search parser \"%s\" does not exist, skipping" msgstr "анализатор текстового поиска \"%s\" не существует, пропускается" -#: commands/dropcmds.c:307 +#: commands/dropcmds.c:302 #, c-format msgid "text search dictionary \"%s\" does not exist, skipping" msgstr "словарь текстового поиска \"%s\" не существует, пропускается" -#: commands/dropcmds.c:314 +#: commands/dropcmds.c:309 #, c-format msgid "text search template \"%s\" does not exist, skipping" msgstr "шаблон текстового поиска \"%s\" не существует, пропускается" -#: commands/dropcmds.c:321 +#: commands/dropcmds.c:316 #, c-format msgid "text search configuration \"%s\" does not exist, skipping" msgstr "конфигурация текстового поиска \"%s\" не существует, пропускается" -#: commands/dropcmds.c:326 +#: commands/dropcmds.c:321 #, c-format msgid "extension \"%s\" does not exist, skipping" msgstr "расширение \"%s\" не существует, пропускается" -#: commands/dropcmds.c:336 +#: commands/dropcmds.c:331 #, c-format msgid "function %s(%s) does not exist, skipping" msgstr "функция %s(%s) не существует, пропускается" -#: commands/dropcmds.c:349 +#: commands/dropcmds.c:344 #, c-format msgid "procedure %s(%s) does not exist, skipping" msgstr "процедура %s(%s) не существует, пропускается" -#: commands/dropcmds.c:362 +#: commands/dropcmds.c:357 #, c-format msgid "routine %s(%s) does not exist, skipping" msgstr "подпрограмма %s(%s) не существует, пропускается" -#: commands/dropcmds.c:375 +#: commands/dropcmds.c:370 #, c-format msgid "aggregate %s(%s) does not exist, skipping" msgstr "агрегатная функция %s(%s) не существует, пропускается" -#: commands/dropcmds.c:388 +#: commands/dropcmds.c:383 #, c-format msgid "operator %s does not exist, skipping" msgstr "оператор %s не существует, пропускается" -#: commands/dropcmds.c:394 +#: commands/dropcmds.c:389 #, c-format msgid "language \"%s\" does not exist, skipping" msgstr "язык \"%s\" не существует, пропускается" -#: commands/dropcmds.c:403 +#: commands/dropcmds.c:398 #, c-format msgid "cast from type %s to type %s does not exist, skipping" msgstr "приведение %s к типу %s не существует, пропускается" -#: commands/dropcmds.c:412 +#: commands/dropcmds.c:407 #, c-format msgid "transform for type %s language \"%s\" does not exist, skipping" msgstr "преобразование для типа %s, языка \"%s\" не существует, пропускается" -#: commands/dropcmds.c:420 +#: commands/dropcmds.c:415 #, c-format msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping" msgstr "триггер \"%s\" для отношения \"%s\" не существует, пропускается" -#: commands/dropcmds.c:429 +#: commands/dropcmds.c:424 #, c-format msgid "policy \"%s\" for relation \"%s\" does not exist, skipping" msgstr "политика \"%s\" для отношения \"%s\" не существует, пропускается" -#: commands/dropcmds.c:436 +#: commands/dropcmds.c:431 #, c-format msgid "event trigger \"%s\" does not exist, skipping" msgstr "событийный триггер \"%s\" не существует, пропускается" -#: commands/dropcmds.c:442 +#: commands/dropcmds.c:437 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist, skipping" msgstr "правило \"%s\" для отношения \"%s\" не существует, пропускается" -#: commands/dropcmds.c:449 +#: commands/dropcmds.c:444 #, c-format msgid "foreign-data wrapper \"%s\" does not exist, skipping" msgstr "обёртка сторонних данных \"%s\" не существует, пропускается" -#: commands/dropcmds.c:453 commands/foreigncmds.c:1360 +#: commands/dropcmds.c:448 commands/foreigncmds.c:1360 #, c-format msgid "server \"%s\" does not exist, skipping" msgstr "сервер \"%s\" не существует, пропускается" -#: commands/dropcmds.c:462 +#: commands/dropcmds.c:457 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\", skipping" msgstr "" "класс операторов \"%s\" не существует для метода доступа \"%s\", пропускается" -#: commands/dropcmds.c:474 +#: commands/dropcmds.c:469 #, c-format msgid "" "operator family \"%s\" does not exist for access method \"%s\", skipping" @@ -8757,179 +9172,189 @@ msgstr "" "семейство операторов \"%s\" не существует для метода доступа \"%s\", " "пропускается" -#: commands/dropcmds.c:481 +#: commands/dropcmds.c:476 #, c-format msgid "publication \"%s\" does not exist, skipping" msgstr "публикация \"%s\" не существует, пропускается" -#: commands/event_trigger.c:125 +#: commands/event_trigger.c:137 #, c-format msgid "permission denied to create event trigger \"%s\"" -msgstr "нет прав на создание событийного триггера \"%s\"" +msgstr "нет прав для создания событийного триггера \"%s\"" -#: commands/event_trigger.c:127 +#: commands/event_trigger.c:139 #, c-format msgid "Must be superuser to create an event trigger." msgstr "Для создания событийного триггера нужно быть суперпользователем." -#: commands/event_trigger.c:136 +#: commands/event_trigger.c:149 #, c-format msgid "unrecognized event name \"%s\"" msgstr "нераспознанное имя события \"%s\"" -#: commands/event_trigger.c:153 +#: commands/event_trigger.c:166 #, c-format msgid "unrecognized filter variable \"%s\"" msgstr "нераспознанная переменная фильтра \"%s\"" -#: commands/event_trigger.c:207 +#: commands/event_trigger.c:181 +#, c-format +msgid "tag filtering is not supported for login event triggers" +msgstr "фильтрация по тегу для событийных триггеров входа не поддерживается" + +#: commands/event_trigger.c:224 #, c-format msgid "filter value \"%s\" not recognized for filter variable \"%s\"" msgstr "значение фильтра \"%s\" неприемлемо для переменной фильтра \"%s\"" #. translator: %s represents an SQL statement name -#: commands/event_trigger.c:213 commands/event_trigger.c:235 +#: commands/event_trigger.c:230 commands/event_trigger.c:252 #, c-format msgid "event triggers are not supported for %s" msgstr "для %s событийные триггеры не поддерживаются" -#: commands/event_trigger.c:248 +#: commands/event_trigger.c:265 #, c-format msgid "filter variable \"%s\" specified more than once" msgstr "переменная фильтра \"%s\" указана больше одного раза" -#: commands/event_trigger.c:376 commands/event_trigger.c:420 -#: commands/event_trigger.c:514 +#: commands/event_trigger.c:438 commands/event_trigger.c:490 +#: commands/event_trigger.c:584 #, c-format msgid "event trigger \"%s\" does not exist" msgstr "событийный триггер \"%s\" не существует" -#: commands/event_trigger.c:452 +#: commands/event_trigger.c:522 #, c-format msgid "event trigger with OID %u does not exist" msgstr "событийный триггер с OID %u не существует" -#: commands/event_trigger.c:482 +#: commands/event_trigger.c:552 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" -msgstr "нет прав на изменение владельца событийного триггера \"%s\"" +msgstr "нет прав для изменения владельца событийного триггера \"%s\"" -#: commands/event_trigger.c:484 +#: commands/event_trigger.c:554 #, c-format msgid "The owner of an event trigger must be a superuser." msgstr "Владельцем событийного триггера должен быть суперпользователь." -#: commands/event_trigger.c:1304 +#: commands/event_trigger.c:1409 #, c-format msgid "%s can only be called in a sql_drop event trigger function" msgstr "%s можно вызывать только в событийной триггерной функции sql_drop" -#: commands/event_trigger.c:1397 commands/event_trigger.c:1418 +#: commands/event_trigger.c:1502 commands/event_trigger.c:1523 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" msgstr "%s можно вызывать только в событийной триггерной функции table_rewrite" -#: commands/event_trigger.c:1831 +#: commands/event_trigger.c:1936 #, c-format msgid "%s can only be called in an event trigger function" msgstr "%s можно вызывать только в событийной триггерной функции" -#: commands/explain.c:220 +#: commands/explain.c:241 commands/explain.c:266 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "нераспознанное значение параметра EXPLAIN \"%s\": \"%s\"" -#: commands/explain.c:227 +#: commands/explain.c:273 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "нераспознанный параметр EXPLAIN: \"%s\"" -#: commands/explain.c:236 +#: commands/explain.c:282 #, c-format msgid "EXPLAIN option WAL requires ANALYZE" msgstr "параметр WAL оператора EXPLAIN требует указания ANALYZE" -#: commands/explain.c:245 +#: commands/explain.c:291 #, c-format msgid "EXPLAIN option TIMING requires ANALYZE" msgstr "параметр TIMING оператора EXPLAIN требует указания ANALYZE" -#: commands/explain.c:251 +#: commands/explain.c:297 +#, c-format +msgid "EXPLAIN option SERIALIZE requires ANALYZE" +msgstr "параметр SERIALIZE оператора EXPLAIN требует указания ANALYZE" + +#: commands/explain.c:303 #, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" msgstr "" "параметры ANALYZE и GENERIC_PLAN оператора EXPLAIN нельзя использовать " "одновременно" -#: commands/extension.c:177 commands/extension.c:3033 +#: commands/extension.c:178 commands/extension.c:3031 #, c-format msgid "extension \"%s\" does not exist" msgstr "расширение \"%s\" не существует" -#: commands/extension.c:276 commands/extension.c:285 commands/extension.c:297 -#: commands/extension.c:307 +#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 +#: commands/extension.c:308 #, c-format msgid "invalid extension name: \"%s\"" msgstr "неверное имя расширения: \"%s\"" -#: commands/extension.c:277 +#: commands/extension.c:278 #, c-format msgid "Extension names must not be empty." msgstr "Имя расширения не может быть пустым." -#: commands/extension.c:286 +#: commands/extension.c:287 #, c-format msgid "Extension names must not contain \"--\"." msgstr "Имя расширения не может содержать \"--\"." -#: commands/extension.c:298 +#: commands/extension.c:299 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "Имя расширения не может начинаться или заканчиваться символом \"-\"." -#: commands/extension.c:308 +#: commands/extension.c:309 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "Имя расширения не может содержать разделители пути." -#: commands/extension.c:323 commands/extension.c:332 commands/extension.c:341 -#: commands/extension.c:351 +#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 +#: commands/extension.c:352 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "неверный идентификатор версии расширения: \"%s\"" -#: commands/extension.c:324 +#: commands/extension.c:325 #, c-format msgid "Version names must not be empty." msgstr "Идентификатор версии не может быть пустым." -#: commands/extension.c:333 +#: commands/extension.c:334 #, c-format msgid "Version names must not contain \"--\"." msgstr "Идентификатор версии не может содержать \"--\"." -#: commands/extension.c:342 +#: commands/extension.c:343 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "" "Идентификатор версии не может начинаться или заканчиваться символом \"-\"." -#: commands/extension.c:352 +#: commands/extension.c:353 #, c-format msgid "Version names must not contain directory separator characters." msgstr "Идентификатор версии не может содержать разделители пути." -#: commands/extension.c:506 +#: commands/extension.c:507 #, c-format msgid "extension \"%s\" is not available" msgstr "расширение \"%s\" отсутствует" -#: commands/extension.c:507 +#: commands/extension.c:508 #, c-format msgid "Could not open extension control file \"%s\": %m." msgstr "Не удалось открыть управляющий файл расширения \"%s\": %m." -#: commands/extension.c:509 +#: commands/extension.c:510 #, c-format msgid "" "The extension must first be installed on the system where PostgreSQL is " @@ -8937,91 +9362,91 @@ msgid "" msgstr "" "Сначала расширение нужно установить в системе, где работает PostgreSQL." -#: commands/extension.c:513 +#: commands/extension.c:514 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "не удалось открыть управляющий файл расширения \"%s\": %m" -#: commands/extension.c:536 commands/extension.c:546 +#: commands/extension.c:537 commands/extension.c:547 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "" "параметр \"%s\" нельзя задавать в дополнительном управляющем файле расширения" -#: commands/extension.c:568 commands/extension.c:576 commands/extension.c:584 -#: utils/misc/guc.c:3100 +#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 +#: utils/misc/guc.c:3147 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "параметр \"%s\" требует логическое значение" -#: commands/extension.c:593 +#: commands/extension.c:594 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" не является верным названием кодировки" -#: commands/extension.c:607 commands/extension.c:622 +#: commands/extension.c:608 commands/extension.c:623 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "параметр \"%s\" должен содержать список имён расширений" -#: commands/extension.c:629 +#: commands/extension.c:630 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "нераспознанный параметр \"%s\" в файле \"%s\"" -#: commands/extension.c:638 +#: commands/extension.c:639 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "" "параметр \"schema\" не может быть указан вместе с \"relocatable\" = true" -#: commands/extension.c:816 +#: commands/extension.c:817 #, c-format msgid "" "transaction control statements are not allowed within an extension script" msgstr "в скрипте расширения не должно быть операторов управления транзакциями" -#: commands/extension.c:896 +#: commands/extension.c:897 #, c-format msgid "permission denied to create extension \"%s\"" -msgstr "нет прав на создание расширения \"%s\"" +msgstr "нет прав для создания расширения \"%s\"" -#: commands/extension.c:899 +#: commands/extension.c:900 #, c-format msgid "" "Must have CREATE privilege on current database to create this extension." msgstr "Для создания этого расширения нужно иметь право CREATE в текущей базе." -#: commands/extension.c:900 +#: commands/extension.c:901 #, c-format msgid "Must be superuser to create this extension." msgstr "Для создания этого расширения нужно быть суперпользователем." -#: commands/extension.c:904 +#: commands/extension.c:905 #, c-format msgid "permission denied to update extension \"%s\"" -msgstr "нет прав на изменение расширения \"%s\"" +msgstr "нет прав для изменения расширения \"%s\"" -#: commands/extension.c:907 +#: commands/extension.c:908 #, c-format msgid "" "Must have CREATE privilege on current database to update this extension." msgstr "" "Для обновления этого расширения нужно иметь право CREATE в текущей базе." -#: commands/extension.c:908 +#: commands/extension.c:909 #, c-format msgid "Must be superuser to update this extension." msgstr "Для изменения этого расширения нужно быть суперпользователем." -#: commands/extension.c:1046 +#: commands/extension.c:1042 #, c-format msgid "invalid character in extension owner: must not contain any of \"%s\"" msgstr "" "недопустимый символ в имени владельца расширения: имя не должно содержать " "\"%s\"" -#: commands/extension.c:1070 commands/extension.c:1097 +#: commands/extension.c:1066 commands/extension.c:1093 #, c-format msgid "" "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" @@ -9029,7 +9454,7 @@ msgstr "" "недопустимый символ в имени схемы расширения \"%s\": имя не должно содержать " "\"%s\"" -#: commands/extension.c:1292 +#: commands/extension.c:1288 #, c-format msgid "" "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" @@ -9037,12 +9462,12 @@ msgstr "" "для расширения \"%s\" не определён путь обновления с версии \"%s\" до версии " "\"%s\"" -#: commands/extension.c:1500 commands/extension.c:3091 +#: commands/extension.c:1496 commands/extension.c:3089 #, c-format msgid "version to install must be specified" msgstr "нужно указать версию для установки" -#: commands/extension.c:1537 +#: commands/extension.c:1533 #, c-format msgid "" "extension \"%s\" has no installation script nor update path for version " @@ -9051,71 +9476,71 @@ msgstr "" "для расширения \"%s\" не определён путь установки или обновления для версии " "\"%s\"" -#: commands/extension.c:1571 +#: commands/extension.c:1567 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "расширение \"%s\" должно устанавливаться в схему \"%s\"" -#: commands/extension.c:1731 +#: commands/extension.c:1727 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "выявлена циклическая зависимость между расширениями \"%s\" и \"%s\"" -#: commands/extension.c:1736 +#: commands/extension.c:1732 #, c-format msgid "installing required extension \"%s\"" msgstr "установка требуемого расширения \"%s\"" -#: commands/extension.c:1759 +#: commands/extension.c:1755 #, c-format msgid "required extension \"%s\" is not installed" msgstr "требуемое расширение \"%s\" не установлено" -#: commands/extension.c:1762 +#: commands/extension.c:1758 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "" "Выполните CREATE EXTENSION ... CASCADE, чтобы установить также требуемые " "расширения." -#: commands/extension.c:1797 +#: commands/extension.c:1793 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "расширение \"%s\" уже существует, пропускается" -#: commands/extension.c:1804 +#: commands/extension.c:1800 #, c-format msgid "extension \"%s\" already exists" msgstr "расширение \"%s\" уже существует" -#: commands/extension.c:1815 +#: commands/extension.c:1811 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "вложенные операторы CREATE EXTENSION не поддерживаются" -#: commands/extension.c:1979 +#: commands/extension.c:1975 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "удалить расширение \"%s\" нельзя, так как это модифицируемый объект" -#: commands/extension.c:2454 +#: commands/extension.c:2450 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "" "%s можно вызывать только из SQL-скрипта, запускаемого командой CREATE " "EXTENSION" -#: commands/extension.c:2466 +#: commands/extension.c:2462 #, c-format msgid "OID %u does not refer to a table" msgstr "OID %u не относится к таблице" -#: commands/extension.c:2471 +#: commands/extension.c:2467 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "таблица \"%s\" не относится к созданному расширению" -#: commands/extension.c:2817 +#: commands/extension.c:2813 #, c-format msgid "" "cannot move extension \"%s\" into schema \"%s\" because the extension " @@ -9124,12 +9549,12 @@ msgstr "" "переместить расширение \"%s\" в схему \"%s\" нельзя, так как оно содержит " "схему" -#: commands/extension.c:2858 commands/extension.c:2952 +#: commands/extension.c:2854 commands/extension.c:2948 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "расширение \"%s\" не поддерживает SET SCHEMA" -#: commands/extension.c:2915 +#: commands/extension.c:2911 #, c-format msgid "" "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" @@ -9137,32 +9562,32 @@ msgstr "" "выполнить SET SCHEMA для расширения \"%s\" нельзя, так как этому " "препятствуют другие расширения" -#: commands/extension.c:2917 +#: commands/extension.c:2913 #, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." msgstr "Расширение \"%s\" не допускает перемещения расширения \"%s\"." -#: commands/extension.c:2954 +#: commands/extension.c:2950 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "объект %s не принадлежит схеме расширения \"%s\"" -#: commands/extension.c:3013 +#: commands/extension.c:3011 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "вложенные операторы ALTER EXTENSION не поддерживаются" -#: commands/extension.c:3102 +#: commands/extension.c:3100 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "версия \"%s\" расширения \"%s\" уже установлена" -#: commands/extension.c:3314 +#: commands/extension.c:3311 #, c-format msgid "cannot add an object of this type to an extension" msgstr "добавить объект этого типа к расширению нельзя" -#: commands/extension.c:3380 +#: commands/extension.c:3409 #, c-format msgid "" "cannot add schema \"%s\" to extension \"%s\" because the schema contains the " @@ -9171,7 +9596,12 @@ msgstr "" "добавить схему \"%s\" к расширению \"%s\" нельзя, так как схема содержит " "расширение" -#: commands/extension.c:3474 +#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#, c-format +msgid "could not find multirange type for data type %s" +msgstr "тип мультидиапазона для типа данных %s не найден" + +#: commands/extension.c:3532 #, c-format msgid "file \"%s\" is too large" msgstr "файл \"%s\" слишком большой" @@ -9189,7 +9619,7 @@ msgstr "параметр \"%s\" указан неоднократно" #: commands/foreigncmds.c:221 commands/foreigncmds.c:229 #, c-format msgid "permission denied to change owner of foreign-data wrapper \"%s\"" -msgstr "нет прав на изменение владельца обёртки сторонних данных \"%s\"" +msgstr "нет прав для изменения владельца обёртки сторонних данных \"%s\"" #: commands/foreigncmds.c:223 #, c-format @@ -9202,7 +9632,7 @@ msgstr "" msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "Владельцем обёртки сторонних данных должен быть суперпользователь." -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:678 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "обёртка сторонних данных \"%s\" не существует" @@ -9220,7 +9650,7 @@ msgstr "сторонний сервер с OID %u не существует" #: commands/foreigncmds.c:580 #, c-format msgid "permission denied to create foreign-data wrapper \"%s\"" -msgstr "нет прав на создание обёртки сторонних данных \"%s\"" +msgstr "нет прав для создания обёртки сторонних данных \"%s\"" #: commands/foreigncmds.c:582 #, c-format @@ -9230,7 +9660,7 @@ msgstr "Для создания обёртки сторонних данных #: commands/foreigncmds.c:697 #, c-format msgid "permission denied to alter foreign-data wrapper \"%s\"" -msgstr "нет прав на изменение обёртки сторонних данных \"%s\"" +msgstr "нет прав для изменения обёртки сторонних данных \"%s\"" #: commands/foreigncmds.c:699 #, c-format @@ -9284,7 +9714,7 @@ msgstr "" "сопоставление пользователя \"%s\" для сервера \"%s\" не существует, " "пропускается" -#: commands/foreigncmds.c:1507 foreign/foreign.c:391 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "обёртка сторонних данных \"%s\" не имеет обработчика" @@ -9299,151 +9729,151 @@ msgstr "обёртка сторонних данных \"%s\" не поддер msgid "importing foreign table \"%s\"" msgstr "импорт сторонней таблицы \"%s\"" -#: commands/functioncmds.c:109 +#: commands/functioncmds.c:104 #, c-format msgid "SQL function cannot return shell type %s" msgstr "SQL-функция не может возвращать тип-пустышку %s" -#: commands/functioncmds.c:114 +#: commands/functioncmds.c:109 #, c-format msgid "return type %s is only a shell" msgstr "возвращаемый тип %s - лишь пустышка" -#: commands/functioncmds.c:143 parser/parse_type.c:354 +#: commands/functioncmds.c:138 parser/parse_type.c:354 #, c-format msgid "type modifier cannot be specified for shell type \"%s\"" msgstr "для типа-пустышки \"%s\" нельзя указать модификатор типа" -#: commands/functioncmds.c:149 +#: commands/functioncmds.c:144 #, c-format msgid "type \"%s\" is not yet defined" msgstr "тип \"%s\" ещё не определён" -#: commands/functioncmds.c:150 +#: commands/functioncmds.c:145 #, c-format msgid "Creating a shell type definition." msgstr "Создание определения типа-пустышки." -#: commands/functioncmds.c:249 +#: commands/functioncmds.c:244 #, c-format msgid "SQL function cannot accept shell type %s" msgstr "SQL-функция не может принимать значение типа-пустышки %s" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:250 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "агрегатная функция не может принимать значение типа-пустышки %s" -#: commands/functioncmds.c:260 +#: commands/functioncmds.c:255 #, c-format msgid "argument type %s is only a shell" msgstr "тип аргумента %s - лишь пустышка" -#: commands/functioncmds.c:270 +#: commands/functioncmds.c:265 #, c-format msgid "type %s does not exist" msgstr "тип %s не существует" -#: commands/functioncmds.c:284 +#: commands/functioncmds.c:279 #, c-format msgid "aggregates cannot accept set arguments" msgstr "агрегатные функции не принимают в аргументах множества" -#: commands/functioncmds.c:288 +#: commands/functioncmds.c:283 #, c-format msgid "procedures cannot accept set arguments" msgstr "процедуры не принимают в аргументах множества" -#: commands/functioncmds.c:292 +#: commands/functioncmds.c:287 #, c-format msgid "functions cannot accept set arguments" msgstr "функции не принимают аргументы-множества" -#: commands/functioncmds.c:302 +#: commands/functioncmds.c:297 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "параметр VARIADIC должен быть последним в списке входных параметров" -#: commands/functioncmds.c:322 +#: commands/functioncmds.c:317 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "параметр VARIADIC должен быть последним в списке параметров" -#: commands/functioncmds.c:347 +#: commands/functioncmds.c:342 #, c-format msgid "VARIADIC parameter must be an array" msgstr "параметр VARIADIC должен быть массивом" -#: commands/functioncmds.c:392 +#: commands/functioncmds.c:387 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "имя параметра \"%s\" указано неоднократно" -#: commands/functioncmds.c:410 +#: commands/functioncmds.c:405 #, c-format msgid "only input parameters can have default values" msgstr "значения по умолчанию могут быть только у входных параметров" -#: commands/functioncmds.c:425 +#: commands/functioncmds.c:420 #, c-format msgid "cannot use table references in parameter default value" msgstr "в значениях параметров по умолчанию нельзя ссылаться на таблицы" -#: commands/functioncmds.c:449 +#: commands/functioncmds.c:444 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "" "входные параметры, следующие за параметром со значением по умолчанию, также " "должны иметь значения по умолчанию" -#: commands/functioncmds.c:459 +#: commands/functioncmds.c:454 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "" "в объявлении процедуры параметры OUT не могут находиться после параметра со " "значением по умолчанию" -#: commands/functioncmds.c:601 commands/functioncmds.c:780 +#: commands/functioncmds.c:596 commands/functioncmds.c:775 #, c-format msgid "invalid attribute in procedure definition" msgstr "некорректный атрибут в определении процедуры" -#: commands/functioncmds.c:697 +#: commands/functioncmds.c:692 #, c-format msgid "support function %s must return type %s" msgstr "вспомогательная функция %s должна возвращать тип %s" -#: commands/functioncmds.c:708 +#: commands/functioncmds.c:703 #, c-format msgid "must be superuser to specify a support function" msgstr "для указания вспомогательной функции нужно быть суперпользователем" -#: commands/functioncmds.c:829 commands/functioncmds.c:1432 +#: commands/functioncmds.c:824 commands/functioncmds.c:1427 #, c-format msgid "COST must be positive" msgstr "значение COST должно быть положительным" -#: commands/functioncmds.c:837 commands/functioncmds.c:1440 +#: commands/functioncmds.c:832 commands/functioncmds.c:1435 #, c-format msgid "ROWS must be positive" msgstr "значение ROWS должно быть положительным" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:861 #, c-format msgid "no function body specified" msgstr "не указано тело функции" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:866 #, c-format msgid "duplicate function body specified" msgstr "тело функции задано неоднократно" -#: commands/functioncmds.c:876 +#: commands/functioncmds.c:871 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "встроенное тело функции SQL допускается только для языка SQL" -#: commands/functioncmds.c:918 +#: commands/functioncmds.c:913 #, c-format msgid "" "SQL function with unquoted function body cannot have polymorphic arguments" @@ -9451,84 +9881,84 @@ msgstr "" "у SQL-функции с телом, задаваемым не в кавычках, не может быть полиморфных " "аргументов" -#: commands/functioncmds.c:944 commands/functioncmds.c:963 +#: commands/functioncmds.c:939 commands/functioncmds.c:958 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "" "%s на данный момент не поддерживается в теле SQL-функции, задаваемом не в " "кавычках" -#: commands/functioncmds.c:991 +#: commands/functioncmds.c:986 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "для языка \"%s\" нужно только одно выражение AS" -#: commands/functioncmds.c:1096 +#: commands/functioncmds.c:1091 #, c-format msgid "no language specified" msgstr "язык не указан" -#: commands/functioncmds.c:1104 commands/functioncmds.c:2105 -#: commands/proclang.c:237 +#: commands/functioncmds.c:1099 commands/functioncmds.c:2117 +#: commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "язык \"%s\" не существует" -#: commands/functioncmds.c:1106 commands/functioncmds.c:2107 +#: commands/functioncmds.c:1101 commands/functioncmds.c:2119 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "Выполните CREATE EXTENSION, чтобы загрузить язык в базу данных." -#: commands/functioncmds.c:1139 commands/functioncmds.c:1424 +#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 #, c-format msgid "only superuser can define a leakproof function" msgstr "" "только суперпользователь может определить функцию с атрибутом LEAKPROOF" -#: commands/functioncmds.c:1190 +#: commands/functioncmds.c:1185 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "" "результат функции должен иметь тип %s (в соответствии с параметрами OUT)" -#: commands/functioncmds.c:1203 +#: commands/functioncmds.c:1198 #, c-format msgid "function result type must be specified" msgstr "необходимо указать тип результата функции" -#: commands/functioncmds.c:1256 commands/functioncmds.c:1444 +#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "указание ROWS неприменимо, когда функция возвращает не множество" -#: commands/functioncmds.c:1547 +#: commands/functioncmds.c:1546 #, c-format msgid "source data type %s is a pseudo-type" msgstr "исходный тип данных %s является псевдотипом" -#: commands/functioncmds.c:1553 +#: commands/functioncmds.c:1552 #, c-format msgid "target data type %s is a pseudo-type" msgstr "целевой тип данных %s является псевдотипом" -#: commands/functioncmds.c:1577 +#: commands/functioncmds.c:1576 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "" "приведение будет проигнорировано, так как исходные данные имеют тип домен" -#: commands/functioncmds.c:1582 +#: commands/functioncmds.c:1581 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "" "приведение будет проигнорировано, так как целевые данные имеют тип домен" -#: commands/functioncmds.c:1607 +#: commands/functioncmds.c:1606 #, c-format msgid "cast function must take one to three arguments" msgstr "функция приведения должна принимать от одного до трёх аргументов" -#: commands/functioncmds.c:1613 +#: commands/functioncmds.c:1612 #, c-format msgid "" "argument of cast function must match or be binary-coercible from source data " @@ -9537,17 +9967,17 @@ msgstr "" "аргумент функции приведения должен совпадать или быть двоично-совместимым с " "исходным типом данных" -#: commands/functioncmds.c:1617 +#: commands/functioncmds.c:1616 #, c-format msgid "second argument of cast function must be type %s" msgstr "второй аргумент функции приведения должен иметь тип %s" -#: commands/functioncmds.c:1622 +#: commands/functioncmds.c:1621 #, c-format msgid "third argument of cast function must be type %s" msgstr "третий аргумент функции приведения должен иметь тип %s" -#: commands/functioncmds.c:1629 +#: commands/functioncmds.c:1628 #, c-format msgid "" "return data type of cast function must match or be binary-coercible to " @@ -9556,127 +9986,132 @@ msgstr "" "тип возвращаемых данных функции приведения должен совпадать или быть двоично-" "совместимым с целевым типом данных" -#: commands/functioncmds.c:1640 +#: commands/functioncmds.c:1639 #, c-format msgid "cast function must not be volatile" msgstr "функция приведения не может быть изменчивой (volatile)" -#: commands/functioncmds.c:1645 +#: commands/functioncmds.c:1644 #, c-format msgid "cast function must be a normal function" msgstr "функция приведения должна быть обычной функцией" -#: commands/functioncmds.c:1649 +#: commands/functioncmds.c:1648 #, c-format msgid "cast function must not return a set" msgstr "функция приведения не может возвращать множество" -#: commands/functioncmds.c:1675 +#: commands/functioncmds.c:1674 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "для создания приведения WITHOUT FUNCTION нужно быть суперпользователем" -#: commands/functioncmds.c:1690 +#: commands/functioncmds.c:1689 #, c-format msgid "source and target data types are not physically compatible" msgstr "исходный и целевой типы данных несовместимы физически" -#: commands/functioncmds.c:1705 +#: commands/functioncmds.c:1709 #, c-format msgid "composite data types are not binary-compatible" msgstr "составные типы данных несовместимы на двоичном уровне" -#: commands/functioncmds.c:1711 -#, c-format -msgid "enum data types are not binary-compatible" -msgstr "типы-перечисления несовместимы на двоичном уровне" - -#: commands/functioncmds.c:1717 +#: commands/functioncmds.c:1715 #, c-format msgid "array data types are not binary-compatible" msgstr "типы-массивы несовместимы на двоичном уровне" -#: commands/functioncmds.c:1734 +#: commands/functioncmds.c:1723 +#, c-format +msgid "range data types are not binary-compatible" +msgstr "диапазонные типы несовместимы на двоичном уровне" + +#: commands/functioncmds.c:1729 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "типы-перечисления несовместимы на двоичном уровне" + +#: commands/functioncmds.c:1746 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "типы-домены не могут считаться двоично-совместимыми" -#: commands/functioncmds.c:1744 +#: commands/functioncmds.c:1756 #, c-format msgid "source data type and target data type are the same" msgstr "исходный тип данных совпадает с целевым" -#: commands/functioncmds.c:1777 +#: commands/functioncmds.c:1789 #, c-format msgid "transform function must not be volatile" msgstr "функция преобразования не может быть изменчивой" -#: commands/functioncmds.c:1781 +#: commands/functioncmds.c:1793 #, c-format msgid "transform function must be a normal function" msgstr "функция преобразования должна быть обычной функцией" -#: commands/functioncmds.c:1785 +#: commands/functioncmds.c:1797 #, c-format msgid "transform function must not return a set" msgstr "функция преобразования не может возвращать множество" -#: commands/functioncmds.c:1789 +#: commands/functioncmds.c:1801 #, c-format msgid "transform function must take one argument" msgstr "функция преобразования должна принимать один аргумент" -#: commands/functioncmds.c:1793 +#: commands/functioncmds.c:1805 #, c-format msgid "first argument of transform function must be type %s" msgstr "первый аргумент функции преобразования должен иметь тип %s" -#: commands/functioncmds.c:1832 +#: commands/functioncmds.c:1844 #, c-format msgid "data type %s is a pseudo-type" msgstr "тип данных %s является псевдотипом" -#: commands/functioncmds.c:1838 +#: commands/functioncmds.c:1850 #, c-format msgid "data type %s is a domain" msgstr "тип данных \"%s\" является доменом" -#: commands/functioncmds.c:1878 +#: commands/functioncmds.c:1890 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "результат функции FROM SQL должен иметь тип %s" -#: commands/functioncmds.c:1904 +#: commands/functioncmds.c:1916 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "результат функции TO SQL должен иметь тип данных преобразования" -#: commands/functioncmds.c:1931 +#: commands/functioncmds.c:1943 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "преобразование для типа %s, языка \"%s\" уже существует" -#: commands/functioncmds.c:2017 +#: commands/functioncmds.c:2029 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "преобразование для типа %s, языка \"%s\" не существует" -#: commands/functioncmds.c:2041 +#: commands/functioncmds.c:2053 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "функция %s уже существует в схеме \"%s\"" -#: commands/functioncmds.c:2092 +#: commands/functioncmds.c:2104 #, c-format msgid "no inline code specified" msgstr "нет внедрённого кода" -#: commands/functioncmds.c:2138 +#: commands/functioncmds.c:2150 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "язык \"%s\" не поддерживает выполнение внедрённого кода" -#: commands/functioncmds.c:2233 +#: commands/functioncmds.c:2245 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" @@ -9684,97 +10119,100 @@ msgstr[0] "процедуре нельзя передать больше %d ар msgstr[1] "процедуре нельзя передать больше %d аргументов" msgstr[2] "процедуре нельзя передать больше %d аргументов" -#: commands/indexcmds.c:640 +#: commands/indexcmds.c:656 #, c-format msgid "must specify at least one column" msgstr "нужно указать минимум один столбец" -#: commands/indexcmds.c:644 +#: commands/indexcmds.c:660 #, c-format msgid "cannot use more than %d columns in an index" msgstr "число столбцов в индексе не может превышать %d" -#: commands/indexcmds.c:687 +#: commands/indexcmds.c:703 #, c-format msgid "cannot create index on relation \"%s\"" msgstr "создать индекс для отношения \"%s\" нельзя" -#: commands/indexcmds.c:713 +#: commands/indexcmds.c:729 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "" "создать индекс в секционированной таблице \"%s\" параллельным способом нельзя" -#: commands/indexcmds.c:718 -#, c-format -msgid "cannot create exclusion constraints on partitioned table \"%s\"" -msgstr "" -"создать ограничение-исключение в секционированной таблице \"%s\" нельзя" - -#: commands/indexcmds.c:728 +#: commands/indexcmds.c:739 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "создавать индексы во временных таблицах других сеансов нельзя" -#: commands/indexcmds.c:766 commands/tablecmds.c:784 commands/tablespace.c:1184 +#: commands/indexcmds.c:777 commands/tablecmds.c:818 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "" "для секционированных отношений нельзя назначить табличное пространство по " "умолчанию" -#: commands/indexcmds.c:798 commands/tablecmds.c:815 commands/tablecmds.c:3405 +#: commands/indexcmds.c:809 commands/tablecmds.c:849 commands/tablecmds.c:3588 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "" "в табличное пространство pg_global можно поместить только разделяемые таблицы" -#: commands/indexcmds.c:831 +#: commands/indexcmds.c:842 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "устаревший метод доступа \"rtree\" подменяется методом \"gist\"" -#: commands/indexcmds.c:852 +#: commands/indexcmds.c:863 #, c-format msgid "access method \"%s\" does not support unique indexes" msgstr "метод доступа \"%s\" не поддерживает уникальные индексы" -#: commands/indexcmds.c:857 +#: commands/indexcmds.c:868 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "метод доступа \"%s\" не поддерживает включаемые столбцы" -#: commands/indexcmds.c:862 +#: commands/indexcmds.c:873 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "метод доступа \"%s\" не поддерживает индексы по многим столбцам" -#: commands/indexcmds.c:867 +#: commands/indexcmds.c:878 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "метод доступа \"%s\" не поддерживает ограничения-исключения" -#: commands/indexcmds.c:994 +#: commands/indexcmds.c:1007 #, c-format msgid "cannot match partition key to an index using access method \"%s\"" msgstr "" "сопоставить ключ секционирования с индексом, использующим метод доступа " "\"%s\", нельзя" -#: commands/indexcmds.c:1004 +#: commands/indexcmds.c:1017 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "" "неподдерживаемое ограничение \"%s\" с определением ключа секционирования" -#: commands/indexcmds.c:1006 +#: commands/indexcmds.c:1019 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "" "Ограничения %s не могут использоваться, когда ключи секционирования включают " "выражения." -#: commands/indexcmds.c:1048 +#: commands/indexcmds.c:1069 +#, c-format +msgid "" +"cannot match partition key to index on column \"%s\" using non-equal " +"operator \"%s\"" +msgstr "" +"сопоставить ключ секционирования с индексом, построенному по столбцу \"%s\" " +"с оператором неравенства \"%s\", нельзя" + +#: commands/indexcmds.c:1085 #, c-format msgid "" "unique constraint on partitioned table must include all partitioning columns" @@ -9782,7 +10220,7 @@ msgstr "" "ограничение уникальности в секционированной таблице должно включать все " "секционирующие столбцы" -#: commands/indexcmds.c:1049 +#: commands/indexcmds.c:1086 #, c-format msgid "" "%s constraint on table \"%s\" lacks column \"%s\" which is part of the " @@ -9791,92 +10229,92 @@ msgstr "" "В ограничении %s таблицы \"%s\" не хватает столбца \"%s\", входящего в ключ " "секционирования." -#: commands/indexcmds.c:1068 commands/indexcmds.c:1087 +#: commands/indexcmds.c:1105 commands/indexcmds.c:1124 #, c-format msgid "index creation on system columns is not supported" msgstr "создание индекса для системных столбцов не поддерживается" -#: commands/indexcmds.c:1316 tcop/utility.c:1526 +#: commands/indexcmds.c:1354 tcop/utility.c:1515 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "создать уникальный индекс в секционированной таблице \"%s\" нельзя" -#: commands/indexcmds.c:1318 tcop/utility.c:1528 +#: commands/indexcmds.c:1356 tcop/utility.c:1517 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "Таблица \"%s\" содержит секции, являющиеся сторонними таблицами." -#: commands/indexcmds.c:1803 +#: commands/indexcmds.c:1806 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "функции в предикате индекса должны быть помечены как IMMUTABLE" -#: commands/indexcmds.c:1881 parser/parse_utilcmd.c:2522 -#: parser/parse_utilcmd.c:2657 +#: commands/indexcmds.c:1885 parser/parse_utilcmd.c:2519 +#: parser/parse_utilcmd.c:2654 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "указанный в ключе столбец \"%s\" не существует" -#: commands/indexcmds.c:1905 parser/parse_utilcmd.c:1821 +#: commands/indexcmds.c:1909 parser/parse_utilcmd.c:1807 #, c-format msgid "expressions are not supported in included columns" msgstr "выражения во включаемых столбцах не поддерживаются" -#: commands/indexcmds.c:1946 +#: commands/indexcmds.c:1950 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "функции в индексном выражении должны быть помечены как IMMUTABLE" -#: commands/indexcmds.c:1961 +#: commands/indexcmds.c:1965 #, c-format msgid "including column does not support a collation" msgstr "включаемые столбцы не поддерживают правила сортировки" -#: commands/indexcmds.c:1965 +#: commands/indexcmds.c:1969 #, c-format msgid "including column does not support an operator class" msgstr "включаемые столбцы не поддерживают классы операторов" -#: commands/indexcmds.c:1969 +#: commands/indexcmds.c:1973 #, c-format msgid "including column does not support ASC/DESC options" msgstr "включаемые столбцы не поддерживают сортировку ASC/DESC" -#: commands/indexcmds.c:1973 +#: commands/indexcmds.c:1977 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "включаемые столбцы не поддерживают указания NULLS FIRST/LAST" -#: commands/indexcmds.c:2014 +#: commands/indexcmds.c:2020 #, c-format msgid "could not determine which collation to use for index expression" msgstr "не удалось определить правило сортировки для индексного выражения" -#: commands/indexcmds.c:2022 commands/tablecmds.c:17534 commands/typecmds.c:807 -#: parser/parse_expr.c:2722 parser/parse_type.c:568 parser/parse_utilcmd.c:3783 -#: utils/adt/misc.c:586 +#: commands/indexcmds.c:2028 commands/tablecmds.c:18185 commands/typecmds.c:811 +#: parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3771 +#: utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "тип %s не поддерживает сортировку (COLLATION)" -#: commands/indexcmds.c:2087 +#: commands/indexcmds.c:2095 #, c-format msgid "operator %s is not commutative" msgstr "оператор %s не коммутативен" -#: commands/indexcmds.c:2089 +#: commands/indexcmds.c:2097 #, c-format msgid "Only commutative operators can be used in exclusion constraints." msgstr "" "В ограничениях-исключениях могут использоваться только коммутативные " "операторы." -#: commands/indexcmds.c:2115 +#: commands/indexcmds.c:2123 #, c-format msgid "operator %s is not a member of operator family \"%s\"" msgstr "оператор \"%s\" не входит в семейство операторов \"%s\"" -#: commands/indexcmds.c:2118 +#: commands/indexcmds.c:2126 #, c-format msgid "" "The exclusion operator must be related to the index operator class for the " @@ -9885,25 +10323,25 @@ msgstr "" "Оператор исключения для ограничения должен относиться к классу операторов " "индекса." -#: commands/indexcmds.c:2153 +#: commands/indexcmds.c:2161 #, c-format msgid "access method \"%s\" does not support ASC/DESC options" msgstr "метод доступа \"%s\" не поддерживает сортировку ASC/DESC" -#: commands/indexcmds.c:2158 +#: commands/indexcmds.c:2166 #, c-format msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "метод доступа \"%s\" не поддерживает параметр NULLS FIRST/LAST" -#: commands/indexcmds.c:2204 commands/tablecmds.c:17559 -#: commands/tablecmds.c:17565 commands/typecmds.c:2301 +#: commands/indexcmds.c:2210 commands/tablecmds.c:18210 +#: commands/tablecmds.c:18216 commands/typecmds.c:2311 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "" "для типа данных %s не определён класс операторов по умолчанию для метода " "доступа \"%s\"" -#: commands/indexcmds.c:2206 +#: commands/indexcmds.c:2212 #, c-format msgid "" "You must specify an operator class for the index or define a default " @@ -9912,86 +10350,89 @@ msgstr "" "Вы должны указать класс операторов для индекса или определить класс " "операторов по умолчанию для этого типа данных." -#: commands/indexcmds.c:2235 commands/indexcmds.c:2243 +#: commands/indexcmds.c:2241 commands/indexcmds.c:2249 #: commands/opclasscmds.c:205 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "класс операторов \"%s\" для метода доступа \"%s\" не существует" -#: commands/indexcmds.c:2257 commands/typecmds.c:2289 +#: commands/indexcmds.c:2263 commands/typecmds.c:2299 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "класс операторов \"%s\" не принимает тип данных %s" -#: commands/indexcmds.c:2347 +#: commands/indexcmds.c:2353 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "" "для типа данных %s определено несколько классов операторов по умолчанию" -#: commands/indexcmds.c:2675 +#: commands/indexcmds.c:2681 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "нераспознанный параметр REINDEX: \"%s\"" -#: commands/indexcmds.c:2899 +#: commands/indexcmds.c:2913 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "" "в таблице \"%s\" нет индексов, которые можно переиндексировать неблокирующим " "способом" -#: commands/indexcmds.c:2913 +#: commands/indexcmds.c:2927 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "в таблице \"%s\" нет индексов для переиндексации" -#: commands/indexcmds.c:2958 commands/indexcmds.c:3468 -#: commands/indexcmds.c:3596 +#: commands/indexcmds.c:2974 commands/indexcmds.c:3485 +#: commands/indexcmds.c:3615 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "Переиндексировать системные каталоги неблокирующим способом нельзя" -#: commands/indexcmds.c:2981 +#: commands/indexcmds.c:2998 #, c-format msgid "can only reindex the currently open database" msgstr "переиндексировать можно только текущую базу данных" -#: commands/indexcmds.c:3075 +#: commands/indexcmds.c:3090 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "" "все системные каталоги пропускаются, так как их нельзя переиндексировать " "неблокирующим способом" -#: commands/indexcmds.c:3108 +#: commands/indexcmds.c:3123 #, c-format msgid "cannot move system relations, skipping all" msgstr "переместить системные отношения нельзя, все они пропускаются" -#: commands/indexcmds.c:3154 +#: commands/indexcmds.c:3169 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "при переиндексировании секционированной таблицы \"%s.%s\"" -#: commands/indexcmds.c:3157 +#: commands/indexcmds.c:3172 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "при перестроении секционированного индекса \"%s.%s\"" -#: commands/indexcmds.c:3348 commands/indexcmds.c:4204 +#: commands/indexcmds.c:3365 commands/indexcmds.c:4241 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "таблица \"%s.%s\" переиндексирована" -#: commands/indexcmds.c:3500 commands/indexcmds.c:3552 +#: commands/indexcmds.c:3517 commands/indexcmds.c:3570 #, c-format -msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" -msgstr "" -"перестроить нерабочий индекс \"%s.%s\" неблокирующим способом нельзя, он " -"пропускается" +msgid "skipping reindex of invalid index \"%s.%s\"" +msgstr "индекс \"%s.%s\" — нерабочий, переиндексация пропускается" + +#: commands/indexcmds.c:3520 commands/indexcmds.c:3573 +#, c-format +msgid "Use DROP INDEX or REINDEX INDEX." +msgstr "Выполните DROP INDEX или REINDEX INDEX." -#: commands/indexcmds.c:3506 +#: commands/indexcmds.c:3524 #, c-format msgid "" "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" @@ -9999,51 +10440,51 @@ msgstr "" "перестроить индекс ограничения-исключения \"%s.%s\" неблокирующим способом " "нельзя, он пропускается" -#: commands/indexcmds.c:3661 +#: commands/indexcmds.c:3680 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "переиндексировать отношение такого типа неблокирующим способом нельзя" -#: commands/indexcmds.c:3682 +#: commands/indexcmds.c:3698 #, c-format msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "" "переместить отношение, не являющееся разделяемым, в табличное пространство " "\"%s\" нельзя" -#: commands/indexcmds.c:4185 commands/indexcmds.c:4197 +#: commands/indexcmds.c:4222 commands/indexcmds.c:4234 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr "индекс \"%s.%s\" был перестроен" -#: commands/indexcmds.c:4187 commands/indexcmds.c:4206 +#: commands/indexcmds.c:4224 commands/indexcmds.c:4243 #, c-format msgid "%s." msgstr "%s." -#: commands/lockcmds.c:92 +#: commands/lockcmds.c:91 #, c-format msgid "cannot lock relation \"%s\"" msgstr "заблокировать отношение \"%s\" нельзя" -#: commands/matview.c:193 +#: commands/matview.c:206 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "" "CONCURRENTLY нельзя использовать, когда материализованное представление не " "наполнено" -#: commands/matview.c:199 gram.y:18306 +#: commands/matview.c:212 gram.y:18918 #, c-format msgid "%s and %s options cannot be used together" msgstr "параметры %s и %s исключают друг друга" -#: commands/matview.c:256 +#: commands/matview.c:269 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "обновить материализованное представление \"%s\" параллельно нельзя" -#: commands/matview.c:259 +#: commands/matview.c:272 #, c-format msgid "" "Create a unique index with no WHERE clause on one or more columns of the " @@ -10052,7 +10493,7 @@ msgstr "" "Создайте уникальный индекс без предложения WHERE для одного или нескольких " "столбцов материализованного представления." -#: commands/matview.c:653 +#: commands/matview.c:666 #, c-format msgid "" "new data for materialized view \"%s\" contains duplicate rows without any " @@ -10061,7 +10502,7 @@ msgstr "" "новые данные для материализованного представления \"%s\" содержат " "дублирующиеся строки (без учёта столбцов с NULL)" -#: commands/matview.c:655 +#: commands/matview.c:668 #, c-format msgid "Row: %s" msgstr "Строка: %s" @@ -10276,22 +10717,22 @@ msgstr "номер оператора %d для (%s,%s) дублируется" msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "оператор %d(%s,%s) уже существует в семействе \"%s\"" -#: commands/opclasscmds.c:1566 +#: commands/opclasscmds.c:1589 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "функция %d(%s,%s) уже существует в семействе операторов \"%s\"" -#: commands/opclasscmds.c:1647 +#: commands/opclasscmds.c:1744 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "оператор %d(%s,%s) не существует в семействе операторов \"%s\"" -#: commands/opclasscmds.c:1687 +#: commands/opclasscmds.c:1784 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "функция %d(%s,%s) не существует в семействе операторов \"%s\"" -#: commands/opclasscmds.c:1718 +#: commands/opclasscmds.c:1815 #, c-format msgid "" "operator class \"%s\" for access method \"%s\" already exists in schema " @@ -10300,7 +10741,7 @@ msgstr "" "класс операторов \"%s\" для метода доступа \"%s\" уже существует в схеме " "\"%s\"" -#: commands/opclasscmds.c:1741 +#: commands/opclasscmds.c:1838 #, c-format msgid "" "operator family \"%s\" for access method \"%s\" already exists in schema " @@ -10314,7 +10755,7 @@ msgstr "" msgid "SETOF type not allowed for operator argument" msgstr "аргументом оператора не может быть тип SETOF" -#: commands/operatorcmds.c:154 commands/operatorcmds.c:481 +#: commands/operatorcmds.c:154 commands/operatorcmds.c:554 #, c-format msgid "operator attribute \"%s\" not recognized" msgstr "атрибут оператора \"%s\" не распознан" @@ -10354,53 +10795,70 @@ msgstr "функция оценки соединения %s присутству msgid "join estimator function %s must return type %s" msgstr "функция оценки соединения %s должна возвращать тип %s" -#: commands/operatorcmds.c:475 +#: commands/operatorcmds.c:388 parser/parse_oper.c:119 parser/parse_oper.c:637 +#: utils/adt/regproc.c:509 utils/adt/regproc.c:683 +#, c-format +msgid "operator does not exist: %s" +msgstr "оператор не существует: %s" + +#: commands/operatorcmds.c:396 parser/parse_oper.c:702 parser/parse_oper.c:815 +#, c-format +msgid "operator is only a shell: %s" +msgstr "оператор \"%s\" - лишь оболочка" + +#: commands/operatorcmds.c:548 #, c-format msgid "operator attribute \"%s\" cannot be changed" msgstr "атрибут оператора \"%s\" нельзя изменить" -#: commands/policy.c:89 commands/policy.c:382 commands/statscmds.c:149 -#: commands/tablecmds.c:1612 commands/tablecmds.c:2215 -#: commands/tablecmds.c:3516 commands/tablecmds.c:6365 -#: commands/tablecmds.c:9192 commands/tablecmds.c:17121 -#: commands/tablecmds.c:17156 commands/trigger.c:323 commands/trigger.c:1339 -#: commands/trigger.c:1449 rewrite/rewriteDefine.c:275 -#: rewrite/rewriteDefine.c:786 rewrite/rewriteRemove.c:80 +#: commands/operatorcmds.c:615 commands/operatorcmds.c:622 +#: commands/operatorcmds.c:628 commands/operatorcmds.c:634 +#, c-format +msgid "operator attribute \"%s\" cannot be changed if it has already been set" +msgstr "атрибут оператора \"%s\" нельзя изменить, если он уже установлен" + +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 +#: commands/tablecmds.c:1740 commands/tablecmds.c:2340 +#: commands/tablecmds.c:3702 commands/tablecmds.c:6605 +#: commands/tablecmds.c:9637 commands/tablecmds.c:17772 +#: commands/tablecmds.c:17807 commands/trigger.c:316 commands/trigger.c:1332 +#: commands/trigger.c:1442 rewrite/rewriteDefine.c:268 +#: rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "доступ запрещён: \"%s\" - это системный каталог" -#: commands/policy.c:172 +#: commands/policy.c:169 #, c-format msgid "ignoring specified roles other than PUBLIC" msgstr "все указанные роли, кроме PUBLIC, игнорируются" -#: commands/policy.c:173 +#: commands/policy.c:170 #, c-format msgid "All roles are members of the PUBLIC role." msgstr "Роль PUBLIC включает в себя все остальные роли." -#: commands/policy.c:606 +#: commands/policy.c:603 #, c-format msgid "WITH CHECK cannot be applied to SELECT or DELETE" msgstr "WITH CHECK нельзя применить к SELECT или DELETE" -#: commands/policy.c:615 commands/policy.c:918 +#: commands/policy.c:612 commands/policy.c:915 #, c-format msgid "only WITH CHECK expression allowed for INSERT" msgstr "для INSERT допускается только выражение WITH CHECK" -#: commands/policy.c:689 commands/policy.c:1141 +#: commands/policy.c:686 commands/policy.c:1138 #, c-format msgid "policy \"%s\" for table \"%s\" already exists" msgstr "политика \"%s\" для таблицы \"%s\" уже существует" -#: commands/policy.c:890 commands/policy.c:1169 commands/policy.c:1240 +#: commands/policy.c:887 commands/policy.c:1166 commands/policy.c:1237 #, c-format msgid "policy \"%s\" for table \"%s\" does not exist" msgstr "политика \"%s\" для таблицы \"%s\" не существует" -#: commands/policy.c:908 +#: commands/policy.c:905 #, c-format msgid "only USING expression allowed for SELECT, DELETE" msgstr "для SELECT, DELETE допускается только выражение USING" @@ -10418,87 +10876,86 @@ msgstr "" "HOLD" #: commands/portalcmds.c:189 commands/portalcmds.c:242 -#: executor/execCurrent.c:70 utils/adt/xml.c:2854 utils/adt/xml.c:3024 +#: executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "курсор \"%s\" не существует" -#: commands/prepare.c:75 +#: commands/prepare.c:72 #, c-format msgid "invalid statement name: must not be empty" msgstr "неверный оператор: имя не должно быть пустым" # [SM]: TO REVIEW -#: commands/prepare.c:230 commands/prepare.c:235 +#: commands/prepare.c:227 commands/prepare.c:232 #, c-format msgid "prepared statement is not a SELECT" msgstr "подготовленный оператор - не SELECT" -#: commands/prepare.c:295 +#: commands/prepare.c:292 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "неверное число параметров для подготовленного оператора \"%s\"" -#: commands/prepare.c:297 +#: commands/prepare.c:294 #, c-format msgid "Expected %d parameters but got %d." msgstr "Ожидалось параметров: %d, получено: %d." -#: commands/prepare.c:330 +#: commands/prepare.c:327 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "параметр $%d типа %s нельзя привести к ожидаемому типу %s" # [SM]: TO REVIEW -#: commands/prepare.c:414 +#: commands/prepare.c:411 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "подготовленный оператор \"%s\" уже существует" # [SM]: TO REVIEW -#: commands/prepare.c:453 +#: commands/prepare.c:450 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "подготовленный оператор \"%s\" не существует" -#: commands/proclang.c:68 +#: commands/proclang.c:66 #, c-format msgid "must be superuser to create custom procedural language" msgstr "" "для создания дополнительного процедурного языка нужно быть суперпользователем" -#: commands/publicationcmds.c:131 postmaster/postmaster.c:1208 -#: postmaster/postmaster.c:1306 storage/file/fd.c:3911 -#: utils/init/miscinit.c:1822 +#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 +#: postmaster/postmaster.c:1210 utils/init/miscinit.c:1865 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "неверный формат списка в параметре \"%s\"" -#: commands/publicationcmds.c:150 +#: commands/publicationcmds.c:143 #, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" msgstr "нераспознанное значение параметра публикации \"%s\": \"%s\"" -#: commands/publicationcmds.c:164 +#: commands/publicationcmds.c:157 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "нераспознанный параметр репликации: \"%s\"" -#: commands/publicationcmds.c:205 +#: commands/publicationcmds.c:198 #, c-format msgid "no schema has been selected for CURRENT_SCHEMA" msgstr "для CURRENT_SCHEMA требуется, чтобы была выбрана схема" -#: commands/publicationcmds.c:502 +#: commands/publicationcmds.c:495 msgid "System columns are not allowed." msgstr "Системные столбцы не допускаются." -#: commands/publicationcmds.c:509 commands/publicationcmds.c:514 -#: commands/publicationcmds.c:531 +#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 +#: commands/publicationcmds.c:524 msgid "User-defined operators are not allowed." msgstr "Пользовательские операторы не допускаются." -#: commands/publicationcmds.c:555 +#: commands/publicationcmds.c:548 msgid "" "Only columns, constants, built-in operators, built-in data types, built-in " "collations, and immutable built-in functions are allowed." @@ -10506,43 +10963,43 @@ msgstr "" "Допускаются только столбцы, константы, встроенные операторы, встроенные типы " "данных, встроенные правила сортировки и встроенные постоянные функции." -#: commands/publicationcmds.c:567 +#: commands/publicationcmds.c:560 msgid "User-defined types are not allowed." msgstr "Пользовательские типы не допускаются." -#: commands/publicationcmds.c:570 +#: commands/publicationcmds.c:563 msgid "User-defined or built-in mutable functions are not allowed." msgstr "Пользовательские или встроенные непостоянные функции не допускаются." -#: commands/publicationcmds.c:573 +#: commands/publicationcmds.c:566 msgid "User-defined collations are not allowed." msgstr "Пользовательские правила сортировки не допускаются." -#: commands/publicationcmds.c:583 +#: commands/publicationcmds.c:576 #, c-format msgid "invalid publication WHERE expression" msgstr "неверное выражение в предложении WHERE публикации" -#: commands/publicationcmds.c:636 +#: commands/publicationcmds.c:629 #, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" msgstr "" "использовать в публикации предложение WHERE для отношения \"%s\" нельзя" -#: commands/publicationcmds.c:638 +#: commands/publicationcmds.c:631 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." msgstr "" "Предложение WHERE нельзя использовать для секционированной таблицы, когда %s " "равен false." -#: commands/publicationcmds.c:709 commands/publicationcmds.c:723 +#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 #, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" msgstr "" "использовать список столбцов отношения \"%s.%s\" в публикации \"%s\" нельзя" -#: commands/publicationcmds.c:712 +#: commands/publicationcmds.c:705 #, c-format msgid "" "Column lists cannot be specified in publications containing FOR TABLES IN " @@ -10551,7 +11008,7 @@ msgstr "" "Списки столбцов нельзя задавать в публикациях, содержащих элементы FOR " "TABLES IN SCHEMA." -#: commands/publicationcmds.c:726 +#: commands/publicationcmds.c:719 #, c-format msgid "" "Column lists cannot be specified for partitioned tables when %s is false." @@ -10559,34 +11016,34 @@ msgstr "" "Списки столбцов нельзя задавать для секционированных таблиц, когда %s равен " "false." -#: commands/publicationcmds.c:761 +#: commands/publicationcmds.c:754 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "для создания публикации всех таблиц нужно быть суперпользователем" -#: commands/publicationcmds.c:832 +#: commands/publicationcmds.c:825 #, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" msgstr "" "для создания публикации вида FOR ALL TABLES IN SCHEMA нужно быть " "суперпользователем" -#: commands/publicationcmds.c:868 +#: commands/publicationcmds.c:861 #, c-format -msgid "wal_level is insufficient to publish logical changes" -msgstr "уровень wal_level недостаточен для публикации логических изменений" +msgid "\"wal_level\" is insufficient to publish logical changes" +msgstr "уровень \"wal_level\" недостаточен для публикации логических изменений" -#: commands/publicationcmds.c:869 +#: commands/publicationcmds.c:862 #, c-format -msgid "Set wal_level to \"logical\" before creating subscriptions." -msgstr "Задайте для wal_level значение \"logical\" до создания подписок." +msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." +msgstr "Задайте для \"wal_level\" значение \"logical\" до создания подписок." -#: commands/publicationcmds.c:965 commands/publicationcmds.c:973 +#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 #, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" msgstr "параметру \"%s\" публикации \"%s\" нельзя присвоить false" -#: commands/publicationcmds.c:968 +#: commands/publicationcmds.c:961 #, c-format msgid "" "The publication contains a WHERE clause for partitioned table \"%s\", which " @@ -10595,7 +11052,7 @@ msgstr "" "Публикация содержит предложение WHERE для секционированной таблицы \"%s\", " "что не допускается, когда \"%s\" равен false." -#: commands/publicationcmds.c:976 +#: commands/publicationcmds.c:969 #, c-format msgid "" "The publication contains a column list for partitioned table \"%s\", which " @@ -10604,12 +11061,12 @@ msgstr "" "Публикация содержит список столбцов для секционированной таблицы \"%s\", что " "не допускается, когда \"%s\" равен false." -#: commands/publicationcmds.c:1299 +#: commands/publicationcmds.c:1292 #, c-format msgid "cannot add schema to publication \"%s\"" msgstr "добавить схему в публикацию \"%s\" нельзя" -#: commands/publicationcmds.c:1301 +#: commands/publicationcmds.c:1294 #, c-format msgid "" "Schemas cannot be added if any tables that specify a column list are already " @@ -10618,82 +11075,82 @@ msgstr "" "Схемы нельзя добавлять в публикацию, если в неё уже добавлены таблицы, для " "которых задан список столбцов." -#: commands/publicationcmds.c:1349 +#: commands/publicationcmds.c:1342 #, c-format msgid "must be superuser to add or set schemas" msgstr "для добавления или замены схем нужно быть суперпользователем" -#: commands/publicationcmds.c:1358 commands/publicationcmds.c:1366 +#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "публикация \"%s\" определена для всех таблиц (FOR ALL TABLES)" -#: commands/publicationcmds.c:1360 +#: commands/publicationcmds.c:1353 #, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." msgstr "В публикации вида FOR ALL TABLES нельзя добавлять или удалять таблицы." -#: commands/publicationcmds.c:1368 +#: commands/publicationcmds.c:1361 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "В публикации всех таблиц нельзя добавлять или удалять таблицы." -#: commands/publicationcmds.c:1392 commands/publicationcmds.c:1431 -#: commands/publicationcmds.c:1968 utils/cache/lsyscache.c:3592 +#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 +#: commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 #, c-format msgid "publication \"%s\" does not exist" msgstr "публикация \"%s\" не существует" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1657 +#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 #, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" msgstr "конфликтующие или избыточные предложения WHERE для таблицы \"%s\"" -#: commands/publicationcmds.c:1601 commands/publicationcmds.c:1669 +#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 #, c-format msgid "conflicting or redundant column lists for table \"%s\"" msgstr "конфликтующие или избыточные списки столбцов для таблицы \"%s\"" -#: commands/publicationcmds.c:1803 +#: commands/publicationcmds.c:1796 #, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" msgstr "в ALTER PUBLICATION ... DROP не должен задаваться список столбцов" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1808 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "отношение \"%s\" не включено в публикацию" -#: commands/publicationcmds.c:1822 +#: commands/publicationcmds.c:1815 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "использовать WHERE при удалении таблицы из публикации нельзя" -#: commands/publicationcmds.c:1882 +#: commands/publicationcmds.c:1875 #, c-format msgid "tables from schema \"%s\" are not part of the publication" msgstr "таблицы из схемы \"%s\" не являются частью публикации" -#: commands/publicationcmds.c:1925 commands/publicationcmds.c:1932 +#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 #, c-format msgid "permission denied to change owner of publication \"%s\"" -msgstr "нет прав на изменение владельца публикации \"%s\"" +msgstr "нет прав для изменения владельца публикации \"%s\"" -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:1920 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "" "Владельцем публикации всех таблиц (FOR ALL TABLES) должен быть " "суперпользователь." -#: commands/publicationcmds.c:1934 +#: commands/publicationcmds.c:1927 #, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." msgstr "" "Владельцем публикации вида FOR TABLES IN SCHEMA должен быть " "суперпользователь." -#: commands/publicationcmds.c:2000 +#: commands/publicationcmds.c:1993 #, c-format msgid "publication with OID %u does not exist" msgstr "публикация с OID %u не существует" @@ -10741,170 +11198,170 @@ msgstr "метки безопасности не поддерживаются д msgid "cannot set security label on relation \"%s\"" msgstr "задать метку безопасности для отношения \"%s\" нельзя" -#: commands/sequence.c:754 +#: commands/sequence.c:748 #, c-format msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" msgstr "" "функция nextval достигла максимума для последовательности \"%s\" (%lld)" -#: commands/sequence.c:773 +#: commands/sequence.c:767 #, c-format msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" msgstr "функция nextval достигла минимума для последовательности \"%s\" (%lld)" -#: commands/sequence.c:891 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "" "текущее значение (currval) для последовательности \"%s\" ещё не определено в " "этом сеансе" -#: commands/sequence.c:910 commands/sequence.c:916 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "последнее значение (lastval) ещё не определено в этом сеансе" -#: commands/sequence.c:996 +#: commands/sequence.c:991 #, c-format msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" msgstr "" "функции setval передано значение %lld вне пределов последовательности " "\"%s\" (%lld..%lld)" -#: commands/sequence.c:1365 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "неверное свойство последовательности SEQUENCE NAME" -#: commands/sequence.c:1391 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "" "типом столбца идентификации может быть только smallint, integer или bigint" -#: commands/sequence.c:1392 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "" "типом последовательности может быть только smallint, integer или bigint" -#: commands/sequence.c:1426 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENT не может быть нулевым" -#: commands/sequence.c:1474 +#: commands/sequence.c:1466 #, c-format msgid "MAXVALUE (%lld) is out of range for sequence data type %s" msgstr "MAXVALUE (%lld) выходит за пределы типа данных последовательности %s" -#: commands/sequence.c:1506 +#: commands/sequence.c:1498 #, c-format msgid "MINVALUE (%lld) is out of range for sequence data type %s" msgstr "MINVALUE (%lld) выходит за пределы типа данных последовательности %s" -#: commands/sequence.c:1514 +#: commands/sequence.c:1506 #, c-format msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" msgstr "MINVALUE (%lld) должно быть меньше MAXVALUE (%lld)" -#: commands/sequence.c:1535 +#: commands/sequence.c:1527 #, c-format msgid "START value (%lld) cannot be less than MINVALUE (%lld)" msgstr "значение START (%lld) не может быть меньше MINVALUE (%lld)" -#: commands/sequence.c:1541 +#: commands/sequence.c:1533 #, c-format msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "значение START (%lld) не может быть больше MAXVALUE (%lld)" -#: commands/sequence.c:1565 +#: commands/sequence.c:1557 #, c-format msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" msgstr "значение RESTART (%lld) не может быть меньше MINVALUE (%lld)" -#: commands/sequence.c:1571 +#: commands/sequence.c:1563 #, c-format msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "значение RESTART (%lld) не может быть больше MAXVALUE (%lld)" -#: commands/sequence.c:1582 +#: commands/sequence.c:1574 #, c-format msgid "CACHE (%lld) must be greater than zero" msgstr "значение CACHE (%lld) должно быть больше нуля" -#: commands/sequence.c:1618 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "неверное указание OWNED BY" # skip-rule: no-space-after-period -#: commands/sequence.c:1619 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "Укажите OWNED BY таблица.столбец или OWNED BY NONE." -#: commands/sequence.c:1644 +#: commands/sequence.c:1636 #, c-format msgid "sequence cannot be owned by relation \"%s\"" msgstr "последовательность не может принадлежать отношению \"%s\"" -#: commands/sequence.c:1652 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "" "последовательность должна иметь того же владельца, что и таблица, с которой " "она связана" -#: commands/sequence.c:1656 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "" "последовательность должна быть в той же схеме, что и таблица, с которой она " "связана" -#: commands/sequence.c:1678 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "сменить владельца последовательности идентификации нельзя" -#: commands/sequence.c:1679 commands/tablecmds.c:13945 -#: commands/tablecmds.c:16544 +#: commands/sequence.c:1671 commands/tablecmds.c:14486 +#: commands/tablecmds.c:17181 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "Последовательность \"%s\" связана с таблицей \"%s\"." -#: commands/statscmds.c:109 commands/statscmds.c:118 tcop/utility.c:1887 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "в CREATE STATISTICS можно указать только одно отношение" -#: commands/statscmds.c:136 +#: commands/statscmds.c:133 #, c-format msgid "cannot define statistics for relation \"%s\"" msgstr "для отношения \"%s\" нельзя определить объект статистики" -#: commands/statscmds.c:190 +#: commands/statscmds.c:187 #, c-format msgid "statistics object \"%s\" already exists, skipping" msgstr "объект статистики \"%s\" уже существует, пропускается" -#: commands/statscmds.c:198 +#: commands/statscmds.c:195 #, c-format msgid "statistics object \"%s\" already exists" msgstr "объект статистики \"%s\" уже существует" -#: commands/statscmds.c:209 +#: commands/statscmds.c:206 #, c-format msgid "cannot have more than %d columns in statistics" msgstr "в статистике не может быть больше %d столбцов" -#: commands/statscmds.c:250 commands/statscmds.c:273 commands/statscmds.c:307 +#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 #, c-format msgid "statistics creation on system columns is not supported" msgstr "создание статистики для системных столбцов не поддерживается" -#: commands/statscmds.c:257 commands/statscmds.c:280 +#: commands/statscmds.c:254 commands/statscmds.c:277 #, c-format msgid "" "column \"%s\" cannot be used in statistics because its type %s has no " @@ -10913,7 +11370,7 @@ msgstr "" "столбец \"%s\" нельзя использовать в статистике, так как для его типа %s не " "определён класс операторов B-дерева по умолчанию" -#: commands/statscmds.c:324 +#: commands/statscmds.c:321 #, c-format msgid "" "expression cannot be used in multivariate statistics because its type %s has " @@ -10922,7 +11379,7 @@ msgstr "" "выражение нельзя использовать в многовариантной статистике, так как для его " "типа %s не определён класс операторов btree по умолчанию" -#: commands/statscmds.c:345 +#: commands/statscmds.c:342 #, c-format msgid "" "when building statistics on a single expression, statistics kinds may not be " @@ -10931,76 +11388,76 @@ msgstr "" "при построении статистики по единственному выражению указывать виды " "статистики нельзя" -#: commands/statscmds.c:374 +#: commands/statscmds.c:371 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "нераспознанный вид статистики \"%s\"" -#: commands/statscmds.c:403 +#: commands/statscmds.c:400 #, c-format msgid "extended statistics require at least 2 columns" msgstr "для расширенной статистики требуются минимум 2 столбца" -#: commands/statscmds.c:421 +#: commands/statscmds.c:418 #, c-format msgid "duplicate column name in statistics definition" msgstr "повторяющееся имя столбца в определении статистики" -#: commands/statscmds.c:456 +#: commands/statscmds.c:453 #, c-format msgid "duplicate expression in statistics definition" msgstr "повторяющееся выражение в определении статистики" -#: commands/statscmds.c:619 commands/tablecmds.c:8187 +#: commands/statscmds.c:628 commands/tablecmds.c:8620 #, c-format msgid "statistics target %d is too low" msgstr "ориентир статистики слишком мал (%d)" -#: commands/statscmds.c:627 commands/tablecmds.c:8195 +#: commands/statscmds.c:636 commands/tablecmds.c:8628 #, c-format msgid "lowering statistics target to %d" msgstr "ориентир статистики снижается до %d" -#: commands/statscmds.c:650 +#: commands/statscmds.c:660 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "объект статистики \"%s.%s\" не существует, пропускается" -#: commands/subscriptioncmds.c:271 commands/subscriptioncmds.c:359 +#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 #, c-format msgid "unrecognized subscription parameter: \"%s\"" msgstr "нераспознанный параметр подписки: \"%s\"" -#: commands/subscriptioncmds.c:327 replication/pgoutput/pgoutput.c:395 +#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:404 #, c-format msgid "unrecognized origin value: \"%s\"" msgstr "нераспознанное значение origin: \"%s\"" -#: commands/subscriptioncmds.c:350 +#: commands/subscriptioncmds.c:363 #, c-format msgid "invalid WAL location (LSN): %s" msgstr "неверная позиция в WAL (LSN): %s" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:374 commands/subscriptioncmds.c:381 -#: commands/subscriptioncmds.c:388 commands/subscriptioncmds.c:410 -#: commands/subscriptioncmds.c:426 +#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 +#: commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 +#: commands/subscriptioncmds.c:439 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "указания %s и %s являются взаимоисключающими" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:416 commands/subscriptioncmds.c:432 +#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 #, c-format msgid "subscription with %s must also set %s" msgstr "для подписки с параметром %s необходимо также задать %s" -#: commands/subscriptioncmds.c:494 +#: commands/subscriptioncmds.c:506 #, c-format msgid "could not receive list of publications from the publisher: %s" msgstr "не удалось получить список публикаций с публикующего сервера: %s" -#: commands/subscriptioncmds.c:526 +#: commands/subscriptioncmds.c:538 #, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" @@ -11008,33 +11465,34 @@ msgstr[0] "публикация %s не существует на публику msgstr[1] "публикации %s не существуют на публикующем сервере" msgstr[2] "публикации %s не существуют на публикующем сервере" -#: commands/subscriptioncmds.c:614 +#: commands/subscriptioncmds.c:626 #, c-format msgid "permission denied to create subscription" msgstr "нет прав для создания подписки" -#: commands/subscriptioncmds.c:615 +#: commands/subscriptioncmds.c:627 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." msgstr "Создавать подписки могут только роли с правами роли \"%s\"." -#: commands/subscriptioncmds.c:745 commands/subscriptioncmds.c:878 -#: replication/logical/tablesync.c:1334 replication/logical/worker.c:4616 +#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 +#: commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 +#: replication/logical/worker.c:4503 #, c-format msgid "could not connect to the publisher: %s" msgstr "не удалось подключиться к серверу публикации: %s" -#: commands/subscriptioncmds.c:816 +#: commands/subscriptioncmds.c:829 #, c-format msgid "created replication slot \"%s\" on publisher" msgstr "на сервере публикации создан слот репликации \"%s\"" -#: commands/subscriptioncmds.c:828 +#: commands/subscriptioncmds.c:841 #, c-format msgid "subscription was created, but is not connected" msgstr "подписка создана, но не подключена" -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:842 #, c-format msgid "" "To initiate replication, you must manually create the replication slot, " @@ -11043,36 +11501,43 @@ msgstr "" "Чтобы начать репликацию, вы должны вручную создать слот репликации, включить " "подписку, а затем обновить её." -#: commands/subscriptioncmds.c:1096 commands/subscriptioncmds.c:1509 -#: commands/subscriptioncmds.c:1892 utils/cache/lsyscache.c:3642 +#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 +#: commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 #, c-format msgid "subscription \"%s\" does not exist" msgstr "подписка \"%s\" не существует" -#: commands/subscriptioncmds.c:1152 +#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 #, c-format msgid "cannot set %s for enabled subscription" msgstr "для включённой подписки нельзя задать %s" -#: commands/subscriptioncmds.c:1234 +#: commands/subscriptioncmds.c:1233 +#, c-format +msgid "" +"cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "" +"задать параметр \"%s\" для подписки, для которой не задано имя слота, нельзя" + +#: commands/subscriptioncmds.c:1279 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "включить подписку, для которой не задано имя слота, нельзя" -#: commands/subscriptioncmds.c:1278 commands/subscriptioncmds.c:1329 +#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 #, c-format msgid "" "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" msgstr "" "ALTER SUBSCRIPTION с обновлением для отключённых подписок не допускается" -#: commands/subscriptioncmds.c:1279 +#: commands/subscriptioncmds.c:1324 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "" "Выполните ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." -#: commands/subscriptioncmds.c:1288 commands/subscriptioncmds.c:1343 +#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 #, c-format msgid "" "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase " @@ -11081,7 +11546,7 @@ msgstr "" "ALTER SUBSCRIPTION с параметром публикации refresh в режиме copy_data не " "допускается, когда включён параметр two_phase" -#: commands/subscriptioncmds.c:1289 +#: commands/subscriptioncmds.c:1334 #, c-format msgid "" "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with " @@ -11091,7 +11556,7 @@ msgstr "" "copy_data = false либо выполните DROP/CREATE SUBSCRIPTION." #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1345 +#: commands/subscriptioncmds.c:1390 #, c-format msgid "" "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE " @@ -11100,13 +11565,13 @@ msgstr "" "Выполните %s с refresh = false или с copy_data = false либо выполните DROP/" "CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1367 +#: commands/subscriptioncmds.c:1412 #, c-format msgid "" "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION ... REFRESH для отключённых подписок не допускается" -#: commands/subscriptioncmds.c:1392 +#: commands/subscriptioncmds.c:1437 #, c-format msgid "" "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase " @@ -11115,7 +11580,7 @@ msgstr "" "ALTER SUBSCRIPTION ... REFRESH в режиме copy_data не допускается, когда " "включён параметр two_phase" -#: commands/subscriptioncmds.c:1393 +#: commands/subscriptioncmds.c:1438 #, c-format msgid "" "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/" @@ -11124,39 +11589,39 @@ msgstr "" "Выполните ALTER SUBSCRIPTION ... REFRESH с copy_data = false либо выполните " "DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1428 +#: commands/subscriptioncmds.c:1473 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "" "позиция пропуска в WAL (LSN %X/%X) должна быть больше начального LSN %X/%X" -#: commands/subscriptioncmds.c:1513 +#: commands/subscriptioncmds.c:1594 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "подписка \"%s\" не существует, пропускается" -#: commands/subscriptioncmds.c:1782 +#: commands/subscriptioncmds.c:1863 #, c-format msgid "dropped replication slot \"%s\" on publisher" msgstr "слот репликации \"%s\" удалён на сервере репликации" -#: commands/subscriptioncmds.c:1791 commands/subscriptioncmds.c:1799 +#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" msgstr "слот репликации \"%s\" на сервере публикации не был удалён: %s" -#: commands/subscriptioncmds.c:1924 +#: commands/subscriptioncmds.c:2005 #, c-format msgid "subscription with OID %u does not exist" msgstr "подписка с OID %u не существует" -#: commands/subscriptioncmds.c:1995 commands/subscriptioncmds.c:2120 +#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" msgstr "" "не удалось получить список реплицируемых таблиц с сервера репликации: %s" -#: commands/subscriptioncmds.c:2031 +#: commands/subscriptioncmds.c:2112 #, c-format msgid "" "subscription \"%s\" requested copy_data with origin = NONE but might copy " @@ -11165,7 +11630,7 @@ msgstr "" "для подписки \"%s\" выбран режим copy_data с origin = NONE, но в неё могут " "попасть данные из другого источника" -#: commands/subscriptioncmds.c:2033 +#: commands/subscriptioncmds.c:2114 #, c-format msgid "" "The subscription being created subscribes to a publication (%s) that " @@ -11183,7 +11648,7 @@ msgstr[2] "" "Создаваемая подписка связана с публикациями (%s), содержащими таблицы, в " "которые записывают другие подписки." -#: commands/subscriptioncmds.c:2036 +#: commands/subscriptioncmds.c:2117 #, c-format msgid "" "Verify that initial data copied from the publisher tables did not come from " @@ -11192,8 +11657,8 @@ msgstr "" "Убедитесь, что начальные данные, скопированные из таблиц публикации, " "поступили не из других источников." -#: commands/subscriptioncmds.c:2142 replication/logical/tablesync.c:893 -#: replication/pgoutput/pgoutput.c:1112 +#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 +#: replication/pgoutput/pgoutput.c:1143 #, c-format msgid "" "cannot use different column lists for table \"%s.%s\" in different " @@ -11202,7 +11667,7 @@ msgstr "" "использовать различные списки столбцов таблицы \"%s.%s\" в разных " "публикациях нельзя" -#: commands/subscriptioncmds.c:2192 +#: commands/subscriptioncmds.c:2273 #, c-format msgid "" "could not connect to publisher when attempting to drop replication slot " @@ -11212,7 +11677,7 @@ msgstr "" "\"%s\": %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2195 +#: commands/subscriptioncmds.c:2276 #, c-format msgid "" "Use %s to disable the subscription, and then use %s to disassociate it from " @@ -11221,194 +11686,197 @@ msgstr "" "Выполните %s, чтобы отключить подписку, а затем выполните %s, чтобы отвязать " "её от слота." -#: commands/subscriptioncmds.c:2226 +#: commands/subscriptioncmds.c:2307 #, c-format msgid "publication name \"%s\" used more than once" msgstr "имя публикации \"%s\" используется неоднократно" -#: commands/subscriptioncmds.c:2270 +#: commands/subscriptioncmds.c:2351 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "публикация \"%s\" уже имеется в подписке \"%s\"" -#: commands/subscriptioncmds.c:2284 +#: commands/subscriptioncmds.c:2365 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "публикация \"%s\" отсутствует в подписке \"%s\"" -#: commands/subscriptioncmds.c:2295 +#: commands/subscriptioncmds.c:2376 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "удалить все публикации из подписки нельзя" -#: commands/subscriptioncmds.c:2352 +#: commands/subscriptioncmds.c:2433 #, c-format msgid "%s requires a Boolean value or \"parallel\"" msgstr "%s требует логическое значение или \"parallel\"" -#: commands/tablecmds.c:246 commands/tablecmds.c:288 +#: commands/tablecmds.c:255 commands/tablecmds.c:297 #, c-format msgid "table \"%s\" does not exist" msgstr "таблица \"%s\" не существует" -#: commands/tablecmds.c:247 commands/tablecmds.c:289 +#: commands/tablecmds.c:256 commands/tablecmds.c:298 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "таблица \"%s\" не существует, пропускается" -#: commands/tablecmds.c:249 commands/tablecmds.c:291 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 msgid "Use DROP TABLE to remove a table." msgstr "Выполните DROP TABLE для удаления таблицы." -#: commands/tablecmds.c:252 +#: commands/tablecmds.c:261 #, c-format msgid "sequence \"%s\" does not exist" msgstr "последовательность \"%s\" не существует" -#: commands/tablecmds.c:253 +#: commands/tablecmds.c:262 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "последовательность \"%s\" не существует, пропускается" -#: commands/tablecmds.c:255 +#: commands/tablecmds.c:264 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "Выполните DROP SEQUENCE для удаления последовательности." -#: commands/tablecmds.c:258 +#: commands/tablecmds.c:267 #, c-format msgid "view \"%s\" does not exist" msgstr "представление \"%s\" не существует" -#: commands/tablecmds.c:259 +#: commands/tablecmds.c:268 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "представление \"%s\" не существует, пропускается" -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:270 msgid "Use DROP VIEW to remove a view." msgstr "Выполните DROP VIEW для удаления представления." -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:273 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "материализованное представление \"%s\" не существует" -#: commands/tablecmds.c:265 +#: commands/tablecmds.c:274 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "материализованное представление \"%s\" не существует, пропускается" -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:276 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "" "Выполните DROP MATERIALIZED VIEW для удаления материализованного " "представления." -#: commands/tablecmds.c:270 commands/tablecmds.c:294 commands/tablecmds.c:19043 -#: parser/parse_utilcmd.c:2254 +#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19805 +#: parser/parse_utilcmd.c:2251 #, c-format msgid "index \"%s\" does not exist" msgstr "индекс \"%s\" не существует" -#: commands/tablecmds.c:271 commands/tablecmds.c:295 +#: commands/tablecmds.c:280 commands/tablecmds.c:304 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "индекс \"%s\" не существует, пропускается" -#: commands/tablecmds.c:273 commands/tablecmds.c:297 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 msgid "Use DROP INDEX to remove an index." msgstr "Выполните DROP INDEX для удаления индекса." -#: commands/tablecmds.c:278 +#: commands/tablecmds.c:287 #, c-format msgid "\"%s\" is not a type" msgstr "\"%s\" - это не тип" -#: commands/tablecmds.c:279 +#: commands/tablecmds.c:288 msgid "Use DROP TYPE to remove a type." msgstr "Выполните DROP TYPE для удаления типа." -#: commands/tablecmds.c:282 commands/tablecmds.c:13784 -#: commands/tablecmds.c:16249 +#: commands/tablecmds.c:291 commands/tablecmds.c:14325 +#: commands/tablecmds.c:16886 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "сторонняя таблица \"%s\" не существует" -#: commands/tablecmds.c:283 +#: commands/tablecmds.c:292 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "сторонняя таблица \"%s\" не существует, пропускается" -#: commands/tablecmds.c:285 +#: commands/tablecmds.c:294 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "Выполните DROP FOREIGN TABLE для удаления сторонней таблицы." -#: commands/tablecmds.c:700 +#: commands/tablecmds.c:734 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMIT можно использовать только для временных таблиц" -#: commands/tablecmds.c:731 +#: commands/tablecmds.c:765 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "" "в рамках операции с ограничениями по безопасности нельзя создать временную " "таблицу" -#: commands/tablecmds.c:767 commands/tablecmds.c:15094 +#: commands/tablecmds.c:801 commands/tablecmds.c:15745 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "отношение \"%s\" наследуется неоднократно" -#: commands/tablecmds.c:951 -#, c-format -msgid "" -"specifying a table access method is not supported on a partitioned table" -msgstr "" -"указание табличного метода доступа для секционированных таблиц не " -"поддерживаются" - -#: commands/tablecmds.c:1044 +#: commands/tablecmds.c:1067 #, c-format msgid "\"%s\" is not partitioned" msgstr "отношение \"%s\" не является секционированным" -#: commands/tablecmds.c:1138 +#: commands/tablecmds.c:1161 #, c-format msgid "cannot partition using more than %d columns" msgstr "число столбцов в ключе секционирования не может превышать %d" -#: commands/tablecmds.c:1194 +#: commands/tablecmds.c:1217 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "создать стороннюю секцию для секционированной таблицы \"%s\" нельзя" -#: commands/tablecmds.c:1196 +#: commands/tablecmds.c:1219 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "Таблица \"%s\" содержит индексы, являющиеся уникальными." -#: commands/tablecmds.c:1361 +#: commands/tablecmds.c:1338 commands/tablecmds.c:13341 +#, c-format +msgid "too many array dimensions" +msgstr "слишком много размерностей массива" + +#: commands/tablecmds.c:1343 parser/parse_clause.c:774 +#: parser/parse_relation.c:1912 +#, c-format +msgid "column \"%s\" cannot be declared SETOF" +msgstr "столбец \"%s\" не может быть объявлен как SETOF" + +#: commands/tablecmds.c:1489 #, c-format msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" msgstr "DROP INDEX CONCURRENTLY не поддерживает удаление нескольких объектов" -#: commands/tablecmds.c:1365 +#: commands/tablecmds.c:1493 #, c-format msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLY не поддерживает режим CASCADE" -#: commands/tablecmds.c:1469 +#: commands/tablecmds.c:1597 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "удалить секционированный индекс \"%s\" параллельным способом нельзя" -#: commands/tablecmds.c:1757 +#: commands/tablecmds.c:1885 #, c-format msgid "cannot truncate only a partitioned table" msgstr "опустошить собственно секционированную таблицу нельзя" -#: commands/tablecmds.c:1758 +#: commands/tablecmds.c:1886 #, c-format msgid "" "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions " @@ -11417,39 +11885,39 @@ msgstr "" "Не указывайте ключевое слово ONLY или выполните TRUNCATE ONLY " "непосредственно для секций." -#: commands/tablecmds.c:1831 +#: commands/tablecmds.c:1959 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "опустошение распространяется на таблицу %s" -#: commands/tablecmds.c:2195 +#: commands/tablecmds.c:2320 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "опустошить стороннюю таблицу \"%s\" нельзя" -#: commands/tablecmds.c:2252 +#: commands/tablecmds.c:2377 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "временные таблицы других сеансов нельзя опустошить" -#: commands/tablecmds.c:2484 commands/tablecmds.c:14991 +#: commands/tablecmds.c:2606 commands/tablecmds.c:15642 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "наследование от секционированной таблицы \"%s\" не допускается" -#: commands/tablecmds.c:2489 +#: commands/tablecmds.c:2611 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "наследование от секции \"%s\" не допускается" -#: commands/tablecmds.c:2497 parser/parse_utilcmd.c:2484 -#: parser/parse_utilcmd.c:2626 +#: commands/tablecmds.c:2619 parser/parse_utilcmd.c:2481 +#: parser/parse_utilcmd.c:2623 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "" "наследуемое отношение \"%s\" не является таблицей или сторонней таблицей" -#: commands/tablecmds.c:2509 +#: commands/tablecmds.c:2631 #, c-format msgid "" "cannot create a temporary relation as partition of permanent relation \"%s\"" @@ -11457,74 +11925,25 @@ msgstr "" "создать временное отношение в качестве секции постоянного отношения \"%s\" " "нельзя" -#: commands/tablecmds.c:2518 commands/tablecmds.c:14970 +#: commands/tablecmds.c:2640 commands/tablecmds.c:15621 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "временное отношение \"%s\" не может наследоваться" -#: commands/tablecmds.c:2528 commands/tablecmds.c:14978 +#: commands/tablecmds.c:2650 commands/tablecmds.c:15629 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "наследование от временного отношения другого сеанса невозможно" -#: commands/tablecmds.c:2581 -#, c-format -msgid "merging multiple inherited definitions of column \"%s\"" -msgstr "слияние нескольких наследованных определений столбца \"%s\"" - -#: commands/tablecmds.c:2593 -#, c-format -msgid "inherited column \"%s\" has a type conflict" -msgstr "конфликт типов в наследованном столбце \"%s\"" - -#: commands/tablecmds.c:2595 commands/tablecmds.c:2624 -#: commands/tablecmds.c:2643 commands/tablecmds.c:2915 -#: commands/tablecmds.c:2951 commands/tablecmds.c:2967 -#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 -#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 -#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 -#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 -#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 -#: parser/parse_param.c:223 -#, c-format -msgid "%s versus %s" -msgstr "%s и %s" - -#: commands/tablecmds.c:2608 -#, c-format -msgid "inherited column \"%s\" has a collation conflict" -msgstr "конфликт правил сортировки в наследованном столбце \"%s\"" - -#: commands/tablecmds.c:2610 commands/tablecmds.c:2931 -#: commands/tablecmds.c:6848 -#, c-format -msgid "\"%s\" versus \"%s\"" -msgstr "\"%s\" и \"%s\"" - -#: commands/tablecmds.c:2622 -#, c-format -msgid "inherited column \"%s\" has a storage parameter conflict" -msgstr "конфликт параметров хранения в наследованном столбце \"%s\"" - -#: commands/tablecmds.c:2641 commands/tablecmds.c:2965 -#, c-format -msgid "column \"%s\" has a compression method conflict" -msgstr "в столбце \"%s\" возник конфликт методов сжатия" - -#: commands/tablecmds.c:2657 -#, c-format -msgid "inherited column \"%s\" has a generation conflict" -msgstr "конфликт свойства генерирования в наследованном столбце \"%s\"" - -#: commands/tablecmds.c:2763 commands/tablecmds.c:2818 -#: commands/tablecmds.c:12477 parser/parse_utilcmd.c:1307 -#: parser/parse_utilcmd.c:1350 parser/parse_utilcmd.c:1749 -#: parser/parse_utilcmd.c:1857 +#: commands/tablecmds.c:2791 commands/tablecmds.c:2845 +#: commands/tablecmds.c:13024 parser/parse_utilcmd.c:1265 +#: parser/parse_utilcmd.c:1308 parser/parse_utilcmd.c:1735 +#: parser/parse_utilcmd.c:1843 #, c-format msgid "cannot convert whole-row table reference" msgstr "преобразовать ссылку на тип всей строки таблицы нельзя" -#: commands/tablecmds.c:2764 parser/parse_utilcmd.c:1308 +#: commands/tablecmds.c:2792 parser/parse_utilcmd.c:1266 #, c-format msgid "" "Generation expression for column \"%s\" contains a whole-row reference to " @@ -11533,89 +11952,58 @@ msgstr "" "Генерирующее выражение столбца \"%s\" ссылается на тип всей строки в таблице " "\"%s\"." -#: commands/tablecmds.c:2819 parser/parse_utilcmd.c:1351 +#: commands/tablecmds.c:2846 parser/parse_utilcmd.c:1309 #, c-format msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." msgstr "Ограничение \"%s\" ссылается на тип всей строки в таблице \"%s\"." -#: commands/tablecmds.c:2897 -#, c-format -msgid "merging column \"%s\" with inherited definition" -msgstr "слияние столбца \"%s\" с наследованным определением" - -#: commands/tablecmds.c:2901 -#, c-format -msgid "moving and merging column \"%s\" with inherited definition" -msgstr "перемещение и слияние столбца \"%s\" с наследуемым определением" - -#: commands/tablecmds.c:2902 -#, c-format -msgid "User-specified column moved to the position of the inherited column." -msgstr "" -"Определённый пользователем столбец перемещён в позицию наследуемого столбца." - -#: commands/tablecmds.c:2913 -#, c-format -msgid "column \"%s\" has a type conflict" -msgstr "конфликт типов в столбце \"%s\"" - -#: commands/tablecmds.c:2929 -#, c-format -msgid "column \"%s\" has a collation conflict" -msgstr "конфликт правил сортировки в столбце \"%s\"" - -#: commands/tablecmds.c:2949 -#, c-format -msgid "column \"%s\" has a storage parameter conflict" -msgstr "конфликт параметров хранения в столбце \"%s\"" - -#: commands/tablecmds.c:2995 commands/tablecmds.c:3082 +#: commands/tablecmds.c:2956 commands/tablecmds.c:3227 #, c-format msgid "column \"%s\" inherits from generated column but specifies default" msgstr "" "столбец \"%s\" наследуется от генерируемого столбца, но для него задано " "значение по умолчанию" -#: commands/tablecmds.c:3000 commands/tablecmds.c:3087 +#: commands/tablecmds.c:2961 commands/tablecmds.c:3232 #, c-format msgid "column \"%s\" inherits from generated column but specifies identity" msgstr "" "столбец \"%s\" наследуется от генерируемого столбца, но для него задано " "свойство идентификации" -#: commands/tablecmds.c:3008 commands/tablecmds.c:3095 +#: commands/tablecmds.c:2969 commands/tablecmds.c:3240 #, c-format msgid "child column \"%s\" specifies generation expression" msgstr "для дочернего столбца \"%s\" указано генерирующее выражение" -#: commands/tablecmds.c:3010 commands/tablecmds.c:3097 +#: commands/tablecmds.c:2971 commands/tablecmds.c:3242 #, c-format msgid "A child table column cannot be generated unless its parent column is." msgstr "" "Дочерний столбец может быть генерируемым, только если родительский столбец " "является таковым." -#: commands/tablecmds.c:3143 +#: commands/tablecmds.c:3017 #, c-format msgid "column \"%s\" inherits conflicting generation expressions" msgstr "столбец \"%s\" наследует конфликтующие генерирующие выражения" -#: commands/tablecmds.c:3145 +#: commands/tablecmds.c:3019 #, c-format msgid "To resolve the conflict, specify a generation expression explicitly." msgstr "Для разрешения конфликта укажите генерирующее выражение явно." -#: commands/tablecmds.c:3149 +#: commands/tablecmds.c:3023 #, c-format msgid "column \"%s\" inherits conflicting default values" msgstr "столбец \"%s\" наследует конфликтующие значения по умолчанию" -#: commands/tablecmds.c:3151 +#: commands/tablecmds.c:3025 #, c-format msgid "To resolve the conflict, specify a default explicitly." msgstr "Для решения конфликта укажите желаемое значение по умолчанию." -#: commands/tablecmds.c:3201 +#: commands/tablecmds.c:3080 #, c-format msgid "" "check constraint name \"%s\" appears multiple times but with different " @@ -11624,113 +12012,193 @@ msgstr "" "имя ограничения-проверки \"%s\" фигурирует несколько раз, но с разными " "выражениями" -#: commands/tablecmds.c:3414 +#: commands/tablecmds.c:3131 #, c-format -msgid "cannot move temporary tables of other sessions" -msgstr "перемещать временные таблицы других сеансов нельзя" +msgid "merging column \"%s\" with inherited definition" +msgstr "слияние столбца \"%s\" с наследованным определением" -#: commands/tablecmds.c:3484 +#: commands/tablecmds.c:3135 #, c-format -msgid "cannot rename column of typed table" -msgstr "переименовать столбец типизированной таблицы нельзя" +msgid "moving and merging column \"%s\" with inherited definition" +msgstr "перемещение и слияние столбца \"%s\" с наследуемым определением" -#: commands/tablecmds.c:3503 +#: commands/tablecmds.c:3136 #, c-format -msgid "cannot rename columns of relation \"%s\"" -msgstr "переименовывать столбцы отношения \"%s\" нельзя" +msgid "User-specified column moved to the position of the inherited column." +msgstr "" +"Определённый пользователем столбец перемещён в позицию наследуемого столбца." -#: commands/tablecmds.c:3598 +#: commands/tablecmds.c:3148 #, c-format -msgid "inherited column \"%s\" must be renamed in child tables too" -msgstr "" -"наследованный столбец \"%s\" должен быть также переименован в дочерних " -"таблицах" +msgid "column \"%s\" has a type conflict" +msgstr "конфликт типов в столбце \"%s\"" -#: commands/tablecmds.c:3630 +#: commands/tablecmds.c:3150 commands/tablecmds.c:3184 +#: commands/tablecmds.c:3200 commands/tablecmds.c:3307 +#: commands/tablecmds.c:3340 commands/tablecmds.c:3356 +#: parser/parse_coerce.c:2192 parser/parse_coerce.c:2212 +#: parser/parse_coerce.c:2232 parser/parse_coerce.c:2253 +#: parser/parse_coerce.c:2308 parser/parse_coerce.c:2342 +#: parser/parse_coerce.c:2418 parser/parse_coerce.c:2449 +#: parser/parse_coerce.c:2488 parser/parse_coerce.c:2555 +#: parser/parse_param.c:223 #, c-format -msgid "cannot rename system column \"%s\"" -msgstr "нельзя переименовать системный столбец \"%s\"" +msgid "%s versus %s" +msgstr "%s и %s" -#: commands/tablecmds.c:3645 +#: commands/tablecmds.c:3162 #, c-format -msgid "cannot rename inherited column \"%s\"" -msgstr "нельзя переименовать наследованный столбец \"%s\"" +msgid "column \"%s\" has a collation conflict" +msgstr "конфликт правил сортировки в столбце \"%s\"" -#: commands/tablecmds.c:3797 +#: commands/tablecmds.c:3164 commands/tablecmds.c:3326 +#: commands/tablecmds.c:7080 #, c-format -msgid "inherited constraint \"%s\" must be renamed in child tables too" -msgstr "" -"наследуемое ограничение \"%s\" должно быть также переименовано в дочерних " -"таблицах" +msgid "\"%s\" versus \"%s\"" +msgstr "\"%s\" и \"%s\"" -#: commands/tablecmds.c:3804 +#: commands/tablecmds.c:3182 #, c-format -msgid "cannot rename inherited constraint \"%s\"" -msgstr "нельзя переименовать наследованное ограничение \"%s\"" +msgid "column \"%s\" has a storage parameter conflict" +msgstr "конфликт параметров хранения в столбце \"%s\"" -#. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4101 +#: commands/tablecmds.c:3198 commands/tablecmds.c:3354 #, c-format -msgid "" -"cannot %s \"%s\" because it is being used by active queries in this session" -msgstr "" -"нельзя выполнить %s \"%s\", так как этот объект используется активными " -"запросами в данном сеансе" +msgid "column \"%s\" has a compression method conflict" +msgstr "в столбце \"%s\" возник конфликт методов сжатия" -#. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4110 +#: commands/tablecmds.c:3293 #, c-format -msgid "cannot %s \"%s\" because it has pending trigger events" -msgstr "" -"нельзя выполнить %s \"%s\", так как с этим объектом связаны отложенные " -"события триггеров" +msgid "merging multiple inherited definitions of column \"%s\"" +msgstr "слияние нескольких наследованных определений столбца \"%s\"" -#: commands/tablecmds.c:4577 +#: commands/tablecmds.c:3305 #, c-format -msgid "cannot alter partition \"%s\" with an incomplete detach" -msgstr "нельзя изменить секцию \"%s\", которая не полностью отсоединена" +msgid "inherited column \"%s\" has a type conflict" +msgstr "конфликт типов в наследованном столбце \"%s\"" -#: commands/tablecmds.c:4770 commands/tablecmds.c:4785 +#: commands/tablecmds.c:3324 #, c-format -msgid "cannot change persistence setting twice" -msgstr "изменить характеристику хранения дважды нельзя" +msgid "inherited column \"%s\" has a collation conflict" +msgstr "конфликт правил сортировки в наследованном столбце \"%s\"" + +#: commands/tablecmds.c:3338 +#, c-format +msgid "inherited column \"%s\" has a storage parameter conflict" +msgstr "конфликт параметров хранения в наследованном столбце \"%s\"" + +#: commands/tablecmds.c:3366 +#, c-format +msgid "inherited column \"%s\" has a generation conflict" +msgstr "конфликт свойства генерирования в наследованном столбце \"%s\"" + +#: commands/tablecmds.c:3597 +#, c-format +msgid "cannot move temporary tables of other sessions" +msgstr "перемещать временные таблицы других сеансов нельзя" + +#: commands/tablecmds.c:3670 +#, c-format +msgid "cannot rename column of typed table" +msgstr "переименовать столбец типизированной таблицы нельзя" + +#: commands/tablecmds.c:3689 +#, c-format +msgid "cannot rename columns of relation \"%s\"" +msgstr "переименовывать столбцы отношения \"%s\" нельзя" + +#: commands/tablecmds.c:3784 +#, c-format +msgid "inherited column \"%s\" must be renamed in child tables too" +msgstr "" +"наследованный столбец \"%s\" должен быть также переименован в дочерних " +"таблицах" + +#: commands/tablecmds.c:3816 +#, c-format +msgid "cannot rename system column \"%s\"" +msgstr "нельзя переименовать системный столбец \"%s\"" + +#: commands/tablecmds.c:3831 +#, c-format +msgid "cannot rename inherited column \"%s\"" +msgstr "нельзя переименовать наследованный столбец \"%s\"" + +#: commands/tablecmds.c:3983 +#, c-format +msgid "inherited constraint \"%s\" must be renamed in child tables too" +msgstr "" +"наследуемое ограничение \"%s\" должно быть также переименовано в дочерних " +"таблицах" + +#: commands/tablecmds.c:3990 +#, c-format +msgid "cannot rename inherited constraint \"%s\"" +msgstr "нельзя переименовать наследованное ограничение \"%s\"" + +#. translator: first %s is a SQL command, eg ALTER TABLE +#: commands/tablecmds.c:4290 +#, c-format +msgid "" +"cannot %s \"%s\" because it is being used by active queries in this session" +msgstr "" +"нельзя выполнить %s \"%s\", так как этот объект используется активными " +"запросами в данном сеансе" + +#. translator: first %s is a SQL command, eg ALTER TABLE +#: commands/tablecmds.c:4299 +#, c-format +msgid "cannot %s \"%s\" because it has pending trigger events" +msgstr "" +"нельзя выполнить %s \"%s\", так как с этим объектом связаны отложенные " +"события триггеров" -#: commands/tablecmds.c:4806 +#: commands/tablecmds.c:4325 #, c-format -msgid "cannot change access method of a partitioned table" -msgstr "менять метод доступа для секционированной таблицы нельзя" +msgid "cannot alter temporary tables of other sessions" +msgstr "модифицировать временные таблицы других сеансов нельзя" -#: commands/tablecmds.c:4812 +#: commands/tablecmds.c:4798 +#, c-format +msgid "cannot alter partition \"%s\" with an incomplete detach" +msgstr "нельзя изменить секцию \"%s\", которая не полностью отсоединена" + +#: commands/tablecmds.c:5002 commands/tablecmds.c:5017 +#, c-format +msgid "cannot change persistence setting twice" +msgstr "изменить характеристику хранения дважды нельзя" + +#: commands/tablecmds.c:5038 #, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" msgstr "множественные подкоманды SET ACCESS METHOD не допускаются" -#: commands/tablecmds.c:5533 +#: commands/tablecmds.c:5768 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "перезаписать системное отношение \"%s\" нельзя" -#: commands/tablecmds.c:5539 +#: commands/tablecmds.c:5774 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "перезаписать таблицу \"%s\", используемую как таблицу каталога, нельзя" -#: commands/tablecmds.c:5549 +#: commands/tablecmds.c:5786 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "перезаписывать временные таблицы других сеансов нельзя" -#: commands/tablecmds.c:6044 +#: commands/tablecmds.c:6281 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "столбец \"%s\" отношения \"%s\" содержит значения NULL" -#: commands/tablecmds.c:6061 +#: commands/tablecmds.c:6298 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "ограничение-проверку \"%s\" отношения \"%s\" нарушает некоторая строка" -#: commands/tablecmds.c:6080 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6317 partitioning/partbounds.c:3387 #, c-format msgid "" "updated partition constraint for default partition \"%s\" would be violated " @@ -11739,24 +12207,24 @@ msgstr "" "изменённое ограничение секции для секции по умолчанию \"%s\" будет нарушено " "некоторыми строками" -#: commands/tablecmds.c:6086 +#: commands/tablecmds.c:6323 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "ограничение секции отношения \"%s\" нарушает некоторая строка" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6348 +#: commands/tablecmds.c:6588 #, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" msgstr "действие ALTER %s нельзя выполнить с отношением \"%s\"" -#: commands/tablecmds.c:6603 commands/tablecmds.c:6610 +#: commands/tablecmds.c:6843 commands/tablecmds.c:6850 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" msgstr "" "изменить тип \"%s\" нельзя, так как он задействован в столбце \"%s.%s\"" -#: commands/tablecmds.c:6617 +#: commands/tablecmds.c:6857 #, c-format msgid "" "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" @@ -11764,77 +12232,77 @@ msgstr "" "изменить стороннюю таблицу \"%s\" нельзя, так как столбец \"%s.%s\" " "задействует тип её строки" -#: commands/tablecmds.c:6624 +#: commands/tablecmds.c:6864 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "" "изменить таблицу \"%s\" нельзя, так как столбец \"%s.%s\" задействует тип её " "строки" -#: commands/tablecmds.c:6680 +#: commands/tablecmds.c:6920 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "изменить тип \"%s\", так как это тип типизированной таблицы" -#: commands/tablecmds.c:6682 +#: commands/tablecmds.c:6922 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "" "Чтобы изменить также типизированные таблицы, выполните ALTER ... CASCADE." -#: commands/tablecmds.c:6728 +#: commands/tablecmds.c:6968 #, c-format msgid "type %s is not a composite type" msgstr "тип %s не является составным" -#: commands/tablecmds.c:6755 +#: commands/tablecmds.c:6995 #, c-format msgid "cannot add column to typed table" msgstr "добавить столбец в типизированную таблицу нельзя" -#: commands/tablecmds.c:6811 +#: commands/tablecmds.c:7043 #, c-format msgid "cannot add column to a partition" msgstr "добавить столбец в секцию нельзя" -#: commands/tablecmds.c:6840 commands/tablecmds.c:15221 +#: commands/tablecmds.c:7072 commands/tablecmds.c:15860 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "дочерняя таблица \"%s\" имеет другой тип для столбца \"%s\"" -#: commands/tablecmds.c:6846 commands/tablecmds.c:15228 +#: commands/tablecmds.c:7078 commands/tablecmds.c:15866 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "" "дочерняя таблица \"%s\" имеет другое правило сортировки для столбца \"%s\"" -#: commands/tablecmds.c:6864 +#: commands/tablecmds.c:7096 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "объединение определений столбца \"%s\" для потомка \"%s\"" -#: commands/tablecmds.c:6911 +#: commands/tablecmds.c:7149 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "" "добавить столбец идентификации в таблицу, у которой есть дочерние, нельзя" -#: commands/tablecmds.c:7162 +#: commands/tablecmds.c:7362 #, c-format msgid "column must be added to child tables too" msgstr "столбец также должен быть добавлен к дочерним таблицам" -#: commands/tablecmds.c:7240 +#: commands/tablecmds.c:7440 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "столбец \"%s\" отношения \"%s\" уже существует, пропускается" -#: commands/tablecmds.c:7247 +#: commands/tablecmds.c:7447 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "столбец \"%s\" отношения \"%s\" уже существует" -#: commands/tablecmds.c:7313 commands/tablecmds.c:12115 +#: commands/tablecmds.c:7513 commands/tablecmds.c:12652 #, c-format msgid "" "cannot remove constraint from only the partitioned table when partitions " @@ -11843,59 +12311,73 @@ msgstr "" "удалить ограничение только из секционированной таблицы, когда существуют " "секции, нельзя" -#: commands/tablecmds.c:7314 commands/tablecmds.c:7631 -#: commands/tablecmds.c:8604 commands/tablecmds.c:12116 +#: commands/tablecmds.c:7514 commands/tablecmds.c:7828 +#: commands/tablecmds.c:8006 commands/tablecmds.c:8113 +#: commands/tablecmds.c:8230 commands/tablecmds.c:9049 +#: commands/tablecmds.c:12653 #, c-format msgid "Do not specify the ONLY keyword." msgstr "Не указывайте ключевое слово ONLY." -#: commands/tablecmds.c:7351 commands/tablecmds.c:7557 -#: commands/tablecmds.c:7699 commands/tablecmds.c:7817 -#: commands/tablecmds.c:7911 commands/tablecmds.c:7970 -#: commands/tablecmds.c:8089 commands/tablecmds.c:8228 -#: commands/tablecmds.c:8298 commands/tablecmds.c:8432 -#: commands/tablecmds.c:12270 commands/tablecmds.c:13807 -#: commands/tablecmds.c:16338 +#: commands/tablecmds.c:7550 commands/tablecmds.c:7754 +#: commands/tablecmds.c:7896 commands/tablecmds.c:8028 +#: commands/tablecmds.c:8157 commands/tablecmds.c:8251 +#: commands/tablecmds.c:8352 commands/tablecmds.c:8509 +#: commands/tablecmds.c:8662 commands/tablecmds.c:8743 +#: commands/tablecmds.c:8877 commands/tablecmds.c:12806 +#: commands/tablecmds.c:14348 commands/tablecmds.c:16975 #, c-format msgid "cannot alter system column \"%s\"" msgstr "системный столбец \"%s\" нельзя изменить" -#: commands/tablecmds.c:7357 commands/tablecmds.c:7705 +#: commands/tablecmds.c:7556 commands/tablecmds.c:7902 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "столбец \"%s\" отношения \"%s\" является столбцом идентификации" -#: commands/tablecmds.c:7400 +#: commands/tablecmds.c:7597 #, c-format msgid "column \"%s\" is in a primary key" msgstr "столбец \"%s\" входит в первичный ключ" -#: commands/tablecmds.c:7405 +#: commands/tablecmds.c:7602 #, c-format msgid "column \"%s\" is in index used as replica identity" msgstr "столбец \"%s\" входит в индекс, используемый для идентификации реплики" -#: commands/tablecmds.c:7428 +#: commands/tablecmds.c:7625 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "столбец \"%s\" в родительской таблице помечен как NOT NULL" -#: commands/tablecmds.c:7628 commands/tablecmds.c:9088 +#: commands/tablecmds.c:7825 commands/tablecmds.c:9533 #, c-format msgid "constraint must be added to child tables too" msgstr "ограничение также должно быть добавлено к дочерним таблицам" -#: commands/tablecmds.c:7629 +#: commands/tablecmds.c:7826 #, c-format msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." msgstr "Столбец \"%s\" отношения \"%s\" уже имеет свойство NOT NULL." -#: commands/tablecmds.c:7714 +#: commands/tablecmds.c:7911 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "столбец \"%s\" отношения \"%s\" является генерируемым" -#: commands/tablecmds.c:7828 +#: commands/tablecmds.c:8005 +#, c-format +msgid "cannot add identity to a column of only the partitioned table" +msgstr "" +"сделать столбцом идентификации столбец одной лишь секционированной таблицы " +"нельзя" + +#: commands/tablecmds.c:8011 +#, c-format +msgid "cannot add identity to a column of a partition" +msgstr "сделать столбцом идентификации столбец одной секции нельзя" + +#: commands/tablecmds.c:8039 #, c-format msgid "" "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity " @@ -11904,46 +12386,74 @@ msgstr "" "столбец \"%s\" отношения \"%s\" должен быть объявлен как NOT NULL, чтобы его " "можно было сделать столбцом идентификации" -#: commands/tablecmds.c:7834 +#: commands/tablecmds.c:8045 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "столбец \"%s\" отношения \"%s\" уже является столбцом идентификации" -#: commands/tablecmds.c:7840 +#: commands/tablecmds.c:8051 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "столбец \"%s\" отношения \"%s\" уже имеет значение по умолчанию" -#: commands/tablecmds.c:7917 commands/tablecmds.c:7978 +#: commands/tablecmds.c:8112 +#, c-format +msgid "cannot change identity column of only the partitioned table" +msgstr "" +"изменить столбец идентификации для одной лишь секционированной таблицы нельзя" + +#: commands/tablecmds.c:8118 +#, c-format +msgid "cannot change identity column of a partition" +msgstr "изменить столбец идентификации для одной секции нельзя" + +#: commands/tablecmds.c:8163 commands/tablecmds.c:8259 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "столбец \"%s\" отношения \"%s\" не является столбцом идентификации" -#: commands/tablecmds.c:7983 +#: commands/tablecmds.c:8229 +#, c-format +msgid "cannot drop identity from a column of only the partitioned table" +msgstr "" +"лишить свойства идентификации столбец одной лишь секционированной таблицы " +"нельзя" + +#: commands/tablecmds.c:8235 +#, c-format +msgid "cannot drop identity from a column of a partition" +msgstr "лишить свойства идентификации столбец одной секции нельзя" + +#: commands/tablecmds.c:8264 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "" "столбец \"%s\" отношения \"%s\" не является столбцом идентификации, " "пропускается" -#: commands/tablecmds.c:8036 +#: commands/tablecmds.c:8358 +#, c-format +msgid "column \"%s\" of relation \"%s\" is not a generated column" +msgstr "столбец \"%s\" отношения \"%s\" не является генерируемым столбцом" + +#: commands/tablecmds.c:8456 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "" "ALTER TABLE / DROP EXPRESSION нужно применять также к дочерним таблицам" -#: commands/tablecmds.c:8058 +#: commands/tablecmds.c:8478 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "нельзя удалить генерирующее выражение из наследуемого столбца" -#: commands/tablecmds.c:8097 +#: commands/tablecmds.c:8517 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column" msgstr "" "столбец \"%s\" отношения \"%s\" не является сохранённым генерируемым столбцом" -#: commands/tablecmds.c:8102 +#: commands/tablecmds.c:8522 #, c-format msgid "" "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" @@ -11951,53 +12461,53 @@ msgstr "" "столбец \"%s\" отношения \"%s\" пропускается, так как не является " "сохранённым генерируемым столбцом" -#: commands/tablecmds.c:8175 +#: commands/tablecmds.c:8600 #, c-format msgid "cannot refer to non-index column by number" msgstr "по номеру можно ссылаться только на столбец в индексе" -#: commands/tablecmds.c:8218 +#: commands/tablecmds.c:8652 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "столбец с номером %d отношения \"%s\" не существует" -#: commands/tablecmds.c:8237 +#: commands/tablecmds.c:8671 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "изменить статистику включённого столбца \"%s\" индекса \"%s\" нельзя" -#: commands/tablecmds.c:8242 +#: commands/tablecmds.c:8676 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "" "изменить статистику столбца \"%s\" (не выражения) индекса \"%s\" нельзя" -#: commands/tablecmds.c:8244 +#: commands/tablecmds.c:8678 #, c-format msgid "Alter statistics on table column instead." msgstr "Вместо этого измените статистику для столбца в таблице." -#: commands/tablecmds.c:8479 +#: commands/tablecmds.c:8924 #, c-format msgid "cannot drop column from typed table" msgstr "нельзя удалить столбец в типизированной таблице" -#: commands/tablecmds.c:8542 +#: commands/tablecmds.c:8987 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "столбец \"%s\" в таблице\"%s\" не существует, пропускается" -#: commands/tablecmds.c:8555 +#: commands/tablecmds.c:9000 #, c-format msgid "cannot drop system column \"%s\"" msgstr "нельзя удалить системный столбец \"%s\"" -#: commands/tablecmds.c:8565 +#: commands/tablecmds.c:9010 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "нельзя удалить наследованный столбец \"%s\"" -#: commands/tablecmds.c:8578 +#: commands/tablecmds.c:9023 #, c-format msgid "" "cannot drop column \"%s\" because it is part of the partition key of " @@ -12006,7 +12516,7 @@ msgstr "" "удалить столбец \"%s\" нельзя, так как он входит в ключ разбиения отношения " "\"%s\"" -#: commands/tablecmds.c:8603 +#: commands/tablecmds.c:9048 #, c-format msgid "" "cannot drop column from only the partitioned table when partitions exist" @@ -12014,7 +12524,7 @@ msgstr "" "удалить столбец только из секционированной таблицы, когда существуют секции, " "нельзя" -#: commands/tablecmds.c:8808 +#: commands/tablecmds.c:9253 #, c-format msgid "" "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned " @@ -12023,14 +12533,14 @@ msgstr "" "ALTER TABLE / ADD CONSTRAINT USING INDEX не поддерживается с " "секционированными таблицами" -#: commands/tablecmds.c:8833 +#: commands/tablecmds.c:9278 #, c-format msgid "" "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" msgstr "" "ALTER TABLE / ADD CONSTRAINT USING INDEX переименует индекс \"%s\" в \"%s\"" -#: commands/tablecmds.c:9170 +#: commands/tablecmds.c:9615 #, c-format msgid "" "cannot use ONLY for foreign key on partitioned table \"%s\" referencing " @@ -12039,7 +12549,7 @@ msgstr "" "нельзя использовать ONLY для стороннего ключа в секционированной таблице " "\"%s\", ссылающегося на отношение \"%s\"" -#: commands/tablecmds.c:9176 +#: commands/tablecmds.c:9621 #, c-format msgid "" "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing " @@ -12048,25 +12558,25 @@ msgstr "" "нельзя добавить с характеристикой NOT VALID сторонний ключ в " "секционированной таблице \"%s\", ссылающийся на отношение \"%s\"" -#: commands/tablecmds.c:9179 +#: commands/tablecmds.c:9624 #, c-format msgid "This feature is not yet supported on partitioned tables." msgstr "" "Эта функциональность с секционированными таблицами пока не поддерживается." -#: commands/tablecmds.c:9186 commands/tablecmds.c:9642 +#: commands/tablecmds.c:9631 commands/tablecmds.c:10092 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "указанный объект \"%s\" не является таблицей" -#: commands/tablecmds.c:9209 +#: commands/tablecmds.c:9654 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "" "ограничения в постоянных таблицах могут ссылаться только на постоянные " "таблицы" -#: commands/tablecmds.c:9216 +#: commands/tablecmds.c:9661 #, c-format msgid "" "constraints on unlogged tables may reference only permanent or unlogged " @@ -12075,13 +12585,13 @@ msgstr "" "ограничения в нежурналируемых таблицах могут ссылаться только на постоянные " "или нежурналируемые таблицы" -#: commands/tablecmds.c:9222 +#: commands/tablecmds.c:9667 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "" "ограничения во временных таблицах могут ссылаться только на временные таблицы" -#: commands/tablecmds.c:9226 +#: commands/tablecmds.c:9671 #, c-format msgid "" "constraints on temporary tables must involve temporary tables of this session" @@ -12089,7 +12599,7 @@ msgstr "" "ограничения во временных таблицах должны ссылаться только на временные " "таблицы текущего сеанса" -#: commands/tablecmds.c:9290 commands/tablecmds.c:9296 +#: commands/tablecmds.c:9735 commands/tablecmds.c:9741 #, c-format msgid "" "invalid %s action for foreign key constraint containing generated column" @@ -12097,22 +12607,22 @@ msgstr "" "некорректное действие %s для ограничения внешнего ключа, содержащего " "генерируемый столбец" -#: commands/tablecmds.c:9312 +#: commands/tablecmds.c:9757 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "число столбцов в источнике и назначении внешнего ключа не совпадает" -#: commands/tablecmds.c:9419 +#: commands/tablecmds.c:9864 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "ограничение внешнего ключа \"%s\" нельзя реализовать" -#: commands/tablecmds.c:9421 +#: commands/tablecmds.c:9866 #, c-format msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." msgstr "Столбцы ключа \"%s\" и \"%s\" имеют несовместимые типы: %s и %s." -#: commands/tablecmds.c:9578 +#: commands/tablecmds.c:10035 #, c-format msgid "" "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" @@ -12120,40 +12630,49 @@ msgstr "" "столбец \"%s\", фигурирующий в действии ON DELETE SET, должен входить во " "внешний ключ" -#: commands/tablecmds.c:9852 commands/tablecmds.c:10322 -#: parser/parse_utilcmd.c:800 parser/parse_utilcmd.c:929 +#: commands/tablecmds.c:10392 commands/tablecmds.c:10832 +#: parser/parse_utilcmd.c:822 parser/parse_utilcmd.c:945 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "ограничения внешнего ключа для сторонних таблиц не поддерживаются" -#: commands/tablecmds.c:10875 commands/tablecmds.c:11156 -#: commands/tablecmds.c:12072 commands/tablecmds.c:12147 +#: commands/tablecmds.c:10815 +#, c-format +msgid "" +"cannot attach table \"%s\" as a partition because it is referenced by " +"foreign key \"%s\"" +msgstr "" +"присоединить таблицу \"%s\" в качестве секции нельзя, так как на неё " +"ссылается внешний ключ \"%s\"" + +#: commands/tablecmds.c:11416 commands/tablecmds.c:11697 +#: commands/tablecmds.c:12609 commands/tablecmds.c:12683 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "ограничение \"%s\" в таблице \"%s\" не существует" -#: commands/tablecmds.c:10882 +#: commands/tablecmds.c:11423 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "ограничение \"%s\" в таблице \"%s\" не является внешним ключом" -#: commands/tablecmds.c:10920 +#: commands/tablecmds.c:11461 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" msgstr "изменить ограничение \"%s\" таблицы \"%s\" нельзя" -#: commands/tablecmds.c:10923 +#: commands/tablecmds.c:11464 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "" "Ограничение \"%s\" является производным от ограничения \"%s\" таблицы \"%s\"." -#: commands/tablecmds.c:10925 +#: commands/tablecmds.c:11466 #, c-format msgid "You may alter the constraint it derives from instead." msgstr "Вместо этого вы можете изменить родительское ограничение." -#: commands/tablecmds.c:11164 +#: commands/tablecmds.c:11705 #, c-format msgid "" "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" @@ -12161,51 +12680,51 @@ msgstr "" "ограничение \"%s\" в таблице \"%s\" не является внешним ключом или " "ограничением-проверкой" -#: commands/tablecmds.c:11241 +#: commands/tablecmds.c:11782 #, c-format msgid "constraint must be validated on child tables too" msgstr "ограничение также должно соблюдаться в дочерних таблицах" -#: commands/tablecmds.c:11328 +#: commands/tablecmds.c:11869 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "столбец \"%s\", указанный в ограничении внешнего ключа, не существует" -#: commands/tablecmds.c:11334 +#: commands/tablecmds.c:11875 #, c-format msgid "system columns cannot be used in foreign keys" msgstr "системные столбцы нельзя использовать во внешних ключах" -#: commands/tablecmds.c:11338 +#: commands/tablecmds.c:11879 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "во внешнем ключе не может быть больше %d столбцов" -#: commands/tablecmds.c:11403 +#: commands/tablecmds.c:11944 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "" "использовать откладываемый первичный ключ в целевой внешней таблице \"%s\" " "нельзя" -#: commands/tablecmds.c:11420 +#: commands/tablecmds.c:11961 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "в целевой внешней таблице \"%s\" нет первичного ключа" -#: commands/tablecmds.c:11488 +#: commands/tablecmds.c:12029 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "в списке столбцов внешнего ключа не должно быть повторений" -#: commands/tablecmds.c:11580 +#: commands/tablecmds.c:12121 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "" "использовать откладываемое ограничение уникальности в целевой внешней " "таблице \"%s\" нельзя" -#: commands/tablecmds.c:11585 +#: commands/tablecmds.c:12126 #, c-format msgid "" "there is no unique constraint matching given keys for referenced table \"%s\"" @@ -12213,27 +12732,39 @@ msgstr "" "в целевой внешней таблице \"%s\" нет ограничения уникальности, " "соответствующего данным ключам" -#: commands/tablecmds.c:12028 +#: commands/tablecmds.c:12565 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "удалить наследованное ограничение \"%s\" таблицы \"%s\" нельзя" -#: commands/tablecmds.c:12078 +#: commands/tablecmds.c:12615 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" msgstr "ограничение \"%s\" в таблице \"%s\" не существует, пропускается" -#: commands/tablecmds.c:12254 +#: commands/tablecmds.c:12790 #, c-format msgid "cannot alter column type of typed table" msgstr "изменить тип столбца в типизированной таблице нельзя" -#: commands/tablecmds.c:12281 +#: commands/tablecmds.c:12816 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "изменяя тип генерируемого столбца, нельзя указывать USING" + +#: commands/tablecmds.c:12817 commands/tablecmds.c:18028 +#: commands/tablecmds.c:18118 commands/trigger.c:656 +#: rewrite/rewriteHandler.c:941 rewrite/rewriteHandler.c:976 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "Столбец \"%s\" является генерируемым." + +#: commands/tablecmds.c:12827 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "изменить наследованный столбец \"%s\" нельзя" -#: commands/tablecmds.c:12290 +#: commands/tablecmds.c:12836 #, c-format msgid "" "cannot alter column \"%s\" because it is part of the partition key of " @@ -12242,7 +12773,7 @@ msgstr "" "изменить столбец \"%s\" нельзя, так как он входит в ключ разбиения отношения " "\"%s\"" -#: commands/tablecmds.c:12340 +#: commands/tablecmds.c:12886 #, c-format msgid "" "result of USING clause for column \"%s\" cannot be cast automatically to " @@ -12250,45 +12781,45 @@ msgid "" msgstr "" "результат USING для столбца \"%s\" нельзя автоматически привести к типу %s" -#: commands/tablecmds.c:12343 +#: commands/tablecmds.c:12889 #, c-format msgid "You might need to add an explicit cast." msgstr "Возможно, необходимо добавить явное приведение." -#: commands/tablecmds.c:12347 +#: commands/tablecmds.c:12893 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "столбец \"%s\" нельзя автоматически привести к типу %s" # skip-rule: double-colons #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12350 +#: commands/tablecmds.c:12897 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "Возможно, необходимо указать \"USING %s::%s\"." -#: commands/tablecmds.c:12449 +#: commands/tablecmds.c:12996 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "изменить наследованный столбец \"%s\" отношения \"%s\" нельзя" -#: commands/tablecmds.c:12478 +#: commands/tablecmds.c:13025 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "Выражение USING ссылается на тип всей строки таблицы." -#: commands/tablecmds.c:12489 +#: commands/tablecmds.c:13036 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "" "тип наследованного столбца \"%s\" должен быть изменён и в дочерних таблицах" -#: commands/tablecmds.c:12614 +#: commands/tablecmds.c:13161 #, c-format msgid "cannot alter type of column \"%s\" twice" msgstr "нельзя изменить тип столбца \"%s\" дважды" -#: commands/tablecmds.c:12652 +#: commands/tablecmds.c:13199 #, c-format msgid "" "generation expression for column \"%s\" cannot be cast automatically to type " @@ -12297,160 +12828,160 @@ msgstr "" "генерирующее выражение для столбца \"%s\" нельзя автоматически привести к " "типу %s" -#: commands/tablecmds.c:12657 +#: commands/tablecmds.c:13204 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "" "значение по умолчанию для столбца \"%s\" нельзя автоматически привести к " "типу %s" -#: commands/tablecmds.c:12745 +#: commands/tablecmds.c:13508 #, c-format msgid "cannot alter type of a column used by a function or procedure" msgstr "изменить тип столбца, задействованного в функции или процедуре, нельзя" -#: commands/tablecmds.c:12746 commands/tablecmds.c:12760 -#: commands/tablecmds.c:12779 commands/tablecmds.c:12797 -#: commands/tablecmds.c:12855 +#: commands/tablecmds.c:13509 commands/tablecmds.c:13524 +#: commands/tablecmds.c:13544 commands/tablecmds.c:13563 +#: commands/tablecmds.c:13622 #, c-format msgid "%s depends on column \"%s\"" msgstr "%s зависит от столбца \"%s\"" -#: commands/tablecmds.c:12759 +#: commands/tablecmds.c:13523 #, c-format msgid "cannot alter type of a column used by a view or rule" msgstr "" "изменить тип столбца, задействованного в представлении или правиле, нельзя" -#: commands/tablecmds.c:12778 +#: commands/tablecmds.c:13543 #, c-format msgid "cannot alter type of a column used in a trigger definition" msgstr "изменить тип столбца, задействованного в определении триггера, нельзя" -#: commands/tablecmds.c:12796 +#: commands/tablecmds.c:13562 #, c-format msgid "cannot alter type of a column used in a policy definition" msgstr "изменить тип столбца, задействованного в определении политики, нельзя" -#: commands/tablecmds.c:12827 +#: commands/tablecmds.c:13593 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "изменить тип столбца, задействованного в генерируемом столбце, нельзя" -#: commands/tablecmds.c:12828 +#: commands/tablecmds.c:13594 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "Столбец \"%s\" используется генерируемым столбцом \"%s\"." -#: commands/tablecmds.c:12854 +#: commands/tablecmds.c:13621 #, c-format msgid "cannot alter type of a column used by a publication WHERE clause" msgstr "" "изменить тип столбца, задействованного в заданном для публикации предложении " "WHERE, нельзя" -#: commands/tablecmds.c:13915 commands/tablecmds.c:13927 +#: commands/tablecmds.c:14456 commands/tablecmds.c:14468 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "сменить владельца индекса \"%s\" нельзя" -#: commands/tablecmds.c:13917 commands/tablecmds.c:13929 +#: commands/tablecmds.c:14458 commands/tablecmds.c:14470 #, c-format msgid "Change the ownership of the index's table instead." msgstr "Однако возможно сменить владельца таблицы, содержащей этот индекс." -#: commands/tablecmds.c:13943 +#: commands/tablecmds.c:14484 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "сменить владельца последовательности \"%s\" нельзя" -#: commands/tablecmds.c:13968 +#: commands/tablecmds.c:14509 #, c-format msgid "cannot change owner of relation \"%s\"" msgstr "сменить владельца отношения \"%s\" нельзя" -#: commands/tablecmds.c:14330 +#: commands/tablecmds.c:14976 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "в одной инструкции не может быть несколько подкоманд SET TABLESPACE" -#: commands/tablecmds.c:14407 +#: commands/tablecmds.c:15053 #, c-format msgid "cannot set options for relation \"%s\"" msgstr "задать параметры отношения \"%s\" нельзя" -#: commands/tablecmds.c:14441 commands/view.c:445 +#: commands/tablecmds.c:15087 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "" "WITH CHECK OPTION поддерживается только с автообновляемыми представлениями" -#: commands/tablecmds.c:14691 +#: commands/tablecmds.c:15338 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "" "в табличных пространствах есть только таблицы, индексы и материализованные " "представления" -#: commands/tablecmds.c:14703 +#: commands/tablecmds.c:15350 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "перемещать объекты в/из табличного пространства pg_global нельзя" -#: commands/tablecmds.c:14795 +#: commands/tablecmds.c:15442 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "" "обработка прерывается из-за невозможности заблокировать отношение \"%s.%s\"" -#: commands/tablecmds.c:14811 +#: commands/tablecmds.c:15458 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr "в табличном пространстве \"%s\" не найдены подходящие отношения" -#: commands/tablecmds.c:14929 +#: commands/tablecmds.c:15580 #, c-format msgid "cannot change inheritance of typed table" msgstr "изменить наследование типизированной таблицы нельзя" -#: commands/tablecmds.c:14934 commands/tablecmds.c:15452 +#: commands/tablecmds.c:15585 commands/tablecmds.c:16085 #, c-format msgid "cannot change inheritance of a partition" msgstr "изменить наследование секции нельзя" -#: commands/tablecmds.c:14939 +#: commands/tablecmds.c:15590 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "изменить наследование секционированной таблицы нельзя" -#: commands/tablecmds.c:14985 +#: commands/tablecmds.c:15636 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "наследование для временного отношения другого сеанса невозможно" -#: commands/tablecmds.c:14998 +#: commands/tablecmds.c:15649 #, c-format msgid "cannot inherit from a partition" msgstr "наследование от секции невозможно" -#: commands/tablecmds.c:15020 commands/tablecmds.c:17878 +#: commands/tablecmds.c:15671 commands/tablecmds.c:18529 #, c-format msgid "circular inheritance not allowed" msgstr "циклическое наследование недопустимо" -#: commands/tablecmds.c:15021 commands/tablecmds.c:17879 +#: commands/tablecmds.c:15672 commands/tablecmds.c:18530 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "\"%s\" уже является потомком \"%s\"." -#: commands/tablecmds.c:15034 +#: commands/tablecmds.c:15685 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "" "триггер \"%s\" не позволяет таблице \"%s\" стать потомком в иерархии " "наследования" -#: commands/tablecmds.c:15036 +#: commands/tablecmds.c:15687 #, c-format msgid "" "ROW triggers with transition tables are not supported in inheritance " @@ -12459,34 +12990,34 @@ msgstr "" "Триггеры ROW с переходными таблицами не поддерживаются в иерархиях " "наследования." -#: commands/tablecmds.c:15239 +#: commands/tablecmds.c:15876 #, c-format msgid "column \"%s\" in child table must be marked NOT NULL" msgstr "столбец \"%s\" в дочерней таблице должен быть помечен как NOT NULL" -#: commands/tablecmds.c:15248 +#: commands/tablecmds.c:15885 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "столбец \"%s\" в дочерней таблице должен быть генерируемым" -#: commands/tablecmds.c:15253 +#: commands/tablecmds.c:15889 #, c-format msgid "column \"%s\" in child table must not be a generated column" msgstr "столбец \"%s\" в дочерней таблице должен быть не генерируемым" -#: commands/tablecmds.c:15284 +#: commands/tablecmds.c:15927 #, c-format msgid "child table is missing column \"%s\"" msgstr "в дочерней таблице не хватает столбца \"%s\"" -#: commands/tablecmds.c:15372 +#: commands/tablecmds.c:16008 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "" "дочерняя таблица \"%s\" содержит другое определение ограничения-проверки " "\"%s\"" -#: commands/tablecmds.c:15380 +#: commands/tablecmds.c:16015 #, c-format msgid "" "constraint \"%s\" conflicts with non-inherited constraint on child table " @@ -12495,7 +13026,7 @@ msgstr "" "ограничение \"%s\" конфликтует с ненаследуемым ограничением дочерней таблицы " "\"%s\"" -#: commands/tablecmds.c:15391 +#: commands/tablecmds.c:16025 #, c-format msgid "" "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" @@ -12503,82 +13034,82 @@ msgstr "" "ограничение \"%s\" конфликтует с непроверенным (NOT VALID) ограничением " "дочерней таблицы \"%s\"" -#: commands/tablecmds.c:15430 +#: commands/tablecmds.c:16063 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "в дочерней таблице не хватает ограничения \"%s\"" -#: commands/tablecmds.c:15516 +#: commands/tablecmds.c:16149 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "" "секция \"%s\" уже ожидает отсоединения от секционированной таблицы \"%s.%s\"" -#: commands/tablecmds.c:15545 commands/tablecmds.c:15593 +#: commands/tablecmds.c:16178 commands/tablecmds.c:16224 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "отношение \"%s\" не является секцией отношения \"%s\"" -#: commands/tablecmds.c:15599 +#: commands/tablecmds.c:16230 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "отношение \"%s\" не является предком отношения \"%s\"" -#: commands/tablecmds.c:15827 +#: commands/tablecmds.c:16457 #, c-format msgid "typed tables cannot inherit" msgstr "типизированные таблицы не могут наследоваться" -#: commands/tablecmds.c:15857 +#: commands/tablecmds.c:16487 #, c-format msgid "table is missing column \"%s\"" msgstr "в таблице не хватает столбца \"%s\"" -#: commands/tablecmds.c:15868 +#: commands/tablecmds.c:16498 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "таблица содержит столбец \"%s\", тогда как тип требует \"%s\"" -#: commands/tablecmds.c:15877 +#: commands/tablecmds.c:16507 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "таблица \"%s\" содержит столбец \"%s\" другого типа" -#: commands/tablecmds.c:15891 +#: commands/tablecmds.c:16521 #, c-format msgid "table has extra column \"%s\"" msgstr "таблица содержит лишний столбец \"%s\"" -#: commands/tablecmds.c:15943 +#: commands/tablecmds.c:16573 #, c-format msgid "\"%s\" is not a typed table" msgstr "\"%s\" - это не типизированная таблица" -#: commands/tablecmds.c:16117 +#: commands/tablecmds.c:16747 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "" "для идентификации реплики нельзя использовать неуникальный индекс \"%s\"" -#: commands/tablecmds.c:16123 +#: commands/tablecmds.c:16753 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "" "для идентификации реплики нельзя использовать не непосредственный индекс " "\"%s\"" -#: commands/tablecmds.c:16129 +#: commands/tablecmds.c:16759 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "" "для идентификации реплики нельзя использовать индекс с выражением \"%s\"" -#: commands/tablecmds.c:16135 +#: commands/tablecmds.c:16765 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "для идентификации реплики нельзя использовать частичный индекс \"%s\"" -#: commands/tablecmds.c:16152 +#: commands/tablecmds.c:16782 #, c-format msgid "" "index \"%s\" cannot be used as replica identity because column %d is a " @@ -12587,7 +13118,7 @@ msgstr "" "индекс \"%s\" нельзя использовать для идентификации реплики, так как столбец " "%d - системный" -#: commands/tablecmds.c:16159 +#: commands/tablecmds.c:16789 #, c-format msgid "" "index \"%s\" cannot be used as replica identity because column \"%s\" is " @@ -12596,13 +13127,13 @@ msgstr "" "индекс \"%s\" нельзя использовать для идентификации реплики, так как столбец " "\"%s\" допускает NULL" -#: commands/tablecmds.c:16404 +#: commands/tablecmds.c:17041 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "" "изменить состояние журналирования таблицы %s нельзя, так как она временная" -#: commands/tablecmds.c:16428 +#: commands/tablecmds.c:17065 #, c-format msgid "" "cannot change table \"%s\" to unlogged because it is part of a publication" @@ -12610,12 +13141,12 @@ msgstr "" "таблицу \"%s\" нельзя сделать нежурналируемой, так как она включена в " "публикацию" -#: commands/tablecmds.c:16430 +#: commands/tablecmds.c:17067 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "Нежурналируемые отношения не поддерживают репликацию." -#: commands/tablecmds.c:16475 +#: commands/tablecmds.c:17112 #, c-format msgid "" "could not change table \"%s\" to logged because it references unlogged table " @@ -12624,7 +13155,7 @@ msgstr "" "не удалось сделать таблицу \"%s\" журналируемой, так как она ссылается на " "нежурналируемую таблицу \"%s\"" -#: commands/tablecmds.c:16485 +#: commands/tablecmds.c:17122 #, c-format msgid "" "could not change table \"%s\" to unlogged because it references logged table " @@ -12633,97 +13164,91 @@ msgstr "" "не удалось сделать таблицу \"%s\" нежурналируемой, так как она ссылается на " "журналируемую таблицу \"%s\"" -#: commands/tablecmds.c:16543 +#: commands/tablecmds.c:17180 #, c-format msgid "cannot move an owned sequence into another schema" msgstr "переместить последовательность с владельцем в другую схему нельзя" -#: commands/tablecmds.c:16645 +#: commands/tablecmds.c:17288 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "отношение \"%s\" уже существует в схеме \"%s\"" -#: commands/tablecmds.c:17065 +#: commands/tablecmds.c:17713 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "\"%s\" - это не таблица и не материализованное представление" -#: commands/tablecmds.c:17215 +#: commands/tablecmds.c:17866 #, c-format msgid "\"%s\" is not a composite type" msgstr "\"%s\" - это не составной тип" -#: commands/tablecmds.c:17245 +#: commands/tablecmds.c:17896 #, c-format msgid "cannot change schema of index \"%s\"" msgstr "сменить схему индекса \"%s\" нельзя" -#: commands/tablecmds.c:17247 commands/tablecmds.c:17261 +#: commands/tablecmds.c:17898 commands/tablecmds.c:17912 #, c-format msgid "Change the schema of the table instead." msgstr "Однако возможно сменить владельца таблицы." -#: commands/tablecmds.c:17251 +#: commands/tablecmds.c:17902 #, c-format msgid "cannot change schema of composite type \"%s\"" msgstr "сменить схему составного типа \"%s\" нельзя" -#: commands/tablecmds.c:17259 +#: commands/tablecmds.c:17910 #, c-format msgid "cannot change schema of TOAST table \"%s\"" msgstr "сменить схему TOAST-таблицы \"%s\" нельзя" -#: commands/tablecmds.c:17291 +#: commands/tablecmds.c:17942 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "стратегия секционирования по списку не поддерживает несколько столбцов" -#: commands/tablecmds.c:17357 +#: commands/tablecmds.c:18008 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "столбец \"%s\", упомянутый в ключе секционирования, не существует" -#: commands/tablecmds.c:17365 +#: commands/tablecmds.c:18016 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "системный столбец \"%s\" нельзя использовать в ключе секционирования" -#: commands/tablecmds.c:17376 commands/tablecmds.c:17466 +#: commands/tablecmds.c:18027 commands/tablecmds.c:18117 #, c-format msgid "cannot use generated column in partition key" msgstr "генерируемый столбец нельзя использовать в ключе секционирования" -#: commands/tablecmds.c:17377 commands/tablecmds.c:17467 commands/trigger.c:663 -#: rewrite/rewriteHandler.c:936 rewrite/rewriteHandler.c:971 -#, c-format -msgid "Column \"%s\" is a generated column." -msgstr "Столбец \"%s\" является генерируемым." - -#: commands/tablecmds.c:17449 +#: commands/tablecmds.c:18100 #, c-format msgid "partition key expressions cannot contain system column references" msgstr "" "выражения ключей секционирования не могут содержать ссылки на системный " "столбец" -#: commands/tablecmds.c:17496 +#: commands/tablecmds.c:18147 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "" "функции в выражении ключа секционирования должны быть помечены как IMMUTABLE" -#: commands/tablecmds.c:17505 +#: commands/tablecmds.c:18156 #, c-format msgid "cannot use constant expression as partition key" msgstr "" "в качестве ключа секционирования нельзя использовать константное выражение" -#: commands/tablecmds.c:17526 +#: commands/tablecmds.c:18177 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "не удалось определить правило сортировки для выражения секционирования" -#: commands/tablecmds.c:17561 +#: commands/tablecmds.c:18212 #, c-format msgid "" "You must specify a hash operator class or define a default hash operator " @@ -12732,7 +13257,7 @@ msgstr "" "Вы должны указать класс операторов хеширования или определить класс " "операторов хеширования по умолчанию для этого типа данных." -#: commands/tablecmds.c:17567 +#: commands/tablecmds.c:18218 #, c-format msgid "" "You must specify a btree operator class or define a default btree operator " @@ -12741,27 +13266,27 @@ msgstr "" "Вы должны указать класс операторов B-дерева или определить класс операторов " "B-дерева по умолчанию для этого типа данных." -#: commands/tablecmds.c:17818 +#: commands/tablecmds.c:18469 #, c-format msgid "\"%s\" is already a partition" msgstr "\"%s\" уже является секцией" -#: commands/tablecmds.c:17824 +#: commands/tablecmds.c:18475 #, c-format msgid "cannot attach a typed table as partition" msgstr "подключить типизированную таблицу в качестве секции нельзя" -#: commands/tablecmds.c:17840 +#: commands/tablecmds.c:18491 #, c-format msgid "cannot attach inheritance child as partition" msgstr "подключить потомок в иерархии наследования в качестве секции нельзя" -#: commands/tablecmds.c:17854 +#: commands/tablecmds.c:18505 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "подключить родитель в иерархии наследования в качестве секции нельзя" -#: commands/tablecmds.c:17888 +#: commands/tablecmds.c:18539 #, c-format msgid "" "cannot attach a temporary relation as partition of permanent relation \"%s\"" @@ -12769,7 +13294,7 @@ msgstr "" "подключить временное отношение в качестве секции постоянного отношения " "\"%s\" нельзя" -#: commands/tablecmds.c:17896 +#: commands/tablecmds.c:18547 #, c-format msgid "" "cannot attach a permanent relation as partition of temporary relation \"%s\"" @@ -12777,92 +13302,102 @@ msgstr "" "подключить постоянное отношение в качестве секции временного отношения " "\"%s\" нельзя" -#: commands/tablecmds.c:17904 +#: commands/tablecmds.c:18555 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "подключить секцию к временному отношению в другом сеансе нельзя" -#: commands/tablecmds.c:17911 +#: commands/tablecmds.c:18562 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "" "подключить временное отношение из другого сеанса в качестве секции нельзя" -#: commands/tablecmds.c:17931 +#: commands/tablecmds.c:18582 +#, c-format +msgid "table \"%s\" being attached contains an identity column \"%s\"" +msgstr "присоединяемая таблица \"%s\" содержит столбец идентификации \"%s\"" + +#: commands/tablecmds.c:18584 +#, c-format +msgid "The new partition may not contain an identity column." +msgstr "Новая секция не может содержать столбец идентификации." + +#: commands/tablecmds.c:18592 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "" "таблица \"%s\" содержит столбец \"%s\", отсутствующий в родителе \"%s\"" -#: commands/tablecmds.c:17934 +#: commands/tablecmds.c:18595 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "" "Новая секция может содержать только столбцы, имеющиеся в родительской " "таблице." -#: commands/tablecmds.c:17946 +#: commands/tablecmds.c:18607 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "триггер \"%s\" не позволяет сделать таблицу \"%s\" секцией" -#: commands/tablecmds.c:17948 +#: commands/tablecmds.c:18609 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "Триггеры ROW с переходными таблицами для секций не поддерживаются." -#: commands/tablecmds.c:18127 +#: commands/tablecmds.c:18785 #, c-format msgid "" "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "" "нельзя присоединить стороннюю таблицу \"%s\" в качестве секции таблицы \"%s\"" -#: commands/tablecmds.c:18130 +#: commands/tablecmds.c:18788 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "Секционированная таблица \"%s\" содержит уникальные индексы." -#: commands/tablecmds.c:18447 +#: commands/tablecmds.c:19110 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "" "секции нельзя отсоединять в режиме CONCURRENTLY, когда существует секция по " "умолчанию" -#: commands/tablecmds.c:18556 +#: commands/tablecmds.c:19219 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "секционированная таблица \"%s\" была параллельно удалена" -#: commands/tablecmds.c:18562 +#: commands/tablecmds.c:19225 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "секция \"%s\" была параллельно удалена" -#: commands/tablecmds.c:19077 commands/tablecmds.c:19097 -#: commands/tablecmds.c:19118 commands/tablecmds.c:19137 -#: commands/tablecmds.c:19179 +#: commands/tablecmds.c:19839 commands/tablecmds.c:19859 +#: commands/tablecmds.c:19880 commands/tablecmds.c:19899 +#: commands/tablecmds.c:19941 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "нельзя присоединить индекс \"%s\" в качестве секции индекса \"%s\"" -#: commands/tablecmds.c:19080 +#: commands/tablecmds.c:19842 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "Индекс \"%s\" уже присоединён к другому индексу." -#: commands/tablecmds.c:19100 +#: commands/tablecmds.c:19862 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "Индекс \"%s\" не является индексом какой-либо секции таблицы \"%s\"." -#: commands/tablecmds.c:19121 +#: commands/tablecmds.c:19883 #, c-format msgid "The index definitions do not match." msgstr "Определения индексов не совпадают." -#: commands/tablecmds.c:19140 +#: commands/tablecmds.c:19902 #, c-format msgid "" "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint " @@ -12871,172 +13406,172 @@ msgstr "" "Индекс \"%s\" принадлежит ограничению в таблице \"%s\", но для индекса " "\"%s\" ограничения нет." -#: commands/tablecmds.c:19182 +#: commands/tablecmds.c:19944 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "К секции \"%s\" уже присоединён другой индекс." -#: commands/tablecmds.c:19418 +#: commands/tablecmds.c:20180 #, c-format msgid "column data type %s does not support compression" msgstr "тим данных столбца %s не поддерживает сжатие" -#: commands/tablecmds.c:19425 +#: commands/tablecmds.c:20187 #, c-format msgid "invalid compression method \"%s\"" msgstr "неверный метод сжатия \"%s\"" -#: commands/tablecmds.c:19451 +#: commands/tablecmds.c:20213 #, c-format msgid "invalid storage type \"%s\"" msgstr "неверный тип хранилища \"%s\"" -#: commands/tablecmds.c:19461 +#: commands/tablecmds.c:20223 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "тип данных столбца %s совместим только с хранилищем PLAIN" -#: commands/tablespace.c:199 commands/tablespace.c:650 +#: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" msgstr "\"%s\" существует, но это не каталог" -#: commands/tablespace.c:230 +#: commands/tablespace.c:224 #, c-format msgid "permission denied to create tablespace \"%s\"" -msgstr "нет прав на создание табличного пространства \"%s\"" +msgstr "нет прав для создания табличного пространства \"%s\"" -#: commands/tablespace.c:232 +#: commands/tablespace.c:226 #, c-format msgid "Must be superuser to create a tablespace." msgstr "Для создания табличного пространства нужно быть суперпользователем." -#: commands/tablespace.c:248 +#: commands/tablespace.c:242 #, c-format msgid "tablespace location cannot contain single quotes" msgstr "в пути к табличному пространству не должно быть одинарных кавычек" -#: commands/tablespace.c:261 +#: commands/tablespace.c:255 #, c-format msgid "tablespace location must be an absolute path" msgstr "путь к табличному пространству должен быть абсолютным" -#: commands/tablespace.c:273 +#: commands/tablespace.c:267 #, c-format msgid "tablespace location \"%s\" is too long" msgstr "путь к табличному пространству \"%s\" слишком длинный" -#: commands/tablespace.c:280 +#: commands/tablespace.c:274 #, c-format msgid "tablespace location should not be inside the data directory" msgstr "табличное пространство не должно располагаться внутри каталога данных" -#: commands/tablespace.c:289 commands/tablespace.c:976 +#: commands/tablespace.c:283 commands/tablespace.c:970 #, c-format msgid "unacceptable tablespace name \"%s\"" msgstr "неприемлемое имя табличного пространства: \"%s\"" -#: commands/tablespace.c:291 commands/tablespace.c:977 +#: commands/tablespace.c:285 commands/tablespace.c:971 #, c-format msgid "The prefix \"pg_\" is reserved for system tablespaces." msgstr "Префикс \"pg_\" зарезервирован для системных табличных пространств." -#: commands/tablespace.c:310 commands/tablespace.c:998 +#: commands/tablespace.c:304 commands/tablespace.c:992 #, c-format msgid "tablespace \"%s\" already exists" msgstr "табличное пространство \"%s\" уже существует" -#: commands/tablespace.c:326 +#: commands/tablespace.c:320 #, c-format msgid "pg_tablespace OID value not set when in binary upgrade mode" msgstr "значение OID в pg_tablespace не задано в режиме двоичного обновления" -#: commands/tablespace.c:431 commands/tablespace.c:959 -#: commands/tablespace.c:1048 commands/tablespace.c:1117 -#: commands/tablespace.c:1263 commands/tablespace.c:1466 +#: commands/tablespace.c:425 commands/tablespace.c:953 +#: commands/tablespace.c:1042 commands/tablespace.c:1111 +#: commands/tablespace.c:1257 commands/tablespace.c:1460 #, c-format msgid "tablespace \"%s\" does not exist" msgstr "табличное пространство \"%s\" не существует" -#: commands/tablespace.c:437 +#: commands/tablespace.c:431 #, c-format msgid "tablespace \"%s\" does not exist, skipping" msgstr "табличное пространство \"%s\" не существует, пропускается" -#: commands/tablespace.c:463 +#: commands/tablespace.c:457 #, c-format msgid "tablespace \"%s\" cannot be dropped because some objects depend on it" msgstr "" "табличное пространство \"%s\" нельзя удалить, так как есть зависящие от него " "объекты" -#: commands/tablespace.c:530 +#: commands/tablespace.c:524 #, c-format msgid "tablespace \"%s\" is not empty" msgstr "табличное пространство \"%s\" не пусто" -#: commands/tablespace.c:617 +#: commands/tablespace.c:611 #, c-format msgid "directory \"%s\" does not exist" msgstr "каталог \"%s\" не существует" -#: commands/tablespace.c:618 +#: commands/tablespace.c:612 #, c-format msgid "Create this directory for the tablespace before restarting the server." msgstr "" "Создайте этот каталог для табличного пространства до перезапуска сервера." -#: commands/tablespace.c:623 +#: commands/tablespace.c:617 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "не удалось установить права для каталога \"%s\": %m" -#: commands/tablespace.c:655 +#: commands/tablespace.c:649 #, c-format msgid "directory \"%s\" already in use as a tablespace" msgstr "каталог \"%s\" уже используется как табличное пространство" -#: commands/tablespace.c:833 commands/tablespace.c:919 +#: commands/tablespace.c:827 commands/tablespace.c:913 #, c-format msgid "could not remove symbolic link \"%s\": %m" msgstr "ошибка при удалении символической ссылки \"%s\": %m" -#: commands/tablespace.c:842 commands/tablespace.c:927 +#: commands/tablespace.c:836 commands/tablespace.c:921 #, c-format msgid "\"%s\" is not a directory or symbolic link" msgstr "\"%s\" - это не каталог или символическая ссылка" -#: commands/tablespace.c:1122 +#: commands/tablespace.c:1116 #, c-format msgid "Tablespace \"%s\" does not exist." msgstr "Табличное пространство \"%s\" не существует." -#: commands/tablespace.c:1568 +#: commands/tablespace.c:1562 #, c-format msgid "directories for tablespace %u could not be removed" msgstr "удалить каталоги табличного пространства %u не удалось" -#: commands/tablespace.c:1570 +#: commands/tablespace.c:1564 #, c-format msgid "You can remove the directories manually if necessary." msgstr "При необходимости вы можете удалить их вручную." -#: commands/trigger.c:232 commands/trigger.c:243 +#: commands/trigger.c:225 commands/trigger.c:236 #, c-format msgid "\"%s\" is a table" msgstr "\"%s\" - это таблица" -#: commands/trigger.c:234 commands/trigger.c:245 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "Tables cannot have INSTEAD OF triggers." msgstr "У таблиц не может быть триггеров INSTEAD OF." -#: commands/trigger.c:266 +#: commands/trigger.c:259 #, c-format msgid "\"%s\" is a partitioned table" msgstr "\"%s\" - секционированная таблица" -#: commands/trigger.c:268 +#: commands/trigger.c:261 #, c-format msgid "" "ROW triggers with transition tables are not supported on partitioned tables." @@ -13044,88 +13579,88 @@ msgstr "" "Триггеры ROW с переходными таблицами не поддерживаются в секционированных " "таблицах." -#: commands/trigger.c:280 commands/trigger.c:287 commands/trigger.c:451 +#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 #, c-format msgid "\"%s\" is a view" msgstr "\"%s\" - это представление" -#: commands/trigger.c:282 +#: commands/trigger.c:275 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." msgstr "У представлений не может быть строковых триггеров BEFORE/AFTER." -#: commands/trigger.c:289 +#: commands/trigger.c:282 #, c-format msgid "Views cannot have TRUNCATE triggers." msgstr "У представлений не может быть триггеров TRUNCATE." -#: commands/trigger.c:297 commands/trigger.c:309 commands/trigger.c:444 +#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 #, c-format msgid "\"%s\" is a foreign table" msgstr "\"%s\" - сторонняя таблица" -#: commands/trigger.c:299 +#: commands/trigger.c:292 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." msgstr "У сторонних таблиц не может быть триггеров INSTEAD OF." -#: commands/trigger.c:311 +#: commands/trigger.c:304 #, c-format msgid "Foreign tables cannot have constraint triggers." msgstr "У сторонних таблиц не может быть ограничивающих триггеров." -#: commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1439 +#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 #, c-format msgid "relation \"%s\" cannot have triggers" msgstr "в отношении \"%s\" не может быть триггеров" -#: commands/trigger.c:387 +#: commands/trigger.c:380 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" msgstr "триггеры TRUNCATE FOR EACH ROW не поддерживаются" -#: commands/trigger.c:395 +#: commands/trigger.c:388 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" msgstr "триггеры INSTEAD OF должны иметь тип FOR EACH ROW" -#: commands/trigger.c:399 +#: commands/trigger.c:392 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" msgstr "триггеры INSTEAD OF несовместимы с условиями WHEN" -#: commands/trigger.c:403 +#: commands/trigger.c:396 #, c-format msgid "INSTEAD OF triggers cannot have column lists" msgstr "для триггеров INSTEAD OF нельзя задать список столбцов" -#: commands/trigger.c:432 +#: commands/trigger.c:425 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "" "указание переменной типа кортеж в предложении REFERENCING не поддерживается" -#: commands/trigger.c:433 +#: commands/trigger.c:426 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "Используйте OLD TABLE или NEW TABLE для именования переходных таблиц." -#: commands/trigger.c:446 +#: commands/trigger.c:439 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "Триггеры сторонних таблиц не могут использовать переходные таблицы." -#: commands/trigger.c:453 +#: commands/trigger.c:446 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "Триггеры представлений не могут использовать переходные таблицы." -#: commands/trigger.c:469 +#: commands/trigger.c:462 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "триггеры ROW с переходными таблицами для секций не поддерживаются" -#: commands/trigger.c:473 +#: commands/trigger.c:466 #, c-format msgid "" "ROW triggers with transition tables are not supported on inheritance children" @@ -13133,17 +13668,17 @@ msgstr "" "триггеры ROW с переходными таблицами для потомков в иерархии наследования не " "поддерживаются" -#: commands/trigger.c:479 +#: commands/trigger.c:472 #, c-format msgid "transition table name can only be specified for an AFTER trigger" msgstr "имя переходной таблицы можно задать только для триггера AFTER" -#: commands/trigger.c:484 +#: commands/trigger.c:477 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "триггеры TRUNCATE с переходными таблицами не поддерживаются" -#: commands/trigger.c:501 +#: commands/trigger.c:494 #, c-format msgid "" "transition tables cannot be specified for triggers with more than one event" @@ -13151,127 +13686,127 @@ msgstr "" "переходные таблицы нельзя задать для триггеров, назначаемых для нескольких " "событий" -#: commands/trigger.c:512 +#: commands/trigger.c:505 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "переходные таблицы нельзя задать для триггеров со списками столбцов" -#: commands/trigger.c:529 +#: commands/trigger.c:522 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" msgstr "NEW TABLE можно задать только для триггеров INSERT или UPDATE" -#: commands/trigger.c:534 +#: commands/trigger.c:527 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE нельзя задать несколько раз" -#: commands/trigger.c:544 +#: commands/trigger.c:537 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" msgstr "OLD TABLE можно задать только для триггеров DELETE или UPDATE" -#: commands/trigger.c:549 +#: commands/trigger.c:542 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE нельзя задать несколько раз" -#: commands/trigger.c:559 +#: commands/trigger.c:552 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "имя OLD TABLE не должно совпадать с именем NEW TABLE" -#: commands/trigger.c:623 commands/trigger.c:636 +#: commands/trigger.c:616 commands/trigger.c:629 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" msgstr "" "в условии WHEN для операторного триггера нельзя ссылаться на значения " "столбцов" -#: commands/trigger.c:628 +#: commands/trigger.c:621 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" msgstr "в условии WHEN для триггера INSERT нельзя ссылаться на значения OLD" -#: commands/trigger.c:641 +#: commands/trigger.c:634 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" msgstr "в условии WHEN для триггера DELETE нельзя ссылаться на значения NEW" -#: commands/trigger.c:646 +#: commands/trigger.c:639 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" msgstr "" "в условии WHEN для триггера BEFORE нельзя ссылаться на системные столбцы NEW" -#: commands/trigger.c:654 commands/trigger.c:662 +#: commands/trigger.c:647 commands/trigger.c:655 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "" "в условии WHEN для триггера BEFORE нельзя ссылаться на генерируемые столбцы " "NEW" -#: commands/trigger.c:655 +#: commands/trigger.c:648 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "" "Используется ссылка на всю строку таблицы, а таблица содержит генерируемые " "столбцы." -#: commands/trigger.c:770 commands/trigger.c:1614 +#: commands/trigger.c:763 commands/trigger.c:1607 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "триггер \"%s\" для отношения \"%s\" уже существует" -#: commands/trigger.c:783 +#: commands/trigger.c:776 #, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" msgstr "триггер \"%s\" для отношения \"%s\" является внутренним или дочерним" -#: commands/trigger.c:802 +#: commands/trigger.c:795 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" msgstr "" "триггер \"%s\" для отношения \"%s\" является триггером, реализующим " "ограничение" -#: commands/trigger.c:1404 commands/trigger.c:1557 commands/trigger.c:1838 +#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "триггер \"%s\" для таблицы \"%s\" не существует" -#: commands/trigger.c:1529 +#: commands/trigger.c:1522 #, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" msgstr "переименовать триггер \"%s\" в таблице \"%s\" нельзя" -#: commands/trigger.c:1531 +#: commands/trigger.c:1524 #, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." msgstr "Однако можно переименовать триггер в секционированной таблице \"%s\"." -#: commands/trigger.c:1631 +#: commands/trigger.c:1624 #, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" msgstr "триггер \"%s\" в отношении \"%s\" переименован" -#: commands/trigger.c:1777 +#: commands/trigger.c:1770 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "нет доступа: \"%s\" - это системный триггер" -#: commands/trigger.c:2386 +#: commands/trigger.c:2379 #, c-format msgid "trigger function %u returned null value" msgstr "триггерная функция %u вернула значение NULL" -#: commands/trigger.c:2446 commands/trigger.c:2664 commands/trigger.c:2917 -#: commands/trigger.c:3270 +#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 +#: commands/trigger.c:3263 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "триггер BEFORE STATEMENT не может возвращать значение" -#: commands/trigger.c:2522 +#: commands/trigger.c:2515 #, c-format msgid "" "moving row to another partition during a BEFORE FOR EACH ROW trigger is not " @@ -13279,7 +13814,7 @@ msgid "" msgstr "" "в триггере BEFORE FOR EACH ROW нельзя перемещать строку в другую секцию" -#: commands/trigger.c:2523 +#: commands/trigger.c:2516 #, c-format msgid "" "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." @@ -13287,20 +13822,10 @@ msgstr "" "До выполнения триггера \"%s\" строка должна была находиться в секции \"%s." "%s\"." -#: commands/trigger.c:3347 executor/nodeModifyTable.c:2369 -#: executor/nodeModifyTable.c:2452 -#, c-format -msgid "" -"tuple to be updated was already modified by an operation triggered by the " -"current command" -msgstr "" -"кортеж, который должен быть изменён, уже модифицирован в операции, вызванной " -"текущей командой" - -#: commands/trigger.c:3348 executor/nodeModifyTable.c:1535 -#: executor/nodeModifyTable.c:1609 executor/nodeModifyTable.c:2370 -#: executor/nodeModifyTable.c:2453 executor/nodeModifyTable.c:2990 -#: executor/nodeModifyTable.c:3117 +#: commands/trigger.c:3341 executor/nodeModifyTable.c:1541 +#: executor/nodeModifyTable.c:1615 executor/nodeModifyTable.c:2377 +#: executor/nodeModifyTable.c:2468 executor/nodeModifyTable.c:3132 +#: executor/nodeModifyTable.c:3302 #, c-format msgid "" "Consider using an AFTER trigger instead of a BEFORE trigger to propagate " @@ -13309,34 +13834,34 @@ msgstr "" "Возможно, для распространения изменений в другие строки следует использовать " "триггер AFTER вместо BEFORE." -#: commands/trigger.c:3389 executor/nodeLockRows.c:228 -#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:308 -#: executor/nodeModifyTable.c:1551 executor/nodeModifyTable.c:2387 -#: executor/nodeModifyTable.c:2595 +#: commands/trigger.c:3382 executor/nodeLockRows.c:228 +#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:314 +#: executor/nodeModifyTable.c:1557 executor/nodeModifyTable.c:2394 +#: executor/nodeModifyTable.c:2618 #, c-format msgid "could not serialize access due to concurrent update" msgstr "не удалось сериализовать доступ из-за параллельного изменения" -#: commands/trigger.c:3397 executor/nodeModifyTable.c:1641 -#: executor/nodeModifyTable.c:2470 executor/nodeModifyTable.c:2619 -#: executor/nodeModifyTable.c:3008 +#: commands/trigger.c:3390 executor/nodeModifyTable.c:1647 +#: executor/nodeModifyTable.c:2485 executor/nodeModifyTable.c:2642 +#: executor/nodeModifyTable.c:3150 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "не удалось сериализовать доступ из-за параллельного удаления" -#: commands/trigger.c:4604 +#: commands/trigger.c:4599 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" msgstr "" "в рамках операции с ограничениями по безопасности нельзя вызвать отложенный " "триггер" -#: commands/trigger.c:5787 +#: commands/trigger.c:5780 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "ограничение \"%s\" не является откладываемым" -#: commands/trigger.c:5810 +#: commands/trigger.c:5803 #, c-format msgid "constraint \"%s\" does not exist" msgstr "ограничение \"%s\" не существует" @@ -13437,12 +13962,12 @@ msgstr "сопоставление для типа фрагмента \"%s\" н msgid "invalid parameter list format: \"%s\"" msgstr "неверный формат списка параметров: \"%s\"" -#: commands/typecmds.c:217 +#: commands/typecmds.c:221 #, c-format msgid "must be superuser to create a base type" msgstr "для создания базового типа нужно быть суперпользователем" -#: commands/typecmds.c:275 +#: commands/typecmds.c:279 #, c-format msgid "" "Create the type as a shell type, then create its I/O functions, then do a " @@ -13451,42 +13976,42 @@ msgstr "" "Создайте тип в виде оболочки, затем определите для него функции ввода-вывода " "и в завершение выполните полноценную команду CREATE TYPE." -#: commands/typecmds.c:327 commands/typecmds.c:1450 commands/typecmds.c:4263 +#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "атрибут типа \"%s\" не распознан" -#: commands/typecmds.c:382 +#: commands/typecmds.c:386 #, c-format msgid "invalid type category \"%s\": must be simple ASCII" msgstr "неверная категория типа \"%s\": допустим только ASCII-символ" -#: commands/typecmds.c:401 +#: commands/typecmds.c:405 #, c-format msgid "array element type cannot be %s" msgstr "типом элемента массива не может быть %s" -#: commands/typecmds.c:433 +#: commands/typecmds.c:437 #, c-format msgid "alignment \"%s\" not recognized" msgstr "тип выравнивания \"%s\" не распознан" -#: commands/typecmds.c:450 commands/typecmds.c:4137 +#: commands/typecmds.c:454 commands/typecmds.c:4354 #, c-format msgid "storage \"%s\" not recognized" msgstr "неизвестная стратегия хранения \"%s\"" -#: commands/typecmds.c:461 +#: commands/typecmds.c:465 #, c-format msgid "type input function must be specified" msgstr "необходимо указать функцию ввода типа" -#: commands/typecmds.c:465 +#: commands/typecmds.c:469 #, c-format msgid "type output function must be specified" msgstr "необходимо указать функцию вывода типа" -#: commands/typecmds.c:470 +#: commands/typecmds.c:474 #, c-format msgid "" "type modifier output function is useless without a type modifier input " @@ -13495,89 +14020,89 @@ msgstr "" "функция вывода модификатора типа бесполезна без функции ввода модификатора " "типа" -#: commands/typecmds.c:512 +#: commands/typecmds.c:516 #, c-format msgid "element type cannot be specified without a subscripting function" msgstr "" "тип элемента нельзя задать без указания обработчика обращения по индексу" -#: commands/typecmds.c:781 +#: commands/typecmds.c:785 #, c-format msgid "\"%s\" is not a valid base type for a domain" msgstr "\"%s\" - неподходящий базовый тип для домена" -#: commands/typecmds.c:879 +#: commands/typecmds.c:883 #, c-format msgid "multiple default expressions" msgstr "неоднократное определение значения типа по умолчанию" -#: commands/typecmds.c:942 commands/typecmds.c:951 +#: commands/typecmds.c:946 commands/typecmds.c:955 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "конфликтующие ограничения NULL/NOT NULL" -#: commands/typecmds.c:967 +#: commands/typecmds.c:971 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "" "ограничения-проверки для доменов не могут иметь характеристики NO INHERIT" -#: commands/typecmds.c:976 commands/typecmds.c:2956 +#: commands/typecmds.c:980 commands/typecmds.c:2940 #, c-format msgid "unique constraints not possible for domains" msgstr "ограничения уникальности невозможны для доменов" -#: commands/typecmds.c:982 commands/typecmds.c:2962 +#: commands/typecmds.c:986 commands/typecmds.c:2946 #, c-format msgid "primary key constraints not possible for domains" msgstr "ограничения первичного ключа невозможны для доменов" -#: commands/typecmds.c:988 commands/typecmds.c:2968 +#: commands/typecmds.c:992 commands/typecmds.c:2952 #, c-format msgid "exclusion constraints not possible for domains" msgstr "ограничения-исключения невозможны для доменов" -#: commands/typecmds.c:994 commands/typecmds.c:2974 +#: commands/typecmds.c:998 commands/typecmds.c:2958 #, c-format msgid "foreign key constraints not possible for domains" msgstr "ограничения внешних ключей невозможны для доменов" -#: commands/typecmds.c:1003 commands/typecmds.c:2983 +#: commands/typecmds.c:1007 commands/typecmds.c:2967 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "" "возможность определения отложенных ограничений для доменов не поддерживается" -#: commands/typecmds.c:1317 utils/cache/typcache.c:2567 +#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 #, c-format msgid "%s is not an enum" msgstr "\"%s\" не является перечислением" -#: commands/typecmds.c:1458 +#: commands/typecmds.c:1468 #, c-format msgid "type attribute \"subtype\" is required" msgstr "требуется атрибут типа \"subtype\"" -#: commands/typecmds.c:1463 +#: commands/typecmds.c:1473 #, c-format msgid "range subtype cannot be %s" msgstr "%s не может быть подтипом диапазона" -#: commands/typecmds.c:1482 +#: commands/typecmds.c:1492 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "" "указано правило сортировки для диапазона, но подтип не поддерживает " "сортировку" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1502 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "" "функцию получения канонического диапазона нельзя задать без предварительно " "созданного типа-пустышки" -#: commands/typecmds.c:1493 +#: commands/typecmds.c:1503 #, c-format msgid "" "Create the type as a shell type, then create its canonicalization function, " @@ -13586,96 +14111,96 @@ msgstr "" "Создайте тип в виде оболочки, затем определите для него функции приведения к " "каноническому виду и в завершение выполните полноценную команду CREATE TYPE." -#: commands/typecmds.c:1965 +#: commands/typecmds.c:1975 #, c-format msgid "type input function %s has multiple matches" msgstr "функция ввода типа %s присутствует в нескольких экземплярах" -#: commands/typecmds.c:1983 +#: commands/typecmds.c:1993 #, c-format msgid "type input function %s must return type %s" msgstr "функция ввода типа %s должна возвращать тип %s" -#: commands/typecmds.c:1999 +#: commands/typecmds.c:2009 #, c-format msgid "type input function %s should not be volatile" msgstr "функция ввода типа %s не должна быть изменчивой" -#: commands/typecmds.c:2027 +#: commands/typecmds.c:2037 #, c-format msgid "type output function %s must return type %s" msgstr "функция вывода типа %s должна возвращать тип %s" -#: commands/typecmds.c:2034 +#: commands/typecmds.c:2044 #, c-format msgid "type output function %s should not be volatile" msgstr "функция вывода типа %s не должна быть изменчивой" -#: commands/typecmds.c:2063 +#: commands/typecmds.c:2073 #, c-format msgid "type receive function %s has multiple matches" msgstr "функция получения типа %s присутствует в нескольких экземплярах" -#: commands/typecmds.c:2081 +#: commands/typecmds.c:2091 #, c-format msgid "type receive function %s must return type %s" msgstr "функция получения типа %s должна возвращать тип %s" -#: commands/typecmds.c:2088 +#: commands/typecmds.c:2098 #, c-format msgid "type receive function %s should not be volatile" msgstr "функция получения типа %s не должна быть изменчивой" -#: commands/typecmds.c:2116 +#: commands/typecmds.c:2126 #, c-format msgid "type send function %s must return type %s" msgstr "функция отправки типа %s должна возвращать тип %s" -#: commands/typecmds.c:2123 +#: commands/typecmds.c:2133 #, c-format msgid "type send function %s should not be volatile" msgstr "функция отправки типа %s не должна быть изменчивой" -#: commands/typecmds.c:2150 +#: commands/typecmds.c:2160 #, c-format msgid "typmod_in function %s must return type %s" msgstr "функция TYPMOD_IN %s должна возвращать тип %s" -#: commands/typecmds.c:2157 +#: commands/typecmds.c:2167 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "функция ввода модификатора типа %s не должна быть изменчивой" -#: commands/typecmds.c:2184 +#: commands/typecmds.c:2194 #, c-format msgid "typmod_out function %s must return type %s" msgstr "функция TYPMOD_OUT %s должна возвращать тип %s" -#: commands/typecmds.c:2191 +#: commands/typecmds.c:2201 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "функция вывода модификатора типа %s не должна быть изменчивой" -#: commands/typecmds.c:2218 +#: commands/typecmds.c:2228 #, c-format msgid "type analyze function %s must return type %s" msgstr "функция анализа типа %s должна возвращать тип %s" -#: commands/typecmds.c:2247 +#: commands/typecmds.c:2257 #, c-format msgid "type subscripting function %s must return type %s" msgstr "" "функция %s, реализующая для типа обращение по индексу, должна возвращать тип " "%s" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2267 #, c-format msgid "user-defined types cannot use subscripting function %s" msgstr "" "для пользовательских типов нельзя использовать функцию-обработчик обращения " "по индексу %s" -#: commands/typecmds.c:2303 +#: commands/typecmds.c:2313 #, c-format msgid "" "You must specify an operator class for the range type or define a default " @@ -13684,207 +14209,218 @@ msgstr "" "Вы должны указать класс операторов для типа диапазона или определить класс " "операторов по умолчанию для этого подтипа." -#: commands/typecmds.c:2334 +#: commands/typecmds.c:2344 #, c-format msgid "range canonical function %s must return range type" msgstr "" "функция получения канонического диапазона %s должна возвращать диапазон" -#: commands/typecmds.c:2340 +#: commands/typecmds.c:2350 #, c-format msgid "range canonical function %s must be immutable" msgstr "" "функция получения канонического диапазона %s должна быть постоянной " "(IMMUTABLE)" -#: commands/typecmds.c:2376 +#: commands/typecmds.c:2386 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "функция различий для подтипа диапазона (%s) должна возвращать тип %s" -#: commands/typecmds.c:2383 +#: commands/typecmds.c:2393 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "" "функция различий для подтипа диапазона (%s) должна быть постоянной " "(IMMUTABLE)" -#: commands/typecmds.c:2410 +#: commands/typecmds.c:2420 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "значение OID массива в pg_type не задано в режиме двоичного обновления" -#: commands/typecmds.c:2443 +#: commands/typecmds.c:2453 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "" "значение OID мультидиапазона в pg_type не задано в режиме двоичного " "обновления" -#: commands/typecmds.c:2476 +#: commands/typecmds.c:2486 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" msgstr "" "значение OID массива мультидиапазонов в pg_type не задано в режиме двоичного " "обновления" -#: commands/typecmds.c:2772 -#, c-format -msgid "column \"%s\" of table \"%s\" contains null values" -msgstr "столбец \"%s\" таблицы \"%s\" содержит значения NULL" - -#: commands/typecmds.c:2885 commands/typecmds.c:3086 +#: commands/typecmds.c:2868 commands/typecmds.c:3093 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "ограничение \"%s\" для домена \"%s\" не существует" -#: commands/typecmds.c:2889 +#: commands/typecmds.c:2872 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "ограничение \"%s\" для домена \"%s\" не существует, пропускается" -#: commands/typecmds.c:3093 +#: commands/typecmds.c:3100 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "" "ограничение \"%s\" для домена \"%s\" не является ограничением-проверкой" -#: commands/typecmds.c:3194 +#: commands/typecmds.c:3180 +#, c-format +msgid "column \"%s\" of table \"%s\" contains null values" +msgstr "столбец \"%s\" таблицы \"%s\" содержит значения NULL" + +#: commands/typecmds.c:3269 #, c-format msgid "" "column \"%s\" of table \"%s\" contains values that violate the new constraint" msgstr "" "столбец \"%s\" таблицы \"%s\" содержит значения, нарушающие новое ограничение" -#: commands/typecmds.c:3423 commands/typecmds.c:3622 commands/typecmds.c:3705 -#: commands/typecmds.c:3893 +#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 +#: commands/typecmds.c:4073 #, c-format msgid "%s is not a domain" msgstr "\"%s\" - это не домен" -#: commands/typecmds.c:3455 +#: commands/typecmds.c:3532 commands/typecmds.c:3686 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "ограничение \"%s\" для домена \"%s\" уже существует" -#: commands/typecmds.c:3506 +#: commands/typecmds.c:3583 #, c-format msgid "cannot use table references in domain check constraint" msgstr "в ограничении-проверке для домена нельзя ссылаться на таблицы" -#: commands/typecmds.c:3634 commands/typecmds.c:3717 commands/typecmds.c:4010 +#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 #, c-format msgid "%s is a table's row type" msgstr "%s - это тип строк таблицы" -#: commands/typecmds.c:3644 commands/typecmds.c:3727 commands/typecmds.c:3925 +#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 #, c-format msgid "cannot alter array type %s" msgstr "изменить тип массива \"%s\" нельзя" -#: commands/typecmds.c:3646 commands/typecmds.c:3729 commands/typecmds.c:3927 +#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 #, c-format msgid "You can alter type %s, which will alter the array type as well." msgstr "Однако можно изменить тип %s, что повлечёт изменение типа массива." -#: commands/typecmds.c:3995 +#: commands/typecmds.c:3892 +#, c-format +msgid "cannot alter multirange type %s" +msgstr "изменить мультидиапазонный тип %s нельзя" + +#: commands/typecmds.c:3895 +#, c-format +msgid "You can alter type %s, which will alter the multirange type as well." +msgstr "" +"Однако можно изменить тип %s, что повлечёт изменение мультидиапазонного типа." + +#: commands/typecmds.c:4202 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "тип \"%s\" уже существует в схеме \"%s\"" -#: commands/typecmds.c:4165 +#: commands/typecmds.c:4382 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "сменить вариант хранения типа на PLAIN нельзя" -#: commands/typecmds.c:4258 +#: commands/typecmds.c:4475 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "у типа нельзя изменить атрибут \"%s\"" -#: commands/typecmds.c:4276 +#: commands/typecmds.c:4493 #, c-format msgid "must be superuser to alter a type" msgstr "для модификации типа нужно быть суперпользователем" -#: commands/typecmds.c:4297 commands/typecmds.c:4306 +#: commands/typecmds.c:4514 commands/typecmds.c:4523 #, c-format msgid "%s is not a base type" msgstr "%s — не базовый тип" -#: commands/user.c:201 +#: commands/user.c:200 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSID уже не нужно указывать" -#: commands/user.c:319 commands/user.c:325 commands/user.c:331 -#: commands/user.c:337 commands/user.c:343 +#: commands/user.c:318 commands/user.c:324 commands/user.c:330 +#: commands/user.c:336 commands/user.c:342 #, c-format msgid "permission denied to create role" msgstr "нет прав для создания роли" -#: commands/user.c:320 +#: commands/user.c:319 #, c-format msgid "Only roles with the %s attribute may create roles." msgstr "Создавать роли могут только роли с атрибутом %s." -#: commands/user.c:326 commands/user.c:332 commands/user.c:338 -#: commands/user.c:344 +#: commands/user.c:325 commands/user.c:331 commands/user.c:337 +#: commands/user.c:343 #, c-format msgid "" "Only roles with the %s attribute may create roles with the %s attribute." msgstr "Создавать роли с атрибутом %s могут только роли с атрибутом %s." -#: commands/user.c:355 commands/user.c:1387 commands/user.c:1394 -#: utils/adt/acl.c:5401 utils/adt/acl.c:5407 gram.y:16726 gram.y:16772 +#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 +#: utils/adt/acl.c:5574 utils/adt/acl.c:5580 gram.y:17310 gram.y:17356 #, c-format msgid "role name \"%s\" is reserved" msgstr "имя роли \"%s\" зарезервировано" -#: commands/user.c:357 commands/user.c:1389 commands/user.c:1396 +#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "Имена ролей, начинающиеся с \"pg_\", зарезервированы." -#: commands/user.c:378 commands/user.c:1411 +#: commands/user.c:377 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "роль \"%s\" уже существует" -#: commands/user.c:440 commands/user.c:925 +#: commands/user.c:439 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "пустая строка не является допустимым паролем; пароль сбрасывается" -#: commands/user.c:469 +#: commands/user.c:468 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "значение OID в pg_authid не задано в режиме двоичного обновления" -#: commands/user.c:653 commands/user.c:1011 +#: commands/user.c:652 commands/user.c:1010 msgid "Cannot alter reserved roles." msgstr "Изменять зарезервированные роли нельзя." -#: commands/user.c:760 commands/user.c:766 commands/user.c:782 -#: commands/user.c:790 commands/user.c:804 commands/user.c:810 -#: commands/user.c:816 commands/user.c:825 commands/user.c:870 -#: commands/user.c:1033 commands/user.c:1044 +#: commands/user.c:759 commands/user.c:765 commands/user.c:781 +#: commands/user.c:789 commands/user.c:803 commands/user.c:809 +#: commands/user.c:815 commands/user.c:824 commands/user.c:869 +#: commands/user.c:1032 commands/user.c:1043 #, c-format msgid "permission denied to alter role" msgstr "нет прав для изменения роли" -#: commands/user.c:761 commands/user.c:1034 +#: commands/user.c:760 commands/user.c:1033 #, c-format msgid "Only roles with the %s attribute may alter roles with the %s attribute." msgstr "Изменять роли с атрибутом %s могут только роли с атрибутом %s." -#: commands/user.c:767 commands/user.c:805 commands/user.c:811 -#: commands/user.c:817 +#: commands/user.c:766 commands/user.c:804 commands/user.c:810 +#: commands/user.c:816 #, c-format msgid "Only roles with the %s attribute may change the %s attribute." msgstr "Изменять атрибут %s могут только роли с атрибутом %s." -#: commands/user.c:783 commands/user.c:1045 +#: commands/user.c:782 commands/user.c:1044 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may alter " @@ -13893,7 +14429,7 @@ msgstr "" "Изменять эту роль могут только роли с атрибутом %s и привилегией %s для роли " "\"%s\"." -#: commands/user.c:791 +#: commands/user.c:790 #, c-format msgid "" "To change another role's password, the current user must have the %s " @@ -13902,32 +14438,34 @@ msgstr "" "Чтобы сменить пароль другой роли, текущий пользователь должен иметь атрибут " "%s и привилегию %s для этой роли." -#: commands/user.c:826 +#: commands/user.c:825 #, c-format -msgid "Only roles with the %s option on role \"%s\" may add members." -msgstr "Добавлять членов могут только роли с привилегией %s для роли \"%s\"." +msgid "Only roles with the %s option on role \"%s\" may add or drop members." +msgstr "" +"Добавлять или удалять членов могут только роли с привилегией %s для роли " +"\"%s\"." -#: commands/user.c:871 +#: commands/user.c:870 #, c-format -msgid "The bootstrap user must have the %s attribute." -msgstr "Стартовый пользователь должен иметь атрибут %s." +msgid "The bootstrap superuser must have the %s attribute." +msgstr "Стартовый суперпользователь должен иметь атрибут %s." -#: commands/user.c:1076 +#: commands/user.c:1075 #, c-format msgid "permission denied to alter setting" msgstr "нет прав для изменения параметров" -#: commands/user.c:1077 +#: commands/user.c:1076 #, c-format msgid "Only roles with the %s attribute may alter settings globally." msgstr "Изменять параметры глобально могут только роли с атрибутом %s." -#: commands/user.c:1101 commands/user.c:1172 commands/user.c:1178 +#: commands/user.c:1100 commands/user.c:1171 commands/user.c:1177 #, c-format msgid "permission denied to drop role" msgstr "нет прав для удаления роли" -#: commands/user.c:1102 +#: commands/user.c:1101 #, c-format msgid "" "Only roles with the %s attribute and the %s option on the target roles may " @@ -13936,41 +14474,41 @@ msgstr "" "Удалять роли могут только роли с атрибутом %s и с привилегией %s для целевых " "ролей." -#: commands/user.c:1126 +#: commands/user.c:1125 #, c-format msgid "cannot use special role specifier in DROP ROLE" msgstr "использовать специальную роль в DROP ROLE нельзя" -#: commands/user.c:1136 commands/user.c:1358 commands/variable.c:836 -#: commands/variable.c:839 commands/variable.c:923 commands/variable.c:926 -#: utils/adt/acl.c:356 utils/adt/acl.c:376 utils/adt/acl.c:5256 -#: utils/adt/acl.c:5304 utils/adt/acl.c:5332 utils/adt/acl.c:5351 -#: utils/adt/regproc.c:1551 utils/init/miscinit.c:756 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:851 +#: commands/variable.c:854 commands/variable.c:971 commands/variable.c:974 +#: utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5429 +#: utils/adt/acl.c:5477 utils/adt/acl.c:5505 utils/adt/acl.c:5524 +#: utils/adt/regproc.c:1571 utils/init/miscinit.c:799 #, c-format msgid "role \"%s\" does not exist" msgstr "роль \"%s\" не существует" -#: commands/user.c:1141 +#: commands/user.c:1140 #, c-format msgid "role \"%s\" does not exist, skipping" msgstr "роль \"%s\" не существует, пропускается" -#: commands/user.c:1154 commands/user.c:1158 +#: commands/user.c:1153 commands/user.c:1157 #, c-format msgid "current user cannot be dropped" msgstr "пользователь не может удалить сам себя" -#: commands/user.c:1162 +#: commands/user.c:1161 #, c-format msgid "session user cannot be dropped" msgstr "пользователя текущего сеанса нельзя удалить" -#: commands/user.c:1173 +#: commands/user.c:1172 #, c-format msgid "Only roles with the %s attribute may drop roles with the %s attribute." msgstr "Только роли с атрибутом %s могут удалять роли с атрибутом %s." -#: commands/user.c:1179 +#: commands/user.c:1178 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may drop " @@ -13979,33 +14517,33 @@ msgstr "" "Эту роль могут удалить только роли с атрибутом %s и привилегией %s для роли " "\"%s\"." -#: commands/user.c:1300 +#: commands/user.c:1299 #, c-format msgid "role \"%s\" cannot be dropped because some objects depend on it" msgstr "роль \"%s\" нельзя удалить, так как есть зависящие от неё объекты" -#: commands/user.c:1374 +#: commands/user.c:1373 #, c-format msgid "session user cannot be renamed" msgstr "пользователя текущего сеанса нельзя переименовать" -#: commands/user.c:1378 +#: commands/user.c:1377 #, c-format msgid "current user cannot be renamed" msgstr "пользователь не может переименовать сам себя" -#: commands/user.c:1422 commands/user.c:1432 +#: commands/user.c:1421 commands/user.c:1431 #, c-format msgid "permission denied to rename role" -msgstr "нет прав на переименование роли" +msgstr "нет прав для переименования роли" -#: commands/user.c:1423 +#: commands/user.c:1422 #, c-format msgid "" "Only roles with the %s attribute may rename roles with the %s attribute." msgstr "Только роли с атрибутом %s могут переименовывать роли с атрибутом %s." -#: commands/user.c:1433 +#: commands/user.c:1432 #, c-format msgid "" "Only roles with the %s attribute and the %s option on role \"%s\" may rename " @@ -14014,43 +14552,43 @@ msgstr "" "Переименовать эту роль могут только роли с атрибутом %s и привилегией %s для " "роли \"%s\"." -#: commands/user.c:1455 +#: commands/user.c:1454 #, c-format msgid "MD5 password cleared because of role rename" msgstr "в результате переименования роли очищен MD5-хеш пароля" -#: commands/user.c:1519 gram.y:1260 +#: commands/user.c:1518 gram.y:1294 #, c-format msgid "unrecognized role option \"%s\"" msgstr "нераспознанный параметр роли \"%s\"" -#: commands/user.c:1524 +#: commands/user.c:1523 #, c-format msgid "unrecognized value for role option \"%s\": \"%s\"" msgstr "нераспознанное значение для параметра роли \"%s\": \"%s\"" -#: commands/user.c:1557 +#: commands/user.c:1556 #, c-format msgid "column names cannot be included in GRANT/REVOKE ROLE" msgstr "в GRANT/REVOKE ROLE нельзя включать названия столбцов" -#: commands/user.c:1597 +#: commands/user.c:1596 #, c-format msgid "permission denied to drop objects" -msgstr "нет прав на удаление объектов" +msgstr "нет прав для удаления объектов" -#: commands/user.c:1598 +#: commands/user.c:1597 #, c-format msgid "Only roles with privileges of role \"%s\" may drop objects owned by it." msgstr "" "Только роли с правами роли \"%s\" могут удалять принадлежащие ей объекты." -#: commands/user.c:1626 commands/user.c:1637 +#: commands/user.c:1625 commands/user.c:1636 #, c-format msgid "permission denied to reassign objects" msgstr "нет прав для переназначения объектов" -#: commands/user.c:1627 +#: commands/user.c:1626 #, c-format msgid "" "Only roles with privileges of role \"%s\" may reassign objects owned by it." @@ -14058,102 +14596,102 @@ msgstr "" "Только роли с правами роли \"%s\" могут поменять владельца принадлежащих ей " "объектов." -#: commands/user.c:1638 +#: commands/user.c:1637 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects to it." msgstr "" "Только роли с правами роли \"%s\" могут назначать её владельцем объектов." -#: commands/user.c:1734 +#: commands/user.c:1733 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "роль \"%s\" не может быть членом другой роли" -#: commands/user.c:1747 +#: commands/user.c:1746 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "роль \"%s\" включена в роль \"%s\"" -#: commands/user.c:1787 commands/user.c:1813 +#: commands/user.c:1786 commands/user.c:1812 #, c-format msgid "%s option cannot be granted back to your own grantor" msgstr "привилегию %s нельзя вернуть тому, кто назначил её вам" -#: commands/user.c:1890 +#: commands/user.c:1889 #, c-format msgid "" "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" msgstr "роль \"%s\" уже назначена членом роли \"%s\" ролью \"%s\"" -#: commands/user.c:2025 +#: commands/user.c:2024 #, c-format msgid "" "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" msgstr "роль \"%s\" не была назначена членом роли \"%s\" ролью \"%s\"" -#: commands/user.c:2125 +#: commands/user.c:2124 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "роль \"%s\" не может содержать явных членов" -#: commands/user.c:2136 commands/user.c:2159 +#: commands/user.c:2135 commands/user.c:2158 #, c-format msgid "permission denied to grant role \"%s\"" msgstr "нет прав для назначения членства в роли \"%s\"" -#: commands/user.c:2138 +#: commands/user.c:2137 #, c-format msgid "Only roles with the %s attribute may grant roles with the %s attribute." msgstr "" "Только роли с атрибутом %s могут назначать членов в ролях с атрибутов %s." -#: commands/user.c:2143 commands/user.c:2166 +#: commands/user.c:2142 commands/user.c:2165 #, c-format msgid "permission denied to revoke role \"%s\"" msgstr "нет прав для лишения членства в роли \"%s\"" -#: commands/user.c:2145 +#: commands/user.c:2144 #, c-format msgid "" "Only roles with the %s attribute may revoke roles with the %s attribute." msgstr "" "Только роли с атрибутом %s могут лишать членства в ролях с атрибутом %s." -#: commands/user.c:2161 +#: commands/user.c:2160 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." msgstr "" "Только роли с привилегией %s для роли \"%s\" могут назначать членов в ней." -#: commands/user.c:2168 +#: commands/user.c:2167 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." msgstr "" "Только роли с привилегией %s для роли \"%s\" могут лишать членства в ней." -#: commands/user.c:2248 commands/user.c:2257 +#: commands/user.c:2247 commands/user.c:2256 #, c-format msgid "permission denied to grant privileges as role \"%s\"" msgstr "нет полномочий для назначения прав доступа роли \"%s\"" -#: commands/user.c:2250 +#: commands/user.c:2249 #, c-format msgid "" "Only roles with privileges of role \"%s\" may grant privileges as this role." msgstr "" "Только роли с правами роли \"%s\" могут назначать права от имени этой роли." -#: commands/user.c:2259 +#: commands/user.c:2258 #, c-format msgid "The grantor must have the %s option on role \"%s\"." msgstr "Праводатель должен иметь привилегию %s для роли \"%s\"." -#: commands/user.c:2267 +#: commands/user.c:2266 #, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" msgstr "нет полномочий для отзыва прав доступа, назначенных ролью \"%s\"" -#: commands/user.c:2269 +#: commands/user.c:2268 #, c-format msgid "" "Only roles with privileges of role \"%s\" may revoke privileges granted by " @@ -14161,17 +14699,17 @@ msgid "" msgstr "" "Только роли с правами роли \"%s\" могут отзывать права от имени этой роли." -#: commands/user.c:2492 utils/adt/acl.c:1309 +#: commands/user.c:2491 utils/adt/acl.c:1324 #, c-format msgid "dependent privileges exist" msgstr "существуют зависимые права" -#: commands/user.c:2493 utils/adt/acl.c:1310 +#: commands/user.c:2492 utils/adt/acl.c:1325 #, c-format msgid "Use CASCADE to revoke them too." msgstr "Используйте CASCADE, чтобы отозвать и их." -#: commands/vacuum.c:137 +#: commands/vacuum.c:134 #, c-format msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" msgstr "" @@ -14246,42 +14784,42 @@ msgstr "ONLY_DATABASE_STATS нельзя задавать с другими па msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%s нельзя выполнить в ходе VACUUM или ANALYZE" -#: commands/vacuum.c:733 +#: commands/vacuum.c:730 #, c-format msgid "permission denied to vacuum \"%s\", skipping it" msgstr "нет доступа для очистки отношения \"%s\", оно пропускается" -#: commands/vacuum.c:746 +#: commands/vacuum.c:743 #, c-format msgid "permission denied to analyze \"%s\", skipping it" msgstr "нет доступа для анализа отношения \"%s\", оно пропускается" -#: commands/vacuum.c:824 commands/vacuum.c:921 +#: commands/vacuum.c:821 commands/vacuum.c:918 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" msgstr "очистка \"%s\" пропускается --- блокировка недоступна" -#: commands/vacuum.c:829 +#: commands/vacuum.c:826 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "очистка \"%s\" пропускается --- это отношение более не существует" -#: commands/vacuum.c:845 commands/vacuum.c:926 +#: commands/vacuum.c:842 commands/vacuum.c:923 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" msgstr "анализ \"%s\" пропускается --- блокировка недоступна" -#: commands/vacuum.c:850 +#: commands/vacuum.c:847 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "анализ \"%s\" пропускается --- это отношение более не существует" -#: commands/vacuum.c:1161 +#: commands/vacuum.c:1139 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" msgstr "момент отсечки для удаления и замораживания кортежей далеко в прошлом" -#: commands/vacuum.c:1162 commands/vacuum.c:1167 +#: commands/vacuum.c:1140 commands/vacuum.c:1145 #, c-format msgid "" "Close open transactions soon to avoid wraparound problems.\n" @@ -14293,42 +14831,42 @@ msgstr "" "Возможно, вам также придётся зафиксировать или откатить старые " "подготовленные транзакции и удалить неиспользуемые слоты репликации." -#: commands/vacuum.c:1166 +#: commands/vacuum.c:1144 #, c-format msgid "cutoff for freezing multixacts is far in the past" msgstr "момент отсечки для замораживания мультитранзакций далеко в прошлом" -#: commands/vacuum.c:1912 +#: commands/vacuum.c:1900 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "" "есть базы данных, которые не очищались на протяжении более чем 2 миллиардов " "транзакций" -#: commands/vacuum.c:1913 +#: commands/vacuum.c:1901 #, c-format msgid "You might have already suffered transaction-wraparound data loss." msgstr "" "Возможно, вы уже потеряли данные в результате зацикливания ID транзакций." -#: commands/vacuum.c:2082 +#: commands/vacuum.c:2080 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "" "\"%s\" пропускается --- очищать не таблицы или специальные системные таблицы " "нельзя" -#: commands/vacuum.c:2507 +#: commands/vacuum.c:2512 #, c-format -msgid "scanned index \"%s\" to remove %d row versions" -msgstr "просканирован индекс \"%s\", удалено версий строк: %d" +msgid "scanned index \"%s\" to remove %lld row versions" +msgstr "просканирован индекс \"%s\", удалено версий строк: %lld" -#: commands/vacuum.c:2526 +#: commands/vacuum.c:2531 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "индекс \"%s\" теперь содержит версий строк: %.0f, в страницах: %u" -#: commands/vacuum.c:2530 +#: commands/vacuum.c:2535 #, c-format msgid "" "%.0f index row versions were removed.\n" @@ -14340,7 +14878,7 @@ msgstr "" "На данный момент удалено страниц индекса: %u, из них свободны для " "использования: %u." -#: commands/vacuumparallel.c:677 +#: commands/vacuumparallel.c:707 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "" @@ -14355,7 +14893,7 @@ msgstr[2] "" "запущено %d параллельных процессов очистки для очистки индекса " "(планировалось: %d)" -#: commands/vacuumparallel.c:683 +#: commands/vacuumparallel.c:713 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "" @@ -14432,7 +14970,7 @@ msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "" "команда SET TRANSACTION ISOLATION LEVEL не должна вызываться в подтранзакции" -#: commands/variable.c:606 storage/lmgr/predicate.c:1629 +#: commands/variable.c:606 storage/lmgr/predicate.c:1685 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "использовать сериализуемый режим в горячем резерве нельзя" @@ -14467,65 +15005,76 @@ msgstr "Изменить клиентскую кодировку сейчас н #: commands/variable.c:781 #, c-format -msgid "cannot change client_encoding during a parallel operation" -msgstr "изменить клиентскую кодировку во время параллельной операции нельзя" +msgid "cannot change \"client_encoding\" during a parallel operation" +msgstr "" +"изменить параметр \"client_encoding\" во время параллельной операции нельзя" + +#: commands/variable.c:876 +#, c-format +msgid "permission will be denied to set session authorization \"%s\"" +msgstr "в доступе для смены объекта авторизации \"%s\" будет отказано" + +#: commands/variable.c:881 +#, c-format +msgid "permission denied to set session authorization \"%s\"" +msgstr "нет доступа для смены объекта авторизации в сеансе \"%s\"" -#: commands/variable.c:948 +#: commands/variable.c:991 #, c-format msgid "permission will be denied to set role \"%s\"" msgstr "нет прав установить роль \"%s\"" -#: commands/variable.c:953 +#: commands/variable.c:996 #, c-format msgid "permission denied to set role \"%s\"" msgstr "нет прав установить роль \"%s\"" -#: commands/variable.c:1153 +#: commands/variable.c:1200 #, c-format msgid "Bonjour is not supported by this build" msgstr "Bonjour не поддерживается в данной сборке" -#: commands/variable.c:1181 +#: commands/variable.c:1228 #, c-format msgid "" -"effective_io_concurrency must be set to 0 on platforms that lack " +"\"effective_io_concurrency\" must be set to 0 on platforms that lack " "posix_fadvise()." msgstr "" -"Значение effective_io_concurrency должно равняться 0 на платформах, где " -"отсутствует lack posix_fadvise()." +"Значение \"effective_io_concurrency\" должно равняться 0 на платформах, где " +"отсутствует posix_fadvise()." -#: commands/variable.c:1194 +#: commands/variable.c:1241 #, c-format msgid "" -"maintenance_io_concurrency must be set to 0 on platforms that lack " +"\"maintenance_io_concurrency\" must be set to 0 on platforms that lack " "posix_fadvise()." msgstr "" -"Значение maintenance_io_concurrency должно равняться 0 на платформах, где " -"отсутствует lack posix_fadvise()." +"Значение \"maintenance_io_concurrency\" должно равняться 0 на платформах, " +"где отсутствует posix_fadvise()." -#: commands/variable.c:1207 +#: commands/variable.c:1254 #, c-format msgid "SSL is not supported by this build" msgstr "SSL не поддерживается в данной сборке" -#: commands/view.c:84 +#: commands/view.c:79 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "" "не удалось определить правило сортировки для столбца представления \"%s\"" -#: commands/view.c:279 commands/view.c:290 +#: commands/view.c:274 commands/view.c:285 #, c-format msgid "cannot drop columns from view" msgstr "удалять столбцы из представления нельзя" -#: commands/view.c:295 +#: commands/view.c:290 #, c-format msgid "cannot change name of view column \"%s\" to \"%s\"" msgstr "изменить имя столбца \"%s\" на \"%s\" в представлении нельзя" # skip-rule: space-before-ellipsis -#: commands/view.c:298 +#: commands/view.c:293 #, c-format msgid "" "Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead." @@ -14533,40 +15082,40 @@ msgstr "" "Чтобы изменить имя столбца представления, выполните ALTER VIEW ... RENAME " "COLUMN ..." -#: commands/view.c:309 +#: commands/view.c:304 #, c-format msgid "cannot change data type of view column \"%s\" from %s to %s" msgstr "изменить тип столбца представления \"%s\" с %s на %s нельзя" -#: commands/view.c:323 +#: commands/view.c:318 #, c-format msgid "cannot change collation of view column \"%s\" from \"%s\" to \"%s\"" msgstr "" "изменить правило сортировки для столбца представления \"%s\" с \"%s\" на " "\"%s\" нельзя" -#: commands/view.c:392 +#: commands/view.c:387 #, c-format msgid "views must not contain SELECT INTO" msgstr "представления не должны содержать SELECT INTO" -#: commands/view.c:404 +#: commands/view.c:399 #, c-format msgid "views must not contain data-modifying statements in WITH" msgstr "представления не должны содержать операторы, изменяющие данные в WITH" -#: commands/view.c:474 +#: commands/view.c:469 #, c-format msgid "CREATE VIEW specifies more column names than columns" msgstr "в CREATE VIEW указано больше имён столбцов, чем самих столбцов" -#: commands/view.c:482 +#: commands/view.c:477 #, c-format msgid "views cannot be unlogged because they do not have storage" msgstr "" "представления не могут быть нежурналируемыми, так как они нигде не хранятся" -#: commands/view.c:496 +#: commands/view.c:491 #, c-format msgid "view \"%s\" will be a temporary view" msgstr "представление \"%s\" будет создано как временное" @@ -14604,7 +15153,7 @@ msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "" "для курсора \"%s\" не выполняется обновляемое сканирование таблицы \"%s\"" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2498 +#: executor/execCurrent.c:280 executor/execExprInterp.c:2555 #, c-format msgid "" "type of parameter %d (%s) does not match that when preparing the plan (%s)" @@ -14612,56 +15161,56 @@ msgstr "" "тип параметра %d (%s) не соответствует тому, с которым подготавливался план " "(%s)" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2510 +#: executor/execCurrent.c:292 executor/execExprInterp.c:2567 #, c-format msgid "no value found for parameter %d" msgstr "не найдено значение параметра %d" -#: executor/execExpr.c:637 executor/execExpr.c:644 executor/execExpr.c:650 -#: executor/execExprInterp.c:4234 executor/execExprInterp.c:4251 -#: executor/execExprInterp.c:4350 executor/nodeModifyTable.c:197 -#: executor/nodeModifyTable.c:208 executor/nodeModifyTable.c:225 -#: executor/nodeModifyTable.c:233 +#: executor/execExpr.c:642 executor/execExpr.c:649 executor/execExpr.c:655 +#: executor/execExprInterp.c:4852 executor/execExprInterp.c:4869 +#: executor/execExprInterp.c:4968 executor/nodeModifyTable.c:203 +#: executor/nodeModifyTable.c:214 executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:239 #, c-format msgid "table row type and query-specified row type do not match" msgstr "тип строки таблицы отличается от типа строки-результата запроса" -#: executor/execExpr.c:638 executor/nodeModifyTable.c:198 +#: executor/execExpr.c:643 executor/nodeModifyTable.c:204 #, c-format msgid "Query has too many columns." msgstr "Запрос возвращает больше столбцов." -#: executor/execExpr.c:645 executor/nodeModifyTable.c:226 +#: executor/execExpr.c:650 executor/nodeModifyTable.c:232 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "" "Запрос выдаёт значение для удалённого столбца (с порядковым номером %d)." -#: executor/execExpr.c:651 executor/execExprInterp.c:4252 -#: executor/nodeModifyTable.c:209 +#: executor/execExpr.c:656 executor/execExprInterp.c:4870 +#: executor/nodeModifyTable.c:215 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "" "В таблице определён тип %s (номер столбца: %d), а в запросе предполагается " "%s." -#: executor/execExpr.c:1099 parser/parse_agg.c:838 +#: executor/execExpr.c:1104 parser/parse_agg.c:838 #, c-format msgid "window function calls cannot be nested" msgstr "вложенные вызовы оконных функций недопустимы" -#: executor/execExpr.c:1618 +#: executor/execExpr.c:1649 #, c-format msgid "target type is not an array" msgstr "целевой тип не является массивом" -#: executor/execExpr.c:1958 +#: executor/execExpr.c:1989 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "столбец ROW() имеет тип %s, а должен - %s" -#: executor/execExpr.c:2574 executor/execSRF.c:719 parser/parse_func.c:138 -#: parser/parse_func.c:655 parser/parse_func.c:1032 +#: executor/execExpr.c:2653 executor/execSRF.c:718 parser/parse_func.c:138 +#: parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" @@ -14669,60 +15218,60 @@ msgstr[0] "функции нельзя передать больше %d аргу msgstr[1] "функции нельзя передать больше %d аргументов" msgstr[2] "функции нельзя передать больше %d аргументов" -#: executor/execExpr.c:2601 executor/execSRF.c:739 executor/functions.c:1067 -#: utils/adt/jsonfuncs.c:3780 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2680 executor/execSRF.c:738 executor/functions.c:1068 +#: utils/adt/jsonfuncs.c:4054 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "" "функция, возвращающая множество, вызвана в контексте, где ему нет места" -#: executor/execExpr.c:3007 parser/parse_node.c:277 parser/parse_node.c:327 +#: executor/execExpr.c:3086 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "" "к элементам типа %s нельзя обращаться по индексам, так как он это не " "поддерживает" -#: executor/execExpr.c:3135 executor/execExpr.c:3157 +#: executor/execExpr.c:3214 executor/execExpr.c:3236 #, c-format msgid "type %s does not support subscripted assignment" msgstr "тип %s не поддерживает изменение элемента по индексу" -#: executor/execExprInterp.c:1962 +#: executor/execExprInterp.c:2019 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "атрибут %d типа %s был удалён" -#: executor/execExprInterp.c:1968 +#: executor/execExprInterp.c:2025 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "атрибут %d типа %s имеет неправильный тип" -#: executor/execExprInterp.c:1970 executor/execExprInterp.c:3104 -#: executor/execExprInterp.c:3150 +#: executor/execExprInterp.c:2027 executor/execExprInterp.c:3226 +#: executor/execExprInterp.c:3272 #, c-format msgid "Table has type %s, but query expects %s." msgstr "В таблице задан тип %s, а в запросе ожидается %s." -#: executor/execExprInterp.c:2050 utils/adt/expandedrecord.c:99 -#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1749 -#: utils/cache/typcache.c:1908 utils/cache/typcache.c:2055 +#: executor/execExprInterp.c:2107 utils/adt/expandedrecord.c:99 +#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 +#: utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 #: utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "тип %s не является составным" -#: executor/execExprInterp.c:2588 +#: executor/execExprInterp.c:2710 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "WHERE CURRENT OF для таблиц такого типа не поддерживается" -#: executor/execExprInterp.c:2801 +#: executor/execExprInterp.c:2923 #, c-format msgid "cannot merge incompatible arrays" msgstr "не удалось объединить несовместимые массивы" -#: executor/execExprInterp.c:2802 +#: executor/execExprInterp.c:2924 #, c-format msgid "" "Array with element type %s cannot be included in ARRAY construct with " @@ -14731,16 +15280,15 @@ msgstr "" "Массив с типом элементов %s нельзя включить в конструкцию ARRAY с типом " "элементов %s." -#: executor/execExprInterp.c:2823 utils/adt/arrayfuncs.c:266 -#: utils/adt/arrayfuncs.c:576 utils/adt/arrayfuncs.c:1330 -#: utils/adt/arrayfuncs.c:3532 utils/adt/arrayfuncs.c:5616 -#: utils/adt/arrayfuncs.c:6133 utils/adt/arraysubs.c:150 +#: executor/execExprInterp.c:2945 utils/adt/arrayfuncs.c:1305 +#: utils/adt/arrayfuncs.c:3503 utils/adt/arrayfuncs.c:5593 +#: utils/adt/arrayfuncs.c:6110 utils/adt/arraysubs.c:150 #: utils/adt/arraysubs.c:488 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "число размерностей массива (%d) превышает предел (%d)" -#: executor/execExprInterp.c:2843 executor/execExprInterp.c:2878 +#: executor/execExprInterp.c:2965 executor/execExprInterp.c:3000 #, c-format msgid "" "multidimensional arrays must have array expressions with matching dimensions" @@ -14748,35 +15296,53 @@ msgstr "" "для многомерных массивов должны задаваться выражения с соответствующими " "размерностями" -#: executor/execExprInterp.c:2855 utils/adt/array_expanded.c:274 -#: utils/adt/arrayfuncs.c:960 utils/adt/arrayfuncs.c:1569 -#: utils/adt/arrayfuncs.c:2377 utils/adt/arrayfuncs.c:2392 -#: utils/adt/arrayfuncs.c:2654 utils/adt/arrayfuncs.c:2670 -#: utils/adt/arrayfuncs.c:2978 utils/adt/arrayfuncs.c:2993 -#: utils/adt/arrayfuncs.c:3334 utils/adt/arrayfuncs.c:3562 -#: utils/adt/arrayfuncs.c:6225 utils/adt/arrayfuncs.c:6566 -#: utils/adt/arrayutils.c:98 utils/adt/arrayutils.c:107 -#: utils/adt/arrayutils.c:114 +#: executor/execExprInterp.c:2977 utils/adt/array_expanded.c:274 +#: utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 +#: utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 +#: utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 +#: utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 +#: utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 +#: utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 +#: utils/adt/arrayfuncs.c:3533 utils/adt/arrayfuncs.c:5365 +#: utils/adt/arrayfuncs.c:6202 utils/adt/arrayfuncs.c:6546 +#: utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 +#: utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "размер массива превышает предел (%d)" -#: executor/execExprInterp.c:3103 executor/execExprInterp.c:3149 +#: executor/execExprInterp.c:3225 executor/execExprInterp.c:3271 #, c-format msgid "attribute %d has wrong type" msgstr "атрибут %d имеет неверный тип" -#: executor/execExprInterp.c:3735 utils/adt/domains.c:155 +#: executor/execExprInterp.c:3857 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "домен %s не допускает значения null" -#: executor/execExprInterp.c:3750 utils/adt/domains.c:193 +#: executor/execExprInterp.c:3872 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "значение домена %s нарушает ограничение-проверку \"%s\"" -#: executor/execExprInterp.c:4235 +#: executor/execExprInterp.c:4447 +#, c-format +msgid "no SQL/JSON item found for specified path of column \"%s\"" +msgstr "по заданному для столбца \"%s\" пути не найден элемент SQL/JSON" + +#: executor/execExprInterp.c:4452 +#, c-format +msgid "no SQL/JSON item found for specified path" +msgstr "по заданному пути не найден элемент SQL/JSON" + +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:4652 executor/execExprInterp.c:4660 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "привести выражение %s (%s) к типу RETURNING не удалось" + +#: executor/execExprInterp.c:4853 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." @@ -14784,14 +15350,14 @@ msgstr[0] "Строка таблицы содержит %d атрибут, а в msgstr[1] "Строка таблицы содержит %d атрибута, а в запросе ожидается %d." msgstr[2] "Строка таблицы содержит %d атрибутов, а в запросе ожидается %d." -#: executor/execExprInterp.c:4351 executor/execSRF.c:978 +#: executor/execExprInterp.c:4969 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "" "Несоответствие параметров физического хранения удалённого атрибута (под " "номером %d)." -#: executor/execIndexing.c:588 +#: executor/execIndexing.c:593 #, c-format msgid "" "ON CONFLICT does not support deferrable unique constraints/exclusion " @@ -14800,32 +15366,32 @@ msgstr "" "ON CONFLICT не поддерживает откладываемые ограничения уникальности/" "ограничения-исключения в качестве определяющего индекса" -#: executor/execIndexing.c:865 +#: executor/execIndexing.c:870 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "не удалось создать ограничение-исключение \"%s\"" -#: executor/execIndexing.c:868 +#: executor/execIndexing.c:873 #, c-format msgid "Key %s conflicts with key %s." msgstr "Ключ %s конфликтует с ключом %s." -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:875 #, c-format msgid "Key conflicts exist." msgstr "Обнаружен конфликт ключей." -#: executor/execIndexing.c:876 +#: executor/execIndexing.c:881 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "конфликтующее значение ключа нарушает ограничение-исключение \"%s\"" -#: executor/execIndexing.c:879 +#: executor/execIndexing.c:884 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "Ключ %s конфликтует с существующим ключом %s." -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:886 #, c-format msgid "Key conflicts with existing key." msgstr "Ключ конфликтует с уже существующим." @@ -14840,167 +15406,119 @@ msgstr "последовательность \"%s\" изменить нельз msgid "cannot change TOAST relation \"%s\"" msgstr "TOAST-отношение \"%s\" изменить нельзя" -#: executor/execMain.c:1063 rewrite/rewriteHandler.c:3079 -#: rewrite/rewriteHandler.c:3966 -#, c-format -msgid "cannot insert into view \"%s\"" -msgstr "вставить данные в представление \"%s\" нельзя" - -#: executor/execMain.c:1065 rewrite/rewriteHandler.c:3082 -#: rewrite/rewriteHandler.c:3969 -#, c-format -msgid "" -"To enable inserting into the view, provide an INSTEAD OF INSERT trigger or " -"an unconditional ON INSERT DO INSTEAD rule." -msgstr "" -"Чтобы представление допускало добавление данных, установите триггер INSTEAD " -"OF INSERT или безусловное правило ON INSERT DO INSTEAD." - -#: executor/execMain.c:1071 rewrite/rewriteHandler.c:3087 -#: rewrite/rewriteHandler.c:3974 -#, c-format -msgid "cannot update view \"%s\"" -msgstr "изменить данные в представлении \"%s\" нельзя" - -#: executor/execMain.c:1073 rewrite/rewriteHandler.c:3090 -#: rewrite/rewriteHandler.c:3977 -#, c-format -msgid "" -"To enable updating the view, provide an INSTEAD OF UPDATE trigger or an " -"unconditional ON UPDATE DO INSTEAD rule." -msgstr "" -"Чтобы представление допускало изменение данных, установите триггер INSTEAD " -"OF UPDATE или безусловное правило ON UPDATE DO INSTEAD." - -#: executor/execMain.c:1079 rewrite/rewriteHandler.c:3095 -#: rewrite/rewriteHandler.c:3982 -#, c-format -msgid "cannot delete from view \"%s\"" -msgstr "удалить данные из представления \"%s\" нельзя" - -#: executor/execMain.c:1081 rewrite/rewriteHandler.c:3098 -#: rewrite/rewriteHandler.c:3985 -#, c-format -msgid "" -"To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an " -"unconditional ON DELETE DO INSTEAD rule." -msgstr "" -"Чтобы представление допускало удаление данных, установите триггер INSTEAD OF " -"DELETE или безусловное правило ON DELETE DO INSTEAD." - -#: executor/execMain.c:1092 +#: executor/execMain.c:1064 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "изменить материализованное представление \"%s\" нельзя" -#: executor/execMain.c:1104 +#: executor/execMain.c:1076 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "вставлять данные в стороннюю таблицу \"%s\" нельзя" -#: executor/execMain.c:1110 +#: executor/execMain.c:1082 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "сторонняя таблица \"%s\" не допускает добавления" -#: executor/execMain.c:1117 +#: executor/execMain.c:1089 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "изменять данные в сторонней таблице \"%s\"" -#: executor/execMain.c:1123 +#: executor/execMain.c:1095 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "сторонняя таблица \"%s\" не допускает изменения" -#: executor/execMain.c:1130 +#: executor/execMain.c:1102 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "удалять данные из сторонней таблицы \"%s\" нельзя" -#: executor/execMain.c:1136 +#: executor/execMain.c:1108 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "сторонняя таблица \"%s\" не допускает удаления" -#: executor/execMain.c:1147 +#: executor/execMain.c:1119 #, c-format msgid "cannot change relation \"%s\"" msgstr "отношение \"%s\" изменить нельзя" -#: executor/execMain.c:1174 +#: executor/execMain.c:1146 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "блокировать строки в последовательности \"%s\" нельзя" -#: executor/execMain.c:1181 +#: executor/execMain.c:1153 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "блокировать строки в TOAST-отношении \"%s\" нельзя" -#: executor/execMain.c:1188 +#: executor/execMain.c:1160 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "блокировать строки в представлении \"%s\" нельзя" -#: executor/execMain.c:1196 +#: executor/execMain.c:1168 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "блокировать строки в материализованном представлении \"%s\" нельзя" -#: executor/execMain.c:1205 executor/execMain.c:2708 +#: executor/execMain.c:1177 executor/execMain.c:2687 #: executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "блокировать строки в сторонней таблице \"%s\" нельзя" -#: executor/execMain.c:1211 +#: executor/execMain.c:1183 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "блокировать строки в отношении \"%s\" нельзя" -#: executor/execMain.c:1922 +#: executor/execMain.c:1901 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "новая строка в отношении \"%s\" нарушает ограничение секции" -#: executor/execMain.c:1924 executor/execMain.c:2008 executor/execMain.c:2059 -#: executor/execMain.c:2169 +#: executor/execMain.c:1903 executor/execMain.c:1987 executor/execMain.c:2038 +#: executor/execMain.c:2148 #, c-format msgid "Failing row contains %s." msgstr "Ошибочная строка содержит %s." -#: executor/execMain.c:2005 +#: executor/execMain.c:1984 #, c-format msgid "" "null value in column \"%s\" of relation \"%s\" violates not-null constraint" msgstr "" "значение NULL в столбце \"%s\" отношения \"%s\" нарушает ограничение NOT NULL" -#: executor/execMain.c:2057 +#: executor/execMain.c:2036 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "новая строка в отношении \"%s\" нарушает ограничение-проверку \"%s\"" -#: executor/execMain.c:2167 +#: executor/execMain.c:2146 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "новая строка нарушает ограничение-проверку для представления \"%s\"" -#: executor/execMain.c:2177 +#: executor/execMain.c:2156 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "" "новая строка нарушает политику защиты на уровне строк \"%s\" для таблицы " "\"%s\"" -#: executor/execMain.c:2182 +#: executor/execMain.c:2161 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "" "новая строка нарушает политику защиты на уровне строк для таблицы \"%s\"" -#: executor/execMain.c:2190 +#: executor/execMain.c:2169 #, c-format msgid "" "target row violates row-level security policy \"%s\" (USING expression) for " @@ -15009,7 +15527,7 @@ msgstr "" "целевая строка нарушает политику защиты на уровне строк \"%s\" (выражение " "USING) для таблицы \"%s\"" -#: executor/execMain.c:2195 +#: executor/execMain.c:2174 #, c-format msgid "" "target row violates row-level security policy (USING expression) for table " @@ -15018,7 +15536,7 @@ msgstr "" "новая строка нарушает политику защиты на уровне строк (выражение USING) для " "таблицы \"%s\"" -#: executor/execMain.c:2202 +#: executor/execMain.c:2181 #, c-format msgid "" "new row violates row-level security policy \"%s\" (USING expression) for " @@ -15027,7 +15545,7 @@ msgstr "" "новая строка нарушает политику защиты на уровне строк \"%s\" (выражение " "USING) для таблицы \"%s\"" -#: executor/execMain.c:2207 +#: executor/execMain.c:2186 #, c-format msgid "" "new row violates row-level security policy (USING expression) for table " @@ -15036,17 +15554,17 @@ msgstr "" "новая строка нарушает политику защиты на уровне строк (выражение USING) для " "таблицы \"%s\"" -#: executor/execPartition.c:330 +#: executor/execPartition.c:327 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "для строки не найдена секция в отношении \"%s\"" -#: executor/execPartition.c:333 +#: executor/execPartition.c:330 #, c-format msgid "Partition key of the failing row contains %s." msgstr "Ключ секционирования для неподходящей строки содержит %s." -#: executor/execReplication.c:231 executor/execReplication.c:415 +#: executor/execReplication.c:272 executor/execReplication.c:456 #, c-format msgid "" "tuple to be locked was already moved to another partition due to concurrent " @@ -15055,31 +15573,31 @@ msgstr "" "кортеж, подлежащий блокировке, был перемещён в другую секцию в результате " "параллельного изменения; следует повторная попытка" -#: executor/execReplication.c:235 executor/execReplication.c:419 +#: executor/execReplication.c:276 executor/execReplication.c:460 #, c-format msgid "concurrent update, retrying" msgstr "параллельное изменение; следует повторная попытка" -#: executor/execReplication.c:241 executor/execReplication.c:425 +#: executor/execReplication.c:282 executor/execReplication.c:466 #, c-format msgid "concurrent delete, retrying" msgstr "параллельное удаление; следует повторная попытка" -#: executor/execReplication.c:311 parser/parse_cte.c:308 -#: parser/parse_oper.c:233 utils/adt/array_userfuncs.c:1348 -#: utils/adt/array_userfuncs.c:1491 utils/adt/arrayfuncs.c:3881 -#: utils/adt/arrayfuncs.c:4436 utils/adt/arrayfuncs.c:6446 -#: utils/adt/rowtypes.c:1230 +#: executor/execReplication.c:352 parser/parse_cte.c:302 +#: parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 +#: utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3852 +#: utils/adt/arrayfuncs.c:4407 utils/adt/arrayfuncs.c:6426 +#: utils/adt/rowtypes.c:1220 #, c-format msgid "could not identify an equality operator for type %s" msgstr "не удалось найти оператор равенства для типа %s" -#: executor/execReplication.c:642 executor/execReplication.c:648 +#: executor/execReplication.c:687 executor/execReplication.c:693 #, c-format msgid "cannot update table \"%s\"" msgstr "изменять данные в таблице \"%s\" нельзя" -#: executor/execReplication.c:644 executor/execReplication.c:656 +#: executor/execReplication.c:689 executor/execReplication.c:701 #, c-format msgid "" "Column used in the publication WHERE expression is not part of the replica " @@ -15088,7 +15606,7 @@ msgstr "" "Столбец, фигурирующий в выражении WHERE публикации, не входит в " "идентификатор реплики." -#: executor/execReplication.c:650 executor/execReplication.c:662 +#: executor/execReplication.c:695 executor/execReplication.c:707 #, c-format msgid "" "Column list used by the publication does not cover the replica identity." @@ -15096,12 +15614,12 @@ msgstr "" "Список столбцов, используемых в публикации, не покрывает идентификатор " "реплики." -#: executor/execReplication.c:654 executor/execReplication.c:660 +#: executor/execReplication.c:699 executor/execReplication.c:705 #, c-format msgid "cannot delete from table \"%s\"" msgstr "удалять данные из таблицы \"%s\" нельзя" -#: executor/execReplication.c:680 +#: executor/execReplication.c:725 #, c-format msgid "" "cannot update table \"%s\" because it does not have a replica identity and " @@ -15110,14 +15628,14 @@ msgstr "" "изменение в таблице \"%s\" невозможно, так как в ней отсутствует " "идентификатор реплики, но она публикует изменения" -#: executor/execReplication.c:682 +#: executor/execReplication.c:727 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "" "Чтобы эта таблица поддерживала изменение, установите REPLICA IDENTITY, " "выполнив ALTER TABLE." -#: executor/execReplication.c:686 +#: executor/execReplication.c:731 #, c-format msgid "" "cannot delete from table \"%s\" because it does not have a replica identity " @@ -15126,7 +15644,7 @@ msgstr "" "удаление из таблицы \"%s\" невозможно, так как в ней отсутствует " "идентификатор реплики, но она публикует удаления" -#: executor/execReplication.c:688 +#: executor/execReplication.c:733 #, c-format msgid "" "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." @@ -15134,34 +15652,34 @@ msgstr "" "Чтобы эта таблица поддерживала удаление, установите REPLICA IDENTITY, " "выполнив ALTER TABLE." -#: executor/execReplication.c:704 +#: executor/execReplication.c:749 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "" "в качестве целевого отношения для логической репликации нельзя использовать " "\"%s.%s\"" -#: executor/execSRF.c:316 +#: executor/execSRF.c:315 #, c-format msgid "rows returned by function are not all of the same row type" msgstr "строки, возвращённые функцией, имеют разные типы" -#: executor/execSRF.c:366 +#: executor/execSRF.c:365 #, c-format msgid "table-function protocol for value-per-call mode was not followed" msgstr "нарушение протокола табличной функции в режиме вызов-значение" -#: executor/execSRF.c:374 executor/execSRF.c:668 +#: executor/execSRF.c:373 executor/execSRF.c:667 #, c-format msgid "table-function protocol for materialize mode was not followed" msgstr "нарушение протокола табличной функции в режиме материализации" -#: executor/execSRF.c:381 executor/execSRF.c:686 +#: executor/execSRF.c:380 executor/execSRF.c:685 #, c-format msgid "unrecognized table-function returnMode: %d" msgstr "нераспознанный режим возврата табличной функции: %d" -#: executor/execSRF.c:895 +#: executor/execSRF.c:894 #, c-format msgid "" "function returning setof record called in context that cannot accept type " @@ -15170,12 +15688,12 @@ msgstr "" "функция, возвращающая запись SET OF, вызвана в контексте, не допускающем " "этот тип" -#: executor/execSRF.c:951 executor/execSRF.c:967 executor/execSRF.c:977 +#: executor/execSRF.c:950 executor/execSRF.c:966 executor/execSRF.c:976 #, c-format msgid "function return row and query-specified return row do not match" msgstr "тип результат функции отличается от типа строки-результата запроса" -#: executor/execSRF.c:952 +#: executor/execSRF.c:951 #, c-format msgid "Returned row contains %d attribute, but query expects %d." msgid_plural "Returned row contains %d attributes, but query expects %d." @@ -15185,23 +15703,33 @@ msgstr[1] "" msgstr[2] "" "Возвращённая строка содержит %d атрибутов, но запрос предполагает %d." -#: executor/execSRF.c:968 +#: executor/execSRF.c:967 #, c-format msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "Возвращён тип %s (номер столбца: %d), а в запросе предполагается %s." -#: executor/execTuples.c:146 executor/execTuples.c:353 -#: executor/execTuples.c:521 executor/execTuples.c:713 +#: executor/execTuples.c:147 executor/execTuples.c:368 +#: executor/execTuples.c:563 executor/execTuples.c:772 #, c-format msgid "cannot retrieve a system column in this context" msgstr "системный столбец нельзя получить в данном контексте" -#: executor/execUtils.c:744 +#: executor/execTuples.c:163 executor/execTuples.c:580 +#, c-format +msgid "don't have transaction information for this type of tuple" +msgstr "для этого типа кортежей транзакционная информация отсутствует" + +#: executor/execTuples.c:390 executor/execTuples.c:794 +#, c-format +msgid "don't have a storage tuple in this context" +msgstr "в данном контексте хранимый кортеж отсутствует" + +#: executor/execUtils.c:713 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "материализованное представление \"%s\" не было наполнено" -#: executor/execUtils.c:746 +#: executor/execUtils.c:715 #, c-format msgid "Use the REFRESH MATERIALIZED VIEW command." msgstr "Примените команду REFRESH MATERIALIZED VIEW." @@ -15211,119 +15739,120 @@ msgstr "Примените команду REFRESH MATERIALIZED VIEW." msgid "could not determine actual type of argument declared %s" msgstr "не удалось определить фактический тип аргумента, объявленного как %s" -#: executor/functions.c:512 +#: executor/functions.c:513 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "в функции SQL нельзя выполнить COPY с участием клиента" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:519 #, c-format msgid "%s is not allowed in an SQL function" msgstr "%s нельзя использовать в SQL-функции" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1742 executor/spi.c:2635 +#: executor/functions.c:527 executor/spi.c:1744 executor/spi.c:2657 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "%s нельзя использовать в не изменчивой (volatile) функции" -#: executor/functions.c:1451 +#: executor/functions.c:1452 #, c-format msgid "SQL function \"%s\" statement %d" msgstr "SQL-функция \"%s\", оператор %d" -#: executor/functions.c:1477 +#: executor/functions.c:1478 #, c-format msgid "SQL function \"%s\" during startup" msgstr "SQL-функция \"%s\" (при старте)" -#: executor/functions.c:1562 +#: executor/functions.c:1563 #, c-format msgid "" "calling procedures with output arguments is not supported in SQL functions" msgstr "" "вызов процедур с выходными аргументами в функциях SQL не поддерживается" -#: executor/functions.c:1710 executor/functions.c:1748 -#: executor/functions.c:1762 executor/functions.c:1857 -#: executor/functions.c:1890 executor/functions.c:1904 +#: executor/functions.c:1698 executor/functions.c:1736 +#: executor/functions.c:1750 executor/functions.c:1845 +#: executor/functions.c:1878 executor/functions.c:1892 #, c-format msgid "return type mismatch in function declared to return %s" msgstr "несовпадение типа возврата в функции (в объявлении указан тип %s)" -#: executor/functions.c:1712 +#: executor/functions.c:1700 #, c-format msgid "" -"Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING." -msgstr "" -"Последним оператором в функции должен быть SELECT или INSERT/UPDATE/DELETE " +"Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE " "RETURNING." +msgstr "" +"Последним оператором в функции должен быть SELECT или INSERT/UPDATE/DELETE/" +"MERGE RETURNING." -#: executor/functions.c:1750 +#: executor/functions.c:1738 #, c-format msgid "Final statement must return exactly one column." msgstr "Последний оператор должен возвращать один столбец." -#: executor/functions.c:1764 +#: executor/functions.c:1752 #, c-format msgid "Actual return type is %s." msgstr "Фактический тип возврата: %s." -#: executor/functions.c:1859 +#: executor/functions.c:1847 #, c-format msgid "Final statement returns too many columns." msgstr "Последний оператор возвращает слишком много столбцов." -#: executor/functions.c:1892 +#: executor/functions.c:1880 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "Последний оператор возвращает %s вместо %s для столбца %d." -#: executor/functions.c:1906 +#: executor/functions.c:1894 #, c-format msgid "Final statement returns too few columns." msgstr "Последний оператор возвращает слишком мало столбцов." -#: executor/functions.c:1934 +#: executor/functions.c:1922 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "для SQL-функций тип возврата %s не поддерживается" -#: executor/nodeAgg.c:3937 executor/nodeWindowAgg.c:2993 +#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2975 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "" "агрегатная функция %u должна иметь совместимые входной и переходный типы" -#: executor/nodeAgg.c:3967 parser/parse_agg.c:680 parser/parse_agg.c:708 +#: executor/nodeAgg.c:3966 parser/parse_agg.c:680 parser/parse_agg.c:708 #, c-format msgid "aggregate function calls cannot be nested" msgstr "вложенные вызовы агрегатных функций недопустимы" -#: executor/nodeCustom.c:154 executor/nodeCustom.c:165 +#: executor/nodeCustom.c:144 executor/nodeCustom.c:155 #, c-format msgid "custom scan \"%s\" does not support MarkPos" msgstr "нестандартное сканирование \"%s\" не поддерживает MarkPos" -#: executor/nodeHashjoin.c:1143 executor/nodeHashjoin.c:1173 +#: executor/nodeHashjoin.c:1131 executor/nodeHashjoin.c:1161 #, c-format msgid "could not rewind hash-join temporary file" msgstr "не удалось переместиться во временном файле хеш-соединения" -#: executor/nodeIndexonlyscan.c:240 +#: executor/nodeIndexonlyscan.c:239 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "" "функции неточного расстояния не поддерживаются в сканировании только по " "индексу" -#: executor/nodeLimit.c:374 +#: executor/nodeLimit.c:373 #, c-format msgid "OFFSET must not be negative" msgstr "OFFSET не может быть отрицательным" -#: executor/nodeLimit.c:400 +#: executor/nodeLimit.c:399 #, c-format msgid "LIMIT must not be negative" msgstr "LIMIT не может быть отрицательным" @@ -15341,12 +15870,12 @@ msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "" "FULL JOIN поддерживается только с условиями, допускающими соединение слиянием" -#: executor/nodeModifyTable.c:234 +#: executor/nodeModifyTable.c:240 #, c-format msgid "Query has too few columns." msgstr "Запрос возвращает меньше столбцов." -#: executor/nodeModifyTable.c:1534 executor/nodeModifyTable.c:1608 +#: executor/nodeModifyTable.c:1540 executor/nodeModifyTable.c:1614 #, c-format msgid "" "tuple to be deleted was already modified by an operation triggered by the " @@ -15355,12 +15884,12 @@ msgstr "" "кортеж, который должен быть удалён, уже модифицирован в операции, вызванной " "текущей командой" -#: executor/nodeModifyTable.c:1763 +#: executor/nodeModifyTable.c:1769 #, c-format msgid "invalid ON UPDATE specification" msgstr "неверное указание ON UPDATE" -#: executor/nodeModifyTable.c:1764 +#: executor/nodeModifyTable.c:1770 #, c-format msgid "" "The result tuple would appear in a different partition than the original " @@ -15369,7 +15898,7 @@ msgstr "" "Результирующий кортеж окажется перемещённым из секции исходного кортежа в " "другую." -#: executor/nodeModifyTable.c:2223 +#: executor/nodeModifyTable.c:2226 #, c-format msgid "" "cannot move tuple across partitions when a non-root ancestor of the source " @@ -15378,26 +15907,26 @@ msgstr "" "нельзя переместить кортеж между секциями, когда внешний ключ непосредственно " "ссылается на предка исходной секции, который не является корнем иерархии" -#: executor/nodeModifyTable.c:2224 +#: executor/nodeModifyTable.c:2227 #, c-format msgid "" "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." msgstr "" "Внешний ключ ссылается на предка \"%s\", а не на корневого предка \"%s\"." -#: executor/nodeModifyTable.c:2227 +#: executor/nodeModifyTable.c:2230 #, c-format msgid "Consider defining the foreign key on table \"%s\"." msgstr "Возможно, имеет смысл перенацелить внешний ключ на таблицу \"%s\"." #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2573 executor/nodeModifyTable.c:2996 -#: executor/nodeModifyTable.c:3123 +#: executor/nodeModifyTable.c:2596 executor/nodeModifyTable.c:3138 +#: executor/nodeModifyTable.c:3308 #, c-format msgid "%s command cannot affect row a second time" msgstr "команда %s не может подействовать на строку дважды" -#: executor/nodeModifyTable.c:2575 +#: executor/nodeModifyTable.c:2598 #, c-format msgid "" "Ensure that no rows proposed for insertion within the same command have " @@ -15406,7 +15935,7 @@ msgstr "" "Проверьте, не содержат ли строки, которые должна добавить команда, " "дублирующиеся значения, подпадающие под ограничения." -#: executor/nodeModifyTable.c:2989 executor/nodeModifyTable.c:3116 +#: executor/nodeModifyTable.c:3131 executor/nodeModifyTable.c:3301 #, c-format msgid "" "tuple to be updated or deleted was already modified by an operation " @@ -15415,28 +15944,28 @@ msgstr "" "кортеж, который должен быть изменён или удалён, уже модифицирован в " "операции, вызванной текущей командой" -#: executor/nodeModifyTable.c:2998 executor/nodeModifyTable.c:3125 +#: executor/nodeModifyTable.c:3140 executor/nodeModifyTable.c:3310 #, c-format msgid "Ensure that not more than one source row matches any one target row." msgstr "" "Проверьте, не может ли какой-либо целевой строке соответствовать более одной " "исходной строки." -#: executor/nodeModifyTable.c:3080 +#: executor/nodeModifyTable.c:3209 #, c-format msgid "" -"tuple to be deleted was already moved to another partition due to concurrent " +"tuple to be merged was already moved to another partition due to concurrent " "update" msgstr "" -"кортеж, подлежащий удалению, был перемещён в другую секцию в результате " +"кортеж, подлежащий объединению, был перемещён в другую секцию в результате " "параллельного изменения" -#: executor/nodeSamplescan.c:260 +#: executor/nodeSamplescan.c:244 #, c-format msgid "TABLESAMPLE parameter cannot be null" msgstr "параметр TABLESAMPLE не может быть NULL" -#: executor/nodeSamplescan.c:272 +#: executor/nodeSamplescan.c:256 #, c-format msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "параметр TABLESAMPLE REPEATABLE не может быть NULL" @@ -15447,7 +15976,7 @@ msgstr "параметр TABLESAMPLE REPEATABLE не может быть NULL" msgid "more than one row returned by a subquery used as an expression" msgstr "подзапрос в выражении вернул больше одной строки" -#: executor/nodeTableFuncscan.c:375 +#: executor/nodeTableFuncscan.c:370 #, c-format msgid "namespace URI must not be null" msgstr "URI пространства имён должен быть не NULL" @@ -15457,17 +15986,17 @@ msgstr "URI пространства имён должен быть не NULL" msgid "row filter expression must not be null" msgstr "выражение отбора строк должно быть не NULL" -#: executor/nodeTableFuncscan.c:415 +#: executor/nodeTableFuncscan.c:416 #, c-format msgid "column filter expression must not be null" msgstr "выражение отбора столбца должно быть не NULL" -#: executor/nodeTableFuncscan.c:416 +#: executor/nodeTableFuncscan.c:417 #, c-format msgid "Filter for column \"%s\" is null." msgstr "Для столбца \"%s\" задано выражение NULL." -#: executor/nodeTableFuncscan.c:506 +#: executor/nodeTableFuncscan.c:507 #, c-format msgid "null is not allowed in column \"%s\"" msgstr "в столбце \"%s\" не допускается NULL" @@ -15497,86 +16026,86 @@ msgstr "смещение конца рамки не может быть NULL" msgid "frame ending offset must not be negative" msgstr "смещение конца рамки не может быть отрицательным" -#: executor/nodeWindowAgg.c:2909 +#: executor/nodeWindowAgg.c:2891 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "" "агрегатная функция %s не поддерживает использование в качестве оконной " "функции" -#: executor/spi.c:242 executor/spi.c:342 +#: executor/spi.c:241 executor/spi.c:341 #, c-format msgid "invalid transaction termination" msgstr "неверное завершение транзакции" -#: executor/spi.c:257 +#: executor/spi.c:256 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "фиксировать транзакцию при наличии активных подтранзакций нельзя" -#: executor/spi.c:348 +#: executor/spi.c:347 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "откатить транзакцию при наличии активных подтранзакций нельзя" -#: executor/spi.c:472 +#: executor/spi.c:471 #, c-format msgid "transaction left non-empty SPI stack" msgstr "после транзакции остался непустой стек SPI" -#: executor/spi.c:473 executor/spi.c:533 +#: executor/spi.c:472 executor/spi.c:532 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "Проверьте наличие вызова \"SPI_finish\"." -#: executor/spi.c:532 +#: executor/spi.c:531 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "после подтранзакции остался непустой стек SPI" -#: executor/spi.c:1600 +#: executor/spi.c:1602 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "не удалось открыть план нескольких запросов как курсор" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1610 +#: executor/spi.c:1612 #, c-format msgid "cannot open %s query as cursor" msgstr "не удалось открыть запрос %s как курсор" -#: executor/spi.c:1716 +#: executor/spi.c:1718 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE не поддерживается" -#: executor/spi.c:1717 parser/analyze.c:2923 +#: executor/spi.c:1719 parser/analyze.c:2928 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "Прокручиваемые курсоры должны быть READ ONLY." -#: executor/spi.c:2474 +#: executor/spi.c:2496 #, c-format msgid "empty query does not return tuples" msgstr "пустой запрос не возвращает кортежи" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2548 +#: executor/spi.c:2570 #, c-format msgid "%s query does not return tuples" msgstr "запрос %s не возвращает кортежи" -#: executor/spi.c:2963 +#: executor/spi.c:2987 #, c-format msgid "SQL expression \"%s\"" msgstr "SQL-выражение \"%s\"" -#: executor/spi.c:2968 +#: executor/spi.c:2992 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "присваивание PL/pgSQL \"%s\"" -#: executor/spi.c:2971 +#: executor/spi.c:2995 #, c-format msgid "SQL statement \"%s\"" msgstr "SQL-оператор: \"%s\"" @@ -15586,28 +16115,34 @@ msgstr "SQL-оператор: \"%s\"" msgid "could not send tuple to shared-memory queue" msgstr "не удалось передать кортеж в очередь в разделяемой памяти" -#: foreign/foreign.c:222 +#: foreign/foreign.c:225 +#, c-format +msgid "user mapping not found for user \"%s\", server \"%s\"" +msgstr "сопоставление для пользователя \"%s\", сервера \"%s\" не найдено" + +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7153 +#: optimizer/util/plancat.c:540 #, c-format -msgid "user mapping not found for \"%s\"" -msgstr "сопоставление пользователя для \"%s\" не найдено" +msgid "access to non-system foreign table is restricted" +msgstr "доступ к несистемным сторонним таблицам ограничен" -#: foreign/foreign.c:647 storage/file/fd.c:3931 +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "неверный параметр \"%s\"" -#: foreign/foreign.c:649 +#: foreign/foreign.c:662 #, c-format msgid "Perhaps you meant the option \"%s\"." msgstr "Возможно, предполагался параметр \"%s\"." -#: foreign/foreign.c:651 +#: foreign/foreign.c:664 #, c-format msgid "There are no valid options in this context." msgstr "В данном контексте недопустимы никакие параметры." -#: lib/dshash.c:254 utils/mmgr/dsa.c:715 utils/mmgr/dsa.c:737 -#: utils/mmgr/dsa.c:818 +#: lib/dshash.c:254 utils/mmgr/dsa.c:708 utils/mmgr/dsa.c:730 +#: utils/mmgr/dsa.c:811 #, c-format msgid "Failed on DSA request of size %zu." msgstr "Ошибка при запросе памяти DSA (%zu Б)." @@ -15617,77 +16152,77 @@ msgstr "Ошибка при запросе памяти DSA (%zu Б)." msgid "expected SASL response, got message type %d" msgstr "ожидался ответ SASL, но получено сообщение %d" -#: libpq/auth-scram.c:270 +#: libpq/auth-scram.c:263 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "клиент выбрал неверный механизм аутентификации SASL" -#: libpq/auth-scram.c:294 libpq/auth-scram.c:543 libpq/auth-scram.c:554 +#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "неверная запись секрета SCRAM для пользователя \"%s\"" -#: libpq/auth-scram.c:305 +#: libpq/auth-scram.c:298 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "Для пользователя \"%s\" нет подходящей записи секрета SCRAM." -#: libpq/auth-scram.c:385 libpq/auth-scram.c:390 libpq/auth-scram.c:744 -#: libpq/auth-scram.c:752 libpq/auth-scram.c:857 libpq/auth-scram.c:870 -#: libpq/auth-scram.c:880 libpq/auth-scram.c:988 libpq/auth-scram.c:995 -#: libpq/auth-scram.c:1010 libpq/auth-scram.c:1025 libpq/auth-scram.c:1039 -#: libpq/auth-scram.c:1057 libpq/auth-scram.c:1072 libpq/auth-scram.c:1386 -#: libpq/auth-scram.c:1394 +#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 +#: libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 +#: libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 +#: libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 +#: libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 +#: libpq/auth-scram.c:1387 #, c-format msgid "malformed SCRAM message" msgstr "неправильное сообщение SCRAM" -#: libpq/auth-scram.c:386 +#: libpq/auth-scram.c:379 #, c-format msgid "The message is empty." msgstr "Сообщение пустое." -#: libpq/auth-scram.c:391 +#: libpq/auth-scram.c:384 #, c-format msgid "Message length does not match input length." msgstr "Длина сообщения не соответствует входной длине." -#: libpq/auth-scram.c:423 +#: libpq/auth-scram.c:416 #, c-format msgid "invalid SCRAM response" msgstr "неверный ответ SCRAM" -#: libpq/auth-scram.c:424 +#: libpq/auth-scram.c:417 #, c-format msgid "Nonce does not match." msgstr "Разовый код не совпадает." -#: libpq/auth-scram.c:500 +#: libpq/auth-scram.c:493 #, c-format msgid "could not generate random salt" msgstr "не удалось сгенерировать случайную соль" -#: libpq/auth-scram.c:745 +#: libpq/auth-scram.c:738 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "Ожидался атрибут \"%c\", но обнаружено \"%s\"." -#: libpq/auth-scram.c:753 libpq/auth-scram.c:881 +#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "Ожидался символ \"=\" для атрибута \"%c\"." -#: libpq/auth-scram.c:858 +#: libpq/auth-scram.c:851 #, c-format msgid "Attribute expected, but found end of string." msgstr "Ожидался атрибут, но обнаружен конец строки." -#: libpq/auth-scram.c:871 +#: libpq/auth-scram.c:864 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "Ожидался атрибут, но обнаружен неправильный символ \"%s\"." -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 #, c-format msgid "" "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not " @@ -15696,17 +16231,17 @@ msgstr "" "Клиент выбрал алгоритм SCRAM-SHA-256-PLUS, но в сообщении SCRAM отсутствуют " "данные связывания каналов." -#: libpq/auth-scram.c:996 libpq/auth-scram.c:1026 +#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 #, c-format msgid "Comma expected, but found character \"%s\"." msgstr "Ожидалась запятая, но обнаружен символ \"%s\"." -#: libpq/auth-scram.c:1017 +#: libpq/auth-scram.c:1010 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "Ошибка согласования связывания каналов SCRAM" -#: libpq/auth-scram.c:1018 +#: libpq/auth-scram.c:1011 #, c-format msgid "" "The client supports SCRAM channel binding but thinks the server does not. " @@ -15715,7 +16250,7 @@ msgstr "" "Клиент поддерживает связывание каналов SCRAM, но полагает, что оно не " "поддерживается сервером. Однако сервер тоже поддерживает связывание каналов." -#: libpq/auth-scram.c:1040 +#: libpq/auth-scram.c:1033 #, c-format msgid "" "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM " @@ -15724,155 +16259,155 @@ msgstr "" "Клиент выбрал алгоритм SCRAM-SHA-256 без связывания каналов, но сообщение " "SCRAM содержит данные связывания каналов." -#: libpq/auth-scram.c:1051 +#: libpq/auth-scram.c:1044 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "неподдерживаемый тип связывания каналов SCRAM \"%s\"" -#: libpq/auth-scram.c:1058 +#: libpq/auth-scram.c:1051 #, c-format msgid "Unexpected channel-binding flag \"%s\"." msgstr "Неожиданный флаг связывания каналов \"%s\"." -#: libpq/auth-scram.c:1068 +#: libpq/auth-scram.c:1061 #, c-format msgid "client uses authorization identity, but it is not supported" msgstr "клиент передал идентификатор для авторизации, но это не поддерживается" -#: libpq/auth-scram.c:1073 +#: libpq/auth-scram.c:1066 #, c-format msgid "Unexpected attribute \"%s\" in client-first-message." msgstr "Неожиданный атрибут \"%s\" в первом сообщении клиента." -#: libpq/auth-scram.c:1089 +#: libpq/auth-scram.c:1082 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "клиенту требуется неподдерживаемое расширение SCRAM" -#: libpq/auth-scram.c:1103 +#: libpq/auth-scram.c:1096 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "непечатаемые символы в разовом коде SCRAM" -#: libpq/auth-scram.c:1234 +#: libpq/auth-scram.c:1227 #, c-format msgid "could not generate random nonce" msgstr "не удалось сгенерировать разовый код" -#: libpq/auth-scram.c:1244 +#: libpq/auth-scram.c:1237 #, c-format msgid "could not encode random nonce" msgstr "не удалось оформить разовый код" -#: libpq/auth-scram.c:1350 +#: libpq/auth-scram.c:1343 #, c-format msgid "SCRAM channel binding check failed" msgstr "ошибка проверки связывания каналов SCRAM" -#: libpq/auth-scram.c:1368 +#: libpq/auth-scram.c:1361 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "" "неожиданный атрибут связывания каналов в последнем сообщении клиента SCRAM" -#: libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:1380 #, c-format msgid "Malformed proof in client-final-message." msgstr "Некорректное подтверждение в последнем сообщении клиента." -#: libpq/auth-scram.c:1395 +#: libpq/auth-scram.c:1388 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "Мусор в конце последнего сообщения клиента." -#: libpq/auth.c:271 +#: libpq/auth.c:269 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "" "пользователь \"%s\" не прошёл проверку подлинности: не разрешённый компьютер" -#: libpq/auth.c:274 +#: libpq/auth.c:272 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (\"trust\")" -#: libpq/auth.c:277 +#: libpq/auth.c:275 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (Ident)" -#: libpq/auth.c:280 +#: libpq/auth.c:278 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (Peer)" -#: libpq/auth.c:285 +#: libpq/auth.c:283 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (по паролю)" -#: libpq/auth.c:290 +#: libpq/auth.c:288 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (GSSAPI)" -#: libpq/auth.c:293 +#: libpq/auth.c:291 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (SSPI)" -#: libpq/auth.c:296 +#: libpq/auth.c:294 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (PAM)" -#: libpq/auth.c:299 +#: libpq/auth.c:297 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (BSD)" -#: libpq/auth.c:302 +#: libpq/auth.c:300 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (LDAP)" -#: libpq/auth.c:305 +#: libpq/auth.c:303 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (по сертификату)" -#: libpq/auth.c:308 +#: libpq/auth.c:306 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "пользователь \"%s\" не прошёл проверку подлинности (RADIUS)" -#: libpq/auth.c:311 +#: libpq/auth.c:309 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "" "пользователь \"%s\" не прошёл проверку подлинности: неверный метод проверки" -#: libpq/auth.c:315 +#: libpq/auth.c:313 #, c-format msgid "Connection matched file \"%s\" line %d: \"%s\"" msgstr "Подключение соответствует строке %2$d в \"%1$s\": \"%3$s\"" -#: libpq/auth.c:359 +#: libpq/auth.c:357 #, c-format msgid "authentication identifier set more than once" msgstr "аутентификационный идентификатор указан повторно" -#: libpq/auth.c:360 +#: libpq/auth.c:358 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "предыдущий идентификатор: \"%s\"; новый: \"%s\"" -#: libpq/auth.c:370 +#: libpq/auth.c:368 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "соединение аутентифицировано: идентификатор=\"%s\" метод=%s (%s:%d)" -#: libpq/auth.c:410 +#: libpq/auth.c:408 #, c-format msgid "" "client certificates can only be checked if a root certificate store is " @@ -15881,25 +16416,25 @@ msgstr "" "сертификаты клиентов могут проверяться, только если доступно хранилище " "корневых сертификатов" -#: libpq/auth.c:421 +#: libpq/auth.c:419 #, c-format msgid "connection requires a valid client certificate" msgstr "для подключения требуется годный сертификат клиента" -#: libpq/auth.c:452 libpq/auth.c:498 +#: libpq/auth.c:450 libpq/auth.c:496 msgid "GSS encryption" msgstr "Шифрование GSS" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:453 libpq/auth.c:499 msgid "SSL encryption" msgstr "Шифрование SSL" -#: libpq/auth.c:457 libpq/auth.c:503 +#: libpq/auth.c:455 libpq/auth.c:501 msgid "no encryption" msgstr "без шифрования" #. translator: last %s describes encryption state -#: libpq/auth.c:463 +#: libpq/auth.c:461 #, c-format msgid "" "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" @@ -15908,7 +16443,7 @@ msgstr "" "пользователь \"%s\", \"%s\"" #. translator: last %s describes encryption state -#: libpq/auth.c:470 +#: libpq/auth.c:468 #, c-format msgid "" "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database " @@ -15917,38 +16452,38 @@ msgstr "" "pg_hba.conf отвергает подключение: компьютер \"%s\", пользователь \"%s\", " "база данных \"%s\", %s" -#: libpq/auth.c:508 +#: libpq/auth.c:506 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "" "IP-адрес клиента разрешается в \"%s\", соответствует прямому преобразованию." -#: libpq/auth.c:511 +#: libpq/auth.c:509 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "" "IP-адрес клиента разрешается в \"%s\", прямое преобразование не проверялось." -#: libpq/auth.c:514 +#: libpq/auth.c:512 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "" "IP-адрес клиента разрешается в \"%s\", это не соответствует прямому " "преобразованию." -#: libpq/auth.c:517 +#: libpq/auth.c:515 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "" "Преобразовать имя клиентского компьютера \"%s\" в IP-адрес не удалось: %s." -#: libpq/auth.c:522 +#: libpq/auth.c:520 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "Получить имя компьютера из IP-адреса клиента не удалось: %s." #. translator: last %s describes encryption state -#: libpq/auth.c:530 +#: libpq/auth.c:528 #, c-format msgid "" "no pg_hba.conf entry for replication connection from host \"%s\", user " @@ -15958,245 +16493,242 @@ msgstr "" "компьютера \"%s\" для пользователя \"%s\", %s" #. translator: last %s describes encryption state -#: libpq/auth.c:538 +#: libpq/auth.c:536 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "" "в pg_hba.conf нет записи для компьютера \"%s\", пользователя \"%s\", базы " "\"%s\", %s" -#: libpq/auth.c:711 +#: libpq/auth.c:656 +#, c-format +msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" +msgstr "соединение аутентифицировано: пользователь=\"%s\" метод=%s (%s:%d)" + +#: libpq/auth.c:725 #, c-format msgid "expected password response, got message type %d" msgstr "ожидался ответ с паролем, но получено сообщение %d" -#: libpq/auth.c:732 +#: libpq/auth.c:746 #, c-format msgid "invalid password packet size" msgstr "неверный размер пакета с паролем" -#: libpq/auth.c:750 +#: libpq/auth.c:764 #, c-format msgid "empty password returned by client" msgstr "клиент возвратил пустой пароль" -#: libpq/auth.c:877 libpq/hba.c:1727 -#, c-format -msgid "" -"MD5 authentication is not supported when \"db_user_namespace\" is enabled" -msgstr "" -"проверка подлинности MD5 не поддерживается, когда включён режим " -"\"db_user_namespace\"" - -#: libpq/auth.c:883 +#: libpq/auth.c:892 #, c-format msgid "could not generate random MD5 salt" msgstr "не удалось сгенерировать случайную соль для MD5" -#: libpq/auth.c:934 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 #, c-format msgid "could not set environment: %m" msgstr "не удалось задать переменную окружения: %m" -#: libpq/auth.c:973 +#: libpq/auth.c:982 #, c-format msgid "expected GSS response, got message type %d" msgstr "ожидался ответ GSS, но получено сообщение %d" -#: libpq/auth.c:1039 +#: libpq/auth.c:1048 msgid "accepting GSS security context failed" msgstr "принять контекст безопасности GSS не удалось" -#: libpq/auth.c:1080 +#: libpq/auth.c:1089 msgid "retrieving GSS user name failed" msgstr "получить имя пользователя GSS не удалось" -#: libpq/auth.c:1226 +#: libpq/auth.c:1235 msgid "could not acquire SSPI credentials" msgstr "не удалось получить удостоверение SSPI" -#: libpq/auth.c:1251 +#: libpq/auth.c:1260 #, c-format msgid "expected SSPI response, got message type %d" msgstr "ожидался ответ SSPI, но получено сообщение %d" -#: libpq/auth.c:1329 +#: libpq/auth.c:1338 msgid "could not accept SSPI security context" msgstr "принять контекст безопасности SSPI не удалось" -#: libpq/auth.c:1370 +#: libpq/auth.c:1379 msgid "could not get token from SSPI security context" msgstr "не удалось получить маркер из контекста безопасности SSPI" -#: libpq/auth.c:1506 libpq/auth.c:1525 +#: libpq/auth.c:1515 libpq/auth.c:1534 #, c-format msgid "could not translate name" msgstr "не удалось преобразовать имя" -#: libpq/auth.c:1538 +#: libpq/auth.c:1547 #, c-format msgid "realm name too long" msgstr "имя области слишком длинное" -#: libpq/auth.c:1553 +#: libpq/auth.c:1562 #, c-format msgid "translated account name too long" msgstr "преобразованное имя учётной записи слишком длинное" -#: libpq/auth.c:1732 +#: libpq/auth.c:1741 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "не удалось создать сокет для подключения к серверу Ident: %m" -#: libpq/auth.c:1747 +#: libpq/auth.c:1756 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "не удалось привязаться к локальному адресу \"%s\": %m" -#: libpq/auth.c:1759 +#: libpq/auth.c:1768 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "не удалось подключиться к серверу Ident по адресу \"%s\", порт %s: %m" -#: libpq/auth.c:1781 +#: libpq/auth.c:1790 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "" "не удалось отправить запрос серверу Ident по адресу \"%s\", порт %s: %m" -#: libpq/auth.c:1798 +#: libpq/auth.c:1807 #, c-format msgid "" "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "" "не удалось получить ответ от сервера Ident по адресу \"%s\", порт %s: %m" -#: libpq/auth.c:1808 +#: libpq/auth.c:1817 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "неверно форматированный ответ от сервера Ident: \"%s\"" -#: libpq/auth.c:1861 +#: libpq/auth.c:1870 #, c-format msgid "peer authentication is not supported on this platform" msgstr "проверка подлинности peer в этой ОС не поддерживается" -#: libpq/auth.c:1865 +#: libpq/auth.c:1874 #, c-format msgid "could not get peer credentials: %m" msgstr "не удалось получить данные пользователя через механизм peer: %m" -#: libpq/auth.c:1877 +#: libpq/auth.c:1886 #, c-format msgid "could not look up local user ID %ld: %s" msgstr "найти локального пользователя по идентификатору (%ld) не удалось: %s" -#: libpq/auth.c:1979 +#: libpq/auth.c:1988 #, c-format msgid "error from underlying PAM layer: %s" msgstr "ошибка в нижележащем слое PAM: %s" -#: libpq/auth.c:1990 +#: libpq/auth.c:1999 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "неподдерживаемое сообщение ответа PAM %d/\"%s\"" -#: libpq/auth.c:2047 +#: libpq/auth.c:2056 #, c-format msgid "could not create PAM authenticator: %s" msgstr "не удалось создать аутентификатор PAM: %s" -#: libpq/auth.c:2058 +#: libpq/auth.c:2067 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "ошибка в pam_set_item(PAM_USER): %s" -#: libpq/auth.c:2090 +#: libpq/auth.c:2099 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "ошибка в pam_set_item(PAM_RHOST): %s" -#: libpq/auth.c:2102 +#: libpq/auth.c:2111 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "ошибка в pam_set_item(PAM_CONV): %s" -#: libpq/auth.c:2115 +#: libpq/auth.c:2124 #, c-format msgid "pam_authenticate failed: %s" msgstr "ошибка в pam_authenticate: %s" -#: libpq/auth.c:2128 +#: libpq/auth.c:2137 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "ошибка в pam_acct_mgmt: %s" -#: libpq/auth.c:2139 +#: libpq/auth.c:2148 #, c-format msgid "could not release PAM authenticator: %s" msgstr "не удалось освободить аутентификатор PAM: %s" -#: libpq/auth.c:2219 +#: libpq/auth.c:2228 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "не удалось инициализировать LDAP (код ошибки: %d)" -#: libpq/auth.c:2256 +#: libpq/auth.c:2265 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "не удалось извлечь имя домена из ldapbasedn" -#: libpq/auth.c:2264 +#: libpq/auth.c:2273 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "для аутентификации LDAP не удалось найти записи DNS SRV для \"%s\"" -#: libpq/auth.c:2266 +#: libpq/auth.c:2275 #, c-format msgid "Set an LDAP server name explicitly." msgstr "Задайте имя сервера LDAP явным образом." -#: libpq/auth.c:2318 +#: libpq/auth.c:2327 #, c-format msgid "could not initialize LDAP: %s" msgstr "не удалось инициализировать LDAP: %s" -#: libpq/auth.c:2328 +#: libpq/auth.c:2337 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "протокол ldaps с текущей библиотекой LDAP не поддерживается" -#: libpq/auth.c:2336 +#: libpq/auth.c:2345 #, c-format msgid "could not initialize LDAP: %m" msgstr "не удалось инициализировать LDAP: %m" -#: libpq/auth.c:2346 +#: libpq/auth.c:2355 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "не удалось задать версию протокола LDAP: %s" -#: libpq/auth.c:2362 +#: libpq/auth.c:2371 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "не удалось начать сеанс LDAP TLS: %s" -#: libpq/auth.c:2439 +#: libpq/auth.c:2448 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "LDAP-сервер не задан и значение ldapbasedn не определено" -#: libpq/auth.c:2446 +#: libpq/auth.c:2455 #, c-format msgid "LDAP server not specified" msgstr "LDAP-сервер не определён" -#: libpq/auth.c:2508 +#: libpq/auth.c:2517 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "недопустимый символ в имени пользователя для проверки подлинности LDAP" -#: libpq/auth.c:2525 +#: libpq/auth.c:2534 #, c-format msgid "" "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": " @@ -16205,28 +16737,28 @@ msgstr "" "не удалось выполнить начальную привязку LDAP для ldapbinddn \"%s\" на " "сервере \"%s\": %s" -#: libpq/auth.c:2555 +#: libpq/auth.c:2564 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "" "не удалось выполнить LDAP-поиск по фильтру \"%s\" на сервере \"%s\": %s" -#: libpq/auth.c:2571 +#: libpq/auth.c:2580 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "в LDAP нет пользователя \"%s\"" -#: libpq/auth.c:2572 +#: libpq/auth.c:2581 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "LDAP-поиск по фильтру \"%s\" на сервере \"%s\" не вернул результатов" -#: libpq/auth.c:2576 +#: libpq/auth.c:2585 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "пользователь LDAP \"%s\" не уникален" -#: libpq/auth.c:2577 +#: libpq/auth.c:2586 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "" @@ -16235,7 +16767,7 @@ msgstr[0] "LDAP-поиск по фильтру \"%s\" на сервере \"%s\" msgstr[1] "LDAP-поиск по фильтру \"%s\" на сервере \"%s\" вернул %d записи." msgstr[2] "LDAP-поиск по фильтру \"%s\" на сервере \"%s\" вернул %d записей." -#: libpq/auth.c:2597 +#: libpq/auth.c:2606 #, c-format msgid "" "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" @@ -16243,24 +16775,18 @@ msgstr "" "не удалось получить dn для первого результата, соответствующего \"%s\" на " "сервере \"%s\": %s" -#: libpq/auth.c:2618 -#, c-format -msgid "could not unbind after searching for user \"%s\" on server \"%s\"" -msgstr "" -"не удалось отвязаться после поиска пользователя \"%s\" на сервере \"%s\"" - -#: libpq/auth.c:2649 +#: libpq/auth.c:2633 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "" "ошибка при регистрации в LDAP пользователя \"%s\" на сервере \"%s\": %s" -#: libpq/auth.c:2681 +#: libpq/auth.c:2665 #, c-format msgid "LDAP diagnostics: %s" msgstr "Диагностика LDAP: %s" -#: libpq/auth.c:2719 +#: libpq/auth.c:2703 #, c-format msgid "" "certificate authentication failed for user \"%s\": client certificate " @@ -16269,7 +16795,7 @@ msgstr "" "ошибка проверки подлинности пользователя \"%s\" по сертификату: сертификат " "клиента не содержит имя пользователя" -#: libpq/auth.c:2740 +#: libpq/auth.c:2724 #, c-format msgid "" "certificate authentication failed for user \"%s\": unable to retrieve " @@ -16278,7 +16804,7 @@ msgstr "" "пользователь \"%s\" не прошёл проверку подлинности по сертификату: не " "удалось получить DN субъекта" -#: libpq/auth.c:2763 +#: libpq/auth.c:2747 #, c-format msgid "" "certificate validation (clientcert=verify-full) failed for user \"%s\": DN " @@ -16287,7 +16813,7 @@ msgstr "" "проверка сертификата (clientcert=verify-full) для пользователя \"%s\" не " "прошла: отличается DN" -#: libpq/auth.c:2768 +#: libpq/auth.c:2752 #, c-format msgid "" "certificate validation (clientcert=verify-full) failed for user \"%s\": CN " @@ -16296,99 +16822,99 @@ msgstr "" "проверка сертификата (clientcert=verify-full) для пользователя \"%s\" не " "прошла: отличается CN" -#: libpq/auth.c:2870 +#: libpq/auth.c:2854 #, c-format msgid "RADIUS server not specified" msgstr "RADIUS-сервер не определён" -#: libpq/auth.c:2877 +#: libpq/auth.c:2861 #, c-format msgid "RADIUS secret not specified" msgstr "секрет RADIUS не определён" # well-spelled: симв -#: libpq/auth.c:2891 +#: libpq/auth.c:2875 #, c-format msgid "" "RADIUS authentication does not support passwords longer than %d characters" msgstr "проверка подлинности RADIUS не поддерживает пароли длиннее %d симв." -#: libpq/auth.c:2993 libpq/hba.c:2369 +#: libpq/auth.c:2977 libpq/hba.c:2352 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "не удалось преобразовать имя сервера RADIUS \"%s\" в адрес: %s" -#: libpq/auth.c:3007 +#: libpq/auth.c:2991 #, c-format msgid "could not generate random encryption vector" msgstr "не удалось сгенерировать случайный вектор шифрования" -#: libpq/auth.c:3044 +#: libpq/auth.c:3028 #, c-format msgid "could not perform MD5 encryption of password: %s" msgstr "не удалось вычислить MD5-хеш пароля: %s" -#: libpq/auth.c:3071 +#: libpq/auth.c:3055 #, c-format msgid "could not create RADIUS socket: %m" msgstr "не удалось создать сокет RADIUS: %m" -#: libpq/auth.c:3087 +#: libpq/auth.c:3071 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "не удалось привязаться к локальному сокету RADIUS: %m" -#: libpq/auth.c:3097 +#: libpq/auth.c:3081 #, c-format msgid "could not send RADIUS packet: %m" msgstr "не удалось отправить пакет RADIUS: %m" -#: libpq/auth.c:3131 libpq/auth.c:3157 +#: libpq/auth.c:3115 libpq/auth.c:3141 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "превышено время ожидания ответа RADIUS от %s" -#: libpq/auth.c:3150 +#: libpq/auth.c:3134 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "не удалось проверить состояние сокета RADIUS: %m" -#: libpq/auth.c:3180 +#: libpq/auth.c:3164 #, c-format msgid "could not read RADIUS response: %m" msgstr "не удалось прочитать ответ RADIUS: %m" -#: libpq/auth.c:3188 +#: libpq/auth.c:3172 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "ответ RADIUS от %s был отправлен с неверного порта: %d" -#: libpq/auth.c:3196 +#: libpq/auth.c:3180 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "слишком короткий ответ RADIUS от %s: %d" -#: libpq/auth.c:3203 +#: libpq/auth.c:3187 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "в ответе RADIUS от %s испорчена длина: %d (фактическая длина %d)" -#: libpq/auth.c:3211 +#: libpq/auth.c:3195 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "пришёл ответ RADIUS от %s на другой запрос: %d (ожидался %d)" -#: libpq/auth.c:3236 +#: libpq/auth.c:3220 #, c-format msgid "could not perform MD5 encryption of received packet: %s" msgstr "не удалось вычислить MD5-хеш для принятого пакета: %s" -#: libpq/auth.c:3246 +#: libpq/auth.c:3230 #, c-format msgid "RADIUS response from %s has incorrect MD5 signature" msgstr "ответ RADIUS от %s содержит неверную подпись MD5" -#: libpq/auth.c:3264 +#: libpq/auth.c:3248 #, c-format msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "ответ RADIUS от %s содержит неверный код (%d) для пользователя \"%s\"" @@ -16449,52 +16975,39 @@ msgstr "не удалось записать файл сервера \"%s\": %m" msgid "large object read request is too large" msgstr "при чтении большого объекта запрошен чрезмерный размер" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:262 utils/adt/genfile.c:294 -#: utils/adt/genfile.c:315 +#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "запрошенная длина не может быть отрицательной" -#: libpq/be-fsstubs.c:871 storage/large_object/inv_api.c:298 -#: storage/large_object/inv_api.c:310 storage/large_object/inv_api.c:507 -#: storage/large_object/inv_api.c:618 storage/large_object/inv_api.c:808 -#, c-format -msgid "permission denied for large object %u" -msgstr "нет доступа к большому объекту %u" - -#: libpq/be-secure-common.c:71 -#, c-format -msgid "could not read from command \"%s\": %m" -msgstr "не удалось прочитать вывод команды \"%s\": %m" - -#: libpq/be-secure-common.c:91 +#: libpq/be-secure-common.c:94 #, c-format msgid "command \"%s\" failed" msgstr "ошибка команды \"%s\"" -#: libpq/be-secure-common.c:119 +#: libpq/be-secure-common.c:123 #, c-format msgid "could not access private key file \"%s\": %m" msgstr "не удалось обратиться к файлу закрытого ключа \"%s\": %m" -#: libpq/be-secure-common.c:129 +#: libpq/be-secure-common.c:133 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "файл закрытого ключа \"%s\" - не обычный файл" -#: libpq/be-secure-common.c:155 +#: libpq/be-secure-common.c:159 #, c-format msgid "private key file \"%s\" must be owned by the database user or root" msgstr "" "файл закрытого ключа \"%s\" должен принадлежать пользователю, запускающему " "сервер, или root" -#: libpq/be-secure-common.c:165 +#: libpq/be-secure-common.c:169 #, c-format msgid "private key file \"%s\" has group or world access" msgstr "к файлу закрытого ключа \"%s\" имеют доступ все или группа" -#: libpq/be-secure-common.c:167 +#: libpq/be-secure-common.c:171 #, c-format msgid "" "File must have permissions u=rw (0600) or less if owned by the database " @@ -16545,82 +17058,82 @@ msgstr "принять контекст безопасности GSSAPI не у msgid "GSSAPI size check error" msgstr "ошибка проверки размера в GSSAPI" -#: libpq/be-secure-openssl.c:125 +#: libpq/be-secure-openssl.c:131 #, c-format msgid "could not create SSL context: %s" msgstr "не удалось создать контекст SSL: %s" -#: libpq/be-secure-openssl.c:151 +#: libpq/be-secure-openssl.c:157 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "не удалось загрузить сертификат сервера \"%s\": %s" -#: libpq/be-secure-openssl.c:171 +#: libpq/be-secure-openssl.c:177 #, c-format msgid "" "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "" "файл закрытого ключа \"%s\" нельзя перезагрузить, так как он защищён паролем" -#: libpq/be-secure-openssl.c:176 +#: libpq/be-secure-openssl.c:182 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "не удалось загрузить файл закрытого ключа \"%s\": %s" -#: libpq/be-secure-openssl.c:185 +#: libpq/be-secure-openssl.c:191 #, c-format msgid "check of private key failed: %s" msgstr "ошибка при проверке закрытого ключа: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:198 libpq/be-secure-openssl.c:221 +#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "для параметра \"%s\" значение \"%s\" не поддерживается в данной сборке" -#: libpq/be-secure-openssl.c:208 +#: libpq/be-secure-openssl.c:214 #, c-format msgid "could not set minimum SSL protocol version" msgstr "не удалось задать минимальную версию протокола SSL" -#: libpq/be-secure-openssl.c:231 +#: libpq/be-secure-openssl.c:237 #, c-format msgid "could not set maximum SSL protocol version" msgstr "не удалось задать максимальную версию протокола SSL" -#: libpq/be-secure-openssl.c:247 +#: libpq/be-secure-openssl.c:253 #, c-format msgid "could not set SSL protocol version range" msgstr "не удалось задать диапазон версий протокола SSL" -#: libpq/be-secure-openssl.c:248 +#: libpq/be-secure-openssl.c:254 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "Версия \"%s\" не может быть выше \"%s\"" -#: libpq/be-secure-openssl.c:285 +#: libpq/be-secure-openssl.c:307 #, c-format msgid "could not set the cipher list (no valid ciphers available)" msgstr "не удалось установить список шифров (подходящие шифры отсутствуют)" -#: libpq/be-secure-openssl.c:305 +#: libpq/be-secure-openssl.c:327 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "не удалось загрузить файл корневых сертификатов \"%s\": %s" -#: libpq/be-secure-openssl.c:354 +#: libpq/be-secure-openssl.c:376 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "" "не удалось загрузить список отзыва сертификатов SSL из файла \"%s\": %s" -#: libpq/be-secure-openssl.c:362 +#: libpq/be-secure-openssl.c:384 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "" "не удалось загрузить списки отзыва сертификатов SSL из каталога \"%s\": %s" -#: libpq/be-secure-openssl.c:370 +#: libpq/be-secure-openssl.c:392 #, c-format msgid "" "could not load SSL certificate revocation list file \"%s\" or directory " @@ -16629,38 +17142,38 @@ msgstr "" "не удалось загрузить списки отзыва сертификатов SSL из файла \"%s\" или " "каталога \"%s\": %s" -#: libpq/be-secure-openssl.c:428 +#: libpq/be-secure-openssl.c:450 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "" "инициализировать SSL-подключение не удалось: контекст SSL не установлен" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:464 #, c-format msgid "could not initialize SSL connection: %s" msgstr "инициализировать SSL-подключение не удалось: %s" -#: libpq/be-secure-openssl.c:447 +#: libpq/be-secure-openssl.c:472 #, c-format msgid "could not set SSL socket: %s" msgstr "не удалось создать SSL-сокет: %s" -#: libpq/be-secure-openssl.c:503 +#: libpq/be-secure-openssl.c:528 #, c-format msgid "could not accept SSL connection: %m" msgstr "не удалось принять SSL-подключение: %m" -#: libpq/be-secure-openssl.c:507 libpq/be-secure-openssl.c:562 +#: libpq/be-secure-openssl.c:532 libpq/be-secure-openssl.c:589 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "не удалось принять SSL-подключение: обрыв данных" -#: libpq/be-secure-openssl.c:546 +#: libpq/be-secure-openssl.c:573 #, c-format msgid "could not accept SSL connection: %s" msgstr "не удалось принять SSL-подключение: %s" -#: libpq/be-secure-openssl.c:550 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "" "This may indicate that the client does not support any SSL protocol version " @@ -16669,60 +17182,65 @@ msgstr "" "Это может указывать на то, что клиент не поддерживает ни одну версию " "протокола SSL между %s и %s." -#: libpq/be-secure-openssl.c:567 libpq/be-secure-openssl.c:756 -#: libpq/be-secure-openssl.c:826 +#: libpq/be-secure-openssl.c:594 libpq/be-secure-openssl.c:809 +#: libpq/be-secure-openssl.c:879 #, c-format msgid "unrecognized SSL error code: %d" msgstr "нераспознанный код ошибки SSL: %d" -#: libpq/be-secure-openssl.c:613 +#: libpq/be-secure-openssl.c:622 +#, c-format +msgid "received SSL connection request with unexpected ALPN protocol" +msgstr "получен запрос на SSL-подключение с неизвестным протоколом ALPN" + +#: libpq/be-secure-openssl.c:666 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "Имя SSL-сертификата включает нулевой байт" -#: libpq/be-secure-openssl.c:659 +#: libpq/be-secure-openssl.c:712 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "уникальное имя (DN) в SSL-сертификате содержит нулевой байт" -#: libpq/be-secure-openssl.c:745 libpq/be-secure-openssl.c:810 +#: libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:863 #, c-format msgid "SSL error: %s" msgstr "ошибка SSL: %s" -#: libpq/be-secure-openssl.c:987 +#: libpq/be-secure-openssl.c:1038 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "не удалось открыть файл параметров DH \"%s\": %m" -#: libpq/be-secure-openssl.c:999 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not load DH parameters file: %s" msgstr "не удалось загрузить файл параметров DH: %s" -#: libpq/be-secure-openssl.c:1009 +#: libpq/be-secure-openssl.c:1060 #, c-format msgid "invalid DH parameters: %s" msgstr "неверные параметры DH: %s" -#: libpq/be-secure-openssl.c:1018 +#: libpq/be-secure-openssl.c:1069 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "неверные параметры DH: p - не простое число" -#: libpq/be-secure-openssl.c:1027 +#: libpq/be-secure-openssl.c:1078 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "" "неверные параметры DH: нет подходящего генератора или небезопасное простое " "число" -#: libpq/be-secure-openssl.c:1163 +#: libpq/be-secure-openssl.c:1214 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "Ошибка при проверке клиентского сертификата на глубине %d: %s." -#: libpq/be-secure-openssl.c:1200 +#: libpq/be-secure-openssl.c:1251 #, c-format msgid "" "Failed certificate data (unverified): subject \"%s\", serial number %s, " @@ -16731,178 +17249,173 @@ msgstr "" "Данные ошибочного сертификата (непроверенные): субъект \"%s\", серийный " "номер %s, издатель \"%s\"." -#: libpq/be-secure-openssl.c:1201 +#: libpq/be-secure-openssl.c:1252 msgid "unknown" msgstr "н/д" -#: libpq/be-secure-openssl.c:1292 +#: libpq/be-secure-openssl.c:1389 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: не удалось загрузить параметры DH" -#: libpq/be-secure-openssl.c:1300 +#: libpq/be-secure-openssl.c:1397 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: не удалось задать параметры DH: %s" -#: libpq/be-secure-openssl.c:1327 +#: libpq/be-secure-openssl.c:1424 #, c-format msgid "ECDH: unrecognized curve name: %s" msgstr "ECDH: нераспознанное имя кривой: %s" -#: libpq/be-secure-openssl.c:1336 +#: libpq/be-secure-openssl.c:1433 #, c-format msgid "ECDH: could not create key" msgstr "ECDH: не удалось создать ключ" -#: libpq/be-secure-openssl.c:1364 +#: libpq/be-secure-openssl.c:1461 msgid "no SSL error reported" msgstr "нет сообщения об ошибке SSL" -#: libpq/be-secure-openssl.c:1381 +#: libpq/be-secure-openssl.c:1479 #, c-format msgid "SSL error code %lu" msgstr "код ошибки SSL: %lu" -#: libpq/be-secure-openssl.c:1540 +#: libpq/be-secure-openssl.c:1636 #, c-format msgid "could not create BIO" msgstr "не удалось создать BIO" -#: libpq/be-secure-openssl.c:1550 +#: libpq/be-secure-openssl.c:1646 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "не удалось получить NID для объекта ASN1_OBJECT" -#: libpq/be-secure-openssl.c:1558 +#: libpq/be-secure-openssl.c:1654 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "не удалось преобразовать NID %d в структуру ASN1_OBJECT" -#: libpq/be-secure.c:207 libpq/be-secure.c:303 -#, c-format -msgid "terminating connection due to unexpected postmaster exit" -msgstr "закрытие подключения из-за неожиданного завершения главного процесса" - -#: libpq/crypt.c:49 +#: libpq/crypt.c:48 #, c-format msgid "Role \"%s\" does not exist." msgstr "Роль \"%s\" не существует." -#: libpq/crypt.c:59 +#: libpq/crypt.c:58 #, c-format msgid "User \"%s\" has no password assigned." msgstr "Пользователь \"%s\" не имеет пароля." -#: libpq/crypt.c:77 +#: libpq/crypt.c:76 #, c-format msgid "User \"%s\" has an expired password." msgstr "Срок действия пароля пользователя \"%s\" истёк." -#: libpq/crypt.c:183 +#: libpq/crypt.c:182 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "" "Пользователь \"%s\" имеет пароль, неподходящий для аутентификации по MD5." -#: libpq/crypt.c:204 libpq/crypt.c:246 libpq/crypt.c:266 +#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 #, c-format msgid "Password does not match for user \"%s\"." msgstr "Пароль не подходит для пользователя \"%s\"." -#: libpq/crypt.c:285 +#: libpq/crypt.c:284 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "Пароль пользователя \"%s\" представлен в неизвестном формате." -#: libpq/hba.c:332 +#: libpq/hba.c:327 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "неверное регулярное выражение \"%s\": %s" -#: libpq/hba.c:334 libpq/hba.c:666 libpq/hba.c:1250 libpq/hba.c:1270 -#: libpq/hba.c:1293 libpq/hba.c:1306 libpq/hba.c:1359 libpq/hba.c:1387 -#: libpq/hba.c:1395 libpq/hba.c:1407 libpq/hba.c:1428 libpq/hba.c:1441 -#: libpq/hba.c:1466 libpq/hba.c:1493 libpq/hba.c:1505 libpq/hba.c:1564 -#: libpq/hba.c:1584 libpq/hba.c:1598 libpq/hba.c:1618 libpq/hba.c:1629 -#: libpq/hba.c:1644 libpq/hba.c:1663 libpq/hba.c:1679 libpq/hba.c:1691 -#: libpq/hba.c:1728 libpq/hba.c:1769 libpq/hba.c:1782 libpq/hba.c:1804 -#: libpq/hba.c:1816 libpq/hba.c:1834 libpq/hba.c:1884 libpq/hba.c:1928 -#: libpq/hba.c:1939 libpq/hba.c:1955 libpq/hba.c:1972 libpq/hba.c:1983 -#: libpq/hba.c:2002 libpq/hba.c:2018 libpq/hba.c:2034 libpq/hba.c:2093 -#: libpq/hba.c:2110 libpq/hba.c:2123 libpq/hba.c:2135 libpq/hba.c:2154 -#: libpq/hba.c:2240 libpq/hba.c:2258 libpq/hba.c:2352 libpq/hba.c:2371 -#: libpq/hba.c:2400 libpq/hba.c:2413 libpq/hba.c:2436 libpq/hba.c:2458 -#: libpq/hba.c:2472 tsearch/ts_locale.c:243 +#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 +#: libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 +#: libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 +#: libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 +#: libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 +#: libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 +#: libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 libpq/hba.c:1799 +#: libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 +#: libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 +#: libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 +#: libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 +#: libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 +#: libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 +#: tsearch/ts_locale.c:241 #, c-format msgid "line %d of configuration file \"%s\"" msgstr "строка %d файла конфигурации \"%s\"" -#: libpq/hba.c:462 +#: libpq/hba.c:457 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "отсутствующий файл настройки аутентификации \"%s\" пропускается" -#: libpq/hba.c:614 +#: libpq/hba.c:609 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "открыть файл \"%s\" не удалось: превышен предел вложенности" -#: libpq/hba.c:1221 +#: libpq/hba.c:1216 #, c-format msgid "error enumerating network interfaces: %m" msgstr "ошибка при перечислении сетевых интерфейсов: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1248 +#: libpq/hba.c:1243 #, c-format msgid "" "authentication option \"%s\" is only valid for authentication methods %s" msgstr "параметр проверки подлинности \"%s\" допускается только для методов %s" -#: libpq/hba.c:1268 +#: libpq/hba.c:1263 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "" "для метода проверки подлинности \"%s\" требуется определить аргумент \"%s\"" -#: libpq/hba.c:1292 +#: libpq/hba.c:1287 #, c-format msgid "missing entry at end of line" msgstr "отсутствует запись в конце строки" -#: libpq/hba.c:1305 +#: libpq/hba.c:1300 #, c-format msgid "multiple values in ident field" msgstr "множественные значения в поле ident" -#: libpq/hba.c:1357 +#: libpq/hba.c:1352 #, c-format msgid "multiple values specified for connection type" msgstr "для типа подключения указано несколько значений" -#: libpq/hba.c:1358 +#: libpq/hba.c:1353 #, c-format msgid "Specify exactly one connection type per line." msgstr "Определите в строке единственный тип подключения." -#: libpq/hba.c:1385 +#: libpq/hba.c:1380 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "запись с hostssl недействительна, так как поддержка SSL отключена" -#: libpq/hba.c:1386 +#: libpq/hba.c:1381 #, c-format -msgid "Set ssl = on in postgresql.conf." -msgstr "Установите ssl = on в postgresql.conf." +msgid "Set \"ssl = on\" in postgresql.conf." +msgstr "Установите \"ssl = on\" в postgresql.conf." -#: libpq/hba.c:1394 +#: libpq/hba.c:1389 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "" "запись с hostssl недействительна, так как SSL не поддерживается в этой сборке" -#: libpq/hba.c:1406 +#: libpq/hba.c:1401 #, c-format msgid "" "hostgssenc record cannot match because GSSAPI is not supported by this build" @@ -16910,126 +17423,126 @@ msgstr "" "запись с hostgssenc недействительна, так как GSSAPI не поддерживается в этой " "сборке" -#: libpq/hba.c:1426 +#: libpq/hba.c:1421 #, c-format msgid "invalid connection type \"%s\"" msgstr "неверный тип подключения \"%s\"" -#: libpq/hba.c:1440 +#: libpq/hba.c:1435 #, c-format msgid "end-of-line before database specification" msgstr "конец строки перед определением базы данных" -#: libpq/hba.c:1465 +#: libpq/hba.c:1460 #, c-format msgid "end-of-line before role specification" msgstr "конец строки перед определением роли" -#: libpq/hba.c:1492 +#: libpq/hba.c:1487 #, c-format msgid "end-of-line before IP address specification" msgstr "конец строки перед определением IP-адресов" -#: libpq/hba.c:1503 +#: libpq/hba.c:1498 #, c-format msgid "multiple values specified for host address" msgstr "для адреса узла указано несколько значений" -#: libpq/hba.c:1504 +#: libpq/hba.c:1499 #, c-format msgid "Specify one address range per line." msgstr "Определите в строке один диапазон адресов." -#: libpq/hba.c:1562 +#: libpq/hba.c:1557 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "неверный IP-адрес \"%s\": %s" -#: libpq/hba.c:1582 +#: libpq/hba.c:1577 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "указать одновременно и имя узла, и маску CIDR нельзя: \"%s\"" -#: libpq/hba.c:1596 +#: libpq/hba.c:1591 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "неверная маска CIDR в адресе \"%s\"" -#: libpq/hba.c:1616 +#: libpq/hba.c:1611 #, c-format msgid "end-of-line before netmask specification" msgstr "конец строки перед определением маски сети" -#: libpq/hba.c:1617 +#: libpq/hba.c:1612 #, c-format msgid "" "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "" "Укажите диапазон адресов в формате CIDR или задайте отдельную маску сети." -#: libpq/hba.c:1628 +#: libpq/hba.c:1623 #, c-format msgid "multiple values specified for netmask" msgstr "для сетевой маски указано несколько значений" -#: libpq/hba.c:1642 +#: libpq/hba.c:1637 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "неверная маска IP \"%s\": %s" -#: libpq/hba.c:1662 +#: libpq/hba.c:1657 #, c-format msgid "IP address and mask do not match" msgstr "IP-адрес не соответствует маске" -#: libpq/hba.c:1678 +#: libpq/hba.c:1673 #, c-format msgid "end-of-line before authentication method" msgstr "конец строки перед методом проверки подлинности" -#: libpq/hba.c:1689 +#: libpq/hba.c:1684 #, c-format msgid "multiple values specified for authentication type" msgstr "для типа проверки подлинности указано несколько значений" -#: libpq/hba.c:1690 +#: libpq/hba.c:1685 #, c-format msgid "Specify exactly one authentication type per line." msgstr "Определите в строке единственный тип проверки подлинности." -#: libpq/hba.c:1767 +#: libpq/hba.c:1750 #, c-format msgid "invalid authentication method \"%s\"" msgstr "неверный метод проверки подлинности \"%s\"" -#: libpq/hba.c:1780 +#: libpq/hba.c:1763 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "" "неверный метод проверки подлинности \"%s\": не поддерживается в этой сборке" -#: libpq/hba.c:1803 +#: libpq/hba.c:1786 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "проверка подлинности gssapi для локальных сокетов не поддерживается" -#: libpq/hba.c:1815 +#: libpq/hba.c:1798 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "проверка подлинности peer поддерживается только для локальных сокетов" -#: libpq/hba.c:1833 +#: libpq/hba.c:1816 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "" "проверка подлинности cert поддерживается только для подключений hostssl" -#: libpq/hba.c:1883 +#: libpq/hba.c:1866 #, c-format msgid "authentication option not in name=value format: %s" msgstr "параметр проверки подлинности указан не в формате имя=значение: %s" -#: libpq/hba.c:1927 +#: libpq/hba.c:1910 #, c-format msgid "" "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, " @@ -17038,7 +17551,7 @@ msgstr "" "нельзя использовать ldapbasedn, ldapbinddn, ldapbindpasswd, " "ldapsearchattribute, ldapsearchfilter или ldapurl вместе с ldapprefix" -#: libpq/hba.c:1938 +#: libpq/hba.c:1921 #, c-format msgid "" "authentication method \"ldap\" requires argument \"ldapbasedn\", " @@ -17047,22 +17560,22 @@ msgstr "" "для метода проверки подлинности \"ldap\" требуется установить аргументы " "\"ldapbasedn\" и \"ldapprefix\" или \"ldapsuffix\"" -#: libpq/hba.c:1954 +#: libpq/hba.c:1937 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "нельзя использовать ldapsearchattribute вместе с ldapsearchfilter" -#: libpq/hba.c:1971 +#: libpq/hba.c:1954 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "список серверов RADIUS не может быть пустым" -#: libpq/hba.c:1982 +#: libpq/hba.c:1965 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "список секретов RADIUS не может быть пустым" -#: libpq/hba.c:1999 +#: libpq/hba.c:1982 #, c-format msgid "" "the number of RADIUS secrets (%d) must be 1 or the same as the number of " @@ -17071,7 +17584,7 @@ msgstr "" "количество секретов RADIUS (%d) должно равняться 1 или количеству серверов " "RADIUS (%d)" -#: libpq/hba.c:2015 +#: libpq/hba.c:1998 #, c-format msgid "" "the number of RADIUS ports (%d) must be 1 or the same as the number of " @@ -17080,7 +17593,7 @@ msgstr "" "количество портов RADIUS (%d) должно равняться 1 или количеству серверов " "RADIUS (%d)" -#: libpq/hba.c:2031 +#: libpq/hba.c:2014 #, c-format msgid "" "the number of RADIUS identifiers (%d) must be 1 or the same as the number of " @@ -17089,16 +17602,16 @@ msgstr "" "количество идентификаторов RADIUS (%d) должно равняться 1 или количеству " "серверов RADIUS (%d)" -#: libpq/hba.c:2083 +#: libpq/hba.c:2066 msgid "ident, peer, gssapi, sspi, and cert" msgstr "ident, peer, gssapi, sspi и cert" -#: libpq/hba.c:2092 +#: libpq/hba.c:2075 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert можно определить только в строках \"hostssl\"" -#: libpq/hba.c:2109 +#: libpq/hba.c:2092 #, c-format msgid "" "clientcert only accepts \"verify-full\" when using \"cert\" authentication" @@ -17106,95 +17619,95 @@ msgstr "" "с проверкой подлинности \"cert\" для clientcert допускается только значение " "\"verify-full\"" -#: libpq/hba.c:2122 +#: libpq/hba.c:2105 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "неверное значение для clientcert: \"%s\"" -#: libpq/hba.c:2134 +#: libpq/hba.c:2117 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname можно определить только в строках \"hostssl\"" -#: libpq/hba.c:2153 +#: libpq/hba.c:2136 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "неверное значение для clientname: \"%s\"" -#: libpq/hba.c:2186 +#: libpq/hba.c:2169 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "не удалось разобрать URL-адрес LDAP \"%s\": %s" -#: libpq/hba.c:2197 +#: libpq/hba.c:2180 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "неподдерживаемая схема в URL-адресе LDAP: %s" -#: libpq/hba.c:2221 +#: libpq/hba.c:2204 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "URL-адреса LDAP не поддерживаются в этой ОС" -#: libpq/hba.c:2239 +#: libpq/hba.c:2222 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "неверное значение ldapscheme: \"%s\"" -#: libpq/hba.c:2257 +#: libpq/hba.c:2240 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "неверный номер порта LDAP: \"%s\"" -#: libpq/hba.c:2303 libpq/hba.c:2310 +#: libpq/hba.c:2286 libpq/hba.c:2293 msgid "gssapi and sspi" msgstr "gssapi и sspi" -#: libpq/hba.c:2319 libpq/hba.c:2328 +#: libpq/hba.c:2302 libpq/hba.c:2311 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2350 +#: libpq/hba.c:2333 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "не удалось разобрать список серверов RADIUS \"%s\"" -#: libpq/hba.c:2398 +#: libpq/hba.c:2381 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "не удалось разобрать список портов RADIUS \"%s\"" -#: libpq/hba.c:2412 +#: libpq/hba.c:2395 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "неверный номер порта RADIUS: \"%s\"" -#: libpq/hba.c:2434 +#: libpq/hba.c:2417 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "не удалось разобрать список секретов RADIUS \"%s\"" -#: libpq/hba.c:2456 +#: libpq/hba.c:2439 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "не удалось разобрать список идентификаторов RADIUS \"%s\"" -#: libpq/hba.c:2470 +#: libpq/hba.c:2453 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "нераспознанное имя атрибута проверки подлинности: \"%s\"" -#: libpq/hba.c:2662 +#: libpq/hba.c:2645 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "файл конфигурации \"%s\" не содержит записей" -#: libpq/hba.c:2815 +#: libpq/hba.c:2798 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "ошибка при поиске по регулярному выражению для \"%s\": %s" -#: libpq/hba.c:2839 +#: libpq/hba.c:2822 #, c-format msgid "" "regular expression \"%s\" has no subexpressions as requested by " @@ -17203,88 +17716,96 @@ msgstr "" "в регулярном выражении \"%s\" нет подвыражений, требуемых для обратной " "ссылки в \"%s\"" -#: libpq/hba.c:2942 +#: libpq/hba.c:2925 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "" "указанное имя пользователя (%s) не совпадает с именем прошедшего проверку " "(%s)" -#: libpq/hba.c:2962 +#: libpq/hba.c:2945 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "" "нет соответствия в файле сопоставлений \"%s\" для пользователя \"%s\", " "прошедшего проверку как \"%s\"" -#: libpq/pqcomm.c:196 +#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 +#: libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 +#: libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 +#: libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#, c-format +msgid "%s(%s) failed: %m" +msgstr "ошибка в %s(%s): %m" + +#: libpq/pqcomm.c:296 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "не удалось перевести сокет в неблокирующий режим: %m" -#: libpq/pqcomm.c:357 +#: libpq/pqcomm.c:456 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "длина пути Unix-сокета \"%s\" превышает предел (%d байт)" -#: libpq/pqcomm.c:377 +#: libpq/pqcomm.c:476 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "перевести имя узла \"%s\", службы \"%s\" в адрес не удалось: %s" -#: libpq/pqcomm.c:381 +#: libpq/pqcomm.c:480 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "не удалось перевести имя службы \"%s\" в адрес: %s" -#: libpq/pqcomm.c:408 +#: libpq/pqcomm.c:502 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "" "не удалось привязаться ко всем запрошенным адресам: превышен предел " "MAXLISTEN (%d)" -#: libpq/pqcomm.c:417 +#: libpq/pqcomm.c:511 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:420 +#: libpq/pqcomm.c:514 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:423 +#: libpq/pqcomm.c:517 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:427 +#: libpq/pqcomm.c:521 #, c-format msgid "unrecognized address family %d" msgstr "нераспознанное семейство адресов: %d" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:451 +#: libpq/pqcomm.c:545 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "не удалось создать сокет %s для адреса \"%s\": %m" #. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:477 libpq/pqcomm.c:495 +#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "ошибка в %s(%s) для адреса %s \"%s\": %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:518 +#: libpq/pqcomm.c:615 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "не удалось привязаться к адресу %s \"%s\": %m" -#: libpq/pqcomm.c:522 +#: libpq/pqcomm.c:619 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "Возможно, порт %d занят другим процессом postmaster?" -#: libpq/pqcomm.c:524 +#: libpq/pqcomm.c:621 #, c-format msgid "" "Is another postmaster already running on port %d? If not, wait a few seconds " @@ -17294,128 +17815,120 @@ msgstr "" "попытку через несколько секунд." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:553 +#: libpq/pqcomm.c:650 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "не удалось привязаться к адресу %s \"%s\": %m" -#: libpq/pqcomm.c:561 +#: libpq/pqcomm.c:658 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "для приёма подключений открыт Unix-сокет \"%s\"" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:566 +#: libpq/pqcomm.c:663 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "для приёма подключений по адресу %s \"%s\" открыт порт %d" -#: libpq/pqcomm.c:655 +#: libpq/pqcomm.c:753 #, c-format msgid "group \"%s\" does not exist" msgstr "группа \"%s\" не существует" -#: libpq/pqcomm.c:665 +#: libpq/pqcomm.c:763 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "не удалось установить группу для файла \"%s\": %m" -#: libpq/pqcomm.c:676 +#: libpq/pqcomm.c:774 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "не удалось установить права доступа для файла \"%s\": %m" -#: libpq/pqcomm.c:704 +#: libpq/pqcomm.c:803 #, c-format msgid "could not accept new connection: %m" msgstr "не удалось принять новое подключение: %m" -#: libpq/pqcomm.c:744 libpq/pqcomm.c:753 libpq/pqcomm.c:785 libpq/pqcomm.c:795 -#: libpq/pqcomm.c:1630 libpq/pqcomm.c:1675 libpq/pqcomm.c:1715 -#: libpq/pqcomm.c:1759 libpq/pqcomm.c:1798 libpq/pqcomm.c:1837 -#: libpq/pqcomm.c:1873 libpq/pqcomm.c:1912 -#, c-format -msgid "%s(%s) failed: %m" -msgstr "ошибка в %s(%s): %m" - -#: libpq/pqcomm.c:899 +#: libpq/pqcomm.c:885 #, c-format msgid "there is no client connection" msgstr "нет клиентского подключения" -#: libpq/pqcomm.c:955 libpq/pqcomm.c:1056 +#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 #, c-format msgid "could not receive data from client: %m" msgstr "не удалось получить данные от клиента: %m" -#: libpq/pqcomm.c:1161 tcop/postgres.c:4405 +#: libpq/pqcomm.c:1149 tcop/postgres.c:4533 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "закрытие подключения из-за потери синхронизации протокола" -#: libpq/pqcomm.c:1227 +#: libpq/pqcomm.c:1215 #, c-format msgid "unexpected EOF within message length word" msgstr "неожиданный обрыв данных в слове длины сообщения" -#: libpq/pqcomm.c:1237 +#: libpq/pqcomm.c:1225 #, c-format msgid "invalid message length" msgstr "неверная длина сообщения" -#: libpq/pqcomm.c:1259 libpq/pqcomm.c:1272 +#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 #, c-format msgid "incomplete message from client" msgstr "неполное сообщение от клиента" -#: libpq/pqcomm.c:1383 +#: libpq/pqcomm.c:1401 #, c-format msgid "could not send data to client: %m" msgstr "не удалось послать данные клиенту: %m" -#: libpq/pqcomm.c:1598 +#: libpq/pqcomm.c:1616 #, c-format msgid "%s(%s) failed: error code %d" msgstr "ошибка в %s(%s): код ошибки %d" -#: libpq/pqcomm.c:1687 +#: libpq/pqcomm.c:1705 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "изменение значения keepalives_idle не поддерживается" -#: libpq/pqcomm.c:1771 libpq/pqcomm.c:1846 libpq/pqcomm.c:1921 +#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s) не поддерживается" -#: libpq/pqformat.c:407 +#: libpq/pqformat.c:404 #, c-format msgid "no data left in message" msgstr "в сообщении не осталось данных" -#: libpq/pqformat.c:518 libpq/pqformat.c:536 libpq/pqformat.c:557 -#: utils/adt/array_userfuncs.c:799 utils/adt/arrayfuncs.c:1507 -#: utils/adt/rowtypes.c:615 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 +#: utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 +#: utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "недостаточно данных осталось в сообщении" -#: libpq/pqformat.c:598 libpq/pqformat.c:627 +#: libpq/pqformat.c:595 libpq/pqformat.c:624 #, c-format msgid "invalid string in message" msgstr "неверная строка в сообщении" -#: libpq/pqformat.c:643 +#: libpq/pqformat.c:640 #, c-format msgid "invalid message format" msgstr "неверный формат сообщения" -#: main/main.c:235 +#: main/main.c:236 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: ошибка WSAStartup: %d\n" -#: main/main.c:329 +#: main/main.c:324 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -17424,7 +17937,7 @@ msgstr "" "%s - сервер PostgreSQL.\n" "\n" -#: main/main.c:330 +#: main/main.c:325 #, c-format msgid "" "Usage:\n" @@ -17435,110 +17948,110 @@ msgstr "" " %s [ПАРАМЕТР]...\n" "\n" -#: main/main.c:331 +#: main/main.c:326 #, c-format msgid "Options:\n" msgstr "Параметры:\n" -#: main/main.c:332 +#: main/main.c:327 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B ЧИСЛО_БУФ число разделяемых буферов\n" -#: main/main.c:333 +#: main/main.c:328 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c ИМЯ=ЗНАЧЕНИЕ установить параметр выполнения\n" -#: main/main.c:334 +#: main/main.c:329 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C ИМЯ вывести значение параметра выполнения и выйти\n" -#: main/main.c:335 +#: main/main.c:330 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 уровень отладочных сообщений\n" -#: main/main.c:336 +#: main/main.c:331 #, c-format msgid " -D DATADIR database directory\n" -msgstr " -D КАТАЛОГ каталог с данными\n" +msgstr " -D КАТ_ДАННЫХ каталог с данными\n" # well-spelled: ДМГ -#: main/main.c:337 +#: main/main.c:332 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e использовать европейский формат дат (ДМГ)\n" -#: main/main.c:338 +#: main/main.c:333 #, c-format msgid " -F turn fsync off\n" msgstr " -F выключить синхронизацию с ФС\n" -#: main/main.c:339 +#: main/main.c:334 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h ИМЯ имя или IP-адрес для приёма сетевых соединений\n" -#: main/main.c:340 +#: main/main.c:335 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr "" " -i включить соединения TCP/IP (устаревший параметр)\n" -#: main/main.c:341 +#: main/main.c:336 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k КАТАЛОГ расположение Unix-сокетов\n" -#: main/main.c:343 +#: main/main.c:338 #, c-format msgid " -l enable SSL connections\n" msgstr " -l разрешить SSL-подключения\n" # well-spelled: ПОДКЛ -#: main/main.c:345 +#: main/main.c:340 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N МАКС_ПОДКЛ предельное число подключений\n" -#: main/main.c:346 +#: main/main.c:341 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p ПОРТ номер порта для приёма подключений\n" -#: main/main.c:347 +#: main/main.c:342 #, c-format msgid " -s show statistics after each query\n" msgstr " -s показывать статистику после каждого запроса\n" -#: main/main.c:348 +#: main/main.c:343 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S РАБ_ПАМЯТЬ задать объём памяти для сортировки (в КБ)\n" -#: main/main.c:349 +#: main/main.c:344 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: main/main.c:350 +#: main/main.c:345 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --ИМЯ=ЗНАЧЕНИЕ установить параметр выполнения\n" -#: main/main.c:351 +#: main/main.c:346 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config вывести параметры конфигурации и выйти\n" -#: main/main.c:352 +#: main/main.c:347 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: main/main.c:354 +#: main/main.c:349 #, c-format msgid "" "\n" @@ -17547,27 +18060,27 @@ msgstr "" "\n" "Параметры для разработчиков:\n" -#: main/main.c:355 +#: main/main.c:350 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h запретить некоторые типы планов\n" -#: main/main.c:356 +#: main/main.c:351 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O разрешить изменять структуру системных таблиц\n" -#: main/main.c:357 +#: main/main.c:352 #, c-format msgid " -P disable system indexes\n" msgstr " -P отключить системные индексы\n" -#: main/main.c:358 +#: main/main.c:353 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex показать время каждого запроса\n" -#: main/main.c:359 +#: main/main.c:354 #, c-format msgid "" " -T send SIGABRT to all backend processes if one dies\n" @@ -17575,13 +18088,13 @@ msgstr "" " -T посылать сигнал SIGABRT всем серверным процессам\n" " при отключении одного\n" -#: main/main.c:360 +#: main/main.c:355 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr "" " -W СЕК ждать заданное число секунд для подключения отладчика\n" -#: main/main.c:362 +#: main/main.c:357 #, c-format msgid "" "\n" @@ -17590,7 +18103,7 @@ msgstr "" "\n" "Параметры для монопольного режима:\n" -#: main/main.c:363 +#: main/main.c:358 #, c-format msgid "" " --single selects single-user mode (must be first argument)\n" @@ -17598,22 +18111,22 @@ msgstr "" " --single включить монопольный режим\n" " (этот аргумент должен быть первым)\n" -#: main/main.c:364 +#: main/main.c:359 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " ИМЯ_БД база данных (по умолчанию - имя пользователя)\n" -#: main/main.c:365 +#: main/main.c:360 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 переопределить уровень отладочных сообщений\n" -#: main/main.c:366 +#: main/main.c:361 #, c-format msgid " -E echo statement before execution\n" msgstr " -E выводить SQL-операторы перед выполнением\n" -#: main/main.c:367 +#: main/main.c:362 #, c-format msgid "" " -j do not use newline as interactive query delimiter\n" @@ -17621,12 +18134,12 @@ msgstr "" " -j не считать конец строки разделителем интерактивных " "запросов\n" -#: main/main.c:368 main/main.c:374 +#: main/main.c:363 main/main.c:369 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r ИМЯ_ФАЙЛА перенаправить STDOUT и STDERR в указанный файл\n" -#: main/main.c:370 +#: main/main.c:365 #, c-format msgid "" "\n" @@ -17635,7 +18148,7 @@ msgstr "" "\n" "Параметры для режима инициализации:\n" -#: main/main.c:371 +#: main/main.c:366 #, c-format msgid "" " --boot selects bootstrapping mode (must be first argument)\n" @@ -17643,14 +18156,14 @@ msgstr "" " --boot включить режим инициализации\n" " (этот аргумент должен быть первым)\n" -#: main/main.c:372 +#: main/main.c:367 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr "" " --check включить режим проверки (этот аргумент должен быть " "первым)\n" -#: main/main.c:373 +#: main/main.c:368 #, c-format msgid "" " DBNAME database name (mandatory argument in bootstrapping " @@ -17658,7 +18171,7 @@ msgid "" msgstr "" " ИМЯ_БД имя базы данных (необходимо в режиме инициализации)\n" -#: main/main.c:376 +#: main/main.c:371 #, c-format msgid "" "\n" @@ -17675,12 +18188,12 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: main/main.c:380 +#: main/main.c:375 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: main/main.c:391 +#: main/main.c:386 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -17693,12 +18206,12 @@ msgstr "" "должен запускать обычный пользователь. Подробнее о том, как\n" "правильно запускать сервер, вы можете узнать в документации.\n" -#: main/main.c:408 +#: main/main.c:403 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: фактический и эффективный ID пользователя должны совпадать\n" -#: main/main.c:415 +#: main/main.c:410 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -17723,19 +18236,14 @@ msgstr "расширенный тип узла \"%s\" уже существуе msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "методы расширенного узла \"%s\" не зарегистрированы" -#: nodes/makefuncs.c:153 statistics/extended_stats.c:2335 +#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "отношение \"%s\" не имеет составного типа" -#: nodes/makefuncs.c:879 -#, c-format -msgid "unrecognized JSON encoding: %s" -msgstr "нераспознанная кодировка JSON: %s" - -#: nodes/nodeFuncs.c:116 nodes/nodeFuncs.c:147 parser/parse_coerce.c:2567 -#: parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 -#: parser/parse_expr.c:2049 parser/parse_func.c:710 parser/parse_oper.c:883 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2604 +#: parser/parse_coerce.c:2742 parser/parse_coerce.c:2789 +#: parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 #: utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" @@ -17751,7 +18259,7 @@ msgstr "портал \"%s\" с параметрами: %s" msgid "unnamed portal with parameters: %s" msgstr "неименованный портал с параметрами: %s" -#: optimizer/path/joinrels.c:973 +#: optimizer/path/joinrels.c:972 #, c-format msgid "" "FULL JOIN is only supported with merge-joinable or hash-joinable join " @@ -17760,32 +18268,32 @@ msgstr "" "FULL JOIN поддерживается только с условиями, допускающими соединение " "слиянием или хеш-соединение" -#: optimizer/plan/createplan.c:7111 parser/parse_merge.c:187 -#: parser/parse_merge.c:194 +#: optimizer/plan/createplan.c:7175 parser/parse_merge.c:203 +#: rewrite/rewriteHandler.c:1680 #, c-format msgid "cannot execute MERGE on relation \"%s\"" -msgstr "выполнить MERGE для отношение \"%s\" нельзя" +msgstr "выполнить MERGE для отношения \"%s\" нельзя" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1408 +#: optimizer/plan/initsplan.c:1407 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "%s не может применяться к NULL-содержащей стороне внешнего соединения" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1361 parser/analyze.c:1772 parser/analyze.c:2029 -#: parser/analyze.c:3242 +#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 +#: parser/analyze.c:3247 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s несовместимо с UNION/INTERSECT/EXCEPT" -#: optimizer/plan/planner.c:2076 optimizer/plan/planner.c:4035 +#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4108 #, c-format msgid "could not implement GROUP BY" msgstr "не удалось реализовать GROUP BY" -#: optimizer/plan/planner.c:2077 optimizer/plan/planner.c:4036 -#: optimizer/plan/planner.c:4676 optimizer/prep/prepunion.c:1053 +#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4109 +#: optimizer/plan/planner.c:4790 optimizer/prep/prepunion.c:1320 #, c-format msgid "" "Some of the datatypes only support hashing, while others only support " @@ -17794,77 +18302,77 @@ msgstr "" "Одни типы данных поддерживают только хеширование, а другие - только " "сортировку." -#: optimizer/plan/planner.c:4675 +#: optimizer/plan/planner.c:4789 #, c-format msgid "could not implement DISTINCT" msgstr "не удалось реализовать DISTINCT" -#: optimizer/plan/planner.c:6014 +#: optimizer/plan/planner.c:6134 #, c-format msgid "could not implement window PARTITION BY" msgstr "не удалось реализовать PARTITION BY для окна" -#: optimizer/plan/planner.c:6015 +#: optimizer/plan/planner.c:6135 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "Столбцы, разбивающие окна, должны иметь сортируемые типы данных." -#: optimizer/plan/planner.c:6019 +#: optimizer/plan/planner.c:6139 #, c-format msgid "could not implement window ORDER BY" msgstr "не удалось реализовать ORDER BY для окна" -#: optimizer/plan/planner.c:6020 +#: optimizer/plan/planner.c:6140 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "Столбцы, сортирующие окна, должны иметь сортируемые типы данных." -#: optimizer/prep/prepunion.c:516 +#: optimizer/prep/prepunion.c:467 #, c-format msgid "could not implement recursive UNION" msgstr "не удалось реализовать рекурсивный UNION" -#: optimizer/prep/prepunion.c:517 +#: optimizer/prep/prepunion.c:468 #, c-format msgid "All column datatypes must be hashable." msgstr "Все столбцы должны иметь хешируемые типы данных." #. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1052 +#: optimizer/prep/prepunion.c:1319 #, c-format msgid "could not implement %s" msgstr "не удалось реализовать %s" -#: optimizer/util/clauses.c:4933 +#: optimizer/util/clauses.c:4963 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "внедрённая в код SQL-функция \"%s\"" -#: optimizer/util/plancat.c:154 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "" "обращаться к временным или нежурналируемым отношениям в процессе " "восстановления нельзя" -#: optimizer/util/plancat.c:726 +#: optimizer/util/plancat.c:768 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "" "указания со ссылкой на всю строку для выбора уникального индекса не " "поддерживаются" -#: optimizer/util/plancat.c:743 +#: optimizer/util/plancat.c:785 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "ограничению в ON CONFLICT не соответствует индекс" -#: optimizer/util/plancat.c:793 +#: optimizer/util/plancat.c:835 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATE не поддерживается с ограничениями-исключениями" -#: optimizer/util/plancat.c:898 +#: optimizer/util/plancat.c:945 #, c-format msgid "" "there is no unique or exclusion constraint matching the ON CONFLICT " @@ -17873,22 +18381,22 @@ msgstr "" "нет уникального ограничения или ограничения-исключения, соответствующего " "указанию ON CONFLICT" -#: parser/analyze.c:826 parser/analyze.c:1551 +#: parser/analyze.c:824 parser/analyze.c:1550 #, c-format msgid "VALUES lists must all be the same length" msgstr "списки VALUES должны иметь одинаковую длину" -#: parser/analyze.c:1028 +#: parser/analyze.c:1027 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT содержит больше выражений, чем целевых столбцов" -#: parser/analyze.c:1046 +#: parser/analyze.c:1045 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERT содержит больше целевых столбцов, чем выражений" -#: parser/analyze.c:1050 +#: parser/analyze.c:1049 #, c-format msgid "" "The insertion source is a row expression containing the same number of " @@ -17897,13 +18405,13 @@ msgstr "" "Источником данных является строка, включающая столько же столбцов, сколько " "требуется для INSERT. Вы намеренно использовали скобки?" -#: parser/analyze.c:1358 parser/analyze.c:1745 +#: parser/analyze.c:1357 parser/analyze.c:1744 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO здесь не допускается" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1674 parser/analyze.c:3474 +#: parser/analyze.c:1673 parser/analyze.c:3479 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s нельзя применять к VALUES" @@ -17947,12 +18455,17 @@ msgstr "" msgid "each %s query must have the same number of columns" msgstr "все запросы в %s должны возвращать одинаковое число столбцов" -#: parser/analyze.c:2584 +#: parser/analyze.c:2535 +#, c-format +msgid "SET target columns cannot be qualified with the relation name." +msgstr "К именам целевых столбцов в SET нельзя добавлять имя отношения." + +#: parser/analyze.c:2589 #, c-format msgid "RETURNING must have at least one column" msgstr "в RETURNING должен быть минимум один столбец" -#: parser/analyze.c:2687 +#: parser/analyze.c:2692 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" @@ -17960,234 +18473,234 @@ msgstr[0] "источник присваиваемого значения выд msgstr[1] "источник присваиваемого значения выдал %d столбца" msgstr[2] "источник присваиваемого значения выдал %d столбцов" -#: parser/analyze.c:2748 +#: parser/analyze.c:2753 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "переменная \"%s\" имеет тип %s, а выражение - тип %s" #. translator: %s is a SQL keyword -#: parser/analyze.c:2873 parser/analyze.c:2881 +#: parser/analyze.c:2878 parser/analyze.c:2886 #, c-format msgid "cannot specify both %s and %s" msgstr "указать %s и %s одновременно нельзя" -#: parser/analyze.c:2901 +#: parser/analyze.c:2906 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR не может содержать операторы, изменяющие данные, в WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2909 +#: parser/analyze.c:2914 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s не поддерживается" -#: parser/analyze.c:2912 +#: parser/analyze.c:2917 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "Сохраняемые курсоры должны быть READ ONLY." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2920 +#: parser/analyze.c:2925 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s не поддерживается" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2931 +#: parser/analyze.c:2936 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s не допускается" -#: parser/analyze.c:2934 +#: parser/analyze.c:2939 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "Независимые курсоры должны быть READ ONLY." -#: parser/analyze.c:3028 +#: parser/analyze.c:3033 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "" "в материализованных представлениях не должны использоваться операторы, " "изменяющие данные в WITH" -#: parser/analyze.c:3038 +#: parser/analyze.c:3043 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "" "в материализованных представлениях не должны использоваться временные " "таблицы и представления" -#: parser/analyze.c:3048 +#: parser/analyze.c:3053 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "" "определять материализованные представления со связанными параметрами нельзя" -#: parser/analyze.c:3060 +#: parser/analyze.c:3065 #, c-format msgid "materialized views cannot be unlogged" msgstr "материализованные представления не могут быть нежурналируемыми" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3249 +#: parser/analyze.c:3254 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s несовместимо с предложением DISTINCT" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3256 +#: parser/analyze.c:3261 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s несовместимо с предложением GROUP BY" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3263 +#: parser/analyze.c:3268 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s несовместимо с предложением HAVING" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3270 +#: parser/analyze.c:3275 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s несовместимо с агрегатными функциями" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3277 +#: parser/analyze.c:3282 #, c-format msgid "%s is not allowed with window functions" msgstr "%s несовместимо с оконными функциями" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3284 +#: parser/analyze.c:3289 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "" "%s не допускается с функциями, возвращающие множества, в списке результатов" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3383 +#: parser/analyze.c:3388 #, c-format msgid "%s must specify unqualified relation names" msgstr "для %s нужно указывать неполные имена отношений" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3447 +#: parser/analyze.c:3452 #, c-format msgid "%s cannot be applied to a join" msgstr "%s нельзя применить к соединению" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3456 +#: parser/analyze.c:3461 #, c-format msgid "%s cannot be applied to a function" msgstr "%s нельзя применить к функции" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3465 +#: parser/analyze.c:3470 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s нельзя применить к табличной функции" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3483 +#: parser/analyze.c:3488 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s нельзя применить к запросу WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3492 +#: parser/analyze.c:3497 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%s нельзя применить к именованному хранилищу кортежей" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3512 +#: parser/analyze.c:3517 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "отношение \"%s\" в определении %s отсутствует в предложении FROM" -#: parser/parse_agg.c:209 parser/parse_oper.c:227 +#: parser/parse_agg.c:210 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "для типа %s не удалось найти оператор сортировки" -#: parser/parse_agg.c:211 +#: parser/parse_agg.c:212 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "Агрегатным функциям с DISTINCT необходимо сортировать входные данные." -#: parser/parse_agg.c:269 +#: parser/parse_agg.c:270 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "у GROUPING должно быть меньше 32 аргументов" -#: parser/parse_agg.c:372 +#: parser/parse_agg.c:373 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "агрегатные функции нельзя применять в условиях JOIN" -#: parser/parse_agg.c:374 +#: parser/parse_agg.c:375 msgid "grouping operations are not allowed in JOIN conditions" msgstr "операции группировки нельзя применять в условиях JOIN" -#: parser/parse_agg.c:386 +#: parser/parse_agg.c:385 msgid "" "aggregate functions are not allowed in FROM clause of their own query level" msgstr "" "агрегатные функции нельзя применять в предложении FROM их уровня запроса" -#: parser/parse_agg.c:388 +#: parser/parse_agg.c:387 msgid "" "grouping operations are not allowed in FROM clause of their own query level" msgstr "" "операции группировки нельзя применять в предложении FROM их уровня запроса" -#: parser/parse_agg.c:393 +#: parser/parse_agg.c:392 msgid "aggregate functions are not allowed in functions in FROM" msgstr "агрегатные функции нельзя применять в функциях во FROM" -#: parser/parse_agg.c:395 +#: parser/parse_agg.c:394 msgid "grouping operations are not allowed in functions in FROM" msgstr "операции группировки нельзя применять в функциях во FROM" -#: parser/parse_agg.c:403 +#: parser/parse_agg.c:402 msgid "aggregate functions are not allowed in policy expressions" msgstr "агрегатные функции нельзя применять в выражениях политик" -#: parser/parse_agg.c:405 +#: parser/parse_agg.c:404 msgid "grouping operations are not allowed in policy expressions" msgstr "операции группировки нельзя применять в выражениях политик" -#: parser/parse_agg.c:422 +#: parser/parse_agg.c:421 msgid "aggregate functions are not allowed in window RANGE" msgstr "агрегатные функции нельзя применять в указании RANGE для окна" -#: parser/parse_agg.c:424 +#: parser/parse_agg.c:423 msgid "grouping operations are not allowed in window RANGE" msgstr "операции группировки нельзя применять в указании RANGE для окна" -#: parser/parse_agg.c:429 +#: parser/parse_agg.c:428 msgid "aggregate functions are not allowed in window ROWS" msgstr "агрегатные функции нельзя применять в указании ROWS для окна" -#: parser/parse_agg.c:431 +#: parser/parse_agg.c:430 msgid "grouping operations are not allowed in window ROWS" msgstr "операции группировки нельзя применять в указании ROWS для окна" -#: parser/parse_agg.c:436 +#: parser/parse_agg.c:435 msgid "aggregate functions are not allowed in window GROUPS" msgstr "агрегатные функции нельзя применять в указании GROUPS для окна" -#: parser/parse_agg.c:438 +#: parser/parse_agg.c:437 msgid "grouping operations are not allowed in window GROUPS" msgstr "операции группировки нельзя применять в указании GROUPS для окна" -#: parser/parse_agg.c:451 +#: parser/parse_agg.c:450 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "агрегатные функции нельзя применять в условиях MERGE WHEN" -#: parser/parse_agg.c:453 +#: parser/parse_agg.c:452 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "операции группировки нельзя применять в условиях MERGE WHEN" @@ -18298,7 +18811,7 @@ msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "операции группировки нельзя применять в условиях COPY FROM WHERE" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:597 parser/parse_clause.c:1956 +#: parser/parse_agg.c:597 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "агрегатные функции нельзя применять в конструкции %s" @@ -18325,8 +18838,8 @@ msgstr "" "вызовы агрегатных функций не могут включать вызовы функций, возвращающих " "множества" -#: parser/parse_agg.c:780 parser/parse_expr.c:1700 parser/parse_expr.c:2182 -#: parser/parse_func.c:884 +#: parser/parse_agg.c:780 parser/parse_expr.c:1762 parser/parse_expr.c:2245 +#: parser/parse_func.c:885 #, c-format msgid "" "You might be able to move the set-returning function into a LATERAL FROM " @@ -18360,82 +18873,82 @@ msgstr "оконные функции нельзя применять в опр msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "оконные функции нельзя применять в условиях MERGE WHEN" -#: parser/parse_agg.c:925 +#: parser/parse_agg.c:926 msgid "window functions are not allowed in check constraints" msgstr "оконные функции нельзя применять в ограничениях-проверках" -#: parser/parse_agg.c:929 +#: parser/parse_agg.c:930 msgid "window functions are not allowed in DEFAULT expressions" msgstr "оконные функции нельзя применять в выражениях DEFAULT" -#: parser/parse_agg.c:932 +#: parser/parse_agg.c:933 msgid "window functions are not allowed in index expressions" msgstr "оконные функции нельзя применять в выражениях индексов" -#: parser/parse_agg.c:935 +#: parser/parse_agg.c:936 msgid "window functions are not allowed in statistics expressions" msgstr "оконные функции нельзя применять в выражениях статистики" -#: parser/parse_agg.c:938 +#: parser/parse_agg.c:939 msgid "window functions are not allowed in index predicates" msgstr "оконные функции нельзя применять в предикатах индексов" -#: parser/parse_agg.c:941 +#: parser/parse_agg.c:942 msgid "window functions are not allowed in transform expressions" msgstr "оконные функции нельзя применять в выражениях преобразований" -#: parser/parse_agg.c:944 +#: parser/parse_agg.c:945 msgid "window functions are not allowed in EXECUTE parameters" msgstr "оконные функции нельзя применять в параметрах EXECUTE" -#: parser/parse_agg.c:947 +#: parser/parse_agg.c:948 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "оконные функции нельзя применять в условиях WHEN для триггеров" -#: parser/parse_agg.c:950 +#: parser/parse_agg.c:951 msgid "window functions are not allowed in partition bound" msgstr "оконные функции нельзя применять в выражении границы секции" -#: parser/parse_agg.c:953 +#: parser/parse_agg.c:954 msgid "window functions are not allowed in partition key expressions" msgstr "оконные функции нельзя применять в выражениях ключа секционирования" -#: parser/parse_agg.c:956 +#: parser/parse_agg.c:957 msgid "window functions are not allowed in CALL arguments" msgstr "оконные функции нельзя применять в аргументах CALL" -#: parser/parse_agg.c:959 +#: parser/parse_agg.c:960 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "оконные функции нельзя применять в условиях COPY FROM WHERE" -#: parser/parse_agg.c:962 +#: parser/parse_agg.c:963 msgid "window functions are not allowed in column generation expressions" msgstr "оконные функции нельзя применять в выражениях генерируемых столбцов" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:985 parser/parse_clause.c:1965 +#: parser/parse_agg.c:986 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "оконные функции нельзя применять в конструкции %s" -#: parser/parse_agg.c:1019 parser/parse_clause.c:2798 +#: parser/parse_agg.c:1020 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "окно \"%s\" не существует" -#: parser/parse_agg.c:1107 +#: parser/parse_agg.c:1108 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "слишком много наборов группирования (при максимуме 4096)" -#: parser/parse_agg.c:1247 +#: parser/parse_agg.c:1248 #, c-format msgid "" "aggregate functions are not allowed in a recursive query's recursive term" msgstr "" "в рекурсивной части рекурсивного запроса агрегатные функции недопустимы" -#: parser/parse_agg.c:1440 +#: parser/parse_agg.c:1441 #, c-format msgid "" "column \"%s.%s\" must appear in the GROUP BY clause or be used in an " @@ -18444,7 +18957,7 @@ msgstr "" "столбец \"%s.%s\" должен фигурировать в предложении GROUP BY или " "использоваться в агрегатной функции" -#: parser/parse_agg.c:1443 +#: parser/parse_agg.c:1444 #, c-format msgid "" "Direct arguments of an ordered-set aggregate must use only grouped columns." @@ -18452,13 +18965,13 @@ msgstr "" "Прямые аргументы сортирующей агрегатной функции могут включать только " "группируемые столбцы." -#: parser/parse_agg.c:1448 +#: parser/parse_agg.c:1449 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "" "подзапрос использует негруппированный столбец \"%s.%s\" из внешнего запроса" -#: parser/parse_agg.c:1612 +#: parser/parse_agg.c:1613 #, c-format msgid "" "arguments to GROUPING must be grouping expressions of the associated query " @@ -18467,25 +18980,25 @@ msgstr "" "аргументами GROUPING должны быть выражения группирования для " "соответствующего уровня запроса" -#: parser/parse_clause.c:195 +#: parser/parse_clause.c:193 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "отношение \"%s\" не может быть целевым в операторе, изменяющем данные" -#: parser/parse_clause.c:571 parser/parse_clause.c:599 parser/parse_func.c:2552 +#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "" "функции, возвращающие множества, должны находиться на верхнем уровне FROM" -#: parser/parse_clause.c:611 +#: parser/parse_clause.c:609 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "" "для одной и той же функции нельзя задать разные списки с определениями " "столбцов" -#: parser/parse_clause.c:644 +#: parser/parse_clause.c:642 #, c-format msgid "" "ROWS FROM() with multiple functions cannot have a column definition list" @@ -18493,7 +19006,7 @@ msgstr "" "у ROWS FROM() с несколькими функциями не может быть списка с определениями " "столбцов" -#: parser/parse_clause.c:645 +#: parser/parse_clause.c:643 #, c-format msgid "" "Put a separate column definition list for each function inside ROWS FROM()." @@ -18501,14 +19014,14 @@ msgstr "" "Добавьте отдельные списки с определениями столбцов для каждой функции в ROWS " "FROM()." -#: parser/parse_clause.c:651 +#: parser/parse_clause.c:649 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "" "у UNNEST() с несколькими аргументами не может быть списка с определениями " "столбцов" -#: parser/parse_clause.c:652 +#: parser/parse_clause.c:650 #, c-format msgid "" "Use separate UNNEST() calls inside ROWS FROM(), and attach a column " @@ -18517,43 +19030,43 @@ msgstr "" "Напишите отдельные вызовы UNNEST() внутри ROWS FROM() и добавьте список " "определений столбцов к каждому." -#: parser/parse_clause.c:659 +#: parser/parse_clause.c:657 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "" "WITH ORDINALITY нельзя использовать со списком с определениями столбцов" -#: parser/parse_clause.c:660 +#: parser/parse_clause.c:658 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "Поместите список определений столбцов внутрь ROWS FROM()." -#: parser/parse_clause.c:760 +#: parser/parse_clause.c:762 parser/parse_jsontable.c:295 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "FOR ORDINALITY допускается только для одного столбца" -#: parser/parse_clause.c:821 +#: parser/parse_clause.c:823 #, c-format msgid "column name \"%s\" is not unique" msgstr "имя столбца \"%s\" не уникально" -#: parser/parse_clause.c:863 +#: parser/parse_clause.c:865 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "имя пространства имён \"%s\" не уникально" -#: parser/parse_clause.c:873 +#: parser/parse_clause.c:875 #, c-format msgid "only one default namespace is allowed" msgstr "допускается только одно пространство имён по умолчанию" -#: parser/parse_clause.c:933 +#: parser/parse_clause.c:935 #, c-format msgid "tablesample method %s does not exist" msgstr "метод %s для получения выборки не существует" -#: parser/parse_clause.c:955 +#: parser/parse_clause.c:957 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" @@ -18561,104 +19074,104 @@ msgstr[0] "метод %s для получения выборки требует msgstr[1] "метод %s для получения выборки требует аргументов: %d, получено: %d" msgstr[2] "метод %s для получения выборки требует аргументов: %d, получено: %d" -#: parser/parse_clause.c:989 +#: parser/parse_clause.c:991 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "метод %s для получения выборки не поддерживает REPEATABLE" -#: parser/parse_clause.c:1138 +#: parser/parse_clause.c:1144 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "" "предложение TABLESAMPLE можно применять только к таблицам и " "материализованным представлениям" -#: parser/parse_clause.c:1325 +#: parser/parse_clause.c:1331 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "имя столбца \"%s\" фигурирует в предложении USING неоднократно" -#: parser/parse_clause.c:1340 +#: parser/parse_clause.c:1346 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "имя общего столбца \"%s\" фигурирует в таблице слева неоднократно" -#: parser/parse_clause.c:1349 +#: parser/parse_clause.c:1355 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "в таблице слева нет столбца \"%s\", указанного в предложении USING" -#: parser/parse_clause.c:1364 +#: parser/parse_clause.c:1370 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "имя общего столбца \"%s\" фигурирует в таблице справа неоднократно" -#: parser/parse_clause.c:1373 +#: parser/parse_clause.c:1379 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "в таблице справа нет столбца \"%s\", указанного в предложении USING" -#: parser/parse_clause.c:1901 +#: parser/parse_clause.c:1907 #, c-format msgid "row count cannot be null in FETCH FIRST ... WITH TIES clause" msgstr "" "количество строк в FETCH FIRST ... WITH TIES должно быть отличным от NULL" #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_clause.c:1926 +#: parser/parse_clause.c:1932 #, c-format msgid "argument of %s must not contain variables" msgstr "аргумент %s не может содержать переменные" #. translator: first %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2091 +#: parser/parse_clause.c:2097 #, c-format msgid "%s \"%s\" is ambiguous" msgstr "выражение %s \"%s\" неоднозначно" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2119 +#: parser/parse_clause.c:2125 #, c-format msgid "non-integer constant in %s" msgstr "не целочисленная константа в %s" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2141 +#: parser/parse_clause.c:2147 #, c-format msgid "%s position %d is not in select list" msgstr "в списке выборки %s нет элемента %d" -#: parser/parse_clause.c:2580 +#: parser/parse_clause.c:2586 #, c-format msgid "CUBE is limited to 12 elements" msgstr "CUBE имеет ограничение в 12 элементов" -#: parser/parse_clause.c:2786 +#: parser/parse_clause.c:2792 #, c-format msgid "window \"%s\" is already defined" msgstr "окно \"%s\" уже определено" -#: parser/parse_clause.c:2847 +#: parser/parse_clause.c:2853 #, c-format msgid "cannot override PARTITION BY clause of window \"%s\"" msgstr "переопределить предложение PARTITION BY для окна \"%s\" нельзя" -#: parser/parse_clause.c:2859 +#: parser/parse_clause.c:2865 #, c-format msgid "cannot override ORDER BY clause of window \"%s\"" msgstr "переопределить предложение ORDER BY для окна \"%s\" нельзя" -#: parser/parse_clause.c:2889 parser/parse_clause.c:2895 +#: parser/parse_clause.c:2895 parser/parse_clause.c:2901 #, c-format msgid "cannot copy window \"%s\" because it has a frame clause" msgstr "скопировать окно \"%s\", имеющее предложение рамки, нельзя" -#: parser/parse_clause.c:2897 +#: parser/parse_clause.c:2903 #, c-format msgid "Omit the parentheses in this OVER clause." msgstr "Уберите скобки в предложении OVER." -#: parser/parse_clause.c:2917 +#: parser/parse_clause.c:2923 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column" @@ -18666,12 +19179,12 @@ msgstr "" "для RANGE со смещением PRECEDING/FOLLOWING требуется ровно один столбец в " "ORDER BY" -#: parser/parse_clause.c:2940 +#: parser/parse_clause.c:2946 #, c-format msgid "GROUPS mode requires an ORDER BY clause" msgstr "для режима GROUPS требуется предложение ORDER BY" -#: parser/parse_clause.c:3011 +#: parser/parse_clause.c:3016 #, c-format msgid "" "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument " @@ -18680,68 +19193,68 @@ msgstr "" "для агрегатной функции с DISTINCT, выражения ORDER BY должны быть в списке " "аргументов" -#: parser/parse_clause.c:3012 +#: parser/parse_clause.c:3017 #, c-format msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list" msgstr "" "в конструкции SELECT DISTINCT выражения ORDER BY должны быть в списке выборки" -#: parser/parse_clause.c:3044 +#: parser/parse_clause.c:3049 #, c-format msgid "an aggregate with DISTINCT must have at least one argument" msgstr "агрегатной функции с DISTINCT нужен минимум один аргумент" -#: parser/parse_clause.c:3045 +#: parser/parse_clause.c:3050 #, c-format msgid "SELECT DISTINCT must have at least one column" msgstr "в SELECT DISTINCT нужен минимум один столбец" -#: parser/parse_clause.c:3111 parser/parse_clause.c:3143 +#: parser/parse_clause.c:3116 parser/parse_clause.c:3148 #, c-format msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions" msgstr "" "выражения SELECT DISTINCT ON должны соответствовать начальным выражениям " "ORDER BY" -#: parser/parse_clause.c:3221 +#: parser/parse_clause.c:3226 #, c-format msgid "ASC/DESC is not allowed in ON CONFLICT clause" msgstr "ASC/DESC нельзя использовать в ON CONFLICT" -#: parser/parse_clause.c:3227 +#: parser/parse_clause.c:3232 #, c-format msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause" msgstr "NULLS FIRST/LAST нельзя использовать в ON CONFLICT" -#: parser/parse_clause.c:3306 +#: parser/parse_clause.c:3311 #, c-format msgid "" "ON CONFLICT DO UPDATE requires inference specification or constraint name" msgstr "" "в ON CONFLICT DO UPDATE требуется наводящее указание или имя ограничения" -#: parser/parse_clause.c:3307 +#: parser/parse_clause.c:3312 #, c-format msgid "For example, ON CONFLICT (column_name)." msgstr "Например: ON CONFLICT (имя_столбца)." -#: parser/parse_clause.c:3318 +#: parser/parse_clause.c:3323 #, c-format msgid "ON CONFLICT is not supported with system catalog tables" msgstr "ON CONFLICT с таблицами системного каталога не поддерживается" -#: parser/parse_clause.c:3326 +#: parser/parse_clause.c:3331 #, c-format msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table" msgstr "" "ON CONFLICT не поддерживается для таблицы \"%s\", служащей таблицей каталога" -#: parser/parse_clause.c:3457 +#: parser/parse_clause.c:3462 #, c-format msgid "operator %s is not a valid ordering operator" msgstr "оператор %s не годится для сортировки" -#: parser/parse_clause.c:3459 +#: parser/parse_clause.c:3464 #, c-format msgid "" "Ordering operators must be \"<\" or \">\" members of btree operator families." @@ -18749,14 +19262,14 @@ msgstr "" "Операторы сортировки должны быть членами \"<\" или \">\" семейств операторов " "btree." -#: parser/parse_clause.c:3770 +#: parser/parse_clause.c:3775 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "" "RANGE со смещением PRECEDING/FOLLOWING не поддерживается для типа столбца %s" -#: parser/parse_clause.c:3776 +#: parser/parse_clause.c:3781 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s " @@ -18765,12 +19278,12 @@ msgstr "" "RANGE со смещением PRECEDING/FOLLOWING не поддерживается для типа столбца %s " "и типа смещения %s" -#: parser/parse_clause.c:3779 +#: parser/parse_clause.c:3784 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "Приведите значение смещения к подходящему типу." -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3789 #, c-format msgid "" "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for " @@ -18779,15 +19292,15 @@ msgstr "" "RANGE со смещением PRECEDING/FOLLOWING допускает несколько интерпретаций для " "типа столбца %s и типа смещения %s" -#: parser/parse_clause.c:3787 +#: parser/parse_clause.c:3792 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "Приведите значение смещения в точности к желаемому типу." #: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 #: parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 -#: parser/parse_expr.c:2083 parser/parse_expr.c:2691 parser/parse_expr.c:3497 -#: parser/parse_target.c:999 +#: parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3405 +#: parser/parse_expr.c:3634 parser/parse_target.c:998 #, c-format msgid "cannot cast type %s to %s" msgstr "привести тип %s к %s нельзя" @@ -18822,112 +19335,112 @@ msgid "argument of %s must not return a set" msgstr "аргумент конструкции %s не должен возвращать множество" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1383 +#: parser/parse_coerce.c:1420 #, c-format msgid "%s types %s and %s cannot be matched" msgstr "в конструкции %s типы %s и %s не имеют общего" -#: parser/parse_coerce.c:1499 +#: parser/parse_coerce.c:1536 #, c-format msgid "argument types %s and %s cannot be matched" msgstr "типы аргументов %s и %s не имеют общего" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1551 +#: parser/parse_coerce.c:1588 #, c-format msgid "%s could not convert type %s to %s" msgstr "в конструкции %s нельзя преобразовать тип %s в %s" -#: parser/parse_coerce.c:2154 parser/parse_coerce.c:2174 -#: parser/parse_coerce.c:2194 parser/parse_coerce.c:2215 -#: parser/parse_coerce.c:2270 parser/parse_coerce.c:2304 +#: parser/parse_coerce.c:2191 parser/parse_coerce.c:2211 +#: parser/parse_coerce.c:2231 parser/parse_coerce.c:2252 +#: parser/parse_coerce.c:2307 parser/parse_coerce.c:2341 #, c-format msgid "arguments declared \"%s\" are not all alike" msgstr "аргументы, объявленные как \"%s\", должны быть однотипными" -#: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 +#: parser/parse_coerce.c:2286 parser/parse_coerce.c:2399 #: utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "аргумент, объявленный как \"%s\", оказался не массивом, а типом %s" -#: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 +#: parser/parse_coerce.c:2319 parser/parse_coerce.c:2469 #: utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "аргумент, объявленный как \"%s\", имеет не диапазонный тип, а %s" -#: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 -#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 +#: parser/parse_coerce.c:2353 parser/parse_coerce.c:2433 +#: parser/parse_coerce.c:2566 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "аргумент, объявленный как \"%s\", имеет не мультидиапазонный тип, а %s" -#: parser/parse_coerce.c:2353 +#: parser/parse_coerce.c:2390 #, c-format msgid "cannot determine element type of \"anyarray\" argument" msgstr "тип элемента аргумента \"anyarray\" определить нельзя" -#: parser/parse_coerce.c:2379 parser/parse_coerce.c:2410 -#: parser/parse_coerce.c:2449 parser/parse_coerce.c:2515 +#: parser/parse_coerce.c:2416 parser/parse_coerce.c:2447 +#: parser/parse_coerce.c:2486 parser/parse_coerce.c:2552 #, c-format msgid "argument declared %s is not consistent with argument declared %s" msgstr "аргумент, объявленный как \"%s\", не согласуется с аргументом %s" -#: parser/parse_coerce.c:2474 +#: parser/parse_coerce.c:2511 #, c-format msgid "could not determine polymorphic type because input has type %s" msgstr "" "не удалось определить полиморфный тип, так как входные аргументы имеют тип %s" -#: parser/parse_coerce.c:2488 +#: parser/parse_coerce.c:2525 #, c-format msgid "type matched to anynonarray is an array type: %s" msgstr "" "в нарушение объявления \"anynonarray\" соответствующий аргумент оказался " "массивом: %s" -#: parser/parse_coerce.c:2498 +#: parser/parse_coerce.c:2535 #, c-format msgid "type matched to anyenum is not an enum type: %s" msgstr "" "в нарушение объявления \"anyenum\" соответствующий аргумент оказался не " "перечислением: %s" -#: parser/parse_coerce.c:2559 +#: parser/parse_coerce.c:2596 #, c-format msgid "arguments of anycompatible family cannot be cast to a common type" msgstr "" "аргументы семейства anycompatible не могут быть приведены к общему типу" -#: parser/parse_coerce.c:2577 parser/parse_coerce.c:2598 -#: parser/parse_coerce.c:2648 parser/parse_coerce.c:2653 -#: parser/parse_coerce.c:2717 parser/parse_coerce.c:2729 +#: parser/parse_coerce.c:2614 parser/parse_coerce.c:2635 +#: parser/parse_coerce.c:2685 parser/parse_coerce.c:2690 +#: parser/parse_coerce.c:2754 parser/parse_coerce.c:2766 #, c-format msgid "could not determine polymorphic type %s because input has type %s" msgstr "" "не удалось определить полиморфный тип %s, так как входные аргументы имеют " "тип %s" -#: parser/parse_coerce.c:2587 +#: parser/parse_coerce.c:2624 #, c-format msgid "anycompatiblerange type %s does not match anycompatible type %s" msgstr "тип %s (anycompatiblerange) не соответствует типу %s (anycompatible)" -#: parser/parse_coerce.c:2608 +#: parser/parse_coerce.c:2645 #, c-format msgid "anycompatiblemultirange type %s does not match anycompatible type %s" msgstr "" "тип %s (anycompatiblemultirange) не соответствует типу %s (anycompatible)" -#: parser/parse_coerce.c:2622 +#: parser/parse_coerce.c:2659 #, c-format msgid "type matched to anycompatiblenonarray is an array type: %s" msgstr "" "в нарушение объявления \"anycompatiblenonarray\" соответствующий аргумент " "оказался массивом: %s" -#: parser/parse_coerce.c:2857 +#: parser/parse_coerce.c:2894 #, c-format msgid "" "A result of type %s requires at least one input of type anyrange or " @@ -18936,7 +19449,7 @@ msgstr "" "Для результата типа %s требуется минимум один аргумент типа anyrange или " "anymultirange." -#: parser/parse_coerce.c:2874 +#: parser/parse_coerce.c:2911 #, c-format msgid "" "A result of type %s requires at least one input of type anycompatiblerange " @@ -18945,7 +19458,7 @@ msgstr "" "Для результата типа %s требуется минимум один аргумент типа " "anycompatiblerange или anycompatiblemultirange." -#: parser/parse_coerce.c:2886 +#: parser/parse_coerce.c:2923 #, c-format msgid "" "A result of type %s requires at least one input of type anyelement, " @@ -18954,7 +19467,7 @@ msgstr "" "Для результата типа %s требуется минимум один аргумент типа anyelement, " "anyarray, anynonarray, anyenum, anyrange или anymultirange." -#: parser/parse_coerce.c:2898 +#: parser/parse_coerce.c:2935 #, c-format msgid "" "A result of type %s requires at least one input of type anycompatible, " @@ -18965,7 +19478,7 @@ msgstr "" "anycompatiblearray, anycompatiblenonarray, anycompatiblerange или " "anycompatiblemultirange." -#: parser/parse_coerce.c:2928 +#: parser/parse_coerce.c:2965 msgid "A result of type internal requires at least one input of type internal." msgstr "" "Для результата типа internal требуется минимум один аргумент типа internal." @@ -19024,22 +19537,17 @@ msgstr "рекурсивная ссылка на запрос \"%s\" не дол msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "рекурсивная ссылка на запрос \"%s\" не должна фигурировать в EXCEPT" -#: parser/parse_cte.c:133 -#, c-format -msgid "MERGE not supported in WITH query" -msgstr "MERGE не поддерживается в запросе WITH" - -#: parser/parse_cte.c:143 +#: parser/parse_cte.c:136 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "имя запроса WITH \"%s\" указано неоднократно" -#: parser/parse_cte.c:314 +#: parser/parse_cte.c:308 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "не удалось найти оператор неравенства для типа %s" -#: parser/parse_cte.c:341 +#: parser/parse_cte.c:335 #, c-format msgid "" "WITH clause containing a data-modifying statement must be at the top level" @@ -19047,7 +19555,7 @@ msgstr "" "предложение WITH, содержащее оператор, изменяющий данные, должно быть на " "верхнем уровне" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:384 #, c-format msgid "" "recursive query \"%s\" column %d has type %s in non-recursive term but type " @@ -19056,12 +19564,12 @@ msgstr "" "в рекурсивном запросе \"%s\" столбец %d имеет тип %s в нерекурсивной части, " "но в результате тип %s" -#: parser/parse_cte.c:396 +#: parser/parse_cte.c:390 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "Приведите результат нерекурсивной части к правильному типу." -#: parser/parse_cte.c:401 +#: parser/parse_cte.c:395 #, c-format msgid "" "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term " @@ -19070,43 +19578,43 @@ msgstr "" "в рекурсивном запросе \"%s\" у столбца %d правило сортировки \"%s\" в не " "рекурсивной части, но в результате правило \"%s\"" -#: parser/parse_cte.c:405 +#: parser/parse_cte.c:399 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "" "Измените правило сортировки в нерекурсивной части, добавив предложение " "COLLATE." -#: parser/parse_cte.c:426 +#: parser/parse_cte.c:420 #, c-format msgid "WITH query is not recursive" msgstr "запрос WITH не рекурсивный" -#: parser/parse_cte.c:457 +#: parser/parse_cte.c:451 #, c-format msgid "" "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "" "с предложением SEARCH или CYCLE в левой стороне UNION должен быть SELECT" -#: parser/parse_cte.c:462 +#: parser/parse_cte.c:456 #, c-format msgid "" "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "" "с предложением SEARCH или CYCLE в правой стороне UNION должен быть SELECT" -#: parser/parse_cte.c:477 +#: parser/parse_cte.c:471 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "столбец поиска \"%s\" отсутствует в списке столбцов запроса WITH" -#: parser/parse_cte.c:484 +#: parser/parse_cte.c:478 #, c-format msgid "search column \"%s\" specified more than once" msgstr "столбец поиска \"%s\" указан неоднократно" -#: parser/parse_cte.c:493 +#: parser/parse_cte.c:487 #, c-format msgid "" "search sequence column name \"%s\" already used in WITH query column list" @@ -19114,64 +19622,64 @@ msgstr "" "имя столбца последовательности поиска \"%s\" уже используется в списке " "столбцов запроса WITH" -#: parser/parse_cte.c:510 +#: parser/parse_cte.c:504 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "столбец цикла \"%s\" отсутствует в списке столбцов запроса WITH" -#: parser/parse_cte.c:517 +#: parser/parse_cte.c:511 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "столбец цикла \"%s\" указан неоднократно" -#: parser/parse_cte.c:526 +#: parser/parse_cte.c:520 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "" "имя столбца пометки цикла \"%s\" уже используется в списке столбцов запроса " "WITH" -#: parser/parse_cte.c:533 +#: parser/parse_cte.c:527 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "" "имя столбца пути цикла \"%s\" уже используется в списке столбцов запроса WITH" -#: parser/parse_cte.c:541 +#: parser/parse_cte.c:535 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "имя столбца пометки цикла совпадает с именем столбца пути цикла" -#: parser/parse_cte.c:551 +#: parser/parse_cte.c:545 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "" "имя столбца последовательности поиска совпадает с именем столбца пометки " "цикла" -#: parser/parse_cte.c:558 +#: parser/parse_cte.c:552 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "" "имя столбца последовательности поиска совпадает с именем столбца пути цикла" -#: parser/parse_cte.c:642 +#: parser/parse_cte.c:636 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "запрос WITH \"%s\" содержит столбцов: %d, но указано: %d" -#: parser/parse_cte.c:822 +#: parser/parse_cte.c:816 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "взаимная рекурсия между элементами WITH не реализована" -#: parser/parse_cte.c:874 +#: parser/parse_cte.c:868 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "" "рекурсивный запрос \"%s\" не должен содержать операторов, изменяющих данные" -#: parser/parse_cte.c:882 +#: parser/parse_cte.c:876 #, c-format msgid "" "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] " @@ -19180,102 +19688,110 @@ msgstr "" "рекурсивный запрос \"%s\" должен иметь форму {нерекурсивная часть} UNION " "[ALL] {рекурсивная часть}" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:911 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "ORDER BY в рекурсивном запросе не поддерживается" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:917 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "OFFSET в рекурсивном запросе не поддерживается" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:923 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "LIMIT в рекурсивном запросе не поддерживается" -#: parser/parse_cte.c:944 +#: parser/parse_cte.c:929 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "FOR UPDATE/SHARE в рекурсивном запросе не поддерживается" -#: parser/parse_cte.c:1001 +#: parser/parse_cte.c:1008 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "рекурсивная ссылка на запрос \"%s\" указана неоднократно" -#: parser/parse_expr.c:294 +#: parser/parse_expr.c:313 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "DEFAULT не допускается в данном контексте" -#: parser/parse_expr.c:371 parser/parse_relation.c:3697 -#: parser/parse_relation.c:3707 parser/parse_relation.c:3725 -#: parser/parse_relation.c:3732 parser/parse_relation.c:3746 +#: parser/parse_expr.c:406 parser/parse_relation.c:3691 +#: parser/parse_relation.c:3701 parser/parse_relation.c:3719 +#: parser/parse_relation.c:3726 parser/parse_relation.c:3740 #, c-format msgid "column %s.%s does not exist" msgstr "столбец %s.%s не существует" -#: parser/parse_expr.c:383 +#: parser/parse_expr.c:418 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "столбец \"%s\" не найден в типе данных %s" -#: parser/parse_expr.c:389 +#: parser/parse_expr.c:424 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "не удалось идентифицировать столбец \"%s\" в типе записи" # skip-rule: space-before-period -#: parser/parse_expr.c:395 +#: parser/parse_expr.c:430 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "" "запись имени столбца .%s применена к типу %s, который не является составным" -#: parser/parse_expr.c:426 parser/parse_target.c:733 +#: parser/parse_expr.c:461 parser/parse_target.c:732 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "расширение строки через \"*\" здесь не поддерживается" -#: parser/parse_expr.c:548 +#: parser/parse_expr.c:584 msgid "cannot use column reference in DEFAULT expression" msgstr "в выражении DEFAULT (по умолчанию) нельзя ссылаться на столбцы" -#: parser/parse_expr.c:551 +#: parser/parse_expr.c:587 msgid "cannot use column reference in partition bound expression" msgstr "в выражении границы секции нельзя ссылаться на столбцы" -#: parser/parse_expr.c:810 parser/parse_relation.c:833 -#: parser/parse_relation.c:915 parser/parse_target.c:1239 +#: parser/parse_expr.c:846 parser/parse_relation.c:833 +#: parser/parse_relation.c:915 parser/parse_target.c:1238 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "неоднозначная ссылка на столбец \"%s\"" -#: parser/parse_expr.c:866 parser/parse_param.c:110 parser/parse_param.c:142 +#: parser/parse_expr.c:902 parser/parse_param.c:110 parser/parse_param.c:142 #: parser/parse_param.c:204 parser/parse_param.c:303 #, c-format msgid "there is no parameter $%d" msgstr "параметр $%d не существует" -#: parser/parse_expr.c:1066 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1103 parser/parse_expr.c:3065 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "для NULLIF требуется, чтобы оператор = возвращал логическое значение" +msgid "%s requires = operator to yield boolean" +msgstr "для %s требуется, чтобы оператор = возвращал логическое значение" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1072 parser/parse_expr.c:3007 +#: parser/parse_expr.c:1109 parser/parse_expr.c:3072 #, c-format msgid "%s must not return a set" msgstr "%s не должна возвращать множество" -#: parser/parse_expr.c:1457 parser/parse_expr.c:1489 +#: parser/parse_expr.c:1395 +#, c-format +msgid "" +"MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" +msgstr "" +"MERGE_ACTION() может использоваться только в списке RETURNING команды MERGE" + +#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 #, c-format msgid "number of columns does not match number of values" msgstr "число столбцов не равно числу значений" -#: parser/parse_expr.c:1503 +#: parser/parse_expr.c:1565 #, c-format msgid "" "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() " @@ -19285,224 +19801,357 @@ msgstr "" "SELECT или выражение ROW()" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1698 parser/parse_expr.c:2180 parser/parse_func.c:2677 +#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "функции, возвращающие множества, нельзя применять в конструкции %s" -#: parser/parse_expr.c:1761 +#: parser/parse_expr.c:1824 msgid "cannot use subquery in check constraint" msgstr "в ограничении-проверке нельзя использовать подзапросы" -#: parser/parse_expr.c:1765 +#: parser/parse_expr.c:1828 msgid "cannot use subquery in DEFAULT expression" msgstr "в выражении DEFAULT нельзя использовать подзапросы" -#: parser/parse_expr.c:1768 +#: parser/parse_expr.c:1831 msgid "cannot use subquery in index expression" msgstr "в индексном выражении нельзя использовать подзапросы" -#: parser/parse_expr.c:1771 +#: parser/parse_expr.c:1834 msgid "cannot use subquery in index predicate" msgstr "в предикате индекса нельзя использовать подзапросы" -#: parser/parse_expr.c:1774 +#: parser/parse_expr.c:1837 msgid "cannot use subquery in statistics expression" msgstr "в выражении статистики нельзя использовать подзапросы" -#: parser/parse_expr.c:1777 +#: parser/parse_expr.c:1840 msgid "cannot use subquery in transform expression" msgstr "нельзя использовать подзапрос в выражении преобразования" -#: parser/parse_expr.c:1780 +#: parser/parse_expr.c:1843 msgid "cannot use subquery in EXECUTE parameter" msgstr "в качестве параметра EXECUTE нельзя использовать подзапрос" -#: parser/parse_expr.c:1783 +#: parser/parse_expr.c:1846 msgid "cannot use subquery in trigger WHEN condition" msgstr "в условии WHEN для триггера нельзя использовать подзапросы" -#: parser/parse_expr.c:1786 +#: parser/parse_expr.c:1849 msgid "cannot use subquery in partition bound" msgstr "в выражении границы секции нельзя использовать подзапросы" -#: parser/parse_expr.c:1789 +#: parser/parse_expr.c:1852 msgid "cannot use subquery in partition key expression" msgstr "в выражении ключа секционирования нельзя использовать подзапросы" -#: parser/parse_expr.c:1792 +#: parser/parse_expr.c:1855 msgid "cannot use subquery in CALL argument" msgstr "в качестве аргумента CALL нельзя использовать подзапрос" -#: parser/parse_expr.c:1795 +#: parser/parse_expr.c:1858 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "в условии COPY FROM WHERE нельзя использовать подзапросы" -#: parser/parse_expr.c:1798 +#: parser/parse_expr.c:1861 msgid "cannot use subquery in column generation expression" msgstr "в выражении генерируемого столбца нельзя использовать подзапросы" -#: parser/parse_expr.c:1851 parser/parse_expr.c:3628 +#: parser/parse_expr.c:1914 parser/parse_expr.c:3764 #, c-format msgid "subquery must return only one column" msgstr "подзапрос должен вернуть только один столбец" -#: parser/parse_expr.c:1922 +#: parser/parse_expr.c:1985 #, c-format msgid "subquery has too many columns" msgstr "в подзапросе слишком много столбцов" -#: parser/parse_expr.c:1927 +#: parser/parse_expr.c:1990 #, c-format msgid "subquery has too few columns" msgstr "в подзапросе недостаточно столбцов" -#: parser/parse_expr.c:2023 +#: parser/parse_expr.c:2086 #, c-format msgid "cannot determine type of empty array" msgstr "тип пустого массива определить нельзя" -#: parser/parse_expr.c:2024 +#: parser/parse_expr.c:2087 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "" "Приведите его к желаемому типу явным образом, например ARRAY[]::integer[]." -#: parser/parse_expr.c:2038 +#: parser/parse_expr.c:2101 #, c-format msgid "could not find element type for data type %s" msgstr "не удалось определить тип элемента для типа данных %s" -#: parser/parse_expr.c:2121 +#: parser/parse_expr.c:2184 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "число элементов в выражениях ROW ограничено %d" -#: parser/parse_expr.c:2326 +#: parser/parse_expr.c:2389 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "вместо значения XML-атрибута без имени должен указываться столбец" -#: parser/parse_expr.c:2327 +#: parser/parse_expr.c:2390 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "вместо значения XML-элемента без имени должен указываться столбец" -#: parser/parse_expr.c:2342 +#: parser/parse_expr.c:2405 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "имя XML-атрибута \"%s\" указано неоднократно" -#: parser/parse_expr.c:2450 +#: parser/parse_expr.c:2513 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "привести результат XMLSERIALIZE к типу %s нельзя" -#: parser/parse_expr.c:2764 parser/parse_expr.c:2960 +#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 #, c-format msgid "unequal number of entries in row expressions" msgstr "разное число элементов в строках" -#: parser/parse_expr.c:2774 +#: parser/parse_expr.c:2837 #, c-format msgid "cannot compare rows of zero length" msgstr "строки нулевой длины сравнивать нельзя" -#: parser/parse_expr.c:2799 +#: parser/parse_expr.c:2862 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "" "оператор сравнения строк должен выдавать результат логического типа, а не %s" -#: parser/parse_expr.c:2806 +#: parser/parse_expr.c:2869 #, c-format msgid "row comparison operator must not return a set" msgstr "оператор сравнения строк не должен возвращать множество" -#: parser/parse_expr.c:2865 parser/parse_expr.c:2906 +#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "не удалось выбрать интерпретацию оператора сравнения строк %s" -#: parser/parse_expr.c:2867 +#: parser/parse_expr.c:2930 #, c-format msgid "" "Row comparison operators must be associated with btree operator families." msgstr "" "Операторы сравнения строк должны быть связаны с семейством операторов btree." -#: parser/parse_expr.c:2908 +#: parser/parse_expr.c:2971 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "Оказалось несколько равноценных кандидатур." -#: parser/parse_expr.c:3001 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "" -"для IS DISTINCT FROM требуется, чтобы оператор = возвращал логическое " -"значение" - -#: parser/parse_expr.c:3239 +#: parser/parse_expr.c:3306 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "" "предложение JSON ENCODING можно добавить только для входного типа bytea" -#: parser/parse_expr.c:3261 +#: parser/parse_expr.c:3370 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "" "с неявным предложением FORMAT JSON можно использовать только строковые типы" -#: parser/parse_expr.c:3262 +#: parser/parse_expr.c:3371 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "" "с явным предложением FORMAT JSON можно использовать только строковые типы" -#: parser/parse_expr.c:3335 +#: parser/parse_expr.c:3460 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "формат JSON можно использовать, только если возвращаемый тип строковый" -#: parser/parse_expr.c:3348 +#: parser/parse_expr.c:3473 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "" "кодировку JSON можно использовать, только если возвращаемый тип — bytea" -#: parser/parse_expr.c:3353 +#: parser/parse_expr.c:3478 #, c-format msgid "unsupported JSON encoding" msgstr "неподдерживаемая кодировка JSON" -#: parser/parse_expr.c:3354 +#: parser/parse_expr.c:3479 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "Для JSON поддерживается только кодировка UTF-8." -#: parser/parse_expr.c:3391 +#: parser/parse_expr.c:3516 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "функции SQL/JSON не могут возвращать типы SETOF" -#: parser/parse_expr.c:3712 parser/parse_func.c:865 +#: parser/parse_expr.c:3521 +#, c-format +msgid "returning pseudo-types is not supported in SQL/JSON functions" +msgstr "функции SQL/JSON не могут возвращать псевдотипы" + +#: parser/parse_expr.c:3849 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "агрегатное предложение ORDER BY для оконных функций не реализовано" -#: parser/parse_expr.c:3934 +#: parser/parse_expr.c:4072 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "" "предложение JSON FORMAT ENCODING можно использовать только с типом bytea" -#: parser/parse_expr.c:3954 +#: parser/parse_expr.c:4092 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "в предикате IS JSON нельзя использовать тип %s" +#: parser/parse_expr.c:4118 parser/parse_expr.c:4239 +#, c-format +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "тип %s нельзя использовать в предложении RETURNING функции %s" + +#: parser/parse_expr.c:4120 +#, c-format +msgid "Try returning json or jsonb." +msgstr "Попробуйте возвратить тип json или jsonb." + +#: parser/parse_expr.c:4168 +#, c-format +msgid "cannot use non-string types with WITH UNIQUE KEYS clause" +msgstr "" +"с предложением WITH UNIQUE KEYS можно использовать только строковые типы " +"данных" + +#: parser/parse_expr.c:4242 +#, c-format +msgid "Try returning a string type or bytea." +msgstr "Попробуйте возвратить строковый тип или bytea." + +#: parser/parse_expr.c:4307 +#, c-format +msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgstr "FORMAT JSON не может указываться в предложении RETURNING %s()" + +#: parser/parse_expr.c:4320 +#, c-format +msgid "" +"SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" +msgstr "" +"когда используется WITH WRAPPER, поведение QUOTES в SQL/JSON задать нельзя" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4334 parser/parse_expr.c:4363 parser/parse_expr.c:4394 +#: parser/parse_expr.c:4420 parser/parse_expr.c:4446 +#: parser/parse_jsontable.c:94 +#, c-format +msgid "invalid %s behavior" +msgstr "неверное поведение %s" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4337 parser/parse_expr.c:4366 +#, c-format +msgid "" +"Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is " +"allowed in %s for %s." +msgstr "" +"В %s для %s допускается только ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT или " +"выражение DEFAULT." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4344 parser/parse_expr.c:4373 parser/parse_expr.c:4402 +#: parser/parse_expr.c:4430 parser/parse_expr.c:4456 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "неверное поведение %s для столбца \"%s\"" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4347 parser/parse_expr.c:4376 +#, c-format +msgid "" +"Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is " +"allowed in %s for formatted columns." +msgstr "" +"В %s для форматируемых столбцов допускается только ERROR, NULL, EMPTY ARRAY, " +"EMPTY OBJECT или выражение DEFAULT." + +#: parser/parse_expr.c:4395 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "В %s для %s допускается только ERROR, TRUE, FALSE или UNKNOWN." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4405 +#, c-format +msgid "" +"Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "" +"В %s для столбцов в EXISTS допускается только ERROR, TRUE, FALSE или UNKNOWN." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4423 parser/parse_expr.c:4449 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "В %s для %s допускается только ERROR, NULL или выражение DEFAULT." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4433 parser/parse_expr.c:4459 +#, c-format +msgid "" +"Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "" +"В %s для скалярных столбцов допускается только ERROR, NULL или выражение " +"DEFAULT." + +#: parser/parse_expr.c:4489 +#, c-format +msgid "JSON path expression must be of type %s, not of type %s" +msgstr "выражение пути JSON должно быть типа %s, а не типа %s" + +#: parser/parse_expr.c:4707 +#, c-format +msgid "" +"can only specify a constant, non-aggregate function, or operator expression " +"for DEFAULT" +msgstr "" +"в DEFAULT может задаваться только константа, вызов не агрегатной функции или " +"выражение с оператором" + +#: parser/parse_expr.c:4712 +#, c-format +msgid "DEFAULT expression must not contain column references" +msgstr "выражения в DEFAULT не могут содержать ссылки на столбцы" + +#: parser/parse_expr.c:4717 +#, c-format +msgid "DEFAULT expression must not return a set" +msgstr "выражение в DEFAULT не может возвращать множество" + +#: parser/parse_expr.c:4793 parser/parse_expr.c:4802 +#, c-format +msgid "cannot cast behavior expression of type %s to %s" +msgstr "привести выражение поведения, имеющее тип %s, к типу %s нельзя" + +#: parser/parse_expr.c:4796 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "Приведите выражение к типу %s явно." + #: parser/parse_func.c:194 #, c-format msgid "argument name \"%s\" used more than once" @@ -19513,7 +20162,7 @@ msgstr "имя аргумента \"%s\" используется неоднок msgid "positional argument cannot follow named argument" msgstr "нумерованный аргумент не может следовать за именованным аргументом" -#: parser/parse_func.c:287 parser/parse_func.c:2367 +#: parser/parse_func.c:287 parser/parse_func.c:2368 #, c-format msgid "%s is not a procedure" msgstr "\"%s\" — не процедура" @@ -19675,7 +20324,7 @@ msgstr "" "Возможно, неверно расположено предложение ORDER BY - оно должно следовать за " "всеми обычными аргументами функции." -#: parser/parse_func.c:622 parser/parse_func.c:2410 +#: parser/parse_func.c:622 parser/parse_func.c:2411 #, c-format msgid "procedure %s does not exist" msgstr "процедура %s не существует" @@ -19703,7 +20352,7 @@ msgstr "" msgid "VARIADIC argument must be an array" msgstr "параметр VARIADIC должен быть массивом" -#: parser/parse_func.c:791 parser/parse_func.c:855 +#: parser/parse_func.c:791 parser/parse_func.c:856 #, c-format msgid "%s(*) must be used to call a parameterless aggregate function" msgstr "агрегатная функция без параметров должна вызываться так: %s(*)" @@ -19718,44 +20367,44 @@ msgstr "агрегатные функции не могут возвращать msgid "aggregates cannot use named arguments" msgstr "у агрегатных функций не может быть именованных аргументов" -#: parser/parse_func.c:845 +#: parser/parse_func.c:846 #, c-format msgid "DISTINCT is not implemented for window functions" msgstr "предложение DISTINCT для оконных функций не реализовано" -#: parser/parse_func.c:874 +#: parser/parse_func.c:875 #, c-format msgid "FILTER is not implemented for non-aggregate window functions" msgstr "предложение FILTER для не агрегатных оконных функций не реализовано" -#: parser/parse_func.c:883 +#: parser/parse_func.c:884 #, c-format msgid "window function calls cannot contain set-returning function calls" msgstr "" "вызовы оконных функций не могут включать вызовы функций, возвращающих " "множества" -#: parser/parse_func.c:891 +#: parser/parse_func.c:892 #, c-format msgid "window functions cannot return sets" msgstr "оконные функции не могут возвращать множества" -#: parser/parse_func.c:2166 parser/parse_func.c:2439 +#: parser/parse_func.c:2167 parser/parse_func.c:2440 #, c-format msgid "could not find a function named \"%s\"" msgstr "не удалось найти функцию с именем \"%s\"" -#: parser/parse_func.c:2180 parser/parse_func.c:2457 +#: parser/parse_func.c:2181 parser/parse_func.c:2458 #, c-format msgid "function name \"%s\" is not unique" msgstr "имя функции \"%s\" не уникально" -#: parser/parse_func.c:2182 parser/parse_func.c:2460 +#: parser/parse_func.c:2183 parser/parse_func.c:2461 #, c-format msgid "Specify the argument list to select the function unambiguously." msgstr "Задайте список аргументов для однозначного выбора функции." -#: parser/parse_func.c:2226 +#: parser/parse_func.c:2227 #, c-format msgid "procedures cannot have more than %d argument" msgid_plural "procedures cannot have more than %d arguments" @@ -19763,207 +20412,209 @@ msgstr[0] "процедуры допускают не более %d аргуме msgstr[1] "процедуры допускают не более %d аргументов" msgstr[2] "процедуры допускают не более %d аргументов" -#: parser/parse_func.c:2357 +#: parser/parse_func.c:2358 #, c-format msgid "%s is not a function" msgstr "%s — не функция" -#: parser/parse_func.c:2377 +#: parser/parse_func.c:2378 #, c-format msgid "function %s is not an aggregate" msgstr "функция \"%s\" не является агрегатной" -#: parser/parse_func.c:2405 +#: parser/parse_func.c:2406 #, c-format msgid "could not find a procedure named \"%s\"" msgstr "не удалось найти процедуру с именем \"%s\"" -#: parser/parse_func.c:2419 +#: parser/parse_func.c:2420 #, c-format msgid "could not find an aggregate named \"%s\"" msgstr "не удалось найти агрегат с именем \"%s\"" -#: parser/parse_func.c:2424 +#: parser/parse_func.c:2425 #, c-format msgid "aggregate %s(*) does not exist" msgstr "агрегатная функция %s(*) не существует" -#: parser/parse_func.c:2429 +#: parser/parse_func.c:2430 #, c-format msgid "aggregate %s does not exist" msgstr "агрегатная функция %s не существует" -#: parser/parse_func.c:2465 +#: parser/parse_func.c:2466 #, c-format msgid "procedure name \"%s\" is not unique" msgstr "имя процедуры \"%s\" не уникально" -#: parser/parse_func.c:2468 +#: parser/parse_func.c:2469 #, c-format msgid "Specify the argument list to select the procedure unambiguously." msgstr "Задайте список аргументов для однозначного выбора процедуры." -#: parser/parse_func.c:2473 +#: parser/parse_func.c:2474 #, c-format msgid "aggregate name \"%s\" is not unique" msgstr "имя агрегатной функции \"%s\" не уникально" -#: parser/parse_func.c:2476 +#: parser/parse_func.c:2477 #, c-format msgid "Specify the argument list to select the aggregate unambiguously." msgstr "Задайте список аргументов для однозначного выбора агрегатной функции." -#: parser/parse_func.c:2481 +#: parser/parse_func.c:2482 #, c-format msgid "routine name \"%s\" is not unique" msgstr "имя подпрограммы \"%s\" не уникально" -#: parser/parse_func.c:2484 +#: parser/parse_func.c:2485 #, c-format msgid "Specify the argument list to select the routine unambiguously." msgstr "Задайте список аргументов для однозначного выбора подпрограммы." -#: parser/parse_func.c:2539 +#: parser/parse_func.c:2540 msgid "set-returning functions are not allowed in JOIN conditions" msgstr "функции, возвращающие множества, нельзя применять в условиях JOIN" -#: parser/parse_func.c:2560 +#: parser/parse_func.c:2561 msgid "set-returning functions are not allowed in policy expressions" msgstr "функции, возвращающие множества, нельзя применять в выражениях политик" -#: parser/parse_func.c:2576 +#: parser/parse_func.c:2577 msgid "set-returning functions are not allowed in window definitions" msgstr "функции, возвращающие множества, нельзя применять в определении окна" -#: parser/parse_func.c:2613 +#: parser/parse_func.c:2615 msgid "set-returning functions are not allowed in MERGE WHEN conditions" msgstr "" "функции, возвращающие множества, нельзя применять в условиях MERGE WHEN" -#: parser/parse_func.c:2617 +#: parser/parse_func.c:2619 msgid "set-returning functions are not allowed in check constraints" msgstr "" "функции, возвращающие множества, нельзя применять в ограничениях-проверках" -#: parser/parse_func.c:2621 +#: parser/parse_func.c:2623 msgid "set-returning functions are not allowed in DEFAULT expressions" msgstr "функции, возвращающие множества, нельзя применять в выражениях DEFAULT" -#: parser/parse_func.c:2624 +#: parser/parse_func.c:2626 msgid "set-returning functions are not allowed in index expressions" msgstr "" "функции, возвращающие множества, нельзя применять в выражениях индексов" -#: parser/parse_func.c:2627 +#: parser/parse_func.c:2629 msgid "set-returning functions are not allowed in index predicates" msgstr "" "функции, возвращающие множества, нельзя применять в предикатах индексов" -#: parser/parse_func.c:2630 +#: parser/parse_func.c:2632 msgid "set-returning functions are not allowed in statistics expressions" msgstr "" "функции, возвращающие множества, нельзя применять в выражениях статистики" -#: parser/parse_func.c:2633 +#: parser/parse_func.c:2635 msgid "set-returning functions are not allowed in transform expressions" msgstr "" "функции, возвращающие множества, нельзя применять в выражениях преобразований" -#: parser/parse_func.c:2636 +#: parser/parse_func.c:2638 msgid "set-returning functions are not allowed in EXECUTE parameters" msgstr "функции, возвращающие множества, нельзя применять в параметрах EXECUTE" -#: parser/parse_func.c:2639 +#: parser/parse_func.c:2641 msgid "set-returning functions are not allowed in trigger WHEN conditions" msgstr "" "функции, возвращающие множества, нельзя применять в условиях WHEN для " "триггеров" -#: parser/parse_func.c:2642 +#: parser/parse_func.c:2644 msgid "set-returning functions are not allowed in partition bound" msgstr "" "функции, возвращающие множества, нельзя применять в выражении границы секции" -#: parser/parse_func.c:2645 +#: parser/parse_func.c:2647 msgid "set-returning functions are not allowed in partition key expressions" msgstr "" "функции, возвращающие множества, нельзя применять в выражениях ключа " "секционирования" -#: parser/parse_func.c:2648 +#: parser/parse_func.c:2650 msgid "set-returning functions are not allowed in CALL arguments" msgstr "функции, возвращающие множества, нельзя применять в аргументах CALL" -#: parser/parse_func.c:2651 +#: parser/parse_func.c:2653 msgid "set-returning functions are not allowed in COPY FROM WHERE conditions" msgstr "" "функции, возвращающие множества, нельзя применять в условиях COPY FROM WHERE" -#: parser/parse_func.c:2654 +#: parser/parse_func.c:2656 msgid "" "set-returning functions are not allowed in column generation expressions" msgstr "" "функции, возвращающие множества, нельзя применять в выражениях генерируемых " "столбцов" -#: parser/parse_merge.c:119 +#: parser/parse_jsontable.c:95 +#, c-format +msgid "" +"Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "" +"На верхнем уровне предложения ON ERROR допускается только EMPTY [ ARRAY ] " +"или ERROR." + +#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#, c-format +msgid "duplicate JSON_TABLE column or path name: %s" +msgstr "повторяющийся столбец или имя пути в JSON_TABLE: %s" + +#: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" msgstr "предложение WITH RECURSIVE не поддерживается с оператором MERGE" -#: parser/parse_merge.c:166 +#: parser/parse_merge.c:176 #, c-format msgid "unreachable WHEN clause specified after unconditional WHEN clause" msgstr "" "после безусловного предложения WHEN указано недостижимое предложение WHEN" -#: parser/parse_merge.c:196 -#, c-format -msgid "MERGE is not supported for relations with rules." -msgstr "MERGE не поддерживается для отношений с правилами." - -#: parser/parse_merge.c:213 +#: parser/parse_merge.c:222 #, c-format msgid "name \"%s\" specified more than once" msgstr "имя \"%s\" указано больше одного раза" -#: parser/parse_merge.c:215 +#: parser/parse_merge.c:224 #, c-format msgid "The name is used both as MERGE target table and data source." msgstr "Это имя используется и в целевой таблице, и в источнике данных MERGE." -#: parser/parse_node.c:87 +#: parser/parse_node.c:82 #, c-format msgid "target lists can have at most %d entries" msgstr "число элементов в целевом списке ограничено %d" -#: parser/parse_oper.c:123 parser/parse_oper.c:690 +#: parser/parse_oper.c:114 parser/parse_oper.c:678 #, c-format msgid "postfix operators are not supported" msgstr "постфиксные операторы не поддерживаются" -#: parser/parse_oper.c:130 parser/parse_oper.c:649 utils/adt/regproc.c:509 -#: utils/adt/regproc.c:683 -#, c-format -msgid "operator does not exist: %s" -msgstr "оператор не существует: %s" - -#: parser/parse_oper.c:229 +#: parser/parse_oper.c:217 #, c-format msgid "Use an explicit ordering operator or modify the query." msgstr "Используйте явный оператор сортировки или измените запрос." -#: parser/parse_oper.c:485 +#: parser/parse_oper.c:473 #, c-format msgid "operator requires run-time type coercion: %s" msgstr "оператору требуется приведение типов во время выполнения: %s" -#: parser/parse_oper.c:641 +#: parser/parse_oper.c:629 #, c-format msgid "operator is not unique: %s" msgstr "оператор не уникален: %s" -#: parser/parse_oper.c:643 +#: parser/parse_oper.c:631 #, c-format msgid "" "Could not choose a best candidate operator. You might need to add explicit " @@ -19972,7 +20623,7 @@ msgstr "" "Не удалось выбрать лучшую кандидатуру оператора. Возможно, вам следует " "добавить явные приведения типов." -#: parser/parse_oper.c:652 +#: parser/parse_oper.c:640 #, c-format msgid "" "No operator matches the given name and argument type. You might need to add " @@ -19981,7 +20632,7 @@ msgstr "" "Оператор с данным именем и типом аргумента не найден. Возможно, вам следует " "добавить явное приведение типа." -#: parser/parse_oper.c:654 +#: parser/parse_oper.c:642 #, c-format msgid "" "No operator matches the given name and argument types. You might need to add " @@ -19990,24 +20641,19 @@ msgstr "" "Оператор с данными именем и типами аргументов не найден. Возможно, вам " "следует добавить явные приведения типов." -#: parser/parse_oper.c:714 parser/parse_oper.c:828 -#, c-format -msgid "operator is only a shell: %s" -msgstr "оператор \"%s\" - лишь оболочка" - -#: parser/parse_oper.c:816 +#: parser/parse_oper.c:803 #, c-format msgid "op ANY/ALL (array) requires array on right side" msgstr "для операторов ANY/ALL (с массивом) требуется массив справа" -#: parser/parse_oper.c:858 +#: parser/parse_oper.c:844 #, c-format msgid "op ANY/ALL (array) requires operator to yield boolean" msgstr "" "для операторов ANY/ALL (с массивом) требуется, чтобы оператор = возвращал " "логическое значение" -#: parser/parse_oper.c:863 +#: parser/parse_oper.c:849 #, c-format msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "" @@ -20019,7 +20665,7 @@ msgstr "" msgid "inconsistent types deduced for parameter $%d" msgstr "для параметра $%d выведены несогласованные типы" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:309 tcop/postgres.c:744 #, c-format msgid "could not determine data type of parameter $%d" msgstr "не удалось определить тип данных параметра $%d" @@ -20039,13 +20685,13 @@ msgstr "ссылка на таблицу %u неоднозначна" msgid "table name \"%s\" specified more than once" msgstr "имя таблицы \"%s\" указано больше одного раза" -#: parser/parse_relation.c:494 parser/parse_relation.c:3639 -#: parser/parse_relation.c:3648 +#: parser/parse_relation.c:494 parser/parse_relation.c:3633 +#: parser/parse_relation.c:3642 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "в элементе предложения FROM неверная ссылка на таблицу \"%s\"" -#: parser/parse_relation.c:498 parser/parse_relation.c:3650 +#: parser/parse_relation.c:498 parser/parse_relation.c:3644 #, c-format msgid "" "There is an entry for table \"%s\", but it cannot be referenced from this " @@ -20077,7 +20723,7 @@ msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "системный столбец \"%s\" нельзя использовать в условии MERGE WHEN" #: parser/parse_relation.c:1236 parser/parse_relation.c:1691 -#: parser/parse_relation.c:2388 +#: parser/parse_relation.c:2384 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "в таблице \"%s\" содержится столбцов: %d, но указано: %d" @@ -20099,13 +20745,13 @@ msgstr "" "Используйте WITH RECURSIVE или исключите ссылки вперёд, переупорядочив " "элементы WITH." -#: parser/parse_relation.c:1834 +#: parser/parse_relation.c:1833 #, c-format msgid "" "a column definition list is redundant for a function with OUT parameters" msgstr "список определений столбцов не нужен для функции с параметрами OUT" -#: parser/parse_relation.c:1840 +#: parser/parse_relation.c:1839 #, c-format msgid "" "a column definition list is redundant for a function returning a named " @@ -20114,79 +20760,79 @@ msgstr "" "список определений столбцов не нужен для функции, возвращающий именованный " "составной тип" -#: parser/parse_relation.c:1847 +#: parser/parse_relation.c:1846 #, c-format msgid "" "a column definition list is only allowed for functions returning \"record\"" msgstr "" "список определений столбцов может быть только у функций, возвращающих запись" -#: parser/parse_relation.c:1858 +#: parser/parse_relation.c:1857 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "" "у функций, возвращающих запись, должен быть список определений столбцов" -#: parser/parse_relation.c:1895 +#: parser/parse_relation.c:1894 #, c-format msgid "column definition lists can have at most %d entries" msgstr "число элементов в списках определения столбцов ограничено %d" -#: parser/parse_relation.c:1955 +#: parser/parse_relation.c:1954 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "" "функция \"%s\", используемая во FROM, возвращает неподдерживаемый тип %s" -#: parser/parse_relation.c:1982 parser/parse_relation.c:2068 +#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "число столбцов, возвращаемых функциями во FROM, ограничено %d" -#: parser/parse_relation.c:2098 +#: parser/parse_relation.c:2096 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "функция %s выдаёт столбцов: %d, но указано: %d" -#: parser/parse_relation.c:2180 +#: parser/parse_relation.c:2177 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "в списках VALUES \"%s\" содержится столбцов: %d, но указано: %d" -#: parser/parse_relation.c:2246 +#: parser/parse_relation.c:2242 #, c-format msgid "joins can have at most %d columns" msgstr "число столбцов в соединениях ограничено %d" -#: parser/parse_relation.c:2271 +#: parser/parse_relation.c:2267 #, c-format msgid "" "join expression \"%s\" has %d columns available but %d columns specified" msgstr "в выражении соединения \"%s\" имеется столбцов: %d, но указано: %d" -#: parser/parse_relation.c:2361 +#: parser/parse_relation.c:2357 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "в запросе \"%s\" в WITH нет предложения RETURNING" -#: parser/parse_relation.c:3641 +#: parser/parse_relation.c:3635 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "Возможно, предполагалась ссылка на псевдоним таблицы \"%s\"." -#: parser/parse_relation.c:3653 +#: parser/parse_relation.c:3647 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "" "Чтобы обратиться к этой таблице, нужно добавить для данного подзапроса " "пометку LATERAL." -#: parser/parse_relation.c:3659 +#: parser/parse_relation.c:3653 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "таблица \"%s\" отсутствует в предложении FROM" -#: parser/parse_relation.c:3699 +#: parser/parse_relation.c:3693 #, c-format msgid "" "There are columns named \"%s\", but they are in tables that cannot be " @@ -20195,12 +20841,12 @@ msgstr "" "Имеются столбцы с именем \"%s\", но они относятся к таблицам, к которым " "нельзя обратиться из этой части запроса." -#: parser/parse_relation.c:3701 +#: parser/parse_relation.c:3695 #, c-format msgid "Try using a table-qualified name." msgstr "Попробуйте использовать имя с указанием таблицы." -#: parser/parse_relation.c:3709 +#: parser/parse_relation.c:3703 #, c-format msgid "" "There is a column named \"%s\" in table \"%s\", but it cannot be referenced " @@ -20209,52 +20855,52 @@ msgstr "" "Столбец \"%s\" есть в таблице \"%s\", но на него нельзя ссылаться из этой " "части запроса." -#: parser/parse_relation.c:3712 +#: parser/parse_relation.c:3706 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "" "Чтобы обратиться к этому столбцу, нужно добавить для данного подзапроса " "пометку LATERAL." -#: parser/parse_relation.c:3714 +#: parser/parse_relation.c:3708 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "" "Чтобы обратиться к этому столбцу, нужно использовать имя с указанием таблицы." -#: parser/parse_relation.c:3734 +#: parser/parse_relation.c:3728 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "Возможно, предполагалась ссылка на столбец \"%s.%s\"." -#: parser/parse_relation.c:3748 +#: parser/parse_relation.c:3742 #, c-format msgid "" "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "" "Возможно, предполагалась ссылка на столбец \"%s.%s\" или столбец \"%s.%s\"." -#: parser/parse_target.c:481 parser/parse_target.c:796 +#: parser/parse_target.c:480 parser/parse_target.c:795 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "присвоить значение системному столбцу \"%s\" нельзя" -#: parser/parse_target.c:509 +#: parser/parse_target.c:508 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "элементу массива нельзя присвоить значение по умолчанию" -#: parser/parse_target.c:514 +#: parser/parse_target.c:513 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "вложенному полю нельзя присвоить значение по умолчанию" -#: parser/parse_target.c:588 +#: parser/parse_target.c:587 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "столбец \"%s\" имеет тип %s, а выражение - %s" -#: parser/parse_target.c:780 +#: parser/parse_target.c:779 #, c-format msgid "" "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a " @@ -20263,7 +20909,7 @@ msgstr "" "присвоить значение полю \"%s\" столбца \"%s\" нельзя, так как тип %s не " "является составным" -#: parser/parse_target.c:789 +#: parser/parse_target.c:788 #, c-format msgid "" "cannot assign to field \"%s\" of column \"%s\" because there is no such " @@ -20272,7 +20918,7 @@ msgstr "" "присвоить значение полю \"%s\" столбца \"%s\" нельзя, так как в типе данных " "%s нет такого столбца" -#: parser/parse_target.c:878 +#: parser/parse_target.c:877 #, c-format msgid "" "subscripted assignment to \"%s\" requires type %s but expression is of type " @@ -20281,12 +20927,12 @@ msgstr "" "для присваивания \"%s\" значения по индексу требуется тип %s, однако " "выражение имеет тип %s" -#: parser/parse_target.c:888 +#: parser/parse_target.c:887 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "вложенное поле \"%s\" имеет тип %s, а выражение - %s" -#: parser/parse_target.c:1328 +#: parser/parse_target.c:1327 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "SELECT * должен ссылаться на таблицы" @@ -20306,8 +20952,8 @@ msgstr "неправильное указание %%TYPE (слишком мно msgid "type reference %s converted to %s" msgstr "ссылка на тип %s преобразована в тип %s" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:395 -#: utils/cache/typcache.c:450 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 +#: utils/cache/typcache.c:452 #, c-format msgid "type \"%s\" is only a shell" msgstr "тип \"%s\" является пустышкой" @@ -20327,74 +20973,79 @@ msgstr "модификатором типа должна быть простая msgid "invalid type name \"%s\"" msgstr "неверное имя типа \"%s\"" -#: parser/parse_utilcmd.c:264 +#: parser/parse_utilcmd.c:263 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "создать секционированную таблицу в виде потомка нельзя" -#: parser/parse_utilcmd.c:589 +#: parser/parse_utilcmd.c:475 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "изменить состояние журналирования временной последовательности нельзя" + +#: parser/parse_utilcmd.c:611 #, c-format msgid "array of serial is not implemented" msgstr "массивы с типом serial не реализованы" -#: parser/parse_utilcmd.c:668 parser/parse_utilcmd.c:680 -#: parser/parse_utilcmd.c:739 +#: parser/parse_utilcmd.c:690 parser/parse_utilcmd.c:702 +#: parser/parse_utilcmd.c:761 #, c-format msgid "" "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "конфликт NULL/NOT NULL в объявлении столбца \"%s\" таблицы \"%s\"" -#: parser/parse_utilcmd.c:692 +#: parser/parse_utilcmd.c:714 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "" "для столбца \"%s\" таблицы \"%s\" указано несколько значений по умолчанию" -#: parser/parse_utilcmd.c:709 +#: parser/parse_utilcmd.c:731 #, c-format msgid "identity columns are not supported on typed tables" msgstr "столбцы идентификации не поддерживаются с типизированными таблицами" -#: parser/parse_utilcmd.c:713 +#: parser/parse_utilcmd.c:735 #, c-format msgid "identity columns are not supported on partitions" msgstr "столбцы идентификации не поддерживаются с секциями" -#: parser/parse_utilcmd.c:722 +#: parser/parse_utilcmd.c:744 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "" "для столбца \"%s\" таблицы \"%s\" свойство identity задано неоднократно" -#: parser/parse_utilcmd.c:752 +#: parser/parse_utilcmd.c:774 #, c-format msgid "generated columns are not supported on typed tables" msgstr "генерируемые столбцы не поддерживаются с типизированными таблицами" -#: parser/parse_utilcmd.c:756 +#: parser/parse_utilcmd.c:778 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "" "для столбца \"%s\" таблицы \"%s\" указано несколько генерирующих выражений" -#: parser/parse_utilcmd.c:774 parser/parse_utilcmd.c:889 +#: parser/parse_utilcmd.c:796 parser/parse_utilcmd.c:911 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "ограничения первичного ключа для сторонних таблиц не поддерживаются" -#: parser/parse_utilcmd.c:783 parser/parse_utilcmd.c:899 +#: parser/parse_utilcmd.c:805 parser/parse_utilcmd.c:921 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "ограничения уникальности для сторонних таблиц не поддерживаются" -#: parser/parse_utilcmd.c:828 +#: parser/parse_utilcmd.c:850 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "" "для столбца \"%s\" таблицы \"%s\" задано и значение по умолчанию, и свойство " "identity" -#: parser/parse_utilcmd.c:836 +#: parser/parse_utilcmd.c:858 #, c-format msgid "" "both default and generation expression specified for column \"%s\" of table " @@ -20403,7 +21054,7 @@ msgstr "" "для столбца \"%s\" таблицы \"%s\" задано и значение по умолчанию, и " "генерирующее выражение" -#: parser/parse_utilcmd.c:844 +#: parser/parse_utilcmd.c:866 #, c-format msgid "" "both identity and generation expression specified for column \"%s\" of table " @@ -20412,93 +21063,88 @@ msgstr "" "для столбца \"%s\" таблицы \"%s\" задано и генерирующее выражение, и " "свойство identity" -#: parser/parse_utilcmd.c:909 +#: parser/parse_utilcmd.c:931 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "ограничения-исключения для сторонних таблиц не поддерживаются" -#: parser/parse_utilcmd.c:915 -#, c-format -msgid "exclusion constraints are not supported on partitioned tables" -msgstr "ограничения-исключения для секционированных таблиц не поддерживаются" - -#: parser/parse_utilcmd.c:980 +#: parser/parse_utilcmd.c:996 #, c-format msgid "LIKE is not supported for creating foreign tables" msgstr "LIKE при создании сторонних таблиц не поддерживается" -#: parser/parse_utilcmd.c:993 +#: parser/parse_utilcmd.c:1009 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "отношение \"%s\" не подходит для предложения LIKE" -#: parser/parse_utilcmd.c:1750 parser/parse_utilcmd.c:1858 +#: parser/parse_utilcmd.c:1736 parser/parse_utilcmd.c:1844 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "Индекс \"%s\" ссылается на тип всей строки таблицы." -#: parser/parse_utilcmd.c:2245 +#: parser/parse_utilcmd.c:2242 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "в CREATE TABLE нельзя использовать существующий индекс" -#: parser/parse_utilcmd.c:2265 +#: parser/parse_utilcmd.c:2262 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "индекс \"%s\" уже связан с ограничением" -#: parser/parse_utilcmd.c:2286 +#: parser/parse_utilcmd.c:2283 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\" не является уникальным индексом" -#: parser/parse_utilcmd.c:2287 parser/parse_utilcmd.c:2294 -#: parser/parse_utilcmd.c:2301 parser/parse_utilcmd.c:2378 +#: parser/parse_utilcmd.c:2284 parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2298 parser/parse_utilcmd.c:2375 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "" "Создать первичный ключ или ограничение уникальности для такого индекса " "нельзя." -#: parser/parse_utilcmd.c:2293 +#: parser/parse_utilcmd.c:2290 #, c-format msgid "index \"%s\" contains expressions" msgstr "индекс \"%s\" содержит выражения" -#: parser/parse_utilcmd.c:2300 +#: parser/parse_utilcmd.c:2297 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\" - частичный индекс" -#: parser/parse_utilcmd.c:2312 +#: parser/parse_utilcmd.c:2309 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\" - откладываемый индекс" -#: parser/parse_utilcmd.c:2313 +#: parser/parse_utilcmd.c:2310 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "" "Создать не откладываемое ограничение на базе откладываемого индекса нельзя." -#: parser/parse_utilcmd.c:2377 +#: parser/parse_utilcmd.c:2374 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "" "в индексе \"%s\" для столбца номер %d не определено поведение сортировки по " "умолчанию" -#: parser/parse_utilcmd.c:2534 +#: parser/parse_utilcmd.c:2531 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "столбец \"%s\" фигурирует в первичном ключе дважды" -#: parser/parse_utilcmd.c:2540 +#: parser/parse_utilcmd.c:2537 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "столбец \"%s\" фигурирует в ограничении уникальности дважды" -#: parser/parse_utilcmd.c:2887 +#: parser/parse_utilcmd.c:2871 #, c-format msgid "" "index expressions and predicates can refer only to the table being indexed" @@ -20506,22 +21152,22 @@ msgstr "" "индексные выражения и предикаты могут ссылаться только на индексируемую " "таблицу" -#: parser/parse_utilcmd.c:2959 +#: parser/parse_utilcmd.c:2943 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "выражения статистики могут ссылаться только на целевую таблицу" -#: parser/parse_utilcmd.c:3002 +#: parser/parse_utilcmd.c:2986 #, c-format msgid "rules on materialized views are not supported" msgstr "правила для материализованных представлений не поддерживаются" -#: parser/parse_utilcmd.c:3062 +#: parser/parse_utilcmd.c:3046 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "в условиях WHERE для правил нельзя ссылаться на другие отношения" -#: parser/parse_utilcmd.c:3134 +#: parser/parse_utilcmd.c:3118 #, c-format msgid "" "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE " @@ -20530,158 +21176,158 @@ msgstr "" "правила с условиями WHERE могут содержать только действия SELECT, INSERT, " "UPDATE или DELETE" -#: parser/parse_utilcmd.c:3152 parser/parse_utilcmd.c:3253 -#: rewrite/rewriteHandler.c:539 rewrite/rewriteManip.c:1087 +#: parser/parse_utilcmd.c:3136 parser/parse_utilcmd.c:3237 +#: rewrite/rewriteHandler.c:544 rewrite/rewriteManip.c:1096 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "условные операторы UNION/INTERSECT/EXCEPT не реализованы" -#: parser/parse_utilcmd.c:3170 +#: parser/parse_utilcmd.c:3154 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "в правиле ON SELECT нельзя использовать OLD" -#: parser/parse_utilcmd.c:3174 +#: parser/parse_utilcmd.c:3158 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "в правиле ON SELECT нельзя использовать NEW" -#: parser/parse_utilcmd.c:3183 +#: parser/parse_utilcmd.c:3167 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "в правиле ON INSERT нельзя использовать OLD" -#: parser/parse_utilcmd.c:3189 +#: parser/parse_utilcmd.c:3173 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "в правиле ON DELETE нельзя использовать NEW" -#: parser/parse_utilcmd.c:3217 +#: parser/parse_utilcmd.c:3201 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "в запросе WITH нельзя ссылаться на OLD" -#: parser/parse_utilcmd.c:3224 +#: parser/parse_utilcmd.c:3208 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "в запросе WITH нельзя ссылаться на NEW" -#: parser/parse_utilcmd.c:3676 +#: parser/parse_utilcmd.c:3664 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "предложение DEFERRABLE расположено неправильно" -#: parser/parse_utilcmd.c:3681 parser/parse_utilcmd.c:3696 +#: parser/parse_utilcmd.c:3669 parser/parse_utilcmd.c:3684 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "DEFERRABLE/NOT DEFERRABLE можно указать только один раз" -#: parser/parse_utilcmd.c:3691 +#: parser/parse_utilcmd.c:3679 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "предложение NOT DEFERRABLE расположено неправильно" -#: parser/parse_utilcmd.c:3704 parser/parse_utilcmd.c:3730 gram.y:5990 +#: parser/parse_utilcmd.c:3692 parser/parse_utilcmd.c:3718 gram.y:6114 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" msgstr "" "ограничение с характеристикой INITIALLY DEFERRED должно быть объявлено как " "DEFERRABLE" -#: parser/parse_utilcmd.c:3712 +#: parser/parse_utilcmd.c:3700 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "предложение INITIALLY DEFERRED расположено неправильно" -#: parser/parse_utilcmd.c:3717 parser/parse_utilcmd.c:3743 +#: parser/parse_utilcmd.c:3705 parser/parse_utilcmd.c:3731 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "INITIALLY IMMEDIATE/DEFERRED можно указать только один раз" -#: parser/parse_utilcmd.c:3738 +#: parser/parse_utilcmd.c:3726 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "предложение INITIALLY IMMEDIATE расположено неправильно" -#: parser/parse_utilcmd.c:3931 +#: parser/parse_utilcmd.c:3919 #, c-format msgid "" "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "в CREATE указана схема (%s), отличная от создаваемой (%s)" -#: parser/parse_utilcmd.c:3966 +#: parser/parse_utilcmd.c:3954 #, c-format msgid "\"%s\" is not a partitioned table" msgstr "\"%s\" — не секционированная таблица" -#: parser/parse_utilcmd.c:3973 +#: parser/parse_utilcmd.c:3961 #, c-format msgid "table \"%s\" is not partitioned" msgstr "таблица \"%s\" не является секционированной" -#: parser/parse_utilcmd.c:3980 +#: parser/parse_utilcmd.c:3968 #, c-format msgid "index \"%s\" is not partitioned" msgstr "индекс \"%s\" не секционирован" -#: parser/parse_utilcmd.c:4020 +#: parser/parse_utilcmd.c:4008 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "у секционированной по хешу таблицы не может быть секции по умолчанию" -#: parser/parse_utilcmd.c:4037 +#: parser/parse_utilcmd.c:4025 #, c-format msgid "invalid bound specification for a hash partition" msgstr "неправильное указание ограничения для хеш-секции" -#: parser/parse_utilcmd.c:4043 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4031 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "модуль для хеш-секции должен быть положительным целым" -#: parser/parse_utilcmd.c:4050 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4038 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "остаток для хеш-секции должен быть меньше модуля" -#: parser/parse_utilcmd.c:4063 +#: parser/parse_utilcmd.c:4051 #, c-format msgid "invalid bound specification for a list partition" msgstr "неправильное указание ограничения для секции по списку" -#: parser/parse_utilcmd.c:4116 +#: parser/parse_utilcmd.c:4104 #, c-format msgid "invalid bound specification for a range partition" msgstr "неправильное указание ограничения для секции по диапазону" -#: parser/parse_utilcmd.c:4122 +#: parser/parse_utilcmd.c:4110 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "" "во FROM должно указываться ровно одно значение для секционирующего столбца" -#: parser/parse_utilcmd.c:4126 +#: parser/parse_utilcmd.c:4114 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "" "в TO должно указываться ровно одно значение для секционирующего столбца" -#: parser/parse_utilcmd.c:4240 +#: parser/parse_utilcmd.c:4228 #, c-format msgid "cannot specify NULL in range bound" msgstr "указать NULL в диапазонном ограничении нельзя" -#: parser/parse_utilcmd.c:4289 +#: parser/parse_utilcmd.c:4277 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "за границей MAXVALUE могут следовать только границы MAXVALUE" -#: parser/parse_utilcmd.c:4296 +#: parser/parse_utilcmd.c:4284 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "за границей MINVALUE могут следовать только границы MINVALUE" -#: parser/parse_utilcmd.c:4339 +#: parser/parse_utilcmd.c:4327 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "указанное значение нельзя привести к типу %s столбца \"%s\"" @@ -20694,12 +21340,12 @@ msgstr "За UESCAPE должна следовать простая строко msgid "invalid Unicode escape character" msgstr "неверный символ спецкода Unicode" -#: parser/parser.c:347 scan.l:1390 +#: parser/parser.c:347 scan.l:1393 #, c-format msgid "invalid Unicode escape value" msgstr "неверное значение спецкода Unicode" -#: parser/parser.c:494 utils/adt/varlena.c:6505 scan.l:701 +#: parser/parser.c:494 utils/adt/varlena.c:6640 scan.l:716 #, c-format msgid "invalid Unicode escape" msgstr "неверный спецкод Unicode" @@ -20709,8 +21355,8 @@ msgstr "неверный спецкод Unicode" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "Спецкоды Unicode должны иметь вид \\XXXX или \\+XXXXXX." -#: parser/parser.c:523 utils/adt/varlena.c:6530 scan.l:662 scan.l:678 -#: scan.l:694 +#: parser/parser.c:523 utils/adt/varlena.c:6665 scan.l:677 scan.l:693 +#: scan.l:709 #, c-format msgid "invalid Unicode surrogate pair" msgstr "неверная суррогатная пара Unicode" @@ -20720,20 +21366,20 @@ msgstr "неверная суррогатная пара Unicode" msgid "identifier \"%s\" will be truncated to \"%.*s\"" msgstr "идентификатор \"%s\" будет усечён до \"%.*s\"" -#: partitioning/partbounds.c:2921 +#: partitioning/partbounds.c:2920 #, c-format msgid "partition \"%s\" conflicts with existing default partition \"%s\"" msgstr "секция \"%s\" конфликтует с существующей секцией по умолчанию \"%s\"" -#: partitioning/partbounds.c:2973 partitioning/partbounds.c:2992 -#: partitioning/partbounds.c:3014 +#: partitioning/partbounds.c:2972 partitioning/partbounds.c:2991 +#: partitioning/partbounds.c:3013 #, c-format msgid "" "every hash partition modulus must be a factor of the next larger modulus" msgstr "" "модуль каждой хеш-секции должен быть делителем модулей, превышающих его" -#: partitioning/partbounds.c:2974 partitioning/partbounds.c:3015 +#: partitioning/partbounds.c:2973 partitioning/partbounds.c:3014 #, c-format msgid "" "The new modulus %d is not a factor of %d, the modulus of existing partition " @@ -20741,29 +21387,29 @@ msgid "" msgstr "" "Новый модуль %d не является делителем %d, модуля существующей секции \"%s\"." -#: partitioning/partbounds.c:2993 +#: partitioning/partbounds.c:2992 #, c-format msgid "" "The new modulus %d is not divisible by %d, the modulus of existing partition " "\"%s\"." msgstr "Новый модуль %d не делится на %d, модуль существующей секции \"%s\"." -#: partitioning/partbounds.c:3128 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "для секции \"%s\" заданы границы, образующие пустой диапазон" -#: partitioning/partbounds.c:3130 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "Указанная нижняя граница %s больше или равна верхней границе %s." -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "секция \"%s\" пересекается с секцией \"%s\"" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "" "skipped scanning foreign table \"%s\" which is a partition of default " @@ -20772,19 +21418,19 @@ msgstr "" "пропущено сканирование сторонней таблицы \"%s\", являющейся секцией секции " "по умолчанию \"%s\"" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "" "remainder for hash partition must be an integer value greater than or equal " "to zero" msgstr "значение остатка для хеш-секции должно быть неотрицательным целым" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\" не является таблицей, секционированной по хешу" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "" "number of partitioning columns (%d) does not match number of partition keys " @@ -20793,7 +21439,7 @@ msgstr "" "число секционирующих столбцов (%d) не равно числу представленных ключей " "секционирования (%d)" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "" "column %d of the partition key has type %s, but supplied value is of type %s" @@ -20801,7 +21447,7 @@ msgstr "" "столбец %d ключа секционирования имеет тип %s, но для него передано значение " "типа %s" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "" "column %d of the partition key has type \"%s\", but supplied value is of " @@ -20810,23 +21456,23 @@ msgstr "" "столбец %d ключа секционирования имеет тип \"%s\", но для него передано " "значение типа \"%s\"" -#: port/pg_sema.c:209 port/pg_shmem.c:708 port/posix_sema.c:209 -#: port/sysv_sema.c:323 port/sysv_shmem.c:708 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 +#: port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "не удалось получить информацию о каталоге данных \"%s\": %m" -#: port/pg_shmem.c:223 port/sysv_shmem.c:223 +#: port/pg_shmem.c:224 port/sysv_shmem.c:224 #, c-format msgid "could not create shared memory segment: %m" msgstr "не удалось создать сегмент разделяемой памяти: %m" -#: port/pg_shmem.c:224 port/sysv_shmem.c:224 +#: port/pg_shmem.c:225 port/sysv_shmem.c:225 #, c-format msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)." msgstr "Ошибка в системном вызове shmget(ключ=%lu, размер=%zu, 0%o)." -#: port/pg_shmem.c:228 port/sysv_shmem.c:228 +#: port/pg_shmem.c:229 port/sysv_shmem.c:229 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " @@ -20840,7 +21486,7 @@ msgstr "" "Подробная информация о настройке разделяемой памяти содержится в " "документации PostgreSQL." -#: port/pg_shmem.c:235 port/sysv_shmem.c:235 +#: port/pg_shmem.c:236 port/sysv_shmem.c:236 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " @@ -20855,7 +21501,7 @@ msgstr "" "Подробная информация о настройке разделяемой памяти содержится в " "документации PostgreSQL." -#: port/pg_shmem.c:241 port/sysv_shmem.c:241 +#: port/pg_shmem.c:242 port/sysv_shmem.c:242 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs " @@ -20872,49 +21518,51 @@ msgstr "" "Подробная информация о настройке разделяемой памяти содержится в " "документации PostgreSQL." -#: port/pg_shmem.c:583 port/sysv_shmem.c:583 port/win32_shmem.c:641 +#: port/pg_shmem.c:584 port/sysv_shmem.c:584 port/win32_shmem.c:646 #, c-format -msgid "huge_page_size must be 0 on this platform." -msgstr "Значение huge_page_size должно равняться 0 на этой платформе." +msgid "\"huge_page_size\" must be 0 on this platform." +msgstr "Значение \"huge_page_size\" должно равняться 0 на этой платформе." -#: port/pg_shmem.c:646 port/sysv_shmem.c:646 +#: port/pg_shmem.c:655 port/sysv_shmem.c:655 #, c-format msgid "could not map anonymous shared memory: %m" msgstr "не удалось получить анонимную разделяемую память: %m" -#: port/pg_shmem.c:648 port/sysv_shmem.c:648 +#: port/pg_shmem.c:657 port/sysv_shmem.c:657 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory " "segment exceeded available memory, swap space, or huge pages. To reduce the " "request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, " -"perhaps by reducing shared_buffers or max_connections." +"perhaps by reducing \"shared_buffers\" or \"max_connections\"." msgstr "" "Эта ошибка обычно возникает, когда PostgreSQL запрашивает сегмент " "разделяемой памяти, превышая объём доступной физической либо виртуальной " "памяти или огромных страниц. Для уменьшения запроса (текущий размер: %zu Б) " "можно снизить использование разделяемой памяти, возможно, уменьшив " -"shared_buffers или max_connections." +"\"shared_buffers\" или \"max_connections\"." -#: port/pg_shmem.c:716 port/sysv_shmem.c:716 +#: port/pg_shmem.c:725 port/sysv_shmem.c:725 #, c-format msgid "huge pages not supported on this platform" msgstr "огромные страницы на этой платформе не поддерживаются" -#: port/pg_shmem.c:723 port/sysv_shmem.c:723 +#: port/pg_shmem.c:732 port/sysv_shmem.c:732 #, c-format -msgid "huge pages not supported with the current shared_memory_type setting" +msgid "" +"huge pages not supported with the current \"shared_memory_type\" setting" msgstr "" -"огромные страницы не поддерживаются с текущим значением shared_memory_type" +"огромные страницы не поддерживаются с текущим значением " +"\"shared_memory_type\"" -#: port/pg_shmem.c:783 port/sysv_shmem.c:783 utils/init/miscinit.c:1358 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1401 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "" "ранее выделенный блок разделяемой памяти (ключ %lu, ID %lu) по-прежнему " "используется" -#: port/pg_shmem.c:786 port/sysv_shmem.c:786 utils/init/miscinit.c:1360 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1403 #, c-format msgid "" "Terminate any old server processes associated with data directory \"%s\"." @@ -20922,17 +21570,17 @@ msgstr "" "Завершите все старые серверные процессы, работающие с каталогом данных " "\"%s\"." -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "не удалось создать семафоры: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "Ошибка в системном вызове semget(%lu, %d, 0%o)." -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs " @@ -20940,18 +21588,19 @@ msgid "" "(SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be " "exceeded. You need to raise the respective kernel parameter. " "Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its " -"max_connections parameter.\n" +"\"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring " "your system for PostgreSQL." msgstr "" "Эта ошибка НЕ означает, что на диске нет места. Вероятнее всего, превышен " "предел числа установленных семафоров (SEMMNI), либо общего числа семафоров " "(SEMMNS) в системе. Увеличьте соответствующий параметр ядра или уменьшите " -"потребность PostgreSQL в семафорах, уменьшив его параметр max_connections.\n" +"потребность PostgreSQL в семафорах, уменьшив его параметр " +"\"max_connections\".\n" "Подробная информация о настройке разделяемой памяти содержится в " "документации PostgreSQL." -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "" "You possibly need to raise your kernel's SEMVMX value to be at least %d. " @@ -21093,53 +21742,43 @@ msgstr "Ошибка в системном вызове DuplicateHandle." msgid "Failed system call was MapViewOfFileEx." msgstr "Ошибка в системном вызове MapViewOfFileEx." -#: postmaster/autovacuum.c:418 -#, c-format -msgid "could not fork autovacuum launcher process: %m" -msgstr "породить процесс запуска автоочистки не удалось: %m" - -#: postmaster/autovacuum.c:765 +#: postmaster/autovacuum.c:686 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "процесс автоочистки запускался слишком долго; его запуск отменён" -#: postmaster/autovacuum.c:1490 -#, c-format -msgid "could not fork autovacuum worker process: %m" -msgstr "не удалось породить рабочий процесс автоочистки: %m" - # skip-rule: capital-letter-first -#: postmaster/autovacuum.c:2353 +#: postmaster/autovacuum.c:2203 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "автоочистка: удаление устаревшей врем. таблицы \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2589 +#: postmaster/autovacuum.c:2439 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "автоматическая очистка таблицы \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2592 +#: postmaster/autovacuum.c:2442 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "автоматический анализ таблицы \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2786 +#: postmaster/autovacuum.c:2636 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "обработка рабочей записи для отношения \"%s.%s.%s\"" -#: postmaster/autovacuum.c:3400 +#: postmaster/autovacuum.c:3254 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "автоочистка не запущена из-за неправильной конфигурации" -#: postmaster/autovacuum.c:3401 +#: postmaster/autovacuum.c:3255 #, c-format msgid "Enable the \"track_counts\" option." msgstr "Включите параметр \"track_counts\"." -#: postmaster/bgworker.c:259 +#: postmaster/bgworker.c:260 #, c-format msgid "" "inconsistent background worker state (max_worker_processes=%d, " @@ -21148,7 +21787,7 @@ msgstr "" "несогласованное состояние фонового рабочего процесса " "(max_worker_processes=%d, total_slots=%d)" -#: postmaster/bgworker.c:669 +#: postmaster/bgworker.c:651 #, c-format msgid "" "background worker \"%s\": background workers without shared memory access " @@ -21157,7 +21796,7 @@ msgstr "" "фоновый процесс \"%s\": фоновые процессы, не обращающиеся к общей памяти, не " "поддерживаются" -#: postmaster/bgworker.c:680 +#: postmaster/bgworker.c:662 #, c-format msgid "" "background worker \"%s\": cannot request database access if starting at " @@ -21166,12 +21805,12 @@ msgstr "" "фоновый процесс \"%s\" не может получить доступ к БД, если он запущен при " "старте главного процесса" -#: postmaster/bgworker.c:694 +#: postmaster/bgworker.c:676 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "фоновый процесс \"%s\": неправильный интервал перезапуска" -#: postmaster/bgworker.c:709 +#: postmaster/bgworker.c:691 #, c-format msgid "" "background worker \"%s\": parallel workers may not be configured for restart" @@ -21179,19 +21818,20 @@ msgstr "" "фоновый процесс \"%s\": параллельные исполнители не могут быть настроены для " "перезапуска" -#: postmaster/bgworker.c:733 tcop/postgres.c:3255 +#: postmaster/bgworker.c:715 tcop/postgres.c:3312 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "завершение фонового процесса \"%s\" по команде администратора" -#: postmaster/bgworker.c:890 +#: postmaster/bgworker.c:888 #, c-format msgid "" -"background worker \"%s\": must be registered in shared_preload_libraries" +"background worker \"%s\": must be registered in \"shared_preload_libraries\"" msgstr "" -"фоновой процесс \"%s\" должен быть зарегистрирован в shared_preload_libraries" +"фоновой процесс \"%s\" должен быть зарегистрирован в " +"\"shared_preload_libraries\"" -#: postmaster/bgworker.c:902 +#: postmaster/bgworker.c:911 #, c-format msgid "" "background worker \"%s\": only dynamic background workers can request " @@ -21200,12 +21840,12 @@ msgstr "" "фоновый процесс \"%s\": только динамические фоновые процессы могут " "запрашивать уведомление" -#: postmaster/bgworker.c:917 +#: postmaster/bgworker.c:926 #, c-format msgid "too many background workers" msgstr "слишком много фоновых процессов" -#: postmaster/bgworker.c:918 +#: postmaster/bgworker.c:927 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "" @@ -21217,13 +21857,12 @@ msgstr[1] "" msgstr[2] "" "Максимально возможное число фоновых процессов при текущих параметрах: %d." -#: postmaster/bgworker.c:922 +#: postmaster/bgworker.c:931 postmaster/checkpointer.c:445 #, c-format -msgid "" -"Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "Возможно, стоит увеличить параметр \"max_worker_processes\"." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "Возможно, стоит увеличить параметр \"%s\"." -#: postmaster/checkpointer.c:431 +#: postmaster/checkpointer.c:441 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" @@ -21231,209 +21870,310 @@ msgstr[0] "контрольные точки происходят слишком msgstr[1] "контрольные точки происходят слишком часто (через %d сек.)" msgstr[2] "контрольные точки происходят слишком часто (через %d сек.)" -#: postmaster/checkpointer.c:435 -#, c-format -msgid "Consider increasing the configuration parameter \"max_wal_size\"." -msgstr "Возможно, стоит увеличить параметр \"max_wal_size\"." - -#: postmaster/checkpointer.c:1059 +#: postmaster/checkpointer.c:1067 #, c-format msgid "checkpoint request failed" msgstr "сбой при запросе контрольной точки" -#: postmaster/checkpointer.c:1060 +#: postmaster/checkpointer.c:1068 #, c-format msgid "Consult recent messages in the server log for details." msgstr "Смотрите подробности в протоколе сервера." -#: postmaster/pgarch.c:416 +#: postmaster/launch_backend.c:381 #, c-format -msgid "archive_mode enabled, yet archiving is not configured" -msgstr "режим архивации включён, но архивирование ещё не настроено" +msgid "could not execute server process \"%s\": %m" +msgstr "запустить серверный процесс \"%s\" не удалось: %m" -#: postmaster/pgarch.c:438 +#: postmaster/launch_backend.c:434 #, c-format -msgid "removed orphan archive status file \"%s\"" -msgstr "удалён ненужный файл состояния архива \"%s\"" +msgid "could not create backend parameter file mapping: error code %lu" +msgstr "" +"создать отображение файла серверных параметров не удалось (код ошибки: %lu)" -#: postmaster/pgarch.c:448 +#: postmaster/launch_backend.c:442 #, c-format -msgid "" -"removal of orphan archive status file \"%s\" failed too many times, will try " -"again later" +msgid "could not map backend parameter memory: error code %lu" msgstr "" -"удалить ненужный файл состояния архива \"%s\" не получилось много раз " -"подряд; следующая попытка будет сделана позже" +"отобразить файл серверных параметров в память не удалось (код ошибки: %lu)" -#: postmaster/pgarch.c:484 +#: postmaster/launch_backend.c:459 #, c-format -msgid "" -"archiving write-ahead log file \"%s\" failed too many times, will try again " -"later" -msgstr "" -"заархивировать файл журнала предзаписи \"%s\" не удалось много раз подряд; " -"следующая попытка будет сделана позже" +msgid "subprocess command line too long" +msgstr "слишком длинная командная строка подпроцесса" -#: postmaster/pgarch.c:791 postmaster/pgarch.c:830 +#: postmaster/launch_backend.c:477 #, c-format -msgid "both archive_command and archive_library set" -msgstr "archive_command и archive_library заданы одновременно" +msgid "CreateProcess() call failed: %m (error code %lu)" +msgstr "ошибка в CreateProcess(): %m (код ошибки: %lu)" -#: postmaster/pgarch.c:792 postmaster/pgarch.c:831 +#: postmaster/launch_backend.c:504 #, c-format -msgid "Only one of archive_command, archive_library may be set." +msgid "could not unmap view of backend parameter file: error code %lu" msgstr "" -"Только один из параметров archive_command, archive_library может иметь " -"значение." +"отключить отображение файла серверных параметров не удалось (код ошибки: %lu)" -#: postmaster/pgarch.c:809 +#: postmaster/launch_backend.c:508 #, c-format -msgid "" -"restarting archiver process because value of \"archive_library\" was changed" +msgid "could not close handle to backend parameter file: error code %lu" msgstr "" -"процесс архиватора перезапускается, так как было изменено значение " -"\"archive_library\"" +"закрыть указатель файла серверных параметров не удалось (код ошибки: %lu)" -#: postmaster/pgarch.c:846 +#: postmaster/launch_backend.c:530 #, c-format -msgid "archive modules have to define the symbol %s" -msgstr "в модулях архивирования должен объявляться символ %s" +msgid "giving up after too many tries to reserve shared memory" +msgstr "" +"число повторных попыток резервирования разделяемой памяти достигло предела" -#: postmaster/pgarch.c:852 +#: postmaster/launch_backend.c:531 #, c-format -msgid "archive modules must register an archive callback" -msgstr "модули архивирования должны регистрировать обработчик вызова архивации" +msgid "This might be caused by ASLR or antivirus software." +msgstr "Это может быть вызвано антивирусным ПО или механизмом ASLR." -#: postmaster/postmaster.c:759 +#: postmaster/launch_backend.c:834 #, c-format -msgid "%s: invalid argument for option -f: \"%s\"\n" -msgstr "%s: неверный аргумент для параметра -f: \"%s\"\n" +msgid "could not duplicate socket %d for use in backend: error code %d" +msgstr "" +"продублировать сокет %d для серверного процесса не удалось (код ошибки: %d)" -#: postmaster/postmaster.c:832 +#: postmaster/launch_backend.c:866 #, c-format -msgid "%s: invalid argument for option -t: \"%s\"\n" -msgstr "%s: неверный аргумент для параметра -t: \"%s\"\n" +msgid "could not create inherited socket: error code %d\n" +msgstr "создать наследуемый сокет не удалось (код ошибки: %d)\n" -#: postmaster/postmaster.c:855 +#: postmaster/launch_backend.c:895 #, c-format -msgid "%s: invalid argument: \"%s\"\n" -msgstr "%s: неверный аргумент: \"%s\"\n" +msgid "could not open backend variables file \"%s\": %m\n" +msgstr "открыть файл серверных переменных \"%s\" не удалось: %m\n" -#: postmaster/postmaster.c:923 +#: postmaster/launch_backend.c:901 #, c-format -msgid "" -"%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must " -"be less than max_connections (%d)\n" -msgstr "" -"%s: значение superuser_reserved_connections (%d) плюс reserved_connections " -"(%d) должно быть меньше max_connections (%d)\n" +msgid "could not read from backend variables file \"%s\": %m\n" +msgstr "прочитать файл серверных переменных \"%s\" не удалось: %m\n" -#: postmaster/postmaster.c:931 +#: postmaster/launch_backend.c:912 #, c-format -msgid "WAL archival cannot be enabled when wal_level is \"minimal\"" -msgstr "Архивацию WAL нельзя включить, если установлен wal_level \"minimal\"" +msgid "could not read startup data from backend variables file \"%s\": %m\n" +msgstr "" +"прочитать стартовые данные из файла серверных переменных \"%s\" не удалось: " +"%m\n" -#: postmaster/postmaster.c:934 +#: postmaster/launch_backend.c:924 #, c-format -msgid "" -"WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or " -"\"logical\"" -msgstr "" -"Для потоковой трансляции WAL (max_wal_senders > 0) wal_level должен быть " -"\"replica\" или \"logical\"" +msgid "could not remove file \"%s\": %m\n" +msgstr "не удалось стереть файл \"%s\": %m\n" -#: postmaster/postmaster.c:942 +#: postmaster/launch_backend.c:940 #, c-format -msgid "%s: invalid datetoken tables, please fix\n" -msgstr "%s: ошибка в таблицах маркеров времени, требуется исправление\n" +msgid "could not map view of backend variables: error code %lu\n" +msgstr "отобразить файл серверных переменных не удалось (код ошибки: %lu)\n" -#: postmaster/postmaster.c:1099 +#: postmaster/launch_backend.c:959 #, c-format -msgid "could not create I/O completion port for child queue" -msgstr "не удалось создать порт завершения ввода/вывода для очереди потомков" +msgid "could not unmap view of backend variables: error code %lu\n" +msgstr "" +"отключить отображение файла серверных переменных не удалось (код ошибки: " +"%lu)\n" -#: postmaster/postmaster.c:1175 +#: postmaster/launch_backend.c:966 +#, c-format +msgid "could not close handle to backend parameter variables: error code %lu\n" +msgstr "" +"закрыть указатель файла серверных переменных не удалось (код ошибки: %lu)\n" + +#: postmaster/pgarch.c:428 +#, c-format +msgid "\"archive_mode\" enabled, yet archiving is not configured" +msgstr "параметр \"archive_mode\" включён, но архивирование ещё не настроено" + +#: postmaster/pgarch.c:452 +#, c-format +msgid "removed orphan archive status file \"%s\"" +msgstr "удалён ненужный файл состояния архива \"%s\"" + +#: postmaster/pgarch.c:462 +#, c-format +msgid "" +"removal of orphan archive status file \"%s\" failed too many times, will try " +"again later" +msgstr "" +"удалить ненужный файл состояния архива \"%s\" не получилось много раз " +"подряд; следующая попытка будет сделана позже" + +#: postmaster/pgarch.c:498 +#, c-format +msgid "" +"archiving write-ahead log file \"%s\" failed too many times, will try again " +"later" +msgstr "" +"заархивировать файл журнала предзаписи \"%s\" не удалось много раз подряд; " +"следующая попытка будет сделана позже" + +#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 +#, c-format +msgid "both \"archive_command\" and \"archive_library\" set" +msgstr "\"archive_command\" и \"archive_library\" заданы одновременно" + +#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 +#, c-format +msgid "Only one of \"archive_command\", \"archive_library\" may be set." +msgstr "" +"Только один из параметров \"archive_command\", \"archive_library\" может " +"иметь значение." + +#: postmaster/pgarch.c:897 +#, c-format +msgid "" +"restarting archiver process because value of \"archive_library\" was changed" +msgstr "" +"процесс архиватора перезапускается, так как было изменено значение " +"\"archive_library\"" + +#: postmaster/pgarch.c:934 +#, c-format +msgid "archive modules have to define the symbol %s" +msgstr "в модулях архивирования должен объявляться символ %s" + +#: postmaster/pgarch.c:940 +#, c-format +msgid "archive modules must register an archive callback" +msgstr "модули архивирования должны регистрировать обработчик вызова архивации" + +#: postmaster/postmaster.c:661 +#, c-format +msgid "%s: invalid argument for option -f: \"%s\"\n" +msgstr "%s: неверный аргумент для параметра -f: \"%s\"\n" + +#: postmaster/postmaster.c:734 +#, c-format +msgid "%s: invalid argument for option -t: \"%s\"\n" +msgstr "%s: неверный аргумент для параметра -t: \"%s\"\n" + +#: postmaster/postmaster.c:757 +#, c-format +msgid "%s: invalid argument: \"%s\"\n" +msgstr "%s: неверный аргумент: \"%s\"\n" + +#: postmaster/postmaster.c:825 +#, c-format +msgid "" +"%s: \"superuser_reserved_connections\" (%d) plus " +"\"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" +msgstr "" +"%s: значение \"superuser_reserved_connections\" (%d) плюс " +"\"reserved_connections\" (%d) должно быть меньше \"max_connections\" (%d)\n" + +#: postmaster/postmaster.c:833 +#, c-format +msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" +msgstr "архивацию WAL нельзя включить, если \"wal_level\" = \"minimal\"" + +#: postmaster/postmaster.c:836 +#, c-format +msgid "" +"WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be " +"\"replica\" or \"logical\"" +msgstr "" +"для потоковой трансляции WAL (\"max_wal_senders\" > 0) \"wal_level\" должен " +"быть \"replica\" или \"logical\"" + +#: postmaster/postmaster.c:839 +#, c-format +msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" +msgstr "обобщение WAL нельзя включить, если выбран \"wal_level\" \"minimal\"" + +#: postmaster/postmaster.c:847 +#, c-format +msgid "%s: invalid datetoken tables, please fix\n" +msgstr "%s: ошибка в таблицах маркеров времени, требуется исправление\n" + +#: postmaster/postmaster.c:1004 +#, c-format +msgid "could not create I/O completion port for child queue" +msgstr "не удалось создать порт завершения ввода/вывода для очереди потомков" + +#: postmaster/postmaster.c:1069 #, c-format msgid "ending log output to stderr" msgstr "завершение вывода в stderr" -#: postmaster/postmaster.c:1176 +#: postmaster/postmaster.c:1070 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "В дальнейшем протокол будет выводиться в \"%s\"." -#: postmaster/postmaster.c:1187 +#: postmaster/postmaster.c:1081 #, c-format msgid "starting %s" msgstr "запускается %s" -#: postmaster/postmaster.c:1239 +#: postmaster/postmaster.c:1143 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "не удалось создать принимающий сокет для \"%s\"" -#: postmaster/postmaster.c:1245 +#: postmaster/postmaster.c:1149 #, c-format msgid "could not create any TCP/IP sockets" msgstr "не удалось создать сокеты TCP/IP" -#: postmaster/postmaster.c:1277 +#: postmaster/postmaster.c:1181 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "функция DNSServiceRegister() выдала ошибку с кодом %ld" -#: postmaster/postmaster.c:1328 +#: postmaster/postmaster.c:1234 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "не удалось создать Unix-сокет в каталоге \"%s\"" -#: postmaster/postmaster.c:1334 +#: postmaster/postmaster.c:1240 #, c-format msgid "could not create any Unix-domain sockets" msgstr "ни один Unix-сокет создать не удалось" -#: postmaster/postmaster.c:1345 +#: postmaster/postmaster.c:1251 #, c-format msgid "no socket created for listening" msgstr "отсутствуют принимающие сокеты" -#: postmaster/postmaster.c:1376 +#: postmaster/postmaster.c:1282 #, c-format -msgid "%s: could not change permissions of external PID file \"%s\": %s\n" -msgstr "%s: не удалось поменять права для внешнего файла PID \"%s\": %s\n" +msgid "%s: could not change permissions of external PID file \"%s\": %m\n" +msgstr "%s: не удалось поменять права для внешнего файла PID \"%s\": %m\n" -#: postmaster/postmaster.c:1380 +#: postmaster/postmaster.c:1286 #, c-format -msgid "%s: could not write external PID file \"%s\": %s\n" -msgstr "%s: не удалось записать внешний файл PID \"%s\": %s\n" +msgid "%s: could not write external PID file \"%s\": %m\n" +msgstr "%s: не удалось записать внешний файл PID \"%s\": %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1408 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 #, c-format msgid "could not load %s" msgstr "не удалось загрузить %s" -#: postmaster/postmaster.c:1434 +#: postmaster/postmaster.c:1342 #, c-format msgid "postmaster became multithreaded during startup" msgstr "процесс postmaster стал многопоточным при запуске" -#: postmaster/postmaster.c:1435 +#: postmaster/postmaster.c:1343 postmaster/postmaster.c:3684 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "Установите в переменной окружения LC_ALL правильную локаль." -#: postmaster/postmaster.c:1536 +#: postmaster/postmaster.c:1442 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: не удалось найти путь к собственному исполняемому файлу" -#: postmaster/postmaster.c:1543 +#: postmaster/postmaster.c:1449 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: подходящий исполняемый файл postgres не найден" -#: postmaster/postmaster.c:1566 utils/misc/tzparser.c:340 +#: postmaster/postmaster.c:1472 utils/misc/tzparser.c:341 #, c-format msgid "" "This may indicate an incomplete PostgreSQL installation, or that the file " @@ -21442,574 +22182,383 @@ msgstr "" "Возможно, PostgreSQL установлен не полностью или файла \"%s\" нет в " "положенном месте." -#: postmaster/postmaster.c:1593 +#: postmaster/postmaster.c:1499 #, c-format msgid "" "%s: could not find the database system\n" "Expected to find it in the directory \"%s\",\n" -"but could not open file \"%s\": %s\n" +"but could not open file \"%s\": %m\n" msgstr "" "%s: не найдена система баз данных\n" "Ожидалось найти её в каталоге \"%s\",\n" -"но открыть файл \"%s\" не удалось: %s\n" +"но открыть файл \"%s\" не удалось: %m\n" # well-spelled: неподчиняющимся #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1890 +#: postmaster/postmaster.c:1789 #, c-format msgid "issuing %s to recalcitrant children" msgstr "неподчиняющимся потомкам посылается %s" -#: postmaster/postmaster.c:1912 +#: postmaster/postmaster.c:1811 #, c-format msgid "" "performing immediate shutdown because data directory lock file is invalid" msgstr "" "немедленное отключение из-за ошибочного файла блокировки каталога данных" -#: postmaster/postmaster.c:1987 postmaster/postmaster.c:2015 -#, c-format -msgid "incomplete startup packet" -msgstr "неполный стартовый пакет" - -#: postmaster/postmaster.c:1999 postmaster/postmaster.c:2032 -#, c-format -msgid "invalid length of startup packet" -msgstr "неверная длина стартового пакета" - -#: postmaster/postmaster.c:2061 -#, c-format -msgid "failed to send SSL negotiation response: %m" -msgstr "не удалось отправить ответ в процессе SSL-согласования: %m" - -#: postmaster/postmaster.c:2079 -#, c-format -msgid "received unencrypted data after SSL request" -msgstr "после запроса SSL получены незашифрованные данные" - -#: postmaster/postmaster.c:2080 postmaster/postmaster.c:2124 -#, c-format -msgid "" -"This could be either a client-software bug or evidence of an attempted man-" -"in-the-middle attack." -msgstr "" -"Это может свидетельствовать об ошибке в клиентском ПО или о попытке атаки " -"MITM." - -#: postmaster/postmaster.c:2105 -#, c-format -msgid "failed to send GSSAPI negotiation response: %m" -msgstr "не удалось отправить ответ в процессе согласования GSSAPI: %m" - -#: postmaster/postmaster.c:2123 -#, c-format -msgid "received unencrypted data after GSSAPI encryption request" -msgstr "после запроса шифрования GSSAPI получены незашифрованные данные" - -#: postmaster/postmaster.c:2147 -#, c-format -msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" -msgstr "" -"неподдерживаемый протокол клиентского приложения %u.%u; сервер поддерживает " -"%u.0 - %u.%u" - -#: postmaster/postmaster.c:2214 -#, c-format -msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." -msgstr "Допустимые значения: \"false\", 0, \"true\", 1, \"database\"." - -#: postmaster/postmaster.c:2255 -#, c-format -msgid "invalid startup packet layout: expected terminator as last byte" -msgstr "" -"неверная структура стартового пакета: последним байтом должен быть терминатор" - -#: postmaster/postmaster.c:2272 -#, c-format -msgid "no PostgreSQL user name specified in startup packet" -msgstr "в стартовом пакете не указано имя пользователя PostgreSQL" - -#: postmaster/postmaster.c:2336 -#, c-format -msgid "the database system is starting up" -msgstr "система баз данных запускается" - -#: postmaster/postmaster.c:2342 -#, c-format -msgid "the database system is not yet accepting connections" -msgstr "система БД ещё не принимает подключения" - -#: postmaster/postmaster.c:2343 -#, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "Согласованное состояние восстановления ещё не достигнуто." - -#: postmaster/postmaster.c:2347 -#, c-format -msgid "the database system is not accepting connections" -msgstr "система БД не принимает подключения" - -#: postmaster/postmaster.c:2348 -#, c-format -msgid "Hot standby mode is disabled." -msgstr "Режим горячего резерва отключён." - -#: postmaster/postmaster.c:2353 -#, c-format -msgid "the database system is shutting down" -msgstr "система баз данных останавливается" - -#: postmaster/postmaster.c:2358 -#, c-format -msgid "the database system is in recovery mode" -msgstr "система баз данных в режиме восстановления" - -#: postmaster/postmaster.c:2363 storage/ipc/procarray.c:491 -#: storage/ipc/sinvaladt.c:306 storage/lmgr/proc.c:353 -#, c-format -msgid "sorry, too many clients already" -msgstr "извините, уже слишком много клиентов" - -#: postmaster/postmaster.c:2450 +#: postmaster/postmaster.c:1874 #, c-format msgid "wrong key in cancel request for process %d" msgstr "неправильный ключ в запросе на отмену процесса %d" -#: postmaster/postmaster.c:2462 +#: postmaster/postmaster.c:1886 #, c-format msgid "PID %d in cancel request did not match any process" msgstr "процесс с кодом %d, полученным в запросе на отмену, не найден" -#: postmaster/postmaster.c:2729 +#: postmaster/postmaster.c:2106 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "получен SIGHUP, файлы конфигурации перезагружаются" #. translator: %s is a configuration file -#: postmaster/postmaster.c:2753 postmaster/postmaster.c:2757 +#: postmaster/postmaster.c:2134 postmaster/postmaster.c:2138 #, c-format msgid "%s was not reloaded" msgstr "%s не был перезагружен" -#: postmaster/postmaster.c:2767 +#: postmaster/postmaster.c:2148 #, c-format msgid "SSL configuration was not reloaded" msgstr "конфигурация SSL не была перезагружена" -#: postmaster/postmaster.c:2857 +#: postmaster/postmaster.c:2234 #, c-format msgid "received smart shutdown request" msgstr "получен запрос на \"вежливое\" выключение" -#: postmaster/postmaster.c:2898 +#: postmaster/postmaster.c:2275 #, c-format msgid "received fast shutdown request" msgstr "получен запрос на быстрое выключение" -#: postmaster/postmaster.c:2916 +#: postmaster/postmaster.c:2293 #, c-format msgid "aborting any active transactions" msgstr "прерывание всех активных транзакций" -#: postmaster/postmaster.c:2940 +#: postmaster/postmaster.c:2317 #, c-format msgid "received immediate shutdown request" msgstr "получен запрос на немедленное выключение" -#: postmaster/postmaster.c:3016 +#: postmaster/postmaster.c:2389 #, c-format msgid "shutdown at recovery target" msgstr "выключение при достижении цели восстановления" -#: postmaster/postmaster.c:3034 postmaster/postmaster.c:3070 +#: postmaster/postmaster.c:2407 postmaster/postmaster.c:2443 msgid "startup process" msgstr "стартовый процесс" -#: postmaster/postmaster.c:3037 +#: postmaster/postmaster.c:2410 #, c-format msgid "aborting startup due to startup process failure" msgstr "прерывание запуска из-за ошибки в стартовом процессе" -#: postmaster/postmaster.c:3110 +#: postmaster/postmaster.c:2485 #, c-format msgid "database system is ready to accept connections" msgstr "система БД готова принимать подключения" -#: postmaster/postmaster.c:3131 +#: postmaster/postmaster.c:2506 msgid "background writer process" msgstr "процесс фоновой записи" -#: postmaster/postmaster.c:3178 +#: postmaster/postmaster.c:2553 msgid "checkpointer process" msgstr "процесс контрольных точек" -#: postmaster/postmaster.c:3194 +#: postmaster/postmaster.c:2569 msgid "WAL writer process" msgstr "процесс записи WAL" -#: postmaster/postmaster.c:3209 +#: postmaster/postmaster.c:2584 msgid "WAL receiver process" msgstr "процесс считывания WAL" -#: postmaster/postmaster.c:3224 +#: postmaster/postmaster.c:2598 +msgid "WAL summarizer process" +msgstr "процесс обобщения WAL" + +#: postmaster/postmaster.c:2613 msgid "autovacuum launcher process" msgstr "процесс запуска автоочистки" -#: postmaster/postmaster.c:3242 +#: postmaster/postmaster.c:2631 msgid "archiver process" msgstr "процесс архивации" -#: postmaster/postmaster.c:3255 +#: postmaster/postmaster.c:2644 msgid "system logger process" msgstr "процесс системного протоколирования" -#: postmaster/postmaster.c:3312 +#: postmaster/postmaster.c:2661 +msgid "slot sync worker process" +msgstr "рабочий процесс синхронизации слотов" + +#: postmaster/postmaster.c:2717 #, c-format msgid "background worker \"%s\"" msgstr "фоновый процесс \"%s\"" -#: postmaster/postmaster.c:3391 postmaster/postmaster.c:3411 -#: postmaster/postmaster.c:3418 postmaster/postmaster.c:3436 +#: postmaster/postmaster.c:2796 postmaster/postmaster.c:2816 +#: postmaster/postmaster.c:2823 postmaster/postmaster.c:2841 msgid "server process" msgstr "процесс сервера" -#: postmaster/postmaster.c:3490 +#: postmaster/postmaster.c:2895 #, c-format msgid "terminating any other active server processes" msgstr "завершение всех остальных активных серверных процессов" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3665 +#: postmaster/postmaster.c:3082 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) завершился с кодом выхода %d" -#: postmaster/postmaster.c:3667 postmaster/postmaster.c:3679 -#: postmaster/postmaster.c:3689 postmaster/postmaster.c:3700 +#: postmaster/postmaster.c:3084 postmaster/postmaster.c:3096 +#: postmaster/postmaster.c:3106 postmaster/postmaster.c:3117 #, c-format msgid "Failed process was running: %s" msgstr "Завершившийся процесс выполнял действие: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3676 +#: postmaster/postmaster.c:3093 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) был прерван исключением 0x%X" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3686 +#: postmaster/postmaster.c:3103 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) был завершён по сигналу %d: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3698 +#: postmaster/postmaster.c:3115 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" -msgstr "%s (PID %d) завершился с неизвестным кодом состояния %d" +msgstr "%s (PID %d) завершился с нераспознанным кодом состояния %d" -#: postmaster/postmaster.c:3906 +#: postmaster/postmaster.c:3331 #, c-format msgid "abnormal database system shutdown" msgstr "аварийное выключение системы БД" -#: postmaster/postmaster.c:3932 +#: postmaster/postmaster.c:3357 #, c-format msgid "shutting down due to startup process failure" msgstr "сервер останавливается из-за ошибки в стартовом процессе" -#: postmaster/postmaster.c:3938 +#: postmaster/postmaster.c:3363 #, c-format -msgid "shutting down because restart_after_crash is off" -msgstr "сервер останавливается, так как параметр restart_after_crash равен off" +msgid "shutting down because \"restart_after_crash\" is off" +msgstr "сервер останавливается, так как \"restart_after_crash\" = \"off\"" -#: postmaster/postmaster.c:3950 +#: postmaster/postmaster.c:3375 #, c-format msgid "all server processes terminated; reinitializing" msgstr "все серверные процессы завершены... переинициализация" -#: postmaster/postmaster.c:4144 postmaster/postmaster.c:5462 -#: postmaster/postmaster.c:5860 +#: postmaster/postmaster.c:3574 postmaster/postmaster.c:3985 +#: postmaster/postmaster.c:4374 #, c-format msgid "could not generate random cancel key" msgstr "не удалось сгенерировать случайный ключ отмены" -#: postmaster/postmaster.c:4206 +#: postmaster/postmaster.c:3607 #, c-format msgid "could not fork new process for connection: %m" msgstr "породить новый процесс для соединения не удалось: %m" -#: postmaster/postmaster.c:4248 +#: postmaster/postmaster.c:3649 msgid "could not fork new process for connection: " msgstr "породить новый процесс для соединения не удалось: " -#: postmaster/postmaster.c:4354 +#: postmaster/postmaster.c:3683 #, c-format -msgid "connection received: host=%s port=%s" -msgstr "принято подключение: узел=%s порт=%s" +msgid "postmaster became multithreaded" +msgstr "процесс postmaster стал многопоточным" -#: postmaster/postmaster.c:4359 -#, c-format -msgid "connection received: host=%s" -msgstr "принято подключение: узел=%s" - -#: postmaster/postmaster.c:4596 -#, c-format -msgid "could not execute server process \"%s\": %m" -msgstr "запустить серверный процесс \"%s\" не удалось: %m" - -#: postmaster/postmaster.c:4654 -#, c-format -msgid "could not create backend parameter file mapping: error code %lu" -msgstr "" -"создать отображение файла серверных параметров не удалось (код ошибки: %lu)" - -#: postmaster/postmaster.c:4663 -#, c-format -msgid "could not map backend parameter memory: error code %lu" -msgstr "" -"отобразить файл серверных параметров в память не удалось (код ошибки: %lu)" - -#: postmaster/postmaster.c:4690 -#, c-format -msgid "subprocess command line too long" -msgstr "слишком длинная командная строка подпроцесса" - -#: postmaster/postmaster.c:4708 -#, c-format -msgid "CreateProcess() call failed: %m (error code %lu)" -msgstr "ошибка в CreateProcess(): %m (код ошибки: %lu)" - -#: postmaster/postmaster.c:4735 -#, c-format -msgid "could not unmap view of backend parameter file: error code %lu" -msgstr "" -"отключить отображение файла серверных параметров не удалось (код ошибки: %lu)" - -#: postmaster/postmaster.c:4739 -#, c-format -msgid "could not close handle to backend parameter file: error code %lu" -msgstr "" -"закрыть указатель файла серверных параметров не удалось (код ошибки: %lu)" - -#: postmaster/postmaster.c:4761 -#, c-format -msgid "giving up after too many tries to reserve shared memory" -msgstr "" -"число повторных попыток резервирования разделяемой памяти достигло предела" - -#: postmaster/postmaster.c:4762 -#, c-format -msgid "This might be caused by ASLR or antivirus software." -msgstr "Это может быть вызвано антивирусным ПО или механизмом ASLR." - -#: postmaster/postmaster.c:4935 -#, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "не удалось загрузить конфигурацию SSL в дочерний процесс" - -#: postmaster/postmaster.c:5060 -#, c-format -msgid "Please report this to <%s>." -msgstr "Пожалуйста, напишите об этой ошибке по адресу <%s>." - -#: postmaster/postmaster.c:5128 +#: postmaster/postmaster.c:3752 #, c-format msgid "database system is ready to accept read-only connections" msgstr "система БД готова принимать подключения в режиме \"только чтение\"" -#: postmaster/postmaster.c:5386 -#, c-format -msgid "could not fork startup process: %m" -msgstr "породить стартовый процесс не удалось: %m" - -#: postmaster/postmaster.c:5390 +#: postmaster/postmaster.c:3935 #, c-format -msgid "could not fork archiver process: %m" -msgstr "породить процесс архиватора не удалось: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "породить процесс \"%s\" не удалось: %m" -#: postmaster/postmaster.c:5394 -#, c-format -msgid "could not fork background writer process: %m" -msgstr "породить процесс фоновой записи не удалось: %m" - -#: postmaster/postmaster.c:5398 -#, c-format -msgid "could not fork checkpointer process: %m" -msgstr "породить процесс контрольных точек не удалось: %m" - -#: postmaster/postmaster.c:5402 -#, c-format -msgid "could not fork WAL writer process: %m" -msgstr "породить процесс записи WAL не удалось: %m" - -#: postmaster/postmaster.c:5406 -#, c-format -msgid "could not fork WAL receiver process: %m" -msgstr "породить процесс считывания WAL не удалось: %m" - -#: postmaster/postmaster.c:5410 -#, c-format -msgid "could not fork process: %m" -msgstr "породить процесс не удалось: %m" - -#: postmaster/postmaster.c:5611 postmaster/postmaster.c:5638 +#: postmaster/postmaster.c:4173 postmaster/postmaster.c:4207 #, c-format msgid "database connection requirement not indicated during registration" msgstr "" "при регистрации фонового процесса не указывалось, что ему требуется " "подключение к БД" -#: postmaster/postmaster.c:5622 postmaster/postmaster.c:5649 +#: postmaster/postmaster.c:4183 postmaster/postmaster.c:4217 #, c-format msgid "invalid processing mode in background worker" msgstr "неправильный режим обработки в фоновом процессе" -#: postmaster/postmaster.c:5734 -#, c-format -msgid "could not fork worker process: %m" -msgstr "породить рабочий процесс не удалось: %m" - -#: postmaster/postmaster.c:5846 -#, c-format -msgid "no slot available for new worker process" -msgstr "для нового рабочего процесса не нашлось свободного слота" - -#: postmaster/postmaster.c:6177 -#, c-format -msgid "could not duplicate socket %d for use in backend: error code %d" -msgstr "" -"продублировать сокет %d для серверного процесса не удалось (код ошибки: %d)" - -#: postmaster/postmaster.c:6209 -#, c-format -msgid "could not create inherited socket: error code %d\n" -msgstr "создать наследуемый сокет не удалось (код ошибки: %d)\n" - -#: postmaster/postmaster.c:6238 -#, c-format -msgid "could not open backend variables file \"%s\": %s\n" -msgstr "открыть файл серверных переменных \"%s\" не удалось: %s\n" - -#: postmaster/postmaster.c:6245 -#, c-format -msgid "could not read from backend variables file \"%s\": %s\n" -msgstr "прочитать файл серверных переменных \"%s\" не удалось: %s\n" - -#: postmaster/postmaster.c:6254 -#, c-format -msgid "could not remove file \"%s\": %s\n" -msgstr "не удалось стереть файл \"%s\": %s\n" - -#: postmaster/postmaster.c:6271 -#, c-format -msgid "could not map view of backend variables: error code %lu\n" -msgstr "отобразить файл серверных переменных не удалось (код ошибки: %lu)\n" - -#: postmaster/postmaster.c:6280 +#: postmaster/postmaster.c:4277 #, c-format -msgid "could not unmap view of backend variables: error code %lu\n" -msgstr "" -"отключить отображение файла серверных переменных не удалось (код ошибки: " -"%lu)\n" +msgid "could not fork background worker process: %m" +msgstr "породить фоновый рабочий процесс не удалось: %m" -#: postmaster/postmaster.c:6287 +#: postmaster/postmaster.c:4360 #, c-format -msgid "could not close handle to backend parameter variables: error code %lu\n" -msgstr "" -"закрыть указатель файла серверных переменных не удалось (код ошибки: %lu)\n" +msgid "no slot available for new background worker process" +msgstr "для нового фонового рабочего процесса нет свободного слота" -#: postmaster/postmaster.c:6446 +#: postmaster/postmaster.c:4623 #, c-format msgid "could not read exit code for process\n" msgstr "прочитать код завершения процесса не удалось\n" -#: postmaster/postmaster.c:6488 +#: postmaster/postmaster.c:4665 #, c-format msgid "could not post child completion status\n" msgstr "отправить состояние завершения потомка не удалось\n" -#: postmaster/syslogger.c:501 postmaster/syslogger.c:1222 +#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 #, c-format msgid "could not read from logger pipe: %m" msgstr "не удалось прочитать из канала протоколирования: %m" -#: postmaster/syslogger.c:598 postmaster/syslogger.c:612 +#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 #, c-format msgid "could not create pipe for syslog: %m" msgstr "не удалось создать канал для syslog: %m" -#: postmaster/syslogger.c:677 +#: postmaster/syslogger.c:712 #, c-format msgid "could not fork system logger: %m" msgstr "не удалось породить процесс системного протоколирования: %m" -#: postmaster/syslogger.c:713 +#: postmaster/syslogger.c:731 #, c-format msgid "redirecting log output to logging collector process" msgstr "передача вывода в протокол процессу сбора протоколов" -#: postmaster/syslogger.c:714 +#: postmaster/syslogger.c:732 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "В дальнейшем протоколы будут выводиться в каталог \"%s\"." -#: postmaster/syslogger.c:722 +#: postmaster/syslogger.c:740 #, c-format msgid "could not redirect stdout: %m" msgstr "не удалось перенаправить stdout: %m" -#: postmaster/syslogger.c:727 postmaster/syslogger.c:744 +#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 #, c-format msgid "could not redirect stderr: %m" msgstr "не удалось перенаправить stderr: %m" -#: postmaster/syslogger.c:1177 +#: postmaster/syslogger.c:1128 #, c-format -msgid "could not write to log file: %s\n" -msgstr "не удалось записать в файл протокола: %s\n" +msgid "could not write to log file: %m\n" +msgstr "не удалось записать в файл протокола: %m\n" -#: postmaster/syslogger.c:1295 +#: postmaster/syslogger.c:1246 #, c-format msgid "could not open log file \"%s\": %m" msgstr "не удалось открыть файл протокола \"%s\": %m" -#: postmaster/syslogger.c:1385 +#: postmaster/syslogger.c:1336 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "отключение автопрокрутки (чтобы включить, передайте SIGHUP)" -#: regex/regc_pg_locale.c:242 +#: postmaster/walsummarizer.c:740 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "процесс обобщения WAL не продвигается" + +#: postmaster/walsummarizer.c:741 +#, c-format +msgid "" +"Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/" +"%X in memory." +msgstr "" +"Обобщение должно охватить %X/%X, но оно остановилось на позиции %X/%X на " +"диске и %X/%X в памяти." + +#: postmaster/walsummarizer.c:755 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "" +"still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "ожидание обобщения позиции %X/%X продолжается %ld сек." +msgstr[1] "ожидание обобщения позиции %X/%X продолжается %ld сек." +msgstr[2] "ожидание обобщения позиции %X/%X продолжается %ld сек." + +#: postmaster/walsummarizer.c:760 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "Процесс обобщения достиг позиции %X/%X на диске и %X/%X в памяти." + +#: postmaster/walsummarizer.c:1000 +#, c-format +msgid "could not find a valid record after %X/%X" +msgstr "не удалось найти корректную запись после %X/%X" + +#: postmaster/walsummarizer.c:1045 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X: %s" +msgstr "не удалось прочитать WAL с линии времени %u в позиции %X/%X: %s" + +#: postmaster/walsummarizer.c:1051 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X" +msgstr "не удалось прочитать WAL с линии времени %u в позиции %X/%X" + +#: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "" "не удалось определить, какое правило сортировки использовать для регулярного " "выражения" -#: regex/regc_pg_locale.c:265 +#: regex/regc_pg_locale.c:262 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "" "недетерминированные правила сортировки не поддерживаются для регулярных " "выражений" -#: replication/libpqwalreceiver/libpqwalreceiver.c:245 -#: replication/libpqwalreceiver/libpqwalreceiver.c:332 +#: replication/libpqwalreceiver/libpqwalreceiver.c:267 +#: replication/libpqwalreceiver/libpqwalreceiver.c:358 #, c-format msgid "password is required" msgstr "требуется пароль" -#: replication/libpqwalreceiver/libpqwalreceiver.c:246 +#: replication/libpqwalreceiver/libpqwalreceiver.c:268 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "" "Только суперпользователи могут подключаться к серверу, не требующему пароль." -#: replication/libpqwalreceiver/libpqwalreceiver.c:247 +#: replication/libpqwalreceiver/libpqwalreceiver.c:269 #, c-format msgid "" "Target server's authentication method must be changed, or set " @@ -22018,29 +22567,30 @@ msgstr "" "Необходимо сменить метод аутентификации на целевом сервере или задать " "password_required=false в параметрах подписки." -#: replication/libpqwalreceiver/libpqwalreceiver.c:259 +#: replication/libpqwalreceiver/libpqwalreceiver.c:285 #, c-format msgid "could not clear search path: %s" msgstr "не удалось очистить путь поиска: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:305 +#: replication/libpqwalreceiver/libpqwalreceiver.c:331 +#: replication/libpqwalreceiver/libpqwalreceiver.c:517 #, c-format msgid "invalid connection string syntax: %s" msgstr "ошибочный синтаксис строки подключения: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:333 +#: replication/libpqwalreceiver/libpqwalreceiver.c:359 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "" "Пользователи, не являющиеся суперпользователями, должны задавать пароль в " "строке соединения." -#: replication/libpqwalreceiver/libpqwalreceiver.c:360 +#: replication/libpqwalreceiver/libpqwalreceiver.c:386 #, c-format msgid "could not parse connection string: %s" msgstr "не удалось разобрать строку подключения: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:433 +#: replication/libpqwalreceiver/libpqwalreceiver.c:459 #, c-format msgid "" "could not receive database system identifier and timeline ID from the " @@ -22049,13 +22599,13 @@ msgstr "" "не удалось получить идентификатор СУБД и код линии времени с главного " "сервера: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:449 -#: replication/libpqwalreceiver/libpqwalreceiver.c:692 +#: replication/libpqwalreceiver/libpqwalreceiver.c:476 +#: replication/libpqwalreceiver/libpqwalreceiver.c:763 #, c-format msgid "invalid response from primary server" msgstr "неверный ответ главного сервера" -#: replication/libpqwalreceiver/libpqwalreceiver.c:450 +#: replication/libpqwalreceiver/libpqwalreceiver.c:477 #, c-format msgid "" "Could not identify system: got %d rows and %d fields, expected %d rows and " @@ -22064,86 +22614,91 @@ msgstr "" "Не удалось идентифицировать систему, получено строк: %d, полей: %d " "(ожидалось: %d и %d (или более))." -#: replication/libpqwalreceiver/libpqwalreceiver.c:535 -#: replication/libpqwalreceiver/libpqwalreceiver.c:542 -#: replication/libpqwalreceiver/libpqwalreceiver.c:572 +#: replication/libpqwalreceiver/libpqwalreceiver.c:606 +#: replication/libpqwalreceiver/libpqwalreceiver.c:613 +#: replication/libpqwalreceiver/libpqwalreceiver.c:643 #, c-format msgid "could not start WAL streaming: %s" msgstr "не удалось начать трансляцию WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:596 +#: replication/libpqwalreceiver/libpqwalreceiver.c:667 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "не удалось отправить главному серверу сообщение о конце передачи: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:619 +#: replication/libpqwalreceiver/libpqwalreceiver.c:690 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "неожиданный набор данных после конца передачи" -#: replication/libpqwalreceiver/libpqwalreceiver.c:634 +#: replication/libpqwalreceiver/libpqwalreceiver.c:705 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "ошибка при остановке потоковой операции COPY: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:644 +#: replication/libpqwalreceiver/libpqwalreceiver.c:715 #, c-format msgid "error reading result of streaming command: %s" msgstr "ошибка при чтении результата команды передачи: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:653 -#: replication/libpqwalreceiver/libpqwalreceiver.c:889 +#: replication/libpqwalreceiver/libpqwalreceiver.c:724 +#: replication/libpqwalreceiver/libpqwalreceiver.c:957 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "неожиданный результат после CommandComplete: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:680 +#: replication/libpqwalreceiver/libpqwalreceiver.c:751 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "не удалось получить файл истории линии времени с главного сервера: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:693 +#: replication/libpqwalreceiver/libpqwalreceiver.c:764 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "Ожидался 1 кортеж с 2 полями, однако получено кортежей: %d, полей: %d." -#: replication/libpqwalreceiver/libpqwalreceiver.c:852 -#: replication/libpqwalreceiver/libpqwalreceiver.c:905 -#: replication/libpqwalreceiver/libpqwalreceiver.c:912 +#: replication/libpqwalreceiver/libpqwalreceiver.c:920 +#: replication/libpqwalreceiver/libpqwalreceiver.c:973 +#: replication/libpqwalreceiver/libpqwalreceiver.c:980 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "не удалось получить данные из потока WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:932 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 #, c-format msgid "could not send data to WAL stream: %s" msgstr "не удалось отправить данные в поток WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1024 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "не удалось создать слот репликации \"%s\": %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1070 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#, c-format +msgid "could not alter replication slot \"%s\": %s" +msgstr "не удалось изменить свойства слота репликации \"%s\": %s" + +#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 #, c-format msgid "invalid query response" msgstr "неверный ответ на запрос" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1071 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 #, c-format msgid "Expected %d fields, got %d fields." msgstr "Ожидалось полей: %d, получено: %d." -#: replication/libpqwalreceiver/libpqwalreceiver.c:1141 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 #, c-format msgid "the query interface requires a database connection" msgstr "для интерфейса запросов требуется подключение к БД" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1172 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 msgid "empty query" msgstr "пустой запрос" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1178 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 msgid "unexpected pipeline mode" msgstr "неожиданный режим канала" @@ -22156,35 +22711,35 @@ msgstr "" "параллельный применяющий процесс логической репликации для подписки \"%s\" " "завершён" -#: replication/logical/applyparallelworker.c:825 +#: replication/logical/applyparallelworker.c:822 #, c-format msgid "lost connection to the logical replication apply worker" msgstr "потеряна связь с применяющим процессом логической репликации" -#: replication/logical/applyparallelworker.c:1027 -#: replication/logical/applyparallelworker.c:1029 +#: replication/logical/applyparallelworker.c:1024 +#: replication/logical/applyparallelworker.c:1026 msgid "logical replication parallel apply worker" msgstr "параллельный применяющий процесс логической репликации" -#: replication/logical/applyparallelworker.c:1043 +#: replication/logical/applyparallelworker.c:1040 #, c-format msgid "logical replication parallel apply worker exited due to error" msgstr "" "параллельный применяющий процесс логической репликации завершён из-за ошибки" -#: replication/logical/applyparallelworker.c:1130 -#: replication/logical/applyparallelworker.c:1303 +#: replication/logical/applyparallelworker.c:1127 +#: replication/logical/applyparallelworker.c:1300 #, c-format msgid "lost connection to the logical replication parallel apply worker" msgstr "" "потеряна связь с параллельным применяющим процессом логическим репликации" -#: replication/logical/applyparallelworker.c:1183 +#: replication/logical/applyparallelworker.c:1180 #, c-format msgid "could not send data to shared-memory queue" msgstr "не удалось передать данные в очередь в разделяемой памяти" -#: replication/logical/applyparallelworker.c:1218 +#: replication/logical/applyparallelworker.c:1215 #, c-format msgid "" "logical replication apply worker will serialize the remaining changes of " @@ -22193,47 +22748,48 @@ msgstr "" "применяющий процесс логической репликации будет сериализовывать остальное " "содержимое удалённой транзакции %u в файл" -#: replication/logical/decode.c:180 replication/logical/logical.c:140 +#: replication/logical/decode.c:177 replication/logical/logical.c:141 #, c-format msgid "" -"logical decoding on standby requires wal_level >= logical on the primary" +"logical decoding on standby requires \"wal_level\" >= \"logical\" on the " +"primary" msgstr "" -"для логического декодирования на ведомом сервере требуется wal_level >= " -"logical на ведущем" +"для логического декодирования на ведомом сервере требуется \"wal_level\" >= " +"\"logical\" на ведущем" -#: replication/logical/launcher.c:331 +#: replication/logical/launcher.c:334 #, c-format msgid "cannot start logical replication workers when max_replication_slots = 0" msgstr "" "нельзя запустить процессы-обработчики логической репликации при " "max_replication_slots = 0" -#: replication/logical/launcher.c:424 +#: replication/logical/launcher.c:427 #, c-format msgid "out of logical replication worker slots" msgstr "недостаточно слотов для процессов логической репликации" -#: replication/logical/launcher.c:425 replication/logical/launcher.c:499 -#: replication/slot.c:1297 storage/lmgr/lock.c:964 storage/lmgr/lock.c:1002 -#: storage/lmgr/lock.c:2787 storage/lmgr/lock.c:4172 storage/lmgr/lock.c:4237 -#: storage/lmgr/lock.c:4587 storage/lmgr/predicate.c:2413 -#: storage/lmgr/predicate.c:2428 storage/lmgr/predicate.c:3825 +#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 +#: replication/slot.c:1524 storage/lmgr/lock.c:985 storage/lmgr/lock.c:1023 +#: storage/lmgr/lock.c:2836 storage/lmgr/lock.c:4221 storage/lmgr/lock.c:4286 +#: storage/lmgr/lock.c:4636 storage/lmgr/predicate.c:2469 +#: storage/lmgr/predicate.c:2484 storage/lmgr/predicate.c:3881 #, c-format -msgid "You might need to increase %s." -msgstr "Возможно, следует увеличить параметр %s." +msgid "You might need to increase \"%s\"." +msgstr "Возможно, следует увеличить параметр \"%s\"." -#: replication/logical/launcher.c:498 +#: replication/logical/launcher.c:513 #, c-format msgid "out of background worker slots" msgstr "недостаточно слотов для фоновых рабочих процессов" -#: replication/logical/launcher.c:705 +#: replication/logical/launcher.c:720 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "" "слот обработчика логической репликации %d пуст, подключиться к нему нельзя" -#: replication/logical/launcher.c:714 +#: replication/logical/launcher.c:729 #, c-format msgid "" "logical replication worker slot %d is already used by another worker, cannot " @@ -22242,28 +22798,28 @@ msgstr "" "слот обработчика логической репликации %d уже занят другим процессом, " "подключиться к нему нельзя" -#: replication/logical/logical.c:120 +#: replication/logical/logical.c:121 #, c-format -msgid "logical decoding requires wal_level >= logical" -msgstr "для логического декодирования требуется wal_level >= logical" +msgid "logical decoding requires \"wal_level\" >= \"logical\"" +msgstr "для логического декодирования требуется \"wal_level\" >= \"logical\"" -#: replication/logical/logical.c:125 +#: replication/logical/logical.c:126 #, c-format msgid "logical decoding requires a database connection" msgstr "для логического декодирования требуется подключение к БД" -#: replication/logical/logical.c:363 replication/logical/logical.c:517 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "" "физический слот репликации нельзя использовать для логического декодирования" -#: replication/logical/logical.c:368 replication/logical/logical.c:522 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "слот репликации \"%s\" создан не в этой базе данных" -#: replication/logical/logical.c:375 +#: replication/logical/logical.c:377 #, c-format msgid "" "cannot create logical replication slot in transaction that has performed " @@ -22271,12 +22827,29 @@ msgid "" msgstr "" "нельзя создать слот логической репликации в транзакции, осуществляющей запись" -#: replication/logical/logical.c:534 replication/logical/logical.c:541 +#: replication/logical/logical.c:540 +#, c-format +msgid "cannot use replication slot \"%s\" for logical decoding" +msgstr "" +"слот репликации \"%s\" нельзя использовать для логического декодирования" + +#: replication/logical/logical.c:542 replication/slot.c:798 +#: replication/slot.c:829 +#, c-format +msgid "This replication slot is being synchronized from the primary server." +msgstr "Этот слот репликации синхронизируется с ведущего сервера." + +#: replication/logical/logical.c:543 +#, c-format +msgid "Specify another replication slot." +msgstr "Укажите другой слот репликации." + +#: replication/logical/logical.c:554 replication/logical/logical.c:561 #, c-format msgid "can no longer get changes from replication slot \"%s\"" msgstr "из слота репликации \"%s\" больше нельзя получать изменения" -#: replication/logical/logical.c:536 +#: replication/logical/logical.c:556 #, c-format msgid "" "This slot has been invalidated because it exceeded the maximum reserved size." @@ -22284,81 +22857,81 @@ msgstr "" "Этот слот был аннулирован из-за превышения максимального зарезервированного " "размера." -#: replication/logical/logical.c:543 +#: replication/logical/logical.c:563 #, c-format msgid "" "This slot has been invalidated because it was conflicting with recovery." msgstr "Этот слот был аннулирован из-за конфликта с восстановлением." -#: replication/logical/logical.c:608 +#: replication/logical/logical.c:628 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "начинается логическое декодирование для слота \"%s\"" -#: replication/logical/logical.c:610 +#: replication/logical/logical.c:630 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "Передача транзакций, фиксируемых после %X/%X, чтение WAL с %X/%X." -#: replication/logical/logical.c:758 +#: replication/logical/logical.c:778 #, c-format msgid "" "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "" "слот \"%s\", модуль вывода \"%s\", в обработчике %s, связанный LSN: %X/%X" -#: replication/logical/logical.c:764 +#: replication/logical/logical.c:784 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "слот \"%s\", модуль вывода \"%s\", в обработчике %s" -#: replication/logical/logical.c:935 replication/logical/logical.c:980 -#: replication/logical/logical.c:1025 replication/logical/logical.c:1071 +#: replication/logical/logical.c:955 replication/logical/logical.c:1000 +#: replication/logical/logical.c:1045 replication/logical/logical.c:1091 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "для логической репликации во время подготовки требуется обработчик %s" -#: replication/logical/logical.c:1303 replication/logical/logical.c:1352 -#: replication/logical/logical.c:1393 replication/logical/logical.c:1479 -#: replication/logical/logical.c:1528 +#: replication/logical/logical.c:1323 replication/logical/logical.c:1372 +#: replication/logical/logical.c:1413 replication/logical/logical.c:1499 +#: replication/logical/logical.c:1548 #, c-format msgid "logical streaming requires a %s callback" msgstr "для логической потоковой репликации требуется обработчик %s" -#: replication/logical/logical.c:1438 +#: replication/logical/logical.c:1458 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "" "для логической потоковой репликации во время подготовки требуется обработчик " "%s" -#: replication/logical/logicalfuncs.c:126 +#: replication/logical/logicalfuncs.c:123 #, c-format msgid "slot name must not be null" msgstr "имя слота не может быть NULL" -#: replication/logical/logicalfuncs.c:142 +#: replication/logical/logicalfuncs.c:139 #, c-format msgid "options array must not be null" msgstr "массив параметров не может быть NULL" -#: replication/logical/logicalfuncs.c:159 +#: replication/logical/logicalfuncs.c:156 #, c-format msgid "array must be one-dimensional" msgstr "массив должен быть одномерным" -#: replication/logical/logicalfuncs.c:165 +#: replication/logical/logicalfuncs.c:162 #, c-format msgid "array must not contain nulls" msgstr "массив не должен содержать элементы null" -#: replication/logical/logicalfuncs.c:180 utils/adt/json.c:1484 -#: utils/adt/jsonb.c:1403 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1420 +#: utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "в массиве должно быть чётное число элементов" -#: replication/logical/logicalfuncs.c:227 +#: replication/logical/logicalfuncs.c:224 #, c-format msgid "" "logical decoding output plugin \"%s\" produces binary output, but function " @@ -22370,10 +22943,11 @@ msgstr "" #: replication/logical/origin.c:190 #, c-format msgid "" -"cannot query or manipulate replication origin when max_replication_slots = 0" +"cannot query or manipulate replication origin when \"max_replication_slots\" " +"is 0" msgstr "" "запрашивать или модифицировать источники репликации при " -"max_replication_slots = 0 нельзя" +"\"max_replication_slots\" = 0 нельзя" #: replication/logical/origin.c:195 #, c-format @@ -22410,10 +22984,11 @@ msgstr "" #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase max_replication_slots" +msgid "" +"could not find free replication state, increase \"max_replication_slots\"" msgstr "" "не удалось найти свободную ячейку для состояния репликации, увеличьте " -"max_replication_slots" +"\"max_replication_slots\"" #: replication/logical/origin.c:806 #, c-format @@ -22427,12 +23002,12 @@ msgstr "" "неверная контрольная сумма файла контрольной точки для слота репликации (%u " "вместо %u)" -#: replication/logical/origin.c:944 replication/logical/origin.c:1141 +#: replication/logical/origin.c:944 replication/logical/origin.c:1143 #, c-format msgid "replication origin with ID %d is already active for PID %d" msgstr "источник репликации с ID %d уже занят процессом с PID %d" -#: replication/logical/origin.c:955 replication/logical/origin.c:1153 +#: replication/logical/origin.c:955 replication/logical/origin.c:1156 #, c-format msgid "" "could not find free replication state slot for replication origin with ID %d" @@ -22440,29 +23015,29 @@ msgstr "" "не удалось найти свободный слот состояния репликации для источника " "репликации с ID %d" -#: replication/logical/origin.c:957 replication/logical/origin.c:1155 -#: replication/slot.c:2120 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 +#: replication/slot.c:2384 #, c-format -msgid "Increase max_replication_slots and try again." -msgstr "Увеличьте параметр max_replication_slots и повторите попытку." +msgid "Increase \"max_replication_slots\" and try again." +msgstr "Увеличьте параметр \"max_replication_slots\" и повторите попытку." -#: replication/logical/origin.c:1112 +#: replication/logical/origin.c:1114 #, c-format msgid "cannot setup replication origin when one is already setup" msgstr "нельзя настроить источник репликации, когда он уже настроен" -#: replication/logical/origin.c:1196 replication/logical/origin.c:1412 -#: replication/logical/origin.c:1432 +#: replication/logical/origin.c:1199 replication/logical/origin.c:1415 +#: replication/logical/origin.c:1435 #, c-format msgid "no replication origin is configured" msgstr "ни один источник репликации не настроен" -#: replication/logical/origin.c:1282 +#: replication/logical/origin.c:1285 #, c-format msgid "replication origin name \"%s\" is reserved" msgstr "имя источника репликации \"%s\" зарезервировано" -#: replication/logical/origin.c:1284 +#: replication/logical/origin.c:1287 #, c-format msgid "" "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." @@ -22470,17 +23045,17 @@ msgstr "" "Имена источников \"%s\", \"%s\", а также имена, начинающиеся с \"pg_\", " "зарезервированы." -#: replication/logical/relation.c:240 +#: replication/logical/relation.c:242 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:243 +#: replication/logical/relation.c:245 #, c-format msgid ", \"%s\"" msgstr ", \"%s\"" -#: replication/logical/relation.c:249 +#: replication/logical/relation.c:251 #, c-format msgid "" "logical replication target relation \"%s.%s\" is missing replicated column: " @@ -22498,7 +23073,7 @@ msgstr[2] "" "в целевом отношении логической репликации (\"%s.%s\") отсутствуют " "реплицируемые столбцы: %s" -#: replication/logical/relation.c:304 +#: replication/logical/relation.c:306 #, c-format msgid "" "logical replication target relation \"%s.%s\" uses system columns in REPLICA " @@ -22507,50 +23082,217 @@ msgstr "" "в целевом отношении логической репликации (\"%s.%s\") в индексе REPLICA " "IDENTITY используются системные столбцы" -#: replication/logical/relation.c:396 +#: replication/logical/relation.c:398 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "целевое отношение логической репликации \"%s.%s\" не существует" -#: replication/logical/reorderbuffer.c:3936 +#: replication/logical/reorderbuffer.c:3999 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "не удалось записать в файл данных для XID %u: %m" -#: replication/logical/reorderbuffer.c:4282 -#: replication/logical/reorderbuffer.c:4307 +#: replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4370 #, c-format msgid "could not read from reorderbuffer spill file: %m" -msgstr "не удалось прочитать из файла подкачки буфера пересортировки: %m" +msgstr "не удалось прочитать файл подкачки буфера пересортировки: %m" -#: replication/logical/reorderbuffer.c:4286 -#: replication/logical/reorderbuffer.c:4311 +#: replication/logical/reorderbuffer.c:4349 +#: replication/logical/reorderbuffer.c:4374 #, c-format msgid "" "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "" -"не удалось прочитать из файла подкачки буфера пересортировки (прочитано " -"байт: %d, требовалось: %u)" +"не удалось прочитать файл подкачки буфера пересортировки (прочитано байт: " +"%d, требовалось: %u)" -#: replication/logical/reorderbuffer.c:4561 +#: replication/logical/reorderbuffer.c:4624 #, c-format msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" msgstr "" "ошибка при удалении файла \"%s\" в процессе удаления pg_replslot/%s/xid*: %m" -#: replication/logical/reorderbuffer.c:5057 +#: replication/logical/reorderbuffer.c:5120 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d, требовалось: %d)" + +#: replication/logical/slotsync.c:215 +#, c-format +msgid "" +"could not synchronize replication slot \"%s\" because remote slot precedes " +"local slot" +msgstr "" +"синхронизировать слот репликации \"%s\" не удалось, так как состояние " +"удалённого слота предшествует локальному" + +#: replication/logical/slotsync.c:217 +#, c-format +msgid "" +"The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has " +"LSN %X/%X and catalog xmin %u." +msgstr "" +"Для удалённого слота текущий LSN %X/%X и xmin каталога %u, тогда как для " +"локального — LSN %X/%X и xmin каталога %u." + +#: replication/logical/slotsync.c:459 +#, c-format +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "слот репликации \"%s\" базы данных с OID %u удалён" + +#: replication/logical/slotsync.c:579 +#, c-format +msgid "could not synchronize replication slot \"%s\"" +msgstr "не удалось синхронизировать слот репликации \"%s\"" + +#: replication/logical/slotsync.c:580 +#, c-format +msgid "" +"Logical decoding could not find consistent point from local slot's LSN %X/%X." msgstr "" -"не удалось прочитать из файла \"%s\" (прочитано байт: %d, требовалось: %d)" +"При логическом декодировании не удалось найти точку согласованности от LSN " +"локального слота %X/%X." -#: replication/logical/snapbuild.c:639 +#: replication/logical/slotsync.c:589 +#, c-format +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "созданный слот репликации \"%s\" сейчас готов к синхронизации" + +#: replication/logical/slotsync.c:628 +#, c-format +msgid "" +"skipping slot synchronization because the received slot sync LSN %X/%X for " +"slot \"%s\" is ahead of the standby position %X/%X" +msgstr "" +"синхронизация слота пропускается, потому что полученная позиция LSN %X/%X " +"для слота \"%s\" предшествует позиции %X/%X на резервном сервере" + +#: replication/logical/slotsync.c:650 +#, c-format +msgid "" +"exiting from slot synchronization because same name slot \"%s\" already " +"exists on the standby" +msgstr "" +"синхронизация слота отменяется, потому что слот с таким же именем \"%s\" уже " +"существует на резервном сервере" + +#: replication/logical/slotsync.c:819 +#, c-format +msgid "could not fetch failover logical slots info from the primary server: %s" +msgstr "" +"не удалось получить информацию о переносимых логических слотах с главного " +"сервера: %s" + +#: replication/logical/slotsync.c:965 +#, c-format +msgid "" +"could not fetch primary_slot_name \"%s\" info from the primary server: %s" +msgstr "не удалось получить информацию о слоте \"%s\" с главного сервера: %s" + +# skip-rule: nastroy1 +#: replication/logical/slotsync.c:967 +#, c-format +msgid "Check if primary_slot_name is configured correctly." +msgstr "Проверьте правильность настройки primary_slot_name." + +#: replication/logical/slotsync.c:987 +#, c-format +msgid "cannot synchronize replication slots from a standby server" +msgstr "синхронизировать слоты репликации с резервного сервера нельзя" + +#. translator: second %s is a GUC variable name +#: replication/logical/slotsync.c:996 +#, c-format +msgid "" +"replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "" +"слот репликации \"%s\", заданный в \"%s\", не существует на главном сервере" + +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1029 +#, c-format +msgid "" +"replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "для синхронизации слотов репликации требуется указание \"%s\" в \"%s\"" + +#: replication/logical/slotsync.c:1050 +#, c-format +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "" +"для синхронизации слотов репликации требуется \"wal_level\" >= \"logical\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "для синхронизации слотов репликации требуется установить \"%s\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1077 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "для синхронизации слотов репликации требуется включить \"%s\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1129 +#, c-format +msgid "" +"replication slot synchronization worker will shut down because \"%s\" is " +"disabled" +msgstr "" +"процесс синхронизации слотов репликации будет остановлен, так как \"%s\" " +"отключён" + +#: replication/logical/slotsync.c:1138 +#, c-format +msgid "" +"replication slot synchronization worker will restart because of a parameter " +"change" +msgstr "" +"процесс синхронизации слотов репликации будет перезапущен вследствие " +"изменения параметров" + +#: replication/logical/slotsync.c:1162 +#, c-format +msgid "" +"replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "" +"процесс синхронизации слотов репликации останавливается, получив сигнал " +"SIGINT" + +#: replication/logical/slotsync.c:1287 +#, c-format +msgid "cannot synchronize replication slots when standby promotion is ongoing" +msgstr "" +"синхронизировать слоты репликации, когда выполняется повышение резервного " +"сервера, нельзя" + +#: replication/logical/slotsync.c:1295 +#, c-format +msgid "cannot synchronize replication slots concurrently" +msgstr "многопоточная синхронизация слотов репликации не поддерживается" + +#: replication/logical/slotsync.c:1403 +#, c-format +msgid "slot sync worker started" +msgstr "рабочий процесс синхронизации слотов запущен" + +#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 +#: replication/walreceiver.c:307 +#, c-format +msgid "could not connect to the primary server: %s" +msgstr "не удалось подключиться к главному серверу: %s" + +#: replication/logical/snapbuild.c:653 #, c-format msgid "initial slot snapshot too large" msgstr "изначальный снимок слота слишком большой" # skip-rule: capital-letter-first -#: replication/logical/snapbuild.c:693 +#: replication/logical/snapbuild.c:707 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "" @@ -22562,68 +23304,68 @@ msgstr[1] "" msgstr[2] "" "экспортирован снимок логического декодирования: \"%s\" (ид. транзакций: %u)" -#: replication/logical/snapbuild.c:1388 replication/logical/snapbuild.c:1480 -#: replication/logical/snapbuild.c:1996 +#: replication/logical/snapbuild.c:1404 replication/logical/snapbuild.c:1501 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "процесс логического декодирования достиг точки согласованности в %X/%X" -#: replication/logical/snapbuild.c:1390 +#: replication/logical/snapbuild.c:1406 #, c-format msgid "There are no running transactions." msgstr "Больше активных транзакций нет." -#: replication/logical/snapbuild.c:1432 +#: replication/logical/snapbuild.c:1453 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "" "процесс логического декодирования нашёл начальную стартовую точку в %X/%X" -#: replication/logical/snapbuild.c:1434 replication/logical/snapbuild.c:1458 +#: replication/logical/snapbuild.c:1455 replication/logical/snapbuild.c:1479 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "Ожидание транзакций (примерно %d), старее %u до конца." -#: replication/logical/snapbuild.c:1456 +#: replication/logical/snapbuild.c:1477 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "" "при логическом декодировании найдена начальная точка согласованности в %X/%X" -#: replication/logical/snapbuild.c:1482 +#: replication/logical/snapbuild.c:1503 #, c-format msgid "There are no old transactions anymore." msgstr "Больше старых транзакций нет." -#: replication/logical/snapbuild.c:1883 +#: replication/logical/snapbuild.c:1904 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "" "файл состояния snapbuild \"%s\" имеет неправильную сигнатуру (%u вместо %u)" -#: replication/logical/snapbuild.c:1889 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "" "файл состояния snapbuild \"%s\" имеет неправильную версию (%u вместо %u)" -#: replication/logical/snapbuild.c:1930 +#: replication/logical/snapbuild.c:1951 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "" "в файле состояния snapbuild \"%s\" неверная контрольная сумма (%u вместо %u)" -#: replication/logical/snapbuild.c:1998 +#: replication/logical/snapbuild.c:2019 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "Логическое декодирование начнётся с сохранённого снимка." -#: replication/logical/snapbuild.c:2105 +#: replication/logical/snapbuild.c:2126 #, c-format msgid "could not parse file name \"%s\"" msgstr "не удалось разобрать имя файла \"%s\"" -#: replication/logical/tablesync.c:160 +#: replication/logical/tablesync.c:161 #, c-format msgid "" "logical replication table synchronization worker for subscription \"%s\", " @@ -22632,7 +23374,7 @@ msgstr "" "процесс синхронизации таблицы при логической репликации для подписки \"%s\", " "таблицы \"%s\" закончил обработку" -#: replication/logical/tablesync.c:639 +#: replication/logical/tablesync.c:641 #, c-format msgid "" "logical replication apply worker for subscription \"%s\" will restart so " @@ -22641,25 +23383,25 @@ msgstr "" "применяющий процесс логической репликации для подписки \"%s\" будет " "перезапущен, чтобы можно было включить режим two_phase" -#: replication/logical/tablesync.c:814 replication/logical/tablesync.c:956 +#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "" "не удалось получить информацию о таблице \"%s.%s\" с сервера публикации: %s" -#: replication/logical/tablesync.c:821 +#: replication/logical/tablesync.c:834 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr "таблица \"%s.%s\" не найдена на сервере публикации" -#: replication/logical/tablesync.c:879 +#: replication/logical/tablesync.c:892 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "" "не удалось получить информацию о списке столбцов таблицы \"%s.%s\" с сервера " "публикации: %s" -#: replication/logical/tablesync.c:1058 +#: replication/logical/tablesync.c:1071 #, c-format msgid "" "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: " @@ -22668,25 +23410,25 @@ msgstr "" "не удалось получить информацию о предложении WHERE таблицы \"%s.%s\" с " "сервера публикации: %s" -#: replication/logical/tablesync.c:1217 +#: replication/logical/tablesync.c:1230 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "" "не удалось начать копирование начального содержимого таблицы \"%s.%s\": %s" -#: replication/logical/tablesync.c:1418 +#: replication/logical/tablesync.c:1429 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "" "при копировании таблицы не удалось начать транзакцию на сервере публикации: " "%s" -#: replication/logical/tablesync.c:1460 +#: replication/logical/tablesync.c:1472 #, c-format msgid "replication origin \"%s\" already exists" msgstr "источник репликации \"%s\" уже существует" -#: replication/logical/tablesync.c:1493 replication/logical/worker.c:2374 +#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 #, c-format msgid "" "user \"%s\" cannot replicate into relation with row-level security enabled: " @@ -22695,14 +23437,14 @@ msgstr "" "пользователь \"%s\" не может реплицировать данные в отношение с включённой " "защитой на уровне строк: \"%s\"" -#: replication/logical/tablesync.c:1506 +#: replication/logical/tablesync.c:1518 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "" "при копировании таблицы не удалось завершить транзакцию на сервере " "публикации: %s" -#: replication/logical/worker.c:499 +#: replication/logical/worker.c:481 #, c-format msgid "" "logical replication parallel apply worker for subscription \"%s\" will stop" @@ -22710,7 +23452,7 @@ msgstr "" "параллельный применяющий процесс логической репликации для подписки \"%s\" " "будет остановлен" -#: replication/logical/worker.c:501 +#: replication/logical/worker.c:483 #, c-format msgid "" "Cannot handle streamed replication transactions using parallel apply workers " @@ -22720,13 +23462,13 @@ msgstr "" "транзакций репликации, передаваемых в потоке, пока все таблицы не " "синхронизированы." -#: replication/logical/worker.c:863 replication/logical/worker.c:978 +#: replication/logical/worker.c:852 replication/logical/worker.c:967 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "" "неправильный формат двоичных данных для столбца логической репликации %d" -#: replication/logical/worker.c:2513 +#: replication/logical/worker.c:2500 #, c-format msgid "" "publisher did not send replica identity column expected by the logical " @@ -22735,7 +23477,7 @@ msgstr "" "сервер публикации не передал столбец идентификации реплики, ожидаемый для " "целевого отношения логической репликации \"%s.%s\"" -#: replication/logical/worker.c:2520 +#: replication/logical/worker.c:2507 #, c-format msgid "" "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY " @@ -22746,22 +23488,22 @@ msgstr "" "IDENTITY, ни ключа PRIMARY KEY, и публикуемое отношение не имеет " "характеристики REPLICA IDENTITY FULL" -#: replication/logical/worker.c:3384 +#: replication/logical/worker.c:3371 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "неверный тип сообщения логической репликации \"??? (%d)\"" -#: replication/logical/worker.c:3556 +#: replication/logical/worker.c:3543 #, c-format msgid "data stream from publisher has ended" msgstr "поток данных с сервера публикации закончился" -#: replication/logical/worker.c:3713 +#: replication/logical/worker.c:3697 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "завершение обработчика логической репликации из-за тайм-аута" -#: replication/logical/worker.c:3907 +#: replication/logical/worker.c:3891 #, c-format msgid "" "logical replication worker for subscription \"%s\" will stop because the " @@ -22770,7 +23512,7 @@ msgstr "" "процесс логической репликации для подписки \"%s\" будет остановлен, так как " "подписка была удалена" -#: replication/logical/worker.c:3920 +#: replication/logical/worker.c:3905 #, c-format msgid "" "logical replication worker for subscription \"%s\" will stop because the " @@ -22779,7 +23521,7 @@ msgstr "" "процесс логической репликации для подписки \"%s\" будет остановлен, так как " "подписка была отключена" -#: replication/logical/worker.c:3951 +#: replication/logical/worker.c:3936 #, c-format msgid "" "logical replication parallel apply worker for subscription \"%s\" will stop " @@ -22788,7 +23530,7 @@ msgstr "" "параллельный применяющий процесс логической репликации для подписки \"%s\" " "будет остановлен вследствие изменения параметров" -#: replication/logical/worker.c:3955 +#: replication/logical/worker.c:3940 #, c-format msgid "" "logical replication worker for subscription \"%s\" will restart because of a " @@ -22797,8 +23539,32 @@ msgstr "" "процесс логической репликации для подписки \"%s\" будет перезапущен " "вследствие изменения параметров" +#: replication/logical/worker.c:3954 +#, c-format +msgid "" +"logical replication parallel apply worker for subscription \"%s\" will stop " +"because the subscription owner's superuser privileges have been revoked" +msgstr "" +"процесс параллельного применения изменений логической репликации для " +"подписки \"%s\" будет остановлен, потому что владелец подписки был лишён " +"прав суперпользователя" + +#: replication/logical/worker.c:3958 +#, c-format +msgid "" +"logical replication worker for subscription \"%s\" will restart because the " +"subscription owner's superuser privileges have been revoked" +msgstr "" +"процесс логической репликации для подписки \"%s\" будет перезапущен, потому " +"что владелец подписки был лишён прав суперпользователя" + #: replication/logical/worker.c:4478 #, c-format +msgid "subscription has no replication slot set" +msgstr "для подписки не задан слот репликации" + +#: replication/logical/worker.c:4591 +#, c-format msgid "" "logical replication worker for subscription %u will not start because the " "subscription was removed during startup" @@ -22806,7 +23572,7 @@ msgstr "" "процесс логической репликации для подписки %u не будет запущен, так как " "подписка была удалена при старте" -#: replication/logical/worker.c:4493 +#: replication/logical/worker.c:4607 #, c-format msgid "" "logical replication worker for subscription \"%s\" will not start because " @@ -22815,7 +23581,7 @@ msgstr "" "процесс логической репликации для подписки \"%s\" не будет запущен, так как " "подписка была отключена при старте" -#: replication/logical/worker.c:4510 +#: replication/logical/worker.c:4631 #, c-format msgid "" "logical replication table synchronization worker for subscription \"%s\", " @@ -22824,40 +23590,35 @@ msgstr "" "процесс синхронизации таблицы при логической репликации для подписки \"%s\", " "таблицы \"%s\" запущен" -#: replication/logical/worker.c:4515 +#: replication/logical/worker.c:4636 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "" "запускается применяющий процесс логической репликации для подписки \"%s\"" -#: replication/logical/worker.c:4590 -#, c-format -msgid "subscription has no replication slot set" -msgstr "для подписки не задан слот репликации" - -#: replication/logical/worker.c:4757 +#: replication/logical/worker.c:4758 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "подписка \"%s\" была отключена из-за ошибки" -#: replication/logical/worker.c:4805 +#: replication/logical/worker.c:4806 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "" "обработчик логической репликации начинает пропускать транзакцию с LSN %X/%X" -#: replication/logical/worker.c:4819 +#: replication/logical/worker.c:4820 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "" "обработчик логической репликации завершил пропуск транзакции с LSN %X/%X" -#: replication/logical/worker.c:4901 +#: replication/logical/worker.c:4902 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "значение skip-LSN для подписки \"%s\" очищено" -#: replication/logical/worker.c:4902 +#: replication/logical/worker.c:4903 #, c-format msgid "" "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN " @@ -22866,7 +23627,7 @@ msgstr "" "Позиция завершения удалённой транзакции в WAL (LSN) %X/%X не совпала со " "значением skip-LSN %X/%X." -#: replication/logical/worker.c:4928 +#: replication/logical/worker.c:4940 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22875,7 +23636,7 @@ msgstr "" "обработка внешних данных для источника репликации \"%s\" в контексте " "сообщения типа \"%s\"" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:4944 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22884,7 +23645,7 @@ msgstr "" "обработка внешних данных из источника репликации \"%s\" в контексте " "сообщения типа \"%s\" в транзакции %u" -#: replication/logical/worker.c:4937 +#: replication/logical/worker.c:4949 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22893,7 +23654,7 @@ msgstr "" "обработка внешних данных для источника репликации \"%s\" в контексте " "сообщения типа \"%s\" в транзакции %u, конечная позиция %X/%X" -#: replication/logical/worker.c:4948 +#: replication/logical/worker.c:4960 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22903,7 +23664,7 @@ msgstr "" "сообщения типа \"%s\" для целевого отношения репликации \"%s.%s\" в " "транзакции %u" -#: replication/logical/worker.c:4955 +#: replication/logical/worker.c:4967 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22914,7 +23675,7 @@ msgstr "" "сообщения типа \"%s\" для целевого отношения репликации \"%s.%s\" в " "транзакции %u, конечная позиция %X/%X" -#: replication/logical/worker.c:4966 +#: replication/logical/worker.c:4978 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22925,7 +23686,7 @@ msgstr "" "сообщения типа \"%s\" для целевого отношения репликации \"%s.%s\", столбца " "\"%s\", в транзакции %u" -#: replication/logical/worker.c:4974 +#: replication/logical/worker.c:4986 #, c-format msgid "" "processing remote data for replication origin \"%s\" during message type " @@ -22936,22 +23697,27 @@ msgstr "" "сообщения типа \"%s\" для целевого отношения репликации \"%s.%s\", столбца " "\"%s\", в транзакции %u, конечная позиция %X/%X" -#: replication/pgoutput/pgoutput.c:317 +#: replication/pgoutput/pgoutput.c:322 #, c-format msgid "invalid proto_version" msgstr "неверное значение proto_version" -#: replication/pgoutput/pgoutput.c:322 +#: replication/pgoutput/pgoutput.c:327 #, c-format msgid "proto_version \"%s\" out of range" msgstr "значение proto_verson \"%s\" вне диапазона" -#: replication/pgoutput/pgoutput.c:339 +#: replication/pgoutput/pgoutput.c:344 #, c-format msgid "invalid publication_names syntax" msgstr "неверный синтаксис publication_names" -#: replication/pgoutput/pgoutput.c:440 +#: replication/pgoutput/pgoutput.c:414 replication/pgoutput/pgoutput.c:418 +#, c-format +msgid "option \"%s\" missing" +msgstr "параметр \"%s\" отсутствует" + +#: replication/pgoutput/pgoutput.c:478 #, c-format msgid "" "client sent proto_version=%d but server only supports protocol %d or lower" @@ -22959,7 +23725,7 @@ msgstr "" "клиент передал proto_version=%d, но сервер поддерживает только протокол %d и " "ниже" -#: replication/pgoutput/pgoutput.c:446 +#: replication/pgoutput/pgoutput.c:484 #, c-format msgid "" "client sent proto_version=%d but server only supports protocol %d or higher" @@ -22967,12 +23733,7 @@ msgstr "" "клиент передал proto_version=%d, но сервер поддерживает только протокол %d и " "выше" -#: replication/pgoutput/pgoutput.c:452 -#, c-format -msgid "publication_names parameter missing" -msgstr "отсутствует параметр publication_names" - -#: replication/pgoutput/pgoutput.c:466 +#: replication/pgoutput/pgoutput.c:499 #, c-format msgid "" "requested proto_version=%d does not support streaming, need %d or higher" @@ -22980,7 +23741,7 @@ msgstr "" "запрошенная версия proto_version=%d не поддерживает потоковую передачу, " "требуется версия %d или выше" -#: replication/pgoutput/pgoutput.c:472 +#: replication/pgoutput/pgoutput.c:505 #, c-format msgid "" "requested proto_version=%d does not support parallel streaming, need %d or " @@ -22989,12 +23750,12 @@ msgstr "" "запрошенная версия proto_version=%d не поддерживает параллельную потоковую " "передачу, требуется версия %d или выше" -#: replication/pgoutput/pgoutput.c:477 +#: replication/pgoutput/pgoutput.c:510 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "запрошена потоковая передача, но она не поддерживается модулем вывода" -#: replication/pgoutput/pgoutput.c:494 +#: replication/pgoutput/pgoutput.c:524 #, c-format msgid "" "requested proto_version=%d does not support two-phase commit, need %d or " @@ -23003,27 +23764,27 @@ msgstr "" "запрошенная версия proto_version=%d не поддерживает двухфазную фиксацию, " "требуется версия %d или выше" -#: replication/pgoutput/pgoutput.c:499 +#: replication/pgoutput/pgoutput.c:529 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "запрошена двухфазная фиксация, но она не поддерживается модулем вывода" -#: replication/slot.c:207 +#: replication/slot.c:260 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "имя слота репликации \"%s\" слишком короткое" -#: replication/slot.c:216 +#: replication/slot.c:269 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "имя слота репликации \"%s\" слишком длинное" -#: replication/slot.c:229 +#: replication/slot.c:282 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "имя слота репликации \"%s\" содержит недопустимый символ" -#: replication/slot.c:231 +#: replication/slot.c:284 #, c-format msgid "" "Replication slot names may only contain lower case letters, numbers, and the " @@ -23032,59 +23793,112 @@ msgstr "" "Имя слота репликации может содержать только буквы в нижнем регистре, цифры и " "знак подчёркивания." -#: replication/slot.c:285 +#: replication/slot.c:333 +#, c-format +msgid "cannot enable failover for a replication slot created on the standby" +msgstr "" +"слот репликации, созданный на ведомом сервере, не может быть переносимым" + +#: replication/slot.c:345 replication/slot.c:849 +#, c-format +msgid "cannot enable failover for a temporary replication slot" +msgstr "временный слот репликации не может быть переносимым" + +#: replication/slot.c:370 #, c-format msgid "replication slot \"%s\" already exists" msgstr "слот репликации \"%s\" уже существует" -#: replication/slot.c:295 +#: replication/slot.c:380 #, c-format msgid "all replication slots are in use" msgstr "используются все слоты репликации" -#: replication/slot.c:296 +#: replication/slot.c:381 #, c-format -msgid "Free one or increase max_replication_slots." -msgstr "Освободите ненужные или увеличьте параметр max_replication_slots." +msgid "Free one or increase \"max_replication_slots\"." +msgstr "Освободите ненужный или увеличьте параметр \"max_replication_slots\"." -#: replication/slot.c:474 replication/slotfuncs.c:736 -#: utils/activity/pgstat_replslot.c:55 utils/adt/genfile.c:774 +#: replication/slot.c:560 replication/slot.c:2450 replication/slotfuncs.c:661 +#: utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "слот репликации \"%s\" не существует" -#: replication/slot.c:520 replication/slot.c:1110 +#: replication/slot.c:606 replication/slot.c:1337 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "слот репликации \"%s\" занят процессом с PID %d" -#: replication/slot.c:756 replication/slot.c:1672 replication/slot.c:2055 +#: replication/slot.c:638 +#, c-format +msgid "acquired logical replication slot \"%s\"" +msgstr "получен слот логической репликации \"%s\"" + +#: replication/slot.c:640 +#, c-format +msgid "acquired physical replication slot \"%s\"" +msgstr "получен слот физической репликации \"%s\"" + +#: replication/slot.c:729 +#, c-format +msgid "released logical replication slot \"%s\"" +msgstr "освобождён слот логической репликации \"%s\"" + +#: replication/slot.c:731 +#, c-format +msgid "released physical replication slot \"%s\"" +msgstr "освобождён слот физической репликации \"%s\"" + +#: replication/slot.c:797 +#, c-format +msgid "cannot drop replication slot \"%s\"" +msgstr "удалить слот репликации \"%s\" нельзя" + +#: replication/slot.c:816 +#, c-format +msgid "cannot use %s with a physical replication slot" +msgstr "выполнить %s со слотом физической репликации нельзя" + +#: replication/slot.c:828 +#, c-format +msgid "cannot alter replication slot \"%s\"" +msgstr "изменить слот репликации \"%s\" нельзя" + +#: replication/slot.c:838 +#, c-format +msgid "cannot enable failover for a replication slot on the standby" +msgstr "сделать переносимым слот репликации на ведомом сервере нельзя" + +#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 #, c-format msgid "could not remove directory \"%s\"" msgstr "ошибка при удалении каталога \"%s\"" -#: replication/slot.c:1145 +#: replication/slot.c:1372 #, c-format -msgid "replication slots can only be used if max_replication_slots > 0" +msgid "replication slots can only be used if \"max_replication_slots\" > 0" msgstr "" -"слоты репликации можно использовать, только если max_replication_slots > 0" +"слоты репликации можно использовать, только если \"max_replication_slots\" > " +"0" -#: replication/slot.c:1150 +#: replication/slot.c:1377 #, c-format -msgid "replication slots can only be used if wal_level >= replica" -msgstr "слоты репликации можно использовать, только если wal_level >= replica" +msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" +msgstr "" +"слоты репликации можно использовать, только если \"wal_level\" >= \"replica\"" -#: replication/slot.c:1162 +#: replication/slot.c:1389 #, c-format msgid "permission denied to use replication slots" msgstr "нет прав для использования слотов репликации" -#: replication/slot.c:1163 +#: replication/slot.c:1390 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "Использовать слоты репликации могут только роли с атрибутом %s." -#: replication/slot.c:1271 +#: replication/slot.c:1498 #, c-format msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." @@ -23092,99 +23906,178 @@ msgstr[0] "Позиция restart_lsn %X/%X слота превысила пре msgstr[1] "Позиция restart_lsn %X/%X слота превысила предел на %llu Б." msgstr[2] "Позиция restart_lsn %X/%X слота превысила предел на %llu Б." -#: replication/slot.c:1279 +#: replication/slot.c:1506 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "Слот конфликтует с горизонтом xid %u." -#: replication/slot.c:1284 +#: replication/slot.c:1511 msgid "" -"Logical decoding on standby requires wal_level >= logical on the primary " -"server." +"Logical decoding on standby requires \"wal_level\" >= \"logical\" on the " +"primary server." msgstr "" -"Для логического декодирования на ведомом сервере требуется wal_level >= " -"logical на ведущем." +"Для логического декодирования на ведомом сервере требуется \"wal_level\" >= " +"\"logical\" на ведущем." -#: replication/slot.c:1292 +#: replication/slot.c:1519 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "завершение процесса %d для освобождения слота репликации \"%s\"" -#: replication/slot.c:1294 +#: replication/slot.c:1521 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "аннулирование устаревшего слота репликации \"%s\"" -#: replication/slot.c:1993 +#: replication/slot.c:2249 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "" "файл слота репликации \"%s\" имеет неправильную сигнатуру (%u вместо %u)" -#: replication/slot.c:2000 +#: replication/slot.c:2256 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "файл состояния snapbuild \"%s\" имеет неподдерживаемую версию %u" -#: replication/slot.c:2007 +#: replication/slot.c:2263 +#, c-format +msgid "replication slot file \"%s\" has corrupted length %u" +msgstr "у файла слота репликации \"%s\" неверная длина: %u" + +#: replication/slot.c:2299 +#, c-format +msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" +msgstr "" +"в файле слота репликации \"%s\" неверная контрольная сумма (%u вместо %u)" + +#: replication/slot.c:2333 +#, c-format +msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" +msgstr "" +"существует слот логической репликации \"%s\", но \"wal_level\" < \"logical\"" + +#: replication/slot.c:2335 +#, c-format +msgid "Change \"wal_level\" to be \"logical\" or higher." +msgstr "Смените \"wal_level\" на \"logical\" или более высокий уровень." + +#: replication/slot.c:2339 +#, c-format +msgid "" +"physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" +msgstr "" +"существует слот физической репликации \"%s\", но \"wal_level\" < \"replica\"" + +#: replication/slot.c:2341 +#, c-format +msgid "Change \"wal_level\" to be \"replica\" or higher." +msgstr "Смените \"wal_level\" на \"replica\" или более высокий уровень." + +#: replication/slot.c:2383 +#, c-format +msgid "too many replication slots active before shutdown" +msgstr "перед завершением активно слишком много слотов репликации" + +#: replication/slot.c:2458 +#, c-format +msgid "\"%s\" is not a physical replication slot" +msgstr "\"%s\" не является слотом физической репликации" + +#: replication/slot.c:2635 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "слот репликации \"%s\", указанный в параметре \"%s\", не существует" + +#: replication/slot.c:2637 replication/slot.c:2671 replication/slot.c:2686 +#, c-format +msgid "" +"Logical replication is waiting on the standby associated with replication " +"slot \"%s\"." +msgstr "" +"Логическая репликация ожидает резервного сервера, связанного со слотом " +"репликации \"%s\"." + +#: replication/slot.c:2639 #, c-format -msgid "replication slot file \"%s\" has corrupted length %u" -msgstr "у файла слота репликации \"%s\" неверная длина: %u" +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "Создайте слот репликации \"%s\" или опустите параметр \"%s\"." -#: replication/slot.c:2043 +#: replication/slot.c:2649 #, c-format -msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" msgstr "" -"в файле слота репликации \"%s\" неверная контрольная сумма (%u вместо %u)" +"слот логической репликации \"%s\" не может быть указан в параметре \"%s\"" -#: replication/slot.c:2077 +#: replication/slot.c:2651 #, c-format -msgid "logical replication slot \"%s\" exists, but wal_level < logical" -msgstr "существует слот логической репликации \"%s\", но wal_level < logical" +msgid "" +"Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "Логическая репликация ожидает исправления слота репликации \"%s\"." -#: replication/slot.c:2079 +#: replication/slot.c:2653 #, c-format -msgid "Change wal_level to be logical or higher." -msgstr "Смените wal_level на logical или более высокий уровень." +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "" +"Удалите указание слота логической репликации \"%s\" из параметра \"%s\"." -#: replication/slot.c:2083 +#: replication/slot.c:2669 #, c-format -msgid "physical replication slot \"%s\" exists, but wal_level < replica" -msgstr "существует слот физической репликации \"%s\", но wal_level < replica" +msgid "" +"physical replication slot \"%s\" specified in parameter \"%s\" has been " +"invalidated" +msgstr "" +"слот физической репликации \"%s\", указанный в параметре \"%s\", был " +"аннулирован" -#: replication/slot.c:2085 +#: replication/slot.c:2673 #, c-format -msgid "Change wal_level to be replica or higher." -msgstr "Смените wal_level на replica или более высокий уровень." +msgid "" +"Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "" +"Удалите и пересоздайте слот репликации \"%s\" или опустите параметр \"%s\"." -#: replication/slot.c:2119 +#: replication/slot.c:2684 #, c-format -msgid "too many replication slots active before shutdown" -msgstr "перед завершением активно слишком много слотов репликации" +msgid "" +"replication slot \"%s\" specified in parameter \"%s\" does not have " +"active_pid" +msgstr "" +"у слота репликации \"%s\", указанного в параметре \"%s\", нулевое значение " +"active_pid" + +#: replication/slot.c:2688 +#, c-format +msgid "" +"Start the standby associated with the replication slot \"%s\", or amend " +"parameter \"%s\"." +msgstr "" +"Запустите резервный сервер, связанный со слотом репликации \"%s\", или " +"опустите параметр \"%s\"." -#: replication/slotfuncs.c:601 +#: replication/slotfuncs.c:526 #, c-format msgid "invalid target WAL LSN" msgstr "неверный целевой LSN" -#: replication/slotfuncs.c:623 +#: replication/slotfuncs.c:548 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "слот репликации \"%s\" нельзя продвинуть вперёд" -#: replication/slotfuncs.c:625 +#: replication/slotfuncs.c:550 #, c-format msgid "" "This slot has never previously reserved WAL, or it has been invalidated." msgstr "Для этого слота ранее не резервировался WAL либо слот был аннулирован." -#: replication/slotfuncs.c:641 +#: replication/slotfuncs.c:566 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "" "продвинуть слот репликации к позиции %X/%X нельзя, минимальная позиция: %X/%X" -#: replication/slotfuncs.c:748 +#: replication/slotfuncs.c:673 #, c-format msgid "" "cannot copy physical replication slot \"%s\" as a logical replication slot" @@ -23192,7 +24085,7 @@ msgstr "" "слот физической репликации \"%s\" нельзя скопировать как слот логической " "репликации" -#: replication/slotfuncs.c:750 +#: replication/slotfuncs.c:675 #, c-format msgid "" "cannot copy logical replication slot \"%s\" as a physical replication slot" @@ -23200,17 +24093,17 @@ msgstr "" "слот логической репликации \"%s\" нельзя скопировать как слот физической " "репликации" -#: replication/slotfuncs.c:757 +#: replication/slotfuncs.c:682 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "скопировать слот репликации, для которого не резервируется WAL, нельзя" -#: replication/slotfuncs.c:834 +#: replication/slotfuncs.c:768 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "не удалось скопировать слот репликации \"%s\"" -#: replication/slotfuncs.c:836 +#: replication/slotfuncs.c:770 #, c-format msgid "" "The source replication slot was modified incompatibly during the copy " @@ -23219,21 +24112,26 @@ msgstr "" "Исходный слот репликации был модифицирован несовместимым образом во время " "копирования." -#: replication/slotfuncs.c:842 +#: replication/slotfuncs.c:776 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "" "скопировать слот логической репликации \"%s\" в незавершённом состоянии " "нельзя" -#: replication/slotfuncs.c:844 +#: replication/slotfuncs.c:778 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "" "Повторите попытку, когда для исходного слота репликации будет определена " "позиция confirmed_flush_lsn." -#: replication/syncrep.c:262 +#: replication/slotfuncs.c:877 +#, c-format +msgid "replication slots can only be synchronized to a standby server" +msgstr "слоты репликации могут синхронизироваться только с резервным сервером" + +#: replication/syncrep.c:261 #, c-format msgid "" "canceling the wait for synchronous replication and terminating connection " @@ -23242,7 +24140,7 @@ msgstr "" "отмена ожидания синхронной репликации и закрытие соединения по команде " "администратора" -#: replication/syncrep.c:263 replication/syncrep.c:280 +#: replication/syncrep.c:262 replication/syncrep.c:279 #, c-format msgid "" "The transaction has already committed locally, but might not have been " @@ -23251,147 +24149,142 @@ msgstr "" "Транзакция уже была зафиксирована локально, но, возможно, не была " "реплицирована на резервный сервер." -#: replication/syncrep.c:279 +#: replication/syncrep.c:278 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "отмена ожидания синхронной репликации по запросу пользователя" -#: replication/syncrep.c:486 +#: replication/syncrep.c:485 #, c-format -msgid "standby \"%s\" is now a synchronous standby with priority %u" -msgstr "резервный сервер \"%s\" стал синхронным с приоритетом %u" +msgid "standby \"%s\" is now a synchronous standby with priority %d" +msgstr "резервный сервер \"%s\" стал синхронным с приоритетом %d" -#: replication/syncrep.c:490 +#: replication/syncrep.c:489 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "" "резервный сервер \"%s\" стал кандидатом для включения в кворум синхронных " "резервных" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1013 #, c-format -msgid "synchronous_standby_names parser failed" -msgstr "ошибка при разборе synchronous_standby_names" +msgid "\"synchronous_standby_names\" parser failed" +msgstr "ошибка при разборе \"synchronous_standby_names\"" -#: replication/syncrep.c:1025 +#: replication/syncrep.c:1019 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "число синхронных резервных серверов (%d) должно быть больше нуля" -#: replication/walreceiver.c:180 +#: replication/walreceiver.c:176 #, c-format msgid "terminating walreceiver process due to administrator command" msgstr "завершение процесса считывания журнала по команде администратора" -#: replication/walreceiver.c:305 -#, c-format -msgid "could not connect to the primary server: %s" -msgstr "не удалось подключиться к главному серверу: %s" - -#: replication/walreceiver.c:352 +#: replication/walreceiver.c:354 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "идентификаторы СУБД на главном и резервном серверах различаются" -#: replication/walreceiver.c:353 +#: replication/walreceiver.c:355 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "Идентификатор на главном сервере: %s, на резервном: %s." -#: replication/walreceiver.c:364 +#: replication/walreceiver.c:366 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "" "последняя линия времени %u на главном сервере отстаёт от восстанавливаемой " "линии времени %u" -#: replication/walreceiver.c:417 +#: replication/walreceiver.c:419 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "" "начало передачи журнала с главного сервера, с позиции %X/%X на линии времени " "%u" -#: replication/walreceiver.c:421 +#: replication/walreceiver.c:423 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "перезапуск передачи журнала с позиции %X/%X на линии времени %u" -#: replication/walreceiver.c:457 +#: replication/walreceiver.c:458 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "продолжить передачу WAL нельзя, восстановление уже окончено" -#: replication/walreceiver.c:501 +#: replication/walreceiver.c:502 #, c-format msgid "replication terminated by primary server" msgstr "репликация прекращена главным сервером" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:503 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "На линии времени %u в %X/%X достигнут конец журнала." -#: replication/walreceiver.c:592 +#: replication/walreceiver.c:593 #, c-format msgid "terminating walreceiver due to timeout" msgstr "завершение приёма журнала из-за тайм-аута" -#: replication/walreceiver.c:624 +#: replication/walreceiver.c:625 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "" "на главном сервере больше нет журналов для запрошенной линии времени %u" -#: replication/walreceiver.c:640 replication/walreceiver.c:1066 +#: replication/walreceiver.c:641 replication/walreceiver.c:1071 #, c-format msgid "could not close WAL segment %s: %m" msgstr "не удалось закрыть сегмент WAL %s: %m" -#: replication/walreceiver.c:759 +#: replication/walreceiver.c:760 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "загрузка файла истории для линии времени %u с главного сервера" -#: replication/walreceiver.c:954 +#: replication/walreceiver.c:959 #, c-format -msgid "could not write to WAL segment %s at offset %u, length %lu: %m" -msgstr "не удалось записать в сегмент WAL %s (смещение %u, длина %lu): %m" +msgid "could not write to WAL segment %s at offset %d, length %lu: %m" +msgstr "не удалось записать в сегмент WAL %s (смещение %d, длина %lu): %m" -#: replication/walsender.c:519 +#: replication/walsender.c:531 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "использовать %s со слотом логической репликации нельзя" -#: replication/walsender.c:623 storage/smgr/md.c:1529 +#: replication/walsender.c:635 storage/smgr/md.c:1735 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "не удалось перейти к концу файла \"%s\": %m" -#: replication/walsender.c:627 +#: replication/walsender.c:639 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "не удалось перейти к началу файла \"%s\": %m" -#: replication/walsender.c:704 +#: replication/walsender.c:853 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "" "слот логической репликации нельзя использовать для физической репликации" -#: replication/walsender.c:770 +#: replication/walsender.c:919 #, c-format msgid "" "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "" "в истории сервера нет запрошенной начальной точки %X/%X на линии времени %u" -#: replication/walsender.c:773 +#: replication/walsender.c:922 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "История этого сервера ответвилась от линии времени %u в %X/%X." -#: replication/walsender.c:817 +#: replication/walsender.c:966 #, c-format msgid "" "requested starting point %X/%X is ahead of the WAL flush position of this " @@ -23400,75 +24293,75 @@ msgstr "" "запрошенная начальная точка %X/%X впереди позиции сброшенных данных журнала " "на этом сервере (%X/%X)" -#: replication/walsender.c:1010 +#: replication/walsender.c:1160 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "" "нераспознанное значение для параметра CREATE_REPLICATION_SLOT \"%s\": \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1095 +#: replication/walsender.c:1266 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s требуется выполнять не в транзакции" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1105 +#: replication/walsender.c:1276 #, c-format msgid "%s must be called inside a transaction" msgstr "%s требуется выполнять внутри транзакции" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1111 +#: replication/walsender.c:1282 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s требуется выполнять в транзакции уровня изоляции REPEATABLE READ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1116 +#: replication/walsender.c:1287 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%s требуется выполнять внутри транзакции только для чтения" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1122 +#: replication/walsender.c:1293 #, c-format msgid "%s must be called before any query" msgstr "%s требуется выполнять до каких-либо запросов" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1128 +#: replication/walsender.c:1299 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s требуется вызывать не в подтранзакции" -#: replication/walsender.c:1275 +#: replication/walsender.c:1472 #, c-format msgid "terminating walsender process after promotion" msgstr "завершение процесса передачи журнала после повышения" -#: replication/walsender.c:1696 +#: replication/walsender.c:2000 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "" "нельзя выполнять новые команды, пока процесс передачи WAL находится в режиме " "остановки" -#: replication/walsender.c:1731 +#: replication/walsender.c:2035 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "" "нельзя выполнять команды SQL в процессе, передающем WAL для физической " "репликации" -#: replication/walsender.c:1764 +#: replication/walsender.c:2068 #, c-format msgid "received replication command: %s" msgstr "получена команда репликации: %s" -#: replication/walsender.c:1772 tcop/fastpath.c:209 tcop/postgres.c:1138 -#: tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2210 -#: tcop/postgres.c:2648 tcop/postgres.c:2726 +#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1142 +#: tcop/postgres.c:1500 tcop/postgres.c:1752 tcop/postgres.c:2234 +#: tcop/postgres.c:2672 tcop/postgres.c:2749 #, c-format msgid "" "current transaction is aborted, commands ignored until end of transaction " @@ -23476,147 +24369,147 @@ msgid "" msgstr "" "текущая транзакция прервана, команды до конца блока транзакции игнорируются" -#: replication/walsender.c:1914 replication/walsender.c:1949 +#: replication/walsender.c:2233 replication/walsender.c:2268 #, c-format msgid "unexpected EOF on standby connection" msgstr "неожиданный обрыв соединения с резервным сервером" -#: replication/walsender.c:1937 +#: replication/walsender.c:2256 #, c-format msgid "invalid standby message type \"%c\"" msgstr "неверный тип сообщения резервного сервера: \"%c\"" -#: replication/walsender.c:2026 +#: replication/walsender.c:2345 #, c-format msgid "unexpected message type \"%c\"" msgstr "неожиданный тип сообщения \"%c\"" -#: replication/walsender.c:2439 +#: replication/walsender.c:2759 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "завершение процесса передачи журнала из-за тайм-аута репликации" -#: rewrite/rewriteDefine.c:111 rewrite/rewriteDefine.c:842 +#: rewrite/rewriteDefine.c:104 rewrite/rewriteDefine.c:835 #, c-format msgid "rule \"%s\" for relation \"%s\" already exists" msgstr "правило \"%s\" для отношения \"%s\" уже существует" -#: rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:780 +#: rewrite/rewriteDefine.c:261 rewrite/rewriteDefine.c:773 #, c-format msgid "relation \"%s\" cannot have rules" msgstr "к отношению \"%s\" не могут применяться правила" -#: rewrite/rewriteDefine.c:299 +#: rewrite/rewriteDefine.c:292 #, c-format msgid "rule actions on OLD are not implemented" msgstr "действия правил для OLD не реализованы" -#: rewrite/rewriteDefine.c:300 +#: rewrite/rewriteDefine.c:293 #, c-format msgid "Use views or triggers instead." msgstr "Воспользуйтесь представлениями или триггерами." -#: rewrite/rewriteDefine.c:304 +#: rewrite/rewriteDefine.c:297 #, c-format msgid "rule actions on NEW are not implemented" msgstr "действия правил для NEW не реализованы" -#: rewrite/rewriteDefine.c:305 +#: rewrite/rewriteDefine.c:298 #, c-format msgid "Use triggers instead." msgstr "Воспользуйтесь триггерами." -#: rewrite/rewriteDefine.c:319 +#: rewrite/rewriteDefine.c:312 #, c-format msgid "relation \"%s\" cannot have ON SELECT rules" msgstr "к отношению \"%s\" не могут применяться правила ON SELECT" -#: rewrite/rewriteDefine.c:329 +#: rewrite/rewriteDefine.c:322 #, c-format msgid "INSTEAD NOTHING rules on SELECT are not implemented" msgstr "правила INSTEAD NOTHING для SELECT не реализованы" -#: rewrite/rewriteDefine.c:330 +#: rewrite/rewriteDefine.c:323 #, c-format msgid "Use views instead." msgstr "Воспользуйтесь представлениями." -#: rewrite/rewriteDefine.c:338 +#: rewrite/rewriteDefine.c:331 #, c-format msgid "multiple actions for rules on SELECT are not implemented" msgstr "множественные действия в правилах для SELECT не поддерживаются" -#: rewrite/rewriteDefine.c:348 +#: rewrite/rewriteDefine.c:341 #, c-format msgid "rules on SELECT must have action INSTEAD SELECT" msgstr "в правилах для SELECT должно быть действие INSTEAD SELECT" -#: rewrite/rewriteDefine.c:356 +#: rewrite/rewriteDefine.c:349 #, c-format msgid "rules on SELECT must not contain data-modifying statements in WITH" msgstr "" "правила для SELECT не должны содержать операторы, изменяющие данные, в WITH" -#: rewrite/rewriteDefine.c:364 +#: rewrite/rewriteDefine.c:357 #, c-format msgid "event qualifications are not implemented for rules on SELECT" msgstr "в правилах для SELECT не может быть условий" -#: rewrite/rewriteDefine.c:391 +#: rewrite/rewriteDefine.c:384 #, c-format msgid "\"%s\" is already a view" msgstr "\"%s\" уже является представлением" -#: rewrite/rewriteDefine.c:415 +#: rewrite/rewriteDefine.c:408 #, c-format msgid "view rule for \"%s\" must be named \"%s\"" msgstr "правило представления для \"%s\" должно называться \"%s\"" -#: rewrite/rewriteDefine.c:442 +#: rewrite/rewriteDefine.c:435 #, c-format msgid "cannot have multiple RETURNING lists in a rule" msgstr "в правиле нельзя указать несколько списков RETURNING" -#: rewrite/rewriteDefine.c:447 +#: rewrite/rewriteDefine.c:440 #, c-format msgid "RETURNING lists are not supported in conditional rules" msgstr "списки RETURNING в условных правилах не поддерживаются" -#: rewrite/rewriteDefine.c:451 +#: rewrite/rewriteDefine.c:444 #, c-format msgid "RETURNING lists are not supported in non-INSTEAD rules" msgstr "списки RETURNING поддерживаются только в правилах INSTEAD" -#: rewrite/rewriteDefine.c:465 +#: rewrite/rewriteDefine.c:458 #, c-format msgid "non-view rule for \"%s\" must not be named \"%s\"" msgstr "" "не относящееся к представлению правило для \"%s\" не может называться \"%s\"" -#: rewrite/rewriteDefine.c:539 +#: rewrite/rewriteDefine.c:532 #, c-format msgid "SELECT rule's target list has too many entries" msgstr "список результата правила для SELECT содержит слишком много столбцов" -#: rewrite/rewriteDefine.c:540 +#: rewrite/rewriteDefine.c:533 #, c-format msgid "RETURNING list has too many entries" msgstr "список RETURNING содержит слишком много столбцов" -#: rewrite/rewriteDefine.c:567 +#: rewrite/rewriteDefine.c:560 #, c-format msgid "cannot convert relation containing dropped columns to view" msgstr "" "преобразовать отношение, содержащее удалённые столбцы, в представление нельзя" -#: rewrite/rewriteDefine.c:568 +#: rewrite/rewriteDefine.c:561 #, c-format msgid "" "cannot create a RETURNING list for a relation containing dropped columns" msgstr "" "создать список RETURNING для отношения, содержащего удалённые столбцы, нельзя" -#: rewrite/rewriteDefine.c:574 +#: rewrite/rewriteDefine.c:567 #, c-format msgid "" "SELECT rule's target entry %d has different column name from column \"%s\"" @@ -23624,67 +24517,67 @@ msgstr "" "элементу %d результата правила для SELECT присвоено имя, отличное от имени " "столбца \"%s\"" -#: rewrite/rewriteDefine.c:576 +#: rewrite/rewriteDefine.c:569 #, c-format msgid "SELECT target entry is named \"%s\"." msgstr "Имя элемента результата SELECT: \"%s\"." -#: rewrite/rewriteDefine.c:585 +#: rewrite/rewriteDefine.c:578 #, c-format msgid "SELECT rule's target entry %d has different type from column \"%s\"" msgstr "" "элемент %d результата правила для SELECT имеет тип, отличный от типа столбца " "\"%s\"" -#: rewrite/rewriteDefine.c:587 +#: rewrite/rewriteDefine.c:580 #, c-format msgid "RETURNING list's entry %d has different type from column \"%s\"" msgstr "элемент %d списка RETURNING имеет тип, отличный от типа столбца \"%s\"" -#: rewrite/rewriteDefine.c:590 rewrite/rewriteDefine.c:614 +#: rewrite/rewriteDefine.c:583 rewrite/rewriteDefine.c:607 #, c-format msgid "SELECT target entry has type %s, but column has type %s." msgstr "Элемент результата SELECT имеет тип %s, тогда как тип столбца - %s." -#: rewrite/rewriteDefine.c:593 rewrite/rewriteDefine.c:618 +#: rewrite/rewriteDefine.c:586 rewrite/rewriteDefine.c:611 #, c-format msgid "RETURNING list entry has type %s, but column has type %s." msgstr "Элемент списка RETURNING имеет тип %s, тогда как тип столбца - %s." -#: rewrite/rewriteDefine.c:609 +#: rewrite/rewriteDefine.c:602 #, c-format msgid "SELECT rule's target entry %d has different size from column \"%s\"" msgstr "" "элемент %d результата правила для SELECT имеет размер, отличный от столбца " "\"%s\"" -#: rewrite/rewriteDefine.c:611 +#: rewrite/rewriteDefine.c:604 #, c-format msgid "RETURNING list's entry %d has different size from column \"%s\"" msgstr "элемент %d списка RETURNING имеет размер, отличный от столбца \"%s\"" -#: rewrite/rewriteDefine.c:628 +#: rewrite/rewriteDefine.c:621 #, c-format msgid "SELECT rule's target list has too few entries" msgstr "список результата правила для SELECT содержит недостаточно элементов" -#: rewrite/rewriteDefine.c:629 +#: rewrite/rewriteDefine.c:622 #, c-format msgid "RETURNING list has too few entries" msgstr "список RETURNING содержит недостаточно элементов" -#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:833 -#: rewrite/rewriteSupport.c:109 +#: rewrite/rewriteDefine.c:711 rewrite/rewriteDefine.c:826 +#: rewrite/rewriteSupport.c:108 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist" msgstr "правило \"%s\" для отношения\"%s\" не существует" -#: rewrite/rewriteDefine.c:852 +#: rewrite/rewriteDefine.c:845 #, c-format msgid "renaming an ON SELECT rule is not allowed" msgstr "переименовывать правило ON SELECT нельзя" -#: rewrite/rewriteHandler.c:583 +#: rewrite/rewriteHandler.c:588 #, c-format msgid "" "WITH query name \"%s\" appears in both a rule action and the query being " @@ -23693,7 +24586,7 @@ msgstr "" "имя запроса WITH \"%s\" оказалось и в действии правила, и в переписываемом " "запросе" -#: rewrite/rewriteHandler.c:610 +#: rewrite/rewriteHandler.c:615 #, c-format msgid "" "INSERT ... SELECT rule actions are not supported for queries having data-" @@ -23702,113 +24595,123 @@ msgstr "" "правила INSERT ... SELECT не поддерживаются для запросов с операторами, " "изменяющими данные, в WITH" -#: rewrite/rewriteHandler.c:663 +#: rewrite/rewriteHandler.c:668 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "RETURNING можно определить только для одного правила" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:934 +#: rewrite/rewriteHandler.c:900 rewrite/rewriteHandler.c:939 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "в столбец \"%s\" можно вставить только значение по умолчанию" -#: rewrite/rewriteHandler.c:897 rewrite/rewriteHandler.c:963 +#: rewrite/rewriteHandler.c:902 rewrite/rewriteHandler.c:968 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "" "Столбец \"%s\" является столбцом идентификации со свойством GENERATED ALWAYS." -#: rewrite/rewriteHandler.c:899 +#: rewrite/rewriteHandler.c:904 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "Для переопределения укажите OVERRIDING SYSTEM VALUE." -#: rewrite/rewriteHandler.c:961 rewrite/rewriteHandler.c:969 +#: rewrite/rewriteHandler.c:966 rewrite/rewriteHandler.c:974 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "столбцу \"%s\" можно присвоить только значение DEFAULT" -#: rewrite/rewriteHandler.c:1116 rewrite/rewriteHandler.c:1134 +#: rewrite/rewriteHandler.c:1109 rewrite/rewriteHandler.c:1127 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "многочисленные присвоения одному столбцу \"%s\"" -#: rewrite/rewriteHandler.c:2119 rewrite/rewriteHandler.c:4040 +#: rewrite/rewriteHandler.c:1682 +#, c-format +msgid "MERGE is not supported for relations with rules." +msgstr "MERGE не поддерживается для отношений с правилами." + +#: rewrite/rewriteHandler.c:1722 rewrite/rewriteHandler.c:3262 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "доступ к несистемному представлению \"%s\" ограничен" + +#: rewrite/rewriteHandler.c:2122 rewrite/rewriteHandler.c:4254 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "обнаружена бесконечная рекурсия в правилах для отношения \"%s\"" -#: rewrite/rewriteHandler.c:2204 +#: rewrite/rewriteHandler.c:2227 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "обнаружена бесконечная рекурсия в политике для отношения \"%s\"" -#: rewrite/rewriteHandler.c:2524 +#: rewrite/rewriteHandler.c:2589 msgid "Junk view columns are not updatable." msgstr "Утилизируемые столбцы представлений не обновляются." -#: rewrite/rewriteHandler.c:2529 +#: rewrite/rewriteHandler.c:2594 msgid "" "View columns that are not columns of their base relation are not updatable." msgstr "" "Столбцы представлений, не являющиеся столбцами базовых отношений, не " "обновляются." -#: rewrite/rewriteHandler.c:2532 +#: rewrite/rewriteHandler.c:2597 msgid "View columns that refer to system columns are not updatable." msgstr "" "Столбцы представлений, ссылающиеся на системные столбцы, не обновляются." -#: rewrite/rewriteHandler.c:2535 +#: rewrite/rewriteHandler.c:2600 msgid "View columns that return whole-row references are not updatable." msgstr "" "Столбцы представлений, возвращающие ссылки на всю строку, не обновляются." -#: rewrite/rewriteHandler.c:2596 +#: rewrite/rewriteHandler.c:2661 msgid "Views containing DISTINCT are not automatically updatable." msgstr "Представления с DISTINCT не обновляются автоматически." -#: rewrite/rewriteHandler.c:2599 +#: rewrite/rewriteHandler.c:2664 msgid "Views containing GROUP BY are not automatically updatable." msgstr "Представления с GROUP BY не обновляются автоматически." -#: rewrite/rewriteHandler.c:2602 +#: rewrite/rewriteHandler.c:2667 msgid "Views containing HAVING are not automatically updatable." msgstr "Представления с HAVING не обновляются автоматически." -#: rewrite/rewriteHandler.c:2605 +#: rewrite/rewriteHandler.c:2670 msgid "" "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "" "Представления с UNION, INTERSECT или EXCEPT не обновляются автоматически." -#: rewrite/rewriteHandler.c:2608 +#: rewrite/rewriteHandler.c:2673 msgid "Views containing WITH are not automatically updatable." msgstr "Представления с WITH не обновляются автоматически." -#: rewrite/rewriteHandler.c:2611 +#: rewrite/rewriteHandler.c:2676 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "Представления с LIMIT или OFFSET не обновляются автоматически." -#: rewrite/rewriteHandler.c:2623 +#: rewrite/rewriteHandler.c:2688 msgid "Views that return aggregate functions are not automatically updatable." msgstr "" "Представления, возвращающие агрегатные функции, не обновляются автоматически." -#: rewrite/rewriteHandler.c:2626 +#: rewrite/rewriteHandler.c:2691 msgid "Views that return window functions are not automatically updatable." msgstr "" "Представления, возвращающие оконные функции, не обновляются автоматически." -#: rewrite/rewriteHandler.c:2629 +#: rewrite/rewriteHandler.c:2694 msgid "" "Views that return set-returning functions are not automatically updatable." msgstr "" "Представления, возвращающие функции с результатом-множеством, не обновляются " "автоматически." -#: rewrite/rewriteHandler.c:2636 rewrite/rewriteHandler.c:2640 -#: rewrite/rewriteHandler.c:2648 +#: rewrite/rewriteHandler.c:2701 rewrite/rewriteHandler.c:2705 +#: rewrite/rewriteHandler.c:2713 msgid "" "Views that do not select from a single table or view are not automatically " "updatable." @@ -23816,27 +24719,124 @@ msgstr "" "Представления, выбирающие данные не из одной таблицы или представления, не " "обновляются автоматически." -#: rewrite/rewriteHandler.c:2651 +#: rewrite/rewriteHandler.c:2716 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "Представления, содержащие TABLESAMPLE, не обновляются автоматически." -#: rewrite/rewriteHandler.c:2675 +#: rewrite/rewriteHandler.c:2740 msgid "Views that have no updatable columns are not automatically updatable." msgstr "" "Представления, не содержащие обновляемых столбцов, не обновляются " "автоматически." -#: rewrite/rewriteHandler.c:3155 +#: rewrite/rewriteHandler.c:3121 rewrite/rewriteHandler.c:3156 +#, c-format +msgid "cannot insert into view \"%s\"" +msgstr "вставить данные в представление \"%s\" нельзя" + +#: rewrite/rewriteHandler.c:3124 +#, c-format +msgid "" +"To enable inserting into the view, provide an INSTEAD OF INSERT trigger or " +"an unconditional ON INSERT DO INSTEAD rule." +msgstr "" +"Чтобы представление допускало добавление данных, установите триггер INSTEAD " +"OF INSERT или безусловное правило ON INSERT DO INSTEAD." + +#: rewrite/rewriteHandler.c:3129 rewrite/rewriteHandler.c:3165 +#, c-format +msgid "cannot update view \"%s\"" +msgstr "изменить данные в представлении \"%s\" нельзя" + +#: rewrite/rewriteHandler.c:3132 +#, c-format +msgid "" +"To enable updating the view, provide an INSTEAD OF UPDATE trigger or an " +"unconditional ON UPDATE DO INSTEAD rule." +msgstr "" +"Чтобы представление допускало изменение данных, установите триггер INSTEAD " +"OF UPDATE или безусловное правило ON UPDATE DO INSTEAD." + +#: rewrite/rewriteHandler.c:3137 rewrite/rewriteHandler.c:3174 +#, c-format +msgid "cannot delete from view \"%s\"" +msgstr "удалить данные из представления \"%s\" нельзя" + +#: rewrite/rewriteHandler.c:3140 +#, c-format +msgid "" +"To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an " +"unconditional ON DELETE DO INSTEAD rule." +msgstr "" +"Чтобы представление допускало удаление данных, установите триггер INSTEAD OF " +"DELETE или безусловное правило ON DELETE DO INSTEAD." + +#: rewrite/rewriteHandler.c:3159 +#, c-format +msgid "" +"To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT " +"trigger." +msgstr "" +"Чтобы представление допускало добавление данных посредством MERGE, создайте " +"триггер INSTEAD OF INSERT." + +#: rewrite/rewriteHandler.c:3168 +#, c-format +msgid "" +"To enable updating the view using MERGE, provide an INSTEAD OF UPDATE " +"trigger." +msgstr "" +"Чтобы представление допускало изменение данных посредством MERGE, создайте " +"триггер INSTEAD OF UPDATE." + +#: rewrite/rewriteHandler.c:3177 +#, c-format +msgid "" +"To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE " +"trigger." +msgstr "" +"Чтобы представление допускало удаление данных посредством MERGE, создайте " +"триггер INSTEAD OF DELETE." + +#: rewrite/rewriteHandler.c:3352 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "вставить данные в столбец \"%s\" представления \"%s\" нельзя" -#: rewrite/rewriteHandler.c:3163 +#: rewrite/rewriteHandler.c:3360 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "изменить данные в столбце \"%s\" представления \"%s\" нельзя" -#: rewrite/rewriteHandler.c:3667 +#: rewrite/rewriteHandler.c:3368 +#, c-format +msgid "cannot merge into column \"%s\" of view \"%s\"" +msgstr "столбец \"%s\" представления \"%s\" не допускает объединение данных" + +#: rewrite/rewriteHandler.c:3396 +#, c-format +msgid "cannot merge into view \"%s\"" +msgstr "представление \"%s\" не допускает объединение данных" + +#: rewrite/rewriteHandler.c:3398 +#, c-format +msgid "" +"MERGE is not supported for views with INSTEAD OF triggers for some actions " +"but not all." +msgstr "" +"MERGE не поддерживается для представлений, имеющих триггеры INSTEAD OF для " +"некоторых, но не всех действий." + +#: rewrite/rewriteHandler.c:3399 +#, c-format +msgid "" +"To enable merging into the view, either provide a full set of INSTEAD OF " +"triggers or drop the existing INSTEAD OF triggers." +msgstr "" +"Чтобы представление допускало объединение данных, или предоставьте полный " +"набор триггеров INSTEAD OF, или удалите существующие триггеры INSTEAD OF." + +#: rewrite/rewriteHandler.c:3912 #, c-format msgid "" "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in " @@ -23845,7 +24845,7 @@ msgstr "" "правила DO INSTEAD NOTIFY не поддерживаются в операторах, изменяющих данные, " "в WITH" -#: rewrite/rewriteHandler.c:3678 +#: rewrite/rewriteHandler.c:3923 #, c-format msgid "" "DO INSTEAD NOTHING rules are not supported for data-modifying statements in " @@ -23854,7 +24854,7 @@ msgstr "" "правила DO INSTEAD NOTHING не поддерживаются в операторах, изменяющих " "данные, в WITH" -#: rewrite/rewriteHandler.c:3692 +#: rewrite/rewriteHandler.c:3937 #, c-format msgid "" "conditional DO INSTEAD rules are not supported for data-modifying statements " @@ -23863,13 +24863,13 @@ msgstr "" "условные правила DO INSTEAD не поддерживаются для операторов, изменяющих " "данные, в WITH" -#: rewrite/rewriteHandler.c:3696 +#: rewrite/rewriteHandler.c:3941 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "" "правила DO ALSO не поддерживаются для операторов, изменяющих данные, в WITH" -#: rewrite/rewriteHandler.c:3701 +#: rewrite/rewriteHandler.c:3946 #, c-format msgid "" "multi-statement DO INSTEAD rules are not supported for data-modifying " @@ -23878,52 +24878,50 @@ msgstr "" "составные правила DO INSTEAD не поддерживаются для операторов, изменяющих " "данные, в WITH" -#: rewrite/rewriteHandler.c:3968 rewrite/rewriteHandler.c:3976 -#: rewrite/rewriteHandler.c:3984 -#, c-format +#: rewrite/rewriteHandler.c:4206 msgid "" "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "" "Представления в сочетании с правилами DO INSTEAD с условиями не обновляются " "автоматически." -#: rewrite/rewriteHandler.c:4089 +#: rewrite/rewriteHandler.c:4303 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "выполнить INSERT RETURNING для отношения \"%s\" нельзя" -#: rewrite/rewriteHandler.c:4091 +#: rewrite/rewriteHandler.c:4305 #, c-format msgid "" "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "" "Необходимо безусловное правило ON INSERT DO INSTEAD с предложением RETURNING." -#: rewrite/rewriteHandler.c:4096 +#: rewrite/rewriteHandler.c:4310 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "выполнить UPDATE RETURNING для отношения \"%s\" нельзя" -#: rewrite/rewriteHandler.c:4098 +#: rewrite/rewriteHandler.c:4312 #, c-format msgid "" "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "" "Необходимо безусловное правило ON UPDATE DO INSTEAD с предложением RETURNING." -#: rewrite/rewriteHandler.c:4103 +#: rewrite/rewriteHandler.c:4317 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "выполнить DELETE RETURNING для отношения \"%s\" нельзя" -#: rewrite/rewriteHandler.c:4105 +#: rewrite/rewriteHandler.c:4319 #, c-format msgid "" "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "" "Необходимо безусловное правило ON DELETE DO INSTEAD с предложением RETURNING." -#: rewrite/rewriteHandler.c:4123 +#: rewrite/rewriteHandler.c:4337 #, c-format msgid "" "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or " @@ -23932,7 +24930,7 @@ msgstr "" "INSERT c предложением ON CONFLICT нельзя использовать с таблицей, для " "которой заданы правила INSERT или UPDATE" -#: rewrite/rewriteHandler.c:4180 +#: rewrite/rewriteHandler.c:4394 #, c-format msgid "" "WITH cannot be used in a query that is rewritten by rules into multiple " @@ -23941,17 +24939,17 @@ msgstr "" "WITH нельзя использовать в запросе, преобразованном правилами в несколько " "запросов" -#: rewrite/rewriteManip.c:1075 +#: rewrite/rewriteManip.c:1084 #, c-format msgid "conditional utility statements are not implemented" msgstr "условные служебные операторы не реализованы" -#: rewrite/rewriteManip.c:1419 +#: rewrite/rewriteManip.c:1431 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "условие WHERE CURRENT OF для представлений не реализовано" -#: rewrite/rewriteManip.c:1754 +#: rewrite/rewriteManip.c:1767 #, c-format msgid "" "NEW variables in ON UPDATE rules cannot reference columns that are part of a " @@ -23995,41 +24993,41 @@ msgstr "нераспознанный параметр Snowball: \"%s\"" msgid "missing Language parameter" msgstr "отсутствует параметр Language" -#: statistics/extended_stats.c:179 +#: statistics/extended_stats.c:176 #, c-format msgid "" "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "" "объект статистики \"%s.%s\" не может быть вычислен для отношения \"%s.%s\"" -#: statistics/mcv.c:1372 +#: statistics/mcv.c:1368 #, c-format msgid "" "function returning record called in context that cannot accept type record" msgstr "" "функция, возвращающая запись, вызвана в контексте, не допускающем этот тип" -#: storage/buffer/bufmgr.c:612 storage/buffer/bufmgr.c:769 +#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 #, c-format msgid "cannot access temporary tables of other sessions" msgstr "обращаться к временным таблицам других сеансов нельзя" -#: storage/buffer/bufmgr.c:1137 +#: storage/buffer/bufmgr.c:1532 #, c-format msgid "invalid page in block %u of relation %s; zeroing out page" msgstr "неверная страница в блоке %u отношения %s; страница обнуляется" -#: storage/buffer/bufmgr.c:1931 storage/buffer/localbuf.c:359 +#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "не удалось увеличить отношение \"%s\" до блока %u" -#: storage/buffer/bufmgr.c:1998 +#: storage/buffer/bufmgr.c:2348 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "неожиданные данные после EOF в блоке %u отношения %s" -#: storage/buffer/bufmgr.c:2000 +#: storage/buffer/bufmgr.c:2350 #, c-format msgid "" "This has been seen to occur with buggy kernels; consider updating your " @@ -24038,37 +25036,32 @@ msgstr "" "Эта ситуация может возникать из-за ошибок в ядре; возможно, вам следует " "обновить ОС." -#: storage/buffer/bufmgr.c:5219 +#: storage/buffer/bufmgr.c:5653 #, c-format msgid "could not write block %u of %s" msgstr "не удалось запись блок %u файла %s" -#: storage/buffer/bufmgr.c:5221 +#: storage/buffer/bufmgr.c:5655 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "Множественные сбои - возможно, постоянная ошибка записи." -#: storage/buffer/bufmgr.c:5243 storage/buffer/bufmgr.c:5263 +#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 #, c-format msgid "writing block %u of relation %s" msgstr "запись блока %u отношения %s" -#: storage/buffer/bufmgr.c:5593 -#, c-format -msgid "snapshot too old" -msgstr "снимок слишком стар" - -#: storage/buffer/localbuf.c:219 +#: storage/buffer/localbuf.c:220 #, c-format msgid "no empty local buffer available" msgstr "нет пустого локального буфера" -#: storage/buffer/localbuf.c:592 +#: storage/buffer/localbuf.c:597 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "обращаться к временным таблицам во время параллельных операций нельзя" -#: storage/buffer/localbuf.c:699 +#: storage/buffer/localbuf.c:712 #, c-format msgid "" "\"temp_buffers\" cannot be changed after any temporary tables have been " @@ -24094,7 +25087,7 @@ msgstr "" msgid "could not read from temporary file: read only %zu of %zu bytes" msgstr "не удалось прочитать временный файл (прочитано байт: %zu из %zu)" -#: storage/file/buffile.c:774 storage/file/buffile.c:895 +#: storage/file/buffile.c:774 storage/file/buffile.c:877 #, c-format msgid "" "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" @@ -24102,115 +25095,115 @@ msgstr "" "не удалось определить размер временного файла \"%s\", входящего в BufFile " "\"%s\": %m" -#: storage/file/buffile.c:974 +#: storage/file/buffile.c:956 #, c-format msgid "could not delete fileset \"%s\": %m" msgstr "ошибка удаления набора файлов \"%s\": %m" -#: storage/file/buffile.c:992 storage/smgr/md.c:338 storage/smgr/md.c:1041 +#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1194 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "не удалось обрезать файл \"%s\": %m" -#: storage/file/fd.c:537 storage/file/fd.c:609 storage/file/fd.c:645 +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" msgstr "не удалось сбросить грязные данные: %m" -#: storage/file/fd.c:567 +#: storage/file/fd.c:613 #, c-format msgid "could not determine dirty data size: %m" msgstr "не удалось определить размер грязных данных: %m" -#: storage/file/fd.c:619 +#: storage/file/fd.c:665 #, c-format msgid "could not munmap() while flushing data: %m" msgstr "ошибка в munmap() при сбросе данных на диск: %m" -#: storage/file/fd.c:937 +#: storage/file/fd.c:983 #, c-format msgid "getrlimit failed: %m" msgstr "ошибка в getrlimit(): %m" -#: storage/file/fd.c:1027 +#: storage/file/fd.c:1073 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "недостаточно дескрипторов файлов для запуска серверного процесса" -#: storage/file/fd.c:1028 +#: storage/file/fd.c:1074 #, c-format msgid "System allows %d, server needs at least %d." msgstr "Система может выделить: %d, серверу требуется минимум: %d." -#: storage/file/fd.c:1116 storage/file/fd.c:2565 storage/file/fd.c:2674 -#: storage/file/fd.c:2825 +#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 +#: storage/file/fd.c:2878 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "нехватка дескрипторов файлов: %m; освободите их и повторите попытку" -#: storage/file/fd.c:1490 +#: storage/file/fd.c:1536 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "временный файл: путь \"%s\", размер %lu" -#: storage/file/fd.c:1629 +#: storage/file/fd.c:1675 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "не удалось создать временный каталог \"%s\": %m" -#: storage/file/fd.c:1636 +#: storage/file/fd.c:1682 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "не удалось создать временный подкаталог \"%s\": %m" -#: storage/file/fd.c:1833 +#: storage/file/fd.c:1879 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "не удалось создать временный файл \"%s\": %m" -#: storage/file/fd.c:1869 +#: storage/file/fd.c:1915 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "не удалось открыть временный файл \"%s\": %m" -#: storage/file/fd.c:1910 +#: storage/file/fd.c:1956 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "ошибка удаления временного файла \"%s\": %m" -#: storage/file/fd.c:1998 +#: storage/file/fd.c:2044 #, c-format msgid "could not delete file \"%s\": %m" msgstr "ошибка удаления файла \"%s\": %m" -#: storage/file/fd.c:2185 +#: storage/file/fd.c:2234 #, c-format msgid "temporary file size exceeds temp_file_limit (%dkB)" msgstr "размер временного файла превышает предел temp_file_limit (%d КБ)" -#: storage/file/fd.c:2541 storage/file/fd.c:2600 +#: storage/file/fd.c:2594 storage/file/fd.c:2653 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "превышен предел maxAllocatedDescs (%d) при попытке открыть файл \"%s\"" -#: storage/file/fd.c:2645 +#: storage/file/fd.c:2698 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "" "превышен предел maxAllocatedDescs (%d) при попытке выполнить команду \"%s\"" -#: storage/file/fd.c:2801 +#: storage/file/fd.c:2854 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "" "превышен предел maxAllocatedDescs (%d) при попытке открыть каталог \"%s\"" -#: storage/file/fd.c:3331 +#: storage/file/fd.c:3384 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "в каталоге временных файлов обнаружен неуместный файл: \"%s\"" -#: storage/file/fd.c:3449 +#: storage/file/fd.c:3502 #, c-format msgid "" "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" @@ -24218,12 +25211,7 @@ msgstr "" "синхронизация каталога данных (syncfs), прошло времени: %ld.%02d с, текущий " "путь: %s" -#: storage/file/fd.c:3463 -#, c-format -msgid "could not synchronize file system for file \"%s\": %m" -msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" - -#: storage/file/fd.c:3676 +#: storage/file/fd.c:3729 #, c-format msgid "" "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: " @@ -24232,7 +25220,7 @@ msgstr "" "синхронизация каталога данных (подготовка к fsync), прошло времени: %ld.%02d " "с, текущий путь: %s" -#: storage/file/fd.c:3708 +#: storage/file/fd.c:3761 #, c-format msgid "" "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" @@ -24240,25 +25228,36 @@ msgstr "" "синхронизация каталога данных (fsync), прошло времени: %ld.%02d с, текущий " "путь: %s" -#: storage/file/fd.c:3897 +#: storage/file/fd.c:3950 #, c-format -msgid "debug_io_direct is not supported on this platform." -msgstr "Параметр debug_io_direct на этой платформе не поддерживается." +msgid "\"debug_io_direct\" is not supported on this platform." +msgstr "Параметр \"debug_io_direct\" не поддерживается в этой ОС." -#: storage/file/fd.c:3944 +#: storage/file/fd.c:3964 +#, c-format +msgid "Invalid list syntax in parameter \"%s\"" +msgstr "Неверный формат списка в параметре \"%s\"." + +#: storage/file/fd.c:3984 +#, c-format +msgid "Invalid option \"%s\"" +msgstr "Неверный параметр \"%s\"." + +#: storage/file/fd.c:3997 #, c-format msgid "" -"debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small" +"\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" msgstr "" -"режим debug_io_direct не поддерживается для WAL из-за слишком маленького " +"режим \"debug_io_direct\" не поддерживается для WAL из-за слишком маленького " "размера XLOG_BLCKSZ" -#: storage/file/fd.c:3951 +#: storage/file/fd.c:4004 #, c-format -msgid "debug_io_direct is not supported for data because BLCKSZ is too small" +msgid "" +"\"debug_io_direct\" is not supported for data because BLCKSZ is too small" msgstr "" -"режим debug_io_direct не поддерживается для данных из-за слишком маленького " -"размера BLCKSZ" +"режим \"debug_io_direct\" не поддерживается для данных из-за слишком " +"маленького размера BLCKSZ" #: storage/file/reinit.c:145 #, c-format @@ -24278,22 +25277,22 @@ msgstr "" "сброс нежурналируемых отношений (очистка), прошло времени: %ld.%02d s, " "текущий путь: %s" -#: storage/file/sharedfileset.c:79 +#: storage/file/sharedfileset.c:73 #, c-format msgid "could not attach to a SharedFileSet that is already destroyed" msgstr "не удалось подключиться к уже уничтоженному набору SharedFileSet" -#: storage/ipc/dsm.c:352 +#: storage/ipc/dsm.c:379 #, c-format msgid "dynamic shared memory control segment is corrupt" msgstr "сегмент управления динамической разделяемой памятью испорчен" -#: storage/ipc/dsm.c:417 +#: storage/ipc/dsm.c:444 #, c-format msgid "dynamic shared memory control segment is not valid" msgstr "сегмент управления динамической разделяемой памятью не в порядке" -#: storage/ipc/dsm.c:599 +#: storage/ipc/dsm.c:626 #, c-format msgid "too many dynamic shared memory segments" msgstr "слишком много сегментов динамической разделяемой памяти" @@ -24354,18 +25353,46 @@ msgstr "не удалось закрыть сегмент разделяемой msgid "could not duplicate handle for \"%s\": %m" msgstr "не удалось продублировать указатель для \"%s\": %m" -#: storage/ipc/procarray.c:3795 +#: storage/ipc/dsm_registry.c:142 +#, c-format +msgid "DSM segment name cannot be empty" +msgstr "имя DSM-сегмента не может быть пустым" + +#: storage/ipc/dsm_registry.c:146 +#, c-format +msgid "DSM segment name too long" +msgstr "имя DSM-сегмента слишком длинное" + +#: storage/ipc/dsm_registry.c:150 +#, c-format +msgid "DSM segment size must be nonzero" +msgstr "размер DSM-сегмента должен быть ненулевым" + +#: storage/ipc/dsm_registry.c:176 +#, c-format +msgid "requested DSM segment size does not match size of existing segment" +msgstr "" +"запрошенный размер сегмента DSM не совпадает с размером существующего " +"сегмента" + +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:357 +#: tcop/backend_startup.c:304 +#, c-format +msgid "sorry, too many clients already" +msgstr "извините, уже слишком много клиентов" + +#: storage/ipc/procarray.c:3857 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "база \"%s\" используется подготовленными транзакциями" -#: storage/ipc/procarray.c:3827 storage/ipc/procarray.c:3836 +#: storage/ipc/procarray.c:3893 storage/ipc/procarray.c:3901 #: storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 #, c-format msgid "permission denied to terminate process" msgstr "нет прав для завершения процесса" -#: storage/ipc/procarray.c:3828 storage/ipc/signalfuncs.c:236 +#: storage/ipc/procarray.c:3894 storage/ipc/signalfuncs.c:236 #, c-format msgid "" "Only roles with the %s attribute may terminate processes of roles with the " @@ -24374,7 +25401,7 @@ msgstr "" "Только роли с атрибутом %s могут завершать процессы, принадлежащие ролям с " "атрибутом %s." -#: storage/ipc/procarray.c:3837 storage/ipc/signalfuncs.c:243 +#: storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:243 #, c-format msgid "" "Only roles with privileges of the role whose process is being terminated or " @@ -24383,45 +25410,45 @@ msgstr "" "Только роли с правами роли, которой принадлежит процесс, или с правами роли " "\"%s\" могут завершить этот процесс." -#: storage/ipc/procsignal.c:420 +#: storage/ipc/procsignal.c:416 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "" "продолжается ожидание получения сигнала ProcSignalBarrier обслуживающим " "процессом с PID %d" -#: storage/ipc/shm_mq.c:384 +#: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" msgstr "" "не удалось передать сообщение размером %zu через очередь в разделяемой памяти" -#: storage/ipc/shm_mq.c:719 +#: storage/ipc/shm_mq.c:718 #, c-format msgid "invalid message size %zu in shared memory queue" msgstr "неверный размер сообщения %zu в очереди в разделяемой памяти" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:963 -#: storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2786 storage/lmgr/lock.c:4171 -#: storage/lmgr/lock.c:4236 storage/lmgr/lock.c:4586 -#: storage/lmgr/predicate.c:2412 storage/lmgr/predicate.c:2427 -#: storage/lmgr/predicate.c:3824 storage/lmgr/predicate.c:4871 -#: utils/hash/dynahash.c:1107 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:984 +#: storage/lmgr/lock.c:1022 storage/lmgr/lock.c:2835 storage/lmgr/lock.c:4220 +#: storage/lmgr/lock.c:4285 storage/lmgr/lock.c:4635 +#: storage/lmgr/predicate.c:2468 storage/lmgr/predicate.c:2483 +#: storage/lmgr/predicate.c:3880 storage/lmgr/predicate.c:4927 +#: utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "нехватка разделяемой памяти" -#: storage/ipc/shmem.c:170 storage/ipc/shmem.c:266 +#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "нехватка разделяемой памяти (требовалось байт: %zu)" -#: storage/ipc/shmem.c:445 +#: storage/ipc/shmem.c:436 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "не удалось создать запись ShmemIndex для структуры данных \"%s\"" -#: storage/ipc/shmem.c:460 +#: storage/ipc/shmem.c:451 #, c-format msgid "" "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, " @@ -24430,7 +25457,7 @@ msgstr "" "размер записи ShmemIndex не соответствует структуре данных " "\"%s\" (ожидалось: %zu, фактически: %zu)" -#: storage/ipc/shmem.c:479 +#: storage/ipc/shmem.c:470 #, c-format msgid "" "not enough shared memory for data structure \"%s\" (%zu bytes requested)" @@ -24438,7 +25465,7 @@ msgstr "" "недостаточно разделяемой памяти для структуры данных \"%s\" (требовалось " "байт: %zu)" -#: storage/ipc/shmem.c:511 storage/ipc/shmem.c:530 +#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 #, c-format msgid "requested shared memory size overflows size_t" msgstr "запрошенный размер разделяемой памяти не умещается в size_t" @@ -24448,8 +25475,8 @@ msgstr "запрошенный размер разделяемой памяти msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %d не относится к обслуживающему процессу PostgreSQL" -#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1387 -#: utils/adt/mcxtfuncs.c:190 +#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1453 +#: utils/adt/mcxtfuncs.c:182 #, c-format msgid "could not send signal to process %d: %m" msgstr "отправить сигнал процессу %d не удалось: %m" @@ -24495,96 +25522,90 @@ msgstr[2] "обслуживающий процесс с PID %d не заверш msgid "\"timeout\" must not be negative" msgstr "\"timeout\" не может быть отрицательным" -#: storage/ipc/signalfuncs.c:284 -#, c-format -msgid "must be superuser to rotate log files with adminpack 1.0" -msgstr "" -"прокручивать файлы протоколов, используя adminpack 1.0, может только " -"суперпользователь" - -#. translator: %s is a SQL function name -#: storage/ipc/signalfuncs.c:286 utils/adt/genfile.c:250 -#, c-format -msgid "Consider using %s, which is part of core, instead." -msgstr "Рассмотрите возможность использования функции %s, включённой в ядро." - -#: storage/ipc/signalfuncs.c:292 storage/ipc/signalfuncs.c:312 +#: storage/ipc/signalfuncs.c:285 #, c-format msgid "rotation not possible because log collection not active" msgstr "прокрутка невозможна, так как протоколирование отключено" -#: storage/ipc/standby.c:330 +#: storage/ipc/standby.c:329 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "процесс восстановления продолжает ожидание после %ld.%03d мс: %s" -#: storage/ipc/standby.c:339 +#: storage/ipc/standby.c:338 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "процесс восстановления завершил ожидание после %ld.%03d мс: %s" -#: storage/ipc/standby.c:921 tcop/postgres.c:3384 +#: storage/ipc/standby.c:920 tcop/postgres.c:3196 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "" "выполнение оператора отменено из-за конфликта с процессом восстановления" -#: storage/ipc/standby.c:922 tcop/postgres.c:2533 +#: storage/ipc/standby.c:921 tcop/postgres.c:2557 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "" "Транзакция пользователя привела к взаимоблокировке с процессом " "восстановления." -#: storage/ipc/standby.c:1488 +#: storage/ipc/standby.c:1486 msgid "unknown reason" msgstr "причина неизвестна" -#: storage/ipc/standby.c:1493 +#: storage/ipc/standby.c:1491 msgid "recovery conflict on buffer pin" msgstr "конфликт восстановления при закреплении буфера" -#: storage/ipc/standby.c:1496 +#: storage/ipc/standby.c:1494 msgid "recovery conflict on lock" msgstr "конфликт восстановления при получении блокировки" -#: storage/ipc/standby.c:1499 +#: storage/ipc/standby.c:1497 msgid "recovery conflict on tablespace" msgstr "конфликт восстановления при обращении к табличному пространству" -#: storage/ipc/standby.c:1502 +#: storage/ipc/standby.c:1500 msgid "recovery conflict on snapshot" msgstr "конфликт восстановления при получении снимка" -#: storage/ipc/standby.c:1505 +#: storage/ipc/standby.c:1503 msgid "recovery conflict on replication slot" msgstr "конфликт восстановления со слотом репликации" -#: storage/ipc/standby.c:1508 +#: storage/ipc/standby.c:1506 msgid "recovery conflict on buffer deadlock" msgstr "конфликт восстановления из-за взаимной блокировки буфера" -#: storage/ipc/standby.c:1511 +#: storage/ipc/standby.c:1509 msgid "recovery conflict on database" msgstr "конфликт восстановления при обращении к базе данных" -#: storage/large_object/inv_api.c:191 +#: storage/large_object/inv_api.c:190 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "" "в записи pg_largeobject для OID %u, стр. %d неверный размер поля данных (%d)" -#: storage/large_object/inv_api.c:273 +#: storage/large_object/inv_api.c:272 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "неверные флаги для открытия большого объекта: %d" -#: storage/large_object/inv_api.c:456 +#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 +#: storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 +#: storage/large_object/inv_api.c:807 +#, c-format +msgid "permission denied for large object %u" +msgstr "нет доступа к большому объекту %u" + +#: storage/large_object/inv_api.c:455 #, c-format msgid "invalid whence setting: %d" msgstr "неверное значение ориентира: %d" -#: storage/large_object/inv_api.c:628 +#: storage/large_object/inv_api.c:627 #, c-format msgid "invalid large object write request size: %d" msgstr "неверный размер записи большого объекта: %d" @@ -24610,113 +25631,113 @@ msgstr "обнаружена взаимоблокировка" msgid "See server log for query details." msgstr "Подробности запроса смотрите в протоколе сервера." -#: storage/lmgr/lmgr.c:859 +#: storage/lmgr/lmgr.c:848 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "при изменении кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:862 +#: storage/lmgr/lmgr.c:851 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "при удалении кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:865 +#: storage/lmgr/lmgr.c:854 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "при блокировке кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:868 +#: storage/lmgr/lmgr.c:857 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "при блокировке изменённой версии (%u,%u) кортежа в отношении \"%s\"" -#: storage/lmgr/lmgr.c:871 +#: storage/lmgr/lmgr.c:860 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "при добавлении кортежа индекса (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:874 +#: storage/lmgr/lmgr.c:863 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "при проверке уникальности кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:877 +#: storage/lmgr/lmgr.c:866 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "при перепроверке изменённого кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:880 +#: storage/lmgr/lmgr.c:869 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "" "при проверке ограничения-исключения для кортежа (%u,%u) в отношении \"%s\"" -#: storage/lmgr/lmgr.c:1212 +#: storage/lmgr/lmgr.c:1239 #, c-format msgid "relation %u of database %u" msgstr "отношение %u базы данных %u" -#: storage/lmgr/lmgr.c:1218 +#: storage/lmgr/lmgr.c:1245 #, c-format msgid "extension of relation %u of database %u" msgstr "расширение отношения %u базы данных %u" -#: storage/lmgr/lmgr.c:1224 +#: storage/lmgr/lmgr.c:1251 #, c-format msgid "pg_database.datfrozenxid of database %u" msgstr "pg_database.datfrozenxid базы %u" -#: storage/lmgr/lmgr.c:1229 +#: storage/lmgr/lmgr.c:1256 #, c-format msgid "page %u of relation %u of database %u" msgstr "страница %u отношения %u базы данных %u" -#: storage/lmgr/lmgr.c:1236 +#: storage/lmgr/lmgr.c:1263 #, c-format msgid "tuple (%u,%u) of relation %u of database %u" msgstr "кортеж (%u,%u) отношения %u базы данных %u" -#: storage/lmgr/lmgr.c:1244 +#: storage/lmgr/lmgr.c:1271 #, c-format msgid "transaction %u" msgstr "транзакция %u" -#: storage/lmgr/lmgr.c:1249 +#: storage/lmgr/lmgr.c:1276 #, c-format msgid "virtual transaction %d/%u" msgstr "виртуальная транзакция %d/%u" -#: storage/lmgr/lmgr.c:1255 +#: storage/lmgr/lmgr.c:1282 #, c-format msgid "speculative token %u of transaction %u" msgstr "спекулятивный маркер %u транзакции %u" -#: storage/lmgr/lmgr.c:1261 +#: storage/lmgr/lmgr.c:1288 #, c-format msgid "object %u of class %u of database %u" msgstr "объект %u класса %u базы данных %u" -#: storage/lmgr/lmgr.c:1269 +#: storage/lmgr/lmgr.c:1296 #, c-format msgid "user lock [%u,%u,%u]" msgstr "пользовательская блокировка [%u,%u,%u]" -#: storage/lmgr/lmgr.c:1276 +#: storage/lmgr/lmgr.c:1303 #, c-format msgid "advisory lock [%u,%u,%u,%u]" msgstr "рекомендательная блокировка [%u,%u,%u,%u]" -#: storage/lmgr/lmgr.c:1284 +#: storage/lmgr/lmgr.c:1311 #, c-format msgid "remote transaction %u of subscription %u of database %u" msgstr "удалённая транзакция %u подписки %u в базе данных %u" -#: storage/lmgr/lmgr.c:1291 +#: storage/lmgr/lmgr.c:1318 #, c-format msgid "unrecognized locktag type %d" msgstr "нераспознанный тип блокировки %d" -#: storage/lmgr/lock.c:791 +#: storage/lmgr/lock.c:812 #, c-format msgid "" "cannot acquire lock mode %s on database objects while recovery is in progress" @@ -24724,7 +25745,7 @@ msgstr "" "пока выполняется восстановление, нельзя получить блокировку объектов базы " "данных в режиме %s" -#: storage/lmgr/lock.c:793 +#: storage/lmgr/lock.c:814 #, c-format msgid "" "Only RowExclusiveLock or less can be acquired on database objects during " @@ -24733,7 +25754,7 @@ msgstr "" "В процессе восстановления для объектов базы данных может быть получена " "только блокировка RowExclusiveLock или менее сильная." -#: storage/lmgr/lock.c:3235 storage/lmgr/lock.c:3303 storage/lmgr/lock.c:3419 +#: storage/lmgr/lock.c:3284 storage/lmgr/lock.c:3352 storage/lmgr/lock.c:3468 #, c-format msgid "" "cannot PREPARE while holding both session-level and transaction-level locks " @@ -24742,21 +25763,21 @@ msgstr "" "нельзя выполнить PREPARE, удерживая блокировки на уровне сеанса и на уровне " "транзакции для одного объекта" -#: storage/lmgr/predicate.c:649 +#: storage/lmgr/predicate.c:653 #, c-format msgid "not enough elements in RWConflictPool to record a read/write conflict" msgstr "в пуле недостаточно элементов для записи о конфликте чтения/записи" -#: storage/lmgr/predicate.c:650 storage/lmgr/predicate.c:675 +#: storage/lmgr/predicate.c:654 storage/lmgr/predicate.c:679 #, c-format msgid "" "You might need to run fewer transactions at a time or increase " -"max_connections." +"\"max_connections\"." msgstr "" -"Попробуйте уменьшить число транзакций в секунду или увеличить параметр " -"max_connections." +"Попробуйте уменьшить число одновременных транзакций или увеличить параметр " +"\"max_connections\"." -#: storage/lmgr/predicate.c:674 +#: storage/lmgr/predicate.c:678 #, c-format msgid "" "not enough elements in RWConflictPool to record a potential read/write " @@ -24765,13 +25786,13 @@ msgstr "" "в пуле недостаточно элементов для записи о потенциальном конфликте чтения/" "записи" -#: storage/lmgr/predicate.c:1630 +#: storage/lmgr/predicate.c:1686 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "" "Параметр \"default_transaction_isolation\" имеет значение \"serializable\"." -#: storage/lmgr/predicate.c:1631 +#: storage/lmgr/predicate.c:1687 #, c-format msgid "" "You can use \"SET default_transaction_isolation = 'repeatable read'\" to " @@ -24780,27 +25801,27 @@ msgstr "" "Чтобы изменить режим по умолчанию, выполните \"SET " "default_transaction_isolation = 'repeatable read'\"." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1738 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "транзакция, импортирующая снимок, не должна быть READ ONLY DEFERRABLE" -#: storage/lmgr/predicate.c:1761 utils/time/snapmgr.c:570 -#: utils/time/snapmgr.c:576 +#: storage/lmgr/predicate.c:1817 utils/time/snapmgr.c:535 +#: utils/time/snapmgr.c:541 #, c-format msgid "could not import the requested snapshot" msgstr "не удалось импортировать запрошенный снимок" -#: storage/lmgr/predicate.c:1762 utils/time/snapmgr.c:577 +#: storage/lmgr/predicate.c:1818 utils/time/snapmgr.c:542 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "Исходный процесс с PID %d уже не работает." -#: storage/lmgr/predicate.c:3935 storage/lmgr/predicate.c:3971 -#: storage/lmgr/predicate.c:4004 storage/lmgr/predicate.c:4012 -#: storage/lmgr/predicate.c:4051 storage/lmgr/predicate.c:4281 -#: storage/lmgr/predicate.c:4600 storage/lmgr/predicate.c:4612 -#: storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4695 +#: storage/lmgr/predicate.c:3991 storage/lmgr/predicate.c:4027 +#: storage/lmgr/predicate.c:4060 storage/lmgr/predicate.c:4068 +#: storage/lmgr/predicate.c:4107 storage/lmgr/predicate.c:4337 +#: storage/lmgr/predicate.c:4656 storage/lmgr/predicate.c:4668 +#: storage/lmgr/predicate.c:4715 storage/lmgr/predicate.c:4751 #, c-format msgid "" "could not serialize access due to read/write dependencies among transactions" @@ -24808,25 +25829,25 @@ msgstr "" "не удалось сериализовать доступ из-за зависимостей чтения/записи между " "транзакциями" -#: storage/lmgr/predicate.c:3937 storage/lmgr/predicate.c:3973 -#: storage/lmgr/predicate.c:4006 storage/lmgr/predicate.c:4014 -#: storage/lmgr/predicate.c:4053 storage/lmgr/predicate.c:4283 -#: storage/lmgr/predicate.c:4602 storage/lmgr/predicate.c:4614 -#: storage/lmgr/predicate.c:4661 storage/lmgr/predicate.c:4697 +#: storage/lmgr/predicate.c:3993 storage/lmgr/predicate.c:4029 +#: storage/lmgr/predicate.c:4062 storage/lmgr/predicate.c:4070 +#: storage/lmgr/predicate.c:4109 storage/lmgr/predicate.c:4339 +#: storage/lmgr/predicate.c:4658 storage/lmgr/predicate.c:4670 +#: storage/lmgr/predicate.c:4717 storage/lmgr/predicate.c:4753 #, c-format msgid "The transaction might succeed if retried." msgstr "Транзакция может завершиться успешно при следующей попытке." -#: storage/lmgr/proc.c:349 +#: storage/lmgr/proc.c:353 #, c-format msgid "" -"number of requested standby connections exceeds max_wal_senders (currently " -"%d)" +"number of requested standby connections exceeds " +"\"max_wal_senders\" (currently %d)" msgstr "" -"число запрошенных подключений резервных серверов превосходит max_wal_senders " -"(сейчас: %d)" +"число запрошенных подключений резервных серверов превышает " +"\"max_wal_senders\" (сейчас: %d)" -#: storage/lmgr/proc.c:1480 +#: storage/lmgr/proc.c:1546 #, c-format msgid "" "process %d avoided deadlock for %s on %s by rearranging queue order after " @@ -24835,7 +25856,7 @@ msgstr "" "процесс %d избежал взаимоблокировки, ожидая в режиме %s блокировку \"%s\", " "изменив порядок очереди через %ld.%03d мс" -#: storage/lmgr/proc.c:1495 +#: storage/lmgr/proc.c:1561 #, c-format msgid "" "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" @@ -24843,121 +25864,266 @@ msgstr "" "процесс %d обнаружил взаимоблокировку, ожидая в режиме %s блокировку \"%s\" " "в течение %ld.%03d мс" -#: storage/lmgr/proc.c:1504 +#: storage/lmgr/proc.c:1570 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "" "процесс %d продолжает ожидать в режиме %s блокировку \"%s\" в течение %ld." "%03d мс" -#: storage/lmgr/proc.c:1511 +#: storage/lmgr/proc.c:1577 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "процесс %d получил в режиме %s блокировку \"%s\" через %ld.%03d мс" -#: storage/lmgr/proc.c:1528 +#: storage/lmgr/proc.c:1594 +#, c-format +msgid "process %d failed to acquire %s on %s after %ld.%03d ms" +msgstr "" +"процесс %d не смог получить в режиме %s блокировку \"%s\" за %ld.%03d мс" + +#: storage/page/bufpage.c:152 +#, c-format +msgid "page verification failed, calculated checksum %u but expected %u" +msgstr "" +"ошибка проверки страницы: получена контрольная сумма %u, а ожидалась - %u" + +#: storage/page/bufpage.c:217 storage/page/bufpage.c:730 +#: storage/page/bufpage.c:1073 storage/page/bufpage.c:1208 +#: storage/page/bufpage.c:1314 storage/page/bufpage.c:1426 +#, c-format +msgid "corrupted page pointers: lower = %u, upper = %u, special = %u" +msgstr "" +"испорченные указатели страницы: нижний = %u, верхний = %u, спецобласть = %u" + +#: storage/page/bufpage.c:759 +#, c-format +msgid "corrupted line pointer: %u" +msgstr "испорченный линейный указатель: %u" + +#: storage/page/bufpage.c:789 storage/page/bufpage.c:1266 +#, c-format +msgid "corrupted item lengths: total %u, available space %u" +msgstr "испорченный размер элемента (общий размер: %u, доступно: %u)" + +#: storage/page/bufpage.c:1092 storage/page/bufpage.c:1233 +#: storage/page/bufpage.c:1330 storage/page/bufpage.c:1442 +#, c-format +msgid "corrupted line pointer: offset = %u, size = %u" +msgstr "испорченный линейный указатель: смещение = %u, размер = %u" + +#: storage/smgr/md.c:485 storage/smgr/md.c:547 +#, c-format +msgid "cannot extend file \"%s\" beyond %u blocks" +msgstr "не удалось увеличить файл \"%s\" до блока %u" + +#: storage/smgr/md.c:500 storage/smgr/md.c:611 +#, c-format +msgid "could not extend file \"%s\": %m" +msgstr "не удалось увеличить файл \"%s\": %m" + +#: storage/smgr/md.c:506 +#, c-format +msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" +msgstr "не удалось увеличить файл \"%s\" (записано байт: %d из %d) в блоке %u" + +#: storage/smgr/md.c:589 +#, c-format +msgid "could not extend file \"%s\" with FileFallocate(): %m" +msgstr "не удалось увеличить файл \"%s\" посредством FileFallocate(): %m" + +#: storage/smgr/md.c:869 +#, c-format +msgid "could not read blocks %u..%u in file \"%s\": %m" +msgstr "не удалось прочитать блоки %u..%u в файле \"%s\": %m" + +#: storage/smgr/md.c:895 +#, c-format +msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" +msgstr "" +"не удалось прочитать блоки %u..%u в файле \"%s\" (прочитано байт: %zu из %zu)" + +#: storage/smgr/md.c:995 +#, c-format +msgid "could not write blocks %u..%u in file \"%s\": %m" +msgstr "не удалось записать блоки %u..%u в файл \"%s\": %m" + +#: storage/smgr/md.c:1165 +#, c-format +msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" +msgstr "" +"не удалось обрезать файл \"%s\" (требуемая длина в блоках: %u, но сейчас он " +"содержит %u)" + +#: storage/smgr/md.c:1220 +#, c-format +msgid "could not truncate file \"%s\" to %u blocks: %m" +msgstr "не удалось обрезать файл \"%s\" до нужного числа блоков (%u): %m" + +#: storage/smgr/md.c:1700 +#, c-format +msgid "" +"could not open file \"%s\" (target block %u): previous segment is only %u " +"blocks" +msgstr "" +"не удалось открыть файл file \"%s\" (целевой блок %u): недостаточно блоков в " +"предыдущем сегменте (всего %u)" + +#: storage/smgr/md.c:1714 +#, c-format +msgid "could not open file \"%s\" (target block %u): %m" +msgstr "не удалось открыть файл file \"%s\" (целевой блок %u): %m" + +#: tcop/backend_startup.c:85 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "не удалось загрузить конфигурацию SSL в дочерний процесс" + +#: tcop/backend_startup.c:208 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "принято подключение: узел=%s порт=%s" + +#: tcop/backend_startup.c:213 +#, c-format +msgid "connection received: host=%s" +msgstr "принято подключение: узел=%s" + +#: tcop/backend_startup.c:277 +#, c-format +msgid "the database system is starting up" +msgstr "система баз данных запускается" + +#: tcop/backend_startup.c:283 +#, c-format +msgid "the database system is not yet accepting connections" +msgstr "система БД ещё не принимает подключения" + +#: tcop/backend_startup.c:284 +#, c-format +msgid "Consistent recovery state has not been yet reached." +msgstr "Согласованное состояние восстановления ещё не достигнуто." + +#: tcop/backend_startup.c:288 +#, c-format +msgid "the database system is not accepting connections" +msgstr "система БД не принимает подключения" + +#: tcop/backend_startup.c:289 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "Режим горячего резерва отключён." + +#: tcop/backend_startup.c:294 +#, c-format +msgid "the database system is shutting down" +msgstr "система баз данных останавливается" + +#: tcop/backend_startup.c:299 +#, c-format +msgid "the database system is in recovery mode" +msgstr "система баз данных в режиме восстановления" + +#: tcop/backend_startup.c:414 #, c-format -msgid "process %d failed to acquire %s on %s after %ld.%03d ms" -msgstr "" -"процесс %d не смог получить в режиме %s блокировку \"%s\" за %ld.%03d мс" +msgid "" +"received direct SSL connection request without ALPN protocol negotiation " +"extension" +msgstr "получен запрос прямого SSL-соединения, но в нём нет расширения ALPN" -#: storage/page/bufpage.c:152 +#: tcop/backend_startup.c:420 #, c-format -msgid "page verification failed, calculated checksum %u but expected %u" -msgstr "" -"ошибка проверки страницы: получена контрольная сумма %u, а ожидалась - %u" +msgid "direct SSL connection accepted" +msgstr "запрос прямого SSL-соединения принят" -#: storage/page/bufpage.c:217 storage/page/bufpage.c:730 -#: storage/page/bufpage.c:1073 storage/page/bufpage.c:1208 -#: storage/page/bufpage.c:1314 storage/page/bufpage.c:1426 +#: tcop/backend_startup.c:430 #, c-format -msgid "corrupted page pointers: lower = %u, upper = %u, special = %u" -msgstr "" -"испорченные указатели страницы: нижний = %u, верхний = %u, спецобласть = %u" +msgid "direct SSL connection rejected" +msgstr "запрос прямого SSL-соединения отвергнут" -#: storage/page/bufpage.c:759 +#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 #, c-format -msgid "corrupted line pointer: %u" -msgstr "испорченный линейный указатель: %u" +msgid "incomplete startup packet" +msgstr "неполный стартовый пакет" -#: storage/page/bufpage.c:789 storage/page/bufpage.c:1266 +#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 #, c-format -msgid "corrupted item lengths: total %u, available space %u" -msgstr "испорченный размер элемента (общий размер: %u, доступно: %u)" +msgid "invalid length of startup packet" +msgstr "неверная длина стартового пакета" -#: storage/page/bufpage.c:1092 storage/page/bufpage.c:1233 -#: storage/page/bufpage.c:1330 storage/page/bufpage.c:1442 +#: tcop/backend_startup.c:573 #, c-format -msgid "corrupted line pointer: offset = %u, size = %u" -msgstr "испорченный линейный указатель: смещение = %u, размер = %u" +msgid "SSLRequest accepted" +msgstr "SSLRequest принят" -#: storage/smgr/md.c:487 storage/smgr/md.c:549 +#: tcop/backend_startup.c:576 #, c-format -msgid "cannot extend file \"%s\" beyond %u blocks" -msgstr "не удалось увеличить файл \"%s\" до блока %u" +msgid "SSLRequest rejected" +msgstr "SSLRequest отвергнут" -#: storage/smgr/md.c:502 storage/smgr/md.c:613 +#: tcop/backend_startup.c:585 #, c-format -msgid "could not extend file \"%s\": %m" -msgstr "не удалось увеличить файл \"%s\": %m" +msgid "failed to send SSL negotiation response: %m" +msgstr "не удалось отправить ответ в процессе SSL-согласования: %m" -#: storage/smgr/md.c:508 +#: tcop/backend_startup.c:603 #, c-format -msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" -msgstr "не удалось увеличить файл \"%s\" (записано байт: %d из %d) в блоке %u" +msgid "received unencrypted data after SSL request" +msgstr "после запроса SSL получены незашифрованные данные" -#: storage/smgr/md.c:591 +#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 #, c-format -msgid "could not extend file \"%s\" with FileFallocate(): %m" -msgstr "не удалось увеличить файл \"%s\" посредством FileFallocate(): %m" +msgid "" +"This could be either a client-software bug or evidence of an attempted man-" +"in-the-middle attack." +msgstr "" +"Это может свидетельствовать об ошибке в клиентском ПО или о попытке атаки " +"MITM." -#: storage/smgr/md.c:782 +#: tcop/backend_startup.c:627 #, c-format -msgid "could not read block %u in file \"%s\": %m" -msgstr "не удалось прочитать блок %u в файле \"%s\": %m" +msgid "GSSENCRequest accepted" +msgstr "GSSENCRequest принят" -#: storage/smgr/md.c:798 +#: tcop/backend_startup.c:630 #, c-format -msgid "could not read block %u in file \"%s\": read only %d of %d bytes" -msgstr "не удалось прочитать блок %u в файле \"%s\" (прочитано байт: %d из %d)" +msgid "GSSENCRequest rejected" +msgstr "GSSENCRequest отвергнут" -#: storage/smgr/md.c:856 +#: tcop/backend_startup.c:639 #, c-format -msgid "could not write block %u in file \"%s\": %m" -msgstr "не удалось записать блок %u в файл \"%s\": %m" +msgid "failed to send GSSAPI negotiation response: %m" +msgstr "не удалось отправить ответ в процессе согласования GSSAPI: %m" -#: storage/smgr/md.c:861 +#: tcop/backend_startup.c:657 #, c-format -msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" -msgstr "не удалось записать блок %u в файл \"%s\" (записано байт: %d из %d)" +msgid "received unencrypted data after GSSAPI encryption request" +msgstr "после запроса шифрования GSSAPI получены незашифрованные данные" -#: storage/smgr/md.c:1012 +#: tcop/backend_startup.c:681 #, c-format -msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" +msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" msgstr "" -"не удалось обрезать файл \"%s\" (требуемая длина в блоках: %u, но сейчас он " -"содержит %u)" +"неподдерживаемый протокол клиентского приложения %u.%u; сервер поддерживает " +"%u.0 - %u.%u" -#: storage/smgr/md.c:1067 +#: tcop/backend_startup.c:744 #, c-format -msgid "could not truncate file \"%s\" to %u blocks: %m" -msgstr "не удалось обрезать файл \"%s\" до нужного числа блоков (%u): %m" +msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." +msgstr "Допустимые значения: \"false\", 0, \"true\", 1, \"database\"." -#: storage/smgr/md.c:1494 +#: tcop/backend_startup.c:785 #, c-format -msgid "" -"could not open file \"%s\" (target block %u): previous segment is only %u " -"blocks" +msgid "invalid startup packet layout: expected terminator as last byte" msgstr "" -"не удалось открыть файл file \"%s\" (целевой блок %u): недостаточно блоков в " -"предыдущем сегменте (всего %u)" +"неверная структура стартового пакета: последним байтом должен быть терминатор" -#: storage/smgr/md.c:1508 +#: tcop/backend_startup.c:802 #, c-format -msgid "could not open file \"%s\" (target block %u): %m" -msgstr "не удалось открыть файл file \"%s\" (целевой блок %u): %m" +msgid "no PostgreSQL user name specified in startup packet" +msgstr "в стартовом пакете не указано имя пользователя PostgreSQL" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2132 +#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "функция с OID %u не существует" @@ -24972,8 +26138,8 @@ msgstr "вызвать функцию \"%s\" через интерфейс fastp msgid "fastpath function call: \"%s\" (OID %u)" msgstr "вызов функции (через fastpath): \"%s\" (OID %u)" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 -#: tcop/postgres.c:2059 tcop/postgres.c:2309 +#: tcop/fastpath.c:313 tcop/postgres.c:1369 tcop/postgres.c:1605 +#: tcop/postgres.c:2071 tcop/postgres.c:2333 #, c-format msgid "duration: %s ms" msgstr "продолжительность: %s мс" @@ -25008,44 +26174,44 @@ msgstr "неверный размер аргумента (%d) в сообщен msgid "incorrect binary data format in function argument %d" msgstr "неправильный формат двоичных данных в аргументе функции %d" -#: tcop/postgres.c:463 tcop/postgres.c:4882 +#: tcop/postgres.c:467 tcop/postgres.c:5012 #, c-format msgid "invalid frontend message type %d" msgstr "неправильный тип клиентского сообщения %d" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1076 #, c-format msgid "statement: %s" msgstr "оператор: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1374 #, c-format msgid "duration: %s ms statement: %s" msgstr "продолжительность: %s мс, оператор: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1480 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "в подготовленный оператор нельзя вставить несколько команд" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1610 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "продолжительность: %s мс, разбор %s: %s" # [SM]: TO REVIEW -#: tcop/postgres.c:1672 tcop/postgres.c:2629 +#: tcop/postgres.c:1677 tcop/postgres.c:2653 #, c-format msgid "unnamed prepared statement does not exist" msgstr "безымянный подготовленный оператор не существует" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1729 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "" "неверное число форматов параметров в сообщении Bind (%d, а параметров %d)" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1735 #, c-format msgid "" "bind message supplies %d parameters, but prepared statement \"%s\" requires " @@ -25054,120 +26220,120 @@ msgstr "" "в сообщении Bind передано неверное число параметров (%d, а подготовленный " "оператор \"%s\" требует %d)" -#: tcop/postgres.c:1937 +#: tcop/postgres.c:1949 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "неверный формат двоичных данных в параметре Bind %d" -#: tcop/postgres.c:2064 +#: tcop/postgres.c:2076 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "продолжительность: %s мс, сообщение Bind %s%s%s: %s" -#: tcop/postgres.c:2118 tcop/postgres.c:2712 +#: tcop/postgres.c:2131 tcop/postgres.c:2735 #, c-format msgid "portal \"%s\" does not exist" msgstr "портал \"%s\" не существует" -#: tcop/postgres.c:2189 +#: tcop/postgres.c:2213 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2191 tcop/postgres.c:2317 +#: tcop/postgres.c:2215 tcop/postgres.c:2341 msgid "execute fetch from" msgstr "выборка из" -#: tcop/postgres.c:2192 tcop/postgres.c:2318 +#: tcop/postgres.c:2216 tcop/postgres.c:2342 msgid "execute" msgstr "выполнение" -#: tcop/postgres.c:2314 +#: tcop/postgres.c:2338 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "продолжительность: %s мс %s %s%s%s: %s" -#: tcop/postgres.c:2462 +#: tcop/postgres.c:2486 #, c-format msgid "prepare: %s" msgstr "подготовка: %s" -#: tcop/postgres.c:2487 +#: tcop/postgres.c:2511 #, c-format -msgid "parameters: %s" -msgstr "параметры: %s" +msgid "Parameters: %s" +msgstr "Параметры: %s" -#: tcop/postgres.c:2502 +#: tcop/postgres.c:2526 #, c-format -msgid "abort reason: recovery conflict" -msgstr "причина прерывания: конфликт при восстановлении" +msgid "Abort reason: recovery conflict" +msgstr "Причина прерывания: конфликт при восстановлении" -#: tcop/postgres.c:2518 +#: tcop/postgres.c:2542 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "Пользователь удерживал фиксатор разделяемого буфера слишком долго." -#: tcop/postgres.c:2521 +#: tcop/postgres.c:2545 #, c-format msgid "User was holding a relation lock for too long." msgstr "Пользователь удерживал блокировку таблицы слишком долго." -#: tcop/postgres.c:2524 +#: tcop/postgres.c:2548 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "" "Пользователь использовал табличное пространство, которое должно быть удалено." -#: tcop/postgres.c:2527 +#: tcop/postgres.c:2551 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "" "Запросу пользователя нужно было видеть версии строк, которые должны быть " "удалены." -#: tcop/postgres.c:2530 +#: tcop/postgres.c:2554 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "" "Пользователь использовал слот логической репликации, который должен быть " "аннулирован." -#: tcop/postgres.c:2536 +#: tcop/postgres.c:2560 #, c-format msgid "User was connected to a database that must be dropped." msgstr "Пользователь был подключён к базе данных, которая должна быть удалена." -#: tcop/postgres.c:2575 +#: tcop/postgres.c:2599 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "портал \"%s\", параметр $%d = %s" -#: tcop/postgres.c:2578 +#: tcop/postgres.c:2602 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "портал \"%s\", параметр $%d" -#: tcop/postgres.c:2584 +#: tcop/postgres.c:2608 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "неименованный портал, параметр $%d = %s" -#: tcop/postgres.c:2587 +#: tcop/postgres.c:2611 #, c-format msgid "unnamed portal parameter $%d" msgstr "неименованный портал, параметр $%d" -#: tcop/postgres.c:2932 +#: tcop/postgres.c:2955 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "закрытие подключения из-за неожиданного сигнала SIGQUIT" -#: tcop/postgres.c:2938 +#: tcop/postgres.c:2961 #, c-format msgid "terminating connection because of crash of another server process" msgstr "закрытие подключения из-за краха другого серверного процесса" -#: tcop/postgres.c:2939 +#: tcop/postgres.c:2962 #, c-format msgid "" "The postmaster has commanded this server process to roll back the current " @@ -25178,7 +26344,7 @@ msgstr "" "транзакцию и завершиться, так как другой серверный процесс завершился " "аварийно и, возможно, разрушил разделяемую память." -#: tcop/postgres.c:2943 tcop/postgres.c:3310 +#: tcop/postgres.c:2966 tcop/postgres.c:3219 #, c-format msgid "" "In a moment you should be able to reconnect to the database and repeat your " @@ -25187,18 +26353,18 @@ msgstr "" "Вы сможете переподключиться к базе данных и повторить вашу команду сию " "минуту." -#: tcop/postgres.c:2950 +#: tcop/postgres.c:2973 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "" "закрытие подключения вследствие получения команды для немедленного отключения" -#: tcop/postgres.c:3036 +#: tcop/postgres.c:3051 #, c-format msgid "floating-point exception" msgstr "исключение в операции с плавающей точкой" -#: tcop/postgres.c:3037 +#: tcop/postgres.c:3052 #, c-format msgid "" "An invalid floating-point operation was signaled. This probably means an out-" @@ -25208,72 +26374,77 @@ msgstr "" "оказался вне допустимых рамок или произошла ошибка вычисления, например, " "деление на ноль." -#: tcop/postgres.c:3214 +#: tcop/postgres.c:3217 +#, c-format +msgid "terminating connection due to conflict with recovery" +msgstr "закрытие подключения из-за конфликта с процессом восстановления" + +#: tcop/postgres.c:3289 #, c-format msgid "canceling authentication due to timeout" msgstr "отмена проверки подлинности из-за тайм-аута" -#: tcop/postgres.c:3218 +#: tcop/postgres.c:3293 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "прекращение процесса автоочистки по команде администратора" -#: tcop/postgres.c:3222 +#: tcop/postgres.c:3297 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "завершение обработчика логической репликации по команде администратора" -#: tcop/postgres.c:3239 tcop/postgres.c:3249 tcop/postgres.c:3308 -#, c-format -msgid "terminating connection due to conflict with recovery" -msgstr "закрытие подключения из-за конфликта с процессом восстановления" - -#: tcop/postgres.c:3260 +#: tcop/postgres.c:3317 #, c-format msgid "terminating connection due to administrator command" msgstr "закрытие подключения по команде администратора" -#: tcop/postgres.c:3291 +#: tcop/postgres.c:3348 #, c-format msgid "connection to client lost" msgstr "подключение к клиенту потеряно" -#: tcop/postgres.c:3361 +#: tcop/postgres.c:3400 #, c-format msgid "canceling statement due to lock timeout" msgstr "выполнение оператора отменено из-за тайм-аута блокировки" -#: tcop/postgres.c:3368 +#: tcop/postgres.c:3407 #, c-format msgid "canceling statement due to statement timeout" msgstr "выполнение оператора отменено из-за тайм-аута" -#: tcop/postgres.c:3375 +#: tcop/postgres.c:3414 #, c-format msgid "canceling autovacuum task" msgstr "отмена задачи автоочистки" -#: tcop/postgres.c:3398 +#: tcop/postgres.c:3427 #, c-format msgid "canceling statement due to user request" msgstr "выполнение оператора отменено по запросу пользователя" -#: tcop/postgres.c:3412 +#: tcop/postgres.c:3448 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "закрытие подключения из-за тайм-аута простоя в транзакции" -#: tcop/postgres.c:3423 +#: tcop/postgres.c:3461 +#, c-format +msgid "terminating connection due to transaction timeout" +msgstr "закрытие подключения из-за тайм-аута транзакции" + +#: tcop/postgres.c:3474 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "закрытие подключения из-за тайм-аута простоя сеанса" -#: tcop/postgres.c:3514 +#: tcop/postgres.c:3564 #, c-format msgid "stack depth limit exceeded" msgstr "превышен предел глубины стека" -#: tcop/postgres.c:3515 +#: tcop/postgres.c:3565 #, c-format msgid "" "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), " @@ -25283,12 +26454,12 @@ msgstr "" "КБ), предварительно убедившись, что ОС предоставляет достаточный размер " "стека." -#: tcop/postgres.c:3562 +#: tcop/postgres.c:3612 #, c-format msgid "\"max_stack_depth\" must not exceed %ldkB." msgstr "Значение \"max_stack_depth\" не должно превышать %ld КБ." -#: tcop/postgres.c:3564 +#: tcop/postgres.c:3614 #, c-format msgid "" "Increase the platform's stack depth limit via \"ulimit -s\" or local " @@ -25297,20 +26468,20 @@ msgstr "" "Увеличьте предел глубины стека в системе с помощью команды \"ulimit -s\" или " "эквивалента в вашей ОС." -#: tcop/postgres.c:3587 +#: tcop/postgres.c:3637 #, c-format -msgid "client_connection_check_interval must be set to 0 on this platform." +msgid "\"client_connection_check_interval\" must be set to 0 on this platform." msgstr "" -"Значение client_connection_check_interval должно равняться 0 на этой " +"Значение \"client_connection_check_interval\" должно равняться 0 на этой " "платформе." -#: tcop/postgres.c:3608 +#: tcop/postgres.c:3658 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "" "Этот параметр нельзя включить, когда \"log_statement_stats\" равен true." -#: tcop/postgres.c:3623 +#: tcop/postgres.c:3673 #, c-format msgid "" "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", " @@ -25320,49 +26491,49 @@ msgstr "" "\"log_parser_stats\", \"log_planner_stats\" или \"log_executor_stats\" равны " "true." -#: tcop/postgres.c:3971 +#: tcop/postgres.c:4098 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "неверный аргумент командной строки для серверного процесса: %s" -#: tcop/postgres.c:3972 tcop/postgres.c:3978 +#: tcop/postgres.c:4099 tcop/postgres.c:4105 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: tcop/postgres.c:3976 +#: tcop/postgres.c:4103 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: неверный аргумент командной строки: %s" -#: tcop/postgres.c:4029 +#: tcop/postgres.c:4156 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: не указаны ни база данных, ни пользователь" -#: tcop/postgres.c:4779 +#: tcop/postgres.c:4909 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "неверный подтип сообщения CLOSE: %d" -#: tcop/postgres.c:4816 +#: tcop/postgres.c:4946 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "неверный подтип сообщения DESCRIBE: %d" -#: tcop/postgres.c:4903 +#: tcop/postgres.c:5033 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "" "вызовы функций через fastpath не поддерживаются для реплицирующих соединений" -#: tcop/postgres.c:4907 +#: tcop/postgres.c:5037 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "" "протокол расширенных запросов не поддерживается для реплицирующих соединений" -#: tcop/postgres.c:5087 +#: tcop/postgres.c:5217 #, c-format msgid "" "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s " @@ -25378,53 +26549,53 @@ msgstr "" "число форматов результатов в сообщении Bind (%d) не равно числу столбцов в " "запросе (%d)" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:942 tcop/pquery.c:1696 #, c-format msgid "cursor can only scan forward" msgstr "курсор может сканировать только вперёд" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:943 tcop/pquery.c:1697 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "Добавьте в его объявление SCROLL, чтобы он мог перемещаться назад." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:417 +#: tcop/utility.c:410 #, c-format msgid "cannot execute %s in a read-only transaction" msgstr "в транзакции в режиме \"только чтение\" нельзя выполнить %s" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:435 +#: tcop/utility.c:428 #, c-format msgid "cannot execute %s during a parallel operation" msgstr "выполнить %s во время параллельных операций нельзя" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:454 +#: tcop/utility.c:447 #, c-format msgid "cannot execute %s during recovery" msgstr "выполнить %s во время восстановления нельзя" #. translator: %s is name of a SQL command, eg PREPARE -#: tcop/utility.c:472 +#: tcop/utility.c:465 #, c-format msgid "cannot execute %s within security-restricted operation" msgstr "в рамках операции с ограничениями по безопасности нельзя выполнить %s" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:828 +#: tcop/utility.c:821 #, c-format msgid "cannot execute %s within a background process" msgstr "выполнять %s в фоновом процессе нельзя" #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:954 +#: tcop/utility.c:947 #, c-format msgid "permission denied to execute %s command" msgstr "нет прав для выполнения команды %s" -#: tcop/utility.c:956 +#: tcop/utility.c:949 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "Выполнять эту команду могут только роли с правами роли \"%s\"." @@ -25579,13 +26750,13 @@ msgstr "неверный флаг аффиксов \"%s\" со значение msgid "could not open dictionary file \"%s\": %m" msgstr "не удалось открыть файл словаря \"%s\": %m" -#: tsearch/spell.c:749 utils/adt/regexp.c:224 jsonpath_gram.y:559 +#: tsearch/spell.c:749 utils/adt/regexp.c:223 jsonpath_gram.y:629 #, c-format msgid "invalid regular expression: %s" msgstr "неверное регулярное выражение: %s" #: tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 -#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18123 gram.y:18140 +#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18735 gram.y:18752 #, c-format msgid "syntax error" msgstr "ошибка синтаксиса" @@ -25625,17 +26796,17 @@ msgstr "количество псевдонимов превышает зада msgid "affix file contains both old-style and new-style commands" msgstr "файл аффиксов содержит команды и в старом, и в новом стиле" -#: tsearch/to_tsany.c:195 utils/adt/tsvector.c:278 utils/adt/tsvector_op.c:1128 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "строка слишком длинна для tsvector (%d Б, при максимуме %d)" -#: tsearch/ts_locale.c:238 +#: tsearch/ts_locale.c:236 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "строка %d файла конфигурации \"%s\": \"%s\"" -#: tsearch/ts_locale.c:317 +#: tsearch/ts_locale.c:315 #, c-format msgid "conversion from wchar_t to server encoding failed: %m" msgstr "преобразовать wchar_t в кодировку сервера не удалось: %m" @@ -25662,37 +26833,32 @@ msgstr "неверное имя файла конфигурации тексто msgid "could not open stop-word file \"%s\": %m" msgstr "не удалось открыть файл стоп-слов \"%s\": %m" -#: tsearch/wparser.c:308 tsearch/wparser.c:396 tsearch/wparser.c:473 +#: tsearch/wparser.c:306 tsearch/wparser.c:394 tsearch/wparser.c:471 #, c-format msgid "text search parser does not support headline creation" msgstr "анализатор текстового поиска не поддерживает создание выдержек" -#: tsearch/wparser_def.c:2663 +#: tsearch/wparser_def.c:2664 #, c-format msgid "unrecognized headline parameter: \"%s\"" msgstr "нераспознанный параметр функции выдержки: \"%s\"" -#: tsearch/wparser_def.c:2673 +#: tsearch/wparser_def.c:2674 #, c-format -msgid "MinWords should be less than MaxWords" -msgstr "Значение MinWords должно быть меньше MaxWords" +msgid "%s must be less than %s" +msgstr "%s должно быть меньше %s" -#: tsearch/wparser_def.c:2677 +#: tsearch/wparser_def.c:2678 #, c-format -msgid "MinWords should be positive" -msgstr "Значение MinWords должно быть положительным" +msgid "%s must be positive" +msgstr "%s должно быть больше нуля" -#: tsearch/wparser_def.c:2681 +#: tsearch/wparser_def.c:2682 tsearch/wparser_def.c:2686 #, c-format -msgid "ShortWord should be >= 0" -msgstr "Значение ShortWord должно быть >= 0" +msgid "%s must be >= 0" +msgstr "%s должно быть >= 0" -#: tsearch/wparser_def.c:2685 -#, c-format -msgid "MaxFragments should be >= 0" -msgstr "Значение MaxFragments должно быть >= 0" - -#: utils/activity/pgstat.c:438 +#: utils/activity/pgstat.c:435 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "ошибка удаления постоянного файла статистики \"%s\": %m" @@ -25707,28 +26873,28 @@ msgstr "неверный вид статистики: \"%s\"" msgid "could not open temporary statistics file \"%s\": %m" msgstr "не удалось открыть временный файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1447 +#: utils/activity/pgstat.c:1455 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "не удалось записать во временный файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1456 +#: utils/activity/pgstat.c:1464 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "не удалось закрыть временный файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1464 +#: utils/activity/pgstat.c:1472 #, c-format msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" msgstr "" "не удалось переименовать временный файл статистики из \"%s\" в \"%s\": %m" -#: utils/activity/pgstat.c:1513 +#: utils/activity/pgstat.c:1521 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "не удалось открыть файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1675 +#: utils/activity/pgstat.c:1683 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "файл статистики \"%s\" испорчен" @@ -25738,115 +26904,125 @@ msgstr "файл статистики \"%s\" испорчен" msgid "function call to dropped function" msgstr "вызвана функция, которая была удалена" -#: utils/activity/pgstat_xact.c:363 +#: utils/activity/pgstat_xact.c:362 #, c-format msgid "resetting existing statistics for kind %s, db=%u, oid=%u" msgstr "сбрасывается существующая статистика вида %s, db=%u, oid=%u" -#: utils/adt/acl.c:177 utils/adt/name.c:93 +#: utils/activity/wait_event.c:207 utils/activity/wait_event.c:232 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "событие ожидания \"%s\" в типе \"%s\" уже существует" + +#: utils/activity/wait_event.c:246 +#, c-format +msgid "too many custom wait events" +msgstr "слишком много пользовательских событий ожидания" + +#: utils/adt/acl.c:183 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "слишком длинный идентификатор" -#: utils/adt/acl.c:178 utils/adt/name.c:94 +#: utils/adt/acl.c:184 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "Идентификатор должен быть короче %d байт." -#: utils/adt/acl.c:266 +#: utils/adt/acl.c:272 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "нераспознанное ключевое слово: \"%s\"" -#: utils/adt/acl.c:267 +#: utils/adt/acl.c:273 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "Ключевым словом ACL должно быть \"group\" или \"user\"." -#: utils/adt/acl.c:275 +#: utils/adt/acl.c:281 #, c-format msgid "missing name" msgstr "отсутствует имя" -#: utils/adt/acl.c:276 +#: utils/adt/acl.c:282 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "За ключевыми словами \"group\" или \"user\" должно следовать имя." -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:288 #, c-format msgid "missing \"=\" sign" msgstr "отсутствует знак \"=\"" -#: utils/adt/acl.c:341 +#: utils/adt/acl.c:350 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "неверный символ режима: должен быть один из \"%s\"" -#: utils/adt/acl.c:371 +#: utils/adt/acl.c:380 #, c-format msgid "a name must follow the \"/\" sign" msgstr "за знаком \"/\" должно следовать имя" -#: utils/adt/acl.c:383 +#: utils/adt/acl.c:392 #, c-format msgid "defaulting grantor to user ID %u" msgstr "назначившим права считается пользователь с ID %u" -#: utils/adt/acl.c:569 +#: utils/adt/acl.c:578 #, c-format msgid "ACL array contains wrong data type" msgstr "Массив ACL содержит неверный тип данных" -#: utils/adt/acl.c:573 +#: utils/adt/acl.c:582 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "Массивы ACL должны быть одномерными" -#: utils/adt/acl.c:577 +#: utils/adt/acl.c:586 #, c-format msgid "ACL arrays must not contain null values" msgstr "Массивы ACL не должны содержать значения null" -#: utils/adt/acl.c:606 +#: utils/adt/acl.c:615 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "лишний мусор в конце спецификации ACL" -#: utils/adt/acl.c:1248 +#: utils/adt/acl.c:1263 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "привилегию назначения прав нельзя вернуть тому, кто назначил её вам" -#: utils/adt/acl.c:1564 +#: utils/adt/acl.c:1579 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert больше не поддерживается" -#: utils/adt/acl.c:1574 +#: utils/adt/acl.c:1589 #, c-format msgid "aclremove is no longer supported" msgstr "aclremove больше не поддерживается" -#: utils/adt/acl.c:1693 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "нераспознанный тип прав: \"%s\"" -#: utils/adt/acl.c:3476 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3550 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "функция \"%s\" не существует" -#: utils/adt/acl.c:5023 +#: utils/adt/acl.c:5196 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "нужны права для выполнения SET ROLE \"%s\"" #: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 -#: utils/adt/array_userfuncs.c:878 utils/adt/json.c:694 utils/adt/json.c:831 -#: utils/adt/json.c:869 utils/adt/jsonb.c:1139 utils/adt/jsonb.c:1211 -#: utils/adt/jsonb.c:1629 utils/adt/jsonb.c:1817 utils/adt/jsonb.c:1827 +#: utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 +#: utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 +#: utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "не удалось определить тип входных данных" @@ -25857,17 +27033,17 @@ msgid "input data type is not an array" msgstr "тип входных данных не является массивом" #: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 -#: utils/adt/float.c:1228 utils/adt/float.c:1302 utils/adt/float.c:4117 -#: utils/adt/float.c:4155 utils/adt/int.c:778 utils/adt/int.c:800 +#: utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 +#: utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 #: utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 #: utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 #: utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 #: utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 #: utils/adt/int.c:1263 utils/adt/int.c:1331 utils/adt/int.c:1337 -#: utils/adt/int8.c:1272 utils/adt/numeric.c:1901 utils/adt/numeric.c:4388 -#: utils/adt/rangetypes.c:1481 utils/adt/rangetypes.c:1494 -#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1132 -#: utils/adt/varlena.c:3134 +#: utils/adt/int8.c:1256 utils/adt/numeric.c:1917 utils/adt/numeric.c:4454 +#: utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 +#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 +#: utils/adt/varlena.c:3137 #, c-format msgid "integer out of range" msgstr "целое вне диапазона" @@ -25907,188 +27083,199 @@ msgstr "Массивы с разными размерностями элемен msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "Массивы с разными размерностями несовместимы для соединения." -#: utils/adt/array_userfuncs.c:987 utils/adt/array_userfuncs.c:995 -#: utils/adt/arrayfuncs.c:5639 utils/adt/arrayfuncs.c:5645 +#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 +#: utils/adt/arrayfuncs.c:5616 utils/adt/arrayfuncs.c:5622 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "аккумулировать массивы различной размерности нельзя" -#: utils/adt/array_userfuncs.c:1286 utils/adt/array_userfuncs.c:1440 +#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "поиск элементов в многомерных массивах не поддерживается" -#: utils/adt/array_userfuncs.c:1315 +#: utils/adt/array_userfuncs.c:1301 #, c-format msgid "initial position must not be null" msgstr "начальная позиция не может быть NULL" -#: utils/adt/array_userfuncs.c:1688 +#: utils/adt/array_userfuncs.c:1674 #, c-format msgid "sample size must be between 0 and %d" msgstr "размер выборки должен задаваться числом от 0 до %d" -#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:288 -#: utils/adt/arrayfuncs.c:299 utils/adt/arrayfuncs.c:321 -#: utils/adt/arrayfuncs.c:338 utils/adt/arrayfuncs.c:352 -#: utils/adt/arrayfuncs.c:360 utils/adt/arrayfuncs.c:367 -#: utils/adt/arrayfuncs.c:507 utils/adt/arrayfuncs.c:522 -#: utils/adt/arrayfuncs.c:533 utils/adt/arrayfuncs.c:548 -#: utils/adt/arrayfuncs.c:569 utils/adt/arrayfuncs.c:599 -#: utils/adt/arrayfuncs.c:606 utils/adt/arrayfuncs.c:614 -#: utils/adt/arrayfuncs.c:648 utils/adt/arrayfuncs.c:671 -#: utils/adt/arrayfuncs.c:691 utils/adt/arrayfuncs.c:808 -#: utils/adt/arrayfuncs.c:817 utils/adt/arrayfuncs.c:847 -#: utils/adt/arrayfuncs.c:862 utils/adt/arrayfuncs.c:915 +#: utils/adt/arrayfuncs.c:264 utils/adt/arrayfuncs.c:273 +#: utils/adt/arrayfuncs.c:284 utils/adt/arrayfuncs.c:307 +#: utils/adt/arrayfuncs.c:440 utils/adt/arrayfuncs.c:454 +#: utils/adt/arrayfuncs.c:466 utils/adt/arrayfuncs.c:636 +#: utils/adt/arrayfuncs.c:668 utils/adt/arrayfuncs.c:703 +#: utils/adt/arrayfuncs.c:718 utils/adt/arrayfuncs.c:777 +#: utils/adt/arrayfuncs.c:782 utils/adt/arrayfuncs.c:870 +#: utils/adt/arrayfuncs.c:897 utils/adt/arrayfuncs.c:904 +#: utils/adt/arrayfuncs.c:941 #, c-format msgid "malformed array literal: \"%s\"" msgstr "ошибочный литерал массива: \"%s\"" -#: utils/adt/arrayfuncs.c:275 -#, c-format -msgid "\"[\" must introduce explicitly-specified array dimensions." -msgstr "За \"[\" должны следовать явно задаваемые размерности массива." - -#: utils/adt/arrayfuncs.c:289 +#: utils/adt/arrayfuncs.c:265 #, c-format -msgid "Missing array dimension value." -msgstr "Отсутствует значение размерности массива." +msgid "Array value must start with \"{\" or dimension information." +msgstr "Значение массива должно начинаться с \"{\" или указания размерности." -#: utils/adt/arrayfuncs.c:300 utils/adt/arrayfuncs.c:339 +#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:467 #, c-format msgid "Missing \"%s\" after array dimensions." msgstr "После размерностей массива отсутствует \"%s\"." -#: utils/adt/arrayfuncs.c:309 utils/adt/arrayfuncs.c:2969 -#: utils/adt/arrayfuncs.c:3014 utils/adt/arrayfuncs.c:3029 +#: utils/adt/arrayfuncs.c:285 #, c-format -msgid "upper bound cannot be less than lower bound" -msgstr "верхняя граница не может быть меньше нижней" +msgid "Array contents must start with \"{\"." +msgstr "Содержимое массива должно начинаться с \"{\"." -#: utils/adt/arrayfuncs.c:322 +#: utils/adt/arrayfuncs.c:308 utils/adt/multirangetypes.c:292 #, c-format -msgid "Array value must start with \"{\" or dimension information." -msgstr "Значение массива должно начинаться с \"{\" или указания размерности." +msgid "Junk after closing right brace." +msgstr "Мусор после закрывающей фигурной скобки." -#: utils/adt/arrayfuncs.c:353 +#: utils/adt/arrayfuncs.c:431 utils/adt/arrayfuncs.c:643 #, c-format -msgid "Array contents must start with \"{\"." -msgstr "Содержимое массива должно начинаться с \"{\"." +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "число размерностей массива превышает предел (%d)" -#: utils/adt/arrayfuncs.c:361 utils/adt/arrayfuncs.c:368 +#: utils/adt/arrayfuncs.c:441 #, c-format -msgid "Specified array dimensions do not match array contents." -msgstr "Указанные размерности массива не соответствуют его содержимому." +msgid "\"[\" must introduce explicitly-specified array dimensions." +msgstr "За \"[\" должны следовать явно задаваемые размерности массива." -#: utils/adt/arrayfuncs.c:508 utils/adt/arrayfuncs.c:534 -#: utils/adt/multirangetypes.c:166 utils/adt/rangetypes.c:2405 -#: utils/adt/rangetypes.c:2413 utils/adt/rowtypes.c:219 -#: utils/adt/rowtypes.c:230 +#: utils/adt/arrayfuncs.c:455 #, c-format -msgid "Unexpected end of input." -msgstr "Неожиданный конец ввода." +msgid "Missing array dimension value." +msgstr "Отсутствует значение размерности массива." + +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 +#: utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 +#, c-format +msgid "upper bound cannot be less than lower bound" +msgstr "верхняя граница не может быть меньше нижней" + +#: utils/adt/arrayfuncs.c:487 +#, c-format +msgid "array upper bound is too large: %d" +msgstr "верхняя граница массива слишком велика: %d" + +#: utils/adt/arrayfuncs.c:538 +#, c-format +msgid "array bound is out of integer range" +msgstr "граница массива вне целочисленного диапазона" -#: utils/adt/arrayfuncs.c:523 utils/adt/arrayfuncs.c:570 -#: utils/adt/arrayfuncs.c:600 utils/adt/arrayfuncs.c:649 +#: utils/adt/arrayfuncs.c:637 utils/adt/arrayfuncs.c:669 +#: utils/adt/arrayfuncs.c:704 utils/adt/arrayfuncs.c:898 #, c-format msgid "Unexpected \"%c\" character." msgstr "Неожиданный знак \"%c\"." -#: utils/adt/arrayfuncs.c:549 utils/adt/arrayfuncs.c:672 +#: utils/adt/arrayfuncs.c:719 #, c-format msgid "Unexpected array element." msgstr "Неожиданный элемент массива." -#: utils/adt/arrayfuncs.c:607 +#: utils/adt/arrayfuncs.c:778 #, c-format -msgid "Unmatched \"%c\" character." -msgstr "Непарный знак \"%c\"." +msgid "Specified array dimensions do not match array contents." +msgstr "Указанные размерности массива не соответствуют его содержимому." -#: utils/adt/arrayfuncs.c:615 utils/adt/jsonfuncs.c:2553 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2598 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "" "Для многомерных массивов должны задаваться вложенные массивы с " "соответствующими размерностями." -#: utils/adt/arrayfuncs.c:692 utils/adt/multirangetypes.c:293 +#: utils/adt/arrayfuncs.c:871 utils/adt/arrayfuncs.c:905 #, c-format -msgid "Junk after closing right brace." -msgstr "Мусор после закрывающей фигурной скобки." +msgid "Incorrectly quoted array element." +msgstr "Элемент массива заключён в кавычки некорректно." + +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 +#: utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 +#: utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#, c-format +msgid "Unexpected end of input." +msgstr "Неожиданный конец ввода." -#: utils/adt/arrayfuncs.c:1326 utils/adt/arrayfuncs.c:3528 -#: utils/adt/arrayfuncs.c:6129 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3499 +#: utils/adt/arrayfuncs.c:6106 #, c-format msgid "invalid number of dimensions: %d" msgstr "неверное число размерностей: %d" -#: utils/adt/arrayfuncs.c:1337 +#: utils/adt/arrayfuncs.c:1312 #, c-format msgid "invalid array flags" msgstr "неверные флаги массива" -#: utils/adt/arrayfuncs.c:1359 +#: utils/adt/arrayfuncs.c:1334 #, c-format msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "" "с бинарными данными связан тип элемента массива %u (%s) вместо ожидаемого %u " "(%s)" -#: utils/adt/arrayfuncs.c:1403 utils/adt/multirangetypes.c:451 -#: utils/adt/rangetypes.c:344 utils/cache/lsyscache.c:2916 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 +#: utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 #, c-format msgid "no binary input function available for type %s" msgstr "для типа %s нет функции ввода двоичных данных" -#: utils/adt/arrayfuncs.c:1543 +#: utils/adt/arrayfuncs.c:1509 #, c-format msgid "improper binary format in array element %d" msgstr "неподходящий двоичный формат в элементе массива %d" -#: utils/adt/arrayfuncs.c:1624 utils/adt/multirangetypes.c:456 -#: utils/adt/rangetypes.c:349 utils/cache/lsyscache.c:2949 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 +#: utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 #, c-format msgid "no binary output function available for type %s" msgstr "для типа %s нет функции вывода двоичных данных" -#: utils/adt/arrayfuncs.c:2103 +#: utils/adt/arrayfuncs.c:2067 #, c-format msgid "slices of fixed-length arrays not implemented" msgstr "разрезание массивов постоянной длины не поддерживается" -#: utils/adt/arrayfuncs.c:2281 utils/adt/arrayfuncs.c:2303 -#: utils/adt/arrayfuncs.c:2352 utils/adt/arrayfuncs.c:2606 -#: utils/adt/arrayfuncs.c:2944 utils/adt/arrayfuncs.c:6115 -#: utils/adt/arrayfuncs.c:6141 utils/adt/arrayfuncs.c:6152 -#: utils/adt/json.c:1497 utils/adt/json.c:1569 utils/adt/jsonb.c:1416 -#: utils/adt/jsonb.c:1500 utils/adt/jsonfuncs.c:4434 utils/adt/jsonfuncs.c:4587 -#: utils/adt/jsonfuncs.c:4698 utils/adt/jsonfuncs.c:4746 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 +#: utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 +#: utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6092 +#: utils/adt/arrayfuncs.c:6118 utils/adt/arrayfuncs.c:6129 +#: utils/adt/json.c:1433 utils/adt/json.c:1505 utils/adt/jsonb.c:1317 +#: utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4710 utils/adt/jsonfuncs.c:4863 +#: utils/adt/jsonfuncs.c:4974 utils/adt/jsonfuncs.c:5022 #, c-format msgid "wrong number of array subscripts" msgstr "неверное число индексов массива" -#: utils/adt/arrayfuncs.c:2286 utils/adt/arrayfuncs.c:2410 -#: utils/adt/arrayfuncs.c:2689 utils/adt/arrayfuncs.c:3019 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 +#: utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "индекс массива вне диапазона" -#: utils/adt/arrayfuncs.c:2291 +#: utils/adt/arrayfuncs.c:2255 #, c-format msgid "cannot assign null value to an element of a fixed-length array" msgstr "нельзя присвоить значение null элементу массива фиксированной длины" -#: utils/adt/arrayfuncs.c:2891 +#: utils/adt/arrayfuncs.c:2855 #, c-format msgid "updates on slices of fixed-length arrays not implemented" msgstr "изменения в срезах массивов фиксированной длины не поддерживаются" -#: utils/adt/arrayfuncs.c:2922 +#: utils/adt/arrayfuncs.c:2886 #, c-format msgid "array slice subscript must provide both boundaries" msgstr "в указании среза массива должны быть заданы обе границы" -#: utils/adt/arrayfuncs.c:2923 +#: utils/adt/arrayfuncs.c:2887 #, c-format msgid "" "When assigning to a slice of an empty array value, slice boundaries must be " @@ -26097,85 +27284,85 @@ msgstr "" "При присвоении значений срезу в пустом массиве, должны полностью задаваться " "обе границы." -#: utils/adt/arrayfuncs.c:2934 utils/adt/arrayfuncs.c:3046 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "исходный массив слишком мал" -#: utils/adt/arrayfuncs.c:3686 +#: utils/adt/arrayfuncs.c:3657 #, c-format msgid "null array element not allowed in this context" msgstr "элемент массива null недопустим в данном контексте" -#: utils/adt/arrayfuncs.c:3857 utils/adt/arrayfuncs.c:4028 -#: utils/adt/arrayfuncs.c:4419 +#: utils/adt/arrayfuncs.c:3828 utils/adt/arrayfuncs.c:3999 +#: utils/adt/arrayfuncs.c:4390 #, c-format msgid "cannot compare arrays of different element types" msgstr "нельзя сравнивать массивы с элементами разных типов" -#: utils/adt/arrayfuncs.c:4206 utils/adt/multirangetypes.c:2806 -#: utils/adt/multirangetypes.c:2878 utils/adt/rangetypes.c:1354 -#: utils/adt/rangetypes.c:1418 utils/adt/rowtypes.c:1885 +#: utils/adt/arrayfuncs.c:4177 utils/adt/multirangetypes.c:2805 +#: utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 +#: utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 #, c-format msgid "could not identify a hash function for type %s" msgstr "не удалось найти функцию хеширования для типа %s" -#: utils/adt/arrayfuncs.c:4334 utils/adt/rowtypes.c:2006 +#: utils/adt/arrayfuncs.c:4305 utils/adt/rowtypes.c:1996 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "не удалось найти функцию расширенного хеширования для типа %s" -#: utils/adt/arrayfuncs.c:5529 +#: utils/adt/arrayfuncs.c:5506 #, c-format msgid "data type %s is not an array type" msgstr "тип данных %s не является типом массива" -#: utils/adt/arrayfuncs.c:5584 +#: utils/adt/arrayfuncs.c:5561 #, c-format msgid "cannot accumulate null arrays" msgstr "аккумулировать NULL-массивы нельзя" -#: utils/adt/arrayfuncs.c:5612 +#: utils/adt/arrayfuncs.c:5589 #, c-format msgid "cannot accumulate empty arrays" msgstr "аккумулировать пустые массивы нельзя" -#: utils/adt/arrayfuncs.c:6013 utils/adt/arrayfuncs.c:6053 +#: utils/adt/arrayfuncs.c:5990 utils/adt/arrayfuncs.c:6030 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "массив размерностей или массив нижних границ не может быть null" -#: utils/adt/arrayfuncs.c:6116 utils/adt/arrayfuncs.c:6142 +#: utils/adt/arrayfuncs.c:6093 utils/adt/arrayfuncs.c:6119 #, c-format msgid "Dimension array must be one dimensional." msgstr "Массив размерностей должен быть одномерным." -#: utils/adt/arrayfuncs.c:6121 utils/adt/arrayfuncs.c:6147 +#: utils/adt/arrayfuncs.c:6098 utils/adt/arrayfuncs.c:6124 #, c-format msgid "dimension values cannot be null" msgstr "значения размерностей не могут быть null" -#: utils/adt/arrayfuncs.c:6153 +#: utils/adt/arrayfuncs.c:6130 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "Массив нижних границ и массив размерностей имеют разные размеры." -#: utils/adt/arrayfuncs.c:6431 +#: utils/adt/arrayfuncs.c:6411 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "удаление элементов из многомерных массивов не поддерживается" -#: utils/adt/arrayfuncs.c:6708 +#: utils/adt/arrayfuncs.c:6688 #, c-format msgid "thresholds must be one-dimensional array" msgstr "границы должны задаваться одномерным массивом" -#: utils/adt/arrayfuncs.c:6713 +#: utils/adt/arrayfuncs.c:6693 #, c-format msgid "thresholds array must not contain NULLs" msgstr "массив границ не должен содержать NULL" -#: utils/adt/arrayfuncs.c:6946 +#: utils/adt/arrayfuncs.c:6926 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "число удаляемых элементов должно быть от 0 до %d" @@ -26190,22 +27377,22 @@ msgstr "индекс элемента массива должен быть це msgid "array subscript in assignment must not be null" msgstr "индекс элемента массива в присваивании не может быть NULL" -#: utils/adt/arrayutils.c:155 +#: utils/adt/arrayutils.c:140 #, c-format msgid "array lower bound is too large: %d" msgstr "нижняя граница массива слишком велика: %d" -#: utils/adt/arrayutils.c:257 +#: utils/adt/arrayutils.c:242 #, c-format msgid "typmod array must be type cstring[]" msgstr "массив typmod должен иметь тип cstring[]" -#: utils/adt/arrayutils.c:262 +#: utils/adt/arrayutils.c:247 #, c-format msgid "typmod array must be one-dimensional" msgstr "массив typmod должен быть одномерным" -#: utils/adt/arrayutils.c:267 +#: utils/adt/arrayutils.c:252 #, c-format msgid "typmod array must not contain nulls" msgstr "массив typmod не должен содержать элементы null" @@ -26216,48 +27403,52 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "преобразование кодировки из %s в ASCII не поддерживается" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:153 utils/adt/cash.c:277 utils/adt/datetime.c:4017 -#: utils/adt/float.c:206 utils/adt/float.c:293 utils/adt/float.c:307 -#: utils/adt/float.c:412 utils/adt/float.c:495 utils/adt/float.c:509 +#: utils/adt/bool.c:149 utils/adt/cash.c:354 utils/adt/datetime.c:4142 +#: utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 +#: utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 #: utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 #: utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 #: utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 #: utils/adt/geo_ops.c:4672 utils/adt/int.c:174 utils/adt/int.c:186 -#: utils/adt/jsonpath.c:183 utils/adt/mac.c:94 utils/adt/mac8.c:225 -#: utils/adt/network.c:99 utils/adt/numeric.c:795 utils/adt/numeric.c:7136 -#: utils/adt/numeric.c:7339 utils/adt/numeric.c:8286 utils/adt/numutils.c:357 -#: utils/adt/numutils.c:619 utils/adt/numutils.c:881 utils/adt/numutils.c:920 -#: utils/adt/numutils.c:942 utils/adt/numutils.c:1006 utils/adt/numutils.c:1028 -#: utils/adt/pg_lsn.c:74 utils/adt/tid.c:72 utils/adt/tid.c:80 -#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:494 -#: utils/adt/uuid.c:135 utils/adt/xid8funcs.c:362 +#: utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 +#: utils/adt/network.c:99 utils/adt/numeric.c:803 utils/adt/numeric.c:7221 +#: utils/adt/numeric.c:7424 utils/adt/numeric.c:8371 utils/adt/numutils.c:356 +#: utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 +#: utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 +#: utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 +#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:510 +#: utils/adt/uuid.c:140 utils/adt/xid8funcs.c:323 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "неверный синтаксис для типа %s: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 -#: utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:351 -#: utils/adt/numutils.c:613 utils/adt/numutils.c:875 utils/adt/numutils.c:926 -#: utils/adt/numutils.c:965 utils/adt/numutils.c:1012 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 +#: utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "значение \"%s\" вне диапазона для типа %s" +msgid "money out of range" +msgstr "денежное значение вне диапазона" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 -#: utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 -#: utils/adt/float.c:105 utils/adt/int.c:843 utils/adt/int.c:959 -#: utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 -#: utils/adt/int.c:1167 utils/adt/int8.c:515 utils/adt/int8.c:573 -#: utils/adt/int8.c:958 utils/adt/int8.c:1038 utils/adt/int8.c:1100 -#: utils/adt/int8.c:1180 utils/adt/numeric.c:3175 utils/adt/numeric.c:3198 -#: utils/adt/numeric.c:3283 utils/adt/numeric.c:3301 utils/adt/numeric.c:3397 -#: utils/adt/numeric.c:8835 utils/adt/numeric.c:9148 utils/adt/numeric.c:9496 -#: utils/adt/numeric.c:9612 utils/adt/numeric.c:11122 -#: utils/adt/timestamp.c:3442 +#: utils/adt/cash.c:161 utils/adt/cash.c:723 utils/adt/float.c:99 +#: utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 +#: utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 +#: utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 +#: utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 +#: utils/adt/numeric.c:3191 utils/adt/numeric.c:3214 utils/adt/numeric.c:3299 +#: utils/adt/numeric.c:3317 utils/adt/numeric.c:3413 utils/adt/numeric.c:8920 +#: utils/adt/numeric.c:9233 utils/adt/numeric.c:9581 utils/adt/numeric.c:9697 +#: utils/adt/numeric.c:11208 utils/adt/timestamp.c:3713 #, c-format msgid "division by zero" msgstr "деление на ноль" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 +#: utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 +#: utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 +#: utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "значение \"%s\" вне диапазона для типа %s" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -26268,164 +27459,187 @@ msgstr "значение \"char\" вне диапазона" msgid "could not compute %s hash: %s" msgstr "не удалось вычислить хеш %s: %s" -#: utils/adt/date.c:63 utils/adt/timestamp.c:100 utils/adt/varbit.c:105 -#: utils/adt/varchar.c:49 +#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 +#: utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "неверный модификатор типа" -#: utils/adt/date.c:75 +#: utils/adt/date.c:76 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "TIME(%d)%s: точность должна быть неотрицательной" -#: utils/adt/date.c:81 +#: utils/adt/date.c:82 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "TIME(%d)%s: точность уменьшена до дозволенного максимума: %d" -#: utils/adt/date.c:166 utils/adt/date.c:174 utils/adt/formatting.c:4241 -#: utils/adt/formatting.c:4250 utils/adt/formatting.c:4363 -#: utils/adt/formatting.c:4373 +#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 +#: utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 +#: utils/adt/formatting.c:4548 #, c-format msgid "date out of range: \"%s\"" msgstr "дата вне диапазона: \"%s\"" -#: utils/adt/date.c:221 utils/adt/date.c:519 utils/adt/date.c:543 -#: utils/adt/rangetypes.c:1577 utils/adt/rangetypes.c:1592 utils/adt/xml.c:2470 +#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 +#: utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "дата вне диапазона" -#: utils/adt/date.c:267 utils/adt/timestamp.c:582 +#: utils/adt/date.c:268 utils/adt/timestamp.c:598 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "значение поля типа date вне диапазона: %d-%02d-%02d" -#: utils/adt/date.c:274 utils/adt/date.c:283 utils/adt/timestamp.c:588 +#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "дата вне диапазона: %d-%02d-%02d" -#: utils/adt/date.c:494 +#: utils/adt/date.c:495 #, c-format msgid "cannot subtract infinite dates" msgstr "вычитать бесконечные даты нельзя" -#: utils/adt/date.c:592 utils/adt/date.c:655 utils/adt/date.c:691 -#: utils/adt/date.c:2885 utils/adt/date.c:2895 +#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 +#: utils/adt/date.c:2906 utils/adt/date.c:2916 #, c-format msgid "date out of range for timestamp" msgstr "дата вне диапазона для типа timestamp" -#: utils/adt/date.c:1121 utils/adt/date.c:1204 utils/adt/date.c:1220 -#: utils/adt/date.c:2206 utils/adt/date.c:2990 utils/adt/timestamp.c:4172 -#: utils/adt/timestamp.c:4382 utils/adt/timestamp.c:4524 -#: utils/adt/timestamp.c:4777 utils/adt/timestamp.c:4978 -#: utils/adt/timestamp.c:5025 utils/adt/timestamp.c:5249 -#: utils/adt/timestamp.c:5296 utils/adt/timestamp.c:5426 +#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 +#: utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 +#: utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 +#: utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 +#: utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 +#: utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 +#: utils/adt/timestamp.c:6070 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "единица \"%s\" для типа %s не поддерживается" -#: utils/adt/date.c:1229 utils/adt/date.c:2222 utils/adt/date.c:3010 -#: utils/adt/timestamp.c:4186 utils/adt/timestamp.c:4399 -#: utils/adt/timestamp.c:4538 utils/adt/timestamp.c:4737 -#: utils/adt/timestamp.c:5034 utils/adt/timestamp.c:5305 -#: utils/adt/timestamp.c:5487 +#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 +#: utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 +#: utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 +#: utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 +#: utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "единица \"%s\" для типа %s не распознана" -#: utils/adt/date.c:1313 utils/adt/date.c:1359 utils/adt/date.c:1918 -#: utils/adt/date.c:1949 utils/adt/date.c:1978 utils/adt/date.c:2848 -#: utils/adt/date.c:3080 utils/adt/datetime.c:424 utils/adt/datetime.c:1809 -#: utils/adt/formatting.c:4081 utils/adt/formatting.c:4117 -#: utils/adt/formatting.c:4210 utils/adt/formatting.c:4339 utils/adt/json.c:467 -#: utils/adt/json.c:506 utils/adt/timestamp.c:232 utils/adt/timestamp.c:264 -#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:709 -#: utils/adt/timestamp.c:787 utils/adt/timestamp.c:820 -#: utils/adt/timestamp.c:2933 utils/adt/timestamp.c:2938 -#: utils/adt/timestamp.c:2957 utils/adt/timestamp.c:2970 -#: utils/adt/timestamp.c:2981 utils/adt/timestamp.c:2987 -#: utils/adt/timestamp.c:2993 utils/adt/timestamp.c:2998 -#: utils/adt/timestamp.c:3059 utils/adt/timestamp.c:3064 -#: utils/adt/timestamp.c:3085 utils/adt/timestamp.c:3098 -#: utils/adt/timestamp.c:3112 utils/adt/timestamp.c:3120 -#: utils/adt/timestamp.c:3126 utils/adt/timestamp.c:3131 -#: utils/adt/timestamp.c:3859 utils/adt/timestamp.c:3983 -#: utils/adt/timestamp.c:4054 utils/adt/timestamp.c:4090 -#: utils/adt/timestamp.c:4180 utils/adt/timestamp.c:4254 -#: utils/adt/timestamp.c:4290 utils/adt/timestamp.c:4393 -#: utils/adt/timestamp.c:4842 utils/adt/timestamp.c:5116 -#: utils/adt/timestamp.c:5555 utils/adt/timestamp.c:5565 -#: utils/adt/timestamp.c:5570 utils/adt/timestamp.c:5576 -#: utils/adt/timestamp.c:5609 utils/adt/timestamp.c:5696 -#: utils/adt/timestamp.c:5737 utils/adt/timestamp.c:5741 -#: utils/adt/timestamp.c:5795 utils/adt/timestamp.c:5799 -#: utils/adt/timestamp.c:5805 utils/adt/timestamp.c:5839 utils/adt/xml.c:2492 -#: utils/adt/xml.c:2499 utils/adt/xml.c:2519 utils/adt/xml.c:2526 +#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 +#: utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 +#: utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 +#: utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 +#: utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 +#: utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 +#: utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 +#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 +#: utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 +#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 +#: utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 +#: utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 +#: utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 +#: utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 +#: utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 +#: utils/adt/timestamp.c:3266 utils/adt/timestamp.c:3279 +#: utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 +#: utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 +#: utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 +#: utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 +#: utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 +#: utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 +#: utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 +#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 +#: utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 +#: utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 +#: utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 +#: utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2574 +#: utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "timestamp вне диапазона" -#: utils/adt/date.c:1535 utils/adt/date.c:2343 utils/adt/formatting.c:4431 +#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 #, c-format msgid "time out of range" msgstr "время вне диапазона" -#: utils/adt/date.c:1587 utils/adt/timestamp.c:597 +#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "значение поля типа time вне диапазона: %d:%02d:%02g" -#: utils/adt/date.c:2107 utils/adt/date.c:2647 utils/adt/float.c:1042 -#: utils/adt/float.c:1118 utils/adt/int.c:635 utils/adt/int.c:682 -#: utils/adt/int.c:717 utils/adt/int8.c:414 utils/adt/numeric.c:2579 -#: utils/adt/timestamp.c:3513 utils/adt/timestamp.c:3540 -#: utils/adt/timestamp.c:3571 +#: utils/adt/date.c:2020 +#, c-format +msgid "cannot convert infinite interval to time" +msgstr "бесконечный интервал нельзя привести к типу time" + +#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#, c-format +msgid "cannot add infinite interval to time" +msgstr "бесконечный интервал нельзя добавить к значению time" + +#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#, c-format +msgid "cannot subtract infinite interval from time" +msgstr "бесконечный интервал нельзя вычесть из значения time" + +#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 +#: utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 +#: utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2595 +#: utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 +#: utils/adt/timestamp.c:3888 #, c-format msgid "invalid preceding or following size in window function" msgstr "неверное смещение PRECEDING или FOLLOWING в оконной функции" -#: utils/adt/date.c:2351 +#: utils/adt/date.c:2360 #, c-format msgid "time zone displacement out of range" msgstr "смещение часового пояса вне диапазона" -#: utils/adt/date.c:3111 utils/adt/timestamp.c:5598 utils/adt/timestamp.c:5828 +#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#, c-format +msgid "interval time zone \"%s\" must be finite" +msgstr "задающий часовой пояс интервал \"%s\" должен быть конечным" + +#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "" "интервал \"%s\", задающий часовой пояс, не должен содержать дней или месяцев" -#: utils/adt/datetime.c:3223 utils/adt/datetime.c:4002 -#: utils/adt/datetime.c:4008 utils/adt/timestamp.c:512 +#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 +#: utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 #, c-format msgid "time zone \"%s\" not recognized" msgstr "часовой пояс \"%s\" не распознан" -#: utils/adt/datetime.c:3976 utils/adt/datetime.c:3983 +#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "значение поля типа date/time вне диапазона: \"%s\"" -#: utils/adt/datetime.c:3985 +#: utils/adt/datetime.c:4110 #, c-format msgid "Perhaps you need a different \"datestyle\" setting." msgstr "Возможно, вам нужно изменить настройку \"datestyle\"." -#: utils/adt/datetime.c:3990 +#: utils/adt/datetime.c:4115 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "значение поля interval вне диапазона: \"%s\"" -#: utils/adt/datetime.c:3996 +#: utils/adt/datetime.c:4121 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "смещение часового пояса вне диапазона: \"%s\"" -#: utils/adt/datetime.c:4010 +#: utils/adt/datetime.c:4135 #, c-format msgid "" "This time zone name appears in the configuration file for time zone " @@ -26434,22 +27648,22 @@ msgstr "" "Это имя часового пояса фигурирует в файле конфигурации часового пояса с " "кодом \"%s\"." -#: utils/adt/datum.c:91 utils/adt/datum.c:103 +#: utils/adt/datum.c:90 utils/adt/datum.c:102 #, c-format msgid "invalid Datum pointer" msgstr "неверный указатель Datum" -#: utils/adt/dbsize.c:761 utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:764 utils/adt/dbsize.c:840 #, c-format msgid "invalid size: \"%s\"" msgstr "некорректная величина: \"%s\"" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:841 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "Неверная единица измерения величины: \"%s\"." -#: utils/adt/dbsize.c:839 +#: utils/adt/dbsize.c:842 #, c-format msgid "" "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." @@ -26457,7 +27671,7 @@ msgstr "" "Допустимые единицы измерения: \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", " "\"TB\" и \"PB\"." -#: utils/adt/domains.c:92 +#: utils/adt/domains.c:95 #, c-format msgid "type %s is not a domain" msgstr "тип \"%s\" не является доменом" @@ -26508,10 +27722,10 @@ msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "" "Входные данные лишены выравнивания, обрезаны или повреждены иным образом." -#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:648 -#: utils/adt/varlena.c:331 utils/adt/varlena.c:372 jsonpath_gram.y:528 -#: jsonpath_scan.l:629 jsonpath_scan.l:640 jsonpath_scan.l:650 -#: jsonpath_scan.l:701 +#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:659 +#: utils/adt/varlena.c:333 utils/adt/varlena.c:374 jsonpath_gram.y:266 +#: jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 +#: jsonpath_scan.l:661 jsonpath_scan.l:712 #, c-format msgid "invalid input syntax for type %s" msgstr "неверный синтаксис для типа %s" @@ -26549,205 +27763,200 @@ msgstr "не удалось определить фактический тип msgid "enum %s contains no values" msgstr "перечисление %s не содержит значений" -#: utils/adt/float.c:89 +#: utils/adt/float.c:83 #, c-format msgid "value out of range: overflow" msgstr "значение вне диапазона: переполнение" -#: utils/adt/float.c:97 +#: utils/adt/float.c:91 #, c-format msgid "value out of range: underflow" msgstr "значение вне диапазона: антипереполнение" -#: utils/adt/float.c:286 +#: utils/adt/float.c:280 #, c-format msgid "\"%s\" is out of range for type real" msgstr "\"%s\" вне диапазона для типа real" -#: utils/adt/float.c:488 +#: utils/adt/float.c:482 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "\"%s\" вне диапазона для типа double precision" -#: utils/adt/float.c:1253 utils/adt/float.c:1327 utils/adt/int.c:355 +#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 #: utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 #: utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 -#: utils/adt/int8.c:1293 utils/adt/numeric.c:4500 utils/adt/numeric.c:4505 +#: utils/adt/int8.c:1277 utils/adt/numeric.c:4593 utils/adt/numeric.c:4598 #, c-format msgid "smallint out of range" msgstr "smallint вне диапазона" -#: utils/adt/float.c:1453 utils/adt/numeric.c:3693 utils/adt/numeric.c:10027 +#: utils/adt/float.c:1447 utils/adt/numeric.c:3709 utils/adt/numeric.c:10112 #, c-format msgid "cannot take square root of a negative number" msgstr "извлечь квадратный корень отрицательного числа нельзя" -#: utils/adt/float.c:1521 utils/adt/numeric.c:3981 utils/adt/numeric.c:4093 +#: utils/adt/float.c:1515 utils/adt/numeric.c:3997 utils/adt/numeric.c:4109 #, c-format msgid "zero raised to a negative power is undefined" msgstr "ноль в отрицательной степени даёт неопределённость" -#: utils/adt/float.c:1525 utils/adt/numeric.c:3985 utils/adt/numeric.c:10918 +#: utils/adt/float.c:1519 utils/adt/numeric.c:4001 utils/adt/numeric.c:11003 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "отрицательное число в дробной степени даёт комплексный результат" -#: utils/adt/float.c:1701 utils/adt/float.c:1734 utils/adt/numeric.c:3893 -#: utils/adt/numeric.c:10698 +#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3909 +#: utils/adt/numeric.c:10783 #, c-format msgid "cannot take logarithm of zero" msgstr "вычислить логарифм нуля нельзя" -#: utils/adt/float.c:1705 utils/adt/float.c:1738 utils/adt/numeric.c:3831 -#: utils/adt/numeric.c:3888 utils/adt/numeric.c:10702 +#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3847 +#: utils/adt/numeric.c:3904 utils/adt/numeric.c:10787 #, c-format msgid "cannot take logarithm of a negative number" msgstr "вычислить логарифм отрицательного числа нельзя" -#: utils/adt/float.c:1771 utils/adt/float.c:1802 utils/adt/float.c:1897 -#: utils/adt/float.c:1924 utils/adt/float.c:1952 utils/adt/float.c:1979 -#: utils/adt/float.c:2126 utils/adt/float.c:2163 utils/adt/float.c:2333 -#: utils/adt/float.c:2389 utils/adt/float.c:2454 utils/adt/float.c:2511 -#: utils/adt/float.c:2702 utils/adt/float.c:2726 +#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 +#: utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 +#: utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 +#: utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 +#: utils/adt/float.c:2696 utils/adt/float.c:2720 #, c-format msgid "input is out of range" msgstr "введённое значение вне диапазона" -#: utils/adt/float.c:2867 -#, c-format -msgid "setseed parameter %g is out of allowed range [-1,1]" -msgstr "параметр setseed %g вне допустимого диапазона [-1,1]" - -#: utils/adt/float.c:4095 utils/adt/numeric.c:1841 +#: utils/adt/float.c:4000 utils/adt/numeric.c:1857 #, c-format msgid "count must be greater than zero" msgstr "счётчик должен быть больше нуля" -#: utils/adt/float.c:4100 utils/adt/numeric.c:1852 +#: utils/adt/float.c:4005 utils/adt/numeric.c:1868 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "операнд, нижняя и верхняя границы не могут быть NaN" -#: utils/adt/float.c:4106 utils/adt/numeric.c:1857 +#: utils/adt/float.c:4011 utils/adt/numeric.c:1873 #, c-format msgid "lower and upper bounds must be finite" msgstr "нижняя и верхняя границы должны быть конечными" -#: utils/adt/float.c:4172 utils/adt/numeric.c:1871 +#: utils/adt/float.c:4077 utils/adt/numeric.c:1887 #, c-format msgid "lower bound cannot equal upper bound" msgstr "нижняя граница не может равняться верхней" -#: utils/adt/formatting.c:519 +#: utils/adt/formatting.c:530 #, c-format msgid "invalid format specification for an interval value" msgstr "неправильная спецификация формата для целого числа" -#: utils/adt/formatting.c:520 +#: utils/adt/formatting.c:531 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "Интервалы не привязываются к определённым календарным датам." -#: utils/adt/formatting.c:1150 +#: utils/adt/formatting.c:1161 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\" может быть только последним шаблоном" -#: utils/adt/formatting.c:1158 +#: utils/adt/formatting.c:1169 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\" должна стоять до \"PR\"" -#: utils/adt/formatting.c:1174 +#: utils/adt/formatting.c:1185 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\" должен стоять до \"PR\"" -#: utils/adt/formatting.c:1201 +#: utils/adt/formatting.c:1212 #, c-format msgid "multiple decimal points" msgstr "многочисленные десятичные точки" -#: utils/adt/formatting.c:1205 utils/adt/formatting.c:1288 +#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "нельзя использовать \"V\" вместе с десятичной точкой" -#: utils/adt/formatting.c:1217 +#: utils/adt/formatting.c:1228 #, c-format msgid "cannot use \"S\" twice" msgstr "нельзя использовать \"S\" дважды" -#: utils/adt/formatting.c:1221 +#: utils/adt/formatting.c:1232 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "нельзя использовать \"S\" вместе с \"PL\"/\"MI\"/\"SG\"/\"PR\"" -#: utils/adt/formatting.c:1241 +#: utils/adt/formatting.c:1252 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "нельзя использовать \"S\" вместе с \"MI\"" -#: utils/adt/formatting.c:1251 +#: utils/adt/formatting.c:1262 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "нельзя использовать \"S\" вместе с \"PL\"" -#: utils/adt/formatting.c:1261 +#: utils/adt/formatting.c:1272 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "нельзя использовать \"S\" вместе с \"SG\"" -#: utils/adt/formatting.c:1270 +#: utils/adt/formatting.c:1281 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "нельзя использовать \"PR\" вместе с \"S\"/\"PL\"/\"MI\"/\"SG\"" -#: utils/adt/formatting.c:1296 +#: utils/adt/formatting.c:1307 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "нельзя использовать \"EEEE\" дважды" -#: utils/adt/formatting.c:1302 +#: utils/adt/formatting.c:1313 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "\"EEEE\" несовместим с другими форматами" -#: utils/adt/formatting.c:1303 +#: utils/adt/formatting.c:1314 #, c-format msgid "" "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "" "\"EEEE\" может использоваться только с шаблонами цифр и десятичной точки." -#: utils/adt/formatting.c:1387 +#: utils/adt/formatting.c:1398 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "неверный разделитель в формате datetime: \"%s\"" -#: utils/adt/formatting.c:1514 +#: utils/adt/formatting.c:1525 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\" не является числом" -#: utils/adt/formatting.c:1592 +#: utils/adt/formatting.c:1603 #, c-format msgid "case conversion failed: %s" msgstr "преобразовать регистр не удалось: %s" -#: utils/adt/formatting.c:1646 utils/adt/formatting.c:1768 -#: utils/adt/formatting.c:1891 +#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 +#: utils/adt/formatting.c:1989 #, c-format msgid "could not determine which collation to use for %s function" msgstr "" "не удалось определить, какое правило сортировки использовать для функции %s" -#: utils/adt/formatting.c:2274 +#: utils/adt/formatting.c:2410 #, c-format msgid "invalid combination of date conventions" msgstr "неверное сочетание стилей дат" -#: utils/adt/formatting.c:2275 +#: utils/adt/formatting.c:2411 #, c-format msgid "" "Do not mix Gregorian and ISO week date conventions in a formatting template." @@ -26755,27 +27964,27 @@ msgstr "" "Не смешивайте Григорианский стиль дат (недель) с ISO в одном шаблоне " "форматирования." -#: utils/adt/formatting.c:2297 +#: utils/adt/formatting.c:2433 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "конфликтующие значения поля \"%s\" в строке форматирования" -#: utils/adt/formatting.c:2299 +#: utils/adt/formatting.c:2435 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "Это значение противоречит предыдущему значению поля того же типа." -#: utils/adt/formatting.c:2366 +#: utils/adt/formatting.c:2502 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "входная строка короче, чем требует поле форматирования \"%s\"" -#: utils/adt/formatting.c:2368 +#: utils/adt/formatting.c:2504 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "Требуется символов: %d, а осталось только %d." -#: utils/adt/formatting.c:2370 utils/adt/formatting.c:2384 +#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 #, c-format msgid "" "If your source string is not fixed-width, try using the \"FM\" modifier." @@ -26783,132 +27992,132 @@ msgstr "" "Если входная строка имеет переменную длину, попробуйте использовать " "модификатор \"FM\"." -#: utils/adt/formatting.c:2380 utils/adt/formatting.c:2393 -#: utils/adt/formatting.c:2614 +#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 +#: utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "неверное значение \"%s\" для \"%s\"" -#: utils/adt/formatting.c:2382 +#: utils/adt/formatting.c:2518 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "Поле должно поглотить символов: %d, но удалось разобрать только %d." -#: utils/adt/formatting.c:2395 +#: utils/adt/formatting.c:2531 #, c-format msgid "Value must be an integer." msgstr "Значение должно быть целым числом." -#: utils/adt/formatting.c:2400 +#: utils/adt/formatting.c:2536 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "значение \"%s\" во входной строке вне диапазона" -#: utils/adt/formatting.c:2402 +#: utils/adt/formatting.c:2538 #, c-format msgid "Value must be in the range %d to %d." msgstr "Значение должно быть в интервале %d..%d." -#: utils/adt/formatting.c:2616 +#: utils/adt/formatting.c:2752 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "" "Данное значение не соответствует ни одному из допустимых значений для этого " "поля." -#: utils/adt/formatting.c:2832 utils/adt/formatting.c:2852 -#: utils/adt/formatting.c:2872 utils/adt/formatting.c:2892 -#: utils/adt/formatting.c:2911 utils/adt/formatting.c:2930 -#: utils/adt/formatting.c:2954 utils/adt/formatting.c:2972 -#: utils/adt/formatting.c:2990 utils/adt/formatting.c:3008 -#: utils/adt/formatting.c:3025 utils/adt/formatting.c:3042 +#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 +#: utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 +#: utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 +#: utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 +#: utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 +#: utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 #, c-format msgid "localized string format value too long" msgstr "слишком длинное значение формата локализованной строки" -#: utils/adt/formatting.c:3322 +#: utils/adt/formatting.c:3458 #, c-format msgid "unmatched format separator \"%c\"" msgstr "нет соответствия для заданного в формате разделителя \"%c\"" -#: utils/adt/formatting.c:3383 +#: utils/adt/formatting.c:3519 #, c-format msgid "unmatched format character \"%s\"" msgstr "нет соответствия для заданного в формате символа \"%s\"" -#: utils/adt/formatting.c:3491 +#: utils/adt/formatting.c:3652 #, c-format -msgid "formatting field \"%s\" is only supported in to_char" -msgstr "поле форматирования \"%s\" поддерживается только в функции to_char" +msgid "Time zone abbreviation is not recognized." +msgstr "Сокращённое название часового пояса не распознано." -#: utils/adt/formatting.c:3665 +#: utils/adt/formatting.c:3853 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "ошибка синтаксиса в значении для шаблона \"Y,YYY\"" -#: utils/adt/formatting.c:3754 +#: utils/adt/formatting.c:3942 #, c-format msgid "input string is too short for datetime format" msgstr "входная строка короче, чем требует формат datetime" -#: utils/adt/formatting.c:3762 +#: utils/adt/formatting.c:3950 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "" "после разбора формата datetime во входной строке остались дополнительные " "символы" -#: utils/adt/formatting.c:4319 +#: utils/adt/formatting.c:4494 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "во входной строке для типа timestamptz нет указания часового пояса" -#: utils/adt/formatting.c:4325 +#: utils/adt/formatting.c:4500 #, c-format msgid "timestamptz out of range" msgstr "значение timestamptz вне диапазона" -#: utils/adt/formatting.c:4353 +#: utils/adt/formatting.c:4528 #, c-format msgid "datetime format is zoned but not timed" msgstr "в формате datetime указан часовой пояс, но отсутствует время" -#: utils/adt/formatting.c:4411 +#: utils/adt/formatting.c:4577 #, c-format msgid "missing time zone in input string for type timetz" msgstr "во входной строке для типа timetz нет указания часового пояса" -#: utils/adt/formatting.c:4417 +#: utils/adt/formatting.c:4583 #, c-format msgid "timetz out of range" msgstr "значение timetz вне диапазона" -#: utils/adt/formatting.c:4443 +#: utils/adt/formatting.c:4609 #, c-format msgid "datetime format is not dated and not timed" msgstr "в формате datetime нет ни даты, ни времени" -#: utils/adt/formatting.c:4575 +#: utils/adt/formatting.c:4786 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "час \"%d\" не соответствует 12-часовому формату времени" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4788 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "Используйте 24-часовой формат или передавайте часы от 1 до 12." -#: utils/adt/formatting.c:4689 +#: utils/adt/formatting.c:4900 #, c-format msgid "cannot calculate day of year without year information" msgstr "нельзя рассчитать день года без информации о годе" -#: utils/adt/formatting.c:5621 +#: utils/adt/formatting.c:5852 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\" не поддерживается при вводе" -#: utils/adt/formatting.c:5633 +#: utils/adt/formatting.c:5864 #, c-format msgid "\"RN\" not supported for input" msgstr "\"RN\" не поддерживается при вводе" @@ -26940,12 +28149,7 @@ msgstr "не удалось переместиться в файле \"%s\": %m" msgid "file length too large" msgstr "длина файла слишком велика" -#: utils/adt/genfile.c:248 -#, c-format -msgid "must be superuser to read files with adminpack 1.0" -msgstr "читать файлы, используя adminpack 1.0, может только суперпользователь" - -#: utils/adt/genfile.c:702 +#: utils/adt/genfile.c:656 #, c-format msgid "tablespace with OID %u does not exist" msgstr "табличное пространство с OID %u не существует" @@ -27001,298 +28205,298 @@ msgstr "точек должно быть минимум 2" msgid "invalid int2vector data" msgstr "неверные данные int2vector" -#: utils/adt/int.c:1529 utils/adt/int8.c:1419 utils/adt/numeric.c:1749 -#: utils/adt/timestamp.c:5889 utils/adt/timestamp.c:5971 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1765 +#: utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 #, c-format msgid "step size cannot equal zero" msgstr "размер шага не может быть нулевым" -#: utils/adt/int8.c:449 utils/adt/int8.c:472 utils/adt/int8.c:486 -#: utils/adt/int8.c:500 utils/adt/int8.c:531 utils/adt/int8.c:555 -#: utils/adt/int8.c:637 utils/adt/int8.c:705 utils/adt/int8.c:711 -#: utils/adt/int8.c:737 utils/adt/int8.c:751 utils/adt/int8.c:775 -#: utils/adt/int8.c:788 utils/adt/int8.c:915 utils/adt/int8.c:929 -#: utils/adt/int8.c:943 utils/adt/int8.c:974 utils/adt/int8.c:996 -#: utils/adt/int8.c:1010 utils/adt/int8.c:1024 utils/adt/int8.c:1057 -#: utils/adt/int8.c:1071 utils/adt/int8.c:1085 utils/adt/int8.c:1116 -#: utils/adt/int8.c:1138 utils/adt/int8.c:1152 utils/adt/int8.c:1166 -#: utils/adt/int8.c:1328 utils/adt/int8.c:1363 utils/adt/numeric.c:4459 -#: utils/adt/rangetypes.c:1528 utils/adt/rangetypes.c:1541 +#: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 +#: utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 +#: utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 +#: utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 +#: utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 +#: utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 +#: utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 +#: utils/adt/int8.c:1055 utils/adt/int8.c:1069 utils/adt/int8.c:1100 +#: utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 +#: utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4542 +#: utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 #: utils/adt/varbit.c:1676 #, c-format msgid "bigint out of range" msgstr "bigint вне диапазона" -#: utils/adt/int8.c:1376 +#: utils/adt/int8.c:1360 #, c-format msgid "OID out of range" msgstr "OID вне диапазона" -#: utils/adt/json.c:320 utils/adt/jsonb.c:781 +#: utils/adt/json.c:202 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "" "значением ключа должен быть скаляр (не массив, композитный тип или json)" -#: utils/adt/json.c:1113 utils/adt/json.c:1123 utils/fmgr/funcapi.c:2090 +#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "не удалось определить тип данных аргумента %d" -#: utils/adt/json.c:1146 utils/adt/json.c:1337 utils/adt/json.c:1513 -#: utils/adt/json.c:1591 utils/adt/jsonb.c:1432 utils/adt/jsonb.c:1522 +#: utils/adt/json.c:1067 utils/adt/json.c:1266 utils/adt/json.c:1449 +#: utils/adt/json.c:1527 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "значение null не может быть ключом объекта" -#: utils/adt/json.c:1189 utils/adt/json.c:1352 +#: utils/adt/json.c:1117 utils/adt/json.c:1288 #, c-format msgid "duplicate JSON object key value: %s" msgstr "повторяющийся ключ в объекте JSON: %s" -#: utils/adt/json.c:1297 utils/adt/jsonb.c:1233 +#: utils/adt/json.c:1226 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "в списке аргументов должно быть чётное число элементов" #. translator: %s is a SQL function name -#: utils/adt/json.c:1299 utils/adt/jsonb.c:1235 +#: utils/adt/json.c:1228 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "Аргументы %s должны состоять из пар ключ-значение." -#: utils/adt/json.c:1491 utils/adt/jsonb.c:1410 +#: utils/adt/json.c:1427 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "массив должен иметь два столбца" -#: utils/adt/json.c:1580 utils/adt/jsonb.c:1511 +#: utils/adt/json.c:1516 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "неподходящие размерности массива" -#: utils/adt/json.c:1764 utils/adt/jsonb_util.c:1958 +#: utils/adt/json.c:1702 utils/adt/jsonb_util.c:1956 #, c-format msgid "duplicate JSON object key value" msgstr "повторяющиеся ключи в объекте JSON" -#: utils/adt/jsonb.c:294 +#: utils/adt/jsonb.c:282 #, c-format msgid "string too long to represent as jsonb string" msgstr "слишком длинная строка для представления в виде строки jsonb" -#: utils/adt/jsonb.c:295 +#: utils/adt/jsonb.c:283 #, c-format msgid "" "Due to an implementation restriction, jsonb strings cannot exceed %d bytes." msgstr "" "Из-за ограничений реализации строки jsonb не могут быть длиннее %d байт." -#: utils/adt/jsonb.c:1252 +#: utils/adt/jsonb.c:1153 #, c-format msgid "argument %d: key must not be null" msgstr "аргумент %d: ключ не может быть NULL" -#: utils/adt/jsonb.c:1843 +#: utils/adt/jsonb.c:1744 #, c-format msgid "field name must not be null" msgstr "имя поля не может быть NULL" -#: utils/adt/jsonb.c:1905 +#: utils/adt/jsonb.c:1806 #, c-format msgid "object keys must be strings" msgstr "ключи объектов должны быть строковыми" -#: utils/adt/jsonb.c:2116 +#: utils/adt/jsonb.c:2017 #, c-format msgid "cannot cast jsonb null to type %s" msgstr "привести значение jsonb null к типу %s нельзя" -#: utils/adt/jsonb.c:2117 +#: utils/adt/jsonb.c:2018 #, c-format msgid "cannot cast jsonb string to type %s" msgstr "привести строку jsonb к типу %s нельзя" -#: utils/adt/jsonb.c:2118 +#: utils/adt/jsonb.c:2019 #, c-format msgid "cannot cast jsonb numeric to type %s" msgstr "привести числовое значение jsonb к типу %s нельзя" -#: utils/adt/jsonb.c:2119 +#: utils/adt/jsonb.c:2020 #, c-format msgid "cannot cast jsonb boolean to type %s" msgstr "привести логическое значение jsonb к типу %s нельзя" -#: utils/adt/jsonb.c:2120 +#: utils/adt/jsonb.c:2021 #, c-format msgid "cannot cast jsonb array to type %s" msgstr "привести массив jsonb к типу %s нельзя" -#: utils/adt/jsonb.c:2121 +#: utils/adt/jsonb.c:2022 #, c-format msgid "cannot cast jsonb object to type %s" msgstr "привести объект jsonb к типу %s нельзя" -#: utils/adt/jsonb.c:2122 +#: utils/adt/jsonb.c:2023 #, c-format msgid "cannot cast jsonb array or object to type %s" msgstr "привести массив или объект jsonb к типу %s нельзя" -#: utils/adt/jsonb_util.c:758 +#: utils/adt/jsonb_util.c:756 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "число пар объекта jsonb превышает предел (%zu)" -#: utils/adt/jsonb_util.c:799 +#: utils/adt/jsonb_util.c:797 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "число элементов массива jsonb превышает предел (%zu)" -#: utils/adt/jsonb_util.c:1673 utils/adt/jsonb_util.c:1693 +#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "общий размер элементов массива jsonb превышает предел (%d байт)" -#: utils/adt/jsonb_util.c:1754 utils/adt/jsonb_util.c:1789 -#: utils/adt/jsonb_util.c:1809 +#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 +#: utils/adt/jsonb_util.c:1807 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "общий размер элементов объекта jsonb превышает предел (%d байт)" -#: utils/adt/jsonbsubs.c:70 utils/adt/jsonbsubs.c:151 +#: utils/adt/jsonbsubs.c:67 utils/adt/jsonbsubs.c:148 #, c-format msgid "jsonb subscript does not support slices" msgstr "jsonb не поддерживает обращение по индексу к срезам" -#: utils/adt/jsonbsubs.c:103 utils/adt/jsonbsubs.c:117 +#: utils/adt/jsonbsubs.c:100 utils/adt/jsonbsubs.c:114 #, c-format msgid "subscript type %s is not supported" msgstr "индекс элемента имеет неподдерживаемый тип %s" -#: utils/adt/jsonbsubs.c:104 +#: utils/adt/jsonbsubs.c:101 #, c-format msgid "jsonb subscript must be coercible to only one type, integer or text." msgstr "" "Индекс элемента в jsonb должен приводиться только к одному типу, integer или " "text." -#: utils/adt/jsonbsubs.c:118 +#: utils/adt/jsonbsubs.c:115 #, c-format msgid "jsonb subscript must be coercible to either integer or text." msgstr "Индекс элемента в jsonb должен приводиться к типу integer или text." -#: utils/adt/jsonbsubs.c:139 +#: utils/adt/jsonbsubs.c:136 #, c-format msgid "jsonb subscript must have text type" msgstr "индекс элемента jsonb должен иметь текстовый тип" -#: utils/adt/jsonbsubs.c:207 +#: utils/adt/jsonbsubs.c:204 #, c-format msgid "jsonb subscript in assignment must not be null" msgstr "индекс элемента jsonb в присваивании не может быть NULL" -#: utils/adt/jsonfuncs.c:572 utils/adt/jsonfuncs.c:821 -#: utils/adt/jsonfuncs.c:2429 utils/adt/jsonfuncs.c:2881 -#: utils/adt/jsonfuncs.c:3676 utils/adt/jsonfuncs.c:4018 +#: utils/adt/jsonfuncs.c:583 utils/adt/jsonfuncs.c:830 +#: utils/adt/jsonfuncs.c:2439 utils/adt/jsonfuncs.c:3015 +#: utils/adt/jsonfuncs.c:3948 utils/adt/jsonfuncs.c:4295 #, c-format msgid "cannot call %s on a scalar" msgstr "вызывать %s со скаляром нельзя" -#: utils/adt/jsonfuncs.c:577 utils/adt/jsonfuncs.c:806 -#: utils/adt/jsonfuncs.c:2883 utils/adt/jsonfuncs.c:3663 +#: utils/adt/jsonfuncs.c:588 utils/adt/jsonfuncs.c:815 +#: utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3935 #, c-format msgid "cannot call %s on an array" msgstr "вызывать %s с массивом нельзя" -#: utils/adt/jsonfuncs.c:636 jsonpath_scan.l:596 +#: utils/adt/jsonfuncs.c:647 jsonpath_scan.l:607 #, c-format msgid "unsupported Unicode escape sequence" msgstr "неподдерживаемая спецпоследовательность Unicode" -#: utils/adt/jsonfuncs.c:713 +#: utils/adt/jsonfuncs.c:724 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "данные JSON, строка %d: %s%s%s" -#: utils/adt/jsonfuncs.c:1875 utils/adt/jsonfuncs.c:1912 +#: utils/adt/jsonfuncs.c:1883 utils/adt/jsonfuncs.c:1920 #, c-format msgid "cannot get array length of a scalar" msgstr "получить длину скаляра нельзя" -#: utils/adt/jsonfuncs.c:1879 utils/adt/jsonfuncs.c:1898 +#: utils/adt/jsonfuncs.c:1887 utils/adt/jsonfuncs.c:1906 #, c-format msgid "cannot get array length of a non-array" msgstr "получить длину массива для не массива нельзя" -#: utils/adt/jsonfuncs.c:1978 +#: utils/adt/jsonfuncs.c:1986 #, c-format msgid "cannot call %s on a non-object" msgstr "вызывать %s с не объектом нельзя" -#: utils/adt/jsonfuncs.c:2166 +#: utils/adt/jsonfuncs.c:2174 #, c-format msgid "cannot deconstruct an array as an object" msgstr "извлечь массив в виде объекта нельзя" -#: utils/adt/jsonfuncs.c:2180 +#: utils/adt/jsonfuncs.c:2188 #, c-format msgid "cannot deconstruct a scalar" msgstr "извлечь скаляр нельзя" -#: utils/adt/jsonfuncs.c:2225 +#: utils/adt/jsonfuncs.c:2233 #, c-format msgid "cannot extract elements from a scalar" msgstr "извлечь элементы из скаляра нельзя" -#: utils/adt/jsonfuncs.c:2229 +#: utils/adt/jsonfuncs.c:2237 #, c-format msgid "cannot extract elements from an object" msgstr "извлечь элементы из объекта нельзя" -#: utils/adt/jsonfuncs.c:2414 utils/adt/jsonfuncs.c:3896 +#: utils/adt/jsonfuncs.c:2424 utils/adt/jsonfuncs.c:4173 #, c-format msgid "cannot call %s on a non-array" msgstr "вызывать %s с не массивом нельзя" -#: utils/adt/jsonfuncs.c:2488 utils/adt/jsonfuncs.c:2493 -#: utils/adt/jsonfuncs.c:2510 utils/adt/jsonfuncs.c:2516 +#: utils/adt/jsonfuncs.c:2515 utils/adt/jsonfuncs.c:2520 +#: utils/adt/jsonfuncs.c:2538 utils/adt/jsonfuncs.c:2544 #, c-format msgid "expected JSON array" msgstr "ожидался массив JSON" -#: utils/adt/jsonfuncs.c:2489 +#: utils/adt/jsonfuncs.c:2516 #, c-format msgid "See the value of key \"%s\"." msgstr "Проверьте значение ключа \"%s\"." -#: utils/adt/jsonfuncs.c:2511 +#: utils/adt/jsonfuncs.c:2539 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "Проверьте элемент массива %s ключа \"%s\"." -#: utils/adt/jsonfuncs.c:2517 +#: utils/adt/jsonfuncs.c:2545 #, c-format msgid "See the array element %s." msgstr "Проверьте элемент массива %s." -#: utils/adt/jsonfuncs.c:2552 +#: utils/adt/jsonfuncs.c:2597 #, c-format msgid "malformed JSON array" msgstr "неправильный массив JSON" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3389 +#: utils/adt/jsonfuncs.c:3647 #, c-format msgid "first argument of %s must be a row type" msgstr "первым аргументом %s должен быть кортеж" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3413 +#: utils/adt/jsonfuncs.c:3671 #, c-format msgid "could not determine row type for result of %s" msgstr "не удалось определить тип строки для результата %s" -#: utils/adt/jsonfuncs.c:3415 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "" "Provide a non-null record argument, or call the function in the FROM clause " @@ -27301,38 +28505,38 @@ msgstr "" "Передайте отличный от NULL аргумент-запись или вызовите эту функцию в " "предложении FROM, используя список определений столбцов." -#: utils/adt/jsonfuncs.c:3785 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4059 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "требуется режим материализации, но он недопустим в этом контексте" -#: utils/adt/jsonfuncs.c:3913 utils/adt/jsonfuncs.c:3997 +#: utils/adt/jsonfuncs.c:4190 utils/adt/jsonfuncs.c:4274 #, c-format msgid "argument of %s must be an array of objects" msgstr "аргументом %s должен быть массив объектов" -#: utils/adt/jsonfuncs.c:3946 +#: utils/adt/jsonfuncs.c:4223 #, c-format msgid "cannot call %s on an object" msgstr "вызывать %s с объектом нельзя" -#: utils/adt/jsonfuncs.c:4380 utils/adt/jsonfuncs.c:4439 -#: utils/adt/jsonfuncs.c:4519 +#: utils/adt/jsonfuncs.c:4656 utils/adt/jsonfuncs.c:4715 +#: utils/adt/jsonfuncs.c:4795 #, c-format msgid "cannot delete from scalar" msgstr "удаление из скаляра невозможно" -#: utils/adt/jsonfuncs.c:4524 +#: utils/adt/jsonfuncs.c:4800 #, c-format msgid "cannot delete from object using integer index" msgstr "удаление из объекта по числовому индексу невозможно" -#: utils/adt/jsonfuncs.c:4592 utils/adt/jsonfuncs.c:4751 +#: utils/adt/jsonfuncs.c:4868 utils/adt/jsonfuncs.c:5027 #, c-format msgid "cannot set path in scalar" msgstr "задать путь в скаляре нельзя" -#: utils/adt/jsonfuncs.c:4633 utils/adt/jsonfuncs.c:4675 +#: utils/adt/jsonfuncs.c:4909 utils/adt/jsonfuncs.c:4951 #, c-format msgid "" "null_value_treatment must be \"delete_key\", \"return_target\", " @@ -27341,12 +28545,12 @@ msgstr "" "значением null_value_treatment должно быть \"delete_key\", " "\"return_target\", \"use_json_null\" или \"raise_exception\"" -#: utils/adt/jsonfuncs.c:4646 +#: utils/adt/jsonfuncs.c:4922 #, c-format msgid "JSON value must not be null" msgstr "значение JSON не может быть NULL" -#: utils/adt/jsonfuncs.c:4647 +#: utils/adt/jsonfuncs.c:4923 #, c-format msgid "" "Exception was raised because null_value_treatment is \"raise_exception\"." @@ -27354,7 +28558,7 @@ msgstr "" "Выдано исключение, так как значением null_value_treatment является " "\"raise_exception\"." -#: utils/adt/jsonfuncs.c:4648 +#: utils/adt/jsonfuncs.c:4924 #, c-format msgid "" "To avoid, either change the null_value_treatment argument or ensure that an " @@ -27363,55 +28567,55 @@ msgstr "" "Чтобы исключения не было, либо измените аргумент null_value_treatment, либо " "не допускайте передачи SQL NULL." -#: utils/adt/jsonfuncs.c:4703 +#: utils/adt/jsonfuncs.c:4979 #, c-format msgid "cannot delete path in scalar" msgstr "удалить путь в скаляре нельзя" -#: utils/adt/jsonfuncs.c:4917 +#: utils/adt/jsonfuncs.c:5193 #, c-format msgid "path element at position %d is null" msgstr "элемент пути в позиции %d равен NULL" -#: utils/adt/jsonfuncs.c:4936 utils/adt/jsonfuncs.c:4967 -#: utils/adt/jsonfuncs.c:5040 +#: utils/adt/jsonfuncs.c:5212 utils/adt/jsonfuncs.c:5243 +#: utils/adt/jsonfuncs.c:5316 #, c-format msgid "cannot replace existing key" msgstr "заменить существующий ключ нельзя" -#: utils/adt/jsonfuncs.c:4937 utils/adt/jsonfuncs.c:4968 +#: utils/adt/jsonfuncs.c:5213 utils/adt/jsonfuncs.c:5244 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "" "Для заданного пути значение ключа должно быть составным объектом, но оно " "оказалось скаляром." -#: utils/adt/jsonfuncs.c:5041 +#: utils/adt/jsonfuncs.c:5317 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "Попробуйте применить функцию jsonb_set для замены значения ключа." -#: utils/adt/jsonfuncs.c:5145 +#: utils/adt/jsonfuncs.c:5421 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "элемент пути в позиции %d - не целочисленный: \"%s\"" -#: utils/adt/jsonfuncs.c:5162 +#: utils/adt/jsonfuncs.c:5438 #, c-format msgid "path element at position %d is out of range: %d" msgstr "элемент пути в позиции %d вне диапазона: %d" -#: utils/adt/jsonfuncs.c:5314 +#: utils/adt/jsonfuncs.c:5590 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "неверный тип флага, допускаются только массивы и скаляры" -#: utils/adt/jsonfuncs.c:5321 +#: utils/adt/jsonfuncs.c:5597 #, c-format msgid "flag array element is not a string" msgstr "элемент массива флагов не является строкой" -#: utils/adt/jsonfuncs.c:5322 utils/adt/jsonfuncs.c:5344 +#: utils/adt/jsonfuncs.c:5598 utils/adt/jsonfuncs.c:5620 #, c-format msgid "" "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and " @@ -27419,197 +28623,313 @@ msgid "" msgstr "" "Допустимые значения: \"string\", \"numeric\", \"boolean\", \"key\" и \"all\"." -#: utils/adt/jsonfuncs.c:5342 +#: utils/adt/jsonfuncs.c:5618 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "неверный флаг в массиве флагов: \"%s\"" -#: utils/adt/jsonpath.c:382 +#: utils/adt/jsonpath.c:389 #, c-format msgid "@ is not allowed in root expressions" msgstr "@ не допускается в корневых выражениях" -#: utils/adt/jsonpath.c:388 +#: utils/adt/jsonpath.c:395 #, c-format msgid "LAST is allowed only in array subscripts" msgstr "LAST принимается только в качестве индекса массива" -#: utils/adt/jsonpath_exec.c:361 +#: utils/adt/jsonpath_exec.c:491 #, c-format msgid "single boolean result is expected" msgstr "ожидался единственный булевский результат" -#: utils/adt/jsonpath_exec.c:557 +#: utils/adt/jsonpath_exec.c:851 #, c-format -msgid "\"vars\" argument is not an object" -msgstr "аргумент \"vars\" не является объектом" +msgid "jsonpath wildcard array accessor can only be applied to an array" +msgstr "" +"выражение обращения по звёздочке в jsonpath может применяться только к " +"массиву" -#: utils/adt/jsonpath_exec.c:558 +#: utils/adt/jsonpath_exec.c:874 #, c-format -msgid "" -"Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgid "jsonpath wildcard member accessor can only be applied to an object" msgstr "" -"Параметры jsonpath должны передаваться в виде пар ключ-значение в объекте " -"\"vars\"." +"выражение обращения по звёздочке в jsonpath может применяться только к " +"объекту" + +#: utils/adt/jsonpath_exec.c:923 +#, c-format +msgid "jsonpath array subscript is out of bounds" +msgstr "индекс массива в jsonpath вне диапазона" + +#: utils/adt/jsonpath_exec.c:980 +#, c-format +msgid "jsonpath array accessor can only be applied to an array" +msgstr "" +"выражение обращения к массиву в jsonpath может применяться только к массиву" -#: utils/adt/jsonpath_exec.c:675 +#: utils/adt/jsonpath_exec.c:1044 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "JSON-объект не содержит ключ \"%s\"" -#: utils/adt/jsonpath_exec.c:687 +#: utils/adt/jsonpath_exec.c:1056 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "" "выражение обращения к члену в jsonpath может применяться только к объекту" -#: utils/adt/jsonpath_exec.c:716 +# skip-rule: space-before-period +#: utils/adt/jsonpath_exec.c:1114 #, c-format -msgid "jsonpath wildcard array accessor can only be applied to an array" +msgid "jsonpath item method .%s() can only be applied to an array" +msgstr "метод .%s() в jsonpath может применяться только к массиву" + +#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 +#, c-format +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type double " +"precision" msgstr "" -"выражение обращения по звёздочке в jsonpath может применяться только к " -"массиву" +"аргумент \"%s\" метода элемента jsonpath .%s() некорректен для типа double " +"precision" -#: utils/adt/jsonpath_exec.c:764 +#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 +#: utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 #, c-format -msgid "jsonpath array subscript is out of bounds" -msgstr "индекс массива в jsonpath вне диапазона" +msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" +msgstr "метод элемента jsonpath .%s() не принимает значения NaN и Infinity" + +# skip-rule: space-before-period +#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 +#: utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 +#, c-format +msgid "" +"jsonpath item method .%s() can only be applied to a string or numeric value" +msgstr "" +"метод .%s() в jsonpath может применяться только к строковому или числовому " +"значению" -#: utils/adt/jsonpath_exec.c:821 +#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 #, c-format -msgid "jsonpath array accessor can only be applied to an array" +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" msgstr "" -"выражение обращения к массиву в jsonpath может применяться только к массиву" +"аргумент \"%s\" метода элемента jsonpath .%s() не подходит для типа bigint" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 #, c-format -msgid "jsonpath wildcard member accessor can only be applied to an object" +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" msgstr "" -"выражение обращения по звёздочке в jsonpath может применяться только к " -"объекту" +"аргумент \"%s\" метода элемента jsonpath .%s() не подходит для типа boolean" # skip-rule: space-before-period -#: utils/adt/jsonpath_exec.c:1007 +#: utils/adt/jsonpath_exec.c:1386 #, c-format -msgid "jsonpath item method .%s() can only be applied to an array" -msgstr "метод .%s() в jsonpath может применяться только к массиву" +msgid "" +"jsonpath item method .%s() can only be applied to a boolean, string, or " +"numeric value" +msgstr "" +"метод .%s() в jsonpath может применяться только к булевскому, строковому или " +"числовому значению" + +#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 +#, c-format +msgid "" +"argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" +msgstr "" +"аргумент \"%s\" метода элемента jsonpath .%s() не подходит для типа numeric" -#: utils/adt/jsonpath_exec.c:1060 +#: utils/adt/jsonpath_exec.c:1487 #, c-format msgid "" -"numeric argument of jsonpath item method .%s() is out of range for type " -"double precision" +"precision of jsonpath item method .%s() is out of range for type integer" +msgstr "точность в аргументе метода jsonpath .%s() вне диапазона типа integer" + +#: utils/adt/jsonpath_exec.c:1501 +#, c-format +msgid "scale of jsonpath item method .%s() is out of range for type integer" msgstr "" -"числовой аргумент метода элемента jsonpath .%s() вне диапазона для типа " -"double precision" +"масштаб в аргументе метода элемента jsonpath .%s() вне диапазона типа integer" -#: utils/adt/jsonpath_exec.c:1081 +#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 #, c-format msgid "" -"string argument of jsonpath item method .%s() is not a valid representation " -"of a double precision number" +"argument \"%s\" of jsonpath item method .%s() is invalid for type integer" msgstr "" -"строковый аргумент метода элемента jsonpath .%s() не является представлением " -"значения double precision" +"аргумент \"%s\" метода элемента jsonpath .%s() не подходит для типа integer" # skip-rule: space-before-period -#: utils/adt/jsonpath_exec.c:1094 +#: utils/adt/jsonpath_exec.c:1648 #, c-format msgid "" -"jsonpath item method .%s() can only be applied to a string or numeric value" +"jsonpath item method .%s() can only be applied to a boolean, string, " +"numeric, or datetime value" msgstr "" -"метод .%s() в jsonpath может применяться только к строковому или числовому " -"значению" +"метод .%s() в jsonpath может применяться только к булевскому, строковому, " +"числовому значению или к дате/времени" -#: utils/adt/jsonpath_exec.c:1587 +#: utils/adt/jsonpath_exec.c:2137 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "" "левый операнд оператора %s в jsonpath не является одним числовым значением" -#: utils/adt/jsonpath_exec.c:1594 +#: utils/adt/jsonpath_exec.c:2144 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "" "правый операнд оператора %s в jsonpath не является одним числовым значением" -#: utils/adt/jsonpath_exec.c:1662 +#: utils/adt/jsonpath_exec.c:2212 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "" "операнд унарного оператора %s в jsonpath не является числовым значением" # skip-rule: space-before-period -#: utils/adt/jsonpath_exec.c:1761 +#: utils/adt/jsonpath_exec.c:2311 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "метод .%s() в jsonpath может применяться только к числовому значению" # skip-rule: space-before-period -#: utils/adt/jsonpath_exec.c:1801 +#: utils/adt/jsonpath_exec.c:2357 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "метод .%s() в jsonpath может применяться только к строке" -#: utils/adt/jsonpath_exec.c:1904 +#: utils/adt/jsonpath_exec.c:2450 +#, c-format +msgid "" +"time precision of jsonpath item method .%s() is out of range for type integer" +msgstr "" +"точность времени в аргументе метода jsonpath .%s() вне диапазона типа integer" + +#: utils/adt/jsonpath_exec.c:2484 utils/adt/jsonpath_exec.c:2490 +#: utils/adt/jsonpath_exec.c:2517 utils/adt/jsonpath_exec.c:2545 +#: utils/adt/jsonpath_exec.c:2598 utils/adt/jsonpath_exec.c:2649 +#: utils/adt/jsonpath_exec.c:2720 #, c-format -msgid "datetime format is not recognized: \"%s\"" -msgstr "формат datetime не распознан: \"%s\"" +msgid "%s format is not recognized: \"%s\"" +msgstr "формат %s не распознан: \"%s\"" -#: utils/adt/jsonpath_exec.c:1906 +#: utils/adt/jsonpath_exec.c:2486 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "" "Воспользуйтесь аргументом datetime для указания формата входных данных." +#: utils/adt/jsonpath_exec.c:2679 utils/adt/jsonpath_exec.c:2760 +#, c-format +msgid "time precision of jsonpath item method .%s() is invalid" +msgstr "точность времени в аргументе метода jsonpath .%s() некорректная" + # skip-rule: space-before-period -#: utils/adt/jsonpath_exec.c:1974 +#: utils/adt/jsonpath_exec.c:2840 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "метод .%s() в jsonpath может применяться только к объекту" -#: utils/adt/jsonpath_exec.c:2156 +#: utils/adt/jsonpath_exec.c:3124 +#, c-format +msgid "could not convert value of type %s to jsonpath" +msgstr "преобразовать значение типа %s в jsonpath не удалось" + +#: utils/adt/jsonpath_exec.c:3158 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "не удалось найти в jsonpath переменную \"%s\"" -#: utils/adt/jsonpath_exec.c:2420 +#: utils/adt/jsonpath_exec.c:3211 +#, c-format +msgid "\"vars\" argument is not an object" +msgstr "аргумент \"vars\" не является объектом" + +#: utils/adt/jsonpath_exec.c:3212 +#, c-format +msgid "" +"Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgstr "" +"Параметры jsonpath должны передаваться в виде пар ключ-значение в объекте " +"\"vars\"." + +#: utils/adt/jsonpath_exec.c:3475 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "индекс элемента в jsonpath не является одним числовым значением" -#: utils/adt/jsonpath_exec.c:2432 +#: utils/adt/jsonpath_exec.c:3487 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "индекс массива в jsonpath вне целочисленного диапазона" -#: utils/adt/jsonpath_exec.c:2609 +#: utils/adt/jsonpath_exec.c:3671 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "значение %s нельзя преобразовать в %s без сведений о часовом поясе" -#: utils/adt/jsonpath_exec.c:2611 +#: utils/adt/jsonpath_exec.c:3673 #, c-format msgid "Use *_tz() function for time zone support." msgstr "Для передачи часового пояса используйте функцию *_tz()." +#: utils/adt/jsonpath_exec.c:3981 +#, c-format +msgid "" +"JSON path expression for column \"%s\" must return single item when no " +"wrapper is requested" +msgstr "" +"выражение пути JSON для столбца \"%s\" в отсутствие обёртки должно " +"возвращать одиночный элемент" + +#: utils/adt/jsonpath_exec.c:3983 utils/adt/jsonpath_exec.c:3988 +#, c-format +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." +msgstr "" +"Используйте предложение WITH WRAPPER, чтобы обернуть элементы SQL/JSON в " +"массив." + +#: utils/adt/jsonpath_exec.c:3987 +#, c-format +msgid "" +"JSON path expression in JSON_QUERY must return single item when no wrapper " +"is requested" +msgstr "" +"выражение пути JSON в JSON_QUERY в отсутствие обёртки должно возвращать " +"одиночный элемент" + +#: utils/adt/jsonpath_exec.c:4045 utils/adt/jsonpath_exec.c:4069 +#, c-format +msgid "JSON path expression for column \"%s\" must return single scalar item" +msgstr "" +"выражение пути JSON для столбца \"%s\" должно возвращать один скалярный " +"элемент" + +#: utils/adt/jsonpath_exec.c:4050 utils/adt/jsonpath_exec.c:4074 +#, c-format +msgid "JSON path expression in JSON_VALUE must return single scalar item" +msgstr "" +"выражение пути JSON в JSON_VALUE должно возвращать один скалярный элемент" + # well-spelled: симв #: utils/adt/levenshtein.c:132 #, c-format msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "длина аргумента levenshtein() превышает максимум (%d симв.)" -#: utils/adt/like.c:161 +#: utils/adt/like.c:159 #, c-format msgid "nondeterministic collations are not supported for LIKE" msgstr "недетерминированные правила сортировки не поддерживаются для LIKE" -#: utils/adt/like.c:190 utils/adt/like_support.c:1024 +#: utils/adt/like.c:188 utils/adt/like_support.c:1023 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "не удалось определить, какой порядок сортировки использовать для ILIKE" -#: utils/adt/like.c:202 +#: utils/adt/like.c:200 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "недетерминированные правила сортировки не поддерживаются для ILIKE" @@ -27619,22 +28939,22 @@ msgstr "недетерминированные правила сортировк msgid "LIKE pattern must not end with escape character" msgstr "шаблон LIKE не должен заканчиваться защитным символом" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "неверный защитный символ" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:802 +#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "Защитный символ должен быть пустым или состоять из одного байта." -#: utils/adt/like_support.c:1014 +#: utils/adt/like_support.c:1013 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "регистронезависимое сравнение не поддерживается для типа bytea" -#: utils/adt/like_support.c:1115 +#: utils/adt/like_support.c:1114 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "сравнение с регулярными выражениями не поддерживается для типа bytea" @@ -27644,12 +28964,12 @@ msgstr "сравнение с регулярными выражениями не msgid "invalid octet value in \"macaddr\" value: \"%s\"" msgstr "неверный октет в значении типа macaddr: \"%s\"" -#: utils/adt/mac8.c:554 +#: utils/adt/mac8.c:555 #, c-format msgid "macaddr8 data out of range to convert to macaddr" msgstr "значение в macaddr8 не допускает преобразование в macaddr" -#: utils/adt/mac8.c:555 +#: utils/adt/mac8.c:556 #, c-format msgid "" "Only addresses that have FF and FE as values in the 4th and 5th bytes from " @@ -27659,7 +28979,7 @@ msgstr "" "Преобразование из macaddr8 в macaddr возможно только для адресов, содержащих " "FF и FE в 4-ом и 5-ом байтах слева, например xx:xx:xx:ff:fe:xx:xx:xx." -#: utils/adt/mcxtfuncs.c:182 +#: utils/adt/mcxtfuncs.c:173 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %d не относится к серверному процессу PostgreSQL" @@ -27698,70 +29018,70 @@ msgstr "может быть открытой меткой" msgid "requires AS" msgstr "требует AS" -#: utils/adt/misc.c:853 utils/adt/misc.c:867 utils/adt/misc.c:906 -#: utils/adt/misc.c:912 utils/adt/misc.c:918 utils/adt/misc.c:941 +#: utils/adt/misc.c:897 utils/adt/misc.c:911 utils/adt/misc.c:950 +#: utils/adt/misc.c:956 utils/adt/misc.c:962 utils/adt/misc.c:985 #, c-format msgid "string is not a valid identifier: \"%s\"" msgstr "строка не является допустимым идентификатором: \"%s\"" -#: utils/adt/misc.c:855 +#: utils/adt/misc.c:899 #, c-format msgid "String has unclosed double quotes." msgstr "В строке не закрыты кавычки." -#: utils/adt/misc.c:869 +#: utils/adt/misc.c:913 #, c-format msgid "Quoted identifier must not be empty." msgstr "Идентификатор в кавычках не может быть пустым." -#: utils/adt/misc.c:908 +#: utils/adt/misc.c:952 #, c-format msgid "No valid identifier before \".\"." msgstr "Перед \".\" нет допустимого идентификатора." -#: utils/adt/misc.c:914 +#: utils/adt/misc.c:958 #, c-format msgid "No valid identifier after \".\"." msgstr "После \".\" нет допустимого идентификатора." -#: utils/adt/misc.c:974 +#: utils/adt/misc.c:1018 #, c-format msgid "log format \"%s\" is not supported" msgstr "формат журнала \"%s\" не поддерживается" -#: utils/adt/misc.c:975 +#: utils/adt/misc.c:1019 #, c-format msgid "The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\"." msgstr "Поддерживаются форматы журналов \"stderr\", \"csvlog\" и \"jsonlog\"." -#: utils/adt/multirangetypes.c:151 utils/adt/multirangetypes.c:164 -#: utils/adt/multirangetypes.c:193 utils/adt/multirangetypes.c:267 -#: utils/adt/multirangetypes.c:291 +#: utils/adt/multirangetypes.c:150 utils/adt/multirangetypes.c:163 +#: utils/adt/multirangetypes.c:192 utils/adt/multirangetypes.c:266 +#: utils/adt/multirangetypes.c:290 #, c-format msgid "malformed multirange literal: \"%s\"" msgstr "ошибочный литерал мультидиапазона: \"%s\"" -#: utils/adt/multirangetypes.c:153 +#: utils/adt/multirangetypes.c:152 #, c-format msgid "Missing left brace." msgstr "Отсутствует левая фигурная скобка." -#: utils/adt/multirangetypes.c:195 +#: utils/adt/multirangetypes.c:194 #, c-format msgid "Expected range start." msgstr "Ожидалось начало диапазона." -#: utils/adt/multirangetypes.c:269 +#: utils/adt/multirangetypes.c:268 #, c-format msgid "Expected comma or end of multirange." msgstr "Ожидалась запятая или конец мультидиапазона." -#: utils/adt/multirangetypes.c:982 +#: utils/adt/multirangetypes.c:981 #, c-format msgid "multiranges cannot be constructed from multidimensional arrays" msgstr "мультидиапазоны нельзя получить из массивов мультидиапазонов" -#: utils/adt/multirangetypes.c:1008 +#: utils/adt/multirangetypes.c:1007 #, c-format msgid "multirange values cannot contain null members" msgstr "мультидиапазоны не могут содержать элементы NULL" @@ -27840,102 +29160,122 @@ msgstr "результат вне диапазона" msgid "cannot subtract inet values of different sizes" msgstr "нельзя вычитать значения inet разного размера" -#: utils/adt/numeric.c:785 utils/adt/numeric.c:3643 utils/adt/numeric.c:7131 -#: utils/adt/numeric.c:7334 utils/adt/numeric.c:7806 utils/adt/numeric.c:10501 -#: utils/adt/numeric.c:10975 utils/adt/numeric.c:11069 -#: utils/adt/numeric.c:11203 +#: utils/adt/numeric.c:793 utils/adt/numeric.c:3659 utils/adt/numeric.c:7216 +#: utils/adt/numeric.c:7419 utils/adt/numeric.c:7891 utils/adt/numeric.c:10586 +#: utils/adt/numeric.c:11061 utils/adt/numeric.c:11155 +#: utils/adt/numeric.c:11290 #, c-format msgid "value overflows numeric format" msgstr "значение переполняет формат numeric" -#: utils/adt/numeric.c:1098 +#: utils/adt/numeric.c:1106 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "неверный знак во внешнем значении \"numeric\"" -#: utils/adt/numeric.c:1104 +#: utils/adt/numeric.c:1112 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "неверный порядок числа во внешнем значении \"numeric\"" -#: utils/adt/numeric.c:1113 +#: utils/adt/numeric.c:1121 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "неверная цифра во внешнем значении \"numeric\"" -#: utils/adt/numeric.c:1328 utils/adt/numeric.c:1342 +#: utils/adt/numeric.c:1336 utils/adt/numeric.c:1350 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "точность NUMERIC %d должна быть между 1 и %d" -#: utils/adt/numeric.c:1333 +#: utils/adt/numeric.c:1341 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "порядок NUMERIC %d должен быть между %d и %d" -#: utils/adt/numeric.c:1351 +#: utils/adt/numeric.c:1359 #, c-format msgid "invalid NUMERIC type modifier" msgstr "неверный модификатор типа NUMERIC" -#: utils/adt/numeric.c:1709 +#: utils/adt/numeric.c:1725 #, c-format msgid "start value cannot be NaN" msgstr "начальное значение не может быть NaN" -#: utils/adt/numeric.c:1713 +#: utils/adt/numeric.c:1729 #, c-format msgid "start value cannot be infinity" msgstr "начальное значение не может быть бесконечностью" -#: utils/adt/numeric.c:1720 +#: utils/adt/numeric.c:1736 #, c-format msgid "stop value cannot be NaN" msgstr "конечное значение не может быть NaN" -#: utils/adt/numeric.c:1724 +#: utils/adt/numeric.c:1740 #, c-format msgid "stop value cannot be infinity" msgstr "конечное значение не может быть бесконечностью" -#: utils/adt/numeric.c:1737 +#: utils/adt/numeric.c:1753 #, c-format msgid "step size cannot be NaN" msgstr "размер шага не может быть NaN" -#: utils/adt/numeric.c:1741 +#: utils/adt/numeric.c:1757 #, c-format msgid "step size cannot be infinity" msgstr "размер шага не может быть бесконечностью" -#: utils/adt/numeric.c:3633 +#: utils/adt/numeric.c:3649 #, c-format msgid "factorial of a negative number is undefined" msgstr "факториал отрицательного числа даёт неопределённость" -#: utils/adt/numeric.c:4366 utils/adt/numeric.c:4446 utils/adt/numeric.c:4487 -#: utils/adt/numeric.c:4683 +#: utils/adt/numeric.c:4256 +#, c-format +msgid "lower bound cannot be NaN" +msgstr "нижняя граница не может быть NaN" + +#: utils/adt/numeric.c:4260 +#, c-format +msgid "lower bound cannot be infinity" +msgstr "нижняя граница не может быть бесконечностью" + +#: utils/adt/numeric.c:4267 +#, c-format +msgid "upper bound cannot be NaN" +msgstr "верхняя граница не может быть NaN" + +#: utils/adt/numeric.c:4271 +#, c-format +msgid "upper bound cannot be infinity" +msgstr "верхняя граница не может быть бесконечностью" + +#: utils/adt/numeric.c:4432 utils/adt/numeric.c:4520 utils/adt/numeric.c:4580 +#: utils/adt/numeric.c:4776 #, c-format msgid "cannot convert NaN to %s" msgstr "нельзя преобразовать NaN в %s" -#: utils/adt/numeric.c:4370 utils/adt/numeric.c:4450 utils/adt/numeric.c:4491 -#: utils/adt/numeric.c:4687 +#: utils/adt/numeric.c:4436 utils/adt/numeric.c:4524 utils/adt/numeric.c:4584 +#: utils/adt/numeric.c:4780 #, c-format msgid "cannot convert infinity to %s" msgstr "нельзя представить бесконечность в %s" -#: utils/adt/numeric.c:4696 +#: utils/adt/numeric.c:4789 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn вне диапазона" -#: utils/adt/numeric.c:7896 utils/adt/numeric.c:7947 +#: utils/adt/numeric.c:7981 utils/adt/numeric.c:8032 #, c-format msgid "numeric field overflow" msgstr "переполнение поля numeric" -#: utils/adt/numeric.c:7897 +#: utils/adt/numeric.c:7982 #, c-format msgid "" "A field with precision %d, scale %d must round to an absolute value less " @@ -27944,13 +29284,19 @@ msgstr "" "Поле с точностью %d, порядком %d должно округляться до абсолютного значения " "меньше чем %s%d." -#: utils/adt/numeric.c:7948 +#: utils/adt/numeric.c:8033 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "" "Поле с точностью %d, порядком %d не может содержать значение бесконечности." -#: utils/adt/oid.c:216 +#: utils/adt/numeric.c:11359 utils/adt/pseudorandomfuncs.c:135 +#: utils/adt/pseudorandomfuncs.c:159 +#, c-format +msgid "lower bound must be less than or equal to upper bound" +msgstr "нижняя граница должна быть меньше или равна верхней" + +#: utils/adt/oid.c:217 #, c-format msgid "invalid oidvector data" msgstr "неверные данные oidvector" @@ -27980,37 +29326,42 @@ msgstr "код запрошенного символа слишком велик msgid "requested character not valid for encoding: %u" msgstr "запрошенный символ не подходит для кодировки: %u" -#: utils/adt/orderedsetaggs.c:448 utils/adt/orderedsetaggs.c:553 -#: utils/adt/orderedsetaggs.c:693 +#: utils/adt/orderedsetaggs.c:446 utils/adt/orderedsetaggs.c:551 +#: utils/adt/orderedsetaggs.c:691 #, c-format msgid "percentile value %g is not between 0 and 1" msgstr "значение перцентиля %g лежит не в диапазоне 0..1" -#: utils/adt/pg_locale.c:1410 +#: utils/adt/pg_locale.c:326 utils/adt/pg_locale.c:358 +#, c-format +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "имя локали \"%s\" содержит не-ASCII символы" + +#: utils/adt/pg_locale.c:1507 #, c-format msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" msgstr "" "не удалось открыть сортировщик для локали \"%s\" с правилами \"%s\": %s" -#: utils/adt/pg_locale.c:1421 utils/adt/pg_locale.c:2831 -#: utils/adt/pg_locale.c:2904 +#: utils/adt/pg_locale.c:1518 utils/adt/pg_locale.c:2992 +#: utils/adt/pg_locale.c:3065 #, c-format msgid "ICU is not supported in this build" msgstr "ICU не поддерживается в данной сборке" -#: utils/adt/pg_locale.c:1450 +#: utils/adt/pg_locale.c:1546 #, c-format msgid "could not create locale \"%s\": %m" msgstr "не удалось создать локаль \"%s\": %m" -#: utils/adt/pg_locale.c:1453 +#: utils/adt/pg_locale.c:1549 #, c-format msgid "" "The operating system could not find any locale data for the locale name " "\"%s\"." msgstr "Операционная система не может найти данные локали с именем \"%s\"." -#: utils/adt/pg_locale.c:1568 +#: utils/adt/pg_locale.c:1670 #, c-format msgid "" "collations with different collate and ctype values are not supported on this " @@ -28019,22 +29370,17 @@ msgstr "" "правила сортировки с разными значениями collate и ctype не поддерживаются на " "этой платформе" -#: utils/adt/pg_locale.c:1577 -#, c-format -msgid "collation provider LIBC is not supported on this platform" -msgstr "провайдер правил сортировки LIBC не поддерживается на этой платформе" - -#: utils/adt/pg_locale.c:1618 +#: utils/adt/pg_locale.c:1717 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "для правила сортировки \"%s\", лишённого версии, была записана версия" -#: utils/adt/pg_locale.c:1624 +#: utils/adt/pg_locale.c:1723 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "несовпадение версии для правила сортировки \"%s\"" -#: utils/adt/pg_locale.c:1626 +#: utils/adt/pg_locale.c:1725 #, c-format msgid "" "The collation in the database was created using version %s, but the " @@ -28043,7 +29389,7 @@ msgstr "" "Правило сортировки в базе данных было создано с версией %s, но операционная " "система предоставляет версию %s." -#: utils/adt/pg_locale.c:1629 +#: utils/adt/pg_locale.c:1728 #, c-format msgid "" "Rebuild all objects affected by this collation and run ALTER COLLATION %s " @@ -28053,92 +29399,98 @@ msgstr "" "ALTER COLLATION %s REFRESH VERSION либо соберите PostgreSQL с правильной " "версией библиотеки." -#: utils/adt/pg_locale.c:1695 +#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:2556 +#: utils/adt/pg_locale.c:2581 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "неверное имя локали \"%s\" для встроенного провайдера" + +#: utils/adt/pg_locale.c:1814 #, c-format msgid "could not load locale \"%s\"" msgstr "не удалось загрузить локаль \"%s\"" -#: utils/adt/pg_locale.c:1720 +#: utils/adt/pg_locale.c:1839 #, c-format msgid "could not get collation version for locale \"%s\": error code %lu" msgstr "" "не удалось получить версию правила сортировки для локали \"%s\" (код ошибки: " "%lu)" -#: utils/adt/pg_locale.c:1776 utils/adt/pg_locale.c:1789 +#: utils/adt/pg_locale.c:1895 utils/adt/pg_locale.c:1908 #, c-format msgid "could not convert string to UTF-16: error code %lu" msgstr "не удалось преобразовать строку в UTF-16 (код ошибки: %lu)" -#: utils/adt/pg_locale.c:1803 +#: utils/adt/pg_locale.c:1920 #, c-format msgid "could not compare Unicode strings: %m" msgstr "не удалось сравнить строки в Unicode: %m" -#: utils/adt/pg_locale.c:1984 +#: utils/adt/pg_locale.c:2094 #, c-format msgid "collation failed: %s" msgstr "ошибка в библиотеке сортировки: %s" -#: utils/adt/pg_locale.c:2205 utils/adt/pg_locale.c:2237 +#: utils/adt/pg_locale.c:2313 utils/adt/pg_locale.c:2345 #, c-format msgid "sort key generation failed: %s" msgstr "не удалось сгенерировать ключ сортировки: %s" -#: utils/adt/pg_locale.c:2474 +#: utils/adt/pg_locale.c:2635 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "не удалось определить язык для локали \"%s\": %s" -#: utils/adt/pg_locale.c:2495 utils/adt/pg_locale.c:2511 +#: utils/adt/pg_locale.c:2656 utils/adt/pg_locale.c:2672 #, c-format msgid "could not open collator for locale \"%s\": %s" msgstr "не удалось открыть сортировщик для локали \"%s\": %s" -#: utils/adt/pg_locale.c:2536 +#: utils/adt/pg_locale.c:2697 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "ICU не поддерживает кодировку \"%s\"" -#: utils/adt/pg_locale.c:2543 +#: utils/adt/pg_locale.c:2704 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "не удалось открыть преобразователь ICU для кодировки \"%s\": %s" -#: utils/adt/pg_locale.c:2561 utils/adt/pg_locale.c:2580 -#: utils/adt/pg_locale.c:2636 utils/adt/pg_locale.c:2647 +#: utils/adt/pg_locale.c:2722 utils/adt/pg_locale.c:2741 +#: utils/adt/pg_locale.c:2797 utils/adt/pg_locale.c:2808 #, c-format msgid "%s failed: %s" msgstr "ошибка %s: %s" -#: utils/adt/pg_locale.c:2822 +#: utils/adt/pg_locale.c:2983 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "не удалось получить из названия локали \"%s\" метку языка: %s" -#: utils/adt/pg_locale.c:2863 +#: utils/adt/pg_locale.c:3024 #, c-format msgid "could not get language from ICU locale \"%s\": %s" msgstr "не удалось определить язык для локали ICU \"%s\": %s" -#: utils/adt/pg_locale.c:2865 utils/adt/pg_locale.c:2894 +#: utils/adt/pg_locale.c:3026 utils/adt/pg_locale.c:3055 #, c-format msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." msgstr "" "Чтобы отключить проверку локалей ICU, установите для параметра \"%s\" " "значение \"%s\"." -#: utils/adt/pg_locale.c:2892 +#: utils/adt/pg_locale.c:3053 #, c-format msgid "ICU locale \"%s\" has unknown language \"%s\"" msgstr "для локали ICU \"%s\" получен неизвестный язык \"%s\"" -#: utils/adt/pg_locale.c:3073 +#: utils/adt/pg_locale.c:3204 #, c-format msgid "invalid multibyte character for locale" msgstr "неверный многобайтный символ для локали" -#: utils/adt/pg_locale.c:3074 +#: utils/adt/pg_locale.c:3205 #, c-format msgid "" "The server's LC_CTYPE locale is probably incompatible with the database " @@ -28146,137 +29498,142 @@ msgid "" msgstr "" "Параметр локали сервера LC_CTYPE, возможно, несовместим с кодировкой БД." -#: utils/adt/pg_lsn.c:263 +#: utils/adt/pg_lsn.c:262 #, c-format msgid "cannot add NaN to pg_lsn" msgstr "нельзя добавить NaN к pg_lsn" -#: utils/adt/pg_lsn.c:297 +#: utils/adt/pg_lsn.c:296 #, c-format msgid "cannot subtract NaN from pg_lsn" msgstr "нельзя вычесть NaN из pg_lsn" -#: utils/adt/pg_upgrade_support.c:29 +#: utils/adt/pg_upgrade_support.c:39 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "" "функцию можно вызывать только когда сервер в режиме двоичного обновления" -#: utils/adt/pgstatfuncs.c:254 +#: utils/adt/pgstatfuncs.c:252 #, c-format msgid "invalid command name: \"%s\"" msgstr "неверное имя команды: \"%s\"" -#: utils/adt/pgstatfuncs.c:1774 +#: utils/adt/pgstatfuncs.c:1739 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "запрошен сброс неизвестного счётчика: \"%s\"" -#: utils/adt/pgstatfuncs.c:1775 +#: utils/adt/pgstatfuncs.c:1740 #, c-format msgid "" -"Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or " -"\"wal\"." +"Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", " +"\"recovery_prefetch\", \"slru\", or \"wal\"." msgstr "" "Допустимые счётчики: \"archiver\", \"bgwriter\", \"io\", " -"\"recovery_prefetch\" и \"wal\"." +"\"recovery_prefetch\", \"slru\" и \"wal\"." -#: utils/adt/pgstatfuncs.c:1857 +#: utils/adt/pgstatfuncs.c:1822 #, c-format msgid "invalid subscription OID %u" msgstr "неверный OID подписки %u" -#: utils/adt/pseudotypes.c:58 utils/adt/pseudotypes.c:92 +#: utils/adt/pseudorandomfuncs.c:69 +#, c-format +msgid "setseed parameter %g is out of allowed range [-1,1]" +msgstr "параметр setseed %g вне допустимого диапазона [-1,1]" + +#: utils/adt/pseudotypes.c:55 utils/adt/pseudotypes.c:89 #, c-format msgid "cannot display a value of type %s" msgstr "значение типа %s нельзя вывести" -#: utils/adt/pseudotypes.c:310 +#: utils/adt/pseudotypes.c:307 #, c-format msgid "cannot accept a value of a shell type" msgstr "значение типа shell нельзя ввести" -#: utils/adt/pseudotypes.c:320 +#: utils/adt/pseudotypes.c:317 #, c-format msgid "cannot display a value of a shell type" msgstr "значение типа shell нельзя вывести" -#: utils/adt/rangetypes.c:415 +#: utils/adt/rangetypes.c:422 #, c-format msgid "range constructor flags argument must not be null" msgstr "аргумент flags конструктора диапазона не может быть NULL" -#: utils/adt/rangetypes.c:1014 +#: utils/adt/rangetypes.c:1021 #, c-format msgid "result of range difference would not be contiguous" msgstr "результат вычитания диапазонов будет не непрерывным" -#: utils/adt/rangetypes.c:1075 +#: utils/adt/rangetypes.c:1082 #, c-format msgid "result of range union would not be contiguous" msgstr "результат объединения диапазонов будет не непрерывным" -#: utils/adt/rangetypes.c:1750 +#: utils/adt/rangetypes.c:1757 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "нижняя граница диапазона должна быть меньше или равна верхней" -#: utils/adt/rangetypes.c:2197 utils/adt/rangetypes.c:2210 -#: utils/adt/rangetypes.c:2224 +#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 +#: utils/adt/rangetypes.c:2283 #, c-format msgid "invalid range bound flags" msgstr "неверные флаги границ диапазона" -#: utils/adt/rangetypes.c:2198 utils/adt/rangetypes.c:2211 -#: utils/adt/rangetypes.c:2225 +#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 +#: utils/adt/rangetypes.c:2284 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "Допустимые значения: \"[]\", \"[)\", \"(]\" и \"()\"." -#: utils/adt/rangetypes.c:2293 utils/adt/rangetypes.c:2310 -#: utils/adt/rangetypes.c:2325 utils/adt/rangetypes.c:2345 -#: utils/adt/rangetypes.c:2356 utils/adt/rangetypes.c:2403 -#: utils/adt/rangetypes.c:2411 +#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 +#: utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 +#: utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "malformed range literal: \"%s\"" msgstr "ошибочный литерал диапазона: \"%s\"" -#: utils/adt/rangetypes.c:2295 +#: utils/adt/rangetypes.c:2354 #, c-format msgid "Junk after \"empty\" key word." msgstr "Мусор после ключевого слова \"empty\"." -#: utils/adt/rangetypes.c:2312 +#: utils/adt/rangetypes.c:2371 #, c-format msgid "Missing left parenthesis or bracket." msgstr "Отсутствует левая скобка (круглая или квадратная)." -#: utils/adt/rangetypes.c:2327 +#: utils/adt/rangetypes.c:2386 #, c-format msgid "Missing comma after lower bound." msgstr "Отсутствует запятая после нижней границы." -#: utils/adt/rangetypes.c:2347 +#: utils/adt/rangetypes.c:2406 #, c-format msgid "Too many commas." msgstr "Слишком много запятых." -#: utils/adt/rangetypes.c:2358 +#: utils/adt/rangetypes.c:2417 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "Мусор после правой скобки." -#: utils/adt/regexp.c:305 utils/adt/regexp.c:1997 utils/adt/varlena.c:4270 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 #, c-format msgid "regular expression failed: %s" msgstr "ошибка в регулярном выражении: %s" -#: utils/adt/regexp.c:446 utils/adt/regexp.c:681 +#: utils/adt/regexp.c:445 utils/adt/regexp.c:680 #, c-format msgid "invalid regular expression option: \"%.*s\"" msgstr "неверный параметр регулярного выражения: \"%.*s\"" -#: utils/adt/regexp.c:683 +#: utils/adt/regexp.c:682 #, c-format msgid "" "If you meant to use regexp_replace() with a start parameter, cast the fourth " @@ -28285,15 +29642,15 @@ msgstr "" "Если вы хотите вызвать regexp_replace() с параметром start, явно приведите " "четвёртый аргумент к целочисленному типу." -#: utils/adt/regexp.c:717 utils/adt/regexp.c:726 utils/adt/regexp.c:1083 -#: utils/adt/regexp.c:1147 utils/adt/regexp.c:1156 utils/adt/regexp.c:1165 -#: utils/adt/regexp.c:1174 utils/adt/regexp.c:1854 utils/adt/regexp.c:1863 -#: utils/adt/regexp.c:1872 utils/misc/guc.c:6627 utils/misc/guc.c:6661 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 +#: utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 +#: utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 +#: utils/adt/regexp.c:1871 utils/misc/guc.c:6820 utils/misc/guc.c:6854 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "неверное значение параметра \"%s\": %d" -#: utils/adt/regexp.c:937 +#: utils/adt/regexp.c:936 #, c-format msgid "" "SQL regular expression may not contain more than two escape-double-quote " @@ -28303,19 +29660,19 @@ msgstr "" "(экранированных кавычек)" #. translator: %s is a SQL function name -#: utils/adt/regexp.c:1094 utils/adt/regexp.c:1185 utils/adt/regexp.c:1272 -#: utils/adt/regexp.c:1311 utils/adt/regexp.c:1699 utils/adt/regexp.c:1754 -#: utils/adt/regexp.c:1883 +#: utils/adt/regexp.c:1093 utils/adt/regexp.c:1184 utils/adt/regexp.c:1271 +#: utils/adt/regexp.c:1310 utils/adt/regexp.c:1698 utils/adt/regexp.c:1753 +#: utils/adt/regexp.c:1882 #, c-format msgid "%s does not support the \"global\" option" msgstr "%s не поддерживает режим \"global\"" -#: utils/adt/regexp.c:1313 +#: utils/adt/regexp.c:1312 #, c-format msgid "Use the regexp_matches function instead." msgstr "Вместо неё используйте функцию regexp_matches." -#: utils/adt/regexp.c:1501 +#: utils/adt/regexp.c:1500 #, c-format msgid "too many regular expression matches" msgstr "слишком много совпадений для регулярного выражения" @@ -28330,19 +29687,19 @@ msgstr "имя \"%s\" имеют несколько функций" msgid "more than one operator named %s" msgstr "имя %s имеют несколько операторов" -#: utils/adt/regproc.c:670 gram.y:8841 +#: utils/adt/regproc.c:670 gram.y:8992 #, c-format msgid "missing argument" msgstr "отсутствует аргумент" -#: utils/adt/regproc.c:671 gram.y:8842 +#: utils/adt/regproc.c:671 gram.y:8993 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "" "Чтобы обозначить отсутствующий аргумент унарного оператора, укажите NONE." -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2009 utils/adt/ruleutils.c:10021 -#: utils/adt/ruleutils.c:10234 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10509 +#: utils/adt/ruleutils.c:10722 #, c-format msgid "too many arguments" msgstr "слишком много аргументов" @@ -28352,65 +29709,65 @@ msgstr "слишком много аргументов" msgid "Provide two argument types for operator." msgstr "Предоставьте для оператора два типа аргументов." -#: utils/adt/regproc.c:1544 utils/adt/regproc.c:1661 utils/adt/regproc.c:1790 -#: utils/adt/regproc.c:1795 utils/adt/varlena.c:3410 utils/adt/varlena.c:3415 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 +#: utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 #, c-format msgid "invalid name syntax" msgstr "ошибка синтаксиса в имени" -#: utils/adt/regproc.c:1904 +#: utils/adt/regproc.c:1924 #, c-format msgid "expected a left parenthesis" msgstr "ожидалась левая скобка" -#: utils/adt/regproc.c:1922 +#: utils/adt/regproc.c:1942 #, c-format msgid "expected a right parenthesis" msgstr "ожидалась правая скобка" -#: utils/adt/regproc.c:1941 +#: utils/adt/regproc.c:1961 #, c-format msgid "expected a type name" msgstr "ожидалось имя типа" -#: utils/adt/regproc.c:1973 +#: utils/adt/regproc.c:1993 #, c-format msgid "improper type name" msgstr "ошибочное имя типа" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1625 -#: utils/adt/ri_triggers.c:2610 +#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 +#: utils/adt/ri_triggers.c:2601 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "" "INSERT или UPDATE в таблице \"%s\" нарушает ограничение внешнего ключа \"%s\"" -#: utils/adt/ri_triggers.c:309 utils/adt/ri_triggers.c:1628 +#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MATCH FULL не позволяет смешивать в значении ключа null и не null." -#: utils/adt/ri_triggers.c:2045 +#: utils/adt/ri_triggers.c:2036 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "функция \"%s\" должна запускаться для INSERT" -#: utils/adt/ri_triggers.c:2051 +#: utils/adt/ri_triggers.c:2042 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "функция \"%s\" должна запускаться для UPDATE" -#: utils/adt/ri_triggers.c:2057 +#: utils/adt/ri_triggers.c:2048 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "функция \"%s\" должна запускаться для DELETE" -#: utils/adt/ri_triggers.c:2080 +#: utils/adt/ri_triggers.c:2071 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "для триггера \"%s\" таблицы \"%s\" нет записи pg_constraint" -#: utils/adt/ri_triggers.c:2082 +#: utils/adt/ri_triggers.c:2073 #, c-format msgid "" "Remove this referential integrity trigger and its mates, then do ALTER TABLE " @@ -28419,12 +29776,12 @@ msgstr "" "Удалите этот триггер ссылочной целостности и связанные объекты, а затем " "выполните ALTER TABLE ADD CONSTRAINT." -#: utils/adt/ri_triggers.c:2112 gram.y:4223 +#: utils/adt/ri_triggers.c:2103 gram.y:4340 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "выражение MATCH PARTIAL ещё не реализовано" -#: utils/adt/ri_triggers.c:2435 +#: utils/adt/ri_triggers.c:2426 #, c-format msgid "" "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave " @@ -28433,33 +29790,33 @@ msgstr "" "неожиданный результат запроса ссылочной целостности к \"%s\" из ограничения " "\"%s\" таблицы \"%s\"" -#: utils/adt/ri_triggers.c:2439 +#: utils/adt/ri_triggers.c:2430 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "Скорее всего это вызвано правилом, переписавшим запрос." -#: utils/adt/ri_triggers.c:2600 +#: utils/adt/ri_triggers.c:2591 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "" "при удалении секции \"%s\" нарушается ограничение внешнего ключа \"%s\"" -#: utils/adt/ri_triggers.c:2603 utils/adt/ri_triggers.c:2628 +#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "На ключ (%s)=(%s) всё ещё есть ссылки в таблице \"%s\"." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2605 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "Ключ (%s)=(%s) отсутствует в таблице \"%s\"." -#: utils/adt/ri_triggers.c:2617 +#: utils/adt/ri_triggers.c:2608 #, c-format msgid "Key is not present in table \"%s\"." msgstr "Ключ отсутствует в таблице \"%s\"." -#: utils/adt/ri_triggers.c:2623 +#: utils/adt/ri_triggers.c:2614 #, c-format msgid "" "update or delete on table \"%s\" violates foreign key constraint \"%s\" on " @@ -28468,48 +29825,48 @@ msgstr "" "UPDATE или DELETE в таблице \"%s\" нарушает ограничение внешнего ключа " "\"%s\" таблицы \"%s\"" -#: utils/adt/ri_triggers.c:2631 +#: utils/adt/ri_triggers.c:2622 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "На ключ всё ещё есть ссылки в таблице \"%s\"." -#: utils/adt/rowtypes.c:106 utils/adt/rowtypes.c:510 +#: utils/adt/rowtypes.c:105 utils/adt/rowtypes.c:509 #, c-format msgid "input of anonymous composite types is not implemented" msgstr "ввод анонимных составных типов не реализован" -#: utils/adt/rowtypes.c:159 utils/adt/rowtypes.c:191 utils/adt/rowtypes.c:217 -#: utils/adt/rowtypes.c:228 utils/adt/rowtypes.c:286 utils/adt/rowtypes.c:297 +#: utils/adt/rowtypes.c:158 utils/adt/rowtypes.c:190 utils/adt/rowtypes.c:216 +#: utils/adt/rowtypes.c:227 utils/adt/rowtypes.c:285 utils/adt/rowtypes.c:296 #, c-format msgid "malformed record literal: \"%s\"" msgstr "ошибка в литерале записи: \"%s\"" -#: utils/adt/rowtypes.c:160 +#: utils/adt/rowtypes.c:159 #, c-format msgid "Missing left parenthesis." msgstr "Отсутствует левая скобка." -#: utils/adt/rowtypes.c:192 +#: utils/adt/rowtypes.c:191 #, c-format msgid "Too few columns." msgstr "Слишком мало столбцов." -#: utils/adt/rowtypes.c:287 +#: utils/adt/rowtypes.c:286 #, c-format msgid "Too many columns." msgstr "Слишком много столбцов." -#: utils/adt/rowtypes.c:298 +#: utils/adt/rowtypes.c:297 #, c-format msgid "Junk after right parenthesis." msgstr "Мусор после правой скобки." -#: utils/adt/rowtypes.c:559 +#: utils/adt/rowtypes.c:558 #, c-format msgid "wrong number of columns: %d, expected %d" msgstr "неверное число столбцов: %d, ожидалось: %d" -#: utils/adt/rowtypes.c:601 +#: utils/adt/rowtypes.c:599 #, c-format msgid "" "binary data has type %u (%s) instead of expected %u (%s) in record column %d" @@ -28517,168 +29874,177 @@ msgstr "" "с бинарными данными связан тип %u (%s) вместо ожидаемого %u (%s) в столбце " "записи %d" -#: utils/adt/rowtypes.c:668 +#: utils/adt/rowtypes.c:660 #, c-format msgid "improper binary format in record column %d" msgstr "неподходящий двоичный формат в столбце записи %d" -#: utils/adt/rowtypes.c:959 utils/adt/rowtypes.c:1205 utils/adt/rowtypes.c:1463 -#: utils/adt/rowtypes.c:1709 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 +#: utils/adt/rowtypes.c:1699 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "не удалось сравнить различные типы столбцов %s и %s, столбец записи %d" -#: utils/adt/rowtypes.c:1050 utils/adt/rowtypes.c:1275 -#: utils/adt/rowtypes.c:1560 utils/adt/rowtypes.c:1745 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 +#: utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "сравнивать типы записей с разным числом столбцов нельзя" -#: utils/adt/ruleutils.c:2679 +#: utils/adt/ruleutils.c:2694 #, c-format msgid "input is a query, not an expression" msgstr "на вход поступил запрос, а не выражение" -#: utils/adt/ruleutils.c:2691 +#: utils/adt/ruleutils.c:2706 #, c-format msgid "expression contains variables of more than one relation" msgstr "выражение содержит переменные из нескольких отношений" -#: utils/adt/ruleutils.c:2698 +#: utils/adt/ruleutils.c:2713 #, c-format msgid "expression contains variables" msgstr "выражение содержит переменные" -#: utils/adt/ruleutils.c:5228 +#: utils/adt/ruleutils.c:5246 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "правило \"%s\" имеет неподдерживаемый тип событий %d" -#: utils/adt/timestamp.c:112 +#: utils/adt/timestamp.c:128 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "TIMESTAMP(%d)%s: точность должна быть неотрицательна" -#: utils/adt/timestamp.c:118 +#: utils/adt/timestamp.c:134 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "TIMESTAMP(%d)%s: точность уменьшена до дозволенного максимума: %d" -#: utils/adt/timestamp.c:378 +#: utils/adt/timestamp.c:394 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "точность timestamp(%d) должна быть между %d и %d" -#: utils/adt/timestamp.c:496 +#: utils/adt/timestamp.c:512 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "" "Запись числового часового пояса должна начинаться с символа \"-\" или \"+\"." -#: utils/adt/timestamp.c:508 +#: utils/adt/timestamp.c:524 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "числовой часовой пояс \"%s\" вне диапазона" -#: utils/adt/timestamp.c:609 utils/adt/timestamp.c:619 -#: utils/adt/timestamp.c:627 +#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 +#: utils/adt/timestamp.c:643 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "timestamp вне диапазона: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:728 +#: utils/adt/timestamp.c:744 #, c-format msgid "timestamp cannot be NaN" msgstr "timestamp не может быть NaN" -#: utils/adt/timestamp.c:746 utils/adt/timestamp.c:758 +#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "timestamp вне диапазона: \"%g\"" -#: utils/adt/timestamp.c:941 utils/adt/timestamp.c:1518 -#: utils/adt/timestamp.c:2708 utils/adt/timestamp.c:2778 -#: utils/adt/timestamp.c:2795 utils/adt/timestamp.c:2848 -#: utils/adt/timestamp.c:2887 utils/adt/timestamp.c:3215 -#: utils/adt/timestamp.c:3220 utils/adt/timestamp.c:3225 -#: utils/adt/timestamp.c:3275 utils/adt/timestamp.c:3282 -#: utils/adt/timestamp.c:3289 utils/adt/timestamp.c:3309 -#: utils/adt/timestamp.c:3316 utils/adt/timestamp.c:3323 -#: utils/adt/timestamp.c:3410 utils/adt/timestamp.c:3485 -#: utils/adt/timestamp.c:3854 utils/adt/timestamp.c:3978 -#: utils/adt/timestamp.c:4026 utils/adt/timestamp.c:4036 -#: utils/adt/timestamp.c:4226 utils/adt/timestamp.c:4236 -#: utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 +#: utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 +#: utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 +#: utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 +#: utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 +#: utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 +#: utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 +#: utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 +#: utils/adt/timestamp.c:3537 utils/adt/timestamp.c:3546 +#: utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 +#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 +#: utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 +#: utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 +#: utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 +#: utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 +#: utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 +#: utils/adt/timestamp.c:5097 #, c-format msgid "interval out of range" msgstr "interval вне диапазона" -#: utils/adt/timestamp.c:1065 utils/adt/timestamp.c:1098 +#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 #, c-format msgid "invalid INTERVAL type modifier" msgstr "неверный модификатор типа INTERVAL" -#: utils/adt/timestamp.c:1081 +#: utils/adt/timestamp.c:1110 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d): точность должна быть неотрицательна" -#: utils/adt/timestamp.c:1087 +#: utils/adt/timestamp.c:1116 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "INTERVAL(%d): точность уменьшена до максимально возможной: %d" -#: utils/adt/timestamp.c:1473 +#: utils/adt/timestamp.c:1506 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "точность interval(%d) должна быть между %d и %d" -#: utils/adt/timestamp.c:2703 -#, c-format -msgid "cannot subtract infinite timestamps" -msgstr "вычитать бесконечные значения timestamp нельзя" - -#: utils/adt/timestamp.c:4015 utils/adt/timestamp.c:4215 +#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 #, c-format msgid "origin out of range" msgstr "начало вне диапазона" -#: utils/adt/timestamp.c:4020 utils/adt/timestamp.c:4220 +#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#, c-format +msgid "timestamps cannot be binned into infinite intervals" +msgstr "значения timestamp нельзя подогнать под бесконечные интервалы" + +#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "" "значения timestamp нельзя подогнать под интервалы, содержащие месяцы или годы" -#: utils/adt/timestamp.c:4031 utils/adt/timestamp.c:4231 +#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 #, c-format msgid "stride must be greater than zero" msgstr "шаг должен быть больше нуля" -#: utils/adt/timestamp.c:4526 +#: utils/adt/timestamp.c:5091 #, c-format msgid "Months usually have fractional weeks." msgstr "В месяцах обычно дробное количество недель." -#: utils/adt/trigfuncs.c:42 +#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#, c-format +msgid "step size cannot be infinite" +msgstr "размер шага не может быть бесконечным" + +#: utils/adt/trigfuncs.c:41 #, c-format msgid "suppress_redundant_updates_trigger: must be called as trigger" msgstr "" "функция suppress_redundant_updates_trigger должна вызываться как триггер" -#: utils/adt/trigfuncs.c:48 +#: utils/adt/trigfuncs.c:47 #, c-format msgid "suppress_redundant_updates_trigger: must be called on update" msgstr "" "функция suppress_redundant_updates_trigger должна вызываться при обновлении" -#: utils/adt/trigfuncs.c:54 +#: utils/adt/trigfuncs.c:53 #, c-format msgid "suppress_redundant_updates_trigger: must be called before update" msgstr "" "функция suppress_redundant_updates_trigger должна вызываться перед " "обновлением" -#: utils/adt/trigfuncs.c:60 +#: utils/adt/trigfuncs.c:59 #, c-format msgid "suppress_redundant_updates_trigger: must be called for each row" msgstr "" @@ -28699,32 +30065,32 @@ msgstr "" msgid "no operand in tsquery: \"%s\"" msgstr "нет оператора в tsquery: \"%s\"" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "слишком большое значение в tsquery: \"%s\"" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "слишком длинный операнд в tsquery: \"%s\"" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "слишком длинное слово в tsquery: \"%s\"" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "ошибка синтаксиса в tsquery: \"%s\"" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "запрос поиска текста не содержит лексемы: \"%s\"" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "tsquery слишком большой" @@ -28763,72 +30129,72 @@ msgstr "массив весов не может содержать null" msgid "weight out of range" msgstr "вес вне диапазона" -#: utils/adt/tsvector.c:217 +#: utils/adt/tsvector.c:216 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "слово слишком длинное (%ld Б, при максимуме %ld)" -#: utils/adt/tsvector.c:224 +#: utils/adt/tsvector.c:223 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "строка слишком длинна для tsvector (%ld Б, при максимуме %ld)" -#: utils/adt/tsvector_op.c:773 +#: utils/adt/tsvector_op.c:771 #, c-format msgid "lexeme array may not contain nulls" msgstr "массив лексем не может содержать элементы null" -#: utils/adt/tsvector_op.c:778 +#: utils/adt/tsvector_op.c:776 #, c-format msgid "lexeme array may not contain empty strings" msgstr "массив лексем не должен содержать пустые строки" -#: utils/adt/tsvector_op.c:847 +#: utils/adt/tsvector_op.c:845 #, c-format msgid "weight array may not contain nulls" msgstr "массив весов не может содержать элементы null" -#: utils/adt/tsvector_op.c:871 +#: utils/adt/tsvector_op.c:869 #, c-format msgid "unrecognized weight: \"%c\"" msgstr "нераспознанный вес: \"%c\"" -#: utils/adt/tsvector_op.c:2601 +#: utils/adt/tsvector_op.c:2599 #, c-format msgid "ts_stat query must return one tsvector column" msgstr "запрос ts_stat должен вернуть один столбец tsvector" -#: utils/adt/tsvector_op.c:2790 +#: utils/adt/tsvector_op.c:2788 #, c-format msgid "tsvector column \"%s\" does not exist" msgstr "столбец \"%s\" типа tsvector не существует" -#: utils/adt/tsvector_op.c:2797 +#: utils/adt/tsvector_op.c:2795 #, c-format msgid "column \"%s\" is not of tsvector type" msgstr "столбец \"%s\" должен иметь тип tsvector" -#: utils/adt/tsvector_op.c:2809 +#: utils/adt/tsvector_op.c:2807 #, c-format msgid "configuration column \"%s\" does not exist" msgstr "столбец конфигурации \"%s\" не существует" -#: utils/adt/tsvector_op.c:2815 +#: utils/adt/tsvector_op.c:2813 #, c-format msgid "column \"%s\" is not of regconfig type" msgstr "столбец \"%s\" должен иметь тип regconfig" -#: utils/adt/tsvector_op.c:2822 +#: utils/adt/tsvector_op.c:2820 #, c-format msgid "configuration column \"%s\" must not be null" msgstr "значение столбца конфигурации \"%s\" не должно быть null" -#: utils/adt/tsvector_op.c:2835 +#: utils/adt/tsvector_op.c:2833 #, c-format msgid "text search configuration name \"%s\" must be schema-qualified" msgstr "имя конфигурации текстового поиска \"%s\" должно указываться со схемой" -#: utils/adt/tsvector_op.c:2860 +#: utils/adt/tsvector_op.c:2858 #, c-format msgid "column \"%s\" is not of a character type" msgstr "столбец \"%s\" имеет не символьный тип" @@ -28849,17 +30215,17 @@ msgstr "нет спец. символа \"%s\"" msgid "wrong position info in tsvector: \"%s\"" msgstr "неверная информация о позиции в tsvector: \"%s\"" -#: utils/adt/uuid.c:413 +#: utils/adt/uuid.c:418 #, c-format msgid "could not generate random values" msgstr "не удалось сгенерировать случайные значения" -#: utils/adt/varbit.c:110 utils/adt/varchar.c:54 +#: utils/adt/varbit.c:110 utils/adt/varchar.c:53 #, c-format msgid "length for type %s must be at least 1" msgstr "длина значения типа %s должна быть как минимум 1" -#: utils/adt/varbit.c:115 utils/adt/varchar.c:58 +#: utils/adt/varbit.c:115 utils/adt/varchar.c:57 #, c-format msgid "length for type %s cannot exceed %d" msgstr "длина значения типа %s не может превышать %d" @@ -28894,9 +30260,9 @@ msgstr "неверная длина во внешней строке битов" msgid "bit string too long for type bit varying(%d)" msgstr "строка битов не умещается в тип bit varying(%d)" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:908 -#: utils/adt/varlena.c:971 utils/adt/varlena.c:1128 utils/adt/varlena.c:3052 -#: utils/adt/varlena.c:3130 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 +#: utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 +#: utils/adt/varlena.c:3133 #, c-format msgid "negative substring length not allowed" msgstr "подстрока должна иметь неотрицательную длину" @@ -28922,106 +30288,113 @@ msgstr "" msgid "bit index %d out of valid range (0..%d)" msgstr "индекс бита %d вне диапазона 0..%d" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3334 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 #, c-format msgid "new bit must be 0 or 1" msgstr "значением бита должен быть 0 или 1" -#: utils/adt/varchar.c:162 utils/adt/varchar.c:313 +#: utils/adt/varchar.c:161 utils/adt/varchar.c:312 #, c-format msgid "value too long for type character(%d)" msgstr "значение не умещается в тип character(%d)" -#: utils/adt/varchar.c:476 utils/adt/varchar.c:640 +#: utils/adt/varchar.c:475 utils/adt/varchar.c:639 #, c-format msgid "value too long for type character varying(%d)" msgstr "значение не умещается в тип character varying(%d)" -#: utils/adt/varchar.c:738 utils/adt/varlena.c:1517 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "" "не удалось определить, какое правило сортировки использовать для сравнения " "строк" -#: utils/adt/varlena.c:1227 utils/adt/varlena.c:1806 +#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "" "недетерминированные правила сортировки не поддерживаются для поиска подстрок" -#: utils/adt/varlena.c:3218 utils/adt/varlena.c:3285 +#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "индекс %d вне диапазона 0..%d" -#: utils/adt/varlena.c:3249 utils/adt/varlena.c:3321 +#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 #, c-format msgid "index %lld out of valid range, 0..%lld" msgstr "индекс %lld вне диапазона 0..%lld" -#: utils/adt/varlena.c:4382 +#: utils/adt/varlena.c:4385 #, c-format msgid "field position must not be zero" msgstr "позиция поля должна быть отлична от 0" -#: utils/adt/varlena.c:5554 +#: utils/adt/varlena.c:5630 #, c-format msgid "unterminated format() type specifier" msgstr "незавершённый спецификатор типа format()" -#: utils/adt/varlena.c:5555 utils/adt/varlena.c:5689 utils/adt/varlena.c:5810 +#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "Для представления одного знака \"%%\" запишите \"%%%%\"." -#: utils/adt/varlena.c:5687 utils/adt/varlena.c:5808 +#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "нераспознанный спецификатор типа format(): \"%.*s\"" -#: utils/adt/varlena.c:5700 utils/adt/varlena.c:5757 +#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 #, c-format msgid "too few arguments for format()" msgstr "мало аргументов для format()" -#: utils/adt/varlena.c:5853 utils/adt/varlena.c:6035 +#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 #, c-format msgid "number is out of range" msgstr "число вне диапазона" -#: utils/adt/varlena.c:5916 utils/adt/varlena.c:5944 +#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "формат ссылается на аргумент 0, но аргументы нумеруются с 1" -#: utils/adt/varlena.c:5937 +#: utils/adt/varlena.c:6013 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "указание аргумента ширины должно оканчиваться \"$\"" -#: utils/adt/varlena.c:5982 +#: utils/adt/varlena.c:6058 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "значения null нельзя представить в виде SQL-идентификатора" -#: utils/adt/varlena.c:6190 +#: utils/adt/varlena.c:6266 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "" "нормализацию Unicode можно выполнять, только если кодировка сервера — UTF8" -#: utils/adt/varlena.c:6203 +#: utils/adt/varlena.c:6279 #, c-format msgid "invalid normalization form: %s" msgstr "неверная форма нормализации: %s" -#: utils/adt/varlena.c:6406 utils/adt/varlena.c:6441 utils/adt/varlena.c:6476 +# well-spelled: категоризацию +#: utils/adt/varlena.c:6324 +#, c-format +msgid "Unicode categorization can only be performed if server encoding is UTF8" +msgstr "" +"категоризацию Unicode можно выполнять, только если кодировка сервера — UTF8" + +#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 #, c-format msgid "invalid Unicode code point: %04X" msgstr "неверный код символа Unicode: %04X" -#: utils/adt/varlena.c:6506 +#: utils/adt/varlena.c:6641 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "" @@ -29032,17 +30405,17 @@ msgstr "" msgid "argument of ntile must be greater than zero" msgstr "аргумент ntile должен быть больше нуля" -#: utils/adt/windowfuncs.c:723 +#: utils/adt/windowfuncs.c:707 #, c-format msgid "argument of nth_value must be greater than zero" msgstr "аргумент nth_value должен быть больше нуля" -#: utils/adt/xid8funcs.c:126 +#: utils/adt/xid8funcs.c:120 #, c-format msgid "transaction ID %llu is in the future" msgstr "ID транзакции %llu относится к будущему" -#: utils/adt/xid8funcs.c:555 +#: utils/adt/xid8funcs.c:522 #, c-format msgid "invalid external pg_snapshot data" msgstr "неверное внешнее представление pg_snapshot" @@ -29057,7 +30430,7 @@ msgstr "XML-функции не поддерживаются" msgid "This functionality requires the server to be built with libxml support." msgstr "Для этой функциональности в сервере не хватает поддержки libxml." -#: utils/adt/xml.c:258 utils/mb/mbutils.c:628 +#: utils/adt/xml.c:258 utils/mb/mbutils.c:627 #, c-format msgid "invalid encoding name \"%s\"" msgstr "неверное имя кодировки: \"%s\"" @@ -29067,37 +30440,37 @@ msgstr "неверное имя кодировки: \"%s\"" msgid "invalid XML comment" msgstr "ошибка в XML-комментарии" -#: utils/adt/xml.c:670 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "не XML-документ" -#: utils/adt/xml.c:966 utils/adt/xml.c:989 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "неправильная XML-инструкция обработки (PI)" -#: utils/adt/xml.c:967 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "назначением XML-инструкции обработки (PI) не может быть \"%s\"." -#: utils/adt/xml.c:990 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "XML-инструкция обработки (PI) не может содержать \"?>\"." -#: utils/adt/xml.c:1069 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "функция xmlvalidate не реализована" -#: utils/adt/xml.c:1125 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "не удалось инициализировать библиотеку XML" -#: utils/adt/xml.c:1126 +#: utils/adt/xml.c:1168 #, c-format msgid "" "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." @@ -29105,12 +30478,12 @@ msgstr "" "В libxml2 оказался несовместимый тип char: sizeof(char)=%zu, " "sizeof(xmlChar)=%zu." -#: utils/adt/xml.c:1212 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "не удалось установить обработчик XML-ошибок" -#: utils/adt/xml.c:1213 +#: utils/adt/xml.c:1255 #, c-format msgid "" "This probably indicates that the version of libxml2 being used is not " @@ -29119,125 +30492,125 @@ msgstr "" "Возможно, это означает, что используемая версия libxml2 несовместима с " "заголовочными файлами libxml2, с которыми был собран PostgreSQL." -#: utils/adt/xml.c:2199 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "Неверный символ." -#: utils/adt/xml.c:2202 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "Требуется пробел." -#: utils/adt/xml.c:2205 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "значениями атрибута standalone могут быть только 'yes' и 'no'." -#: utils/adt/xml.c:2208 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "Ошибочное объявление: не указана версия." -#: utils/adt/xml.c:2211 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "В объявлении не указана кодировка." -#: utils/adt/xml.c:2214 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "Ошибка при разборе XML-объявления: ожидается '?>'." -#: utils/adt/xml.c:2217 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "Нераспознанный код ошибки libxml: %d." -#: utils/adt/xml.c:2471 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML не поддерживает бесконечность в датах." -#: utils/adt/xml.c:2493 utils/adt/xml.c:2520 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML не поддерживает бесконечность в timestamp." -#: utils/adt/xml.c:2936 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "неверный запрос" -#: utils/adt/xml.c:3028 +#: utils/adt/xml.c:3110 #, c-format msgid "portal \"%s\" does not return tuples" msgstr "портал \"%s\" не возвращает кортежи" -#: utils/adt/xml.c:4280 +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "неправильный массив с сопоставлениями пространств имён XML" -#: utils/adt/xml.c:4281 +#: utils/adt/xml.c:4363 #, c-format msgid "" "The array must be two-dimensional with length of the second axis equal to 2." msgstr "Массив должен быть двухмерным и содержать 2 элемента по второй оси." -#: utils/adt/xml.c:4305 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "пустое выражение XPath" -#: utils/adt/xml.c:4357 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "ни префикс, ни URI пространства имён не может быть null" -#: utils/adt/xml.c:4364 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "" "не удалось зарегистрировать пространство имён XML с префиксом \"%s\" и URI " "\"%s\"" -#: utils/adt/xml.c:4707 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "пространство имён DEFAULT не поддерживается" -#: utils/adt/xml.c:4736 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "путь отбираемых строк не должен быть пустым" -#: utils/adt/xml.c:4767 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "путь отбираемого столбца не должен быть пустым" -#: utils/adt/xml.c:4911 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "выражение XPath, отбирающее столбец, возвратило более одного значения" -#: utils/cache/lsyscache.c:1043 +#: utils/cache/lsyscache.c:1017 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "приведение типа %s к типу %s не существует" -#: utils/cache/lsyscache.c:2845 utils/cache/lsyscache.c:2878 -#: utils/cache/lsyscache.c:2911 utils/cache/lsyscache.c:2944 +#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 +#: utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 #, c-format msgid "type %s is only a shell" msgstr "тип %s является пустышкой" -#: utils/cache/lsyscache.c:2850 +#: utils/cache/lsyscache.c:2892 #, c-format msgid "no input function available for type %s" msgstr "для типа %s нет функции ввода" -#: utils/cache/lsyscache.c:2883 +#: utils/cache/lsyscache.c:2925 #, c-format msgid "no output function available for type %s" msgstr "для типа %s нет функции вывода" -#: utils/cache/partcache.c:219 +#: utils/cache/partcache.c:216 #, c-format msgid "" "operator class \"%s\" of access method %s is missing support function %d for " @@ -29246,56 +30619,56 @@ msgstr "" "в классе операторов \"%s\" метода доступа %s нет опорной функции %d для типа " "%s" -#: utils/cache/plancache.c:724 +#: utils/cache/plancache.c:747 #, c-format msgid "cached plan must not change result type" msgstr "в кешированном плане не должен изменяться тип результата" -#: utils/cache/relcache.c:3741 +#: utils/cache/relcache.c:3801 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "" "значение relfilenumber для кучи не задано в режиме двоичного обновления" -#: utils/cache/relcache.c:3749 +#: utils/cache/relcache.c:3809 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "" "неожиданный запрос нового значения relfilenumber в режиме двоичного " "обновления" -#: utils/cache/relcache.c:6495 +#: utils/cache/relcache.c:6539 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "создать файл инициализации для кеша отношений \"%s\" не удалось: %m" -#: utils/cache/relcache.c:6497 +#: utils/cache/relcache.c:6541 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "Продолжаем всё равно, хотя что-то не так." -#: utils/cache/relcache.c:6819 +#: utils/cache/relcache.c:6871 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "не удалось стереть файл кеша \"%s\": %m" -#: utils/cache/relmapper.c:597 +#: utils/cache/relmapper.c:596 #, c-format msgid "cannot PREPARE a transaction that modified relation mapping" msgstr "" "выполнить PREPARE для транзакции, изменившей сопоставление отношений, нельзя" -#: utils/cache/relmapper.c:853 +#: utils/cache/relmapper.c:852 #, c-format msgid "relation mapping file \"%s\" contains invalid data" msgstr "файл сопоставления отношений \"%s\" содержит неверные данные" -#: utils/cache/relmapper.c:863 +#: utils/cache/relmapper.c:862 #, c-format msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "ошибка контрольной суммы в файле сопоставления отношений \"%s\"" -#: utils/cache/typcache.c:1809 utils/fmgr/funcapi.c:574 +#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "тип записи не зарегистрирован" @@ -29310,102 +30683,102 @@ msgstr "ЛОВУШКА: Исключительное условие: невер msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "ЛОВУШКА: нарушение Assert(\"%s\"), файл: \"%s\", строка: %d, PID: %d\n" -#: utils/error/elog.c:416 +#: utils/error/elog.c:415 #, c-format msgid "error occurred before error message processing is available\n" msgstr "произошла ошибка до готовности подсистемы обработки сообщений\n" -#: utils/error/elog.c:2096 +#: utils/error/elog.c:2134 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "открыть файл \"%s\" как stderr не удалось: %m" -#: utils/error/elog.c:2109 +#: utils/error/elog.c:2147 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "открыть файл \"%s\" как stdout не удалось: %m" -#: utils/error/elog.c:2145 +#: utils/error/elog.c:2183 #, c-format -msgid "invalid character" -msgstr "неверный символ" +msgid "Invalid character" +msgstr "Недопустимый символ" -#: utils/error/elog.c:2851 utils/error/elog.c:2878 utils/error/elog.c:2894 +#: utils/error/elog.c:2889 utils/error/elog.c:2916 utils/error/elog.c:2932 msgid "[unknown]" msgstr "[н/д]" -#: utils/error/elog.c:3167 utils/error/elog.c:3488 utils/error/elog.c:3595 +#: utils/error/elog.c:3202 utils/error/elog.c:3526 utils/error/elog.c:3633 msgid "missing error text" msgstr "отсутствует текст ошибки" -#: utils/error/elog.c:3170 utils/error/elog.c:3173 +#: utils/error/elog.c:3205 utils/error/elog.c:3208 #, c-format msgid " at character %d" msgstr " (символ %d)" -#: utils/error/elog.c:3183 utils/error/elog.c:3190 +#: utils/error/elog.c:3218 utils/error/elog.c:3225 msgid "DETAIL: " msgstr "ПОДРОБНОСТИ: " -#: utils/error/elog.c:3197 +#: utils/error/elog.c:3232 msgid "HINT: " msgstr "ПОДСКАЗКА: " -#: utils/error/elog.c:3204 +#: utils/error/elog.c:3239 msgid "QUERY: " msgstr "ЗАПРОС: " -#: utils/error/elog.c:3211 +#: utils/error/elog.c:3246 msgid "CONTEXT: " msgstr "КОНТЕКСТ: " -#: utils/error/elog.c:3221 +#: utils/error/elog.c:3256 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "ПОЛОЖЕНИЕ: %s, %s:%d\n" -#: utils/error/elog.c:3228 +#: utils/error/elog.c:3263 #, c-format msgid "LOCATION: %s:%d\n" msgstr "ПОЛОЖЕНИЕ: %s:%d\n" -#: utils/error/elog.c:3235 +#: utils/error/elog.c:3270 msgid "BACKTRACE: " msgstr "СТЕК: " -#: utils/error/elog.c:3247 +#: utils/error/elog.c:3282 msgid "STATEMENT: " msgstr "ОПЕРАТОР: " -#: utils/error/elog.c:3640 +#: utils/error/elog.c:3678 msgid "DEBUG" msgstr "ОТЛАДКА" -#: utils/error/elog.c:3644 +#: utils/error/elog.c:3682 msgid "LOG" msgstr "СООБЩЕНИЕ" -#: utils/error/elog.c:3647 +#: utils/error/elog.c:3685 msgid "INFO" msgstr "ИНФОРМАЦИЯ" -#: utils/error/elog.c:3650 +#: utils/error/elog.c:3688 msgid "NOTICE" msgstr "ЗАМЕЧАНИЕ" -#: utils/error/elog.c:3654 +#: utils/error/elog.c:3692 msgid "WARNING" msgstr "ПРЕДУПРЕЖДЕНИЕ" -#: utils/error/elog.c:3657 +#: utils/error/elog.c:3695 msgid "ERROR" msgstr "ОШИБКА" -#: utils/error/elog.c:3660 +#: utils/error/elog.c:3698 msgid "FATAL" msgstr "ВАЖНО" -#: utils/error/elog.c:3663 +#: utils/error/elog.c:3701 msgid "PANIC" msgstr "ПАНИКА" @@ -29478,22 +30851,22 @@ msgstr "Отличительный блок имеет неверную длин msgid "incompatible library \"%s\": magic block mismatch" msgstr "несовместимая библиотека \"%s\": несоответствие отличительного блока" -#: utils/fmgr/dfmgr.c:492 +#: utils/fmgr/dfmgr.c:475 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "доступ к библиотеке \"%s\" не разрешён" -#: utils/fmgr/dfmgr.c:518 +#: utils/fmgr/dfmgr.c:501 #, c-format msgid "invalid macro name in dynamic library path: %s" msgstr "неправильный макрос в пути динамической библиотеки: %s" -#: utils/fmgr/dfmgr.c:558 +#: utils/fmgr/dfmgr.c:541 #, c-format msgid "zero-length component in parameter \"dynamic_library_path\"" msgstr "параметр dynamic_library_path содержит компонент нулевой длины" -#: utils/fmgr/dfmgr.c:577 +#: utils/fmgr/dfmgr.c:560 #, c-format msgid "component in parameter \"dynamic_library_path\" is not an absolute path" msgstr "" @@ -29524,14 +30897,14 @@ msgid "unrecognized API version %d reported by info function \"%s\"" msgstr "" "версия API (%d), выданная информационной функцией \"%s\", не поддерживается" -#: utils/fmgr/fmgr.c:2080 +#: utils/fmgr/fmgr.c:2109 #, c-format msgid "operator class options info is absent in function call context" msgstr "" "информация о параметрах класса операторов отсутствует в контексте вызова " "функции" -#: utils/fmgr/fmgr.c:2147 +#: utils/fmgr/fmgr.c:2176 #, c-format msgid "language validation function %u called for language %u instead of %u" msgstr "функция языковой проверки %u вызвана для языка %u (а не %u)" @@ -29551,11 +30924,6 @@ msgid "argument declared %s does not contain a range type but type %s" msgstr "" "аргумент, объявленный как \"%s\", содержит не диапазонный тип, а тип %s" -#: utils/fmgr/funcapi.c:725 -#, c-format -msgid "could not find multirange type for data type %s" -msgstr "тип мультидиапазона для типа данных %s не найден" - #: utils/fmgr/funcapi.c:1929 utils/fmgr/funcapi.c:1961 #, c-format msgid "number of aliases does not match number of columns" @@ -29571,105 +30939,100 @@ msgstr "псевдоним столбца не указан" msgid "could not determine row description for function returning record" msgstr "не удалось определить описание строки для функции, возвращающей запись" -#: utils/init/miscinit.c:346 +#: utils/init/miscinit.c:353 #, c-format msgid "data directory \"%s\" does not exist" msgstr "каталог данных \"%s\" не существует" -#: utils/init/miscinit.c:351 +#: utils/init/miscinit.c:358 #, c-format msgid "could not read permissions of directory \"%s\": %m" -msgstr "не удалось считать права на каталог \"%s\": %m" +msgstr "не удалось прочитать права на каталог \"%s\": %m" -#: utils/init/miscinit.c:359 +#: utils/init/miscinit.c:366 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "указанный каталог данных \"%s\" не существует" -#: utils/init/miscinit.c:375 +#: utils/init/miscinit.c:382 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "владелец каталога данных \"%s\" определён неверно" -#: utils/init/miscinit.c:377 +#: utils/init/miscinit.c:384 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "" "Сервер должен запускать пользователь, являющийся владельцем каталога данных." -#: utils/init/miscinit.c:395 +#: utils/init/miscinit.c:402 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "для каталога данных \"%s\" установлены неправильные права доступа" -#: utils/init/miscinit.c:397 +#: utils/init/miscinit.c:404 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "Маска прав должна быть u=rwx (0700) или u=rwx,g=rx (0750)." -#: utils/init/miscinit.c:455 +#: utils/init/miscinit.c:462 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "не удалось перейти в каталог \"%s\": %m" -#: utils/init/miscinit.c:692 utils/misc/guc.c:3557 +#: utils/init/miscinit.c:720 utils/misc/guc.c:3650 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "" "параметр \"%s\" нельзя задать в рамках операции с ограничениями по " "безопасности" -#: utils/init/miscinit.c:764 +#: utils/init/miscinit.c:807 #, c-format msgid "role with OID %u does not exist" msgstr "роль с OID %u не существует" -#: utils/init/miscinit.c:794 +#: utils/init/miscinit.c:853 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "для роли \"%s\" вход запрещён" -#: utils/init/miscinit.c:812 +#: utils/init/miscinit.c:874 #, c-format msgid "too many connections for role \"%s\"" msgstr "слишком много подключений для роли \"%s\"" -#: utils/init/miscinit.c:919 -#, c-format -msgid "permission denied to set session authorization" -msgstr "нет прав для смены объекта авторизации в сеансе" - -#: utils/init/miscinit.c:1002 +#: utils/init/miscinit.c:1045 #, c-format msgid "invalid role OID: %u" msgstr "неверный OID роли: %u" -#: utils/init/miscinit.c:1149 +#: utils/init/miscinit.c:1192 #, c-format msgid "database system is shut down" msgstr "система БД выключена" -#: utils/init/miscinit.c:1236 +#: utils/init/miscinit.c:1279 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "не удалось создать файл блокировки \"%s\": %m" -#: utils/init/miscinit.c:1250 +#: utils/init/miscinit.c:1293 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "не удалось открыть файл блокировки \"%s\": %m" -#: utils/init/miscinit.c:1257 +#: utils/init/miscinit.c:1300 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "не удалось прочитать файл блокировки \"%s\": %m" -#: utils/init/miscinit.c:1266 +#: utils/init/miscinit.c:1309 #, c-format msgid "lock file \"%s\" is empty" msgstr "файл блокировки \"%s\" пуст" -#: utils/init/miscinit.c:1267 +#: utils/init/miscinit.c:1310 #, c-format msgid "" "Either another server is starting, or the lock file is the remnant of a " @@ -29678,38 +31041,38 @@ msgstr "" "Либо сейчас запускается другой сервер, либо этот файл остался в результате " "сбоя при предыдущем запуске." -#: utils/init/miscinit.c:1311 +#: utils/init/miscinit.c:1354 #, c-format msgid "lock file \"%s\" already exists" msgstr "файл блокировки \"%s\" уже существует" -#: utils/init/miscinit.c:1315 +#: utils/init/miscinit.c:1358 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "Другой экземпляр postgres (PID %d) работает с каталогом данных \"%s\"?" -#: utils/init/miscinit.c:1317 +#: utils/init/miscinit.c:1360 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "" "Другой экземпляр postmaster (PID %d) работает с каталогом данных \"%s\"?" -#: utils/init/miscinit.c:1320 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "Другой экземпляр postgres (PID %d) использует файл сокета \"%s\"?" -#: utils/init/miscinit.c:1322 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "Другой экземпляр postmaster (PID %d) использует файл сокета \"%s\"?" -#: utils/init/miscinit.c:1373 +#: utils/init/miscinit.c:1416 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "не удалось стереть старый файл блокировки \"%s\": %m" -#: utils/init/miscinit.c:1375 +#: utils/init/miscinit.c:1418 #, c-format msgid "" "The file seems accidentally left over, but it could not be removed. Please " @@ -29718,48 +31081,48 @@ msgstr "" "Кажется, файл сохранился по ошибке, но удалить его не получилось. " "Пожалуйста, удалите файл вручную и повторите попытку." -#: utils/init/miscinit.c:1412 utils/init/miscinit.c:1426 -#: utils/init/miscinit.c:1437 +#: utils/init/miscinit.c:1455 utils/init/miscinit.c:1469 +#: utils/init/miscinit.c:1480 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "не удалось записать файл блокировки \"%s\": %m" -#: utils/init/miscinit.c:1548 utils/init/miscinit.c:1690 utils/misc/guc.c:5597 +#: utils/init/miscinit.c:1591 utils/init/miscinit.c:1733 utils/misc/guc.c:5765 #, c-format msgid "could not read from file \"%s\": %m" msgstr "не удалось прочитать файл \"%s\": %m" -#: utils/init/miscinit.c:1678 +#: utils/init/miscinit.c:1721 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "не удалось открыть файл \"%s\": %m; ошибка игнорируется" -#: utils/init/miscinit.c:1703 +#: utils/init/miscinit.c:1746 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "файл блокировки \"%s\" содержит неверный PID: %ld вместо %ld" -#: utils/init/miscinit.c:1742 utils/init/miscinit.c:1758 +#: utils/init/miscinit.c:1785 utils/init/miscinit.c:1801 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "\"%s\" не является каталогом данных" -#: utils/init/miscinit.c:1744 +#: utils/init/miscinit.c:1787 #, c-format msgid "File \"%s\" is missing." msgstr "Файл \"%s\" отсутствует." -#: utils/init/miscinit.c:1760 +#: utils/init/miscinit.c:1803 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "Файл \"%s\" содержит неприемлемые данные." -#: utils/init/miscinit.c:1762 +#: utils/init/miscinit.c:1805 #, c-format msgid "You might need to initdb." msgstr "Возможно, вам нужно выполнить initdb." -#: utils/init/miscinit.c:1770 +#: utils/init/miscinit.c:1813 #, c-format msgid "" "The data directory was initialized by PostgreSQL version %s, which is not " @@ -29844,17 +31207,17 @@ msgstr "доступ к базе \"%s\" запрещён" msgid "User does not have CONNECT privilege." msgstr "Пользователь не имеет привилегии CONNECT." -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:389 #, c-format msgid "too many connections for database \"%s\"" msgstr "слишком много подключений к БД \"%s\"" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:413 utils/init/postinit.c:420 #, c-format msgid "database locale is incompatible with operating system" msgstr "локаль БД несовместима с операционной системой" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:414 #, c-format msgid "" "The database was initialized with LC_COLLATE \"%s\", which is not " @@ -29863,7 +31226,7 @@ msgstr "" "База данных была инициализирована с параметром LC_COLLATE \"%s\", но сейчас " "setlocale() не воспринимает его." -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:416 utils/init/postinit.c:423 #, c-format msgid "" "Recreate the database with another locale or install the missing locale." @@ -29871,7 +31234,7 @@ msgstr "" "Пересоздайте базу данных с другой локалью или установите поддержку нужной " "локали." -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:421 #, c-format msgid "" "The database was initialized with LC_CTYPE \"%s\", which is not recognized " @@ -29880,12 +31243,12 @@ msgstr "" "База данных была инициализирована с параметром LC_CTYPE \"%s\", но сейчас " "setlocale() не воспринимает его." -#: utils/init/postinit.c:475 +#: utils/init/postinit.c:493 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "несовпадение версии для правила сортировки в базе данных \"%s\"" -#: utils/init/postinit.c:477 +#: utils/init/postinit.c:495 #, c-format msgid "" "The database was created using collation version %s, but the operating " @@ -29894,7 +31257,7 @@ msgstr "" "База данных была создана с версией правила сортировки %s, но операционная " "система предоставляет версию %s." -#: utils/init/postinit.c:480 +#: utils/init/postinit.c:498 #, c-format msgid "" "Rebuild all objects in this database that use the default collation and run " @@ -29905,31 +31268,31 @@ msgstr "" "сортировки, и выполните ALTER DATABASE %s REFRESH COLLATION VERSION, либо " "соберите PostgreSQL с правильной версией библиотеки." -#: utils/init/postinit.c:891 +#: utils/init/postinit.c:904 #, c-format msgid "no roles are defined in this database system" msgstr "в этой системе баз данных не создано ни одной роли" -#: utils/init/postinit.c:892 +#: utils/init/postinit.c:905 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "Вы должны немедленно выполнить CREATE USER \"%s\" CREATEUSER;." -#: utils/init/postinit.c:928 +#: utils/init/postinit.c:942 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "" "нужно быть суперпользователем, чтобы подключиться в режиме двоичного " "обновления" -#: utils/init/postinit.c:949 +#: utils/init/postinit.c:962 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "" "оставшиеся слоты подключений зарезервированы для подключений ролей с " "атрибутом %s" -#: utils/init/postinit.c:955 +#: utils/init/postinit.c:968 #, c-format msgid "" "remaining connection slots are reserved for roles with privileges of the " @@ -29938,32 +31301,32 @@ msgstr "" "оставшиеся слоты подключений зарезервированы для подключений ролей с правами " "роли \"%s\"" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:980 #, c-format msgid "permission denied to start WAL sender" msgstr "нет прав для запуска процесса, передающего WAL" -#: utils/init/postinit.c:968 +#: utils/init/postinit.c:981 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "Только роли с атрибутом %s могут запускать процессы, передающие WAL." -#: utils/init/postinit.c:1086 +#: utils/init/postinit.c:1099 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "Похоже, она только что была удалена или переименована." -#: utils/init/postinit.c:1090 +#: utils/init/postinit.c:1103 #, c-format msgid "database %u does not exist" msgstr "база данных %u не существует" -#: utils/init/postinit.c:1099 +#: utils/init/postinit.c:1112 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "подключиться к некорректной базе \"%s\" нельзя" -#: utils/init/postinit.c:1159 +#: utils/init/postinit.c:1173 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "Подкаталог базы данных \"%s\" отсутствует." @@ -29990,48 +31353,48 @@ msgstr "неожиданный ID кодировки %d для наборов с msgid "unexpected encoding ID %d for WIN character sets" msgstr "неожиданный ID кодировки %d для наборов символов WIN" -#: utils/mb/mbutils.c:298 utils/mb/mbutils.c:901 +#: utils/mb/mbutils.c:297 utils/mb/mbutils.c:900 #, c-format msgid "conversion between %s and %s is not supported" msgstr "преобразование %s <-> %s не поддерживается" -#: utils/mb/mbutils.c:403 utils/mb/mbutils.c:431 utils/mb/mbutils.c:816 -#: utils/mb/mbutils.c:843 +#: utils/mb/mbutils.c:402 utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 +#: utils/mb/mbutils.c:842 #, c-format msgid "String of %d bytes is too long for encoding conversion." msgstr "Строка из %d байт слишком длинна для преобразования кодировки." -#: utils/mb/mbutils.c:569 +#: utils/mb/mbutils.c:568 #, c-format msgid "invalid source encoding name \"%s\"" msgstr "неверное имя исходной кодировки: \"%s\"" -#: utils/mb/mbutils.c:574 +#: utils/mb/mbutils.c:573 #, c-format msgid "invalid destination encoding name \"%s\"" msgstr "неверное имя кодировки результата: \"%s\"" -#: utils/mb/mbutils.c:714 +#: utils/mb/mbutils.c:713 #, c-format msgid "invalid byte value for encoding \"%s\": 0x%02x" msgstr "недопустимое байтовое значение для кодировки \"%s\": 0x%02x" -#: utils/mb/mbutils.c:878 +#: utils/mb/mbutils.c:877 #, c-format msgid "invalid Unicode code point" msgstr "неверный код Unicode" -#: utils/mb/mbutils.c:1204 +#: utils/mb/mbutils.c:1201 #, c-format msgid "bind_textdomain_codeset failed" msgstr "ошибка в bind_textdomain_codeset" -#: utils/mb/mbutils.c:1725 +#: utils/mb/mbutils.c:1718 #, c-format msgid "invalid byte sequence for encoding \"%s\": %s" msgstr "неверная последовательность байт для кодировки \"%s\": %s" -#: utils/mb/mbutils.c:1758 +#: utils/mb/mbutils.c:1751 #, c-format msgid "" "character with byte sequence %s in encoding \"%s\" has no equivalent in " @@ -30050,14 +31413,14 @@ msgstr "пустое имя каталога конфигурации: \"%s\"" msgid "could not open configuration directory \"%s\": %m" msgstr "открыть каталог конфигурации \"%s\" не удалось: %m" -#: utils/misc/guc.c:115 +#: utils/misc/guc.c:122 msgid "" "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "" "Допустимые единицы измерения для этого параметра: \"B\", \"kB\", \"MB\", " "\"GB\" и \"TB\"." -#: utils/misc/guc.c:152 +#: utils/misc/guc.c:159 msgid "" "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", " "and \"d\"." @@ -30065,36 +31428,36 @@ msgstr "" "Допустимые единицы измерения для этого параметра: \"us\", \"ms\", \"s\", " "\"min\", \"h\" и \"d\"." -#: utils/misc/guc.c:421 +#: utils/misc/guc.c:430 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "нераспознанный параметр конфигурации \"%s\" в файле \"%s\", строке %d" -#: utils/misc/guc.c:461 utils/misc/guc.c:3411 utils/misc/guc.c:3655 -#: utils/misc/guc.c:3753 utils/misc/guc.c:3851 utils/misc/guc.c:3975 -#: utils/misc/guc.c:4078 +#: utils/misc/guc.c:470 utils/misc/guc.c:3504 utils/misc/guc.c:3748 +#: utils/misc/guc.c:3846 utils/misc/guc.c:3944 utils/misc/guc.c:4071 +#: utils/misc/guc.c:4212 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "параметр \"%s\" изменяется только при перезапуске сервера" -#: utils/misc/guc.c:497 +#: utils/misc/guc.c:506 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "" "параметр \"%s\" удалён из файла конфигурации, он принимает значение по " "умолчанию" -#: utils/misc/guc.c:562 +#: utils/misc/guc.c:571 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "параметр \"%s\" принял значение \"%s\"" -#: utils/misc/guc.c:604 +#: utils/misc/guc.c:613 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "файл конфигурации \"%s\" содержит ошибки" -#: utils/misc/guc.c:609 +#: utils/misc/guc.c:618 #, c-format msgid "" "configuration file \"%s\" contains errors; unaffected changes were applied" @@ -30102,17 +31465,17 @@ msgstr "" "файл конфигурации \"%s\" содержит ошибки; были применены не зависимые " "изменения" -#: utils/misc/guc.c:614 +#: utils/misc/guc.c:623 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "файл конфигурации \"%s\" содержит ошибки; изменения не были применены" -#: utils/misc/guc.c:1211 utils/misc/guc.c:1227 +#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "неверное имя параметра конфигурации: \"%s\"" -#: utils/misc/guc.c:1213 +#: utils/misc/guc.c:1141 #, c-format msgid "" "Custom parameter names must be two or more simple identifiers separated by " @@ -30121,22 +31484,22 @@ msgstr "" "Имена нестандартных параметров должны состоять из двух или более простых " "идентификаторов, разделённых точками." -#: utils/misc/guc.c:1229 +#: utils/misc/guc.c:1157 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\" — зарезервированный префикс." -#: utils/misc/guc.c:1243 +#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "нераспознанный параметр конфигурации: \"%s\"" -#: utils/misc/guc.c:1767 +#: utils/misc/guc.c:1802 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: ошибка доступа к каталогу \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: ошибка при обращении к каталогу \"%s\": %m\n" -#: utils/misc/guc.c:1772 +#: utils/misc/guc.c:1806 #, c-format msgid "" "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" @@ -30144,7 +31507,7 @@ msgstr "" "Запустите initdb или pg_basebackup для инициализации каталога данных " "PostgreSQL.\n" -#: utils/misc/guc.c:1796 +#: utils/misc/guc.c:1830 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" @@ -30155,12 +31518,12 @@ msgstr "" "Вы должны указать его расположение в параметре --config-file или -D, либо " "установить переменную окружения PGDATA.\n" -#: utils/misc/guc.c:1819 +#: utils/misc/guc.c:1853 #, c-format -msgid "%s: could not access the server configuration file \"%s\": %s\n" -msgstr "%s не может открыть файл конфигурации сервера \"%s\": %s\n" +msgid "%s: could not access the server configuration file \"%s\": %m\n" +msgstr "%s не может открыть файл конфигурации сервера \"%s\": %m\n" -#: utils/misc/guc.c:1847 +#: utils/misc/guc.c:1881 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -30171,7 +31534,7 @@ msgstr "" "Их расположение можно задать как значение \"data_directory\" в файле \"%s\", " "либо передать в параметре -D, либо установить переменную окружения PGDATA.\n" -#: utils/misc/guc.c:1899 +#: utils/misc/guc.c:1933 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" @@ -30182,7 +31545,7 @@ msgstr "" "Его расположение можно задать как значение \"hba_file\" в файле \"%s\", либо " "передать в параметре -D, либо установить переменную окружения PGDATA.\n" -#: utils/misc/guc.c:1930 +#: utils/misc/guc.c:1964 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" @@ -30193,124 +31556,138 @@ msgstr "" "Его расположение можно задать как значение \"ident_file\" в файле \"%s\", " "либо передать в параметре -D, либо установить переменную окружения PGDATA.\n" -#: utils/misc/guc.c:2896 +#: utils/misc/guc.c:2943 msgid "Value exceeds integer range." msgstr "Значение выходит за рамки целых чисел." -#: utils/misc/guc.c:3132 +#: utils/misc/guc.c:3185 #, c-format -msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)" -msgstr "%d%s%s вне диапазона, допустимого для параметра \"%s\" (%d .. %d)" +msgid "" +"%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" +msgstr "" +"%d%s%s вне диапазона, допустимого для параметра \"%s\" (%d%s%s .. %d%s%s)" -#: utils/misc/guc.c:3168 +#: utils/misc/guc.c:3226 #, c-format -msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)" -msgstr "%g%s%s вне диапазона, допустимого для параметра \"%s\" (%g .. %g)" +msgid "" +"%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" +msgstr "" +"%g%s%s вне диапазона, допустимого для параметра \"%s\" (%g%s%s .. %g%s%s)" -#: utils/misc/guc.c:3369 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3465 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "устанавливать параметры во время параллельных операций нельзя" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "параметр \"%s\" нельзя установить во время параллельной операции" -#: utils/misc/guc.c:3388 utils/misc/guc.c:4539 +#: utils/misc/guc.c:3481 utils/misc/guc.c:4696 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "параметр \"%s\" нельзя изменить" -#: utils/misc/guc.c:3421 +#: utils/misc/guc.c:3514 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "параметр \"%s\" нельзя изменить сейчас" -#: utils/misc/guc.c:3448 utils/misc/guc.c:3510 utils/misc/guc.c:4515 -#: utils/misc/guc.c:6563 +#: utils/misc/guc.c:3541 utils/misc/guc.c:3603 utils/misc/guc.c:4671 +#: utils/misc/guc.c:6756 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "нет прав для изменения параметра \"%s\"" -#: utils/misc/guc.c:3490 +#: utils/misc/guc.c:3583 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "параметр \"%s\" нельзя задать после установления соединения" -#: utils/misc/guc.c:3549 +#: utils/misc/guc.c:3642 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "" "параметр \"%s\" нельзя задать в функции с контекстом безопасности " "определившего" -#: utils/misc/guc.c:3570 +#: utils/misc/guc.c:3663 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "параметр \"%s\" нельзя сбросить" -#: utils/misc/guc.c:3577 +#: utils/misc/guc.c:3670 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "параметр \"%s\" нельзя задавать локально в функциях" -#: utils/misc/guc.c:4221 utils/misc/guc.c:4268 utils/misc/guc.c:5282 +#: utils/misc/guc.c:4370 utils/misc/guc.c:4418 utils/misc/guc.c:5450 #, c-format msgid "permission denied to examine \"%s\"" msgstr "нет прав для просмотра параметра \"%s\"" -#: utils/misc/guc.c:4222 utils/misc/guc.c:4269 utils/misc/guc.c:5283 +#: utils/misc/guc.c:4371 utils/misc/guc.c:4419 utils/misc/guc.c:5451 #, c-format msgid "" "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "Просматривать этот параметр могут только роли с правами роли \"%s\"." -#: utils/misc/guc.c:4505 +#: utils/misc/guc.c:4629 +#, c-format +msgid "ALTER SYSTEM is not allowed in this environment" +msgstr "команда ALTER SYSTEM запрещена в этом окружении" + +#: utils/misc/guc.c:4661 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "нет прав для выполнения ALTER SYSTEM RESET ALL" -#: utils/misc/guc.c:4571 +#: utils/misc/guc.c:4740 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "значение параметра для ALTER SYSTEM не должно быть многострочным" -#: utils/misc/guc.c:4617 +#: utils/misc/guc.c:4785 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "не удалось разобрать содержимое файла \"%s\"" -#: utils/misc/guc.c:4799 +#: utils/misc/guc.c:4967 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "попытка переопределить параметр \"%s\"" -#: utils/misc/guc.c:5138 +#: utils/misc/guc.c:5306 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "неверное имя параметра конфигурации: \"%s\", он удаляется" -#: utils/misc/guc.c:5140 +#: utils/misc/guc.c:5308 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "Теперь \"%s\" — зарезервированный префикс." -#: utils/misc/guc.c:6017 +#: utils/misc/guc.c:6179 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "при назначении параметру \"%s\" значения \"%s\"" -#: utils/misc/guc.c:6186 +#: utils/misc/guc.c:6348 #, c-format msgid "parameter \"%s\" could not be set" msgstr "параметр \"%s\" нельзя установить" -#: utils/misc/guc.c:6276 +#: utils/misc/guc.c:6438 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "не удалось разобрать значение параметра \"%s\"" -#: utils/misc/guc.c:6695 +#: utils/misc/guc.c:6888 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "неверное значение параметра \"%s\": %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "устанавливать параметры во время параллельных операций нельзя" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -30326,59 +31703,59 @@ msgstr "SET %s принимает только один аргумент" msgid "SET requires parameter name" msgstr "SET требует имя параметра" -#: utils/misc/guc_tables.c:662 +#: utils/misc/guc_tables.c:676 msgid "Ungrouped" msgstr "Разное" -#: utils/misc/guc_tables.c:664 +#: utils/misc/guc_tables.c:677 msgid "File Locations" msgstr "Расположения файлов" -#: utils/misc/guc_tables.c:666 +#: utils/misc/guc_tables.c:678 msgid "Connections and Authentication / Connection Settings" msgstr "Подключения и аутентификация / Параметры подключений" -#: utils/misc/guc_tables.c:668 +#: utils/misc/guc_tables.c:679 msgid "Connections and Authentication / TCP Settings" msgstr "Подключения и аутентификация / Параметры TCP" -#: utils/misc/guc_tables.c:670 +#: utils/misc/guc_tables.c:680 msgid "Connections and Authentication / Authentication" msgstr "Подключения и аутентификация / Аутентификация" -#: utils/misc/guc_tables.c:672 +#: utils/misc/guc_tables.c:681 msgid "Connections and Authentication / SSL" msgstr "Подключения и аутентификация / SSL" -#: utils/misc/guc_tables.c:674 +#: utils/misc/guc_tables.c:682 msgid "Resource Usage / Memory" msgstr "Использование ресурсов / Память" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:683 msgid "Resource Usage / Disk" msgstr "Использование ресурсов / Диск" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:684 msgid "Resource Usage / Kernel Resources" msgstr "Использование ресурсов / Ресурсы ядра" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:685 msgid "Resource Usage / Cost-Based Vacuum Delay" msgstr "Использование ресурсов / Задержка очистки по стоимости" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:686 msgid "Resource Usage / Background Writer" msgstr "Использование ресурсов / Фоновая запись" -#: utils/misc/guc_tables.c:684 +#: utils/misc/guc_tables.c:687 msgid "Resource Usage / Asynchronous Behavior" msgstr "Использование ресурсов / Асинхронное поведение" -#: utils/misc/guc_tables.c:686 +#: utils/misc/guc_tables.c:688 msgid "Write-Ahead Log / Settings" msgstr "Журнал WAL / Параметры" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:689 msgid "Write-Ahead Log / Checkpoints" msgstr "Журнал WAL / Контрольные точки" @@ -30386,210 +31763,214 @@ msgstr "Журнал WAL / Контрольные точки" msgid "Write-Ahead Log / Archiving" msgstr "Журнал WAL / Архивация" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:691 msgid "Write-Ahead Log / Recovery" msgstr "Журнал WAL / Восстановление" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:692 msgid "Write-Ahead Log / Archive Recovery" msgstr "Журнал WAL / Восстановление из архива" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:693 msgid "Write-Ahead Log / Recovery Target" msgstr "Журнал WAL / Цель восстановления" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:694 +msgid "Write-Ahead Log / Summarization" +msgstr "Журнал WAL / Обобщение" + +#: utils/misc/guc_tables.c:695 msgid "Replication / Sending Servers" msgstr "Репликация / Передающие серверы" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:696 msgid "Replication / Primary Server" msgstr "Репликация / Ведущий сервер" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:697 msgid "Replication / Standby Servers" msgstr "Репликация / Резервные серверы" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:698 msgid "Replication / Subscribers" msgstr "Репликация / Подписчики" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:699 msgid "Query Tuning / Planner Method Configuration" msgstr "Настройка запросов / Конфигурация методов планировщика" -#: utils/misc/guc_tables.c:708 +#: utils/misc/guc_tables.c:700 msgid "Query Tuning / Planner Cost Constants" msgstr "Настройка запросов / Константы стоимости для планировщика" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:701 msgid "Query Tuning / Genetic Query Optimizer" msgstr "Настройка запросов / Генетический оптимизатор запросов" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:702 msgid "Query Tuning / Other Planner Options" msgstr "Настройка запросов / Другие параметры планировщика" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:703 msgid "Reporting and Logging / Where to Log" msgstr "Отчёты и протоколы / Куда записывать" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:704 msgid "Reporting and Logging / When to Log" msgstr "Отчёты и протоколы / Когда записывать" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:705 msgid "Reporting and Logging / What to Log" msgstr "Отчёты и протоколы / Что записывать" -#: utils/misc/guc_tables.c:720 +#: utils/misc/guc_tables.c:706 msgid "Reporting and Logging / Process Title" msgstr "Отчёты и протоколы / Заголовок процесса" -#: utils/misc/guc_tables.c:722 +#: utils/misc/guc_tables.c:707 msgid "Statistics / Monitoring" msgstr "Статистика / Мониторинг" -#: utils/misc/guc_tables.c:724 +#: utils/misc/guc_tables.c:708 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "Статистика / Накопительная статистика по запросам и индексам" -#: utils/misc/guc_tables.c:726 +#: utils/misc/guc_tables.c:709 msgid "Autovacuum" msgstr "Автоочистка" -#: utils/misc/guc_tables.c:728 +#: utils/misc/guc_tables.c:710 msgid "Client Connection Defaults / Statement Behavior" msgstr "Параметры клиентских подключений по умолчанию / Поведение команд" -#: utils/misc/guc_tables.c:730 +#: utils/misc/guc_tables.c:711 msgid "Client Connection Defaults / Locale and Formatting" msgstr "" "Параметры клиентских подключений по умолчанию / Языковая среда и форматы" -#: utils/misc/guc_tables.c:732 +#: utils/misc/guc_tables.c:712 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "" "Параметры клиентских подключений по умолчанию / Предзагрузка разделяемых " "библиотек" -#: utils/misc/guc_tables.c:734 +#: utils/misc/guc_tables.c:713 msgid "Client Connection Defaults / Other Defaults" msgstr "Параметры клиентских подключений по умолчанию / Другие параметры" -#: utils/misc/guc_tables.c:736 +#: utils/misc/guc_tables.c:714 msgid "Lock Management" msgstr "Управление блокировками" -#: utils/misc/guc_tables.c:738 +#: utils/misc/guc_tables.c:715 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "Версия и совместимость платформ / Предыдущие версии PostgreSQL" -#: utils/misc/guc_tables.c:740 +#: utils/misc/guc_tables.c:716 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "Версия и совместимость платформ / Другие платформы и клиенты" -#: utils/misc/guc_tables.c:742 +#: utils/misc/guc_tables.c:717 msgid "Error Handling" msgstr "Обработка ошибок" -#: utils/misc/guc_tables.c:744 +#: utils/misc/guc_tables.c:718 msgid "Preset Options" msgstr "Предопределённые параметры" -#: utils/misc/guc_tables.c:746 +#: utils/misc/guc_tables.c:719 msgid "Customized Options" msgstr "Внесистемные параметры" -#: utils/misc/guc_tables.c:748 +#: utils/misc/guc_tables.c:720 msgid "Developer Options" msgstr "Параметры для разработчиков" -#: utils/misc/guc_tables.c:805 +#: utils/misc/guc_tables.c:775 msgid "Enables the planner's use of sequential-scan plans." msgstr "" "Разрешает планировщику использовать планы последовательного сканирования." -#: utils/misc/guc_tables.c:815 +#: utils/misc/guc_tables.c:785 msgid "Enables the planner's use of index-scan plans." msgstr "Разрешает планировщику использовать планы сканирования по индексу." -#: utils/misc/guc_tables.c:825 +#: utils/misc/guc_tables.c:795 msgid "Enables the planner's use of index-only-scan plans." msgstr "Разрешает планировщику использовать планы сканирования только индекса." -#: utils/misc/guc_tables.c:835 +#: utils/misc/guc_tables.c:805 msgid "Enables the planner's use of bitmap-scan plans." msgstr "" "Разрешает планировщику использовать планы сканирования по битовой карте." -#: utils/misc/guc_tables.c:845 +#: utils/misc/guc_tables.c:815 msgid "Enables the planner's use of TID scan plans." msgstr "Разрешает планировщику использовать планы сканирования TID." -#: utils/misc/guc_tables.c:855 +#: utils/misc/guc_tables.c:825 msgid "Enables the planner's use of explicit sort steps." msgstr "Разрешает планировщику использовать шаги с явной сортировкой." -#: utils/misc/guc_tables.c:865 +#: utils/misc/guc_tables.c:835 msgid "Enables the planner's use of incremental sort steps." msgstr "" "Разрешает планировщику использовать шаги с инкрементальной сортировкой." -#: utils/misc/guc_tables.c:875 +#: utils/misc/guc_tables.c:845 msgid "Enables the planner's use of hashed aggregation plans." msgstr "Разрешает планировщику использовать планы агрегирования по хешу." -#: utils/misc/guc_tables.c:885 +#: utils/misc/guc_tables.c:855 msgid "Enables the planner's use of materialization." msgstr "Разрешает планировщику использовать материализацию." # well-spelled: мемоизацию -#: utils/misc/guc_tables.c:895 +#: utils/misc/guc_tables.c:865 msgid "Enables the planner's use of memoization." msgstr "Разрешает планировщику использовать мемоизацию." -#: utils/misc/guc_tables.c:905 +#: utils/misc/guc_tables.c:875 msgid "Enables the planner's use of nested-loop join plans." msgstr "" "Разрешает планировщику использовать планы соединения с вложенными циклами." -#: utils/misc/guc_tables.c:915 +#: utils/misc/guc_tables.c:885 msgid "Enables the planner's use of merge join plans." msgstr "Разрешает планировщику использовать планы соединения слиянием." -#: utils/misc/guc_tables.c:925 +#: utils/misc/guc_tables.c:895 msgid "Enables the planner's use of hash join plans." msgstr "Разрешает планировщику использовать планы соединения по хешу." -#: utils/misc/guc_tables.c:935 +#: utils/misc/guc_tables.c:905 msgid "Enables the planner's use of gather merge plans." msgstr "Разрешает планировщику использовать планы сбора слиянием." -#: utils/misc/guc_tables.c:945 +#: utils/misc/guc_tables.c:915 msgid "Enables partitionwise join." msgstr "Включает соединения с учётом секционирования." -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:925 msgid "Enables partitionwise aggregation and grouping." msgstr "Включает агрегирование и группировку с учётом секционирования." -#: utils/misc/guc_tables.c:965 +#: utils/misc/guc_tables.c:935 msgid "Enables the planner's use of parallel append plans." msgstr "Разрешает планировщику использовать планы параллельного добавления." -#: utils/misc/guc_tables.c:975 +#: utils/misc/guc_tables.c:945 msgid "Enables the planner's use of parallel hash plans." msgstr "" "Разрешает планировщику использовать планы параллельного соединения по хешу." -#: utils/misc/guc_tables.c:985 +#: utils/misc/guc_tables.c:955 msgid "Enables plan-time and execution-time partition pruning." msgstr "" "Включает устранение секций во время планирования и во время выполнения " "запросов." -#: utils/misc/guc_tables.c:986 +#: utils/misc/guc_tables.c:956 msgid "" "Allows the query planner and executor to compare partition bounds to " "conditions in the query to determine which partitions must be scanned." @@ -30597,7 +31978,7 @@ msgstr "" "Разрешает планировщику и исполнителю запросов сопоставлять границы секций с " "условиями в запросе и выделять отдельные секции для сканирования." -#: utils/misc/guc_tables.c:997 +#: utils/misc/guc_tables.c:967 msgid "" "Enables the planner's ability to produce plans that provide presorted input " "for ORDER BY / DISTINCT aggregate functions." @@ -30605,7 +31986,7 @@ msgstr "" "Включает в планировщике возможность формировать планы, подающие ранее " "сортированные данные на вход агрегирующим функциям с ORDER BY / DISTINCT." -#: utils/misc/guc_tables.c:1000 +#: utils/misc/guc_tables.c:970 msgid "" "Allows the query planner to build plans that provide presorted input for " "aggregate functions with an ORDER BY / DISTINCT clause. When disabled, " @@ -30616,49 +31997,66 @@ msgstr "" "данные. Когда этот параметр отключён, во время выполнения всегда неявно " "производится сортировка." -#: utils/misc/guc_tables.c:1012 +#: utils/misc/guc_tables.c:982 msgid "Enables the planner's use of async append plans." msgstr "Разрешает планировщику использовать планы асинхронного добавления." -#: utils/misc/guc_tables.c:1022 +#: utils/misc/guc_tables.c:992 +msgid "Enables reordering of GROUP BY keys." +msgstr "Включает переупорядочивание ключей GROUP BY." + +#: utils/misc/guc_tables.c:1002 msgid "Enables genetic query optimization." msgstr "Включает генетическую оптимизацию запросов." -#: utils/misc/guc_tables.c:1023 +#: utils/misc/guc_tables.c:1003 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "Этот алгоритм пытается построить план без полного перебора." -#: utils/misc/guc_tables.c:1034 +#: utils/misc/guc_tables.c:1017 msgid "Shows whether the current user is a superuser." msgstr "Показывает, является ли текущий пользователь суперпользователем." -#: utils/misc/guc_tables.c:1044 +#: utils/misc/guc_tables.c:1032 +msgid "Allows running the ALTER SYSTEM command." +msgstr "Разрешает выполнять команду ALTER SYSTEM." + +#: utils/misc/guc_tables.c:1033 +msgid "" +"Can be set to off for environments where global configuration changes should " +"be made using a different method." +msgstr "" +"Может быть выключен в окружениях, где изменения глобальной конфигурации " +"должны производиться другим методом." + +#: utils/misc/guc_tables.c:1043 msgid "Enables advertising the server via Bonjour." msgstr "Включает объявление сервера посредством Bonjour." -#: utils/misc/guc_tables.c:1053 +#: utils/misc/guc_tables.c:1052 msgid "Collects transaction commit time." msgstr "Записывает время фиксации транзакций." -#: utils/misc/guc_tables.c:1062 +#: utils/misc/guc_tables.c:1061 msgid "Enables SSL connections." msgstr "Разрешает SSL-подключения." -#: utils/misc/guc_tables.c:1071 -msgid "Controls whether ssl_passphrase_command is called during server reload." +#: utils/misc/guc_tables.c:1070 +msgid "" +"Controls whether \"ssl_passphrase_command\" is called during server reload." msgstr "" -"Определяет, будет ли вызываться ssl_passphrase_command при перезагрузке " +"Определяет, будет ли вызываться \"ssl_passphrase_command\" при перезагрузке " "сервера." -#: utils/misc/guc_tables.c:1080 +#: utils/misc/guc_tables.c:1079 msgid "Give priority to server ciphersuite order." msgstr "Назначает более приоритетным набор шифров сервера." -#: utils/misc/guc_tables.c:1089 +#: utils/misc/guc_tables.c:1088 msgid "Forces synchronization of updates to disk." msgstr "Принудительная запись изменений на диск." -#: utils/misc/guc_tables.c:1090 +#: utils/misc/guc_tables.c:1089 msgid "" "The server will use the fsync() system call in several places to make sure " "that updates are physically written to disk. This ensures that a database " @@ -30669,11 +32067,11 @@ msgstr "" "обеспечивающую физическую запись данных на диск. Тем самым гарантируется, " "что кластер БД придёт в целостное состояние после отказа ОС или оборудования." -#: utils/misc/guc_tables.c:1101 +#: utils/misc/guc_tables.c:1100 msgid "Continues processing after a checksum failure." msgstr "Продолжает обработку при ошибке контрольной суммы." -#: utils/misc/guc_tables.c:1102 +#: utils/misc/guc_tables.c:1101 msgid "" "Detection of a checksum failure normally causes PostgreSQL to report an " "error, aborting the current transaction. Setting ignore_checksum_failure to " @@ -30687,34 +32085,34 @@ msgstr "" "что может привести к сбоям или другим серьёзным проблемам. Это имеет место, " "только если включён контроль целостности страниц." -#: utils/misc/guc_tables.c:1116 +#: utils/misc/guc_tables.c:1115 msgid "Continues processing past damaged page headers." msgstr "Продолжает обработку при повреждении заголовков страниц." -#: utils/misc/guc_tables.c:1117 +#: utils/misc/guc_tables.c:1116 msgid "" "Detection of a damaged page header normally causes PostgreSQL to report an " -"error, aborting the current transaction. Setting zero_damaged_pages to true " -"causes the system to instead report a warning, zero out the damaged page, " -"and continue processing. This behavior will destroy data, namely all the " -"rows on the damaged page." +"error, aborting the current transaction. Setting \"zero_damaged_pages\" to " +"true causes the system to instead report a warning, zero out the damaged " +"page, and continue processing. This behavior will destroy data, namely all " +"the rows on the damaged page." msgstr "" "Обнаруживая повреждённый заголовок страницы, PostgreSQL обычно сообщает об " -"ошибке и прерывает текущую транзакцию. Но если zero_damaged_pages равен " +"ошибке и прерывает текущую транзакцию. Но если \"zero_damaged_pages\" равен " "true, система выдаст предупреждение, обнулит повреждённую страницу и " "продолжит работу. Это приведёт к потере данных, а именно строк в " "повреждённой странице." -#: utils/misc/guc_tables.c:1130 +#: utils/misc/guc_tables.c:1129 msgid "Continues recovery after an invalid pages failure." msgstr "" "Продолжает восстановление после ошибок, связанных с неправильными страницами." -#: utils/misc/guc_tables.c:1131 +#: utils/misc/guc_tables.c:1130 msgid "" "Detection of WAL records having references to invalid pages during recovery " "causes PostgreSQL to raise a PANIC-level error, aborting the recovery. " -"Setting ignore_invalid_pages to true causes the system to ignore invalid " +"Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid " "page references in WAL records (but still report a warning), and continue " "recovery. This behavior may cause crashes, data loss, propagate or hide " "corruption, or other serious problems. Only has an effect during recovery or " @@ -30722,19 +32120,19 @@ msgid "" msgstr "" "Обнаруживая в записях WAL ссылки на неправильные страницы во время " "восстановления, PostgreSQL выдаёт ошибку уровня ПАНИКА и прерывает " -"восстановление. Если ignore_invalid_pages равен true, система игнорирует " +"восстановление. Если \"ignore_invalid_pages\" равен true, система игнорирует " "такие некорректные ссылки (но всё же выдаёт предупреждение) и продолжает " "восстановление. Это может привести к краху сервера, потере данных, " "распространению или сокрытию повреждения данных и другим серьёзным " "проблемам. Данный параметр действует только при восстановлении или в режиме " "резервного сервера." -#: utils/misc/guc_tables.c:1149 +#: utils/misc/guc_tables.c:1148 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "" "Запись полных страниц в WAL при первом изменении после контрольной точки." -#: utils/misc/guc_tables.c:1150 +#: utils/misc/guc_tables.c:1149 msgid "" "A page write in process during an operating system crash might be only " "partially written to disk. During recovery, the row changes stored in WAL " @@ -30747,7 +32145,7 @@ msgstr "" "при первом изменении после контрольной точки, что позволяет полностью " "восстановить данные." -#: utils/misc/guc_tables.c:1163 +#: utils/misc/guc_tables.c:1162 msgid "" "Writes full pages to WAL when first modified after a checkpoint, even for a " "non-critical modification." @@ -30755,93 +32153,98 @@ msgstr "" "Запись полных страниц в WAL при первом изменении после контрольной точки, " "даже при некритическом изменении." -#: utils/misc/guc_tables.c:1173 +#: utils/misc/guc_tables.c:1172 msgid "Writes zeroes to new WAL files before first use." msgstr "Записывать нули в новые файлы WAL перед первым использованием." -#: utils/misc/guc_tables.c:1183 +#: utils/misc/guc_tables.c:1182 msgid "Recycles WAL files by renaming them." msgstr "Перерабатывать файлы WAL, производя переименование." -#: utils/misc/guc_tables.c:1193 +#: utils/misc/guc_tables.c:1192 msgid "Logs each checkpoint." msgstr "Протоколировать каждую контрольную точку." -#: utils/misc/guc_tables.c:1202 +#: utils/misc/guc_tables.c:1201 msgid "Logs each successful connection." msgstr "Протоколировать устанавливаемые соединения." -#: utils/misc/guc_tables.c:1211 +#: utils/misc/guc_tables.c:1210 +msgid "Logs details of pre-authentication connection handshake." +msgstr "" +"Протоколировать сообщения об установлении соединения до аутентификации." + +#: utils/misc/guc_tables.c:1220 msgid "Logs end of a session, including duration." msgstr "Протоколировать конец сеанса, отмечая длительность." -#: utils/misc/guc_tables.c:1220 +#: utils/misc/guc_tables.c:1229 msgid "Logs each replication command." msgstr "Протоколировать каждую команду репликации." -#: utils/misc/guc_tables.c:1229 +#: utils/misc/guc_tables.c:1238 msgid "Shows whether the running server has assertion checks enabled." msgstr "Показывает, включены ли проверки истинности на работающем сервере." -#: utils/misc/guc_tables.c:1240 +#: utils/misc/guc_tables.c:1249 msgid "Terminate session on any error." msgstr "Завершать сеансы при любой ошибке." -#: utils/misc/guc_tables.c:1249 +#: utils/misc/guc_tables.c:1258 msgid "Reinitialize server after backend crash." msgstr "Перезапускать систему БД при аварии серверного процесса." -#: utils/misc/guc_tables.c:1258 +#: utils/misc/guc_tables.c:1267 msgid "Remove temporary files after backend crash." msgstr "Удалять временные файлы после аварии обслуживающего процесса." -#: utils/misc/guc_tables.c:1268 +#: utils/misc/guc_tables.c:1277 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "" "Посылать дочерним процессам SIGABRT, а не SIGQUIT при сбое серверного " "процесса." -#: utils/misc/guc_tables.c:1278 +#: utils/misc/guc_tables.c:1287 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "Посылать SIGABRT, а не SIGKILL зависшим дочерним процессам." -#: utils/misc/guc_tables.c:1289 +#: utils/misc/guc_tables.c:1298 msgid "Logs the duration of each completed SQL statement." msgstr "Протоколировать длительность каждого выполненного SQL-оператора." -#: utils/misc/guc_tables.c:1298 +#: utils/misc/guc_tables.c:1307 msgid "Logs each query's parse tree." msgstr "Протоколировать дерево разбора для каждого запроса." -#: utils/misc/guc_tables.c:1307 +#: utils/misc/guc_tables.c:1316 msgid "Logs each query's rewritten parse tree." msgstr "Протоколировать перезаписанное дерево разбора для каждого запроса." -#: utils/misc/guc_tables.c:1316 +#: utils/misc/guc_tables.c:1325 msgid "Logs each query's execution plan." msgstr "Протоколировать план выполнения каждого запроса." -#: utils/misc/guc_tables.c:1325 +#: utils/misc/guc_tables.c:1334 msgid "Indents parse and plan tree displays." msgstr "Отступы при отображении деревьев разбора и плана запросов." -#: utils/misc/guc_tables.c:1334 +#: utils/misc/guc_tables.c:1343 msgid "Writes parser performance statistics to the server log." msgstr "Запись статистики разбора запросов в протокол сервера." -#: utils/misc/guc_tables.c:1343 +#: utils/misc/guc_tables.c:1352 msgid "Writes planner performance statistics to the server log." msgstr "Запись статистики планирования в протокол сервера." -#: utils/misc/guc_tables.c:1352 +#: utils/misc/guc_tables.c:1361 msgid "Writes executor performance statistics to the server log." msgstr "Запись статистики выполнения запросов в протокол сервера." -#: utils/misc/guc_tables.c:1361 +#: utils/misc/guc_tables.c:1370 msgid "Writes cumulative performance statistics to the server log." msgstr "Запись общей статистики производительности в протокол сервера." -#: utils/misc/guc_tables.c:1371 +#: utils/misc/guc_tables.c:1380 msgid "" "Logs system resource usage statistics (memory and CPU) on various B-tree " "operations." @@ -30849,11 +32252,11 @@ msgstr "" "Фиксировать статистику использования системных ресурсов (памяти и " "процессора) при различных операциях с b-деревом." -#: utils/misc/guc_tables.c:1383 +#: utils/misc/guc_tables.c:1392 msgid "Collects information about executing commands." msgstr "Собирает информацию о выполняющихся командах." -#: utils/misc/guc_tables.c:1384 +#: utils/misc/guc_tables.c:1393 msgid "" "Enables the collection of information on the currently executing command of " "each session, along with the time at which that command began execution." @@ -30861,70 +32264,70 @@ msgstr "" "Включает сбор информации о командах, выполняющихся во всех сеансах, а также " "время запуска команды." -#: utils/misc/guc_tables.c:1394 +#: utils/misc/guc_tables.c:1403 msgid "Collects statistics on database activity." msgstr "Собирает статистику активности в БД." -#: utils/misc/guc_tables.c:1403 +#: utils/misc/guc_tables.c:1412 msgid "Collects timing statistics for database I/O activity." msgstr "Собирает статистику по времени активности ввода/вывода." -#: utils/misc/guc_tables.c:1412 +#: utils/misc/guc_tables.c:1421 msgid "Collects timing statistics for WAL I/O activity." msgstr "Собирает статистику по времени активности ввода/вывода WAL." -#: utils/misc/guc_tables.c:1422 +#: utils/misc/guc_tables.c:1431 msgid "Updates the process title to show the active SQL command." msgstr "Выводит в заголовок процесса активную SQL-команду." -#: utils/misc/guc_tables.c:1423 +#: utils/misc/guc_tables.c:1432 msgid "" "Enables updating of the process title every time a new SQL command is " "received by the server." msgstr "Отражает в заголовке процесса каждую SQL-команду, поступающую серверу." -#: utils/misc/guc_tables.c:1432 +#: utils/misc/guc_tables.c:1441 msgid "Starts the autovacuum subprocess." msgstr "Запускает подпроцесс автоочистки." -#: utils/misc/guc_tables.c:1442 +#: utils/misc/guc_tables.c:1451 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "Генерирует отладочные сообщения для LISTEN и NOTIFY." -#: utils/misc/guc_tables.c:1454 +#: utils/misc/guc_tables.c:1463 msgid "Emits information about lock usage." msgstr "Выдавать информацию о применяемых блокировках." -#: utils/misc/guc_tables.c:1464 +#: utils/misc/guc_tables.c:1473 msgid "Emits information about user lock usage." msgstr "Выдавать информацию о применяемых пользовательских блокировках." -#: utils/misc/guc_tables.c:1474 +#: utils/misc/guc_tables.c:1483 msgid "Emits information about lightweight lock usage." msgstr "Выдавать информацию о применяемых лёгких блокировках." -#: utils/misc/guc_tables.c:1484 +#: utils/misc/guc_tables.c:1493 msgid "" "Dumps information about all current locks when a deadlock timeout occurs." msgstr "" "Выводить информацию обо всех текущих блокировках в случае тайм-аута при " "взаимоблокировке." -#: utils/misc/guc_tables.c:1496 +#: utils/misc/guc_tables.c:1505 msgid "Logs long lock waits." msgstr "Протоколировать длительные ожидания в блокировках." -#: utils/misc/guc_tables.c:1505 +#: utils/misc/guc_tables.c:1514 msgid "Logs standby recovery conflict waits." msgstr "" "Протоколировать события ожидания разрешения конфликтов при восстановлении на " "ведомом." -#: utils/misc/guc_tables.c:1514 +#: utils/misc/guc_tables.c:1523 msgid "Logs the host name in the connection logs." msgstr "Записывать имя узла в протоколы подключений." -#: utils/misc/guc_tables.c:1515 +#: utils/misc/guc_tables.c:1524 msgid "" "By default, connection logs only show the IP address of the connecting host. " "If you want them to show the host name you can turn this on, but depending " @@ -30936,11 +32339,11 @@ msgstr "" "параметр, но учтите, что это может значительно повлиять на " "производительность." -#: utils/misc/guc_tables.c:1526 +#: utils/misc/guc_tables.c:1535 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "Обрабатывать \"expr=NULL\" как \"expr IS NULL\"." -#: utils/misc/guc_tables.c:1527 +#: utils/misc/guc_tables.c:1536 msgid "" "When turned on, expressions of the form expr = NULL (or NULL = expr) are " "treated as expr IS NULL, that is, they return true if expr evaluates to the " @@ -30952,10 +32355,6 @@ msgstr "" "совпадает с NULL, и false в противном случае. По правилам expr = NULL всегда " "должно возвращать null (неопределённость)." -#: utils/misc/guc_tables.c:1539 -msgid "Enables per-database user names." -msgstr "Включает связывание имён пользователей с базами данных." - #: utils/misc/guc_tables.c:1548 msgid "Sets the default read-only status of new transactions." msgstr "" @@ -31012,10 +32411,10 @@ msgstr "" #: utils/misc/guc_tables.c:1632 msgid "" -"Start a subprocess to capture stderr output and/or csvlogs into log files." +"Start a subprocess to capture stderr, csvlog and/or jsonlog into log files." msgstr "" -"Запускает подпроцесс для чтения stderr и/или csv-файлов и записи в файлы " -"протоколов." +"Запускает подпроцесс для чтения stderr, csvlog и/или jsonlog и записи в " +"файлы протоколов." #: utils/misc/guc_tables.c:1641 msgid "Truncate existing log files of same name during log rotation." @@ -31071,11 +32470,17 @@ msgid "Sets whether to include or exclude transaction with recovery target." msgstr "Определяет, включать ли транзакцию в целевую точку восстановления." #: utils/misc/guc_tables.c:1778 +msgid "Starts the WAL summarizer process to enable incremental backup." +msgstr "" +"Запускает процесс обобщения WAL, необходимый для инкрементального " +"копирования." + +#: utils/misc/guc_tables.c:1788 msgid "Allows connections and queries during recovery." msgstr "" "Разрешает принимать новые подключения и запросы в процессе восстановления." -#: utils/misc/guc_tables.c:1788 +#: utils/misc/guc_tables.c:1798 msgid "" "Allows feedback from a hot standby to the primary that will avoid query " "conflicts." @@ -31083,19 +32488,19 @@ msgstr "" "Разрешает обратную связь сервера горячего резерва с основным для " "предотвращения конфликтов при длительных запросах." -#: utils/misc/guc_tables.c:1798 +#: utils/misc/guc_tables.c:1808 msgid "Shows whether hot standby is currently active." msgstr "Показывает, активен ли в настоящий момент режим горячего резерва." -#: utils/misc/guc_tables.c:1809 +#: utils/misc/guc_tables.c:1819 msgid "Allows modifications of the structure of system tables." msgstr "Разрешает модифицировать структуру системных таблиц." -#: utils/misc/guc_tables.c:1820 +#: utils/misc/guc_tables.c:1830 msgid "Disables reading from system indexes." msgstr "Запрещает использование системных индексов." -#: utils/misc/guc_tables.c:1821 +#: utils/misc/guc_tables.c:1831 msgid "" "It does not prevent updating the indexes, so it is safe to use. The worst " "consequence is slowness." @@ -31103,20 +32508,20 @@ msgstr "" "При этом индексы продолжают обновляться, так что данное поведение безопасно. " "Худшее следствие - замедление." -#: utils/misc/guc_tables.c:1832 +#: utils/misc/guc_tables.c:1842 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "" "Позволяет размещать табличные пространства внутри pg_tblspc; предназначается " "для тестирования." -#: utils/misc/guc_tables.c:1843 +#: utils/misc/guc_tables.c:1853 msgid "" "Enables backward compatibility mode for privilege checks on large objects." msgstr "" "Включает режим обратной совместимости при проверке привилегий для больших " "объектов." -#: utils/misc/guc_tables.c:1844 +#: utils/misc/guc_tables.c:1854 msgid "" "Skips privilege checks when reading or modifying large objects, for " "compatibility with PostgreSQL releases prior to 9.0." @@ -31124,66 +32529,66 @@ msgstr "" "Пропускает проверки привилегий при чтении или изменении больших объектов " "(для совместимости с версиями PostgreSQL до 9.0)." -#: utils/misc/guc_tables.c:1854 +#: utils/misc/guc_tables.c:1864 msgid "When generating SQL fragments, quote all identifiers." msgstr "" "Генерируя SQL-фрагменты, заключать все идентификаторы в двойные кавычки." -#: utils/misc/guc_tables.c:1864 +#: utils/misc/guc_tables.c:1874 msgid "Shows whether data checksums are turned on for this cluster." msgstr "Показывает, включён ли в этом кластере контроль целостности данных." -#: utils/misc/guc_tables.c:1875 +#: utils/misc/guc_tables.c:1885 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "" "Добавлять последовательный номер в сообщения syslog во избежание подавления " "повторов." -#: utils/misc/guc_tables.c:1885 +#: utils/misc/guc_tables.c:1895 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "" "Разбивать сообщения, передаваемые в syslog, по строкам размером не больше " "1024 байт." -#: utils/misc/guc_tables.c:1895 +#: utils/misc/guc_tables.c:1905 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "" "Определяет, будут ли узлы сбора и сбора слиянием также выполнять подпланы." -#: utils/misc/guc_tables.c:1896 +#: utils/misc/guc_tables.c:1906 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "" "Должны ли узлы сбора также выполнять подпланы или только собирать кортежи?" -#: utils/misc/guc_tables.c:1906 +#: utils/misc/guc_tables.c:1916 msgid "Allow JIT compilation." msgstr "Включить JIT-компиляцию." -#: utils/misc/guc_tables.c:1917 +#: utils/misc/guc_tables.c:1927 msgid "Register JIT-compiled functions with debugger." msgstr "Регистрировать JIT-скомпилированные функции в отладчике." -#: utils/misc/guc_tables.c:1934 +#: utils/misc/guc_tables.c:1944 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "Выводить битовый код LLVM для облегчения отладки JIT." -#: utils/misc/guc_tables.c:1945 +#: utils/misc/guc_tables.c:1955 msgid "Allow JIT compilation of expressions." msgstr "Включить JIT-компиляцию выражений." -#: utils/misc/guc_tables.c:1956 +#: utils/misc/guc_tables.c:1966 msgid "Register JIT-compiled functions with perf profiler." msgstr "Регистрировать JIT-компилируемые функции в профилировщике perf." -#: utils/misc/guc_tables.c:1973 +#: utils/misc/guc_tables.c:1983 msgid "Allow JIT compilation of tuple deforming." msgstr "Разрешить JIT-компиляцию кода преобразования кортежей." -#: utils/misc/guc_tables.c:1984 +#: utils/misc/guc_tables.c:1994 msgid "Whether to continue running after a failure to sync data files." msgstr "Продолжать работу после ошибки при сохранении файлов данных на диске." -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2003 msgid "" "Sets whether a WAL receiver should create a temporary replication slot if no " "permanent slot is configured." @@ -31191,28 +32596,46 @@ msgstr "" "Определяет, должен ли приёмник WAL создавать временный слот репликации, если " "не настроен постоянный слот." -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2012 +msgid "Enables event triggers." +msgstr "Включает событийные триггеры." + +#: utils/misc/guc_tables.c:2013 +msgid "When enabled, event triggers will fire for all applicable statements." +msgstr "" +"При включении событийные триггеры будут срабатывать для всех операторов, для " +"которых применимы." + +#: utils/misc/guc_tables.c:2022 +msgid "" +"Enables a physical standby to synchronize logical failover replication slots " +"from the primary server." +msgstr "" +"Позволяет физической реплике синхронизировать переносимые слоты логической " +"репликации с ведущего сервера." + +#: utils/misc/guc_tables.c:2040 msgid "" "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "" "Задаёт время задержки перед принудительным переключением на следующий файл " "WAL." -#: utils/misc/guc_tables.c:2022 +#: utils/misc/guc_tables.c:2051 msgid "" "Sets the amount of time to wait after authentication on connection startup." msgstr "" "Задаёт время ожидания после аутентификации при установлении соединения." -#: utils/misc/guc_tables.c:2024 utils/misc/guc_tables.c:2658 +#: utils/misc/guc_tables.c:2053 utils/misc/guc_tables.c:2780 msgid "This allows attaching a debugger to the process." msgstr "Это позволяет подключить к процессу отладчик." -#: utils/misc/guc_tables.c:2033 +#: utils/misc/guc_tables.c:2062 msgid "Sets the default statistics target." msgstr "Устанавливает ориентир статистики по умолчанию." -#: utils/misc/guc_tables.c:2034 +#: utils/misc/guc_tables.c:2063 msgid "" "This applies to table columns that have not had a column-specific target set " "via ALTER TABLE SET STATISTICS." @@ -31220,13 +32643,13 @@ msgstr "" "Это значение распространяется на столбцы таблицы, для которых ориентир " "статистики не задан явно через ALTER TABLE SET STATISTICS." -#: utils/misc/guc_tables.c:2043 +#: utils/misc/guc_tables.c:2072 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "" "Задаёт предел для списка FROM, при превышении которого подзапросы не " "сворачиваются." -#: utils/misc/guc_tables.c:2045 +#: utils/misc/guc_tables.c:2074 msgid "" "The planner will merge subqueries into upper queries if the resulting FROM " "list would have no more than this many items." @@ -31234,13 +32657,13 @@ msgstr "" "Планировщик объединит вложенные запросы с внешними, если в полученном списке " "FROM будет не больше заданного числа элементов." -#: utils/misc/guc_tables.c:2056 +#: utils/misc/guc_tables.c:2085 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "" "Задаёт предел для списка FROM, при превышении которого конструкции JOIN " "сохраняются." -#: utils/misc/guc_tables.c:2058 +#: utils/misc/guc_tables.c:2087 msgid "" "The planner will flatten explicit JOIN constructs into lists of FROM items " "whenever a list of no more than this many items would result." @@ -31248,34 +32671,34 @@ msgstr "" "Планировщик будет сносить явные конструкции JOIN в списки FROM, пока в " "результирующем списке не больше заданного числа элементов." -#: utils/misc/guc_tables.c:2069 +#: utils/misc/guc_tables.c:2098 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "" "Задаёт предел для списка FROM, при превышении которого применяется GEQO." -#: utils/misc/guc_tables.c:2079 +#: utils/misc/guc_tables.c:2108 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "" "GEQO: оценка усилий для планирования, задающая значения по умолчанию для " "других параметров GEQO." -#: utils/misc/guc_tables.c:2089 +#: utils/misc/guc_tables.c:2118 msgid "GEQO: number of individuals in the population." msgstr "GEQO: число особей в популяции." -#: utils/misc/guc_tables.c:2090 utils/misc/guc_tables.c:2100 +#: utils/misc/guc_tables.c:2119 utils/misc/guc_tables.c:2129 msgid "Zero selects a suitable default value." msgstr "При нуле выбирается подходящее значение по умолчанию." -#: utils/misc/guc_tables.c:2099 +#: utils/misc/guc_tables.c:2128 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: число итераций алгоритма." -#: utils/misc/guc_tables.c:2111 +#: utils/misc/guc_tables.c:2140 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "Задаёт интервал ожидания в блокировке до проверки на взаимоблокировку." -#: utils/misc/guc_tables.c:2122 +#: utils/misc/guc_tables.c:2151 msgid "" "Sets the maximum delay before canceling queries when a hot standby server is " "processing archived WAL data." @@ -31283,7 +32706,7 @@ msgstr "" "Задаёт максимальную задержку до отмены запроса, когда сервер горячего " "резерва обрабатывает данные WAL из архива." -#: utils/misc/guc_tables.c:2133 +#: utils/misc/guc_tables.c:2162 msgid "" "Sets the maximum delay before canceling queries when a hot standby server is " "processing streamed WAL data." @@ -31291,13 +32714,13 @@ msgstr "" "Задаёт максимальную задержку до отмены запроса, когда сервер горячего " "резерва обрабатывает данные WAL из потока." -#: utils/misc/guc_tables.c:2144 +#: utils/misc/guc_tables.c:2173 msgid "Sets the minimum delay for applying changes during recovery." msgstr "" "Задаёт минимальную задержку для применения изменений в процессе " "восстановления." -#: utils/misc/guc_tables.c:2155 +#: utils/misc/guc_tables.c:2184 msgid "" "Sets the maximum interval between WAL receiver status reports to the sending " "server." @@ -31305,21 +32728,21 @@ msgstr "" "Задаёт максимальный интервал между отчётами о состоянии приёмника WAL, " "отправляемыми передающему серверу." -#: utils/misc/guc_tables.c:2166 +#: utils/misc/guc_tables.c:2195 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "" "Задаёт предельное время ожидания для получения данных от передающего сервера." -#: utils/misc/guc_tables.c:2177 +#: utils/misc/guc_tables.c:2206 msgid "Sets the maximum number of concurrent connections." msgstr "Задаёт максимально возможное число подключений." -#: utils/misc/guc_tables.c:2188 +#: utils/misc/guc_tables.c:2217 msgid "Sets the number of connection slots reserved for superusers." msgstr "" "Определяет, сколько слотов подключений забронировано для суперпользователей." -#: utils/misc/guc_tables.c:2198 +#: utils/misc/guc_tables.c:2227 msgid "" "Sets the number of connection slots reserved for roles with privileges of " "pg_use_reserved_connections." @@ -31327,19 +32750,19 @@ msgstr "" "Определяет, сколько слотов подключений забронировано для ролей с правом " "pg_use_reserved_connections." -#: utils/misc/guc_tables.c:2209 +#: utils/misc/guc_tables.c:2238 msgid "Amount of dynamic shared memory reserved at startup." msgstr "Объём динамической разделяемой памяти, резервируемый при запуске." -#: utils/misc/guc_tables.c:2224 +#: utils/misc/guc_tables.c:2253 msgid "Sets the number of shared memory buffers used by the server." msgstr "Задаёт количество буферов в разделяемой памяти, используемых сервером." -#: utils/misc/guc_tables.c:2235 +#: utils/misc/guc_tables.c:2264 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "Задаёт размер пула буферов для операций VACUUM, ANALYZE и автоочистки." -#: utils/misc/guc_tables.c:2246 +#: utils/misc/guc_tables.c:2275 msgid "" "Shows the size of the server's main shared memory area (rounded up to the " "nearest MB)." @@ -31347,29 +32770,90 @@ msgstr "" "Показывает объём основной области общей памяти сервера (округляется до " "ближайшего значения в мегабайтах)." -#: utils/misc/guc_tables.c:2257 +#: utils/misc/guc_tables.c:2286 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "" "Показывает количество огромных страниц, необходимое для основной области " "общей памяти." -#: utils/misc/guc_tables.c:2258 +#: utils/misc/guc_tables.c:2287 msgid "-1 indicates that the value could not be determined." msgstr "Значение -1 показывает, что определить это количество не удалось." -#: utils/misc/guc_tables.c:2268 +#: utils/misc/guc_tables.c:2297 +msgid "" +"Sets the size of the dedicated buffer pool used for the commit timestamp " +"cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования времени " +"фиксации транзакций." + +#: utils/misc/guc_tables.c:2298 utils/misc/guc_tables.c:2353 +#: utils/misc/guc_tables.c:2364 +msgid "" +"Specify 0 to have this value determined as a fraction of shared_buffers." +msgstr "При значении 0 это число определяется как процент от shared_buffers." + +#: utils/misc/guc_tables.c:2308 +msgid "" +"Sets the size of the dedicated buffer pool used for the MultiXact member " +"cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования " +"членства в MultiXact." + +#: utils/misc/guc_tables.c:2319 +msgid "" +"Sets the size of the dedicated buffer pool used for the MultiXact offset " +"cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования " +"смещений MultiXact." + +#: utils/misc/guc_tables.c:2330 +msgid "" +"Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY " +"message cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования " +"сообщений LISTEN/NOTIFY." + +#: utils/misc/guc_tables.c:2341 +msgid "" +"Sets the size of the dedicated buffer pool used for the serializable " +"transaction cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования " +"сериализуемых транзакций." + +#: utils/misc/guc_tables.c:2352 +msgid "" +"Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования " +"подтранзакций." + +#: utils/misc/guc_tables.c:2363 +msgid "" +"Sets the size of the dedicated buffer pool used for the transaction status " +"cache." +msgstr "" +"Задаёт размер выделенного пула буферов, используемых для кеширования статуса " +"транзакций." + +#: utils/misc/guc_tables.c:2374 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "Задаёт предельное число временных буферов на один сеанс." -#: utils/misc/guc_tables.c:2279 +#: utils/misc/guc_tables.c:2385 msgid "Sets the TCP port the server listens on." msgstr "Задаёт TCP-порт для работы сервера." -#: utils/misc/guc_tables.c:2289 +#: utils/misc/guc_tables.c:2395 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Задаёт права доступа для Unix-сокета." -#: utils/misc/guc_tables.c:2290 +#: utils/misc/guc_tables.c:2396 msgid "" "Unix-domain sockets use the usual Unix file system permission set. The " "parameter value is expected to be a numeric mode specification in the form " @@ -31381,11 +32865,11 @@ msgstr "" "воспринимаемом системными функциями chmod и umask. (Чтобы использовать " "привычный восьмеричный формат, добавьте в начало ноль (0).)" -#: utils/misc/guc_tables.c:2304 +#: utils/misc/guc_tables.c:2410 msgid "Sets the file permissions for log files." msgstr "Задаёт права доступа к файлам протоколов." -#: utils/misc/guc_tables.c:2305 +#: utils/misc/guc_tables.c:2411 msgid "" "The parameter value is expected to be a numeric mode specification in the " "form accepted by the chmod and umask system calls. (To use the customary " @@ -31395,11 +32879,11 @@ msgstr "" "функциями chmod и umask. (Чтобы использовать привычный восьмеричный формат, " "добавьте в начало ноль (0).)" -#: utils/misc/guc_tables.c:2319 +#: utils/misc/guc_tables.c:2425 msgid "Shows the mode of the data directory." msgstr "Показывает режим каталога данных." -#: utils/misc/guc_tables.c:2320 +#: utils/misc/guc_tables.c:2426 msgid "" "The parameter value is a numeric mode specification in the form accepted by " "the chmod and umask system calls. (To use the customary octal format the " @@ -31409,11 +32893,11 @@ msgstr "" "функциями chmod и umask. (Чтобы использовать привычный восьмеричный формат, " "добавьте в начало ноль (0).)" -#: utils/misc/guc_tables.c:2333 +#: utils/misc/guc_tables.c:2439 msgid "Sets the maximum memory to be used for query workspaces." msgstr "Задаёт предельный объём памяти для рабочих пространств запросов." -#: utils/misc/guc_tables.c:2334 +#: utils/misc/guc_tables.c:2440 msgid "" "This much memory can be used by each internal sort operation and hash table " "before switching to temporary disk files." @@ -31421,19 +32905,19 @@ msgstr "" "Такой объём памяти может использоваться каждой внутренней операцией " "сортировки и таблицей хешей до переключения на временные файлы на диске." -#: utils/misc/guc_tables.c:2346 +#: utils/misc/guc_tables.c:2457 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "Задаёт предельный объём памяти для операций по обслуживанию." -#: utils/misc/guc_tables.c:2347 +#: utils/misc/guc_tables.c:2458 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "Подразумеваются в частности операции VACUUM и CREATE INDEX." -#: utils/misc/guc_tables.c:2357 +#: utils/misc/guc_tables.c:2468 msgid "Sets the maximum memory to be used for logical decoding." msgstr "Задаёт предельный объём памяти для логического декодирования." -#: utils/misc/guc_tables.c:2358 +#: utils/misc/guc_tables.c:2469 msgid "" "This much memory can be used by each internal reorder buffer before spilling " "to disk." @@ -31441,85 +32925,94 @@ msgstr "" "Такой объём памяти может использоваться каждым внутренним буфером " "пересортировки до вымещения данных на диск." -#: utils/misc/guc_tables.c:2374 +#: utils/misc/guc_tables.c:2485 msgid "Sets the maximum stack depth, in kilobytes." msgstr "Задаёт максимальную глубину стека (в КБ)." -#: utils/misc/guc_tables.c:2385 +#: utils/misc/guc_tables.c:2496 msgid "Limits the total size of all temporary files used by each process." msgstr "" "Ограничивает общий размер всех временных файлов, доступный для каждого " "процесса." -#: utils/misc/guc_tables.c:2386 +#: utils/misc/guc_tables.c:2497 msgid "-1 means no limit." msgstr "-1 отключает ограничение." -#: utils/misc/guc_tables.c:2396 +#: utils/misc/guc_tables.c:2507 msgid "Vacuum cost for a page found in the buffer cache." msgstr "Стоимость очистки для страницы, найденной в кеше." -#: utils/misc/guc_tables.c:2406 +#: utils/misc/guc_tables.c:2517 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "Стоимость очистки для страницы, не найденной в кеше." -#: utils/misc/guc_tables.c:2416 +#: utils/misc/guc_tables.c:2527 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "Стоимость очистки для страницы, которая не была \"грязной\"." -#: utils/misc/guc_tables.c:2426 +#: utils/misc/guc_tables.c:2537 msgid "Vacuum cost amount available before napping." msgstr "Суммарная стоимость очистки, при которой нужна передышка." -#: utils/misc/guc_tables.c:2436 +#: utils/misc/guc_tables.c:2547 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "" "Суммарная стоимость очистки, при которой нужна передышка, для автоочистки." -#: utils/misc/guc_tables.c:2446 +#: utils/misc/guc_tables.c:2557 msgid "" "Sets the maximum number of simultaneously open files for each server process." msgstr "" "Задаёт предельное число одновременно открытых файлов для каждого серверного " "процесса." -#: utils/misc/guc_tables.c:2459 +#: utils/misc/guc_tables.c:2570 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "Задаёт предельное число одновременно подготовленных транзакций." -#: utils/misc/guc_tables.c:2470 +#: utils/misc/guc_tables.c:2581 msgid "Sets the minimum OID of tables for tracking locks." msgstr "Задаёт минимальный OID таблиц, для которых отслеживаются блокировки." -#: utils/misc/guc_tables.c:2471 +#: utils/misc/guc_tables.c:2582 msgid "Is used to avoid output on system tables." msgstr "Применяется для игнорирования системных таблиц." -#: utils/misc/guc_tables.c:2480 +#: utils/misc/guc_tables.c:2591 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "Задаёт OID таблицы для безусловного отслеживания блокировок." -#: utils/misc/guc_tables.c:2492 +#: utils/misc/guc_tables.c:2603 msgid "Sets the maximum allowed duration of any statement." msgstr "Задаёт предельную длительность для любого оператора." -#: utils/misc/guc_tables.c:2493 utils/misc/guc_tables.c:2504 -#: utils/misc/guc_tables.c:2515 utils/misc/guc_tables.c:2526 +#: utils/misc/guc_tables.c:2604 utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2626 utils/misc/guc_tables.c:2637 +#: utils/misc/guc_tables.c:2648 msgid "A value of 0 turns off the timeout." msgstr "Нулевое значение отключает тайм-аут." -#: utils/misc/guc_tables.c:2503 +#: utils/misc/guc_tables.c:2614 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "Задаёт максимальную продолжительность ожидания блокировок." -#: utils/misc/guc_tables.c:2514 +#: utils/misc/guc_tables.c:2625 msgid "" "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "" "Задаёт предельно допустимую длительность простоя между запросами в " "транзакции." -#: utils/misc/guc_tables.c:2525 +#: utils/misc/guc_tables.c:2636 +msgid "" +"Sets the maximum allowed duration of any transaction within a session (not a " +"prepared transaction)." +msgstr "" +"Задаёт предельно допустимую длительность для любых транзакций в сеансе " +"(кроме подготовленных)." + +#: utils/misc/guc_tables.c:2647 msgid "" "Sets the maximum allowed idle time between queries, when not in a " "transaction." @@ -31527,37 +33020,37 @@ msgstr "" "Задаёт предельно допустимую длительность простоя между запросами вне " "транзакций." -#: utils/misc/guc_tables.c:2536 +#: utils/misc/guc_tables.c:2658 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "" "Минимальный возраст строк таблицы, при котором VACUUM может их заморозить." -#: utils/misc/guc_tables.c:2546 +#: utils/misc/guc_tables.c:2668 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "" "Возраст, при котором VACUUM должен сканировать всю таблицу с целью " "заморозить кортежи." -#: utils/misc/guc_tables.c:2556 +#: utils/misc/guc_tables.c:2678 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "" "Минимальный возраст, при котором VACUUM будет замораживать MultiXactId в " "строке таблицы." -#: utils/misc/guc_tables.c:2566 +#: utils/misc/guc_tables.c:2688 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "" "Возраст multixact, при котором VACUUM должен сканировать всю таблицу с целью " "заморозить кортежи." -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2698 msgid "" "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "" "Возраст, при котором VACUUM должен включить защиту от зацикливания во " "избежание отказа." -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2707 msgid "" "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound " "outage." @@ -31565,44 +33058,44 @@ msgstr "" "Возраст мультитранзакций, при котором VACUUM должен включить защиту от " "зацикливания во избежание отказа." -#: utils/misc/guc_tables.c:2598 +#: utils/misc/guc_tables.c:2720 msgid "Sets the maximum number of locks per transaction." msgstr "Задаёт предельное число блокировок на транзакцию." -#: utils/misc/guc_tables.c:2599 +#: utils/misc/guc_tables.c:2721 msgid "" "The shared lock table is sized on the assumption that at most " -"max_locks_per_transaction objects per server process or prepared transaction " -"will need to be locked at any one time." +"\"max_locks_per_transaction\" objects per server process or prepared " +"transaction will need to be locked at any one time." msgstr "" "Размер разделяемой таблицы блокировок выбирается из предположения, что в " "один момент времени потребуется заблокировать не более " -"max_locks_per_transaction объектов для одного серверного процесса или " +"\"max_locks_per_transaction\" объектов для одного серверного процесса или " "подготовленной транзакции." -#: utils/misc/guc_tables.c:2610 +#: utils/misc/guc_tables.c:2732 msgid "Sets the maximum number of predicate locks per transaction." msgstr "Задаёт предельное число предикатных блокировок на транзакцию." -#: utils/misc/guc_tables.c:2611 +#: utils/misc/guc_tables.c:2733 msgid "" "The shared predicate lock table is sized on the assumption that at most " -"max_pred_locks_per_transaction objects per server process or prepared " +"\"max_pred_locks_per_transaction\" objects per server process or prepared " "transaction will need to be locked at any one time." msgstr "" "Размер разделяемой таблицы предикатных блокировок выбирается из " "предположения, что в один момент времени потребуется заблокировать не более " -"max_pred_locks_per_transaction объектов для одного серверного процесса или " -"подготовленной транзакции." +"\"max_pred_locks_per_transaction\" объектов для одного серверного процесса " +"или подготовленной транзакции." -#: utils/misc/guc_tables.c:2622 +#: utils/misc/guc_tables.c:2744 msgid "" "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "" "Задаёт максимальное число страниц и кортежей, блокируемых предикатными " "блокировками в одном отношении." -#: utils/misc/guc_tables.c:2623 +#: utils/misc/guc_tables.c:2745 msgid "" "If more than this total of pages and tuples in the same relation are locked " "by a connection, those locks are replaced by a relation-level lock." @@ -31610,13 +33103,13 @@ msgstr "" "Если одним соединением блокируется больше этого общего числа страниц и " "кортежей, эти блокировки заменяются блокировкой на уровне отношения." -#: utils/misc/guc_tables.c:2633 +#: utils/misc/guc_tables.c:2755 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "" "Задаёт максимальное число кортежей, блокируемых предикатными блокировками в " "одной странице." -#: utils/misc/guc_tables.c:2634 +#: utils/misc/guc_tables.c:2756 msgid "" "If more than this number of tuples on the same page are locked by a " "connection, those locks are replaced by a page-level lock." @@ -31624,45 +33117,50 @@ msgstr "" "Если одним соединением блокируется больше этого числа кортежей на одной " "странице, эти блокировки заменяются блокировкой на уровне страницы." -#: utils/misc/guc_tables.c:2644 +#: utils/misc/guc_tables.c:2766 msgid "Sets the maximum allowed time to complete client authentication." msgstr "Ограничивает время, за которое клиент должен пройти аутентификацию." -#: utils/misc/guc_tables.c:2656 +#: utils/misc/guc_tables.c:2778 msgid "" "Sets the amount of time to wait before authentication on connection startup." msgstr "Задаёт время ожидания до аутентификации при установлении соединения." -#: utils/misc/guc_tables.c:2668 +#: utils/misc/guc_tables.c:2790 +msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." +msgstr "" +"Задаёт максимальное число страниц, выделяемых для очереди NOTIFY / LISTEN." + +#: utils/misc/guc_tables.c:2800 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "Размер буфера для упреждающего чтения WAL во время восстановления." -#: utils/misc/guc_tables.c:2669 +#: utils/misc/guc_tables.c:2801 msgid "" "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "" "Максимальный объём WAL, прочитываемый наперёд для осуществления предвыборки " "изменяемых блоков данных." -#: utils/misc/guc_tables.c:2679 +#: utils/misc/guc_tables.c:2811 msgid "Sets the size of WAL files held for standby servers." msgstr "" "Определяет предельный объём файлов WAL, сохраняемых для резервных серверов." -#: utils/misc/guc_tables.c:2690 +#: utils/misc/guc_tables.c:2822 msgid "Sets the minimum size to shrink the WAL to." msgstr "Задаёт минимальный размер WAL при сжатии." -#: utils/misc/guc_tables.c:2702 +#: utils/misc/guc_tables.c:2834 msgid "Sets the WAL size that triggers a checkpoint." msgstr "Задаёт размер WAL, при котором инициируется контрольная точка." -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2846 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "" "Задаёт максимальное время между автоматическими контрольными точками WAL." -#: utils/misc/guc_tables.c:2725 +#: utils/misc/guc_tables.c:2857 msgid "" "Sets the maximum time before warning if checkpoints triggered by WAL volume " "happen too frequently." @@ -31670,7 +33168,7 @@ msgstr "" "Задаёт максимальный интервал, в котором выдаётся предупреждение о том, что " "контрольные точки, вызванные активностью WAL, происходят слишком часто." -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2859 msgid "" "Write a message to the server log if checkpoints caused by the filling of " "WAL segment files happen more frequently than this amount of time. Zero " @@ -31680,49 +33178,54 @@ msgstr "" "контрольными точками, вызванными заполнением файлов сегментов WAL, меньше " "заданного значения. Нулевое значение отключает эти предупреждения." -#: utils/misc/guc_tables.c:2740 utils/misc/guc_tables.c:2958 -#: utils/misc/guc_tables.c:2998 +#: utils/misc/guc_tables.c:2872 utils/misc/guc_tables.c:3090 +#: utils/misc/guc_tables.c:3144 msgid "" "Number of pages after which previously performed writes are flushed to disk." msgstr "" "Число страниц, по достижении которого ранее выполненные операции записи " "сбрасываются на диск." -#: utils/misc/guc_tables.c:2751 +#: utils/misc/guc_tables.c:2883 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "Задаёт число буферов дисковых страниц в разделяемой памяти для WAL." -#: utils/misc/guc_tables.c:2762 +#: utils/misc/guc_tables.c:2884 +msgid "" +"Specify -1 to have this value determined as a fraction of shared_buffers." +msgstr "При значении -1 это число определяется как процент от shared_buffers." + +#: utils/misc/guc_tables.c:2894 msgid "Time between WAL flushes performed in the WAL writer." msgstr "Задержка между сбросом WAL в процессе, записывающем WAL." -#: utils/misc/guc_tables.c:2773 +#: utils/misc/guc_tables.c:2905 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "" "Объём WAL, обработанный пишущим WAL процессом, при котором инициируется " "сброс журнала на диск." -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2916 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "" "Размер нового файла, при достижении которого файл не пишется в WAL, а " "сбрасывается на диск." -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2927 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "" "Задаёт предельное число одновременно работающих процессов передачи WAL." -#: utils/misc/guc_tables.c:2806 +#: utils/misc/guc_tables.c:2938 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "Задаёт предельное число одновременно существующих слотов репликации." -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2948 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "" "Задаёт максимальный размер WAL, который могут резервировать слоты репликации." -#: utils/misc/guc_tables.c:2817 +#: utils/misc/guc_tables.c:2949 msgid "" "Replication slots will be marked as failed, and segments released for " "deletion or recycling, if this much space is occupied by WAL on disk." @@ -31731,11 +33234,11 @@ msgstr "" "помечены как нерабочие, а сегменты будут освобождены для удаления или " "переработки." -#: utils/misc/guc_tables.c:2829 +#: utils/misc/guc_tables.c:2961 msgid "Sets the maximum time to wait for WAL replication." msgstr "Задаёт предельное время ожидания репликации WAL." -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2972 msgid "" "Sets the delay in microseconds between transaction commit and flushing WAL " "to disk." @@ -31743,19 +33246,19 @@ msgstr "" "Задаёт задержку в микросекундах между фиксированием транзакций и сбросом WAL " "на диск." -#: utils/misc/guc_tables.c:2852 +#: utils/misc/guc_tables.c:2984 msgid "" "Sets the minimum number of concurrent open transactions required before " -"performing commit_delay." +"performing \"commit_delay\"." msgstr "" "Задаёт минимальное число одновременно открытых транзакций, которое требуется " -"для применения commit_delay." +"для применения \"commit_delay\"." -#: utils/misc/guc_tables.c:2863 +#: utils/misc/guc_tables.c:2995 msgid "Sets the number of digits displayed for floating-point values." msgstr "Задаёт число выводимых цифр для чисел с плавающей точкой." -#: utils/misc/guc_tables.c:2864 +#: utils/misc/guc_tables.c:2996 msgid "" "This affects real, double precision, and geometric data types. A zero or " "negative parameter value is added to the standard number of digits (FLT_DIG " @@ -31767,7 +33270,7 @@ msgstr "" "(FLT_DIG или DBL_DIG соответственно). Положительное значение включает режим " "точного вывода." -#: utils/misc/guc_tables.c:2876 +#: utils/misc/guc_tables.c:3008 msgid "" "Sets the minimum execution time above which a sample of statements will be " "logged. Sampling is determined by log_statement_sample_rate." @@ -31776,22 +33279,22 @@ msgstr "" "которого он выводится в журнал. Выборка определяется параметром " "log_statement_sample_rate." -#: utils/misc/guc_tables.c:2879 +#: utils/misc/guc_tables.c:3011 msgid "Zero logs a sample of all queries. -1 turns this feature off." msgstr "При 0 выводятся все запросы в выборке; -1 отключает эти сообщения." -#: utils/misc/guc_tables.c:2889 +#: utils/misc/guc_tables.c:3021 msgid "" "Sets the minimum execution time above which all statements will be logged." msgstr "" "Задаёт предельное время выполнения любого оператора, при превышении которого " "он выводится в журнал." -#: utils/misc/guc_tables.c:2891 +#: utils/misc/guc_tables.c:3023 msgid "Zero prints all queries. -1 turns this feature off." msgstr "При 0 выводятся все запросы; -1 отключает эти сообщения." -#: utils/misc/guc_tables.c:2901 +#: utils/misc/guc_tables.c:3033 msgid "" "Sets the minimum execution time above which autovacuum actions will be " "logged." @@ -31799,12 +33302,12 @@ msgstr "" "Задаёт предельное время выполнения автоочистки, при превышении которого эта " "операция протоколируется в журнале." -#: utils/misc/guc_tables.c:2903 +#: utils/misc/guc_tables.c:3035 msgid "Zero prints all actions. -1 turns autovacuum logging off." msgstr "" "При 0 протоколируются все операции автоочистки; -1 отключает эти сообщения." -#: utils/misc/guc_tables.c:2913 +#: utils/misc/guc_tables.c:3045 msgid "" "Sets the maximum length in bytes of data logged for bind parameter values " "when logging statements." @@ -31812,11 +33315,11 @@ msgstr "" "Задаёт максимальный размер данных (в байтах), выводимых в значениях " "привязанных параметров при протоколировании операторов." -#: utils/misc/guc_tables.c:2915 utils/misc/guc_tables.c:2927 +#: utils/misc/guc_tables.c:3047 utils/misc/guc_tables.c:3059 msgid "-1 to print values in full." msgstr "При -1 значения выводятся полностью." -#: utils/misc/guc_tables.c:2925 +#: utils/misc/guc_tables.c:3057 msgid "" "Sets the maximum length in bytes of data logged for bind parameter values " "when logging statements, on error." @@ -31824,17 +33327,17 @@ msgstr "" "Задаёт максимальный размер данных (в байтах), выводимых в значениях " "привязанных параметров при протоколировании операторов в случае ошибки." -#: utils/misc/guc_tables.c:2937 +#: utils/misc/guc_tables.c:3069 msgid "Background writer sleep time between rounds." msgstr "Время простоя в процессе фоновой записи между подходами." -#: utils/misc/guc_tables.c:2948 +#: utils/misc/guc_tables.c:3080 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "" "Максимальное число LRU-страниц, сбрасываемых за один подход, в процессе " "фоновой записи." -#: utils/misc/guc_tables.c:2971 +#: utils/misc/guc_tables.c:3103 msgid "" "Number of simultaneous requests that can be handled efficiently by the disk " "subsystem." @@ -31842,89 +33345,97 @@ msgstr "" "Число одновременных запросов, которые могут быть эффективно обработаны " "дисковой подсистемой." -#: utils/misc/guc_tables.c:2985 +#: utils/misc/guc_tables.c:3117 msgid "" -"A variant of effective_io_concurrency that is used for maintenance work." +"A variant of \"effective_io_concurrency\" that is used for maintenance work." msgstr "" -"Вариация параметра effective_io_concurrency, предназначенная для операций " -"обслуживания БД." +"Вариация параметра \"effective_io_concurrency\", предназначенная для " +"операций обслуживания БД." -#: utils/misc/guc_tables.c:3011 +#: utils/misc/guc_tables.c:3132 +msgid "Limit on the size of data reads and writes." +msgstr "Предельный размер для операций чтения и записи данных." + +#: utils/misc/guc_tables.c:3157 msgid "Maximum number of concurrent worker processes." msgstr "Задаёт максимально возможное число рабочих процессов." -#: utils/misc/guc_tables.c:3023 +#: utils/misc/guc_tables.c:3169 msgid "Maximum number of logical replication worker processes." msgstr "" "Задаёт максимально возможное число рабочих процессов логической репликации." -#: utils/misc/guc_tables.c:3035 +#: utils/misc/guc_tables.c:3181 msgid "Maximum number of table synchronization workers per subscription." msgstr "" "Задаёт максимально возможное число процессов синхронизации таблиц для одной " "подписки." -#: utils/misc/guc_tables.c:3047 +#: utils/misc/guc_tables.c:3193 msgid "Maximum number of parallel apply workers per subscription." msgstr "" "Задаёт максимально возможное число параллельных применяющих процессов для " "одной подписки." -#: utils/misc/guc_tables.c:3057 +#: utils/misc/guc_tables.c:3203 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "" "Задаёт время задержки перед принудительным переключением на следующий файл " "журнала." -#: utils/misc/guc_tables.c:3069 +#: utils/misc/guc_tables.c:3215 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "" "Задаёт максимальный размер, которого может достичь файл журнала до " "переключения на другой файл." -#: utils/misc/guc_tables.c:3081 +#: utils/misc/guc_tables.c:3227 msgid "Shows the maximum number of function arguments." msgstr "Показывает максимально возможное число аргументов функций." -#: utils/misc/guc_tables.c:3092 +#: utils/misc/guc_tables.c:3238 msgid "Shows the maximum number of index keys." msgstr "Показывает максимально возможное число ключей в индексе." -#: utils/misc/guc_tables.c:3103 +#: utils/misc/guc_tables.c:3249 msgid "Shows the maximum identifier length." msgstr "Показывает максимально возможную длину идентификатора." -#: utils/misc/guc_tables.c:3114 +#: utils/misc/guc_tables.c:3260 msgid "Shows the size of a disk block." msgstr "Показывает размер дискового блока." -#: utils/misc/guc_tables.c:3125 +#: utils/misc/guc_tables.c:3271 msgid "Shows the number of pages per disk file." msgstr "Показывает число страниц в одном файле." -#: utils/misc/guc_tables.c:3136 +#: utils/misc/guc_tables.c:3282 msgid "Shows the block size in the write ahead log." msgstr "Показывает размер блока в журнале WAL." -#: utils/misc/guc_tables.c:3147 +#: utils/misc/guc_tables.c:3293 msgid "" "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "" "Задаёт время задержки перед повторной попыткой обращения к WAL после неудачи." -#: utils/misc/guc_tables.c:3159 +#: utils/misc/guc_tables.c:3305 msgid "Shows the size of write ahead log segments." msgstr "Показывает размер сегментов журнала предзаписи." -#: utils/misc/guc_tables.c:3172 +#: utils/misc/guc_tables.c:3318 +msgid "Time for which WAL summary files should be kept." +msgstr "Время, в течение которого должны сохраняться файлы обобщения WAL." + +#: utils/misc/guc_tables.c:3331 msgid "Time to sleep between autovacuum runs." msgstr "Время простоя между запусками автоочистки." -#: utils/misc/guc_tables.c:3182 +#: utils/misc/guc_tables.c:3341 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "Минимальное число изменений или удалений кортежей, вызывающее очистку." -#: utils/misc/guc_tables.c:3191 +#: utils/misc/guc_tables.c:3350 msgid "" "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert " "vacuums." @@ -31932,27 +33443,27 @@ msgstr "" "Минимальное число добавлений кортежей, вызывающее очистку; при -1 такая " "очистка отключается." -#: utils/misc/guc_tables.c:3200 +#: utils/misc/guc_tables.c:3359 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "" "Минимальное число добавлений, изменений или удалений кортежей, вызывающее " "анализ." -#: utils/misc/guc_tables.c:3210 +#: utils/misc/guc_tables.c:3369 msgid "" "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "" "Возраст, при котором необходима автоочистка таблицы для предотвращения " "зацикливания ID транзакций." -#: utils/misc/guc_tables.c:3222 +#: utils/misc/guc_tables.c:3381 msgid "" "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "" "Возраст multixact, при котором необходима автоочистка таблицы для " "предотвращения зацикливания multixact." -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3391 msgid "" "Sets the maximum number of simultaneously running autovacuum worker " "processes." @@ -31960,65 +33471,53 @@ msgstr "" "Задаёт предельное число одновременно выполняющихся рабочих процессов " "автоочистки." -#: utils/misc/guc_tables.c:3242 +#: utils/misc/guc_tables.c:3401 msgid "" "Sets the maximum number of parallel processes per maintenance operation." msgstr "" "Задаёт максимальное число параллельных процессов на одну операцию " "обслуживания." -#: utils/misc/guc_tables.c:3252 +#: utils/misc/guc_tables.c:3411 msgid "Sets the maximum number of parallel processes per executor node." msgstr "Задаёт максимальное число параллельных процессов на узел исполнителя." -#: utils/misc/guc_tables.c:3263 +#: utils/misc/guc_tables.c:3422 msgid "" "Sets the maximum number of parallel workers that can be active at one time." msgstr "" -"Задаёт максимальное число параллельных процессов, которые могут быть активны " -"одновременно." +"Задаёт максимальное число параллельных исполнителей, которые могут быть " +"активны одновременно." -#: utils/misc/guc_tables.c:3274 +#: utils/misc/guc_tables.c:3433 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "" "Задаёт предельный объём памяти для каждого рабочего процесса автоочистки." -#: utils/misc/guc_tables.c:3285 -msgid "" -"Time before a snapshot is too old to read pages changed after the snapshot " -"was taken." -msgstr "" -"Срок, по истечении которого снимок считается слишком старым для получения " -"страниц, изменённых после создания снимка." - -#: utils/misc/guc_tables.c:3286 -msgid "A value of -1 disables this feature." -msgstr "Значение -1 отключает это поведение." - -#: utils/misc/guc_tables.c:3296 +#: utils/misc/guc_tables.c:3444 msgid "Time between issuing TCP keepalives." msgstr "Интервал между TCP-пакетами пульса (keep-alive)." -#: utils/misc/guc_tables.c:3297 utils/misc/guc_tables.c:3308 -#: utils/misc/guc_tables.c:3432 +#: utils/misc/guc_tables.c:3445 utils/misc/guc_tables.c:3456 +#: utils/misc/guc_tables.c:3580 msgid "A value of 0 uses the system default." msgstr "При нулевом значении действует системный параметр." -#: utils/misc/guc_tables.c:3307 +#: utils/misc/guc_tables.c:3455 msgid "Time between TCP keepalive retransmits." msgstr "Интервал между повторениями TCP-пакетов пульса (keep-alive)." -#: utils/misc/guc_tables.c:3318 +#: utils/misc/guc_tables.c:3466 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "" "Повторное согласование SSL более не поддерживается; единственное допустимое " "значение - 0." -#: utils/misc/guc_tables.c:3329 +#: utils/misc/guc_tables.c:3477 msgid "Maximum number of TCP keepalive retransmits." msgstr "Максимальное число повторений TCP-пакетов пульса (keep-alive)." -#: utils/misc/guc_tables.c:3330 +#: utils/misc/guc_tables.c:3478 msgid "" "Number of consecutive keepalive retransmits that can be lost before a " "connection is considered dead. A value of 0 uses the system default." @@ -32027,15 +33526,15 @@ msgstr "" "чем соединение будет считаться пропавшим. При нулевом значении действует " "системный параметр." -#: utils/misc/guc_tables.c:3341 +#: utils/misc/guc_tables.c:3489 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "Ограничивает результат точного поиска с использованием GIN." -#: utils/misc/guc_tables.c:3352 +#: utils/misc/guc_tables.c:3500 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "Подсказывает планировщику примерный общий размер кешей данных." -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3501 msgid "" "That is, the total size of the caches (kernel cache and shared buffers) used " "for PostgreSQL data files. This is measured in disk pages, which are " @@ -32045,12 +33544,12 @@ msgstr "" "попадают файлы данных PostgreSQL. Размер задаётся в дисковых страницах " "(обычно это 8 КБ)." -#: utils/misc/guc_tables.c:3364 +#: utils/misc/guc_tables.c:3512 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "" "Задаёт минимальный объём данных в таблице для параллельного сканирования." -#: utils/misc/guc_tables.c:3365 +#: utils/misc/guc_tables.c:3513 msgid "" "If the planner estimates that it will read a number of table pages too small " "to reach this limit, a parallel scan will not be considered." @@ -32059,12 +33558,12 @@ msgstr "" "задано этим ограничением, он исключает параллельное сканирование из " "рассмотрения." -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3523 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "" "Задаёт минимальный объём данных в индексе для параллельного сканирования." -#: utils/misc/guc_tables.c:3376 +#: utils/misc/guc_tables.c:3524 msgid "" "If the planner estimates that it will read a number of index pages too small " "to reach this limit, a parallel scan will not be considered." @@ -32073,68 +33572,68 @@ msgstr "" "задано этим ограничением, он исключает параллельное сканирование из " "рассмотрения." -#: utils/misc/guc_tables.c:3387 +#: utils/misc/guc_tables.c:3535 msgid "Shows the server version as an integer." msgstr "Показывает версию сервера в виде целого числа." -#: utils/misc/guc_tables.c:3398 +#: utils/misc/guc_tables.c:3546 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "" "Фиксирует в протоколе превышение временными файлами заданного размера (в КБ)." -#: utils/misc/guc_tables.c:3399 +#: utils/misc/guc_tables.c:3547 msgid "Zero logs all files. The default is -1 (turning this feature off)." msgstr "" "При 0 отмечаются все файлы; при -1 эти сообщения отключаются (по умолчанию)." -#: utils/misc/guc_tables.c:3409 +#: utils/misc/guc_tables.c:3557 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "Задаёт размер, резервируемый для pg_stat_activity.query (в байтах)." -#: utils/misc/guc_tables.c:3420 +#: utils/misc/guc_tables.c:3568 msgid "Sets the maximum size of the pending list for GIN index." msgstr "Задаёт максимальный размер списка-очереди для GIN-индекса." -#: utils/misc/guc_tables.c:3431 +#: utils/misc/guc_tables.c:3579 msgid "TCP user timeout." msgstr "Пользовательский таймаут TCP." -#: utils/misc/guc_tables.c:3442 +#: utils/misc/guc_tables.c:3590 msgid "The size of huge page that should be requested." msgstr "Запрашиваемый размер огромных страниц." -#: utils/misc/guc_tables.c:3453 +#: utils/misc/guc_tables.c:3601 msgid "Aggressively flush system caches for debugging purposes." msgstr "Включает агрессивный сброс системных кешей для целей отладки." -#: utils/misc/guc_tables.c:3476 +#: utils/misc/guc_tables.c:3624 msgid "" "Sets the time interval between checks for disconnection while running " "queries." msgstr "" "Задаёт интервал между проверками подключения во время выполнения запросов." -#: utils/misc/guc_tables.c:3487 +#: utils/misc/guc_tables.c:3635 msgid "Time between progress updates for long-running startup operations." msgstr "" "Интервал между обновлениями состояния длительных операций, выполняемых при " "запуске." -#: utils/misc/guc_tables.c:3489 +#: utils/misc/guc_tables.c:3637 msgid "0 turns this feature off." msgstr "При 0 эта функциональность отключается." -#: utils/misc/guc_tables.c:3499 +#: utils/misc/guc_tables.c:3647 msgid "Sets the iteration count for SCRAM secret generation." msgstr "Задаёт количество итераций для формирования секрета SCRAM." -#: utils/misc/guc_tables.c:3519 +#: utils/misc/guc_tables.c:3667 msgid "" "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "" "Задаёт для планировщика ориентир стоимости последовательного чтения страницы." -#: utils/misc/guc_tables.c:3530 +#: utils/misc/guc_tables.c:3678 msgid "" "Sets the planner's estimate of the cost of a nonsequentially fetched disk " "page." @@ -32142,13 +33641,13 @@ msgstr "" "Задаёт для планировщика ориентир стоимости непоследовательного чтения " "страницы." -#: utils/misc/guc_tables.c:3541 +#: utils/misc/guc_tables.c:3689 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "" "Задаёт для планировщика ориентир стоимости обработки каждого кортежа " "(строки)." -#: utils/misc/guc_tables.c:3552 +#: utils/misc/guc_tables.c:3700 msgid "" "Sets the planner's estimate of the cost of processing each index entry " "during an index scan." @@ -32156,7 +33655,7 @@ msgstr "" "Задаёт для планировщика ориентир стоимости обработки каждого элемента " "индекса в процессе сканирования индекса." -#: utils/misc/guc_tables.c:3563 +#: utils/misc/guc_tables.c:3711 msgid "" "Sets the planner's estimate of the cost of processing each operator or " "function call." @@ -32164,7 +33663,7 @@ msgstr "" "Задаёт для планировщика ориентир стоимости обработки каждого оператора или " "вызова функции." -#: utils/misc/guc_tables.c:3574 +#: utils/misc/guc_tables.c:3722 msgid "" "Sets the planner's estimate of the cost of passing each tuple (row) from " "worker to leader backend." @@ -32172,7 +33671,7 @@ msgstr "" "Задаёт для планировщика ориентир стоимости передачи каждого кортежа (строки) " "ведущему процессу от рабочего." -#: utils/misc/guc_tables.c:3585 +#: utils/misc/guc_tables.c:3733 msgid "" "Sets the planner's estimate of the cost of starting up worker processes for " "parallel query." @@ -32180,40 +33679,40 @@ msgstr "" "Задаёт для планировщика ориентир стоимости запуска рабочих процессов для " "параллельного выполнения запроса." -#: utils/misc/guc_tables.c:3597 +#: utils/misc/guc_tables.c:3745 msgid "Perform JIT compilation if query is more expensive." msgstr "Стоимость запроса, при превышении которой производится JIT-компиляция." -#: utils/misc/guc_tables.c:3598 +#: utils/misc/guc_tables.c:3746 msgid "-1 disables JIT compilation." msgstr "-1 отключает JIT-компиляцию." -#: utils/misc/guc_tables.c:3608 +#: utils/misc/guc_tables.c:3756 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "" "Стоимость запроса, при превышении которой оптимизируются JIT-" "скомпилированные функции." -#: utils/misc/guc_tables.c:3609 +#: utils/misc/guc_tables.c:3757 msgid "-1 disables optimization." msgstr "-1 отключает оптимизацию." -#: utils/misc/guc_tables.c:3619 +#: utils/misc/guc_tables.c:3767 msgid "Perform JIT inlining if query is more expensive." msgstr "Стоимость запроса, при которой выполняется встраивание JIT." -#: utils/misc/guc_tables.c:3620 +#: utils/misc/guc_tables.c:3768 msgid "-1 disables inlining." msgstr "-1 отключает встраивание кода." -#: utils/misc/guc_tables.c:3630 +#: utils/misc/guc_tables.c:3778 msgid "" "Sets the planner's estimate of the fraction of a cursor's rows that will be " "retrieved." msgstr "" "Задаёт для планировщика ориентир доли требуемых строк курсора в общем числе." -#: utils/misc/guc_tables.c:3642 +#: utils/misc/guc_tables.c:3790 msgid "" "Sets the planner's estimate of the average size of a recursive query's " "working table." @@ -32221,37 +33720,37 @@ msgstr "" "Задаёт для планировщика ориентир среднего размера рабочей таблицы в " "рекурсивном запросе." -#: utils/misc/guc_tables.c:3654 +#: utils/misc/guc_tables.c:3802 msgid "GEQO: selective pressure within the population." msgstr "GEQO: селективное давление в популяции." -#: utils/misc/guc_tables.c:3665 +#: utils/misc/guc_tables.c:3813 msgid "GEQO: seed for random path selection." msgstr "GEQO: отправное значение для случайного выбора пути." -#: utils/misc/guc_tables.c:3676 -msgid "Multiple of work_mem to use for hash tables." -msgstr "Множитель work_mem, определяющий объём памяти для хеш-таблиц." +#: utils/misc/guc_tables.c:3824 +msgid "Multiple of \"work_mem\" to use for hash tables." +msgstr "Множитель \"work_mem\", определяющий объём памяти для хеш-таблиц." -#: utils/misc/guc_tables.c:3687 +#: utils/misc/guc_tables.c:3835 msgid "Multiple of the average buffer usage to free per round." msgstr "" "Множитель для среднего числа использованных буферов, определяющий число " "буферов, освобождаемых за один подход." -#: utils/misc/guc_tables.c:3697 +#: utils/misc/guc_tables.c:3845 msgid "Sets the seed for random-number generation." msgstr "Задаёт отправное значение для генератора случайных чисел." -#: utils/misc/guc_tables.c:3708 +#: utils/misc/guc_tables.c:3856 msgid "Vacuum cost delay in milliseconds." msgstr "Задержка очистки (в миллисекундах)." -#: utils/misc/guc_tables.c:3719 +#: utils/misc/guc_tables.c:3867 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "Задержка очистки для автоочистки (в миллисекундах)." -#: utils/misc/guc_tables.c:3730 +#: utils/misc/guc_tables.c:3878 msgid "" "Number of tuple updates or deletes prior to vacuum as a fraction of " "reltuples." @@ -32259,13 +33758,13 @@ msgstr "" "Отношение числа обновлений или удалений кортежей к reltuples, определяющее " "потребность в очистке." -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3888 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "" "Отношение числа добавлений кортежей к reltuples, определяющее потребность в " "очистке." -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3898 msgid "" "Number of tuple inserts, updates, or deletes prior to analyze as a fraction " "of reltuples." @@ -32273,7 +33772,7 @@ msgstr "" "Отношение числа добавлений, обновлений или удалений кортежей к reltuples, " "определяющее потребность в анализе." -#: utils/misc/guc_tables.c:3760 +#: utils/misc/guc_tables.c:3908 msgid "" "Time spent flushing dirty buffers during checkpoint, as fraction of " "checkpoint interval." @@ -32281,25 +33780,26 @@ msgstr "" "Отношение продолжительности сброса \"грязных\" буферов во время контрольной " "точки к интервалу контрольных точек." -#: utils/misc/guc_tables.c:3770 -msgid "Fraction of statements exceeding log_min_duration_sample to be logged." +#: utils/misc/guc_tables.c:3918 +msgid "" +"Fraction of statements exceeding \"log_min_duration_sample\" to be logged." msgstr "" "Доля записываемых в журнал операторов с длительностью, превышающей " -"log_min_duration_sample." +"\"log_min_duration_sample\"." -#: utils/misc/guc_tables.c:3771 +#: utils/misc/guc_tables.c:3919 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "" "Может задаваться значением от 0.0 (не записывать никакие операторы) и 1.0 " "(записывать все)." -#: utils/misc/guc_tables.c:3780 +#: utils/misc/guc_tables.c:3928 msgid "Sets the fraction of transactions from which to log all statements." msgstr "" "Задаёт долю транзакций, все операторы которых будут записываться в журнал " "сервера." -#: utils/misc/guc_tables.c:3781 +#: utils/misc/guc_tables.c:3929 msgid "" "Use a value between 0.0 (never log) and 1.0 (log all statements for all " "transactions)." @@ -32307,48 +33807,48 @@ msgstr "" "Значение 0.0 означает — не записывать никакие транзакции, а значение 1.0 — " "записывать все операторы всех транзакций." -#: utils/misc/guc_tables.c:3800 +#: utils/misc/guc_tables.c:3948 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "Задаёт команду оболочки, вызываемую для архивации файла WAL." -#: utils/misc/guc_tables.c:3801 +#: utils/misc/guc_tables.c:3949 msgid "This is used only if \"archive_library\" is not set." msgstr "Это параметр используется, только если не задан \"archive_library\"." -#: utils/misc/guc_tables.c:3810 +#: utils/misc/guc_tables.c:3958 msgid "Sets the library that will be called to archive a WAL file." msgstr "Задаёт библиотеку, вызываемую для архивации файла WAL." -#: utils/misc/guc_tables.c:3811 +#: utils/misc/guc_tables.c:3959 msgid "An empty string indicates that \"archive_command\" should be used." msgstr "" "Пустая строка указывает, что должен использоваться параметр " "\"archive_command\"." -#: utils/misc/guc_tables.c:3820 +#: utils/misc/guc_tables.c:3968 msgid "" "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "" "Задаёт команду оболочки, которая будет вызываться для извлечения из архива " "файла WAL." -#: utils/misc/guc_tables.c:3830 +#: utils/misc/guc_tables.c:3978 msgid "Sets the shell command that will be executed at every restart point." msgstr "" "Задаёт команду оболочки, которая будет выполняться при каждой точке " "перезапуска." -#: utils/misc/guc_tables.c:3840 +#: utils/misc/guc_tables.c:3988 msgid "" "Sets the shell command that will be executed once at the end of recovery." msgstr "" "Задаёт команду оболочки, которая будет выполняться в конце восстановления." -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:3998 msgid "Specifies the timeline to recover into." msgstr "Указывает линию времени для выполнения восстановления." -#: utils/misc/guc_tables.c:3860 +#: utils/misc/guc_tables.c:4008 msgid "" "Set to \"immediate\" to end recovery as soon as a consistent state is " "reached." @@ -32356,24 +33856,24 @@ msgstr "" "Задайте значение \"immediate\", чтобы восстановление остановилось сразу " "после достижения согласованного состояния." -#: utils/misc/guc_tables.c:3869 +#: utils/misc/guc_tables.c:4017 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "" "Задаёт идентификатор транзакции, вплоть до которой будет производиться " "восстановление." -#: utils/misc/guc_tables.c:3878 +#: utils/misc/guc_tables.c:4026 msgid "Sets the time stamp up to which recovery will proceed." msgstr "" "Задаёт момент времени, вплоть до которого будет производиться восстановление." -#: utils/misc/guc_tables.c:3887 +#: utils/misc/guc_tables.c:4035 msgid "Sets the named restore point up to which recovery will proceed." msgstr "" "Задаёт именованную точку восстановления, до которой будет производиться " "восстановление." -#: utils/misc/guc_tables.c:3896 +#: utils/misc/guc_tables.c:4044 msgid "" "Sets the LSN of the write-ahead log location up to which recovery will " "proceed." @@ -32381,61 +33881,61 @@ msgstr "" "Задаёт в виде LSN позицию в журнале предзаписи, до которой будет " "производиться восстановление." -#: utils/misc/guc_tables.c:3906 +#: utils/misc/guc_tables.c:4054 msgid "Sets the connection string to be used to connect to the sending server." msgstr "" "Задаёт строку соединения, которая будет использоваться для подключения к " "передающему серверу." -#: utils/misc/guc_tables.c:3917 +#: utils/misc/guc_tables.c:4065 msgid "Sets the name of the replication slot to use on the sending server." msgstr "" "Задаёт имя слота репликации, который будет использоваться на передающем " "сервере." -#: utils/misc/guc_tables.c:3927 +#: utils/misc/guc_tables.c:4075 msgid "Sets the client's character set encoding." msgstr "Задаёт кодировку символов, используемую клиентом." -#: utils/misc/guc_tables.c:3938 +#: utils/misc/guc_tables.c:4086 msgid "Controls information prefixed to each log line." msgstr "Определяет содержимое префикса каждой строки протокола." -#: utils/misc/guc_tables.c:3939 +#: utils/misc/guc_tables.c:4087 msgid "If blank, no prefix is used." msgstr "При пустом значении префикс также отсутствует." -#: utils/misc/guc_tables.c:3948 +#: utils/misc/guc_tables.c:4096 msgid "Sets the time zone to use in log messages." msgstr "Задаёт часовой пояс для вывода времени в сообщениях протокола." -#: utils/misc/guc_tables.c:3958 +#: utils/misc/guc_tables.c:4106 msgid "Sets the display format for date and time values." msgstr "Устанавливает формат вывода дат и времени." -#: utils/misc/guc_tables.c:3959 +#: utils/misc/guc_tables.c:4107 msgid "Also controls interpretation of ambiguous date inputs." msgstr "Также помогает разбирать неоднозначно заданные вводимые даты." -#: utils/misc/guc_tables.c:3970 +#: utils/misc/guc_tables.c:4118 msgid "Sets the default table access method for new tables." msgstr "Задаёт табличный метод доступа по умолчанию для новых таблиц." -#: utils/misc/guc_tables.c:3981 +#: utils/misc/guc_tables.c:4129 msgid "Sets the default tablespace to create tables and indexes in." msgstr "" "Задаёт табличное пространство по умолчанию для новых таблиц и индексов." -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4130 msgid "An empty string selects the database's default tablespace." msgstr "При пустом значении используется табличное пространство базы данных." -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4140 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "" "Задаёт табличное пространство(а) для временных таблиц и файлов сортировки." -#: utils/misc/guc_tables.c:4003 +#: utils/misc/guc_tables.c:4151 msgid "" "Sets whether a CREATEROLE user automatically grants the role to themselves, " "and with which options." @@ -32443,11 +33943,11 @@ msgstr "" "Определяет, будет ли пользователь CREATEROLE автоматически включать себя в " "создаваемую роль и с какими параметрами." -#: utils/misc/guc_tables.c:4015 +#: utils/misc/guc_tables.c:4163 msgid "Sets the path for dynamically loadable modules." msgstr "Задаёт путь для динамически загружаемых модулей." -#: utils/misc/guc_tables.c:4016 +#: utils/misc/guc_tables.c:4164 msgid "" "If a dynamically loadable module needs to be opened and the specified name " "does not have a directory component (i.e., the name does not contain a " @@ -32457,71 +33957,71 @@ msgstr "" "указан путь (нет символа '/'), система будет искать этот файл в заданном " "пути." -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4177 msgid "Sets the location of the Kerberos server key file." msgstr "Задаёт размещение файла с ключом Kerberos для данного сервера." -#: utils/misc/guc_tables.c:4040 +#: utils/misc/guc_tables.c:4188 msgid "Sets the Bonjour service name." msgstr "Задаёт название службы Bonjour." -#: utils/misc/guc_tables.c:4050 +#: utils/misc/guc_tables.c:4198 msgid "Sets the language in which messages are displayed." msgstr "Задаёт язык выводимых сообщений." -#: utils/misc/guc_tables.c:4060 +#: utils/misc/guc_tables.c:4208 msgid "Sets the locale for formatting monetary amounts." msgstr "Задаёт локаль для форматирования денежных сумм." -#: utils/misc/guc_tables.c:4070 +#: utils/misc/guc_tables.c:4218 msgid "Sets the locale for formatting numbers." msgstr "Задаёт локаль для форматирования чисел." -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4228 msgid "Sets the locale for formatting date and time values." msgstr "Задаёт локаль для форматирования дат и времени." -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4238 msgid "Lists shared libraries to preload into each backend." msgstr "" "Список разделяемых библиотек, заранее загружаемых в каждый обслуживающий " "процесс." -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4249 msgid "Lists shared libraries to preload into server." msgstr "Список разделяемых библиотек, заранее загружаемых в память сервера." -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4260 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "" "Список непривилегированных разделяемых библиотек, заранее загружаемых в " "каждый обслуживающий процесс." -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4271 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "Задаёт порядок просмотра схемы при поиске неполных имён." -#: utils/misc/guc_tables.c:4135 +#: utils/misc/guc_tables.c:4283 msgid "Shows the server (database) character set encoding." msgstr "Показывает кодировку символов сервера (базы данных)." -#: utils/misc/guc_tables.c:4147 +#: utils/misc/guc_tables.c:4295 msgid "Shows the server version." msgstr "Показывает версию сервера." -#: utils/misc/guc_tables.c:4159 +#: utils/misc/guc_tables.c:4307 msgid "Sets the current role." msgstr "Задаёт текущую роль." -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4319 msgid "Sets the session user name." msgstr "Задаёт имя пользователя в сеансе." -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4330 msgid "Sets the destination for server log output." msgstr "Определяет, куда будет выводиться протокол сервера." -#: utils/misc/guc_tables.c:4183 +#: utils/misc/guc_tables.c:4331 msgid "" "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", " "\"jsonlog\", and \"eventlog\", depending on the platform." @@ -32529,24 +34029,24 @@ msgstr "" "Значение может включать сочетание слов \"stderr\", \"syslog\", \"csvlog\", " "\"jsonlog\" и \"eventlog\", в зависимости от платформы." -#: utils/misc/guc_tables.c:4194 +#: utils/misc/guc_tables.c:4342 msgid "Sets the destination directory for log files." msgstr "Задаёт целевой каталог для файлов протоколов." -#: utils/misc/guc_tables.c:4195 +#: utils/misc/guc_tables.c:4343 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "" "Путь может быть абсолютным или указываться относительно каталога данных." -#: utils/misc/guc_tables.c:4205 +#: utils/misc/guc_tables.c:4353 msgid "Sets the file name pattern for log files." msgstr "Задаёт шаблон имени для файлов протоколов." -#: utils/misc/guc_tables.c:4216 +#: utils/misc/guc_tables.c:4364 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "Задаёт имя программы для идентификации сообщений PostgreSQL в syslog." -#: utils/misc/guc_tables.c:4227 +#: utils/misc/guc_tables.c:4375 msgid "" "Sets the application name used to identify PostgreSQL messages in the event " "log." @@ -32554,121 +34054,121 @@ msgstr "" "Задаёт имя приложения для идентификации сообщений PostgreSQL в журнале " "событий." -#: utils/misc/guc_tables.c:4238 +#: utils/misc/guc_tables.c:4386 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "" "Задаёт часовой пояс для вывода и разбора строкового представления времени." -#: utils/misc/guc_tables.c:4248 +#: utils/misc/guc_tables.c:4396 msgid "Selects a file of time zone abbreviations." msgstr "Выбирает файл с сокращёнными названиями часовых поясов." -#: utils/misc/guc_tables.c:4258 +#: utils/misc/guc_tables.c:4406 msgid "Sets the owning group of the Unix-domain socket." msgstr "Задаёт группу-владельца Unix-сокета." -#: utils/misc/guc_tables.c:4259 +#: utils/misc/guc_tables.c:4407 msgid "" "The owning user of the socket is always the user that starts the server." msgstr "" "Собственно владельцем сокета всегда будет пользователь, запускающий сервер." -#: utils/misc/guc_tables.c:4269 +#: utils/misc/guc_tables.c:4417 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "Задаёт каталоги, где будут создаваться Unix-сокеты." -#: utils/misc/guc_tables.c:4280 +#: utils/misc/guc_tables.c:4428 msgid "Sets the host name or IP address(es) to listen to." msgstr "Задаёт имя узла или IP-адрес(а) для привязки." -#: utils/misc/guc_tables.c:4295 +#: utils/misc/guc_tables.c:4443 msgid "Sets the server's data directory." msgstr "Определяет каталог данных сервера." -#: utils/misc/guc_tables.c:4306 +#: utils/misc/guc_tables.c:4454 msgid "Sets the server's main configuration file." msgstr "Определяет основной файл конфигурации сервера." -#: utils/misc/guc_tables.c:4317 +#: utils/misc/guc_tables.c:4465 msgid "Sets the server's \"hba\" configuration file." msgstr "Задаёт путь к файлу конфигурации \"hba\"." -#: utils/misc/guc_tables.c:4328 +#: utils/misc/guc_tables.c:4476 msgid "Sets the server's \"ident\" configuration file." msgstr "Задаёт путь к файлу конфигурации \"ident\"." -#: utils/misc/guc_tables.c:4339 +#: utils/misc/guc_tables.c:4487 msgid "Writes the postmaster PID to the specified file." msgstr "Файл, в который будет записан код процесса postmaster." -#: utils/misc/guc_tables.c:4350 +#: utils/misc/guc_tables.c:4498 msgid "Shows the name of the SSL library." msgstr "Показывает имя библиотеки SSL." -#: utils/misc/guc_tables.c:4365 +#: utils/misc/guc_tables.c:4513 msgid "Location of the SSL server certificate file." msgstr "Размещение файла сертификата сервера для SSL." -#: utils/misc/guc_tables.c:4375 +#: utils/misc/guc_tables.c:4523 msgid "Location of the SSL server private key file." msgstr "Размещение файла с закрытым ключом сервера для SSL." -#: utils/misc/guc_tables.c:4385 +#: utils/misc/guc_tables.c:4533 msgid "Location of the SSL certificate authority file." msgstr "Размещение файла центра сертификации для SSL." -#: utils/misc/guc_tables.c:4395 +#: utils/misc/guc_tables.c:4543 msgid "Location of the SSL certificate revocation list file." msgstr "Размещение файла со списком отзыва сертификатов для SSL." -#: utils/misc/guc_tables.c:4405 +#: utils/misc/guc_tables.c:4553 msgid "Location of the SSL certificate revocation list directory." msgstr "Размещение каталога со списками отзыва сертификатов для SSL." -#: utils/misc/guc_tables.c:4415 +#: utils/misc/guc_tables.c:4563 msgid "" "Number of synchronous standbys and list of names of potential synchronous " "ones." msgstr "" "Количество потенциально синхронных резервных серверов и список их имён." -#: utils/misc/guc_tables.c:4426 +#: utils/misc/guc_tables.c:4574 msgid "Sets default text search configuration." msgstr "Задаёт конфигурацию текстового поиска по умолчанию." -#: utils/misc/guc_tables.c:4436 +#: utils/misc/guc_tables.c:4584 msgid "Sets the list of allowed SSL ciphers." msgstr "Задаёт список допустимых алгоритмов шифрования для SSL." -#: utils/misc/guc_tables.c:4451 +#: utils/misc/guc_tables.c:4599 msgid "Sets the curve to use for ECDH." msgstr "Задаёт кривую для ECDH." -#: utils/misc/guc_tables.c:4466 +#: utils/misc/guc_tables.c:4614 msgid "Location of the SSL DH parameters file." msgstr "Размещение файла с параметрами SSL DH." -#: utils/misc/guc_tables.c:4477 +#: utils/misc/guc_tables.c:4625 msgid "Command to obtain passphrases for SSL." msgstr "Команда, позволяющая получить пароль для SSL." -#: utils/misc/guc_tables.c:4488 +#: utils/misc/guc_tables.c:4636 msgid "Sets the application name to be reported in statistics and logs." msgstr "" "Задаёт имя приложения, которое будет выводиться в статистике и протоколах." -#: utils/misc/guc_tables.c:4499 +#: utils/misc/guc_tables.c:4647 msgid "Sets the name of the cluster, which is included in the process title." msgstr "Задаёт имя кластера, которое будет добавляться в название процесса." -#: utils/misc/guc_tables.c:4510 +#: utils/misc/guc_tables.c:4658 msgid "" "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "" "Задаёт перечень менеджеров ресурсов WAL, для которых выполняются проверки " "целостности WAL." -#: utils/misc/guc_tables.c:4511 +#: utils/misc/guc_tables.c:4659 msgid "" "Full-page images will be logged for all data blocks and cross-checked " "against the results of WAL replay." @@ -32676,32 +34176,53 @@ msgstr "" "При этом в журнал будут записываться образы полных страниц для всех блоков " "данных для сверки с результатами воспроизведения WAL." -#: utils/misc/guc_tables.c:4521 +#: utils/misc/guc_tables.c:4669 msgid "JIT provider to use." msgstr "Используемый провайдер JIT." -#: utils/misc/guc_tables.c:4532 +#: utils/misc/guc_tables.c:4680 msgid "Log backtrace for errors in these functions." msgstr "Записывать в журнал стек в случае ошибок в перечисленных функциях." -#: utils/misc/guc_tables.c:4543 +#: utils/misc/guc_tables.c:4691 msgid "Use direct I/O for file access." msgstr "Использовать прямой ввод/вывод для работы с файлами." -#: utils/misc/guc_tables.c:4563 +#: utils/misc/guc_tables.c:4702 +msgid "" +"Lists streaming replication standby server replication slot names that " +"logical WAL sender processes will wait for." +msgstr "" +"Определяет список имён слотов потовой репликации, готовности которых будут " +"ждать процессы передачи логических изменений." + +#: utils/misc/guc_tables.c:4704 +msgid "" +"Logical WAL sender processes will send decoded changes to output plugins " +"only after the specified replication slots have confirmed receiving WAL." +msgstr "" +"Процессы передачи логических изменений из WAL будут передавать " +"декодированные изменения модулям вывода только после того, как указанные " +"слоты репликации подтвердят получение WAL." + +#: utils/misc/guc_tables.c:4716 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "Запрещает доступ к несистемным отношениям указанных видов." + +#: utils/misc/guc_tables.c:4736 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "Определяет, можно ли использовать \"\\'\" в текстовых строках." -#: utils/misc/guc_tables.c:4573 +#: utils/misc/guc_tables.c:4746 msgid "Sets the output format for bytea." msgstr "Задаёт формат вывода данных типа bytea." -#: utils/misc/guc_tables.c:4583 +#: utils/misc/guc_tables.c:4756 msgid "Sets the message levels that are sent to the client." msgstr "Ограничивает уровень сообщений, передаваемых клиенту." -#: utils/misc/guc_tables.c:4584 utils/misc/guc_tables.c:4680 -#: utils/misc/guc_tables.c:4691 utils/misc/guc_tables.c:4763 +#: utils/misc/guc_tables.c:4757 utils/misc/guc_tables.c:4853 +#: utils/misc/guc_tables.c:4864 msgid "" "Each level includes all the levels that follow it. The later the level, the " "fewer messages are sent." @@ -32709,16 +34230,16 @@ msgstr "" "Каждый уровень включает все последующие. Чем выше уровень, тем меньше " "сообщений." -#: utils/misc/guc_tables.c:4594 +#: utils/misc/guc_tables.c:4767 msgid "Enables in-core computation of query identifiers." msgstr "Включает внутреннее вычисление идентификаторов запросов." -#: utils/misc/guc_tables.c:4604 +#: utils/misc/guc_tables.c:4777 msgid "Enables the planner to use constraints to optimize queries." msgstr "" "Разрешает планировщику оптимизировать запросы, полагаясь на ограничения." -#: utils/misc/guc_tables.c:4605 +#: utils/misc/guc_tables.c:4778 msgid "" "Table scans will be skipped if their constraints guarantee that no rows " "match the query." @@ -32726,93 +34247,88 @@ msgstr "" "Сканирование таблицы не будет выполняться, если её ограничения гарантируют, " "что запросу не удовлетворяют никакие строки." -#: utils/misc/guc_tables.c:4616 +#: utils/misc/guc_tables.c:4789 msgid "Sets the default compression method for compressible values." msgstr "Задаёт выбираемый по умолчанию метод сжатия для сжимаемых значений." -#: utils/misc/guc_tables.c:4627 +#: utils/misc/guc_tables.c:4800 msgid "Sets the transaction isolation level of each new transaction." msgstr "Задаёт уровень изоляции транзакций для новых транзакций." -#: utils/misc/guc_tables.c:4637 +#: utils/misc/guc_tables.c:4810 msgid "Sets the current transaction's isolation level." msgstr "Задаёт текущий уровень изоляции транзакций." -#: utils/misc/guc_tables.c:4648 +#: utils/misc/guc_tables.c:4821 msgid "Sets the display format for interval values." msgstr "Задаёт формат отображения для внутренних значений." -#: utils/misc/guc_tables.c:4659 +#: utils/misc/guc_tables.c:4832 msgid "Log level for reporting invalid ICU locale strings." msgstr "Уровень протоколирования сообщений о некорректных строках локалей ICU." -#: utils/misc/guc_tables.c:4669 +#: utils/misc/guc_tables.c:4842 msgid "Sets the verbosity of logged messages." msgstr "Задаёт детализацию протоколируемых сообщений." -#: utils/misc/guc_tables.c:4679 +#: utils/misc/guc_tables.c:4852 msgid "Sets the message levels that are logged." msgstr "Ограничивает уровни протоколируемых сообщений." -#: utils/misc/guc_tables.c:4690 +#: utils/misc/guc_tables.c:4863 msgid "" "Causes all statements generating error at or above this level to be logged." msgstr "" "Включает протоколирование для SQL-операторов, выполненных с ошибкой этого " "или большего уровня." -#: utils/misc/guc_tables.c:4701 +#: utils/misc/guc_tables.c:4874 msgid "Sets the type of statements logged." msgstr "Задаёт тип протоколируемых операторов." -#: utils/misc/guc_tables.c:4711 +#: utils/misc/guc_tables.c:4884 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "Задаёт получателя сообщений, отправляемых в syslog." -#: utils/misc/guc_tables.c:4722 +#: utils/misc/guc_tables.c:4895 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "" "Задаёт режим срабатывания триггеров и правил перезаписи для текущего сеанса." -#: utils/misc/guc_tables.c:4732 +#: utils/misc/guc_tables.c:4905 msgid "Sets the current transaction's synchronization level." msgstr "Задаёт уровень синхронизации текущей транзакции." -#: utils/misc/guc_tables.c:4742 -msgid "Allows archiving of WAL files using archive_command." -msgstr "Разрешает архивацию файлов WAL командой archive_command." +#: utils/misc/guc_tables.c:4915 +msgid "Allows archiving of WAL files using \"archive_command\"." +msgstr "Разрешает архивацию файлов WAL с использованием \"archive_command\"." -#: utils/misc/guc_tables.c:4752 +#: utils/misc/guc_tables.c:4925 msgid "Sets the action to perform upon reaching the recovery target." msgstr "" "Задаёт действие, которое будет выполняться по достижении цели восстановления." -#: utils/misc/guc_tables.c:4762 -msgid "Enables logging of recovery-related debugging information." -msgstr "" -"Включает протоколирование отладочной информации, связанной с репликацией." - -#: utils/misc/guc_tables.c:4779 +#: utils/misc/guc_tables.c:4935 msgid "Collects function-level statistics on database activity." msgstr "Включает сбор статистики активности в БД на уровне функций." -#: utils/misc/guc_tables.c:4790 +#: utils/misc/guc_tables.c:4946 msgid "Sets the consistency of accesses to statistics data." msgstr "Задаёт режим согласования доступа к данным статистики." -#: utils/misc/guc_tables.c:4800 +#: utils/misc/guc_tables.c:4956 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "Сжимать данные записываемых в WAL полных страниц заданным методом." -#: utils/misc/guc_tables.c:4810 +#: utils/misc/guc_tables.c:4966 msgid "Sets the level of information written to the WAL." msgstr "Задаёт уровень информации, записываемой в WAL." -#: utils/misc/guc_tables.c:4820 +#: utils/misc/guc_tables.c:4976 msgid "Selects the dynamic shared memory implementation used." msgstr "Выбирает используемую реализацию динамической разделяемой памяти." -#: utils/misc/guc_tables.c:4830 +#: utils/misc/guc_tables.c:4986 msgid "" "Selects the shared memory implementation used for the main shared memory " "region." @@ -32820,15 +34336,15 @@ msgstr "" "Выбирает реализацию разделяемой памяти для управления основным блоком " "разделяемой памяти." -#: utils/misc/guc_tables.c:4840 +#: utils/misc/guc_tables.c:4996 msgid "Selects the method used for forcing WAL updates to disk." msgstr "Выбирает метод принудительной записи изменений в WAL на диск." -#: utils/misc/guc_tables.c:4850 +#: utils/misc/guc_tables.c:5006 msgid "Sets how binary values are to be encoded in XML." msgstr "Определяет, как должны кодироваться двоичные значения в XML." -#: utils/misc/guc_tables.c:4860 +#: utils/misc/guc_tables.c:5016 msgid "" "Sets whether XML data in implicit parsing and serialization operations is to " "be considered as documents or content fragments." @@ -32836,23 +34352,27 @@ msgstr "" "Определяет, следует ли рассматривать XML-данные в неявных операциях разбора " "и сериализации как документы или как фрагменты содержания." -#: utils/misc/guc_tables.c:4871 +#: utils/misc/guc_tables.c:5027 msgid "Use of huge pages on Linux or Windows." msgstr "Включает использование огромных страниц в Linux и в Windows." -#: utils/misc/guc_tables.c:4881 +#: utils/misc/guc_tables.c:5037 +msgid "Indicates the status of huge pages." +msgstr "Показывает состояние использования огромных страниц." + +#: utils/misc/guc_tables.c:5048 msgid "Prefetch referenced blocks during recovery." msgstr "Осуществлять предвыборку изменяемых блоков в процессе восстановления." -#: utils/misc/guc_tables.c:4882 +#: utils/misc/guc_tables.c:5049 msgid "Look ahead in the WAL to find references to uncached data." msgstr "Прочитывать WAL наперёд для вычисления ещё не кешированных блоков." -#: utils/misc/guc_tables.c:4891 +#: utils/misc/guc_tables.c:5058 msgid "Forces the planner's use parallel query nodes." msgstr "Принудительно включает в планировщике узлы параллельного выполнения." -#: utils/misc/guc_tables.c:4892 +#: utils/misc/guc_tables.c:5059 msgid "" "This can be useful for testing the parallel query infrastructure by forcing " "the planner to generate plans that contain nodes that perform tuple " @@ -32862,15 +34382,15 @@ msgstr "" "выполнения, так как планировщик будет строить планы с передачей кортежей " "между параллельными исполнителями и основным процессом." -#: utils/misc/guc_tables.c:4904 +#: utils/misc/guc_tables.c:5071 msgid "Chooses the algorithm for encrypting passwords." msgstr "Выбирает алгоритм шифрования паролей." -#: utils/misc/guc_tables.c:4914 +#: utils/misc/guc_tables.c:5081 msgid "Controls the planner's selection of custom or generic plan." msgstr "Управляет выбором специализированных или общих планов планировщиком." -#: utils/misc/guc_tables.c:4915 +#: utils/misc/guc_tables.c:5082 msgid "" "Prepared statements can have custom and generic plans, and the planner will " "attempt to choose which is better. This can be set to override the default " @@ -32880,30 +34400,30 @@ msgstr "" "планы, и планировщик пытается выбрать лучший вариант. Этот параметр " "позволяет переопределить поведение по умолчанию." -#: utils/misc/guc_tables.c:4927 +#: utils/misc/guc_tables.c:5094 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "" "Задаёт минимальную версию протокола SSL/TLS, которая может использоваться." -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5106 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "" "Задаёт максимальную версию протокола SSL/TLS, которая может использоваться." -#: utils/misc/guc_tables.c:4951 +#: utils/misc/guc_tables.c:5118 msgid "" "Sets the method for synchronizing the data directory before crash recovery." msgstr "" "Задаёт метод синхронизации каталога данных перед восстановления после сбоя." -#: utils/misc/guc_tables.c:4960 +#: utils/misc/guc_tables.c:5127 msgid "" "Forces immediate streaming or serialization of changes in large transactions." msgstr "" "Включает непосредственную передачу или сериализацию изменений в больших " "транзакциях." -#: utils/misc/guc_tables.c:4961 +#: utils/misc/guc_tables.c:5128 msgid "" "On the publisher, it allows streaming or serializing each change in logical " "decoding. On the subscriber, it allows serialization of all changes to files " @@ -32921,8 +34441,8 @@ msgstr "" msgid "internal error: unrecognized run-time parameter type\n" msgstr "внутренняя ошибка: нераспознанный тип параметра времени выполнения\n" -#: utils/misc/pg_controldata.c:51 utils/misc/pg_controldata.c:91 -#: utils/misc/pg_controldata.c:182 utils/misc/pg_controldata.c:223 +#: utils/misc/pg_controldata.c:50 utils/misc/pg_controldata.c:90 +#: utils/misc/pg_controldata.c:181 utils/misc/pg_controldata.c:222 #, c-format msgid "calculated CRC checksum does not match value stored in file" msgstr "" @@ -32951,12 +34471,12 @@ msgstr "" "Чтобы отключить политику для владельца таблицы, воспользуйтесь командой " "ALTER TABLE NO FORCE ROW LEVEL SECURITY." -#: utils/misc/timeout.c:524 +#: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" msgstr "добавить другие причины тайм-аута нельзя" -#: utils/misc/tzparser.c:60 +#: utils/misc/tzparser.c:61 #, c-format msgid "" "time zone abbreviation \"%s\" is too long (maximum %d characters) in time " @@ -32965,44 +34485,44 @@ msgstr "" "краткое обозначение часового пояса \"%s\" должно содержать меньше символов " "(максимум %d) (файл часовых поясов \"%s\", строка %d)" -#: utils/misc/tzparser.c:72 +#: utils/misc/tzparser.c:73 #, c-format msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "" "смещение часового пояса %d выходит за рамки (файл часовых поясов \"%s\", " "строка %d)" -#: utils/misc/tzparser.c:111 +#: utils/misc/tzparser.c:112 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "" "отсутствует краткое обозначение часового пояса (файл часовых поясов \"%s\", " "строка %d)" -#: utils/misc/tzparser.c:120 +#: utils/misc/tzparser.c:121 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "" "отсутствует смещение часового пояса (файл часовых поясов \"%s\", строка %d)" -#: utils/misc/tzparser.c:132 +#: utils/misc/tzparser.c:133 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "" "смещение часового пояса должно быть числом (файл часовых поясов \"%s\", " "строка %d)" -#: utils/misc/tzparser.c:168 +#: utils/misc/tzparser.c:169 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "ошибка синтаксиса в файле часовых поясов \"%s\", строке %d" -#: utils/misc/tzparser.c:236 +#: utils/misc/tzparser.c:237 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "краткое обозначение часового пояса \"%s\" определено неоднократно" -#: utils/misc/tzparser.c:238 +#: utils/misc/tzparser.c:239 #, c-format msgid "" "Entry in time zone file \"%s\", line %d, conflicts with entry in file " @@ -33011,86 +34531,84 @@ msgstr "" "Запись в файле часовых поясов \"%s\", строке %d, противоречит записи в файле " "\"%s\", строке %d." -#: utils/misc/tzparser.c:300 +#: utils/misc/tzparser.c:301 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "неправильное имя файла часовых поясов: \"%s\"" -#: utils/misc/tzparser.c:313 +#: utils/misc/tzparser.c:314 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "предел вложенности файлов часовых поясов превышен в файле \"%s\"" -#: utils/misc/tzparser.c:352 utils/misc/tzparser.c:365 +#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "прочитать файл часовых поясов \"%s\" не удалось: %m" -#: utils/misc/tzparser.c:376 +#: utils/misc/tzparser.c:377 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "слишком длинная строка в файле часовых поясов \"%s\" (строка %d)" -#: utils/misc/tzparser.c:400 +#: utils/misc/tzparser.c:401 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "" "в @INCLUDE не указано имя файла (файл часовых поясов \"%s\", строка %d)" -#: utils/mmgr/aset.c:446 utils/mmgr/generation.c:206 utils/mmgr/slab.c:367 +#: utils/mmgr/aset.c:452 utils/mmgr/bump.c:184 utils/mmgr/generation.c:216 +#: utils/mmgr/slab.c:371 #, c-format msgid "Failed while creating memory context \"%s\"." msgstr "Ошибка при создании контекста памяти \"%s\"." -#: utils/mmgr/dsa.c:532 utils/mmgr/dsa.c:1350 +#: utils/mmgr/dsa.c:523 utils/mmgr/dsa.c:1364 #, c-format msgid "could not attach to dynamic shared area" msgstr "не удалось подключиться к динамической разделяемой области" -#: utils/mmgr/mcxt.c:1047 utils/mmgr/mcxt.c:1083 utils/mmgr/mcxt.c:1121 -#: utils/mmgr/mcxt.c:1159 utils/mmgr/mcxt.c:1247 utils/mmgr/mcxt.c:1278 -#: utils/mmgr/mcxt.c:1314 utils/mmgr/mcxt.c:1503 utils/mmgr/mcxt.c:1548 -#: utils/mmgr/mcxt.c:1605 +#: utils/mmgr/mcxt.c:1155 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "Ошибка при запросе блока размером %zu в контексте памяти \"%s\"." -#: utils/mmgr/mcxt.c:1210 +#: utils/mmgr/mcxt.c:1299 #, c-format msgid "logging memory contexts of PID %d" msgstr "вывод информации о памяти процесса с PID %d" -#: utils/mmgr/portalmem.c:188 +#: utils/mmgr/portalmem.c:187 #, c-format msgid "cursor \"%s\" already exists" msgstr "курсор \"%s\" уже существует" -#: utils/mmgr/portalmem.c:192 +#: utils/mmgr/portalmem.c:191 #, c-format msgid "closing existing cursor \"%s\"" msgstr "существующий курсор (\"%s\") закрывается" -#: utils/mmgr/portalmem.c:402 +#: utils/mmgr/portalmem.c:401 #, c-format msgid "portal \"%s\" cannot be run" msgstr "портал \"%s\" не может быть запущен" -#: utils/mmgr/portalmem.c:480 +#: utils/mmgr/portalmem.c:479 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "удалить закреплённый портал \"%s\" нельзя" -#: utils/mmgr/portalmem.c:488 +#: utils/mmgr/portalmem.c:487 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "удалить активный портал \"%s\" нельзя" -#: utils/mmgr/portalmem.c:739 +#: utils/mmgr/portalmem.c:738 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "нельзя выполнить PREPARE для транзакции, создавшей курсор WITH HOLD" -#: utils/mmgr/portalmem.c:1230 +#: utils/mmgr/portalmem.c:1232 #, c-format msgid "" "cannot perform transaction commands inside a cursor loop that is not read-" @@ -33101,15 +34619,15 @@ msgstr "" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %ld of temporary file" -msgstr "не удалось переместиться к блоку %ld временного файла" +msgid "could not seek to block %lld of temporary file" +msgstr "не удалось переместиться к блоку %lld временного файла" -#: utils/sort/sharedtuplestore.c:467 +#: utils/sort/sharedtuplestore.c:466 #, c-format msgid "unexpected chunk in shared tuplestore temporary file" msgstr "неожиданный фрагмент в файле общего временного хранилища кортежей" -#: utils/sort/sharedtuplestore.c:549 +#: utils/sort/sharedtuplestore.c:548 #, c-format msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "" @@ -33121,17 +34639,17 @@ msgstr "" msgid "cannot have more than %d runs for an external sort" msgstr "число потоков данных для внешней сортировки не может превышать %d" -#: utils/sort/tuplesortvariants.c:1363 +#: utils/sort/tuplesortvariants.c:1552 #, c-format msgid "could not create unique index \"%s\"" msgstr "создать уникальный индекс \"%s\" не удалось" -#: utils/sort/tuplesortvariants.c:1365 +#: utils/sort/tuplesortvariants.c:1554 #, c-format msgid "Key %s is duplicated." msgstr "Ключ %s дублируется." -#: utils/sort/tuplesortvariants.c:1366 +#: utils/sort/tuplesortvariants.c:1555 #, c-format msgid "Duplicate keys exist." msgstr "Данные содержат дублирующиеся ключи." @@ -33145,32 +34663,32 @@ msgstr "Данные содержат дублирующиеся ключи." msgid "could not seek in tuplestore temporary file" msgstr "не удалось переместиться во временном файле хранилища кортежей" -#: utils/time/snapmgr.c:571 +#: utils/time/snapmgr.c:536 #, c-format msgid "The source transaction is not running anymore." msgstr "Исходная транзакция уже не выполняется." -#: utils/time/snapmgr.c:1166 +#: utils/time/snapmgr.c:1136 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "экспортировать снимок из вложенной транзакции нельзя" -#: utils/time/snapmgr.c:1325 utils/time/snapmgr.c:1330 -#: utils/time/snapmgr.c:1335 utils/time/snapmgr.c:1350 -#: utils/time/snapmgr.c:1355 utils/time/snapmgr.c:1360 -#: utils/time/snapmgr.c:1375 utils/time/snapmgr.c:1380 -#: utils/time/snapmgr.c:1385 utils/time/snapmgr.c:1487 -#: utils/time/snapmgr.c:1503 utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 +#: utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 +#: utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 +#: utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 +#: utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 +#: utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "неверные данные снимка в файле \"%s\"" -#: utils/time/snapmgr.c:1422 +#: utils/time/snapmgr.c:1393 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "команда SET TRANSACTION SNAPSHOT должна выполняться до запросов" -#: utils/time/snapmgr.c:1431 +#: utils/time/snapmgr.c:1402 #, c-format msgid "" "a snapshot-importing transaction must have isolation level SERIALIZABLE or " @@ -33179,12 +34697,17 @@ msgstr "" "транзакция, импортирующая снимок, должна иметь уровень изоляции SERIALIZABLE " "или REPEATABLE READ" -#: utils/time/snapmgr.c:1440 utils/time/snapmgr.c:1449 +#: utils/time/snapmgr.c:1411 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "неверный идентификатор снимка: \"%s\"" -#: utils/time/snapmgr.c:1541 +#: utils/time/snapmgr.c:1426 +#, c-format +msgid "snapshot \"%s\" does not exist" +msgstr "снимок \"%s\" не существует" + +#: utils/time/snapmgr.c:1524 #, c-format msgid "" "a serializable transaction cannot import a snapshot from a non-serializable " @@ -33192,7 +34715,7 @@ msgid "" msgstr "" "сериализуемая транзакция не может импортировать снимок из не сериализуемой" -#: utils/time/snapmgr.c:1545 +#: utils/time/snapmgr.c:1528 #, c-format msgid "" "a non-read-only serializable transaction cannot import a snapshot from a " @@ -33201,279 +34724,294 @@ msgstr "" "сериализуемая транзакция в режиме \"чтение-запись\" не может импортировать " "снимок из транзакции в режиме \"только чтение\"" -#: utils/time/snapmgr.c:1560 +#: utils/time/snapmgr.c:1543 #, c-format msgid "cannot import a snapshot from a different database" msgstr "нельзя импортировать снимок из другой базы данных" -#: gram.y:1197 +#: gram.y:1231 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "вариант UNENCRYPTED PASSWORD более не поддерживается" -#: gram.y:1198 +#: gram.y:1232 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." msgstr "" "Удалите слово UNENCRYPTED, чтобы сохранить пароль в зашифрованном виде." -#: gram.y:1525 gram.y:1541 +#: gram.y:1559 gram.y:1575 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "CREATE SCHEMA IF NOT EXISTS не может включать элементы схемы" -#: gram.y:1693 +#: gram.y:1727 #, c-format msgid "current database cannot be changed" msgstr "сменить текущую базу данных нельзя" -#: gram.y:1826 +#: gram.y:1860 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "" "интервал, задающий часовой пояс, должен иметь точность HOUR или HOUR TO " "MINUTE" -#: gram.y:2443 +#: gram.y:2487 #, c-format msgid "column number must be in range from 1 to %d" msgstr "номер столбца должен быть в диапазоне от 1 до %d" -#: gram.y:3039 +#: gram.y:3083 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "параметр последовательности \"%s\" здесь не поддерживается" -#: gram.y:3068 +#: gram.y:3122 #, c-format msgid "modulus for hash partition provided more than once" msgstr "модуль для хеш-секции указан неоднократно" -#: gram.y:3077 +#: gram.y:3131 #, c-format msgid "remainder for hash partition provided more than once" msgstr "остаток для хеш-секции указан неоднократно" -#: gram.y:3084 +#: gram.y:3138 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "нераспознанное указание ограничения хеш-секции \"%s\"" -#: gram.y:3092 +#: gram.y:3146 #, c-format msgid "modulus for hash partition must be specified" msgstr "необходимо указать модуль для хеш-секции" -#: gram.y:3096 +#: gram.y:3150 #, c-format msgid "remainder for hash partition must be specified" msgstr "необходимо указать остаток для хеш-секции" -#: gram.y:3304 gram.y:3338 +#: gram.y:3358 gram.y:3392 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "указания STDIN/STDOUT несовместимы с PROGRAM" -#: gram.y:3310 +#: gram.y:3364 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "предложение WHERE не допускается с COPY TO" -#: gram.y:3649 gram.y:3656 gram.y:12821 gram.y:12829 +#: gram.y:3712 gram.y:3719 gram.y:13023 gram.y:13031 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "указание GLOBAL при создании временных таблиц устарело" -#: gram.y:3932 +#: gram.y:3995 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" msgstr "для генерируемого столбца должно указываться GENERATED ALWAYS" -#: gram.y:4315 +#: gram.y:4432 #, c-format msgid "a column list with %s is only supported for ON DELETE actions" msgstr "список столбцов с %s поддерживается только для действий ON DELETE" -#: gram.y:5027 +#: gram.y:5151 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM более не поддерживается" -#: gram.y:5725 +#: gram.y:5849 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "нераспознанный вариант политики безопасности строк \"%s\"" -#: gram.y:5726 +#: gram.y:5850 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." msgstr "" "В настоящее время поддерживаются только политики PERMISSIVE и RESTRICTIVE." -#: gram.y:5811 +#: gram.y:5935 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGER не поддерживается" -#: gram.y:5848 +#: gram.y:5972 msgid "duplicate trigger events specified" msgstr "события триггера повторяются" -#: gram.y:5997 +#: gram.y:6121 #, c-format msgid "conflicting constraint properties" msgstr "противоречащие характеристики ограничения" -#: gram.y:6096 +#: gram.y:6220 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "оператор CREATE ASSERTION ещё не реализован" -#: gram.y:6504 +#: gram.y:6537 +#, c-format +msgid "dropping an enum value is not implemented" +msgstr "удаление значения из перечисления не поддерживается" + +#: gram.y:6655 #, c-format msgid "RECHECK is no longer required" msgstr "RECHECK более не требуется" -#: gram.y:6505 +#: gram.y:6656 #, c-format msgid "Update your data type." msgstr "Обновите тип данных." -#: gram.y:8378 +#: gram.y:8529 #, c-format msgid "aggregates cannot have output arguments" msgstr "у агрегатных функций не может быть выходных аргументов" -#: gram.y:11054 gram.y:11073 +#: gram.y:11221 gram.y:11240 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "" "предложение WITH CHECK OPTION не поддерживается для рекурсивных представлений" -#: gram.y:12960 +#: gram.y:13162 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "синтаксис LIMIT #,# не поддерживается" -#: gram.y:12961 +#: gram.y:13163 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "Используйте отдельные предложения LIMIT и OFFSET." -#: gram.y:13821 +#: gram.y:14038 #, c-format msgid "only one DEFAULT value is allowed" msgstr "допускается только одно значение DEFAULT" -#: gram.y:13830 +#: gram.y:14047 #, c-format msgid "only one PATH value per column is allowed" msgstr "для столбца допускается только одно значение PATH" -#: gram.y:13839 +#: gram.y:14056 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "" "конфликтующие или избыточные объявления NULL/NOT NULL для столбца \"%s\"" -#: gram.y:13848 +#: gram.y:14065 #, c-format msgid "unrecognized column option \"%s\"" msgstr "нераспознанный параметр столбца \"%s\"" -#: gram.y:14102 +#: gram.y:14147 +#, c-format +msgid "only string constants are supported in JSON_TABLE path specification" +msgstr "в указании пути JSON_TABLE поддерживаются только строковые константы" + +#: gram.y:14469 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "тип float должен иметь точность минимум 1 бит" -#: gram.y:14111 +#: gram.y:14478 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "тип float должен иметь точность меньше 54 бит" -#: gram.y:14614 +#: gram.y:14995 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "неверное число параметров в левой части выражения OVERLAPS" -#: gram.y:14619 +#: gram.y:15000 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "неверное число параметров в правой части выражения OVERLAPS" -#: gram.y:14796 +#: gram.y:15177 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "предикат UNIQUE ещё не реализован" -#: gram.y:15212 +#: gram.y:15591 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "ORDER BY с WITHIN GROUP можно указать только один раз" -#: gram.y:15217 +#: gram.y:15596 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "DISTINCT нельзя использовать с WITHIN GROUP" -#: gram.y:15222 +#: gram.y:15601 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "VARIADIC нельзя использовать с WITHIN GROUP" -#: gram.y:15856 gram.y:15880 +#: gram.y:16328 gram.y:16352 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "началом рамки не может быть UNBOUNDED FOLLOWING" -#: gram.y:15861 +#: gram.y:16333 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "" "рамка, начинающаяся со следующей строки, не может заканчиваться текущей" -#: gram.y:15885 +#: gram.y:16357 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "концом рамки не может быть UNBOUNDED PRECEDING" -#: gram.y:15891 +#: gram.y:16363 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "" "рамка, начинающаяся с текущей строки, не может иметь предшествующих строк" -#: gram.y:15898 +#: gram.y:16370 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "" "рамка, начинающаяся со следующей строки, не может иметь предшествующих строк" -#: gram.y:16659 +#: gram.y:16919 +#, c-format +msgid "unrecognized JSON encoding: %s" +msgstr "нераспознанная кодировка JSON: %s" + +#: gram.y:17243 #, c-format msgid "type modifier cannot have parameter name" msgstr "параметр функции-модификатора типа должен быть безымянным" -#: gram.y:16665 +#: gram.y:17249 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "модификатор типа не может включать ORDER BY" -#: gram.y:16733 gram.y:16740 gram.y:16747 +#: gram.y:17317 gram.y:17324 gram.y:17331 #, c-format msgid "%s cannot be used as a role name here" msgstr "%s нельзя использовать здесь как имя роли" -#: gram.y:16837 gram.y:18294 +#: gram.y:17421 gram.y:18906 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" msgstr "WITH TIES нельзя задать без предложения ORDER BY" -#: gram.y:17973 gram.y:18160 +#: gram.y:18597 gram.y:18772 msgid "improper use of \"*\"" msgstr "недопустимое использование \"*\"" -#: gram.y:18224 +#: gram.y:18836 #, c-format msgid "" "an ordered-set aggregate with a VARIADIC direct argument must have one " @@ -33482,70 +35020,70 @@ msgstr "" "сортирующая агрегатная функция с непосредственным аргументом VARIADIC должна " "иметь один агрегатный аргумент VARIADIC того же типа данных" -#: gram.y:18261 +#: gram.y:18873 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "ORDER BY можно указать только один раз" -#: gram.y:18272 +#: gram.y:18884 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "OFFSET можно указать только один раз" -#: gram.y:18281 +#: gram.y:18893 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "LIMIT можно указать только один раз" -#: gram.y:18290 +#: gram.y:18902 #, c-format msgid "multiple limit options not allowed" msgstr "параметры LIMIT можно указать только один раз" -#: gram.y:18317 +#: gram.y:18929 #, c-format msgid "multiple WITH clauses not allowed" msgstr "WITH можно указать только один раз" -#: gram.y:18510 +#: gram.y:19122 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "в табличных функциях не может быть аргументов OUT и INOUT" -#: gram.y:18643 +#: gram.y:19255 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "COLLATE можно указать только один раз" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18681 gram.y:18694 +#: gram.y:19293 gram.y:19306 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "ограничения %s не могут иметь характеристики DEFERRABLE" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18707 +#: gram.y:19319 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "ограничения %s не могут иметь характеристики NOT VALID" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18720 +#: gram.y:19332 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "ограничения %s не могут иметь характеристики NO INHERIT" -#: gram.y:18742 +#: gram.y:19354 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "нераспознанная стратегия секционирования \"%s\"" -#: gram.y:18766 +#: gram.y:19378 #, c-format msgid "invalid publication object list" msgstr "неверный список объектов публикации" -#: gram.y:18767 +#: gram.y:19379 #, c-format msgid "" "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table " @@ -33554,22 +35092,22 @@ msgstr "" "Перед именем отдельной таблицы или схемы нужно указать TABLE либо TABLES IN " "SCHEMA." -#: gram.y:18783 +#: gram.y:19395 #, c-format msgid "invalid table name" msgstr "неверное имя таблицы" -#: gram.y:18804 +#: gram.y:19416 #, c-format msgid "WHERE clause not allowed for schema" msgstr "предложение WHERE не допускается для схемы" -#: gram.y:18811 +#: gram.y:19423 #, c-format msgid "column specification not allowed for schema" msgstr "указание столбца не допускается для схемы" -#: gram.y:18825 +#: gram.y:19437 #, c-format msgid "invalid schema name" msgstr "неверное имя схемы" @@ -33618,12 +35156,18 @@ msgstr "" "обнаружено слишком много синтаксических ошибок, обработка файла \"%s\" " "прекращается" -#: jsonpath_gram.y:529 +# skip-rule: space-after-comma, space-before-period +#: jsonpath_gram.y:267 +#, c-format +msgid ".decimal() can only have an optional precision[,scale]." +msgstr "Аргументами .decimal() могут быть только точность[,масштаб]." + +#: jsonpath_gram.y:599 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." msgstr "Нераспознанный символ флага \"%.*s\" в предикате LIKE_REGEX." -#: jsonpath_gram.y:607 +#: jsonpath_gram.y:677 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "" @@ -33641,7 +35185,7 @@ msgstr "неверная последовательность шестнадца msgid "unexpected end after backslash" msgstr "неожиданный конец строки после обратной косой черты" -#: jsonpath_scan.l:201 repl_scanner.l:209 scan.l:741 +#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:756 msgid "unterminated quoted string" msgstr "незавершённая строка в кавычках" @@ -33653,8 +35197,8 @@ msgstr "неожиданный конец комментария" msgid "invalid numeric literal" msgstr "неверная числовая строка" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1049 -#: scan.l:1053 scan.l:1057 scan.l:1061 scan.l:1065 scan.l:1069 scan.l:1073 +#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1064 +#: scan.l:1068 scan.l:1072 scan.l:1076 msgid "trailing junk after numeric literal" msgstr "мусорное содержимое после числовой константы" @@ -33670,70 +35214,70 @@ msgstr "%s в конце аргумента jsonpath" msgid "%s at or near \"%s\" of jsonpath input" msgstr "%s в строке jsonpath (примерное положение: \"%s\")" -#: jsonpath_scan.l:557 +#: jsonpath_scan.l:568 msgid "invalid input" msgstr "некорректные входные данные" -#: jsonpath_scan.l:583 +#: jsonpath_scan.l:594 msgid "invalid hexadecimal digit" msgstr "неверная шестнадцатеричная цифра" -#: jsonpath_scan.l:614 +#: jsonpath_scan.l:625 #, c-format msgid "could not convert Unicode to server encoding" msgstr "не удалось преобразовать символ Unicode в серверную кодировку" -#: repl_gram.y:301 repl_gram.y:333 +#: repl_gram.y:318 repl_gram.y:359 #, c-format msgid "invalid timeline %u" msgstr "неверная линия времени %u" -#: repl_scanner.l:152 +#: repl_scanner.l:154 msgid "invalid streaming start location" msgstr "неверная позиция начала потока" -#: scan.l:482 +#: scan.l:497 msgid "unterminated /* comment" msgstr "незавершённый комментарий /*" -#: scan.l:502 +#: scan.l:517 msgid "unterminated bit string literal" msgstr "оборванная битовая строка" -#: scan.l:516 +#: scan.l:531 msgid "unterminated hexadecimal string literal" msgstr "оборванная шестнадцатеричная строка" -#: scan.l:566 +#: scan.l:581 #, c-format msgid "unsafe use of string constant with Unicode escapes" msgstr "небезопасное использование строковой константы со спецкодами Unicode" -#: scan.l:567 +#: scan.l:582 #, c-format msgid "" "String constants with Unicode escapes cannot be used when " -"standard_conforming_strings is off." +"\"standard_conforming_strings\" is off." msgstr "" "Строки со спецкодами Unicode нельзя использовать, когда параметр " -"standard_conforming_strings выключен." +"\"standard_conforming_strings\" выключен." -#: scan.l:628 +#: scan.l:643 msgid "unhandled previous state in xqs" msgstr "" "необрабатываемое предыдущее состояние при обнаружении закрывающего апострофа" -#: scan.l:702 +#: scan.l:717 #, c-format msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX." msgstr "Спецкоды Unicode должны иметь вид \\uXXXX или \\UXXXXXXXX." -#: scan.l:713 +#: scan.l:728 #, c-format msgid "unsafe use of \\' in a string literal" msgstr "небезопасное использование символа \\' в строке" -#: scan.l:714 +#: scan.l:729 #, c-format msgid "" "Use '' to write quotes in strings. \\' is insecure in client-only encodings." @@ -33741,56 +35285,56 @@ msgstr "" "Записывайте апостроф в строке в виде ''. Запись \\' небезопасна для " "исключительно клиентских кодировок." -#: scan.l:786 +#: scan.l:801 msgid "unterminated dollar-quoted string" msgstr "незавершённая строка с $" -#: scan.l:803 scan.l:813 +#: scan.l:818 scan.l:828 msgid "zero-length delimited identifier" msgstr "пустой идентификатор в кавычках" -#: scan.l:824 syncrep_scanner.l:101 +#: scan.l:839 syncrep_scanner.l:101 msgid "unterminated quoted identifier" msgstr "незавершённый идентификатор в кавычках" -#: scan.l:987 +#: scan.l:1002 msgid "operator too long" msgstr "слишком длинный оператор" -#: scan.l:1000 +#: scan.l:1015 msgid "trailing junk after parameter" msgstr "мусорное содержимое после параметра" -#: scan.l:1021 +#: scan.l:1036 msgid "invalid hexadecimal integer" msgstr "неверное шестнадцатеричное целое" -#: scan.l:1025 +#: scan.l:1040 msgid "invalid octal integer" msgstr "неверное восьмеричное целое" -#: scan.l:1029 +#: scan.l:1044 msgid "invalid binary integer" msgstr "неверное двоичное целое" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1236 +#: scan.l:1239 #, c-format msgid "%s at end of input" msgstr "%s в конце" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1244 +#: scan.l:1247 #, c-format msgid "%s at or near \"%s\"" msgstr "%s (примерное положение: \"%s\")" -#: scan.l:1434 +#: scan.l:1439 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "нестандартное применение \\' в строке" -#: scan.l:1435 +#: scan.l:1440 #, c-format msgid "" "Use '' to write quotes in strings, or use the escape string syntax (E'...')." @@ -33798,27 +35342,323 @@ msgstr "" "Записывайте апостроф в строках в виде '' или используйте синтаксис спецстрок " "(E'...')." -#: scan.l:1444 +#: scan.l:1449 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "нестандартное применение \\\\ в строке" -#: scan.l:1445 +#: scan.l:1450 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "" "Используйте для записи обратных слэшей синтаксис спецстрок, например E'\\\\'." -#: scan.l:1459 +#: scan.l:1464 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "нестандартное использование спецсимвола в строке" -#: scan.l:1460 +#: scan.l:1465 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "Используйте для записи спецсимволов синтаксис спецстрок E'\\r\\n'." +#, c-format +#~ msgid "cannot use RETURNING type %s in %s" +#~ msgstr "использовать в RETURNING тип %s в %s нельзя" + +#, c-format +#~ msgid "Please report this to <%s>." +#~ msgstr "Пожалуйста, напишите об этой ошибке по адресу <%s>." + +#, c-format +#~ msgid "MinWords should be less than MaxWords" +#~ msgstr "Значение MinWords должно быть меньше MaxWords" + +#, c-format +#~ msgid "MinWords should be positive" +#~ msgstr "Значение MinWords должно быть положительным" + +#, c-format +#~ msgid "ShortWord should be >= 0" +#~ msgstr "Значение ShortWord должно быть >= 0" + +#, c-format +#~ msgid "MaxFragments should be >= 0" +#~ msgstr "Значение MaxFragments должно быть >= 0" + +#, c-format +#~ msgid "" +#~ "database is not accepting commands to avoid wraparound data loss in " +#~ "database \"%s\"" +#~ msgstr "" +#~ "база данных не принимает команды во избежание потери данных из-за " +#~ "зацикливания транзакций в базе данных \"%s\"" + +#, c-format +#~ msgid "" +#~ "Stop the postmaster and vacuum that database in single-user mode.\n" +#~ "You might also need to commit or roll back old prepared transactions, or " +#~ "drop stale replication slots." +#~ msgstr "" +#~ "Остановите управляющий процесс (postmaster) и выполните очистку (VACUUM) " +#~ "базы данных в монопольном режиме.\n" +#~ "Возможно, вам также придётся зафиксировать или откатить старые " +#~ "подготовленные транзакции и удалить неиспользуемые слоты репликации." + +#, c-format +#~ msgid "" +#~ "database is not accepting commands to avoid wraparound data loss in " +#~ "database with OID %u" +#~ msgstr "" +#~ "база данных не принимает команды во избежание потери данных из-за " +#~ "зацикливания транзакций в базе данных с OID %u" + +#, c-format +#~ msgid "cannot commit subtransactions during a parallel operation" +#~ msgstr "фиксировать подтранзакции во время параллельных операций нельзя" + +#, c-format +#~ msgid "invalid segment number %d in file \"%s\"" +#~ msgstr "неверный номер сегмента %d в файле \"%s\"" + +#, c-format +#~ msgid "-X requires a power of two value between 1 MB and 1 GB" +#~ msgstr "" +#~ "для -X требуется число, равное степени двух, в интервале от 1 МБ до 1 ГБ" + +#, c-format +#~ msgid "invalid parameter name \"%s\"" +#~ msgstr "неверное имя параметра \"%s\"" + +#, c-format +#~ msgid "MERGE not supported in COPY" +#~ msgstr "MERGE не поддерживается в COPY" + +#, c-format +#~ msgid "cannot specify DELIMITER in BINARY mode" +#~ msgstr "в режиме BINARY нельзя указывать DELIMITER" + +#, c-format +#~ msgid "cannot specify DEFAULT in BINARY mode" +#~ msgstr "в режиме BINARY нельзя указывать DEFAULT" + +#, c-format +#~ msgid "cannot specify HEADER in BINARY mode" +#~ msgstr "в режиме BINARY нельзя использовать HEADER" + +#, c-format +#~ msgid "COPY quote available only in CSV mode" +#~ msgstr "определить кавычки для COPY можно только в режиме CSV" + +#, c-format +#~ msgid "COPY escape available only in CSV mode" +#~ msgstr "определить спецсимвол для COPY можно только в режиме CSV" + +#, c-format +#~ msgid "COPY force quote available only in CSV mode" +#~ msgstr "" +#~ "параметр force quote для COPY можно использовать только в режиме CSV" + +#, c-format +#~ msgid "COPY force quote only available using COPY TO" +#~ msgstr "параметр force quote для COPY можно использовать только с COPY TO" + +#, c-format +#~ msgid "COPY force not null available only in CSV mode" +#~ msgstr "" +#~ "параметр force not null для COPY можно использовать только в режиме CSV" + +#, c-format +#~ msgid "COPY force not null only available using COPY FROM" +#~ msgstr "" +#~ "параметр force not null для COPY можно использовать только с COPY FROM" + +#, c-format +#~ msgid "COPY force null available only in CSV mode" +#~ msgstr "параметр force null для COPY можно использовать только в режиме CSV" + +#, c-format +#~ msgid "COPY force null only available using COPY FROM" +#~ msgstr "параметр force null для COPY можно использовать только с COPY FROM" + +#, c-format +#~ msgid "COPY DEFAULT only available using COPY FROM" +#~ msgstr "параметр DEFAULT для COPY можно использовать только с COPY FROM" + +#, c-format +#~ msgid "COPY delimiter must not appear in the DEFAULT specification" +#~ msgstr "" +#~ "разделитель для COPY не должен присутствовать в представлении DEFAULT" + +#, c-format +#~ msgid "CSV quote character must not appear in the DEFAULT specification" +#~ msgstr "" +#~ "символ кавычек в CSV не должен присутствовать в представлении DEFAULT" + +#, c-format +#~ msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" +#~ msgstr "столбец FORCE_NOT_NULL \"%s\" не фигурирует в COPY" + +#, c-format +#~ msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" +#~ msgstr "столбец FORCE_QUOTE \"%s\" не фигурирует в COPY" + +#, c-format +#~ msgid "cannot create exclusion constraints on partitioned table \"%s\"" +#~ msgstr "" +#~ "создать ограничение-исключение в секционированной таблице \"%s\" нельзя" + +#, c-format +#~ msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" +#~ msgstr "" +#~ "перестроить нерабочий индекс \"%s.%s\" неблокирующим способом нельзя, он " +#~ "пропускается" + +#, c-format +#~ msgid "" +#~ "specifying a table access method is not supported on a partitioned table" +#~ msgstr "" +#~ "указание табличного метода доступа для секционированных таблиц не " +#~ "поддерживаются" + +#, c-format +#~ msgid "cannot change access method of a partitioned table" +#~ msgstr "менять метод доступа для секционированной таблицы нельзя" + +#, c-format +#~ msgid "" +#~ "MD5 authentication is not supported when \"db_user_namespace\" is enabled" +#~ msgstr "" +#~ "проверка подлинности MD5 не поддерживается, когда включён режим " +#~ "\"db_user_namespace\"" + +#, c-format +#~ msgid "could not unbind after searching for user \"%s\" on server \"%s\"" +#~ msgstr "" +#~ "не удалось отвязаться после поиска пользователя \"%s\" на сервере \"%s\"" + +#, c-format +#~ msgid "MERGE not supported in WITH query" +#~ msgstr "MERGE не поддерживается в запросе WITH" + +#, c-format +#~ msgid "IS DISTINCT FROM requires = operator to yield boolean" +#~ msgstr "" +#~ "для IS DISTINCT FROM требуется, чтобы оператор = возвращал логическое " +#~ "значение" + +#, c-format +#~ msgid "could not fork autovacuum launcher process: %m" +#~ msgstr "породить процесс запуска автоочистки не удалось: %m" + +#, c-format +#~ msgid "could not fork autovacuum worker process: %m" +#~ msgstr "не удалось породить рабочий процесс автоочистки: %m" + +#, c-format +#~ msgid "" +#~ "Consider increasing the configuration parameter \"max_worker_processes\"." +#~ msgstr "Возможно, стоит увеличить параметр \"max_worker_processes\"." + +#, c-format +#~ msgid "could not fork startup process: %m" +#~ msgstr "породить стартовый процесс не удалось: %m" + +#, c-format +#~ msgid "could not fork archiver process: %m" +#~ msgstr "породить процесс архиватора не удалось: %m" + +#, c-format +#~ msgid "could not fork checkpointer process: %m" +#~ msgstr "породить процесс контрольных точек не удалось: %m" + +#, c-format +#~ msgid "could not fork WAL writer process: %m" +#~ msgstr "породить процесс записи WAL не удалось: %m" + +#, c-format +#~ msgid "could not fork WAL receiver process: %m" +#~ msgstr "породить процесс считывания WAL не удалось: %m" + +#, c-format +#~ msgid "could not fork worker process: %m" +#~ msgstr "породить рабочий процесс не удалось: %m" + +#, c-format +#~ msgid "could not remove file \"%s\": %s\n" +#~ msgstr "не удалось стереть файл \"%s\": %s\n" + +#, c-format +#~ msgid "publication_names parameter missing" +#~ msgstr "отсутствует параметр publication_names" + +#, c-format +#~ msgid "snapshot too old" +#~ msgstr "снимок слишком стар" + +#, c-format +#~ msgid "must be superuser to rotate log files with adminpack 1.0" +#~ msgstr "" +#~ "прокручивать файлы протоколов, используя adminpack 1.0, может только " +#~ "суперпользователь" + +#, c-format +#~ msgid "Consider using %s, which is part of core, instead." +#~ msgstr "" +#~ "Рассмотрите возможность использования функции %s, включённой в ядро." + +#, c-format +#~ msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" +#~ msgstr "не удалось записать блок %u в файл \"%s\" (записано байт: %d из %d)" + +#, c-format +#~ msgid "Unmatched \"%c\" character." +#~ msgstr "Непарный знак \"%c\"." + +#, c-format +#~ msgid "formatting field \"%s\" is only supported in to_char" +#~ msgstr "поле форматирования \"%s\" поддерживается только в функции to_char" + +#, c-format +#~ msgid "must be superuser to read files with adminpack 1.0" +#~ msgstr "" +#~ "читать файлы, используя adminpack 1.0, может только суперпользователь" + +#, c-format +#~ msgid "" +#~ "string argument of jsonpath item method .%s() is not a valid " +#~ "representation of a double precision number" +#~ msgstr "" +#~ "строковый аргумент метода элемента jsonpath .%s() не является " +#~ "представлением значения double precision" + +#, c-format +#~ msgid "collation provider LIBC is not supported on this platform" +#~ msgstr "" +#~ "провайдер правил сортировки LIBC не поддерживается на этой платформе" + +#, c-format +#~ msgid "cannot subtract infinite timestamps" +#~ msgstr "вычитать бесконечные значения timestamp нельзя" + +#~ msgid "Enables per-database user names." +#~ msgstr "Включает связывание имён пользователей с базами данных." + +#~ msgid "" +#~ "Time before a snapshot is too old to read pages changed after the " +#~ "snapshot was taken." +#~ msgstr "" +#~ "Срок, по истечении которого снимок считается слишком старым для получения " +#~ "страниц, изменённых после создания снимка." + +#~ msgid "A value of -1 disables this feature." +#~ msgstr "Значение -1 отключает это поведение." + +#~ msgid "Enables logging of recovery-related debugging information." +#~ msgstr "" +#~ "Включает протоколирование отладочной информации, связанной с репликацией." + #, c-format #~ msgid "out of memory while trying to decode a record of length %u" #~ msgstr "не удалось выделить память для декодирования записи длины %u" @@ -34216,10 +36056,6 @@ msgstr "Используйте для записи спецсимволов си #~ "слот \"%s\" аннулируется, так как его позиция restart_lsn %X/%X превышает " #~ "max_slot_wal_keep_size" -#, c-format -#~ msgid "cannot read from logical replication slot \"%s\"" -#~ msgstr "прочитать из слота логической репликации \"%s\" нельзя" - #, c-format #~ msgid "cannot convert partitioned table \"%s\" to a view" #~ msgstr "" @@ -34450,9 +36286,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "oidvector has too many elements" #~ msgstr "oidvector содержит слишком много элементов" -#~ msgid "Enables reordering of GROUP BY keys." -#~ msgstr "Включает переупорядочивание ключей GROUP BY." - #~ msgid "unknown compression option \"%s\"" #~ msgstr "неизвестный параметр сжатия \"%s\"" @@ -34522,14 +36355,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "JSON_TABLE path name is not allowed here" #~ msgstr "SELECT ... INTO здесь не допускается" -#, fuzzy -#~ msgid "JSON path expression must be type %s, not type %s" -#~ msgstr "аргумент конструкции %s должен иметь тип %s, а не %s" - -#, fuzzy -#~ msgid "cannot cast DEFAULT expression type %s to %s" -#~ msgstr "привести тип %s к %s нельзя" - #, fuzzy #~ msgid "JSON_TABLE() is not yet implemented for the json type" #~ msgstr "REINDEX для секционированных индексов ещё не реализован" @@ -34538,10 +36363,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "%s() is not yet implemented for the json type" #~ msgstr "политики для этой команды ещё не реализованы" -#, fuzzy -#~ msgid "cannot use RETURNING type %s in %s" -#~ msgstr "привести тип %s к %s нельзя" - #, fuzzy #~ msgid "invalid JSON_TABLE plan" #~ msgstr "неверное указание OWNED BY" @@ -34988,9 +36809,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "Writes temporary statistics files to the specified directory." #~ msgstr "Каталог, в который будут записываться временные файлы статистики." -#~ msgid "must be superuser to execute ALTER SYSTEM command" -#~ msgstr "выполнить команду ALTER SYSTEM может только суперпользователь" - #~ msgid "" #~ "query-specified return tuple and function return type are not compatible" #~ msgstr "" @@ -35767,9 +37585,6 @@ msgstr "Используйте для записи спецсимволов си #~ "Этот параметр определяет, нужно ли шифровать пароли, заданные в CREATE " #~ "USER или ALTER USER без указания ENCRYPTED или UNENCRYPTED." -#~ msgid "\"%s\" cannot be lower than \"%s\"." -#~ msgstr "Версия \"%s\" не может быть ниже \"%s\"." - #~ msgid "could not write to temporary file: %m" #~ msgstr "не удалось записать во временный файл: %m" @@ -36287,9 +38102,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "using previous checkpoint record at %X/%X" #~ msgstr "используется предыдущая запись контрольной точки по смещению %X/%X" -#~ msgid "invalid secondary checkpoint link in control file" -#~ msgstr "неверная ссылка на вторичную контрольную точку в файле pg_control" - #~ msgid "invalid secondary checkpoint record" #~ msgstr "неверная запись вторичной контрольной точки" @@ -36400,9 +38212,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "data directory \"%s\" has group or world access" #~ msgstr "к каталогу данных \"%s\" имеют доступ все или группа" -#~ msgid "worker process" -#~ msgstr "рабочий процесс" - #~ msgid "built-in type %u not found" #~ msgstr "встроенный тип %u не найден" @@ -36417,13 +38226,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgstr "" #~ "тип данных \"%s.%s\", требуемый для логической репликации, не существует" -#~ msgid "" -#~ "logical replication could not find row for delete in replication target " -#~ "relation \"%s\"" -#~ msgstr "" -#~ "при логической репликации не удалось найти строку для удаления в целевом " -#~ "отношении репликации \"%s\"" - #~ msgid "memory for serializable conflict tracking is nearly exhausted" #~ msgstr "" #~ "память для отслеживания конфликтов сериализации практически исчерпана" @@ -36848,9 +38650,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgid "Proceeding with relation creation anyway." #~ msgstr "Несмотря на это, создание отношения продолжается." -#~ msgid "default expression must not return a set" -#~ msgstr "выражение по умолчанию не может возвращать множество" - #~ msgid "access method name cannot be qualified" #~ msgstr "имя метода доступа не может быть составным" @@ -37503,21 +39302,12 @@ msgstr "Используйте для записи спецсимволов си #~ "Для архивации WAL (archive_mode=on) wal_level должен быть \"archive\", " #~ "\"hot_standby\" или \"logical\"" -#~ msgid "postmaster became multithreaded" -#~ msgstr "процесс postmaster стал многопоточным" - #~ msgid "could not determine input data types" #~ msgstr "не удалось определить типы входных данных" #~ msgid "neither input type is an array" #~ msgstr "входной тип так же не является массивом" -#~ msgid "unexpected \"=\"" -#~ msgstr "неожиданный знак \"=\"" - -#~ msgid "invalid symbol" -#~ msgstr "неверный символ" - #~ msgid "" #~ "must be superuser or have the same role to cancel queries running in " #~ "other server processes" @@ -37574,11 +39364,6 @@ msgstr "Используйте для записи спецсимволов си #~ msgstr "" #~ "распознать идентификатор локального пользователя (%ld) не удалось: %s" -#~ msgid "cannot use physical replication slot created for logical decoding" -#~ msgstr "" -#~ "для логического декодирования нельзя использовать созданный физический " -#~ "слот репликации" - #~ msgid "" #~ "incomplete read from reorderbuffer spill file: read %d instead of %u bytes" #~ msgstr "" @@ -38065,9 +39850,6 @@ msgstr "Используйте для записи спецсимволов си #~ "Недостаточно памяти для переназначения блокировок подготовленных " #~ "транзакций." -#~ msgid "\"interval\" time zone \"%s\" not valid" -#~ msgstr "\"интервал\" содержит неверный часовой пояс \"%s\"" - #~ msgid "inconsistent use of year %04d and \"BC\"" #~ msgstr "несогласованное использование в годе %04d и \"BC\"" diff --git a/src/backend/po/sv.po b/src/backend/po/sv.po index 2d2e2272672d8..db87d04a3c232 100644 --- a/src/backend/po/sv.po +++ b/src/backend/po/sv.po @@ -1,5 +1,5 @@ # Swedish message translation file for postgresql -# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # # Många av termerna är tekniska termer som refererar till begrepp i SQL-satser # och liknande. Om man översätter vissa av dessa så kommer det bli väldigt @@ -21,10 +21,10 @@ # hänvisas till och inte någon annan städning. msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-23 02:45+0000\n" -"PO-Revision-Date: 2023-09-23 15:32+0200\n" +"POT-Creation-Date: 2025-02-12 13:46+0000\n" +"PO-Revision-Date: 2025-02-12 20:52+0100\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -33,6 +33,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#: ../common/binaryheap.c:121 ../common/binaryheap.c:159 +#, c-format +msgid "out of binary heap slots" +msgstr "slut på slottar i binär-heap" + #: ../common/compression.c:132 ../common/compression.c:141 #: ../common/compression.c:150 #, c-format @@ -90,64 +95,66 @@ msgstr "komprimeringsalgoritmen \"%s\" stöder inte långdistansläge" msgid "not recorded" msgstr "ej sparad" -#: ../common/controldata_utils.c:69 ../common/controldata_utils.c:73 -#: commands/copyfrom.c:1670 commands/extension.c:3480 utils/adt/genfile.c:123 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 +#: commands/copyfrom.c:1739 commands/extension.c:3538 utils/adt/genfile.c:123 +#: utils/time/snapmgr.c:1430 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "kunde inte öppna filen \"%s\" för läsning: %m" -#: ../common/controldata_utils.c:84 ../common/controldata_utils.c:86 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 #: access/transam/timeline.c:143 access/transam/timeline.c:362 -#: access/transam/twophase.c:1347 access/transam/xlog.c:3193 -#: access/transam/xlog.c:3996 access/transam/xlogrecovery.c:1199 -#: access/transam/xlogrecovery.c:1291 access/transam/xlogrecovery.c:1328 -#: access/transam/xlogrecovery.c:1388 backup/basebackup.c:1842 -#: commands/extension.c:3490 libpq/hba.c:769 replication/logical/origin.c:745 -#: replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5050 -#: replication/logical/snapbuild.c:2031 replication/slot.c:1953 -#: replication/slot.c:1994 replication/walsender.c:643 +#: access/transam/twophase.c:1353 access/transam/xlog.c:3477 +#: access/transam/xlog.c:4341 access/transam/xlogrecovery.c:1238 +#: access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 +#: access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 +#: backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 +#: replication/logical/reorderbuffer.c:5113 +#: replication/logical/snapbuild.c:2052 replication/slot.c:2236 +#: replication/slot.c:2277 replication/walsender.c:655 #: storage/file/buffile.c:470 storage/file/copydir.c:185 -#: utils/adt/genfile.c:197 utils/adt/misc.c:984 utils/cache/relmapper.c:827 +#: utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "kunde inte läsa fil \"%s\": %m" -#: ../common/controldata_utils.c:92 ../common/controldata_utils.c:95 -#: access/transam/xlog.c:3198 access/transam/xlog.c:4001 -#: backup/basebackup.c:1846 replication/logical/origin.c:750 -#: replication/logical/origin.c:789 replication/logical/snapbuild.c:2036 -#: replication/slot.c:1957 replication/slot.c:1998 replication/walsender.c:648 -#: utils/cache/relmapper.c:831 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 +#: access/transam/xlog.c:3482 access/transam/xlog.c:4346 +#: replication/logical/origin.c:750 replication/logical/origin.c:789 +#: replication/logical/snapbuild.c:2057 replication/slot.c:2240 +#: replication/slot.c:2281 replication/walsender.c:660 +#: utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" -#: ../common/controldata_utils.c:104 ../common/controldata_utils.c:108 -#: ../common/controldata_utils.c:233 ../common/controldata_utils.c:236 -#: access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1280 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 +#: ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 +#: access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 #: access/transam/timeline.c:392 access/transam/timeline.c:438 -#: access/transam/timeline.c:512 access/transam/twophase.c:1359 -#: access/transam/twophase.c:1771 access/transam/xlog.c:3039 -#: access/transam/xlog.c:3233 access/transam/xlog.c:3238 -#: access/transam/xlog.c:3374 access/transam/xlog.c:3966 -#: access/transam/xlog.c:4885 commands/copyfrom.c:1730 commands/copyto.c:332 +#: access/transam/timeline.c:512 access/transam/twophase.c:1365 +#: access/transam/twophase.c:1784 access/transam/xlog.c:3323 +#: access/transam/xlog.c:3517 access/transam/xlog.c:3522 +#: access/transam/xlog.c:3658 access/transam/xlog.c:4311 +#: access/transam/xlog.c:5246 commands/copyfrom.c:1799 commands/copyto.c:325 #: libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 #: replication/logical/origin.c:683 replication/logical/origin.c:822 -#: replication/logical/reorderbuffer.c:5102 -#: replication/logical/snapbuild.c:1798 replication/logical/snapbuild.c:1922 -#: replication/slot.c:1844 replication/slot.c:2005 replication/walsender.c:658 -#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:782 -#: storage/file/fd.c:3700 storage/file/fd.c:3806 utils/cache/relmapper.c:839 -#: utils/cache/relmapper.c:945 +#: replication/logical/reorderbuffer.c:5165 +#: replication/logical/snapbuild.c:1819 replication/logical/snapbuild.c:1943 +#: replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 +#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:828 +#: storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 +#: utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "kunde inte stänga fil \"%s\": %m" -#: ../common/controldata_utils.c:124 +#: ../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "byte-ordning stämmer inte" -#: ../common/controldata_utils.c:126 +#: ../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -160,141 +167,157 @@ msgstr "" "inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" "och PostgreSQL-installationen vara inkompatibel med databaskatalogen." -#: ../common/controldata_utils.c:181 ../common/controldata_utils.c:186 -#: ../common/file_utils.c:228 ../common/file_utils.c:287 -#: ../common/file_utils.c:361 access/heap/rewriteheap.c:1263 -#: access/transam/timeline.c:111 access/transam/timeline.c:251 -#: access/transam/timeline.c:348 access/transam/twophase.c:1303 -#: access/transam/xlog.c:2946 access/transam/xlog.c:3109 -#: access/transam/xlog.c:3148 access/transam/xlog.c:3341 -#: access/transam/xlog.c:3986 access/transam/xlogrecovery.c:4179 -#: access/transam/xlogrecovery.c:4282 access/transam/xlogutils.c:838 -#: backup/basebackup.c:538 backup/basebackup.c:1512 libpq/hba.c:629 -#: postmaster/syslogger.c:1560 replication/logical/origin.c:735 -#: replication/logical/reorderbuffer.c:3706 -#: replication/logical/reorderbuffer.c:4257 -#: replication/logical/reorderbuffer.c:5030 -#: replication/logical/snapbuild.c:1753 replication/logical/snapbuild.c:1863 -#: replication/slot.c:1925 replication/walsender.c:616 -#: replication/walsender.c:2731 storage/file/copydir.c:151 -#: storage/file/fd.c:757 storage/file/fd.c:3457 storage/file/fd.c:3687 -#: storage/file/fd.c:3777 storage/smgr/md.c:663 utils/cache/relmapper.c:816 -#: utils/cache/relmapper.c:924 utils/error/elog.c:2082 -#: utils/init/miscinit.c:1530 utils/init/miscinit.c:1664 -#: utils/init/miscinit.c:1741 utils/misc/guc.c:4600 utils/misc/guc.c:4650 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 +#: ../common/file_utils.c:70 ../common/file_utils.c:347 +#: ../common/file_utils.c:406 ../common/file_utils.c:480 +#: access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 +#: access/transam/timeline.c:251 access/transam/timeline.c:348 +#: access/transam/twophase.c:1309 access/transam/xlog.c:3230 +#: access/transam/xlog.c:3393 access/transam/xlog.c:3432 +#: access/transam/xlog.c:3625 access/transam/xlog.c:4331 +#: access/transam/xlogrecovery.c:4264 access/transam/xlogrecovery.c:4367 +#: access/transam/xlogutils.c:836 backup/basebackup.c:547 +#: backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 +#: postmaster/syslogger.c:1511 replication/logical/origin.c:735 +#: replication/logical/reorderbuffer.c:3766 +#: replication/logical/reorderbuffer.c:4320 +#: replication/logical/reorderbuffer.c:5093 +#: replication/logical/snapbuild.c:1774 replication/logical/snapbuild.c:1884 +#: replication/slot.c:2208 replication/walsender.c:628 +#: replication/walsender.c:3051 storage/file/copydir.c:151 +#: storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 +#: storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 +#: utils/cache/relmapper.c:935 utils/error/elog.c:2124 +#: utils/init/miscinit.c:1580 utils/init/miscinit.c:1714 +#: utils/init/miscinit.c:1791 utils/misc/guc.c:4777 utils/misc/guc.c:4827 #, c-format msgid "could not open file \"%s\": %m" msgstr "kunde inte öppna fil \"%s\": %m" -#: ../common/controldata_utils.c:202 ../common/controldata_utils.c:205 -#: access/transam/twophase.c:1744 access/transam/twophase.c:1753 -#: access/transam/xlog.c:8755 access/transam/xlogfuncs.c:708 -#: backup/basebackup_server.c:175 backup/basebackup_server.c:268 -#: postmaster/postmaster.c:5573 postmaster/syslogger.c:1571 -#: postmaster/syslogger.c:1584 postmaster/syslogger.c:1597 -#: utils/cache/relmapper.c:936 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 +#: access/transam/twophase.c:1757 access/transam/twophase.c:1766 +#: access/transam/xlog.c:9280 access/transam/xlogfuncs.c:698 +#: backup/basebackup_server.c:173 backup/basebackup_server.c:266 +#: backup/walsummary.c:304 postmaster/postmaster.c:4127 +#: postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 +#: postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "kunde inte skriva fil \"%s\": %m" -#: ../common/controldata_utils.c:219 ../common/controldata_utils.c:224 -#: ../common/file_utils.c:299 ../common/file_utils.c:369 -#: access/heap/rewriteheap.c:959 access/heap/rewriteheap.c:1169 -#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:432 -#: access/transam/timeline.c:506 access/transam/twophase.c:1765 -#: access/transam/xlog.c:3032 access/transam/xlog.c:3227 -#: access/transam/xlog.c:3959 access/transam/xlog.c:8145 -#: access/transam/xlog.c:8190 backup/basebackup_server.c:209 -#: replication/logical/snapbuild.c:1791 replication/slot.c:1830 -#: replication/slot.c:1935 storage/file/fd.c:774 storage/file/fd.c:3798 -#: storage/smgr/md.c:1135 storage/smgr/md.c:1180 storage/sync/sync.c:451 -#: utils/misc/guc.c:4370 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 +#: ../common/file_utils.c:418 ../common/file_utils.c:488 +#: access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 +#: access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 +#: access/transam/timeline.c:506 access/transam/twophase.c:1778 +#: access/transam/xlog.c:3316 access/transam/xlog.c:3511 +#: access/transam/xlog.c:4304 access/transam/xlog.c:8655 +#: access/transam/xlog.c:8700 backup/basebackup_server.c:207 +#: commands/dbcommands.c:514 replication/logical/snapbuild.c:1812 +#: replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 +#: storage/file/fd.c:3851 storage/smgr/md.c:1331 storage/smgr/md.c:1376 +#: storage/sync/sync.c:446 utils/misc/guc.c:4530 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "kunde inte fsync:a fil \"%s\": %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:133 -#: ../common/cryptohash_openssl.c:332 ../common/exec.c:550 ../common/exec.c:595 -#: ../common/exec.c:687 ../common/hmac.c:309 ../common/hmac.c:325 -#: ../common/hmac_openssl.c:132 ../common/hmac_openssl.c:327 -#: ../common/md5_common.c:155 ../common/psprintf.c:143 -#: ../common/scram-common.c:258 ../common/stringinfo.c:305 ../port/path.c:751 -#: ../port/path.c:789 ../port/path.c:806 access/transam/twophase.c:1412 -#: access/transam/xlogrecovery.c:589 lib/dshash.c:253 libpq/auth.c:1345 -#: libpq/auth.c:1389 libpq/auth.c:1946 libpq/be-secure-gssapi.c:524 -#: postmaster/bgworker.c:352 postmaster/bgworker.c:934 -#: postmaster/postmaster.c:2537 postmaster/postmaster.c:4130 -#: postmaster/postmaster.c:5498 postmaster/postmaster.c:5869 -#: replication/libpqwalreceiver/libpqwalreceiver.c:308 -#: replication/logical/logical.c:208 replication/walsender.c:686 -#: storage/buffer/localbuf.c:601 storage/file/fd.c:866 storage/file/fd.c:1397 -#: storage/file/fd.c:1558 storage/file/fd.c:2478 storage/ipc/procarray.c:1449 -#: storage/ipc/procarray.c:2232 storage/ipc/procarray.c:2239 -#: storage/ipc/procarray.c:2738 storage/ipc/procarray.c:3374 -#: utils/adt/formatting.c:1690 utils/adt/formatting.c:1812 -#: utils/adt/formatting.c:1935 utils/adt/pg_locale.c:473 -#: utils/adt/pg_locale.c:637 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:514 -#: utils/hash/dynahash.c:614 utils/hash/dynahash.c:1111 utils/mb/mbutils.c:402 -#: utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 utils/mb/mbutils.c:842 -#: utils/misc/guc.c:640 utils/misc/guc.c:665 utils/misc/guc.c:1053 -#: utils/misc/guc.c:4348 utils/misc/tzparser.c:476 utils/mmgr/aset.c:445 -#: utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:736 utils/mmgr/dsa.c:817 -#: utils/mmgr/generation.c:205 utils/mmgr/mcxt.c:1046 utils/mmgr/mcxt.c:1082 -#: utils/mmgr/mcxt.c:1120 utils/mmgr/mcxt.c:1158 utils/mmgr/mcxt.c:1246 -#: utils/mmgr/mcxt.c:1277 utils/mmgr/mcxt.c:1313 utils/mmgr/mcxt.c:1502 -#: utils/mmgr/mcxt.c:1547 utils/mmgr/mcxt.c:1604 utils/mmgr/slab.c:366 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 +#: ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 +#: ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 +#: ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 +#: ../common/md5_common.c:156 ../common/parse_manifest.c:157 +#: ../common/parse_manifest.c:852 ../common/psprintf.c:143 +#: ../common/scram-common.c:268 ../common/stringinfo.c:314 ../port/path.c:828 +#: ../port/path.c:865 ../port/path.c:882 access/transam/twophase.c:1418 +#: access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 +#: libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 +#: postmaster/bgworker.c:355 postmaster/bgworker.c:945 +#: postmaster/postmaster.c:3560 postmaster/postmaster.c:4021 +#: postmaster/postmaster.c:4383 postmaster/walsummarizer.c:935 +#: replication/libpqwalreceiver/libpqwalreceiver.c:387 +#: replication/logical/logical.c:210 replication/walsender.c:835 +#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 +#: storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1465 +#: storage/ipc/procarray.c:2219 storage/ipc/procarray.c:2226 +#: storage/ipc/procarray.c:2731 storage/ipc/procarray.c:3435 +#: utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 +#: utils/adt/formatting.c:2075 utils/adt/pg_locale.c:532 +#: utils/adt/pg_locale.c:696 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 +#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 +#: utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 +#: utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 +#: utils/misc/guc.c:4508 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 +#: utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 +#: utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 +#: utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "slut på minne" #: ../common/cryptohash.c:266 ../common/cryptohash.c:272 -#: ../common/cryptohash_openssl.c:344 ../common/cryptohash_openssl.c:352 -#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:339 -#: ../common/hmac_openssl.c:347 +#: ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 +#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 +#: ../common/hmac_openssl.c:377 msgid "success" msgstr "lyckades" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:346 -#: ../common/hmac_openssl.c:341 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 +#: ../common/hmac_openssl.c:371 msgid "destination buffer too small" msgstr "destinationsbuffer för liten" -#: ../common/cryptohash_openssl.c:348 ../common/hmac_openssl.c:343 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 msgid "OpenSSL failure" msgstr "OpenSSL-fel" -#: ../common/exec.c:172 +#: ../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../common/exec.c:215 +#: ../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../common/exec.c:223 +#: ../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../common/exec.c:250 +#: ../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../common/exec.c:412 libpq/pqcomm.c:728 storage/ipc/latch.c:1128 -#: storage/ipc/latch.c:1308 storage/ipc/latch.c:1541 storage/ipc/latch.c:1703 -#: storage/ipc/latch.c:1829 +#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1723 +#: commands/copyto.c:654 libpq/be-secure-common.c:59 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 +#: storage/ipc/latch.c:1349 storage/ipc/latch.c:1589 storage/ipc/latch.c:1751 +#: storage/ipc/latch.c:1877 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" #: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 #: ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 -#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:791 -#: ../port/path.c:808 utils/misc/ps_status.c:168 utils/misc/ps_status.c:176 -#: utils/misc/ps_status.c:203 utils/misc/ps_status.c:211 +#: ../common/psprintf.c:145 ../port/path.c:830 ../port/path.c:867 +#: ../port/path.c:884 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 +#: utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 #, c-format msgid "out of memory\n" msgstr "slut på minne\n" @@ -304,39 +327,51 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" -#: ../common/file_utils.c:87 ../common/file_utils.c:447 -#: ../common/file_utils.c:451 access/transam/twophase.c:1315 -#: access/transam/xlogarchive.c:112 access/transam/xlogarchive.c:229 -#: backup/basebackup.c:346 backup/basebackup.c:544 backup/basebackup.c:615 -#: commands/copyfrom.c:1680 commands/copyto.c:702 commands/extension.c:3469 -#: commands/tablespace.c:810 commands/tablespace.c:899 postmaster/pgarch.c:590 -#: replication/logical/snapbuild.c:1649 storage/file/fd.c:1922 -#: storage/file/fd.c:2008 storage/file/fd.c:3511 utils/adt/dbsize.c:106 -#: utils/adt/dbsize.c:258 utils/adt/dbsize.c:338 utils/adt/genfile.c:483 -#: utils/adt/genfile.c:658 utils/adt/misc.c:340 +#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../common/file_utils.c:120 ../common/file_utils.c:566 +#: ../common/file_utils.c:570 access/transam/twophase.c:1321 +#: access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 +#: backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 +#: backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1749 +#: commands/copyto.c:700 commands/extension.c:3527 commands/tablespace.c:804 +#: commands/tablespace.c:893 postmaster/pgarch.c:680 +#: replication/logical/snapbuild.c:1670 replication/logical/snapbuild.c:2173 +#: storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 +#: utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 +#: utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "kunde inte göra stat() på fil \"%s\": %m" -#: ../common/file_utils.c:162 ../common/pgfnames.c:48 ../common/rmtree.c:63 -#: commands/tablespace.c:734 commands/tablespace.c:744 -#: postmaster/postmaster.c:1564 storage/file/fd.c:2880 -#: storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:338 +#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../common/file_utils.c:151 ../common/file_utils.c:281 +#: ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 +#: commands/tablespace.c:738 postmaster/postmaster.c:1470 +#: storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 +#: utils/misc/tzparser.c:339 #, c-format msgid "could not open directory \"%s\": %m" msgstr "kunde inte öppna katalog \"%s\": %m" -#: ../common/file_utils.c:196 ../common/pgfnames.c:69 ../common/rmtree.c:104 -#: storage/file/fd.c:2892 +#: ../common/file_utils.c:169 ../common/file_utils.c:315 +#: ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 #, c-format msgid "could not read directory \"%s\": %m" msgstr "kunde inte läsa katalog \"%s\": %m" -#: ../common/file_utils.c:379 access/transam/xlogarchive.c:383 -#: postmaster/pgarch.c:746 postmaster/syslogger.c:1608 -#: replication/logical/snapbuild.c:1810 replication/slot.c:723 -#: replication/slot.c:1716 replication/slot.c:1858 storage/file/fd.c:792 -#: utils/time/snapmgr.c:1284 +#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 +#: postmaster/pgarch.c:834 postmaster/syslogger.c:1559 +#: replication/logical/snapbuild.c:1831 replication/slot.c:936 +#: replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 +#: utils/time/snapmgr.c:1255 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" @@ -345,90 +380,102 @@ msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" msgid "internal error" msgstr "internt fel" -#: ../common/jsonapi.c:1144 +#: ../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "Recursive-descent-parser kan inte använda inkrementell lexer." + +#: ../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "Inkrementell parser kräver en inkrementell lexer." + +#: ../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON nästlad för djupt, maximal tillåtet djup är 6400." + +#: ../common/jsonapi.c:2127 #, c-format -msgid "Escape sequence \"\\%s\" is invalid." -msgstr "Escape-sekvens \"\\%s\" är ogiltig." +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Escape-sekvens \"\\%.*s\" är ogiltig." -#: ../common/jsonapi.c:1147 +#: ../common/jsonapi.c:2131 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Tecken med värde 0x%02x måste escape:as." -#: ../common/jsonapi.c:1150 +#: ../common/jsonapi.c:2135 #, c-format -msgid "Expected end of input, but found \"%s\"." -msgstr "Förväntade slut på indata, men hittade \"%s\"." +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Förväntade slut på indata, men hittade \"%.*s\"." -#: ../common/jsonapi.c:1153 +#: ../common/jsonapi.c:2138 #, c-format -msgid "Expected array element or \"]\", but found \"%s\"." -msgstr "Färväntade array-element eller \"]\", men hittade \"%s\"." +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Färväntade array-element eller \"]\", men hittade \"%.*s\"." -#: ../common/jsonapi.c:1156 +#: ../common/jsonapi.c:2141 #, c-format -msgid "Expected \",\" or \"]\", but found \"%s\"." -msgstr "Förväntade \",\" eller \"]\", men hittade \"%s\"." +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Förväntade \",\" eller \"]\", men hittade \"%.*s\"." -#: ../common/jsonapi.c:1159 +#: ../common/jsonapi.c:2144 #, c-format -msgid "Expected \":\", but found \"%s\"." -msgstr "Förväntade sig \":\" men hittade \"%s\"." +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Förväntade sig \":\" men hittade \"%.*s\"." -#: ../common/jsonapi.c:1162 +#: ../common/jsonapi.c:2147 #, c-format -msgid "Expected JSON value, but found \"%s\"." -msgstr "Förväntade JSON-värde, men hittade \"%s\"." +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Förväntade JSON-värde, men hittade \"%.*s\"." -#: ../common/jsonapi.c:1165 +#: ../common/jsonapi.c:2150 msgid "The input string ended unexpectedly." msgstr "Indatasträngen avslutades oväntat." -#: ../common/jsonapi.c:1167 +#: ../common/jsonapi.c:2152 #, c-format -msgid "Expected string or \"}\", but found \"%s\"." -msgstr "Färväntade sträng eller \"}\", men hittade \"%s\"." +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Färväntade sträng eller \"}\", men hittade \"%.*s\"." -#: ../common/jsonapi.c:1170 +#: ../common/jsonapi.c:2155 #, c-format -msgid "Expected \",\" or \"}\", but found \"%s\"." -msgstr "Förväntade sig \",\" eller \"}\" men hittade \"%s\"." +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Förväntade sig \",\" eller \"}\" men hittade \"%.*s\"." -#: ../common/jsonapi.c:1173 +#: ../common/jsonapi.c:2158 #, c-format -msgid "Expected string, but found \"%s\"." -msgstr "Förväntade sträng, men hittade \"%s\"." +msgid "Expected string, but found \"%.*s\"." +msgstr "Förväntade sträng, men hittade \"%.*s\"." -#: ../common/jsonapi.c:1176 +#: ../common/jsonapi.c:2161 #, c-format -msgid "Token \"%s\" is invalid." -msgstr "Token \"%s\" är ogiltig." +msgid "Token \"%.*s\" is invalid." +msgstr "Token \"%.*s\" är ogiltig." -#: ../common/jsonapi.c:1179 jsonpath_scan.l:597 +#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 kan inte konverteras till text." -#: ../common/jsonapi.c:1181 +#: ../common/jsonapi.c:2166 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\" måste följas av fyra hexdecimala siffror." -#: ../common/jsonapi.c:1184 +#: ../common/jsonapi.c:2169 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "Escape-värden för unicode kan inte användas för kodpunkter med värde över 007F när kodningen inte är UTF8." -#: ../common/jsonapi.c:1187 +#: ../common/jsonapi.c:2178 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Escape-värde för unicode kan inte översättas till serverns kodning %s." -#: ../common/jsonapi.c:1190 jsonpath_scan.l:630 +#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicodes övre surrogathalva får inte komma efter en övre surrogathalva." -#: ../common/jsonapi.c:1192 jsonpath_scan.l:641 jsonpath_scan.l:651 -#: jsonpath_scan.l:702 +#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 +#: jsonpath_scan.l:713 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicodes lägre surrogathalva måste följa en övre surrogathalva." @@ -453,11 +500,168 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "kunde inte initiera kontrollsumma för backup-manifest" + +#: ../common/parse_manifest.c:203 ../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "manifestet avslutades oväntat" + +#: ../common/parse_manifest.c:209 ../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "kunde inte uppdatera kontrollsumma för backup-manifest" + +#: ../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "oväntad objektstart" + +#: ../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "oväntat objektslut" + +#: ../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "oväntad array-start" + +#: ../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "oväntat array-slut" + +#: ../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "förväntade en versionsindikator" + +#: ../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "okänt toppnivåfält" + +#: ../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "oväntat filfält" + +#: ../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "oväntat WAL-intervall-fält" + +#: ../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "oväntat objektfält" + +#: ../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "oväntad skalar" + +#: ../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "manifestversion är inte ett heltal" + +#: ../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "oväntad manifestversion" + +#: ../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "manifestets systemidentifierare är inte ett heltal" + +#: ../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "saknas sökväg" + +#: ../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "både sökväg och kodad sökväg" + +#: ../common/parse_manifest.c:666 +msgid "missing size" +msgstr "saknar storlek" + +#: ../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "kontrollsumma utan algoritm" + +#: ../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "kunde inte avkoda filnamn" + +#: ../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "filstorlek är inte ett haltal" + +#: ../common/parse_manifest.c:699 backup/basebackup.c:870 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "okänd algoritm för kontrollsumma: \"%s\"" + +#: ../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "ogiltig kontrollsumma för fil \"%s\": \"%s\"" + +#: ../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "saknar tidslinje" + +#: ../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "saknar start-LSN" + +#: ../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "saknar slut-LSN" + +#: ../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "tidslinje är inte ett heltal" + +#: ../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "kunde inte parsa start-LSN" + +#: ../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "kunde inte parsa slut-LSN" + +#: ../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "förväntade minst två rader" + +#: ../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "sista raden är inte nyradsterminerad" + +#: ../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "kunde inte göra klart kontrollsumma för backup-manifest" + +#: ../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "manifestet har ingen kontrollsumma" + +#: ../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "ogiltig kontrollsumma för manifest: \"%s\"" + +#: ../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "kontrollsumma för manifest matchar inte" + +#: ../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "kunde inte parsa backup-manifest: %s" + #: ../common/percentrepl.c:79 ../common/percentrepl.c:85 #: ../common/percentrepl.c:118 ../common/percentrepl.c:124 -#: postmaster/postmaster.c:2211 utils/misc/guc.c:3118 utils/misc/guc.c:3154 -#: utils/misc/guc.c:3224 utils/misc/guc.c:4547 utils/misc/guc.c:6721 -#: utils/misc/guc.c:6762 +#: tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 +#: utils/misc/guc.c:3283 utils/misc/guc.c:4712 utils/misc/guc.c:6931 +#: utils/misc/guc.c:6972 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "ogiltigt värde för parameter \"%s\": \"%s\"" @@ -517,45 +721,45 @@ msgstr "kunde inte köra igen med token för begränsad åtkomst: felkod %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "kunde inte hämta statuskod för underprocess: felkod %lu" -#: ../common/rmtree.c:95 access/heap/rewriteheap.c:1248 -#: access/transam/twophase.c:1704 access/transam/xlogarchive.c:120 -#: access/transam/xlogarchive.c:393 postmaster/postmaster.c:1143 -#: postmaster/syslogger.c:1537 replication/logical/origin.c:591 -#: replication/logical/reorderbuffer.c:4526 -#: replication/logical/snapbuild.c:1691 replication/logical/snapbuild.c:2125 -#: replication/slot.c:1909 storage/file/fd.c:832 storage/file/fd.c:3325 -#: storage/file/fd.c:3387 storage/file/reinit.c:262 storage/ipc/dsm.c:316 -#: storage/smgr/md.c:383 storage/smgr/md.c:442 storage/sync/sync.c:248 -#: utils/time/snapmgr.c:1608 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 +#: access/transam/twophase.c:1717 access/transam/xlogarchive.c:119 +#: access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 +#: postmaster/syslogger.c:1488 replication/logical/origin.c:591 +#: replication/logical/reorderbuffer.c:4589 +#: replication/logical/snapbuild.c:1712 replication/logical/snapbuild.c:2146 +#: replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 +#: storage/file/fd.c:3440 storage/file/reinit.c:261 storage/ipc/dsm.c:343 +#: storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 +#: utils/time/snapmgr.c:1591 #, c-format msgid "could not remove file \"%s\": %m" msgstr "kunde inte ta bort fil \"%s\": %m" -#: ../common/rmtree.c:122 commands/tablespace.c:773 commands/tablespace.c:786 -#: commands/tablespace.c:821 commands/tablespace.c:911 storage/file/fd.c:3317 -#: storage/file/fd.c:3726 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 +#: commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 +#: storage/file/fd.c:3779 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "kunde inte ta bort katalog \"%s\": %m" -#: ../common/scram-common.c:271 +#: ../common/scram-common.c:281 msgid "could not encode salt" msgstr "kunde inte koda saltet" -#: ../common/scram-common.c:287 +#: ../common/scram-common.c:297 msgid "could not encode stored key" msgstr "kunde inte koda den lagrade nyckeln" -#: ../common/scram-common.c:304 +#: ../common/scram-common.c:314 msgid "could not encode server key" msgstr "kunde inte koda servernyckeln" -#: ../common/stringinfo.c:306 +#: ../common/stringinfo.c:315 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "Kan inte utöka strängbuffer som innehåller %d byte med ytterligare %d bytes." -#: ../common/stringinfo.c:310 +#: ../common/stringinfo.c:319 #, c-format msgid "" "out of memory\n" @@ -571,7 +775,7 @@ msgstr "" msgid "could not look up effective user ID %ld: %s" msgstr "kunde inte slå upp effektivt användar-id %ld: %s" -#: ../common/username.c:45 libpq/auth.c:1881 +#: ../common/username.c:45 libpq/auth.c:1888 msgid "user does not exist" msgstr "användaren finns inte" @@ -663,22 +867,22 @@ msgstr "Fortsätter att försöka i 30 sekunder." msgid "You might have antivirus, backup, or similar software interfering with the database system." msgstr "Du kan ha antivirus, backup eller liknande mjukvara som stör databassystemet" -#: ../port/path.c:775 +#: ../port/path.c:852 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "kunde inte fastställa nuvarande arbetskatalog: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "kunde inte fastställa nuvarande arbetskatalog: %m\n" #: ../port/strerror.c:72 #, c-format msgid "operating system error %d" msgstr "operativsystemfel %d" -#: ../port/thread.c:50 ../port/thread.c:86 +#: ../port/user.c:43 ../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "kunde inte slå upp lokalt användar-id %d: %s" -#: ../port/thread.c:55 ../port/thread.c:91 +#: ../port/user.c:48 ../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "lokal användare med ID %d existerar inte" @@ -698,115 +902,104 @@ msgstr "kunde inte hämta SID för PowerUser-grupp: felkod %lu\n" msgid "could not check access token membership: error code %lu\n" msgstr "kunde inte kontrollera access-token-medlemskap: felkod %lu\n" -#: access/brin/brin.c:216 +#: access/brin/brin.c:405 #, c-format msgid "request for BRIN range summarization for index \"%s\" page %u was not recorded" msgstr "förfrågan efter BRIN-intervallsummering för index \"%s\" sida %u har inte spelats in" -#: access/brin/brin.c:1036 access/brin/brin.c:1137 access/gin/ginfast.c:1040 -#: access/transam/xlogfuncs.c:189 access/transam/xlogfuncs.c:214 -#: access/transam/xlogfuncs.c:247 access/transam/xlogfuncs.c:286 -#: access/transam/xlogfuncs.c:307 access/transam/xlogfuncs.c:328 -#: access/transam/xlogfuncs.c:398 access/transam/xlogfuncs.c:456 +#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 +#: access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 +#: access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 +#: access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 +#: access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 #, c-format msgid "recovery is in progress" msgstr "återställning pågår" -#: access/brin/brin.c:1037 access/brin/brin.c:1138 +#: access/brin/brin.c:1386 access/brin/brin.c:1494 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "BRIN-kontrollfunktioner kan inte köras under återställning." -#: access/brin/brin.c:1042 access/brin/brin.c:1143 +#: access/brin/brin.c:1391 access/brin/brin.c:1499 #, c-format msgid "block number out of range: %lld" msgstr "blocknummer är utanför giltigt intervall: %lld" -#: access/brin/brin.c:1086 access/brin/brin.c:1169 +#: access/brin/brin.c:1436 access/brin/brin.c:1525 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\" är inte ett BRIN-index" -#: access/brin/brin.c:1102 access/brin/brin.c:1185 +#: access/brin/brin.c:1452 access/brin/brin.c:1541 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "kunde inte öppna föräldratabell för index \"%s\"" -#: access/brin/brin_bloom.c:750 access/brin/brin_bloom.c:792 -#: access/brin/brin_minmax_multi.c:3011 access/brin/brin_minmax_multi.c:3148 -#: statistics/dependencies.c:663 statistics/dependencies.c:716 -#: statistics/mcv.c:1484 statistics/mcv.c:1515 statistics/mvdistinct.c:344 -#: statistics/mvdistinct.c:397 utils/adt/pseudotypes.c:43 -#: utils/adt/pseudotypes.c:77 utils/adt/tsgistidx.c:93 +#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 +#: parser/parse_utilcmd.c:2277 #, c-format -msgid "cannot accept a value of type %s" -msgstr "kan inte acceptera ett värde av type %s" +msgid "index \"%s\" is not valid" +msgstr "index \"%s\" är inte giltigt" -#: access/brin/brin_minmax_multi.c:2171 access/brin/brin_minmax_multi.c:2178 -#: access/brin/brin_minmax_multi.c:2185 utils/adt/timestamp.c:941 -#: utils/adt/timestamp.c:1518 utils/adt/timestamp.c:2708 -#: utils/adt/timestamp.c:2778 utils/adt/timestamp.c:2795 -#: utils/adt/timestamp.c:2848 utils/adt/timestamp.c:2887 -#: utils/adt/timestamp.c:3184 utils/adt/timestamp.c:3189 -#: utils/adt/timestamp.c:3194 utils/adt/timestamp.c:3244 -#: utils/adt/timestamp.c:3251 utils/adt/timestamp.c:3258 -#: utils/adt/timestamp.c:3278 utils/adt/timestamp.c:3285 -#: utils/adt/timestamp.c:3292 utils/adt/timestamp.c:3322 -#: utils/adt/timestamp.c:3330 utils/adt/timestamp.c:3374 -#: utils/adt/timestamp.c:3796 utils/adt/timestamp.c:3920 -#: utils/adt/timestamp.c:4440 +#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 +#: access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 +#: statistics/dependencies.c:661 statistics/dependencies.c:714 +#: statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 +#: statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 +#: utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format -msgid "interval out of range" -msgstr "interval utanför giltigt intervall" +msgid "cannot accept a value of type %s" +msgstr "kan inte acceptera ett värde av type %s" -#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 -#: access/brin/brin_pageops.c:852 access/gin/ginentrypage.c:110 -#: access/gist/gist.c:1442 access/spgist/spgdoinsert.c:2002 -#: access/spgist/spgdoinsert.c:2279 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 +#: access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 +#: access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 +#: access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "indexradstorlek %zu överstiger maximum %zu för index \"%s\"" -#: access/brin/brin_revmap.c:393 access/brin/brin_revmap.c:399 +#: access/brin/brin_revmap.c:383 access/brin/brin_revmap.c:389 #, c-format msgid "corrupted BRIN index: inconsistent range map" msgstr "trasigt BRIN-index: inkonsistent intervall-map" -#: access/brin/brin_revmap.c:593 +#: access/brin/brin_revmap.c:583 #, c-format msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "oväntad sidtyp 0x%04X i BRIN-index \"%s\" block %u" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:151 -#: access/gist/gistvalidate.c:153 access/hash/hashvalidate.c:139 +#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 +#: access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 #: access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with invalid support number %d" msgstr "operatorfamilj \"%s\" för accessmetod %s innehåller funktion %s med ogiltigt supportnummer %d" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:163 -#: access/gist/gistvalidate.c:165 access/hash/hashvalidate.c:118 +#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 +#: access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 #: access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d" msgstr "operatorfamilj \"%s\" för accessmetod %s innehåller funktion %s med felaktig signatur för supportnummer %d" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:182 -#: access/gist/gistvalidate.c:185 access/hash/hashvalidate.c:160 +#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 +#: access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 #: access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d" msgstr "operatorfamilj \"%s\" för accessmetod %s innehåller operator %s med ogiltigt strateginummer %d" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:195 +#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 #: access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 #: access/spgist/spgvalidate.c:237 #, c-format msgid "operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s" msgstr "operatorfamilj \"%s\" för accessmetod %s innehåller ogiltig ORDER BY-specifikatioon för operator %s" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:208 -#: access/gist/gistvalidate.c:233 access/hash/hashvalidate.c:186 +#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 +#: access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 #: access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with wrong signature" @@ -829,38 +1022,38 @@ msgstr "operatorfamilj \"%s\" för accessmetod %s saknas supportfunktion(er) f msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "operatorklass \"%s\" för accessmetoden %s saknar operator(er)" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:250 -#: access/gist/gistvalidate.c:274 +#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 +#: access/gist/gistvalidate.c:273 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d" msgstr "operatorklass \"%s\" för accessmetod %s saknar supportfunktion %d" -#: access/common/attmap.c:122 +#: access/common/attmap.c:121 #, c-format msgid "Returned type %s does not match expected type %s in column %d." msgstr "Returnerad typ %s matchar inte förväntad type %s i kolumn %d." -#: access/common/attmap.c:150 +#: access/common/attmap.c:149 #, c-format msgid "Number of returned columns (%d) does not match expected column count (%d)." msgstr "Antalet returnerade kolumner (%d) matchar inte förväntat antal kolumner (%d)." -#: access/common/attmap.c:234 access/common/attmap.c:246 +#: access/common/attmap.c:233 access/common/attmap.c:245 #, c-format msgid "could not convert row type" msgstr "kunde inte konvertera radtypen" -#: access/common/attmap.c:235 +#: access/common/attmap.c:234 #, c-format msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s." msgstr "Attribut \"%s\" för typ %s matchar inte motsvarande attribut för typ %s." -#: access/common/attmap.c:247 +#: access/common/attmap.c:246 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "Attribut \"%s\" i typ %s finns inte i typ %s." -#: access/common/heaptuple.c:1124 access/common/heaptuple.c:1459 +#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "antalet kolumner (%d) överskrider gränsen (%d)" @@ -870,122 +1063,110 @@ msgstr "antalet kolumner (%d) överskrider gränsen (%d)" msgid "number of index columns (%d) exceeds limit (%d)" msgstr "antalet indexerade kolumner (%d) överskrider gränsen (%d)" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:950 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:970 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "indexrad kräver %zu byte, maximal storlek är %zu" -#: access/common/printtup.c:292 tcop/fastpath.c:107 tcop/fastpath.c:454 -#: tcop/postgres.c:1944 +#: access/common/printtup.c:292 commands/explain.c:5376 tcop/fastpath.c:107 +#: tcop/fastpath.c:454 tcop/postgres.c:1956 #, c-format msgid "unsupported format code: %d" msgstr "ej stödd formatkod: %d" -#: access/common/reloptions.c:521 access/common/reloptions.c:532 +#: access/common/reloptions.c:519 access/common/reloptions.c:530 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "Giltiga värden är \"on\", \"off\" och \"auto\"." -#: access/common/reloptions.c:543 +#: access/common/reloptions.c:541 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "Giltiga värden är \"local\" och \"cascaded\"." -#: access/common/reloptions.c:691 +#: access/common/reloptions.c:689 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "överskriden gräns för användardefinierade relationsparametertyper" -#: access/common/reloptions.c:1233 +#: access/common/reloptions.c:1231 #, c-format msgid "RESET must not include values for parameters" msgstr "RESET får inte ha med värden på parametrar" -#: access/common/reloptions.c:1265 +#: access/common/reloptions.c:1263 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "okänd parameternamnrymd \"%s\"" -#: access/common/reloptions.c:1302 commands/variable.c:1167 +#: access/common/reloptions.c:1300 commands/variable.c:1214 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "tabeller deklarerade med WITH OIDS stöds inte" -#: access/common/reloptions.c:1470 +#: access/common/reloptions.c:1468 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "okänd parameter \"%s\"" -#: access/common/reloptions.c:1582 +#: access/common/reloptions.c:1580 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "parameter \"%s\" angiven mer än en gång" -#: access/common/reloptions.c:1598 +#: access/common/reloptions.c:1596 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "ogiltigt värde för booleansk flagga \"%s\": \"%s\"" -#: access/common/reloptions.c:1610 +#: access/common/reloptions.c:1608 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "ogiltigt värde för heltalsflagga \"%s\": \"%s\"" -#: access/common/reloptions.c:1616 access/common/reloptions.c:1636 +#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "värdet %s är utanför sitt intervall för flaggan \"%s\"" -#: access/common/reloptions.c:1618 +#: access/common/reloptions.c:1616 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "Giltiga värden är mellan \"%d\" och \"%d\"." -#: access/common/reloptions.c:1630 +#: access/common/reloptions.c:1628 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "ogiltigt värde för flyttalsflagga \"%s\": %s" -#: access/common/reloptions.c:1638 +#: access/common/reloptions.c:1636 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "Giltiga värden är mellan \"%f\" och \"%f\"." -#: access/common/reloptions.c:1660 +#: access/common/reloptions.c:1658 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "ogiltigt värde för enum-flagga \"%s\": %s" -#: access/common/reloptions.c:1991 +#: access/common/reloptions.c:1989 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "kan inte ange lagringsparametrar för partitionerad tabell" -#: access/common/reloptions.c:1992 +#: access/common/reloptions.c:1990 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "Ange lagringsparametrar för dess löv-partition istället." -#: access/common/toast_compression.c:33 +#: access/common/toast_compression.c:31 #, c-format msgid "compression method lz4 not supported" msgstr "komprimeringsmetod lz4 stöds ej" -#: access/common/toast_compression.c:34 +#: access/common/toast_compression.c:32 #, c-format msgid "This functionality requires the server to be built with lz4 support." msgstr "Denna funktionalitet kräver att servern byggts med lz4-stöd." -#: access/common/tupdesc.c:837 commands/tablecmds.c:6953 -#: commands/tablecmds.c:12973 -#, c-format -msgid "too many array dimensions" -msgstr "för många array-dimensioner" - -#: access/common/tupdesc.c:842 parser/parse_clause.c:772 -#: parser/parse_relation.c:1913 -#, c-format -msgid "column \"%s\" cannot be declared SETOF" -msgstr "kolumn \"%s\" kan inte deklareras som SETOF" - #: access/gin/ginbulk.c:44 #, c-format msgid "posting list is too long" @@ -993,8 +1174,8 @@ msgstr "post-listan är för lång" #: access/gin/ginbulk.c:45 #, c-format -msgid "Reduce maintenance_work_mem." -msgstr "Minska maintenance_work_mem." +msgid "Reduce \"maintenance_work_mem\"." +msgstr "Minska \"maintenance_work_mem\"." #: access/gin/ginfast.c:1041 #, c-format @@ -1011,7 +1192,7 @@ msgstr "\"%s\" är inte ett GIN-index" msgid "cannot access temporary indexes of other sessions" msgstr "kan inte flytta temporära index tillhörande andra sessioner" -#: access/gin/ginget.c:273 access/nbtree/nbtinsert.c:762 +#: access/gin/ginget.c:271 access/nbtree/nbtinsert.c:762 #, c-format msgid "failed to re-find tuple within index \"%s\"" msgstr "misslyckades att återfinna tuple i index \"%s\"" @@ -1026,50 +1207,50 @@ msgstr "gamla GIN-index stöder inte hela-index-scan eller sökningar efter null msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "För att fixa detta, kör REINDEX INDEX \"%s\"." -#: access/gin/ginutil.c:146 executor/execExpr.c:2169 -#: utils/adt/arrayfuncs.c:3996 utils/adt/arrayfuncs.c:6683 -#: utils/adt/rowtypes.c:984 +#: access/gin/ginutil.c:147 executor/execExpr.c:2200 +#: utils/adt/arrayfuncs.c:4016 utils/adt/arrayfuncs.c:6712 +#: utils/adt/rowtypes.c:974 #, c-format msgid "could not identify a comparison function for type %s" msgstr "kunde inte hitta någon jämförelsefunktion för typen %s" -#: access/gin/ginvalidate.c:92 access/gist/gistvalidate.c:93 +#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 #: access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 #, c-format msgid "operator family \"%s\" of access method %s contains support function %s with different left and right input types" msgstr "operatorfamilj \"%s\" för accessmetod %s innehåller supportfunktion %s med olika vänster- och höger-inputtyper" -#: access/gin/ginvalidate.c:260 +#: access/gin/ginvalidate.c:258 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d or %d" msgstr "operatorklass \"%s\" för accessmetod \"%s\" saknar supportfunktion %d eller %d" -#: access/gin/ginvalidate.c:333 access/gist/gistvalidate.c:350 +#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 #: access/spgist/spgvalidate.c:387 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "supportfunktionsnummer %d är ogiltig för accessmetod %s" -#: access/gist/gist.c:759 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "index \"%s\" innehåller en inre tupel som är markerad ogiltig" -#: access/gist/gist.c:761 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 #, c-format msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1." msgstr "Detta orsakas av en inkomplett siduppdelning under krashåterställning körd innan uppdatering till PostgreSQL 9.1." -#: access/gist/gist.c:762 access/gist/gistutil.c:801 access/gist/gistutil.c:812 -#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:227 -#: access/hash/hashutil.c:238 access/hash/hashutil.c:250 -#: access/hash/hashutil.c:271 access/nbtree/nbtpage.c:813 +#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 +#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 +#: access/hash/hashutil.c:237 access/hash/hashutil.c:249 +#: access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 #: access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "Var vänlig och kör REINDEX på det." -#: access/gist/gist.c:1176 +#: access/gist/gist.c:1196 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "lagar ofärdig split i index \"%s\", block %u" @@ -1084,52 +1265,52 @@ msgstr "picksplit-metod för kolumn %d i index \"%s\" misslyckades" msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command." msgstr "Indexet är inte optimalt. För att optimera det, kontakta en utvecklare eller försök använda kolumnen som det andra värdet i CREATE INDEX-kommandot." -#: access/gist/gistutil.c:798 access/hash/hashutil.c:224 +#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 #: access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "index \"%s\" innehåller en oväntad nollställd sida vid block %u" -#: access/gist/gistutil.c:809 access/hash/hashutil.c:235 -#: access/hash/hashutil.c:247 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 +#: access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "index \"%s\" har en trasig sida vid block %u" -#: access/gist/gistvalidate.c:203 +#: access/gist/gistvalidate.c:202 #, c-format msgid "operator family \"%s\" of access method %s contains unsupported ORDER BY specification for operator %s" msgstr "operatorfamiljen \"%s\" för accessmetod %s innehåller en ORDER BY som inte stöds för operator %s" -#: access/gist/gistvalidate.c:214 +#: access/gist/gistvalidate.c:213 #, c-format msgid "operator family \"%s\" of access method %s contains incorrect ORDER BY opfamily specification for operator %s" msgstr "operatorfamiljen \"%s\" för accessmetod %s innehåller en inkorrekt ORDER BY \"opfamiily\"-specifikation för operator %s" -#: access/hash/hashfunc.c:279 access/hash/hashfunc.c:333 -#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:333 +#: utils/adt/varchar.c:1008 utils/adt/varchar.c:1065 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "kunde inte bestämma vilken jämförelse (collation) som skall användas för sträng-hashning" -#: access/hash/hashfunc.c:280 access/hash/hashfunc.c:334 catalog/heap.c:668 -#: catalog/heap.c:674 commands/createas.c:206 commands/createas.c:515 -#: commands/indexcmds.c:2039 commands/tablecmds.c:17462 commands/view.c:86 -#: regex/regc_pg_locale.c:243 utils/adt/formatting.c:1648 -#: utils/adt/formatting.c:1770 utils/adt/formatting.c:1893 utils/adt/like.c:191 -#: utils/adt/like_support.c:1025 utils/adt/varchar.c:739 -#: utils/adt/varchar.c:1010 utils/adt/varchar.c:1065 utils/adt/varlena.c:1518 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:334 catalog/heap.c:672 +#: catalog/heap.c:678 commands/createas.c:201 commands/createas.c:508 +#: commands/indexcmds.c:2021 commands/tablecmds.c:18178 commands/view.c:81 +#: regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 +#: utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 +#: utils/adt/like_support.c:1024 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1066 utils/adt/varlena.c:1521 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "Använd en COLLATE-klausul för att sätta jämförelsen explicit." -#: access/hash/hashinsert.c:86 +#: access/hash/hashinsert.c:84 #, c-format msgid "index row size %zu exceeds hash maximum %zu" msgstr "indexradstorlek %zu överstiger hash-maximum %zu" -#: access/hash/hashinsert.c:88 access/spgist/spgdoinsert.c:2006 -#: access/spgist/spgdoinsert.c:2283 access/spgist/spgutils.c:1011 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 +#: access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1031 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "Värden större än en buffert-sida kan inte indexeras." @@ -1144,17 +1325,17 @@ msgstr "ogiltigt overflow-blocknummer %u" msgid "out of overflow pages in hash index \"%s\"" msgstr "slut på överspillsidor i hash-index \"%s\"" -#: access/hash/hashsearch.c:315 +#: access/hash/hashsearch.c:311 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "hash-index stöder inte hela-index-scans" -#: access/hash/hashutil.c:263 +#: access/hash/hashutil.c:262 #, c-format msgid "index \"%s\" is not a hash index" msgstr "index \"%s\" är inte ett hashträd" -#: access/hash/hashutil.c:269 +#: access/hash/hashutil.c:268 #, c-format msgid "index \"%s\" has wrong hash version" msgstr "index \"%s\" har fel hash-version" @@ -1169,228 +1350,235 @@ msgstr "operatorfamilj \"%s\" för accessmetod %s saknar supportfunktion för op msgid "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "operatorfamilj \"%s\" för accessmetod %s saknar mellan-typ-operator(er)" -#: access/heap/heapam.c:2027 +#: access/heap/heapam.c:2206 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "kan inte lägga till tupler i en parellell arbetare" -#: access/heap/heapam.c:2546 +#: access/heap/heapam.c:2725 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "kan inte radera tupler under en parallell operation" -#: access/heap/heapam.c:2593 +#: access/heap/heapam.c:2772 #, c-format msgid "attempted to delete invisible tuple" msgstr "försökte ta bort en osynlig tuple" -#: access/heap/heapam.c:3036 access/heap/heapam.c:5903 +#: access/heap/heapam.c:3220 access/heap/heapam.c:6501 access/index/genam.c:818 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "kan inte uppdatera tupler under en parallell operation" -#: access/heap/heapam.c:3164 +#: access/heap/heapam.c:3397 #, c-format msgid "attempted to update invisible tuple" msgstr "försökte uppdatera en osynlig tuple" -#: access/heap/heapam.c:4551 access/heap/heapam.c:4589 -#: access/heap/heapam.c:4854 access/heap/heapam_handler.c:467 +#: access/heap/heapam.c:4908 access/heap/heapam.c:4946 +#: access/heap/heapam.c:5211 access/heap/heapam_handler.c:468 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "kunde inte låsa rad i relationen \"%s\"" -#: access/heap/heapam_handler.c:412 +#: access/heap/heapam.c:6314 commands/trigger.c:3340 +#: executor/nodeModifyTable.c:2376 executor/nodeModifyTable.c:2467 +#, c-format +msgid "tuple to be updated was already modified by an operation triggered by the current command" +msgstr "tupel som skall uppdateras hade redan ändrats av en operation som triggats av aktuellt kommando" + +#: access/heap/heapam_handler.c:413 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update" msgstr "tupel som skall låsas har redan flyttats till en annan partition av en samtida uppdatering" -#: access/heap/hio.c:536 access/heap/rewriteheap.c:659 +#: access/heap/hio.c:535 access/heap/rewriteheap.c:640 #, c-format msgid "row is too big: size %zu, maximum size %zu" msgstr "raden är för stor: storlek %zu, maximal storlek %zu" -#: access/heap/rewriteheap.c:919 +#: access/heap/rewriteheap.c:885 #, c-format msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "kunde inte skriva till fil \"%s\", skrev %d av %d: %m." -#: access/heap/rewriteheap.c:1011 access/heap/rewriteheap.c:1128 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 #: access/transam/timeline.c:329 access/transam/timeline.c:481 -#: access/transam/xlog.c:2971 access/transam/xlog.c:3162 -#: access/transam/xlog.c:3938 access/transam/xlog.c:8744 -#: access/transam/xlogfuncs.c:702 backup/basebackup_server.c:151 -#: backup/basebackup_server.c:244 commands/dbcommands.c:518 -#: postmaster/postmaster.c:4557 postmaster/postmaster.c:5560 -#: replication/logical/origin.c:603 replication/slot.c:1777 -#: storage/file/copydir.c:157 storage/smgr/md.c:232 utils/time/snapmgr.c:1263 +#: access/transam/xlog.c:3255 access/transam/xlog.c:3446 +#: access/transam/xlog.c:4283 access/transam/xlog.c:9269 +#: access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 +#: backup/basebackup_server.c:242 commands/dbcommands.c:494 +#: postmaster/launch_backend.c:340 postmaster/postmaster.c:4114 +#: postmaster/walsummarizer.c:1212 replication/logical/origin.c:603 +#: replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 +#: utils/time/snapmgr.c:1234 #, c-format msgid "could not create file \"%s\": %m" msgstr "kunde inte skapa fil \"%s\": %m" -#: access/heap/rewriteheap.c:1138 +#: access/heap/rewriteheap.c:1104 #, c-format msgid "could not truncate file \"%s\" to %u: %m" msgstr "kunde inte trunkera fil \"%s\" till %u: %m" -#: access/heap/rewriteheap.c:1156 access/transam/timeline.c:384 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 #: access/transam/timeline.c:424 access/transam/timeline.c:498 -#: access/transam/xlog.c:3021 access/transam/xlog.c:3218 -#: access/transam/xlog.c:3950 commands/dbcommands.c:530 -#: postmaster/postmaster.c:4567 postmaster/postmaster.c:4577 +#: access/transam/xlog.c:3305 access/transam/xlog.c:3502 +#: access/transam/xlog.c:4295 commands/dbcommands.c:506 +#: postmaster/launch_backend.c:351 postmaster/launch_backend.c:363 #: replication/logical/origin.c:615 replication/logical/origin.c:657 -#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1767 -#: replication/slot.c:1812 storage/file/buffile.c:545 -#: storage/file/copydir.c:197 utils/init/miscinit.c:1605 -#: utils/init/miscinit.c:1616 utils/init/miscinit.c:1624 utils/misc/guc.c:4331 -#: utils/misc/guc.c:4362 utils/misc/guc.c:5490 utils/misc/guc.c:5508 -#: utils/time/snapmgr.c:1268 utils/time/snapmgr.c:1275 +#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1788 +#: replication/slot.c:2094 storage/file/buffile.c:545 +#: storage/file/copydir.c:197 utils/init/miscinit.c:1655 +#: utils/init/miscinit.c:1666 utils/init/miscinit.c:1674 utils/misc/guc.c:4491 +#: utils/misc/guc.c:4522 utils/misc/guc.c:5675 utils/misc/guc.c:5693 +#: utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 #, c-format msgid "could not write to file \"%s\": %m" msgstr "kunde inte skriva till fil \"%s\": %m" -#: access/heap/vacuumlazy.c:482 +#: access/heap/vacuumlazy.c:473 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "aggressiv vaccum av \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:487 +#: access/heap/vacuumlazy.c:478 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "kör vaccum på \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:635 +#: access/heap/vacuumlazy.c:626 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "avslutade vacuum av \"%s.%s.%s\": indexskanningar: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:637 #, c-format msgid "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "automatisk aggressiv vacuum för att förhindra \"wraparound\" av tabell \"%s.%s.%s\": indexskanningar: %d\n" -#: access/heap/vacuumlazy.c:648 +#: access/heap/vacuumlazy.c:639 #, c-format msgid "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "automatisk vacuum för att förhindra \"wraparound\" av tabell \"%s.%s.%s\": indexskanningar: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:644 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "automatisk vacuum av tabell \"%s.%s.%s\": indexskanningar: %d\n" -#: access/heap/vacuumlazy.c:655 +#: access/heap/vacuumlazy.c:646 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "automatisk vacuum av tabell \"%s.%s.%s\": indexskanningar: %d\n" -#: access/heap/vacuumlazy.c:662 +#: access/heap/vacuumlazy.c:653 #, c-format msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" msgstr "sidor: %u borttagna, %u kvar, %u skannade (%-2f%% av totala antalet)\n" -#: access/heap/vacuumlazy.c:669 +#: access/heap/vacuumlazy.c:660 #, c-format msgid "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" msgstr "tupler: %lld borttagna, %lld kvar, %lld är döda men ännu inte möjliga att ta bort\n" -#: access/heap/vacuumlazy.c:675 +#: access/heap/vacuumlazy.c:666 #, c-format msgid "tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n" msgstr "tupler missade: %lld döda från %u sidor som inte tagits bort på grund av låstvister vid städning\n" -#: access/heap/vacuumlazy.c:681 +#: access/heap/vacuumlazy.c:672 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "gräns för borttagning: %u, som var %d XID:er gammal när operationen avslutades\n" -#: access/heap/vacuumlazy.c:688 +#: access/heap/vacuumlazy.c:679 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "ny relfrozenxid: %u, som är %d XID:er före tidigare värde\n" -#: access/heap/vacuumlazy.c:696 +#: access/heap/vacuumlazy.c:687 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "ny relminmxid: %u, som är %d MXID:er för tidigare värde\n" -#: access/heap/vacuumlazy.c:699 +#: access/heap/vacuumlazy.c:690 #, c-format msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" msgstr "frysta: %u sidor i tabellen (%.2f%% av totalt) hade %lld frysta tupler\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:698 msgid "index scan not needed: " msgstr "index-scan behövdes inte: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:700 msgid "index scan needed: " msgstr "index-scan behövdes: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:702 #, c-format msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" msgstr "%u sidor i tabell (%.2f%% av totalt) hade %lld döda postidentifierare borttagna\n" -#: access/heap/vacuumlazy.c:716 +#: access/heap/vacuumlazy.c:707 msgid "index scan bypassed: " msgstr "index-scan överhoppad: " -#: access/heap/vacuumlazy.c:718 +#: access/heap/vacuumlazy.c:709 msgid "index scan bypassed by failsafe: " msgstr "index-scan överhoppad av felsäkerhetsfunktion: " -#: access/heap/vacuumlazy.c:720 +#: access/heap/vacuumlazy.c:711 #, c-format msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" msgstr "%u sidor från tabell (%.2f%% totalt) har %lld döda postidentifierare\n" -#: access/heap/vacuumlazy.c:735 +#: access/heap/vacuumlazy.c:726 #, c-format msgid "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u reusable\n" msgstr "index \"%s\": sidor: %u totalt, %u tidigare borttagna, %u nuvarande borttagna, %u återanvändbara\n" -#: access/heap/vacuumlazy.c:747 commands/analyze.c:796 +#: access/heap/vacuumlazy.c:738 commands/analyze.c:794 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "I/O-timing: läs: %.3f ms, skriv: %.3f ms\n" -#: access/heap/vacuumlazy.c:757 commands/analyze.c:799 +#: access/heap/vacuumlazy.c:748 commands/analyze.c:797 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "snitt läshastighet: %.3f MB/s, snitt skrivhastighet: %.3f MB/s\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:801 +#: access/heap/vacuumlazy.c:751 commands/analyze.c:799 #, c-format msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" msgstr "bufferanvändning: %lld träffar, %lld missar, %lld nersmutsade\n" -#: access/heap/vacuumlazy.c:765 +#: access/heap/vacuumlazy.c:756 #, c-format msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" msgstr "WAL-användning: %lld poster, %lld hela sidor, %llu bytes\n" -#: access/heap/vacuumlazy.c:769 commands/analyze.c:805 +#: access/heap/vacuumlazy.c:760 commands/analyze.c:803 #, c-format msgid "system usage: %s" msgstr "systemanvändning: %s" -#: access/heap/vacuumlazy.c:2482 +#: access/heap/vacuumlazy.c:2170 #, c-format msgid "table \"%s\": removed %lld dead item identifiers in %u pages" msgstr "tabell \"%s\": tog bort %lld döda postidentifierare i %u sidor" -#: access/heap/vacuumlazy.c:2642 +#: access/heap/vacuumlazy.c:2324 #, c-format msgid "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans" msgstr "hoppar över ej nödvändigt underhåll av tabell \"%s.%s.%s\" som skyddsåtgärd efter %d index-scan" -#: access/heap/vacuumlazy.c:2645 +#: access/heap/vacuumlazy.c:2327 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "Tabellens relfrozenxid eller relminmxid är för långt bak i tiden." -#: access/heap/vacuumlazy.c:2646 +#: access/heap/vacuumlazy.c:2328 #, c-format msgid "" "Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" @@ -1399,67 +1587,67 @@ msgstr "" "Överväg att öka konfigurationsparametern \"maintenance_work_mem\" eller \"autovacuum_work_mem\".\n" "Du kan också överväga andra metoder för att VACUUM skall hinna med allokeringen av transactions-ID." -#: access/heap/vacuumlazy.c:2891 +#: access/heap/vacuumlazy.c:2590 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "\"%s\": stoppar trunkering pga konfliktande låskrav" -#: access/heap/vacuumlazy.c:2961 +#: access/heap/vacuumlazy.c:2660 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "tabell \"%s\": trunkerade %u till %u sidor" -#: access/heap/vacuumlazy.c:3023 +#: access/heap/vacuumlazy.c:2722 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "tabell \"%s\": pausar trunkering pga konfliktande låskrav" -#: access/heap/vacuumlazy.c:3183 +#: access/heap/vacuumlazy.c:2841 #, c-format msgid "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary tables in parallel" msgstr "stänger av parallell-flaggan för vacuumn på \"%s\" --- kan inte köra vacuum på temporära tabeller parallellt" -#: access/heap/vacuumlazy.c:3399 +#: access/heap/vacuumlazy.c:3108 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "vid skanning av block %u offset %u i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3402 +#: access/heap/vacuumlazy.c:3111 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "vid skanning av block %u i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3406 +#: access/heap/vacuumlazy.c:3115 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "vid skanning av relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3414 +#: access/heap/vacuumlazy.c:3123 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "vid vacuum av block %u offset %u i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3417 +#: access/heap/vacuumlazy.c:3126 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "vid vacuum av block %u i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3421 +#: access/heap/vacuumlazy.c:3130 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "vid vacuum av relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3426 commands/vacuumparallel.c:1074 +#: access/heap/vacuumlazy.c:3135 commands/vacuumparallel.c:1112 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "vid vaccum av index \"%s\" i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3431 commands/vacuumparallel.c:1080 +#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1118 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "vid uppstädning av index \"%s\" i relation \"%s.%s\"" -#: access/heap/vacuumlazy.c:3437 +#: access/heap/vacuumlazy.c:3146 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "vid trunkering av relation \"%s.%s\" till %u block" @@ -1474,19 +1662,24 @@ msgstr "accessmetod \"%s\" har inte typ %s" msgid "index access method \"%s\" does not have a handler" msgstr "indexaccessmetod \"%s\" har ingen hanterare" -#: access/index/genam.c:490 +#: access/index/genam.c:489 #, c-format msgid "transaction aborted during system catalog scan" msgstr "transaktionen avbruten under scan av systemkatalog" -#: access/index/indexam.c:142 catalog/objectaddress.c:1394 -#: commands/indexcmds.c:2867 commands/tablecmds.c:272 commands/tablecmds.c:296 -#: commands/tablecmds.c:17163 commands/tablecmds.c:18935 +#: access/index/genam.c:657 access/index/indexam.c:82 +#, c-format +msgid "cannot access index \"%s\" while it is being reindexed" +msgstr "kan inte använda index \"%s\" som håller på att indexeras om" + +#: access/index/indexam.c:203 catalog/objectaddress.c:1356 +#: commands/indexcmds.c:2851 commands/tablecmds.c:281 commands/tablecmds.c:305 +#: commands/tablecmds.c:17873 commands/tablecmds.c:19762 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\" är inte ett index" -#: access/index/indexam.c:979 +#: access/index/indexam.c:1028 #, c-format msgid "operator class %s has no options" msgstr "operatorklass %s har inga flaggor" @@ -1507,7 +1700,7 @@ msgid "This may be because of a non-immutable index expression." msgstr "Det kan bero på ett icke-immutable indexuttryck." #: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 -#: parser/parse_utilcmd.c:2317 +#: parser/parse_utilcmd.c:2323 #, c-format msgid "index \"%s\" is not a btree" msgstr "index \"%s\" är inte ett btree" @@ -1517,27 +1710,27 @@ msgstr "index \"%s\" är inte ett btree" msgid "version mismatch in index \"%s\": file version %d, current version %d, minimal supported version %d" msgstr "versionsfel i index \"%s\": filversion %d, aktuell version %d, minsta supportade version %d" -#: access/nbtree/nbtpage.c:1866 +#: access/nbtree/nbtpage.c:1861 #, c-format msgid "index \"%s\" contains a half-dead internal page" msgstr "index \"%s\" innehåller en halvdöd intern sida" -#: access/nbtree/nbtpage.c:1868 +#: access/nbtree/nbtpage.c:1863 #, c-format msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it." msgstr "Detta kan ha orsakats av en avbruten VACUUM i version 9.3 eller äldre, innan uppdatering. Vänligen REINDEX:era det." -#: access/nbtree/nbtutils.c:2662 +#: access/nbtree/nbtutils.c:5108 #, c-format msgid "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" msgstr "indexradstorlek %zu överstiger btree version %u maximum %zu för index \"%s\"" -#: access/nbtree/nbtutils.c:2668 +#: access/nbtree/nbtutils.c:5114 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "Indexrad refererar tupel (%u,%u) i relation \"%s\"." -#: access/nbtree/nbtutils.c:2672 +#: access/nbtree/nbtutils.c:5118 #, c-format msgid "" "Values larger than 1/3 of a buffer page cannot be indexed.\n" @@ -1552,12 +1745,18 @@ msgstr "" msgid "operator family \"%s\" of access method %s is missing support function for types %s and %s" msgstr "operatorfamilj \"%s\" för accessmetod %s saknar supportfunktioner för typerna %s och %s" +#: access/sequence/sequence.c:75 access/table/table.c:145 +#: optimizer/util/plancat.c:144 +#, c-format +msgid "cannot open relation \"%s\"" +msgstr "kan inte öppna relationen \"%s\"" + #: access/spgist/spgutils.c:245 #, c-format msgid "compress method must be defined when leaf type is different from input type" msgstr "komprimeringsmetod måste definieras när lövtypen skiljer sig från indatatypen" -#: access/spgist/spgutils.c:1008 +#: access/spgist/spgutils.c:1028 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "SP-GiST inre tuplestorlek %zu överstiger maximala %zu" @@ -1572,314 +1771,313 @@ msgstr "SP-GiST lövdatatyp %s matchar deklarerad typ %s" msgid "operator family \"%s\" of access method %s is missing support function %d for type %s" msgstr "operatorfamilj \"%s\" för accessmetod %s saknar supportfunktion %d för typ %s" -#: access/table/table.c:145 optimizer/util/plancat.c:145 -#, c-format -msgid "cannot open relation \"%s\"" -msgstr "kan inte öppna relationen \"%s\"" - -#: access/table/tableam.c:265 +#: access/table/tableam.c:255 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "tid (%u, %u) är inte giltigt för relation \"%s\"" -#: access/table/tableamapi.c:116 +#: access/table/tableamapi.c:109 #, c-format -msgid "%s cannot be empty." -msgstr "%s får inte vara tom." +msgid "\"%s\" cannot be empty." +msgstr "\"%s\" får inte vara tom." -#: access/table/tableamapi.c:123 access/transam/xlogrecovery.c:4774 +#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4859 #, c-format -msgid "%s is too long (maximum %d characters)." -msgstr "%s är för lång (maximalt %d tecken)." +msgid "\"%s\" is too long (maximum %d characters)." +msgstr "\"%s\" är för lång (maximalt %d tecken)." -#: access/table/tableamapi.c:146 +#: access/table/tableamapi.c:139 #, c-format msgid "table access method \"%s\" does not exist" msgstr "tabellaccessmetod \"%s\" existerar inte" -#: access/table/tableamapi.c:151 +#: access/table/tableamapi.c:144 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "Tabellaccessmetod \"%s\" existerar inte." -#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:152 +#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:151 #, c-format msgid "sample percentage must be between 0 and 100" msgstr "urvalsprocent måste vara mellan 0 och 100" -#: access/transam/commit_ts.c:279 +#: access/transam/commit_ts.c:287 #, c-format msgid "cannot retrieve commit timestamp for transaction %u" msgstr "kan inte hämta commit-tidsstämpel för transaktion %u" -#: access/transam/commit_ts.c:377 +#: access/transam/commit_ts.c:385 #, c-format msgid "could not get commit timestamp data" msgstr "kunde inte hämta commit-tidsstämpeldata" -#: access/transam/commit_ts.c:379 +#: access/transam/commit_ts.c:387 #, c-format msgid "Make sure the configuration parameter \"%s\" is set on the primary server." msgstr "Se till att konfigurationsparametern \"%s\" är satt på primär-servern." -#: access/transam/commit_ts.c:381 +#: access/transam/commit_ts.c:389 #, c-format msgid "Make sure the configuration parameter \"%s\" is set." msgstr "Se till att konfigurationsparametern \"%s\" är satt." -#: access/transam/multixact.c:1023 +#: access/transam/multixact.c:1091 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"" -msgstr "databasen tar inte emot kommandon som genererar nya MultiXactId:er för att förhinda dataförlust vid \"wraparound\" i databasen \"%s\"" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"" +msgstr "databasen tar inte emot kommandon som tilldelar nya MultiXactId:er för att förhinda dataförlust vid \"wraparound\" i databasen \"%s\"" -#: access/transam/multixact.c:1025 access/transam/multixact.c:1032 -#: access/transam/multixact.c:1056 access/transam/multixact.c:1065 +#: access/transam/multixact.c:1093 access/transam/multixact.c:1100 +#: access/transam/multixact.c:1124 access/transam/multixact.c:1133 +#: access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format msgid "" "Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"Utför en hela databasen-VACUUM i den databasen.\n" +"Utför en databas-VACUUM i hela den databasen.\n" "Du kan också behöva commit:a eller rulla tillbaka gamla förberedda transaktioner eller slänga gamla replikeringsslottar." -#: access/transam/multixact.c:1030 +#: access/transam/multixact.c:1098 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u" -msgstr "databasen tar inte emot kommandon som genererar nya MultiXactId:er för att förhinda dataförlust vid \"wraparound\" i databasen med OID %u" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u" +msgstr "databasen tar inte emot kommandon som tilldelar nya MultiXactId:er för att förhinda dataförlust vid \"wraparound\" i databasen med OID %u" -#: access/transam/multixact.c:1051 access/transam/multixact.c:2333 +#: access/transam/multixact.c:1119 access/transam/multixact.c:2474 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used" msgstr[0] "databasen \"%s\" måste städas innan ytterligare %u MultiXactId används" msgstr[1] "databasen \"%s\" måste städas innan ytterligare %u MultiXactId:er används" -#: access/transam/multixact.c:1060 access/transam/multixact.c:2342 +#: access/transam/multixact.c:1128 access/transam/multixact.c:2483 #, c-format msgid "database with OID %u must be vacuumed before %u more MultiXactId is used" msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used" msgstr[0] "databas med OID %u måste städas (vacuum) innan %u till MultiXactId används" msgstr[1] "databas med OID %u måste städas (vacuum) innan %u till MultiXactId:er används" -#: access/transam/multixact.c:1121 +#: access/transam/multixact.c:1189 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "multixact \"members\"-gräns överskriden" -#: access/transam/multixact.c:1122 +#: access/transam/multixact.c:1190 #, c-format msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member." msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members." msgstr[0] "Detta kommando skapar en multixact med %u medlemmar, men återstående utrymmer räcker bara till %u medlem." msgstr[1] "Detta kommando skapar en multixact med %u medlemmar, men återstående utrymmer räcker bara till %u medlemmar." -#: access/transam/multixact.c:1127 +#: access/transam/multixact.c:1195 #, c-format -msgid "Execute a database-wide VACUUM in database with OID %u with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Kör en hela-databas-VACUUM i databas med OID %u med reducerade iställningar vacuum_multixact_freeze_min_age och vacuum_multixact_freeze_table_age." +msgid "Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Kör en databas-VACUUM i hela databasen med OID %u med reducerade inställningar för \"vacuum_multixact_freeze_min_age\" och \"vacuum_multixact_freeze_table_age\"." -#: access/transam/multixact.c:1158 +#: access/transam/multixact.c:1226 #, c-format msgid "database with OID %u must be vacuumed before %d more multixact member is used" msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used" msgstr[0] "databas med OID %u måste städas innan %d mer multixact-medlem används" msgstr[1] "databas med OID %u måste städas innan %d fler multixact-medlemmar används" -#: access/transam/multixact.c:1163 +#: access/transam/multixact.c:1231 #, c-format -msgid "Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Kör en hela-databas-VACUUM i den databasen med reducerade inställningar för vacuum_multixact_freeze_min_age och vacuum_multixact_freeze_table_age." +msgid "Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Kör en databas-VACUUM i hela den databasen med reducerade inställningar för \"vacuum_multixact_freeze_min_age\" och \"vacuum_multixact_freeze_table_age\"." -#: access/transam/multixact.c:1302 +#: access/transam/multixact.c:1371 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "MultiXactId %u finns inte längre -- troligen en wraparound" -#: access/transam/multixact.c:1308 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "MultiXactId %u har inte skapats än -- troligen en wraparound" -#: access/transam/multixact.c:2338 access/transam/multixact.c:2347 -#: access/transam/varsup.c:151 access/transam/varsup.c:158 -#: access/transam/varsup.c:466 access/transam/varsup.c:473 +#: access/transam/multixact.c:2479 access/transam/multixact.c:2488 #, c-format msgid "" -"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n" +"To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"För att undvika att databasen stängs ner, utför en hela databas-VACCUM i den databasen.\n" +"För att undvika fel vid tilldelning av MultiXactId så utför en databas-VACCUM för hela den databasen.\n" "Du kan också behöva commit:a eller rulla tillbaka gamla förberedda transaktioner eller slänga gamla replikeringsslottar." -#: access/transam/multixact.c:2622 +#: access/transam/multixact.c:2767 #, c-format msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" msgstr "MultiXact-medlems wraparound-skydd är avslagen eftersom äldsta checkpoint:ade MultiXact %u inte finns på disk" -#: access/transam/multixact.c:2644 +#: access/transam/multixact.c:2789 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "MultiXact-medlems wraparound-skydd är nu påslagen" -#: access/transam/multixact.c:3027 +#: access/transam/multixact.c:3180 #, c-format msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "äldsta MultiXact %u hittas inte, tidigast MultiXact %u, skippar trunkering" -#: access/transam/multixact.c:3045 +#: access/transam/multixact.c:3198 #, c-format msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation" msgstr "kan inte trunkera upp till %u eftersom den inte finns på disk, skippar trunkering" -#: access/transam/multixact.c:3359 +#: access/transam/multixact.c:3517 #, c-format msgid "invalid MultiXactId: %u" msgstr "ogiltig MultiXactId: %u" -#: access/transam/parallel.c:729 access/transam/parallel.c:848 +#: access/transam/parallel.c:748 access/transam/parallel.c:867 #, c-format msgid "parallel worker failed to initialize" msgstr "parallell arbetare misslyckades med initiering" -#: access/transam/parallel.c:730 access/transam/parallel.c:849 +#: access/transam/parallel.c:749 access/transam/parallel.c:868 #, c-format msgid "More details may be available in the server log." msgstr "Fler detaljer kan finnas i serverloggen." -#: access/transam/parallel.c:910 +#: access/transam/parallel.c:929 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "postmaster avslutade under en parallell transaktion" -#: access/transam/parallel.c:1097 +#: access/transam/parallel.c:1116 #, c-format msgid "lost connection to parallel worker" msgstr "tappad kopplingen till parallell arbetare" -#: access/transam/parallel.c:1163 access/transam/parallel.c:1165 +#: access/transam/parallel.c:1172 access/transam/parallel.c:1174 msgid "parallel worker" msgstr "parallell arbetare" -#: access/transam/parallel.c:1319 replication/logical/applyparallelworker.c:893 +#: access/transam/parallel.c:1344 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "kunde inte skapa dynamiskt delat minnessegment: %m" -#: access/transam/parallel.c:1324 replication/logical/applyparallelworker.c:899 +#: access/transam/parallel.c:1349 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "ogiltigt magiskt nummer i dynamiskt delat minnessegment" -#: access/transam/rmgr.c:84 +#: access/transam/rmgr.c:93 #, c-format msgid "resource manager with ID %d not registered" msgstr "resurshanterare med ID %d är inte registrerad" -#: access/transam/rmgr.c:85 +#: access/transam/rmgr.c:94 #, c-format -msgid "Include the extension module that implements this resource manager in shared_preload_libraries." -msgstr "Inkludera utökningsmodulen som implementerar denna resurshanterar i shared_preload_libraries." +msgid "Include the extension module that implements this resource manager in \"shared_preload_libraries\"." +msgstr "Inkludera utökningsmodulen som implementerar denna resurshanterare i \"shared_preload_libraries\"." -#: access/transam/rmgr.c:101 +#: access/transam/rmgr.c:110 #, c-format msgid "custom resource manager name is invalid" msgstr "namn på egendefinierad resurshanterare är ogiltigt" -#: access/transam/rmgr.c:102 +#: access/transam/rmgr.c:111 #, c-format msgid "Provide a non-empty name for the custom resource manager." msgstr "Ange ett icke-tomt namn för den egendefinierade resurshanteraren." -#: access/transam/rmgr.c:105 +#: access/transam/rmgr.c:114 #, c-format msgid "custom resource manager ID %d is out of range" msgstr "egendefinierat resurshanterar-ID %d är utanför giltigt intervall" -#: access/transam/rmgr.c:106 +#: access/transam/rmgr.c:115 #, c-format msgid "Provide a custom resource manager ID between %d and %d." msgstr "Ange ett egendefinierat resurshanterar-ID mellan %d och %d." -#: access/transam/rmgr.c:111 access/transam/rmgr.c:116 -#: access/transam/rmgr.c:128 +#: access/transam/rmgr.c:120 access/transam/rmgr.c:125 +#: access/transam/rmgr.c:137 #, c-format msgid "failed to register custom resource manager \"%s\" with ID %d" msgstr "misslyckades med att registera en egendefinierad resurshanterare \"%s\" med ID %d" -#: access/transam/rmgr.c:112 +#: access/transam/rmgr.c:121 #, c-format -msgid "Custom resource manager must be registered while initializing modules in shared_preload_libraries." -msgstr "Egendefinierad resurshanterare måste vara registerad när man initierar moduler i shared_preload_libraries." +msgid "Custom resource manager must be registered while initializing modules in \"shared_preload_libraries\"." +msgstr "Egendefinierad resurshanterare måste vara registerad när man initierar moduler i \"shared_preload_libraries\"." -#: access/transam/rmgr.c:117 +#: access/transam/rmgr.c:126 #, c-format msgid "Custom resource manager \"%s\" already registered with the same ID." msgstr "Egendefinierad resurshanterare \"%s\" är redan registrerade med samma ID." -#: access/transam/rmgr.c:129 +#: access/transam/rmgr.c:138 #, c-format msgid "Existing resource manager with ID %d has the same name." msgstr "Det finns redan en resurshanterare med ID %d som har samma namn." -#: access/transam/rmgr.c:135 +#: access/transam/rmgr.c:144 #, c-format msgid "registered custom resource manager \"%s\" with ID %d" msgstr "registrerade egendefinerad resurshanterare \"%s\" med ID %d" -#: access/transam/slru.c:714 +#: access/transam/slru.c:361 +#, c-format +msgid "\"%s\" must be a multiple of %d" +msgstr "\"%s\" måste vara en multiple av \"%d\"" + +#: access/transam/slru.c:830 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "filen \"%s\" existerar inte, läses som nollor" -#: access/transam/slru.c:946 access/transam/slru.c:952 -#: access/transam/slru.c:960 access/transam/slru.c:965 -#: access/transam/slru.c:972 access/transam/slru.c:977 -#: access/transam/slru.c:984 access/transam/slru.c:991 +#: access/transam/slru.c:1059 access/transam/slru.c:1065 +#: access/transam/slru.c:1073 access/transam/slru.c:1078 +#: access/transam/slru.c:1085 access/transam/slru.c:1090 +#: access/transam/slru.c:1097 access/transam/slru.c:1104 #, c-format msgid "could not access status of transaction %u" msgstr "kunde inte läsa status på transaktion %u" -#: access/transam/slru.c:947 +#: access/transam/slru.c:1060 #, c-format msgid "Could not open file \"%s\": %m." msgstr "Kunde inte öppna fil \"%s\": %m." -#: access/transam/slru.c:953 +#: access/transam/slru.c:1066 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "Kunde inte söka i fil \"%s\" till offset %d: %m." -#: access/transam/slru.c:961 +#: access/transam/slru.c:1074 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "Kunde inte läsa från fil \"%s\" på offset %d: %m." -#: access/transam/slru.c:966 +#: access/transam/slru.c:1079 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "Kunde inte läsa från fil \"%s\" på offset %d: läste för få bytes." -#: access/transam/slru.c:973 +#: access/transam/slru.c:1086 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "Kunde inte skriva till fil \"%s\" på offset %d: %m." -#: access/transam/slru.c:978 +#: access/transam/slru.c:1091 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "Kunde inte skriva till fil \"%s\" på offset %d: skrev för få bytes." -#: access/transam/slru.c:985 +#: access/transam/slru.c:1098 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "Kunde inte fsync:a fil \"%s\": %m." -#: access/transam/slru.c:992 +#: access/transam/slru.c:1105 #, c-format msgid "Could not close file \"%s\": %m." msgstr "Kunde inte stänga fil \"%s\": %m." -#: access/transam/slru.c:1253 +#: access/transam/slru.c:1431 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "Kunde inte trunkera katalog \"%s\": trolig wraparound" @@ -1924,788 +2122,824 @@ msgstr "Tidslinje-ID:er måste vara mindre än barnens tidslinje-ID:er." msgid "requested timeline %u is not in this server's history" msgstr "efterfrågad tidslinje %u finns inte i denna servers historik" -#: access/transam/twophase.c:386 +#: access/transam/twophase.c:368 #, c-format msgid "transaction identifier \"%s\" is too long" msgstr "transaktionsidentifierare \"%s\" är för lång" -#: access/transam/twophase.c:393 +#: access/transam/twophase.c:375 #, c-format msgid "prepared transactions are disabled" msgstr "förberedda transaktioner är avslagna" -#: access/transam/twophase.c:394 +#: access/transam/twophase.c:376 #, c-format -msgid "Set max_prepared_transactions to a nonzero value." -msgstr "Sätt max_prepared_transactions till ett ickenollvärde." +msgid "Set \"max_prepared_transactions\" to a nonzero value." +msgstr "Sätt \"max_prepared_transactions\" till ett värde som inte är noll." -#: access/transam/twophase.c:413 +#: access/transam/twophase.c:395 #, c-format msgid "transaction identifier \"%s\" is already in use" msgstr "transaktionsidentifierare \"%s\" används redan" -#: access/transam/twophase.c:422 access/transam/twophase.c:2517 +#: access/transam/twophase.c:404 access/transam/twophase.c:2531 #, c-format msgid "maximum number of prepared transactions reached" msgstr "maximalt antal förberedda transaktioner har uppnåtts" -#: access/transam/twophase.c:423 access/transam/twophase.c:2518 +#: access/transam/twophase.c:405 access/transam/twophase.c:2532 #, c-format -msgid "Increase max_prepared_transactions (currently %d)." -msgstr "Öka max_prepared_transactions (nu %d)." +msgid "Increase \"max_prepared_transactions\" (currently %d)." +msgstr "Öka \"max_prepared_transactions\" (nu %d)." -#: access/transam/twophase.c:599 +#: access/transam/twophase.c:580 #, c-format msgid "prepared transaction with identifier \"%s\" is busy" msgstr "förberedd transaktion med identifierare \"%s\" är upptagen" -#: access/transam/twophase.c:605 +#: access/transam/twophase.c:586 #, c-format msgid "permission denied to finish prepared transaction" msgstr "rättighet saknas för att slutföra förberedd transaktion" -#: access/transam/twophase.c:606 +#: access/transam/twophase.c:587 #, c-format msgid "Must be superuser or the user that prepared the transaction." msgstr "Måste vara superuser eller den användare som förberedde transaktionen" -#: access/transam/twophase.c:617 +#: access/transam/twophase.c:598 #, c-format msgid "prepared transaction belongs to another database" msgstr "förberedda transaktionen tillhör en annan databas" -#: access/transam/twophase.c:618 +#: access/transam/twophase.c:599 #, c-format msgid "Connect to the database where the transaction was prepared to finish it." msgstr "Anslut till databasen där transaktionen var förberedd för att slutföra den." -#: access/transam/twophase.c:633 +#: access/transam/twophase.c:614 #, c-format msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "förberedd transaktion med identifierare \"%s\" finns inte" -#: access/transam/twophase.c:1168 +#: access/transam/twophase.c:1174 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "tvåfas-statusfilens maximala längd överskriden" -#: access/transam/twophase.c:1323 +#: access/transam/twophase.c:1329 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" msgstr[0] "felaktig storlek på fil \"%s\": %lld byte" msgstr[1] "felaktig storlek på fil \"%s\": %lld bytes" -#: access/transam/twophase.c:1332 +#: access/transam/twophase.c:1338 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "inkorrekt justering (alignment) av CRC-offset för fil \"%s\"" -#: access/transam/twophase.c:1350 +#: access/transam/twophase.c:1356 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "kunde inte läsa fil \"%s\": läste %d av %lld" -#: access/transam/twophase.c:1365 +#: access/transam/twophase.c:1371 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "felaktigt magiskt nummer lagrat i fil \"%s\"" -#: access/transam/twophase.c:1371 +#: access/transam/twophase.c:1377 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "felaktig storlek lagrad i fil \"%s\"" -#: access/transam/twophase.c:1383 +#: access/transam/twophase.c:1389 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "beräknad CRC-checksumma matchar inte värdet som är lagrat i filen \"%s\"" -#: access/transam/twophase.c:1413 access/transam/xlogrecovery.c:590 -#: replication/logical/logical.c:209 replication/walsender.c:687 +#: access/transam/twophase.c:1419 access/transam/xlogrecovery.c:565 +#: postmaster/walsummarizer.c:936 replication/logical/logical.c:211 +#: replication/walsender.c:836 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "Misslyckades vid allokering av en WAL-läs-processor." -#: access/transam/twophase.c:1423 +#: access/transam/twophase.c:1429 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "kunde inte läsa tvåfas-status från WAL vid %X/%X: %s" -#: access/transam/twophase.c:1428 +#: access/transam/twophase.c:1434 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "kunde inte läsa tvåfas-status från WAL vid %X/%X" -#: access/transam/twophase.c:1436 +#: access/transam/twophase.c:1442 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "förväntad tvåfas-statusdata finns inte i WAL vid %X/%X" -#: access/transam/twophase.c:1732 +#: access/transam/twophase.c:1745 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "kan inte återskapa fil \"%s\": %m" -#: access/transam/twophase.c:1859 +#: access/transam/twophase.c:1872 #, c-format msgid "%u two-phase state file was written for a long-running prepared transaction" msgid_plural "%u two-phase state files were written for long-running prepared transactions" msgstr[0] "%u tvåfas-statusfil skrevs för långkörande förberedd transkation" msgstr[1] "%u tvåfas-statusfiler skrevs för långkörande förberedda transaktioner" -#: access/transam/twophase.c:2093 +#: access/transam/twophase.c:2107 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "återskapar förberedd transaktion %u från delat minne" -#: access/transam/twophase.c:2186 +#: access/transam/twophase.c:2200 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "tar bort död tvåfas-statusfil för transaktioon %u" -#: access/transam/twophase.c:2193 +#: access/transam/twophase.c:2207 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "tar bort död tvåfas-statusfil från minne för transaktion %u" -#: access/transam/twophase.c:2206 +#: access/transam/twophase.c:2220 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "tar bort framtida tvåfas-statusfil för transaktion %u" -#: access/transam/twophase.c:2213 +#: access/transam/twophase.c:2227 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "tar bort framtida tvåfas-statusfil från minne för transaktion %u" -#: access/transam/twophase.c:2238 +#: access/transam/twophase.c:2252 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "korrupt tvåfas-statusfil för transaktion %u" -#: access/transam/twophase.c:2243 +#: access/transam/twophase.c:2257 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "korrupt tvåfas-status i minnet för transaktion %u" -#: access/transam/twophase.c:2500 +#: access/transam/twophase.c:2514 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "kunde inte återställa tvåfas-statusfil för transaktion %u" -#: access/transam/twophase.c:2502 +#: access/transam/twophase.c:2516 #, c-format msgid "Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk." msgstr "Statefil för tvåfas har hittats i WAL-post %X/%X men denna transaktion har redan återställts från disk." -#: access/transam/twophase.c:2510 jit/jit.c:205 utils/fmgr/dfmgr.c:209 -#: utils/fmgr/dfmgr.c:415 +#: access/transam/twophase.c:2524 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 #, c-format msgid "could not access file \"%s\": %m" msgstr "kunde inte komma åt filen \"%s\": %m" -#: access/transam/varsup.c:129 +#: access/transam/varsup.c:156 +#, c-format +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"" +msgstr "databasen tar inte emot kommandon som tilldelar nya transaktions-ID för att förhinda dataförlust vid \"wraparound\" i databasen \"%s\"" + +#: access/transam/varsup.c:163 +#, c-format +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u" +msgstr "databasen tar inte emot kommandon som tilldelar nya transaktions-ID för att förhinda dataförlust vid \"wraparound\" i databasen med OID %u" + +#: access/transam/varsup.c:175 access/transam/varsup.c:490 #, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database \"%s\"" -msgstr "databasen tar inte emot kommandon för att förhinda dataförlust vid \"wraparound\" i databasen \"%s\"" +msgid "database \"%s\" must be vacuumed within %u transactions" +msgstr "databas \"%s\" måste städas (vacuum) inom %u transaktioner" -#: access/transam/varsup.c:131 access/transam/varsup.c:138 +#: access/transam/varsup.c:178 #, c-format msgid "" -"Stop the postmaster and vacuum that database in single-user mode.\n" +"To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." msgstr "" -"Stoppa postmaster och städa (vacuum) den databasen i enanvändarläge.\n" -"Du kan också behöva commit:a eller rulla tillbaka förberedda transaktioner eller slänga gamla replikeringsslottar." +"För att undvika fel vid tilldelning av transaktions-ID så utför en databas-VACCUM för hela den databasen.\n" +"Du kan också behöva commit:a eller rulla tillbaka gamla förberedda transaktioner eller slänga gamla replikeringsslottar." -#: access/transam/varsup.c:136 +#: access/transam/varsup.c:182 access/transam/varsup.c:497 #, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database with OID %u" -msgstr "databasen tar inte emot kommandon för att förhinda dataförlust vid wraparound i databas med OID %u" +msgid "database with OID %u must be vacuumed within %u transactions" +msgstr "databas med OID %u måste städas (vacuum) inom %u transaktioner" -#: access/transam/varsup.c:148 access/transam/varsup.c:463 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 +#: access/transam/varsup.c:500 #, c-format -msgid "database \"%s\" must be vacuumed within %u transactions" -msgstr "databas \"%s\" måste städas (vacuum) inom %u transaktioner" +msgid "" +"To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "" +"För att undvika fel vid tilldelning av XID så utför en databas-VACCUM för hela den databasen.\n" +"Du kan också behöva commit:a eller rulla tillbaka gamla förberedda transaktioner eller slänga gamla replikeringsslottar." -#: access/transam/varsup.c:155 access/transam/varsup.c:470 +#: access/transam/xact.c:649 #, c-format -msgid "database with OID %u must be vacuumed within %u transactions" -msgstr "databas med OID %u måste städas (vacuum) inom %u transaktioner" +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "can inte tilldela transaktions-ID under en parallell operation" + +#: access/transam/xact.c:840 +#, c-format +msgid "cannot modify data in a parallel worker" +msgstr "kan inte modifiera data i en parellell arbetare" + +#: access/transam/xact.c:1115 +#, c-format +msgid "cannot start commands during a parallel operation" +msgstr "kan inte starta kommandon under en parallell operation" -#: access/transam/xact.c:1102 +#: access/transam/xact.c:1123 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "kan inte ha mer än 2^32-2 kommandon i en transaktion" -#: access/transam/xact.c:1643 +#: access/transam/xact.c:1664 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "maximalt antal commit:ade undertransaktioner (%d) överskridet" -#: access/transam/xact.c:2513 +#: access/transam/xact.c:2561 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "kan inte göra PREPARE på en transaktion som har arbetat med temporära objekt" -#: access/transam/xact.c:2523 +#: access/transam/xact.c:2571 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "kan inte göra PREPARE på en transaktion som har exporterade snapshots" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3490 +#: access/transam/xact.c:3593 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s kan inte köras i ett transaktionsblock" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3500 +#: access/transam/xact.c:3603 #, c-format msgid "%s cannot run inside a subtransaction" -msgstr "%s kan inte köras i ett undertransaktionsblock" +msgstr "%s kan inte köras i en undertransaktion" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3510 +#: access/transam/xact.c:3613 #, c-format msgid "%s cannot be executed within a pipeline" msgstr "%s kan inte köras inuti en pipeline" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3520 +#: access/transam/xact.c:3623 #, c-format msgid "%s cannot be executed from a function" msgstr "%s kan inte köras från en funktion" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3591 access/transam/xact.c:3916 -#: access/transam/xact.c:3995 access/transam/xact.c:4118 -#: access/transam/xact.c:4269 access/transam/xact.c:4338 -#: access/transam/xact.c:4449 +#: access/transam/xact.c:3694 access/transam/xact.c:4019 +#: access/transam/xact.c:4098 access/transam/xact.c:4221 +#: access/transam/xact.c:4372 access/transam/xact.c:4441 +#: access/transam/xact.c:4552 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%s kan bara användas i transaktionsblock" -#: access/transam/xact.c:3802 +#: access/transam/xact.c:3905 #, c-format msgid "there is already a transaction in progress" msgstr "det är redan en transaktion igång" -#: access/transam/xact.c:3921 access/transam/xact.c:4000 -#: access/transam/xact.c:4123 +#: access/transam/xact.c:4024 access/transam/xact.c:4103 +#: access/transam/xact.c:4226 #, c-format msgid "there is no transaction in progress" msgstr "ingen transaktion pågår" -#: access/transam/xact.c:4011 +#: access/transam/xact.c:4114 #, c-format msgid "cannot commit during a parallel operation" msgstr "kan inte commit:a under en parallell operation" -#: access/transam/xact.c:4134 +#: access/transam/xact.c:4237 #, c-format msgid "cannot abort during a parallel operation" msgstr "can inte avbryta under en parallell operation" -#: access/transam/xact.c:4233 +#: access/transam/xact.c:4336 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "kan inte definiera sparpunkter under en parallell operation" -#: access/transam/xact.c:4320 +#: access/transam/xact.c:4423 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "kan inte frigöra en sparpunkt under en parallell operation" -#: access/transam/xact.c:4330 access/transam/xact.c:4381 -#: access/transam/xact.c:4441 access/transam/xact.c:4490 +#: access/transam/xact.c:4433 access/transam/xact.c:4484 +#: access/transam/xact.c:4544 access/transam/xact.c:4593 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "sparpunkt \"%s\" existerar inte" -#: access/transam/xact.c:4387 access/transam/xact.c:4496 +#: access/transam/xact.c:4490 access/transam/xact.c:4599 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "sparpunkt \"%s\" finns inte inom aktuell sparpunktsnivå" -#: access/transam/xact.c:4429 +#: access/transam/xact.c:4532 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "kan inte rulla tillbaka till sparpunkt under en parallell operation" -#: access/transam/xact.c:4557 +#: access/transam/xact.c:5376 #, c-format -msgid "cannot start subtransactions during a parallel operation" -msgstr "kan inte starta subtransaktioner under en parallell operation" +msgid "cannot have more than 2^32-1 subtransactions in a transaction" +msgstr "kan inte ha mer än 2^32-1 undertransaktioner i en transaktion" -#: access/transam/xact.c:4625 +#: access/transam/xlog.c:1542 #, c-format -msgid "cannot commit subtransactions during a parallel operation" -msgstr "kan inte commit:a subtransaktioner undert en parallell operation" +msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" +msgstr "förfrågan att flush:a efter slutet av genererad WAL; efterfrågad %X/%X, aktuell position %X/%X" -#: access/transam/xact.c:5271 +#: access/transam/xlog.c:1769 #, c-format -msgid "cannot have more than 2^32-1 subtransactions in a transaction" -msgstr "kan inte ha mer än 2^32-1 subtransaktioner i en transaktion" +msgid "cannot read past end of generated WAL: requested %X/%X, current position %X/%X" +msgstr "kan inte läsa efter slutet av genererad WAL; efterfrågad %X/%X, aktuell position %X/%X" -#: access/transam/xlog.c:1466 +#: access/transam/xlog.c:2210 access/transam/xlog.c:4501 #, c-format -msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" -msgstr "förfrågan att flush:a efter slutet av genererad WAL; efterfrågad %X/%X, aktuell position %X/%X" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL-segmentstorleken måste vara en tvåpotens mellan 1 MB och 1 GB." #: access/transam/xlog.c:2228 #, c-format -msgid "could not write to log file %s at offset %u, length %zu: %m" -msgstr "kunde inte skriva till loggfil %s vid offset %u, längd %zu: %m" +msgid "\"%s\" must be set to -1 during binary upgrade mode." +msgstr "\"%s\" måsta vara satt till -1 i binärt uppgraderingsläge" + +#: access/transam/xlog.c:2477 +#, c-format +msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" +msgstr "kunde inte skriva till loggfil \"%s\" vid offset %u, längd %zu: %m" -#: access/transam/xlog.c:3455 access/transam/xlogutils.c:833 -#: replication/walsender.c:2725 +#: access/transam/xlog.c:3739 access/transam/xlogutils.c:831 +#: replication/walsender.c:3045 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "efterfrågat WAL-segment %s har redan tagits bort" -#: access/transam/xlog.c:3739 +#: access/transam/xlog.c:4061 #, c-format msgid "could not rename file \"%s\": %m" msgstr "kunde inte byta namn på fil \"%s\": %m" -#: access/transam/xlog.c:3781 access/transam/xlog.c:3791 +#: access/transam/xlog.c:4104 access/transam/xlog.c:4115 +#: access/transam/xlog.c:4136 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "krävd WAL-katalog \"%s\" finns inte" -#: access/transam/xlog.c:3797 +#: access/transam/xlog.c:4121 access/transam/xlog.c:4142 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "skapar saknad WAL-katalog \"%s\"" -#: access/transam/xlog.c:3800 commands/dbcommands.c:3172 +#: access/transam/xlog.c:4125 access/transam/xlog.c:4145 +#: commands/dbcommands.c:3262 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "kunde inte skapa saknad katalog \"%s\": %m" -#: access/transam/xlog.c:3867 +#: access/transam/xlog.c:4212 #, c-format msgid "could not generate secret authorization token" msgstr "kunde inte generera hemligt auktorisationstoken" -#: access/transam/xlog.c:4017 access/transam/xlog.c:4026 -#: access/transam/xlog.c:4050 access/transam/xlog.c:4057 -#: access/transam/xlog.c:4064 access/transam/xlog.c:4069 -#: access/transam/xlog.c:4076 access/transam/xlog.c:4083 -#: access/transam/xlog.c:4090 access/transam/xlog.c:4097 -#: access/transam/xlog.c:4104 access/transam/xlog.c:4111 -#: access/transam/xlog.c:4120 access/transam/xlog.c:4127 -#: utils/init/miscinit.c:1762 +#: access/transam/xlog.c:4363 access/transam/xlog.c:4373 +#: access/transam/xlog.c:4399 access/transam/xlog.c:4407 +#: access/transam/xlog.c:4415 access/transam/xlog.c:4421 +#: access/transam/xlog.c:4429 access/transam/xlog.c:4437 +#: access/transam/xlog.c:4445 access/transam/xlog.c:4453 +#: access/transam/xlog.c:4461 access/transam/xlog.c:4469 +#: access/transam/xlog.c:4479 access/transam/xlog.c:4487 +#: utils/init/miscinit.c:1812 #, c-format msgid "database files are incompatible with server" msgstr "databasfilerna är inkompatibla med servern" -#: access/transam/xlog.c:4018 +#: access/transam/xlog.c:4364 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)." msgstr "Databasklustret initierades med PG_CONTROL_VERSION %d (0x%08x), men servern kompilerades med PG_CONTROL_VERSION %d (0x%08x)." -#: access/transam/xlog.c:4022 +#: access/transam/xlog.c:4368 #, c-format msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb." msgstr "Detta kan orsakas av en felaktig byte-ordning. Du behöver troligen köra initdb." -#: access/transam/xlog.c:4027 +#: access/transam/xlog.c:4374 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "Databasklustret initierades med PG_CONTROL_VERSION %d, men servern kompilerades med PG_CONTROL_VERSION %d." -#: access/transam/xlog.c:4030 access/transam/xlog.c:4054 -#: access/transam/xlog.c:4061 access/transam/xlog.c:4066 +#: access/transam/xlog.c:4377 access/transam/xlog.c:4403 +#: access/transam/xlog.c:4411 access/transam/xlog.c:4417 #, c-format msgid "It looks like you need to initdb." msgstr "Du behöver troligen köra initdb." -#: access/transam/xlog.c:4041 +#: access/transam/xlog.c:4389 #, c-format msgid "incorrect checksum in control file" msgstr "ogiltig kontrollsumma kontrollfil" -#: access/transam/xlog.c:4051 +#: access/transam/xlog.c:4400 #, c-format msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." msgstr "Databasklustret initierades med CATALOG_VERSION_NO %d, men servern kompilerades med CATALOG_VERSION_NO %d." -#: access/transam/xlog.c:4058 +#: access/transam/xlog.c:4408 #, c-format msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." msgstr "Databasklustret initierades med MAXALIGN %d, men servern kompilerades med MAXALIGN %d." -#: access/transam/xlog.c:4065 +#: access/transam/xlog.c:4416 #, c-format msgid "The database cluster appears to use a different floating-point number format than the server executable." msgstr "Databasklustret verkar använda en annan flyttalsrepresentation än vad serverprogrammet gör." -#: access/transam/xlog.c:4070 +#: access/transam/xlog.c:4422 #, c-format msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." msgstr "Databasklustret initierades med BLCKSZ %d, men servern kompilerades med BLCKSZ %d." -#: access/transam/xlog.c:4073 access/transam/xlog.c:4080 -#: access/transam/xlog.c:4087 access/transam/xlog.c:4094 -#: access/transam/xlog.c:4101 access/transam/xlog.c:4108 -#: access/transam/xlog.c:4115 access/transam/xlog.c:4123 -#: access/transam/xlog.c:4130 +#: access/transam/xlog.c:4425 access/transam/xlog.c:4433 +#: access/transam/xlog.c:4441 access/transam/xlog.c:4449 +#: access/transam/xlog.c:4457 access/transam/xlog.c:4465 +#: access/transam/xlog.c:4473 access/transam/xlog.c:4482 +#: access/transam/xlog.c:4490 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "Det verkar som om du måste kompilera om eller köra initdb." -#: access/transam/xlog.c:4077 +#: access/transam/xlog.c:4430 #, c-format msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." msgstr "Databasklustret initierades med RELSEG_SIZE %d, men servern kompilerades med RELSEG_SIZE %d." -#: access/transam/xlog.c:4084 +#: access/transam/xlog.c:4438 #, c-format msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." msgstr "Databasklustret initierades med XLOG_BLCKSZ %d, men servern kompilerades med XLOG_BLCKSZ %d." -#: access/transam/xlog.c:4091 +#: access/transam/xlog.c:4446 #, c-format msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." msgstr "Databasklustret initierades med NAMEDATALEN %d, men servern kompilerades med NAMEDATALEN %d." -#: access/transam/xlog.c:4098 +#: access/transam/xlog.c:4454 #, c-format msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." msgstr "Databasklustret initierades med INDEX_MAX_KEYS %d, men servern kompilerades med INDEX_MAX_KEYS %d." -#: access/transam/xlog.c:4105 +#: access/transam/xlog.c:4462 #, c-format msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." msgstr "Databasklustret initierades med TOAST_MAX_CHUNK_SIZE %d, men servern kompilerades med TOAST_MAX_CHUNK_SIZE %d." -#: access/transam/xlog.c:4112 +#: access/transam/xlog.c:4470 #, c-format msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." msgstr "Databasklustret initierades med LOBLKSIZE %d, men servern kompilerades med LOBLKSIZE %d." -#: access/transam/xlog.c:4121 +#: access/transam/xlog.c:4480 #, c-format msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL." msgstr "Databasklustret initierades utan USE_FLOAT8_BYVAL, men servern kompilerades med USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4128 +#: access/transam/xlog.c:4488 #, c-format msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL." msgstr "Databasklustret initierades med USE_FLOAT8_BYVAL, men servern kompilerades utan USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4137 +#: access/transam/xlog.c:4497 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte" -msgstr[1] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" +msgstr[1] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" -#: access/transam/xlog.c:4149 +#: access/transam/xlog.c:4510 #, c-format msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"min_wal_size\" måste vara minst dubbla \"wal_segment_size\"" -#: access/transam/xlog.c:4153 +#: access/transam/xlog.c:4514 #, c-format msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"max_wal_size\" måste vara minst dubbla \"wal_segment_size\"" -#: access/transam/xlog.c:4308 catalog/namespace.c:4335 -#: commands/tablespace.c:1216 commands/user.c:2536 commands/variable.c:72 -#: utils/error/elog.c:2205 +#: access/transam/xlog.c:4662 catalog/namespace.c:4696 +#: commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 +#: replication/slot.c:2429 tcop/postgres.c:3715 utils/error/elog.c:2247 #, c-format msgid "List syntax is invalid." msgstr "List-syntaxen är ogiltig." -#: access/transam/xlog.c:4354 commands/user.c:2552 commands/variable.c:173 -#: utils/error/elog.c:2231 +#: access/transam/xlog.c:4708 commands/user.c:2545 commands/variable.c:173 +#: tcop/postgres.c:3731 utils/error/elog.c:2273 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "Okänt nyckelord: \"%s\"" -#: access/transam/xlog.c:4768 +#: access/transam/xlog.c:5129 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "kunde inte skriva bootstrap-write-ahead-loggfil: %m" -#: access/transam/xlog.c:4776 +#: access/transam/xlog.c:5137 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "kunde inte fsync:a bootstrap-write-ahead-loggfil: %m" -#: access/transam/xlog.c:4782 +#: access/transam/xlog.c:5143 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "kunde inte stänga bootstrap-write-ahead-loggfil: %m" -#: access/transam/xlog.c:4999 +#: access/transam/xlog.c:5368 #, c-format -msgid "WAL was generated with wal_level=minimal, cannot continue recovering" -msgstr "WAL genererades med wal_level=minimal, kan inte fortsätta återställande" +msgid "WAL was generated with \"wal_level=minimal\", cannot continue recovering" +msgstr "WAL genererades med \"wal_level=minimal\", kan inte fortsätta återställande" -#: access/transam/xlog.c:5000 +#: access/transam/xlog.c:5369 #, c-format -msgid "This happens if you temporarily set wal_level=minimal on the server." -msgstr "Detta händer om du temporärt sätter wal_level=minimal på servern." +msgid "This happens if you temporarily set \"wal_level=minimal\" on the server." +msgstr "Detta händer om du temporärt sätter \"wal_level=minimal\" på servern." -#: access/transam/xlog.c:5001 +#: access/transam/xlog.c:5370 #, c-format -msgid "Use a backup taken after setting wal_level to higher than minimal." -msgstr "Använd en backup som är tagen efter att inställningen wal_level satts till ett högre värde än minimal." +msgid "Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." +msgstr "Använd en backup som är tagen efter att inställningen \"wal_level\" satts till ett högre värde än \"minimal\"." -#: access/transam/xlog.c:5065 +#: access/transam/xlog.c:5435 #, c-format msgid "control file contains invalid checkpoint location" msgstr "kontrollfil innehåller ogiltig checkpoint-position" -#: access/transam/xlog.c:5076 +#: access/transam/xlog.c:5446 #, c-format msgid "database system was shut down at %s" msgstr "databassystemet stängdes ner vid %s" -#: access/transam/xlog.c:5082 +#: access/transam/xlog.c:5452 #, c-format msgid "database system was shut down in recovery at %s" msgstr "databassystemet stängdes ner under återställning vid %s" -#: access/transam/xlog.c:5088 +#: access/transam/xlog.c:5458 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "nedstängning av databasen avbröts; senast kända upptidpunkt vid %s" -#: access/transam/xlog.c:5094 +#: access/transam/xlog.c:5464 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "databassystemet avbröts under återställning vid %s" -#: access/transam/xlog.c:5096 +#: access/transam/xlog.c:5466 #, c-format msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "Det betyder troligen att en del data är förstörd och du behöver återställa databasen från den senaste backup:en." -#: access/transam/xlog.c:5102 +#: access/transam/xlog.c:5472 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "databassystemet avbröts under återställning vid loggtid %s" -#: access/transam/xlog.c:5104 +#: access/transam/xlog.c:5474 #, c-format msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target." msgstr "Om detta har hänt mer än en gång så kan data vara korrupt och du kanske måste återställa till ett tidigare återställningsmål." -#: access/transam/xlog.c:5110 +#: access/transam/xlog.c:5480 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "databassystemet avbröts; senast kända upptidpunkt vid %s" -#: access/transam/xlog.c:5116 +#: access/transam/xlog.c:5487 #, c-format msgid "control file contains invalid database cluster state" msgstr "kontrollfil innehåller ogiltigt databasklustertillstånd" -#: access/transam/xlog.c:5500 +#: access/transam/xlog.c:5875 #, c-format msgid "WAL ends before end of online backup" msgstr "WAL slutar före sluttiden av online-backup:en" -#: access/transam/xlog.c:5501 +#: access/transam/xlog.c:5876 #, c-format msgid "All WAL generated while online backup was taken must be available at recovery." msgstr "Alla genererade WAL under tiden online-backup:en togs måste vara tillgängliga vid återställning." -#: access/transam/xlog.c:5504 +#: access/transam/xlog.c:5880 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL avslutas innan konstistent återställningspunkt" -#: access/transam/xlog.c:5550 +#: access/transam/xlog.c:5926 #, c-format msgid "selected new timeline ID: %u" msgstr "valt nytt tidslinje-ID: %u" -#: access/transam/xlog.c:5583 +#: access/transam/xlog.c:5959 #, c-format msgid "archive recovery complete" msgstr "arkivåterställning klar" -#: access/transam/xlog.c:6189 +#: access/transam/xlog.c:6612 #, c-format msgid "shutting down" msgstr "stänger ner" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6228 +#: access/transam/xlog.c:6651 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "restartpoint startar:%s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6240 +#: access/transam/xlog.c:6663 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "checkpoint startar:%s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6305 +#: access/transam/xlog.c:6728 #, c-format msgid "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "restartpoint klar: skrev %d buffers (%.1f%%); %d WAL-fil(er) tillagda, %d borttagna, %d recyclade; skriv=%ld.%03d s, synk=%ld.%03d s, totalt=%ld.%03d s; synk-filer=%d, längsta=%ld.%03d s, genomsnitt=%ld.%03d s; distans=%d kB, estimat=%d kB; lsn=%X/%X, redo-lsn=%X/%X" -#: access/transam/xlog.c:6328 +#: access/transam/xlog.c:6751 #, c-format msgid "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "checkpoint klar: skrev %d buffers (%.1f%%); %d WAL-fil(er) tillagda, %d borttagna, %d recyclade; skriv=%ld.%03d s, synk=%ld.%03d s, totalt=%ld.%03d s; synk-filer=%d, längsta=%ld.%03d s, genomsnitt=%ld.%03d s; distans=%d kB, estimat=%d kB; lsn=%X/%X, redo-lsn=%X/%X" -#: access/transam/xlog.c:6766 +#: access/transam/xlog.c:7233 #, c-format msgid "concurrent write-ahead log activity while database system is shutting down" msgstr "samtidig write-ahead-logg-aktivitet när databassystemet stängs ner" -#: access/transam/xlog.c:7327 +#: access/transam/xlog.c:7818 #, c-format msgid "recovery restart point at %X/%X" msgstr "återställningens omstartspunkt vid %X/%X" -#: access/transam/xlog.c:7329 +#: access/transam/xlog.c:7820 #, c-format msgid "Last completed transaction was at log time %s." msgstr "Senaste kompletta transaktionen var vid loggtid %s" -#: access/transam/xlog.c:7577 +#: access/transam/xlog.c:8082 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "återställningspunkt \"%s\" skapad vid %X/%X" -#: access/transam/xlog.c:7784 +#: access/transam/xlog.c:8289 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "online-backup avbröts, återställning kan inte fortsätta" -#: access/transam/xlog.c:7841 +#: access/transam/xlog.c:8347 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "oväntad tidslinje-ID %u (skall vara %u) i checkpoint-post för nedstängning" -#: access/transam/xlog.c:7899 +#: access/transam/xlog.c:8405 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "oväntad tidslinje-ID %u (skall vara %u) i checkpoint-post för online" -#: access/transam/xlog.c:7928 +#: access/transam/xlog.c:8434 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "oväntad tidslinje-ID %u (skall vara %u) i post för slutet av återställning" -#: access/transam/xlog.c:8195 +#: access/transam/xlog.c:8705 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "kunde inte fsync:a skriv-igenom-loggfil \"%s\": %m" -#: access/transam/xlog.c:8200 +#: access/transam/xlog.c:8710 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "kunde inte fdatasync:a fil \"%s\": %m" -#: access/transam/xlog.c:8285 access/transam/xlog.c:8608 +#: access/transam/xlog.c:8797 access/transam/xlog.c:9133 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "WAL-nivå inte tillräcklig för att kunna skapa en online-backup" -#: access/transam/xlog.c:8286 access/transam/xlog.c:8609 -#: access/transam/xlogfuncs.c:254 +#: access/transam/xlog.c:8798 access/transam/xlogfuncs.c:248 #, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "wal_level måste vara satt till \"replica\" eller \"logical\" vid serverstart." +msgid "\"wal_level\" must be set to \"replica\" or \"logical\" at server start." +msgstr "\"wal_level\" måste vara satt till \"replica\" eller \"logical\" vid serverstart." -#: access/transam/xlog.c:8291 +#: access/transam/xlog.c:8803 #, c-format msgid "backup label too long (max %d bytes)" msgstr "backup-etikett för lång (max %d byte)" -#: access/transam/xlog.c:8412 +#: access/transam/xlog.c:8924 #, c-format -msgid "WAL generated with full_page_writes=off was replayed since last restartpoint" -msgstr "WAL skapad med full_page_writes=off har återspelats sedab senaste omstartpunkten" +msgid "WAL generated with \"full_page_writes=off\" was replayed since last restartpoint" +msgstr "WAL skapad med \"full_page_writes=off\" har återspelats sedan senaste omstartpunkten" -#: access/transam/xlog.c:8414 access/transam/xlog.c:8697 +#: access/transam/xlog.c:8926 access/transam/xlog.c:9222 #, c-format -msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the primary, and then try an online backup again." -msgstr "Det betyder att backup:en som tas på standby:en är trasig och inte skall användas. Slå på full_page_writes och kör CHECKPOINT på primären och försök sedan ta en ny online-backup igen." +msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, and then try an online backup again." +msgstr "Det betyder att backup:en som tas på standby:en är trasig och inte skall användas. Slå på \"full_page_writes\" och kör CHECKPOINT på primären och försök sedan ta en ny online-backup igen." -#: access/transam/xlog.c:8481 backup/basebackup.c:1351 utils/adt/misc.c:354 +#: access/transam/xlog.c:9006 backup/basebackup.c:1417 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "kan inte läsa symbolisk länk \"%s\": %m" -#: access/transam/xlog.c:8488 backup/basebackup.c:1356 utils/adt/misc.c:359 +#: access/transam/xlog.c:9013 backup/basebackup.c:1422 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "mål för symbolisk länk \"%s\" är för lång" -#: access/transam/xlog.c:8647 backup/basebackup.c:1217 +#: access/transam/xlog.c:9134 +#, c-format +msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgstr "wal_level måste vara satt till \"replica\" eller \"logical\" vid serverstart." + +#: access/transam/xlog.c:9172 backup/basebackup.c:1281 #, c-format msgid "the standby was promoted during online backup" msgstr "standby:en befordrades under online-backup" -#: access/transam/xlog.c:8648 backup/basebackup.c:1218 +#: access/transam/xlog.c:9173 backup/basebackup.c:1282 #, c-format msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup." msgstr "Det betyder att backupen som tas är trasig och inte skall användas. Försök ta en ny online-backup." -#: access/transam/xlog.c:8695 +#: access/transam/xlog.c:9220 #, c-format -msgid "WAL generated with full_page_writes=off was replayed during online backup" -msgstr "WAL skapad med full_page_writes=off återspelades under online-backup" +msgid "WAL generated with \"full_page_writes=off\" was replayed during online backup" +msgstr "WAL skapad med \"full_page_writes=off\" återspelades under online-backup" -#: access/transam/xlog.c:8811 +#: access/transam/xlog.c:9336 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "base_backup klar, väntar på att de WAL-segment som krävs blir arkiverade" -#: access/transam/xlog.c:8825 +#: access/transam/xlog.c:9350 #, c-format msgid "still waiting for all required WAL segments to be archived (%d seconds elapsed)" msgstr "väntar fortfarande på att alla krävda WAL-segments skall bli arkiverade (%d sekunder har gått)" -#: access/transam/xlog.c:8827 +#: access/transam/xlog.c:9352 #, c-format -msgid "Check that your archive_command is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." -msgstr "Kontrollera att ditt archive_command kör som det skall. Du kan avbryta denna backup på ett säkert sätt men databasbackup:en kommer inte vara användbart utan att alla WAL-segment finns." +msgid "Check that your \"archive_command\" is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." +msgstr "Kontrollera att ditt \"archive_command\" kör som det skall. Du kan avbryta denna backup på ett säkert sätt men databasbackup:en kommer inte vara användbar utan att alla WAL-segment finns." -#: access/transam/xlog.c:8834 +#: access/transam/xlog.c:9359 #, c-format msgid "all required WAL segments have been archived" msgstr "alla krävda WAL-segments har arkiverats" -#: access/transam/xlog.c:8838 +#: access/transam/xlog.c:9363 #, c-format msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup" msgstr "WAL-arkivering är inte påslagen; du måste se till att alla krävda WAL-segment har kopierats på annat sätt för att backup:en skall vara komplett" -#: access/transam/xlog.c:8877 +#: access/transam/xlog.c:9402 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "avbryter backup på grund av att backend:en stoppades innan pg_backup_stop anropades" -#: access/transam/xlogarchive.c:207 +#: access/transam/xlogarchive.c:213 #, c-format msgid "archive file \"%s\" has wrong size: %lld instead of %lld" msgstr "arkivfil \"%s\" har fel storlek: %lld istället för %lld" -#: access/transam/xlogarchive.c:216 +#: access/transam/xlogarchive.c:222 #, c-format msgid "restored log file \"%s\" from archive" msgstr "återställd logfil \"%s\" från arkiv" -#: access/transam/xlogarchive.c:230 +#: access/transam/xlogarchive.c:236 #, c-format -msgid "restore_command returned a zero exit status, but stat() failed." -msgstr "restore_command returnerade exit-kod noll men stat() misslyckades." +msgid "\"restore_command\" returned a zero exit status, but stat() failed." +msgstr "\"restore_command\" returnerade exit-kod noll men stat() misslyckades." -#: access/transam/xlogarchive.c:262 +#: access/transam/xlogarchive.c:268 #, c-format msgid "could not restore file \"%s\" from archive: %s" msgstr "kunde inte återställa fil \"%s\" från arkiv: %s" @@ -2713,926 +2947,961 @@ msgstr "kunde inte återställa fil \"%s\" från arkiv: %s" #. translator: First %s represents a postgresql.conf parameter name like #. "recovery_end_command", the 2nd is the value of that parameter, the #. third an already translated error message. -#: access/transam/xlogarchive.c:340 +#: access/transam/xlogarchive.c:346 #, c-format msgid "%s \"%s\": %s" msgstr "%s \"%s\": %s" -#: access/transam/xlogarchive.c:450 access/transam/xlogarchive.c:530 +#: access/transam/xlogarchive.c:456 access/transam/xlogarchive.c:536 #, c-format msgid "could not create archive status file \"%s\": %m" msgstr "kunde inte skapa arkiveringsstatusfil \"%s\": %m" -#: access/transam/xlogarchive.c:458 access/transam/xlogarchive.c:538 +#: access/transam/xlogarchive.c:464 access/transam/xlogarchive.c:544 #, c-format msgid "could not write archive status file \"%s\": %m" msgstr "kunde inte skriva arkiveringsstatusfil \"%s\": %m" -#: access/transam/xlogfuncs.c:75 backup/basebackup.c:973 +#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 #, c-format msgid "a backup is already in progress in this session" msgstr "en backup är redan på gång i denna session" -#: access/transam/xlogfuncs.c:146 +#: access/transam/xlogfuncs.c:140 #, c-format msgid "backup is not in progress" msgstr "ingen backup är på gång" -#: access/transam/xlogfuncs.c:147 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "Did you call pg_backup_start()?" msgstr "Anropade du pg_backup_start()?" -#: access/transam/xlogfuncs.c:190 access/transam/xlogfuncs.c:248 -#: access/transam/xlogfuncs.c:287 access/transam/xlogfuncs.c:308 -#: access/transam/xlogfuncs.c:329 +#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 +#: access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 +#: access/transam/xlogfuncs.c:323 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "WAL-kontrollfunktioner kan inte köras under återställning." -#: access/transam/xlogfuncs.c:215 access/transam/xlogfuncs.c:399 -#: access/transam/xlogfuncs.c:457 +#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 +#: access/transam/xlogfuncs.c:447 #, c-format msgid "%s cannot be executed during recovery." msgstr "%s kan inte köras under återställning" -#: access/transam/xlogfuncs.c:221 +#: access/transam/xlogfuncs.c:215 #, c-format -msgid "pg_log_standby_snapshot() can only be used if wal_level >= replica" -msgstr "pg_log_standby_snapshot() kan bara användas om wal_level >= replica" +msgid "pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" +msgstr "pg_log_standby_snapshot() kan bara användas om \"wal_level\" >= \"replica\"" -#: access/transam/xlogfuncs.c:253 +#: access/transam/xlogfuncs.c:247 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "WAL-nivån är inte tillräcklig för att skapa en återställningspunkt" -#: access/transam/xlogfuncs.c:261 +#: access/transam/xlogfuncs.c:255 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "värdet för långt för en återställningspunkt (maximalt %d tecken)" -#: access/transam/xlogfuncs.c:496 +#: access/transam/xlogfuncs.c:486 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "ogiltigt WAL-filnamn \"%s\"" -#: access/transam/xlogfuncs.c:532 access/transam/xlogfuncs.c:562 -#: access/transam/xlogfuncs.c:586 access/transam/xlogfuncs.c:609 -#: access/transam/xlogfuncs.c:689 +#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 +#: access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 +#: access/transam/xlogfuncs.c:679 #, c-format msgid "recovery is not in progress" msgstr "återställning är inte i gång" -#: access/transam/xlogfuncs.c:533 access/transam/xlogfuncs.c:563 -#: access/transam/xlogfuncs.c:587 access/transam/xlogfuncs.c:610 -#: access/transam/xlogfuncs.c:690 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 +#: access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 +#: access/transam/xlogfuncs.c:680 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "Återställningskontrollfunktioner kan bara köras under återställning." -#: access/transam/xlogfuncs.c:538 access/transam/xlogfuncs.c:568 +#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 #, c-format msgid "standby promotion is ongoing" -msgstr "standby-befordring pågår" +msgstr "standby-befordran pågår" -#: access/transam/xlogfuncs.c:539 access/transam/xlogfuncs.c:569 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%s kan inte köras efter att befordran startats." -#: access/transam/xlogfuncs.c:695 +#: access/transam/xlogfuncs.c:685 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "\"wait_seconds\" får inte vara negativ eller noll" -#: access/transam/xlogfuncs.c:715 storage/ipc/signalfuncs.c:260 +#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "misslyckades med att sända en signal till postmaster: %m" -#: access/transam/xlogfuncs.c:751 +#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#, c-format +msgid "terminating connection due to unexpected postmaster exit" +msgstr "avslutar anslutning på grund av att postmaster stängde oväntat ner" + +#: access/transam/xlogfuncs.c:740 +#, c-format +msgid "while waiting on promotion" +msgstr "vid väntan på befordran" + +#: access/transam/xlogfuncs.c:744 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" msgstr[0] "servern befordrades inte inom %d sekund" msgstr[1] "servern befordrades inte inom %d sekunder" -#: access/transam/xlogprefetcher.c:1092 +#: access/transam/xlogprefetcher.c:1088 #, c-format -msgid "recovery_prefetch is not supported on platforms that lack posix_fadvise()." -msgstr "recovery_prefetch stöds inte på plattformar som saknar posix_fadvise()." +msgid "\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()." +msgstr "\"recovery_prefetch\" stöds inte på plattformar som saknar posix_fadvise()." -#: access/transam/xlogreader.c:610 +#: access/transam/xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" -#: access/transam/xlogreader.c:619 +#: access/transam/xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord är begärd vid %X/%X" -#: access/transam/xlogreader.c:740 +#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 +#, c-format +msgid "invalid record length at %X/%X: expected at least %u, got %u" +msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" + +#: access/transam/xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "det finns ingen contrecord-flagga vid %X/%X" -#: access/transam/xlogreader.c:753 +#: access/transam/xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "ogiltig contrecord-längd %u (förväntade %lld) vid %X/%X" -#: access/transam/xlogreader.c:812 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "postlängd %u vid %X/%X är för lång" - -#: access/transam/xlogreader.c:878 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "slut på minne vid avkodning av post med längden %u" - -#: access/transam/xlogreader.c:1130 -#, c-format -msgid "invalid record length at %X/%X: expected at least %u, got %u" -msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" - -#: access/transam/xlogreader.c:1138 +#: access/transam/xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ogiltigt resurshanterar-ID %u vid %X/%X" -#: access/transam/xlogreader.c:1151 access/transam/xlogreader.c:1167 +#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "post med inkorrekt prev-link %X/%X vid %X/%X" -#: access/transam/xlogreader.c:1203 +#: access/transam/xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "felaktig resurshanterardatakontrollsumma i post vid %X/%X" -#: access/transam/xlogreader.c:1237 +#: access/transam/xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "felaktigt magiskt nummer %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1252 access/transam/xlogreader.c:1294 +#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ogiltiga infobitar %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1268 +#: access/transam/xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL-fil är från ett annat databassystem: WAL-filens databassystemidentifierare är %llu, pg_control databassystemidentifierare är %llu" -#: access/transam/xlogreader.c:1276 +#: access/transam/xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt segmentstorlek i sidhuvud" -#: access/transam/xlogreader.c:1282 +#: access/transam/xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt XLOG_BLCKSZ i sidhuvud" -#: access/transam/xlogreader.c:1314 +#: access/transam/xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "oväntad sidadress %X/%X i WAL-segment %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1340 +#: access/transam/xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "ej-i-sekvens för tidslinje-ID %u (efter %u) i WAL-segment %s, LSN %X/%X, offset %u" -#: access/transam/xlogreader.c:1746 +#: access/transam/xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "\"ej i sekvens\"-block_id %u vid %X/%X" -#: access/transam/xlogreader.c:1770 +#: access/transam/xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA är satt men ingen data inkluderad vid %X/%X" -#: access/transam/xlogreader.c:1777 +#: access/transam/xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA är ej satt men datalängden är %u vid %X/%X" -#: access/transam/xlogreader.c:1813 +#: access/transam/xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är satt men håloffset %u längd %u blockavbildlängd %u vid %X/%X" -#: access/transam/xlogreader.c:1829 +#: access/transam/xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är inte satt men håloffset %u längd %u vid %X/%X" -#: access/transam/xlogreader.c:1843 +#: access/transam/xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED är satt men blockavbildlängd %u vid %X/%X" -#: access/transam/xlogreader.c:1858 +#: access/transam/xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "varken BKPIMAGE_HAS_HOLE eller BKPIMAGE_COMPRESSED är satt men blockavbildlängd är %u vid %X/%X" -#: access/transam/xlogreader.c:1874 +#: access/transam/xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL är satt men ingen tidigare rel vid %X/%X" -#: access/transam/xlogreader.c:1886 +#: access/transam/xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "ogiltig block_id %u vid %X/%X" -#: access/transam/xlogreader.c:1953 +#: access/transam/xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "post med ogiltig längd vid %X/%X" -#: access/transam/xlogreader.c:1979 +#: access/transam/xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "kunde inte hitta backup-block med ID %d i WAL-post" -#: access/transam/xlogreader.c:2063 +#: access/transam/xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt block %d angivet" -#: access/transam/xlogreader.c:2070 +#: access/transam/xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt state, block %d" -#: access/transam/xlogreader.c:2097 access/transam/xlogreader.c:2114 +#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med %s stöds inte av bygget, block %d" -#: access/transam/xlogreader.c:2123 +#: access/transam/xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med okänd metod, block %d" -#: access/transam/xlogreader.c:2131 +#: access/transam/xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "kunde inte packa upp avbild vid %X/%X, block %d" -#: access/transam/xlogrecovery.c:547 -#, c-format -msgid "entering standby mode" -msgstr "går in i standby-läge" - -#: access/transam/xlogrecovery.c:550 -#, c-format -msgid "starting point-in-time recovery to XID %u" -msgstr "startar point-in-time-återställning till XID %u" - -#: access/transam/xlogrecovery.c:554 -#, c-format -msgid "starting point-in-time recovery to %s" -msgstr "startar point-in-time-återställning till %s" - -#: access/transam/xlogrecovery.c:558 -#, c-format -msgid "starting point-in-time recovery to \"%s\"" -msgstr "startar point-in-time-återställning till \"%s\"" - -#: access/transam/xlogrecovery.c:562 -#, c-format -msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" -msgstr "startar point-in-time-återställning till WAL-position (LSN) \"%X/%X\"" - -#: access/transam/xlogrecovery.c:566 -#, c-format -msgid "starting point-in-time recovery to earliest consistent point" -msgstr "startar point-in-time-återställning till tidigast konsistenta punkt" - -#: access/transam/xlogrecovery.c:569 +#: access/transam/xlogrecovery.c:617 #, c-format -msgid "starting archive recovery" -msgstr "Startar arkivåterställning" +msgid "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u" +msgstr "startar backupåterställning med redo LSN %X/%X, checkpoint LSN %X/%X, på tidslinje ID %u" -#: access/transam/xlogrecovery.c:653 +#: access/transam/xlogrecovery.c:649 #, c-format -msgid "could not find redo location referenced by checkpoint record" -msgstr "kunde inte hitta redo-position refererad av checkpoint-post" +msgid "could not find redo location %X/%X referenced by checkpoint record at %X/%X" +msgstr "kunde inte hitta redo-position %X/%X refererad av checkpoint-post vid %X/%X" -#: access/transam/xlogrecovery.c:654 access/transam/xlogrecovery.c:664 +#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 #, c-format msgid "" -"If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n" +"If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup." msgstr "" -"Om du återställer från en backup, gör touch på \"%s/recovery.signal\" och lägg till\n" +"Om du återställer från en backup, gör touch på \"%s/recovery.signal\" eller \"%s/standby.signal\" och lägg till\n" "önskade återställningsalternativ. Om du inte återställer från en backup, försök ta\n" "bort filen \"%s/backup_label\". Var försiktig: borttagning av \"%s/backup_label\"\n" "kommer resultera i ett trasigt kluster om du återställer från en backup." -#: access/transam/xlogrecovery.c:663 +#: access/transam/xlogrecovery.c:660 #, c-format -msgid "could not locate required checkpoint record" -msgstr "kunde inte hitta den checkpoint-post som krävs" +msgid "could not locate required checkpoint record at %X/%X" +msgstr "kunde inte hitta den checkpoint-post som krävs vid %X/%X" -#: access/transam/xlogrecovery.c:692 commands/tablespace.c:670 +#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "kan inte skapa symbolisk länk \"%s\": %m" -#: access/transam/xlogrecovery.c:724 access/transam/xlogrecovery.c:730 +#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "hoppar över fil \"%s\" då ingen fil \"%s\" finns" -#: access/transam/xlogrecovery.c:726 +#: access/transam/xlogrecovery.c:725 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "Filen \"%s\" döptes om till \"%s\"." -#: access/transam/xlogrecovery.c:732 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "Kunde inte döpa om fil \"%s\" till \"%s\": %m" -#: access/transam/xlogrecovery.c:786 +#: access/transam/xlogrecovery.c:770 +#, c-format +msgid "restarting backup recovery with redo LSN %X/%X" +msgstr "startar om backupåterställning med redo LSN %X/%X" + +#: access/transam/xlogrecovery.c:795 +#, c-format +msgid "could not locate a valid checkpoint record at %X/%X" +msgstr "kunde inte hitta en giltig checkpoint-post vid %X/%X" + +#: access/transam/xlogrecovery.c:806 +#, c-format +msgid "entering standby mode" +msgstr "går in i standby-läge" + +#: access/transam/xlogrecovery.c:809 +#, c-format +msgid "starting point-in-time recovery to XID %u" +msgstr "startar point-in-time-återställning till XID %u" + +#: access/transam/xlogrecovery.c:813 +#, c-format +msgid "starting point-in-time recovery to %s" +msgstr "startar point-in-time-återställning till %s" + +#: access/transam/xlogrecovery.c:817 +#, c-format +msgid "starting point-in-time recovery to \"%s\"" +msgstr "startar point-in-time-återställning till \"%s\"" + +#: access/transam/xlogrecovery.c:821 +#, c-format +msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" +msgstr "startar point-in-time-återställning till WAL-position (LSN) \"%X/%X\"" + +#: access/transam/xlogrecovery.c:825 +#, c-format +msgid "starting point-in-time recovery to earliest consistent point" +msgstr "startar point-in-time-återställning till tidigast konsistenta punkt" + +#: access/transam/xlogrecovery.c:828 #, c-format -msgid "could not locate a valid checkpoint record" -msgstr "kunde inte hitta en giltig checkpoint-post" +msgid "starting archive recovery" +msgstr "Startar arkivåterställning" -#: access/transam/xlogrecovery.c:810 +#: access/transam/xlogrecovery.c:849 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "efterfrågad tidslinje %u är inte ett barn till denna servers historik" -#: access/transam/xlogrecovery.c:812 +#: access/transam/xlogrecovery.c:851 #, c-format msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." msgstr "Senaste checkpoint är vid %X/%X på tidslinje %u, men i historiken för efterfrågad tidslinje så avvek servern från den tidslinjen vid %X/%X." -#: access/transam/xlogrecovery.c:826 +#: access/transam/xlogrecovery.c:865 #, c-format msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u" msgstr "efterfågan tidslinje %u innehåller inte minimal återställningspunkt %X/%X på tidslinje %u" -#: access/transam/xlogrecovery.c:854 +#: access/transam/xlogrecovery.c:893 #, c-format msgid "invalid next transaction ID" msgstr "nästa transaktions-ID ogiltig" -#: access/transam/xlogrecovery.c:859 +#: access/transam/xlogrecovery.c:898 #, c-format msgid "invalid redo in checkpoint record" msgstr "ogiltig redo i checkpoint-post" -#: access/transam/xlogrecovery.c:870 +#: access/transam/xlogrecovery.c:909 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "ogiltig redo-post i nedstängnings-checkpoint" -#: access/transam/xlogrecovery.c:899 +#: access/transam/xlogrecovery.c:938 #, c-format msgid "database system was not properly shut down; automatic recovery in progress" msgstr "databassystemet stängdes inte ned korrekt; automatisk återställning pågår" -#: access/transam/xlogrecovery.c:903 +#: access/transam/xlogrecovery.c:942 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "krashåterställning startar i tidslinje %u och har måltidslinje %u" -#: access/transam/xlogrecovery.c:946 +#: access/transam/xlogrecovery.c:985 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label innehåller data som inte stämmer med kontrollfil" -#: access/transam/xlogrecovery.c:947 +#: access/transam/xlogrecovery.c:986 #, c-format msgid "This means that the backup is corrupted and you will have to use another backup for recovery." msgstr "Det betyder att backup:en är trasig och du behöver använda en annan backup för att återställa." -#: access/transam/xlogrecovery.c:1001 +#: access/transam/xlogrecovery.c:1040 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "använda återställningskommandofil \"%s\" stöds inte" -#: access/transam/xlogrecovery.c:1066 +#: access/transam/xlogrecovery.c:1105 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "standby-läge stöd inte av enanvändarservrar" -#: access/transam/xlogrecovery.c:1083 +#: access/transam/xlogrecovery.c:1122 #, c-format -msgid "specified neither primary_conninfo nor restore_command" -msgstr "angav varken primary_conninfo eller restore_command" +msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" +msgstr "angav varken \"primary_conninfo\" eller \"restore_command\"" -#: access/transam/xlogrecovery.c:1084 +#: access/transam/xlogrecovery.c:1123 #, c-format msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there." msgstr "Databasservern kommer med jämna mellanrum att poll:a pg_wal-underkatalogen för att se om filer placerats där." -#: access/transam/xlogrecovery.c:1092 +#: access/transam/xlogrecovery.c:1131 #, c-format -msgid "must specify restore_command when standby mode is not enabled" -msgstr "måste ange restore_command när standby-läge inte är påslaget" +msgid "must specify \"restore_command\" when standby mode is not enabled" +msgstr "måste ange \"restore_command\" när standby-läge inte är påslaget" -#: access/transam/xlogrecovery.c:1130 +#: access/transam/xlogrecovery.c:1169 #, c-format msgid "recovery target timeline %u does not exist" msgstr "återställningsmåltidslinje %u finns inte" -#: access/transam/xlogrecovery.c:1213 access/transam/xlogrecovery.c:1220 -#: access/transam/xlogrecovery.c:1279 access/transam/xlogrecovery.c:1359 -#: access/transam/xlogrecovery.c:1383 +#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 +#: access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 +#: access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 #, c-format msgid "invalid data in file \"%s\"" msgstr "felaktig data i fil \"%s\"" -#: access/transam/xlogrecovery.c:1280 +#: access/transam/xlogrecovery.c:1319 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "Parsad tidslinje-ID är %u men förväntade sig %u." -#: access/transam/xlogrecovery.c:1662 +#: access/transam/xlogrecovery.c:1330 +#, c-format +msgid "this is an incremental backup, not a data directory" +msgstr "detta är en inkrementell backup, inte en datakatalog" + +#: access/transam/xlogrecovery.c:1331 +#, c-format +msgid "Use pg_combinebackup to reconstruct a valid data directory." +msgstr "Använd pg_combinebackup för att återskapa en giltig datakatalog." + +#: access/transam/xlogrecovery.c:1717 +#, c-format +msgid "unexpected record type found at redo point %X/%X" +msgstr "oväntad typ på post hittad vid redo-punkt %X/%X" + +#: access/transam/xlogrecovery.c:1740 #, c-format msgid "redo starts at %X/%X" msgstr "redo startar vid %X/%X" -#: access/transam/xlogrecovery.c:1675 +#: access/transam/xlogrecovery.c:1753 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "redo pågår, förbrukad tid: %ld.%02d s, nuvarande LSN: %X/%X" -#: access/transam/xlogrecovery.c:1767 +#: access/transam/xlogrecovery.c:1843 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "efterfrågad återställningsstoppunkt är före en konsistent återställningspunkt" -#: access/transam/xlogrecovery.c:1799 +#: access/transam/xlogrecovery.c:1875 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "redo gjord vid %X/%X systemanvändning: %s" -#: access/transam/xlogrecovery.c:1805 +#: access/transam/xlogrecovery.c:1881 #, c-format msgid "last completed transaction was at log time %s" msgstr "senaste kompletta transaktionen var vid loggtid %s" -#: access/transam/xlogrecovery.c:1814 +#: access/transam/xlogrecovery.c:1890 #, c-format msgid "redo is not required" msgstr "redo behövs inte" -#: access/transam/xlogrecovery.c:1825 +#: access/transam/xlogrecovery.c:1901 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "återställning avslutades innan det konfigurerade återställningsmålet nåddes" -#: access/transam/xlogrecovery.c:2019 +#: access/transam/xlogrecovery.c:2095 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "lyckades hoppa över saknad contrecord vid %X/%X, överskriven vid %s" -#: access/transam/xlogrecovery.c:2086 +#: access/transam/xlogrecovery.c:2162 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "Oväntat katalogpost \"%s\" hittades i %s" -#: access/transam/xlogrecovery.c:2088 +#: access/transam/xlogrecovery.c:2164 #, c-format msgid "All directory entries in pg_tblspc/ should be symbolic links." msgstr "Alla katalogposter i pg_tblspc/ skall vara symboliska länkar" -#: access/transam/xlogrecovery.c:2089 +#: access/transam/xlogrecovery.c:2165 +#, c-format +msgid "Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete." +msgstr "Ta bort dessa kataloger eller sätt \"allow_in_place_tablespaces\" temporärt till ON och låt återställningen gå klart." + +#: access/transam/xlogrecovery.c:2217 #, c-format -msgid "Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete." -msgstr "Ta bort dessa kataloger eller sätt allow_in_place_tablespaces temporärt till ON och låt återställningen gå klart." +msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" +msgstr "slutförde backupåterställning vid redo-LSN %X/%X och slut-LSN %X/%X" -#: access/transam/xlogrecovery.c:2163 +#: access/transam/xlogrecovery.c:2247 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "konsistent återställningstillstånd uppnått vid %X/%X" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2201 +#: access/transam/xlogrecovery.c:2285 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "WAL-redo vid %X/%X för %s" -#: access/transam/xlogrecovery.c:2299 +#: access/transam/xlogrecovery.c:2383 #, c-format msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record" msgstr "oväntad föregående tidslinje-ID %u (nuvarande tidslinje-ID %u) i checkpoint-post" -#: access/transam/xlogrecovery.c:2308 +#: access/transam/xlogrecovery.c:2392 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "oväntad tidslinje-ID %u (efter %u) i checkpoint-post" -#: access/transam/xlogrecovery.c:2324 +#: access/transam/xlogrecovery.c:2408 #, c-format msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u" msgstr "oväntad tidslinje-ID %u i checkpoint-post, innan vi nått minimal återställningspunkt %X/%X på tidslinje %u" -#: access/transam/xlogrecovery.c:2508 access/transam/xlogrecovery.c:2784 +#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 #, c-format msgid "recovery stopping after reaching consistency" msgstr "återställning stoppad efter att ha uppnått konsistens" -#: access/transam/xlogrecovery.c:2529 +#: access/transam/xlogrecovery.c:2613 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "återställning stoppad före WAL-position (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2619 +#: access/transam/xlogrecovery.c:2703 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "återställning stoppad före commit av transaktion %u, tid %s" -#: access/transam/xlogrecovery.c:2626 +#: access/transam/xlogrecovery.c:2710 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "återställning stoppad före abort av transaktion %u, tid %s" -#: access/transam/xlogrecovery.c:2679 +#: access/transam/xlogrecovery.c:2763 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "återställning stoppad vid återställningspunkt \"%s\", tid %s" -#: access/transam/xlogrecovery.c:2697 +#: access/transam/xlogrecovery.c:2781 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "återställning stoppad efter WAL-position (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2764 +#: access/transam/xlogrecovery.c:2848 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "återställning stoppad efter commit av transaktion %u, tid %s" -#: access/transam/xlogrecovery.c:2772 +#: access/transam/xlogrecovery.c:2856 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "återställning stoppad efter abort av transaktion %u, tid %s" -#: access/transam/xlogrecovery.c:2853 +#: access/transam/xlogrecovery.c:2937 #, c-format msgid "pausing at the end of recovery" msgstr "pausar vid slutet av återställning" -#: access/transam/xlogrecovery.c:2854 +#: access/transam/xlogrecovery.c:2938 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "Kör pg_wal_replay_resume() för att befordra." -#: access/transam/xlogrecovery.c:2857 access/transam/xlogrecovery.c:4594 +#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4679 #, c-format msgid "recovery has paused" msgstr "återställning har pausats" -#: access/transam/xlogrecovery.c:2858 +#: access/transam/xlogrecovery.c:2942 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "Kör pg_wal_replay_resume() för att fortsätta." -#: access/transam/xlogrecovery.c:3121 +#: access/transam/xlogrecovery.c:3205 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "oväntad tidslinje-ID %u i WAL-segment %s, LSN %X/%X, offset %u" -#: access/transam/xlogrecovery.c:3329 +#: access/transam/xlogrecovery.c:3413 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "kunde inte läsa från WAL-segment %s, LSN %X/%X, offset %u: %m" -#: access/transam/xlogrecovery.c:3336 +#: access/transam/xlogrecovery.c:3420 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" msgstr "kunde inte läsa från WAL-segment %s, LSN %X/%X, offset %u, läste %d av %zu" -#: access/transam/xlogrecovery.c:3976 +#: access/transam/xlogrecovery.c:4061 #, c-format msgid "invalid checkpoint location" msgstr "ogiltig checkpoint-position" -#: access/transam/xlogrecovery.c:3986 +#: access/transam/xlogrecovery.c:4071 #, c-format msgid "invalid checkpoint record" msgstr "ogiltig checkpoint-post" -#: access/transam/xlogrecovery.c:3992 +#: access/transam/xlogrecovery.c:4077 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "ogiltig resurshanterar-ID i checkpoint-post" -#: access/transam/xlogrecovery.c:4000 +#: access/transam/xlogrecovery.c:4085 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "ogiltig xl_info i checkpoint-post" -#: access/transam/xlogrecovery.c:4006 +#: access/transam/xlogrecovery.c:4091 #, c-format msgid "invalid length of checkpoint record" msgstr "ogiltig längd på checkpoint-post" -#: access/transam/xlogrecovery.c:4060 +#: access/transam/xlogrecovery.c:4145 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "ny tidslinje %u är inte ett barn till databasens systemtidslinje %u" -#: access/transam/xlogrecovery.c:4074 +#: access/transam/xlogrecovery.c:4159 #, c-format msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X" msgstr "ny tidslinje %u skapad från aktuella databasens systemtidslinje %u innan nuvarande återställningspunkt %X/%X" -#: access/transam/xlogrecovery.c:4093 +#: access/transam/xlogrecovery.c:4178 #, c-format msgid "new target timeline is %u" msgstr "ny måltidslinje är %u" -#: access/transam/xlogrecovery.c:4296 +#: access/transam/xlogrecovery.c:4381 #, c-format msgid "WAL receiver process shutdown requested" msgstr "nedstängning av WAL-mottagarprocess efterfrågad" -#: access/transam/xlogrecovery.c:4356 +#: access/transam/xlogrecovery.c:4441 #, c-format msgid "received promote request" -msgstr "tog emot förfrågan om befordring" +msgstr "tog emot förfrågan om befordran" -#: access/transam/xlogrecovery.c:4585 +#: access/transam/xlogrecovery.c:4670 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "hot standby är inte möjligt på grund av otillräckliga parameterinställningar" -#: access/transam/xlogrecovery.c:4586 access/transam/xlogrecovery.c:4613 -#: access/transam/xlogrecovery.c:4643 +#: access/transam/xlogrecovery.c:4671 access/transam/xlogrecovery.c:4698 +#: access/transam/xlogrecovery.c:4728 #, c-format msgid "%s = %d is a lower setting than on the primary server, where its value was %d." msgstr "%s = %d har ett lägre värde än på primärservern där värdet var %d." -#: access/transam/xlogrecovery.c:4595 +#: access/transam/xlogrecovery.c:4680 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "Om återställning avpausas så kommer servern stänga ner." -#: access/transam/xlogrecovery.c:4596 +#: access/transam/xlogrecovery.c:4681 #, c-format msgid "You can then restart the server after making the necessary configuration changes." msgstr "Du kan då återstarta servern efter att ha gjort de nödvändiga konfigurationsändringarna." -#: access/transam/xlogrecovery.c:4607 +#: access/transam/xlogrecovery.c:4692 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "befordran är inte möjligt på grund av otillräckliga parameterinställningar" -#: access/transam/xlogrecovery.c:4617 +#: access/transam/xlogrecovery.c:4702 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "Starta om servern efter att ha gjort de nödvändiga konfigurationsändringarna." -#: access/transam/xlogrecovery.c:4641 +#: access/transam/xlogrecovery.c:4726 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "återställning avbruten på grund av otillräckliga parametervärden" -#: access/transam/xlogrecovery.c:4647 +#: access/transam/xlogrecovery.c:4732 #, c-format msgid "You can restart the server after making the necessary configuration changes." msgstr "Du kan starta om servern efter att du gjort de nödvändiga konfigurationsändringarna." -#: access/transam/xlogrecovery.c:4689 +#: access/transam/xlogrecovery.c:4774 #, c-format msgid "multiple recovery targets specified" msgstr "multipla återställningsmål angivna" -#: access/transam/xlogrecovery.c:4690 +#: access/transam/xlogrecovery.c:4775 #, c-format -msgid "At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set." -msgstr "Som mest en av recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time och recovery_target_xid kan sättas." +msgid "At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set." +msgstr "Som mest en av \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\" och \"recovery_target_xid\" kan sättas." -#: access/transam/xlogrecovery.c:4701 +#: access/transam/xlogrecovery.c:4786 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "Det enda tillåtna värdet är \"immediate\"." -#: access/transam/xlogrecovery.c:4853 utils/adt/timestamp.c:186 -#: utils/adt/timestamp.c:439 +#: access/transam/xlogrecovery.c:4938 utils/adt/timestamp.c:202 +#: utils/adt/timestamp.c:455 #, c-format msgid "timestamp out of range: \"%s\"" msgstr "timestamp utanför giltigt intervall: \"%s\"" -#: access/transam/xlogrecovery.c:4898 +#: access/transam/xlogrecovery.c:4983 #, c-format -msgid "recovery_target_timeline is not a valid number." -msgstr "recovery_target_timeline är inte ett giltigt nummer." +msgid "\"recovery_target_timeline\" is not a valid number." +msgstr "\"recovery_target_timeline\" är inte ett giltigt nummer." -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1032 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "kunde inte läsa från WAL-segment %s, offset %d: %m" -#: access/transam/xlogutils.c:1046 +#: access/transam/xlogutils.c:1039 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "kunde inte läsa från WAL-segment %s, offset %d, läste %d av %d" -#: archive/shell_archive.c:96 +#: archive/shell_archive.c:98 #, c-format msgid "archive command failed with exit code %d" msgstr "arkiveringskommando misslyckades med felkod %d" -#: archive/shell_archive.c:98 archive/shell_archive.c:108 -#: archive/shell_archive.c:114 archive/shell_archive.c:123 +#: archive/shell_archive.c:100 archive/shell_archive.c:110 +#: archive/shell_archive.c:116 archive/shell_archive.c:125 #, c-format msgid "The failed archive command was: %s" msgstr "Det misslyckade arkiveringskommandot var: %s" -#: archive/shell_archive.c:105 +#: archive/shell_archive.c:107 #, c-format msgid "archive command was terminated by exception 0x%X" msgstr "arkiveringskommandot terminerades med avbrott 0x%X" -#: archive/shell_archive.c:107 postmaster/postmaster.c:3678 +#: archive/shell_archive.c:109 postmaster/postmaster.c:3095 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "Se C-include-fil \"ntstatus.h\" för en beskrivning av det hexdecimala värdet." -#: archive/shell_archive.c:112 +#: archive/shell_archive.c:114 #, c-format msgid "archive command was terminated by signal %d: %s" msgstr "arkiveringskommandot terminerades av signal %d: %s" -#: archive/shell_archive.c:121 +#: archive/shell_archive.c:123 #, c-format msgid "archive command exited with unrecognized status %d" msgstr "arkiveringskommandot avslutade med okänd statuskod %d" -#: backup/backup_manifest.c:253 +#: backup/backup_manifest.c:254 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "förväntade sluttidslinje %u men hittade tidslinje %u" -#: backup/backup_manifest.c:277 +#: backup/backup_manifest.c:278 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "förväntade starttidslinje %u men hittade tidslinje %u" -#: backup/backup_manifest.c:304 +#: backup/backup_manifest.c:305 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "starttidslinje %u hittades inte i historiken för tidslinje %u" -#: backup/backup_manifest.c:355 +#: backup/backup_manifest.c:356 #, c-format msgid "could not rewind temporary file" msgstr "kunde inte spola tillbaka temporär fil" -#: backup/basebackup.c:470 +#: backup/basebackup.c:479 #, c-format msgid "could not find any WAL files" msgstr "kunde inte hitta några WAL-filer" -#: backup/basebackup.c:485 backup/basebackup.c:500 backup/basebackup.c:509 +#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 #, c-format msgid "could not find WAL file \"%s\"" msgstr "kunde inte hitta WAL-fil \"%s\"" -#: backup/basebackup.c:551 backup/basebackup.c:576 +#: backup/basebackup.c:560 backup/basebackup.c:585 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "oväntad WAL-filstorlek \"%s\"" -#: backup/basebackup.c:646 +#: backup/basebackup.c:656 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" msgstr[0] "totalt %lld verifieringsfel av checksumma" msgstr[1] "totalt %lld verifieringsfel av checksumma" -#: backup/basebackup.c:653 +#: backup/basebackup.c:663 #, c-format msgid "checksum verification failure during base backup" msgstr "misslyckad verifiering av checksumma under basbackup" -#: backup/basebackup.c:722 backup/basebackup.c:731 backup/basebackup.c:742 -#: backup/basebackup.c:759 backup/basebackup.c:768 backup/basebackup.c:779 -#: backup/basebackup.c:796 backup/basebackup.c:805 backup/basebackup.c:817 -#: backup/basebackup.c:841 backup/basebackup.c:855 backup/basebackup.c:866 -#: backup/basebackup.c:877 backup/basebackup.c:890 +#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 +#: backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 +#: backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 +#: backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 +#: backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 #, c-format msgid "duplicate option \"%s\"" msgstr "duplicerad flagga \"%s\"" -#: backup/basebackup.c:750 +#: backup/basebackup.c:761 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "okänd checkpoint-typ: \"%s\"" -#: backup/basebackup.c:785 +#: backup/basebackup.c:793 +#, c-format +msgid "incremental backups cannot be taken unless WAL summarization is enabled" +msgstr "inkrementella backup:er kan inte tas om inte WAL-summering är påslagen" + +#: backup/basebackup.c:809 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%d är utanför giltigt intervall för parameter \"%s\" (%d .. %d)" -#: backup/basebackup.c:830 +#: backup/basebackup.c:854 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "okänd manifestflagga: \"%s\"" -#: backup/basebackup.c:846 -#, c-format -msgid "unrecognized checksum algorithm: \"%s\"" -msgstr "okänd algoritm för kontrollsumma: \"%s\"" - -#: backup/basebackup.c:881 +#: backup/basebackup.c:905 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "okänd komprimeringsalgoritm: \"%s\"" -#: backup/basebackup.c:897 +#: backup/basebackup.c:921 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "okänd basbackupflagga: \"%s\"" -#: backup/basebackup.c:908 +#: backup/basebackup.c:932 #, c-format msgid "manifest checksums require a backup manifest" msgstr "manifestchecksummor kräver ett backup-manifest" -#: backup/basebackup.c:917 +#: backup/basebackup.c:941 #, c-format msgid "target detail cannot be used without target" msgstr "målinställningar kan inte användas utan ett mål" -#: backup/basebackup.c:926 backup/basebackup_target.c:218 +#: backup/basebackup.c:950 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "målet \"%s\" stöder inte målinställningar" -#: backup/basebackup.c:937 +#: backup/basebackup.c:961 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "komprimeringsinställning kan inte anges om komprimering inte är påslagen" -#: backup/basebackup.c:950 +#: backup/basebackup.c:974 #, c-format msgid "invalid compression specification: %s" msgstr "ogiltig inställning för komprimering: %s" -#: backup/basebackup.c:1116 backup/basebackup.c:1294 +#: backup/basebackup.c:1024 +#, c-format +msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" +msgstr "måste UPLOAD_MANIFEST innan befordran av en inkrementell BASE_BACKUP" + +#: backup/basebackup.c:1157 backup/basebackup.c:1358 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "kunde inte ta status på fil eller katalog \"%s\": %m" -#: backup/basebackup.c:1430 +#: backup/basebackup.c:1544 #, c-format msgid "skipping special file \"%s\"" msgstr "hoppar över specialfil \"%s\"" -#: backup/basebackup.c:1542 -#, c-format -msgid "invalid segment number %d in file \"%s\"" -msgstr "ogiltigt segmentnummer %d i fil \"%s\"" - -#: backup/basebackup.c:1574 +#: backup/basebackup.c:1751 #, c-format msgid "could not verify checksum in file \"%s\", block %u: read buffer size %d and page size %d differ" msgstr "kunde inte verifiera checksumma i fil \"%s\", block %u: läsbufferstorlek %d och sidstorlek %d skiljer sig åt" -#: backup/basebackup.c:1658 +#: backup/basebackup.c:1813 +#, c-format +msgid "file \"%s\" has a total of %d checksum verification failure" +msgid_plural "file \"%s\" has a total of %d checksum verification failures" +msgstr[0] "filen \"%s\" har totalt %d kontrollerad felaktiga checksumma" +msgstr[1] "filen \"%s\" har totalt %d kontrollerade felaktiga checksummor" + +#: backup/basebackup.c:1917 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" msgstr "checksumkontroll misslyckades i fil \"%s\", block %u: beräknade %X men förväntade %X" -#: backup/basebackup.c:1665 +#: backup/basebackup.c:1924 #, c-format msgid "further checksum verification failures in file \"%s\" will not be reported" msgstr "ytterligare kontroller av checksummor i fil \"%s\" kommer inte rapporteras" -#: backup/basebackup.c:1721 -#, c-format -msgid "file \"%s\" has a total of %d checksum verification failure" -msgid_plural "file \"%s\" has a total of %d checksum verification failures" -msgstr[0] "filen \"%s\" har totalt %d kontrollerad felaktiga checksumma" -msgstr[1] "filen \"%s\" har totalt %d kontrollerade felaktiga checksummor" - -#: backup/basebackup.c:1767 +#: backup/basebackup.c:2048 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "filnamnet är för långt för tar-format: \"%s\"" -#: backup/basebackup.c:1772 +#: backup/basebackup.c:2053 #, c-format msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "mål för symbolisk länk är för långt för tar-format: filnamn \"%s\", mål \"%s\"" +#: backup/basebackup.c:2127 +#, c-format +msgid "could not read file \"%s\": read %zd of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %zd av %zu" + #: backup/basebackup_gzip.c:67 #, c-format msgid "gzip compression is not supported by this build" @@ -3643,53 +3912,114 @@ msgstr "gzip-komprimering stöds inte av detta bygge" msgid "could not initialize compression library" msgstr "kunde inte initierar komprimeringsbibliotek" +#: backup/basebackup_incremental.c:294 +#, c-format +msgid "manifest contains no required WAL ranges" +msgstr "manifestet innehåller inga WAL-intervall som krävs" + +#: backup/basebackup_incremental.c:349 +#, c-format +msgid "timeline %u found in manifest, but not in this server's history" +msgstr "tidslinje %u hittades i manifest men inte i denna servers historik" + +#: backup/basebackup_incremental.c:414 +#, c-format +msgid "manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "manifestet kräver WAL från initiala tidslinjen %u vid start %X/%X men den tidslinjen börjar vid %X/%X" + +#: backup/basebackup_incremental.c:424 +#, c-format +msgid "manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "manifestet kräver WAL från tidslinje %u att fortsätta med som startar vid %X/%X men den tidslinjen börjar vid %X/%X" + +#: backup/basebackup_incremental.c:435 +#, c-format +msgid "manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X" +msgstr "manifestet kräver WAL från avslutande tidslinje %u som slutar vid %X/%X, men denna backup startar vid %X/%X" + +#: backup/basebackup_incremental.c:439 +#, c-format +msgid "This can happen for incremental backups on a standby if there was little activity since the previous backup." +msgstr "Detta kan hända vid inkrementella backuper på en standby om det är lite aktivitet från föregående backup." + +#: backup/basebackup_incremental.c:446 +#, c-format +msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" +msgstr "manifestet kräver WAL från en icke avslutande tidslinje %u som slutar vid %X/%X men denns server bytte tidslinje vid %X/%X" + +#: backup/basebackup_incremental.c:527 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist" +msgstr "WAL-summering krävs för tidslinje %u från %X/%X till %X/%X men inga summeringar för den tidslinjen och det LSN-intervallet finns" + +#: backup/basebackup_incremental.c:534 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete" +msgstr "WAL-summering krävs för tidslinje %u från %X/%X till %X/%X men summeringar för den tidslinjen och det LSN-intervallet är inkompletta" + +#: backup/basebackup_incremental.c:538 +#, c-format +msgid "The first unsummarized LSN in this range is %X/%X." +msgstr "Den första icke summerade LSN i detta intervall är %X/%X." + +#: backup/basebackup_incremental.c:938 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "backupmanifest version 1 stöder inte inkrementell backup" + +#: backup/basebackup_incremental.c:956 +#, c-format +msgid "system identifier in backup manifest is %llu, but database system identifier is %llu" +msgstr "manifestets systemidentifierare är %llu men databasens systemidentifierare är %llu" + #: backup/basebackup_lz4.c:67 #, c-format msgid "lz4 compression is not supported by this build" msgstr "lz4-komprimering stöds inte av detta bygge" -#: backup/basebackup_server.c:75 +#: backup/basebackup_server.c:73 #, c-format msgid "permission denied to create backup stored on server" msgstr "rättighet saknas för att skapa backup som lagras på servern" -#: backup/basebackup_server.c:76 +#: backup/basebackup_server.c:74 #, c-format msgid "Only roles with privileges of the \"%s\" role may create a backup stored on the server." msgstr "Bara roller med rättigheter från rollen \"%s\" får skapa backup som lagras på servern." -#: backup/basebackup_server.c:91 +#: backup/basebackup_server.c:89 #, c-format msgid "relative path not allowed for backup stored on server" msgstr "relativ sökväg tillåts inte för backup som sparas på servern" -#: backup/basebackup_server.c:104 commands/dbcommands.c:501 -#: commands/tablespace.c:163 commands/tablespace.c:179 -#: commands/tablespace.c:599 commands/tablespace.c:644 replication/slot.c:1704 +#: backup/basebackup_server.c:102 commands/dbcommands.c:477 +#: commands/tablespace.c:157 commands/tablespace.c:173 +#: commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 #: storage/file/copydir.c:47 #, c-format msgid "could not create directory \"%s\": %m" msgstr "kunde inte skapa katalog \"%s\": %m" -#: backup/basebackup_server.c:117 +#: backup/basebackup_server.c:115 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "katalogen \"%s\" existerar men är inte tom" -#: backup/basebackup_server.c:125 utils/init/postinit.c:1164 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1178 #, c-format msgid "could not access directory \"%s\": %m" msgstr "kunde inte komma åt katalog \"%s\": %m" -#: backup/basebackup_server.c:177 backup/basebackup_server.c:184 -#: backup/basebackup_server.c:270 backup/basebackup_server.c:277 -#: storage/smgr/md.c:504 storage/smgr/md.c:511 storage/smgr/md.c:593 -#: storage/smgr/md.c:615 storage/smgr/md.c:865 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 +#: backup/basebackup_server.c:268 backup/basebackup_server.c:275 +#: backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 +#: storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 #, c-format msgid "Check free disk space." msgstr "Kontrollera ledigt diskutrymme." -#: backup/basebackup_server.c:181 backup/basebackup_server.c:274 +#: backup/basebackup_server.c:179 backup/basebackup_server.c:272 +#: backup/walsummary.c:309 #, c-format msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" msgstr "kunde inte skriva fil \"%s\": skrev bara %d av %d byte vid offset %u" @@ -3719,709 +4049,720 @@ msgstr "kunde inte sätta komprimeringens arbetarantal till %d: %s" msgid "could not enable long-distance mode: %s" msgstr "kunde inte aktivera långdistansläge: %s" -#: bootstrap/bootstrap.c:243 postmaster/postmaster.c:721 tcop/postgres.c:3819 +#: backup/walsummaryfuncs.c:95 +#, c-format +msgid "invalid timeline %lld" +msgstr "ogiltig tidslinje %lld" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3946 #, c-format msgid "--%s requires a value" msgstr "--%s kräver ett värde" -#: bootstrap/bootstrap.c:248 postmaster/postmaster.c:726 tcop/postgres.c:3824 +#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3951 #, c-format msgid "-c %s requires a value" msgstr "-c %s kräver ett värde" -#: bootstrap/bootstrap.c:289 -#, c-format -msgid "-X requires a power of two value between 1 MB and 1 GB" -msgstr "-X kräver ett tvåpotensvärde mellan 1 MB och 1 GB" - -#: bootstrap/bootstrap.c:295 postmaster/postmaster.c:844 -#: postmaster/postmaster.c:857 +#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 +#: postmaster/postmaster.c:759 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Försök med \"%s --help\" för mer information.\n" -#: bootstrap/bootstrap.c:304 +#: bootstrap/bootstrap.c:291 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: ogiltigt kommandoradsargument\n" -#: catalog/aclchk.c:201 +#: catalog/aclchk.c:211 #, c-format msgid "grant options can only be granted to roles" msgstr "\"grant option\" kan bara ges till roller" -#: catalog/aclchk.c:323 +#: catalog/aclchk.c:333 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "inga rättigheter givna för kolumn \"%s\" i relation \"%s\"" -#: catalog/aclchk.c:328 +#: catalog/aclchk.c:338 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "inga rättigheter gavs till \"%s\"" -#: catalog/aclchk.c:336 +#: catalog/aclchk.c:346 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "inte alla rättigheter givna för kolumn \"%s\" i relation \"%s\"" -#: catalog/aclchk.c:341 +#: catalog/aclchk.c:351 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "inte alla rättigheter givna för \"%s\"" -#: catalog/aclchk.c:352 +#: catalog/aclchk.c:362 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "inga rättigheter kunde tas tillbaka från kolumn \"%s\" i relation \"%s\"" -#: catalog/aclchk.c:357 +#: catalog/aclchk.c:367 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "inga rättigheter kunde tas tillbaka från \"%s\"" -#: catalog/aclchk.c:365 +#: catalog/aclchk.c:375 #, c-format msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "inte alla rättigheter kunde tas tillbaka från kolumn \"%s\" i relation \"%s\"" -#: catalog/aclchk.c:370 +#: catalog/aclchk.c:380 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "inte alla rättigheter kunde tas tillbaka från \"%s\"" -#: catalog/aclchk.c:402 +#: catalog/aclchk.c:412 #, c-format msgid "grantor must be current user" msgstr "utfärdare måste vara den aktiva användaren" -#: catalog/aclchk.c:470 catalog/aclchk.c:1045 +#: catalog/aclchk.c:480 catalog/aclchk.c:1055 #, c-format msgid "invalid privilege type %s for relation" msgstr "ogiltig privilegietyp %s för relation" -#: catalog/aclchk.c:474 catalog/aclchk.c:1049 +#: catalog/aclchk.c:484 catalog/aclchk.c:1059 #, c-format msgid "invalid privilege type %s for sequence" msgstr "ogiltig privilegietyp %s för sekvens" -#: catalog/aclchk.c:478 +#: catalog/aclchk.c:488 #, c-format msgid "invalid privilege type %s for database" msgstr "ogiltig privilegietyp %s för databas" -#: catalog/aclchk.c:482 +#: catalog/aclchk.c:492 #, c-format msgid "invalid privilege type %s for domain" msgstr "ogiltig privilegietyp %s för domän" -#: catalog/aclchk.c:486 catalog/aclchk.c:1053 +#: catalog/aclchk.c:496 catalog/aclchk.c:1063 #, c-format msgid "invalid privilege type %s for function" msgstr "ogiltig privilegietyp %s för funktion" -#: catalog/aclchk.c:490 +#: catalog/aclchk.c:500 #, c-format msgid "invalid privilege type %s for language" msgstr "ogiltig privilegietyp %s för språk" -#: catalog/aclchk.c:494 +#: catalog/aclchk.c:504 #, c-format msgid "invalid privilege type %s for large object" msgstr "ogiltig privilegietyp %s för stort objekt" -#: catalog/aclchk.c:498 catalog/aclchk.c:1069 +#: catalog/aclchk.c:508 catalog/aclchk.c:1079 #, c-format msgid "invalid privilege type %s for schema" msgstr "ogiltig privilegietyp %s för schema" -#: catalog/aclchk.c:502 catalog/aclchk.c:1057 +#: catalog/aclchk.c:512 catalog/aclchk.c:1067 #, c-format msgid "invalid privilege type %s for procedure" msgstr "ogiltig rättighetstyp %s för procedur" -#: catalog/aclchk.c:506 catalog/aclchk.c:1061 +#: catalog/aclchk.c:516 catalog/aclchk.c:1071 #, c-format msgid "invalid privilege type %s for routine" msgstr "ogiltig rättighetstyp %s för rutin" -#: catalog/aclchk.c:510 +#: catalog/aclchk.c:520 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "ogiltig privilegietyp %s för tabellutrymme" -#: catalog/aclchk.c:514 catalog/aclchk.c:1065 +#: catalog/aclchk.c:524 catalog/aclchk.c:1075 #, c-format msgid "invalid privilege type %s for type" msgstr "ogiltig privilegietyp %s för typ" -#: catalog/aclchk.c:518 +#: catalog/aclchk.c:528 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "ogiltig privilegietyp %s för främmande data-omvandlare" -#: catalog/aclchk.c:522 +#: catalog/aclchk.c:532 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "ogiltig privilegietyp %s för främmande server" -#: catalog/aclchk.c:526 +#: catalog/aclchk.c:536 #, c-format msgid "invalid privilege type %s for parameter" msgstr "ogiltig privilegietyp %s för parameter" -#: catalog/aclchk.c:565 +#: catalog/aclchk.c:575 #, c-format msgid "column privileges are only valid for relations" msgstr "kolumnprivilegier är bara giltiga för relationer" -#: catalog/aclchk.c:728 catalog/aclchk.c:3555 catalog/objectaddress.c:1092 -#: catalog/pg_largeobject.c:116 storage/large_object/inv_api.c:287 +#: catalog/aclchk.c:738 catalog/aclchk.c:3629 catalog/objectaddress.c:1054 +#: catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 #, c-format msgid "large object %u does not exist" msgstr "stort objekt %u existerar inte" -#: catalog/aclchk.c:1102 +#: catalog/aclchk.c:1112 #, c-format msgid "default privileges cannot be set for columns" msgstr "standardrättigheter kan inte sättas för kolumner" -#: catalog/aclchk.c:1138 +#: catalog/aclchk.c:1148 #, c-format msgid "permission denied to change default privileges" msgstr "rättighet saknas för att ändra standardrättigheter" -#: catalog/aclchk.c:1256 +#: catalog/aclchk.c:1266 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "kan inte använda IN SCHEMA-klausul samtidigt som GRANT/REVOKE ON SCHEMAS" -#: catalog/aclchk.c:1595 catalog/catalog.c:631 catalog/objectaddress.c:1561 -#: catalog/pg_publication.c:533 commands/analyze.c:390 commands/copy.c:837 -#: commands/sequence.c:1663 commands/tablecmds.c:7339 commands/tablecmds.c:7495 -#: commands/tablecmds.c:7545 commands/tablecmds.c:7619 -#: commands/tablecmds.c:7689 commands/tablecmds.c:7801 -#: commands/tablecmds.c:7895 commands/tablecmds.c:7954 -#: commands/tablecmds.c:8043 commands/tablecmds.c:8073 -#: commands/tablecmds.c:8201 commands/tablecmds.c:8283 -#: commands/tablecmds.c:8417 commands/tablecmds.c:8525 -#: commands/tablecmds.c:12240 commands/tablecmds.c:12421 -#: commands/tablecmds.c:12582 commands/tablecmds.c:13744 -#: commands/tablecmds.c:16273 commands/trigger.c:949 parser/analyze.c:2518 -#: parser/parse_relation.c:737 parser/parse_target.c:1054 -#: parser/parse_type.c:144 parser/parse_utilcmd.c:3413 -#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2876 -#: utils/adt/ruleutils.c:2799 +#: catalog/aclchk.c:1617 catalog/catalog.c:659 catalog/objectaddress.c:1523 +#: catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:951 +#: commands/sequence.c:1655 commands/tablecmds.c:7541 commands/tablecmds.c:7695 +#: commands/tablecmds.c:7745 commands/tablecmds.c:7819 +#: commands/tablecmds.c:7889 commands/tablecmds.c:8019 +#: commands/tablecmds.c:8148 commands/tablecmds.c:8242 +#: commands/tablecmds.c:8343 commands/tablecmds.c:8470 +#: commands/tablecmds.c:8500 commands/tablecmds.c:8642 +#: commands/tablecmds.c:8735 commands/tablecmds.c:8869 +#: commands/tablecmds.c:8981 commands/tablecmds.c:12797 +#: commands/tablecmds.c:12989 commands/tablecmds.c:13150 +#: commands/tablecmds.c:14339 commands/tablecmds.c:16966 commands/trigger.c:942 +#: parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 +#: parser/parse_type.c:144 parser/parse_utilcmd.c:3409 +#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2923 +#: utils/adt/ruleutils.c:2812 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "kolumn \"%s\" i relation \"%s\" existerar inte" -#: catalog/aclchk.c:1840 +#: catalog/aclchk.c:1862 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" är ett index" -#: catalog/aclchk.c:1847 commands/tablecmds.c:13901 commands/tablecmds.c:17172 +#: catalog/aclchk.c:1869 commands/tablecmds.c:14496 commands/tablecmds.c:17882 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\" är en composite-typ" -#: catalog/aclchk.c:1855 catalog/objectaddress.c:1401 commands/sequence.c:1171 -#: commands/tablecmds.c:254 commands/tablecmds.c:17136 utils/adt/acl.c:2084 -#: utils/adt/acl.c:2114 utils/adt/acl.c:2146 utils/adt/acl.c:2178 -#: utils/adt/acl.c:2206 utils/adt/acl.c:2236 +#: catalog/aclchk.c:1877 catalog/objectaddress.c:1363 commands/tablecmds.c:263 +#: commands/tablecmds.c:17846 utils/adt/acl.c:2107 utils/adt/acl.c:2137 +#: utils/adt/acl.c:2170 utils/adt/acl.c:2206 utils/adt/acl.c:2237 +#: utils/adt/acl.c:2268 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\" är inte en sekvens" -#: catalog/aclchk.c:1893 +#: catalog/aclchk.c:1915 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "sekvensen \"%s\" stöder bara USAGE-, SELECT- och UPDATE-rättigheter" -#: catalog/aclchk.c:1910 +#: catalog/aclchk.c:1932 #, c-format msgid "invalid privilege type %s for table" msgstr "ogiltig rättighetstyp %s för tabell" -#: catalog/aclchk.c:2072 +#: catalog/aclchk.c:2097 #, c-format msgid "invalid privilege type %s for column" msgstr "ogitligt rättighetstyp %s för kolumn" -#: catalog/aclchk.c:2085 +#: catalog/aclchk.c:2110 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "sekvensen \"%s\" stöder bara kolumnrättigheten SELECT" -#: catalog/aclchk.c:2275 +#: catalog/aclchk.c:2301 #, c-format msgid "language \"%s\" is not trusted" msgstr "språket \"%s\" är inte betrott" -#: catalog/aclchk.c:2277 +#: catalog/aclchk.c:2303 #, c-format msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages." msgstr "GRANT och REVOKE är inte tillåtna på icke betrodda språk då bara en superuser kan använda icke betrodda språk." -#: catalog/aclchk.c:2427 +#: catalog/aclchk.c:2454 #, c-format msgid "cannot set privileges of array types" msgstr "kan inte sätta privilegier för array-typer" -#: catalog/aclchk.c:2428 +#: catalog/aclchk.c:2455 #, c-format msgid "Set the privileges of the element type instead." msgstr "Sätt rättigheter för elementtypen istället." -#: catalog/aclchk.c:2435 catalog/objectaddress.c:1667 +#: catalog/aclchk.c:2459 +#, c-format +msgid "cannot set privileges of multirange types" +msgstr "kan inte sätta privilegier för multirange-typer" + +#: catalog/aclchk.c:2460 +#, c-format +msgid "Set the privileges of the range type instead." +msgstr "Sätt rättigheter för range-typen istället." + +#: catalog/aclchk.c:2467 catalog/objectaddress.c:1629 #, c-format msgid "\"%s\" is not a domain" msgstr "\"%s\" är inte en domän" -#: catalog/aclchk.c:2619 +#: catalog/aclchk.c:2653 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "okänd privilegietyp \"%s\"" -#: catalog/aclchk.c:2684 +#: catalog/aclchk.c:2720 #, c-format msgid "permission denied for aggregate %s" msgstr "rättighet saknas för aggregat %s" -#: catalog/aclchk.c:2687 +#: catalog/aclchk.c:2723 #, c-format msgid "permission denied for collation %s" msgstr "rättighet saknas för jämförelse %s" -#: catalog/aclchk.c:2690 +#: catalog/aclchk.c:2726 #, c-format msgid "permission denied for column %s" msgstr "rättighet saknas för kolumn %s" -#: catalog/aclchk.c:2693 +#: catalog/aclchk.c:2729 #, c-format msgid "permission denied for conversion %s" msgstr "rättighet saknas för konvertering %s" -#: catalog/aclchk.c:2696 +#: catalog/aclchk.c:2732 #, c-format msgid "permission denied for database %s" msgstr "rättighet saknas för databas %s" -#: catalog/aclchk.c:2699 +#: catalog/aclchk.c:2735 #, c-format msgid "permission denied for domain %s" msgstr "rättighet saknas för domän %s" -#: catalog/aclchk.c:2702 +#: catalog/aclchk.c:2738 #, c-format msgid "permission denied for event trigger %s" msgstr "rättighet saknas för händelsetrigger %s" -#: catalog/aclchk.c:2705 +#: catalog/aclchk.c:2741 #, c-format msgid "permission denied for extension %s" msgstr "rättighet saknas för utökning %s" -#: catalog/aclchk.c:2708 +#: catalog/aclchk.c:2744 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "rättighet saknas för främmande data-omvandlare %s" -#: catalog/aclchk.c:2711 +#: catalog/aclchk.c:2747 #, c-format msgid "permission denied for foreign server %s" msgstr "rättighet saknas för främmande server %s" -#: catalog/aclchk.c:2714 +#: catalog/aclchk.c:2750 #, c-format msgid "permission denied for foreign table %s" msgstr "rättighet saknas för främmande tabell %s" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2753 #, c-format msgid "permission denied for function %s" msgstr "rättighet saknas för funktion %s" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2756 #, c-format msgid "permission denied for index %s" msgstr "rättighet saknas för index %s" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2759 #, c-format msgid "permission denied for language %s" msgstr "rättighet saknas för språk %s" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2762 #, c-format msgid "permission denied for large object %s" msgstr "rättighet saknas för stort objekt %s" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2765 #, c-format msgid "permission denied for materialized view %s" msgstr "rättighet saknas för materialiserad vy %s" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2768 #, c-format msgid "permission denied for operator class %s" msgstr "rättighet saknas för operatorklasss %s" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2771 #, c-format msgid "permission denied for operator %s" msgstr "rättighet saknas för operator %s" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2774 #, c-format msgid "permission denied for operator family %s" msgstr "rättighet saknas för operatorfamilj %s" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2777 #, c-format msgid "permission denied for parameter %s" msgstr "rättighet saknas för parametern %s" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2780 #, c-format msgid "permission denied for policy %s" msgstr "rättighet saknas för policy %s" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2783 #, c-format msgid "permission denied for procedure %s" msgstr "rättighet saknas för procedur %s" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2786 #, c-format msgid "permission denied for publication %s" msgstr "rättighet saknas för publicering %s" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2789 #, c-format msgid "permission denied for routine %s" msgstr "rättighet saknas för rutin %s" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2792 #, c-format msgid "permission denied for schema %s" msgstr "rättighet saknas för schema %s" -#: catalog/aclchk.c:2759 commands/sequence.c:659 commands/sequence.c:885 -#: commands/sequence.c:927 commands/sequence.c:968 commands/sequence.c:1761 -#: commands/sequence.c:1810 +#: catalog/aclchk.c:2795 commands/sequence.c:654 commands/sequence.c:880 +#: commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 +#: commands/sequence.c:1799 #, c-format msgid "permission denied for sequence %s" msgstr "rättighet saknas för sekvens %s" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2798 #, c-format msgid "permission denied for statistics object %s" msgstr "rättighet saknas för statistikobjekt %s" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2801 #, c-format msgid "permission denied for subscription %s" msgstr "rättighet saknas för prenumeration %s" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2804 #, c-format msgid "permission denied for table %s" msgstr "rättighet saknas för tabell %s" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2807 #, c-format msgid "permission denied for tablespace %s" msgstr "rättighet saknas för tabellutrymme %s" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2810 #, c-format msgid "permission denied for text search configuration %s" msgstr "rättighet saknas för textsökkonfigurering %s" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2813 #, c-format msgid "permission denied for text search dictionary %s" msgstr "rättighet saknas för textsökordlista %s" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2816 #, c-format msgid "permission denied for type %s" msgstr "rättighet saknas för typ %s" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2819 #, c-format msgid "permission denied for view %s" msgstr "rättighet saknas för vy %s" -#: catalog/aclchk.c:2819 +#: catalog/aclchk.c:2855 #, c-format msgid "must be owner of aggregate %s" msgstr "måste vara ägaren till aggregatet %s" -#: catalog/aclchk.c:2822 +#: catalog/aclchk.c:2858 #, c-format msgid "must be owner of collation %s" msgstr "måste vara ägaren till jämförelsen %s" -#: catalog/aclchk.c:2825 +#: catalog/aclchk.c:2861 #, c-format msgid "must be owner of conversion %s" msgstr "måste vara ägaren till konverteringen %s" -#: catalog/aclchk.c:2828 +#: catalog/aclchk.c:2864 #, c-format msgid "must be owner of database %s" msgstr "måste vara ägaren till databasen %s" -#: catalog/aclchk.c:2831 +#: catalog/aclchk.c:2867 #, c-format msgid "must be owner of domain %s" msgstr "måste vara ägaren av domänen %s" -#: catalog/aclchk.c:2834 +#: catalog/aclchk.c:2870 #, c-format msgid "must be owner of event trigger %s" msgstr "måste vara ägaren till händelsetrigger %s" -#: catalog/aclchk.c:2837 +#: catalog/aclchk.c:2873 #, c-format msgid "must be owner of extension %s" msgstr "måste vara ägaren till utökningen %s" -#: catalog/aclchk.c:2840 +#: catalog/aclchk.c:2876 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "måste vara ägaren till främmande data-omvandlaren %s" -#: catalog/aclchk.c:2843 +#: catalog/aclchk.c:2879 #, c-format msgid "must be owner of foreign server %s" msgstr "måste vara ägaren till främmande servern %s" -#: catalog/aclchk.c:2846 +#: catalog/aclchk.c:2882 #, c-format msgid "must be owner of foreign table %s" msgstr "måste vara ägaren till främmande tabellen %s" -#: catalog/aclchk.c:2849 +#: catalog/aclchk.c:2885 #, c-format msgid "must be owner of function %s" msgstr "måste vara ägaren till funktionen %s" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2888 #, c-format msgid "must be owner of index %s" msgstr "måste vara ägaren till indexet %s" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2891 #, c-format msgid "must be owner of language %s" msgstr "måste vara ägaren till språket %s" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2894 #, c-format msgid "must be owner of large object %s" msgstr "måste vara ägaren till stora objektet %s" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2897 #, c-format msgid "must be owner of materialized view %s" msgstr "måste vara ägaren till den materialiserade vyn %s" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2900 #, c-format msgid "must be owner of operator class %s" msgstr "måste vara ägaren till operatorklassen %s" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2903 #, c-format msgid "must be owner of operator %s" msgstr "måste vara ägaren till operatorn %s" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2906 #, c-format msgid "must be owner of operator family %s" msgstr "måste vara ägaren till operatorfamiljen %s" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2909 #, c-format msgid "must be owner of procedure %s" msgstr "måste vara ägaren till proceduren %s" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2912 #, c-format msgid "must be owner of publication %s" msgstr "måste vara ägaren till publiceringen %s" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2915 #, c-format msgid "must be owner of routine %s" msgstr "måste vara ägaren till rutinen %s" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2918 #, c-format msgid "must be owner of sequence %s" msgstr "måste vara ägaren till sekvensen %s" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2921 #, c-format msgid "must be owner of subscription %s" msgstr "måste vara ägaren till prenumerationen %s" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2924 #, c-format msgid "must be owner of table %s" msgstr "måste vara ägaren till tabellen %s" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2927 #, c-format msgid "must be owner of type %s" msgstr "måste vara ägaren till typen %s" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2930 #, c-format msgid "must be owner of view %s" msgstr "måste vara ägaren till vyn %s" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2933 #, c-format msgid "must be owner of schema %s" msgstr "måste vara ägaren till schemat %s" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2936 #, c-format msgid "must be owner of statistics object %s" msgstr "måste vara ägaren till statistikobjektet %s" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2939 #, c-format msgid "must be owner of tablespace %s" msgstr "måste vara ägaren till tabellutrymmet %s" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2942 #, c-format msgid "must be owner of text search configuration %s" msgstr "måste vara ägaren till textsökkonfigurationen %s" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2945 #, c-format msgid "must be owner of text search dictionary %s" msgstr "måste vara ägaren till textsökordlistan %s" -#: catalog/aclchk.c:2923 +#: catalog/aclchk.c:2959 #, c-format msgid "must be owner of relation %s" msgstr "måste vara ägaren till relationen %s" -#: catalog/aclchk.c:2969 +#: catalog/aclchk.c:3005 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "rättighet saknas för kolumn \"%s\" i relation \"%s\"" -#: catalog/aclchk.c:3104 catalog/aclchk.c:3979 catalog/aclchk.c:4011 +#: catalog/aclchk.c:3162 catalog/aclchk.c:4170 catalog/aclchk.c:4201 #, c-format msgid "%s with OID %u does not exist" msgstr "%s med OID %u existerar inte" -#: catalog/aclchk.c:3188 catalog/aclchk.c:3207 +#: catalog/aclchk.c:3245 catalog/aclchk.c:3264 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "attribut %d i relation med OID %u existerar inte" -#: catalog/aclchk.c:3302 +#: catalog/aclchk.c:3302 catalog/aclchk.c:3365 catalog/aclchk.c:4004 #, c-format msgid "relation with OID %u does not exist" msgstr "relation med OID %u existerar inte" -#: catalog/aclchk.c:3476 +#: catalog/aclchk.c:3550 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "parameter ACL med OID %u existerar inte" -#: catalog/aclchk.c:3640 commands/collationcmds.c:808 -#: commands/publicationcmds.c:1746 +#: catalog/aclchk.c:3723 commands/collationcmds.c:853 +#: commands/publicationcmds.c:1739 #, c-format msgid "schema with OID %u does not exist" msgstr "schema med OID %u existerar inte" -#: catalog/aclchk.c:3705 utils/cache/typcache.c:390 utils/cache/typcache.c:445 +#: catalog/aclchk.c:3797 catalog/aclchk.c:3824 catalog/aclchk.c:3853 +#: utils/cache/typcache.c:392 utils/cache/typcache.c:447 #, c-format msgid "type with OID %u does not exist" msgstr "typ med OID %u existerar inte" -#: catalog/catalog.c:449 +#: catalog/catalog.c:477 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "letar fortfarande efter en oanvänd OID i relationen \"%s\"" -#: catalog/catalog.c:451 +#: catalog/catalog.c:479 #, c-format msgid "OID candidates have been checked %llu time, but no unused OID has been found yet." msgid_plural "OID candidates have been checked %llu times, but no unused OID has been found yet." msgstr[0] "OID-kandidater har kontrollerats %llu gång men inga oanvända OID:er har hittats än." msgstr[1] "OID-kandidater har kontrollerats %llu gånger men inga oanvända OID:er har hittats än." -#: catalog/catalog.c:476 +#: catalog/catalog.c:504 #, c-format msgid "new OID has been assigned in relation \"%s\" after %llu retry" msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" msgstr[0] "ny OID har tilldelats i relation \"%s\" after %llu försök" msgstr[1] "ny OID har tilldelats i relation \"%s\" after %llu försök" -#: catalog/catalog.c:609 catalog/catalog.c:676 +#: catalog/catalog.c:637 catalog/catalog.c:704 #, c-format msgid "must be superuser to call %s()" msgstr "måste vara en superuser för att anropa %s()" -#: catalog/catalog.c:618 +#: catalog/catalog.c:646 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() kan bara användas på systemkataloger" -#: catalog/catalog.c:623 parser/parse_utilcmd.c:2264 +#: catalog/catalog.c:651 parser/parse_utilcmd.c:2270 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "index \"%s\" tillhör inte tabell \"%s\"" -#: catalog/catalog.c:640 +#: catalog/catalog.c:668 #, c-format msgid "column \"%s\" is not of type oid" msgstr "kolumnen \"%s\" är inte av typen oid" -#: catalog/catalog.c:647 +#: catalog/catalog.c:675 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "index \"%s\" är inte indexet för kolumnen \"%s\"" -#: catalog/dependency.c:546 catalog/pg_shdepend.c:658 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "kan inte ta bort %s eftersom den krävs av databassystemet" -#: catalog/dependency.c:838 catalog/dependency.c:1065 +#: catalog/dependency.c:789 catalog/dependency.c:1016 #, c-format msgid "cannot drop %s because %s requires it" msgstr "kan inte ta bort %s eftersom %s behöver den" -#: catalog/dependency.c:840 catalog/dependency.c:1067 +#: catalog/dependency.c:791 catalog/dependency.c:1018 #, c-format msgid "You can drop %s instead." msgstr "Du kan ta bort %s i stället." -#: catalog/dependency.c:1146 catalog/dependency.c:1155 +#: catalog/dependency.c:1097 catalog/dependency.c:1106 #, c-format msgid "%s depends on %s" msgstr "%s beror på %s" -#: catalog/dependency.c:1170 catalog/dependency.c:1179 +#: catalog/dependency.c:1121 catalog/dependency.c:1130 #, c-format msgid "drop cascades to %s" msgstr "drop svämmar över (cascades) till %s" -#: catalog/dependency.c:1187 catalog/pg_shdepend.c:823 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format msgid "" "\n" @@ -4436,714 +4777,715 @@ msgstr[1] "" "\n" "och %d andra objekt (se serverloggen för en lista)" -#: catalog/dependency.c:1199 +#: catalog/dependency.c:1150 #, c-format msgid "cannot drop %s because other objects depend on it" msgstr "kan inte ta bort %s eftersom andra objekt beror på den" -#: catalog/dependency.c:1202 catalog/dependency.c:1209 -#: catalog/dependency.c:1220 commands/tablecmds.c:1335 -#: commands/tablecmds.c:14386 commands/tablespace.c:466 commands/user.c:1309 -#: commands/vacuum.c:211 commands/view.c:446 libpq/auth.c:326 -#: replication/logical/applyparallelworker.c:1044 replication/syncrep.c:1017 -#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1358 utils/misc/guc.c:3120 -#: utils/misc/guc.c:3156 utils/misc/guc.c:3226 utils/misc/guc.c:6615 -#: utils/misc/guc.c:6649 utils/misc/guc.c:6683 utils/misc/guc.c:6726 -#: utils/misc/guc.c:6768 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 +#: catalog/dependency.c:1171 commands/tablecmds.c:1459 +#: commands/tablecmds.c:15088 commands/tablespace.c:460 commands/user.c:1302 +#: commands/vacuum.c:211 commands/view.c:441 executor/execExprInterp.c:4655 +#: executor/execExprInterp.c:4663 libpq/auth.c:324 +#: replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 +#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1432 utils/misc/guc.c:3169 +#: utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6825 +#: utils/misc/guc.c:6859 utils/misc/guc.c:6893 utils/misc/guc.c:6936 +#: utils/misc/guc.c:6978 #, c-format msgid "%s" msgstr "%s" -#: catalog/dependency.c:1203 catalog/dependency.c:1210 +#: catalog/dependency.c:1154 catalog/dependency.c:1161 #, c-format msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "Använd DROP ... CASCADE för att ta bort de beroende objekten också." -#: catalog/dependency.c:1207 +#: catalog/dependency.c:1158 #, c-format msgid "cannot drop desired object(s) because other objects depend on them" msgstr "kan inte ta bort önskade objekt eftersom andra objekt beror på dem" -#: catalog/dependency.c:1215 +#: catalog/dependency.c:1166 #, c-format msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" msgstr[0] "drop svämmar över (cascades) till %d andra objekt" msgstr[1] "drop svämmar över (cascades) till %d andra objekt" -#: catalog/dependency.c:1899 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "konstant av typen %s kan inte användas här" -#: catalog/dependency.c:2420 parser/parse_relation.c:3404 -#: parser/parse_relation.c:3414 +#: catalog/dependency.c:2375 parser/parse_relation.c:3407 +#: parser/parse_relation.c:3417 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "kolumn %d i relation \"%s\" finns inte" -#: catalog/heap.c:324 +#: catalog/heap.c:325 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "rättighet saknas för att skapa \"%s.%s\"" -#: catalog/heap.c:326 +#: catalog/heap.c:327 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "Systemkatalogändringar är för tillfället inte tillåtna." -#: catalog/heap.c:466 commands/tablecmds.c:2374 commands/tablecmds.c:3047 -#: commands/tablecmds.c:6922 +#: catalog/heap.c:467 commands/tablecmds.c:2495 commands/tablecmds.c:2917 +#: commands/tablecmds.c:7163 #, c-format msgid "tables can have at most %d columns" msgstr "tabeller kan ha som mest %d kolumner" -#: catalog/heap.c:484 commands/tablecmds.c:7229 +#: catalog/heap.c:485 commands/tablecmds.c:7432 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "kolumnnamn \"%s\" står i konflikt med ett systemkolumnnamn" -#: catalog/heap.c:500 +#: catalog/heap.c:501 #, c-format msgid "column name \"%s\" specified more than once" msgstr "kolumnnamn \"%s\" angiven mer än en gång" #. translator: first %s is an integer not a name -#: catalog/heap.c:575 +#: catalog/heap.c:579 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "partitionsnyckelkolumn \"%s\" har pseudo-typ %s" -#: catalog/heap.c:580 +#: catalog/heap.c:584 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "kolumn \"%s\" har pseudo-typ %s" -#: catalog/heap.c:611 +#: catalog/heap.c:615 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "composite-typ %s kan inte vara en del av sig själv" #. translator: first %s is an integer not a name -#: catalog/heap.c:666 +#: catalog/heap.c:670 #, c-format msgid "no collation was derived for partition key column %s with collatable type %s" msgstr "ingen jämförelse kunde härledas för partitionsnyckelkolumn %s med jämförelsetyp %s" -#: catalog/heap.c:672 commands/createas.c:203 commands/createas.c:512 +#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:505 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "ingen jämförelse kunde härledas för kolumn \"%s\" med jämförelsetyp %s" -#: catalog/heap.c:1148 catalog/index.c:887 commands/createas.c:408 -#: commands/tablecmds.c:3987 +#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:401 +#: commands/tablecmds.c:4171 #, c-format msgid "relation \"%s\" already exists" msgstr "relationen \"%s\" finns redan" -#: catalog/heap.c:1164 catalog/pg_type.c:434 catalog/pg_type.c:782 -#: catalog/pg_type.c:954 commands/typecmds.c:249 commands/typecmds.c:261 -#: commands/typecmds.c:754 commands/typecmds.c:1169 commands/typecmds.c:1395 -#: commands/typecmds.c:1575 commands/typecmds.c:2546 +#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 +#: catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 +#: commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 +#: commands/typecmds.c:1585 commands/typecmds.c:2556 #, c-format msgid "type \"%s\" already exists" msgstr "typen \"%s\" existerar redan" -#: catalog/heap.c:1165 +#: catalog/heap.c:1178 #, c-format msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type." msgstr "En relation har en associerad typ med samma namn så du måste använda ett namn som inte krockar med någon existerande typ." -#: catalog/heap.c:1205 +#: catalog/heap.c:1218 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "relfile-nummervärde för toast är inte satt i binärt uppgraderingsläge" -#: catalog/heap.c:1216 +#: catalog/heap.c:1229 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "pg_class heap OID-värde är inte satt i binärt uppgraderingsläge" -#: catalog/heap.c:1226 +#: catalog/heap.c:1239 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "relfile-nummervärde är inte satt i binärt uppgraderingsläge" -#: catalog/heap.c:2119 +#: catalog/heap.c:2130 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "kan inte lägga till NO INHERIT-villkor till partitionerad tabell \"%s\"" -#: catalog/heap.c:2393 +#: catalog/heap.c:2402 #, c-format msgid "check constraint \"%s\" already exists" msgstr "check-villkor \"%s\" finns redan" -#: catalog/heap.c:2563 catalog/index.c:901 catalog/pg_constraint.c:682 -#: commands/tablecmds.c:8900 +#: catalog/heap.c:2574 catalog/index.c:913 catalog/pg_constraint.c:724 +#: commands/tablecmds.c:9356 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "integritetsvillkor \"%s\" för relation \"%s\" finns redan" -#: catalog/heap.c:2570 +#: catalog/heap.c:2581 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "villkor \"%s\" står i konflikt med icke-ärvt villkor på relation \"%s\"" -#: catalog/heap.c:2581 +#: catalog/heap.c:2592 #, c-format msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "villkor \"%s\" står i konflikt med ärvt villkor på relation \"%s\"" -#: catalog/heap.c:2591 +#: catalog/heap.c:2602 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "villkor \"%s\" står i konflikt med NOT VALID-villkor på relation \"%s\"" -#: catalog/heap.c:2596 +#: catalog/heap.c:2607 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "slår samman villkor \"%s\" med ärvd definition" -#: catalog/heap.c:2622 catalog/pg_constraint.c:811 commands/tablecmds.c:2672 -#: commands/tablecmds.c:3199 commands/tablecmds.c:6858 -#: commands/tablecmds.c:15208 commands/tablecmds.c:15349 +#: catalog/heap.c:2633 catalog/pg_constraint.c:853 commands/tablecmds.c:3074 +#: commands/tablecmds.c:3377 commands/tablecmds.c:7089 +#: commands/tablecmds.c:15907 commands/tablecmds.c:16038 #, c-format msgid "too many inheritance parents" msgstr "för många föräldrar i arv" -#: catalog/heap.c:2706 +#: catalog/heap.c:2717 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "kan inte använda genererad kolumn \"%s\" i kolumngenereringsuttryck" -#: catalog/heap.c:2708 +#: catalog/heap.c:2719 #, c-format msgid "A generated column cannot reference another generated column." msgstr "En genererad kolumn kan inte referera till en annan genererad kolumn." -#: catalog/heap.c:2714 +#: catalog/heap.c:2725 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "kan inte använda hela-raden-variabel i kolumngenereringsuttryck" -#: catalog/heap.c:2715 +#: catalog/heap.c:2726 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "Detta skulle leda till att den genererade kolumnen beror på sitt eget värde." -#: catalog/heap.c:2768 +#: catalog/heap.c:2781 #, c-format msgid "generation expression is not immutable" msgstr "genereringsuttryck är inte immutable" -#: catalog/heap.c:2796 rewrite/rewriteHandler.c:1297 +#: catalog/heap.c:2809 rewrite/rewriteHandler.c:1276 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "kolumn \"%s\" har typ %s men default-uttryck har typen %s" -#: catalog/heap.c:2801 commands/prepare.c:334 parser/analyze.c:2742 -#: parser/parse_target.c:593 parser/parse_target.c:874 -#: parser/parse_target.c:884 rewrite/rewriteHandler.c:1302 +#: catalog/heap.c:2814 commands/prepare.c:331 parser/analyze.c:2758 +#: parser/parse_target.c:592 parser/parse_target.c:882 +#: parser/parse_target.c:892 rewrite/rewriteHandler.c:1281 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "Du måste skriva om eller typomvandla uttrycket." -#: catalog/heap.c:2848 +#: catalog/heap.c:2861 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "bara tabell \"%s\" kan refereras i check-villkoret" -#: catalog/heap.c:3154 +#: catalog/heap.c:3167 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "inget stöd för kombinationen ON COMMIT och främmande nyckel" -#: catalog/heap.c:3155 +#: catalog/heap.c:3168 #, c-format msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting." msgstr "Tabell \"%s\" refererar till \"%s\", men de har inte samma ON COMMIT-inställning." -#: catalog/heap.c:3160 +#: catalog/heap.c:3173 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "kan inte trunkera en tabell som refererars till i ett främmande nyckelvillkor" -#: catalog/heap.c:3161 +#: catalog/heap.c:3174 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "Tabell \"%s\" refererar till \"%s\"." -#: catalog/heap.c:3163 +#: catalog/heap.c:3176 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "Trunkera tabellen \"%s\" samtidigt, eller använd TRUNCATE ... CASCADE." -#: catalog/index.c:225 parser/parse_utilcmd.c:2170 +#: catalog/index.c:219 parser/parse_utilcmd.c:2176 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "multipla primärnycklar för tabell \"%s\" tillåts inte" -#: catalog/index.c:239 +#: catalog/index.c:233 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "primärnycklar kan inte använda NULLS NOT DISTINCT-index" -#: catalog/index.c:256 +#: catalog/index.c:250 #, c-format msgid "primary keys cannot be expressions" msgstr "primärnycklar kan inte vara uttryck" -#: catalog/index.c:273 +#: catalog/index.c:267 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "primärnyckelkolumn \"%s\" är inte markerad NOT NULL" -#: catalog/index.c:786 catalog/index.c:1942 +#: catalog/index.c:798 catalog/index.c:1915 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "användardefinierade index på systemkatalogen är inte möjligt" -#: catalog/index.c:826 +#: catalog/index.c:838 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "ickedeterministiska jämförelser (collation) stöds inte för operatorklass \"%s\"" -#: catalog/index.c:841 +#: catalog/index.c:853 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "samtida indexskapande på systemkatalogtabeller stöds inte" -#: catalog/index.c:850 catalog/index.c:1318 +#: catalog/index.c:862 catalog/index.c:1331 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "samtida indexskapande för uteslutningsvillkor stöds inte" -#: catalog/index.c:859 +#: catalog/index.c:871 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "delade index kan inte skapas efter initdb" -#: catalog/index.c:879 commands/createas.c:423 commands/sequence.c:158 +#: catalog/index.c:891 commands/createas.c:416 commands/sequence.c:159 #: parser/parse_utilcmd.c:209 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "relationen \"%s\" finns redan, hoppar över" -#: catalog/index.c:929 +#: catalog/index.c:941 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "pg_class index OID-värde är inte satt i binärt uppgraderingsläge" -#: catalog/index.c:939 utils/cache/relcache.c:3731 +#: catalog/index.c:951 utils/cache/relcache.c:3791 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "relfile-nummervärde för index är inte satt i binärt uppgraderingsläge" -#: catalog/index.c:2241 +#: catalog/index.c:2214 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY måste vara första operationen i transaktion" -#: catalog/index.c:3649 +#: catalog/index.c:3668 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "kan inte omindexera temporära tabeller som tillhör andra sessioner" -#: catalog/index.c:3660 commands/indexcmds.c:3631 +#: catalog/index.c:3679 commands/indexcmds.c:3626 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "kan inte omindexera angivet index i TOAST-tabell" -#: catalog/index.c:3676 commands/indexcmds.c:3511 commands/indexcmds.c:3655 -#: commands/tablecmds.c:3402 +#: catalog/index.c:3695 commands/indexcmds.c:3504 commands/indexcmds.c:3650 +#: commands/tablecmds.c:3581 #, c-format msgid "cannot move system relation \"%s\"" msgstr "kan inte flytta systemrelation \"%s\"" -#: catalog/index.c:3820 +#: catalog/index.c:3832 #, c-format msgid "index \"%s\" was reindexed" msgstr "index \"%s\" omindexerades" -#: catalog/index.c:3957 +#: catalog/index.c:3998 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "kan inte omindexera ogiltigt index \"%s.%s\" på TOAST-tabell, hoppar över" -#: catalog/namespace.c:260 catalog/namespace.c:464 catalog/namespace.c:556 -#: commands/trigger.c:5718 +#: catalog/namespace.c:462 catalog/namespace.c:666 catalog/namespace.c:758 +#: commands/trigger.c:5729 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "referenser till andra databaser är inte implementerat: \"%s.%s.%s\"" -#: catalog/namespace.c:317 +#: catalog/namespace.c:519 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "temporära tabeller kan inte anges med ett schemanamn" -#: catalog/namespace.c:398 +#: catalog/namespace.c:600 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "kunde inte ta lås på relationen \"%s.%s\"" -#: catalog/namespace.c:403 commands/lockcmds.c:144 commands/lockcmds.c:224 +#: catalog/namespace.c:605 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "kunde inte ta lås på relationen \"%s\"" -#: catalog/namespace.c:431 parser/parse_relation.c:1430 +#: catalog/namespace.c:633 parser/parse_relation.c:1430 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "relationen \"%s.%s\" existerar inte" -#: catalog/namespace.c:436 parser/parse_relation.c:1443 +#: catalog/namespace.c:638 parser/parse_relation.c:1443 #: parser/parse_relation.c:1451 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "relationen \"%s\" existerar inte" -#: catalog/namespace.c:502 catalog/namespace.c:3073 commands/extension.c:1611 -#: commands/extension.c:1617 +#: catalog/namespace.c:704 catalog/namespace.c:3522 commands/extension.c:1607 +#: commands/extension.c:1613 #, c-format msgid "no schema has been selected to create in" msgstr "inget schema har valts för att skapa i" -#: catalog/namespace.c:654 catalog/namespace.c:667 +#: catalog/namespace.c:856 catalog/namespace.c:869 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "kan inte skapa relationer i temporära scheman som tillhör andra sessioner" -#: catalog/namespace.c:658 +#: catalog/namespace.c:860 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "kan inte skapa temporär relation i icke-temporärt schema" -#: catalog/namespace.c:673 +#: catalog/namespace.c:875 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "bara temporära relationer får skapas i temporära scheman" -#: catalog/namespace.c:2265 +#: catalog/namespace.c:2619 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "statistikobjektet \"%s\" existerar inte" -#: catalog/namespace.c:2388 +#: catalog/namespace.c:2761 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "textsökparser \"%s\" finns inte" -#: catalog/namespace.c:2514 utils/adt/regproc.c:1439 +#: catalog/namespace.c:2906 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "textsökkatalog \"%s\" finns inte" -#: catalog/namespace.c:2641 +#: catalog/namespace.c:3052 #, c-format msgid "text search template \"%s\" does not exist" msgstr "textsökmall \"%s\" finns inte" -#: catalog/namespace.c:2767 commands/tsearchcmds.c:1162 -#: utils/adt/regproc.c:1329 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3197 commands/tsearchcmds.c:1168 +#: utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "textsökkonfiguration \"%s\" finns inte" -#: catalog/namespace.c:2880 parser/parse_expr.c:832 parser/parse_target.c:1246 +#: catalog/namespace.c:3329 parser/parse_expr.c:868 parser/parse_target.c:1259 #, c-format msgid "cross-database references are not implemented: %s" msgstr "referenser till andra databaser är inte implementerat: %s" -#: catalog/namespace.c:2886 gram.y:18569 gram.y:18609 parser/parse_expr.c:839 -#: parser/parse_target.c:1253 +#: catalog/namespace.c:3335 gram.y:19181 gram.y:19221 parser/parse_expr.c:875 +#: parser/parse_target.c:1266 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "ej korrekt kvalificerat namn (för många namn med punkt): %s" -#: catalog/namespace.c:3016 +#: catalog/namespace.c:3465 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "kan inte flytta objekt in eller ut från temporära scheman" -#: catalog/namespace.c:3022 +#: catalog/namespace.c:3471 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "kan inte flytta objekt in eller ut från TOAST-schema" -#: catalog/namespace.c:3095 commands/schemacmds.c:264 commands/schemacmds.c:344 -#: commands/tablecmds.c:1280 utils/adt/regproc.c:1668 +#: catalog/namespace.c:3544 commands/schemacmds.c:264 commands/schemacmds.c:344 +#: commands/tablecmds.c:1404 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "schema \"%s\" existerar inte" -#: catalog/namespace.c:3126 +#: catalog/namespace.c:3575 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "ej korrekt relationsnamn (för många namn med punkt): %s" -#: catalog/namespace.c:3693 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4016 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "jämförelse \"%s\" för kodning \"%s\" finns inte" -#: catalog/namespace.c:3748 +#: catalog/namespace.c:4071 #, c-format msgid "conversion \"%s\" does not exist" msgstr "konvertering \"%s\" finns inte" -#: catalog/namespace.c:4012 +#: catalog/namespace.c:4412 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "rättighet saknas för att skapa temporära tabeller i databasen \"%s\"" -#: catalog/namespace.c:4028 +#: catalog/namespace.c:4428 #, c-format msgid "cannot create temporary tables during recovery" msgstr "kan inte skapa temptabeller under återställning" -#: catalog/namespace.c:4034 +#: catalog/namespace.c:4434 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "kan inte skapa temporära tabeller under en parallell operation" -#: catalog/objectaddress.c:1409 commands/policy.c:96 commands/policy.c:376 -#: commands/tablecmds.c:248 commands/tablecmds.c:290 commands/tablecmds.c:2206 -#: commands/tablecmds.c:12357 +#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 +#: commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2327 +#: commands/tablecmds.c:12925 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\" är inte en tabell" -#: catalog/objectaddress.c:1416 commands/tablecmds.c:260 -#: commands/tablecmds.c:17141 commands/view.c:119 +#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 +#: commands/tablecmds.c:17851 commands/view.c:114 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\" är inte en vy" -#: catalog/objectaddress.c:1423 commands/matview.c:186 commands/tablecmds.c:266 -#: commands/tablecmds.c:17146 +#: catalog/objectaddress.c:1385 commands/matview.c:199 commands/tablecmds.c:275 +#: commands/tablecmds.c:17856 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\" är inte en materialiserad vy" -#: catalog/objectaddress.c:1430 commands/tablecmds.c:284 -#: commands/tablecmds.c:17151 +#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 +#: commands/tablecmds.c:17861 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\" är inte en främmande tabell" -#: catalog/objectaddress.c:1471 +#: catalog/objectaddress.c:1433 #, c-format msgid "must specify relation and object name" msgstr "måste ange relation och objektnamn" -#: catalog/objectaddress.c:1547 catalog/objectaddress.c:1600 +#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 #, c-format msgid "column name must be qualified" msgstr "kolumnnamn måste vara kvalificerat" -#: catalog/objectaddress.c:1619 +#: catalog/objectaddress.c:1581 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "standardvärde för kolumn \"%s\" i relation \"%s\" existerar inte" -#: catalog/objectaddress.c:1656 commands/functioncmds.c:137 -#: commands/tablecmds.c:276 commands/typecmds.c:274 commands/typecmds.c:3689 +#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 +#: commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 #: parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 -#: utils/adt/acl.c:4441 +#: utils/adt/acl.c:4560 #, c-format msgid "type \"%s\" does not exist" msgstr "typen \"%s\" existerar inte" -#: catalog/objectaddress.c:1775 +#: catalog/objectaddress.c:1737 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "operator %d (%s, %s) för %s finns inte" -#: catalog/objectaddress.c:1806 +#: catalog/objectaddress.c:1768 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "funktion %d (%s, %s) för %s finns inte" -#: catalog/objectaddress.c:1857 catalog/objectaddress.c:1883 +#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "användarmappning för användare \"%s\" på server \"%s\" finns inte" -#: catalog/objectaddress.c:1872 commands/foreigncmds.c:430 -#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:700 +#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 +#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "server \"%s\" finns inte" -#: catalog/objectaddress.c:1939 +#: catalog/objectaddress.c:1901 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "publiceringsrelation \"%s\" i publicering \"%s\" finns inte" -#: catalog/objectaddress.c:1986 +#: catalog/objectaddress.c:1948 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "publiceringsschema \"%s\" i publicering \"%s\" finns inte" -#: catalog/objectaddress.c:2044 +#: catalog/objectaddress.c:2006 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "okänd standard-ACL-objekttyp \"%c\"" -#: catalog/objectaddress.c:2045 +#: catalog/objectaddress.c:2007 #, c-format msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." msgstr "Giltiga objekttyper är \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -#: catalog/objectaddress.c:2096 +#: catalog/objectaddress.c:2058 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "standard ACL för användare \"%s\" i schema \"%s\" på %s finns inte" -#: catalog/objectaddress.c:2101 +#: catalog/objectaddress.c:2063 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "standard ACL för användare \"%s\" på %s finns inte" -#: catalog/objectaddress.c:2127 catalog/objectaddress.c:2184 -#: catalog/objectaddress.c:2239 +#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 +#: catalog/objectaddress.c:2201 #, c-format msgid "name or argument lists may not contain nulls" msgstr "namn eller argumentlistor får inte innehålla null" -#: catalog/objectaddress.c:2161 +#: catalog/objectaddress.c:2123 #, c-format msgid "unsupported object type \"%s\"" msgstr "ej stöd för objekttyp \"%s\"" -#: catalog/objectaddress.c:2180 catalog/objectaddress.c:2197 -#: catalog/objectaddress.c:2262 catalog/objectaddress.c:2346 +#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 +#: catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 #, c-format msgid "name list length must be exactly %d" msgstr "namnlistlängen måste vara exakt %d" -#: catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2163 #, c-format msgid "large object OID may not be null" msgstr "stort objekt-OID får inte vara null" -#: catalog/objectaddress.c:2210 catalog/objectaddress.c:2280 -#: catalog/objectaddress.c:2287 +#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 +#: catalog/objectaddress.c:2249 #, c-format msgid "name list length must be at least %d" msgstr "namnlistlängden måste vara minst %d" -#: catalog/objectaddress.c:2273 catalog/objectaddress.c:2294 +#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 #, c-format msgid "argument list length must be exactly %d" msgstr "argumentlistans längd måste vara exakt %d" -#: catalog/objectaddress.c:2508 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 #, c-format msgid "must be owner of large object %u" msgstr "måste vara ägaren till stort objekt %u" -#: catalog/objectaddress.c:2523 commands/functioncmds.c:1561 +#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 #, c-format msgid "must be owner of type %s or type %s" msgstr "måste vara ägaren till typ %s eller typ %s" -#: catalog/objectaddress.c:2550 catalog/objectaddress.c:2559 -#: catalog/objectaddress.c:2565 +#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 +#: catalog/objectaddress.c:2527 #, c-format msgid "permission denied" msgstr "rättighet saknas" -#: catalog/objectaddress.c:2551 catalog/objectaddress.c:2560 +#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 #, c-format msgid "The current user must have the %s attribute." msgstr "Aktuella användaren måste ha attributet %s." -#: catalog/objectaddress.c:2566 +#: catalog/objectaddress.c:2528 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "Aktuella användaren måste ha flaggan %s på rollen \"%s\"." -#: catalog/objectaddress.c:2580 +#: catalog/objectaddress.c:2542 #, c-format msgid "must be superuser" msgstr "måste vara en superuser" -#: catalog/objectaddress.c:2649 +#: catalog/objectaddress.c:2611 #, c-format msgid "unrecognized object type \"%s\"" msgstr "okänd objekttyp \"%s\"" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2941 +#: catalog/objectaddress.c:2928 #, c-format msgid "column %s of %s" msgstr "kolumn %s av %s" -#: catalog/objectaddress.c:2956 +#: catalog/objectaddress.c:2943 #, c-format msgid "function %s" msgstr "funktion %s" -#: catalog/objectaddress.c:2969 +#: catalog/objectaddress.c:2956 #, c-format msgid "type %s" msgstr "typ %s" -#: catalog/objectaddress.c:3006 +#: catalog/objectaddress.c:2993 #, c-format msgid "cast from %s to %s" msgstr "typomvandling från %s till %s" -#: catalog/objectaddress.c:3039 +#: catalog/objectaddress.c:3026 #, c-format msgid "collation %s" msgstr "jämförelse %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3057 #, c-format msgid "constraint %s on %s" msgstr "villkor %s på %s" -#: catalog/objectaddress.c:3076 +#: catalog/objectaddress.c:3063 #, c-format msgid "constraint %s" msgstr "villkor %s" -#: catalog/objectaddress.c:3108 +#: catalog/objectaddress.c:3095 #, c-format msgid "conversion %s" msgstr "konvertering %s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3130 +#: catalog/objectaddress.c:3117 #, c-format msgid "default value for %s" msgstr "default-värde för %s" -#: catalog/objectaddress.c:3141 +#: catalog/objectaddress.c:3128 #, c-format msgid "language %s" msgstr "språk %s" -#: catalog/objectaddress.c:3149 +#: catalog/objectaddress.c:3136 #, c-format msgid "large object %u" msgstr "stort objekt %u" -#: catalog/objectaddress.c:3162 +#: catalog/objectaddress.c:3149 #, c-format msgid "operator %s" msgstr "operator %s" -#: catalog/objectaddress.c:3199 +#: catalog/objectaddress.c:3186 #, c-format msgid "operator class %s for access method %s" msgstr "operatorklass %s för accessmetod %s" -#: catalog/objectaddress.c:3227 +#: catalog/objectaddress.c:3214 #, c-format msgid "access method %s" msgstr "accessmetod %s" @@ -5152,7 +5494,7 @@ msgstr "accessmetod %s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3276 +#: catalog/objectaddress.c:3269 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "operator %d (%s, %s) för %s: %s" @@ -5161,236 +5503,236 @@ msgstr "operator %d (%s, %s) för %s: %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3333 +#: catalog/objectaddress.c:3334 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "funktion %d (%s, %s) för %s: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3385 +#: catalog/objectaddress.c:3388 #, c-format msgid "rule %s on %s" msgstr "regel %s på %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3431 +#: catalog/objectaddress.c:3434 #, c-format msgid "trigger %s on %s" msgstr "trigger %s på %s" -#: catalog/objectaddress.c:3451 +#: catalog/objectaddress.c:3454 #, c-format msgid "schema %s" msgstr "schema %s" -#: catalog/objectaddress.c:3479 +#: catalog/objectaddress.c:3482 #, c-format msgid "statistics object %s" msgstr "statistikobjekt %s" -#: catalog/objectaddress.c:3510 +#: catalog/objectaddress.c:3513 #, c-format msgid "text search parser %s" msgstr "textsökparser %s" -#: catalog/objectaddress.c:3541 +#: catalog/objectaddress.c:3544 #, c-format msgid "text search dictionary %s" msgstr "textsökordlista %s" -#: catalog/objectaddress.c:3572 +#: catalog/objectaddress.c:3575 #, c-format msgid "text search template %s" msgstr "textsökmall %s" -#: catalog/objectaddress.c:3603 +#: catalog/objectaddress.c:3606 #, c-format msgid "text search configuration %s" msgstr "textsökkonfiguration %s" -#: catalog/objectaddress.c:3616 +#: catalog/objectaddress.c:3619 #, c-format msgid "role %s" msgstr "roll %s" -#: catalog/objectaddress.c:3653 catalog/objectaddress.c:5505 +#: catalog/objectaddress.c:3656 catalog/objectaddress.c:5505 #, c-format msgid "membership of role %s in role %s" msgstr "medlemskap av rollen %s i rollen %s" -#: catalog/objectaddress.c:3674 +#: catalog/objectaddress.c:3677 #, c-format msgid "database %s" msgstr "databas %s" -#: catalog/objectaddress.c:3690 +#: catalog/objectaddress.c:3693 #, c-format msgid "tablespace %s" msgstr "tabellutrymme %s" -#: catalog/objectaddress.c:3701 +#: catalog/objectaddress.c:3704 #, c-format msgid "foreign-data wrapper %s" msgstr "främmande data-omvandlare %s" -#: catalog/objectaddress.c:3711 +#: catalog/objectaddress.c:3714 #, c-format msgid "server %s" msgstr "server %s" -#: catalog/objectaddress.c:3744 +#: catalog/objectaddress.c:3747 #, c-format msgid "user mapping for %s on server %s" msgstr "användarmappning för %s på server %s" -#: catalog/objectaddress.c:3796 +#: catalog/objectaddress.c:3799 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "standardrättigheter för nya relationer som tillhör rollen %s i schema %s" -#: catalog/objectaddress.c:3800 +#: catalog/objectaddress.c:3803 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "standardrättigheter för nya relationer som tillhör rollen %s" -#: catalog/objectaddress.c:3806 +#: catalog/objectaddress.c:3809 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "standardrättigheter för nya sekvenser som tillhör rollen %s i schema %s" -#: catalog/objectaddress.c:3810 +#: catalog/objectaddress.c:3813 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "standardrättigheter för nya sekvenser som tillhör rollen %s" -#: catalog/objectaddress.c:3816 +#: catalog/objectaddress.c:3819 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "standardrättigheter för nya funktioner som tillhör rollen %s i schema %s" -#: catalog/objectaddress.c:3820 +#: catalog/objectaddress.c:3823 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "standardrättigheter för nya funktioner som tillhör rollen %s" -#: catalog/objectaddress.c:3826 +#: catalog/objectaddress.c:3829 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "standardrättigheter för nya typer som tillhör rollen %s i schema %s" -#: catalog/objectaddress.c:3830 +#: catalog/objectaddress.c:3833 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "standardrättigheter för nya typer som tillhör rollen %s" -#: catalog/objectaddress.c:3836 +#: catalog/objectaddress.c:3839 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr " %zu)" msgstr "servern försöke skicka för stort GSSAPI-paket (%zu > %zu)" @@ -15235,810 +15692,810 @@ msgstr "kunde inte acceptera GSSSPI-säkerhetskontext" msgid "GSSAPI size check error" msgstr "GSSAPI-fel vid kontroll av storlek" -#: libpq/be-secure-openssl.c:125 +#: libpq/be-secure-openssl.c:131 #, c-format msgid "could not create SSL context: %s" msgstr "kunde inte skapa SSL-kontext: %s" -#: libpq/be-secure-openssl.c:151 +#: libpq/be-secure-openssl.c:157 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "kunde inte ladda serverns certifikatfil \"%s\": %s" -#: libpq/be-secure-openssl.c:171 +#: libpq/be-secure-openssl.c:177 #, c-format msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "privat nyckelfil \"%s\" kan inte laddas om eftersom den kräver en lösenordsfras" -#: libpq/be-secure-openssl.c:176 +#: libpq/be-secure-openssl.c:182 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "kunde inte läsa in privata nyckelfilen \"%s\": %s" -#: libpq/be-secure-openssl.c:185 +#: libpq/be-secure-openssl.c:191 #, c-format msgid "check of private key failed: %s" msgstr "kontroll av privat nyckel misslyckades: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:198 libpq/be-secure-openssl.c:221 +#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "\"%s\"-inställning \"%s\" stöds inte av detta bygge" -#: libpq/be-secure-openssl.c:208 +#: libpq/be-secure-openssl.c:214 #, c-format msgid "could not set minimum SSL protocol version" msgstr "kunde inte sätta minimal SSL-protokollversion" -#: libpq/be-secure-openssl.c:231 +#: libpq/be-secure-openssl.c:237 #, c-format msgid "could not set maximum SSL protocol version" msgstr "kunde inte sätta maximal SSL-protokollversion" -#: libpq/be-secure-openssl.c:247 +#: libpq/be-secure-openssl.c:253 #, c-format msgid "could not set SSL protocol version range" msgstr "kunde inte sätta SSL-protokollversionsintervall" -#: libpq/be-secure-openssl.c:248 +#: libpq/be-secure-openssl.c:254 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "\"%s\" får inte vara högre än \"%s\"" -#: libpq/be-secure-openssl.c:285 +#: libpq/be-secure-openssl.c:307 #, c-format msgid "could not set the cipher list (no valid ciphers available)" msgstr "kunde inte sätta kryptolistan (inga giltiga krypton är tillgängliga)" -#: libpq/be-secure-openssl.c:305 +#: libpq/be-secure-openssl.c:327 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "kunde inte ladda root-certifikatfilen \"%s\": %s" -#: libpq/be-secure-openssl.c:354 +#: libpq/be-secure-openssl.c:376 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "kunde inte ladda fil \"%s\" med certifikatåterkallningslista för SSL: %s" -#: libpq/be-secure-openssl.c:362 +#: libpq/be-secure-openssl.c:384 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "kunde inte ladda katalog \"%s\" för certifikatåterkallning: %s" -#: libpq/be-secure-openssl.c:370 +#: libpq/be-secure-openssl.c:392 #, c-format msgid "could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s" msgstr "kunde inte ladda fil \"%s\" eller katalog \"%s\" med certifikatåterkallning för SSL: %s" -#: libpq/be-secure-openssl.c:428 +#: libpq/be-secure-openssl.c:450 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "kunde inte initiera SSL-uppkoppling: SSL-kontex ej uppsatt" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:464 #, c-format msgid "could not initialize SSL connection: %s" msgstr "kunde inte initiera SSL-uppkoppling: %s" -#: libpq/be-secure-openssl.c:447 +#: libpq/be-secure-openssl.c:472 #, c-format msgid "could not set SSL socket: %s" msgstr "kunde inte sätta SSL-uttag (socket): %s" -#: libpq/be-secure-openssl.c:502 +#: libpq/be-secure-openssl.c:528 #, c-format msgid "could not accept SSL connection: %m" msgstr "kunde inte acceptera SSL-uppkoppling: %m" -#: libpq/be-secure-openssl.c:506 libpq/be-secure-openssl.c:561 +#: libpq/be-secure-openssl.c:532 libpq/be-secure-openssl.c:589 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "kunde inte starta SSL-anslutning: hittade EOF" -#: libpq/be-secure-openssl.c:545 +#: libpq/be-secure-openssl.c:573 #, c-format msgid "could not accept SSL connection: %s" msgstr "kunde inte acceptera SSL-uppkoppling: %s" -#: libpq/be-secure-openssl.c:549 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "This may indicate that the client does not support any SSL protocol version between %s and %s." msgstr "Detta kan tyda på att servern inte stöder någon SSL-protokolversion mellan %s och %s." -#: libpq/be-secure-openssl.c:566 libpq/be-secure-openssl.c:755 -#: libpq/be-secure-openssl.c:819 +#: libpq/be-secure-openssl.c:594 libpq/be-secure-openssl.c:809 +#: libpq/be-secure-openssl.c:879 #, c-format msgid "unrecognized SSL error code: %d" msgstr "okänd SSL-felkod: %d" -#: libpq/be-secure-openssl.c:612 +#: libpq/be-secure-openssl.c:622 +#, c-format +msgid "received SSL connection request with unexpected ALPN protocol" +msgstr "tog emot anslutningsförfrågan för SSL med oväntat ALPN-protokoll" + +#: libpq/be-secure-openssl.c:666 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "SSL-certifikatets \"comman name\" innehåller null-värden" -#: libpq/be-secure-openssl.c:658 +#: libpq/be-secure-openssl.c:712 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "SSL-certifikatets utskiljande namn innehåller null-värden" -#: libpq/be-secure-openssl.c:744 libpq/be-secure-openssl.c:803 +#: libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:863 #, c-format msgid "SSL error: %s" msgstr "SSL-fel: %s" -#: libpq/be-secure-openssl.c:985 +#: libpq/be-secure-openssl.c:1038 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "kunde inte öppna DH-parameterfil \"%s\": %m" -#: libpq/be-secure-openssl.c:997 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not load DH parameters file: %s" msgstr "kunde inte ladda DH-parameterfil: %s" -#: libpq/be-secure-openssl.c:1007 +#: libpq/be-secure-openssl.c:1060 #, c-format msgid "invalid DH parameters: %s" msgstr "ogiltiga DH-parametrar: %s" -#: libpq/be-secure-openssl.c:1016 +#: libpq/be-secure-openssl.c:1069 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "ogiltiga DH-parametrar: p är inte ett primtal" -#: libpq/be-secure-openssl.c:1025 +#: libpq/be-secure-openssl.c:1078 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "ogiltiga DH-parametrar: varken lämplig generator eller säkert primtal" -#: libpq/be-secure-openssl.c:1161 +#: libpq/be-secure-openssl.c:1214 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "Klientcertifikat-autentisering misslyckades vid djupet %d: %s." -#: libpq/be-secure-openssl.c:1198 +#: libpq/be-secure-openssl.c:1251 #, c-format msgid "Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"." msgstr "Felaktig certifikatdata (ej verifierad): ämne \"%s\", serienummer %s, utställare \"%s\"." -#: libpq/be-secure-openssl.c:1199 +#: libpq/be-secure-openssl.c:1252 msgid "unknown" msgstr "okänd" -#: libpq/be-secure-openssl.c:1290 +#: libpq/be-secure-openssl.c:1389 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: kunde inte ladda DH-parametrar" -#: libpq/be-secure-openssl.c:1298 +#: libpq/be-secure-openssl.c:1397 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: kunde inte sätta DH-parametrar: %s" -#: libpq/be-secure-openssl.c:1325 +#: libpq/be-secure-openssl.c:1424 #, c-format msgid "ECDH: unrecognized curve name: %s" msgstr "ECDH: okänt kurvnamn: %s" -#: libpq/be-secure-openssl.c:1334 +#: libpq/be-secure-openssl.c:1433 #, c-format msgid "ECDH: could not create key" msgstr "ECDH: kunde inte skapa nyckel" -#: libpq/be-secure-openssl.c:1362 +#: libpq/be-secure-openssl.c:1461 msgid "no SSL error reported" msgstr "inget SSL-fel rapporterat" -#: libpq/be-secure-openssl.c:1366 +#: libpq/be-secure-openssl.c:1479 #, c-format msgid "SSL error code %lu" msgstr "SSL-felkod %lu" -#: libpq/be-secure-openssl.c:1525 +#: libpq/be-secure-openssl.c:1636 #, c-format msgid "could not create BIO" msgstr "kunde inte skapa BIO" -#: libpq/be-secure-openssl.c:1535 +#: libpq/be-secure-openssl.c:1646 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "kunde inte hämta NID för ASN1_OBJECT-objekt" -#: libpq/be-secure-openssl.c:1543 +#: libpq/be-secure-openssl.c:1654 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "kunde inte konvertera NID %d till en ASN1_OBJECT-struktur" -#: libpq/be-secure.c:207 libpq/be-secure.c:303 -#, c-format -msgid "terminating connection due to unexpected postmaster exit" -msgstr "avslutar anslutning på grund av att postmaster stängde oväntat ner" - -#: libpq/crypt.c:49 +#: libpq/crypt.c:48 #, c-format msgid "Role \"%s\" does not exist." msgstr "Rollen \"%s\" finns inte." -#: libpq/crypt.c:59 +#: libpq/crypt.c:58 #, c-format msgid "User \"%s\" has no password assigned." msgstr "Användaren \"%s\" har inget lösenord satt." -#: libpq/crypt.c:77 +#: libpq/crypt.c:76 #, c-format msgid "User \"%s\" has an expired password." msgstr "Användaren \"%s\" har ett utgånget lösenord." -#: libpq/crypt.c:183 +#: libpq/crypt.c:182 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "Användaren \"%s\" har ett lösenord som inte kan användas med MD5-autentisering." -#: libpq/crypt.c:204 libpq/crypt.c:246 libpq/crypt.c:266 +#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 #, c-format msgid "Password does not match for user \"%s\"." msgstr "Lösenordet matchar inte för användare \"%s\"." -#: libpq/crypt.c:285 +#: libpq/crypt.c:284 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "Lösenordet för användare \"%s\" är på ett okänt format." -#: libpq/hba.c:332 +#: libpq/hba.c:327 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "ogiltigt reguljärt uttryck \"%s\": %s" -#: libpq/hba.c:334 libpq/hba.c:666 libpq/hba.c:1250 libpq/hba.c:1270 -#: libpq/hba.c:1293 libpq/hba.c:1306 libpq/hba.c:1359 libpq/hba.c:1387 -#: libpq/hba.c:1395 libpq/hba.c:1407 libpq/hba.c:1428 libpq/hba.c:1441 -#: libpq/hba.c:1466 libpq/hba.c:1493 libpq/hba.c:1505 libpq/hba.c:1564 -#: libpq/hba.c:1584 libpq/hba.c:1598 libpq/hba.c:1618 libpq/hba.c:1629 -#: libpq/hba.c:1644 libpq/hba.c:1663 libpq/hba.c:1679 libpq/hba.c:1691 -#: libpq/hba.c:1728 libpq/hba.c:1769 libpq/hba.c:1782 libpq/hba.c:1804 -#: libpq/hba.c:1816 libpq/hba.c:1834 libpq/hba.c:1884 libpq/hba.c:1928 -#: libpq/hba.c:1939 libpq/hba.c:1955 libpq/hba.c:1972 libpq/hba.c:1983 -#: libpq/hba.c:2002 libpq/hba.c:2018 libpq/hba.c:2034 libpq/hba.c:2093 -#: libpq/hba.c:2110 libpq/hba.c:2123 libpq/hba.c:2135 libpq/hba.c:2154 -#: libpq/hba.c:2240 libpq/hba.c:2258 libpq/hba.c:2352 libpq/hba.c:2371 -#: libpq/hba.c:2400 libpq/hba.c:2413 libpq/hba.c:2436 libpq/hba.c:2458 -#: libpq/hba.c:2472 tsearch/ts_locale.c:243 +#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 +#: libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 +#: libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 +#: libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 +#: libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 +#: libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 +#: libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 libpq/hba.c:1799 +#: libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 +#: libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 +#: libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 +#: libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 +#: libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 +#: libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 +#: tsearch/ts_locale.c:241 #, c-format msgid "line %d of configuration file \"%s\"" msgstr "rad %d i konfigurationsfil \"%s\"" -#: libpq/hba.c:462 +#: libpq/hba.c:457 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "hoppar över saknad autentiseringsfil \"%s\"" -#: libpq/hba.c:614 +#: libpq/hba.c:609 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "kunde inte öppna filen \"%s\": maximalt nästlingsdjup överskridet" -#: libpq/hba.c:1221 +#: libpq/hba.c:1216 #, c-format msgid "error enumerating network interfaces: %m" msgstr "fel vid uppräkning av nätverksinterface: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1248 +#: libpq/hba.c:1243 #, c-format msgid "authentication option \"%s\" is only valid for authentication methods %s" msgstr "autentiseringsflagga \"%s\" är bara giltig för autentiseringsmetoder %s" -#: libpq/hba.c:1268 +#: libpq/hba.c:1263 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "autentiseringsmetod \"%s\" kräver att argumentet \"%s\" är satt" -#: libpq/hba.c:1292 +#: libpq/hba.c:1287 #, c-format msgid "missing entry at end of line" msgstr "saknar post vid slutet av raden" -#: libpq/hba.c:1305 +#: libpq/hba.c:1300 #, c-format msgid "multiple values in ident field" msgstr "multipla värden i ident-fält" -#: libpq/hba.c:1357 +#: libpq/hba.c:1352 #, c-format msgid "multiple values specified for connection type" msgstr "multipla värden angivna för anslutningstyp" -#: libpq/hba.c:1358 +#: libpq/hba.c:1353 #, c-format msgid "Specify exactly one connection type per line." msgstr "Ange exakt en anslutningstyp per rad." -#: libpq/hba.c:1385 +#: libpq/hba.c:1380 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "hostssl-post kan inte matcha då SSL är avslaget" -#: libpq/hba.c:1386 +#: libpq/hba.c:1381 #, c-format -msgid "Set ssl = on in postgresql.conf." -msgstr "Sätt ssl = on i postgresql.conf." +msgid "Set \"ssl = on\" in postgresql.conf." +msgstr "Sätt \"ssl = on\" i postgresql.conf." -#: libpq/hba.c:1394 +#: libpq/hba.c:1389 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "hostssl-post kan inte matcha då SSL inte stöds i detta bygge" -#: libpq/hba.c:1406 +#: libpq/hba.c:1401 #, c-format msgid "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "hostgssenc-post kan inte matcha då GSSAPI inte stöds i detta bygge" -#: libpq/hba.c:1426 +#: libpq/hba.c:1421 #, c-format msgid "invalid connection type \"%s\"" msgstr "ogiltig anslutningstyp \"%s\"" -#: libpq/hba.c:1440 +#: libpq/hba.c:1435 #, c-format msgid "end-of-line before database specification" msgstr "slut-på-rad innan databasspecifikation" -#: libpq/hba.c:1465 +#: libpq/hba.c:1460 #, c-format msgid "end-of-line before role specification" msgstr "slut-på-rad innan rollspecifikation" -#: libpq/hba.c:1492 +#: libpq/hba.c:1487 #, c-format msgid "end-of-line before IP address specification" msgstr "slut-på-rad före IP-adressangivelse" -#: libpq/hba.c:1503 +#: libpq/hba.c:1498 #, c-format msgid "multiple values specified for host address" msgstr "multipla värden angivna för värdnamn" -#: libpq/hba.c:1504 +#: libpq/hba.c:1499 #, c-format msgid "Specify one address range per line." msgstr "Ange ett adressintervall per rad." -#: libpq/hba.c:1562 +#: libpq/hba.c:1557 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "ogiltig IP-adress \"%s\": %s" -#: libpq/hba.c:1582 +#: libpq/hba.c:1577 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "får inte ange både värdnamn och CIDR-mask: \"%s\"" -#: libpq/hba.c:1596 +#: libpq/hba.c:1591 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "ogiltig CIDR-mask i adress \"%s\"" -#: libpq/hba.c:1616 +#: libpq/hba.c:1611 #, c-format msgid "end-of-line before netmask specification" msgstr "slut-på-fil innan nätmask-angivelse" -#: libpq/hba.c:1617 +#: libpq/hba.c:1612 #, c-format msgid "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "Ange adressintervall på CIDR-format eller ange en separat nätmask." -#: libpq/hba.c:1628 +#: libpq/hba.c:1623 #, c-format msgid "multiple values specified for netmask" msgstr "multipla värden angivna för nätmask" -#: libpq/hba.c:1642 +#: libpq/hba.c:1637 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "ogiltig IP-mask \"%s\": %s" -#: libpq/hba.c:1662 +#: libpq/hba.c:1657 #, c-format msgid "IP address and mask do not match" msgstr "IP-adress och mask matchar inte varandra" -#: libpq/hba.c:1678 +#: libpq/hba.c:1673 #, c-format msgid "end-of-line before authentication method" msgstr "slut-på-rad innan autentiseringsmetod" -#: libpq/hba.c:1689 +#: libpq/hba.c:1684 #, c-format msgid "multiple values specified for authentication type" msgstr "multipla värden angivna för autentiseringstyp" -#: libpq/hba.c:1690 +#: libpq/hba.c:1685 #, c-format msgid "Specify exactly one authentication type per line." msgstr "Ange exakt en autentiseringstyp per rad." -#: libpq/hba.c:1767 +#: libpq/hba.c:1750 #, c-format msgid "invalid authentication method \"%s\"" msgstr "ogiltig autentiseringsmetod \"%s\"" -#: libpq/hba.c:1780 +#: libpq/hba.c:1763 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "ogiltig autentiseringsmetod \"%s\": stöds inte av detta bygge" -#: libpq/hba.c:1803 +#: libpq/hba.c:1786 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "gssapi-autentisering stöds ej på lokala uttag (socket)" -#: libpq/hba.c:1815 +#: libpq/hba.c:1798 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "peer-autentisering stöds bara på logala uttag (socket)" -#: libpq/hba.c:1833 +#: libpq/hba.c:1816 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "cert-autentisering stöds bara för hostssl-anslutningar" -#: libpq/hba.c:1883 +#: libpq/hba.c:1866 #, c-format msgid "authentication option not in name=value format: %s" msgstr "autentiseringsflagga et på formatet namn=värde: %s" -#: libpq/hba.c:1927 +#: libpq/hba.c:1910 #, c-format msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" msgstr "kan inte använda ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter eller ldapurl tillsammans med ldapprefix" -#: libpq/hba.c:1938 +#: libpq/hba.c:1921 #, c-format msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "autentiseringsmetoden \"ldap\" kräver att argumenten \"ldapbasedn\", \"ldapprefix\" eller \"ldapsuffix\" är satta" -#: libpq/hba.c:1954 +#: libpq/hba.c:1937 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "kan inte använda ldapsearchattribute tillsammans med ldapsearchfilter" -#: libpq/hba.c:1971 +#: libpq/hba.c:1954 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "listan med RADIUS-servrar kan inte vara tom" -#: libpq/hba.c:1982 +#: libpq/hba.c:1965 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "listan med RADIUS-hemligheter kan inte vara tom" -#: libpq/hba.c:1999 +#: libpq/hba.c:1982 #, c-format msgid "the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "antalet RADIUS-hemligheter (%d) måste vara 1 eller samma som antalet RADIUS-servrar (%d)" -#: libpq/hba.c:2015 +#: libpq/hba.c:1998 #, c-format msgid "the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "antalet RADIUS-portar (%d) måste vara 1 eller samma som antalet RADIUS-servrar (%d)" -#: libpq/hba.c:2031 +#: libpq/hba.c:2014 #, c-format msgid "the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "antalet RADIUS-identifierare (%d) måste vara 1 eller samma som antalet RADIUS-servrar (%d)" -#: libpq/hba.c:2083 +#: libpq/hba.c:2066 msgid "ident, peer, gssapi, sspi, and cert" msgstr "ident, peer, gssapi, sspi och cert" -#: libpq/hba.c:2092 +#: libpq/hba.c:2075 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert kan bara konfigureras för \"hostssl\"-rader" -#: libpq/hba.c:2109 +#: libpq/hba.c:2092 #, c-format msgid "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "clientcert tillåter bara \"verify-full\" när man använder \"cert\"-autentisering" -#: libpq/hba.c:2122 +#: libpq/hba.c:2105 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "ogiltigt värde för clientcert: \"%s\"" -#: libpq/hba.c:2134 +#: libpq/hba.c:2117 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname kan bara konfigureras för \"hostssl\"-rader" -#: libpq/hba.c:2153 +#: libpq/hba.c:2136 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "ogiltigt värde för clientname: \"%s\"" -#: libpq/hba.c:2186 +#: libpq/hba.c:2169 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "kunde inte parsa LDAP-URL \"%s\": %s" -#: libpq/hba.c:2197 +#: libpq/hba.c:2180 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "ej stöd för LDAP-URL-schema: %s" -#: libpq/hba.c:2221 +#: libpq/hba.c:2204 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "LDAP-URL:er stöds inte på denna platform" -#: libpq/hba.c:2239 +#: libpq/hba.c:2222 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "ogiltigt ldap-schema-värde: \"%s\"" -#: libpq/hba.c:2257 +#: libpq/hba.c:2240 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "ogiltigt LDAP-portnummer \"%s\"" -#: libpq/hba.c:2303 libpq/hba.c:2310 +#: libpq/hba.c:2286 libpq/hba.c:2293 msgid "gssapi and sspi" msgstr "gssapi och sspi" -#: libpq/hba.c:2319 libpq/hba.c:2328 +#: libpq/hba.c:2302 libpq/hba.c:2311 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2350 +#: libpq/hba.c:2333 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "kunde inte parsa RADIUS-serverlista \"%s\"" -#: libpq/hba.c:2398 +#: libpq/hba.c:2381 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "kunde inte parsa RADIUS-portlista \"%s\"" -#: libpq/hba.c:2412 +#: libpq/hba.c:2395 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "ogiltigt RADIUS-portnummer: \"%s\"" -#: libpq/hba.c:2434 +#: libpq/hba.c:2417 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "kunde inte parsa RADIUS-hemlighetlista: \"%s\"" -#: libpq/hba.c:2456 +#: libpq/hba.c:2439 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "kunde inte parsa RADIUS-identifierarlista: \"%s\"" -#: libpq/hba.c:2470 +#: libpq/hba.c:2453 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "okänd autentiseringsflaggnamn: \"%s\"" -#: libpq/hba.c:2662 +#: libpq/hba.c:2645 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "konfigurationsfil \"%s\" innehåller inga poster" -#: libpq/hba.c:2815 +#: libpq/hba.c:2798 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "matchning av reguljärt uttryck för \"%s\" misslyckades: %s" -#: libpq/hba.c:2839 +#: libpq/hba.c:2822 #, c-format msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"" msgstr "reguljärt uttryck \"%s\" har inga deluttryck som krävs för bakåtreferens i \"%s\"" -#: libpq/hba.c:2942 +#: libpq/hba.c:2925 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "givet användarnamn (%s) och autentiserat användarnamn (%s) matchar inte" -#: libpq/hba.c:2962 +#: libpq/hba.c:2945 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "ingen träff i användarmappning \"%s\" för användare \"%s\" autentiserad som \"%s\"" -#: libpq/pqcomm.c:200 +#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 +#: libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 +#: libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 +#: libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#, c-format +msgid "%s(%s) failed: %m" +msgstr "%s(%s) misslyckades: %m" + +#: libpq/pqcomm.c:296 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "kunde inte sätta uttag (socket) till ickeblockerande läge: %m" -#: libpq/pqcomm.c:361 +#: libpq/pqcomm.c:456 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Sökväg till unixdomänuttag \"%s\" är för lång (maximalt %d byte)" -#: libpq/pqcomm.c:381 +#: libpq/pqcomm.c:476 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "kunde inte översätta värdnamn \"%s\", service \"%s\" till adress: %s" -#: libpq/pqcomm.c:385 +#: libpq/pqcomm.c:480 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "kunde inte översätta service \"%s\" till adress: %s" -#: libpq/pqcomm.c:412 +#: libpq/pqcomm.c:502 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "kunde inte binda till alla efterfrågade adresser: MAXLISTEN (%d) överskriden" -#: libpq/pqcomm.c:421 +#: libpq/pqcomm.c:511 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:424 +#: libpq/pqcomm.c:514 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:427 +#: libpq/pqcomm.c:517 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:431 +#: libpq/pqcomm.c:521 #, c-format msgid "unrecognized address family %d" msgstr "ej igenkänd adressfamilj %d" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:455 +#: libpq/pqcomm.c:545 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "kunde inte skapa %s-uttag för adress \"%s\": %m" #. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:481 libpq/pqcomm.c:499 +#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%s(%s) misslyckades för %s-adress \"%s\": %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:522 +#: libpq/pqcomm.c:615 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "kunde inte binda %s-adress \"%s\": %m" -#: libpq/pqcomm.c:526 +#: libpq/pqcomm.c:619 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "Kör en annan postmaster redan på port %d?" -#: libpq/pqcomm.c:528 +#: libpq/pqcomm.c:621 #, c-format msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry." msgstr "Kör en annan postmaster redan på port %d? Om inte, vänta några sekunder och försök igen." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:557 +#: libpq/pqcomm.c:650 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "kunde inte lyssna på %s-adress \"%s\": %m" -#: libpq/pqcomm.c:565 +#: libpq/pqcomm.c:658 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "lyssnar på Unix-uttag (socket) \"%s\"" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:570 +#: libpq/pqcomm.c:663 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "lyssnar på %s-adress \"%s\", port %d" -#: libpq/pqcomm.c:659 +#: libpq/pqcomm.c:753 #, c-format msgid "group \"%s\" does not exist" msgstr "gruppen \"%s\" existerar inte" -#: libpq/pqcomm.c:669 +#: libpq/pqcomm.c:763 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "kunde inte sätta gruppen på filen \"%s\": %m" -#: libpq/pqcomm.c:680 +#: libpq/pqcomm.c:774 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "kunde inte sätta rättigheter på filen \"%s\": %m" -#: libpq/pqcomm.c:708 +#: libpq/pqcomm.c:803 #, c-format msgid "could not accept new connection: %m" msgstr "kunde inte acceptera ny uppkoppling: %m" -#: libpq/pqcomm.c:748 libpq/pqcomm.c:757 libpq/pqcomm.c:789 libpq/pqcomm.c:799 -#: libpq/pqcomm.c:1624 libpq/pqcomm.c:1669 libpq/pqcomm.c:1709 -#: libpq/pqcomm.c:1753 libpq/pqcomm.c:1792 libpq/pqcomm.c:1831 -#: libpq/pqcomm.c:1867 libpq/pqcomm.c:1906 -#, c-format -msgid "%s(%s) failed: %m" -msgstr "%s(%s) misslyckades: %m" - -#: libpq/pqcomm.c:903 +#: libpq/pqcomm.c:885 #, c-format msgid "there is no client connection" msgstr "det finns ingen klientanslutning" -#: libpq/pqcomm.c:954 libpq/pqcomm.c:1050 +#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 #, c-format msgid "could not receive data from client: %m" msgstr "kunde inte ta emot data från klient: %m" -#: libpq/pqcomm.c:1155 tcop/postgres.c:4405 +#: libpq/pqcomm.c:1149 tcop/postgres.c:4533 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "stänger anslutning då protokollsynkroniseringen tappades" -#: libpq/pqcomm.c:1221 +#: libpq/pqcomm.c:1215 #, c-format msgid "unexpected EOF within message length word" msgstr "oväntat EOF inom meddelandelängdord" -#: libpq/pqcomm.c:1231 +#: libpq/pqcomm.c:1225 #, c-format msgid "invalid message length" msgstr "ogiltig meddelandelängd" -#: libpq/pqcomm.c:1253 libpq/pqcomm.c:1266 +#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 #, c-format msgid "incomplete message from client" msgstr "inkomplett meddelande från klient" -#: libpq/pqcomm.c:1377 +#: libpq/pqcomm.c:1401 #, c-format msgid "could not send data to client: %m" msgstr "kunde inte skicka data till klient: %m" -#: libpq/pqcomm.c:1592 +#: libpq/pqcomm.c:1616 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) misslyckades: felkod %d" -#: libpq/pqcomm.c:1681 +#: libpq/pqcomm.c:1705 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "sätta idle-tid på keepalive stöds inte" -#: libpq/pqcomm.c:1765 libpq/pqcomm.c:1840 libpq/pqcomm.c:1915 +#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s) stöds inte" -#: libpq/pqformat.c:407 +#: libpq/pqformat.c:404 #, c-format msgid "no data left in message" msgstr "ingen data kvar i meddelandet" -#: libpq/pqformat.c:518 libpq/pqformat.c:536 libpq/pqformat.c:557 -#: utils/adt/array_userfuncs.c:799 utils/adt/arrayfuncs.c:1506 -#: utils/adt/rowtypes.c:615 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 +#: utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 +#: utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "otillräckligt med data kvar i meddelande" -#: libpq/pqformat.c:598 libpq/pqformat.c:627 +#: libpq/pqformat.c:595 libpq/pqformat.c:624 #, c-format msgid "invalid string in message" msgstr "ogiltig sträng i meddelande" -#: libpq/pqformat.c:643 +#: libpq/pqformat.c:640 #, c-format msgid "invalid message format" msgstr "ogiltigt meddelandeformat" -#: main/main.c:235 +#: main/main.c:236 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: WSAStartup misslyckades: %d\n" -#: main/main.c:329 +#: main/main.c:324 #, c-format msgid "" "%s is the PostgreSQL server.\n" @@ -16047,7 +16504,7 @@ msgstr "" "%s är PostgreSQL-servern.\n" "\n" -#: main/main.c:330 +#: main/main.c:325 #, c-format msgid "" "Usage:\n" @@ -16058,107 +16515,107 @@ msgstr "" " %s [FLAGGA]...\n" "\n" -#: main/main.c:331 +#: main/main.c:326 #, c-format msgid "Options:\n" msgstr "Flaggor:\n" -#: main/main.c:332 +#: main/main.c:327 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS antalet delade buffertar\n" -#: main/main.c:333 +#: main/main.c:328 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c NAMN=VÄRDE sätt körparameter\n" -#: main/main.c:334 +#: main/main.c:329 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C NAMN skriv ut värde av runtime-parameter, avsluta sen\n" -#: main/main.c:335 +#: main/main.c:330 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 debug-nivå\n" -#: main/main.c:336 +#: main/main.c:331 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR databaskatalog\n" -#: main/main.c:337 +#: main/main.c:332 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e använd europeiskt datumformat för indata (DMY)\n" -#: main/main.c:338 +#: main/main.c:333 #, c-format msgid " -F turn fsync off\n" msgstr " -F slå av fsync\n" -#: main/main.c:339 +#: main/main.c:334 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h VÄRDNAMN värdnamn eller IP-adress att lyssna på\n" -#: main/main.c:340 +#: main/main.c:335 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr " -i tillåt TCP/IP-uppkopplingar (obsolet)\n" -#: main/main.c:341 +#: main/main.c:336 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k KATALOG plats för unix-domän-uttag (socket)\n" -#: main/main.c:343 +#: main/main.c:338 #, c-format msgid " -l enable SSL connections\n" msgstr " -l tillåt SSL-anslutningar\n" -#: main/main.c:345 +#: main/main.c:340 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N MAX-ANSLUT maximalt antal tillåtna anslutningar\n" -#: main/main.c:346 +#: main/main.c:341 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p PORT portnummer att lyssna på\n" -#: main/main.c:347 +#: main/main.c:342 #, c-format msgid " -s show statistics after each query\n" msgstr " -s visa statistik efter varje fråga\n" -#: main/main.c:348 +#: main/main.c:343 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S WORK-MEM ställ in mängden minne för sorteringar (i kB)\n" -#: main/main.c:349 +#: main/main.c:344 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: main/main.c:350 +#: main/main.c:345 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --NAMN=VÄRDE sätt parameter (som används under körning)\n" -#: main/main.c:351 +#: main/main.c:346 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config beskriv konfigurationsparametrar, avsluta sedan\n" -#: main/main.c:352 +#: main/main.c:347 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: main/main.c:354 +#: main/main.c:349 #, c-format msgid "" "\n" @@ -16167,37 +16624,37 @@ msgstr "" "\n" "Utvecklarflaggor:\n" -#: main/main.c:355 +#: main/main.c:350 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h förbjud användning av vissa plan-typer\n" -#: main/main.c:356 +#: main/main.c:351 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O tillåt strukturändring av systemtabeller\n" -#: main/main.c:357 +#: main/main.c:352 #, c-format msgid " -P disable system indexes\n" msgstr " -P stäng av systemindex\n" -#: main/main.c:358 +#: main/main.c:353 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex visa tidtagning efter varje fråga\n" -#: main/main.c:359 +#: main/main.c:354 #, c-format msgid " -T send SIGABRT to all backend processes if one dies\n" msgstr " -T skicka SIGABRT till alla serverprocesser om en dör\n" -#: main/main.c:360 +#: main/main.c:355 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr " -W NUM vänta NUM sekunder för att tillåta att en debugger kopplas in\n" -#: main/main.c:362 +#: main/main.c:357 #, c-format msgid "" "\n" @@ -16206,37 +16663,37 @@ msgstr "" "\n" "Flaggor för enanvändarläge:\n" -#: main/main.c:363 +#: main/main.c:358 #, c-format msgid " --single selects single-user mode (must be first argument)\n" msgstr " --single väljer enanvändarläge (måste vara första argumentet)\n" -#: main/main.c:364 +#: main/main.c:359 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAMN databasnamn (standard är användarnamnet)\n" -#: main/main.c:365 +#: main/main.c:360 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 överskugga debug-nivå\n" -#: main/main.c:366 +#: main/main.c:361 #, c-format msgid " -E echo statement before execution\n" msgstr " -E skriv ut sats före körning\n" -#: main/main.c:367 +#: main/main.c:362 #, c-format msgid " -j do not use newline as interactive query delimiter\n" msgstr " -j använd inte nyrad som en interaktiv frågeavskiljare\n" -#: main/main.c:368 main/main.c:374 +#: main/main.c:363 main/main.c:369 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r FILNAMN skicka stdout och stderr till angiven fil\n" -#: main/main.c:370 +#: main/main.c:365 #, c-format msgid "" "\n" @@ -16245,22 +16702,22 @@ msgstr "" "\n" "Flaggor för bootstrap-läge:\n" -#: main/main.c:371 +#: main/main.c:366 #, c-format msgid " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot väljer bootstrap-läge (måste vara första argumentet)\n" -#: main/main.c:372 +#: main/main.c:367 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr " --check väljer kontrolläge (måste vara första argumentet)\n" -#: main/main.c:373 +#: main/main.c:368 #, c-format msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n" msgstr " DBNAMN databasnamn (krävs i bootstrap-läge)\n" -#: main/main.c:376 +#: main/main.c:371 #, c-format msgid "" "\n" @@ -16276,12 +16733,12 @@ msgstr "" "\n" "Rapportera buggar till <%s>.\n" -#: main/main.c:380 +#: main/main.c:375 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: main/main.c:391 +#: main/main.c:386 #, c-format msgid "" "\"root\" execution of the PostgreSQL server is not permitted.\n" @@ -16294,12 +16751,12 @@ msgstr "" "ev. säkehetsproblem. Se dokumentationen för mer information om hur man\n" "startar servern på rätt sätt.\n" -#: main/main.c:408 +#: main/main.c:403 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: riktig och effektiv användar-ID måste matcha varandra\n" -#: main/main.c:415 +#: main/main.c:410 #, c-format msgid "" "Execution of PostgreSQL by a user with administrative permissions is not\n" @@ -16324,20 +16781,15 @@ msgstr "utökningsbar nodtyp \"%s\" finns redan" msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "ExtensibleNodeMethods \"%s\" har inte registerats" -#: nodes/makefuncs.c:153 statistics/extended_stats.c:2335 +#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "relationen \"%s\" har ingen composite-typ" -#: nodes/makefuncs.c:879 -#, c-format -msgid "unrecognized JSON encoding: %s" -msgstr "okänd JSON-kodning: %s" - -#: nodes/nodeFuncs.c:116 nodes/nodeFuncs.c:147 parser/parse_coerce.c:2567 -#: parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 -#: parser/parse_expr.c:2049 parser/parse_func.c:710 parser/parse_oper.c:883 -#: utils/fmgr/funcapi.c:661 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2604 +#: parser/parse_coerce.c:2742 parser/parse_coerce.c:2789 +#: parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 +#: utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "kunde inte hitta array-typ för datatyp %s" @@ -16352,931 +16804,936 @@ msgstr "portal \"%s\" med parametrar: %s" msgid "unnamed portal with parameters: %s" msgstr "ej namngiven portal med parametrar: %s" -#: optimizer/path/joinrels.c:973 +#: optimizer/path/joinrels.c:972 #, c-format msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions" msgstr "FULL JOIN stöds bara med villkor som är merge-joinbara eller hash-joinbara" -#: optimizer/plan/createplan.c:7111 parser/parse_merge.c:182 -#: parser/parse_merge.c:189 +#: optimizer/plan/createplan.c:7175 parser/parse_merge.c:203 +#: rewrite/rewriteHandler.c:1680 #, c-format msgid "cannot execute MERGE on relation \"%s\"" msgstr "kan inte utföra MERGE på relation \"%s\"" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1408 +#: optimizer/plan/initsplan.c:1407 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "%s kan inte appliceras på den nullbara sidan av en outer join" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1361 parser/analyze.c:1761 parser/analyze.c:2018 -#: parser/analyze.c:3231 +#: optimizer/plan/planner.c:1380 parser/analyze.c:1771 parser/analyze.c:2029 +#: parser/analyze.c:3247 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s tillåts inte med UNION/INTERSECT/EXCEPT" -#: optimizer/plan/planner.c:2082 optimizer/plan/planner.c:4040 +#: optimizer/plan/planner.c:2121 optimizer/plan/planner.c:4108 #, c-format msgid "could not implement GROUP BY" msgstr "kunde inte implementera GROUP BY" -#: optimizer/plan/planner.c:2083 optimizer/plan/planner.c:4041 -#: optimizer/plan/planner.c:4681 optimizer/prep/prepunion.c:1053 +#: optimizer/plan/planner.c:2122 optimizer/plan/planner.c:4109 +#: optimizer/plan/planner.c:4790 optimizer/prep/prepunion.c:1320 #, c-format msgid "Some of the datatypes only support hashing, while others only support sorting." msgstr "Några av datatyperna stöder bara hash:ning medan andra bara stöder sortering." -#: optimizer/plan/planner.c:4680 +#: optimizer/plan/planner.c:4789 #, c-format msgid "could not implement DISTINCT" msgstr "kunde inte implementera DISTINCT" -#: optimizer/plan/planner.c:6019 +#: optimizer/plan/planner.c:6134 #, c-format msgid "could not implement window PARTITION BY" msgstr "kunde inte implementera fönster-PARTITION BY" -#: optimizer/plan/planner.c:6020 +#: optimizer/plan/planner.c:6135 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "Fönsterpartitioneringskolumner måsta ha en sorterbar datatyp." -#: optimizer/plan/planner.c:6024 +#: optimizer/plan/planner.c:6139 #, c-format msgid "could not implement window ORDER BY" msgstr "kunde inte implementera fönster-ORDER BY" -#: optimizer/plan/planner.c:6025 +#: optimizer/plan/planner.c:6140 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "Fönsterordningskolumner måste ha en sorterbar datatyp." -#: optimizer/prep/prepunion.c:516 +#: optimizer/prep/prepunion.c:467 #, c-format msgid "could not implement recursive UNION" msgstr "kunde inte implementera rekursiv UNION" -#: optimizer/prep/prepunion.c:517 +#: optimizer/prep/prepunion.c:468 #, c-format msgid "All column datatypes must be hashable." msgstr "Alla kolumndatatyper måsta vara hash-bara." #. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1052 +#: optimizer/prep/prepunion.c:1319 #, c-format msgid "could not implement %s" msgstr "kunde inte implementera %s" -#: optimizer/util/clauses.c:4856 +#: optimizer/util/clauses.c:4963 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "SQL-funktion \"%s\" vid inline:ing" -#: optimizer/util/plancat.c:154 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "kan inte accessa temporära eller ologgade relationer under återställning" -#: optimizer/util/plancat.c:726 +#: optimizer/util/plancat.c:768 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "inferens av unikt index för hel rad stöds inte" -#: optimizer/util/plancat.c:743 +#: optimizer/util/plancat.c:785 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "villkor för ON CONFLICT-klausul har inget associerat index" -#: optimizer/util/plancat.c:793 +#: optimizer/util/plancat.c:835 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATE stöds inte med uteslutningsvillkor" -#: optimizer/util/plancat.c:898 +#: optimizer/util/plancat.c:945 #, c-format msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification" msgstr "finns inget unik eller uteslutningsvillkor som matchar ON CONFLICT-specifikationen" -#: parser/analyze.c:826 parser/analyze.c:1540 +#: parser/analyze.c:824 parser/analyze.c:1550 #, c-format msgid "VALUES lists must all be the same length" msgstr "VÄRDE-listor måste alla ha samma längd" -#: parser/analyze.c:1028 +#: parser/analyze.c:1027 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT har fler uttryck än målkolumner" -#: parser/analyze.c:1046 +#: parser/analyze.c:1045 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERT har fler målkolumner än uttryck" -#: parser/analyze.c:1050 +#: parser/analyze.c:1049 #, c-format msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?" msgstr "Imatningskällan är ett raduttryck som innehåller samma antal kolumner som INSERT:en förväntade sig. Glömde du använda extra parenteser?" -#: parser/analyze.c:1347 parser/analyze.c:1734 +#: parser/analyze.c:1357 parser/analyze.c:1744 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO tillåts inte här" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1663 parser/analyze.c:3463 +#: parser/analyze.c:1673 parser/analyze.c:3479 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s kan inte appliceras på VÄRDEN" -#: parser/analyze.c:1900 +#: parser/analyze.c:1911 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "ogiltig UNION/INTERSECT/EXCEPT ORDER BY-klausul" -#: parser/analyze.c:1901 +#: parser/analyze.c:1912 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "Bara kolumnnamn i resultatet kan användas, inte uttryck eller funktioner." -#: parser/analyze.c:1902 +#: parser/analyze.c:1913 #, c-format msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause." msgstr "Lägg till uttrycket/funktionen till varje SELECT eller flytta UNION:en in i en FROM-klausul." -#: parser/analyze.c:2008 +#: parser/analyze.c:2019 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "INTO tillåts bara i den första SELECT i UNION/INTERSECT/EXCEPT" -#: parser/analyze.c:2080 +#: parser/analyze.c:2091 #, c-format msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level" msgstr "UNION/INTERSECT/EXCEPT-medlemssats kan inte referera till andra relationer på samma frågenivå" -#: parser/analyze.c:2167 +#: parser/analyze.c:2178 #, c-format msgid "each %s query must have the same number of columns" msgstr "varje %s-fråga måste ha samma antal kolumner" -#: parser/analyze.c:2573 +#: parser/analyze.c:2535 +#, c-format +msgid "SET target columns cannot be qualified with the relation name." +msgstr "målkolumner för SET kan inte kvalifiiceras med ett relationsnamn." + +#: parser/analyze.c:2589 #, c-format msgid "RETURNING must have at least one column" msgstr "RETURNING måste ha minst en kolumn" -#: parser/analyze.c:2676 +#: parser/analyze.c:2692 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" msgstr[0] "tilldelningskälla returnerade %d kolumn" msgstr[1] "tilldelningskälla returnerade %d kolumner" -#: parser/analyze.c:2737 +#: parser/analyze.c:2753 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "variabeln \"%s\" har typ %s men uttrycket har typ %s" #. translator: %s is a SQL keyword -#: parser/analyze.c:2862 parser/analyze.c:2870 +#: parser/analyze.c:2878 parser/analyze.c:2886 #, c-format msgid "cannot specify both %s and %s" msgstr "kan inte ange både %s och %s" -#: parser/analyze.c:2890 +#: parser/analyze.c:2906 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR får inte innehålla datamodifierande satser i WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2898 +#: parser/analyze.c:2914 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s stöds inte" -#: parser/analyze.c:2901 +#: parser/analyze.c:2917 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "Hållbara markörer måste vara READ ONLY." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2909 +#: parser/analyze.c:2925 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s stöds inte" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2920 +#: parser/analyze.c:2936 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s är inte giltig" -#: parser/analyze.c:2923 +#: parser/analyze.c:2939 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "Okänsliga markörer måste vara READ ONLY." -#: parser/analyze.c:3017 +#: parser/analyze.c:3033 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "materialiserade vyer får inte innehålla datamodifierande satser i WITH" -#: parser/analyze.c:3027 +#: parser/analyze.c:3043 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "materialiserade vyer får inte använda temporära tabeller eller vyer" -#: parser/analyze.c:3037 +#: parser/analyze.c:3053 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "materialiserade vyer kan inte defineras med bundna parametrar" -#: parser/analyze.c:3049 +#: parser/analyze.c:3065 #, c-format msgid "materialized views cannot be unlogged" msgstr "materialiserad vyer kan inte vara ologgade" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3238 +#: parser/analyze.c:3254 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s tillåts inte med DISTINCT-klausul" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3245 +#: parser/analyze.c:3261 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s tillåts inte med GROUP BY-klausul" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3252 +#: parser/analyze.c:3268 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s tillåts inte med HAVING-klausul" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3259 +#: parser/analyze.c:3275 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s tillåts inte med aggregatfunktioner" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3266 +#: parser/analyze.c:3282 #, c-format msgid "%s is not allowed with window functions" msgstr "%s tillåts inte med fönsterfunktioner" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3273 +#: parser/analyze.c:3289 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "%s tillåts inte med mängdreturnerande funktioner i mållistan" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3372 +#: parser/analyze.c:3388 #, c-format msgid "%s must specify unqualified relation names" msgstr "%s: måste ange okvalificerade relationsnamn" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3436 +#: parser/analyze.c:3452 #, c-format msgid "%s cannot be applied to a join" msgstr "%s kan inte appliceras på en join" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3445 +#: parser/analyze.c:3461 #, c-format msgid "%s cannot be applied to a function" msgstr "%s kan inte appliceras på en funktion" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3454 +#: parser/analyze.c:3470 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s kan inte appliceras på tabellfunktion" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3472 +#: parser/analyze.c:3488 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s kan inte appliceras på en WITH-fråga" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3481 +#: parser/analyze.c:3497 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%s kan inte appliceras på en namngiven tupellagring" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3501 +#: parser/analyze.c:3517 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "relationen \"%s\" i %s-klausul hittades inte i FROM-klausul" -#: parser/parse_agg.c:221 parser/parse_oper.c:227 +#: parser/parse_agg.c:210 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "kunde inte identifiera en jämförelseoperator för typ %s" -#: parser/parse_agg.c:223 +#: parser/parse_agg.c:212 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "Aggregat med DISTINCT måste kunna sortera sina indata." -#: parser/parse_agg.c:258 +#: parser/parse_agg.c:270 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPING måste ha färre än 32 argument" -#: parser/parse_agg.c:361 +#: parser/parse_agg.c:373 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "aggregatfunktioner tillåts inte i JOIN-villkor" -#: parser/parse_agg.c:363 +#: parser/parse_agg.c:375 msgid "grouping operations are not allowed in JOIN conditions" msgstr "gruppoperationer tillåts inte i JOIN-villkor" -#: parser/parse_agg.c:375 +#: parser/parse_agg.c:385 msgid "aggregate functions are not allowed in FROM clause of their own query level" msgstr "aggregatfunktioner tillåts inte i FROM-klausul på sin egen frågenivå" -#: parser/parse_agg.c:377 +#: parser/parse_agg.c:387 msgid "grouping operations are not allowed in FROM clause of their own query level" msgstr "gruppoperationer tillåts inte i FROM-klausul på sin egen frågenivå" -#: parser/parse_agg.c:382 +#: parser/parse_agg.c:392 msgid "aggregate functions are not allowed in functions in FROM" msgstr "aggregatfunktioner tillåts inte i funktioner i FROM" -#: parser/parse_agg.c:384 +#: parser/parse_agg.c:394 msgid "grouping operations are not allowed in functions in FROM" msgstr "gruppoperationer tillåts inte i funktioner i FROM" -#: parser/parse_agg.c:392 +#: parser/parse_agg.c:402 msgid "aggregate functions are not allowed in policy expressions" msgstr "aggregatfunktioner tillåts inte i policyuttryck" -#: parser/parse_agg.c:394 +#: parser/parse_agg.c:404 msgid "grouping operations are not allowed in policy expressions" msgstr "gruppoperationer tillåts inte i policyuttryck" -#: parser/parse_agg.c:411 +#: parser/parse_agg.c:421 msgid "aggregate functions are not allowed in window RANGE" msgstr "aggregatfunktioner tillåts inte i fönster-RANGE" -#: parser/parse_agg.c:413 +#: parser/parse_agg.c:423 msgid "grouping operations are not allowed in window RANGE" msgstr "grupperingsoperationer tillåts inte i fönster-RANGE" -#: parser/parse_agg.c:418 +#: parser/parse_agg.c:428 msgid "aggregate functions are not allowed in window ROWS" msgstr "aggregatfunktioner tillåts inte i fönster-RADER" -#: parser/parse_agg.c:420 +#: parser/parse_agg.c:430 msgid "grouping operations are not allowed in window ROWS" msgstr "grupperingsfunktioner tillåts inte i fönster-RADER" -#: parser/parse_agg.c:425 +#: parser/parse_agg.c:435 msgid "aggregate functions are not allowed in window GROUPS" msgstr "aggregatfunktioner tillåts inte i fönster-GROUPS" -#: parser/parse_agg.c:427 +#: parser/parse_agg.c:437 msgid "grouping operations are not allowed in window GROUPS" msgstr "grupperingsfunktioner tillåts inte i fönster-GROUPS" -#: parser/parse_agg.c:440 +#: parser/parse_agg.c:450 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "aggregatfunktioner tillåts inte i MERGE WHEN-villkor" -#: parser/parse_agg.c:442 +#: parser/parse_agg.c:452 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "gruppoperationer tillåts inte i MERGE WHEN-villkor" -#: parser/parse_agg.c:468 +#: parser/parse_agg.c:479 msgid "aggregate functions are not allowed in check constraints" msgstr "aggregatfunktioner tillåts inte i check-villkor" -#: parser/parse_agg.c:470 +#: parser/parse_agg.c:481 msgid "grouping operations are not allowed in check constraints" msgstr "gruppoperationer tillåts inte i check-villkor" -#: parser/parse_agg.c:477 +#: parser/parse_agg.c:488 msgid "aggregate functions are not allowed in DEFAULT expressions" msgstr "aggregatfunktioner tillåts inte i DEFAULT-uttryck" -#: parser/parse_agg.c:479 +#: parser/parse_agg.c:490 msgid "grouping operations are not allowed in DEFAULT expressions" msgstr "grupperingsoperationer tillåts inte i DEFAULT-uttryck" -#: parser/parse_agg.c:484 +#: parser/parse_agg.c:495 msgid "aggregate functions are not allowed in index expressions" msgstr "aggregatfunktioner tillåts inte i indexuttryck" -#: parser/parse_agg.c:486 +#: parser/parse_agg.c:497 msgid "grouping operations are not allowed in index expressions" msgstr "gruppoperationer tillåts inte i indexuttryck" -#: parser/parse_agg.c:491 +#: parser/parse_agg.c:502 msgid "aggregate functions are not allowed in index predicates" msgstr "aggregatfunktionsanrop tillåts inte i indexpredikat" -#: parser/parse_agg.c:493 +#: parser/parse_agg.c:504 msgid "grouping operations are not allowed in index predicates" msgstr "gruppoperationer tillåts inte i indexpredikat" -#: parser/parse_agg.c:498 +#: parser/parse_agg.c:509 msgid "aggregate functions are not allowed in statistics expressions" msgstr "aggregatfunktioner tillåts inte i statistikuttryck" -#: parser/parse_agg.c:500 +#: parser/parse_agg.c:511 msgid "grouping operations are not allowed in statistics expressions" msgstr "gruppoperationer tillåts inte i statistikuttryck" -#: parser/parse_agg.c:505 +#: parser/parse_agg.c:516 msgid "aggregate functions are not allowed in transform expressions" msgstr "aggregatfunktioner tillåts inte i transform-uttryck" -#: parser/parse_agg.c:507 +#: parser/parse_agg.c:518 msgid "grouping operations are not allowed in transform expressions" msgstr "gruppoperationer tillåts inte i transforme-uttryck" -#: parser/parse_agg.c:512 +#: parser/parse_agg.c:523 msgid "aggregate functions are not allowed in EXECUTE parameters" msgstr "aggregatfunktioner tillåts inte i EXECUTE-parametrar" -#: parser/parse_agg.c:514 +#: parser/parse_agg.c:525 msgid "grouping operations are not allowed in EXECUTE parameters" msgstr "gruppoperationer tillåts inte i EXECUTE-parametrar" -#: parser/parse_agg.c:519 +#: parser/parse_agg.c:530 msgid "aggregate functions are not allowed in trigger WHEN conditions" msgstr "aggregatfunktioner tillåts inte i WHEN-villkor" -#: parser/parse_agg.c:521 +#: parser/parse_agg.c:532 msgid "grouping operations are not allowed in trigger WHEN conditions" msgstr "gruppoperationer tillåts inte i WHEN-villkor" -#: parser/parse_agg.c:526 +#: parser/parse_agg.c:537 msgid "aggregate functions are not allowed in partition bound" msgstr "aggregatfunktioner tillåts inte i partitionsgräns" -#: parser/parse_agg.c:528 +#: parser/parse_agg.c:539 msgid "grouping operations are not allowed in partition bound" msgstr "gruppoperationer tillåts inte i partitionsgräns" -#: parser/parse_agg.c:533 +#: parser/parse_agg.c:544 msgid "aggregate functions are not allowed in partition key expressions" msgstr "aggregatfunktioner tillåts inte i partitionsnyckeluttryck" -#: parser/parse_agg.c:535 +#: parser/parse_agg.c:546 msgid "grouping operations are not allowed in partition key expressions" msgstr "gruppoperationer tillåts inte i partitionsnyckeluttryck" -#: parser/parse_agg.c:541 +#: parser/parse_agg.c:552 msgid "aggregate functions are not allowed in column generation expressions" msgstr "aggregatfunktioner tillåts inte i kolumngenereringsuttryck" -#: parser/parse_agg.c:543 +#: parser/parse_agg.c:554 msgid "grouping operations are not allowed in column generation expressions" msgstr "gruppoperationer tillåts inte i kolumngenereringsuttryck" -#: parser/parse_agg.c:549 +#: parser/parse_agg.c:560 msgid "aggregate functions are not allowed in CALL arguments" msgstr "aggregatfunktioner tillåts inte i CALL-argument" -#: parser/parse_agg.c:551 +#: parser/parse_agg.c:562 msgid "grouping operations are not allowed in CALL arguments" msgstr "gruppoperationer tillåts inte i CALL-argument" -#: parser/parse_agg.c:557 +#: parser/parse_agg.c:568 msgid "aggregate functions are not allowed in COPY FROM WHERE conditions" msgstr "aggregatfunktioner tillåts inte i COPY FROM WHERE-villkor" -#: parser/parse_agg.c:559 +#: parser/parse_agg.c:570 msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "gruppoperationer tillåts inte i COPY FROM WHERE-villkor" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:586 parser/parse_clause.c:1956 +#: parser/parse_agg.c:597 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "aggregatfunktioner tillåts inte i %s" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:589 +#: parser/parse_agg.c:600 #, c-format msgid "grouping operations are not allowed in %s" msgstr "gruppoperationer tillåts inte i %s" -#: parser/parse_agg.c:690 +#: parser/parse_agg.c:701 #, c-format msgid "outer-level aggregate cannot contain a lower-level variable in its direct arguments" msgstr "yttre aggregat kan inte innehålla inre variabel i sitt direkta argument" -#: parser/parse_agg.c:768 +#: parser/parse_agg.c:779 #, c-format msgid "aggregate function calls cannot contain set-returning function calls" msgstr "aggregatfunktionsanrop kan inte innehålla mängdreturnerande funktionsanrop" -#: parser/parse_agg.c:769 parser/parse_expr.c:1700 parser/parse_expr.c:2182 -#: parser/parse_func.c:884 +#: parser/parse_agg.c:780 parser/parse_expr.c:1762 parser/parse_expr.c:2245 +#: parser/parse_func.c:885 #, c-format msgid "You might be able to move the set-returning function into a LATERAL FROM item." msgstr "Du kanske kan flytta den mängdreturnerande funktionen in i en LATERAL FROM-konstruktion." -#: parser/parse_agg.c:774 +#: parser/parse_agg.c:785 #, c-format msgid "aggregate function calls cannot contain window function calls" msgstr "aggregatfunktionsanrop kan inte innehålla fönsterfunktionanrop" -#: parser/parse_agg.c:853 +#: parser/parse_agg.c:864 msgid "window functions are not allowed in JOIN conditions" msgstr "fönsterfunktioner tillåts inte i JOIN-villkor" -#: parser/parse_agg.c:860 +#: parser/parse_agg.c:871 msgid "window functions are not allowed in functions in FROM" msgstr "fönsterfunktioner tillåts inte i funktioner i FROM" -#: parser/parse_agg.c:866 +#: parser/parse_agg.c:877 msgid "window functions are not allowed in policy expressions" msgstr "fönsterfunktioner tillåts inte i policy-uttryck" -#: parser/parse_agg.c:879 +#: parser/parse_agg.c:890 msgid "window functions are not allowed in window definitions" msgstr "fönsterfunktioner tillåts inte i fönsterdefinitioner" -#: parser/parse_agg.c:890 +#: parser/parse_agg.c:901 msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "fönsterfunktioner tillåts inte i MERGE WHEN-villkor" -#: parser/parse_agg.c:914 +#: parser/parse_agg.c:926 msgid "window functions are not allowed in check constraints" msgstr "fönsterfunktioner tillåts inte i check-villkor" -#: parser/parse_agg.c:918 +#: parser/parse_agg.c:930 msgid "window functions are not allowed in DEFAULT expressions" msgstr "fönsterfunktioner tillåts inte i DEFAULT-uttryck" -#: parser/parse_agg.c:921 +#: parser/parse_agg.c:933 msgid "window functions are not allowed in index expressions" msgstr "fönsterfunktioner tillåts inte i indexuttryck" -#: parser/parse_agg.c:924 +#: parser/parse_agg.c:936 msgid "window functions are not allowed in statistics expressions" msgstr "fönsterfunktioner tillåts inte i statistikuttryck" -#: parser/parse_agg.c:927 +#: parser/parse_agg.c:939 msgid "window functions are not allowed in index predicates" msgstr "fönsterfunktioner tillåts inte i indexpredikat" -#: parser/parse_agg.c:930 +#: parser/parse_agg.c:942 msgid "window functions are not allowed in transform expressions" msgstr "fönsterfunktioner tillåts inte i transform-uttrycket" -#: parser/parse_agg.c:933 +#: parser/parse_agg.c:945 msgid "window functions are not allowed in EXECUTE parameters" msgstr "fönsterfunktioner tillåts inte i EXECUTE-parametrar" -#: parser/parse_agg.c:936 +#: parser/parse_agg.c:948 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "fönsterfunktioner tillåts inte i WHEN-villkor" -#: parser/parse_agg.c:939 +#: parser/parse_agg.c:951 msgid "window functions are not allowed in partition bound" msgstr "fönsterfunktioner tillåts inte i partitiongräns" -#: parser/parse_agg.c:942 +#: parser/parse_agg.c:954 msgid "window functions are not allowed in partition key expressions" msgstr "fönsterfunktioner tillåts inte i partitionsnyckeluttryck" -#: parser/parse_agg.c:945 +#: parser/parse_agg.c:957 msgid "window functions are not allowed in CALL arguments" msgstr "fönsterfunktioner tillåts inte i CALL-argument" -#: parser/parse_agg.c:948 +#: parser/parse_agg.c:960 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "fönsterfunktioner tillåts inte i COPY FROM WHERE-villkor" -#: parser/parse_agg.c:951 +#: parser/parse_agg.c:963 msgid "window functions are not allowed in column generation expressions" msgstr "fönsterfunktioner tillåts inte i kolumngenereringsuttryck" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:974 parser/parse_clause.c:1965 +#: parser/parse_agg.c:986 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "fönsterfunktioner tillåts inte i %s" -#: parser/parse_agg.c:1008 parser/parse_clause.c:2798 +#: parser/parse_agg.c:1020 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "fönster \"%s\" finns inte" -#: parser/parse_agg.c:1096 +#: parser/parse_agg.c:1108 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "för många grupperingsmängder (maximalt 4096)" -#: parser/parse_agg.c:1236 +#: parser/parse_agg.c:1248 #, c-format msgid "aggregate functions are not allowed in a recursive query's recursive term" msgstr "aggregatfunktioner tillåts inte i en rekursiv frågas rekursiva term" -#: parser/parse_agg.c:1429 +#: parser/parse_agg.c:1441 #, c-format msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function" msgstr "kolumn \"%s.%s\" måste stå med i GROUP BY-klausulen eller användas i en aggregatfunktion" -#: parser/parse_agg.c:1432 +#: parser/parse_agg.c:1444 #, c-format msgid "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "Direkta argument till en sorterad-mängd-aggregat får bara använda grupperade kolumner." -#: parser/parse_agg.c:1437 +#: parser/parse_agg.c:1449 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "underfråga använder ogrupperad kolumn \"%s.%s\" från yttre fråga" -#: parser/parse_agg.c:1601 +#: parser/parse_agg.c:1613 #, c-format msgid "arguments to GROUPING must be grouping expressions of the associated query level" msgstr "argument till GROUPING måste vare grupputtryck på den tillhörande frågenivån" -#: parser/parse_clause.c:195 +#: parser/parse_clause.c:193 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "relationen \"%s\" kan inte vara målet för en modifierande sats" -#: parser/parse_clause.c:571 parser/parse_clause.c:599 parser/parse_func.c:2552 +#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "mängdreturnerande funktioner måste vara på toppnivå i FROM" -#: parser/parse_clause.c:611 +#: parser/parse_clause.c:609 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "multipla kolumndefinitionslistor tillåts inte i samma funktion" -#: parser/parse_clause.c:644 +#: parser/parse_clause.c:642 #, c-format msgid "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "ROWS FROM() med multipla funktioner kan inte ha en kolumndefinitionslista" -#: parser/parse_clause.c:645 +#: parser/parse_clause.c:643 #, c-format msgid "Put a separate column definition list for each function inside ROWS FROM()." msgstr "Lägg till en separat kolumndefinitionslista för varje funktion inne i ROWS FROM()." -#: parser/parse_clause.c:651 +#: parser/parse_clause.c:649 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "UNNEST() med multipla argument kan inte ha en kolumndefinitionslista" -#: parser/parse_clause.c:652 +#: parser/parse_clause.c:650 #, c-format msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one." msgstr "Använd separata UNNEST()-anrop inne i ROWS FROM() och koppla en kolumndefinitionslista till varje." -#: parser/parse_clause.c:659 +#: parser/parse_clause.c:657 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY kan inte användas tillsammans med en kolumndefinitionslista" -#: parser/parse_clause.c:660 +#: parser/parse_clause.c:658 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "Placera kolumndefinitionslistan inne i ROWS FROM()." -#: parser/parse_clause.c:760 +#: parser/parse_clause.c:762 parser/parse_jsontable.c:295 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "bara en FOR ORDINALITY-kolumn tillåts" -#: parser/parse_clause.c:821 +#: parser/parse_clause.c:823 #, c-format msgid "column name \"%s\" is not unique" msgstr "kolumnnamn \"%s\" är inte unikt" -#: parser/parse_clause.c:863 +#: parser/parse_clause.c:865 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "namespace-namn \"%s\" är inte unikt" -#: parser/parse_clause.c:873 +#: parser/parse_clause.c:875 #, c-format msgid "only one default namespace is allowed" msgstr "bara ett standard-namespace tillåts" -#: parser/parse_clause.c:933 +#: parser/parse_clause.c:935 #, c-format msgid "tablesample method %s does not exist" msgstr "tabellsamplingsmetod \"%s\" existerar inte" -#: parser/parse_clause.c:955 +#: parser/parse_clause.c:957 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" msgstr[0] "tabellsamplingsmetod %s kräver %d argument, inte %d" msgstr[1] "tabellsamplingsmetod %s kräver %d argument, inte %d" -#: parser/parse_clause.c:989 +#: parser/parse_clause.c:991 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "tabellsamplingsmetod %s stöder inte REPEATABLE" -#: parser/parse_clause.c:1138 +#: parser/parse_clause.c:1144 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "TABLESAMPLE-klausul kan bara appliceras på tabeller och materialiserade vyer" -#: parser/parse_clause.c:1325 +#: parser/parse_clause.c:1331 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "kolumnnamn \"%s\" angivet mer än en gång i USING-klausul" -#: parser/parse_clause.c:1340 +#: parser/parse_clause.c:1346 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "gemensamt kolumnnamn \"%s\" finns mer än en gång i vänstra tabellen" -#: parser/parse_clause.c:1349 +#: parser/parse_clause.c:1355 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "kolumn \"%s\" angiven i USING-klausul finns inte i den vänstra tabellen" -#: parser/parse_clause.c:1364 +#: parser/parse_clause.c:1370 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "gemensamt kolumnnamn \"%s\" finns mer än en gång i högra tabellen" -#: parser/parse_clause.c:1373 +#: parser/parse_clause.c:1379 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "kolumn \"%s\" angiven i USING-klausul finns inte i den högra tabellen" -#: parser/parse_clause.c:1901 +#: parser/parse_clause.c:1907 #, c-format msgid "row count cannot be null in FETCH FIRST ... WITH TIES clause" msgstr "radantal kan inte vara null i FETCH FIRST ... WITH TIES-klausul" #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_clause.c:1926 +#: parser/parse_clause.c:1932 #, c-format msgid "argument of %s must not contain variables" msgstr "argumentet till %s får inte innehålla variabler" #. translator: first %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2091 +#: parser/parse_clause.c:2097 #, c-format msgid "%s \"%s\" is ambiguous" msgstr "%s \"%s\" är tvetydig" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2119 +#: parser/parse_clause.c:2125 #, c-format msgid "non-integer constant in %s" msgstr "ej heltalskonstant i %s" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2141 +#: parser/parse_clause.c:2147 #, c-format msgid "%s position %d is not in select list" msgstr "%s-position %d finns inte i select-listan" -#: parser/parse_clause.c:2580 +#: parser/parse_clause.c:2586 #, c-format msgid "CUBE is limited to 12 elements" msgstr "CUBE är begränsad till 12 element" -#: parser/parse_clause.c:2786 +#: parser/parse_clause.c:2792 #, c-format msgid "window \"%s\" is already defined" msgstr "fönster \"%s\" är redan definierad" -#: parser/parse_clause.c:2847 +#: parser/parse_clause.c:2853 #, c-format msgid "cannot override PARTITION BY clause of window \"%s\"" msgstr "kan inte övertrumfa PARTITION BY-klausul för fönster \"%s\"" -#: parser/parse_clause.c:2859 +#: parser/parse_clause.c:2865 #, c-format msgid "cannot override ORDER BY clause of window \"%s\"" msgstr "kan inte övertrumfa ORDER BY-klausul för fönster \"%s\"" -#: parser/parse_clause.c:2889 parser/parse_clause.c:2895 +#: parser/parse_clause.c:2895 parser/parse_clause.c:2901 #, c-format msgid "cannot copy window \"%s\" because it has a frame clause" msgstr "kan inte kopiera fönster \"%s\" då det har en fönsterramklausul" -#: parser/parse_clause.c:2897 +#: parser/parse_clause.c:2903 #, c-format msgid "Omit the parentheses in this OVER clause." msgstr "Ta bort parenteserna i denna OVER-klausul." -#: parser/parse_clause.c:2917 +#: parser/parse_clause.c:2923 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column" msgstr "RANGE med offset PRECEDING/FOLLOWING kräver exakt en ORDER BY-kolumn" -#: parser/parse_clause.c:2940 +#: parser/parse_clause.c:2946 #, c-format msgid "GROUPS mode requires an ORDER BY clause" msgstr "GROUPS-läge kräver en ORDER BY-klausul" -#: parser/parse_clause.c:3011 +#: parser/parse_clause.c:3016 #, c-format msgid "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list" msgstr "i ett aggregat med DISTINCT så måste ORDER BY-uttryck finnas i argumentlistan" -#: parser/parse_clause.c:3012 +#: parser/parse_clause.c:3017 #, c-format msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list" msgstr "i SELECT DISTINCT så måste ORDER BY-uttryck finnas i select-listan" -#: parser/parse_clause.c:3044 +#: parser/parse_clause.c:3049 #, c-format msgid "an aggregate with DISTINCT must have at least one argument" msgstr "ett aggregat med DISTINCT måste ha minst ett argument" -#: parser/parse_clause.c:3045 +#: parser/parse_clause.c:3050 #, c-format msgid "SELECT DISTINCT must have at least one column" msgstr "SELECT DISTINCT måste ha minst en kolumn" -#: parser/parse_clause.c:3111 parser/parse_clause.c:3143 +#: parser/parse_clause.c:3116 parser/parse_clause.c:3148 #, c-format msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions" msgstr "SELECT DISTINCT ON-uttrycken måste matcha de initiala ORDER BY-uttrycken" -#: parser/parse_clause.c:3221 +#: parser/parse_clause.c:3226 #, c-format msgid "ASC/DESC is not allowed in ON CONFLICT clause" msgstr "ASC/DESC tillåts inte i ON CONFLICT-klausul" -#: parser/parse_clause.c:3227 +#: parser/parse_clause.c:3232 #, c-format msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause" msgstr "NULLS FIRST/LAST tillåts inte i ON CONFLICT-klausul" -#: parser/parse_clause.c:3306 +#: parser/parse_clause.c:3311 #, c-format msgid "ON CONFLICT DO UPDATE requires inference specification or constraint name" msgstr "ON CONFLICT DO UPDATE kräver inferensangivelse eller villkorsnamn" -#: parser/parse_clause.c:3307 +#: parser/parse_clause.c:3312 #, c-format msgid "For example, ON CONFLICT (column_name)." msgstr "Till exempel, ON CONFLICT (kolumnnamn)." -#: parser/parse_clause.c:3318 +#: parser/parse_clause.c:3323 #, c-format msgid "ON CONFLICT is not supported with system catalog tables" msgstr "ON CONFLICT stöds inte för systemkatalogtabeller" -#: parser/parse_clause.c:3326 +#: parser/parse_clause.c:3331 #, c-format msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table" msgstr "ON CONFLICT stöds inte på tabell \"%s\" som används som katalogtabell" -#: parser/parse_clause.c:3457 +#: parser/parse_clause.c:3462 #, c-format msgid "operator %s is not a valid ordering operator" msgstr "operator %s är inte en giltig sorteringsoperator" -#: parser/parse_clause.c:3459 +#: parser/parse_clause.c:3464 #, c-format msgid "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "Sorteringsoperationer måste vara \"<\"- eller \">\"-medlemmar i btree-operatorfamiljer." -#: parser/parse_clause.c:3770 +#: parser/parse_clause.c:3775 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "RANGE med offset PRECEDING/FOLLOWING stöds inte för kolumntyp %s" -#: parser/parse_clause.c:3776 +#: parser/parse_clause.c:3781 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s and offset type %s" msgstr "RANGE med offset PRECEDING/FOLLOWING stöd inte av kolumntyp %s och offset-typ %s" -#: parser/parse_clause.c:3779 +#: parser/parse_clause.c:3784 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "Typomvandla offset-värdet till lämplig typ." -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3789 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for column type %s and offset type %s" msgstr "RANGE med offset PRECEDING/FOLLOWING har multipla tolkingar för kolumntyp %s och offset-typ %s" -#: parser/parse_clause.c:3787 +#: parser/parse_clause.c:3792 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "Typomvandla offset-värdet till exakt den önskade typen." #: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 #: parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 -#: parser/parse_expr.c:2083 parser/parse_expr.c:2691 parser/parse_expr.c:3497 -#: parser/parse_target.c:985 +#: parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3405 +#: parser/parse_expr.c:3634 parser/parse_target.c:998 #, c-format msgid "cannot cast type %s to %s" msgstr "kan inte omvandla typ %s till %s" @@ -17311,121 +17768,121 @@ msgid "argument of %s must not return a set" msgstr "argumentet till %s får inte returnera en mängd" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1383 +#: parser/parse_coerce.c:1420 #, c-format msgid "%s types %s and %s cannot be matched" msgstr "%s typer %s och %s matchar inte" -#: parser/parse_coerce.c:1499 +#: parser/parse_coerce.c:1536 #, c-format msgid "argument types %s and %s cannot be matched" msgstr "argumenttyperna %s och %s matchar inte" #. translator: first %s is name of a SQL construct, eg CASE -#: parser/parse_coerce.c:1551 +#: parser/parse_coerce.c:1588 #, c-format msgid "%s could not convert type %s to %s" msgstr "%s kan inte konvertera typ %s till %s" -#: parser/parse_coerce.c:2154 parser/parse_coerce.c:2174 -#: parser/parse_coerce.c:2194 parser/parse_coerce.c:2215 -#: parser/parse_coerce.c:2270 parser/parse_coerce.c:2304 +#: parser/parse_coerce.c:2191 parser/parse_coerce.c:2211 +#: parser/parse_coerce.c:2231 parser/parse_coerce.c:2252 +#: parser/parse_coerce.c:2307 parser/parse_coerce.c:2341 #, c-format msgid "arguments declared \"%s\" are not all alike" msgstr "argument deklarerade \"%s\" är inte alla likadana" -#: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 -#: utils/fmgr/funcapi.c:592 +#: parser/parse_coerce.c:2286 parser/parse_coerce.c:2399 +#: utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "argumentet deklarerad %s är inte en array utan typ %s" -#: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 -#: utils/fmgr/funcapi.c:606 +#: parser/parse_coerce.c:2319 parser/parse_coerce.c:2469 +#: utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "argumentet deklarerad %s är inte en intervalltyp utan typ %s" -#: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 -#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:624 utils/fmgr/funcapi.c:689 +#: parser/parse_coerce.c:2353 parser/parse_coerce.c:2433 +#: parser/parse_coerce.c:2566 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "argumentet deklarerad %s är inte en multirange-typ utan typ %s" -#: parser/parse_coerce.c:2353 +#: parser/parse_coerce.c:2390 #, c-format msgid "cannot determine element type of \"anyarray\" argument" msgstr "kan inte bestämma elementtypen av \"anyarray\"-argument" -#: parser/parse_coerce.c:2379 parser/parse_coerce.c:2410 -#: parser/parse_coerce.c:2449 parser/parse_coerce.c:2515 +#: parser/parse_coerce.c:2416 parser/parse_coerce.c:2447 +#: parser/parse_coerce.c:2486 parser/parse_coerce.c:2552 #, c-format msgid "argument declared %s is not consistent with argument declared %s" msgstr "argument deklarerad %s är inte konsistent med argument deklarerad %s" -#: parser/parse_coerce.c:2474 +#: parser/parse_coerce.c:2511 #, c-format msgid "could not determine polymorphic type because input has type %s" msgstr "kunde inte bestämma en polymorf typ då indata har typ %s" -#: parser/parse_coerce.c:2488 +#: parser/parse_coerce.c:2525 #, c-format msgid "type matched to anynonarray is an array type: %s" msgstr "typen som matchar anynonarray är en array-typ: %s" -#: parser/parse_coerce.c:2498 +#: parser/parse_coerce.c:2535 #, c-format msgid "type matched to anyenum is not an enum type: %s" msgstr "typen som matchar anyenum är inte en enum-typ: %s" -#: parser/parse_coerce.c:2559 +#: parser/parse_coerce.c:2596 #, c-format msgid "arguments of anycompatible family cannot be cast to a common type" msgstr "argument till en anycompatible-familj kan inte typomvandlas till en vanlig typ" -#: parser/parse_coerce.c:2577 parser/parse_coerce.c:2598 -#: parser/parse_coerce.c:2648 parser/parse_coerce.c:2653 -#: parser/parse_coerce.c:2717 parser/parse_coerce.c:2729 +#: parser/parse_coerce.c:2614 parser/parse_coerce.c:2635 +#: parser/parse_coerce.c:2685 parser/parse_coerce.c:2690 +#: parser/parse_coerce.c:2754 parser/parse_coerce.c:2766 #, c-format msgid "could not determine polymorphic type %s because input has type %s" msgstr "kunde inte bestämma en polymorf typ %s då indata har typ %s" -#: parser/parse_coerce.c:2587 +#: parser/parse_coerce.c:2624 #, c-format msgid "anycompatiblerange type %s does not match anycompatible type %s" msgstr "anycompatiblerange-typ %s matchar inte anycompatiblerange-typ %s" -#: parser/parse_coerce.c:2608 +#: parser/parse_coerce.c:2645 #, c-format msgid "anycompatiblemultirange type %s does not match anycompatible type %s" msgstr "anycompatiblemultirange-typ %s matchar inte anycompatible-typ %s" -#: parser/parse_coerce.c:2622 +#: parser/parse_coerce.c:2659 #, c-format msgid "type matched to anycompatiblenonarray is an array type: %s" msgstr "typen som matchar anycompatiblenonarray är en array-typ: %s" -#: parser/parse_coerce.c:2857 +#: parser/parse_coerce.c:2894 #, c-format msgid "A result of type %s requires at least one input of type anyrange or anymultirange." msgstr "Ett resultat av typen %s kräver minst en indata med typen anyrange eller anymultirange." -#: parser/parse_coerce.c:2874 +#: parser/parse_coerce.c:2911 #, c-format msgid "A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange." msgstr "Ett resultat av typ %s kräver minst en indata av typen anycompatiblerange eller anycompatiblemultirange." -#: parser/parse_coerce.c:2886 +#: parser/parse_coerce.c:2923 #, c-format msgid "A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange." msgstr "Ett resultat av typ %s kräver minst en indata av typen anyelement, anyarray, anynonarray, anyenum, anyrange eller anymultirange." -#: parser/parse_coerce.c:2898 +#: parser/parse_coerce.c:2935 #, c-format msgid "A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange." msgstr "Ett resultat av typ %s kräver minst en indata av typ anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange eller anycompatiblemultirange." -#: parser/parse_coerce.c:2928 +#: parser/parse_coerce.c:2965 msgid "A result of type internal requires at least one input of type internal." msgstr "Ett resultat av typ internal kräver minst en indata av typ internal." @@ -17471,471 +17928,586 @@ msgstr "rekursiv referens till fråga \"%s\" får inte finnas i en INTERSECT" msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "rekursiv referens till fråga \"%s\" får inte finnas i en EXCEPT" -#: parser/parse_cte.c:133 -#, c-format -msgid "MERGE not supported in WITH query" -msgstr "MERGE stöds inte i WITH-fråga" - -#: parser/parse_cte.c:143 +#: parser/parse_cte.c:136 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "WITH-frågenamn \"%s\" angivet mer än en gång" -#: parser/parse_cte.c:314 +#: parser/parse_cte.c:308 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "kunde inte hitta en olikhetsoperator för typ %s" -#: parser/parse_cte.c:341 +#: parser/parse_cte.c:335 #, c-format msgid "WITH clause containing a data-modifying statement must be at the top level" msgstr "WITH-klausul som innehåller en datamodifierande sats måste vara på toppnivå" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:384 #, c-format msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall" msgstr "rekursiv fråga \"%s\" kolumn %d har typ %s i den ickerekursiva termen med typ %s totalt sett" -#: parser/parse_cte.c:396 +#: parser/parse_cte.c:390 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "Typomvandla utdatan för den ickerekursiva termen till korrekt typ." -#: parser/parse_cte.c:401 +#: parser/parse_cte.c:395 #, c-format msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall" msgstr "rekursiv fråga \"%s\" kolumn %d har jämförelse (collation) \"%s\" i en icke-rekursiv term men jämförelse \"%s\" totalt sett" -#: parser/parse_cte.c:405 +#: parser/parse_cte.c:399 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "Använd en COLLATE-klausul för att sätta jämförelse för den icke-rekursiva termen." -#: parser/parse_cte.c:426 +#: parser/parse_cte.c:420 #, c-format msgid "WITH query is not recursive" msgstr "WITH-fråga är inte rekursiv" -#: parser/parse_cte.c:457 +#: parser/parse_cte.c:451 #, c-format msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "med en SEARCH- eller CYCLE-klausul så måste vänstersidan av en UNION vara en SELECT" -#: parser/parse_cte.c:462 +#: parser/parse_cte.c:456 #, c-format msgid "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "med en SEARCH- eller CYCLE-klausul så måste högersidan av en UNION vara en SELECT" -#: parser/parse_cte.c:477 +#: parser/parse_cte.c:471 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "sökkolumn \"%s\" finns inte med i kolumnlistan för WITH-fråga" -#: parser/parse_cte.c:484 +#: parser/parse_cte.c:478 #, c-format msgid "search column \"%s\" specified more than once" msgstr "sökkolumn \"%s\" angiven mer än en gång" -#: parser/parse_cte.c:493 +#: parser/parse_cte.c:487 #, c-format msgid "search sequence column name \"%s\" already used in WITH query column list" msgstr "namn på söksekvensenskolumn \"%s\" används redan i kolumnlistan till WITH-fråga" -#: parser/parse_cte.c:510 +#: parser/parse_cte.c:504 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "cycle-kolumn \"%s\" finns inte i kolumnlistan i WITH-fråga" -#: parser/parse_cte.c:517 +#: parser/parse_cte.c:511 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "cycle-kolumn \"%s\" angiven mer än en gång" -#: parser/parse_cte.c:526 +#: parser/parse_cte.c:520 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "mark-kolumnnamn \"%s\" för cycle används redan i kolumnlistan i WITH-fråga" -#: parser/parse_cte.c:533 +#: parser/parse_cte.c:527 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "path-kolumnnamn \"%s\" för cycle används redan i kolumnlistan i WITH-fråga" -#: parser/parse_cte.c:541 +#: parser/parse_cte.c:535 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "mark-kolumnnamn och path-kolumnnamn i cycle är båda samma" -#: parser/parse_cte.c:551 +#: parser/parse_cte.c:545 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "namn på söksekvenskolumn och namn på mark-kolumn i cycle är båda samma" -#: parser/parse_cte.c:558 +#: parser/parse_cte.c:552 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "namn på söksekvenskolumn och namn på path-kolumn i cycle är båda samma" -#: parser/parse_cte.c:642 +#: parser/parse_cte.c:636 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "WITH-fråga \"%s\" har %d kolumner tillgängliga men %d kolumner angivna" -#: parser/parse_cte.c:822 +#: parser/parse_cte.c:816 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "ömsesidig rekursion mellan WITH-poster är inte implementerat" -#: parser/parse_cte.c:874 +#: parser/parse_cte.c:868 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "rekursiv fråga \"%s\" får inte innehålla datamodifierande satser" -#: parser/parse_cte.c:882 +#: parser/parse_cte.c:876 #, c-format msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term" msgstr "rekursiv fråga \"%s\" är inte på formen icke-rekursiv-term UNION [ALL] rekursiv-term" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:911 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "ORDER BY i en rekursiv fråga är inte implementerat" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:917 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "OFFSET i en rekursiv fråga är inte implementerat" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:923 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "LIMIT i en rekursiv fråga är inte implementerat" -#: parser/parse_cte.c:944 +#: parser/parse_cte.c:929 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "FOR UPDATE/SHARE i en rekursiv fråga är inte implementerat" -#: parser/parse_cte.c:1001 +#: parser/parse_cte.c:1008 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "rekursiv referens till fråga \"%s\" får inte finnas med mer än en gång" -#: parser/parse_expr.c:294 +#: parser/parse_expr.c:313 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "DEFAULT tillåts inte i detta kontext" -#: parser/parse_expr.c:371 parser/parse_relation.c:3688 -#: parser/parse_relation.c:3698 parser/parse_relation.c:3716 -#: parser/parse_relation.c:3723 parser/parse_relation.c:3737 +#: parser/parse_expr.c:406 parser/parse_relation.c:3691 +#: parser/parse_relation.c:3701 parser/parse_relation.c:3719 +#: parser/parse_relation.c:3726 parser/parse_relation.c:3740 #, c-format msgid "column %s.%s does not exist" msgstr "kolumnen %s.%s finns inte" -#: parser/parse_expr.c:383 +#: parser/parse_expr.c:418 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "kolumn \"%s\" fanns inte i datatypen %s" -#: parser/parse_expr.c:389 +#: parser/parse_expr.c:424 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "kunde inte hitta kolumnen \"%s\" i record-datatyp" -#: parser/parse_expr.c:395 +#: parser/parse_expr.c:430 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "kolumnotation .%s använd på typ %s som inte är en sammanslagen typ" -#: parser/parse_expr.c:426 parser/parse_target.c:733 +#: parser/parse_expr.c:461 parser/parse_target.c:732 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "radexpansion via \"*\" stöds inte här" -#: parser/parse_expr.c:548 +#: parser/parse_expr.c:584 msgid "cannot use column reference in DEFAULT expression" msgstr "kan inte använda kolumnreferenser i DEFAULT-uttryck" -#: parser/parse_expr.c:551 +#: parser/parse_expr.c:587 msgid "cannot use column reference in partition bound expression" msgstr "kan inte använda kolumnreferenser i partitionsgränsuttryck" -#: parser/parse_expr.c:810 parser/parse_relation.c:833 -#: parser/parse_relation.c:915 parser/parse_target.c:1225 +#: parser/parse_expr.c:846 parser/parse_relation.c:833 +#: parser/parse_relation.c:915 parser/parse_target.c:1238 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "kolumnreferens \"%s\" är tvetydig" -#: parser/parse_expr.c:866 parser/parse_param.c:110 parser/parse_param.c:142 +#: parser/parse_expr.c:902 parser/parse_param.c:110 parser/parse_param.c:142 #: parser/parse_param.c:204 parser/parse_param.c:303 #, c-format msgid "there is no parameter $%d" msgstr "det finns ingen parameter $%d" -#: parser/parse_expr.c:1066 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1103 parser/parse_expr.c:3065 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "NULLIF kräver att =-operatorn returnerar boolean" +msgid "%s requires = operator to yield boolean" +msgstr "%s kräver att operatorn = returnerar boolean" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1072 parser/parse_expr.c:3007 +#: parser/parse_expr.c:1109 parser/parse_expr.c:3072 #, c-format msgid "%s must not return a set" msgstr "%s får inte returnera en mängd" -#: parser/parse_expr.c:1457 parser/parse_expr.c:1489 +#: parser/parse_expr.c:1395 +#, c-format +msgid "MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" +msgstr "MERGE_ACTION() kan bara användas i RETURNING-listan för ett MERGE-kommando" + +#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 #, c-format msgid "number of columns does not match number of values" msgstr "antalet kolumner matchar inte antalet värden" -#: parser/parse_expr.c:1503 +#: parser/parse_expr.c:1565 #, c-format msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" msgstr "källa till en multiple-kolumn-UPDATE-post måste vara en sub-SELECT eller ROW()-uttryck" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1698 parser/parse_expr.c:2180 parser/parse_func.c:2677 +#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "mängdreturnerande funktioner tillåts inte i %s" -#: parser/parse_expr.c:1761 +#: parser/parse_expr.c:1824 msgid "cannot use subquery in check constraint" msgstr "kan inte använda subfråga i check-villkor" -#: parser/parse_expr.c:1765 +#: parser/parse_expr.c:1828 msgid "cannot use subquery in DEFAULT expression" msgstr "kan inte använda underfråga i DEFAULT-uttryck" -#: parser/parse_expr.c:1768 +#: parser/parse_expr.c:1831 msgid "cannot use subquery in index expression" msgstr "kan inte använda subfråga i indexuttryck" -#: parser/parse_expr.c:1771 +#: parser/parse_expr.c:1834 msgid "cannot use subquery in index predicate" msgstr "kan inte använda subfråga i indexpredikat" -#: parser/parse_expr.c:1774 +#: parser/parse_expr.c:1837 msgid "cannot use subquery in statistics expression" msgstr "kan inte använda underfråga i statistikuttryck" -#: parser/parse_expr.c:1777 +#: parser/parse_expr.c:1840 msgid "cannot use subquery in transform expression" msgstr "kan inte använda underfråga i transformeringsuttrycket" -#: parser/parse_expr.c:1780 +#: parser/parse_expr.c:1843 msgid "cannot use subquery in EXECUTE parameter" msgstr "kan inte använda subfråga i EXECUTE-parameter" -#: parser/parse_expr.c:1783 +#: parser/parse_expr.c:1846 msgid "cannot use subquery in trigger WHEN condition" msgstr "kan inte använda subfråga i triggerns WHEN-villkor" -#: parser/parse_expr.c:1786 +#: parser/parse_expr.c:1849 msgid "cannot use subquery in partition bound" msgstr "kan inte använda underfråga i partitionsgräns" -#: parser/parse_expr.c:1789 +#: parser/parse_expr.c:1852 msgid "cannot use subquery in partition key expression" msgstr "kan inte använda underfråga i partitionsnyckeluttryck" -#: parser/parse_expr.c:1792 +#: parser/parse_expr.c:1855 msgid "cannot use subquery in CALL argument" msgstr "kan inte använda subfråga i CALL-argument" -#: parser/parse_expr.c:1795 +#: parser/parse_expr.c:1858 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "kan inte använda subfråga i COPY FROM WHERE-villkor" -#: parser/parse_expr.c:1798 +#: parser/parse_expr.c:1861 msgid "cannot use subquery in column generation expression" msgstr "kan inte använda subfråga i kolumngenereringsuttryck" -#: parser/parse_expr.c:1851 parser/parse_expr.c:3628 +#: parser/parse_expr.c:1914 parser/parse_expr.c:3764 #, c-format msgid "subquery must return only one column" msgstr "underfråga kan bara returnera en kolumn" -#: parser/parse_expr.c:1922 +#: parser/parse_expr.c:1985 #, c-format msgid "subquery has too many columns" msgstr "underfråga har för många kolumner" -#: parser/parse_expr.c:1927 +#: parser/parse_expr.c:1990 #, c-format msgid "subquery has too few columns" msgstr "underfråga har för få kolumner" -#: parser/parse_expr.c:2023 +#: parser/parse_expr.c:2086 #, c-format msgid "cannot determine type of empty array" msgstr "kan inte bestämma typen av en tom array" -#: parser/parse_expr.c:2024 +#: parser/parse_expr.c:2087 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "Typomvandla explicit till den önskade typen, till exempel ARRAY[]::integer[]." -#: parser/parse_expr.c:2038 +#: parser/parse_expr.c:2101 #, c-format msgid "could not find element type for data type %s" msgstr "kunde inte hitta elementtyp för datatyp %s" -#: parser/parse_expr.c:2121 +#: parser/parse_expr.c:2184 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "ROW-uttryck kan ha som mest %d poster" -#: parser/parse_expr.c:2326 +#: parser/parse_expr.c:2389 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "onamnat XML-attributvärde måste vara en kolumnreferens" -#: parser/parse_expr.c:2327 +#: parser/parse_expr.c:2390 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "onamnat XML-elementvärde måste vara en kolumnreferens" -#: parser/parse_expr.c:2342 +#: parser/parse_expr.c:2405 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "XML-attributnamn \"%s\" finns med mer än en gång" -#: parser/parse_expr.c:2450 +#: parser/parse_expr.c:2513 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "kan inte typomvandla XMLSERIALIZE-resultat till %s" -#: parser/parse_expr.c:2764 parser/parse_expr.c:2960 +#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 #, c-format msgid "unequal number of entries in row expressions" msgstr "olika antal element i raduttryck" -#: parser/parse_expr.c:2774 +#: parser/parse_expr.c:2837 #, c-format msgid "cannot compare rows of zero length" msgstr "kan inte jämföra rader med längden noll" -#: parser/parse_expr.c:2799 +#: parser/parse_expr.c:2862 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "operator för radjämförelse måste resultera i typen boolean, inte %s" -#: parser/parse_expr.c:2806 +#: parser/parse_expr.c:2869 #, c-format msgid "row comparison operator must not return a set" msgstr "radjämförelseoperator får inte returnera en mängd" -#: parser/parse_expr.c:2865 parser/parse_expr.c:2906 +#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "kunde inte lista ut tolkning av radjämförelseoperator %s" -#: parser/parse_expr.c:2867 +#: parser/parse_expr.c:2930 #, c-format msgid "Row comparison operators must be associated with btree operator families." msgstr "Radjämförelseoperatorer måste vara associerade med btreee-operatorfamiljer." -#: parser/parse_expr.c:2908 +#: parser/parse_expr.c:2971 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "Det finns flera lika sannolika kandidater." -#: parser/parse_expr.c:3001 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "IS DISTINCT FROM kräver att operatorn = ger tillbaka en boolean" - -#: parser/parse_expr.c:3239 +#: parser/parse_expr.c:3306 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "JSON ENCODING tillåts bara för input-typen bytea" -#: parser/parse_expr.c:3261 +#: parser/parse_expr.c:3370 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "kan inte använda icke-strängtyper med implicit FORMAT JSON-klausul" -#: parser/parse_expr.c:3262 +#: parser/parse_expr.c:3371 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "kan inte använda icke-strängtyper med explicit FORMAT JSON-klausul" -#: parser/parse_expr.c:3335 +#: parser/parse_expr.c:3460 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "kan inte använda JSON-formatet för utddata som inte är strängar" -#: parser/parse_expr.c:3348 +#: parser/parse_expr.c:3473 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "kan inte sätta JSON-kodning för utdata-typer som inte är bytea" -#: parser/parse_expr.c:3353 +#: parser/parse_expr.c:3478 #, c-format msgid "unsupported JSON encoding" msgstr "ej stödd JSON-kodning" -#: parser/parse_expr.c:3354 +#: parser/parse_expr.c:3479 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "Enbart JSON-kodningen UTF8 stöds." -#: parser/parse_expr.c:3391 +#: parser/parse_expr.c:3516 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "returtyp SETOF stöds inte för SQL/JSON-funktioner" -#: parser/parse_expr.c:3712 parser/parse_func.c:865 +#: parser/parse_expr.c:3521 +#, c-format +msgid "returning pseudo-types is not supported in SQL/JSON functions" +msgstr "pseudo-typer stöds inte som resultat för SQL/JSON-funktioner" + +#: parser/parse_expr.c:3849 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "aggregat-ORDER BY är inte implementerat för fönsterfunktioner" -#: parser/parse_expr.c:3934 +#: parser/parse_expr.c:4072 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "kan inte använda JSON FORMAT ENCODING för indatatyper som inte är bytea" -#: parser/parse_expr.c:3954 +#: parser/parse_expr.c:4092 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "kan inte använda typen %s i ett IS JSON-predikat" -#: parser/parse_func.c:194 +#: parser/parse_expr.c:4118 parser/parse_expr.c:4239 #, c-format -msgid "argument name \"%s\" used more than once" -msgstr "argumentnamn \"%s\" angivet mer än en gång" +msgid "cannot use type %s in RETURNING clause of %s" +msgstr "kan inte använda typen %s i RETURNING-klausul för %s" -#: parser/parse_func.c:205 +#: parser/parse_expr.c:4120 #, c-format -msgid "positional argument cannot follow named argument" -msgstr "positionella argument kan inte komma efter namngivna argument" +msgid "Try returning json or jsonb." +msgstr "Försök returnera json eller jsonb." -#: parser/parse_func.c:287 parser/parse_func.c:2367 +#: parser/parse_expr.c:4168 #, c-format -msgid "%s is not a procedure" -msgstr "%s är inte en procedur" +msgid "cannot use non-string types with WITH UNIQUE KEYS clause" +msgstr "kan inte använda icke-strängtyper med WITH UNIQUE KEYS-klausul" -#: parser/parse_func.c:291 +#: parser/parse_expr.c:4242 #, c-format -msgid "To call a function, use SELECT." -msgstr "För att anropa en funktion, använd SELECT." +msgid "Try returning a string type or bytea." +msgstr "Försök returnera en strängtyp eller bytea." -#: parser/parse_func.c:297 +#: parser/parse_expr.c:4307 #, c-format -msgid "%s is a procedure" -msgstr "\"%s\" är en procedur" +msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgstr "kan inte ange FORMAT JSON i RETURNING-klausul för %s()" -#: parser/parse_func.c:301 +#: parser/parse_expr.c:4320 #, c-format -msgid "To call a procedure, use CALL." -msgstr "För att anropa en procedur, använd CALL" +msgid "SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" +msgstr "SQL/JSON QUOTES får inte anges tillsammans med WITH WRAPPER" -#: parser/parse_func.c:315 +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4334 parser/parse_expr.c:4363 parser/parse_expr.c:4394 +#: parser/parse_expr.c:4420 parser/parse_expr.c:4446 +#: parser/parse_jsontable.c:94 #, c-format -msgid "%s(*) specified, but %s is not an aggregate function" -msgstr "%s(*) angivet, men %s är inte en aggregatfunktion" +msgid "invalid %s behavior" +msgstr "ogiltig %s-angivelse" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4337 parser/parse_expr.c:4366 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s." +msgstr "Bara uttrycken ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT eller DEFAULT tillåts i %s för %s." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4344 parser/parse_expr.c:4373 parser/parse_expr.c:4402 +#: parser/parse_expr.c:4430 parser/parse_expr.c:4456 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "ogiltig %s-angivelse för kolumn \"%s\"" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4347 parser/parse_expr.c:4376 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns." +msgstr "Bara uttrycken ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT eller DEFAULT tillåts i %s för formatterade kolumner." + +#: parser/parse_expr.c:4395 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "Bara ERROR, TRUE, FALSE eller UNKNOWN tillåts i %s för %s." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4405 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "Bara ERROR, TRUE, FALSE eller UNKNOWN tillåts i %s för EXISTS-kolumner." + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4423 parser/parse_expr.c:4449 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "Bara uttrycken ERROR, NULL eller DEFAULT tillåts i %s för %s." + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4433 parser/parse_expr.c:4459 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "Bara uttrycken ERROR, NULL eller DEFAULT tillåts i %s för skalära kolumner." + +#: parser/parse_expr.c:4489 +#, c-format +msgid "JSON path expression must be of type %s, not of type %s" +msgstr "Uttryck för JSON-sökväg måste vara av typ %s, inte av typ %s" + +#: parser/parse_expr.c:4707 +#, c-format +msgid "can only specify a constant, non-aggregate function, or operator expression for DEFAULT" +msgstr "kan bara ange en konstant, en icke-aggregat-funktion eller ett operatoruttryck för DEFAULT" + +#: parser/parse_expr.c:4712 +#, c-format +msgid "DEFAULT expression must not contain column references" +msgstr "DEFAULT-uttryck får inte innehålla kolumnreferenser" + +#: parser/parse_expr.c:4717 +#, c-format +msgid "DEFAULT expression must not return a set" +msgstr "DEFAULT-uttryck får inte returnera en mängd" + +#: parser/parse_expr.c:4793 parser/parse_expr.c:4802 +#, c-format +msgid "cannot cast behavior expression of type %s to %s" +msgstr "kan inte omvandla uttryck av typ %s till %s" + +#: parser/parse_expr.c:4796 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "Du måste explicit omvandla uttrycket till typen %s." + +#: parser/parse_func.c:194 +#, c-format +msgid "argument name \"%s\" used more than once" +msgstr "argumentnamn \"%s\" angivet mer än en gång" + +#: parser/parse_func.c:205 +#, c-format +msgid "positional argument cannot follow named argument" +msgstr "positionella argument kan inte komma efter namngivna argument" + +#: parser/parse_func.c:287 parser/parse_func.c:2368 +#, c-format +msgid "%s is not a procedure" +msgstr "%s är inte en procedur" + +#: parser/parse_func.c:291 +#, c-format +msgid "To call a function, use SELECT." +msgstr "För att anropa en funktion, använd SELECT." + +#: parser/parse_func.c:297 +#, c-format +msgid "%s is a procedure" +msgstr "\"%s\" är en procedur" + +#: parser/parse_func.c:301 +#, c-format +msgid "To call a procedure, use CALL." +msgstr "För att anropa en procedur, använd CALL" + +#: parser/parse_func.c:315 +#, c-format +msgid "%s(*) specified, but %s is not an aggregate function" +msgstr "%s(*) angivet, men %s är inte en aggregatfunktion" #: parser/parse_func.c:322 #, c-format @@ -18031,7 +18603,7 @@ msgstr "Kunde inte välja en bästa kandidatfunktion: Du kan behöva lägga till msgid "No aggregate function matches the given name and argument types. Perhaps you misplaced ORDER BY; ORDER BY must appear after all regular arguments of the aggregate." msgstr "Ingen aggregatfunktion matchar det givna namnet och argumenttyperna. Kanske har du placerat ORDER BY på fel plats; ORDER BY måste komma efter alla vanliga argument till aggregatet." -#: parser/parse_func.c:622 parser/parse_func.c:2410 +#: parser/parse_func.c:622 parser/parse_func.c:2411 #, c-format msgid "procedure %s does not exist" msgstr "proceduren \"%s\" finns inte" @@ -18051,7 +18623,7 @@ msgstr "Ingen funktion matchar det angivna namnet och argumenttyperna. Du kan be msgid "VARIADIC argument must be an array" msgstr "VARIADIC-argument måste vara en array" -#: parser/parse_func.c:791 parser/parse_func.c:855 +#: parser/parse_func.c:791 parser/parse_func.c:856 #, c-format msgid "%s(*) must be used to call a parameterless aggregate function" msgstr "%s(*) måste användas för att anropa en parameterlös aggregatfunktion" @@ -18066,263 +18638,257 @@ msgstr "aggregat kan inte returnera mängder" msgid "aggregates cannot use named arguments" msgstr "aggregat kan inte använda namngivna argument" -#: parser/parse_func.c:845 +#: parser/parse_func.c:846 #, c-format msgid "DISTINCT is not implemented for window functions" msgstr "DISTINCT är inte implementerad för fönsterfunktioner" -#: parser/parse_func.c:874 +#: parser/parse_func.c:875 #, c-format msgid "FILTER is not implemented for non-aggregate window functions" msgstr "FILTER är inte implementerat för icke-aggregat-fönsterfunktioner" -#: parser/parse_func.c:883 +#: parser/parse_func.c:884 #, c-format msgid "window function calls cannot contain set-returning function calls" msgstr "fönsterfunktioner kan inte innehålla funtionsanrop till funktioner som returnerar mängder" -#: parser/parse_func.c:891 +#: parser/parse_func.c:892 #, c-format msgid "window functions cannot return sets" msgstr "fönsterfunktioner kan inte returnera mängder" -#: parser/parse_func.c:2166 parser/parse_func.c:2439 +#: parser/parse_func.c:2167 parser/parse_func.c:2440 #, c-format msgid "could not find a function named \"%s\"" msgstr "kunde inte hitta funktion med namn \"%s\"" -#: parser/parse_func.c:2180 parser/parse_func.c:2457 +#: parser/parse_func.c:2181 parser/parse_func.c:2458 #, c-format msgid "function name \"%s\" is not unique" msgstr "funktionsnamn \"%s\" är inte unikt" -#: parser/parse_func.c:2182 parser/parse_func.c:2460 +#: parser/parse_func.c:2183 parser/parse_func.c:2461 #, c-format msgid "Specify the argument list to select the function unambiguously." msgstr "Ange argumentlistan för att välja funktionen entydigt." -#: parser/parse_func.c:2226 +#: parser/parse_func.c:2227 #, c-format msgid "procedures cannot have more than %d argument" msgid_plural "procedures cannot have more than %d arguments" msgstr[0] "procedurer kan inte ha mer än %d argument" msgstr[1] "procedurer kan inte ha mer än %d argument" -#: parser/parse_func.c:2357 +#: parser/parse_func.c:2358 #, c-format msgid "%s is not a function" msgstr "%s är inte en funktion" -#: parser/parse_func.c:2377 +#: parser/parse_func.c:2378 #, c-format msgid "function %s is not an aggregate" msgstr "funktionen %s är inte en aggregatfunktion" -#: parser/parse_func.c:2405 +#: parser/parse_func.c:2406 #, c-format msgid "could not find a procedure named \"%s\"" msgstr "kunde inte hitta en procedur med namn \"%s\"" -#: parser/parse_func.c:2419 +#: parser/parse_func.c:2420 #, c-format msgid "could not find an aggregate named \"%s\"" msgstr "kunde inte hitta ett aggregat med namn \"%s\"" -#: parser/parse_func.c:2424 +#: parser/parse_func.c:2425 #, c-format msgid "aggregate %s(*) does not exist" msgstr "aggregatfunktion %s(*) existerar inte" -#: parser/parse_func.c:2429 +#: parser/parse_func.c:2430 #, c-format msgid "aggregate %s does not exist" msgstr "aggregatfunktion %s existerar inte" -#: parser/parse_func.c:2465 +#: parser/parse_func.c:2466 #, c-format msgid "procedure name \"%s\" is not unique" msgstr "procedurnamn \"%s\" är inte unikt" -#: parser/parse_func.c:2468 +#: parser/parse_func.c:2469 #, c-format msgid "Specify the argument list to select the procedure unambiguously." msgstr "Ange argumentlistan för att välja proceduren entydigt." -#: parser/parse_func.c:2473 +#: parser/parse_func.c:2474 #, c-format msgid "aggregate name \"%s\" is not unique" msgstr "aggregatnamn \"%s\" är inte unikt" -#: parser/parse_func.c:2476 +#: parser/parse_func.c:2477 #, c-format msgid "Specify the argument list to select the aggregate unambiguously." msgstr "Ange argumentlistan för att välja aggregatet entydigt." -#: parser/parse_func.c:2481 +#: parser/parse_func.c:2482 #, c-format msgid "routine name \"%s\" is not unique" msgstr "rutinnamn \"%s\" är inte unikt" -#: parser/parse_func.c:2484 +#: parser/parse_func.c:2485 #, c-format msgid "Specify the argument list to select the routine unambiguously." msgstr "Ange argumentlistan för att välja rutinen entydigt." -#: parser/parse_func.c:2539 +#: parser/parse_func.c:2540 msgid "set-returning functions are not allowed in JOIN conditions" msgstr "mängdreturnerande funktioner tillåts inte i JOIN-villkor" -#: parser/parse_func.c:2560 +#: parser/parse_func.c:2561 msgid "set-returning functions are not allowed in policy expressions" msgstr "mängdreturnerande funktioner tillåts inte i policy-uttryck" -#: parser/parse_func.c:2576 +#: parser/parse_func.c:2577 msgid "set-returning functions are not allowed in window definitions" msgstr "mängdreturnerande funktioner tillåts inte i fönsterdefinitioner" -#: parser/parse_func.c:2613 +#: parser/parse_func.c:2615 msgid "set-returning functions are not allowed in MERGE WHEN conditions" msgstr "mängdreturnerande funktioner tillåts inte i MERGE WHEN-villkor" -#: parser/parse_func.c:2617 +#: parser/parse_func.c:2619 msgid "set-returning functions are not allowed in check constraints" msgstr "mängdreturnerande funktioner tillåts inte i check-villkor" -#: parser/parse_func.c:2621 +#: parser/parse_func.c:2623 msgid "set-returning functions are not allowed in DEFAULT expressions" msgstr "mängdreturnerande funktioner tillåts inte i DEFAULT-uttryck" -#: parser/parse_func.c:2624 +#: parser/parse_func.c:2626 msgid "set-returning functions are not allowed in index expressions" msgstr "mängdreturnerande funktioner tillåts inte i indexuttryck" -#: parser/parse_func.c:2627 +#: parser/parse_func.c:2629 msgid "set-returning functions are not allowed in index predicates" msgstr "mängdreturnerande funktioner tillåts inte i indexpredukat" -#: parser/parse_func.c:2630 +#: parser/parse_func.c:2632 msgid "set-returning functions are not allowed in statistics expressions" msgstr "mängdreturnerande funktioner tillåts inte i statistikuttryck" -#: parser/parse_func.c:2633 +#: parser/parse_func.c:2635 msgid "set-returning functions are not allowed in transform expressions" msgstr "mängdreturnerande funktioner tillåts inte i transformuttryck" -#: parser/parse_func.c:2636 +#: parser/parse_func.c:2638 msgid "set-returning functions are not allowed in EXECUTE parameters" msgstr "mängdreturnerande funktioner tillåts inte i EXECUTE-parametrar" -#: parser/parse_func.c:2639 +#: parser/parse_func.c:2641 msgid "set-returning functions are not allowed in trigger WHEN conditions" msgstr "mängdreturnerande funktioner tillåts inte i WHEN-villkor" -#: parser/parse_func.c:2642 +#: parser/parse_func.c:2644 msgid "set-returning functions are not allowed in partition bound" msgstr "mängdreturnerande funktioner tillåts inte i partitionsgräns" -#: parser/parse_func.c:2645 +#: parser/parse_func.c:2647 msgid "set-returning functions are not allowed in partition key expressions" msgstr "mängdreturnerande funktioner tillåts inte i partitionsnyckeluttryck" -#: parser/parse_func.c:2648 +#: parser/parse_func.c:2650 msgid "set-returning functions are not allowed in CALL arguments" msgstr "mängdreturnerande funktioner tillåts inte i CALL-argument" -#: parser/parse_func.c:2651 +#: parser/parse_func.c:2653 msgid "set-returning functions are not allowed in COPY FROM WHERE conditions" msgstr "mängdreturnerande funktioner tillåts inte i COPY FROM WHERE-villkor" -#: parser/parse_func.c:2654 +#: parser/parse_func.c:2656 msgid "set-returning functions are not allowed in column generation expressions" msgstr "mängdreturnerande funktioner tillåts inte i kolumngenereringsuttryck" -#: parser/parse_merge.c:119 +#: parser/parse_jsontable.c:95 +#, c-format +msgid "Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "Enbart EMPTY [ ARRAY ] eller ERROR tillåts på toppnivå i ON ERROR-klausul." + +#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#, c-format +msgid "duplicate JSON_TABLE column or path name: %s" +msgstr "duplicerad JSON_TABLE-kolumn eller sökvägsnamn: %s" + +#: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" msgstr "WHERE RECURSIVE stöds inte i MERGE-satser" -#: parser/parse_merge.c:161 +#: parser/parse_merge.c:176 #, c-format msgid "unreachable WHEN clause specified after unconditional WHEN clause" msgstr "onåbar WHEN-klausul har angivits efter en ej villkorlig WHEN-klausul" -#: parser/parse_merge.c:191 -#, c-format -msgid "MERGE is not supported for relations with rules." -msgstr "MERGE stöds inte för relationer med regler." - -#: parser/parse_merge.c:208 +#: parser/parse_merge.c:222 #, c-format msgid "name \"%s\" specified more than once" msgstr "namnet \"%s\" angivet mer än en gång" -#: parser/parse_merge.c:210 +#: parser/parse_merge.c:224 #, c-format msgid "The name is used both as MERGE target table and data source." msgstr "Namnet används både som MERGE-måltabell och som datakälla." -#: parser/parse_node.c:87 +#: parser/parse_node.c:82 #, c-format msgid "target lists can have at most %d entries" msgstr "mållista kan ha som mest %d poster" -#: parser/parse_oper.c:123 parser/parse_oper.c:690 +#: parser/parse_oper.c:114 parser/parse_oper.c:678 #, c-format msgid "postfix operators are not supported" msgstr "postfix-operatorer stöds inte" -#: parser/parse_oper.c:130 parser/parse_oper.c:649 utils/adt/regproc.c:509 -#: utils/adt/regproc.c:683 -#, c-format -msgid "operator does not exist: %s" -msgstr "operator existerar inte: %s" - -#: parser/parse_oper.c:229 +#: parser/parse_oper.c:217 #, c-format msgid "Use an explicit ordering operator or modify the query." msgstr "Använd en explicit ordningsoperator eller ändra frågan." -#: parser/parse_oper.c:485 +#: parser/parse_oper.c:473 #, c-format msgid "operator requires run-time type coercion: %s" msgstr "operator kräver run-time-typomvandling: %s" -#: parser/parse_oper.c:641 +#: parser/parse_oper.c:629 #, c-format msgid "operator is not unique: %s" msgstr "operatorn är inte unik: %s" -#: parser/parse_oper.c:643 +#: parser/parse_oper.c:631 #, c-format msgid "Could not choose a best candidate operator. You might need to add explicit type casts." msgstr "Kunde inte välja en bästa kandidatoperator. Du behöver troligen lägga till en explicit typomvandling." -#: parser/parse_oper.c:652 +#: parser/parse_oper.c:640 #, c-format msgid "No operator matches the given name and argument type. You might need to add an explicit type cast." msgstr "Ingen operator matchar det angivna namnet och argumenttyp. Du kan behöva lägga till explicita typomvandlingar." -#: parser/parse_oper.c:654 +#: parser/parse_oper.c:642 #, c-format msgid "No operator matches the given name and argument types. You might need to add explicit type casts." msgstr "Ingen operator matchar det angivna namnet och argumenttyperna. Du kan behöva lägga till explicita typomvandlingar." -#: parser/parse_oper.c:714 parser/parse_oper.c:828 -#, c-format -msgid "operator is only a shell: %s" -msgstr "operator är bara en shell-typ: %s" - -#: parser/parse_oper.c:816 +#: parser/parse_oper.c:803 #, c-format msgid "op ANY/ALL (array) requires array on right side" msgstr "op ANY/ALL (array) kräver en array på höger sida" -#: parser/parse_oper.c:858 +#: parser/parse_oper.c:844 #, c-format msgid "op ANY/ALL (array) requires operator to yield boolean" msgstr "op ANY/ALL (array) kräver att operatorn returnerar en boolean" -#: parser/parse_oper.c:863 +#: parser/parse_oper.c:849 #, c-format msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "op ANY/ALL (array) kräver att operatorn inte returnerar en mängd" @@ -18332,7 +18898,7 @@ msgstr "op ANY/ALL (array) kräver att operatorn inte returnerar en mängd" msgid "inconsistent types deduced for parameter $%d" msgstr "inkonsistenta typer härledda för parameter $%d" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:309 tcop/postgres.c:744 #, c-format msgid "could not determine data type of parameter $%d" msgstr "kunde inte lista ut datatypen för parameter $%d" @@ -18352,13 +18918,13 @@ msgstr "tabellreferens %u är tvetydig" msgid "table name \"%s\" specified more than once" msgstr "tabellnamn \"%s\" angivet mer än en gång" -#: parser/parse_relation.c:494 parser/parse_relation.c:3630 -#: parser/parse_relation.c:3639 +#: parser/parse_relation.c:494 parser/parse_relation.c:3633 +#: parser/parse_relation.c:3642 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "ogiltig referens till FROM-klausulpost för tabell \"%s\"" -#: parser/parse_relation.c:498 parser/parse_relation.c:3641 +#: parser/parse_relation.c:498 parser/parse_relation.c:3644 #, c-format msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query." msgstr "Det finns en post för tabell \"%s\" men den kan inte refereras till från denna del av frågan." @@ -18384,7 +18950,7 @@ msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "kan inte använda systemkolumn \"%s\" i MERGE WHEN-villkor" #: parser/parse_relation.c:1236 parser/parse_relation.c:1691 -#: parser/parse_relation.c:2388 +#: parser/parse_relation.c:2384 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "tabell \"%s\" har %d kolumner tillgängliga men %d kolumner angivna" @@ -18399,157 +18965,157 @@ msgstr "Det finns en WITH-post med namn \"%s\" men den kan inte refereras till f msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references." msgstr "Använd WITH RECURSIVE eller ändra ordning på WITH-posterna för att ta bort framåt-referenser." -#: parser/parse_relation.c:1834 +#: parser/parse_relation.c:1833 #, c-format msgid "a column definition list is redundant for a function with OUT parameters" msgstr "en kolumndefinitionslista är redundant för en funktion med OUT-parametrar" -#: parser/parse_relation.c:1840 +#: parser/parse_relation.c:1839 #, c-format msgid "a column definition list is redundant for a function returning a named composite type" msgstr "en kolumndefinitionslista är redundant för en funktion som returnerar en namngiven composite-typ" -#: parser/parse_relation.c:1847 +#: parser/parse_relation.c:1846 #, c-format msgid "a column definition list is only allowed for functions returning \"record\"" msgstr "en kolumndefinitionslista tillåts bara för funktioner som returnerar \"record\"" -#: parser/parse_relation.c:1858 +#: parser/parse_relation.c:1857 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "en kolumndefinitionslista krävs för funktioner som returnerar \"record\"" -#: parser/parse_relation.c:1895 +#: parser/parse_relation.c:1894 #, c-format msgid "column definition lists can have at most %d entries" msgstr "kolumndefinitionslistor kan ha som mest %d poster" -#: parser/parse_relation.c:1955 +#: parser/parse_relation.c:1954 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "funktion \"%s\" i FROM har en icke stödd returtyp %s" -#: parser/parse_relation.c:1982 parser/parse_relation.c:2068 +#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "funktioner i FROM kan returnera som mest %d kolumner" -#: parser/parse_relation.c:2098 +#: parser/parse_relation.c:2096 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "funktionen %s har %d kolumner tillgängliga men %d kolumner angivna" -#: parser/parse_relation.c:2180 +#: parser/parse_relation.c:2177 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "VALUES-lista \"%s\" har %d kolumner tillgängliga men %d kolumner angivna" -#: parser/parse_relation.c:2246 +#: parser/parse_relation.c:2242 #, c-format msgid "joins can have at most %d columns" msgstr "joins kan ha som mest %d kolumner" -#: parser/parse_relation.c:2271 +#: parser/parse_relation.c:2267 #, c-format msgid "join expression \"%s\" has %d columns available but %d columns specified" msgstr "join-uttryck \"%s\" har %d kolumner tillgängliga men %d kolumner angivna" -#: parser/parse_relation.c:2361 +#: parser/parse_relation.c:2357 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "WITH-fråga \"%s\" har ingen RETURNING-klausul" -#: parser/parse_relation.c:3632 +#: parser/parse_relation.c:3635 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "Kanske tänkte du referera till tabellaliaset \"%s\"." -#: parser/parse_relation.c:3644 +#: parser/parse_relation.c:3647 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "För att referera till den tabellen så måste denna subfråga markeras som LATERAL." -#: parser/parse_relation.c:3650 +#: parser/parse_relation.c:3653 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "saknar FROM-klausulpost för tabell \"%s\"" -#: parser/parse_relation.c:3690 +#: parser/parse_relation.c:3693 #, c-format msgid "There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query." msgstr "Det finns kolumner med namn \"%s\", men de är i tabeller som inte kan refereras till från denna del av frågan." -#: parser/parse_relation.c:3692 +#: parser/parse_relation.c:3695 #, c-format msgid "Try using a table-qualified name." msgstr "Försök med ett tabell-prefixat namn." -#: parser/parse_relation.c:3700 +#: parser/parse_relation.c:3703 #, c-format msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." msgstr "Det finns en kolumn med namn \"%s\" i tabell \"%s\" men den kan inte refereras till från denna del av frågan." -#: parser/parse_relation.c:3703 +#: parser/parse_relation.c:3706 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "För att referera till den kolumnen så måste denna subfråga markeras som LATERAL." -#: parser/parse_relation.c:3705 +#: parser/parse_relation.c:3708 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "För att referera till den kolumnen så måste du använda ett tabell-prefixat namn." -#: parser/parse_relation.c:3725 +#: parser/parse_relation.c:3728 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "Kanske tänkte du referera till kolumnen \"%s.%s\"." -#: parser/parse_relation.c:3739 +#: parser/parse_relation.c:3742 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "Kanske tänkte du referera till kolumnen \"%s.%s\" eller kolumnen \"%s.%s\"." -#: parser/parse_target.c:481 parser/parse_target.c:796 +#: parser/parse_target.c:480 parser/parse_target.c:795 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "kan inte skriva till systemkolumn \"%s\"" -#: parser/parse_target.c:509 +#: parser/parse_target.c:508 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "kan inte sätta ett array-element till DEFAULT" -#: parser/parse_target.c:514 +#: parser/parse_target.c:513 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "kan inte sätta ett underfält till DEFAULT" -#: parser/parse_target.c:588 +#: parser/parse_target.c:587 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "kolumn \"%s\" har typ %s men uttrycket är av typ %s" -#: parser/parse_target.c:780 +#: parser/parse_target.c:779 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type" msgstr "kan inte tilldela till fält \"%s\" i kolumn \"%s\" då dess typ %s inte är en composit-typ" -#: parser/parse_target.c:789 +#: parser/parse_target.c:788 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s" msgstr "kan inte tilldela till fält \"%s\" i kolumn \"%s\" då det inte finns någon sådan kolumn i datatypen %s" -#: parser/parse_target.c:869 +#: parser/parse_target.c:877 #, c-format msgid "subscripted assignment to \"%s\" requires type %s but expression is of type %s" msgstr "tilldelning med array-index till \"%s\" kräver typ %s men uttrycket har typ %s" -#: parser/parse_target.c:879 +#: parser/parse_target.c:887 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "underfält \"%s\" har typ %s men uttrycket har typ %s" -#: parser/parse_target.c:1314 +#: parser/parse_target.c:1327 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "SELECT * utan tabeller angivna är inte giltigt" @@ -18569,8 +19135,8 @@ msgstr "dålig %%TYPE-referens (för många punktade namn): %s" msgid "type reference %s converted to %s" msgstr "typreferens %s konverterad till %s" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:395 -#: utils/cache/typcache.c:450 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 +#: utils/cache/typcache.c:452 #, c-format msgid "type \"%s\" is only a shell" msgstr "typ \"%s\" är bara ett skal" @@ -18590,330 +19156,325 @@ msgstr "typmodifierare måste vare enkla konstanter eller identifierare" msgid "invalid type name \"%s\"" msgstr "ogiltigt typnamn \"%s\"" -#: parser/parse_utilcmd.c:264 +#: parser/parse_utilcmd.c:263 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "kan inte skapa partitionerad tabell som barnarv" -#: parser/parse_utilcmd.c:580 +#: parser/parse_utilcmd.c:475 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "kan inte sätta loggningsstatus för en temporär sekvens" + +#: parser/parse_utilcmd.c:611 #, c-format msgid "array of serial is not implemented" msgstr "array med serial är inte implementerat" -#: parser/parse_utilcmd.c:659 parser/parse_utilcmd.c:671 -#: parser/parse_utilcmd.c:730 +#: parser/parse_utilcmd.c:690 parser/parse_utilcmd.c:702 +#: parser/parse_utilcmd.c:761 #, c-format msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "motstridiga NULL/NOT NULL-villkor för kolumnen \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:683 +#: parser/parse_utilcmd.c:714 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "multipla default-värden angivna för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:700 +#: parser/parse_utilcmd.c:731 #, c-format msgid "identity columns are not supported on typed tables" msgstr "identitetskolumner stöds inte på typade tabeller" -#: parser/parse_utilcmd.c:704 +#: parser/parse_utilcmd.c:735 #, c-format msgid "identity columns are not supported on partitions" msgstr "identitetskolumner stöds inte för partitioner" -#: parser/parse_utilcmd.c:713 +#: parser/parse_utilcmd.c:744 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "multipla identitetspecifikationer för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:743 +#: parser/parse_utilcmd.c:774 #, c-format msgid "generated columns are not supported on typed tables" msgstr "genererade kolumner stöds inte på typade tabeller" -#: parser/parse_utilcmd.c:747 +#: parser/parse_utilcmd.c:778 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "multipla genereringsklausuler angivna för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:765 parser/parse_utilcmd.c:880 +#: parser/parse_utilcmd.c:796 parser/parse_utilcmd.c:911 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "primärnyckelvillkor stöds inte på främmande tabeller" -#: parser/parse_utilcmd.c:774 parser/parse_utilcmd.c:890 +#: parser/parse_utilcmd.c:805 parser/parse_utilcmd.c:921 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "unika villkor stöds inte på främmande tabeller" -#: parser/parse_utilcmd.c:819 +#: parser/parse_utilcmd.c:850 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "både default och identity angiven för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:827 +#: parser/parse_utilcmd.c:858 #, c-format msgid "both default and generation expression specified for column \"%s\" of table \"%s\"" msgstr "både default och genereringsuttryck angiven för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:835 +#: parser/parse_utilcmd.c:866 #, c-format msgid "both identity and generation expression specified for column \"%s\" of table \"%s\"" msgstr "både identity och genereringsuttryck angiven för kolumn \"%s\" i tabell \"%s\"" -#: parser/parse_utilcmd.c:900 +#: parser/parse_utilcmd.c:931 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "uteslutningsvillkor stöds inte på främmande tabeller" -#: parser/parse_utilcmd.c:906 -#, c-format -msgid "exclusion constraints are not supported on partitioned tables" -msgstr "uteslutningsvillkor stöds inte för partitionerade tabeller" - -#: parser/parse_utilcmd.c:971 +#: parser/parse_utilcmd.c:996 #, c-format msgid "LIKE is not supported for creating foreign tables" msgstr "LIKE stöds inte för att skapa främmande tabeller" -#: parser/parse_utilcmd.c:984 +#: parser/parse_utilcmd.c:1009 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "relationen \"%s\" är ogiltig i LIKE-klausul" -#: parser/parse_utilcmd.c:1741 parser/parse_utilcmd.c:1849 +#: parser/parse_utilcmd.c:1736 parser/parse_utilcmd.c:1844 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "Index \"%s\" innehåller en hela-raden-referens." -#: parser/parse_utilcmd.c:2236 +#: parser/parse_utilcmd.c:2242 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "kan inte använda ett existerande index i CREATE TABLE" -#: parser/parse_utilcmd.c:2256 +#: parser/parse_utilcmd.c:2262 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "index \"%s\" är redan associerad med ett villkor" -#: parser/parse_utilcmd.c:2271 -#, c-format -msgid "index \"%s\" is not valid" -msgstr "index \"%s\" är inte giltigt" - -#: parser/parse_utilcmd.c:2277 +#: parser/parse_utilcmd.c:2283 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\" är inte ett unikt index" -#: parser/parse_utilcmd.c:2278 parser/parse_utilcmd.c:2285 -#: parser/parse_utilcmd.c:2292 parser/parse_utilcmd.c:2369 +#: parser/parse_utilcmd.c:2284 parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2298 parser/parse_utilcmd.c:2375 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "Kan inte skapa en primärnyckel eller ett unikt villkor med hjälp av ett sådant index." -#: parser/parse_utilcmd.c:2284 +#: parser/parse_utilcmd.c:2290 #, c-format msgid "index \"%s\" contains expressions" msgstr "index \"%s\" innehåller uttryck" -#: parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2297 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\" är ett partiellt index" -#: parser/parse_utilcmd.c:2303 +#: parser/parse_utilcmd.c:2309 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\" är ett \"deferrable\" index" -#: parser/parse_utilcmd.c:2304 +#: parser/parse_utilcmd.c:2310 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "Kan inte skapa ett icke-\"deferrable\" integritetsvillkor från ett \"deferrable\" index." -#: parser/parse_utilcmd.c:2368 +#: parser/parse_utilcmd.c:2374 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "index \"%s\" kolumn nummer %d har ingen standard för sorteringsbeteende" -#: parser/parse_utilcmd.c:2525 +#: parser/parse_utilcmd.c:2531 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "kolumn \"%s\" finns med två gånger i primära nyckel-villkoret" -#: parser/parse_utilcmd.c:2531 +#: parser/parse_utilcmd.c:2537 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "kolumn \"%s\" finns med två gånger i unique-villkoret" -#: parser/parse_utilcmd.c:2878 +#: parser/parse_utilcmd.c:2871 #, c-format msgid "index expressions and predicates can refer only to the table being indexed" msgstr "indexuttryck och predikat kan bara referera till tabellen som indexeras" -#: parser/parse_utilcmd.c:2950 +#: parser/parse_utilcmd.c:2943 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "statistikuttryck kan bara referera till tabellen som är refererad" -#: parser/parse_utilcmd.c:2993 +#: parser/parse_utilcmd.c:2986 #, c-format msgid "rules on materialized views are not supported" msgstr "regler på materialiserade vyer stöds inte" -#: parser/parse_utilcmd.c:3053 +#: parser/parse_utilcmd.c:3046 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "WHERE-villkor i regel kan inte innehålla referenser till andra relationer" -#: parser/parse_utilcmd.c:3125 +#: parser/parse_utilcmd.c:3118 #, c-format msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions" msgstr "regler med WHERE-villkor kan bara innehålla SELECT-, INSERT-, UPDATE- eller DELETE-handlingar" -#: parser/parse_utilcmd.c:3143 parser/parse_utilcmd.c:3244 -#: rewrite/rewriteHandler.c:539 rewrite/rewriteManip.c:1087 +#: parser/parse_utilcmd.c:3136 parser/parse_utilcmd.c:3237 +#: rewrite/rewriteHandler.c:544 rewrite/rewriteManip.c:1096 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "UNION-/INTERSECT-/EXCEPT-satser med villkor är inte implementerat" -#: parser/parse_utilcmd.c:3161 +#: parser/parse_utilcmd.c:3154 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "ON SELECT-regel kan inte använda OLD" -#: parser/parse_utilcmd.c:3165 +#: parser/parse_utilcmd.c:3158 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "ON SELECT-regel kan inte använda NEW" -#: parser/parse_utilcmd.c:3174 +#: parser/parse_utilcmd.c:3167 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "ON INSERT-regel kan inte använda OLD" -#: parser/parse_utilcmd.c:3180 +#: parser/parse_utilcmd.c:3173 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "ON DELETE-regel kan inte använda NEW" -#: parser/parse_utilcmd.c:3208 +#: parser/parse_utilcmd.c:3201 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "kan inte referera till OLD i WITH-fråga" -#: parser/parse_utilcmd.c:3215 +#: parser/parse_utilcmd.c:3208 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "kan inte referera till NEW i WITH-fråga" -#: parser/parse_utilcmd.c:3667 +#: parser/parse_utilcmd.c:3664 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "felplacerad DEFERRABLE-klausul" -#: parser/parse_utilcmd.c:3672 parser/parse_utilcmd.c:3687 +#: parser/parse_utilcmd.c:3669 parser/parse_utilcmd.c:3684 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "multipla DEFERRABLE/NOT DEFERRABLE-klausuler tillåts inte" -#: parser/parse_utilcmd.c:3682 +#: parser/parse_utilcmd.c:3679 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "felplacerad NOT DEFERRABLE-klausul" -#: parser/parse_utilcmd.c:3703 +#: parser/parse_utilcmd.c:3700 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "felplacerad INITIALLY DEFERRED-klausul" -#: parser/parse_utilcmd.c:3708 parser/parse_utilcmd.c:3734 +#: parser/parse_utilcmd.c:3705 parser/parse_utilcmd.c:3731 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "multipla INITIALLY IMMEDIATE/DEFERRED-klausuler tillåts inte" -#: parser/parse_utilcmd.c:3729 +#: parser/parse_utilcmd.c:3726 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "felplacerad klausul INITIALLY IMMEDIATE" -#: parser/parse_utilcmd.c:3922 +#: parser/parse_utilcmd.c:3919 #, c-format msgid "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "CREATE anger ett schema (%s) som skiljer sig från det som skapas (%s)" -#: parser/parse_utilcmd.c:3957 +#: parser/parse_utilcmd.c:3954 #, c-format msgid "\"%s\" is not a partitioned table" msgstr "\"%s\" är inte en partitionerad tabell" -#: parser/parse_utilcmd.c:3964 +#: parser/parse_utilcmd.c:3961 #, c-format msgid "table \"%s\" is not partitioned" msgstr "tabell \"%s\" är inte partitionerad" -#: parser/parse_utilcmd.c:3971 +#: parser/parse_utilcmd.c:3968 #, c-format msgid "index \"%s\" is not partitioned" msgstr "index \"%s\" är inte partitionerad" -#: parser/parse_utilcmd.c:4011 +#: parser/parse_utilcmd.c:4008 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "en hash-partitionerad tabell får inte ha en standardpartition" -#: parser/parse_utilcmd.c:4028 +#: parser/parse_utilcmd.c:4025 #, c-format msgid "invalid bound specification for a hash partition" msgstr "ogiltig gränsangivelse för hash-partition" -#: parser/parse_utilcmd.c:4034 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4031 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "modulo för hash-partition vara ett heltalsvärde större än noll" -#: parser/parse_utilcmd.c:4041 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4038 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "rest för hash-partition måste vara lägre än modulo" -#: parser/parse_utilcmd.c:4054 +#: parser/parse_utilcmd.c:4051 #, c-format msgid "invalid bound specification for a list partition" msgstr "ogiltig gränsangivelse för listpartition" -#: parser/parse_utilcmd.c:4107 +#: parser/parse_utilcmd.c:4104 #, c-format msgid "invalid bound specification for a range partition" msgstr "ogiltig gränsangivelse för range-partition" -#: parser/parse_utilcmd.c:4113 +#: parser/parse_utilcmd.c:4110 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "FROM måste ge exakt ett värde per partitionerande kolumn" -#: parser/parse_utilcmd.c:4117 +#: parser/parse_utilcmd.c:4114 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "TO måste ge exakt ett värde per partitionerande kolumn" -#: parser/parse_utilcmd.c:4231 +#: parser/parse_utilcmd.c:4228 #, c-format msgid "cannot specify NULL in range bound" msgstr "kan inte ange NULL i range-gräns" -#: parser/parse_utilcmd.c:4280 +#: parser/parse_utilcmd.c:4277 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "varje gräns efter MAXVALUE måste också vara MAXVALUE" -#: parser/parse_utilcmd.c:4287 +#: parser/parse_utilcmd.c:4284 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "varje gräns efter MINVALUE måste också vara MINVALUE" -#: parser/parse_utilcmd.c:4330 +#: parser/parse_utilcmd.c:4327 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "angivet värde kan inte typomvandlas till typ %s för kolumn \"%s\"" @@ -18926,12 +19487,12 @@ msgstr "UESCAPE måste följas av en enkel stränglitteral" msgid "invalid Unicode escape character" msgstr "ogiltigt Unicode-escapetecken" -#: parser/parser.c:347 scan.l:1390 +#: parser/parser.c:347 scan.l:1393 #, c-format msgid "invalid Unicode escape value" msgstr "ogiltigt Unicode-escapevärde" -#: parser/parser.c:494 scan.l:701 utils/adt/varlena.c:6505 +#: parser/parser.c:494 scan.l:716 utils/adt/varlena.c:6640 #, c-format msgid "invalid Unicode escape" msgstr "ogiltig Unicode-escapesekvens" @@ -18941,8 +19502,8 @@ msgstr "ogiltig Unicode-escapesekvens" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "Unicode-escapesekvenser måste vara \\XXXX eller \\+XXXXXX." -#: parser/parser.c:523 scan.l:662 scan.l:678 scan.l:694 -#: utils/adt/varlena.c:6530 +#: parser/parser.c:523 scan.l:677 scan.l:693 scan.l:709 +#: utils/adt/varlena.c:6665 #, c-format msgid "invalid Unicode surrogate pair" msgstr "ogiltigt Unicode-surrogatpar" @@ -18952,89 +19513,89 @@ msgstr "ogiltigt Unicode-surrogatpar" msgid "identifier \"%s\" will be truncated to \"%.*s\"" msgstr "identifierare \"%s\" kommer trunkeras till \"%.*s\"" -#: partitioning/partbounds.c:2921 +#: partitioning/partbounds.c:2920 #, c-format msgid "partition \"%s\" conflicts with existing default partition \"%s\"" msgstr "partition \"%s\" står i konflikt med existerande default-partition \"%s\"" -#: partitioning/partbounds.c:2973 partitioning/partbounds.c:2992 -#: partitioning/partbounds.c:3014 +#: partitioning/partbounds.c:2972 partitioning/partbounds.c:2991 +#: partitioning/partbounds.c:3013 #, c-format msgid "every hash partition modulus must be a factor of the next larger modulus" msgstr "varje hash-partition-modulo måste vara en faktror av näste högre modulo" -#: partitioning/partbounds.c:2974 partitioning/partbounds.c:3015 +#: partitioning/partbounds.c:2973 partitioning/partbounds.c:3014 #, c-format msgid "The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\"." msgstr "Ny modulon %d är inte en faktor av %d som är modulo för den existerande partitionen \"%s\"." -#: partitioning/partbounds.c:2993 +#: partitioning/partbounds.c:2992 #, c-format msgid "The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\"." msgstr "Ny modulon %d är inte delbar med %d som är modulo för den existerande paritionen \"%s\"." -#: partitioning/partbounds.c:3128 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "tom intervallsgräns angiven för partition \"%s\"" -#: partitioning/partbounds.c:3130 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." -msgstr "Angiven lägre gräns %s är större än eller lika med övre gräns %s." +msgstr "Angiven undre gräns %s är större än eller lika med övre gräns %s." -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "partition \"%s\" skulle överlappa partition \"%s\"" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"" msgstr "hoppade över skanning av främmand tabell \"%s\" som er en partition för standardpartitionen \"%s\"" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "remainder for hash partition must be an integer value greater than or equal to zero" msgstr "rest för hash-partition måste vara ett heltalsvärde större än eller lika med noll" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\" är inte en hash-partitionerad tabell" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" msgstr "antalet partitioneringskolumner (%d) stämmer inte med antalet partioneringsnycklas som angivits (%d)" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "kolumn %d i partitioneringsnyckeln har typ %s men använt värde har typ %s" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"" msgstr "kolumn %d i partitioneringsnyckeln har typ \"%s\" men använt värde har typ \"%s\"" -#: port/pg_sema.c:209 port/pg_shmem.c:708 port/posix_sema.c:209 -#: port/sysv_sema.c:323 port/sysv_shmem.c:708 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 +#: port/sysv_sema.c:329 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "kunde inte göra stat() på datakatalog \"%s\": %m" -#: port/pg_shmem.c:223 port/sysv_shmem.c:223 +#: port/pg_shmem.c:224 port/sysv_shmem.c:224 #, c-format msgid "could not create shared memory segment: %m" msgstr "kunde inte skapa delat minnessegment: %m" -#: port/pg_shmem.c:224 port/sysv_shmem.c:224 +#: port/pg_shmem.c:225 port/sysv_shmem.c:225 #, c-format msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)." msgstr "Misslyckade systemanropet var semget(key=%lu, size=%zu, 0%o)." -#: port/pg_shmem.c:228 port/sysv_shmem.c:228 +#: port/pg_shmem.c:229 port/sysv_shmem.c:229 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n" @@ -19043,7 +19604,7 @@ msgstr "" "Felet betyder vanligen att PostgreSQLs begäran av delat minnessegment överskred kärnans SHMMAX-parameter eller möjligen att det är lägre än kärnans SHMMIN-parameter.\n" "PostgreSQLs dokumentation innehåller mer information om konfigueration av delat minne." -#: port/pg_shmem.c:235 port/sysv_shmem.c:235 +#: port/pg_shmem.c:236 port/sysv_shmem.c:236 #, c-format msgid "" "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n" @@ -19052,7 +19613,7 @@ msgstr "" "Felet betyder vanligen att PostgreSQLs begäran av delat minnessegment överskred kärnans SHMALL-parameter. Du kan behöva rekonfigurera kärnan med ett större SHMALL.\n" "PostgreSQLs dokumentation innehåller mer information om konfigueration av delat minne." -#: port/pg_shmem.c:241 port/sysv_shmem.c:241 +#: port/pg_shmem.c:242 port/sysv_shmem.c:242 #, c-format msgid "" "This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n" @@ -19061,59 +19622,59 @@ msgstr "" "Felet betyder *inte* att diskutrymmet tagit slut. Felet sker aningen om alla tillgängliga ID-nummer för delat minne tagit slut och då behöver du öka kärnans SHMMNI-parameter eller för att systemets totala gräns för delat minne ha nåtts.\n" "PostgreSQLs dokumentation innehåller mer information om konfigueration av delat minne." -#: port/pg_shmem.c:583 port/sysv_shmem.c:583 port/win32_shmem.c:641 +#: port/pg_shmem.c:584 port/sysv_shmem.c:584 port/win32_shmem.c:646 #, c-format -msgid "huge_page_size must be 0 on this platform." -msgstr "huge_page_size måste vara 0 på denna plattform." +msgid "\"huge_page_size\" must be 0 on this platform." +msgstr "\"huge_page_size\" måste vara 0 på denna plattform." -#: port/pg_shmem.c:646 port/sysv_shmem.c:646 +#: port/pg_shmem.c:655 port/sysv_shmem.c:655 #, c-format msgid "could not map anonymous shared memory: %m" msgstr "kunde inte mappa anonymt delat minne: %m" -#: port/pg_shmem.c:648 port/sysv_shmem.c:648 +#: port/pg_shmem.c:657 port/sysv_shmem.c:657 #, c-format -msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections." -msgstr "Detta fel betyder vanligtvis att PostgreSQL:s begäran av delat minnessegment överskrider mängden tillgängligt minne, swap eller stora sidor. För att minska begärd storlek (nu %zu byte) minska PostgreSQL:s användning av delat minne t.ex. genom att dra ner på shared_buffers eller max_connections." +msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing \"shared_buffers\" or \"max_connections\"." +msgstr "Detta fel betyder vanligtvis att PostgreSQL:s begäran av delat minnessegment överskrider mängden tillgängligt minne, swap eller stora sidor. För att minska begärd storlek (nu %zu byte) minska PostgreSQL:s användning av delat minne t.ex. genom att dra ner på \"shared_buffers\" eller \"max_connections\"." -#: port/pg_shmem.c:716 port/sysv_shmem.c:716 +#: port/pg_shmem.c:725 port/sysv_shmem.c:725 #, c-format msgid "huge pages not supported on this platform" msgstr "stora sidor stöds inte på denna plattform" -#: port/pg_shmem.c:723 port/sysv_shmem.c:723 +#: port/pg_shmem.c:732 port/sysv_shmem.c:732 #, c-format -msgid "huge pages not supported with the current shared_memory_type setting" -msgstr "stora sidor stöds inte vid nuvarande inställning av shared_memory_type" +msgid "huge pages not supported with the current \"shared_memory_type\" setting" +msgstr "stora sidor stöds inte vid nuvarande inställning av \"shared_memory_type\"" -#: port/pg_shmem.c:783 port/sysv_shmem.c:783 utils/init/miscinit.c:1351 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1401 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "redan existerande delat minnesblock (nyckel %lu, ID %lu) används fortfarande" -#: port/pg_shmem.c:786 port/sysv_shmem.c:786 utils/init/miscinit.c:1353 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1403 #, c-format msgid "Terminate any old server processes associated with data directory \"%s\"." msgstr "Stäng ner gamla serverprocesser som hör ihop med datakatalogen \"%s\"." -#: port/sysv_sema.c:120 +#: port/sysv_sema.c:126 #, c-format msgid "could not create semaphores: %m" msgstr "kan inte skapa semafor: %m" -#: port/sysv_sema.c:121 +#: port/sysv_sema.c:127 #, c-format msgid "Failed system call was semget(%lu, %d, 0%o)." msgstr "Misslyckade systemanropet var semget(%lu, %d, 0%o)." -#: port/sysv_sema.c:125 +#: port/sysv_sema.c:131 #, c-format msgid "" -"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its max_connections parameter.\n" +"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its \"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring your system for PostgreSQL." -msgstr "Detta fel betyder *inte* att disken blivit full. Detta fel kommer när systemgränsen för maximalt antal semaforvektorer (SEMMNI) överskridits eller när systemets globala maximum för semaforer (SEMMNS) överskridits. Du behöver öka respektive kernel-parameter. Alternativt kan du minska PostgreSQL:s användning av semaforer genom att dra ner på parametern max_connections. PostgreSQL:s dokumentation innehåller mer information om hur du konfigurerar systemet för PostgreSQL." +msgstr "Detta fel betyder *inte* att disken blivit full. Detta fel kommer när systemgränsen för maximalt antal semaforvektorer (SEMMNI) överskridits eller när systemets globala maximum för semaforer (SEMMNS) överskridits. Du behöver öka respektive kernel-parameter. Alternativt kan du minska PostgreSQL:s användning av semaforer genom att dra ner på parametern \"max_connections\". PostgreSQL:s dokumentation innehåller mer information om hur du konfigurerar systemet för PostgreSQL." -#: port/sysv_sema.c:155 +#: port/sysv_sema.c:161 #, c-format msgid "You possibly need to raise your kernel's SEMVMX value to be at least %d. Look into the PostgreSQL documentation for details." msgstr "Du kan behöva öka kärnans SEMVMX-värde till minst %d. Se PostgreSQL:s dokumentation för mer information." @@ -19238,972 +19799,877 @@ msgstr "Misslyckat systemanrop var DuplicateHandle." msgid "Failed system call was MapViewOfFileEx." msgstr "Misslyckat systemanrop var MapViewOfFileEx." -#: postmaster/autovacuum.c:417 -#, c-format -msgid "could not fork autovacuum launcher process: %m" -msgstr "kunde inte starta autovacuum-process: %m" - -#: postmaster/autovacuum.c:764 +#: postmaster/autovacuum.c:686 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "autovacuum-arbetaren tog för lång tid på sig att starta; avbruten" -#: postmaster/autovacuum.c:1489 -#, c-format -msgid "could not fork autovacuum worker process: %m" -msgstr "kunde inte starta autovacuum-arbetsprocess: %m" - -#: postmaster/autovacuum.c:2334 +#: postmaster/autovacuum.c:2203 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "autovacuum: slänger övergiven temptabell \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2570 +#: postmaster/autovacuum.c:2439 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "automatisk vacuum av tabell \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2573 +#: postmaster/autovacuum.c:2442 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "automatisk analys av tabell \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2767 +#: postmaster/autovacuum.c:2636 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "processar arbetspost för relation \"%s.%s.%s\"" -#: postmaster/autovacuum.c:3381 +#: postmaster/autovacuum.c:3254 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "autovacuum har inte startats på grund av en felkonfigurering" -#: postmaster/autovacuum.c:3382 +#: postmaster/autovacuum.c:3255 #, c-format msgid "Enable the \"track_counts\" option." msgstr "Slå på flaggan \"track_counts\"." -#: postmaster/bgworker.c:259 +#: postmaster/bgworker.c:260 #, c-format msgid "inconsistent background worker state (max_worker_processes=%d, total_slots=%d)" msgstr "inkonsistent tillstånd i bakgrundsarbetare (max_worker_processes=%d, total_slots=%d)" -#: postmaster/bgworker.c:669 +#: postmaster/bgworker.c:651 #, c-format msgid "background worker \"%s\": background workers without shared memory access are not supported" msgstr "bakgrundsarbetare \"%s\": bakgrundsarbetare utan access till delat minne stöds inte" -#: postmaster/bgworker.c:680 +#: postmaster/bgworker.c:662 #, c-format msgid "background worker \"%s\": cannot request database access if starting at postmaster start" msgstr "bakgrundsarbetare \"%s\" kan inte få databasaccess om den startar när postmaster startar" -#: postmaster/bgworker.c:694 +#: postmaster/bgworker.c:676 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "bakgrundsarbetare \"%s\": ogiltigt omstartsintervall" -#: postmaster/bgworker.c:709 +#: postmaster/bgworker.c:691 #, c-format msgid "background worker \"%s\": parallel workers may not be configured for restart" msgstr "bakgrundsarbetare \"%s\": parallella arbetare kan inte konfigureras för omstart" -#: postmaster/bgworker.c:733 tcop/postgres.c:3255 +#: postmaster/bgworker.c:715 tcop/postgres.c:3312 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "terminerar bakgrundsarbetare \"%s\" pga administratörskommando" -#: postmaster/bgworker.c:890 +#: postmaster/bgworker.c:888 #, c-format -msgid "background worker \"%s\": must be registered in shared_preload_libraries" -msgstr "bakgrundsarbetare \"%s\": måste vara registrerad i shared_preload_libraries" +msgid "background worker \"%s\": must be registered in \"shared_preload_libraries\"" +msgstr "bakgrundsarbetare \"%s\": måste vara registrerad i \"shared_preload_libraries\"" -#: postmaster/bgworker.c:902 +#: postmaster/bgworker.c:911 #, c-format msgid "background worker \"%s\": only dynamic background workers can request notification" msgstr "bakgrundsarbetare \"%s\": bara dynamiska bakgrundsarbetare kan be om notifiering" -#: postmaster/bgworker.c:917 +#: postmaster/bgworker.c:926 #, c-format msgid "too many background workers" msgstr "för många bakgrundsarbetare" -#: postmaster/bgworker.c:918 +#: postmaster/bgworker.c:927 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "Up to %d background workers can be registered with the current settings." msgstr[0] "Upp till %d bakgrundsarbetare kan registreras med nuvarande inställning." msgstr[1] "Upp till %d bakgrundsarbetare kan registreras med nuvarande inställning." -#: postmaster/bgworker.c:922 +#: postmaster/bgworker.c:931 postmaster/checkpointer.c:445 #, c-format -msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "Överväg att öka konfigurationsparametern \"max_worker_processes\"." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "Överväg att öka konfigurationsparametern \"%s\"." -#: postmaster/checkpointer.c:431 +#: postmaster/checkpointer.c:441 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" msgstr[0] "checkpoint:s sker för ofta (%d sekund emellan)" msgstr[1] "checkpoint:s sker för ofta (%d sekunder emellan)" -#: postmaster/checkpointer.c:435 -#, c-format -msgid "Consider increasing the configuration parameter \"max_wal_size\"." -msgstr "Överväg att öka konfigurationsparametern \"max_wal_size\"." - -#: postmaster/checkpointer.c:1059 +#: postmaster/checkpointer.c:1067 #, c-format msgid "checkpoint request failed" msgstr "checkpoint-behgäran misslyckades" -#: postmaster/checkpointer.c:1060 +#: postmaster/checkpointer.c:1068 #, c-format msgid "Consult recent messages in the server log for details." msgstr "Se senaste meddelanden i serverloggen för mer information." -#: postmaster/pgarch.c:416 +#: postmaster/launch_backend.c:381 +#, c-format +msgid "could not execute server process \"%s\": %m" +msgstr "kunde inte köra serverprocess \"%s\": %m" + +#: postmaster/launch_backend.c:434 +#, c-format +msgid "could not create backend parameter file mapping: error code %lu" +msgstr "kunde inte skapa fil-mapping för backend-parametrar: felkod %lu" + +#: postmaster/launch_backend.c:442 +#, c-format +msgid "could not map backend parameter memory: error code %lu" +msgstr "kunde inte mappa minne för backend-parametrar: felkod %lu" + +#: postmaster/launch_backend.c:459 +#, c-format +msgid "subprocess command line too long" +msgstr "subprocessens kommando är för långt" + +#: postmaster/launch_backend.c:477 +#, c-format +msgid "CreateProcess() call failed: %m (error code %lu)" +msgstr "Anrop till CreateProcess() misslyckades: %m (felkod %lu)" + +#: postmaster/launch_backend.c:504 +#, c-format +msgid "could not unmap view of backend parameter file: error code %lu" +msgstr "kunde inte avmappa vy för backend:ens parameterfil: felkod %lu" + +#: postmaster/launch_backend.c:508 +#, c-format +msgid "could not close handle to backend parameter file: error code %lu" +msgstr "kunde inte stänga \"handle\" till backend:ens parameterfil: felkod %lu" + +#: postmaster/launch_backend.c:530 #, c-format -msgid "archive_mode enabled, yet archiving is not configured" -msgstr "archive_mode är påslagen, men ändå är arkivering inte konfigurerad" +msgid "giving up after too many tries to reserve shared memory" +msgstr "ger upp efter för många försök att reservera delat minne" + +#: postmaster/launch_backend.c:531 +#, c-format +msgid "This might be caused by ASLR or antivirus software." +msgstr "Detta kan orsakas av ASLR eller antivirusprogram." + +#: postmaster/launch_backend.c:834 +#, c-format +msgid "could not duplicate socket %d for use in backend: error code %d" +msgstr "kunde inte duplicera uttag (socket) %d för att använda i backend: felkod %d" + +#: postmaster/launch_backend.c:866 +#, c-format +msgid "could not create inherited socket: error code %d\n" +msgstr "kunde inte skapa ärvt uttag (socket): felkod %d\n" + +#: postmaster/launch_backend.c:895 +#, c-format +msgid "could not open backend variables file \"%s\": %m\n" +msgstr "kunde inte öppna bakändans variabelfil \"%s\": %m\n" + +#: postmaster/launch_backend.c:901 +#, c-format +msgid "could not read from backend variables file \"%s\": %m\n" +msgstr "kunde inte läsa från bakändans variabelfil \"%s\": %m\n" + +#: postmaster/launch_backend.c:912 +#, c-format +msgid "could not read startup data from backend variables file \"%s\": %m\n" +msgstr "kunde inte uppstartsdata från bakändans variabelfil \"%s\": %m\n" + +#: postmaster/launch_backend.c:924 +#, c-format +msgid "could not remove file \"%s\": %m\n" +msgstr "kunde inte ta bort fil \"%s\": %m\n" + +#: postmaster/launch_backend.c:940 +#, c-format +msgid "could not map view of backend variables: error code %lu\n" +msgstr "kunde inte mappa in vy för bakgrundsvariabler: felkod %lu\n" + +#: postmaster/launch_backend.c:959 +#, c-format +msgid "could not unmap view of backend variables: error code %lu\n" +msgstr "kunde inte avmappa vy för bakgrundsvariabler: felkod %lu\n" + +#: postmaster/launch_backend.c:966 +#, c-format +msgid "could not close handle to backend parameter variables: error code %lu\n" +msgstr "kunde inte stänga \"handle\" till backend:ens parametervariabler: felkod %lu\n" + +#: postmaster/pgarch.c:428 +#, c-format +msgid "\"archive_mode\" enabled, yet archiving is not configured" +msgstr "\"archive_mode\" är påslagen, men ändå är arkivering inte konfigurerad" -#: postmaster/pgarch.c:438 +#: postmaster/pgarch.c:452 #, c-format msgid "removed orphan archive status file \"%s\"" msgstr "tog bort övergiven arkivstatusfil \"%s\": %m" -#: postmaster/pgarch.c:448 +#: postmaster/pgarch.c:462 #, c-format msgid "removal of orphan archive status file \"%s\" failed too many times, will try again later" msgstr "borttagning av övergiven arkivstatusfil \"%s\" misslyckades för många gånger, kommer försöka igen senare" -#: postmaster/pgarch.c:484 +#: postmaster/pgarch.c:498 #, c-format msgid "archiving write-ahead log file \"%s\" failed too many times, will try again later" msgstr "arkivering av write-ahead-logg-fil \"%s\" misslyckades för många gånger, kommer försöka igen senare" -#: postmaster/pgarch.c:791 postmaster/pgarch.c:830 +#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 #, c-format -msgid "both archive_command and archive_library set" -msgstr "både archive_command och archive_library är satt" +msgid "both \"archive_command\" and \"archive_library\" set" +msgstr "både \"archive_command\" och \"archive_library\" är satt" -#: postmaster/pgarch.c:792 postmaster/pgarch.c:831 +#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 #, c-format -msgid "Only one of archive_command, archive_library may be set." -msgstr "Bara en av archive_command och archive_library får sättas." +msgid "Only one of \"archive_command\", \"archive_library\" may be set." +msgstr "Bara en av \"archive_command\" och \"archive_library\" får sättas." -#: postmaster/pgarch.c:809 +#: postmaster/pgarch.c:897 #, c-format msgid "restarting archiver process because value of \"archive_library\" was changed" msgstr "startar om arkiveringsprocess då värdet på \"archive_library\" har ändrats" -#: postmaster/pgarch.c:846 +#: postmaster/pgarch.c:934 #, c-format msgid "archive modules have to define the symbol %s" msgstr "arkiveringsmoduler måste definiera symbolen %s" -#: postmaster/pgarch.c:852 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules must register an archive callback" msgstr "arkiveringsmoduler måste registrera en arkiverings-callback" -#: postmaster/postmaster.c:759 +#: postmaster/postmaster.c:661 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: ogiltigt argument till flagga -f: \"%s\"\n" -#: postmaster/postmaster.c:832 +#: postmaster/postmaster.c:734 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: ogiltigt argument till flagga -t: \"%s\"\n" -#: postmaster/postmaster.c:855 +#: postmaster/postmaster.c:757 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: ogiltigt argument: \"%s\"\n" -#: postmaster/postmaster.c:923 +#: postmaster/postmaster.c:825 +#, c-format +msgid "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" +msgstr "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) måste vara mindre än \"max_connections\" (%d)\n" + +#: postmaster/postmaster.c:833 #, c-format -msgid "%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must be less than max_connections (%d)\n" -msgstr "%s: superuser_reserved_connections (%d) plus reserved_connections (%d) måste vara mindre än max_connections (%d)\n" +msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" +msgstr "WAL-arkivering kan inte slås på när \"wal_level\" är \"minimal\"" -#: postmaster/postmaster.c:931 +#: postmaster/postmaster.c:836 #, c-format -msgid "WAL archival cannot be enabled when wal_level is \"minimal\"" -msgstr "WAL-arkivering kan inte slås på när wal_level är \"minimal\"" +msgid "WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be \"replica\" or \"logical\"" +msgstr "WAL-strömning (\"max_wal_senders\" > 0) kräver att \"wal_level\" är \"replica\" eller \"logical\"" -#: postmaster/postmaster.c:934 +#: postmaster/postmaster.c:839 #, c-format -msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or \"logical\"" -msgstr "WAL-strömning (max_wal_senders > 0) kräver wal_level \"replica\" eller \"logical\"" +msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" +msgstr "WAL kan inte summeras när \"wal_level\" är \"minimal\"" -#: postmaster/postmaster.c:942 +#: postmaster/postmaster.c:847 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "%s: ogiltiga datumtokentabeller, det behöver lagas\n" -#: postmaster/postmaster.c:1099 +#: postmaster/postmaster.c:1004 #, c-format msgid "could not create I/O completion port for child queue" msgstr "kunde inte skapa \"I/O completion port\" för barnkö" -#: postmaster/postmaster.c:1175 +#: postmaster/postmaster.c:1069 #, c-format msgid "ending log output to stderr" msgstr "avslutar loggutmatning till stderr" -#: postmaster/postmaster.c:1176 +#: postmaster/postmaster.c:1070 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "Framtida loggutmatning kommer gå till logg-destination \"%s\"." -#: postmaster/postmaster.c:1187 +#: postmaster/postmaster.c:1081 #, c-format msgid "starting %s" msgstr "startar %s" -#: postmaster/postmaster.c:1239 +#: postmaster/postmaster.c:1143 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "kunde inte skapa lyssnande uttag (socket) för \"%s\"" -#: postmaster/postmaster.c:1245 +#: postmaster/postmaster.c:1149 #, c-format msgid "could not create any TCP/IP sockets" msgstr "kunde inte skapa TCP/IP-uttag (socket)" -#: postmaster/postmaster.c:1277 +#: postmaster/postmaster.c:1181 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "DNSServiceRegister() misslyckades: felkod %ld" -#: postmaster/postmaster.c:1328 +#: postmaster/postmaster.c:1234 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "kunde inte skapa unix-domän-uttag (socket) i katalog \"%s\"" -#: postmaster/postmaster.c:1334 +#: postmaster/postmaster.c:1240 #, c-format msgid "could not create any Unix-domain sockets" msgstr "kunde inte skapa något Unix-domän-uttag (socket)" -#: postmaster/postmaster.c:1345 +#: postmaster/postmaster.c:1251 #, c-format msgid "no socket created for listening" msgstr "inget uttag (socket) skapat för lyssnande" -#: postmaster/postmaster.c:1376 +#: postmaster/postmaster.c:1282 #, c-format -msgid "%s: could not change permissions of external PID file \"%s\": %s\n" -msgstr "%s: kunde inte ändra rättigheter på extern PID-fil \"%s\": %s\n" +msgid "%s: could not change permissions of external PID file \"%s\": %m\n" +msgstr "%s: kunde inte ändra rättigheter på extern PID-fil \"%s\": %m\n" -#: postmaster/postmaster.c:1380 +#: postmaster/postmaster.c:1286 #, c-format -msgid "%s: could not write external PID file \"%s\": %s\n" -msgstr "%s: kunde inte skriva extern PID-fil \"%s\": %s\n" +msgid "%s: could not write external PID file \"%s\": %m\n" +msgstr "%s: kunde inte skriva extern PID-fil \"%s\": %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1408 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 #, c-format msgid "could not load %s" msgstr "kunde inte ladda \"%s\"" -#: postmaster/postmaster.c:1434 +#: postmaster/postmaster.c:1342 #, c-format msgid "postmaster became multithreaded during startup" msgstr "postmaster blev flertrådad under uppstart" -#: postmaster/postmaster.c:1435 +#: postmaster/postmaster.c:1343 postmaster/postmaster.c:3684 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "Sätt omgivningsvariabeln LC_ALL till en giltig lokal." -#: postmaster/postmaster.c:1536 +#: postmaster/postmaster.c:1442 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: kunde inte hitta min egna körbara fils sökväg" -#: postmaster/postmaster.c:1543 +#: postmaster/postmaster.c:1449 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: kunde inte hitta matchande postgres-binär" -#: postmaster/postmaster.c:1566 utils/misc/tzparser.c:340 +#: postmaster/postmaster.c:1472 utils/misc/tzparser.c:341 #, c-format msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location." msgstr "Detta tyder på en inkomplett PostgreSQL-installation alternativt att filen \"%s\" har flyttats bort från sin korrekta plats." -#: postmaster/postmaster.c:1593 +#: postmaster/postmaster.c:1499 #, c-format msgid "" "%s: could not find the database system\n" "Expected to find it in the directory \"%s\",\n" -"but could not open file \"%s\": %s\n" +"but could not open file \"%s\": %m\n" msgstr "" "%s: kunde inte hitta databassystemet\n" "Förväntade mig att hitta det i katalogen \"%s\",\n" -"men kunde inte öppna filen \"%s\": %s\n" +"men kunde inte öppna filen \"%s\": %m\n" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1890 +#: postmaster/postmaster.c:1789 #, c-format msgid "issuing %s to recalcitrant children" msgstr "skickar %s till motsträviga barn" -#: postmaster/postmaster.c:1912 +#: postmaster/postmaster.c:1811 #, c-format msgid "performing immediate shutdown because data directory lock file is invalid" msgstr "stänger ner omedelbart då datakatalogens låsfil är ogiltig" -#: postmaster/postmaster.c:1987 postmaster/postmaster.c:2015 -#, c-format -msgid "incomplete startup packet" -msgstr "ofullständigt startuppaket" - -#: postmaster/postmaster.c:1999 postmaster/postmaster.c:2032 -#, c-format -msgid "invalid length of startup packet" -msgstr "ogiltig längd på startuppaket" - -#: postmaster/postmaster.c:2061 -#, c-format -msgid "failed to send SSL negotiation response: %m" -msgstr "misslyckades att skicka SSL-förhandlingssvar: %m" - -#: postmaster/postmaster.c:2079 -#, c-format -msgid "received unencrypted data after SSL request" -msgstr "tog emot okrypterad data efter SSL-förfrågan" - -#: postmaster/postmaster.c:2080 postmaster/postmaster.c:2124 -#, c-format -msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." -msgstr "Detta kan antingen vara en bug i klientens mjukvara eller bevis på ett försök att utföra en attack av typen man-in-the-middle." - -#: postmaster/postmaster.c:2105 -#, c-format -msgid "failed to send GSSAPI negotiation response: %m" -msgstr "misslyckades att skicka GSSAPI-förhandlingssvar: %m" - -#: postmaster/postmaster.c:2123 -#, c-format -msgid "received unencrypted data after GSSAPI encryption request" -msgstr "tog emot okrypterad data efter GSSAPI-krypteringsförfrågan" - -#: postmaster/postmaster.c:2147 -#, c-format -msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" -msgstr "inget stöd för framändans protokoll %u.%u: servern stöder %u.0 till %u.%u" - -#: postmaster/postmaster.c:2214 -#, c-format -msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." -msgstr "Giltiga värden är: \"false\", 0, \"true\", 1, \"database\"." - -#: postmaster/postmaster.c:2255 -#, c-format -msgid "invalid startup packet layout: expected terminator as last byte" -msgstr "ogiltig startpaketlayout: förväntade en terminator som sista byte" - -#: postmaster/postmaster.c:2272 -#, c-format -msgid "no PostgreSQL user name specified in startup packet" -msgstr "inget PostgreSQL-användarnamn angivet i startuppaketet" - -#: postmaster/postmaster.c:2336 -#, c-format -msgid "the database system is starting up" -msgstr "databassystemet startar upp" - -#: postmaster/postmaster.c:2342 -#, c-format -msgid "the database system is not yet accepting connections" -msgstr "databassystemet tar ännu inte emot anslutningar" - -#: postmaster/postmaster.c:2343 -#, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "Konsistent återställningstillstånd har ännu inte uppnåtts." - -#: postmaster/postmaster.c:2347 -#, c-format -msgid "the database system is not accepting connections" -msgstr "databassystemet tar inte emot anslutningar" - -#: postmaster/postmaster.c:2348 -#, c-format -msgid "Hot standby mode is disabled." -msgstr "Hot standby-läge är avstängt." - -#: postmaster/postmaster.c:2353 -#, c-format -msgid "the database system is shutting down" -msgstr "databassystemet stänger ner" - -#: postmaster/postmaster.c:2358 -#, c-format -msgid "the database system is in recovery mode" -msgstr "databassystemet är återställningsläge" - -#: postmaster/postmaster.c:2363 storage/ipc/procarray.c:491 -#: storage/ipc/sinvaladt.c:306 storage/lmgr/proc.c:353 -#, c-format -msgid "sorry, too many clients already" -msgstr "ledsen, för många klienter" - -#: postmaster/postmaster.c:2450 +#: postmaster/postmaster.c:1874 #, c-format msgid "wrong key in cancel request for process %d" msgstr "fel nyckel i avbrytbegäran för process %d" -#: postmaster/postmaster.c:2462 +#: postmaster/postmaster.c:1886 #, c-format msgid "PID %d in cancel request did not match any process" msgstr "PID %d i avbrytbegäran matchade inte någon process" -#: postmaster/postmaster.c:2729 +#: postmaster/postmaster.c:2106 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "mottog SIGHUP, läser om konfigurationsfiler" #. translator: %s is a configuration file -#: postmaster/postmaster.c:2753 postmaster/postmaster.c:2757 +#: postmaster/postmaster.c:2134 postmaster/postmaster.c:2138 #, c-format msgid "%s was not reloaded" msgstr "%s laddades inte om" -#: postmaster/postmaster.c:2767 +#: postmaster/postmaster.c:2148 #, c-format msgid "SSL configuration was not reloaded" msgstr "SSL-konfiguration laddades inte om" -#: postmaster/postmaster.c:2857 +#: postmaster/postmaster.c:2234 #, c-format msgid "received smart shutdown request" msgstr "tog emot förfrågan om att stänga ner smart" -#: postmaster/postmaster.c:2898 +#: postmaster/postmaster.c:2275 #, c-format msgid "received fast shutdown request" msgstr "tog emot förfrågan om att stänga ner snabbt" -#: postmaster/postmaster.c:2916 +#: postmaster/postmaster.c:2293 #, c-format msgid "aborting any active transactions" msgstr "avbryter aktiva transaktioner" -#: postmaster/postmaster.c:2940 +#: postmaster/postmaster.c:2317 #, c-format msgid "received immediate shutdown request" msgstr "mottog begäran för omedelbar nedstängning" -#: postmaster/postmaster.c:3016 +#: postmaster/postmaster.c:2389 #, c-format msgid "shutdown at recovery target" msgstr "nedstängs vid återställningsmål" -#: postmaster/postmaster.c:3034 postmaster/postmaster.c:3070 +#: postmaster/postmaster.c:2407 postmaster/postmaster.c:2443 msgid "startup process" msgstr "uppstartprocess" -#: postmaster/postmaster.c:3037 +#: postmaster/postmaster.c:2410 #, c-format msgid "aborting startup due to startup process failure" msgstr "avbryter uppstart på grund av fel i startprocessen" -#: postmaster/postmaster.c:3110 +#: postmaster/postmaster.c:2485 #, c-format msgid "database system is ready to accept connections" msgstr "databassystemet är redo att ta emot anslutningar" -#: postmaster/postmaster.c:3131 +#: postmaster/postmaster.c:2506 msgid "background writer process" msgstr "bakgrundsskrivarprocess" -#: postmaster/postmaster.c:3178 +#: postmaster/postmaster.c:2553 msgid "checkpointer process" msgstr "checkpoint-process" -#: postmaster/postmaster.c:3194 +#: postmaster/postmaster.c:2569 msgid "WAL writer process" msgstr "WAL-skrivarprocess" -#: postmaster/postmaster.c:3209 +#: postmaster/postmaster.c:2584 msgid "WAL receiver process" msgstr "WAL-mottagarprocess" -#: postmaster/postmaster.c:3224 +#: postmaster/postmaster.c:2598 +msgid "WAL summarizer process" +msgstr "WAL-summeringsprocess" + +#: postmaster/postmaster.c:2613 msgid "autovacuum launcher process" msgstr "autovacuum-startprocess" -#: postmaster/postmaster.c:3242 +#: postmaster/postmaster.c:2631 msgid "archiver process" msgstr "arkiveringsprocess" -#: postmaster/postmaster.c:3255 +#: postmaster/postmaster.c:2644 msgid "system logger process" msgstr "system-logg-process" -#: postmaster/postmaster.c:3312 +#: postmaster/postmaster.c:2661 +msgid "slot sync worker process" +msgstr "arbetarprocess för slotsynkronisering" + +#: postmaster/postmaster.c:2717 #, c-format msgid "background worker \"%s\"" msgstr "bakgrundsarbetare \"%s\"" -#: postmaster/postmaster.c:3391 postmaster/postmaster.c:3411 -#: postmaster/postmaster.c:3418 postmaster/postmaster.c:3436 +#: postmaster/postmaster.c:2796 postmaster/postmaster.c:2816 +#: postmaster/postmaster.c:2823 postmaster/postmaster.c:2841 msgid "server process" msgstr "serverprocess" -#: postmaster/postmaster.c:3490 +#: postmaster/postmaster.c:2895 #, c-format msgid "terminating any other active server processes" msgstr "avslutar andra aktiva serverprocesser" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3665 +#: postmaster/postmaster.c:3082 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) avslutade med felkod %d" -#: postmaster/postmaster.c:3667 postmaster/postmaster.c:3679 -#: postmaster/postmaster.c:3689 postmaster/postmaster.c:3700 +#: postmaster/postmaster.c:3084 postmaster/postmaster.c:3096 +#: postmaster/postmaster.c:3106 postmaster/postmaster.c:3117 #, c-format msgid "Failed process was running: %s" msgstr "Misslyckad process körde: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3676 +#: postmaster/postmaster.c:3093 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) terminerades av avbrott 0x%X" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3686 +#: postmaster/postmaster.c:3103 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) terminerades av signal %d: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3698 +#: postmaster/postmaster.c:3115 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d) avslutade med okänd status %d" -#: postmaster/postmaster.c:3906 +#: postmaster/postmaster.c:3331 #, c-format msgid "abnormal database system shutdown" msgstr "ej normal databasnedstängning" -#: postmaster/postmaster.c:3932 +#: postmaster/postmaster.c:3357 #, c-format msgid "shutting down due to startup process failure" msgstr "stänger ner på grund av fel i startprocessen" -#: postmaster/postmaster.c:3938 +#: postmaster/postmaster.c:3363 #, c-format -msgid "shutting down because restart_after_crash is off" -msgstr "stänger ner då restart_after_crash är av" +msgid "shutting down because \"restart_after_crash\" is off" +msgstr "stänger ner då \"restart_after_crash\" är av" -#: postmaster/postmaster.c:3950 +#: postmaster/postmaster.c:3375 #, c-format msgid "all server processes terminated; reinitializing" msgstr "alla serverprocesser är avslutade; initierar på nytt" -#: postmaster/postmaster.c:4144 postmaster/postmaster.c:5462 -#: postmaster/postmaster.c:5860 +#: postmaster/postmaster.c:3574 postmaster/postmaster.c:3985 +#: postmaster/postmaster.c:4374 #, c-format msgid "could not generate random cancel key" msgstr "kunde inte skapa slumpad avbrytningsnyckel" -#: postmaster/postmaster.c:4206 +#: postmaster/postmaster.c:3607 #, c-format msgid "could not fork new process for connection: %m" msgstr "kunde inte fork():a ny process for uppkoppling: %m" -#: postmaster/postmaster.c:4248 +#: postmaster/postmaster.c:3649 msgid "could not fork new process for connection: " msgstr "kunde inte fork():a ny process for uppkoppling: " -#: postmaster/postmaster.c:4354 +#: postmaster/postmaster.c:3683 #, c-format -msgid "connection received: host=%s port=%s" -msgstr "ansluting mottagen: värd=%s port=%s" +msgid "postmaster became multithreaded" +msgstr "postmaster blev flertrådad" -#: postmaster/postmaster.c:4359 +#: postmaster/postmaster.c:3752 #, c-format -msgid "connection received: host=%s" -msgstr "ansluting mottagen: värd=%s" +msgid "database system is ready to accept read-only connections" +msgstr "databassystemet är redo att ta emot read-only-anslutningar" -#: postmaster/postmaster.c:4596 +#: postmaster/postmaster.c:3935 #, c-format -msgid "could not execute server process \"%s\": %m" -msgstr "kunde inte köra serverprocess \"%s\": %m" +msgid "could not fork \"%s\" process: %m" +msgstr "kunde inte fork:a \"%s\"-process: %m" -#: postmaster/postmaster.c:4654 -#, c-format -msgid "could not create backend parameter file mapping: error code %lu" -msgstr "kunde inte skapa fil-mapping för backend-parametrar: felkod %lu" - -#: postmaster/postmaster.c:4663 -#, c-format -msgid "could not map backend parameter memory: error code %lu" -msgstr "kunde inte mappa minne för backend-parametrar: felkod %lu" - -#: postmaster/postmaster.c:4690 -#, c-format -msgid "subprocess command line too long" -msgstr "subprocessens kommando är för långt" - -#: postmaster/postmaster.c:4708 -#, c-format -msgid "CreateProcess() call failed: %m (error code %lu)" -msgstr "Anrop till CreateProcess() misslyckades: %m (felkod %lu)" - -#: postmaster/postmaster.c:4735 -#, c-format -msgid "could not unmap view of backend parameter file: error code %lu" -msgstr "kunde inte avmappa vy för backend:ens parameterfil: felkod %lu" - -#: postmaster/postmaster.c:4739 -#, c-format -msgid "could not close handle to backend parameter file: error code %lu" -msgstr "kunde inte stänga \"handle\" till backend:ens parameterfil: felkod %lu" - -#: postmaster/postmaster.c:4761 -#, c-format -msgid "giving up after too many tries to reserve shared memory" -msgstr "ger upp efter för många försök att reservera delat minne" - -#: postmaster/postmaster.c:4762 -#, c-format -msgid "This might be caused by ASLR or antivirus software." -msgstr "Detta kan orsakas av ASLR eller antivirusprogram." - -#: postmaster/postmaster.c:4935 -#, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "SSL-konfigurering kunde inte laddas i barnprocess" - -#: postmaster/postmaster.c:5060 -#, c-format -msgid "Please report this to <%s>." -msgstr "Rapportera gärna detta till <%s>." - -#: postmaster/postmaster.c:5128 -#, c-format -msgid "database system is ready to accept read-only connections" -msgstr "databassystemet är redo att ta emot read-only-anslutningar" - -#: postmaster/postmaster.c:5386 -#, c-format -msgid "could not fork startup process: %m" -msgstr "kunde inte starta startup-processen: %m" - -#: postmaster/postmaster.c:5390 -#, c-format -msgid "could not fork archiver process: %m" -msgstr "kunde inte fork:a arkivprocess: %m" - -#: postmaster/postmaster.c:5394 -#, c-format -msgid "could not fork background writer process: %m" -msgstr "kunde inte starta process för bakgrundsskrivare: %m" - -#: postmaster/postmaster.c:5398 -#, c-format -msgid "could not fork checkpointer process: %m" -msgstr "kunde inte fork:a bakgrundsprocess: %m" - -#: postmaster/postmaster.c:5402 -#, c-format -msgid "could not fork WAL writer process: %m" -msgstr "kunde inte fork:a WAL-skrivprocess: %m" - -#: postmaster/postmaster.c:5406 -#, c-format -msgid "could not fork WAL receiver process: %m" -msgstr "kunde inte fork:a WAL-mottagarprocess: %m" - -#: postmaster/postmaster.c:5410 -#, c-format -msgid "could not fork process: %m" -msgstr "kunde inte fork:a process: %m" - -#: postmaster/postmaster.c:5611 postmaster/postmaster.c:5638 +#: postmaster/postmaster.c:4173 postmaster/postmaster.c:4207 #, c-format msgid "database connection requirement not indicated during registration" msgstr "krav på databasanslutning fanns inte med vid registering" -#: postmaster/postmaster.c:5622 postmaster/postmaster.c:5649 +#: postmaster/postmaster.c:4183 postmaster/postmaster.c:4217 #, c-format msgid "invalid processing mode in background worker" msgstr "ogiltigt processläge i bakgrundsarbetare" -#: postmaster/postmaster.c:5734 -#, c-format -msgid "could not fork worker process: %m" -msgstr "kunde inte starta (fork) arbetarprocess: %m" - -#: postmaster/postmaster.c:5846 -#, c-format -msgid "no slot available for new worker process" -msgstr "ingen slot tillgänglig för ny arbetsprocess" - -#: postmaster/postmaster.c:6177 -#, c-format -msgid "could not duplicate socket %d for use in backend: error code %d" -msgstr "kunde inte duplicera uttag (socket) %d för att använda i backend: felkod %d" - -#: postmaster/postmaster.c:6209 -#, c-format -msgid "could not create inherited socket: error code %d\n" -msgstr "kunde inte skapa ärvt uttag (socket): felkod %d\n" - -#: postmaster/postmaster.c:6238 -#, c-format -msgid "could not open backend variables file \"%s\": %s\n" -msgstr "kunde inte öppna bakändans variabelfil \"%s\": %s\n" - -#: postmaster/postmaster.c:6245 -#, c-format -msgid "could not read from backend variables file \"%s\": %s\n" -msgstr "kunde inte läsa från bakändans variabelfil \"%s\": %s\n" - -#: postmaster/postmaster.c:6254 -#, c-format -msgid "could not remove file \"%s\": %s\n" -msgstr "kunde inte ta bort fil \"%s\": %s\n" - -#: postmaster/postmaster.c:6271 -#, c-format -msgid "could not map view of backend variables: error code %lu\n" -msgstr "kunde inte mappa in vy för bakgrundsvariabler: felkod %lu\n" - -#: postmaster/postmaster.c:6280 +#: postmaster/postmaster.c:4277 #, c-format -msgid "could not unmap view of backend variables: error code %lu\n" -msgstr "kunde inte avmappa vy för bakgrundsvariabler: felkod %lu\n" +msgid "could not fork background worker process: %m" +msgstr "kunde inte fork:a process för bakgrundsarbete: %m" -#: postmaster/postmaster.c:6287 +#: postmaster/postmaster.c:4360 #, c-format -msgid "could not close handle to backend parameter variables: error code %lu\n" -msgstr "kunde inte stänga \"handle\" till backend:ens parametervariabler: felkod %lu\n" +msgid "no slot available for new background worker process" +msgstr "ingen slot tillgänglig till ny process för bakgrundsarbete" -#: postmaster/postmaster.c:6446 +#: postmaster/postmaster.c:4623 #, c-format msgid "could not read exit code for process\n" msgstr "kunde inte läsa avslutningskod för process\n" -#: postmaster/postmaster.c:6488 +#: postmaster/postmaster.c:4665 #, c-format msgid "could not post child completion status\n" msgstr "kunde inte skicka barnets avslutningsstatus\n" -#: postmaster/syslogger.c:501 postmaster/syslogger.c:1222 +#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 #, c-format msgid "could not read from logger pipe: %m" msgstr "kunde inte läsa från loggrör (pipe): %m" -#: postmaster/syslogger.c:598 postmaster/syslogger.c:612 +#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 #, c-format msgid "could not create pipe for syslog: %m" msgstr "kunde inte skapa rör (pipe) för syslog: %m" -#: postmaster/syslogger.c:677 +#: postmaster/syslogger.c:712 #, c-format msgid "could not fork system logger: %m" msgstr "kunde inte fork:a systemloggaren: %m" -#: postmaster/syslogger.c:713 +#: postmaster/syslogger.c:731 #, c-format msgid "redirecting log output to logging collector process" msgstr "omdirigerar loggutmatning till logginsamlingsprocess" -#: postmaster/syslogger.c:714 +#: postmaster/syslogger.c:732 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "Framtida loggutmatning kommer dyka upp i katalog \"%s\"." -#: postmaster/syslogger.c:722 +#: postmaster/syslogger.c:740 #, c-format msgid "could not redirect stdout: %m" msgstr "kunde inte omdirigera stdout: %m" -#: postmaster/syslogger.c:727 postmaster/syslogger.c:744 +#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 #, c-format msgid "could not redirect stderr: %m" msgstr "kunde inte omdirigera stderr: %m" -#: postmaster/syslogger.c:1177 +#: postmaster/syslogger.c:1128 #, c-format -msgid "could not write to log file: %s\n" -msgstr "kunde inte skriva till loggfil: %s\n" +msgid "could not write to log file: %m\n" +msgstr "kunde inte skriva till loggfil: %m\n" -#: postmaster/syslogger.c:1295 +#: postmaster/syslogger.c:1246 #, c-format msgid "could not open log file \"%s\": %m" msgstr "kunde inte öppna loggfil \"%s\": %m" -#: postmaster/syslogger.c:1385 +#: postmaster/syslogger.c:1336 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "stänger av automatisk rotation (använd SIGHUP för att slå på igen)" -#: regex/regc_pg_locale.c:242 +#: postmaster/walsummarizer.c:740 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "WAL-summering avancerar inte" + +#: postmaster/walsummarizer.c:741 +#, c-format +msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." +msgstr "Summering krävs till %X/%X men har fastnat vid %X/%X på disk och vid %X/%X i minnet." + +#: postmaster/walsummarizer.c:755 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "väntar fortfarande på WAL-summering till %X/%X efter %ld sekund" +msgstr[1] "väntar fortfarande på WAL-summering till %X/%X efter %ld sekunder" + +#: postmaster/walsummarizer.c:760 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "Summering har nått %X/%X på disk och %X/%X i minnet." + +#: postmaster/walsummarizer.c:1000 +#, c-format +msgid "could not find a valid record after %X/%X" +msgstr "kunde inte hitta en giltig post efter %X/%X" + +#: postmaster/walsummarizer.c:1045 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X: %s" +msgstr "kunde inte läsa WAL från tidslinje %u vid %X/%X: %s" + +#: postmaster/walsummarizer.c:1051 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X" +msgstr "kunde inte läsa WAL från tidslinje %u vid %X/%X" + +#: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "kunde inte bestämma vilken jämförelse (collation) som skall användas för reguljära uttryck" -#: regex/regc_pg_locale.c:265 +#: regex/regc_pg_locale.c:262 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "ickedeterministiska jämförelser (collation) stöds inte för reguljära uttryck" -#: repl_gram.y:301 repl_gram.y:333 +#: repl_gram.y:318 repl_gram.y:359 #, c-format msgid "invalid timeline %u" msgstr "ogiltig tidslinje %u" -#: repl_scanner.l:152 +#: repl_scanner.l:154 msgid "invalid streaming start location" msgstr "ogiltig startposition för strömning" -#: replication/libpqwalreceiver/libpqwalreceiver.c:197 -#: replication/libpqwalreceiver/libpqwalreceiver.c:280 +#: replication/libpqwalreceiver/libpqwalreceiver.c:267 +#: replication/libpqwalreceiver/libpqwalreceiver.c:358 #, c-format msgid "password is required" msgstr "lösenord krävs" -#: replication/libpqwalreceiver/libpqwalreceiver.c:198 +#: replication/libpqwalreceiver/libpqwalreceiver.c:268 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "Icke superanvändare kan inte ansluta till servern om den inte kräver lösenord." -#: replication/libpqwalreceiver/libpqwalreceiver.c:199 +#: replication/libpqwalreceiver/libpqwalreceiver.c:269 #, c-format msgid "Target server's authentication method must be changed, or set password_required=false in the subscription parameters." msgstr "Målserverns autentiseringsmetod måste ändras eller så måste man sätta password_required=false i prenumerationens parametrar." -#: replication/libpqwalreceiver/libpqwalreceiver.c:211 +#: replication/libpqwalreceiver/libpqwalreceiver.c:285 #, c-format msgid "could not clear search path: %s" msgstr "kunde inte nollställa sökväg: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:257 +#: replication/libpqwalreceiver/libpqwalreceiver.c:331 +#: replication/libpqwalreceiver/libpqwalreceiver.c:517 #, c-format msgid "invalid connection string syntax: %s" msgstr "ogiltig anslutningssträngsyntax %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:281 +#: replication/libpqwalreceiver/libpqwalreceiver.c:359 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "Icke superanvändare måste ange ett lösenord i anslutningssträngen." -#: replication/libpqwalreceiver/libpqwalreceiver.c:307 +#: replication/libpqwalreceiver/libpqwalreceiver.c:386 #, c-format msgid "could not parse connection string: %s" msgstr "kunde inte parsa anslutningssträng: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:380 +#: replication/libpqwalreceiver/libpqwalreceiver.c:459 #, c-format msgid "could not receive database system identifier and timeline ID from the primary server: %s" msgstr "kunde inte hämta databassystemidentifierare och tidslinje-ID från primära servern: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:392 -#: replication/libpqwalreceiver/libpqwalreceiver.c:635 +#: replication/libpqwalreceiver/libpqwalreceiver.c:476 +#: replication/libpqwalreceiver/libpqwalreceiver.c:763 #, c-format msgid "invalid response from primary server" msgstr "ogiltigt svar från primär server" -#: replication/libpqwalreceiver/libpqwalreceiver.c:393 +#: replication/libpqwalreceiver/libpqwalreceiver.c:477 #, c-format msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields." msgstr "Kunde inte identifiera system: fick %d rader och %d fält, förväntade %d rader och %d eller fler fält." -#: replication/libpqwalreceiver/libpqwalreceiver.c:478 -#: replication/libpqwalreceiver/libpqwalreceiver.c:485 -#: replication/libpqwalreceiver/libpqwalreceiver.c:515 +#: replication/libpqwalreceiver/libpqwalreceiver.c:606 +#: replication/libpqwalreceiver/libpqwalreceiver.c:613 +#: replication/libpqwalreceiver/libpqwalreceiver.c:643 #, c-format msgid "could not start WAL streaming: %s" msgstr "kunde inte starta WAL-strömning: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:539 +#: replication/libpqwalreceiver/libpqwalreceiver.c:667 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "kunde inte skicka meddelandet end-of-streaming till primären: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:562 +#: replication/libpqwalreceiver/libpqwalreceiver.c:690 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "oväntad resultatmängd efter end-of-streaming" -#: replication/libpqwalreceiver/libpqwalreceiver.c:577 +#: replication/libpqwalreceiver/libpqwalreceiver.c:705 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "fel vid nestängning av strömmande COPY: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:587 +#: replication/libpqwalreceiver/libpqwalreceiver.c:715 #, c-format msgid "error reading result of streaming command: %s" msgstr "fel vid läsning av resultat från strömningskommando: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:596 -#: replication/libpqwalreceiver/libpqwalreceiver.c:832 +#: replication/libpqwalreceiver/libpqwalreceiver.c:724 +#: replication/libpqwalreceiver/libpqwalreceiver.c:957 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "oväntat resultat efter CommandComplete: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:623 +#: replication/libpqwalreceiver/libpqwalreceiver.c:751 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "kan inte ta emot fil med tidslinjehistorik från primära servern: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:636 +#: replication/libpqwalreceiver/libpqwalreceiver.c:764 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "Förväntade 1 tupel med 2 fält, fick %d tupler med %d fält." -#: replication/libpqwalreceiver/libpqwalreceiver.c:795 -#: replication/libpqwalreceiver/libpqwalreceiver.c:848 -#: replication/libpqwalreceiver/libpqwalreceiver.c:855 +#: replication/libpqwalreceiver/libpqwalreceiver.c:920 +#: replication/libpqwalreceiver/libpqwalreceiver.c:973 +#: replication/libpqwalreceiver/libpqwalreceiver.c:980 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "kunde inte ta emot data från WAL-ström: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:875 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 #, c-format msgid "could not send data to WAL stream: %s" msgstr "kunde inte skicka data till WAL-ström: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:967 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "kunde inte skapa replikeringsslot \"%s\": %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1013 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#, c-format +msgid "could not alter replication slot \"%s\": %s" +msgstr "kunde inte ändra replikeringsslot \"%s\": %s" + +#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 #, c-format msgid "invalid query response" msgstr "ogiltigt frågerespons" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1014 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 #, c-format msgid "Expected %d fields, got %d fields." msgstr "Förväntade %d fält, fick %d fält." -#: replication/libpqwalreceiver/libpqwalreceiver.c:1084 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 #, c-format msgid "the query interface requires a database connection" msgstr "frågeinterface:et kräver en databasanslutning" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1115 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 msgid "empty query" msgstr "tom fråga" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1121 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 msgid "unexpected pipeline mode" msgstr "oväntat pipeline-läge" @@ -20212,189 +20678,205 @@ msgstr "oväntat pipeline-läge" msgid "logical replication parallel apply worker for subscription \"%s\" has finished" msgstr "logisk replikerings parallella ändringsapplicerare för prenumeration \"%s\" har avslutat" -#: replication/logical/applyparallelworker.c:825 +#: replication/logical/applyparallelworker.c:822 #, c-format msgid "lost connection to the logical replication apply worker" msgstr "tappade anslutning till den logiska replikeringens ändringsapplicerare" -#: replication/logical/applyparallelworker.c:1027 -#: replication/logical/applyparallelworker.c:1029 +#: replication/logical/applyparallelworker.c:1024 +#: replication/logical/applyparallelworker.c:1026 msgid "logical replication parallel apply worker" msgstr "logisk replikerings ändringsapplicerare" -#: replication/logical/applyparallelworker.c:1043 +#: replication/logical/applyparallelworker.c:1040 #, c-format msgid "logical replication parallel apply worker exited due to error" msgstr "logiska replikeringens ändringsappliceraren avslutade på grund av ett fel" -#: replication/logical/applyparallelworker.c:1130 -#: replication/logical/applyparallelworker.c:1303 +#: replication/logical/applyparallelworker.c:1127 +#: replication/logical/applyparallelworker.c:1300 #, c-format msgid "lost connection to the logical replication parallel apply worker" msgstr "tappade anslutning till den logiska replikeringens parallella ändringsapplicerare" -#: replication/logical/applyparallelworker.c:1183 +#: replication/logical/applyparallelworker.c:1180 #, c-format msgid "could not send data to shared-memory queue" msgstr "kunde inte skicka data till kö i delat minne" -#: replication/logical/applyparallelworker.c:1218 +#: replication/logical/applyparallelworker.c:1215 #, c-format msgid "logical replication apply worker will serialize the remaining changes of remote transaction %u to a file" msgstr "logiska replikeringens ändringsapplicerare kommer spara ner återstående ändringarna av fjärrtransaktion %u til en fil" -#: replication/logical/decode.c:180 replication/logical/logical.c:140 +#: replication/logical/decode.c:177 replication/logical/logical.c:141 #, c-format -msgid "logical decoding on standby requires wal_level >= logical on the primary" -msgstr "logisk avkodning på standby kräver wal_level >= logical på primären" +msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" +msgstr "logisk avkodning på standby kräver \"wal_level\" >= \"logical\" på primären" -#: replication/logical/launcher.c:331 +#: replication/logical/launcher.c:334 #, c-format msgid "cannot start logical replication workers when max_replication_slots = 0" msgstr "kan inte starta logisk replikeringsarbetare när max_replication_slots = 0" -#: replication/logical/launcher.c:424 +#: replication/logical/launcher.c:427 #, c-format msgid "out of logical replication worker slots" msgstr "slut på logiska replikeringsarbetarslots" -#: replication/logical/launcher.c:425 replication/logical/launcher.c:499 -#: replication/slot.c:1297 storage/lmgr/lock.c:964 storage/lmgr/lock.c:1002 -#: storage/lmgr/lock.c:2787 storage/lmgr/lock.c:4172 storage/lmgr/lock.c:4237 -#: storage/lmgr/lock.c:4587 storage/lmgr/predicate.c:2413 -#: storage/lmgr/predicate.c:2428 storage/lmgr/predicate.c:3825 +#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 +#: replication/slot.c:1524 storage/lmgr/lock.c:985 storage/lmgr/lock.c:1023 +#: storage/lmgr/lock.c:2836 storage/lmgr/lock.c:4221 storage/lmgr/lock.c:4286 +#: storage/lmgr/lock.c:4636 storage/lmgr/predicate.c:2469 +#: storage/lmgr/predicate.c:2484 storage/lmgr/predicate.c:3881 #, c-format -msgid "You might need to increase %s." -msgstr "Du kan behöva öka %s." +msgid "You might need to increase \"%s\"." +msgstr "Du kan behöva öka \"%s\"." -#: replication/logical/launcher.c:498 +#: replication/logical/launcher.c:513 #, c-format msgid "out of background worker slots" msgstr "slut på bakgrundsarbetarslots" -#: replication/logical/launcher.c:705 +#: replication/logical/launcher.c:720 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "logisk replikeringsarbetarslot %d är tom, kan inte ansluta" -#: replication/logical/launcher.c:714 +#: replication/logical/launcher.c:729 #, c-format msgid "logical replication worker slot %d is already used by another worker, cannot attach" msgstr "logiisk replikeringsarbetarslot %d används redan av en annan arbetare, kan inte ansluta" -#: replication/logical/logical.c:120 +#: replication/logical/logical.c:121 #, c-format -msgid "logical decoding requires wal_level >= logical" -msgstr "logisk avkodning kräver wal_level >= logical" +msgid "logical decoding requires \"wal_level\" >= \"logical\"" +msgstr "logisk avkodning kräver \"wal_level\" >= \"logical\"" -#: replication/logical/logical.c:125 +#: replication/logical/logical.c:126 #, c-format msgid "logical decoding requires a database connection" msgstr "logisk avkodning kräver en databasanslutning" -#: replication/logical/logical.c:363 replication/logical/logical.c:517 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "kan inte använda fysisk replikeringsslot för logisk avkodning" -#: replication/logical/logical.c:368 replication/logical/logical.c:522 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "replikeringsslot \"%s\" har inte skapats i denna databasen" -#: replication/logical/logical.c:375 +#: replication/logical/logical.c:377 #, c-format msgid "cannot create logical replication slot in transaction that has performed writes" msgstr "kan inte skapa logisk replikeringsslot i transaktion som redan har utfört skrivningar" -#: replication/logical/logical.c:534 replication/logical/logical.c:541 +#: replication/logical/logical.c:540 +#, c-format +msgid "cannot use replication slot \"%s\" for logical decoding" +msgstr "kan inte använda replikeringsslot \"%s\" för logisk avkodning" + +#: replication/logical/logical.c:542 replication/slot.c:798 +#: replication/slot.c:829 +#, c-format +msgid "This replication slot is being synchronized from the primary server." +msgstr "Denna replikeringsslot synkroniseras från primära servern." + +#: replication/logical/logical.c:543 +#, c-format +msgid "Specify another replication slot." +msgstr "Ange en annan replikeringsslot." + +#: replication/logical/logical.c:554 replication/logical/logical.c:561 #, c-format msgid "can no longer get changes from replication slot \"%s\"" msgstr "kan inte längre få ändringar från replikeringsslot \"%s\"" -#: replication/logical/logical.c:536 +#: replication/logical/logical.c:556 #, c-format msgid "This slot has been invalidated because it exceeded the maximum reserved size." msgstr "Denna slot har invaliderats då den överskred maximal reserverad storlek." -#: replication/logical/logical.c:543 +#: replication/logical/logical.c:563 #, c-format msgid "This slot has been invalidated because it was conflicting with recovery." msgstr "Denna slot har invaliderats den var i konflikt med återställningen." -#: replication/logical/logical.c:608 +#: replication/logical/logical.c:628 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "startar logisk avkodning för slot \"%s\"" -#: replication/logical/logical.c:610 +#: replication/logical/logical.c:630 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "Strömmar transaktioner commit:ade efter %X/%X, läser WAL från %X/%X" -#: replication/logical/logical.c:758 +#: replication/logical/logical.c:778 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "slot \"%s\", utdata-plugin \"%s\", i callback:en %s, associerad LSN %X/%X" -#: replication/logical/logical.c:764 +#: replication/logical/logical.c:784 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "slot \"%s\", utdata-plugin \"%s\", i callback:en %s" -#: replication/logical/logical.c:935 replication/logical/logical.c:980 -#: replication/logical/logical.c:1025 replication/logical/logical.c:1071 +#: replication/logical/logical.c:955 replication/logical/logical.c:1000 +#: replication/logical/logical.c:1045 replication/logical/logical.c:1091 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "logisk replikering vid prepare-tillfället kräver en %s-callback" -#: replication/logical/logical.c:1303 replication/logical/logical.c:1352 -#: replication/logical/logical.c:1393 replication/logical/logical.c:1479 -#: replication/logical/logical.c:1528 +#: replication/logical/logical.c:1323 replication/logical/logical.c:1372 +#: replication/logical/logical.c:1413 replication/logical/logical.c:1499 +#: replication/logical/logical.c:1548 #, c-format msgid "logical streaming requires a %s callback" msgstr "logisk strömning kräven en %s-callback" -#: replication/logical/logical.c:1438 +#: replication/logical/logical.c:1458 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "logisk strömning vid prepare-tillfället kräver en %s-callback" -#: replication/logical/logicalfuncs.c:126 +#: replication/logical/logicalfuncs.c:123 #, c-format msgid "slot name must not be null" msgstr "slot-namn får inte vara null" -#: replication/logical/logicalfuncs.c:142 +#: replication/logical/logicalfuncs.c:139 #, c-format msgid "options array must not be null" msgstr "flagg-array får inte vara null" -#: replication/logical/logicalfuncs.c:159 +#: replication/logical/logicalfuncs.c:156 #, c-format msgid "array must be one-dimensional" msgstr "array:en måste vara endimensionell" -#: replication/logical/logicalfuncs.c:165 +#: replication/logical/logicalfuncs.c:162 #, c-format msgid "array must not contain nulls" msgstr "array:en får inte innehålla null" -#: replication/logical/logicalfuncs.c:180 utils/adt/json.c:1484 -#: utils/adt/jsonb.c:1403 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1420 +#: utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "array:en måste ha ett jämnt antal element" -#: replication/logical/logicalfuncs.c:227 +#: replication/logical/logicalfuncs.c:224 #, c-format msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data" msgstr "utdata-plugin \"%s\" för logisk avkodning producerar binär utdata men funktionen \"%s\" förväntar sig textdata" #: replication/logical/origin.c:190 #, c-format -msgid "cannot query or manipulate replication origin when max_replication_slots = 0" -msgstr "kan inte se eller ändra replikeringskällor när max_replication_slots = 0" +msgid "cannot query or manipulate replication origin when \"max_replication_slots\" is 0" +msgstr "kan inte se eller ändra replikeringskällor när \"max_replication_slots\" är 0" #: replication/logical/origin.c:195 #, c-format @@ -20428,8 +20910,8 @@ msgstr "replikeringscheckpoint har fel magiskt tal %u istället för %u" #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase max_replication_slots" -msgstr "kunde inte hitta ledig replikeringsplats, öka max_replication_slots" +msgid "could not find free replication state, increase \"max_replication_slots\"" +msgstr "kunde inte hitta ledig replikeringsplats, öka \"max_replication_slots\"" #: replication/logical/origin.c:806 #, c-format @@ -20441,1233 +20923,1549 @@ msgstr "återställde replikeringstillstånd för nod %d till %X/%X" msgid "replication slot checkpoint has wrong checksum %u, expected %u" msgstr "replikeringsslot-checkpoint har felaktig kontrollsumma %u, förväntade %u" -#: replication/logical/origin.c:944 replication/logical/origin.c:1141 +#: replication/logical/origin.c:944 replication/logical/origin.c:1143 #, c-format msgid "replication origin with ID %d is already active for PID %d" msgstr "replikeringskälla med ID %d är redan aktiv för PID %d" -#: replication/logical/origin.c:955 replication/logical/origin.c:1153 +#: replication/logical/origin.c:955 replication/logical/origin.c:1156 #, c-format msgid "could not find free replication state slot for replication origin with ID %d" msgstr "kunde inte hitta ledig replikerings-state-slot för replikerings-origin med ID %d" -#: replication/logical/origin.c:957 replication/logical/origin.c:1155 -#: replication/slot.c:2093 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 +#: replication/slot.c:2384 #, c-format -msgid "Increase max_replication_slots and try again." -msgstr "Öka max_replication_slots och försök igen." +msgid "Increase \"max_replication_slots\" and try again." +msgstr "Öka \"max_replication_slots\" och försök igen." -#: replication/logical/origin.c:1112 +#: replication/logical/origin.c:1114 #, c-format msgid "cannot setup replication origin when one is already setup" msgstr "kan inte ställa in replikeringskälla när en redan är inställd" -#: replication/logical/origin.c:1196 replication/logical/origin.c:1412 -#: replication/logical/origin.c:1432 +#: replication/logical/origin.c:1199 replication/logical/origin.c:1415 +#: replication/logical/origin.c:1435 #, c-format msgid "no replication origin is configured" msgstr "ingen replikeringskälla är konfigurerad" -#: replication/logical/origin.c:1282 +#: replication/logical/origin.c:1285 #, c-format msgid "replication origin name \"%s\" is reserved" msgstr "replikeringskällnamn \"%s\" är reserverat" -#: replication/logical/origin.c:1284 +#: replication/logical/origin.c:1287 #, c-format msgid "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." msgstr "Källnamn \"%s\", \"%s\" och namn som startar med \"pg_\" är reserverade." -#: replication/logical/relation.c:240 +#: replication/logical/relation.c:242 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:243 +#: replication/logical/relation.c:245 #, c-format msgid ", \"%s\"" msgstr ", \"%s\"" -#: replication/logical/relation.c:249 +#: replication/logical/relation.c:251 #, c-format msgid "logical replication target relation \"%s.%s\" is missing replicated column: %s" msgid_plural "logical replication target relation \"%s.%s\" is missing replicated columns: %s" msgstr[0] "destinationsrelation \"%s.%s\" för logisk replikering saknar en replikerad kolumn: %s" msgstr[1] "destinationsrelation \"%s.%s\" för logisk replikering saknar några replikerade kolumner: %s" -#: replication/logical/relation.c:304 +#: replication/logical/relation.c:306 #, c-format msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index" msgstr "destinationsrelation \"%s.%s\" för logisk replikering använder systemkolumner i REPLICA IDENTITY-index" -#: replication/logical/relation.c:396 +#: replication/logical/relation.c:398 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "destinationsrelation \"%s.%s\" för logisk replikering finns inte" -#: replication/logical/reorderbuffer.c:3936 +#: replication/logical/reorderbuffer.c:3999 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "kunde inte skriva till datafil för XID %u: %m" -#: replication/logical/reorderbuffer.c:4282 -#: replication/logical/reorderbuffer.c:4307 +#: replication/logical/reorderbuffer.c:4345 +#: replication/logical/reorderbuffer.c:4370 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "kunde inte läsa från reorderbuffer spill-fil: %m" -#: replication/logical/reorderbuffer.c:4286 -#: replication/logical/reorderbuffer.c:4311 +#: replication/logical/reorderbuffer.c:4349 +#: replication/logical/reorderbuffer.c:4374 #, c-format msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "kunde inte läsa från reorderbuffer spill-fil: läste %d istället för %u byte" -#: replication/logical/reorderbuffer.c:4561 +#: replication/logical/reorderbuffer.c:4624 #, c-format msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" msgstr "kunde inte radera fil \"%s\" vid borttagning av pg_replslot/%s/xid*: %m" -#: replication/logical/reorderbuffer.c:5057 +#: replication/logical/reorderbuffer.c:5120 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "kunde inte läsa från fil \"%s\": läste %d istället för %d byte" -#: replication/logical/snapbuild.c:639 +#: replication/logical/slotsync.c:215 +#, c-format +msgid "could not synchronize replication slot \"%s\" because remote slot precedes local slot" +msgstr "kunde inte synkronisera replikeringsslot \"%s\" då fjärrslotten ligger tidigare än den lokala slotten" + +#: replication/logical/slotsync.c:217 +#, c-format +msgid "The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u." +msgstr "Fjärrslotten har LSN %X/%X och katalog-xmin %u men lokala slotten har LSN %X/%X och katalog-xmin %u." + +#: replication/logical/slotsync.c:459 +#, c-format +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "slängde replikerings-slot \"%s\" för databas med OID %u" + +#: replication/logical/slotsync.c:579 +#, c-format +msgid "could not synchronize replication slot \"%s\"" +msgstr "kunde inte synkronisera replikeringsslot \"%s\"" + +#: replication/logical/slotsync.c:580 +#, c-format +msgid "Logical decoding could not find consistent point from local slot's LSN %X/%X." +msgstr "Logisk avkodning kunde inte hitta en konsistent punkt från lokala slottens LSN %X/%X" + +#: replication/logical/slotsync.c:589 +#, c-format +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "nyskapad replikeringsslot \"%s\" är redo för synk nu" + +#: replication/logical/slotsync.c:628 +#, c-format +msgid "skipping slot synchronization because the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" +msgstr "hoppar över slotsynkronisering då den mottagna slottens synk-LSN %X/%X för slot \"%s\" är längre fram än standby-positionen %X/%X" + +#: replication/logical/slotsync.c:650 +#, c-format +msgid "exiting from slot synchronization because same name slot \"%s\" already exists on the standby" +msgstr "avslutar slotsynkronisering då samma slotnamn \"%s\" redan finns på standby:en" + +#: replication/logical/slotsync.c:819 +#, c-format +msgid "could not fetch failover logical slots info from the primary server: %s" +msgstr "kan inte hämta logisk slot för failover från primära servern: %s" + +#: replication/logical/slotsync.c:965 +#, c-format +msgid "could not fetch primary_slot_name \"%s\" info from the primary server: %s" +msgstr "kan inte hämta info för primary_slot_name \"%s\" från primära servern: %s" + +#: replication/logical/slotsync.c:967 +#, c-format +msgid "Check if primary_slot_name is configured correctly." +msgstr "Kontrollera att primary_slot_name är korrekt konfigurerad." + +#: replication/logical/slotsync.c:987 +#, c-format +msgid "cannot synchronize replication slots from a standby server" +msgstr "kan inte synkronisera replikeringsslottar från en standby-server" + +#. translator: second %s is a GUC variable name +#: replication/logical/slotsync.c:996 +#, c-format +msgid "replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "replikeringsslot \"%s\" angiven av %s finns inte på den primära servern." + +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1029 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "synkronisering av replikeringsslot kräver att \"%s\" anges i %s" + +#: replication/logical/slotsync.c:1050 +#, c-format +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "synkronisering av replikeringsslot kräver at \"wal_level\" >= \"logical\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "synkronisering av replikeringsslot kräver att \"%s\" också anges" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1077 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "synkronisering av replikeringsslot kräver att \"%s\" också slås på" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1129 +#, c-format +msgid "replication slot synchronization worker will shut down because \"%s\" is disabled" +msgstr "arbetare för synkronisering av replikeringsslot kommer stängas ner då \"%s\" är avslagen" + +#: replication/logical/slotsync.c:1138 +#, c-format +msgid "replication slot synchronization worker will restart because of a parameter change" +msgstr "arbetare för synkronisering av replikeringsslot kommer startas om då parametrar ändrats" + +#: replication/logical/slotsync.c:1162 +#, c-format +msgid "replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "arbetare för synkronisering av replikeringsslot stänger ner efter mottagning av SIGINT" + +#: replication/logical/slotsync.c:1287 +#, c-format +msgid "cannot synchronize replication slots when standby promotion is ongoing" +msgstr "kan inte synkronisera replikeringsslot när befordran av standby pågår" + +#: replication/logical/slotsync.c:1295 +#, c-format +msgid "cannot synchronize replication slots concurrently" +msgstr "kan inte synkronisera replikeringsslottar parallellt" + +#: replication/logical/slotsync.c:1403 +#, c-format +msgid "slot sync worker started" +msgstr "arbetare för slot-synk startad" + +#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 +#: replication/walreceiver.c:307 +#, c-format +msgid "could not connect to the primary server: %s" +msgstr "kunde inte ansluta till primärserver: %s" + +#: replication/logical/snapbuild.c:653 #, c-format msgid "initial slot snapshot too large" msgstr "initialt slot-snapshot är för stort" -#: replication/logical/snapbuild.c:693 +#: replication/logical/snapbuild.c:707 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs" msgstr[0] "exporterade logisk avkodnings-snapshot: \"%s\" med %u transaktions-ID" msgstr[1] "exporterade logisk avkodnings-snapshot: \"%s\" med %u transaktions-ID" -#: replication/logical/snapbuild.c:1388 replication/logical/snapbuild.c:1480 -#: replication/logical/snapbuild.c:1996 +#: replication/logical/snapbuild.c:1404 replication/logical/snapbuild.c:1501 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "logisk avkodning hittade konsistent punkt vid %X/%X" -#: replication/logical/snapbuild.c:1390 +#: replication/logical/snapbuild.c:1406 #, c-format msgid "There are no running transactions." msgstr "Det finns inga körande transaktioner." -#: replication/logical/snapbuild.c:1432 +#: replication/logical/snapbuild.c:1453 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "logisk avkodning hittade initial startpunkt vid %X/%X" -#: replication/logical/snapbuild.c:1434 replication/logical/snapbuild.c:1458 +#: replication/logical/snapbuild.c:1455 replication/logical/snapbuild.c:1479 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "Väntar på att transaktioner (cirka %d) äldre än %u skall gå klart." -#: replication/logical/snapbuild.c:1456 +#: replication/logical/snapbuild.c:1477 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "logisk avkodning hittade initial konsistent punkt vid %X/%X" -#: replication/logical/snapbuild.c:1482 +#: replication/logical/snapbuild.c:1503 #, c-format msgid "There are no old transactions anymore." msgstr "Det finns inte längre några gamla transaktioner." -#: replication/logical/snapbuild.c:1883 +#: replication/logical/snapbuild.c:1904 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "snapbuild-state-fil \"%s\" har fel magiskt tal: %u istället för %u" -#: replication/logical/snapbuild.c:1889 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "snapbuild-state-fil \"%s\" har en ej stödd version: %u istället för %u" -#: replication/logical/snapbuild.c:1930 +#: replication/logical/snapbuild.c:1951 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "checksumma stämmer inte för snapbuild-state-fil \"%s\": är %u, skall vara %u" -#: replication/logical/snapbuild.c:1998 +#: replication/logical/snapbuild.c:2019 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "Logisk avkodning kommer starta med sparat snapshot." -#: replication/logical/snapbuild.c:2105 +#: replication/logical/snapbuild.c:2126 #, c-format msgid "could not parse file name \"%s\"" msgstr "kunde inte parsa filnamn \"%s\"" -#: replication/logical/tablesync.c:153 +#: replication/logical/tablesync.c:161 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" msgstr "logisk replikerings tabellsynkroniseringsarbetare för prenumeration \"%s\", tabell \"%s\" är klar" -#: replication/logical/tablesync.c:622 +#: replication/logical/tablesync.c:641 #, c-format msgid "logical replication apply worker for subscription \"%s\" will restart so that two_phase can be enabled" msgstr "arbetarprocess för uppspelning av logisk replikering av prenumeration \"%s\" kommer starta om så att two_phase kan slås på" -#: replication/logical/tablesync.c:797 replication/logical/tablesync.c:939 +#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "kunde inte hämta tabellinfo för tabell \"%s.%s\" från publicerare: %s" -#: replication/logical/tablesync.c:804 +#: replication/logical/tablesync.c:834 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr "tabell \"%s.%s\" hittades inte hos publicerare" -#: replication/logical/tablesync.c:862 +#: replication/logical/tablesync.c:892 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "kunde inte hämta kolumlista för tabell \"%s.%s\" från publicerare: %s" -#: replication/logical/tablesync.c:1041 +#: replication/logical/tablesync.c:1071 #, c-format msgid "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: %s" msgstr "kunde inte hämta tabells WHERE-klausul för tabell \"%s.%s\" från publicerare: %s" -#: replication/logical/tablesync.c:1192 +#: replication/logical/tablesync.c:1230 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "kunde inte starta initial innehållskopiering för tabell \"%s.%s\": %s" -#: replication/logical/tablesync.c:1393 +#: replication/logical/tablesync.c:1429 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "tabellkopiering kunde inte starta transaktion på publiceraren: %s" -#: replication/logical/tablesync.c:1435 +#: replication/logical/tablesync.c:1472 #, c-format msgid "replication origin \"%s\" already exists" msgstr "replikeringsurspring \"%s\" finns redan" -#: replication/logical/tablesync.c:1468 replication/logical/worker.c:2374 +#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 #, c-format msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" msgstr "användaren \"%s\" kan inte replikera in i en relation med radsäkerhet påslagen: \"%s\"" -#: replication/logical/tablesync.c:1481 +#: replication/logical/tablesync.c:1518 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "tabellkopiering kunde inte slutföra transaktion på publiceraren: %s" -#: replication/logical/worker.c:499 +#: replication/logical/worker.c:481 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop" msgstr "logiska replikeringens parallella ändringsapplicerare för prenumeration \"%s\" kommer stoppa" -#: replication/logical/worker.c:501 +#: replication/logical/worker.c:483 #, c-format msgid "Cannot handle streamed replication transactions using parallel apply workers until all tables have been synchronized." msgstr "Kan inte hantera strömmade replikerade transaktioner med parallell ändringsapplicerare innan alla tabeller har synkroniserats." -#: replication/logical/worker.c:863 replication/logical/worker.c:978 +#: replication/logical/worker.c:852 replication/logical/worker.c:967 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "inkorrekt binärt dataformat i logisk replikeringskolumn %d" -#: replication/logical/worker.c:2513 +#: replication/logical/worker.c:2500 #, c-format msgid "publisher did not send replica identity column expected by the logical replication target relation \"%s.%s\"" msgstr "publicerare skickade inte identitetskolumn för replika som förväntades av den logiska replikeringens målrelation \"%s.%s\"" -#: replication/logical/worker.c:2520 +#: replication/logical/worker.c:2507 #, c-format msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL" msgstr "logisk replikeringsmålrelation \"%s.%s\" har varken REPLICA IDENTITY-index eller PRIMARY KEY och den publicerade relationen har inte REPLICA IDENTITY FULL" -#: replication/logical/worker.c:3384 +#: replication/logical/worker.c:3371 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "ogiltig logisk replikeringsmeddelandetyp \"??? (%d)\"" -#: replication/logical/worker.c:3556 +#: replication/logical/worker.c:3543 #, c-format msgid "data stream from publisher has ended" msgstr "dataströmmen från publiceraren har avslutats" -#: replication/logical/worker.c:3713 +#: replication/logical/worker.c:3697 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "avslutar logisk replikeringsarbetare på grund av timeout" -#: replication/logical/worker.c:3907 +#: replication/logical/worker.c:3891 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed" msgstr "logiska replikerings ändringsapplicerare för prenumeration \"%s\" kommer att stoppa då prenumerationen har tagits bort" -#: replication/logical/worker.c:3920 +#: replication/logical/worker.c:3905 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled" msgstr "logiska replikerings ändringsapplicerare för prenumeration \"%s\" kommer att stoppa då prenumerationen har stängts av" -#: replication/logical/worker.c:3951 +#: replication/logical/worker.c:3936 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because of a parameter change" msgstr "logiska replikeringens ändringsapplicerare för prenumeration \"%s\" kommer att stoppa på grund av ändrade parametrar" -#: replication/logical/worker.c:3955 +#: replication/logical/worker.c:3940 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because of a parameter change" msgstr "logiska replikeringens ändringsapplicerare för prenumeration \"%s\" kommer att startas om på grund av ändrade parametrar" +#: replication/logical/worker.c:3954 +#, c-format +msgid "logical replication parallel apply worker for subscription \"%s\" will stop because the subscription owner's superuser privileges have been revoked" +msgstr "logiska replikerings parallella ändringsapplicerare för prenumeration \"%s\" kommer att stoppa då prenumerationens ägare har blivit av med superuser-rättigheten" + +#: replication/logical/worker.c:3958 +#, c-format +msgid "logical replication worker for subscription \"%s\" will restart because the subscription owner's superuser privileges have been revoked" +msgstr "logiska replikerings ändringsapplicerare för prenumeration \"%s\" kommer att startas om då prenumerationens ägare har blivit av med superuser-rättigheten" + #: replication/logical/worker.c:4478 #, c-format +msgid "subscription has no replication slot set" +msgstr "prenumeration har ingen replikeringsslot angiven" + +#: replication/logical/worker.c:4591 +#, c-format msgid "logical replication worker for subscription %u will not start because the subscription was removed during startup" msgstr "logiska replikeringens ändringsapplicerare för prenumeration %u kommer inte att startas då prenumerationen togs bort i uppstarten" -#: replication/logical/worker.c:4493 +#: replication/logical/worker.c:4607 #, c-format msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup" msgstr "logiska replikeringens ändringsapplicerare för prenumeration \"%s\" kommer inte att startas då prenumerationen stängdes av i uppstarten" -#: replication/logical/worker.c:4510 +#: replication/logical/worker.c:4631 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" msgstr "logisk replikerings tabellsynkroniseringsarbetare för prenumeration \"%s\", tabell \"%s\" har startat" -#: replication/logical/worker.c:4515 +#: replication/logical/worker.c:4636 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "logiska replikeringens ändringsapplicerare för prenumeration \"%s\" har startat" -#: replication/logical/worker.c:4590 -#, c-format -msgid "subscription has no replication slot set" -msgstr "prenumeration har ingen replikeringsslot angiven" - -#: replication/logical/worker.c:4757 +#: replication/logical/worker.c:4758 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "prenumeration \"%s\" har avaktiverats på grund av ett fel" -#: replication/logical/worker.c:4805 +#: replication/logical/worker.c:4806 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "logisk replikering börjar hoppa över transaktion vid LSN %X/%X" -#: replication/logical/worker.c:4819 +#: replication/logical/worker.c:4820 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "logisk replikering har slutfört överhoppande av transaktionen vid LSN %X/%X" -#: replication/logical/worker.c:4901 +#: replication/logical/worker.c:4902 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "överhoppnings-LSN för logiska prenumerationen \"%s\" har nollställts" -#: replication/logical/worker.c:4902 +#: replication/logical/worker.c:4903 #, c-format msgid "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X." msgstr "Fjärrtransaktionens slut-WAL-position (LSN) %X/%X matchade inte överhoppnings-LSN %X/%X." -#: replication/logical/worker.c:4928 +#: replication/logical/worker.c:4940 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\"" msgstr "processar fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\"" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:4944 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u" msgstr "processar fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" i transaktion %u" -#: replication/logical/worker.c:4937 +#: replication/logical/worker.c:4949 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X" msgstr "processande av fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" i transaktion %u blev klar vid %X/%X" -#: replication/logical/worker.c:4948 +#: replication/logical/worker.c:4960 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u" msgstr "processande av fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" för replikeringsmålrelation \"%s.%s\" i transaktion %u" -#: replication/logical/worker.c:4955 +#: replication/logical/worker.c:4967 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X" msgstr "processande av fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" för replikeringsmålrelation \"%s.%s\" i transaktion %u blev klart vid %X/%X" -#: replication/logical/worker.c:4966 +#: replication/logical/worker.c:4978 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" msgstr "processande av fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" för replikeringsmålrelation \"%s.%s\" kolumn \"%s\" i transaktion %u" -#: replication/logical/worker.c:4974 +#: replication/logical/worker.c:4986 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X" msgstr "processande av fjärrdata för replikeringskälla \"%s\" vid meddelandetyp \"%s\" för replikeringsmålrelation \"%s.%s\" kolumn \"%s\" i transaktion %u blev klart vid %X/%X" -#: replication/pgoutput/pgoutput.c:318 +#: replication/pgoutput/pgoutput.c:322 #, c-format msgid "invalid proto_version" msgstr "ogiltig proto_version" -#: replication/pgoutput/pgoutput.c:323 +#: replication/pgoutput/pgoutput.c:327 #, c-format msgid "proto_version \"%s\" out of range" msgstr "proto_version \"%s\" är utanför giltigt intervall" -#: replication/pgoutput/pgoutput.c:340 +#: replication/pgoutput/pgoutput.c:344 #, c-format msgid "invalid publication_names syntax" msgstr "ogiltig publication_names-syntax" -#: replication/pgoutput/pgoutput.c:443 +#: replication/pgoutput/pgoutput.c:414 replication/pgoutput/pgoutput.c:418 +#, c-format +msgid "option \"%s\" missing" +msgstr "flaggan \"%s\" saknas." + +#: replication/pgoutput/pgoutput.c:478 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or lower" msgstr "klienten skickade proto_version=%d men servern stöder bara protokoll %d eller lägre" -#: replication/pgoutput/pgoutput.c:449 +#: replication/pgoutput/pgoutput.c:484 #, c-format msgid "client sent proto_version=%d but server only supports protocol %d or higher" msgstr "klienten skickade proto_version=%d men servern stöder bara protokoll %d eller högre" -#: replication/pgoutput/pgoutput.c:455 -#, c-format -msgid "publication_names parameter missing" -msgstr "saknar parameter publication_names" - -#: replication/pgoutput/pgoutput.c:469 +#: replication/pgoutput/pgoutput.c:499 #, c-format msgid "requested proto_version=%d does not support streaming, need %d or higher" msgstr "efterfrågade proto_version=%d stöder inte strömning, kräver %d eller högre" -#: replication/pgoutput/pgoutput.c:475 +#: replication/pgoutput/pgoutput.c:505 #, c-format msgid "requested proto_version=%d does not support parallel streaming, need %d or higher" msgstr "efterfrågade proto_version=%d stöder inte parallell strömning, kräver %d eller högre" -#: replication/pgoutput/pgoutput.c:480 +#: replication/pgoutput/pgoutput.c:510 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "ströming begärdes men det stöds inte av utdata-plugin:en" -#: replication/pgoutput/pgoutput.c:497 +#: replication/pgoutput/pgoutput.c:524 #, c-format msgid "requested proto_version=%d does not support two-phase commit, need %d or higher" msgstr "efterfrågade proto_version=%d stöder inte tvåfas-commit, kräver %d eller högre" -#: replication/pgoutput/pgoutput.c:502 +#: replication/pgoutput/pgoutput.c:529 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "tvåfas-commit begärdes men det stöds inte av utdata-plugin:en" -#: replication/slot.c:207 +#: replication/slot.c:260 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "replikeringsslotnamn \"%s\" är för kort" -#: replication/slot.c:216 +#: replication/slot.c:269 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "replikeringsslotnamn \"%s\" är för långt" -#: replication/slot.c:229 +#: replication/slot.c:282 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "replikeringsslotnamn \"%s\" innehåller ogiltiga tecken" -#: replication/slot.c:231 +#: replication/slot.c:284 #, c-format msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character." msgstr "Replikeringsslotnamn får bara innehålla små bokstäver, nummer och understreck." -#: replication/slot.c:285 +#: replication/slot.c:333 +#, c-format +msgid "cannot enable failover for a replication slot created on the standby" +msgstr "kan inte aktivera failover för en replikeringsslot som skapats på standby:en" + +#: replication/slot.c:345 replication/slot.c:849 +#, c-format +msgid "cannot enable failover for a temporary replication slot" +msgstr "kan inte aktivera failover för en temporär repllikeringsslot" + +#: replication/slot.c:370 #, c-format msgid "replication slot \"%s\" already exists" msgstr "replikeringsslot \"%s\" finns redan" -#: replication/slot.c:295 +#: replication/slot.c:380 #, c-format msgid "all replication slots are in use" msgstr "alla replikeringsslots används" -#: replication/slot.c:296 +#: replication/slot.c:381 #, c-format -msgid "Free one or increase max_replication_slots." -msgstr "Frigör en eller öka max_replication_slots." +msgid "Free one or increase \"max_replication_slots\"." +msgstr "Frigör en eller öka \"max_replication_slots\"." -#: replication/slot.c:474 replication/slotfuncs.c:736 -#: utils/activity/pgstat_replslot.c:55 utils/adt/genfile.c:774 +#: replication/slot.c:560 replication/slot.c:2450 replication/slotfuncs.c:661 +#: utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "replikeringsslot \"%s\" existerar inte" -#: replication/slot.c:520 replication/slot.c:1110 +#: replication/slot.c:606 replication/slot.c:1337 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "replikeringsslot \"%s\" är aktiv för PID %d" -#: replication/slot.c:756 replication/slot.c:1645 replication/slot.c:2028 +#: replication/slot.c:638 +#, c-format +msgid "acquired logical replication slot \"%s\"" +msgstr "tog logisk replikeringsslot \"%s\"" + +#: replication/slot.c:640 +#, c-format +msgid "acquired physical replication slot \"%s\"" +msgstr "tog fysisk replikeringsslot \"%s\"" + +#: replication/slot.c:729 +#, c-format +msgid "released logical replication slot \"%s\"" +msgstr "släppte logisk replikeringsslot \"%s\"" + +#: replication/slot.c:731 +#, c-format +msgid "released physical replication slot \"%s\"" +msgstr "släppte fysisk replikeringsslot \"%s\"" + +#: replication/slot.c:797 +#, c-format +msgid "cannot drop replication slot \"%s\"" +msgstr "kan inte slänga replikeringsslot \"%s\"" + +#: replication/slot.c:816 +#, c-format +msgid "cannot use %s with a physical replication slot" +msgstr "kan inte använda %s med en fysisk replikeringsslot" + +#: replication/slot.c:828 +#, c-format +msgid "cannot alter replication slot \"%s\"" +msgstr "kan inte ändra replikeringsslot \"%s\"" + +#: replication/slot.c:838 +#, c-format +msgid "cannot enable failover for a replication slot on the standby" +msgstr "kan inte aktivera failover för en replikeringsslot på standby:en" + +#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 #, c-format msgid "could not remove directory \"%s\"" msgstr "kunde inte ta bort katalog \"%s\"" -#: replication/slot.c:1145 +#: replication/slot.c:1372 #, c-format -msgid "replication slots can only be used if max_replication_slots > 0" -msgstr "replikeringsslots kan bara användas om max_replication_slots > 0" +msgid "replication slots can only be used if \"max_replication_slots\" > 0" +msgstr "replikeringsslots kan bara användas om \"max_replication_slots\" > 0" -#: replication/slot.c:1150 +#: replication/slot.c:1377 #, c-format -msgid "replication slots can only be used if wal_level >= replica" -msgstr "replikeringsslots kan bara användas om wal_level >= replica" +msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" +msgstr "replikeringsslots kan bara användas om \"wal_level\" >= \"replica\"" -#: replication/slot.c:1162 +#: replication/slot.c:1389 #, c-format msgid "permission denied to use replication slots" msgstr "rättighet saknas för att använda replikeringsslottar" -#: replication/slot.c:1163 +#: replication/slot.c:1390 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "Bara roller med attributet %s får använda replikeringsslottar." -#: replication/slot.c:1271 +#: replication/slot.c:1498 #, c-format msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." msgstr[0] "Slottens restart_lsn %X/%X överskrider gränsen på %llu byte." msgstr[1] "Slottens restart_lsn %X/%X överskrider gränsen på %llu bytes." -#: replication/slot.c:1279 +#: replication/slot.c:1506 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "Slotten är i konflikt med xid-horisont %u." -#: replication/slot.c:1284 -msgid "Logical decoding on standby requires wal_level >= logical on the primary server." -msgstr "logisk avkodning på standby kräver wal_level >= logical på primären" +#: replication/slot.c:1511 +msgid "Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server." +msgstr "logisk avkodning på standby kräver \"wal_level\" >= \"logical\" på primären" -#: replication/slot.c:1292 +#: replication/slot.c:1519 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "avslutar process %d för att frigöra replikeringsslot \"%s\"" -#: replication/slot.c:1294 +#: replication/slot.c:1521 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "invaliderar obsolet replikeringssslot \"%s\"" -#: replication/slot.c:1966 +#: replication/slot.c:2249 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "replikeringsslotfil \"%s\" har fel magiskt nummer: %u istället för %u" -#: replication/slot.c:1973 +#: replication/slot.c:2256 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "replikeringsslotfil \"%s\" har en icke stödd version %u" -#: replication/slot.c:1980 +#: replication/slot.c:2263 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "replikeringsslotfil \"%s\" har felaktig längd %u" -#: replication/slot.c:2016 +#: replication/slot.c:2299 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "kontrollsummefel för replikeringsslot-fil \"%s\": är %u, skall vara %u" -#: replication/slot.c:2050 +#: replication/slot.c:2333 #, c-format -msgid "logical replication slot \"%s\" exists, but wal_level < logical" -msgstr "logisk replikeringsslot \"%s\" finns men wal_level < replica" +msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" +msgstr "logisk replikeringsslot \"%s\" finns men \"wal_level\" < \"replica\"" -#: replication/slot.c:2052 +#: replication/slot.c:2335 #, c-format -msgid "Change wal_level to be logical or higher." -msgstr "Ändra wal_level till logical eller högre." +msgid "Change \"wal_level\" to be \"logical\" or higher." +msgstr "Ändra \"wal_level\" till \"logical\" eller högre." -#: replication/slot.c:2056 +#: replication/slot.c:2339 #, c-format -msgid "physical replication slot \"%s\" exists, but wal_level < replica" -msgstr "fysisk replikeringsslot \"%s\" finns men wal_level < replica" +msgid "physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" +msgstr "fysisk replikeringsslot \"%s\" finns men \"wal_level\" < \"replica\"" -#: replication/slot.c:2058 +#: replication/slot.c:2341 #, c-format -msgid "Change wal_level to be replica or higher." -msgstr "Ändra wal_level till replica eller högre." +msgid "Change \"wal_level\" to be \"replica\" or higher." +msgstr "Ändra \"wal_level\" till \"replica\" eller högre." -#: replication/slot.c:2092 +#: replication/slot.c:2383 #, c-format msgid "too many replication slots active before shutdown" msgstr "för många aktiva replikeringsslottar innan nerstängning" -#: replication/slotfuncs.c:601 +#: replication/slot.c:2458 +#, c-format +msgid "\"%s\" is not a physical replication slot" +msgstr "\"%s\" är inte en fysisk replikeringsslot" + +#: replication/slot.c:2635 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "replikeringsslot \"%s\" som angivits i parametern \"%s\" existerar inte" + +#: replication/slot.c:2637 replication/slot.c:2671 replication/slot.c:2686 +#, c-format +msgid "Logical replication is waiting on the standby associated with replication slot \"%s\"." +msgstr "Logisk replikering väntar på standby associerad med replikeringsslot \"%s\"." + +#: replication/slot.c:2639 +#, c-format +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "Skapa replikeringsslotten \"%s\" eller ändra parametern \"%s\"" + +#: replication/slot.c:2649 +#, c-format +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "kan inte ange logisk replikeringsslot \"%s\" i parametern \"%s\"" + +#: replication/slot.c:2651 +#, c-format +msgid "Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "Logiska replikering väntar på rättning av replikeringsslot \"%s\"" + +#: replication/slot.c:2653 +#, c-format +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "Ta bort logisk replikeringsslot \"%s\" från parametern \"%s\"" + +#: replication/slot.c:2669 +#, c-format +msgid "physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated" +msgstr "fysisk replikeringsslot \"%s\" angiven i parametern \"%s\" har invaliderats" + +#: replication/slot.c:2673 +#, c-format +msgid "Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "Släng och återskapa replikeringsslotten \"%s\" eller ändra parametern %s." + +#: replication/slot.c:2684 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not have active_pid" +msgstr "replikeringsslot \"%s\" angiven i parametern \"%s\" har inte active_pid" + +#: replication/slot.c:2688 +#, c-format +msgid "Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "Starta standby associerad med replikeringsslot \"%s\" eller ändra parametern \"%s\"." + +#: replication/slotfuncs.c:526 #, c-format msgid "invalid target WAL LSN" msgstr "ogiltig mål-LSN för WAL" -#: replication/slotfuncs.c:623 +#: replication/slotfuncs.c:548 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "replikeringsslot \"%s\" kan inte avanceras" -#: replication/slotfuncs.c:625 +#: replication/slotfuncs.c:550 #, c-format msgid "This slot has never previously reserved WAL, or it has been invalidated." msgstr "Denna slot har aldrig tidigare reserverat WAL eller så har den invaliderats." -#: replication/slotfuncs.c:641 +#: replication/slotfuncs.c:566 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "kan inte flytta fram replikeringsslot till %X/%X, minimum är %X/%X" -#: replication/slotfuncs.c:748 +#: replication/slotfuncs.c:673 #, c-format msgid "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "kan inte kopiera fysisk replikeringsslot \"%s\" som en logisk replikeringsslot" -#: replication/slotfuncs.c:750 +#: replication/slotfuncs.c:675 #, c-format msgid "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "kan inte kopiera logisk replikeringsslot \"%s\" som en fysisk replikeringsslot" -#: replication/slotfuncs.c:757 +#: replication/slotfuncs.c:682 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "kan inte kopiera en replikeringsslot som inte tidigare har reserverat WAL" -#: replication/slotfuncs.c:834 +#: replication/slotfuncs.c:768 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "kunde inte kopiera replikeringsslot \"%s\"" -#: replication/slotfuncs.c:836 +#: replication/slotfuncs.c:770 #, c-format msgid "The source replication slot was modified incompatibly during the copy operation." msgstr "Källreplikeringsslotten ändrades på ett inkompatibelt sätt under copy-operationen." -#: replication/slotfuncs.c:842 +#: replication/slotfuncs.c:776 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "kan inte kopiera ej slutförd replikeringsslot \"%s\"" -#: replication/slotfuncs.c:844 +#: replication/slotfuncs.c:778 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "Försök igen när källreplikeringsslottens confirmed_flush_lsn är giltig." -#: replication/syncrep.c:262 +#: replication/slotfuncs.c:877 +#, c-format +msgid "replication slots can only be synchronized to a standby server" +msgstr "replikerings-slot kan bara synkroniseras till en standby-server" + +#: replication/syncrep.c:261 #, c-format msgid "canceling the wait for synchronous replication and terminating connection due to administrator command" msgstr "avbryter väntan på synkron replikering samt avslutar anslutning på grund av ett administratörskommando" -#: replication/syncrep.c:263 replication/syncrep.c:280 +#: replication/syncrep.c:262 replication/syncrep.c:279 #, c-format msgid "The transaction has already committed locally, but might not have been replicated to the standby." msgstr "Transaktionen har redan commit:ats lokalt men har kanske inte replikerats till standby:en." -#: replication/syncrep.c:279 +#: replication/syncrep.c:278 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "avbryter väntan på synkron replikering efter användarens önskemål" -#: replication/syncrep.c:486 +#: replication/syncrep.c:485 #, c-format -msgid "standby \"%s\" is now a synchronous standby with priority %u" -msgstr "standby \"%s\" är nu en synkron standby med prioritet %u" +msgid "standby \"%s\" is now a synchronous standby with priority %d" +msgstr "standby \"%s\" är nu en synkron standby med prioritet %d" -#: replication/syncrep.c:490 +#: replication/syncrep.c:489 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "standby \"%s\" är nu en kvorumkandidat för synkron standby" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1013 #, c-format -msgid "synchronous_standby_names parser failed" -msgstr "synchronous_standby_names-parser misslyckades" +msgid "\"synchronous_standby_names\" parser failed" +msgstr "\"synchronous_standby_names\"-parser misslyckades" -#: replication/syncrep.c:1025 +#: replication/syncrep.c:1019 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "antal synkrona standbys (%d) måste vara fler än noll" -#: replication/walreceiver.c:180 +#: replication/walreceiver.c:176 #, c-format msgid "terminating walreceiver process due to administrator command" msgstr "avslutar wal-mottagarprocessen på grund av ett administratörskommando" -#: replication/walreceiver.c:305 -#, c-format -msgid "could not connect to the primary server: %s" -msgstr "kunde inte ansluta till primärserver: %s" - -#: replication/walreceiver.c:352 +#: replication/walreceiver.c:354 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "databassystemets identifierare skiljer sig åt mellan primären och standby:en" -#: replication/walreceiver.c:353 +#: replication/walreceiver.c:355 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "Primärens identifierare är %s, standby:ens identifierare är %s." -#: replication/walreceiver.c:364 +#: replication/walreceiver.c:366 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "högsta tidslinjen %u i primären är efter återställningstidslinjen %u" -#: replication/walreceiver.c:417 +#: replication/walreceiver.c:419 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "startade strömning av WAL från primären vid %X/%X på tidslinje %u" -#: replication/walreceiver.c:421 +#: replication/walreceiver.c:423 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "återstartade WAL-strömning vid %X/%X på tidslinje %u" -#: replication/walreceiver.c:457 +#: replication/walreceiver.c:458 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "kan inte fortsätta WAL-strömning, återställning har redan avslutats" -#: replication/walreceiver.c:501 +#: replication/walreceiver.c:502 #, c-format msgid "replication terminated by primary server" msgstr "replikering avslutad av primär server" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:503 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "Slut på WAL nådd på tidslinje %u vid %X/%X." -#: replication/walreceiver.c:592 +#: replication/walreceiver.c:593 #, c-format msgid "terminating walreceiver due to timeout" msgstr "avslutar wal-mottagare på grund av timeout" -#: replication/walreceiver.c:624 +#: replication/walreceiver.c:625 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "primär server har ingen mer WAL på efterfrågad tidslinje %u" -#: replication/walreceiver.c:640 replication/walreceiver.c:1066 +#: replication/walreceiver.c:641 replication/walreceiver.c:1071 #, c-format msgid "could not close WAL segment %s: %m" msgstr "kunde inte stänga WAL-segment %s: %m" -#: replication/walreceiver.c:759 +#: replication/walreceiver.c:760 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "hämtar tidslinjehistorikfil för tidslinje %u från primära servern" -#: replication/walreceiver.c:954 +#: replication/walreceiver.c:959 #, c-format -msgid "could not write to WAL segment %s at offset %u, length %lu: %m" -msgstr "kunde inte skriva till WAL-segment %s på offset %u, längd %lu: %m" +msgid "could not write to WAL segment %s at offset %d, length %lu: %m" +msgstr "kunde inte skriva till WAL-segment %s på offset %d, längd %lu: %m" -#: replication/walsender.c:519 +#: replication/walsender.c:531 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "kan inte använda %s med logisk replikeringsslot" -#: replication/walsender.c:623 storage/smgr/md.c:1529 +#: replication/walsender.c:635 storage/smgr/md.c:1735 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "kunde inte söka (seek) till slutet av filen \"%s\": %m" -#: replication/walsender.c:627 +#: replication/walsender.c:639 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "kunde inte söka till början av filen \"%s\": %m" -#: replication/walsender.c:704 +#: replication/walsender.c:853 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "kan inte använda logisk replikeringsslot för fysisk replikering" -#: replication/walsender.c:770 +#: replication/walsender.c:919 #, c-format msgid "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "efterfrågad startpunkt %X/%X på tidslinje %u finns inte i denna servers historik" -#: replication/walsender.c:773 +#: replication/walsender.c:922 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "Denna servers historik delade sig från tidslinje %u vid %X/%X." -#: replication/walsender.c:817 +#: replication/walsender.c:966 #, c-format msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X" msgstr "efterfrågad startpunkt %X/%X är längre fram än denna servers flush:ade WAL-skrivposition %X/%X" -#: replication/walsender.c:1010 +#: replication/walsender.c:1160 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "okänt värde för CREATE_REPLICATION_SLOT-flagga \"%s\": \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1095 +#: replication/walsender.c:1266 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s får inte anropas i en transaktion" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1105 +#: replication/walsender.c:1276 #, c-format msgid "%s must be called inside a transaction" msgstr "%s måste anropas i en transaktion" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1111 +#: replication/walsender.c:1282 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s måste anropas i transaktions REPEATABLE READ-isolationsläge" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1116 +#: replication/walsender.c:1287 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%s måste anropas i en read-only-transaktion" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1122 +#: replication/walsender.c:1293 #, c-format msgid "%s must be called before any query" msgstr "%s måste anropas innan någon fråga" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1128 +#: replication/walsender.c:1299 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s får inte anropas i en undertransaktion" -#: replication/walsender.c:1275 +#: replication/walsender.c:1472 #, c-format msgid "terminating walsender process after promotion" -msgstr "stänger ner walsender-process efter befordring" +msgstr "stänger ner walsender-process efter befordran" -#: replication/walsender.c:1696 +#: replication/walsender.c:2000 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "kan inte utföra nya kommandon när WAL-sändare är i stopp-läge" -#: replication/walsender.c:1731 +#: replication/walsender.c:2035 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "kan inte köra SQL-kommandon i WAL-sändare för fysisk replikering" -#: replication/walsender.c:1764 +#: replication/walsender.c:2068 #, c-format msgid "received replication command: %s" msgstr "tog emot replikeringskommando: %s" -#: replication/walsender.c:1772 tcop/fastpath.c:209 tcop/postgres.c:1138 -#: tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2210 -#: tcop/postgres.c:2648 tcop/postgres.c:2726 +#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1142 +#: tcop/postgres.c:1500 tcop/postgres.c:1752 tcop/postgres.c:2234 +#: tcop/postgres.c:2672 tcop/postgres.c:2749 #, c-format msgid "current transaction is aborted, commands ignored until end of transaction block" msgstr "aktuella transaktionen har avbrutits, alla kommandon ignoreras tills slutet på transaktionen" -#: replication/walsender.c:1914 replication/walsender.c:1949 +#: replication/walsender.c:2233 replication/walsender.c:2268 #, c-format msgid "unexpected EOF on standby connection" msgstr "oväntat EOF från standby-anslutning" -#: replication/walsender.c:1937 +#: replication/walsender.c:2256 #, c-format msgid "invalid standby message type \"%c\"" msgstr "ogiltigt standby-meddelandetyp \"%c\"" -#: replication/walsender.c:2026 +#: replication/walsender.c:2345 #, c-format msgid "unexpected message type \"%c\"" msgstr "oväntad meddelandetyp \"%c\"" -#: replication/walsender.c:2439 +#: replication/walsender.c:2759 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "avslutar walsender-process på grund av replikerings-timeout" -#: rewrite/rewriteDefine.c:111 rewrite/rewriteDefine.c:842 +#: rewrite/rewriteDefine.c:104 rewrite/rewriteDefine.c:835 #, c-format msgid "rule \"%s\" for relation \"%s\" already exists" msgstr "regel \"%s\" för relation \"%s\" existerar redan" -#: rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:780 +#: rewrite/rewriteDefine.c:261 rewrite/rewriteDefine.c:773 #, c-format msgid "relation \"%s\" cannot have rules" msgstr "relationen \"%s\" kan inte ha regler" -#: rewrite/rewriteDefine.c:299 +#: rewrite/rewriteDefine.c:292 #, c-format msgid "rule actions on OLD are not implemented" msgstr "regelhandlingar på OLD är inte implementerat" -#: rewrite/rewriteDefine.c:300 +#: rewrite/rewriteDefine.c:293 #, c-format msgid "Use views or triggers instead." msgstr "Använd vyer eller triggrar istället." -#: rewrite/rewriteDefine.c:304 +#: rewrite/rewriteDefine.c:297 #, c-format msgid "rule actions on NEW are not implemented" msgstr "regelhandlingar på NEW är inte implementerat" -#: rewrite/rewriteDefine.c:305 +#: rewrite/rewriteDefine.c:298 #, c-format msgid "Use triggers instead." msgstr "Använd triggrar istället." -#: rewrite/rewriteDefine.c:319 +#: rewrite/rewriteDefine.c:312 #, c-format msgid "relation \"%s\" cannot have ON SELECT rules" msgstr "relationen \"%s\" kan inte ha ON SELECT-regler" -#: rewrite/rewriteDefine.c:329 +#: rewrite/rewriteDefine.c:322 #, c-format msgid "INSTEAD NOTHING rules on SELECT are not implemented" msgstr "INSTEAD NOTHING-regler på SELECT är inte implementerat ännu" -#: rewrite/rewriteDefine.c:330 +#: rewrite/rewriteDefine.c:323 #, c-format msgid "Use views instead." msgstr "Använd vyer istället." -#: rewrite/rewriteDefine.c:338 +#: rewrite/rewriteDefine.c:331 #, c-format msgid "multiple actions for rules on SELECT are not implemented" msgstr "flera regelhandlingar på SELECT är inte implementerat" -#: rewrite/rewriteDefine.c:348 +#: rewrite/rewriteDefine.c:341 #, c-format msgid "rules on SELECT must have action INSTEAD SELECT" msgstr "regler på SELECT måste ha handlingen INSTEAD SELECT" -#: rewrite/rewriteDefine.c:356 +#: rewrite/rewriteDefine.c:349 #, c-format msgid "rules on SELECT must not contain data-modifying statements in WITH" msgstr "regler på SELECT får inte innehålla datamodifierande satser i WITH" -#: rewrite/rewriteDefine.c:364 +#: rewrite/rewriteDefine.c:357 #, c-format msgid "event qualifications are not implemented for rules on SELECT" msgstr "händelsebegränsningar är inte implementerat för regler på SELECT" -#: rewrite/rewriteDefine.c:391 +#: rewrite/rewriteDefine.c:384 #, c-format msgid "\"%s\" is already a view" msgstr "\"%s\" är redan en vy" -#: rewrite/rewriteDefine.c:415 +#: rewrite/rewriteDefine.c:408 #, c-format msgid "view rule for \"%s\" must be named \"%s\"" msgstr "vy-regel (rule) för \"%s\" måste ha namnet \"%s\"" -#: rewrite/rewriteDefine.c:442 +#: rewrite/rewriteDefine.c:435 #, c-format msgid "cannot have multiple RETURNING lists in a rule" msgstr "kan inte ha flera RETURNING-listor i en regel" -#: rewrite/rewriteDefine.c:447 +#: rewrite/rewriteDefine.c:440 #, c-format msgid "RETURNING lists are not supported in conditional rules" msgstr "RETURNING-listor stöds inte i villkorade regler" -#: rewrite/rewriteDefine.c:451 +#: rewrite/rewriteDefine.c:444 #, c-format msgid "RETURNING lists are not supported in non-INSTEAD rules" msgstr "RETURNING-listor stöds inte i icke-INSTEAD-regler" -#: rewrite/rewriteDefine.c:465 +#: rewrite/rewriteDefine.c:458 #, c-format msgid "non-view rule for \"%s\" must not be named \"%s\"" msgstr "regel (rule) för icke-vy \"%s\" får inte ha namnet \"%s\"" -#: rewrite/rewriteDefine.c:539 +#: rewrite/rewriteDefine.c:532 #, c-format msgid "SELECT rule's target list has too many entries" msgstr "SELECT-regelns mållista har för många poster" -#: rewrite/rewriteDefine.c:540 +#: rewrite/rewriteDefine.c:533 #, c-format msgid "RETURNING list has too many entries" msgstr "RETURNING-lista har för många element" -#: rewrite/rewriteDefine.c:567 +#: rewrite/rewriteDefine.c:560 #, c-format msgid "cannot convert relation containing dropped columns to view" msgstr "kan inte konvertera en relation som har borttagna kolumner till en vy" -#: rewrite/rewriteDefine.c:568 +#: rewrite/rewriteDefine.c:561 #, c-format msgid "cannot create a RETURNING list for a relation containing dropped columns" msgstr "kan inte skapa en RETURNING-lista för relationer som innehåller borttagna kolumner" -#: rewrite/rewriteDefine.c:574 +#: rewrite/rewriteDefine.c:567 #, c-format msgid "SELECT rule's target entry %d has different column name from column \"%s\"" msgstr "SELECT-regels målpost %d har ett annat kolumnnamn än kolumnen \"%s\"" -#: rewrite/rewriteDefine.c:576 +#: rewrite/rewriteDefine.c:569 #, c-format msgid "SELECT target entry is named \"%s\"." msgstr "SELECT-målpost har namn \"%s\"." -#: rewrite/rewriteDefine.c:585 +#: rewrite/rewriteDefine.c:578 #, c-format msgid "SELECT rule's target entry %d has different type from column \"%s\"" msgstr "SELECT-regels målpot %d har en annan typ än kolumnen \"%s\"" -#: rewrite/rewriteDefine.c:587 +#: rewrite/rewriteDefine.c:580 #, c-format msgid "RETURNING list's entry %d has different type from column \"%s\"" msgstr "RETURNING-listans post %d har en annan typ än kolumnen \"%s\"" -#: rewrite/rewriteDefine.c:590 rewrite/rewriteDefine.c:614 +#: rewrite/rewriteDefine.c:583 rewrite/rewriteDefine.c:607 #, c-format msgid "SELECT target entry has type %s, but column has type %s." msgstr "SELECT-målpost har typ %s men kolumnen har typ %s." -#: rewrite/rewriteDefine.c:593 rewrite/rewriteDefine.c:618 +#: rewrite/rewriteDefine.c:586 rewrite/rewriteDefine.c:611 #, c-format msgid "RETURNING list entry has type %s, but column has type %s." msgstr "RETURNING-listpost har typ %s men kolumnen har typ %s." -#: rewrite/rewriteDefine.c:609 +#: rewrite/rewriteDefine.c:602 #, c-format msgid "SELECT rule's target entry %d has different size from column \"%s\"" msgstr "SELECT-regelns målpost %d har en annan storlek än kolumnen \"%s\"" -#: rewrite/rewriteDefine.c:611 +#: rewrite/rewriteDefine.c:604 #, c-format msgid "RETURNING list's entry %d has different size from column \"%s\"" msgstr "RETURNING-listpost %d har en annan storlek än kolumnen\"%s\"" -#: rewrite/rewriteDefine.c:628 +#: rewrite/rewriteDefine.c:621 #, c-format msgid "SELECT rule's target list has too few entries" msgstr "SELECT-regels mållista har för få element" -#: rewrite/rewriteDefine.c:629 +#: rewrite/rewriteDefine.c:622 #, c-format msgid "RETURNING list has too few entries" msgstr "RETURNING-lista har för få element" -#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:833 -#: rewrite/rewriteSupport.c:109 +#: rewrite/rewriteDefine.c:711 rewrite/rewriteDefine.c:826 +#: rewrite/rewriteSupport.c:108 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist" msgstr "regel \"%s\" för relation \"%s\" existerar inte" -#: rewrite/rewriteDefine.c:852 +#: rewrite/rewriteDefine.c:845 #, c-format msgid "renaming an ON SELECT rule is not allowed" msgstr "byta namn på en ON SELECT-regel tillåts inte" -#: rewrite/rewriteHandler.c:583 +#: rewrite/rewriteHandler.c:588 #, c-format msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten" msgstr "WITH-frågenamn \"%s\" finns både i en regelhändelse och i frågan som skrivs om" -#: rewrite/rewriteHandler.c:610 +#: rewrite/rewriteHandler.c:615 #, c-format msgid "INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH" msgstr "INSERT ... SELECT-regler stöds inte för frågor som har datamodifierande satser i WITH" -#: rewrite/rewriteHandler.c:663 +#: rewrite/rewriteHandler.c:668 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "kan inte ha RETURNING-listor i multipla regler" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:934 +#: rewrite/rewriteHandler.c:900 rewrite/rewriteHandler.c:939 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "kan inte sätta in ett icke-DEFAULT-värde i kolumn \"%s\"" -#: rewrite/rewriteHandler.c:897 rewrite/rewriteHandler.c:963 +#: rewrite/rewriteHandler.c:902 rewrite/rewriteHandler.c:968 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "Kolumn \"%s\" är en identitetskolumn definierad som GENERATED ALWAYS." -#: rewrite/rewriteHandler.c:899 +#: rewrite/rewriteHandler.c:904 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "Använd OVERRIDING SYSTEM VALUE för att överskugga." -#: rewrite/rewriteHandler.c:961 rewrite/rewriteHandler.c:969 +#: rewrite/rewriteHandler.c:966 rewrite/rewriteHandler.c:974 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "kolumn \"%s\" kan bara uppdateras till DEFAULT" -#: rewrite/rewriteHandler.c:1116 rewrite/rewriteHandler.c:1134 +#: rewrite/rewriteHandler.c:1109 rewrite/rewriteHandler.c:1127 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "flera tilldelningar till samma kolumn \"%s\"" -#: rewrite/rewriteHandler.c:2119 rewrite/rewriteHandler.c:4040 +#: rewrite/rewriteHandler.c:1682 +#, c-format +msgid "MERGE is not supported for relations with rules." +msgstr "MERGE stöds inte för relationer med regler." + +#: rewrite/rewriteHandler.c:1722 rewrite/rewriteHandler.c:3262 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "access till icke-system vy \"%s\" är begränsad" + +#: rewrite/rewriteHandler.c:2122 rewrite/rewriteHandler.c:4254 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "oändlig rekursion detekterad i reglerna för relation \"%s\"" -#: rewrite/rewriteHandler.c:2204 +#: rewrite/rewriteHandler.c:2227 #, c-format msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "oändlig rekursion detekterad i policy för relation \"%s\"" -#: rewrite/rewriteHandler.c:2524 +#: rewrite/rewriteHandler.c:2589 msgid "Junk view columns are not updatable." msgstr "Skräpkolumner i vy är inte uppdateringsbara." -#: rewrite/rewriteHandler.c:2529 +#: rewrite/rewriteHandler.c:2594 msgid "View columns that are not columns of their base relation are not updatable." msgstr "Vykolumner som inte är kolumner i dess basrelation är inte uppdateringsbara." -#: rewrite/rewriteHandler.c:2532 +#: rewrite/rewriteHandler.c:2597 msgid "View columns that refer to system columns are not updatable." msgstr "Vykolumner som refererar till systemkolumner är inte uppdateringsbara." -#: rewrite/rewriteHandler.c:2535 +#: rewrite/rewriteHandler.c:2600 msgid "View columns that return whole-row references are not updatable." msgstr "Vykolumner som returnerar hel-rad-referenser är inte uppdateringsbara." -#: rewrite/rewriteHandler.c:2596 +#: rewrite/rewriteHandler.c:2661 msgid "Views containing DISTINCT are not automatically updatable." msgstr "Vyer som innehåller DISTINCT är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2599 +#: rewrite/rewriteHandler.c:2664 msgid "Views containing GROUP BY are not automatically updatable." msgstr "Vyer som innehåller GROUP BY är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2602 +#: rewrite/rewriteHandler.c:2667 msgid "Views containing HAVING are not automatically updatable." msgstr "Vyer som innehåller HAVING är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2605 +#: rewrite/rewriteHandler.c:2670 msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "Vyer som innehåller UNION, INTERSECT eller EXCEPT är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2608 +#: rewrite/rewriteHandler.c:2673 msgid "Views containing WITH are not automatically updatable." msgstr "Vyer som innehåller WITH är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2611 +#: rewrite/rewriteHandler.c:2676 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "Vyer som innehåller LIMIT eller OFFSET är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2623 +#: rewrite/rewriteHandler.c:2688 msgid "Views that return aggregate functions are not automatically updatable." msgstr "Vyer som returnerar aggregatfunktioner är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2626 +#: rewrite/rewriteHandler.c:2691 msgid "Views that return window functions are not automatically updatable." msgstr "Vyer som returnerar fönsterfunktioner uppdateras inte automatiskt." -#: rewrite/rewriteHandler.c:2629 +#: rewrite/rewriteHandler.c:2694 msgid "Views that return set-returning functions are not automatically updatable." msgstr "Vyer som returnerar mängd-returnerande funktioner är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2636 rewrite/rewriteHandler.c:2640 -#: rewrite/rewriteHandler.c:2648 +#: rewrite/rewriteHandler.c:2701 rewrite/rewriteHandler.c:2705 +#: rewrite/rewriteHandler.c:2713 msgid "Views that do not select from a single table or view are not automatically updatable." msgstr "Vyer som inte läser från en ensam tabell eller vy är inte automatiskt uppdateringsbar." -#: rewrite/rewriteHandler.c:2651 +#: rewrite/rewriteHandler.c:2716 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "Vyer som innehåller TABLESAMPLE är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:2675 +#: rewrite/rewriteHandler.c:2740 msgid "Views that have no updatable columns are not automatically updatable." msgstr "Vyer som inte har några uppdateringsbara kolumner är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:3155 +#: rewrite/rewriteHandler.c:3121 rewrite/rewriteHandler.c:3156 #, c-format -msgid "cannot insert into column \"%s\" of view \"%s\"" -msgstr "kan inte insert:a i kolumn \"%s\" i vy \"%s\"" +msgid "cannot insert into view \"%s\"" +msgstr "kan inte sätta in i vy \"%s\"" -#: rewrite/rewriteHandler.c:3163 +#: rewrite/rewriteHandler.c:3124 #, c-format -msgid "cannot update column \"%s\" of view \"%s\"" -msgstr "kan inte uppdatera kolumn \"%s\" i view \"%s\"" +msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." +msgstr "För att tillåta insättning i en vy så skapa en INSTEAD OF INSERT-trigger eller en villkorslös ON INSERT DO INSTEAD-regel." -#: rewrite/rewriteHandler.c:3667 +#: rewrite/rewriteHandler.c:3129 rewrite/rewriteHandler.c:3165 #, c-format -msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" -msgstr "DO INSTEAD NOTIFY-regler stöds inte för datamodifierande satser i WITH" +msgid "cannot update view \"%s\"" +msgstr "kan inte uppdatera vy \"%s\"" -#: rewrite/rewriteHandler.c:3678 +#: rewrite/rewriteHandler.c:3132 #, c-format -msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" -msgstr "DO INSTEAD NOTHING-regler stöds inte för datamodifierande satser i WITH" +msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." +msgstr "För att tillåta uppdatering av en vy så skapa en INSTEAD OF UPDATE-trigger eller en villkorslös ON UPDATE DO INSTEAD-regel." -#: rewrite/rewriteHandler.c:3692 +#: rewrite/rewriteHandler.c:3137 rewrite/rewriteHandler.c:3174 #, c-format -msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" -msgstr "villkorliga DO INSTEAD-regler stöds inte för datamodifierande satser i WITH" +msgid "cannot delete from view \"%s\"" +msgstr "kan inte radera från vy \"%s\"" -#: rewrite/rewriteHandler.c:3696 +#: rewrite/rewriteHandler.c:3140 #, c-format -msgid "DO ALSO rules are not supported for data-modifying statements in WITH" -msgstr "DO ALSO-regler stöds inte för datamodifierande satser i WITH" +msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." +msgstr "För att tillåta bortagning i en vy så skapa en INSTEAD OF DELETE-trigger eller en villkorslös ON DELETE DO INSTEAD-regel." -#: rewrite/rewriteHandler.c:3701 +#: rewrite/rewriteHandler.c:3159 +#, c-format +msgid "To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger." +msgstr "För att tillåta insert till en vy med MERGE så krävs en INSTEAD OF INSERT-trigger." + +#: rewrite/rewriteHandler.c:3168 +#, c-format +msgid "To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger." +msgstr "För att tillåta uppdatering av en vy så krävs en INSTEAD OF UPDATE-trigger." + +#: rewrite/rewriteHandler.c:3177 +#, c-format +msgid "To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger." +msgstr "För att tillåta borttagning från en vy så krävs en INSTEAD OF DELETE-trigger." + +#: rewrite/rewriteHandler.c:3352 +#, c-format +msgid "cannot insert into column \"%s\" of view \"%s\"" +msgstr "kan inte insert:a i kolumn \"%s\" i vy \"%s\"" + +#: rewrite/rewriteHandler.c:3360 +#, c-format +msgid "cannot update column \"%s\" of view \"%s\"" +msgstr "kan inte uppdatera kolumn \"%s\" i view \"%s\"" + +#: rewrite/rewriteHandler.c:3368 +#, c-format +msgid "cannot merge into column \"%s\" of view \"%s\"" +msgstr "kan inte merge:a till kolumn \"%s\" i vy \"%s\"" + +#: rewrite/rewriteHandler.c:3396 +#, c-format +msgid "cannot merge into view \"%s\"" +msgstr "kan inte merge:a till vy \"%s\"" + +#: rewrite/rewriteHandler.c:3398 +#, c-format +msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions but not all." +msgstr "MERGE stöds inte för vyer med INSTEAD OF-trigger för vissa actions men inte för andra." + +#: rewrite/rewriteHandler.c:3399 +#, c-format +msgid "To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers." +msgstr "För att tillåta merge till en vy så antingen skapa en full uppsättning INSTEAD OF-triggers eller släng de befintliga INSERT OF-triggers." + +#: rewrite/rewriteHandler.c:3912 +#, c-format +msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" +msgstr "DO INSTEAD NOTIFY-regler stöds inte för datamodifierande satser i WITH" + +#: rewrite/rewriteHandler.c:3923 +#, c-format +msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" +msgstr "DO INSTEAD NOTHING-regler stöds inte för datamodifierande satser i WITH" + +#: rewrite/rewriteHandler.c:3937 +#, c-format +msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" +msgstr "villkorliga DO INSTEAD-regler stöds inte för datamodifierande satser i WITH" + +#: rewrite/rewriteHandler.c:3941 +#, c-format +msgid "DO ALSO rules are not supported for data-modifying statements in WITH" +msgstr "DO ALSO-regler stöds inte för datamodifierande satser i WITH" + +#: rewrite/rewriteHandler.c:3946 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "fler-satsiga DO INSTEAD-regler stöds inte för datamodifierande satser i WITH" -#: rewrite/rewriteHandler.c:3968 rewrite/rewriteHandler.c:3976 -#: rewrite/rewriteHandler.c:3984 -#, c-format +#: rewrite/rewriteHandler.c:4206 msgid "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "Vyer med villkorliga DO INSTEAD-regler är inte automatiskt uppdateringsbara." -#: rewrite/rewriteHandler.c:4089 +#: rewrite/rewriteHandler.c:4303 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "kan inte utföra INSERT RETURNING på relation \"%s\"" -#: rewrite/rewriteHandler.c:4091 +#: rewrite/rewriteHandler.c:4305 #, c-format msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "Du behöver en villkorslös ON INSERT DO INSTEAD-regel med en RETURNING-klausul." -#: rewrite/rewriteHandler.c:4096 +#: rewrite/rewriteHandler.c:4310 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "kan inte utföra UPDATE RETURNING på relation \"%s\"" -#: rewrite/rewriteHandler.c:4098 +#: rewrite/rewriteHandler.c:4312 #, c-format msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "Du behöver en villkorslös ON UPDATE DO INSTEAD-regel med en RETURNING-klausul." -#: rewrite/rewriteHandler.c:4103 +#: rewrite/rewriteHandler.c:4317 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "kan inte utföra DELETE RETURNING på relation \"%s\"" -#: rewrite/rewriteHandler.c:4105 +#: rewrite/rewriteHandler.c:4319 #, c-format msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "Du behöver en villkorslös ON DELETE DO INSTEAD-regel med en RETURNING-klausul." -#: rewrite/rewriteHandler.c:4123 +#: rewrite/rewriteHandler.c:4337 #, c-format msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" msgstr "INSERT med ON CONFLICT-klausul kan inte användas med tabell som har INSERT- eller UPDATE-regler" -#: rewrite/rewriteHandler.c:4180 +#: rewrite/rewriteHandler.c:4394 #, c-format msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries" msgstr "WITH kan inte användas i en fråga där regler skrivit om den till flera olika frågor" -#: rewrite/rewriteManip.c:1075 +#: rewrite/rewriteManip.c:1084 #, c-format msgid "conditional utility statements are not implemented" msgstr "villkorliga hjälpsatser är inte implementerat" -#: rewrite/rewriteManip.c:1419 +#: rewrite/rewriteManip.c:1431 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "WHERE CURRENT OF för en vy är inte implementerat" -#: rewrite/rewriteManip.c:1754 +#: rewrite/rewriteManip.c:1767 #, c-format msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command" msgstr "NEW-variabler i ON UPDATE-regler kan inte referera till kolumner som är del av en multiple uppdatering i subjektets UPDATE-kommando" @@ -21677,117 +22475,117 @@ msgstr "NEW-variabler i ON UPDATE-regler kan inte referera till kolumner som är msgid "with a SEARCH or CYCLE clause, the recursive reference to WITH query \"%s\" must be at the top level of its right-hand SELECT" msgstr "med en SEARCH- eller CYCLE-klausul så måste rekursiva referensen till WITH-fråga \"%s\" vara på toppnivå eller i dess högra SELECT" -#: scan.l:482 +#: scan.l:497 msgid "unterminated /* comment" msgstr "ej avslutad /*-kommentar" -#: scan.l:502 +#: scan.l:517 msgid "unterminated bit string literal" msgstr "ej avslutad bitsträngslitteral" -#: scan.l:516 +#: scan.l:531 msgid "unterminated hexadecimal string literal" msgstr "ej avslutad hexadecimal stränglitteral" -#: scan.l:566 +#: scan.l:581 #, c-format msgid "unsafe use of string constant with Unicode escapes" msgstr "osäker användning av strängkonstand med Unicode-escape:r" -#: scan.l:567 +#: scan.l:582 #, c-format -msgid "String constants with Unicode escapes cannot be used when standard_conforming_strings is off." -msgstr "Strängkonstanter som innehåller Unicode-escapesekvenser kan inte användas när standard_conforming_strings är av." +msgid "String constants with Unicode escapes cannot be used when \"standard_conforming_strings\" is off." +msgstr "Strängkonstanter som innehåller Unicode-escapesekvenser kan inte användas när \"standard_conforming_strings\" är av." -#: scan.l:628 +#: scan.l:643 msgid "unhandled previous state in xqs" msgstr "tidigare state i xqs som ej kan hanteras" -#: scan.l:702 +#: scan.l:717 #, c-format msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX." msgstr "Unicode-escapesekvenser måste vara \\uXXXX eller \\UXXXXXXXX." -#: scan.l:713 +#: scan.l:728 #, c-format msgid "unsafe use of \\' in a string literal" msgstr "osäker användning av \\' i stränglitteral" -#: scan.l:714 +#: scan.l:729 #, c-format msgid "Use '' to write quotes in strings. \\' is insecure in client-only encodings." msgstr "Använd '' för att inkludera ett enkelcitattecken i en sträng. \\' är inte säkert i klient-teckenkodning." -#: scan.l:786 +#: scan.l:801 msgid "unterminated dollar-quoted string" msgstr "icke terminerad dollarciterad sträng" -#: scan.l:803 scan.l:813 +#: scan.l:818 scan.l:828 msgid "zero-length delimited identifier" msgstr "noll-längds avdelad identifierare" -#: scan.l:824 syncrep_scanner.l:101 +#: scan.l:839 syncrep_scanner.l:101 msgid "unterminated quoted identifier" msgstr "icke terminerad citerad identifierare" -#: scan.l:987 +#: scan.l:1002 msgid "operator too long" msgstr "operatorn är för lång" -#: scan.l:1000 +#: scan.l:1015 msgid "trailing junk after parameter" msgstr "skräptecken kommer efter parameter" -#: scan.l:1021 +#: scan.l:1036 msgid "invalid hexadecimal integer" msgstr "ogiltigt hexdecimalt heltal" -#: scan.l:1025 +#: scan.l:1040 msgid "invalid octal integer" msgstr "ogiltigt oktalt heltal" -#: scan.l:1029 +#: scan.l:1044 msgid "invalid binary integer" msgstr "ogiltigt binärt heltal" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1236 +#: scan.l:1239 #, c-format msgid "%s at end of input" msgstr "%s vid slutet av indatan" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1244 +#: scan.l:1247 #, c-format msgid "%s at or near \"%s\"" msgstr "%s vid eller nära \"%s\"" -#: scan.l:1434 +#: scan.l:1439 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "ickestandard användning av \\' i stränglitteral" -#: scan.l:1435 +#: scan.l:1440 #, c-format msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "Använd '' för att skriva citattecken i strängar eller använd escape-strängsyntac (E'...')." -#: scan.l:1444 +#: scan.l:1449 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "ickestandard användning av \\\\ i strängslitteral" -#: scan.l:1445 +#: scan.l:1450 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "Använd escape-strängsyntax för bakstreck, dvs. E'\\\\'." -#: scan.l:1459 +#: scan.l:1464 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "ickestandard användning av escape i stränglitteral" -#: scan.l:1460 +#: scan.l:1465 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "Använd escape-strängsyntax, dvs E'\\r\\n'." @@ -21818,72 +22616,67 @@ msgstr "okänd Snowball-parameter: \"%s\"" msgid "missing Language parameter" msgstr "saknar parameter \"Language\"" -#: statistics/extended_stats.c:179 +#: statistics/extended_stats.c:176 #, c-format msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "statistikobjekt \"%s.%s\" kunde inte beräknas för relation \"%s.%s\"" -#: statistics/mcv.c:1372 +#: statistics/mcv.c:1368 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "en funktion med post som värde anropades i sammanhang där poster inte kan godtagas." -#: storage/buffer/bufmgr.c:612 storage/buffer/bufmgr.c:769 +#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 #, c-format msgid "cannot access temporary tables of other sessions" msgstr "får inte röra temporära tabeller som tillhör andra sessioner" -#: storage/buffer/bufmgr.c:1137 +#: storage/buffer/bufmgr.c:1532 #, c-format msgid "invalid page in block %u of relation %s; zeroing out page" msgstr "felaktig sida i block %u för relation %s; nollställer sidan" -#: storage/buffer/bufmgr.c:1931 storage/buffer/localbuf.c:359 +#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "kan inte utöka relation %s utöver %u block" -#: storage/buffer/bufmgr.c:1998 +#: storage/buffer/bufmgr.c:2348 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "oväntad data efter EOF i block %u för relation %s" -#: storage/buffer/bufmgr.c:2000 +#: storage/buffer/bufmgr.c:2350 #, c-format msgid "This has been seen to occur with buggy kernels; consider updating your system." msgstr "Detta beteende har observerats med buggiga kärnor; fundera på att uppdatera ditt system." -#: storage/buffer/bufmgr.c:5219 +#: storage/buffer/bufmgr.c:5653 #, c-format msgid "could not write block %u of %s" msgstr "kunde inte skriva block %u av %s" -#: storage/buffer/bufmgr.c:5221 +#: storage/buffer/bufmgr.c:5655 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "Multipla fel --- skrivfelet kan vara permanent." -#: storage/buffer/bufmgr.c:5243 storage/buffer/bufmgr.c:5263 +#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 #, c-format msgid "writing block %u of relation %s" msgstr "skriver block %u i relation %s" -#: storage/buffer/bufmgr.c:5593 -#, c-format -msgid "snapshot too old" -msgstr "snapshot för gammal" - -#: storage/buffer/localbuf.c:219 +#: storage/buffer/localbuf.c:220 #, c-format msgid "no empty local buffer available" msgstr "ingen tom lokal buffer tillgänglig" -#: storage/buffer/localbuf.c:592 +#: storage/buffer/localbuf.c:597 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "kan inte komma åt temporära tabeller under en parallell operation" -#: storage/buffer/localbuf.c:699 +#: storage/buffer/localbuf.c:712 #, c-format msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." msgstr "\"temp_buffers\" kan inte ändras efter att man använt temporära tabeller i sessionen." @@ -21903,152 +22696,157 @@ msgstr "kunde inte läsa från filmängd \"%s\": läste bara %zu av %zu byte" msgid "could not read from temporary file: read only %zu of %zu bytes" msgstr "kunde inte läsa från temporärfil: läste bara %zu av %zu byte" -#: storage/file/buffile.c:774 storage/file/buffile.c:895 +#: storage/file/buffile.c:774 storage/file/buffile.c:877 #, c-format msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" msgstr "kunde inte bestämma storlek på temporär fil \"%s\" från BufFile \"%s\": %m" -#: storage/file/buffile.c:974 +#: storage/file/buffile.c:956 #, c-format msgid "could not delete fileset \"%s\": %m" msgstr "kunde inte radera filmängd \"%s\": %m" -#: storage/file/buffile.c:992 storage/smgr/md.c:338 storage/smgr/md.c:1041 +#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1194 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "kunde inte trunkera fil \"%s\": %m" -#: storage/file/fd.c:537 storage/file/fd.c:609 storage/file/fd.c:645 +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" msgstr "kunde inte flush:a smutsig data: %m" -#: storage/file/fd.c:567 +#: storage/file/fd.c:613 #, c-format msgid "could not determine dirty data size: %m" msgstr "kunde inte lista ut storlek på smutsig data: %m" -#: storage/file/fd.c:619 +#: storage/file/fd.c:665 #, c-format msgid "could not munmap() while flushing data: %m" msgstr "kunde inte göra munmap() vid flush:ning av data: %m" -#: storage/file/fd.c:937 +#: storage/file/fd.c:983 #, c-format msgid "getrlimit failed: %m" msgstr "getrlimit misslyckades: %m" -#: storage/file/fd.c:1027 +#: storage/file/fd.c:1073 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "otillräckligt antal fildeskriptorer tillgängligt för att starta serverprocessen" -#: storage/file/fd.c:1028 +#: storage/file/fd.c:1074 #, c-format msgid "System allows %d, server needs at least %d." msgstr "Systemet tillåter %d, servern behöver minst %d." -#: storage/file/fd.c:1116 storage/file/fd.c:2565 storage/file/fd.c:2674 -#: storage/file/fd.c:2825 +#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 +#: storage/file/fd.c:2878 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "slut på fildeskriptorer: %m; frigör och försök igen" -#: storage/file/fd.c:1490 +#: storage/file/fd.c:1536 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "temporär fil: sökväg \"%s\", storlek %lu" -#: storage/file/fd.c:1629 +#: storage/file/fd.c:1675 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "kunde inte skapa temporär katalog \"%s\": %m" -#: storage/file/fd.c:1636 +#: storage/file/fd.c:1682 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "kunde inte skapa temporär underkatalog \"%s\": %m" -#: storage/file/fd.c:1833 +#: storage/file/fd.c:1879 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "kan inte skapa temporär fil \"%s\": %m" -#: storage/file/fd.c:1869 +#: storage/file/fd.c:1915 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "kunde inte öppna temporär fil \"%s\": %m" # unlink refererar till unix-funktionen unlink() så den översätter vi inte -#: storage/file/fd.c:1910 +#: storage/file/fd.c:1956 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "kunde inte unlink:a temporär fil \"%s\": %m" -#: storage/file/fd.c:1998 +#: storage/file/fd.c:2044 #, c-format msgid "could not delete file \"%s\": %m" msgstr "kunde inte radera fil \"%s\": %m" -#: storage/file/fd.c:2185 +#: storage/file/fd.c:2234 #, c-format msgid "temporary file size exceeds temp_file_limit (%dkB)" msgstr "storlek på temporär fil överskrider temp_file_limit (%dkB)" -#: storage/file/fd.c:2541 storage/file/fd.c:2600 +#: storage/file/fd.c:2594 storage/file/fd.c:2653 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "överskred maxAllocatedDescs (%d) vid försök att öppna fil \"%s\"" -#: storage/file/fd.c:2645 +#: storage/file/fd.c:2698 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "överskred maxAllocatedDescs (%d) vid försök att köra kommando \"%s\"" -#: storage/file/fd.c:2801 +#: storage/file/fd.c:2854 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "överskred maxAllocatedDescs (%d) vid försök att öppna katalog \"%s\"" -#: storage/file/fd.c:3331 +#: storage/file/fd.c:3384 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "oväntad fil hittades i katalogen för temporära filer: \"%s\"" -#: storage/file/fd.c:3449 +#: storage/file/fd.c:3502 #, c-format msgid "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "synkroniserar datakatalog (syncfs), förbrukad tid: %ld.%02d s, aktuell sökväg: %s" -#: storage/file/fd.c:3463 -#, c-format -msgid "could not synchronize file system for file \"%s\": %m" -msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" - -#: storage/file/fd.c:3676 +#: storage/file/fd.c:3729 #, c-format msgid "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "synkroniserar datakatalog (pre-fsync), förbrukad tid: %ld.%02d s, aktuell sökväg: %s" -#: storage/file/fd.c:3708 +#: storage/file/fd.c:3761 #, c-format msgid "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "synkroniserar datakatalog (fsync), förbrukad tid: %ld.%02d s, aktuell sökväg: %s" -#: storage/file/fd.c:3897 +#: storage/file/fd.c:3950 +#, c-format +msgid "\"debug_io_direct\" is not supported on this platform." +msgstr "\"debug_io_direct\" stöds inte på denna plattform." + +#: storage/file/fd.c:3964 +#, c-format +msgid "Invalid list syntax in parameter \"%s\"" +msgstr "Ogiltigt listsyntax för parameter \"%s\"" + +#: storage/file/fd.c:3984 #, c-format -msgid "debug_io_direct is not supported on this platform." -msgstr "debug_io_direct stöds inte på denna plattform." +msgid "Invalid option \"%s\"" +msgstr "Ogiltig flagga \"%s\"" -#: storage/file/fd.c:3944 +#: storage/file/fd.c:3997 #, c-format -msgid "debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small" -msgstr "debug_io_direct stöds inte för WAL då XLOG_BLCKSZ är för liten" +msgid "\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" +msgstr "\"debug_io_direct\" stöds inte för WAL då XLOG_BLCKSZ är för liten" -#: storage/file/fd.c:3951 +#: storage/file/fd.c:4004 #, c-format -msgid "debug_io_direct is not supported for data because BLCKSZ is too small" -msgstr "debug_io_direct stöds inte för data då BLCKSZ är för liten" +msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" +msgstr "\"debug_io_direct\" stöds inte för data då BLCKSZ är för liten" #: storage/file/reinit.c:145 #, c-format @@ -22060,22 +22858,22 @@ msgstr "nollställer ologgade relationer (init), förbrukad tid %ld.%02d s, aktu msgid "resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s" msgstr "nollställer ologgade relationer (cleanup), förbrukad tid %ld.%02d s, aktuell sökväg: %s" -#: storage/file/sharedfileset.c:79 +#: storage/file/sharedfileset.c:73 #, c-format msgid "could not attach to a SharedFileSet that is already destroyed" msgstr "kunde inte koppla till en SharedFileSet som redan tagits bort" -#: storage/ipc/dsm.c:352 +#: storage/ipc/dsm.c:379 #, c-format msgid "dynamic shared memory control segment is corrupt" msgstr "dynamiskt delat minnes kontrollsegment är korrupt" -#: storage/ipc/dsm.c:417 +#: storage/ipc/dsm.c:444 #, c-format msgid "dynamic shared memory control segment is not valid" msgstr "dynamiskt delat minnes kontrollsegment är inte giltigt" -#: storage/ipc/dsm.c:599 +#: storage/ipc/dsm.c:626 #, c-format msgid "too many dynamic shared memory segments" msgstr "för många dynamiska delade minnessegment" @@ -22135,73 +22933,99 @@ msgstr "kunde inte stänga delat minnessegment \"%s\": %m" msgid "could not duplicate handle for \"%s\": %m" msgstr "kunde inte duplicera handle för \"%s\": %m" -#: storage/ipc/procarray.c:3796 +#: storage/ipc/dsm_registry.c:142 +#, c-format +msgid "DSM segment name cannot be empty" +msgstr "Namn på DSM-segment får inte vara tomt" + +#: storage/ipc/dsm_registry.c:146 +#, c-format +msgid "DSM segment name too long" +msgstr "Namn på DSM-segment är för långt" + +#: storage/ipc/dsm_registry.c:150 +#, c-format +msgid "DSM segment size must be nonzero" +msgstr "Storlek på DSM-segment får inte vara noll" + +#: storage/ipc/dsm_registry.c:176 +#, c-format +msgid "requested DSM segment size does not match size of existing segment" +msgstr "efterfrågad storlek på DSM-segment matchar inte storleken på nuvarande segment" + +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:357 +#: tcop/backend_startup.c:304 +#, c-format +msgid "sorry, too many clients already" +msgstr "ledsen, för många klienter" + +#: storage/ipc/procarray.c:3857 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "databasen \"%s\" används av förberedda transationer" -#: storage/ipc/procarray.c:3828 storage/ipc/procarray.c:3837 -#: storage/ipc/signalfuncs.c:230 storage/ipc/signalfuncs.c:237 +#: storage/ipc/procarray.c:3893 storage/ipc/procarray.c:3901 +#: storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 #, c-format msgid "permission denied to terminate process" msgstr "rättighet saknas för att avsluta process" -#: storage/ipc/procarray.c:3829 storage/ipc/signalfuncs.c:231 +#: storage/ipc/procarray.c:3894 storage/ipc/signalfuncs.c:236 #, c-format msgid "Only roles with the %s attribute may terminate processes of roles with the %s attribute." msgstr "Bara roller med attributet %s får terminera processer för roller som har attributet %s." -#: storage/ipc/procarray.c:3838 storage/ipc/signalfuncs.c:238 +#: storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:243 #, c-format msgid "Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process." msgstr "Bara roller med rättigheter från rollen vars process kommer termineras eller med rättigheter från rollen \"%s\" får terminera denna process." -#: storage/ipc/procsignal.c:420 +#: storage/ipc/procsignal.c:416 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "väntare fortfarande på att backend:en med PID %d skall acceptera ProcSignalBarrier" -#: storage/ipc/shm_mq.c:384 +#: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" msgstr "kan inte skicka ett meddelande med storlek %zu via kö i delat minne" -#: storage/ipc/shm_mq.c:719 +#: storage/ipc/shm_mq.c:718 #, c-format msgid "invalid message size %zu in shared memory queue" msgstr "ogiltig meddelandestorlek %zu i kö i delat minne" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:963 -#: storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2786 storage/lmgr/lock.c:4171 -#: storage/lmgr/lock.c:4236 storage/lmgr/lock.c:4586 -#: storage/lmgr/predicate.c:2412 storage/lmgr/predicate.c:2427 -#: storage/lmgr/predicate.c:3824 storage/lmgr/predicate.c:4871 -#: utils/hash/dynahash.c:1107 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:984 +#: storage/lmgr/lock.c:1022 storage/lmgr/lock.c:2835 storage/lmgr/lock.c:4220 +#: storage/lmgr/lock.c:4285 storage/lmgr/lock.c:4635 +#: storage/lmgr/predicate.c:2468 storage/lmgr/predicate.c:2483 +#: storage/lmgr/predicate.c:3880 storage/lmgr/predicate.c:4927 +#: utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "slut på delat minne" -#: storage/ipc/shmem.c:170 storage/ipc/shmem.c:266 +#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "slut på delat minne (%zu byte efterfrågat)" -#: storage/ipc/shmem.c:445 +#: storage/ipc/shmem.c:436 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "kunde inte skapa ShmemIndex-post för datastrukturen \"%s\"" -#: storage/ipc/shmem.c:460 +#: storage/ipc/shmem.c:451 #, c-format msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu" msgstr "ShmemIndex-poststorlek är fel för datastruktur \"%s\": förväntade %zu var %zu" -#: storage/ipc/shmem.c:479 +#: storage/ipc/shmem.c:470 #, c-format msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)" msgstr "otillräckligt delat minne för datastruktur \"%s\" (efterfrågade %zu byte)" -#: storage/ipc/shmem.c:511 storage/ipc/shmem.c:530 +#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 #, c-format msgid "requested shared memory size overflows size_t" msgstr "efterfrågad delat minnesstorlek överskrider size_t" @@ -22211,128 +23035,124 @@ msgstr "efterfrågad delat minnesstorlek överskrider size_t" msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %d är inte en PostgreSQL backend-process" -#: storage/ipc/signalfuncs.c:104 storage/lmgr/proc.c:1379 -#: utils/adt/mcxtfuncs.c:190 +#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1453 +#: utils/adt/mcxtfuncs.c:182 #, c-format msgid "could not send signal to process %d: %m" msgstr "kunde inte skicka signal till process %d: %m" -#: storage/ipc/signalfuncs.c:124 storage/ipc/signalfuncs.c:131 +#: storage/ipc/signalfuncs.c:129 storage/ipc/signalfuncs.c:136 #, c-format msgid "permission denied to cancel query" msgstr "rättighet saknas för att avbryta fråga" -#: storage/ipc/signalfuncs.c:125 +#: storage/ipc/signalfuncs.c:130 #, c-format msgid "Only roles with the %s attribute may cancel queries of roles with the %s attribute." msgstr "Bara roller med attributet %s får avbryta frågor åt roller med attributet %s." -#: storage/ipc/signalfuncs.c:132 +#: storage/ipc/signalfuncs.c:137 #, c-format msgid "Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query." msgstr "Bara roller med rättigheter från rollen vars fråga kommer avbrytas eller med rättigheter från rollen \"%s\" får avbryta denna fråga." -#: storage/ipc/signalfuncs.c:174 +#: storage/ipc/signalfuncs.c:179 #, c-format msgid "could not check the existence of the backend with PID %d: %m" msgstr "kunde inte kontrollera existensen av en backend med PID %d: %m" -#: storage/ipc/signalfuncs.c:192 +#: storage/ipc/signalfuncs.c:197 #, c-format msgid "backend with PID %d did not terminate within %lld millisecond" msgid_plural "backend with PID %d did not terminate within %lld milliseconds" msgstr[0] "backend med PID %d terminerade inte inom %lld millisekund" msgstr[1] "backend med PID %d terminerade inte inom %lld millisekunder" -#: storage/ipc/signalfuncs.c:223 +#: storage/ipc/signalfuncs.c:228 #, c-format msgid "\"timeout\" must not be negative" msgstr "\"timeout\" kan inte vara negativ" -#: storage/ipc/signalfuncs.c:279 -#, c-format -msgid "must be superuser to rotate log files with adminpack 1.0" -msgstr "måste vara superuser för att rotera loggfiler med adminpack 1.0" - -#. translator: %s is a SQL function name -#: storage/ipc/signalfuncs.c:281 utils/adt/genfile.c:250 -#, c-format -msgid "Consider using %s, which is part of core, instead." -msgstr "Du kanske kan använda %s istället som är en del av core." - -#: storage/ipc/signalfuncs.c:287 storage/ipc/signalfuncs.c:307 +#: storage/ipc/signalfuncs.c:285 #, c-format msgid "rotation not possible because log collection not active" msgstr "rotering är inte möjligt då logginsamling inte är aktiverad" -#: storage/ipc/standby.c:330 +#: storage/ipc/standby.c:329 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "återställning väntar fortfarande efter %ld.%03d ms: %s" -#: storage/ipc/standby.c:339 +#: storage/ipc/standby.c:338 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "återställning slutade vänta efter efter %ld.%03d ms: %s" -#: storage/ipc/standby.c:921 tcop/postgres.c:3384 +#: storage/ipc/standby.c:920 tcop/postgres.c:3196 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "avbryter sats på grund av konflikt med återställning" -#: storage/ipc/standby.c:922 tcop/postgres.c:2533 +#: storage/ipc/standby.c:921 tcop/postgres.c:2557 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "Användartransaktion orsakade deadlock för buffer vid återställning." -#: storage/ipc/standby.c:1488 +#: storage/ipc/standby.c:1486 msgid "unknown reason" msgstr "okänt skäl" -#: storage/ipc/standby.c:1493 +#: storage/ipc/standby.c:1491 msgid "recovery conflict on buffer pin" msgstr "återställningskonflikt vid bufferfastlåsning" -#: storage/ipc/standby.c:1496 +#: storage/ipc/standby.c:1494 msgid "recovery conflict on lock" msgstr "återställningskonflikt vid lås" -#: storage/ipc/standby.c:1499 +#: storage/ipc/standby.c:1497 msgid "recovery conflict on tablespace" msgstr "återställningskonflikt vid tabellutrymme" -#: storage/ipc/standby.c:1502 +#: storage/ipc/standby.c:1500 msgid "recovery conflict on snapshot" msgstr "återställningskonflikt vid snapshot" -#: storage/ipc/standby.c:1505 +#: storage/ipc/standby.c:1503 msgid "recovery conflict on replication slot" msgstr "återställningskonflikt vid replikeringsslot" -#: storage/ipc/standby.c:1508 +#: storage/ipc/standby.c:1506 msgid "recovery conflict on buffer deadlock" msgstr "återställningskonflikt vid bufferdeadlock" -#: storage/ipc/standby.c:1511 +#: storage/ipc/standby.c:1509 msgid "recovery conflict on database" msgstr "återställningskonflikt vid databas" -#: storage/large_object/inv_api.c:191 +#: storage/large_object/inv_api.c:190 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "pg_largeobject-post för OID %u, sida %d har ogiltig datafältstorlek %d" -#: storage/large_object/inv_api.c:274 +#: storage/large_object/inv_api.c:272 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "ogiltiga flaggor för att öppna stort objekt: %d" -#: storage/large_object/inv_api.c:457 +#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 +#: storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 +#: storage/large_object/inv_api.c:807 +#, c-format +msgid "permission denied for large object %u" +msgstr "rättighet saknas för stort objekt %u" + +#: storage/large_object/inv_api.c:455 #, c-format msgid "invalid whence setting: %d" msgstr "ogiltig whence-inställning: %d" -#: storage/large_object/inv_api.c:629 +#: storage/large_object/inv_api.c:627 #, c-format msgid "invalid large object write request size: %d" msgstr "ogiltig storlek för stort objects skrivningbegäran: %d" @@ -22357,211 +23177,211 @@ msgstr "deadlock upptäckt" msgid "See server log for query details." msgstr "Se server-logg för frågedetaljer." -#: storage/lmgr/lmgr.c:859 +#: storage/lmgr/lmgr.c:848 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "vid uppdatering av tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:862 +#: storage/lmgr/lmgr.c:851 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "vid borttagning av tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:865 +#: storage/lmgr/lmgr.c:854 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "vid låsning av tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:868 +#: storage/lmgr/lmgr.c:857 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "vid låsning av uppdaterad version (%u,%u) av tupel i relation \"%s\"" -#: storage/lmgr/lmgr.c:871 +#: storage/lmgr/lmgr.c:860 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "vid insättning av indextupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:874 +#: storage/lmgr/lmgr.c:863 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "vid kontroll av unikhet av tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:877 +#: storage/lmgr/lmgr.c:866 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "vid återkontroll av uppdaterad tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:880 +#: storage/lmgr/lmgr.c:869 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "vid kontroll av uteslutningsvillkor av tupel (%u,%u) i relation \"%s\"" -#: storage/lmgr/lmgr.c:1174 +#: storage/lmgr/lmgr.c:1239 #, c-format msgid "relation %u of database %u" msgstr "relation %u i databasen %u" -#: storage/lmgr/lmgr.c:1180 +#: storage/lmgr/lmgr.c:1245 #, c-format msgid "extension of relation %u of database %u" msgstr "utökning av relation %u i databas %u" -#: storage/lmgr/lmgr.c:1186 +#: storage/lmgr/lmgr.c:1251 #, c-format msgid "pg_database.datfrozenxid of database %u" msgstr "pg_database.datfrozenxid för databas %u" -#: storage/lmgr/lmgr.c:1191 +#: storage/lmgr/lmgr.c:1256 #, c-format msgid "page %u of relation %u of database %u" msgstr "sida %u i relation %u i databas %u" -#: storage/lmgr/lmgr.c:1198 +#: storage/lmgr/lmgr.c:1263 #, c-format msgid "tuple (%u,%u) of relation %u of database %u" msgstr "tuple (%u,%u) i relation %u i databas %u" -#: storage/lmgr/lmgr.c:1206 +#: storage/lmgr/lmgr.c:1271 #, c-format msgid "transaction %u" msgstr "transaktion %u" -#: storage/lmgr/lmgr.c:1211 +#: storage/lmgr/lmgr.c:1276 #, c-format msgid "virtual transaction %d/%u" msgstr "vituell transaktion %d/%u" -#: storage/lmgr/lmgr.c:1217 +#: storage/lmgr/lmgr.c:1282 #, c-format msgid "speculative token %u of transaction %u" msgstr "spekulativ token %u för transaktion %u" -#: storage/lmgr/lmgr.c:1223 +#: storage/lmgr/lmgr.c:1288 #, c-format msgid "object %u of class %u of database %u" msgstr "objekt %u av klass %u i databas %u" -#: storage/lmgr/lmgr.c:1231 +#: storage/lmgr/lmgr.c:1296 #, c-format msgid "user lock [%u,%u,%u]" msgstr "användarlås [%u,%u,%u]" -#: storage/lmgr/lmgr.c:1238 +#: storage/lmgr/lmgr.c:1303 #, c-format msgid "advisory lock [%u,%u,%u,%u]" msgstr "rådgivande lås [%u,%u,%u,%u]" -#: storage/lmgr/lmgr.c:1246 +#: storage/lmgr/lmgr.c:1311 #, c-format msgid "remote transaction %u of subscription %u of database %u" msgstr "fjärrtransaktion %u för prenumeration %u i databas %u" -#: storage/lmgr/lmgr.c:1253 +#: storage/lmgr/lmgr.c:1318 #, c-format msgid "unrecognized locktag type %d" msgstr "okänd låsetikettyp %d" -#: storage/lmgr/lock.c:791 +#: storage/lmgr/lock.c:812 #, c-format msgid "cannot acquire lock mode %s on database objects while recovery is in progress" msgstr "kan inte ta låsläge %s på databasobjekt när återställning pågår" -#: storage/lmgr/lock.c:793 +#: storage/lmgr/lock.c:814 #, c-format msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery." msgstr "Bara RowExclusiveLock eller lägre kan tas på databasobjekt under återställning." -#: storage/lmgr/lock.c:3235 storage/lmgr/lock.c:3303 storage/lmgr/lock.c:3419 +#: storage/lmgr/lock.c:3284 storage/lmgr/lock.c:3352 storage/lmgr/lock.c:3468 #, c-format msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object" msgstr "kan inte göra PREPARE samtidigt som vi håller lås på sessionsnivå och transaktionsnivå för samma objekt" -#: storage/lmgr/predicate.c:649 +#: storage/lmgr/predicate.c:653 #, c-format msgid "not enough elements in RWConflictPool to record a read/write conflict" msgstr "ej tillräckligt med element i RWConflictPool för att spara ner en läs/skriv-konflikt" -#: storage/lmgr/predicate.c:650 storage/lmgr/predicate.c:675 +#: storage/lmgr/predicate.c:654 storage/lmgr/predicate.c:679 #, c-format -msgid "You might need to run fewer transactions at a time or increase max_connections." -msgstr "Du kan behöva köra färre samtidiga transaktioner eller öka max_connections." +msgid "You might need to run fewer transactions at a time or increase \"max_connections\"." +msgstr "Du kan behöva köra färre samtidiga transaktioner eller öka \"max_connections\"." -#: storage/lmgr/predicate.c:674 +#: storage/lmgr/predicate.c:678 #, c-format msgid "not enough elements in RWConflictPool to record a potential read/write conflict" msgstr "ej tillräckligt med element i RWConflictPool för att spara ner en potentiell läs/skriv-konflikt" -#: storage/lmgr/predicate.c:1630 +#: storage/lmgr/predicate.c:1686 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "\"default_transaction_isolation\" är satt till \"serializable\"." -#: storage/lmgr/predicate.c:1631 +#: storage/lmgr/predicate.c:1687 #, c-format msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default." msgstr "Du kan använda \"SET default_transaction_isolation = 'repeatable read'\" för att ändra standardvärdet." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1738 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "en snapshot-importerande transaktion får inte vara READ ONLY DEFERRABLE" -#: storage/lmgr/predicate.c:1761 utils/time/snapmgr.c:570 -#: utils/time/snapmgr.c:576 +#: storage/lmgr/predicate.c:1817 utils/time/snapmgr.c:535 +#: utils/time/snapmgr.c:541 #, c-format msgid "could not import the requested snapshot" msgstr "kunde inte importera efterfrågat snapshot" -#: storage/lmgr/predicate.c:1762 utils/time/snapmgr.c:577 +#: storage/lmgr/predicate.c:1818 utils/time/snapmgr.c:542 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "Källprocessen med PID %d kör inte längre." -#: storage/lmgr/predicate.c:3935 storage/lmgr/predicate.c:3971 -#: storage/lmgr/predicate.c:4004 storage/lmgr/predicate.c:4012 -#: storage/lmgr/predicate.c:4051 storage/lmgr/predicate.c:4281 -#: storage/lmgr/predicate.c:4600 storage/lmgr/predicate.c:4612 -#: storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4695 +#: storage/lmgr/predicate.c:3991 storage/lmgr/predicate.c:4027 +#: storage/lmgr/predicate.c:4060 storage/lmgr/predicate.c:4068 +#: storage/lmgr/predicate.c:4107 storage/lmgr/predicate.c:4337 +#: storage/lmgr/predicate.c:4656 storage/lmgr/predicate.c:4668 +#: storage/lmgr/predicate.c:4715 storage/lmgr/predicate.c:4751 #, c-format msgid "could not serialize access due to read/write dependencies among transactions" msgstr "kunde inte serialisera åtkomst på grund av läs/skriv-beroenden bland transaktionerna" -#: storage/lmgr/predicate.c:3937 storage/lmgr/predicate.c:3973 -#: storage/lmgr/predicate.c:4006 storage/lmgr/predicate.c:4014 -#: storage/lmgr/predicate.c:4053 storage/lmgr/predicate.c:4283 -#: storage/lmgr/predicate.c:4602 storage/lmgr/predicate.c:4614 -#: storage/lmgr/predicate.c:4661 storage/lmgr/predicate.c:4697 +#: storage/lmgr/predicate.c:3993 storage/lmgr/predicate.c:4029 +#: storage/lmgr/predicate.c:4062 storage/lmgr/predicate.c:4070 +#: storage/lmgr/predicate.c:4109 storage/lmgr/predicate.c:4339 +#: storage/lmgr/predicate.c:4658 storage/lmgr/predicate.c:4670 +#: storage/lmgr/predicate.c:4717 storage/lmgr/predicate.c:4753 #, c-format msgid "The transaction might succeed if retried." msgstr "Transaktionen kan lyckas om den körs igen." -#: storage/lmgr/proc.c:349 +#: storage/lmgr/proc.c:353 #, c-format -msgid "number of requested standby connections exceeds max_wal_senders (currently %d)" -msgstr "antalet efterfrågade standby-anslutningar överskrider max_wal_senders (nu %d)" +msgid "number of requested standby connections exceeds \"max_wal_senders\" (currently %d)" +msgstr "antalet efterfrågade standby-anslutningar överskrider \"max_wal_senders\" (nu %d)" -#: storage/lmgr/proc.c:1472 +#: storage/lmgr/proc.c:1546 #, c-format msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" msgstr "process %d undvek deadlock på %s för %s genom att kasta om köordningen efter %ld.%03d ms" -#: storage/lmgr/proc.c:1487 +#: storage/lmgr/proc.c:1561 #, c-format msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "process %d upptäckte deadlock medan den väntade på %s för %s efter %ld.%03d ms" -#: storage/lmgr/proc.c:1496 +#: storage/lmgr/proc.c:1570 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "process %d väntar fortfarande på %s för %s efter %ld.%03d ms" -#: storage/lmgr/proc.c:1503 +#: storage/lmgr/proc.c:1577 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "process %d fick %s på %s efter %ld.%03d ms" -#: storage/lmgr/proc.c:1520 +#: storage/lmgr/proc.c:1594 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "process %d misslyckades att ta %s på %s efter %ld.%03d ms" @@ -22594,67 +23414,202 @@ msgstr "trasiga postlängder: totalt %u, tillgänglig plats %u" msgid "corrupted line pointer: offset = %u, size = %u" msgstr "korrupt radpekare: offset = %u, storlek = %u" -#: storage/smgr/md.c:487 storage/smgr/md.c:549 +#: storage/smgr/md.c:485 storage/smgr/md.c:547 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "kan inte utöka fil \"%s\" utöver %u block" -#: storage/smgr/md.c:502 storage/smgr/md.c:613 +#: storage/smgr/md.c:500 storage/smgr/md.c:611 #, c-format msgid "could not extend file \"%s\": %m" msgstr "kunde inte utöka fil \"%s\": %m" -#: storage/smgr/md.c:508 +#: storage/smgr/md.c:506 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "kunde inte utöka fil \"%s\": skrev bara %d av %d byte vid block %u" -#: storage/smgr/md.c:591 +#: storage/smgr/md.c:589 #, c-format msgid "could not extend file \"%s\" with FileFallocate(): %m" msgstr "kunde inte utöka fil \"%s\" med FileFallocate(): %m" -#: storage/smgr/md.c:782 -#, c-format -msgid "could not read block %u in file \"%s\": %m" -msgstr "kunde inte läsa block %u i fil \"%s\": %m" - -#: storage/smgr/md.c:798 +#: storage/smgr/md.c:869 #, c-format -msgid "could not read block %u in file \"%s\": read only %d of %d bytes" -msgstr "kunde inte läsa block %u i fil \"%s\": läste bara %d av %d byte" +msgid "could not read blocks %u..%u in file \"%s\": %m" +msgstr "kunde inte läsa block %u..%u i fil \"%s\": %m" -#: storage/smgr/md.c:856 +#: storage/smgr/md.c:895 #, c-format -msgid "could not write block %u in file \"%s\": %m" -msgstr "kunde inte skriva block %u i fil \"%s\": %m" +msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" +msgstr "kunde inte läsa block %u..%u i fil \"%s\": läste bara %zu av %zu byte" -#: storage/smgr/md.c:861 +#: storage/smgr/md.c:995 #, c-format -msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" -msgstr "kunde inte skriva block %u i fil \"%s\": skrev bara %d av %d byte" +msgid "could not write blocks %u..%u in file \"%s\": %m" +msgstr "kunde inte skriva block %u..%u i fil \"%s\": %m" -#: storage/smgr/md.c:1012 +#: storage/smgr/md.c:1165 #, c-format msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" msgstr "kunde inte trunkera fil \"%s\" till %u block: den är bara %u block nu" -#: storage/smgr/md.c:1067 +#: storage/smgr/md.c:1220 #, c-format msgid "could not truncate file \"%s\" to %u blocks: %m" msgstr "kunde inte trunkera fil \"%s\" till %u block: %m" -#: storage/smgr/md.c:1494 +#: storage/smgr/md.c:1700 #, c-format msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" msgstr "kunde inte öppna fil \"%s\" (målblock %u): föregående segment är bara %u block" -#: storage/smgr/md.c:1508 +#: storage/smgr/md.c:1714 #, c-format msgid "could not open file \"%s\" (target block %u): %m" msgstr "kunde inte öppna fil \"%s\" (målblock %u): %m" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2132 +#: tcop/backend_startup.c:85 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "SSL-konfigurering kunde inte laddas i barnprocess" + +#: tcop/backend_startup.c:208 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "ansluting mottagen: värd=%s port=%s" + +#: tcop/backend_startup.c:213 +#, c-format +msgid "connection received: host=%s" +msgstr "ansluting mottagen: värd=%s" + +#: tcop/backend_startup.c:277 +#, c-format +msgid "the database system is starting up" +msgstr "databassystemet startar upp" + +#: tcop/backend_startup.c:283 +#, c-format +msgid "the database system is not yet accepting connections" +msgstr "databassystemet tar ännu inte emot anslutningar" + +#: tcop/backend_startup.c:284 +#, c-format +msgid "Consistent recovery state has not been yet reached." +msgstr "Konsistent återställningstillstånd har ännu inte uppnåtts." + +#: tcop/backend_startup.c:288 +#, c-format +msgid "the database system is not accepting connections" +msgstr "databassystemet tar inte emot anslutningar" + +#: tcop/backend_startup.c:289 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "Hot standby-läge är avstängt." + +#: tcop/backend_startup.c:294 +#, c-format +msgid "the database system is shutting down" +msgstr "databassystemet stänger ner" + +#: tcop/backend_startup.c:299 +#, c-format +msgid "the database system is in recovery mode" +msgstr "databassystemet är återställningsläge" + +#: tcop/backend_startup.c:414 +#, c-format +msgid "received direct SSL connection request without ALPN protocol negotiation extension" +msgstr "förfrågan för direkt SSL-anslutning har mottagits utan utökning för ALPN-protokollförhandling" + +#: tcop/backend_startup.c:420 +#, c-format +msgid "direct SSL connection accepted" +msgstr "direkt SSL-anslutning accepterad" + +#: tcop/backend_startup.c:430 +#, c-format +msgid "direct SSL connection rejected" +msgstr "direkt SSL-anslutning avvisad" + +#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#, c-format +msgid "incomplete startup packet" +msgstr "ofullständigt startuppaket" + +#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#, c-format +msgid "invalid length of startup packet" +msgstr "ogiltig längd på startuppaket" + +#: tcop/backend_startup.c:573 +#, c-format +msgid "SSLRequest accepted" +msgstr "SSLRequest accepterad" + +#: tcop/backend_startup.c:576 +#, c-format +msgid "SSLRequest rejected" +msgstr "SSLRequest nekad" + +#: tcop/backend_startup.c:585 +#, c-format +msgid "failed to send SSL negotiation response: %m" +msgstr "misslyckades att skicka SSL-förhandlingssvar: %m" + +#: tcop/backend_startup.c:603 +#, c-format +msgid "received unencrypted data after SSL request" +msgstr "tog emot okrypterad data efter SSL-förfrågan" + +#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#, c-format +msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." +msgstr "Detta kan antingen vara en bug i klientens mjukvara eller bevis på ett försök att utföra en attack av typen man-in-the-middle." + +#: tcop/backend_startup.c:627 +#, c-format +msgid "GSSENCRequest accepted" +msgstr "GSSENCRequest accepterad" + +#: tcop/backend_startup.c:630 +#, c-format +msgid "GSSENCRequest rejected" +msgstr "GSSENCRequest nekad" + +#: tcop/backend_startup.c:639 +#, c-format +msgid "failed to send GSSAPI negotiation response: %m" +msgstr "misslyckades att skicka GSSAPI-förhandlingssvar: %m" + +#: tcop/backend_startup.c:657 +#, c-format +msgid "received unencrypted data after GSSAPI encryption request" +msgstr "tog emot okrypterad data efter GSSAPI-krypteringsförfrågan" + +#: tcop/backend_startup.c:681 +#, c-format +msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" +msgstr "inget stöd för framändans protokoll %u.%u: servern stöder %u.0 till %u.%u" + +#: tcop/backend_startup.c:744 +#, c-format +msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." +msgstr "Giltiga värden är: \"false\", 0, \"true\", 1, \"database\"." + +#: tcop/backend_startup.c:785 +#, c-format +msgid "invalid startup packet layout: expected terminator as last byte" +msgstr "ogiltig startpaketlayout: förväntade en terminator som sista byte" + +#: tcop/backend_startup.c:802 +#, c-format +msgid "no PostgreSQL user name specified in startup packet" +msgstr "inget PostgreSQL-användarnamn angivet i startuppaketet" + +#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "funktionen med OID %u existerar inte" @@ -22669,8 +23624,8 @@ msgstr "kan inte anropa funktionen \"%s\" via fastpath-interface" msgid "fastpath function call: \"%s\" (OID %u)" msgstr "fastpath funktionsanrop: \"%s\" (OID %u)" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 -#: tcop/postgres.c:2059 tcop/postgres.c:2309 +#: tcop/fastpath.c:313 tcop/postgres.c:1369 tcop/postgres.c:1605 +#: tcop/postgres.c:2071 tcop/postgres.c:2333 #, c-format msgid "duration: %s ms" msgstr "varaktighet %s ms" @@ -22700,315 +23655,320 @@ msgstr "ogiltig argumentstorlek %d i funktionsaropsmeddelande" msgid "incorrect binary data format in function argument %d" msgstr "inkorrekt binärt dataformat i funktionsargument %d" -#: tcop/postgres.c:463 tcop/postgres.c:4882 +#: tcop/postgres.c:467 tcop/postgres.c:5012 #, c-format msgid "invalid frontend message type %d" msgstr "ogiltig frontend-meddelandetyp %d" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1076 #, c-format msgid "statement: %s" msgstr "sats: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1374 #, c-format msgid "duration: %s ms statement: %s" msgstr "varaktighet: %s ms sats: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1480 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "kan inte stoppa in multipla kommandon i en förberedd sats" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1610 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "varaktighet: %s ms parse %s: %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2629 +#: tcop/postgres.c:1677 tcop/postgres.c:2653 #, c-format msgid "unnamed prepared statement does not exist" msgstr "förberedd sats utan namn existerar inte" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1729 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "bind-meddelande har %d parameterformat men %d parametrar" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1735 #, c-format msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d" msgstr "bind-meddelande ger %d parametrar men förberedd sats \"%s\" kräver %d" -#: tcop/postgres.c:1937 +#: tcop/postgres.c:1949 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "inkorrekt binärdataformat i bind-parameter %d" -#: tcop/postgres.c:2064 +#: tcop/postgres.c:2076 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "varaktighet: %s ms bind %s%s%s: %s" -#: tcop/postgres.c:2118 tcop/postgres.c:2712 +#: tcop/postgres.c:2131 tcop/postgres.c:2735 #, c-format msgid "portal \"%s\" does not exist" msgstr "portal \"%s\" existerar inte" -#: tcop/postgres.c:2189 +#: tcop/postgres.c:2213 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2191 tcop/postgres.c:2317 +#: tcop/postgres.c:2215 tcop/postgres.c:2341 msgid "execute fetch from" msgstr "kör hämtning från" -#: tcop/postgres.c:2192 tcop/postgres.c:2318 +#: tcop/postgres.c:2216 tcop/postgres.c:2342 msgid "execute" msgstr "kör" -#: tcop/postgres.c:2314 +#: tcop/postgres.c:2338 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "varaktighet: %s ms %s %s%s%s: %s" -#: tcop/postgres.c:2462 +#: tcop/postgres.c:2486 #, c-format msgid "prepare: %s" msgstr "prepare: %s" -#: tcop/postgres.c:2487 +#: tcop/postgres.c:2511 #, c-format -msgid "parameters: %s" -msgstr "parametrar: %s" +msgid "Parameters: %s" +msgstr "Parametrar: %s" -#: tcop/postgres.c:2502 +#: tcop/postgres.c:2526 #, c-format -msgid "abort reason: recovery conflict" -msgstr "abortskäl: återställningskonflikt" +msgid "Abort reason: recovery conflict" +msgstr "Abortskäl: återställningskonflikt" -#: tcop/postgres.c:2518 +#: tcop/postgres.c:2542 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "Användaren höll delad bufferfastlåsning för länge." -#: tcop/postgres.c:2521 +#: tcop/postgres.c:2545 #, c-format msgid "User was holding a relation lock for too long." msgstr "Användare höll ett relationslås för länge." -#: tcop/postgres.c:2524 +#: tcop/postgres.c:2548 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "Användaren använde eller har använt ett tablespace som tagits bort." -#: tcop/postgres.c:2527 +#: tcop/postgres.c:2551 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "Användarfrågan kan ha behövt se radversioner som har tagits bort." -#: tcop/postgres.c:2530 +#: tcop/postgres.c:2554 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "Användaren använde en logisk replikeringsslot som måste invalideras." -#: tcop/postgres.c:2536 +#: tcop/postgres.c:2560 #, c-format msgid "User was connected to a database that must be dropped." msgstr "Användare var ansluten till databas som måste slängas." -#: tcop/postgres.c:2575 +#: tcop/postgres.c:2599 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "portal \"%s\" parameter $%d = %s" -#: tcop/postgres.c:2578 +#: tcop/postgres.c:2602 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "portal \"%s\" parameter $%d" -#: tcop/postgres.c:2584 +#: tcop/postgres.c:2608 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "ej namngiven portalparameter $%d = %s" -#: tcop/postgres.c:2587 +#: tcop/postgres.c:2611 #, c-format msgid "unnamed portal parameter $%d" msgstr "ej namngiven portalparameter $%d" -#: tcop/postgres.c:2932 +#: tcop/postgres.c:2955 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "stänger anslutning på grund av oväntad SIGQUIT-signal" -#: tcop/postgres.c:2938 +#: tcop/postgres.c:2961 #, c-format msgid "terminating connection because of crash of another server process" msgstr "avbryter anslutning på grund av en krash i en annan serverprocess" -#: tcop/postgres.c:2939 +#: tcop/postgres.c:2962 #, c-format msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory." msgstr "Postmastern har sagt åt denna serverprocess att rulla tillbaka den aktuella transaktionen och avsluta då en annan process har avslutats onormalt och har eventuellt trasat sönder delat minne." -#: tcop/postgres.c:2943 tcop/postgres.c:3310 +#: tcop/postgres.c:2966 tcop/postgres.c:3219 #, c-format msgid "In a moment you should be able to reconnect to the database and repeat your command." msgstr "Du kan strax återansluta till databasen och upprepa kommandot." -#: tcop/postgres.c:2950 +#: tcop/postgres.c:2973 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "stänger anslutning på grund av kommando för omedelbar nedstängning" -#: tcop/postgres.c:3036 +#: tcop/postgres.c:3051 #, c-format msgid "floating-point exception" msgstr "flyttalsavbrott" -#: tcop/postgres.c:3037 +#: tcop/postgres.c:3052 #, c-format msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero." msgstr "En ogiltig flyttalsoperation har signalerats. Detta beror troligen på ett resultat som är utanför giltigt intervall eller en ogiltig operation så som division med noll." -#: tcop/postgres.c:3214 +#: tcop/postgres.c:3217 +#, c-format +msgid "terminating connection due to conflict with recovery" +msgstr "avslutar anslutning på grund av konflikt med återställning" + +#: tcop/postgres.c:3289 #, c-format msgid "canceling authentication due to timeout" msgstr "avbryter autentisering på grund av timeout" -#: tcop/postgres.c:3218 +#: tcop/postgres.c:3293 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "avslutar autovacuum-process på grund av ett administratörskommando" -#: tcop/postgres.c:3222 +#: tcop/postgres.c:3297 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "avslutar logisk replikeringsarbetare på grund av ett administratörskommando" -#: tcop/postgres.c:3239 tcop/postgres.c:3249 tcop/postgres.c:3308 -#, c-format -msgid "terminating connection due to conflict with recovery" -msgstr "avslutar anslutning på grund av konflikt med återställning" - -#: tcop/postgres.c:3260 +#: tcop/postgres.c:3317 #, c-format msgid "terminating connection due to administrator command" msgstr "avslutar anslutning på grund av ett administratörskommando" -#: tcop/postgres.c:3291 +#: tcop/postgres.c:3348 #, c-format msgid "connection to client lost" msgstr "anslutning till klient har brutits" -#: tcop/postgres.c:3361 +#: tcop/postgres.c:3400 #, c-format msgid "canceling statement due to lock timeout" msgstr "avbryter sats på grund av lås-timeout" -#: tcop/postgres.c:3368 +#: tcop/postgres.c:3407 #, c-format msgid "canceling statement due to statement timeout" msgstr "avbryter sats på grund av sats-timeout" -#: tcop/postgres.c:3375 +#: tcop/postgres.c:3414 #, c-format msgid "canceling autovacuum task" msgstr "avbryter autovacuum-uppgift" -#: tcop/postgres.c:3398 +#: tcop/postgres.c:3427 #, c-format msgid "canceling statement due to user request" msgstr "avbryter sats på användares begäran" -#: tcop/postgres.c:3412 +#: tcop/postgres.c:3448 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "terminerar anslutning på grund av idle-in-transaction-timeout" -#: tcop/postgres.c:3423 +#: tcop/postgres.c:3461 +#, c-format +msgid "terminating connection due to transaction timeout" +msgstr "terminerar anslutning på grund av transaktionstimeout" + +#: tcop/postgres.c:3474 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "stänger anslutning på grund av idle-session-timeout" -#: tcop/postgres.c:3514 +#: tcop/postgres.c:3564 #, c-format msgid "stack depth limit exceeded" msgstr "maximalt stackdjup överskridet" -#: tcop/postgres.c:3515 +#: tcop/postgres.c:3565 #, c-format msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." msgstr "Öka konfigurationsparametern \"max_stack_depth\" (nu %dkB) efter att ha undersökt att plattformens gräns för stackdjup är tillräcklig." -#: tcop/postgres.c:3562 +#: tcop/postgres.c:3612 #, c-format msgid "\"max_stack_depth\" must not exceed %ldkB." msgstr "\"max_stack_depth\" får ej överskrida %ldkB." -#: tcop/postgres.c:3564 +#: tcop/postgres.c:3614 #, c-format msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." msgstr "Öka plattformens stackdjupbegränsning via \"ulimit -s\" eller motsvarande." -#: tcop/postgres.c:3587 +#: tcop/postgres.c:3637 #, c-format -msgid "client_connection_check_interval must be set to 0 on this platform." -msgstr "client_connection_check_interval måste sättas till 0 på denna plattform." +msgid "\"client_connection_check_interval\" must be set to 0 on this platform." +msgstr "\"client_connection_check_interval\" måste sättas till 0 på denna plattform." -#: tcop/postgres.c:3608 +#: tcop/postgres.c:3658 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "Kan inte slå på parameter när \"log_statement_stats\" är satt." -#: tcop/postgres.c:3623 +#: tcop/postgres.c:3673 #, c-format msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true." msgstr "Kan inte slå på \"log_statement_stats\" när \"log_parser_stats\", \"log_planner_stats\" eller \"log_executor_stats\" är satta." -#: tcop/postgres.c:3971 +#: tcop/postgres.c:4098 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "ogiltigt kommandoradsargument för serverprocess: %s" -#: tcop/postgres.c:3972 tcop/postgres.c:3978 +#: tcop/postgres.c:4099 tcop/postgres.c:4105 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: tcop/postgres.c:3976 +#: tcop/postgres.c:4103 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: ogiltigt kommandoradsargument: %s" -#: tcop/postgres.c:4029 +#: tcop/postgres.c:4156 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: ingen databas eller användarnamn angivet" -#: tcop/postgres.c:4779 +#: tcop/postgres.c:4909 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "ogiltig subtyp %d för CLOSE-meddelande" -#: tcop/postgres.c:4816 +#: tcop/postgres.c:4946 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "ogiltig subtyp %d för DESCRIBE-meddelande" -#: tcop/postgres.c:4903 +#: tcop/postgres.c:5033 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "fastpath-funktionsanrop stöds inte i en replikeringsanslutning" -#: tcop/postgres.c:4907 +#: tcop/postgres.c:5037 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "utökat frågeprotokoll stöds inte i en replikeringsanslutning" -#: tcop/postgres.c:5087 +#: tcop/postgres.c:5217 #, c-format msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s" msgstr "nedkoppling: sessionstid: %d:%02d:%02d.%03d användare=%s databas=%s värd=%s%s%s" @@ -23018,53 +23978,53 @@ msgstr "nedkoppling: sessionstid: %d:%02d:%02d.%03d användare=%s databas=%s vä msgid "bind message has %d result formats but query has %d columns" msgstr "bind-meddelande har %d resultatformat men frågan har %d kolumner" -#: tcop/pquery.c:944 tcop/pquery.c:1701 +#: tcop/pquery.c:942 tcop/pquery.c:1696 #, c-format msgid "cursor can only scan forward" msgstr "markör kan bara hoppa framåt" -#: tcop/pquery.c:945 tcop/pquery.c:1702 +#: tcop/pquery.c:943 tcop/pquery.c:1697 #, c-format msgid "Declare it with SCROLL option to enable backward scan." msgstr "Deklarera den med flaggan SCROLL för att kunna traversera bakåt." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:417 +#: tcop/utility.c:410 #, c-format msgid "cannot execute %s in a read-only transaction" msgstr "kan inte köra %s i read-only-transaktion" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:435 +#: tcop/utility.c:428 #, c-format msgid "cannot execute %s during a parallel operation" msgstr "kan inte köra %s under parallell operation" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:454 +#: tcop/utility.c:447 #, c-format msgid "cannot execute %s during recovery" msgstr "kan inte köra %s under återställning" #. translator: %s is name of a SQL command, eg PREPARE -#: tcop/utility.c:472 +#: tcop/utility.c:465 #, c-format msgid "cannot execute %s within security-restricted operation" msgstr "kan inte köra %s inom säkerhetsbegränsad operation" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:828 +#: tcop/utility.c:821 #, c-format msgid "cannot execute %s within a background process" msgstr "kan inte köra %s i en bakgrundsprocess" #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:954 +#: tcop/utility.c:947 #, c-format msgid "permission denied to execute %s command" msgstr "rättighet saknas för köra kommandot %s" -#: tcop/utility.c:956 +#: tcop/utility.c:949 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "Bara roller med rättigheter från rollen \"%s\" får köra detta kommando." @@ -23127,7 +24087,7 @@ msgstr "kunde inte öppna synonymordboksfil \"%s\": %m" #: tsearch/dict_thesaurus.c:212 #, c-format msgid "unexpected delimiter" -msgstr "oväntad avdelare" +msgstr "oväntad separator" #: tsearch/dict_thesaurus.c:262 tsearch/dict_thesaurus.c:278 #, c-format @@ -23246,17 +24206,17 @@ msgstr "antalet alias överskriver angivet antal %d" msgid "affix file contains both old-style and new-style commands" msgstr "affix-fil innehåller kommandon på gammalt och nytt format" -#: tsearch/to_tsany.c:195 utils/adt/tsvector.c:278 utils/adt/tsvector_op.c:1128 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "strängen är för lång för tsvector (%d byte, max %d byte)" -#: tsearch/ts_locale.c:238 +#: tsearch/ts_locale.c:236 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "rad %d i konfigureringsfil \"%s\": \"%s\"" -#: tsearch/ts_locale.c:317 +#: tsearch/ts_locale.c:315 #, c-format msgid "conversion from wchar_t to server encoding failed: %m" msgstr "konvertering från wchar_t till serverkodning misslyckades: %m" @@ -23283,72 +24243,67 @@ msgstr "ogiltigt filnamn \"%s\" till textsökkonfiguration" msgid "could not open stop-word file \"%s\": %m" msgstr "kunde inte öppna stoppordsfil \"%s\": %m" -#: tsearch/wparser.c:308 tsearch/wparser.c:396 tsearch/wparser.c:473 +#: tsearch/wparser.c:306 tsearch/wparser.c:394 tsearch/wparser.c:471 #, c-format msgid "text search parser does not support headline creation" msgstr "textsökparsern stöder inte skapande av rubriker" -#: tsearch/wparser_def.c:2663 +#: tsearch/wparser_def.c:2664 #, c-format msgid "unrecognized headline parameter: \"%s\"" msgstr "okänd rubrikparameter: \"%s\"" -#: tsearch/wparser_def.c:2673 -#, c-format -msgid "MinWords should be less than MaxWords" -msgstr "MinWords skall vara mindre än MaxWords" - -#: tsearch/wparser_def.c:2677 +#: tsearch/wparser_def.c:2674 #, c-format -msgid "MinWords should be positive" -msgstr "MinWords skall vara positiv" +msgid "%s must be less than %s" +msgstr "%s måste vara mindre än %s" -#: tsearch/wparser_def.c:2681 +#: tsearch/wparser_def.c:2678 #, c-format -msgid "ShortWord should be >= 0" -msgstr "ShortWord skall vara >= 0" +msgid "%s must be positive" +msgstr "%s måste vara positiv" -#: tsearch/wparser_def.c:2685 +#: tsearch/wparser_def.c:2682 tsearch/wparser_def.c:2686 #, c-format -msgid "MaxFragments should be >= 0" -msgstr "MaxFragments skall vara >= 0" +msgid "%s must be >= 0" +msgstr "%s måste vara >= 0" -#: utils/activity/pgstat.c:438 +#: utils/activity/pgstat.c:435 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "kunde inte radera permanent statistikfil \"%s\": %m" -#: utils/activity/pgstat.c:1252 +#: utils/activity/pgstat.c:1255 #, c-format msgid "invalid statistics kind: \"%s\"" msgstr "ogiltig statistiktyp \"%s\"" -#: utils/activity/pgstat.c:1332 +#: utils/activity/pgstat.c:1335 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "kunde inte öppna temporär statistikfil \"%s\": %m" -#: utils/activity/pgstat.c:1444 +#: utils/activity/pgstat.c:1455 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "kunde inte skriva temporär statistikfil \"%s\": %m" -#: utils/activity/pgstat.c:1453 +#: utils/activity/pgstat.c:1464 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "kunde inte stänga temporär statistikfil \"%s\": %m" -#: utils/activity/pgstat.c:1461 +#: utils/activity/pgstat.c:1472 #, c-format msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" msgstr "kunde inte döpa om temporär statistikfil \"%s\" till \"%s\": %m" -#: utils/activity/pgstat.c:1510 +#: utils/activity/pgstat.c:1521 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "kunde inte öppna statistikfil \"%s\": %m" -#: utils/activity/pgstat.c:1672 +#: utils/activity/pgstat.c:1683 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "korrupt statistikfil \"%s\"" @@ -23358,115 +24313,125 @@ msgstr "korrupt statistikfil \"%s\"" msgid "function call to dropped function" msgstr "funktionsanrop till borttagen funktion" -#: utils/activity/pgstat_xact.c:363 +#: utils/activity/pgstat_xact.c:362 #, c-format msgid "resetting existing statistics for kind %s, db=%u, oid=%u" msgstr "återställer existerande statistik för typ %s, db=%u, oid=%u" -#: utils/adt/acl.c:177 utils/adt/name.c:93 +#: utils/activity/wait_event.c:207 utils/activity/wait_event.c:232 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "wait event \"%s\" finns redan i type \"%s\"" + +#: utils/activity/wait_event.c:246 +#, c-format +msgid "too many custom wait events" +msgstr "för många egendefinierade wait event" + +#: utils/adt/acl.c:183 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "identifieraren för lång" -#: utils/adt/acl.c:178 utils/adt/name.c:94 +#: utils/adt/acl.c:184 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "Identifierare måste vara mindre än %d tecken." -#: utils/adt/acl.c:266 +#: utils/adt/acl.c:272 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "okänt nyckelord: \"%s\"" -#: utils/adt/acl.c:267 +#: utils/adt/acl.c:273 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "ACL-nyckelord måste vara \"group\" eller \"user\"." -#: utils/adt/acl.c:275 +#: utils/adt/acl.c:281 #, c-format msgid "missing name" msgstr "namn saknas" -#: utils/adt/acl.c:276 +#: utils/adt/acl.c:282 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "Ett namn måste följa efter nyckelorden \"group\" resp. \"user\"." -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:288 #, c-format msgid "missing \"=\" sign" msgstr "saknar \"=\"-tecken" -#: utils/adt/acl.c:341 +#: utils/adt/acl.c:350 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "ogiltigt lägestecken: måste vara en av \"%s\"" -#: utils/adt/acl.c:371 +#: utils/adt/acl.c:380 #, c-format msgid "a name must follow the \"/\" sign" msgstr "ett namn måste följa på tecknet \"/\"" -#: utils/adt/acl.c:383 +#: utils/adt/acl.c:392 #, c-format msgid "defaulting grantor to user ID %u" msgstr "sätter fullmaktsgivaranvändar-ID till standardvärdet %u" -#: utils/adt/acl.c:569 +#: utils/adt/acl.c:578 #, c-format msgid "ACL array contains wrong data type" msgstr "ACL-array innehåller fel datatyp" -#: utils/adt/acl.c:573 +#: utils/adt/acl.c:582 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "ACL-array:er måste vara endimensionella" -#: utils/adt/acl.c:577 +#: utils/adt/acl.c:586 #, c-format msgid "ACL arrays must not contain null values" msgstr "ACL-array:er får inte innehålla null-värden" -#: utils/adt/acl.c:606 +#: utils/adt/acl.c:615 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "skräp vid slutet av ACL-angivelse" -#: utils/adt/acl.c:1248 +#: utils/adt/acl.c:1263 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "fullmaksgivarflaggor kan inte ges tillbaka till den som givit det till dig" -#: utils/adt/acl.c:1564 +#: utils/adt/acl.c:1579 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert stöds inte länge" -#: utils/adt/acl.c:1574 +#: utils/adt/acl.c:1589 #, c-format msgid "aclremove is no longer supported" msgstr "aclremove stöds inte längre" -#: utils/adt/acl.c:1693 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "okänd privilegietyp: \"%s\"" -#: utils/adt/acl.c:3476 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3550 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "funktionen \"%s\" finns inte" -#: utils/adt/acl.c:5023 +#: utils/adt/acl.c:5196 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "måste kunna utföra SET ROLE \"%s\"" #: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 -#: utils/adt/array_userfuncs.c:878 utils/adt/json.c:694 utils/adt/json.c:831 -#: utils/adt/json.c:869 utils/adt/jsonb.c:1139 utils/adt/jsonb.c:1211 -#: utils/adt/jsonb.c:1629 utils/adt/jsonb.c:1817 utils/adt/jsonb.c:1827 +#: utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 +#: utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 +#: utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "kan inte bestämma indatatyp" @@ -23477,17 +24442,17 @@ msgid "input data type is not an array" msgstr "indatatyp är inte en array" #: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 -#: utils/adt/float.c:1228 utils/adt/float.c:1302 utils/adt/float.c:4117 -#: utils/adt/float.c:4155 utils/adt/int.c:778 utils/adt/int.c:800 +#: utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 +#: utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 #: utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 #: utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 #: utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 #: utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 #: utils/adt/int.c:1263 utils/adt/int.c:1331 utils/adt/int.c:1337 -#: utils/adt/int8.c:1257 utils/adt/numeric.c:1901 utils/adt/numeric.c:4388 -#: utils/adt/rangetypes.c:1481 utils/adt/rangetypes.c:1494 -#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1132 -#: utils/adt/varlena.c:3134 +#: utils/adt/int8.c:1256 utils/adt/numeric.c:1917 utils/adt/numeric.c:4454 +#: utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 +#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 +#: utils/adt/varlena.c:3137 #, c-format msgid "integer out of range" msgstr "heltal utanför giltigt intervall" @@ -23524,267 +24489,278 @@ msgstr "Array:er med olika elementdimensioner är inte kompatibla för sammaslag msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "Array:er med olika dimensioner fungerar inte vid konkatenering." -#: utils/adt/array_userfuncs.c:987 utils/adt/array_userfuncs.c:995 -#: utils/adt/arrayfuncs.c:5590 utils/adt/arrayfuncs.c:5596 +#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 +#: utils/adt/arrayfuncs.c:5616 utils/adt/arrayfuncs.c:5622 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "kan inte ackumulera arrayer med olika dimensioner" -#: utils/adt/array_userfuncs.c:1286 utils/adt/array_userfuncs.c:1440 +#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "sökning efter element i en multidimensionell array stöds inte" -#: utils/adt/array_userfuncs.c:1315 +#: utils/adt/array_userfuncs.c:1301 #, c-format msgid "initial position must not be null" msgstr "initiala positionen får ej vara null" -#: utils/adt/array_userfuncs.c:1688 +#: utils/adt/array_userfuncs.c:1674 #, c-format msgid "sample size must be between 0 and %d" msgstr "samplingsstorleken måste vara mellan 0 och %d" -#: utils/adt/arrayfuncs.c:273 utils/adt/arrayfuncs.c:287 -#: utils/adt/arrayfuncs.c:298 utils/adt/arrayfuncs.c:320 -#: utils/adt/arrayfuncs.c:337 utils/adt/arrayfuncs.c:351 -#: utils/adt/arrayfuncs.c:359 utils/adt/arrayfuncs.c:366 -#: utils/adt/arrayfuncs.c:506 utils/adt/arrayfuncs.c:521 -#: utils/adt/arrayfuncs.c:532 utils/adt/arrayfuncs.c:547 -#: utils/adt/arrayfuncs.c:568 utils/adt/arrayfuncs.c:598 -#: utils/adt/arrayfuncs.c:605 utils/adt/arrayfuncs.c:613 -#: utils/adt/arrayfuncs.c:647 utils/adt/arrayfuncs.c:670 -#: utils/adt/arrayfuncs.c:690 utils/adt/arrayfuncs.c:807 -#: utils/adt/arrayfuncs.c:816 utils/adt/arrayfuncs.c:846 -#: utils/adt/arrayfuncs.c:861 utils/adt/arrayfuncs.c:914 +#: utils/adt/arrayfuncs.c:264 utils/adt/arrayfuncs.c:273 +#: utils/adt/arrayfuncs.c:284 utils/adt/arrayfuncs.c:307 +#: utils/adt/arrayfuncs.c:440 utils/adt/arrayfuncs.c:454 +#: utils/adt/arrayfuncs.c:466 utils/adt/arrayfuncs.c:636 +#: utils/adt/arrayfuncs.c:668 utils/adt/arrayfuncs.c:703 +#: utils/adt/arrayfuncs.c:718 utils/adt/arrayfuncs.c:777 +#: utils/adt/arrayfuncs.c:782 utils/adt/arrayfuncs.c:870 +#: utils/adt/arrayfuncs.c:897 utils/adt/arrayfuncs.c:904 +#: utils/adt/arrayfuncs.c:941 #, c-format msgid "malformed array literal: \"%s\"" msgstr "felaktig array-literal: \"%s\"" -#: utils/adt/arrayfuncs.c:274 -#, c-format -msgid "\"[\" must introduce explicitly-specified array dimensions." -msgstr "\"[\" måste införa explicit angivna array-dimensioner." - -#: utils/adt/arrayfuncs.c:288 +#: utils/adt/arrayfuncs.c:265 #, c-format -msgid "Missing array dimension value." -msgstr "Saknar värde i array-dimension." +msgid "Array value must start with \"{\" or dimension information." +msgstr "Array-värde måste starta med \"{\" eller dimensionsinformation" -#: utils/adt/arrayfuncs.c:299 utils/adt/arrayfuncs.c:338 +#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:467 #, c-format msgid "Missing \"%s\" after array dimensions." msgstr "Saknar \"%s\" efter array-dimensioner." -#: utils/adt/arrayfuncs.c:308 utils/adt/arrayfuncs.c:2933 -#: utils/adt/arrayfuncs.c:2965 utils/adt/arrayfuncs.c:2980 +#: utils/adt/arrayfuncs.c:285 #, c-format -msgid "upper bound cannot be less than lower bound" -msgstr "övre gränsen kan inte vara lägre än undre gränsen" +msgid "Array contents must start with \"{\"." +msgstr "Array-innehåll måste starta med \"{\"." -#: utils/adt/arrayfuncs.c:321 +#: utils/adt/arrayfuncs.c:308 utils/adt/multirangetypes.c:292 #, c-format -msgid "Array value must start with \"{\" or dimension information." -msgstr "Array-värde måste starta med \"{\" eller dimensionsinformation" +msgid "Junk after closing right brace." +msgstr "Skräp efter avslutande höger parentes." -#: utils/adt/arrayfuncs.c:352 +#: utils/adt/arrayfuncs.c:431 utils/adt/arrayfuncs.c:643 #, c-format -msgid "Array contents must start with \"{\"." -msgstr "Array-innehåll måste starta med \"{\"." +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "antal array-dimensioner överskriver maximalt tillåtna (%d)" -#: utils/adt/arrayfuncs.c:360 utils/adt/arrayfuncs.c:367 +#: utils/adt/arrayfuncs.c:441 #, c-format -msgid "Specified array dimensions do not match array contents." -msgstr "Angivna array-dimensioner matchar inte array-innehållet." +msgid "\"[\" must introduce explicitly-specified array dimensions." +msgstr "\"[\" måste införa explicit angivna array-dimensioner." -#: utils/adt/arrayfuncs.c:507 utils/adt/arrayfuncs.c:533 -#: utils/adt/multirangetypes.c:166 utils/adt/rangetypes.c:2405 -#: utils/adt/rangetypes.c:2413 utils/adt/rowtypes.c:219 -#: utils/adt/rowtypes.c:230 +#: utils/adt/arrayfuncs.c:455 #, c-format -msgid "Unexpected end of input." -msgstr "oväntat slut på indata." +msgid "Missing array dimension value." +msgstr "Saknar värde i array-dimension." + +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 +#: utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 +#, c-format +msgid "upper bound cannot be less than lower bound" +msgstr "övre gränsen kan inte vara lägre än undre gränsen" + +#: utils/adt/arrayfuncs.c:487 +#, c-format +msgid "array upper bound is too large: %d" +msgstr "övre gräns för array är för stor: %d" + +#: utils/adt/arrayfuncs.c:538 +#, c-format +msgid "array bound is out of integer range" +msgstr "array-gräns är utanför giltigt interval för integer" -#: utils/adt/arrayfuncs.c:522 utils/adt/arrayfuncs.c:569 -#: utils/adt/arrayfuncs.c:599 utils/adt/arrayfuncs.c:648 +#: utils/adt/arrayfuncs.c:637 utils/adt/arrayfuncs.c:669 +#: utils/adt/arrayfuncs.c:704 utils/adt/arrayfuncs.c:898 #, c-format msgid "Unexpected \"%c\" character." msgstr "oväntat tecken \"%c\"." -#: utils/adt/arrayfuncs.c:548 utils/adt/arrayfuncs.c:671 +#: utils/adt/arrayfuncs.c:719 #, c-format msgid "Unexpected array element." msgstr "Oväntat array-element." -#: utils/adt/arrayfuncs.c:606 +#: utils/adt/arrayfuncs.c:778 #, c-format -msgid "Unmatched \"%c\" character." -msgstr "Icke matchat tecken \"%c\"." +msgid "Specified array dimensions do not match array contents." +msgstr "Angivna array-dimensioner matchar inte array-innehållet." -#: utils/adt/arrayfuncs.c:614 utils/adt/jsonfuncs.c:2553 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2598 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "Flerdimensionella array:er måste ha underarray:er med matchande dimensioner." -#: utils/adt/arrayfuncs.c:691 utils/adt/multirangetypes.c:293 +#: utils/adt/arrayfuncs.c:871 utils/adt/arrayfuncs.c:905 #, c-format -msgid "Junk after closing right brace." -msgstr "Skräp efter avslutande höger parentes." +msgid "Incorrectly quoted array element." +msgstr "Felaktigt quote:at array-element." + +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 +#: utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 +#: utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#, c-format +msgid "Unexpected end of input." +msgstr "oväntat slut på indata." -#: utils/adt/arrayfuncs.c:1325 utils/adt/arrayfuncs.c:3479 -#: utils/adt/arrayfuncs.c:6080 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3499 +#: utils/adt/arrayfuncs.c:6106 #, c-format msgid "invalid number of dimensions: %d" msgstr "felaktigt antal dimensioner: %d" -#: utils/adt/arrayfuncs.c:1336 +#: utils/adt/arrayfuncs.c:1312 #, c-format msgid "invalid array flags" msgstr "ogiltiga array-flaggor" -#: utils/adt/arrayfuncs.c:1358 +#: utils/adt/arrayfuncs.c:1334 #, c-format msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "binär data har array-elementtyp typ %u (%s) istället för förväntade %u (%s)" -#: utils/adt/arrayfuncs.c:1402 utils/adt/multirangetypes.c:451 -#: utils/adt/rangetypes.c:344 utils/cache/lsyscache.c:2916 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 +#: utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 #, c-format msgid "no binary input function available for type %s" msgstr "ingen binär indatafunktion finns för typen %s" -#: utils/adt/arrayfuncs.c:1542 +#: utils/adt/arrayfuncs.c:1509 #, c-format msgid "improper binary format in array element %d" msgstr "felaktigt binärt format i array-element %d" -#: utils/adt/arrayfuncs.c:1623 utils/adt/multirangetypes.c:456 -#: utils/adt/rangetypes.c:349 utils/cache/lsyscache.c:2949 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 +#: utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 #, c-format msgid "no binary output function available for type %s" msgstr "det saknas en binär output-funktion för typen %s" -#: utils/adt/arrayfuncs.c:2102 +#: utils/adt/arrayfuncs.c:2067 #, c-format msgid "slices of fixed-length arrays not implemented" msgstr "slice av fixlängd-array är inte implementerat" -#: utils/adt/arrayfuncs.c:2280 utils/adt/arrayfuncs.c:2302 -#: utils/adt/arrayfuncs.c:2351 utils/adt/arrayfuncs.c:2589 -#: utils/adt/arrayfuncs.c:2911 utils/adt/arrayfuncs.c:6066 -#: utils/adt/arrayfuncs.c:6092 utils/adt/arrayfuncs.c:6103 -#: utils/adt/json.c:1497 utils/adt/json.c:1569 utils/adt/jsonb.c:1416 -#: utils/adt/jsonb.c:1500 utils/adt/jsonfuncs.c:4434 utils/adt/jsonfuncs.c:4587 -#: utils/adt/jsonfuncs.c:4698 utils/adt/jsonfuncs.c:4746 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 +#: utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 +#: utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6092 +#: utils/adt/arrayfuncs.c:6118 utils/adt/arrayfuncs.c:6129 +#: utils/adt/json.c:1433 utils/adt/json.c:1505 utils/adt/jsonb.c:1317 +#: utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4710 utils/adt/jsonfuncs.c:4863 +#: utils/adt/jsonfuncs.c:4974 utils/adt/jsonfuncs.c:5022 #, c-format msgid "wrong number of array subscripts" msgstr "fel antal array-indexeringar" -#: utils/adt/arrayfuncs.c:2285 utils/adt/arrayfuncs.c:2393 -#: utils/adt/arrayfuncs.c:2656 utils/adt/arrayfuncs.c:2970 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 +#: utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "array-index utanför giltigt område" -#: utils/adt/arrayfuncs.c:2290 +#: utils/adt/arrayfuncs.c:2255 #, c-format msgid "cannot assign null value to an element of a fixed-length array" msgstr "kan inte tilldela null-värde till ett element i en array med fast längd" -#: utils/adt/arrayfuncs.c:2858 +#: utils/adt/arrayfuncs.c:2855 #, c-format msgid "updates on slices of fixed-length arrays not implemented" msgstr "uppdatering av slice på fixlängd-array är inte implementerat" -#: utils/adt/arrayfuncs.c:2889 +#: utils/adt/arrayfuncs.c:2886 #, c-format msgid "array slice subscript must provide both boundaries" msgstr "array-slice-index måste inkludera båda gränser" -#: utils/adt/arrayfuncs.c:2890 +#: utils/adt/arrayfuncs.c:2887 #, c-format msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified." msgstr "Vid tilldelning till en slice av en tom array så måste slice-gränserna anges" -#: utils/adt/arrayfuncs.c:2901 utils/adt/arrayfuncs.c:2997 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "käll-array för liten" -#: utils/adt/arrayfuncs.c:3637 +#: utils/adt/arrayfuncs.c:3657 #, c-format msgid "null array element not allowed in this context" msgstr "null-element i arrayer stöds inte i detta kontext" -#: utils/adt/arrayfuncs.c:3808 utils/adt/arrayfuncs.c:3979 -#: utils/adt/arrayfuncs.c:4370 +#: utils/adt/arrayfuncs.c:3828 utils/adt/arrayfuncs.c:3999 +#: utils/adt/arrayfuncs.c:4390 #, c-format msgid "cannot compare arrays of different element types" msgstr "kan inte jämföra arrayer med olika elementtyper" -#: utils/adt/arrayfuncs.c:4157 utils/adt/multirangetypes.c:2806 -#: utils/adt/multirangetypes.c:2878 utils/adt/rangetypes.c:1354 -#: utils/adt/rangetypes.c:1418 utils/adt/rowtypes.c:1885 +#: utils/adt/arrayfuncs.c:4177 utils/adt/multirangetypes.c:2805 +#: utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 +#: utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 #, c-format msgid "could not identify a hash function for type %s" msgstr "kunde inte hitta en hash-funktion för typ %s" -#: utils/adt/arrayfuncs.c:4285 utils/adt/rowtypes.c:2006 +#: utils/adt/arrayfuncs.c:4305 utils/adt/rowtypes.c:1996 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "kunde inte hitta en utökad hash-funktion för typ %s" -#: utils/adt/arrayfuncs.c:5480 +#: utils/adt/arrayfuncs.c:5506 #, c-format msgid "data type %s is not an array type" msgstr "datatypen %s är inte en arraytyp" -#: utils/adt/arrayfuncs.c:5535 +#: utils/adt/arrayfuncs.c:5561 #, c-format msgid "cannot accumulate null arrays" msgstr "kan inte ackumulera null-array:er" -#: utils/adt/arrayfuncs.c:5563 +#: utils/adt/arrayfuncs.c:5589 #, c-format msgid "cannot accumulate empty arrays" msgstr "kan inte ackumulera tomma array:er" -#: utils/adt/arrayfuncs.c:5964 utils/adt/arrayfuncs.c:6004 +#: utils/adt/arrayfuncs.c:5990 utils/adt/arrayfuncs.c:6030 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "dimensionsarray eller undre gränsarray kan inte vara null" -#: utils/adt/arrayfuncs.c:6067 utils/adt/arrayfuncs.c:6093 +#: utils/adt/arrayfuncs.c:6093 utils/adt/arrayfuncs.c:6119 #, c-format msgid "Dimension array must be one dimensional." msgstr "Dimensionsarray måste vara endimensionell." -#: utils/adt/arrayfuncs.c:6072 utils/adt/arrayfuncs.c:6098 +#: utils/adt/arrayfuncs.c:6098 utils/adt/arrayfuncs.c:6124 #, c-format msgid "dimension values cannot be null" msgstr "dimensionsvärden kan inte vara null" -#: utils/adt/arrayfuncs.c:6104 +#: utils/adt/arrayfuncs.c:6130 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "Undre arraygräns har annan storlek än dimensionsarray." -#: utils/adt/arrayfuncs.c:6382 +#: utils/adt/arrayfuncs.c:6411 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "borttagning av element från en multidimensionell array stöds inte" -#: utils/adt/arrayfuncs.c:6659 +#: utils/adt/arrayfuncs.c:6688 #, c-format msgid "thresholds must be one-dimensional array" msgstr "gränsvärden måste vara en endimensionell array" -#: utils/adt/arrayfuncs.c:6664 +#: utils/adt/arrayfuncs.c:6693 #, c-format msgid "thresholds array must not contain NULLs" msgstr "gränsvärdesarray får inte innehålla NULLL-värden" -#: utils/adt/arrayfuncs.c:6897 +#: utils/adt/arrayfuncs.c:6926 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "antal element att trimma måste vara mellan 0 och %d" @@ -23799,22 +24775,22 @@ msgstr "array-index måste ha typen integer" msgid "array subscript in assignment must not be null" msgstr "array-index i tilldelning kan inte vara null" -#: utils/adt/arrayutils.c:161 +#: utils/adt/arrayutils.c:140 #, c-format msgid "array lower bound is too large: %d" -msgstr "lägre gräns för array är för stor: %d" +msgstr "undre gräns för array är för stor: %d" -#: utils/adt/arrayutils.c:263 +#: utils/adt/arrayutils.c:242 #, c-format msgid "typmod array must be type cstring[]" msgstr "typmod-array måste ha typ cstring[]" -#: utils/adt/arrayutils.c:268 +#: utils/adt/arrayutils.c:247 #, c-format msgid "typmod array must be one-dimensional" msgstr "typmod-array måste vara endimensionell" -#: utils/adt/arrayutils.c:273 +#: utils/adt/arrayutils.c:252 #, c-format msgid "typmod array must not contain nulls" msgstr "typmod-arrayen får inte innehålla null-värden" @@ -23825,48 +24801,52 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "kodningskonvertering från %s till ASCII stöds inte" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:153 utils/adt/cash.c:277 utils/adt/datetime.c:4017 -#: utils/adt/float.c:206 utils/adt/float.c:293 utils/adt/float.c:307 -#: utils/adt/float.c:412 utils/adt/float.c:495 utils/adt/float.c:509 +#: utils/adt/bool.c:149 utils/adt/cash.c:354 utils/adt/datetime.c:4142 +#: utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 +#: utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 #: utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 #: utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 #: utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 #: utils/adt/geo_ops.c:4672 utils/adt/int.c:174 utils/adt/int.c:186 -#: utils/adt/jsonpath.c:183 utils/adt/mac.c:94 utils/adt/mac8.c:225 -#: utils/adt/network.c:99 utils/adt/numeric.c:795 utils/adt/numeric.c:7136 -#: utils/adt/numeric.c:7339 utils/adt/numeric.c:8286 utils/adt/numutils.c:357 -#: utils/adt/numutils.c:619 utils/adt/numutils.c:881 utils/adt/numutils.c:920 -#: utils/adt/numutils.c:942 utils/adt/numutils.c:1006 utils/adt/numutils.c:1028 -#: utils/adt/pg_lsn.c:74 utils/adt/tid.c:72 utils/adt/tid.c:80 -#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:494 -#: utils/adt/uuid.c:135 utils/adt/xid8funcs.c:354 +#: utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 +#: utils/adt/network.c:99 utils/adt/numeric.c:803 utils/adt/numeric.c:7221 +#: utils/adt/numeric.c:7424 utils/adt/numeric.c:8371 utils/adt/numutils.c:356 +#: utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 +#: utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 +#: utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 +#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:510 +#: utils/adt/uuid.c:140 utils/adt/xid8funcs.c:323 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "ogiltig indatasyntax för type %s: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 -#: utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:351 -#: utils/adt/numutils.c:613 utils/adt/numutils.c:875 utils/adt/numutils.c:926 -#: utils/adt/numutils.c:965 utils/adt/numutils.c:1012 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 +#: utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "värdet \"%s\" är utanför giltigt intervall för typen %s" +msgid "money out of range" +msgstr "money utanför giltigt intervall" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 -#: utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 -#: utils/adt/float.c:105 utils/adt/int.c:843 utils/adt/int.c:959 -#: utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 -#: utils/adt/int.c:1167 utils/adt/int8.c:515 utils/adt/int8.c:573 -#: utils/adt/int8.c:943 utils/adt/int8.c:1023 utils/adt/int8.c:1085 -#: utils/adt/int8.c:1165 utils/adt/numeric.c:3175 utils/adt/numeric.c:3198 -#: utils/adt/numeric.c:3283 utils/adt/numeric.c:3301 utils/adt/numeric.c:3397 -#: utils/adt/numeric.c:8835 utils/adt/numeric.c:9148 utils/adt/numeric.c:9496 -#: utils/adt/numeric.c:9612 utils/adt/numeric.c:11122 -#: utils/adt/timestamp.c:3406 +#: utils/adt/cash.c:161 utils/adt/cash.c:723 utils/adt/float.c:99 +#: utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 +#: utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 +#: utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 +#: utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 +#: utils/adt/numeric.c:3191 utils/adt/numeric.c:3214 utils/adt/numeric.c:3299 +#: utils/adt/numeric.c:3317 utils/adt/numeric.c:3413 utils/adt/numeric.c:8920 +#: utils/adt/numeric.c:9233 utils/adt/numeric.c:9581 utils/adt/numeric.c:9697 +#: utils/adt/numeric.c:11208 utils/adt/timestamp.c:3713 #, c-format msgid "division by zero" msgstr "division med noll" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 +#: utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 +#: utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 +#: utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "värdet \"%s\" är utanför giltigt intervall för typen %s" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -23877,159 +24857,186 @@ msgstr "\"char\" utanför sitt intervall" msgid "could not compute %s hash: %s" msgstr "kunde inte beräkna %s-hash: %s" -#: utils/adt/date.c:63 utils/adt/timestamp.c:100 utils/adt/varbit.c:105 -#: utils/adt/varchar.c:49 +#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 +#: utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "ogiltig typmodifierare" -#: utils/adt/date.c:75 +#: utils/adt/date.c:76 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "TIME(%d)%s-precisionen får inte vara negativ" -#: utils/adt/date.c:81 +#: utils/adt/date.c:82 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "TIME(%d)%s-precisionen reducerad till maximalt tillåtna, %d" -#: utils/adt/date.c:166 utils/adt/date.c:174 utils/adt/formatting.c:4241 -#: utils/adt/formatting.c:4250 utils/adt/formatting.c:4363 -#: utils/adt/formatting.c:4373 +#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 +#: utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 +#: utils/adt/formatting.c:4548 #, c-format msgid "date out of range: \"%s\"" msgstr "datum utanför giltigt intervall \"%s\"" -#: utils/adt/date.c:221 utils/adt/date.c:519 utils/adt/date.c:543 -#: utils/adt/rangetypes.c:1577 utils/adt/rangetypes.c:1592 utils/adt/xml.c:2460 +#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 +#: utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "datum utanför giltigt intervall" -#: utils/adt/date.c:267 utils/adt/timestamp.c:582 +#: utils/adt/date.c:268 utils/adt/timestamp.c:598 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "datumfältvärde utanför giltigt område: %d-%02d-%02d" -#: utils/adt/date.c:274 utils/adt/date.c:283 utils/adt/timestamp.c:588 +#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "datum utanför giltigt område: %d-%02d-%02d" -#: utils/adt/date.c:494 +#: utils/adt/date.c:495 #, c-format msgid "cannot subtract infinite dates" msgstr "kan inte subtrahera oändliga datum" -#: utils/adt/date.c:592 utils/adt/date.c:655 utils/adt/date.c:691 -#: utils/adt/date.c:2885 utils/adt/date.c:2895 +#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 +#: utils/adt/date.c:2906 utils/adt/date.c:2916 #, c-format msgid "date out of range for timestamp" msgstr "datum utanför filtigt område för timestamp" -#: utils/adt/date.c:1121 utils/adt/date.c:1204 utils/adt/date.c:1220 -#: utils/adt/date.c:2206 utils/adt/date.c:2990 utils/adt/timestamp.c:4097 -#: utils/adt/timestamp.c:4290 utils/adt/timestamp.c:4432 -#: utils/adt/timestamp.c:4685 utils/adt/timestamp.c:4886 -#: utils/adt/timestamp.c:4933 utils/adt/timestamp.c:5157 -#: utils/adt/timestamp.c:5204 utils/adt/timestamp.c:5334 +#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 +#: utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 +#: utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 +#: utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 +#: utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 +#: utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 +#: utils/adt/timestamp.c:6070 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "enheten \"%s\" stöds inte för typen %s" -#: utils/adt/date.c:1229 utils/adt/date.c:2222 utils/adt/date.c:3010 -#: utils/adt/timestamp.c:4111 utils/adt/timestamp.c:4307 -#: utils/adt/timestamp.c:4446 utils/adt/timestamp.c:4645 -#: utils/adt/timestamp.c:4942 utils/adt/timestamp.c:5213 -#: utils/adt/timestamp.c:5395 +#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 +#: utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 +#: utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 +#: utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 +#: utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "enheten \"%s\" känns inte igen för typen %s" -#: utils/adt/date.c:1313 utils/adt/date.c:1359 utils/adt/date.c:1918 -#: utils/adt/date.c:1949 utils/adt/date.c:1978 utils/adt/date.c:2848 -#: utils/adt/date.c:3080 utils/adt/datetime.c:424 utils/adt/datetime.c:1809 -#: utils/adt/formatting.c:4081 utils/adt/formatting.c:4117 -#: utils/adt/formatting.c:4210 utils/adt/formatting.c:4339 utils/adt/json.c:467 -#: utils/adt/json.c:506 utils/adt/timestamp.c:232 utils/adt/timestamp.c:264 -#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:709 -#: utils/adt/timestamp.c:787 utils/adt/timestamp.c:820 -#: utils/adt/timestamp.c:2933 utils/adt/timestamp.c:2954 -#: utils/adt/timestamp.c:2967 utils/adt/timestamp.c:2976 -#: utils/adt/timestamp.c:2984 utils/adt/timestamp.c:3045 -#: utils/adt/timestamp.c:3068 utils/adt/timestamp.c:3081 -#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3100 -#: utils/adt/timestamp.c:3801 utils/adt/timestamp.c:3925 -#: utils/adt/timestamp.c:4015 utils/adt/timestamp.c:4105 -#: utils/adt/timestamp.c:4198 utils/adt/timestamp.c:4301 -#: utils/adt/timestamp.c:4750 utils/adt/timestamp.c:5024 -#: utils/adt/timestamp.c:5463 utils/adt/timestamp.c:5473 -#: utils/adt/timestamp.c:5478 utils/adt/timestamp.c:5484 -#: utils/adt/timestamp.c:5517 utils/adt/timestamp.c:5604 -#: utils/adt/timestamp.c:5645 utils/adt/timestamp.c:5649 -#: utils/adt/timestamp.c:5703 utils/adt/timestamp.c:5707 -#: utils/adt/timestamp.c:5713 utils/adt/timestamp.c:5747 utils/adt/xml.c:2482 -#: utils/adt/xml.c:2489 utils/adt/xml.c:2509 utils/adt/xml.c:2516 +#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 +#: utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 +#: utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 +#: utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 +#: utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 +#: utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 +#: utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 +#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 +#: utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 +#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 +#: utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 +#: utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 +#: utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 +#: utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 +#: utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 +#: utils/adt/timestamp.c:3266 utils/adt/timestamp.c:3279 +#: utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 +#: utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 +#: utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 +#: utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 +#: utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 +#: utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 +#: utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 +#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 +#: utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 +#: utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 +#: utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 +#: utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2574 +#: utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "timestamp utanför giltigt intervall" -#: utils/adt/date.c:1535 utils/adt/date.c:2343 utils/adt/formatting.c:4431 +#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 #, c-format msgid "time out of range" msgstr "time utanför giltigt intervall" -#: utils/adt/date.c:1587 utils/adt/timestamp.c:597 +#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "time-värde utanför giltigt område: %d:%02d:%02g" -#: utils/adt/date.c:2107 utils/adt/date.c:2647 utils/adt/float.c:1042 -#: utils/adt/float.c:1118 utils/adt/int.c:635 utils/adt/int.c:682 -#: utils/adt/int.c:717 utils/adt/int8.c:414 utils/adt/numeric.c:2579 -#: utils/adt/timestamp.c:3455 utils/adt/timestamp.c:3482 -#: utils/adt/timestamp.c:3513 +#: utils/adt/date.c:2020 +#, c-format +msgid "cannot convert infinite interval to time" +msgstr "kan inte konvertera oändligt intervall till time" + +#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#, c-format +msgid "cannot add infinite interval to time" +msgstr "kan inte addera oändligt intervall till time" + +#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#, c-format +msgid "cannot subtract infinite interval from time" +msgstr "kan inte subtrahera oändligt intervall från time" + +#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 +#: utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 +#: utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2595 +#: utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 +#: utils/adt/timestamp.c:3888 #, c-format msgid "invalid preceding or following size in window function" msgstr "ogiltig föregående eller efterföljande storlek i fönsterfunktion" -#: utils/adt/date.c:2351 +#: utils/adt/date.c:2360 #, c-format msgid "time zone displacement out of range" msgstr "tidszonförskjutning utanför giltigt intervall" -#: utils/adt/date.c:3110 utils/adt/timestamp.c:5506 utils/adt/timestamp.c:5736 +#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#, c-format +msgid "interval time zone \"%s\" must be finite" +msgstr "intervalltidszonen \"%s\" måste vara ändlig" + +#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "intervalltidszonen \"%s\" kan inte inkludera månader eller år" -#: utils/adt/datetime.c:3223 utils/adt/datetime.c:4002 -#: utils/adt/datetime.c:4008 utils/adt/timestamp.c:512 +#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 +#: utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 #, c-format msgid "time zone \"%s\" not recognized" msgstr "tidszon \"%s\" känns inte igen" -#: utils/adt/datetime.c:3976 utils/adt/datetime.c:3983 +#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "datum/tid-värde utanför giltigt område: \"%s\"" -#: utils/adt/datetime.c:3985 +#: utils/adt/datetime.c:4110 #, c-format msgid "Perhaps you need a different \"datestyle\" setting." msgstr "Du kanske behöver en annan inställning av variabeln \"datestyle\"." -#: utils/adt/datetime.c:3990 +#: utils/adt/datetime.c:4115 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "intervall-värde utanför giltigt område: \"%s\"" -#: utils/adt/datetime.c:3996 +#: utils/adt/datetime.c:4121 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "tidszonförskjutning itanför sitt intervall: \"%s\"" -#: utils/adt/datetime.c:4010 +#: utils/adt/datetime.c:4135 #, c-format msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"." msgstr "Detta tidszonsnamn finns i konfigurationsfilen för tidszonsförkortning \"%s\"." @@ -24039,22 +25046,22 @@ msgstr "Detta tidszonsnamn finns i konfigurationsfilen för tidszonsförkortning msgid "invalid Datum pointer" msgstr "ogiltigt Datum-pekare" -#: utils/adt/dbsize.c:761 utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:764 utils/adt/dbsize.c:840 #, c-format msgid "invalid size: \"%s\"" msgstr "ogiltig storlek: \"%s\"" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:841 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "Ogiltig storleksenhet: \"%s\"." -#: utils/adt/dbsize.c:839 +#: utils/adt/dbsize.c:842 #, c-format msgid "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." msgstr "Giltiga enheter är \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\" och \"PB\"." -#: utils/adt/domains.c:92 +#: utils/adt/domains.c:95 #, c-format msgid "type %s is not a domain" msgstr "typen %s är inte en domän" @@ -24136,353 +25143,348 @@ msgstr "kunde inte bestämma den verkliga enum-typen" msgid "enum %s contains no values" msgstr "enum %s innehåller inga värden" -#: utils/adt/float.c:89 +#: utils/adt/float.c:83 #, c-format msgid "value out of range: overflow" msgstr "värde utanför giltigt intervall: overflow" -#: utils/adt/float.c:97 +#: utils/adt/float.c:91 #, c-format msgid "value out of range: underflow" msgstr "värde utanför giltigt intervall: underflow" -#: utils/adt/float.c:286 +#: utils/adt/float.c:280 #, c-format msgid "\"%s\" is out of range for type real" msgstr "\"%s\" är utanför giltigt intervall för typen real" -#: utils/adt/float.c:488 +#: utils/adt/float.c:482 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "\"%s\" är utanför giltigt intervall för typen double precision" -#: utils/adt/float.c:1253 utils/adt/float.c:1327 utils/adt/int.c:355 +#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 #: utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 #: utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 -#: utils/adt/int8.c:1278 utils/adt/numeric.c:4500 utils/adt/numeric.c:4505 +#: utils/adt/int8.c:1277 utils/adt/numeric.c:4593 utils/adt/numeric.c:4598 #, c-format msgid "smallint out of range" msgstr "smallint utanför sitt intervall" -#: utils/adt/float.c:1453 utils/adt/numeric.c:3693 utils/adt/numeric.c:10027 +#: utils/adt/float.c:1447 utils/adt/numeric.c:3709 utils/adt/numeric.c:10112 #, c-format msgid "cannot take square root of a negative number" msgstr "kan inte ta kvadratroten av ett negativt tal" -#: utils/adt/float.c:1521 utils/adt/numeric.c:3981 utils/adt/numeric.c:4093 +#: utils/adt/float.c:1515 utils/adt/numeric.c:3997 utils/adt/numeric.c:4109 #, c-format msgid "zero raised to a negative power is undefined" msgstr "noll upphöjt med ett negativt tal är odefinierat" -#: utils/adt/float.c:1525 utils/adt/numeric.c:3985 utils/adt/numeric.c:10918 +#: utils/adt/float.c:1519 utils/adt/numeric.c:4001 utils/adt/numeric.c:11003 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "ett negativt tal upphöjt i en icke-negativ potens ger ett komplext resultat" -#: utils/adt/float.c:1701 utils/adt/float.c:1734 utils/adt/numeric.c:3893 -#: utils/adt/numeric.c:10698 +#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3909 +#: utils/adt/numeric.c:10783 #, c-format msgid "cannot take logarithm of zero" msgstr "kan inte ta logartimen av noll" -#: utils/adt/float.c:1705 utils/adt/float.c:1738 utils/adt/numeric.c:3831 -#: utils/adt/numeric.c:3888 utils/adt/numeric.c:10702 +#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3847 +#: utils/adt/numeric.c:3904 utils/adt/numeric.c:10787 #, c-format msgid "cannot take logarithm of a negative number" msgstr "kan inte ta logaritmen av ett negativt tal" -#: utils/adt/float.c:1771 utils/adt/float.c:1802 utils/adt/float.c:1897 -#: utils/adt/float.c:1924 utils/adt/float.c:1952 utils/adt/float.c:1979 -#: utils/adt/float.c:2126 utils/adt/float.c:2163 utils/adt/float.c:2333 -#: utils/adt/float.c:2389 utils/adt/float.c:2454 utils/adt/float.c:2511 -#: utils/adt/float.c:2702 utils/adt/float.c:2726 +#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 +#: utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 +#: utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 +#: utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 +#: utils/adt/float.c:2696 utils/adt/float.c:2720 #, c-format msgid "input is out of range" msgstr "indata är utanför giltigt intervall" -#: utils/adt/float.c:2867 -#, c-format -msgid "setseed parameter %g is out of allowed range [-1,1]" -msgstr "setseed-parameter %g är utanför giltigt intervall [-1,1]" - -#: utils/adt/float.c:4095 utils/adt/numeric.c:1841 +#: utils/adt/float.c:4000 utils/adt/numeric.c:1857 #, c-format msgid "count must be greater than zero" msgstr "antal måste vara större än noll" -#: utils/adt/float.c:4100 utils/adt/numeric.c:1852 +#: utils/adt/float.c:4005 utils/adt/numeric.c:1868 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" -msgstr "operand, lägre gräns och övre gräns kan inte vara NaN" +msgstr "operand, undre gräns och övre gräns kan inte vara NaN" -#: utils/adt/float.c:4106 utils/adt/numeric.c:1857 +#: utils/adt/float.c:4011 utils/adt/numeric.c:1873 #, c-format msgid "lower and upper bounds must be finite" -msgstr "lägre och övre gräns måste vara ändliga" +msgstr "undre och övre gräns måste vara ändliga" -#: utils/adt/float.c:4172 utils/adt/numeric.c:1871 +#: utils/adt/float.c:4077 utils/adt/numeric.c:1887 #, c-format msgid "lower bound cannot equal upper bound" -msgstr "lägre gräns kan inte vara samma som övre gräns" +msgstr "undre gräns kan inte vara samma som övre gräns" -#: utils/adt/formatting.c:519 +#: utils/adt/formatting.c:530 #, c-format msgid "invalid format specification for an interval value" msgstr "ogiltig formatspecifikation för ett intervallvärdei" -#: utils/adt/formatting.c:520 +#: utils/adt/formatting.c:531 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "Intervaller är inte kopplade till specifika kalenderdatum." -#: utils/adt/formatting.c:1150 +#: utils/adt/formatting.c:1161 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\" måste vara det sista mönstret som används" -#: utils/adt/formatting.c:1158 +#: utils/adt/formatting.c:1169 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\" måste vara före \"PR\"" -#: utils/adt/formatting.c:1174 +#: utils/adt/formatting.c:1185 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\" måste vara före \"PR\"" -#: utils/adt/formatting.c:1201 +#: utils/adt/formatting.c:1212 #, c-format msgid "multiple decimal points" msgstr "multipla decimalpunkter" -#: utils/adt/formatting.c:1205 utils/adt/formatting.c:1288 +#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "kan inte använda \"V\" ach decimalpunkt tillsammans" -#: utils/adt/formatting.c:1217 +#: utils/adt/formatting.c:1228 #, c-format msgid "cannot use \"S\" twice" msgstr "kan inte använda \"S\" två gånger" -#: utils/adt/formatting.c:1221 +#: utils/adt/formatting.c:1232 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "kan inte använda \"S\" och \"PL\"/\"MI\"/\"SG\"/\"PR\" tillsammans" -#: utils/adt/formatting.c:1241 +#: utils/adt/formatting.c:1252 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "kan inte använda \"S\" och \"MI\" tillsammans." -#: utils/adt/formatting.c:1251 +#: utils/adt/formatting.c:1262 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "kan inte använda \"S\" och \"PL\" tillsammans." -#: utils/adt/formatting.c:1261 +#: utils/adt/formatting.c:1272 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "kan inte använda \"S\" och \"SG\" tillsammans." -#: utils/adt/formatting.c:1270 +#: utils/adt/formatting.c:1281 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "kan inte använda \"PR\" och \"S\"/\"PL\"/\"MI\"/\"SG\" tillsammans." -#: utils/adt/formatting.c:1296 +#: utils/adt/formatting.c:1307 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "kan inte använda \"EEEE\" två gånger" -#: utils/adt/formatting.c:1302 +#: utils/adt/formatting.c:1313 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "\"EEEE\" är inkompatibel med andra format" -#: utils/adt/formatting.c:1303 +#: utils/adt/formatting.c:1314 #, c-format msgid "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "\"EEEE\" får bara användas tillsammans med siffror- och decimalpunkts-mönster." -#: utils/adt/formatting.c:1387 +#: utils/adt/formatting.c:1398 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "ogiltigt formatseparator för datetime: \"%s\"" -#: utils/adt/formatting.c:1514 +#: utils/adt/formatting.c:1525 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\" är inte ett nummer" -#: utils/adt/formatting.c:1592 +#: utils/adt/formatting.c:1603 #, c-format msgid "case conversion failed: %s" msgstr "case-konvertering misslyckades: %s" -#: utils/adt/formatting.c:1646 utils/adt/formatting.c:1768 -#: utils/adt/formatting.c:1891 +#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 +#: utils/adt/formatting.c:1989 #, c-format msgid "could not determine which collation to use for %s function" msgstr "kunde inte bestämma jämförelse (collation) för funktionen %s" -#: utils/adt/formatting.c:2274 +#: utils/adt/formatting.c:2410 #, c-format msgid "invalid combination of date conventions" msgstr "ogiltig kombination av datumkonventioner" -#: utils/adt/formatting.c:2275 +#: utils/adt/formatting.c:2411 #, c-format msgid "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr "Blanda inte datumkonventionerna Gregoriansk och ISO-veckor i formatteringsmall." -#: utils/adt/formatting.c:2297 +#: utils/adt/formatting.c:2433 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "värden för \"%s\" i formatsträng står i konflikt med varandra" -#: utils/adt/formatting.c:2299 +#: utils/adt/formatting.c:2435 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "Detta värde motsäger en tidigare inställning för samma fälttyp." -#: utils/adt/formatting.c:2366 +#: utils/adt/formatting.c:2502 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "källsträngen är för kort för formatfält \"%s\"" -#: utils/adt/formatting.c:2368 +#: utils/adt/formatting.c:2504 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "Fältet kräver %d tecken men bara %d återstår." -#: utils/adt/formatting.c:2370 utils/adt/formatting.c:2384 +#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 #, c-format msgid "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "Om din källsträng inte är av fast längd så testa med modifieraren \"FM\"." -#: utils/adt/formatting.c:2380 utils/adt/formatting.c:2393 -#: utils/adt/formatting.c:2614 +#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 +#: utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "ogiltigt värde \"%s\" för \"%s\"" -#: utils/adt/formatting.c:2382 +#: utils/adt/formatting.c:2518 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "Fältet kräver %d tecken men bara %d kunde parsas." -#: utils/adt/formatting.c:2395 +#: utils/adt/formatting.c:2531 #, c-format msgid "Value must be an integer." msgstr "Värdet måste vara ett heltal." -#: utils/adt/formatting.c:2400 +#: utils/adt/formatting.c:2536 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "värdet för \"%s\" i källsträng är utanför giltigt intervall" -#: utils/adt/formatting.c:2402 +#: utils/adt/formatting.c:2538 #, c-format msgid "Value must be in the range %d to %d." msgstr "Värdet måste vara i intervallet %d till %d." -#: utils/adt/formatting.c:2616 +#: utils/adt/formatting.c:2752 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "Det givna värdet matchar inget av de tillåtna värdena för detta fält." -#: utils/adt/formatting.c:2832 utils/adt/formatting.c:2852 -#: utils/adt/formatting.c:2872 utils/adt/formatting.c:2892 -#: utils/adt/formatting.c:2911 utils/adt/formatting.c:2930 -#: utils/adt/formatting.c:2954 utils/adt/formatting.c:2972 -#: utils/adt/formatting.c:2990 utils/adt/formatting.c:3008 -#: utils/adt/formatting.c:3025 utils/adt/formatting.c:3042 +#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 +#: utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 +#: utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 +#: utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 +#: utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 +#: utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 #, c-format msgid "localized string format value too long" msgstr "lokaliserat strängformatvärde är för långt" -#: utils/adt/formatting.c:3322 +#: utils/adt/formatting.c:3458 #, c-format msgid "unmatched format separator \"%c\"" msgstr "ej matchande formatteringsseparator \"%c\"" -#: utils/adt/formatting.c:3383 +#: utils/adt/formatting.c:3519 #, c-format msgid "unmatched format character \"%s\"" msgstr "ej matchande formatteringstecken \"%s\"" -#: utils/adt/formatting.c:3491 +#: utils/adt/formatting.c:3652 #, c-format -msgid "formatting field \"%s\" is only supported in to_char" -msgstr "formateringsfält \"%s\" stöds bara i to_char" +msgid "Time zone abbreviation is not recognized." +msgstr "Känner inte igen förkortning för tidszon." -#: utils/adt/formatting.c:3665 +#: utils/adt/formatting.c:3853 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "ogiltig indatasträng för \"Y,YYY\"" -#: utils/adt/formatting.c:3754 +#: utils/adt/formatting.c:3942 #, c-format msgid "input string is too short for datetime format" msgstr "indatasträngen är för kort för datetime-formatet" -#: utils/adt/formatting.c:3762 +#: utils/adt/formatting.c:3950 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "efterföljande tecken finns kvar i indatasträngen efter datetime-formattering" -#: utils/adt/formatting.c:4319 +#: utils/adt/formatting.c:4494 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "saknar tidszon i indatasträngen för typen timestamptz" -#: utils/adt/formatting.c:4325 +#: utils/adt/formatting.c:4500 #, c-format msgid "timestamptz out of range" msgstr "timestamptz utanför giltigt intervall" -#: utils/adt/formatting.c:4353 +#: utils/adt/formatting.c:4528 #, c-format msgid "datetime format is zoned but not timed" msgstr "datetime-format har zon men inte tid" -#: utils/adt/formatting.c:4411 +#: utils/adt/formatting.c:4577 #, c-format msgid "missing time zone in input string for type timetz" msgstr "saknar tidszon i indatasträng för typ timetz" -#: utils/adt/formatting.c:4417 +#: utils/adt/formatting.c:4583 #, c-format msgid "timetz out of range" msgstr "timetz utanför giltigt intervall" -#: utils/adt/formatting.c:4443 +#: utils/adt/formatting.c:4609 #, c-format msgid "datetime format is not dated and not timed" msgstr "datetime-format har inte datum och inte tid" -#: utils/adt/formatting.c:4575 +#: utils/adt/formatting.c:4786 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "timmen \"%d\" är ogiltigt för en 12-timmars-klocka" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4788 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "Använd en 24-timmars-klocka eller ange en timme mellan 1 och 12." -#: utils/adt/formatting.c:4689 +#: utils/adt/formatting.c:4900 #, c-format msgid "cannot calculate day of year without year information" msgstr "kan inte beräkna dag på året utan årsinformation" -#: utils/adt/formatting.c:5621 +#: utils/adt/formatting.c:5852 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\" stöds inte för indata" -#: utils/adt/formatting.c:5633 +#: utils/adt/formatting.c:5864 #, c-format msgid "\"RN\" not supported for input" msgstr "\"RN\" stöds inte för indata" @@ -24514,12 +25516,7 @@ msgstr "kunde inte söka (seek) i fil \"%s\": %m" msgid "file length too large" msgstr "fillängd är för stor" -#: utils/adt/genfile.c:248 -#, c-format -msgid "must be superuser to read files with adminpack 1.0" -msgstr "måste vara superuser för att läsa filer med adminpack 1.0" - -#: utils/adt/genfile.c:702 +#: utils/adt/genfile.c:656 #, c-format msgid "tablespace with OID %u does not exist" msgstr "tabellutrymme med OID %u finns inte" @@ -24575,555 +25572,640 @@ msgstr "måste efterfråga minst 2 punkter" msgid "invalid int2vector data" msgstr "ogiltig int2vector-data" -#: utils/adt/int.c:1529 utils/adt/int8.c:1404 utils/adt/numeric.c:1749 -#: utils/adt/timestamp.c:5797 utils/adt/timestamp.c:5879 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1765 +#: utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 #, c-format msgid "step size cannot equal zero" msgstr "stegstorleken kan inte vara noll" -#: utils/adt/int8.c:449 utils/adt/int8.c:472 utils/adt/int8.c:486 -#: utils/adt/int8.c:500 utils/adt/int8.c:531 utils/adt/int8.c:555 -#: utils/adt/int8.c:637 utils/adt/int8.c:705 utils/adt/int8.c:711 -#: utils/adt/int8.c:737 utils/adt/int8.c:751 utils/adt/int8.c:775 -#: utils/adt/int8.c:788 utils/adt/int8.c:900 utils/adt/int8.c:914 -#: utils/adt/int8.c:928 utils/adt/int8.c:959 utils/adt/int8.c:981 -#: utils/adt/int8.c:995 utils/adt/int8.c:1009 utils/adt/int8.c:1042 -#: utils/adt/int8.c:1056 utils/adt/int8.c:1070 utils/adt/int8.c:1101 -#: utils/adt/int8.c:1123 utils/adt/int8.c:1137 utils/adt/int8.c:1151 -#: utils/adt/int8.c:1313 utils/adt/int8.c:1348 utils/adt/numeric.c:4459 -#: utils/adt/rangetypes.c:1528 utils/adt/rangetypes.c:1541 +#: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 +#: utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 +#: utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 +#: utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 +#: utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 +#: utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 +#: utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 +#: utils/adt/int8.c:1055 utils/adt/int8.c:1069 utils/adt/int8.c:1100 +#: utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 +#: utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4542 +#: utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 #: utils/adt/varbit.c:1676 #, c-format msgid "bigint out of range" msgstr "bigint utanför sitt intervall" -#: utils/adt/int8.c:1361 +#: utils/adt/int8.c:1360 #, c-format msgid "OID out of range" msgstr "OID utanför sitt intervall" -#: utils/adt/json.c:320 utils/adt/jsonb.c:781 +#: utils/adt/json.c:202 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "nyckelvärde måste vara skalär, inte array, composite eller json" -#: utils/adt/json.c:1113 utils/adt/json.c:1123 utils/fmgr/funcapi.c:2082 +#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "kunde inte lista ut datatypen för argument %d" -#: utils/adt/json.c:1146 utils/adt/json.c:1337 utils/adt/json.c:1513 -#: utils/adt/json.c:1591 utils/adt/jsonb.c:1432 utils/adt/jsonb.c:1522 +#: utils/adt/json.c:1067 utils/adt/json.c:1266 utils/adt/json.c:1449 +#: utils/adt/json.c:1527 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "null-värde tillåts inte som objektnyckel" -#: utils/adt/json.c:1189 utils/adt/json.c:1352 +#: utils/adt/json.c:1117 utils/adt/json.c:1288 #, c-format msgid "duplicate JSON object key value: %s" msgstr "duplicerat nyckelvärde i JSON objekt: %s" -#: utils/adt/json.c:1297 utils/adt/jsonb.c:1233 +#: utils/adt/json.c:1226 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "argumentlistan måste ha ett jämt antal element" #. translator: %s is a SQL function name -#: utils/adt/json.c:1299 utils/adt/jsonb.c:1235 +#: utils/adt/json.c:1228 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "Argumenten till %s måste bestå av varannan nyckel och varannat värde." -#: utils/adt/json.c:1491 utils/adt/jsonb.c:1410 +#: utils/adt/json.c:1427 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "array:en måste ha två kolumner" -#: utils/adt/json.c:1580 utils/adt/jsonb.c:1511 +#: utils/adt/json.c:1516 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "array-dimensionerna stämmer inte" -#: utils/adt/json.c:1764 utils/adt/jsonb_util.c:1958 +#: utils/adt/json.c:1702 utils/adt/jsonb_util.c:1956 #, c-format msgid "duplicate JSON object key value" msgstr "duplicerat nyckelvärde i JSON objekt" -#: utils/adt/jsonb.c:294 +#: utils/adt/jsonb.c:282 #, c-format msgid "string too long to represent as jsonb string" msgstr "strängen är för lång för att representeras som en jsonb-sträng" -#: utils/adt/jsonb.c:295 +#: utils/adt/jsonb.c:283 #, c-format msgid "Due to an implementation restriction, jsonb strings cannot exceed %d bytes." msgstr "På grund av en implementationsbegränsning så kan jsonb-strängar inte överstiga %d byte." -#: utils/adt/jsonb.c:1252 +#: utils/adt/jsonb.c:1153 #, c-format msgid "argument %d: key must not be null" msgstr "argument %d: nyckeln får inte vara null" -#: utils/adt/jsonb.c:1843 +#: utils/adt/jsonb.c:1744 #, c-format msgid "field name must not be null" msgstr "fältnamnet får inte vara null" -#: utils/adt/jsonb.c:1905 +#: utils/adt/jsonb.c:1806 #, c-format msgid "object keys must be strings" msgstr "objektnycklar måste vara strängar" -#: utils/adt/jsonb.c:2116 +#: utils/adt/jsonb.c:2017 #, c-format msgid "cannot cast jsonb null to type %s" msgstr "kan inte typomvandla jsonb-null till type %s" -#: utils/adt/jsonb.c:2117 +#: utils/adt/jsonb.c:2018 #, c-format msgid "cannot cast jsonb string to type %s" msgstr "kan inte typomvandla jsonb-sträng till typ %s" -#: utils/adt/jsonb.c:2118 +#: utils/adt/jsonb.c:2019 #, c-format msgid "cannot cast jsonb numeric to type %s" msgstr "kan inte typomvandla jsonb-numeric till typ %s" -#: utils/adt/jsonb.c:2119 +#: utils/adt/jsonb.c:2020 #, c-format msgid "cannot cast jsonb boolean to type %s" msgstr "kan inte typomvandla jsonb-boolean till typ %s" -#: utils/adt/jsonb.c:2120 +#: utils/adt/jsonb.c:2021 #, c-format msgid "cannot cast jsonb array to type %s" msgstr "kan inte typomvandla jsonb-array till typ %s" -#: utils/adt/jsonb.c:2121 +#: utils/adt/jsonb.c:2022 #, c-format msgid "cannot cast jsonb object to type %s" msgstr "kan inte typomvandla jsonb-objekt till typ %s" -#: utils/adt/jsonb.c:2122 +#: utils/adt/jsonb.c:2023 #, c-format msgid "cannot cast jsonb array or object to type %s" msgstr "kan inte typomvandla jsonb-array eller objekt till typ %s" -#: utils/adt/jsonb_util.c:758 +#: utils/adt/jsonb_util.c:756 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "antalet jsonb-objektpar överskrider det maximalt tillåtna (%zu)" -#: utils/adt/jsonb_util.c:799 +#: utils/adt/jsonb_util.c:797 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "antalet jsonb-array-element överskrider det maximalt tillåtna (%zu)" -#: utils/adt/jsonb_util.c:1673 utils/adt/jsonb_util.c:1693 +#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "total storleken på element i jsonb-array överskrider maximala %d byte" -#: utils/adt/jsonb_util.c:1754 utils/adt/jsonb_util.c:1789 -#: utils/adt/jsonb_util.c:1809 +#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 +#: utils/adt/jsonb_util.c:1807 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "total storleken på element i jsonb-objekt överskrider maximala %d byte" -#: utils/adt/jsonbsubs.c:70 utils/adt/jsonbsubs.c:151 +#: utils/adt/jsonbsubs.c:67 utils/adt/jsonbsubs.c:148 #, c-format msgid "jsonb subscript does not support slices" msgstr "array-index-syntax för jsonb stöder inte slices" -#: utils/adt/jsonbsubs.c:103 utils/adt/jsonbsubs.c:117 +#: utils/adt/jsonbsubs.c:100 utils/adt/jsonbsubs.c:114 #, c-format msgid "subscript type %s is not supported" msgstr "array-index-typ %s stöds inte" -#: utils/adt/jsonbsubs.c:104 +#: utils/adt/jsonbsubs.c:101 #, c-format msgid "jsonb subscript must be coercible to only one type, integer or text." msgstr "array-index för jsonb måste vara konverterbar till en av typerna integer eller text." -#: utils/adt/jsonbsubs.c:118 +#: utils/adt/jsonbsubs.c:115 #, c-format msgid "jsonb subscript must be coercible to either integer or text." msgstr "array-index för jsonb måste vara konverterbar till antingen integer eller text." -#: utils/adt/jsonbsubs.c:139 +#: utils/adt/jsonbsubs.c:136 #, c-format msgid "jsonb subscript must have text type" msgstr "array-index för jsonb måste ha typen text" -#: utils/adt/jsonbsubs.c:207 +#: utils/adt/jsonbsubs.c:204 #, c-format msgid "jsonb subscript in assignment must not be null" msgstr "array-index för jsonb i tilldelning kan inte vara null" -#: utils/adt/jsonfuncs.c:572 utils/adt/jsonfuncs.c:821 -#: utils/adt/jsonfuncs.c:2429 utils/adt/jsonfuncs.c:2881 -#: utils/adt/jsonfuncs.c:3676 utils/adt/jsonfuncs.c:4018 +#: utils/adt/jsonfuncs.c:583 utils/adt/jsonfuncs.c:830 +#: utils/adt/jsonfuncs.c:2439 utils/adt/jsonfuncs.c:3015 +#: utils/adt/jsonfuncs.c:3948 utils/adt/jsonfuncs.c:4295 #, c-format msgid "cannot call %s on a scalar" msgstr "kan inte anropa %s på en skalär" -#: utils/adt/jsonfuncs.c:577 utils/adt/jsonfuncs.c:806 -#: utils/adt/jsonfuncs.c:2883 utils/adt/jsonfuncs.c:3663 +#: utils/adt/jsonfuncs.c:588 utils/adt/jsonfuncs.c:815 +#: utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3935 #, c-format msgid "cannot call %s on an array" msgstr "kan inte anropa %s på en array" -#: utils/adt/jsonfuncs.c:713 +#: utils/adt/jsonfuncs.c:724 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "JSON-data, rad %d: %s%s%s" -#: utils/adt/jsonfuncs.c:1875 utils/adt/jsonfuncs.c:1912 +#: utils/adt/jsonfuncs.c:1883 utils/adt/jsonfuncs.c:1920 #, c-format msgid "cannot get array length of a scalar" msgstr "kan inte hämta array-längd på skalär" -#: utils/adt/jsonfuncs.c:1879 utils/adt/jsonfuncs.c:1898 +#: utils/adt/jsonfuncs.c:1887 utils/adt/jsonfuncs.c:1906 #, c-format msgid "cannot get array length of a non-array" msgstr "kan inte hämta array-längd på icke-array" -#: utils/adt/jsonfuncs.c:1978 +#: utils/adt/jsonfuncs.c:1986 #, c-format msgid "cannot call %s on a non-object" msgstr "kan inte anropa %s på ett icke-objekt" -#: utils/adt/jsonfuncs.c:2166 +#: utils/adt/jsonfuncs.c:2174 #, c-format msgid "cannot deconstruct an array as an object" msgstr "kan inte dekonstruera en array som ett objekt" -#: utils/adt/jsonfuncs.c:2180 +#: utils/adt/jsonfuncs.c:2188 #, c-format msgid "cannot deconstruct a scalar" msgstr "kan inte dekonstruera en skalär" -#: utils/adt/jsonfuncs.c:2225 +#: utils/adt/jsonfuncs.c:2233 #, c-format msgid "cannot extract elements from a scalar" msgstr "kan inte extrahera element från en skalär" -#: utils/adt/jsonfuncs.c:2229 +#: utils/adt/jsonfuncs.c:2237 #, c-format msgid "cannot extract elements from an object" msgstr "kan inte extrahera element från ett objekt" -#: utils/adt/jsonfuncs.c:2414 utils/adt/jsonfuncs.c:3896 +#: utils/adt/jsonfuncs.c:2424 utils/adt/jsonfuncs.c:4173 #, c-format msgid "cannot call %s on a non-array" msgstr "kan inte anropa %s på icke-array" -#: utils/adt/jsonfuncs.c:2488 utils/adt/jsonfuncs.c:2493 -#: utils/adt/jsonfuncs.c:2510 utils/adt/jsonfuncs.c:2516 +#: utils/adt/jsonfuncs.c:2515 utils/adt/jsonfuncs.c:2520 +#: utils/adt/jsonfuncs.c:2538 utils/adt/jsonfuncs.c:2544 #, c-format msgid "expected JSON array" msgstr "förväntade JSON-array" -#: utils/adt/jsonfuncs.c:2489 +#: utils/adt/jsonfuncs.c:2516 #, c-format msgid "See the value of key \"%s\"." msgstr "Se värdetypen för nyckel \"%s\"" -#: utils/adt/jsonfuncs.c:2511 +#: utils/adt/jsonfuncs.c:2539 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "Se array-element %s för nyckel \"%s\"." -#: utils/adt/jsonfuncs.c:2517 +#: utils/adt/jsonfuncs.c:2545 #, c-format msgid "See the array element %s." msgstr "Se array-element %s." -#: utils/adt/jsonfuncs.c:2552 +#: utils/adt/jsonfuncs.c:2597 #, c-format msgid "malformed JSON array" msgstr "felaktig JSON-array" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3389 +#: utils/adt/jsonfuncs.c:3647 #, c-format msgid "first argument of %s must be a row type" msgstr "första argumentet till %s måste vara en radtyp" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3413 +#: utils/adt/jsonfuncs.c:3671 #, c-format msgid "could not determine row type for result of %s" msgstr "kunde inte lista ut radtyp för resultat av %s" -#: utils/adt/jsonfuncs.c:3415 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "Provide a non-null record argument, or call the function in the FROM clause using a column definition list." msgstr "Ange en icke-null record som argument eller anropa funktionen i FROM-klausulen med en kolumndefinitionslista." -#: utils/adt/jsonfuncs.c:3785 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4059 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialiserat läge krävs, men stöds inte i detta kontext" -#: utils/adt/jsonfuncs.c:3913 utils/adt/jsonfuncs.c:3997 +#: utils/adt/jsonfuncs.c:4190 utils/adt/jsonfuncs.c:4274 #, c-format msgid "argument of %s must be an array of objects" msgstr "argumentet till %s måste vara en array med objekt" -#: utils/adt/jsonfuncs.c:3946 +#: utils/adt/jsonfuncs.c:4223 #, c-format msgid "cannot call %s on an object" msgstr "kan inte anropa %s på ett objekt" -#: utils/adt/jsonfuncs.c:4380 utils/adt/jsonfuncs.c:4439 -#: utils/adt/jsonfuncs.c:4519 +#: utils/adt/jsonfuncs.c:4656 utils/adt/jsonfuncs.c:4715 +#: utils/adt/jsonfuncs.c:4795 #, c-format msgid "cannot delete from scalar" msgstr "kan inte radera från en skalär" -#: utils/adt/jsonfuncs.c:4524 +#: utils/adt/jsonfuncs.c:4800 #, c-format msgid "cannot delete from object using integer index" msgstr "kan inte radera från objekt genom att använda heltalsindex" -#: utils/adt/jsonfuncs.c:4592 utils/adt/jsonfuncs.c:4751 +#: utils/adt/jsonfuncs.c:4868 utils/adt/jsonfuncs.c:5027 #, c-format msgid "cannot set path in scalar" msgstr "kan inte sätta sökväg i skalär" -#: utils/adt/jsonfuncs.c:4633 utils/adt/jsonfuncs.c:4675 +#: utils/adt/jsonfuncs.c:4909 utils/adt/jsonfuncs.c:4951 #, c-format msgid "null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"" msgstr "null_value_treatment måste vara \"delete_key\", \"return_target\", \"use_json_null\" eller \"raise_exception\"" -#: utils/adt/jsonfuncs.c:4646 +#: utils/adt/jsonfuncs.c:4922 #, c-format msgid "JSON value must not be null" msgstr "JSON-värde får inte vara null" -#: utils/adt/jsonfuncs.c:4647 +#: utils/adt/jsonfuncs.c:4923 #, c-format msgid "Exception was raised because null_value_treatment is \"raise_exception\"." msgstr "Avbrott utlöstes då null_value_treatment är \"raise_exception\"." -#: utils/adt/jsonfuncs.c:4648 +#: utils/adt/jsonfuncs.c:4924 #, c-format msgid "To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed." msgstr "För att undvika detta så ändra null_value_treatment-argumentet eller se till att ett SQL-NULL inte skickas." -#: utils/adt/jsonfuncs.c:4703 +#: utils/adt/jsonfuncs.c:4979 #, c-format msgid "cannot delete path in scalar" msgstr "kan inte radera sökväg i skalär" -#: utils/adt/jsonfuncs.c:4917 +#: utils/adt/jsonfuncs.c:5193 #, c-format msgid "path element at position %d is null" msgstr "sökvägselement vid position %d är null" -#: utils/adt/jsonfuncs.c:4936 utils/adt/jsonfuncs.c:4967 -#: utils/adt/jsonfuncs.c:5040 +#: utils/adt/jsonfuncs.c:5212 utils/adt/jsonfuncs.c:5243 +#: utils/adt/jsonfuncs.c:5316 #, c-format msgid "cannot replace existing key" msgstr "kan inte ersätta befintlig nyckel" -#: utils/adt/jsonfuncs.c:4937 utils/adt/jsonfuncs.c:4968 +#: utils/adt/jsonfuncs.c:5213 utils/adt/jsonfuncs.c:5244 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "Sökvägen förväntar sig att nyckeln är ett sammansatt objekt men det är ett skalärt värde." -#: utils/adt/jsonfuncs.c:5041 +#: utils/adt/jsonfuncs.c:5317 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "Försök använda funktionen jsonb_set för att ersätta nyckelvärde." -#: utils/adt/jsonfuncs.c:5145 +#: utils/adt/jsonfuncs.c:5421 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "sökvägselement vid position %d är inte ett heltal: \"%s\"" -#: utils/adt/jsonfuncs.c:5162 +#: utils/adt/jsonfuncs.c:5438 #, c-format msgid "path element at position %d is out of range: %d" msgstr "sökvägselement vid position %d är utanför giltigt intervall: %d\"" -#: utils/adt/jsonfuncs.c:5314 +#: utils/adt/jsonfuncs.c:5590 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "fel flaggtyp, bara array:er och skalärer tillåts" -#: utils/adt/jsonfuncs.c:5321 +#: utils/adt/jsonfuncs.c:5597 #, c-format msgid "flag array element is not a string" msgstr "flaggelement i arrayen är inte en sträng" -#: utils/adt/jsonfuncs.c:5322 utils/adt/jsonfuncs.c:5344 +#: utils/adt/jsonfuncs.c:5598 utils/adt/jsonfuncs.c:5620 #, c-format msgid "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\"." msgstr "Möjliga värden är: \"string\", \"numeric\", \"boolean\", \"key\" samt \"all\"." -#: utils/adt/jsonfuncs.c:5342 +#: utils/adt/jsonfuncs.c:5618 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "fel flagga i flagg-array: \"%s\"" -#: utils/adt/jsonpath.c:382 +#: utils/adt/jsonpath.c:389 #, c-format msgid "@ is not allowed in root expressions" msgstr "@ är inte tillåten i rotuttryck" -#: utils/adt/jsonpath.c:388 +#: utils/adt/jsonpath.c:395 #, c-format msgid "LAST is allowed only in array subscripts" msgstr "LAST tillåts bara i array-indexeringar" -#: utils/adt/jsonpath_exec.c:361 +#: utils/adt/jsonpath_exec.c:491 #, c-format msgid "single boolean result is expected" msgstr "förväntade ett booleanskt resultat" -#: utils/adt/jsonpath_exec.c:557 +#: utils/adt/jsonpath_exec.c:851 #, c-format -msgid "\"vars\" argument is not an object" -msgstr "\"variabel\"-argumentet är inte ett objekt" +msgid "jsonpath wildcard array accessor can only be applied to an array" +msgstr "jsonpaths arrayväljare med wildcard kan bara applcieras på en array" -#: utils/adt/jsonpath_exec.c:558 +#: utils/adt/jsonpath_exec.c:874 #, c-format -msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." -msgstr "Jsonpath-parametrar skall kodas som nyckel-värde-par av \"variabel\"-objekt." +msgid "jsonpath wildcard member accessor can only be applied to an object" +msgstr "jsonpaths medlemsväljare med wildcard kan bara appliceras på ett objekt" + +#: utils/adt/jsonpath_exec.c:923 +#, c-format +msgid "jsonpath array subscript is out of bounds" +msgstr "array-index för jsonpath är utanför giltigt område" + +#: utils/adt/jsonpath_exec.c:980 +#, c-format +msgid "jsonpath array accessor can only be applied to an array" +msgstr "jsonpaths arrayväljare kan bara appliceras på en array" -#: utils/adt/jsonpath_exec.c:675 +#: utils/adt/jsonpath_exec.c:1044 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "JSON-objekt innehåller inte nyckeln \"%s\"" -#: utils/adt/jsonpath_exec.c:687 +#: utils/adt/jsonpath_exec.c:1056 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "jsonpaths medlemsväljare kan bara appliceras på ett objekt" -#: utils/adt/jsonpath_exec.c:716 +#: utils/adt/jsonpath_exec.c:1114 #, c-format -msgid "jsonpath wildcard array accessor can only be applied to an array" -msgstr "jsonpaths arrayväljare med wildcard kan bara applcieras på en array" +msgid "jsonpath item method .%s() can only be applied to an array" +msgstr "jsonpaths elementmetod .%s() kan bara applicerars på en array" -#: utils/adt/jsonpath_exec.c:764 +#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 #, c-format -msgid "jsonpath array subscript is out of bounds" -msgstr "array-index för jsonpath är utanför giltigt område" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type double precision" +msgstr "argumentet \"%s\" till jsonpaths elementmetod .%s() är ogiltig för typen double precision" -#: utils/adt/jsonpath_exec.c:821 +#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 +#: utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 #, c-format -msgid "jsonpath array accessor can only be applied to an array" -msgstr "jsonpaths arrayväljare kan bara appliceras på en array" +msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" +msgstr "NaN eller Infinity tillåts inte för jsonpaths elementmetod .%s()" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 +#: utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 #, c-format -msgid "jsonpath wildcard member accessor can only be applied to an object" -msgstr "jsonpaths medlemsväljare med wildcard kan bara appliceras på ett objekt" +msgid "jsonpath item method .%s() can only be applied to a string or numeric value" +msgstr "jsonpaths elementmetod .%s() kan bara applicerars på en sträng eller ett numeriskt värde" -#: utils/adt/jsonpath_exec.c:1007 +#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 #, c-format -msgid "jsonpath item method .%s() can only be applied to an array" -msgstr "jsonpaths elementmetod .%s() lkan bara applicerar på en array" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" +msgstr "argumentet \"%s\" till jsonpaths elementmetod .%s() är ogiltig för typen bigint" -#: utils/adt/jsonpath_exec.c:1060 +#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 #, c-format -msgid "numeric argument of jsonpath item method .%s() is out of range for type double precision" -msgstr "numeriskt argument till jsonpaths elementmetod .%s() är utanför giltigt intervall för typen double precision" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" +msgstr "argumentet \"%s\" till jsonpaths elementmetod .%s() är ogiltig för typen boolean" -#: utils/adt/jsonpath_exec.c:1081 +#: utils/adt/jsonpath_exec.c:1386 #, c-format -msgid "string argument of jsonpath item method .%s() is not a valid representation of a double precision number" -msgstr "strängargument till jsonpaths elementmetod .%s() är inte en giltig representation av ett double precision-nummer" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, or numeric value" +msgstr "jsonpaths elementmetod .%s() kan bara appliceras på en boolean, sträng eller ett numeriskt värde" -#: utils/adt/jsonpath_exec.c:1094 +#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 #, c-format -msgid "jsonpath item method .%s() can only be applied to a string or numeric value" -msgstr "jsonpaths elementmetod .%s() kan bara applicerar på en sträng eller ett numeriskt värde" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" +msgstr "argumentet \"%s\" till jsonpaths elementmetod .%s() är ogiltig för typen numeric" + +#: utils/adt/jsonpath_exec.c:1487 +#, c-format +msgid "precision of jsonpath item method .%s() is out of range for type integer" +msgstr "precisionen för jsonpaths elementmetod .%s() är utanför giltigt intervall för typen integer" + +#: utils/adt/jsonpath_exec.c:1501 +#, c-format +msgid "scale of jsonpath item method .%s() is out of range for type integer" +msgstr "skalan för jsonpaths elementmetod .%s() är utanför giltigt intervall för typen integer" + +#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 +#, c-format +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type integer" +msgstr "argumentet \"%s\" till jsonpaths elementmetod .%s() är ogiltig för typen integer" + +#: utils/adt/jsonpath_exec.c:1648 +#, c-format +msgid "jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value" +msgstr "jsonpaths elementmetod .%s() kan bara applicerars på en boolean, sträng eller ett datetime-värde" -#: utils/adt/jsonpath_exec.c:1584 +#: utils/adt/jsonpath_exec.c:2137 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "vänster operand på jsonpath-operator %s är inte ett ensamt numeriskt värde" -#: utils/adt/jsonpath_exec.c:1591 +#: utils/adt/jsonpath_exec.c:2144 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "höger operand på jsonpath-operator %s är inte ett ensamt numeriskt värde" -#: utils/adt/jsonpath_exec.c:1659 +#: utils/adt/jsonpath_exec.c:2212 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "operand till unär jsonpath-operator %s är inte ett numeriskt värde" -#: utils/adt/jsonpath_exec.c:1758 +#: utils/adt/jsonpath_exec.c:2311 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "jsonpaths elementmetod .%s() kan bara appliceras på ett numeriskt värde" -#: utils/adt/jsonpath_exec.c:1798 +#: utils/adt/jsonpath_exec.c:2357 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" -msgstr "jsonpaths elementmetod .%s() lkan bara applicerar på en sträng" +msgstr "jsonpaths elementmetod .%s() kan bara appliceras på en sträng" + +#: utils/adt/jsonpath_exec.c:2450 +#, c-format +msgid "time precision of jsonpath item method .%s() is out of range for type integer" +msgstr "tidsprecisionen till jsonpaths elementmetod .%s() är utanför giltigt intervall för typen integer" -#: utils/adt/jsonpath_exec.c:1901 +#: utils/adt/jsonpath_exec.c:2484 utils/adt/jsonpath_exec.c:2490 +#: utils/adt/jsonpath_exec.c:2517 utils/adt/jsonpath_exec.c:2545 +#: utils/adt/jsonpath_exec.c:2598 utils/adt/jsonpath_exec.c:2649 +#: utils/adt/jsonpath_exec.c:2720 #, c-format -msgid "datetime format is not recognized: \"%s\"" -msgstr "datetime-format känns inte igen: \"%s\"" +msgid "%s format is not recognized: \"%s\"" +msgstr "%s-format känns inte igen: \"%s\"" -#: utils/adt/jsonpath_exec.c:1903 +#: utils/adt/jsonpath_exec.c:2486 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "Använd ett datetime-mallargument för att ange indataformatet." -#: utils/adt/jsonpath_exec.c:1971 +#: utils/adt/jsonpath_exec.c:2679 utils/adt/jsonpath_exec.c:2760 +#, c-format +msgid "time precision of jsonpath item method .%s() is invalid" +msgstr "tidsprecisionen till jsonpaths elementmetod .%s() är ogiltigt" + +#: utils/adt/jsonpath_exec.c:2840 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "elementmetod .%s() för jsonpath kan bara appliceras på ett objekt" -#: utils/adt/jsonpath_exec.c:2153 +#: utils/adt/jsonpath_exec.c:3124 +#, c-format +msgid "could not convert value of type %s to jsonpath" +msgstr "kunde inte konvertera värde av typ %s till jsonpath" + +#: utils/adt/jsonpath_exec.c:3158 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "kunde inte hitta jsonpath-variabel \"%s\"" -#: utils/adt/jsonpath_exec.c:2417 +#: utils/adt/jsonpath_exec.c:3211 +#, c-format +msgid "\"vars\" argument is not an object" +msgstr "\"variabel\"-argumentet är inte ett objekt" + +#: utils/adt/jsonpath_exec.c:3212 +#, c-format +msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgstr "Jsonpath-parametrar skall kodas som nyckel-värde-par av \"variabel\"-objekt." + +#: utils/adt/jsonpath_exec.c:3475 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "array-index för jsonpath är inte ett ensamt numeriskt värde" -#: utils/adt/jsonpath_exec.c:2429 +#: utils/adt/jsonpath_exec.c:3487 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "array-index för jsonpath är utanför giltigt interval för integer" -#: utils/adt/jsonpath_exec.c:2606 +#: utils/adt/jsonpath_exec.c:3671 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "kan inte konvertera värde från %s till %s utan att använda tidszon" -#: utils/adt/jsonpath_exec.c:2608 +#: utils/adt/jsonpath_exec.c:3673 #, c-format msgid "Use *_tz() function for time zone support." msgstr "ANvända *_tz()-funktioner som stöder tidszon." +#: utils/adt/jsonpath_exec.c:3981 +#, c-format +msgid "JSON path expression for column \"%s\" must return single item when no wrapper is requested" +msgstr "Uttryck för JSON-sökväg för kolumn \"%s\" skall returnera exakt ett värde när wrapper inte efterfrågas" + +#: utils/adt/jsonpath_exec.c:3983 utils/adt/jsonpath_exec.c:3988 +#, c-format +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." +msgstr "Använd klausulen WITH WRAPPER för att packa SQL/JSON-poster in i en array." + +#: utils/adt/jsonpath_exec.c:3987 +#, c-format +msgid "JSON path expression in JSON_QUERY must return single item when no wrapper is requested" +msgstr "Uttryck för JSON-sökväg i JSON_QUERY skall returnera exakt ett värde när wrapper inte efterfrågas" + +#: utils/adt/jsonpath_exec.c:4045 utils/adt/jsonpath_exec.c:4069 +#, c-format +msgid "JSON path expression for column \"%s\" must return single scalar item" +msgstr "Uttryck för JSON-sökväg för kolumn \"%s\" skall returnera exakt ett skalärt värde" + +#: utils/adt/jsonpath_exec.c:4050 utils/adt/jsonpath_exec.c:4074 +#, c-format +msgid "JSON path expression in JSON_VALUE must return single scalar item" +msgstr "Uttryck för JSON-sökväg i JSON_VALUE skall returnera exakt ett skalärt värde" + #: utils/adt/levenshtein.c:132 #, c-format msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "levenshtein-argument överskrider maximala längden på %d tecken" -#: utils/adt/like.c:161 +#: utils/adt/like.c:159 #, c-format msgid "nondeterministic collations are not supported for LIKE" msgstr "ickedeterministiska jämförelser (collation) stöds inte för LIKE" -#: utils/adt/like.c:190 utils/adt/like_support.c:1024 +#: utils/adt/like.c:188 utils/adt/like_support.c:1023 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "kunde inte bestämma vilken jämförelse (collation) som skall användas för ILIKE" -#: utils/adt/like.c:202 +#: utils/adt/like.c:200 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "ickedeterministiska jämförelser (collation) stöds inte för ILIKE" @@ -25133,22 +26215,22 @@ msgstr "ickedeterministiska jämförelser (collation) stöds inte för ILIKE" msgid "LIKE pattern must not end with escape character" msgstr "LIKE-mönster för inte sluta med ett escape-tecken" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "ogiltig escape-sträng" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:802 +#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "Escape-sträng måste vara tom eller ett tecken." -#: utils/adt/like_support.c:1014 +#: utils/adt/like_support.c:1013 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "matchning utan skiftlägeskänslighet stöds inte för typen bytea" -#: utils/adt/like_support.c:1115 +#: utils/adt/like_support.c:1114 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "matching med reguljär-uttryck stöds inte för typen bytea" @@ -25158,17 +26240,17 @@ msgstr "matching med reguljär-uttryck stöds inte för typen bytea" msgid "invalid octet value in \"macaddr\" value: \"%s\"" msgstr "ogiltigt oktet-värde i \"macaddr\"-värde: \"%s\"" -#: utils/adt/mac8.c:554 +#: utils/adt/mac8.c:555 #, c-format msgid "macaddr8 data out of range to convert to macaddr" msgstr "macaddr8-data utanför giltigt intervall för att konverteras till macaddr" -#: utils/adt/mac8.c:555 +#: utils/adt/mac8.c:556 #, c-format msgid "Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr." msgstr "Bara adresser som har FF och FE som värden i 4:e och 5:e byten från vänster, till exempel xx:xx:xx:ff:fe:xx:xx:xx, är möjliga att konvertera från macaddr8 till macaddr." -#: utils/adt/mcxtfuncs.c:182 +#: utils/adt/mcxtfuncs.c:173 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %d är inte en PostgreSQL serverprocess" @@ -25207,70 +26289,70 @@ msgstr "kan vara en enkelt namn" msgid "requires AS" msgstr "kräver AS" -#: utils/adt/misc.c:853 utils/adt/misc.c:867 utils/adt/misc.c:906 -#: utils/adt/misc.c:912 utils/adt/misc.c:918 utils/adt/misc.c:941 +#: utils/adt/misc.c:897 utils/adt/misc.c:911 utils/adt/misc.c:950 +#: utils/adt/misc.c:956 utils/adt/misc.c:962 utils/adt/misc.c:985 #, c-format msgid "string is not a valid identifier: \"%s\"" msgstr "sträng är inte en giltig identifierare: \"%s\"" -#: utils/adt/misc.c:855 +#: utils/adt/misc.c:899 #, c-format msgid "String has unclosed double quotes." msgstr "Sträng har ej avslutade dubbla citattecken." -#: utils/adt/misc.c:869 +#: utils/adt/misc.c:913 #, c-format msgid "Quoted identifier must not be empty." msgstr "Citerad identifierare får inte vara tom." -#: utils/adt/misc.c:908 +#: utils/adt/misc.c:952 #, c-format msgid "No valid identifier before \".\"." msgstr "Ingen giltig indentifierare innan \".\"." -#: utils/adt/misc.c:914 +#: utils/adt/misc.c:958 #, c-format msgid "No valid identifier after \".\"." msgstr "Ingen giltig identifierare efter \".\"." -#: utils/adt/misc.c:974 +#: utils/adt/misc.c:1018 #, c-format msgid "log format \"%s\" is not supported" msgstr "loggformat \"%s\" stöds inte" -#: utils/adt/misc.c:975 +#: utils/adt/misc.c:1019 #, c-format msgid "The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\"." msgstr "Loggformat som stöds är \"stderr\", \"csvlog\" och \"jsonlog\"." -#: utils/adt/multirangetypes.c:151 utils/adt/multirangetypes.c:164 -#: utils/adt/multirangetypes.c:193 utils/adt/multirangetypes.c:267 -#: utils/adt/multirangetypes.c:291 +#: utils/adt/multirangetypes.c:150 utils/adt/multirangetypes.c:163 +#: utils/adt/multirangetypes.c:192 utils/adt/multirangetypes.c:266 +#: utils/adt/multirangetypes.c:290 #, c-format msgid "malformed multirange literal: \"%s\"" msgstr "trasig multirange-litteral: \"%s\"" -#: utils/adt/multirangetypes.c:153 +#: utils/adt/multirangetypes.c:152 #, c-format msgid "Missing left brace." msgstr "Saknar vänster krullparentes" -#: utils/adt/multirangetypes.c:195 +#: utils/adt/multirangetypes.c:194 #, c-format msgid "Expected range start." msgstr "Förväntade range-start" -#: utils/adt/multirangetypes.c:269 +#: utils/adt/multirangetypes.c:268 #, c-format msgid "Expected comma or end of multirange." msgstr "Oväntat komma eller slut på multirange." -#: utils/adt/multirangetypes.c:982 +#: utils/adt/multirangetypes.c:981 #, c-format msgid "multiranges cannot be constructed from multidimensional arrays" msgstr "multiranges kan inte skapas från en multidimensionell array" -#: utils/adt/multirangetypes.c:1008 +#: utils/adt/multirangetypes.c:1007 #, c-format msgid "multirange values cannot contain null members" msgstr "multirange-värden kan inte innehålla null-medlemmar" @@ -25349,112 +26431,138 @@ msgstr "resultatet är utanför giltigt intervall" msgid "cannot subtract inet values of different sizes" msgstr "kan inte subtrahera inet-värden av olika storlek" -#: utils/adt/numeric.c:785 utils/adt/numeric.c:3643 utils/adt/numeric.c:7131 -#: utils/adt/numeric.c:7334 utils/adt/numeric.c:7806 utils/adt/numeric.c:10501 -#: utils/adt/numeric.c:10975 utils/adt/numeric.c:11069 -#: utils/adt/numeric.c:11203 +#: utils/adt/numeric.c:793 utils/adt/numeric.c:3659 utils/adt/numeric.c:7216 +#: utils/adt/numeric.c:7419 utils/adt/numeric.c:7891 utils/adt/numeric.c:10586 +#: utils/adt/numeric.c:11061 utils/adt/numeric.c:11155 +#: utils/adt/numeric.c:11290 #, c-format msgid "value overflows numeric format" msgstr "overflow på värde i formatet numeric" -#: utils/adt/numeric.c:1098 +#: utils/adt/numeric.c:1106 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "ogiltigt tecken i externt \"numric\"-värde" -#: utils/adt/numeric.c:1104 +#: utils/adt/numeric.c:1112 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "ogiltig skala i externt \"numeric\"-värde" -#: utils/adt/numeric.c:1113 +#: utils/adt/numeric.c:1121 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "felaktig siffra i externt numeriskt (\"numeric\") värde " -#: utils/adt/numeric.c:1328 utils/adt/numeric.c:1342 +#: utils/adt/numeric.c:1336 utils/adt/numeric.c:1350 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "Precisionen %d för NUMERIC måste vara mellan 1 och %d" -#: utils/adt/numeric.c:1333 +#: utils/adt/numeric.c:1341 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "Skalan %d för NUMERIC måste vara mellan %d och %d" -#: utils/adt/numeric.c:1351 +#: utils/adt/numeric.c:1359 #, c-format msgid "invalid NUMERIC type modifier" msgstr "ogiltig typmodifierare för NUMERIC" -#: utils/adt/numeric.c:1709 +#: utils/adt/numeric.c:1725 #, c-format msgid "start value cannot be NaN" msgstr "startvärde får inte vara NaN" -#: utils/adt/numeric.c:1713 +#: utils/adt/numeric.c:1729 #, c-format msgid "start value cannot be infinity" msgstr "startvärde får inte vara oändligt" -#: utils/adt/numeric.c:1720 +#: utils/adt/numeric.c:1736 #, c-format msgid "stop value cannot be NaN" msgstr "stoppvärde får inte vara NaN" -#: utils/adt/numeric.c:1724 +#: utils/adt/numeric.c:1740 #, c-format msgid "stop value cannot be infinity" msgstr "stoppvärde får inte vara oändligt" -#: utils/adt/numeric.c:1737 +#: utils/adt/numeric.c:1753 #, c-format msgid "step size cannot be NaN" msgstr "stegstorlek får inte vara NaN" -#: utils/adt/numeric.c:1741 +#: utils/adt/numeric.c:1757 #, c-format msgid "step size cannot be infinity" msgstr "stegstorlek får inte vara oändligt" -#: utils/adt/numeric.c:3633 +#: utils/adt/numeric.c:3649 #, c-format msgid "factorial of a negative number is undefined" msgstr "fakultet av ett negativt tal är odefinierat" -#: utils/adt/numeric.c:4366 utils/adt/numeric.c:4446 utils/adt/numeric.c:4487 -#: utils/adt/numeric.c:4683 +#: utils/adt/numeric.c:4256 +#, c-format +msgid "lower bound cannot be NaN" +msgstr "undre gräns kan inte vara NaN" + +#: utils/adt/numeric.c:4260 +#, c-format +msgid "lower bound cannot be infinity" +msgstr "undre gräns kan inte vara oändlig" + +#: utils/adt/numeric.c:4267 +#, c-format +msgid "upper bound cannot be NaN" +msgstr "övre gräns kan inte vara NaN" + +#: utils/adt/numeric.c:4271 +#, c-format +msgid "upper bound cannot be infinity" +msgstr "övre gräns kan inte vara oändlig" + +#: utils/adt/numeric.c:4432 utils/adt/numeric.c:4520 utils/adt/numeric.c:4580 +#: utils/adt/numeric.c:4776 #, c-format msgid "cannot convert NaN to %s" msgstr "kan inte konvertera NaN till %s" -#: utils/adt/numeric.c:4370 utils/adt/numeric.c:4450 utils/adt/numeric.c:4491 -#: utils/adt/numeric.c:4687 +#: utils/adt/numeric.c:4436 utils/adt/numeric.c:4524 utils/adt/numeric.c:4584 +#: utils/adt/numeric.c:4780 #, c-format msgid "cannot convert infinity to %s" msgstr "kan inte konvertera oändlighet till %s" -#: utils/adt/numeric.c:4696 +#: utils/adt/numeric.c:4789 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn är utanför giltigt intervall" -#: utils/adt/numeric.c:7896 utils/adt/numeric.c:7947 +#: utils/adt/numeric.c:7981 utils/adt/numeric.c:8032 #, c-format msgid "numeric field overflow" msgstr "overflow i numeric-fält" -#: utils/adt/numeric.c:7897 +#: utils/adt/numeric.c:7982 #, c-format msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d." msgstr "Ett fält med precision %d, skala %d måste avrundas till ett absolut värde mindre än %s%d." -#: utils/adt/numeric.c:7948 +#: utils/adt/numeric.c:8033 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "Ett fält med precision %d, skala %d kan inte innehålla ett oändligt värde." -#: utils/adt/oid.c:216 +#: utils/adt/numeric.c:11359 utils/adt/pseudorandomfuncs.c:135 +#: utils/adt/pseudorandomfuncs.c:159 +#, c-format +msgid "lower bound must be less than or equal to upper bound" +msgstr "undre gräns måste vara mindre eller lika med övre gräns" + +#: utils/adt/oid.c:217 #, c-format msgid "invalid oidvector data" msgstr "ogiltig oidvector-data" @@ -25484,306 +26592,317 @@ msgstr "efterfrågat tecken är för stort för kodning: %u" msgid "requested character not valid for encoding: %u" msgstr "efterfrågat tecken är inte giltigt för kodning: %u" -#: utils/adt/orderedsetaggs.c:448 utils/adt/orderedsetaggs.c:553 -#: utils/adt/orderedsetaggs.c:693 +#: utils/adt/orderedsetaggs.c:446 utils/adt/orderedsetaggs.c:551 +#: utils/adt/orderedsetaggs.c:691 #, c-format msgid "percentile value %g is not between 0 and 1" msgstr "percentil-värde %g är inte mellan 0 och 1" -#: utils/adt/pg_locale.c:1410 +#: utils/adt/pg_locale.c:326 utils/adt/pg_locale.c:358 +#, c-format +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "lokalnamn \"%s\" innehåller tecken som ej är ASCII" + +#: utils/adt/pg_locale.c:1507 #, c-format msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" msgstr "kunde inte öppna jämförelse för lokal \"%s\" med regler \"%s\": %s" -#: utils/adt/pg_locale.c:1421 utils/adt/pg_locale.c:2831 -#: utils/adt/pg_locale.c:2904 +#: utils/adt/pg_locale.c:1518 utils/adt/pg_locale.c:2992 +#: utils/adt/pg_locale.c:3065 #, c-format msgid "ICU is not supported in this build" msgstr "ICU stöds inte av detta bygge" -#: utils/adt/pg_locale.c:1450 +#: utils/adt/pg_locale.c:1546 #, c-format msgid "could not create locale \"%s\": %m" msgstr "kunde inte skapa locale \"%s\": %m" -#: utils/adt/pg_locale.c:1453 +#: utils/adt/pg_locale.c:1549 #, c-format msgid "The operating system could not find any locale data for the locale name \"%s\"." msgstr "Operativsystemet kunde inte hitta någon lokaldata för lokalnamnet \"%s\"." -#: utils/adt/pg_locale.c:1568 +#: utils/adt/pg_locale.c:1670 #, c-format msgid "collations with different collate and ctype values are not supported on this platform" msgstr "jämförelser (collations) med olika collate- och ctype-värden stöds inte på denna plattform" -#: utils/adt/pg_locale.c:1577 -#, c-format -msgid "collation provider LIBC is not supported on this platform" -msgstr "leverantören LIBC för jämförelse (collation) stöds inte på denna plattform" - -#: utils/adt/pg_locale.c:1618 +#: utils/adt/pg_locale.c:1717 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "jämförelse (collation) \"%s\" har ingen version men en version har lagrats" -#: utils/adt/pg_locale.c:1624 +#: utils/adt/pg_locale.c:1723 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "jämförelse (collation) \"%s\" har en version som inte matchar" -#: utils/adt/pg_locale.c:1626 +#: utils/adt/pg_locale.c:1725 #, c-format msgid "The collation in the database was created using version %s, but the operating system provides version %s." msgstr "Jämförelsen (collation) i databasen har skapats med version %s men operativsystemet har version %s." -#: utils/adt/pg_locale.c:1629 +#: utils/adt/pg_locale.c:1728 #, c-format msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." msgstr "Bygg om alla objekt som påverkas av denna jämförelse (collation) och kör ALTER COLLATION %s REFRESH VERSION eller bygg PostgreSQL med rätt bibliotekversion." -#: utils/adt/pg_locale.c:1695 +#: utils/adt/pg_locale.c:1772 utils/adt/pg_locale.c:2556 +#: utils/adt/pg_locale.c:2581 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "ogiltigt lokalnamn \"%s\" för inbyggd leverantör" + +#: utils/adt/pg_locale.c:1814 #, c-format msgid "could not load locale \"%s\"" msgstr "kunde inte skapa locale \"%s\"" -#: utils/adt/pg_locale.c:1720 +#: utils/adt/pg_locale.c:1839 #, c-format msgid "could not get collation version for locale \"%s\": error code %lu" msgstr "kunde inte hitta jämförelseversion (collation) för lokal \"%s\": felkod %lu" -#: utils/adt/pg_locale.c:1776 utils/adt/pg_locale.c:1789 +#: utils/adt/pg_locale.c:1895 utils/adt/pg_locale.c:1908 #, c-format msgid "could not convert string to UTF-16: error code %lu" msgstr "kunde inte konvertera sträng till UTF-16: felkod %lu" -#: utils/adt/pg_locale.c:1803 +#: utils/adt/pg_locale.c:1920 #, c-format msgid "could not compare Unicode strings: %m" msgstr "kunde inte jämföra Unicode-strängar: %m" -#: utils/adt/pg_locale.c:1984 +#: utils/adt/pg_locale.c:2094 #, c-format msgid "collation failed: %s" msgstr "jämförelse misslyckades: %s" -#: utils/adt/pg_locale.c:2205 utils/adt/pg_locale.c:2237 +#: utils/adt/pg_locale.c:2313 utils/adt/pg_locale.c:2345 #, c-format msgid "sort key generation failed: %s" msgstr "generering av sorteringsnyckel misslyckades: %s" -#: utils/adt/pg_locale.c:2474 +#: utils/adt/pg_locale.c:2635 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "kunde inte härleda språk från lokalen \"%s\": %s" -#: utils/adt/pg_locale.c:2495 utils/adt/pg_locale.c:2511 +#: utils/adt/pg_locale.c:2656 utils/adt/pg_locale.c:2672 #, c-format msgid "could not open collator for locale \"%s\": %s" msgstr "kunde inte öppna jämförelse för lokal \"%s\": %s" -#: utils/adt/pg_locale.c:2536 +#: utils/adt/pg_locale.c:2697 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "kodning \"%s\" stöds inte av ICU" -#: utils/adt/pg_locale.c:2543 +#: utils/adt/pg_locale.c:2704 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "kunde inte öppna ICU-konverterare för kodning \"%s\": %s" -#: utils/adt/pg_locale.c:2561 utils/adt/pg_locale.c:2580 -#: utils/adt/pg_locale.c:2636 utils/adt/pg_locale.c:2647 +#: utils/adt/pg_locale.c:2722 utils/adt/pg_locale.c:2741 +#: utils/adt/pg_locale.c:2797 utils/adt/pg_locale.c:2808 #, c-format msgid "%s failed: %s" msgstr "%s misslyckades: %s" -#: utils/adt/pg_locale.c:2822 +#: utils/adt/pg_locale.c:2983 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "kunde inte konvertera lokalnamn \"%s\" till språktagg: %s" -#: utils/adt/pg_locale.c:2863 +#: utils/adt/pg_locale.c:3024 #, c-format msgid "could not get language from ICU locale \"%s\": %s" msgstr "kunde inte härleda språk från ICU-lokalen \"%s\": %s" -#: utils/adt/pg_locale.c:2865 utils/adt/pg_locale.c:2894 +#: utils/adt/pg_locale.c:3026 utils/adt/pg_locale.c:3055 #, c-format msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." msgstr "För att stänga av validering av ICU-lokal, sätt parameter \"%s\" till \"%s\"" -#: utils/adt/pg_locale.c:2892 +#: utils/adt/pg_locale.c:3053 #, c-format msgid "ICU locale \"%s\" has unknown language \"%s\"" msgstr "ICU-lokalen \"%s\" har ett okänt språk \"%s\"" -#: utils/adt/pg_locale.c:3073 +#: utils/adt/pg_locale.c:3204 #, c-format msgid "invalid multibyte character for locale" msgstr "ogiltigt multibyte-tecken för lokalen" -#: utils/adt/pg_locale.c:3074 +#: utils/adt/pg_locale.c:3205 #, c-format msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding." msgstr "Serverns LC_CTYPE-lokal är troligen inkompatibel med databasens teckenkodning." -#: utils/adt/pg_lsn.c:263 +#: utils/adt/pg_lsn.c:262 #, c-format msgid "cannot add NaN to pg_lsn" msgstr "kan inte addera NaN till pg_lsn" -#: utils/adt/pg_lsn.c:297 +#: utils/adt/pg_lsn.c:296 #, c-format msgid "cannot subtract NaN from pg_lsn" msgstr "kan inte subtrahera Nan från pg_lsn" -#: utils/adt/pg_upgrade_support.c:29 +#: utils/adt/pg_upgrade_support.c:39 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "funktionen kan bara anropas när servern är i binärt uppgraderingsläge" -#: utils/adt/pgstatfuncs.c:254 +#: utils/adt/pgstatfuncs.c:252 #, c-format msgid "invalid command name: \"%s\"" msgstr "ogiltigt kommandonamn: \"%s\"" -#: utils/adt/pgstatfuncs.c:1774 +#: utils/adt/pgstatfuncs.c:1739 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "okänt återställningsmål \"%s\"" -#: utils/adt/pgstatfuncs.c:1775 +#: utils/adt/pgstatfuncs.c:1740 #, c-format -msgid "Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or \"wal\"." -msgstr "Målet måste vara \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\" eller \"wal\"." +msgid "Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"." +msgstr "Målet måste vara \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\" eller \"wal\"." -#: utils/adt/pgstatfuncs.c:1857 +#: utils/adt/pgstatfuncs.c:1822 #, c-format msgid "invalid subscription OID %u" msgstr "ogiltigt prenumerations-OID: %u" -#: utils/adt/pseudotypes.c:58 utils/adt/pseudotypes.c:92 +#: utils/adt/pseudorandomfuncs.c:69 +#, c-format +msgid "setseed parameter %g is out of allowed range [-1,1]" +msgstr "setseed-parameter %g är utanför giltigt intervall [-1,1]" + +#: utils/adt/pseudotypes.c:55 utils/adt/pseudotypes.c:89 #, c-format msgid "cannot display a value of type %s" msgstr "kan inte visa ett värde av typ %s" -#: utils/adt/pseudotypes.c:310 +#: utils/adt/pseudotypes.c:307 #, c-format msgid "cannot accept a value of a shell type" msgstr "kan inte acceptera ett värde av typen shell" -#: utils/adt/pseudotypes.c:320 +#: utils/adt/pseudotypes.c:317 #, c-format msgid "cannot display a value of a shell type" msgstr "kan inte visa ett värde av typen shell" -#: utils/adt/rangetypes.c:415 +#: utils/adt/rangetypes.c:422 #, c-format msgid "range constructor flags argument must not be null" msgstr "konstruktorflaggargument till range får inte vara null" -#: utils/adt/rangetypes.c:1014 +#: utils/adt/rangetypes.c:1021 #, c-format msgid "result of range difference would not be contiguous" msgstr "resultatet av range-skillnad skulle inte vara angränsande" -#: utils/adt/rangetypes.c:1075 +#: utils/adt/rangetypes.c:1082 #, c-format msgid "result of range union would not be contiguous" msgstr "resultatet av range-union skulle inte vara angränsande" -#: utils/adt/rangetypes.c:1750 +#: utils/adt/rangetypes.c:1757 #, c-format msgid "range lower bound must be less than or equal to range upper bound" -msgstr "lägre gräns för range måste vara lägre eller lika med övre gräns för range" +msgstr "undre gräns för range måste vara lägre eller lika med övre gräns för range" -#: utils/adt/rangetypes.c:2197 utils/adt/rangetypes.c:2210 -#: utils/adt/rangetypes.c:2224 +#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 +#: utils/adt/rangetypes.c:2283 #, c-format msgid "invalid range bound flags" msgstr "ogiltig gränsflagga för range" -#: utils/adt/rangetypes.c:2198 utils/adt/rangetypes.c:2211 -#: utils/adt/rangetypes.c:2225 +#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 +#: utils/adt/rangetypes.c:2284 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "Giltiga värden är \"[]\", \"[)\", \"(]\" och \"()\"." -#: utils/adt/rangetypes.c:2293 utils/adt/rangetypes.c:2310 -#: utils/adt/rangetypes.c:2325 utils/adt/rangetypes.c:2345 -#: utils/adt/rangetypes.c:2356 utils/adt/rangetypes.c:2403 -#: utils/adt/rangetypes.c:2411 +#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 +#: utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 +#: utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "malformed range literal: \"%s\"" msgstr "trasig range-litteral: \"%s\"" -#: utils/adt/rangetypes.c:2295 +#: utils/adt/rangetypes.c:2354 #, c-format msgid "Junk after \"empty\" key word." msgstr "Skräp efter nyckelordet \"empty\"." -#: utils/adt/rangetypes.c:2312 +#: utils/adt/rangetypes.c:2371 #, c-format msgid "Missing left parenthesis or bracket." msgstr "Saknar vänster parentes eller hakparentes." -#: utils/adt/rangetypes.c:2327 +#: utils/adt/rangetypes.c:2386 #, c-format msgid "Missing comma after lower bound." -msgstr "Saknar komma efter lägre gräns." +msgstr "Saknar komma efter undre gräns." -#: utils/adt/rangetypes.c:2347 +#: utils/adt/rangetypes.c:2406 #, c-format msgid "Too many commas." msgstr "För många komman." -#: utils/adt/rangetypes.c:2358 +#: utils/adt/rangetypes.c:2417 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "Skräp efter höger parentes eller hakparentes." -#: utils/adt/regexp.c:305 utils/adt/regexp.c:1997 utils/adt/varlena.c:4270 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 #, c-format msgid "regular expression failed: %s" msgstr "reguljärt uttryck misslyckades: %s" -#: utils/adt/regexp.c:446 utils/adt/regexp.c:681 +#: utils/adt/regexp.c:445 utils/adt/regexp.c:680 #, c-format msgid "invalid regular expression option: \"%.*s\"" msgstr "ogiltigt flagga till reguljärt uttryck: \"%.*s\"" -#: utils/adt/regexp.c:683 +#: utils/adt/regexp.c:682 #, c-format msgid "If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly." msgstr "Om du menade att använda regexp_replace() med en startstartparameter så cast:a fjärde argumentet uttryckligen till integer." -#: utils/adt/regexp.c:717 utils/adt/regexp.c:726 utils/adt/regexp.c:1083 -#: utils/adt/regexp.c:1147 utils/adt/regexp.c:1156 utils/adt/regexp.c:1165 -#: utils/adt/regexp.c:1174 utils/adt/regexp.c:1854 utils/adt/regexp.c:1863 -#: utils/adt/regexp.c:1872 utils/misc/guc.c:6610 utils/misc/guc.c:6644 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 +#: utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 +#: utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 +#: utils/adt/regexp.c:1871 utils/misc/guc.c:6820 utils/misc/guc.c:6854 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "ogiltigt värde för parameter \"%s\": %d" -#: utils/adt/regexp.c:937 +#: utils/adt/regexp.c:936 #, c-format msgid "SQL regular expression may not contain more than two escape-double-quote separators" msgstr "Regulart uttryck i SQL får inte innehålla mer än två dubbelcitat-escape-separatorer" #. translator: %s is a SQL function name -#: utils/adt/regexp.c:1094 utils/adt/regexp.c:1185 utils/adt/regexp.c:1272 -#: utils/adt/regexp.c:1311 utils/adt/regexp.c:1699 utils/adt/regexp.c:1754 -#: utils/adt/regexp.c:1883 +#: utils/adt/regexp.c:1093 utils/adt/regexp.c:1184 utils/adt/regexp.c:1271 +#: utils/adt/regexp.c:1310 utils/adt/regexp.c:1698 utils/adt/regexp.c:1753 +#: utils/adt/regexp.c:1882 #, c-format msgid "%s does not support the \"global\" option" msgstr "%s stöder inte \"global\"-flaggan" -#: utils/adt/regexp.c:1313 +#: utils/adt/regexp.c:1312 #, c-format msgid "Use the regexp_matches function instead." msgstr "Använd regexp_matches-funktionen istället." -#: utils/adt/regexp.c:1501 +#: utils/adt/regexp.c:1500 #, c-format msgid "too many regular expression matches" msgstr "för många reguljära uttryck matchar" @@ -25798,8 +26917,8 @@ msgstr "mer än en funktion med namn %s" msgid "more than one operator named %s" msgstr "mer än en operator med namn %s" -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2009 utils/adt/ruleutils.c:10020 -#: utils/adt/ruleutils.c:10233 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10509 +#: utils/adt/ruleutils.c:10722 #, c-format msgid "too many arguments" msgstr "för många argument" @@ -25809,162 +26928,162 @@ msgstr "för många argument" msgid "Provide two argument types for operator." msgstr "Ange två argumenttyper för operatorn." -#: utils/adt/regproc.c:1544 utils/adt/regproc.c:1661 utils/adt/regproc.c:1790 -#: utils/adt/regproc.c:1795 utils/adt/varlena.c:3410 utils/adt/varlena.c:3415 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 +#: utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 #, c-format msgid "invalid name syntax" msgstr "ogiltig namnsyntax" -#: utils/adt/regproc.c:1904 +#: utils/adt/regproc.c:1924 #, c-format msgid "expected a left parenthesis" msgstr "förväntade en vänsterparentes" -#: utils/adt/regproc.c:1922 +#: utils/adt/regproc.c:1942 #, c-format msgid "expected a right parenthesis" msgstr "förväntade en högreparentes" -#: utils/adt/regproc.c:1941 +#: utils/adt/regproc.c:1961 #, c-format msgid "expected a type name" msgstr "förväntade ett typnamn" -#: utils/adt/regproc.c:1973 +#: utils/adt/regproc.c:1993 #, c-format msgid "improper type name" msgstr "olämpligt typnamn" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1625 -#: utils/adt/ri_triggers.c:2610 +#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 +#: utils/adt/ri_triggers.c:2601 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "insert eller update på tabell \"%s\" bryter mot främmande nyckel-villkoret \"%s\"" -#: utils/adt/ri_triggers.c:309 utils/adt/ri_triggers.c:1628 +#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MATCH FULL tillåter inte att man blandar null och icke-null-värden." -#: utils/adt/ri_triggers.c:2045 +#: utils/adt/ri_triggers.c:2036 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "funktionen \"%s\" måste köras för INSERT" -#: utils/adt/ri_triggers.c:2051 +#: utils/adt/ri_triggers.c:2042 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "funktionen \"%s\" måste köras för UPDATE" -#: utils/adt/ri_triggers.c:2057 +#: utils/adt/ri_triggers.c:2048 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "funktionen \"%s\" måste köras för DELETE" -#: utils/adt/ri_triggers.c:2080 +#: utils/adt/ri_triggers.c:2071 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "ingen pg_constraint-post för trigger \"%s\" på tabell \"%s\"" -#: utils/adt/ri_triggers.c:2082 +#: utils/adt/ri_triggers.c:2073 #, c-format msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT." msgstr "Ta bort denna trigger för referensiell integritet och dess kollegor, gör sen ALTER TABLE ADD CONSTRAINT." -#: utils/adt/ri_triggers.c:2435 +#: utils/adt/ri_triggers.c:2426 #, c-format msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result" msgstr "referentiell integritetsfråga på \"%s\" från villkor \"%s\" på \"%s\" gav oväntat resultat" -#: utils/adt/ri_triggers.c:2439 +#: utils/adt/ri_triggers.c:2430 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "Detta beror troligen på att en regel har skrivit om frågan." -#: utils/adt/ri_triggers.c:2600 +#: utils/adt/ri_triggers.c:2591 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "borttagning av partition \"%s\" bryter mot främmande nyckel-villkoret \"%s\"" -#: utils/adt/ri_triggers.c:2603 utils/adt/ri_triggers.c:2628 +#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "Nyckeln (%s)=(%s) refereras fortfarande till från tabell \"%s\"." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2605 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "Nyckel (%s)=(%s) finns inte i tabellen \"%s\"." -#: utils/adt/ri_triggers.c:2617 +#: utils/adt/ri_triggers.c:2608 #, c-format msgid "Key is not present in table \"%s\"." msgstr "Nyckeln finns inte i tabellen \"%s\"." -#: utils/adt/ri_triggers.c:2623 +#: utils/adt/ri_triggers.c:2614 #, c-format msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"" msgstr "update eller delete på tabell \"%s\" bryter mot främmande nyckel-villkoret \"%s\" för tabell \"%s\"" -#: utils/adt/ri_triggers.c:2631 +#: utils/adt/ri_triggers.c:2622 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "Nyckel refereras fortfarande till från tabell \"%s\"." -#: utils/adt/rowtypes.c:106 utils/adt/rowtypes.c:510 +#: utils/adt/rowtypes.c:105 utils/adt/rowtypes.c:509 #, c-format msgid "input of anonymous composite types is not implemented" msgstr "inläsning av annonym composite-typ är inte implementerat" -#: utils/adt/rowtypes.c:159 utils/adt/rowtypes.c:191 utils/adt/rowtypes.c:217 -#: utils/adt/rowtypes.c:228 utils/adt/rowtypes.c:286 utils/adt/rowtypes.c:297 +#: utils/adt/rowtypes.c:158 utils/adt/rowtypes.c:190 utils/adt/rowtypes.c:216 +#: utils/adt/rowtypes.c:227 utils/adt/rowtypes.c:285 utils/adt/rowtypes.c:296 #, c-format msgid "malformed record literal: \"%s\"" msgstr "felaktig postliteral: \"%s\"" -#: utils/adt/rowtypes.c:160 +#: utils/adt/rowtypes.c:159 #, c-format msgid "Missing left parenthesis." msgstr "Saknar vänster parentes" -#: utils/adt/rowtypes.c:192 +#: utils/adt/rowtypes.c:191 #, c-format msgid "Too few columns." msgstr "För få kolumner." -#: utils/adt/rowtypes.c:287 +#: utils/adt/rowtypes.c:286 #, c-format msgid "Too many columns." msgstr "För många kolumner." -#: utils/adt/rowtypes.c:298 +#: utils/adt/rowtypes.c:297 #, c-format msgid "Junk after right parenthesis." msgstr "Skräp efter höger parentes" -#: utils/adt/rowtypes.c:559 +#: utils/adt/rowtypes.c:558 #, c-format msgid "wrong number of columns: %d, expected %d" msgstr "fel antal kolumner: %d, förväntade %d" -#: utils/adt/rowtypes.c:601 +#: utils/adt/rowtypes.c:599 #, c-format msgid "binary data has type %u (%s) instead of expected %u (%s) in record column %d" msgstr "binär data har typ %u (%s) istället för förväntad %u (%s) i postkolumn %d" -#: utils/adt/rowtypes.c:668 +#: utils/adt/rowtypes.c:660 #, c-format msgid "improper binary format in record column %d" msgstr "felaktigt binärt format i postkolumn %d" -#: utils/adt/rowtypes.c:959 utils/adt/rowtypes.c:1205 utils/adt/rowtypes.c:1463 -#: utils/adt/rowtypes.c:1709 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 +#: utils/adt/rowtypes.c:1699 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "kan inte jämföra olika kolumntyper %s och %s vid postkolumn %d" -#: utils/adt/rowtypes.c:1050 utils/adt/rowtypes.c:1275 -#: utils/adt/rowtypes.c:1560 utils/adt/rowtypes.c:1745 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 +#: utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "kan inte jämföra record-typer med olika antal kolumner" @@ -25984,113 +27103,139 @@ msgstr "uttryck innehåller variabler till mer än en relation" msgid "expression contains variables" msgstr "uttryck innehåller variabler" -#: utils/adt/ruleutils.c:5227 +#: utils/adt/ruleutils.c:5246 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "regel \"%s\" har en icke stödd händelsetyp %d" -#: utils/adt/timestamp.c:112 +#: utils/adt/timestamp.c:128 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "prceision för TIMESTAMP(%d)%s kan inte vara negativ" -#: utils/adt/timestamp.c:118 +#: utils/adt/timestamp.c:134 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "precision för TIMESTAMP(%d)%s reducerad till högsta tillåtna, %d" -#: utils/adt/timestamp.c:378 +#: utils/adt/timestamp.c:394 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "timestamp(%d)-precision måste vara mellan %d och %d" -#: utils/adt/timestamp.c:496 +#: utils/adt/timestamp.c:512 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "Numeriska tidszoner måste ha \"-\" eller \"+\" som sitt första tecken." -#: utils/adt/timestamp.c:508 +#: utils/adt/timestamp.c:524 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "numerisk tidszon \"%s\" utanför giltigt intervall" -#: utils/adt/timestamp.c:609 utils/adt/timestamp.c:619 -#: utils/adt/timestamp.c:627 +#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 +#: utils/adt/timestamp.c:643 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "timestamp utanför giltigt intervall: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:728 +#: utils/adt/timestamp.c:744 #, c-format msgid "timestamp cannot be NaN" msgstr "timestamp kan inte vara NaN" -#: utils/adt/timestamp.c:746 utils/adt/timestamp.c:758 +#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "timestamp utanför giltigt intervall: \"%g\"" -#: utils/adt/timestamp.c:1065 utils/adt/timestamp.c:1098 +#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 +#: utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 +#: utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 +#: utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 +#: utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 +#: utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 +#: utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 +#: utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 +#: utils/adt/timestamp.c:3537 utils/adt/timestamp.c:3546 +#: utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 +#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 +#: utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 +#: utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 +#: utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 +#: utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 +#: utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 +#: utils/adt/timestamp.c:5097 +#, c-format +msgid "interval out of range" +msgstr "interval utanför giltigt intervall" + +#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 #, c-format msgid "invalid INTERVAL type modifier" msgstr "ogitligt modifierare för typen INTERVAL" -#: utils/adt/timestamp.c:1081 +#: utils/adt/timestamp.c:1110 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d)-precision kan inte vara negativ" -#: utils/adt/timestamp.c:1087 +#: utils/adt/timestamp.c:1116 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "INTERVAL(%d)-precision reducerad till maximalt tillåtna, %d" -#: utils/adt/timestamp.c:1473 +#: utils/adt/timestamp.c:1506 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "interval(%d)-precision måste vara mellan %d och %d" -#: utils/adt/timestamp.c:2703 -#, c-format -msgid "cannot subtract infinite timestamps" -msgstr "kan inte subtrahera oändliga tider (timestamp)" - -#: utils/adt/timestamp.c:3956 utils/adt/timestamp.c:4139 +#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 #, c-format msgid "origin out of range" msgstr "origin utanför giltigt intervall" -#: utils/adt/timestamp.c:3961 utils/adt/timestamp.c:4144 +#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#, c-format +msgid "timestamps cannot be binned into infinite intervals" +msgstr "timestamps kan inte injusteras in i oändliga intervall" + +#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "timestamps kan inte injusteras in i intervall som innehåller månader eller år" -#: utils/adt/timestamp.c:3968 utils/adt/timestamp.c:4151 +#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 #, c-format msgid "stride must be greater than zero" msgstr "\"stride\" måste vara större än noll" -#: utils/adt/timestamp.c:4434 +#: utils/adt/timestamp.c:5091 #, c-format msgid "Months usually have fractional weeks." msgstr "Månader har vanligtvis veckor som decimaltal." -#: utils/adt/trigfuncs.c:42 +#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#, c-format +msgid "step size cannot be infinite" +msgstr "stegstorlek får inte vara oändlig" + +#: utils/adt/trigfuncs.c:41 #, c-format msgid "suppress_redundant_updates_trigger: must be called as trigger" msgstr "suppress_redundant_updates_trigger: måste anropas som trigger" -#: utils/adt/trigfuncs.c:48 +#: utils/adt/trigfuncs.c:47 #, c-format msgid "suppress_redundant_updates_trigger: must be called on update" msgstr "suppress_redundant_updates_trigger: måste anropas vid update" -#: utils/adt/trigfuncs.c:54 +#: utils/adt/trigfuncs.c:53 #, c-format msgid "suppress_redundant_updates_trigger: must be called before update" msgstr "suppress_redundant_updates_trigger: måste anropas innan update" -#: utils/adt/trigfuncs.c:60 +#: utils/adt/trigfuncs.c:59 #, c-format msgid "suppress_redundant_updates_trigger: must be called for each row" msgstr "suppress_redundant_updates_trigger: måste anropas för varje rad" @@ -26105,32 +27250,32 @@ msgstr "distans i frasoperator måste vara ett heltalsvärde mellan noll och %d, msgid "no operand in tsquery: \"%s\"" msgstr "ingen operand i tsquery: \"%s\"" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "värdet är för stort i tsquery: \"%s\"" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "operanden är för lång i tsquery: \"%s\"" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "ord för långt i tsquery: \"%s\"" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "syntaxfel i tsquery: \"%s\"" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "textsökfråga innehåller inte lexem: \"%s\"" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "tsquery är för stor" @@ -26165,72 +27310,72 @@ msgstr "array med vikter får inte innehålla null-värden" msgid "weight out of range" msgstr "vikten är utanför giltigt intervall" -#: utils/adt/tsvector.c:217 +#: utils/adt/tsvector.c:216 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "ordet är för långt (%ld byte, max %ld byte)" -#: utils/adt/tsvector.c:224 +#: utils/adt/tsvector.c:223 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "strängen är för lång för tsvector (%ld byte, max %ld byte)" -#: utils/adt/tsvector_op.c:773 +#: utils/adt/tsvector_op.c:771 #, c-format msgid "lexeme array may not contain nulls" msgstr "lexem-array:en får inte innehålla null-värden" -#: utils/adt/tsvector_op.c:778 +#: utils/adt/tsvector_op.c:776 #, c-format msgid "lexeme array may not contain empty strings" msgstr "lexem-array:en får inte innehålla tomma strängar" -#: utils/adt/tsvector_op.c:847 +#: utils/adt/tsvector_op.c:845 #, c-format msgid "weight array may not contain nulls" msgstr "vikt-array:en får inte innehålla null-värden" -#: utils/adt/tsvector_op.c:871 +#: utils/adt/tsvector_op.c:869 #, c-format msgid "unrecognized weight: \"%c\"" msgstr "okänd vikt: \"%c\"" -#: utils/adt/tsvector_op.c:2601 +#: utils/adt/tsvector_op.c:2599 #, c-format msgid "ts_stat query must return one tsvector column" msgstr "ts_stat-frågan måste returnera en tsvector-kolumn" -#: utils/adt/tsvector_op.c:2790 +#: utils/adt/tsvector_op.c:2788 #, c-format msgid "tsvector column \"%s\" does not exist" msgstr "tsvector-kolumnen \"%s\" existerar inte" -#: utils/adt/tsvector_op.c:2797 +#: utils/adt/tsvector_op.c:2795 #, c-format msgid "column \"%s\" is not of tsvector type" msgstr "kolumnen \"%s\" är inte av typen tsvector" -#: utils/adt/tsvector_op.c:2809 +#: utils/adt/tsvector_op.c:2807 #, c-format msgid "configuration column \"%s\" does not exist" -msgstr "konfigurationskolumnen \"%s\" existerar inte" +msgstr "kolumnen \"%s\" för konfiguration existerar inte" -#: utils/adt/tsvector_op.c:2815 +#: utils/adt/tsvector_op.c:2813 #, c-format msgid "column \"%s\" is not of regconfig type" msgstr "kolumn \"%s\" har inte regconfig-typ" -#: utils/adt/tsvector_op.c:2822 +#: utils/adt/tsvector_op.c:2820 #, c-format msgid "configuration column \"%s\" must not be null" -msgstr "konfigurationskolumn \"%s\" får inte vara null" +msgstr "kolumn \"%s\" för konfiguration får inte vara null" -#: utils/adt/tsvector_op.c:2835 +#: utils/adt/tsvector_op.c:2833 #, c-format msgid "text search configuration name \"%s\" must be schema-qualified" -msgstr "Textsökkonfigurationsnamn \"%s\" måste vara angivet med schema" +msgstr "Konfigurationsnamn \"%s\" för textsök måste vara angivet med schema" -#: utils/adt/tsvector_op.c:2860 +#: utils/adt/tsvector_op.c:2858 #, c-format msgid "column \"%s\" is not of a character type" msgstr "kolumnen \"%s\" är inte av typen character" @@ -26250,17 +27395,17 @@ msgstr "det finns inget escape-tecken: \"%s\"" msgid "wrong position info in tsvector: \"%s\"" msgstr "fel positionsinfo i tsvector: \"%s\"" -#: utils/adt/uuid.c:413 +#: utils/adt/uuid.c:418 #, c-format msgid "could not generate random values" msgstr "kunde inte generera slumpmässiga värden" -#: utils/adt/varbit.c:110 utils/adt/varchar.c:54 +#: utils/adt/varbit.c:110 utils/adt/varchar.c:53 #, c-format msgid "length for type %s must be at least 1" msgstr "längden för typ %s måste vara minst 1" -#: utils/adt/varbit.c:115 utils/adt/varchar.c:58 +#: utils/adt/varbit.c:115 utils/adt/varchar.c:57 #, c-format msgid "length for type %s cannot exceed %d" msgstr "längden för typ %s kan inte överstiga %d" @@ -26295,9 +27440,9 @@ msgstr "ogiltig längd på extern bitsträng" msgid "bit string too long for type bit varying(%d)" msgstr "bitsträngen för lång för typen bit varying(%d)" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:908 -#: utils/adt/varlena.c:971 utils/adt/varlena.c:1128 utils/adt/varlena.c:3052 -#: utils/adt/varlena.c:3130 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 +#: utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 +#: utils/adt/varlena.c:3133 #, c-format msgid "negative substring length not allowed" msgstr "negativ substräng-läng tillåts inte" @@ -26322,337 +27467,342 @@ msgstr "kan inte XOR:a bitsträngar av olika storlek" msgid "bit index %d out of valid range (0..%d)" msgstr "bitindex %d utanför giltigt intervall (0..%d)" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3334 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 #, c-format msgid "new bit must be 0 or 1" msgstr "nya biten måste vara 0 eller 1" -#: utils/adt/varchar.c:162 utils/adt/varchar.c:313 +#: utils/adt/varchar.c:161 utils/adt/varchar.c:312 #, c-format msgid "value too long for type character(%d)" msgstr "värdet för långt för typen character (%d)" -#: utils/adt/varchar.c:476 utils/adt/varchar.c:640 +#: utils/adt/varchar.c:475 utils/adt/varchar.c:639 #, c-format msgid "value too long for type character varying(%d)" msgstr "värdet för långt för typen character varying(%d)" -#: utils/adt/varchar.c:738 utils/adt/varlena.c:1517 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "kunde inte bestämma vilken jämförelse (collation) som skall användas för strängjämförelse" -#: utils/adt/varlena.c:1227 utils/adt/varlena.c:1806 +#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "ickedeterministiska jämförelser (collation) stöds inte för substrängsökningar" -#: utils/adt/varlena.c:3218 utils/adt/varlena.c:3285 +#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "index %d utanför giltigt intervall, 0..%d" -#: utils/adt/varlena.c:3249 utils/adt/varlena.c:3321 +#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 #, c-format msgid "index %lld out of valid range, 0..%lld" msgstr "index %lld utanför giltigt intervall, 0..%lld" -#: utils/adt/varlena.c:4382 +#: utils/adt/varlena.c:4385 #, c-format msgid "field position must not be zero" msgstr "fältpositionen får inte vara noll" -#: utils/adt/varlena.c:5554 +#: utils/adt/varlena.c:5630 #, c-format msgid "unterminated format() type specifier" msgstr "icketerminerad typangivelse för format()" -#: utils/adt/varlena.c:5555 utils/adt/varlena.c:5689 utils/adt/varlena.c:5810 +#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "För ett ensamt \"%%\" använd \"%%%%\"." -#: utils/adt/varlena.c:5687 utils/adt/varlena.c:5808 +#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "okänd typspecifierare \"%.*s\" för format()" -#: utils/adt/varlena.c:5700 utils/adt/varlena.c:5757 +#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 #, c-format msgid "too few arguments for format()" msgstr "för få argument till format()" -#: utils/adt/varlena.c:5853 utils/adt/varlena.c:6035 +#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 #, c-format msgid "number is out of range" msgstr "numret är utanför giltigt intervall" -#: utils/adt/varlena.c:5916 utils/adt/varlena.c:5944 +#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "formatet anger argument 0 men argumenten är numrerade från 1" -#: utils/adt/varlena.c:5937 +#: utils/adt/varlena.c:6013 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "argumentposition för bredd måste avslutas med \"$\"" -#: utils/adt/varlena.c:5982 +#: utils/adt/varlena.c:6058 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "null-värden kan inte formatteras som SQL-identifierare" -#: utils/adt/varlena.c:6190 +#: utils/adt/varlena.c:6266 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "Unicode-normalisering kan bara utföras om server-kodningen är UTF8" -#: utils/adt/varlena.c:6203 +#: utils/adt/varlena.c:6279 #, c-format msgid "invalid normalization form: %s" msgstr "ogiltigt normaliseringsform: %s" -#: utils/adt/varlena.c:6406 utils/adt/varlena.c:6441 utils/adt/varlena.c:6476 +#: utils/adt/varlena.c:6324 +#, c-format +msgid "Unicode categorization can only be performed if server encoding is UTF8" +msgstr "Unicode-kategorisering kan bara utföras om server-kodningen är UTF8" + +#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 #, c-format msgid "invalid Unicode code point: %04X" msgstr "ogiltig Unicode-kodpunkt: %04X" -#: utils/adt/varlena.c:6506 +#: utils/adt/varlena.c:6641 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "Unicode-escapesekvenser måste vara \\XXXX, \\+XXXXXX, \\UXXXX eller \\UXXXXXXXX." -#: utils/adt/windowfuncs.c:442 +#: utils/adt/windowfuncs.c:443 #, c-format msgid "argument of ntile must be greater than zero" msgstr "argumentet till ntile måste vara större än noll" -#: utils/adt/windowfuncs.c:706 +#: utils/adt/windowfuncs.c:707 #, c-format msgid "argument of nth_value must be greater than zero" msgstr "argumentet till nth_value måste vara större än noll" -#: utils/adt/xid8funcs.c:125 +#: utils/adt/xid8funcs.c:120 #, c-format msgid "transaction ID %llu is in the future" msgstr "transaktions-ID %llu är från framtiden" -#: utils/adt/xid8funcs.c:547 +#: utils/adt/xid8funcs.c:522 #, c-format msgid "invalid external pg_snapshot data" msgstr "ogiltig extern pg_snapshot-data" -#: utils/adt/xml.c:228 +#: utils/adt/xml.c:238 #, c-format msgid "unsupported XML feature" msgstr "ej stödd XML-finess" -#: utils/adt/xml.c:229 +#: utils/adt/xml.c:239 #, c-format msgid "This functionality requires the server to be built with libxml support." msgstr "Denna funktionalitet kräver att servern byggts med libxml-support." -#: utils/adt/xml.c:248 utils/mb/mbutils.c:628 +#: utils/adt/xml.c:258 utils/mb/mbutils.c:627 #, c-format msgid "invalid encoding name \"%s\"" msgstr "ogiltigt kodningsnamn \"%s\"" -#: utils/adt/xml.c:496 utils/adt/xml.c:501 +#: utils/adt/xml.c:506 utils/adt/xml.c:511 #, c-format msgid "invalid XML comment" msgstr "ogiltigt XML-kommentar" -#: utils/adt/xml.c:660 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "inget XML-dokument" -#: utils/adt/xml.c:956 utils/adt/xml.c:979 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "ogiltig XML-processinstruktion" -#: utils/adt/xml.c:957 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "XML-processinstruktions målnamn kan inte vara \"%s\"." -#: utils/adt/xml.c:980 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "XML-processinstruktion kan inte innehålla \"?>\"." -#: utils/adt/xml.c:1059 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "xmlvalidate är inte implementerat" -#: utils/adt/xml.c:1115 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "kunde inte initiera XML-bibliotek" -#: utils/adt/xml.c:1116 +#: utils/adt/xml.c:1168 #, c-format msgid "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." msgstr "libxml2 har inkompatibel char-typ: sizeof(char)=%zu, sizeof(xmlChar)=%zu." -#: utils/adt/xml.c:1202 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "kunde inte ställa in XML-felhanterare" -#: utils/adt/xml.c:1203 +#: utils/adt/xml.c:1255 #, c-format msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with." msgstr "Detta tyder på att libxml2-versionen som används inte är kompatibel med libxml2-header-filerna som PostgreSQL byggts med." -#: utils/adt/xml.c:2189 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "Ogiltigt teckenvärde." -#: utils/adt/xml.c:2192 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "Mellanslag krävs." -#: utils/adt/xml.c:2195 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "standalone tillåter bara 'yes' eller 'no'." -#: utils/adt/xml.c:2198 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "Felaktig deklaration: saknar version." -#: utils/adt/xml.c:2201 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "Saknar kodning i textdeklaration." -#: utils/adt/xml.c:2204 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "Parsar XML-deklaration: förväntade sig '?>'" -#: utils/adt/xml.c:2207 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "Okänd libxml-felkod: %d." -#: utils/adt/xml.c:2461 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML stöder inte oändliga datumvärden." -#: utils/adt/xml.c:2483 utils/adt/xml.c:2510 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML stöder inte oändliga timestamp-värden." -#: utils/adt/xml.c:2926 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "ogiltig fråga" -#: utils/adt/xml.c:3018 +#: utils/adt/xml.c:3110 #, c-format msgid "portal \"%s\" does not return tuples" msgstr "portalen \"%s\" returnerar inga tupler" -#: utils/adt/xml.c:4270 +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "ogiltig array till XML-namnrymdmappning" -#: utils/adt/xml.c:4271 +#: utils/adt/xml.c:4363 #, c-format msgid "The array must be two-dimensional with length of the second axis equal to 2." msgstr "Arrayen måste vara tvådimensionell där längden på andra axeln är 2." -#: utils/adt/xml.c:4295 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "tomt XPath-uttryck" -#: utils/adt/xml.c:4347 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "varken namnrymdnamn eller URI får vara null" -#: utils/adt/xml.c:4354 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "kunde inte registrera XML-namnrymd med namn \"%s\" och URL \"%s\"" -#: utils/adt/xml.c:4697 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "namnrymden DEFAULT stöds inte" -#: utils/adt/xml.c:4726 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "sökvägsfilter för rad får inte vara tomma strängen" -#: utils/adt/xml.c:4757 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "sokvägsfilter för kolumn får inte vara tomma strängen" -#: utils/adt/xml.c:4901 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "mer än ett värde returnerades från kolumns XPath-uttryck" -#: utils/cache/lsyscache.c:1043 +#: utils/cache/lsyscache.c:1017 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "typomvandling från typ %s till typ %s finns inte" -#: utils/cache/lsyscache.c:2845 utils/cache/lsyscache.c:2878 -#: utils/cache/lsyscache.c:2911 utils/cache/lsyscache.c:2944 +#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 +#: utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 #, c-format msgid "type %s is only a shell" msgstr "typ %s är bara en shell-typ" -#: utils/cache/lsyscache.c:2850 +#: utils/cache/lsyscache.c:2892 #, c-format msgid "no input function available for type %s" msgstr "ingen inläsningsfunktion finns för typ %s" -#: utils/cache/lsyscache.c:2883 +#: utils/cache/lsyscache.c:2925 #, c-format msgid "no output function available for type %s" msgstr "ingen utmatningsfunktion finns för typ %s" -#: utils/cache/partcache.c:219 +#: utils/cache/partcache.c:216 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d for type %s" msgstr "operatorklass \"%s\" för accessmetod %s saknar supportfunktion %d för typ %s" -#: utils/cache/plancache.c:724 +#: utils/cache/plancache.c:747 #, c-format msgid "cached plan must not change result type" msgstr "cache:ad plan får inte ändra resultattyp" -#: utils/cache/relcache.c:3741 +#: utils/cache/relcache.c:3801 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "relfile-nummer för heap är inte satt i binärt uppgraderingsläge" -#: utils/cache/relcache.c:3749 +#: utils/cache/relcache.c:3809 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "oväntad begäran av nytt relfile-nummer i binärt uppgraderingsläge" -#: utils/cache/relcache.c:6495 +#: utils/cache/relcache.c:6539 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "kunde inte skapa initieringsfil \"%s\" för relations-cache: %m" -#: utils/cache/relcache.c:6497 +#: utils/cache/relcache.c:6541 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "Fortsätter ändå, trots att något är fel." -#: utils/cache/relcache.c:6819 +#: utils/cache/relcache.c:6871 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "kunde inte ta bort cache-fil \"%s\": %m" @@ -26662,17 +27812,17 @@ msgstr "kunde inte ta bort cache-fil \"%s\": %m" msgid "cannot PREPARE a transaction that modified relation mapping" msgstr "kan inte göra PREPARE på en transaktion som ändrat relationsmappningen" -#: utils/cache/relmapper.c:850 +#: utils/cache/relmapper.c:852 #, c-format msgid "relation mapping file \"%s\" contains invalid data" msgstr "relationsmappningsfilen \"%s\" innehåller ogiltig data" -#: utils/cache/relmapper.c:860 +#: utils/cache/relmapper.c:862 #, c-format msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "relationsmappningsfilen \"%s\" innehåller en felaktig checksumma" -#: utils/cache/typcache.c:1809 utils/fmgr/funcapi.c:566 +#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "posttypen har inte registrerats" @@ -26687,102 +27837,102 @@ msgstr "TRAP: ExceptionalCondition: fel argument i PID %d\n" msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "TRAP: misslyckad Assert(\"%s\"), Fil: \"%s\", Rad: %d, PID: %d)\n" -#: utils/error/elog.c:416 +#: utils/error/elog.c:415 #, c-format msgid "error occurred before error message processing is available\n" msgstr "fel uppstod innan processning av felmeddelande är tillgängligt\n" -#: utils/error/elog.c:2092 +#: utils/error/elog.c:2134 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "kunde inte återöppna filen \"%s\" som stderr: %m" -#: utils/error/elog.c:2105 +#: utils/error/elog.c:2147 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "kunde inte återöppna filen \"%s\" som stdout: %m" -#: utils/error/elog.c:2141 +#: utils/error/elog.c:2183 #, c-format -msgid "invalid character" -msgstr "ogiltigt tecken" +msgid "Invalid character" +msgstr "Ogiltigt tecken" -#: utils/error/elog.c:2847 utils/error/elog.c:2874 utils/error/elog.c:2890 +#: utils/error/elog.c:2889 utils/error/elog.c:2916 utils/error/elog.c:2932 msgid "[unknown]" msgstr "[okänd]" -#: utils/error/elog.c:3163 utils/error/elog.c:3484 utils/error/elog.c:3591 +#: utils/error/elog.c:3202 utils/error/elog.c:3526 utils/error/elog.c:3633 msgid "missing error text" msgstr "saknar feltext" -#: utils/error/elog.c:3166 utils/error/elog.c:3169 +#: utils/error/elog.c:3205 utils/error/elog.c:3208 #, c-format msgid " at character %d" msgstr " vid tecken %d" -#: utils/error/elog.c:3179 utils/error/elog.c:3186 +#: utils/error/elog.c:3218 utils/error/elog.c:3225 msgid "DETAIL: " msgstr "DETALJ: " -#: utils/error/elog.c:3193 +#: utils/error/elog.c:3232 msgid "HINT: " msgstr "TIPS: " -#: utils/error/elog.c:3200 +#: utils/error/elog.c:3239 msgid "QUERY: " msgstr "FRÅGA: " -#: utils/error/elog.c:3207 +#: utils/error/elog.c:3246 msgid "CONTEXT: " msgstr "KONTEXT: " -#: utils/error/elog.c:3217 +#: utils/error/elog.c:3256 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "PLATS: %s, %s:%d\n" -#: utils/error/elog.c:3224 +#: utils/error/elog.c:3263 #, c-format msgid "LOCATION: %s:%d\n" msgstr "PLATS: %s:%d\n" -#: utils/error/elog.c:3231 +#: utils/error/elog.c:3270 msgid "BACKTRACE: " msgstr "BACKTRACE: " -#: utils/error/elog.c:3243 +#: utils/error/elog.c:3282 msgid "STATEMENT: " msgstr "SATS: " -#: utils/error/elog.c:3636 +#: utils/error/elog.c:3678 msgid "DEBUG" msgstr "DEBUG" -#: utils/error/elog.c:3640 +#: utils/error/elog.c:3682 msgid "LOG" msgstr "LOGG" -#: utils/error/elog.c:3643 +#: utils/error/elog.c:3685 msgid "INFO" msgstr "INFO" -#: utils/error/elog.c:3646 +#: utils/error/elog.c:3688 msgid "NOTICE" msgstr "NOTIS" -#: utils/error/elog.c:3650 +#: utils/error/elog.c:3692 msgid "WARNING" msgstr "VARNING" -#: utils/error/elog.c:3653 +#: utils/error/elog.c:3695 msgid "ERROR" msgstr "FEL" -#: utils/error/elog.c:3656 +#: utils/error/elog.c:3698 msgid "FATAL" msgstr "FATALT" -#: utils/error/elog.c:3659 +#: utils/error/elog.c:3701 msgid "PANIC" msgstr "PANIK" @@ -26855,22 +28005,22 @@ msgstr "Magiskt block har oväntad längd eller annan paddning." msgid "incompatible library \"%s\": magic block mismatch" msgstr "inkompatibelt bibliotek \"%s\": magiskt block matchar inte" -#: utils/fmgr/dfmgr.c:492 +#: utils/fmgr/dfmgr.c:475 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "åtkomst till biblioteket \"%s\" tillåts inte" -#: utils/fmgr/dfmgr.c:518 +#: utils/fmgr/dfmgr.c:501 #, c-format msgid "invalid macro name in dynamic library path: %s" msgstr "ogiltigt macro-namn i dynamisk biblioteksökväg: %s" -#: utils/fmgr/dfmgr.c:558 +#: utils/fmgr/dfmgr.c:541 #, c-format msgid "zero-length component in parameter \"dynamic_library_path\"" msgstr "komponent med längden noll i parameter \"dynamic_library_path\"" -#: utils/fmgr/dfmgr.c:577 +#: utils/fmgr/dfmgr.c:560 #, c-format msgid "component in parameter \"dynamic_library_path\" is not an absolute path" msgstr "komponent som inte är en absolut sökväg i parameter \"dynamic_library_path\"" @@ -26895,223 +28045,213 @@ msgstr "SQL-anropbara funktioner kräver en medföljande PG_FUNCTION_INFO_V1(fun msgid "unrecognized API version %d reported by info function \"%s\"" msgstr "okänd API-version %d rapporterad av infofunktion \"%s\"" -#: utils/fmgr/fmgr.c:2080 +#: utils/fmgr/fmgr.c:2109 #, c-format msgid "operator class options info is absent in function call context" msgstr "info om operatorklassflaggor saknas i funktionens anropskontext" -#: utils/fmgr/fmgr.c:2147 +#: utils/fmgr/fmgr.c:2176 #, c-format msgid "language validation function %u called for language %u instead of %u" msgstr "språkvalideringsfunktion %u anropad för språk %u istället för %u" -#: utils/fmgr/funcapi.c:489 +#: utils/fmgr/funcapi.c:496 #, c-format msgid "could not determine actual result type for function \"%s\" declared to return type %s" msgstr "kunde inte bestämma resultattyp för funktion \"%s\" som deklarerats att returnera typ %s" -#: utils/fmgr/funcapi.c:634 +#: utils/fmgr/funcapi.c:642 #, c-format msgid "argument declared %s does not contain a range type but type %s" msgstr "argumentet deklarerad %s innehåller inte en range-typ utan typ %s" -#: utils/fmgr/funcapi.c:717 -#, c-format -msgid "could not find multirange type for data type %s" -msgstr "kunde inte hitta multirange-typ för datatyp %s" - -#: utils/fmgr/funcapi.c:1921 utils/fmgr/funcapi.c:1953 +#: utils/fmgr/funcapi.c:1929 utils/fmgr/funcapi.c:1961 #, c-format msgid "number of aliases does not match number of columns" msgstr "antalet alias matchar inte antalet kolumner" -#: utils/fmgr/funcapi.c:1947 +#: utils/fmgr/funcapi.c:1955 #, c-format msgid "no column alias was provided" msgstr "inget kolumnalias angivet" -#: utils/fmgr/funcapi.c:1971 +#: utils/fmgr/funcapi.c:1979 #, c-format msgid "could not determine row description for function returning record" msgstr "kunde inte få radbeskrivning för funktion som returnerar en record" -#: utils/init/miscinit.c:347 +#: utils/init/miscinit.c:353 #, c-format msgid "data directory \"%s\" does not exist" msgstr "databaskatalogen \"%s\" existerar inte" -#: utils/init/miscinit.c:352 +#: utils/init/miscinit.c:358 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "kunde inte läsa rättigheter på katalog \"%s\": %m" -#: utils/init/miscinit.c:360 +#: utils/init/miscinit.c:366 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "angiven datakatalog \"%s\" är inte en katalog" -#: utils/init/miscinit.c:376 +#: utils/init/miscinit.c:382 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "datakatalogen \"%s\" har fel ägare" -#: utils/init/miscinit.c:378 +#: utils/init/miscinit.c:384 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "Servern måste startas av den användare som äger datakatalogen." -#: utils/init/miscinit.c:396 +#: utils/init/miscinit.c:402 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "datakatalogen \"%s\" har felaktiga rättigheter" -#: utils/init/miscinit.c:398 +#: utils/init/miscinit.c:404 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "Rättigheterna skall vara u=rwx (0700) eller u=rwx,g=rx (0750)." -#: utils/init/miscinit.c:456 +#: utils/init/miscinit.c:462 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "kunde inte byta katalog till \"%s\": %m" -#: utils/init/miscinit.c:693 utils/misc/guc.c:3548 +#: utils/init/miscinit.c:720 utils/misc/guc.c:3650 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "kan inte sätta parameter \"%s\" från en säkerhetsbegränsad operation" -#: utils/init/miscinit.c:765 +#: utils/init/miscinit.c:807 #, c-format msgid "role with OID %u does not exist" msgstr "roll med OID %u existerar inte" -#: utils/init/miscinit.c:795 +#: utils/init/miscinit.c:853 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "roll \"%s\" tillåts inte logga in" -#: utils/init/miscinit.c:813 +#: utils/init/miscinit.c:874 #, c-format msgid "too many connections for role \"%s\"" msgstr "för många uppkopplingar för roll \"%s\"" -#: utils/init/miscinit.c:912 -#, c-format -msgid "permission denied to set session authorization" -msgstr "rättighet saknas för att sätta sessionsauktorisation" - -#: utils/init/miscinit.c:995 +#: utils/init/miscinit.c:1045 #, c-format msgid "invalid role OID: %u" msgstr "ogiltigt roll-OID: %u" -#: utils/init/miscinit.c:1142 +#: utils/init/miscinit.c:1192 #, c-format msgid "database system is shut down" msgstr "databassystemet är nedstängt" -#: utils/init/miscinit.c:1229 +#: utils/init/miscinit.c:1279 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "kan inte skapa låsfil \"%s\": %m" -#: utils/init/miscinit.c:1243 +#: utils/init/miscinit.c:1293 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "kunde inte öppna låsfil \"%s\": %m" -#: utils/init/miscinit.c:1250 +#: utils/init/miscinit.c:1300 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "kunde inte läsa låsfil \"%s\": %m" -#: utils/init/miscinit.c:1259 +#: utils/init/miscinit.c:1309 #, c-format msgid "lock file \"%s\" is empty" msgstr "låsfilen \"%s\" är tom" -#: utils/init/miscinit.c:1260 +#: utils/init/miscinit.c:1310 #, c-format msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash." msgstr "Antingen startar en annan server eller så är låsfilen kvar från en tidigare serverkrash vid uppstart." -#: utils/init/miscinit.c:1304 +#: utils/init/miscinit.c:1354 #, c-format msgid "lock file \"%s\" already exists" msgstr "låsfil med namn \"%s\" finns redan" -#: utils/init/miscinit.c:1308 +#: utils/init/miscinit.c:1358 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "Kör en annan postgres (PID %d) i datakatalogen \"%s\"?" -#: utils/init/miscinit.c:1310 +#: utils/init/miscinit.c:1360 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "Kör en annan postmaster (PID %d) i datakatalogen \"%s\"?" -#: utils/init/miscinit.c:1313 +#: utils/init/miscinit.c:1363 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "Använder en annan postgres (PID %d) uttagesfilen (socket) \"%s\"?" -#: utils/init/miscinit.c:1315 +#: utils/init/miscinit.c:1365 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "Använder en annan postmaster (PID %d) uttagesfilen (socket) \"%s\"?" -#: utils/init/miscinit.c:1366 +#: utils/init/miscinit.c:1416 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "kunde inte ta bort gammal låsfil \"%s\": %m" -#: utils/init/miscinit.c:1368 +#: utils/init/miscinit.c:1418 #, c-format msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again." msgstr "Filen verkar ha lämnats kvar av misstag, men kan inte tas bort. Ta bort den för hand och försök igen.>" -#: utils/init/miscinit.c:1405 utils/init/miscinit.c:1419 -#: utils/init/miscinit.c:1430 +#: utils/init/miscinit.c:1455 utils/init/miscinit.c:1469 +#: utils/init/miscinit.c:1480 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "kunde inte skriva låsfil \"%s\": %m" -#: utils/init/miscinit.c:1541 utils/init/miscinit.c:1683 utils/misc/guc.c:5580 +#: utils/init/miscinit.c:1591 utils/init/miscinit.c:1733 utils/misc/guc.c:5765 #, c-format msgid "could not read from file \"%s\": %m" msgstr "kunde inte läsa från fil \"%s\": %m" -#: utils/init/miscinit.c:1671 +#: utils/init/miscinit.c:1721 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "kunde inte öppna fil \"%s\": %m: fortsätter ändå" -#: utils/init/miscinit.c:1696 +#: utils/init/miscinit.c:1746 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "låsfil \"%s\" innehåller fel PID: %ld istället för %ld" -#: utils/init/miscinit.c:1735 utils/init/miscinit.c:1751 +#: utils/init/miscinit.c:1785 utils/init/miscinit.c:1801 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "\"%s\" är inte en giltigt datakatalog" -#: utils/init/miscinit.c:1737 +#: utils/init/miscinit.c:1787 #, c-format msgid "File \"%s\" is missing." msgstr "Filen \"%s\" saknas." -#: utils/init/miscinit.c:1753 +#: utils/init/miscinit.c:1803 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "Filen \"%s\" innehåller inte giltig data." -#: utils/init/miscinit.c:1755 +#: utils/init/miscinit.c:1805 #, c-format msgid "You might need to initdb." msgstr "Du kan behöva köra initdb." -#: utils/init/miscinit.c:1763 +#: utils/init/miscinit.c:1813 #, c-format msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s." msgstr "Datakatalogen har skapats av PostgreSQL version %s, som inte är kompatibel med version %s." @@ -27188,97 +28328,97 @@ msgstr "rättighet saknas för databas \"%s\"" msgid "User does not have CONNECT privilege." msgstr "Användaren har inte rättigheten CONNECT." -#: utils/init/postinit.c:386 +#: utils/init/postinit.c:389 #, c-format msgid "too many connections for database \"%s\"" msgstr "för många uppkopplingar till databasen \"%s\"" -#: utils/init/postinit.c:410 utils/init/postinit.c:417 +#: utils/init/postinit.c:413 utils/init/postinit.c:420 #, c-format msgid "database locale is incompatible with operating system" msgstr "databaslokalen är inkompatibel med operativsystemet" -#: utils/init/postinit.c:411 +#: utils/init/postinit.c:414 #, c-format msgid "The database was initialized with LC_COLLATE \"%s\", which is not recognized by setlocale()." msgstr "Databasen initierades med LC_COLLATE \"%s\" vilket inte känns igen av setlocale()." -#: utils/init/postinit.c:413 utils/init/postinit.c:420 +#: utils/init/postinit.c:416 utils/init/postinit.c:423 #, c-format msgid "Recreate the database with another locale or install the missing locale." msgstr "Återskapa databasen med en annan lokal eller installera den saknade lokalen." -#: utils/init/postinit.c:418 +#: utils/init/postinit.c:421 #, c-format msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "Databasen initierades med LC_CTYPE \"%s\", vilket inte känns igen av setlocale()." -#: utils/init/postinit.c:475 +#: utils/init/postinit.c:493 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "databasen \"%s\" har en jämförelse (collation) vars version som inte matchar" -#: utils/init/postinit.c:477 +#: utils/init/postinit.c:495 #, c-format msgid "The database was created using collation version %s, but the operating system provides version %s." msgstr "Databasen skapades med jämförelseversion %s men operativsystemet tillhandahåller version %s." -#: utils/init/postinit.c:480 +#: utils/init/postinit.c:498 #, c-format msgid "Rebuild all objects in this database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "Bygg om alla objekt i denna databas som använder standardjämförelse (collation) och kör ALTER DATABASE %s REFRESH COLLATION VERSION eller bygg PostgreSQL med rätt bibliotekversion." -#: utils/init/postinit.c:891 +#: utils/init/postinit.c:904 #, c-format msgid "no roles are defined in this database system" msgstr "inga roller är definierade i detta databassystem" -#: utils/init/postinit.c:892 +#: utils/init/postinit.c:905 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "Du borde direkt köra CREATE USER \"%s\" SUPERUSER;." -#: utils/init/postinit.c:928 +#: utils/init/postinit.c:942 #, c-format msgid "must be superuser to connect in binary upgrade mode" -msgstr "måste vara superuser för att ansluta i binärt uppgraderingsläger" +msgstr "måste vara superuser för att ansluta i binärt uppgraderingsläge" -#: utils/init/postinit.c:949 +#: utils/init/postinit.c:962 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "resterande anslutningsslottar är reserverade för roller med attributet %s" -#: utils/init/postinit.c:955 +#: utils/init/postinit.c:968 #, c-format msgid "remaining connection slots are reserved for roles with privileges of the \"%s\" role" msgstr "resterande anslutningsslottar är reserverade för roller med rättigheter från rollen \"%s\"" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:980 #, c-format msgid "permission denied to start WAL sender" msgstr "rättighet saknas för att starta WAL-skickare" -#: utils/init/postinit.c:968 +#: utils/init/postinit.c:981 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "Bara roller med attributet %s får starta en process för WAL-skickande." -#: utils/init/postinit.c:1086 +#: utils/init/postinit.c:1099 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "Det verkar precis ha tagits bort eller döpts om." -#: utils/init/postinit.c:1090 +#: utils/init/postinit.c:1103 #, c-format msgid "database %u does not exist" msgstr "databasen %u existerar inte" -#: utils/init/postinit.c:1099 +#: utils/init/postinit.c:1112 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "kan inte ansluta till ogiltig databas \"%s\"" -#: utils/init/postinit.c:1159 +#: utils/init/postinit.c:1173 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "Databasens underbibliotek \"%s\" saknas." @@ -27305,53 +28445,48 @@ msgstr "oväntat kodnings-ID %d för ISO 8859-teckenuppsättningarna" msgid "unexpected encoding ID %d for WIN character sets" msgstr "oväntat kodnings-ID %d för WIN-teckenuppsättningarna" -#: utils/mb/mbutils.c:298 utils/mb/mbutils.c:901 +#: utils/mb/mbutils.c:297 utils/mb/mbutils.c:900 #, c-format msgid "conversion between %s and %s is not supported" msgstr "konvertering mellan %s och %s stöds inte" -#: utils/mb/mbutils.c:386 -#, c-format -msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" -msgstr "standardkonverteringsfunktion för kodning \"%s\" till \"%s\" finns inte" - -#: utils/mb/mbutils.c:403 utils/mb/mbutils.c:431 utils/mb/mbutils.c:816 -#: utils/mb/mbutils.c:843 +#: utils/mb/mbutils.c:402 utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 +#: utils/mb/mbutils.c:842 #, c-format msgid "String of %d bytes is too long for encoding conversion." msgstr "Sträng på %d byte är för lång för kodningskonvertering." -#: utils/mb/mbutils.c:569 +#: utils/mb/mbutils.c:568 #, c-format msgid "invalid source encoding name \"%s\"" msgstr "ogiltigt källkodningsnamn \"%s\"" -#: utils/mb/mbutils.c:574 +#: utils/mb/mbutils.c:573 #, c-format msgid "invalid destination encoding name \"%s\"" msgstr "ogiltigt målkodningsnamn \"%s\"" -#: utils/mb/mbutils.c:714 +#: utils/mb/mbutils.c:713 #, c-format msgid "invalid byte value for encoding \"%s\": 0x%02x" msgstr "ogiltigt byte-sekvens för kodning \"%s\": 0x%02x\"" -#: utils/mb/mbutils.c:878 +#: utils/mb/mbutils.c:877 #, c-format msgid "invalid Unicode code point" msgstr "ogiltig Unicode-kodpunkt" -#: utils/mb/mbutils.c:1204 +#: utils/mb/mbutils.c:1201 #, c-format msgid "bind_textdomain_codeset failed" msgstr "bind_textdomain_codeset misslyckades" -#: utils/mb/mbutils.c:1725 +#: utils/mb/mbutils.c:1718 #, c-format msgid "invalid byte sequence for encoding \"%s\": %s" msgstr "ogiltigt byte-sekvens för kodning \"%s\": %s" -#: utils/mb/mbutils.c:1758 +#: utils/mb/mbutils.c:1751 #, c-format msgid "character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"" msgstr "tecken med byte-sekvens %s i kodning \"%s\" har inget motsvarande i kodning \"%s\"" @@ -27366,82 +28501,82 @@ msgstr "konfigurationskatalogens namn är tomt: \"%s\"" msgid "could not open configuration directory \"%s\": %m" msgstr "kunde inte öppna konfigureringskatalog \"%s\": %m" -#: utils/misc/guc.c:115 +#: utils/misc/guc.c:122 msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "Giltiga enheter för denna parameter är \"B\", \"kB\", \"MB\", \"GB\" och \"TB\"." -#: utils/misc/guc.c:152 +#: utils/misc/guc.c:159 msgid "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\"." msgstr "Giltiga enheter för denna parameter är \"us\", \"ms\", \"s\", \"min\", \"h\" och \"d\"." -#: utils/misc/guc.c:421 +#: utils/misc/guc.c:430 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "okänd konfigurationsparameter \"%s\" i fil \"%s\" rad %d" -#: utils/misc/guc.c:461 utils/misc/guc.c:3406 utils/misc/guc.c:3646 -#: utils/misc/guc.c:3744 utils/misc/guc.c:3842 utils/misc/guc.c:3966 -#: utils/misc/guc.c:4069 +#: utils/misc/guc.c:470 utils/misc/guc.c:3504 utils/misc/guc.c:3748 +#: utils/misc/guc.c:3846 utils/misc/guc.c:3944 utils/misc/guc.c:4071 +#: utils/misc/guc.c:4212 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "parameter \"%s\" kan inte ändras utan att starta om servern" -#: utils/misc/guc.c:497 +#: utils/misc/guc.c:506 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "parameter \"%s\" borttagen från konfigurationsfil, återställs till standard" -#: utils/misc/guc.c:562 +#: utils/misc/guc.c:571 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "parameter \"%s\" ändrad till \"%s\"" -#: utils/misc/guc.c:604 +#: utils/misc/guc.c:613 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "konfigurationsfil \"%s\" innehåller fel" -#: utils/misc/guc.c:609 +#: utils/misc/guc.c:618 #, c-format msgid "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "konfigurationsfil \"%s\" innehåller fel; opåverkade ändringar har utförts" -#: utils/misc/guc.c:614 +#: utils/misc/guc.c:623 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "konfigurationsfil \"%s\" innehåller fel; inga ändringar har utförts" -#: utils/misc/guc.c:1211 utils/misc/guc.c:1227 +#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "ogiltig konfigurationsparameter \"%s\"" -#: utils/misc/guc.c:1213 +#: utils/misc/guc.c:1141 #, c-format msgid "Custom parameter names must be two or more simple identifiers separated by dots." msgstr "Egenskapade parameternamn måste vara två eller fler enkla identifierare separerade med punkter." -#: utils/misc/guc.c:1229 +#: utils/misc/guc.c:1157 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\" är ett reserverat prefix." -#: utils/misc/guc.c:1243 +#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "okänd konfigurationsparameter \"%s\"" -#: utils/misc/guc.c:1765 +#: utils/misc/guc.c:1802 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: kunde inte komma åt katalogen \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: kunde inte komma åt katalogen \"%s\": %m\n" -#: utils/misc/guc.c:1770 +#: utils/misc/guc.c:1806 #, c-format msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" msgstr "Kör initdb eller pg_basebackup för att initiera en PostgreSQL-datakatalog.\n" -#: utils/misc/guc.c:1794 +#: utils/misc/guc.c:1830 #, c-format msgid "" "%s does not know where to find the server configuration file.\n" @@ -27450,12 +28585,12 @@ msgstr "" "%s vet inte var servens konfigurationsfil är.\n" "Du måste ange flaggan --config-file eller -D alternativt sätta omgivningsvariabeln PGDATA.\n" -#: utils/misc/guc.c:1817 +#: utils/misc/guc.c:1853 #, c-format -msgid "%s: could not access the server configuration file \"%s\": %s\n" -msgstr "%s: har inte åtkomst till serverns konfigureringsfil \"%s\": %s\n" +msgid "%s: could not access the server configuration file \"%s\": %m\n" +msgstr "%s: ingen åtkomst till serverns konfigureringsfil \"%s\": %m\n" -#: utils/misc/guc.c:1845 +#: utils/misc/guc.c:1881 #, c-format msgid "" "%s does not know where to find the database system data.\n" @@ -27464,7 +28599,7 @@ msgstr "" "%s vet inte var databasens systemdata är.\n" "Det kan anges med \"data_directory\" i \"%s\" eller med flaggan -D alternativt genom att sätta omgivningsvariabeln PGDATA.\n" -#: utils/misc/guc.c:1897 +#: utils/misc/guc.c:1933 #, c-format msgid "" "%s does not know where to find the \"hba\" configuration file.\n" @@ -27473,7 +28608,7 @@ msgstr "" "%s vet inte var \"hba\"-konfigurationsfilen är.\n" "Detta kan anges som \"hba_file\" i \"%s\" eller med flaggan -D alternativt genom att sätta omgivningsvariabeln PGDATA.\n" -#: utils/misc/guc.c:1928 +#: utils/misc/guc.c:1964 #, c-format msgid "" "%s does not know where to find the \"ident\" configuration file.\n" @@ -27482,121 +28617,131 @@ msgstr "" "%s vet inte var \"ident\"-konfigurationsfilen är.\n" "Detta kan anges som \"ident_file\" i \"%s\" eller med flaggan -D alternativt genom att sätta omgivningsvariabeln PGDATA.\n" -#: utils/misc/guc.c:2894 +#: utils/misc/guc.c:2943 msgid "Value exceeds integer range." msgstr "Värde överskriver heltalsintervall." -#: utils/misc/guc.c:3130 +#: utils/misc/guc.c:3185 #, c-format -msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)" -msgstr "%d%s%s är utanför giltigt intervall för parameter \"%s\" (%d .. %d)" +msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" +msgstr "%d%s%s är utanför giltigt intervall för parameter \"%s\" (%d%s%s .. %d%s%s)" -#: utils/misc/guc.c:3166 +#: utils/misc/guc.c:3226 #, c-format -msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)" -msgstr "%g%s%s är utanför giltigt intervall för parameter \"%s\" (%g .. %g)" +msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" +msgstr "%g%s%s är utanför giltigt intervall för parameter \"%s\" (%g%s%s .. %g%s%s)" -#: utils/misc/guc.c:3366 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3465 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "kan inte sätta parametrar under en parallell operation" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "parameter \"%s\" can inte sättas under en parallell operation" -#: utils/misc/guc.c:3383 utils/misc/guc.c:4530 +#: utils/misc/guc.c:3481 utils/misc/guc.c:4696 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "parameter \"%s\" kan inte ändras" -#: utils/misc/guc.c:3416 +#: utils/misc/guc.c:3514 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "parameter \"%s\" kan inte ändras nu" -#: utils/misc/guc.c:3443 utils/misc/guc.c:3501 utils/misc/guc.c:4506 -#: utils/misc/guc.c:6546 +#: utils/misc/guc.c:3541 utils/misc/guc.c:3603 utils/misc/guc.c:4671 +#: utils/misc/guc.c:6756 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "rättighet saknas för att sätta parameter \"%s\"" -#: utils/misc/guc.c:3481 +#: utils/misc/guc.c:3583 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "parameter \"%s\" kan inte ändras efter uppkopplingen startats" -#: utils/misc/guc.c:3540 +#: utils/misc/guc.c:3642 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "kan inte sätta parameter \"%s\" inom en security-definer-funktion" -#: utils/misc/guc.c:3561 +#: utils/misc/guc.c:3663 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "parametern \"%s\" kunde inte återställas" -#: utils/misc/guc.c:3568 +#: utils/misc/guc.c:3670 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "parametern \"%s\" kan inte ändras lokalt i funktioner" -#: utils/misc/guc.c:4212 utils/misc/guc.c:4259 utils/misc/guc.c:5266 +#: utils/misc/guc.c:4370 utils/misc/guc.c:4418 utils/misc/guc.c:5450 #, c-format msgid "permission denied to examine \"%s\"" msgstr "rättighet saknas för att se \"%s\"" -#: utils/misc/guc.c:4213 utils/misc/guc.c:4260 utils/misc/guc.c:5267 +#: utils/misc/guc.c:4371 utils/misc/guc.c:4419 utils/misc/guc.c:5451 #, c-format msgid "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "Bara roller med rättigheter från rollen \"%s\" får se denna parameter." -#: utils/misc/guc.c:4496 +#: utils/misc/guc.c:4629 +#, c-format +msgid "ALTER SYSTEM is not allowed in this environment" +msgstr "ALTER SYSTEM tillåts inte i denna miljö" + +#: utils/misc/guc.c:4661 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "rättighet saknas för att utföra ALTER SYSTEM RESET ALL" -#: utils/misc/guc.c:4562 +#: utils/misc/guc.c:4740 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "parametervärde till ALTER SYSTEM kan inte innehålla nyradstecken" -#: utils/misc/guc.c:4608 +#: utils/misc/guc.c:4785 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "kunde inte parsa innehållet i fil \"%s\"" -#: utils/misc/guc.c:4790 +#: utils/misc/guc.c:4967 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "försök att omdefiniera parameter \"%s\"" -#: utils/misc/guc.c:5129 +#: utils/misc/guc.c:5306 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "ogiltigt konfigurationsparameternamn \"%s\", tas bort" -#: utils/misc/guc.c:5131 +#: utils/misc/guc.c:5308 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "\"%s\" är nu ett reserverat prefix." -#: utils/misc/guc.c:6000 +#: utils/misc/guc.c:6179 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "vid sättande av parameter \"%s\" till \"%s\"" -#: utils/misc/guc.c:6169 +#: utils/misc/guc.c:6348 #, c-format msgid "parameter \"%s\" could not be set" msgstr "parameter \"%s\" kunde inte sättas" -#: utils/misc/guc.c:6259 +#: utils/misc/guc.c:6438 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "kunde inte tolka inställningen för parameter \"%s\"" -#: utils/misc/guc.c:6678 +#: utils/misc/guc.c:6888 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "ogiltigt värde för parameter \"%s\": %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "kan inte sätta parametrar under en parallell operation" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -27612,59 +28757,59 @@ msgstr "SET %s tar bara ett argument" msgid "SET requires parameter name" msgstr "SET kräver ett parameternamn" -#: utils/misc/guc_tables.c:662 +#: utils/misc/guc_tables.c:676 msgid "Ungrouped" msgstr "Ej grupperad" -#: utils/misc/guc_tables.c:664 +#: utils/misc/guc_tables.c:677 msgid "File Locations" msgstr "Filplatser" -#: utils/misc/guc_tables.c:666 +#: utils/misc/guc_tables.c:678 msgid "Connections and Authentication / Connection Settings" msgstr "Uppkopplingar och Autentisering / Uppkopplingsinställningar" -#: utils/misc/guc_tables.c:668 +#: utils/misc/guc_tables.c:679 msgid "Connections and Authentication / TCP Settings" msgstr "Uppkopplingar och Autentisering / TCP-inställningar" -#: utils/misc/guc_tables.c:670 +#: utils/misc/guc_tables.c:680 msgid "Connections and Authentication / Authentication" msgstr "Uppkopplingar och Autentisering / Autentisering" -#: utils/misc/guc_tables.c:672 +#: utils/misc/guc_tables.c:681 msgid "Connections and Authentication / SSL" msgstr "Uppkopplingar och Autentisering / SSL" -#: utils/misc/guc_tables.c:674 +#: utils/misc/guc_tables.c:682 msgid "Resource Usage / Memory" msgstr "Resursanvändning / Minne" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:683 msgid "Resource Usage / Disk" msgstr "Resursanvändning / Disk" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:684 msgid "Resource Usage / Kernel Resources" msgstr "Resursanvändning / Kärnresurser" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:685 msgid "Resource Usage / Cost-Based Vacuum Delay" msgstr "Resursanvändning / Kostnadsbaserad Vacuum-fördröjning" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:686 msgid "Resource Usage / Background Writer" msgstr "Resursanvändning / Bakgrundskrivare" -#: utils/misc/guc_tables.c:684 +#: utils/misc/guc_tables.c:687 msgid "Resource Usage / Asynchronous Behavior" msgstr "Resursanvändning / Asynkront beteende" -#: utils/misc/guc_tables.c:686 +#: utils/misc/guc_tables.c:688 msgid "Write-Ahead Log / Settings" msgstr "Write-Ahead Log / Inställningar" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:689 msgid "Write-Ahead Log / Checkpoints" msgstr "Write-Ahead Log / Checkpoint:er" @@ -27672,458 +28817,474 @@ msgstr "Write-Ahead Log / Checkpoint:er" msgid "Write-Ahead Log / Archiving" msgstr "Write-Ahead Log / Arkivering" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:691 msgid "Write-Ahead Log / Recovery" msgstr "Write-Ahead Log / Återställning" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:692 msgid "Write-Ahead Log / Archive Recovery" msgstr "Write-Ahead Log / Återställning från arkiv" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:693 msgid "Write-Ahead Log / Recovery Target" msgstr "Write-Ahead Log / Återställningsmål" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:694 +msgid "Write-Ahead Log / Summarization" +msgstr "Write-Ahead Log / Summering" + +#: utils/misc/guc_tables.c:695 msgid "Replication / Sending Servers" msgstr "Replilering / Skickande servrar" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:696 msgid "Replication / Primary Server" msgstr "Replikering / Primärserver" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:697 msgid "Replication / Standby Servers" msgstr "Replikering / Standby-servrar" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:698 msgid "Replication / Subscribers" msgstr "Replikering / Prenumeranter" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:699 msgid "Query Tuning / Planner Method Configuration" msgstr "Frågeoptimering / Planeringsmetodinställningar" -#: utils/misc/guc_tables.c:708 +#: utils/misc/guc_tables.c:700 msgid "Query Tuning / Planner Cost Constants" msgstr "Frågeoptimering / Plannerarens kostnadskonstanter" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:701 msgid "Query Tuning / Genetic Query Optimizer" msgstr "Frågeoptimering / Genetisk frågeoptimerare" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:702 msgid "Query Tuning / Other Planner Options" msgstr "Frågeoptimering / Andra planeringsinställningar" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:703 msgid "Reporting and Logging / Where to Log" msgstr "Rapportering och loggning / Logga var?" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:704 msgid "Reporting and Logging / When to Log" msgstr "Rapportering och loggning / Logga när?" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:705 msgid "Reporting and Logging / What to Log" msgstr "Rapportering och loggning / Logga vad?" -#: utils/misc/guc_tables.c:720 +#: utils/misc/guc_tables.c:706 msgid "Reporting and Logging / Process Title" msgstr "Rapportering och loggning / Processtitel" -#: utils/misc/guc_tables.c:722 +#: utils/misc/guc_tables.c:707 msgid "Statistics / Monitoring" msgstr "Statistik / Övervakning" -#: utils/misc/guc_tables.c:724 +#: utils/misc/guc_tables.c:708 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "Statistik / Ihopsamlad fråge- och index-statistik" -#: utils/misc/guc_tables.c:726 +#: utils/misc/guc_tables.c:709 msgid "Autovacuum" msgstr "Autovacuum" -#: utils/misc/guc_tables.c:728 +#: utils/misc/guc_tables.c:710 msgid "Client Connection Defaults / Statement Behavior" msgstr "Standard för klientanslutning / Satsbeteende" -#: utils/misc/guc_tables.c:730 +#: utils/misc/guc_tables.c:711 msgid "Client Connection Defaults / Locale and Formatting" msgstr "Standard för klientanslutning / Lokal och formattering" -#: utils/misc/guc_tables.c:732 +#: utils/misc/guc_tables.c:712 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "Standard för klientanslutning / Förladdning av delat bibliotek" -#: utils/misc/guc_tables.c:734 +#: utils/misc/guc_tables.c:713 msgid "Client Connection Defaults / Other Defaults" msgstr "Standard för klientanslutning / Övriga standardvärden" -#: utils/misc/guc_tables.c:736 +#: utils/misc/guc_tables.c:714 msgid "Lock Management" msgstr "Låshantering" -#: utils/misc/guc_tables.c:738 +#: utils/misc/guc_tables.c:715 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "Version och plattformskompabilitet / Tidigare PostrgreSQL-versioner" -#: utils/misc/guc_tables.c:740 +#: utils/misc/guc_tables.c:716 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "Version och plattformskompabilitet / Andra plattformar och klienter" -#: utils/misc/guc_tables.c:742 +#: utils/misc/guc_tables.c:717 msgid "Error Handling" msgstr "Felhantering" -#: utils/misc/guc_tables.c:744 +#: utils/misc/guc_tables.c:718 msgid "Preset Options" msgstr "Förinställningsflaggor" -#: utils/misc/guc_tables.c:746 +#: utils/misc/guc_tables.c:719 msgid "Customized Options" msgstr "Ändrade flaggor" -#: utils/misc/guc_tables.c:748 +#: utils/misc/guc_tables.c:720 msgid "Developer Options" msgstr "Utvecklarflaggor" -#: utils/misc/guc_tables.c:805 +#: utils/misc/guc_tables.c:775 msgid "Enables the planner's use of sequential-scan plans." msgstr "Aktiverar planerarens användning av planer med sekvensiell skanning." -#: utils/misc/guc_tables.c:815 +#: utils/misc/guc_tables.c:785 msgid "Enables the planner's use of index-scan plans." msgstr "Aktiverar planerarens användning av planer med indexskanning." -#: utils/misc/guc_tables.c:825 +#: utils/misc/guc_tables.c:795 msgid "Enables the planner's use of index-only-scan plans." msgstr "Aktiverar planerarens användning av planer med skanning av enbart index." -#: utils/misc/guc_tables.c:835 +#: utils/misc/guc_tables.c:805 msgid "Enables the planner's use of bitmap-scan plans." msgstr "Aktiverar planerarens användning av planer med bitmapskanning." -#: utils/misc/guc_tables.c:845 +#: utils/misc/guc_tables.c:815 msgid "Enables the planner's use of TID scan plans." msgstr "Aktiverar planerarens användning av planer med TID-skanning." -#: utils/misc/guc_tables.c:855 +#: utils/misc/guc_tables.c:825 msgid "Enables the planner's use of explicit sort steps." msgstr "Slår på planerarens användning av explicita sorteringssteg." -#: utils/misc/guc_tables.c:865 +#: utils/misc/guc_tables.c:835 msgid "Enables the planner's use of incremental sort steps." msgstr "Aktiverar planerarens användning av inkrementella sorteringssteg." -#: utils/misc/guc_tables.c:875 +#: utils/misc/guc_tables.c:845 msgid "Enables the planner's use of hashed aggregation plans." msgstr "Aktiverar planerarens användning av planer med hash-aggregering" -#: utils/misc/guc_tables.c:885 +#: utils/misc/guc_tables.c:855 msgid "Enables the planner's use of materialization." msgstr "Aktiverar planerarens användning av materialisering." -#: utils/misc/guc_tables.c:895 +#: utils/misc/guc_tables.c:865 msgid "Enables the planner's use of memoization." msgstr "Aktiverar planerarens användning av memoization." -#: utils/misc/guc_tables.c:905 +#: utils/misc/guc_tables.c:875 msgid "Enables the planner's use of nested-loop join plans." msgstr "Aktiverar planerarens användning av planer med nästlad loop-join," -#: utils/misc/guc_tables.c:915 +#: utils/misc/guc_tables.c:885 msgid "Enables the planner's use of merge join plans." msgstr "Aktiverar planerarens användning av merge-join-planer." -#: utils/misc/guc_tables.c:925 +#: utils/misc/guc_tables.c:895 msgid "Enables the planner's use of hash join plans." msgstr "Aktiverar planerarens användning av hash-join-planer." -#: utils/misc/guc_tables.c:935 +#: utils/misc/guc_tables.c:905 msgid "Enables the planner's use of gather merge plans." msgstr "Aktiverar planerarens användning av planer med gather-merge." -#: utils/misc/guc_tables.c:945 +#: utils/misc/guc_tables.c:915 msgid "Enables partitionwise join." msgstr "Aktiverar join per partition." -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:925 msgid "Enables partitionwise aggregation and grouping." msgstr "Aktiverar aggregering och gruppering per partition." -#: utils/misc/guc_tables.c:965 +#: utils/misc/guc_tables.c:935 msgid "Enables the planner's use of parallel append plans." msgstr "Aktiverar planerarens användning av planer med parallell append." -#: utils/misc/guc_tables.c:975 +#: utils/misc/guc_tables.c:945 msgid "Enables the planner's use of parallel hash plans." msgstr "Aktiverar planerarens användning av planer med parallell hash." -#: utils/misc/guc_tables.c:985 +#: utils/misc/guc_tables.c:955 msgid "Enables plan-time and execution-time partition pruning." msgstr "Aktiverar rensning av partitioner vid planering och vid körning." -#: utils/misc/guc_tables.c:986 +#: utils/misc/guc_tables.c:956 msgid "Allows the query planner and executor to compare partition bounds to conditions in the query to determine which partitions must be scanned." msgstr "Tillåter att frågeplaneraren och exekveraren jämför partitionsgränser med villkor i frågan för att bestämma vilka partitioner som skall skannas." -#: utils/misc/guc_tables.c:997 +#: utils/misc/guc_tables.c:967 msgid "Enables the planner's ability to produce plans that provide presorted input for ORDER BY / DISTINCT aggregate functions." msgstr "Slår på planerarens möjlighet att skapa planer som tillhandahåller försorterad indata till aggregatfunktioner med ORDER BY / DISTINCT." -#: utils/misc/guc_tables.c:1000 +#: utils/misc/guc_tables.c:970 msgid "Allows the query planner to build plans that provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." msgstr "Tillåter att planeraren kan skapa planer som tillhandahåller försorterad indata till aggregatfunktioner med en ORDER BY / DISTINCT-klausul. Om avstängd så kommer implicita sorteringar alltid utföras vid exekvering." -#: utils/misc/guc_tables.c:1012 +#: utils/misc/guc_tables.c:982 msgid "Enables the planner's use of async append plans." msgstr "Aktiverar planerarens användning av planer med async append." -#: utils/misc/guc_tables.c:1022 +#: utils/misc/guc_tables.c:992 +msgid "Enables reordering of GROUP BY keys." +msgstr "Aktiverar omkastning av nycklar i GROUP BY." + +#: utils/misc/guc_tables.c:1002 msgid "Enables genetic query optimization." msgstr "Aktiverar genetisk frågeoptimering." -#: utils/misc/guc_tables.c:1023 +#: utils/misc/guc_tables.c:1003 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "Denna algoritm försöker utföra planering utan fullständig sökning." -#: utils/misc/guc_tables.c:1034 +#: utils/misc/guc_tables.c:1017 msgid "Shows whether the current user is a superuser." msgstr "Visar om den aktuella användaren är en superuser." -#: utils/misc/guc_tables.c:1044 +#: utils/misc/guc_tables.c:1032 +msgid "Allows running the ALTER SYSTEM command." +msgstr "Tillåter att kommandot ALTER SYSTEM körs." + +#: utils/misc/guc_tables.c:1033 +msgid "Can be set to off for environments where global configuration changes should be made using a different method." +msgstr "Kan sättas till av för miljöer där global konfiguration skall hanteras på annat sätt." + +#: utils/misc/guc_tables.c:1043 msgid "Enables advertising the server via Bonjour." msgstr "Aktiverar annonsering av servern via Bonjour." -#: utils/misc/guc_tables.c:1053 +#: utils/misc/guc_tables.c:1052 msgid "Collects transaction commit time." msgstr "Samlar in tid för transaktions-commit." -#: utils/misc/guc_tables.c:1062 +#: utils/misc/guc_tables.c:1061 msgid "Enables SSL connections." msgstr "Tillåter SSL-anslutningar." -#: utils/misc/guc_tables.c:1071 -msgid "Controls whether ssl_passphrase_command is called during server reload." -msgstr "Styr hurvida ssl_passphrase_command anropas vid omladdning av server." +#: utils/misc/guc_tables.c:1070 +msgid "Controls whether \"ssl_passphrase_command\" is called during server reload." +msgstr "Styr hurvida \"ssl_passphrase_command\" anropas vid omladdning av server." -#: utils/misc/guc_tables.c:1080 +#: utils/misc/guc_tables.c:1079 msgid "Give priority to server ciphersuite order." msgstr "Ge prioritet till serverns ordning av kryptometoder." -#: utils/misc/guc_tables.c:1089 +#: utils/misc/guc_tables.c:1088 msgid "Forces synchronization of updates to disk." msgstr "Tvingar synkronisering av uppdateringar till disk." -#: utils/misc/guc_tables.c:1090 +#: utils/misc/guc_tables.c:1089 msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This ensures that a database cluster will recover to a consistent state after an operating system or hardware crash." msgstr "Servern kommer använda systemanropet fsync() på ett antal platser för att se till att uppdateringar fysiskt skrivs till disk. Detta för att säkerställa att databasklustret kan starta i ett konsistent tillstånd efter en operativsystemkrash eller hårdvarukrash." -#: utils/misc/guc_tables.c:1101 +#: utils/misc/guc_tables.c:1100 msgid "Continues processing after a checksum failure." msgstr "Fortsätter processande efter checksummefel." -#: utils/misc/guc_tables.c:1102 +#: utils/misc/guc_tables.c:1101 msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled." msgstr "Normalt vid detektion av checksummefel så rapporterar PostgreSQL felet och avbryter den aktuella transaktionen. Sätts ignore_checksum_failure till true så kommer systemet hoppa över felet (men fortfarande rapportera en varning). Detta beteende kan orsaka krasher eller andra allvarliga problem. Detta påverkas bara om checksummor är påslaget." -#: utils/misc/guc_tables.c:1116 +#: utils/misc/guc_tables.c:1115 msgid "Continues processing past damaged page headers." msgstr "Fortsätter processande efter trasiga sidhuvuden." -#: utils/misc/guc_tables.c:1117 -msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." -msgstr "Normalt vid detektion av trasiga sidhuvuden så rapporterar PostgreSQL felet och avbryter den aktuella transaktionen. Sätts zero_damaged_pages till true så kommer systemet istället rapportera en varning, nollställa den trasiga sidan samt fortsätta processa. Detta kommer förstöra data (alla rader i den trasiga sidan)." +#: utils/misc/guc_tables.c:1116 +msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting \"zero_damaged_pages\" to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." +msgstr "Normalt vid detektion av trasiga sidhuvuden så rapporterar PostgreSQL felet och avbryter den aktuella transaktionen. Sätts \"zero_damaged_pages\" till true så kommer systemet istället rapportera en varning, nollställa den trasiga sidan samt fortsätta processa. Detta kommer förstöra data (alla rader i den trasiga sidan)." -#: utils/misc/guc_tables.c:1130 +#: utils/misc/guc_tables.c:1129 msgid "Continues recovery after an invalid pages failure." msgstr "Fortsätter återställande efter fel på grund av ogiltiga sidor." -#: utils/misc/guc_tables.c:1131 -msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting ignore_invalid_pages to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." -msgstr "Normalt vid detektion av WAL-poster som refererar till ogiltiga sidor under återställning så kommer PostgreSQL att signalera ett fel på PANIC-nivå och avbryta återställningen. Sätts ignore_invalid_pages till true så kommer systemet hoppa över ogiltiga sidreferenser i WAL-poster (men fortfarande rapportera en varning) och fortsätta återställningen. Detta beteende kan orsaka krasher, dataförluster, sprida eller dölja korruption eller ge andra allvarliga problem. Detta påverkar bara under återställning eller i standby-läge." +#: utils/misc/guc_tables.c:1130 +msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." +msgstr "Normalt vid detektion av WAL-poster som refererar till ogiltiga sidor under återställning så kommer PostgreSQL att signalera ett fel på PANIC-nivå och avbryta återställningen. Sätts \"ignore_invalid_pages\" till true så kommer systemet hoppa över ogiltiga sidreferenser i WAL-poster (men fortfarande rapportera en varning) och fortsätta återställningen. Detta beteende kan orsaka krasher, dataförluster, sprida eller dölja korruption eller ge andra allvarliga problem. Detta påverkar bara under återställning eller i standby-läge." -#: utils/misc/guc_tables.c:1149 +#: utils/misc/guc_tables.c:1148 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "Skriver fulla sidor till WAL första gången de ändras efter en checkpoint." -#: utils/misc/guc_tables.c:1150 +#: utils/misc/guc_tables.c:1149 msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible." msgstr "En sidskrivning som sker vid en operativsystemkrash kan bli delvis utskriven till disk. Under återställning så kommer radändringar i WAL:en inte vara tillräckligt för att återställa datan. Denna flagga skriver ut sidor först efter att en WAL-checkpoint gjorts vilket gör att full återställning kan ske." -#: utils/misc/guc_tables.c:1163 +#: utils/misc/guc_tables.c:1162 msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification." msgstr "Skriver fulla sidor till WAL första gången de ändras efter en checkpoint, även för ickekritisk ändring." -#: utils/misc/guc_tables.c:1173 +#: utils/misc/guc_tables.c:1172 msgid "Writes zeroes to new WAL files before first use." msgstr "Skriv nollor till nya WAL-filer innan första användning." -#: utils/misc/guc_tables.c:1183 +#: utils/misc/guc_tables.c:1182 msgid "Recycles WAL files by renaming them." msgstr "Återanvänder WAL-filer genom att byta namn på dem." -#: utils/misc/guc_tables.c:1193 +#: utils/misc/guc_tables.c:1192 msgid "Logs each checkpoint." msgstr "Logga varje checkpoint." -#: utils/misc/guc_tables.c:1202 +#: utils/misc/guc_tables.c:1201 msgid "Logs each successful connection." msgstr "Logga varje lyckad anslutning." -#: utils/misc/guc_tables.c:1211 +#: utils/misc/guc_tables.c:1210 +msgid "Logs details of pre-authentication connection handshake." +msgstr "Logga detaljer om anslutningshandskakning före autentisering." + +#: utils/misc/guc_tables.c:1220 msgid "Logs end of a session, including duration." msgstr "Loggar slut på session, inklusive längden." -#: utils/misc/guc_tables.c:1220 +#: utils/misc/guc_tables.c:1229 msgid "Logs each replication command." msgstr "Loggar alla replikeringskommanon." -#: utils/misc/guc_tables.c:1229 +#: utils/misc/guc_tables.c:1238 msgid "Shows whether the running server has assertion checks enabled." msgstr "Visar om den körande servern har assert-kontroller påslagna." -#: utils/misc/guc_tables.c:1240 +#: utils/misc/guc_tables.c:1249 msgid "Terminate session on any error." msgstr "Avbryt sessionen vid fel." -#: utils/misc/guc_tables.c:1249 +#: utils/misc/guc_tables.c:1258 msgid "Reinitialize server after backend crash." msgstr "Återinitiera servern efter en backend-krash." -#: utils/misc/guc_tables.c:1258 +#: utils/misc/guc_tables.c:1267 msgid "Remove temporary files after backend crash." msgstr "Ta bort temporära filer efter en backend-krash." -#: utils/misc/guc_tables.c:1268 +#: utils/misc/guc_tables.c:1277 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "Skicka SIGABRT och inte SIGQUIT till barnprocesser efter att backend:en krashat." -#: utils/misc/guc_tables.c:1278 +#: utils/misc/guc_tables.c:1287 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "Skicka SIGABRT och inte SIGKILL till barnprocesser som fastnat." -#: utils/misc/guc_tables.c:1289 +#: utils/misc/guc_tables.c:1298 msgid "Logs the duration of each completed SQL statement." msgstr "Loggar tiden för varje avslutad SQL-sats." -#: utils/misc/guc_tables.c:1298 +#: utils/misc/guc_tables.c:1307 msgid "Logs each query's parse tree." msgstr "Loggar alla frågors parse-träd." -#: utils/misc/guc_tables.c:1307 +#: utils/misc/guc_tables.c:1316 msgid "Logs each query's rewritten parse tree." msgstr "Logga alla frågors omskrivet parse-träd." -#: utils/misc/guc_tables.c:1316 +#: utils/misc/guc_tables.c:1325 msgid "Logs each query's execution plan." msgstr "Logga alla frågors körningsplan." -#: utils/misc/guc_tables.c:1325 +#: utils/misc/guc_tables.c:1334 msgid "Indents parse and plan tree displays." msgstr "Indentera parse och planeringsträdutskrifter" -#: utils/misc/guc_tables.c:1334 +#: utils/misc/guc_tables.c:1343 msgid "Writes parser performance statistics to the server log." msgstr "Skriver parserns prestandastatistik till serverloggen." -#: utils/misc/guc_tables.c:1343 +#: utils/misc/guc_tables.c:1352 msgid "Writes planner performance statistics to the server log." msgstr "Skriver planerarens prestandastatistik till serverloggen." -#: utils/misc/guc_tables.c:1352 +#: utils/misc/guc_tables.c:1361 msgid "Writes executor performance statistics to the server log." msgstr "Skrivere exekverarens prestandastatistik till serverloggen." -#: utils/misc/guc_tables.c:1361 +#: utils/misc/guc_tables.c:1370 msgid "Writes cumulative performance statistics to the server log." msgstr "Skriver ackumulerad prestandastatistik till serverloggen." -#: utils/misc/guc_tables.c:1371 +#: utils/misc/guc_tables.c:1380 msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations." msgstr "Loggar statisik för användning av systemresurser (minne och CPU) för olika B-tree-operationer." -#: utils/misc/guc_tables.c:1383 +#: utils/misc/guc_tables.c:1392 msgid "Collects information about executing commands." msgstr "Samla information om körda kommanon." -#: utils/misc/guc_tables.c:1384 +#: utils/misc/guc_tables.c:1393 msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution." msgstr "Slår på insamling av information om det nu körande kommandot för varje session, tillsammans med klockslaget när det kommandot började köra." -#: utils/misc/guc_tables.c:1394 +#: utils/misc/guc_tables.c:1403 msgid "Collects statistics on database activity." msgstr "Samla in statistik om databasaktivitet." -#: utils/misc/guc_tables.c:1403 +#: utils/misc/guc_tables.c:1412 msgid "Collects timing statistics for database I/O activity." msgstr "Samla in timingstatistik om databasens I/O-aktivitet." -#: utils/misc/guc_tables.c:1412 +#: utils/misc/guc_tables.c:1421 msgid "Collects timing statistics for WAL I/O activity." msgstr "Samla in timingstatistik om I/O-aktivitet för WAL." -#: utils/misc/guc_tables.c:1422 +#: utils/misc/guc_tables.c:1431 msgid "Updates the process title to show the active SQL command." msgstr "Uppdaterar processtitel till att visa aktivt SQL-kommando." -#: utils/misc/guc_tables.c:1423 +#: utils/misc/guc_tables.c:1432 msgid "Enables updating of the process title every time a new SQL command is received by the server." msgstr "Slår på uppdatering av processtiteln varje gång ett nytt SQL-kommando tas emot av servern." -#: utils/misc/guc_tables.c:1432 +#: utils/misc/guc_tables.c:1441 msgid "Starts the autovacuum subprocess." msgstr "Starta autovacuum-barnprocess." -#: utils/misc/guc_tables.c:1442 +#: utils/misc/guc_tables.c:1451 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "Skapar debug-output för LISTEN och NOTIFY." -#: utils/misc/guc_tables.c:1454 +#: utils/misc/guc_tables.c:1463 msgid "Emits information about lock usage." msgstr "Visar information om låsanvändning." -#: utils/misc/guc_tables.c:1464 +#: utils/misc/guc_tables.c:1473 msgid "Emits information about user lock usage." msgstr "Visar information om användares låsanvändning." -#: utils/misc/guc_tables.c:1474 +#: utils/misc/guc_tables.c:1483 msgid "Emits information about lightweight lock usage." msgstr "Visar information om lättviktig låsanvändning." -#: utils/misc/guc_tables.c:1484 +#: utils/misc/guc_tables.c:1493 msgid "Dumps information about all current locks when a deadlock timeout occurs." msgstr "Dumpar information om alla aktuella lås när en deadlock-timeout sker." -#: utils/misc/guc_tables.c:1496 +#: utils/misc/guc_tables.c:1505 msgid "Logs long lock waits." msgstr "Loggar långa väntetider på lås." -#: utils/misc/guc_tables.c:1505 +#: utils/misc/guc_tables.c:1514 msgid "Logs standby recovery conflict waits." msgstr "Loggar väntande på återställningskonflikter i standby" -#: utils/misc/guc_tables.c:1514 +#: utils/misc/guc_tables.c:1523 msgid "Logs the host name in the connection logs." msgstr "Loggar hostnamnet i anslutningsloggen." -#: utils/misc/guc_tables.c:1515 +#: utils/misc/guc_tables.c:1524 msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty." msgstr "Som standard visar anslutningsloggen bara IP-adressen för den anslutande värden. Om du vill att värdnamnet skall visas så kan du slå på detta men beroende på hur uppsättningen av namnuppslag är gjored så kan detta ha en markant prestandapåverkan." -#: utils/misc/guc_tables.c:1526 +#: utils/misc/guc_tables.c:1535 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "Tolkar \"uttryck=NULL\" som \"uttryck IS NULL\"." -#: utils/misc/guc_tables.c:1527 +#: utils/misc/guc_tables.c:1536 msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)." msgstr "Om påslagen så kommer uttryck på formen uttryck = NULL (eller NULL = uttryck) att behandlas som uttryck IS NULL, det vill säga returnera true om uttryck evalueras till värdet null eller evalueras till false annars. Det korrekta beteendet för uttryck = NULL är att alltid returnera null (okänt)." -#: utils/misc/guc_tables.c:1539 -msgid "Enables per-database user names." -msgstr "Aktiverar användarnamn per databas." - #: utils/misc/guc_tables.c:1548 msgid "Sets the default read-only status of new transactions." msgstr "Ställer in standard read-only-status för nya transaktioner." @@ -28165,8 +29326,8 @@ msgid "WITH OIDS is no longer supported; this can only be false." msgstr "WITH OIDS stöds inte längre; denna kan bara vara false." #: utils/misc/guc_tables.c:1632 -msgid "Start a subprocess to capture stderr output and/or csvlogs into log files." -msgstr "Starta en subprocess för att fånga output från stderr och/eller csv-loggar till loggfiler." +msgid "Start a subprocess to capture stderr, csvlog and/or jsonlog into log files." +msgstr "Starta en subprocess för att fånga stderr, csvlog och/eller jsonlog till loggfiler." #: utils/misc/guc_tables.c:1641 msgid "Truncate existing log files of same name during log rotation." @@ -28217,1366 +29378,1440 @@ msgid "Sets whether to include or exclude transaction with recovery target." msgstr "Anger hurvida man skall inkludera eller exkludera transaktion för återställningmål." #: utils/misc/guc_tables.c:1778 +msgid "Starts the WAL summarizer process to enable incremental backup." +msgstr "Startar process för WAL-summering för att tillåta inkrementella backuper." + +#: utils/misc/guc_tables.c:1788 msgid "Allows connections and queries during recovery." msgstr "Tillåt anslutningar och frågor under återställning." -#: utils/misc/guc_tables.c:1788 +#: utils/misc/guc_tables.c:1798 msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts." msgstr "Tillåter feedback från en hot standby till primären för att undvika frågekonflikter." -#: utils/misc/guc_tables.c:1798 +#: utils/misc/guc_tables.c:1808 msgid "Shows whether hot standby is currently active." msgstr "Visar hurvida hot standby är aktiv för närvarande." -#: utils/misc/guc_tables.c:1809 +#: utils/misc/guc_tables.c:1819 msgid "Allows modifications of the structure of system tables." msgstr "Tillåter strukturförändringar av systemtabeller." -#: utils/misc/guc_tables.c:1820 +#: utils/misc/guc_tables.c:1830 msgid "Disables reading from system indexes." msgstr "Stänger av läsning från systemindex." -#: utils/misc/guc_tables.c:1821 +#: utils/misc/guc_tables.c:1831 msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness." msgstr "Det förhindrar inte uppdatering av index så det är helt säkert att använda. Det värsta som kan hända är att det är långsamt." -#: utils/misc/guc_tables.c:1832 +#: utils/misc/guc_tables.c:1842 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "Tillåter tabellutrymmen direkt inuti pg_tblspc, för testning" -#: utils/misc/guc_tables.c:1843 +#: utils/misc/guc_tables.c:1853 msgid "Enables backward compatibility mode for privilege checks on large objects." msgstr "Slår på bakåtkompabilitetsläge för rättighetskontroller på stora objekt." -#: utils/misc/guc_tables.c:1844 +#: utils/misc/guc_tables.c:1854 msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0." msgstr "Hoppar över rättighetskontroller vid läsning eller modifiering av stora objekt, för kompabilitet med PostgreSQL-releaser innan 9.0." -#: utils/misc/guc_tables.c:1854 +#: utils/misc/guc_tables.c:1864 msgid "When generating SQL fragments, quote all identifiers." msgstr "När SQL-fragment genereras så citera alla identifierare." -#: utils/misc/guc_tables.c:1864 +#: utils/misc/guc_tables.c:1874 msgid "Shows whether data checksums are turned on for this cluster." msgstr "Visar om datachecksummor är påslagna för detta kluster." -#: utils/misc/guc_tables.c:1875 +#: utils/misc/guc_tables.c:1885 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "Lägg till sekvensnummer till syslog-meddelanden för att undvika att duplikat tas bort." -#: utils/misc/guc_tables.c:1885 +#: utils/misc/guc_tables.c:1895 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "Dela meddelanden som skickas till syslog till egna rader och begränsa till 1024 byte." -#: utils/misc/guc_tables.c:1895 +#: utils/misc/guc_tables.c:1905 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "Bestämmer om \"Gather\" och \"Gather Merge\" också exekverar subplaner." -#: utils/misc/guc_tables.c:1896 +#: utils/misc/guc_tables.c:1906 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "Skall gather-noder också exekvera subplaner eller bara samla in tupler?" -#: utils/misc/guc_tables.c:1906 +#: utils/misc/guc_tables.c:1916 msgid "Allow JIT compilation." msgstr "Tillåt JIT-kompilering." -#: utils/misc/guc_tables.c:1917 +#: utils/misc/guc_tables.c:1927 msgid "Register JIT-compiled functions with debugger." msgstr "Registrera JIT-kompilerade funktioner hos debuggern." -#: utils/misc/guc_tables.c:1934 +#: utils/misc/guc_tables.c:1944 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "Skriv ut LLVM-bitkod för att möjliggöra JIT-debuggning." -#: utils/misc/guc_tables.c:1945 +#: utils/misc/guc_tables.c:1955 msgid "Allow JIT compilation of expressions." msgstr "Tillåt JIT-kompilering av uttryck." -#: utils/misc/guc_tables.c:1956 +#: utils/misc/guc_tables.c:1966 msgid "Register JIT-compiled functions with perf profiler." msgstr "Registrera JIT-kompilerade funktioner med perf-profilerare." -#: utils/misc/guc_tables.c:1973 +#: utils/misc/guc_tables.c:1983 msgid "Allow JIT compilation of tuple deforming." msgstr "Tillåt JIT-kompilering av tupeluppdelning." -#: utils/misc/guc_tables.c:1984 +#: utils/misc/guc_tables.c:1994 msgid "Whether to continue running after a failure to sync data files." msgstr "Hurvida vi skall fortsätta efter ett fel att synka datafiler." -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2003 msgid "Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured." msgstr "Anger hurvida en WAL-mottagare skall skapa en temporär replikeringsslot om ingen permanent slot är konfigurerad." -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2012 +msgid "Enables event triggers." +msgstr "Aktiverar händelsetriggrar." + +#: utils/misc/guc_tables.c:2013 +msgid "When enabled, event triggers will fire for all applicable statements." +msgstr "Om aktiverad så kommer händelsetriggrar anropas för alla satser där det går." + +#: utils/misc/guc_tables.c:2022 +msgid "Enables a physical standby to synchronize logical failover replication slots from the primary server." +msgstr "Tillåter att en fysisk standby synkroniserar logiska replikeringsslottar för failover från primära servern." + +#: utils/misc/guc_tables.c:2040 msgid "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "Sätter tiden vi väntar innan vi tvingar ett byte till nästa WAL-fil." -#: utils/misc/guc_tables.c:2022 +#: utils/misc/guc_tables.c:2051 msgid "Sets the amount of time to wait after authentication on connection startup." msgstr "Sätter tiden att vänta efter authentiserng vid uppstart av anslutningen." -#: utils/misc/guc_tables.c:2024 utils/misc/guc_tables.c:2658 +#: utils/misc/guc_tables.c:2053 utils/misc/guc_tables.c:2780 msgid "This allows attaching a debugger to the process." msgstr "Detta tillåter att man ansluter en debugger till processen." -#: utils/misc/guc_tables.c:2033 +#: utils/misc/guc_tables.c:2062 msgid "Sets the default statistics target." msgstr "Sätter standardstatistikmålet." -#: utils/misc/guc_tables.c:2034 +#: utils/misc/guc_tables.c:2063 msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS." msgstr "Detta gäller tabellkolumner som inte har ett kolumnspecifikt mål satt med ALTER TABLE SET STATISTICS." -#: utils/misc/guc_tables.c:2043 +#: utils/misc/guc_tables.c:2072 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "Sätter en övre gräns på FROM-listans storlek där subfrågor slås isär." -#: utils/misc/guc_tables.c:2045 +#: utils/misc/guc_tables.c:2074 msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items." msgstr "Planeraren kommer slå samman subfrågor med yttre frågor om den resulterande FROM-listan inte har fler än så här många poster." -#: utils/misc/guc_tables.c:2056 +#: utils/misc/guc_tables.c:2085 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "Sätter en övre gräns på FROM-listans storlek där JOIN-konstruktioner plattas till." -#: utils/misc/guc_tables.c:2058 +#: utils/misc/guc_tables.c:2087 msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result." msgstr "Planeraren kommer platta till explicita JOIN-konstruktioner till listor av FROM-poster när resultatet blir en lista med max så här många poster." -#: utils/misc/guc_tables.c:2069 +#: utils/misc/guc_tables.c:2098 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "Sätter en undre gräns på antal FROM-poster när GEQO används." -#: utils/misc/guc_tables.c:2079 +#: utils/misc/guc_tables.c:2108 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "GEQO: effort används som standard för andra GEQO-parametrar." -#: utils/misc/guc_tables.c:2089 +#: utils/misc/guc_tables.c:2118 msgid "GEQO: number of individuals in the population." msgstr "GEQO: antal individer i populationen." -#: utils/misc/guc_tables.c:2090 utils/misc/guc_tables.c:2100 +#: utils/misc/guc_tables.c:2119 utils/misc/guc_tables.c:2129 msgid "Zero selects a suitable default value." msgstr "Noll väljer ett lämpligt standardvärde." -#: utils/misc/guc_tables.c:2099 +#: utils/misc/guc_tables.c:2128 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: antal iterationer för algoritmen." -#: utils/misc/guc_tables.c:2111 +#: utils/misc/guc_tables.c:2140 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "Sätter tiden som väntas på ett lås innan kontroll av deadlock sker." -#: utils/misc/guc_tables.c:2122 +#: utils/misc/guc_tables.c:2151 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data." msgstr "Sätter maximal fördröjning innan frågor avbryts när en \"hot standby\"-server processar arkiverad WAL-data." -#: utils/misc/guc_tables.c:2133 +#: utils/misc/guc_tables.c:2162 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data." msgstr "Sätter maximal fördröjning innan frågor avbryts när en \"hot stanby\"-server processar strömmad WAL-data." -#: utils/misc/guc_tables.c:2144 +#: utils/misc/guc_tables.c:2173 msgid "Sets the minimum delay for applying changes during recovery." msgstr "Ställer in minsta fördröjning för att applicera ändringar under återställning." -#: utils/misc/guc_tables.c:2155 +#: utils/misc/guc_tables.c:2184 msgid "Sets the maximum interval between WAL receiver status reports to the sending server." msgstr "Sätter maximalt intervall mellan statusrapporter till skickande server från WAL-mottagaren." -#: utils/misc/guc_tables.c:2166 +#: utils/misc/guc_tables.c:2195 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "Sätter maximal väntetid för att ta emot data från skickande server." -#: utils/misc/guc_tables.c:2177 +#: utils/misc/guc_tables.c:2206 msgid "Sets the maximum number of concurrent connections." msgstr "Sätter maximalt antal samtidiga anslutningar." -#: utils/misc/guc_tables.c:2188 +#: utils/misc/guc_tables.c:2217 msgid "Sets the number of connection slots reserved for superusers." msgstr "Sätter antalet anslutningsslottar som reserverats för superusers." -#: utils/misc/guc_tables.c:2198 +#: utils/misc/guc_tables.c:2227 msgid "Sets the number of connection slots reserved for roles with privileges of pg_use_reserved_connections." msgstr "Sätter antalet anslutningsslottar som reserverats för roller med rättigheter från pg_use_reserved_connections." -#: utils/misc/guc_tables.c:2209 +#: utils/misc/guc_tables.c:2238 msgid "Amount of dynamic shared memory reserved at startup." msgstr "Mängd dynamiskt delat minne som reserveras vid uppstart" -#: utils/misc/guc_tables.c:2224 +#: utils/misc/guc_tables.c:2253 msgid "Sets the number of shared memory buffers used by the server." msgstr "Sätter antalet delade minnesbuffrar som används av servern." -#: utils/misc/guc_tables.c:2235 +#: utils/misc/guc_tables.c:2264 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "Sätter buffer-poolens storlek för VACUUM, ANALYZE och autovacuum." -#: utils/misc/guc_tables.c:2246 +#: utils/misc/guc_tables.c:2275 msgid "Shows the size of the server's main shared memory area (rounded up to the nearest MB)." msgstr "Visa storlek på serverns huvudsakliga delade minnesarea (avrundat upp till närmaste MB)." -#: utils/misc/guc_tables.c:2257 +#: utils/misc/guc_tables.c:2286 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "Visa antal stora sidor som krävs för den huvudsakliga delade minnesarean." -#: utils/misc/guc_tables.c:2258 +#: utils/misc/guc_tables.c:2287 msgid "-1 indicates that the value could not be determined." msgstr "-1 betyder att värdet inte kunde bestämmas." -#: utils/misc/guc_tables.c:2268 +#: utils/misc/guc_tables.c:2297 +msgid "Sets the size of the dedicated buffer pool used for the commit timestamp cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av commit-tidsstämplar." + +#: utils/misc/guc_tables.c:2298 utils/misc/guc_tables.c:2353 +#: utils/misc/guc_tables.c:2364 +msgid "Specify 0 to have this value determined as a fraction of shared_buffers." +msgstr "Ange 0 för att sätta detta värde till en bråkdel av shared_buffers." + +#: utils/misc/guc_tables.c:2308 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact member cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av MultiXact-medlemmar." + +#: utils/misc/guc_tables.c:2319 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact offset cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av MultiXact-offset." + +#: utils/misc/guc_tables.c:2330 +msgid "Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY message cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av LISTEN/NOTIFY-meddelande." + +#: utils/misc/guc_tables.c:2341 +msgid "Sets the size of the dedicated buffer pool used for the serializable transaction cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av serialiserbara transaktioner." + +#: utils/misc/guc_tables.c:2352 +msgid "Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används som cache för undertransaktioner." + +#: utils/misc/guc_tables.c:2363 +msgid "Sets the size of the dedicated buffer pool used for the transaction status cache." +msgstr "Sätter storlek på den dedikerade bufferpoolen som används till cache av transaktionsstatus." + +#: utils/misc/guc_tables.c:2374 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "Sätter maximalt antal temporära buffertar som används per session." -#: utils/misc/guc_tables.c:2279 +#: utils/misc/guc_tables.c:2385 msgid "Sets the TCP port the server listens on." msgstr "Sätter TCP-porten som servern lyssnar på." -#: utils/misc/guc_tables.c:2289 +#: utils/misc/guc_tables.c:2395 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Sätter accessrättigheter för Unix-domainuttag (socket)." -#: utils/misc/guc_tables.c:2290 +#: utils/misc/guc_tables.c:2396 msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Unixdomänuttag (socket) använder unix vanliga filsystemsrättigheter. Parametervärdet förväntas vara en numerisk rättighetsangivelse så som accepteras av systemanropen chmod och umask. (För att använda det vanliga oktala formatet så måste numret börja med 0 (noll).)" -#: utils/misc/guc_tables.c:2304 +#: utils/misc/guc_tables.c:2410 msgid "Sets the file permissions for log files." msgstr "Sätter filrättigheter för loggfiler." -#: utils/misc/guc_tables.c:2305 +#: utils/misc/guc_tables.c:2411 msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Parametervärdet förväntas vara en numerisk rättighetsangivelse så som accepteras av systemanropen chmod och umask. (För att använda det vanliga oktala formatet så måste numret börja med 0 (noll).)" -#: utils/misc/guc_tables.c:2319 +#: utils/misc/guc_tables.c:2425 msgid "Shows the mode of the data directory." msgstr "Visar rättigheter för datakatalog" -#: utils/misc/guc_tables.c:2320 +#: utils/misc/guc_tables.c:2426 msgid "The parameter value is a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Parametervärdet är en numerisk rättighetsangivelse så som accepteras av systemanropen chmod och umask. (För att använda det vanliga oktala formatet så måste numret börja med 0 (noll).)" -#: utils/misc/guc_tables.c:2333 +#: utils/misc/guc_tables.c:2439 msgid "Sets the maximum memory to be used for query workspaces." msgstr "Sätter maximalt minne som används för frågors arbetsyta." -#: utils/misc/guc_tables.c:2334 +#: utils/misc/guc_tables.c:2440 msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files." msgstr "Så här mycket minne kan användas av varje intern sorteringsoperation resp. hash-tabell innan temporära filer på disk börjar användas." -#: utils/misc/guc_tables.c:2346 +#: utils/misc/guc_tables.c:2457 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "Sätter det maximala minnet som får användas för underhållsoperationer." -#: utils/misc/guc_tables.c:2347 +#: utils/misc/guc_tables.c:2458 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "Detta inkluderar operationer som VACUUM och CREATE INDEX." -#: utils/misc/guc_tables.c:2357 +#: utils/misc/guc_tables.c:2468 msgid "Sets the maximum memory to be used for logical decoding." msgstr "Sätter det maximala minnet som får användas för logisk avkodning." -#: utils/misc/guc_tables.c:2358 +#: utils/misc/guc_tables.c:2469 msgid "This much memory can be used by each internal reorder buffer before spilling to disk." msgstr "Så här mycket minne kan användas av varje intern omsorteringsbuffer innan data spills till disk." -#: utils/misc/guc_tables.c:2374 +#: utils/misc/guc_tables.c:2485 msgid "Sets the maximum stack depth, in kilobytes." msgstr "Sätter det maximala stackdjupet, i kilobyte." -#: utils/misc/guc_tables.c:2385 +#: utils/misc/guc_tables.c:2496 msgid "Limits the total size of all temporary files used by each process." msgstr "Begränsar den totala storleken för alla temporära filer som används i en process." -#: utils/misc/guc_tables.c:2386 +#: utils/misc/guc_tables.c:2497 msgid "-1 means no limit." msgstr "-1 betyder ingen gräns." -#: utils/misc/guc_tables.c:2396 +#: utils/misc/guc_tables.c:2507 msgid "Vacuum cost for a page found in the buffer cache." msgstr "Vacuum-kostnad för en sida som hittas i buffer-cache:n." -#: utils/misc/guc_tables.c:2406 +#: utils/misc/guc_tables.c:2517 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "Vacuum-kostnad för en sida som inte hittas i buffer-cache:n." -#: utils/misc/guc_tables.c:2416 +#: utils/misc/guc_tables.c:2527 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "Vacuum-kostnad för sidor som smutsats ner vid vacuum." -#: utils/misc/guc_tables.c:2426 +#: utils/misc/guc_tables.c:2537 msgid "Vacuum cost amount available before napping." msgstr "Vacuum-kostnad kvar innan pausande." -#: utils/misc/guc_tables.c:2436 +#: utils/misc/guc_tables.c:2547 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "Vacuum-kostnad kvar innan pausande, för autovacuum." -#: utils/misc/guc_tables.c:2446 +#: utils/misc/guc_tables.c:2557 msgid "Sets the maximum number of simultaneously open files for each server process." msgstr "Sätter det maximala antalet filer som en serverprocess kan ha öppna på en gång." -#: utils/misc/guc_tables.c:2459 +#: utils/misc/guc_tables.c:2570 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "Sätter det maximala antalet förberedda transaktioner man får ha på en gång." -#: utils/misc/guc_tables.c:2470 +#: utils/misc/guc_tables.c:2581 msgid "Sets the minimum OID of tables for tracking locks." msgstr "Sätter minsta tabell-OID för spårning av lås." -#: utils/misc/guc_tables.c:2471 +#: utils/misc/guc_tables.c:2582 msgid "Is used to avoid output on system tables." msgstr "Används för att undvika utdata för systemtabeller." -#: utils/misc/guc_tables.c:2480 +#: utils/misc/guc_tables.c:2591 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "Sätter OID för tabellen med ovillkorlig låsspårning." -#: utils/misc/guc_tables.c:2492 +#: utils/misc/guc_tables.c:2603 msgid "Sets the maximum allowed duration of any statement." msgstr "Sätter den maximala tiden som en sats får köra." -#: utils/misc/guc_tables.c:2493 utils/misc/guc_tables.c:2504 -#: utils/misc/guc_tables.c:2515 utils/misc/guc_tables.c:2526 +#: utils/misc/guc_tables.c:2604 utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2626 utils/misc/guc_tables.c:2637 +#: utils/misc/guc_tables.c:2648 msgid "A value of 0 turns off the timeout." msgstr "Värdet 0 stänger av timeout:en." -#: utils/misc/guc_tables.c:2503 +#: utils/misc/guc_tables.c:2614 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "Sätter den maximala tiden som man får vänta på ett lås." -#: utils/misc/guc_tables.c:2514 +#: utils/misc/guc_tables.c:2625 msgid "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "Sätter den maximalt tillåtna inaktiva tiden mellan frågor i en transaktion." -#: utils/misc/guc_tables.c:2525 +#: utils/misc/guc_tables.c:2636 +msgid "Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)." +msgstr "Sätter den maximala tillåtana tiden för en transaktion i en session (ej en preparerad transaktion)." + +#: utils/misc/guc_tables.c:2647 msgid "Sets the maximum allowed idle time between queries, when not in a transaction." msgstr "Sätter den maximalt tillåtna inaktiva tiden mellan frågor utanför en transaktion." -#: utils/misc/guc_tables.c:2536 +#: utils/misc/guc_tables.c:2658 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "Minimal ålder där VACUUM skall frysa en tabellrad." -#: utils/misc/guc_tables.c:2546 +#: utils/misc/guc_tables.c:2668 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "Ålder där VACUUM skall skanna hela tabellen för att frysa tupler." -#: utils/misc/guc_tables.c:2556 +#: utils/misc/guc_tables.c:2678 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "Minsta ålder där VACUUM skall frysa en MultiXactId i en tabellrad." -#: utils/misc/guc_tables.c:2566 +#: utils/misc/guc_tables.c:2688 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "Multixact-ålder där VACUUM skall skanna hela tabellen för att frysa tupler." -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2698 msgid "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "Ålder där VACUUM skall startas som skyddsåtgärd för att undvika wraparound-stopp." -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2707 msgid "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "Multixact-ålder där VACUUM skall startas som skyddsåtgärd för att undvika wraparound-stopp." -#: utils/misc/guc_tables.c:2598 +#: utils/misc/guc_tables.c:2720 msgid "Sets the maximum number of locks per transaction." msgstr "Sätter det maximala antalet lås per transaktion." -#: utils/misc/guc_tables.c:2599 -msgid "The shared lock table is sized on the assumption that at most max_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "Den delade låstabellen har storlek efter antagandet att maximalt max_locks_per_transaction objekt per serverprocess eller per förberedd transaktion kommer behöva låsas vid varje enskild tidpunkt." +#: utils/misc/guc_tables.c:2721 +msgid "The shared lock table is sized on the assumption that at most \"max_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "Den delade låstabellen har storlek efter antagandet att maximalt \"max_locks_per_transaction\" objekt per serverprocess eller per förberedd transaktion kommer behöva låsas vid varje enskild tidpunkt." -#: utils/misc/guc_tables.c:2610 +#: utils/misc/guc_tables.c:2732 msgid "Sets the maximum number of predicate locks per transaction." msgstr "Sätter det maximala antalet predikatlås per transaktion." -#: utils/misc/guc_tables.c:2611 -msgid "The shared predicate lock table is sized on the assumption that at most max_pred_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "Den delade predikatlåstabellen har storlek efter antagandet att maximalt max_pred_locks_per_transaction objekt per serverprocess eller per förberedd transaktion kommer behöva låsas vid varje enskild tidpunkt." +#: utils/misc/guc_tables.c:2733 +msgid "The shared predicate lock table is sized on the assumption that at most \"max_pred_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "Den delade predikatlåstabellen har storlek efter antagandet att maximalt \"max_pred_locks_per_transaction\" objekt per serverprocess eller per förberedd transaktion kommer behöva låsas vid varje enskild tidpunkt." -#: utils/misc/guc_tables.c:2622 +#: utils/misc/guc_tables.c:2744 msgid "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "Sätter det maximala antalet predikatlåsta sidor och tupler per relation." -#: utils/misc/guc_tables.c:2623 +#: utils/misc/guc_tables.c:2745 msgid "If more than this total of pages and tuples in the same relation are locked by a connection, those locks are replaced by a relation-level lock." msgstr "Om fler än detta totala antal sidor och tupler för samma relation är låsta av en anslutning så ersätts dessa lås med ett lås på relationen." -#: utils/misc/guc_tables.c:2633 +#: utils/misc/guc_tables.c:2755 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "Sätter det maximala antalet predikatlåsta tupler per sida." -#: utils/misc/guc_tables.c:2634 +#: utils/misc/guc_tables.c:2756 msgid "If more than this number of tuples on the same page are locked by a connection, those locks are replaced by a page-level lock." msgstr "Om fler än detta antal tupler på samma sida är låsta av en anslutning så ersätts dessa lås med ett lås på sidan." -#: utils/misc/guc_tables.c:2644 +#: utils/misc/guc_tables.c:2766 msgid "Sets the maximum allowed time to complete client authentication." msgstr "Sätter maximalt tillåten tid att slutföra klientautentisering." -#: utils/misc/guc_tables.c:2656 +#: utils/misc/guc_tables.c:2778 msgid "Sets the amount of time to wait before authentication on connection startup." msgstr "Sätter tiden att vänta före authentiserng vid uppstart av anslutningen.." -#: utils/misc/guc_tables.c:2668 +#: utils/misc/guc_tables.c:2790 +msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." +msgstr "Sätter det maximala antalet allokerade sidor till kö för NOTIFY / LISTEN." + +#: utils/misc/guc_tables.c:2800 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "Bufferstorlek för read-ahead av WAL vid återställning." -#: utils/misc/guc_tables.c:2669 +#: utils/misc/guc_tables.c:2801 msgid "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "Maximal längd att läsa i förväg av WAL för att prefetch:a refererade datablock." -#: utils/misc/guc_tables.c:2679 +#: utils/misc/guc_tables.c:2811 msgid "Sets the size of WAL files held for standby servers." msgstr "Sätter storlek på WAL-filer som sparas för standby-servrar." -#: utils/misc/guc_tables.c:2690 +#: utils/misc/guc_tables.c:2822 msgid "Sets the minimum size to shrink the WAL to." msgstr "Sätter maximal storlek som WAL kan krympas till." -#: utils/misc/guc_tables.c:2702 +#: utils/misc/guc_tables.c:2834 msgid "Sets the WAL size that triggers a checkpoint." msgstr "Sätter WAL-storlek som triggar en checkpoint." -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2846 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "Sätter maximal tid mellan två automatiska WAL-checkpoint:er." -#: utils/misc/guc_tables.c:2725 +#: utils/misc/guc_tables.c:2857 msgid "Sets the maximum time before warning if checkpoints triggered by WAL volume happen too frequently." msgstr "Sätter maximal tid innan en varning ges för att stor WAL-volymn gör att checkpoint triggas för ofta." -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2859 msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. Zero turns off the warning." msgstr "Skriv ett meddelande i serverloggen om checkpoint:er som orsakas av fulla WAL-segmentfiler händer oftare än denna tid. Noll stänger av varningen." -#: utils/misc/guc_tables.c:2740 utils/misc/guc_tables.c:2958 -#: utils/misc/guc_tables.c:2998 +#: utils/misc/guc_tables.c:2872 utils/misc/guc_tables.c:3090 +#: utils/misc/guc_tables.c:3144 msgid "Number of pages after which previously performed writes are flushed to disk." msgstr "Antal sidor varefter tidigare skrivningar flush:as till disk." -#: utils/misc/guc_tables.c:2751 +#: utils/misc/guc_tables.c:2883 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "Sätter antal buffrar för disksidor i delat minne för WAL." -#: utils/misc/guc_tables.c:2762 +#: utils/misc/guc_tables.c:2884 +msgid "Specify -1 to have this value determined as a fraction of shared_buffers." +msgstr "Ange -1 för att sätta detta värde till en bråkdel av shared_buffers." + +#: utils/misc/guc_tables.c:2894 msgid "Time between WAL flushes performed in the WAL writer." msgstr "Tid mellan WAL-flush:ar utförda i WAL-skrivaren." -#: utils/misc/guc_tables.c:2773 +#: utils/misc/guc_tables.c:2905 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "Mängden WAL utskrivna av WAL-skrivaren som triggar en flush." -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2916 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "Minimal storlek på ny fil som skall fsync:as istället för att skriva till WAL." -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2927 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "Sätter maximalt antal samtidigt körande WAL-sändarprocesser." -#: utils/misc/guc_tables.c:2806 +#: utils/misc/guc_tables.c:2938 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "Sätter maximalt antal samtidigt definierade replikeringsslottar." -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2948 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "Sätter maximalt WAL-storlek som kan reserveras av replikeringsslottar." -#: utils/misc/guc_tables.c:2817 +#: utils/misc/guc_tables.c:2949 msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk." msgstr "Replikeringsslottar kommer markeras som misslyckade och segment kommer släppas till borttagning eller återanvändning när så här mycket plats används av WAL på disk." -#: utils/misc/guc_tables.c:2829 +#: utils/misc/guc_tables.c:2961 msgid "Sets the maximum time to wait for WAL replication." msgstr "Sätter maximal tid att vänta på WAL-replikering." -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2972 msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk." msgstr "Sätter fördröjning i mikrosekunder mellan transaktions-commit ochj flush:ning av WAL till disk." -#: utils/misc/guc_tables.c:2852 -msgid "Sets the minimum number of concurrent open transactions required before performing commit_delay." -msgstr "Sätter minsta antal samtida öppna transaktioner som krävs innan vi utför en commit_delay." +#: utils/misc/guc_tables.c:2984 +msgid "Sets the minimum number of concurrent open transactions required before performing \"commit_delay\"." +msgstr "Sätter minsta antal samtida öppna transaktioner som krävs innan vi utför en \"commit_delay\"." -#: utils/misc/guc_tables.c:2863 +#: utils/misc/guc_tables.c:2995 msgid "Sets the number of digits displayed for floating-point values." msgstr "Sätter antal siffror som visas för flyttalsvärden." -#: utils/misc/guc_tables.c:2864 +#: utils/misc/guc_tables.c:2996 msgid "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than zero selects precise output mode." msgstr "Detta påverkar real, double precision och geometriska datatyper. Noll eller negativt parametervärde läggs till standard antal siffror (FLT_DIG eller DBL_DIG respektive). Ett värde större än noll väljer ett exakt utmatningsläge." -#: utils/misc/guc_tables.c:2876 +#: utils/misc/guc_tables.c:3008 msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by log_statement_sample_rate." msgstr "Sätter minimal körtid där ett urval av långsammare satser kommer loggas. Urvalet bestämms av log_statement_sample_rate." -#: utils/misc/guc_tables.c:2879 +#: utils/misc/guc_tables.c:3011 msgid "Zero logs a sample of all queries. -1 turns this feature off." msgstr "Noll loggar ett urval som inkluderar alla frågor. -1 stänger av denna funktion." -#: utils/misc/guc_tables.c:2889 +#: utils/misc/guc_tables.c:3021 msgid "Sets the minimum execution time above which all statements will be logged." msgstr "Sätter minimal körtid där alla långsammare satser kommer loggas." -#: utils/misc/guc_tables.c:2891 +#: utils/misc/guc_tables.c:3023 msgid "Zero prints all queries. -1 turns this feature off." msgstr "Noll skriver ut alla frågor. -1 stänger av denna finess." -#: utils/misc/guc_tables.c:2901 +#: utils/misc/guc_tables.c:3033 msgid "Sets the minimum execution time above which autovacuum actions will be logged." msgstr "Sätter minimal körtid där långsammare autovacuum-operationer kommer loggas." -#: utils/misc/guc_tables.c:2903 +#: utils/misc/guc_tables.c:3035 msgid "Zero prints all actions. -1 turns autovacuum logging off." msgstr "Noll skriver ut alla operationer. -1 stänger av autovacuum." -#: utils/misc/guc_tables.c:2913 +#: utils/misc/guc_tables.c:3045 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements." msgstr "Sätter maximal längd i byte på data som loggas för bind-parametrar vid loggning av satser." -#: utils/misc/guc_tables.c:2915 utils/misc/guc_tables.c:2927 +#: utils/misc/guc_tables.c:3047 utils/misc/guc_tables.c:3059 msgid "-1 to print values in full." msgstr "-1 för att skriva ut hela värden." -#: utils/misc/guc_tables.c:2925 +#: utils/misc/guc_tables.c:3057 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements, on error." msgstr "Sätter maximal längs i byte på data som loggas för bind-parametrar vid loggning av satser i samband med fel." -#: utils/misc/guc_tables.c:2937 +#: utils/misc/guc_tables.c:3069 msgid "Background writer sleep time between rounds." msgstr "Bakgrundsskrivarens sleep-tid mellan körningar." -#: utils/misc/guc_tables.c:2948 +#: utils/misc/guc_tables.c:3080 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "Bakgrundsskrivarens maximala antal LRU-sidor som flush:as per omgång." -#: utils/misc/guc_tables.c:2971 +#: utils/misc/guc_tables.c:3103 msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem." msgstr "Antal samtidiga förfrågningar som kan effektivt kan hanteras av disksystemet." -#: utils/misc/guc_tables.c:2985 -msgid "A variant of effective_io_concurrency that is used for maintenance work." -msgstr "En variant av effective_io_concurrency som används för underhållsarbete." +#: utils/misc/guc_tables.c:3117 +msgid "A variant of \"effective_io_concurrency\" that is used for maintenance work." +msgstr "En variant av \"effective_io_concurrency\" som används för underhållsarbete." -#: utils/misc/guc_tables.c:3011 +#: utils/misc/guc_tables.c:3132 +msgid "Limit on the size of data reads and writes." +msgstr "Begränsa storlek på data för läsning och skrivning." + +#: utils/misc/guc_tables.c:3157 msgid "Maximum number of concurrent worker processes." msgstr "Maximalt antal samtidiga arbetsprocesser." -#: utils/misc/guc_tables.c:3023 +#: utils/misc/guc_tables.c:3169 msgid "Maximum number of logical replication worker processes." msgstr "Maximalt antal arbetsprocesser för logisk replikering." -#: utils/misc/guc_tables.c:3035 +#: utils/misc/guc_tables.c:3181 msgid "Maximum number of table synchronization workers per subscription." msgstr "Maximalt antal arbetare som synkroniserar tabeller per prenumeration." -#: utils/misc/guc_tables.c:3047 +#: utils/misc/guc_tables.c:3193 msgid "Maximum number of parallel apply workers per subscription." msgstr "Maximalt antal parallella arbetare som applicerar ändring per prenumeration." -#: utils/misc/guc_tables.c:3057 +#: utils/misc/guc_tables.c:3203 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "Sätter tiden vi väntar innan vi tvingar rotering av loggfil." -#: utils/misc/guc_tables.c:3069 +#: utils/misc/guc_tables.c:3215 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "Sätter maximalt storlek en loggfil kan bli innan vi tvingar rotering." -#: utils/misc/guc_tables.c:3081 +#: utils/misc/guc_tables.c:3227 msgid "Shows the maximum number of function arguments." msgstr "Visar maximalt antal funktionsargument." -#: utils/misc/guc_tables.c:3092 +#: utils/misc/guc_tables.c:3238 msgid "Shows the maximum number of index keys." msgstr "Visar maximalt antal indexnycklar." -#: utils/misc/guc_tables.c:3103 +#: utils/misc/guc_tables.c:3249 msgid "Shows the maximum identifier length." msgstr "Visar den maximala identifierarlängden." -#: utils/misc/guc_tables.c:3114 +#: utils/misc/guc_tables.c:3260 msgid "Shows the size of a disk block." msgstr "Visar storleken på ett diskblock." -#: utils/misc/guc_tables.c:3125 +#: utils/misc/guc_tables.c:3271 msgid "Shows the number of pages per disk file." msgstr "Visar antal sidor per diskfil." -#: utils/misc/guc_tables.c:3136 +#: utils/misc/guc_tables.c:3282 msgid "Shows the block size in the write ahead log." msgstr "Visar blockstorleken i the write-ahead-loggen." -#: utils/misc/guc_tables.c:3147 +#: utils/misc/guc_tables.c:3293 msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "Sätter väntetiden innan databasen försöker ta emot WAL efter ett misslyckat försök." -#: utils/misc/guc_tables.c:3159 +#: utils/misc/guc_tables.c:3305 msgid "Shows the size of write ahead log segments." msgstr "Visar storleken på write-ahead-log-segment." -#: utils/misc/guc_tables.c:3172 +#: utils/misc/guc_tables.c:3318 +msgid "Time for which WAL summary files should be kept." +msgstr "Tid som filer för WAL-summering skall behållas." + +#: utils/misc/guc_tables.c:3331 msgid "Time to sleep between autovacuum runs." msgstr "Tid att sova mellan körningar av autovacuum." -#: utils/misc/guc_tables.c:3182 +#: utils/misc/guc_tables.c:3341 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "Minst antal tupel-uppdateringar eller raderingar innan vacuum." -#: utils/misc/guc_tables.c:3191 +#: utils/misc/guc_tables.c:3350 msgid "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums." msgstr "Minsta antal tupel-insert innnan vacuum eller -1 för att stänga av insert-vacuum." -#: utils/misc/guc_tables.c:3200 +#: utils/misc/guc_tables.c:3359 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "Minsta antal tupel-insert, -update eller -delete innan analyze." -#: utils/misc/guc_tables.c:3210 +#: utils/misc/guc_tables.c:3369 msgid "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "Ålder då autovacuum körs på en tabell för att förhindra wrapaound på transaktions-ID." -#: utils/misc/guc_tables.c:3222 +#: utils/misc/guc_tables.c:3381 msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "Ålder på multixact då autovacuum körs på en tabell för att förhindra wrapaound på multixact." -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3391 msgid "Sets the maximum number of simultaneously running autovacuum worker processes." msgstr "Sätter maximalt antal samtidigt körande arbetsprocesser för autovacuum." -#: utils/misc/guc_tables.c:3242 +#: utils/misc/guc_tables.c:3401 msgid "Sets the maximum number of parallel processes per maintenance operation." msgstr "Sätter maximalt antal parallella processer per underhållsoperation." -#: utils/misc/guc_tables.c:3252 +#: utils/misc/guc_tables.c:3411 msgid "Sets the maximum number of parallel processes per executor node." msgstr "Sätter maximalt antal parallella processer per exekveringsnod." -#: utils/misc/guc_tables.c:3263 +#: utils/misc/guc_tables.c:3422 msgid "Sets the maximum number of parallel workers that can be active at one time." msgstr "Sätter maximalt antal parallella arbetare som kan vara aktiva på en gång." -#: utils/misc/guc_tables.c:3274 +#: utils/misc/guc_tables.c:3433 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "Sätter maximalt minne som kan användas av varje arbetsprocess för autovacuum." -#: utils/misc/guc_tables.c:3285 -msgid "Time before a snapshot is too old to read pages changed after the snapshot was taken." -msgstr "Tid innan ett snapshot är för gammalt för att läsa sidor som ändrats efter snapshot:en tagits." - -#: utils/misc/guc_tables.c:3286 -msgid "A value of -1 disables this feature." -msgstr "Värdet -1 stänger av denna funktion." - -#: utils/misc/guc_tables.c:3296 +#: utils/misc/guc_tables.c:3444 msgid "Time between issuing TCP keepalives." msgstr "Tid mellan skickande av TCP-keepalive." -#: utils/misc/guc_tables.c:3297 utils/misc/guc_tables.c:3308 -#: utils/misc/guc_tables.c:3432 +#: utils/misc/guc_tables.c:3445 utils/misc/guc_tables.c:3456 +#: utils/misc/guc_tables.c:3580 msgid "A value of 0 uses the system default." msgstr "Värdet 0 anger systemets standardvärde." -#: utils/misc/guc_tables.c:3307 +#: utils/misc/guc_tables.c:3455 msgid "Time between TCP keepalive retransmits." msgstr "Tid mellan omsändning av TCP-keepalive." -#: utils/misc/guc_tables.c:3318 +#: utils/misc/guc_tables.c:3466 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "SSL-förhandling stöds inte längre; denna kan bara vara 0." -#: utils/misc/guc_tables.c:3329 +#: utils/misc/guc_tables.c:3477 msgid "Maximum number of TCP keepalive retransmits." msgstr "Maximalt antal omsändningar av TCP-keepalive." -#: utils/misc/guc_tables.c:3330 +#: utils/misc/guc_tables.c:3478 msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default." msgstr "Atalet keepalive-omsändingar i rad som kan försvinna innan en anslutning anses vara död. Värdet 0 betyder systemstandardvärdet." -#: utils/misc/guc_tables.c:3341 +#: utils/misc/guc_tables.c:3489 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "Sätter maximalt tillåtna resultat för exakt sökning med GIN." -#: utils/misc/guc_tables.c:3352 +#: utils/misc/guc_tables.c:3500 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "Sätter planerarens antagande om totala storleken på datacachen." -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3501 msgid "That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each." msgstr "Det är totala storleken på cachen (kernelcache och delade buffertar) som användas för PostgreSQLs datafiler. Det mäts i disksidor som normalt är 8 kb styck." -#: utils/misc/guc_tables.c:3364 +#: utils/misc/guc_tables.c:3512 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "Sätter minsta mängd tabelldata för en parallell skanning." -#: utils/misc/guc_tables.c:3365 +#: utils/misc/guc_tables.c:3513 msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered." msgstr "Om planeraren beräknar att den kommer läsa för få tabellsidor för att nå denna gräns så kommer den inte försöka med en parallell skanning." -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3523 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "Anger minimala mängden indexdata för en parallell scan." -#: utils/misc/guc_tables.c:3376 +#: utils/misc/guc_tables.c:3524 msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered." msgstr "Om planeraren beräknar att den kommer läsa för få indexsidor för att nå denna gräns så kommer den inte försöka med en parallell skanning." -#: utils/misc/guc_tables.c:3387 +#: utils/misc/guc_tables.c:3535 msgid "Shows the server version as an integer." msgstr "Visar serverns version som ett heltal." -#: utils/misc/guc_tables.c:3398 +#: utils/misc/guc_tables.c:3546 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "Logga användning av temporära filer som är större än detta antal kilobyte." -#: utils/misc/guc_tables.c:3399 +#: utils/misc/guc_tables.c:3547 msgid "Zero logs all files. The default is -1 (turning this feature off)." msgstr "Noll loggar alla filer. Standard är -1 (stänger av denna finess)." -#: utils/misc/guc_tables.c:3409 +#: utils/misc/guc_tables.c:3557 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "Ställer in storleken reserverad för pg_stat_activity.query, i byte." -#: utils/misc/guc_tables.c:3420 +#: utils/misc/guc_tables.c:3568 msgid "Sets the maximum size of the pending list for GIN index." msgstr "Sätter maximal storlek på väntelistan för GIN-index." -#: utils/misc/guc_tables.c:3431 +#: utils/misc/guc_tables.c:3579 msgid "TCP user timeout." msgstr "Användartimeout för TCP." -#: utils/misc/guc_tables.c:3442 +#: utils/misc/guc_tables.c:3590 msgid "The size of huge page that should be requested." msgstr "Storleken på stora sidor skall hämtas." -#: utils/misc/guc_tables.c:3453 +#: utils/misc/guc_tables.c:3601 msgid "Aggressively flush system caches for debugging purposes." msgstr "Flush:a systemcache aggressivt för att förenkla debugging." -#: utils/misc/guc_tables.c:3476 +#: utils/misc/guc_tables.c:3624 msgid "Sets the time interval between checks for disconnection while running queries." msgstr "Sätter tidsintervall mellan test för nedkoppling när frågor körs." -#: utils/misc/guc_tables.c:3487 +#: utils/misc/guc_tables.c:3635 msgid "Time between progress updates for long-running startup operations." msgstr "Tid mellan uppdatering av progress för startupoperationer som kör länge." -#: utils/misc/guc_tables.c:3489 +#: utils/misc/guc_tables.c:3637 msgid "0 turns this feature off." msgstr "0 stänger av denna finess." -#: utils/misc/guc_tables.c:3499 +#: utils/misc/guc_tables.c:3647 msgid "Sets the iteration count for SCRAM secret generation." msgstr "Sätter iterationsräknare för generering av SCRAM-hemlighet." -#: utils/misc/guc_tables.c:3519 +#: utils/misc/guc_tables.c:3667 msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "Ställer in planerarens estimat av kostnaden för att hämta en disksida sekvensiellt." -#: utils/misc/guc_tables.c:3530 +#: utils/misc/guc_tables.c:3678 msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page." msgstr "Ställer in planerarens estimat av kostnaden för att hämta en disksida icke-sekvensiellt." -#: utils/misc/guc_tables.c:3541 +#: utils/misc/guc_tables.c:3689 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "Ställer in planerarens estimat av kostnaden för att processa varje tupel (rad)." -#: utils/misc/guc_tables.c:3552 +#: utils/misc/guc_tables.c:3700 msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan." msgstr "Sätter planerarens kostnadsuppskattning för att processa varje indexpost under en indexskanning." -#: utils/misc/guc_tables.c:3563 +#: utils/misc/guc_tables.c:3711 msgid "Sets the planner's estimate of the cost of processing each operator or function call." msgstr "Sätter planerarens kostnadsuppskattning för att processa varje operator- eller funktions-anrop." -#: utils/misc/guc_tables.c:3574 +#: utils/misc/guc_tables.c:3722 msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to leader backend." msgstr "Sätter planerarens kostnadsuppskattning för att skicka varje tupel (rad) från en arbetare till ledar-backend:en. " -#: utils/misc/guc_tables.c:3585 +#: utils/misc/guc_tables.c:3733 msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query." msgstr "Sätter planerarens kostnadsuppskattning för att starta upp en arbetsprocess för en parallell fråga." -#: utils/misc/guc_tables.c:3597 +#: utils/misc/guc_tables.c:3745 msgid "Perform JIT compilation if query is more expensive." msgstr "Utför JIT-kompilering om frågan är dyrare." -#: utils/misc/guc_tables.c:3598 +#: utils/misc/guc_tables.c:3746 msgid "-1 disables JIT compilation." msgstr "-1 stänger av JIT-kompilering." -#: utils/misc/guc_tables.c:3608 +#: utils/misc/guc_tables.c:3756 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "Optimera JIT-kompilerade funktioner om frågan är dyrare." -#: utils/misc/guc_tables.c:3609 +#: utils/misc/guc_tables.c:3757 msgid "-1 disables optimization." msgstr "-1 stänger av optimering." -#: utils/misc/guc_tables.c:3619 +#: utils/misc/guc_tables.c:3767 msgid "Perform JIT inlining if query is more expensive." msgstr "Utför JIT-\"inlining\" om frågan är dyrare." -#: utils/misc/guc_tables.c:3620 +#: utils/misc/guc_tables.c:3768 msgid "-1 disables inlining." msgstr "-1 stänger av \"inlining\"" -#: utils/misc/guc_tables.c:3630 +#: utils/misc/guc_tables.c:3778 msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." msgstr "Sätter planerarens uppskattning av hur stor del av markörens rader som kommer hämtas. " -#: utils/misc/guc_tables.c:3642 +#: utils/misc/guc_tables.c:3790 msgid "Sets the planner's estimate of the average size of a recursive query's working table." msgstr "Sätter planerarens uppskattning av genomsnittliga storleken på en rekursiv frågas arbetstabell." -#: utils/misc/guc_tables.c:3654 +#: utils/misc/guc_tables.c:3802 msgid "GEQO: selective pressure within the population." msgstr "GEQO: selektionstryck inom populationen." -#: utils/misc/guc_tables.c:3665 +#: utils/misc/guc_tables.c:3813 msgid "GEQO: seed for random path selection." msgstr "GEQO: slumptalsfrö för val av slumpad sökväg." -#: utils/misc/guc_tables.c:3676 -msgid "Multiple of work_mem to use for hash tables." -msgstr "Multipel av work_mem för att använda till hash-tabeller." +#: utils/misc/guc_tables.c:3824 +msgid "Multiple of \"work_mem\" to use for hash tables." +msgstr "Multipel av \"work_mem\" för att använda till hash-tabeller." -#: utils/misc/guc_tables.c:3687 +#: utils/misc/guc_tables.c:3835 msgid "Multiple of the average buffer usage to free per round." msgstr "Multipel av genomsnittlig bufferanvändning som frias per runda." -#: utils/misc/guc_tables.c:3697 +#: utils/misc/guc_tables.c:3845 msgid "Sets the seed for random-number generation." msgstr "Sätter fröet för slumptalsgeneratorn." -#: utils/misc/guc_tables.c:3708 +#: utils/misc/guc_tables.c:3856 msgid "Vacuum cost delay in milliseconds." msgstr "Städkostfördröjning i millisekunder." -#: utils/misc/guc_tables.c:3719 +#: utils/misc/guc_tables.c:3867 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "Städkostfördröjning i millisekunder, för autovacuum." -#: utils/misc/guc_tables.c:3730 +#: utils/misc/guc_tables.c:3878 msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples." msgstr "Antalet tupeluppdateringar eller borttagningar innan vacuum relativt reltuples." -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3888 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "Antal tupelinsättningar innan vacuum relativt reltuples." -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3898 msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples." msgstr "Antalet tupelinsättningar, uppdateringar eller borttagningar innan analyze relativt reltuples." -#: utils/misc/guc_tables.c:3760 +#: utils/misc/guc_tables.c:3908 msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval." msgstr "Tid lagd på att flusha nedsmutsade buffrar vid checkpoint relativt checkpoint-intervallet." -#: utils/misc/guc_tables.c:3770 -msgid "Fraction of statements exceeding log_min_duration_sample to be logged." -msgstr "Bråkdel av satser som överskrider log_min_duration_sample som skall loggas." +#: utils/misc/guc_tables.c:3918 +msgid "Fraction of statements exceeding \"log_min_duration_sample\" to be logged." +msgstr "Bråkdel av satser som överskrider \"log_min_duration_sample\" som skall loggas." -#: utils/misc/guc_tables.c:3771 +#: utils/misc/guc_tables.c:3919 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "Använd ett värde mellan 0.0 (logga aldrig) och 1.0 (logga alltid)." -#: utils/misc/guc_tables.c:3780 +#: utils/misc/guc_tables.c:3928 msgid "Sets the fraction of transactions from which to log all statements." msgstr "Ställer in bråkdel av transaktionerna från vilka alla satser skall loggas." -#: utils/misc/guc_tables.c:3781 +#: utils/misc/guc_tables.c:3929 msgid "Use a value between 0.0 (never log) and 1.0 (log all statements for all transactions)." msgstr "Använd ett värde mellan 0.0 (logga aldrig) till 1.0 (logga all satser i alla transaktioner)." -#: utils/misc/guc_tables.c:3800 +#: utils/misc/guc_tables.c:3948 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "Sätter shell-kommandot som kommer anropas för att arkivera en WAL-fil." -#: utils/misc/guc_tables.c:3801 +#: utils/misc/guc_tables.c:3949 msgid "This is used only if \"archive_library\" is not set." msgstr "Detta används enbart om \"archive_library\" inte är satt." -#: utils/misc/guc_tables.c:3810 +#: utils/misc/guc_tables.c:3958 msgid "Sets the library that will be called to archive a WAL file." msgstr "Sätter biblioteket som kommer anropas för att arkivera en WAL-fil." -#: utils/misc/guc_tables.c:3811 +#: utils/misc/guc_tables.c:3959 msgid "An empty string indicates that \"archive_command\" should be used." msgstr "En tom sträng betyder att \"archive_command\" skall användas." -#: utils/misc/guc_tables.c:3820 +#: utils/misc/guc_tables.c:3968 msgid "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "Sätter shell-kommandot som kommer anropas för att få en arkiverad WAL-fil." -#: utils/misc/guc_tables.c:3830 +#: utils/misc/guc_tables.c:3978 msgid "Sets the shell command that will be executed at every restart point." msgstr "Sätter shell-kommandot som kommer anropas vid varje omstartspunkt." -#: utils/misc/guc_tables.c:3840 +#: utils/misc/guc_tables.c:3988 msgid "Sets the shell command that will be executed once at the end of recovery." msgstr "Sätter shell-kommandot som kommer anropas en gång i slutet av en återställning." -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:3998 msgid "Specifies the timeline to recover into." msgstr "Anger tidslinjen att återställa till." -#: utils/misc/guc_tables.c:3860 +#: utils/misc/guc_tables.c:4008 msgid "Set to \"immediate\" to end recovery as soon as a consistent state is reached." msgstr "Sätt till \"immediate\" för att avsluta återställning så snart ett konsistent tillstånd uppnås." -#: utils/misc/guc_tables.c:3869 +#: utils/misc/guc_tables.c:4017 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "Sätter transaktions-ID som återställning kommer gå till." -#: utils/misc/guc_tables.c:3878 +#: utils/misc/guc_tables.c:4026 msgid "Sets the time stamp up to which recovery will proceed." msgstr "Sätter tidsstämpel som återställning kommer gå till." -#: utils/misc/guc_tables.c:3887 +#: utils/misc/guc_tables.c:4035 msgid "Sets the named restore point up to which recovery will proceed." msgstr "Sätter namngiven återställningspunkt som återställning kommer gå till." -#: utils/misc/guc_tables.c:3896 +#: utils/misc/guc_tables.c:4044 msgid "Sets the LSN of the write-ahead log location up to which recovery will proceed." msgstr "Sätter LSN för write-ahead-logg-position som återställning kommer få till." -#: utils/misc/guc_tables.c:3906 +#: utils/misc/guc_tables.c:4054 msgid "Sets the connection string to be used to connect to the sending server." msgstr "Sätter anslutningssträng som anvönds för att ansluta till skickande server." -#: utils/misc/guc_tables.c:3917 +#: utils/misc/guc_tables.c:4065 msgid "Sets the name of the replication slot to use on the sending server." msgstr "Sätter namnet på replikeringsslotten som skall användas av den skickande servern." -#: utils/misc/guc_tables.c:3927 +#: utils/misc/guc_tables.c:4075 msgid "Sets the client's character set encoding." msgstr "Ställer in klientens teckenkodning." -#: utils/misc/guc_tables.c:3938 +#: utils/misc/guc_tables.c:4086 msgid "Controls information prefixed to each log line." msgstr "Styr information prefixat till varje loggrad." -#: utils/misc/guc_tables.c:3939 +#: utils/misc/guc_tables.c:4087 msgid "If blank, no prefix is used." msgstr "Om tom så används inget prefix." -#: utils/misc/guc_tables.c:3948 +#: utils/misc/guc_tables.c:4096 msgid "Sets the time zone to use in log messages." msgstr "Sätter tidszonen som används i loggmeddelanden." -#: utils/misc/guc_tables.c:3958 +#: utils/misc/guc_tables.c:4106 msgid "Sets the display format for date and time values." msgstr "Sätter displayformat för datum och tidvärden." -#: utils/misc/guc_tables.c:3959 +#: utils/misc/guc_tables.c:4107 msgid "Also controls interpretation of ambiguous date inputs." msgstr "Styr också tolkning av tvetydig datumindata." -#: utils/misc/guc_tables.c:3970 +#: utils/misc/guc_tables.c:4118 msgid "Sets the default table access method for new tables." msgstr "Ställer in standard tabellaccessmetod för nya tabeller." -#: utils/misc/guc_tables.c:3981 +#: utils/misc/guc_tables.c:4129 msgid "Sets the default tablespace to create tables and indexes in." msgstr "Ställer in standard tabellutrymme där tabeller och index skapas." -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4130 msgid "An empty string selects the database's default tablespace." msgstr "En tom sträng väljer databasens standardtabellutrymme." -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4140 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "Ställer in tablespace för temporära tabeller och sorteringsfiler." -#: utils/misc/guc_tables.c:4003 +#: utils/misc/guc_tables.c:4151 msgid "Sets whether a CREATEROLE user automatically grants the role to themselves, and with which options." msgstr "Sätter hurvida en CREATEROLE-användare automatiskt får rollen själva, och med vilka flaggor." -#: utils/misc/guc_tables.c:4015 +#: utils/misc/guc_tables.c:4163 msgid "Sets the path for dynamically loadable modules." msgstr "Sätter sökvägen till dynamiskt laddade moduler." -#: utils/misc/guc_tables.c:4016 +#: utils/misc/guc_tables.c:4164 msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file." msgstr "Om en dynamiskt laddad modul behöver öppnas och det angivna namnet inte har en katalogkomponent (dvs, namnet inte innehåller snedstreck) så kommer systemet använda denna sökväg för filen." -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4177 msgid "Sets the location of the Kerberos server key file." msgstr "Ställer in platsen för Kerberos servernyckelfil." -#: utils/misc/guc_tables.c:4040 +#: utils/misc/guc_tables.c:4188 msgid "Sets the Bonjour service name." msgstr "Sätter Bonjour-tjänstens namn." -#: utils/misc/guc_tables.c:4050 +#: utils/misc/guc_tables.c:4198 msgid "Sets the language in which messages are displayed." msgstr "Sätter språket som meddelanden visas i." -#: utils/misc/guc_tables.c:4060 +#: utils/misc/guc_tables.c:4208 msgid "Sets the locale for formatting monetary amounts." msgstr "Sätter lokalen för att formattera monetära belopp." -#: utils/misc/guc_tables.c:4070 +#: utils/misc/guc_tables.c:4218 msgid "Sets the locale for formatting numbers." msgstr "Ställer in lokalen för att formattera nummer." -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4228 msgid "Sets the locale for formatting date and time values." msgstr "Sätter lokalen för att formattera datum och tider." -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4238 msgid "Lists shared libraries to preload into each backend." msgstr "Listar delade bibliotek som skall förladdas i varje backend." -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4249 msgid "Lists shared libraries to preload into server." msgstr "Listar delade bibliotek som skall förladdas i servern." -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4260 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "Listar ej priviligerade delade bibliotek som förladdas in i varje backend." -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4271 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "Sätter schemats sökordning för namn som inte är schema-prefixade." -#: utils/misc/guc_tables.c:4135 +#: utils/misc/guc_tables.c:4283 msgid "Shows the server (database) character set encoding." msgstr "Visar serverns (databasens) teckenkodning." -#: utils/misc/guc_tables.c:4147 +#: utils/misc/guc_tables.c:4295 msgid "Shows the server version." msgstr "Visar serverversionen" -#: utils/misc/guc_tables.c:4159 +#: utils/misc/guc_tables.c:4307 msgid "Sets the current role." msgstr "Ställer in den aktiva rollen." -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4319 msgid "Sets the session user name." msgstr "Sätter sessionens användarnamn." -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4330 msgid "Sets the destination for server log output." msgstr "Sätter serverloggens destination." -#: utils/misc/guc_tables.c:4183 +#: utils/misc/guc_tables.c:4331 msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", and \"eventlog\", depending on the platform." msgstr "Giltiga värden är kombinationer av \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\" och \"eventlog\", beroende på plattform." -#: utils/misc/guc_tables.c:4194 +#: utils/misc/guc_tables.c:4342 msgid "Sets the destination directory for log files." msgstr "Sätter destinationskatalogen för loggfiler." -#: utils/misc/guc_tables.c:4195 +#: utils/misc/guc_tables.c:4343 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "Kan anges relativt datakatalogen eller som en absolut sökväg." -#: utils/misc/guc_tables.c:4205 +#: utils/misc/guc_tables.c:4353 msgid "Sets the file name pattern for log files." msgstr "Sätter filnamnsmallen för loggfiler." -#: utils/misc/guc_tables.c:4216 +#: utils/misc/guc_tables.c:4364 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "Sätter programnamnet som används för att identifiera PostgreSQLs meddelanden i syslog." -#: utils/misc/guc_tables.c:4227 +#: utils/misc/guc_tables.c:4375 msgid "Sets the application name used to identify PostgreSQL messages in the event log." msgstr "Sätter applikationsnamnet som används för att identifiera PostgreSQLs meddelanden i händelseloggen." -#: utils/misc/guc_tables.c:4238 +#: utils/misc/guc_tables.c:4386 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "Ställer in tidszon för visande och tolkande av tidsstämplar." -#: utils/misc/guc_tables.c:4248 +#: utils/misc/guc_tables.c:4396 msgid "Selects a file of time zone abbreviations." msgstr "Väljer en fil för tidszonsförkortningar." -#: utils/misc/guc_tables.c:4258 +#: utils/misc/guc_tables.c:4406 msgid "Sets the owning group of the Unix-domain socket." msgstr "Sätter ägande grupp för Unix-domainuttaget (socket)." -#: utils/misc/guc_tables.c:4259 +#: utils/misc/guc_tables.c:4407 msgid "The owning user of the socket is always the user that starts the server." msgstr "Ägaren av uttaget (socker) är alltid användaren som startar servern." -#: utils/misc/guc_tables.c:4269 +#: utils/misc/guc_tables.c:4417 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "Ställer in kataloger där Unix-domän-uttag (socket) kommer skapas." -#: utils/misc/guc_tables.c:4280 +#: utils/misc/guc_tables.c:4428 msgid "Sets the host name or IP address(es) to listen to." msgstr "Sätter värdnamn eller IP-adress(er) att lyssna på." -#: utils/misc/guc_tables.c:4295 +#: utils/misc/guc_tables.c:4443 msgid "Sets the server's data directory." msgstr "Ställer in serverns datakatalog." -#: utils/misc/guc_tables.c:4306 +#: utils/misc/guc_tables.c:4454 msgid "Sets the server's main configuration file." msgstr "Sätter serverns huvudkonfigurationsfil." -#: utils/misc/guc_tables.c:4317 +#: utils/misc/guc_tables.c:4465 msgid "Sets the server's \"hba\" configuration file." msgstr "Sätter serverns \"hba\"-konfigurationsfil." -#: utils/misc/guc_tables.c:4328 +#: utils/misc/guc_tables.c:4476 msgid "Sets the server's \"ident\" configuration file." msgstr "Sätter serverns \"ident\"-konfigurationsfil." -#: utils/misc/guc_tables.c:4339 +#: utils/misc/guc_tables.c:4487 msgid "Writes the postmaster PID to the specified file." msgstr "Skriver postmaster-PID till angiven fil." -#: utils/misc/guc_tables.c:4350 +#: utils/misc/guc_tables.c:4498 msgid "Shows the name of the SSL library." msgstr "Visar namnet på SSL-biblioteket." -#: utils/misc/guc_tables.c:4365 +#: utils/misc/guc_tables.c:4513 msgid "Location of the SSL server certificate file." msgstr "Plats för serverns SSL-certifikatfil." -#: utils/misc/guc_tables.c:4375 +#: utils/misc/guc_tables.c:4523 msgid "Location of the SSL server private key file." msgstr "Plats för serverns privata SSL-nyckelfil." -#: utils/misc/guc_tables.c:4385 +#: utils/misc/guc_tables.c:4533 msgid "Location of the SSL certificate authority file." msgstr "Plats för SSL-certifikats auktoritetsfil." -#: utils/misc/guc_tables.c:4395 +#: utils/misc/guc_tables.c:4543 msgid "Location of the SSL certificate revocation list file." msgstr "Plats för SSL-certifikats återkallningsfil." -#: utils/misc/guc_tables.c:4405 +#: utils/misc/guc_tables.c:4553 msgid "Location of the SSL certificate revocation list directory." msgstr "Plats av katalog för SSL-certifikats återkallningslistor." -#: utils/misc/guc_tables.c:4415 +#: utils/misc/guc_tables.c:4563 msgid "Number of synchronous standbys and list of names of potential synchronous ones." msgstr "Antalet synkrona standby och en lista med namn på potentiellt synkrona sådana." -#: utils/misc/guc_tables.c:4426 +#: utils/misc/guc_tables.c:4574 msgid "Sets default text search configuration." msgstr "Ställer in standard textsökkonfiguration." -#: utils/misc/guc_tables.c:4436 +#: utils/misc/guc_tables.c:4584 msgid "Sets the list of allowed SSL ciphers." msgstr "Ställer in listan med tillåtna SSL-krypton." -#: utils/misc/guc_tables.c:4451 +#: utils/misc/guc_tables.c:4599 msgid "Sets the curve to use for ECDH." msgstr "Ställer in kurvan att använda för ECDH." -#: utils/misc/guc_tables.c:4466 +#: utils/misc/guc_tables.c:4614 msgid "Location of the SSL DH parameters file." msgstr "Plats för SSL DH-parameterfil." -#: utils/misc/guc_tables.c:4477 +#: utils/misc/guc_tables.c:4625 msgid "Command to obtain passphrases for SSL." msgstr "Kommando för att hämta lösenfraser för SSL." -#: utils/misc/guc_tables.c:4488 +#: utils/misc/guc_tables.c:4636 msgid "Sets the application name to be reported in statistics and logs." msgstr "Sätter applikationsnamn som rapporteras i statistik och loggar." -#: utils/misc/guc_tables.c:4499 +#: utils/misc/guc_tables.c:4647 msgid "Sets the name of the cluster, which is included in the process title." msgstr "Sätter namnet på klustret som inkluderas i processtiteln." -#: utils/misc/guc_tables.c:4510 +#: utils/misc/guc_tables.c:4658 msgid "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "Sätter WAL-resurshanterare som WAL-konsistenskontoller görs med." -#: utils/misc/guc_tables.c:4511 +#: utils/misc/guc_tables.c:4659 msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay." msgstr "Hela sidkopior kommer loggas för alla datablock och kontrolleras mot resultatet av en WAL-uppspelning." -#: utils/misc/guc_tables.c:4521 +#: utils/misc/guc_tables.c:4669 msgid "JIT provider to use." msgstr "JIT-leverantör som används." -#: utils/misc/guc_tables.c:4532 +#: utils/misc/guc_tables.c:4680 msgid "Log backtrace for errors in these functions." msgstr "Loggar backtrace vid fel i dessa funktioner." -#: utils/misc/guc_tables.c:4543 +#: utils/misc/guc_tables.c:4691 msgid "Use direct I/O for file access." msgstr "Använd direct-I/O för filaccess." -#: utils/misc/guc_tables.c:4563 +#: utils/misc/guc_tables.c:4702 +msgid "Lists streaming replication standby server replication slot names that logical WAL sender processes will wait for." +msgstr "Listar replikeringsslotnamn på server för replikering-standby som processen för skickande av logisk WAL väntar på." + +#: utils/misc/guc_tables.c:4704 +msgid "Logical WAL sender processes will send decoded changes to output plugins only after the specified replication slots have confirmed receiving WAL." +msgstr "Processen för skickande av logisk WAL skickar avkodade ändringar till utdata-plugin:er enbart efter att de angivna replikeringsslottarna bekräftat att de tagit emot WAL." + +#: utils/misc/guc_tables.c:4716 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "Förhindrar access till icke-system-relationer av angivna sorter." + +#: utils/misc/guc_tables.c:4736 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "Anger hurvida \"\\'\" tillåts i sträng-literaler." -#: utils/misc/guc_tables.c:4573 +#: utils/misc/guc_tables.c:4746 msgid "Sets the output format for bytea." msgstr "Ställer in output-format för bytea." -#: utils/misc/guc_tables.c:4583 +#: utils/misc/guc_tables.c:4756 msgid "Sets the message levels that are sent to the client." msgstr "Ställer in meddelandenivåer som skickas till klienten." -#: utils/misc/guc_tables.c:4584 utils/misc/guc_tables.c:4680 -#: utils/misc/guc_tables.c:4691 utils/misc/guc_tables.c:4763 +#: utils/misc/guc_tables.c:4757 utils/misc/guc_tables.c:4853 +#: utils/misc/guc_tables.c:4864 msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent." msgstr "Varje nivå inkluderar de efterföljande nivåerna. Ju senare nivå destå färre meddlanden skickas." -#: utils/misc/guc_tables.c:4594 +#: utils/misc/guc_tables.c:4767 msgid "Enables in-core computation of query identifiers." msgstr "Slår på intern uträkning av identifierare för frågor." -#: utils/misc/guc_tables.c:4604 +#: utils/misc/guc_tables.c:4777 msgid "Enables the planner to use constraints to optimize queries." msgstr "Slår på planerarens användning av integritetsvillkor för att optimera frågor." -#: utils/misc/guc_tables.c:4605 +#: utils/misc/guc_tables.c:4778 msgid "Table scans will be skipped if their constraints guarantee that no rows match the query." msgstr "Tabellskanningar kommer hoppas över om dess integritetsvillkor garanterar att inga rader komma matchas av frågan." -#: utils/misc/guc_tables.c:4616 +#: utils/misc/guc_tables.c:4789 msgid "Sets the default compression method for compressible values." msgstr "Ställer in standard komprimeringsmetod för komprimeringsbara värden." -#: utils/misc/guc_tables.c:4627 +#: utils/misc/guc_tables.c:4800 msgid "Sets the transaction isolation level of each new transaction." msgstr "Ställer in isolationsnivån för nya transaktioner." -#: utils/misc/guc_tables.c:4637 +#: utils/misc/guc_tables.c:4810 msgid "Sets the current transaction's isolation level." msgstr "Sätter den aktuella transaktionsisolationsnivån." -#: utils/misc/guc_tables.c:4648 +#: utils/misc/guc_tables.c:4821 msgid "Sets the display format for interval values." msgstr "Ställer in visningsformat för intervallvärden." -#: utils/misc/guc_tables.c:4659 +#: utils/misc/guc_tables.c:4832 msgid "Log level for reporting invalid ICU locale strings." msgstr "Loggnivå för rapportering av ogiltiga ICU-lokalsträngar." -#: utils/misc/guc_tables.c:4669 +#: utils/misc/guc_tables.c:4842 msgid "Sets the verbosity of logged messages." msgstr "Ställer in pratighet för loggade meddelanden." -#: utils/misc/guc_tables.c:4679 +#: utils/misc/guc_tables.c:4852 msgid "Sets the message levels that are logged." msgstr "Ställer in meddelandenivåer som loggas." -#: utils/misc/guc_tables.c:4690 +#: utils/misc/guc_tables.c:4863 msgid "Causes all statements generating error at or above this level to be logged." msgstr "Gör att alla satser som genererar fel vid eller över denna nivå kommer loggas." -#: utils/misc/guc_tables.c:4701 +#: utils/misc/guc_tables.c:4874 msgid "Sets the type of statements logged." msgstr "Ställer in vilken sorts satser som loggas." -#: utils/misc/guc_tables.c:4711 +#: utils/misc/guc_tables.c:4884 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "Ställer in syslog-\"facility\" som används när syslog är påslagen." -#: utils/misc/guc_tables.c:4722 +#: utils/misc/guc_tables.c:4895 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "Sätter sessionens beteende för triggrar och omskrivningsregler." -#: utils/misc/guc_tables.c:4732 +#: utils/misc/guc_tables.c:4905 msgid "Sets the current transaction's synchronization level." msgstr "Ställer in den nuvarande transaktionens synkroniseringsnivå." -#: utils/misc/guc_tables.c:4742 -msgid "Allows archiving of WAL files using archive_command." -msgstr "Tillåter arkivering av WAL-filer med hjälp av archive_command." +#: utils/misc/guc_tables.c:4915 +msgid "Allows archiving of WAL files using \"archive_command\"." +msgstr "Tillåter arkivering av WAL-filer med hjälp av \"archive_command\"." -#: utils/misc/guc_tables.c:4752 +#: utils/misc/guc_tables.c:4925 msgid "Sets the action to perform upon reaching the recovery target." msgstr "Sätter handling som skall utföras när återställningsmål nås." -#: utils/misc/guc_tables.c:4762 -msgid "Enables logging of recovery-related debugging information." -msgstr "Slår på loggning av återställningsrelaterad debug-information." - -#: utils/misc/guc_tables.c:4779 +#: utils/misc/guc_tables.c:4935 msgid "Collects function-level statistics on database activity." msgstr "Samlar in statistik på funktionsnivå över databasaktivitet." -#: utils/misc/guc_tables.c:4790 +#: utils/misc/guc_tables.c:4946 msgid "Sets the consistency of accesses to statistics data." msgstr "Sätter konsistensinställning för accesser av statistikdata." -#: utils/misc/guc_tables.c:4800 +#: utils/misc/guc_tables.c:4956 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "Komprimerar skrivning av hela sidor i WAL-filen med angiven metod." -#: utils/misc/guc_tables.c:4810 +#: utils/misc/guc_tables.c:4966 msgid "Sets the level of information written to the WAL." msgstr "Ställer in mängden information som skrivs till WAL." -#: utils/misc/guc_tables.c:4820 +#: utils/misc/guc_tables.c:4976 msgid "Selects the dynamic shared memory implementation used." msgstr "Väljer implementation som används för dynamiskt delat minne." -#: utils/misc/guc_tables.c:4830 +#: utils/misc/guc_tables.c:4986 msgid "Selects the shared memory implementation used for the main shared memory region." msgstr "Väljer implementation för delat minne som används för det delade minnets huvudregionen." -#: utils/misc/guc_tables.c:4840 +#: utils/misc/guc_tables.c:4996 msgid "Selects the method used for forcing WAL updates to disk." msgstr "Väljer metod för att tvinga WAL-uppdateringar till disk." -#: utils/misc/guc_tables.c:4850 +#: utils/misc/guc_tables.c:5006 msgid "Sets how binary values are to be encoded in XML." msgstr "Ställer in hur binära värden kodas i XML." -#: utils/misc/guc_tables.c:4860 +#: utils/misc/guc_tables.c:5016 msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments." msgstr "Anger hurvida XML-data vid implicit parsning och serialiseringsoperationer ses som dokument eller innehållsfragment." -#: utils/misc/guc_tables.c:4871 +#: utils/misc/guc_tables.c:5027 msgid "Use of huge pages on Linux or Windows." msgstr "Använd stora sidor på Linux resp. Windows." -#: utils/misc/guc_tables.c:4881 +#: utils/misc/guc_tables.c:5037 +msgid "Indicates the status of huge pages." +msgstr "Visas status för stora sidor." + +#: utils/misc/guc_tables.c:5048 msgid "Prefetch referenced blocks during recovery." msgstr "Prefetch:a refererade block vid återställning." -#: utils/misc/guc_tables.c:4882 +#: utils/misc/guc_tables.c:5049 msgid "Look ahead in the WAL to find references to uncached data." msgstr "Sök framåt i WAL för att hitta referenser till icke cache:ad data." -#: utils/misc/guc_tables.c:4891 +#: utils/misc/guc_tables.c:5058 msgid "Forces the planner's use parallel query nodes." msgstr "Tvingar planeraren att använda parallella frågenoder." -#: utils/misc/guc_tables.c:4892 +#: utils/misc/guc_tables.c:5059 msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans that contain nodes that perform tuple communication between workers and the main process." msgstr "Detta är användbart för att testa infrastrukturen för parallella frågor genom att tvinga planeraren att generera planer som innehåller noder som skickar tupler mellan arbetare och huvudprocessen." -#: utils/misc/guc_tables.c:4904 +#: utils/misc/guc_tables.c:5071 msgid "Chooses the algorithm for encrypting passwords." msgstr "Väljer algoritm för att kryptera lösenord." -#: utils/misc/guc_tables.c:4914 +#: utils/misc/guc_tables.c:5081 msgid "Controls the planner's selection of custom or generic plan." msgstr "Styr planerarens användning av egendefinierad eller generell plan." -#: utils/misc/guc_tables.c:4915 +#: utils/misc/guc_tables.c:5082 msgid "Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior." msgstr "Preparerade satser kan ha egendefinierade och generella planer och planeraren kommer försöka välja den som är bäst. Detta kan anges att övertrumfa standardbeteendet." -#: utils/misc/guc_tables.c:4927 +#: utils/misc/guc_tables.c:5094 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "Sätter minsta SSL/TLS-protokollversion som skall användas." -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5106 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "Sätter högsta SSL/TLS-protokollversion som skall användas." -#: utils/misc/guc_tables.c:4951 +#: utils/misc/guc_tables.c:5118 msgid "Sets the method for synchronizing the data directory before crash recovery." msgstr "Ställer in metoden för att synkronisera datakatalogen innan kraschåterställning." -#: utils/misc/guc_tables.c:4960 +#: utils/misc/guc_tables.c:5127 msgid "Forces immediate streaming or serialization of changes in large transactions." msgstr "Tvingar omedelbar strömning eller serialisering av ändringar i stora transaktioner." -#: utils/misc/guc_tables.c:4961 +#: utils/misc/guc_tables.c:5128 msgid "On the publisher, it allows streaming or serializing each change in logical decoding. On the subscriber, it allows serialization of all changes to files and notifies the parallel apply workers to read and apply them at the end of the transaction." msgstr "På publiceringssidan så tillåter detta strömning eller serialisering av varje ändring i den logiska kodningen. På prenumerationsstidan så tillåter det serialisering av alla ändringar till filer samt notifiering till den parallella appliceraren att läsa in och applicera dem i slutet av transaktionen." @@ -29585,8 +30820,8 @@ msgstr "På publiceringssidan så tillåter detta strömning eller serialisering msgid "internal error: unrecognized run-time parameter type\n" msgstr "internt fel: okänd parametertyp\n" -#: utils/misc/pg_controldata.c:48 utils/misc/pg_controldata.c:86 -#: utils/misc/pg_controldata.c:175 utils/misc/pg_controldata.c:214 +#: utils/misc/pg_controldata.c:50 utils/misc/pg_controldata.c:90 +#: utils/misc/pg_controldata.c:181 utils/misc/pg_controldata.c:222 #, c-format msgid "calculated CRC checksum does not match value stored in file" msgstr "uträknad CRC-checksumma matchar inte värdet som är lagrat i fil" @@ -29606,145 +30841,143 @@ msgstr "frågan påverkas av radsäkerhetspolicyn för tabell \"%s\"" msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." msgstr "För att slå av policyn för tabellens ägare, använd ALTER TABLE NO FORCE ROW LEVEL SECURITY." -#: utils/misc/timeout.c:524 +#: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" msgstr "kan inte lägga till fler timeoutskäl" -#: utils/misc/tzparser.c:60 +#: utils/misc/tzparser.c:61 #, c-format msgid "time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d" msgstr "tidszonförkortningen \"%s\" är för lång (max %d tecken) i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:72 +#: utils/misc/tzparser.c:73 #, c-format msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "tidszonoffset %d är otanför giltigt intervall i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:111 +#: utils/misc/tzparser.c:112 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "tidszonförkortning saknas i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:120 +#: utils/misc/tzparser.c:121 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "tidszonoffset saknas i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:132 +#: utils/misc/tzparser.c:133 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "felaktigt nummer för tidszonsoffset i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:168 +#: utils/misc/tzparser.c:169 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "felaktig syntax i tidszonfilen \"%s\", rad %d" -#: utils/misc/tzparser.c:236 +#: utils/misc/tzparser.c:237 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "tidszonförkortningen \"%s\" är definierad flera gånger" -#: utils/misc/tzparser.c:238 +#: utils/misc/tzparser.c:239 #, c-format msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d." msgstr "Post i tidszonfilen \"%s\", rad %d, står i konflikt med post i filen \"%s\", rad %d." -#: utils/misc/tzparser.c:300 +#: utils/misc/tzparser.c:301 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "ogiltigt tidszonfilnamn: \"%s\"" -#: utils/misc/tzparser.c:313 +#: utils/misc/tzparser.c:314 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "tidszonfilens rekursiva maxtak överskridet i filen \"%s\"" -#: utils/misc/tzparser.c:352 utils/misc/tzparser.c:365 +#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "kunde inte läsa tidszonfil \"%s\": %m" -#: utils/misc/tzparser.c:376 +#: utils/misc/tzparser.c:377 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "raden är för lång i tidszonfil \"%s\", rad %d" -#: utils/misc/tzparser.c:400 +#: utils/misc/tzparser.c:401 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "@INCLUDE utan filnamn i tidszonfil \"%s\", rad %d" -#: utils/mmgr/aset.c:446 utils/mmgr/generation.c:206 utils/mmgr/slab.c:367 +#: utils/mmgr/aset.c:452 utils/mmgr/bump.c:184 utils/mmgr/generation.c:216 +#: utils/mmgr/slab.c:371 #, c-format msgid "Failed while creating memory context \"%s\"." msgstr "Misslyckades vid skapande av minneskontext \"%s\"." -#: utils/mmgr/dsa.c:532 utils/mmgr/dsa.c:1346 +#: utils/mmgr/dsa.c:523 utils/mmgr/dsa.c:1364 #, c-format msgid "could not attach to dynamic shared area" msgstr "kunde inte ansluta till dynamisk delad area" -#: utils/mmgr/mcxt.c:1047 utils/mmgr/mcxt.c:1083 utils/mmgr/mcxt.c:1121 -#: utils/mmgr/mcxt.c:1159 utils/mmgr/mcxt.c:1247 utils/mmgr/mcxt.c:1278 -#: utils/mmgr/mcxt.c:1314 utils/mmgr/mcxt.c:1503 utils/mmgr/mcxt.c:1548 -#: utils/mmgr/mcxt.c:1605 +#: utils/mmgr/mcxt.c:1155 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "Misslyckades med förfrågan av storlek %zu i minneskontext \"%s\"." -#: utils/mmgr/mcxt.c:1210 +#: utils/mmgr/mcxt.c:1299 #, c-format msgid "logging memory contexts of PID %d" msgstr "loggar minneskontext för PID %d" -#: utils/mmgr/portalmem.c:188 +#: utils/mmgr/portalmem.c:187 #, c-format msgid "cursor \"%s\" already exists" msgstr "markör \"%s\" finns redan" -#: utils/mmgr/portalmem.c:192 +#: utils/mmgr/portalmem.c:191 #, c-format msgid "closing existing cursor \"%s\"" msgstr "stänger existerande markör \"%s\"" -#: utils/mmgr/portalmem.c:402 +#: utils/mmgr/portalmem.c:401 #, c-format msgid "portal \"%s\" cannot be run" msgstr "portal \"%s\" kan inte köras" -#: utils/mmgr/portalmem.c:480 +#: utils/mmgr/portalmem.c:479 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "kan inte ta bort fastsatt portal \"%s\"" -#: utils/mmgr/portalmem.c:488 +#: utils/mmgr/portalmem.c:487 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "kan inte ta bort aktiv portal \"%s\"" -#: utils/mmgr/portalmem.c:739 +#: utils/mmgr/portalmem.c:738 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "kan inte göra PREPARE på en transaktion som skapat en markör med WITH HOLD" -#: utils/mmgr/portalmem.c:1230 +#: utils/mmgr/portalmem.c:1232 #, c-format msgid "cannot perform transaction commands inside a cursor loop that is not read-only" msgstr "kan inte utföra transaktionskommandon i en markörloop som inte är read-only" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %ld of temporary file" -msgstr "kunde inte söka (seek) till block %ld i temporärfil" +msgid "could not seek to block %lld of temporary file" +msgstr "kunde inte söka (seek) till block %lld i temporärfil" -#: utils/sort/sharedtuplestore.c:467 +#: utils/sort/sharedtuplestore.c:466 #, c-format msgid "unexpected chunk in shared tuplestore temporary file" msgstr "oväntad chunk i delad temporär lagringsfil för tupler" -#: utils/sort/sharedtuplestore.c:549 +#: utils/sort/sharedtuplestore.c:548 #, c-format msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "kunde inte söka (seek) till block %u i delad temporär lagringsfil för tupler" @@ -29754,17 +30987,17 @@ msgstr "kunde inte söka (seek) till block %u i delad temporär lagringsfil för msgid "cannot have more than %d runs for an external sort" msgstr "kan inte ha mer än %d körningar för en extern sortering" -#: utils/sort/tuplesortvariants.c:1363 +#: utils/sort/tuplesortvariants.c:1552 #, c-format msgid "could not create unique index \"%s\"" msgstr "kunde inte skapa unikt index \"%s\"" -#: utils/sort/tuplesortvariants.c:1365 +#: utils/sort/tuplesortvariants.c:1554 #, c-format msgid "Key %s is duplicated." msgstr "Nyckeln %s är duplicerad." -#: utils/sort/tuplesortvariants.c:1366 +#: utils/sort/tuplesortvariants.c:1555 #, c-format msgid "Duplicate keys exist." msgstr "Duplicerade nycklar existerar." @@ -29778,540 +31011,57 @@ msgstr "Duplicerade nycklar existerar." msgid "could not seek in tuplestore temporary file" msgstr "kunde inte söka i temporär lagringsfil för tupler" -#: utils/time/snapmgr.c:571 +#: utils/time/snapmgr.c:536 #, c-format msgid "The source transaction is not running anymore." msgstr "Källtransaktionen kör inte längre." -#: utils/time/snapmgr.c:1166 +#: utils/time/snapmgr.c:1136 #, c-format msgid "cannot export a snapshot from a subtransaction" -msgstr "kan inte exportera ett snapshot från en subtransaktion" +msgstr "kan inte exportera ett snapshot från en undertransaktion" -#: utils/time/snapmgr.c:1325 utils/time/snapmgr.c:1330 -#: utils/time/snapmgr.c:1335 utils/time/snapmgr.c:1350 -#: utils/time/snapmgr.c:1355 utils/time/snapmgr.c:1360 -#: utils/time/snapmgr.c:1375 utils/time/snapmgr.c:1380 -#: utils/time/snapmgr.c:1385 utils/time/snapmgr.c:1487 -#: utils/time/snapmgr.c:1503 utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 +#: utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 +#: utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 +#: utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 +#: utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 +#: utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "ogiltig snapshot-data i fil \"%s\"" -#: utils/time/snapmgr.c:1422 +#: utils/time/snapmgr.c:1393 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "SET TRANSACTION SNAPSHOT måste anropas innan någon fråga" -#: utils/time/snapmgr.c:1431 +#: utils/time/snapmgr.c:1402 #, c-format msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ" msgstr "en snapshot-importerande transaktion måste ha isoleringsnivå SERIALIZABLE eller REPEATABLE READ" -#: utils/time/snapmgr.c:1440 utils/time/snapmgr.c:1449 +#: utils/time/snapmgr.c:1411 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "ogiltig snapshot-identifierare: \"%s\"" -#: utils/time/snapmgr.c:1541 +#: utils/time/snapmgr.c:1426 +#, c-format +msgid "snapshot \"%s\" does not exist" +msgstr "snapshot \"%s\" existerar inte" + +#: utils/time/snapmgr.c:1524 #, c-format msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction" msgstr "en serialiserbar transaktion kan inte importera ett snapshot från en icke-serialiserbar transaktion" -#: utils/time/snapmgr.c:1545 +#: utils/time/snapmgr.c:1528 #, c-format msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction" msgstr "en serialiserbar transaktion som inte är read-only kan inte importera en snapshot från en read-only-transaktion." -#: utils/time/snapmgr.c:1560 +#: utils/time/snapmgr.c:1543 #, c-format msgid "cannot import a snapshot from a different database" msgstr "kan inte importera en snapshot från en annan databas" - -#, c-format -#~ msgid " -n do not reinitialize shared memory after abnormal exit\n" -#~ msgstr " -n initiera inte delat minne på nytt efter onormal avstängning\n" - -#, c-format -#~ msgid " GSS (authenticated=%s, encrypted=%s)" -#~ msgstr "GSS (autentiserad=%s, krypterad=%s)" - -#, c-format -#~ msgid "Apply system library package updates." -#~ msgstr "Applicera paketuppdateringar för systembibliotek." - -#, c-format -#~ msgid "Close open transactions with multixacts soon to avoid wraparound problems." -#~ msgstr "Stäng öppna transaktioner med multixacts snart för att undvika \"wraparound\"." - -#~ msgid "Controls when to replicate or apply each change." -#~ msgstr "Styr när man skall replikera eller applicera en ändring." - -#, c-format -#~ msgid "FORMAT JSON has no effect for json and jsonb types" -#~ msgstr "FORMAT JSON har ingen effekt på typerna json och jsonb" - -#, c-format -#~ msgid "For example, FROM (SELECT ...) [AS] foo." -#~ msgstr "Till exempel, FROM (SELECT ...) [AS] foo" - -#, c-format -#~ msgid "For example, FROM (VALUES ...) [AS] foo." -#~ msgstr "Till exempel, FROM (VALUES ...) [AS] foo" - -#~ msgid "Forces use of parallel query facilities." -#~ msgstr "Tvingar användning av parallella frågefinesser." - -#, c-format -#~ msgid "Foreign tables cannot have TRUNCATE triggers." -#~ msgstr "Främmande tabeller kan inte ha TRUNCATE-triggrar." - -#~ msgid "If possible, run query using a parallel worker and with parallel restrictions." -#~ msgstr "Om det är möjligt så kör fråga med en parallell arbetare och med parallella begränsningar." - -#, c-format -#~ msgid "In particular, the table cannot be involved in any foreign key relationships." -#~ msgstr "Mer specifikt, tabellen kan inte vare inblandad i främmande-nyckelberoenden." - -#, c-format -#~ msgid "LDAP over SSL is not supported on this platform." -#~ msgstr "LDAP över SSL stöds inte på denna plattform" - -#~ msgid "Number of transactions by which VACUUM and HOT cleanup should be deferred, if any." -#~ msgstr "Antalet transaktioner som VACUUM och HOT-städning skall fördröjas (om någon)." - -#, c-format -#~ msgid "Object keys should be text." -#~ msgstr "Objektnycklar skall vara text." - -#, c-format -#~ msgid "Omit the generation expression in the definition of the child table column to inherit the generation expression from the parent table." -#~ msgstr "Utelämna genereringsuttrycket i definitionen av barntabellkolumnen för att ärva genereringsuttrycket från föräldratabellen." - -#~ msgid "Shows the character classification and case conversion locale." -#~ msgstr "Visar lokal för teckenklassificering samt skiftlägeskonvertering." - -#~ msgid "Shows the collation order locale." -#~ msgstr "Visar lokal för jämförelseordning." - -#~ msgid "Specifies a file name whose presence ends recovery in the standby." -#~ msgstr "Anger ett filnamn vars närvaro gör att återställning avslutas i en standby." - -#, c-format -#~ msgid "Subscribed publication %s is subscribing to other publications." -#~ msgid_plural "Subscribed publications %s are subscribing to other publications." -#~ msgstr[0] "Prenumererad publicering %s prenumererar på andra publiceringar." -#~ msgstr[1] "Prenumererade publiceringar %s prenumererar på andra publiceringar." - -#, c-format -#~ msgid "The owner of a subscription must be a superuser." -#~ msgstr "Ägaren av en prenumeration måste vara en superuser." - -#, c-format -#~ msgid "VALUES in FROM must have an alias" -#~ msgstr "VALUES i FROM måste ha ett alias" - -#, c-format -#~ msgid "Valid options in this context are: %s" -#~ msgstr "Giltiga flaggor i detta kontext är: %s" - -#, c-format -#~ msgid "You might need to increase max_locks_per_transaction." -#~ msgstr "Du kan behöva öka parametern max_locks_per_transaction." - -#, c-format -#~ msgid "You might need to increase max_logical_replication_workers." -#~ msgstr "Du kan behöva öka max_logical_replication_workers." - -#, c-format -#~ msgid "You might need to increase max_pred_locks_per_transaction." -#~ msgstr "Du kan behöva öka parametern max_pred_locks_per_transaction." - -#, c-format -#~ msgid "You might need to increase max_worker_processes." -#~ msgstr "Du kan behöva öka max_worker_processes." - -#, c-format -#~ msgid "argument %d cannot be null" -#~ msgstr "argument %d kan inte vara null" - -#, c-format -#~ msgid "authentication file token too long, skipping: \"%s\"" -#~ msgstr "autentiseringsfil-token för lång, hoppar över: \"%s\"" - -#, c-format -#~ msgid "cannot convert partition \"%s\" to a view" -#~ msgstr "kan inte konvertera partition \"%s\" till en vy" - -#, c-format -#~ msgid "cannot convert partitioned table \"%s\" to a view" -#~ msgstr "kan inte konvertera partitionerad tabell \"%s\" till en vy" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "kan inte skapa token för begränsad åtkomst på denna plattorm: felkod %lu" - -#, c-format -#~ msgid "cannot read from logical replication slot \"%s\"" -#~ msgstr "kan inte läsa från logisk replikeringsslot \"%s\"" - -#, c-format -#~ msgid "column \"%s\" in child table has a conflicting generation expression" -#~ msgstr "kolumn \"%s\" i barntabell har ett motstridigt genereringsuttryck" - -#, c-format -#~ msgid "conversion with OID %u does not exist" -#~ msgstr "konvertering med OID %u existerar inte" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has child tables" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy då den har barntabeller" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has indexes" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy eftersom den har index" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has parent tables" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy då den har föräldratabeller" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has row security enabled" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy eftersom den har radsäkerhet påslagen" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has row security policies" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy eftersom den har radsäkerhetspolicy" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it has triggers" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy då den har triggrar" - -#, c-format -#~ msgid "could not convert table \"%s\" to a view because it is not empty" -#~ msgstr "kunde inte konvertera tabell \"%s\" till en vy då den inte är tom" - -#, c-format -#~ msgid "could not form array type name for type \"%s\"" -#~ msgstr "kunde inte skapa array-typnamn för typ \"%s\"" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not link file \"%s\" to \"%s\": %m" -#~ msgstr "kunde inte länka fil \"%s\" till \"%s\": %m" - -#, c-format -#~ msgid "could not load function _ldap_start_tls_sA in wldap32.dll" -#~ msgstr "kunde inte ladda funktionen _ldap_start_tls_sA i wldap32.dll" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "kunde inte ladda länkbibliotek \"%s\": felkod %lu" - -#, c-format -#~ msgid "could not load pg_hba.conf" -#~ msgstr "kunde inte ladda pg_hba.conf" - -#, c-format -#~ msgid "could not open secondary authentication file \"@%s\" as \"%s\": %m" -#~ msgstr "kunde inte öppna sekundär autentiseringsfil \"@%s\" som \"%s\": %m" - -#, c-format -#~ msgid "could not open usermap file \"%s\": %m" -#~ msgstr "kunde inte öppna användarmappningsfil \"%s\": %m" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "kunde inte läsa binär \"%s\"" - -#, c-format -#~ msgid "could not read block %ld of temporary file: read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa block %ld i temporärfil: läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not read from hash-join temporary file: read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa från hash-join-temporärfil: läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not read from shared tuplestore temporary file" -#~ msgstr "kunde inte läsa från delad temporär lagringsfil för tupler" - -#, c-format -#~ msgid "could not read from shared tuplestore temporary file: read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa från delad temporär lagringsfil för tupler: läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not read from streaming transaction's changes file \"%s\": read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa från strömmande transaktionens ändringsfil \"%s\": läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not read from streaming transaction's subxact file \"%s\": read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa från strömmande transaktions subxact-fil \"%s\": läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not read from tuplestore temporary file: read only %zu of %zu bytes" -#~ msgstr "kunde inte läsa från temporär lagringsfil för tupler: läste bara %zu av %zu byte" - -#, c-format -#~ msgid "could not remove file or directory \"%s\": %m" -#~ msgstr "kunde inte ta bort fil eller katalog \"%s\": %m" - -#, c-format -#~ msgid "could not stat promote trigger file \"%s\": %m" -#~ msgstr "kunde inte göra stat() på triggerfil för befordring \"%s\": %m" - -#, c-format -#~ msgid "duplicate JSON key %s" -#~ msgstr "Duplicerad JSON-nyckel %s" - -#, c-format -#~ msgid "duplicate JSON object key" -#~ msgstr "duplicerad nyckel i JSON-objekt" - -#, c-format -#~ msgid "extension with OID %u does not exist" -#~ msgstr "utökning med OID %u existerar inte" - -#, c-format -#~ msgid "generated columns are not supported on partitions" -#~ msgstr "genererade kolumner stöds inte för partitioner" - -#, c-format -#~ msgid "gtsvector_in not implemented" -#~ msgstr "gtsvector_in är inte implementerad" - -#, c-format -#~ msgid "invalid checkpoint link in backup_label file" -#~ msgstr "ogiltig checkpoint-länk i \"backup_label\"-fil" - -#, c-format -#~ msgid "invalid info bits %04X in log segment %s, offset %u" -#~ msgstr "ogiltiga infobitar %04X i loggsegment %s, offset %u" - -#, c-format -#~ msgid "invalid length of primary checkpoint record" -#~ msgstr "ogiltig längd i primär checkpoint-post" - -#, c-format -#~ msgid "invalid magic number %04X in log segment %s, offset %u" -#~ msgstr "felaktigt magiskt nummer %04X i loggsegment %s, offset %u" - -#, c-format -#~ msgid "invalid primary checkpoint link in control file" -#~ msgstr "ogiltig primär checkpoint-länk i kontrollfil" - -#, c-format -#~ msgid "invalid primary checkpoint record" -#~ msgstr "ogiltig primär checkpoint-post" - -#, c-format -#~ msgid "invalid record length at %X/%X: wanted %u, got %u" -#~ msgstr "ogiltig postlängd vid %X/%X: förväntade %u, fick %u" - -#, c-format -#~ msgid "invalid record offset at %X/%X" -#~ msgstr "ogiltig postoffset vid %X/%X" - -#, c-format -#~ msgid "invalid resource manager ID in primary checkpoint record" -#~ msgstr "ogiltig resurshanterar-ID i primär checkpoint-post" - -#, c-format -#~ msgid "invalid xl_info in primary checkpoint record" -#~ msgstr "ogiltig xl_info i primär checkpoint-post" - -#, c-format -#~ msgid "invalidating slot \"%s\" because its restart_lsn %X/%X exceeds max_slot_wal_keep_size" -#~ msgstr "invaliderar slot \"%s\" då dess restart_lsn %X/%X överskrider max_slot_wal_keep_size" - -#, c-format -#~ msgid "language with OID %u does not exist" -#~ msgstr "språk med OID %u existerar inte" - -#, c-format -#~ msgid "local connections are not supported by this build" -#~ msgstr "lokala anslutningar stöds inte av detta bygge" - -#, c-format -#~ msgid "logical decoding cannot be used while in recovery" -#~ msgstr "logisk avkodning kan inte användas under återställning" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "det saknas en contrecord vid %X/%X" - -#, c-format -#~ msgid "must be a member of the role whose process is being terminated or member of pg_signal_backend" -#~ msgstr "måste vara medlem i den roll vars process håller på att avslutas eller medlem i pg_signal_backend" - -#, c-format -#~ msgid "must be a member of the role whose query is being canceled or member of pg_signal_backend" -#~ msgstr "måste vara medlem i den roll vars fråga håller på att avbrytas eller medlem i pg_signal_backend" - -#, c-format -#~ msgid "must be a superuser to cancel superuser query" -#~ msgstr "måste vara superuser för att avbryta en superusers fråga" - -#, c-format -#~ msgid "must be a superuser to terminate superuser process" -#~ msgstr "måste vara superuser för stoppa en superusers process" - -#, c-format -#~ msgid "must be superuser or have privileges of pg_checkpoint to do CHECKPOINT" -#~ msgstr "måste vara superuser eller ha rättigheter från pg_checkpoint att göra CHECKPOINT" - -#, c-format -#~ msgid "must be superuser or have privileges of pg_read_all_settings to examine \"%s\"" -#~ msgstr "måste vara superuser eller ha rättigheter från pg_read_all_settings för att undersöka \"%s\"" - -#, c-format -#~ msgid "must be superuser or replication role to start walsender" -#~ msgstr "måste vara superuser eller replikeringsroll för att starta \"walsender\"" - -#, c-format -#~ msgid "must be superuser or replication role to use replication slots" -#~ msgstr "måste vara superuser eller replikeringsroll för att använda replikeringsslottar" - -#, c-format -#~ msgid "must be superuser to alter replication roles or change replication attribute" -#~ msgstr "måste vara en superuser eller replikeringsroll för att använda replikeringsslottar" - -#, c-format -#~ msgid "must be superuser to alter superuser roles or change superuser attribute" -#~ msgstr "måste vara superuser för ändra superuser-roller eller ändra superuser-attribut" - -#, c-format -#~ msgid "must be superuser to alter superusers" -#~ msgstr "måste vara en superuser för att ändra en superuser" - -#, c-format -#~ msgid "must be superuser to change bypassrls attribute" -#~ msgstr "måste vara en superuser för ändra bypassrls-attribut" - -#, c-format -#~ msgid "must be superuser to create bypassrls users" -#~ msgstr "måste vara en superuser för att skapa bypassrls-användare" - -#, c-format -#~ msgid "must be superuser to create replication users" -#~ msgstr "måste vara en superuser för att skapa replikeringsanvändare" - -#, c-format -#~ msgid "must be superuser to create subscriptions" -#~ msgstr "måste vara en superuser för att skapa prenumerationer" - -#, c-format -#~ msgid "must be superuser to create superusers" -#~ msgstr "måste vara en superuser för att skapa nya superuser" - -#, c-format -#~ msgid "must be superuser to drop superusers" -#~ msgstr "måste vara en superuser för att ta bort en superuser" - -#, c-format -#~ msgid "must be superuser to rename superusers" -#~ msgstr "måste vara en superuser för att döpa om en superúser" - -#, c-format -#~ msgid "must be superuser to set grantor" -#~ msgstr "måste vara en superuser för att sätta fullmaktsgivare" - -#, c-format -#~ msgid "must be superuser to skip transaction" -#~ msgstr "måste vara en superuser för att hoppa över transaktioner" - -#, c-format -#~ msgid "must have CREATEROLE privilege" -#~ msgstr "måste ha rättigheten CREATEROLE" - -#, c-format -#~ msgid "oldest xmin is far in the past" -#~ msgstr "äldsta xmin är från lång tid tillbaka" - -#, c-format -#~ msgid "operator class with OID %u does not exist" -#~ msgstr "operatorklass med OID %u existerar inte" - -#, c-format -#~ msgid "operator family with OID %u does not exist" -#~ msgstr "operatorfamilj med OID %u existerar inte" - -#, c-format -#~ msgid "operator with OID %u does not exist" -#~ msgstr "operator med OID %u existerar inte" - -# FIXME -#, c-format -#~ msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u" -#~ msgstr "\"ej i sekvens\"-fel på tidslinje-ID %u (efter %u) i loggsegment %s, offset %u" - -#, c-format -#~ msgid "permission denied to change owner of subscription \"%s\"" -#~ msgstr "rättighet saknas för att byta ägare på prenumeration \"%s\"" - -#, c-format -#~ msgid "promote trigger file found: %s" -#~ msgstr "triggerfil för befordring hittad: %s" - -#, c-format -#~ msgid "select() failed in postmaster: %m" -#~ msgstr "select() misslyckades i postmaster: %m" - -#, c-format -#~ msgid "skipping \"%s\" --- only superuser can analyze it" -#~ msgstr "hoppar över \"%s\" --- bara superuser kan analysera den" - -#, c-format -#~ msgid "skipping \"%s\" --- only superuser can vacuum it" -#~ msgstr "hoppar över \"%s\" --- bara en superuser kan städa den" - -#, c-format -#~ msgid "skipping \"%s\" --- only superuser or database owner can analyze it" -#~ msgstr "hoppar över \"%s\" --- bara superuser eller databasägaren kan analysera den" - -#, c-format -#~ msgid "skipping \"%s\" --- only superuser or database owner can vacuum it" -#~ msgstr "hoppar över \"%s\" --- bara en superuser eller databasägaren kan städa den" - -#, c-format -#~ msgid "skipping \"%s\" --- only table or database owner can analyze it" -#~ msgstr "hoppar över \"%s\" --- bara tabell eller databasägaren kan analysera den" - -#, c-format -#~ msgid "skipping \"%s\" --- only table or database owner can vacuum it" -#~ msgstr "hoppar över \"%s\" --- bara tabell eller databasägaren kan köra vacuum på den" - -#, c-format -#~ msgid "statistics object with OID %u does not exist" -#~ msgstr "statistikobjekt med OID %u finns inte" - -#, c-format -#~ msgid "subquery in FROM must have an alias" -#~ msgstr "subfråga i FROM måste ha ett alias" - -#, c-format -#~ msgid "tables were not subscribed, you will have to run %s to subscribe the tables" -#~ msgstr "tabellerna prenumererades inte på, du behöver köra %s för att prenumerera på dessa tabeller" - -#, c-format -#~ msgid "tablespaces are not supported on this platform" -#~ msgstr "tabellutrymmen stöds inte på denna plattform" - -#, c-format -#~ msgid "text search configuration with OID %u does not exist" -#~ msgstr "textsökkonfiguration med OID %u existerar inte" - -#, c-format -#~ msgid "text search dictionary with OID %u does not exist" -#~ msgstr "textsökordlista med OID %u existerar inte" - -#, c-format -#~ msgid "unexpected EOF for tape %p: requested %zu bytes, read %zu bytes" -#~ msgstr "oväntat EOF för band %p: efterfrågade %zu byte, läste %zu byte" - -#, c-format -#~ msgid "unexpected pageaddr %X/%X in log segment %s, offset %u" -#~ msgstr "oväntad sidadress %X/%X i loggsegment %s, offset %u" diff --git a/src/backend/po/uk.po b/src/backend/po/uk.po index 1e9c7943db916..6c4c0add9ee56 100644 --- a/src/backend/po/uk.po +++ b/src/backend/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-09 18:10+0000\n" -"PO-Revision-Date: 2024-02-11 17:37+0100\n" +"POT-Creation-Date: 2024-09-23 10:41+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,9 +14,13 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/postgres.pot\n" -"X-Crowdin-File-ID: 951\n" -"X-Generator: Poedit 3.4.2\n" +"X-Crowdin-File: /REL_17_STABLE/postgres.pot\n" +"X-Crowdin-File-ID: 988\n" + +#: ../common/binaryheap.c:121 ../common/binaryheap.c:159 +#, c-format +msgid "out of binary heap slots" +msgstr "недостатньо слотів двійкової купи" #: ../common/compression.c:132 ../common/compression.c:141 #: ../common/compression.c:150 @@ -75,209 +79,225 @@ msgstr "алгоритм стиснення \"%s\" не підтримує ре msgid "not recorded" msgstr "не записано" -#: ../common/controldata_utils.c:79 ../common/controldata_utils.c:83 -#: commands/copyfrom.c:1687 commands/extension.c:3480 utils/adt/genfile.c:123 +#: ../common/controldata_utils.c:93 ../common/controldata_utils.c:97 +#: commands/copyfrom.c:1739 commands/extension.c:3538 utils/adt/genfile.c:123 +#: utils/time/snapmgr.c:1430 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не вдалося відкрити файл \"%s\" для читання: %m" -#: ../common/controldata_utils.c:94 ../common/controldata_utils.c:96 +#: ../common/controldata_utils.c:108 ../common/controldata_utils.c:110 #: access/transam/timeline.c:143 access/transam/timeline.c:362 -#: access/transam/twophase.c:1347 access/transam/xlog.c:3195 -#: access/transam/xlog.c:3998 access/transam/xlogrecovery.c:1225 -#: access/transam/xlogrecovery.c:1317 access/transam/xlogrecovery.c:1354 -#: access/transam/xlogrecovery.c:1414 backup/basebackup.c:1842 -#: commands/extension.c:3490 libpq/hba.c:769 replication/logical/origin.c:745 -#: replication/logical/origin.c:781 replication/logical/reorderbuffer.c:5050 -#: replication/logical/snapbuild.c:2031 replication/slot.c:1953 -#: replication/slot.c:1994 replication/walsender.c:643 +#: access/transam/twophase.c:1369 access/transam/xlog.c:3476 +#: access/transam/xlog.c:4340 access/transam/xlogrecovery.c:1238 +#: access/transam/xlogrecovery.c:1336 access/transam/xlogrecovery.c:1373 +#: access/transam/xlogrecovery.c:1440 backup/basebackup.c:2123 +#: backup/walsummary.c:283 commands/extension.c:3548 libpq/hba.c:764 +#: replication/logical/origin.c:745 replication/logical/origin.c:781 +#: replication/logical/reorderbuffer.c:5108 +#: replication/logical/snapbuild.c:2052 replication/slot.c:2236 +#: replication/slot.c:2277 replication/walsender.c:655 #: storage/file/buffile.c:470 storage/file/copydir.c:185 -#: utils/adt/genfile.c:197 utils/adt/misc.c:984 utils/cache/relmapper.c:830 +#: utils/adt/genfile.c:197 utils/adt/misc.c:1028 utils/cache/relmapper.c:829 #, c-format msgid "could not read file \"%s\": %m" msgstr "не вдалося прочитати файл \"%s\": %m" -#: ../common/controldata_utils.c:102 ../common/controldata_utils.c:105 -#: access/transam/xlog.c:3200 access/transam/xlog.c:4003 -#: backup/basebackup.c:1846 replication/logical/origin.c:750 -#: replication/logical/origin.c:789 replication/logical/snapbuild.c:2036 -#: replication/slot.c:1957 replication/slot.c:1998 replication/walsender.c:648 -#: utils/cache/relmapper.c:834 +#: ../common/controldata_utils.c:116 ../common/controldata_utils.c:119 +#: access/transam/xlog.c:3481 access/transam/xlog.c:4345 +#: replication/logical/origin.c:750 replication/logical/origin.c:789 +#: replication/logical/snapbuild.c:2057 replication/slot.c:2240 +#: replication/slot.c:2281 replication/walsender.c:660 +#: utils/cache/relmapper.c:833 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" -#: ../common/controldata_utils.c:114 ../common/controldata_utils.c:118 -#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:266 -#: access/heap/rewriteheap.c:1175 access/heap/rewriteheap.c:1280 +#: ../common/controldata_utils.c:128 ../common/controldata_utils.c:132 +#: ../common/controldata_utils.c:277 ../common/controldata_utils.c:280 +#: access/heap/rewriteheap.c:1141 access/heap/rewriteheap.c:1246 #: access/transam/timeline.c:392 access/transam/timeline.c:438 -#: access/transam/timeline.c:512 access/transam/twophase.c:1359 -#: access/transam/twophase.c:1771 access/transam/xlog.c:3041 -#: access/transam/xlog.c:3235 access/transam/xlog.c:3240 -#: access/transam/xlog.c:3376 access/transam/xlog.c:3968 -#: access/transam/xlog.c:4887 commands/copyfrom.c:1747 commands/copyto.c:332 +#: access/transam/timeline.c:512 access/transam/twophase.c:1381 +#: access/transam/twophase.c:1793 access/transam/xlog.c:3322 +#: access/transam/xlog.c:3516 access/transam/xlog.c:3521 +#: access/transam/xlog.c:3657 access/transam/xlog.c:4310 +#: access/transam/xlog.c:5245 commands/copyfrom.c:1799 commands/copyto.c:325 #: libpq/be-fsstubs.c:470 libpq/be-fsstubs.c:540 #: replication/logical/origin.c:683 replication/logical/origin.c:822 -#: replication/logical/reorderbuffer.c:5102 -#: replication/logical/snapbuild.c:1798 replication/logical/snapbuild.c:1922 -#: replication/slot.c:1844 replication/slot.c:2005 replication/walsender.c:658 -#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:782 -#: storage/file/fd.c:3700 storage/file/fd.c:3806 utils/cache/relmapper.c:842 -#: utils/cache/relmapper.c:957 +#: replication/logical/reorderbuffer.c:5160 +#: replication/logical/snapbuild.c:1819 replication/logical/snapbuild.c:1943 +#: replication/slot.c:2126 replication/slot.c:2288 replication/walsender.c:670 +#: storage/file/copydir.c:208 storage/file/copydir.c:213 storage/file/fd.c:828 +#: storage/file/fd.c:3753 storage/file/fd.c:3859 utils/cache/relmapper.c:841 +#: utils/cache/relmapper.c:956 #, c-format msgid "could not close file \"%s\": %m" msgstr "неможливо закрити файл \"%s\": %m" -#: ../common/controldata_utils.c:154 +#: ../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "неправильний порядок байтів" -#: ../common/controldata_utils.c:156 +#: ../common/controldata_utils.c:170 #, c-format -msgid "" -"possible byte ordering mismatch\n" +msgid "possible byte ordering mismatch\n" "The byte ordering used to store the pg_control file might not match the one\n" "used by this program. In that case the results below would be incorrect, and\n" "the PostgreSQL installation would be incompatible with this data directory." -msgstr "" -"можлива помилка у послідовності байтів.\n" +msgstr "можлива помилка у послідовності байтів.\n" "Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." -#: ../common/controldata_utils.c:211 ../common/controldata_utils.c:216 -#: ../common/file_utils.c:228 ../common/file_utils.c:287 -#: ../common/file_utils.c:361 access/heap/rewriteheap.c:1263 -#: access/transam/timeline.c:111 access/transam/timeline.c:251 -#: access/transam/timeline.c:348 access/transam/twophase.c:1303 -#: access/transam/xlog.c:2948 access/transam/xlog.c:3111 -#: access/transam/xlog.c:3150 access/transam/xlog.c:3343 -#: access/transam/xlog.c:3988 access/transam/xlogrecovery.c:4213 -#: access/transam/xlogrecovery.c:4316 access/transam/xlogutils.c:838 -#: backup/basebackup.c:538 backup/basebackup.c:1512 libpq/hba.c:629 -#: postmaster/syslogger.c:1560 replication/logical/origin.c:735 -#: replication/logical/reorderbuffer.c:3706 -#: replication/logical/reorderbuffer.c:4257 -#: replication/logical/reorderbuffer.c:5030 -#: replication/logical/snapbuild.c:1753 replication/logical/snapbuild.c:1863 -#: replication/slot.c:1925 replication/walsender.c:616 -#: replication/walsender.c:2731 storage/file/copydir.c:151 -#: storage/file/fd.c:757 storage/file/fd.c:3457 storage/file/fd.c:3687 -#: storage/file/fd.c:3777 storage/smgr/md.c:663 utils/cache/relmapper.c:819 -#: utils/cache/relmapper.c:936 utils/error/elog.c:2086 -#: utils/init/miscinit.c:1537 utils/init/miscinit.c:1671 -#: utils/init/miscinit.c:1748 utils/misc/guc.c:4609 utils/misc/guc.c:4659 +#: ../common/controldata_utils.c:225 ../common/controldata_utils.c:230 +#: ../common/file_utils.c:70 ../common/file_utils.c:347 +#: ../common/file_utils.c:406 ../common/file_utils.c:480 +#: access/heap/rewriteheap.c:1229 access/transam/timeline.c:111 +#: access/transam/timeline.c:251 access/transam/timeline.c:348 +#: access/transam/twophase.c:1325 access/transam/xlog.c:3229 +#: access/transam/xlog.c:3392 access/transam/xlog.c:3431 +#: access/transam/xlog.c:3624 access/transam/xlog.c:4330 +#: access/transam/xlogrecovery.c:4263 access/transam/xlogrecovery.c:4366 +#: access/transam/xlogutils.c:836 backup/basebackup.c:547 +#: backup/basebackup.c:1598 backup/walsummary.c:220 libpq/hba.c:624 +#: postmaster/syslogger.c:1511 replication/logical/origin.c:735 +#: replication/logical/reorderbuffer.c:3761 +#: replication/logical/reorderbuffer.c:4315 +#: replication/logical/reorderbuffer.c:5088 +#: replication/logical/snapbuild.c:1774 replication/logical/snapbuild.c:1884 +#: replication/slot.c:2208 replication/walsender.c:628 +#: replication/walsender.c:3051 storage/file/copydir.c:151 +#: storage/file/fd.c:803 storage/file/fd.c:3510 storage/file/fd.c:3740 +#: storage/file/fd.c:3830 storage/smgr/md.c:661 utils/cache/relmapper.c:818 +#: utils/cache/relmapper.c:935 utils/error/elog.c:2124 +#: utils/init/miscinit.c:1526 utils/init/miscinit.c:1660 +#: utils/init/miscinit.c:1737 utils/misc/guc.c:4736 utils/misc/guc.c:4786 #, c-format msgid "could not open file \"%s\": %m" msgstr "не можливо відкрити файл \"%s\": %m" -#: ../common/controldata_utils.c:232 ../common/controldata_utils.c:235 -#: access/transam/twophase.c:1744 access/transam/twophase.c:1753 -#: access/transam/xlog.c:8757 access/transam/xlogfuncs.c:708 -#: backup/basebackup_server.c:175 backup/basebackup_server.c:268 -#: postmaster/postmaster.c:5573 postmaster/syslogger.c:1571 -#: postmaster/syslogger.c:1584 postmaster/syslogger.c:1597 -#: utils/cache/relmapper.c:948 +#: ../common/controldata_utils.c:246 ../common/controldata_utils.c:249 +#: access/transam/twophase.c:1766 access/transam/twophase.c:1775 +#: access/transam/xlog.c:9255 access/transam/xlogfuncs.c:698 +#: backup/basebackup_server.c:173 backup/basebackup_server.c:266 +#: backup/walsummary.c:304 postmaster/postmaster.c:4125 +#: postmaster/syslogger.c:1522 postmaster/syslogger.c:1535 +#: postmaster/syslogger.c:1548 utils/cache/relmapper.c:947 #, c-format msgid "could not write file \"%s\": %m" msgstr "не вдалося записати файл \"%s\": %m" -#: ../common/controldata_utils.c:249 ../common/controldata_utils.c:254 -#: ../common/file_utils.c:299 ../common/file_utils.c:369 -#: access/heap/rewriteheap.c:959 access/heap/rewriteheap.c:1169 -#: access/heap/rewriteheap.c:1274 access/transam/timeline.c:432 -#: access/transam/timeline.c:506 access/transam/twophase.c:1765 -#: access/transam/xlog.c:3034 access/transam/xlog.c:3229 -#: access/transam/xlog.c:3961 access/transam/xlog.c:8147 -#: access/transam/xlog.c:8192 backup/basebackup_server.c:209 -#: commands/dbcommands.c:515 replication/logical/snapbuild.c:1791 -#: replication/slot.c:1830 replication/slot.c:1935 storage/file/fd.c:774 -#: storage/file/fd.c:3798 storage/smgr/md.c:1135 storage/smgr/md.c:1180 -#: storage/sync/sync.c:451 utils/misc/guc.c:4379 +#: ../common/controldata_utils.c:263 ../common/controldata_utils.c:268 +#: ../common/file_utils.c:418 ../common/file_utils.c:488 +#: access/heap/rewriteheap.c:925 access/heap/rewriteheap.c:1135 +#: access/heap/rewriteheap.c:1240 access/transam/timeline.c:432 +#: access/transam/timeline.c:506 access/transam/twophase.c:1787 +#: access/transam/xlog.c:3315 access/transam/xlog.c:3510 +#: access/transam/xlog.c:4303 access/transam/xlog.c:8630 +#: access/transam/xlog.c:8675 backup/basebackup_server.c:207 +#: commands/dbcommands.c:514 replication/logical/snapbuild.c:1812 +#: replication/slot.c:2112 replication/slot.c:2218 storage/file/fd.c:820 +#: storage/file/fd.c:3851 storage/smgr/md.c:1329 storage/smgr/md.c:1374 +#: storage/sync/sync.c:446 utils/misc/guc.c:4489 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не вдалося fsync файл \"%s\": %m" -#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:133 -#: ../common/cryptohash_openssl.c:332 ../common/exec.c:550 ../common/exec.c:595 -#: ../common/exec.c:687 ../common/hmac.c:309 ../common/hmac.c:325 -#: ../common/hmac_openssl.c:132 ../common/hmac_openssl.c:327 -#: ../common/md5_common.c:155 ../common/psprintf.c:143 -#: ../common/scram-common.c:269 ../common/stringinfo.c:305 ../port/path.c:751 -#: ../port/path.c:789 ../port/path.c:806 access/transam/twophase.c:1412 -#: access/transam/xlogrecovery.c:589 lib/dshash.c:253 libpq/auth.c:1343 -#: libpq/auth.c:1387 libpq/auth.c:1944 libpq/be-secure-gssapi.c:524 -#: postmaster/bgworker.c:352 postmaster/bgworker.c:934 -#: postmaster/postmaster.c:2537 postmaster/postmaster.c:4130 -#: postmaster/postmaster.c:5498 postmaster/postmaster.c:5869 -#: replication/libpqwalreceiver/libpqwalreceiver.c:361 -#: replication/logical/logical.c:208 replication/walsender.c:686 -#: storage/buffer/localbuf.c:601 storage/file/fd.c:866 storage/file/fd.c:1397 -#: storage/file/fd.c:1558 storage/file/fd.c:2478 storage/ipc/procarray.c:1449 -#: storage/ipc/procarray.c:2231 storage/ipc/procarray.c:2238 -#: storage/ipc/procarray.c:2737 storage/ipc/procarray.c:3373 -#: utils/adt/formatting.c:1690 utils/adt/formatting.c:1812 -#: utils/adt/formatting.c:1935 utils/adt/pg_locale.c:473 -#: utils/adt/pg_locale.c:637 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:514 -#: utils/hash/dynahash.c:614 utils/hash/dynahash.c:1111 utils/mb/mbutils.c:402 -#: utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 utils/mb/mbutils.c:842 -#: utils/misc/guc.c:640 utils/misc/guc.c:665 utils/misc/guc.c:1053 -#: utils/misc/guc.c:4357 utils/misc/tzparser.c:476 utils/mmgr/aset.c:445 -#: utils/mmgr/dsa.c:714 utils/mmgr/dsa.c:736 utils/mmgr/dsa.c:817 -#: utils/mmgr/generation.c:205 utils/mmgr/mcxt.c:1046 utils/mmgr/mcxt.c:1082 -#: utils/mmgr/mcxt.c:1120 utils/mmgr/mcxt.c:1158 utils/mmgr/mcxt.c:1246 -#: utils/mmgr/mcxt.c:1277 utils/mmgr/mcxt.c:1313 utils/mmgr/mcxt.c:1502 -#: utils/mmgr/mcxt.c:1547 utils/mmgr/mcxt.c:1604 utils/mmgr/slab.c:366 +#: ../common/cryptohash.c:261 ../common/cryptohash_openssl.c:158 +#: ../common/cryptohash_openssl.c:356 ../common/exec.c:562 ../common/exec.c:607 +#: ../common/exec.c:699 ../common/hmac.c:309 ../common/hmac.c:325 +#: ../common/hmac_openssl.c:160 ../common/hmac_openssl.c:357 +#: ../common/md5_common.c:156 ../common/parse_manifest.c:157 +#: ../common/parse_manifest.c:853 ../common/psprintf.c:143 +#: ../common/scram-common.c:269 ../common/stringinfo.c:314 ../port/path.c:751 +#: ../port/path.c:788 ../port/path.c:805 access/transam/twophase.c:1434 +#: access/transam/xlogrecovery.c:564 lib/dshash.c:253 libpq/auth.c:1352 +#: libpq/auth.c:1396 libpq/auth.c:1953 libpq/be-secure-gssapi.c:524 +#: postmaster/bgworker.c:355 postmaster/bgworker.c:945 +#: postmaster/postmaster.c:3559 postmaster/postmaster.c:4019 +#: postmaster/postmaster.c:4381 postmaster/walsummarizer.c:935 +#: replication/libpqwalreceiver/libpqwalreceiver.c:387 +#: replication/logical/logical.c:210 replication/walsender.c:835 +#: storage/buffer/localbuf.c:606 storage/file/fd.c:912 storage/file/fd.c:1443 +#: storage/file/fd.c:1604 storage/file/fd.c:2531 storage/ipc/procarray.c:1465 +#: storage/ipc/procarray.c:2219 storage/ipc/procarray.c:2226 +#: storage/ipc/procarray.c:2731 storage/ipc/procarray.c:3435 +#: utils/adt/formatting.c:1725 utils/adt/formatting.c:1873 +#: utils/adt/formatting.c:2075 utils/adt/pg_locale.c:509 +#: utils/adt/pg_locale.c:673 utils/fmgr/dfmgr.c:229 utils/hash/dynahash.c:516 +#: utils/hash/dynahash.c:616 utils/hash/dynahash.c:1099 utils/mb/mbutils.c:401 +#: utils/mb/mbutils.c:429 utils/mb/mbutils.c:814 utils/mb/mbutils.c:841 +#: utils/misc/guc.c:649 utils/misc/guc.c:674 utils/misc/guc.c:1062 +#: utils/misc/guc.c:4467 utils/misc/tzparser.c:477 utils/mmgr/aset.c:451 +#: utils/mmgr/bump.c:183 utils/mmgr/dsa.c:707 utils/mmgr/dsa.c:729 +#: utils/mmgr/dsa.c:810 utils/mmgr/generation.c:215 utils/mmgr/mcxt.c:1154 +#: utils/mmgr/slab.c:370 #, c-format msgid "out of memory" msgstr "недостатньо пам'яті" #: ../common/cryptohash.c:266 ../common/cryptohash.c:272 -#: ../common/cryptohash_openssl.c:344 ../common/cryptohash_openssl.c:352 -#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:339 -#: ../common/hmac_openssl.c:347 +#: ../common/cryptohash_openssl.c:368 ../common/cryptohash_openssl.c:376 +#: ../common/hmac.c:321 ../common/hmac.c:329 ../common/hmac_openssl.c:369 +#: ../common/hmac_openssl.c:377 msgid "success" msgstr "успіх" -#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:346 -#: ../common/hmac_openssl.c:341 +#: ../common/cryptohash.c:268 ../common/cryptohash_openssl.c:370 +#: ../common/hmac_openssl.c:371 msgid "destination buffer too small" msgstr "буфер призначення занадто малий" -#: ../common/cryptohash_openssl.c:348 ../common/hmac_openssl.c:343 +#: ../common/cryptohash_openssl.c:372 ../common/hmac_openssl.c:373 msgid "OpenSSL failure" msgstr "Помилка OpenSSL" -#: ../common/exec.c:172 +#: ../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../common/exec.c:215 +#: ../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../common/exec.c:223 +#: ../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../common/exec.c:250 +#: ../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../common/exec.c:412 libpq/pqcomm.c:728 storage/ipc/latch.c:1128 -#: storage/ipc/latch.c:1308 storage/ipc/latch.c:1541 storage/ipc/latch.c:1703 -#: storage/ipc/latch.c:1829 +#: ../common/exec.c:382 commands/collationcmds.c:876 commands/copyfrom.c:1723 +#: commands/copyto.c:650 libpq/be-secure-common.c:59 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../common/exec.c:394 libpq/be-secure-common.c:71 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../common/exec.c:424 libpq/pqcomm.c:192 storage/ipc/latch.c:1169 +#: storage/ipc/latch.c:1349 storage/ipc/latch.c:1582 storage/ipc/latch.c:1744 +#: storage/ipc/latch.c:1870 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" #: ../common/fe_memutils.c:35 ../common/fe_memutils.c:75 #: ../common/fe_memutils.c:98 ../common/fe_memutils.c:161 -#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:791 -#: ../port/path.c:808 utils/misc/ps_status.c:168 utils/misc/ps_status.c:176 -#: utils/misc/ps_status.c:203 utils/misc/ps_status.c:211 +#: ../common/psprintf.c:145 ../port/path.c:753 ../port/path.c:790 +#: ../port/path.c:807 utils/misc/ps_status.c:193 utils/misc/ps_status.c:201 +#: utils/misc/ps_status.c:228 utils/misc/ps_status.c:236 #, c-format msgid "out of memory\n" msgstr "недостатньо пам'яті\n" @@ -287,39 +307,51 @@ msgstr "недостатньо пам'яті\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" -#: ../common/file_utils.c:87 ../common/file_utils.c:447 -#: ../common/file_utils.c:451 access/transam/twophase.c:1315 -#: access/transam/xlogarchive.c:112 access/transam/xlogarchive.c:236 -#: backup/basebackup.c:346 backup/basebackup.c:544 backup/basebackup.c:615 -#: commands/copyfrom.c:1697 commands/copyto.c:702 commands/extension.c:3469 -#: commands/tablespace.c:810 commands/tablespace.c:899 postmaster/pgarch.c:590 -#: replication/logical/snapbuild.c:1649 storage/file/fd.c:1922 -#: storage/file/fd.c:2008 storage/file/fd.c:3511 utils/adt/dbsize.c:106 -#: utils/adt/dbsize.c:258 utils/adt/dbsize.c:338 utils/adt/genfile.c:483 -#: utils/adt/genfile.c:658 utils/adt/misc.c:340 +#: ../common/file_utils.c:76 storage/file/fd.c:3516 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../common/file_utils.c:120 ../common/file_utils.c:566 +#: ../common/file_utils.c:570 access/transam/twophase.c:1337 +#: access/transam/xlogarchive.c:111 access/transam/xlogarchive.c:235 +#: backup/basebackup.c:355 backup/basebackup.c:553 backup/basebackup.c:624 +#: backup/walsummary.c:247 backup/walsummary.c:254 commands/copyfrom.c:1749 +#: commands/copyto.c:696 commands/extension.c:3527 commands/tablespace.c:804 +#: commands/tablespace.c:893 postmaster/pgarch.c:680 +#: replication/logical/snapbuild.c:1670 replication/logical/snapbuild.c:2173 +#: storage/file/fd.c:1968 storage/file/fd.c:2054 storage/file/fd.c:3564 +#: utils/adt/dbsize.c:105 utils/adt/dbsize.c:257 utils/adt/dbsize.c:337 +#: utils/adt/genfile.c:437 utils/adt/genfile.c:612 utils/adt/misc.c:340 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" -#: ../common/file_utils.c:162 ../common/pgfnames.c:48 ../common/rmtree.c:63 -#: commands/tablespace.c:734 commands/tablespace.c:744 -#: postmaster/postmaster.c:1564 storage/file/fd.c:2880 -#: storage/file/reinit.c:126 utils/adt/misc.c:256 utils/misc/tzparser.c:338 +#: ../common/file_utils.c:130 ../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../common/file_utils.c:151 ../common/file_utils.c:281 +#: ../common/pgfnames.c:48 ../common/rmtree.c:63 commands/tablespace.c:728 +#: commands/tablespace.c:738 postmaster/postmaster.c:1468 +#: storage/file/fd.c:2933 storage/file/reinit.c:126 utils/adt/misc.c:256 +#: utils/misc/tzparser.c:339 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не вдалося відкрити каталог \"%s\": %m" -#: ../common/file_utils.c:196 ../common/pgfnames.c:69 ../common/rmtree.c:104 -#: storage/file/fd.c:2892 +#: ../common/file_utils.c:169 ../common/file_utils.c:315 +#: ../common/pgfnames.c:69 ../common/rmtree.c:106 storage/file/fd.c:2945 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не вдалося прочитати каталог \"%s\": %m" -#: ../common/file_utils.c:379 access/transam/xlogarchive.c:390 -#: postmaster/pgarch.c:746 postmaster/syslogger.c:1608 -#: replication/logical/snapbuild.c:1810 replication/slot.c:723 -#: replication/slot.c:1716 replication/slot.c:1858 storage/file/fd.c:792 -#: utils/time/snapmgr.c:1284 +#: ../common/file_utils.c:498 access/transam/xlogarchive.c:389 +#: postmaster/pgarch.c:834 postmaster/syslogger.c:1559 +#: replication/logical/snapbuild.c:1831 replication/slot.c:936 +#: replication/slot.c:1998 replication/slot.c:2140 storage/file/fd.c:838 +#: utils/time/snapmgr.c:1255 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" @@ -328,90 +360,102 @@ msgstr "не вдалося перейменувати файл \"%s\" на \"%s msgid "internal error" msgstr "внутрішня помилка" -#: ../common/jsonapi.c:1144 +#: ../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "Рекурсивний спуск не може використовувати інкрементний лексичний аналізатор." + +#: ../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "Інкрементний аналізатор потребує Інкрементний лексичний аналізатор." + +#: ../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON вкладений занадто глибокий, максимально дозволена глибина - 6400." + +#: ../common/jsonapi.c:2127 #, c-format -msgid "Escape sequence \"\\%s\" is invalid." -msgstr "Неприпустима спеціальна послідовність \"\\%s\"." +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Неприпустима спеціальна послідовність \"\\%.*s\"." -#: ../common/jsonapi.c:1147 +#: ../common/jsonapi.c:2131 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Символ зі значенням 0x%02x повинен бути пропущений." -#: ../common/jsonapi.c:1150 +#: ../common/jsonapi.c:2135 #, c-format -msgid "Expected end of input, but found \"%s\"." -msgstr "Очікувався кінець введення, але знайдено \"%s\"." +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Очікувався кінець введення, але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1153 +#: ../common/jsonapi.c:2138 #, c-format -msgid "Expected array element or \"]\", but found \"%s\"." -msgstr "Очікувався елемент масиву або \"]\", але знайдено \"%s\"." +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Очікувався елемент масиву або \"]\", але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1156 +#: ../common/jsonapi.c:2141 #, c-format -msgid "Expected \",\" or \"]\", but found \"%s\"." -msgstr "Очікувалось \",\" або \"]\", але знайдено \"%s\"." +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Очікувалось \",\" або \"]\", але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1159 +#: ../common/jsonapi.c:2144 #, c-format -msgid "Expected \":\", but found \"%s\"." -msgstr "Очікувалось \":\", але знайдено \"%s\"." +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Очікувалось \":\", але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1162 +#: ../common/jsonapi.c:2147 #, c-format -msgid "Expected JSON value, but found \"%s\"." -msgstr "Очікувалось значення JSON, але знайдено \"%s\"." +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Очікувалось значення JSON, але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1165 +#: ../common/jsonapi.c:2150 msgid "The input string ended unexpectedly." msgstr "Несподіваний кінець вхідного рядка." -#: ../common/jsonapi.c:1167 +#: ../common/jsonapi.c:2152 #, c-format -msgid "Expected string or \"}\", but found \"%s\"." -msgstr "Очікувався рядок або \"}\", але знайдено \"%s\"." +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Очікувався рядок або \"}\", але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1170 +#: ../common/jsonapi.c:2155 #, c-format -msgid "Expected \",\" or \"}\", but found \"%s\"." -msgstr "Очікувалось \",\" або \"}\", але знайдено \"%s\"." +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Очікувалось \",\" або \"}\", але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1173 +#: ../common/jsonapi.c:2158 #, c-format -msgid "Expected string, but found \"%s\"." -msgstr "Очікувався рядок, але знайдено \"%s\"." +msgid "Expected string, but found \"%.*s\"." +msgstr "Очікувався рядок, але знайдено \"%.*s\"." -#: ../common/jsonapi.c:1176 +#: ../common/jsonapi.c:2161 #, c-format -msgid "Token \"%s\" is invalid." -msgstr "Неприпустимий маркер \"%s\"." +msgid "Token \"%.*s\" is invalid." +msgstr "Неприпустимий маркер \"%.*s\"." -#: ../common/jsonapi.c:1179 jsonpath_scan.l:597 +#: ../common/jsonapi.c:2164 jsonpath_scan.l:608 #, c-format msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 не можна перетворити в текст." -#: ../common/jsonapi.c:1181 +#: ../common/jsonapi.c:2166 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "За \"\\u\" повинні прямувати чотири шістнадцяткових числа." -#: ../common/jsonapi.c:1184 +#: ../common/jsonapi.c:2169 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "Значення виходу Unicode не можна використовувати для значень кодових точок більше 007F, якщо кодування не UTF8." -#: ../common/jsonapi.c:1187 +#: ../common/jsonapi.c:2178 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Значення символу Unicode не вдалося перекласти в кодування сервера %s." -#: ../common/jsonapi.c:1190 jsonpath_scan.l:630 +#: ../common/jsonapi.c:2185 jsonpath_scan.l:641 #, c-format msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Старший сурогат Unicode не повинен прямувати за іншим старшим сурогатом." -#: ../common/jsonapi.c:1192 jsonpath_scan.l:641 jsonpath_scan.l:651 -#: jsonpath_scan.l:702 +#: ../common/jsonapi.c:2187 jsonpath_scan.l:652 jsonpath_scan.l:662 +#: jsonpath_scan.l:713 #, c-format msgid "Unicode low surrogate must follow a high surrogate." msgstr "Молодший сурогат Unicode не повинен прямувати за іншим молодшим сурогатом." @@ -436,11 +480,168 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../common/parse_manifest.c:159 ../common/parse_manifest.c:855 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "не вдалося ініціалізувати контрольну суму маніфесту" + +#: ../common/parse_manifest.c:204 ../common/parse_manifest.c:261 +msgid "manifest ended unexpectedly" +msgstr "маніфест закінчився несподівано" + +#: ../common/parse_manifest.c:210 ../common/parse_manifest.c:862 +#, c-format +msgid "could not update checksum of manifest" +msgstr "не вдалося оновити контрольну суму маніфесту" + +#: ../common/parse_manifest.c:302 +msgid "unexpected object start" +msgstr "неочікуваний початок об'єкта" + +#: ../common/parse_manifest.c:337 +msgid "unexpected object end" +msgstr "неочікуваний кінець об'єкта" + +#: ../common/parse_manifest.c:366 +msgid "unexpected array start" +msgstr "неочікуваний початок масиву" + +#: ../common/parse_manifest.c:391 +msgid "unexpected array end" +msgstr "неочікуваний кінець масиву" + +#: ../common/parse_manifest.c:418 +msgid "expected version indicator" +msgstr "індикатор очікуваної версії" + +#: ../common/parse_manifest.c:454 +msgid "unrecognized top-level field" +msgstr "нерозпізнане поле верхнього рівня" + +#: ../common/parse_manifest.c:473 +msgid "unexpected file field" +msgstr "неочікуване поле файлу" + +#: ../common/parse_manifest.c:487 +msgid "unexpected WAL range field" +msgstr "неочікуване поле діапазону WAL" + +#: ../common/parse_manifest.c:493 +msgid "unexpected object field" +msgstr "неочікуване поле об'єкта" + +#: ../common/parse_manifest.c:583 +msgid "unexpected scalar" +msgstr "неочікуваний скаляр" + +#: ../common/parse_manifest.c:609 +msgid "manifest version not an integer" +msgstr "версія маніфесту не ціле число" + +#: ../common/parse_manifest.c:613 +msgid "unexpected manifest version" +msgstr "неочікувана версія маніфесту" + +#: ../common/parse_manifest.c:637 +msgid "system identifier in manifest not an integer" +msgstr "системний ідентифікатор в маніфесті не ціле число" + +#: ../common/parse_manifest.c:662 +msgid "missing path name" +msgstr "пропущено шлях" + +#: ../common/parse_manifest.c:665 +msgid "both path name and encoded path name" +msgstr "і ім'я шляху, і закодований шлях" + +#: ../common/parse_manifest.c:667 +msgid "missing size" +msgstr "відсутній розмір" + +#: ../common/parse_manifest.c:670 +msgid "checksum without algorithm" +msgstr "контрольна сума без алгоритму" + +#: ../common/parse_manifest.c:684 +msgid "could not decode file name" +msgstr "не вдалося декодувати ім'я файлу" + +#: ../common/parse_manifest.c:694 +msgid "file size is not an integer" +msgstr "розмір файлу не є цілим числом" + +#: ../common/parse_manifest.c:700 backup/basebackup.c:870 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "нерозпізнаний алгоритм контрольної суми: \"%s\"" + +#: ../common/parse_manifest.c:719 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "неприпустима контрольна сума для файлу \"%s\": \"%s\"" + +#: ../common/parse_manifest.c:762 +msgid "missing timeline" +msgstr "відсутня часова шкала" + +#: ../common/parse_manifest.c:764 +msgid "missing start LSN" +msgstr "відсутній LSN початку" + +#: ../common/parse_manifest.c:766 +msgid "missing end LSN" +msgstr "відсутній LSN кінця" + +#: ../common/parse_manifest.c:772 +msgid "timeline is not an integer" +msgstr "часова лінія не є цілим числом" + +#: ../common/parse_manifest.c:775 +msgid "could not parse start LSN" +msgstr "не вдалося проаналізувати початковий LSN" + +#: ../common/parse_manifest.c:778 +msgid "could not parse end LSN" +msgstr "не вдалося проаналізувати кінцевий LSN" + +#: ../common/parse_manifest.c:843 +msgid "expected at least 2 lines" +msgstr "очікувалося принаймні 2 рядки" + +#: ../common/parse_manifest.c:846 +msgid "last line not newline-terminated" +msgstr "останній рядок не завершений новим рядком" + +#: ../common/parse_manifest.c:865 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "не вдалося остаточно завершити контрольну суму маніфесту" + +#: ../common/parse_manifest.c:869 +#, c-format +msgid "manifest has no checksum" +msgstr "у маніфесті немає контрольної суми" + +#: ../common/parse_manifest.c:873 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "неприпустима контрольна сума маніфесту: \"%s\"" + +#: ../common/parse_manifest.c:877 +#, c-format +msgid "manifest checksum mismatch" +msgstr "невідповідність контрольної суми маніфесту" + +#: ../common/parse_manifest.c:892 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "не вдалося проаналізувати маніфест резервної копії: %s" + #: ../common/percentrepl.c:79 ../common/percentrepl.c:85 #: ../common/percentrepl.c:118 ../common/percentrepl.c:124 -#: postmaster/postmaster.c:2211 utils/misc/guc.c:3120 utils/misc/guc.c:3156 -#: utils/misc/guc.c:3226 utils/misc/guc.c:4556 utils/misc/guc.c:6738 -#: utils/misc/guc.c:6779 +#: tcop/backend_startup.c:741 utils/misc/guc.c:3167 utils/misc/guc.c:3208 +#: utils/misc/guc.c:3283 utils/misc/guc.c:4671 utils/misc/guc.c:6896 +#: utils/misc/guc.c:6937 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" msgstr "неприпустиме значення параметру \"%s\": \"%s\"" @@ -500,23 +701,23 @@ msgstr "не вдалося перезапустити з обмеженим т msgid "could not get exit code from subprocess: error code %lu" msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu" -#: ../common/rmtree.c:95 access/heap/rewriteheap.c:1248 -#: access/transam/twophase.c:1704 access/transam/xlogarchive.c:120 -#: access/transam/xlogarchive.c:400 postmaster/postmaster.c:1143 -#: postmaster/syslogger.c:1537 replication/logical/origin.c:591 -#: replication/logical/reorderbuffer.c:4526 -#: replication/logical/snapbuild.c:1691 replication/logical/snapbuild.c:2125 -#: replication/slot.c:1909 storage/file/fd.c:832 storage/file/fd.c:3325 -#: storage/file/fd.c:3387 storage/file/reinit.c:262 storage/ipc/dsm.c:316 -#: storage/smgr/md.c:383 storage/smgr/md.c:442 storage/sync/sync.c:248 -#: utils/time/snapmgr.c:1608 +#: ../common/rmtree.c:97 access/heap/rewriteheap.c:1214 +#: access/transam/twophase.c:1726 access/transam/xlogarchive.c:119 +#: access/transam/xlogarchive.c:399 postmaster/postmaster.c:1048 +#: postmaster/syslogger.c:1488 replication/logical/origin.c:591 +#: replication/logical/reorderbuffer.c:4584 +#: replication/logical/snapbuild.c:1712 replication/logical/snapbuild.c:2146 +#: replication/slot.c:2192 storage/file/fd.c:878 storage/file/fd.c:3378 +#: storage/file/fd.c:3440 storage/file/reinit.c:261 storage/ipc/dsm.c:343 +#: storage/smgr/md.c:381 storage/smgr/md.c:440 storage/sync/sync.c:243 +#: utils/time/snapmgr.c:1591 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не можливо видалити файл \"%s\": %m" -#: ../common/rmtree.c:122 commands/tablespace.c:773 commands/tablespace.c:786 -#: commands/tablespace.c:821 commands/tablespace.c:911 storage/file/fd.c:3317 -#: storage/file/fd.c:3726 +#: ../common/rmtree.c:124 commands/tablespace.c:767 commands/tablespace.c:780 +#: commands/tablespace.c:815 commands/tablespace.c:905 storage/file/fd.c:3370 +#: storage/file/fd.c:3779 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "не вдалося видалити каталог \"%s\": %m" @@ -533,20 +734,16 @@ msgstr "на вдалося закодувати збережений ключ" msgid "could not encode server key" msgstr "не вдалося закодувати серверний ключ" -#: ../common/stringinfo.c:306 +#: ../common/stringinfo.c:315 #, c-format msgid "Cannot enlarge string buffer containing %d bytes by %d more bytes." msgstr "Не вдалося збільшити рядковий буфер (містить: %d байтів, потребувалось: %d байтів)." -#: ../common/stringinfo.c:310 +#: ../common/stringinfo.c:319 #, c-format -msgid "" -"out of memory\n" -"\n" +msgid "out of memory\n\n" "Cannot enlarge string buffer containing %d bytes by %d more bytes.\n" -msgstr "" -"недостатньо пам'яті\n" -"\n" +msgstr "недостатньо пам'яті\n\n" "Неможливо збільшити рядковий буфер (містить: %d байт, потребувалось: %d байт).\n" #: ../common/username.c:43 @@ -554,7 +751,7 @@ msgstr "" msgid "could not look up effective user ID %ld: %s" msgstr "не можу знайти користувача з ефективним ID %ld: %s" -#: ../common/username.c:45 libpq/auth.c:1879 +#: ../common/username.c:45 libpq/auth.c:1888 msgid "user does not exist" msgstr "користувача не існує" @@ -648,20 +845,20 @@ msgstr "Ви можливо маєте антивірус, резервне ко #: ../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "не вдалося отримати поточний робочий каталог: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "не вдалося отримати поточний робочий каталог: %m\n" #: ../port/strerror.c:72 #, c-format msgid "operating system error %d" msgstr "помилка операційної системи %d" -#: ../port/thread.c:50 ../port/thread.c:86 +#: ../port/user.c:43 ../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "не вдалося знайти локального користувача з ідентифікатором %d: %s" -#: ../port/thread.c:55 ../port/thread.c:91 +#: ../port/user.c:48 ../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "локального користувача з ідентифікатором %d не існує" @@ -681,104 +878,104 @@ msgstr "не вдалося отримати SID для групи PowerUsers: msgid "could not check access token membership: error code %lu\n" msgstr "не вдається перевірити членство токену доступу: код помилки %lu\n" -#: access/brin/brin.c:216 +#: access/brin/brin.c:405 #, c-format msgid "request for BRIN range summarization for index \"%s\" page %u was not recorded" msgstr "запит на підсумок діапазону BRIN для індексу «%s» сторінки %u не вдалося записати" -#: access/brin/brin.c:1036 access/brin/brin.c:1143 access/gin/ginfast.c:1039 -#: access/transam/xlogfuncs.c:189 access/transam/xlogfuncs.c:214 -#: access/transam/xlogfuncs.c:247 access/transam/xlogfuncs.c:286 -#: access/transam/xlogfuncs.c:307 access/transam/xlogfuncs.c:328 -#: access/transam/xlogfuncs.c:398 access/transam/xlogfuncs.c:456 +#: access/brin/brin.c:1385 access/brin/brin.c:1493 access/gin/ginfast.c:1040 +#: access/transam/xlogfuncs.c:183 access/transam/xlogfuncs.c:208 +#: access/transam/xlogfuncs.c:241 access/transam/xlogfuncs.c:280 +#: access/transam/xlogfuncs.c:301 access/transam/xlogfuncs.c:322 +#: access/transam/xlogfuncs.c:388 access/transam/xlogfuncs.c:446 #, c-format msgid "recovery is in progress" msgstr "відновлення у процесі" -#: access/brin/brin.c:1037 access/brin/brin.c:1144 +#: access/brin/brin.c:1386 access/brin/brin.c:1494 #, c-format msgid "BRIN control functions cannot be executed during recovery." msgstr "Контрольна функція BRIN не може бути виконана під час відновлення." -#: access/brin/brin.c:1042 access/brin/brin.c:1149 +#: access/brin/brin.c:1391 access/brin/brin.c:1499 #, c-format msgid "block number out of range: %lld" msgstr "номер блоку поза діапазоном: %lld" -#: access/brin/brin.c:1086 access/brin/brin.c:1175 +#: access/brin/brin.c:1436 access/brin/brin.c:1525 #, c-format msgid "\"%s\" is not a BRIN index" msgstr "\"%s\" не є індексом BRIN" -#: access/brin/brin.c:1102 access/brin/brin.c:1191 +#: access/brin/brin.c:1452 access/brin/brin.c:1541 #, c-format msgid "could not open parent table of index \"%s\"" msgstr "не вдалося відкрити батьківську таблицю індексу \"%s\"" -#: access/brin/brin.c:1111 access/brin/brin.c:1207 access/gin/ginfast.c:1084 -#: parser/parse_utilcmd.c:2280 +#: access/brin/brin.c:1461 access/brin/brin.c:1557 access/gin/ginfast.c:1085 +#: parser/parse_utilcmd.c:2277 #, c-format msgid "index \"%s\" is not valid" msgstr "індекс \"%s\" не є припустимим" -#: access/brin/brin_bloom.c:749 access/brin/brin_bloom.c:791 -#: access/brin/brin_minmax_multi.c:2985 access/brin/brin_minmax_multi.c:3122 -#: statistics/dependencies.c:663 statistics/dependencies.c:716 -#: statistics/mcv.c:1484 statistics/mcv.c:1515 statistics/mvdistinct.c:344 -#: statistics/mvdistinct.c:397 utils/adt/pseudotypes.c:43 -#: utils/adt/pseudotypes.c:77 utils/adt/tsgistidx.c:93 +#: access/brin/brin_bloom.c:783 access/brin/brin_bloom.c:825 +#: access/brin/brin_minmax_multi.c:2993 access/brin/brin_minmax_multi.c:3130 +#: statistics/dependencies.c:661 statistics/dependencies.c:714 +#: statistics/mcv.c:1480 statistics/mcv.c:1511 statistics/mvdistinct.c:343 +#: statistics/mvdistinct.c:396 utils/adt/pseudotypes.c:40 +#: utils/adt/pseudotypes.c:74 utils/adt/tsgistidx.c:94 #, c-format msgid "cannot accept a value of type %s" msgstr "не можна прийняти значення типу %s" -#: access/brin/brin_pageops.c:76 access/brin/brin_pageops.c:362 -#: access/brin/brin_pageops.c:852 access/gin/ginentrypage.c:110 -#: access/gist/gist.c:1462 access/spgist/spgdoinsert.c:2002 -#: access/spgist/spgdoinsert.c:2279 +#: access/brin/brin_pageops.c:75 access/brin/brin_pageops.c:361 +#: access/brin/brin_pageops.c:851 access/gin/ginentrypage.c:109 +#: access/gist/gist.c:1463 access/spgist/spgdoinsert.c:2001 +#: access/spgist/spgdoinsert.c:2278 #, c-format msgid "index row size %zu exceeds maximum %zu for index \"%s\"" msgstr "розмір рядка індексу %zu перевищує максимальний %zu для індексу \"%s\"" -#: access/brin/brin_revmap.c:393 access/brin/brin_revmap.c:399 +#: access/brin/brin_revmap.c:383 access/brin/brin_revmap.c:389 #, c-format msgid "corrupted BRIN index: inconsistent range map" msgstr "пошкоджений BRIN індекс: несумісна карта діапазонів" -#: access/brin/brin_revmap.c:593 +#: access/brin/brin_revmap.c:583 #, c-format msgid "unexpected page type 0x%04X in BRIN index \"%s\" block %u" msgstr "неочікуваний тип сторінки 0x%04X в BRIN індексі \"%s\" блокує %u" -#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:151 -#: access/gist/gistvalidate.c:153 access/hash/hashvalidate.c:139 +#: access/brin/brin_validate.c:118 access/gin/ginvalidate.c:149 +#: access/gist/gistvalidate.c:152 access/hash/hashvalidate.c:139 #: access/nbtree/nbtvalidate.c:120 access/spgist/spgvalidate.c:189 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with invalid support number %d" msgstr "сімейство операторів \"%s\" методу доступу %s містить функцію %s з недопустимим номером підтримки %d" -#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:163 -#: access/gist/gistvalidate.c:165 access/hash/hashvalidate.c:118 +#: access/brin/brin_validate.c:134 access/gin/ginvalidate.c:161 +#: access/gist/gistvalidate.c:164 access/hash/hashvalidate.c:118 #: access/nbtree/nbtvalidate.c:132 access/spgist/spgvalidate.c:201 #, c-format msgid "operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d" msgstr "сімейство операторів \"%s\" з доступом %s містить функцію %s з неправильним підписом для номеру підтримки %d" -#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:182 -#: access/gist/gistvalidate.c:185 access/hash/hashvalidate.c:160 +#: access/brin/brin_validate.c:156 access/gin/ginvalidate.c:180 +#: access/gist/gistvalidate.c:184 access/hash/hashvalidate.c:160 #: access/nbtree/nbtvalidate.c:152 access/spgist/spgvalidate.c:221 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with invalid strategy number %d" msgstr "сімейство операторів \"%s\" з доступом %s містить оператор %s з недопустимим стратегічним номером %d" -#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:195 +#: access/brin/brin_validate.c:185 access/gin/ginvalidate.c:193 #: access/hash/hashvalidate.c:173 access/nbtree/nbtvalidate.c:165 #: access/spgist/spgvalidate.c:237 #, c-format msgid "operator family \"%s\" of access method %s contains invalid ORDER BY specification for operator %s" msgstr "сімейство операторів \"%s\" з доступом %s містить некоректну специфікацію ORDER BY для оператора %s" -#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:208 -#: access/gist/gistvalidate.c:233 access/hash/hashvalidate.c:186 +#: access/brin/brin_validate.c:198 access/gin/ginvalidate.c:206 +#: access/gist/gistvalidate.c:232 access/hash/hashvalidate.c:186 #: access/nbtree/nbtvalidate.c:178 access/spgist/spgvalidate.c:253 #, c-format msgid "operator family \"%s\" of access method %s contains operator %s with wrong signature" @@ -801,38 +998,38 @@ msgstr "сімейство операторів \"%s\" з методом дос msgid "operator class \"%s\" of access method %s is missing operator(s)" msgstr "клас операторів \"%s\" з методом доступа %s не має операторів" -#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:250 -#: access/gist/gistvalidate.c:274 +#: access/brin/brin_validate.c:270 access/gin/ginvalidate.c:248 +#: access/gist/gistvalidate.c:273 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d" msgstr "клас операторів \"%s\" з доступом %s немає функції підтримки %d" -#: access/common/attmap.c:122 +#: access/common/attmap.c:121 #, c-format msgid "Returned type %s does not match expected type %s in column %d." msgstr "Повернений тип %s не відповідає очікуваному типу %s в стовпці %d." -#: access/common/attmap.c:150 +#: access/common/attmap.c:149 #, c-format msgid "Number of returned columns (%d) does not match expected column count (%d)." msgstr "Кількість повернених стовпців (%d) не відповідає очікуваній кількості стовпців (%d)." -#: access/common/attmap.c:234 access/common/attmap.c:246 +#: access/common/attmap.c:233 access/common/attmap.c:245 #, c-format msgid "could not convert row type" msgstr "неможливо конвертувати тип рядка" -#: access/common/attmap.c:235 +#: access/common/attmap.c:234 #, c-format msgid "Attribute \"%s\" of type %s does not match corresponding attribute of type %s." msgstr "Атрибут \"%s\" типу %s не збігається з відповідним атрибутом типу %s." -#: access/common/attmap.c:247 +#: access/common/attmap.c:246 #, c-format msgid "Attribute \"%s\" of type %s does not exist in type %s." msgstr "Атрибут \"%s\" типу %s не існує в типі %s." -#: access/common/heaptuple.c:1133 access/common/heaptuple.c:1468 +#: access/common/heaptuple.c:1132 access/common/heaptuple.c:1467 #, c-format msgid "number of columns (%d) exceeds limit (%d)" msgstr "кількість стовпців (%d) перевищує обмеження (%d)" @@ -842,122 +1039,110 @@ msgstr "кількість стовпців (%d) перевищує обмеже msgid "number of index columns (%d) exceeds limit (%d)" msgstr "кількість індексних стовпців (%d) перевищує обмеження (%d)" -#: access/common/indextuple.c:209 access/spgist/spgutils.c:957 +#: access/common/indextuple.c:209 access/spgist/spgutils.c:970 #, c-format msgid "index row requires %zu bytes, maximum size is %zu" msgstr "індексний рядок вимагає %zu байтів, максимальний розмір %zu" -#: access/common/printtup.c:292 tcop/fastpath.c:107 tcop/fastpath.c:454 -#: tcop/postgres.c:1944 +#: access/common/printtup.c:292 commands/explain.c:5376 tcop/fastpath.c:107 +#: tcop/fastpath.c:454 tcop/postgres.c:1956 #, c-format msgid "unsupported format code: %d" msgstr "цей формат коду не підтримується:%d" -#: access/common/reloptions.c:521 access/common/reloptions.c:532 +#: access/common/reloptions.c:519 access/common/reloptions.c:530 msgid "Valid values are \"on\", \"off\", and \"auto\"." msgstr "Дійсні значення \"увімкнено\", \"вимкнено\" та \"автоматично\"." -#: access/common/reloptions.c:543 +#: access/common/reloptions.c:541 msgid "Valid values are \"local\" and \"cascaded\"." msgstr "Припустимі значення лише \"local\" і \"cascaded\"." -#: access/common/reloptions.c:691 +#: access/common/reloptions.c:689 #, c-format msgid "user-defined relation parameter types limit exceeded" msgstr "перевищено встановлене користувачем обмеження типу параметрів відношення" -#: access/common/reloptions.c:1233 +#: access/common/reloptions.c:1231 #, c-format msgid "RESET must not include values for parameters" msgstr "RESET не має містити значення для параметрів" -#: access/common/reloptions.c:1265 +#: access/common/reloptions.c:1263 #, c-format msgid "unrecognized parameter namespace \"%s\"" msgstr "нерозпізнаний параметр простору імен \"%s\"" -#: access/common/reloptions.c:1302 commands/variable.c:1167 +#: access/common/reloptions.c:1300 commands/variable.c:1191 #, c-format msgid "tables declared WITH OIDS are not supported" msgstr "таблиці, позначені WITH OIDS, не підтримуються" -#: access/common/reloptions.c:1470 +#: access/common/reloptions.c:1468 #, c-format msgid "unrecognized parameter \"%s\"" msgstr "нерозпізнаний параметр \"%s\"" -#: access/common/reloptions.c:1582 +#: access/common/reloptions.c:1580 #, c-format msgid "parameter \"%s\" specified more than once" msgstr "параметр «%s» вказано кілька разів" -#: access/common/reloptions.c:1598 +#: access/common/reloptions.c:1596 #, c-format msgid "invalid value for boolean option \"%s\": %s" msgstr "неприпустиме значення для булевого параметра \"%s\": %s" -#: access/common/reloptions.c:1610 +#: access/common/reloptions.c:1608 #, c-format msgid "invalid value for integer option \"%s\": %s" msgstr "неприпустиме значення для цілого параметра \"%s\": %s" -#: access/common/reloptions.c:1616 access/common/reloptions.c:1636 +#: access/common/reloptions.c:1614 access/common/reloptions.c:1634 #, c-format msgid "value %s out of bounds for option \"%s\"" msgstr "значення %s поза допустимими межами для параметра \"%s\"" -#: access/common/reloptions.c:1618 +#: access/common/reloptions.c:1616 #, c-format msgid "Valid values are between \"%d\" and \"%d\"." msgstr "Припустимі значення знаходяться між \"%d\" і \"%d\"." -#: access/common/reloptions.c:1630 +#: access/common/reloptions.c:1628 #, c-format msgid "invalid value for floating point option \"%s\": %s" msgstr "неприпустиме значення для числа з плавучою точкою параметра \"%s\": %s" -#: access/common/reloptions.c:1638 +#: access/common/reloptions.c:1636 #, c-format msgid "Valid values are between \"%f\" and \"%f\"." msgstr "Припустимі значення знаходяться між \"%f\" і \"%f\"." -#: access/common/reloptions.c:1660 +#: access/common/reloptions.c:1658 #, c-format msgid "invalid value for enum option \"%s\": %s" msgstr "недійсне значення для параметра перерахування \"%s\": %s" -#: access/common/reloptions.c:1991 +#: access/common/reloptions.c:1989 #, c-format msgid "cannot specify storage parameters for a partitioned table" msgstr "неможливо вказати параметри сховища для секціонованої таблиці" -#: access/common/reloptions.c:1992 +#: access/common/reloptions.c:1990 #, c-format msgid "Specify storage parameters for its leaf partitions instead." msgstr "Вкажіть параметри сховища для табличних розділів." -#: access/common/toast_compression.c:33 +#: access/common/toast_compression.c:31 #, c-format msgid "compression method lz4 not supported" msgstr "метод стискання lz4 не підтримується" -#: access/common/toast_compression.c:34 +#: access/common/toast_compression.c:32 #, c-format msgid "This functionality requires the server to be built with lz4 support." msgstr "Ця функціональність потребує, щоб сервер був побудований з підтримкою lz4." -#: access/common/tupdesc.c:837 commands/tablecmds.c:6957 -#: commands/tablecmds.c:12985 -#, c-format -msgid "too many array dimensions" -msgstr "занадто багато вимірів масиву" - -#: access/common/tupdesc.c:842 parser/parse_clause.c:772 -#: parser/parse_relation.c:1913 -#, c-format -msgid "column \"%s\" cannot be declared SETOF" -msgstr "стовпець\"%s\" не може бути оголошений SETOF" - #: access/gin/ginbulk.c:44 #, c-format msgid "posting list is too long" @@ -965,25 +1150,25 @@ msgstr "список вказівників задовгий" #: access/gin/ginbulk.c:45 #, c-format -msgid "Reduce maintenance_work_mem." -msgstr "Зменшіть maintenance_work_mem." +msgid "Reduce \"maintenance_work_mem\"." +msgstr "Зменшіть \"maintenance_work_mem\"." -#: access/gin/ginfast.c:1040 +#: access/gin/ginfast.c:1041 #, c-format msgid "GIN pending list cannot be cleaned up during recovery." msgstr "Черга записів GIN не може бути очищена під час відновлення." -#: access/gin/ginfast.c:1047 +#: access/gin/ginfast.c:1048 #, c-format msgid "\"%s\" is not a GIN index" msgstr "\"%s\" не є індексом GIN" -#: access/gin/ginfast.c:1058 +#: access/gin/ginfast.c:1059 #, c-format msgid "cannot access temporary indexes of other sessions" msgstr "доступ до тимчасових індексів з інших сесій заблокований" -#: access/gin/ginget.c:273 access/nbtree/nbtinsert.c:762 +#: access/gin/ginget.c:271 access/nbtree/nbtinsert.c:762 #, c-format msgid "failed to re-find tuple within index \"%s\"" msgstr "не вдалося повторно знайти кортеж в межах індексу \"%s\"" @@ -998,50 +1183,50 @@ msgstr "старі індекси GIN не підтримують сканува msgid "To fix this, do REINDEX INDEX \"%s\"." msgstr "Щоб виправити це, зробіть REINDEX INDEX \"%s\"." -#: access/gin/ginutil.c:146 executor/execExpr.c:2169 -#: utils/adt/arrayfuncs.c:4045 utils/adt/arrayfuncs.c:6732 -#: utils/adt/rowtypes.c:984 +#: access/gin/ginutil.c:147 executor/execExpr.c:2192 +#: utils/adt/arrayfuncs.c:4016 utils/adt/arrayfuncs.c:6712 +#: utils/adt/rowtypes.c:974 #, c-format msgid "could not identify a comparison function for type %s" msgstr "не вдалося визначити порівняльну функцію для типу %s" -#: access/gin/ginvalidate.c:92 access/gist/gistvalidate.c:93 +#: access/gin/ginvalidate.c:90 access/gist/gistvalidate.c:92 #: access/hash/hashvalidate.c:102 access/spgist/spgvalidate.c:102 #, c-format msgid "operator family \"%s\" of access method %s contains support function %s with different left and right input types" msgstr "сімейство операторів \"%s\" з методом доступу %s містить функцію підтримки %s з різними типами вводу зліва і справа" -#: access/gin/ginvalidate.c:260 +#: access/gin/ginvalidate.c:258 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d or %d" msgstr "клас операторів \"%s\" з методом доступу %s не має функції підтримки %d або %d" -#: access/gin/ginvalidate.c:333 access/gist/gistvalidate.c:350 +#: access/gin/ginvalidate.c:331 access/gist/gistvalidate.c:349 #: access/spgist/spgvalidate.c:387 #, c-format msgid "support function number %d is invalid for access method %s" msgstr "номер функції підтримки %d неприпустимий для методу доступу %s" -#: access/gist/gist.c:759 access/gist/gistvacuum.c:426 +#: access/gist/gist.c:760 access/gist/gistvacuum.c:426 #, c-format msgid "index \"%s\" contains an inner tuple marked as invalid" msgstr "індекс \"%s\" містить внутрішній кортеж, позначений як неправильний" -#: access/gist/gist.c:761 access/gist/gistvacuum.c:428 +#: access/gist/gist.c:762 access/gist/gistvacuum.c:428 #, c-format msgid "This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1." msgstr "Це викликано неповним поділом сторінки під час відновлення перед покращенням до версії PostgreSQL 9.1." -#: access/gist/gist.c:762 access/gist/gistutil.c:801 access/gist/gistutil.c:812 -#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:227 -#: access/hash/hashutil.c:238 access/hash/hashutil.c:250 -#: access/hash/hashutil.c:271 access/nbtree/nbtpage.c:813 +#: access/gist/gist.c:763 access/gist/gistutil.c:800 access/gist/gistutil.c:811 +#: access/gist/gistvacuum.c:429 access/hash/hashutil.c:226 +#: access/hash/hashutil.c:237 access/hash/hashutil.c:249 +#: access/hash/hashutil.c:270 access/nbtree/nbtpage.c:813 #: access/nbtree/nbtpage.c:824 #, c-format msgid "Please REINDEX it." msgstr "Будь ласка, виконайте REINDEX." -#: access/gist/gist.c:1195 +#: access/gist/gist.c:1196 #, c-format msgid "fixing incomplete split in index \"%s\", block %u" msgstr "виправлення неповного розділу в індексі \"%s\", блок %u" @@ -1056,52 +1241,52 @@ msgstr "помилка методу picksplit для стовпця %d інде msgid "The index is not optimal. To optimize it, contact a developer, or try to use the column as the second one in the CREATE INDEX command." msgstr "Індекс не є оптимальним. Щоб оптимізувати його, зв'яжіться з розробником або спробуйте використати стовпець як другий індекс у команді CREATE INDEX." -#: access/gist/gistutil.c:798 access/hash/hashutil.c:224 +#: access/gist/gistutil.c:797 access/hash/hashutil.c:223 #: access/nbtree/nbtpage.c:810 #, c-format msgid "index \"%s\" contains unexpected zero page at block %u" msgstr "індекс \"%s\" містить неочікувану нульову сторінку в блоці %u" -#: access/gist/gistutil.c:809 access/hash/hashutil.c:235 -#: access/hash/hashutil.c:247 access/nbtree/nbtpage.c:821 +#: access/gist/gistutil.c:808 access/hash/hashutil.c:234 +#: access/hash/hashutil.c:246 access/nbtree/nbtpage.c:821 #, c-format msgid "index \"%s\" contains corrupted page at block %u" msgstr "індекс \"%s\" містить пошкоджену сторінку в блоці %u" -#: access/gist/gistvalidate.c:203 +#: access/gist/gistvalidate.c:202 #, c-format msgid "operator family \"%s\" of access method %s contains unsupported ORDER BY specification for operator %s" msgstr "сімейство операторів \"%s\" з методом доступу %s містить непідтримувану для оператора специфікацію ORDER BY %s" -#: access/gist/gistvalidate.c:214 +#: access/gist/gistvalidate.c:213 #, c-format msgid "operator family \"%s\" of access method %s contains incorrect ORDER BY opfamily specification for operator %s" msgstr "сімейство операторів \"%s\" з методом доступу %s містить некоректну для оператора специфікацію ORDER BY opfamily %s" -#: access/hash/hashfunc.c:279 access/hash/hashfunc.c:333 -#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1064 +#: access/hash/hashfunc.c:277 access/hash/hashfunc.c:333 +#: utils/adt/varchar.c:1008 utils/adt/varchar.c:1065 #, c-format msgid "could not determine which collation to use for string hashing" msgstr "не вдалося визначити, який параметр сортування використати для обчислення хешу рядків" -#: access/hash/hashfunc.c:280 access/hash/hashfunc.c:334 catalog/heap.c:668 -#: catalog/heap.c:674 commands/createas.c:206 commands/createas.c:515 -#: commands/indexcmds.c:2015 commands/tablecmds.c:17490 commands/view.c:86 -#: regex/regc_pg_locale.c:243 utils/adt/formatting.c:1648 -#: utils/adt/formatting.c:1770 utils/adt/formatting.c:1893 utils/adt/like.c:191 -#: utils/adt/like_support.c:1025 utils/adt/varchar.c:739 -#: utils/adt/varchar.c:1010 utils/adt/varchar.c:1065 utils/adt/varlena.c:1518 +#: access/hash/hashfunc.c:278 access/hash/hashfunc.c:334 catalog/heap.c:672 +#: catalog/heap.c:678 commands/createas.c:201 commands/createas.c:508 +#: commands/indexcmds.c:2048 commands/tablecmds.c:18068 commands/view.c:81 +#: regex/regc_pg_locale.c:245 utils/adt/formatting.c:1653 +#: utils/adt/formatting.c:1801 utils/adt/formatting.c:1991 utils/adt/like.c:189 +#: utils/adt/like_support.c:1024 utils/adt/varchar.c:738 +#: utils/adt/varchar.c:1009 utils/adt/varchar.c:1066 utils/adt/varlena.c:1521 #, c-format msgid "Use the COLLATE clause to set the collation explicitly." msgstr "Використайте опцію COLLATE для задання параметрів сортування." -#: access/hash/hashinsert.c:86 +#: access/hash/hashinsert.c:84 #, c-format msgid "index row size %zu exceeds hash maximum %zu" msgstr "індексний рядок розміру %zu перевищує максимальний хеш %zu" -#: access/hash/hashinsert.c:88 access/spgist/spgdoinsert.c:2006 -#: access/spgist/spgdoinsert.c:2283 access/spgist/spgutils.c:1018 +#: access/hash/hashinsert.c:86 access/spgist/spgdoinsert.c:2005 +#: access/spgist/spgdoinsert.c:2282 access/spgist/spgutils.c:1031 #, c-format msgid "Values larger than a buffer page cannot be indexed." msgstr "Значення, що перевищують буфер сторінки, не можна індексувати." @@ -1116,17 +1301,17 @@ msgstr "недійсний номер блока переповнення %u" msgid "out of overflow pages in hash index \"%s\"" msgstr "закінчились переповнені сторінки в хеш-індексі \"%s\"" -#: access/hash/hashsearch.c:315 +#: access/hash/hashsearch.c:311 #, c-format msgid "hash indexes do not support whole-index scans" msgstr "хеш-індекси не підтримують сканування цілого індексу" -#: access/hash/hashutil.c:263 +#: access/hash/hashutil.c:262 #, c-format msgid "index \"%s\" is not a hash index" msgstr "індекс \"%s\" не є хеш-індексом" -#: access/hash/hashutil.c:269 +#: access/hash/hashutil.c:268 #, c-format msgid "index \"%s\" has wrong hash version" msgstr "індекс \"%s\" має неправильну версію хешу" @@ -1141,297 +1326,296 @@ msgstr "сімейство операторів \"%s\" з методом дос msgid "operator family \"%s\" of access method %s is missing cross-type operator(s)" msgstr "сімейство операторів \"%s\" з методом доступу %s не містить міжтипового оператора (ів)" -#: access/heap/heapam.c:2038 +#: access/heap/heapam.c:2195 #, c-format msgid "cannot insert tuples in a parallel worker" msgstr "не вдалося вставити кортежі в паралельного працівника" -#: access/heap/heapam.c:2557 +#: access/heap/heapam.c:2714 #, c-format msgid "cannot delete tuples during a parallel operation" msgstr "не вдалося видалити кортежі під час паралельної операції" -#: access/heap/heapam.c:2604 +#: access/heap/heapam.c:2761 #, c-format msgid "attempted to delete invisible tuple" msgstr "спроба видалити невидимий кортеж" -#: access/heap/heapam.c:3052 access/heap/heapam.c:5921 +#: access/heap/heapam.c:3209 access/heap/heapam.c:6082 #, c-format msgid "cannot update tuples during a parallel operation" msgstr "неможливо оновити кортежі під час паралельної операції" -#: access/heap/heapam.c:3180 +#: access/heap/heapam.c:3337 #, c-format msgid "attempted to update invisible tuple" msgstr "спроба оновити невидимий кортеж" -#: access/heap/heapam.c:4569 access/heap/heapam.c:4607 -#: access/heap/heapam.c:4872 access/heap/heapam_handler.c:467 +#: access/heap/heapam.c:4726 access/heap/heapam.c:4764 +#: access/heap/heapam.c:5029 access/heap/heapam_handler.c:468 #, c-format msgid "could not obtain lock on row in relation \"%s\"" msgstr "не вдалося отримати блокування у рядку стосовно \"%s\"" -#: access/heap/heapam_handler.c:412 +#: access/heap/heapam_handler.c:413 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update" msgstr "кортеж, який підлягає блокуванню, вже був переміщений до іншої секції в результаті паралельного оновлення" -#: access/heap/hio.c:536 access/heap/rewriteheap.c:659 +#: access/heap/hio.c:535 access/heap/rewriteheap.c:640 #, c-format msgid "row is too big: size %zu, maximum size %zu" msgstr "рядок завеликий: розмір %zu, максимальний розмір %zu" -#: access/heap/rewriteheap.c:919 +#: access/heap/rewriteheap.c:885 #, c-format msgid "could not write to file \"%s\", wrote %d of %d: %m" msgstr "не вдалося записати до файлу \"%s\", записано %d з %d: %m" -#: access/heap/rewriteheap.c:1011 access/heap/rewriteheap.c:1128 +#: access/heap/rewriteheap.c:977 access/heap/rewriteheap.c:1094 #: access/transam/timeline.c:329 access/transam/timeline.c:481 -#: access/transam/xlog.c:2973 access/transam/xlog.c:3164 -#: access/transam/xlog.c:3940 access/transam/xlog.c:8746 -#: access/transam/xlogfuncs.c:702 backup/basebackup_server.c:151 -#: backup/basebackup_server.c:244 commands/dbcommands.c:495 -#: postmaster/postmaster.c:4557 postmaster/postmaster.c:5560 -#: replication/logical/origin.c:603 replication/slot.c:1777 -#: storage/file/copydir.c:157 storage/smgr/md.c:232 utils/time/snapmgr.c:1263 +#: access/transam/xlog.c:3254 access/transam/xlog.c:3445 +#: access/transam/xlog.c:4282 access/transam/xlog.c:9244 +#: access/transam/xlogfuncs.c:692 backup/basebackup_server.c:149 +#: backup/basebackup_server.c:242 commands/dbcommands.c:494 +#: postmaster/launch_backend.c:340 postmaster/postmaster.c:4112 +#: postmaster/walsummarizer.c:1212 replication/logical/origin.c:603 +#: replication/slot.c:2059 storage/file/copydir.c:157 storage/smgr/md.c:230 +#: utils/time/snapmgr.c:1234 #, c-format msgid "could not create file \"%s\": %m" msgstr "неможливо створити файл \"%s\": %m" -#: access/heap/rewriteheap.c:1138 +#: access/heap/rewriteheap.c:1104 #, c-format msgid "could not truncate file \"%s\" to %u: %m" msgstr "не вдалося скоротити файл \"%s\" до потрібного розміру %u: %m" -#: access/heap/rewriteheap.c:1156 access/transam/timeline.c:384 +#: access/heap/rewriteheap.c:1122 access/transam/timeline.c:384 #: access/transam/timeline.c:424 access/transam/timeline.c:498 -#: access/transam/xlog.c:3023 access/transam/xlog.c:3220 -#: access/transam/xlog.c:3952 commands/dbcommands.c:507 -#: postmaster/postmaster.c:4567 postmaster/postmaster.c:4577 +#: access/transam/xlog.c:3304 access/transam/xlog.c:3501 +#: access/transam/xlog.c:4294 commands/dbcommands.c:506 +#: postmaster/launch_backend.c:351 postmaster/launch_backend.c:363 #: replication/logical/origin.c:615 replication/logical/origin.c:657 -#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1767 -#: replication/slot.c:1812 storage/file/buffile.c:545 -#: storage/file/copydir.c:197 utils/init/miscinit.c:1612 -#: utils/init/miscinit.c:1623 utils/init/miscinit.c:1631 utils/misc/guc.c:4340 -#: utils/misc/guc.c:4371 utils/misc/guc.c:5507 utils/misc/guc.c:5525 -#: utils/time/snapmgr.c:1268 utils/time/snapmgr.c:1275 +#: replication/logical/origin.c:676 replication/logical/snapbuild.c:1788 +#: replication/slot.c:2094 storage/file/buffile.c:545 +#: storage/file/copydir.c:197 utils/init/miscinit.c:1601 +#: utils/init/miscinit.c:1612 utils/init/miscinit.c:1620 utils/misc/guc.c:4450 +#: utils/misc/guc.c:4481 utils/misc/guc.c:5634 utils/misc/guc.c:5652 +#: utils/time/snapmgr.c:1239 utils/time/snapmgr.c:1246 #, c-format msgid "could not write to file \"%s\": %m" msgstr "неможливо записати до файлу \"%s\": %m" -#: access/heap/vacuumlazy.c:482 +#: access/heap/vacuumlazy.c:473 #, c-format msgid "aggressively vacuuming \"%s.%s.%s\"" msgstr "агресивне очищення \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:487 +#: access/heap/vacuumlazy.c:478 #, c-format msgid "vacuuming \"%s.%s.%s\"" msgstr "очищення \"%s.%s.%s\"" -#: access/heap/vacuumlazy.c:635 +#: access/heap/vacuumlazy.c:626 #, c-format msgid "finished vacuuming \"%s.%s.%s\": index scans: %d\n" msgstr "очищення закінчено \"%s.%s.%s\": сканувань індексу: %d\n" -#: access/heap/vacuumlazy.c:646 +#: access/heap/vacuumlazy.c:637 #, c-format msgid "automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "автоматичний агресивний вакуум для запобігання зацикленню таблиці \"%s.%s.%s\": сканування індексу: %d\n" -#: access/heap/vacuumlazy.c:648 +#: access/heap/vacuumlazy.c:639 #, c-format msgid "automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n" msgstr "автоматичне очищення для запобігання зацикленню таблиці \"%s.%s.%s\": сканування індексу: %d\n" -#: access/heap/vacuumlazy.c:653 +#: access/heap/vacuumlazy.c:644 #, c-format msgid "automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "автоматична агресивне очищення таблиці \"%s.%s.%s\": сканувань індексу: %d\n" -#: access/heap/vacuumlazy.c:655 +#: access/heap/vacuumlazy.c:646 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\": index scans: %d\n" msgstr "автоматичне очищення таблиці \"%s.%s.%s\": сканувань індексу: %d\n" -#: access/heap/vacuumlazy.c:662 +#: access/heap/vacuumlazy.c:653 #, c-format msgid "pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n" msgstr "сторінок: %u видалено, %u залишилось, %u відскановано (%.2f%% від загальної кількості)\n" -#: access/heap/vacuumlazy.c:669 +#: access/heap/vacuumlazy.c:660 #, c-format msgid "tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n" msgstr "кортежів: %lld видалено, %lld залишилось, %lld мертвих, але все ще не можуть бути видаленні\n" -#: access/heap/vacuumlazy.c:675 +#: access/heap/vacuumlazy.c:666 #, c-format msgid "tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n" msgstr "пропущено кортежів: %lld померлих з %u сторінок не видалено через очищення блокування\n" -#: access/heap/vacuumlazy.c:681 +#: access/heap/vacuumlazy.c:672 #, c-format msgid "removable cutoff: %u, which was %d XIDs old when operation ended\n" msgstr "Видалення вирізу: %u, це було %d XIDs старий при завершенні операції\n" -#: access/heap/vacuumlazy.c:688 +#: access/heap/vacuumlazy.c:679 #, c-format msgid "new relfrozenxid: %u, which is %d XIDs ahead of previous value\n" msgstr "новий relfrozenxid: %u, що є %d XIDs попереду попереднього значення\n" -#: access/heap/vacuumlazy.c:696 +#: access/heap/vacuumlazy.c:687 #, c-format msgid "new relminmxid: %u, which is %d MXIDs ahead of previous value\n" msgstr "новий relminmxid: %u, що становить %d MXIDs попереду попереднього значення\n" -#: access/heap/vacuumlazy.c:699 +#: access/heap/vacuumlazy.c:690 #, c-format msgid "frozen: %u pages from table (%.2f%% of total) had %lld tuples frozen\n" msgstr "заморожено: %u сторінок з таблиці (%.2f%% з усього) має %lld заморожені рядків\n" -#: access/heap/vacuumlazy.c:707 +#: access/heap/vacuumlazy.c:698 msgid "index scan not needed: " msgstr "сканування індексу не потрібне: " -#: access/heap/vacuumlazy.c:709 +#: access/heap/vacuumlazy.c:700 msgid "index scan needed: " msgstr "сканування індексу потрібне: " -#: access/heap/vacuumlazy.c:711 +#: access/heap/vacuumlazy.c:702 #, c-format msgid "%u pages from table (%.2f%% of total) had %lld dead item identifiers removed\n" msgstr "у %u сторінок з таблиці (%.2f%% від загальної кількості) було видалено %lld мертвих ідентифікаторів елементів\n" -#: access/heap/vacuumlazy.c:716 +#: access/heap/vacuumlazy.c:707 msgid "index scan bypassed: " msgstr "сканування індексу пропущено: " -#: access/heap/vacuumlazy.c:718 +#: access/heap/vacuumlazy.c:709 msgid "index scan bypassed by failsafe: " msgstr "сканування індексу безпечно пропущено: " -#: access/heap/vacuumlazy.c:720 +#: access/heap/vacuumlazy.c:711 #, c-format msgid "%u pages from table (%.2f%% of total) have %lld dead item identifiers\n" msgstr "%u сторінок з таблиці (%.2f%% від загальної кількості) мають %lld мертвих ідентифікаторів елементів\n" -#: access/heap/vacuumlazy.c:735 +#: access/heap/vacuumlazy.c:726 #, c-format msgid "index \"%s\": pages: %u in total, %u newly deleted, %u currently deleted, %u reusable\n" msgstr "індекс \"%s\": сторінок: %u загалом, %u нещодавно видалено, %u наразі видалено, %u для повторного використання\n" -#: access/heap/vacuumlazy.c:747 commands/analyze.c:796 +#: access/heap/vacuumlazy.c:738 commands/analyze.c:794 #, c-format msgid "I/O timings: read: %.3f ms, write: %.3f ms\n" msgstr "час вводу-виведення: читання %.3f мс, запис: %.3f мс\n" -#: access/heap/vacuumlazy.c:757 commands/analyze.c:799 +#: access/heap/vacuumlazy.c:748 commands/analyze.c:797 #, c-format msgid "avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n" msgstr "середня швидкість читання: %.3f МБ/с, середня швидкість запису: %.3f МБ/с\n" -#: access/heap/vacuumlazy.c:760 commands/analyze.c:801 +#: access/heap/vacuumlazy.c:751 commands/analyze.c:799 #, c-format msgid "buffer usage: %lld hits, %lld misses, %lld dirtied\n" msgstr "використання буфера: %lld звернень, %lld промахів, %lld, брудних записів\n" -#: access/heap/vacuumlazy.c:765 +#: access/heap/vacuumlazy.c:756 #, c-format msgid "WAL usage: %lld records, %lld full page images, %llu bytes\n" msgstr "Використання WAL: %lld записів, %lld зображень на повну сторінку, %llu байтів\n" -#: access/heap/vacuumlazy.c:769 commands/analyze.c:805 +#: access/heap/vacuumlazy.c:760 commands/analyze.c:803 #, c-format msgid "system usage: %s" msgstr "використання системи: %s" -#: access/heap/vacuumlazy.c:2482 +#: access/heap/vacuumlazy.c:2172 #, c-format msgid "table \"%s\": removed %lld dead item identifiers in %u pages" msgstr "таблиця \"%s\": видалено %lld мертвих ідентифікаторів елементів в %u сторінках" -#: access/heap/vacuumlazy.c:2642 +#: access/heap/vacuumlazy.c:2326 #, c-format msgid "bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans" msgstr "безпечне пропущення неістотного обслуговування таблиці \"%s.%s.%s\" після %d сканів індексу" -#: access/heap/vacuumlazy.c:2645 +#: access/heap/vacuumlazy.c:2329 #, c-format msgid "The table's relfrozenxid or relminmxid is too far in the past." msgstr "relfrozenxid або relminmxid таблиці занадто далеко в минулому." -#: access/heap/vacuumlazy.c:2646 +#: access/heap/vacuumlazy.c:2330 #, c-format -msgid "" -"Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" +msgid "Consider increasing configuration parameter \"maintenance_work_mem\" or \"autovacuum_work_mem\".\n" "You might also need to consider other ways for VACUUM to keep up with the allocation of transaction IDs." -msgstr "" -"Можливо, слід збільшити параметр конфігурації \"maintenance_work_mem\" або \"autovacuum_work_mem\".\n" +msgstr "Можливо, слід збільшити параметр конфігурації \"maintenance_work_mem\" або \"autovacuum_work_mem\".\n" "Можливо, вам також доведеться розглянути інші способи, щоб VACUUM не відставав від розподілу ідентифікаторів транзакцій." -#: access/heap/vacuumlazy.c:2891 +#: access/heap/vacuumlazy.c:2592 #, c-format msgid "\"%s\": stopping truncate due to conflicting lock request" msgstr "\"%s\": зупинка скорочення через конфліктний запит блокування" -#: access/heap/vacuumlazy.c:2961 +#: access/heap/vacuumlazy.c:2662 #, c-format msgid "table \"%s\": truncated %u to %u pages" msgstr "таблиця \"%s: скорочена від %u до %u сторінок" -#: access/heap/vacuumlazy.c:3023 +#: access/heap/vacuumlazy.c:2724 #, c-format msgid "table \"%s\": suspending truncate due to conflicting lock request" msgstr "таблиця \"%s: припинення скорочення через конфліктуючий запит блокування" -#: access/heap/vacuumlazy.c:3183 +#: access/heap/vacuumlazy.c:2843 #, c-format msgid "disabling parallel option of vacuum on \"%s\" --- cannot vacuum temporary tables in parallel" msgstr "вимкнення паралельної опції очищення на \"%s\" --- неможливо паралельно очистити тимчасові таблиці" -#: access/heap/vacuumlazy.c:3399 +#: access/heap/vacuumlazy.c:3113 #, c-format msgid "while scanning block %u offset %u of relation \"%s.%s\"" msgstr "під час сканування блоку %u зсувом %u відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3402 +#: access/heap/vacuumlazy.c:3116 #, c-format msgid "while scanning block %u of relation \"%s.%s\"" msgstr "у процесі сканування блоку %u відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3406 +#: access/heap/vacuumlazy.c:3120 #, c-format msgid "while scanning relation \"%s.%s\"" msgstr "у процесі сканування відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3414 +#: access/heap/vacuumlazy.c:3128 #, c-format msgid "while vacuuming block %u offset %u of relation \"%s.%s\"" msgstr "під час очищення блоку %u зсувом %u відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3417 +#: access/heap/vacuumlazy.c:3131 #, c-format msgid "while vacuuming block %u of relation \"%s.%s\"" msgstr "у процесі очищення блоку %u відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3421 +#: access/heap/vacuumlazy.c:3135 #, c-format msgid "while vacuuming relation \"%s.%s\"" msgstr "у процесі очищення відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3426 commands/vacuumparallel.c:1074 +#: access/heap/vacuumlazy.c:3140 commands/vacuumparallel.c:1113 #, c-format msgid "while vacuuming index \"%s\" of relation \"%s.%s\"" msgstr "у процесі очищення індексу \"%s\" відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3431 commands/vacuumparallel.c:1080 +#: access/heap/vacuumlazy.c:3145 commands/vacuumparallel.c:1119 #, c-format msgid "while cleaning up index \"%s\" of relation \"%s.%s\"" msgstr "у процесі очищення індексу \"%s\" відношення \"%s.%s\"" -#: access/heap/vacuumlazy.c:3437 +#: access/heap/vacuumlazy.c:3151 #, c-format msgid "while truncating relation \"%s.%s\" to %u blocks" msgstr "у процесі скорочення відношення \"%s.%s\" до %u блоків" @@ -1446,19 +1630,24 @@ msgstr "метод доступу \"%s\" не є типу %s" msgid "index access method \"%s\" does not have a handler" msgstr "для методу доступу індекса \"%s\" не заданий обробник" -#: access/index/genam.c:490 +#: access/index/genam.c:487 #, c-format msgid "transaction aborted during system catalog scan" msgstr "транзакцію перервано під час сканування системного каталогу" -#: access/index/indexam.c:203 catalog/objectaddress.c:1394 -#: commands/indexcmds.c:2843 commands/tablecmds.c:272 commands/tablecmds.c:296 -#: commands/tablecmds.c:17185 commands/tablecmds.c:18963 +#: access/index/genam.c:655 access/index/indexam.c:82 +#, c-format +msgid "cannot access index \"%s\" while it is being reindexed" +msgstr "неможливо отримати доступ до індекса \"%s\" в процесі реіндексації" + +#: access/index/indexam.c:203 catalog/objectaddress.c:1356 +#: commands/indexcmds.c:2878 commands/tablecmds.c:281 commands/tablecmds.c:305 +#: commands/tablecmds.c:17763 commands/tablecmds.c:19574 #, c-format msgid "\"%s\" is not an index" msgstr "\"%s\" не є індексом" -#: access/index/indexam.c:1016 +#: access/index/indexam.c:1028 #, c-format msgid "operator class %s has no options" msgstr "клас операторів %s без параметрів" @@ -1479,7 +1668,7 @@ msgid "This may be because of a non-immutable index expression." msgstr "Можливо, це викликано змінною природою індексного вираження." #: access/nbtree/nbtpage.c:157 access/nbtree/nbtpage.c:611 -#: parser/parse_utilcmd.c:2326 +#: parser/parse_utilcmd.c:2323 #, c-format msgid "index \"%s\" is not a btree" msgstr "індекс \"%s\" не є b-деревом" @@ -1489,33 +1678,31 @@ msgstr "індекс \"%s\" не є b-деревом" msgid "version mismatch in index \"%s\": file version %d, current version %d, minimal supported version %d" msgstr "невідповідність версії в індексі \"%s\": версія файла %d, поточна версія %d, мінімальна підтримувана версія %d" -#: access/nbtree/nbtpage.c:1866 +#: access/nbtree/nbtpage.c:1861 #, c-format msgid "index \"%s\" contains a half-dead internal page" msgstr "індекс \"%s\" містить наполовину мертву внутрішню сторінку" -#: access/nbtree/nbtpage.c:1868 +#: access/nbtree/nbtpage.c:1863 #, c-format msgid "This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it." msgstr "Це могло статися через переривання VACUUM у версії 9.3 або старше перед оновленням. Будь ласка, виконайте REINDEX." -#: access/nbtree/nbtutils.c:2677 +#: access/nbtree/nbtutils.c:5102 #, c-format msgid "index row size %zu exceeds btree version %u maximum %zu for index \"%s\"" msgstr "розмір рядка індексу %zu перевищує максимальний розмір для версії %u btree %zu для індексу \"%s\"" -#: access/nbtree/nbtutils.c:2683 +#: access/nbtree/nbtutils.c:5108 #, c-format msgid "Index row references tuple (%u,%u) in relation \"%s\"." msgstr "Рядок індексу посилається на кортеж (%u,,%u) у відношенні \"%s\"." -#: access/nbtree/nbtutils.c:2687 +#: access/nbtree/nbtutils.c:5112 #, c-format -msgid "" -"Values larger than 1/3 of a buffer page cannot be indexed.\n" +msgid "Values larger than 1/3 of a buffer page cannot be indexed.\n" "Consider a function index of an MD5 hash of the value, or use full text indexing." -msgstr "" -"Значення, що займають більше, ніж 1/3 сторінки буферу, не можуть бути індексовані.\n" +msgstr "Значення, що займають більше, ніж 1/3 сторінки буферу, не можуть бути індексовані.\n" "Радимо застосувати індекс MD5-хеш значення або використати повнотекстове індексування." #: access/nbtree/nbtvalidate.c:246 @@ -1523,12 +1710,18 @@ msgstr "" msgid "operator family \"%s\" of access method %s is missing support function for types %s and %s" msgstr "сімейство операторів \"%s\" методу доступу %s не має опорної функції для типів %s та %s" -#: access/spgist/spgutils.c:243 +#: access/sequence/sequence.c:75 access/table/table.c:145 +#: optimizer/util/plancat.c:144 +#, c-format +msgid "cannot open relation \"%s\"" +msgstr "неможливо відкрити відношення \"%s\"" + +#: access/spgist/spgutils.c:245 #, c-format msgid "compress method must be defined when leaf type is different from input type" msgstr "метод стиснення повинен бути визначений, коли тип листів відрізняється від вхідного типу" -#: access/spgist/spgutils.c:1015 +#: access/spgist/spgutils.c:1028 #, c-format msgid "SP-GiST inner tuple size %zu exceeds maximum %zu" msgstr "Внутрішній розмір кортежу SP-GiST %zu перевищує максимальний %zu" @@ -1543,82 +1736,76 @@ msgstr "тип даних кінцевого вузла SP-GiST %s не відп msgid "operator family \"%s\" of access method %s is missing support function %d for type %s" msgstr "сімейство операторів \"%s\" методу доступу %s не має опорної функції для типів %d для типу %s" -#: access/table/table.c:145 optimizer/util/plancat.c:145 -#, c-format -msgid "cannot open relation \"%s\"" -msgstr "неможливо відкрити відношення \"%s\"" - -#: access/table/tableam.c:265 +#: access/table/tableam.c:255 #, c-format msgid "tid (%u, %u) is not valid for relation \"%s\"" msgstr "невірний tid (%u, %u) для відношення \"%s\"" -#: access/table/tableamapi.c:116 +#: access/table/tableamapi.c:109 #, c-format -msgid "%s cannot be empty." -msgstr "%s не може бути пустим." +msgid "\"%s\" cannot be empty." +msgstr "\"%s\" не може бути пустим." -#: access/table/tableamapi.c:123 access/transam/xlogrecovery.c:4808 +#: access/table/tableamapi.c:116 access/transam/xlogrecovery.c:4858 #, c-format -msgid "%s is too long (maximum %d characters)." -msgstr "%s занадто довгий (максимум %d символів)." +msgid "\"%s\" is too long (maximum %d characters)." +msgstr "\"%s\" занадто довгий (максимум %d символів)." -#: access/table/tableamapi.c:146 +#: access/table/tableamapi.c:139 #, c-format msgid "table access method \"%s\" does not exist" msgstr "табличного методу доступу \"%s\" не існує" -#: access/table/tableamapi.c:151 +#: access/table/tableamapi.c:144 #, c-format msgid "Table access method \"%s\" does not exist." msgstr "Табличного методу доступу \"%s\" не існує." -#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:152 +#: access/tablesample/bernoulli.c:148 access/tablesample/system.c:151 #, c-format msgid "sample percentage must be between 0 and 100" msgstr "відсоток вибірки повинен задаватися числом від 0 до 100" -#: access/transam/commit_ts.c:279 +#: access/transam/commit_ts.c:287 #, c-format msgid "cannot retrieve commit timestamp for transaction %u" msgstr "не вдалося отримати мітку позначки часу транзакції %u" -#: access/transam/commit_ts.c:377 +#: access/transam/commit_ts.c:385 #, c-format msgid "could not get commit timestamp data" msgstr "не вдалося отримати позначку часу фіксації" -#: access/transam/commit_ts.c:379 +#: access/transam/commit_ts.c:387 #, c-format msgid "Make sure the configuration parameter \"%s\" is set on the primary server." msgstr "Переконайтесь, що в конфігурації основного серверу встановлений параметр \"%s\"." -#: access/transam/commit_ts.c:381 +#: access/transam/commit_ts.c:389 #, c-format msgid "Make sure the configuration parameter \"%s\" is set." msgstr "Переконайтесь, що в конфігурації встановлений параметр \"%s\"." -#: access/transam/multixact.c:1023 +#: access/transam/multixact.c:1091 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database \"%s\"" -msgstr "щоб уникнути втрат даних у базі даних \"%s\", база даних не приймає команди, що створюють нові MultiXactIds" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database \"%s\"" +msgstr "база даних не приймає команди, які призначають нові MultiXactId, щоб уникнути втрати даних через зациклення у базі даних \"%s\"" -#: access/transam/multixact.c:1025 access/transam/multixact.c:1032 -#: access/transam/multixact.c:1056 access/transam/multixact.c:1065 +#: access/transam/multixact.c:1093 access/transam/multixact.c:1100 +#: access/transam/multixact.c:1124 access/transam/multixact.c:1133 +#: access/transam/varsup.c:158 access/transam/varsup.c:165 #, c-format -msgid "" -"Execute a database-wide VACUUM in that database.\n" +msgid "Execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." -msgstr "" -"Виконати очистку (VACUUM) по всій базі даних.\n" +msgstr "Виконати очистку (VACUUM) по всій базі даних.\n" "Можливо, вам доведеться зафіксувати, відкотити назад старі підготовані транзакції або видалити застарілі слоти реплікації." -#: access/transam/multixact.c:1030 +#: access/transam/multixact.c:1098 #, c-format -msgid "database is not accepting commands that generate new MultiXactIds to avoid wraparound data loss in database with OID %u" -msgstr "щоб уникнути втрат даних в базі даних з OID %u, база даних не приймає команди, що створюють нові MultiXactIds" +msgid "database is not accepting commands that assign new MultiXactIds to avoid wraparound data loss in database with OID %u" +msgstr "база даних не приймає команди, які призначають нові MultiXactId, щоб уникнути втрати даних через зациклення у базі даних з OID %u" -#: access/transam/multixact.c:1051 access/transam/multixact.c:2333 +#: access/transam/multixact.c:1119 access/transam/multixact.c:2474 #, c-format msgid "database \"%s\" must be vacuumed before %u more MultiXactId is used" msgid_plural "database \"%s\" must be vacuumed before %u more MultiXactIds are used" @@ -1627,7 +1814,7 @@ msgstr[1] "бази даних \"%s\" повинні бути очищені (va msgstr[2] "баз даних \"%s\" повинні бути очищені (vacuumed) перед тим, як більшість MultiXactIds буде використано (%u)" msgstr[3] "баз даних \"%s\" повинні бути очищені (vacuumed) перед тим, як більшість MultiXactId буде використано (%u)" -#: access/transam/multixact.c:1060 access/transam/multixact.c:2342 +#: access/transam/multixact.c:1128 access/transam/multixact.c:2483 #, c-format msgid "database with OID %u must be vacuumed before %u more MultiXactId is used" msgid_plural "database with OID %u must be vacuumed before %u more MultiXactIds are used" @@ -1636,12 +1823,12 @@ msgstr[1] "бази даних з OID %u повинні бути очищені msgstr[2] "баз даних з OID %u повинні бути очищені (vacuumed), перед тим як більшість MultiXactIds буде використано (%u)" msgstr[3] "баз даних з OID %u повинні бути очищені (vacuumed), перед тим як більшість MultiXactId буде використано (%u)" -#: access/transam/multixact.c:1121 +#: access/transam/multixact.c:1189 #, c-format msgid "multixact \"members\" limit exceeded" msgstr "перевищено ліміт членів мультитранзакції" -#: access/transam/multixact.c:1122 +#: access/transam/multixact.c:1190 #, c-format msgid "This command would create a multixact with %u members, but the remaining space is only enough for %u member." msgid_plural "This command would create a multixact with %u members, but the remaining space is only enough for %u members." @@ -1650,12 +1837,12 @@ msgstr[1] "Мультитранзакція створена цією коман msgstr[2] "Мультитранзакція створена цією командою з %u членів, але місця вистачає лише для %u членів." msgstr[3] "Мультитранзакція створена цією командою з %u членів, але місця вистачає лише для %u членів." -#: access/transam/multixact.c:1127 +#: access/transam/multixact.c:1195 #, c-format -msgid "Execute a database-wide VACUUM in database with OID %u with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Виконати очистку (VACUUM) по всій базі даних з OID %u зі зменшенням значення vacuum_multixact_freeze_min_age та vacuum_multixact_freeze_table_age settings." +msgid "Execute a database-wide VACUUM in database with OID %u with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Виконати очистку (VACUUM) по всій базі даних з OID %u зі зменшенням значення \"vacuum_multixact_freeze_min_age\" та \"vacuum_multixact_freeze_table_age settings\"." -#: access/transam/multixact.c:1158 +#: access/transam/multixact.c:1226 #, c-format msgid "database with OID %u must be vacuumed before %d more multixact member is used" msgid_plural "database with OID %u must be vacuumed before %d more multixact members are used" @@ -1664,201 +1851,202 @@ msgstr[1] "база даних з OID %u повинна бути очищена msgstr[2] "база даних з OID %u повинна бути очищена перед використанням додаткових членів мультитранзакції (%d)" msgstr[3] "база даних з OID %u повинна бути очищена перед використанням додаткових членів мультитранзакції (%d)" -#: access/transam/multixact.c:1163 +#: access/transam/multixact.c:1231 #, c-format -msgid "Execute a database-wide VACUUM in that database with reduced vacuum_multixact_freeze_min_age and vacuum_multixact_freeze_table_age settings." -msgstr "Виконати очищення (VACUUM) по всій цій базі даних зі зменшенням значення vacuum_multixact_freeze_min_age та vacuum_multixact_freeze_table_age settings." +msgid "Execute a database-wide VACUUM in that database with reduced \"vacuum_multixact_freeze_min_age\" and \"vacuum_multixact_freeze_table_age\" settings." +msgstr "Виконати очищення (VACUUM) по всій цій базі даних зі зменшенням значення \"vacuum_multixact_freeze_min_age\" та \"vacuum_multixact_freeze_table_age\" settings." -#: access/transam/multixact.c:1302 +#: access/transam/multixact.c:1371 #, c-format msgid "MultiXactId %u does no longer exist -- apparent wraparound" msgstr "MultiXactId %u припинив існування -- очевидно відбулося зациклення" -#: access/transam/multixact.c:1308 +#: access/transam/multixact.c:1377 #, c-format msgid "MultiXactId %u has not been created yet -- apparent wraparound" msgstr "MultiXactId %u ще не був створений -- очевидно відбулося зациклення" -#: access/transam/multixact.c:2338 access/transam/multixact.c:2347 -#: access/transam/varsup.c:151 access/transam/varsup.c:158 -#: access/transam/varsup.c:466 access/transam/varsup.c:473 +#: access/transam/multixact.c:2479 access/transam/multixact.c:2488 #, c-format -msgid "" -"To avoid a database shutdown, execute a database-wide VACUUM in that database.\n" +msgid "To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." -msgstr "" -"Щоб уникнути вимкнення бази даних, виконайте VACUUM для всієї бази даних.\n" -"Можливо, вам доведеться зафіксувати або відкотити назад старі підготовленні транзакції або видалити застарілі слоти реплікації." +msgstr "Щоб уникнути збоїв у призначенні MultiXactId, виконайте VACUUM для всієї бази даних у цій базі даних.\n" +"Вам також може знадобитися зафіксувати або відкотити старі підготовлені транзакції, або видалити застарілі слоти реплікації." -#: access/transam/multixact.c:2622 +#: access/transam/multixact.c:2767 #, c-format msgid "MultiXact member wraparound protections are disabled because oldest checkpointed MultiXact %u does not exist on disk" msgstr "Захист від зациклення члену MultiXact вимкнена, оскільки найстаріша контрольна точка MultiXact %u не існує на диску" -#: access/transam/multixact.c:2644 +#: access/transam/multixact.c:2789 #, c-format msgid "MultiXact member wraparound protections are now enabled" msgstr "Захист від зациклення члену MultiXact наразі ввімкнена" -#: access/transam/multixact.c:3027 +#: access/transam/multixact.c:3180 #, c-format msgid "oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation" msgstr "найстарішу MultiXact %u не знайдено, найновіша MultiXact %u, скорочення пропускається" -#: access/transam/multixact.c:3045 +#: access/transam/multixact.c:3198 #, c-format msgid "cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation" msgstr "неможливо виконати скорочення до MultiXact %u, оскільки її не існує на диску, скорочення пропускається" -#: access/transam/multixact.c:3359 +#: access/transam/multixact.c:3517 #, c-format msgid "invalid MultiXactId: %u" msgstr "неприпустимий MultiXactId: %u" -#: access/transam/parallel.c:729 access/transam/parallel.c:848 +#: access/transam/parallel.c:731 access/transam/parallel.c:850 #, c-format msgid "parallel worker failed to initialize" msgstr "не вдалося виконати ініціалізацію паралельного виконавця" -#: access/transam/parallel.c:730 access/transam/parallel.c:849 +#: access/transam/parallel.c:732 access/transam/parallel.c:851 #, c-format msgid "More details may be available in the server log." msgstr "Більше деталей можуть бути доступні в журналі серверу." -#: access/transam/parallel.c:910 +#: access/transam/parallel.c:912 #, c-format msgid "postmaster exited during a parallel transaction" msgstr "postmaster завершився під час паралельної транзакції" -#: access/transam/parallel.c:1097 +#: access/transam/parallel.c:1099 #, c-format msgid "lost connection to parallel worker" msgstr "втрачено зв'язок з паралельним виконавцем" -#: access/transam/parallel.c:1163 access/transam/parallel.c:1165 +#: access/transam/parallel.c:1155 access/transam/parallel.c:1157 msgid "parallel worker" msgstr "паралельний виконавець" -#: access/transam/parallel.c:1319 replication/logical/applyparallelworker.c:893 +#: access/transam/parallel.c:1327 replication/logical/applyparallelworker.c:890 #, c-format msgid "could not map dynamic shared memory segment" msgstr "не вдалося відобразити динамічний сегмент спільної пам'яті" -#: access/transam/parallel.c:1324 replication/logical/applyparallelworker.c:899 +#: access/transam/parallel.c:1332 replication/logical/applyparallelworker.c:896 #, c-format msgid "invalid magic number in dynamic shared memory segment" msgstr "неприпустиме магічне число в динамічному сегменті спільної пам'яті" -#: access/transam/rmgr.c:84 +#: access/transam/rmgr.c:93 #, c-format msgid "resource manager with ID %d not registered" msgstr "менеджер ресурсів з ID %d не зареєстрований" -#: access/transam/rmgr.c:85 +#: access/transam/rmgr.c:94 #, c-format -msgid "Include the extension module that implements this resource manager in shared_preload_libraries." -msgstr "Включає модуль розширення, який впроваджує цей менеджер ресурсів у shared_preload_libraries." +msgid "Include the extension module that implements this resource manager in \"shared_preload_libraries\"." +msgstr "Включає модуль розширення, який впроваджує цей менеджер ресурсів у \"shared_preload_libraries\"." -#: access/transam/rmgr.c:101 +#: access/transam/rmgr.c:110 #, c-format msgid "custom resource manager name is invalid" msgstr "назва користувацького менеджера ресурсів неприпустима" -#: access/transam/rmgr.c:102 +#: access/transam/rmgr.c:111 #, c-format msgid "Provide a non-empty name for the custom resource manager." msgstr "Вкажіть непорожню назву для користувацького менеджера ресурсів." -#: access/transam/rmgr.c:105 +#: access/transam/rmgr.c:114 #, c-format msgid "custom resource manager ID %d is out of range" msgstr "ID %d користувацького менеджера ресурсів поза діапазоном" -#: access/transam/rmgr.c:106 +#: access/transam/rmgr.c:115 #, c-format msgid "Provide a custom resource manager ID between %d and %d." msgstr "Вкажіть ID користувацького менеджера ресурсів між %d і %d." -#: access/transam/rmgr.c:111 access/transam/rmgr.c:116 -#: access/transam/rmgr.c:128 +#: access/transam/rmgr.c:120 access/transam/rmgr.c:125 +#: access/transam/rmgr.c:137 #, c-format msgid "failed to register custom resource manager \"%s\" with ID %d" msgstr "не вдалося зареєструвати користувацький менеджер ресурсів \"%s\" з ID %d" -#: access/transam/rmgr.c:112 +#: access/transam/rmgr.c:121 #, c-format -msgid "Custom resource manager must be registered while initializing modules in shared_preload_libraries." -msgstr "Користувацький менеджер ресурсів повинен бути зареєстрований під час ініціалізації модулів у shared_preload_libraries." +msgid "Custom resource manager must be registered while initializing modules in \"shared_preload_libraries\"." +msgstr "Користувацький менеджер ресурсів повинен бути зареєстрований під час ініціалізації модулів у \"shared_preload_libraries\"." -#: access/transam/rmgr.c:117 +#: access/transam/rmgr.c:126 #, c-format msgid "Custom resource manager \"%s\" already registered with the same ID." msgstr "Користувацький менеджер ресурсів \"%s\" вже зареєстрований з таким самим ID." -#: access/transam/rmgr.c:129 +#: access/transam/rmgr.c:138 #, c-format msgid "Existing resource manager with ID %d has the same name." msgstr "Існуючий менеджер ресурсів з ID %d має таку саму назву." -#: access/transam/rmgr.c:135 +#: access/transam/rmgr.c:144 #, c-format msgid "registered custom resource manager \"%s\" with ID %d" msgstr "зареєстрований користувацький менеджер ресурсів \"%s\" з ID %d" -#: access/transam/slru.c:714 +#: access/transam/slru.c:361 +#, c-format +msgid "\"%s\" must be a multiple of %d" +msgstr "\"%s\" має бути кратним %d" + +#: access/transam/slru.c:830 #, c-format msgid "file \"%s\" doesn't exist, reading as zeroes" msgstr "файл \"%s\" не існує, вважається нульовим" -#: access/transam/slru.c:946 access/transam/slru.c:952 -#: access/transam/slru.c:960 access/transam/slru.c:965 -#: access/transam/slru.c:972 access/transam/slru.c:977 -#: access/transam/slru.c:984 access/transam/slru.c:991 +#: access/transam/slru.c:1059 access/transam/slru.c:1065 +#: access/transam/slru.c:1073 access/transam/slru.c:1078 +#: access/transam/slru.c:1085 access/transam/slru.c:1090 +#: access/transam/slru.c:1097 access/transam/slru.c:1104 #, c-format msgid "could not access status of transaction %u" msgstr "не можливо отримати статус транзакції %u" -#: access/transam/slru.c:947 +#: access/transam/slru.c:1060 #, c-format msgid "Could not open file \"%s\": %m." msgstr "Не можливо відкрити файл \"%s\": %m." -#: access/transam/slru.c:953 +#: access/transam/slru.c:1066 #, c-format msgid "Could not seek in file \"%s\" to offset %d: %m." msgstr "Не вдалося знайти у файлі \"%s\" до зсуву %d: %m." -#: access/transam/slru.c:961 +#: access/transam/slru.c:1074 #, c-format msgid "Could not read from file \"%s\" at offset %d: %m." msgstr "Не вдалося прочитати з файлу \"%s\" по зсуву %d: %m." -#: access/transam/slru.c:966 +#: access/transam/slru.c:1079 #, c-format msgid "Could not read from file \"%s\" at offset %d: read too few bytes." msgstr "Не вдалося прочитати з файлу \"%s\" по зсуву %d: прочитано занадто мало байтів." -#: access/transam/slru.c:973 +#: access/transam/slru.c:1086 #, c-format msgid "Could not write to file \"%s\" at offset %d: %m." msgstr "Не вдалося записати до файлу \"%s\" зсув %d: %m." -#: access/transam/slru.c:978 +#: access/transam/slru.c:1091 #, c-format msgid "Could not write to file \"%s\" at offset %d: wrote too few bytes." msgstr "Не вдалося записати до файлу \"%s\" зсув %d: записано занадто мало байтів." -#: access/transam/slru.c:985 +#: access/transam/slru.c:1098 #, c-format msgid "Could not fsync file \"%s\": %m." msgstr "Не вдалося синхронізувати файл \"%s\": %m." -#: access/transam/slru.c:992 +#: access/transam/slru.c:1105 #, c-format msgid "Could not close file \"%s\": %m." msgstr "Не можливо закрити файл \"%s\": %m." -#: access/transam/slru.c:1253 +#: access/transam/slru.c:1431 #, c-format msgid "could not truncate directory \"%s\": apparent wraparound" msgstr "не вдалося спустошити каталог \"%s\": очевидно сталося зациклення" @@ -1903,72 +2091,72 @@ msgstr "Ідентифікатори ліній часу повинні бути msgid "requested timeline %u is not in this server's history" msgstr "в історії даного серверу немає запитаної лінії часу %u" -#: access/transam/twophase.c:386 +#: access/transam/twophase.c:368 #, c-format msgid "transaction identifier \"%s\" is too long" msgstr "ідентифікатор транзакції \"%s\" задовгий" -#: access/transam/twophase.c:393 +#: access/transam/twophase.c:375 #, c-format msgid "prepared transactions are disabled" msgstr "підготовлені транзакції вимкнено" -#: access/transam/twophase.c:394 +#: access/transam/twophase.c:376 #, c-format -msgid "Set max_prepared_transactions to a nonzero value." -msgstr "Встановіть ненульове значення параметра max_prepared_transactions." +msgid "Set \"max_prepared_transactions\" to a nonzero value." +msgstr "Встановіть ненульове значення параметра \"max_prepared_transactions\"." -#: access/transam/twophase.c:413 +#: access/transam/twophase.c:395 #, c-format msgid "transaction identifier \"%s\" is already in use" msgstr "ідентифікатор транзакції \"%s\" вже використовується" -#: access/transam/twophase.c:422 access/transam/twophase.c:2517 +#: access/transam/twophase.c:404 access/transam/twophase.c:2540 #, c-format msgid "maximum number of prepared transactions reached" msgstr "досягнуто максимального числа підготованих транзакцій" -#: access/transam/twophase.c:423 access/transam/twophase.c:2518 +#: access/transam/twophase.c:405 access/transam/twophase.c:2541 #, c-format -msgid "Increase max_prepared_transactions (currently %d)." -msgstr "Збільшіть max_prepared_transactions (наразі %d)." +msgid "Increase \"max_prepared_transactions\" (currently %d)." +msgstr "Збільшіть \"max_prepared_transactions\" (наразі %d)." -#: access/transam/twophase.c:599 +#: access/transam/twophase.c:580 #, c-format msgid "prepared transaction with identifier \"%s\" is busy" msgstr "підготовлена транзакція з ідентифікатором \"%s\" зайнята" -#: access/transam/twophase.c:605 +#: access/transam/twophase.c:586 #, c-format msgid "permission denied to finish prepared transaction" msgstr "немає дозволу для завершення підготовлених транзакцій" -#: access/transam/twophase.c:606 +#: access/transam/twophase.c:587 #, c-format msgid "Must be superuser or the user that prepared the transaction." msgstr "Треба пути суперкористувачем або користувачем, який підготував транзакцію." -#: access/transam/twophase.c:617 +#: access/transam/twophase.c:598 #, c-format msgid "prepared transaction belongs to another database" msgstr "підготовлена транзакція належить до іншої бази даних" -#: access/transam/twophase.c:618 +#: access/transam/twophase.c:599 #, c-format msgid "Connect to the database where the transaction was prepared to finish it." msgstr "З'єднайтесь з базою даних, де була підготовлена транзакція, щоб завершити її." -#: access/transam/twophase.c:633 +#: access/transam/twophase.c:614 #, c-format msgid "prepared transaction with identifier \"%s\" does not exist" msgstr "підготовленої транзакції з ідентифікатором \"%s\" не існує" -#: access/transam/twophase.c:1168 +#: access/transam/twophase.c:1190 #, c-format msgid "two-phase state file maximum length exceeded" msgstr "перевищено граничний розмір файла у 2-фазовому стані" -#: access/transam/twophase.c:1323 +#: access/transam/twophase.c:1345 #, c-format msgid "incorrect size of file \"%s\": %lld byte" msgid_plural "incorrect size of file \"%s\": %lld bytes" @@ -1977,58 +2165,59 @@ msgstr[1] "неправильний розмір файлу \"%s\": %lld бай msgstr[2] "неправильний розмір файлу \"%s\": %lld байтів" msgstr[3] "неправильний розмір файлу \"%s\": %lld байтів" -#: access/transam/twophase.c:1332 +#: access/transam/twophase.c:1354 #, c-format msgid "incorrect alignment of CRC offset for file \"%s\"" msgstr "неправильне вирівнювання зсуву CRC для файлу \"%s\"" -#: access/transam/twophase.c:1350 +#: access/transam/twophase.c:1372 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %lld" -#: access/transam/twophase.c:1365 +#: access/transam/twophase.c:1387 #, c-format msgid "invalid magic number stored in file \"%s\"" msgstr "неприпустиме магічне число, збережене у файлі\"%s\"" -#: access/transam/twophase.c:1371 +#: access/transam/twophase.c:1393 #, c-format msgid "invalid size stored in file \"%s\"" msgstr "неприпустимий розмір, збережений у файлі \"%s\"" -#: access/transam/twophase.c:1383 +#: access/transam/twophase.c:1405 #, c-format msgid "calculated CRC checksum does not match value stored in file \"%s\"" msgstr "обчислена контрольна сума CRC не відповідає значенню, збереженому у файлі \"%s\"" -#: access/transam/twophase.c:1413 access/transam/xlogrecovery.c:590 -#: replication/logical/logical.c:209 replication/walsender.c:687 +#: access/transam/twophase.c:1435 access/transam/xlogrecovery.c:565 +#: postmaster/walsummarizer.c:936 replication/logical/logical.c:211 +#: replication/walsender.c:836 #, c-format msgid "Failed while allocating a WAL reading processor." msgstr "Не вдалося розмістити обробник журналу транзакцій." -#: access/transam/twophase.c:1423 +#: access/transam/twophase.c:1445 #, c-format msgid "could not read two-phase state from WAL at %X/%X: %s" msgstr "не вдалося прочитати 2-фазовий стан з WAL при %X/%X: %s" -#: access/transam/twophase.c:1428 +#: access/transam/twophase.c:1450 #, c-format msgid "could not read two-phase state from WAL at %X/%X" msgstr "не вдалося прочитати 2-фазовий стан з WAL при %X/%X" -#: access/transam/twophase.c:1436 +#: access/transam/twophase.c:1458 #, c-format msgid "expected two-phase state data is not present in WAL at %X/%X" msgstr "очікувані дані 2-фазного стану відсутні в WAL при %X/%X" -#: access/transam/twophase.c:1732 +#: access/transam/twophase.c:1754 #, c-format msgid "could not recreate file \"%s\": %m" msgstr "не вдалося відтворити файл \"%s\": %m" -#: access/transam/twophase.c:1859 +#: access/transam/twophase.c:1881 #, c-format msgid "%u two-phase state file was written for a long-running prepared transaction" msgid_plural "%u two-phase state files were written for long-running prepared transactions" @@ -2037,660 +2226,691 @@ msgstr[1] "%u 2-фазовий стан файлів був записаний msgstr[2] "%u 2-фазовий стан файлів був записаний завдяки довготривалим підготовленим транзакціям" msgstr[3] "%u 2-фазовий стан файлів був записаний завдяки довготривалим підготовленим транзакціям" -#: access/transam/twophase.c:2093 +#: access/transam/twophase.c:2116 #, c-format msgid "recovering prepared transaction %u from shared memory" msgstr "відновлення підготовленої транзакції %u із спільної пам'яті" -#: access/transam/twophase.c:2186 +#: access/transam/twophase.c:2209 #, c-format msgid "removing stale two-phase state file for transaction %u" msgstr "видалення застарілого файла 2-фазового стану для транзакції %u" -#: access/transam/twophase.c:2193 +#: access/transam/twophase.c:2216 #, c-format msgid "removing stale two-phase state from memory for transaction %u" msgstr "видалення з пам'яті застарілого 2-фазового стану для транзакції %u" -#: access/transam/twophase.c:2206 +#: access/transam/twophase.c:2229 #, c-format msgid "removing future two-phase state file for transaction %u" msgstr "видалення файлу майбутнього 2-фазового стану для транзакції %u" -#: access/transam/twophase.c:2213 +#: access/transam/twophase.c:2236 #, c-format msgid "removing future two-phase state from memory for transaction %u" msgstr "видалення з пам'яті майбутнього 2-фазового стану для транзакції %u" -#: access/transam/twophase.c:2238 +#: access/transam/twophase.c:2261 #, c-format msgid "corrupted two-phase state file for transaction %u" msgstr "пошкоджений файл двофазного стану для транзакції %u" -#: access/transam/twophase.c:2243 +#: access/transam/twophase.c:2266 #, c-format msgid "corrupted two-phase state in memory for transaction %u" msgstr "пошкоджена пам'ять двофазного стану для транзакції %u" -#: access/transam/twophase.c:2500 +#: access/transam/twophase.c:2523 #, c-format msgid "could not recover two-phase state file for transaction %u" msgstr "не вдалося відновити файл 2-фазового стану для транзакції %u" -#: access/transam/twophase.c:2502 +#: access/transam/twophase.c:2525 #, c-format msgid "Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk." msgstr "Файл 2-фазового стану був знайдений в запису WAL %X/%X, але ця транзакція вже відновлена з диску." -#: access/transam/twophase.c:2510 jit/jit.c:205 utils/fmgr/dfmgr.c:209 -#: utils/fmgr/dfmgr.c:415 +#: access/transam/twophase.c:2533 storage/file/fd.c:514 utils/fmgr/dfmgr.c:209 #, c-format msgid "could not access file \"%s\": %m" msgstr "немає доступу до файлу \"%s\": %m" -#: access/transam/varsup.c:129 -#, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database \"%s\"" -msgstr "база даних не приймає команди, щоб уникнути втрати даних через зациклення транзакцій в БД \"%s\"" - -#: access/transam/varsup.c:131 access/transam/varsup.c:138 +#: access/transam/varsup.c:156 #, c-format -msgid "" -"Stop the postmaster and vacuum that database in single-user mode.\n" -"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." -msgstr "" -"Зупиніть postmaster і виконайте очищення (vacuum) бази даних в однокористувацькому режимі.\n" -"Можливо, також доведеться зафіксувати або відкотити назад старі підготовлені транзакції, або розірвати застарілі реплікаційні слоти." +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database \"%s\"" +msgstr "база даних не приймає команди, які призначають нові ідентифікатори транзакцій, щоб уникнути обхідної втрати даних у базі даних \"%s\"" -#: access/transam/varsup.c:136 +#: access/transam/varsup.c:163 #, c-format -msgid "database is not accepting commands to avoid wraparound data loss in database with OID %u" -msgstr "база даних не приймає команди задля уникнення втрати даних через зациклення транзакцій в базі даних з OID %u" +msgid "database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database with OID %u" +msgstr "база даних не приймає команди, які призначають нові ідентифікатори транзакцій, щоб уникнути обхідної втрати даних у базі даних з OID %u" -#: access/transam/varsup.c:148 access/transam/varsup.c:463 +#: access/transam/varsup.c:175 access/transam/varsup.c:490 #, c-format msgid "database \"%s\" must be vacuumed within %u transactions" msgstr "база даних \"%s\" повинна бути очищена (граничне число транзакцій: %u)" -#: access/transam/varsup.c:155 access/transam/varsup.c:470 +#: access/transam/varsup.c:178 +#, c-format +msgid "To avoid transaction ID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "Щоб уникнути збоїв у призначенні ID транзакцій, виконайте VACUUM для всієї бази даних у цій базі даних.\n" +"Вам також може знадобитися зафіксувати або відкотити старі підготовлені транзакції, або видалити застарілі слоти реплікації." + +#: access/transam/varsup.c:182 access/transam/varsup.c:497 #, c-format msgid "database with OID %u must be vacuumed within %u transactions" msgstr "база даних з OID %u повинна бути очищена (граничне число транзакцій: %u)" -#: access/transam/xact.c:1102 +#: access/transam/varsup.c:185 access/transam/varsup.c:493 +#: access/transam/varsup.c:500 +#, c-format +msgid "To avoid XID assignment failures, execute a database-wide VACUUM in that database.\n" +"You might also need to commit or roll back old prepared transactions, or drop stale replication slots." +msgstr "Щоб уникнути збоїв у призначенні XID, виконайте VACUUM для всієї бази даних у цій базі даних.\n" +"Вам також може знадобитися зафіксувати або відкотити старі підготовлені транзакції, або видалити застарілі слоти реплікації." + +#: access/transam/xact.c:649 +#, c-format +msgid "cannot assign transaction IDs during a parallel operation" +msgstr "не можна призначити ідентифікатори транзакцій під час паралельних операцій" + +#: access/transam/xact.c:840 +#, c-format +msgid "cannot modify data in a parallel worker" +msgstr "неможливо змінити дані паралельного виконавця" + +#: access/transam/xact.c:1115 +#, c-format +msgid "cannot start commands during a parallel operation" +msgstr "неможливо запустити команди під час паралельних операцій" + +#: access/transam/xact.c:1123 #, c-format msgid "cannot have more than 2^32-2 commands in a transaction" msgstr "в одній транзакції не може бути більше 2^32-2 команд" -#: access/transam/xact.c:1643 +#: access/transam/xact.c:1664 #, c-format msgid "maximum number of committed subtransactions (%d) exceeded" msgstr "перевищено межу числа зафіксованих підтранзакцій (%d)" -#: access/transam/xact.c:2513 +#: access/transam/xact.c:2561 #, c-format msgid "cannot PREPARE a transaction that has operated on temporary objects" msgstr "неможливо виконати PREPARE для транзакції, що здійснювалася на тимчасових об'єктах" -#: access/transam/xact.c:2523 +#: access/transam/xact.c:2571 #, c-format msgid "cannot PREPARE a transaction that has exported snapshots" msgstr "не можна виконати PREPARE для транзакції, яка має експортовані знімки" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3490 +#: access/transam/xact.c:3593 #, c-format msgid "%s cannot run inside a transaction block" msgstr "%s неможливо запустити всередині блоку транзакції" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3500 +#: access/transam/xact.c:3603 #, c-format msgid "%s cannot run inside a subtransaction" msgstr "%s неможливо запустити всередині підтранзакції" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3510 +#: access/transam/xact.c:3613 #, c-format msgid "%s cannot be executed within a pipeline" msgstr "%s не можна використовувати в межах конвеєра" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3520 +#: access/transam/xact.c:3623 #, c-format msgid "%s cannot be executed from a function" msgstr "%s неможливо виконати з функції" #. translator: %s represents an SQL statement name -#: access/transam/xact.c:3591 access/transam/xact.c:3916 -#: access/transam/xact.c:3995 access/transam/xact.c:4118 -#: access/transam/xact.c:4269 access/transam/xact.c:4338 -#: access/transam/xact.c:4449 +#: access/transam/xact.c:3694 access/transam/xact.c:4019 +#: access/transam/xact.c:4098 access/transam/xact.c:4221 +#: access/transam/xact.c:4372 access/transam/xact.c:4441 +#: access/transam/xact.c:4552 #, c-format msgid "%s can only be used in transaction blocks" msgstr "%s може використовуватися тільки в блоках транзакції" -#: access/transam/xact.c:3802 +#: access/transam/xact.c:3905 #, c-format msgid "there is already a transaction in progress" msgstr "транзакція вже виконується" -#: access/transam/xact.c:3921 access/transam/xact.c:4000 -#: access/transam/xact.c:4123 +#: access/transam/xact.c:4024 access/transam/xact.c:4103 +#: access/transam/xact.c:4226 #, c-format msgid "there is no transaction in progress" msgstr "немає незавершеної транзакції" -#: access/transam/xact.c:4011 +#: access/transam/xact.c:4114 #, c-format msgid "cannot commit during a parallel operation" msgstr "не можна фіксувати транзакції під час паралельних операцій" -#: access/transam/xact.c:4134 +#: access/transam/xact.c:4237 #, c-format msgid "cannot abort during a parallel operation" msgstr "не можна перервати під час паралельних операцій" -#: access/transam/xact.c:4233 +#: access/transam/xact.c:4336 #, c-format msgid "cannot define savepoints during a parallel operation" msgstr "не можна визначати точки збереження під час паралельних операцій" -#: access/transam/xact.c:4320 +#: access/transam/xact.c:4423 #, c-format msgid "cannot release savepoints during a parallel operation" msgstr "не можна вивільняти точки збереження під час паралельних транзакцій" -#: access/transam/xact.c:4330 access/transam/xact.c:4381 -#: access/transam/xact.c:4441 access/transam/xact.c:4490 +#: access/transam/xact.c:4433 access/transam/xact.c:4484 +#: access/transam/xact.c:4544 access/transam/xact.c:4593 #, c-format msgid "savepoint \"%s\" does not exist" msgstr "точка збереження \"%s\" не існує" -#: access/transam/xact.c:4387 access/transam/xact.c:4496 +#: access/transam/xact.c:4490 access/transam/xact.c:4599 #, c-format msgid "savepoint \"%s\" does not exist within current savepoint level" msgstr "точка збереження \"%s\" не існує на поточному рівні збереження точок" -#: access/transam/xact.c:4429 +#: access/transam/xact.c:4532 #, c-format msgid "cannot rollback to savepoints during a parallel operation" msgstr "не можна відкотити назад до точки збереження під час паралельних операцій" -#: access/transam/xact.c:4557 -#, c-format -msgid "cannot start subtransactions during a parallel operation" -msgstr "не можна запустити підтранзакцію під час паралельних операцій" - -#: access/transam/xact.c:4625 -#, c-format -msgid "cannot commit subtransactions during a parallel operation" -msgstr "не можна визначити підтранзакцію під час паралельних операцій" - -#: access/transam/xact.c:5271 +#: access/transam/xact.c:5376 #, c-format msgid "cannot have more than 2^32-1 subtransactions in a transaction" msgstr "в одній транзакції не може бути більше 2^32-1 підтранзакцій" -#: access/transam/xlog.c:1468 +#: access/transam/xlog.c:1541 #, c-format msgid "request to flush past end of generated WAL; request %X/%X, current position %X/%X" msgstr "запит на очищення минулого кінця згенерованого WAL; запит %X/%X, поточна позиція %X/%X" -#: access/transam/xlog.c:2230 +#: access/transam/xlog.c:1768 +#, c-format +msgid "cannot read past end of generated WAL: requested %X/%X, current position %X/%X" +msgstr "не вдалося прочитати останній кінець згенерованого WAL: запит %X/%X, поточна позиція %X/%X" + +#: access/transam/xlog.c:2209 access/transam/xlog.c:4500 #, c-format -msgid "could not write to log file %s at offset %u, length %zu: %m" -msgstr "не вдалося записати у файл журналу %s (зсув: %u, довжина: %zu): %m" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Розмір сегмента WAL повинен бути степенем двійки від 1 МБ до 1 ГБ." -#: access/transam/xlog.c:3457 access/transam/xlogutils.c:833 -#: replication/walsender.c:2725 +#: access/transam/xlog.c:2227 +#, c-format +msgid "\"%s\" must be set to -1 during binary upgrade mode." +msgstr "\"%s\" має бути встановлено на -1 під час двійкового режиму оновлення." + +#: access/transam/xlog.c:2476 +#, c-format +msgid "could not write to log file \"%s\" at offset %u, length %zu: %m" +msgstr "не вдалося записати до файлу журналу подій \"%s\" при зсуві %u, довжина %zu: %m" + +#: access/transam/xlog.c:3738 access/transam/xlogutils.c:831 +#: replication/walsender.c:3045 #, c-format msgid "requested WAL segment %s has already been removed" msgstr "запитуваний сегмент WAL %s вже видалений" -#: access/transam/xlog.c:3741 +#: access/transam/xlog.c:4060 #, c-format msgid "could not rename file \"%s\": %m" msgstr "не вдалося перейменувати файл \"%s\": %m" -#: access/transam/xlog.c:3783 access/transam/xlog.c:3793 +#: access/transam/xlog.c:4103 access/transam/xlog.c:4114 +#: access/transam/xlog.c:4135 #, c-format msgid "required WAL directory \"%s\" does not exist" msgstr "необхідний каталог WAL \"%s\" не існує" -#: access/transam/xlog.c:3799 +#: access/transam/xlog.c:4120 access/transam/xlog.c:4141 #, c-format msgid "creating missing WAL directory \"%s\"" msgstr "створюється відсутній каталог WAL \"%s\"" -#: access/transam/xlog.c:3802 commands/dbcommands.c:3172 +#: access/transam/xlog.c:4124 access/transam/xlog.c:4144 +#: commands/dbcommands.c:3259 #, c-format msgid "could not create missing directory \"%s\": %m" msgstr "не вдалося створити відстуній каталог \"%s\": %m" -#: access/transam/xlog.c:3869 +#: access/transam/xlog.c:4211 #, c-format msgid "could not generate secret authorization token" msgstr "не вдалося згенерувати секретний токен для авторизації" -#: access/transam/xlog.c:4019 access/transam/xlog.c:4028 -#: access/transam/xlog.c:4052 access/transam/xlog.c:4059 -#: access/transam/xlog.c:4066 access/transam/xlog.c:4071 -#: access/transam/xlog.c:4078 access/transam/xlog.c:4085 -#: access/transam/xlog.c:4092 access/transam/xlog.c:4099 -#: access/transam/xlog.c:4106 access/transam/xlog.c:4113 -#: access/transam/xlog.c:4122 access/transam/xlog.c:4129 -#: utils/init/miscinit.c:1769 +#: access/transam/xlog.c:4362 access/transam/xlog.c:4372 +#: access/transam/xlog.c:4398 access/transam/xlog.c:4406 +#: access/transam/xlog.c:4414 access/transam/xlog.c:4420 +#: access/transam/xlog.c:4428 access/transam/xlog.c:4436 +#: access/transam/xlog.c:4444 access/transam/xlog.c:4452 +#: access/transam/xlog.c:4460 access/transam/xlog.c:4468 +#: access/transam/xlog.c:4478 access/transam/xlog.c:4486 +#: utils/init/miscinit.c:1758 #, c-format msgid "database files are incompatible with server" msgstr "файли бази даних є несумісними з даним сервером" -#: access/transam/xlog.c:4020 +#: access/transam/xlog.c:4363 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d (0x%08x), but the server was compiled with PG_CONTROL_VERSION %d (0x%08x)." msgstr "Кластер бази даних було ініціалізовано з PG_CONTROL_VERSION %d (0x%08x), але сервер було скомпільовано з PG_CONTROL_VERSION %d (0x%08x)." -#: access/transam/xlog.c:4024 +#: access/transam/xlog.c:4367 #, c-format msgid "This could be a problem of mismatched byte ordering. It looks like you need to initdb." msgstr "Можливо, проблема викликана різним порядком байту. Здається, вам потрібно виконати команду \"initdb\"." -#: access/transam/xlog.c:4029 +#: access/transam/xlog.c:4373 #, c-format msgid "The database cluster was initialized with PG_CONTROL_VERSION %d, but the server was compiled with PG_CONTROL_VERSION %d." msgstr "Кластер баз даних був ініціалізований з PG_CONTROL_VERSION %d, але сервер скомпільований з PG_CONTROL_VERSION %d." -#: access/transam/xlog.c:4032 access/transam/xlog.c:4056 -#: access/transam/xlog.c:4063 access/transam/xlog.c:4068 +#: access/transam/xlog.c:4376 access/transam/xlog.c:4402 +#: access/transam/xlog.c:4410 access/transam/xlog.c:4416 #, c-format msgid "It looks like you need to initdb." msgstr "Здається, Вам треба виконати initdb." -#: access/transam/xlog.c:4043 +#: access/transam/xlog.c:4388 #, c-format msgid "incorrect checksum in control file" msgstr "помилка контрольної суми у файлі pg_control" -#: access/transam/xlog.c:4053 +#: access/transam/xlog.c:4399 #, c-format msgid "The database cluster was initialized with CATALOG_VERSION_NO %d, but the server was compiled with CATALOG_VERSION_NO %d." msgstr "Кластер бази даних було ініціалізовано з CATALOG_VERSION_NO %d, але сервер було скомпільовано з CATALOG_VERSION_NO %d." -#: access/transam/xlog.c:4060 +#: access/transam/xlog.c:4407 #, c-format msgid "The database cluster was initialized with MAXALIGN %d, but the server was compiled with MAXALIGN %d." msgstr "Кластер бази даних було ініціалізовано з MAXALIGN %d, але сервер було скомпільовано з MAXALIGN %d." -#: access/transam/xlog.c:4067 +#: access/transam/xlog.c:4415 #, c-format msgid "The database cluster appears to use a different floating-point number format than the server executable." msgstr "Здається, в кластері баз даних і в програмі сервера використовуються різні формати чисел з плаваючою точкою." -#: access/transam/xlog.c:4072 +#: access/transam/xlog.c:4421 #, c-format msgid "The database cluster was initialized with BLCKSZ %d, but the server was compiled with BLCKSZ %d." msgstr "Кластер бази даних було ініціалізовано з BLCKSZ %d, але сервер було скомпільовано з BLCKSZ %d." -#: access/transam/xlog.c:4075 access/transam/xlog.c:4082 -#: access/transam/xlog.c:4089 access/transam/xlog.c:4096 -#: access/transam/xlog.c:4103 access/transam/xlog.c:4110 -#: access/transam/xlog.c:4117 access/transam/xlog.c:4125 -#: access/transam/xlog.c:4132 +#: access/transam/xlog.c:4424 access/transam/xlog.c:4432 +#: access/transam/xlog.c:4440 access/transam/xlog.c:4448 +#: access/transam/xlog.c:4456 access/transam/xlog.c:4464 +#: access/transam/xlog.c:4472 access/transam/xlog.c:4481 +#: access/transam/xlog.c:4489 #, c-format msgid "It looks like you need to recompile or initdb." msgstr "Здається, вам потрібно перекомпілювати сервер або виконати initdb." -#: access/transam/xlog.c:4079 +#: access/transam/xlog.c:4429 #, c-format msgid "The database cluster was initialized with RELSEG_SIZE %d, but the server was compiled with RELSEG_SIZE %d." msgstr "Кластер бази даних було ініціалізовано з ELSEG_SIZE %d, але сервер було скомпільовано з ELSEG_SIZE %d." -#: access/transam/xlog.c:4086 +#: access/transam/xlog.c:4437 #, c-format msgid "The database cluster was initialized with XLOG_BLCKSZ %d, but the server was compiled with XLOG_BLCKSZ %d." msgstr "Кластер бази даних було ініціалізовано з XLOG_BLCKSZ %d, але сервер було скомпільовано з XLOG_BLCKSZ %d." -#: access/transam/xlog.c:4093 +#: access/transam/xlog.c:4445 #, c-format msgid "The database cluster was initialized with NAMEDATALEN %d, but the server was compiled with NAMEDATALEN %d." msgstr "Кластер бази даних було ініціалізовано з NAMEDATALEN %d, але сервер було скомпільовано з NAMEDATALEN %d." -#: access/transam/xlog.c:4100 +#: access/transam/xlog.c:4453 #, c-format msgid "The database cluster was initialized with INDEX_MAX_KEYS %d, but the server was compiled with INDEX_MAX_KEYS %d." msgstr "Кластер бази даних було ініціалізовано з INDEX_MAX_KEYS %d, але сервер було скомпільовано з INDEX_MAX_KEYS %d." -#: access/transam/xlog.c:4107 +#: access/transam/xlog.c:4461 #, c-format msgid "The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d, but the server was compiled with TOAST_MAX_CHUNK_SIZE %d." msgstr "Кластер бази даних було ініціалізовано з TOAST_MAX_CHUNK_SIZE %d, але сервер було скомпільовано з TOAST_MAX_CHUNK_SIZE %d." -#: access/transam/xlog.c:4114 +#: access/transam/xlog.c:4469 #, c-format msgid "The database cluster was initialized with LOBLKSIZE %d, but the server was compiled with LOBLKSIZE %d." msgstr "Кластер бази даних було ініціалізовано з LOBLKSIZE %d, але сервер було скомпільовано з LOBLKSIZE %d." -#: access/transam/xlog.c:4123 +#: access/transam/xlog.c:4479 #, c-format msgid "The database cluster was initialized without USE_FLOAT8_BYVAL but the server was compiled with USE_FLOAT8_BYVAL." msgstr "Кластер бази даних було ініціалізовано без USE_FLOAT8_BYVAL, але сервер було скомпільовано з USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4130 +#: access/transam/xlog.c:4487 #, c-format msgid "The database cluster was initialized with USE_FLOAT8_BYVAL but the server was compiled without USE_FLOAT8_BYVAL." msgstr "Кластер бази даних було ініціалізовано з USE_FLOAT8_BYVAL, але сервер було скомпільовано без USE_FLOAT8_BYVAL." -#: access/transam/xlog.c:4139 +#: access/transam/xlog.c:4496 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[1] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[2] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[3] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "невірний розмір сегменту WAL у файлі керування (%d байт)" +msgstr[1] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[2] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[3] "невірний розмір сегмента WAL у файлі керування (%d байтів)" -#: access/transam/xlog.c:4151 +#: access/transam/xlog.c:4509 #, c-format msgid "\"min_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"min_wal_size\" має бути мінімум у 2 рази більше, ніж \"wal_segment_size\"" -#: access/transam/xlog.c:4155 +#: access/transam/xlog.c:4513 #, c-format msgid "\"max_wal_size\" must be at least twice \"wal_segment_size\"" msgstr "\"max_wal_size\" має бути мінімум у 2 рази більше, ніж \"wal_segment_size\"" -#: access/transam/xlog.c:4310 catalog/namespace.c:4335 -#: commands/tablespace.c:1216 commands/user.c:2530 commands/variable.c:72 -#: utils/error/elog.c:2209 +#: access/transam/xlog.c:4661 catalog/namespace.c:4681 +#: commands/tablespace.c:1210 commands/user.c:2529 commands/variable.c:72 +#: replication/slot.c:2429 tcop/postgres.c:3715 utils/error/elog.c:2247 #, c-format msgid "List syntax is invalid." msgstr "Помилка синтаксису у списку." -#: access/transam/xlog.c:4356 commands/user.c:2546 commands/variable.c:173 -#: utils/error/elog.c:2235 +#: access/transam/xlog.c:4707 commands/user.c:2545 commands/variable.c:173 +#: tcop/postgres.c:3731 utils/error/elog.c:2273 #, c-format msgid "Unrecognized key word: \"%s\"." msgstr "Нерозпізнане ключове слово: \"%s\"." -#: access/transam/xlog.c:4770 +#: access/transam/xlog.c:5128 #, c-format msgid "could not write bootstrap write-ahead log file: %m" msgstr "не вдалося записати початкове завантаження випереджувального журналювання: %m" -#: access/transam/xlog.c:4778 +#: access/transam/xlog.c:5136 #, c-format msgid "could not fsync bootstrap write-ahead log file: %m" msgstr "не вдалося скинути на диск початкове завантаження випереджувального журналювання: %m" -#: access/transam/xlog.c:4784 +#: access/transam/xlog.c:5142 #, c-format msgid "could not close bootstrap write-ahead log file: %m" msgstr "не вдалося закрити початкове завантаження випереджувального журналювання: %m" -#: access/transam/xlog.c:5001 +#: access/transam/xlog.c:5367 #, c-format -msgid "WAL was generated with wal_level=minimal, cannot continue recovering" -msgstr "WAL був створений з параметром wal_level=minimal, неможливо продовжити відновлення" +msgid "WAL was generated with \"wal_level=minimal\", cannot continue recovering" +msgstr "WAL був створений з \"wal_level=minimal\", неможливо продовжити відновлення" -#: access/transam/xlog.c:5002 +#: access/transam/xlog.c:5368 #, c-format -msgid "This happens if you temporarily set wal_level=minimal on the server." -msgstr "Це трапляється, якщо ви тимчасово встановили параметр wal_level=minimal на сервері." +msgid "This happens if you temporarily set \"wal_level=minimal\" on the server." +msgstr "Це трапляється, якщо ви тимчасово встановили \"wal_level=minimal\" на сервері." -#: access/transam/xlog.c:5003 +#: access/transam/xlog.c:5369 #, c-format -msgid "Use a backup taken after setting wal_level to higher than minimal." -msgstr "Використовуйте резервну копію, зроблену після встановлення значення wal_level, що перевищує максимальне." +msgid "Use a backup taken after setting \"wal_level\" to higher than \"minimal\"." +msgstr "Використовуйте резервну копію, зроблену після встановлення значення wal_level, що перевищує мінимальний рівень." -#: access/transam/xlog.c:5067 +#: access/transam/xlog.c:5434 #, c-format msgid "control file contains invalid checkpoint location" msgstr "контрольний файл містить недійсне розташування контрольної точки" -#: access/transam/xlog.c:5078 +#: access/transam/xlog.c:5445 #, c-format msgid "database system was shut down at %s" msgstr "система бази даних була вимкнена %s" -#: access/transam/xlog.c:5084 +#: access/transam/xlog.c:5451 #, c-format msgid "database system was shut down in recovery at %s" msgstr "система бази даних завершила роботу у процесі відновлення %s" -#: access/transam/xlog.c:5090 +#: access/transam/xlog.c:5457 #, c-format msgid "database system shutdown was interrupted; last known up at %s" msgstr "завершення роботи бази даних було перервано; останній момент роботи %s" -#: access/transam/xlog.c:5096 +#: access/transam/xlog.c:5463 #, c-format msgid "database system was interrupted while in recovery at %s" msgstr "система бази даних була перервана в процесі відновлення %s" -#: access/transam/xlog.c:5098 +#: access/transam/xlog.c:5465 #, c-format msgid "This probably means that some data is corrupted and you will have to use the last backup for recovery." msgstr "Це, ймовірно, означає, що деякі дані були пошкоджені, і вам доведеться відновити базу даних з останнього збереження." -#: access/transam/xlog.c:5104 +#: access/transam/xlog.c:5471 #, c-format msgid "database system was interrupted while in recovery at log time %s" msgstr "робота системи бази даних була перервана в процесі відновлення, час в журналі %s" -#: access/transam/xlog.c:5106 +#: access/transam/xlog.c:5473 #, c-format msgid "If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target." msgstr "Якщо це відбувається більше, ніж один раз, можливо, якісь дані були зіпсовані, і для відновлення треба вибрати більш ранню точку." -#: access/transam/xlog.c:5112 +#: access/transam/xlog.c:5479 #, c-format msgid "database system was interrupted; last known up at %s" msgstr "робота системи бази даних була перервана; останній момент роботи %s" -#: access/transam/xlog.c:5118 +#: access/transam/xlog.c:5486 #, c-format msgid "control file contains invalid database cluster state" msgstr "контрольний файл містить недійсний стан кластеру бази даних" -#: access/transam/xlog.c:5502 +#: access/transam/xlog.c:5874 #, c-format msgid "WAL ends before end of online backup" msgstr "WAL завершився до завершення онлайн резервного копіювання" -#: access/transam/xlog.c:5503 +#: access/transam/xlog.c:5875 #, c-format msgid "All WAL generated while online backup was taken must be available at recovery." msgstr "Всі журнали WAL, створені під час резервного копіювання \"на ходу\", повинні бути в наявності для відновлення." -#: access/transam/xlog.c:5506 +#: access/transam/xlog.c:5879 #, c-format msgid "WAL ends before consistent recovery point" msgstr "WAL завершився до узгодженої точки відновлення" -#: access/transam/xlog.c:5552 +#: access/transam/xlog.c:5925 #, c-format msgid "selected new timeline ID: %u" msgstr "вибрано новий ID часової лінії: %u" -#: access/transam/xlog.c:5585 +#: access/transam/xlog.c:5958 #, c-format msgid "archive recovery complete" msgstr "відновлення архіву завершено" -#: access/transam/xlog.c:6191 +#: access/transam/xlog.c:6587 #, c-format msgid "shutting down" msgstr "завершення роботи" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6230 +#: access/transam/xlog.c:6626 #, c-format msgid "restartpoint starting:%s%s%s%s%s%s%s%s" msgstr "початок точки перезапуску: %s%s%s%s%s%s%s%s" #. translator: the placeholders show checkpoint options -#: access/transam/xlog.c:6242 +#: access/transam/xlog.c:6638 #, c-format msgid "checkpoint starting:%s%s%s%s%s%s%s%s" msgstr "початок контрольної точки: %s%s%s%s%s%s%s%s" -#: access/transam/xlog.c:6307 +#: access/transam/xlog.c:6703 #, c-format msgid "restartpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "точка перезапуску завершена: записано %d буферів (%.1f%%); %d WAL файлів додано, %d видалено, %d перероблених; запис=%ld.%03d сек, синхронізація=%ld.%03d сек, усього=%ld.%03d сек; файли синхронізації=%d, найдовший=%ld.%03d сек, середній=%ld.%03d сек; дистанція=%d кб, приблизно=%d кб; lsn=%X/%X, lsn повтору=%X/%X" -#: access/transam/xlog.c:6330 +#: access/transam/xlog.c:6726 #, c-format msgid "checkpoint complete: wrote %d buffers (%.1f%%); %d WAL file(s) added, %d removed, %d recycled; write=%ld.%03d s, sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X" msgstr "контрольна точка завершена: записано %d буферів (%.1f%%); %d WAL файлів додано, %d видалено, %d перероблених; запис=%ld.%03d сек, синхронізація=%ld.%03d сек, усього=%ld.%03d сек; файли синхронізації=%d, найдовший=%ld.%03d сек, середній=%ld.%03d сек; дистанція=%d кб, приблизно=%d кб; lsn=%X/%X, lsn повтору=%X/%X" -#: access/transam/xlog.c:6768 +#: access/transam/xlog.c:7208 #, c-format msgid "concurrent write-ahead log activity while database system is shutting down" msgstr "під час того вимкнення БД помічено конкурентну активність у випереджувальному журналюванні" -#: access/transam/xlog.c:7329 +#: access/transam/xlog.c:7793 #, c-format msgid "recovery restart point at %X/%X" msgstr "відновлення збереженої точки %X/%X" -#: access/transam/xlog.c:7331 +#: access/transam/xlog.c:7795 #, c-format msgid "Last completed transaction was at log time %s." msgstr "Остання завершена транзакція була в %s." -#: access/transam/xlog.c:7579 +#: access/transam/xlog.c:8057 #, c-format msgid "restore point \"%s\" created at %X/%X" msgstr "точка відновлення \"%s\" створена в %X/%X" -#: access/transam/xlog.c:7786 +#: access/transam/xlog.c:8264 #, c-format msgid "online backup was canceled, recovery cannot continue" msgstr "онлайн резервне копіювання скасовано, неможливо продовжити відновлення" -#: access/transam/xlog.c:7843 +#: access/transam/xlog.c:8322 #, c-format msgid "unexpected timeline ID %u (should be %u) in shutdown checkpoint record" msgstr "неочікуваний ID лінії часу %u (повинен бути %u) у записі контрольної точки вимкнення" -#: access/transam/xlog.c:7901 +#: access/transam/xlog.c:8380 #, c-format msgid "unexpected timeline ID %u (should be %u) in online checkpoint record" msgstr "неочікуваний ID лінії часу %u (повинен бути %u) у записі контрольної точки онлайн" -#: access/transam/xlog.c:7930 +#: access/transam/xlog.c:8409 #, c-format msgid "unexpected timeline ID %u (should be %u) in end-of-recovery record" msgstr "неочікуваний ID лінії часу %u (повинен бути %u) у записі кінця відновлення" -#: access/transam/xlog.c:8197 +#: access/transam/xlog.c:8680 #, c-format msgid "could not fsync write-through file \"%s\": %m" msgstr "не вдалосьясинхронізувати файл наскрізного запису %s: %m" -#: access/transam/xlog.c:8202 +#: access/transam/xlog.c:8685 #, c-format msgid "could not fdatasync file \"%s\": %m" msgstr "не вдалося fdatasync файл \"%s\": %m" -#: access/transam/xlog.c:8287 access/transam/xlog.c:8610 +#: access/transam/xlog.c:8772 access/transam/xlog.c:9108 #, c-format msgid "WAL level not sufficient for making an online backup" msgstr "Обраний рівень WAL недостатній для резервного копіювання \"на ходу\"" -#: access/transam/xlog.c:8288 access/transam/xlog.c:8611 -#: access/transam/xlogfuncs.c:254 +#: access/transam/xlog.c:8773 access/transam/xlogfuncs.c:248 #, c-format -msgid "wal_level must be set to \"replica\" or \"logical\" at server start." -msgstr "встановіть wal_level \"replica\" або \"logical\" при запуску серверу." +msgid "\"wal_level\" must be set to \"replica\" or \"logical\" at server start." +msgstr "\"wal_level\" потрібно задати \"replica\" або \"logical\" при запуску сервера." -#: access/transam/xlog.c:8293 +#: access/transam/xlog.c:8778 #, c-format msgid "backup label too long (max %d bytes)" msgstr "мітка резервного копіювання задовга (максимум %d байт)" -#: access/transam/xlog.c:8414 +#: access/transam/xlog.c:8899 #, c-format -msgid "WAL generated with full_page_writes=off was replayed since last restartpoint" -msgstr "Після останньої точки відновлення був відтворений WAL, створений в режимі full_page_writes=off" +msgid "WAL generated with \"full_page_writes=off\" was replayed since last restartpoint" +msgstr "Після останньої точки відновлення був відтворений WAL, створений в режимі \"full_page_writes=off\"" -#: access/transam/xlog.c:8416 access/transam/xlog.c:8699 +#: access/transam/xlog.c:8901 access/transam/xlog.c:9197 #, c-format -msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable full_page_writes and run CHECKPOINT on the primary, and then try an online backup again." -msgstr "Це означає, що резервна копія, зроблена на резервному сервері пошкоджена і не повинна використовуватись. Активуйте full_page_writes і запустіть CHECKPOINT на основному сервері, а потім спробуйте ще раз створити резервну копію в Інтернеті." +msgid "This means that the backup being taken on the standby is corrupt and should not be used. Enable \"full_page_writes\" and run CHECKPOINT on the primary, and then try an online backup again." +msgstr "Це означає, що резервна копія, зроблена на резервному сервері пошкоджена і не повинна використовуватись. Активуйте \"full_page_writes\" і запустіть CHECKPOINT на основному сервері, а потім спробуйте ще раз створити резервну копію." -#: access/transam/xlog.c:8483 backup/basebackup.c:1351 utils/adt/misc.c:354 +#: access/transam/xlog.c:8981 backup/basebackup.c:1417 utils/adt/misc.c:354 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "не можливо прочитати символічне послання \"%s\": %m" -#: access/transam/xlog.c:8490 backup/basebackup.c:1356 utils/adt/misc.c:359 +#: access/transam/xlog.c:8988 backup/basebackup.c:1422 utils/adt/misc.c:359 #, c-format msgid "symbolic link \"%s\" target is too long" msgstr "таргет символічного посилання \"%s\" задовгий" -#: access/transam/xlog.c:8649 backup/basebackup.c:1217 +#: access/transam/xlog.c:9109 +#, c-format +msgid "wal_level must be set to \"replica\" or \"logical\" at server start." +msgstr "встановіть wal_level \"replica\" або \"logical\" при запуску серверу." + +#: access/transam/xlog.c:9147 backup/basebackup.c:1281 #, c-format msgid "the standby was promoted during online backup" msgstr "режим очікування було підвищено у процесі резервного копіювання \"на ходу\"" -#: access/transam/xlog.c:8650 backup/basebackup.c:1218 +#: access/transam/xlog.c:9148 backup/basebackup.c:1282 #, c-format msgid "This means that the backup being taken is corrupt and should not be used. Try taking another online backup." msgstr "Це означає, що вибрана резервна копія є пошкодженою і її не слід використовувати. Спробуйте використати іншу онлайн резервну копію." -#: access/transam/xlog.c:8697 +#: access/transam/xlog.c:9195 #, c-format -msgid "WAL generated with full_page_writes=off was replayed during online backup" -msgstr "У процесі резервного копіювання \"на ходу\" був відтворений WAL, створений в режимі full_page_writes=off" +msgid "WAL generated with \"full_page_writes=off\" was replayed during online backup" +msgstr "WAL створений з \"full_page_writes=off\" було відтворено під час резервного копіювання" -#: access/transam/xlog.c:8813 +#: access/transam/xlog.c:9311 #, c-format msgid "base backup done, waiting for required WAL segments to be archived" msgstr "резервне копіювання виконане, очікуються необхідні сегменти WAL для архівації" -#: access/transam/xlog.c:8827 +#: access/transam/xlog.c:9325 #, c-format msgid "still waiting for all required WAL segments to be archived (%d seconds elapsed)" msgstr "все ще чекає на необхідні сегменти WAL для архівації (%d секунд пройшло)" -#: access/transam/xlog.c:8829 +#: access/transam/xlog.c:9327 #, c-format -msgid "Check that your archive_command is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." -msgstr "Перевірте, чи правильно виконується команда archive_command. Ви можете безпечно скасувати це резервне копіювання, але резервна копія БД буде непридатна без усіх сегментів WAL." +msgid "Check that your \"archive_command\" is executing properly. You can safely cancel this backup, but the database backup will not be usable without all the WAL segments." +msgstr "Перевірте, що ваша \"archive_command\" виконується належним чином. Ви можете безпечно скасувати резервну копію, але резервне копіювання бази даних буде непридатним без всіх сегментів WAL." -#: access/transam/xlog.c:8836 +#: access/transam/xlog.c:9334 #, c-format msgid "all required WAL segments have been archived" msgstr "усі необхідні сегменти WAL архівовані" -#: access/transam/xlog.c:8840 +#: access/transam/xlog.c:9338 #, c-format msgid "WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup" msgstr "архівація WAL не налаштована; ви повинні забезпечити копіювання всіх необхідних сегментів WAL іншими засобами для отримання резервної копії" -#: access/transam/xlog.c:8879 +#: access/transam/xlog.c:9377 #, c-format msgid "aborting backup due to backend exiting before pg_backup_stop was called" msgstr "припинення резервного копіювання через завершення обслуговуючого процесу до виклику pg_backup_stop" -#: access/transam/xlogarchive.c:214 +#: access/transam/xlogarchive.c:213 #, c-format msgid "archive file \"%s\" has wrong size: %lld instead of %lld" msgstr "файл архіву \"%s\" має неправильний розмір: %lld замість %lld" -#: access/transam/xlogarchive.c:223 +#: access/transam/xlogarchive.c:222 #, c-format msgid "restored log file \"%s\" from archive" msgstr "відновлений файл журналу \"%s\" з архіву" -#: access/transam/xlogarchive.c:237 +#: access/transam/xlogarchive.c:236 #, c-format -msgid "restore_command returned a zero exit status, but stat() failed." -msgstr "restore_command повернула нульовий статус виходу, але stat() не вдався." +msgid "\"restore_command\" returned a zero exit status, but stat() failed." +msgstr "\"restore_command\" повернула нульовий статус виходу, але виклик stat() не вдався." -#: access/transam/xlogarchive.c:269 +#: access/transam/xlogarchive.c:268 #, c-format msgid "could not restore file \"%s\" from archive: %s" msgstr "неможливо відновити файл \"%s\" з архіву: %s" @@ -2698,104 +2918,114 @@ msgstr "неможливо відновити файл \"%s\" з архіву: % #. translator: First %s represents a postgresql.conf parameter name like #. "recovery_end_command", the 2nd is the value of that parameter, the #. third an already translated error message. -#: access/transam/xlogarchive.c:347 +#: access/transam/xlogarchive.c:346 #, c-format msgid "%s \"%s\": %s" msgstr "%s \"%s\": %s" -#: access/transam/xlogarchive.c:457 access/transam/xlogarchive.c:537 +#: access/transam/xlogarchive.c:456 access/transam/xlogarchive.c:536 #, c-format msgid "could not create archive status file \"%s\": %m" msgstr "неможливо створити файл статусу архіву \"%s\": %m" -#: access/transam/xlogarchive.c:465 access/transam/xlogarchive.c:545 +#: access/transam/xlogarchive.c:464 access/transam/xlogarchive.c:544 #, c-format msgid "could not write archive status file \"%s\": %m" msgstr "неможливо записати файл архівного статусу \"%s\": %m" -#: access/transam/xlogfuncs.c:75 backup/basebackup.c:973 +#: access/transam/xlogfuncs.c:69 backup/basebackup.c:997 #, c-format msgid "a backup is already in progress in this session" msgstr "резервне копіювання наразі триває в цьому сеансі" -#: access/transam/xlogfuncs.c:146 +#: access/transam/xlogfuncs.c:140 #, c-format msgid "backup is not in progress" msgstr "резервне копіювання не виконується" -#: access/transam/xlogfuncs.c:147 +#: access/transam/xlogfuncs.c:141 #, c-format msgid "Did you call pg_backup_start()?" msgstr "Ви викликали pg_backup_start()?" -#: access/transam/xlogfuncs.c:190 access/transam/xlogfuncs.c:248 -#: access/transam/xlogfuncs.c:287 access/transam/xlogfuncs.c:308 -#: access/transam/xlogfuncs.c:329 +#: access/transam/xlogfuncs.c:184 access/transam/xlogfuncs.c:242 +#: access/transam/xlogfuncs.c:281 access/transam/xlogfuncs.c:302 +#: access/transam/xlogfuncs.c:323 #, c-format msgid "WAL control functions cannot be executed during recovery." msgstr "Функції управління WAL не можна використовувати під час відновлення." -#: access/transam/xlogfuncs.c:215 access/transam/xlogfuncs.c:399 -#: access/transam/xlogfuncs.c:457 +#: access/transam/xlogfuncs.c:209 access/transam/xlogfuncs.c:389 +#: access/transam/xlogfuncs.c:447 #, c-format msgid "%s cannot be executed during recovery." msgstr "%s не можна використовувати під час відновлення." -#: access/transam/xlogfuncs.c:221 +#: access/transam/xlogfuncs.c:215 #, c-format -msgid "pg_log_standby_snapshot() can only be used if wal_level >= replica" -msgstr "pg_log_standby_snapshot() можна використовувати лише якщо wal_level >= replica" +msgid "pg_log_standby_snapshot() can only be used if \"wal_level\" >= \"replica\"" +msgstr "pg_log_standby_snapshot() можна використовувати лише якщо \"wal_level\" >= \"replica\"" -#: access/transam/xlogfuncs.c:253 +#: access/transam/xlogfuncs.c:247 #, c-format msgid "WAL level not sufficient for creating a restore point" msgstr "Обраний рівень WAL не достатній для створення точки відновлення" -#: access/transam/xlogfuncs.c:261 +#: access/transam/xlogfuncs.c:255 #, c-format msgid "value too long for restore point (maximum %d characters)" msgstr "значення для точки відновлення перевищує межу (%d симв.)" -#: access/transam/xlogfuncs.c:496 +#: access/transam/xlogfuncs.c:486 #, c-format msgid "invalid WAL file name \"%s\"" msgstr "неприпустиме ім'я файлу WAL \"%s\"" -#: access/transam/xlogfuncs.c:532 access/transam/xlogfuncs.c:562 -#: access/transam/xlogfuncs.c:586 access/transam/xlogfuncs.c:609 -#: access/transam/xlogfuncs.c:689 +#: access/transam/xlogfuncs.c:522 access/transam/xlogfuncs.c:552 +#: access/transam/xlogfuncs.c:576 access/transam/xlogfuncs.c:599 +#: access/transam/xlogfuncs.c:679 #, c-format msgid "recovery is not in progress" msgstr "відновлення не виконується" -#: access/transam/xlogfuncs.c:533 access/transam/xlogfuncs.c:563 -#: access/transam/xlogfuncs.c:587 access/transam/xlogfuncs.c:610 -#: access/transam/xlogfuncs.c:690 +#: access/transam/xlogfuncs.c:523 access/transam/xlogfuncs.c:553 +#: access/transam/xlogfuncs.c:577 access/transam/xlogfuncs.c:600 +#: access/transam/xlogfuncs.c:680 #, c-format msgid "Recovery control functions can only be executed during recovery." msgstr "Функції управління відновленням можна використовувати тільки під час відновлення." -#: access/transam/xlogfuncs.c:538 access/transam/xlogfuncs.c:568 +#: access/transam/xlogfuncs.c:528 access/transam/xlogfuncs.c:558 #, c-format msgid "standby promotion is ongoing" msgstr "просування в режимі очікування триває" -#: access/transam/xlogfuncs.c:539 access/transam/xlogfuncs.c:569 +#: access/transam/xlogfuncs.c:529 access/transam/xlogfuncs.c:559 #, c-format msgid "%s cannot be executed after promotion is triggered." msgstr "%s не може бути виконаний після того як підвищення запущено." -#: access/transam/xlogfuncs.c:695 +#: access/transam/xlogfuncs.c:685 #, c-format msgid "\"wait_seconds\" must not be negative or zero" msgstr "\"wait_seconds\" не має бути від'ємним чи нулем" -#: access/transam/xlogfuncs.c:715 storage/ipc/signalfuncs.c:265 +#: access/transam/xlogfuncs.c:707 storage/ipc/signalfuncs.c:265 #, c-format msgid "failed to send signal to postmaster: %m" msgstr "надіслати сигнал процесу postmaster не вдалося: %m" -#: access/transam/xlogfuncs.c:751 +#: access/transam/xlogfuncs.c:739 libpq/be-secure.c:237 libpq/be-secure.c:346 +#, c-format +msgid "terminating connection due to unexpected postmaster exit" +msgstr "завершення підключення через неочікуване закриття головного процесу" + +#: access/transam/xlogfuncs.c:740 +#, c-format +msgid "while waiting on promotion" +msgstr "в очікуванні на підвищення" + +#: access/transam/xlogfuncs.c:744 #, c-format msgid "server did not promote within %d second" msgid_plural "server did not promote within %d seconds" @@ -2804,704 +3034,717 @@ msgstr[1] "сервер не підвищувався протягом %d сек msgstr[2] "сервер не підвищувався протягом %d секунд" msgstr[3] "сервер не підвищувався протягом %d секунд" -#: access/transam/xlogprefetcher.c:1092 +#: access/transam/xlogprefetcher.c:1088 #, c-format -msgid "recovery_prefetch is not supported on platforms that lack posix_fadvise()." -msgstr "recovery_prefetch не підтримується на платформах, у яких відсутня posix_fadvise()." +msgid "\"recovery_prefetch\" is not supported on platforms that lack posix_fadvise()." +msgstr "\"recovery_prefetch\" не підтримується на платформах, у яких відсутня posix_fadvise()." -#: access/transam/xlogreader.c:621 +#: access/transam/xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "неприпустиме зміщення запису в %X/%X: очікувалось хоча б %u, отримано %u" -#: access/transam/xlogreader.c:630 +#: access/transam/xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "по зсуву %X/%X запитано продовження запису" -#: access/transam/xlogreader.c:671 access/transam/xlogreader.c:1136 +#: access/transam/xlogreader.c:669 access/transam/xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "неприпустима довжина запису %X/%X: очікувалась мінімум %u, отримано %u" -#: access/transam/xlogreader.c:760 +#: access/transam/xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "немає прапорця contrecord в позиції %X/%X" -#: access/transam/xlogreader.c:773 +#: access/transam/xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неприпустима довжина contrecord %u (очікувалось %lld) на %X/%X" -#: access/transam/xlogreader.c:1144 +#: access/transam/xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "невірний ID менеджера ресурсів %u в %X/%X" -#: access/transam/xlogreader.c:1157 access/transam/xlogreader.c:1173 +#: access/transam/xlogreader.c:1155 access/transam/xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запис з неправильним попереднім посиланням %X/%X на %X/%X" -#: access/transam/xlogreader.c:1211 +#: access/transam/xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "некоректна контрольна сума даних менеджера ресурсів у запису по зсуву %X/%X" -#: access/transam/xlogreader.c:1245 +#: access/transam/xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірне магічне число %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: access/transam/xlogreader.c:1260 access/transam/xlogreader.c:1302 +#: access/transam/xlogreader.c:1258 access/transam/xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірні інформаційні біти %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: access/transam/xlogreader.c:1276 +#: access/transam/xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL файл належить іншій системі баз даних: ідентифікатор системи баз даних де міститься WAL файл - %llu, а ідентифікатор системи баз даних pg_control - %llu" -#: access/transam/xlogreader.c:1284 +#: access/transam/xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний розмір сегменту в заголовку сторінки" -#: access/transam/xlogreader.c:1290 +#: access/transam/xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний XLOG_BLCKSZ в заголовку сторінки" -#: access/transam/xlogreader.c:1322 +#: access/transam/xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неочікуваний pageaddr %X/%X у сегменті WAL %s, LSN %X/%X, зміщення %u" -#: access/transam/xlogreader.c:1348 +#: access/transam/xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "порушення послідовності ID лінії часу %u (після %u) у сегменті WAL %s, LSN %X/%X, зсув %u" -#: access/transam/xlogreader.c:1754 +#: access/transam/xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ідентифікатор блока %u out-of-order в позиції %X/%X" -#: access/transam/xlogreader.c:1778 +#: access/transam/xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але немає даних в позиції %X/%X" -#: access/transam/xlogreader.c:1785 +#: access/transam/xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але довжина даних дорівнює %u в позиції %X/%X" -#: access/transam/xlogreader.c:1821 +#: access/transam/xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE встановлений, але для пропуску задані: зсув %u, довжина %u, при довжині образу блока %u в позиції %X/%X" -#: access/transam/xlogreader.c:1837 +#: access/transam/xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE не встановлений, але для пропуску задані: зсув %u, довжина %u в позиції %X/%X" -#: access/transam/xlogreader.c:1851 +#: access/transam/xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED встановлений, але довжина образу блока дорівнює %u в позиції %X/%X" -#: access/transam/xlogreader.c:1866 +#: access/transam/xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ні BKPIMAGE_HAS_HOLE, ні BKPIMAGE_COMPRESSED не встановлені, але довжина образу блока дорівнює %u в позиції %X/%X" -#: access/transam/xlogreader.c:1882 +#: access/transam/xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL встановлений, але попереднє значення не задано в позиції %X/%X" -#: access/transam/xlogreader.c:1894 +#: access/transam/xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "невірний ідентифікатор блоку %u в позиції %X/%X" -#: access/transam/xlogreader.c:1961 +#: access/transam/xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запис з невірною довжиною на %X/%X" -#: access/transam/xlogreader.c:1987 +#: access/transam/xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не вдалося знайти блок резервної копії з ID %d у записі WAL" -#: access/transam/xlogreader.c:2071 +#: access/transam/xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "не вдалося відновити зображення %X/%X з недійсним вказаним блоком %d" -#: access/transam/xlogreader.c:2078 +#: access/transam/xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "не вдалося відновити зображення %X/%X з недійсним станом, блок %d" -#: access/transam/xlogreader.c:2105 access/transam/xlogreader.c:2122 +#: access/transam/xlogreader.c:2100 access/transam/xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "не вдалося відновити зображення в %X/%X, стиснуте %s, не підтримується збіркою, блок %d" -#: access/transam/xlogreader.c:2131 +#: access/transam/xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "не вдалося відновити зображення %X/%X стиснуте з невідомим методом, блок %d" -#: access/transam/xlogreader.c:2139 +#: access/transam/xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не вдалося розпакувати зображення на %X/%X, блок %d" -#: access/transam/xlogrecovery.c:547 -#, c-format -msgid "entering standby mode" -msgstr "перехід у режим очікування" - -#: access/transam/xlogrecovery.c:550 -#, c-format -msgid "starting point-in-time recovery to XID %u" -msgstr "починається відновлення точки в часі до XID %u" - -#: access/transam/xlogrecovery.c:554 -#, c-format -msgid "starting point-in-time recovery to %s" -msgstr "починається відновлення точки в часі до %s" - -#: access/transam/xlogrecovery.c:558 -#, c-format -msgid "starting point-in-time recovery to \"%s\"" -msgstr "починається відновлення точки в часі до \"%s\"" - -#: access/transam/xlogrecovery.c:562 -#, c-format -msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" -msgstr "починається відновлення точки в часі до локації WAL (LSN) \"%X/%X\"" - -#: access/transam/xlogrecovery.c:566 -#, c-format -msgid "starting point-in-time recovery to earliest consistent point" -msgstr "починається відновлення даних до першої точки домовленості" - -#: access/transam/xlogrecovery.c:569 -#, c-format -msgid "starting archive recovery" -msgstr "початок відновлення архіву" - -#: access/transam/xlogrecovery.c:637 +#: access/transam/xlogrecovery.c:617 #, c-format msgid "starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u" msgstr "стартуємо відновлення резервної копії з LSN повторення %X/%X, LSN контрольної точки %X/%X, на часовій шкалі з ID %u" -#: access/transam/xlogrecovery.c:669 +#: access/transam/xlogrecovery.c:649 #, c-format -msgid "could not find redo location referenced by checkpoint record" -msgstr "не вдалося знайти положення REDO, вказане записом контрольної точки" +msgid "could not find redo location %X/%X referenced by checkpoint record at %X/%X" +msgstr "не вдалося знайти положення REDO %X/%X, вказане записом контрольної точки в %X/%X" -#: access/transam/xlogrecovery.c:670 access/transam/xlogrecovery.c:680 +#: access/transam/xlogrecovery.c:651 access/transam/xlogrecovery.c:662 #, c-format -msgid "" -"If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n" +msgid "If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n" "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n" "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup." -msgstr "" -"Якщо ви відновлюєте з резервної копії, оновіть файл \"%s/recovery.signal\" та додайте необхідні параметри відновлення.\n" -"Якщо ви не відновлюєте з резервної копії, спробуйте видалити файл \"%s/backup_label\".\n" -"Будьте обережні: видалення \"%s/backup_label\" призведе до пошкодження кластеру при відновленні з резервної копії." +msgstr "Якщо ви відновлюєтеся з резервної копії, оновіть \"%s/recovery.signal\" або \"%s/standby.signal\" і додайте необхідні параметри відновлення.\n" +"Якщо ви відновлюєте не з резервної копії, спробуйте видалити файл \"%s/backup_label\".\n" +"Будьте обережні: видалення \"%s/backup_label\" призведе до пошкодження кластера при відновленні з резервної копії." -#: access/transam/xlogrecovery.c:679 +#: access/transam/xlogrecovery.c:660 #, c-format -msgid "could not locate required checkpoint record" -msgstr "не вдалося знайти запис потрібної контрольної точки" +msgid "could not locate required checkpoint record at %X/%X" +msgstr "не вдалося знайти запис необхідної контрольної точки в %X/%X" -#: access/transam/xlogrecovery.c:708 commands/tablespace.c:670 +#: access/transam/xlogrecovery.c:690 commands/tablespace.c:664 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не вдалося створити символічне послання \"%s\": %m" -#: access/transam/xlogrecovery.c:740 access/transam/xlogrecovery.c:746 +#: access/transam/xlogrecovery.c:723 access/transam/xlogrecovery.c:729 #, c-format msgid "ignoring file \"%s\" because no file \"%s\" exists" msgstr "файл \"%s\" ігнорується, тому що файлу \"%s\" не існує" -#: access/transam/xlogrecovery.c:742 +#: access/transam/xlogrecovery.c:725 #, c-format msgid "File \"%s\" was renamed to \"%s\"." msgstr "Файл \"%s\" був перейменований на \"%s\"." -#: access/transam/xlogrecovery.c:748 +#: access/transam/xlogrecovery.c:731 #, c-format msgid "Could not rename file \"%s\" to \"%s\": %m." msgstr "Неможливо перейменувати файл \"%s\" на \"%s\": %m." -#: access/transam/xlogrecovery.c:787 +#: access/transam/xlogrecovery.c:770 #, c-format msgid "restarting backup recovery with redo LSN %X/%X" msgstr "перезапуск відновлення резервної копії на LSN %X/%X" -#: access/transam/xlogrecovery.c:812 +#: access/transam/xlogrecovery.c:795 +#, c-format +msgid "could not locate a valid checkpoint record at %X/%X" +msgstr "не вдалося знайти запис допустимої контрольної точки в %X/%X" + +#: access/transam/xlogrecovery.c:806 +#, c-format +msgid "entering standby mode" +msgstr "перехід у режим очікування" + +#: access/transam/xlogrecovery.c:809 +#, c-format +msgid "starting point-in-time recovery to XID %u" +msgstr "починається відновлення точки в часі до XID %u" + +#: access/transam/xlogrecovery.c:813 +#, c-format +msgid "starting point-in-time recovery to %s" +msgstr "починається відновлення точки в часі до %s" + +#: access/transam/xlogrecovery.c:817 +#, c-format +msgid "starting point-in-time recovery to \"%s\"" +msgstr "починається відновлення точки в часі до \"%s\"" + +#: access/transam/xlogrecovery.c:821 +#, c-format +msgid "starting point-in-time recovery to WAL location (LSN) \"%X/%X\"" +msgstr "починається відновлення точки в часі до локації WAL (LSN) \"%X/%X\"" + +#: access/transam/xlogrecovery.c:825 +#, c-format +msgid "starting point-in-time recovery to earliest consistent point" +msgstr "починається відновлення даних до першої точки домовленості" + +#: access/transam/xlogrecovery.c:828 #, c-format -msgid "could not locate a valid checkpoint record" -msgstr "не вдалося знайти запис допустимої контрольної точки" +msgid "starting archive recovery" +msgstr "початок відновлення архіву" -#: access/transam/xlogrecovery.c:836 +#: access/transam/xlogrecovery.c:849 #, c-format msgid "requested timeline %u is not a child of this server's history" msgstr "запитувана лінія часу %u не є відгалуженням історії цього серверу" -#: access/transam/xlogrecovery.c:838 +#: access/transam/xlogrecovery.c:851 #, c-format msgid "Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X." msgstr "Остання контрольна точка %X/%X на лінії часу %u, але в історії запитуваної лінії часу сервер відгалузився з цієї лінії в %X/%X." -#: access/transam/xlogrecovery.c:852 +#: access/transam/xlogrecovery.c:865 #, c-format msgid "requested timeline %u does not contain minimum recovery point %X/%X on timeline %u" msgstr "запитувана лінія часу %u не містить мінімальну точку відновлення %X/%X на лінії часу %u" -#: access/transam/xlogrecovery.c:880 +#: access/transam/xlogrecovery.c:893 #, c-format msgid "invalid next transaction ID" msgstr "невірний ID наступної транзакції" -#: access/transam/xlogrecovery.c:885 +#: access/transam/xlogrecovery.c:898 #, c-format msgid "invalid redo in checkpoint record" msgstr "невірний запис REDO в контрольній точці" -#: access/transam/xlogrecovery.c:896 +#: access/transam/xlogrecovery.c:909 #, c-format msgid "invalid redo record in shutdown checkpoint" msgstr "невірний запис REDO в контрольній точці вимкнення" -#: access/transam/xlogrecovery.c:925 +#: access/transam/xlogrecovery.c:938 #, c-format msgid "database system was not properly shut down; automatic recovery in progress" msgstr "робота системи бази даних не була завершена належним чином; відбувається автоматичне відновлення" -#: access/transam/xlogrecovery.c:929 +#: access/transam/xlogrecovery.c:942 #, c-format msgid "crash recovery starts in timeline %u and has target timeline %u" msgstr "відновлення після збою починається на лінії часу %u і має цільову лінію часу: %u" -#: access/transam/xlogrecovery.c:972 +#: access/transam/xlogrecovery.c:985 #, c-format msgid "backup_label contains data inconsistent with control file" msgstr "backup_label містить дані, які не узгоджені з файлом pg_control" -#: access/transam/xlogrecovery.c:973 +#: access/transam/xlogrecovery.c:986 #, c-format msgid "This means that the backup is corrupted and you will have to use another backup for recovery." msgstr "Це означає, що резервна копія була пошкоджена і вам доведеться використати іншу резервну копію для відновлення." -#: access/transam/xlogrecovery.c:1027 +#: access/transam/xlogrecovery.c:1040 #, c-format msgid "using recovery command file \"%s\" is not supported" msgstr "використання файлу команд відновлення \"%s\" не підтримується" -#: access/transam/xlogrecovery.c:1092 +#: access/transam/xlogrecovery.c:1105 #, c-format msgid "standby mode is not supported by single-user servers" msgstr "режим очікування не підтримується однокористувацьким сервером" -#: access/transam/xlogrecovery.c:1109 +#: access/transam/xlogrecovery.c:1122 #, c-format -msgid "specified neither primary_conninfo nor restore_command" -msgstr "не заззначено ані параметр primary_conninfo, ані параметр restore_command" +msgid "specified neither \"primary_conninfo\" nor \"restore_command\"" +msgstr "не вказано ні \"primary_conninfo\", ані \"restore_command\"" -#: access/transam/xlogrecovery.c:1110 +#: access/transam/xlogrecovery.c:1123 #, c-format msgid "The database server will regularly poll the pg_wal subdirectory to check for files placed there." msgstr "Сервер бази даних буде регулярно опитувати підкатолог pg_wal і перевіряти файли, що містяться у ньому." -#: access/transam/xlogrecovery.c:1118 +#: access/transam/xlogrecovery.c:1131 #, c-format -msgid "must specify restore_command when standby mode is not enabled" -msgstr "необхідно вказати restore_command, якщо не ввімкнено режиму очікування" +msgid "must specify \"restore_command\" when standby mode is not enabled" +msgstr "необхідно вказати \"restore_command\", якщо не ввімкнено режиму очікування" -#: access/transam/xlogrecovery.c:1156 +#: access/transam/xlogrecovery.c:1169 #, c-format msgid "recovery target timeline %u does not exist" msgstr "цільова лінія часу відновлення %u не існує" -#: access/transam/xlogrecovery.c:1239 access/transam/xlogrecovery.c:1246 -#: access/transam/xlogrecovery.c:1305 access/transam/xlogrecovery.c:1385 -#: access/transam/xlogrecovery.c:1409 +#: access/transam/xlogrecovery.c:1252 access/transam/xlogrecovery.c:1259 +#: access/transam/xlogrecovery.c:1318 access/transam/xlogrecovery.c:1406 +#: access/transam/xlogrecovery.c:1415 access/transam/xlogrecovery.c:1435 #, c-format msgid "invalid data in file \"%s\"" msgstr "невірні дані у файлі \"%s\"" -#: access/transam/xlogrecovery.c:1306 +#: access/transam/xlogrecovery.c:1319 #, c-format msgid "Timeline ID parsed is %u, but expected %u." msgstr "Проаналізовано ID часової лінії %u, очіувалося %u." -#: access/transam/xlogrecovery.c:1688 +#: access/transam/xlogrecovery.c:1330 +#, c-format +msgid "this is an incremental backup, not a data directory" +msgstr "це інкрементна резервна копія, а не каталог даних" + +#: access/transam/xlogrecovery.c:1331 +#, c-format +msgid "Use pg_combinebackup to reconstruct a valid data directory." +msgstr "Використовуйте pg_combinebackup для відновлення правильного каталогу даних." + +#: access/transam/xlogrecovery.c:1717 +#, c-format +msgid "unexpected record type found at redo point %X/%X" +msgstr "знайдено неочікуваний тип запису в точці повторення %X/%X" + +#: access/transam/xlogrecovery.c:1740 #, c-format msgid "redo starts at %X/%X" msgstr "запис REDO починається з %X/%X" -#: access/transam/xlogrecovery.c:1701 +#: access/transam/xlogrecovery.c:1753 #, c-format msgid "redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X" msgstr "запис REDO триває, минуло часу: %ld.%02d s, поточний LSN: %X/%X" -#: access/transam/xlogrecovery.c:1793 +#: access/transam/xlogrecovery.c:1843 #, c-format msgid "requested recovery stop point is before consistent recovery point" msgstr "запитувана точка відновлення передує узгодженій точці відновлення" -#: access/transam/xlogrecovery.c:1825 +#: access/transam/xlogrecovery.c:1875 #, c-format msgid "redo done at %X/%X system usage: %s" msgstr "повторно виконано через %X/%X системне використання: %s" -#: access/transam/xlogrecovery.c:1831 +#: access/transam/xlogrecovery.c:1881 #, c-format msgid "last completed transaction was at log time %s" msgstr "остання завершена транзакція була в %s" -#: access/transam/xlogrecovery.c:1840 +#: access/transam/xlogrecovery.c:1890 #, c-format msgid "redo is not required" msgstr "дані REDO не потрібні" -#: access/transam/xlogrecovery.c:1851 +#: access/transam/xlogrecovery.c:1901 #, c-format msgid "recovery ended before configured recovery target was reached" msgstr "відновлення завершилось до досягення налаштованої цілі відновлення" -#: access/transam/xlogrecovery.c:2045 +#: access/transam/xlogrecovery.c:2095 #, c-format msgid "successfully skipped missing contrecord at %X/%X, overwritten at %s" msgstr "успішно пропущений відсутній contrecord при %X/%X, перезаписано на %s" -#: access/transam/xlogrecovery.c:2112 +#: access/transam/xlogrecovery.c:2162 #, c-format msgid "unexpected directory entry \"%s\" found in %s" msgstr "знайдено неочікуваний запис каталогу \"%s\" в %s" -#: access/transam/xlogrecovery.c:2114 +#: access/transam/xlogrecovery.c:2164 #, c-format msgid "All directory entries in pg_tblspc/ should be symbolic links." msgstr "Всі записи каталогу в pg_tblspc/ повинні бути символічними посиланнями." -#: access/transam/xlogrecovery.c:2115 +#: access/transam/xlogrecovery.c:2165 #, c-format -msgid "Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete." -msgstr "Видаліть ті каталоги, або тимчасово встановіть для параметра allow_in_place_tablespaces значення ON, щоб завершити відновлення." +msgid "Remove those directories, or set \"allow_in_place_tablespaces\" to ON transiently to let recovery complete." +msgstr "Видаліть ті каталоги, або тимчасово встановіть для параметра \"allow_in_place_tablespaces\" значення ON, щоб завершити відновлення." -#: access/transam/xlogrecovery.c:2167 +#: access/transam/xlogrecovery.c:2217 #, c-format msgid "completed backup recovery with redo LSN %X/%X and end LSN %X/%X" msgstr "завершено відновлення резервної копії з LSN повторення %X/%X і LSN закінчення %X/%X" -#: access/transam/xlogrecovery.c:2197 +#: access/transam/xlogrecovery.c:2247 #, c-format msgid "consistent recovery state reached at %X/%X" msgstr "узгоджений стан відновлення досягнутий %X/%X" #. translator: %s is a WAL record description -#: access/transam/xlogrecovery.c:2235 +#: access/transam/xlogrecovery.c:2285 #, c-format msgid "WAL redo at %X/%X for %s" msgstr "запис REDO в WAL в позиції %X/%X для %s" -#: access/transam/xlogrecovery.c:2333 +#: access/transam/xlogrecovery.c:2383 #, c-format msgid "unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record" msgstr "несподіваний ID попередньої лінії часу %u (ID теперішньої лінії часу %u) в записі контрольної точки" -#: access/transam/xlogrecovery.c:2342 +#: access/transam/xlogrecovery.c:2392 #, c-format msgid "unexpected timeline ID %u (after %u) in checkpoint record" msgstr "неочікуваний ID лінії часу %u (після %u) в записі контрольної точки" -#: access/transam/xlogrecovery.c:2358 +#: access/transam/xlogrecovery.c:2408 #, c-format msgid "unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u" msgstr "неочікуваний ID лінії часу %u в записі контрольної точки, до досягнення мінімальної точки відновлення %X/%X на лінії часу %u" -#: access/transam/xlogrecovery.c:2542 access/transam/xlogrecovery.c:2818 +#: access/transam/xlogrecovery.c:2592 access/transam/xlogrecovery.c:2868 #, c-format msgid "recovery stopping after reaching consistency" msgstr "відновлення зупиняється після досягнення узгодженості" -#: access/transam/xlogrecovery.c:2563 +#: access/transam/xlogrecovery.c:2613 #, c-format msgid "recovery stopping before WAL location (LSN) \"%X/%X\"" msgstr "відновлення зупиняється перед позицією WAL (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2653 +#: access/transam/xlogrecovery.c:2703 #, c-format msgid "recovery stopping before commit of transaction %u, time %s" msgstr "відновлення припиняється до підтвердження транзакції %u, час %s" -#: access/transam/xlogrecovery.c:2660 +#: access/transam/xlogrecovery.c:2710 #, c-format msgid "recovery stopping before abort of transaction %u, time %s" msgstr "відновлення припиняється до скасування транзакції %u, час %s" -#: access/transam/xlogrecovery.c:2713 +#: access/transam/xlogrecovery.c:2763 #, c-format msgid "recovery stopping at restore point \"%s\", time %s" msgstr "відновлення припиняється в точці відновлення\"%s\", час %s" -#: access/transam/xlogrecovery.c:2731 +#: access/transam/xlogrecovery.c:2781 #, c-format msgid "recovery stopping after WAL location (LSN) \"%X/%X\"" msgstr "відновлення припиняється пісня локації WAL (LSN) \"%X/%X\"" -#: access/transam/xlogrecovery.c:2798 +#: access/transam/xlogrecovery.c:2848 #, c-format msgid "recovery stopping after commit of transaction %u, time %s" msgstr "відновлення припиняється після підтвердження транзакції %u, час %s" -#: access/transam/xlogrecovery.c:2806 +#: access/transam/xlogrecovery.c:2856 #, c-format msgid "recovery stopping after abort of transaction %u, time %s" msgstr "відновлення припиняється після скасування транзакції %u, час %s" -#: access/transam/xlogrecovery.c:2887 +#: access/transam/xlogrecovery.c:2937 #, c-format msgid "pausing at the end of recovery" msgstr "пауза в кінці відновлення" -#: access/transam/xlogrecovery.c:2888 +#: access/transam/xlogrecovery.c:2938 #, c-format msgid "Execute pg_wal_replay_resume() to promote." msgstr "Виконайте pg_wal_replay_resume() для підвищення рівня." -#: access/transam/xlogrecovery.c:2891 access/transam/xlogrecovery.c:4628 +#: access/transam/xlogrecovery.c:2941 access/transam/xlogrecovery.c:4678 #, c-format msgid "recovery has paused" msgstr "відновлення зупинено" -#: access/transam/xlogrecovery.c:2892 +#: access/transam/xlogrecovery.c:2942 #, c-format msgid "Execute pg_wal_replay_resume() to continue." msgstr "Виконайте pg_wal_replay_resume(), щоб продовжити." -#: access/transam/xlogrecovery.c:3155 +#: access/transam/xlogrecovery.c:3205 #, c-format msgid "unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u" msgstr "неочікуваний ID лінії часу %u в сегменті WAL %s, LSN %X/%X, offset %u" -#: access/transam/xlogrecovery.c:3363 +#: access/transam/xlogrecovery.c:3413 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: %m" msgstr "не вдалося прочитати сегмент журналу %s, LSN %X/%X, зсув %u: %m" -#: access/transam/xlogrecovery.c:3370 +#: access/transam/xlogrecovery.c:3420 #, c-format msgid "could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu" msgstr "не вдалося прочитати сегмент WAL %s, LSN %X/%X, зсув %u: прочитано %d з %zu" -#: access/transam/xlogrecovery.c:4010 +#: access/transam/xlogrecovery.c:4060 #, c-format msgid "invalid checkpoint location" msgstr "невірне розташування контрольної точки" -#: access/transam/xlogrecovery.c:4020 +#: access/transam/xlogrecovery.c:4070 #, c-format msgid "invalid checkpoint record" msgstr "невірний запис контрольної точки" -#: access/transam/xlogrecovery.c:4026 +#: access/transam/xlogrecovery.c:4076 #, c-format msgid "invalid resource manager ID in checkpoint record" msgstr "невірний ID менеджера ресурсів в записі контрольної точки" -#: access/transam/xlogrecovery.c:4034 +#: access/transam/xlogrecovery.c:4084 #, c-format msgid "invalid xl_info in checkpoint record" msgstr "невірний xl_info у записі контрольної точки" -#: access/transam/xlogrecovery.c:4040 +#: access/transam/xlogrecovery.c:4090 #, c-format msgid "invalid length of checkpoint record" msgstr "невірна довжина запису контрольної точки" -#: access/transam/xlogrecovery.c:4094 +#: access/transam/xlogrecovery.c:4144 #, c-format msgid "new timeline %u is not a child of database system timeline %u" msgstr "нова лінія часу %u не є дочірньою для лінії часу системи бази даних %u" -#: access/transam/xlogrecovery.c:4108 +#: access/transam/xlogrecovery.c:4158 #, c-format msgid "new timeline %u forked off current database system timeline %u before current recovery point %X/%X" msgstr "нова лінія часу %u відгалузилась від поточної лінії часу бази даних %u до поточної точки відновлення %X/%X" -#: access/transam/xlogrecovery.c:4127 +#: access/transam/xlogrecovery.c:4177 #, c-format msgid "new target timeline is %u" msgstr "нова цільова лінія часу %u" -#: access/transam/xlogrecovery.c:4330 +#: access/transam/xlogrecovery.c:4380 #, c-format msgid "WAL receiver process shutdown requested" msgstr "Запит на вимкнення процесу приймача WAL" -#: access/transam/xlogrecovery.c:4390 +#: access/transam/xlogrecovery.c:4440 #, c-format msgid "received promote request" msgstr "отримано запит підвищення статусу" -#: access/transam/xlogrecovery.c:4619 +#: access/transam/xlogrecovery.c:4669 #, c-format msgid "hot standby is not possible because of insufficient parameter settings" msgstr "hot standby неможливий через недостатнє налаштування параметрів" -#: access/transam/xlogrecovery.c:4620 access/transam/xlogrecovery.c:4647 -#: access/transam/xlogrecovery.c:4677 +#: access/transam/xlogrecovery.c:4670 access/transam/xlogrecovery.c:4697 +#: access/transam/xlogrecovery.c:4727 #, c-format msgid "%s = %d is a lower setting than on the primary server, where its value was %d." msgstr "%s = %d є нижчим параметром, ніж на основному сервері, де його значення було %d." -#: access/transam/xlogrecovery.c:4629 +#: access/transam/xlogrecovery.c:4679 #, c-format msgid "If recovery is unpaused, the server will shut down." msgstr "Якщо відновлення не буде зупинено, сервер завершить роботу." -#: access/transam/xlogrecovery.c:4630 +#: access/transam/xlogrecovery.c:4680 #, c-format msgid "You can then restart the server after making the necessary configuration changes." msgstr "Після здійснення необхідних змін у конфігурації, ви можете перезапустити сервер." -#: access/transam/xlogrecovery.c:4641 +#: access/transam/xlogrecovery.c:4691 #, c-format msgid "promotion is not possible because of insufficient parameter settings" msgstr "підвищення неможливе через недостатнє налаштування параметрів" -#: access/transam/xlogrecovery.c:4651 +#: access/transam/xlogrecovery.c:4701 #, c-format msgid "Restart the server after making the necessary configuration changes." msgstr "Перезапустити сервер після здійснення необхідних змін у конфігурації." -#: access/transam/xlogrecovery.c:4675 +#: access/transam/xlogrecovery.c:4725 #, c-format msgid "recovery aborted because of insufficient parameter settings" msgstr "відновлення перервано через недостатнє налаштування параметрів" -#: access/transam/xlogrecovery.c:4681 +#: access/transam/xlogrecovery.c:4731 #, c-format msgid "You can restart the server after making the necessary configuration changes." msgstr "Ви можете перезапустити сервер, після здійснення необхідних змін у конфігурації." -#: access/transam/xlogrecovery.c:4723 +#: access/transam/xlogrecovery.c:4773 #, c-format msgid "multiple recovery targets specified" msgstr "вказано декілька цілей відновлення" -#: access/transam/xlogrecovery.c:4724 +#: access/transam/xlogrecovery.c:4774 #, c-format -msgid "At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set." -msgstr "Максимум один із recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid може бути встановлений." +msgid "At most one of \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" may be set." +msgstr "Максимум один із \"recovery_target\", \"recovery_target_lsn\", \"recovery_target_name\", \"recovery_target_time\", \"recovery_target_xid\" може бути встановлений." -#: access/transam/xlogrecovery.c:4735 +#: access/transam/xlogrecovery.c:4785 #, c-format msgid "The only allowed value is \"immediate\"." msgstr "Єдиним дозволеним значенням є \"immediate\"." -#: access/transam/xlogrecovery.c:4887 utils/adt/timestamp.c:186 -#: utils/adt/timestamp.c:439 +#: access/transam/xlogrecovery.c:4937 utils/adt/timestamp.c:202 +#: utils/adt/timestamp.c:455 #, c-format msgid "timestamp out of range: \"%s\"" msgstr "позначка часу поза діапазоном: \"%s\"" -#: access/transam/xlogrecovery.c:4932 +#: access/transam/xlogrecovery.c:4982 #, c-format -msgid "recovery_target_timeline is not a valid number." -msgstr "recovery_target_timeline не є допустимим числом." +msgid "\"recovery_target_timeline\" is not a valid number." +msgstr "\"recovery_target_timeline\" не є допустимим числом." -#: access/transam/xlogutils.c:1039 +#: access/transam/xlogutils.c:1032 #, c-format msgid "could not read from WAL segment %s, offset %d: %m" msgstr "не вдалося прочитати сегмент WAL %s, зсув %d: %m" -#: access/transam/xlogutils.c:1046 +#: access/transam/xlogutils.c:1039 #, c-format msgid "could not read from WAL segment %s, offset %d: read %d of %d" msgstr "не вдалося прочитати сегмент WAL %s, зсув %d: прочитано %d з %d" -#: archive/shell_archive.c:96 +#: archive/shell_archive.c:98 #, c-format msgid "archive command failed with exit code %d" msgstr "команда архівації завершилась помилкой з кодом %d" -#: archive/shell_archive.c:98 archive/shell_archive.c:108 -#: archive/shell_archive.c:114 archive/shell_archive.c:123 +#: archive/shell_archive.c:100 archive/shell_archive.c:110 +#: archive/shell_archive.c:116 archive/shell_archive.c:125 #, c-format msgid "The failed archive command was: %s" msgstr "Команда архівації з помилкою: %s" -#: archive/shell_archive.c:105 +#: archive/shell_archive.c:107 #, c-format msgid "archive command was terminated by exception 0x%X" msgstr "команда архівації була перервана винятком 0x%X" -#: archive/shell_archive.c:107 postmaster/postmaster.c:3678 +#: archive/shell_archive.c:109 postmaster/postmaster.c:3094 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "Опис цього Шістнадцяткового значення дивіться у включаємому C-файлі \"ntstatus.h\"." -#: archive/shell_archive.c:112 +#: archive/shell_archive.c:114 #, c-format msgid "archive command was terminated by signal %d: %s" msgstr "команда архівації була перервана сигналом %d: %s" -#: archive/shell_archive.c:121 +#: archive/shell_archive.c:123 #, c-format msgid "archive command exited with unrecognized status %d" msgstr "команда архівації завершена з нерозпізнаним статусом %d" -#: backup/backup_manifest.c:253 +#: backup/backup_manifest.c:254 #, c-format msgid "expected end timeline %u but found timeline %u" msgstr "очікувався кінець часової шкали %u але знайдено часову шкалу %u" -#: backup/backup_manifest.c:277 +#: backup/backup_manifest.c:278 #, c-format msgid "expected start timeline %u but found timeline %u" msgstr "очікувався початок часової шкали %u але знайдено часову шкалу %u" -#: backup/backup_manifest.c:304 +#: backup/backup_manifest.c:305 #, c-format msgid "start timeline %u not found in history of timeline %u" msgstr "початок часової шкали %u не знайдено в історії часової шкали %u" -#: backup/backup_manifest.c:355 +#: backup/backup_manifest.c:356 #, c-format msgid "could not rewind temporary file" msgstr "не вдалося перемотати назад тимчасовий файл" -#: backup/basebackup.c:470 +#: backup/basebackup.c:479 #, c-format msgid "could not find any WAL files" msgstr "не вдалося знайти ні одного файла WAL" -#: backup/basebackup.c:485 backup/basebackup.c:500 backup/basebackup.c:509 +#: backup/basebackup.c:494 backup/basebackup.c:509 backup/basebackup.c:518 #, c-format msgid "could not find WAL file \"%s\"" msgstr "не вдалося знайти файл WAL \"%s\"" -#: backup/basebackup.c:551 backup/basebackup.c:576 +#: backup/basebackup.c:560 backup/basebackup.c:585 #, c-format msgid "unexpected WAL file size \"%s\"" msgstr "неочікуаний розмір файлу WAL \"%s\"" -#: backup/basebackup.c:646 +#: backup/basebackup.c:656 #, c-format msgid "%lld total checksum verification failure" msgid_plural "%lld total checksum verification failures" @@ -3510,106 +3753,96 @@ msgstr[1] "всього помилок перевірки контрольних msgstr[2] "всього помилок перевірки контрольних сум: %lld" msgstr[3] "всього помилок перевірки контрольних сум: %lld" -#: backup/basebackup.c:653 +#: backup/basebackup.c:663 #, c-format msgid "checksum verification failure during base backup" msgstr "під час базового резервного копіювання виявлено неполадки контрольних сум" -#: backup/basebackup.c:722 backup/basebackup.c:731 backup/basebackup.c:742 -#: backup/basebackup.c:759 backup/basebackup.c:768 backup/basebackup.c:779 -#: backup/basebackup.c:796 backup/basebackup.c:805 backup/basebackup.c:817 -#: backup/basebackup.c:841 backup/basebackup.c:855 backup/basebackup.c:866 -#: backup/basebackup.c:877 backup/basebackup.c:890 +#: backup/basebackup.c:733 backup/basebackup.c:742 backup/basebackup.c:753 +#: backup/basebackup.c:770 backup/basebackup.c:779 backup/basebackup.c:788 +#: backup/basebackup.c:803 backup/basebackup.c:820 backup/basebackup.c:829 +#: backup/basebackup.c:841 backup/basebackup.c:865 backup/basebackup.c:879 +#: backup/basebackup.c:890 backup/basebackup.c:901 backup/basebackup.c:914 #, c-format msgid "duplicate option \"%s\"" msgstr "повторюваний параметр \"%s\"" -#: backup/basebackup.c:750 +#: backup/basebackup.c:761 #, c-format msgid "unrecognized checkpoint type: \"%s\"" msgstr "нерозпізнаний тип контрольної точки: \"%s\"" -#: backup/basebackup.c:785 +#: backup/basebackup.c:793 +#, c-format +msgid "incremental backups cannot be taken unless WAL summarization is enabled" +msgstr "інкрементні резервні копії не можна створювати, якщо не ввімкнено підсумовування WAL" + +#: backup/basebackup.c:809 #, c-format msgid "%d is outside the valid range for parameter \"%s\" (%d .. %d)" msgstr "%d за припустимим діапазномо для параметру \"%s\" (%d .. %d)" -#: backup/basebackup.c:830 +#: backup/basebackup.c:854 #, c-format msgid "unrecognized manifest option: \"%s\"" msgstr "нерозпізнаний параметр маніфесту: \"%s\"" -#: backup/basebackup.c:846 -#, c-format -msgid "unrecognized checksum algorithm: \"%s\"" -msgstr "нерозпізнаний алгоритм контрольної суми: \"%s\"" - -#: backup/basebackup.c:881 +#: backup/basebackup.c:905 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "нерозпізнаний алгоритм стискання: \"%s\"" -#: backup/basebackup.c:897 +#: backup/basebackup.c:921 #, c-format msgid "unrecognized base backup option: \"%s\"" msgstr "нерозпізнаний параметр базової резервної копії: \"%s\"" -#: backup/basebackup.c:908 +#: backup/basebackup.c:932 #, c-format msgid "manifest checksums require a backup manifest" msgstr "контрольні суми маніфесту потребують резервного копіювання маніфесту" -#: backup/basebackup.c:917 +#: backup/basebackup.c:941 #, c-format msgid "target detail cannot be used without target" msgstr "елемент цілі не можна використовувати без цілі" -#: backup/basebackup.c:926 backup/basebackup_target.c:218 +#: backup/basebackup.c:950 backup/basebackup_target.c:218 #, c-format msgid "target \"%s\" does not accept a target detail" msgstr "ціль \"%s\" не приймає елемент цілі" -#: backup/basebackup.c:937 +#: backup/basebackup.c:961 #, c-format msgid "compression detail cannot be specified unless compression is enabled" msgstr "деталі стиснення не можуть бути вказані, якщо не увімкнено стиснення" -#: backup/basebackup.c:950 +#: backup/basebackup.c:974 #, c-format msgid "invalid compression specification: %s" msgstr "неприпустима специфікація стискання: %s" -#: backup/basebackup.c:1116 backup/basebackup.c:1294 +#: backup/basebackup.c:1024 +#, c-format +msgid "must UPLOAD_MANIFEST before performing an incremental BASE_BACKUP" +msgstr "повинен UPLOAD_MANIFEST перед виконанням інкрементного BASE_BACKUP" + +#: backup/basebackup.c:1157 backup/basebackup.c:1358 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "не вдалося отримати інформацію про файл або каталог \"%s\": %m" -#: backup/basebackup.c:1430 +#: backup/basebackup.c:1544 #, c-format msgid "skipping special file \"%s\"" msgstr "спеціальний файл \"%s\" пропускається" -#: backup/basebackup.c:1542 -#, c-format -msgid "invalid segment number %d in file \"%s\"" -msgstr "неприпустимий номер сегменту %d в файлі \"%s\"" - -#: backup/basebackup.c:1574 +#: backup/basebackup.c:1751 #, c-format msgid "could not verify checksum in file \"%s\", block %u: read buffer size %d and page size %d differ" msgstr "не вдалося перевірити контрольну суму у файлі \"%s\", блок %u: розмір прочитаного буфера %d і розмір прочитаної сторінки %d відрізняються" -#: backup/basebackup.c:1658 -#, c-format -msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" -msgstr "помилка перевірки контрольної суми у файлі \"%s\", блок %u: обчислено %X, але очікувалось %X" - -#: backup/basebackup.c:1665 -#, c-format -msgid "further checksum verification failures in file \"%s\" will not be reported" -msgstr "про подальші помилки під час перевірки контрольної суми в файлі \"%s\" повідомлятись не буде" - -#: backup/basebackup.c:1721 +#: backup/basebackup.c:1813 #, c-format msgid "file \"%s\" has a total of %d checksum verification failure" msgid_plural "file \"%s\" has a total of %d checksum verification failures" @@ -3618,16 +3851,31 @@ msgstr[1] "файл \"%s\" має загальну кількість помил msgstr[2] "файл \"%s\" має загальну кількість помилок перевірки контрольної суми: %d" msgstr[3] "файл \"%s\" має загальну кількість помилок перевірки контрольної суми: %d" -#: backup/basebackup.c:1767 +#: backup/basebackup.c:1917 +#, c-format +msgid "checksum verification failed in file \"%s\", block %u: calculated %X but expected %X" +msgstr "помилка перевірки контрольної суми у файлі \"%s\", блок %u: обчислено %X, але очікувалось %X" + +#: backup/basebackup.c:1924 +#, c-format +msgid "further checksum verification failures in file \"%s\" will not be reported" +msgstr "про подальші помилки під час перевірки контрольної суми в файлі \"%s\" повідомлятись не буде" + +#: backup/basebackup.c:2048 #, c-format msgid "file name too long for tar format: \"%s\"" msgstr "ім'я файлу занадто довге для tar формату: \"%s\"" -#: backup/basebackup.c:1772 +#: backup/basebackup.c:2053 #, c-format msgid "symbolic link target too long for tar format: file name \"%s\", target \"%s\"" msgstr "мета символьного посилання занадто довга для формату tar: ім'я файлу \"%s\", мета \"%s\"" +#: backup/basebackup.c:2127 +#, c-format +msgid "could not read file \"%s\": read %zd of %zu" +msgstr "не вдалося прочитати файл \"%s\": читання %zd з %zu" + #: backup/basebackup_gzip.c:67 #, c-format msgid "gzip compression is not supported by this build" @@ -3638,53 +3886,114 @@ msgstr "стискання gzip не підтримується цією збі msgid "could not initialize compression library" msgstr "не вдалося ініціалізувати бібліотеку стискання" -#: backup/basebackup_lz4.c:67 +#: backup/basebackup_incremental.c:294 #, c-format -msgid "lz4 compression is not supported by this build" -msgstr "стискання lz4 не підтримується цією збіркою" +msgid "manifest contains no required WAL ranges" +msgstr "маніфест не містить необхідних діапазонів WAL" -#: backup/basebackup_server.c:75 +#: backup/basebackup_incremental.c:349 #, c-format -msgid "permission denied to create backup stored on server" -msgstr "немає прав на створення резервної копії, збереженої на сервері" +msgid "timeline %u found in manifest, but not in this server's history" +msgstr "часову шкалу %u знайдено в маніфесті, але не в історії цього сервера" -#: backup/basebackup_server.c:76 +#: backup/basebackup_incremental.c:414 #, c-format -msgid "Only roles with privileges of the \"%s\" role may create a backup stored on the server." -msgstr "Тільки ролі з привілеями ролі \"%s\" можуть створювати резервні копії, що зберігаються на сервері." +msgid "manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "маніфест вимагає WAL з початкової шкали %u, починаючи з %X/%X, але ця шкала починається з %X/%X" -#: backup/basebackup_server.c:91 +#: backup/basebackup_incremental.c:424 #, c-format -msgid "relative path not allowed for backup stored on server" +msgid "manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X" +msgstr "маніфест вимагає WAL зі шкали продовження %u, починаючи з %X/%X, але ця шкала починається з %X/%X" + +#: backup/basebackup_incremental.c:435 +#, c-format +msgid "manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X" +msgstr "маніфест вимагає WAL з кінцевої шкали часу %u, що закінчується на %X/%X, але ця резервна копія починається з %X/%X" + +#: backup/basebackup_incremental.c:439 +#, c-format +msgid "This can happen for incremental backups on a standby if there was little activity since the previous backup." +msgstr "Це може статися з інкрементними резервними копіями на резервному сервері, якщо було замало активності з минулої резервної копії." + +#: backup/basebackup_incremental.c:446 +#, c-format +msgid "manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X" +msgstr "маніфест вимагає WAL з не фінальної лінійки %u, що закінчується на %X/%X, але цей сервер перемкнув лінійки на %X/%X" + +#: backup/basebackup_incremental.c:527 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist" +msgstr "Зведення WAL потрібні на часовій шкалі %u від %X/%X до %X/%X, але зведень для цієї шкали та діапазону LSN не існує" + +#: backup/basebackup_incremental.c:534 +#, c-format +msgid "WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete" +msgstr "Зведення WAL потрібні на часовій шкалі %u від %X/%X до %X/%X, але зведення для цієї часової шкали та діапазону LSN є неповними" + +#: backup/basebackup_incremental.c:538 +#, c-format +msgid "The first unsummarized LSN in this range is %X/%X." +msgstr "Перший не підсумований LSN у цьому діапазоні - %X/%X." + +#: backup/basebackup_incremental.c:938 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "маніфест резервного копіювання версії 1 не підтримує інкреметного резервного копіювання" + +#: backup/basebackup_incremental.c:956 +#, c-format +msgid "system identifier in backup manifest is %llu, but database system identifier is %llu" +msgstr "системний ідентифікатор в маніфесті резервного копіювання %llu, але ідентифікатор системи бази даних є %llu" + +#: backup/basebackup_lz4.c:67 +#, c-format +msgid "lz4 compression is not supported by this build" +msgstr "стискання lz4 не підтримується цією збіркою" + +#: backup/basebackup_server.c:73 +#, c-format +msgid "permission denied to create backup stored on server" +msgstr "немає прав на створення резервної копії, збереженої на сервері" + +#: backup/basebackup_server.c:74 +#, c-format +msgid "Only roles with privileges of the \"%s\" role may create a backup stored on the server." +msgstr "Тільки ролі з привілеями ролі \"%s\" можуть створювати резервні копії, що зберігаються на сервері." + +#: backup/basebackup_server.c:89 +#, c-format +msgid "relative path not allowed for backup stored on server" msgstr "відносний шлях не дозволений для резервного копіювання збереженого на сервері" -#: backup/basebackup_server.c:104 commands/dbcommands.c:478 -#: commands/tablespace.c:163 commands/tablespace.c:179 -#: commands/tablespace.c:599 commands/tablespace.c:644 replication/slot.c:1704 +#: backup/basebackup_server.c:102 commands/dbcommands.c:477 +#: commands/tablespace.c:157 commands/tablespace.c:173 +#: commands/tablespace.c:593 commands/tablespace.c:638 replication/slot.c:1986 #: storage/file/copydir.c:47 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не вдалося створити каталог \"%s\": %m" -#: backup/basebackup_server.c:117 +#: backup/basebackup_server.c:115 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" існує, але він не порожній" -#: backup/basebackup_server.c:125 utils/init/postinit.c:1164 +#: backup/basebackup_server.c:123 utils/init/postinit.c:1177 #, c-format msgid "could not access directory \"%s\": %m" msgstr "немає доступу до каталогу \"%s\": %m" -#: backup/basebackup_server.c:177 backup/basebackup_server.c:184 -#: backup/basebackup_server.c:270 backup/basebackup_server.c:277 -#: storage/smgr/md.c:504 storage/smgr/md.c:511 storage/smgr/md.c:593 -#: storage/smgr/md.c:615 storage/smgr/md.c:865 +#: backup/basebackup_server.c:175 backup/basebackup_server.c:182 +#: backup/basebackup_server.c:268 backup/basebackup_server.c:275 +#: backup/walsummary.c:312 storage/smgr/md.c:502 storage/smgr/md.c:509 +#: storage/smgr/md.c:591 storage/smgr/md.c:613 storage/smgr/md.c:999 #, c-format msgid "Check free disk space." msgstr "Перевірьте вільний дисковий простір." -#: backup/basebackup_server.c:181 backup/basebackup_server.c:274 +#: backup/basebackup_server.c:179 backup/basebackup_server.c:272 +#: backup/walsummary.c:309 #, c-format msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" msgstr "не вдалося записати файл \"%s\": записано лише %d з %d байтів зі зсувом %u" @@ -3714,645 +4023,656 @@ msgstr "не вдалося встановити кількість процес msgid "could not enable long-distance mode: %s" msgstr "не вдалося включити режим довгої відстані: %s" -#: bootstrap/bootstrap.c:243 postmaster/postmaster.c:721 tcop/postgres.c:3819 +#: backup/walsummaryfuncs.c:95 +#, c-format +msgid "invalid timeline %lld" +msgstr "неприпустима часова шкала %lld" + +#: bootstrap/bootstrap.c:239 postmaster/postmaster.c:623 tcop/postgres.c:3946 #, c-format msgid "--%s requires a value" msgstr "--%s необхідне значення" -#: bootstrap/bootstrap.c:248 postmaster/postmaster.c:726 tcop/postgres.c:3824 +#: bootstrap/bootstrap.c:244 postmaster/postmaster.c:628 tcop/postgres.c:3951 #, c-format msgid "-c %s requires a value" msgstr "-c %s необхідне значення" -#: bootstrap/bootstrap.c:289 -#, c-format -msgid "-X requires a power of two value between 1 MB and 1 GB" -msgstr "для -X необхідне число, яке дорівнює ступеню 2 в інтервалі від 1 МБ до 1 ГБ" - -#: bootstrap/bootstrap.c:295 postmaster/postmaster.c:844 -#: postmaster/postmaster.c:857 +#: bootstrap/bootstrap.c:282 postmaster/postmaster.c:746 +#: postmaster/postmaster.c:759 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Спробуйте \"%s --help\" для додаткової інформації.\n" -#: bootstrap/bootstrap.c:304 +#: bootstrap/bootstrap.c:291 #, c-format msgid "%s: invalid command-line arguments\n" msgstr "%s: невірні аргументи командного рядка\n" -#: catalog/aclchk.c:201 +#: catalog/aclchk.c:210 #, c-format msgid "grant options can only be granted to roles" msgstr "право надання прав можна надавати тільки ролям" -#: catalog/aclchk.c:323 +#: catalog/aclchk.c:332 #, c-format msgid "no privileges were granted for column \"%s\" of relation \"%s\"" msgstr "для стовпця \"%s\" відношення \"%s\" не призначено ніяких прав" -#: catalog/aclchk.c:328 +#: catalog/aclchk.c:337 #, c-format msgid "no privileges were granted for \"%s\"" msgstr "для \"%s\" не призначено ніяких прав" -#: catalog/aclchk.c:336 +#: catalog/aclchk.c:345 #, c-format msgid "not all privileges were granted for column \"%s\" of relation \"%s\"" msgstr "для стовпця \"%s\" відношення \"%s\" призначено не всі права" -#: catalog/aclchk.c:341 +#: catalog/aclchk.c:350 #, c-format msgid "not all privileges were granted for \"%s\"" msgstr "для \"%s\" призначено не всі права" -#: catalog/aclchk.c:352 +#: catalog/aclchk.c:361 #, c-format msgid "no privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "для стовпця \"%s\" відношення \"%s\" жодні права не можуть бути відкликані" -#: catalog/aclchk.c:357 +#: catalog/aclchk.c:366 #, c-format msgid "no privileges could be revoked for \"%s\"" msgstr "для \"%s\" жодні права не можуть бути відкликані" -#: catalog/aclchk.c:365 +#: catalog/aclchk.c:374 #, c-format msgid "not all privileges could be revoked for column \"%s\" of relation \"%s\"" msgstr "для стовпця \"%s\" відношення \"%s\" не всі права можуть бути відкликані" -#: catalog/aclchk.c:370 +#: catalog/aclchk.c:379 #, c-format msgid "not all privileges could be revoked for \"%s\"" msgstr "для \"%s\" не всі права можуть бути відкликані" -#: catalog/aclchk.c:402 +#: catalog/aclchk.c:411 #, c-format msgid "grantor must be current user" msgstr "грантодавець повинен бути поточним користувачем" -#: catalog/aclchk.c:470 catalog/aclchk.c:1045 +#: catalog/aclchk.c:479 catalog/aclchk.c:1054 #, c-format msgid "invalid privilege type %s for relation" msgstr "недійсний тип права %s для відношення" -#: catalog/aclchk.c:474 catalog/aclchk.c:1049 +#: catalog/aclchk.c:483 catalog/aclchk.c:1058 #, c-format msgid "invalid privilege type %s for sequence" msgstr "невірний тип права %s для послідовності" -#: catalog/aclchk.c:478 +#: catalog/aclchk.c:487 #, c-format msgid "invalid privilege type %s for database" msgstr "недійсний тип права %s для бази даних" -#: catalog/aclchk.c:482 +#: catalog/aclchk.c:491 #, c-format msgid "invalid privilege type %s for domain" msgstr "недійсний тип права %s для домену" -#: catalog/aclchk.c:486 catalog/aclchk.c:1053 +#: catalog/aclchk.c:495 catalog/aclchk.c:1062 #, c-format msgid "invalid privilege type %s for function" msgstr "недійсний тип права %s для функції" -#: catalog/aclchk.c:490 +#: catalog/aclchk.c:499 #, c-format msgid "invalid privilege type %s for language" msgstr "недійсний тип права %s для мови" -#: catalog/aclchk.c:494 +#: catalog/aclchk.c:503 #, c-format msgid "invalid privilege type %s for large object" msgstr "недійсний тип права %s для великого об'єкту" -#: catalog/aclchk.c:498 catalog/aclchk.c:1069 +#: catalog/aclchk.c:507 catalog/aclchk.c:1078 #, c-format msgid "invalid privilege type %s for schema" msgstr "недійсний тип привілеїв %s для схеми" -#: catalog/aclchk.c:502 catalog/aclchk.c:1057 +#: catalog/aclchk.c:511 catalog/aclchk.c:1066 #, c-format msgid "invalid privilege type %s for procedure" msgstr "недійсний тип привілеїв %s для процедури" -#: catalog/aclchk.c:506 catalog/aclchk.c:1061 +#: catalog/aclchk.c:515 catalog/aclchk.c:1070 #, c-format msgid "invalid privilege type %s for routine" msgstr "недійсний тип привілею %s для підпрограми" -#: catalog/aclchk.c:510 +#: catalog/aclchk.c:519 #, c-format msgid "invalid privilege type %s for tablespace" msgstr "недійсний тип привілеїв %s для табличного простору" -#: catalog/aclchk.c:514 catalog/aclchk.c:1065 +#: catalog/aclchk.c:523 catalog/aclchk.c:1074 #, c-format msgid "invalid privilege type %s for type" msgstr "недійсний тип привілею %s для типу" -#: catalog/aclchk.c:518 +#: catalog/aclchk.c:527 #, c-format msgid "invalid privilege type %s for foreign-data wrapper" msgstr "недійсний тип привілею %s для джерела сторонніх даних" -#: catalog/aclchk.c:522 +#: catalog/aclchk.c:531 #, c-format msgid "invalid privilege type %s for foreign server" msgstr "недійсний тип привілею %s для стороннього серверу" -#: catalog/aclchk.c:526 +#: catalog/aclchk.c:535 #, c-format msgid "invalid privilege type %s for parameter" msgstr "неприпустимий тип привілею %s для параметру" -#: catalog/aclchk.c:565 +#: catalog/aclchk.c:574 #, c-format msgid "column privileges are only valid for relations" msgstr "привілеї стовпця дійсні лише для зв'язків" -#: catalog/aclchk.c:728 catalog/aclchk.c:3555 catalog/objectaddress.c:1092 -#: catalog/pg_largeobject.c:116 storage/large_object/inv_api.c:286 +#: catalog/aclchk.c:737 catalog/aclchk.c:3624 catalog/objectaddress.c:1054 +#: catalog/pg_largeobject.c:113 storage/large_object/inv_api.c:285 #, c-format msgid "large object %u does not exist" msgstr "великого об'єкту %u не існує" -#: catalog/aclchk.c:1102 +#: catalog/aclchk.c:1111 #, c-format msgid "default privileges cannot be set for columns" msgstr "права за замовчуванням не можна встановити для стовпців" -#: catalog/aclchk.c:1138 +#: catalog/aclchk.c:1147 #, c-format msgid "permission denied to change default privileges" msgstr "немає дозволу для зміни прав за замовчуванням" -#: catalog/aclchk.c:1256 +#: catalog/aclchk.c:1265 #, c-format msgid "cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS" msgstr "речення IN SCHEMA не можна використати в GRANT/REVOKE ON SCHEMAS" -#: catalog/aclchk.c:1595 catalog/catalog.c:631 catalog/objectaddress.c:1561 -#: catalog/pg_publication.c:533 commands/analyze.c:390 commands/copy.c:837 -#: commands/sequence.c:1663 commands/tablecmds.c:7343 commands/tablecmds.c:7499 -#: commands/tablecmds.c:7549 commands/tablecmds.c:7623 -#: commands/tablecmds.c:7693 commands/tablecmds.c:7809 -#: commands/tablecmds.c:7903 commands/tablecmds.c:7962 -#: commands/tablecmds.c:8051 commands/tablecmds.c:8081 -#: commands/tablecmds.c:8209 commands/tablecmds.c:8291 -#: commands/tablecmds.c:8425 commands/tablecmds.c:8533 -#: commands/tablecmds.c:12252 commands/tablecmds.c:12433 -#: commands/tablecmds.c:12594 commands/tablecmds.c:13756 -#: commands/tablecmds.c:16287 commands/trigger.c:949 parser/analyze.c:2518 -#: parser/parse_relation.c:737 parser/parse_target.c:1054 -#: parser/parse_type.c:144 parser/parse_utilcmd.c:3422 -#: parser/parse_utilcmd.c:3458 parser/parse_utilcmd.c:3500 utils/adt/acl.c:2876 -#: utils/adt/ruleutils.c:2797 +#: catalog/aclchk.c:1616 catalog/catalog.c:650 catalog/objectaddress.c:1523 +#: catalog/pg_publication.c:528 commands/analyze.c:380 commands/copy.c:947 +#: commands/sequence.c:1655 commands/tablecmds.c:7518 commands/tablecmds.c:7672 +#: commands/tablecmds.c:7722 commands/tablecmds.c:7796 +#: commands/tablecmds.c:7866 commands/tablecmds.c:7996 +#: commands/tablecmds.c:8125 commands/tablecmds.c:8219 +#: commands/tablecmds.c:8320 commands/tablecmds.c:8447 +#: commands/tablecmds.c:8477 commands/tablecmds.c:8619 +#: commands/tablecmds.c:8712 commands/tablecmds.c:8846 +#: commands/tablecmds.c:8958 commands/tablecmds.c:12695 +#: commands/tablecmds.c:12887 commands/tablecmds.c:13048 +#: commands/tablecmds.c:14237 commands/tablecmds.c:16863 commands/trigger.c:942 +#: parser/analyze.c:2530 parser/parse_relation.c:737 parser/parse_target.c:1067 +#: parser/parse_type.c:144 parser/parse_utilcmd.c:3409 +#: parser/parse_utilcmd.c:3449 parser/parse_utilcmd.c:3491 utils/adt/acl.c:2923 +#: utils/adt/ruleutils.c:2807 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist" msgstr "стовпець \"%s\" зв'язку \"%s\" не існує" -#: catalog/aclchk.c:1840 +#: catalog/aclchk.c:1861 #, c-format msgid "\"%s\" is an index" msgstr "\"%s\" є індексом" -#: catalog/aclchk.c:1847 commands/tablecmds.c:13913 commands/tablecmds.c:17194 +#: catalog/aclchk.c:1868 commands/tablecmds.c:14394 commands/tablecmds.c:17772 #, c-format msgid "\"%s\" is a composite type" msgstr "\"%s\" це складений тип" -#: catalog/aclchk.c:1855 catalog/objectaddress.c:1401 commands/sequence.c:1171 -#: commands/tablecmds.c:254 commands/tablecmds.c:17158 utils/adt/acl.c:2084 -#: utils/adt/acl.c:2114 utils/adt/acl.c:2146 utils/adt/acl.c:2178 -#: utils/adt/acl.c:2206 utils/adt/acl.c:2236 +#: catalog/aclchk.c:1876 catalog/objectaddress.c:1363 commands/tablecmds.c:263 +#: commands/tablecmds.c:17736 utils/adt/acl.c:2107 utils/adt/acl.c:2137 +#: utils/adt/acl.c:2170 utils/adt/acl.c:2206 utils/adt/acl.c:2237 +#: utils/adt/acl.c:2268 #, c-format msgid "\"%s\" is not a sequence" msgstr "\"%s\" не є послідовністю" -#: catalog/aclchk.c:1893 +#: catalog/aclchk.c:1914 #, c-format msgid "sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges" msgstr "послідовність \"%s\" підтримує лише привілеї USAGE, SELECT та UPDATE" -#: catalog/aclchk.c:1910 +#: catalog/aclchk.c:1931 #, c-format msgid "invalid privilege type %s for table" msgstr "недійсний тип привілею %s для таблиці" -#: catalog/aclchk.c:2072 +#: catalog/aclchk.c:2093 #, c-format msgid "invalid privilege type %s for column" msgstr "недійсний тип привілею %s для стовпця" -#: catalog/aclchk.c:2085 +#: catalog/aclchk.c:2106 #, c-format msgid "sequence \"%s\" only supports SELECT column privileges" msgstr "послідовність \"%s\" підтримує тільки привілей стовпця SELECT" -#: catalog/aclchk.c:2275 +#: catalog/aclchk.c:2296 #, c-format msgid "language \"%s\" is not trusted" msgstr "мова \"%s\" не є довіреною" -#: catalog/aclchk.c:2277 +#: catalog/aclchk.c:2298 #, c-format msgid "GRANT and REVOKE are not allowed on untrusted languages, because only superusers can use untrusted languages." msgstr "GRANT і REVOKE не є допустимими для недовірених мов, тому що тільки суперкористувачі можуть використовувати недовірені мови." -#: catalog/aclchk.c:2427 +#: catalog/aclchk.c:2449 #, c-format msgid "cannot set privileges of array types" msgstr "не можна встановити права для типів масивів" -#: catalog/aclchk.c:2428 +#: catalog/aclchk.c:2450 #, c-format msgid "Set the privileges of the element type instead." msgstr "Замість цього встановіть права для типу елементу." -#: catalog/aclchk.c:2435 catalog/objectaddress.c:1667 +#: catalog/aclchk.c:2454 +#, c-format +msgid "cannot set privileges of multirange types" +msgstr "не можна встановити права для типів множинного діапазону" + +#: catalog/aclchk.c:2455 +#, c-format +msgid "Set the privileges of the range type instead." +msgstr "Замість цього встановіть права типу діапазону." + +#: catalog/aclchk.c:2462 catalog/objectaddress.c:1629 #, c-format msgid "\"%s\" is not a domain" msgstr "\"%s\" не є доменом" -#: catalog/aclchk.c:2619 +#: catalog/aclchk.c:2648 #, c-format msgid "unrecognized privilege type \"%s\"" msgstr "нерозпізнаний привілей \"%s\"" -#: catalog/aclchk.c:2684 +#: catalog/aclchk.c:2715 #, c-format msgid "permission denied for aggregate %s" msgstr "немає дозволу для агрегату %s" -#: catalog/aclchk.c:2687 +#: catalog/aclchk.c:2718 #, c-format msgid "permission denied for collation %s" msgstr "немає дозволу для сортування %s" -#: catalog/aclchk.c:2690 +#: catalog/aclchk.c:2721 #, c-format msgid "permission denied for column %s" msgstr "немає дозволу для стовпця %s" -#: catalog/aclchk.c:2693 +#: catalog/aclchk.c:2724 #, c-format msgid "permission denied for conversion %s" msgstr "немає дозволу для перетворення %s" -#: catalog/aclchk.c:2696 +#: catalog/aclchk.c:2727 #, c-format msgid "permission denied for database %s" msgstr "немає доступу для бази даних %s" -#: catalog/aclchk.c:2699 +#: catalog/aclchk.c:2730 #, c-format msgid "permission denied for domain %s" msgstr "немає дозволу для домену %s" -#: catalog/aclchk.c:2702 +#: catalog/aclchk.c:2733 #, c-format msgid "permission denied for event trigger %s" msgstr "немає дозволу для тригера подій %s" -#: catalog/aclchk.c:2705 +#: catalog/aclchk.c:2736 #, c-format msgid "permission denied for extension %s" msgstr "немає дозволу для розширення %s" -#: catalog/aclchk.c:2708 +#: catalog/aclchk.c:2739 #, c-format msgid "permission denied for foreign-data wrapper %s" msgstr "немає дозволу для джерела сторонніх даних %s" -#: catalog/aclchk.c:2711 +#: catalog/aclchk.c:2742 #, c-format msgid "permission denied for foreign server %s" msgstr "немає дозволу для стороннього серверу %s" -#: catalog/aclchk.c:2714 +#: catalog/aclchk.c:2745 #, c-format msgid "permission denied for foreign table %s" msgstr "немає дозволу для сторонньої таблиці %s" -#: catalog/aclchk.c:2717 +#: catalog/aclchk.c:2748 #, c-format msgid "permission denied for function %s" msgstr "немає дозволу для функції %s" -#: catalog/aclchk.c:2720 +#: catalog/aclchk.c:2751 #, c-format msgid "permission denied for index %s" msgstr "немає дозволу для індексу %s" -#: catalog/aclchk.c:2723 +#: catalog/aclchk.c:2754 #, c-format msgid "permission denied for language %s" msgstr "немає дозволу для мови %s" -#: catalog/aclchk.c:2726 +#: catalog/aclchk.c:2757 #, c-format msgid "permission denied for large object %s" msgstr "немає дозволу для великого об'єкту %s" -#: catalog/aclchk.c:2729 +#: catalog/aclchk.c:2760 #, c-format msgid "permission denied for materialized view %s" msgstr "немає дозволу для матеріалізованого подання %s" -#: catalog/aclchk.c:2732 +#: catalog/aclchk.c:2763 #, c-format msgid "permission denied for operator class %s" msgstr "немає дозволу для класу операторів %s" -#: catalog/aclchk.c:2735 +#: catalog/aclchk.c:2766 #, c-format msgid "permission denied for operator %s" msgstr "немає дозволу для оператора %s" -#: catalog/aclchk.c:2738 +#: catalog/aclchk.c:2769 #, c-format msgid "permission denied for operator family %s" msgstr "немає дозволу для сімейства операторів %s" -#: catalog/aclchk.c:2741 +#: catalog/aclchk.c:2772 #, c-format msgid "permission denied for parameter %s" msgstr "дозвіл відхилено для параметру %s" -#: catalog/aclchk.c:2744 +#: catalog/aclchk.c:2775 #, c-format msgid "permission denied for policy %s" msgstr "немає дозволу для політики %s" -#: catalog/aclchk.c:2747 +#: catalog/aclchk.c:2778 #, c-format msgid "permission denied for procedure %s" msgstr "немає дозволу для процедури %s" -#: catalog/aclchk.c:2750 +#: catalog/aclchk.c:2781 #, c-format msgid "permission denied for publication %s" msgstr "немає дозволу для публікації %s" -#: catalog/aclchk.c:2753 +#: catalog/aclchk.c:2784 #, c-format msgid "permission denied for routine %s" msgstr "немає дозволу для підпрограми %s" -#: catalog/aclchk.c:2756 +#: catalog/aclchk.c:2787 #, c-format msgid "permission denied for schema %s" msgstr "немає дозволу для схеми %s" -#: catalog/aclchk.c:2759 commands/sequence.c:659 commands/sequence.c:885 -#: commands/sequence.c:927 commands/sequence.c:968 commands/sequence.c:1761 -#: commands/sequence.c:1810 +#: catalog/aclchk.c:2790 commands/sequence.c:654 commands/sequence.c:880 +#: commands/sequence.c:922 commands/sequence.c:963 commands/sequence.c:1753 +#: commands/sequence.c:1799 #, c-format msgid "permission denied for sequence %s" msgstr "немає дозволу для послідовності %s" -#: catalog/aclchk.c:2762 +#: catalog/aclchk.c:2793 #, c-format msgid "permission denied for statistics object %s" msgstr "немає дозволу для об'єкту статистики %s" -#: catalog/aclchk.c:2765 +#: catalog/aclchk.c:2796 #, c-format msgid "permission denied for subscription %s" msgstr "немає дозволу для підписки %s" -#: catalog/aclchk.c:2768 +#: catalog/aclchk.c:2799 #, c-format msgid "permission denied for table %s" msgstr "немає дозволу для таблиці %s" -#: catalog/aclchk.c:2771 +#: catalog/aclchk.c:2802 #, c-format msgid "permission denied for tablespace %s" msgstr "немає дозволу для табличного простору %s" -#: catalog/aclchk.c:2774 +#: catalog/aclchk.c:2805 #, c-format msgid "permission denied for text search configuration %s" msgstr "немає дозволу для конфігурації текстового пошуку %s" -#: catalog/aclchk.c:2777 +#: catalog/aclchk.c:2808 #, c-format msgid "permission denied for text search dictionary %s" msgstr "немає дозволу для словника текстового пошуку %s" -#: catalog/aclchk.c:2780 +#: catalog/aclchk.c:2811 #, c-format msgid "permission denied for type %s" msgstr "немає дозволу для типу %s" -#: catalog/aclchk.c:2783 +#: catalog/aclchk.c:2814 #, c-format msgid "permission denied for view %s" msgstr "немає дозволу для подання %s" -#: catalog/aclchk.c:2819 +#: catalog/aclchk.c:2850 #, c-format msgid "must be owner of aggregate %s" msgstr "треба бути власником агрегату %s" -#: catalog/aclchk.c:2822 +#: catalog/aclchk.c:2853 #, c-format msgid "must be owner of collation %s" msgstr "треба бути власником правил сортування %s" -#: catalog/aclchk.c:2825 +#: catalog/aclchk.c:2856 #, c-format msgid "must be owner of conversion %s" msgstr "треба бути власником перетворення %s" -#: catalog/aclchk.c:2828 +#: catalog/aclchk.c:2859 #, c-format msgid "must be owner of database %s" msgstr "треба бути власником бази даних %s" -#: catalog/aclchk.c:2831 +#: catalog/aclchk.c:2862 #, c-format msgid "must be owner of domain %s" msgstr "треба бути власником домену %s" -#: catalog/aclchk.c:2834 +#: catalog/aclchk.c:2865 #, c-format msgid "must be owner of event trigger %s" msgstr "треба бути власником тригеру подій %s" -#: catalog/aclchk.c:2837 +#: catalog/aclchk.c:2868 #, c-format msgid "must be owner of extension %s" msgstr "треба бути власником розширення %s" -#: catalog/aclchk.c:2840 +#: catalog/aclchk.c:2871 #, c-format msgid "must be owner of foreign-data wrapper %s" msgstr "треба бути власником джерела сторонніх даних %s" -#: catalog/aclchk.c:2843 +#: catalog/aclchk.c:2874 #, c-format msgid "must be owner of foreign server %s" msgstr "треба бути власником стороннього серверу %s" -#: catalog/aclchk.c:2846 +#: catalog/aclchk.c:2877 #, c-format msgid "must be owner of foreign table %s" msgstr "треба бути власником сторонньої таблиці %s" -#: catalog/aclchk.c:2849 +#: catalog/aclchk.c:2880 #, c-format msgid "must be owner of function %s" msgstr "треба бути власником функції %s" -#: catalog/aclchk.c:2852 +#: catalog/aclchk.c:2883 #, c-format msgid "must be owner of index %s" msgstr "треба бути власником індексу %s" -#: catalog/aclchk.c:2855 +#: catalog/aclchk.c:2886 #, c-format msgid "must be owner of language %s" msgstr "треба бути власником мови %s" -#: catalog/aclchk.c:2858 +#: catalog/aclchk.c:2889 #, c-format msgid "must be owner of large object %s" msgstr "треба бути власником великого об'єкту %s" -#: catalog/aclchk.c:2861 +#: catalog/aclchk.c:2892 #, c-format msgid "must be owner of materialized view %s" msgstr "треба бути власником матеріалізованого подання %s" -#: catalog/aclchk.c:2864 +#: catalog/aclchk.c:2895 #, c-format msgid "must be owner of operator class %s" msgstr "треба бути власником класу операторів %s" -#: catalog/aclchk.c:2867 +#: catalog/aclchk.c:2898 #, c-format msgid "must be owner of operator %s" msgstr "треба бути власником оператора %s" -#: catalog/aclchk.c:2870 +#: catalog/aclchk.c:2901 #, c-format msgid "must be owner of operator family %s" msgstr "треба бути власником сімейства операторів %s" -#: catalog/aclchk.c:2873 +#: catalog/aclchk.c:2904 #, c-format msgid "must be owner of procedure %s" msgstr "треба бути власником процедури %s" -#: catalog/aclchk.c:2876 +#: catalog/aclchk.c:2907 #, c-format msgid "must be owner of publication %s" msgstr "треба бути власником публікації %s" -#: catalog/aclchk.c:2879 +#: catalog/aclchk.c:2910 #, c-format msgid "must be owner of routine %s" msgstr "треба бути власником підпрограми %s" -#: catalog/aclchk.c:2882 +#: catalog/aclchk.c:2913 #, c-format msgid "must be owner of sequence %s" msgstr "треба бути власником послідовності %s" -#: catalog/aclchk.c:2885 +#: catalog/aclchk.c:2916 #, c-format msgid "must be owner of subscription %s" msgstr "треба бути власником підписки %s" -#: catalog/aclchk.c:2888 +#: catalog/aclchk.c:2919 #, c-format msgid "must be owner of table %s" msgstr "треба бути власником таблиці %s" -#: catalog/aclchk.c:2891 +#: catalog/aclchk.c:2922 #, c-format msgid "must be owner of type %s" msgstr "треба бути власником типу %s" -#: catalog/aclchk.c:2894 +#: catalog/aclchk.c:2925 #, c-format msgid "must be owner of view %s" msgstr "треба бути власником подання %s" -#: catalog/aclchk.c:2897 +#: catalog/aclchk.c:2928 #, c-format msgid "must be owner of schema %s" msgstr "треба бути власником схеми %s" -#: catalog/aclchk.c:2900 +#: catalog/aclchk.c:2931 #, c-format msgid "must be owner of statistics object %s" msgstr "треба бути власником об'єкту статистики %s" -#: catalog/aclchk.c:2903 +#: catalog/aclchk.c:2934 #, c-format msgid "must be owner of tablespace %s" msgstr "треба бути власником табличного простору %s" -#: catalog/aclchk.c:2906 +#: catalog/aclchk.c:2937 #, c-format msgid "must be owner of text search configuration %s" msgstr "треба бути власником конфігурації текстового пошуку %s" -#: catalog/aclchk.c:2909 +#: catalog/aclchk.c:2940 #, c-format msgid "must be owner of text search dictionary %s" msgstr "треба бути власником словника текстового пошуку %s" -#: catalog/aclchk.c:2923 +#: catalog/aclchk.c:2954 #, c-format msgid "must be owner of relation %s" msgstr "треба бути власником відношення %s" -#: catalog/aclchk.c:2969 +#: catalog/aclchk.c:3000 #, c-format msgid "permission denied for column \"%s\" of relation \"%s\"" msgstr "немає дозволу для стовпця \"%s\" відношення \"%s\"" -#: catalog/aclchk.c:3104 catalog/aclchk.c:3984 catalog/aclchk.c:4015 +#: catalog/aclchk.c:3157 catalog/aclchk.c:4165 catalog/aclchk.c:4196 #, c-format msgid "%s with OID %u does not exist" msgstr "%s з OID %u не існує" -#: catalog/aclchk.c:3188 catalog/aclchk.c:3207 +#: catalog/aclchk.c:3240 catalog/aclchk.c:3259 #, c-format msgid "attribute %d of relation with OID %u does not exist" msgstr "атрибут %d відношення з OID %u не існує" -#: catalog/aclchk.c:3302 +#: catalog/aclchk.c:3297 catalog/aclchk.c:3360 catalog/aclchk.c:3999 #, c-format msgid "relation with OID %u does not exist" msgstr "відношення з OID %u не існує" -#: catalog/aclchk.c:3476 +#: catalog/aclchk.c:3545 #, c-format msgid "parameter ACL with OID %u does not exist" msgstr "параметр ACL з OID %u не існує" -#: catalog/aclchk.c:3640 commands/collationcmds.c:813 -#: commands/publicationcmds.c:1746 +#: catalog/aclchk.c:3718 commands/collationcmds.c:853 +#: commands/publicationcmds.c:1739 #, c-format msgid "schema with OID %u does not exist" msgstr "схема з OID %u не існує" -#: catalog/aclchk.c:3705 utils/cache/typcache.c:390 utils/cache/typcache.c:445 +#: catalog/aclchk.c:3792 catalog/aclchk.c:3819 catalog/aclchk.c:3848 +#: utils/cache/typcache.c:392 utils/cache/typcache.c:447 #, c-format msgid "type with OID %u does not exist" msgstr "тип з OID %u не існує" -#: catalog/catalog.c:449 +#: catalog/catalog.c:468 #, c-format msgid "still searching for an unused OID in relation \"%s\"" msgstr "все ще шукаю невикористаний OID у відношенні \"%s\"" -#: catalog/catalog.c:451 +#: catalog/catalog.c:470 #, c-format msgid "OID candidates have been checked %llu time, but no unused OID has been found yet." msgid_plural "OID candidates have been checked %llu times, but no unused OID has been found yet." @@ -4361,7 +4681,7 @@ msgstr[1] "OID кандидати буле перевірені %llu рази, msgstr[2] "OID кандидати буле перевірені %llu разів, але невикористаного OID все ще не знайдено." msgstr[3] "OID кандидати буле перевірені %llu разів, але невикористаного OID все ще не знайдено." -#: catalog/catalog.c:476 +#: catalog/catalog.c:495 #, c-format msgid "new OID has been assigned in relation \"%s\" after %llu retry" msgid_plural "new OID has been assigned in relation \"%s\" after %llu retries" @@ -4370,106 +4690,101 @@ msgstr[1] "новий OID було призначено у відношенні msgstr[2] "новий OID було призначено у відношенні \"%s\" після %llu повторних спроб" msgstr[3] "новий OID було призначено у відношенні \"%s\" після %llu повторних спроб" -#: catalog/catalog.c:609 catalog/catalog.c:676 +#: catalog/catalog.c:628 catalog/catalog.c:695 #, c-format msgid "must be superuser to call %s()" msgstr "для виклику %s() потрібно бути суперкористувачем" -#: catalog/catalog.c:618 +#: catalog/catalog.c:637 #, c-format msgid "pg_nextoid() can only be used on system catalogs" msgstr "pg_nextoid() можна використовувати лише для системних каталогів" -#: catalog/catalog.c:623 parser/parse_utilcmd.c:2273 +#: catalog/catalog.c:642 parser/parse_utilcmd.c:2270 #, c-format msgid "index \"%s\" does not belong to table \"%s\"" msgstr "індекс \"%s\" не належить таблиці \"%s\"" -#: catalog/catalog.c:640 +#: catalog/catalog.c:659 #, c-format msgid "column \"%s\" is not of type oid" msgstr "стовпець \"%s\" повинен мати тип oid" -#: catalog/catalog.c:647 +#: catalog/catalog.c:666 #, c-format msgid "index \"%s\" is not the index for column \"%s\"" msgstr "індекс \"%s\" не є індексом для стовпця \"%s\"" -#: catalog/dependency.c:546 catalog/pg_shdepend.c:658 +#: catalog/dependency.c:497 catalog/pg_shdepend.c:703 #, c-format msgid "cannot drop %s because it is required by the database system" msgstr "не вдалося видалити %s, оскільки він потрібний системі бази даних" -#: catalog/dependency.c:838 catalog/dependency.c:1065 +#: catalog/dependency.c:789 catalog/dependency.c:1016 #, c-format msgid "cannot drop %s because %s requires it" msgstr "не вдалося видалити %s, оскільки %s потребує його" -#: catalog/dependency.c:840 catalog/dependency.c:1067 +#: catalog/dependency.c:791 catalog/dependency.c:1018 #, c-format msgid "You can drop %s instead." msgstr "Ви можете видалити %s замість цього." -#: catalog/dependency.c:1146 catalog/dependency.c:1155 +#: catalog/dependency.c:1097 catalog/dependency.c:1106 #, c-format msgid "%s depends on %s" msgstr "%s залежить від %s" -#: catalog/dependency.c:1170 catalog/dependency.c:1179 +#: catalog/dependency.c:1121 catalog/dependency.c:1130 #, c-format msgid "drop cascades to %s" msgstr "видалення поширюється (cascades) на об'єкт %s" -#: catalog/dependency.c:1187 catalog/pg_shdepend.c:823 +#: catalog/dependency.c:1138 catalog/pg_shdepend.c:868 #, c-format -msgid "" -"\n" +msgid "\n" "and %d other object (see server log for list)" -msgid_plural "" -"\n" +msgid_plural "\n" "and %d other objects (see server log for list)" -msgstr[0] "" -"\n" +msgstr[0] "\n" "і ще %d інших об'єктів (див. список у протоколі серверу)" -msgstr[1] "" -"\n" +msgstr[1] "\n" "і ще %d інші об'єкти (див. список у протоколі серверу)" -msgstr[2] "" -"\n" +msgstr[2] "\n" "і ще %d інших об'єктів (див. список у протоколі серверу)" -msgstr[3] "" -"\n" +msgstr[3] "\n" "і ще %d інших об'єктів (див. список у протоколі серверу)" -#: catalog/dependency.c:1199 +#: catalog/dependency.c:1150 #, c-format msgid "cannot drop %s because other objects depend on it" msgstr "неможливо видалити %s, тому що від нього залежать інші об'єкти" -#: catalog/dependency.c:1202 catalog/dependency.c:1209 -#: catalog/dependency.c:1220 commands/tablecmds.c:1335 -#: commands/tablecmds.c:14400 commands/tablespace.c:466 commands/user.c:1303 -#: commands/vacuum.c:211 commands/view.c:446 libpq/auth.c:326 -#: replication/logical/applyparallelworker.c:1044 replication/syncrep.c:1017 -#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1366 utils/misc/guc.c:3122 -#: utils/misc/guc.c:3158 utils/misc/guc.c:3228 utils/misc/guc.c:6632 -#: utils/misc/guc.c:6666 utils/misc/guc.c:6700 utils/misc/guc.c:6743 -#: utils/misc/guc.c:6785 +#: catalog/dependency.c:1153 catalog/dependency.c:1160 +#: catalog/dependency.c:1171 commands/tablecmds.c:1442 +#: commands/tablecmds.c:14986 commands/tablespace.c:460 commands/user.c:1302 +#: commands/vacuum.c:211 commands/view.c:441 executor/execExprInterp.c:4643 +#: executor/execExprInterp.c:4651 libpq/auth.c:324 +#: replication/logical/applyparallelworker.c:1041 replication/syncrep.c:1011 +#: storage/lmgr/deadlock.c:1134 storage/lmgr/proc.c:1427 utils/misc/guc.c:3169 +#: utils/misc/guc.c:3210 utils/misc/guc.c:3285 utils/misc/guc.c:6790 +#: utils/misc/guc.c:6824 utils/misc/guc.c:6858 utils/misc/guc.c:6901 +#: utils/misc/guc.c:6943 #, c-format msgid "%s" msgstr "%s" -#: catalog/dependency.c:1203 catalog/dependency.c:1210 +#: catalog/dependency.c:1154 catalog/dependency.c:1161 #, c-format msgid "Use DROP ... CASCADE to drop the dependent objects too." msgstr "Використайте DROP ... CASCADE для видалення залежних об'єктів також." -#: catalog/dependency.c:1207 +#: catalog/dependency.c:1158 #, c-format msgid "cannot drop desired object(s) because other objects depend on them" msgstr "не можна видалити бажаний(-і) об'єкт(-и) тому, що інші об'єкти залежні від нього(них)" -#: catalog/dependency.c:1215 +#: catalog/dependency.c:1166 #, c-format msgid "drop cascades to %d other object" msgid_plural "drop cascades to %d other objects" @@ -4478,679 +4793,679 @@ msgstr[1] "видалення поширюється (cascades) на ще %d і msgstr[2] "видалення поширюється (cascades) на ще %d інших об'єктів" msgstr[3] "видалення поширюється (cascades) на ще %d інших об'єктів" -#: catalog/dependency.c:1899 +#: catalog/dependency.c:1850 #, c-format msgid "constant of the type %s cannot be used here" msgstr "константа типу %s не може бути використана тут" -#: catalog/dependency.c:2420 parser/parse_relation.c:3404 -#: parser/parse_relation.c:3414 +#: catalog/dependency.c:2375 parser/parse_relation.c:3407 +#: parser/parse_relation.c:3417 #, c-format msgid "column %d of relation \"%s\" does not exist" msgstr "стовпець %d відношення \"%s\" не існує" -#: catalog/heap.c:324 +#: catalog/heap.c:325 #, c-format msgid "permission denied to create \"%s.%s\"" msgstr "немає дозволу для створення \"%s.%s\"" -#: catalog/heap.c:326 +#: catalog/heap.c:327 #, c-format msgid "System catalog modifications are currently disallowed." msgstr "Змінення системного каталогу наразі заборонено." -#: catalog/heap.c:466 commands/tablecmds.c:2374 commands/tablecmds.c:3047 -#: commands/tablecmds.c:6926 +#: catalog/heap.c:467 commands/tablecmds.c:2478 commands/tablecmds.c:2900 +#: commands/tablecmds.c:7140 #, c-format msgid "tables can have at most %d columns" msgstr "таблиці можуть містити максимум %d стовпців" -#: catalog/heap.c:484 commands/tablecmds.c:7233 +#: catalog/heap.c:485 commands/tablecmds.c:7409 #, c-format msgid "column name \"%s\" conflicts with a system column name" msgstr "ім'я стовпця \"%s\" конфліктує з системним іменем стовпця" -#: catalog/heap.c:500 +#: catalog/heap.c:501 #, c-format msgid "column name \"%s\" specified more than once" msgstr "ім'я стовпця \"%s\" вказано кілька разів" #. translator: first %s is an integer not a name -#: catalog/heap.c:575 +#: catalog/heap.c:579 #, c-format msgid "partition key column %s has pseudo-type %s" msgstr "стовпець ключа секціонування %s має псевдотип %s" -#: catalog/heap.c:580 +#: catalog/heap.c:584 #, c-format msgid "column \"%s\" has pseudo-type %s" msgstr "стовпець \"%s\" має псевдо-тип %s" -#: catalog/heap.c:611 +#: catalog/heap.c:615 #, c-format msgid "composite type %s cannot be made a member of itself" msgstr "складений тип %s не може містити сам себе" #. translator: first %s is an integer not a name -#: catalog/heap.c:666 +#: catalog/heap.c:670 #, c-format msgid "no collation was derived for partition key column %s with collatable type %s" msgstr "для стовпця ключа секціонування \"%s\" з сортируючим типом %s не вдалося отримати параметри сортування" -#: catalog/heap.c:672 commands/createas.c:203 commands/createas.c:512 +#: catalog/heap.c:676 commands/createas.c:198 commands/createas.c:505 #, c-format msgid "no collation was derived for column \"%s\" with collatable type %s" msgstr "для стовпця \"%s\" із сортувальним типом %s не вдалося отримати параметри сортування" -#: catalog/heap.c:1148 catalog/index.c:887 commands/createas.c:408 -#: commands/tablecmds.c:3987 +#: catalog/heap.c:1161 catalog/index.c:899 commands/createas.c:401 +#: commands/tablecmds.c:4149 #, c-format msgid "relation \"%s\" already exists" msgstr "відношення \"%s\" вже існує" -#: catalog/heap.c:1164 catalog/pg_type.c:434 catalog/pg_type.c:782 -#: catalog/pg_type.c:954 commands/typecmds.c:249 commands/typecmds.c:261 -#: commands/typecmds.c:754 commands/typecmds.c:1169 commands/typecmds.c:1395 -#: commands/typecmds.c:1575 commands/typecmds.c:2546 +#: catalog/heap.c:1177 catalog/pg_type.c:434 catalog/pg_type.c:805 +#: catalog/pg_type.c:977 commands/typecmds.c:253 commands/typecmds.c:265 +#: commands/typecmds.c:758 commands/typecmds.c:1179 commands/typecmds.c:1405 +#: commands/typecmds.c:1585 commands/typecmds.c:2556 #, c-format msgid "type \"%s\" already exists" msgstr "тип \"%s\" вже існує" -#: catalog/heap.c:1165 +#: catalog/heap.c:1178 #, c-format msgid "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type." msgstr "З відношенням вже пов'язаний тип з таким самим іменем, тому виберіть ім'я, яке не буде конфліктувати з типами, що існують." -#: catalog/heap.c:1205 +#: catalog/heap.c:1218 #, c-format msgid "toast relfilenumber value not set when in binary upgrade mode" msgstr "значення toast relfilenumber не встановлено в режимі двійкового оновлення" -#: catalog/heap.c:1216 +#: catalog/heap.c:1229 #, c-format msgid "pg_class heap OID value not set when in binary upgrade mode" msgstr "значення OID в pg_class не задано в режимі двійкового оновлення" -#: catalog/heap.c:1226 +#: catalog/heap.c:1239 #, c-format msgid "relfilenumber value not set when in binary upgrade mode" msgstr "значення relfilenumber не встановлено в режимі двійкового оновлення" -#: catalog/heap.c:2119 +#: catalog/heap.c:2128 #, c-format msgid "cannot add NO INHERIT constraint to partitioned table \"%s\"" msgstr "не можна додати обмеження NO INHERIT до секціонованої таблиці \"%s\"" -#: catalog/heap.c:2394 +#: catalog/heap.c:2400 #, c-format msgid "check constraint \"%s\" already exists" msgstr "обмеження перевірки \"%s\" вже інсує" -#: catalog/heap.c:2564 catalog/index.c:901 catalog/pg_constraint.c:682 -#: commands/tablecmds.c:8908 +#: catalog/heap.c:2572 catalog/index.c:913 catalog/pg_constraint.c:724 +#: commands/tablecmds.c:9333 #, c-format msgid "constraint \"%s\" for relation \"%s\" already exists" msgstr "обмеження \"%s\" відношення \"%s\" вже існує" -#: catalog/heap.c:2571 +#: catalog/heap.c:2579 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"" msgstr "обмеження \"%s\" конфліктує з неуспадкованим обмеженням відношення \"%s\"" -#: catalog/heap.c:2582 +#: catalog/heap.c:2590 #, c-format msgid "constraint \"%s\" conflicts with inherited constraint on relation \"%s\"" msgstr "обмеження \"%s\" конфліктує з успадкованим обмеженням відношення \"%s\"" -#: catalog/heap.c:2592 +#: catalog/heap.c:2600 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" msgstr "обмеження \"%s\" конфліктує з обмеженням NOT VALID в відношенні \"%s\"" -#: catalog/heap.c:2597 +#: catalog/heap.c:2605 #, c-format msgid "merging constraint \"%s\" with inherited definition" msgstr "злиття обмеження \"%s\" з успадкованим визначенням" -#: catalog/heap.c:2623 catalog/pg_constraint.c:811 commands/tablecmds.c:2672 -#: commands/tablecmds.c:3199 commands/tablecmds.c:6858 -#: commands/tablecmds.c:15222 commands/tablecmds.c:15363 +#: catalog/heap.c:2631 catalog/pg_constraint.c:853 commands/tablecmds.c:3057 +#: commands/tablecmds.c:3360 commands/tablecmds.c:7066 +#: commands/tablecmds.c:15804 commands/tablecmds.c:15935 #, c-format msgid "too many inheritance parents" msgstr "занадто багато батьків наслідування" -#: catalog/heap.c:2707 +#: catalog/heap.c:2715 #, c-format msgid "cannot use generated column \"%s\" in column generation expression" msgstr "в виразі створення стовпця не можна використовувати згенерований стовпець \"%s\"" -#: catalog/heap.c:2709 +#: catalog/heap.c:2717 #, c-format msgid "A generated column cannot reference another generated column." msgstr "Згенерований стовпець не може посилатися на інший згенерований стовпець." -#: catalog/heap.c:2715 +#: catalog/heap.c:2723 #, c-format msgid "cannot use whole-row variable in column generation expression" msgstr "у виразі створення стовпців не можна використовувати змінну усього рядка" -#: catalog/heap.c:2716 +#: catalog/heap.c:2724 #, c-format msgid "This would cause the generated column to depend on its own value." msgstr "Це призведе до того, що згенерований стовпець буде залежати від власного значення." -#: catalog/heap.c:2771 +#: catalog/heap.c:2779 #, c-format msgid "generation expression is not immutable" msgstr "вираз генерації не є незмінним" -#: catalog/heap.c:2799 rewrite/rewriteHandler.c:1297 +#: catalog/heap.c:2807 rewrite/rewriteHandler.c:1282 #, c-format msgid "column \"%s\" is of type %s but default expression is of type %s" msgstr "стовпець \"%s\" має тип %s, але тип виразу за замовчуванням %s" -#: catalog/heap.c:2804 commands/prepare.c:334 parser/analyze.c:2742 -#: parser/parse_target.c:593 parser/parse_target.c:874 -#: parser/parse_target.c:884 rewrite/rewriteHandler.c:1302 +#: catalog/heap.c:2812 commands/prepare.c:331 parser/analyze.c:2758 +#: parser/parse_target.c:592 parser/parse_target.c:882 +#: parser/parse_target.c:892 rewrite/rewriteHandler.c:1287 #, c-format msgid "You will need to rewrite or cast the expression." msgstr "Потрібно буде переписати або привести вираз." -#: catalog/heap.c:2851 +#: catalog/heap.c:2859 #, c-format msgid "only table \"%s\" can be referenced in check constraint" msgstr "в обмеженні-перевірці можна посилатися лише на таблицю \"%s\"" -#: catalog/heap.c:3157 +#: catalog/heap.c:3165 #, c-format msgid "unsupported ON COMMIT and foreign key combination" msgstr "непідтримуване поєднання зовнішнього ключа з ON COMMIT" -#: catalog/heap.c:3158 +#: catalog/heap.c:3166 #, c-format msgid "Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting." msgstr "Таблиця \"%s\" посилається на \"%s\", але вони не мають той же параметр ON COMMIT." -#: catalog/heap.c:3163 +#: catalog/heap.c:3171 #, c-format msgid "cannot truncate a table referenced in a foreign key constraint" msgstr "скоротити таблицю, на яку посилається зовнішній ключ, не можливо" -#: catalog/heap.c:3164 +#: catalog/heap.c:3172 #, c-format msgid "Table \"%s\" references \"%s\"." msgstr "Таблиця \"%s\" посилається на \"%s\"." -#: catalog/heap.c:3166 +#: catalog/heap.c:3174 #, c-format msgid "Truncate table \"%s\" at the same time, or use TRUNCATE ... CASCADE." msgstr "Скоротіть таблицю \"%s\" паралельно або використайте TRUNCATE ... CASCADE." -#: catalog/index.c:225 parser/parse_utilcmd.c:2179 +#: catalog/index.c:219 parser/parse_utilcmd.c:2176 #, c-format msgid "multiple primary keys for table \"%s\" are not allowed" msgstr "таблиця \"%s\" не може містити кілька первинних ключів" -#: catalog/index.c:239 +#: catalog/index.c:233 #, c-format msgid "primary keys cannot use NULLS NOT DISTINCT indexes" msgstr "первинні ключі не можуть використовувати NULLS NOT DISTINCT індекси" -#: catalog/index.c:256 +#: catalog/index.c:250 #, c-format msgid "primary keys cannot be expressions" msgstr "первинні ключі не можуть бути виразами" -#: catalog/index.c:273 +#: catalog/index.c:267 #, c-format msgid "primary key column \"%s\" is not marked NOT NULL" msgstr "стовпець первинного ключа \"%s\" не позначений як NOT NULL" -#: catalog/index.c:786 catalog/index.c:1942 +#: catalog/index.c:798 catalog/index.c:1915 #, c-format msgid "user-defined indexes on system catalog tables are not supported" msgstr "користувацькі індекси в таблицях системного каталогу не підтримуються" -#: catalog/index.c:826 +#: catalog/index.c:838 #, c-format msgid "nondeterministic collations are not supported for operator class \"%s\"" msgstr "недетерміновані правила сортування не підтримуються для класу операторів \"%s\"" -#: catalog/index.c:841 +#: catalog/index.c:853 #, c-format msgid "concurrent index creation on system catalog tables is not supported" msgstr "паралельне створення індексу в таблицях системного каталогу не підтримується" -#: catalog/index.c:850 catalog/index.c:1318 +#: catalog/index.c:862 catalog/index.c:1331 #, c-format msgid "concurrent index creation for exclusion constraints is not supported" msgstr "парарельне створення індексу для обмежень-виключень не підтримується" -#: catalog/index.c:859 +#: catalog/index.c:871 #, c-format msgid "shared indexes cannot be created after initdb" msgstr "не можливо створити спільні індекси після initdb" -#: catalog/index.c:879 commands/createas.c:423 commands/sequence.c:158 +#: catalog/index.c:891 commands/createas.c:416 commands/sequence.c:159 #: parser/parse_utilcmd.c:209 #, c-format msgid "relation \"%s\" already exists, skipping" msgstr "ввідношення \"%s\" вже існує, пропускаємо" -#: catalog/index.c:929 +#: catalog/index.c:941 #, c-format msgid "pg_class index OID value not set when in binary upgrade mode" msgstr "значення OID індекса в pg_class не встановлено в режимі двійкового оновлення" -#: catalog/index.c:939 utils/cache/relcache.c:3731 +#: catalog/index.c:951 utils/cache/relcache.c:3790 #, c-format msgid "index relfilenumber value not set when in binary upgrade mode" msgstr "значення індексу relfilenumber не встановлено в режимі двійкового оновлення" -#: catalog/index.c:2241 +#: catalog/index.c:2214 #, c-format msgid "DROP INDEX CONCURRENTLY must be first action in transaction" msgstr "DROP INDEX CONCURRENTLY повинен бути першою дією в транзакції" -#: catalog/index.c:3675 +#: catalog/index.c:3670 #, c-format msgid "cannot reindex temporary tables of other sessions" msgstr "повторно індексувати тимчасові таблиці інших сеансів не можна" -#: catalog/index.c:3686 commands/indexcmds.c:3607 +#: catalog/index.c:3681 commands/indexcmds.c:3653 #, c-format msgid "cannot reindex invalid index on TOAST table" msgstr "переіндексувати неприпустимий індекс в таблиці TOAST не можна" -#: catalog/index.c:3702 commands/indexcmds.c:3487 commands/indexcmds.c:3631 -#: commands/tablecmds.c:3402 +#: catalog/index.c:3697 commands/indexcmds.c:3531 commands/indexcmds.c:3677 +#: commands/tablecmds.c:3564 #, c-format msgid "cannot move system relation \"%s\"" msgstr "перемістити системне відношення \"%s\" не можна" -#: catalog/index.c:3846 +#: catalog/index.c:3834 #, c-format msgid "index \"%s\" was reindexed" msgstr "індекс \"%s\" був перебудований" -#: catalog/index.c:3983 +#: catalog/index.c:4000 #, c-format msgid "cannot reindex invalid index \"%s.%s\" on TOAST table, skipping" msgstr "переіндексувати неприпустимий індекс \"%s.%s\" в таблиці TOAST не можна, пропускається" -#: catalog/namespace.c:260 catalog/namespace.c:464 catalog/namespace.c:556 -#: commands/trigger.c:5736 +#: catalog/namespace.c:447 catalog/namespace.c:651 catalog/namespace.c:743 +#: commands/trigger.c:5731 #, c-format msgid "cross-database references are not implemented: \"%s.%s.%s\"" msgstr "cross-database посилання не реалізовані: \"%s.%s.%s\"" -#: catalog/namespace.c:317 +#: catalog/namespace.c:504 #, c-format msgid "temporary tables cannot specify a schema name" msgstr "для тимчасових таблиць ім'я схеми не вказується" -#: catalog/namespace.c:398 +#: catalog/namespace.c:585 #, c-format msgid "could not obtain lock on relation \"%s.%s\"" msgstr "не вдалося отримати блокування зв'язку \"%s.%s\"" -#: catalog/namespace.c:403 commands/lockcmds.c:144 commands/lockcmds.c:224 +#: catalog/namespace.c:590 commands/lockcmds.c:143 commands/lockcmds.c:223 #, c-format msgid "could not obtain lock on relation \"%s\"" msgstr "не вдалося отримати блокування зв'язку \"%s\"" -#: catalog/namespace.c:431 parser/parse_relation.c:1430 +#: catalog/namespace.c:618 parser/parse_relation.c:1430 #, c-format msgid "relation \"%s.%s\" does not exist" msgstr "відношення \"%s.%s\" не існує" -#: catalog/namespace.c:436 parser/parse_relation.c:1443 +#: catalog/namespace.c:623 parser/parse_relation.c:1443 #: parser/parse_relation.c:1451 utils/adt/regproc.c:913 #, c-format msgid "relation \"%s\" does not exist" msgstr "відношення \"%s\" не існує" -#: catalog/namespace.c:502 catalog/namespace.c:3073 commands/extension.c:1611 -#: commands/extension.c:1617 +#: catalog/namespace.c:689 catalog/namespace.c:3507 commands/extension.c:1607 +#: commands/extension.c:1613 #, c-format msgid "no schema has been selected to create in" msgstr "не вибрано схему для створення об'єктів" -#: catalog/namespace.c:654 catalog/namespace.c:667 +#: catalog/namespace.c:841 catalog/namespace.c:854 #, c-format msgid "cannot create relations in temporary schemas of other sessions" msgstr "неможливо створити відношення в тимчасових схемах з інших сеансів" -#: catalog/namespace.c:658 +#: catalog/namespace.c:845 #, c-format msgid "cannot create temporary relation in non-temporary schema" msgstr "неможливо створити тимчасове відношення в не тимчасовій схемі" -#: catalog/namespace.c:673 +#: catalog/namespace.c:860 #, c-format msgid "only temporary relations may be created in temporary schemas" msgstr "в тимчасових схемах можуть бути створені тільки тимчасові відношення" -#: catalog/namespace.c:2265 +#: catalog/namespace.c:2604 #, c-format msgid "statistics object \"%s\" does not exist" msgstr "об'єкт статистики \"%s\" не існує" -#: catalog/namespace.c:2388 +#: catalog/namespace.c:2746 #, c-format msgid "text search parser \"%s\" does not exist" msgstr "парсер текстового пошуку \"%s\" не існує" -#: catalog/namespace.c:2514 utils/adt/regproc.c:1439 +#: catalog/namespace.c:2891 utils/adt/regproc.c:1459 #, c-format msgid "text search dictionary \"%s\" does not exist" msgstr "словник текстового пошуку \"%s\" не існує" -#: catalog/namespace.c:2641 +#: catalog/namespace.c:3037 #, c-format msgid "text search template \"%s\" does not exist" msgstr "шаблон текстового пошуку \"%s\" не існує" -#: catalog/namespace.c:2767 commands/tsearchcmds.c:1168 -#: utils/adt/regproc.c:1329 utils/cache/ts_cache.c:635 +#: catalog/namespace.c:3182 commands/tsearchcmds.c:1168 +#: utils/adt/regproc.c:1349 utils/cache/ts_cache.c:635 #, c-format msgid "text search configuration \"%s\" does not exist" msgstr "конфігурація текстового пошуку \"%s\" не існує" -#: catalog/namespace.c:2880 parser/parse_expr.c:832 parser/parse_target.c:1246 +#: catalog/namespace.c:3314 parser/parse_expr.c:868 parser/parse_target.c:1259 #, c-format msgid "cross-database references are not implemented: %s" msgstr "міжбазові посилання не реалізовані: %s" -#: catalog/namespace.c:2886 parser/parse_expr.c:839 parser/parse_target.c:1253 -#: gram.y:18569 gram.y:18609 +#: catalog/namespace.c:3320 parser/parse_expr.c:875 parser/parse_target.c:1266 +#: gram.y:19181 gram.y:19221 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неправильне повне ім'я (забагато компонентів): %s" -#: catalog/namespace.c:3016 +#: catalog/namespace.c:3450 #, c-format msgid "cannot move objects into or out of temporary schemas" msgstr "не можна переміщати об'єкти в або з тимчасових схем" -#: catalog/namespace.c:3022 +#: catalog/namespace.c:3456 #, c-format msgid "cannot move objects into or out of TOAST schema" msgstr "не можна переміщати об'єкти в або з схем TOAST" -#: catalog/namespace.c:3095 commands/schemacmds.c:264 commands/schemacmds.c:344 -#: commands/tablecmds.c:1280 utils/adt/regproc.c:1668 +#: catalog/namespace.c:3529 commands/schemacmds.c:264 commands/schemacmds.c:344 +#: commands/tablecmds.c:1387 utils/adt/regproc.c:1688 #, c-format msgid "schema \"%s\" does not exist" msgstr "схема \"%s\" не існує" -#: catalog/namespace.c:3126 +#: catalog/namespace.c:3560 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неправильне ім'я зв'язку (забагато компонентів): %s" -#: catalog/namespace.c:3693 utils/adt/regproc.c:1056 +#: catalog/namespace.c:4001 utils/adt/regproc.c:1056 #, c-format msgid "collation \"%s\" for encoding \"%s\" does not exist" msgstr "правило сортування \"%s\" для кодування \"%s\" не існує" -#: catalog/namespace.c:3748 +#: catalog/namespace.c:4056 #, c-format msgid "conversion \"%s\" does not exist" msgstr "перетворення\"%s\" не існує" -#: catalog/namespace.c:4012 +#: catalog/namespace.c:4397 #, c-format msgid "permission denied to create temporary tables in database \"%s\"" msgstr "немає дозволу для створення тимчасових таблиць в базі даних \"%s\"" -#: catalog/namespace.c:4028 +#: catalog/namespace.c:4413 #, c-format msgid "cannot create temporary tables during recovery" msgstr "не можна створити тимчасові таблиці під час відновлення" -#: catalog/namespace.c:4034 +#: catalog/namespace.c:4419 #, c-format msgid "cannot create temporary tables during a parallel operation" msgstr "не можна створити тимчасові таблиці під час паралельної операції" -#: catalog/objectaddress.c:1409 commands/policy.c:96 commands/policy.c:376 -#: commands/tablecmds.c:248 commands/tablecmds.c:290 commands/tablecmds.c:2206 -#: commands/tablecmds.c:12369 +#: catalog/objectaddress.c:1371 commands/policy.c:93 commands/policy.c:373 +#: commands/tablecmds.c:257 commands/tablecmds.c:299 commands/tablecmds.c:2310 +#: commands/tablecmds.c:12823 #, c-format msgid "\"%s\" is not a table" msgstr "\"%s\" не є таблицею" -#: catalog/objectaddress.c:1416 commands/tablecmds.c:260 -#: commands/tablecmds.c:17163 commands/view.c:119 +#: catalog/objectaddress.c:1378 commands/tablecmds.c:269 +#: commands/tablecmds.c:17741 commands/view.c:114 #, c-format msgid "\"%s\" is not a view" msgstr "\"%s\" не є поданням" -#: catalog/objectaddress.c:1423 commands/matview.c:186 commands/tablecmds.c:266 -#: commands/tablecmds.c:17168 +#: catalog/objectaddress.c:1385 commands/matview.c:199 commands/tablecmds.c:275 +#: commands/tablecmds.c:17746 #, c-format msgid "\"%s\" is not a materialized view" msgstr "\"%s\" не є матеріалізованим поданням" -#: catalog/objectaddress.c:1430 commands/tablecmds.c:284 -#: commands/tablecmds.c:17173 +#: catalog/objectaddress.c:1392 commands/tablecmds.c:293 +#: commands/tablecmds.c:17751 #, c-format msgid "\"%s\" is not a foreign table" msgstr "\"%s\" не є сторонньою таблицею" -#: catalog/objectaddress.c:1471 +#: catalog/objectaddress.c:1433 #, c-format msgid "must specify relation and object name" msgstr "треба вказати відношення й ім'я об'єкта" -#: catalog/objectaddress.c:1547 catalog/objectaddress.c:1600 +#: catalog/objectaddress.c:1509 catalog/objectaddress.c:1562 #, c-format msgid "column name must be qualified" msgstr "слід вказати ім'я стовпця" -#: catalog/objectaddress.c:1619 +#: catalog/objectaddress.c:1581 #, c-format msgid "default value for column \"%s\" of relation \"%s\" does not exist" msgstr "значення за замовчуванням для стовпця \"%s\" відношення \"%s\" не існує" -#: catalog/objectaddress.c:1656 commands/functioncmds.c:137 -#: commands/tablecmds.c:276 commands/typecmds.c:274 commands/typecmds.c:3691 +#: catalog/objectaddress.c:1618 commands/functioncmds.c:132 +#: commands/tablecmds.c:285 commands/typecmds.c:278 commands/typecmds.c:3843 #: parser/parse_type.c:243 parser/parse_type.c:272 parser/parse_type.c:801 -#: utils/adt/acl.c:4441 +#: utils/adt/acl.c:4560 #, c-format msgid "type \"%s\" does not exist" msgstr "тип \"%s\" не існує" -#: catalog/objectaddress.c:1775 +#: catalog/objectaddress.c:1737 #, c-format msgid "operator %d (%s, %s) of %s does not exist" msgstr "оператор %d (%s, %s) з %s не існує" -#: catalog/objectaddress.c:1806 +#: catalog/objectaddress.c:1768 #, c-format msgid "function %d (%s, %s) of %s does not exist" msgstr "функція %d (%s, %s) з %s не існує" -#: catalog/objectaddress.c:1857 catalog/objectaddress.c:1883 +#: catalog/objectaddress.c:1819 catalog/objectaddress.c:1845 #, c-format msgid "user mapping for user \"%s\" on server \"%s\" does not exist" msgstr "відображення користувача для користувача \"%s\" на сервері \"%s\"не існує" -#: catalog/objectaddress.c:1872 commands/foreigncmds.c:430 -#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:700 +#: catalog/objectaddress.c:1834 commands/foreigncmds.c:430 +#: commands/foreigncmds.c:993 commands/foreigncmds.c:1356 foreign/foreign.c:713 #, c-format msgid "server \"%s\" does not exist" msgstr "сервер \"%s\" не існує" -#: catalog/objectaddress.c:1939 +#: catalog/objectaddress.c:1901 #, c-format msgid "publication relation \"%s\" in publication \"%s\" does not exist" msgstr "відношення публікації \"%s\" в публікації \"%s\" не існує" -#: catalog/objectaddress.c:1986 +#: catalog/objectaddress.c:1948 #, c-format msgid "publication schema \"%s\" in publication \"%s\" does not exist" msgstr "схема публікації \"%s\" в публікації \"%s\" не існує" -#: catalog/objectaddress.c:2044 +#: catalog/objectaddress.c:2006 #, c-format msgid "unrecognized default ACL object type \"%c\"" msgstr "нерозпізнаний тип об'єкта ACL за замовчуванням \"%c\"" -#: catalog/objectaddress.c:2045 +#: catalog/objectaddress.c:2007 #, c-format msgid "Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." msgstr "Припустимі типи об'єктів: \"%c\", \"%c\", \"%c\", \"%c\", \"%c\"." -#: catalog/objectaddress.c:2096 +#: catalog/objectaddress.c:2058 #, c-format msgid "default ACL for user \"%s\" in schema \"%s\" on %s does not exist" msgstr "ACL за замовчуванням для користувача \"%s\" в схемі \"%s\" для об'єкту %s не існує" -#: catalog/objectaddress.c:2101 +#: catalog/objectaddress.c:2063 #, c-format msgid "default ACL for user \"%s\" on %s does not exist" msgstr "ACL за замовчуванням для користувача \"%s\" і для об'єкту %s не існує" -#: catalog/objectaddress.c:2127 catalog/objectaddress.c:2184 -#: catalog/objectaddress.c:2239 +#: catalog/objectaddress.c:2089 catalog/objectaddress.c:2146 +#: catalog/objectaddress.c:2201 #, c-format msgid "name or argument lists may not contain nulls" msgstr "списки імен та аргументів не повинні містити Null" -#: catalog/objectaddress.c:2161 +#: catalog/objectaddress.c:2123 #, c-format msgid "unsupported object type \"%s\"" msgstr "непідтримуваний тип об'єкта \"%s\"" -#: catalog/objectaddress.c:2180 catalog/objectaddress.c:2197 -#: catalog/objectaddress.c:2262 catalog/objectaddress.c:2346 +#: catalog/objectaddress.c:2142 catalog/objectaddress.c:2159 +#: catalog/objectaddress.c:2224 catalog/objectaddress.c:2308 #, c-format msgid "name list length must be exactly %d" msgstr "довжина списку імен повинна бути точно %d" -#: catalog/objectaddress.c:2201 +#: catalog/objectaddress.c:2163 #, c-format msgid "large object OID may not be null" msgstr "OID великого об'єкта не повинно бути нулем" -#: catalog/objectaddress.c:2210 catalog/objectaddress.c:2280 -#: catalog/objectaddress.c:2287 +#: catalog/objectaddress.c:2172 catalog/objectaddress.c:2242 +#: catalog/objectaddress.c:2249 #, c-format msgid "name list length must be at least %d" msgstr "довжина списку імен повинна бути щонайменше %d" -#: catalog/objectaddress.c:2273 catalog/objectaddress.c:2294 +#: catalog/objectaddress.c:2235 catalog/objectaddress.c:2256 #, c-format msgid "argument list length must be exactly %d" msgstr "довжина списку аргументів повинна бути точно %d" -#: catalog/objectaddress.c:2508 libpq/be-fsstubs.c:329 +#: catalog/objectaddress.c:2470 libpq/be-fsstubs.c:329 #, c-format msgid "must be owner of large object %u" msgstr "треба бути власником великого об'єкта %u" -#: catalog/objectaddress.c:2523 commands/functioncmds.c:1561 +#: catalog/objectaddress.c:2485 commands/functioncmds.c:1560 #, c-format msgid "must be owner of type %s or type %s" msgstr "треба бути власником типу %s або типу %s" -#: catalog/objectaddress.c:2550 catalog/objectaddress.c:2559 -#: catalog/objectaddress.c:2565 +#: catalog/objectaddress.c:2512 catalog/objectaddress.c:2521 +#: catalog/objectaddress.c:2527 #, c-format msgid "permission denied" msgstr "немає доступу" -#: catalog/objectaddress.c:2551 catalog/objectaddress.c:2560 +#: catalog/objectaddress.c:2513 catalog/objectaddress.c:2522 #, c-format msgid "The current user must have the %s attribute." msgstr "Поточний користувач повинен мати атрибут %s." -#: catalog/objectaddress.c:2566 +#: catalog/objectaddress.c:2528 #, c-format msgid "The current user must have the %s option on role \"%s\"." msgstr "Поточний користувач повинен мати параметр %s для ролі \"%s\"." -#: catalog/objectaddress.c:2580 +#: catalog/objectaddress.c:2542 #, c-format msgid "must be superuser" msgstr "треба бути суперкористувачем" -#: catalog/objectaddress.c:2649 +#: catalog/objectaddress.c:2611 #, c-format msgid "unrecognized object type \"%s\"" msgstr "нерозпізнаний тип об'єкту \"%s\"" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:2941 +#: catalog/objectaddress.c:2903 #, c-format msgid "column %s of %s" msgstr "стовпець %s з %s" -#: catalog/objectaddress.c:2956 +#: catalog/objectaddress.c:2918 #, c-format msgid "function %s" msgstr "функція %s" -#: catalog/objectaddress.c:2969 +#: catalog/objectaddress.c:2931 #, c-format msgid "type %s" msgstr "тип %s" -#: catalog/objectaddress.c:3006 +#: catalog/objectaddress.c:2968 #, c-format msgid "cast from %s to %s" msgstr "приведення від %s до %s" -#: catalog/objectaddress.c:3039 +#: catalog/objectaddress.c:3001 #, c-format msgid "collation %s" msgstr "сортування %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3070 +#: catalog/objectaddress.c:3032 #, c-format msgid "constraint %s on %s" msgstr "обмеження %s на %s" -#: catalog/objectaddress.c:3076 +#: catalog/objectaddress.c:3038 #, c-format msgid "constraint %s" msgstr "обмеження %s" -#: catalog/objectaddress.c:3108 +#: catalog/objectaddress.c:3070 #, c-format msgid "conversion %s" msgstr "перетворення %s" #. translator: %s is typically "column %s of table %s" -#: catalog/objectaddress.c:3130 +#: catalog/objectaddress.c:3092 #, c-format msgid "default value for %s" msgstr "значення за замовчуванням для %s" -#: catalog/objectaddress.c:3141 +#: catalog/objectaddress.c:3103 #, c-format msgid "language %s" msgstr "мова %s" -#: catalog/objectaddress.c:3149 +#: catalog/objectaddress.c:3111 #, c-format msgid "large object %u" msgstr "великий об'єкт %u" -#: catalog/objectaddress.c:3162 +#: catalog/objectaddress.c:3124 #, c-format msgid "operator %s" msgstr "оператор %s" -#: catalog/objectaddress.c:3199 +#: catalog/objectaddress.c:3161 #, c-format msgid "operator class %s for access method %s" msgstr "клас операторів %s для методу доступу %s" -#: catalog/objectaddress.c:3227 +#: catalog/objectaddress.c:3189 #, c-format msgid "access method %s" msgstr "метод доступу %s" @@ -5159,7 +5474,7 @@ msgstr "метод доступу %s" #. first two %s's are data type names, the third %s is the #. description of the operator family, and the last %s is the #. textual form of the operator with arguments. -#: catalog/objectaddress.c:3276 +#: catalog/objectaddress.c:3238 #, c-format msgid "operator %d (%s, %s) of %s: %s" msgstr "оператор %d (%s, %s) з %s: %s" @@ -5168,236 +5483,236 @@ msgstr "оператор %d (%s, %s) з %s: %s" #. are data type names, the third %s is the description of the #. operator family, and the last %s is the textual form of the #. function with arguments. -#: catalog/objectaddress.c:3333 +#: catalog/objectaddress.c:3295 #, c-format msgid "function %d (%s, %s) of %s: %s" msgstr "функція %d (%s, %s) з %s: %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3385 +#: catalog/objectaddress.c:3347 #, c-format msgid "rule %s on %s" msgstr "правило %s на %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3431 +#: catalog/objectaddress.c:3393 #, c-format msgid "trigger %s on %s" msgstr "тригер %s на %s" -#: catalog/objectaddress.c:3451 +#: catalog/objectaddress.c:3413 #, c-format msgid "schema %s" msgstr "схема %s" -#: catalog/objectaddress.c:3479 +#: catalog/objectaddress.c:3441 #, c-format msgid "statistics object %s" msgstr "об'єкт статистики %s" -#: catalog/objectaddress.c:3510 +#: catalog/objectaddress.c:3472 #, c-format msgid "text search parser %s" msgstr "парсер текстового пошуку %s" -#: catalog/objectaddress.c:3541 +#: catalog/objectaddress.c:3503 #, c-format msgid "text search dictionary %s" msgstr "словник текстового пошуку %s" -#: catalog/objectaddress.c:3572 +#: catalog/objectaddress.c:3534 #, c-format msgid "text search template %s" msgstr "шаблон текстового пошуку %s" -#: catalog/objectaddress.c:3603 +#: catalog/objectaddress.c:3565 #, c-format msgid "text search configuration %s" msgstr "конфігурація текстового пошуку %s" -#: catalog/objectaddress.c:3616 +#: catalog/objectaddress.c:3578 #, c-format msgid "role %s" msgstr "роль %s" -#: catalog/objectaddress.c:3653 catalog/objectaddress.c:5505 +#: catalog/objectaddress.c:3615 catalog/objectaddress.c:5464 #, c-format msgid "membership of role %s in role %s" msgstr "членство ролі %s в ролі %s" -#: catalog/objectaddress.c:3674 +#: catalog/objectaddress.c:3636 #, c-format msgid "database %s" msgstr "база даних %s" -#: catalog/objectaddress.c:3690 +#: catalog/objectaddress.c:3652 #, c-format msgid "tablespace %s" msgstr "табличний простір %s" -#: catalog/objectaddress.c:3701 +#: catalog/objectaddress.c:3663 #, c-format msgid "foreign-data wrapper %s" msgstr "джерело сторонніх даних %s" -#: catalog/objectaddress.c:3711 +#: catalog/objectaddress.c:3673 #, c-format msgid "server %s" msgstr "сервер %s" -#: catalog/objectaddress.c:3744 +#: catalog/objectaddress.c:3706 #, c-format msgid "user mapping for %s on server %s" msgstr "зіставлення користувача для %s на сервері %s" -#: catalog/objectaddress.c:3796 +#: catalog/objectaddress.c:3758 #, c-format msgid "default privileges on new relations belonging to role %s in schema %s" msgstr "права за замовчуванням для нових відношень, що належать ролі %s в схемі %s" -#: catalog/objectaddress.c:3800 +#: catalog/objectaddress.c:3762 #, c-format msgid "default privileges on new relations belonging to role %s" msgstr "права за замовчуванням для нових відношень, що належать ролі %s" -#: catalog/objectaddress.c:3806 +#: catalog/objectaddress.c:3768 #, c-format msgid "default privileges on new sequences belonging to role %s in schema %s" msgstr "права за замовчуванням для нових послідовностей, що належать ролі %s в схемі %s" -#: catalog/objectaddress.c:3810 +#: catalog/objectaddress.c:3772 #, c-format msgid "default privileges on new sequences belonging to role %s" msgstr "права за замовчуванням для нових послідовностей, що належать ролі %s" -#: catalog/objectaddress.c:3816 +#: catalog/objectaddress.c:3778 #, c-format msgid "default privileges on new functions belonging to role %s in schema %s" msgstr "права за замовчуванням для нових функцій, що належать ролі %s в схемі %s" -#: catalog/objectaddress.c:3820 +#: catalog/objectaddress.c:3782 #, c-format msgid "default privileges on new functions belonging to role %s" msgstr "права за замовчуванням для нових функцій, що належать ролі %s" -#: catalog/objectaddress.c:3826 +#: catalog/objectaddress.c:3788 #, c-format msgid "default privileges on new types belonging to role %s in schema %s" msgstr "права за замовчуванням для нових типів, що належать ролі %s в схемі %s" -#: catalog/objectaddress.c:3830 +#: catalog/objectaddress.c:3792 #, c-format msgid "default privileges on new types belonging to role %s" msgstr "права за замовчуванням для нових типів, що належать ролі %s" -#: catalog/objectaddress.c:3836 +#: catalog/objectaddress.c:3798 #, c-format msgid "default privileges on new schemas belonging to role %s" msgstr "права за замовчуванням для нових схем, що належать ролі %s" -#: catalog/objectaddress.c:3843 +#: catalog/objectaddress.c:3805 #, c-format msgid "default privileges belonging to role %s in schema %s" msgstr "права за замовчуванням, що належать ролі %s в схемі %s" -#: catalog/objectaddress.c:3847 +#: catalog/objectaddress.c:3809 #, c-format msgid "default privileges belonging to role %s" msgstr "права за замовчуванням належать ролі %s" -#: catalog/objectaddress.c:3869 +#: catalog/objectaddress.c:3831 #, c-format msgid "extension %s" msgstr "розширення %s" -#: catalog/objectaddress.c:3886 +#: catalog/objectaddress.c:3848 #, c-format msgid "event trigger %s" msgstr "тригер подій %s" -#: catalog/objectaddress.c:3910 +#: catalog/objectaddress.c:3872 #, c-format msgid "parameter %s" msgstr "параметр %s" #. translator: second %s is, e.g., "table %s" -#: catalog/objectaddress.c:3953 +#: catalog/objectaddress.c:3915 #, c-format msgid "policy %s on %s" msgstr "політика %s на %s" -#: catalog/objectaddress.c:3967 +#: catalog/objectaddress.c:3929 #, c-format msgid "publication %s" msgstr "публікація %s" -#: catalog/objectaddress.c:3980 +#: catalog/objectaddress.c:3942 #, c-format msgid "publication of schema %s in publication %s" msgstr "публікація схеми %s в публікації %s" #. translator: first %s is, e.g., "table %s" -#: catalog/objectaddress.c:4011 +#: catalog/objectaddress.c:3973 #, c-format msgid "publication of %s in publication %s" msgstr "відношення публікації %s в публікації %s" -#: catalog/objectaddress.c:4024 +#: catalog/objectaddress.c:3986 #, c-format msgid "subscription %s" msgstr "підписка %s" -#: catalog/objectaddress.c:4045 +#: catalog/objectaddress.c:4007 #, c-format msgid "transform for %s language %s" msgstr "трансформація для %s мови %s" -#: catalog/objectaddress.c:4116 +#: catalog/objectaddress.c:4076 #, c-format msgid "table %s" msgstr "таблиця %s" -#: catalog/objectaddress.c:4121 +#: catalog/objectaddress.c:4081 #, c-format msgid "index %s" msgstr "індекс %s" -#: catalog/objectaddress.c:4125 +#: catalog/objectaddress.c:4085 #, c-format msgid "sequence %s" msgstr "послідовність %s" -#: catalog/objectaddress.c:4129 +#: catalog/objectaddress.c:4089 #, c-format msgid "toast table %s" msgstr "таблиця toast %s" -#: catalog/objectaddress.c:4133 +#: catalog/objectaddress.c:4093 #, c-format msgid "view %s" msgstr "подання %s" -#: catalog/objectaddress.c:4137 +#: catalog/objectaddress.c:4097 #, c-format msgid "materialized view %s" msgstr "матеріалізоване подання %s" -#: catalog/objectaddress.c:4141 +#: catalog/objectaddress.c:4101 #, c-format msgid "composite type %s" msgstr "складений тип %s" -#: catalog/objectaddress.c:4145 +#: catalog/objectaddress.c:4105 #, c-format msgid "foreign table %s" msgstr "зовнішня таблиця %s" -#: catalog/objectaddress.c:4150 +#: catalog/objectaddress.c:4110 #, c-format msgid "relation %s" msgstr "відношення %s" -#: catalog/objectaddress.c:4191 +#: catalog/objectaddress.c:4151 #, c-format msgid "operator family %s for access method %s" msgstr "сімейство операторів %s для методу доступу %s" @@ -5441,7 +5756,7 @@ msgstr "не можна пропустити початкове значення msgid "return type of inverse transition function %s is not %s" msgstr "інвертована функція переходу %s повинна повертати тип %s" -#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:3009 +#: catalog/pg_aggregate.c:352 executor/nodeWindowAgg.c:2992 #, c-format msgid "strictness of aggregate's forward and inverse transition functions must match" msgstr "пряма й інвертована функції переходу агрегату повинні мати однакову суворість" @@ -5456,7 +5771,7 @@ msgstr "фінальна функція з додатковими аргумен msgid "return type of combine function %s is not %s" msgstr "комбінуюча функція %s повинна повертати тип %s" -#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3903 +#: catalog/pg_aggregate.c:439 executor/nodeAgg.c:3902 #, c-format msgid "combine function with transition type %s must not be declared STRICT" msgstr "комбінуюча функція з перехідним типом %s не повинна оголошуватись як сувора (STRICT)" @@ -5471,12 +5786,12 @@ msgstr "функція серіалізації %s повинна поверта msgid "return type of deserialization function %s is not %s" msgstr "функція десеріалізації %s повинна повертати тип %s" -#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:191 catalog/pg_proc.c:225 +#: catalog/pg_aggregate.c:498 catalog/pg_proc.c:189 catalog/pg_proc.c:223 #, c-format msgid "cannot determine result data type" msgstr "не вдалося визначити тип результату" -#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:204 catalog/pg_proc.c:233 +#: catalog/pg_aggregate.c:513 catalog/pg_proc.c:202 catalog/pg_proc.c:231 #, c-format msgid "unsafe use of pseudo-type \"internal\"" msgstr "небезпечне використання псевдотипу (pseudo-type) \"internal\"" @@ -5491,7 +5806,7 @@ msgstr "реалізація рухомого агрегату повертає msgid "sort operator can only be specified for single-argument aggregates" msgstr "оператора сортування можна вказати лише для агрегатних функцій з одним аргументом" -#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:386 +#: catalog/pg_aggregate.c:706 catalog/pg_proc.c:384 #, c-format msgid "cannot change routine kind" msgstr "неможливо змінити тип підпрограми" @@ -5516,13 +5831,13 @@ msgstr "\"%s\" є агрегатом для гіпотетичних набор msgid "cannot change number of direct arguments of an aggregate function" msgstr "змінити кількість прямих аргументів агрегатної функції не можна" -#: catalog/pg_aggregate.c:858 commands/functioncmds.c:691 -#: commands/typecmds.c:1975 commands/typecmds.c:2021 commands/typecmds.c:2073 -#: commands/typecmds.c:2110 commands/typecmds.c:2144 commands/typecmds.c:2178 -#: commands/typecmds.c:2212 commands/typecmds.c:2241 commands/typecmds.c:2328 -#: commands/typecmds.c:2370 parser/parse_func.c:417 parser/parse_func.c:448 +#: catalog/pg_aggregate.c:858 commands/functioncmds.c:686 +#: commands/typecmds.c:1985 commands/typecmds.c:2031 commands/typecmds.c:2083 +#: commands/typecmds.c:2120 commands/typecmds.c:2154 commands/typecmds.c:2188 +#: commands/typecmds.c:2222 commands/typecmds.c:2251 commands/typecmds.c:2338 +#: commands/typecmds.c:2380 parser/parse_func.c:417 parser/parse_func.c:448 #: parser/parse_func.c:475 parser/parse_func.c:489 parser/parse_func.c:611 -#: parser/parse_func.c:631 parser/parse_func.c:2171 parser/parse_func.c:2444 +#: parser/parse_func.c:631 parser/parse_func.c:2172 parser/parse_func.c:2445 #, c-format msgid "function %s does not exist" msgstr "функції %s не існує" @@ -5597,133 +5912,133 @@ msgstr "Ця операція не підтримується для секці msgid "This operation is not supported for partitioned indexes." msgstr "Ця операція не підтримується для секціонованих індексів." -#: catalog/pg_collation.c:102 catalog/pg_collation.c:160 +#: catalog/pg_collation.c:101 catalog/pg_collation.c:159 #, c-format msgid "collation \"%s\" already exists, skipping" msgstr "сортування \"%s\" вже існує, пропускаємо" -#: catalog/pg_collation.c:104 +#: catalog/pg_collation.c:103 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists, skipping" msgstr "правило сортування \"%s \" для кодування \"%s\" вже існує, пропускаємо" -#: catalog/pg_collation.c:112 catalog/pg_collation.c:167 +#: catalog/pg_collation.c:111 catalog/pg_collation.c:166 #, c-format msgid "collation \"%s\" already exists" msgstr "правило сортування \"%s\" вже існує" -#: catalog/pg_collation.c:114 +#: catalog/pg_collation.c:113 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists" msgstr "правило сортування \"%s \" для кодування \"%s\" вже існує" -#: catalog/pg_constraint.c:690 +#: catalog/pg_constraint.c:732 #, c-format msgid "constraint \"%s\" for domain %s already exists" msgstr "обмеження \"%s\" для домену %s вже існує" -#: catalog/pg_constraint.c:890 catalog/pg_constraint.c:983 +#: catalog/pg_constraint.c:932 catalog/pg_constraint.c:1025 #, c-format msgid "constraint \"%s\" for table \"%s\" does not exist" msgstr "індексу \"%s\" для таблиці \"%s\" не існує" -#: catalog/pg_constraint.c:1083 +#: catalog/pg_constraint.c:1125 #, c-format msgid "constraint \"%s\" for domain %s does not exist" msgstr "обмеження \"%s\" для домену \"%s\" не існує" -#: catalog/pg_conversion.c:67 +#: catalog/pg_conversion.c:64 #, c-format msgid "conversion \"%s\" already exists" msgstr "перетворення \"%s\" вже існує" -#: catalog/pg_conversion.c:80 +#: catalog/pg_conversion.c:77 #, c-format msgid "default conversion for %s to %s already exists" msgstr "перетворення за замовчуванням від %s до %s вже існує" -#: catalog/pg_depend.c:222 commands/extension.c:3368 +#: catalog/pg_depend.c:224 commands/extension.c:3397 #, c-format msgid "%s is already a member of extension \"%s\"" msgstr "%s вже є членом розширення \"%s\"" -#: catalog/pg_depend.c:229 catalog/pg_depend.c:280 commands/extension.c:3408 +#: catalog/pg_depend.c:231 catalog/pg_depend.c:282 commands/extension.c:3437 #, c-format msgid "%s is not a member of extension \"%s\"" msgstr "%s не є членом розширення \"%s\"" -#: catalog/pg_depend.c:232 +#: catalog/pg_depend.c:234 #, c-format msgid "An extension is not allowed to replace an object that it does not own." msgstr "Розширенню не дозволяється замінювати об'єкт, який йому не належить." -#: catalog/pg_depend.c:283 +#: catalog/pg_depend.c:285 #, c-format msgid "An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns." msgstr "Розширення може використовувати лише CREATE ... IF NOT EXISTS, щоб пропустити створення об'єкту, якщо конфліктуючий об'єкт уже належить йому." -#: catalog/pg_depend.c:646 +#: catalog/pg_depend.c:648 #, c-format msgid "cannot remove dependency on %s because it is a system object" msgstr "неможливо видалити залежність від об'єкта %s, тому що це системний об'єкт" -#: catalog/pg_enum.c:137 catalog/pg_enum.c:259 catalog/pg_enum.c:554 +#: catalog/pg_enum.c:175 catalog/pg_enum.c:314 catalog/pg_enum.c:624 #, c-format msgid "invalid enum label \"%s\"" msgstr "неприпустима мітка перераховування \"%s\"" -#: catalog/pg_enum.c:138 catalog/pg_enum.c:260 catalog/pg_enum.c:555 +#: catalog/pg_enum.c:176 catalog/pg_enum.c:315 catalog/pg_enum.c:625 #, c-format msgid "Labels must be %d bytes or less." msgstr "Мітки повинні бути %d байт або менше." -#: catalog/pg_enum.c:288 +#: catalog/pg_enum.c:343 #, c-format msgid "enum label \"%s\" already exists, skipping" msgstr "мітка перераховування \"%s\" вже існує, пропускаємо" -#: catalog/pg_enum.c:295 catalog/pg_enum.c:598 +#: catalog/pg_enum.c:350 catalog/pg_enum.c:668 #, c-format msgid "enum label \"%s\" already exists" msgstr "мітка перераховування \"%s\" вже існує" -#: catalog/pg_enum.c:350 catalog/pg_enum.c:593 +#: catalog/pg_enum.c:405 catalog/pg_enum.c:663 #, c-format msgid "\"%s\" is not an existing enum label" msgstr "\"%s\" не є існуючою міткою перераховування" -#: catalog/pg_enum.c:408 +#: catalog/pg_enum.c:463 #, c-format msgid "pg_enum OID value not set when in binary upgrade mode" msgstr "значення OID в pg_enum не встановлено в режимі двійкового оновлення" -#: catalog/pg_enum.c:418 +#: catalog/pg_enum.c:473 #, c-format msgid "ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade" msgstr "Конструкція ALTER TYPE ADD BEFORE/AFTER несумісна з двійковим оновленням даних" -#: catalog/pg_inherits.c:593 +#: catalog/pg_inherits.c:592 #, c-format msgid "cannot detach partition \"%s\"" msgstr "не можна відключити розділ \"%s\"" -#: catalog/pg_inherits.c:595 +#: catalog/pg_inherits.c:594 #, c-format msgid "The partition is being detached concurrently or has an unfinished detach." msgstr "Розділ відключається одночасно або має незакінчене відключення." -#: catalog/pg_inherits.c:596 commands/tablecmds.c:4583 -#: commands/tablecmds.c:15478 +#: catalog/pg_inherits.c:595 commands/tablecmds.c:4777 +#: commands/tablecmds.c:16050 #, c-format msgid "Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation." msgstr "Використайте ALTER TABLE ... DETACH PARTITION ... FINALIZE щоб завершити очікувану операцію відключення." -#: catalog/pg_inherits.c:600 +#: catalog/pg_inherits.c:599 #, c-format msgid "cannot complete detaching partition \"%s\"" msgstr "не можна завершити відключення розділу \"%s\"" -#: catalog/pg_inherits.c:602 +#: catalog/pg_inherits.c:601 #, c-format msgid "There's no pending concurrent detach." msgstr "Немає жодного очікуючого паралельного відключення." @@ -5733,77 +6048,92 @@ msgstr "Немає жодного очікуючого паралельного msgid "schema \"%s\" already exists" msgstr "схема \"%s\" вже існує" -#: catalog/pg_operator.c:219 catalog/pg_operator.c:361 +#: catalog/pg_operator.c:213 catalog/pg_operator.c:355 #, c-format msgid "\"%s\" is not a valid operator name" msgstr "\"%s\" не є коректним оператором" -#: catalog/pg_operator.c:370 +#: catalog/pg_operator.c:379 +#, c-format +msgid "operator %s already exists" +msgstr "оператор %s вже існує" + +#: catalog/pg_operator.c:445 commands/operatorcmds.c:600 +#, c-format +msgid "operator cannot be its own negator" +msgstr "оператор не може бути власним запереченням" + +#: catalog/pg_operator.c:572 #, c-format msgid "only binary operators can have commutators" msgstr "(commutators) можна визначити лише для бінарних операторів" -#: catalog/pg_operator.c:374 commands/operatorcmds.c:509 +#: catalog/pg_operator.c:576 #, c-format msgid "only binary operators can have join selectivity" msgstr "функцію оцінки з'єднання можливо визначити лише для бінарних операторів" -#: catalog/pg_operator.c:378 +#: catalog/pg_operator.c:580 #, c-format msgid "only binary operators can merge join" msgstr "підтримку з'єднання злиттям можливо позначити лише для бінарних операторів" -#: catalog/pg_operator.c:382 +#: catalog/pg_operator.c:584 #, c-format msgid "only binary operators can hash" msgstr "підтримка хешу можливо позначити лише для бінарних операторів" -#: catalog/pg_operator.c:393 +#: catalog/pg_operator.c:593 #, c-format msgid "only boolean operators can have negators" msgstr "зворотню операцію можливо визначити лише для логічних операторів" -#: catalog/pg_operator.c:397 commands/operatorcmds.c:517 +#: catalog/pg_operator.c:597 #, c-format msgid "only boolean operators can have restriction selectivity" msgstr "функцію оцінки обмеження можливо визначити лише для логічних операторів" -#: catalog/pg_operator.c:401 commands/operatorcmds.c:521 +#: catalog/pg_operator.c:601 #, c-format msgid "only boolean operators can have join selectivity" msgstr "функцію оцінки з'єднання можливо визначити лише для логічних операторів" -#: catalog/pg_operator.c:405 +#: catalog/pg_operator.c:605 #, c-format msgid "only boolean operators can merge join" msgstr "підтримку з'єднання злиттям можливо позначити лише для логічних операторів" -#: catalog/pg_operator.c:409 +#: catalog/pg_operator.c:609 #, c-format msgid "only boolean operators can hash" msgstr "підтримку хешу можливо позначити лише для логічних операторів" -#: catalog/pg_operator.c:421 +#: catalog/pg_operator.c:739 #, c-format -msgid "operator %s already exists" -msgstr "оператор %s вже існує" +msgid "commutator operator %s is already the commutator of operator %s" +msgstr "оператор комутатора %s вже є комутатором оператора %s" -#: catalog/pg_operator.c:621 +#: catalog/pg_operator.c:744 #, c-format -msgid "operator cannot be its own negator or sort operator" -msgstr "оператор не може бути зворотнім до себе або власним оператором сортування" +msgid "commutator operator %s is already the commutator of operator %u" +msgstr "оператор комутатора %s вже є комутатором оператора %u" -#: catalog/pg_parameter_acl.c:53 +#: catalog/pg_operator.c:807 #, c-format -msgid "parameter ACL \"%s\" does not exist" -msgstr "параметр ACL \"%s\" не існує" +msgid "negator operator %s is already the negator of operator %s" +msgstr "оператор заперечення %s вже є запереченням оператора %s" -#: catalog/pg_parameter_acl.c:88 +#: catalog/pg_operator.c:812 #, c-format -msgid "invalid parameter name \"%s\"" -msgstr "неприпустима назва параметру \"%s\"" +msgid "negator operator %s is already the negator of operator %u" +msgstr "заперечний оператор %s вже є запереченням оператора %u" + +#: catalog/pg_parameter_acl.c:50 +#, c-format +msgid "parameter ACL \"%s\" does not exist" +msgstr "параметр ACL \"%s\" не існує" -#: catalog/pg_proc.c:132 parser/parse_func.c:2233 +#: catalog/pg_proc.c:130 parser/parse_func.c:2234 #, c-format msgid "functions cannot have more than %d argument" msgid_plural "functions cannot have more than %d arguments" @@ -5812,37 +6142,37 @@ msgstr[1] "функції не можуть мати більше %d аргум msgstr[2] "функції не можуть мати більше %d аргументів" msgstr[3] "функції не можуть мати більше %d аргументів" -#: catalog/pg_proc.c:376 +#: catalog/pg_proc.c:374 #, c-format msgid "function \"%s\" already exists with same argument types" msgstr "функція \"%s\" з аргументами таких типів вже існує" -#: catalog/pg_proc.c:388 +#: catalog/pg_proc.c:386 #, c-format msgid "\"%s\" is an aggregate function." msgstr "\"%s\" є функцією агрегату." -#: catalog/pg_proc.c:390 +#: catalog/pg_proc.c:388 #, c-format msgid "\"%s\" is a function." msgstr "\"%s\" є функцією." -#: catalog/pg_proc.c:392 +#: catalog/pg_proc.c:390 #, c-format msgid "\"%s\" is a procedure." msgstr "\"%s\" є процедурою." -#: catalog/pg_proc.c:394 +#: catalog/pg_proc.c:392 #, c-format msgid "\"%s\" is a window function." msgstr "\"%s\" є функцією вікна." -#: catalog/pg_proc.c:414 +#: catalog/pg_proc.c:412 #, c-format msgid "cannot change whether a procedure has output parameters" msgstr "неможливо визначити вихідні параметри для процедури" -#: catalog/pg_proc.c:415 catalog/pg_proc.c:445 +#: catalog/pg_proc.c:413 catalog/pg_proc.c:443 #, c-format msgid "cannot change return type of existing function" msgstr "неможливо змінити тип повернення існуючої функції" @@ -5851,171 +6181,170 @@ msgstr "неможливо змінити тип повернення існую #. AGGREGATE #. #. translator: first %s is DROP FUNCTION or DROP PROCEDURE -#: catalog/pg_proc.c:421 catalog/pg_proc.c:448 catalog/pg_proc.c:493 -#: catalog/pg_proc.c:519 catalog/pg_proc.c:543 +#: catalog/pg_proc.c:419 catalog/pg_proc.c:446 catalog/pg_proc.c:491 +#: catalog/pg_proc.c:517 catalog/pg_proc.c:541 #, c-format msgid "Use %s %s first." msgstr "Використайте %s %s спочатку." -#: catalog/pg_proc.c:446 +#: catalog/pg_proc.c:444 #, c-format msgid "Row type defined by OUT parameters is different." msgstr "Параметри OUT визначають другий тип рядку." -#: catalog/pg_proc.c:490 +#: catalog/pg_proc.c:488 #, c-format msgid "cannot change name of input parameter \"%s\"" msgstr "неможливо змінити ім'я вхідного параметру \"%s\"" -#: catalog/pg_proc.c:517 +#: catalog/pg_proc.c:515 #, c-format msgid "cannot remove parameter defaults from existing function" msgstr "неможливо прибрати параметр за замовчуванням з існуючої функції" -#: catalog/pg_proc.c:541 +#: catalog/pg_proc.c:539 #, c-format msgid "cannot change data type of existing parameter default value" msgstr "неможливо змінити тип даних для існуючого значення параметру за замовчуванням" -#: catalog/pg_proc.c:752 +#: catalog/pg_proc.c:750 #, c-format msgid "there is no built-in function named \"%s\"" msgstr "немає вбудованої функції \"%s\"" -#: catalog/pg_proc.c:845 +#: catalog/pg_proc.c:843 #, c-format msgid "SQL functions cannot return type %s" msgstr "Функції SQL не можуть повернути тип %s" -#: catalog/pg_proc.c:860 +#: catalog/pg_proc.c:858 #, c-format msgid "SQL functions cannot have arguments of type %s" msgstr "функції SQL не можуть мати аргументи типу %s" -#: catalog/pg_proc.c:987 executor/functions.c:1466 +#: catalog/pg_proc.c:986 executor/functions.c:1468 #, c-format msgid "SQL function \"%s\"" msgstr "Функція SQL \"%s\"" -#: catalog/pg_publication.c:71 catalog/pg_publication.c:79 -#: catalog/pg_publication.c:87 catalog/pg_publication.c:93 +#: catalog/pg_publication.c:66 catalog/pg_publication.c:74 +#: catalog/pg_publication.c:82 catalog/pg_publication.c:88 #, c-format msgid "cannot add relation \"%s\" to publication" msgstr "не можна додати відношення \"%s\" до публікації" -#: catalog/pg_publication.c:81 +#: catalog/pg_publication.c:76 #, c-format msgid "This operation is not supported for system tables." msgstr "Ця операція не підтримується для системних таблиць." -#: catalog/pg_publication.c:89 +#: catalog/pg_publication.c:84 #, c-format msgid "This operation is not supported for temporary tables." msgstr "Ця операція не підтримується для тимчасових таблиць." -#: catalog/pg_publication.c:95 +#: catalog/pg_publication.c:90 #, c-format msgid "This operation is not supported for unlogged tables." msgstr "Ця операція не підтримується для таблиць без журналювання." -#: catalog/pg_publication.c:109 catalog/pg_publication.c:117 +#: catalog/pg_publication.c:104 catalog/pg_publication.c:112 #, c-format msgid "cannot add schema \"%s\" to publication" msgstr "не можна додати схему \"%s\" до публікації" -#: catalog/pg_publication.c:111 +#: catalog/pg_publication.c:106 #, c-format msgid "This operation is not supported for system schemas." msgstr "Ця операція не підтримується для системних схем." -#: catalog/pg_publication.c:119 +#: catalog/pg_publication.c:114 #, c-format msgid "Temporary schemas cannot be replicated." msgstr "Тимчасові схеми не можуть бути репліковані." -#: catalog/pg_publication.c:397 +#: catalog/pg_publication.c:392 #, c-format msgid "relation \"%s\" is already member of publication \"%s\"" msgstr "відношення \"%s\" вже є членом публікації \"%s\"" -#: catalog/pg_publication.c:539 +#: catalog/pg_publication.c:534 #, c-format msgid "cannot use system column \"%s\" in publication column list" msgstr "не можна використати системний стовпець \"%s\" у списку стовпців публікації" -#: catalog/pg_publication.c:545 +#: catalog/pg_publication.c:540 #, c-format msgid "cannot use generated column \"%s\" in publication column list" msgstr "не можна використати згенерований стовпець \"%s\" у списку стовпців публікації" -#: catalog/pg_publication.c:551 +#: catalog/pg_publication.c:546 #, c-format msgid "duplicate column \"%s\" in publication column list" msgstr "дуплікат стовпця \"%s\" в списку стовпців публікації" -#: catalog/pg_publication.c:641 +#: catalog/pg_publication.c:636 #, c-format msgid "schema \"%s\" is already member of publication \"%s\"" msgstr "схема \"%s\" вже є членом публікації \"%s\"" -#: catalog/pg_shdepend.c:830 +#: catalog/pg_shdepend.c:875 #, c-format -msgid "" -"\n" +msgid "\n" "and objects in %d other database (see server log for list)" -msgid_plural "" -"\n" +msgid_plural "\n" "and objects in %d other databases (see server log for list)" -msgstr[0] "" -"\n" +msgstr[0] "\n" "і об'єкти в %d іншій базі даних (див. список в протоколі сервера)" -msgstr[1] "" -"\n" +msgstr[1] "\n" "і об'єкти в %d інших базах даних (див. список в протоколі сервера)" -msgstr[2] "" -"\n" +msgstr[2] "\n" "і об'єкти в %d інших базах даних (див. список в протоколі сервера)" -msgstr[3] "" -"\n" +msgstr[3] "\n" "і об'єкти в %d інших базах даних (див. список в протоколі сервера)" -#: catalog/pg_shdepend.c:1177 +#: catalog/pg_shdepend.c:1222 #, c-format msgid "role %u was concurrently dropped" msgstr "роль %u було видалено паралельним способом" -#: catalog/pg_shdepend.c:1189 +#: catalog/pg_shdepend.c:1234 #, c-format msgid "tablespace %u was concurrently dropped" msgstr "табличний простір %u було видалено паралельним способом" -#: catalog/pg_shdepend.c:1203 +#: catalog/pg_shdepend.c:1248 #, c-format msgid "database %u was concurrently dropped" msgstr "базу даних %u було видалено паралельним способом" -#: catalog/pg_shdepend.c:1254 +#: catalog/pg_shdepend.c:1299 #, c-format msgid "owner of %s" msgstr "власник об'єкту %s" -#: catalog/pg_shdepend.c:1256 +#: catalog/pg_shdepend.c:1301 #, c-format msgid "privileges for %s" msgstr "права для %s" -#: catalog/pg_shdepend.c:1258 +#: catalog/pg_shdepend.c:1303 +#, c-format +msgid "initial privileges for %s" +msgstr "початкові права для %s" + +#: catalog/pg_shdepend.c:1305 #, c-format msgid "target of %s" msgstr "ціль %s" -#: catalog/pg_shdepend.c:1260 +#: catalog/pg_shdepend.c:1307 #, c-format msgid "tablespace for %s" msgstr "табличний простір для %s" #. translator: %s will always be "database %s" -#: catalog/pg_shdepend.c:1268 +#: catalog/pg_shdepend.c:1315 #, c-format msgid "%d object in %s" msgid_plural "%d objects in %s" @@ -6024,22 +6353,22 @@ msgstr[1] "%d об'єкти в %s" msgstr[2] "%d об'єктів у %s" msgstr[3] "%d об'єктів у %s" -#: catalog/pg_shdepend.c:1332 +#: catalog/pg_shdepend.c:1379 #, c-format msgid "cannot drop objects owned by %s because they are required by the database system" msgstr "не вдалося видалити об'єкти, що належать %s, оскільки вони потрібні системі бази даних" -#: catalog/pg_shdepend.c:1498 +#: catalog/pg_shdepend.c:1560 #, c-format msgid "cannot reassign ownership of objects owned by %s because they are required by the database system" msgstr "не вдалося змінити власника об'єктів, що належать ролі %s, тому що вони необхідні системі баз даних" -#: catalog/pg_subscription.c:424 +#: catalog/pg_subscription.c:438 #, c-format msgid "could not drop relation mapping for subscription \"%s\"" msgstr "не вдалося видалити зіставлення відношень для підписки \"%s\"" -#: catalog/pg_subscription.c:426 +#: catalog/pg_subscription.c:440 #, c-format msgid "Table synchronization for relation \"%s\" is in progress and is in state \"%c\"." msgstr "Синхронізація таблиць для відношення \"%s\" у процесі та знаходиться у стані \"%c\"." @@ -6047,227 +6376,227 @@ msgstr "Синхронізація таблиць для відношення \" #. translator: first %s is a SQL ALTER command and second %s is a #. SQL DROP command #. -#: catalog/pg_subscription.c:433 +#: catalog/pg_subscription.c:447 #, c-format msgid "Use %s to enable subscription if not already enabled or use %s to drop the subscription." msgstr "Використайте %s, щоб активувати підписку, якщо вона ще не активована, або використайте %s, щоб видалити підписку." -#: catalog/pg_type.c:134 catalog/pg_type.c:474 +#: catalog/pg_type.c:133 catalog/pg_type.c:474 #, c-format msgid "pg_type OID value not set when in binary upgrade mode" msgstr "значення OID в pg_type не задано в режимі двійкового оновлення" -#: catalog/pg_type.c:254 +#: catalog/pg_type.c:253 #, c-format msgid "invalid type internal size %d" msgstr "неприпустимий внутрішній розмір типу %d" -#: catalog/pg_type.c:270 catalog/pg_type.c:278 catalog/pg_type.c:286 -#: catalog/pg_type.c:295 +#: catalog/pg_type.c:269 catalog/pg_type.c:277 catalog/pg_type.c:285 +#: catalog/pg_type.c:294 #, c-format msgid "alignment \"%c\" is invalid for passed-by-value type of size %d" msgstr "вирівнювання \"%c\" недійсне для типу переданого за значенням розміром: %d" -#: catalog/pg_type.c:302 +#: catalog/pg_type.c:301 #, c-format msgid "internal size %d is invalid for passed-by-value type" msgstr "внутрішній розмір %d недійсний для типу, переданого за значенням" -#: catalog/pg_type.c:312 catalog/pg_type.c:318 +#: catalog/pg_type.c:311 catalog/pg_type.c:317 #, c-format msgid "alignment \"%c\" is invalid for variable-length type" msgstr "вирівнювання \"%c\" недійсне для типу змінної довжини" -#: catalog/pg_type.c:326 commands/typecmds.c:4146 +#: catalog/pg_type.c:325 commands/typecmds.c:4363 #, c-format msgid "fixed-size types must have storage PLAIN" msgstr "для типів фіксованого розміру застосовується лише режим зберігання PLAIN" -#: catalog/pg_type.c:955 +#: catalog/pg_type.c:978 #, c-format msgid "Failed while creating a multirange type for type \"%s\"." msgstr "Помилка під час створення багатодіапазонного типу для типу \"%s\"." -#: catalog/pg_type.c:956 +#: catalog/pg_type.c:979 #, c-format msgid "You can manually specify a multirange type name using the \"multirange_type_name\" attribute." msgstr "Ви можете вручну вказати назву багатодіапазонного типу за допомогою атрибуту \"multirange_type_name\"." -#: catalog/storage.c:505 storage/buffer/bufmgr.c:1145 +#: catalog/storage.c:508 storage/buffer/bufmgr.c:1540 #, c-format msgid "invalid page in block %u of relation %s" msgstr "неприпустима сторінка в блоці %u відношення %s" -#: commands/aggregatecmds.c:171 +#: commands/aggregatecmds.c:167 #, c-format msgid "only ordered-set aggregates can be hypothetical" msgstr "гіпотетичними можуть бути тільки впорядковані агрегати" -#: commands/aggregatecmds.c:196 +#: commands/aggregatecmds.c:192 #, c-format msgid "aggregate attribute \"%s\" not recognized" msgstr "атрибут агрегату \"%s\" не розпізнано" -#: commands/aggregatecmds.c:206 +#: commands/aggregatecmds.c:202 #, c-format msgid "aggregate stype must be specified" msgstr "у визначенні агрегату необхідно вказати stype" -#: commands/aggregatecmds.c:210 +#: commands/aggregatecmds.c:206 #, c-format msgid "aggregate sfunc must be specified" msgstr "в визначенні агрегату потребується sfunc" -#: commands/aggregatecmds.c:222 +#: commands/aggregatecmds.c:218 #, c-format msgid "aggregate msfunc must be specified when mstype is specified" msgstr "в визначенні агрегату потребується msfunc, коли mstype визначений" -#: commands/aggregatecmds.c:226 +#: commands/aggregatecmds.c:222 #, c-format msgid "aggregate minvfunc must be specified when mstype is specified" msgstr "в визначенні агрегату потребується minvfunc, коли mstype визначений" -#: commands/aggregatecmds.c:233 +#: commands/aggregatecmds.c:229 #, c-format msgid "aggregate msfunc must not be specified without mstype" msgstr "msfunc для агрегату не повинна визначатись без mstype" -#: commands/aggregatecmds.c:237 +#: commands/aggregatecmds.c:233 #, c-format msgid "aggregate minvfunc must not be specified without mstype" msgstr "minvfunc для агрегату не повинна визначатись без mstype" -#: commands/aggregatecmds.c:241 +#: commands/aggregatecmds.c:237 #, c-format msgid "aggregate mfinalfunc must not be specified without mstype" msgstr "mfinalfunc для агрегату не повинна визначатись без mstype" -#: commands/aggregatecmds.c:245 +#: commands/aggregatecmds.c:241 #, c-format msgid "aggregate msspace must not be specified without mstype" msgstr "msspace для агрегату не повинна визначатись без mstype" -#: commands/aggregatecmds.c:249 +#: commands/aggregatecmds.c:245 #, c-format msgid "aggregate minitcond must not be specified without mstype" msgstr "minitcond для агрегату не повинна визначатись без mstype" -#: commands/aggregatecmds.c:278 +#: commands/aggregatecmds.c:274 #, c-format msgid "aggregate input type must be specified" msgstr "слід указати тип агрегату вводу" -#: commands/aggregatecmds.c:308 +#: commands/aggregatecmds.c:304 #, c-format msgid "basetype is redundant with aggregate input type specification" msgstr "в визначенні агрегату з зазначенням вхідного типу не потрібен базовий тип" -#: commands/aggregatecmds.c:351 commands/aggregatecmds.c:392 +#: commands/aggregatecmds.c:347 commands/aggregatecmds.c:388 #, c-format msgid "aggregate transition data type cannot be %s" msgstr "тип даних агрегату транзакції не може бути %s" -#: commands/aggregatecmds.c:363 +#: commands/aggregatecmds.c:359 #, c-format msgid "serialization functions may be specified only when the aggregate transition data type is %s" msgstr "функції серіалізації можуть визначатись, лише коли перехідний тип даних агрегату %s" -#: commands/aggregatecmds.c:373 +#: commands/aggregatecmds.c:369 #, c-format msgid "must specify both or neither of serialization and deserialization functions" msgstr "повинні визначатись обидві або жодна з серіалізуючих та десеріалізуючих функцій" -#: commands/aggregatecmds.c:438 commands/functioncmds.c:639 +#: commands/aggregatecmds.c:434 commands/functioncmds.c:634 #, c-format msgid "parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE" msgstr "параметр \"parallel\" має мати значення SAFE, RESTRICTED, або UNSAFE" -#: commands/aggregatecmds.c:494 +#: commands/aggregatecmds.c:490 #, c-format msgid "parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE" msgstr "параметр \"%s\" має мати значення READ_ONLY, SHAREABLE, або READ_WRITE" -#: commands/alter.c:86 commands/event_trigger.c:174 +#: commands/alter.c:82 commands/event_trigger.c:191 #, c-format msgid "event trigger \"%s\" already exists" msgstr "тригер подій \"%s\" вже існує" -#: commands/alter.c:89 commands/foreigncmds.c:593 +#: commands/alter.c:85 commands/foreigncmds.c:593 #, c-format msgid "foreign-data wrapper \"%s\" already exists" msgstr "джерело сторонніх даних \"%s\" вже існує" -#: commands/alter.c:92 commands/foreigncmds.c:884 +#: commands/alter.c:88 commands/foreigncmds.c:884 #, c-format msgid "server \"%s\" already exists" msgstr "сервер \"%s\" вже існує" -#: commands/alter.c:95 commands/proclang.c:133 +#: commands/alter.c:91 commands/proclang.c:131 #, c-format msgid "language \"%s\" already exists" msgstr "мова \"%s\" вже існує" -#: commands/alter.c:98 commands/publicationcmds.c:771 +#: commands/alter.c:94 commands/publicationcmds.c:764 #, c-format msgid "publication \"%s\" already exists" msgstr "публікація \"%s\" вже існує" -#: commands/alter.c:101 commands/subscriptioncmds.c:657 +#: commands/alter.c:97 commands/subscriptioncmds.c:669 #, c-format msgid "subscription \"%s\" already exists" msgstr "підписка \"%s\" вже існує" -#: commands/alter.c:124 +#: commands/alter.c:120 #, c-format msgid "conversion \"%s\" already exists in schema \"%s\"" msgstr "перетворення \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:128 +#: commands/alter.c:124 #, c-format msgid "statistics object \"%s\" already exists in schema \"%s\"" msgstr "об'єкт статистики \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:132 +#: commands/alter.c:128 #, c-format msgid "text search parser \"%s\" already exists in schema \"%s\"" msgstr "парсер текстового пошуку \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:136 +#: commands/alter.c:132 #, c-format msgid "text search dictionary \"%s\" already exists in schema \"%s\"" msgstr "словник текстового пошуку \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:140 +#: commands/alter.c:136 #, c-format msgid "text search template \"%s\" already exists in schema \"%s\"" msgstr "шаблон текстового пошуку \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:144 +#: commands/alter.c:140 #, c-format msgid "text search configuration \"%s\" already exists in schema \"%s\"" msgstr "конфігурація текстового пошуку \"%s\" вже існує в схемі \"%s\"" -#: commands/alter.c:217 +#: commands/alter.c:213 #, c-format msgid "must be superuser to rename %s" msgstr "перейменувати %s може тільки суперкористувач" -#: commands/alter.c:259 commands/subscriptioncmds.c:636 -#: commands/subscriptioncmds.c:1116 commands/subscriptioncmds.c:1198 -#: commands/subscriptioncmds.c:1837 +#: commands/alter.c:255 commands/subscriptioncmds.c:648 +#: commands/subscriptioncmds.c:1129 commands/subscriptioncmds.c:1212 +#: commands/subscriptioncmds.c:1918 #, c-format msgid "password_required=false is superuser-only" msgstr "password_required=false тільки для суперкористувачів" -#: commands/alter.c:260 commands/subscriptioncmds.c:637 -#: commands/subscriptioncmds.c:1117 commands/subscriptioncmds.c:1199 -#: commands/subscriptioncmds.c:1838 +#: commands/alter.c:256 commands/subscriptioncmds.c:649 +#: commands/subscriptioncmds.c:1130 commands/subscriptioncmds.c:1213 +#: commands/subscriptioncmds.c:1919 #, c-format msgid "Subscriptions with the password_required option set to false may only be created or modified by the superuser." msgstr "Підписки з налаштуванням password_required=false можуть бути створені або змінені тільки суперкористувачем." -#: commands/alter.c:775 +#: commands/alter.c:734 #, c-format msgid "must be superuser to set schema of %s" msgstr "встановити схему об'єкту %s може тільки суперкористувач" @@ -6287,8 +6616,8 @@ msgstr "Тільки суперкористувач може створити м msgid "access method \"%s\" already exists" msgstr "метод доступу \"%s\" вже існує" -#: commands/amcmds.c:154 commands/indexcmds.c:216 commands/indexcmds.c:839 -#: commands/opclasscmds.c:375 commands/opclasscmds.c:833 +#: commands/amcmds.c:154 commands/indexcmds.c:222 commands/indexcmds.c:842 +#: commands/opclasscmds.c:374 commands/opclasscmds.c:832 #, c-format msgid "access method \"%s\" does not exist" msgstr "методу доступу \"%s\" не існує" @@ -6298,114 +6627,114 @@ msgstr "методу доступу \"%s\" не існує" msgid "handler function is not specified" msgstr "функція-обробник не вказана" -#: commands/amcmds.c:264 commands/event_trigger.c:183 -#: commands/foreigncmds.c:489 commands/proclang.c:80 commands/trigger.c:709 -#: parser/parse_clause.c:941 +#: commands/amcmds.c:264 commands/event_trigger.c:200 +#: commands/foreigncmds.c:489 commands/proclang.c:78 commands/trigger.c:702 +#: parser/parse_clause.c:943 #, c-format msgid "function %s must return type %s" msgstr "функція %s повинна повертати тип %s" -#: commands/analyze.c:228 +#: commands/analyze.c:217 #, c-format msgid "skipping \"%s\" --- cannot analyze this foreign table" msgstr "пропуск об'єкту \"%s\" --- неможливо аналізувати цю сторонню таблицю" -#: commands/analyze.c:245 +#: commands/analyze.c:234 #, c-format msgid "skipping \"%s\" --- cannot analyze non-tables or special system tables" msgstr "пропуск об'єкту \"%s\" --- неможливо аналізувати не-таблиці або спеціальні системні таблиці" -#: commands/analyze.c:325 +#: commands/analyze.c:314 #, c-format msgid "analyzing \"%s.%s\" inheritance tree" msgstr "аналізується дерево наслідування \"%s.%s\"" -#: commands/analyze.c:330 +#: commands/analyze.c:319 #, c-format msgid "analyzing \"%s.%s\"" msgstr "аналіз \"%s.%s\"" -#: commands/analyze.c:395 +#: commands/analyze.c:385 #, c-format msgid "column \"%s\" of relation \"%s\" appears more than once" msgstr "стовпець \"%s\" відносно \"%s\" з'являється більше одного разу" -#: commands/analyze.c:787 +#: commands/analyze.c:785 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"\n" msgstr "автоматичний аналіз таблиці \"%s.%s.%s\"\n" -#: commands/analyze.c:1334 +#: commands/analyze.c:1300 #, c-format msgid "\"%s\": scanned %d of %u pages, containing %.0f live rows and %.0f dead rows; %d rows in sample, %.0f estimated total rows" msgstr "\"%s\": проскановано %d з %u сторінок, вони містять %.0f живих рядків і %.0f мертвих рядків; %d рядків вибрані; %.0f приблизне загальне число рядків" -#: commands/analyze.c:1418 +#: commands/analyze.c:1384 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables" msgstr "пропускається аналіз дерева наслідування \"%s.%s\" --- це дерево наслідування не містить дочірніх таблиць" -#: commands/analyze.c:1516 +#: commands/analyze.c:1482 #, c-format msgid "skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables" msgstr "пропускається аналіз дерева наслідування \"%s.%s\" --- це дерево наслідування не містить аналізуючих дочірніх таблиць" -#: commands/async.c:646 +#: commands/async.c:612 #, c-format msgid "channel name cannot be empty" msgstr "ім'я каналу не може бути пустим" -#: commands/async.c:652 +#: commands/async.c:618 #, c-format msgid "channel name too long" msgstr "ім'я каналу задовге" -#: commands/async.c:657 +#: commands/async.c:623 #, c-format msgid "payload string too long" msgstr "рядок навантаження задовгий" -#: commands/async.c:876 +#: commands/async.c:842 #, c-format msgid "cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY" msgstr "виконати PREPARE для транзакції, яка виконала LISTEN, UNLISTEN або NOTIFY неможливо" -#: commands/async.c:980 +#: commands/async.c:946 #, c-format msgid "too many notifications in the NOTIFY queue" msgstr "занадто багато сповіщень у черзі NOTIFY" -#: commands/async.c:1602 +#: commands/async.c:1553 #, c-format msgid "NOTIFY queue is %.0f%% full" msgstr "Черга NOTIFY заповнена на %.0f%%" -#: commands/async.c:1604 +#: commands/async.c:1555 #, c-format msgid "The server process with PID %d is among those with the oldest transactions." msgstr "Серверний процес з PID %d серед процесів з найдавнішими транзакціями." -#: commands/async.c:1607 +#: commands/async.c:1558 #, c-format msgid "The NOTIFY queue cannot be emptied until that process ends its current transaction." msgstr "Черга NOTIFY не може бути спорожненою, поки цей процес не завершить поточну транзакцію." -#: commands/cluster.c:130 +#: commands/cluster.c:128 #, c-format msgid "unrecognized CLUSTER option \"%s\"" msgstr "нерозпізнаний параметр CLUSTER \"%s\"" -#: commands/cluster.c:160 commands/cluster.c:433 +#: commands/cluster.c:159 commands/cluster.c:433 #, c-format msgid "cannot cluster temporary tables of other sessions" msgstr "не можна кластеризувати тимчасові таблиці з інших сеансів" -#: commands/cluster.c:178 +#: commands/cluster.c:177 #, c-format msgid "there is no previously clustered index for table \"%s\"" msgstr "немає попереднього кластеризованого індексу для таблиці \"%s\"" -#: commands/cluster.c:192 commands/tablecmds.c:14214 commands/tablecmds.c:16057 +#: commands/cluster.c:191 commands/tablecmds.c:14695 commands/tablecmds.c:16626 #, c-format msgid "index \"%s\" for table \"%s\" does not exist" msgstr "індекс \"%s\" для таблці \"%s\" не існує" @@ -6420,7 +6749,7 @@ msgstr "не можна кластеризувати спільний катал msgid "cannot vacuum temporary tables of other sessions" msgstr "не можна очищати тимчасові таблиці з інших сеансів" -#: commands/cluster.c:513 commands/tablecmds.c:16067 +#: commands/cluster.c:513 commands/tablecmds.c:16636 #, c-format msgid "\"%s\" is not an index for table \"%s\"" msgstr "\"%s\" не є індексом для таблиці \"%s\"" @@ -6445,62 +6774,66 @@ msgstr "неможливо кластеризувати за невірним і msgid "cannot mark index clustered in partitioned table" msgstr "неможливо помітити індекс кластеризованим в секційній таблиці" -#: commands/cluster.c:950 +#: commands/cluster.c:956 #, c-format msgid "clustering \"%s.%s\" using index scan on \"%s\"" msgstr "кластеризація \"%s.%s\" з використанням сканування індексу \"%s\"" -#: commands/cluster.c:956 +#: commands/cluster.c:962 #, c-format msgid "clustering \"%s.%s\" using sequential scan and sort" msgstr "кластеризація \"%s.%s\"з використанням послідовного сканування та сортування" -#: commands/cluster.c:961 +#: commands/cluster.c:967 #, c-format msgid "vacuuming \"%s.%s\"" msgstr "очищення \"%s.%s\"" -#: commands/cluster.c:988 +#: commands/cluster.c:994 #, c-format msgid "\"%s.%s\": found %.0f removable, %.0f nonremovable row versions in %u pages" msgstr "\"%s.%s\": знайдено версій рядків, що можуть бути видалені %.0f, що не можуть бути видалені %.0f, переглянуто сторінок %u" -#: commands/cluster.c:993 +#: commands/cluster.c:999 #, c-format -msgid "" -"%.0f dead row versions cannot be removed yet.\n" +msgid "%.0f dead row versions cannot be removed yet.\n" "%s." -msgstr "" -"%.0f \"мертві\" версії рядків досі не можуть бути видалені.\n" +msgstr "%.0f \"мертві\" версії рядків досі не можуть бути видалені.\n" "%s." -#: commands/collationcmds.c:112 +#: commands/cluster.c:1744 +#, c-format +msgid "permission denied to cluster \"%s\", skipping it" +msgstr "відмовлено в дозволі кластеру \"%s\", пропуск" + +#: commands/collationcmds.c:110 #, c-format msgid "collation attribute \"%s\" not recognized" msgstr "атрибут collation \"%s\" не розпізнаний" -#: commands/collationcmds.c:125 commands/collationcmds.c:131 -#: commands/define.c:389 commands/tablecmds.c:7884 -#: replication/pgoutput/pgoutput.c:309 replication/pgoutput/pgoutput.c:332 -#: replication/pgoutput/pgoutput.c:346 replication/pgoutput/pgoutput.c:356 -#: replication/pgoutput/pgoutput.c:366 replication/pgoutput/pgoutput.c:376 -#: replication/pgoutput/pgoutput.c:386 replication/walsender.c:996 -#: replication/walsender.c:1018 replication/walsender.c:1028 +#: commands/collationcmds.c:123 commands/collationcmds.c:129 +#: commands/define.c:388 commands/tablecmds.c:8106 +#: replication/pgoutput/pgoutput.c:307 replication/pgoutput/pgoutput.c:330 +#: replication/pgoutput/pgoutput.c:344 replication/pgoutput/pgoutput.c:354 +#: replication/pgoutput/pgoutput.c:364 replication/pgoutput/pgoutput.c:374 +#: replication/pgoutput/pgoutput.c:386 replication/walsender.c:1146 +#: replication/walsender.c:1168 replication/walsender.c:1178 +#: replication/walsender.c:1187 replication/walsender.c:1426 #, c-format msgid "conflicting or redundant options" msgstr "конфліктуючі або надлишкові параметри" -#: commands/collationcmds.c:126 +#: commands/collationcmds.c:124 #, c-format msgid "LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE." msgstr "LOCALE не може вказуватись разом з LC_COLLATE або LC_CTYPE." -#: commands/collationcmds.c:132 +#: commands/collationcmds.c:130 #, c-format msgid "FROM cannot be specified together with any other options." msgstr "FROM не можна вказувати разом з будь-якими іншими параметрами." -#: commands/collationcmds.c:191 +#: commands/collationcmds.c:189 #, c-format msgid "collation \"default\" cannot be copied" msgstr "сортування \"за замовчуванням\" не може бути скопійовано" @@ -6510,100 +6843,94 @@ msgstr "сортування \"за замовчуванням\" не може msgid "unrecognized collation provider: %s" msgstr "нерозпізнаний постачальник правил сортування: %s" -#: commands/collationcmds.c:253 commands/collationcmds.c:259 -#: commands/collationcmds.c:267 +#: commands/collationcmds.c:253 commands/collationcmds.c:264 +#: commands/collationcmds.c:270 commands/collationcmds.c:278 #, c-format msgid "parameter \"%s\" must be specified" msgstr "необхідно вказати параметр \"%s\"" -#: commands/collationcmds.c:282 commands/dbcommands.c:1091 +#: commands/collationcmds.c:293 commands/dbcommands.c:1134 #, c-format msgid "using standard form \"%s\" for ICU locale \"%s\"" msgstr "використання стандартної форми \"%s\" для мови ICU \"%s\"" -#: commands/collationcmds.c:301 +#: commands/collationcmds.c:312 #, c-format msgid "nondeterministic collations not supported with this provider" msgstr "недетерміновані правила сортування не підтримуються цим провайдером" -#: commands/collationcmds.c:306 commands/dbcommands.c:1110 +#: commands/collationcmds.c:317 commands/dbcommands.c:1087 #, c-format msgid "ICU rules cannot be specified unless locale provider is ICU" msgstr "Правила ICU не можна вказати, якщо постачальник локалі не ICU" -#: commands/collationcmds.c:325 +#: commands/collationcmds.c:340 #, c-format msgid "current database's encoding is not supported with this provider" msgstr "кодування поточної бази даних не підтримується цим провайдером" -#: commands/collationcmds.c:385 +#: commands/collationcmds.c:409 #, c-format msgid "collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"" msgstr "правило сортування \"%s\" для кодування \"%s\" вже існує в схемі \"%s\"" -#: commands/collationcmds.c:396 +#: commands/collationcmds.c:420 #, c-format msgid "collation \"%s\" already exists in schema \"%s\"" msgstr "правило сортування \"%s\" вже існує в схемі \"%s\"" -#: commands/collationcmds.c:421 +#: commands/collationcmds.c:445 #, c-format msgid "cannot refresh version of default collation" msgstr "оновити версію правила сортування за замовчуванням не можна" #. translator: %s is an SQL command #. translator: %s is an SQL ALTER command -#: commands/collationcmds.c:423 commands/subscriptioncmds.c:1331 -#: commands/tablecmds.c:7709 commands/tablecmds.c:7719 -#: commands/tablecmds.c:13916 commands/tablecmds.c:17196 -#: commands/tablecmds.c:17217 commands/typecmds.c:3637 commands/typecmds.c:3720 -#: commands/typecmds.c:4013 +#: commands/collationcmds.c:447 commands/subscriptioncmds.c:1376 +#: commands/tablecmds.c:7882 commands/tablecmds.c:7892 +#: commands/tablecmds.c:7894 commands/tablecmds.c:14397 +#: commands/tablecmds.c:17774 commands/tablecmds.c:17795 +#: commands/typecmds.c:3787 commands/typecmds.c:3872 commands/typecmds.c:4226 #, c-format msgid "Use %s instead." msgstr "Використайте %s замість цього." -#: commands/collationcmds.c:451 commands/dbcommands.c:2488 +#: commands/collationcmds.c:480 commands/dbcommands.c:2567 #, c-format msgid "changing version from %s to %s" msgstr "зміна версії з %s на %s" -#: commands/collationcmds.c:466 commands/dbcommands.c:2501 +#: commands/collationcmds.c:495 commands/dbcommands.c:2580 #, c-format msgid "version has not changed" msgstr "версію не змінено" -#: commands/collationcmds.c:499 commands/dbcommands.c:2667 +#: commands/collationcmds.c:528 commands/dbcommands.c:2746 #, c-format msgid "database with OID %u does not exist" msgstr "база даних з OID %u не існує" -#: commands/collationcmds.c:520 +#: commands/collationcmds.c:554 #, c-format msgid "collation with OID %u does not exist" msgstr "порядку сортування %u з OID не існує" -#: commands/collationcmds.c:808 +#: commands/collationcmds.c:848 #, c-format msgid "must be superuser to import system collations" msgstr "імпортувати систмені правила сортування може тільки суперкористувач" -#: commands/collationcmds.c:836 commands/copyfrom.c:1671 commands/copyto.c:656 -#: libpq/be-secure-common.c:59 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не вдалося виконати команду \"%s\": %m" - -#: commands/collationcmds.c:928 commands/collationcmds.c:1013 +#: commands/collationcmds.c:968 commands/collationcmds.c:1053 #, c-format msgid "no usable system locales were found" msgstr "придатні системні локалі не знайдені" -#: commands/comment.c:61 commands/dbcommands.c:1612 commands/dbcommands.c:1824 -#: commands/dbcommands.c:1934 commands/dbcommands.c:2132 -#: commands/dbcommands.c:2370 commands/dbcommands.c:2461 -#: commands/dbcommands.c:2571 commands/dbcommands.c:3071 -#: utils/init/postinit.c:1021 utils/init/postinit.c:1085 -#: utils/init/postinit.c:1157 +#: commands/comment.c:61 commands/dbcommands.c:1665 commands/dbcommands.c:1892 +#: commands/dbcommands.c:2002 commands/dbcommands.c:2200 +#: commands/dbcommands.c:2438 commands/dbcommands.c:2529 +#: commands/dbcommands.c:2650 commands/dbcommands.c:3158 +#: utils/init/postinit.c:1033 utils/init/postinit.c:1097 +#: utils/init/postinit.c:1170 #, c-format msgid "database \"%s\" does not exist" msgstr "бази даних \"%s\" не існує" @@ -6613,309 +6940,264 @@ msgstr "бази даних \"%s\" не існує" msgid "cannot set comment on relation \"%s\"" msgstr "встановити коментар для відношення \"%s\" не можна" -#: commands/constraint.c:63 utils/adt/ri_triggers.c:2028 +#: commands/constraint.c:61 utils/adt/ri_triggers.c:2019 #, c-format msgid "function \"%s\" was not called by trigger manager" msgstr "функція \"%s\" не була викликана менеджером тригерів" -#: commands/constraint.c:70 utils/adt/ri_triggers.c:2037 +#: commands/constraint.c:68 utils/adt/ri_triggers.c:2028 #, c-format msgid "function \"%s\" must be fired AFTER ROW" msgstr "функція \"%s\" повинна запускатися в AFTER ROW" -#: commands/constraint.c:84 +#: commands/constraint.c:82 #, c-format msgid "function \"%s\" must be fired for INSERT or UPDATE" msgstr "функція \"%s\" повинна запускатися для INSERT або UPDATE" -#: commands/conversioncmds.c:69 +#: commands/conversioncmds.c:62 #, c-format msgid "source encoding \"%s\" does not exist" msgstr "вихідного кодування \"%s\" не існує" -#: commands/conversioncmds.c:76 +#: commands/conversioncmds.c:69 #, c-format msgid "destination encoding \"%s\" does not exist" msgstr "цільового кодування \"%s\" не існує" -#: commands/conversioncmds.c:89 +#: commands/conversioncmds.c:82 #, c-format msgid "encoding conversion to or from \"SQL_ASCII\" is not supported" msgstr "перетворення кодування в або з \"SQL_ASCII\" не підтримується" -#: commands/conversioncmds.c:102 +#: commands/conversioncmds.c:95 #, c-format msgid "encoding conversion function %s must return type %s" msgstr "функція перетворення кодування %s повинна повертати тип %s" -#: commands/conversioncmds.c:132 +#: commands/conversioncmds.c:125 #, c-format msgid "encoding conversion function %s returned incorrect result for empty input" msgstr "функція перетворення кодування %s повернула неправильний результат для порожнього вводу" -#: commands/copy.c:86 +#: commands/copy.c:84 #, c-format msgid "permission denied to COPY to or from an external program" msgstr "немає дозволу для COPY в або з зовнішньої програми" -#: commands/copy.c:87 +#: commands/copy.c:85 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to or from an external program." msgstr "Тільки ролі з правами \"%s\" можуть виконувати COPY з зовнішньою програмою." -#: commands/copy.c:89 commands/copy.c:100 commands/copy.c:109 +#: commands/copy.c:87 commands/copy.c:98 commands/copy.c:107 #, c-format msgid "Anyone can COPY to stdout or from stdin. psql's \\copy command also works for anyone." msgstr "Будь-хто може використати COPY to stdout або from stdin, а також команду psql \\copy." -#: commands/copy.c:97 +#: commands/copy.c:95 #, c-format msgid "permission denied to COPY from a file" msgstr "немає дозволу для COPY з файлу" -#: commands/copy.c:98 +#: commands/copy.c:96 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY from a file." msgstr "Тільки ролі з правами \"%s\" можуть виконувати COPY з файлу." -#: commands/copy.c:106 +#: commands/copy.c:104 #, c-format msgid "permission denied to COPY to a file" msgstr "немає дозволу для COPY в файл" -#: commands/copy.c:107 +#: commands/copy.c:105 #, c-format msgid "Only roles with privileges of the \"%s\" role may COPY to a file." msgstr "Тільки ролі з правами \"%s\" можуть виконувати COPY в файл." -#: commands/copy.c:195 +#: commands/copy.c:193 #, c-format msgid "COPY FROM not supported with row-level security" msgstr "COPY FROM не підтримується із захистом на рівні рядків" -#: commands/copy.c:196 +#: commands/copy.c:194 #, c-format msgid "Use INSERT statements instead." msgstr "Використайте оператори INSERT замість цього." -#: commands/copy.c:290 -#, c-format -msgid "MERGE not supported in COPY" -msgstr "COPY не підтримує MERGE" - -#: commands/copy.c:383 +#: commands/copy.c:375 #, c-format msgid "cannot use \"%s\" with HEADER in COPY TO" msgstr "використовувати \"%s\" з HEADER в COPY TO не можна" -#: commands/copy.c:392 +#: commands/copy.c:384 #, c-format msgid "%s requires a Boolean value or \"match\"" msgstr "%s потребує Boolean або \"відповідність\"" -#: commands/copy.c:451 +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR, +#. second %s is a COPY with direction, e.g. COPY TO +#: commands/copy.c:402 commands/copy.c:782 commands/copy.c:796 +#: commands/copy.c:811 commands/copy.c:837 commands/copy.c:847 +#, c-format +msgid "COPY %s cannot be used with %s" +msgstr "COPY %s не можна використовувати з %s" + +#. translator: first %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:416 commands/copy.c:441 +#, c-format +msgid "COPY %s \"%s\" not recognized" +msgstr "COPY %s \"%s\" не розпізнано" + +#: commands/copy.c:502 #, c-format msgid "COPY format \"%s\" not recognized" msgstr "Формат \"%s\" для COPY не розпізнано" -#: commands/copy.c:509 commands/copy.c:522 commands/copy.c:535 -#: commands/copy.c:554 +#: commands/copy.c:560 commands/copy.c:575 commands/copy.c:590 +#: commands/copy.c:609 #, c-format msgid "argument to option \"%s\" must be a list of column names" msgstr "аргументом функції \"%s\" повинен бути список імен стовпців" -#: commands/copy.c:566 +#: commands/copy.c:621 #, c-format msgid "argument to option \"%s\" must be a valid encoding name" msgstr "аргументом функції \"%s\" повинне бути припустиме ім'я коду" -#: commands/copy.c:573 commands/dbcommands.c:859 commands/dbcommands.c:2318 +#: commands/copy.c:642 commands/dbcommands.c:866 commands/dbcommands.c:2386 #, c-format msgid "option \"%s\" not recognized" msgstr "параметр \"%s\" не розпізнано" -#: commands/copy.c:585 -#, c-format -msgid "cannot specify DELIMITER in BINARY mode" -msgstr "неможливо визначити DELIMITER в режимі BINARY" - -#: commands/copy.c:590 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:655 commands/copy.c:660 commands/copy.c:665 +#: commands/copy.c:740 #, c-format -msgid "cannot specify NULL in BINARY mode" -msgstr "неможливо визначити NULL в режимі BINARY" +msgid "cannot specify %s in BINARY mode" +msgstr "не можна вказати %s в режимі BINARY" -#: commands/copy.c:595 +#: commands/copy.c:670 #, c-format -msgid "cannot specify DEFAULT in BINARY mode" -msgstr "в режимі BINARY не можна визначити DEFAULT" +msgid "only ON_ERROR STOP is allowed in BINARY mode" +msgstr "в режимі BINARY допускається лише ON_ERROR STOP" -#: commands/copy.c:617 +#: commands/copy.c:692 #, c-format msgid "COPY delimiter must be a single one-byte character" msgstr "роздільник для COPY повинен бути однобайтовим символом" -#: commands/copy.c:624 +#: commands/copy.c:699 #, c-format msgid "COPY delimiter cannot be newline or carriage return" msgstr "Роздільник для COPY не може бути символом нового рядка або повернення каретки" -#: commands/copy.c:630 +#: commands/copy.c:705 #, c-format msgid "COPY null representation cannot use newline or carriage return" msgstr "Подання NULL для COPY не може включати символ нового рядка або повернення каретки" -#: commands/copy.c:640 +#: commands/copy.c:715 #, c-format msgid "COPY default representation cannot use newline or carriage return" msgstr "Подання для COPY за замовчуванням не може включати символ нового рядка або повернення каретки" -#: commands/copy.c:658 +#: commands/copy.c:733 #, c-format msgid "COPY delimiter cannot be \"%s\"" msgstr "роздільник COPY не може бути \"%s\"" -#: commands/copy.c:664 +#. translator: %s is the name of a COPY option, e.g. ON_ERROR +#: commands/copy.c:747 commands/copy.c:764 commands/copy.c:776 +#: commands/copy.c:790 commands/copy.c:804 #, c-format -msgid "cannot specify HEADER in BINARY mode" -msgstr "не можна вказати HEADER у режимі BINARY" +msgid "COPY %s requires CSV mode" +msgstr "Для COPY %s потрібен режим CSV" -#: commands/copy.c:670 -#, c-format -msgid "COPY quote available only in CSV mode" -msgstr "лапки для COPY доустпні тільки в режимі CSV" - -#: commands/copy.c:675 +#: commands/copy.c:752 #, c-format msgid "COPY quote must be a single one-byte character" msgstr "лапки для COPY повинні бути однобайтовим символом" -#: commands/copy.c:680 +#: commands/copy.c:757 #, c-format msgid "COPY delimiter and quote must be different" msgstr "роздільник і лапки для COPY повинні бути різними" -#: commands/copy.c:686 -#, c-format -msgid "COPY escape available only in CSV mode" -msgstr "вихід для COPY доступний тільки в режимі CSV" - -#: commands/copy.c:691 +#: commands/copy.c:769 #, c-format msgid "COPY escape must be a single one-byte character" msgstr "вихід для COPY повинен бути однобайтовим символом" -#: commands/copy.c:697 -#, c-format -msgid "COPY force quote available only in CSV mode" -msgstr "Параметр force quote для COPY можна використати тільки в режимі CSV" - -#: commands/copy.c:701 -#, c-format -msgid "COPY force quote only available using COPY TO" -msgstr "Параметр force quote для COPY можна використати тільки з COPY TO" - -#: commands/copy.c:707 -#, c-format -msgid "COPY force not null available only in CSV mode" -msgstr "Параметр force not null для COPY можна використати тільки в режимі CSV" - -#: commands/copy.c:711 -#, c-format -msgid "COPY force not null only available using COPY FROM" -msgstr "Параметр force not null для COPY можна використати тільки з COPY FROM" - -#: commands/copy.c:717 -#, c-format -msgid "COPY force null available only in CSV mode" -msgstr "Параметр force null для COPY можна використати тільки в режимі CSV" - -#: commands/copy.c:722 -#, c-format -msgid "COPY force null only available using COPY FROM" -msgstr "Параметр force null only для COPY можна використати тільки з COPY FROM" - -#: commands/copy.c:728 -#, c-format -msgid "COPY delimiter must not appear in the NULL specification" -msgstr "роздільник COPY не повинен з'являтися у специфікації NULL" - -#: commands/copy.c:735 -#, c-format -msgid "CSV quote character must not appear in the NULL specification" -msgstr "лапки CSV не повинні з'являтися у специфікації NULL" - -#: commands/copy.c:742 -#, c-format -msgid "COPY DEFAULT only available using COPY FROM" -msgstr "COPY DEFAULT тільки для COPY FROM" - -#: commands/copy.c:748 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:819 commands/copy.c:855 #, c-format -msgid "COPY delimiter must not appear in the DEFAULT specification" -msgstr "роздільник COPY не повинен з'являтися у специфікації DEFAULT" +msgid "COPY delimiter character must not appear in the %s specification" +msgstr "символ розділювача для COPY не повинен з'являтися в специфікації %s" -#: commands/copy.c:755 +#. translator: %s is the name of a COPY option, e.g. NULL +#: commands/copy.c:828 commands/copy.c:864 #, c-format -msgid "CSV quote character must not appear in the DEFAULT specification" -msgstr "лапки CSV не повинні з'являтися у специфікації DEFAULT" +msgid "CSV quote character must not appear in the %s specification" +msgstr "лапки CSV не повинні з'являтися у специфікації %s" -#: commands/copy.c:763 +#: commands/copy.c:873 #, c-format msgid "NULL specification and DEFAULT specification cannot be the same" msgstr "Специфікація NULL і специфікація DEFAULT не може співпадати" -#: commands/copy.c:825 +#: commands/copy.c:935 #, c-format msgid "column \"%s\" is a generated column" msgstr "стовпець \"%s\" є згенерованим стовпцем" -#: commands/copy.c:827 +#: commands/copy.c:937 #, c-format msgid "Generated columns cannot be used in COPY." msgstr "Згенеровані стовпці не можна використовувати в COPY." -#: commands/copy.c:842 commands/indexcmds.c:1886 commands/statscmds.c:242 -#: commands/tablecmds.c:2405 commands/tablecmds.c:3127 -#: commands/tablecmds.c:3626 parser/parse_relation.c:3689 -#: parser/parse_relation.c:3699 parser/parse_relation.c:3717 -#: parser/parse_relation.c:3724 parser/parse_relation.c:3738 -#: utils/adt/tsvector_op.c:2855 +#: commands/copy.c:952 commands/indexcmds.c:1917 commands/statscmds.c:239 +#: commands/tablecmds.c:2509 commands/tablecmds.c:2980 +#: commands/tablecmds.c:3788 parser/parse_relation.c:3692 +#: parser/parse_relation.c:3702 parser/parse_relation.c:3720 +#: parser/parse_relation.c:3727 parser/parse_relation.c:3741 +#: utils/adt/tsvector_op.c:2853 #, c-format msgid "column \"%s\" does not exist" msgstr "стовпця \"%s\" не існує" -#: commands/copy.c:849 commands/tablecmds.c:2431 commands/trigger.c:958 -#: parser/parse_target.c:1070 parser/parse_target.c:1081 +#: commands/copy.c:959 commands/tablecmds.c:2535 commands/trigger.c:951 +#: parser/parse_target.c:1083 parser/parse_target.c:1094 #, c-format msgid "column \"%s\" specified more than once" msgstr "стовпець \"%s\" вказано більше чим один раз" -#: commands/copyfrom.c:122 +#: commands/copyfrom.c:118 #, c-format msgid "COPY %s" msgstr "COPY %s" -#: commands/copyfrom.c:130 +#: commands/copyfrom.c:126 #, c-format msgid "COPY %s, line %llu, column %s" msgstr "COPY %s, рядок %llu, стовпець %s" -#: commands/copyfrom.c:135 commands/copyfrom.c:181 +#: commands/copyfrom.c:131 commands/copyfrom.c:177 #, c-format msgid "COPY %s, line %llu" msgstr "COPY %s, рядок %llu" -#: commands/copyfrom.c:147 +#: commands/copyfrom.c:143 #, c-format msgid "COPY %s, line %llu, column %s: \"%s\"" msgstr "COPY %s, рядок %llu, стовпець %s: \"%s\"" -#: commands/copyfrom.c:157 +#: commands/copyfrom.c:153 #, c-format msgid "COPY %s, line %llu, column %s: null input" msgstr "COPY %s, рядок %llu, стовпець %s: null введення" -#: commands/copyfrom.c:174 +#: commands/copyfrom.c:170 #, c-format msgid "COPY %s, line %llu: \"%s\"" msgstr "COPY %s, рядок %llu: \"%s\"" @@ -6960,37 +7242,43 @@ msgstr "виконати COPY FREEZE через попередню активн msgid "cannot perform COPY FREEZE because the table was not created or truncated in the current subtransaction" msgstr "не можна виконати COPY FREEZE, тому, що таблиця не була створена або скорочена в поточній підтранзакції" -#: commands/copyfrom.c:1414 +#: commands/copyfrom.c:1313 #, c-format -msgid "FORCE_NOT_NULL column \"%s\" not referenced by COPY" -msgstr "Стовпець FORCE_NOT_NULL \"%s\" не фігурує в COPY" +msgid "%llu row was skipped due to data type incompatibility" +msgid_plural "%llu rows were skipped due to data type incompatibility" +msgstr[0] "Рядок %llu пропущено через несумісність типів даних" +msgstr[1] "Рядки %llu пропущено через несумісність типів даних" +msgstr[2] "Рядки %llu пропущено через несумісність типів даних" +msgstr[3] "Рядки %llu пропущено через несумісність типів даних" -#: commands/copyfrom.c:1437 +#. translator: first %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#. translator: %s is the name of a COPY option, e.g. FORCE_NOT_NULL +#: commands/copyfrom.c:1448 commands/copyfrom.c:1491 commands/copyto.c:597 #, c-format -msgid "FORCE_NULL column \"%s\" not referenced by COPY" -msgstr "Стовпець FORCE_NULL \"%s\" не фігурує в COPY" +msgid "%s column \"%s\" not referenced by COPY" +msgstr "%s стовпець \"%s\" не фігурує в COPY" -#: commands/copyfrom.c:1490 utils/mb/mbutils.c:386 +#: commands/copyfrom.c:1544 utils/mb/mbutils.c:385 #, c-format msgid "default conversion function for encoding \"%s\" to \"%s\" does not exist" msgstr "функції за замовчуванням перетворення з кодування \"%s\" в \"%s\" не існує" -#: commands/copyfrom.c:1690 +#: commands/copyfrom.c:1742 #, c-format msgid "COPY FROM instructs the PostgreSQL server process to read a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY FROM наказує серверному процесу PostgreSQL прочитати дані з файлу. Можливо, вам потрібна клієнтська команда, наприклад \\copy в psql." -#: commands/copyfrom.c:1703 commands/copyto.c:708 +#: commands/copyfrom.c:1755 commands/copyto.c:702 #, c-format msgid "\"%s\" is a directory" msgstr "\"%s\" - каталог" -#: commands/copyfrom.c:1771 commands/copyto.c:306 libpq/be-secure-common.c:83 +#: commands/copyfrom.c:1823 commands/copyto.c:299 libpq/be-secure-common.c:83 #, c-format msgid "could not close pipe to external command: %m" msgstr "не вдалося закрити канал за допомогою зовнішньої команди: %m" -#: commands/copyfrom.c:1786 commands/copyto.c:311 +#: commands/copyfrom.c:1838 commands/copyto.c:304 #, c-format msgid "program \"%s\" failed" msgstr "збій програми \"%s\"" @@ -7031,17 +7319,17 @@ msgid "could not read from COPY file: %m" msgstr "не вдалося прочитати файл COPY: %m" #: commands/copyfromparse.c:278 commands/copyfromparse.c:303 -#: tcop/postgres.c:377 +#: replication/walsender.c:756 replication/walsender.c:782 tcop/postgres.c:381 #, c-format msgid "unexpected EOF on client connection with an open transaction" msgstr "неочікуваний обрив з'єднання з клієнтом при відкритій транзакції" -#: commands/copyfromparse.c:294 +#: commands/copyfromparse.c:294 replication/walsender.c:772 #, c-format msgid "unexpected message type 0x%02X during COPY from stdin" msgstr "неочікуваний тип повідомлення 0x%02X під час COPY з stdin" -#: commands/copyfromparse.c:317 +#: commands/copyfromparse.c:317 replication/walsender.c:803 #, c-format msgid "COPY from stdin failed: %s" msgstr "помилка при stdin COPY: %s" @@ -7061,8 +7349,8 @@ msgstr "невідповідність назви стовпця в полі з msgid "column name mismatch in header line field %d: got \"%s\", expected \"%s\"" msgstr "невідповідність назви стовпця в полі заголовку %d: отримано \"%s\", очікувалось \"%s\"" -#: commands/copyfromparse.c:892 commands/copyfromparse.c:1512 -#: commands/copyfromparse.c:1768 +#: commands/copyfromparse.c:892 commands/copyfromparse.c:1554 +#: commands/copyfromparse.c:1810 #, c-format msgid "extra data after last expected column" msgstr "зайві дані після вмісту останнього стовпця" @@ -7072,465 +7360,481 @@ msgstr "зайві дані після вмісту останнього сто msgid "missing data for column \"%s\"" msgstr "відсутні дані для стовпця \"%s\"" -#: commands/copyfromparse.c:999 +#: commands/copyfromparse.c:990 +#, c-format +msgid "skipping row due to data type incompatibility at line %llu for column \"%s\": \"%s\"" +msgstr "пропуск рядка через несумісність типів даних в рядку %llu для стовпця \"%s\": \"%s\"" + +#: commands/copyfromparse.c:998 +#, c-format +msgid "skipping row due to data type incompatibility at line %llu for column \"%s\": null input" +msgstr "пропуск рядка через несумісність типів даних в рядку %llu для стовпця \"%s\": значення null" + +#: commands/copyfromparse.c:1044 #, c-format msgid "received copy data after EOF marker" msgstr "після маркера кінця файлу продовжуються дані COPY" -#: commands/copyfromparse.c:1006 +#: commands/copyfromparse.c:1051 #, c-format msgid "row field count is %d, expected %d" msgstr "кількість полів у рядку: %d, очікувалось: %d" -#: commands/copyfromparse.c:1294 commands/copyfromparse.c:1311 +#: commands/copyfromparse.c:1336 commands/copyfromparse.c:1353 #, c-format msgid "literal carriage return found in data" msgstr "в даних виявлено явне повернення каретки" -#: commands/copyfromparse.c:1295 commands/copyfromparse.c:1312 +#: commands/copyfromparse.c:1337 commands/copyfromparse.c:1354 #, c-format msgid "unquoted carriage return found in data" msgstr "в даних виявлено повернення каретки без лапок" -#: commands/copyfromparse.c:1297 commands/copyfromparse.c:1314 +#: commands/copyfromparse.c:1339 commands/copyfromparse.c:1356 #, c-format msgid "Use \"\\r\" to represent carriage return." msgstr "Використайте \"\\r\", щоб позначити повернення каретки." -#: commands/copyfromparse.c:1298 commands/copyfromparse.c:1315 +#: commands/copyfromparse.c:1340 commands/copyfromparse.c:1357 #, c-format msgid "Use quoted CSV field to represent carriage return." msgstr "Використайте CSV в лапках, щоб позначити повернення каретки." -#: commands/copyfromparse.c:1327 +#: commands/copyfromparse.c:1369 #, c-format msgid "literal newline found in data" msgstr "в даних знайдено явний новий рядок" -#: commands/copyfromparse.c:1328 +#: commands/copyfromparse.c:1370 #, c-format msgid "unquoted newline found in data" msgstr "в даних знайдено новий рядок без лапок" -#: commands/copyfromparse.c:1330 +#: commands/copyfromparse.c:1372 #, c-format msgid "Use \"\\n\" to represent newline." msgstr "Використайте \"\\n\", щоб представити новий рядок." -#: commands/copyfromparse.c:1331 +#: commands/copyfromparse.c:1373 #, c-format msgid "Use quoted CSV field to represent newline." msgstr "Використайте CSV в лапках, щоб позначити новий рядок." -#: commands/copyfromparse.c:1377 commands/copyfromparse.c:1413 +#: commands/copyfromparse.c:1419 commands/copyfromparse.c:1455 #, c-format msgid "end-of-copy marker does not match previous newline style" msgstr "маркер \"кінець копії\" не відповідає попередньому стилю нового рядка" -#: commands/copyfromparse.c:1386 commands/copyfromparse.c:1402 +#: commands/copyfromparse.c:1428 commands/copyfromparse.c:1444 #, c-format msgid "end-of-copy marker corrupt" msgstr "маркер \"кінець копії\" зіпсований" -#: commands/copyfromparse.c:1704 commands/copyfromparse.c:1919 +#: commands/copyfromparse.c:1746 commands/copyfromparse.c:1961 #, c-format msgid "unexpected default marker in COPY data" msgstr "неочікуваний маркер за замовчуванням в даних COPY" -#: commands/copyfromparse.c:1705 commands/copyfromparse.c:1920 +#: commands/copyfromparse.c:1747 commands/copyfromparse.c:1962 #, c-format msgid "Column \"%s\" has no default value." msgstr "Колонка \"%s\" не має значення за замовчуванням." -#: commands/copyfromparse.c:1852 +#: commands/copyfromparse.c:1894 #, c-format msgid "unterminated CSV quoted field" msgstr "незакінчене поле в лапках CSV" -#: commands/copyfromparse.c:1954 commands/copyfromparse.c:1973 +#: commands/copyfromparse.c:1996 commands/copyfromparse.c:2015 #, c-format msgid "unexpected EOF in COPY data" msgstr "неочікуваний кінец файлу в даних COPY" -#: commands/copyfromparse.c:1963 +#: commands/copyfromparse.c:2005 #, c-format msgid "invalid field size" msgstr "невірний розмір поля" -#: commands/copyfromparse.c:1986 +#: commands/copyfromparse.c:2028 #, c-format msgid "incorrect binary data format" msgstr "невірний двійковий формат даних" -#: commands/copyto.c:236 +#: commands/copyto.c:229 #, c-format msgid "could not write to COPY program: %m" msgstr "не вдалося записати в канал програми COPY: %m" -#: commands/copyto.c:241 +#: commands/copyto.c:234 #, c-format msgid "could not write to COPY file: %m" msgstr "не можливо записати в файл COPY: %m" -#: commands/copyto.c:386 +#: commands/copyto.c:379 #, c-format msgid "cannot copy from view \"%s\"" msgstr "неможливо скопіювати з подання \"%s\"" -#: commands/copyto.c:388 commands/copyto.c:394 commands/copyto.c:400 -#: commands/copyto.c:411 +#: commands/copyto.c:381 commands/copyto.c:387 commands/copyto.c:393 +#: commands/copyto.c:404 #, c-format msgid "Try the COPY (SELECT ...) TO variant." msgstr "Спробуйте варіацію COPY (SELECT ...) TO." -#: commands/copyto.c:392 +#: commands/copyto.c:385 #, c-format msgid "cannot copy from materialized view \"%s\"" msgstr "неможливо скопіювати з матеріалізованого подання \"%s\"" -#: commands/copyto.c:398 +#: commands/copyto.c:391 #, c-format msgid "cannot copy from foreign table \"%s\"" msgstr "неможливо скопіювати зі сторонньої таблиці \"%s\"" -#: commands/copyto.c:404 +#: commands/copyto.c:397 #, c-format msgid "cannot copy from sequence \"%s\"" msgstr "не вдалося скопіювати з послідовності \"%s\"" -#: commands/copyto.c:409 +#: commands/copyto.c:402 #, c-format msgid "cannot copy from partitioned table \"%s\"" msgstr "неможливо скопіювати з секційної таблиці \"%s\"" -#: commands/copyto.c:415 +#: commands/copyto.c:408 #, c-format msgid "cannot copy from non-table relation \"%s\"" msgstr "не можна копіювати з відношення \"%s\", котре не є таблицею" -#: commands/copyto.c:467 +#: commands/copyto.c:460 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for COPY" msgstr "правила DO INSTEAD NOTHING не підтримуються для COPY" -#: commands/copyto.c:481 +#: commands/copyto.c:474 #, c-format msgid "conditional DO INSTEAD rules are not supported for COPY" msgstr "умовні правила DO INSTEAD не підтримуються для COPY" -#: commands/copyto.c:485 +#: commands/copyto.c:478 #, c-format msgid "DO ALSO rules are not supported for the COPY" msgstr "правила DO ALSO не підтримуються для COPY" -#: commands/copyto.c:490 +#: commands/copyto.c:483 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for COPY" msgstr "складові правила DO INSTEAD не підтримуються з COPY" -#: commands/copyto.c:500 +#: commands/copyto.c:493 #, c-format msgid "COPY (SELECT INTO) is not supported" msgstr "COPY (SELECT INTO) не підтримується" -#: commands/copyto.c:517 +#: commands/copyto.c:511 #, c-format msgid "COPY query must have a RETURNING clause" msgstr "В запиті COPY повинно бути речення RETURNING" -#: commands/copyto.c:546 +#: commands/copyto.c:540 #, c-format msgid "relation referenced by COPY statement has changed" msgstr "відношення, згадане в операторі COPY, змінилось" -#: commands/copyto.c:605 -#, c-format -msgid "FORCE_QUOTE column \"%s\" not referenced by COPY" -msgstr "Стовпець FORCE_QUOTE \"%s\" не фігурує в COPY" - -#: commands/copyto.c:673 +#: commands/copyto.c:667 #, c-format msgid "relative path not allowed for COPY to file" msgstr "при виконанні COPY в файл не можна вказувати відносний шлях" -#: commands/copyto.c:692 +#: commands/copyto.c:686 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "не вдалося відкрити файл \"%s\" для запису: %m" -#: commands/copyto.c:695 +#: commands/copyto.c:689 #, c-format msgid "COPY TO instructs the PostgreSQL server process to write a file. You may want a client-side facility such as psql's \\copy." msgstr "COPY TO наказує серверному процесу PostgreSQL записати дані до файлу. Можливо, вам потрібна клієнтська команда, наприклад \\copy в psql." -#: commands/createas.c:215 commands/createas.c:523 +#: commands/createas.c:210 commands/createas.c:516 #, c-format msgid "too many column names were specified" msgstr "вказано забагато імен стовпців" -#: commands/createas.c:546 +#: commands/createas.c:539 #, c-format msgid "policies not yet implemented for this command" msgstr "політики для цієї команди все ще не реалізовані" -#: commands/dbcommands.c:822 +#: commands/dbcommands.c:829 #, c-format msgid "LOCATION is not supported anymore" msgstr "LOCATION більше не підтримується" -#: commands/dbcommands.c:823 +#: commands/dbcommands.c:830 #, c-format msgid "Consider using tablespaces instead." msgstr "Розгляньте можливість використання табличних просторів." -#: commands/dbcommands.c:848 +#: commands/dbcommands.c:855 #, c-format msgid "OIDs less than %u are reserved for system objects" msgstr "OID котрі менше ніж %u, зарезервовані для системних об'єктів" -#: commands/dbcommands.c:879 utils/adt/ascii.c:146 +#: commands/dbcommands.c:886 utils/adt/ascii.c:146 #, c-format msgid "%d is not a valid encoding code" msgstr "%d не є вірним кодом кодування" -#: commands/dbcommands.c:890 utils/adt/ascii.c:128 +#: commands/dbcommands.c:897 utils/adt/ascii.c:128 #, c-format msgid "%s is not a valid encoding name" msgstr "%s не є вірним ім'ям кодування" -#: commands/dbcommands.c:919 +#: commands/dbcommands.c:931 #, c-format msgid "unrecognized locale provider: %s" msgstr "нерозпізнаний постачальник локалів: %s" -#: commands/dbcommands.c:932 commands/dbcommands.c:2351 commands/user.c:300 -#: commands/user.c:740 +#: commands/dbcommands.c:944 commands/dbcommands.c:2419 commands/user.c:299 +#: commands/user.c:739 #, c-format msgid "invalid connection limit: %d" msgstr "недійсний ліміт з'єднання: %d" -#: commands/dbcommands.c:953 +#: commands/dbcommands.c:965 #, c-format msgid "permission denied to create database" msgstr "немає дозволу для створення бази даних" -#: commands/dbcommands.c:977 +#: commands/dbcommands.c:989 #, c-format msgid "template database \"%s\" does not exist" msgstr "шаблону бази даних \"%s\" не існує" -#: commands/dbcommands.c:987 +#: commands/dbcommands.c:999 #, c-format msgid "cannot use invalid database \"%s\" as template" msgstr "не можна використовувати невірну базу даних \"%s\" в якості шаблону" -#: commands/dbcommands.c:988 commands/dbcommands.c:2380 -#: utils/init/postinit.c:1100 +#: commands/dbcommands.c:1000 commands/dbcommands.c:2448 +#: utils/init/postinit.c:1112 #, c-format msgid "Use DROP DATABASE to drop invalid databases." msgstr "Використайте DROP DATABASE для видалення невірних баз даних." -#: commands/dbcommands.c:999 +#: commands/dbcommands.c:1011 #, c-format msgid "permission denied to copy database \"%s\"" msgstr "немає дозволу для копіювання бази даних \"%s\"" -#: commands/dbcommands.c:1016 +#: commands/dbcommands.c:1028 #, c-format msgid "invalid create database strategy \"%s\"" msgstr "неприпустима стратегія створення бази даних \"%s\"" -#: commands/dbcommands.c:1017 +#: commands/dbcommands.c:1029 #, c-format -msgid "Valid strategies are \"wal_log\", and \"file_copy\"." -msgstr "Припустимі стратегії: \"wal_log\" і \"file_copy\"." +msgid "Valid strategies are \"wal_log\" and \"file_copy\"." +msgstr "Припустимі стратегії - це \"wal_log\" і \"file_copy\"." -#: commands/dbcommands.c:1043 +#: commands/dbcommands.c:1050 #, c-format msgid "invalid server encoding %d" msgstr "недійсний сервер кодування %d" -#: commands/dbcommands.c:1049 +#: commands/dbcommands.c:1056 #, c-format msgid "invalid LC_COLLATE locale name: \"%s\"" msgstr "неприпустиме ім'я локалі LC_COLLATE: \"%s\"" -#: commands/dbcommands.c:1050 commands/dbcommands.c:1056 +#: commands/dbcommands.c:1057 commands/dbcommands.c:1063 #, c-format msgid "If the locale name is specific to ICU, use ICU_LOCALE." msgstr "Якщо ім'я локалі характерне для ICU, використовуйте ICU_LOCALE." -#: commands/dbcommands.c:1055 +#: commands/dbcommands.c:1062 #, c-format msgid "invalid LC_CTYPE locale name: \"%s\"" msgstr "неприпустиме ім'я локалі LC_CTYPE: \"%s\"" -#: commands/dbcommands.c:1066 +#: commands/dbcommands.c:1074 +#, c-format +msgid "BUILTIN_LOCALE cannot be specified unless locale provider is builtin" +msgstr "BUILTIN_LOCALE не може бути вказано, якщо постачальник локалі не вбудований" + +#: commands/dbcommands.c:1082 +#, c-format +msgid "ICU locale cannot be specified unless locale provider is ICU" +msgstr "ICU локаль не може бути визначена, якщо постачальник локалі не ICU" + +#: commands/dbcommands.c:1100 +#, c-format +msgid "LOCALE or BUILTIN_LOCALE must be specified" +msgstr "Необхідно вказати LOCALE або BUILTIN_LOCALE" + +#: commands/dbcommands.c:1109 #, c-format msgid "encoding \"%s\" is not supported with ICU provider" msgstr "кодування \"%s\" не підтримується провайдером ICU" -#: commands/dbcommands.c:1076 +#: commands/dbcommands.c:1119 #, c-format msgid "LOCALE or ICU_LOCALE must be specified" msgstr "Необхідно вказати LOCALE або ICU_LOCALE" -#: commands/dbcommands.c:1105 -#, c-format -msgid "ICU locale cannot be specified unless locale provider is ICU" -msgstr "ICU локаль не може бути визначена, якщо постачальник локалі не ICU" - -#: commands/dbcommands.c:1128 +#: commands/dbcommands.c:1163 #, c-format msgid "new encoding (%s) is incompatible with the encoding of the template database (%s)" msgstr "нове кодування (%s) несумісне з кодуванням шаблона бази даних (%s)" -#: commands/dbcommands.c:1131 +#: commands/dbcommands.c:1166 #, c-format msgid "Use the same encoding as in the template database, or use template0 as template." msgstr "Використайте кодування шаблона бази даних або виберіть template0 в якості шаблона." -#: commands/dbcommands.c:1136 +#: commands/dbcommands.c:1171 #, c-format msgid "new collation (%s) is incompatible with the collation of the template database (%s)" msgstr "нове правило сортування (%s) несумісне з правилом в шаблоні бази даних (%s)" -#: commands/dbcommands.c:1138 +#: commands/dbcommands.c:1173 #, c-format msgid "Use the same collation as in the template database, or use template0 as template." msgstr "Використайте те ж саме правило сортування, що і в шаблоні бази даних, або виберіть template0 в якості шаблона." -#: commands/dbcommands.c:1143 +#: commands/dbcommands.c:1178 #, c-format msgid "new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)" msgstr "новий параметр LC_CTYPE (%s) несумісний з LC_CTYPE в шаблоні бази даних (%s)" -#: commands/dbcommands.c:1145 +#: commands/dbcommands.c:1180 #, c-format msgid "Use the same LC_CTYPE as in the template database, or use template0 as template." msgstr "Використайте той самий LC_CTYPE, що і в шаблоні бази даних, або виберіть template0 в якості шаблона." -#: commands/dbcommands.c:1150 +#: commands/dbcommands.c:1185 #, c-format msgid "new locale provider (%s) does not match locale provider of the template database (%s)" msgstr "новий постачальник локалі (%s) не відповідає постачальнику локалі шаблону бази даних (%s)" -#: commands/dbcommands.c:1152 +#: commands/dbcommands.c:1187 #, c-format msgid "Use the same locale provider as in the template database, or use template0 as template." msgstr "Використайте такого ж постачальника локалі, що й у шаблоні бази даних, або використайте template0 в якості шаблону." -#: commands/dbcommands.c:1164 +#: commands/dbcommands.c:1199 #, c-format msgid "new ICU locale (%s) is incompatible with the ICU locale of the template database (%s)" msgstr "нова ICU локаль (%s) несумісна з ICU локалью шаблону бази даних (%s)" -#: commands/dbcommands.c:1166 +#: commands/dbcommands.c:1201 #, c-format msgid "Use the same ICU locale as in the template database, or use template0 as template." msgstr "Використайте таку ж ICU локаль, що й у шаблоні бази даних, або використайте template0 в якості шаблону." -#: commands/dbcommands.c:1177 +#: commands/dbcommands.c:1212 #, c-format msgid "new ICU collation rules (%s) are incompatible with the ICU collation rules of the template database (%s)" msgstr "нові правила сортування ICU (%s) несумісні з правилами сортування ICU шаблону бази даних (%s)" -#: commands/dbcommands.c:1179 +#: commands/dbcommands.c:1214 #, c-format msgid "Use the same ICU collation rules as in the template database, or use template0 as template." msgstr "Використайте ті ж правила сортування ICU, що й в шаблоні бази даних, або виберіть template0 в якості шаблону." -#: commands/dbcommands.c:1202 +#: commands/dbcommands.c:1243 #, c-format msgid "template database \"%s\" has a collation version, but no actual collation version could be determined" msgstr "шаблон бази даних \"%s\" має версію правил сортування, але фактичну версію визначити не вдалося" -#: commands/dbcommands.c:1207 +#: commands/dbcommands.c:1248 #, c-format msgid "template database \"%s\" has a collation version mismatch" msgstr "шаблон бази даних \"%s\" має невідповідність версії параметрів сортування" -#: commands/dbcommands.c:1209 +#: commands/dbcommands.c:1250 #, c-format msgid "The template database was created using collation version %s, but the operating system provides version %s." msgstr "Шаблон бази даних було створено за допомогою параметрів сортування версії %s, але операційна система надає версію %s." -#: commands/dbcommands.c:1212 +#: commands/dbcommands.c:1253 #, c-format msgid "Rebuild all objects in the template database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "Перебудуйте всі об'єкти шаблону бази даних, які використовують стандартний параметр сортування або виконайте ALTER DATABASE %s REFRESH COLLATION VERSION, або побудуйте PostgreSQL з правильною версією бібліотеки." -#: commands/dbcommands.c:1248 commands/dbcommands.c:1980 +#: commands/dbcommands.c:1298 commands/dbcommands.c:2048 #, c-format msgid "pg_global cannot be used as default tablespace" msgstr "pg_global не можна використати в якості табличного простору за замовчуванням" -#: commands/dbcommands.c:1274 +#: commands/dbcommands.c:1324 #, c-format msgid "cannot assign new default tablespace \"%s\"" msgstr "не вдалося призначити новий табличний простір за замовчуванням \"%s\"" -#: commands/dbcommands.c:1276 +#: commands/dbcommands.c:1326 #, c-format msgid "There is a conflict because database \"%s\" already has some tables in this tablespace." msgstr "БД \"%s\" вже містить таблиці, що знаходяться в цьому табличному просторі." -#: commands/dbcommands.c:1306 commands/dbcommands.c:1853 +#: commands/dbcommands.c:1356 commands/dbcommands.c:1921 #, c-format msgid "database \"%s\" already exists" msgstr "база даних \"%s\" вже існує" -#: commands/dbcommands.c:1320 +#: commands/dbcommands.c:1370 #, c-format msgid "source database \"%s\" is being accessed by other users" msgstr "вихідна база даних \"%s\" зайнята іншими користувачами" -#: commands/dbcommands.c:1342 +#: commands/dbcommands.c:1392 #, c-format msgid "database OID %u is already in use by database \"%s\"" msgstr "OID %u вже використовується базою даних \"%s\" вже використовує" -#: commands/dbcommands.c:1348 +#: commands/dbcommands.c:1398 #, c-format msgid "data directory with the specified OID %u already exists" msgstr "каталог даних з вказаним OID %u вже існує" -#: commands/dbcommands.c:1520 commands/dbcommands.c:1535 +#: commands/dbcommands.c:1571 commands/dbcommands.c:1586 +#: utils/adt/pg_locale.c:2565 #, c-format msgid "encoding \"%s\" does not match locale \"%s\"" msgstr "кодування \"%s\" не відповідає локалі \"%s\"" -#: commands/dbcommands.c:1523 +#: commands/dbcommands.c:1574 #, c-format msgid "The chosen LC_CTYPE setting requires encoding \"%s\"." msgstr "Обраний параметр LC_CTYPE потребує кодування \"%s\"." -#: commands/dbcommands.c:1538 +#: commands/dbcommands.c:1589 #, c-format msgid "The chosen LC_COLLATE setting requires encoding \"%s\"." msgstr "Обраний параметр LC_COLLATE потребує кодування \"%s\"." -#: commands/dbcommands.c:1619 +#: commands/dbcommands.c:1672 #, c-format msgid "database \"%s\" does not exist, skipping" msgstr "бази даних \"%s\" не існує, пропускаємо" -#: commands/dbcommands.c:1643 +#: commands/dbcommands.c:1696 #, c-format msgid "cannot drop a template database" msgstr "неможливо видалити шаблон бази даних" -#: commands/dbcommands.c:1649 +#: commands/dbcommands.c:1702 #, c-format msgid "cannot drop the currently open database" msgstr "неможливо видалити наразі відкриту базу даних" -#: commands/dbcommands.c:1662 +#: commands/dbcommands.c:1715 #, c-format msgid "database \"%s\" is used by an active logical replication slot" msgstr "база даних \"%s\" використовується активним слотом логічної реплікації" -#: commands/dbcommands.c:1664 +#: commands/dbcommands.c:1717 #, c-format msgid "There is %d active slot." msgid_plural "There are %d active slots." @@ -7539,12 +7843,12 @@ msgstr[1] "Активні слоти %d." msgstr[2] "Активних слотів %d." msgstr[3] "Активних слотів %d." -#: commands/dbcommands.c:1678 +#: commands/dbcommands.c:1731 #, c-format msgid "database \"%s\" is being used by logical replication subscription" msgstr "база даних \"%s\" використовується в підписці логічної реплікації" -#: commands/dbcommands.c:1680 +#: commands/dbcommands.c:1733 #, c-format msgid "There is %d subscription." msgid_plural "There are %d subscriptions." @@ -7553,74 +7857,74 @@ msgstr[1] "Знайдено підписки %d." msgstr[2] "Знайдено підписок %d." msgstr[3] "Знайдено підписок %d." -#: commands/dbcommands.c:1701 commands/dbcommands.c:1875 -#: commands/dbcommands.c:2002 +#: commands/dbcommands.c:1754 commands/dbcommands.c:1943 +#: commands/dbcommands.c:2070 #, c-format msgid "database \"%s\" is being accessed by other users" msgstr "база даних \"%s\" зайнята іншими користувачами" -#: commands/dbcommands.c:1835 +#: commands/dbcommands.c:1903 #, c-format msgid "permission denied to rename database" msgstr "немає дозволу для перейменування бази даних" -#: commands/dbcommands.c:1864 +#: commands/dbcommands.c:1932 #, c-format msgid "current database cannot be renamed" msgstr "поточна база даних не може бути перейменована" -#: commands/dbcommands.c:1958 +#: commands/dbcommands.c:2026 #, c-format msgid "cannot change the tablespace of the currently open database" msgstr "неможливо змінити табличний простір наразі відкритої бази даних" -#: commands/dbcommands.c:2064 +#: commands/dbcommands.c:2132 #, c-format msgid "some relations of database \"%s\" are already in tablespace \"%s\"" msgstr "деякі відношення бази даних \"%s\" вже є в табличному просторі \"%s\"" -#: commands/dbcommands.c:2066 +#: commands/dbcommands.c:2134 #, c-format msgid "You must move them back to the database's default tablespace before using this command." msgstr "Перед тим, як виконувати цю команду, вам треба повернути їх в табличний простір за замовчуванням для цієї бази даних." -#: commands/dbcommands.c:2193 commands/dbcommands.c:2909 -#: commands/dbcommands.c:3209 commands/dbcommands.c:3322 +#: commands/dbcommands.c:2261 commands/dbcommands.c:2996 +#: commands/dbcommands.c:3296 commands/dbcommands.c:3409 #, c-format msgid "some useless files may be left behind in old database directory \"%s\"" msgstr "у старому каталозі бази даних \"%s\" могли залишитися непотрібні файли" -#: commands/dbcommands.c:2254 +#: commands/dbcommands.c:2322 #, c-format msgid "unrecognized DROP DATABASE option \"%s\"" msgstr "нерозпізнаний параметр DROP DATABASE \"%s\"" -#: commands/dbcommands.c:2332 +#: commands/dbcommands.c:2400 #, c-format msgid "option \"%s\" cannot be specified with other options" msgstr "параметр \"%s\" не може бути вказаним з іншими параметрами" -#: commands/dbcommands.c:2379 +#: commands/dbcommands.c:2447 #, c-format msgid "cannot alter invalid database \"%s\"" msgstr "неможливо змінити невірну базу даних \"%s\"" -#: commands/dbcommands.c:2396 +#: commands/dbcommands.c:2464 #, c-format msgid "cannot disallow connections for current database" msgstr "не можна заборонити з'єднання для поточної бази даних" -#: commands/dbcommands.c:2611 +#: commands/dbcommands.c:2690 #, c-format msgid "permission denied to change owner of database" msgstr "немає дозволу для зміни власника бази даних" -#: commands/dbcommands.c:3015 +#: commands/dbcommands.c:3102 #, c-format msgid "There are %d other session(s) and %d prepared transaction(s) using the database." msgstr "Знайдено %d інших сеансів і %d підготованих транзакцій з використанням цієї бази даних." -#: commands/dbcommands.c:3018 +#: commands/dbcommands.c:3105 #, c-format msgid "There is %d other session using the database." msgid_plural "There are %d other sessions using the database." @@ -7629,7 +7933,7 @@ msgstr[1] "Є %d інші сеанси з використанням цієї б msgstr[2] "Є %d інших сеансів з використанням цієї бази даних." msgstr[3] "Є %d інших сеансів з використанням цієї бази даних." -#: commands/dbcommands.c:3023 storage/ipc/procarray.c:3797 +#: commands/dbcommands.c:3110 storage/ipc/procarray.c:3859 #, c-format msgid "There is %d prepared transaction using the database." msgid_plural "There are %d prepared transactions using the database." @@ -7638,583 +7942,598 @@ msgstr[1] "З цією базою даних пов'язані %d підгото msgstr[2] "З цією базою даних пов'язані %d підготовлених транзакцій." msgstr[3] "З цією базою даних пов'язані %d підготовлених транзакцій." -#: commands/dbcommands.c:3165 +#: commands/dbcommands.c:3252 #, c-format msgid "missing directory \"%s\"" msgstr "відсутній каталог \"%s\"" -#: commands/dbcommands.c:3223 commands/tablespace.c:190 -#: commands/tablespace.c:639 +#: commands/dbcommands.c:3310 commands/tablespace.c:184 +#: commands/tablespace.c:633 #, c-format msgid "could not stat directory \"%s\": %m" msgstr "не вдалося отримати інформацію про каталог \"%s\": %m" -#: commands/define.c:54 commands/define.c:258 commands/define.c:290 -#: commands/define.c:318 commands/define.c:364 +#: commands/define.c:53 commands/define.c:257 commands/define.c:289 +#: commands/define.c:317 commands/define.c:363 #, c-format msgid "%s requires a parameter" msgstr "%s потребує параметру" -#: commands/define.c:87 commands/define.c:98 commands/define.c:192 -#: commands/define.c:210 commands/define.c:225 commands/define.c:243 +#: commands/define.c:86 commands/define.c:97 commands/define.c:191 +#: commands/define.c:209 commands/define.c:224 commands/define.c:242 #, c-format msgid "%s requires a numeric value" msgstr "%s потребує числового значення" -#: commands/define.c:154 +#: commands/define.c:153 #, c-format msgid "%s requires a Boolean value" msgstr "%s потребує логічного значення" -#: commands/define.c:168 commands/define.c:177 commands/define.c:327 +#: commands/define.c:167 commands/define.c:176 commands/define.c:326 #, c-format msgid "%s requires an integer value" msgstr "%s потребує ціле значення" -#: commands/define.c:272 +#: commands/define.c:271 #, c-format msgid "argument of %s must be a name" msgstr "аргументом %s повинно бути ім'я" -#: commands/define.c:302 +#: commands/define.c:301 #, c-format msgid "argument of %s must be a type name" msgstr "аргументом %s повинно бути ім'я типу" -#: commands/define.c:348 +#: commands/define.c:347 #, c-format msgid "invalid argument for %s: \"%s\"" msgstr "невірний аргумент для %s: \"%s\"" -#: commands/dropcmds.c:101 commands/functioncmds.c:1387 -#: utils/adt/ruleutils.c:2895 +#: commands/dropcmds.c:96 commands/functioncmds.c:1382 +#: utils/adt/ruleutils.c:2905 #, c-format msgid "\"%s\" is an aggregate function" msgstr "\"%s\" є функцією агрегату" -#: commands/dropcmds.c:103 +#: commands/dropcmds.c:98 #, c-format msgid "Use DROP AGGREGATE to drop aggregate functions." msgstr "Використайте DROP AGGREGATE, щоб видалити агрегатні функції." -#: commands/dropcmds.c:158 commands/sequence.c:474 commands/tablecmds.c:3710 -#: commands/tablecmds.c:3868 commands/tablecmds.c:3920 -#: commands/tablecmds.c:16482 tcop/utility.c:1336 +#: commands/dropcmds.c:153 commands/sequence.c:462 commands/tablecmds.c:3872 +#: commands/tablecmds.c:4030 commands/tablecmds.c:4082 +#: commands/tablecmds.c:17058 tcop/utility.c:1325 #, c-format msgid "relation \"%s\" does not exist, skipping" msgstr "відношення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:188 commands/dropcmds.c:287 commands/tablecmds.c:1285 +#: commands/dropcmds.c:183 commands/dropcmds.c:282 commands/tablecmds.c:1392 #, c-format msgid "schema \"%s\" does not exist, skipping" msgstr "схеми \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:228 commands/dropcmds.c:267 commands/tablecmds.c:277 +#: commands/dropcmds.c:223 commands/dropcmds.c:262 commands/tablecmds.c:286 #, c-format msgid "type \"%s\" does not exist, skipping" msgstr "типу \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:257 +#: commands/dropcmds.c:252 #, c-format msgid "access method \"%s\" does not exist, skipping" msgstr "методу доступу \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:275 +#: commands/dropcmds.c:270 #, c-format msgid "collation \"%s\" does not exist, skipping" msgstr "правила сортування \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:282 +#: commands/dropcmds.c:277 #, c-format msgid "conversion \"%s\" does not exist, skipping" msgstr "перетворення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:293 commands/statscmds.c:654 +#: commands/dropcmds.c:288 commands/statscmds.c:664 #, c-format msgid "statistics object \"%s\" does not exist, skipping" msgstr "об'єкту статистики \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:300 +#: commands/dropcmds.c:295 #, c-format msgid "text search parser \"%s\" does not exist, skipping" msgstr "парсеру текстового пошуку \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:307 +#: commands/dropcmds.c:302 #, c-format msgid "text search dictionary \"%s\" does not exist, skipping" msgstr "словника текстового пошуку \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:314 +#: commands/dropcmds.c:309 #, c-format msgid "text search template \"%s\" does not exist, skipping" msgstr "шаблону текстового пошуку \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:321 +#: commands/dropcmds.c:316 #, c-format msgid "text search configuration \"%s\" does not exist, skipping" msgstr "конфігурації текстового пошуку \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:326 +#: commands/dropcmds.c:321 #, c-format msgid "extension \"%s\" does not exist, skipping" msgstr "розширення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:336 +#: commands/dropcmds.c:331 #, c-format msgid "function %s(%s) does not exist, skipping" msgstr "функції %s(%s) не існує, пропускаємо" -#: commands/dropcmds.c:349 +#: commands/dropcmds.c:344 #, c-format msgid "procedure %s(%s) does not exist, skipping" msgstr "процедури %s(%s) не існує, пропускаємо" -#: commands/dropcmds.c:362 +#: commands/dropcmds.c:357 #, c-format msgid "routine %s(%s) does not exist, skipping" msgstr "підпрограми %s(%s) не існує, пропускаємо" -#: commands/dropcmds.c:375 +#: commands/dropcmds.c:370 #, c-format msgid "aggregate %s(%s) does not exist, skipping" msgstr "агрегату %s(%s) не існує, пропускаємо" -#: commands/dropcmds.c:388 +#: commands/dropcmds.c:383 #, c-format msgid "operator %s does not exist, skipping" msgstr "оператора \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:394 +#: commands/dropcmds.c:389 #, c-format msgid "language \"%s\" does not exist, skipping" msgstr "мови \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:403 +#: commands/dropcmds.c:398 #, c-format msgid "cast from type %s to type %s does not exist, skipping" msgstr "приведення від типу %s до типу %s не існує, пропускаємо" -#: commands/dropcmds.c:412 +#: commands/dropcmds.c:407 #, c-format msgid "transform for type %s language \"%s\" does not exist, skipping" msgstr "трансформації для типу %s мови \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:420 +#: commands/dropcmds.c:415 #, c-format msgid "trigger \"%s\" for relation \"%s\" does not exist, skipping" msgstr "тригеру \"%s\" для відношення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:429 +#: commands/dropcmds.c:424 #, c-format msgid "policy \"%s\" for relation \"%s\" does not exist, skipping" msgstr "політики \"%s\" для відношення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:436 +#: commands/dropcmds.c:431 #, c-format msgid "event trigger \"%s\" does not exist, skipping" msgstr "тригеру подій \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:442 +#: commands/dropcmds.c:437 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist, skipping" msgstr "правила \"%s\" для відношення \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:449 +#: commands/dropcmds.c:444 #, c-format msgid "foreign-data wrapper \"%s\" does not exist, skipping" msgstr "джерела сторонніх даних \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:453 commands/foreigncmds.c:1360 +#: commands/dropcmds.c:448 commands/foreigncmds.c:1360 #, c-format msgid "server \"%s\" does not exist, skipping" msgstr "серверу \"%s\" не існує, пропускаємо" -#: commands/dropcmds.c:462 +#: commands/dropcmds.c:457 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\", skipping" msgstr "класу операторів \"%s\" не існує для методу доступу \"%s\", пропускаємо" -#: commands/dropcmds.c:474 +#: commands/dropcmds.c:469 #, c-format msgid "operator family \"%s\" does not exist for access method \"%s\", skipping" msgstr "сімейства операторів \"%s\" не існує для методу доступу \"%s\", пропускаємо" -#: commands/dropcmds.c:481 +#: commands/dropcmds.c:476 #, c-format msgid "publication \"%s\" does not exist, skipping" msgstr "публікації \"%s\" не існує, пропускаємо" -#: commands/event_trigger.c:125 +#: commands/event_trigger.c:137 #, c-format msgid "permission denied to create event trigger \"%s\"" msgstr "немає дозволу для створення тригера подій %s\"" -#: commands/event_trigger.c:127 +#: commands/event_trigger.c:139 #, c-format msgid "Must be superuser to create an event trigger." msgstr "Тільки суперкористувач може створити тригер подій." -#: commands/event_trigger.c:136 +#: commands/event_trigger.c:149 #, c-format msgid "unrecognized event name \"%s\"" msgstr "нерозпізнане ім'я подій \"%s\"" -#: commands/event_trigger.c:153 +#: commands/event_trigger.c:166 #, c-format msgid "unrecognized filter variable \"%s\"" msgstr "нерозпізнана змінна фільтру \"%s\"" -#: commands/event_trigger.c:207 +#: commands/event_trigger.c:181 +#, c-format +msgid "tag filtering is not supported for login event triggers" +msgstr "фільтрація тегів не підтримується для тригерів події входу" + +#: commands/event_trigger.c:224 #, c-format msgid "filter value \"%s\" not recognized for filter variable \"%s\"" msgstr "значення фільтру \"%s\" не розпізнано для змінної фільтру \"%s\"" #. translator: %s represents an SQL statement name -#: commands/event_trigger.c:213 commands/event_trigger.c:235 +#: commands/event_trigger.c:230 commands/event_trigger.c:252 #, c-format msgid "event triggers are not supported for %s" msgstr "для %s тригери подій не підтримуються" -#: commands/event_trigger.c:248 +#: commands/event_trigger.c:265 #, c-format msgid "filter variable \"%s\" specified more than once" msgstr "змінну фільтра \"%s\" вказано кілька разів" -#: commands/event_trigger.c:376 commands/event_trigger.c:420 -#: commands/event_trigger.c:514 +#: commands/event_trigger.c:435 commands/event_trigger.c:487 +#: commands/event_trigger.c:581 #, c-format msgid "event trigger \"%s\" does not exist" msgstr "тригеру подій \"%s\" не існує" -#: commands/event_trigger.c:452 +#: commands/event_trigger.c:519 #, c-format msgid "event trigger with OID %u does not exist" msgstr "тригер подій %u з OID не існує" -#: commands/event_trigger.c:482 +#: commands/event_trigger.c:549 #, c-format msgid "permission denied to change owner of event trigger \"%s\"" msgstr "немає дозволу для зміни власника тригера подій \"%s\"" -#: commands/event_trigger.c:484 +#: commands/event_trigger.c:551 #, c-format msgid "The owner of an event trigger must be a superuser." msgstr "Власником тригеру подій може бути тільки суперкористувач." -#: commands/event_trigger.c:1304 +#: commands/event_trigger.c:1411 #, c-format msgid "%s can only be called in a sql_drop event trigger function" msgstr "%s можливо викликати лише в подієвій тригерній функції sql_drop" -#: commands/event_trigger.c:1397 commands/event_trigger.c:1418 +#: commands/event_trigger.c:1504 commands/event_trigger.c:1525 #, c-format msgid "%s can only be called in a table_rewrite event trigger function" msgstr "%s можливо викликати лише в подієвій тригерній функції table_rewrite" -#: commands/event_trigger.c:1831 +#: commands/event_trigger.c:1938 #, c-format msgid "%s can only be called in an event trigger function" msgstr "%s можливо викликати тільки в подієвій тригерній функції" -#: commands/explain.c:220 +#: commands/explain.c:241 commands/explain.c:266 #, c-format msgid "unrecognized value for EXPLAIN option \"%s\": \"%s\"" msgstr "нерозпізнане значення параметру EXPLAIN \"%s\": \"%s\"" -#: commands/explain.c:227 +#: commands/explain.c:273 #, c-format msgid "unrecognized EXPLAIN option \"%s\"" msgstr "нерозпізнаний параметр EXPLAIN \"%s\"" -#: commands/explain.c:236 +#: commands/explain.c:282 #, c-format msgid "EXPLAIN option WAL requires ANALYZE" msgstr "Параметр WAL оператора EXPLAIN потребує вказівки ANALYZE" -#: commands/explain.c:245 +#: commands/explain.c:291 #, c-format msgid "EXPLAIN option TIMING requires ANALYZE" msgstr "Параметр TIMING оператора EXPLAIN потребує вказівки ANALYZE" -#: commands/explain.c:251 +#: commands/explain.c:297 +#, c-format +msgid "EXPLAIN option SERIALIZE requires ANALYZE" +msgstr "Параметр SERIALIZE оператора EXPLAIN потребує вказівки ANALYZE" + +#: commands/explain.c:303 #, c-format msgid "EXPLAIN options ANALYZE and GENERIC_PLAN cannot be used together" msgstr "Параметри ANALYZE і GENERIC_PLAN не можуть використовуватись разом" -#: commands/extension.c:177 commands/extension.c:3033 +#: commands/extension.c:178 commands/extension.c:3031 #, c-format msgid "extension \"%s\" does not exist" msgstr "розширення \"%s\" не існує" -#: commands/extension.c:276 commands/extension.c:285 commands/extension.c:297 -#: commands/extension.c:307 +#: commands/extension.c:277 commands/extension.c:286 commands/extension.c:298 +#: commands/extension.c:308 #, c-format msgid "invalid extension name: \"%s\"" msgstr "невірне ім'я розширення: \"%s\"" -#: commands/extension.c:277 +#: commands/extension.c:278 #, c-format msgid "Extension names must not be empty." msgstr "Імена розширення не повинні бути пустими." -#: commands/extension.c:286 +#: commands/extension.c:287 #, c-format msgid "Extension names must not contain \"--\"." msgstr "Імена розширення не повинні містити \"--\"." -#: commands/extension.c:298 +#: commands/extension.c:299 #, c-format msgid "Extension names must not begin or end with \"-\"." msgstr "Імена розширення не повинні починатися або закінчуватися символом \"-\"." -#: commands/extension.c:308 +#: commands/extension.c:309 #, c-format msgid "Extension names must not contain directory separator characters." msgstr "Імена розширення не повинні містити роздільники шляху." -#: commands/extension.c:323 commands/extension.c:332 commands/extension.c:341 -#: commands/extension.c:351 +#: commands/extension.c:324 commands/extension.c:333 commands/extension.c:342 +#: commands/extension.c:352 #, c-format msgid "invalid extension version name: \"%s\"" msgstr "невірне ім'я версії розширення: \"%s\"" -#: commands/extension.c:324 +#: commands/extension.c:325 #, c-format msgid "Version names must not be empty." msgstr "Імена версії не повинні бути пустими." -#: commands/extension.c:333 +#: commands/extension.c:334 #, c-format msgid "Version names must not contain \"--\"." msgstr "Імена версії не повинні містити \"--\"." -#: commands/extension.c:342 +#: commands/extension.c:343 #, c-format msgid "Version names must not begin or end with \"-\"." msgstr "Імена версії не повинні починатись або закінчуватись символом \"-\"." -#: commands/extension.c:352 +#: commands/extension.c:353 #, c-format msgid "Version names must not contain directory separator characters." msgstr "Імена версії не повинні містити роздільники шляху." -#: commands/extension.c:506 +#: commands/extension.c:507 #, c-format msgid "extension \"%s\" is not available" msgstr "розширення \"%s\" недоступне" -#: commands/extension.c:507 +#: commands/extension.c:508 #, c-format msgid "Could not open extension control file \"%s\": %m." msgstr "Не вдалося відкрити контрольний файл розширення \"%s\": %m." -#: commands/extension.c:509 +#: commands/extension.c:510 #, c-format msgid "The extension must first be installed on the system where PostgreSQL is running." msgstr "Розширення спочатку має бути встановлене в системі, де запущено PostgreSQL." -#: commands/extension.c:513 +#: commands/extension.c:514 #, c-format msgid "could not open extension control file \"%s\": %m" msgstr "не вдалося відкрити керуючий файл розширення \"%s\": %m" -#: commands/extension.c:536 commands/extension.c:546 +#: commands/extension.c:537 commands/extension.c:547 #, c-format msgid "parameter \"%s\" cannot be set in a secondary extension control file" msgstr "параметр \"%s\" не можна задавати в додатковому керуючому файлі розширення" -#: commands/extension.c:568 commands/extension.c:576 commands/extension.c:584 -#: utils/misc/guc.c:3100 +#: commands/extension.c:569 commands/extension.c:577 commands/extension.c:585 +#: utils/misc/guc.c:3147 #, c-format msgid "parameter \"%s\" requires a Boolean value" msgstr "параметр \"%s\" потребує логічного значення" -#: commands/extension.c:593 +#: commands/extension.c:594 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" не є невірним ім'ям кодування" -#: commands/extension.c:607 commands/extension.c:622 +#: commands/extension.c:608 commands/extension.c:623 #, c-format msgid "parameter \"%s\" must be a list of extension names" msgstr "параметр \"%s\" повинен містити список імен розширень" -#: commands/extension.c:629 +#: commands/extension.c:630 #, c-format msgid "unrecognized parameter \"%s\" in file \"%s\"" msgstr "нерозпізнаний параметр \"%s\" в файлі \"%s\"" -#: commands/extension.c:638 +#: commands/extension.c:639 #, c-format msgid "parameter \"schema\" cannot be specified when \"relocatable\" is true" msgstr "параметр \"schema\" не може бути вказаним, коли \"relocatable\" є дійсним" -#: commands/extension.c:816 +#: commands/extension.c:817 #, c-format msgid "transaction control statements are not allowed within an extension script" msgstr "в скрипті розширення не повинно бути операторів управління транзакціями" -#: commands/extension.c:896 +#: commands/extension.c:897 #, c-format msgid "permission denied to create extension \"%s\"" msgstr "немає дозволу для створення розширення %s\"" -#: commands/extension.c:899 +#: commands/extension.c:900 #, c-format msgid "Must have CREATE privilege on current database to create this extension." msgstr "Необхідно мати право CREATE для поточної бази даних щоб створити це розширення." -#: commands/extension.c:900 +#: commands/extension.c:901 #, c-format msgid "Must be superuser to create this extension." msgstr "Тільки суперкористувач може створити це розширення." -#: commands/extension.c:904 +#: commands/extension.c:905 #, c-format msgid "permission denied to update extension \"%s\"" msgstr "немає дозволу для оновлення розширення %s\"" -#: commands/extension.c:907 +#: commands/extension.c:908 #, c-format msgid "Must have CREATE privilege on current database to update this extension." msgstr "Необхідно мати право CREATE для поточної бази даних щоб оновити це розширення." -#: commands/extension.c:908 +#: commands/extension.c:909 #, c-format msgid "Must be superuser to update this extension." msgstr "Тільки суперкористувач може оновити це розширення." -#: commands/extension.c:1046 +#: commands/extension.c:1042 #, c-format msgid "invalid character in extension owner: must not contain any of \"%s\"" msgstr "неприпустимий символ у власника розширення: не може містити жодного з \"%s\"" -#: commands/extension.c:1070 commands/extension.c:1097 +#: commands/extension.c:1066 commands/extension.c:1093 #, c-format msgid "invalid character in extension \"%s\" schema: must not contain any of \"%s\"" msgstr "неприпустимий символ у розширенні \"%s\" схеми: не повинно містити жодної з \"%s\"" -#: commands/extension.c:1292 +#: commands/extension.c:1288 #, c-format msgid "extension \"%s\" has no update path from version \"%s\" to version \"%s\"" msgstr "розширення \"%s\" не має жодного шляху оновлення від версії \"%s\" до версії \"%s\"" -#: commands/extension.c:1500 commands/extension.c:3091 +#: commands/extension.c:1496 commands/extension.c:3089 #, c-format msgid "version to install must be specified" msgstr "для інсталяції слід указати версію" -#: commands/extension.c:1537 +#: commands/extension.c:1533 #, c-format msgid "extension \"%s\" has no installation script nor update path for version \"%s\"" msgstr "розширення \"%s\" не має ні скрипту для встановлення, ні шляху оновлення для версії \"%s\"" -#: commands/extension.c:1571 +#: commands/extension.c:1567 #, c-format msgid "extension \"%s\" must be installed in schema \"%s\"" msgstr "розширення \"%s\" треба встановлювати в схемі \"%s\"" -#: commands/extension.c:1731 +#: commands/extension.c:1727 #, c-format msgid "cyclic dependency detected between extensions \"%s\" and \"%s\"" msgstr "виявлено циклічну залежність між розширеннями \"%s\" і \"%s\"" -#: commands/extension.c:1736 +#: commands/extension.c:1732 #, c-format msgid "installing required extension \"%s\"" msgstr "встановлення необхідних розширень \"%s\"" -#: commands/extension.c:1759 +#: commands/extension.c:1755 #, c-format msgid "required extension \"%s\" is not installed" msgstr "необхідні розширення \"%s\" не встановлено" -#: commands/extension.c:1762 +#: commands/extension.c:1758 #, c-format msgid "Use CREATE EXTENSION ... CASCADE to install required extensions too." msgstr "Використайте CREATE EXTENSION ... CASCADE також для встановлення необхідних розширень." -#: commands/extension.c:1797 +#: commands/extension.c:1793 #, c-format msgid "extension \"%s\" already exists, skipping" msgstr "розширення \"%s\" вже існує, пропускаємо" -#: commands/extension.c:1804 +#: commands/extension.c:1800 #, c-format msgid "extension \"%s\" already exists" msgstr "розширення \"%s\" вже існує" -#: commands/extension.c:1815 +#: commands/extension.c:1811 #, c-format msgid "nested CREATE EXTENSION is not supported" msgstr "вкладенні оператори CREATE EXTENSION не підтримуються" -#: commands/extension.c:1979 +#: commands/extension.c:1975 #, c-format msgid "cannot drop extension \"%s\" because it is being modified" msgstr "неможливо видалити розширення \"%s\", оскільки воно змінюється" -#: commands/extension.c:2454 +#: commands/extension.c:2450 #, c-format msgid "%s can only be called from an SQL script executed by CREATE EXTENSION" msgstr "%s можна викликати лише з SQL-скрипта, виконаного CREATE EXTENSION" -#: commands/extension.c:2466 +#: commands/extension.c:2462 #, c-format msgid "OID %u does not refer to a table" msgstr "OID %u не посилається на таблицю" -#: commands/extension.c:2471 +#: commands/extension.c:2467 #, c-format msgid "table \"%s\" is not a member of the extension being created" msgstr "таблиця \"%s\" не є членом створеного розширення" -#: commands/extension.c:2817 +#: commands/extension.c:2813 #, c-format msgid "cannot move extension \"%s\" into schema \"%s\" because the extension contains the schema" msgstr "неможливо перемістити розширення \"%s\" в схему \"%s\", оскільки розширення містить схему" -#: commands/extension.c:2858 commands/extension.c:2952 +#: commands/extension.c:2854 commands/extension.c:2948 #, c-format msgid "extension \"%s\" does not support SET SCHEMA" msgstr "розширення \"%s\" не підтримує SET SCHEMA" -#: commands/extension.c:2915 +#: commands/extension.c:2911 #, c-format msgid "cannot SET SCHEMA of extension \"%s\" because other extensions prevent it" msgstr "неможливо виконати SET SCHEMA для розширення \"%s\", оскільки інші розширення заважають цьому" -#: commands/extension.c:2917 +#: commands/extension.c:2913 #, c-format msgid "Extension \"%s\" requests no relocation of extension \"%s\"." msgstr "Розширення \"%s\" запитує не переносити розширення \"%s\"." -#: commands/extension.c:2954 +#: commands/extension.c:2950 #, c-format msgid "%s is not in the extension's schema \"%s\"" msgstr "%s не є схемою розширення \"%s\"" -#: commands/extension.c:3013 +#: commands/extension.c:3011 #, c-format msgid "nested ALTER EXTENSION is not supported" msgstr "вкладенні оператори ALTER EXTENSION не підтримуються" -#: commands/extension.c:3102 +#: commands/extension.c:3100 #, c-format msgid "version \"%s\" of extension \"%s\" is already installed" msgstr "версія \"%s\" розширення \"%s\" вже встановлена" -#: commands/extension.c:3314 +#: commands/extension.c:3311 #, c-format msgid "cannot add an object of this type to an extension" msgstr "додати об'єкт цього типу до розширення не можна" -#: commands/extension.c:3380 +#: commands/extension.c:3409 #, c-format msgid "cannot add schema \"%s\" to extension \"%s\" because the schema contains the extension" msgstr "неможливо додати схему \"%s\" до розширення \"%s\", оскільки схема містить розширення" -#: commands/extension.c:3474 +#: commands/extension.c:3491 commands/typecmds.c:4042 utils/fmgr/funcapi.c:725 +#, c-format +msgid "could not find multirange type for data type %s" +msgstr "не вдалося знайти багатодіапазонний тип для типу даних %s" + +#: commands/extension.c:3532 #, c-format msgid "file \"%s\" is too large" msgstr "файл \"%s\" занадто великий" @@ -8244,7 +8563,7 @@ msgstr "Треба бути суперкористувачем, щоб змін msgid "The owner of a foreign-data wrapper must be a superuser." msgstr "Власником джерела сторонніх даних може бути тільки суперкористувач." -#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:678 +#: commands/foreigncmds.c:291 commands/foreigncmds.c:707 foreign/foreign.c:691 #, c-format msgid "foreign-data wrapper \"%s\" does not exist" msgstr "джерела сторонніх даних \"%s\" не існує" @@ -8314,7 +8633,7 @@ msgstr "зіставлення користувача \"%s\" не існує д msgid "user mapping for \"%s\" does not exist for server \"%s\", skipping" msgstr "зіставлення користувача \"%s\" не існує для сервера \"%s\", пропускаємо" -#: commands/foreigncmds.c:1507 foreign/foreign.c:391 +#: commands/foreigncmds.c:1507 foreign/foreign.c:404 #, c-format msgid "foreign-data wrapper \"%s\" has no handler" msgstr "джерело сторонніх даних \"%s\" не має обробника" @@ -8329,363 +8648,368 @@ msgstr "джерело сторонніх даних \"%s\" не підтрим msgid "importing foreign table \"%s\"" msgstr "імпорт сторонньої таблиці \"%s\"" -#: commands/functioncmds.c:109 +#: commands/functioncmds.c:104 #, c-format msgid "SQL function cannot return shell type %s" msgstr "SQL-функція не може повертати тип оболонки %s" -#: commands/functioncmds.c:114 +#: commands/functioncmds.c:109 #, c-format msgid "return type %s is only a shell" msgstr "тип, що повертається, %s - лише оболонка" -#: commands/functioncmds.c:143 parser/parse_type.c:354 +#: commands/functioncmds.c:138 parser/parse_type.c:354 #, c-format msgid "type modifier cannot be specified for shell type \"%s\"" msgstr "для типу оболонки \"%s\" неможливо вказати модифікатор типу" -#: commands/functioncmds.c:149 +#: commands/functioncmds.c:144 #, c-format msgid "type \"%s\" is not yet defined" msgstr "тип \"%s\" все ще не визначений" -#: commands/functioncmds.c:150 +#: commands/functioncmds.c:145 #, c-format msgid "Creating a shell type definition." msgstr "Створення визначення типу оболонки." -#: commands/functioncmds.c:249 +#: commands/functioncmds.c:244 #, c-format msgid "SQL function cannot accept shell type %s" msgstr "SQL-функція не може приймати значення типу оболонки %s" -#: commands/functioncmds.c:255 +#: commands/functioncmds.c:250 #, c-format msgid "aggregate cannot accept shell type %s" msgstr "агрегатна функція не може приймати значення типу оболонки %s" -#: commands/functioncmds.c:260 +#: commands/functioncmds.c:255 #, c-format msgid "argument type %s is only a shell" msgstr "тип аргументу %s - лише оболонка" -#: commands/functioncmds.c:270 +#: commands/functioncmds.c:265 #, c-format msgid "type %s does not exist" msgstr "тип \"%s\" не існує" -#: commands/functioncmds.c:284 +#: commands/functioncmds.c:279 #, c-format msgid "aggregates cannot accept set arguments" msgstr "агрегатні функції не приймають в аргументах набору" -#: commands/functioncmds.c:288 +#: commands/functioncmds.c:283 #, c-format msgid "procedures cannot accept set arguments" msgstr "процедури не приймають в аргументах набору" -#: commands/functioncmds.c:292 +#: commands/functioncmds.c:287 #, c-format msgid "functions cannot accept set arguments" msgstr "функції не приймають в аргументах набору" -#: commands/functioncmds.c:302 +#: commands/functioncmds.c:297 #, c-format msgid "VARIADIC parameter must be the last input parameter" msgstr "Параметр VARIADIC повинен бути останнім в списку вхідних параметрів" -#: commands/functioncmds.c:322 +#: commands/functioncmds.c:317 #, c-format msgid "VARIADIC parameter must be the last parameter" msgstr "Параметр VARIADIC повинен бути останнім параметром" -#: commands/functioncmds.c:347 +#: commands/functioncmds.c:342 #, c-format msgid "VARIADIC parameter must be an array" msgstr "Параметр VARIADIC повинен бути масивом" -#: commands/functioncmds.c:392 +#: commands/functioncmds.c:387 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "ім'я параметру «%s» використано декілька разів" -#: commands/functioncmds.c:410 +#: commands/functioncmds.c:405 #, c-format msgid "only input parameters can have default values" msgstr "тільки ввідні параметри можуть мати значення за замовчуванням" -#: commands/functioncmds.c:425 +#: commands/functioncmds.c:420 #, c-format msgid "cannot use table references in parameter default value" msgstr "у значенні параметру за замовчуванням не можна посилатись на таблиці" -#: commands/functioncmds.c:449 +#: commands/functioncmds.c:444 #, c-format msgid "input parameters after one with a default value must also have defaults" msgstr "вхідні параметри, наступні за параметром зі значенням \"за замовчуванням\", також повинні мати значення \"за замовчуванням\"" -#: commands/functioncmds.c:459 +#: commands/functioncmds.c:454 #, c-format msgid "procedure OUT parameters cannot appear after one with a default value" msgstr "параметри процедури OUT не можуть з'являтись після параметра зі значенням за замовчуванням" -#: commands/functioncmds.c:601 commands/functioncmds.c:780 +#: commands/functioncmds.c:596 commands/functioncmds.c:775 #, c-format msgid "invalid attribute in procedure definition" msgstr "некоректний атрибут у визначенні процедури" -#: commands/functioncmds.c:697 +#: commands/functioncmds.c:692 #, c-format msgid "support function %s must return type %s" msgstr "функція підтримки %s повинна повертати тип %s" -#: commands/functioncmds.c:708 +#: commands/functioncmds.c:703 #, c-format msgid "must be superuser to specify a support function" msgstr "для уточнення функції підтримки потрібно бути суперкористувачем" -#: commands/functioncmds.c:829 commands/functioncmds.c:1432 +#: commands/functioncmds.c:824 commands/functioncmds.c:1427 #, c-format msgid "COST must be positive" msgstr "COST має бути додатнім" -#: commands/functioncmds.c:837 commands/functioncmds.c:1440 +#: commands/functioncmds.c:832 commands/functioncmds.c:1435 #, c-format msgid "ROWS must be positive" msgstr "Значення ROWS повинно бути позитивним" -#: commands/functioncmds.c:866 +#: commands/functioncmds.c:861 #, c-format msgid "no function body specified" msgstr "не вказано тіло функції" -#: commands/functioncmds.c:871 +#: commands/functioncmds.c:866 #, c-format msgid "duplicate function body specified" msgstr "вказано тіло дубліката функції" -#: commands/functioncmds.c:876 +#: commands/functioncmds.c:871 #, c-format msgid "inline SQL function body only valid for language SQL" msgstr "вбудоване тіло функції SQL допустиме лише для мови SQL" -#: commands/functioncmds.c:918 +#: commands/functioncmds.c:913 #, c-format msgid "SQL function with unquoted function body cannot have polymorphic arguments" msgstr "SQL функція з тілом без лапок не може мати поліморфні аргументи" -#: commands/functioncmds.c:944 commands/functioncmds.c:963 +#: commands/functioncmds.c:939 commands/functioncmds.c:958 #, c-format msgid "%s is not yet supported in unquoted SQL function body" msgstr "%s ще не підтримується у тілі SQL функції без лапок" -#: commands/functioncmds.c:991 +#: commands/functioncmds.c:986 #, c-format msgid "only one AS item needed for language \"%s\"" msgstr "для мови \"%s\" потрібен лише один вираз AS" -#: commands/functioncmds.c:1096 +#: commands/functioncmds.c:1091 #, c-format msgid "no language specified" msgstr "не вказано жодної мови" -#: commands/functioncmds.c:1104 commands/functioncmds.c:2105 -#: commands/proclang.c:237 +#: commands/functioncmds.c:1099 commands/functioncmds.c:2117 +#: commands/proclang.c:235 #, c-format msgid "language \"%s\" does not exist" msgstr "мови \"%s\" не існує" -#: commands/functioncmds.c:1106 commands/functioncmds.c:2107 +#: commands/functioncmds.c:1101 commands/functioncmds.c:2119 #, c-format msgid "Use CREATE EXTENSION to load the language into the database." msgstr "Використайте CREATE EXTENSION, щоб завантажити мову в базу даних." -#: commands/functioncmds.c:1139 commands/functioncmds.c:1424 +#: commands/functioncmds.c:1134 commands/functioncmds.c:1419 #, c-format msgid "only superuser can define a leakproof function" msgstr "лише суперкористувачі можуть визначити функцію з атрибутом leakproof" -#: commands/functioncmds.c:1190 +#: commands/functioncmds.c:1185 #, c-format msgid "function result type must be %s because of OUT parameters" msgstr "результат функції повинен мати тип %s відповідно з параметрами OUT" -#: commands/functioncmds.c:1203 +#: commands/functioncmds.c:1198 #, c-format msgid "function result type must be specified" msgstr "необхідно вказати тип результату функції" -#: commands/functioncmds.c:1256 commands/functioncmds.c:1444 +#: commands/functioncmds.c:1251 commands/functioncmds.c:1439 #, c-format msgid "ROWS is not applicable when function does not return a set" msgstr "ROWS не застосовується, коли функція не повертає набір" -#: commands/functioncmds.c:1547 +#: commands/functioncmds.c:1546 #, c-format msgid "source data type %s is a pseudo-type" msgstr "вихідний тип даних %s є псевдотипом" -#: commands/functioncmds.c:1553 +#: commands/functioncmds.c:1552 #, c-format msgid "target data type %s is a pseudo-type" msgstr "цільовий тип даних %s є псевдотипом" -#: commands/functioncmds.c:1577 +#: commands/functioncmds.c:1576 #, c-format msgid "cast will be ignored because the source data type is a domain" msgstr "приведення буде ігноруватися, оскільки вихідні дані мають тип домену" -#: commands/functioncmds.c:1582 +#: commands/functioncmds.c:1581 #, c-format msgid "cast will be ignored because the target data type is a domain" msgstr "приведення буде ігноруватися, оскільки цільові дані мають тип домену" -#: commands/functioncmds.c:1607 +#: commands/functioncmds.c:1606 #, c-format msgid "cast function must take one to three arguments" msgstr "функція приведення повинна приймати від одного до трьох аргументів" -#: commands/functioncmds.c:1613 +#: commands/functioncmds.c:1612 #, c-format msgid "argument of cast function must match or be binary-coercible from source data type" msgstr "аргумент функції приведення повинен співпадати або бути двійково-сумісним з вихідним типом даних" -#: commands/functioncmds.c:1617 +#: commands/functioncmds.c:1616 #, c-format msgid "second argument of cast function must be type %s" msgstr "другий аргумент функції приведення повинен мати тип %s" -#: commands/functioncmds.c:1622 +#: commands/functioncmds.c:1621 #, c-format msgid "third argument of cast function must be type %s" msgstr "третій аргумент функції приведення повинен мати тип %s" -#: commands/functioncmds.c:1629 +#: commands/functioncmds.c:1628 #, c-format msgid "return data type of cast function must match or be binary-coercible to target data type" msgstr "тип вертаючих даних функції приведення повинен співпадати або бути двійково-сумісним з цільовим типом даних" -#: commands/functioncmds.c:1640 +#: commands/functioncmds.c:1639 #, c-format msgid "cast function must not be volatile" msgstr "функція приведення не може бути змінною (volatile)" -#: commands/functioncmds.c:1645 +#: commands/functioncmds.c:1644 #, c-format msgid "cast function must be a normal function" msgstr "функція приведення повинна бути звичайною функцією" -#: commands/functioncmds.c:1649 +#: commands/functioncmds.c:1648 #, c-format msgid "cast function must not return a set" msgstr "функція приведення не може вертати набір" -#: commands/functioncmds.c:1675 +#: commands/functioncmds.c:1674 #, c-format msgid "must be superuser to create a cast WITHOUT FUNCTION" msgstr "тільки суперкористувач може створити приведення WITHOUT FUNCTION" -#: commands/functioncmds.c:1690 +#: commands/functioncmds.c:1689 #, c-format msgid "source and target data types are not physically compatible" msgstr "вихідний та цільовий типи даних не сумісні фізично" -#: commands/functioncmds.c:1705 +#: commands/functioncmds.c:1709 #, c-format msgid "composite data types are not binary-compatible" msgstr "складені типи даних не сумісні на двійковому рівні" -#: commands/functioncmds.c:1711 -#, c-format -msgid "enum data types are not binary-compatible" -msgstr "типи переліку не сумісні на двійковому рівні" - -#: commands/functioncmds.c:1717 +#: commands/functioncmds.c:1715 #, c-format msgid "array data types are not binary-compatible" msgstr "типи масивів не сумісні на двійковому рівні" -#: commands/functioncmds.c:1734 +#: commands/functioncmds.c:1723 +#, c-format +msgid "range data types are not binary-compatible" +msgstr "типи-діапазону не сумісні на двійковому рівні" + +#: commands/functioncmds.c:1729 +#, c-format +msgid "enum data types are not binary-compatible" +msgstr "типи переліку не сумісні на двійковому рівні" + +#: commands/functioncmds.c:1746 #, c-format msgid "domain data types must not be marked binary-compatible" msgstr "типи доменів не можуть вважатись сумісними на двійковому рівні" -#: commands/functioncmds.c:1744 +#: commands/functioncmds.c:1756 #, c-format msgid "source data type and target data type are the same" msgstr "вихідний тип даних співпадає з цільовим типом" -#: commands/functioncmds.c:1777 +#: commands/functioncmds.c:1789 #, c-format msgid "transform function must not be volatile" msgstr "функція перетворення не може бути мінливою" -#: commands/functioncmds.c:1781 +#: commands/functioncmds.c:1793 #, c-format msgid "transform function must be a normal function" msgstr "функція перетворення повинна бути нормальною функцією" -#: commands/functioncmds.c:1785 +#: commands/functioncmds.c:1797 #, c-format msgid "transform function must not return a set" msgstr "функція перетворення не повинна повертати набір" -#: commands/functioncmds.c:1789 +#: commands/functioncmds.c:1801 #, c-format msgid "transform function must take one argument" msgstr "функція перетворення повинна приймати один аргумент" -#: commands/functioncmds.c:1793 +#: commands/functioncmds.c:1805 #, c-format msgid "first argument of transform function must be type %s" msgstr "перший аргумент функції перетворення повинен бути типу %s" -#: commands/functioncmds.c:1832 +#: commands/functioncmds.c:1844 #, c-format msgid "data type %s is a pseudo-type" msgstr "тип даних %s є псевдотипом" -#: commands/functioncmds.c:1838 +#: commands/functioncmds.c:1850 #, c-format msgid "data type %s is a domain" msgstr "тип даних %s є доменом" -#: commands/functioncmds.c:1878 +#: commands/functioncmds.c:1890 #, c-format msgid "return data type of FROM SQL function must be %s" msgstr "результат функції FROM SQL має бути типу %s" -#: commands/functioncmds.c:1904 +#: commands/functioncmds.c:1916 #, c-format msgid "return data type of TO SQL function must be the transform data type" msgstr "результат функції TO SQL повинен мати тип даних перетворення" -#: commands/functioncmds.c:1931 +#: commands/functioncmds.c:1943 #, c-format msgid "transform for type %s language \"%s\" already exists" msgstr "перетворення для типу %s мови \"%s\" вже існує" -#: commands/functioncmds.c:2017 +#: commands/functioncmds.c:2029 #, c-format msgid "transform for type %s language \"%s\" does not exist" msgstr "перетворення для типу %s мови \"%s\" не існує" -#: commands/functioncmds.c:2041 +#: commands/functioncmds.c:2053 #, c-format msgid "function %s already exists in schema \"%s\"" msgstr "функція %s вже існує в схемі \"%s\"" -#: commands/functioncmds.c:2092 +#: commands/functioncmds.c:2104 #, c-format msgid "no inline code specified" msgstr "не вказано жодного впровадженого коду" -#: commands/functioncmds.c:2138 +#: commands/functioncmds.c:2150 #, c-format msgid "language \"%s\" does not support inline code execution" msgstr "мова \"%s\" не підтримує виконання впровадженого коду" -#: commands/functioncmds.c:2233 +#: commands/functioncmds.c:2245 #, c-format msgid "cannot pass more than %d argument to a procedure" msgid_plural "cannot pass more than %d arguments to a procedure" @@ -8694,555 +9018,560 @@ msgstr[1] "процедурі неможливо передати більше % msgstr[2] "процедурі неможливо передати більше %d аргументів" msgstr[3] "процедурі неможливо передати більше %d аргументів" -#: commands/indexcmds.c:640 +#: commands/indexcmds.c:648 #, c-format msgid "must specify at least one column" msgstr "треба вказати хоча б один стовпець" -#: commands/indexcmds.c:644 +#: commands/indexcmds.c:652 #, c-format msgid "cannot use more than %d columns in an index" msgstr "не можна використовувати більше ніж %d стовпців в індексі" -#: commands/indexcmds.c:687 +#: commands/indexcmds.c:695 #, c-format msgid "cannot create index on relation \"%s\"" msgstr "створити індекс для відношення \"%s\" не можна" -#: commands/indexcmds.c:713 +#: commands/indexcmds.c:721 #, c-format msgid "cannot create index on partitioned table \"%s\" concurrently" msgstr "неможливо створити індекс в секційній таблиці \"%s\" паралельним способом" -#: commands/indexcmds.c:718 -#, c-format -msgid "cannot create exclusion constraints on partitioned table \"%s\"" -msgstr "створити обмеження-виняток в секціонованій таблиці \"%s\" не можна" - -#: commands/indexcmds.c:728 +#: commands/indexcmds.c:731 #, c-format msgid "cannot create indexes on temporary tables of other sessions" msgstr "неможливо створити індекси в тимчасових таблицях в інших сеансах" -#: commands/indexcmds.c:766 commands/tablecmds.c:784 commands/tablespace.c:1184 +#: commands/indexcmds.c:769 commands/tablecmds.c:801 commands/tablespace.c:1178 #, c-format msgid "cannot specify default tablespace for partitioned relations" msgstr "для секціонованих відношень не можна вказати табличний простір за замовчуванням" -#: commands/indexcmds.c:798 commands/tablecmds.c:819 commands/tablecmds.c:3409 +#: commands/indexcmds.c:801 commands/tablecmds.c:832 commands/tablecmds.c:3571 #, c-format msgid "only shared relations can be placed in pg_global tablespace" msgstr "тільки спільні відношення можуть бути поміщені в табличний pg_global" -#: commands/indexcmds.c:831 +#: commands/indexcmds.c:834 #, c-format msgid "substituting access method \"gist\" for obsolete method \"rtree\"" msgstr "застарілий метод доступу \"rtree\" підміняється методом \"gist\"" -#: commands/indexcmds.c:852 +#: commands/indexcmds.c:855 #, c-format msgid "access method \"%s\" does not support unique indexes" msgstr "методу доступу \"%s\" не підтримує унікальні індекси" -#: commands/indexcmds.c:857 +#: commands/indexcmds.c:860 #, c-format msgid "access method \"%s\" does not support included columns" msgstr "методу доступу \"%s\" не підтримує включені стовпці" -#: commands/indexcmds.c:862 +#: commands/indexcmds.c:865 #, c-format msgid "access method \"%s\" does not support multicolumn indexes" msgstr "метод доступу \"%s\" не підтримує багатостовпцеві індекси" -#: commands/indexcmds.c:867 +#: commands/indexcmds.c:870 #, c-format msgid "access method \"%s\" does not support exclusion constraints" msgstr "метод доступу \"%s\" не підтримує обмеження-винятки" -#: commands/indexcmds.c:994 +#: commands/indexcmds.c:999 #, c-format msgid "cannot match partition key to an index using access method \"%s\"" msgstr "не можна зіставити ключ розділу з індексом використовуючи метод доступу \"%s\"" -#: commands/indexcmds.c:1004 +#: commands/indexcmds.c:1009 #, c-format msgid "unsupported %s constraint with partition key definition" msgstr "непідтримуване обмеження \"%s\" з визначенням ключа секціонування" -#: commands/indexcmds.c:1006 +#: commands/indexcmds.c:1011 #, c-format msgid "%s constraints cannot be used when partition keys include expressions." msgstr "обмеження %s не можуть використовуватись, якщо ключі секціонування включають вирази." -#: commands/indexcmds.c:1048 +#: commands/indexcmds.c:1061 +#, c-format +msgid "cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"" +msgstr "не вдається зіставити ключ розділу з індексом у стовпці \"%s\" за допомогою оператора нерівності \"%s\"" + +#: commands/indexcmds.c:1077 #, c-format msgid "unique constraint on partitioned table must include all partitioning columns" msgstr "обмеження унікальності в секціонованій таблиці повинно включати всі стовпці секціонування" -#: commands/indexcmds.c:1049 +#: commands/indexcmds.c:1078 #, c-format msgid "%s constraint on table \"%s\" lacks column \"%s\" which is part of the partition key." msgstr "в обмеженні %s таблиці\"%s\" не вистачає стовпця \"%s\", що є частиною ключа секціонування." -#: commands/indexcmds.c:1068 commands/indexcmds.c:1087 +#: commands/indexcmds.c:1097 commands/indexcmds.c:1116 #, c-format msgid "index creation on system columns is not supported" msgstr "створення індексу для системних стовпців не підтримується" -#: commands/indexcmds.c:1316 tcop/utility.c:1526 +#: commands/indexcmds.c:1346 tcop/utility.c:1515 #, c-format msgid "cannot create unique index on partitioned table \"%s\"" msgstr "не можна створити унікальний індекс в секціонованій таблиці \"%s\"" -#: commands/indexcmds.c:1318 tcop/utility.c:1528 +#: commands/indexcmds.c:1348 tcop/utility.c:1517 #, c-format msgid "Table \"%s\" contains partitions that are foreign tables." msgstr "Таблиця \"%s\" містить секції, які є зовнішніми таблицями." -#: commands/indexcmds.c:1803 +#: commands/indexcmds.c:1833 #, c-format msgid "functions in index predicate must be marked IMMUTABLE" msgstr "функції в предикаті індексу повинні бути позначені як IMMUTABLE" -#: commands/indexcmds.c:1881 parser/parse_utilcmd.c:2522 -#: parser/parse_utilcmd.c:2657 +#: commands/indexcmds.c:1912 parser/parse_utilcmd.c:2519 +#: parser/parse_utilcmd.c:2654 #, c-format msgid "column \"%s\" named in key does not exist" msgstr "вказаний у ключі стовпець \"%s\" не існує" -#: commands/indexcmds.c:1905 parser/parse_utilcmd.c:1821 +#: commands/indexcmds.c:1936 parser/parse_utilcmd.c:1807 #, c-format msgid "expressions are not supported in included columns" msgstr "вирази не підтримуються у включених стовпцях " -#: commands/indexcmds.c:1946 +#: commands/indexcmds.c:1977 #, c-format msgid "functions in index expression must be marked IMMUTABLE" msgstr "функції в індексному виразі повинні бути позначені як IMMUTABLE" -#: commands/indexcmds.c:1961 +#: commands/indexcmds.c:1992 #, c-format msgid "including column does not support a collation" msgstr "включені стовпці не підтримують правила сортування" -#: commands/indexcmds.c:1965 +#: commands/indexcmds.c:1996 #, c-format msgid "including column does not support an operator class" msgstr "включені стовпці не підтримують класи операторів" -#: commands/indexcmds.c:1969 +#: commands/indexcmds.c:2000 #, c-format msgid "including column does not support ASC/DESC options" msgstr "включені стовпці не підтримують параметри ASC/DESC" -#: commands/indexcmds.c:1973 +#: commands/indexcmds.c:2004 #, c-format msgid "including column does not support NULLS FIRST/LAST options" msgstr "включені стовпці не підтримують параметри NULLS FIRST/LAST" -#: commands/indexcmds.c:2014 +#: commands/indexcmds.c:2047 #, c-format msgid "could not determine which collation to use for index expression" msgstr "не вдалося визначити, яке правило сортування використати для індексного виразу" -#: commands/indexcmds.c:2022 commands/tablecmds.c:17497 commands/typecmds.c:807 -#: parser/parse_expr.c:2722 parser/parse_type.c:568 parser/parse_utilcmd.c:3783 -#: utils/adt/misc.c:586 +#: commands/indexcmds.c:2055 commands/tablecmds.c:18075 commands/typecmds.c:811 +#: parser/parse_expr.c:2785 parser/parse_type.c:568 parser/parse_utilcmd.c:3771 +#: utils/adt/misc.c:630 #, c-format msgid "collations are not supported by type %s" msgstr "тип %s не підтримує правила сортування" -#: commands/indexcmds.c:2087 +#: commands/indexcmds.c:2122 #, c-format msgid "operator %s is not commutative" msgstr "оператор %s не комутативний" -#: commands/indexcmds.c:2089 +#: commands/indexcmds.c:2124 #, c-format msgid "Only commutative operators can be used in exclusion constraints." msgstr "В обмеженнях-виключеннях можуть використовуватись лише комутативні оператори." -#: commands/indexcmds.c:2115 +#: commands/indexcmds.c:2150 #, c-format msgid "operator %s is not a member of operator family \"%s\"" msgstr "оператор %s не є членом сімейства операторів \"%s\"" -#: commands/indexcmds.c:2118 +#: commands/indexcmds.c:2153 #, c-format msgid "The exclusion operator must be related to the index operator class for the constraint." msgstr "Оператор винятку для обмеження повинен відноситись до класу операторів індексу." -#: commands/indexcmds.c:2153 +#: commands/indexcmds.c:2188 #, c-format msgid "access method \"%s\" does not support ASC/DESC options" msgstr "метод доступу \"%s\" не підтримує параметри ASC/DESC" -#: commands/indexcmds.c:2158 +#: commands/indexcmds.c:2193 #, c-format msgid "access method \"%s\" does not support NULLS FIRST/LAST options" msgstr "метод доступу \"%s\" не підтримує параметри NULLS FIRST/LAST" -#: commands/indexcmds.c:2204 commands/tablecmds.c:17522 -#: commands/tablecmds.c:17528 commands/typecmds.c:2301 +#: commands/indexcmds.c:2237 commands/tablecmds.c:18100 +#: commands/tablecmds.c:18106 commands/typecmds.c:2311 #, c-format msgid "data type %s has no default operator class for access method \"%s\"" msgstr "тип даних %s не має класу операторів за замовчуванням для методу доступу \"%s\"" -#: commands/indexcmds.c:2206 +#: commands/indexcmds.c:2239 #, c-format msgid "You must specify an operator class for the index or define a default operator class for the data type." msgstr "Ви повинні вказати клас операторів для індексу або визначити клас операторів за замовчуванням для цього типу даних." -#: commands/indexcmds.c:2235 commands/indexcmds.c:2243 -#: commands/opclasscmds.c:205 +#: commands/indexcmds.c:2268 commands/indexcmds.c:2276 +#: commands/opclasscmds.c:204 #, c-format msgid "operator class \"%s\" does not exist for access method \"%s\"" msgstr "клас операторів \"%s\" не існує для методу доступу \"%s\"" -#: commands/indexcmds.c:2257 commands/typecmds.c:2289 +#: commands/indexcmds.c:2290 commands/typecmds.c:2299 #, c-format msgid "operator class \"%s\" does not accept data type %s" msgstr "клас операторів \"%s\" не приймає тип даних %s" -#: commands/indexcmds.c:2347 +#: commands/indexcmds.c:2380 #, c-format msgid "there are multiple default operator classes for data type %s" msgstr "для типу даних %s є кілька класів операторів за замовчуванням" -#: commands/indexcmds.c:2675 +#: commands/indexcmds.c:2708 #, c-format msgid "unrecognized REINDEX option \"%s\"" msgstr "нерозпізнаний параметр REINDEX \"%s\"" -#: commands/indexcmds.c:2899 +#: commands/indexcmds.c:2940 #, c-format msgid "table \"%s\" has no indexes that can be reindexed concurrently" msgstr "таблиця \"%s\" не має індексів, які можна переіндексувати паралельно" -#: commands/indexcmds.c:2913 +#: commands/indexcmds.c:2954 #, c-format msgid "table \"%s\" has no indexes to reindex" msgstr "таблиця \"%s\" не має індексів для переіндексування" -#: commands/indexcmds.c:2958 commands/indexcmds.c:3468 -#: commands/indexcmds.c:3596 +#: commands/indexcmds.c:3001 commands/indexcmds.c:3512 +#: commands/indexcmds.c:3642 #, c-format msgid "cannot reindex system catalogs concurrently" msgstr "не можна конкурентно переіндексувати системні каталоги" -#: commands/indexcmds.c:2981 +#: commands/indexcmds.c:3025 #, c-format msgid "can only reindex the currently open database" msgstr "переіндексувати можна тільки наразі відкриту базу даних" -#: commands/indexcmds.c:3075 +#: commands/indexcmds.c:3117 #, c-format msgid "cannot reindex system catalogs concurrently, skipping all" msgstr "не можна конкурентно переіндексувати системні каталоги, пропускаємо" -#: commands/indexcmds.c:3108 +#: commands/indexcmds.c:3150 #, c-format msgid "cannot move system relations, skipping all" msgstr "не можна перемістити системні відношення, пропускаються усі" -#: commands/indexcmds.c:3154 +#: commands/indexcmds.c:3196 #, c-format msgid "while reindexing partitioned table \"%s.%s\"" msgstr "під час переіндексування секціонованої таблиці \"%s.%s\"" -#: commands/indexcmds.c:3157 +#: commands/indexcmds.c:3199 #, c-format msgid "while reindexing partitioned index \"%s.%s\"" msgstr "під час переіндексування секціонованого індексу \"%s.%s\"" -#: commands/indexcmds.c:3348 commands/indexcmds.c:4204 +#: commands/indexcmds.c:3392 commands/indexcmds.c:4268 #, c-format msgid "table \"%s.%s\" was reindexed" msgstr "таблиця \"%s.%s\" була переіндексована" -#: commands/indexcmds.c:3500 commands/indexcmds.c:3552 +#: commands/indexcmds.c:3544 commands/indexcmds.c:3597 +#, c-format +msgid "skipping reindex of invalid index \"%s.%s\"" +msgstr "пропуск пере індексації недійсного індексу \"%s.%s\"" + +#: commands/indexcmds.c:3547 commands/indexcmds.c:3600 #, c-format -msgid "cannot reindex invalid index \"%s.%s\" concurrently, skipping" -msgstr "неможливо переіндексувати пошкоджений індекс \"%s.%s\" паралельно, пропускається" +msgid "Use DROP INDEX or REINDEX INDEX." +msgstr "Використовуйте DROP INDEX або REINDEX INDEX." -#: commands/indexcmds.c:3506 +#: commands/indexcmds.c:3551 #, c-format msgid "cannot reindex exclusion constraint index \"%s.%s\" concurrently, skipping" msgstr "неможливо переіндексувати індекс обмеження-виключення \"%s.%s\" паралельно, пропускається" -#: commands/indexcmds.c:3661 +#: commands/indexcmds.c:3707 #, c-format msgid "cannot reindex this type of relation concurrently" msgstr "неможливо переіндексувати цей тип відношень паралельон" -#: commands/indexcmds.c:3682 +#: commands/indexcmds.c:3725 #, c-format msgid "cannot move non-shared relation to tablespace \"%s\"" msgstr "не можна перемістити не спільне відношення до табличного простору \"%s\"" -#: commands/indexcmds.c:4185 commands/indexcmds.c:4197 +#: commands/indexcmds.c:4249 commands/indexcmds.c:4261 #, c-format msgid "index \"%s.%s\" was reindexed" msgstr "індекс \"%s.%s\" був перебудований" -#: commands/indexcmds.c:4187 commands/indexcmds.c:4206 +#: commands/indexcmds.c:4251 commands/indexcmds.c:4270 #, c-format msgid "%s." msgstr "%s." -#: commands/lockcmds.c:92 +#: commands/lockcmds.c:91 #, c-format msgid "cannot lock relation \"%s\"" msgstr "блокувати відношення \"%s\" не можна" -#: commands/matview.c:193 +#: commands/matview.c:206 #, c-format msgid "CONCURRENTLY cannot be used when the materialized view is not populated" msgstr "CONCURRENTLY не може використовуватись, коли матеріалізоване подання не наповнено" -#: commands/matview.c:199 gram.y:18306 +#: commands/matview.c:212 gram.y:18918 #, c-format msgid "%s and %s options cannot be used together" msgstr "параметри %s та %s не можуть бути використані разом" -#: commands/matview.c:256 +#: commands/matview.c:269 #, c-format msgid "cannot refresh materialized view \"%s\" concurrently" msgstr "оновити матеріалізоване подання \"%s\" паралельно не можна" -#: commands/matview.c:259 +#: commands/matview.c:272 #, c-format msgid "Create a unique index with no WHERE clause on one or more columns of the materialized view." msgstr "Створіть унікальний індекс без речення WHERE для одного або більше стовпців матеріалізованого подання." -#: commands/matview.c:653 +#: commands/matview.c:666 #, c-format msgid "new data for materialized view \"%s\" contains duplicate rows without any null columns" msgstr "нові дані для матеріалізованого подання \"%s\" містять рядки, які дублюються (без урахування стовпців з null)" -#: commands/matview.c:655 +#: commands/matview.c:668 #, c-format msgid "Row: %s" msgstr "Рядок: %s" -#: commands/opclasscmds.c:124 +#: commands/opclasscmds.c:123 #, c-format msgid "operator family \"%s\" does not exist for access method \"%s\"" msgstr "сімейство операторів \"%s\" не існує для методу доступу \"%s\"" -#: commands/opclasscmds.c:267 +#: commands/opclasscmds.c:266 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists" msgstr "сімейство операторів \"%s\" для методу доступу \"%s\" вже існує" -#: commands/opclasscmds.c:416 +#: commands/opclasscmds.c:415 #, c-format msgid "must be superuser to create an operator class" msgstr "тільки суперкористувач може створити клас операторів" -#: commands/opclasscmds.c:493 commands/opclasscmds.c:910 -#: commands/opclasscmds.c:1056 +#: commands/opclasscmds.c:492 commands/opclasscmds.c:909 +#: commands/opclasscmds.c:1055 #, c-format msgid "invalid operator number %d, must be between 1 and %d" msgstr "неприпустимий номер оператора %d, число має бути між 1 і %d" -#: commands/opclasscmds.c:538 commands/opclasscmds.c:960 -#: commands/opclasscmds.c:1072 +#: commands/opclasscmds.c:537 commands/opclasscmds.c:959 +#: commands/opclasscmds.c:1071 #, c-format msgid "invalid function number %d, must be between 1 and %d" msgstr "неприпустимий номер функції %d, число має бути між 1 і %d" -#: commands/opclasscmds.c:567 +#: commands/opclasscmds.c:566 #, c-format msgid "storage type specified more than once" msgstr "тип сховища вказано більше одного разу" -#: commands/opclasscmds.c:594 +#: commands/opclasscmds.c:593 #, c-format msgid "storage type cannot be different from data type for access method \"%s\"" msgstr "тип сховища не може відрізнятися від типу даних для методу доступу \"%s\"" -#: commands/opclasscmds.c:610 +#: commands/opclasscmds.c:609 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists" msgstr "клас операторів \"%s\" для методу доступу \"%s\" вже існує" -#: commands/opclasscmds.c:638 +#: commands/opclasscmds.c:637 #, c-format msgid "could not make operator class \"%s\" be default for type %s" msgstr "клас операторів \"%s\" не вдалося зробити класом за замовчуванням для типу %s" -#: commands/opclasscmds.c:641 +#: commands/opclasscmds.c:640 #, c-format msgid "Operator class \"%s\" already is the default." msgstr "Клас операторів \"%s\" вже є класом за замовчуванням." -#: commands/opclasscmds.c:801 +#: commands/opclasscmds.c:800 #, c-format msgid "must be superuser to create an operator family" msgstr "тільки суперкористувач може створити сімейство операторів" -#: commands/opclasscmds.c:861 +#: commands/opclasscmds.c:860 #, c-format msgid "must be superuser to alter an operator family" msgstr "тільки суперкористувач може змінити сімейство операторів" -#: commands/opclasscmds.c:919 +#: commands/opclasscmds.c:918 #, c-format msgid "operator argument types must be specified in ALTER OPERATOR FAMILY" msgstr "типи аргументу оператора повинні бути вказані в ALTER OPERATOR FAMILY" -#: commands/opclasscmds.c:994 +#: commands/opclasscmds.c:993 #, c-format msgid "STORAGE cannot be specified in ALTER OPERATOR FAMILY" msgstr "STORAGE не може бути вказано в ALTER OPERATOR FAMILY" -#: commands/opclasscmds.c:1128 +#: commands/opclasscmds.c:1127 #, c-format msgid "one or two argument types must be specified" msgstr "треба вказати один або два типи аргументу" -#: commands/opclasscmds.c:1154 +#: commands/opclasscmds.c:1153 #, c-format msgid "index operators must be binary" msgstr "індексні оператори повинні бути бінарними" -#: commands/opclasscmds.c:1173 +#: commands/opclasscmds.c:1172 #, c-format msgid "access method \"%s\" does not support ordering operators" msgstr "метод доступу \"%s\" не підтримує сортувальних операторів" -#: commands/opclasscmds.c:1184 +#: commands/opclasscmds.c:1183 #, c-format msgid "index search operators must return boolean" msgstr "оператори пошуку по індексу повинні повертати логічне значення" -#: commands/opclasscmds.c:1224 +#: commands/opclasscmds.c:1223 #, c-format msgid "associated data types for operator class options parsing functions must match opclass input type" msgstr "пов'язані типи даних для функцій обробки параметрів класів операторів повинні відповідати типу вхідних даних opclass" -#: commands/opclasscmds.c:1231 +#: commands/opclasscmds.c:1230 #, c-format msgid "left and right associated data types for operator class options parsing functions must match" msgstr "ліві та праві пов'язані типи даних для функцій розбору параметрів класів операторів повинні збігатись" -#: commands/opclasscmds.c:1239 +#: commands/opclasscmds.c:1238 #, c-format msgid "invalid operator class options parsing function" msgstr "неприпустима функція розбору параметрів класів операторів" -#: commands/opclasscmds.c:1240 +#: commands/opclasscmds.c:1239 #, c-format msgid "Valid signature of operator class options parsing function is %s." msgstr "Допустимий підпис для функції розбору параметрів класів операторів: %s." -#: commands/opclasscmds.c:1259 +#: commands/opclasscmds.c:1258 #, c-format msgid "btree comparison functions must have two arguments" msgstr "функції порівняння btree повинні мати два аргумента" -#: commands/opclasscmds.c:1263 +#: commands/opclasscmds.c:1262 #, c-format msgid "btree comparison functions must return integer" msgstr "функції порівняння btree повинні повертати ціле число" -#: commands/opclasscmds.c:1280 +#: commands/opclasscmds.c:1279 #, c-format msgid "btree sort support functions must accept type \"internal\"" msgstr "опорні функції сортування btree повинні приймати тип \"internal\"" -#: commands/opclasscmds.c:1284 +#: commands/opclasscmds.c:1283 #, c-format msgid "btree sort support functions must return void" msgstr "опорні функції сортування btree повинні повертати недійсне (void)" -#: commands/opclasscmds.c:1295 +#: commands/opclasscmds.c:1294 #, c-format msgid "btree in_range functions must have five arguments" msgstr "функції in_range для btree повинні приймати п'ять аргументів" -#: commands/opclasscmds.c:1299 +#: commands/opclasscmds.c:1298 #, c-format msgid "btree in_range functions must return boolean" msgstr "функції in_range для btree повинні повертати логічне значення" -#: commands/opclasscmds.c:1315 +#: commands/opclasscmds.c:1314 #, c-format msgid "btree equal image functions must have one argument" msgstr "функції equal image для btree повинні приймати один аргумент" -#: commands/opclasscmds.c:1319 +#: commands/opclasscmds.c:1318 #, c-format msgid "btree equal image functions must return boolean" msgstr "функції equal image для btree повинні повертати логічне значення" -#: commands/opclasscmds.c:1332 +#: commands/opclasscmds.c:1331 #, c-format msgid "btree equal image functions must not be cross-type" msgstr "функції equal image для btree не можуть бути хрестоподібного типу" -#: commands/opclasscmds.c:1342 +#: commands/opclasscmds.c:1341 #, c-format msgid "hash function 1 must have one argument" msgstr "геш-функція 1 повинна приймати один аргумент" -#: commands/opclasscmds.c:1346 +#: commands/opclasscmds.c:1345 #, c-format msgid "hash function 1 must return integer" msgstr "геш-функція 1 повинна повертати ціле число" -#: commands/opclasscmds.c:1353 +#: commands/opclasscmds.c:1352 #, c-format msgid "hash function 2 must have two arguments" msgstr "геш-функція 2 повинна приймати два аргументи" -#: commands/opclasscmds.c:1357 +#: commands/opclasscmds.c:1356 #, c-format msgid "hash function 2 must return bigint" msgstr "геш-функція 2 повинна повертати велике ціле (bigint)" -#: commands/opclasscmds.c:1382 +#: commands/opclasscmds.c:1381 #, c-format msgid "associated data types must be specified for index support function" msgstr "для опорної функції індексів повинні бути вказані пов'язані типи даних" -#: commands/opclasscmds.c:1407 +#: commands/opclasscmds.c:1406 #, c-format msgid "function number %d for (%s,%s) appears more than once" msgstr "номер функції %d для (%s,%s) з'являється більш ніж один раз" -#: commands/opclasscmds.c:1414 +#: commands/opclasscmds.c:1413 #, c-format msgid "operator number %d for (%s,%s) appears more than once" msgstr "номер оператора %d для (%s,%s) з'являється більш ніж один раз" -#: commands/opclasscmds.c:1460 +#: commands/opclasscmds.c:1459 #, c-format msgid "operator %d(%s,%s) already exists in operator family \"%s\"" msgstr "оператор %d(%s,%s) вже існує в сімействі операторів \"%s\"" -#: commands/opclasscmds.c:1566 +#: commands/opclasscmds.c:1565 #, c-format msgid "function %d(%s,%s) already exists in operator family \"%s\"" msgstr "функція %d(%s,%s) вже існує в сімействі операторів \"%s\"" -#: commands/opclasscmds.c:1647 +#: commands/opclasscmds.c:1646 #, c-format msgid "operator %d(%s,%s) does not exist in operator family \"%s\"" msgstr "оператора %d(%s,%s) не існує в сімействі операторів \"%s\"" -#: commands/opclasscmds.c:1687 +#: commands/opclasscmds.c:1686 #, c-format msgid "function %d(%s,%s) does not exist in operator family \"%s\"" msgstr "функції %d(%s,%s) не існує в сімействі операторів \"%s\"" -#: commands/opclasscmds.c:1718 +#: commands/opclasscmds.c:1717 #, c-format msgid "operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "клас операторів \"%s\" для методу доступу \"%s\" вже існує в схемі \"%s\"" -#: commands/opclasscmds.c:1741 +#: commands/opclasscmds.c:1740 #, c-format msgid "operator family \"%s\" for access method \"%s\" already exists in schema \"%s\"" msgstr "сімейство операторів \"%s\" для методу доступу \"%s\" вже існує в схемі \"%s\"" @@ -9252,7 +9581,7 @@ msgstr "сімейство операторів \"%s\" для методу до msgid "SETOF type not allowed for operator argument" msgstr "Аргументом оператора не може бути тип SETOF" -#: commands/operatorcmds.c:154 commands/operatorcmds.c:481 +#: commands/operatorcmds.c:154 commands/operatorcmds.c:554 #, c-format msgid "operator attribute \"%s\" not recognized" msgstr "атрибут оператора \"%s\" не розпізнаний" @@ -9292,53 +9621,70 @@ msgstr "функція оцінювання з'єднання %s має декі msgid "join estimator function %s must return type %s" msgstr "функція оцінювання з'єднання %s повинна повертати тип %s" -#: commands/operatorcmds.c:475 +#: commands/operatorcmds.c:388 parser/parse_oper.c:119 parser/parse_oper.c:637 +#: utils/adt/regproc.c:509 utils/adt/regproc.c:683 +#, c-format +msgid "operator does not exist: %s" +msgstr "оператор не існує: %s" + +#: commands/operatorcmds.c:396 parser/parse_oper.c:702 parser/parse_oper.c:815 +#, c-format +msgid "operator is only a shell: %s" +msgstr "оператор є лише оболонкою: %s" + +#: commands/operatorcmds.c:548 #, c-format msgid "operator attribute \"%s\" cannot be changed" msgstr "атрибут оператора \"%s\" неможливо змінити" -#: commands/policy.c:89 commands/policy.c:382 commands/statscmds.c:149 -#: commands/tablecmds.c:1616 commands/tablecmds.c:2219 -#: commands/tablecmds.c:3520 commands/tablecmds.c:6369 -#: commands/tablecmds.c:9189 commands/tablecmds.c:17084 -#: commands/tablecmds.c:17119 commands/trigger.c:323 commands/trigger.c:1339 -#: commands/trigger.c:1449 rewrite/rewriteDefine.c:275 -#: rewrite/rewriteDefine.c:786 rewrite/rewriteRemove.c:80 +#: commands/operatorcmds.c:615 commands/operatorcmds.c:622 +#: commands/operatorcmds.c:628 commands/operatorcmds.c:634 +#, c-format +msgid "operator attribute \"%s\" cannot be changed if it has already been set" +msgstr "атрибут оператора \"%s\" не може бути змінений, якщо він вже встановлений" + +#: commands/policy.c:86 commands/policy.c:379 commands/statscmds.c:146 +#: commands/tablecmds.c:1723 commands/tablecmds.c:2323 +#: commands/tablecmds.c:3682 commands/tablecmds.c:6582 +#: commands/tablecmds.c:9614 commands/tablecmds.c:17662 +#: commands/tablecmds.c:17697 commands/trigger.c:316 commands/trigger.c:1332 +#: commands/trigger.c:1442 rewrite/rewriteDefine.c:268 +#: rewrite/rewriteDefine.c:779 rewrite/rewriteRemove.c:74 #, c-format msgid "permission denied: \"%s\" is a system catalog" msgstr "доступ заборонений: \"%s\" - системний каталог" -#: commands/policy.c:172 +#: commands/policy.c:169 #, c-format msgid "ignoring specified roles other than PUBLIC" msgstr "всі вказані ролі, крім PUBLIC, ігноруються" -#: commands/policy.c:173 +#: commands/policy.c:170 #, c-format msgid "All roles are members of the PUBLIC role." msgstr "Роль PUBLIC включає в себе всі інші ролі." -#: commands/policy.c:606 +#: commands/policy.c:603 #, c-format msgid "WITH CHECK cannot be applied to SELECT or DELETE" msgstr "WITH CHECK не можна застосувати до SELECT або DELETE" -#: commands/policy.c:615 commands/policy.c:918 +#: commands/policy.c:612 commands/policy.c:915 #, c-format msgid "only WITH CHECK expression allowed for INSERT" msgstr "для INSERT допускається лише вираз WITH CHECK" -#: commands/policy.c:689 commands/policy.c:1141 +#: commands/policy.c:686 commands/policy.c:1138 #, c-format msgid "policy \"%s\" for table \"%s\" already exists" msgstr "політика \"%s\" для таблиці \"%s\" вже існує" -#: commands/policy.c:890 commands/policy.c:1169 commands/policy.c:1240 +#: commands/policy.c:887 commands/policy.c:1166 commands/policy.c:1237 #, c-format msgid "policy \"%s\" for table \"%s\" does not exist" msgstr "політика \"%s\" для таблиці \"%s\" не існує" -#: commands/policy.c:908 +#: commands/policy.c:905 #, c-format msgid "only USING expression allowed for SELECT, DELETE" msgstr "для SELECT, DELETE допускається лише вираз USING" @@ -9354,245 +9700,244 @@ msgid "cannot create a cursor WITH HOLD within security-restricted operation" msgstr "не можна створити курсос WITH HOLD в межах операції з обмеженням по безпеці" #: commands/portalcmds.c:189 commands/portalcmds.c:242 -#: executor/execCurrent.c:70 utils/adt/xml.c:2854 utils/adt/xml.c:3024 +#: executor/execCurrent.c:70 utils/adt/xml.c:2936 utils/adt/xml.c:3106 #, c-format msgid "cursor \"%s\" does not exist" msgstr "курсор \"%s\" не існує" -#: commands/prepare.c:75 +#: commands/prepare.c:72 #, c-format msgid "invalid statement name: must not be empty" msgstr "неприпустиме ім'я оператора: не повинне бути пустим" -#: commands/prepare.c:230 commands/prepare.c:235 +#: commands/prepare.c:227 commands/prepare.c:232 #, c-format msgid "prepared statement is not a SELECT" msgstr "підготовлений оператор не SELECT" -#: commands/prepare.c:295 +#: commands/prepare.c:292 #, c-format msgid "wrong number of parameters for prepared statement \"%s\"" msgstr "невірне число параметрів для підготовленого оператора \"%s\"" -#: commands/prepare.c:297 +#: commands/prepare.c:294 #, c-format msgid "Expected %d parameters but got %d." msgstr "Очікувалось %d параметрів, але отримано %d." -#: commands/prepare.c:330 +#: commands/prepare.c:327 #, c-format msgid "parameter $%d of type %s cannot be coerced to the expected type %s" msgstr "параметр $%d типу %s не можна привести до очікуваного типу %s" -#: commands/prepare.c:414 +#: commands/prepare.c:411 #, c-format msgid "prepared statement \"%s\" already exists" msgstr "підготовлений оператор \"%s\" вже існує" -#: commands/prepare.c:453 +#: commands/prepare.c:450 #, c-format msgid "prepared statement \"%s\" does not exist" msgstr "підготовлений оператор \"%s\" не існує" -#: commands/proclang.c:68 +#: commands/proclang.c:66 #, c-format msgid "must be superuser to create custom procedural language" msgstr "для створення користувацької мови потрібно бути суперкористувачем" -#: commands/publicationcmds.c:131 postmaster/postmaster.c:1208 -#: postmaster/postmaster.c:1306 storage/file/fd.c:3911 -#: utils/init/miscinit.c:1822 +#: commands/publicationcmds.c:124 postmaster/postmaster.c:1108 +#: postmaster/postmaster.c:1210 utils/init/miscinit.c:1811 #, c-format msgid "invalid list syntax in parameter \"%s\"" msgstr "неприпустимий синтаксис списку в параметрі \"%s\"" -#: commands/publicationcmds.c:150 +#: commands/publicationcmds.c:143 #, c-format msgid "unrecognized value for publication option \"%s\": \"%s\"" msgstr "нерозпізнане значення параметра публікації \"%s\": \"%s\"" -#: commands/publicationcmds.c:164 +#: commands/publicationcmds.c:157 #, c-format msgid "unrecognized publication parameter: \"%s\"" msgstr "нерозпізнаний параметр публікації: \"%s\"" -#: commands/publicationcmds.c:205 +#: commands/publicationcmds.c:198 #, c-format msgid "no schema has been selected for CURRENT_SCHEMA" msgstr "жодної схеми не вибрано для CURRENT_SCHEMA" -#: commands/publicationcmds.c:502 +#: commands/publicationcmds.c:495 msgid "System columns are not allowed." msgstr "Системні стовпці не допускаються." -#: commands/publicationcmds.c:509 commands/publicationcmds.c:514 -#: commands/publicationcmds.c:531 +#: commands/publicationcmds.c:502 commands/publicationcmds.c:507 +#: commands/publicationcmds.c:524 msgid "User-defined operators are not allowed." msgstr "Користувацькі оператори не допускаються." -#: commands/publicationcmds.c:555 +#: commands/publicationcmds.c:548 msgid "Only columns, constants, built-in operators, built-in data types, built-in collations, and immutable built-in functions are allowed." msgstr "Дозволяються тільки стовпці, константи, вбудовані оператори, вбудовані типи даних, вбудовані параметри сортування та незмінні вбудовані функції." -#: commands/publicationcmds.c:567 +#: commands/publicationcmds.c:560 msgid "User-defined types are not allowed." msgstr "Користувацькі типи не допускаються." -#: commands/publicationcmds.c:570 +#: commands/publicationcmds.c:563 msgid "User-defined or built-in mutable functions are not allowed." msgstr "Користувацькі або вбудовані змінні функції не допускаються." -#: commands/publicationcmds.c:573 +#: commands/publicationcmds.c:566 msgid "User-defined collations are not allowed." msgstr "Користувацькі параметри сортування не допускаються." -#: commands/publicationcmds.c:583 +#: commands/publicationcmds.c:576 #, c-format msgid "invalid publication WHERE expression" msgstr "неприпустимий вираз публікації WHERE" -#: commands/publicationcmds.c:636 +#: commands/publicationcmds.c:629 #, c-format msgid "cannot use publication WHERE clause for relation \"%s\"" msgstr "використовувати вираз публікації WHERE для відношення \"%s\" не можна" -#: commands/publicationcmds.c:638 +#: commands/publicationcmds.c:631 #, c-format msgid "WHERE clause cannot be used for a partitioned table when %s is false." msgstr "вираз WHERE для секціонованих таблиць не можна використовувати, коли %s є false." -#: commands/publicationcmds.c:709 commands/publicationcmds.c:723 +#: commands/publicationcmds.c:702 commands/publicationcmds.c:716 #, c-format msgid "cannot use column list for relation \"%s.%s\" in publication \"%s\"" msgstr "не можна використовувати список стовпців для відношення \"%s.%s\" в публікації \"%s\"" -#: commands/publicationcmds.c:712 +#: commands/publicationcmds.c:705 #, c-format msgid "Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements." msgstr "Списки стовпців не можна вказувати в публікаціях, що містять елементи FOR TABLES IN SCHEMA." -#: commands/publicationcmds.c:726 +#: commands/publicationcmds.c:719 #, c-format msgid "Column lists cannot be specified for partitioned tables when %s is false." msgstr "Списки стовпців для секціонованих таблиць не можна використовувати, коли %s є false." -#: commands/publicationcmds.c:761 +#: commands/publicationcmds.c:754 #, c-format msgid "must be superuser to create FOR ALL TABLES publication" msgstr "для створення публікації УСІХ ТАБЛИЦЬ потрібно бути суперкористувачем" -#: commands/publicationcmds.c:832 +#: commands/publicationcmds.c:825 #, c-format msgid "must be superuser to create FOR TABLES IN SCHEMA publication" msgstr "щоб створити публікацію FOR TABLES IN SCHEMA потрібно бути суперкористувачем" -#: commands/publicationcmds.c:868 +#: commands/publicationcmds.c:861 #, c-format -msgid "wal_level is insufficient to publish logical changes" -msgstr "недостатній wal_level для публікації логічних змін" +msgid "\"wal_level\" is insufficient to publish logical changes" +msgstr "недостатній \"wal_level\" для публікації логічних змін" -#: commands/publicationcmds.c:869 +#: commands/publicationcmds.c:862 #, c-format -msgid "Set wal_level to \"logical\" before creating subscriptions." -msgstr "Встановіть wal_level на \"logical\" перед створенням підписок." +msgid "Set \"wal_level\" to \"logical\" before creating subscriptions." +msgstr "Встановіть \"wal_level\" на \"logical\" перед створенням підписок." -#: commands/publicationcmds.c:965 commands/publicationcmds.c:973 +#: commands/publicationcmds.c:958 commands/publicationcmds.c:966 #, c-format msgid "cannot set parameter \"%s\" to false for publication \"%s\"" msgstr "встановити параметр \"%s\" на false для публікації \"%s\" не можна" -#: commands/publicationcmds.c:968 +#: commands/publicationcmds.c:961 #, c-format msgid "The publication contains a WHERE clause for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "Публікація містить вираз WHERE для секціонованої таблиці \"%s\", який не допускається коли \"%s\" є false." -#: commands/publicationcmds.c:976 +#: commands/publicationcmds.c:969 #, c-format msgid "The publication contains a column list for partitioned table \"%s\", which is not allowed when \"%s\" is false." msgstr "Публікація містить список стовпців для секціонованої таблиці \"%s\", який не допускається коли \"%s\" є false." -#: commands/publicationcmds.c:1299 +#: commands/publicationcmds.c:1292 #, c-format msgid "cannot add schema to publication \"%s\"" msgstr "не можна додати схему до публікації \"%s\"" -#: commands/publicationcmds.c:1301 +#: commands/publicationcmds.c:1294 #, c-format msgid "Schemas cannot be added if any tables that specify a column list are already part of the publication." msgstr "Схеми не можна додавати, якщо будь-яка таблиця, що вказуює на список стовпців, вже є частиною публікації." -#: commands/publicationcmds.c:1349 +#: commands/publicationcmds.c:1342 #, c-format msgid "must be superuser to add or set schemas" msgstr "для додавання або встановлення схем потрібно бути суперкористувачем" -#: commands/publicationcmds.c:1358 commands/publicationcmds.c:1366 +#: commands/publicationcmds.c:1351 commands/publicationcmds.c:1359 #, c-format msgid "publication \"%s\" is defined as FOR ALL TABLES" msgstr "публікація \"%s\" визначена ДЛЯ ВСІХ ТАБЛИЦЬ" -#: commands/publicationcmds.c:1360 +#: commands/publicationcmds.c:1353 #, c-format msgid "Schemas cannot be added to or dropped from FOR ALL TABLES publications." msgstr "До публікації FOR ALL TABLES не можна додати або видалити схеми." -#: commands/publicationcmds.c:1368 +#: commands/publicationcmds.c:1361 #, c-format msgid "Tables cannot be added to or dropped from FOR ALL TABLES publications." msgstr "У публікації ВСІХ ТАБЛИЦЬ не можна додати або видалити таблиці." -#: commands/publicationcmds.c:1392 commands/publicationcmds.c:1431 -#: commands/publicationcmds.c:1968 utils/cache/lsyscache.c:3592 +#: commands/publicationcmds.c:1385 commands/publicationcmds.c:1424 +#: commands/publicationcmds.c:1961 utils/cache/lsyscache.c:3634 #, c-format msgid "publication \"%s\" does not exist" msgstr "публікація \"%s\" вже існує" -#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1657 +#: commands/publicationcmds.c:1587 commands/publicationcmds.c:1650 #, c-format msgid "conflicting or redundant WHERE clauses for table \"%s\"" msgstr "конфліктуючі або надлишкові вирази WHERE для таблиці \"%s\"" -#: commands/publicationcmds.c:1601 commands/publicationcmds.c:1669 +#: commands/publicationcmds.c:1594 commands/publicationcmds.c:1662 #, c-format msgid "conflicting or redundant column lists for table \"%s\"" msgstr "конфліктуючі або надлишкові списки стовпців для таблиці \"%s\"" -#: commands/publicationcmds.c:1803 +#: commands/publicationcmds.c:1796 #, c-format msgid "column list must not be specified in ALTER PUBLICATION ... DROP" msgstr "список стовпців не можна вказувати в ALTER PUBLICATION ... DROP" -#: commands/publicationcmds.c:1815 +#: commands/publicationcmds.c:1808 #, c-format msgid "relation \"%s\" is not part of the publication" msgstr "відносини \"%s\" не є частиною публікації" -#: commands/publicationcmds.c:1822 +#: commands/publicationcmds.c:1815 #, c-format msgid "cannot use a WHERE clause when removing a table from a publication" msgstr "під час видалення таблиці з публікації використовувати вираз WHERE не можна" -#: commands/publicationcmds.c:1882 +#: commands/publicationcmds.c:1875 #, c-format msgid "tables from schema \"%s\" are not part of the publication" msgstr "таблиці зі схеми \"%s\" не є частиною публікації" -#: commands/publicationcmds.c:1925 commands/publicationcmds.c:1932 +#: commands/publicationcmds.c:1918 commands/publicationcmds.c:1925 #, c-format msgid "permission denied to change owner of publication \"%s\"" msgstr "немає прав на зміну власника публікації \"%s\"" -#: commands/publicationcmds.c:1927 +#: commands/publicationcmds.c:1920 #, c-format msgid "The owner of a FOR ALL TABLES publication must be a superuser." msgstr "Власником публікації УСІХ ТАБЛИЦЬ повинен бути суперкористувач." -#: commands/publicationcmds.c:1934 +#: commands/publicationcmds.c:1927 #, c-format msgid "The owner of a FOR TABLES IN SCHEMA publication must be a superuser." msgstr "Власник публікації публікації FOR TABLES IN SCHEMA повинен бути суперкористувачем." -#: commands/publicationcmds.c:2000 +#: commands/publicationcmds.c:1993 #, c-format msgid "publication with OID %u does not exist" msgstr "публікації %u з OID не існує" @@ -9637,242 +9982,242 @@ msgstr "мітки безпеки не підтримуються для цьо msgid "cannot set security label on relation \"%s\"" msgstr "не можна встановити мітку безпеки для відношення \"%s\"" -#: commands/sequence.c:754 +#: commands/sequence.c:748 #, c-format msgid "nextval: reached maximum value of sequence \"%s\" (%lld)" msgstr "nextval: досягнено максимального значення послідовності \"%s\" (%lld)" -#: commands/sequence.c:773 +#: commands/sequence.c:767 #, c-format msgid "nextval: reached minimum value of sequence \"%s\" (%lld)" msgstr "nextval: досягнено мінімального значення послідовності \"%s\" (%lld)" -#: commands/sequence.c:891 +#: commands/sequence.c:886 #, c-format msgid "currval of sequence \"%s\" is not yet defined in this session" msgstr "поточне значення (currval) для послідовності \"%s\" ще не визначено у цьому сеансі" -#: commands/sequence.c:910 commands/sequence.c:916 +#: commands/sequence.c:905 commands/sequence.c:911 #, c-format msgid "lastval is not yet defined in this session" msgstr "останнє значення ще не визначено в цьому сеансі" -#: commands/sequence.c:996 +#: commands/sequence.c:991 #, c-format msgid "setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)" msgstr "setval: значення %lld поза межами послідовності \"%s\" (%lld..%lld)" -#: commands/sequence.c:1365 +#: commands/sequence.c:1357 #, c-format msgid "invalid sequence option SEQUENCE NAME" msgstr "неприпустимий параметр послідовності SEQUENCE NAME" -#: commands/sequence.c:1391 +#: commands/sequence.c:1383 #, c-format msgid "identity column type must be smallint, integer, or bigint" msgstr "типом стовпця ідентифікації може бути тільки smallint, integer або bigint" -#: commands/sequence.c:1392 +#: commands/sequence.c:1384 #, c-format msgid "sequence type must be smallint, integer, or bigint" msgstr "типом послідовності може бути тільки smallint, integer або bigint" -#: commands/sequence.c:1426 +#: commands/sequence.c:1418 #, c-format msgid "INCREMENT must not be zero" msgstr "INCREMENT не повинен бути нулем" -#: commands/sequence.c:1474 +#: commands/sequence.c:1466 #, c-format msgid "MAXVALUE (%lld) is out of range for sequence data type %s" msgstr "MAXVALUE (%lld) виходить за межі діапазону типу даних послідовності %s" -#: commands/sequence.c:1506 +#: commands/sequence.c:1498 #, c-format msgid "MINVALUE (%lld) is out of range for sequence data type %s" msgstr "MINVALUE (%lld) виходить за межі діапазону для типу даних послідовності %s" -#: commands/sequence.c:1514 +#: commands/sequence.c:1506 #, c-format msgid "MINVALUE (%lld) must be less than MAXVALUE (%lld)" msgstr "MINVALUE (%lld) повинно бути меншим за MAXVALUE (%lld)" -#: commands/sequence.c:1535 +#: commands/sequence.c:1527 #, c-format msgid "START value (%lld) cannot be less than MINVALUE (%lld)" msgstr "Значення START (%lld) не може бути меншим за MINVALUE (%lld)" -#: commands/sequence.c:1541 +#: commands/sequence.c:1533 #, c-format msgid "START value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "Значення START (%lld) не може бути більшим за MAXVALUE (%lld)" -#: commands/sequence.c:1565 +#: commands/sequence.c:1557 #, c-format msgid "RESTART value (%lld) cannot be less than MINVALUE (%lld)" msgstr "Значення RESTART (%lld) не може бути меншим за MINVALUE (%lld)" -#: commands/sequence.c:1571 +#: commands/sequence.c:1563 #, c-format msgid "RESTART value (%lld) cannot be greater than MAXVALUE (%lld)" msgstr "Значення RESTART (%lld) не може бути більшим за MAXVALUE (%lld)" -#: commands/sequence.c:1582 +#: commands/sequence.c:1574 #, c-format msgid "CACHE (%lld) must be greater than zero" msgstr "CACHE (%lld) повинно бути більше нуля" -#: commands/sequence.c:1618 +#: commands/sequence.c:1610 #, c-format msgid "invalid OWNED BY option" msgstr "неприпустимий параметр OWNED BY" -#: commands/sequence.c:1619 +#: commands/sequence.c:1611 #, c-format msgid "Specify OWNED BY table.column or OWNED BY NONE." msgstr "Вкажіть OWNED BY таблиця.стовпець або OWNED BY NONE." -#: commands/sequence.c:1644 +#: commands/sequence.c:1636 #, c-format msgid "sequence cannot be owned by relation \"%s\"" msgstr "послідовність не може належати відношенню \"%s\"" -#: commands/sequence.c:1652 +#: commands/sequence.c:1644 #, c-format msgid "sequence must have same owner as table it is linked to" msgstr "послідовність повинна мати того ж власника, що і таблиця, з якою вона зв'язана" -#: commands/sequence.c:1656 +#: commands/sequence.c:1648 #, c-format msgid "sequence must be in same schema as table it is linked to" msgstr "послідовність повинна бути в тій самій схемі, що і таблиця, з якою вона зв'язана" -#: commands/sequence.c:1678 +#: commands/sequence.c:1670 #, c-format msgid "cannot change ownership of identity sequence" msgstr "змінити власника послідовності ідентифікації не можна" -#: commands/sequence.c:1679 commands/tablecmds.c:13903 -#: commands/tablecmds.c:16502 +#: commands/sequence.c:1671 commands/tablecmds.c:14384 +#: commands/tablecmds.c:17078 #, c-format msgid "Sequence \"%s\" is linked to table \"%s\"." msgstr "Послідовність \"%s\" зв'язана з таблицею \"%s\"." -#: commands/statscmds.c:109 commands/statscmds.c:118 tcop/utility.c:1887 +#: commands/statscmds.c:106 commands/statscmds.c:115 tcop/utility.c:1883 #, c-format msgid "only a single relation is allowed in CREATE STATISTICS" msgstr "в CREATE STATISTICS можна вказати лише одне відношення" -#: commands/statscmds.c:136 +#: commands/statscmds.c:133 #, c-format msgid "cannot define statistics for relation \"%s\"" msgstr "визначити статистику відношення \"%s\" не можна" -#: commands/statscmds.c:190 +#: commands/statscmds.c:187 #, c-format msgid "statistics object \"%s\" already exists, skipping" msgstr "об'єкт статистики \"%s\" вже існує, пропускається" -#: commands/statscmds.c:198 +#: commands/statscmds.c:195 #, c-format msgid "statistics object \"%s\" already exists" msgstr "об'єкт статистики \"%s\" вже існує" -#: commands/statscmds.c:209 +#: commands/statscmds.c:206 #, c-format msgid "cannot have more than %d columns in statistics" msgstr "в статистиці не може бути більше ніж %d стовпців" -#: commands/statscmds.c:250 commands/statscmds.c:273 commands/statscmds.c:307 +#: commands/statscmds.c:247 commands/statscmds.c:270 commands/statscmds.c:304 #, c-format msgid "statistics creation on system columns is not supported" msgstr "створення статистики для системних стовпців не підтримується" -#: commands/statscmds.c:257 commands/statscmds.c:280 +#: commands/statscmds.c:254 commands/statscmds.c:277 #, c-format msgid "column \"%s\" cannot be used in statistics because its type %s has no default btree operator class" msgstr "стовпець \"%s\" не можна використати в статистиці, тому що для його типу %s не визначений клас оператора (btree) за замовчуванням" -#: commands/statscmds.c:324 +#: commands/statscmds.c:321 #, c-format msgid "expression cannot be used in multivariate statistics because its type %s has no default btree operator class" msgstr "вираз не може використовуватись у багатоваріативній статистиці, тому що його тип %s немає визначеного класу оператора btree за замовчуванням" -#: commands/statscmds.c:345 +#: commands/statscmds.c:342 #, c-format msgid "when building statistics on a single expression, statistics kinds may not be specified" msgstr "при побудові статистики для одного виразу види статистики можуть не вказуватись" -#: commands/statscmds.c:374 +#: commands/statscmds.c:371 #, c-format msgid "unrecognized statistics kind \"%s\"" msgstr "нерозпізнаний вид статистики \"%s\"" -#: commands/statscmds.c:403 +#: commands/statscmds.c:400 #, c-format msgid "extended statistics require at least 2 columns" msgstr "для розширеної статистики потрібно мінімум 2 стовпці" -#: commands/statscmds.c:421 +#: commands/statscmds.c:418 #, c-format msgid "duplicate column name in statistics definition" msgstr "дублювання імені стовпця у визначенні статистики" -#: commands/statscmds.c:456 +#: commands/statscmds.c:453 #, c-format msgid "duplicate expression in statistics definition" msgstr "дублікат виразу у визначенні статистики" -#: commands/statscmds.c:619 commands/tablecmds.c:8188 +#: commands/statscmds.c:628 commands/tablecmds.c:8597 #, c-format msgid "statistics target %d is too low" msgstr "мета статистики занадто мала %d" -#: commands/statscmds.c:627 commands/tablecmds.c:8196 +#: commands/statscmds.c:636 commands/tablecmds.c:8605 #, c-format msgid "lowering statistics target to %d" msgstr "мета статистики знижується до %d" -#: commands/statscmds.c:650 +#: commands/statscmds.c:660 #, c-format msgid "statistics object \"%s.%s\" does not exist, skipping" msgstr "об'єкт статистики \"%s.%s\" не існує, пропускається" -#: commands/subscriptioncmds.c:271 commands/subscriptioncmds.c:359 +#: commands/subscriptioncmds.c:275 commands/subscriptioncmds.c:372 #, c-format msgid "unrecognized subscription parameter: \"%s\"" msgstr "нерозпізнаний параметр підписки: \"%s\"" -#: commands/subscriptioncmds.c:327 replication/pgoutput/pgoutput.c:395 +#: commands/subscriptioncmds.c:340 replication/pgoutput/pgoutput.c:397 #, c-format msgid "unrecognized origin value: \"%s\"" msgstr "нерозпізнане значення походження: \"%s\"" -#: commands/subscriptioncmds.c:350 +#: commands/subscriptioncmds.c:363 #, c-format msgid "invalid WAL location (LSN): %s" msgstr "неприпустиме розташування WAL (LSN): %s" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:374 commands/subscriptioncmds.c:381 -#: commands/subscriptioncmds.c:388 commands/subscriptioncmds.c:410 -#: commands/subscriptioncmds.c:426 +#: commands/subscriptioncmds.c:387 commands/subscriptioncmds.c:394 +#: commands/subscriptioncmds.c:401 commands/subscriptioncmds.c:423 +#: commands/subscriptioncmds.c:439 #, c-format msgid "%s and %s are mutually exclusive options" msgstr "%s та %s є взаємовиключними опціями" #. translator: both %s are strings of the form "option = value" -#: commands/subscriptioncmds.c:416 commands/subscriptioncmds.c:432 +#: commands/subscriptioncmds.c:429 commands/subscriptioncmds.c:445 #, c-format msgid "subscription with %s must also set %s" msgstr "підписка з %s повинна також встановити %s" -#: commands/subscriptioncmds.c:494 +#: commands/subscriptioncmds.c:506 #, c-format msgid "could not receive list of publications from the publisher: %s" msgstr "не вдалося отримати список публікацій з сервера публікації: %s" -#: commands/subscriptioncmds.c:526 +#: commands/subscriptioncmds.c:538 #, c-format msgid "publication %s does not exist on the publisher" msgid_plural "publications %s do not exist on the publisher" @@ -9881,130 +10226,136 @@ msgstr[1] "публікацій %s не існує на сервері публ msgstr[2] "публікацій %s не існує на сервері публікації" msgstr[3] "публікацій %s не існує на сервері публікації" -#: commands/subscriptioncmds.c:614 +#: commands/subscriptioncmds.c:626 #, c-format msgid "permission denied to create subscription" msgstr "немає дозволу для створення підписки" -#: commands/subscriptioncmds.c:615 +#: commands/subscriptioncmds.c:627 #, c-format msgid "Only roles with privileges of the \"%s\" role may create subscriptions." msgstr "Тільки ролі з правами \"%s\" можуть створювати підписки." -#: commands/subscriptioncmds.c:745 commands/subscriptioncmds.c:878 -#: replication/logical/tablesync.c:1327 replication/logical/worker.c:4616 +#: commands/subscriptioncmds.c:758 commands/subscriptioncmds.c:891 +#: commands/subscriptioncmds.c:1524 replication/logical/tablesync.c:1345 +#: replication/logical/worker.c:4503 #, c-format msgid "could not connect to the publisher: %s" msgstr "не вдалося підключитись до сервера публікації: %s" -#: commands/subscriptioncmds.c:816 +#: commands/subscriptioncmds.c:829 #, c-format msgid "created replication slot \"%s\" on publisher" msgstr "на сервері публікації створений слот реплікації \"%s\"" -#: commands/subscriptioncmds.c:828 +#: commands/subscriptioncmds.c:841 #, c-format msgid "subscription was created, but is not connected" msgstr "підписка була створена, але не підключена" -#: commands/subscriptioncmds.c:829 +#: commands/subscriptioncmds.c:842 #, c-format msgid "To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription." msgstr "Щоб ініціювати реплікацію, необхідно вручну створити слот реплікації, підключити підписку і оновити підписку." -#: commands/subscriptioncmds.c:1096 commands/subscriptioncmds.c:1509 -#: commands/subscriptioncmds.c:1892 utils/cache/lsyscache.c:3642 +#: commands/subscriptioncmds.c:1109 commands/subscriptioncmds.c:1590 +#: commands/subscriptioncmds.c:1973 utils/cache/lsyscache.c:3684 #, c-format msgid "subscription \"%s\" does not exist" msgstr "підписка \"%s\" не існує" -#: commands/subscriptioncmds.c:1152 +#: commands/subscriptioncmds.c:1166 commands/subscriptioncmds.c:1245 #, c-format msgid "cannot set %s for enabled subscription" msgstr "неможливо встановити %s для увімкненої підписки" -#: commands/subscriptioncmds.c:1234 +#: commands/subscriptioncmds.c:1233 +#, c-format +msgid "cannot set option \"%s\" for a subscription that does not have a slot name" +msgstr "не може задати параметр \"%s\" для підписки, яка не має назви слоту" + +#: commands/subscriptioncmds.c:1279 #, c-format msgid "cannot enable subscription that does not have a slot name" msgstr "увімкнути підписку, для якої не задано ім'я слота, не можна" -#: commands/subscriptioncmds.c:1278 commands/subscriptioncmds.c:1329 +#: commands/subscriptioncmds.c:1323 commands/subscriptioncmds.c:1374 #, c-format msgid "ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION з оновленням для відключених підписок не допускається" -#: commands/subscriptioncmds.c:1279 +#: commands/subscriptioncmds.c:1324 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." msgstr "Використайте ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false)." -#: commands/subscriptioncmds.c:1288 commands/subscriptioncmds.c:1343 +#: commands/subscriptioncmds.c:1333 commands/subscriptioncmds.c:1388 #, c-format msgid "ALTER SUBSCRIPTION with refresh and copy_data is not allowed when two_phase is enabled" msgstr "ALTER SUBSCRIPTION з параметрами refresh і copy_data не допускається, коли two_phase ввімкнено" -#: commands/subscriptioncmds.c:1289 +#: commands/subscriptioncmds.c:1334 #, c-format msgid "Use ALTER SUBSCRIPTION ... SET PUBLICATION with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "Використайте ALTER SUBSCRIPTION ... SET PUBLICATION з параметрами refresh або copy_data, які дорівнюють false, або використайте DROP/CREATE SUBSCRIPTION." #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:1345 +#: commands/subscriptioncmds.c:1390 #, c-format msgid "Use %s with refresh = false, or with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "Використовуйте %s з refresh = false, або з copy_data = false, або використовуйте DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1367 +#: commands/subscriptioncmds.c:1412 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions" msgstr "ALTER SUBSCRIPTION ... REFRESH для відключених підписок не допускається" -#: commands/subscriptioncmds.c:1392 +#: commands/subscriptioncmds.c:1437 #, c-format msgid "ALTER SUBSCRIPTION ... REFRESH with copy_data is not allowed when two_phase is enabled" msgstr "ALTER SUBSCRIPTION ... REFRESH з параметром copy_data не допускається, коли two_phase ввімкнено" -#: commands/subscriptioncmds.c:1393 +#: commands/subscriptioncmds.c:1438 #, c-format msgid "Use ALTER SUBSCRIPTION ... REFRESH with copy_data = false, or use DROP/CREATE SUBSCRIPTION." msgstr "Використайте ALTER SUBSCRIPTION ... REFRESH з параметром copy_data, який дорівнює false, або використайте DROP/CREATE SUBSCRIPTION." -#: commands/subscriptioncmds.c:1428 +#: commands/subscriptioncmds.c:1473 #, c-format msgid "skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X" msgstr "пропустити розташування WAL (LSN %X/%X) повинно бути більше, ніж origin LSN %X/%X" -#: commands/subscriptioncmds.c:1513 +#: commands/subscriptioncmds.c:1594 #, c-format msgid "subscription \"%s\" does not exist, skipping" msgstr "підписка \"%s\" не існує, пропускається" -#: commands/subscriptioncmds.c:1782 +#: commands/subscriptioncmds.c:1863 #, c-format msgid "dropped replication slot \"%s\" on publisher" msgstr "видалено слот реплікації \"%s\" на сервері публікації" -#: commands/subscriptioncmds.c:1791 commands/subscriptioncmds.c:1799 +#: commands/subscriptioncmds.c:1872 commands/subscriptioncmds.c:1880 #, c-format msgid "could not drop replication slot \"%s\" on publisher: %s" msgstr "не вдалося видалити слот реплікації \"%s\" на сервері публікації: %s" -#: commands/subscriptioncmds.c:1924 +#: commands/subscriptioncmds.c:2005 #, c-format msgid "subscription with OID %u does not exist" msgstr "підписки %u з OID не існує" -#: commands/subscriptioncmds.c:1995 commands/subscriptioncmds.c:2120 +#: commands/subscriptioncmds.c:2076 commands/subscriptioncmds.c:2201 #, c-format msgid "could not receive list of replicated tables from the publisher: %s" msgstr "не вдалося отримати список реплікованих таблиць із сервера публікації: %s" -#: commands/subscriptioncmds.c:2031 +#: commands/subscriptioncmds.c:2112 #, c-format msgid "subscription \"%s\" requested copy_data with origin = NONE but might copy data that had a different origin" msgstr "підписка \"%s\" запросив copy_data зі походженням = NONE, але може скопіювати дані, що мають інше походження" -#: commands/subscriptioncmds.c:2033 +#: commands/subscriptioncmds.c:2114 #, c-format msgid "The subscription being created subscribes to a publication (%s) that contains tables that are written to by other subscriptions." msgid_plural "The subscription being created subscribes to publications (%s) that contain tables that are written to by other subscriptions." @@ -10013,1885 +10364,1961 @@ msgstr[1] "Створювана підписка підписується на msgstr[2] "Створювана підписка підписується на публікації (%s), яка містить таблиці, до яких записуються інші підписки." msgstr[3] "Створювана підписка підписується на публікації (%s), яка містить таблиці, до яких записуються інші підписки." -#: commands/subscriptioncmds.c:2036 +#: commands/subscriptioncmds.c:2117 #, c-format msgid "Verify that initial data copied from the publisher tables did not come from other origins." msgstr "Переконайтеся, що вихідні дані, скопійовані з таблиць публікатора, не були отримані з інших джерел." -#: commands/subscriptioncmds.c:2142 replication/logical/tablesync.c:886 -#: replication/pgoutput/pgoutput.c:1112 +#: commands/subscriptioncmds.c:2223 replication/logical/tablesync.c:906 +#: replication/pgoutput/pgoutput.c:1117 #, c-format msgid "cannot use different column lists for table \"%s.%s\" in different publications" msgstr "використовувати різні списки стовпців для таблиці \"%s.%s\" в різних публікаціях не можна" -#: commands/subscriptioncmds.c:2192 +#: commands/subscriptioncmds.c:2273 #, c-format msgid "could not connect to publisher when attempting to drop replication slot \"%s\": %s" msgstr "не вдалося з'єднатись з сервером публікації під час спроби видалити слот реплікації \"%s\": %s" #. translator: %s is an SQL ALTER command -#: commands/subscriptioncmds.c:2195 +#: commands/subscriptioncmds.c:2276 #, c-format msgid "Use %s to disable the subscription, and then use %s to disassociate it from the slot." msgstr "Використовуйте %s, щоб вимкнути підписку, а потім використайте %s, щоб від'єднати її від слоту." -#: commands/subscriptioncmds.c:2226 +#: commands/subscriptioncmds.c:2307 #, c-format msgid "publication name \"%s\" used more than once" msgstr "ім'я публікації \"%s\" використовується більше ніж один раз" -#: commands/subscriptioncmds.c:2270 +#: commands/subscriptioncmds.c:2351 #, c-format msgid "publication \"%s\" is already in subscription \"%s\"" msgstr "публікація \"%s\" вже в підписці \"%s\"" -#: commands/subscriptioncmds.c:2284 +#: commands/subscriptioncmds.c:2365 #, c-format msgid "publication \"%s\" is not in subscription \"%s\"" msgstr "публікація \"%s\" не знаходиться в підписці \"%s\"" -#: commands/subscriptioncmds.c:2295 +#: commands/subscriptioncmds.c:2376 #, c-format msgid "cannot drop all the publications from a subscription" msgstr "не можна видалити всі публікації з підписки" -#: commands/subscriptioncmds.c:2352 +#: commands/subscriptioncmds.c:2433 #, c-format msgid "%s requires a Boolean value or \"parallel\"" msgstr "%s потребує логічне значення або \"parallel\"" -#: commands/tablecmds.c:246 commands/tablecmds.c:288 +#: commands/tablecmds.c:255 commands/tablecmds.c:297 #, c-format msgid "table \"%s\" does not exist" msgstr "таблиця \"%s\" не існує" -#: commands/tablecmds.c:247 commands/tablecmds.c:289 +#: commands/tablecmds.c:256 commands/tablecmds.c:298 #, c-format msgid "table \"%s\" does not exist, skipping" msgstr "таблиця \"%s\" не існує, пропускається" -#: commands/tablecmds.c:249 commands/tablecmds.c:291 +#: commands/tablecmds.c:258 commands/tablecmds.c:300 msgid "Use DROP TABLE to remove a table." msgstr "Використайте DROP TABLE для видалення таблиці." -#: commands/tablecmds.c:252 +#: commands/tablecmds.c:261 #, c-format msgid "sequence \"%s\" does not exist" msgstr "послідовність \"%s\" не існує" -#: commands/tablecmds.c:253 +#: commands/tablecmds.c:262 #, c-format msgid "sequence \"%s\" does not exist, skipping" msgstr "послідовність \"%s\" не існує, пропускається" -#: commands/tablecmds.c:255 +#: commands/tablecmds.c:264 msgid "Use DROP SEQUENCE to remove a sequence." msgstr "Використайте DROP SEQUENCE, щоб видалити послідовність." -#: commands/tablecmds.c:258 +#: commands/tablecmds.c:267 #, c-format msgid "view \"%s\" does not exist" msgstr "подання \"%s\" не існує" -#: commands/tablecmds.c:259 +#: commands/tablecmds.c:268 #, c-format msgid "view \"%s\" does not exist, skipping" msgstr "подання \"%s\" не існує, пропускається" -#: commands/tablecmds.c:261 +#: commands/tablecmds.c:270 msgid "Use DROP VIEW to remove a view." msgstr "Використайте DROP VIEW для видалення подання." -#: commands/tablecmds.c:264 +#: commands/tablecmds.c:273 #, c-format msgid "materialized view \"%s\" does not exist" msgstr "матеріалізоване подання \"%s\" не існує" -#: commands/tablecmds.c:265 +#: commands/tablecmds.c:274 #, c-format msgid "materialized view \"%s\" does not exist, skipping" msgstr "матеріалізоване подання \"%s\" не існує, пропускається" -#: commands/tablecmds.c:267 +#: commands/tablecmds.c:276 msgid "Use DROP MATERIALIZED VIEW to remove a materialized view." msgstr "Використайте DROP MATERIALIZED VIEW, щоб видалити матеріалізоване подання." -#: commands/tablecmds.c:270 commands/tablecmds.c:294 commands/tablecmds.c:19006 -#: parser/parse_utilcmd.c:2254 +#: commands/tablecmds.c:279 commands/tablecmds.c:303 commands/tablecmds.c:19617 +#: parser/parse_utilcmd.c:2251 #, c-format msgid "index \"%s\" does not exist" msgstr "індекс \"%s\" не існує" -#: commands/tablecmds.c:271 commands/tablecmds.c:295 +#: commands/tablecmds.c:280 commands/tablecmds.c:304 #, c-format msgid "index \"%s\" does not exist, skipping" msgstr "індекс \"%s\" не існує, пропускається" -#: commands/tablecmds.c:273 commands/tablecmds.c:297 +#: commands/tablecmds.c:282 commands/tablecmds.c:306 msgid "Use DROP INDEX to remove an index." msgstr "Використайте DROP INDEX, щоб видалити індекс." -#: commands/tablecmds.c:278 +#: commands/tablecmds.c:287 #, c-format msgid "\"%s\" is not a type" msgstr "\"%s\" не є типом" -#: commands/tablecmds.c:279 +#: commands/tablecmds.c:288 msgid "Use DROP TYPE to remove a type." msgstr "Використайте DROP TYPE, щоб видалити тип." -#: commands/tablecmds.c:282 commands/tablecmds.c:13742 -#: commands/tablecmds.c:16207 +#: commands/tablecmds.c:291 commands/tablecmds.c:14223 +#: commands/tablecmds.c:16783 #, c-format msgid "foreign table \"%s\" does not exist" msgstr "зовнішня таблиця \"%s\" не існує" -#: commands/tablecmds.c:283 +#: commands/tablecmds.c:292 #, c-format msgid "foreign table \"%s\" does not exist, skipping" msgstr "зовнішня таблиця \"%s\" не існує, пропускається" -#: commands/tablecmds.c:285 +#: commands/tablecmds.c:294 msgid "Use DROP FOREIGN TABLE to remove a foreign table." msgstr "Використайте DROP FOREIGN TABLE щоб видалити сторонню таблицю." -#: commands/tablecmds.c:700 +#: commands/tablecmds.c:717 #, c-format msgid "ON COMMIT can only be used on temporary tables" msgstr "ON COMMIT можна використовувати лише для тимчасових таблиць" -#: commands/tablecmds.c:731 +#: commands/tablecmds.c:748 #, c-format msgid "cannot create temporary table within security-restricted operation" msgstr "неможливо створити тимчасову таблицю в межах операції з обмеженням безпеки" -#: commands/tablecmds.c:767 commands/tablecmds.c:15052 +#: commands/tablecmds.c:784 commands/tablecmds.c:15642 #, c-format msgid "relation \"%s\" would be inherited from more than once" msgstr "відношення \"%s\" буде успадковуватись більш ніж один раз" -#: commands/tablecmds.c:955 -#, c-format -msgid "specifying a table access method is not supported on a partitioned table" -msgstr "вказання методу доступу до таблиці не підтримується з секційною таблицею" - -#: commands/tablecmds.c:1048 +#: commands/tablecmds.c:1050 #, c-format msgid "\"%s\" is not partitioned" msgstr "\"%s\" не секціоновано" -#: commands/tablecmds.c:1142 +#: commands/tablecmds.c:1144 #, c-format msgid "cannot partition using more than %d columns" msgstr "число стовпців в ключі секціонування не може перевищувати %d" -#: commands/tablecmds.c:1198 +#: commands/tablecmds.c:1200 #, c-format msgid "cannot create foreign partition of partitioned table \"%s\"" msgstr "не можна створити зовнішню секцію в секціонованій таблиці \"%s\"" -#: commands/tablecmds.c:1200 +#: commands/tablecmds.c:1202 #, c-format msgid "Table \"%s\" contains indexes that are unique." msgstr "Таблиця \"%s\" містить індекси, які унікальні." -#: commands/tablecmds.c:1365 +#: commands/tablecmds.c:1321 commands/tablecmds.c:13239 #, c-format -msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" -msgstr "DROP INDEX CONCURRENTLY не підтримує видалення кількох об'єктів" +msgid "too many array dimensions" +msgstr "занадто багато вимірів масиву" -#: commands/tablecmds.c:1369 +#: commands/tablecmds.c:1326 parser/parse_clause.c:774 +#: parser/parse_relation.c:1912 #, c-format -msgid "DROP INDEX CONCURRENTLY does not support CASCADE" +msgid "column \"%s\" cannot be declared SETOF" +msgstr "стовпець\"%s\" не може бути оголошений SETOF" + +#: commands/tablecmds.c:1472 +#, c-format +msgid "DROP INDEX CONCURRENTLY does not support dropping multiple objects" +msgstr "DROP INDEX CONCURRENTLY не підтримує видалення кількох об'єктів" + +#: commands/tablecmds.c:1476 +#, c-format +msgid "DROP INDEX CONCURRENTLY does not support CASCADE" msgstr "DROP INDEX CONCURRENTLY не підтримує режим CASCADE" -#: commands/tablecmds.c:1473 +#: commands/tablecmds.c:1580 #, c-format msgid "cannot drop partitioned index \"%s\" concurrently" msgstr "неможливо видалити секціонований індекс \"%s\" паралельно" -#: commands/tablecmds.c:1761 +#: commands/tablecmds.c:1868 #, c-format msgid "cannot truncate only a partitioned table" msgstr "скоротити тільки секціоновану таблицю не можна" -#: commands/tablecmds.c:1762 +#: commands/tablecmds.c:1869 #, c-format msgid "Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly." msgstr "Не вказуйте ключове слово ONLY або використайте TRUNCATE ONLY безпосередньо для секцій." -#: commands/tablecmds.c:1835 +#: commands/tablecmds.c:1942 #, c-format msgid "truncate cascades to table \"%s\"" msgstr "скорочення поширюється на таблицю \"%s\"" -#: commands/tablecmds.c:2199 +#: commands/tablecmds.c:2303 #, c-format msgid "cannot truncate foreign table \"%s\"" msgstr "скоротити зовнішню таблицю \"%s\" не можна" -#: commands/tablecmds.c:2256 +#: commands/tablecmds.c:2360 #, c-format msgid "cannot truncate temporary tables of other sessions" msgstr "тимчасові таблиці інших сеансів не можна скоротити" -#: commands/tablecmds.c:2488 commands/tablecmds.c:14949 +#: commands/tablecmds.c:2589 commands/tablecmds.c:15539 #, c-format msgid "cannot inherit from partitioned table \"%s\"" msgstr "успадкування від секціонованої таблиці \"%s\" не допускається" -#: commands/tablecmds.c:2493 +#: commands/tablecmds.c:2594 #, c-format msgid "cannot inherit from partition \"%s\"" msgstr "успадкування від розділу \"%s\" не допускається" -#: commands/tablecmds.c:2501 parser/parse_utilcmd.c:2484 -#: parser/parse_utilcmd.c:2626 +#: commands/tablecmds.c:2602 parser/parse_utilcmd.c:2481 +#: parser/parse_utilcmd.c:2623 #, c-format msgid "inherited relation \"%s\" is not a table or foreign table" msgstr "успадковане відношення \"%s\" не є таблицею або сторонньою таблицею" -#: commands/tablecmds.c:2513 +#: commands/tablecmds.c:2614 #, c-format msgid "cannot create a temporary relation as partition of permanent relation \"%s\"" msgstr "створити тимчасове відношення як секцію постійного відношення\"%s\" не можна" -#: commands/tablecmds.c:2522 commands/tablecmds.c:14928 +#: commands/tablecmds.c:2623 commands/tablecmds.c:15518 #, c-format msgid "cannot inherit from temporary relation \"%s\"" msgstr "тимчасове відношення \"%s\" не може успадковуватись" -#: commands/tablecmds.c:2532 commands/tablecmds.c:14936 +#: commands/tablecmds.c:2633 commands/tablecmds.c:15526 #, c-format msgid "cannot inherit from temporary relation of another session" msgstr "успадкування від тимчасового відношення іншого сеансу неможливе" -#: commands/tablecmds.c:2585 +#: commands/tablecmds.c:2774 commands/tablecmds.c:2828 +#: commands/tablecmds.c:12922 parser/parse_utilcmd.c:1265 +#: parser/parse_utilcmd.c:1308 parser/parse_utilcmd.c:1735 +#: parser/parse_utilcmd.c:1843 #, c-format -msgid "merging multiple inherited definitions of column \"%s\"" -msgstr "злиття декількох успадкованих визначень стовпця \"%s\"" +msgid "cannot convert whole-row table reference" +msgstr "перетворити посилання на тип усього рядка таблиці не можна" -#: commands/tablecmds.c:2597 +#: commands/tablecmds.c:2775 parser/parse_utilcmd.c:1266 #, c-format -msgid "inherited column \"%s\" has a type conflict" -msgstr "конфлікт типів в успадкованому стовпці \"%s\"" +msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." +msgstr "Вираз генерації для стовпця \"%s\" містить посилання на весь рядок на таблицю \"%s\"." -#: commands/tablecmds.c:2599 commands/tablecmds.c:2628 -#: commands/tablecmds.c:2647 commands/tablecmds.c:2919 -#: commands/tablecmds.c:2955 commands/tablecmds.c:2971 -#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 -#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 -#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 -#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 -#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 -#: parser/parse_param.c:223 +#: commands/tablecmds.c:2829 parser/parse_utilcmd.c:1309 #, c-format -msgid "%s versus %s" -msgstr "%s проти %s" +msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." +msgstr "Обмеження \"%s\" посилається на тип усього рядка в таблиці \"%s\"." -#: commands/tablecmds.c:2612 +#: commands/tablecmds.c:2939 commands/tablecmds.c:3210 #, c-format -msgid "inherited column \"%s\" has a collation conflict" -msgstr "конфлікт правил сортування в успадкованому стовпці \"%s\"" +msgid "column \"%s\" inherits from generated column but specifies default" +msgstr "стовпець \"%s\" успадковується із згенерованого стовпця, але вказує за замовчуванням" -#: commands/tablecmds.c:2614 commands/tablecmds.c:2935 -#: commands/tablecmds.c:6849 +#: commands/tablecmds.c:2944 commands/tablecmds.c:3215 #, c-format -msgid "\"%s\" versus \"%s\"" -msgstr "\"%s\" проти \"%s\"" +msgid "column \"%s\" inherits from generated column but specifies identity" +msgstr "стовпець \"%s\" успадковується із згенерованого стовпця, але вказує ідентичність" -#: commands/tablecmds.c:2626 +#: commands/tablecmds.c:2952 commands/tablecmds.c:3223 #, c-format -msgid "inherited column \"%s\" has a storage parameter conflict" -msgstr "конфлікт параметрів зберігання в успадкованому стовпці \"%s\"" +msgid "child column \"%s\" specifies generation expression" +msgstr "дочірній стовпець \"%s\" визначає вираз генерації" -#: commands/tablecmds.c:2645 commands/tablecmds.c:2969 +#: commands/tablecmds.c:2954 commands/tablecmds.c:3225 #, c-format -msgid "column \"%s\" has a compression method conflict" -msgstr "конфлікт методів стиснення в стовпці \"%s\"" +msgid "A child table column cannot be generated unless its parent column is." +msgstr "Стовпець дочірньої таблиці не може бути створений, якщо не створено стовпець батьківської таблиці." -#: commands/tablecmds.c:2661 +#: commands/tablecmds.c:3000 #, c-format -msgid "inherited column \"%s\" has a generation conflict" -msgstr "конфлікт генерування в успадкованому стовпці \"%s\"" +msgid "column \"%s\" inherits conflicting generation expressions" +msgstr "стовпець \"%s\" успадковує конфліктуючи вирази генерації" -#: commands/tablecmds.c:2767 commands/tablecmds.c:2822 -#: commands/tablecmds.c:12468 parser/parse_utilcmd.c:1307 -#: parser/parse_utilcmd.c:1350 parser/parse_utilcmd.c:1749 -#: parser/parse_utilcmd.c:1857 +#: commands/tablecmds.c:3002 #, c-format -msgid "cannot convert whole-row table reference" -msgstr "перетворити посилання на тип усього рядка таблиці не можна" +msgid "To resolve the conflict, specify a generation expression explicitly." +msgstr "Щоб вирішити цей конфлікт, явно вкажіть вираз генерації." -#: commands/tablecmds.c:2768 parser/parse_utilcmd.c:1308 +#: commands/tablecmds.c:3006 #, c-format -msgid "Generation expression for column \"%s\" contains a whole-row reference to table \"%s\"." -msgstr "Вираз генерації для стовпця \"%s\" містить посилання на весь рядок на таблицю \"%s\"." +msgid "column \"%s\" inherits conflicting default values" +msgstr "стовпець \"%s\" успадковує конфліктні значення за замовчуванням" -#: commands/tablecmds.c:2823 parser/parse_utilcmd.c:1351 +#: commands/tablecmds.c:3008 #, c-format -msgid "Constraint \"%s\" contains a whole-row reference to table \"%s\"." -msgstr "Обмеження \"%s\" посилається на тип усього рядка в таблиці \"%s\"." +msgid "To resolve the conflict, specify a default explicitly." +msgstr "Для усунення конфлікту вкажіть бажане значення за замовчуванням." + +#: commands/tablecmds.c:3063 +#, c-format +msgid "check constraint name \"%s\" appears multiple times but with different expressions" +msgstr "ім'я перевірочного обмеження \"%s\" з'являється декілька разів, але з різними виразами" -#: commands/tablecmds.c:2901 +#: commands/tablecmds.c:3114 #, c-format msgid "merging column \"%s\" with inherited definition" msgstr "злиття стовпця \"%s\" з успадкованим визначенням" -#: commands/tablecmds.c:2905 +#: commands/tablecmds.c:3118 #, c-format msgid "moving and merging column \"%s\" with inherited definition" msgstr "переміщення і злиття стовпця \"%s\" з успадкованим визначенням" -#: commands/tablecmds.c:2906 +#: commands/tablecmds.c:3119 #, c-format msgid "User-specified column moved to the position of the inherited column." msgstr "Визначений користувачем стовпець переміщений в позицію успадкованого стовпця." -#: commands/tablecmds.c:2917 +#: commands/tablecmds.c:3131 #, c-format msgid "column \"%s\" has a type conflict" msgstr "конфлікт типів в стовпці \"%s\"" -#: commands/tablecmds.c:2933 -#, c-format -msgid "column \"%s\" has a collation conflict" -msgstr "конфлікт правил сортування в стовпці \"%s\"" - -#: commands/tablecmds.c:2953 +#: commands/tablecmds.c:3133 commands/tablecmds.c:3167 +#: commands/tablecmds.c:3183 commands/tablecmds.c:3290 +#: commands/tablecmds.c:3323 commands/tablecmds.c:3339 +#: parser/parse_coerce.c:2155 parser/parse_coerce.c:2175 +#: parser/parse_coerce.c:2195 parser/parse_coerce.c:2216 +#: parser/parse_coerce.c:2271 parser/parse_coerce.c:2305 +#: parser/parse_coerce.c:2381 parser/parse_coerce.c:2412 +#: parser/parse_coerce.c:2451 parser/parse_coerce.c:2518 +#: parser/parse_param.c:223 #, c-format -msgid "column \"%s\" has a storage parameter conflict" -msgstr "конфлікт параметрів зберігання в стовпці \"%s\"" +msgid "%s versus %s" +msgstr "%s проти %s" -#: commands/tablecmds.c:2999 commands/tablecmds.c:3086 +#: commands/tablecmds.c:3145 #, c-format -msgid "column \"%s\" inherits from generated column but specifies default" -msgstr "стовпець \"%s\" успадковується із згенерованого стовпця, але вказує за замовчуванням" +msgid "column \"%s\" has a collation conflict" +msgstr "конфлікт правил сортування в стовпці \"%s\"" -#: commands/tablecmds.c:3004 commands/tablecmds.c:3091 +#: commands/tablecmds.c:3147 commands/tablecmds.c:3309 +#: commands/tablecmds.c:7057 #, c-format -msgid "column \"%s\" inherits from generated column but specifies identity" -msgstr "стовпець \"%s\" успадковується із згенерованого стовпця, але вказує ідентичність" +msgid "\"%s\" versus \"%s\"" +msgstr "\"%s\" проти \"%s\"" -#: commands/tablecmds.c:3012 commands/tablecmds.c:3099 +#: commands/tablecmds.c:3165 #, c-format -msgid "child column \"%s\" specifies generation expression" -msgstr "дочірній стовпець \"%s\" визначає вираз генерації" +msgid "column \"%s\" has a storage parameter conflict" +msgstr "конфлікт параметрів зберігання в стовпці \"%s\"" -#: commands/tablecmds.c:3014 commands/tablecmds.c:3101 +#: commands/tablecmds.c:3181 commands/tablecmds.c:3337 #, c-format -msgid "A child table column cannot be generated unless its parent column is." -msgstr "Стовпець дочірньої таблиці не може бути створений, якщо не створено стовпець батьківської таблиці." +msgid "column \"%s\" has a compression method conflict" +msgstr "конфлікт методів стиснення в стовпці \"%s\"" -#: commands/tablecmds.c:3147 +#: commands/tablecmds.c:3276 #, c-format -msgid "column \"%s\" inherits conflicting generation expressions" -msgstr "стовпець \"%s\" успадковує конфліктуючи вирази генерації" +msgid "merging multiple inherited definitions of column \"%s\"" +msgstr "злиття декількох успадкованих визначень стовпця \"%s\"" -#: commands/tablecmds.c:3149 +#: commands/tablecmds.c:3288 #, c-format -msgid "To resolve the conflict, specify a generation expression explicitly." -msgstr "Щоб вирішити цей конфлікт, явно вкажіть вираз генерації." +msgid "inherited column \"%s\" has a type conflict" +msgstr "конфлікт типів в успадкованому стовпці \"%s\"" -#: commands/tablecmds.c:3153 +#: commands/tablecmds.c:3307 #, c-format -msgid "column \"%s\" inherits conflicting default values" -msgstr "стовпець \"%s\" успадковує конфліктні значення за замовчуванням" +msgid "inherited column \"%s\" has a collation conflict" +msgstr "конфлікт правил сортування в успадкованому стовпці \"%s\"" -#: commands/tablecmds.c:3155 +#: commands/tablecmds.c:3321 #, c-format -msgid "To resolve the conflict, specify a default explicitly." -msgstr "Для усунення конфлікту вкажіть бажане значення за замовчуванням." +msgid "inherited column \"%s\" has a storage parameter conflict" +msgstr "конфлікт параметрів зберігання в успадкованому стовпці \"%s\"" -#: commands/tablecmds.c:3205 +#: commands/tablecmds.c:3349 #, c-format -msgid "check constraint name \"%s\" appears multiple times but with different expressions" -msgstr "ім'я перевірочного обмеження \"%s\" з'являється декілька разів, але з різними виразами" +msgid "inherited column \"%s\" has a generation conflict" +msgstr "конфлікт генерування в успадкованому стовпці \"%s\"" -#: commands/tablecmds.c:3418 +#: commands/tablecmds.c:3580 #, c-format msgid "cannot move temporary tables of other sessions" msgstr "переміщувати тимчасові таблиці інших сеансів не можна" -#: commands/tablecmds.c:3488 +#: commands/tablecmds.c:3650 #, c-format msgid "cannot rename column of typed table" msgstr "перейменувати стовпець типізованої таблиці не можна" -#: commands/tablecmds.c:3507 +#: commands/tablecmds.c:3669 #, c-format msgid "cannot rename columns of relation \"%s\"" msgstr "перейменувати стовпці відношення %s не можна" -#: commands/tablecmds.c:3602 +#: commands/tablecmds.c:3764 #, c-format msgid "inherited column \"%s\" must be renamed in child tables too" msgstr "успадкований стовпець \"%s\" повинен бути перейменований в дочірніх таблицях також" -#: commands/tablecmds.c:3634 +#: commands/tablecmds.c:3796 #, c-format msgid "cannot rename system column \"%s\"" msgstr "не можна перейменувати системний стовпець \"%s\"" -#: commands/tablecmds.c:3649 +#: commands/tablecmds.c:3811 #, c-format msgid "cannot rename inherited column \"%s\"" msgstr "не можна перейменувати успадкований стовпець \"%s\"" -#: commands/tablecmds.c:3801 +#: commands/tablecmds.c:3963 #, c-format msgid "inherited constraint \"%s\" must be renamed in child tables too" msgstr "успадковане обмеження \"%s\" повинно бути перейменовано в дочірніх таблицях також" -#: commands/tablecmds.c:3808 +#: commands/tablecmds.c:3970 #, c-format msgid "cannot rename inherited constraint \"%s\"" msgstr "не можна перейменувати успадковане обмеження \"%s\"" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4105 +#: commands/tablecmds.c:4267 #, c-format msgid "cannot %s \"%s\" because it is being used by active queries in this session" msgstr "не можна виконати %s \"%s\", тому що цей об'єкт використовується активними запитами в цьому сеансі" #. translator: first %s is a SQL command, eg ALTER TABLE -#: commands/tablecmds.c:4114 +#: commands/tablecmds.c:4276 #, c-format msgid "cannot %s \"%s\" because it has pending trigger events" msgstr "не можна виконати %s \"%s\", тому що з цим об'єктом зв'язані очікуванні події тригерів" -#: commands/tablecmds.c:4581 +#: commands/tablecmds.c:4302 +#, c-format +msgid "cannot alter temporary tables of other sessions" +msgstr "не можна змінювати тимчасові таблиці з інших сеансів" + +#: commands/tablecmds.c:4775 #, c-format msgid "cannot alter partition \"%s\" with an incomplete detach" msgstr "не можна змінити розділ \"%s\" з неповним відключенням" -#: commands/tablecmds.c:4774 commands/tablecmds.c:4789 +#: commands/tablecmds.c:4979 commands/tablecmds.c:4994 #, c-format msgid "cannot change persistence setting twice" msgstr "неможливо двічі змінити параметр стійкості" -#: commands/tablecmds.c:4810 -#, c-format -msgid "cannot change access method of a partitioned table" -msgstr "неможливо змінити метод доступу секціонованої таблиці" - -#: commands/tablecmds.c:4816 +#: commands/tablecmds.c:5015 #, c-format msgid "cannot have multiple SET ACCESS METHOD subcommands" msgstr "неможливо мати декілька підкоманд SET ACCESS METHOD" -#: commands/tablecmds.c:5537 +#: commands/tablecmds.c:5745 #, c-format msgid "cannot rewrite system relation \"%s\"" msgstr "перезаписати системне відношення \"%s\" не можна" -#: commands/tablecmds.c:5543 +#: commands/tablecmds.c:5751 #, c-format msgid "cannot rewrite table \"%s\" used as a catalog table" msgstr "перезаписати таблицю \"%s\", що використовується як таблиця каталогу, не можна" -#: commands/tablecmds.c:5553 +#: commands/tablecmds.c:5763 #, c-format msgid "cannot rewrite temporary tables of other sessions" msgstr "неможливо перезаписати тимчасові таблиці інших сеансів" -#: commands/tablecmds.c:6048 +#: commands/tablecmds.c:6258 #, c-format msgid "column \"%s\" of relation \"%s\" contains null values" msgstr "стовпець \"%s\" відношення \"%s\" містить null значення" -#: commands/tablecmds.c:6065 +#: commands/tablecmds.c:6275 #, c-format msgid "check constraint \"%s\" of relation \"%s\" is violated by some row" msgstr "перевірка обмеження \"%s\" відношення \"%s\" порушується деяким рядком" -#: commands/tablecmds.c:6084 partitioning/partbounds.c:3388 +#: commands/tablecmds.c:6294 partitioning/partbounds.c:3387 #, c-format msgid "updated partition constraint for default partition \"%s\" would be violated by some row" msgstr "оновлене обмеження секції для секції за замовчуванням \"%s\" буде порушено деякими рядками" -#: commands/tablecmds.c:6090 +#: commands/tablecmds.c:6300 #, c-format msgid "partition constraint of relation \"%s\" is violated by some row" msgstr "обмеження секції відношення \"%s\" порушується деяким рядком" #. translator: %s is a group of some SQL keywords -#: commands/tablecmds.c:6352 +#: commands/tablecmds.c:6565 #, c-format msgid "ALTER action %s cannot be performed on relation \"%s\"" msgstr "Дію ALTER %s не можна виконати на відношенні \"%s\"" -#: commands/tablecmds.c:6607 commands/tablecmds.c:6614 +#: commands/tablecmds.c:6820 commands/tablecmds.c:6827 #, c-format msgid "cannot alter type \"%s\" because column \"%s.%s\" uses it" msgstr "неможливо змінити тип \"%s\", тому що стовпець \"%s.%s\" використовує його" -#: commands/tablecmds.c:6621 +#: commands/tablecmds.c:6834 #, c-format msgid "cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type" msgstr "неможливо змінити сторонню таблицю \"%s\", тому що стовпець \"%s.%s\" використовує тип її рядка" -#: commands/tablecmds.c:6628 +#: commands/tablecmds.c:6841 #, c-format msgid "cannot alter table \"%s\" because column \"%s.%s\" uses its row type" msgstr "неможливо змінити таблицю \"%s\", тому що стовпець \"%s.%s\" використовує тип її рядка" -#: commands/tablecmds.c:6684 +#: commands/tablecmds.c:6897 #, c-format msgid "cannot alter type \"%s\" because it is the type of a typed table" msgstr "неможливо змінити тип \"%s\", тому що це тип типізованої таблиці" -#: commands/tablecmds.c:6686 +#: commands/tablecmds.c:6899 #, c-format msgid "Use ALTER ... CASCADE to alter the typed tables too." msgstr "Щоб змінити типізовані таблиці, використайте також ALTER ... CASCADE." -#: commands/tablecmds.c:6732 +#: commands/tablecmds.c:6945 #, c-format msgid "type %s is not a composite type" msgstr "тип %s не є складеним" -#: commands/tablecmds.c:6759 +#: commands/tablecmds.c:6972 #, c-format msgid "cannot add column to typed table" msgstr "неможливо додати стовпець до типізованої таблиці" -#: commands/tablecmds.c:6812 +#: commands/tablecmds.c:7020 #, c-format msgid "cannot add column to a partition" msgstr "неможливо додати стовпець до розділу" -#: commands/tablecmds.c:6841 commands/tablecmds.c:15179 +#: commands/tablecmds.c:7049 commands/tablecmds.c:15757 #, c-format msgid "child table \"%s\" has different type for column \"%s\"" msgstr "дочірня таблиця \"%s\" має інший тип для стовпця \"%s\"" -#: commands/tablecmds.c:6847 commands/tablecmds.c:15186 +#: commands/tablecmds.c:7055 commands/tablecmds.c:15763 #, c-format msgid "child table \"%s\" has different collation for column \"%s\"" msgstr "дочірня таблиця \"%s\" має інше правило сортування для стовпця \"%s\"" -#: commands/tablecmds.c:6865 +#: commands/tablecmds.c:7073 #, c-format msgid "merging definition of column \"%s\" for child \"%s\"" msgstr "об'єднання визначення стовпця \"%s\" для нащадка \"%s\"" -#: commands/tablecmds.c:6912 +#: commands/tablecmds.c:7126 #, c-format msgid "cannot recursively add identity column to table that has child tables" msgstr "неможливо додати стовпець ідентифікації в таблицю, яка має дочірні таблиці" -#: commands/tablecmds.c:7163 +#: commands/tablecmds.c:7339 #, c-format msgid "column must be added to child tables too" msgstr "стовпець також повинен бути доданий до дочірніх таблиць" -#: commands/tablecmds.c:7241 +#: commands/tablecmds.c:7417 #, c-format msgid "column \"%s\" of relation \"%s\" already exists, skipping" msgstr "стовпець \"%s\" відношення \"%s\" вже існує, пропускається" -#: commands/tablecmds.c:7248 +#: commands/tablecmds.c:7424 #, c-format msgid "column \"%s\" of relation \"%s\" already exists" msgstr "стовпець \"%s\" відношення \"%s\" вже існує" -#: commands/tablecmds.c:7314 commands/tablecmds.c:12106 +#: commands/tablecmds.c:7490 commands/tablecmds.c:12550 #, c-format msgid "cannot remove constraint from only the partitioned table when partitions exist" msgstr "неможливо видалити обмеження тільки з секціонованої таблиці, коли існують секції" -#: commands/tablecmds.c:7315 commands/tablecmds.c:7632 -#: commands/tablecmds.c:8601 commands/tablecmds.c:12107 +#: commands/tablecmds.c:7491 commands/tablecmds.c:7805 +#: commands/tablecmds.c:7983 commands/tablecmds.c:8090 +#: commands/tablecmds.c:8207 commands/tablecmds.c:9026 +#: commands/tablecmds.c:12551 #, c-format msgid "Do not specify the ONLY keyword." msgstr "Не вказуйте ключове слово ONLY." -#: commands/tablecmds.c:7352 commands/tablecmds.c:7558 -#: commands/tablecmds.c:7700 commands/tablecmds.c:7818 -#: commands/tablecmds.c:7912 commands/tablecmds.c:7971 -#: commands/tablecmds.c:8090 commands/tablecmds.c:8229 -#: commands/tablecmds.c:8299 commands/tablecmds.c:8433 -#: commands/tablecmds.c:12261 commands/tablecmds.c:13765 -#: commands/tablecmds.c:16296 +#: commands/tablecmds.c:7527 commands/tablecmds.c:7731 +#: commands/tablecmds.c:7873 commands/tablecmds.c:8005 +#: commands/tablecmds.c:8134 commands/tablecmds.c:8228 +#: commands/tablecmds.c:8329 commands/tablecmds.c:8486 +#: commands/tablecmds.c:8639 commands/tablecmds.c:8720 +#: commands/tablecmds.c:8854 commands/tablecmds.c:12704 +#: commands/tablecmds.c:14246 commands/tablecmds.c:16872 #, c-format msgid "cannot alter system column \"%s\"" msgstr "не можна змінити системний стовпець \"%s\"" -#: commands/tablecmds.c:7358 commands/tablecmds.c:7706 +#: commands/tablecmds.c:7533 commands/tablecmds.c:7879 #, c-format msgid "column \"%s\" of relation \"%s\" is an identity column" msgstr "стовпець \"%s\" відношення \"%s\" є стовпцем ідентифікації" -#: commands/tablecmds.c:7401 +#: commands/tablecmds.c:7574 #, c-format msgid "column \"%s\" is in a primary key" msgstr "стовпець \"%s\" входить до первинного ключа" -#: commands/tablecmds.c:7406 +#: commands/tablecmds.c:7579 #, c-format msgid "column \"%s\" is in index used as replica identity" msgstr "стовпець \"%s\" в індексі, що використовується як ідентифікація репліки" -#: commands/tablecmds.c:7429 +#: commands/tablecmds.c:7602 #, c-format msgid "column \"%s\" is marked NOT NULL in parent table" msgstr "стовпець \"%s\" в батьківській таблиці позначений як NOT NULL" -#: commands/tablecmds.c:7629 commands/tablecmds.c:9085 +#: commands/tablecmds.c:7802 commands/tablecmds.c:9510 #, c-format msgid "constraint must be added to child tables too" msgstr "обмеження повинно бути додано у дочірні таблиці також" -#: commands/tablecmds.c:7630 +#: commands/tablecmds.c:7803 #, c-format msgid "Column \"%s\" of relation \"%s\" is not already NOT NULL." msgstr "Стовпець \"%s\" відношення \"%s\" вже не NOT NULL." -#: commands/tablecmds.c:7715 +#: commands/tablecmds.c:7888 #, c-format msgid "column \"%s\" of relation \"%s\" is a generated column" msgstr "стовпець \"%s\" відношення \"%s\" є згенерованим стовпцем" -#: commands/tablecmds.c:7829 +#: commands/tablecmds.c:7982 +#, c-format +msgid "cannot add identity to a column of only the partitioned table" +msgstr "не може додати ідентифікатор до стовпця лише розділеної таблиці" + +#: commands/tablecmds.c:7988 +#, c-format +msgid "cannot add identity to a column of a partition" +msgstr "не може додати ідентифікатор до стовпця розділу" + +#: commands/tablecmds.c:8016 #, c-format msgid "column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added" msgstr "стовпець \"%s\" відношення \"%s\" повинен бути оголошений як NOT NULL, щоб додати ідентифікацію" -#: commands/tablecmds.c:7835 +#: commands/tablecmds.c:8022 #, c-format msgid "column \"%s\" of relation \"%s\" is already an identity column" msgstr "стовпець \"%s\" відношення \"%s\" вже є стовпцем ідентифікації" -#: commands/tablecmds.c:7841 +#: commands/tablecmds.c:8028 #, c-format msgid "column \"%s\" of relation \"%s\" already has a default value" msgstr "стовпець \"%s\" відношення \"%s\" вже має значення за замовчуванням" -#: commands/tablecmds.c:7918 commands/tablecmds.c:7979 +#: commands/tablecmds.c:8089 +#, c-format +msgid "cannot change identity column of only the partitioned table" +msgstr "не можна змінювати стовпець ідентичності лише в розбитій на розділи таблиці" + +#: commands/tablecmds.c:8095 +#, c-format +msgid "cannot change identity column of a partition" +msgstr "не можна змінити стовпець ідентичності розділу" + +#: commands/tablecmds.c:8140 commands/tablecmds.c:8236 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column" msgstr "стовпець \"%s\" відношення \"%s\" не є стовпцем ідентифікації" -#: commands/tablecmds.c:7984 +#: commands/tablecmds.c:8206 +#, c-format +msgid "cannot drop identity from a column of only the partitioned table" +msgstr "не можна вилучити ідентифікатор зі стовпця лише розбитої на розділи таблиці" + +#: commands/tablecmds.c:8212 +#, c-format +msgid "cannot drop identity from a column of a partition" +msgstr "не можна вилучити ідентифікатор зі стовпця розділу" + +#: commands/tablecmds.c:8241 #, c-format msgid "column \"%s\" of relation \"%s\" is not an identity column, skipping" msgstr "стовпець \"%s\" відношення \"%s\" не є стовпцем ідентифікації, пропускається" -#: commands/tablecmds.c:8037 +#: commands/tablecmds.c:8335 +#, c-format +msgid "column \"%s\" of relation \"%s\" is not a generated column" +msgstr "стовпець \"%s\" відношення \"%s\" не є згенерованим стовпцем" + +#: commands/tablecmds.c:8433 #, c-format msgid "ALTER TABLE / DROP EXPRESSION must be applied to child tables too" msgstr "ALTER TABLE / DROP EXPRESSION повинен бути застосований і до дочірніх таблиць" -#: commands/tablecmds.c:8059 +#: commands/tablecmds.c:8455 #, c-format msgid "cannot drop generation expression from inherited column" msgstr "не можна видалити вираз генерації з успадкованого стовпця" -#: commands/tablecmds.c:8098 +#: commands/tablecmds.c:8494 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column" msgstr "стовпець \"%s\" відношення \"%s\" не є збереженим згенерованим стовпцем" -#: commands/tablecmds.c:8103 +#: commands/tablecmds.c:8499 #, c-format msgid "column \"%s\" of relation \"%s\" is not a stored generated column, skipping" msgstr "стовпець \"%s\" відношення \"%s\" не є збереженим згенерованим стовпцем, пропускається" -#: commands/tablecmds.c:8176 +#: commands/tablecmds.c:8577 #, c-format msgid "cannot refer to non-index column by number" msgstr "не можна посилатись на неіндексований стовпець за номером" -#: commands/tablecmds.c:8219 +#: commands/tablecmds.c:8629 #, c-format msgid "column number %d of relation \"%s\" does not exist" msgstr "стовпець з номером %d відношення %s не існує" -#: commands/tablecmds.c:8238 +#: commands/tablecmds.c:8648 #, c-format msgid "cannot alter statistics on included column \"%s\" of index \"%s\"" msgstr "змінити статистику включеного стовпця \"%s\" індексу \"%s\" не можна" -#: commands/tablecmds.c:8243 +#: commands/tablecmds.c:8653 #, c-format msgid "cannot alter statistics on non-expression column \"%s\" of index \"%s\"" msgstr "змінити статистику невираженого стовпця \"%s\" індексу \"%s\" не можна" -#: commands/tablecmds.c:8245 +#: commands/tablecmds.c:8655 #, c-format msgid "Alter statistics on table column instead." msgstr "Замість цього змініть статистику стовпця в таблиці." -#: commands/tablecmds.c:8480 +#: commands/tablecmds.c:8901 #, c-format msgid "cannot drop column from typed table" msgstr "не можна видалити стовпець з типізованої таблиці" -#: commands/tablecmds.c:8539 +#: commands/tablecmds.c:8964 #, c-format msgid "column \"%s\" of relation \"%s\" does not exist, skipping" msgstr "стовпець \"%s\" відношення \"%s\" не існує, пропускається" -#: commands/tablecmds.c:8552 +#: commands/tablecmds.c:8977 #, c-format msgid "cannot drop system column \"%s\"" msgstr "не можна видалити системний стовпець \"%s\"" -#: commands/tablecmds.c:8562 +#: commands/tablecmds.c:8987 #, c-format msgid "cannot drop inherited column \"%s\"" msgstr "не можна видалити успадкований стовпець \"%s\"" -#: commands/tablecmds.c:8575 +#: commands/tablecmds.c:9000 #, c-format msgid "cannot drop column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "не можна видалити стовпець \"%s\", тому що він є частиною ключа секції відношення \"%s\"" -#: commands/tablecmds.c:8600 +#: commands/tablecmds.c:9025 #, c-format msgid "cannot drop column from only the partitioned table when partitions exist" msgstr "видалити стовпець тільки з секціонованої таблиці, коли існують секції, не можна" -#: commands/tablecmds.c:8805 +#: commands/tablecmds.c:9230 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX is not supported on partitioned tables" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX не підтримується із секціонованими таблицями" -#: commands/tablecmds.c:8830 +#: commands/tablecmds.c:9255 #, c-format msgid "ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"" msgstr "ALTER TABLE / ADD CONSTRAINT USING INDEX перейменує індекс \"%s\" в \"%s\"" -#: commands/tablecmds.c:9167 +#: commands/tablecmds.c:9592 #, c-format msgid "cannot use ONLY for foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "не можна використати ONLY для стороннього ключа в секціонованій таблиці \"%s\", який посилається на відношення \"%s\"" -#: commands/tablecmds.c:9173 +#: commands/tablecmds.c:9598 #, c-format msgid "cannot add NOT VALID foreign key on partitioned table \"%s\" referencing relation \"%s\"" msgstr "не можна додати сторонній ключ з характеристикою NOT VALID в секціоновану таблицю \"%s\", який посилається на відношення \"%s\"" -#: commands/tablecmds.c:9176 +#: commands/tablecmds.c:9601 #, c-format msgid "This feature is not yet supported on partitioned tables." msgstr "Ця функція ще не підтримується з секціонованими таблицями." -#: commands/tablecmds.c:9183 commands/tablecmds.c:9639 +#: commands/tablecmds.c:9608 commands/tablecmds.c:10064 #, c-format msgid "referenced relation \"%s\" is not a table" msgstr "вказане відношення \"%s\" не є таблицею" -#: commands/tablecmds.c:9206 +#: commands/tablecmds.c:9631 #, c-format msgid "constraints on permanent tables may reference only permanent tables" msgstr "обмеження в постійних таблицях можуть посилатись лише на постійні таблиці" -#: commands/tablecmds.c:9213 +#: commands/tablecmds.c:9638 #, c-format msgid "constraints on unlogged tables may reference only permanent or unlogged tables" msgstr "обмеження в нежурнальованих таблицях можуть посилатись тільки на постійні або нежурналюємі таблиці" -#: commands/tablecmds.c:9219 +#: commands/tablecmds.c:9644 #, c-format msgid "constraints on temporary tables may reference only temporary tables" msgstr "обмеження в тимчасових таблицях можуть посилатись лише на тимчасові таблиці" -#: commands/tablecmds.c:9223 +#: commands/tablecmds.c:9648 #, c-format msgid "constraints on temporary tables must involve temporary tables of this session" msgstr "обмеження в тимчасових таблицях повинні посилатись лише на тичасові таблиці поточного сеансу" -#: commands/tablecmds.c:9287 commands/tablecmds.c:9293 +#: commands/tablecmds.c:9712 commands/tablecmds.c:9718 #, c-format msgid "invalid %s action for foreign key constraint containing generated column" msgstr "неприпустима дія %s для обмеження зовнішнього ключа, який містить згеренований стовпець" -#: commands/tablecmds.c:9309 +#: commands/tablecmds.c:9734 #, c-format msgid "number of referencing and referenced columns for foreign key disagree" msgstr "число стовпців в джерелі і призначенні зовнішнього ключа не збігається" -#: commands/tablecmds.c:9416 +#: commands/tablecmds.c:9841 #, c-format msgid "foreign key constraint \"%s\" cannot be implemented" msgstr "обмеження зовнішнього ключа \"%s\" не можна реалізувати" -#: commands/tablecmds.c:9418 +#: commands/tablecmds.c:9843 #, c-format msgid "Key columns \"%s\" and \"%s\" are of incompatible types: %s and %s." msgstr "Стовпці ключа \"%s\" і \"%s\" містять несумісні типи: %s і %s." -#: commands/tablecmds.c:9575 +#: commands/tablecmds.c:10000 #, c-format msgid "column \"%s\" referenced in ON DELETE SET action must be part of foreign key" msgstr "стовпець \"%s\" вказаний у дії ON DELETE SET повинен бути частиною зовнішнього ключа" -#: commands/tablecmds.c:9849 commands/tablecmds.c:10319 -#: parser/parse_utilcmd.c:800 parser/parse_utilcmd.c:929 +#: commands/tablecmds.c:10274 commands/tablecmds.c:10761 +#: parser/parse_utilcmd.c:822 parser/parse_utilcmd.c:945 #, c-format msgid "foreign key constraints are not supported on foreign tables" msgstr "обмеження зовнішнього ключа для сторонніх таблиць не підтримуються" -#: commands/tablecmds.c:10872 commands/tablecmds.c:11150 -#: commands/tablecmds.c:12063 commands/tablecmds.c:12138 +#: commands/tablecmds.c:10744 +#, c-format +msgid "cannot attach table \"%s\" as a partition because it is referenced by foreign key \"%s\"" +msgstr "не можна підключити таблицю \"%s\" в якості секції, тому що на неї посилається сторонній ключ \"%s\"" + +#: commands/tablecmds.c:11314 commands/tablecmds.c:11595 +#: commands/tablecmds.c:12507 commands/tablecmds.c:12581 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist" msgstr "обмеження \"%s\" відношення \"%s\" не існує" -#: commands/tablecmds.c:10879 +#: commands/tablecmds.c:11321 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key constraint" msgstr "обмеження \"%s\" відношення \"%s\" не є обмеженням зовнішнього ключа" -#: commands/tablecmds.c:10917 +#: commands/tablecmds.c:11359 #, c-format msgid "cannot alter constraint \"%s\" on relation \"%s\"" msgstr "не можна змінити обмеження \"%s\" відношення \"%s\"" -#: commands/tablecmds.c:10920 +#: commands/tablecmds.c:11362 #, c-format msgid "Constraint \"%s\" is derived from constraint \"%s\" of relation \"%s\"." msgstr "Обмеження \"%s\" походить з обмеження \"%s\" відношення \"%s\"." -#: commands/tablecmds.c:10922 +#: commands/tablecmds.c:11364 #, c-format msgid "You may alter the constraint it derives from instead." msgstr "Натомість ви можете змінити початкове обмеження." -#: commands/tablecmds.c:11158 +#: commands/tablecmds.c:11603 #, c-format msgid "constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint" msgstr "обмеження \"%s\" відношення \"%s\" не є зовнішнім ключем або перевіркою обмеженням " -#: commands/tablecmds.c:11235 +#: commands/tablecmds.c:11680 #, c-format msgid "constraint must be validated on child tables too" msgstr "обмеження повинно дотримуватися в дочірніх таблицях також" -#: commands/tablecmds.c:11322 +#: commands/tablecmds.c:11767 #, c-format msgid "column \"%s\" referenced in foreign key constraint does not exist" msgstr "стовпець \"%s\", вказаний в обмеженні зовнішнього ключа, не існує" -#: commands/tablecmds.c:11328 +#: commands/tablecmds.c:11773 #, c-format msgid "system columns cannot be used in foreign keys" msgstr "в зовнішніх ключах не можна використовувати системні стовпці" -#: commands/tablecmds.c:11332 +#: commands/tablecmds.c:11777 #, c-format msgid "cannot have more than %d keys in a foreign key" msgstr "у зовнішньому ключі не може бути більш ніж %d ключів" -#: commands/tablecmds.c:11397 +#: commands/tablecmds.c:11842 #, c-format msgid "cannot use a deferrable primary key for referenced table \"%s\"" msgstr "використовувати затримуваний первинний ключ в цільовій зовнішній таблиці \"%s\" не можна" -#: commands/tablecmds.c:11414 +#: commands/tablecmds.c:11859 #, c-format msgid "there is no primary key for referenced table \"%s\"" msgstr "у цільовій зовнішній таблиці \"%s\" немає первинного ключа" -#: commands/tablecmds.c:11482 +#: commands/tablecmds.c:11927 #, c-format msgid "foreign key referenced-columns list must not contain duplicates" msgstr "у списку стовпців зовнішнього ключа не повинно бути повторень" -#: commands/tablecmds.c:11574 +#: commands/tablecmds.c:12019 #, c-format msgid "cannot use a deferrable unique constraint for referenced table \"%s\"" msgstr "використовувати затримане обмеження унікальності в цільовій зовнішній таблиці \"%s\" не можна" -#: commands/tablecmds.c:11579 +#: commands/tablecmds.c:12024 #, c-format msgid "there is no unique constraint matching given keys for referenced table \"%s\"" msgstr "у цільовій зовнішній таблиці \"%s\" немає обмеження унікальності, відповідного даним ключам" -#: commands/tablecmds.c:12019 +#: commands/tablecmds.c:12463 #, c-format msgid "cannot drop inherited constraint \"%s\" of relation \"%s\"" msgstr "видалити успадковане обмеження \"%s\" відношення \"%s\" не можна" -#: commands/tablecmds.c:12069 +#: commands/tablecmds.c:12513 #, c-format msgid "constraint \"%s\" of relation \"%s\" does not exist, skipping" msgstr "обмеження \"%s\" відношення \"%s\" не існує, пропускається" -#: commands/tablecmds.c:12245 +#: commands/tablecmds.c:12688 #, c-format msgid "cannot alter column type of typed table" msgstr "змінити тип стовпця в типізованій таблиці не можна" -#: commands/tablecmds.c:12272 +#: commands/tablecmds.c:12714 +#, c-format +msgid "cannot specify USING when altering type of generated column" +msgstr "не можна вказати USING під час зміни типу згенерованого стовпця" + +#: commands/tablecmds.c:12715 commands/tablecmds.c:17918 +#: commands/tablecmds.c:18008 commands/trigger.c:656 +#: rewrite/rewriteHandler.c:935 rewrite/rewriteHandler.c:970 +#, c-format +msgid "Column \"%s\" is a generated column." +msgstr "Стовпець \"%s\" є згенерованим стовпцем." + +#: commands/tablecmds.c:12725 #, c-format msgid "cannot alter inherited column \"%s\"" msgstr "змінити успадкований стовпець \"%s\" не можна" -#: commands/tablecmds.c:12281 +#: commands/tablecmds.c:12734 #, c-format msgid "cannot alter column \"%s\" because it is part of the partition key of relation \"%s\"" msgstr "не можна змінити стовпець \"%s\", тому що він є частиною ключа секції відношення \"%s\"" -#: commands/tablecmds.c:12331 +#: commands/tablecmds.c:12784 #, c-format msgid "result of USING clause for column \"%s\" cannot be cast automatically to type %s" msgstr "результати речення USING для стовпця \"%s\" не можна автоматично наведено для типу %s" -#: commands/tablecmds.c:12334 +#: commands/tablecmds.c:12787 #, c-format msgid "You might need to add an explicit cast." msgstr "Можливо, необхідно додати явне приведення типу." -#: commands/tablecmds.c:12338 +#: commands/tablecmds.c:12791 #, c-format msgid "column \"%s\" cannot be cast automatically to type %s" msgstr "стовпець \"%s\" не можна автоматично привести до типу %s" #. translator: USING is SQL, don't translate it -#: commands/tablecmds.c:12341 +#: commands/tablecmds.c:12795 #, c-format msgid "You might need to specify \"USING %s::%s\"." msgstr "Можливо, необхідно вказати \"USING %s::%s\"." -#: commands/tablecmds.c:12440 +#: commands/tablecmds.c:12894 #, c-format msgid "cannot alter inherited column \"%s\" of relation \"%s\"" msgstr "не можна змінити успадкований стовпець \"%s\" відношення \"%s\"" -#: commands/tablecmds.c:12469 +#: commands/tablecmds.c:12923 #, c-format msgid "USING expression contains a whole-row table reference." msgstr "Вираз USING містить посилання на тип усього рядка таблиці." -#: commands/tablecmds.c:12480 +#: commands/tablecmds.c:12934 #, c-format msgid "type of inherited column \"%s\" must be changed in child tables too" msgstr "тип успадкованого стовпця \"%s\" повинен бути змінений і в дочірніх таблицях" -#: commands/tablecmds.c:12605 +#: commands/tablecmds.c:13059 #, c-format msgid "cannot alter type of column \"%s\" twice" msgstr "не можна змінити тип стовпця \"%s\" двічі" -#: commands/tablecmds.c:12643 +#: commands/tablecmds.c:13097 #, c-format msgid "generation expression for column \"%s\" cannot be cast automatically to type %s" msgstr "вираз генерації для стовпця \"%s\" не можна автоматично привести до типу %s" -#: commands/tablecmds.c:12648 +#: commands/tablecmds.c:13102 #, c-format msgid "default for column \"%s\" cannot be cast automatically to type %s" msgstr "значення за замовчуванням для стовпця \"%s\" не можна автоматично привести до типу %s" -#: commands/tablecmds.c:12729 +#: commands/tablecmds.c:13406 #, c-format -msgid "cannot alter type of a column used by a view or rule" -msgstr "змінити тип стовпця, залученого в поданні або правилі, не можна" +msgid "cannot alter type of a column used by a function or procedure" +msgstr "неможливо змінити тип стовпця, який використовується функцією або процедурою" -#: commands/tablecmds.c:12730 commands/tablecmds.c:12749 -#: commands/tablecmds.c:12767 +#: commands/tablecmds.c:13407 commands/tablecmds.c:13422 +#: commands/tablecmds.c:13442 commands/tablecmds.c:13461 +#: commands/tablecmds.c:13520 #, c-format msgid "%s depends on column \"%s\"" msgstr "%s залежить від стовпця \"%s\"" -#: commands/tablecmds.c:12748 +#: commands/tablecmds.c:13421 +#, c-format +msgid "cannot alter type of a column used by a view or rule" +msgstr "змінити тип стовпця, залученого в поданні або правилі, не можна" + +#: commands/tablecmds.c:13441 #, c-format msgid "cannot alter type of a column used in a trigger definition" msgstr "неможливо змінити тип стовпця, що використовується у визначенні тригеру" -#: commands/tablecmds.c:12766 +#: commands/tablecmds.c:13460 #, c-format msgid "cannot alter type of a column used in a policy definition" msgstr "неможливо змінити тип стовпця, що використовується у визначенні політики" -#: commands/tablecmds.c:12797 +#: commands/tablecmds.c:13491 #, c-format msgid "cannot alter type of a column used by a generated column" msgstr "змінити тип стовпця, який використовується згенерованим стовпцем, не можна" -#: commands/tablecmds.c:12798 +#: commands/tablecmds.c:13492 #, c-format msgid "Column \"%s\" is used by generated column \"%s\"." msgstr "Стовпець \"%s\" використовується згенерованим стовпцем \"%s\"." -#: commands/tablecmds.c:13873 commands/tablecmds.c:13885 +#: commands/tablecmds.c:13519 +#, c-format +msgid "cannot alter type of a column used by a publication WHERE clause" +msgstr "неможливо змінити тип стовпця, який використовується публікацією в реченні WHERE" + +#: commands/tablecmds.c:14354 commands/tablecmds.c:14366 #, c-format msgid "cannot change owner of index \"%s\"" msgstr "неможливо змінити власника індексу \"%s\"" -#: commands/tablecmds.c:13875 commands/tablecmds.c:13887 +#: commands/tablecmds.c:14356 commands/tablecmds.c:14368 #, c-format msgid "Change the ownership of the index's table instead." msgstr "Замість цього змініть власника таблиці, що містить цей індекс." -#: commands/tablecmds.c:13901 +#: commands/tablecmds.c:14382 #, c-format msgid "cannot change owner of sequence \"%s\"" msgstr "неможливо змінити власника послідовності \"%s\"" -#: commands/tablecmds.c:13926 +#: commands/tablecmds.c:14407 #, c-format msgid "cannot change owner of relation \"%s\"" msgstr "неможливо змінити власника відношення \"%s\"" -#: commands/tablecmds.c:14288 +#: commands/tablecmds.c:14874 #, c-format msgid "cannot have multiple SET TABLESPACE subcommands" msgstr "в одній інструкції не може бути декілька підкоманд SET TABLESPACE" -#: commands/tablecmds.c:14365 +#: commands/tablecmds.c:14951 #, c-format msgid "cannot set options for relation \"%s\"" msgstr "неможливо встановити параметри відношення \"%s\"" -#: commands/tablecmds.c:14399 commands/view.c:445 +#: commands/tablecmds.c:14985 commands/view.c:440 #, c-format msgid "WITH CHECK OPTION is supported only on automatically updatable views" msgstr "WITH CHECK OPTION підтримується лише з автооновлюваними поданнями" -#: commands/tablecmds.c:14649 +#: commands/tablecmds.c:15235 #, c-format msgid "only tables, indexes, and materialized views exist in tablespaces" msgstr "у табличних просторах існують лише таблиці, індекси та матеріалізовані подання" -#: commands/tablecmds.c:14661 +#: commands/tablecmds.c:15247 #, c-format msgid "cannot move relations in to or out of pg_global tablespace" msgstr "переміщувати відношення у або з табличного простору pg_global не можна" -#: commands/tablecmds.c:14753 +#: commands/tablecmds.c:15339 #, c-format msgid "aborting because lock on relation \"%s.%s\" is not available" msgstr "переривання через блокування відношення \"%s.%s\" неможливе" -#: commands/tablecmds.c:14769 +#: commands/tablecmds.c:15355 #, c-format msgid "no matching relations in tablespace \"%s\" found" msgstr " табличному просторі \"%s\" не знайдені відповідні відносини" -#: commands/tablecmds.c:14887 +#: commands/tablecmds.c:15477 #, c-format msgid "cannot change inheritance of typed table" msgstr "змінити успадкування типізованої таблиці не можна" -#: commands/tablecmds.c:14892 commands/tablecmds.c:15410 +#: commands/tablecmds.c:15482 commands/tablecmds.c:15982 #, c-format msgid "cannot change inheritance of a partition" msgstr "змінити успадкування секції не можна" -#: commands/tablecmds.c:14897 +#: commands/tablecmds.c:15487 #, c-format msgid "cannot change inheritance of partitioned table" msgstr "змінити успадкування секціонованої таблиці не можна" -#: commands/tablecmds.c:14943 +#: commands/tablecmds.c:15533 #, c-format msgid "cannot inherit to temporary relation of another session" msgstr "успадкування для тимчасового відношення іншого сеансу не можливе" -#: commands/tablecmds.c:14956 +#: commands/tablecmds.c:15546 #, c-format msgid "cannot inherit from a partition" msgstr "успадкування від секції неможливе" -#: commands/tablecmds.c:14978 commands/tablecmds.c:17841 +#: commands/tablecmds.c:15568 commands/tablecmds.c:18419 #, c-format msgid "circular inheritance not allowed" msgstr "циклічне успадкування неприпустиме" -#: commands/tablecmds.c:14979 commands/tablecmds.c:17842 +#: commands/tablecmds.c:15569 commands/tablecmds.c:18420 #, c-format msgid "\"%s\" is already a child of \"%s\"." msgstr "\"%s\" вже є нащадком \"%s\"." -#: commands/tablecmds.c:14992 +#: commands/tablecmds.c:15582 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming an inheritance child" msgstr "тригер \"%s\" не дозволяє таблиці \"%s\" стати нащадком успадкування" -#: commands/tablecmds.c:14994 +#: commands/tablecmds.c:15584 #, c-format msgid "ROW triggers with transition tables are not supported in inheritance hierarchies." msgstr "Тригери ROW з перехідними таблицями не підтримуються в ієрархіях успадкування." -#: commands/tablecmds.c:15197 +#: commands/tablecmds.c:15773 #, c-format msgid "column \"%s\" in child table must be marked NOT NULL" msgstr "стовпець \"%s\" в дочірній таблиці має бути позначений як NOT NULL" -#: commands/tablecmds.c:15206 +#: commands/tablecmds.c:15782 #, c-format msgid "column \"%s\" in child table must be a generated column" msgstr "стовпець \"%s\" у дочірній таблиці повинен бути згенерованим стовпцем" -#: commands/tablecmds.c:15211 +#: commands/tablecmds.c:15786 #, c-format msgid "column \"%s\" in child table must not be a generated column" msgstr "стовпець \"%s\" у дочірній таблиці повинен бути не генерованим стовпцем" -#: commands/tablecmds.c:15242 +#: commands/tablecmds.c:15824 #, c-format msgid "child table is missing column \"%s\"" msgstr "у дочірній таблиці не вистачає стовпця \"%s\"" -#: commands/tablecmds.c:15330 +#: commands/tablecmds.c:15905 #, c-format msgid "child table \"%s\" has different definition for check constraint \"%s\"" msgstr "дочірня таблиця \"%s\" має інше визначення перевірочного обмеження \"%s\"" -#: commands/tablecmds.c:15338 +#: commands/tablecmds.c:15912 #, c-format msgid "constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"" msgstr "обмеження \"%s\" конфліктує з неуспадкованим обмеженням дочірньої таблиці \"%s\"" -#: commands/tablecmds.c:15349 +#: commands/tablecmds.c:15922 #, c-format msgid "constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"" msgstr "обмеження \"%s\" конфліктує з NOT VALID обмеженням дочірньої таблиці \"%s\"" -#: commands/tablecmds.c:15388 +#: commands/tablecmds.c:15960 #, c-format msgid "child table is missing constraint \"%s\"" msgstr "у дочірній таблиці не вистачає обмеження \"%s\"" -#: commands/tablecmds.c:15474 +#: commands/tablecmds.c:16046 #, c-format msgid "partition \"%s\" already pending detach in partitioned table \"%s.%s\"" msgstr "розділ \"%s\" вже очікує відключення в секціонованій таблиці \"%s.%s\"" -#: commands/tablecmds.c:15503 commands/tablecmds.c:15551 +#: commands/tablecmds.c:16075 commands/tablecmds.c:16121 #, c-format msgid "relation \"%s\" is not a partition of relation \"%s\"" msgstr "відношення \"%s\" не є секцією відношення \"%s\"" -#: commands/tablecmds.c:15557 +#: commands/tablecmds.c:16127 #, c-format msgid "relation \"%s\" is not a parent of relation \"%s\"" msgstr "відношення \"%s\" не є предком відношення \"%s\"" -#: commands/tablecmds.c:15785 +#: commands/tablecmds.c:16354 #, c-format msgid "typed tables cannot inherit" msgstr "типізовані таблиці не можуть успадковуватись" -#: commands/tablecmds.c:15815 +#: commands/tablecmds.c:16384 #, c-format msgid "table is missing column \"%s\"" msgstr "у таблиці не вистачає стовпця \"%s\"" -#: commands/tablecmds.c:15826 +#: commands/tablecmds.c:16395 #, c-format msgid "table has column \"%s\" where type requires \"%s\"" msgstr "таблиця містить стовпець \"%s\", а тип потребує \"%s\"" -#: commands/tablecmds.c:15835 +#: commands/tablecmds.c:16404 #, c-format msgid "table \"%s\" has different type for column \"%s\"" msgstr "таблиця \"%s\" містить стовпець \"%s\" іншого типу" -#: commands/tablecmds.c:15849 +#: commands/tablecmds.c:16418 #, c-format msgid "table has extra column \"%s\"" msgstr "таблиця містить зайвий стовпець \"%s\"" -#: commands/tablecmds.c:15901 +#: commands/tablecmds.c:16470 #, c-format msgid "\"%s\" is not a typed table" msgstr "\"%s\" - не типізована таблиця" -#: commands/tablecmds.c:16075 +#: commands/tablecmds.c:16644 #, c-format msgid "cannot use non-unique index \"%s\" as replica identity" msgstr "для ідентифікації репліки не можна використати неунікальний індекс \"%s\"" -#: commands/tablecmds.c:16081 +#: commands/tablecmds.c:16650 #, c-format msgid "cannot use non-immediate index \"%s\" as replica identity" msgstr "для ідентифікації репліки не можна використати небезпосередній індекс \"%s\"" -#: commands/tablecmds.c:16087 +#: commands/tablecmds.c:16656 #, c-format msgid "cannot use expression index \"%s\" as replica identity" msgstr "для ідентифікації репліки не можна використати індекс з виразом \"%s\"" -#: commands/tablecmds.c:16093 +#: commands/tablecmds.c:16662 #, c-format msgid "cannot use partial index \"%s\" as replica identity" msgstr "для ідентифікації репліки не можна використати частковий індекс \"%s\"" -#: commands/tablecmds.c:16110 +#: commands/tablecmds.c:16679 #, c-format msgid "index \"%s\" cannot be used as replica identity because column %d is a system column" msgstr "індекс \"%s\" не можна використати як ідентифікацію репліки, тому що стовпець %d - системний стовпець" -#: commands/tablecmds.c:16117 +#: commands/tablecmds.c:16686 #, c-format msgid "index \"%s\" cannot be used as replica identity because column \"%s\" is nullable" msgstr "індекс \"%s\" не можна використати як ідентифікацію репліки, тому що стовпець \"%s\" допускає Null" -#: commands/tablecmds.c:16362 +#: commands/tablecmds.c:16938 #, c-format msgid "cannot change logged status of table \"%s\" because it is temporary" msgstr "змінити стан журналювання таблиці \"%s\" не можна, тому що вона тимчасова" -#: commands/tablecmds.c:16386 +#: commands/tablecmds.c:16962 #, c-format msgid "cannot change table \"%s\" to unlogged because it is part of a publication" msgstr "таблицю \"%s\" не можна змінити на нежурнальовану, тому що вона є частиною публікації" -#: commands/tablecmds.c:16388 +#: commands/tablecmds.c:16964 #, c-format msgid "Unlogged relations cannot be replicated." msgstr "Нежурнальовані відношення не підтримують реплікацію." -#: commands/tablecmds.c:16433 +#: commands/tablecmds.c:17009 #, c-format msgid "could not change table \"%s\" to logged because it references unlogged table \"%s\"" msgstr "не вдалося змінити таблицю \"%s\" на журнальовану, тому що вона посилається на нежурнальовану таблицю \"%s\"" -#: commands/tablecmds.c:16443 +#: commands/tablecmds.c:17019 #, c-format msgid "could not change table \"%s\" to unlogged because it references logged table \"%s\"" msgstr "не вдалося змінити таблицю \"%s\" на нежурнальовану, тому що вона посилається на журнальовану таблицю \"%s\"" -#: commands/tablecmds.c:16501 +#: commands/tablecmds.c:17077 #, c-format msgid "cannot move an owned sequence into another schema" msgstr "перемістити послідовність з власником в іншу схему не можна" -#: commands/tablecmds.c:16608 +#: commands/tablecmds.c:17182 #, c-format msgid "relation \"%s\" already exists in schema \"%s\"" msgstr "відношення \"%s\" вже існує в схемі \"%s\"" -#: commands/tablecmds.c:17028 +#: commands/tablecmds.c:17603 #, c-format msgid "\"%s\" is not a table or materialized view" msgstr "\"%s\" не є таблицею або матеріалізованим поданням" -#: commands/tablecmds.c:17178 +#: commands/tablecmds.c:17756 #, c-format msgid "\"%s\" is not a composite type" msgstr "\"%s\" - не складений тип" -#: commands/tablecmds.c:17208 +#: commands/tablecmds.c:17786 #, c-format msgid "cannot change schema of index \"%s\"" msgstr "змінити схему індексу \"%s\" не можна" -#: commands/tablecmds.c:17210 commands/tablecmds.c:17224 +#: commands/tablecmds.c:17788 commands/tablecmds.c:17802 #, c-format msgid "Change the schema of the table instead." msgstr "Замість цього змініть схему таблиці." -#: commands/tablecmds.c:17214 +#: commands/tablecmds.c:17792 #, c-format msgid "cannot change schema of composite type \"%s\"" msgstr "змінити схему складеного типу \"%s\" не можна" -#: commands/tablecmds.c:17222 +#: commands/tablecmds.c:17800 #, c-format msgid "cannot change schema of TOAST table \"%s\"" msgstr "змінити схему таблиці TOAST \"%s\" не можна" -#: commands/tablecmds.c:17254 +#: commands/tablecmds.c:17832 #, c-format msgid "cannot use \"list\" partition strategy with more than one column" msgstr "стратегія секціонування \"по списку\" не може використовувати декілька стовпців" -#: commands/tablecmds.c:17320 +#: commands/tablecmds.c:17898 #, c-format msgid "column \"%s\" named in partition key does not exist" msgstr "стовпець \"%s\", згаданий в ключі секціонування, не існує" -#: commands/tablecmds.c:17328 +#: commands/tablecmds.c:17906 #, c-format msgid "cannot use system column \"%s\" in partition key" msgstr "системний стовпець \"%s\" не можна використати в ключі секціонування" -#: commands/tablecmds.c:17339 commands/tablecmds.c:17429 +#: commands/tablecmds.c:17917 commands/tablecmds.c:18007 #, c-format msgid "cannot use generated column in partition key" msgstr "використати згенерований стовпець в ключі секції, не можна" -#: commands/tablecmds.c:17340 commands/tablecmds.c:17430 commands/trigger.c:663 -#: rewrite/rewriteHandler.c:936 rewrite/rewriteHandler.c:971 -#, c-format -msgid "Column \"%s\" is a generated column." -msgstr "Стовпець \"%s\" є згенерованим стовпцем." - -#: commands/tablecmds.c:17412 +#: commands/tablecmds.c:17990 #, c-format msgid "partition key expressions cannot contain system column references" msgstr "вирази ключа секціонування не можуть містити посилання на системний стовпець" -#: commands/tablecmds.c:17459 +#: commands/tablecmds.c:18037 #, c-format msgid "functions in partition key expression must be marked IMMUTABLE" msgstr "функції у виразі ключа секціонування повинні бути позначені як IMMUTABLE" -#: commands/tablecmds.c:17468 +#: commands/tablecmds.c:18046 #, c-format msgid "cannot use constant expression as partition key" msgstr "не можна використати константий вираз як ключ секціонування" -#: commands/tablecmds.c:17489 +#: commands/tablecmds.c:18067 #, c-format msgid "could not determine which collation to use for partition expression" msgstr "не вдалося визначити, яке правило сортування використати для виразу секціонування" -#: commands/tablecmds.c:17524 +#: commands/tablecmds.c:18102 #, c-format msgid "You must specify a hash operator class or define a default hash operator class for the data type." msgstr "Ви повинні вказати клас операторів гешування або визначити клас операторів гешування за замовчуванням для цього типу даних." -#: commands/tablecmds.c:17530 +#: commands/tablecmds.c:18108 #, c-format msgid "You must specify a btree operator class or define a default btree operator class for the data type." msgstr "Ви повинні вказати клас операторів (btree) або визначити клас операторів (btree) за замовчуванням для цього типу даних." -#: commands/tablecmds.c:17781 +#: commands/tablecmds.c:18359 #, c-format msgid "\"%s\" is already a partition" msgstr "\"%s\" вже є секцією" -#: commands/tablecmds.c:17787 +#: commands/tablecmds.c:18365 #, c-format msgid "cannot attach a typed table as partition" msgstr "неможливо підключити типізовану таблицю в якості секції" -#: commands/tablecmds.c:17803 +#: commands/tablecmds.c:18381 #, c-format msgid "cannot attach inheritance child as partition" msgstr "неможливо підключити нащадка успадкування в якості секції" -#: commands/tablecmds.c:17817 +#: commands/tablecmds.c:18395 #, c-format msgid "cannot attach inheritance parent as partition" msgstr "неможливо підключити предка успадкування в якості секції" -#: commands/tablecmds.c:17851 +#: commands/tablecmds.c:18429 #, c-format msgid "cannot attach a temporary relation as partition of permanent relation \"%s\"" msgstr "неможливо підкючити тимчасове відношення в якості секції постійного відношення \"%s\"" -#: commands/tablecmds.c:17859 +#: commands/tablecmds.c:18437 #, c-format msgid "cannot attach a permanent relation as partition of temporary relation \"%s\"" msgstr "неможливо підключити постійне відношення в якості секції тимчасового відношення \"%s\"" -#: commands/tablecmds.c:17867 +#: commands/tablecmds.c:18445 #, c-format msgid "cannot attach as partition of temporary relation of another session" msgstr "неможливо підключити секцію до тимчасового відношення в іншому сеансі" -#: commands/tablecmds.c:17874 +#: commands/tablecmds.c:18452 #, c-format msgid "cannot attach temporary relation of another session as partition" msgstr "неможливо підключити тимчасове відношення з іншого сеансу в якості секції" -#: commands/tablecmds.c:17894 +#: commands/tablecmds.c:18472 +#, c-format +msgid "table \"%s\" being attached contains an identity column \"%s\"" +msgstr "таблиця \"%s\", що додається, містить стовпець ідентичності \"%s\"" + +#: commands/tablecmds.c:18474 +#, c-format +msgid "The new partition may not contain an identity column." +msgstr "Новий розділ може не містити стовпця ідентичності." + +#: commands/tablecmds.c:18482 #, c-format msgid "table \"%s\" contains column \"%s\" not found in parent \"%s\"" msgstr "таблиця \"%s\" містить стовпець \"%s\", відсутній в батьківській \"%s\"" -#: commands/tablecmds.c:17897 +#: commands/tablecmds.c:18485 #, c-format msgid "The new partition may contain only the columns present in parent." msgstr "Нова секція може містити лише стовпці, що є у батьківській таблиці." -#: commands/tablecmds.c:17909 +#: commands/tablecmds.c:18497 #, c-format msgid "trigger \"%s\" prevents table \"%s\" from becoming a partition" msgstr "тригер \"%s\" не дозволяє зробити таблицю \"%s\" секцією" -#: commands/tablecmds.c:17911 +#: commands/tablecmds.c:18499 #, c-format msgid "ROW triggers with transition tables are not supported on partitions." msgstr "Тригери ROW з перехідними таблицями не підтримуються для секцій." -#: commands/tablecmds.c:18090 +#: commands/tablecmds.c:18675 #, c-format msgid "cannot attach foreign table \"%s\" as partition of partitioned table \"%s\"" msgstr "не можна підключити зовнішню таблицю \"%s\" в якості секції секціонованої таблиці \"%s\"" -#: commands/tablecmds.c:18093 +#: commands/tablecmds.c:18678 #, c-format msgid "Partitioned table \"%s\" contains unique indexes." msgstr "Секціонована таблиця \"%s\" містить унікальні індекси." -#: commands/tablecmds.c:18410 +#: commands/tablecmds.c:19000 #, c-format msgid "cannot detach partitions concurrently when a default partition exists" msgstr "не можна одночасно відключити розділи, коли існує розділ за замовчуванням" -#: commands/tablecmds.c:18519 +#: commands/tablecmds.c:19109 #, c-format msgid "partitioned table \"%s\" was removed concurrently" msgstr "секціоновану таблицю \"%s\" було видалено одночасно" -#: commands/tablecmds.c:18525 +#: commands/tablecmds.c:19115 #, c-format msgid "partition \"%s\" was removed concurrently" msgstr "розділ \"%s\" було видалено паралельно" -#: commands/tablecmds.c:19040 commands/tablecmds.c:19060 -#: commands/tablecmds.c:19081 commands/tablecmds.c:19100 -#: commands/tablecmds.c:19142 +#: commands/tablecmds.c:19651 commands/tablecmds.c:19671 +#: commands/tablecmds.c:19692 commands/tablecmds.c:19711 +#: commands/tablecmds.c:19753 #, c-format msgid "cannot attach index \"%s\" as a partition of index \"%s\"" msgstr "неможливо підключити індекс \"%s\" в якості секції індексу \"%s\"" -#: commands/tablecmds.c:19043 +#: commands/tablecmds.c:19654 #, c-format msgid "Index \"%s\" is already attached to another index." msgstr "Індекс \"%s\" вже підключений до іншого індексу." -#: commands/tablecmds.c:19063 +#: commands/tablecmds.c:19674 #, c-format msgid "Index \"%s\" is not an index on any partition of table \"%s\"." msgstr "Індекс \"%s\" не є індексом жодної секції таблиці \"%s\"." -#: commands/tablecmds.c:19084 +#: commands/tablecmds.c:19695 #, c-format msgid "The index definitions do not match." msgstr "Визначення індексів не співпадають." -#: commands/tablecmds.c:19103 +#: commands/tablecmds.c:19714 #, c-format msgid "The index \"%s\" belongs to a constraint in table \"%s\" but no constraint exists for index \"%s\"." msgstr "Індекс \"%s\" належить обмеженню в таблиці \"%s\", але обмеження для індексу \"%s\" не існує." -#: commands/tablecmds.c:19145 +#: commands/tablecmds.c:19756 #, c-format msgid "Another index is already attached for partition \"%s\"." msgstr "До секції \"%s\" вже підключений інший індекс." -#: commands/tablecmds.c:19381 +#: commands/tablecmds.c:19992 #, c-format msgid "column data type %s does not support compression" msgstr "тип даних стовпця %s не підтримує стискання" -#: commands/tablecmds.c:19388 +#: commands/tablecmds.c:19999 #, c-format msgid "invalid compression method \"%s\"" msgstr "неприпустимий метод стискання \"%s\"" -#: commands/tablecmds.c:19414 +#: commands/tablecmds.c:20025 #, c-format msgid "invalid storage type \"%s\"" msgstr "неприпустимий тип сховища \"%s\"" -#: commands/tablecmds.c:19424 +#: commands/tablecmds.c:20035 #, c-format msgid "column data type %s can only have storage PLAIN" msgstr "тип даних стовпця %s може мати тільки сховище PLAIN" -#: commands/tablespace.c:199 commands/tablespace.c:650 +#: commands/tablespace.c:193 commands/tablespace.c:644 #, c-format msgid "\"%s\" exists but is not a directory" msgstr "\"%s\" існує, але це не каталог" -#: commands/tablespace.c:230 +#: commands/tablespace.c:224 #, c-format msgid "permission denied to create tablespace \"%s\"" msgstr "немає прав на створення табличного простору \"%s\"" -#: commands/tablespace.c:232 +#: commands/tablespace.c:226 #, c-format msgid "Must be superuser to create a tablespace." msgstr "Щоб створити табличний простір, потрібно бути суперкористувачем." -#: commands/tablespace.c:248 +#: commands/tablespace.c:242 #, c-format msgid "tablespace location cannot contain single quotes" msgstr "у шляху до розташування табличного простіру не повинно бути одинарних лапок" -#: commands/tablespace.c:261 +#: commands/tablespace.c:255 #, c-format msgid "tablespace location must be an absolute path" msgstr "шлях до розташування табличного простору повинен бути абсолютним" -#: commands/tablespace.c:273 +#: commands/tablespace.c:267 #, c-format msgid "tablespace location \"%s\" is too long" msgstr "шлях до розташування табличного простору \"%s\" занадто довгий" -#: commands/tablespace.c:280 +#: commands/tablespace.c:274 #, c-format msgid "tablespace location should not be inside the data directory" msgstr "табличний простір не повинен розташовуватись всередині каталогу даних" -#: commands/tablespace.c:289 commands/tablespace.c:976 +#: commands/tablespace.c:283 commands/tablespace.c:970 #, c-format msgid "unacceptable tablespace name \"%s\"" msgstr "неприпустиме ім'я табличного простору \"%s\"" -#: commands/tablespace.c:291 commands/tablespace.c:977 +#: commands/tablespace.c:285 commands/tablespace.c:971 #, c-format msgid "The prefix \"pg_\" is reserved for system tablespaces." msgstr "Префікс \"\"pg_\" зарезервований для системних табличних просторів." -#: commands/tablespace.c:310 commands/tablespace.c:998 +#: commands/tablespace.c:304 commands/tablespace.c:992 #, c-format msgid "tablespace \"%s\" already exists" msgstr "табличний простір \"%s\" вже існує" -#: commands/tablespace.c:326 +#: commands/tablespace.c:320 #, c-format msgid "pg_tablespace OID value not set when in binary upgrade mode" msgstr "значення OID pg_tablespace не встановлено в режимі двійкового оновлення" -#: commands/tablespace.c:431 commands/tablespace.c:959 -#: commands/tablespace.c:1048 commands/tablespace.c:1117 -#: commands/tablespace.c:1263 commands/tablespace.c:1466 +#: commands/tablespace.c:425 commands/tablespace.c:953 +#: commands/tablespace.c:1042 commands/tablespace.c:1111 +#: commands/tablespace.c:1257 commands/tablespace.c:1460 #, c-format msgid "tablespace \"%s\" does not exist" msgstr "табличний простір \"%s\" не існує" -#: commands/tablespace.c:437 +#: commands/tablespace.c:431 #, c-format msgid "tablespace \"%s\" does not exist, skipping" msgstr "табличний простір \"%s\" вже існує, пропускається" -#: commands/tablespace.c:463 +#: commands/tablespace.c:457 #, c-format msgid "tablespace \"%s\" cannot be dropped because some objects depend on it" msgstr "табличний простір \"%s\" не можна видалити, тому що деякі об'єкти залежать від нього" -#: commands/tablespace.c:530 +#: commands/tablespace.c:524 #, c-format msgid "tablespace \"%s\" is not empty" msgstr "табличний простір \"%s\" не пустий" -#: commands/tablespace.c:617 +#: commands/tablespace.c:611 #, c-format msgid "directory \"%s\" does not exist" msgstr "каталог \"%s\" не існує" -#: commands/tablespace.c:618 +#: commands/tablespace.c:612 #, c-format msgid "Create this directory for the tablespace before restarting the server." msgstr "Створіть цей каталог для табличного простору до перезапуску сервера." -#: commands/tablespace.c:623 +#: commands/tablespace.c:617 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "не вдалося встановити права для каталогу \"%s\": %m" -#: commands/tablespace.c:655 +#: commands/tablespace.c:649 #, c-format msgid "directory \"%s\" already in use as a tablespace" msgstr "каталог \"%s\" вже використовується в якості табличного простору" -#: commands/tablespace.c:833 commands/tablespace.c:919 +#: commands/tablespace.c:827 commands/tablespace.c:913 #, c-format msgid "could not remove symbolic link \"%s\": %m" msgstr "не вдалося видалити символьне посилання \"%s\": %m" -#: commands/tablespace.c:842 commands/tablespace.c:927 +#: commands/tablespace.c:836 commands/tablespace.c:921 #, c-format msgid "\"%s\" is not a directory or symbolic link" msgstr "\"%s\" - не каталог або символьне посилання" -#: commands/tablespace.c:1122 +#: commands/tablespace.c:1116 #, c-format msgid "Tablespace \"%s\" does not exist." msgstr "Табличний простір \"%s\" не існує." -#: commands/tablespace.c:1568 +#: commands/tablespace.c:1562 #, c-format msgid "directories for tablespace %u could not be removed" msgstr "не вдалося видалити каталоги табличного простору %u" -#: commands/tablespace.c:1570 +#: commands/tablespace.c:1564 #, c-format msgid "You can remove the directories manually if necessary." msgstr "За потреби ви можете видалити каталоги вручну." -#: commands/trigger.c:232 commands/trigger.c:243 +#: commands/trigger.c:225 commands/trigger.c:236 #, c-format msgid "\"%s\" is a table" msgstr "\"%s\" - таблиця" -#: commands/trigger.c:234 commands/trigger.c:245 +#: commands/trigger.c:227 commands/trigger.c:238 #, c-format msgid "Tables cannot have INSTEAD OF triggers." msgstr "Таблиці не можуть мати тригери INSTEAD OF." -#: commands/trigger.c:266 +#: commands/trigger.c:259 #, c-format msgid "\"%s\" is a partitioned table" msgstr "\"%s\" є секційною таблицею" -#: commands/trigger.c:268 +#: commands/trigger.c:261 #, c-format msgid "ROW triggers with transition tables are not supported on partitioned tables." msgstr "Тригери ROW з перехідними таблицями не підтримуються для секційованих таблиць." -#: commands/trigger.c:280 commands/trigger.c:287 commands/trigger.c:451 +#: commands/trigger.c:273 commands/trigger.c:280 commands/trigger.c:444 #, c-format msgid "\"%s\" is a view" msgstr "\"%s\" - подання" -#: commands/trigger.c:282 +#: commands/trigger.c:275 #, c-format msgid "Views cannot have row-level BEFORE or AFTER triggers." msgstr "Подання не можуть мати рядкові тригери BEFORE або AFTER." -#: commands/trigger.c:289 +#: commands/trigger.c:282 #, c-format msgid "Views cannot have TRUNCATE triggers." msgstr "Подання не можуть мати тригери TRUNCATE." -#: commands/trigger.c:297 commands/trigger.c:309 commands/trigger.c:444 +#: commands/trigger.c:290 commands/trigger.c:302 commands/trigger.c:437 #, c-format msgid "\"%s\" is a foreign table" msgstr "\"%s\" - зовнішня таблиця" -#: commands/trigger.c:299 +#: commands/trigger.c:292 #, c-format msgid "Foreign tables cannot have INSTEAD OF triggers." msgstr "Зовнішні таблиці не можуть мати тригери INSTEAD OF." -#: commands/trigger.c:311 +#: commands/trigger.c:304 #, c-format msgid "Foreign tables cannot have constraint triggers." msgstr "Зовнішні таблиці не можуть мати обмежувальні тригери." -#: commands/trigger.c:316 commands/trigger.c:1332 commands/trigger.c:1439 +#: commands/trigger.c:309 commands/trigger.c:1325 commands/trigger.c:1432 #, c-format msgid "relation \"%s\" cannot have triggers" msgstr "відношення \"%s\" не може мати тригери" -#: commands/trigger.c:387 +#: commands/trigger.c:380 #, c-format msgid "TRUNCATE FOR EACH ROW triggers are not supported" msgstr "Тригери TRUNCATE FOR EACH ROW не підтримуються" -#: commands/trigger.c:395 +#: commands/trigger.c:388 #, c-format msgid "INSTEAD OF triggers must be FOR EACH ROW" msgstr "Тригери INSTEAD OF повинні мати тип FOR EACH ROW" -#: commands/trigger.c:399 +#: commands/trigger.c:392 #, c-format msgid "INSTEAD OF triggers cannot have WHEN conditions" msgstr "Тригери INSTEAD OF не можуть мати умови WHEN" -#: commands/trigger.c:403 +#: commands/trigger.c:396 #, c-format msgid "INSTEAD OF triggers cannot have column lists" msgstr "Тригери INSTEAD OF не можуть мати список стовпців" -#: commands/trigger.c:432 +#: commands/trigger.c:425 #, c-format msgid "ROW variable naming in the REFERENCING clause is not supported" msgstr "Змінна іменування ROW в реченні REFERENCING не підтримується" -#: commands/trigger.c:433 +#: commands/trigger.c:426 #, c-format msgid "Use OLD TABLE or NEW TABLE for naming transition tables." msgstr "Використайте OLD TABLE або NEW TABLE для іменування перехідних таблиць." -#: commands/trigger.c:446 +#: commands/trigger.c:439 #, c-format msgid "Triggers on foreign tables cannot have transition tables." msgstr "Тригери зовнішніх таблиць не можуть використовувати перехідні таблиці." -#: commands/trigger.c:453 +#: commands/trigger.c:446 #, c-format msgid "Triggers on views cannot have transition tables." msgstr "Тригери подань не можуть використовувати перехідні таблиці." -#: commands/trigger.c:469 +#: commands/trigger.c:462 #, c-format msgid "ROW triggers with transition tables are not supported on partitions" msgstr "Тригери ROW з перехідними таблицями для секцій не підтримуються" -#: commands/trigger.c:473 +#: commands/trigger.c:466 #, c-format msgid "ROW triggers with transition tables are not supported on inheritance children" msgstr "Тригери ROW з перехідними таблицями для нащадків успадкування не підтримуються" -#: commands/trigger.c:479 +#: commands/trigger.c:472 #, c-format msgid "transition table name can only be specified for an AFTER trigger" msgstr "ім'я перехідної таблиці можна задати лише для тригеру AFTER" -#: commands/trigger.c:484 +#: commands/trigger.c:477 #, c-format msgid "TRUNCATE triggers with transition tables are not supported" msgstr "Тригери TRUNCATE з перехідними таблицями не підтримуються" -#: commands/trigger.c:501 +#: commands/trigger.c:494 #, c-format msgid "transition tables cannot be specified for triggers with more than one event" msgstr "перехідні таблиці не можна задати для тригерів, призначених для кількох подій" -#: commands/trigger.c:512 +#: commands/trigger.c:505 #, c-format msgid "transition tables cannot be specified for triggers with column lists" msgstr "перехідні таблиці не можна задати для тригерів зі списками стовпців" -#: commands/trigger.c:529 +#: commands/trigger.c:522 #, c-format msgid "NEW TABLE can only be specified for an INSERT or UPDATE trigger" msgstr "NEW TABLE можна задати лише для тригерів INSERT або UPDATE" -#: commands/trigger.c:534 +#: commands/trigger.c:527 #, c-format msgid "NEW TABLE cannot be specified multiple times" msgstr "NEW TABLE не можна задавати декілька разів" -#: commands/trigger.c:544 +#: commands/trigger.c:537 #, c-format msgid "OLD TABLE can only be specified for a DELETE or UPDATE trigger" msgstr "OLD TABLE можна задати лише для тригерів DELETE або UPDATE" -#: commands/trigger.c:549 +#: commands/trigger.c:542 #, c-format msgid "OLD TABLE cannot be specified multiple times" msgstr "OLD TABLE не можна задавати декілька разів" -#: commands/trigger.c:559 +#: commands/trigger.c:552 #, c-format msgid "OLD TABLE name and NEW TABLE name cannot be the same" msgstr "Ім'я OLD TABLE та ім'я NEW TABLE не можуть бути однаковими" -#: commands/trigger.c:623 commands/trigger.c:636 +#: commands/trigger.c:616 commands/trigger.c:629 #, c-format msgid "statement trigger's WHEN condition cannot reference column values" msgstr "в умові WHEN операторного тригера не можна посилатись на значення стовпця" -#: commands/trigger.c:628 +#: commands/trigger.c:621 #, c-format msgid "INSERT trigger's WHEN condition cannot reference OLD values" msgstr "В умові WHEN тригеру INSERT не можна посилатись на значення OLD" -#: commands/trigger.c:641 +#: commands/trigger.c:634 #, c-format msgid "DELETE trigger's WHEN condition cannot reference NEW values" msgstr "В умові WHEN тригера DELETE не можна посилатись на значення NEW" -#: commands/trigger.c:646 +#: commands/trigger.c:639 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW system columns" msgstr "В умові WHEN тригера BEFORE не можна посилатись на системні стовпці NEW" -#: commands/trigger.c:654 commands/trigger.c:662 +#: commands/trigger.c:647 commands/trigger.c:655 #, c-format msgid "BEFORE trigger's WHEN condition cannot reference NEW generated columns" msgstr "В умові WHEN тригера BEFORE не можна посилатись на згенеровані стовпці NEW" -#: commands/trigger.c:655 +#: commands/trigger.c:648 #, c-format msgid "A whole-row reference is used and the table contains generated columns." msgstr "Використовується посилання на весь рядок і таблиця містить згенеровані стовпці." -#: commands/trigger.c:770 commands/trigger.c:1614 +#: commands/trigger.c:763 commands/trigger.c:1607 #, c-format msgid "trigger \"%s\" for relation \"%s\" already exists" msgstr "тригер \"%s\" для відношення \"%s\" вже існує" -#: commands/trigger.c:783 +#: commands/trigger.c:776 #, c-format msgid "trigger \"%s\" for relation \"%s\" is an internal or a child trigger" msgstr "тригер \"%s\" для відношення \"%s\" є зовнішнім або дочірнім тригером" -#: commands/trigger.c:802 +#: commands/trigger.c:795 #, c-format msgid "trigger \"%s\" for relation \"%s\" is a constraint trigger" msgstr "тригер \"%s\" для відношення \"%s\" є зовнішнім тригером" -#: commands/trigger.c:1404 commands/trigger.c:1557 commands/trigger.c:1838 +#: commands/trigger.c:1397 commands/trigger.c:1550 commands/trigger.c:1831 #, c-format msgid "trigger \"%s\" for table \"%s\" does not exist" msgstr "тригер \"%s\" для таблиці \"%s\" не існує" -#: commands/trigger.c:1529 +#: commands/trigger.c:1522 #, c-format msgid "cannot rename trigger \"%s\" on table \"%s\"" msgstr "перейменувати тригер \"%s\" для таблиці \"%s\" не можна" -#: commands/trigger.c:1531 +#: commands/trigger.c:1524 #, c-format msgid "Rename the trigger on the partitioned table \"%s\" instead." msgstr "Замість цього перейменуйте тригер для секціонованої таблиці \"%s\"." -#: commands/trigger.c:1631 +#: commands/trigger.c:1624 #, c-format msgid "renamed trigger \"%s\" on relation \"%s\"" msgstr "перейменовано тригер \"%s\" для відношення \"%s\"" -#: commands/trigger.c:1777 +#: commands/trigger.c:1770 #, c-format msgid "permission denied: \"%s\" is a system trigger" msgstr "немає доступу: \"%s\" - системний тригер" -#: commands/trigger.c:2386 +#: commands/trigger.c:2379 #, c-format msgid "trigger function %u returned null value" msgstr "тригерна функція %u повернула значення null" -#: commands/trigger.c:2446 commands/trigger.c:2664 commands/trigger.c:2917 -#: commands/trigger.c:3270 +#: commands/trigger.c:2439 commands/trigger.c:2657 commands/trigger.c:2910 +#: commands/trigger.c:3263 #, c-format msgid "BEFORE STATEMENT trigger cannot return a value" msgstr "Тригер BEFORE STATEMENT не може повертати значення" -#: commands/trigger.c:2522 +#: commands/trigger.c:2515 #, c-format msgid "moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported" msgstr "переміщення рядка до іншої секції під час тригеру BEFORE FOR EACH ROW не підтримується" -#: commands/trigger.c:2523 +#: commands/trigger.c:2516 #, c-format msgid "Before executing trigger \"%s\", the row was to be in partition \"%s.%s\"." msgstr "Перед виконанням тригера \"%s\", рядок повинен був бути в секції \"%s.%s\"." -#: commands/trigger.c:3347 executor/nodeModifyTable.c:2369 -#: executor/nodeModifyTable.c:2452 +#: commands/trigger.c:3340 executor/nodeModifyTable.c:2373 +#: executor/nodeModifyTable.c:2456 #, c-format msgid "tuple to be updated was already modified by an operation triggered by the current command" msgstr "кортеж, який повинен бути оновленим, вже змінений в операції, яка викликана поточною командою" -#: commands/trigger.c:3348 executor/nodeModifyTable.c:1535 -#: executor/nodeModifyTable.c:1609 executor/nodeModifyTable.c:2370 -#: executor/nodeModifyTable.c:2453 executor/nodeModifyTable.c:3098 +#: commands/trigger.c:3341 executor/nodeModifyTable.c:1541 +#: executor/nodeModifyTable.c:1615 executor/nodeModifyTable.c:2374 +#: executor/nodeModifyTable.c:2457 executor/nodeModifyTable.c:3093 +#: executor/nodeModifyTable.c:3254 #, c-format msgid "Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows." msgstr "Можливо, для поширення змін в інші рядки слід використати тригер AFTER замість тригера BEFORE." -#: commands/trigger.c:3389 executor/nodeLockRows.c:228 -#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:308 -#: executor/nodeModifyTable.c:1551 executor/nodeModifyTable.c:2387 -#: executor/nodeModifyTable.c:2595 +#: commands/trigger.c:3382 executor/nodeLockRows.c:228 +#: executor/nodeLockRows.c:237 executor/nodeModifyTable.c:314 +#: executor/nodeModifyTable.c:1557 executor/nodeModifyTable.c:2391 +#: executor/nodeModifyTable.c:2599 #, c-format msgid "could not serialize access due to concurrent update" msgstr "не вдалося серіалізувати доступ через паралельне оновлення" -#: commands/trigger.c:3397 executor/nodeModifyTable.c:1641 -#: executor/nodeModifyTable.c:2470 executor/nodeModifyTable.c:2619 -#: executor/nodeModifyTable.c:2986 +#: commands/trigger.c:3390 executor/nodeModifyTable.c:1647 +#: executor/nodeModifyTable.c:2474 executor/nodeModifyTable.c:2623 +#: executor/nodeModifyTable.c:3111 #, c-format msgid "could not serialize access due to concurrent delete" msgstr "не вдалося серіалізувати доступ через паралельне видалення" -#: commands/trigger.c:4604 +#: commands/trigger.c:4601 #, c-format msgid "cannot fire deferred trigger within security-restricted operation" msgstr "не можна виконати відкладений тригер в межах операції з обмеженням по безпеці" -#: commands/trigger.c:5787 +#: commands/trigger.c:5782 #, c-format msgid "constraint \"%s\" is not deferrable" msgstr "обмеження \"%s\" не є відкладеним" -#: commands/trigger.c:5810 +#: commands/trigger.c:5805 #, c-format msgid "constraint \"%s\" does not exist" msgstr "обмеження \"%s\" не існує" @@ -11991,663 +12418,673 @@ msgstr "зіставлення для типу маркера \"%s\" не існ msgid "invalid parameter list format: \"%s\"" msgstr "неприпустимий формат списку параметрів: \"%s\"" -#: commands/typecmds.c:217 +#: commands/typecmds.c:221 #, c-format msgid "must be superuser to create a base type" msgstr "для створення базового типу потрібно бути суперкористувачем" -#: commands/typecmds.c:275 +#: commands/typecmds.c:279 #, c-format msgid "Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE." msgstr "Створіть тип в якості оболонки, потім створіть його функції вводу-виводу, а потім виконайте повну CREATE TYPE." -#: commands/typecmds.c:327 commands/typecmds.c:1450 commands/typecmds.c:4263 +#: commands/typecmds.c:331 commands/typecmds.c:1460 commands/typecmds.c:4480 #, c-format msgid "type attribute \"%s\" not recognized" msgstr "атрибут типу \"%s\" не розпізнаний" -#: commands/typecmds.c:382 +#: commands/typecmds.c:386 #, c-format msgid "invalid type category \"%s\": must be simple ASCII" msgstr "неприпустима категорія типу \"%s\": повинен бути простий ASCII" -#: commands/typecmds.c:401 +#: commands/typecmds.c:405 #, c-format msgid "array element type cannot be %s" msgstr "типом елементу масиву не може бути %s" -#: commands/typecmds.c:433 +#: commands/typecmds.c:437 #, c-format msgid "alignment \"%s\" not recognized" msgstr "тип вирівнювання \"%s\" не розпізнаний" -#: commands/typecmds.c:450 commands/typecmds.c:4137 +#: commands/typecmds.c:454 commands/typecmds.c:4354 #, c-format msgid "storage \"%s\" not recognized" msgstr "сховище \"%s\" не розпізнане" -#: commands/typecmds.c:461 +#: commands/typecmds.c:465 #, c-format msgid "type input function must be specified" msgstr "необхідно вказати функцію вводу типу" -#: commands/typecmds.c:465 +#: commands/typecmds.c:469 #, c-format msgid "type output function must be specified" msgstr "необхідно вказати функцію виводу типу" -#: commands/typecmds.c:470 +#: commands/typecmds.c:474 #, c-format msgid "type modifier output function is useless without a type modifier input function" msgstr "функція виводу модифікатора типу недоцільна без функції вводу модифікатора типу" -#: commands/typecmds.c:512 +#: commands/typecmds.c:516 #, c-format msgid "element type cannot be specified without a subscripting function" msgstr "тип елементу не можна вказати без припустимої функції підписки" -#: commands/typecmds.c:781 +#: commands/typecmds.c:785 #, c-format msgid "\"%s\" is not a valid base type for a domain" msgstr "\"%s\" - невідповідний базовий тип для домену" -#: commands/typecmds.c:879 +#: commands/typecmds.c:883 #, c-format msgid "multiple default expressions" msgstr "неодноразове визначення значення типу за замовчуванням" -#: commands/typecmds.c:942 commands/typecmds.c:951 +#: commands/typecmds.c:946 commands/typecmds.c:955 #, c-format msgid "conflicting NULL/NOT NULL constraints" msgstr "конфліктуючі обмеження NULL/NOT NULL" -#: commands/typecmds.c:967 +#: commands/typecmds.c:971 #, c-format msgid "check constraints for domains cannot be marked NO INHERIT" msgstr "перевірки обмеження для доменів не можуть позначатись як NO INHERIT" -#: commands/typecmds.c:976 commands/typecmds.c:2956 +#: commands/typecmds.c:980 commands/typecmds.c:2940 #, c-format msgid "unique constraints not possible for domains" msgstr "обмеження унікальності неможливе для доменів" -#: commands/typecmds.c:982 commands/typecmds.c:2962 +#: commands/typecmds.c:986 commands/typecmds.c:2946 #, c-format msgid "primary key constraints not possible for domains" msgstr "обмеження первинного ключа неможливі для доменів" -#: commands/typecmds.c:988 commands/typecmds.c:2968 +#: commands/typecmds.c:992 commands/typecmds.c:2952 #, c-format msgid "exclusion constraints not possible for domains" msgstr "обмеження винятків неможливі для доменів" -#: commands/typecmds.c:994 commands/typecmds.c:2974 +#: commands/typecmds.c:998 commands/typecmds.c:2958 #, c-format msgid "foreign key constraints not possible for domains" msgstr "обмеження зовнішніх ключів неможливі для доменів" -#: commands/typecmds.c:1003 commands/typecmds.c:2983 +#: commands/typecmds.c:1007 commands/typecmds.c:2967 #, c-format msgid "specifying constraint deferrability not supported for domains" msgstr "зазначення відкладення обмежень для доменів не підтримується" -#: commands/typecmds.c:1317 utils/cache/typcache.c:2567 +#: commands/typecmds.c:1327 utils/cache/typcache.c:2570 #, c-format msgid "%s is not an enum" msgstr "%s не є переліком" -#: commands/typecmds.c:1458 +#: commands/typecmds.c:1468 #, c-format msgid "type attribute \"subtype\" is required" msgstr "вимагається атрибут типу \"subtype\"" -#: commands/typecmds.c:1463 +#: commands/typecmds.c:1473 #, c-format msgid "range subtype cannot be %s" msgstr "%s не може бути підтипом діапазону" -#: commands/typecmds.c:1482 +#: commands/typecmds.c:1492 #, c-format msgid "range collation specified but subtype does not support collation" msgstr "вказано правило сортування для діапазону, але підтип не підтримує сортування" -#: commands/typecmds.c:1492 +#: commands/typecmds.c:1502 #, c-format msgid "cannot specify a canonical function without a pre-created shell type" msgstr "неможливо вказати канонічну функцію без попередньо створеного типу оболонки" -#: commands/typecmds.c:1493 +#: commands/typecmds.c:1503 #, c-format msgid "Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE." msgstr "Створіть тип в якості оболонки, потім створіть його функцію канонізації, а потім виконайте повну CREATE TYPE." -#: commands/typecmds.c:1965 +#: commands/typecmds.c:1975 #, c-format msgid "type input function %s has multiple matches" msgstr "функція введення типу %s має декілька збігів" -#: commands/typecmds.c:1983 +#: commands/typecmds.c:1993 #, c-format msgid "type input function %s must return type %s" msgstr "функція вводу типу %s повинна повертати тип %s" -#: commands/typecmds.c:1999 +#: commands/typecmds.c:2009 #, c-format msgid "type input function %s should not be volatile" msgstr "функція введення типу %s не повинна бути змінною" -#: commands/typecmds.c:2027 +#: commands/typecmds.c:2037 #, c-format msgid "type output function %s must return type %s" msgstr "функція виводу типу %s повинна повертати тип %s" -#: commands/typecmds.c:2034 +#: commands/typecmds.c:2044 #, c-format msgid "type output function %s should not be volatile" msgstr "функція виводу типу %s не повинна бути змінною" -#: commands/typecmds.c:2063 +#: commands/typecmds.c:2073 #, c-format msgid "type receive function %s has multiple matches" msgstr "функція отримання типу %s має декілька збігів" -#: commands/typecmds.c:2081 +#: commands/typecmds.c:2091 #, c-format msgid "type receive function %s must return type %s" msgstr "функція отримання типу %s повинна повертати тип %s" -#: commands/typecmds.c:2088 +#: commands/typecmds.c:2098 #, c-format msgid "type receive function %s should not be volatile" msgstr "функція отримання типу %s не повинна бути змінною" -#: commands/typecmds.c:2116 +#: commands/typecmds.c:2126 #, c-format msgid "type send function %s must return type %s" msgstr "функція відправлення типу %s повинна повертати тип %s" -#: commands/typecmds.c:2123 +#: commands/typecmds.c:2133 #, c-format msgid "type send function %s should not be volatile" msgstr "функція відправлення типу %s не повинна бути змінною" -#: commands/typecmds.c:2150 +#: commands/typecmds.c:2160 #, c-format msgid "typmod_in function %s must return type %s" msgstr "функція typmod_in %s повинна повертати тип %s" -#: commands/typecmds.c:2157 +#: commands/typecmds.c:2167 #, c-format msgid "type modifier input function %s should not be volatile" msgstr "функція вводу модифікатора типу %s не повинна бути змінною" -#: commands/typecmds.c:2184 +#: commands/typecmds.c:2194 #, c-format msgid "typmod_out function %s must return type %s" msgstr "функція typmod_out %s повинна повертати тип %s" -#: commands/typecmds.c:2191 +#: commands/typecmds.c:2201 #, c-format msgid "type modifier output function %s should not be volatile" msgstr "функція виводу модифікатора типу %s не повинна бути змінною" -#: commands/typecmds.c:2218 +#: commands/typecmds.c:2228 #, c-format msgid "type analyze function %s must return type %s" msgstr "функція аналізу типу %s повинна повертати тип %s" -#: commands/typecmds.c:2247 +#: commands/typecmds.c:2257 #, c-format msgid "type subscripting function %s must return type %s" msgstr "функція підписки типу %s повинна повертати тип %s" -#: commands/typecmds.c:2257 +#: commands/typecmds.c:2267 #, c-format msgid "user-defined types cannot use subscripting function %s" msgstr "типи визначені користувачем не можуть використовувати функцію підписки %s" -#: commands/typecmds.c:2303 +#: commands/typecmds.c:2313 #, c-format msgid "You must specify an operator class for the range type or define a default operator class for the subtype." msgstr "Ви повинні вказати клас операторів для типу діапазону або визначити клас операторів за замовчуванням для цього підтипу." -#: commands/typecmds.c:2334 +#: commands/typecmds.c:2344 #, c-format msgid "range canonical function %s must return range type" msgstr "функція канонічного діапазону %s повинна вертати тип діапазону" -#: commands/typecmds.c:2340 +#: commands/typecmds.c:2350 #, c-format msgid "range canonical function %s must be immutable" msgstr "функція канонічного діапазону %s повинна бути незмінною" -#: commands/typecmds.c:2376 +#: commands/typecmds.c:2386 #, c-format msgid "range subtype diff function %s must return type %s" msgstr "функція розбіжностей для підтипу діапазону %s повинна повертати тип %s" -#: commands/typecmds.c:2383 +#: commands/typecmds.c:2393 #, c-format msgid "range subtype diff function %s must be immutable" msgstr "функція розбіжностей для підтипу діапазону %s повинна бути незмінною" -#: commands/typecmds.c:2410 +#: commands/typecmds.c:2420 #, c-format msgid "pg_type array OID value not set when in binary upgrade mode" msgstr "значення OID масиву pg_type не встановлено в режимі двійкового оновлення" -#: commands/typecmds.c:2443 +#: commands/typecmds.c:2453 #, c-format msgid "pg_type multirange OID value not set when in binary upgrade mode" msgstr "значення OID в pg_type не задано під час режиму двійкового оновлення" -#: commands/typecmds.c:2476 +#: commands/typecmds.c:2486 #, c-format msgid "pg_type multirange array OID value not set when in binary upgrade mode" msgstr "значення OID масиву в pg_type не задано під час режиму двійкового оновлення" -#: commands/typecmds.c:2772 -#, c-format -msgid "column \"%s\" of table \"%s\" contains null values" -msgstr "стовпець \"%s\" таблиці \"%s\" містить значення NULL" - -#: commands/typecmds.c:2885 commands/typecmds.c:3086 +#: commands/typecmds.c:2868 commands/typecmds.c:3093 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist" msgstr "обмеження \"%s\" для домену \"%s\" не існує" -#: commands/typecmds.c:2889 +#: commands/typecmds.c:2872 #, c-format msgid "constraint \"%s\" of domain \"%s\" does not exist, skipping" msgstr "обмеження \"%s\" для домену \"%s\" не існує, пропускається" -#: commands/typecmds.c:3093 +#: commands/typecmds.c:3100 #, c-format msgid "constraint \"%s\" of domain \"%s\" is not a check constraint" msgstr "обмеження \"%s\" для домену \"%s\" не є перевірочним обмеженням" -#: commands/typecmds.c:3194 +#: commands/typecmds.c:3180 +#, c-format +msgid "column \"%s\" of table \"%s\" contains null values" +msgstr "стовпець \"%s\" таблиці \"%s\" містить значення NULL" + +#: commands/typecmds.c:3269 #, c-format msgid "column \"%s\" of table \"%s\" contains values that violate the new constraint" msgstr "стовпець \"%s\" таблиці \"%s\" містить значення, які порушують нове обмеження" -#: commands/typecmds.c:3423 commands/typecmds.c:3622 commands/typecmds.c:3705 -#: commands/typecmds.c:3893 +#: commands/typecmds.c:3498 commands/typecmds.c:3772 commands/typecmds.c:3857 +#: commands/typecmds.c:4073 #, c-format msgid "%s is not a domain" msgstr "%s - не домен" -#: commands/typecmds.c:3455 +#: commands/typecmds.c:3532 commands/typecmds.c:3686 #, c-format msgid "constraint \"%s\" for domain \"%s\" already exists" msgstr "обмеження \"%s\" для домену \"%s\" вже існує" -#: commands/typecmds.c:3506 +#: commands/typecmds.c:3583 #, c-format msgid "cannot use table references in domain check constraint" msgstr "у перевірочному обмеженні для домену не можна посилатись на таблиці" -#: commands/typecmds.c:3634 commands/typecmds.c:3717 commands/typecmds.c:4010 +#: commands/typecmds.c:3784 commands/typecmds.c:3869 commands/typecmds.c:4223 #, c-format msgid "%s is a table's row type" msgstr "%s - тип рядків таблиці" -#: commands/typecmds.c:3644 commands/typecmds.c:3727 commands/typecmds.c:3925 +#: commands/typecmds.c:3794 commands/typecmds.c:3879 commands/typecmds.c:4121 #, c-format msgid "cannot alter array type %s" msgstr "змінити тип масиву \"%s\" не можна" -#: commands/typecmds.c:3646 commands/typecmds.c:3729 commands/typecmds.c:3927 +#: commands/typecmds.c:3796 commands/typecmds.c:3881 commands/typecmds.c:4123 #, c-format msgid "You can alter type %s, which will alter the array type as well." msgstr "Ви можете змінити тип %s, який спричинить зміну типу масиву." -#: commands/typecmds.c:3995 +#: commands/typecmds.c:3892 +#, c-format +msgid "cannot alter multirange type %s" +msgstr "не можна змінювати багатодіапазонний тип %s" + +#: commands/typecmds.c:3895 +#, c-format +msgid "You can alter type %s, which will alter the multirange type as well." +msgstr "Ви можете змінити тип %s, що також змінить тип мультидіапазону." + +#: commands/typecmds.c:4202 #, c-format msgid "type \"%s\" already exists in schema \"%s\"" msgstr "тип \"%s\" вже існує в схемі \"%s\"" -#: commands/typecmds.c:4165 +#: commands/typecmds.c:4382 #, c-format msgid "cannot change type's storage to PLAIN" msgstr "неможливо змінити сховище типу на PLAIN" -#: commands/typecmds.c:4258 +#: commands/typecmds.c:4475 #, c-format msgid "type attribute \"%s\" cannot be changed" msgstr "атрибут типу \"%s\" неможливо змінити" -#: commands/typecmds.c:4276 +#: commands/typecmds.c:4493 #, c-format msgid "must be superuser to alter a type" msgstr "для зміни типу потрібно бути суперкористувачем" -#: commands/typecmds.c:4297 commands/typecmds.c:4306 +#: commands/typecmds.c:4514 commands/typecmds.c:4523 #, c-format msgid "%s is not a base type" msgstr "%s - не є базовим типом" -#: commands/user.c:201 +#: commands/user.c:200 #, c-format msgid "SYSID can no longer be specified" msgstr "SYSID вже не потрібно вказувати" -#: commands/user.c:319 commands/user.c:325 commands/user.c:331 -#: commands/user.c:337 commands/user.c:343 +#: commands/user.c:318 commands/user.c:324 commands/user.c:330 +#: commands/user.c:336 commands/user.c:342 #, c-format msgid "permission denied to create role" msgstr "немає прав для створення ролі" -#: commands/user.c:320 +#: commands/user.c:319 #, c-format msgid "Only roles with the %s attribute may create roles." msgstr "Створювати ролі можуть лише ролі з атрибутом %s." -#: commands/user.c:326 commands/user.c:332 commands/user.c:338 -#: commands/user.c:344 +#: commands/user.c:325 commands/user.c:331 commands/user.c:337 +#: commands/user.c:343 #, c-format msgid "Only roles with the %s attribute may create roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть створювати ролі з атрибутом %s." -#: commands/user.c:355 commands/user.c:1387 commands/user.c:1394 -#: utils/adt/acl.c:5401 utils/adt/acl.c:5407 gram.y:16726 gram.y:16772 +#: commands/user.c:354 commands/user.c:1386 commands/user.c:1393 +#: utils/adt/acl.c:5574 utils/adt/acl.c:5580 gram.y:17310 gram.y:17356 #, c-format msgid "role name \"%s\" is reserved" msgstr "ім'я ролі \"%s\" зарезервовано" -#: commands/user.c:357 commands/user.c:1389 commands/user.c:1396 +#: commands/user.c:356 commands/user.c:1388 commands/user.c:1395 #, c-format msgid "Role names starting with \"pg_\" are reserved." msgstr "Імена ролей, які починаються на \"pg_\", зарезервовані." -#: commands/user.c:378 commands/user.c:1411 +#: commands/user.c:377 commands/user.c:1410 #, c-format msgid "role \"%s\" already exists" msgstr "роль \"%s\" вже існує" -#: commands/user.c:440 commands/user.c:925 +#: commands/user.c:439 commands/user.c:924 #, c-format msgid "empty string is not a valid password, clearing password" msgstr "пустий рядок є неприпустимим паролем, пароль скидається" -#: commands/user.c:469 +#: commands/user.c:468 #, c-format msgid "pg_authid OID value not set when in binary upgrade mode" msgstr "значення OID в pg_authid не встановлено в режимі двійкового оновлення" -#: commands/user.c:653 commands/user.c:1011 +#: commands/user.c:652 commands/user.c:1010 msgid "Cannot alter reserved roles." msgstr "Не можна змінити зарезервовані ролі." -#: commands/user.c:760 commands/user.c:766 commands/user.c:782 -#: commands/user.c:790 commands/user.c:804 commands/user.c:810 -#: commands/user.c:816 commands/user.c:825 commands/user.c:870 -#: commands/user.c:1033 commands/user.c:1044 +#: commands/user.c:759 commands/user.c:765 commands/user.c:781 +#: commands/user.c:789 commands/user.c:803 commands/user.c:809 +#: commands/user.c:815 commands/user.c:824 commands/user.c:869 +#: commands/user.c:1032 commands/user.c:1043 #, c-format msgid "permission denied to alter role" msgstr "немає прав на зміну ролі" -#: commands/user.c:761 commands/user.c:1034 +#: commands/user.c:760 commands/user.c:1033 #, c-format msgid "Only roles with the %s attribute may alter roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть змінювати ролі з атрибутом %s." -#: commands/user.c:767 commands/user.c:805 commands/user.c:811 -#: commands/user.c:817 +#: commands/user.c:766 commands/user.c:804 commands/user.c:810 +#: commands/user.c:816 #, c-format msgid "Only roles with the %s attribute may change the %s attribute." msgstr "Змінити атрибут %s може тільки роль з атрибутом %s." -#: commands/user.c:783 commands/user.c:1045 +#: commands/user.c:782 commands/user.c:1044 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may alter this role." msgstr "Тільки ролі з атрибутом %s та опцією %s на роль \"%s\" можуть змінити цю роль." -#: commands/user.c:791 +#: commands/user.c:790 #, c-format msgid "To change another role's password, the current user must have the %s attribute and the %s option on the role." msgstr "Щоб змінити пароль іншої ролі, поточний користувач повинен мати атрибут %s та параметр %s в ролі." -#: commands/user.c:826 +#: commands/user.c:825 #, c-format msgid "Only roles with the %s option on role \"%s\" may add members." msgstr "Тільки ролі з опцією %s на роль \"%s\" можуть додавати учасників." -#: commands/user.c:871 +#: commands/user.c:870 #, c-format -msgid "The bootstrap user must have the %s attribute." -msgstr "Початковий користувач повинен мати атрибут %s." +msgid "The bootstrap superuser must have the %s attribute." +msgstr "Суперкористувач завантажувача повинен мати атрибут %s." -#: commands/user.c:1076 +#: commands/user.c:1075 #, c-format msgid "permission denied to alter setting" msgstr "немає прав на зміну налаштувань" -#: commands/user.c:1077 +#: commands/user.c:1076 #, c-format msgid "Only roles with the %s attribute may alter settings globally." msgstr "Тільки ролі з атрибутом %s можуть змінювати налаштування глобально." -#: commands/user.c:1101 commands/user.c:1172 commands/user.c:1178 +#: commands/user.c:1100 commands/user.c:1171 commands/user.c:1177 #, c-format msgid "permission denied to drop role" msgstr "немає прав для видалення ролі" -#: commands/user.c:1102 +#: commands/user.c:1101 #, c-format msgid "Only roles with the %s attribute and the %s option on the target roles may drop roles." msgstr "Тільки ролі з атрибутом %s та опцією %s на цільових ролях можуть видаляти ролі." -#: commands/user.c:1126 +#: commands/user.c:1125 #, c-format msgid "cannot use special role specifier in DROP ROLE" msgstr "використати спеціальну роль у DROP ROLE не можна" -#: commands/user.c:1136 commands/user.c:1358 commands/variable.c:836 -#: commands/variable.c:839 commands/variable.c:923 commands/variable.c:926 -#: utils/adt/acl.c:356 utils/adt/acl.c:376 utils/adt/acl.c:5256 -#: utils/adt/acl.c:5304 utils/adt/acl.c:5332 utils/adt/acl.c:5351 -#: utils/adt/regproc.c:1551 utils/init/miscinit.c:756 +#: commands/user.c:1135 commands/user.c:1357 commands/variable.c:838 +#: commands/variable.c:841 commands/variable.c:947 commands/variable.c:950 +#: utils/adt/acl.c:365 utils/adt/acl.c:385 utils/adt/acl.c:5429 +#: utils/adt/acl.c:5477 utils/adt/acl.c:5505 utils/adt/acl.c:5524 +#: utils/adt/regproc.c:1571 utils/init/miscinit.c:762 #, c-format msgid "role \"%s\" does not exist" msgstr "роль \"%s\" не існує" -#: commands/user.c:1141 +#: commands/user.c:1140 #, c-format msgid "role \"%s\" does not exist, skipping" msgstr "роль \"%s\" не існує, пропускається" -#: commands/user.c:1154 commands/user.c:1158 +#: commands/user.c:1153 commands/user.c:1157 #, c-format msgid "current user cannot be dropped" msgstr "користувач не можна видалити сам себе" -#: commands/user.c:1162 +#: commands/user.c:1161 #, c-format msgid "session user cannot be dropped" msgstr "користувача поточного сеансу не можна видалити" -#: commands/user.c:1173 +#: commands/user.c:1172 #, c-format msgid "Only roles with the %s attribute may drop roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть видаляти ролі з атрибутом %s." -#: commands/user.c:1179 +#: commands/user.c:1178 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may drop this role." msgstr "Тільки ролі з атрибутом %s та опцією %s на роль \"%s\" можуть видалити цю роль." -#: commands/user.c:1300 +#: commands/user.c:1299 #, c-format msgid "role \"%s\" cannot be dropped because some objects depend on it" msgstr "роль \"%s\" не можна видалити, тому що деякі об'єкти залежать від неї" -#: commands/user.c:1374 +#: commands/user.c:1373 #, c-format msgid "session user cannot be renamed" msgstr "користувача поточного сеансу не можна перейменувати" -#: commands/user.c:1378 +#: commands/user.c:1377 #, c-format msgid "current user cannot be renamed" msgstr "користувач не може перейменувати сам себе" -#: commands/user.c:1422 commands/user.c:1432 +#: commands/user.c:1421 commands/user.c:1431 #, c-format msgid "permission denied to rename role" msgstr "немає прав на перейменування ролі" -#: commands/user.c:1423 +#: commands/user.c:1422 #, c-format msgid "Only roles with the %s attribute may rename roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть перейменовувати ролі з атрибутом %s." -#: commands/user.c:1433 +#: commands/user.c:1432 #, c-format msgid "Only roles with the %s attribute and the %s option on role \"%s\" may rename this role." msgstr "Тільки ролі з атрибутом %s та опцією %s на роль \"%s\" можуть перейменувати цю роль." -#: commands/user.c:1455 +#: commands/user.c:1454 #, c-format msgid "MD5 password cleared because of role rename" msgstr "У результаті перейменування ролі сума MD5 паролю очищена" -#: commands/user.c:1519 gram.y:1260 +#: commands/user.c:1518 gram.y:1294 #, c-format msgid "unrecognized role option \"%s\"" msgstr "нерозпізнаний параметр ролі \"%s\"" -#: commands/user.c:1524 +#: commands/user.c:1523 #, c-format msgid "unrecognized value for role option \"%s\": \"%s\"" msgstr "нерозпізнане значення параметру ролі \"%s\": \"%s\"" -#: commands/user.c:1557 +#: commands/user.c:1556 #, c-format msgid "column names cannot be included in GRANT/REVOKE ROLE" msgstr "в GRANT/REVOKE ROLE не можна включати назви стовпців" -#: commands/user.c:1597 +#: commands/user.c:1596 #, c-format msgid "permission denied to drop objects" msgstr "немає прав на видалення об'єктів" -#: commands/user.c:1598 +#: commands/user.c:1597 #, c-format msgid "Only roles with privileges of role \"%s\" may drop objects owned by it." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть видаляти об'єкти, що належать йому." -#: commands/user.c:1626 commands/user.c:1637 +#: commands/user.c:1625 commands/user.c:1636 #, c-format msgid "permission denied to reassign objects" msgstr "немає прав на повторне призначення об'єктів" -#: commands/user.c:1627 +#: commands/user.c:1626 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects owned by it." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть переназначати об'єкти, що належать йому." -#: commands/user.c:1638 +#: commands/user.c:1637 #, c-format msgid "Only roles with privileges of role \"%s\" may reassign objects to it." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть перепризначати об'єкти." -#: commands/user.c:1734 +#: commands/user.c:1733 #, c-format msgid "role \"%s\" cannot be a member of any role" msgstr "роль \"%s\" не може бути членом якої-небудь ролі" -#: commands/user.c:1747 +#: commands/user.c:1746 #, c-format msgid "role \"%s\" is a member of role \"%s\"" msgstr "роль \"%s\" - учасник ролі \"%s\"" -#: commands/user.c:1787 commands/user.c:1813 +#: commands/user.c:1786 commands/user.c:1812 #, c-format msgid "%s option cannot be granted back to your own grantor" msgstr "параметр %s не можна призначити тому, хто призначив їх вам" -#: commands/user.c:1890 +#: commands/user.c:1889 #, c-format msgid "role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"" msgstr "роль \"%s\" вже отримала членство в ролі \"%s\" від ролі \"%s\"" -#: commands/user.c:2025 +#: commands/user.c:2024 #, c-format msgid "role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"" msgstr "роль \"%s\" не отримала членство в ролі \"%s\" від ролі \"%s\"" -#: commands/user.c:2125 +#: commands/user.c:2124 #, c-format msgid "role \"%s\" cannot have explicit members" msgstr "роль \"%s\" не може мати явних членів" -#: commands/user.c:2136 commands/user.c:2159 +#: commands/user.c:2135 commands/user.c:2158 #, c-format msgid "permission denied to grant role \"%s\"" msgstr "немає дозволу для надання ролі \"%s\"" -#: commands/user.c:2138 +#: commands/user.c:2137 #, c-format msgid "Only roles with the %s attribute may grant roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть надавати членство ролі з атрибутом %s." -#: commands/user.c:2143 commands/user.c:2166 +#: commands/user.c:2142 commands/user.c:2165 #, c-format msgid "permission denied to revoke role \"%s\"" msgstr "немає дозволу для відкликання ролі \"%s\"" -#: commands/user.c:2145 +#: commands/user.c:2144 #, c-format msgid "Only roles with the %s attribute may revoke roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть відкликати членство ролі з атрибутом %s." -#: commands/user.c:2161 +#: commands/user.c:2160 #, c-format msgid "Only roles with the %s option on role \"%s\" may grant this role." msgstr "Тільки ролі з опцією %s на роль \"%s\" можуть надавати членство до цієї ролі." -#: commands/user.c:2168 +#: commands/user.c:2167 #, c-format msgid "Only roles with the %s option on role \"%s\" may revoke this role." msgstr "Тільки ролі з опцією %s на роль \"%s\" можуть відкликати членство в цій ролі." -#: commands/user.c:2248 commands/user.c:2257 +#: commands/user.c:2247 commands/user.c:2256 #, c-format msgid "permission denied to grant privileges as role \"%s\"" msgstr "немає дозволу для надання привілеїв ролі \"%s\"" -#: commands/user.c:2250 +#: commands/user.c:2249 #, c-format msgid "Only roles with privileges of role \"%s\" may grant privileges as this role." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть надавати привілеї цієї ролі." -#: commands/user.c:2259 +#: commands/user.c:2258 #, c-format msgid "The grantor must have the %s option on role \"%s\"." msgstr "Власник прав повинен мати опцію %s для ролі \"%s\"." -#: commands/user.c:2267 +#: commands/user.c:2266 #, c-format msgid "permission denied to revoke privileges granted by role \"%s\"" msgstr "відмовлено у дозволі на відкликання привілеїв, наданих роллю \"%s\"" -#: commands/user.c:2269 +#: commands/user.c:2268 #, c-format msgid "Only roles with privileges of role \"%s\" may revoke privileges granted by this role." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть відкликати привілеї, надані цією роллю." -#: commands/user.c:2492 utils/adt/acl.c:1309 +#: commands/user.c:2491 utils/adt/acl.c:1324 #, c-format msgid "dependent privileges exist" msgstr "залежні права існують" -#: commands/user.c:2493 utils/adt/acl.c:1310 +#: commands/user.c:2492 utils/adt/acl.c:1325 #, c-format msgid "Use CASCADE to revoke them too." msgstr "Використайте CASCADE, щоб відкликати їх." -#: commands/vacuum.c:137 +#: commands/vacuum.c:134 #, c-format msgid "\"vacuum_buffer_usage_limit\" must be 0 or between %d kB and %d kB" msgstr "\"vacuum_buffer_usage_limit\" має бути 0 або між %d та %d kB" @@ -12717,92 +13154,88 @@ msgstr "ONLY_DATABASE_STATS не можна вказувати з іншими msgid "%s cannot be executed from VACUUM or ANALYZE" msgstr "%s не можна виконати під час VACUUM або ANALYZE" -#: commands/vacuum.c:733 +#: commands/vacuum.c:730 #, c-format msgid "permission denied to vacuum \"%s\", skipping it" msgstr "немає дозволу для очистки\"%s\", пропускаємо його" -#: commands/vacuum.c:746 +#: commands/vacuum.c:743 #, c-format msgid "permission denied to analyze \"%s\", skipping it" msgstr "відмовлено в дозволі на аналіз \"%s\", пропуск" -#: commands/vacuum.c:824 commands/vacuum.c:921 +#: commands/vacuum.c:821 commands/vacuum.c:918 #, c-format msgid "skipping vacuum of \"%s\" --- lock not available" msgstr "очистка \"%s\" пропускається --- блокування недоступне" -#: commands/vacuum.c:829 +#: commands/vacuum.c:826 #, c-format msgid "skipping vacuum of \"%s\" --- relation no longer exists" msgstr "очистка \"%s\" пропускається --- це відношення більше не існує" -#: commands/vacuum.c:845 commands/vacuum.c:926 +#: commands/vacuum.c:842 commands/vacuum.c:923 #, c-format msgid "skipping analyze of \"%s\" --- lock not available" msgstr "пропуск аналізу об'єкта \"%s\" --- блокування недоступне" -#: commands/vacuum.c:850 +#: commands/vacuum.c:847 #, c-format msgid "skipping analyze of \"%s\" --- relation no longer exists" msgstr "пропуск аналізу об'єкта\"%s\" --- відношення більше не існує" -#: commands/vacuum.c:1161 +#: commands/vacuum.c:1139 #, c-format msgid "cutoff for removing and freezing tuples is far in the past" msgstr "відсікання для видалення та заморожування кортежів залишилося далеко в минулому" -#: commands/vacuum.c:1162 commands/vacuum.c:1167 +#: commands/vacuum.c:1140 commands/vacuum.c:1145 #, c-format -msgid "" -"Close open transactions soon to avoid wraparound problems.\n" +msgid "Close open transactions soon to avoid wraparound problems.\n" "You might also need to commit or roll back old prepared transactions, or drop stale replication slots." -msgstr "" -"Завершіть відкриті транзакції якнайшвидше, щоб уникнути проблеми зациклення.\n" +msgstr "Завершіть відкриті транзакції якнайшвидше, щоб уникнути проблеми зациклення.\n" "Можливо, вам також доведеться затвердити або відкотити старі підготовленні транзакції, або видалити застарілі слоти реплікації." -#: commands/vacuum.c:1166 +#: commands/vacuum.c:1144 #, c-format msgid "cutoff for freezing multixacts is far in the past" msgstr "відсікання для заморожування мультитранзакцій залишилося далеко в минулому" -#: commands/vacuum.c:1908 +#: commands/vacuum.c:1890 #, c-format msgid "some databases have not been vacuumed in over 2 billion transactions" msgstr "деякі бази даних не очищалися протягом більш ніж 2 мільярдів транзакцій" -#: commands/vacuum.c:1909 +#: commands/vacuum.c:1891 #, c-format msgid "You might have already suffered transaction-wraparound data loss." msgstr "Можливо, ви вже втратили дані в результаті зациклення транзакцій." -#: commands/vacuum.c:2078 +#: commands/vacuum.c:2070 #, c-format msgid "skipping \"%s\" --- cannot vacuum non-tables or special system tables" msgstr "пропускається \"%s\" --- очищати не таблиці або спеціальні системні таблиці не можна" -#: commands/vacuum.c:2503 +#: commands/vacuum.c:2502 #, c-format -msgid "scanned index \"%s\" to remove %d row versions" -msgstr "просканований індекс \"%s\", видалено версій рядків %d" +msgid "scanned index \"%s\" to remove %lld row versions" +msgstr "" -#: commands/vacuum.c:2522 +#: commands/vacuum.c:2521 #, c-format msgid "index \"%s\" now contains %.0f row versions in %u pages" msgstr "індекс \"%s\" наразі містить %.0f версій рядків у %u сторінках" -#: commands/vacuum.c:2526 +#: commands/vacuum.c:2525 #, c-format -msgid "" -"%.0f index row versions were removed.\n" +msgid "%.0f index row versions were removed.\n" "%u index pages were newly deleted.\n" "%u index pages are currently deleted, of which %u are currently reusable." -msgstr "" -"%.0f версій індексних рядків було видалено.\n" +msgstr "%.0f версій індексних рядків було видалено.\n" "%u індексних сторінок щойно видалено.\n" "%u індексних сторінок наразі видалено, з яких %u наразі можна використовувати повторно." -#: commands/vacuumparallel.c:677 +#: commands/vacuumparallel.c:708 #, c-format msgid "launched %d parallel vacuum worker for index vacuuming (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index vacuuming (planned: %d)" @@ -12811,7 +13244,7 @@ msgstr[1] "запущено %d паралельних виконавців оч msgstr[2] "запущено %d паралельних виконавців очистки для очищення індексу (заплановано: %d)" msgstr[3] "запущено %d паралельних виконавців очистки для очищення індексу (заплановано: %d)" -#: commands/vacuumparallel.c:683 +#: commands/vacuumparallel.c:714 #, c-format msgid "launched %d parallel vacuum worker for index cleanup (planned: %d)" msgid_plural "launched %d parallel vacuum workers for index cleanup (planned: %d)" @@ -12875,7 +13308,7 @@ msgstr "Команда SET TRANSACTION ISOLATION LEVEL повинна викли msgid "SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction" msgstr "Команда SET TRANSACTION ISOLATION LEVEL не повинна викликатияь в підтранзакції" -#: commands/variable.c:606 storage/lmgr/predicate.c:1629 +#: commands/variable.c:606 storage/lmgr/predicate.c:1680 #, c-format msgid "cannot use serializable mode in a hot standby" msgstr "використовувати серіалізований режим в hot standby не можна" @@ -12907,90 +13340,100 @@ msgstr "Змінити клієнтське кодування зараз нем #: commands/variable.c:781 #, c-format -msgid "cannot change client_encoding during a parallel operation" -msgstr "змінити клієнтське кодування під час паралельної операції неможливо" +msgid "cannot change \"client_encoding\" during a parallel operation" +msgstr "" + +#: commands/variable.c:863 +#, c-format +msgid "permission will be denied to set session authorization \"%s\"" +msgstr "буде відмовлено у встановленні авторизації сеансу \"%s\"" + +#: commands/variable.c:868 +#, c-format +msgid "permission denied to set session authorization \"%s\"" +msgstr "відмовлено у встановленні авторизації сеансу \"%s\"" -#: commands/variable.c:948 +#: commands/variable.c:972 #, c-format msgid "permission will be denied to set role \"%s\"" msgstr "немає прав для встановлення ролі \"%s\"" -#: commands/variable.c:953 +#: commands/variable.c:977 #, c-format msgid "permission denied to set role \"%s\"" msgstr "немає прав для встановлення ролі \"%s\"" -#: commands/variable.c:1153 +#: commands/variable.c:1177 #, c-format msgid "Bonjour is not supported by this build" msgstr "Bonjour не підтримується даною збіркою" -#: commands/variable.c:1181 +#: commands/variable.c:1205 #, c-format -msgid "effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise()." -msgstr "значення effective_io_concurrency повинне дорівнювати 0 (нулю) на платформах, де відсутній posix_fadvise()." +msgid "\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." +msgstr "" -#: commands/variable.c:1194 +#: commands/variable.c:1218 #, c-format -msgid "maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise()." -msgstr "maintenance_io_concurrency повинне бути встановлене на 0, на платформах які не мають posix_fadvise()." +msgid "\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()." +msgstr "" -#: commands/variable.c:1207 +#: commands/variable.c:1231 #, c-format msgid "SSL is not supported by this build" msgstr "SSL не підтримується даною збіркою" -#: commands/view.c:84 +#: commands/view.c:79 #, c-format msgid "could not determine which collation to use for view column \"%s\"" msgstr "не вдалося визначити, яке правило сортування використати для стовпця подання \"%s\"" -#: commands/view.c:279 commands/view.c:290 +#: commands/view.c:274 commands/view.c:285 #, c-format msgid "cannot drop columns from view" msgstr "видалити стовпці з подання неможливо" -#: commands/view.c:295 +#: commands/view.c:290 #, c-format msgid "cannot change name of view column \"%s\" to \"%s\"" msgstr "змінити ім'я стовпця \"%s\" на \"%s\" в поданні неможливо" -#: commands/view.c:298 +#: commands/view.c:293 #, c-format msgid "Use ALTER VIEW ... RENAME COLUMN ... to change name of view column instead." msgstr "Щоб змінити назву стовпця подання, замість цього використайте ALTER VIEW ... RENAME COLUMN." -#: commands/view.c:309 +#: commands/view.c:304 #, c-format msgid "cannot change data type of view column \"%s\" from %s to %s" msgstr "змінити тип стовпця подання \"%s\" з %s на %s неможливо" -#: commands/view.c:323 +#: commands/view.c:318 #, c-format msgid "cannot change collation of view column \"%s\" from \"%s\" to \"%s\"" msgstr "змінити параметри сортування стовпця подання \"%s\" з \"%s\" на \"%s\" не можна" -#: commands/view.c:392 +#: commands/view.c:387 #, c-format msgid "views must not contain SELECT INTO" msgstr "подання не повинні містити SELECT INTO" -#: commands/view.c:404 +#: commands/view.c:399 #, c-format msgid "views must not contain data-modifying statements in WITH" msgstr "подання не повинні містити інструкції, які змінюють дані в WITH" -#: commands/view.c:474 +#: commands/view.c:469 #, c-format msgid "CREATE VIEW specifies more column names than columns" msgstr "У CREATE VIEW вказано більше імен стовпців, ніж самих стовпців" -#: commands/view.c:482 +#: commands/view.c:477 #, c-format msgid "views cannot be unlogged because they do not have storage" msgstr "подання не можуть бути нежурнальованими, так як вони не мають сховища" -#: commands/view.c:496 +#: commands/view.c:491 #, c-format msgid "view \"%s\" will be a temporary view" msgstr "подання \"%s\" буде тичасовим поданням" @@ -13026,58 +13469,58 @@ msgstr "курсор \"%s\" не розташовується у рядку" msgid "cursor \"%s\" is not a simply updatable scan of table \"%s\"" msgstr "курсор \"%s\" - не просте оновлюване сканування таблиці \"%s\"" -#: executor/execCurrent.c:280 executor/execExprInterp.c:2498 +#: executor/execCurrent.c:280 executor/execExprInterp.c:2543 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "тип параметру %d (%s) не відповідає тому, з котрим тривала підготовка плану (%s)" -#: executor/execCurrent.c:292 executor/execExprInterp.c:2510 +#: executor/execCurrent.c:292 executor/execExprInterp.c:2555 #, c-format msgid "no value found for parameter %d" msgstr "не знайдено значення для параметру %d" -#: executor/execExpr.c:637 executor/execExpr.c:644 executor/execExpr.c:650 -#: executor/execExprInterp.c:4234 executor/execExprInterp.c:4251 -#: executor/execExprInterp.c:4350 executor/nodeModifyTable.c:197 -#: executor/nodeModifyTable.c:208 executor/nodeModifyTable.c:225 -#: executor/nodeModifyTable.c:233 +#: executor/execExpr.c:642 executor/execExpr.c:649 executor/execExpr.c:655 +#: executor/execExprInterp.c:4840 executor/execExprInterp.c:4857 +#: executor/execExprInterp.c:4956 executor/nodeModifyTable.c:203 +#: executor/nodeModifyTable.c:214 executor/nodeModifyTable.c:231 +#: executor/nodeModifyTable.c:239 #, c-format msgid "table row type and query-specified row type do not match" msgstr "тип рядка таблиці відрізняється від типу рядка-результату запиту" -#: executor/execExpr.c:638 executor/nodeModifyTable.c:198 +#: executor/execExpr.c:643 executor/nodeModifyTable.c:204 #, c-format msgid "Query has too many columns." msgstr "Запит повертає дуже багато стовпців." -#: executor/execExpr.c:645 executor/nodeModifyTable.c:226 +#: executor/execExpr.c:650 executor/nodeModifyTable.c:232 #, c-format msgid "Query provides a value for a dropped column at ordinal position %d." msgstr "Запит надає значення для видаленого стовпця з порядковим номером %d." -#: executor/execExpr.c:651 executor/execExprInterp.c:4252 -#: executor/nodeModifyTable.c:209 +#: executor/execExpr.c:656 executor/execExprInterp.c:4858 +#: executor/nodeModifyTable.c:215 #, c-format msgid "Table has type %s at ordinal position %d, but query expects %s." msgstr "Таблиця має тип %s у порядковому розташуванні %d, але запит очікує %s." -#: executor/execExpr.c:1099 parser/parse_agg.c:838 +#: executor/execExpr.c:1104 parser/parse_agg.c:838 #, c-format msgid "window function calls cannot be nested" msgstr "виклики віконних функцій не можуть бути вкладеними" -#: executor/execExpr.c:1618 +#: executor/execExpr.c:1641 #, c-format msgid "target type is not an array" msgstr "цільовий тип не є масивом" -#: executor/execExpr.c:1958 +#: executor/execExpr.c:1981 #, c-format msgid "ROW() column has type %s instead of type %s" msgstr "Стовпець ROW() має тип %s замість %s" -#: executor/execExpr.c:2574 executor/execSRF.c:719 parser/parse_func.c:138 -#: parser/parse_func.c:655 parser/parse_func.c:1032 +#: executor/execExpr.c:2643 executor/execSRF.c:718 parser/parse_func.c:138 +#: parser/parse_func.c:655 parser/parse_func.c:1033 #, c-format msgid "cannot pass more than %d argument to a function" msgid_plural "cannot pass more than %d arguments to a function" @@ -13086,104 +13529,121 @@ msgstr[1] "функції не можна передати більше ніж % msgstr[2] "функції не можна передати більше ніж %d аргументів" msgstr[3] "функції не можна передати більше ніж %d аргументів" -#: executor/execExpr.c:2601 executor/execSRF.c:739 executor/functions.c:1066 -#: utils/adt/jsonfuncs.c:3780 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 +#: executor/execExpr.c:2670 executor/execSRF.c:738 executor/functions.c:1068 +#: utils/adt/jsonfuncs.c:4054 utils/fmgr/funcapi.c:89 utils/fmgr/funcapi.c:143 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "функція \"set-valued\" викликана в контексті, де йому немає місця" -#: executor/execExpr.c:3007 parser/parse_node.c:277 parser/parse_node.c:327 +#: executor/execExpr.c:3076 parser/parse_node.c:272 parser/parse_node.c:322 #, c-format msgid "cannot subscript type %s because it does not support subscripting" msgstr "не можна підписати вказати тип %s, тому що він не підтримує підписку" -#: executor/execExpr.c:3135 executor/execExpr.c:3157 +#: executor/execExpr.c:3204 executor/execExpr.c:3226 #, c-format msgid "type %s does not support subscripted assignment" msgstr "тип %s не підтримує вказані присвоєння за підпискою" -#: executor/execExprInterp.c:1962 +#: executor/execExprInterp.c:2007 #, c-format msgid "attribute %d of type %s has been dropped" msgstr "атрибут %d типу %s був видалений" -#: executor/execExprInterp.c:1968 +#: executor/execExprInterp.c:2013 #, c-format msgid "attribute %d of type %s has wrong type" msgstr "атрибут %d типу %s має неправильний тип" -#: executor/execExprInterp.c:1970 executor/execExprInterp.c:3104 -#: executor/execExprInterp.c:3150 +#: executor/execExprInterp.c:2015 executor/execExprInterp.c:3214 +#: executor/execExprInterp.c:3260 #, c-format msgid "Table has type %s, but query expects %s." msgstr "Таблиця має тип %s, але запит очікував %s." -#: executor/execExprInterp.c:2050 utils/adt/expandedrecord.c:99 -#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1749 -#: utils/cache/typcache.c:1908 utils/cache/typcache.c:2055 -#: utils/fmgr/funcapi.c:561 +#: executor/execExprInterp.c:2095 utils/adt/expandedrecord.c:99 +#: utils/adt/expandedrecord.c:231 utils/cache/typcache.c:1752 +#: utils/cache/typcache.c:1911 utils/cache/typcache.c:2058 +#: utils/fmgr/funcapi.c:569 #, c-format msgid "type %s is not composite" msgstr "тип %s не є складеним" -#: executor/execExprInterp.c:2588 +#: executor/execExprInterp.c:2698 #, c-format msgid "WHERE CURRENT OF is not supported for this table type" msgstr "WHERE CURRENT OF для таблиць такого типу не підтримується" -#: executor/execExprInterp.c:2801 +#: executor/execExprInterp.c:2911 #, c-format msgid "cannot merge incompatible arrays" msgstr "не можна об'єднати несумісні масиви" -#: executor/execExprInterp.c:2802 +#: executor/execExprInterp.c:2912 #, c-format msgid "Array with element type %s cannot be included in ARRAY construct with element type %s." msgstr "Масив з типом елементів %s не може бути включений в конструкцію ARRAY з типом елементів %s." -#: executor/execExprInterp.c:2823 utils/adt/arrayfuncs.c:266 -#: utils/adt/arrayfuncs.c:576 utils/adt/arrayfuncs.c:1330 -#: utils/adt/arrayfuncs.c:3532 utils/adt/arrayfuncs.c:5616 -#: utils/adt/arrayfuncs.c:6133 utils/adt/arraysubs.c:150 +#: executor/execExprInterp.c:2933 utils/adt/arrayfuncs.c:1305 +#: utils/adt/arrayfuncs.c:3503 utils/adt/arrayfuncs.c:5593 +#: utils/adt/arrayfuncs.c:6110 utils/adt/arraysubs.c:150 #: utils/adt/arraysubs.c:488 #, c-format msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" msgstr "число вимірів масива (%d) перевищує ліміт (%d)" -#: executor/execExprInterp.c:2843 executor/execExprInterp.c:2878 +#: executor/execExprInterp.c:2953 executor/execExprInterp.c:2988 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "для багатовимірних масивів повинні задаватись вирази з відповідними вимірами" -#: executor/execExprInterp.c:2855 utils/adt/array_expanded.c:274 -#: utils/adt/arrayfuncs.c:960 utils/adt/arrayfuncs.c:1569 -#: utils/adt/arrayfuncs.c:2377 utils/adt/arrayfuncs.c:2392 -#: utils/adt/arrayfuncs.c:2654 utils/adt/arrayfuncs.c:2670 -#: utils/adt/arrayfuncs.c:2978 utils/adt/arrayfuncs.c:2993 -#: utils/adt/arrayfuncs.c:3334 utils/adt/arrayfuncs.c:3562 -#: utils/adt/arrayfuncs.c:6225 utils/adt/arrayfuncs.c:6566 -#: utils/adt/arrayutils.c:98 utils/adt/arrayutils.c:107 -#: utils/adt/arrayutils.c:114 +#: executor/execExprInterp.c:2965 utils/adt/array_expanded.c:274 +#: utils/adt/arrayfuncs.c:335 utils/adt/arrayfuncs.c:494 +#: utils/adt/arrayfuncs.c:727 utils/adt/arrayfuncs.c:1533 +#: utils/adt/arrayfuncs.c:2341 utils/adt/arrayfuncs.c:2356 +#: utils/adt/arrayfuncs.c:2618 utils/adt/arrayfuncs.c:2634 +#: utils/adt/arrayfuncs.c:2895 utils/adt/arrayfuncs.c:2949 +#: utils/adt/arrayfuncs.c:2964 utils/adt/arrayfuncs.c:3305 +#: utils/adt/arrayfuncs.c:3533 utils/adt/arrayfuncs.c:5365 +#: utils/adt/arrayfuncs.c:6202 utils/adt/arrayfuncs.c:6546 +#: utils/adt/arrayutils.c:83 utils/adt/arrayutils.c:92 +#: utils/adt/arrayutils.c:99 #, c-format msgid "array size exceeds the maximum allowed (%d)" msgstr "розмір масиву перевищує максимальний допустимий розмір (%d)" -#: executor/execExprInterp.c:3103 executor/execExprInterp.c:3149 +#: executor/execExprInterp.c:3213 executor/execExprInterp.c:3259 #, c-format msgid "attribute %d has wrong type" msgstr "атрибут %d має неправильний тип" -#: executor/execExprInterp.c:3735 utils/adt/domains.c:155 +#: executor/execExprInterp.c:3845 utils/adt/domains.c:158 #, c-format msgid "domain %s does not allow null values" msgstr "домен %s не допускає значення null" -#: executor/execExprInterp.c:3750 utils/adt/domains.c:193 +#: executor/execExprInterp.c:3860 utils/adt/domains.c:196 #, c-format msgid "value for domain %s violates check constraint \"%s\"" msgstr "значення домену %s порушує перевірочнео бмеження \"%s\"" -#: executor/execExprInterp.c:4235 +#: executor/execExprInterp.c:4435 +#, c-format +msgid "no SQL/JSON item found for specified path of column \"%s\"" +msgstr "" + +#: executor/execExprInterp.c:4440 +#, c-format +msgid "no SQL/JSON item found for specified path" +msgstr "" + +#. translator: first %s is a SQL/JSON clause (e.g. ON ERROR) +#: executor/execExprInterp.c:4640 executor/execExprInterp.c:4648 +#, c-format +msgid "could not coerce %s expression (%s) to the RETURNING type" +msgstr "" + +#: executor/execExprInterp.c:4841 #, c-format msgid "Table row contains %d attribute, but query expects %d." msgid_plural "Table row contains %d attributes, but query expects %d." @@ -13192,329 +13652,293 @@ msgstr[1] "Рядок таблиці містить %d атрибути, але msgstr[2] "Рядок таблиці містить %d атрибутів, але запит очікував %d." msgstr[3] "Рядок таблиці містить %d атрибутів, але запит очікував %d." -#: executor/execExprInterp.c:4351 executor/execSRF.c:978 +#: executor/execExprInterp.c:4957 executor/execSRF.c:977 #, c-format msgid "Physical storage mismatch on dropped attribute at ordinal position %d." msgstr "Невідповідність параметрів фізичного зберігання видаленого атрибуту %d." -#: executor/execIndexing.c:588 +#: executor/execIndexing.c:593 #, c-format msgid "ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters" msgstr "ON CONFLICT не підтримує відкладені обмеження унікальності/обмеження-виключення в якості визначального індексу" -#: executor/execIndexing.c:865 +#: executor/execIndexing.c:870 #, c-format msgid "could not create exclusion constraint \"%s\"" msgstr "не вдалося створити обмеження-виключення \"%s\"" -#: executor/execIndexing.c:868 +#: executor/execIndexing.c:873 #, c-format msgid "Key %s conflicts with key %s." msgstr "Ключ %s конфліктує з ключем %s." -#: executor/execIndexing.c:870 +#: executor/execIndexing.c:875 #, c-format msgid "Key conflicts exist." msgstr "Існують конфлікти ключей." -#: executor/execIndexing.c:876 +#: executor/execIndexing.c:881 #, c-format msgid "conflicting key value violates exclusion constraint \"%s\"" msgstr "конфліктуюче значення ключа порушує обмеження-виключення \"%s\"" -#: executor/execIndexing.c:879 +#: executor/execIndexing.c:884 #, c-format msgid "Key %s conflicts with existing key %s." msgstr "Ключ %s конфліктує з існуючим ключем %s." -#: executor/execIndexing.c:881 +#: executor/execIndexing.c:886 #, c-format msgid "Key conflicts with existing key." msgstr "Ключ конфліктує з існуючим ключем." -#: executor/execMain.c:1039 +#: executor/execMain.c:1043 #, c-format msgid "cannot change sequence \"%s\"" msgstr "послідовність \"%s\" не можна змінити" -#: executor/execMain.c:1045 +#: executor/execMain.c:1049 #, c-format msgid "cannot change TOAST relation \"%s\"" msgstr "TOAST-відношення \"%s\" не можна змінити" -#: executor/execMain.c:1063 rewrite/rewriteHandler.c:3079 -#: rewrite/rewriteHandler.c:3966 -#, c-format -msgid "cannot insert into view \"%s\"" -msgstr "вставити дані в подання \"%s\" не можна" - -#: executor/execMain.c:1065 rewrite/rewriteHandler.c:3082 -#: rewrite/rewriteHandler.c:3969 -#, c-format -msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." -msgstr "Щоб подання допускало додавання даних, встановіть тригер INSTEAD OF INSERT або безумовне правило ON INSERT DO INSTEAD." - -#: executor/execMain.c:1071 rewrite/rewriteHandler.c:3087 -#: rewrite/rewriteHandler.c:3974 -#, c-format -msgid "cannot update view \"%s\"" -msgstr "оновити подання \"%s\" не можна" - -#: executor/execMain.c:1073 rewrite/rewriteHandler.c:3090 -#: rewrite/rewriteHandler.c:3977 -#, c-format -msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." -msgstr "Щоб подання допускало оновлення, встановіть тригер INSTEAD OF UPDATE або безумовне правило ON UPDATE DO INSTEAD." - -#: executor/execMain.c:1079 rewrite/rewriteHandler.c:3095 -#: rewrite/rewriteHandler.c:3982 -#, c-format -msgid "cannot delete from view \"%s\"" -msgstr "видалити дані з подання \"%s\" не можна" - -#: executor/execMain.c:1081 rewrite/rewriteHandler.c:3098 -#: rewrite/rewriteHandler.c:3985 -#, c-format -msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." -msgstr "Щоб подання допускало видалення даних, встановіть тригер INSTEAD OF DELETE або безумновне правило ON DELETE DO INSTEAD." - -#: executor/execMain.c:1092 +#: executor/execMain.c:1068 #, c-format msgid "cannot change materialized view \"%s\"" msgstr "змінити матеріалізоване подання \"%s\" не можна" -#: executor/execMain.c:1104 +#: executor/execMain.c:1080 #, c-format msgid "cannot insert into foreign table \"%s\"" msgstr "вставляти дані в зовнішню таблицю \"%s\" не можна" -#: executor/execMain.c:1110 +#: executor/execMain.c:1086 #, c-format msgid "foreign table \"%s\" does not allow inserts" msgstr "зовнішня таблиця \"%s\" не допускає додавання даних" -#: executor/execMain.c:1117 +#: executor/execMain.c:1093 #, c-format msgid "cannot update foreign table \"%s\"" msgstr "оновити зовнішню таблицю \"%s\" не можна" -#: executor/execMain.c:1123 +#: executor/execMain.c:1099 #, c-format msgid "foreign table \"%s\" does not allow updates" msgstr "зовнішня таблиця \"%s\" не дозволяє оновлення" -#: executor/execMain.c:1130 +#: executor/execMain.c:1106 #, c-format msgid "cannot delete from foreign table \"%s\"" msgstr "видаляти дані з зовнішньої таблиці \"%s\" не можна" -#: executor/execMain.c:1136 +#: executor/execMain.c:1112 #, c-format msgid "foreign table \"%s\" does not allow deletes" msgstr "зовнішня таблиця \"%s\" не дозволяє видалення даних" -#: executor/execMain.c:1147 +#: executor/execMain.c:1123 #, c-format msgid "cannot change relation \"%s\"" msgstr "відношення \"%s\" не можна змінити" -#: executor/execMain.c:1174 +#: executor/execMain.c:1150 #, c-format msgid "cannot lock rows in sequence \"%s\"" msgstr "блокувати рядки в послідовності \"%s\" не можна" -#: executor/execMain.c:1181 +#: executor/execMain.c:1157 #, c-format msgid "cannot lock rows in TOAST relation \"%s\"" msgstr "блокувати рядки в TOAST-відношенні \"%s\" не можна" -#: executor/execMain.c:1188 +#: executor/execMain.c:1164 #, c-format msgid "cannot lock rows in view \"%s\"" msgstr "блокувати рядки в поданні \"%s\" не можна" -#: executor/execMain.c:1196 +#: executor/execMain.c:1172 #, c-format msgid "cannot lock rows in materialized view \"%s\"" msgstr "блокувати рядки в матеріалізованому поданні \"%s\" не можна" -#: executor/execMain.c:1205 executor/execMain.c:2708 +#: executor/execMain.c:1181 executor/execMain.c:2686 #: executor/nodeLockRows.c:135 #, c-format msgid "cannot lock rows in foreign table \"%s\"" msgstr "блокувати рядки в зовнішній таблиці \"%s\" не можна" -#: executor/execMain.c:1211 +#: executor/execMain.c:1187 #, c-format msgid "cannot lock rows in relation \"%s\"" msgstr "блокувати рядки у відношенні \"%s\" не можна" -#: executor/execMain.c:1922 +#: executor/execMain.c:1900 #, c-format msgid "new row for relation \"%s\" violates partition constraint" msgstr "новий рядок для відношення \"%s\" порушує обмеження секції" -#: executor/execMain.c:1924 executor/execMain.c:2008 executor/execMain.c:2059 -#: executor/execMain.c:2169 +#: executor/execMain.c:1902 executor/execMain.c:1986 executor/execMain.c:2037 +#: executor/execMain.c:2147 #, c-format msgid "Failing row contains %s." msgstr "Помилковий рядок містить %s." -#: executor/execMain.c:2005 +#: executor/execMain.c:1983 #, c-format msgid "null value in column \"%s\" of relation \"%s\" violates not-null constraint" msgstr "null значення в стовпці \"%s\" відношення \"%s\" порушує not-null обмеження" -#: executor/execMain.c:2057 +#: executor/execMain.c:2035 #, c-format msgid "new row for relation \"%s\" violates check constraint \"%s\"" msgstr "новий рядок для відношення \"%s\" порушує перевірне обмеження перевірку \"%s\"" -#: executor/execMain.c:2167 +#: executor/execMain.c:2145 #, c-format msgid "new row violates check option for view \"%s\"" msgstr "новий рядок порушує параметр перевірки для подання \"%s\"" -#: executor/execMain.c:2177 +#: executor/execMain.c:2155 #, c-format msgid "new row violates row-level security policy \"%s\" for table \"%s\"" msgstr "новий рядок порушує політику захисту на рівні рядків \"%s\" для таблиці \"%s\"" -#: executor/execMain.c:2182 +#: executor/execMain.c:2160 #, c-format msgid "new row violates row-level security policy for table \"%s\"" msgstr "новий рядок порушує політику захисту на рівні рядків для таблиці \"%s\"" -#: executor/execMain.c:2190 +#: executor/execMain.c:2168 #, c-format msgid "target row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "цільовий рядок порушує політику захисту на рівні рядків \"%s\" (вираз USING) для таблиці \"%s\"" -#: executor/execMain.c:2195 +#: executor/execMain.c:2173 #, c-format msgid "target row violates row-level security policy (USING expression) for table \"%s\"" msgstr "цільовий рядок порушує політику захисту на рівні рядків (вираз USING) для таблиці \"%s\"" -#: executor/execMain.c:2202 +#: executor/execMain.c:2180 #, c-format msgid "new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"" msgstr "новий рядок порушує політику захисту на рівні рядків \"%s\" (вираз USING) для таблиці \"%s\"" -#: executor/execMain.c:2207 +#: executor/execMain.c:2185 #, c-format msgid "new row violates row-level security policy (USING expression) for table \"%s\"" msgstr "новий рядок порушує політику захисту на рівні рядків (вираз USING) для таблиці \"%s\"" -#: executor/execPartition.c:330 +#: executor/execPartition.c:327 #, c-format msgid "no partition of relation \"%s\" found for row" msgstr "для рядка не знайдено секції у відношенні \"%s\"" -#: executor/execPartition.c:333 +#: executor/execPartition.c:330 #, c-format msgid "Partition key of the failing row contains %s." msgstr "Ключ секціонування для невідповідного рядка містить %s." -#: executor/execReplication.c:231 executor/execReplication.c:415 +#: executor/execReplication.c:272 executor/execReplication.c:456 #, c-format msgid "tuple to be locked was already moved to another partition due to concurrent update, retrying" msgstr "кортеж, що підлягає блокуванню, вже переміщено в іншу секцію в результаті паралельного оновлення, триває повторна спроба" -#: executor/execReplication.c:235 executor/execReplication.c:419 +#: executor/execReplication.c:276 executor/execReplication.c:460 #, c-format msgid "concurrent update, retrying" msgstr "паралельне оновлення, триває повторна спроба" -#: executor/execReplication.c:241 executor/execReplication.c:425 +#: executor/execReplication.c:282 executor/execReplication.c:466 #, c-format msgid "concurrent delete, retrying" msgstr "паралельне видалення, триває повторна спроба" -#: executor/execReplication.c:311 parser/parse_cte.c:308 -#: parser/parse_oper.c:233 utils/adt/array_userfuncs.c:1348 -#: utils/adt/array_userfuncs.c:1491 utils/adt/arrayfuncs.c:3881 -#: utils/adt/arrayfuncs.c:4436 utils/adt/arrayfuncs.c:6446 -#: utils/adt/rowtypes.c:1230 +#: executor/execReplication.c:352 parser/parse_cte.c:302 +#: parser/parse_oper.c:221 utils/adt/array_userfuncs.c:1334 +#: utils/adt/array_userfuncs.c:1477 utils/adt/arrayfuncs.c:3852 +#: utils/adt/arrayfuncs.c:4407 utils/adt/arrayfuncs.c:6426 +#: utils/adt/rowtypes.c:1220 #, c-format msgid "could not identify an equality operator for type %s" msgstr "не вдалося визначити оператора рівності для типу %s" -#: executor/execReplication.c:642 executor/execReplication.c:648 +#: executor/execReplication.c:683 executor/execReplication.c:689 #, c-format msgid "cannot update table \"%s\"" msgstr "оновити таблицю \"%s\" не можна" -#: executor/execReplication.c:644 executor/execReplication.c:656 +#: executor/execReplication.c:685 executor/execReplication.c:697 #, c-format msgid "Column used in the publication WHERE expression is not part of the replica identity." msgstr "Стовпець, що використовується в виразі WHERE публікації не є частиною ідентифікації репліки." -#: executor/execReplication.c:650 executor/execReplication.c:662 +#: executor/execReplication.c:691 executor/execReplication.c:703 #, c-format msgid "Column list used by the publication does not cover the replica identity." msgstr "Список стовпців, який використовується публікацією, не охоплює ідентифікацію репліки." -#: executor/execReplication.c:654 executor/execReplication.c:660 +#: executor/execReplication.c:695 executor/execReplication.c:701 #, c-format msgid "cannot delete from table \"%s\"" msgstr "видалити дані з таблиці \"%s\" не можна" -#: executor/execReplication.c:680 +#: executor/execReplication.c:721 #, c-format msgid "cannot update table \"%s\" because it does not have a replica identity and publishes updates" msgstr "оновлення в таблиці \"%s\" неможливе, тому що в ній відсутній ідентифікатор репліки, і вона публікує оновлення" -#: executor/execReplication.c:682 +#: executor/execReplication.c:723 #, c-format msgid "To enable updating the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "Щоб ця таблиця підтримувала оновлення, встановіть REPLICA IDENTITY, використавши ALTER TABLE." -#: executor/execReplication.c:686 +#: executor/execReplication.c:727 #, c-format msgid "cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes" msgstr "видалення з таблиці \"%s\" неможливе, тому що в ній відсутній ідентифікатор репліки, і вона публікує видалення" -#: executor/execReplication.c:688 +#: executor/execReplication.c:729 #, c-format msgid "To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE." msgstr "Щоб ця таблиця підтримувала видалення, встановіть REPLICA IDENTITY, використавши ALTER TABLE." -#: executor/execReplication.c:704 +#: executor/execReplication.c:745 #, c-format msgid "cannot use relation \"%s.%s\" as logical replication target" msgstr "використовувати відношення \"%s.%s\" як ціль логічної реплікації, не можна" -#: executor/execSRF.c:316 +#: executor/execSRF.c:315 #, c-format msgid "rows returned by function are not all of the same row type" msgstr "рядки, які повернула функція, не мають однаковий тип рядка" -#: executor/execSRF.c:366 +#: executor/execSRF.c:365 #, c-format msgid "table-function protocol for value-per-call mode was not followed" msgstr "протокол функції-таблиці для режиму значення-на-виклик не дотримувався" -#: executor/execSRF.c:374 executor/execSRF.c:668 +#: executor/execSRF.c:373 executor/execSRF.c:667 #, c-format msgid "table-function protocol for materialize mode was not followed" msgstr "порушення протоколу табличної функції в режимі матеріалізації" -#: executor/execSRF.c:381 executor/execSRF.c:686 +#: executor/execSRF.c:380 executor/execSRF.c:685 #, c-format msgid "unrecognized table-function returnMode: %d" msgstr "нерозпізнаний режим повернення табличної функції: %d" -#: executor/execSRF.c:895 +#: executor/execSRF.c:894 #, c-format msgid "function returning setof record called in context that cannot accept type record" msgstr "функція, що повертає набір записів, викликана в контексті, що не може прийняти тип запису" -#: executor/execSRF.c:951 executor/execSRF.c:967 executor/execSRF.c:977 +#: executor/execSRF.c:950 executor/execSRF.c:966 executor/execSRF.c:976 #, c-format msgid "function return row and query-specified return row do not match" msgstr "тип результату функції відрізняється від типу рядка-результату запиту" -#: executor/execSRF.c:952 +#: executor/execSRF.c:951 #, c-format msgid "Returned row contains %d attribute, but query expects %d." msgid_plural "Returned row contains %d attributes, but query expects %d." @@ -13523,23 +13947,33 @@ msgstr[1] "Повернений рядок містить %d атрибути, msgstr[2] "Повернений рядок містить %d атрибутів, але запит очікував %d." msgstr[3] "Повернений рядок містить %d атрибутів, але запит очікував %d." -#: executor/execSRF.c:968 +#: executor/execSRF.c:967 #, c-format msgid "Returned type %s at ordinal position %d, but query expects %s." msgstr "Повернений тип %s у порядковій позиції %d, але запит очікував %s." -#: executor/execTuples.c:146 executor/execTuples.c:353 -#: executor/execTuples.c:521 executor/execTuples.c:713 +#: executor/execTuples.c:147 executor/execTuples.c:368 +#: executor/execTuples.c:563 executor/execTuples.c:772 #, c-format msgid "cannot retrieve a system column in this context" msgstr "не можна отримати системний стовпець в цьому контексті" -#: executor/execUtils.c:744 +#: executor/execTuples.c:163 executor/execTuples.c:580 +#, c-format +msgid "don't have transaction information for this type of tuple" +msgstr "" + +#: executor/execTuples.c:390 executor/execTuples.c:794 +#, c-format +msgid "don't have a storage tuple in this context" +msgstr "" + +#: executor/execUtils.c:713 #, c-format msgid "materialized view \"%s\" has not been populated" msgstr "матеріалізоване подання \"%s\" не було наповнене" -#: executor/execUtils.c:746 +#: executor/execUtils.c:715 #, c-format msgid "Use the REFRESH MATERIALIZED VIEW command." msgstr "Використайте команду REFRESH MATERIALIZED VIEW." @@ -13549,111 +13983,111 @@ msgstr "Використайте команду REFRESH MATERIALIZED VIEW." msgid "could not determine actual type of argument declared %s" msgstr "не вдалося визначити фактичний тип аргументу, оголошеного як %s" -#: executor/functions.c:512 +#: executor/functions.c:513 #, c-format msgid "cannot COPY to/from client in an SQL function" msgstr "у функції SQL не можна виконати COPY до/з клієнта" #. translator: %s is a SQL statement name -#: executor/functions.c:518 +#: executor/functions.c:519 #, c-format msgid "%s is not allowed in an SQL function" msgstr "функція SQL не дозволяє використання %s" #. translator: %s is a SQL statement name -#: executor/functions.c:526 executor/spi.c:1742 executor/spi.c:2635 +#: executor/functions.c:527 executor/spi.c:1741 executor/spi.c:2651 #, c-format msgid "%s is not allowed in a non-volatile function" msgstr "незмінна функція не дозволяє використання %s" -#: executor/functions.c:1450 +#: executor/functions.c:1452 #, c-format msgid "SQL function \"%s\" statement %d" msgstr "SQL функція \"%s\" оператор %d" -#: executor/functions.c:1476 +#: executor/functions.c:1478 #, c-format msgid "SQL function \"%s\" during startup" msgstr "SQL функція \"%s\" під час запуску" -#: executor/functions.c:1561 +#: executor/functions.c:1563 #, c-format msgid "calling procedures with output arguments is not supported in SQL functions" msgstr "виклик процедур з вихідними аргументами в функціях SQL не підтримується" -#: executor/functions.c:1694 executor/functions.c:1732 -#: executor/functions.c:1746 executor/functions.c:1836 -#: executor/functions.c:1869 executor/functions.c:1883 +#: executor/functions.c:1698 executor/functions.c:1736 +#: executor/functions.c:1750 executor/functions.c:1845 +#: executor/functions.c:1878 executor/functions.c:1892 #, c-format msgid "return type mismatch in function declared to return %s" msgstr "невідповідність типу повернення в функції, оголошеній як %s" -#: executor/functions.c:1696 +#: executor/functions.c:1700 #, c-format -msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING." -msgstr "Останнім оператором у функції повинен бути SELECT або INSERT/UPDATE/DELETE RETURNING." +msgid "Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING." +msgstr "" -#: executor/functions.c:1734 +#: executor/functions.c:1738 #, c-format msgid "Final statement must return exactly one column." msgstr "Останній оператор повинен вертати один стовпець." -#: executor/functions.c:1748 +#: executor/functions.c:1752 #, c-format msgid "Actual return type is %s." msgstr "Фактичний тип повернення: %s." -#: executor/functions.c:1838 +#: executor/functions.c:1847 #, c-format msgid "Final statement returns too many columns." msgstr "Останній оператор вертає дуже багато стовпців." -#: executor/functions.c:1871 +#: executor/functions.c:1880 #, c-format msgid "Final statement returns %s instead of %s at column %d." msgstr "Останній оператор поветрає %s замість %s для стовпця %d." -#: executor/functions.c:1885 +#: executor/functions.c:1894 #, c-format msgid "Final statement returns too few columns." msgstr "Останній оператор вертає дуже мало стовпців." -#: executor/functions.c:1913 +#: executor/functions.c:1922 #, c-format msgid "return type %s is not supported for SQL functions" msgstr "для SQL функцій тип повернення %s не підтримується" -#: executor/nodeAgg.c:3937 executor/nodeWindowAgg.c:2993 +#: executor/nodeAgg.c:3936 executor/nodeWindowAgg.c:2976 #, c-format msgid "aggregate %u needs to have compatible input type and transition type" msgstr "агрегатна функція %u повинна мати сумісні тип введення і тип переходу" -#: executor/nodeAgg.c:3967 parser/parse_agg.c:680 parser/parse_agg.c:708 +#: executor/nodeAgg.c:3966 parser/parse_agg.c:680 parser/parse_agg.c:708 #, c-format msgid "aggregate function calls cannot be nested" msgstr "виклики агрегатних функцій не можуть бути вкладеними" -#: executor/nodeCustom.c:154 executor/nodeCustom.c:165 +#: executor/nodeCustom.c:144 executor/nodeCustom.c:155 #, c-format msgid "custom scan \"%s\" does not support MarkPos" msgstr "налаштовуване сканування \"%s\" не підтримує MarkPos" -#: executor/nodeHashjoin.c:1143 executor/nodeHashjoin.c:1173 +#: executor/nodeHashjoin.c:1131 executor/nodeHashjoin.c:1161 #, c-format msgid "could not rewind hash-join temporary file" msgstr "не вдалося перемотати назад тимчасовий файл хеш-з'єднання" -#: executor/nodeIndexonlyscan.c:238 +#: executor/nodeIndexonlyscan.c:239 #, c-format msgid "lossy distance functions are not supported in index-only scans" msgstr "функції неточної (lossy) дистанції не підтримуються в скануваннях лише по індексу" -#: executor/nodeLimit.c:374 +#: executor/nodeLimit.c:373 #, c-format msgid "OFFSET must not be negative" msgstr "OFFSET повинен бути не негативним" -#: executor/nodeLimit.c:400 +#: executor/nodeLimit.c:399 #, c-format msgid "LIMIT must not be negative" msgstr "LIMIT повинен бути не негативним" @@ -13668,73 +14102,74 @@ msgstr "RIGHT JOIN підтримується лише з умовами, які msgid "FULL JOIN is only supported with merge-joinable join conditions" msgstr "FULL JOIN підтримується лише з умовами, які допускають з'єднання злиттям" -#: executor/nodeModifyTable.c:234 +#: executor/nodeModifyTable.c:240 #, c-format msgid "Query has too few columns." msgstr "Запит повертає дуже мало стовпців." -#: executor/nodeModifyTable.c:1534 executor/nodeModifyTable.c:1608 +#: executor/nodeModifyTable.c:1540 executor/nodeModifyTable.c:1614 #, c-format msgid "tuple to be deleted was already modified by an operation triggered by the current command" msgstr "кортеж, який підлягає видаленню, вже змінений в операції, яка викликана поточною командою" -#: executor/nodeModifyTable.c:1763 +#: executor/nodeModifyTable.c:1769 #, c-format msgid "invalid ON UPDATE specification" msgstr "неприпустима специфікація ON UPDATE" -#: executor/nodeModifyTable.c:1764 +#: executor/nodeModifyTable.c:1770 #, c-format msgid "The result tuple would appear in a different partition than the original tuple." msgstr "Результуючий кортеж з'явиться в іншій секції в порівнянні з оригінальним кортежем." -#: executor/nodeModifyTable.c:2223 +#: executor/nodeModifyTable.c:2226 #, c-format msgid "cannot move tuple across partitions when a non-root ancestor of the source partition is directly referenced in a foreign key" msgstr "не можна пересувати кортеж між різними партиціями, коли не кореневий предок секції джерела безпосередньо посилається на зовнішній ключ" -#: executor/nodeModifyTable.c:2224 +#: executor/nodeModifyTable.c:2227 #, c-format msgid "A foreign key points to ancestor \"%s\" but not the root ancestor \"%s\"." msgstr "Зовнішній ключ вказує на предка \"%s\", але не на кореневого предка \"%s\"." -#: executor/nodeModifyTable.c:2227 +#: executor/nodeModifyTable.c:2230 #, c-format msgid "Consider defining the foreign key on table \"%s\"." msgstr "Розгляньте визначення зовнішнього ключа для таблиці \"%s\"." #. translator: %s is a SQL command name -#: executor/nodeModifyTable.c:2573 executor/nodeModifyTable.c:2975 +#: executor/nodeModifyTable.c:2577 executor/nodeModifyTable.c:3099 +#: executor/nodeModifyTable.c:3260 #, c-format msgid "%s command cannot affect row a second time" msgstr "команда %s не може вплинути на рядок вдруге" -#: executor/nodeModifyTable.c:2575 +#: executor/nodeModifyTable.c:2579 #, c-format msgid "Ensure that no rows proposed for insertion within the same command have duplicate constrained values." msgstr "Переконайтеся, що немає рядків для вставки з тією ж командою з дуплікованими обмежувальними значеннями." -#: executor/nodeModifyTable.c:2977 +#: executor/nodeModifyTable.c:3092 executor/nodeModifyTable.c:3253 #, c-format -msgid "Ensure that not more than one source row matches any one target row." -msgstr "Переконайтесь, що не більше ніж один вихідний рядок відповідає будь-якому одному цільовому рядку." +msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" +msgstr "кортеж, який підлягає оновленню або видаленню, вже змінено операцією, викликаною поточною командою" -#: executor/nodeModifyTable.c:3058 +#: executor/nodeModifyTable.c:3101 executor/nodeModifyTable.c:3262 #, c-format -msgid "tuple to be deleted was already moved to another partition due to concurrent update" -msgstr "кортеж, який підлягає видаленню, вже переміщено в іншу секцію в результаті паралельного оновлення" +msgid "Ensure that not more than one source row matches any one target row." +msgstr "Переконайтесь, що не більше ніж один вихідний рядок відповідає будь-якому одному цільовому рядку." -#: executor/nodeModifyTable.c:3097 +#: executor/nodeModifyTable.c:3170 #, c-format -msgid "tuple to be updated or deleted was already modified by an operation triggered by the current command" -msgstr "кортеж, який підлягає оновленню або видаленню, вже змінено операцією, викликаною поточною командою" +msgid "tuple to be merged was already moved to another partition due to concurrent update" +msgstr "" -#: executor/nodeSamplescan.c:260 +#: executor/nodeSamplescan.c:244 #, c-format msgid "TABLESAMPLE parameter cannot be null" msgstr "Параметр TABLESAMPLE не може бути null" -#: executor/nodeSamplescan.c:272 +#: executor/nodeSamplescan.c:256 #, c-format msgid "TABLESAMPLE REPEATABLE parameter cannot be null" msgstr "Параметр TABLESAMPLE REPEATABLE не може бути null" @@ -13745,7 +14180,7 @@ msgstr "Параметр TABLESAMPLE REPEATABLE не може бути null" msgid "more than one row returned by a subquery used as an expression" msgstr "підзапит, використаний в якості вираження, повернув більше ніж один рядок" -#: executor/nodeTableFuncscan.c:375 +#: executor/nodeTableFuncscan.c:370 #, c-format msgid "namespace URI must not be null" msgstr "простір імен URI не повинен бути null" @@ -13755,17 +14190,17 @@ msgstr "простір імен URI не повинен бути null" msgid "row filter expression must not be null" msgstr "вираз фільтру рядків не повинен бути null" -#: executor/nodeTableFuncscan.c:415 +#: executor/nodeTableFuncscan.c:416 #, c-format msgid "column filter expression must not be null" msgstr "вираз фільтру стовпців не повинен бути null" -#: executor/nodeTableFuncscan.c:416 +#: executor/nodeTableFuncscan.c:417 #, c-format msgid "Filter for column \"%s\" is null." msgstr "Фільтр для стовпця \"%s\" є null." -#: executor/nodeTableFuncscan.c:506 +#: executor/nodeTableFuncscan.c:507 #, c-format msgid "null is not allowed in column \"%s\"" msgstr "у стовпці \"%s\" не допускається null" @@ -13795,84 +14230,84 @@ msgstr "зсув кінця рамки не повинен бути null" msgid "frame ending offset must not be negative" msgstr "зсув кінця рамки не повинен бути негативним" -#: executor/nodeWindowAgg.c:2909 +#: executor/nodeWindowAgg.c:2892 #, c-format msgid "aggregate function %s does not support use as a window function" msgstr "агрегатна функція %s не підтримує використання в якості віконної функції" -#: executor/spi.c:242 executor/spi.c:342 +#: executor/spi.c:241 executor/spi.c:341 #, c-format msgid "invalid transaction termination" msgstr "неприпустиме завершення транзакції" -#: executor/spi.c:257 +#: executor/spi.c:256 #, c-format msgid "cannot commit while a subtransaction is active" msgstr "неможливо затвердити, коли підтранзакції активні" -#: executor/spi.c:348 +#: executor/spi.c:347 #, c-format msgid "cannot roll back while a subtransaction is active" msgstr "неможливо відкотити, коли підтранзакції активні" -#: executor/spi.c:472 +#: executor/spi.c:471 #, c-format msgid "transaction left non-empty SPI stack" msgstr "транзакція залишила непорожню групу SPI" -#: executor/spi.c:473 executor/spi.c:533 +#: executor/spi.c:472 executor/spi.c:532 #, c-format msgid "Check for missing \"SPI_finish\" calls." msgstr "Перевірте наявність виклику \"SPI_finish\"." -#: executor/spi.c:532 +#: executor/spi.c:531 #, c-format msgid "subtransaction left non-empty SPI stack" msgstr "підтранзакція залишила непорожню групу SPI" -#: executor/spi.c:1600 +#: executor/spi.c:1599 #, c-format msgid "cannot open multi-query plan as cursor" msgstr "неможливо відкрити план декількох запитів як курсор" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:1610 +#: executor/spi.c:1609 #, c-format msgid "cannot open %s query as cursor" msgstr "неможливо відкрити запит %s як курсор" -#: executor/spi.c:1716 +#: executor/spi.c:1715 #, c-format msgid "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported" msgstr "DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE не підтримується" -#: executor/spi.c:1717 parser/analyze.c:2912 +#: executor/spi.c:1716 parser/analyze.c:2928 #, c-format msgid "Scrollable cursors must be READ ONLY." msgstr "Курсори з прокручуванням повинні бути READ ONLY." -#: executor/spi.c:2474 +#: executor/spi.c:2490 #, c-format msgid "empty query does not return tuples" msgstr "пустий запит не повертає кортежі" #. translator: %s is name of a SQL command, eg INSERT -#: executor/spi.c:2548 +#: executor/spi.c:2564 #, c-format msgid "%s query does not return tuples" msgstr "%s запит не повертає кортежі" -#: executor/spi.c:2963 +#: executor/spi.c:2981 #, c-format msgid "SQL expression \"%s\"" msgstr "SQL вираз \"%s\"" -#: executor/spi.c:2968 +#: executor/spi.c:2986 #, c-format msgid "PL/pgSQL assignment \"%s\"" msgstr "PL/pgSQL присвоєння \"%s\"" -#: executor/spi.c:2971 +#: executor/spi.c:2989 #, c-format msgid "SQL statement \"%s\"" msgstr "SQL-оператор \"%s\"" @@ -13882,28 +14317,34 @@ msgstr "SQL-оператор \"%s\"" msgid "could not send tuple to shared-memory queue" msgstr "не вдалося передати кортеж у чергу в спільну пам'ять" -#: foreign/foreign.c:222 +#: foreign/foreign.c:225 +#, c-format +msgid "user mapping not found for user \"%s\", server \"%s\"" +msgstr "зіставлення користувача не знайдено для користувача \"%s\", сервер \"%s\"" + +#: foreign/foreign.c:336 optimizer/plan/createplan.c:7153 +#: optimizer/util/plancat.c:540 #, c-format -msgid "user mapping not found for \"%s\"" -msgstr "зіставлення користувача \"%s\" не знайдено" +msgid "access to non-system foreign table is restricted" +msgstr "" -#: foreign/foreign.c:647 storage/file/fd.c:3931 +#: foreign/foreign.c:660 #, c-format msgid "invalid option \"%s\"" msgstr "недійсний параметр \"%s\"" -#: foreign/foreign.c:649 +#: foreign/foreign.c:662 #, c-format msgid "Perhaps you meant the option \"%s\"." msgstr "Можливо, ви мали на увазі параметр \"%s\"." -#: foreign/foreign.c:651 +#: foreign/foreign.c:664 #, c-format msgid "There are no valid options in this context." msgstr "У цьому контексті немає припустимих варіантів." -#: lib/dshash.c:254 utils/mmgr/dsa.c:715 utils/mmgr/dsa.c:737 -#: utils/mmgr/dsa.c:818 +#: lib/dshash.c:254 utils/mmgr/dsa.c:708 utils/mmgr/dsa.c:730 +#: utils/mmgr/dsa.c:811 #, c-format msgid "Failed on DSA request of size %zu." msgstr "Не вдалося виконати запит DSA розміру %zu." @@ -13913,568 +14354,568 @@ msgstr "Не вдалося виконати запит DSA розміру %zu." msgid "expected SASL response, got message type %d" msgstr "очікувалася відповідь SASL, але отримано тип повідомлення %d" -#: libpq/auth-scram.c:270 +#: libpq/auth-scram.c:263 #, c-format msgid "client selected an invalid SASL authentication mechanism" msgstr "клієнт обрав неприпустимий механізм автентифікації SASL" -#: libpq/auth-scram.c:294 libpq/auth-scram.c:543 libpq/auth-scram.c:554 +#: libpq/auth-scram.c:287 libpq/auth-scram.c:536 libpq/auth-scram.c:547 #, c-format msgid "invalid SCRAM secret for user \"%s\"" msgstr "неприпустимий секрет SCRAM для користувача \"%s\"" -#: libpq/auth-scram.c:305 +#: libpq/auth-scram.c:298 #, c-format msgid "User \"%s\" does not have a valid SCRAM secret." msgstr "Користувач \"%s\" не має припустимого секрету SCRAM." -#: libpq/auth-scram.c:385 libpq/auth-scram.c:390 libpq/auth-scram.c:744 -#: libpq/auth-scram.c:752 libpq/auth-scram.c:857 libpq/auth-scram.c:870 -#: libpq/auth-scram.c:880 libpq/auth-scram.c:988 libpq/auth-scram.c:995 -#: libpq/auth-scram.c:1010 libpq/auth-scram.c:1025 libpq/auth-scram.c:1039 -#: libpq/auth-scram.c:1057 libpq/auth-scram.c:1072 libpq/auth-scram.c:1386 -#: libpq/auth-scram.c:1394 +#: libpq/auth-scram.c:378 libpq/auth-scram.c:383 libpq/auth-scram.c:737 +#: libpq/auth-scram.c:745 libpq/auth-scram.c:850 libpq/auth-scram.c:863 +#: libpq/auth-scram.c:873 libpq/auth-scram.c:981 libpq/auth-scram.c:988 +#: libpq/auth-scram.c:1003 libpq/auth-scram.c:1018 libpq/auth-scram.c:1032 +#: libpq/auth-scram.c:1050 libpq/auth-scram.c:1065 libpq/auth-scram.c:1379 +#: libpq/auth-scram.c:1387 #, c-format msgid "malformed SCRAM message" msgstr "неправильне повідомлення SCRAM" -#: libpq/auth-scram.c:386 +#: libpq/auth-scram.c:379 #, c-format msgid "The message is empty." msgstr "Повідомлення порожнє." -#: libpq/auth-scram.c:391 +#: libpq/auth-scram.c:384 #, c-format msgid "Message length does not match input length." msgstr "Довжина повідомлення не відповідає довжині вводу." -#: libpq/auth-scram.c:423 +#: libpq/auth-scram.c:416 #, c-format msgid "invalid SCRAM response" msgstr "неприпустима відповідь SCRAM" -#: libpq/auth-scram.c:424 +#: libpq/auth-scram.c:417 #, c-format msgid "Nonce does not match." msgstr "Одноразовий ідентифікатор не збігається." -#: libpq/auth-scram.c:500 +#: libpq/auth-scram.c:493 #, c-format msgid "could not generate random salt" msgstr "не вдалося згенерувати випадкову сіль" -#: libpq/auth-scram.c:745 +#: libpq/auth-scram.c:738 #, c-format msgid "Expected attribute \"%c\" but found \"%s\"." msgstr "Очікувався атрибут \"%c\", але знайдено \"%s\"." -#: libpq/auth-scram.c:753 libpq/auth-scram.c:881 +#: libpq/auth-scram.c:746 libpq/auth-scram.c:874 #, c-format msgid "Expected character \"=\" for attribute \"%c\"." msgstr "Очікувався символ \"=\" для атрибуту \"%c\"." -#: libpq/auth-scram.c:858 +#: libpq/auth-scram.c:851 #, c-format msgid "Attribute expected, but found end of string." msgstr "Очікувався атрибут, але знайдено кінець рядка." -#: libpq/auth-scram.c:871 +#: libpq/auth-scram.c:864 #, c-format msgid "Attribute expected, but found invalid character \"%s\"." msgstr "Очікувався атрибут, але знайдено неприпустимий символ \"%s\"." -#: libpq/auth-scram.c:989 libpq/auth-scram.c:1011 +#: libpq/auth-scram.c:982 libpq/auth-scram.c:1004 #, c-format msgid "The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data." msgstr "Клієнт обрав алгоритм SCRAM-SHA-256-PLUS, але повідомлення SCRAM не містить даних зв’язування каналів." -#: libpq/auth-scram.c:996 libpq/auth-scram.c:1026 +#: libpq/auth-scram.c:989 libpq/auth-scram.c:1019 #, c-format msgid "Comma expected, but found character \"%s\"." msgstr "Очікувалась кома, але знайдено символ \"%s\"." -#: libpq/auth-scram.c:1017 +#: libpq/auth-scram.c:1010 #, c-format msgid "SCRAM channel binding negotiation error" msgstr "Помилка узгодження зв’язування каналів SCRAM" -#: libpq/auth-scram.c:1018 +#: libpq/auth-scram.c:1011 #, c-format msgid "The client supports SCRAM channel binding but thinks the server does not. However, this server does support channel binding." msgstr "Клієнт підтримує зв’язування каналів SCRAM, але думає, що сервер не підтримує. Однак, сервер теж підтримує зв’язування каналів." -#: libpq/auth-scram.c:1040 +#: libpq/auth-scram.c:1033 #, c-format msgid "The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data." msgstr "Клієнт обрав алгоритм SCRAM-SHA-256 без зв’язування каналів, але повідомлення SCRAM містить дані зв’язування каналів." -#: libpq/auth-scram.c:1051 +#: libpq/auth-scram.c:1044 #, c-format msgid "unsupported SCRAM channel-binding type \"%s\"" msgstr "непідтримуваний тип зв'язування каналів SCRAM \"%s\"" -#: libpq/auth-scram.c:1058 +#: libpq/auth-scram.c:1051 #, c-format msgid "Unexpected channel-binding flag \"%s\"." msgstr "Неочікувана позначка зв'язування каналів \"%s\"." -#: libpq/auth-scram.c:1068 +#: libpq/auth-scram.c:1061 #, c-format msgid "client uses authorization identity, but it is not supported" msgstr "клієнт використовує ідентифікатор для авторизації, але це не підтримується" -#: libpq/auth-scram.c:1073 +#: libpq/auth-scram.c:1066 #, c-format msgid "Unexpected attribute \"%s\" in client-first-message." msgstr "Неочікуваний атрибут \"%s\" у першому повідомленні клієнта." -#: libpq/auth-scram.c:1089 +#: libpq/auth-scram.c:1082 #, c-format msgid "client requires an unsupported SCRAM extension" msgstr "клієнт потребує непідтримуване розширення SCRAM" -#: libpq/auth-scram.c:1103 +#: libpq/auth-scram.c:1096 #, c-format msgid "non-printable characters in SCRAM nonce" msgstr "недруковані символи в одноразовому ідентифікаторі SCRAM" -#: libpq/auth-scram.c:1234 +#: libpq/auth-scram.c:1227 #, c-format msgid "could not generate random nonce" msgstr "не вдалося згенерувати випадковий одноразовий ідентифікатор" -#: libpq/auth-scram.c:1244 +#: libpq/auth-scram.c:1237 #, c-format msgid "could not encode random nonce" msgstr "не вдалося кодувати випадковий одноразовий ідентифікатор" -#: libpq/auth-scram.c:1350 +#: libpq/auth-scram.c:1343 #, c-format msgid "SCRAM channel binding check failed" msgstr "Помилка перевірки зв'язування каналів SCRAM" -#: libpq/auth-scram.c:1368 +#: libpq/auth-scram.c:1361 #, c-format msgid "unexpected SCRAM channel-binding attribute in client-final-message" msgstr "неочікуваний атрибут зв'язування каналів SCRAM в останньому повідомленні клієнта" -#: libpq/auth-scram.c:1387 +#: libpq/auth-scram.c:1380 #, c-format msgid "Malformed proof in client-final-message." msgstr "Неправильне підтвердження в останньому повідомленні клієнта." -#: libpq/auth-scram.c:1395 +#: libpq/auth-scram.c:1388 #, c-format msgid "Garbage found at the end of client-final-message." msgstr "Сміття знайдено в кінці останнього повідомлення клієнта." -#: libpq/auth.c:271 +#: libpq/auth.c:269 #, c-format msgid "authentication failed for user \"%s\": host rejected" msgstr "користувач \"%s\" не пройшов автентифікацію: відхилений хост" -#: libpq/auth.c:274 +#: libpq/auth.c:272 #, c-format msgid "\"trust\" authentication failed for user \"%s\"" msgstr "користувач \"%s\" не пройшов автентифікацію \"trust\"" -#: libpq/auth.c:277 +#: libpq/auth.c:275 #, c-format msgid "Ident authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію Ident" -#: libpq/auth.c:280 +#: libpq/auth.c:278 #, c-format msgid "Peer authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію Peer" -#: libpq/auth.c:285 +#: libpq/auth.c:283 #, c-format msgid "password authentication failed for user \"%s\"" msgstr "користувач \"%s\" не пройшов автентифікацію за допомогою пароля" -#: libpq/auth.c:290 +#: libpq/auth.c:288 #, c-format msgid "GSSAPI authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію GSSAPI" -#: libpq/auth.c:293 +#: libpq/auth.c:291 #, c-format msgid "SSPI authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію SSPI" -#: libpq/auth.c:296 +#: libpq/auth.c:294 #, c-format msgid "PAM authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію PAM" -#: libpq/auth.c:299 +#: libpq/auth.c:297 #, c-format msgid "BSD authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію BSD" -#: libpq/auth.c:302 +#: libpq/auth.c:300 #, c-format msgid "LDAP authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію LDAP" -#: libpq/auth.c:305 +#: libpq/auth.c:303 #, c-format msgid "certificate authentication failed for user \"%s\"" msgstr "користувач \"%s\" не пройшов автентифікацію за сертифікатом" -#: libpq/auth.c:308 +#: libpq/auth.c:306 #, c-format msgid "RADIUS authentication failed for user \"%s\"" msgstr "Користувач \"%s\" не пройшов автентифікацію RADIUS" -#: libpq/auth.c:311 +#: libpq/auth.c:309 #, c-format msgid "authentication failed for user \"%s\": invalid authentication method" msgstr "користувач \"%s\" не пройшов автентифікацію: неприпустимий метод автентифікації" -#: libpq/auth.c:315 +#: libpq/auth.c:313 #, c-format msgid "Connection matched file \"%s\" line %d: \"%s\"" -msgstr "З'єднання відповідає файлу \"%s\" рядку %d: \"%s\"" +msgstr "З'єднання відповідає файлу \"%s\" рядок %d: \"%s\"" -#: libpq/auth.c:359 +#: libpq/auth.c:357 #, c-format msgid "authentication identifier set more than once" msgstr "ідентифікатор автентифікації встановлено більш ніж один раз" -#: libpq/auth.c:360 +#: libpq/auth.c:358 #, c-format msgid "previous identifier: \"%s\"; new identifier: \"%s\"" msgstr "попередній ідентифікатор: \"%s\"; новий ідентифікатор: \"%s\"" -#: libpq/auth.c:370 +#: libpq/auth.c:368 #, c-format msgid "connection authenticated: identity=\"%s\" method=%s (%s:%d)" msgstr "підключення автентифіковано: ідентифікатор=\"%s\" метод=%s (%s:%d)" -#: libpq/auth.c:410 +#: libpq/auth.c:408 #, c-format msgid "client certificates can only be checked if a root certificate store is available" msgstr "сертифікати клієнтів можуть перевірятися, лише якщо доступне сховище кореневих сертифікатів" -#: libpq/auth.c:421 +#: libpq/auth.c:419 #, c-format msgid "connection requires a valid client certificate" msgstr "підключення потребує припустимий сертифікат клієнта" -#: libpq/auth.c:452 libpq/auth.c:498 +#: libpq/auth.c:450 libpq/auth.c:496 msgid "GSS encryption" msgstr "Шифрування GSS" -#: libpq/auth.c:455 libpq/auth.c:501 +#: libpq/auth.c:453 libpq/auth.c:499 msgid "SSL encryption" msgstr "Шифрування SSL" -#: libpq/auth.c:457 libpq/auth.c:503 +#: libpq/auth.c:455 libpq/auth.c:501 msgid "no encryption" msgstr "без шифрування" #. translator: last %s describes encryption state -#: libpq/auth.c:463 +#: libpq/auth.c:461 #, c-format msgid "pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s" msgstr "pg_hba.conf відхиляє підключення реплікації для хосту \"%s\", користувача \"%s\", %s" #. translator: last %s describes encryption state -#: libpq/auth.c:470 +#: libpq/auth.c:468 #, c-format msgid "pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "pg_hba.conf відхиляє підключення для хосту \"%s\", користувача \"%s\", бази даних \"%s\", %s" -#: libpq/auth.c:508 +#: libpq/auth.c:506 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup matches." msgstr "IP-адреса клієнта дозволяється в \"%s\", відповідає прямому перетворенню." -#: libpq/auth.c:511 +#: libpq/auth.c:509 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup not checked." msgstr "IP-адреса клієнта дозволяється в \"%s\", пряме перетворення не перевірялося." -#: libpq/auth.c:514 +#: libpq/auth.c:512 #, c-format msgid "Client IP address resolved to \"%s\", forward lookup does not match." msgstr "IP-адреса клієнта дозволяється в \"%s\", не відповідає прямому перетворенню." -#: libpq/auth.c:517 +#: libpq/auth.c:515 #, c-format msgid "Could not translate client host name \"%s\" to IP address: %s." msgstr "Перекласти ім'я клієнтського хосту \"%s\" в IP-адресу: %s, не вдалося." -#: libpq/auth.c:522 +#: libpq/auth.c:520 #, c-format msgid "Could not resolve client IP address to a host name: %s." msgstr "Отримати ім'я хосту з IP-адреси клієнта: %s, не вдалося." #. translator: last %s describes encryption state -#: libpq/auth.c:530 +#: libpq/auth.c:528 #, c-format msgid "no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s" msgstr "в pg_hba.conf немає запису, що дозволяє підключення для реплікації з хосту \"%s\", користувача \"%s\", %s" #. translator: last %s describes encryption state -#: libpq/auth.c:538 +#: libpq/auth.c:536 #, c-format msgid "no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s" msgstr "в pg_hba.conf немає запису для хосту \"%s\", користувача \"%s\", бази даних \"%s\", %s" -#: libpq/auth.c:711 +#: libpq/auth.c:656 +#, c-format +msgid "connection authenticated: user=\"%s\" method=%s (%s:%d)" +msgstr "підключення автентифіковано: user=\"%s\" method=%s (%s:%d)" + +#: libpq/auth.c:725 #, c-format msgid "expected password response, got message type %d" msgstr "очікувалася відповід з паролем, але отримано тип повідомлення %d" -#: libpq/auth.c:732 +#: libpq/auth.c:746 #, c-format msgid "invalid password packet size" msgstr "неприпустимий розмір пакету з паролем" -#: libpq/auth.c:750 +#: libpq/auth.c:764 #, c-format msgid "empty password returned by client" msgstr "клієнт повернув пустий пароль" -#: libpq/auth.c:877 libpq/hba.c:1727 -#, c-format -msgid "MD5 authentication is not supported when \"db_user_namespace\" is enabled" -msgstr "Автентифікація MD5 не підтримується, коли увімкнуто режим \"db_user_namespace\"" - -#: libpq/auth.c:883 +#: libpq/auth.c:892 #, c-format msgid "could not generate random MD5 salt" msgstr "не вдалося створити випадкову сіль для MD5" -#: libpq/auth.c:934 libpq/be-secure-gssapi.c:540 +#: libpq/auth.c:943 libpq/be-secure-gssapi.c:540 #, c-format msgid "could not set environment: %m" msgstr "не вдалося встановити середовище: %m" -#: libpq/auth.c:973 +#: libpq/auth.c:982 #, c-format msgid "expected GSS response, got message type %d" msgstr "очікувалася відповідь GSS, але отримано тип повідомлення %d" -#: libpq/auth.c:1039 +#: libpq/auth.c:1048 msgid "accepting GSS security context failed" msgstr "прийняти контекст безпеки GSS не вдалось" -#: libpq/auth.c:1080 +#: libpq/auth.c:1089 msgid "retrieving GSS user name failed" msgstr "отримання ім'я користувача GSS не виконано" -#: libpq/auth.c:1226 +#: libpq/auth.c:1235 msgid "could not acquire SSPI credentials" msgstr "не вдалось отримати облікові дані SSPI" -#: libpq/auth.c:1251 +#: libpq/auth.c:1260 #, c-format msgid "expected SSPI response, got message type %d" msgstr "очікувалась відповідь SSPI, але отримано тип повідомлення %d" -#: libpq/auth.c:1329 +#: libpq/auth.c:1338 msgid "could not accept SSPI security context" msgstr "прийняти контекст безпеки SSPI не вдалося" -#: libpq/auth.c:1370 +#: libpq/auth.c:1379 msgid "could not get token from SSPI security context" msgstr "не вдалося отримати маркер з контексту безпеки SSPI" -#: libpq/auth.c:1506 libpq/auth.c:1525 +#: libpq/auth.c:1515 libpq/auth.c:1534 #, c-format msgid "could not translate name" msgstr "не вдалося перекласти ім'я" -#: libpq/auth.c:1538 +#: libpq/auth.c:1547 #, c-format msgid "realm name too long" msgstr "ім'я області дуже довге" -#: libpq/auth.c:1553 +#: libpq/auth.c:1562 #, c-format msgid "translated account name too long" msgstr "ім'я перекладеного облікового запису дуже довге" -#: libpq/auth.c:1732 +#: libpq/auth.c:1741 #, c-format msgid "could not create socket for Ident connection: %m" msgstr "не вдалося створити сокет для підключення до серверу Ident: %m" -#: libpq/auth.c:1747 +#: libpq/auth.c:1756 #, c-format msgid "could not bind to local address \"%s\": %m" msgstr "не вдалося прив'язатися до локальної адреси \"%s\": %m" -#: libpq/auth.c:1759 +#: libpq/auth.c:1768 #, c-format msgid "could not connect to Ident server at address \"%s\", port %s: %m" msgstr "не вдалося підключитися до Ident-серверу за адресою \"%s\", порт %s: %m" -#: libpq/auth.c:1781 +#: libpq/auth.c:1790 #, c-format msgid "could not send query to Ident server at address \"%s\", port %s: %m" msgstr "не вдалося надіслати запит до Ident -серверу за адресою \"%s\", порт %s: %m" -#: libpq/auth.c:1798 +#: libpq/auth.c:1807 #, c-format msgid "could not receive response from Ident server at address \"%s\", port %s: %m" msgstr "не вдалося отримати відповідь від Ident-серверу за адресою \"%s\", порт %s: %m" -#: libpq/auth.c:1808 +#: libpq/auth.c:1817 #, c-format msgid "invalidly formatted response from Ident server: \"%s\"" msgstr "неприпустимо форматована відповідь від Ident-серверу: \"%s\"" -#: libpq/auth.c:1861 +#: libpq/auth.c:1870 #, c-format msgid "peer authentication is not supported on this platform" msgstr "автентифікація peer не підтримується на цій платформі" -#: libpq/auth.c:1865 +#: libpq/auth.c:1874 #, c-format msgid "could not get peer credentials: %m" msgstr "не вдалося отримати облікові дані користувача через peer: %m" -#: libpq/auth.c:1877 +#: libpq/auth.c:1886 #, c-format msgid "could not look up local user ID %ld: %s" msgstr "не вдалося знайти локального користувача за ідентифікатором (%ld): %s" -#: libpq/auth.c:1979 +#: libpq/auth.c:1988 #, c-format msgid "error from underlying PAM layer: %s" msgstr "помилка у нижчому шарі PAM: %s" -#: libpq/auth.c:1990 +#: libpq/auth.c:1999 #, c-format msgid "unsupported PAM conversation %d/\"%s\"" msgstr "непідтримувана розмова PAM %d/\"%s\"" -#: libpq/auth.c:2047 +#: libpq/auth.c:2056 #, c-format msgid "could not create PAM authenticator: %s" msgstr "не вдалося створити автентифікатор PAM: %s" -#: libpq/auth.c:2058 +#: libpq/auth.c:2067 #, c-format msgid "pam_set_item(PAM_USER) failed: %s" msgstr "помилка в pam_set_item(PAM_USER): %s" -#: libpq/auth.c:2090 +#: libpq/auth.c:2099 #, c-format msgid "pam_set_item(PAM_RHOST) failed: %s" msgstr "помилка в pam_set_item(PAM_RHOST): %s" -#: libpq/auth.c:2102 +#: libpq/auth.c:2111 #, c-format msgid "pam_set_item(PAM_CONV) failed: %s" msgstr "помилка в pam_set_item(PAM_CONV): %s" -#: libpq/auth.c:2115 +#: libpq/auth.c:2124 #, c-format msgid "pam_authenticate failed: %s" msgstr "помилка в pam_authenticate: %sв" -#: libpq/auth.c:2128 +#: libpq/auth.c:2137 #, c-format msgid "pam_acct_mgmt failed: %s" msgstr "помилка в pam_acct_mgmt: %s" -#: libpq/auth.c:2139 +#: libpq/auth.c:2148 #, c-format msgid "could not release PAM authenticator: %s" msgstr "не вдалося вивільнити автентифікатор PAM: %s" -#: libpq/auth.c:2219 +#: libpq/auth.c:2228 #, c-format msgid "could not initialize LDAP: error code %d" msgstr "не вдалося ініціалізувати протокол LDAP: код помилки %d" -#: libpq/auth.c:2256 +#: libpq/auth.c:2265 #, c-format msgid "could not extract domain name from ldapbasedn" msgstr "не вдалося отримати назву домена з ldapbasedn" -#: libpq/auth.c:2264 +#: libpq/auth.c:2273 #, c-format msgid "LDAP authentication could not find DNS SRV records for \"%s\"" msgstr "Автентифікація LDAP не змогла знайти записи DNS SRV для \"%s\"" -#: libpq/auth.c:2266 +#: libpq/auth.c:2275 #, c-format msgid "Set an LDAP server name explicitly." msgstr "Встановіть назву сервера LDAP, явно." -#: libpq/auth.c:2318 +#: libpq/auth.c:2327 #, c-format msgid "could not initialize LDAP: %s" msgstr "не вдалося ініціалізувати протокол LDAP: %s" -#: libpq/auth.c:2328 +#: libpq/auth.c:2337 #, c-format msgid "ldaps not supported with this LDAP library" msgstr "протокол ldaps з поточною бібліотекою LDAP не підтримується" -#: libpq/auth.c:2336 +#: libpq/auth.c:2345 #, c-format msgid "could not initialize LDAP: %m" msgstr "не вдалося ініціалізувати протокол LDAP: %m" -#: libpq/auth.c:2346 +#: libpq/auth.c:2355 #, c-format msgid "could not set LDAP protocol version: %s" msgstr "не вдалося встановити версію протоколу LDAP: %s" -#: libpq/auth.c:2362 +#: libpq/auth.c:2371 #, c-format msgid "could not start LDAP TLS session: %s" msgstr "не вдалося почати сеанс протоколу LDAP TLS: %s" -#: libpq/auth.c:2439 +#: libpq/auth.c:2448 #, c-format msgid "LDAP server not specified, and no ldapbasedn" msgstr "Сервер LDAP не вказаний, і не ldapbasedn" -#: libpq/auth.c:2446 +#: libpq/auth.c:2455 #, c-format msgid "LDAP server not specified" msgstr "LDAP-сервер не вказаний" -#: libpq/auth.c:2508 +#: libpq/auth.c:2517 #, c-format msgid "invalid character in user name for LDAP authentication" msgstr "неприпустимий символ в імені користувача для автентифікації LDAP" -#: libpq/auth.c:2525 +#: libpq/auth.c:2534 #, c-format msgid "could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s" msgstr "не вдалося виконати початкову прив'язку LDAP для ldapbinddn \"%s\" на сервері \"%s\": %s" -#: libpq/auth.c:2555 +#: libpq/auth.c:2564 #, c-format msgid "could not search LDAP for filter \"%s\" on server \"%s\": %s" msgstr "не вдалося виконати LDAP-пошук за фільтром \"%s\" на сервері \"%s\": %s" -#: libpq/auth.c:2571 +#: libpq/auth.c:2580 #, c-format msgid "LDAP user \"%s\" does not exist" msgstr "LDAP-користувач \"%s\" не існує" -#: libpq/auth.c:2572 +#: libpq/auth.c:2581 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned no entries." msgstr "LDAP-пошук за фільтром \"%s\" на сервері \"%s\" не повернув записів." -#: libpq/auth.c:2576 +#: libpq/auth.c:2585 #, c-format msgid "LDAP user \"%s\" is not unique" msgstr "LDAP-користувач \"%s\" не унікальний" -#: libpq/auth.c:2577 +#: libpq/auth.c:2586 #, c-format msgid "LDAP search for filter \"%s\" on server \"%s\" returned %d entry." msgid_plural "LDAP search for filter \"%s\" on server \"%s\" returned %d entries." @@ -14483,137 +14924,132 @@ msgstr[1] "LDAP-пошук за фільтром \"%s\" на сервері \"%s msgstr[2] "LDAP-пошук за фільтром \"%s\" на сервері \"%s\" повернув %d записів." msgstr[3] "LDAP-пошук за фільтром \"%s\" на сервері \"%s\" повернув %d записів." -#: libpq/auth.c:2597 +#: libpq/auth.c:2606 #, c-format msgid "could not get dn for the first entry matching \"%s\" on server \"%s\": %s" msgstr "не вдалося отримати dn для першого результату, що відповідає \"%s\" на сервері \"%s\": %s" -#: libpq/auth.c:2618 -#, c-format -msgid "could not unbind after searching for user \"%s\" on server \"%s\"" -msgstr "не вдалося відв'язатись після пошуку користувача \"%s\" на сервері \"%s\"" - -#: libpq/auth.c:2649 +#: libpq/auth.c:2633 #, c-format msgid "LDAP login failed for user \"%s\" on server \"%s\": %s" msgstr "Помилка під час реєстрації в протоколі LDAP користувача \"%s\" на сервері \"%s\": %s" -#: libpq/auth.c:2681 +#: libpq/auth.c:2665 #, c-format msgid "LDAP diagnostics: %s" msgstr "Діагностика LDAP: %s" -#: libpq/auth.c:2719 +#: libpq/auth.c:2703 #, c-format msgid "certificate authentication failed for user \"%s\": client certificate contains no user name" msgstr "помилка автентифікації сертифіката для користувача \"%s\": сертифікат клієнта не містить імені користувача" -#: libpq/auth.c:2740 +#: libpq/auth.c:2724 #, c-format msgid "certificate authentication failed for user \"%s\": unable to retrieve subject DN" msgstr "помилка автентифікації сертифікату для користувача \"%s\": не вдалося отримати DN суб'єкта" -#: libpq/auth.c:2763 +#: libpq/auth.c:2747 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch" msgstr "помилка перевірки сертифікату (clientcert=verify-full) для користувача \"%s\": DN невідповідність" -#: libpq/auth.c:2768 +#: libpq/auth.c:2752 #, c-format msgid "certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch" msgstr "помилка перевірки сертифікату (clientcert=verify-full) для користувача \"%s\": CN невідповідність" -#: libpq/auth.c:2870 +#: libpq/auth.c:2854 #, c-format msgid "RADIUS server not specified" msgstr "RADIUS-сервер не вказаний" -#: libpq/auth.c:2877 +#: libpq/auth.c:2861 #, c-format msgid "RADIUS secret not specified" msgstr "Секрет RADIUS не вказаний" -#: libpq/auth.c:2891 +#: libpq/auth.c:2875 #, c-format msgid "RADIUS authentication does not support passwords longer than %d characters" msgstr "Автентифікація RADIUS не підтримує паролі довші ніж %d символів" -#: libpq/auth.c:2993 libpq/hba.c:2369 +#: libpq/auth.c:2977 libpq/hba.c:2352 #, c-format msgid "could not translate RADIUS server name \"%s\" to address: %s" msgstr "не вдалося перетворити ім'я серверу RADIUS \"%s\" в адресу: %s" -#: libpq/auth.c:3007 +#: libpq/auth.c:2991 #, c-format msgid "could not generate random encryption vector" msgstr "не вдалося створити випадковий вектор шифрування" -#: libpq/auth.c:3044 +#: libpq/auth.c:3028 #, c-format msgid "could not perform MD5 encryption of password: %s" msgstr "не вдалося виконати MD5 шифрування паролю: %s" -#: libpq/auth.c:3071 +#: libpq/auth.c:3055 #, c-format msgid "could not create RADIUS socket: %m" msgstr "не вдалося створити сокет RADIUS: %m" -#: libpq/auth.c:3087 +#: libpq/auth.c:3071 #, c-format msgid "could not bind local RADIUS socket: %m" msgstr "не вдалося прив'язатися до локального сокету RADIUS: %m" -#: libpq/auth.c:3097 +#: libpq/auth.c:3081 #, c-format msgid "could not send RADIUS packet: %m" msgstr "не вдалося відправити пакет RADIUS: %m" -#: libpq/auth.c:3131 libpq/auth.c:3157 +#: libpq/auth.c:3115 libpq/auth.c:3141 #, c-format msgid "timeout waiting for RADIUS response from %s" msgstr "перевищено час очікування відповіді RADIUS від %s" -#: libpq/auth.c:3150 +#: libpq/auth.c:3134 #, c-format msgid "could not check status on RADIUS socket: %m" msgstr "не вдалося перевірити статус сокету RADIUS: %m" -#: libpq/auth.c:3180 +#: libpq/auth.c:3164 #, c-format msgid "could not read RADIUS response: %m" msgstr "не вдалося прочитати відповідь RADIUS: %m" -#: libpq/auth.c:3188 +#: libpq/auth.c:3172 #, c-format msgid "RADIUS response from %s was sent from incorrect port: %d" msgstr "Відповідь RADIUS від %s була відправлена з неправильного порту: %d" -#: libpq/auth.c:3196 +#: libpq/auth.c:3180 #, c-format msgid "RADIUS response from %s too short: %d" msgstr "Занадто коротка відповідь RADIUS від %s: %d" -#: libpq/auth.c:3203 +#: libpq/auth.c:3187 #, c-format msgid "RADIUS response from %s has corrupt length: %d (actual length %d)" msgstr "У відповіді RADIUS від %s покшоджена довжина: %d (фактична довжина %d)" -#: libpq/auth.c:3211 +#: libpq/auth.c:3195 #, c-format msgid "RADIUS response from %s is to a different request: %d (should be %d)" msgstr "Прийшла відповідь RADIUS від %s на інший запит: %d (очікувалася %d)" -#: libpq/auth.c:3236 +#: libpq/auth.c:3220 #, c-format msgid "could not perform MD5 encryption of received packet: %s" msgstr "не вдалося виконати MD5 шифрування отриманого пакету: %s" -#: libpq/auth.c:3246 +#: libpq/auth.c:3230 #, c-format msgid "RADIUS response from %s has incorrect MD5 signature" msgstr "Відповідь RADIUS від %s має неправильний підпис MD5" -#: libpq/auth.c:3264 +#: libpq/auth.c:3248 #, c-format msgid "RADIUS response from %s has invalid code (%d) for user \"%s\"" msgstr "Відповідь RADIUS від %s має неприпустимий код (%d) для користувача \"%s\"" @@ -14670,50 +15106,37 @@ msgstr "не вдалося написати файл сервера \"%s\": %m" msgid "large object read request is too large" msgstr "запит на читання великого об'єкту має завеликий розмір" -#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:262 utils/adt/genfile.c:294 -#: utils/adt/genfile.c:315 +#: libpq/be-fsstubs.c:816 utils/adt/genfile.c:248 utils/adt/genfile.c:269 #, c-format msgid "requested length cannot be negative" msgstr "запитувана довжина не може бути негативною" -#: libpq/be-fsstubs.c:871 storage/large_object/inv_api.c:298 -#: storage/large_object/inv_api.c:310 storage/large_object/inv_api.c:507 -#: storage/large_object/inv_api.c:618 storage/large_object/inv_api.c:808 -#, c-format -msgid "permission denied for large object %u" -msgstr "немає дозволу для великого об'єкта %u" - -#: libpq/be-secure-common.c:71 -#, c-format -msgid "could not read from command \"%s\": %m" -msgstr "не вдалося прочитати висновок команди \"%s\": %m" - -#: libpq/be-secure-common.c:91 +#: libpq/be-secure-common.c:94 #, c-format msgid "command \"%s\" failed" msgstr "помилка команди \"%s\"" -#: libpq/be-secure-common.c:119 +#: libpq/be-secure-common.c:123 #, c-format msgid "could not access private key file \"%s\": %m" msgstr "не вдалось отримати доступ до файла закритиго ключа \"%s\": %m" -#: libpq/be-secure-common.c:129 +#: libpq/be-secure-common.c:133 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "файл закритого ключа \"%s\" не є звичайним" -#: libpq/be-secure-common.c:155 +#: libpq/be-secure-common.c:159 #, c-format msgid "private key file \"%s\" must be owned by the database user or root" msgstr "файл закритого ключа \"%s\" повинен належати користувачу бази даних або коріня" -#: libpq/be-secure-common.c:165 +#: libpq/be-secure-common.c:169 #, c-format msgid "private key file \"%s\" has group or world access" msgstr "до файлу закритого ключа \"%s\" мають доступ група або всі" -#: libpq/be-secure-common.c:167 +#: libpq/be-secure-common.c:171 #, c-format msgid "File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root." msgstr "Файл повинен мати дозволи u=rw (0600) або менше, якщо він належить користувачу бази даних, або u=rw,g=r (0640) або менше, якщо він належить кореню." @@ -14759,1077 +15182,1055 @@ msgstr "не вдалося прийняти контекст безпеки GSS msgid "GSSAPI size check error" msgstr "помилка перевірки розміру GSSAPI" -#: libpq/be-secure-openssl.c:125 +#: libpq/be-secure-openssl.c:131 #, c-format msgid "could not create SSL context: %s" msgstr "не вдалося створити контекст SSL: %s" -#: libpq/be-secure-openssl.c:151 +#: libpq/be-secure-openssl.c:157 #, c-format msgid "could not load server certificate file \"%s\": %s" msgstr "не вдалося завантажити сертифікат серверу \"%s\": %s" -#: libpq/be-secure-openssl.c:171 +#: libpq/be-secure-openssl.c:177 #, c-format msgid "private key file \"%s\" cannot be reloaded because it requires a passphrase" msgstr "файл закритого ключа \"%s\" не можна перезавантажити, тому що це потребує парольну фразу" -#: libpq/be-secure-openssl.c:176 +#: libpq/be-secure-openssl.c:182 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "не вдалось завантажити файл закритого ключа \"%s\": %s" -#: libpq/be-secure-openssl.c:185 +#: libpq/be-secure-openssl.c:191 #, c-format msgid "check of private key failed: %s" msgstr "помилка під час перевірки приватного ключа: %s" #. translator: first %s is a GUC option name, second %s is its value -#: libpq/be-secure-openssl.c:198 libpq/be-secure-openssl.c:221 +#: libpq/be-secure-openssl.c:204 libpq/be-secure-openssl.c:227 #, c-format msgid "\"%s\" setting \"%s\" not supported by this build" msgstr "\"%s\" налаштування \"%s\" не підтримується цією збіркою" -#: libpq/be-secure-openssl.c:208 +#: libpq/be-secure-openssl.c:214 #, c-format msgid "could not set minimum SSL protocol version" msgstr "не вдалося встановити мінімальну версію протоколу SSL" -#: libpq/be-secure-openssl.c:231 +#: libpq/be-secure-openssl.c:237 #, c-format msgid "could not set maximum SSL protocol version" msgstr "не вдалося встановити максимальну версію протоколу SSL" -#: libpq/be-secure-openssl.c:247 +#: libpq/be-secure-openssl.c:253 #, c-format msgid "could not set SSL protocol version range" msgstr "не вдалося встановити діапазон версій протоколу SSL" -#: libpq/be-secure-openssl.c:248 +#: libpq/be-secure-openssl.c:254 #, c-format msgid "\"%s\" cannot be higher than \"%s\"" msgstr "\"%s\" не може бути більше, ніж \"%s\"" -#: libpq/be-secure-openssl.c:285 +#: libpq/be-secure-openssl.c:307 #, c-format msgid "could not set the cipher list (no valid ciphers available)" msgstr "не вдалося встановити список шифрів (немає дійсних шифрів)" -#: libpq/be-secure-openssl.c:305 +#: libpq/be-secure-openssl.c:327 #, c-format msgid "could not load root certificate file \"%s\": %s" msgstr "не вдалося завантажити файл кореневого сертифікату \"%s\": %s" -#: libpq/be-secure-openssl.c:354 +#: libpq/be-secure-openssl.c:376 #, c-format msgid "could not load SSL certificate revocation list file \"%s\": %s" msgstr "не вдалося завантажити файл зі списком відкликаних сертифікатів SSL \"%s\": %s" -#: libpq/be-secure-openssl.c:362 +#: libpq/be-secure-openssl.c:384 #, c-format msgid "could not load SSL certificate revocation list directory \"%s\": %s" msgstr "не вдалося завантажити каталог списку відкликаних сертифікатів SSL \"%s\": %s" -#: libpq/be-secure-openssl.c:370 +#: libpq/be-secure-openssl.c:392 #, c-format msgid "could not load SSL certificate revocation list file \"%s\" or directory \"%s\": %s" msgstr "не вдалося завантажити файл \"%s\" або каталог \"%s\" списку відкликаних сертифікатів SSL: %s" -#: libpq/be-secure-openssl.c:428 +#: libpq/be-secure-openssl.c:450 #, c-format msgid "could not initialize SSL connection: SSL context not set up" msgstr "не вдалося ініціалізувати SSL-підключення: контекст SSL не встановлений" -#: libpq/be-secure-openssl.c:439 +#: libpq/be-secure-openssl.c:464 #, c-format msgid "could not initialize SSL connection: %s" msgstr "не вдалося ініціалізувати SSL-підключення: %s" -#: libpq/be-secure-openssl.c:447 +#: libpq/be-secure-openssl.c:472 #, c-format msgid "could not set SSL socket: %s" msgstr "не вдалося встановити SSL-сокет: %s" -#: libpq/be-secure-openssl.c:503 +#: libpq/be-secure-openssl.c:528 #, c-format msgid "could not accept SSL connection: %m" msgstr "не вдалося прийняти SSL-підключення: %m" -#: libpq/be-secure-openssl.c:507 libpq/be-secure-openssl.c:562 +#: libpq/be-secure-openssl.c:532 libpq/be-secure-openssl.c:589 #, c-format msgid "could not accept SSL connection: EOF detected" msgstr "не вдалося прийняти SSL-підключення: виявлений EOF" -#: libpq/be-secure-openssl.c:546 +#: libpq/be-secure-openssl.c:573 #, c-format msgid "could not accept SSL connection: %s" msgstr "не вдалося отримати підключення SSL: %s" -#: libpq/be-secure-openssl.c:550 +#: libpq/be-secure-openssl.c:577 #, c-format msgid "This may indicate that the client does not support any SSL protocol version between %s and %s." msgstr "Це може вказувати, що клієнт не підтримує жодної версії протоколу SSL між %s і %s." -#: libpq/be-secure-openssl.c:567 libpq/be-secure-openssl.c:756 -#: libpq/be-secure-openssl.c:826 +#: libpq/be-secure-openssl.c:594 libpq/be-secure-openssl.c:809 +#: libpq/be-secure-openssl.c:879 #, c-format msgid "unrecognized SSL error code: %d" msgstr "нерозпізнаний код помилки SSL: %d" -#: libpq/be-secure-openssl.c:613 +#: libpq/be-secure-openssl.c:622 +#, c-format +msgid "received SSL connection request with unexpected ALPN protocol" +msgstr "" + +#: libpq/be-secure-openssl.c:666 #, c-format msgid "SSL certificate's common name contains embedded null" msgstr "Спільне ім'я SSL-сертифікату містить нульовий байт" -#: libpq/be-secure-openssl.c:659 +#: libpq/be-secure-openssl.c:712 #, c-format msgid "SSL certificate's distinguished name contains embedded null" msgstr "Унікальна назва сертифікату SSL містить вбудоване null-значення" -#: libpq/be-secure-openssl.c:745 libpq/be-secure-openssl.c:810 +#: libpq/be-secure-openssl.c:798 libpq/be-secure-openssl.c:863 #, c-format msgid "SSL error: %s" msgstr "Помилка SSL: %s" -#: libpq/be-secure-openssl.c:987 +#: libpq/be-secure-openssl.c:1038 #, c-format msgid "could not open DH parameters file \"%s\": %m" msgstr "не вдалося відкрити файл параметрів DH \"%s\": %m" -#: libpq/be-secure-openssl.c:999 +#: libpq/be-secure-openssl.c:1050 #, c-format msgid "could not load DH parameters file: %s" msgstr "не вдалося завантажити файл параметрів DH: %s" -#: libpq/be-secure-openssl.c:1009 +#: libpq/be-secure-openssl.c:1060 #, c-format msgid "invalid DH parameters: %s" msgstr "неприпустимі параметри DH: %s" -#: libpq/be-secure-openssl.c:1018 +#: libpq/be-secure-openssl.c:1069 #, c-format msgid "invalid DH parameters: p is not prime" msgstr "неприпустимі параметри DH: р - не штрих" -#: libpq/be-secure-openssl.c:1027 +#: libpq/be-secure-openssl.c:1078 #, c-format msgid "invalid DH parameters: neither suitable generator or safe prime" msgstr "неприпустимі параметри DH: немає придатного генератора або безпечного штриха" -#: libpq/be-secure-openssl.c:1163 +#: libpq/be-secure-openssl.c:1214 #, c-format msgid "Client certificate verification failed at depth %d: %s." msgstr "Не вдалося перевірити сертифікат клієнта на глибині %d: %s." -#: libpq/be-secure-openssl.c:1200 +#: libpq/be-secure-openssl.c:1251 #, c-format msgid "Failed certificate data (unverified): subject \"%s\", serial number %s, issuer \"%s\"." msgstr "Помилкові дані сертифіката (неперевірені): тема \"%s\", серійний номер %s, емітент \"%s\"." -#: libpq/be-secure-openssl.c:1201 +#: libpq/be-secure-openssl.c:1252 msgid "unknown" msgstr "невідомо" -#: libpq/be-secure-openssl.c:1292 +#: libpq/be-secure-openssl.c:1389 #, c-format msgid "DH: could not load DH parameters" msgstr "DH: не вдалося завантажити параметри DH" -#: libpq/be-secure-openssl.c:1300 +#: libpq/be-secure-openssl.c:1397 #, c-format msgid "DH: could not set DH parameters: %s" msgstr "DH: не вдалося встановити параметри DH: %s" -#: libpq/be-secure-openssl.c:1327 +#: libpq/be-secure-openssl.c:1424 #, c-format msgid "ECDH: unrecognized curve name: %s" msgstr "ECDH: нерозпізнане ім'я кривої: %s" -#: libpq/be-secure-openssl.c:1336 +#: libpq/be-secure-openssl.c:1433 #, c-format msgid "ECDH: could not create key" msgstr "ECDH: не вдалося створити ключ" -#: libpq/be-secure-openssl.c:1364 +#: libpq/be-secure-openssl.c:1461 msgid "no SSL error reported" msgstr "немає повідомлення про помилку SSL" -#: libpq/be-secure-openssl.c:1368 +#: libpq/be-secure-openssl.c:1479 #, c-format msgid "SSL error code %lu" msgstr "Код помилки SSL %lu" -#: libpq/be-secure-openssl.c:1527 +#: libpq/be-secure-openssl.c:1636 #, c-format msgid "could not create BIO" msgstr "неможливо створити BIO" -#: libpq/be-secure-openssl.c:1537 +#: libpq/be-secure-openssl.c:1646 #, c-format msgid "could not get NID for ASN1_OBJECT object" msgstr "не вдалося отримати NID для об'єкту ASN1_OBJECT" -#: libpq/be-secure-openssl.c:1545 +#: libpq/be-secure-openssl.c:1654 #, c-format msgid "could not convert NID %d to an ASN1_OBJECT structure" msgstr "не вдалося перетворити NID %d в структуру ASN1_OBJECT" -#: libpq/be-secure.c:207 libpq/be-secure.c:303 -#, c-format -msgid "terminating connection due to unexpected postmaster exit" -msgstr "завершення підключення через неочікуване закриття головного процесу" - -#: libpq/crypt.c:49 +#: libpq/crypt.c:48 #, c-format msgid "Role \"%s\" does not exist." msgstr "Роль \"%s\" не існує." -#: libpq/crypt.c:59 +#: libpq/crypt.c:58 #, c-format msgid "User \"%s\" has no password assigned." msgstr "Користувач \"%s\" не має пароля." -#: libpq/crypt.c:77 +#: libpq/crypt.c:76 #, c-format msgid "User \"%s\" has an expired password." msgstr "Користувач \"%s\" має прострочений пароль." -#: libpq/crypt.c:183 +#: libpq/crypt.c:182 #, c-format msgid "User \"%s\" has a password that cannot be used with MD5 authentication." msgstr "Користувач \"%s\" має пароль, який не можна використовувати з автентифікацією MD5." -#: libpq/crypt.c:204 libpq/crypt.c:246 libpq/crypt.c:266 +#: libpq/crypt.c:203 libpq/crypt.c:245 libpq/crypt.c:265 #, c-format msgid "Password does not match for user \"%s\"." msgstr "Пароль не підходить для користувача \"%s\"." -#: libpq/crypt.c:285 +#: libpq/crypt.c:284 #, c-format msgid "Password of user \"%s\" is in unrecognized format." msgstr "Пароль користувача \"%s\" представлений в нерозпізнаному форматі." -#: libpq/hba.c:332 +#: libpq/hba.c:327 #, c-format msgid "invalid regular expression \"%s\": %s" msgstr "недійсний регулярний вираз \"%s\": %s" -#: libpq/hba.c:334 libpq/hba.c:666 libpq/hba.c:1250 libpq/hba.c:1270 -#: libpq/hba.c:1293 libpq/hba.c:1306 libpq/hba.c:1359 libpq/hba.c:1387 -#: libpq/hba.c:1395 libpq/hba.c:1407 libpq/hba.c:1428 libpq/hba.c:1441 -#: libpq/hba.c:1466 libpq/hba.c:1493 libpq/hba.c:1505 libpq/hba.c:1564 -#: libpq/hba.c:1584 libpq/hba.c:1598 libpq/hba.c:1618 libpq/hba.c:1629 -#: libpq/hba.c:1644 libpq/hba.c:1663 libpq/hba.c:1679 libpq/hba.c:1691 -#: libpq/hba.c:1728 libpq/hba.c:1769 libpq/hba.c:1782 libpq/hba.c:1804 -#: libpq/hba.c:1816 libpq/hba.c:1834 libpq/hba.c:1884 libpq/hba.c:1928 -#: libpq/hba.c:1939 libpq/hba.c:1955 libpq/hba.c:1972 libpq/hba.c:1983 -#: libpq/hba.c:2002 libpq/hba.c:2018 libpq/hba.c:2034 libpq/hba.c:2093 -#: libpq/hba.c:2110 libpq/hba.c:2123 libpq/hba.c:2135 libpq/hba.c:2154 -#: libpq/hba.c:2240 libpq/hba.c:2258 libpq/hba.c:2352 libpq/hba.c:2371 -#: libpq/hba.c:2400 libpq/hba.c:2413 libpq/hba.c:2436 libpq/hba.c:2458 -#: libpq/hba.c:2472 tsearch/ts_locale.c:243 +#: libpq/hba.c:329 libpq/hba.c:661 libpq/hba.c:1245 libpq/hba.c:1265 +#: libpq/hba.c:1288 libpq/hba.c:1301 libpq/hba.c:1354 libpq/hba.c:1382 +#: libpq/hba.c:1390 libpq/hba.c:1402 libpq/hba.c:1423 libpq/hba.c:1436 +#: libpq/hba.c:1461 libpq/hba.c:1488 libpq/hba.c:1500 libpq/hba.c:1559 +#: libpq/hba.c:1579 libpq/hba.c:1593 libpq/hba.c:1613 libpq/hba.c:1624 +#: libpq/hba.c:1639 libpq/hba.c:1658 libpq/hba.c:1674 libpq/hba.c:1686 +#: libpq/hba.c:1752 libpq/hba.c:1765 libpq/hba.c:1787 libpq/hba.c:1799 +#: libpq/hba.c:1817 libpq/hba.c:1867 libpq/hba.c:1911 libpq/hba.c:1922 +#: libpq/hba.c:1938 libpq/hba.c:1955 libpq/hba.c:1966 libpq/hba.c:1985 +#: libpq/hba.c:2001 libpq/hba.c:2017 libpq/hba.c:2076 libpq/hba.c:2093 +#: libpq/hba.c:2106 libpq/hba.c:2118 libpq/hba.c:2137 libpq/hba.c:2223 +#: libpq/hba.c:2241 libpq/hba.c:2335 libpq/hba.c:2354 libpq/hba.c:2383 +#: libpq/hba.c:2396 libpq/hba.c:2419 libpq/hba.c:2441 libpq/hba.c:2455 +#: tsearch/ts_locale.c:241 #, c-format msgid "line %d of configuration file \"%s\"" msgstr "рядок %d файла конфігурації \"%s\"" -#: libpq/hba.c:462 +#: libpq/hba.c:457 #, c-format msgid "skipping missing authentication file \"%s\"" msgstr "пропускається відсутній файл автентифікації \"%s\"" -#: libpq/hba.c:614 +#: libpq/hba.c:609 #, c-format msgid "could not open file \"%s\": maximum nesting depth exceeded" msgstr "не вдалося відкрити файл \"%s\": максимальну глибину вкладення перевищено" -#: libpq/hba.c:1221 +#: libpq/hba.c:1216 #, c-format msgid "error enumerating network interfaces: %m" msgstr "помилка перерахування мережевих інтерфейсів: %m" #. translator: the second %s is a list of auth methods -#: libpq/hba.c:1248 +#: libpq/hba.c:1243 #, c-format msgid "authentication option \"%s\" is only valid for authentication methods %s" msgstr "параметр автентифікації \"%s\" припустимий лише для способів автентифікації %s" -#: libpq/hba.c:1268 +#: libpq/hba.c:1263 #, c-format msgid "authentication method \"%s\" requires argument \"%s\" to be set" msgstr "спосіб автентифікації \"%s\" потребує аргумент \"%s\" для встановлення" -#: libpq/hba.c:1292 +#: libpq/hba.c:1287 #, c-format msgid "missing entry at end of line" msgstr "відсутній запис в кінці рядка" -#: libpq/hba.c:1305 +#: libpq/hba.c:1300 #, c-format msgid "multiple values in ident field" msgstr "кілька значень в полі ident" -#: libpq/hba.c:1357 +#: libpq/hba.c:1352 #, c-format msgid "multiple values specified for connection type" msgstr "кілька значень вказано для типу підключення" -#: libpq/hba.c:1358 +#: libpq/hba.c:1353 #, c-format msgid "Specify exactly one connection type per line." msgstr "Вкажіть в рядку єдиний тип підключення." -#: libpq/hba.c:1385 +#: libpq/hba.c:1380 #, c-format msgid "hostssl record cannot match because SSL is disabled" msgstr "запис hostssl не збігається, тому що протокол SSL вимкнутий" -#: libpq/hba.c:1386 +#: libpq/hba.c:1381 #, c-format -msgid "Set ssl = on in postgresql.conf." -msgstr "Встановіть ssl = on в postgresql.conf." +msgid "Set \"ssl = on\" in postgresql.conf." +msgstr "" -#: libpq/hba.c:1394 +#: libpq/hba.c:1389 #, c-format msgid "hostssl record cannot match because SSL is not supported by this build" msgstr "запис hostssl не збігається, тому що SSL не підтримується цією збіркою" -#: libpq/hba.c:1406 +#: libpq/hba.c:1401 #, c-format msgid "hostgssenc record cannot match because GSSAPI is not supported by this build" msgstr "запис hostgssenc не може збігатись, оскільки GSSAPI не підтримується цією збіркою" -#: libpq/hba.c:1426 +#: libpq/hba.c:1421 #, c-format msgid "invalid connection type \"%s\"" msgstr "неприпустимий тип підключення \"%s\"" -#: libpq/hba.c:1440 +#: libpq/hba.c:1435 #, c-format msgid "end-of-line before database specification" msgstr "кінець рядка перед визначенням бази даних" -#: libpq/hba.c:1465 +#: libpq/hba.c:1460 #, c-format msgid "end-of-line before role specification" msgstr "кінець рядка перед визначенням ролі" -#: libpq/hba.c:1492 +#: libpq/hba.c:1487 #, c-format msgid "end-of-line before IP address specification" msgstr "кінець рядка перед визначенням IP-адрес" -#: libpq/hba.c:1503 +#: libpq/hba.c:1498 #, c-format msgid "multiple values specified for host address" msgstr "для адреси хоста вказано кілька значень" -#: libpq/hba.c:1504 +#: libpq/hba.c:1499 #, c-format msgid "Specify one address range per line." msgstr "Вкажіть один діапазон адреси в рядку." -#: libpq/hba.c:1562 +#: libpq/hba.c:1557 #, c-format msgid "invalid IP address \"%s\": %s" msgstr "неприпустима IP адреса \"%s\": %s" -#: libpq/hba.c:1582 +#: libpq/hba.c:1577 #, c-format msgid "specifying both host name and CIDR mask is invalid: \"%s\"" msgstr "визначити одночасно ім’я хоста і маску CIDR не можна: \"%s\"" -#: libpq/hba.c:1596 +#: libpq/hba.c:1591 #, c-format msgid "invalid CIDR mask in address \"%s\"" msgstr "неприпустима маска CIDR в адресі \"%s\"" -#: libpq/hba.c:1616 +#: libpq/hba.c:1611 #, c-format msgid "end-of-line before netmask specification" msgstr "кінець рядка перед визначенням маски мережі" -#: libpq/hba.c:1617 +#: libpq/hba.c:1612 #, c-format msgid "Specify an address range in CIDR notation, or provide a separate netmask." msgstr "Вкажіть діапазон адрес в нотації CIDR або надайте окрему маску мережі." -#: libpq/hba.c:1628 +#: libpq/hba.c:1623 #, c-format msgid "multiple values specified for netmask" msgstr "для маски мережі вказано декілька значень" -#: libpq/hba.c:1642 +#: libpq/hba.c:1637 #, c-format msgid "invalid IP mask \"%s\": %s" msgstr "неприпустима маска IP \"%s\": %s" -#: libpq/hba.c:1662 +#: libpq/hba.c:1657 #, c-format msgid "IP address and mask do not match" msgstr "IP-адреса і маска не збігаються" -#: libpq/hba.c:1678 +#: libpq/hba.c:1673 #, c-format msgid "end-of-line before authentication method" msgstr "кінець рядка перед способом автентифікації" -#: libpq/hba.c:1689 +#: libpq/hba.c:1684 #, c-format msgid "multiple values specified for authentication type" msgstr "для типу автентифікації вказано декілька значень" -#: libpq/hba.c:1690 +#: libpq/hba.c:1685 #, c-format msgid "Specify exactly one authentication type per line." msgstr "Вкажіть у рядку єдиний тип автентифікації." -#: libpq/hba.c:1767 +#: libpq/hba.c:1750 #, c-format msgid "invalid authentication method \"%s\"" msgstr "неприпустимий спосіб автентифікації \"%s\"" -#: libpq/hba.c:1780 +#: libpq/hba.c:1763 #, c-format msgid "invalid authentication method \"%s\": not supported by this build" msgstr "неприпустимий спосіб автентифікації \"%s\": не підтримується цією збіркою" -#: libpq/hba.c:1803 +#: libpq/hba.c:1786 #, c-format msgid "gssapi authentication is not supported on local sockets" msgstr "автентифікація gssapi для локальних сокетів не підтримується" -#: libpq/hba.c:1815 +#: libpq/hba.c:1798 #, c-format msgid "peer authentication is only supported on local sockets" msgstr "автентифікація peer підтримується лише для локальних сокетів" -#: libpq/hba.c:1833 +#: libpq/hba.c:1816 #, c-format msgid "cert authentication is only supported on hostssl connections" msgstr "автентифікація cert підтримується лише для підключень hostssl" -#: libpq/hba.c:1883 +#: libpq/hba.c:1866 #, c-format msgid "authentication option not in name=value format: %s" msgstr "параметр автентифікації вказаний не в форматі ім’я=значення: %s" -#: libpq/hba.c:1927 +#: libpq/hba.c:1910 #, c-format msgid "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix" msgstr "не можна використовувати ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter або ldapurl разом з ldapprefix" -#: libpq/hba.c:1938 +#: libpq/hba.c:1921 #, c-format msgid "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set" msgstr "спосіб автентифікації \"ldap\" потребує встановити аргумент \"ldapbasedn\", \"ldapprefix\" або \"ldapsuffix\"" -#: libpq/hba.c:1954 +#: libpq/hba.c:1937 #, c-format msgid "cannot use ldapsearchattribute together with ldapsearchfilter" msgstr "не можна використовувати ldapsearchattribute разом з ldapsearchfilter" -#: libpq/hba.c:1971 +#: libpq/hba.c:1954 #, c-format msgid "list of RADIUS servers cannot be empty" msgstr "список серверів RADIUS не може бути порожнім" -#: libpq/hba.c:1982 +#: libpq/hba.c:1965 #, c-format msgid "list of RADIUS secrets cannot be empty" msgstr "список секретів RADIUS не може бути порожнім" -#: libpq/hba.c:1999 +#: libpq/hba.c:1982 #, c-format msgid "the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "кількість секретів RADIUS (%d) повинна бути 1 або дорівнювати кількості серверів RADIUS (%d)" -#: libpq/hba.c:2015 +#: libpq/hba.c:1998 #, c-format msgid "the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "кількість портів RADIUS (%d) повинна бути 1 або дорівнювати кількості серверів RADIUS (%d)" -#: libpq/hba.c:2031 +#: libpq/hba.c:2014 #, c-format msgid "the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)" msgstr "кількість ідентифікаторів RADIUS (%d) повинна бути 1 або дорівнювати кількості серверів RADIUS (%d)" -#: libpq/hba.c:2083 +#: libpq/hba.c:2066 msgid "ident, peer, gssapi, sspi, and cert" msgstr "ident, peer, gssapi, sspi і cert" -#: libpq/hba.c:2092 +#: libpq/hba.c:2075 #, c-format msgid "clientcert can only be configured for \"hostssl\" rows" msgstr "clientcert може бути налаштовано лише для рядків \"hostssl\"" -#: libpq/hba.c:2109 +#: libpq/hba.c:2092 #, c-format msgid "clientcert only accepts \"verify-full\" when using \"cert\" authentication" msgstr "clientcert приймає лише \"verify-full\" під час використання автентифікації \"cert\"" -#: libpq/hba.c:2122 +#: libpq/hba.c:2105 #, c-format msgid "invalid value for clientcert: \"%s\"" msgstr "неприпустиме значення для clientcert: \"%s\"" -#: libpq/hba.c:2134 +#: libpq/hba.c:2117 #, c-format msgid "clientname can only be configured for \"hostssl\" rows" msgstr "clientname можна налаштувати лише для рядків \"hostssl\"" -#: libpq/hba.c:2153 +#: libpq/hba.c:2136 #, c-format msgid "invalid value for clientname: \"%s\"" msgstr "неприпустиме значення для clientname: \"%s\"" -#: libpq/hba.c:2186 +#: libpq/hba.c:2169 #, c-format msgid "could not parse LDAP URL \"%s\": %s" msgstr "не вдалося аналізувати URL-адресу LDAP \"%s\": %s" -#: libpq/hba.c:2197 +#: libpq/hba.c:2180 #, c-format msgid "unsupported LDAP URL scheme: %s" msgstr "непідтримувана схема в URL-адресі LDAP: %s" -#: libpq/hba.c:2221 +#: libpq/hba.c:2204 #, c-format msgid "LDAP URLs not supported on this platform" msgstr "URL-адреса LDAP не підтримується на цій платформі" -#: libpq/hba.c:2239 +#: libpq/hba.c:2222 #, c-format msgid "invalid ldapscheme value: \"%s\"" msgstr "недійсне значення ldapscheme: \"%s\"" -#: libpq/hba.c:2257 +#: libpq/hba.c:2240 #, c-format msgid "invalid LDAP port number: \"%s\"" msgstr "недійсний номер порту LDAP: \"%s\"" -#: libpq/hba.c:2303 libpq/hba.c:2310 +#: libpq/hba.c:2286 libpq/hba.c:2293 msgid "gssapi and sspi" msgstr "gssapi і sspi" -#: libpq/hba.c:2319 libpq/hba.c:2328 +#: libpq/hba.c:2302 libpq/hba.c:2311 msgid "sspi" msgstr "sspi" -#: libpq/hba.c:2350 +#: libpq/hba.c:2333 #, c-format msgid "could not parse RADIUS server list \"%s\"" msgstr "не вдалося проаналізувати список серверів RADIUS \"%s\"" -#: libpq/hba.c:2398 +#: libpq/hba.c:2381 #, c-format msgid "could not parse RADIUS port list \"%s\"" msgstr "не вдалося проаналізувати список портів RADIUS \"%s\"" -#: libpq/hba.c:2412 +#: libpq/hba.c:2395 #, c-format msgid "invalid RADIUS port number: \"%s\"" msgstr "недійсний номер порту RADIUS: \"%s\"" -#: libpq/hba.c:2434 +#: libpq/hba.c:2417 #, c-format msgid "could not parse RADIUS secret list \"%s\"" msgstr "не вдалося проаналізувати список секретів RADIUS \"%s\"" -#: libpq/hba.c:2456 +#: libpq/hba.c:2439 #, c-format msgid "could not parse RADIUS identifiers list \"%s\"" msgstr "не вдалося проаналізувати список ідентифікаторів RADIUS \"%s\"" -#: libpq/hba.c:2470 +#: libpq/hba.c:2453 #, c-format msgid "unrecognized authentication option name: \"%s\"" msgstr "нерозпізнане ім’я параметра автентифікації: \"%s\"" -#: libpq/hba.c:2662 +#: libpq/hba.c:2645 #, c-format msgid "configuration file \"%s\" contains no entries" msgstr "файл конфігурації \"%s\" не містить елементів" -#: libpq/hba.c:2815 +#: libpq/hba.c:2798 #, c-format msgid "regular expression match for \"%s\" failed: %s" msgstr "помилка при пошуку за регулярним виразом для \"%s\": %s" -#: libpq/hba.c:2839 +#: libpq/hba.c:2822 #, c-format msgid "regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"" msgstr "регулярний вираз \"%s не містить підвиразів, необхідних для зворотного посилання в \"%s\"" -#: libpq/hba.c:2942 +#: libpq/hba.c:2925 #, c-format msgid "provided user name (%s) and authenticated user name (%s) do not match" msgstr "вказане ім'я користувача (%s) і автентифіковане ім'я користувача (%s) не збігаються" -#: libpq/hba.c:2962 +#: libpq/hba.c:2945 #, c-format msgid "no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"" msgstr "немає відповідності у файлі зіставлень \"%s\" для користувача \"%s\" автентифікованого як \"%s\"" -#: libpq/pqcomm.c:200 +#: libpq/pqcomm.c:211 libpq/pqcomm.c:219 libpq/pqcomm.c:250 libpq/pqcomm.c:259 +#: libpq/pqcomm.c:1648 libpq/pqcomm.c:1693 libpq/pqcomm.c:1733 +#: libpq/pqcomm.c:1777 libpq/pqcomm.c:1816 libpq/pqcomm.c:1855 +#: libpq/pqcomm.c:1891 libpq/pqcomm.c:1930 +#, c-format +msgid "%s(%s) failed: %m" +msgstr "%s(%s) помилка: %m" + +#: libpq/pqcomm.c:296 #, c-format msgid "could not set socket to nonblocking mode: %m" msgstr "не вдалося перевести сокет у неблокуючий режим: %m" -#: libpq/pqcomm.c:361 +#: libpq/pqcomm.c:456 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Шлях Unix-сокету \"%s\" занадто довгий (максимум %d байтів)" -#: libpq/pqcomm.c:381 +#: libpq/pqcomm.c:476 #, c-format msgid "could not translate host name \"%s\", service \"%s\" to address: %s" msgstr "не вдалось перекласти ім'я хоста \"%s\", служби \"%s\" в адресу: %s" -#: libpq/pqcomm.c:385 +#: libpq/pqcomm.c:480 #, c-format msgid "could not translate service \"%s\" to address: %s" msgstr "не вдалось перекласти службу \"%s\" в адресу: %s" -#: libpq/pqcomm.c:412 +#: libpq/pqcomm.c:502 #, c-format msgid "could not bind to all requested addresses: MAXLISTEN (%d) exceeded" msgstr "не вдалось прив'язатись до всіх запитаних адрес: MAXLISTEN (%d) перевищено" -#: libpq/pqcomm.c:421 +#: libpq/pqcomm.c:511 msgid "IPv4" msgstr "IPv4" -#: libpq/pqcomm.c:424 +#: libpq/pqcomm.c:514 msgid "IPv6" msgstr "IPv6" -#: libpq/pqcomm.c:427 +#: libpq/pqcomm.c:517 msgid "Unix" msgstr "Unix" -#: libpq/pqcomm.c:431 +#: libpq/pqcomm.c:521 #, c-format msgid "unrecognized address family %d" msgstr "нерозпізнане сімейство адресів %d" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:455 +#: libpq/pqcomm.c:545 #, c-format msgid "could not create %s socket for address \"%s\": %m" msgstr "не вдалось створити сокет %s для адреси \"%s\": %m" #. translator: third %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:481 libpq/pqcomm.c:499 +#: libpq/pqcomm.c:574 libpq/pqcomm.c:592 #, c-format msgid "%s(%s) failed for %s address \"%s\": %m" msgstr "%s(%s) помилка %s для адреси \"%s\": %m" #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:522 +#: libpq/pqcomm.c:615 #, c-format msgid "could not bind %s address \"%s\": %m" msgstr "не вдалось прив'язатись до адреси %s \"%s\": %m" -#: libpq/pqcomm.c:526 +#: libpq/pqcomm.c:619 #, c-format msgid "Is another postmaster already running on port %d?" msgstr "Можливо інший процес postmaster вже виконується на порті %d?" -#: libpq/pqcomm.c:528 +#: libpq/pqcomm.c:621 #, c-format msgid "Is another postmaster already running on port %d? If not, wait a few seconds and retry." msgstr "Можливо порт %d вже зайнятий іншим процесом postmaster? Якщо ні, почекайте пару секунд і спробуйте знову." #. translator: first %s is IPv4, IPv6, or Unix -#: libpq/pqcomm.c:557 +#: libpq/pqcomm.c:650 #, c-format msgid "could not listen on %s address \"%s\": %m" msgstr "не вдалось прослухати на адресі %s \"%s\": %m" -#: libpq/pqcomm.c:565 +#: libpq/pqcomm.c:658 #, c-format msgid "listening on Unix socket \"%s\"" msgstr "прослуховувати UNIX сокет \"%s\"" #. translator: first %s is IPv4 or IPv6 -#: libpq/pqcomm.c:570 +#: libpq/pqcomm.c:663 #, c-format msgid "listening on %s address \"%s\", port %d" msgstr "прослуховувати %s адресу \"%s\", порт %d" -#: libpq/pqcomm.c:659 +#: libpq/pqcomm.c:753 #, c-format msgid "group \"%s\" does not exist" msgstr "група \"%s\" не існує" -#: libpq/pqcomm.c:669 +#: libpq/pqcomm.c:763 #, c-format msgid "could not set group of file \"%s\": %m" msgstr "не вдалось встановити групу для файла \"%s\": %m" -#: libpq/pqcomm.c:680 +#: libpq/pqcomm.c:774 #, c-format msgid "could not set permissions of file \"%s\": %m" msgstr "не вдалось встановити дозволи для файла \"%s\": %m" -#: libpq/pqcomm.c:708 +#: libpq/pqcomm.c:803 #, c-format msgid "could not accept new connection: %m" msgstr "не вдалось прийняти нове підключення: %m" -#: libpq/pqcomm.c:748 libpq/pqcomm.c:757 libpq/pqcomm.c:789 libpq/pqcomm.c:799 -#: libpq/pqcomm.c:1634 libpq/pqcomm.c:1679 libpq/pqcomm.c:1719 -#: libpq/pqcomm.c:1763 libpq/pqcomm.c:1802 libpq/pqcomm.c:1841 -#: libpq/pqcomm.c:1877 libpq/pqcomm.c:1916 -#, c-format -msgid "%s(%s) failed: %m" -msgstr "%s(%s) помилка: %m" - -#: libpq/pqcomm.c:903 +#: libpq/pqcomm.c:885 #, c-format msgid "there is no client connection" msgstr "немає клієнтського підключення" -#: libpq/pqcomm.c:959 libpq/pqcomm.c:1060 +#: libpq/pqcomm.c:941 libpq/pqcomm.c:1042 #, c-format msgid "could not receive data from client: %m" msgstr "не вдалось отримати дані від клієнта: %m" -#: libpq/pqcomm.c:1165 tcop/postgres.c:4405 +#: libpq/pqcomm.c:1149 tcop/postgres.c:4533 #, c-format msgid "terminating connection because protocol synchronization was lost" msgstr "завершення підключення через втрату синхронізації протоколу" -#: libpq/pqcomm.c:1231 +#: libpq/pqcomm.c:1215 #, c-format msgid "unexpected EOF within message length word" msgstr "неочікуваний EOF в слові довжини повідомлення" -#: libpq/pqcomm.c:1241 +#: libpq/pqcomm.c:1225 #, c-format msgid "invalid message length" msgstr "неприпустима довжина повідомлення" -#: libpq/pqcomm.c:1263 libpq/pqcomm.c:1276 +#: libpq/pqcomm.c:1247 libpq/pqcomm.c:1260 #, c-format msgid "incomplete message from client" msgstr "неповне повідомлення від клієнта" -#: libpq/pqcomm.c:1387 +#: libpq/pqcomm.c:1401 #, c-format msgid "could not send data to client: %m" msgstr "не вдалось надіслати дані клієнту: %m" -#: libpq/pqcomm.c:1602 +#: libpq/pqcomm.c:1616 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) помилка: код помилки %d" -#: libpq/pqcomm.c:1691 +#: libpq/pqcomm.c:1705 #, c-format msgid "setting the keepalive idle time is not supported" msgstr "встановлення часу простою keepalive не підтримується" -#: libpq/pqcomm.c:1775 libpq/pqcomm.c:1850 libpq/pqcomm.c:1925 +#: libpq/pqcomm.c:1789 libpq/pqcomm.c:1864 libpq/pqcomm.c:1939 #, c-format msgid "%s(%s) not supported" msgstr "%s(%s) не підтримується" -#: libpq/pqformat.c:407 +#: libpq/pqformat.c:404 #, c-format msgid "no data left in message" msgstr "у повідомлення не залишилось даних" -#: libpq/pqformat.c:518 libpq/pqformat.c:536 libpq/pqformat.c:557 -#: utils/adt/array_userfuncs.c:799 utils/adt/arrayfuncs.c:1507 -#: utils/adt/rowtypes.c:615 +#: libpq/pqformat.c:515 libpq/pqformat.c:533 libpq/pqformat.c:554 +#: utils/adt/array_userfuncs.c:797 utils/adt/arrayfuncs.c:1481 +#: utils/adt/rowtypes.c:613 #, c-format msgid "insufficient data left in message" msgstr "недостатьно даних залишилось в повідомленні" -#: libpq/pqformat.c:598 libpq/pqformat.c:627 +#: libpq/pqformat.c:595 libpq/pqformat.c:624 #, c-format msgid "invalid string in message" msgstr "неприпустимий рядок в повідомленні" -#: libpq/pqformat.c:643 +#: libpq/pqformat.c:640 #, c-format msgid "invalid message format" msgstr "неприпустимий формат повідомлення" -#: main/main.c:235 +#: main/main.c:234 #, c-format msgid "%s: WSAStartup failed: %d\n" msgstr "%s: помилка WSAStartup: %d\n" -#: main/main.c:329 +#: main/main.c:322 #, c-format -msgid "" -"%s is the PostgreSQL server.\n" -"\n" -msgstr "" -"%s - сервер PostgreSQL.\n" -"\n" +msgid "%s is the PostgreSQL server.\n\n" +msgstr "%s - сервер PostgreSQL.\n\n" -#: main/main.c:330 +#: main/main.c:323 #, c-format -msgid "" -"Usage:\n" -" %s [OPTION]...\n" -"\n" -msgstr "" -"Використання:\n" -" %s [OPTION]...\n" -"\n" +msgid "Usage:\n" +" %s [OPTION]...\n\n" +msgstr "Використання:\n" +" %s [OPTION]...\n\n" -#: main/main.c:331 +#: main/main.c:324 #, c-format msgid "Options:\n" msgstr "Параметри:\n" -#: main/main.c:332 +#: main/main.c:325 #, c-format msgid " -B NBUFFERS number of shared buffers\n" msgstr " -B NBUFFERS число спільних буферів\n" -#: main/main.c:333 +#: main/main.c:326 #, c-format msgid " -c NAME=VALUE set run-time parameter\n" msgstr " -c NAME=VALUE встановити параметр під час виконання\n" -#: main/main.c:334 +#: main/main.c:327 #, c-format msgid " -C NAME print value of run-time parameter, then exit\n" msgstr " -C NAME вивести значення параметру під час виконання і вийти\n" -#: main/main.c:335 +#: main/main.c:328 #, c-format msgid " -d 1-5 debugging level\n" msgstr " -d 1-5 рівень налагодження\n" -#: main/main.c:336 +#: main/main.c:329 #, c-format msgid " -D DATADIR database directory\n" msgstr " -D DATADIR каталог бази даних\n" -#: main/main.c:337 +#: main/main.c:330 #, c-format msgid " -e use European date input format (DMY)\n" msgstr " -e використати європейський формат дат (DMY)\n" -#: main/main.c:338 +#: main/main.c:331 #, c-format msgid " -F turn fsync off\n" msgstr " -F вимкнути fsync\n" -#: main/main.c:339 +#: main/main.c:332 #, c-format msgid " -h HOSTNAME host name or IP address to listen on\n" msgstr " -h HOSTNAME ім’я хоста або IP-адреса для прослуховування\n" -#: main/main.c:340 +#: main/main.c:333 #, c-format msgid " -i enable TCP/IP connections (deprecated)\n" msgstr " -i активувати підключення TCP/IP (застаріле)\n" -#: main/main.c:341 +#: main/main.c:334 #, c-format msgid " -k DIRECTORY Unix-domain socket location\n" msgstr " -k DIRECTORY розташування Unix-сокетів\n" -#: main/main.c:343 +#: main/main.c:336 #, c-format msgid " -l enable SSL connections\n" msgstr " -l активувати SSL-підключення\n" -#: main/main.c:345 +#: main/main.c:338 #, c-format msgid " -N MAX-CONNECT maximum number of allowed connections\n" msgstr " -N MAX-CONNECT максимальне число дозволених підключень\n" -#: main/main.c:346 +#: main/main.c:339 #, c-format msgid " -p PORT port number to listen on\n" msgstr " -p PORT номер порту для прослуховування\n" -#: main/main.c:347 +#: main/main.c:340 #, c-format msgid " -s show statistics after each query\n" msgstr " -s відображувати статистику після кожного запиту\n" -#: main/main.c:348 +#: main/main.c:341 #, c-format msgid " -S WORK-MEM set amount of memory for sorts (in kB)\n" msgstr " -S WORK-MEM вказати обсяг пам'яті для сортування (в КБ)\n" -#: main/main.c:349 +#: main/main.c:342 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: main/main.c:350 +#: main/main.c:343 #, c-format msgid " --NAME=VALUE set run-time parameter\n" msgstr " --NAME=VALUE встановити параметр під час виконання\n" -#: main/main.c:351 +#: main/main.c:344 #, c-format msgid " --describe-config describe configuration parameters, then exit\n" msgstr " --describe-config описати параметри конфігурації і вийти\n" -#: main/main.c:352 +#: main/main.c:345 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати довідку і вийти\n" -#: main/main.c:354 +#: main/main.c:347 #, c-format -msgid "" -"\n" +msgid "\n" "Developer options:\n" -msgstr "" -"\n" +msgstr "\n" "Параметри для розробників:\n" -#: main/main.c:355 +#: main/main.c:348 #, c-format msgid " -f s|i|o|b|t|n|m|h forbid use of some plan types\n" msgstr " -f s|i|o|b|t|n|m|h заборонити використовувати деякі типи плану\n" -#: main/main.c:356 +#: main/main.c:349 #, c-format msgid " -O allow system table structure changes\n" msgstr " -O дозволити змінювати структуру системних таблиць\n" -#: main/main.c:357 +#: main/main.c:350 #, c-format msgid " -P disable system indexes\n" msgstr " -P вимкнути системні індекси\n" -#: main/main.c:358 +#: main/main.c:351 #, c-format msgid " -t pa|pl|ex show timings after each query\n" msgstr " -t pa|pl|ex показувати час після кожного запиту\n" -#: main/main.c:359 +#: main/main.c:352 #, c-format msgid " -T send SIGABRT to all backend processes if one dies\n" msgstr " -T надіслати SIGABRT усім внутрішнім процесам, якщо один вимкнеться\n" -#: main/main.c:360 +#: main/main.c:353 #, c-format msgid " -W NUM wait NUM seconds to allow attach from a debugger\n" msgstr " -W NUM очікувати NUM секунд, щоб дозволити підключення від налагоджувача\n" -#: main/main.c:362 +#: main/main.c:355 #, c-format -msgid "" -"\n" +msgid "\n" "Options for single-user mode:\n" -msgstr "" -"\n" +msgstr "\n" "Параметри для однокористувацького режиму:\n" -#: main/main.c:363 +#: main/main.c:356 #, c-format msgid " --single selects single-user mode (must be first argument)\n" msgstr " --single установка однокористувацького режиму (цей аргумент повинен бути першим)\n" -#: main/main.c:364 +#: main/main.c:357 #, c-format msgid " DBNAME database name (defaults to user name)\n" msgstr " DBNAME ім’я бази даних (за замовчуванням - ім'я користувача)\n" -#: main/main.c:365 +#: main/main.c:358 #, c-format msgid " -d 0-5 override debugging level\n" msgstr " -d 0-5 змінити рівень налагодження\n" -#: main/main.c:366 +#: main/main.c:359 #, c-format msgid " -E echo statement before execution\n" msgstr " -E інструкція відлуння перед виконанням\n" -#: main/main.c:367 +#: main/main.c:360 #, c-format msgid " -j do not use newline as interactive query delimiter\n" msgstr " -j не використовувати новий рядок як роздільник інтерактивних запитів\n" -#: main/main.c:368 main/main.c:374 +#: main/main.c:361 main/main.c:367 #, c-format msgid " -r FILENAME send stdout and stderr to given file\n" msgstr " -r FILENAME надіслати stdout і stderr до вказаного файлу\n" -#: main/main.c:370 +#: main/main.c:363 #, c-format -msgid "" -"\n" +msgid "\n" "Options for bootstrapping mode:\n" -msgstr "" -"\n" +msgstr "\n" "Параметри для режиму початкового завантаження:\n" -#: main/main.c:371 +#: main/main.c:364 #, c-format msgid " --boot selects bootstrapping mode (must be first argument)\n" msgstr " --boot установка режиму початкового завантаження (цей аргумент повинен бути першим)\n" -#: main/main.c:372 +#: main/main.c:365 #, c-format msgid " --check selects check mode (must be first argument)\n" msgstr " --check обирає режим перевірки (має бути першим аргументом)\n" -#: main/main.c:373 +#: main/main.c:366 #, c-format msgid " DBNAME database name (mandatory argument in bootstrapping mode)\n" msgstr " DBNAME ім'я бази даних (обов'язковий аргумент у режимі початкового завантаження)\n" -#: main/main.c:376 +#: main/main.c:369 #, c-format -msgid "" -"\n" +msgid "\n" "Please read the documentation for the complete list of run-time\n" "configuration settings and how to set them on the command line or in\n" -"the configuration file.\n" -"\n" +"the configuration file.\n\n" "Report bugs to <%s>.\n" -msgstr "" -"\n" -"Будь-ласка прочитайте інструкцію для повного списку параметрів конфігурації виконання і їх встановлення у командний рядок або в файл конфігурації.\n" -"\n" +msgstr "\n" +"Будь-ласка прочитайте інструкцію для повного списку параметрів конфігурації виконання і їх встановлення у командний рядок або в файл конфігурації.\n\n" "Про помилки повідомляйте <%s>.\n" -#: main/main.c:380 +#: main/main.c:373 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: main/main.c:391 +#: main/main.c:384 #, c-format -msgid "" -"\"root\" execution of the PostgreSQL server is not permitted.\n" +msgid "\"root\" execution of the PostgreSQL server is not permitted.\n" "The server must be started under an unprivileged user ID to prevent\n" "possible system security compromise. See the documentation for\n" "more information on how to properly start the server.\n" -msgstr "" -"Запускати сервер PostgreSQL під іменем \"root\" не дозволено.\n" +msgstr "Запускати сервер PostgreSQL під іменем \"root\" не дозволено.\n" "Для запобігання компрометації системи безпеки сервер повинен запускати непривілейований користувач. Дивіться документацію, щоб дізнатися більше про те, як правильно запустити сервер.\n" -#: main/main.c:408 +#: main/main.c:401 #, c-format msgid "%s: real and effective user IDs must match\n" msgstr "%s: дійсний і ефективний ID користувача повинні збігатися\n" -#: main/main.c:415 +#: main/main.c:408 #, c-format -msgid "" -"Execution of PostgreSQL by a user with administrative permissions is not\n" +msgid "Execution of PostgreSQL by a user with administrative permissions is not\n" "permitted.\n" "The server must be started under an unprivileged user ID to prevent\n" "possible system security compromises. See the documentation for\n" "more information on how to properly start the server.\n" -msgstr "" -"Запускати PostgreSQL під іменем користувача з правами адміністратора не дозволено.\n" +msgstr "Запускати PostgreSQL під іменем користувача з правами адміністратора не дозволено.\n" "Для запобігання можливої компрометації системи безпеки сервер повинен запускати непривілейований користувач. Дивіться документацію, щоб дізнатися більше про те, як правильно запустити сервер.\n" #: nodes/extensible.c:66 @@ -15842,20 +16243,15 @@ msgstr "розширений тип вузла \"%s\" вже існує" msgid "ExtensibleNodeMethods \"%s\" was not registered" msgstr "Методи розширеного вузла \"%s\" не зареєстровані" -#: nodes/makefuncs.c:153 statistics/extended_stats.c:2335 +#: nodes/makefuncs.c:152 statistics/extended_stats.c:2310 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "відношення \"%s\" не має складеного типу" -#: nodes/makefuncs.c:879 -#, c-format -msgid "unrecognized JSON encoding: %s" -msgstr "нерозпізнане кодування JSON: %s" - -#: nodes/nodeFuncs.c:116 nodes/nodeFuncs.c:147 parser/parse_coerce.c:2567 +#: nodes/nodeFuncs.c:118 nodes/nodeFuncs.c:149 parser/parse_coerce.c:2567 #: parser/parse_coerce.c:2705 parser/parse_coerce.c:2752 -#: parser/parse_expr.c:2049 parser/parse_func.c:710 parser/parse_oper.c:883 -#: utils/fmgr/funcapi.c:661 +#: parser/parse_expr.c:2112 parser/parse_func.c:710 parser/parse_oper.c:869 +#: utils/fmgr/funcapi.c:669 #, c-format msgid "could not find array type for data type %s" msgstr "не вдалося знайти тип масиву для типу даних %s" @@ -15870,179 +16266,184 @@ msgstr "портал \"%s\" з параметрами: %s" msgid "unnamed portal with parameters: %s" msgstr "портал без імені з параметрами: %s" -#: optimizer/path/joinrels.c:973 +#: optimizer/path/joinrels.c:972 #, c-format msgid "FULL JOIN is only supported with merge-joinable or hash-joinable join conditions" msgstr "FULL JOIN підтримується лише з умовами, які допускають з'єднання злиттям або хеш-з'єднанням" -#: optimizer/plan/createplan.c:7111 parser/parse_merge.c:182 -#: parser/parse_merge.c:189 +#: optimizer/plan/createplan.c:7175 parser/parse_merge.c:203 +#: rewrite/rewriteHandler.c:1696 #, c-format msgid "cannot execute MERGE on relation \"%s\"" msgstr "не можна виконати MERGE для відношення \"%s\"" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/initsplan.c:1408 +#: optimizer/plan/initsplan.c:1407 #, c-format msgid "%s cannot be applied to the nullable side of an outer join" msgstr "%s не можна застосовувати до нульової сторони зовнішнього з’єднання" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: optimizer/plan/planner.c:1361 parser/analyze.c:1761 parser/analyze.c:2018 -#: parser/analyze.c:3231 +#: optimizer/plan/planner.c:1386 parser/analyze.c:1771 parser/analyze.c:2029 +#: parser/analyze.c:3247 #, c-format msgid "%s is not allowed with UNION/INTERSECT/EXCEPT" msgstr "%s несумісно з UNION/INTERSECT/EXCEPT" -#: optimizer/plan/planner.c:2076 optimizer/plan/planner.c:4035 +#: optimizer/plan/planner.c:2127 optimizer/plan/planner.c:4113 #, c-format msgid "could not implement GROUP BY" msgstr "не вдалося реалізувати GROUP BY" -#: optimizer/plan/planner.c:2077 optimizer/plan/planner.c:4036 -#: optimizer/plan/planner.c:4676 optimizer/prep/prepunion.c:1053 +#: optimizer/plan/planner.c:2128 optimizer/plan/planner.c:4114 +#: optimizer/plan/planner.c:4795 optimizer/prep/prepunion.c:1320 #, c-format msgid "Some of the datatypes only support hashing, while others only support sorting." msgstr "Деякі типи даних підтримують лише хешування, в той час як інші підтримують тільки сортування." -#: optimizer/plan/planner.c:4675 +#: optimizer/plan/planner.c:4794 #, c-format msgid "could not implement DISTINCT" msgstr "не вдалося реалізувати DISTINCT" -#: optimizer/plan/planner.c:6014 +#: optimizer/plan/planner.c:6139 #, c-format msgid "could not implement window PARTITION BY" msgstr "не вдалося реалізувати PARTITION BY для вікна" -#: optimizer/plan/planner.c:6015 +#: optimizer/plan/planner.c:6140 #, c-format msgid "Window partitioning columns must be of sortable datatypes." msgstr "Стовпці, що розділяють вікна, повинні мати типи даних з можливістю сортування." -#: optimizer/plan/planner.c:6019 +#: optimizer/plan/planner.c:6144 #, c-format msgid "could not implement window ORDER BY" msgstr "не вдалося реалізувати ORDER BY для вікна" -#: optimizer/plan/planner.c:6020 +#: optimizer/plan/planner.c:6145 #, c-format msgid "Window ordering columns must be of sortable datatypes." msgstr "Стовпці, що впорядковують вікна, повинні мати типи даних з можливістю сортування." -#: optimizer/prep/prepunion.c:516 +#: optimizer/prep/prepunion.c:467 #, c-format msgid "could not implement recursive UNION" msgstr "не вдалося реалізувати рекурсивний UNION" -#: optimizer/prep/prepunion.c:517 +#: optimizer/prep/prepunion.c:468 #, c-format msgid "All column datatypes must be hashable." msgstr "Усі стовпці повинні мати типи даних з можливістю хешування." #. translator: %s is UNION, INTERSECT, or EXCEPT -#: optimizer/prep/prepunion.c:1052 +#: optimizer/prep/prepunion.c:1319 #, c-format msgid "could not implement %s" msgstr "не вдалося реалізувати %s" -#: optimizer/util/clauses.c:4929 +#: optimizer/util/clauses.c:4951 #, c-format msgid "SQL function \"%s\" during inlining" msgstr "Впроваджена в код SQL-функція \"%s\"" -#: optimizer/util/plancat.c:154 +#: optimizer/util/plancat.c:153 #, c-format msgid "cannot access temporary or unlogged relations during recovery" msgstr "отримати доступ до тимчасових або нежурнальованих відношень під час відновлення не можна" -#: optimizer/util/plancat.c:726 +#: optimizer/util/plancat.c:768 #, c-format msgid "whole row unique index inference specifications are not supported" msgstr "вказівки з посиланням на весь рядок для вибору унікального індексу не підтримуються" -#: optimizer/util/plancat.c:743 +#: optimizer/util/plancat.c:785 #, c-format msgid "constraint in ON CONFLICT clause has no associated index" msgstr "з обмеженням в реченні ON CONFLICT не пов'язаний індекс" -#: optimizer/util/plancat.c:793 +#: optimizer/util/plancat.c:835 #, c-format msgid "ON CONFLICT DO UPDATE not supported with exclusion constraints" msgstr "ON CONFLICT DO UPDATE не підтримується з обмеженнями-винятками" -#: optimizer/util/plancat.c:898 +#: optimizer/util/plancat.c:945 #, c-format msgid "there is no unique or exclusion constraint matching the ON CONFLICT specification" msgstr "немає унікального обмеження або обмеження-виключення відповідного специфікації ON CONFLICT" -#: parser/analyze.c:826 parser/analyze.c:1540 +#: parser/analyze.c:824 parser/analyze.c:1550 #, c-format msgid "VALUES lists must all be the same length" msgstr "Списки VALUES повинні мати однакову довжину" -#: parser/analyze.c:1028 +#: parser/analyze.c:1027 #, c-format msgid "INSERT has more expressions than target columns" msgstr "INSERT містить більше виразів, ніж цільових стовпців" -#: parser/analyze.c:1046 +#: parser/analyze.c:1045 #, c-format msgid "INSERT has more target columns than expressions" msgstr "INSERT містить більше цільових стовпців, ніж виразів" -#: parser/analyze.c:1050 +#: parser/analyze.c:1049 #, c-format msgid "The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?" msgstr "Джерелом даних є вираз рядка, який містить стільки ж стовпців, скільки потребується для INSERT. Ви випадково використовували додаткові дужки?" -#: parser/analyze.c:1347 parser/analyze.c:1734 +#: parser/analyze.c:1357 parser/analyze.c:1744 #, c-format msgid "SELECT ... INTO is not allowed here" msgstr "SELECT ... INTO не дозволяється тут" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:1663 parser/analyze.c:3463 +#: parser/analyze.c:1673 parser/analyze.c:3479 #, c-format msgid "%s cannot be applied to VALUES" msgstr "%s не можна застосовувати до VALUES" -#: parser/analyze.c:1900 +#: parser/analyze.c:1911 #, c-format msgid "invalid UNION/INTERSECT/EXCEPT ORDER BY clause" msgstr "неприпустиме речення UNION/INTERSECT/EXCEPT ORDER BY" -#: parser/analyze.c:1901 +#: parser/analyze.c:1912 #, c-format msgid "Only result column names can be used, not expressions or functions." msgstr "Дозволено використання тільки імен стовпців, але не виразів або функцій." -#: parser/analyze.c:1902 +#: parser/analyze.c:1913 #, c-format msgid "Add the expression/function to every SELECT, or move the UNION into a FROM clause." msgstr "Додайте вираз/функція до кожного SELECT, або перемістіть UNION у речення FROM." -#: parser/analyze.c:2008 +#: parser/analyze.c:2019 #, c-format msgid "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT" msgstr "INTO дозволяється додати лише до першого SELECT в UNION/INTERSECT/EXCEPT" -#: parser/analyze.c:2080 +#: parser/analyze.c:2091 #, c-format msgid "UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level" msgstr "Учасник інструкції UNION/INTERSECT/EXCEPT не може посилатись на інші відносини на тому ж рівні" -#: parser/analyze.c:2167 +#: parser/analyze.c:2178 #, c-format msgid "each %s query must have the same number of columns" msgstr "кожен %s запит повинен мати однакову кількість стовпців" -#: parser/analyze.c:2573 +#: parser/analyze.c:2535 +#, c-format +msgid "SET target columns cannot be qualified with the relation name." +msgstr "Цільові стовпці SET не можуть бути кваліфіковані за допомогою імені відношення." + +#: parser/analyze.c:2589 #, c-format msgid "RETURNING must have at least one column" msgstr "В RETURNING повинен бути мінімум один стовпець" -#: parser/analyze.c:2676 +#: parser/analyze.c:2692 #, c-format msgid "assignment source returned %d column" msgid_plural "assignment source returned %d columns" @@ -16051,224 +16452,224 @@ msgstr[1] "джерело призначення повернуло %d стов msgstr[2] "джерело призначення повернуло %d стовпців" msgstr[3] "джерело призначення повернуло %d стовпців" -#: parser/analyze.c:2737 +#: parser/analyze.c:2753 #, c-format msgid "variable \"%s\" is of type %s but expression is of type %s" msgstr "змінна \"%s\" має тип %s, але вираз має тип %s" #. translator: %s is a SQL keyword -#: parser/analyze.c:2862 parser/analyze.c:2870 +#: parser/analyze.c:2878 parser/analyze.c:2886 #, c-format msgid "cannot specify both %s and %s" msgstr "не можна вказати як %s, так і %s" -#: parser/analyze.c:2890 +#: parser/analyze.c:2906 #, c-format msgid "DECLARE CURSOR must not contain data-modifying statements in WITH" msgstr "DECLARE CURSOR не повинен містити операторів, які змінюють дані в WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2898 +#: parser/analyze.c:2914 #, c-format msgid "DECLARE CURSOR WITH HOLD ... %s is not supported" msgstr "DECLARE CURSOR WITH HOLD ... %s не підтримується" -#: parser/analyze.c:2901 +#: parser/analyze.c:2917 #, c-format msgid "Holdable cursors must be READ ONLY." msgstr "Курсори, що зберігаються повинні бути READ ONLY." #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2909 +#: parser/analyze.c:2925 #, c-format msgid "DECLARE SCROLL CURSOR ... %s is not supported" msgstr "DECLARE SCROLL CURSOR ... %s не підтримується" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:2920 +#: parser/analyze.c:2936 #, c-format msgid "DECLARE INSENSITIVE CURSOR ... %s is not valid" msgstr "DECLARE INSENSITIVE CURSOR ... %s не є припустимим" -#: parser/analyze.c:2923 +#: parser/analyze.c:2939 #, c-format msgid "Insensitive cursors must be READ ONLY." msgstr "Нечутливі курсори повинні бути READ ONLY." -#: parser/analyze.c:3017 +#: parser/analyze.c:3033 #, c-format msgid "materialized views must not use data-modifying statements in WITH" msgstr "в матеріалізованих поданнях не повинні використовуватись оператори, які змінюють дані в WITH" -#: parser/analyze.c:3027 +#: parser/analyze.c:3043 #, c-format msgid "materialized views must not use temporary tables or views" msgstr "в матеріалізованих поданнях не повинні використовуватись тимчасові таблиці або подання" -#: parser/analyze.c:3037 +#: parser/analyze.c:3053 #, c-format msgid "materialized views may not be defined using bound parameters" msgstr "визначати матеріалізовані подання з зв'язаними параметрами не можна" -#: parser/analyze.c:3049 +#: parser/analyze.c:3065 #, c-format msgid "materialized views cannot be unlogged" msgstr "матеріалізовані подання не можуть бути нежурнальованими" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3238 +#: parser/analyze.c:3254 #, c-format msgid "%s is not allowed with DISTINCT clause" msgstr "%s не дозволяється з реченням DISTINCT" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3245 +#: parser/analyze.c:3261 #, c-format msgid "%s is not allowed with GROUP BY clause" msgstr "%s не дозволяється з реченням GROUP BY" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3252 +#: parser/analyze.c:3268 #, c-format msgid "%s is not allowed with HAVING clause" msgstr "%s не дозволяється з реченням HAVING" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3259 +#: parser/analyze.c:3275 #, c-format msgid "%s is not allowed with aggregate functions" msgstr "%s не дозволяється з агрегатними функціями" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3266 +#: parser/analyze.c:3282 #, c-format msgid "%s is not allowed with window functions" msgstr "%s не дозволяється з віконними функціями" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3273 +#: parser/analyze.c:3289 #, c-format msgid "%s is not allowed with set-returning functions in the target list" msgstr "%s не дозволяється з функціями, які повертають безлічі, в цільовому списку" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3372 +#: parser/analyze.c:3388 #, c-format msgid "%s must specify unqualified relation names" msgstr "для %s потрібно вказати некваліфіковані імена відносин" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3436 +#: parser/analyze.c:3452 #, c-format msgid "%s cannot be applied to a join" msgstr "%s не можна застосовувати до з'єднання" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3445 +#: parser/analyze.c:3461 #, c-format msgid "%s cannot be applied to a function" msgstr "%s не можна застосовувати до функції" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3454 +#: parser/analyze.c:3470 #, c-format msgid "%s cannot be applied to a table function" msgstr "%s не можна застосовувати до табличної функції" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3472 +#: parser/analyze.c:3488 #, c-format msgid "%s cannot be applied to a WITH query" msgstr "%s не можна застосовувати до запиту WITH" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3481 +#: parser/analyze.c:3497 #, c-format msgid "%s cannot be applied to a named tuplestore" msgstr "%s не можна застосовувати до іменованого джерела кортежів" #. translator: %s is a SQL row locking clause such as FOR UPDATE -#: parser/analyze.c:3501 +#: parser/analyze.c:3517 #, c-format msgid "relation \"%s\" in %s clause not found in FROM clause" msgstr "відношення \"%s\" в реченні %s не знайдено в реченні FROM" -#: parser/parse_agg.c:209 parser/parse_oper.c:227 +#: parser/parse_agg.c:210 parser/parse_oper.c:215 #, c-format msgid "could not identify an ordering operator for type %s" msgstr "для типу %s не вдалося визначити оператора сортування" -#: parser/parse_agg.c:211 +#: parser/parse_agg.c:212 #, c-format msgid "Aggregates with DISTINCT must be able to sort their inputs." msgstr "Агрегатним функціям з DISTINCT необхідно сортувати їх вхідні дані." -#: parser/parse_agg.c:269 +#: parser/parse_agg.c:270 #, c-format msgid "GROUPING must have fewer than 32 arguments" msgstr "GROUPING повинно містити меньше, ніж 32 аргумента" -#: parser/parse_agg.c:372 +#: parser/parse_agg.c:373 msgid "aggregate functions are not allowed in JOIN conditions" msgstr "агрегатні функції не дозволяються в умовах JOIN" -#: parser/parse_agg.c:374 +#: parser/parse_agg.c:375 msgid "grouping operations are not allowed in JOIN conditions" msgstr "операції групування не дозволяються в умовах JOIN" -#: parser/parse_agg.c:386 +#: parser/parse_agg.c:385 msgid "aggregate functions are not allowed in FROM clause of their own query level" msgstr "агрегатні функції не можна застосовувати в реченні FROM їх рівня запиту" -#: parser/parse_agg.c:388 +#: parser/parse_agg.c:387 msgid "grouping operations are not allowed in FROM clause of their own query level" msgstr "операції групування не можна застосовувати в реченні FROM їх рівня запиту" -#: parser/parse_agg.c:393 +#: parser/parse_agg.c:392 msgid "aggregate functions are not allowed in functions in FROM" msgstr "агрегатні функції не можна застосовувати у функціях у FROM" -#: parser/parse_agg.c:395 +#: parser/parse_agg.c:394 msgid "grouping operations are not allowed in functions in FROM" msgstr "операції групування не можна застосовувати у функціях у FROM" -#: parser/parse_agg.c:403 +#: parser/parse_agg.c:402 msgid "aggregate functions are not allowed in policy expressions" msgstr "агрегатні функції не можна застосовувати у виразах політики" -#: parser/parse_agg.c:405 +#: parser/parse_agg.c:404 msgid "grouping operations are not allowed in policy expressions" msgstr "операції групування не можна застосовувати у виразах політики" -#: parser/parse_agg.c:422 +#: parser/parse_agg.c:421 msgid "aggregate functions are not allowed in window RANGE" msgstr "агрегатні функції не можна застосовувати у вікні RANGE " -#: parser/parse_agg.c:424 +#: parser/parse_agg.c:423 msgid "grouping operations are not allowed in window RANGE" msgstr "операції групування не можна застосовувати у вікні RANGE" -#: parser/parse_agg.c:429 +#: parser/parse_agg.c:428 msgid "aggregate functions are not allowed in window ROWS" msgstr "агрегатні функції не можна застосовувати у вікні ROWS" -#: parser/parse_agg.c:431 +#: parser/parse_agg.c:430 msgid "grouping operations are not allowed in window ROWS" msgstr "операції групування не можна застосовувати у вікні ROWS" -#: parser/parse_agg.c:436 +#: parser/parse_agg.c:435 msgid "aggregate functions are not allowed in window GROUPS" msgstr "агрегатні функції не можна застосовувати у вікні GROUPS" -#: parser/parse_agg.c:438 +#: parser/parse_agg.c:437 msgid "grouping operations are not allowed in window GROUPS" msgstr "операції групування не можна застосовувати у вікні GROUPS" -#: parser/parse_agg.c:451 +#: parser/parse_agg.c:450 msgid "aggregate functions are not allowed in MERGE WHEN conditions" msgstr "агрегатні функції не можна застосовувати в умовах MERGE WHEN" -#: parser/parse_agg.c:453 +#: parser/parse_agg.c:452 msgid "grouping operations are not allowed in MERGE WHEN conditions" msgstr "операції групування не можна застосовувати в умовах MERGE WHEN" @@ -16377,7 +16778,7 @@ msgid "grouping operations are not allowed in COPY FROM WHERE conditions" msgstr "операції групування не можна застосовувати в умовах COPY FROM WHERE" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:597 parser/parse_clause.c:1956 +#: parser/parse_agg.c:597 parser/parse_clause.c:1962 #, c-format msgid "aggregate functions are not allowed in %s" msgstr "агрегатні функції не можна застосовувати в %s" @@ -16398,8 +16799,8 @@ msgstr "агрегат зовнішнього рівня не може міст msgid "aggregate function calls cannot contain set-returning function calls" msgstr "виклики агрегатної функції не можуть містити викликів функції, що повертають множину" -#: parser/parse_agg.c:780 parser/parse_expr.c:1700 parser/parse_expr.c:2182 -#: parser/parse_func.c:884 +#: parser/parse_agg.c:780 parser/parse_expr.c:1762 parser/parse_expr.c:2245 +#: parser/parse_func.c:885 #, c-format msgid "You might be able to move the set-returning function into a LATERAL FROM item." msgstr "Можливо перемістити функцію, що повертає множину, в елемент LATERAL FROM." @@ -16429,170 +16830,170 @@ msgstr "віконні функції не можна застосовувати msgid "window functions are not allowed in MERGE WHEN conditions" msgstr "віконні функції не можна застосовувати в умовах MERGE WHEN" -#: parser/parse_agg.c:925 +#: parser/parse_agg.c:926 msgid "window functions are not allowed in check constraints" msgstr "віконні функції не можна застосовувати в перевірках обмежень" -#: parser/parse_agg.c:929 +#: parser/parse_agg.c:930 msgid "window functions are not allowed in DEFAULT expressions" msgstr "віконні функції не можна застосовувати у виразах DEFAULT" -#: parser/parse_agg.c:932 +#: parser/parse_agg.c:933 msgid "window functions are not allowed in index expressions" msgstr "віконні функції не можна застосовувати у виразах індексів" -#: parser/parse_agg.c:935 +#: parser/parse_agg.c:936 msgid "window functions are not allowed in statistics expressions" msgstr "віконні функції не можна застосовувати у виразах статистики" -#: parser/parse_agg.c:938 +#: parser/parse_agg.c:939 msgid "window functions are not allowed in index predicates" msgstr "віконні функції не можна застосовувати в предикатах індексів" -#: parser/parse_agg.c:941 +#: parser/parse_agg.c:942 msgid "window functions are not allowed in transform expressions" msgstr "віконні функції не можна застосовувати у виразах перетворювання" -#: parser/parse_agg.c:944 +#: parser/parse_agg.c:945 msgid "window functions are not allowed in EXECUTE parameters" msgstr "віконні функції не можна застосовувати в параметрах EXECUTE" -#: parser/parse_agg.c:947 +#: parser/parse_agg.c:948 msgid "window functions are not allowed in trigger WHEN conditions" msgstr "віконні функції не можна застосовувати в умовах WHEN для тригерів" -#: parser/parse_agg.c:950 +#: parser/parse_agg.c:951 msgid "window functions are not allowed in partition bound" msgstr "віконні функції не можна застосовувати в границі секції" -#: parser/parse_agg.c:953 +#: parser/parse_agg.c:954 msgid "window functions are not allowed in partition key expressions" msgstr "віконні функції не можна застосовувати у виразах ключа секціонування" -#: parser/parse_agg.c:956 +#: parser/parse_agg.c:957 msgid "window functions are not allowed in CALL arguments" msgstr "віконні функції не можна застосовувати в аргументах CALL" -#: parser/parse_agg.c:959 +#: parser/parse_agg.c:960 msgid "window functions are not allowed in COPY FROM WHERE conditions" msgstr "віконні функції не можна застосовувати в умовах COPY FROM WHERE" -#: parser/parse_agg.c:962 +#: parser/parse_agg.c:963 msgid "window functions are not allowed in column generation expressions" msgstr "віконні функції не можна застосовувати у виразах генерації стовпців" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_agg.c:985 parser/parse_clause.c:1965 +#: parser/parse_agg.c:986 parser/parse_clause.c:1971 #, c-format msgid "window functions are not allowed in %s" msgstr "віконні функції не можна застосовувати в %s" -#: parser/parse_agg.c:1019 parser/parse_clause.c:2798 +#: parser/parse_agg.c:1020 parser/parse_clause.c:2804 #, c-format msgid "window \"%s\" does not exist" msgstr "вікно \"%s\" не існує" -#: parser/parse_agg.c:1107 +#: parser/parse_agg.c:1108 #, c-format msgid "too many grouping sets present (maximum 4096)" msgstr "забагато наборів групування (максимум 4096)" -#: parser/parse_agg.c:1247 +#: parser/parse_agg.c:1248 #, c-format msgid "aggregate functions are not allowed in a recursive query's recursive term" msgstr "агрегатні функції не дозволені у рекурсивному терміні рекурсивного запиту" -#: parser/parse_agg.c:1440 +#: parser/parse_agg.c:1441 #, c-format msgid "column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function" msgstr "стовпець \"%s.%s\" повинен з'являтися у реченні Група BY або використовуватися в агрегатній функції" -#: parser/parse_agg.c:1443 +#: parser/parse_agg.c:1444 #, c-format msgid "Direct arguments of an ordered-set aggregate must use only grouped columns." msgstr "Прямі аргументи сортувального агрегату можуть використовувати лише згруповані стовпці." -#: parser/parse_agg.c:1448 +#: parser/parse_agg.c:1449 #, c-format msgid "subquery uses ungrouped column \"%s.%s\" from outer query" msgstr "вкладений запит використовує не згруповані стовпці \"%s.%s\" з зовнішнього запиту" -#: parser/parse_agg.c:1612 +#: parser/parse_agg.c:1613 #, c-format msgid "arguments to GROUPING must be grouping expressions of the associated query level" msgstr "аргументами групування мають бути вирази групування пов'язаного рівня запиту" -#: parser/parse_clause.c:195 +#: parser/parse_clause.c:193 #, c-format msgid "relation \"%s\" cannot be the target of a modifying statement" msgstr "відношення \"%s\" не може бути метою модифікованої інструкції" -#: parser/parse_clause.c:571 parser/parse_clause.c:599 parser/parse_func.c:2552 +#: parser/parse_clause.c:569 parser/parse_clause.c:597 parser/parse_func.c:2553 #, c-format msgid "set-returning functions must appear at top level of FROM" msgstr "функції, що повертають множину, мають з'являтися на вищому рівні FROM" -#: parser/parse_clause.c:611 +#: parser/parse_clause.c:609 #, c-format msgid "multiple column definition lists are not allowed for the same function" msgstr "кілька списків з визначенням стовпців не дозволені для тої самої функції" -#: parser/parse_clause.c:644 +#: parser/parse_clause.c:642 #, c-format msgid "ROWS FROM() with multiple functions cannot have a column definition list" msgstr "ROWS FROM() з декількома функціями не можуть мати список з визначенням стовпців" -#: parser/parse_clause.c:645 +#: parser/parse_clause.c:643 #, c-format msgid "Put a separate column definition list for each function inside ROWS FROM()." msgstr "Укладіть окремі списки з визначенням стовпців для кожної з функцій всередині ROWS FROM()." -#: parser/parse_clause.c:651 +#: parser/parse_clause.c:649 #, c-format msgid "UNNEST() with multiple arguments cannot have a column definition list" msgstr "UNNEST() з кількома аргументами не можуть мати список з визначенням стовпців" -#: parser/parse_clause.c:652 +#: parser/parse_clause.c:650 #, c-format msgid "Use separate UNNEST() calls inside ROWS FROM(), and attach a column definition list to each one." msgstr "Використайте окремі виклики UNNEST() всередині ROWS FROM() і підключіть список з визначенням стовпців до кожного." -#: parser/parse_clause.c:659 +#: parser/parse_clause.c:657 #, c-format msgid "WITH ORDINALITY cannot be used with a column definition list" msgstr "WITH ORDINALITY не можна використовувати з списком з визначенням стовпців" -#: parser/parse_clause.c:660 +#: parser/parse_clause.c:658 #, c-format msgid "Put the column definition list inside ROWS FROM()." msgstr "Помістіть список з визначенням стовпців всередину ROWS FROM()." -#: parser/parse_clause.c:760 +#: parser/parse_clause.c:762 parser/parse_jsontable.c:295 #, c-format msgid "only one FOR ORDINALITY column is allowed" msgstr "FOR ORDINALITY дозволяється лише для одного стовпця" -#: parser/parse_clause.c:821 +#: parser/parse_clause.c:823 #, c-format msgid "column name \"%s\" is not unique" msgstr "ім'я стовпця \"%s\" не є унікальним" -#: parser/parse_clause.c:863 +#: parser/parse_clause.c:865 #, c-format msgid "namespace name \"%s\" is not unique" msgstr "ім'я простору імен \"%s\" не є унікальним" -#: parser/parse_clause.c:873 +#: parser/parse_clause.c:875 #, c-format msgid "only one default namespace is allowed" msgstr "дозволено тільки один простір імен за замовчуванням" -#: parser/parse_clause.c:933 +#: parser/parse_clause.c:935 #, c-format msgid "tablesample method %s does not exist" msgstr "метод %s для отримання вибірки не існує" -#: parser/parse_clause.c:955 +#: parser/parse_clause.c:957 #, c-format msgid "tablesample method %s requires %d argument, not %d" msgid_plural "tablesample method %s requires %d arguments, not %d" @@ -16601,204 +17002,204 @@ msgstr[1] "метод %s для отримання вибірки потребу msgstr[2] "метод %s для отримання вибірки потребує аргументів: %d, отримано: %d" msgstr[3] "метод %s для отримання вибірки потребує аргументів: %d, отримано: %d" -#: parser/parse_clause.c:989 +#: parser/parse_clause.c:991 #, c-format msgid "tablesample method %s does not support REPEATABLE" msgstr "метод %s для отримання вибірки не підтримує REPEATABLE" -#: parser/parse_clause.c:1138 +#: parser/parse_clause.c:1144 #, c-format msgid "TABLESAMPLE clause can only be applied to tables and materialized views" msgstr "Речення TABLESAMPLE можна застосовувати лише до таблиць або матеріалізованих подань" -#: parser/parse_clause.c:1325 +#: parser/parse_clause.c:1331 #, c-format msgid "column name \"%s\" appears more than once in USING clause" msgstr "ім’я стовпця \"%s\" з'являється у реченні USING неодноразово" -#: parser/parse_clause.c:1340 +#: parser/parse_clause.c:1346 #, c-format msgid "common column name \"%s\" appears more than once in left table" msgstr "ім’я спільного стовпця \"%s\" з'являється у таблиці зліва неодноразово" -#: parser/parse_clause.c:1349 +#: parser/parse_clause.c:1355 #, c-format msgid "column \"%s\" specified in USING clause does not exist in left table" msgstr "в таблиці зліва не існує стовпець \"%s\", вказаний в реченні USING" -#: parser/parse_clause.c:1364 +#: parser/parse_clause.c:1370 #, c-format msgid "common column name \"%s\" appears more than once in right table" msgstr "ім’я спільного стовпця \"%s\" з'являється в таблиці справа неодноразово" -#: parser/parse_clause.c:1373 +#: parser/parse_clause.c:1379 #, c-format msgid "column \"%s\" specified in USING clause does not exist in right table" msgstr "в таблиці справа не існує стовпець \"%s\", вказаний в реченні USING" -#: parser/parse_clause.c:1901 +#: parser/parse_clause.c:1907 #, c-format msgid "row count cannot be null in FETCH FIRST ... WITH TIES clause" msgstr "кількість рядків не може бути NULL в операторі FETCH FIRST ... WITH TIES" #. translator: %s is name of a SQL construct, eg LIMIT -#: parser/parse_clause.c:1926 +#: parser/parse_clause.c:1932 #, c-format msgid "argument of %s must not contain variables" msgstr "аргумент %s не може містити змінні" #. translator: first %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2091 +#: parser/parse_clause.c:2097 #, c-format msgid "%s \"%s\" is ambiguous" msgstr "вираз %s \"%s\" неоднозначний" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2119 +#: parser/parse_clause.c:2125 #, c-format msgid "non-integer constant in %s" msgstr "нецілочисельна константа в %s" #. translator: %s is name of a SQL construct, eg ORDER BY -#: parser/parse_clause.c:2141 +#: parser/parse_clause.c:2147 #, c-format msgid "%s position %d is not in select list" msgstr "в списку вибірки %s немає позиції %d" -#: parser/parse_clause.c:2580 +#: parser/parse_clause.c:2586 #, c-format msgid "CUBE is limited to 12 elements" msgstr "CUBE має обмеження в 12 елементів" -#: parser/parse_clause.c:2786 +#: parser/parse_clause.c:2792 #, c-format msgid "window \"%s\" is already defined" msgstr "вікно \"%s\" вже визначено" -#: parser/parse_clause.c:2847 +#: parser/parse_clause.c:2853 #, c-format msgid "cannot override PARTITION BY clause of window \"%s\"" msgstr "змінити речення PARTITION BY для вікна \"%s\" не можна" -#: parser/parse_clause.c:2859 +#: parser/parse_clause.c:2865 #, c-format msgid "cannot override ORDER BY clause of window \"%s\"" msgstr "змінити речення ORDER BY для вікна \"%s\" не можна" -#: parser/parse_clause.c:2889 parser/parse_clause.c:2895 +#: parser/parse_clause.c:2895 parser/parse_clause.c:2901 #, c-format msgid "cannot copy window \"%s\" because it has a frame clause" msgstr "скопіювати вікно \"%s\", яке має речення рамки, не можна" -#: parser/parse_clause.c:2897 +#: parser/parse_clause.c:2903 #, c-format msgid "Omit the parentheses in this OVER clause." msgstr "Пропустіть дужки в реченні OVER." -#: parser/parse_clause.c:2917 +#: parser/parse_clause.c:2923 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column" msgstr "Для RANGE з зсувом PRECEDING/FOLLOWING потребується лише один стовпець в ORDER BY" -#: parser/parse_clause.c:2940 +#: parser/parse_clause.c:2946 #, c-format msgid "GROUPS mode requires an ORDER BY clause" msgstr "Для режиму GROUPS потребується речення ORDER BY" -#: parser/parse_clause.c:3011 +#: parser/parse_clause.c:3016 #, c-format msgid "in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list" msgstr "для агрегатної функції з DISTINCT, вирази ORDER BY повинні з'являтись у списку аргументів" -#: parser/parse_clause.c:3012 +#: parser/parse_clause.c:3017 #, c-format msgid "for SELECT DISTINCT, ORDER BY expressions must appear in select list" msgstr "для SELECT DISTINCT вирази ORDER BY повинні бути в списку вибірки" -#: parser/parse_clause.c:3044 +#: parser/parse_clause.c:3049 #, c-format msgid "an aggregate with DISTINCT must have at least one argument" msgstr "агрегатна функція з DISTINCT повинна мати мінімум один аргумент" -#: parser/parse_clause.c:3045 +#: parser/parse_clause.c:3050 #, c-format msgid "SELECT DISTINCT must have at least one column" msgstr "SELECT DISTINCT повинен мати мінімум один стовпець" -#: parser/parse_clause.c:3111 parser/parse_clause.c:3143 +#: parser/parse_clause.c:3116 parser/parse_clause.c:3148 #, c-format msgid "SELECT DISTINCT ON expressions must match initial ORDER BY expressions" msgstr "Вирази SELECT DISTINCT ON повинні відповідати початковим виразам ORDER BY" -#: parser/parse_clause.c:3221 +#: parser/parse_clause.c:3226 #, c-format msgid "ASC/DESC is not allowed in ON CONFLICT clause" msgstr "ASC/DESC не дозволяється в реченні ON CONFLICT" -#: parser/parse_clause.c:3227 +#: parser/parse_clause.c:3232 #, c-format msgid "NULLS FIRST/LAST is not allowed in ON CONFLICT clause" msgstr "NULLS FIRST/LAST не довзоляється в реченні ON CONFLICT" -#: parser/parse_clause.c:3306 +#: parser/parse_clause.c:3311 #, c-format msgid "ON CONFLICT DO UPDATE requires inference specification or constraint name" msgstr "ON CONFLICT DO UPDATE вимагає специфікації висновку або імені обмеження" -#: parser/parse_clause.c:3307 +#: parser/parse_clause.c:3312 #, c-format msgid "For example, ON CONFLICT (column_name)." msgstr "Наприклад, ON CONFLICT (ім'я_стовпця)." -#: parser/parse_clause.c:3318 +#: parser/parse_clause.c:3323 #, c-format msgid "ON CONFLICT is not supported with system catalog tables" msgstr "ON CONFLICT не підтримується таблицями системного каталогу" -#: parser/parse_clause.c:3326 +#: parser/parse_clause.c:3331 #, c-format msgid "ON CONFLICT is not supported on table \"%s\" used as a catalog table" msgstr "ON CONFLICT не підтримується в таблиці \"%s\", що використовується як таблиця каталогу" -#: parser/parse_clause.c:3457 +#: parser/parse_clause.c:3462 #, c-format msgid "operator %s is not a valid ordering operator" msgstr "оператор %s не є дійсним оператором сортування" -#: parser/parse_clause.c:3459 +#: parser/parse_clause.c:3464 #, c-format msgid "Ordering operators must be \"<\" or \">\" members of btree operator families." msgstr "Оператори сортування повинні бути учасниками \"<\" або \">\" сімейств операторів btree." -#: parser/parse_clause.c:3770 +#: parser/parse_clause.c:3775 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s" msgstr "RANGE зі зсувом PRECEDING/FOLLOWING не підтримується для типу стовпця %s" -#: parser/parse_clause.c:3776 +#: parser/parse_clause.c:3781 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING is not supported for column type %s and offset type %s" msgstr "RANGE зі зсувом PRECEDING/FOLLOWING не підтримується для типу стовпця %s і типу зсуву %s" -#: parser/parse_clause.c:3779 +#: parser/parse_clause.c:3784 #, c-format msgid "Cast the offset value to an appropriate type." msgstr "Приведіть значення зсуву до потрібного типу." -#: parser/parse_clause.c:3784 +#: parser/parse_clause.c:3789 #, c-format msgid "RANGE with offset PRECEDING/FOLLOWING has multiple interpretations for column type %s and offset type %s" msgstr "RANGE зі зсувом PRECEDING/FOLLOWING має декілька інтерпретацій для типу стовпця %s і типу зсуву %s" -#: parser/parse_clause.c:3787 +#: parser/parse_clause.c:3792 #, c-format msgid "Cast the offset value to the exact intended type." msgstr "Приведіть значення зсуву в точності до призначеного типу." #: parser/parse_coerce.c:1050 parser/parse_coerce.c:1088 #: parser/parse_coerce.c:1106 parser/parse_coerce.c:1121 -#: parser/parse_expr.c:2083 parser/parse_expr.c:2691 parser/parse_expr.c:3497 -#: parser/parse_target.c:985 +#: parser/parse_expr.c:2146 parser/parse_expr.c:2754 parser/parse_expr.c:3405 +#: parser/parse_expr.c:3634 parser/parse_target.c:998 #, c-format msgid "cannot cast type %s to %s" msgstr "неможливо транслювати тип %s в %s" @@ -16857,19 +17258,19 @@ msgid "arguments declared \"%s\" are not all alike" msgstr "оголошенні аргументи \"%s\", повинні бути схожими" #: parser/parse_coerce.c:2249 parser/parse_coerce.c:2362 -#: utils/fmgr/funcapi.c:592 +#: utils/fmgr/funcapi.c:600 #, c-format msgid "argument declared %s is not an array but type %s" msgstr "аргумент, оголошений як %s , є не масивом, а типом %s" #: parser/parse_coerce.c:2282 parser/parse_coerce.c:2432 -#: utils/fmgr/funcapi.c:606 +#: utils/fmgr/funcapi.c:614 #, c-format msgid "argument declared %s is not a range type but type %s" msgstr "аргумент, оголошений як %s, є не діапазонним типом, а типом %s" #: parser/parse_coerce.c:2316 parser/parse_coerce.c:2396 -#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:624 utils/fmgr/funcapi.c:689 +#: parser/parse_coerce.c:2529 utils/fmgr/funcapi.c:632 utils/fmgr/funcapi.c:697 #, c-format msgid "argument declared %s is not a multirange type but type %s" msgstr "оголошений аргумент %s не є багатодіапазонним типом, а типом %s" @@ -16993,437 +17394,547 @@ msgstr "рекурсивне посилання на запит \"%s\" не по msgid "recursive reference to query \"%s\" must not appear within EXCEPT" msgstr "рекурсивне посилання на запит \"%s\" не повинне з'являтись в EXCEPT" -#: parser/parse_cte.c:133 -#, c-format -msgid "MERGE not supported in WITH query" -msgstr "MERGE не підтримується в запиті WITH" - -#: parser/parse_cte.c:143 +#: parser/parse_cte.c:136 #, c-format msgid "WITH query name \"%s\" specified more than once" msgstr "Ім’я запиту WITH \"%s\" вказано неодноразово" -#: parser/parse_cte.c:314 +#: parser/parse_cte.c:308 #, c-format msgid "could not identify an inequality operator for type %s" msgstr "не вдалося визначити оператора нерівності для типу %s" -#: parser/parse_cte.c:341 +#: parser/parse_cte.c:335 #, c-format msgid "WITH clause containing a data-modifying statement must be at the top level" msgstr "Речення WITH, яке містить оператор, що змінює дані, повинне бути на верхньому рівні" -#: parser/parse_cte.c:390 +#: parser/parse_cte.c:384 #, c-format msgid "recursive query \"%s\" column %d has type %s in non-recursive term but type %s overall" msgstr "у рекурсивному запиті \"%s\" стовпець %d має тип %s у нерекурсивній частині, але загалом тип %s" -#: parser/parse_cte.c:396 +#: parser/parse_cte.c:390 #, c-format msgid "Cast the output of the non-recursive term to the correct type." msgstr "Приведіть результат нерекурсивної частини до правильного типу." -#: parser/parse_cte.c:401 +#: parser/parse_cte.c:395 #, c-format msgid "recursive query \"%s\" column %d has collation \"%s\" in non-recursive term but collation \"%s\" overall" msgstr "у рекурсивному запиті \"%s\" стовпець %d має параметри сортування \"%s\" у нерекурсивній частині, але загалом параметри сортування \"%s\"" -#: parser/parse_cte.c:405 +#: parser/parse_cte.c:399 #, c-format msgid "Use the COLLATE clause to set the collation of the non-recursive term." msgstr "Використайте речення COLLATE, щоб встановити параметри сортування в нерекурсивній частині." -#: parser/parse_cte.c:426 +#: parser/parse_cte.c:420 #, c-format msgid "WITH query is not recursive" msgstr "Запит WITH не є рекурсивним" -#: parser/parse_cte.c:457 +#: parser/parse_cte.c:451 #, c-format msgid "with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT" msgstr "з реченням з SEARCH або CYCLE, ліва сторона UNION повинна бути SELECT" -#: parser/parse_cte.c:462 +#: parser/parse_cte.c:456 #, c-format msgid "with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT" msgstr "з реченням з SEARCH або CYCLE, права сторона UNION повинна бути SELECT" -#: parser/parse_cte.c:477 +#: parser/parse_cte.c:471 #, c-format msgid "search column \"%s\" not in WITH query column list" msgstr "пошуковий стовпець \"%s\" відсутній в списку стовпців запиту WITH" -#: parser/parse_cte.c:484 +#: parser/parse_cte.c:478 #, c-format msgid "search column \"%s\" specified more than once" msgstr "пошуковий стовпець \"%s\" вказано більше одного разу" -#: parser/parse_cte.c:493 +#: parser/parse_cte.c:487 #, c-format msgid "search sequence column name \"%s\" already used in WITH query column list" msgstr "назва послідовності пошуку \"%s\" вже використовується у списку стовпців запиту WITH" -#: parser/parse_cte.c:510 +#: parser/parse_cte.c:504 #, c-format msgid "cycle column \"%s\" not in WITH query column list" msgstr "стовпець циклу \"%s\" відсутній в списку стовпців запиту WITH" -#: parser/parse_cte.c:517 +#: parser/parse_cte.c:511 #, c-format msgid "cycle column \"%s\" specified more than once" msgstr "стовпець циклу \"%s\" вказано більше одного разу" -#: parser/parse_cte.c:526 +#: parser/parse_cte.c:520 #, c-format msgid "cycle mark column name \"%s\" already used in WITH query column list" msgstr "назва стовпця позначки циклу \"%s\" вже використовується у списку стовпців запиту WITH" -#: parser/parse_cte.c:533 +#: parser/parse_cte.c:527 #, c-format msgid "cycle path column name \"%s\" already used in WITH query column list" msgstr "назва стовпця циклу шляху \"%s\" вже використовується у списку стовпців запиту WITH" -#: parser/parse_cte.c:541 +#: parser/parse_cte.c:535 #, c-format msgid "cycle mark column name and cycle path column name are the same" msgstr "назва стовпця позначки циклу і назва стовпця циклу шляху однакові" -#: parser/parse_cte.c:551 +#: parser/parse_cte.c:545 #, c-format msgid "search sequence column name and cycle mark column name are the same" msgstr "назва стовпця послідовності пошуку і назва стовпця позначки циклу однакові" -#: parser/parse_cte.c:558 +#: parser/parse_cte.c:552 #, c-format msgid "search sequence column name and cycle path column name are the same" msgstr "назва стовпця послідовності пошуку і назва стовпця циклу шляху однакові" -#: parser/parse_cte.c:642 +#: parser/parse_cte.c:636 #, c-format msgid "WITH query \"%s\" has %d columns available but %d columns specified" msgstr "Запит WITH \"%s\" має %d доступних стовпців, але %d стовпців вказано" -#: parser/parse_cte.c:822 +#: parser/parse_cte.c:816 #, c-format msgid "mutual recursion between WITH items is not implemented" msgstr "взаємна рекурсія між елементами WITH не реалізована" -#: parser/parse_cte.c:874 +#: parser/parse_cte.c:868 #, c-format msgid "recursive query \"%s\" must not contain data-modifying statements" msgstr "рекурсивний запит \"%s\" не повинен містити оператори, які змінюють дані" -#: parser/parse_cte.c:882 +#: parser/parse_cte.c:876 #, c-format msgid "recursive query \"%s\" does not have the form non-recursive-term UNION [ALL] recursive-term" msgstr "рекурсивний запит \"%s\" не має форми (нерекурсивна частина) UNION [ALL] (рекурсивна частина)" -#: parser/parse_cte.c:926 +#: parser/parse_cte.c:911 #, c-format msgid "ORDER BY in a recursive query is not implemented" msgstr "ORDER BY в рекурсивному запиті не реалізовано" -#: parser/parse_cte.c:932 +#: parser/parse_cte.c:917 #, c-format msgid "OFFSET in a recursive query is not implemented" msgstr "OFFSET у рекурсивному запиті не реалізовано" -#: parser/parse_cte.c:938 +#: parser/parse_cte.c:923 #, c-format msgid "LIMIT in a recursive query is not implemented" msgstr "LIMIT у рекурсивному запиті не реалізовано" -#: parser/parse_cte.c:944 +#: parser/parse_cte.c:929 #, c-format msgid "FOR UPDATE/SHARE in a recursive query is not implemented" msgstr "FOR UPDATE/SHARE в рекурсивному запиті не реалізовано" -#: parser/parse_cte.c:1001 +#: parser/parse_cte.c:1008 #, c-format msgid "recursive reference to query \"%s\" must not appear more than once" msgstr "рекурсивне посилання на запит \"%s\" не повинне з'являтись неодноразово" -#: parser/parse_expr.c:294 +#: parser/parse_expr.c:313 #, c-format msgid "DEFAULT is not allowed in this context" msgstr "DEFAULT не допускається в цьому контексті" -#: parser/parse_expr.c:371 parser/parse_relation.c:3688 -#: parser/parse_relation.c:3698 parser/parse_relation.c:3716 -#: parser/parse_relation.c:3723 parser/parse_relation.c:3737 +#: parser/parse_expr.c:406 parser/parse_relation.c:3691 +#: parser/parse_relation.c:3701 parser/parse_relation.c:3719 +#: parser/parse_relation.c:3726 parser/parse_relation.c:3740 #, c-format msgid "column %s.%s does not exist" msgstr "стовпець %s.%s не існує" -#: parser/parse_expr.c:383 +#: parser/parse_expr.c:418 #, c-format msgid "column \"%s\" not found in data type %s" msgstr "стовпець \"%s\" не знайдено в типі даних %s" -#: parser/parse_expr.c:389 +#: parser/parse_expr.c:424 #, c-format msgid "could not identify column \"%s\" in record data type" msgstr "не вдалося ідентифікувати стовпець \"%s\" в типі запису" -#: parser/parse_expr.c:395 +#: parser/parse_expr.c:430 #, c-format msgid "column notation .%s applied to type %s, which is not a composite type" msgstr "запис імені стовпця .%s застосований до типу %s, котрий не є складеним типом" -#: parser/parse_expr.c:426 parser/parse_target.c:733 +#: parser/parse_expr.c:461 parser/parse_target.c:732 #, c-format msgid "row expansion via \"*\" is not supported here" msgstr "розширення рядка через \"*\" тут не підтримується" -#: parser/parse_expr.c:548 +#: parser/parse_expr.c:584 msgid "cannot use column reference in DEFAULT expression" msgstr "у виразі DEFAULT не можна використовувати посилання на стовпець" -#: parser/parse_expr.c:551 +#: parser/parse_expr.c:587 msgid "cannot use column reference in partition bound expression" msgstr "у виразі границі секції не можна використовувати посилання на стовпці" -#: parser/parse_expr.c:810 parser/parse_relation.c:833 -#: parser/parse_relation.c:915 parser/parse_target.c:1225 +#: parser/parse_expr.c:846 parser/parse_relation.c:833 +#: parser/parse_relation.c:915 parser/parse_target.c:1238 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "посилання на стовпець \"%s\" є неоднозначним" -#: parser/parse_expr.c:866 parser/parse_param.c:110 parser/parse_param.c:142 +#: parser/parse_expr.c:902 parser/parse_param.c:110 parser/parse_param.c:142 #: parser/parse_param.c:204 parser/parse_param.c:303 #, c-format msgid "there is no parameter $%d" msgstr "параметр $%d не існує" -#: parser/parse_expr.c:1066 +#. translator: %s is name of a SQL construct, eg NULLIF +#: parser/parse_expr.c:1103 parser/parse_expr.c:3065 #, c-format -msgid "NULLIF requires = operator to yield boolean" -msgstr "NULLIF потребує = щоб оператор повертав логічне значення" +msgid "%s requires = operator to yield boolean" +msgstr "" #. translator: %s is name of a SQL construct, eg NULLIF -#: parser/parse_expr.c:1072 parser/parse_expr.c:3007 +#: parser/parse_expr.c:1109 parser/parse_expr.c:3072 #, c-format msgid "%s must not return a set" msgstr "%s не повинна повертати набір" -#: parser/parse_expr.c:1457 parser/parse_expr.c:1489 +#: parser/parse_expr.c:1395 +#, c-format +msgid "MERGE_ACTION() can only be used in the RETURNING list of a MERGE command" +msgstr "" + +#: parser/parse_expr.c:1519 parser/parse_expr.c:1551 #, c-format msgid "number of columns does not match number of values" msgstr "кількість стовпців не відповідає кількості значень" -#: parser/parse_expr.c:1503 +#: parser/parse_expr.c:1565 #, c-format msgid "source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" msgstr "джерелом для елементу UPDATE з декількома стовпцями повинен бути вкладений SELECT або вираз ROW()" #. translator: %s is name of a SQL construct, eg GROUP BY -#: parser/parse_expr.c:1698 parser/parse_expr.c:2180 parser/parse_func.c:2677 +#: parser/parse_expr.c:1760 parser/parse_expr.c:2243 parser/parse_func.c:2679 #, c-format msgid "set-returning functions are not allowed in %s" msgstr "функції, повертаючі набори, не дозволяються в %s" -#: parser/parse_expr.c:1761 +#: parser/parse_expr.c:1824 msgid "cannot use subquery in check constraint" msgstr "в обмеженні-перевірці не можна використовувати підзапити" -#: parser/parse_expr.c:1765 +#: parser/parse_expr.c:1828 msgid "cannot use subquery in DEFAULT expression" msgstr "у виразі DEFAULT не можна використовувати підзапити" -#: parser/parse_expr.c:1768 +#: parser/parse_expr.c:1831 msgid "cannot use subquery in index expression" msgstr "в індексному виразі не можна використовувати підзапити" -#: parser/parse_expr.c:1771 +#: parser/parse_expr.c:1834 msgid "cannot use subquery in index predicate" msgstr "в предикаті індексу не можна використовувати підзапити" -#: parser/parse_expr.c:1774 +#: parser/parse_expr.c:1837 msgid "cannot use subquery in statistics expression" msgstr "у виразі статистики не можна використовувати підзапит" -#: parser/parse_expr.c:1777 +#: parser/parse_expr.c:1840 msgid "cannot use subquery in transform expression" msgstr "у виразі перетворення не можна використовувати підзапити" -#: parser/parse_expr.c:1780 +#: parser/parse_expr.c:1843 msgid "cannot use subquery in EXECUTE parameter" msgstr "в параметрі EXECUTE не можна використовувати підзапити" -#: parser/parse_expr.c:1783 +#: parser/parse_expr.c:1846 msgid "cannot use subquery in trigger WHEN condition" msgstr "в умові WHEN для тригеру не можна використовувати підзапити" -#: parser/parse_expr.c:1786 +#: parser/parse_expr.c:1849 msgid "cannot use subquery in partition bound" msgstr "в границі секції не можна використовувати підзапити" -#: parser/parse_expr.c:1789 +#: parser/parse_expr.c:1852 msgid "cannot use subquery in partition key expression" msgstr "у виразі ключа секціонування не можна використовувати підзапити" -#: parser/parse_expr.c:1792 +#: parser/parse_expr.c:1855 msgid "cannot use subquery in CALL argument" msgstr "в аргументі CALL не можна використовувати підзапити" -#: parser/parse_expr.c:1795 +#: parser/parse_expr.c:1858 msgid "cannot use subquery in COPY FROM WHERE condition" msgstr "не можна використовувати підзапити в умові COPY FROM WHERE" -#: parser/parse_expr.c:1798 +#: parser/parse_expr.c:1861 msgid "cannot use subquery in column generation expression" msgstr "у виразі генерації стовпців не можна використовувати підзапити" -#: parser/parse_expr.c:1851 parser/parse_expr.c:3628 +#: parser/parse_expr.c:1914 parser/parse_expr.c:3764 #, c-format msgid "subquery must return only one column" msgstr "підзапит повинен повертати лише один стовпець" -#: parser/parse_expr.c:1922 +#: parser/parse_expr.c:1985 #, c-format msgid "subquery has too many columns" msgstr "підзапит має занадто багато стовпців" -#: parser/parse_expr.c:1927 +#: parser/parse_expr.c:1990 #, c-format msgid "subquery has too few columns" msgstr "підзапит має занадто мало стовпців" -#: parser/parse_expr.c:2023 +#: parser/parse_expr.c:2086 #, c-format msgid "cannot determine type of empty array" msgstr "тип пустого масиву визначити не можна" -#: parser/parse_expr.c:2024 +#: parser/parse_expr.c:2087 #, c-format msgid "Explicitly cast to the desired type, for example ARRAY[]::integer[]." msgstr "Приведіть його до бажаного типу явним чином, наприклад ARRAY[]::integer[]." -#: parser/parse_expr.c:2038 +#: parser/parse_expr.c:2101 #, c-format msgid "could not find element type for data type %s" msgstr "не вдалося знайти тип елементу для типу даних %s" -#: parser/parse_expr.c:2121 +#: parser/parse_expr.c:2184 #, c-format msgid "ROW expressions can have at most %d entries" msgstr "ROW вирази можуть мати максимум %d елементів" -#: parser/parse_expr.c:2326 +#: parser/parse_expr.c:2389 #, c-format msgid "unnamed XML attribute value must be a column reference" msgstr "замість значення XML-атрибуту без імені повинен вказуватись стовпець" -#: parser/parse_expr.c:2327 +#: parser/parse_expr.c:2390 #, c-format msgid "unnamed XML element value must be a column reference" msgstr "замість значення XML-елементу без імені повинен вказуватись стовпець" -#: parser/parse_expr.c:2342 +#: parser/parse_expr.c:2405 #, c-format msgid "XML attribute name \"%s\" appears more than once" msgstr "Ім'я XML-атрибуту \"%s\" з'являється неодноразово" -#: parser/parse_expr.c:2450 +#: parser/parse_expr.c:2513 #, c-format msgid "cannot cast XMLSERIALIZE result to %s" msgstr "привести результат XMLSERIALIZE до %s не можна" -#: parser/parse_expr.c:2764 parser/parse_expr.c:2960 +#: parser/parse_expr.c:2827 parser/parse_expr.c:3023 #, c-format msgid "unequal number of entries in row expressions" msgstr "неоднакова кількість елементів у виразах рядка" -#: parser/parse_expr.c:2774 +#: parser/parse_expr.c:2837 #, c-format msgid "cannot compare rows of zero length" msgstr "рядки нульової довжини порівнювати не можна" -#: parser/parse_expr.c:2799 +#: parser/parse_expr.c:2862 #, c-format msgid "row comparison operator must yield type boolean, not type %s" msgstr "оператор порівняння рядків повинен видавати логічний тип, а не %s" -#: parser/parse_expr.c:2806 +#: parser/parse_expr.c:2869 #, c-format msgid "row comparison operator must not return a set" msgstr "оператор порівняння рядків повинен вертати набір" -#: parser/parse_expr.c:2865 parser/parse_expr.c:2906 +#: parser/parse_expr.c:2928 parser/parse_expr.c:2969 #, c-format msgid "could not determine interpretation of row comparison operator %s" msgstr "не вдалося визначити інтерпретацію оператора порівняння рядків %s" -#: parser/parse_expr.c:2867 +#: parser/parse_expr.c:2930 #, c-format msgid "Row comparison operators must be associated with btree operator families." msgstr "Оператори порівняння рядків повинні бути пов'язанні з сімейством операторів btree." -#: parser/parse_expr.c:2908 +#: parser/parse_expr.c:2971 #, c-format msgid "There are multiple equally-plausible candidates." msgstr "Існує декілька рівноцінних кандидатів." -#: parser/parse_expr.c:3001 -#, c-format -msgid "IS DISTINCT FROM requires = operator to yield boolean" -msgstr "IS DISTINCT FROM, потребує = щоб оператор повертав логічне значення" - -#: parser/parse_expr.c:3239 +#: parser/parse_expr.c:3306 #, c-format msgid "JSON ENCODING clause is only allowed for bytea input type" msgstr "Вираз JSON ENCODING дозволено лише для типу введення bytea" -#: parser/parse_expr.c:3261 +#: parser/parse_expr.c:3370 #, c-format msgid "cannot use non-string types with implicit FORMAT JSON clause" msgstr "використовувати типи, які не є string з неявним виразом FORMAT JSON не можна" -#: parser/parse_expr.c:3262 +#: parser/parse_expr.c:3371 #, c-format msgid "cannot use non-string types with explicit FORMAT JSON clause" msgstr "використовувати типи, які не є string з явним виразом FORMAT JSON не можна" -#: parser/parse_expr.c:3335 +#: parser/parse_expr.c:3460 #, c-format msgid "cannot use JSON format with non-string output types" msgstr "використовувати формат JSON з типами виводу, які не є string не можна" -#: parser/parse_expr.c:3348 +#: parser/parse_expr.c:3473 #, c-format msgid "cannot set JSON encoding for non-bytea output types" msgstr "встановити кодування JSON для типів виводу, які не є bytea не можна" -#: parser/parse_expr.c:3353 +#: parser/parse_expr.c:3478 #, c-format msgid "unsupported JSON encoding" msgstr "непідтримуване JSON кодування" -#: parser/parse_expr.c:3354 +#: parser/parse_expr.c:3479 #, c-format msgid "Only UTF8 JSON encoding is supported." msgstr "Підтримується лише кодування UTF8 формату JSON." -#: parser/parse_expr.c:3391 +#: parser/parse_expr.c:3516 #, c-format msgid "returning SETOF types is not supported in SQL/JSON functions" msgstr "повернення типів SETOF не підтримується у функціях SQL/JSON" -#: parser/parse_expr.c:3712 parser/parse_func.c:865 +#: parser/parse_expr.c:3521 +#, c-format +msgid "returning pseudo-types is not supported in SQL/JSON functions" +msgstr "" + +#: parser/parse_expr.c:3849 parser/parse_func.c:866 #, c-format msgid "aggregate ORDER BY is not implemented for window functions" msgstr "агрегатне речення ORDER BY для віконних функцій не реалізовано" -#: parser/parse_expr.c:3934 +#: parser/parse_expr.c:4072 #, c-format msgid "cannot use JSON FORMAT ENCODING clause for non-bytea input types" msgstr "використовувати вираз JSON FORMAT ENCODING для типів введення, які не є bytea не можна" -#: parser/parse_expr.c:3954 +#: parser/parse_expr.c:4092 #, c-format msgid "cannot use type %s in IS JSON predicate" msgstr "використовувати тип %s в предикаті IS JSON не можна" +#: parser/parse_expr.c:4118 parser/parse_expr.c:4238 +#, c-format +msgid "cannot use RETURNING type %s in %s" +msgstr "не можна використовувати тип RETURNING %s в %s" + +#: parser/parse_expr.c:4167 +#, c-format +msgid "cannot use non-string types with WITH UNIQUE KEYS clause" +msgstr "не можна використовувати не строкові типи з пунктом WITH UNIQUE KEYS" + +#: parser/parse_expr.c:4241 +#, c-format +msgid "Try returning a string type or bytea." +msgstr "Спробуйте повернути тип string або bytea." + +#: parser/parse_expr.c:4306 +#, c-format +msgid "cannot specify FORMAT JSON in RETURNING clause of %s()" +msgstr "" + +#: parser/parse_expr.c:4319 +#, c-format +msgid "SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used" +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4333 parser/parse_expr.c:4362 parser/parse_expr.c:4393 +#: parser/parse_expr.c:4419 parser/parse_expr.c:4445 +#: parser/parse_jsontable.c:94 +#, c-format +msgid "invalid %s behavior" +msgstr "" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4336 parser/parse_expr.c:4365 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s." +msgstr "" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4343 parser/parse_expr.c:4372 parser/parse_expr.c:4401 +#: parser/parse_expr.c:4429 parser/parse_expr.c:4455 +#, c-format +msgid "invalid %s behavior for column \"%s\"" +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4346 parser/parse_expr.c:4375 +#, c-format +msgid "Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns." +msgstr "" + +#: parser/parse_expr.c:4394 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s." +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4404 +#, c-format +msgid "Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns." +msgstr "" + +#. translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY), +#. second %s is a SQL/JSON function name (e.g. JSON_QUERY) +#: parser/parse_expr.c:4422 parser/parse_expr.c:4448 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s." +msgstr "" + +#. translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) +#: parser/parse_expr.c:4432 parser/parse_expr.c:4458 +#, c-format +msgid "Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns." +msgstr "" + +#: parser/parse_expr.c:4488 +#, c-format +msgid "JSON path expression must be of type %s, not of type %s" +msgstr "" + +#: parser/parse_expr.c:4706 +#, c-format +msgid "can only specify a constant, non-aggregate function, or operator expression for DEFAULT" +msgstr "" + +#: parser/parse_expr.c:4711 +#, c-format +msgid "DEFAULT expression must not contain column references" +msgstr "" + +#: parser/parse_expr.c:4716 +#, c-format +msgid "DEFAULT expression must not return a set" +msgstr "" + +#: parser/parse_expr.c:4792 parser/parse_expr.c:4801 +#, c-format +msgid "cannot cast behavior expression of type %s to %s" +msgstr "" + +#: parser/parse_expr.c:4795 +#, c-format +msgid "You will need to explicitly cast the expression to type %s." +msgstr "" + #: parser/parse_func.c:194 #, c-format msgid "argument name \"%s\" used more than once" @@ -17434,7 +17945,7 @@ msgstr "ім’я аргументу \"%s\" використовується н msgid "positional argument cannot follow named argument" msgstr "позиційний аргумент не може стежити за іменованим аргументомв" -#: parser/parse_func.c:287 parser/parse_func.c:2367 +#: parser/parse_func.c:287 parser/parse_func.c:2368 #, c-format msgid "%s is not a procedure" msgstr "%s не є процедурою" @@ -17557,7 +18068,7 @@ msgstr "Не вдалося обрати найкращу кандидатуру msgid "No aggregate function matches the given name and argument types. Perhaps you misplaced ORDER BY; ORDER BY must appear after all regular arguments of the aggregate." msgstr "Агрегатну функцію з цим ім'ям і типами аргументів не знайдено. Можливо, ви невірно розмістили речення ORDER BY; речення ORDER BY повинно з'являтись після всіх звичайних аргументів агрегату." -#: parser/parse_func.c:622 parser/parse_func.c:2410 +#: parser/parse_func.c:622 parser/parse_func.c:2411 #, c-format msgid "procedure %s does not exist" msgstr "процедура %s не існує" @@ -17577,7 +18088,7 @@ msgstr "Функцію з цим ім'ям і типами аргументів msgid "VARIADIC argument must be an array" msgstr "Аргумент VARIADIC повинен бути масивом" -#: parser/parse_func.c:791 parser/parse_func.c:855 +#: parser/parse_func.c:791 parser/parse_func.c:856 #, c-format msgid "%s(*) must be used to call a parameterless aggregate function" msgstr " %s(*) треба використовувати для виклику агрегатної функції без параметрів" @@ -17592,42 +18103,42 @@ msgstr "агрегатні функції не можуть повертати msgid "aggregates cannot use named arguments" msgstr "агрегатні функції не можуть використовувати іменовані аргументи" -#: parser/parse_func.c:845 +#: parser/parse_func.c:846 #, c-format msgid "DISTINCT is not implemented for window functions" msgstr "DISTINCT для віконних функції не реалізовано" -#: parser/parse_func.c:874 +#: parser/parse_func.c:875 #, c-format msgid "FILTER is not implemented for non-aggregate window functions" msgstr "FILTER для неагрегатних віконних функцій не реалізовано" -#: parser/parse_func.c:883 +#: parser/parse_func.c:884 #, c-format msgid "window function calls cannot contain set-returning function calls" msgstr "виклики віконних функцій не можуть містити виклики функцій, які повертають набори" -#: parser/parse_func.c:891 +#: parser/parse_func.c:892 #, c-format msgid "window functions cannot return sets" msgstr "віконні функції не можуть повертати набори" -#: parser/parse_func.c:2166 parser/parse_func.c:2439 +#: parser/parse_func.c:2167 parser/parse_func.c:2440 #, c-format msgid "could not find a function named \"%s\"" msgstr "не вдалося знайти функцію з іменем \"%s\"" -#: parser/parse_func.c:2180 parser/parse_func.c:2457 +#: parser/parse_func.c:2181 parser/parse_func.c:2458 #, c-format msgid "function name \"%s\" is not unique" msgstr "ім’я функції \"%s\" не є унікальним" -#: parser/parse_func.c:2182 parser/parse_func.c:2460 +#: parser/parse_func.c:2183 parser/parse_func.c:2461 #, c-format msgid "Specify the argument list to select the function unambiguously." msgstr "Укажіть список аргументів для однозначного вибору функції." -#: parser/parse_func.c:2226 +#: parser/parse_func.c:2227 #, c-format msgid "procedures cannot have more than %d argument" msgid_plural "procedures cannot have more than %d arguments" @@ -17636,221 +18147,215 @@ msgstr[1] "процедури не можуть мати більш ніж %d а msgstr[2] "процедури не можуть мати більш ніж %d аргументів" msgstr[3] "процедури не можуть мати більш ніж %d аргументів" -#: parser/parse_func.c:2357 +#: parser/parse_func.c:2358 #, c-format msgid "%s is not a function" msgstr "%s не є функцією" -#: parser/parse_func.c:2377 +#: parser/parse_func.c:2378 #, c-format msgid "function %s is not an aggregate" msgstr "функція %s не є агрегатною" -#: parser/parse_func.c:2405 +#: parser/parse_func.c:2406 #, c-format msgid "could not find a procedure named \"%s\"" msgstr "не вдалося знайти процедуру з іменем \"%s\"" -#: parser/parse_func.c:2419 +#: parser/parse_func.c:2420 #, c-format msgid "could not find an aggregate named \"%s\"" msgstr "не вдалося знайти агрегат з ім'ям \"%s\"" -#: parser/parse_func.c:2424 +#: parser/parse_func.c:2425 #, c-format msgid "aggregate %s(*) does not exist" msgstr "агрегат %s (*) не існує" -#: parser/parse_func.c:2429 +#: parser/parse_func.c:2430 #, c-format msgid "aggregate %s does not exist" msgstr "агрегат %s не існує" -#: parser/parse_func.c:2465 +#: parser/parse_func.c:2466 #, c-format msgid "procedure name \"%s\" is not unique" msgstr "назва процедури \"%s\" не є унікальною" -#: parser/parse_func.c:2468 +#: parser/parse_func.c:2469 #, c-format msgid "Specify the argument list to select the procedure unambiguously." msgstr "Вкажіть список аргументів для однозначного вибору процедури." -#: parser/parse_func.c:2473 +#: parser/parse_func.c:2474 #, c-format msgid "aggregate name \"%s\" is not unique" msgstr "назва агрегатної функції \"%s\" не є унікальною" -#: parser/parse_func.c:2476 +#: parser/parse_func.c:2477 #, c-format msgid "Specify the argument list to select the aggregate unambiguously." msgstr "Вкажіть список аргументів для однозначного вибору агрегатної функції." -#: parser/parse_func.c:2481 +#: parser/parse_func.c:2482 #, c-format msgid "routine name \"%s\" is not unique" msgstr "назва підпрограми \"%s\" не є унікальною" -#: parser/parse_func.c:2484 +#: parser/parse_func.c:2485 #, c-format msgid "Specify the argument list to select the routine unambiguously." msgstr "Вкажіть список аргументів для однозначного вибору підпрограми." -#: parser/parse_func.c:2539 +#: parser/parse_func.c:2540 msgid "set-returning functions are not allowed in JOIN conditions" msgstr "функції, що повертають множину, не можна застосовувати в умовах групування" -#: parser/parse_func.c:2560 +#: parser/parse_func.c:2561 msgid "set-returning functions are not allowed in policy expressions" msgstr "функції, що повертають множину, не можна застосовувати у виразах політики" -#: parser/parse_func.c:2576 +#: parser/parse_func.c:2577 msgid "set-returning functions are not allowed in window definitions" msgstr "функції, що повертають множину, не можна застосовувати у віконних визначеннях" -#: parser/parse_func.c:2613 +#: parser/parse_func.c:2615 msgid "set-returning functions are not allowed in MERGE WHEN conditions" msgstr "функції, які повертають набір, не можна застосовувати в умовах MERGE WHEN" -#: parser/parse_func.c:2617 +#: parser/parse_func.c:2619 msgid "set-returning functions are not allowed in check constraints" msgstr "функції, що повертають множину, не можна застосовувати в обмеженнях Check" -#: parser/parse_func.c:2621 +#: parser/parse_func.c:2623 msgid "set-returning functions are not allowed in DEFAULT expressions" msgstr "функції, що повертають множину, не можна застосовувати у стандартних виразах" -#: parser/parse_func.c:2624 +#: parser/parse_func.c:2626 msgid "set-returning functions are not allowed in index expressions" msgstr "функції, що повертають множину, не можна застосовувати в індексних виразах" -#: parser/parse_func.c:2627 +#: parser/parse_func.c:2629 msgid "set-returning functions are not allowed in index predicates" msgstr "функції, що повертають множину, не можна застосовувати в індексних предикатах" -#: parser/parse_func.c:2630 +#: parser/parse_func.c:2632 msgid "set-returning functions are not allowed in statistics expressions" msgstr "функції, що повертають набори, не можна застосовувати у виразах статистики" -#: parser/parse_func.c:2633 +#: parser/parse_func.c:2635 msgid "set-returning functions are not allowed in transform expressions" msgstr "функції, що повертають множину, не можна застосовувати у виразах перетворення" -#: parser/parse_func.c:2636 +#: parser/parse_func.c:2638 msgid "set-returning functions are not allowed in EXECUTE parameters" msgstr "функції, що повертають множину, не можна застосовуватив параметрах виконання" -#: parser/parse_func.c:2639 +#: parser/parse_func.c:2641 msgid "set-returning functions are not allowed in trigger WHEN conditions" msgstr "функції, що повертають множину, не можна застосовувати в умовах для тригерів WHEN" -#: parser/parse_func.c:2642 +#: parser/parse_func.c:2644 msgid "set-returning functions are not allowed in partition bound" msgstr "функції, що повертають множину не можна застосовувати в границі секції" -#: parser/parse_func.c:2645 +#: parser/parse_func.c:2647 msgid "set-returning functions are not allowed in partition key expressions" msgstr "функції, що повертають множину, не можна застосовувати у виразах ключа розділення" -#: parser/parse_func.c:2648 +#: parser/parse_func.c:2650 msgid "set-returning functions are not allowed in CALL arguments" msgstr "функції, що повертають множину, не можна застосовувати в аргументах Відеовикликів" -#: parser/parse_func.c:2651 +#: parser/parse_func.c:2653 msgid "set-returning functions are not allowed in COPY FROM WHERE conditions" msgstr "функції, що повертають множину не можна застосовувати в умовах COPY FROM WHERE" -#: parser/parse_func.c:2654 +#: parser/parse_func.c:2656 msgid "set-returning functions are not allowed in column generation expressions" msgstr "функції, що повертають множину не можна застосовувати у виразах генерації стовпців" -#: parser/parse_merge.c:119 +#: parser/parse_jsontable.c:95 +#, c-format +msgid "Only EMPTY [ ARRAY ] or ERROR is allowed in the top-level ON ERROR clause." +msgstr "" + +#: parser/parse_jsontable.c:189 parser/parse_jsontable.c:203 +#, c-format +msgid "duplicate JSON_TABLE column or path name: %s" +msgstr "" + +#: parser/parse_merge.c:129 #, c-format msgid "WITH RECURSIVE is not supported for MERGE statement" msgstr "WITH RECURSIVE не підтримується для інструкції MERGE" -#: parser/parse_merge.c:161 +#: parser/parse_merge.c:176 #, c-format msgid "unreachable WHEN clause specified after unconditional WHEN clause" msgstr "недосяжна речення WHEN зазначено після безумовного речення WHEN" -#: parser/parse_merge.c:191 -#, c-format -msgid "MERGE is not supported for relations with rules." -msgstr "MERGE не підтримує відношення з правилами." - -#: parser/parse_merge.c:208 +#: parser/parse_merge.c:222 #, c-format msgid "name \"%s\" specified more than once" msgstr "ім'я \"%s\" вказано кілька разів" -#: parser/parse_merge.c:210 +#: parser/parse_merge.c:224 #, c-format msgid "The name is used both as MERGE target table and data source." msgstr "Ім'я вказано одночасно як цільова таблиця та джерело MERGE." -#: parser/parse_node.c:87 +#: parser/parse_node.c:82 #, c-format msgid "target lists can have at most %d entries" msgstr "цільові списки можуть мати максимум %d елементів" -#: parser/parse_oper.c:123 parser/parse_oper.c:690 +#: parser/parse_oper.c:114 parser/parse_oper.c:678 #, c-format msgid "postfix operators are not supported" msgstr "постфіксні оператори не підтримуються" -#: parser/parse_oper.c:130 parser/parse_oper.c:649 utils/adt/regproc.c:509 -#: utils/adt/regproc.c:683 -#, c-format -msgid "operator does not exist: %s" -msgstr "оператор не існує: %s" - -#: parser/parse_oper.c:229 +#: parser/parse_oper.c:217 #, c-format msgid "Use an explicit ordering operator or modify the query." msgstr "Використати явний оператор сортування або змінити запит." -#: parser/parse_oper.c:485 +#: parser/parse_oper.c:473 #, c-format msgid "operator requires run-time type coercion: %s" msgstr "оператор вимагає приведення типів під час виконання: %s" -#: parser/parse_oper.c:641 +#: parser/parse_oper.c:629 #, c-format msgid "operator is not unique: %s" msgstr "оператор не є унікальним: %s" -#: parser/parse_oper.c:643 +#: parser/parse_oper.c:631 #, c-format msgid "Could not choose a best candidate operator. You might need to add explicit type casts." msgstr "Не вдалося вибрати найкращу кандидатуру оператора. Вам, можливо треба додати явні приведення типів." -#: parser/parse_oper.c:652 +#: parser/parse_oper.c:640 #, c-format msgid "No operator matches the given name and argument type. You might need to add an explicit type cast." msgstr "Жодний оператор не відповідає даному імені та типу аргументу. Вам, можливо, треба додати явне приведення типу." -#: parser/parse_oper.c:654 +#: parser/parse_oper.c:642 #, c-format msgid "No operator matches the given name and argument types. You might need to add explicit type casts." msgstr "Жодний оператор не відповідає даному імені та типу аргументу. Вам, можливо, треба додати явні приведення типів." -#: parser/parse_oper.c:714 parser/parse_oper.c:828 -#, c-format -msgid "operator is only a shell: %s" -msgstr "оператор є лише оболонкою: %s" - -#: parser/parse_oper.c:816 +#: parser/parse_oper.c:803 #, c-format msgid "op ANY/ALL (array) requires array on right side" msgstr "op ANY/ALL (масив) вимагає масив справа" -#: parser/parse_oper.c:858 +#: parser/parse_oper.c:844 #, c-format msgid "op ANY/ALL (array) requires operator to yield boolean" msgstr "op ANY/ALL (масив) вимагає оператора для видання логічного типу" -#: parser/parse_oper.c:863 +#: parser/parse_oper.c:849 #, c-format msgid "op ANY/ALL (array) requires operator not to return a set" msgstr "op ANY/ALL (масив) вимагає оператора не для повернення множини" @@ -17860,7 +18365,7 @@ msgstr "op ANY/ALL (масив) вимагає оператора не для п msgid "inconsistent types deduced for parameter $%d" msgstr "для параметру $%d виведені неузгоджені типи" -#: parser/parse_param.c:309 tcop/postgres.c:740 +#: parser/parse_param.c:309 tcop/postgres.c:744 #, c-format msgid "could not determine data type of parameter $%d" msgstr "не вдалося визначити тип даних параметра $%d" @@ -17880,13 +18385,13 @@ msgstr "посилання на таблицю %u неоднозначне" msgid "table name \"%s\" specified more than once" msgstr "ім'я таблиці \"%s\" вказано більше одного разу" -#: parser/parse_relation.c:494 parser/parse_relation.c:3630 -#: parser/parse_relation.c:3639 +#: parser/parse_relation.c:494 parser/parse_relation.c:3633 +#: parser/parse_relation.c:3642 #, c-format msgid "invalid reference to FROM-clause entry for table \"%s\"" msgstr "в елементі речення FROM неприпустиме посилання на таблицю \"%s\"" -#: parser/parse_relation.c:498 parser/parse_relation.c:3641 +#: parser/parse_relation.c:498 parser/parse_relation.c:3644 #, c-format msgid "There is an entry for table \"%s\", but it cannot be referenced from this part of the query." msgstr "Таблиця \"%s\" присутня в запиті, але посилатися на неї з цієї частини запиту не можна." @@ -17912,7 +18417,7 @@ msgid "cannot use system column \"%s\" in MERGE WHEN condition" msgstr "неможливо використати симтемний стовпець \"%s\" в умові MERGE WHEN" #: parser/parse_relation.c:1236 parser/parse_relation.c:1691 -#: parser/parse_relation.c:2388 +#: parser/parse_relation.c:2384 #, c-format msgid "table \"%s\" has %d columns available but %d columns specified" msgstr "таблиця \"%s\" має %d доступних стовпців, але вказано %d стовпців" @@ -17927,157 +18432,157 @@ msgstr "Існує WITH елемент \"%s\" але на нього не мож msgid "Use WITH RECURSIVE, or re-order the WITH items to remove forward references." msgstr "Використовувати WITH RECURSIVE, або перевпорядкувати елементи WITH, щоб видалити попередні посилання." -#: parser/parse_relation.c:1834 +#: parser/parse_relation.c:1833 #, c-format msgid "a column definition list is redundant for a function with OUT parameters" msgstr "список з визначенням стовпців не потрібен для функції з параметрами OUT" -#: parser/parse_relation.c:1840 +#: parser/parse_relation.c:1839 #, c-format msgid "a column definition list is redundant for a function returning a named composite type" msgstr "список з визначенням стовпців не потрібен для функції, яка повертає іменований складений тип" -#: parser/parse_relation.c:1847 +#: parser/parse_relation.c:1846 #, c-format msgid "a column definition list is only allowed for functions returning \"record\"" msgstr "список з визначенням стовпців дозволений лише для функцій, що повертають \"запис\"" -#: parser/parse_relation.c:1858 +#: parser/parse_relation.c:1857 #, c-format msgid "a column definition list is required for functions returning \"record\"" msgstr "список з визначенням стовпців вимагається для функцій, що повертають \"запис\"" -#: parser/parse_relation.c:1895 +#: parser/parse_relation.c:1894 #, c-format msgid "column definition lists can have at most %d entries" msgstr "списки визначень стовпців можуть мати максимум %d елементів" -#: parser/parse_relation.c:1955 +#: parser/parse_relation.c:1954 #, c-format msgid "function \"%s\" in FROM has unsupported return type %s" msgstr "функція \"%s\" у FROM повертає тип, що не підтримується %s" -#: parser/parse_relation.c:1982 parser/parse_relation.c:2068 +#: parser/parse_relation.c:1981 parser/parse_relation.c:2066 #, c-format msgid "functions in FROM can return at most %d columns" msgstr "функції з FROM можуть повертати не більше %d стовпців" -#: parser/parse_relation.c:2098 +#: parser/parse_relation.c:2096 #, c-format msgid "%s function has %d columns available but %d columns specified" msgstr "функція \"%s\" має %d доступних стовпців, але вказано %d стовпців" -#: parser/parse_relation.c:2180 +#: parser/parse_relation.c:2177 #, c-format msgid "VALUES lists \"%s\" have %d columns available but %d columns specified" msgstr "VALUES списки \"%s\" мають %d доступних стовпців, але %d стовпців вказано" -#: parser/parse_relation.c:2246 +#: parser/parse_relation.c:2242 #, c-format msgid "joins can have at most %d columns" msgstr "з'єднання можуть мати максимум %d стовпців" -#: parser/parse_relation.c:2271 +#: parser/parse_relation.c:2267 #, c-format msgid "join expression \"%s\" has %d columns available but %d columns specified" msgstr "вираз з'єднання \"%s\" має %d доступних стовпців, але %d стовпців вказано" -#: parser/parse_relation.c:2361 +#: parser/parse_relation.c:2357 #, c-format msgid "WITH query \"%s\" does not have a RETURNING clause" msgstr "WITH запит \"%s\" не має речення RETURNING" -#: parser/parse_relation.c:3632 +#: parser/parse_relation.c:3635 #, c-format msgid "Perhaps you meant to reference the table alias \"%s\"." msgstr "Можливо, малося на увазі посилання на псевдонім таблиці \"%s\"." -#: parser/parse_relation.c:3644 +#: parser/parse_relation.c:3647 #, c-format msgid "To reference that table, you must mark this subquery with LATERAL." msgstr "Щоб використати цю таблицю, вам потрібно позначити цей підзапит як LATERAL." -#: parser/parse_relation.c:3650 +#: parser/parse_relation.c:3653 #, c-format msgid "missing FROM-clause entry for table \"%s\"" msgstr "таблиця \"%s\" відсутня в реченні FROM" -#: parser/parse_relation.c:3690 +#: parser/parse_relation.c:3693 #, c-format msgid "There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query." msgstr "Є стовпці з назвою \"%s\", але вони знаходяться в таблицях, на які не можна посилатися з цієї частини запиту." -#: parser/parse_relation.c:3692 +#: parser/parse_relation.c:3695 #, c-format msgid "Try using a table-qualified name." msgstr "Спробуй використати повне ім'я включно з таблицею." -#: parser/parse_relation.c:3700 +#: parser/parse_relation.c:3703 #, c-format msgid "There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query." msgstr "Є стовпець з іменем \"%s\" в таблиці \"%s\", але на нього не можна посилатись з цієї частини запиту." -#: parser/parse_relation.c:3703 +#: parser/parse_relation.c:3706 #, c-format msgid "To reference that column, you must mark this subquery with LATERAL." msgstr "Щоб використати цей стовпець, вам потрібно позначити цей підзапит як LATERAL." -#: parser/parse_relation.c:3705 +#: parser/parse_relation.c:3708 #, c-format msgid "To reference that column, you must use a table-qualified name." msgstr "Щоб посилатися на цей стовпець, ви повинні використовувати повне ім'я включно з таблицею." -#: parser/parse_relation.c:3725 +#: parser/parse_relation.c:3728 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\"." msgstr "Можливо, передбачалось посилання на стовпець \"%s.%s\"." -#: parser/parse_relation.c:3739 +#: parser/parse_relation.c:3742 #, c-format msgid "Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\"." msgstr "Можливо, передбачалось посилання на стовпець \"%s.%s\" або стовпець \"%s.%s\"." -#: parser/parse_target.c:481 parser/parse_target.c:796 +#: parser/parse_target.c:480 parser/parse_target.c:795 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "призначити значення системному стовпцю \"%s\" не можна" -#: parser/parse_target.c:509 +#: parser/parse_target.c:508 #, c-format msgid "cannot set an array element to DEFAULT" msgstr "елементу масива не можна встановити значення DEFAULT" -#: parser/parse_target.c:514 +#: parser/parse_target.c:513 #, c-format msgid "cannot set a subfield to DEFAULT" msgstr "підполю не можна встановити значення DEFAULT" -#: parser/parse_target.c:588 +#: parser/parse_target.c:587 #, c-format msgid "column \"%s\" is of type %s but expression is of type %s" msgstr "стовпець \"%s\" має тип %s, а вираз %s" -#: parser/parse_target.c:780 +#: parser/parse_target.c:779 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type" msgstr "призначити значення полю \"%s\" стовпця \"%s\" не можна, тому, що тип %s не є складеним типом" -#: parser/parse_target.c:789 +#: parser/parse_target.c:788 #, c-format msgid "cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s" msgstr "призначити значення полю \"%s\" стовпця \"%s\" не можна, тому, що в типі даних %s немає такого стовпця" -#: parser/parse_target.c:869 +#: parser/parse_target.c:877 #, c-format msgid "subscripted assignment to \"%s\" requires type %s but expression is of type %s" msgstr "індексоване присвоєння \"%s\" вимагає тип %s, але вираз має тип %s" -#: parser/parse_target.c:879 +#: parser/parse_target.c:887 #, c-format msgid "subfield \"%s\" is of type %s but expression is of type %s" msgstr "підполе \"%s\" має тип %s, але вираз має тип %s" -#: parser/parse_target.c:1314 +#: parser/parse_target.c:1327 #, c-format msgid "SELECT * with no tables specified is not valid" msgstr "SELECT * повинен посилатись на таблиці" @@ -18097,8 +18602,8 @@ msgstr "неправильне посилання %%TYPE (занадто баг msgid "type reference %s converted to %s" msgstr "посилання на тип %s перетворене на тип %s" -#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:395 -#: utils/cache/typcache.c:450 +#: parser/parse_type.c:278 parser/parse_type.c:813 utils/cache/typcache.c:397 +#: utils/cache/typcache.c:452 #, c-format msgid "type \"%s\" is only a shell" msgstr "тип \"%s\" є лише оболонкою" @@ -18118,330 +18623,330 @@ msgstr "модифікатором типу повинна бути звичай msgid "invalid type name \"%s\"" msgstr "невірне ім'я типу \"%s\"" -#: parser/parse_utilcmd.c:264 +#: parser/parse_utilcmd.c:263 #, c-format msgid "cannot create partitioned table as inheritance child" msgstr "створити секціоновану таблицю в якості нащадка не можна" -#: parser/parse_utilcmd.c:589 +#: parser/parse_utilcmd.c:475 +#, c-format +msgid "cannot set logged status of a temporary sequence" +msgstr "" + +#: parser/parse_utilcmd.c:611 #, c-format msgid "array of serial is not implemented" msgstr "масиви послідовності не реалізовані" -#: parser/parse_utilcmd.c:668 parser/parse_utilcmd.c:680 -#: parser/parse_utilcmd.c:739 +#: parser/parse_utilcmd.c:690 parser/parse_utilcmd.c:702 +#: parser/parse_utilcmd.c:761 #, c-format msgid "conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"" msgstr "несумісні оголошення NULL/NOT NULL для стовпця \"%s\" таблиці \"%s\"" -#: parser/parse_utilcmd.c:692 +#: parser/parse_utilcmd.c:714 #, c-format msgid "multiple default values specified for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" вказано декілька значень за замовчуванням" -#: parser/parse_utilcmd.c:709 +#: parser/parse_utilcmd.c:731 #, c-format msgid "identity columns are not supported on typed tables" msgstr "ідентифікаційні стовпці не підтримуються в типізованих таблицях" -#: parser/parse_utilcmd.c:713 +#: parser/parse_utilcmd.c:735 #, c-format msgid "identity columns are not supported on partitions" msgstr "ідентифікаційні стовпці не підтримуються з секціями" -#: parser/parse_utilcmd.c:722 +#: parser/parse_utilcmd.c:744 #, c-format msgid "multiple identity specifications for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" властивість identity вказана неодноразово" -#: parser/parse_utilcmd.c:752 +#: parser/parse_utilcmd.c:774 #, c-format msgid "generated columns are not supported on typed tables" msgstr "згенеровані стовпці не підтримуються в типізованих таблицях" -#: parser/parse_utilcmd.c:756 +#: parser/parse_utilcmd.c:778 #, c-format msgid "multiple generation clauses specified for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" вказано декілька речень генерації" -#: parser/parse_utilcmd.c:774 parser/parse_utilcmd.c:889 +#: parser/parse_utilcmd.c:796 parser/parse_utilcmd.c:911 #, c-format msgid "primary key constraints are not supported on foreign tables" msgstr "обмеження первинного ключа для сторонніх таблиць не підтримуються" -#: parser/parse_utilcmd.c:783 parser/parse_utilcmd.c:899 +#: parser/parse_utilcmd.c:805 parser/parse_utilcmd.c:921 #, c-format msgid "unique constraints are not supported on foreign tables" msgstr "обмеження унікальності для сторонніх таблиць не підтримуються" -#: parser/parse_utilcmd.c:828 +#: parser/parse_utilcmd.c:850 #, c-format msgid "both default and identity specified for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" вказано значення за замовчуванням і властивість identity" -#: parser/parse_utilcmd.c:836 +#: parser/parse_utilcmd.c:858 #, c-format msgid "both default and generation expression specified for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" вказано вираз за замовчуванням і вираз генерації" -#: parser/parse_utilcmd.c:844 +#: parser/parse_utilcmd.c:866 #, c-format msgid "both identity and generation expression specified for column \"%s\" of table \"%s\"" msgstr "для стовпця \"%s\" таблиці \"%s\" вказано вираз ідентичності і вираз генерації" -#: parser/parse_utilcmd.c:909 +#: parser/parse_utilcmd.c:931 #, c-format msgid "exclusion constraints are not supported on foreign tables" msgstr "обмеження-виключення для сторонніх таблиць не підтримуються" -#: parser/parse_utilcmd.c:915 -#, c-format -msgid "exclusion constraints are not supported on partitioned tables" -msgstr "обмеження-виключення для секціонованих таблиць не підтримуються" - -#: parser/parse_utilcmd.c:980 +#: parser/parse_utilcmd.c:996 #, c-format msgid "LIKE is not supported for creating foreign tables" msgstr "LIKE не підтримується при створенні сторонніх таблиць" -#: parser/parse_utilcmd.c:993 +#: parser/parse_utilcmd.c:1009 #, c-format msgid "relation \"%s\" is invalid in LIKE clause" msgstr "невірше відношення \"%s\" в реченні LIKE" -#: parser/parse_utilcmd.c:1750 parser/parse_utilcmd.c:1858 +#: parser/parse_utilcmd.c:1736 parser/parse_utilcmd.c:1844 #, c-format msgid "Index \"%s\" contains a whole-row table reference." msgstr "Індекс \"%s\" містить посилання на таблицю на весь рядок." -#: parser/parse_utilcmd.c:2245 +#: parser/parse_utilcmd.c:2242 #, c-format msgid "cannot use an existing index in CREATE TABLE" msgstr "у CREATE TABLE не можна використовувати існуючий індекс" -#: parser/parse_utilcmd.c:2265 +#: parser/parse_utilcmd.c:2262 #, c-format msgid "index \"%s\" is already associated with a constraint" msgstr "індекс \"%s\" вже пов'язаний з обмеженням" -#: parser/parse_utilcmd.c:2286 +#: parser/parse_utilcmd.c:2283 #, c-format msgid "\"%s\" is not a unique index" msgstr "\"%s\" не є унікальним індексом" -#: parser/parse_utilcmd.c:2287 parser/parse_utilcmd.c:2294 -#: parser/parse_utilcmd.c:2301 parser/parse_utilcmd.c:2378 +#: parser/parse_utilcmd.c:2284 parser/parse_utilcmd.c:2291 +#: parser/parse_utilcmd.c:2298 parser/parse_utilcmd.c:2375 #, c-format msgid "Cannot create a primary key or unique constraint using such an index." msgstr "Створити первинний ключ або обмеження унікальності, використовуючи такий індекс, не можна." -#: parser/parse_utilcmd.c:2293 +#: parser/parse_utilcmd.c:2290 #, c-format msgid "index \"%s\" contains expressions" msgstr "індекс \"%s\" містить вирази" -#: parser/parse_utilcmd.c:2300 +#: parser/parse_utilcmd.c:2297 #, c-format msgid "\"%s\" is a partial index" msgstr "\"%s\" є частковим індексом" -#: parser/parse_utilcmd.c:2312 +#: parser/parse_utilcmd.c:2309 #, c-format msgid "\"%s\" is a deferrable index" msgstr "\"%s\" є індексом, що відкладається" -#: parser/parse_utilcmd.c:2313 +#: parser/parse_utilcmd.c:2310 #, c-format msgid "Cannot create a non-deferrable constraint using a deferrable index." msgstr "Створити обмеження, що не відкладається, використовуючи індекс, що відкладається, не можна." -#: parser/parse_utilcmd.c:2377 +#: parser/parse_utilcmd.c:2374 #, c-format msgid "index \"%s\" column number %d does not have default sorting behavior" msgstr "індекс \"%s\" номер стовпця %d не має поведінки сортування за замовчуванням" -#: parser/parse_utilcmd.c:2534 +#: parser/parse_utilcmd.c:2531 #, c-format msgid "column \"%s\" appears twice in primary key constraint" msgstr "стовпець \"%s\" з'являється двічі в обмеженні первинного ключа" -#: parser/parse_utilcmd.c:2540 +#: parser/parse_utilcmd.c:2537 #, c-format msgid "column \"%s\" appears twice in unique constraint" msgstr "стовпець \"%s\" з'являється двічі в обмеженні унікальності" -#: parser/parse_utilcmd.c:2887 +#: parser/parse_utilcmd.c:2871 #, c-format msgid "index expressions and predicates can refer only to the table being indexed" msgstr "індекс-вирази й предикати можуть посилатись лише на індексовану таблицю" -#: parser/parse_utilcmd.c:2959 +#: parser/parse_utilcmd.c:2943 #, c-format msgid "statistics expressions can refer only to the table being referenced" msgstr "вирази статистики можуть посилатися лише на таблицю, для якої збирається статистика" -#: parser/parse_utilcmd.c:3002 +#: parser/parse_utilcmd.c:2986 #, c-format msgid "rules on materialized views are not supported" msgstr "правила для матеріалізованих подань не підтримуються" -#: parser/parse_utilcmd.c:3062 +#: parser/parse_utilcmd.c:3046 #, c-format msgid "rule WHERE condition cannot contain references to other relations" msgstr "в умовах WHERE правила не можуть містити посилання на інші зв'язки" -#: parser/parse_utilcmd.c:3134 +#: parser/parse_utilcmd.c:3118 #, c-format msgid "rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions" msgstr "правила з умовами WHERE можуть мати лише дії SELECT, INSERT, UPDATE або DELETE" -#: parser/parse_utilcmd.c:3152 parser/parse_utilcmd.c:3253 -#: rewrite/rewriteHandler.c:539 rewrite/rewriteManip.c:1087 +#: parser/parse_utilcmd.c:3136 parser/parse_utilcmd.c:3237 +#: rewrite/rewriteHandler.c:538 rewrite/rewriteManip.c:1095 #, c-format msgid "conditional UNION/INTERSECT/EXCEPT statements are not implemented" msgstr "умовні оператори UNION/INTERSECT/EXCEPT не реалізовані" -#: parser/parse_utilcmd.c:3170 +#: parser/parse_utilcmd.c:3154 #, c-format msgid "ON SELECT rule cannot use OLD" msgstr "у правилі ON SELECT не можна використовувати OLD" -#: parser/parse_utilcmd.c:3174 +#: parser/parse_utilcmd.c:3158 #, c-format msgid "ON SELECT rule cannot use NEW" msgstr "у правилі ON SELECT не можна використовувати NEW" -#: parser/parse_utilcmd.c:3183 +#: parser/parse_utilcmd.c:3167 #, c-format msgid "ON INSERT rule cannot use OLD" msgstr "у правилі ON INSERT не можна використовувати OLD" -#: parser/parse_utilcmd.c:3189 +#: parser/parse_utilcmd.c:3173 #, c-format msgid "ON DELETE rule cannot use NEW" msgstr "у правилі ON DELETE не можна використовувати NEW" -#: parser/parse_utilcmd.c:3217 +#: parser/parse_utilcmd.c:3201 #, c-format msgid "cannot refer to OLD within WITH query" msgstr "у запиті WITH не можна посилатися на OLD" -#: parser/parse_utilcmd.c:3224 +#: parser/parse_utilcmd.c:3208 #, c-format msgid "cannot refer to NEW within WITH query" msgstr "у запиті WITH не можна посилатися на NEW" -#: parser/parse_utilcmd.c:3676 +#: parser/parse_utilcmd.c:3664 #, c-format msgid "misplaced DEFERRABLE clause" msgstr "речення DEFERRABLE розташовано неправильно" -#: parser/parse_utilcmd.c:3681 parser/parse_utilcmd.c:3696 +#: parser/parse_utilcmd.c:3669 parser/parse_utilcmd.c:3684 #, c-format msgid "multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed" msgstr "декілька речень DEFERRABLE/NOT DEFERRABLE не допускаються" -#: parser/parse_utilcmd.c:3691 +#: parser/parse_utilcmd.c:3679 #, c-format msgid "misplaced NOT DEFERRABLE clause" msgstr "речення NOT DEFERRABLE розташовано неправильно" -#: parser/parse_utilcmd.c:3704 parser/parse_utilcmd.c:3730 gram.y:5990 +#: parser/parse_utilcmd.c:3692 parser/parse_utilcmd.c:3718 gram.y:6114 #, c-format msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" msgstr "обмеження, оголошене як INITIALLY DEFERRED, повинно бути оголошене як DEFERRABLE" -#: parser/parse_utilcmd.c:3712 +#: parser/parse_utilcmd.c:3700 #, c-format msgid "misplaced INITIALLY DEFERRED clause" msgstr "речення INITIALLY DEFERRED розташовано неправильно" -#: parser/parse_utilcmd.c:3717 parser/parse_utilcmd.c:3743 +#: parser/parse_utilcmd.c:3705 parser/parse_utilcmd.c:3731 #, c-format msgid "multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed" msgstr "декілька речень INITIALLY IMMEDIATE/DEFERRED не допускаються" -#: parser/parse_utilcmd.c:3738 +#: parser/parse_utilcmd.c:3726 #, c-format msgid "misplaced INITIALLY IMMEDIATE clause" msgstr "речення INITIALLY IMMEDIATE розташовано неправильно" -#: parser/parse_utilcmd.c:3931 +#: parser/parse_utilcmd.c:3919 #, c-format msgid "CREATE specifies a schema (%s) different from the one being created (%s)" msgstr "В CREATE вказана схема (%s), яка відрізняється від створюваної (%s)" -#: parser/parse_utilcmd.c:3966 +#: parser/parse_utilcmd.c:3954 #, c-format msgid "\"%s\" is not a partitioned table" msgstr "\"%s\" не є секціонованою таблицею" -#: parser/parse_utilcmd.c:3973 +#: parser/parse_utilcmd.c:3961 #, c-format msgid "table \"%s\" is not partitioned" msgstr "таблиця \"%s\" не є секційною" -#: parser/parse_utilcmd.c:3980 +#: parser/parse_utilcmd.c:3968 #, c-format msgid "index \"%s\" is not partitioned" msgstr "індекс \"%s\" не є секціонованим" -#: parser/parse_utilcmd.c:4020 +#: parser/parse_utilcmd.c:4008 #, c-format msgid "a hash-partitioned table may not have a default partition" msgstr "у геш-секціонованій таблиці не може бути розділу за замовчуванням" -#: parser/parse_utilcmd.c:4037 +#: parser/parse_utilcmd.c:4025 #, c-format msgid "invalid bound specification for a hash partition" msgstr "неприпустима вказівка границі для геш-секції" -#: parser/parse_utilcmd.c:4043 partitioning/partbounds.c:4803 +#: parser/parse_utilcmd.c:4031 partitioning/partbounds.c:4802 #, c-format msgid "modulus for hash partition must be an integer value greater than zero" msgstr "модуль для хеш-секції повинен бути цілим числом більшим за нуль" -#: parser/parse_utilcmd.c:4050 partitioning/partbounds.c:4811 +#: parser/parse_utilcmd.c:4038 partitioning/partbounds.c:4810 #, c-format msgid "remainder for hash partition must be less than modulus" msgstr "залишок для геш-секції повинен бути меньшим, ніж модуль" -#: parser/parse_utilcmd.c:4063 +#: parser/parse_utilcmd.c:4051 #, c-format msgid "invalid bound specification for a list partition" msgstr "нерипустима вказівка границі для секції по списку" -#: parser/parse_utilcmd.c:4116 +#: parser/parse_utilcmd.c:4104 #, c-format msgid "invalid bound specification for a range partition" msgstr "неприпустима вказівка границі для секції діапазону" -#: parser/parse_utilcmd.c:4122 +#: parser/parse_utilcmd.c:4110 #, c-format msgid "FROM must specify exactly one value per partitioning column" msgstr "В FROM повинно вказуватися лише одне значення для стовпця секціонування" -#: parser/parse_utilcmd.c:4126 +#: parser/parse_utilcmd.c:4114 #, c-format msgid "TO must specify exactly one value per partitioning column" msgstr "В TO повинно вказуватися лише одне значення для стовпця секціонування" -#: parser/parse_utilcmd.c:4240 +#: parser/parse_utilcmd.c:4228 #, c-format msgid "cannot specify NULL in range bound" msgstr "вказати NULL в діапазоні границі не можна" -#: parser/parse_utilcmd.c:4289 +#: parser/parse_utilcmd.c:4277 #, c-format msgid "every bound following MAXVALUE must also be MAXVALUE" msgstr "за кожною границею MAXVALUE повинні бути лише границі MAXVALUE" -#: parser/parse_utilcmd.c:4296 +#: parser/parse_utilcmd.c:4284 #, c-format msgid "every bound following MINVALUE must also be MINVALUE" msgstr "за кожною границею MINVALUE повинні бути лише границі MINVALUE" -#: parser/parse_utilcmd.c:4339 +#: parser/parse_utilcmd.c:4327 #, c-format msgid "specified value cannot be cast to type %s for column \"%s\"" msgstr "вказане значення не можна привести до типу %s для стовпця \"%s\"" @@ -18454,12 +18959,12 @@ msgstr "UESCAPE повинен відстежуватись простим лі msgid "invalid Unicode escape character" msgstr "неприпустимий символ спеціального коду Unicode" -#: parser/parser.c:347 scan.l:1390 +#: parser/parser.c:347 scan.l:1393 #, c-format msgid "invalid Unicode escape value" msgstr "неприпустиме значення спеціального коду Unicode" -#: parser/parser.c:494 utils/adt/varlena.c:6505 scan.l:701 +#: parser/parser.c:494 utils/adt/varlena.c:6640 scan.l:716 #, c-format msgid "invalid Unicode escape" msgstr "неприпустимий спеціальний код Unicode" @@ -18469,8 +18974,8 @@ msgstr "неприпустимий спеціальний код Unicode" msgid "Unicode escapes must be \\XXXX or \\+XXXXXX." msgstr "Спеціальні символи Unicode повинні бути \\XXXX або \\+XXXXXX." -#: parser/parser.c:523 utils/adt/varlena.c:6530 scan.l:662 scan.l:678 -#: scan.l:694 +#: parser/parser.c:523 utils/adt/varlena.c:6665 scan.l:677 scan.l:693 +#: scan.l:709 #, c-format msgid "invalid Unicode surrogate pair" msgstr "неприпустима сурогатна пара Unicode" @@ -18480,146 +18985,140 @@ msgstr "неприпустима сурогатна пара Unicode" msgid "identifier \"%s\" will be truncated to \"%.*s\"" msgstr "ідентифікатор \"%s\" буде скорочено до \"%.*s\"" -#: partitioning/partbounds.c:2921 +#: partitioning/partbounds.c:2920 #, c-format msgid "partition \"%s\" conflicts with existing default partition \"%s\"" msgstr "існують конфлікти між розділом \"%s\" та існуючим розділом за замовчуванням \"%s\"" -#: partitioning/partbounds.c:2973 partitioning/partbounds.c:2992 -#: partitioning/partbounds.c:3014 +#: partitioning/partbounds.c:2972 partitioning/partbounds.c:2991 +#: partitioning/partbounds.c:3013 #, c-format msgid "every hash partition modulus must be a factor of the next larger modulus" msgstr "модуль кожної геш-секції повинен бути дільником наступних більших модулів" -#: partitioning/partbounds.c:2974 partitioning/partbounds.c:3015 +#: partitioning/partbounds.c:2973 partitioning/partbounds.c:3014 #, c-format msgid "The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\"." msgstr "Новий модуль %d не є дільником %d, поточний модуль розділу \"%s\"." -#: partitioning/partbounds.c:2993 +#: partitioning/partbounds.c:2992 #, c-format msgid "The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\"." msgstr "Новий модуль %d не ділиться на %d, поточний модуль розділу \"%s\"." -#: partitioning/partbounds.c:3128 +#: partitioning/partbounds.c:3127 #, c-format msgid "empty range bound specified for partition \"%s\"" msgstr "для секції \"%s\" вказані границі, які утворюють пустий діапазон" -#: partitioning/partbounds.c:3130 +#: partitioning/partbounds.c:3129 #, c-format msgid "Specified lower bound %s is greater than or equal to upper bound %s." msgstr "Вказана нижня границя %s більша або дорівнює верхній границі %s." -#: partitioning/partbounds.c:3238 +#: partitioning/partbounds.c:3237 #, c-format msgid "partition \"%s\" would overlap partition \"%s\"" msgstr "секція \"%s\" буде перекривати секцію \"%s\"" -#: partitioning/partbounds.c:3355 +#: partitioning/partbounds.c:3354 #, c-format msgid "skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"" msgstr "пропущено сканування зовнішньої таблиці \"%s\" яка є секцією секції за замовчуванням \"%s\"" -#: partitioning/partbounds.c:4807 +#: partitioning/partbounds.c:4806 #, c-format msgid "remainder for hash partition must be an integer value greater than or equal to zero" msgstr "залишок для хеш-секції повинен бути цілим числом більшим або рівним нулю" -#: partitioning/partbounds.c:4831 +#: partitioning/partbounds.c:4830 #, c-format msgid "\"%s\" is not a hash partitioned table" msgstr "\"%s\" не є геш-секціонованою таблицею" -#: partitioning/partbounds.c:4842 partitioning/partbounds.c:4959 +#: partitioning/partbounds.c:4841 partitioning/partbounds.c:4958 #, c-format msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" msgstr "кількість секціонованих стовпців (%d) не дорівнює кількості наданих ключів секціонування (%d)" -#: partitioning/partbounds.c:4864 +#: partitioning/partbounds.c:4863 #, c-format msgid "column %d of the partition key has type %s, but supplied value is of type %s" msgstr "стовпець %d ключа секціонування має тип %s, але для нього вказане значення типу %s" -#: partitioning/partbounds.c:4896 +#: partitioning/partbounds.c:4895 #, c-format msgid "column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"" msgstr "стовпець %d ключа секціонування має тип \"%s\", але для нього вказано значення типу \"%s\"" -#: port/pg_sema.c:209 port/pg_shmem.c:708 port/posix_sema.c:209 -#: port/sysv_sema.c:323 port/sysv_shmem.c:708 +#: port/pg_sema.c:209 port/pg_shmem.c:717 port/posix_sema.c:209 +#: port/sysv_sema.c:323 port/sysv_shmem.c:717 #, c-format msgid "could not stat data directory \"%s\": %m" msgstr "не вдалося встановити дані каталогу \"%s\": %m" -#: port/pg_shmem.c:223 port/sysv_shmem.c:223 +#: port/pg_shmem.c:224 port/sysv_shmem.c:224 #, c-format msgid "could not create shared memory segment: %m" msgstr "не вдалося створити сегмент спільної пам'яті: %m" -#: port/pg_shmem.c:224 port/sysv_shmem.c:224 +#: port/pg_shmem.c:225 port/sysv_shmem.c:225 #, c-format msgid "Failed system call was shmget(key=%lu, size=%zu, 0%o)." msgstr "Помилка в системному виклику shmget (ключ=%lu, розмір=%zu, 0%o)." -#: port/pg_shmem.c:228 port/sysv_shmem.c:228 +#: port/pg_shmem.c:229 port/sysv_shmem.c:229 #, c-format -msgid "" -"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n" +msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter, or possibly that it is less than your kernel's SHMMIN parameter.\n" "The PostgreSQL documentation contains more information about shared memory configuration." -msgstr "" -"Ця помилка зазвичай означає, що запит PostgreSQL для сегменту спільної пам'яті перевищує параметр SHMMAX вашого ядра, або можливо що він менший за параметр SHMMIN вашого ядра.\n" +msgstr "Ця помилка зазвичай означає, що запит PostgreSQL для сегменту спільної пам'яті перевищує параметр SHMMAX вашого ядра, або можливо що він менший за параметр SHMMIN вашого ядра.\n" "Більше інформації про налаштування спільної пам'яті міститься в інструкції PostgreSQL." -#: port/pg_shmem.c:235 port/sysv_shmem.c:235 +#: port/pg_shmem.c:236 port/sysv_shmem.c:236 #, c-format -msgid "" -"This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n" +msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMALL parameter. You might need to reconfigure the kernel with larger SHMALL.\n" "The PostgreSQL documentation contains more information about shared memory configuration." -msgstr "" -"Ця помилка зазвичай означає, що запит PostgreSQL для сегменту спільної пам'яті перевищує параметр SHMALL вашого ядра. Можливо, вам слід переналаштувати ваше ядро, збільшивши параметр SHMALL.\n" +msgstr "Ця помилка зазвичай означає, що запит PostgreSQL для сегменту спільної пам'яті перевищує параметр SHMALL вашого ядра. Можливо, вам слід переналаштувати ваше ядро, збільшивши параметр SHMALL.\n" "Більше інформації про налаштування спільної пам'яті міститься в інструкції PostgreSQL." -#: port/pg_shmem.c:241 port/sysv_shmem.c:241 +#: port/pg_shmem.c:242 port/sysv_shmem.c:242 #, c-format -msgid "" -"This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n" +msgid "This error does *not* mean that you have run out of disk space. It occurs either if all available shared memory IDs have been taken, in which case you need to raise the SHMMNI parameter in your kernel, or because the system's overall limit for shared memory has been reached.\n" "The PostgreSQL documentation contains more information about shared memory configuration." -msgstr "" -"Ця помилка НЕ означає, що на диску немає місця. Ймовірніше за все, були зайняті всі доступні ID спільної пам'яті, в такому випадку вам потрібно підвищити параметр SHMMNI у вашому ядрі, або перевищено граничний розмір спільної пам'яті.\n" +msgstr "Ця помилка НЕ означає, що на диску немає місця. Ймовірніше за все, були зайняті всі доступні ID спільної пам'яті, в такому випадку вам потрібно підвищити параметр SHMMNI у вашому ядрі, або перевищено граничний розмір спільної пам'яті.\n" "Детальна інформація про налаштування спільної пам'яті міститься в інструкції PostgreSQL." -#: port/pg_shmem.c:583 port/sysv_shmem.c:583 port/win32_shmem.c:641 +#: port/pg_shmem.c:584 port/sysv_shmem.c:584 port/win32_shmem.c:646 #, c-format -msgid "huge_page_size must be 0 on this platform." -msgstr "huge_page_size повинен бути 0 на цій платформі." +msgid "\"huge_page_size\" must be 0 on this platform." +msgstr "" -#: port/pg_shmem.c:646 port/sysv_shmem.c:646 +#: port/pg_shmem.c:655 port/sysv_shmem.c:655 #, c-format msgid "could not map anonymous shared memory: %m" msgstr "не вдалося показати анонімну спільну пам'ять: %m" -#: port/pg_shmem.c:648 port/sysv_shmem.c:648 +#: port/pg_shmem.c:657 port/sysv_shmem.c:657 #, c-format -msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections." -msgstr "Ця помилка зазвичай означає, що запит PostgreSQL для сегменту спільної пам'яті перевищує об'єм доступної фізичної або віртуальної пам'яті або гігантских сторінок. Щоб зменшити розмір запиту (поточний: %zu байтів), зменшіть використання спільної пам'яті PostgreSQL, можливо зменшив shared_buffers або max_connections." +msgid "This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently %zu bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing \"shared_buffers\" or \"max_connections\"." +msgstr "" -#: port/pg_shmem.c:716 port/sysv_shmem.c:716 +#: port/pg_shmem.c:725 port/sysv_shmem.c:725 #, c-format msgid "huge pages not supported on this platform" msgstr "величезні сторінки на цій плтаформі не підтримуються" -#: port/pg_shmem.c:723 port/sysv_shmem.c:723 +#: port/pg_shmem.c:732 port/sysv_shmem.c:732 #, c-format -msgid "huge pages not supported with the current shared_memory_type setting" -msgstr "величезні сторінки не підтримуються з поточним параметром shared_memory_type" +msgid "huge pages not supported with the current \"shared_memory_type\" setting" +msgstr "" -#: port/pg_shmem.c:783 port/sysv_shmem.c:783 utils/init/miscinit.c:1358 +#: port/pg_shmem.c:798 port/sysv_shmem.c:798 utils/init/miscinit.c:1347 #, c-format msgid "pre-existing shared memory block (key %lu, ID %lu) is still in use" msgstr "раніше виділений блок спільної пам'яті (ключ %lu, ідентифікатор %lu) все ще використовується" -#: port/pg_shmem.c:786 port/sysv_shmem.c:786 utils/init/miscinit.c:1360 +#: port/pg_shmem.c:801 port/sysv_shmem.c:801 utils/init/miscinit.c:1349 #, c-format msgid "Terminate any old server processes associated with data directory \"%s\"." msgstr "Припинити будь-які старі серверні процеси, пов'язані з каталогом даних \"%s\"." @@ -18636,12 +19135,9 @@ msgstr "Помилка системного виклику semget(%lu, %d, 0%o). #: port/sysv_sema.c:125 #, c-format -msgid "" -"This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its max_connections parameter.\n" +msgid "This error does *not* mean that you have run out of disk space. It occurs when either the system limit for the maximum number of semaphore sets (SEMMNI), or the system wide maximum number of semaphores (SEMMNS), would be exceeded. You need to raise the respective kernel parameter. Alternatively, reduce PostgreSQL's consumption of semaphores by reducing its \"max_connections\" parameter.\n" "The PostgreSQL documentation contains more information about configuring your system for PostgreSQL." msgstr "" -"Ця помилка НЕ означає, що на диску немає місця. Ймовірніше за все перевищено ліміт числа встановлених семафорів (SEMMNI), або загального числа семафорів (SEMMNS) в системі. Вам потрібно збільшити відповідний параметр ядра. Інший спосіб - зменшити споживання PostgreSQL в семафорах, зменшивши параметр max_connections.\n" -"Більше інформації про налаштування вашої системи для PostgreSQL міститься в інструкції PostgreSQL." #: port/sysv_sema.c:155 #, c-format @@ -18768,97 +19264,87 @@ msgstr "Помилка в системному виклику DuplicateHandle." msgid "Failed system call was MapViewOfFileEx." msgstr "Помилка в системному виклику MapViewOfFileEx." -#: postmaster/autovacuum.c:417 -#, c-format -msgid "could not fork autovacuum launcher process: %m" -msgstr "не вдалося породити процес запуску автоочистки: %m" - -#: postmaster/autovacuum.c:764 +#: postmaster/autovacuum.c:686 #, c-format msgid "autovacuum worker took too long to start; canceled" msgstr "старт процеса автовакуума зайняв забагато часу; скасовано" -#: postmaster/autovacuum.c:1489 -#, c-format -msgid "could not fork autovacuum worker process: %m" -msgstr "не вдалося породити робочий процес автоочитски: %m" - -#: postmaster/autovacuum.c:2334 +#: postmaster/autovacuum.c:2199 #, c-format msgid "autovacuum: dropping orphan temp table \"%s.%s.%s\"" msgstr "автоочистка: видалення застарілої тимчасової таблиці \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2570 +#: postmaster/autovacuum.c:2435 #, c-format msgid "automatic vacuum of table \"%s.%s.%s\"" msgstr "автоматична очистка таблиці \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2573 +#: postmaster/autovacuum.c:2438 #, c-format msgid "automatic analyze of table \"%s.%s.%s\"" msgstr "автоматичний аналіз таблиці \"%s.%s.%s\"" -#: postmaster/autovacuum.c:2767 +#: postmaster/autovacuum.c:2632 #, c-format msgid "processing work entry for relation \"%s.%s.%s\"" msgstr "обробка робочого введення для відношення \"%s.%s.%s\"" -#: postmaster/autovacuum.c:3381 +#: postmaster/autovacuum.c:3250 #, c-format msgid "autovacuum not started because of misconfiguration" msgstr "автоочистку не запущено через неправильну конфігурацію" -#: postmaster/autovacuum.c:3382 +#: postmaster/autovacuum.c:3251 #, c-format msgid "Enable the \"track_counts\" option." msgstr "Активувати параметр \"track_counts\"." -#: postmaster/bgworker.c:259 +#: postmaster/bgworker.c:260 #, c-format msgid "inconsistent background worker state (max_worker_processes=%d, total_slots=%d)" msgstr "несумісний стан фонового процесу (max_worker_processes=%d, total_slots=%d)" -#: postmaster/bgworker.c:669 +#: postmaster/bgworker.c:651 #, c-format msgid "background worker \"%s\": background workers without shared memory access are not supported" msgstr "фоновий виконавець \"%s\": фонові виконавці без доступу до спільної пам'яті не підтримуються" -#: postmaster/bgworker.c:680 +#: postmaster/bgworker.c:662 #, c-format msgid "background worker \"%s\": cannot request database access if starting at postmaster start" msgstr "фоновий виконавець \"%s\": не може запитувати доступ до бази даних, якщо його запущено при старті адміністратора поштового сервісу" -#: postmaster/bgworker.c:694 +#: postmaster/bgworker.c:676 #, c-format msgid "background worker \"%s\": invalid restart interval" msgstr "фоновий виконавець \"%s\": неприпустимий інтервал перезавантаження" -#: postmaster/bgworker.c:709 +#: postmaster/bgworker.c:691 #, c-format msgid "background worker \"%s\": parallel workers may not be configured for restart" msgstr "фоновий виконавець\"%s\": паралельні виконавці не можуть бути налаштовані для перезавантаження" -#: postmaster/bgworker.c:733 tcop/postgres.c:3255 +#: postmaster/bgworker.c:715 tcop/postgres.c:3312 #, c-format msgid "terminating background worker \"%s\" due to administrator command" msgstr "завершення фонового процесу \"%s\" по команді адміністратора" -#: postmaster/bgworker.c:890 +#: postmaster/bgworker.c:888 #, c-format -msgid "background worker \"%s\": must be registered in shared_preload_libraries" -msgstr "фоновий процес \"%s\": повинен бути зареєстрований в shared_preload_libraries" +msgid "background worker \"%s\": must be registered in \"shared_preload_libraries\"" +msgstr "" -#: postmaster/bgworker.c:902 +#: postmaster/bgworker.c:911 #, c-format msgid "background worker \"%s\": only dynamic background workers can request notification" msgstr "фоновий процес \"%s\": лише динамічні фонові процеси можуть запитувати сповіщення" -#: postmaster/bgworker.c:917 +#: postmaster/bgworker.c:926 #, c-format msgid "too many background workers" msgstr "занадто багато фонових процесів" -#: postmaster/bgworker.c:918 +#: postmaster/bgworker.c:927 #, c-format msgid "Up to %d background worker can be registered with the current settings." msgid_plural "Up to %d background workers can be registered with the current settings." @@ -18867,12 +19353,12 @@ msgstr[1] "Максимальне можливе число фонових пр msgstr[2] "Максимальне можливе число фонових процесів при поточних параметрах: %d." msgstr[3] "Максимальне можливе число фонових процесів при поточних параметрах: %d." -#: postmaster/bgworker.c:922 +#: postmaster/bgworker.c:931 postmaster/checkpointer.c:445 #, c-format -msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgstr "Можливо, слід збільшити параметр конфігурації \"max_worker_processes\"." +msgid "Consider increasing the configuration parameter \"%s\"." +msgstr "" -#: postmaster/checkpointer.c:431 +#: postmaster/checkpointer.c:441 #, c-format msgid "checkpoints are occurring too frequently (%d second apart)" msgid_plural "checkpoints are occurring too frequently (%d seconds apart)" @@ -18881,854 +19367,769 @@ msgstr[1] "контрольні точки відбуваються занадт msgstr[2] "контрольні точки відбуваються занадто часто (через %d сек.)" msgstr[3] "контрольні точки відбуваються занадто часто (через %d сек.)" -#: postmaster/checkpointer.c:435 -#, c-format -msgid "Consider increasing the configuration parameter \"max_wal_size\"." -msgstr "Можливо, слід збільшити параметр конфігурації \"max_wal_size\"." - -#: postmaster/checkpointer.c:1059 +#: postmaster/checkpointer.c:1067 #, c-format msgid "checkpoint request failed" msgstr "збій при запиті контрольної точки" -#: postmaster/checkpointer.c:1060 +#: postmaster/checkpointer.c:1068 #, c-format msgid "Consult recent messages in the server log for details." msgstr "Для деталей, зверніться до останніх повідомлень в протоколі серверу." -#: postmaster/pgarch.c:416 +#: postmaster/launch_backend.c:381 #, c-format -msgid "archive_mode enabled, yet archiving is not configured" -msgstr "archive_mode активовано, але архівування не налаштовано" +msgid "could not execute server process \"%s\": %m" +msgstr "не вдалося виконати серверні процеси \"%s\":%m" -#: postmaster/pgarch.c:438 +#: postmaster/launch_backend.c:434 #, c-format -msgid "removed orphan archive status file \"%s\"" -msgstr "видалено залишковий файл статусу архіву \"%s\"" +msgid "could not create backend parameter file mapping: error code %lu" +msgstr "не вдалося створити відображення файлу параметру внутрішнього сервера: код помилки %lu" + +#: postmaster/launch_backend.c:442 +#, c-format +msgid "could not map backend parameter memory: error code %lu" +msgstr "не вдалося відобразити пам'ять параметру внутрішнього сервера: код помилки %lu" + +#: postmaster/launch_backend.c:459 +#, c-format +msgid "subprocess command line too long" +msgstr "командний рядок підпроцесу занадто довгий" + +#: postmaster/launch_backend.c:477 +#, c-format +msgid "CreateProcess() call failed: %m (error code %lu)" +msgstr "помилка виклику CreateProcess(): %m (код помилки %lu)" + +#: postmaster/launch_backend.c:504 +#, c-format +msgid "could not unmap view of backend parameter file: error code %lu" +msgstr "не вдалося вимкнути відображення файлу параметру внутрішнього сервера: код помилки %lu" + +#: postmaster/launch_backend.c:508 +#, c-format +msgid "could not close handle to backend parameter file: error code %lu" +msgstr "не вдалося закрити покажчик файлу параметру внутрішнього сервера: код помилки %lu" + +#: postmaster/launch_backend.c:530 +#, c-format +msgid "giving up after too many tries to reserve shared memory" +msgstr "кількість повторних спроб резервування спільної пам'яті досягло межі" + +#: postmaster/launch_backend.c:531 +#, c-format +msgid "This might be caused by ASLR or antivirus software." +msgstr "Це може бути викликано антивірусним програмним забезпеченням або ASLR." + +#: postmaster/launch_backend.c:834 +#, c-format +msgid "could not duplicate socket %d for use in backend: error code %d" +msgstr "не вдалося продублювати сокет %d для використання: код помилки %d" + +#: postmaster/launch_backend.c:866 +#, c-format +msgid "could not create inherited socket: error code %d\n" +msgstr "не вдалося створити успадкований сокет: код помилки %d\n" + +#: postmaster/launch_backend.c:895 +#, c-format +msgid "could not open backend variables file \"%s\": %m\n" +msgstr "" + +#: postmaster/launch_backend.c:901 +#, c-format +msgid "could not read from backend variables file \"%s\": %m\n" +msgstr "" -#: postmaster/pgarch.c:448 +#: postmaster/launch_backend.c:912 +#, c-format +msgid "could not read startup data from backend variables file \"%s\": %m\n" +msgstr "" + +#: postmaster/launch_backend.c:924 +#, c-format +msgid "could not remove file \"%s\": %m\n" +msgstr "" + +#: postmaster/launch_backend.c:940 +#, c-format +msgid "could not map view of backend variables: error code %lu\n" +msgstr "не вдалося відобразити файл серверних змінних: код помилки %lu\n" + +#: postmaster/launch_backend.c:959 +#, c-format +msgid "could not unmap view of backend variables: error code %lu\n" +msgstr "не вдалося вимкнути відображення файлу серверних змінних: код помилки %lu\n" + +#: postmaster/launch_backend.c:966 +#, c-format +msgid "could not close handle to backend parameter variables: error code %lu\n" +msgstr "не вдалося закрити покажчик файлу серверних змінних: код помилки %lu\n" + +#: postmaster/pgarch.c:428 +#, c-format +msgid "\"archive_mode\" enabled, yet archiving is not configured" +msgstr "" + +#: postmaster/pgarch.c:452 +#, c-format +msgid "removed orphan archive status file \"%s\"" +msgstr "видалено залишковий файл статусу архіву \"%s\"" + +#: postmaster/pgarch.c:462 #, c-format msgid "removal of orphan archive status file \"%s\" failed too many times, will try again later" msgstr "видалення залишкового файлу статусу архіву \"%s\" не вдалося занадто багато разів, пізніже спробуємо знову" -#: postmaster/pgarch.c:484 +#: postmaster/pgarch.c:498 #, c-format msgid "archiving write-ahead log file \"%s\" failed too many times, will try again later" msgstr "архівація файлу випереджувальног журналювання \"%s\" не виконана багато разів, наступна спроба буде пізніже" -#: postmaster/pgarch.c:791 postmaster/pgarch.c:830 +#: postmaster/pgarch.c:879 postmaster/pgarch.c:918 #, c-format -msgid "both archive_command and archive_library set" -msgstr "встановлено команду archive_command і archive_library" +msgid "both \"archive_command\" and \"archive_library\" set" +msgstr "" -#: postmaster/pgarch.c:792 postmaster/pgarch.c:831 +#: postmaster/pgarch.c:880 postmaster/pgarch.c:919 #, c-format -msgid "Only one of archive_command, archive_library may be set." -msgstr "Можливо встановити лише одну з archive_command, archive_library." +msgid "Only one of \"archive_command\", \"archive_library\" may be set." +msgstr "" -#: postmaster/pgarch.c:809 +#: postmaster/pgarch.c:897 #, c-format msgid "restarting archiver process because value of \"archive_library\" was changed" msgstr "перезапуск процесу архіватора, оскільки значення \"archive_library\" було змінено" -#: postmaster/pgarch.c:846 +#: postmaster/pgarch.c:934 #, c-format msgid "archive modules have to define the symbol %s" msgstr "архівні модулі повинні визначити символ %s" -#: postmaster/pgarch.c:852 +#: postmaster/pgarch.c:940 #, c-format msgid "archive modules must register an archive callback" msgstr "модулі архіву повинні реєструвати зворотний виклик архіву" -#: postmaster/postmaster.c:759 +#: postmaster/postmaster.c:661 #, c-format msgid "%s: invalid argument for option -f: \"%s\"\n" msgstr "%s: неприпустимий аргумент для параметру -f: \"%s\"\n" -#: postmaster/postmaster.c:832 +#: postmaster/postmaster.c:734 #, c-format msgid "%s: invalid argument for option -t: \"%s\"\n" msgstr "%s: неприпустимий аргумент для параметру -t: \"%s\"\n" -#: postmaster/postmaster.c:855 +#: postmaster/postmaster.c:757 #, c-format msgid "%s: invalid argument: \"%s\"\n" msgstr "%s: неприпустимий аргумент: \"%s\"\n" -#: postmaster/postmaster.c:923 +#: postmaster/postmaster.c:825 #, c-format -msgid "%s: superuser_reserved_connections (%d) plus reserved_connections (%d) must be less than max_connections (%d)\n" -msgstr "%s: superuser_reserved_connections (%d) плюс reserved_connections (%d) має бути меншим за max_connections (%d)\n" +msgid "%s: \"superuser_reserved_connections\" (%d) plus \"reserved_connections\" (%d) must be less than \"max_connections\" (%d)\n" +msgstr "" -#: postmaster/postmaster.c:931 +#: postmaster/postmaster.c:833 #, c-format -msgid "WAL archival cannot be enabled when wal_level is \"minimal\"" -msgstr "WAL архіватор не може бути активованим, коли wal_level \"мінімальний\"" +msgid "WAL archival cannot be enabled when \"wal_level\" is \"minimal\"" +msgstr "" -#: postmaster/postmaster.c:934 +#: postmaster/postmaster.c:836 #, c-format -msgid "WAL streaming (max_wal_senders > 0) requires wal_level \"replica\" or \"logical\"" -msgstr "Потокове передавання WAL (max_wal_senders > 0) вимагає wal_level \"replica\" або \"logical\"" +msgid "WAL streaming (\"max_wal_senders\" > 0) requires \"wal_level\" to be \"replica\" or \"logical\"" +msgstr "Потокове передавання WAL (\"max_wal_senders\" > 0) вимагає \"wal_level\" \"replica\" або \"logical\"" -#: postmaster/postmaster.c:942 +#: postmaster/postmaster.c:839 +#, c-format +msgid "WAL cannot be summarized when \"wal_level\" is \"minimal\"" +msgstr "неможливо підсумувати WAL, якщо \"wal_level\" дорівнє \"minimal\"" + +#: postmaster/postmaster.c:847 #, c-format msgid "%s: invalid datetoken tables, please fix\n" msgstr "%s: неприпустимі таблиці маркерів часу, будь-ласка виправіть\n" -#: postmaster/postmaster.c:1099 +#: postmaster/postmaster.c:1004 #, c-format msgid "could not create I/O completion port for child queue" msgstr "не вдалося створити завершений порт вводу-виводу для черги дітей" -#: postmaster/postmaster.c:1175 +#: postmaster/postmaster.c:1069 #, c-format msgid "ending log output to stderr" msgstr "завершення запису виводу Stderr" -#: postmaster/postmaster.c:1176 +#: postmaster/postmaster.c:1070 #, c-format msgid "Future log output will go to log destination \"%s\"." msgstr "В майбутньому запис виведення буде записуватися в призначення \"%s\"." -#: postmaster/postmaster.c:1187 +#: postmaster/postmaster.c:1081 #, c-format msgid "starting %s" msgstr "початок %s" -#: postmaster/postmaster.c:1239 +#: postmaster/postmaster.c:1143 #, c-format msgid "could not create listen socket for \"%s\"" msgstr "не вдалося створити сокет прослуховування для \"%s\"" -#: postmaster/postmaster.c:1245 +#: postmaster/postmaster.c:1149 #, c-format msgid "could not create any TCP/IP sockets" msgstr "не вдалося створити TCP/IP сокети" -#: postmaster/postmaster.c:1277 +#: postmaster/postmaster.c:1181 #, c-format msgid "DNSServiceRegister() failed: error code %ld" msgstr "Помилка DNSServiceRegister(): код помилки %ld" -#: postmaster/postmaster.c:1328 +#: postmaster/postmaster.c:1234 #, c-format msgid "could not create Unix-domain socket in directory \"%s\"" msgstr "не вдалося створити Unix-domain сокет в каталозі \"%s\"" -#: postmaster/postmaster.c:1334 +#: postmaster/postmaster.c:1240 #, c-format msgid "could not create any Unix-domain sockets" msgstr "не вдалося створити Unix-domain сокети" -#: postmaster/postmaster.c:1345 +#: postmaster/postmaster.c:1251 #, c-format msgid "no socket created for listening" msgstr "не створено жодного сокету для прослуховування" -#: postmaster/postmaster.c:1376 +#: postmaster/postmaster.c:1282 #, c-format -msgid "%s: could not change permissions of external PID file \"%s\": %s\n" -msgstr "%s: не вдалося змінити дозволи зовнішнього PID файлу \"%s\": %s\n" +msgid "%s: could not change permissions of external PID file \"%s\": %m\n" +msgstr "%s: не вдалося змінити дозволи зовнішнього PID файлу \"%s\": %m\n" -#: postmaster/postmaster.c:1380 +#: postmaster/postmaster.c:1286 #, c-format -msgid "%s: could not write external PID file \"%s\": %s\n" -msgstr "%s: не вдалося записати зовнішній PID файл \"%s\": %s\n" +msgid "%s: could not write external PID file \"%s\": %m\n" +msgstr "%s: не вдалося записати зовнішній PID файл \"%s\": %m\n" #. translator: %s is a configuration file -#: postmaster/postmaster.c:1408 utils/init/postinit.c:221 +#: postmaster/postmaster.c:1314 utils/init/postinit.c:221 #, c-format msgid "could not load %s" msgstr "не вдалося завантажити %s" -#: postmaster/postmaster.c:1434 +#: postmaster/postmaster.c:1340 #, c-format msgid "postmaster became multithreaded during startup" msgstr "адміністратор поштового сервера став багатопотоковим під час запуску" -#: postmaster/postmaster.c:1435 +#: postmaster/postmaster.c:1341 #, c-format msgid "Set the LC_ALL environment variable to a valid locale." msgstr "Встановити в змінній середовища LC_ALL дійісну локаль." -#: postmaster/postmaster.c:1536 +#: postmaster/postmaster.c:1440 #, c-format msgid "%s: could not locate my own executable path" msgstr "%s: не вдалося знайти свій власний шлях для виконання" -#: postmaster/postmaster.c:1543 +#: postmaster/postmaster.c:1447 #, c-format msgid "%s: could not locate matching postgres executable" msgstr "%s: не вдалося знайти відповідний postgres файл, що виконується" -#: postmaster/postmaster.c:1566 utils/misc/tzparser.c:340 +#: postmaster/postmaster.c:1470 utils/misc/tzparser.c:341 #, c-format msgid "This may indicate an incomplete PostgreSQL installation, or that the file \"%s\" has been moved away from its proper location." msgstr "Це може означати неповне встановлення PostgreSQL, або те, що файл \"%s\" було переміщено з його правильного розташування." -#: postmaster/postmaster.c:1593 +#: postmaster/postmaster.c:1497 #, c-format -msgid "" -"%s: could not find the database system\n" +msgid "%s: could not find the database system\n" "Expected to find it in the directory \"%s\",\n" -"but could not open file \"%s\": %s\n" -msgstr "" -"%s: не вдалося знайти систему бази даних\n" +"but could not open file \"%s\": %m\n" +msgstr "%s: не вдалося знайти систему бази даних\n" "Очікувалося знайти її у каталозі \"%s\",\n" -"але не вдалося відкрити файл \"%s\": %s\n" +"але не вдалося відкрити файл \"%s\": %m\n" #. translator: %s is SIGKILL or SIGABRT -#: postmaster/postmaster.c:1890 +#: postmaster/postmaster.c:1787 #, c-format msgid "issuing %s to recalcitrant children" msgstr "надсилання %s непокірливим дітям" -#: postmaster/postmaster.c:1912 +#: postmaster/postmaster.c:1809 #, c-format msgid "performing immediate shutdown because data directory lock file is invalid" msgstr "виконується негайне припинення роботи через неприпустимий файл блокування каталогу даних" -#: postmaster/postmaster.c:1987 postmaster/postmaster.c:2015 -#, c-format -msgid "incomplete startup packet" -msgstr "неповний стартовий пакет" - -#: postmaster/postmaster.c:1999 postmaster/postmaster.c:2032 -#, c-format -msgid "invalid length of startup packet" -msgstr "неприпустима довжина стартового пакету" - -#: postmaster/postmaster.c:2061 -#, c-format -msgid "failed to send SSL negotiation response: %m" -msgstr "помилка надсилання протоколу SSL в процесі відповіді зв'язування: %m" - -#: postmaster/postmaster.c:2079 -#, c-format -msgid "received unencrypted data after SSL request" -msgstr "отримані незашифровані дані після запиту SSL" - -#: postmaster/postmaster.c:2080 postmaster/postmaster.c:2124 -#, c-format -msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." -msgstr "Це може бути або помилкою клієнтського програмного забезпечення, або доказом спроби техносферної атаки." - -#: postmaster/postmaster.c:2105 -#, c-format -msgid "failed to send GSSAPI negotiation response: %m" -msgstr "помилка надсилання GSSAPI в процесі відповіді зв'язування: %m" - -#: postmaster/postmaster.c:2123 -#, c-format -msgid "received unencrypted data after GSSAPI encryption request" -msgstr "отримані незашифровані дані після запиту шифрування GSSAPI" - -#: postmaster/postmaster.c:2147 -#, c-format -msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" -msgstr "протокол інтерфейсу, що не підтримується, %u.%u: сервер підтримує %u.0 до %u.%u" - -#: postmaster/postmaster.c:2214 -#, c-format -msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." -msgstr "Дійсні значення: \"false\", 0, \"true\", 1, \"database\"." - -#: postmaster/postmaster.c:2255 -#, c-format -msgid "invalid startup packet layout: expected terminator as last byte" -msgstr "неприпустима структура стартового пакету: останнім байтом очікувався термінатор" - -#: postmaster/postmaster.c:2272 -#, c-format -msgid "no PostgreSQL user name specified in startup packet" -msgstr "не вказано жодного ім'я користувача PostgreSQL у стартовому пакеті" - -#: postmaster/postmaster.c:2336 -#, c-format -msgid "the database system is starting up" -msgstr "система бази даних запускається" - -#: postmaster/postmaster.c:2342 -#, c-format -msgid "the database system is not yet accepting connections" -msgstr "система бази даних ще не приймає підключення" - -#: postmaster/postmaster.c:2343 -#, c-format -msgid "Consistent recovery state has not been yet reached." -msgstr "Узгодженого стану відновлення ще не досягнуто." - -#: postmaster/postmaster.c:2347 -#, c-format -msgid "the database system is not accepting connections" -msgstr "система бази даних не приймає підключення" - -#: postmaster/postmaster.c:2348 -#, c-format -msgid "Hot standby mode is disabled." -msgstr "Режим Hot standby вимкнений." - -#: postmaster/postmaster.c:2353 -#, c-format -msgid "the database system is shutting down" -msgstr "система бази даних завершує роботу" - -#: postmaster/postmaster.c:2358 -#, c-format -msgid "the database system is in recovery mode" -msgstr "система бази даних у режимі відновлення" - -#: postmaster/postmaster.c:2363 storage/ipc/procarray.c:491 -#: storage/ipc/sinvaladt.c:306 storage/lmgr/proc.c:353 -#, c-format -msgid "sorry, too many clients already" -msgstr "вибачте, вже забагато клієнтів" - -#: postmaster/postmaster.c:2450 +#: postmaster/postmaster.c:1872 #, c-format msgid "wrong key in cancel request for process %d" msgstr "неправильний ключ в запиті скасування процесу %d" -#: postmaster/postmaster.c:2462 +#: postmaster/postmaster.c:1884 #, c-format msgid "PID %d in cancel request did not match any process" msgstr "PID %d в запиті на скасування не відповідає жодному процесу" -#: postmaster/postmaster.c:2729 +#: postmaster/postmaster.c:2105 #, c-format msgid "received SIGHUP, reloading configuration files" msgstr "отримано SIGHUP, поновлення файлів конфігурацій" #. translator: %s is a configuration file -#: postmaster/postmaster.c:2753 postmaster/postmaster.c:2757 +#: postmaster/postmaster.c:2133 postmaster/postmaster.c:2137 #, c-format msgid "%s was not reloaded" msgstr "%s не було перезавантажено" -#: postmaster/postmaster.c:2767 +#: postmaster/postmaster.c:2147 #, c-format msgid "SSL configuration was not reloaded" msgstr "Конфігурація протоколу SSL не була перезавантажена" -#: postmaster/postmaster.c:2857 +#: postmaster/postmaster.c:2233 #, c-format msgid "received smart shutdown request" msgstr "отримано smart запит на завершення роботи" -#: postmaster/postmaster.c:2898 +#: postmaster/postmaster.c:2274 #, c-format msgid "received fast shutdown request" msgstr "отримано швидкий запит на завершення роботи" -#: postmaster/postmaster.c:2916 +#: postmaster/postmaster.c:2292 #, c-format msgid "aborting any active transactions" msgstr "переривання будь-яких активних транзакцій" -#: postmaster/postmaster.c:2940 +#: postmaster/postmaster.c:2316 #, c-format msgid "received immediate shutdown request" msgstr "отримано запит на негайне завершення роботи" -#: postmaster/postmaster.c:3016 +#: postmaster/postmaster.c:2388 #, c-format msgid "shutdown at recovery target" msgstr "завершення роботи при відновленні мети" -#: postmaster/postmaster.c:3034 postmaster/postmaster.c:3070 +#: postmaster/postmaster.c:2406 postmaster/postmaster.c:2442 msgid "startup process" msgstr "стартовий процес" -#: postmaster/postmaster.c:3037 +#: postmaster/postmaster.c:2409 #, c-format msgid "aborting startup due to startup process failure" msgstr "переривання запуску через помилку в стартовому процесі" -#: postmaster/postmaster.c:3110 +#: postmaster/postmaster.c:2484 #, c-format msgid "database system is ready to accept connections" msgstr "система бази даних готова до отримання підключення" -#: postmaster/postmaster.c:3131 +#: postmaster/postmaster.c:2505 msgid "background writer process" msgstr "процес фонового запису" -#: postmaster/postmaster.c:3178 +#: postmaster/postmaster.c:2552 msgid "checkpointer process" msgstr "процес контрольних точок" -#: postmaster/postmaster.c:3194 +#: postmaster/postmaster.c:2568 msgid "WAL writer process" msgstr "Процес запису WAL" -#: postmaster/postmaster.c:3209 +#: postmaster/postmaster.c:2583 msgid "WAL receiver process" msgstr "Процес отримання WAL" -#: postmaster/postmaster.c:3224 +#: postmaster/postmaster.c:2597 +msgid "WAL summarizer process" +msgstr "Процес підсумовування WAL" + +#: postmaster/postmaster.c:2612 msgid "autovacuum launcher process" msgstr "процес запуску автоочистки" -#: postmaster/postmaster.c:3242 +#: postmaster/postmaster.c:2630 msgid "archiver process" msgstr "процес архівації" -#: postmaster/postmaster.c:3255 +#: postmaster/postmaster.c:2643 msgid "system logger process" msgstr "процес системного журналювання" -#: postmaster/postmaster.c:3312 +#: postmaster/postmaster.c:2660 +msgid "slot sync worker process" +msgstr "робочий процес синхронізації слоту" + +#: postmaster/postmaster.c:2716 #, c-format msgid "background worker \"%s\"" msgstr "фоновий виконавець \"%s\"" -#: postmaster/postmaster.c:3391 postmaster/postmaster.c:3411 -#: postmaster/postmaster.c:3418 postmaster/postmaster.c:3436 +#: postmaster/postmaster.c:2795 postmaster/postmaster.c:2815 +#: postmaster/postmaster.c:2822 postmaster/postmaster.c:2840 msgid "server process" msgstr "процес сервера" -#: postmaster/postmaster.c:3490 +#: postmaster/postmaster.c:2894 #, c-format msgid "terminating any other active server processes" msgstr "завершення будь-яких інших активних серверних процесів" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3665 +#: postmaster/postmaster.c:3081 #, c-format msgid "%s (PID %d) exited with exit code %d" msgstr "%s (PID %d) завершився з кодом виходу %d" -#: postmaster/postmaster.c:3667 postmaster/postmaster.c:3679 -#: postmaster/postmaster.c:3689 postmaster/postmaster.c:3700 +#: postmaster/postmaster.c:3083 postmaster/postmaster.c:3095 +#: postmaster/postmaster.c:3105 postmaster/postmaster.c:3116 #, c-format msgid "Failed process was running: %s" msgstr "Процес що завершився виконував дію: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3676 +#: postmaster/postmaster.c:3092 #, c-format msgid "%s (PID %d) was terminated by exception 0x%X" msgstr "%s (PID %d) був перерваний винятком 0x%X" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3686 +#: postmaster/postmaster.c:3102 #, c-format msgid "%s (PID %d) was terminated by signal %d: %s" msgstr "%s (PID %d) був перерваний сигналом %d: %s" #. translator: %s is a noun phrase describing a child process, such as #. "server process" -#: postmaster/postmaster.c:3698 +#: postmaster/postmaster.c:3114 #, c-format msgid "%s (PID %d) exited with unrecognized status %d" msgstr "%s (PID %d) завершився з нерозпізнаним статусом %d" -#: postmaster/postmaster.c:3906 +#: postmaster/postmaster.c:3330 #, c-format msgid "abnormal database system shutdown" msgstr "ненормальне завершення роботи системи бази даних" -#: postmaster/postmaster.c:3932 +#: postmaster/postmaster.c:3356 #, c-format msgid "shutting down due to startup process failure" msgstr "завершення роботи через помилку в стартовому процесі" -#: postmaster/postmaster.c:3938 +#: postmaster/postmaster.c:3362 #, c-format -msgid "shutting down because restart_after_crash is off" -msgstr "завершення роботи, тому що restart_after_crash вимкнено" +msgid "shutting down because \"restart_after_crash\" is off" +msgstr "завершення роботи, тому що \"restart_after_crash\" вимкнено" -#: postmaster/postmaster.c:3950 +#: postmaster/postmaster.c:3374 #, c-format msgid "all server processes terminated; reinitializing" msgstr "усі серверні процеси перервано; повторна ініціалізація" -#: postmaster/postmaster.c:4144 postmaster/postmaster.c:5462 -#: postmaster/postmaster.c:5860 +#: postmaster/postmaster.c:3573 postmaster/postmaster.c:3983 +#: postmaster/postmaster.c:4372 #, c-format msgid "could not generate random cancel key" msgstr "не вдалося згенерувати випадковий ключ скасування" -#: postmaster/postmaster.c:4206 +#: postmaster/postmaster.c:3606 #, c-format msgid "could not fork new process for connection: %m" msgstr "не вдалося породити нові процеси для з'єднання: %m" -#: postmaster/postmaster.c:4248 +#: postmaster/postmaster.c:3648 msgid "could not fork new process for connection: " msgstr "не вдалося породити нові процеси для з'єднання: " -#: postmaster/postmaster.c:4354 -#, c-format -msgid "connection received: host=%s port=%s" -msgstr "з'єднання отримано: хост=%s порт=%s" - -#: postmaster/postmaster.c:4359 -#, c-format -msgid "connection received: host=%s" -msgstr "з'єднання отримано: хост=%s" - -#: postmaster/postmaster.c:4596 -#, c-format -msgid "could not execute server process \"%s\": %m" -msgstr "не вдалося виконати серверні процеси \"%s\":%m" - -#: postmaster/postmaster.c:4654 -#, c-format -msgid "could not create backend parameter file mapping: error code %lu" -msgstr "не вдалося створити відображення файлу параметру внутрішнього сервера: код помилки %lu" - -#: postmaster/postmaster.c:4663 -#, c-format -msgid "could not map backend parameter memory: error code %lu" -msgstr "не вдалося відобразити пам'ять параметру внутрішнього сервера: код помилки %lu" - -#: postmaster/postmaster.c:4690 -#, c-format -msgid "subprocess command line too long" -msgstr "командний рядок підпроцесу занадто довгий" - -#: postmaster/postmaster.c:4708 -#, c-format -msgid "CreateProcess() call failed: %m (error code %lu)" -msgstr "помилка виклику CreateProcess(): %m (код помилки %lu)" - -#: postmaster/postmaster.c:4735 -#, c-format -msgid "could not unmap view of backend parameter file: error code %lu" -msgstr "не вдалося вимкнути відображення файлу параметру внутрішнього сервера: код помилки %lu" - -#: postmaster/postmaster.c:4739 -#, c-format -msgid "could not close handle to backend parameter file: error code %lu" -msgstr "не вдалося закрити покажчик файлу параметру внутрішнього сервера: код помилки %lu" - -#: postmaster/postmaster.c:4761 -#, c-format -msgid "giving up after too many tries to reserve shared memory" -msgstr "кількість повторних спроб резервування спільної пам'яті досягло межі" - -#: postmaster/postmaster.c:4762 -#, c-format -msgid "This might be caused by ASLR or antivirus software." -msgstr "Це може бути викликано антивірусним програмним забезпеченням або ASLR." - -#: postmaster/postmaster.c:4935 -#, c-format -msgid "SSL configuration could not be loaded in child process" -msgstr "Не вдалося завантажити конфігурацію SSL в дочірній процес" - -#: postmaster/postmaster.c:5060 +#: postmaster/postmaster.c:3682 #, c-format msgid "Please report this to <%s>." msgstr "Будь-ласка повідомте про це <%s>." -#: postmaster/postmaster.c:5128 +#: postmaster/postmaster.c:3750 #, c-format msgid "database system is ready to accept read-only connections" msgstr "система бази даних готова до отримання підключення лише для читання" -#: postmaster/postmaster.c:5386 -#, c-format -msgid "could not fork startup process: %m" -msgstr "не вдалося породити стартовий процес: %m" - -#: postmaster/postmaster.c:5390 -#, c-format -msgid "could not fork archiver process: %m" -msgstr "не вдалося породити процес архіватора: %m" - -#: postmaster/postmaster.c:5394 -#, c-format -msgid "could not fork background writer process: %m" -msgstr "не вдалося породити фоновий процес запису: %m" - -#: postmaster/postmaster.c:5398 -#, c-format -msgid "could not fork checkpointer process: %m" -msgstr "не вдалося породити процес контрольних точок: %m" - -#: postmaster/postmaster.c:5402 -#, c-format -msgid "could not fork WAL writer process: %m" -msgstr "не вдалося породити процес запису WAL: %m" - -#: postmaster/postmaster.c:5406 +#: postmaster/postmaster.c:3933 #, c-format -msgid "could not fork WAL receiver process: %m" -msgstr "не вдалося породити процес отримання WAL: %m" +msgid "could not fork \"%s\" process: %m" +msgstr "не вдалося породити процес \"%s\": %m" -#: postmaster/postmaster.c:5410 -#, c-format -msgid "could not fork process: %m" -msgstr "не вдалося породити процес: %m" - -#: postmaster/postmaster.c:5611 postmaster/postmaster.c:5638 +#: postmaster/postmaster.c:4171 postmaster/postmaster.c:4205 #, c-format msgid "database connection requirement not indicated during registration" msgstr "під час реєстрації не вказувалося, що вимагається підключення до бази даних" -#: postmaster/postmaster.c:5622 postmaster/postmaster.c:5649 +#: postmaster/postmaster.c:4181 postmaster/postmaster.c:4215 #, c-format msgid "invalid processing mode in background worker" msgstr "неприпустимий режим обробки у фоновому записі" -#: postmaster/postmaster.c:5734 -#, c-format -msgid "could not fork worker process: %m" -msgstr "не вдалося породити процес запису: %m" - -#: postmaster/postmaster.c:5846 -#, c-format -msgid "no slot available for new worker process" -msgstr "немає доступного слоту для нового робочого процесу" - -#: postmaster/postmaster.c:6177 -#, c-format -msgid "could not duplicate socket %d for use in backend: error code %d" -msgstr "не вдалося продублювати сокет %d для використання: код помилки %d" - -#: postmaster/postmaster.c:6209 -#, c-format -msgid "could not create inherited socket: error code %d\n" -msgstr "не вдалося створити успадкований сокет: код помилки %d\n" - -#: postmaster/postmaster.c:6238 +#: postmaster/postmaster.c:4275 #, c-format -msgid "could not open backend variables file \"%s\": %s\n" -msgstr "не вдалося відкрити внутрішні змінні файли \"%s\": %s\n" +msgid "could not fork background worker process: %m" +msgstr "не вдалося породити фоновий процес: %m" -#: postmaster/postmaster.c:6245 +#: postmaster/postmaster.c:4358 #, c-format -msgid "could not read from backend variables file \"%s\": %s\n" -msgstr "не вдалося прочитати внутрішні змінні файли \"%s\": %s\n" +msgid "no slot available for new background worker process" +msgstr "немає доступного слоту для нового фонового робочого процесу" -#: postmaster/postmaster.c:6254 -#, c-format -msgid "could not remove file \"%s\": %s\n" -msgstr "не вдалося видалити файл \"%s\": %s\n" - -#: postmaster/postmaster.c:6271 -#, c-format -msgid "could not map view of backend variables: error code %lu\n" -msgstr "не вдалося відобразити файл серверних змінних: код помилки %lu\n" - -#: postmaster/postmaster.c:6280 -#, c-format -msgid "could not unmap view of backend variables: error code %lu\n" -msgstr "не вдалося вимкнути відображення файлу серверних змінних: код помилки %lu\n" - -#: postmaster/postmaster.c:6287 -#, c-format -msgid "could not close handle to backend parameter variables: error code %lu\n" -msgstr "не вдалося закрити покажчик файлу серверних змінних: код помилки %lu\n" - -#: postmaster/postmaster.c:6446 +#: postmaster/postmaster.c:4621 #, c-format msgid "could not read exit code for process\n" msgstr "не вдалося прочитати код завершення процесу\n" -#: postmaster/postmaster.c:6488 +#: postmaster/postmaster.c:4663 #, c-format msgid "could not post child completion status\n" msgstr "не вдалося надіслати статус завершення нащадка\n" -#: postmaster/syslogger.c:501 postmaster/syslogger.c:1222 +#: postmaster/syslogger.c:529 postmaster/syslogger.c:1173 #, c-format msgid "could not read from logger pipe: %m" msgstr "не вдалося прочитати з каналу журналювання: %m" -#: postmaster/syslogger.c:598 postmaster/syslogger.c:612 +#: postmaster/syslogger.c:629 postmaster/syslogger.c:643 #, c-format msgid "could not create pipe for syslog: %m" msgstr "не вдалося створити канал для syslog: %m" -#: postmaster/syslogger.c:677 +#: postmaster/syslogger.c:712 #, c-format msgid "could not fork system logger: %m" msgstr "не вдалося породити процес системного журналювання: %m" -#: postmaster/syslogger.c:713 +#: postmaster/syslogger.c:731 #, c-format msgid "redirecting log output to logging collector process" msgstr "переспрямовування виводу в протокол прочесу збирача протоколів" -#: postmaster/syslogger.c:714 +#: postmaster/syslogger.c:732 #, c-format msgid "Future log output will appear in directory \"%s\"." msgstr "Наступні протоколи будуть виводитись в каталог \"%s\"." -#: postmaster/syslogger.c:722 +#: postmaster/syslogger.c:740 #, c-format msgid "could not redirect stdout: %m" msgstr "не вдалося переспрямувати stdout: %m" -#: postmaster/syslogger.c:727 postmaster/syslogger.c:744 +#: postmaster/syslogger.c:745 postmaster/syslogger.c:762 #, c-format msgid "could not redirect stderr: %m" msgstr "не вдалося переспрямувати stderr: %m" -#: postmaster/syslogger.c:1177 +#: postmaster/syslogger.c:1128 #, c-format -msgid "could not write to log file: %s\n" -msgstr "не вдалося записати до файлу протокола: %s\n" +msgid "could not write to log file: %m\n" +msgstr "не вдалося записати до файлу протокола: %m\n" -#: postmaster/syslogger.c:1295 +#: postmaster/syslogger.c:1246 #, c-format msgid "could not open log file \"%s\": %m" msgstr "не вдалося відкрити файл журналу \"%s\": %m" -#: postmaster/syslogger.c:1385 +#: postmaster/syslogger.c:1336 #, c-format msgid "disabling automatic rotation (use SIGHUP to re-enable)" msgstr "вимкнення автоматичного обертання (щоб повторно ввімкнути, використайте SIGHUP)" -#: regex/regc_pg_locale.c:242 +#: postmaster/walsummarizer.c:740 +#, c-format +msgid "WAL summarization is not progressing" +msgstr "Підбиття підсумків WAL не просувається" + +#: postmaster/walsummarizer.c:741 +#, c-format +msgid "Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory." +msgstr "Підсумовування потрібне через %X/%X, але воно застрягло на %X/%X на диску та %X/%X у пам'яті." + +#: postmaster/walsummarizer.c:755 +#, c-format +msgid "still waiting for WAL summarization through %X/%X after %ld second" +msgid_plural "still waiting for WAL summarization through %X/%X after %ld seconds" +msgstr[0] "все ще чекає на підбиття підсумків WAL через %X/%X через %ld секунду" +msgstr[1] "все ще чекає на підбиття підсумків WAL через %X/%X через %ld секунди" +msgstr[2] "все ще чекає на підбиття підсумків WAL через %X/%X через %ld секунд" +msgstr[3] "все ще чекає на підбиття підсумків WAL через %X/%X через %ld секунд" + +#: postmaster/walsummarizer.c:760 +#, c-format +msgid "Summarization has reached %X/%X on disk and %X/%X in memory." +msgstr "Підсумок досягнув %X/%X на диску та %X/%X у пам'яті." + +#: postmaster/walsummarizer.c:1000 +#, c-format +msgid "could not find a valid record after %X/%X" +msgstr "не вдалося знайти припустимий запис після %X/%X" + +#: postmaster/walsummarizer.c:1045 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X: %s" +msgstr "не вдалося прочитати WAL з часової шкали %u за адресою %X/%X: %s" + +#: postmaster/walsummarizer.c:1051 +#, c-format +msgid "could not read WAL from timeline %u at %X/%X" +msgstr "не вдалося прочитати WAL з часової шкали %u на %X/%X" + +#: regex/regc_pg_locale.c:244 #, c-format msgid "could not determine which collation to use for regular expression" msgstr "не вдалося визначити які параметри сортування використати для регулярного виразу" -#: regex/regc_pg_locale.c:265 +#: regex/regc_pg_locale.c:262 #, c-format msgid "nondeterministic collations are not supported for regular expressions" msgstr "недетерміновані правила сортування не підтримуються для регулярних виразів" -#: replication/libpqwalreceiver/libpqwalreceiver.c:245 -#: replication/libpqwalreceiver/libpqwalreceiver.c:332 +#: replication/libpqwalreceiver/libpqwalreceiver.c:267 +#: replication/libpqwalreceiver/libpqwalreceiver.c:358 #, c-format msgid "password is required" msgstr "пароль обов'язковий" -#: replication/libpqwalreceiver/libpqwalreceiver.c:246 +#: replication/libpqwalreceiver/libpqwalreceiver.c:268 #, c-format msgid "Non-superuser cannot connect if the server does not request a password." msgstr "Несуперкористувач не може підключитися, якщо сервер не запитує пароль." -#: replication/libpqwalreceiver/libpqwalreceiver.c:247 +#: replication/libpqwalreceiver/libpqwalreceiver.c:269 #, c-format msgid "Target server's authentication method must be changed, or set password_required=false in the subscription parameters." msgstr "Необхідно змінити метод автентифікації цільового сервера або встановити password_required=false у параметрах підписки." -#: replication/libpqwalreceiver/libpqwalreceiver.c:259 +#: replication/libpqwalreceiver/libpqwalreceiver.c:285 #, c-format msgid "could not clear search path: %s" msgstr "не вдалося очистити шлях пошуку: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:305 +#: replication/libpqwalreceiver/libpqwalreceiver.c:331 +#: replication/libpqwalreceiver/libpqwalreceiver.c:517 #, c-format msgid "invalid connection string syntax: %s" msgstr "неприпустимий синтаксис рядка підключення: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:333 +#: replication/libpqwalreceiver/libpqwalreceiver.c:359 #, c-format msgid "Non-superusers must provide a password in the connection string." msgstr "Несуперкористувачі повинні вказати пароль для рядка підключення." -#: replication/libpqwalreceiver/libpqwalreceiver.c:360 +#: replication/libpqwalreceiver/libpqwalreceiver.c:386 #, c-format msgid "could not parse connection string: %s" msgstr "не вдалося аналізувати рядок підключення: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:433 +#: replication/libpqwalreceiver/libpqwalreceiver.c:459 #, c-format msgid "could not receive database system identifier and timeline ID from the primary server: %s" msgstr "не вдалося отримати ідентифікатор системи бази даних та ідентифікатор часової шкали з основного серверу: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:449 -#: replication/libpqwalreceiver/libpqwalreceiver.c:692 +#: replication/libpqwalreceiver/libpqwalreceiver.c:476 +#: replication/libpqwalreceiver/libpqwalreceiver.c:763 #, c-format msgid "invalid response from primary server" msgstr "неприпустима відповідь з основного серверу" -#: replication/libpqwalreceiver/libpqwalreceiver.c:450 +#: replication/libpqwalreceiver/libpqwalreceiver.c:477 #, c-format msgid "Could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields." msgstr "Не вдалося ідентифікувати систему: отримано %d рядків і %d полів, очікувалось %d рядків і %d або більше полів." -#: replication/libpqwalreceiver/libpqwalreceiver.c:535 -#: replication/libpqwalreceiver/libpqwalreceiver.c:542 -#: replication/libpqwalreceiver/libpqwalreceiver.c:572 +#: replication/libpqwalreceiver/libpqwalreceiver.c:606 +#: replication/libpqwalreceiver/libpqwalreceiver.c:613 +#: replication/libpqwalreceiver/libpqwalreceiver.c:643 #, c-format msgid "could not start WAL streaming: %s" msgstr "не вдалося почати потокове передавання WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:596 +#: replication/libpqwalreceiver/libpqwalreceiver.c:667 #, c-format msgid "could not send end-of-streaming message to primary: %s" msgstr "не вдалося передати основному серверу повідомлення про кінець передвання: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:619 +#: replication/libpqwalreceiver/libpqwalreceiver.c:690 #, c-format msgid "unexpected result set after end-of-streaming" msgstr "неочікуваний набір результатів після кінця передачі" -#: replication/libpqwalreceiver/libpqwalreceiver.c:634 +#: replication/libpqwalreceiver/libpqwalreceiver.c:705 #, c-format msgid "error while shutting down streaming COPY: %s" msgstr "помилка при завершенні потокового передавання \"копіювати\": %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:644 +#: replication/libpqwalreceiver/libpqwalreceiver.c:715 #, c-format msgid "error reading result of streaming command: %s" msgstr "помилка при читанні результату команди потокового передавання: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:653 -#: replication/libpqwalreceiver/libpqwalreceiver.c:889 +#: replication/libpqwalreceiver/libpqwalreceiver.c:724 +#: replication/libpqwalreceiver/libpqwalreceiver.c:957 #, c-format msgid "unexpected result after CommandComplete: %s" msgstr "неочікуваний результат CommandComplete: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:680 +#: replication/libpqwalreceiver/libpqwalreceiver.c:751 #, c-format msgid "could not receive timeline history file from the primary server: %s" msgstr "не вдалося отримати файл історії часової шкали з основного сервера: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:693 +#: replication/libpqwalreceiver/libpqwalreceiver.c:764 #, c-format msgid "Expected 1 tuple with 2 fields, got %d tuples with %d fields." msgstr "Очікувалося 1 кортеж з 2 поле, отримано %d кортежів з %d полями." -#: replication/libpqwalreceiver/libpqwalreceiver.c:852 -#: replication/libpqwalreceiver/libpqwalreceiver.c:905 -#: replication/libpqwalreceiver/libpqwalreceiver.c:912 +#: replication/libpqwalreceiver/libpqwalreceiver.c:920 +#: replication/libpqwalreceiver/libpqwalreceiver.c:973 +#: replication/libpqwalreceiver/libpqwalreceiver.c:980 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "не вдалося отримати дані з WAL потоку: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:932 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1000 #, c-format msgid "could not send data to WAL stream: %s" msgstr "не вдалося передати дані потоку WAL: %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1024 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1101 #, c-format msgid "could not create replication slot \"%s\": %s" msgstr "не вдалося створити слот реплікації \"%s\": %s" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1070 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1140 +#, c-format +msgid "could not alter replication slot \"%s\": %s" +msgstr "не може змінити слот реплікації \"%s\": %s" + +#: replication/libpqwalreceiver/libpqwalreceiver.c:1174 #, c-format msgid "invalid query response" msgstr "неприпустима відповідь на запит" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1071 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1175 #, c-format msgid "Expected %d fields, got %d fields." msgstr "Очікувалося %d полів, отримано %d полі." -#: replication/libpqwalreceiver/libpqwalreceiver.c:1141 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1245 #, c-format msgid "the query interface requires a database connection" msgstr "інтерфейс запитів вимагає підключення до бази даних" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1172 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1277 msgid "empty query" msgstr "пустий запит" -#: replication/libpqwalreceiver/libpqwalreceiver.c:1178 +#: replication/libpqwalreceiver/libpqwalreceiver.c:1283 msgid "unexpected pipeline mode" msgstr "неочікуваний режим конвеєра" @@ -19737,189 +20138,205 @@ msgstr "неочікуваний режим конвеєра" msgid "logical replication parallel apply worker for subscription \"%s\" has finished" msgstr "завершено логічну реплікацію паралельного аплікатора для підписки \"%s\"" -#: replication/logical/applyparallelworker.c:825 +#: replication/logical/applyparallelworker.c:822 #, c-format msgid "lost connection to the logical replication apply worker" msgstr "втрачено зв'язок з робочим застосунком логічної реплікації" -#: replication/logical/applyparallelworker.c:1027 -#: replication/logical/applyparallelworker.c:1029 +#: replication/logical/applyparallelworker.c:1024 +#: replication/logical/applyparallelworker.c:1026 msgid "logical replication parallel apply worker" msgstr "застосовуючій робочий процес паралельної реплікації" -#: replication/logical/applyparallelworker.c:1043 +#: replication/logical/applyparallelworker.c:1040 #, c-format msgid "logical replication parallel apply worker exited due to error" msgstr "паралельний робочий додаток логічнаої реплікації завершив роботу через помилку" -#: replication/logical/applyparallelworker.c:1130 -#: replication/logical/applyparallelworker.c:1303 +#: replication/logical/applyparallelworker.c:1127 +#: replication/logical/applyparallelworker.c:1300 #, c-format msgid "lost connection to the logical replication parallel apply worker" msgstr "втрачено зв'язок з паралельним робочим застосунком логічної реплікації" -#: replication/logical/applyparallelworker.c:1183 +#: replication/logical/applyparallelworker.c:1180 #, c-format msgid "could not send data to shared-memory queue" msgstr "не вдалося передати дані в чергу в спільну пам'ять" -#: replication/logical/applyparallelworker.c:1218 +#: replication/logical/applyparallelworker.c:1215 #, c-format msgid "logical replication apply worker will serialize the remaining changes of remote transaction %u to a file" msgstr "застосовуючий процес логічної реплікації буде серіалізувати зміни, що залишилися віддаленою транзакцією %u до файлу" -#: replication/logical/decode.c:180 replication/logical/logical.c:140 +#: replication/logical/decode.c:177 replication/logical/logical.c:141 #, c-format -msgid "logical decoding on standby requires wal_level >= logical on the primary" -msgstr "логічне декодування на standby вимагає wal_level >= logical в основному" +msgid "logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary" +msgstr "логічне декодування на standby вимагає \"wal_level\" >= \"logical\" на основному сервері" -#: replication/logical/launcher.c:331 +#: replication/logical/launcher.c:334 #, c-format msgid "cannot start logical replication workers when max_replication_slots = 0" msgstr "неможливо почати логічні записи реплікацій, коли max_replication_slots = 0" -#: replication/logical/launcher.c:424 +#: replication/logical/launcher.c:427 #, c-format msgid "out of logical replication worker slots" msgstr "недостатньо слотів для процесів логічної реплікації" -#: replication/logical/launcher.c:425 replication/logical/launcher.c:499 -#: replication/slot.c:1297 storage/lmgr/lock.c:964 storage/lmgr/lock.c:1002 -#: storage/lmgr/lock.c:2787 storage/lmgr/lock.c:4172 storage/lmgr/lock.c:4237 -#: storage/lmgr/lock.c:4587 storage/lmgr/predicate.c:2413 -#: storage/lmgr/predicate.c:2428 storage/lmgr/predicate.c:3825 +#: replication/logical/launcher.c:428 replication/logical/launcher.c:514 +#: replication/slot.c:1524 storage/lmgr/lock.c:985 storage/lmgr/lock.c:1023 +#: storage/lmgr/lock.c:2826 storage/lmgr/lock.c:4211 storage/lmgr/lock.c:4276 +#: storage/lmgr/lock.c:4626 storage/lmgr/predicate.c:2464 +#: storage/lmgr/predicate.c:2479 storage/lmgr/predicate.c:3876 #, c-format -msgid "You might need to increase %s." -msgstr "Можливо, вам слід збільшити %s." +msgid "You might need to increase \"%s\"." +msgstr "Можливо, вам слід збільшити \"%s\"." -#: replication/logical/launcher.c:498 +#: replication/logical/launcher.c:513 #, c-format msgid "out of background worker slots" msgstr "недостатньо слотів для фонових робочих процесів" -#: replication/logical/launcher.c:705 +#: replication/logical/launcher.c:720 #, c-format msgid "logical replication worker slot %d is empty, cannot attach" msgstr "слот запису логічної реплікації %d пустий, неможливо підключитися" -#: replication/logical/launcher.c:714 +#: replication/logical/launcher.c:729 #, c-format msgid "logical replication worker slot %d is already used by another worker, cannot attach" msgstr "слот запису логічної реплікації %d вже використовується іншим виконавцем, неможливо підключитися" -#: replication/logical/logical.c:120 +#: replication/logical/logical.c:121 #, c-format -msgid "logical decoding requires wal_level >= logical" -msgstr "логічне декодування вимагає wal_level >= logical" +msgid "logical decoding requires \"wal_level\" >= \"logical\"" +msgstr "логічне декодування вимагає \"wal_level\" >= logical\"" -#: replication/logical/logical.c:125 +#: replication/logical/logical.c:126 #, c-format msgid "logical decoding requires a database connection" msgstr "логічне декодування вимагає підключення до бази даних" -#: replication/logical/logical.c:363 replication/logical/logical.c:517 +#: replication/logical/logical.c:365 replication/logical/logical.c:519 #, c-format msgid "cannot use physical replication slot for logical decoding" msgstr "неможливо використовувати слот невідповідної реплікації для логічного кодування" -#: replication/logical/logical.c:368 replication/logical/logical.c:522 +#: replication/logical/logical.c:370 replication/logical/logical.c:529 #, c-format msgid "replication slot \"%s\" was not created in this database" msgstr "слот реплікації \"%s\" був створений не в цій базі даних" -#: replication/logical/logical.c:375 +#: replication/logical/logical.c:377 #, c-format msgid "cannot create logical replication slot in transaction that has performed writes" msgstr "неможливо створити слот логічної реплікації у транзакції, що виконує записування" -#: replication/logical/logical.c:534 replication/logical/logical.c:541 +#: replication/logical/logical.c:540 +#, c-format +msgid "cannot use replication slot \"%s\" for logical decoding" +msgstr "не може використовувати слот реплікації \"%s\" для логічного декодування" + +#: replication/logical/logical.c:542 replication/slot.c:798 +#: replication/slot.c:829 +#, c-format +msgid "This replication slot is being synchronized from the primary server." +msgstr "Цей слот реплікації синхронізується з основного сервера." + +#: replication/logical/logical.c:543 +#, c-format +msgid "Specify another replication slot." +msgstr "Вкажіть інший слот реплікації." + +#: replication/logical/logical.c:554 replication/logical/logical.c:561 #, c-format msgid "can no longer get changes from replication slot \"%s\"" msgstr "більше не можна отримувати зміни з слоту реплікації \"%s\"" -#: replication/logical/logical.c:536 +#: replication/logical/logical.c:556 #, c-format msgid "This slot has been invalidated because it exceeded the maximum reserved size." msgstr "Цей слот визнано недійсним, тому що він перевищив максимально зарезервований розмір." -#: replication/logical/logical.c:543 +#: replication/logical/logical.c:563 #, c-format msgid "This slot has been invalidated because it was conflicting with recovery." msgstr "Цей слот було скасовано, оскільки він суперечив відновленню." -#: replication/logical/logical.c:608 +#: replication/logical/logical.c:628 #, c-format msgid "starting logical decoding for slot \"%s\"" msgstr "початок логічного декодування для слоту \"%s\"" -#: replication/logical/logical.c:610 +#: replication/logical/logical.c:630 #, c-format msgid "Streaming transactions committing after %X/%X, reading WAL from %X/%X." msgstr "Потокове передавання транзакцій, що затверджені, після %X/%X, читання WAL з %X/%X." -#: replication/logical/logical.c:758 +#: replication/logical/logical.c:778 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X" msgstr "слот \"%s\", плагін виходу \"%s\", у зворотньому виклику %s, пов'язаний номер LSN %X/%X" -#: replication/logical/logical.c:764 +#: replication/logical/logical.c:784 #, c-format msgid "slot \"%s\", output plugin \"%s\", in the %s callback" msgstr "слот \"%s\", плагін виходу \"%s\", у зворотньому виклику %s" -#: replication/logical/logical.c:935 replication/logical/logical.c:980 -#: replication/logical/logical.c:1025 replication/logical/logical.c:1071 +#: replication/logical/logical.c:955 replication/logical/logical.c:1000 +#: replication/logical/logical.c:1045 replication/logical/logical.c:1091 #, c-format msgid "logical replication at prepare time requires a %s callback" msgstr "логічна реплікація під час підготовки потребує %s зворотнього виклику" -#: replication/logical/logical.c:1303 replication/logical/logical.c:1352 -#: replication/logical/logical.c:1393 replication/logical/logical.c:1479 -#: replication/logical/logical.c:1528 +#: replication/logical/logical.c:1323 replication/logical/logical.c:1372 +#: replication/logical/logical.c:1413 replication/logical/logical.c:1499 +#: replication/logical/logical.c:1548 #, c-format msgid "logical streaming requires a %s callback" msgstr "логічне потокове передавання потребує %s зворотнього виклику" -#: replication/logical/logical.c:1438 +#: replication/logical/logical.c:1458 #, c-format msgid "logical streaming at prepare time requires a %s callback" msgstr "логічне потокове передавання під час підготовки потребує %s зворотнього виклику" -#: replication/logical/logicalfuncs.c:126 +#: replication/logical/logicalfuncs.c:123 #, c-format msgid "slot name must not be null" msgstr "ім'я слоту має бути не Null-значення" -#: replication/logical/logicalfuncs.c:142 +#: replication/logical/logicalfuncs.c:139 #, c-format msgid "options array must not be null" msgstr "масив параметрів має бути не Null-значення" -#: replication/logical/logicalfuncs.c:159 +#: replication/logical/logicalfuncs.c:156 #, c-format msgid "array must be one-dimensional" msgstr "масив має бути одновимірним" -#: replication/logical/logicalfuncs.c:165 +#: replication/logical/logicalfuncs.c:162 #, c-format msgid "array must not contain nulls" msgstr "масив не має включати nulls" -#: replication/logical/logicalfuncs.c:180 utils/adt/json.c:1484 -#: utils/adt/jsonb.c:1403 +#: replication/logical/logicalfuncs.c:177 utils/adt/json.c:1420 +#: utils/adt/jsonb.c:1304 #, c-format msgid "array must have even number of elements" msgstr "масив повинен мати парну кількість елементів" -#: replication/logical/logicalfuncs.c:227 +#: replication/logical/logicalfuncs.c:224 #, c-format msgid "logical decoding output plugin \"%s\" produces binary output, but function \"%s\" expects textual data" msgstr "плагін виходу логічного декодування \"%s\" виробляє бінарний вихід, але функція \"%s\" очікує текстові дані" #: replication/logical/origin.c:190 #, c-format -msgid "cannot query or manipulate replication origin when max_replication_slots = 0" -msgstr "неможливо вимагати або маніпулювати джерелами реплікації, коли max_replication_slots = 0" +msgid "cannot query or manipulate replication origin when \"max_replication_slots\" is 0" +msgstr "неможливо надіслати запит або маніпулювати джерелами реплікації, коли \"max_replication_slots\" = 0" #: replication/logical/origin.c:195 #, c-format @@ -19953,8 +20370,8 @@ msgstr "контрольна точка реплікації має неправ #: replication/logical/origin.c:798 #, c-format -msgid "could not find free replication state, increase max_replication_slots" -msgstr "не вдалося знайти вільний слот для стану реплікації, збільшіть max_replication_slots" +msgid "could not find free replication state, increase \"max_replication_slots\"" +msgstr "не вдалося знайти вільний слот для стану реплікації, збільшіть \"max_replication_slots\"" #: replication/logical/origin.c:806 #, c-format @@ -19966,54 +20383,54 @@ msgstr "відновлений стан реплікації вузла %d в %X msgid "replication slot checkpoint has wrong checksum %u, expected %u" msgstr "неправильна контрольна сума файлу контрольної точки для слота реплікації %u, очікувалось %u" -#: replication/logical/origin.c:944 replication/logical/origin.c:1141 +#: replication/logical/origin.c:944 replication/logical/origin.c:1143 #, c-format msgid "replication origin with ID %d is already active for PID %d" msgstr "джерело реплікації з ID %d вже активний для PID %d" -#: replication/logical/origin.c:955 replication/logical/origin.c:1153 +#: replication/logical/origin.c:955 replication/logical/origin.c:1156 #, c-format msgid "could not find free replication state slot for replication origin with ID %d" msgstr "не вдалося знайти вільний слот стану реплікації для джерела реплікації з ID %d" -#: replication/logical/origin.c:957 replication/logical/origin.c:1155 -#: replication/slot.c:2093 +#: replication/logical/origin.c:957 replication/logical/origin.c:1158 +#: replication/slot.c:2384 #, c-format -msgid "Increase max_replication_slots and try again." -msgstr "Збільшіть max_replication_slots і спробуйте знову." +msgid "Increase \"max_replication_slots\" and try again." +msgstr "Збільшіть \"max_replication_slots\" і спробуйте знову." -#: replication/logical/origin.c:1112 +#: replication/logical/origin.c:1114 #, c-format msgid "cannot setup replication origin when one is already setup" msgstr "не можна налаштувати джерело реплікації, коли один вже налаштований" -#: replication/logical/origin.c:1196 replication/logical/origin.c:1412 -#: replication/logical/origin.c:1432 +#: replication/logical/origin.c:1199 replication/logical/origin.c:1415 +#: replication/logical/origin.c:1435 #, c-format msgid "no replication origin is configured" msgstr "жодне джерело реплікації не налаштоване" -#: replication/logical/origin.c:1282 +#: replication/logical/origin.c:1285 #, c-format msgid "replication origin name \"%s\" is reserved" msgstr "назва джерела реплікації \"%s\" зарезервована" -#: replication/logical/origin.c:1284 +#: replication/logical/origin.c:1287 #, c-format msgid "Origin names \"%s\", \"%s\", and names starting with \"pg_\" are reserved." msgstr "Імена походженням \"%s\", \"%s\" та імена, що починаються з \"pg_\", є зарезервованими." -#: replication/logical/relation.c:240 +#: replication/logical/relation.c:242 #, c-format msgid "\"%s\"" msgstr "\"%s\"" -#: replication/logical/relation.c:243 +#: replication/logical/relation.c:245 #, c-format msgid ", \"%s\"" msgstr ", \"%s\"" -#: replication/logical/relation.c:249 +#: replication/logical/relation.c:251 #, c-format msgid "logical replication target relation \"%s.%s\" is missing replicated column: %s" msgid_plural "logical replication target relation \"%s.%s\" is missing replicated columns: %s" @@ -20022,49 +20439,177 @@ msgstr[1] "в цільовому відношенні логічної репл msgstr[2] "в цільовому відношенні логічної реплікації \"%s.%s\" пропущено репліковані стовпці: %s" msgstr[3] "в цільовому відношенні логічної реплікації \"%s.%s\" пропущено репліковані стовпці: %s" -#: replication/logical/relation.c:304 +#: replication/logical/relation.c:306 #, c-format msgid "logical replication target relation \"%s.%s\" uses system columns in REPLICA IDENTITY index" msgstr "в цільовому відношенні логічної реплікації \"%s.%s\" в індексі REPLICA IDENTITY використовуються системні стовпці" -#: replication/logical/relation.c:396 +#: replication/logical/relation.c:398 #, c-format msgid "logical replication target relation \"%s.%s\" does not exist" msgstr "цільове відношення логічної реплікації \"%s.%s\" не існує" -#: replication/logical/reorderbuffer.c:3936 +#: replication/logical/reorderbuffer.c:3994 #, c-format msgid "could not write to data file for XID %u: %m" msgstr "не вдалося записати у файл даних для XID %u: %m" -#: replication/logical/reorderbuffer.c:4282 -#: replication/logical/reorderbuffer.c:4307 +#: replication/logical/reorderbuffer.c:4340 +#: replication/logical/reorderbuffer.c:4365 #, c-format msgid "could not read from reorderbuffer spill file: %m" msgstr "не вдалося прочитати з файлу розгортання буферу пересортування: %m" -#: replication/logical/reorderbuffer.c:4286 -#: replication/logical/reorderbuffer.c:4311 +#: replication/logical/reorderbuffer.c:4344 +#: replication/logical/reorderbuffer.c:4369 #, c-format msgid "could not read from reorderbuffer spill file: read %d instead of %u bytes" msgstr "не вдалося прочитати з файлу розгортання буферу пересортування: прочитано %d замість %u байт" -#: replication/logical/reorderbuffer.c:4561 +#: replication/logical/reorderbuffer.c:4619 #, c-format msgid "could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m" msgstr "не вдалося видалити файл \"%s\" під час видалення pg_replslot/%s/xid*: %m" -#: replication/logical/reorderbuffer.c:5057 +#: replication/logical/reorderbuffer.c:5115 #, c-format msgid "could not read from file \"%s\": read %d instead of %d bytes" msgstr "не вдалося прочитати з файлу \"%s\": прочитано %d замість %d байт" -#: replication/logical/snapbuild.c:639 +#: replication/logical/slotsync.c:215 +#, c-format +msgid "could not synchronize replication slot \"%s\" because remote slot precedes local slot" +msgstr "не вдалося синхронізувати слот реплікації \"%s\", оскільки віддалений слот передує локальному" + +#: replication/logical/slotsync.c:217 +#, c-format +msgid "The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u." +msgstr "Віддалений слот має LSN %X/%X і каталог xmin %u, а локальний слот має LSN %X/%X і каталог xmin %u." + +#: replication/logical/slotsync.c:459 +#, c-format +msgid "dropped replication slot \"%s\" of database with OID %u" +msgstr "видалено слот реплікації \"%s\" бази даних з OID %u" + +#: replication/logical/slotsync.c:579 +#, c-format +msgid "could not synchronize replication slot \"%s\"" +msgstr "не вдалося синхронізувати слот реплікації \"%s\"" + +#: replication/logical/slotsync.c:580 +#, c-format +msgid "Logical decoding could not find consistent point from local slot's LSN %X/%X." +msgstr "Логічне декодування не може знайти стійку точку з локальних LSN %X/%X." + +#: replication/logical/slotsync.c:589 +#, c-format +msgid "newly created replication slot \"%s\" is sync-ready now" +msgstr "новостворений слот реплікації \"%s\" готовий до синхронізації" + +#: replication/logical/slotsync.c:628 +#, c-format +msgid "skipping slot synchronization because the received slot sync LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X" +msgstr "пропуск синхронізації слотів, оскільки отримана синхронізація слотів LSN %X/%X для слота \"%s\" випереджає позицію очікування %X/%X" + +#: replication/logical/slotsync.c:650 +#, c-format +msgid "exiting from slot synchronization because same name slot \"%s\" already exists on the standby" +msgstr "вихід із синхронізації слотів, оскільки однойменний слот \"%s\" вже існує у режимі очікування" + +#: replication/logical/slotsync.c:819 +#, c-format +msgid "could not fetch failover logical slots info from the primary server: %s" +msgstr "не вдалося отримати інформацію про логічні слоти обходу відмови з основного сервера: %s" + +#: replication/logical/slotsync.c:965 +#, c-format +msgid "could not fetch primary_slot_name \"%s\" info from the primary server: %s" +msgstr "не вдалося отримати інформацію primary_slot_name \"%s\" з первинного сервера: %s" + +#: replication/logical/slotsync.c:967 +#, c-format +msgid "Check if primary_slot_name is configured correctly." +msgstr "Перевірте, чи правильно налаштовано primary_slot_name." + +#: replication/logical/slotsync.c:987 +#, c-format +msgid "cannot synchronize replication slots from a standby server" +msgstr "не вдається синхронізувати слоти реплікації з резервного сервера" + +#. translator: second %s is a GUC variable name +#: replication/logical/slotsync.c:996 +#, c-format +msgid "replication slot \"%s\" specified by \"%s\" does not exist on primary server" +msgstr "слот реплікації \"%s\", на який вказує \"%s\", не існує на основному сервері" + +#. translator: first %s is a connection option; second %s is a GUC +#. variable name +#. +#: replication/logical/slotsync.c:1029 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be specified in \"%s\"" +msgstr "для синхронізації слотів реплікації потрібно, щоб \"%s\" було вказано у \"%s\"" + +#: replication/logical/slotsync.c:1050 +#, c-format +msgid "replication slot synchronization requires \"wal_level\" >= \"logical\"" +msgstr "синхронізація слотів вимагає \"wal_level\" >= \"logical\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1063 replication/logical/slotsync.c:1091 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be set" +msgstr "для синхронізації слотів реплікації потрібно, щоб було вказано \"%s\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1077 +#, c-format +msgid "replication slot synchronization requires \"%s\" to be enabled" +msgstr "синхронізація слотів реплікації потребує ввімкнення \"%s\"" + +#. translator: %s is a GUC variable name +#: replication/logical/slotsync.c:1129 +#, c-format +msgid "replication slot synchronization worker will shut down because \"%s\" is disabled" +msgstr "процес синхронизації слотів реплікації буде вимкнутий, тому що \"%s\" відключено" + +#: replication/logical/slotsync.c:1138 +#, c-format +msgid "replication slot synchronization worker will restart because of a parameter change" +msgstr "процес синхронізації слотів реплікації буде перезавантажений через зміну параметра" + +#: replication/logical/slotsync.c:1162 +#, c-format +msgid "replication slot synchronization worker is shutting down on receiving SIGINT" +msgstr "процес синхронізації слотів реплікації буде вимкнуто через отримання повідомлення SIGINT" + +#: replication/logical/slotsync.c:1287 +#, c-format +msgid "cannot synchronize replication slots when standby promotion is ongoing" +msgstr "неможливо синхронізувати слоти реплікації під час підвищення резервного сервера" + +#: replication/logical/slotsync.c:1295 +#, c-format +msgid "cannot synchronize replication slots concurrently" +msgstr "не може синхронізувати слоти реплікації одночасно" + +#: replication/logical/slotsync.c:1403 +#, c-format +msgid "slot sync worker started" +msgstr "запущено працівника синхронізації слотів" + +#: replication/logical/slotsync.c:1466 replication/slotfuncs.c:900 +#: replication/walreceiver.c:307 +#, c-format +msgid "could not connect to the primary server: %s" +msgstr "не вдалося підключитися до основного серверу: %s" + +#: replication/logical/snapbuild.c:653 #, c-format msgid "initial slot snapshot too large" msgstr "початковий знімок слота занадто великий" -#: replication/logical/snapbuild.c:693 +#: replication/logical/snapbuild.c:707 #, c-format msgid "exported logical decoding snapshot: \"%s\" with %u transaction ID" msgid_plural "exported logical decoding snapshot: \"%s\" with %u transaction IDs" @@ -20073,389 +20618,449 @@ msgstr[1] "експортовано знімок логічного декоду msgstr[2] "експортовано знімок логічного декодування \"%s\" з %u ID транзакціями" msgstr[3] "експортовано знімок логічного декодування \"%s\" з %u ID транзакціями" -#: replication/logical/snapbuild.c:1388 replication/logical/snapbuild.c:1480 -#: replication/logical/snapbuild.c:1996 +#: replication/logical/snapbuild.c:1404 replication/logical/snapbuild.c:1501 +#: replication/logical/snapbuild.c:2017 #, c-format msgid "logical decoding found consistent point at %X/%X" msgstr "узгодження процесу логічного кодування знайдено в точці %X/%X" -#: replication/logical/snapbuild.c:1390 +#: replication/logical/snapbuild.c:1406 #, c-format msgid "There are no running transactions." msgstr "Більше активних транзакцій немає." -#: replication/logical/snapbuild.c:1432 +#: replication/logical/snapbuild.c:1453 #, c-format msgid "logical decoding found initial starting point at %X/%X" msgstr "початкова стартова точка процесу логічного декодування знайдена в точці %X/%X" -#: replication/logical/snapbuild.c:1434 replication/logical/snapbuild.c:1458 +#: replication/logical/snapbuild.c:1455 replication/logical/snapbuild.c:1479 #, c-format msgid "Waiting for transactions (approximately %d) older than %u to end." msgstr "Очікування транзакцій (приблизно %d) старіше, ніж %u до кінця." -#: replication/logical/snapbuild.c:1456 +#: replication/logical/snapbuild.c:1477 #, c-format msgid "logical decoding found initial consistent point at %X/%X" msgstr "початкова точка узгодження процесу логічного кодування знайдена в точці %X/%X" -#: replication/logical/snapbuild.c:1482 +#: replication/logical/snapbuild.c:1503 #, c-format msgid "There are no old transactions anymore." msgstr "Більше старих транзакцій немає." -#: replication/logical/snapbuild.c:1883 +#: replication/logical/snapbuild.c:1904 #, c-format msgid "snapbuild state file \"%s\" has wrong magic number: %u instead of %u" msgstr "файл стану snapbuild \"%s\" має неправильне магічне число: %u замість %u" -#: replication/logical/snapbuild.c:1889 +#: replication/logical/snapbuild.c:1910 #, c-format msgid "snapbuild state file \"%s\" has unsupported version: %u instead of %u" msgstr "файл стану snapbuild \"%s\" має непідтримуючу версію: %u замість %u" -#: replication/logical/snapbuild.c:1930 +#: replication/logical/snapbuild.c:1951 #, c-format msgid "checksum mismatch for snapbuild state file \"%s\": is %u, should be %u" msgstr "у файлі стану snapbuild \"%s\" невідповідність контрольної суми: %u, повинно бути %u" -#: replication/logical/snapbuild.c:1998 +#: replication/logical/snapbuild.c:2019 #, c-format msgid "Logical decoding will begin using saved snapshot." msgstr "Логічне декодування почнеться зі збереженого знімку." -#: replication/logical/snapbuild.c:2105 +#: replication/logical/snapbuild.c:2126 #, c-format msgid "could not parse file name \"%s\"" msgstr "не вдалося аналізувати ім'я файлу \"%s\"" -#: replication/logical/tablesync.c:153 +#: replication/logical/tablesync.c:161 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has finished" msgstr "процес синхронізації таблиці при логічній реплікації для підписки \"%s\", таблиці \"%s\" закінчив обробку" -#: replication/logical/tablesync.c:632 +#: replication/logical/tablesync.c:641 #, c-format msgid "logical replication apply worker for subscription \"%s\" will restart so that two_phase can be enabled" msgstr "застосовуючий процес логічної реплікації для підписки \"%s\" буде перезавантажено, щоб можна було активувати two_phase" -#: replication/logical/tablesync.c:807 replication/logical/tablesync.c:949 +#: replication/logical/tablesync.c:827 replication/logical/tablesync.c:969 #, c-format msgid "could not fetch table info for table \"%s.%s\" from publisher: %s" msgstr "не вдалося отримати інформацію про таблицю \"%s.%s\" з серверу публікації: %s" -#: replication/logical/tablesync.c:814 +#: replication/logical/tablesync.c:834 #, c-format msgid "table \"%s.%s\" not found on publisher" msgstr "таблиця \"%s.%s\" не знайдена на сервері публікації" -#: replication/logical/tablesync.c:872 +#: replication/logical/tablesync.c:892 #, c-format msgid "could not fetch column list info for table \"%s.%s\" from publisher: %s" msgstr "не вдалося отримати інформацію про список стовпців для таблиці \"%s.%s\" з серверу публікації: %s" -#: replication/logical/tablesync.c:1051 +#: replication/logical/tablesync.c:1071 #, c-format msgid "could not fetch table WHERE clause info for table \"%s.%s\" from publisher: %s" msgstr "не вдалося отримати інформацію про вираз WHERE для таблиці \"%s.%s\" з серверу публікації: %s" -#: replication/logical/tablesync.c:1210 +#: replication/logical/tablesync.c:1230 #, c-format msgid "could not start initial contents copy for table \"%s.%s\": %s" msgstr "не вдалося почати копіювання початкового змісту таблиці \"%s.%s\": %s" -#: replication/logical/tablesync.c:1411 +#: replication/logical/tablesync.c:1429 #, c-format msgid "table copy could not start transaction on publisher: %s" msgstr "копії таблиці не вдалося запустити транзакцію на сервері публікації: %s" -#: replication/logical/tablesync.c:1453 +#: replication/logical/tablesync.c:1472 #, c-format msgid "replication origin \"%s\" already exists" msgstr "джерело реплікації \"%s\" вже існує" -#: replication/logical/tablesync.c:1486 replication/logical/worker.c:2374 +#: replication/logical/tablesync.c:1505 replication/logical/worker.c:2361 #, c-format msgid "user \"%s\" cannot replicate into relation with row-level security enabled: \"%s\"" msgstr "користувач \"%s\" не може реплікувати у відношення з увімкненим захистом на рівні рядків: \"%s\"" -#: replication/logical/tablesync.c:1499 +#: replication/logical/tablesync.c:1518 #, c-format msgid "table copy could not finish transaction on publisher: %s" msgstr "копії таблиці не вдалося завершити транзакцію на сервері публікації: %s" -#: replication/logical/worker.c:499 +#: replication/logical/worker.c:481 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop" msgstr "застосовуючий процес логічної реплікації для підписки \"%s\" буде зупинено" -#: replication/logical/worker.c:501 +#: replication/logical/worker.c:483 #, c-format msgid "Cannot handle streamed replication transactions using parallel apply workers until all tables have been synchronized." msgstr "Неможливо обробляти транзакції потокової реплікації з використанням паралельних застосовуючих працівників, доки не буде синхронізовано всі таблиці." -#: replication/logical/worker.c:863 replication/logical/worker.c:978 +#: replication/logical/worker.c:852 replication/logical/worker.c:967 #, c-format msgid "incorrect binary data format in logical replication column %d" msgstr "невірний формат двійкових даних в стовпці логічної реплікації %d" -#: replication/logical/worker.c:2513 +#: replication/logical/worker.c:2500 #, c-format msgid "publisher did not send replica identity column expected by the logical replication target relation \"%s.%s\"" msgstr "сервер публікації не передав стовпець ідентифікації репліки очікуваний для цільового зв'язку логічної реплікації \"%s.%s\"" -#: replication/logical/worker.c:2520 +#: replication/logical/worker.c:2507 #, c-format msgid "logical replication target relation \"%s.%s\" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL" msgstr "в цільовому зв'язку логічної реплікації \"%s.%s\" немає ні індексу REPLICA IDENTITY, ні ключа PRIMARY KEY і публіковаий зв'язок не має REPLICA IDENTITY FULL" -#: replication/logical/worker.c:3384 +#: replication/logical/worker.c:3371 #, c-format msgid "invalid logical replication message type \"??? (%d)\"" msgstr "неприпустимий тип повідомлення логічної реплікації \"??? (%d)\"" -#: replication/logical/worker.c:3556 +#: replication/logical/worker.c:3543 #, c-format msgid "data stream from publisher has ended" msgstr "потік даних з серверу публікації завершився" -#: replication/logical/worker.c:3713 +#: replication/logical/worker.c:3697 #, c-format msgid "terminating logical replication worker due to timeout" msgstr "завершення процесу логічної реплікації через тайм-аут" -#: replication/logical/worker.c:3907 +#: replication/logical/worker.c:3891 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was removed" msgstr "процес логічної реплікації для підписки \"%s\" буде зупинено, тому, що підписка була видалена" -#: replication/logical/worker.c:3920 +#: replication/logical/worker.c:3905 #, c-format msgid "logical replication worker for subscription \"%s\" will stop because the subscription was disabled" msgstr "процес логічної реплікації для підписки \"%s\" буде зупинено, тому, що підписка була вимкнута" -#: replication/logical/worker.c:3951 +#: replication/logical/worker.c:3936 #, c-format msgid "logical replication parallel apply worker for subscription \"%s\" will stop because of a parameter change" msgstr "процес, що застосовує паралельну логічну реплікацію для підписки \"%s\", буде зупинено через зміну параметру" -#: replication/logical/worker.c:3955 +#: replication/logical/worker.c:3940 #, c-format msgid "logical replication worker for subscription \"%s\" will restart because of a parameter change" msgstr "процес логічної реплікації для підписки \"%s\", буде перезавантажено через зміну параметру" +#: replication/logical/worker.c:3954 +#, c-format +msgid "logical replication parallel apply worker for subscription \"%s\" will stop because the subscription owner's superuser privileges have been revoked" +msgstr "логічна реплікація паралельного аплікатора для підписки \"%s\" буде зупинена, оскільки права суперкористувача власника підписки було відкликано" + +#: replication/logical/worker.c:3958 +#, c-format +msgid "logical replication worker for subscription \"%s\" will restart because the subscription owner's superuser privileges have been revoked" +msgstr "працівник логічної реплікації для підписки \"%s\" буде перезапущено, оскільки права суперкористувача власника підписки було відкликано" + #: replication/logical/worker.c:4478 #, c-format +msgid "subscription has no replication slot set" +msgstr "для підписки не встановлений слот реплікації" + +#: replication/logical/worker.c:4591 +#, c-format msgid "logical replication worker for subscription %u will not start because the subscription was removed during startup" msgstr "процес логічної реплікації для підписки %u не буде почато, тому, що підписка була видалена під час запуску" -#: replication/logical/worker.c:4493 +#: replication/logical/worker.c:4607 #, c-format msgid "logical replication worker for subscription \"%s\" will not start because the subscription was disabled during startup" msgstr "процес логічної реплікації для підписки \"%s\" не буде почато, тому, що підписка була вимкнута під час запуску" -#: replication/logical/worker.c:4510 +#: replication/logical/worker.c:4631 #, c-format msgid "logical replication table synchronization worker for subscription \"%s\", table \"%s\" has started" msgstr "просец синхронізації таблиці під час логічної реплікації для підписки \"%s\", таблиці \"%s\" запущений" -#: replication/logical/worker.c:4515 +#: replication/logical/worker.c:4636 #, c-format msgid "logical replication apply worker for subscription \"%s\" has started" msgstr "застосовуючий процес логічної реплікації для підписки \"%s\" запущений" -#: replication/logical/worker.c:4590 -#, c-format -msgid "subscription has no replication slot set" -msgstr "для підписки не встановлений слот реплікації" - -#: replication/logical/worker.c:4757 +#: replication/logical/worker.c:4758 #, c-format msgid "subscription \"%s\" has been disabled because of an error" msgstr "підписка \"%s\" була відключена через помилку" -#: replication/logical/worker.c:4805 +#: replication/logical/worker.c:4806 #, c-format msgid "logical replication starts skipping transaction at LSN %X/%X" msgstr "логічна реплікація починає пропускати транзакцію в LSN %X/%X" -#: replication/logical/worker.c:4819 +#: replication/logical/worker.c:4820 #, c-format msgid "logical replication completed skipping transaction at LSN %X/%X" msgstr "логічна реплікація завершила пропускати транзакцію в LSN %X/%X" -#: replication/logical/worker.c:4901 +#: replication/logical/worker.c:4902 #, c-format msgid "skip-LSN of subscription \"%s\" cleared" msgstr "очищено LSN пропуску підписки \"%s\"" -#: replication/logical/worker.c:4902 +#: replication/logical/worker.c:4903 #, c-format msgid "Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X." msgstr "Кінцеве розташування WAL віддаленої транзакції (LSN) %X/%X не відповідає skip-LSN %X/%X." -#: replication/logical/worker.c:4928 +#: replication/logical/worker.c:4940 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\"" msgstr "обробка віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\"" -#: replication/logical/worker.c:4932 +#: replication/logical/worker.c:4944 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u" msgstr "обробка віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" у транзакції %u" -#: replication/logical/worker.c:4937 +#: replication/logical/worker.c:4949 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X" msgstr "обробку віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" у транзакції %u завершено о %X/%X" -#: replication/logical/worker.c:4948 +#: replication/logical/worker.c:4960 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u" msgstr "обробка віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" для цільового відношення реплікації \"%s.%s\" в транзакції %u" -#: replication/logical/worker.c:4955 +#: replication/logical/worker.c:4967 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X" msgstr "обробку віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" для цільового відношення реплікації \"%s.%s\" в транзакції %u завершено о %X/%X" -#: replication/logical/worker.c:4966 +#: replication/logical/worker.c:4978 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u" msgstr "обробка віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" для цільового відношення реплікації \"%s.%s\" стовпчик \"%s\" у транзакції %u" -#: replication/logical/worker.c:4974 +#: replication/logical/worker.c:4986 #, c-format msgid "processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X" msgstr "обробку віддалених даних для джерела реплікації \"%s\" під час повідомлення типу \"%s\" для цільового відношення реплікації \"%s.%s\" стовпчик \"%s\" у транзакції %u завершено о %X/%X" -#: replication/pgoutput/pgoutput.c:317 +#: replication/pgoutput/pgoutput.c:315 #, c-format msgid "invalid proto_version" msgstr "неприпустиме значення proto_version" -#: replication/pgoutput/pgoutput.c:322 +#: replication/pgoutput/pgoutput.c:320 #, c-format msgid "proto_version \"%s\" out of range" msgstr "значення proto_version \"%s\" за межами діапазону" -#: replication/pgoutput/pgoutput.c:339 +#: replication/pgoutput/pgoutput.c:337 #, c-format msgid "invalid publication_names syntax" msgstr "неприпустимий синтаксис publication_names" -#: replication/pgoutput/pgoutput.c:440 +#: replication/pgoutput/pgoutput.c:407 replication/pgoutput/pgoutput.c:411 #, c-format -msgid "client sent proto_version=%d but server only supports protocol %d or lower" -msgstr "клієнт передав proto_version=%d, але сервер підтримує лише протокол %d або нижче" +msgid "option \"%s\" missing" +msgstr "параметр \"%s\" відсутній" -#: replication/pgoutput/pgoutput.c:446 +#: replication/pgoutput/pgoutput.c:452 #, c-format -msgid "client sent proto_version=%d but server only supports protocol %d or higher" -msgstr "клієнт передав proto_version=%d, але сервер підтримує лише протокол %d або вище" +msgid "client sent proto_version=%d but server only supports protocol %d or lower" +msgstr "клієнт передав proto_version=%d, але сервер підтримує лише протокол %d або нижче" -#: replication/pgoutput/pgoutput.c:452 +#: replication/pgoutput/pgoutput.c:458 #, c-format -msgid "publication_names parameter missing" -msgstr "пропущено параметр publication_names" +msgid "client sent proto_version=%d but server only supports protocol %d or higher" +msgstr "клієнт передав proto_version=%d, але сервер підтримує лише протокол %d або вище" -#: replication/pgoutput/pgoutput.c:466 +#: replication/pgoutput/pgoutput.c:473 #, c-format msgid "requested proto_version=%d does not support streaming, need %d or higher" msgstr "запитувана proto_version=%d не підтримує потокову передачу, потребується %d або вища" -#: replication/pgoutput/pgoutput.c:472 +#: replication/pgoutput/pgoutput.c:479 #, c-format msgid "requested proto_version=%d does not support parallel streaming, need %d or higher" msgstr "запитувана proto_version=%d не підтримує паралельний потік, потрібно %d або вище" -#: replication/pgoutput/pgoutput.c:477 +#: replication/pgoutput/pgoutput.c:484 #, c-format msgid "streaming requested, but not supported by output plugin" msgstr "запитане потокова передавача, але не підтримується плагіном виводу" -#: replication/pgoutput/pgoutput.c:494 +#: replication/pgoutput/pgoutput.c:498 #, c-format msgid "requested proto_version=%d does not support two-phase commit, need %d or higher" msgstr "запитувана proto_version=%d не підтримує двоетапне затвердження, потрібна %d або вища" -#: replication/pgoutput/pgoutput.c:499 +#: replication/pgoutput/pgoutput.c:503 #, c-format msgid "two-phase commit requested, but not supported by output plugin" msgstr "запитано двоетапне затвердження, але не підтримується плагіном виводу" -#: replication/slot.c:207 +#: replication/slot.c:260 #, c-format msgid "replication slot name \"%s\" is too short" msgstr "ім'я слоту реплікації \"%s\" занадто коротке" -#: replication/slot.c:216 +#: replication/slot.c:269 #, c-format msgid "replication slot name \"%s\" is too long" msgstr "ім'я слоту реплікації \"%s\" занадто довге" -#: replication/slot.c:229 +#: replication/slot.c:282 #, c-format msgid "replication slot name \"%s\" contains invalid character" msgstr "ім'я слоту реплікації \"%s\" містить неприпустимий символ" -#: replication/slot.c:231 +#: replication/slot.c:284 #, c-format msgid "Replication slot names may only contain lower case letters, numbers, and the underscore character." msgstr "Імена слота реплікації можуть містити лише букви в нижньому кейсі, числа, і символ підкреслення." -#: replication/slot.c:285 +#: replication/slot.c:333 +#, c-format +msgid "cannot enable failover for a replication slot created on the standby" +msgstr "не вдається увімкнути відмовостійкість для слота реплікації, створеного в режимі очікування" + +#: replication/slot.c:345 replication/slot.c:849 +#, c-format +msgid "cannot enable failover for a temporary replication slot" +msgstr "не вдається увімкнути відмовостійкість для тимчасового слота реплікації" + +#: replication/slot.c:370 #, c-format msgid "replication slot \"%s\" already exists" msgstr "слот реплікації \"%s\" вже існує" -#: replication/slot.c:295 +#: replication/slot.c:380 #, c-format msgid "all replication slots are in use" msgstr "використовуються всі слоти реплікації" -#: replication/slot.c:296 +#: replication/slot.c:381 #, c-format -msgid "Free one or increase max_replication_slots." -msgstr "Звільніть непотрібні або збільшіть max_replication_slots." +msgid "Free one or increase \"max_replication_slots\"." +msgstr "Звільніть непотрібні або збільшіть \"max_replication_slots\"." -#: replication/slot.c:474 replication/slotfuncs.c:736 -#: utils/activity/pgstat_replslot.c:55 utils/adt/genfile.c:774 +#: replication/slot.c:560 replication/slot.c:2453 replication/slotfuncs.c:661 +#: utils/activity/pgstat_replslot.c:56 utils/adt/genfile.c:728 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "слот реплікації \"%s\" не існує" -#: replication/slot.c:520 replication/slot.c:1110 +#: replication/slot.c:606 replication/slot.c:1337 #, c-format msgid "replication slot \"%s\" is active for PID %d" msgstr "слот реплікації \"%s\" активний для PID %d" -#: replication/slot.c:756 replication/slot.c:1645 replication/slot.c:2028 +#: replication/slot.c:638 +#, c-format +msgid "acquired logical replication slot \"%s\"" +msgstr "придбано слот логічної реплікації \"%s\"" + +#: replication/slot.c:640 +#, c-format +msgid "acquired physical replication slot \"%s\"" +msgstr "придбано фізичний слот реплікації \"%s\"" + +#: replication/slot.c:729 +#, c-format +msgid "released logical replication slot \"%s\"" +msgstr "звільнено слот логічної реплікації \"%s\"" + +#: replication/slot.c:731 +#, c-format +msgid "released physical replication slot \"%s\"" +msgstr "звільнено фізичний слот реплікації \"%s\"" + +#: replication/slot.c:797 +#, c-format +msgid "cannot drop replication slot \"%s\"" +msgstr "не може скинути слот реплікації \"%s\"" + +#: replication/slot.c:816 +#, c-format +msgid "cannot use %s with a physical replication slot" +msgstr "не може використовувати %s з фізичним слотом реплікації" + +#: replication/slot.c:828 +#, c-format +msgid "cannot alter replication slot \"%s\"" +msgstr "не може змінювати слот реплікації \"%s\"" + +#: replication/slot.c:838 +#, c-format +msgid "cannot enable failover for a replication slot on the standby" +msgstr "не вдається увімкнути обхід відмови для слота реплікації в режимі очікування" + +#: replication/slot.c:969 replication/slot.c:1927 replication/slot.c:2311 #, c-format msgid "could not remove directory \"%s\"" msgstr "не вдалося видалити каталог \"%s\"" -#: replication/slot.c:1145 +#: replication/slot.c:1372 #, c-format -msgid "replication slots can only be used if max_replication_slots > 0" -msgstr "слоти реплікації можна використовувати лише якщо max_replication_slots > 0" +msgid "replication slots can only be used if \"max_replication_slots\" > 0" +msgstr "слоти реплікації можна використовувати лише якщо \"max_replication_slots\" > 0" -#: replication/slot.c:1150 +#: replication/slot.c:1377 #, c-format -msgid "replication slots can only be used if wal_level >= replica" -msgstr "слоти реплікації можна використовувати лише якщо wal_level >= replica" +msgid "replication slots can only be used if \"wal_level\" >= \"replica\"" +msgstr "слоти реплікації можна використовувати лише якщо \"wal_level\" >= \"replica\"" -#: replication/slot.c:1162 +#: replication/slot.c:1389 #, c-format msgid "permission denied to use replication slots" msgstr "немає дозволу для використання слотів реплікації" -#: replication/slot.c:1163 +#: replication/slot.c:1390 #, c-format msgid "Only roles with the %s attribute may use replication slots." msgstr "Тільки ролі з атрибутом %s можуть використовувати слоти реплікації." -#: replication/slot.c:1271 +#: replication/slot.c:1498 #, c-format msgid "The slot's restart_lsn %X/%X exceeds the limit by %llu byte." msgid_plural "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes." @@ -20464,575 +21069,640 @@ msgstr[1] "Значення restart_lsn слота %X/%X перевищує лі msgstr[2] "Значення restart_lsn слота %X/%X перевищує ліміт на %llu байтів." msgstr[3] "Значення restart_lsn слота %X/%X перевищує ліміт на %llu байтів." -#: replication/slot.c:1279 +#: replication/slot.c:1506 #, c-format msgid "The slot conflicted with xid horizon %u." msgstr "Слот конфліктував з горизонтом xid %u." -#: replication/slot.c:1284 -msgid "Logical decoding on standby requires wal_level >= logical on the primary server." -msgstr "Логічне декодування на standby вимагає wal_level >= logical на основному сервері." +#: replication/slot.c:1511 +msgid "Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server." +msgstr "Логічне декодування на резервному сервері вимагає \"wal_level\" >= \"logical\" на основному сервері." -#: replication/slot.c:1292 +#: replication/slot.c:1519 #, c-format msgid "terminating process %d to release replication slot \"%s\"" msgstr "завершення процесу %d для звільнення слоту реплікації \"%s\"" -#: replication/slot.c:1294 +#: replication/slot.c:1521 #, c-format msgid "invalidating obsolete replication slot \"%s\"" msgstr "анулювання застарілого слоту реплікації \"%s\"" -#: replication/slot.c:1966 +#: replication/slot.c:2249 #, c-format msgid "replication slot file \"%s\" has wrong magic number: %u instead of %u" msgstr "файл слоту реплікації \"%s\" має неправильне магічне число: %u замість %u" -#: replication/slot.c:1973 +#: replication/slot.c:2256 #, c-format msgid "replication slot file \"%s\" has unsupported version %u" msgstr "файл слоту реплікації \"%s\" має непідтримуючу версію %u" -#: replication/slot.c:1980 +#: replication/slot.c:2263 #, c-format msgid "replication slot file \"%s\" has corrupted length %u" msgstr "файл слоту реплікації \"%s\" має пошкоджену довжину %u" -#: replication/slot.c:2016 +#: replication/slot.c:2299 #, c-format msgid "checksum mismatch for replication slot file \"%s\": is %u, should be %u" msgstr "у файлі слоту реплікації \"%s\" невідповідність контрольної суми: %u, повинно бути %u" -#: replication/slot.c:2050 +#: replication/slot.c:2333 #, c-format -msgid "logical replication slot \"%s\" exists, but wal_level < logical" -msgstr "слот логічної реплікації \"%s\" існує, але wal_level < logical" +msgid "logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"" +msgstr "слот логічної реплікації \"%s\" існує, але \"wal_level\" < \"logical\"" -#: replication/slot.c:2052 +#: replication/slot.c:2335 #, c-format -msgid "Change wal_level to be logical or higher." -msgstr "Змініть wal_level на logical або вище." +msgid "Change \"wal_level\" to be \"logical\" or higher." +msgstr "Змініть \"wal_level\" на \"logical\" або вище." -#: replication/slot.c:2056 +#: replication/slot.c:2339 #, c-format -msgid "physical replication slot \"%s\" exists, but wal_level < replica" -msgstr "слот фізичної реплікації \"%s\" існує, але wal_level < replica" +msgid "physical replication slot \"%s\" exists, but \"wal_level\" < \"replica\"" +msgstr "слот фізичної реплікації \"%s\" існує, але \"wal_level\" < \"replica\"" -#: replication/slot.c:2058 +#: replication/slot.c:2341 #, c-format -msgid "Change wal_level to be replica or higher." -msgstr "Змініть wal_level на replica або вище." +msgid "Change \"wal_level\" to be \"replica\" or higher." +msgstr "Змініть \"wal_level\" на \"replica\" або вище." -#: replication/slot.c:2092 +#: replication/slot.c:2383 #, c-format msgid "too many replication slots active before shutdown" msgstr "перед завершенням роботи активно занадто багато слотів реплікації" -#: replication/slotfuncs.c:601 +#: replication/slot.c:2461 +#, c-format +msgid "\"%s\" is not a physical replication slot" +msgstr "\"%s\" не є фізичним слотом реплікації" + +#: replication/slot.c:2638 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not exist" +msgstr "слот реплікації \"%s\", вказаний в параметрі \"%s\", не існує" + +#: replication/slot.c:2640 replication/slot.c:2681 replication/slot.c:2696 +#, c-format +msgid "Logical replication is waiting on the standby associated with replication slot \"%s\"." +msgstr "Логічна реплікація чекає на слоті реплікації, що пов'язана з слотом реплікації \"%s\"." + +#: replication/slot.c:2642 +#, c-format +msgid "Create the replication slot \"%s\" or amend parameter \"%s\"." +msgstr "Створіть слот реплікації \"%s\" або змініть параметр \"%s\"." + +#: replication/slot.c:2659 +#, c-format +msgid "cannot specify logical replication slot \"%s\" in parameter \"%s\"" +msgstr "неможливо вказати слот логічної реплікації \"%s\" в параметрі \"%s\"" + +#: replication/slot.c:2661 +#, c-format +msgid "Logical replication is waiting for correction on replication slot \"%s\"." +msgstr "Логічна реплікація очікує на корекцію на слоті реплікації \"%s\"." + +#: replication/slot.c:2663 +#, c-format +msgid "Remove the logical replication slot \"%s\" from parameter \"%s\"." +msgstr "Приберіть слот логічної реплікації \"%s\" з параметру \"%s\"." + +#: replication/slot.c:2679 +#, c-format +msgid "physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated" +msgstr "" + +#: replication/slot.c:2683 +#, c-format +msgid "Drop and recreate the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "" + +#: replication/slot.c:2694 +#, c-format +msgid "replication slot \"%s\" specified in parameter \"%s\" does not have active_pid" +msgstr "" + +#: replication/slot.c:2698 +#, c-format +msgid "Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\"." +msgstr "" + +#: replication/slotfuncs.c:526 #, c-format msgid "invalid target WAL LSN" msgstr "неприпустима ціль WAL LSN" -#: replication/slotfuncs.c:623 +#: replication/slotfuncs.c:548 #, c-format msgid "replication slot \"%s\" cannot be advanced" msgstr "слот реплікації \"%s\" не може бути розширеним" -#: replication/slotfuncs.c:625 +#: replication/slotfuncs.c:550 #, c-format msgid "This slot has never previously reserved WAL, or it has been invalidated." msgstr "Цей слот ніколи раніше не резервував WAL, або він був недійсним." -#: replication/slotfuncs.c:641 +#: replication/slotfuncs.c:566 #, c-format msgid "cannot advance replication slot to %X/%X, minimum is %X/%X" msgstr "просунути слот реплікації до позиції %X/%X не можна, мінімальна позиція %X/%X" -#: replication/slotfuncs.c:748 +#: replication/slotfuncs.c:673 #, c-format msgid "cannot copy physical replication slot \"%s\" as a logical replication slot" msgstr "не можна скопіювати слот фізичної реплікації \"%s\" як слот логічної реплікації" -#: replication/slotfuncs.c:750 +#: replication/slotfuncs.c:675 #, c-format msgid "cannot copy logical replication slot \"%s\" as a physical replication slot" msgstr "не можна скопіювати слот логічної реплікації \"%s\" як слот фізичної реплікації" -#: replication/slotfuncs.c:757 +#: replication/slotfuncs.c:682 #, c-format msgid "cannot copy a replication slot that doesn't reserve WAL" msgstr "не можна скопіювати слот реплікації, який не резервує WAL" -#: replication/slotfuncs.c:834 +#: replication/slotfuncs.c:768 #, c-format msgid "could not copy replication slot \"%s\"" msgstr "не вдалося скопіювати слот реплікації \"%s\"" -#: replication/slotfuncs.c:836 +#: replication/slotfuncs.c:770 #, c-format msgid "The source replication slot was modified incompatibly during the copy operation." msgstr "Слот реплікації джерела був змінений несумісно під час операції копіювання." -#: replication/slotfuncs.c:842 +#: replication/slotfuncs.c:776 #, c-format msgid "cannot copy unfinished logical replication slot \"%s\"" msgstr "не можна скопіювати незавершений слот логічної реплікації \"%s\"" -#: replication/slotfuncs.c:844 +#: replication/slotfuncs.c:778 #, c-format msgid "Retry when the source replication slot's confirmed_flush_lsn is valid." msgstr "Повторіть, коли confirmed_flush_lsn слоту джерела реплікації є дійсним." -#: replication/syncrep.c:262 +#: replication/slotfuncs.c:877 +#, c-format +msgid "replication slots can only be synchronized to a standby server" +msgstr "слоти реплікації можна синхронізувати лише з резервним сервером" + +#: replication/syncrep.c:261 #, c-format msgid "canceling the wait for synchronous replication and terminating connection due to administrator command" msgstr "скасування очікування синхронної реплікації і завершення з'єднання по команді адміністратора" -#: replication/syncrep.c:263 replication/syncrep.c:280 +#: replication/syncrep.c:262 replication/syncrep.c:279 #, c-format msgid "The transaction has already committed locally, but might not have been replicated to the standby." msgstr "Транзакція вже була затверджена локально, але можливо не була реплікована до режиму очікування." -#: replication/syncrep.c:279 +#: replication/syncrep.c:278 #, c-format msgid "canceling wait for synchronous replication due to user request" msgstr "скасування очікування синхронної реплікації по запиту користувача" -#: replication/syncrep.c:486 +#: replication/syncrep.c:485 #, c-format -msgid "standby \"%s\" is now a synchronous standby with priority %u" -msgstr "режим очікування \"%s\" зараз є синхронним з пріоритетом %u" +msgid "standby \"%s\" is now a synchronous standby with priority %d" +msgstr "очікування \"%s\" тепер є синхронним очікуванням з пріоритетом %d" -#: replication/syncrep.c:490 +#: replication/syncrep.c:489 #, c-format msgid "standby \"%s\" is now a candidate for quorum synchronous standby" msgstr "режим очікування \"%s\" зараз є кандидатом для включення в кворум синхронних" -#: replication/syncrep.c:1019 +#: replication/syncrep.c:1013 #, c-format -msgid "synchronous_standby_names parser failed" -msgstr "помилка при аналізуванні synchronous_standby_names" +msgid "\"synchronous_standby_names\" parser failed" +msgstr "" -#: replication/syncrep.c:1025 +#: replication/syncrep.c:1019 #, c-format msgid "number of synchronous standbys (%d) must be greater than zero" msgstr "кількість синхронних режимів очікування (%d) повинно бути більше нуля" -#: replication/walreceiver.c:180 +#: replication/walreceiver.c:176 #, c-format msgid "terminating walreceiver process due to administrator command" msgstr "завершення процесу walreceiver по команді адміністратора" -#: replication/walreceiver.c:305 -#, c-format -msgid "could not connect to the primary server: %s" -msgstr "не вдалося підключитися до основного серверу: %s" - -#: replication/walreceiver.c:352 +#: replication/walreceiver.c:354 #, c-format msgid "database system identifier differs between the primary and standby" msgstr "ідентифікатор системи бази даних на основному і резервному серверах відрізняються" -#: replication/walreceiver.c:353 +#: replication/walreceiver.c:355 #, c-format msgid "The primary's identifier is %s, the standby's identifier is %s." msgstr "Ідентифікатор на основному сервері %s, на резервному %s." -#: replication/walreceiver.c:364 +#: replication/walreceiver.c:366 #, c-format msgid "highest timeline %u of the primary is behind recovery timeline %u" msgstr "остання часова шкала %u на основному сервері відстає від відновлюючої часової шкали %u" -#: replication/walreceiver.c:417 +#: replication/walreceiver.c:419 #, c-format msgid "started streaming WAL from primary at %X/%X on timeline %u" msgstr "запущено потокове передавання WAL з основного серверу з позиції %X/%X на часовій шкалі %u" -#: replication/walreceiver.c:421 +#: replication/walreceiver.c:423 #, c-format msgid "restarted WAL streaming at %X/%X on timeline %u" msgstr "перезапуска потокового передавання WAL з позиції %X/%X на часовій шкалі %u" -#: replication/walreceiver.c:457 +#: replication/walreceiver.c:458 #, c-format msgid "cannot continue WAL streaming, recovery has already ended" msgstr "продовжити потокове передавання WAL не можна, відновлення вже завершено" -#: replication/walreceiver.c:501 +#: replication/walreceiver.c:502 #, c-format msgid "replication terminated by primary server" msgstr "реплікація завершена основним сервером" -#: replication/walreceiver.c:502 +#: replication/walreceiver.c:503 #, c-format msgid "End of WAL reached on timeline %u at %X/%X." msgstr "На часовій шкалі %u в позиції %X/%X WAL досяг кінця." -#: replication/walreceiver.c:592 +#: replication/walreceiver.c:593 #, c-format msgid "terminating walreceiver due to timeout" msgstr "завершення процесу walreceiver через тайм-аут" -#: replication/walreceiver.c:624 +#: replication/walreceiver.c:625 #, c-format msgid "primary server contains no more WAL on requested timeline %u" msgstr "основний сервер більше не містить WAL для запитаної часової шкали %u" -#: replication/walreceiver.c:640 replication/walreceiver.c:1066 +#: replication/walreceiver.c:641 replication/walreceiver.c:1071 #, c-format msgid "could not close WAL segment %s: %m" msgstr "не вдалося закрити сегмент WAL %s: %m" -#: replication/walreceiver.c:759 +#: replication/walreceiver.c:760 #, c-format msgid "fetching timeline history file for timeline %u from primary server" msgstr "отримання файлу історії часової шкали для часової шкали %u з основного серверу" -#: replication/walreceiver.c:954 +#: replication/walreceiver.c:959 #, c-format -msgid "could not write to WAL segment %s at offset %u, length %lu: %m" -msgstr "не вдалося записати в сегмент WAL %s зсув %u, довжина %lu: %m" +msgid "could not write to WAL segment %s at offset %d, length %lu: %m" +msgstr "не вдалося записати у сегмент WAL %s зі зміщенням %d, довжиною %lu: %m" -#: replication/walsender.c:519 +#: replication/walsender.c:531 #, c-format msgid "cannot use %s with a logical replication slot" msgstr "використовувати %s зі слотом логічної реплікації не можна" -#: replication/walsender.c:623 storage/smgr/md.c:1529 +#: replication/walsender.c:635 storage/smgr/md.c:1723 #, c-format msgid "could not seek to end of file \"%s\": %m" msgstr "не вдалося досягти кінця файлу \"%s\": %m" -#: replication/walsender.c:627 +#: replication/walsender.c:639 #, c-format msgid "could not seek to beginning of file \"%s\": %m" msgstr "не вдалося знайти початок файлу \"%s\": %m" -#: replication/walsender.c:704 +#: replication/walsender.c:853 #, c-format msgid "cannot use a logical replication slot for physical replication" msgstr "використовувати логічний слот реплікації для фізичної реплікації, не можна" -#: replication/walsender.c:770 +#: replication/walsender.c:919 #, c-format msgid "requested starting point %X/%X on timeline %u is not in this server's history" msgstr "в історії серверу немає запитаної початкової точки %X/%X на часовій шкалі %u" -#: replication/walsender.c:773 +#: replication/walsender.c:922 #, c-format msgid "This server's history forked from timeline %u at %X/%X." msgstr "Історія цього серверу відгалузилась від часової шкали %u в позиції %X/%X." -#: replication/walsender.c:817 +#: replication/walsender.c:966 #, c-format msgid "requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X" msgstr "запитана початкова точка %X/%X попереду позиція очищених даних WAL на цьому сервері %X/%X" -#: replication/walsender.c:1010 +#: replication/walsender.c:1160 #, c-format msgid "unrecognized value for CREATE_REPLICATION_SLOT option \"%s\": \"%s\"" msgstr "нерозпізнане значення для параметру CREATE_REPLICATION_SLOT \"%s\": \"%s\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1095 +#: replication/walsender.c:1266 #, c-format msgid "%s must not be called inside a transaction" msgstr "%s не має викликатися всередині транзакції" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1105 +#: replication/walsender.c:1276 #, c-format msgid "%s must be called inside a transaction" msgstr "%s має викликатися всередині транзакції" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1111 +#: replication/walsender.c:1282 #, c-format msgid "%s must be called in REPEATABLE READ isolation mode transaction" msgstr "%s повинен бути викликаний в режимі ізоляції REPEATABLE READ" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1116 +#: replication/walsender.c:1287 #, c-format msgid "%s must be called in a read-only transaction" msgstr "%s має викликатися в транзакції \"лише для читання\"" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1122 +#: replication/walsender.c:1293 #, c-format msgid "%s must be called before any query" msgstr "%s має викликатися до будь-якого запиту" #. translator: %s is a CREATE_REPLICATION_SLOT statement -#: replication/walsender.c:1128 +#: replication/walsender.c:1299 #, c-format msgid "%s must not be called in a subtransaction" msgstr "%s не має викликатися всередині підтранзакції" -#: replication/walsender.c:1275 +#: replication/walsender.c:1472 #, c-format msgid "terminating walsender process after promotion" msgstr "завершення процесу walsender після підвищення" -#: replication/walsender.c:1696 +#: replication/walsender.c:2000 #, c-format msgid "cannot execute new commands while WAL sender is in stopping mode" msgstr "не можна виконувати нові команди, поки процес відправки WAL знаходиться в режимі зупинки" -#: replication/walsender.c:1731 +#: replication/walsender.c:2035 #, c-format msgid "cannot execute SQL commands in WAL sender for physical replication" msgstr "не можна виконувати команди SQL в процесі відправки WAL для фізичної реплікації" -#: replication/walsender.c:1764 +#: replication/walsender.c:2068 #, c-format msgid "received replication command: %s" msgstr "отримано команду реплікації: %s" -#: replication/walsender.c:1772 tcop/fastpath.c:209 tcop/postgres.c:1138 -#: tcop/postgres.c:1496 tcop/postgres.c:1736 tcop/postgres.c:2210 -#: tcop/postgres.c:2648 tcop/postgres.c:2726 +#: replication/walsender.c:2076 tcop/fastpath.c:209 tcop/postgres.c:1142 +#: tcop/postgres.c:1500 tcop/postgres.c:1752 tcop/postgres.c:2234 +#: tcop/postgres.c:2672 tcop/postgres.c:2749 #, c-format msgid "current transaction is aborted, commands ignored until end of transaction block" msgstr "поточна транзакція перервана, команди до кінця блока транзакції пропускаються" -#: replication/walsender.c:1914 replication/walsender.c:1949 +#: replication/walsender.c:2233 replication/walsender.c:2268 #, c-format msgid "unexpected EOF on standby connection" msgstr "неочікуваний обрив з'єднання з резервним сервером" -#: replication/walsender.c:1937 +#: replication/walsender.c:2256 #, c-format msgid "invalid standby message type \"%c\"" msgstr "неприпустимий тип повідомлення резервного серверу \"%c\"" -#: replication/walsender.c:2026 +#: replication/walsender.c:2345 #, c-format msgid "unexpected message type \"%c\"" msgstr "неочікуваний тип повідомлення \"%c\"" -#: replication/walsender.c:2439 +#: replication/walsender.c:2759 #, c-format msgid "terminating walsender process due to replication timeout" msgstr "завершення процесу walsender через тайм-аут реплікації" -#: rewrite/rewriteDefine.c:111 rewrite/rewriteDefine.c:842 +#: rewrite/rewriteDefine.c:104 rewrite/rewriteDefine.c:835 #, c-format msgid "rule \"%s\" for relation \"%s\" already exists" msgstr "правило \"%s\" для зв'язка \"%s\" вже існує" -#: rewrite/rewriteDefine.c:268 rewrite/rewriteDefine.c:780 +#: rewrite/rewriteDefine.c:261 rewrite/rewriteDefine.c:773 #, c-format msgid "relation \"%s\" cannot have rules" msgstr "відношення \"%s\" не може мати правил" -#: rewrite/rewriteDefine.c:299 +#: rewrite/rewriteDefine.c:292 #, c-format msgid "rule actions on OLD are not implemented" msgstr "дії правил для OLD не реалізовані" -#: rewrite/rewriteDefine.c:300 +#: rewrite/rewriteDefine.c:293 #, c-format msgid "Use views or triggers instead." msgstr "Використайте подання або тригери замість." -#: rewrite/rewriteDefine.c:304 +#: rewrite/rewriteDefine.c:297 #, c-format msgid "rule actions on NEW are not implemented" msgstr "дії правил для NEW не реалізовані" -#: rewrite/rewriteDefine.c:305 +#: rewrite/rewriteDefine.c:298 #, c-format msgid "Use triggers instead." msgstr "Використайте тригери замість." -#: rewrite/rewriteDefine.c:319 +#: rewrite/rewriteDefine.c:312 #, c-format msgid "relation \"%s\" cannot have ON SELECT rules" msgstr "відношення \"%s\" не може мати правил ON SELECT" -#: rewrite/rewriteDefine.c:329 +#: rewrite/rewriteDefine.c:322 #, c-format msgid "INSTEAD NOTHING rules on SELECT are not implemented" msgstr "Правила INSTEAD NOTHING для SELECT не реалізовані" -#: rewrite/rewriteDefine.c:330 +#: rewrite/rewriteDefine.c:323 #, c-format msgid "Use views instead." msgstr "Використайте подання замість." -#: rewrite/rewriteDefine.c:338 +#: rewrite/rewriteDefine.c:331 #, c-format msgid "multiple actions for rules on SELECT are not implemented" msgstr "декілька дій в правилах для SELECT не реалізовані" -#: rewrite/rewriteDefine.c:348 +#: rewrite/rewriteDefine.c:341 #, c-format msgid "rules on SELECT must have action INSTEAD SELECT" msgstr "правила для SELECT повинні мати дію INSTEAD SELECT" -#: rewrite/rewriteDefine.c:356 +#: rewrite/rewriteDefine.c:349 #, c-format msgid "rules on SELECT must not contain data-modifying statements in WITH" msgstr "правила для SELECT не повинні містити операторів, які змінюють дані в WITH" -#: rewrite/rewriteDefine.c:364 +#: rewrite/rewriteDefine.c:357 #, c-format msgid "event qualifications are not implemented for rules on SELECT" msgstr "в правилах для SELECT не може бути умов" -#: rewrite/rewriteDefine.c:391 +#: rewrite/rewriteDefine.c:384 #, c-format msgid "\"%s\" is already a view" msgstr "\"%s\" вже є поданням" -#: rewrite/rewriteDefine.c:415 +#: rewrite/rewriteDefine.c:408 #, c-format msgid "view rule for \"%s\" must be named \"%s\"" msgstr "правило подання для \"%s\" повинно називатися \"%s\"" -#: rewrite/rewriteDefine.c:442 +#: rewrite/rewriteDefine.c:435 #, c-format msgid "cannot have multiple RETURNING lists in a rule" msgstr "правило не може мати декілька списків RETURNING" -#: rewrite/rewriteDefine.c:447 +#: rewrite/rewriteDefine.c:440 #, c-format msgid "RETURNING lists are not supported in conditional rules" msgstr "Умовні правила не підтримують списки RETURNING" -#: rewrite/rewriteDefine.c:451 +#: rewrite/rewriteDefine.c:444 #, c-format msgid "RETURNING lists are not supported in non-INSTEAD rules" msgstr "Правила non-INSTEAD не підтримують списки RETURNING" -#: rewrite/rewriteDefine.c:465 +#: rewrite/rewriteDefine.c:458 #, c-format msgid "non-view rule for \"%s\" must not be named \"%s\"" msgstr "правило не-подання для \"%s\" не повинно мати назву \"%s\"" -#: rewrite/rewriteDefine.c:539 +#: rewrite/rewriteDefine.c:532 #, c-format msgid "SELECT rule's target list has too many entries" msgstr "Список цілей правила для SELECT має занадто багато елементів" -#: rewrite/rewriteDefine.c:540 +#: rewrite/rewriteDefine.c:533 #, c-format msgid "RETURNING list has too many entries" msgstr "Список RETURNING має занадто багато елементів" -#: rewrite/rewriteDefine.c:567 +#: rewrite/rewriteDefine.c:560 #, c-format msgid "cannot convert relation containing dropped columns to view" msgstr "перетворити зв'язок, який містить видаленні стовпці, на подання не можна" -#: rewrite/rewriteDefine.c:568 +#: rewrite/rewriteDefine.c:561 #, c-format msgid "cannot create a RETURNING list for a relation containing dropped columns" msgstr "створити список RETURNING для зв'язка, який містить видаленні стовпці, не можна" -#: rewrite/rewriteDefine.c:574 +#: rewrite/rewriteDefine.c:567 #, c-format msgid "SELECT rule's target entry %d has different column name from column \"%s\"" msgstr "Елемент результата правила для SELECT %d відрізняється іменем стовпця від стовпця \"%s\"" -#: rewrite/rewriteDefine.c:576 +#: rewrite/rewriteDefine.c:569 #, c-format msgid "SELECT target entry is named \"%s\"." msgstr "Ім'я елемента результату SELECT \"%s\"." -#: rewrite/rewriteDefine.c:585 +#: rewrite/rewriteDefine.c:578 #, c-format msgid "SELECT rule's target entry %d has different type from column \"%s\"" msgstr "Елемент результата правила для SELECT %d відрізняється типом від стовпця \"%s\"" -#: rewrite/rewriteDefine.c:587 +#: rewrite/rewriteDefine.c:580 #, c-format msgid "RETURNING list's entry %d has different type from column \"%s\"" msgstr "Елемент списку RETURNING %d відрізняється типом від стовпця \"%s\"" -#: rewrite/rewriteDefine.c:590 rewrite/rewriteDefine.c:614 +#: rewrite/rewriteDefine.c:583 rewrite/rewriteDefine.c:607 #, c-format msgid "SELECT target entry has type %s, but column has type %s." msgstr "Елемент результату SELECT має тип %s, але стовпець має тип %s." -#: rewrite/rewriteDefine.c:593 rewrite/rewriteDefine.c:618 +#: rewrite/rewriteDefine.c:586 rewrite/rewriteDefine.c:611 #, c-format msgid "RETURNING list entry has type %s, but column has type %s." msgstr "Елемент списку RETURNING має тип %s, але стовпець має тип %s." -#: rewrite/rewriteDefine.c:609 +#: rewrite/rewriteDefine.c:602 #, c-format msgid "SELECT rule's target entry %d has different size from column \"%s\"" msgstr "Елемент результата правил для SELECT %d відрізняється розміром від стовпця \"%s\"" -#: rewrite/rewriteDefine.c:611 +#: rewrite/rewriteDefine.c:604 #, c-format msgid "RETURNING list's entry %d has different size from column \"%s\"" msgstr "Елемент списку RETURNING %d відрізняється розміром від стовпця \"%s\"" -#: rewrite/rewriteDefine.c:628 +#: rewrite/rewriteDefine.c:621 #, c-format msgid "SELECT rule's target list has too few entries" msgstr "Список результату правила для SELECT має занадто мало елементів" -#: rewrite/rewriteDefine.c:629 +#: rewrite/rewriteDefine.c:622 #, c-format msgid "RETURNING list has too few entries" msgstr "Список RETURNING має занадто мало елементів" -#: rewrite/rewriteDefine.c:718 rewrite/rewriteDefine.c:833 -#: rewrite/rewriteSupport.c:109 +#: rewrite/rewriteDefine.c:711 rewrite/rewriteDefine.c:826 +#: rewrite/rewriteSupport.c:108 #, c-format msgid "rule \"%s\" for relation \"%s\" does not exist" msgstr "правило \"%s\" для відношення \"%s\" не існує" -#: rewrite/rewriteDefine.c:852 +#: rewrite/rewriteDefine.c:845 #, c-format msgid "renaming an ON SELECT rule is not allowed" msgstr "не допускається перейменування правила ON SELECT" -#: rewrite/rewriteHandler.c:583 +#: rewrite/rewriteHandler.c:582 #, c-format msgid "WITH query name \"%s\" appears in both a rule action and the query being rewritten" msgstr "Ім'я запиту WITH \"%s\" з'являється і в дії правила, і в переписаному запиті" -#: rewrite/rewriteHandler.c:610 +#: rewrite/rewriteHandler.c:609 #, c-format msgid "INSERT ... SELECT rule actions are not supported for queries having data-modifying statements in WITH" msgstr "Дії правил INSERT ... SELECT не підтримуються для запитів, які змінюють дані в операторах WITH" -#: rewrite/rewriteHandler.c:663 +#: rewrite/rewriteHandler.c:662 #, c-format msgid "cannot have RETURNING lists in multiple rules" msgstr "списки RETURNING може мати лише одне правило" -#: rewrite/rewriteHandler.c:895 rewrite/rewriteHandler.c:934 +#: rewrite/rewriteHandler.c:894 rewrite/rewriteHandler.c:933 #, c-format msgid "cannot insert a non-DEFAULT value into column \"%s\"" msgstr "вставити значення non-DEFAULT до стовпця \"%s\" не можна" -#: rewrite/rewriteHandler.c:897 rewrite/rewriteHandler.c:963 +#: rewrite/rewriteHandler.c:896 rewrite/rewriteHandler.c:962 #, c-format msgid "Column \"%s\" is an identity column defined as GENERATED ALWAYS." msgstr "Стовпець \"%s\" є ідентифікаційним стовпцем визначеним як GENERATED ALWAYS." -#: rewrite/rewriteHandler.c:899 +#: rewrite/rewriteHandler.c:898 #, c-format msgid "Use OVERRIDING SYSTEM VALUE to override." msgstr "Для зміни використайте OVERRIDING SYSTEM VALUE." -#: rewrite/rewriteHandler.c:961 rewrite/rewriteHandler.c:969 +#: rewrite/rewriteHandler.c:960 rewrite/rewriteHandler.c:968 #, c-format msgid "column \"%s\" can only be updated to DEFAULT" msgstr "стовпець \"%s\" може бути оновлено тільки до DEFAULT" -#: rewrite/rewriteHandler.c:1116 rewrite/rewriteHandler.c:1134 +#: rewrite/rewriteHandler.c:1115 rewrite/rewriteHandler.c:1133 #, c-format msgid "multiple assignments to same column \"%s\"" msgstr "кілька завдань для одного стовпця \"%s\"" -#: rewrite/rewriteHandler.c:2119 rewrite/rewriteHandler.c:4040 +#: rewrite/rewriteHandler.c:1698 +#, c-format +msgid "MERGE is not supported for relations with rules." +msgstr "MERGE не підтримує відношення з правилами." + +#: rewrite/rewriteHandler.c:1738 rewrite/rewriteHandler.c:3229 +#, c-format +msgid "access to non-system view \"%s\" is restricted" +msgstr "" + +#: rewrite/rewriteHandler.c:2119 rewrite/rewriteHandler.c:4221 #, c-format msgid "infinite recursion detected in rules for relation \"%s\"" msgstr "виявлена безкінечна рекурсія у правилах для відносин \"%s\"" @@ -21042,163 +21712,226 @@ msgstr "виявлена безкінечна рекурсія у правила msgid "infinite recursion detected in policy for relation \"%s\"" msgstr "виявлена безкінечна рекурсія в політиці для зв'язка \"%s\"" -#: rewrite/rewriteHandler.c:2524 +#: rewrite/rewriteHandler.c:2556 msgid "Junk view columns are not updatable." msgstr "Утилізовані стовпці подань не оновлюються." -#: rewrite/rewriteHandler.c:2529 +#: rewrite/rewriteHandler.c:2561 msgid "View columns that are not columns of their base relation are not updatable." msgstr "Стовпці подання, які не є стовпцями базового зв'язку, не оновлюються." -#: rewrite/rewriteHandler.c:2532 +#: rewrite/rewriteHandler.c:2564 msgid "View columns that refer to system columns are not updatable." msgstr "Стовпці подання, які посилаються на системні стовпці, не оновлюються." -#: rewrite/rewriteHandler.c:2535 +#: rewrite/rewriteHandler.c:2567 msgid "View columns that return whole-row references are not updatable." msgstr "Стовпці подання, що повертають посилання на весь рядок, не оновлюються." -#: rewrite/rewriteHandler.c:2596 +#: rewrite/rewriteHandler.c:2628 msgid "Views containing DISTINCT are not automatically updatable." msgstr "Подання які містять DISTINCT не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2599 +#: rewrite/rewriteHandler.c:2631 msgid "Views containing GROUP BY are not automatically updatable." msgstr "Подання які містять GROUP BY не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2602 +#: rewrite/rewriteHandler.c:2634 msgid "Views containing HAVING are not automatically updatable." msgstr "Подання які містять HAVING не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2605 +#: rewrite/rewriteHandler.c:2637 msgid "Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." msgstr "Подання які містять UNION, INTERSECT, або EXCEPT не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2608 +#: rewrite/rewriteHandler.c:2640 msgid "Views containing WITH are not automatically updatable." msgstr "Подання які містять WITH не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2611 +#: rewrite/rewriteHandler.c:2643 msgid "Views containing LIMIT or OFFSET are not automatically updatable." msgstr "Подання які містять LIMIT або OFFSET не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2623 +#: rewrite/rewriteHandler.c:2655 msgid "Views that return aggregate functions are not automatically updatable." msgstr "Подання які повертають агрегатні функції не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2626 +#: rewrite/rewriteHandler.c:2658 msgid "Views that return window functions are not automatically updatable." msgstr "Подання які повертають віконні функції не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2629 +#: rewrite/rewriteHandler.c:2661 msgid "Views that return set-returning functions are not automatically updatable." msgstr "Подання які повертають set-returning функції не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2636 rewrite/rewriteHandler.c:2640 -#: rewrite/rewriteHandler.c:2648 +#: rewrite/rewriteHandler.c:2668 rewrite/rewriteHandler.c:2672 +#: rewrite/rewriteHandler.c:2680 msgid "Views that do not select from a single table or view are not automatically updatable." msgstr "Подання які обирають дані не з одної таблиці або подання не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2651 +#: rewrite/rewriteHandler.c:2683 msgid "Views containing TABLESAMPLE are not automatically updatable." msgstr "Подання які містять TABLESAMPLE не оновлюються автоматично." -#: rewrite/rewriteHandler.c:2675 +#: rewrite/rewriteHandler.c:2707 msgid "Views that have no updatable columns are not automatically updatable." msgstr "Подання які не мають оновлюваних стовпців не оновлюються автоматично." -#: rewrite/rewriteHandler.c:3155 +#: rewrite/rewriteHandler.c:3088 rewrite/rewriteHandler.c:3123 +#, c-format +msgid "cannot insert into view \"%s\"" +msgstr "вставити дані в подання \"%s\" не можна" + +#: rewrite/rewriteHandler.c:3091 +#, c-format +msgid "To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." +msgstr "Щоб подання допускало додавання даних, встановіть тригер INSTEAD OF INSERT або безумовне правило ON INSERT DO INSTEAD." + +#: rewrite/rewriteHandler.c:3096 rewrite/rewriteHandler.c:3132 +#, c-format +msgid "cannot update view \"%s\"" +msgstr "оновити подання \"%s\" не можна" + +#: rewrite/rewriteHandler.c:3099 +#, c-format +msgid "To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." +msgstr "Щоб подання допускало оновлення, встановіть тригер INSTEAD OF UPDATE або безумовне правило ON UPDATE DO INSTEAD." + +#: rewrite/rewriteHandler.c:3104 rewrite/rewriteHandler.c:3141 +#, c-format +msgid "cannot delete from view \"%s\"" +msgstr "видалити дані з подання \"%s\" не можна" + +#: rewrite/rewriteHandler.c:3107 +#, c-format +msgid "To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." +msgstr "Щоб подання допускало видалення даних, встановіть тригер INSTEAD OF DELETE або безумновне правило ON DELETE DO INSTEAD." + +#: rewrite/rewriteHandler.c:3126 +#, c-format +msgid "To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger." +msgstr "" + +#: rewrite/rewriteHandler.c:3135 +#, c-format +msgid "To enable updating the view using MERGE, provide an INSTEAD OF UPDATE trigger." +msgstr "" + +#: rewrite/rewriteHandler.c:3144 +#, c-format +msgid "To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger." +msgstr "" + +#: rewrite/rewriteHandler.c:3319 #, c-format msgid "cannot insert into column \"%s\" of view \"%s\"" msgstr "вставити дані в стовпець \"%s\" подання \"%s\" не можна" -#: rewrite/rewriteHandler.c:3163 +#: rewrite/rewriteHandler.c:3327 #, c-format msgid "cannot update column \"%s\" of view \"%s\"" msgstr "оновити дані в стовпці \"%s\" подання \"%s\" не можна" -#: rewrite/rewriteHandler.c:3667 +#: rewrite/rewriteHandler.c:3335 +#, c-format +msgid "cannot merge into column \"%s\" of view \"%s\"" +msgstr "" + +#: rewrite/rewriteHandler.c:3363 +#, c-format +msgid "cannot merge into view \"%s\"" +msgstr "" + +#: rewrite/rewriteHandler.c:3365 +#, c-format +msgid "MERGE is not supported for views with INSTEAD OF triggers for some actions but not all." +msgstr "" + +#: rewrite/rewriteHandler.c:3366 +#, c-format +msgid "To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers." +msgstr "" + +#: rewrite/rewriteHandler.c:3879 #, c-format msgid "DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH" msgstr "Правила DO INSTEAD NOTIFY не підтримуються для операторів, які змінюють дані в WITH" -#: rewrite/rewriteHandler.c:3678 +#: rewrite/rewriteHandler.c:3890 #, c-format msgid "DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" msgstr "Правила DO INSTEAD NOTHING не підтримуються для операторів, які змінюють дані в WITH" -#: rewrite/rewriteHandler.c:3692 +#: rewrite/rewriteHandler.c:3904 #, c-format msgid "conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "умовні правила DO INSTEAD не підтримуються для операторів, які змінюють дані в WITH" -#: rewrite/rewriteHandler.c:3696 +#: rewrite/rewriteHandler.c:3908 #, c-format msgid "DO ALSO rules are not supported for data-modifying statements in WITH" msgstr "Правила DO ALSO не підтримуються для операторів, які змінюють дані в WITH" -#: rewrite/rewriteHandler.c:3701 +#: rewrite/rewriteHandler.c:3913 #, c-format msgid "multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" msgstr "складові правила DO INSTEAD не підтримуються операторами, які змінюють дані у WITH" -#: rewrite/rewriteHandler.c:3968 rewrite/rewriteHandler.c:3976 -#: rewrite/rewriteHandler.c:3984 -#, c-format +#: rewrite/rewriteHandler.c:4173 msgid "Views with conditional DO INSTEAD rules are not automatically updatable." msgstr "Подання з умовними правилами DO INSTEAD не оновлюються автоматично." -#: rewrite/rewriteHandler.c:4089 +#: rewrite/rewriteHandler.c:4270 #, c-format msgid "cannot perform INSERT RETURNING on relation \"%s\"" msgstr "виконати INSERT RETURNING для зв'язка \"%s\" не можна" -#: rewrite/rewriteHandler.c:4091 +#: rewrite/rewriteHandler.c:4272 #, c-format msgid "You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." msgstr "Вам потрібне безумовне правило ON INSERT DO INSTEAD з реченням RETURNING." -#: rewrite/rewriteHandler.c:4096 +#: rewrite/rewriteHandler.c:4277 #, c-format msgid "cannot perform UPDATE RETURNING on relation \"%s\"" msgstr "виконати UPDATE RETURNING для зв'язка \"%s\" не можна" -#: rewrite/rewriteHandler.c:4098 +#: rewrite/rewriteHandler.c:4279 #, c-format msgid "You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." msgstr "Вам потрібне безумовне правило ON UPDATE DO INSTEAD з реченням RETURNING." -#: rewrite/rewriteHandler.c:4103 +#: rewrite/rewriteHandler.c:4284 #, c-format msgid "cannot perform DELETE RETURNING on relation \"%s\"" msgstr "виконати DELETE RETURNING для зв'язка \"%s\" не можна" -#: rewrite/rewriteHandler.c:4105 +#: rewrite/rewriteHandler.c:4286 #, c-format msgid "You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." msgstr "Вам потрібне безумовне правило ON DELETE DO INSTEAD з реченням RETURNING." -#: rewrite/rewriteHandler.c:4123 +#: rewrite/rewriteHandler.c:4304 #, c-format msgid "INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" msgstr "INSERT з реченням ON CONFLICT не можна використовувати з таблицею, яка має правила INSERT або UPDATE" -#: rewrite/rewriteHandler.c:4180 +#: rewrite/rewriteHandler.c:4361 #, c-format msgid "WITH cannot be used in a query that is rewritten by rules into multiple queries" msgstr "WITH не можна використовувати в запиті, який переписаний правилами в декілька запитів" -#: rewrite/rewriteManip.c:1075 +#: rewrite/rewriteManip.c:1083 #, c-format msgid "conditional utility statements are not implemented" msgstr "умовні службові оператори не реалізовані" -#: rewrite/rewriteManip.c:1419 +#: rewrite/rewriteManip.c:1430 #, c-format msgid "WHERE CURRENT OF on a view is not implemented" msgstr "Умова WHERE CURRENT OF для подання не реалізована" -#: rewrite/rewriteManip.c:1754 +#: rewrite/rewriteManip.c:1765 #, c-format msgid "NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command" msgstr "Змінні NEW в правилах ON UPDATE не можуть посилатись на стовпці, які є частиною декілької призначень в команді UPDATE" @@ -21234,72 +21967,67 @@ msgstr "нерозпізнаний параметр Snowball: \"%s\"" msgid "missing Language parameter" msgstr "пропущений параметр Language" -#: statistics/extended_stats.c:179 +#: statistics/extended_stats.c:176 #, c-format msgid "statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"" msgstr "об'єкт статистики \"%s.%s\" не вдалося обчислити для відношення \"%s.%s\"" -#: statistics/mcv.c:1372 +#: statistics/mcv.c:1368 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "функція, що повертає набір, викликана у контексті, що не приймає тип запис" -#: storage/buffer/bufmgr.c:612 storage/buffer/bufmgr.c:769 +#: storage/buffer/bufmgr.c:649 storage/buffer/bufmgr.c:805 #, c-format msgid "cannot access temporary tables of other sessions" msgstr "доступ до тимчасових таблиць з інших сесій заблоковано" -#: storage/buffer/bufmgr.c:1137 +#: storage/buffer/bufmgr.c:1532 #, c-format msgid "invalid page in block %u of relation %s; zeroing out page" msgstr "неприпустима сторінка в блоці %u відношення %s; сторінка обнуляється" -#: storage/buffer/bufmgr.c:1931 storage/buffer/localbuf.c:359 +#: storage/buffer/bufmgr.c:2277 storage/buffer/localbuf.c:361 #, c-format msgid "cannot extend relation %s beyond %u blocks" msgstr "не можна розширити відношення %s понад %u блоків" -#: storage/buffer/bufmgr.c:1998 +#: storage/buffer/bufmgr.c:2348 #, c-format msgid "unexpected data beyond EOF in block %u of relation %s" msgstr "неочікуванні дані після EOF в блоці %u відношення %s" -#: storage/buffer/bufmgr.c:2000 +#: storage/buffer/bufmgr.c:2350 #, c-format msgid "This has been seen to occur with buggy kernels; consider updating your system." msgstr "Ця ситуація може виникати через помилки в ядрі; можливо, вам слід оновити вашу систему." -#: storage/buffer/bufmgr.c:5219 +#: storage/buffer/bufmgr.c:5653 #, c-format msgid "could not write block %u of %s" msgstr "неможливо записати блок %u файлу %s" -#: storage/buffer/bufmgr.c:5221 +#: storage/buffer/bufmgr.c:5655 #, c-format msgid "Multiple failures --- write error might be permanent." msgstr "Кілька неполадок --- можливо, постійна помилка запису." -#: storage/buffer/bufmgr.c:5243 storage/buffer/bufmgr.c:5263 +#: storage/buffer/bufmgr.c:5677 storage/buffer/bufmgr.c:5697 #, c-format msgid "writing block %u of relation %s" msgstr "записування блоку %u зв'язку %s" -#: storage/buffer/bufmgr.c:5593 -#, c-format -msgid "snapshot too old" -msgstr "знімок є застарим" - -#: storage/buffer/localbuf.c:219 +#: storage/buffer/localbuf.c:220 #, c-format msgid "no empty local buffer available" msgstr "немає жодного пустого локального буферу" -#: storage/buffer/localbuf.c:592 +#: storage/buffer/localbuf.c:597 #, c-format msgid "cannot access temporary tables during a parallel operation" msgstr "немає доступу до тимчасових таблиць під час паралельної операції" -#: storage/buffer/localbuf.c:699 +#: storage/buffer/localbuf.c:712 #, c-format msgid "\"temp_buffers\" cannot be changed after any temporary tables have been accessed in the session." msgstr "параметр \"temp_buffers\" не можна змінити після того, як тимчасові таблиці отримали доступ в сеансі." @@ -21319,151 +22047,156 @@ msgstr "не вдалося прочитати файл \"%s\": прочитан msgid "could not read from temporary file: read only %zu of %zu bytes" msgstr "не вдалося прочитати тимчасовий файл: прочитано лише %zu з %zu байт" -#: storage/file/buffile.c:774 storage/file/buffile.c:895 +#: storage/file/buffile.c:774 storage/file/buffile.c:877 #, c-format msgid "could not determine size of temporary file \"%s\" from BufFile \"%s\": %m" msgstr "не вдалося визначити розмір тимчасового файлу \"%s\" з BufFile \"%s\": %m" -#: storage/file/buffile.c:974 +#: storage/file/buffile.c:956 #, c-format msgid "could not delete fileset \"%s\": %m" msgstr "не вдалося видалити набір файлів \"%s\": %m" -#: storage/file/buffile.c:992 storage/smgr/md.c:338 storage/smgr/md.c:1041 +#: storage/file/buffile.c:974 storage/smgr/md.c:336 storage/smgr/md.c:1192 #, c-format msgid "could not truncate file \"%s\": %m" msgstr "не вдалося скоротити файл \"%s\": %m" -#: storage/file/fd.c:537 storage/file/fd.c:609 storage/file/fd.c:645 +#: storage/file/fd.c:583 storage/file/fd.c:655 storage/file/fd.c:691 #, c-format msgid "could not flush dirty data: %m" msgstr "не вдалося очистити \"брудні\" дані: %m" -#: storage/file/fd.c:567 +#: storage/file/fd.c:613 #, c-format msgid "could not determine dirty data size: %m" msgstr "не вдалося визначити розмір \"брудних\" даних: %m" -#: storage/file/fd.c:619 +#: storage/file/fd.c:665 #, c-format msgid "could not munmap() while flushing data: %m" msgstr "не вдалося munmap() під час очищення даних: %m" -#: storage/file/fd.c:937 +#: storage/file/fd.c:983 #, c-format msgid "getrlimit failed: %m" msgstr "помилка getrlimit: %m" -#: storage/file/fd.c:1027 +#: storage/file/fd.c:1073 #, c-format msgid "insufficient file descriptors available to start server process" msgstr "недостатньо доступних дескрипторів файлу для запуску серверного процесу" -#: storage/file/fd.c:1028 +#: storage/file/fd.c:1074 #, c-format msgid "System allows %d, server needs at least %d." msgstr "Система дозволяє %d, сервер потребує щонайменше %d." -#: storage/file/fd.c:1116 storage/file/fd.c:2565 storage/file/fd.c:2674 -#: storage/file/fd.c:2825 +#: storage/file/fd.c:1162 storage/file/fd.c:2618 storage/file/fd.c:2727 +#: storage/file/fd.c:2878 #, c-format msgid "out of file descriptors: %m; release and retry" msgstr "нестача дескрипторів файлу: %m; вивільніть і спробуйте знову" -#: storage/file/fd.c:1490 +#: storage/file/fd.c:1536 #, c-format msgid "temporary file: path \"%s\", size %lu" msgstr "тимчасовий файл: шлях \"%s\", розмір %lu" -#: storage/file/fd.c:1629 +#: storage/file/fd.c:1675 #, c-format msgid "cannot create temporary directory \"%s\": %m" msgstr "неможливо створити тимчасовий каталог \"%s\": %m" -#: storage/file/fd.c:1636 +#: storage/file/fd.c:1682 #, c-format msgid "cannot create temporary subdirectory \"%s\": %m" msgstr "неможливо створити тимчасовий підкаталог \"%s\": %m" -#: storage/file/fd.c:1833 +#: storage/file/fd.c:1879 #, c-format msgid "could not create temporary file \"%s\": %m" msgstr "неможливо створити тимчасовий файл \"%s\": %m" -#: storage/file/fd.c:1869 +#: storage/file/fd.c:1915 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "неможливо відкрити тимчасовий файл \"%s\": %m" -#: storage/file/fd.c:1910 +#: storage/file/fd.c:1956 #, c-format msgid "could not unlink temporary file \"%s\": %m" msgstr "помилка видалення тимчасового файлу \"%s\": %m" -#: storage/file/fd.c:1998 +#: storage/file/fd.c:2044 #, c-format msgid "could not delete file \"%s\": %m" msgstr "не вдалося видалити файл \"%s\": %m" -#: storage/file/fd.c:2185 +#: storage/file/fd.c:2234 #, c-format msgid "temporary file size exceeds temp_file_limit (%dkB)" msgstr "розмір тимчасового файлу перевищує temp_file_limit (%d Кб)" -#: storage/file/fd.c:2541 storage/file/fd.c:2600 +#: storage/file/fd.c:2594 storage/file/fd.c:2653 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open file \"%s\"" msgstr "перевищено maxAllocatedDescs (%d) при спробі відкрити файл \"%s\"" -#: storage/file/fd.c:2645 +#: storage/file/fd.c:2698 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to execute command \"%s\"" msgstr "перевищено maxAllocatedDescs (%d) при спробі виконати команду \"%s\"" -#: storage/file/fd.c:2801 +#: storage/file/fd.c:2854 #, c-format msgid "exceeded maxAllocatedDescs (%d) while trying to open directory \"%s\"" msgstr "перевищено maxAllocatedDescs (%d) при спробі відкрити каталог \"%s\"" -#: storage/file/fd.c:3331 +#: storage/file/fd.c:3384 #, c-format msgid "unexpected file found in temporary-files directory: \"%s\"" msgstr "знайдено неочікуваний файл в каталозі тимчасових файлів: \"%s\"" -#: storage/file/fd.c:3449 +#: storage/file/fd.c:3502 #, c-format msgid "syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s" msgstr "синхронізація каталогу даних (syncfs), витрачено часу: %ld.%02d с, поточний шлях: %s" -#: storage/file/fd.c:3463 -#, c-format -msgid "could not synchronize file system for file \"%s\": %m" -msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" - -#: storage/file/fd.c:3676 +#: storage/file/fd.c:3729 #, c-format msgid "syncing data directory (pre-fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "Синхронізація каталогу даних (pre-fsync), витрачено часу: %ld.%02d с, поточний шлях: %s" -#: storage/file/fd.c:3708 +#: storage/file/fd.c:3761 #, c-format msgid "syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s" msgstr "синхронізація каталогу даних (fsync), витрачено часу: %ld.%02d с, поточний шлях: %s" -#: storage/file/fd.c:3897 +#: storage/file/fd.c:3950 #, c-format -msgid "debug_io_direct is not supported on this platform." -msgstr "debug_io_direct не підтримується на цій платформі." +msgid "\"debug_io_direct\" is not supported on this platform." +msgstr "" + +#: storage/file/fd.c:3964 +#, c-format +msgid "Invalid list syntax in parameter \"%s\"" +msgstr "" -#: storage/file/fd.c:3944 +#: storage/file/fd.c:3984 #, c-format -msgid "debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small" -msgstr "debug_io_direct не підтримується для WAL, оскільки XLOG_BLCKSZ занадто малий" +msgid "Invalid option \"%s\"" +msgstr "Недійсний параметр \"%s\"" -#: storage/file/fd.c:3951 +#: storage/file/fd.c:3997 #, c-format -msgid "debug_io_direct is not supported for data because BLCKSZ is too small" -msgstr "debug_io_direct не підтримується для даних, тому що BLCKSZ занадто малий" +msgid "\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small" +msgstr "" + +#: storage/file/fd.c:4004 +#, c-format +msgid "\"debug_io_direct\" is not supported for data because BLCKSZ is too small" +msgstr "" #: storage/file/reinit.c:145 #, c-format @@ -21475,22 +22208,22 @@ msgstr "скидання нежурнальованих відношень (init msgid "resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s" msgstr "скидання нежурнальованих відношень (очищення), витрачено часу: %ld.%02d с, поточний шлях: %s" -#: storage/file/sharedfileset.c:79 +#: storage/file/sharedfileset.c:73 #, c-format msgid "could not attach to a SharedFileSet that is already destroyed" msgstr "не вдалося підключитися до вже знищеному набору SharedFileSet" -#: storage/ipc/dsm.c:352 +#: storage/ipc/dsm.c:379 #, c-format msgid "dynamic shared memory control segment is corrupt" msgstr "сегмент керування динамічної спільної пам'яті пошкоджений" -#: storage/ipc/dsm.c:417 +#: storage/ipc/dsm.c:444 #, c-format msgid "dynamic shared memory control segment is not valid" msgstr "сегмент керування динамічної спільної пам'яті недійсний" -#: storage/ipc/dsm.c:599 +#: storage/ipc/dsm.c:626 #, c-format msgid "too many dynamic shared memory segments" msgstr "занадто багато сегментів динамічної спільної пам'яті" @@ -21550,73 +22283,99 @@ msgstr "не вдалося закрити сегмент спільної па msgid "could not duplicate handle for \"%s\": %m" msgstr "не вдалося продублювати маркер для \"%s\": %m" -#: storage/ipc/procarray.c:3795 +#: storage/ipc/dsm_registry.c:142 +#, c-format +msgid "DSM segment name cannot be empty" +msgstr "Ім'я сегмента DSM не може бути порожнім" + +#: storage/ipc/dsm_registry.c:146 +#, c-format +msgid "DSM segment name too long" +msgstr "Занадто довге ім'я сегменту DSM" + +#: storage/ipc/dsm_registry.c:150 +#, c-format +msgid "DSM segment size must be nonzero" +msgstr "Розмір сегменту DSM повинен бути ненульовим" + +#: storage/ipc/dsm_registry.c:176 +#, c-format +msgid "requested DSM segment size does not match size of existing segment" +msgstr "розмір запитуваного сегмента DSM не збігається з розміром наявного сегмента" + +#: storage/ipc/procarray.c:488 storage/lmgr/proc.c:352 +#: tcop/backend_startup.c:304 +#, c-format +msgid "sorry, too many clients already" +msgstr "вибачте, вже забагато клієнтів" + +#: storage/ipc/procarray.c:3857 #, c-format msgid "database \"%s\" is being used by prepared transactions" msgstr "база даних \"%s\" використовується підготовленими транзакціями" -#: storage/ipc/procarray.c:3827 storage/ipc/procarray.c:3836 +#: storage/ipc/procarray.c:3893 storage/ipc/procarray.c:3901 #: storage/ipc/signalfuncs.c:235 storage/ipc/signalfuncs.c:242 #, c-format msgid "permission denied to terminate process" msgstr "немає дозволу для припинення процесу" -#: storage/ipc/procarray.c:3828 storage/ipc/signalfuncs.c:236 +#: storage/ipc/procarray.c:3894 storage/ipc/signalfuncs.c:236 #, c-format msgid "Only roles with the %s attribute may terminate processes of roles with the %s attribute." msgstr "Тільки ролі з атрибутом %s можуть припинити процеси ролей з атрибутом %s." -#: storage/ipc/procarray.c:3837 storage/ipc/signalfuncs.c:243 +#: storage/ipc/procarray.c:3902 storage/ipc/signalfuncs.c:243 #, c-format msgid "Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process." msgstr "Лише ролі з привілеями ролі, процес якої завершується, або з привілеями ролі \"%s\" можуть завершити цей процес." -#: storage/ipc/procsignal.c:420 +#: storage/ipc/procsignal.c:416 #, c-format msgid "still waiting for backend with PID %d to accept ProcSignalBarrier" msgstr "все ще чекаємо на прийняття ProcSignalBarrier від бекенд з PID %d" -#: storage/ipc/shm_mq.c:384 +#: storage/ipc/shm_mq.c:383 #, c-format msgid "cannot send a message of size %zu via shared memory queue" msgstr "не можна надсилати повідомлення розміру %zu через чергу спільної пам'яті" -#: storage/ipc/shm_mq.c:719 +#: storage/ipc/shm_mq.c:718 #, c-format msgid "invalid message size %zu in shared memory queue" msgstr "неприпустимий розмір повідомлення %zu в черзі спільної пам'яті" -#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:963 -#: storage/lmgr/lock.c:1001 storage/lmgr/lock.c:2786 storage/lmgr/lock.c:4171 -#: storage/lmgr/lock.c:4236 storage/lmgr/lock.c:4586 -#: storage/lmgr/predicate.c:2412 storage/lmgr/predicate.c:2427 -#: storage/lmgr/predicate.c:3824 storage/lmgr/predicate.c:4871 -#: utils/hash/dynahash.c:1107 +#: storage/ipc/shm_toc.c:118 storage/ipc/shm_toc.c:200 storage/lmgr/lock.c:984 +#: storage/lmgr/lock.c:1022 storage/lmgr/lock.c:2825 storage/lmgr/lock.c:4210 +#: storage/lmgr/lock.c:4275 storage/lmgr/lock.c:4625 +#: storage/lmgr/predicate.c:2463 storage/lmgr/predicate.c:2478 +#: storage/lmgr/predicate.c:3875 storage/lmgr/predicate.c:4922 +#: utils/hash/dynahash.c:1095 #, c-format msgid "out of shared memory" msgstr "нестача спільної пам'яті" -#: storage/ipc/shmem.c:170 storage/ipc/shmem.c:266 +#: storage/ipc/shmem.c:161 storage/ipc/shmem.c:257 #, c-format msgid "out of shared memory (%zu bytes requested)" msgstr "нестача спільної пам'яті (потребується %zu байт)" -#: storage/ipc/shmem.c:445 +#: storage/ipc/shmem.c:436 #, c-format msgid "could not create ShmemIndex entry for data structure \"%s\"" msgstr "не вдалося створити введення ShmemIndex для структури даних \"%s\"" -#: storage/ipc/shmem.c:460 +#: storage/ipc/shmem.c:451 #, c-format msgid "ShmemIndex entry size is wrong for data structure \"%s\": expected %zu, actual %zu" msgstr "розмір введення ShmemIndex є неправильним для структури даних \"%s\": очікувано %zu, фактично %zu" -#: storage/ipc/shmem.c:479 +#: storage/ipc/shmem.c:470 #, c-format msgid "not enough shared memory for data structure \"%s\" (%zu bytes requested)" msgstr "недостатньо спільної пам'яті для структури даних \"%s\" (потрібно було %zu байтів)" -#: storage/ipc/shmem.c:511 storage/ipc/shmem.c:530 +#: storage/ipc/shmem.c:502 storage/ipc/shmem.c:521 #, c-format msgid "requested shared memory size overflows size_t" msgstr "запитаний сегмент спільної пам'яті не вміщається в size_t" @@ -21626,8 +22385,8 @@ msgstr "запитаний сегмент спільної пам'яті не в msgid "PID %d is not a PostgreSQL backend process" msgstr "PID %d не є внутрішнім процесом PostgreSQL" -#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1387 -#: utils/adt/mcxtfuncs.c:190 +#: storage/ipc/signalfuncs.c:109 storage/lmgr/proc.c:1448 +#: utils/adt/mcxtfuncs.c:182 #, c-format msgid "could not send signal to process %d: %m" msgstr "не вдалося надіслати сигнал процесу %d: %m" @@ -21666,90 +22425,86 @@ msgstr[3] "процес з PID %d не завершився протягом %ll msgid "\"timeout\" must not be negative" msgstr "\"timeout\" повинен не може бути негативним" -#: storage/ipc/signalfuncs.c:284 -#, c-format -msgid "must be superuser to rotate log files with adminpack 1.0" -msgstr "прокручувати файли протоколів використовуючи adminpack 1.0, може лише суперкористувач" - -#. translator: %s is a SQL function name -#: storage/ipc/signalfuncs.c:286 utils/adt/genfile.c:250 -#, c-format -msgid "Consider using %s, which is part of core, instead." -msgstr "Розгляньте використання %s, що є частиною ядра." - -#: storage/ipc/signalfuncs.c:292 storage/ipc/signalfuncs.c:312 +#: storage/ipc/signalfuncs.c:285 #, c-format msgid "rotation not possible because log collection not active" msgstr "обертання неможливе тому, що записування колекції не активоване" -#: storage/ipc/standby.c:330 +#: storage/ipc/standby.c:329 #, c-format msgid "recovery still waiting after %ld.%03d ms: %s" msgstr "відновлення все ще чекає, після %ld.%03d мс: %s" -#: storage/ipc/standby.c:339 +#: storage/ipc/standby.c:338 #, c-format msgid "recovery finished waiting after %ld.%03d ms: %s" msgstr "відновлення закінчило очікування після %ld.%03d мс: %s" -#: storage/ipc/standby.c:921 tcop/postgres.c:3384 +#: storage/ipc/standby.c:920 tcop/postgres.c:3196 #, c-format msgid "canceling statement due to conflict with recovery" msgstr "виконання оператора скасовано через конфлікт з процесом відновлення" -#: storage/ipc/standby.c:922 tcop/postgres.c:2533 +#: storage/ipc/standby.c:921 tcop/postgres.c:2557 #, c-format msgid "User transaction caused buffer deadlock with recovery." msgstr "Транзакція користувача призвела до взаємного блокування з процесом відновлення." -#: storage/ipc/standby.c:1488 +#: storage/ipc/standby.c:1486 msgid "unknown reason" msgstr "невідома причина" -#: storage/ipc/standby.c:1493 +#: storage/ipc/standby.c:1491 msgid "recovery conflict on buffer pin" msgstr "конфлікт відновлення, закріпленого в буфері" -#: storage/ipc/standby.c:1496 +#: storage/ipc/standby.c:1494 msgid "recovery conflict on lock" msgstr "конфлікт відновлення при блокуванні" -#: storage/ipc/standby.c:1499 +#: storage/ipc/standby.c:1497 msgid "recovery conflict on tablespace" msgstr "конфлікт відновлення у табличному просторі" -#: storage/ipc/standby.c:1502 +#: storage/ipc/standby.c:1500 msgid "recovery conflict on snapshot" msgstr "конфлікт відновлення під час знімку" -#: storage/ipc/standby.c:1505 +#: storage/ipc/standby.c:1503 msgid "recovery conflict on replication slot" msgstr "конфлікт відновлення у слоті реплікації" -#: storage/ipc/standby.c:1508 +#: storage/ipc/standby.c:1506 msgid "recovery conflict on buffer deadlock" msgstr "конфлікт відновлення при взаємному блокуванні буфера" -#: storage/ipc/standby.c:1511 +#: storage/ipc/standby.c:1509 msgid "recovery conflict on database" msgstr "конфлікт відновлення у базі даних" -#: storage/large_object/inv_api.c:191 +#: storage/large_object/inv_api.c:190 #, c-format msgid "pg_largeobject entry for OID %u, page %d has invalid data field size %d" msgstr "у введенні pg_largeobject для OID %u, сторінка %d має неприпустимий розмір поля даних %d" -#: storage/large_object/inv_api.c:273 +#: storage/large_object/inv_api.c:272 #, c-format msgid "invalid flags for opening a large object: %d" msgstr "неприпустимі позначки для відкриття великого об'єкту: %d" -#: storage/large_object/inv_api.c:456 +#: storage/large_object/inv_api.c:297 storage/large_object/inv_api.c:309 +#: storage/large_object/inv_api.c:506 storage/large_object/inv_api.c:617 +#: storage/large_object/inv_api.c:807 +#, c-format +msgid "permission denied for large object %u" +msgstr "немає дозволу для великого об'єкта %u" + +#: storage/large_object/inv_api.c:455 #, c-format msgid "invalid whence setting: %d" msgstr "неприпустиме значення орієнтиру: %d" -#: storage/large_object/inv_api.c:628 +#: storage/large_object/inv_api.c:627 #, c-format msgid "invalid large object write request size: %d" msgstr "неприпустимий розмір запису великого об'єкту: %d" @@ -21774,211 +22529,211 @@ msgstr "виявлено взаємне блокування" msgid "See server log for query details." msgstr "Подробиці запиту перегляньте в записі серверу." -#: storage/lmgr/lmgr.c:859 +#: storage/lmgr/lmgr.c:848 #, c-format msgid "while updating tuple (%u,%u) in relation \"%s\"" msgstr "при оновленні кортежу (%u,%u) в зв'язку \"%s\"" -#: storage/lmgr/lmgr.c:862 +#: storage/lmgr/lmgr.c:851 #, c-format msgid "while deleting tuple (%u,%u) in relation \"%s\"" msgstr "при видаленні кортежу (%u,%u) в зв'язку \"%s\"" -#: storage/lmgr/lmgr.c:865 +#: storage/lmgr/lmgr.c:854 #, c-format msgid "while locking tuple (%u,%u) in relation \"%s\"" msgstr "при блокуванні кортежу (%u,%u) в зв'язку \"%s\"" -#: storage/lmgr/lmgr.c:868 +#: storage/lmgr/lmgr.c:857 #, c-format msgid "while locking updated version (%u,%u) of tuple in relation \"%s\"" msgstr "при блокуванні оновленої версії (%u,%u) кортежу в зв'язку \"%s\"" -#: storage/lmgr/lmgr.c:871 +#: storage/lmgr/lmgr.c:860 #, c-format msgid "while inserting index tuple (%u,%u) in relation \"%s\"" msgstr "при вставці кортежу індексу (%u,%u) в зв'язку \"%s\"" -#: storage/lmgr/lmgr.c:874 +#: storage/lmgr/lmgr.c:863 #, c-format msgid "while checking uniqueness of tuple (%u,%u) in relation \"%s\"" msgstr "під час перевірки унікальності кортежа (%u,%u) у відношенні \"%s\"" -#: storage/lmgr/lmgr.c:877 +#: storage/lmgr/lmgr.c:866 #, c-format msgid "while rechecking updated tuple (%u,%u) in relation \"%s\"" msgstr "під час повторної перевірки оновленого кортежа (%u,%u) у відношенні \"%s\"" -#: storage/lmgr/lmgr.c:880 +#: storage/lmgr/lmgr.c:869 #, c-format msgid "while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"" msgstr "під час перевірки обмеження-виключення для кортежа (%u,%u) у відношенні \"%s\"" -#: storage/lmgr/lmgr.c:1174 +#: storage/lmgr/lmgr.c:1239 #, c-format msgid "relation %u of database %u" msgstr "відношення %u бази даних %u" -#: storage/lmgr/lmgr.c:1180 +#: storage/lmgr/lmgr.c:1245 #, c-format msgid "extension of relation %u of database %u" msgstr "розширення відношення %u бази даних %u" -#: storage/lmgr/lmgr.c:1186 +#: storage/lmgr/lmgr.c:1251 #, c-format msgid "pg_database.datfrozenxid of database %u" msgstr "pg_database.datfrozenxid бази даних %u" -#: storage/lmgr/lmgr.c:1191 +#: storage/lmgr/lmgr.c:1256 #, c-format msgid "page %u of relation %u of database %u" msgstr "сторінка %u відношення %u бази даних %u" -#: storage/lmgr/lmgr.c:1198 +#: storage/lmgr/lmgr.c:1263 #, c-format msgid "tuple (%u,%u) of relation %u of database %u" msgstr "кортеж (%u,%u) відношення %u бази даних %u" -#: storage/lmgr/lmgr.c:1206 +#: storage/lmgr/lmgr.c:1271 #, c-format msgid "transaction %u" msgstr "транзакція %u" -#: storage/lmgr/lmgr.c:1211 +#: storage/lmgr/lmgr.c:1276 #, c-format msgid "virtual transaction %d/%u" msgstr "віртуальна транзакція %d/%u" -#: storage/lmgr/lmgr.c:1217 +#: storage/lmgr/lmgr.c:1282 #, c-format msgid "speculative token %u of transaction %u" msgstr "орієнтовний маркер %u транзакції %u" -#: storage/lmgr/lmgr.c:1223 +#: storage/lmgr/lmgr.c:1288 #, c-format msgid "object %u of class %u of database %u" msgstr "об’єкт %u класу %u бази даних %u" -#: storage/lmgr/lmgr.c:1231 +#: storage/lmgr/lmgr.c:1296 #, c-format msgid "user lock [%u,%u,%u]" msgstr "користувацьке блокування [%u,%u,%u]" -#: storage/lmgr/lmgr.c:1238 +#: storage/lmgr/lmgr.c:1303 #, c-format msgid "advisory lock [%u,%u,%u,%u]" msgstr "рекомендаційне блокування [%u,%u,%u,%u]" -#: storage/lmgr/lmgr.c:1246 +#: storage/lmgr/lmgr.c:1311 #, c-format msgid "remote transaction %u of subscription %u of database %u" msgstr "віддалена транзакція %u з підписки %u з бази даних %u" -#: storage/lmgr/lmgr.c:1253 +#: storage/lmgr/lmgr.c:1318 #, c-format msgid "unrecognized locktag type %d" msgstr "нерозпізнаний тип блокування %d" -#: storage/lmgr/lock.c:791 +#: storage/lmgr/lock.c:812 #, c-format msgid "cannot acquire lock mode %s on database objects while recovery is in progress" msgstr "поки виконується відновлення, не можна отримати блокування об'єктів бази даних в режимі %s" -#: storage/lmgr/lock.c:793 +#: storage/lmgr/lock.c:814 #, c-format msgid "Only RowExclusiveLock or less can be acquired on database objects during recovery." msgstr "Під час процесу відновлення для об'єктів бази даних може бути отримане лише блокування RowExclusiveLock або менш сильна." -#: storage/lmgr/lock.c:3235 storage/lmgr/lock.c:3303 storage/lmgr/lock.c:3419 +#: storage/lmgr/lock.c:3274 storage/lmgr/lock.c:3342 storage/lmgr/lock.c:3458 #, c-format msgid "cannot PREPARE while holding both session-level and transaction-level locks on the same object" msgstr "не можна виконати PREPARE, під час утримання блокування на рівні сеансу і на рівні транзакції для одного об'єкта" -#: storage/lmgr/predicate.c:649 +#: storage/lmgr/predicate.c:653 #, c-format msgid "not enough elements in RWConflictPool to record a read/write conflict" msgstr "в RWConflictPool недостатньо елементів для запису про конфлікт читання/запису" -#: storage/lmgr/predicate.c:650 storage/lmgr/predicate.c:675 +#: storage/lmgr/predicate.c:654 storage/lmgr/predicate.c:679 #, c-format -msgid "You might need to run fewer transactions at a time or increase max_connections." -msgstr "Можливо, вам слід виконувати менше транзакцій в секунду або збільшити параметр max_connections." +msgid "You might need to run fewer transactions at a time or increase \"max_connections\"." +msgstr "" -#: storage/lmgr/predicate.c:674 +#: storage/lmgr/predicate.c:678 #, c-format msgid "not enough elements in RWConflictPool to record a potential read/write conflict" msgstr "в RWConflictPool недостатньо елементів для запису про потенціальний конфлікт читання/запису" -#: storage/lmgr/predicate.c:1630 +#: storage/lmgr/predicate.c:1681 #, c-format msgid "\"default_transaction_isolation\" is set to \"serializable\"." msgstr "параметр \"default_transaction_isolation\" має значення \"serializable\"." -#: storage/lmgr/predicate.c:1631 +#: storage/lmgr/predicate.c:1682 #, c-format msgid "You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default." msgstr "Ви можете використати \"SET default_transaction_isolation = 'repeatable read'\" щоб змінити режим за замовчуванням." -#: storage/lmgr/predicate.c:1682 +#: storage/lmgr/predicate.c:1733 #, c-format msgid "a snapshot-importing transaction must not be READ ONLY DEFERRABLE" msgstr "транзакція, яка імпортує знімок не повинна бутив READ ONLY DEFERRABLE" -#: storage/lmgr/predicate.c:1761 utils/time/snapmgr.c:570 -#: utils/time/snapmgr.c:576 +#: storage/lmgr/predicate.c:1812 utils/time/snapmgr.c:535 +#: utils/time/snapmgr.c:541 #, c-format msgid "could not import the requested snapshot" msgstr "не вдалося імпортувати запитаний знімок" -#: storage/lmgr/predicate.c:1762 utils/time/snapmgr.c:577 +#: storage/lmgr/predicate.c:1813 utils/time/snapmgr.c:542 #, c-format msgid "The source process with PID %d is not running anymore." msgstr "Вихідний процес з PID %d вже не виконується." -#: storage/lmgr/predicate.c:3935 storage/lmgr/predicate.c:3971 -#: storage/lmgr/predicate.c:4004 storage/lmgr/predicate.c:4012 -#: storage/lmgr/predicate.c:4051 storage/lmgr/predicate.c:4281 -#: storage/lmgr/predicate.c:4600 storage/lmgr/predicate.c:4612 -#: storage/lmgr/predicate.c:4659 storage/lmgr/predicate.c:4695 +#: storage/lmgr/predicate.c:3986 storage/lmgr/predicate.c:4022 +#: storage/lmgr/predicate.c:4055 storage/lmgr/predicate.c:4063 +#: storage/lmgr/predicate.c:4102 storage/lmgr/predicate.c:4332 +#: storage/lmgr/predicate.c:4651 storage/lmgr/predicate.c:4663 +#: storage/lmgr/predicate.c:4710 storage/lmgr/predicate.c:4746 #, c-format msgid "could not serialize access due to read/write dependencies among transactions" msgstr "не вдалося серіалізувати доступ через залежність читання/запису серед транзакцій" -#: storage/lmgr/predicate.c:3937 storage/lmgr/predicate.c:3973 -#: storage/lmgr/predicate.c:4006 storage/lmgr/predicate.c:4014 -#: storage/lmgr/predicate.c:4053 storage/lmgr/predicate.c:4283 -#: storage/lmgr/predicate.c:4602 storage/lmgr/predicate.c:4614 -#: storage/lmgr/predicate.c:4661 storage/lmgr/predicate.c:4697 +#: storage/lmgr/predicate.c:3988 storage/lmgr/predicate.c:4024 +#: storage/lmgr/predicate.c:4057 storage/lmgr/predicate.c:4065 +#: storage/lmgr/predicate.c:4104 storage/lmgr/predicate.c:4334 +#: storage/lmgr/predicate.c:4653 storage/lmgr/predicate.c:4665 +#: storage/lmgr/predicate.c:4712 storage/lmgr/predicate.c:4748 #, c-format msgid "The transaction might succeed if retried." msgstr "Транзакція може завершитися успішно, якщо повторити спробу." -#: storage/lmgr/proc.c:349 +#: storage/lmgr/proc.c:348 #, c-format -msgid "number of requested standby connections exceeds max_wal_senders (currently %d)" -msgstr "кількість запитаних підключень резервного серверу перевищує max_wal_senders (поточна %d)" +msgid "number of requested standby connections exceeds \"max_wal_senders\" (currently %d)" +msgstr "" -#: storage/lmgr/proc.c:1480 +#: storage/lmgr/proc.c:1541 #, c-format msgid "process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" msgstr "процес %d уникнув взаємного блокування, чекаючи в режимі %s блокування %s змінивши порядок черги після %ld.%03d мс" -#: storage/lmgr/proc.c:1495 +#: storage/lmgr/proc.c:1556 #, c-format msgid "process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" msgstr "процес %d виявив взаємне блокування, чекаючи в режимі %s блокування %s після %ld.%03d мс" -#: storage/lmgr/proc.c:1504 +#: storage/lmgr/proc.c:1565 #, c-format msgid "process %d still waiting for %s on %s after %ld.%03d ms" msgstr "процес %d все ще чекає в режимі %s блокування %s після %ld.%03d мс" -#: storage/lmgr/proc.c:1511 +#: storage/lmgr/proc.c:1572 #, c-format msgid "process %d acquired %s on %s after %ld.%03d ms" msgstr "процес %d отримав в режимі %s блокування %s після %ld.%03d мс" -#: storage/lmgr/proc.c:1528 +#: storage/lmgr/proc.c:1589 #, c-format msgid "process %d failed to acquire %s on %s after %ld.%03d ms" msgstr "процес %d не зміг отримати в режимі %s блокування %s після %ld.%03d мс" @@ -22011,67 +22766,202 @@ msgstr "пошкоджена довжина елементу: загальний msgid "corrupted line pointer: offset = %u, size = %u" msgstr "пошкоджений вказівник рядка: зсув = %u, розмір = %u" -#: storage/smgr/md.c:487 storage/smgr/md.c:549 +#: storage/smgr/md.c:485 storage/smgr/md.c:547 #, c-format msgid "cannot extend file \"%s\" beyond %u blocks" msgstr "не можна розширити файл \"%s\" до блоку %u" -#: storage/smgr/md.c:502 storage/smgr/md.c:613 +#: storage/smgr/md.c:500 storage/smgr/md.c:611 #, c-format msgid "could not extend file \"%s\": %m" msgstr "не вдалося розширити файл \"%s\": %m" -#: storage/smgr/md.c:508 +#: storage/smgr/md.c:506 #, c-format msgid "could not extend file \"%s\": wrote only %d of %d bytes at block %u" msgstr "не вдалося розширити файл \"%s\" записано лише %d з %d байт в блоку %u" -#: storage/smgr/md.c:591 +#: storage/smgr/md.c:589 #, c-format msgid "could not extend file \"%s\" with FileFallocate(): %m" msgstr "не вдалося розширити файл \"%s\" за допомогою FileFallocate(): %m" -#: storage/smgr/md.c:782 +#: storage/smgr/md.c:869 +#, c-format +msgid "could not read blocks %u..%u in file \"%s\": %m" +msgstr "не вдалося прочитати блоки %u..%u у файлі \"%s\": %m" + +#: storage/smgr/md.c:895 +#, c-format +msgid "could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes" +msgstr "не вдалося прочитати блоки %u..%u у файлі \"%s\": прочитано лише %zu з %zu байтів" + +#: storage/smgr/md.c:995 +#, c-format +msgid "could not write blocks %u..%u in file \"%s\": %m" +msgstr "не вдалося записати блоки %u..%u у файл \"%s\": %m" + +#: storage/smgr/md.c:1163 +#, c-format +msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" +msgstr "не вдалося скоротити файл \"%s\" до %u блоків: лише %u блоків зараз" + +#: storage/smgr/md.c:1218 +#, c-format +msgid "could not truncate file \"%s\" to %u blocks: %m" +msgstr "не вдалося скоротити файл \"%s\" до %u блоків: %m" + +#: storage/smgr/md.c:1688 +#, c-format +msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" +msgstr "не вдалося відкрити файл \"%s\" (цільовий блок %u): попередній сегмент має лише %u блоків" + +#: storage/smgr/md.c:1702 +#, c-format +msgid "could not open file \"%s\" (target block %u): %m" +msgstr "не вдалося відкрити файл \"%s\" (цільовий блок %u): %m" + +#: tcop/backend_startup.c:85 +#, c-format +msgid "SSL configuration could not be loaded in child process" +msgstr "Не вдалося завантажити конфігурацію SSL в дочірній процес" + +#: tcop/backend_startup.c:208 +#, c-format +msgid "connection received: host=%s port=%s" +msgstr "з'єднання отримано: хост=%s порт=%s" + +#: tcop/backend_startup.c:213 +#, c-format +msgid "connection received: host=%s" +msgstr "з'єднання отримано: хост=%s" + +#: tcop/backend_startup.c:277 +#, c-format +msgid "the database system is starting up" +msgstr "система бази даних запускається" + +#: tcop/backend_startup.c:283 #, c-format -msgid "could not read block %u in file \"%s\": %m" -msgstr "не вдалося прочитати блок %u в файлі \"%s\": %m" +msgid "the database system is not yet accepting connections" +msgstr "система бази даних ще не приймає підключення" + +#: tcop/backend_startup.c:284 +#, c-format +msgid "Consistent recovery state has not been yet reached." +msgstr "Узгодженого стану відновлення ще не досягнуто." + +#: tcop/backend_startup.c:288 +#, c-format +msgid "the database system is not accepting connections" +msgstr "система бази даних не приймає підключення" + +#: tcop/backend_startup.c:289 +#, c-format +msgid "Hot standby mode is disabled." +msgstr "Режим Hot standby вимкнений." + +#: tcop/backend_startup.c:294 +#, c-format +msgid "the database system is shutting down" +msgstr "система бази даних завершує роботу" + +#: tcop/backend_startup.c:299 +#, c-format +msgid "the database system is in recovery mode" +msgstr "система бази даних у режимі відновлення" + +#: tcop/backend_startup.c:414 +#, c-format +msgid "received direct SSL connection request without ALPN protocol negotiation extension" +msgstr "" + +#: tcop/backend_startup.c:420 +#, c-format +msgid "direct SSL connection accepted" +msgstr "" + +#: tcop/backend_startup.c:430 +#, c-format +msgid "direct SSL connection rejected" +msgstr "" + +#: tcop/backend_startup.c:489 tcop/backend_startup.c:517 +#, c-format +msgid "incomplete startup packet" +msgstr "неповний стартовий пакет" + +#: tcop/backend_startup.c:501 tcop/backend_startup.c:538 +#, c-format +msgid "invalid length of startup packet" +msgstr "неприпустима довжина стартового пакету" + +#: tcop/backend_startup.c:573 +#, c-format +msgid "SSLRequest accepted" +msgstr "" + +#: tcop/backend_startup.c:576 +#, c-format +msgid "SSLRequest rejected" +msgstr "" + +#: tcop/backend_startup.c:585 +#, c-format +msgid "failed to send SSL negotiation response: %m" +msgstr "помилка надсилання протоколу SSL в процесі відповіді зв'язування: %m" + +#: tcop/backend_startup.c:603 +#, c-format +msgid "received unencrypted data after SSL request" +msgstr "отримані незашифровані дані після запиту SSL" + +#: tcop/backend_startup.c:604 tcop/backend_startup.c:658 +#, c-format +msgid "This could be either a client-software bug or evidence of an attempted man-in-the-middle attack." +msgstr "Це може бути або помилкою клієнтського програмного забезпечення, або доказом спроби техносферної атаки." + +#: tcop/backend_startup.c:627 +#, c-format +msgid "GSSENCRequest accepted" +msgstr "" -#: storage/smgr/md.c:798 +#: tcop/backend_startup.c:630 #, c-format -msgid "could not read block %u in file \"%s\": read only %d of %d bytes" -msgstr "не вдалося прочитати блок %u в файлі \"%s\": прочитано лише %d з %d байт" +msgid "GSSENCRequest rejected" +msgstr "" -#: storage/smgr/md.c:856 +#: tcop/backend_startup.c:639 #, c-format -msgid "could not write block %u in file \"%s\": %m" -msgstr "не вдалося записати блок %u у файл \"%s\": %m" +msgid "failed to send GSSAPI negotiation response: %m" +msgstr "помилка надсилання GSSAPI в процесі відповіді зв'язування: %m" -#: storage/smgr/md.c:861 +#: tcop/backend_startup.c:657 #, c-format -msgid "could not write block %u in file \"%s\": wrote only %d of %d bytes" -msgstr "не вдалося записати блок %u в файл \"%s\": записано лише %d з %d байт" +msgid "received unencrypted data after GSSAPI encryption request" +msgstr "отримані незашифровані дані після запиту шифрування GSSAPI" -#: storage/smgr/md.c:1012 +#: tcop/backend_startup.c:681 #, c-format -msgid "could not truncate file \"%s\" to %u blocks: it's only %u blocks now" -msgstr "не вдалося скоротити файл \"%s\" до %u блоків: лише %u блоків зараз" +msgid "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u" +msgstr "протокол інтерфейсу, що не підтримується, %u.%u: сервер підтримує %u.0 до %u.%u" -#: storage/smgr/md.c:1067 +#: tcop/backend_startup.c:744 #, c-format -msgid "could not truncate file \"%s\" to %u blocks: %m" -msgstr "не вдалося скоротити файл \"%s\" до %u блоків: %m" +msgid "Valid values are: \"false\", 0, \"true\", 1, \"database\"." +msgstr "Дійсні значення: \"false\", 0, \"true\", 1, \"database\"." -#: storage/smgr/md.c:1494 +#: tcop/backend_startup.c:785 #, c-format -msgid "could not open file \"%s\" (target block %u): previous segment is only %u blocks" -msgstr "не вдалося відкрити файл \"%s\" (цільовий блок %u): попередній сегмент має лише %u блоків" +msgid "invalid startup packet layout: expected terminator as last byte" +msgstr "неприпустима структура стартового пакету: останнім байтом очікувався термінатор" -#: storage/smgr/md.c:1508 +#: tcop/backend_startup.c:802 #, c-format -msgid "could not open file \"%s\" (target block %u): %m" -msgstr "не вдалося відкрити файл \"%s\" (цільовий блок %u): %m" +msgid "no PostgreSQL user name specified in startup packet" +msgstr "не вказано жодного ім'я користувача PostgreSQL у стартовому пакеті" -#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2132 +#: tcop/fastpath.c:142 utils/fmgr/fmgr.c:2161 #, c-format msgid "function with OID %u does not exist" msgstr "функція з OID %u не існує" @@ -22086,8 +22976,8 @@ msgstr "неможливо викликати функцію \"%s\" через msgid "fastpath function call: \"%s\" (OID %u)" msgstr "виклик функції fastpath: \"%s\" (OID %u)" -#: tcop/fastpath.c:313 tcop/postgres.c:1365 tcop/postgres.c:1601 -#: tcop/postgres.c:2059 tcop/postgres.c:2309 +#: tcop/fastpath.c:313 tcop/postgres.c:1369 tcop/postgres.c:1605 +#: tcop/postgres.c:2071 tcop/postgres.c:2333 #, c-format msgid "duration: %s ms" msgstr "тривалість: %s мс" @@ -22117,315 +23007,320 @@ msgstr "неприпустимий розмір аргументу %d в пов msgid "incorrect binary data format in function argument %d" msgstr "неправильний формат двійкових даних в аргументі функції %d" -#: tcop/postgres.c:463 tcop/postgres.c:4882 +#: tcop/postgres.c:467 tcop/postgres.c:5012 #, c-format msgid "invalid frontend message type %d" msgstr "неприпустимий тип клієнтського повідомлення %d" -#: tcop/postgres.c:1072 +#: tcop/postgres.c:1076 #, c-format msgid "statement: %s" msgstr "оператор: %s" -#: tcop/postgres.c:1370 +#: tcop/postgres.c:1374 #, c-format msgid "duration: %s ms statement: %s" msgstr "тривалість: %s мс, оператор: %s" -#: tcop/postgres.c:1476 +#: tcop/postgres.c:1480 #, c-format msgid "cannot insert multiple commands into a prepared statement" msgstr "до підтготовленого оператору не можна вставити декілька команд" -#: tcop/postgres.c:1606 +#: tcop/postgres.c:1610 #, c-format msgid "duration: %s ms parse %s: %s" msgstr "тривалість: %s мс, аналізування %s: %s" -#: tcop/postgres.c:1672 tcop/postgres.c:2629 +#: tcop/postgres.c:1677 tcop/postgres.c:2653 #, c-format msgid "unnamed prepared statement does not exist" msgstr "підготовлений оператор без імені не існує" -#: tcop/postgres.c:1713 +#: tcop/postgres.c:1729 #, c-format msgid "bind message has %d parameter formats but %d parameters" msgstr "повідомлення bind має %d форматів, але %d параметрів" -#: tcop/postgres.c:1719 +#: tcop/postgres.c:1735 #, c-format msgid "bind message supplies %d parameters, but prepared statement \"%s\" requires %d" msgstr "в повідомленні bind передано %d параметрів, але підготовлений оператор \"%s\" потребує %d" -#: tcop/postgres.c:1937 +#: tcop/postgres.c:1949 #, c-format msgid "incorrect binary data format in bind parameter %d" msgstr "невірний формат двійкових даних в параметрі bind %d" -#: tcop/postgres.c:2064 +#: tcop/postgres.c:2076 #, c-format msgid "duration: %s ms bind %s%s%s: %s" msgstr "тривалість: %s мс, повідомлення bind %s%s%s: %s" -#: tcop/postgres.c:2118 tcop/postgres.c:2712 +#: tcop/postgres.c:2131 tcop/postgres.c:2735 #, c-format msgid "portal \"%s\" does not exist" msgstr "портал \"%s\" не існує" -#: tcop/postgres.c:2189 +#: tcop/postgres.c:2213 #, c-format msgid "%s %s%s%s: %s" msgstr "%s %s%s%s: %s" -#: tcop/postgres.c:2191 tcop/postgres.c:2317 +#: tcop/postgres.c:2215 tcop/postgres.c:2341 msgid "execute fetch from" msgstr "виконати витягнення з" -#: tcop/postgres.c:2192 tcop/postgres.c:2318 +#: tcop/postgres.c:2216 tcop/postgres.c:2342 msgid "execute" msgstr "виконувати" -#: tcop/postgres.c:2314 +#: tcop/postgres.c:2338 #, c-format msgid "duration: %s ms %s %s%s%s: %s" msgstr "тривалість: %s мс %s %s%s%s: %s" -#: tcop/postgres.c:2462 +#: tcop/postgres.c:2486 #, c-format msgid "prepare: %s" msgstr "підготовка: %s" -#: tcop/postgres.c:2487 +#: tcop/postgres.c:2511 #, c-format -msgid "parameters: %s" -msgstr "параметри: %s" +msgid "Parameters: %s" +msgstr "Параметри: %s" -#: tcop/postgres.c:2502 +#: tcop/postgres.c:2526 #, c-format -msgid "abort reason: recovery conflict" -msgstr "причина переривання: конфлікт під час відновлення" +msgid "Abort reason: recovery conflict" +msgstr "Причина переривання: конфлікт відновлення" -#: tcop/postgres.c:2518 +#: tcop/postgres.c:2542 #, c-format msgid "User was holding shared buffer pin for too long." msgstr "Користувач утримував позначку спільного буферу занадто довго." -#: tcop/postgres.c:2521 +#: tcop/postgres.c:2545 #, c-format msgid "User was holding a relation lock for too long." msgstr "Користувач утримував блокування відношення занадто довго." -#: tcop/postgres.c:2524 +#: tcop/postgres.c:2548 #, c-format msgid "User was or might have been using tablespace that must be dropped." msgstr "Користувач використовував табличний простір який повинен бути видаленим." -#: tcop/postgres.c:2527 +#: tcop/postgres.c:2551 #, c-format msgid "User query might have needed to see row versions that must be removed." msgstr "Запиту користувача потрібно було бачити версії рядків, які повинні бути видалені." -#: tcop/postgres.c:2530 +#: tcop/postgres.c:2554 #, c-format msgid "User was using a logical replication slot that must be invalidated." msgstr "Користувач використовував логічний слот реплікації, який повинен бути анульований." -#: tcop/postgres.c:2536 +#: tcop/postgres.c:2560 #, c-format msgid "User was connected to a database that must be dropped." msgstr "Користувач був підключен до бази даних, яка повинна бути видалена." -#: tcop/postgres.c:2575 +#: tcop/postgres.c:2599 #, c-format msgid "portal \"%s\" parameter $%d = %s" msgstr "параметр порталу \"%s\": $%d = %s" -#: tcop/postgres.c:2578 +#: tcop/postgres.c:2602 #, c-format msgid "portal \"%s\" parameter $%d" msgstr "параметр порталу \"%s\": $%d" -#: tcop/postgres.c:2584 +#: tcop/postgres.c:2608 #, c-format msgid "unnamed portal parameter $%d = %s" msgstr "параметр порталу без назви $%d = %s" -#: tcop/postgres.c:2587 +#: tcop/postgres.c:2611 #, c-format msgid "unnamed portal parameter $%d" msgstr "параметр порталу без назви $%d" -#: tcop/postgres.c:2932 +#: tcop/postgres.c:2955 #, c-format msgid "terminating connection because of unexpected SIGQUIT signal" msgstr "завершення підключення через неочікуваний сигнал SIGQUIT" -#: tcop/postgres.c:2938 +#: tcop/postgres.c:2961 #, c-format msgid "terminating connection because of crash of another server process" msgstr "завершення підключення через аварійне завершення роботи іншого серверного процесу" -#: tcop/postgres.c:2939 +#: tcop/postgres.c:2962 #, c-format msgid "The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory." msgstr "Керуючий процес віддав команду цьому серверному процесу відкотити поточну транзакцію і завершитися, тому, що інший серверний процес завершився неправильно і можливо пошкодив спільну пам'ять." -#: tcop/postgres.c:2943 tcop/postgres.c:3310 +#: tcop/postgres.c:2966 tcop/postgres.c:3219 #, c-format msgid "In a moment you should be able to reconnect to the database and repeat your command." msgstr "В цей момент ви можете повторно підключитися до бази даних і повторити вашу команду." -#: tcop/postgres.c:2950 +#: tcop/postgres.c:2973 #, c-format msgid "terminating connection due to immediate shutdown command" msgstr "завершення підключення через команду негайного завершення роботи" -#: tcop/postgres.c:3036 +#: tcop/postgres.c:3051 #, c-format msgid "floating-point exception" msgstr "виняток в операції з рухомою комою" -#: tcop/postgres.c:3037 +#: tcop/postgres.c:3052 #, c-format msgid "An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero." msgstr "Надійшло повідомлення про неприпустиму операцію з рухомою комою. Можливо, це значить, що результат виявився за діапазоном або виникла неприпустима операція, така як ділення на нуль." -#: tcop/postgres.c:3214 +#: tcop/postgres.c:3217 +#, c-format +msgid "terminating connection due to conflict with recovery" +msgstr "завершення підключення через конфлікт з процесом відновлення" + +#: tcop/postgres.c:3289 #, c-format msgid "canceling authentication due to timeout" msgstr "скасування автентифікації через тайм-аут" -#: tcop/postgres.c:3218 +#: tcop/postgres.c:3293 #, c-format msgid "terminating autovacuum process due to administrator command" msgstr "завершення процесу автоочистки по команді адміністратора" -#: tcop/postgres.c:3222 +#: tcop/postgres.c:3297 #, c-format msgid "terminating logical replication worker due to administrator command" msgstr "завершення обробника логічної реплікації по команді адміністратора" -#: tcop/postgres.c:3239 tcop/postgres.c:3249 tcop/postgres.c:3308 -#, c-format -msgid "terminating connection due to conflict with recovery" -msgstr "завершення підключення через конфлікт з процесом відновлення" - -#: tcop/postgres.c:3260 +#: tcop/postgres.c:3317 #, c-format msgid "terminating connection due to administrator command" msgstr "завершення підключення по команді адміністратора" -#: tcop/postgres.c:3291 +#: tcop/postgres.c:3348 #, c-format msgid "connection to client lost" msgstr "підключення до клієнта втрачено" -#: tcop/postgres.c:3361 +#: tcop/postgres.c:3400 #, c-format msgid "canceling statement due to lock timeout" msgstr "виконання оператора скасовано через тайм-аут блокування" -#: tcop/postgres.c:3368 +#: tcop/postgres.c:3407 #, c-format msgid "canceling statement due to statement timeout" msgstr "виконання оператора скасовано через тайм-аут" -#: tcop/postgres.c:3375 +#: tcop/postgres.c:3414 #, c-format msgid "canceling autovacuum task" msgstr "скасування завдання автоочистки" -#: tcop/postgres.c:3398 +#: tcop/postgres.c:3427 #, c-format msgid "canceling statement due to user request" msgstr "виконання оператора скасовано по запиту користувача" -#: tcop/postgres.c:3412 +#: tcop/postgres.c:3448 #, c-format msgid "terminating connection due to idle-in-transaction timeout" msgstr "завершення підключення через тайм-аут бездіяльності в транзакції" -#: tcop/postgres.c:3423 +#: tcop/postgres.c:3461 +#, c-format +msgid "terminating connection due to transaction timeout" +msgstr "переривання з'єднання через тайм-аут транзакції" + +#: tcop/postgres.c:3474 #, c-format msgid "terminating connection due to idle-session timeout" msgstr "завершення підключення через тайм-аут неактивного сеансу" -#: tcop/postgres.c:3514 +#: tcop/postgres.c:3564 #, c-format msgid "stack depth limit exceeded" msgstr "перевищено ліміт глибини стека" -#: tcop/postgres.c:3515 +#: tcop/postgres.c:3565 #, c-format msgid "Increase the configuration parameter \"max_stack_depth\" (currently %dkB), after ensuring the platform's stack depth limit is adequate." msgstr "Збільште параметр конфігурації \"max_stack_depth\" (поточне значення %d КБ), попередньо переконавшись, що ОС надає достатній розмір стеку." -#: tcop/postgres.c:3562 +#: tcop/postgres.c:3612 #, c-format msgid "\"max_stack_depth\" must not exceed %ldkB." msgstr "Значення \"max_stack_depth\" не повинно перевищувати %ld КБ." -#: tcop/postgres.c:3564 +#: tcop/postgres.c:3614 #, c-format msgid "Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent." msgstr "Збільшіть ліміт глибини стека в системі через команду \"ulimit -s\" або через локальний еквівалент." -#: tcop/postgres.c:3587 +#: tcop/postgres.c:3637 #, c-format -msgid "client_connection_check_interval must be set to 0 on this platform." -msgstr "client_connection_check_interval має бути встановлений в 0 на цій платформі." +msgid "\"client_connection_check_interval\" must be set to 0 on this platform." +msgstr "" -#: tcop/postgres.c:3608 +#: tcop/postgres.c:3658 #, c-format msgid "Cannot enable parameter when \"log_statement_stats\" is true." msgstr "Не можна ввімкнути параметр, коли \"log_statement_stats\" дорівнює true." -#: tcop/postgres.c:3623 +#: tcop/postgres.c:3673 #, c-format msgid "Cannot enable \"log_statement_stats\" when \"log_parser_stats\", \"log_planner_stats\", or \"log_executor_stats\" is true." msgstr "Не можна ввімкнути \"log_statement_stats\", коли \"log_parser_stats\", \"log_planner_stats\", або \"log_executor_stats\" дорівнюють true." -#: tcop/postgres.c:3971 +#: tcop/postgres.c:4098 #, c-format msgid "invalid command-line argument for server process: %s" msgstr "неприпустимий аргумент командного рядка для серверного процесу: %s" -#: tcop/postgres.c:3972 tcop/postgres.c:3978 +#: tcop/postgres.c:4099 tcop/postgres.c:4105 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: tcop/postgres.c:3976 +#: tcop/postgres.c:4103 #, c-format msgid "%s: invalid command-line argument: %s" msgstr "%s: неприпустимий аргумент командного рядка: %s" -#: tcop/postgres.c:4029 +#: tcop/postgres.c:4156 #, c-format msgid "%s: no database nor user name specified" msgstr "%s: ні база даних, ні ім'я користувача не вказані" -#: tcop/postgres.c:4779 +#: tcop/postgres.c:4909 #, c-format msgid "invalid CLOSE message subtype %d" msgstr "неприпустимий підтип повідомлення CLOSE %d" -#: tcop/postgres.c:4816 +#: tcop/postgres.c:4946 #, c-format msgid "invalid DESCRIBE message subtype %d" msgstr "неприпустимий підтип повідомлення DESCRIBE %d" -#: tcop/postgres.c:4903 +#: tcop/postgres.c:5033 #, c-format msgid "fastpath function calls not supported in a replication connection" msgstr "виклики функції fastpath не підтримуються в підключенні реплікації" -#: tcop/postgres.c:4907 +#: tcop/postgres.c:5037 #, c-format msgid "extended query protocol not supported in a replication connection" msgstr "протокол розширених запитів не підтримується в підключенні реплікації" -#: tcop/postgres.c:5087 +#: tcop/postgres.c:5217 #, c-format msgid "disconnection: session time: %d:%02d:%02d.%03d user=%s database=%s host=%s%s%s" msgstr "відключення: час сеансу: %d:%02d:%02d.%03d користувач = %s база даних = %s хост = %s%s%s" @@ -22446,42 +23341,42 @@ msgid "Declare it with SCROLL option to enable backward scan." msgstr "Оголосити з параметром SCROLL, щоб активувати зворотню розгортку." #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:417 +#: tcop/utility.c:410 #, c-format msgid "cannot execute %s in a read-only transaction" msgstr "не можна виконати %s в транзакції \"лише для читання\"" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:435 +#: tcop/utility.c:428 #, c-format msgid "cannot execute %s during a parallel operation" msgstr "не можна виконати %s під час паралельних операцій" #. translator: %s is name of a SQL command, eg CREATE -#: tcop/utility.c:454 +#: tcop/utility.c:447 #, c-format msgid "cannot execute %s during recovery" msgstr "не можна виконати %s під час відновлення" #. translator: %s is name of a SQL command, eg PREPARE -#: tcop/utility.c:472 +#: tcop/utility.c:465 #, c-format msgid "cannot execute %s within security-restricted operation" msgstr "не можна виконати %s в межах операції з обмеженнями безпеки" #. translator: %s is name of a SQL command, eg LISTEN -#: tcop/utility.c:828 +#: tcop/utility.c:821 #, c-format msgid "cannot execute %s within a background process" msgstr "не можна виконати %s у фоновому процесі" #. translator: %s is name of a SQL command, eg CHECKPOINT -#: tcop/utility.c:954 +#: tcop/utility.c:947 #, c-format msgid "permission denied to execute %s command" msgstr "немає дозволу для виконання команди %s" -#: tcop/utility.c:956 +#: tcop/utility.c:949 #, c-format msgid "Only roles with privileges of the \"%s\" role may execute this command." msgstr "Цю команду можуть виконувати лише ролі з привілеями ролі \"%s\"." @@ -22632,13 +23527,13 @@ msgstr "неприпустима позначка affix \"%s\" зі значен msgid "could not open dictionary file \"%s\": %m" msgstr "не вдалося відкрити файл словника \"%s\": %m" -#: tsearch/spell.c:749 utils/adt/regexp.c:224 jsonpath_gram.y:559 +#: tsearch/spell.c:749 utils/adt/regexp.c:223 jsonpath_gram.y:629 #, c-format msgid "invalid regular expression: %s" msgstr "неприпустимий регулярний вираз: %s" #: tsearch/spell.c:963 tsearch/spell.c:980 tsearch/spell.c:997 -#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18123 gram.y:18140 +#: tsearch/spell.c:1014 tsearch/spell.c:1079 gram.y:18735 gram.y:18752 #, c-format msgid "syntax error" msgstr "синтаксична помилка" @@ -22674,17 +23569,17 @@ msgstr "кількість псевдонімів перевищує вказа msgid "affix file contains both old-style and new-style commands" msgstr "файл affix містить команди і в старому, і в новому стилі" -#: tsearch/to_tsany.c:195 utils/adt/tsvector.c:278 utils/adt/tsvector_op.c:1128 +#: tsearch/to_tsany.c:194 utils/adt/tsvector.c:277 utils/adt/tsvector_op.c:1126 #, c-format msgid "string is too long for tsvector (%d bytes, max %d bytes)" msgstr "рядок занадто довгий для tsvector (%d байт, максимум %d байт)" -#: tsearch/ts_locale.c:238 +#: tsearch/ts_locale.c:236 #, c-format msgid "line %d of configuration file \"%s\": \"%s\"" msgstr "рядок %d файлу конфігурації \"%s\": \"%s\"" -#: tsearch/ts_locale.c:317 +#: tsearch/ts_locale.c:315 #, c-format msgid "conversion from wchar_t to server encoding failed: %m" msgstr "перетворити wchar_t в кодування серверу не вдалося: %mв" @@ -22711,72 +23606,72 @@ msgstr "неприпустиме ім'я файлу конфігурації т msgid "could not open stop-word file \"%s\": %m" msgstr "не вдалося відкрити файл стоп-слова \"%s\": %m" -#: tsearch/wparser.c:308 tsearch/wparser.c:396 tsearch/wparser.c:473 +#: tsearch/wparser.c:306 tsearch/wparser.c:394 tsearch/wparser.c:471 #, c-format msgid "text search parser does not support headline creation" msgstr "аналізатор текстового пошуку не підтримує створення заголовку" -#: tsearch/wparser_def.c:2663 +#: tsearch/wparser_def.c:2664 #, c-format msgid "unrecognized headline parameter: \"%s\"" msgstr "нерозпізнаний параметр заголовку: \"%s\"" -#: tsearch/wparser_def.c:2673 +#: tsearch/wparser_def.c:2674 #, c-format msgid "MinWords should be less than MaxWords" msgstr "Значення MinWords повинно бути меньшим за MaxWords" -#: tsearch/wparser_def.c:2677 +#: tsearch/wparser_def.c:2678 #, c-format msgid "MinWords should be positive" msgstr "Значення MinWords повинно бути позитивним" -#: tsearch/wparser_def.c:2681 +#: tsearch/wparser_def.c:2682 #, c-format msgid "ShortWord should be >= 0" msgstr "Значення ShortWord повинно бути >= 0" -#: tsearch/wparser_def.c:2685 +#: tsearch/wparser_def.c:2686 #, c-format msgid "MaxFragments should be >= 0" msgstr "Значення MaxFragments повинно бути >= 0" -#: utils/activity/pgstat.c:438 +#: utils/activity/pgstat.c:435 #, c-format msgid "could not unlink permanent statistics file \"%s\": %m" msgstr "не вдалося від'єднати файл постійної статистики \"%s\": %m" -#: utils/activity/pgstat.c:1255 +#: utils/activity/pgstat.c:1252 #, c-format msgid "invalid statistics kind: \"%s\"" msgstr "неприпустимий тип статистики: \"%s\"" -#: utils/activity/pgstat.c:1335 +#: utils/activity/pgstat.c:1332 #, c-format msgid "could not open temporary statistics file \"%s\": %m" msgstr "не вдалося відкрити тимчасовий файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1447 +#: utils/activity/pgstat.c:1444 #, c-format msgid "could not write temporary statistics file \"%s\": %m" msgstr "не вдалося записати в тимчасовий файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1456 +#: utils/activity/pgstat.c:1453 #, c-format msgid "could not close temporary statistics file \"%s\": %m" msgstr "не вдалося закрити тимчасовий файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1464 +#: utils/activity/pgstat.c:1461 #, c-format msgid "could not rename temporary statistics file \"%s\" to \"%s\": %m" msgstr "не вдалося перейменувати тимчасовий файл статистики з \"%s\" в \"%s\": %m" -#: utils/activity/pgstat.c:1513 +#: utils/activity/pgstat.c:1510 #, c-format msgid "could not open statistics file \"%s\": %m" msgstr "не вдалося відкрити файл статистики \"%s\": %m" -#: utils/activity/pgstat.c:1675 +#: utils/activity/pgstat.c:1672 #, c-format msgid "corrupted statistics file \"%s\"" msgstr "пошкоджений файл статистики \"%s\"" @@ -22786,115 +23681,125 @@ msgstr "пошкоджений файл статистики \"%s\"" msgid "function call to dropped function" msgstr "виклик видаленої функції" -#: utils/activity/pgstat_xact.c:363 +#: utils/activity/pgstat_xact.c:362 #, c-format msgid "resetting existing statistics for kind %s, db=%u, oid=%u" msgstr "скидання існуючої статистики для типу %s, db=%u, oid=%u" -#: utils/adt/acl.c:177 utils/adt/name.c:93 +#: utils/activity/wait_event.c:207 utils/activity/wait_event.c:232 +#, c-format +msgid "wait event \"%s\" already exists in type \"%s\"" +msgstr "" + +#: utils/activity/wait_event.c:246 +#, c-format +msgid "too many custom wait events" +msgstr "" + +#: utils/adt/acl.c:183 utils/adt/name.c:93 #, c-format msgid "identifier too long" msgstr "занадто довгий ідентифікатор" -#: utils/adt/acl.c:178 utils/adt/name.c:94 +#: utils/adt/acl.c:184 utils/adt/name.c:94 #, c-format msgid "Identifier must be less than %d characters." msgstr "Ідентифікатор повинен бути короче ніж %d символів." -#: utils/adt/acl.c:266 +#: utils/adt/acl.c:272 #, c-format msgid "unrecognized key word: \"%s\"" msgstr "нерозпізнане ключове слово: \"%s\"" -#: utils/adt/acl.c:267 +#: utils/adt/acl.c:273 #, c-format msgid "ACL key word must be \"group\" or \"user\"." msgstr "Ключовим словом ACL повинно бути \"group\" або \"user\"." -#: utils/adt/acl.c:275 +#: utils/adt/acl.c:281 #, c-format msgid "missing name" msgstr "пропущено ім'я" -#: utils/adt/acl.c:276 +#: utils/adt/acl.c:282 #, c-format msgid "A name must follow the \"group\" or \"user\" key word." msgstr "За ключовими словами \"group\" або \"user\" повинно йти ім'я." -#: utils/adt/acl.c:282 +#: utils/adt/acl.c:288 #, c-format msgid "missing \"=\" sign" msgstr "пропущено знак \"=\"" -#: utils/adt/acl.c:341 +#: utils/adt/acl.c:350 #, c-format msgid "invalid mode character: must be one of \"%s\"" msgstr "неприпустимий символ режиму: повинен бути один з \"%s\"" -#: utils/adt/acl.c:371 +#: utils/adt/acl.c:380 #, c-format msgid "a name must follow the \"/\" sign" msgstr "за знаком \"/\" повинно прямувати ім'я" -#: utils/adt/acl.c:383 +#: utils/adt/acl.c:392 #, c-format msgid "defaulting grantor to user ID %u" msgstr "призначив права користувач з ідентифікатором %u" -#: utils/adt/acl.c:569 +#: utils/adt/acl.c:578 #, c-format msgid "ACL array contains wrong data type" msgstr "Масив ACL містить неправильний тип даних" -#: utils/adt/acl.c:573 +#: utils/adt/acl.c:582 #, c-format msgid "ACL arrays must be one-dimensional" msgstr "Масиви ACL повинні бути одновимірними" -#: utils/adt/acl.c:577 +#: utils/adt/acl.c:586 #, c-format msgid "ACL arrays must not contain null values" msgstr "Масиви ACL не повинні містити значення null" -#: utils/adt/acl.c:606 +#: utils/adt/acl.c:615 #, c-format msgid "extra garbage at the end of the ACL specification" msgstr "зайве сміття в кінці специфікації ACL" -#: utils/adt/acl.c:1248 +#: utils/adt/acl.c:1263 #, c-format msgid "grant options cannot be granted back to your own grantor" msgstr "параметри призначення прав не можна повернути тому, хто призначив їх вам" -#: utils/adt/acl.c:1564 +#: utils/adt/acl.c:1579 #, c-format msgid "aclinsert is no longer supported" msgstr "aclinsert більше не підтримується" -#: utils/adt/acl.c:1574 +#: utils/adt/acl.c:1589 #, c-format msgid "aclremove is no longer supported" msgstr "aclremove більше не підтримується" -#: utils/adt/acl.c:1693 +#: utils/adt/acl.c:1709 #, c-format msgid "unrecognized privilege type: \"%s\"" msgstr "нерозпізнаний тип прав: \"%s\"" -#: utils/adt/acl.c:3476 utils/adt/regproc.c:100 utils/adt/regproc.c:265 +#: utils/adt/acl.c:3550 utils/adt/regproc.c:100 utils/adt/regproc.c:265 #, c-format msgid "function \"%s\" does not exist" msgstr "функція \"%s\" не існує" -#: utils/adt/acl.c:5023 +#: utils/adt/acl.c:5196 #, c-format msgid "must be able to SET ROLE \"%s\"" msgstr "потрібно мати можливість SET ROLE \"%s\"" #: utils/adt/array_userfuncs.c:102 utils/adt/array_userfuncs.c:489 -#: utils/adt/array_userfuncs.c:878 utils/adt/json.c:694 utils/adt/json.c:831 -#: utils/adt/json.c:869 utils/adt/jsonb.c:1139 utils/adt/jsonb.c:1211 -#: utils/adt/jsonb.c:1629 utils/adt/jsonb.c:1817 utils/adt/jsonb.c:1827 +#: utils/adt/array_userfuncs.c:866 utils/adt/json.c:602 utils/adt/json.c:740 +#: utils/adt/json.c:790 utils/adt/jsonb.c:1025 utils/adt/jsonb.c:1098 +#: utils/adt/jsonb.c:1530 utils/adt/jsonb.c:1718 utils/adt/jsonb.c:1728 #, c-format msgid "could not determine input data type" msgstr "не вдалося визначити тип вхідних даних" @@ -22905,17 +23810,17 @@ msgid "input data type is not an array" msgstr "тип вхідних даних не є масивом" #: utils/adt/array_userfuncs.c:151 utils/adt/array_userfuncs.c:203 -#: utils/adt/float.c:1228 utils/adt/float.c:1302 utils/adt/float.c:4117 -#: utils/adt/float.c:4155 utils/adt/int.c:778 utils/adt/int.c:800 +#: utils/adt/float.c:1222 utils/adt/float.c:1296 utils/adt/float.c:4022 +#: utils/adt/float.c:4060 utils/adt/int.c:778 utils/adt/int.c:800 #: utils/adt/int.c:814 utils/adt/int.c:828 utils/adt/int.c:859 #: utils/adt/int.c:880 utils/adt/int.c:997 utils/adt/int.c:1011 #: utils/adt/int.c:1025 utils/adt/int.c:1058 utils/adt/int.c:1072 #: utils/adt/int.c:1086 utils/adt/int.c:1117 utils/adt/int.c:1199 #: utils/adt/int.c:1263 utils/adt/int.c:1331 utils/adt/int.c:1337 -#: utils/adt/int8.c:1257 utils/adt/numeric.c:1901 utils/adt/numeric.c:4388 -#: utils/adt/rangetypes.c:1481 utils/adt/rangetypes.c:1494 -#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1132 -#: utils/adt/varlena.c:3134 +#: utils/adt/int8.c:1256 utils/adt/numeric.c:1917 utils/adt/numeric.c:4454 +#: utils/adt/rangetypes.c:1488 utils/adt/rangetypes.c:1501 +#: utils/adt/varbit.c:1195 utils/adt/varbit.c:1596 utils/adt/varlena.c:1135 +#: utils/adt/varlena.c:3137 #, c-format msgid "integer out of range" msgstr "ціле число поза діапазоном" @@ -22952,267 +23857,278 @@ msgstr "Масиви з різними вимірами елементів не msgid "Arrays with differing dimensions are not compatible for concatenation." msgstr "Масиви з різними вимірами не є сумісними для об'єднання." -#: utils/adt/array_userfuncs.c:987 utils/adt/array_userfuncs.c:995 -#: utils/adt/arrayfuncs.c:5639 utils/adt/arrayfuncs.c:5645 +#: utils/adt/array_userfuncs.c:975 utils/adt/array_userfuncs.c:983 +#: utils/adt/arrayfuncs.c:5616 utils/adt/arrayfuncs.c:5622 #, c-format msgid "cannot accumulate arrays of different dimensionality" msgstr "накопичувати масиви різної розмірності не можна" -#: utils/adt/array_userfuncs.c:1286 utils/adt/array_userfuncs.c:1440 +#: utils/adt/array_userfuncs.c:1272 utils/adt/array_userfuncs.c:1426 #, c-format msgid "searching for elements in multidimensional arrays is not supported" msgstr "пошук елементів у багатовимірних масивах не підтримується" -#: utils/adt/array_userfuncs.c:1315 +#: utils/adt/array_userfuncs.c:1301 #, c-format msgid "initial position must not be null" msgstr "початкова позиція не повинна бути null" -#: utils/adt/array_userfuncs.c:1688 +#: utils/adt/array_userfuncs.c:1674 #, c-format msgid "sample size must be between 0 and %d" msgstr "розмір вибірки повинен бути між 0 і %d" -#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:288 -#: utils/adt/arrayfuncs.c:299 utils/adt/arrayfuncs.c:321 -#: utils/adt/arrayfuncs.c:338 utils/adt/arrayfuncs.c:352 -#: utils/adt/arrayfuncs.c:360 utils/adt/arrayfuncs.c:367 -#: utils/adt/arrayfuncs.c:507 utils/adt/arrayfuncs.c:522 -#: utils/adt/arrayfuncs.c:533 utils/adt/arrayfuncs.c:548 -#: utils/adt/arrayfuncs.c:569 utils/adt/arrayfuncs.c:599 -#: utils/adt/arrayfuncs.c:606 utils/adt/arrayfuncs.c:614 -#: utils/adt/arrayfuncs.c:648 utils/adt/arrayfuncs.c:671 -#: utils/adt/arrayfuncs.c:691 utils/adt/arrayfuncs.c:808 -#: utils/adt/arrayfuncs.c:817 utils/adt/arrayfuncs.c:847 -#: utils/adt/arrayfuncs.c:862 utils/adt/arrayfuncs.c:915 +#: utils/adt/arrayfuncs.c:264 utils/adt/arrayfuncs.c:273 +#: utils/adt/arrayfuncs.c:284 utils/adt/arrayfuncs.c:307 +#: utils/adt/arrayfuncs.c:440 utils/adt/arrayfuncs.c:454 +#: utils/adt/arrayfuncs.c:466 utils/adt/arrayfuncs.c:636 +#: utils/adt/arrayfuncs.c:668 utils/adt/arrayfuncs.c:703 +#: utils/adt/arrayfuncs.c:718 utils/adt/arrayfuncs.c:777 +#: utils/adt/arrayfuncs.c:782 utils/adt/arrayfuncs.c:870 +#: utils/adt/arrayfuncs.c:897 utils/adt/arrayfuncs.c:904 +#: utils/adt/arrayfuncs.c:941 #, c-format msgid "malformed array literal: \"%s\"" msgstr "неправильний літерал масиву: \"%s\"" -#: utils/adt/arrayfuncs.c:275 -#, c-format -msgid "\"[\" must introduce explicitly-specified array dimensions." -msgstr "\"[\" повинно представляти явно вказані виміри масиву." - -#: utils/adt/arrayfuncs.c:289 +#: utils/adt/arrayfuncs.c:265 #, c-format -msgid "Missing array dimension value." -msgstr "Пропущено значення виміру масиву." +msgid "Array value must start with \"{\" or dimension information." +msgstr "Значення масиву повинно починатись з \"{\" або з інформації про вимір." -#: utils/adt/arrayfuncs.c:300 utils/adt/arrayfuncs.c:339 +#: utils/adt/arrayfuncs.c:274 utils/adt/arrayfuncs.c:467 #, c-format msgid "Missing \"%s\" after array dimensions." msgstr "Пропущено \"%s\" після вимірів масиву." -#: utils/adt/arrayfuncs.c:309 utils/adt/arrayfuncs.c:2969 -#: utils/adt/arrayfuncs.c:3014 utils/adt/arrayfuncs.c:3029 +#: utils/adt/arrayfuncs.c:285 #, c-format -msgid "upper bound cannot be less than lower bound" -msgstr "верхня границя не може бути меньше нижньої границі" +msgid "Array contents must start with \"{\"." +msgstr "Вміст масиву повинен починатись з \"{\"." -#: utils/adt/arrayfuncs.c:322 +#: utils/adt/arrayfuncs.c:308 utils/adt/multirangetypes.c:292 #, c-format -msgid "Array value must start with \"{\" or dimension information." -msgstr "Значення масиву повинно починатись з \"{\" або з інформації про вимір." +msgid "Junk after closing right brace." +msgstr "Сміття після закриття правої дужки." -#: utils/adt/arrayfuncs.c:353 +#: utils/adt/arrayfuncs.c:431 utils/adt/arrayfuncs.c:643 #, c-format -msgid "Array contents must start with \"{\"." -msgstr "Вміст масиву повинен починатись з \"{\"." +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "кількість вимірів масиву перевищує максимально дозволену (%d)" -#: utils/adt/arrayfuncs.c:361 utils/adt/arrayfuncs.c:368 +#: utils/adt/arrayfuncs.c:441 #, c-format -msgid "Specified array dimensions do not match array contents." -msgstr "Вказані виміри масиву не відповідають його вмісту." +msgid "\"[\" must introduce explicitly-specified array dimensions." +msgstr "\"[\" повинно представляти явно вказані виміри масиву." -#: utils/adt/arrayfuncs.c:508 utils/adt/arrayfuncs.c:534 -#: utils/adt/multirangetypes.c:166 utils/adt/rangetypes.c:2405 -#: utils/adt/rangetypes.c:2413 utils/adt/rowtypes.c:219 -#: utils/adt/rowtypes.c:230 +#: utils/adt/arrayfuncs.c:455 #, c-format -msgid "Unexpected end of input." -msgstr "Неочікуваний кінец введення." +msgid "Missing array dimension value." +msgstr "Пропущено значення виміру масиву." -#: utils/adt/arrayfuncs.c:523 utils/adt/arrayfuncs.c:570 -#: utils/adt/arrayfuncs.c:600 utils/adt/arrayfuncs.c:649 +#: utils/adt/arrayfuncs.c:481 utils/adt/arrayfuncs.c:2940 +#: utils/adt/arrayfuncs.c:2985 utils/adt/arrayfuncs.c:3000 +#, c-format +msgid "upper bound cannot be less than lower bound" +msgstr "верхня границя не може бути меньше нижньої границі" + +#: utils/adt/arrayfuncs.c:487 +#, c-format +msgid "array upper bound is too large: %d" +msgstr "верхня межа масиву занадто велика: %d" + +#: utils/adt/arrayfuncs.c:538 +#, c-format +msgid "array bound is out of integer range" +msgstr "межа масиву знаходиться за межами цілочисельного діапазону" + +#: utils/adt/arrayfuncs.c:637 utils/adt/arrayfuncs.c:669 +#: utils/adt/arrayfuncs.c:704 utils/adt/arrayfuncs.c:898 #, c-format msgid "Unexpected \"%c\" character." msgstr "Неочікуваний символ \"%c\"." -#: utils/adt/arrayfuncs.c:549 utils/adt/arrayfuncs.c:672 +#: utils/adt/arrayfuncs.c:719 #, c-format msgid "Unexpected array element." msgstr "Неочікуваний елемент масиву." -#: utils/adt/arrayfuncs.c:607 +#: utils/adt/arrayfuncs.c:778 #, c-format -msgid "Unmatched \"%c\" character." -msgstr "Невідповідний символ \"%c\"." +msgid "Specified array dimensions do not match array contents." +msgstr "Вказані виміри масиву не відповідають його вмісту." -#: utils/adt/arrayfuncs.c:615 utils/adt/jsonfuncs.c:2553 +#: utils/adt/arrayfuncs.c:783 utils/adt/jsonfuncs.c:2598 #, c-format msgid "Multidimensional arrays must have sub-arrays with matching dimensions." msgstr "Багатовимірні масиви повинні мати вкладені масиви з відповідними вимірами." -#: utils/adt/arrayfuncs.c:692 utils/adt/multirangetypes.c:293 +#: utils/adt/arrayfuncs.c:871 utils/adt/arrayfuncs.c:905 #, c-format -msgid "Junk after closing right brace." -msgstr "Сміття після закриття правої дужки." +msgid "Incorrectly quoted array element." +msgstr "Неправильно процитовано елемент масиву." + +#: utils/adt/arrayfuncs.c:942 utils/adt/multirangetypes.c:165 +#: utils/adt/rangetypes.c:2464 utils/adt/rangetypes.c:2472 +#: utils/adt/rowtypes.c:218 utils/adt/rowtypes.c:229 +#, c-format +msgid "Unexpected end of input." +msgstr "Неочікуваний кінец введення." -#: utils/adt/arrayfuncs.c:1326 utils/adt/arrayfuncs.c:3528 -#: utils/adt/arrayfuncs.c:6129 +#: utils/adt/arrayfuncs.c:1301 utils/adt/arrayfuncs.c:3499 +#: utils/adt/arrayfuncs.c:6106 #, c-format msgid "invalid number of dimensions: %d" msgstr "неприпустима кількість вимірів: %d" -#: utils/adt/arrayfuncs.c:1337 +#: utils/adt/arrayfuncs.c:1312 #, c-format msgid "invalid array flags" msgstr "неприпустимі позначки масиву" -#: utils/adt/arrayfuncs.c:1359 +#: utils/adt/arrayfuncs.c:1334 #, c-format msgid "binary data has array element type %u (%s) instead of expected %u (%s)" msgstr "двійкові дані мають тип елементу масиву %u (%s) замість очікуваного %u (%s)" -#: utils/adt/arrayfuncs.c:1403 utils/adt/multirangetypes.c:451 -#: utils/adt/rangetypes.c:344 utils/cache/lsyscache.c:2916 +#: utils/adt/arrayfuncs.c:1378 utils/adt/multirangetypes.c:450 +#: utils/adt/rangetypes.c:351 utils/cache/lsyscache.c:2958 #, c-format msgid "no binary input function available for type %s" msgstr "для типу %s немає функції введення двійкових даних" -#: utils/adt/arrayfuncs.c:1543 +#: utils/adt/arrayfuncs.c:1509 #, c-format msgid "improper binary format in array element %d" msgstr "неправильний двійковий формат в елементі масиву %d" -#: utils/adt/arrayfuncs.c:1624 utils/adt/multirangetypes.c:456 -#: utils/adt/rangetypes.c:349 utils/cache/lsyscache.c:2949 +#: utils/adt/arrayfuncs.c:1588 utils/adt/multirangetypes.c:455 +#: utils/adt/rangetypes.c:356 utils/cache/lsyscache.c:2991 #, c-format msgid "no binary output function available for type %s" msgstr "для типу %s немає функції виводу двійкових даних" -#: utils/adt/arrayfuncs.c:2103 +#: utils/adt/arrayfuncs.c:2067 #, c-format msgid "slices of fixed-length arrays not implemented" msgstr "розрізання масивів постійної довжини не реалізовано" -#: utils/adt/arrayfuncs.c:2281 utils/adt/arrayfuncs.c:2303 -#: utils/adt/arrayfuncs.c:2352 utils/adt/arrayfuncs.c:2606 -#: utils/adt/arrayfuncs.c:2944 utils/adt/arrayfuncs.c:6115 -#: utils/adt/arrayfuncs.c:6141 utils/adt/arrayfuncs.c:6152 -#: utils/adt/json.c:1497 utils/adt/json.c:1569 utils/adt/jsonb.c:1416 -#: utils/adt/jsonb.c:1500 utils/adt/jsonfuncs.c:4434 utils/adt/jsonfuncs.c:4587 -#: utils/adt/jsonfuncs.c:4698 utils/adt/jsonfuncs.c:4746 +#: utils/adt/arrayfuncs.c:2245 utils/adt/arrayfuncs.c:2267 +#: utils/adt/arrayfuncs.c:2316 utils/adt/arrayfuncs.c:2570 +#: utils/adt/arrayfuncs.c:2915 utils/adt/arrayfuncs.c:6092 +#: utils/adt/arrayfuncs.c:6118 utils/adt/arrayfuncs.c:6129 +#: utils/adt/json.c:1433 utils/adt/json.c:1505 utils/adt/jsonb.c:1317 +#: utils/adt/jsonb.c:1401 utils/adt/jsonfuncs.c:4710 utils/adt/jsonfuncs.c:4863 +#: utils/adt/jsonfuncs.c:4974 utils/adt/jsonfuncs.c:5022 #, c-format msgid "wrong number of array subscripts" msgstr "невірне число верхніх індексів масива" -#: utils/adt/arrayfuncs.c:2286 utils/adt/arrayfuncs.c:2410 -#: utils/adt/arrayfuncs.c:2689 utils/adt/arrayfuncs.c:3019 +#: utils/adt/arrayfuncs.c:2250 utils/adt/arrayfuncs.c:2374 +#: utils/adt/arrayfuncs.c:2653 utils/adt/arrayfuncs.c:2990 #, c-format msgid "array subscript out of range" msgstr "верхній індекс масиву поза діапазоном" -#: utils/adt/arrayfuncs.c:2291 +#: utils/adt/arrayfuncs.c:2255 #, c-format msgid "cannot assign null value to an element of a fixed-length array" msgstr "не можна призначати значення null значення елементу масива постійної довжини" -#: utils/adt/arrayfuncs.c:2891 +#: utils/adt/arrayfuncs.c:2855 #, c-format msgid "updates on slices of fixed-length arrays not implemented" msgstr "оновлення в зрізах масивів постійної довжини не реалізовані" -#: utils/adt/arrayfuncs.c:2922 +#: utils/adt/arrayfuncs.c:2886 #, c-format msgid "array slice subscript must provide both boundaries" msgstr "у вказівці зрізу масива повинні бути задані обидві межі" -#: utils/adt/arrayfuncs.c:2923 +#: utils/adt/arrayfuncs.c:2887 #, c-format msgid "When assigning to a slice of an empty array value, slice boundaries must be fully specified." msgstr "Під час присвоєння значень зрізу в пустому масиві, межі зрізу повинні вказуватися повністю." -#: utils/adt/arrayfuncs.c:2934 utils/adt/arrayfuncs.c:3046 +#: utils/adt/arrayfuncs.c:2905 utils/adt/arrayfuncs.c:3017 #, c-format msgid "source array too small" msgstr "вихідний масив занадто малий" -#: utils/adt/arrayfuncs.c:3686 +#: utils/adt/arrayfuncs.c:3657 #, c-format msgid "null array element not allowed in this context" msgstr "елемент масиву null не дозволений в цьому контексті" -#: utils/adt/arrayfuncs.c:3857 utils/adt/arrayfuncs.c:4028 -#: utils/adt/arrayfuncs.c:4419 +#: utils/adt/arrayfuncs.c:3828 utils/adt/arrayfuncs.c:3999 +#: utils/adt/arrayfuncs.c:4390 #, c-format msgid "cannot compare arrays of different element types" msgstr "не можна порівнювати масиви з елементами різних типів" -#: utils/adt/arrayfuncs.c:4206 utils/adt/multirangetypes.c:2806 -#: utils/adt/multirangetypes.c:2878 utils/adt/rangetypes.c:1354 -#: utils/adt/rangetypes.c:1418 utils/adt/rowtypes.c:1885 +#: utils/adt/arrayfuncs.c:4177 utils/adt/multirangetypes.c:2805 +#: utils/adt/multirangetypes.c:2877 utils/adt/rangetypes.c:1361 +#: utils/adt/rangetypes.c:1425 utils/adt/rowtypes.c:1875 #, c-format msgid "could not identify a hash function for type %s" msgstr "не вдалося визначити геш-функцію для типу %s" -#: utils/adt/arrayfuncs.c:4334 utils/adt/rowtypes.c:2006 +#: utils/adt/arrayfuncs.c:4305 utils/adt/rowtypes.c:1996 #, c-format msgid "could not identify an extended hash function for type %s" msgstr "не вдалося визначити розширену геш-функцію для типу %s" -#: utils/adt/arrayfuncs.c:5529 +#: utils/adt/arrayfuncs.c:5506 #, c-format msgid "data type %s is not an array type" msgstr "тип даних %s не є типом масиву" -#: utils/adt/arrayfuncs.c:5584 +#: utils/adt/arrayfuncs.c:5561 #, c-format msgid "cannot accumulate null arrays" msgstr "накопичувати null-масиви не можна" -#: utils/adt/arrayfuncs.c:5612 +#: utils/adt/arrayfuncs.c:5589 #, c-format msgid "cannot accumulate empty arrays" msgstr "накопичувати пусті масиви не можна" -#: utils/adt/arrayfuncs.c:6013 utils/adt/arrayfuncs.c:6053 +#: utils/adt/arrayfuncs.c:5990 utils/adt/arrayfuncs.c:6030 #, c-format msgid "dimension array or low bound array cannot be null" msgstr "масив розмірності або масив нижніх границь не може бути null" -#: utils/adt/arrayfuncs.c:6116 utils/adt/arrayfuncs.c:6142 +#: utils/adt/arrayfuncs.c:6093 utils/adt/arrayfuncs.c:6119 #, c-format msgid "Dimension array must be one dimensional." msgstr "Масив розмірності повинен бути одновимірним." -#: utils/adt/arrayfuncs.c:6121 utils/adt/arrayfuncs.c:6147 +#: utils/adt/arrayfuncs.c:6098 utils/adt/arrayfuncs.c:6124 #, c-format msgid "dimension values cannot be null" msgstr "значення розмірностей не можуть бути null" -#: utils/adt/arrayfuncs.c:6153 +#: utils/adt/arrayfuncs.c:6130 #, c-format msgid "Low bound array has different size than dimensions array." msgstr "Масив нижніх границь відрізняється за розміром від масиву розмірностей." -#: utils/adt/arrayfuncs.c:6431 +#: utils/adt/arrayfuncs.c:6411 #, c-format msgid "removing elements from multidimensional arrays is not supported" msgstr "видалення елементів з багатовимірних масивів не підтримується" -#: utils/adt/arrayfuncs.c:6708 +#: utils/adt/arrayfuncs.c:6688 #, c-format msgid "thresholds must be one-dimensional array" msgstr "граничне значення повинно вказуватись одновимірним масивом" -#: utils/adt/arrayfuncs.c:6713 +#: utils/adt/arrayfuncs.c:6693 #, c-format msgid "thresholds array must not contain NULLs" msgstr "масив границь не повинен містити NULL" -#: utils/adt/arrayfuncs.c:6946 +#: utils/adt/arrayfuncs.c:6926 #, c-format msgid "number of elements to trim must be between 0 and %d" msgstr "кількість елементів для обрізки має бути між 0 і %d" @@ -23227,22 +24143,22 @@ msgstr "індекс елементу масиву має бути цілим ч msgid "array subscript in assignment must not be null" msgstr "підрядковий символ масиву у призначенні не може бути NULL" -#: utils/adt/arrayutils.c:155 +#: utils/adt/arrayutils.c:140 #, c-format msgid "array lower bound is too large: %d" msgstr "нижня границя масиву занадто велика: %d" -#: utils/adt/arrayutils.c:257 +#: utils/adt/arrayutils.c:242 #, c-format msgid "typmod array must be type cstring[]" msgstr "масив typmod повинен мати тип cstring[]" -#: utils/adt/arrayutils.c:262 +#: utils/adt/arrayutils.c:247 #, c-format msgid "typmod array must be one-dimensional" msgstr "масив typmod повинен бути одновимірним" -#: utils/adt/arrayutils.c:267 +#: utils/adt/arrayutils.c:252 #, c-format msgid "typmod array must not contain nulls" msgstr "масив typmod не повинен містити елементи nulls" @@ -23253,48 +24169,52 @@ msgid "encoding conversion from %s to ASCII not supported" msgstr "перетворення кодування з %s в ASCII не підтримується" #. translator: first %s is inet or cidr -#: utils/adt/bool.c:153 utils/adt/cash.c:277 utils/adt/datetime.c:4017 -#: utils/adt/float.c:206 utils/adt/float.c:293 utils/adt/float.c:307 -#: utils/adt/float.c:412 utils/adt/float.c:495 utils/adt/float.c:509 +#: utils/adt/bool.c:149 utils/adt/cash.c:354 utils/adt/datetime.c:4142 +#: utils/adt/float.c:200 utils/adt/float.c:287 utils/adt/float.c:301 +#: utils/adt/float.c:406 utils/adt/float.c:489 utils/adt/float.c:503 #: utils/adt/geo_ops.c:250 utils/adt/geo_ops.c:335 utils/adt/geo_ops.c:974 #: utils/adt/geo_ops.c:1417 utils/adt/geo_ops.c:1454 utils/adt/geo_ops.c:1462 #: utils/adt/geo_ops.c:3428 utils/adt/geo_ops.c:4650 utils/adt/geo_ops.c:4665 #: utils/adt/geo_ops.c:4672 utils/adt/int.c:174 utils/adt/int.c:186 -#: utils/adt/jsonpath.c:183 utils/adt/mac.c:94 utils/adt/mac8.c:225 -#: utils/adt/network.c:99 utils/adt/numeric.c:795 utils/adt/numeric.c:7136 -#: utils/adt/numeric.c:7339 utils/adt/numeric.c:8286 utils/adt/numutils.c:357 -#: utils/adt/numutils.c:619 utils/adt/numutils.c:881 utils/adt/numutils.c:920 -#: utils/adt/numutils.c:942 utils/adt/numutils.c:1006 utils/adt/numutils.c:1028 -#: utils/adt/pg_lsn.c:74 utils/adt/tid.c:72 utils/adt/tid.c:80 -#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:494 -#: utils/adt/uuid.c:135 utils/adt/xid8funcs.c:362 +#: utils/adt/jsonpath.c:185 utils/adt/mac.c:94 utils/adt/mac8.c:226 +#: utils/adt/network.c:99 utils/adt/numeric.c:803 utils/adt/numeric.c:7221 +#: utils/adt/numeric.c:7424 utils/adt/numeric.c:8371 utils/adt/numutils.c:356 +#: utils/adt/numutils.c:618 utils/adt/numutils.c:880 utils/adt/numutils.c:919 +#: utils/adt/numutils.c:941 utils/adt/numutils.c:1005 utils/adt/numutils.c:1027 +#: utils/adt/pg_lsn.c:73 utils/adt/tid.c:72 utils/adt/tid.c:80 +#: utils/adt/tid.c:94 utils/adt/tid.c:103 utils/adt/timestamp.c:510 +#: utils/adt/uuid.c:140 utils/adt/xid8funcs.c:360 #, c-format msgid "invalid input syntax for type %s: \"%s\"" msgstr "неприпустимий синтаксис для типу %s: \"%s\"" -#: utils/adt/cash.c:215 utils/adt/cash.c:240 utils/adt/cash.c:250 -#: utils/adt/cash.c:290 utils/adt/int.c:180 utils/adt/numutils.c:351 -#: utils/adt/numutils.c:613 utils/adt/numutils.c:875 utils/adt/numutils.c:926 -#: utils/adt/numutils.c:965 utils/adt/numutils.c:1012 +#: utils/adt/cash.c:98 utils/adt/cash.c:111 utils/adt/cash.c:124 +#: utils/adt/cash.c:137 utils/adt/cash.c:150 #, c-format -msgid "value \"%s\" is out of range for type %s" -msgstr "значення \"%s\" поза діапазоном для типу %s" +msgid "money out of range" +msgstr "" -#: utils/adt/cash.c:652 utils/adt/cash.c:702 utils/adt/cash.c:753 -#: utils/adt/cash.c:802 utils/adt/cash.c:854 utils/adt/cash.c:904 -#: utils/adt/float.c:105 utils/adt/int.c:843 utils/adt/int.c:959 -#: utils/adt/int.c:1039 utils/adt/int.c:1101 utils/adt/int.c:1139 -#: utils/adt/int.c:1167 utils/adt/int8.c:515 utils/adt/int8.c:573 -#: utils/adt/int8.c:943 utils/adt/int8.c:1023 utils/adt/int8.c:1085 -#: utils/adt/int8.c:1165 utils/adt/numeric.c:3175 utils/adt/numeric.c:3198 -#: utils/adt/numeric.c:3283 utils/adt/numeric.c:3301 utils/adt/numeric.c:3397 -#: utils/adt/numeric.c:8835 utils/adt/numeric.c:9148 utils/adt/numeric.c:9496 -#: utils/adt/numeric.c:9612 utils/adt/numeric.c:11122 -#: utils/adt/timestamp.c:3430 +#: utils/adt/cash.c:161 utils/adt/cash.c:723 utils/adt/float.c:99 +#: utils/adt/int.c:843 utils/adt/int.c:959 utils/adt/int.c:1039 +#: utils/adt/int.c:1101 utils/adt/int.c:1139 utils/adt/int.c:1167 +#: utils/adt/int8.c:514 utils/adt/int8.c:572 utils/adt/int8.c:942 +#: utils/adt/int8.c:1022 utils/adt/int8.c:1084 utils/adt/int8.c:1164 +#: utils/adt/numeric.c:3191 utils/adt/numeric.c:3214 utils/adt/numeric.c:3299 +#: utils/adt/numeric.c:3317 utils/adt/numeric.c:3413 utils/adt/numeric.c:8920 +#: utils/adt/numeric.c:9233 utils/adt/numeric.c:9581 utils/adt/numeric.c:9697 +#: utils/adt/numeric.c:11208 utils/adt/timestamp.c:3713 #, c-format msgid "division by zero" msgstr "ділення на нуль" +#: utils/adt/cash.c:292 utils/adt/cash.c:317 utils/adt/cash.c:327 +#: utils/adt/cash.c:367 utils/adt/int.c:180 utils/adt/numutils.c:350 +#: utils/adt/numutils.c:612 utils/adt/numutils.c:874 utils/adt/numutils.c:925 +#: utils/adt/numutils.c:964 utils/adt/numutils.c:1011 +#, c-format +msgid "value \"%s\" is out of range for type %s" +msgstr "значення \"%s\" поза діапазоном для типу %s" + #: utils/adt/char.c:197 #, c-format msgid "\"char\" out of range" @@ -23305,185 +24225,211 @@ msgstr "значення \"char\" поза діапазоном" msgid "could not compute %s hash: %s" msgstr "не вдалося обчислити %s хеш: %s" -#: utils/adt/date.c:63 utils/adt/timestamp.c:100 utils/adt/varbit.c:105 -#: utils/adt/varchar.c:49 +#: utils/adt/date.c:64 utils/adt/timestamp.c:116 utils/adt/varbit.c:105 +#: utils/adt/varchar.c:48 #, c-format msgid "invalid type modifier" msgstr "неприпустимий тип модифікатора" -#: utils/adt/date.c:75 +#: utils/adt/date.c:76 #, c-format msgid "TIME(%d)%s precision must not be negative" msgstr "TIME(%d)%s точність не повинна бути від'ємною" -#: utils/adt/date.c:81 +#: utils/adt/date.c:82 #, c-format msgid "TIME(%d)%s precision reduced to maximum allowed, %d" msgstr "TIME(%d)%s точність зменшена до дозволеного максимуму, %d" -#: utils/adt/date.c:166 utils/adt/date.c:174 utils/adt/formatting.c:4241 -#: utils/adt/formatting.c:4250 utils/adt/formatting.c:4363 -#: utils/adt/formatting.c:4373 +#: utils/adt/date.c:167 utils/adt/date.c:175 utils/adt/formatting.c:4424 +#: utils/adt/formatting.c:4433 utils/adt/formatting.c:4538 +#: utils/adt/formatting.c:4548 #, c-format msgid "date out of range: \"%s\"" msgstr "дата поза діапазоном: \"%s\"" -#: utils/adt/date.c:221 utils/adt/date.c:519 utils/adt/date.c:543 -#: utils/adt/rangetypes.c:1577 utils/adt/rangetypes.c:1592 utils/adt/xml.c:2470 +#: utils/adt/date.c:222 utils/adt/date.c:520 utils/adt/date.c:544 +#: utils/adt/rangetypes.c:1584 utils/adt/rangetypes.c:1599 utils/adt/xml.c:2552 #, c-format msgid "date out of range" msgstr "дата поза діапазоном" -#: utils/adt/date.c:267 utils/adt/timestamp.c:582 +#: utils/adt/date.c:268 utils/adt/timestamp.c:598 #, c-format msgid "date field value out of range: %d-%02d-%02d" msgstr "значення поля типу date поза діапазоном: %d-%02d-%02d" -#: utils/adt/date.c:274 utils/adt/date.c:283 utils/adt/timestamp.c:588 +#: utils/adt/date.c:275 utils/adt/date.c:284 utils/adt/timestamp.c:604 #, c-format msgid "date out of range: %d-%02d-%02d" msgstr "дата поза діапазоном: %d-%02d-%02d" -#: utils/adt/date.c:494 +#: utils/adt/date.c:495 #, c-format msgid "cannot subtract infinite dates" msgstr "віднімати безкінечні дати не можна" -#: utils/adt/date.c:592 utils/adt/date.c:655 utils/adt/date.c:691 -#: utils/adt/date.c:2885 utils/adt/date.c:2895 +#: utils/adt/date.c:593 utils/adt/date.c:656 utils/adt/date.c:692 +#: utils/adt/date.c:2906 utils/adt/date.c:2916 #, c-format msgid "date out of range for timestamp" msgstr "для позначки часу дата поза діапазоном" -#: utils/adt/date.c:1121 utils/adt/date.c:1204 utils/adt/date.c:1220 -#: utils/adt/date.c:2206 utils/adt/date.c:2990 utils/adt/timestamp.c:4143 -#: utils/adt/timestamp.c:4336 utils/adt/timestamp.c:4478 -#: utils/adt/timestamp.c:4731 utils/adt/timestamp.c:4932 -#: utils/adt/timestamp.c:4979 utils/adt/timestamp.c:5203 -#: utils/adt/timestamp.c:5250 utils/adt/timestamp.c:5380 +#: utils/adt/date.c:1122 utils/adt/date.c:1205 utils/adt/date.c:1221 +#: utils/adt/date.c:2215 utils/adt/date.c:3011 utils/adt/timestamp.c:4726 +#: utils/adt/timestamp.c:4941 utils/adt/timestamp.c:5089 +#: utils/adt/timestamp.c:5342 utils/adt/timestamp.c:5543 +#: utils/adt/timestamp.c:5590 utils/adt/timestamp.c:5814 +#: utils/adt/timestamp.c:5861 utils/adt/timestamp.c:5941 +#: utils/adt/timestamp.c:6070 #, c-format msgid "unit \"%s\" not supported for type %s" msgstr "одиниця \"%s\" не підтримується для типу %s" -#: utils/adt/date.c:1229 utils/adt/date.c:2222 utils/adt/date.c:3010 -#: utils/adt/timestamp.c:4157 utils/adt/timestamp.c:4353 -#: utils/adt/timestamp.c:4492 utils/adt/timestamp.c:4691 -#: utils/adt/timestamp.c:4988 utils/adt/timestamp.c:5259 -#: utils/adt/timestamp.c:5441 +#: utils/adt/date.c:1230 utils/adt/date.c:2231 utils/adt/date.c:3031 +#: utils/adt/timestamp.c:4740 utils/adt/timestamp.c:4958 +#: utils/adt/timestamp.c:5103 utils/adt/timestamp.c:5302 +#: utils/adt/timestamp.c:5599 utils/adt/timestamp.c:5870 +#: utils/adt/timestamp.c:5911 utils/adt/timestamp.c:6131 #, c-format msgid "unit \"%s\" not recognized for type %s" msgstr "нерозпізнана одиниця \"%s\" для типу %s" -#: utils/adt/date.c:1313 utils/adt/date.c:1359 utils/adt/date.c:1918 -#: utils/adt/date.c:1949 utils/adt/date.c:1978 utils/adt/date.c:2848 -#: utils/adt/date.c:3080 utils/adt/datetime.c:424 utils/adt/datetime.c:1809 -#: utils/adt/formatting.c:4081 utils/adt/formatting.c:4117 -#: utils/adt/formatting.c:4210 utils/adt/formatting.c:4339 utils/adt/json.c:467 -#: utils/adt/json.c:506 utils/adt/timestamp.c:232 utils/adt/timestamp.c:264 -#: utils/adt/timestamp.c:700 utils/adt/timestamp.c:709 -#: utils/adt/timestamp.c:787 utils/adt/timestamp.c:820 -#: utils/adt/timestamp.c:2933 utils/adt/timestamp.c:2954 -#: utils/adt/timestamp.c:2967 utils/adt/timestamp.c:2978 -#: utils/adt/timestamp.c:2984 utils/adt/timestamp.c:2992 -#: utils/adt/timestamp.c:3053 utils/adt/timestamp.c:3076 -#: utils/adt/timestamp.c:3089 utils/adt/timestamp.c:3103 -#: utils/adt/timestamp.c:3111 utils/adt/timestamp.c:3119 -#: utils/adt/timestamp.c:3847 utils/adt/timestamp.c:3971 -#: utils/adt/timestamp.c:4061 utils/adt/timestamp.c:4151 -#: utils/adt/timestamp.c:4244 utils/adt/timestamp.c:4347 -#: utils/adt/timestamp.c:4796 utils/adt/timestamp.c:5070 -#: utils/adt/timestamp.c:5509 utils/adt/timestamp.c:5519 -#: utils/adt/timestamp.c:5524 utils/adt/timestamp.c:5530 -#: utils/adt/timestamp.c:5563 utils/adt/timestamp.c:5650 -#: utils/adt/timestamp.c:5691 utils/adt/timestamp.c:5695 -#: utils/adt/timestamp.c:5749 utils/adt/timestamp.c:5753 -#: utils/adt/timestamp.c:5759 utils/adt/timestamp.c:5793 utils/adt/xml.c:2492 -#: utils/adt/xml.c:2499 utils/adt/xml.c:2519 utils/adt/xml.c:2526 +#: utils/adt/date.c:1314 utils/adt/date.c:1360 utils/adt/date.c:1919 +#: utils/adt/date.c:1950 utils/adt/date.c:1979 utils/adt/date.c:2869 +#: utils/adt/date.c:3101 utils/adt/datetime.c:422 utils/adt/datetime.c:1807 +#: utils/adt/formatting.c:4269 utils/adt/formatting.c:4305 +#: utils/adt/formatting.c:4392 utils/adt/formatting.c:4514 utils/adt/json.c:366 +#: utils/adt/json.c:405 utils/adt/timestamp.c:248 utils/adt/timestamp.c:280 +#: utils/adt/timestamp.c:716 utils/adt/timestamp.c:725 +#: utils/adt/timestamp.c:803 utils/adt/timestamp.c:836 +#: utils/adt/timestamp.c:3066 utils/adt/timestamp.c:3075 +#: utils/adt/timestamp.c:3092 utils/adt/timestamp.c:3097 +#: utils/adt/timestamp.c:3116 utils/adt/timestamp.c:3129 +#: utils/adt/timestamp.c:3140 utils/adt/timestamp.c:3146 +#: utils/adt/timestamp.c:3152 utils/adt/timestamp.c:3157 +#: utils/adt/timestamp.c:3210 utils/adt/timestamp.c:3219 +#: utils/adt/timestamp.c:3240 utils/adt/timestamp.c:3245 +#: utils/adt/timestamp.c:3266 utils/adt/timestamp.c:3279 +#: utils/adt/timestamp.c:3293 utils/adt/timestamp.c:3301 +#: utils/adt/timestamp.c:3307 utils/adt/timestamp.c:3312 +#: utils/adt/timestamp.c:4380 utils/adt/timestamp.c:4532 +#: utils/adt/timestamp.c:4608 utils/adt/timestamp.c:4644 +#: utils/adt/timestamp.c:4734 utils/adt/timestamp.c:4813 +#: utils/adt/timestamp.c:4849 utils/adt/timestamp.c:4952 +#: utils/adt/timestamp.c:5407 utils/adt/timestamp.c:5681 +#: utils/adt/timestamp.c:6199 utils/adt/timestamp.c:6209 +#: utils/adt/timestamp.c:6214 utils/adt/timestamp.c:6220 +#: utils/adt/timestamp.c:6260 utils/adt/timestamp.c:6347 +#: utils/adt/timestamp.c:6388 utils/adt/timestamp.c:6392 +#: utils/adt/timestamp.c:6446 utils/adt/timestamp.c:6450 +#: utils/adt/timestamp.c:6456 utils/adt/timestamp.c:6497 utils/adt/xml.c:2574 +#: utils/adt/xml.c:2581 utils/adt/xml.c:2601 utils/adt/xml.c:2608 #, c-format msgid "timestamp out of range" msgstr "позначка часу поза діапазоном" -#: utils/adt/date.c:1535 utils/adt/date.c:2343 utils/adt/formatting.c:4431 +#: utils/adt/date.c:1536 utils/adt/date.c:2352 utils/adt/formatting.c:4597 #, c-format msgid "time out of range" msgstr "час поза діапазоном" -#: utils/adt/date.c:1587 utils/adt/timestamp.c:597 +#: utils/adt/date.c:1588 utils/adt/timestamp.c:613 #, c-format msgid "time field value out of range: %d:%02d:%02g" msgstr "значення поля типу time поза діапазоном: %d:%02d:%02g" -#: utils/adt/date.c:2107 utils/adt/date.c:2647 utils/adt/float.c:1042 -#: utils/adt/float.c:1118 utils/adt/int.c:635 utils/adt/int.c:682 -#: utils/adt/int.c:717 utils/adt/int8.c:414 utils/adt/numeric.c:2579 -#: utils/adt/timestamp.c:3501 utils/adt/timestamp.c:3528 -#: utils/adt/timestamp.c:3559 +#: utils/adt/date.c:2020 +#, c-format +msgid "cannot convert infinite interval to time" +msgstr "не можна перетворити нескінченний інтервал у час" + +#: utils/adt/date.c:2061 utils/adt/date.c:2605 +#, c-format +msgid "cannot add infinite interval to time" +msgstr "не можна додати нескінченний інтервал до часу" + +#: utils/adt/date.c:2084 utils/adt/date.c:2632 +#, c-format +msgid "cannot subtract infinite interval from time" +msgstr "не можна відняти від часу нескінченний інтервал" + +#: utils/adt/date.c:2115 utils/adt/date.c:2667 utils/adt/float.c:1036 +#: utils/adt/float.c:1112 utils/adt/int.c:635 utils/adt/int.c:682 +#: utils/adt/int.c:717 utils/adt/int8.c:413 utils/adt/numeric.c:2595 +#: utils/adt/timestamp.c:3810 utils/adt/timestamp.c:3847 +#: utils/adt/timestamp.c:3888 #, c-format msgid "invalid preceding or following size in window function" msgstr "неприпустимий розмір preceding або following у віконній функції" -#: utils/adt/date.c:2351 +#: utils/adt/date.c:2360 #, c-format msgid "time zone displacement out of range" msgstr "зсув часового поясу поза діапазоном" -#: utils/adt/date.c:3111 utils/adt/timestamp.c:5552 utils/adt/timestamp.c:5782 +#: utils/adt/date.c:3132 utils/adt/timestamp.c:6242 utils/adt/timestamp.c:6479 +#, c-format +msgid "interval time zone \"%s\" must be finite" +msgstr "часовий пояс інтервалу \"%s\" має бути скінченним" + +#: utils/adt/date.c:3139 utils/adt/timestamp.c:6249 utils/adt/timestamp.c:6486 #, c-format msgid "interval time zone \"%s\" must not include months or days" msgstr "інтервал \"%s\", який задає часовий пояс, не повинен включати місяці або дні" -#: utils/adt/datetime.c:3223 utils/adt/datetime.c:4002 -#: utils/adt/datetime.c:4008 utils/adt/timestamp.c:512 +#: utils/adt/datetime.c:3232 utils/adt/datetime.c:4127 +#: utils/adt/datetime.c:4133 utils/adt/timestamp.c:528 #, c-format msgid "time zone \"%s\" not recognized" msgstr "часовий пояс \"%s\" не розпізнаний" -#: utils/adt/datetime.c:3976 utils/adt/datetime.c:3983 +#: utils/adt/datetime.c:4101 utils/adt/datetime.c:4108 #, c-format msgid "date/time field value out of range: \"%s\"" msgstr "значення поля типу дата/час поза діапазоном: \"%s\"" -#: utils/adt/datetime.c:3985 +#: utils/adt/datetime.c:4110 #, c-format msgid "Perhaps you need a different \"datestyle\" setting." msgstr "Можливо, вам потрібні інші налаштування \"datestyle\"." -#: utils/adt/datetime.c:3990 +#: utils/adt/datetime.c:4115 #, c-format msgid "interval field value out of range: \"%s\"" msgstr "значення поля типу інтервал, поза діапазоном: \"%s\"" -#: utils/adt/datetime.c:3996 +#: utils/adt/datetime.c:4121 #, c-format msgid "time zone displacement out of range: \"%s\"" msgstr "зміщення часового поясу, поза діапазоном: \"%s\"" -#: utils/adt/datetime.c:4010 +#: utils/adt/datetime.c:4135 #, c-format msgid "This time zone name appears in the configuration file for time zone abbreviation \"%s\"." msgstr "Це ім'я часового поясу з'являється у файлі конфігурації часового поясу з кодом \"%s\"." -#: utils/adt/datum.c:91 utils/adt/datum.c:103 +#: utils/adt/datum.c:90 utils/adt/datum.c:102 #, c-format msgid "invalid Datum pointer" msgstr "неприпустимий вказівник Datum" -#: utils/adt/dbsize.c:761 utils/adt/dbsize.c:837 +#: utils/adt/dbsize.c:764 utils/adt/dbsize.c:840 #, c-format msgid "invalid size: \"%s\"" msgstr "неприпустимий розмір: \"%s\"" -#: utils/adt/dbsize.c:838 +#: utils/adt/dbsize.c:841 #, c-format msgid "Invalid size unit: \"%s\"." msgstr "Неприпустима одиниця вимірювання розміру: \"%s\"." -#: utils/adt/dbsize.c:839 +#: utils/adt/dbsize.c:842 #, c-format msgid "Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\"." msgstr "Припустимі одиниці вимірювання: \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", і \"PB\"." -#: utils/adt/domains.c:92 +#: utils/adt/domains.c:95 #, c-format msgid "type %s is not a domain" msgstr "тип %s не є доменом" @@ -23533,10 +24479,10 @@ msgstr "неприпустима скінченна послідовність b msgid "Input data is missing padding, is truncated, or is otherwise corrupted." msgstr "Вхідні дані позбавлені можливості заповнення, скорочені, або пошкоджені іншим чином." -#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:648 -#: utils/adt/varlena.c:331 utils/adt/varlena.c:372 jsonpath_gram.y:528 -#: jsonpath_scan.l:629 jsonpath_scan.l:640 jsonpath_scan.l:650 -#: jsonpath_scan.l:701 +#: utils/adt/encode.c:492 utils/adt/encode.c:557 utils/adt/jsonfuncs.c:659 +#: utils/adt/varlena.c:333 utils/adt/varlena.c:374 jsonpath_gram.y:266 +#: jsonpath_gram.y:598 jsonpath_scan.l:640 jsonpath_scan.l:651 +#: jsonpath_scan.l:661 jsonpath_scan.l:712 #, c-format msgid "invalid input syntax for type %s" msgstr "неприпустимий вхідний синтаксис для типу %s" @@ -23573,353 +24519,348 @@ msgstr "не вдалося визначити фактичний тип пер msgid "enum %s contains no values" msgstr "перелік %s не містить значень" -#: utils/adt/float.c:89 +#: utils/adt/float.c:83 #, c-format msgid "value out of range: overflow" msgstr "значення поза діапазоном: надлишок" -#: utils/adt/float.c:97 +#: utils/adt/float.c:91 #, c-format msgid "value out of range: underflow" msgstr "значення поза діапазоном: недостача" -#: utils/adt/float.c:286 +#: utils/adt/float.c:280 #, c-format msgid "\"%s\" is out of range for type real" msgstr "\"%s\" поза діапазоном для дійсного типу" -#: utils/adt/float.c:488 +#: utils/adt/float.c:482 #, c-format msgid "\"%s\" is out of range for type double precision" msgstr "\"%s\" поза діапазоном для типу double precision" -#: utils/adt/float.c:1253 utils/adt/float.c:1327 utils/adt/int.c:355 +#: utils/adt/float.c:1247 utils/adt/float.c:1321 utils/adt/int.c:355 #: utils/adt/int.c:893 utils/adt/int.c:915 utils/adt/int.c:929 #: utils/adt/int.c:943 utils/adt/int.c:975 utils/adt/int.c:1213 -#: utils/adt/int8.c:1278 utils/adt/numeric.c:4500 utils/adt/numeric.c:4505 +#: utils/adt/int8.c:1277 utils/adt/numeric.c:4593 utils/adt/numeric.c:4598 #, c-format msgid "smallint out of range" msgstr "двобайтове ціле поза діапазоном" -#: utils/adt/float.c:1453 utils/adt/numeric.c:3693 utils/adt/numeric.c:10027 +#: utils/adt/float.c:1447 utils/adt/numeric.c:3709 utils/adt/numeric.c:10112 #, c-format msgid "cannot take square root of a negative number" msgstr "вилучити квадратний корінь від'ємного числа не можна" -#: utils/adt/float.c:1521 utils/adt/numeric.c:3981 utils/adt/numeric.c:4093 +#: utils/adt/float.c:1515 utils/adt/numeric.c:3997 utils/adt/numeric.c:4109 #, c-format msgid "zero raised to a negative power is undefined" msgstr "нуль у від'ємному ступені дає невизначеність" -#: utils/adt/float.c:1525 utils/adt/numeric.c:3985 utils/adt/numeric.c:10918 +#: utils/adt/float.c:1519 utils/adt/numeric.c:4001 utils/adt/numeric.c:11003 #, c-format msgid "a negative number raised to a non-integer power yields a complex result" msgstr "від'ємне число у не цілому ступені дає комплексний результат" -#: utils/adt/float.c:1701 utils/adt/float.c:1734 utils/adt/numeric.c:3893 -#: utils/adt/numeric.c:10698 +#: utils/adt/float.c:1695 utils/adt/float.c:1728 utils/adt/numeric.c:3909 +#: utils/adt/numeric.c:10783 #, c-format msgid "cannot take logarithm of zero" msgstr "обчислити логарифм нуля не можна" -#: utils/adt/float.c:1705 utils/adt/float.c:1738 utils/adt/numeric.c:3831 -#: utils/adt/numeric.c:3888 utils/adt/numeric.c:10702 +#: utils/adt/float.c:1699 utils/adt/float.c:1732 utils/adt/numeric.c:3847 +#: utils/adt/numeric.c:3904 utils/adt/numeric.c:10787 #, c-format msgid "cannot take logarithm of a negative number" msgstr "обчислити логарифм від'ємного числа не можна" -#: utils/adt/float.c:1771 utils/adt/float.c:1802 utils/adt/float.c:1897 -#: utils/adt/float.c:1924 utils/adt/float.c:1952 utils/adt/float.c:1979 -#: utils/adt/float.c:2126 utils/adt/float.c:2163 utils/adt/float.c:2333 -#: utils/adt/float.c:2389 utils/adt/float.c:2454 utils/adt/float.c:2511 -#: utils/adt/float.c:2702 utils/adt/float.c:2726 +#: utils/adt/float.c:1765 utils/adt/float.c:1796 utils/adt/float.c:1891 +#: utils/adt/float.c:1918 utils/adt/float.c:1946 utils/adt/float.c:1973 +#: utils/adt/float.c:2120 utils/adt/float.c:2157 utils/adt/float.c:2327 +#: utils/adt/float.c:2383 utils/adt/float.c:2448 utils/adt/float.c:2505 +#: utils/adt/float.c:2696 utils/adt/float.c:2720 #, c-format msgid "input is out of range" msgstr "введене значення поза діапазоном" -#: utils/adt/float.c:2867 -#, c-format -msgid "setseed parameter %g is out of allowed range [-1,1]" -msgstr "параметр setseed %g поза допустимим діапазоном [-1,1]" - -#: utils/adt/float.c:4095 utils/adt/numeric.c:1841 +#: utils/adt/float.c:4000 utils/adt/numeric.c:1857 #, c-format msgid "count must be greater than zero" msgstr "лічильник повинен бути більше нуля" -#: utils/adt/float.c:4100 utils/adt/numeric.c:1852 +#: utils/adt/float.c:4005 utils/adt/numeric.c:1868 #, c-format msgid "operand, lower bound, and upper bound cannot be NaN" msgstr "операнд, нижня границя і верхня границя не можуть бути NaN" -#: utils/adt/float.c:4106 utils/adt/numeric.c:1857 +#: utils/adt/float.c:4011 utils/adt/numeric.c:1873 #, c-format msgid "lower and upper bounds must be finite" msgstr "нижня і верхня границі повинні бути скінченними" -#: utils/adt/float.c:4172 utils/adt/numeric.c:1871 +#: utils/adt/float.c:4077 utils/adt/numeric.c:1887 #, c-format msgid "lower bound cannot equal upper bound" msgstr "нижня границя не може дорівнювати верхній границі" -#: utils/adt/formatting.c:519 +#: utils/adt/formatting.c:530 #, c-format msgid "invalid format specification for an interval value" msgstr "неприпустима специфікація формату для цілого значення" -#: utils/adt/formatting.c:520 +#: utils/adt/formatting.c:531 #, c-format msgid "Intervals are not tied to specific calendar dates." msgstr "Інтервали не зв'язуються з певними календарними датами." -#: utils/adt/formatting.c:1150 +#: utils/adt/formatting.c:1161 #, c-format msgid "\"EEEE\" must be the last pattern used" msgstr "\"EEEE\" повинно бути останнім використаним шаблоном" -#: utils/adt/formatting.c:1158 +#: utils/adt/formatting.c:1169 #, c-format msgid "\"9\" must be ahead of \"PR\"" msgstr "\"9\" повинна бути до \"PR\"" -#: utils/adt/formatting.c:1174 +#: utils/adt/formatting.c:1185 #, c-format msgid "\"0\" must be ahead of \"PR\"" msgstr "\"0\" повинен бути до \"PR\"" -#: utils/adt/formatting.c:1201 +#: utils/adt/formatting.c:1212 #, c-format msgid "multiple decimal points" msgstr "численні десяткові точки" -#: utils/adt/formatting.c:1205 utils/adt/formatting.c:1288 +#: utils/adt/formatting.c:1216 utils/adt/formatting.c:1299 #, c-format msgid "cannot use \"V\" and decimal point together" msgstr "використовувати \"V\" і десяткову точку разом, не можна" -#: utils/adt/formatting.c:1217 +#: utils/adt/formatting.c:1228 #, c-format msgid "cannot use \"S\" twice" msgstr "використовувати \"S\" двічі, не можна" -#: utils/adt/formatting.c:1221 +#: utils/adt/formatting.c:1232 #, c-format msgid "cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together" msgstr "використовувати \"S\" і \"PL\"/\"MI\"/\"SG\"/\"PR\" разом, не можна" -#: utils/adt/formatting.c:1241 +#: utils/adt/formatting.c:1252 #, c-format msgid "cannot use \"S\" and \"MI\" together" msgstr "використовувати \"S\" і \"MI\" разом, не можна" -#: utils/adt/formatting.c:1251 +#: utils/adt/formatting.c:1262 #, c-format msgid "cannot use \"S\" and \"PL\" together" msgstr "не можна використовувати \"S\" і \"PL\" разом" -#: utils/adt/formatting.c:1261 +#: utils/adt/formatting.c:1272 #, c-format msgid "cannot use \"S\" and \"SG\" together" msgstr "не можна використовувати \"S\" і \"SG\" разом" -#: utils/adt/formatting.c:1270 +#: utils/adt/formatting.c:1281 #, c-format msgid "cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together" msgstr "не можна використовувати \"PR\" і \"S\"/\"PL\"/\"MI\"/\"SG\" разом" -#: utils/adt/formatting.c:1296 +#: utils/adt/formatting.c:1307 #, c-format msgid "cannot use \"EEEE\" twice" msgstr "не можна використовувати \"EEEE\" двічі" -#: utils/adt/formatting.c:1302 +#: utils/adt/formatting.c:1313 #, c-format msgid "\"EEEE\" is incompatible with other formats" msgstr "\"EEEE\" є несумісним з іншими форматами" -#: utils/adt/formatting.c:1303 +#: utils/adt/formatting.c:1314 #, c-format msgid "\"EEEE\" may only be used together with digit and decimal point patterns." msgstr "\"EEEE\" може використовуватись лише разом з шаблонами цифр і десяткової точки." -#: utils/adt/formatting.c:1387 +#: utils/adt/formatting.c:1398 #, c-format msgid "invalid datetime format separator: \"%s\"" msgstr "неприпустимий роздільник формату дати й часу: \"%s\"" -#: utils/adt/formatting.c:1514 +#: utils/adt/formatting.c:1525 #, c-format msgid "\"%s\" is not a number" msgstr "\"%s\" не є числом" -#: utils/adt/formatting.c:1592 +#: utils/adt/formatting.c:1603 #, c-format msgid "case conversion failed: %s" msgstr "помилка при перетворенні регістру: %s" -#: utils/adt/formatting.c:1646 utils/adt/formatting.c:1768 -#: utils/adt/formatting.c:1891 +#: utils/adt/formatting.c:1651 utils/adt/formatting.c:1799 +#: utils/adt/formatting.c:1989 #, c-format msgid "could not determine which collation to use for %s function" msgstr "не вдалося визначити який параметр сортування використати для функції %s" -#: utils/adt/formatting.c:2274 +#: utils/adt/formatting.c:2410 #, c-format msgid "invalid combination of date conventions" msgstr "неприпустиме поєднання стилів дат" -#: utils/adt/formatting.c:2275 +#: utils/adt/formatting.c:2411 #, c-format msgid "Do not mix Gregorian and ISO week date conventions in a formatting template." msgstr "Не змішуйте Gregorian і ISO стилі дат (тижнів) в одному шаблоні форматування." -#: utils/adt/formatting.c:2297 +#: utils/adt/formatting.c:2433 #, c-format msgid "conflicting values for \"%s\" field in formatting string" msgstr "конфліктуючі значення для \"%s\" поля в рядку форматування" -#: utils/adt/formatting.c:2299 +#: utils/adt/formatting.c:2435 #, c-format msgid "This value contradicts a previous setting for the same field type." msgstr "Це значення суперечить попередньому параметри для поля того ж типу." -#: utils/adt/formatting.c:2366 +#: utils/adt/formatting.c:2502 #, c-format msgid "source string too short for \"%s\" formatting field" msgstr "вихідний рядок занадто короткий для \"%s\" поля форматування" -#: utils/adt/formatting.c:2368 +#: utils/adt/formatting.c:2504 #, c-format msgid "Field requires %d characters, but only %d remain." msgstr "Поле потребує %d символів, але залишилось лише %d." -#: utils/adt/formatting.c:2370 utils/adt/formatting.c:2384 +#: utils/adt/formatting.c:2506 utils/adt/formatting.c:2520 #, c-format msgid "If your source string is not fixed-width, try using the \"FM\" modifier." msgstr "Якщо ваш вихідний рядок не має постійної ширини, спробуйте використати \"FM\" модифікатор." -#: utils/adt/formatting.c:2380 utils/adt/formatting.c:2393 -#: utils/adt/formatting.c:2614 +#: utils/adt/formatting.c:2516 utils/adt/formatting.c:2529 +#: utils/adt/formatting.c:2750 utils/adt/formatting.c:3650 #, c-format msgid "invalid value \"%s\" for \"%s\"" msgstr "неприпустиме значення \"%s\" для \"%s\"" -#: utils/adt/formatting.c:2382 +#: utils/adt/formatting.c:2518 #, c-format msgid "Field requires %d characters, but only %d could be parsed." msgstr "Поле потребує %d символів, але вдалося аналізувати лише %d." -#: utils/adt/formatting.c:2395 +#: utils/adt/formatting.c:2531 #, c-format msgid "Value must be an integer." msgstr "Значення повинне бути цілим числом." -#: utils/adt/formatting.c:2400 +#: utils/adt/formatting.c:2536 #, c-format msgid "value for \"%s\" in source string is out of range" msgstr "значення для \"%s\" у вихідному рядку поза діапазоном" -#: utils/adt/formatting.c:2402 +#: utils/adt/formatting.c:2538 #, c-format msgid "Value must be in the range %d to %d." msgstr "Значення повинне бути в діапазоні %d до %d." -#: utils/adt/formatting.c:2616 +#: utils/adt/formatting.c:2752 #, c-format msgid "The given value did not match any of the allowed values for this field." msgstr "Дане значення не відповідає жодному з доступних значень для цього поля." -#: utils/adt/formatting.c:2832 utils/adt/formatting.c:2852 -#: utils/adt/formatting.c:2872 utils/adt/formatting.c:2892 -#: utils/adt/formatting.c:2911 utils/adt/formatting.c:2930 -#: utils/adt/formatting.c:2954 utils/adt/formatting.c:2972 -#: utils/adt/formatting.c:2990 utils/adt/formatting.c:3008 -#: utils/adt/formatting.c:3025 utils/adt/formatting.c:3042 +#: utils/adt/formatting.c:2968 utils/adt/formatting.c:2988 +#: utils/adt/formatting.c:3008 utils/adt/formatting.c:3028 +#: utils/adt/formatting.c:3047 utils/adt/formatting.c:3066 +#: utils/adt/formatting.c:3090 utils/adt/formatting.c:3108 +#: utils/adt/formatting.c:3126 utils/adt/formatting.c:3144 +#: utils/adt/formatting.c:3161 utils/adt/formatting.c:3178 #, c-format msgid "localized string format value too long" msgstr "занадто довге значення формату локалізованого рядка" -#: utils/adt/formatting.c:3322 +#: utils/adt/formatting.c:3458 #, c-format msgid "unmatched format separator \"%c\"" msgstr "невідповідний роздільник формату \"%c\"" -#: utils/adt/formatting.c:3383 +#: utils/adt/formatting.c:3519 #, c-format msgid "unmatched format character \"%s\"" msgstr "невідповідний формат символу \"%s\"" -#: utils/adt/formatting.c:3491 +#: utils/adt/formatting.c:3652 #, c-format -msgid "formatting field \"%s\" is only supported in to_char" -msgstr "поле форматування \"%s\" підтримується лише в функції to_char" +msgid "Time zone abbreviation is not recognized." +msgstr "Абревіатуру часової зони не розпізнано." -#: utils/adt/formatting.c:3665 +#: utils/adt/formatting.c:3853 #, c-format msgid "invalid input string for \"Y,YYY\"" msgstr "неприпустимий вхідний рядок для \"Y,YYY\"" -#: utils/adt/formatting.c:3754 +#: utils/adt/formatting.c:3942 #, c-format msgid "input string is too short for datetime format" msgstr "вхідний рядок занадто короткий для формату дати й часу" -#: utils/adt/formatting.c:3762 +#: utils/adt/formatting.c:3950 #, c-format msgid "trailing characters remain in input string after datetime format" msgstr "символи наприкінці залишаються у вхідному рядку після формату дати й часу" -#: utils/adt/formatting.c:4319 +#: utils/adt/formatting.c:4494 #, c-format msgid "missing time zone in input string for type timestamptz" msgstr "пропущено часовий пояс у вхідному рядку для типу timestamptz" -#: utils/adt/formatting.c:4325 +#: utils/adt/formatting.c:4500 #, c-format msgid "timestamptz out of range" msgstr "timestamptz поза діапазоном" -#: utils/adt/formatting.c:4353 +#: utils/adt/formatting.c:4528 #, c-format msgid "datetime format is zoned but not timed" msgstr "формат дати й часу зоновано, але не приурочено" -#: utils/adt/formatting.c:4411 +#: utils/adt/formatting.c:4577 #, c-format msgid "missing time zone in input string for type timetz" msgstr "пропущено часовий пояс у вхідному рядку для типу timetz" -#: utils/adt/formatting.c:4417 +#: utils/adt/formatting.c:4583 #, c-format msgid "timetz out of range" msgstr "timetz поза діапазоном" -#: utils/adt/formatting.c:4443 +#: utils/adt/formatting.c:4609 #, c-format msgid "datetime format is not dated and not timed" msgstr "формат дати й часу не датований і не приурочений" -#: utils/adt/formatting.c:4575 +#: utils/adt/formatting.c:4786 #, c-format msgid "hour \"%d\" is invalid for the 12-hour clock" msgstr "година \"%d\" неприпустима для 12-часового годинника" -#: utils/adt/formatting.c:4577 +#: utils/adt/formatting.c:4788 #, c-format msgid "Use the 24-hour clock, or give an hour between 1 and 12." msgstr "Використайте 24-часовий годинник, або передавайте години від 1 до 12." -#: utils/adt/formatting.c:4689 +#: utils/adt/formatting.c:4900 #, c-format msgid "cannot calculate day of year without year information" msgstr "не можна обчислити день року без інформації про рік" -#: utils/adt/formatting.c:5621 +#: utils/adt/formatting.c:5852 #, c-format msgid "\"EEEE\" not supported for input" msgstr "\"EEEE\" не підтримується при введенні" -#: utils/adt/formatting.c:5633 +#: utils/adt/formatting.c:5864 #, c-format msgid "\"RN\" not supported for input" msgstr "\"RN\" не підтримується при введенні" @@ -23951,12 +24892,7 @@ msgstr "не вдалося знайти в файлі \"%s\": %m" msgid "file length too large" msgstr "довжина файлу завелика" -#: utils/adt/genfile.c:248 -#, c-format -msgid "must be superuser to read files with adminpack 1.0" -msgstr "щоб читати файли, використовуючи adminpack 1.0 потрібно бути суперкористувачем" - -#: utils/adt/genfile.c:702 +#: utils/adt/genfile.c:656 #, c-format msgid "tablespace with OID %u does not exist" msgstr "табличний простір з OID %u не існує" @@ -24012,560 +24948,645 @@ msgstr "повинно бути запитано мінімум 2 точки" msgid "invalid int2vector data" msgstr "неприпустимі дані int2vector" -#: utils/adt/int.c:1529 utils/adt/int8.c:1404 utils/adt/numeric.c:1749 -#: utils/adt/timestamp.c:5843 utils/adt/timestamp.c:5925 +#: utils/adt/int.c:1529 utils/adt/int8.c:1403 utils/adt/numeric.c:1765 +#: utils/adt/timestamp.c:6546 utils/adt/timestamp.c:6632 #, c-format msgid "step size cannot equal zero" msgstr "розмір кроку не може дорівнювати нулю" -#: utils/adt/int8.c:449 utils/adt/int8.c:472 utils/adt/int8.c:486 -#: utils/adt/int8.c:500 utils/adt/int8.c:531 utils/adt/int8.c:555 -#: utils/adt/int8.c:637 utils/adt/int8.c:705 utils/adt/int8.c:711 -#: utils/adt/int8.c:737 utils/adt/int8.c:751 utils/adt/int8.c:775 -#: utils/adt/int8.c:788 utils/adt/int8.c:900 utils/adt/int8.c:914 -#: utils/adt/int8.c:928 utils/adt/int8.c:959 utils/adt/int8.c:981 -#: utils/adt/int8.c:995 utils/adt/int8.c:1009 utils/adt/int8.c:1042 -#: utils/adt/int8.c:1056 utils/adt/int8.c:1070 utils/adt/int8.c:1101 -#: utils/adt/int8.c:1123 utils/adt/int8.c:1137 utils/adt/int8.c:1151 -#: utils/adt/int8.c:1313 utils/adt/int8.c:1348 utils/adt/numeric.c:4459 -#: utils/adt/rangetypes.c:1528 utils/adt/rangetypes.c:1541 +#: utils/adt/int8.c:448 utils/adt/int8.c:471 utils/adt/int8.c:485 +#: utils/adt/int8.c:499 utils/adt/int8.c:530 utils/adt/int8.c:554 +#: utils/adt/int8.c:636 utils/adt/int8.c:704 utils/adt/int8.c:710 +#: utils/adt/int8.c:736 utils/adt/int8.c:750 utils/adt/int8.c:774 +#: utils/adt/int8.c:787 utils/adt/int8.c:899 utils/adt/int8.c:913 +#: utils/adt/int8.c:927 utils/adt/int8.c:958 utils/adt/int8.c:980 +#: utils/adt/int8.c:994 utils/adt/int8.c:1008 utils/adt/int8.c:1041 +#: utils/adt/int8.c:1055 utils/adt/int8.c:1069 utils/adt/int8.c:1100 +#: utils/adt/int8.c:1122 utils/adt/int8.c:1136 utils/adt/int8.c:1150 +#: utils/adt/int8.c:1312 utils/adt/int8.c:1347 utils/adt/numeric.c:4542 +#: utils/adt/rangetypes.c:1535 utils/adt/rangetypes.c:1548 #: utils/adt/varbit.c:1676 #, c-format msgid "bigint out of range" msgstr "bigint поза діапазоном" -#: utils/adt/int8.c:1361 +#: utils/adt/int8.c:1360 #, c-format msgid "OID out of range" msgstr "OID поза діапазоном" -#: utils/adt/json.c:320 utils/adt/jsonb.c:781 +#: utils/adt/json.c:202 utils/adt/jsonb.c:664 #, c-format msgid "key value must be scalar, not array, composite, or json" msgstr "значенням ключа повинен бути скаляр, не масив, композитний тип, або json" -#: utils/adt/json.c:1113 utils/adt/json.c:1123 utils/fmgr/funcapi.c:2082 +#: utils/adt/json.c:1034 utils/adt/json.c:1044 utils/fmgr/funcapi.c:2090 #, c-format msgid "could not determine data type for argument %d" msgstr "не вдалося визначити тип даних для аргументу %d" -#: utils/adt/json.c:1146 utils/adt/json.c:1337 utils/adt/json.c:1513 -#: utils/adt/json.c:1591 utils/adt/jsonb.c:1432 utils/adt/jsonb.c:1522 +#: utils/adt/json.c:1067 utils/adt/json.c:1266 utils/adt/json.c:1449 +#: utils/adt/json.c:1527 utils/adt/jsonb.c:1333 utils/adt/jsonb.c:1423 #, c-format msgid "null value not allowed for object key" msgstr "значення null не дозволене для ключа об'єкту" -#: utils/adt/json.c:1189 utils/adt/json.c:1352 +#: utils/adt/json.c:1117 utils/adt/json.c:1288 #, c-format msgid "duplicate JSON object key value: %s" msgstr "дублікат ключа об'єкта JSON: %s" -#: utils/adt/json.c:1297 utils/adt/jsonb.c:1233 +#: utils/adt/json.c:1226 utils/adt/jsonb.c:1134 #, c-format msgid "argument list must have even number of elements" msgstr "список аргументів повинен мати парну кількість елементів" #. translator: %s is a SQL function name -#: utils/adt/json.c:1299 utils/adt/jsonb.c:1235 +#: utils/adt/json.c:1228 utils/adt/jsonb.c:1136 #, c-format msgid "The arguments of %s must consist of alternating keys and values." msgstr "Аргументи %s повинні складатись з альтернативних ключей і значень." -#: utils/adt/json.c:1491 utils/adt/jsonb.c:1410 +#: utils/adt/json.c:1427 utils/adt/jsonb.c:1311 #, c-format msgid "array must have two columns" msgstr "масив повинен мати два стовпця" -#: utils/adt/json.c:1580 utils/adt/jsonb.c:1511 +#: utils/adt/json.c:1516 utils/adt/jsonb.c:1412 #, c-format msgid "mismatched array dimensions" msgstr "невідповідні виміри масиву" -#: utils/adt/json.c:1764 utils/adt/jsonb_util.c:1958 +#: utils/adt/json.c:1702 utils/adt/jsonb_util.c:1956 #, c-format msgid "duplicate JSON object key value" msgstr "дублікат значення ключа об'єкту JSON" -#: utils/adt/jsonb.c:294 +#: utils/adt/jsonb.c:282 #, c-format msgid "string too long to represent as jsonb string" msgstr "рядок занадто довгий для представлення в якості рядка jsonb" -#: utils/adt/jsonb.c:295 +#: utils/adt/jsonb.c:283 #, c-format msgid "Due to an implementation restriction, jsonb strings cannot exceed %d bytes." msgstr "Через обмеження упровадження, рядки jsonb не можуть перевищувати %d байт." -#: utils/adt/jsonb.c:1252 +#: utils/adt/jsonb.c:1153 #, c-format msgid "argument %d: key must not be null" msgstr "аргумент %d: ключ не повинен бути null" -#: utils/adt/jsonb.c:1843 +#: utils/adt/jsonb.c:1744 #, c-format msgid "field name must not be null" msgstr "ім'я поля не повинно бути null" -#: utils/adt/jsonb.c:1905 +#: utils/adt/jsonb.c:1806 #, c-format msgid "object keys must be strings" msgstr "ключі об'єктів повинні бути рядками" -#: utils/adt/jsonb.c:2116 +#: utils/adt/jsonb.c:2017 #, c-format msgid "cannot cast jsonb null to type %s" msgstr "привести значення jsonb null до типу %s не можна" -#: utils/adt/jsonb.c:2117 +#: utils/adt/jsonb.c:2018 #, c-format msgid "cannot cast jsonb string to type %s" msgstr "привести рядок jsonb до типу %s не можна" -#: utils/adt/jsonb.c:2118 +#: utils/adt/jsonb.c:2019 #, c-format msgid "cannot cast jsonb numeric to type %s" msgstr "привести число jsonb до типу %s не можна" -#: utils/adt/jsonb.c:2119 +#: utils/adt/jsonb.c:2020 #, c-format msgid "cannot cast jsonb boolean to type %s" msgstr "привести логічне значення jsonb до типу %s не можна" -#: utils/adt/jsonb.c:2120 +#: utils/adt/jsonb.c:2021 #, c-format msgid "cannot cast jsonb array to type %s" msgstr "привести масив jsonb до типу %s не можна" -#: utils/adt/jsonb.c:2121 +#: utils/adt/jsonb.c:2022 #, c-format msgid "cannot cast jsonb object to type %s" msgstr "привести об'єкт jsonb до типу %s не можна" -#: utils/adt/jsonb.c:2122 +#: utils/adt/jsonb.c:2023 #, c-format msgid "cannot cast jsonb array or object to type %s" msgstr "привести масив або об'єкт jsonb до типу %s не можна" -#: utils/adt/jsonb_util.c:758 +#: utils/adt/jsonb_util.c:756 #, c-format msgid "number of jsonb object pairs exceeds the maximum allowed (%zu)" msgstr "кількість пар об'єкта jsonb перевищує максимально дозволену (%zu)" -#: utils/adt/jsonb_util.c:799 +#: utils/adt/jsonb_util.c:797 #, c-format msgid "number of jsonb array elements exceeds the maximum allowed (%zu)" msgstr "кількість елементів масиву jsonb перевищує максимально дозволену(%zu)" -#: utils/adt/jsonb_util.c:1673 utils/adt/jsonb_util.c:1693 +#: utils/adt/jsonb_util.c:1671 utils/adt/jsonb_util.c:1691 #, c-format msgid "total size of jsonb array elements exceeds the maximum of %d bytes" msgstr "загальний розмір елементів масиву jsonb перевищує максимум %d байт" -#: utils/adt/jsonb_util.c:1754 utils/adt/jsonb_util.c:1789 -#: utils/adt/jsonb_util.c:1809 +#: utils/adt/jsonb_util.c:1752 utils/adt/jsonb_util.c:1787 +#: utils/adt/jsonb_util.c:1807 #, c-format msgid "total size of jsonb object elements exceeds the maximum of %d bytes" msgstr "загальний розмір елементів об'єкту jsonb перевищує максимум %d байт" -#: utils/adt/jsonbsubs.c:70 utils/adt/jsonbsubs.c:151 +#: utils/adt/jsonbsubs.c:67 utils/adt/jsonbsubs.c:148 #, c-format msgid "jsonb subscript does not support slices" msgstr "підрядковий символ jsonb не підтримує сектори" -#: utils/adt/jsonbsubs.c:103 utils/adt/jsonbsubs.c:117 +#: utils/adt/jsonbsubs.c:100 utils/adt/jsonbsubs.c:114 #, c-format msgid "subscript type %s is not supported" msgstr "тип підписки %s не підтримується" -#: utils/adt/jsonbsubs.c:104 +#: utils/adt/jsonbsubs.c:101 #, c-format msgid "jsonb subscript must be coercible to only one type, integer or text." msgstr "підрядковий символ jsonb повинен бути приведений лише до одного типу, integer або text." -#: utils/adt/jsonbsubs.c:118 +#: utils/adt/jsonbsubs.c:115 #, c-format msgid "jsonb subscript must be coercible to either integer or text." msgstr "підрядковий символ jsonb повинен бути приведений або до integer, або до text." -#: utils/adt/jsonbsubs.c:139 +#: utils/adt/jsonbsubs.c:136 #, c-format msgid "jsonb subscript must have text type" msgstr "підрядковий символ jsonb повинен мати тип text" -#: utils/adt/jsonbsubs.c:207 +#: utils/adt/jsonbsubs.c:204 #, c-format msgid "jsonb subscript in assignment must not be null" msgstr "підрядковий символ jsonb у присвоєнні не повинен бути null" -#: utils/adt/jsonfuncs.c:572 utils/adt/jsonfuncs.c:821 -#: utils/adt/jsonfuncs.c:2429 utils/adt/jsonfuncs.c:2881 -#: utils/adt/jsonfuncs.c:3676 utils/adt/jsonfuncs.c:4018 +#: utils/adt/jsonfuncs.c:583 utils/adt/jsonfuncs.c:830 +#: utils/adt/jsonfuncs.c:2439 utils/adt/jsonfuncs.c:3015 +#: utils/adt/jsonfuncs.c:3948 utils/adt/jsonfuncs.c:4295 #, c-format msgid "cannot call %s on a scalar" msgstr "викликати %s зі скаляром, не можна" -#: utils/adt/jsonfuncs.c:577 utils/adt/jsonfuncs.c:806 -#: utils/adt/jsonfuncs.c:2883 utils/adt/jsonfuncs.c:3663 +#: utils/adt/jsonfuncs.c:588 utils/adt/jsonfuncs.c:815 +#: utils/adt/jsonfuncs.c:3017 utils/adt/jsonfuncs.c:3935 #, c-format msgid "cannot call %s on an array" msgstr "викликати %s з масивом, не можна" -#: utils/adt/jsonfuncs.c:636 jsonpath_scan.l:596 +#: utils/adt/jsonfuncs.c:647 jsonpath_scan.l:607 #, c-format msgid "unsupported Unicode escape sequence" msgstr "непідтримувана спеціальна послідовність Unicode" -#: utils/adt/jsonfuncs.c:713 +#: utils/adt/jsonfuncs.c:724 #, c-format msgid "JSON data, line %d: %s%s%s" msgstr "Дані JSON, рядок %d: %s%s%s" -#: utils/adt/jsonfuncs.c:1875 utils/adt/jsonfuncs.c:1912 +#: utils/adt/jsonfuncs.c:1883 utils/adt/jsonfuncs.c:1920 #, c-format msgid "cannot get array length of a scalar" msgstr "отримати довжину скаляра масиву не можна" -#: utils/adt/jsonfuncs.c:1879 utils/adt/jsonfuncs.c:1898 +#: utils/adt/jsonfuncs.c:1887 utils/adt/jsonfuncs.c:1906 #, c-format msgid "cannot get array length of a non-array" msgstr "отримати довжину масива для не масиву не можна" -#: utils/adt/jsonfuncs.c:1978 +#: utils/adt/jsonfuncs.c:1986 #, c-format msgid "cannot call %s on a non-object" msgstr "викликати %s з не об'єктом, не можна" -#: utils/adt/jsonfuncs.c:2166 +#: utils/adt/jsonfuncs.c:2174 #, c-format msgid "cannot deconstruct an array as an object" msgstr "вилучити масив у вигляді об'єкту не можна" -#: utils/adt/jsonfuncs.c:2180 +#: utils/adt/jsonfuncs.c:2188 #, c-format msgid "cannot deconstruct a scalar" msgstr "вилучити скаляр не можна" -#: utils/adt/jsonfuncs.c:2225 +#: utils/adt/jsonfuncs.c:2233 #, c-format msgid "cannot extract elements from a scalar" msgstr "вилучити елементи зі скаляру не можна" -#: utils/adt/jsonfuncs.c:2229 +#: utils/adt/jsonfuncs.c:2237 #, c-format msgid "cannot extract elements from an object" msgstr "вилучити елементи з об'єкту не можна" -#: utils/adt/jsonfuncs.c:2414 utils/adt/jsonfuncs.c:3896 +#: utils/adt/jsonfuncs.c:2424 utils/adt/jsonfuncs.c:4173 #, c-format msgid "cannot call %s on a non-array" msgstr "викликати %s з не масивом не можна" -#: utils/adt/jsonfuncs.c:2488 utils/adt/jsonfuncs.c:2493 -#: utils/adt/jsonfuncs.c:2510 utils/adt/jsonfuncs.c:2516 +#: utils/adt/jsonfuncs.c:2515 utils/adt/jsonfuncs.c:2520 +#: utils/adt/jsonfuncs.c:2538 utils/adt/jsonfuncs.c:2544 #, c-format msgid "expected JSON array" msgstr "очікувався масив JSON" -#: utils/adt/jsonfuncs.c:2489 +#: utils/adt/jsonfuncs.c:2516 #, c-format msgid "See the value of key \"%s\"." msgstr "Перевірте значення ключа \"%s\"." -#: utils/adt/jsonfuncs.c:2511 +#: utils/adt/jsonfuncs.c:2539 #, c-format msgid "See the array element %s of key \"%s\"." msgstr "Перевірте елемент масиву %s ключа \"%s\"." -#: utils/adt/jsonfuncs.c:2517 +#: utils/adt/jsonfuncs.c:2545 #, c-format msgid "See the array element %s." msgstr "Перевірте елемент масиву %s." -#: utils/adt/jsonfuncs.c:2552 +#: utils/adt/jsonfuncs.c:2597 #, c-format msgid "malformed JSON array" msgstr "неправильний масив JSON" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3389 +#: utils/adt/jsonfuncs.c:3647 #, c-format msgid "first argument of %s must be a row type" msgstr "першим аргументом %s повинен бути тип рядка" #. translator: %s is a function name, eg json_to_record -#: utils/adt/jsonfuncs.c:3413 +#: utils/adt/jsonfuncs.c:3671 #, c-format msgid "could not determine row type for result of %s" msgstr "не вдалося визначити тип рядка для результату %s" -#: utils/adt/jsonfuncs.c:3415 +#: utils/adt/jsonfuncs.c:3673 #, c-format msgid "Provide a non-null record argument, or call the function in the FROM clause using a column definition list." msgstr "Надайте аргумент ненульового запису, або викличте функцію в реченні FROM, використовуючи список визначення стовпців." -#: utils/adt/jsonfuncs.c:3785 utils/fmgr/funcapi.c:94 +#: utils/adt/jsonfuncs.c:4059 utils/fmgr/funcapi.c:94 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "необхідний режим матеріалізації (materialize mode), але він неприпустимий у цьому контексті" -#: utils/adt/jsonfuncs.c:3913 utils/adt/jsonfuncs.c:3997 +#: utils/adt/jsonfuncs.c:4190 utils/adt/jsonfuncs.c:4274 #, c-format msgid "argument of %s must be an array of objects" msgstr "аргументом %s повинен бути масив об'єктів" -#: utils/adt/jsonfuncs.c:3946 +#: utils/adt/jsonfuncs.c:4223 #, c-format msgid "cannot call %s on an object" msgstr "викликати %s з об'єктом не можна" -#: utils/adt/jsonfuncs.c:4380 utils/adt/jsonfuncs.c:4439 -#: utils/adt/jsonfuncs.c:4519 +#: utils/adt/jsonfuncs.c:4656 utils/adt/jsonfuncs.c:4715 +#: utils/adt/jsonfuncs.c:4795 #, c-format msgid "cannot delete from scalar" msgstr "видалити зі скаляру не можна" -#: utils/adt/jsonfuncs.c:4524 +#: utils/adt/jsonfuncs.c:4800 #, c-format msgid "cannot delete from object using integer index" msgstr "видалити з об'єкту по числовому індексу не можна" -#: utils/adt/jsonfuncs.c:4592 utils/adt/jsonfuncs.c:4751 +#: utils/adt/jsonfuncs.c:4868 utils/adt/jsonfuncs.c:5027 #, c-format msgid "cannot set path in scalar" msgstr "встановити шлях в скалярі не можна" -#: utils/adt/jsonfuncs.c:4633 utils/adt/jsonfuncs.c:4675 +#: utils/adt/jsonfuncs.c:4909 utils/adt/jsonfuncs.c:4951 #, c-format msgid "null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"" msgstr "null_value_treatment має бути \"delete_key\", \"return_target\", \"use_json_null\", або \"raise_exception\"" -#: utils/adt/jsonfuncs.c:4646 +#: utils/adt/jsonfuncs.c:4922 #, c-format msgid "JSON value must not be null" msgstr "Значення JSON не повинне бути null" -#: utils/adt/jsonfuncs.c:4647 +#: utils/adt/jsonfuncs.c:4923 #, c-format msgid "Exception was raised because null_value_treatment is \"raise_exception\"." msgstr "Виняток було запущено через те, що null_value_treatment дорівнює \"raise_exception\"." -#: utils/adt/jsonfuncs.c:4648 +#: utils/adt/jsonfuncs.c:4924 #, c-format msgid "To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed." msgstr "Щоб уникнути, або змініть аргумент null_value_treatment або переконайтесь що SQL NULL не передано." -#: utils/adt/jsonfuncs.c:4703 +#: utils/adt/jsonfuncs.c:4979 #, c-format msgid "cannot delete path in scalar" msgstr "видалити шлях в скалярі не можна" -#: utils/adt/jsonfuncs.c:4917 +#: utils/adt/jsonfuncs.c:5193 #, c-format msgid "path element at position %d is null" msgstr "елемент шляху в позиції %d є null" -#: utils/adt/jsonfuncs.c:4936 utils/adt/jsonfuncs.c:4967 -#: utils/adt/jsonfuncs.c:5040 +#: utils/adt/jsonfuncs.c:5212 utils/adt/jsonfuncs.c:5243 +#: utils/adt/jsonfuncs.c:5316 #, c-format msgid "cannot replace existing key" msgstr "замініти існуючий ключ не можна" -#: utils/adt/jsonfuncs.c:4937 utils/adt/jsonfuncs.c:4968 +#: utils/adt/jsonfuncs.c:5213 utils/adt/jsonfuncs.c:5244 #, c-format msgid "The path assumes key is a composite object, but it is a scalar value." msgstr "Шлях припускає, що ключ є складеним об'єктом, але це скалярне значення." -#: utils/adt/jsonfuncs.c:5041 +#: utils/adt/jsonfuncs.c:5317 #, c-format msgid "Try using the function jsonb_set to replace key value." msgstr "Спробуйте, використати функцію jsonb_set, щоб замінити значення ключа." -#: utils/adt/jsonfuncs.c:5145 +#: utils/adt/jsonfuncs.c:5421 #, c-format msgid "path element at position %d is not an integer: \"%s\"" msgstr "елмент шляху в позиції %d не є цілим числом: \"%s\"" -#: utils/adt/jsonfuncs.c:5162 +#: utils/adt/jsonfuncs.c:5438 #, c-format msgid "path element at position %d is out of range: %d" msgstr "елемент шляху в позиції %d поза діапазоном: %d" -#: utils/adt/jsonfuncs.c:5314 +#: utils/adt/jsonfuncs.c:5590 #, c-format msgid "wrong flag type, only arrays and scalars are allowed" msgstr "неправильний тип позначки, дозволені лише масиви і скаляри" -#: utils/adt/jsonfuncs.c:5321 +#: utils/adt/jsonfuncs.c:5597 #, c-format msgid "flag array element is not a string" msgstr "елемент масиву позначок не є рядком" -#: utils/adt/jsonfuncs.c:5322 utils/adt/jsonfuncs.c:5344 +#: utils/adt/jsonfuncs.c:5598 utils/adt/jsonfuncs.c:5620 #, c-format msgid "Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\"." msgstr "Можливі значення: \"string\", \"numeric\", \"boolean\", \"key\", і \"all\"." -#: utils/adt/jsonfuncs.c:5342 +#: utils/adt/jsonfuncs.c:5618 #, c-format msgid "wrong flag in flag array: \"%s\"" msgstr "неправильна позначка в масиві позначок: \"%s\"" -#: utils/adt/jsonpath.c:382 +#: utils/adt/jsonpath.c:389 #, c-format msgid "@ is not allowed in root expressions" msgstr "@ не дозволяється в кореневих виразах" -#: utils/adt/jsonpath.c:388 +#: utils/adt/jsonpath.c:395 #, c-format msgid "LAST is allowed only in array subscripts" msgstr "LAST дозволяється лише в підрядкових символах масиву" -#: utils/adt/jsonpath_exec.c:361 +#: utils/adt/jsonpath_exec.c:491 #, c-format msgid "single boolean result is expected" msgstr "очікується один логічний результат" -#: utils/adt/jsonpath_exec.c:557 +#: utils/adt/jsonpath_exec.c:851 #, c-format -msgid "\"vars\" argument is not an object" -msgstr "аргумент \"vars\" не є об'єктом" +msgid "jsonpath wildcard array accessor can only be applied to an array" +msgstr "доступ до підстановочного масиву jsonpath може бути застосований лише до масиву" -#: utils/adt/jsonpath_exec.c:558 +#: utils/adt/jsonpath_exec.c:874 #, c-format -msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." -msgstr "Параметри Jsonpath повинні бути закодовані в якості пар \"ключ-значення\" об'єкту \"vars\"." +msgid "jsonpath wildcard member accessor can only be applied to an object" +msgstr "доступ до підстановочного елемента jsonpath може бути застосований лише до об'єкта" + +#: utils/adt/jsonpath_exec.c:923 +#, c-format +msgid "jsonpath array subscript is out of bounds" +msgstr "підрядковий символ масиву jsonpath поза межами" + +#: utils/adt/jsonpath_exec.c:980 +#, c-format +msgid "jsonpath array accessor can only be applied to an array" +msgstr "доступ до масиву jsonpath може бути застосований лише до масиву" -#: utils/adt/jsonpath_exec.c:675 +#: utils/adt/jsonpath_exec.c:1044 #, c-format msgid "JSON object does not contain key \"%s\"" msgstr "Об'єкт JSON не містить ключа \"%s\"" -#: utils/adt/jsonpath_exec.c:687 +#: utils/adt/jsonpath_exec.c:1056 #, c-format msgid "jsonpath member accessor can only be applied to an object" msgstr "доступ для елемента jsonpath може бути застосований лише до об'єкта" -#: utils/adt/jsonpath_exec.c:716 +#: utils/adt/jsonpath_exec.c:1114 #, c-format -msgid "jsonpath wildcard array accessor can only be applied to an array" -msgstr "доступ до підстановочного масиву jsonpath може бути застосований лише до масиву" +msgid "jsonpath item method .%s() can only be applied to an array" +msgstr "метод елемента jsonpath .%s() може бути застосований лише до масиву" -#: utils/adt/jsonpath_exec.c:764 +#: utils/adt/jsonpath_exec.c:1167 utils/adt/jsonpath_exec.c:1193 #, c-format -msgid "jsonpath array subscript is out of bounds" -msgstr "підрядковий символ масиву jsonpath поза межами" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type double precision" +msgstr "" -#: utils/adt/jsonpath_exec.c:821 +#: utils/adt/jsonpath_exec.c:1172 utils/adt/jsonpath_exec.c:1198 +#: utils/adt/jsonpath_exec.c:1414 utils/adt/jsonpath_exec.c:1446 #, c-format -msgid "jsonpath array accessor can only be applied to an array" -msgstr "доступ до масиву jsonpath може бути застосований лише до масиву" +msgid "NaN or Infinity is not allowed for jsonpath item method .%s()" +msgstr "" -#: utils/adt/jsonpath_exec.c:873 +#: utils/adt/jsonpath_exec.c:1211 utils/adt/jsonpath_exec.c:1313 +#: utils/adt/jsonpath_exec.c:1455 utils/adt/jsonpath_exec.c:1593 #, c-format -msgid "jsonpath wildcard member accessor can only be applied to an object" -msgstr "доступ до підстановочного елемента jsonpath може бути застосований лише до об'єкта" +msgid "jsonpath item method .%s() can only be applied to a string or numeric value" +msgstr "метод елемента jsonpath .%s() може бути застосований лише до рядка або числового значення" -#: utils/adt/jsonpath_exec.c:1007 +#: utils/adt/jsonpath_exec.c:1281 utils/adt/jsonpath_exec.c:1305 #, c-format -msgid "jsonpath item method .%s() can only be applied to an array" -msgstr "метод елемента jsonpath .%s() може бути застосований лише до масиву" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type bigint" +msgstr "" -#: utils/adt/jsonpath_exec.c:1060 +#: utils/adt/jsonpath_exec.c:1357 utils/adt/jsonpath_exec.c:1377 #, c-format -msgid "numeric argument of jsonpath item method .%s() is out of range for type double precision" -msgstr "числовий аргумент методу елемента jsonpath .%s() поза діапазоном для типу double precision" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type boolean" +msgstr "" -#: utils/adt/jsonpath_exec.c:1081 +#: utils/adt/jsonpath_exec.c:1386 #, c-format -msgid "string argument of jsonpath item method .%s() is not a valid representation of a double precision number" -msgstr "строковий аргумент методу елемента jsonpath .%s() не є представленням числа double precision" +msgid "jsonpath item method .%s() can only be applied to a boolean, string, or numeric value" +msgstr "" -#: utils/adt/jsonpath_exec.c:1094 +#: utils/adt/jsonpath_exec.c:1439 utils/adt/jsonpath_exec.c:1528 #, c-format -msgid "jsonpath item method .%s() can only be applied to a string or numeric value" -msgstr "метод елемента jsonpath .%s() може бути застосований лише до рядка або числового значення" +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type numeric" +msgstr "" + +#: utils/adt/jsonpath_exec.c:1487 +#, c-format +msgid "precision of jsonpath item method .%s() is out of range for type integer" +msgstr "точність методу елементу jsonpath .%s() знаходиться за межами діапазону для типу integer" + +#: utils/adt/jsonpath_exec.c:1501 +#, c-format +msgid "scale of jsonpath item method .%s() is out of range for type integer" +msgstr "масштаб методу jsonpath елементу .%s() знаходиться за межами діапазону для типу integer" + +#: utils/adt/jsonpath_exec.c:1561 utils/adt/jsonpath_exec.c:1585 +#, c-format +msgid "argument \"%s\" of jsonpath item method .%s() is invalid for type integer" +msgstr "" -#: utils/adt/jsonpath_exec.c:1584 +#: utils/adt/jsonpath_exec.c:1648 +#, c-format +msgid "jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value" +msgstr "" + +#: utils/adt/jsonpath_exec.c:2137 #, c-format msgid "left operand of jsonpath operator %s is not a single numeric value" msgstr "лівий операнд оператора jsonpath %s не є єдиним числовим значенням" -#: utils/adt/jsonpath_exec.c:1591 +#: utils/adt/jsonpath_exec.c:2144 #, c-format msgid "right operand of jsonpath operator %s is not a single numeric value" msgstr "правий операнд оператора jsonpath %s не є єдиним числовим значенням" -#: utils/adt/jsonpath_exec.c:1659 +#: utils/adt/jsonpath_exec.c:2212 #, c-format msgid "operand of unary jsonpath operator %s is not a numeric value" msgstr "операнд унарного оператора jsonpath %s не є єдиним числовим значенням" -#: utils/adt/jsonpath_exec.c:1758 +#: utils/adt/jsonpath_exec.c:2311 #, c-format msgid "jsonpath item method .%s() can only be applied to a numeric value" msgstr "метод елемента jsonpath .%s() може бути застосований лише до числового значення" -#: utils/adt/jsonpath_exec.c:1798 +#: utils/adt/jsonpath_exec.c:2357 #, c-format msgid "jsonpath item method .%s() can only be applied to a string" msgstr "метод елемента jsonpath .%s() може бути застосований лише до рядку" -#: utils/adt/jsonpath_exec.c:1901 +#: utils/adt/jsonpath_exec.c:2450 +#, c-format +msgid "time precision of jsonpath item method .%s() is out of range for type integer" +msgstr "точність часу методу елементу jsonpath .%s() знаходиться за межами діапазону для типу integer" + +#: utils/adt/jsonpath_exec.c:2484 utils/adt/jsonpath_exec.c:2490 +#: utils/adt/jsonpath_exec.c:2517 utils/adt/jsonpath_exec.c:2545 +#: utils/adt/jsonpath_exec.c:2598 utils/adt/jsonpath_exec.c:2649 +#: utils/adt/jsonpath_exec.c:2720 #, c-format -msgid "datetime format is not recognized: \"%s\"" -msgstr "формат дати й часу не розпізнано: \"%s\"" +msgid "%s format is not recognized: \"%s\"" +msgstr "Формат %s не розпізнано: \"%s\"" -#: utils/adt/jsonpath_exec.c:1903 +#: utils/adt/jsonpath_exec.c:2486 #, c-format msgid "Use a datetime template argument to specify the input data format." msgstr "Використайте аргумент шаблону дати й часу щоб вказати формат вхідних даних." -#: utils/adt/jsonpath_exec.c:1971 +#: utils/adt/jsonpath_exec.c:2679 utils/adt/jsonpath_exec.c:2760 +#, c-format +msgid "time precision of jsonpath item method .%s() is invalid" +msgstr "" + +#: utils/adt/jsonpath_exec.c:2840 #, c-format msgid "jsonpath item method .%s() can only be applied to an object" msgstr "метод елемента jsonpath .%s() може бути застосований лише до об'єкта" -#: utils/adt/jsonpath_exec.c:2153 +#: utils/adt/jsonpath_exec.c:3124 +#, c-format +msgid "could not convert value of type %s to jsonpath" +msgstr "" + +#: utils/adt/jsonpath_exec.c:3158 #, c-format msgid "could not find jsonpath variable \"%s\"" msgstr "не вдалося знайти змінну jsonpath \"%s\"" -#: utils/adt/jsonpath_exec.c:2417 +#: utils/adt/jsonpath_exec.c:3211 +#, c-format +msgid "\"vars\" argument is not an object" +msgstr "аргумент \"vars\" не є об'єктом" + +#: utils/adt/jsonpath_exec.c:3212 +#, c-format +msgid "Jsonpath parameters should be encoded as key-value pairs of \"vars\" object." +msgstr "Параметри Jsonpath повинні бути закодовані в якості пар \"ключ-значення\" об'єкту \"vars\"." + +#: utils/adt/jsonpath_exec.c:3475 #, c-format msgid "jsonpath array subscript is not a single numeric value" msgstr "підрядковий символ масиву jsonpath не є єдиним числовим значенням" -#: utils/adt/jsonpath_exec.c:2429 +#: utils/adt/jsonpath_exec.c:3487 #, c-format msgid "jsonpath array subscript is out of integer range" msgstr "підрядковий символ масиву jsonpath поза цілим діапазоном" -#: utils/adt/jsonpath_exec.c:2606 +#: utils/adt/jsonpath_exec.c:3671 #, c-format msgid "cannot convert value from %s to %s without time zone usage" msgstr "не можна перетворити значення з %s в %s без використання часового поясу" -#: utils/adt/jsonpath_exec.c:2608 +#: utils/adt/jsonpath_exec.c:3673 #, c-format msgid "Use *_tz() function for time zone support." msgstr "Використовуйте функцію *_tz() для підтримки часового поясу." +#: utils/adt/jsonpath_exec.c:3981 +#, c-format +msgid "JSON path expression for column \"%s\" should return single item without wrapper" +msgstr "" + +#: utils/adt/jsonpath_exec.c:3983 utils/adt/jsonpath_exec.c:3988 +#, c-format +msgid "Use the WITH WRAPPER clause to wrap SQL/JSON items into an array." +msgstr "" + +#: utils/adt/jsonpath_exec.c:3987 +#, c-format +msgid "JSON path expression in JSON_QUERY should return single item without wrapper" +msgstr "" + +#: utils/adt/jsonpath_exec.c:4045 utils/adt/jsonpath_exec.c:4069 +#, c-format +msgid "JSON path expression for column \"%s\" should return single scalar item" +msgstr "" + +#: utils/adt/jsonpath_exec.c:4050 utils/adt/jsonpath_exec.c:4074 +#, c-format +msgid "JSON path expression in JSON_VALUE should return single scalar item" +msgstr "" + #: utils/adt/levenshtein.c:132 #, c-format msgid "levenshtein argument exceeds maximum length of %d characters" msgstr "довжина аргументу levenshtein перевищує максимальну довжину, %d символів" -#: utils/adt/like.c:161 +#: utils/adt/like.c:159 #, c-format msgid "nondeterministic collations are not supported for LIKE" msgstr "недетерміновані параметри сортування не підтримуються для LIKE" -#: utils/adt/like.c:190 utils/adt/like_support.c:1024 +#: utils/adt/like.c:188 utils/adt/like_support.c:1023 #, c-format msgid "could not determine which collation to use for ILIKE" msgstr "не вдалося визначити який параметр сортування використати для ILIKE" -#: utils/adt/like.c:202 +#: utils/adt/like.c:200 #, c-format msgid "nondeterministic collations are not supported for ILIKE" msgstr "недетерміновані параметри сортування не підтримуються для ILIKE" @@ -24575,22 +25596,22 @@ msgstr "недетерміновані параметри сортування msgid "LIKE pattern must not end with escape character" msgstr "Шаблон LIKE не повинен закінчуватись символом виходу" -#: utils/adt/like_match.c:293 utils/adt/regexp.c:801 +#: utils/adt/like_match.c:293 utils/adt/regexp.c:800 #, c-format msgid "invalid escape string" msgstr "неприпустимий рядок виходу" -#: utils/adt/like_match.c:294 utils/adt/regexp.c:802 +#: utils/adt/like_match.c:294 utils/adt/regexp.c:801 #, c-format msgid "Escape string must be empty or one character." msgstr "Рядок виходу повинен бути пустим або складатися з одного символу." -#: utils/adt/like_support.c:1014 +#: utils/adt/like_support.c:1013 #, c-format msgid "case insensitive matching not supported on type bytea" msgstr "порівняння без урахування регістру не підтримується для типу bytea" -#: utils/adt/like_support.c:1115 +#: utils/adt/like_support.c:1114 #, c-format msgid "regular-expression matching not supported on type bytea" msgstr "порівняння з регулярними виразами не підтримується для типу bytea" @@ -24600,17 +25621,17 @@ msgstr "порівняння з регулярними виразами не п msgid "invalid octet value in \"macaddr\" value: \"%s\"" msgstr "неприпустиме значення октету в значенні типу \"macaddr\": \"%s\"" -#: utils/adt/mac8.c:554 +#: utils/adt/mac8.c:555 #, c-format msgid "macaddr8 data out of range to convert to macaddr" msgstr "дані macaddr8 поза діапазоном, для перетворення в macaddr" -#: utils/adt/mac8.c:555 +#: utils/adt/mac8.c:556 #, c-format msgid "Only addresses that have FF and FE as values in the 4th and 5th bytes from the left, for example xx:xx:xx:ff:fe:xx:xx:xx, are eligible to be converted from macaddr8 to macaddr." msgstr "Лише адреси, які мають FF і FE в якості значень в четвертому і п'ятому байті зліва, наприклад xx:xx:xx:ff:fe:xx:xx:xx можуть бути перетворені з macaddr8 в macaddr." -#: utils/adt/mcxtfuncs.c:182 +#: utils/adt/mcxtfuncs.c:173 #, c-format msgid "PID %d is not a PostgreSQL server process" msgstr "PID %d не є серверним процесом PostgreSQL" @@ -24649,70 +25670,70 @@ msgstr "може бути пустою міткою" msgid "requires AS" msgstr "потребує AS" -#: utils/adt/misc.c:853 utils/adt/misc.c:867 utils/adt/misc.c:906 -#: utils/adt/misc.c:912 utils/adt/misc.c:918 utils/adt/misc.c:941 +#: utils/adt/misc.c:897 utils/adt/misc.c:911 utils/adt/misc.c:950 +#: utils/adt/misc.c:956 utils/adt/misc.c:962 utils/adt/misc.c:985 #, c-format msgid "string is not a valid identifier: \"%s\"" msgstr "рядок не є припустимим ідентифікатором: \"%s\"" -#: utils/adt/misc.c:855 +#: utils/adt/misc.c:899 #, c-format msgid "String has unclosed double quotes." msgstr "Рядок має не закриті лапки." -#: utils/adt/misc.c:869 +#: utils/adt/misc.c:913 #, c-format msgid "Quoted identifier must not be empty." msgstr "Ідентифікатор в лапках не повинен бути пустим." -#: utils/adt/misc.c:908 +#: utils/adt/misc.c:952 #, c-format msgid "No valid identifier before \".\"." msgstr "Перед \".\" немає припустимого ідентифікатору." -#: utils/adt/misc.c:914 +#: utils/adt/misc.c:958 #, c-format msgid "No valid identifier after \".\"." msgstr "Після \".\" немає припустимого ідентифікатора." -#: utils/adt/misc.c:974 +#: utils/adt/misc.c:1018 #, c-format msgid "log format \"%s\" is not supported" msgstr "формат журналу \"%s\" не підтримується" -#: utils/adt/misc.c:975 +#: utils/adt/misc.c:1019 #, c-format msgid "The supported log formats are \"stderr\", \"csvlog\", and \"jsonlog\"." msgstr "Підтримуванні формати журналів: \"stderr\", \"csvlog\", і \"jsonlog\"." -#: utils/adt/multirangetypes.c:151 utils/adt/multirangetypes.c:164 -#: utils/adt/multirangetypes.c:193 utils/adt/multirangetypes.c:267 -#: utils/adt/multirangetypes.c:291 +#: utils/adt/multirangetypes.c:150 utils/adt/multirangetypes.c:163 +#: utils/adt/multirangetypes.c:192 utils/adt/multirangetypes.c:266 +#: utils/adt/multirangetypes.c:290 #, c-format msgid "malformed multirange literal: \"%s\"" msgstr "неправильний багатодіапазонний літерал: \"%s\"" -#: utils/adt/multirangetypes.c:153 +#: utils/adt/multirangetypes.c:152 #, c-format msgid "Missing left brace." msgstr "Пропущено ліву дужку." -#: utils/adt/multirangetypes.c:195 +#: utils/adt/multirangetypes.c:194 #, c-format msgid "Expected range start." msgstr "Очікуваний початок діапазону." -#: utils/adt/multirangetypes.c:269 +#: utils/adt/multirangetypes.c:268 #, c-format msgid "Expected comma or end of multirange." msgstr "Очікувалась кома або закінчення мультидіапазону." -#: utils/adt/multirangetypes.c:982 +#: utils/adt/multirangetypes.c:981 #, c-format msgid "multiranges cannot be constructed from multidimensional arrays" msgstr "мультидіапазони не можуть бути побудовані з багатовимірних масивів" -#: utils/adt/multirangetypes.c:1008 +#: utils/adt/multirangetypes.c:1007 #, c-format msgid "multirange values cannot contain null members" msgstr "мультидіапазонні значення не можуть містити членів null" @@ -24791,112 +25812,138 @@ msgstr "результат поза діапазоном" msgid "cannot subtract inet values of different sizes" msgstr "не можна віднімати значення inet різного розміру" -#: utils/adt/numeric.c:785 utils/adt/numeric.c:3643 utils/adt/numeric.c:7131 -#: utils/adt/numeric.c:7334 utils/adt/numeric.c:7806 utils/adt/numeric.c:10501 -#: utils/adt/numeric.c:10975 utils/adt/numeric.c:11069 -#: utils/adt/numeric.c:11203 +#: utils/adt/numeric.c:793 utils/adt/numeric.c:3659 utils/adt/numeric.c:7216 +#: utils/adt/numeric.c:7419 utils/adt/numeric.c:7891 utils/adt/numeric.c:10586 +#: utils/adt/numeric.c:11061 utils/adt/numeric.c:11155 +#: utils/adt/numeric.c:11290 #, c-format msgid "value overflows numeric format" msgstr "значення переповнюють формат numeric" -#: utils/adt/numeric.c:1098 +#: utils/adt/numeric.c:1106 #, c-format msgid "invalid sign in external \"numeric\" value" msgstr "неприпустимий знак у зовнішньому значенні \"numeric\"" -#: utils/adt/numeric.c:1104 +#: utils/adt/numeric.c:1112 #, c-format msgid "invalid scale in external \"numeric\" value" msgstr "неприпустимий масштаб у зовнішньому значенні \"numeric\"" -#: utils/adt/numeric.c:1113 +#: utils/adt/numeric.c:1121 #, c-format msgid "invalid digit in external \"numeric\" value" msgstr "неприпустиме число у зовнішньому значенні \"numeric\"" -#: utils/adt/numeric.c:1328 utils/adt/numeric.c:1342 +#: utils/adt/numeric.c:1336 utils/adt/numeric.c:1350 #, c-format msgid "NUMERIC precision %d must be between 1 and %d" msgstr "Точність NUMERIC %d повинна бути між 1 і %d" -#: utils/adt/numeric.c:1333 +#: utils/adt/numeric.c:1341 #, c-format msgid "NUMERIC scale %d must be between %d and %d" msgstr "Масштаб NUMERIC %d повинен бути між %d і %d" -#: utils/adt/numeric.c:1351 +#: utils/adt/numeric.c:1359 #, c-format msgid "invalid NUMERIC type modifier" msgstr "неприпустимий модифікатор типу NUMERIC" -#: utils/adt/numeric.c:1709 +#: utils/adt/numeric.c:1725 #, c-format msgid "start value cannot be NaN" msgstr "початкове значення не може бути NaN" -#: utils/adt/numeric.c:1713 +#: utils/adt/numeric.c:1729 #, c-format msgid "start value cannot be infinity" msgstr "початкове значення не може бути нескінченністю" -#: utils/adt/numeric.c:1720 +#: utils/adt/numeric.c:1736 #, c-format msgid "stop value cannot be NaN" msgstr "кінцеве значення не може бути NaN" -#: utils/adt/numeric.c:1724 +#: utils/adt/numeric.c:1740 #, c-format msgid "stop value cannot be infinity" msgstr "кінцеве значення не може бути нескінченністю" -#: utils/adt/numeric.c:1737 +#: utils/adt/numeric.c:1753 #, c-format msgid "step size cannot be NaN" msgstr "розмір кроку не може бути NaN" -#: utils/adt/numeric.c:1741 +#: utils/adt/numeric.c:1757 #, c-format msgid "step size cannot be infinity" msgstr "розмір кроку не може бути нескінченністю" -#: utils/adt/numeric.c:3633 +#: utils/adt/numeric.c:3649 #, c-format msgid "factorial of a negative number is undefined" msgstr "факторіал від'ємного числа не визначено" -#: utils/adt/numeric.c:4366 utils/adt/numeric.c:4446 utils/adt/numeric.c:4487 -#: utils/adt/numeric.c:4683 +#: utils/adt/numeric.c:4256 +#, c-format +msgid "lower bound cannot be NaN" +msgstr "" + +#: utils/adt/numeric.c:4260 +#, c-format +msgid "lower bound cannot be infinity" +msgstr "" + +#: utils/adt/numeric.c:4267 +#, c-format +msgid "upper bound cannot be NaN" +msgstr "" + +#: utils/adt/numeric.c:4271 +#, c-format +msgid "upper bound cannot be infinity" +msgstr "" + +#: utils/adt/numeric.c:4432 utils/adt/numeric.c:4520 utils/adt/numeric.c:4580 +#: utils/adt/numeric.c:4776 #, c-format msgid "cannot convert NaN to %s" msgstr "неможливо перетворити NaN на %s" -#: utils/adt/numeric.c:4370 utils/adt/numeric.c:4450 utils/adt/numeric.c:4491 -#: utils/adt/numeric.c:4687 +#: utils/adt/numeric.c:4436 utils/adt/numeric.c:4524 utils/adt/numeric.c:4584 +#: utils/adt/numeric.c:4780 #, c-format msgid "cannot convert infinity to %s" msgstr "неможливо перетворити нескінченність на %s" -#: utils/adt/numeric.c:4696 +#: utils/adt/numeric.c:4789 #, c-format msgid "pg_lsn out of range" msgstr "pg_lsn поза діапазоном" -#: utils/adt/numeric.c:7896 utils/adt/numeric.c:7947 +#: utils/adt/numeric.c:7981 utils/adt/numeric.c:8032 #, c-format msgid "numeric field overflow" msgstr "надлишок поля numeric" -#: utils/adt/numeric.c:7897 +#: utils/adt/numeric.c:7982 #, c-format msgid "A field with precision %d, scale %d must round to an absolute value less than %s%d." msgstr "Поле з точністю %d, масштабом %d повинне округлятись до абсолютного значення меньше, ніж %s%d." -#: utils/adt/numeric.c:7948 +#: utils/adt/numeric.c:8033 #, c-format msgid "A field with precision %d, scale %d cannot hold an infinite value." msgstr "Поле з точністю %d, масштабом %d не може містити нескінченне значення." -#: utils/adt/oid.c:216 +#: utils/adt/numeric.c:11359 utils/adt/pseudorandomfuncs.c:135 +#: utils/adt/pseudorandomfuncs.c:159 +#, c-format +msgid "lower bound must be less than or equal to upper bound" +msgstr "" + +#: utils/adt/oid.c:217 #, c-format msgid "invalid oidvector data" msgstr "неприпустимі дані oidvector" @@ -24926,306 +25973,312 @@ msgstr "запитаний символ занадто великий для к msgid "requested character not valid for encoding: %u" msgstr "запитаний символ не припустимий для кодування: %u" -#: utils/adt/orderedsetaggs.c:448 utils/adt/orderedsetaggs.c:553 -#: utils/adt/orderedsetaggs.c:693 +#: utils/adt/orderedsetaggs.c:446 utils/adt/orderedsetaggs.c:551 +#: utils/adt/orderedsetaggs.c:691 #, c-format msgid "percentile value %g is not between 0 and 1" msgstr "значення процентиля %g не є між 0 і 1" -#: utils/adt/pg_locale.c:1410 +#: utils/adt/pg_locale.c:1484 #, c-format msgid "could not open collator for locale \"%s\" with rules \"%s\": %s" msgstr "не вдалося відкрити сортувальник для локалізації\"%s\" з правилами \"%s\": %s" -#: utils/adt/pg_locale.c:1421 utils/adt/pg_locale.c:2831 -#: utils/adt/pg_locale.c:2904 +#: utils/adt/pg_locale.c:1495 utils/adt/pg_locale.c:2969 +#: utils/adt/pg_locale.c:3042 #, c-format msgid "ICU is not supported in this build" msgstr "ICU не підтримується в цій збірці" -#: utils/adt/pg_locale.c:1450 +#: utils/adt/pg_locale.c:1523 #, c-format msgid "could not create locale \"%s\": %m" msgstr "не вдалося створити локалізацію \"%s\": %m" -#: utils/adt/pg_locale.c:1453 +#: utils/adt/pg_locale.c:1526 #, c-format msgid "The operating system could not find any locale data for the locale name \"%s\"." msgstr "Операційній системі не вдалося знайти дані локалізації з іменем \"%s\"." -#: utils/adt/pg_locale.c:1568 +#: utils/adt/pg_locale.c:1647 #, c-format msgid "collations with different collate and ctype values are not supported on this platform" msgstr "параметри сортування з різними значеннями collate і ctype не підтримуються на цій платформі" -#: utils/adt/pg_locale.c:1577 -#, c-format -msgid "collation provider LIBC is not supported on this platform" -msgstr "провайдер параметрів сортування LIBC не підтримується на цій платформі" - -#: utils/adt/pg_locale.c:1618 +#: utils/adt/pg_locale.c:1694 #, c-format msgid "collation \"%s\" has no actual version, but a version was recorded" msgstr "для параметру сортування \"%s\" який не має фактичної версії, була вказана версія" -#: utils/adt/pg_locale.c:1624 +#: utils/adt/pg_locale.c:1700 #, c-format msgid "collation \"%s\" has version mismatch" msgstr "невідповідність версій для параметру сортування \"%s\"" -#: utils/adt/pg_locale.c:1626 +#: utils/adt/pg_locale.c:1702 #, c-format msgid "The collation in the database was created using version %s, but the operating system provides version %s." msgstr "Параметр сортування в базі даних був створений з версією %s, але операційна система надає версію %s." -#: utils/adt/pg_locale.c:1629 +#: utils/adt/pg_locale.c:1705 #, c-format msgid "Rebuild all objects affected by this collation and run ALTER COLLATION %s REFRESH VERSION, or build PostgreSQL with the right library version." msgstr "Перебудуйте всі об'єкти, які стосуються цього параметру сортування і виконайте ALTER COLLATION %s REFRESH VERSION, або побудуйте PostgreSQL з правильною версією бібліотеки." -#: utils/adt/pg_locale.c:1695 +#: utils/adt/pg_locale.c:1749 utils/adt/pg_locale.c:2533 +#: utils/adt/pg_locale.c:2558 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "неприпустиме ім'я локалі \"%s\" для вбудованого провайдера" + +#: utils/adt/pg_locale.c:1791 #, c-format msgid "could not load locale \"%s\"" msgstr "не вдалося завантажити локаль \"%s\"" -#: utils/adt/pg_locale.c:1720 +#: utils/adt/pg_locale.c:1816 #, c-format msgid "could not get collation version for locale \"%s\": error code %lu" msgstr "не вдалося отримати версію параметрів сортування для локалізації \"%s\": код помилки %lu" -#: utils/adt/pg_locale.c:1776 utils/adt/pg_locale.c:1789 +#: utils/adt/pg_locale.c:1872 utils/adt/pg_locale.c:1885 #, c-format msgid "could not convert string to UTF-16: error code %lu" msgstr "не вдалося перетворити рядок в UTF-16: код помилки %lu" -#: utils/adt/pg_locale.c:1803 +#: utils/adt/pg_locale.c:1897 #, c-format msgid "could not compare Unicode strings: %m" msgstr "не вдалося порівняти рядки в Unicode: %m" -#: utils/adt/pg_locale.c:1984 +#: utils/adt/pg_locale.c:2071 #, c-format msgid "collation failed: %s" msgstr "помилка в бібліотеці сортування: %s" -#: utils/adt/pg_locale.c:2205 utils/adt/pg_locale.c:2237 +#: utils/adt/pg_locale.c:2290 utils/adt/pg_locale.c:2322 #, c-format msgid "sort key generation failed: %s" msgstr "не вдалося згенерувати ключ сортування: %s" -#: utils/adt/pg_locale.c:2474 +#: utils/adt/pg_locale.c:2612 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "не вдалося отримати мову з локалі \"%s\": %s" -#: utils/adt/pg_locale.c:2495 utils/adt/pg_locale.c:2511 +#: utils/adt/pg_locale.c:2633 utils/adt/pg_locale.c:2649 #, c-format msgid "could not open collator for locale \"%s\": %s" msgstr "не вдалося відкрити сортувальник для локалізації \"%s\": %s" -#: utils/adt/pg_locale.c:2536 +#: utils/adt/pg_locale.c:2674 #, c-format msgid "encoding \"%s\" not supported by ICU" msgstr "ICU не підтримує кодування \"%s\"" -#: utils/adt/pg_locale.c:2543 +#: utils/adt/pg_locale.c:2681 #, c-format msgid "could not open ICU converter for encoding \"%s\": %s" msgstr "не вдалося відкрити перетворювач ICU для кодування \"%s\": %s" -#: utils/adt/pg_locale.c:2561 utils/adt/pg_locale.c:2580 -#: utils/adt/pg_locale.c:2636 utils/adt/pg_locale.c:2647 +#: utils/adt/pg_locale.c:2699 utils/adt/pg_locale.c:2718 +#: utils/adt/pg_locale.c:2774 utils/adt/pg_locale.c:2785 #, c-format msgid "%s failed: %s" msgstr "%s помилка: %s" -#: utils/adt/pg_locale.c:2822 +#: utils/adt/pg_locale.c:2960 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "не вдалося перетворити локальну назву \"%s\" на мітку мови: %s" -#: utils/adt/pg_locale.c:2863 +#: utils/adt/pg_locale.c:3001 #, c-format msgid "could not get language from ICU locale \"%s\": %s" msgstr "не вдалося отримати мову з локалі ICU \"%s\": %s" -#: utils/adt/pg_locale.c:2865 utils/adt/pg_locale.c:2894 +#: utils/adt/pg_locale.c:3003 utils/adt/pg_locale.c:3032 #, c-format msgid "To disable ICU locale validation, set the parameter \"%s\" to \"%s\"." msgstr "Щоб вимкнути перевірку мови ICU, встановіть параметр \"%s\" на \"%s\"." -#: utils/adt/pg_locale.c:2892 +#: utils/adt/pg_locale.c:3030 #, c-format msgid "ICU locale \"%s\" has unknown language \"%s\"" msgstr "locale ICU \"%s\" має невідому мову \"%s\"" -#: utils/adt/pg_locale.c:3073 +#: utils/adt/pg_locale.c:3181 #, c-format msgid "invalid multibyte character for locale" msgstr "неприпустимий мультибайтний символ для локалізації" -#: utils/adt/pg_locale.c:3074 +#: utils/adt/pg_locale.c:3182 #, c-format msgid "The server's LC_CTYPE locale is probably incompatible with the database encoding." msgstr "Параметр локалізації серверу LC_CTYPE, можливо, несумісний з кодуванням бази даних." -#: utils/adt/pg_lsn.c:263 +#: utils/adt/pg_lsn.c:262 #, c-format msgid "cannot add NaN to pg_lsn" msgstr "не можна додати NaN в pg_lsn" -#: utils/adt/pg_lsn.c:297 +#: utils/adt/pg_lsn.c:296 #, c-format msgid "cannot subtract NaN from pg_lsn" msgstr "віднімати NaN з pg_lsn не можна" -#: utils/adt/pg_upgrade_support.c:29 +#: utils/adt/pg_upgrade_support.c:39 #, c-format msgid "function can only be called when server is in binary upgrade mode" msgstr "функцію можна викликати тільки коли сервер знаходиться в режимі двійкового оновлення" -#: utils/adt/pgstatfuncs.c:254 +#: utils/adt/pgstatfuncs.c:252 #, c-format msgid "invalid command name: \"%s\"" msgstr "неприпустиме ім’я команди: \"%s\"" -#: utils/adt/pgstatfuncs.c:1774 +#: utils/adt/pgstatfuncs.c:1739 #, c-format msgid "unrecognized reset target: \"%s\"" msgstr "нерозпізнане відновлення мети: \"%s\"" -#: utils/adt/pgstatfuncs.c:1775 +#: utils/adt/pgstatfuncs.c:1740 #, c-format -msgid "Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or \"wal\"." -msgstr "Ціль має бути \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", або \"wal\"." +msgid "Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\"." +msgstr "Ціллю має бути \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\" або \"wal\"." -#: utils/adt/pgstatfuncs.c:1857 +#: utils/adt/pgstatfuncs.c:1822 #, c-format msgid "invalid subscription OID %u" msgstr "некоректний OID підписки %u" -#: utils/adt/pseudotypes.c:58 utils/adt/pseudotypes.c:92 +#: utils/adt/pseudorandomfuncs.c:69 +#, c-format +msgid "setseed parameter %g is out of allowed range [-1,1]" +msgstr "параметр setseed %g поза допустимим діапазоном [-1,1]" + +#: utils/adt/pseudotypes.c:55 utils/adt/pseudotypes.c:89 #, c-format msgid "cannot display a value of type %s" msgstr "значення типу %s не можна відобразити" -#: utils/adt/pseudotypes.c:310 +#: utils/adt/pseudotypes.c:307 #, c-format msgid "cannot accept a value of a shell type" msgstr "не можна прийняти значення типу shell" -#: utils/adt/pseudotypes.c:320 +#: utils/adt/pseudotypes.c:317 #, c-format msgid "cannot display a value of a shell type" msgstr "не можна відобразити значення типу shell" -#: utils/adt/rangetypes.c:415 +#: utils/adt/rangetypes.c:422 #, c-format msgid "range constructor flags argument must not be null" msgstr "аргумент позначок конструктору діапазону не може бути null" -#: utils/adt/rangetypes.c:1014 +#: utils/adt/rangetypes.c:1021 #, c-format msgid "result of range difference would not be contiguous" msgstr "результат різниці діапазонів не буде безперервним" -#: utils/adt/rangetypes.c:1075 +#: utils/adt/rangetypes.c:1082 #, c-format msgid "result of range union would not be contiguous" msgstr "результат об'єднання діапазонів не буде безперервним" -#: utils/adt/rangetypes.c:1750 +#: utils/adt/rangetypes.c:1757 #, c-format msgid "range lower bound must be less than or equal to range upper bound" msgstr "нижня границя діапазону повинна бути менше або дорівнювати верхній границі діапазону" -#: utils/adt/rangetypes.c:2197 utils/adt/rangetypes.c:2210 -#: utils/adt/rangetypes.c:2224 +#: utils/adt/rangetypes.c:2256 utils/adt/rangetypes.c:2269 +#: utils/adt/rangetypes.c:2283 #, c-format msgid "invalid range bound flags" msgstr "неприпустимі позначки границь діапазону" -#: utils/adt/rangetypes.c:2198 utils/adt/rangetypes.c:2211 -#: utils/adt/rangetypes.c:2225 +#: utils/adt/rangetypes.c:2257 utils/adt/rangetypes.c:2270 +#: utils/adt/rangetypes.c:2284 #, c-format msgid "Valid values are \"[]\", \"[)\", \"(]\", and \"()\"." msgstr "Припустимі значення \"[]\", \"[)\", \"(]\", і \"()\"." -#: utils/adt/rangetypes.c:2293 utils/adt/rangetypes.c:2310 -#: utils/adt/rangetypes.c:2325 utils/adt/rangetypes.c:2345 -#: utils/adt/rangetypes.c:2356 utils/adt/rangetypes.c:2403 -#: utils/adt/rangetypes.c:2411 +#: utils/adt/rangetypes.c:2352 utils/adt/rangetypes.c:2369 +#: utils/adt/rangetypes.c:2384 utils/adt/rangetypes.c:2404 +#: utils/adt/rangetypes.c:2415 utils/adt/rangetypes.c:2462 +#: utils/adt/rangetypes.c:2470 #, c-format msgid "malformed range literal: \"%s\"" msgstr "неправильний літерал діапазону: \"%s\"" -#: utils/adt/rangetypes.c:2295 +#: utils/adt/rangetypes.c:2354 #, c-format msgid "Junk after \"empty\" key word." msgstr "Сміття після ключового слова \"empty\"." -#: utils/adt/rangetypes.c:2312 +#: utils/adt/rangetypes.c:2371 #, c-format msgid "Missing left parenthesis or bracket." msgstr "Пропущено ліву дужку (круглу або квадратну)." -#: utils/adt/rangetypes.c:2327 +#: utils/adt/rangetypes.c:2386 #, c-format msgid "Missing comma after lower bound." msgstr "Пропущено кому після нижньої границі." -#: utils/adt/rangetypes.c:2347 +#: utils/adt/rangetypes.c:2406 #, c-format msgid "Too many commas." msgstr "Занадто багато ком." -#: utils/adt/rangetypes.c:2358 +#: utils/adt/rangetypes.c:2417 #, c-format msgid "Junk after right parenthesis or bracket." msgstr "Сміття після правої дужки." -#: utils/adt/regexp.c:305 utils/adt/regexp.c:1997 utils/adt/varlena.c:4270 +#: utils/adt/regexp.c:304 utils/adt/regexp.c:1996 utils/adt/varlena.c:4273 #, c-format msgid "regular expression failed: %s" msgstr "помилка в регулярному виразі: %s" -#: utils/adt/regexp.c:446 utils/adt/regexp.c:681 +#: utils/adt/regexp.c:445 utils/adt/regexp.c:680 #, c-format msgid "invalid regular expression option: \"%.*s\"" msgstr "неприпустимий параметр регулярного виразу: \"%.*s\"" -#: utils/adt/regexp.c:683 +#: utils/adt/regexp.c:682 #, c-format msgid "If you meant to use regexp_replace() with a start parameter, cast the fourth argument to integer explicitly." msgstr "Якщо ви хочете використовувати regexp_replace() з початковим параметром, приведіть тип четвертого аргумента до цілого числа." -#: utils/adt/regexp.c:717 utils/adt/regexp.c:726 utils/adt/regexp.c:1083 -#: utils/adt/regexp.c:1147 utils/adt/regexp.c:1156 utils/adt/regexp.c:1165 -#: utils/adt/regexp.c:1174 utils/adt/regexp.c:1854 utils/adt/regexp.c:1863 -#: utils/adt/regexp.c:1872 utils/misc/guc.c:6627 utils/misc/guc.c:6661 +#: utils/adt/regexp.c:716 utils/adt/regexp.c:725 utils/adt/regexp.c:1082 +#: utils/adt/regexp.c:1146 utils/adt/regexp.c:1155 utils/adt/regexp.c:1164 +#: utils/adt/regexp.c:1173 utils/adt/regexp.c:1853 utils/adt/regexp.c:1862 +#: utils/adt/regexp.c:1871 utils/misc/guc.c:6785 utils/misc/guc.c:6819 #, c-format msgid "invalid value for parameter \"%s\": %d" msgstr "неприпустиме значення для параметра \"%s\": %d" -#: utils/adt/regexp.c:937 +#: utils/adt/regexp.c:936 #, c-format msgid "SQL regular expression may not contain more than two escape-double-quote separators" msgstr "Регулярний вираз SQL не може містити більше двох роздільників escape-double-quote" #. translator: %s is a SQL function name -#: utils/adt/regexp.c:1094 utils/adt/regexp.c:1185 utils/adt/regexp.c:1272 -#: utils/adt/regexp.c:1311 utils/adt/regexp.c:1699 utils/adt/regexp.c:1754 -#: utils/adt/regexp.c:1883 +#: utils/adt/regexp.c:1093 utils/adt/regexp.c:1184 utils/adt/regexp.c:1271 +#: utils/adt/regexp.c:1310 utils/adt/regexp.c:1698 utils/adt/regexp.c:1753 +#: utils/adt/regexp.c:1882 #, c-format msgid "%s does not support the \"global\" option" msgstr "%s не підтримує параметр \"global\"" -#: utils/adt/regexp.c:1313 +#: utils/adt/regexp.c:1312 #, c-format msgid "Use the regexp_matches function instead." msgstr "Використайте функцію regexp_matches замість." -#: utils/adt/regexp.c:1501 +#: utils/adt/regexp.c:1500 #, c-format msgid "too many regular expression matches" msgstr "занадто багато відповідностей для регулярного виразу" @@ -25240,18 +26293,18 @@ msgstr "ім'я \"%s\" мають декілька функцій" msgid "more than one operator named %s" msgstr "ім'я %s мають декілька операторів" -#: utils/adt/regproc.c:670 gram.y:8841 +#: utils/adt/regproc.c:670 gram.y:8992 #, c-format msgid "missing argument" msgstr "пропущено аргумент" -#: utils/adt/regproc.c:671 gram.y:8842 +#: utils/adt/regproc.c:671 gram.y:8993 #, c-format msgid "Use NONE to denote the missing argument of a unary operator." msgstr "Щоб позначити пропущений аргумент унарного оператору, використайте NONE." -#: utils/adt/regproc.c:675 utils/adt/regproc.c:2009 utils/adt/ruleutils.c:10018 -#: utils/adt/ruleutils.c:10231 +#: utils/adt/regproc.c:675 utils/adt/regproc.c:2029 utils/adt/ruleutils.c:10498 +#: utils/adt/ruleutils.c:10711 #, c-format msgid "too many arguments" msgstr "занадто багато аргументів" @@ -25261,308 +26314,319 @@ msgstr "занадто багато аргументів" msgid "Provide two argument types for operator." msgstr "Надайте для оператора два типи аргументів." -#: utils/adt/regproc.c:1544 utils/adt/regproc.c:1661 utils/adt/regproc.c:1790 -#: utils/adt/regproc.c:1795 utils/adt/varlena.c:3410 utils/adt/varlena.c:3415 +#: utils/adt/regproc.c:1564 utils/adt/regproc.c:1681 utils/adt/regproc.c:1810 +#: utils/adt/regproc.c:1815 utils/adt/varlena.c:3413 utils/adt/varlena.c:3418 #, c-format msgid "invalid name syntax" msgstr "неприпустимий синтаксис в імені" -#: utils/adt/regproc.c:1904 +#: utils/adt/regproc.c:1924 #, c-format msgid "expected a left parenthesis" msgstr "очікувалась ліва дужка" -#: utils/adt/regproc.c:1922 +#: utils/adt/regproc.c:1942 #, c-format msgid "expected a right parenthesis" msgstr "очікувалась права дужка" -#: utils/adt/regproc.c:1941 +#: utils/adt/regproc.c:1961 #, c-format msgid "expected a type name" msgstr "очікувалось ім'я типу" -#: utils/adt/regproc.c:1973 +#: utils/adt/regproc.c:1993 #, c-format msgid "improper type name" msgstr "неправильне ім'я типу" -#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1625 -#: utils/adt/ri_triggers.c:2610 +#: utils/adt/ri_triggers.c:303 utils/adt/ri_triggers.c:1616 +#: utils/adt/ri_triggers.c:2601 #, c-format msgid "insert or update on table \"%s\" violates foreign key constraint \"%s\"" msgstr "insert або update в таблиці \"%s\" порушує обмеження зовнішнього ключа \"%s\"" -#: utils/adt/ri_triggers.c:309 utils/adt/ri_triggers.c:1628 +#: utils/adt/ri_triggers.c:306 utils/adt/ri_triggers.c:1619 #, c-format msgid "MATCH FULL does not allow mixing of null and nonnull key values." msgstr "MATCH FULL не дозволяє змішувати в значенні ключа null і nonnull." -#: utils/adt/ri_triggers.c:2045 +#: utils/adt/ri_triggers.c:2036 #, c-format msgid "function \"%s\" must be fired for INSERT" msgstr "функція \"%s\" повинна запускатись для INSERT" -#: utils/adt/ri_triggers.c:2051 +#: utils/adt/ri_triggers.c:2042 #, c-format msgid "function \"%s\" must be fired for UPDATE" msgstr "функція \"%s\" повинна запускатись для UPDATE" -#: utils/adt/ri_triggers.c:2057 +#: utils/adt/ri_triggers.c:2048 #, c-format msgid "function \"%s\" must be fired for DELETE" msgstr "функція \"%s\" повинна запускатись для DELETE" -#: utils/adt/ri_triggers.c:2080 +#: utils/adt/ri_triggers.c:2071 #, c-format msgid "no pg_constraint entry for trigger \"%s\" on table \"%s\"" msgstr "для тригеру \"%s\" таблиці \"%s\" немає введення pg_constraint" -#: utils/adt/ri_triggers.c:2082 +#: utils/adt/ri_triggers.c:2073 #, c-format msgid "Remove this referential integrity trigger and its mates, then do ALTER TABLE ADD CONSTRAINT." msgstr "Видаліть цей тригер цілісності зв’язків і пов'язані об'єкти, а потім виконайте ALTER TABLE ADD CONSTRAINT." -#: utils/adt/ri_triggers.c:2112 gram.y:4223 +#: utils/adt/ri_triggers.c:2103 gram.y:4340 #, c-format msgid "MATCH PARTIAL not yet implemented" msgstr "Вираз MATCH PARTIAL все ще не реалізований" -#: utils/adt/ri_triggers.c:2435 +#: utils/adt/ri_triggers.c:2426 #, c-format msgid "referential integrity query on \"%s\" from constraint \"%s\" on \"%s\" gave unexpected result" msgstr "неочікуваний результат запиту цілісності зв’язків до \"%s\" з обмеження \"%s\" таблиці \"%s\"" -#: utils/adt/ri_triggers.c:2439 +#: utils/adt/ri_triggers.c:2430 #, c-format msgid "This is most likely due to a rule having rewritten the query." msgstr "Скоріше за все, це викликано правилом, яке переписало запит." -#: utils/adt/ri_triggers.c:2600 +#: utils/adt/ri_triggers.c:2591 #, c-format msgid "removing partition \"%s\" violates foreign key constraint \"%s\"" msgstr "видалення секції \"%s\" порушує обмеження зовнішнього ключа \"%s" -#: utils/adt/ri_triggers.c:2603 utils/adt/ri_triggers.c:2628 +#: utils/adt/ri_triggers.c:2594 utils/adt/ri_triggers.c:2619 #, c-format msgid "Key (%s)=(%s) is still referenced from table \"%s\"." msgstr "На ключ (%s)=(%s) все ще є посилання в таблиці \"%s\"." -#: utils/adt/ri_triggers.c:2614 +#: utils/adt/ri_triggers.c:2605 #, c-format msgid "Key (%s)=(%s) is not present in table \"%s\"." msgstr "Ключ (%s)=(%s) не присутній в таблиці \"%s\"." -#: utils/adt/ri_triggers.c:2617 +#: utils/adt/ri_triggers.c:2608 #, c-format msgid "Key is not present in table \"%s\"." msgstr "Ключ не присутній в таблиці \"%s\"." -#: utils/adt/ri_triggers.c:2623 +#: utils/adt/ri_triggers.c:2614 #, c-format msgid "update or delete on table \"%s\" violates foreign key constraint \"%s\" on table \"%s\"" msgstr "update або delete в таблиці \"%s\" порушує обмеження зовнішнього ключа \"%s\" таблиці \"%s\"" -#: utils/adt/ri_triggers.c:2631 +#: utils/adt/ri_triggers.c:2622 #, c-format msgid "Key is still referenced from table \"%s\"." msgstr "На ключ все ще є посилання в таблиці \"%s\"." -#: utils/adt/rowtypes.c:106 utils/adt/rowtypes.c:510 +#: utils/adt/rowtypes.c:105 utils/adt/rowtypes.c:509 #, c-format msgid "input of anonymous composite types is not implemented" msgstr "введення анонімних складених типів не реалізовано" -#: utils/adt/rowtypes.c:159 utils/adt/rowtypes.c:191 utils/adt/rowtypes.c:217 -#: utils/adt/rowtypes.c:228 utils/adt/rowtypes.c:286 utils/adt/rowtypes.c:297 +#: utils/adt/rowtypes.c:158 utils/adt/rowtypes.c:190 utils/adt/rowtypes.c:216 +#: utils/adt/rowtypes.c:227 utils/adt/rowtypes.c:285 utils/adt/rowtypes.c:296 #, c-format msgid "malformed record literal: \"%s\"" msgstr "невірно сформований літерал запису: \"%s\"" -#: utils/adt/rowtypes.c:160 +#: utils/adt/rowtypes.c:159 #, c-format msgid "Missing left parenthesis." msgstr "Відсутня ліва дужка." -#: utils/adt/rowtypes.c:192 +#: utils/adt/rowtypes.c:191 #, c-format msgid "Too few columns." msgstr "Занадто мало стовпців." -#: utils/adt/rowtypes.c:287 +#: utils/adt/rowtypes.c:286 #, c-format msgid "Too many columns." msgstr "Занадто багато стовпців." -#: utils/adt/rowtypes.c:298 +#: utils/adt/rowtypes.c:297 #, c-format msgid "Junk after right parenthesis." msgstr "Сміття післа правої дужки." -#: utils/adt/rowtypes.c:559 +#: utils/adt/rowtypes.c:558 #, c-format msgid "wrong number of columns: %d, expected %d" msgstr "неправильна кількість стовпців: %d, очікувалось %d" -#: utils/adt/rowtypes.c:601 +#: utils/adt/rowtypes.c:599 #, c-format msgid "binary data has type %u (%s) instead of expected %u (%s) in record column %d" msgstr "двійкові дані мають тип %u (%s) замість очікуваного %u (%s) в стовпці запису %d" -#: utils/adt/rowtypes.c:668 +#: utils/adt/rowtypes.c:660 #, c-format msgid "improper binary format in record column %d" msgstr "неправильний двійковий формат у стовпці запису %d" -#: utils/adt/rowtypes.c:959 utils/adt/rowtypes.c:1205 utils/adt/rowtypes.c:1463 -#: utils/adt/rowtypes.c:1709 +#: utils/adt/rowtypes.c:949 utils/adt/rowtypes.c:1195 utils/adt/rowtypes.c:1453 +#: utils/adt/rowtypes.c:1699 #, c-format msgid "cannot compare dissimilar column types %s and %s at record column %d" msgstr "не можна порівнювати неподібні типи стовпців %s і %s, стовпець запису %d" -#: utils/adt/rowtypes.c:1050 utils/adt/rowtypes.c:1275 -#: utils/adt/rowtypes.c:1560 utils/adt/rowtypes.c:1745 +#: utils/adt/rowtypes.c:1040 utils/adt/rowtypes.c:1265 +#: utils/adt/rowtypes.c:1550 utils/adt/rowtypes.c:1735 #, c-format msgid "cannot compare record types with different numbers of columns" msgstr "не можна порівнювати типи записів з різної кількістю стовпців" -#: utils/adt/ruleutils.c:2679 +#: utils/adt/ruleutils.c:2689 #, c-format msgid "input is a query, not an expression" msgstr "вхідне значення є запитом, а не виразом" -#: utils/adt/ruleutils.c:2691 +#: utils/adt/ruleutils.c:2701 #, c-format msgid "expression contains variables of more than one relation" msgstr "вираз містить змінні більше одного відношення" -#: utils/adt/ruleutils.c:2698 +#: utils/adt/ruleutils.c:2708 #, c-format msgid "expression contains variables" msgstr "вираз містить змінні" -#: utils/adt/ruleutils.c:5225 +#: utils/adt/ruleutils.c:5241 #, c-format msgid "rule \"%s\" has unsupported event type %d" msgstr "правило \"%s\" має непідтримуваний тип подій %d" -#: utils/adt/timestamp.c:112 +#: utils/adt/timestamp.c:128 #, c-format msgid "TIMESTAMP(%d)%s precision must not be negative" msgstr "TIMESTAMP(%d)%s точність не повинна бути від'ємною" -#: utils/adt/timestamp.c:118 +#: utils/adt/timestamp.c:134 #, c-format msgid "TIMESTAMP(%d)%s precision reduced to maximum allowed, %d" msgstr "TIMESTAMP(%d)%s точність зменшена до дозволеного максимуму, %d" -#: utils/adt/timestamp.c:378 +#: utils/adt/timestamp.c:394 #, c-format msgid "timestamp(%d) precision must be between %d and %d" msgstr "точність позначки часу (%d) повинна бути між %d і %d" -#: utils/adt/timestamp.c:496 +#: utils/adt/timestamp.c:512 #, c-format msgid "Numeric time zones must have \"-\" or \"+\" as first character." msgstr "Числові часові пояси повинні мати \"-\" або \"+\" в якості першого символу." -#: utils/adt/timestamp.c:508 +#: utils/adt/timestamp.c:524 #, c-format msgid "numeric time zone \"%s\" out of range" msgstr "числовий часовий пояс \"%s\" поза діапазоном" -#: utils/adt/timestamp.c:609 utils/adt/timestamp.c:619 -#: utils/adt/timestamp.c:627 +#: utils/adt/timestamp.c:625 utils/adt/timestamp.c:635 +#: utils/adt/timestamp.c:643 #, c-format msgid "timestamp out of range: %d-%02d-%02d %d:%02d:%02g" msgstr "позначка часу поза діапазоном: %d-%02d-%02d %d:%02d:%02g" -#: utils/adt/timestamp.c:728 +#: utils/adt/timestamp.c:744 #, c-format msgid "timestamp cannot be NaN" msgstr "позначка часу не може бути NaN" -#: utils/adt/timestamp.c:746 utils/adt/timestamp.c:758 +#: utils/adt/timestamp.c:762 utils/adt/timestamp.c:774 #, c-format msgid "timestamp out of range: \"%g\"" msgstr "позначка часу поза діапазоном: \"%g\"" -#: utils/adt/timestamp.c:941 utils/adt/timestamp.c:1518 -#: utils/adt/timestamp.c:2708 utils/adt/timestamp.c:2778 -#: utils/adt/timestamp.c:2795 utils/adt/timestamp.c:2848 -#: utils/adt/timestamp.c:2887 utils/adt/timestamp.c:3203 -#: utils/adt/timestamp.c:3208 utils/adt/timestamp.c:3213 -#: utils/adt/timestamp.c:3263 utils/adt/timestamp.c:3270 -#: utils/adt/timestamp.c:3277 utils/adt/timestamp.c:3297 -#: utils/adt/timestamp.c:3304 utils/adt/timestamp.c:3311 -#: utils/adt/timestamp.c:3398 utils/adt/timestamp.c:3473 -#: utils/adt/timestamp.c:3842 utils/adt/timestamp.c:3966 -#: utils/adt/timestamp.c:4486 +#: utils/adt/timestamp.c:957 utils/adt/timestamp.c:1516 +#: utils/adt/timestamp.c:1526 utils/adt/timestamp.c:1587 +#: utils/adt/timestamp.c:2807 utils/adt/timestamp.c:2816 +#: utils/adt/timestamp.c:2831 utils/adt/timestamp.c:2905 +#: utils/adt/timestamp.c:2922 utils/adt/timestamp.c:2979 +#: utils/adt/timestamp.c:3022 utils/adt/timestamp.c:3400 +#: utils/adt/timestamp.c:3458 utils/adt/timestamp.c:3481 +#: utils/adt/timestamp.c:3490 utils/adt/timestamp.c:3514 +#: utils/adt/timestamp.c:3537 utils/adt/timestamp.c:3546 +#: utils/adt/timestamp.c:3681 utils/adt/timestamp.c:3782 +#: utils/adt/timestamp.c:4189 utils/adt/timestamp.c:4226 +#: utils/adt/timestamp.c:4274 utils/adt/timestamp.c:4283 +#: utils/adt/timestamp.c:4375 utils/adt/timestamp.c:4422 +#: utils/adt/timestamp.c:4431 utils/adt/timestamp.c:4527 +#: utils/adt/timestamp.c:4580 utils/adt/timestamp.c:4590 +#: utils/adt/timestamp.c:4785 utils/adt/timestamp.c:4795 +#: utils/adt/timestamp.c:5097 #, c-format msgid "interval out of range" msgstr "інтервал поза діапазоном" -#: utils/adt/timestamp.c:1065 utils/adt/timestamp.c:1098 +#: utils/adt/timestamp.c:1094 utils/adt/timestamp.c:1127 #, c-format msgid "invalid INTERVAL type modifier" msgstr "неприпустимий модифікатор типу INTERVAL" -#: utils/adt/timestamp.c:1081 +#: utils/adt/timestamp.c:1110 #, c-format msgid "INTERVAL(%d) precision must not be negative" msgstr "INTERVAL(%d) точність не повинна бути від'ємною" -#: utils/adt/timestamp.c:1087 +#: utils/adt/timestamp.c:1116 #, c-format msgid "INTERVAL(%d) precision reduced to maximum allowed, %d" msgstr "INTERVAL(%d) точність зменшена до максимально можливої, %d" -#: utils/adt/timestamp.c:1473 +#: utils/adt/timestamp.c:1506 #, c-format msgid "interval(%d) precision must be between %d and %d" msgstr "interval(%d) точність повинна бути між %d і %d" -#: utils/adt/timestamp.c:2703 -#, c-format -msgid "cannot subtract infinite timestamps" -msgstr "віднімати безкінечні позначки часу не можна" - -#: utils/adt/timestamp.c:4002 utils/adt/timestamp.c:4185 +#: utils/adt/timestamp.c:4564 utils/adt/timestamp.c:4769 #, c-format msgid "origin out of range" msgstr "джерело поза діапазоном" -#: utils/adt/timestamp.c:4007 utils/adt/timestamp.c:4190 +#: utils/adt/timestamp.c:4569 utils/adt/timestamp.c:4774 +#, c-format +msgid "timestamps cannot be binned into infinite intervals" +msgstr "мітки часу не можуть бути розбиті на нескінченні інтервали" + +#: utils/adt/timestamp.c:4574 utils/adt/timestamp.c:4779 #, c-format msgid "timestamps cannot be binned into intervals containing months or years" msgstr "позначки часу не можна розділяти на інтервали, що містять місяці або роки" -#: utils/adt/timestamp.c:4014 utils/adt/timestamp.c:4197 +#: utils/adt/timestamp.c:4585 utils/adt/timestamp.c:4790 #, c-format msgid "stride must be greater than zero" msgstr "крок повинен бути більше нуля" -#: utils/adt/timestamp.c:4480 +#: utils/adt/timestamp.c:5091 #, c-format msgid "Months usually have fractional weeks." msgstr "У місяців зазвичай є дробові тижні." -#: utils/adt/trigfuncs.c:42 +#: utils/adt/timestamp.c:6551 utils/adt/timestamp.c:6637 +#, c-format +msgid "step size cannot be infinite" +msgstr "розмір кроку не може бути нескінченним" + +#: utils/adt/trigfuncs.c:41 #, c-format msgid "suppress_redundant_updates_trigger: must be called as trigger" msgstr "suppress_redundant_updates_trigger: повинна викликатись як тригер" -#: utils/adt/trigfuncs.c:48 +#: utils/adt/trigfuncs.c:47 #, c-format msgid "suppress_redundant_updates_trigger: must be called on update" msgstr "suppress_redundant_updates_trigger: повинна викликатись при оновленні" -#: utils/adt/trigfuncs.c:54 +#: utils/adt/trigfuncs.c:53 #, c-format msgid "suppress_redundant_updates_trigger: must be called before update" msgstr "suppress_redundant_updates_trigger: повинна викликатись перед оновленням" -#: utils/adt/trigfuncs.c:60 +#: utils/adt/trigfuncs.c:59 #, c-format msgid "suppress_redundant_updates_trigger: must be called for each row" msgstr "suppress_redundant_updates_trigger: повинна викликатис перед кожним рядком" @@ -25577,32 +26641,32 @@ msgstr "відстань у фразовому операторі повинна msgid "no operand in tsquery: \"%s\"" msgstr "немає оператора в tsquery: \"%s\"" -#: utils/adt/tsquery.c:558 +#: utils/adt/tsquery.c:554 #, c-format msgid "value is too big in tsquery: \"%s\"" msgstr "занадто велике значення в tsquery: \"%s\"" -#: utils/adt/tsquery.c:563 +#: utils/adt/tsquery.c:559 #, c-format msgid "operand is too long in tsquery: \"%s\"" msgstr "занадто довгий операнд в tsquery: \"%s\"" -#: utils/adt/tsquery.c:591 +#: utils/adt/tsquery.c:587 #, c-format msgid "word is too long in tsquery: \"%s\"" msgstr "занадто довге слово в tsquery: \"%s\"" -#: utils/adt/tsquery.c:717 utils/adt/tsvector_parser.c:147 +#: utils/adt/tsquery.c:713 utils/adt/tsvector_parser.c:147 #, c-format msgid "syntax error in tsquery: \"%s\"" msgstr "синтаксична помилка в tsquery: \"%s\"" -#: utils/adt/tsquery.c:883 +#: utils/adt/tsquery.c:879 #, c-format msgid "text-search query doesn't contain lexemes: \"%s\"" msgstr "запит пошуку тексту не містить лексем: \"%s\"" -#: utils/adt/tsquery.c:894 utils/adt/tsquery_util.c:376 +#: utils/adt/tsquery.c:890 utils/adt/tsquery_util.c:376 #, c-format msgid "tsquery is too large" msgstr "tsquery занадто великий" @@ -25637,72 +26701,72 @@ msgstr "масив значимості не повинен містити null" msgid "weight out of range" msgstr "значимість поза діапазоном" -#: utils/adt/tsvector.c:217 +#: utils/adt/tsvector.c:216 #, c-format msgid "word is too long (%ld bytes, max %ld bytes)" msgstr "слово занадто довге (%ld байт, при максимумі %ld)" -#: utils/adt/tsvector.c:224 +#: utils/adt/tsvector.c:223 #, c-format msgid "string is too long for tsvector (%ld bytes, max %ld bytes)" msgstr "рядок занадто довгий для tsvector (%ld байт, при максимумі %ld)" -#: utils/adt/tsvector_op.c:773 +#: utils/adt/tsvector_op.c:771 #, c-format msgid "lexeme array may not contain nulls" msgstr "масив лексем не може містити null" -#: utils/adt/tsvector_op.c:778 +#: utils/adt/tsvector_op.c:776 #, c-format msgid "lexeme array may not contain empty strings" msgstr "масив лексем не може містити порожніх рядків" -#: utils/adt/tsvector_op.c:847 +#: utils/adt/tsvector_op.c:845 #, c-format msgid "weight array may not contain nulls" msgstr "масив значимості не може містити null" -#: utils/adt/tsvector_op.c:871 +#: utils/adt/tsvector_op.c:869 #, c-format msgid "unrecognized weight: \"%c\"" msgstr "нерозпізнана значимість: \"%c\"" -#: utils/adt/tsvector_op.c:2601 +#: utils/adt/tsvector_op.c:2599 #, c-format msgid "ts_stat query must return one tsvector column" msgstr "запит ts_stat повинен повернути один стовпець tsvector" -#: utils/adt/tsvector_op.c:2790 +#: utils/adt/tsvector_op.c:2788 #, c-format msgid "tsvector column \"%s\" does not exist" msgstr "стовпець типу tsvector \"%s\" не існує" -#: utils/adt/tsvector_op.c:2797 +#: utils/adt/tsvector_op.c:2795 #, c-format msgid "column \"%s\" is not of tsvector type" msgstr "стовпець \"%s\" повинен мати тип tsvector" -#: utils/adt/tsvector_op.c:2809 +#: utils/adt/tsvector_op.c:2807 #, c-format msgid "configuration column \"%s\" does not exist" msgstr "стовпець конфігурації \"%s\" не існує" -#: utils/adt/tsvector_op.c:2815 +#: utils/adt/tsvector_op.c:2813 #, c-format msgid "column \"%s\" is not of regconfig type" msgstr "стовпець \"%s\" повинен мати тип regconfig" -#: utils/adt/tsvector_op.c:2822 +#: utils/adt/tsvector_op.c:2820 #, c-format msgid "configuration column \"%s\" must not be null" msgstr "значення стовпця конфігурації \"%s\" не повинне бути null" -#: utils/adt/tsvector_op.c:2835 +#: utils/adt/tsvector_op.c:2833 #, c-format msgid "text search configuration name \"%s\" must be schema-qualified" msgstr "ім'я конфігурації текстового пошуку \"%s\" повинно вказуватися зі схемою" -#: utils/adt/tsvector_op.c:2860 +#: utils/adt/tsvector_op.c:2858 #, c-format msgid "column \"%s\" is not of a character type" msgstr "стовпець \"%s\" має не символьний тип" @@ -25722,17 +26786,17 @@ msgstr "немає пропущеного символу: \"%s\"" msgid "wrong position info in tsvector: \"%s\"" msgstr "неправильна інформація про позицію в tsvector: \"%s\"" -#: utils/adt/uuid.c:413 +#: utils/adt/uuid.c:418 #, c-format msgid "could not generate random values" msgstr "не вдалося згенерувати випадкові значення" -#: utils/adt/varbit.c:110 utils/adt/varchar.c:54 +#: utils/adt/varbit.c:110 utils/adt/varchar.c:53 #, c-format msgid "length for type %s must be at least 1" msgstr "довжина для типу %s повинна бути мінімум 1" -#: utils/adt/varbit.c:115 utils/adt/varchar.c:58 +#: utils/adt/varbit.c:115 utils/adt/varchar.c:57 #, c-format msgid "length for type %s cannot exceed %d" msgstr "довжина для типу %s не може перевищувати %d" @@ -25767,9 +26831,9 @@ msgstr "неприпустима довжина у зовнішньому ряд msgid "bit string too long for type bit varying(%d)" msgstr "рядок бітів занадто довгий для типу bit varying(%d)" -#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:908 -#: utils/adt/varlena.c:971 utils/adt/varlena.c:1128 utils/adt/varlena.c:3052 -#: utils/adt/varlena.c:3130 +#: utils/adt/varbit.c:1081 utils/adt/varbit.c:1191 utils/adt/varlena.c:911 +#: utils/adt/varlena.c:974 utils/adt/varlena.c:1131 utils/adt/varlena.c:3055 +#: utils/adt/varlena.c:3133 #, c-format msgid "negative substring length not allowed" msgstr "від'ємна довжина підрядка не дозволена" @@ -25794,122 +26858,127 @@ msgstr "не можна використовувати (XOR) для бітови msgid "bit index %d out of valid range (0..%d)" msgstr "індекс біту %d поза припустимим діапазоном (0..%d)" -#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3334 +#: utils/adt/varbit.c:1833 utils/adt/varlena.c:3337 #, c-format msgid "new bit must be 0 or 1" msgstr "новий біт повинен бути 0 або 1" -#: utils/adt/varchar.c:162 utils/adt/varchar.c:313 +#: utils/adt/varchar.c:161 utils/adt/varchar.c:312 #, c-format msgid "value too long for type character(%d)" msgstr "значення занадто довге для типу character(%d)" -#: utils/adt/varchar.c:476 utils/adt/varchar.c:640 +#: utils/adt/varchar.c:475 utils/adt/varchar.c:639 #, c-format msgid "value too long for type character varying(%d)" msgstr "значення занадто довге для типу character varying(%d)" -#: utils/adt/varchar.c:738 utils/adt/varlena.c:1517 +#: utils/adt/varchar.c:737 utils/adt/varlena.c:1520 #, c-format msgid "could not determine which collation to use for string comparison" msgstr "не вдалося визначити, який параметр сортування використати для порівняння рядків" -#: utils/adt/varlena.c:1227 utils/adt/varlena.c:1806 +#: utils/adt/varlena.c:1230 utils/adt/varlena.c:1809 #, c-format msgid "nondeterministic collations are not supported for substring searches" msgstr "недетерміновані параметри сортування не підтримуються для пошуку підрядків" -#: utils/adt/varlena.c:3218 utils/adt/varlena.c:3285 +#: utils/adt/varlena.c:3221 utils/adt/varlena.c:3288 #, c-format msgid "index %d out of valid range, 0..%d" msgstr "індекс %d поза припустимим діапазоном, 0..%d" -#: utils/adt/varlena.c:3249 utils/adt/varlena.c:3321 +#: utils/adt/varlena.c:3252 utils/adt/varlena.c:3324 #, c-format msgid "index %lld out of valid range, 0..%lld" msgstr "індекс %lld поза допустимим діапазоном, 0..%lld" -#: utils/adt/varlena.c:4382 +#: utils/adt/varlena.c:4385 #, c-format msgid "field position must not be zero" msgstr "позиція поля не повинна бути нульовою" -#: utils/adt/varlena.c:5554 +#: utils/adt/varlena.c:5630 #, c-format msgid "unterminated format() type specifier" msgstr "незавершений специфікатор типу format()" -#: utils/adt/varlena.c:5555 utils/adt/varlena.c:5689 utils/adt/varlena.c:5810 +#: utils/adt/varlena.c:5631 utils/adt/varlena.c:5765 utils/adt/varlena.c:5886 #, c-format msgid "For a single \"%%\" use \"%%%%\"." msgstr "Для представлення одного знаку \"%%\", використайте \"%%%%\"." -#: utils/adt/varlena.c:5687 utils/adt/varlena.c:5808 +#: utils/adt/varlena.c:5763 utils/adt/varlena.c:5884 #, c-format msgid "unrecognized format() type specifier \"%.*s\"" msgstr "нерозпізнаний специфікатор типу format() \"%.*s\"" -#: utils/adt/varlena.c:5700 utils/adt/varlena.c:5757 +#: utils/adt/varlena.c:5776 utils/adt/varlena.c:5833 #, c-format msgid "too few arguments for format()" msgstr "занадто мало аргументів для format()" -#: utils/adt/varlena.c:5853 utils/adt/varlena.c:6035 +#: utils/adt/varlena.c:5929 utils/adt/varlena.c:6111 #, c-format msgid "number is out of range" msgstr "число поза діапазоном" -#: utils/adt/varlena.c:5916 utils/adt/varlena.c:5944 +#: utils/adt/varlena.c:5992 utils/adt/varlena.c:6020 #, c-format msgid "format specifies argument 0, but arguments are numbered from 1" msgstr "формат посилається на аргумент 0, але аргументи нумеруются з 1" -#: utils/adt/varlena.c:5937 +#: utils/adt/varlena.c:6013 #, c-format msgid "width argument position must be ended by \"$\"" msgstr "вказівка аргументу ширини повинно закінчуватися \"$\"" -#: utils/adt/varlena.c:5982 +#: utils/adt/varlena.c:6058 #, c-format msgid "null values cannot be formatted as an SQL identifier" msgstr "значення null не можна форматувати у вигляді SQL-ідентифікатору" -#: utils/adt/varlena.c:6190 +#: utils/adt/varlena.c:6266 #, c-format msgid "Unicode normalization can only be performed if server encoding is UTF8" msgstr "Нормалізація Unicode може виконуватись лише тоді, коли кодування серверу - UTF8" -#: utils/adt/varlena.c:6203 +#: utils/adt/varlena.c:6279 #, c-format msgid "invalid normalization form: %s" msgstr "неприпустима форма нормалізації: %s" -#: utils/adt/varlena.c:6406 utils/adt/varlena.c:6441 utils/adt/varlena.c:6476 +#: utils/adt/varlena.c:6324 +#, c-format +msgid "Unicode categorization can only be performed if server encoding is UTF8" +msgstr "Категоризація в юні коді може бути виконана, тільки якщо кодування сервера - UTF8" + +#: utils/adt/varlena.c:6541 utils/adt/varlena.c:6576 utils/adt/varlena.c:6611 #, c-format msgid "invalid Unicode code point: %04X" msgstr "неприпустима точка коду Unicode: %04X" -#: utils/adt/varlena.c:6506 +#: utils/adt/varlena.c:6641 #, c-format msgid "Unicode escapes must be \\XXXX, \\+XXXXXX, \\uXXXX, or \\UXXXXXXXX." msgstr "Спеціальні коди Unicode повинні бути \\XXXX, \\+XXXXXX, \\uXXXXXX, або \\UXXXXXX." -#: utils/adt/windowfuncs.c:442 +#: utils/adt/windowfuncs.c:443 #, c-format msgid "argument of ntile must be greater than zero" msgstr "аргумент ntile повинен бути більше нуля" -#: utils/adt/windowfuncs.c:706 +#: utils/adt/windowfuncs.c:707 #, c-format msgid "argument of nth_value must be greater than zero" msgstr "аргумент nth_value повинен бути більше нуля" -#: utils/adt/xid8funcs.c:126 +#: utils/adt/xid8funcs.c:124 #, c-format msgid "transaction ID %llu is in the future" msgstr "ідентифікатор транзакції %llu знаходиться в майбутньому" -#: utils/adt/xid8funcs.c:555 +#: utils/adt/xid8funcs.c:553 #, c-format msgid "invalid external pg_snapshot data" msgstr "неприпустимі зовнішні дані pg_snapshot" @@ -25924,7 +26993,7 @@ msgstr "XML-функції не підтримуються" msgid "This functionality requires the server to be built with libxml support." msgstr "Ця функціональність потребує, щоб сервер був побудований з підтримкою libxml." -#: utils/adt/xml.c:258 utils/mb/mbutils.c:628 +#: utils/adt/xml.c:258 utils/mb/mbutils.c:627 #, c-format msgid "invalid encoding name \"%s\"" msgstr "неприпустиме ім’я кодування \"%s\"" @@ -25934,217 +27003,217 @@ msgstr "неприпустиме ім’я кодування \"%s\"" msgid "invalid XML comment" msgstr "неприпустимий XML-коментар" -#: utils/adt/xml.c:670 +#: utils/adt/xml.c:697 #, c-format msgid "not an XML document" msgstr "не XML-документ" -#: utils/adt/xml.c:966 utils/adt/xml.c:989 +#: utils/adt/xml.c:1008 utils/adt/xml.c:1031 #, c-format msgid "invalid XML processing instruction" msgstr "неприпустима XML-команда обробки" -#: utils/adt/xml.c:967 +#: utils/adt/xml.c:1009 #, c-format msgid "XML processing instruction target name cannot be \"%s\"." msgstr "Метою XML-команди обробки не може бути \"%s\"." -#: utils/adt/xml.c:990 +#: utils/adt/xml.c:1032 #, c-format msgid "XML processing instruction cannot contain \"?>\"." msgstr "XML-команда обробки не може містити \"?>\"." -#: utils/adt/xml.c:1069 +#: utils/adt/xml.c:1111 #, c-format msgid "xmlvalidate is not implemented" msgstr "функція xmlvalidate не реалізована" -#: utils/adt/xml.c:1125 +#: utils/adt/xml.c:1167 #, c-format msgid "could not initialize XML library" msgstr "не вдалося ініціалізувати бібліотеку XML" -#: utils/adt/xml.c:1126 +#: utils/adt/xml.c:1168 #, c-format msgid "libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu." msgstr "libxml2 має несумісний тип char: sizeof(char)=%zu, sizeof(xmlChar)=%zu." -#: utils/adt/xml.c:1212 +#: utils/adt/xml.c:1254 #, c-format msgid "could not set up XML error handler" msgstr "не вдалося встановити обробник XML-помилок" -#: utils/adt/xml.c:1213 +#: utils/adt/xml.c:1255 #, c-format msgid "This probably indicates that the version of libxml2 being used is not compatible with the libxml2 header files that PostgreSQL was built with." msgstr "Можливо це означає, що використовувана версія libxml2 несумісна з файлами-заголовками libxml2, з котрими був зібраний PostgreSQL." -#: utils/adt/xml.c:2199 +#: utils/adt/xml.c:2281 msgid "Invalid character value." msgstr "Неприпустиме значення символу." -#: utils/adt/xml.c:2202 +#: utils/adt/xml.c:2284 msgid "Space required." msgstr "Потребується пробіл." -#: utils/adt/xml.c:2205 +#: utils/adt/xml.c:2287 msgid "standalone accepts only 'yes' or 'no'." msgstr "значеннями атрибуту standalone можуть бути лише 'yes' або 'no'." -#: utils/adt/xml.c:2208 +#: utils/adt/xml.c:2290 msgid "Malformed declaration: missing version." msgstr "Неправильне оголошення: пропущена версія." -#: utils/adt/xml.c:2211 +#: utils/adt/xml.c:2293 msgid "Missing encoding in text declaration." msgstr "В оголошенні пропущене кодування." -#: utils/adt/xml.c:2214 +#: utils/adt/xml.c:2296 msgid "Parsing XML declaration: '?>' expected." msgstr "Аналіз XML-оголошення: '?>' очікується." -#: utils/adt/xml.c:2217 +#: utils/adt/xml.c:2299 #, c-format msgid "Unrecognized libxml error code: %d." msgstr "Нерозпізнаний код помилки libxml: %d." -#: utils/adt/xml.c:2471 +#: utils/adt/xml.c:2553 #, c-format msgid "XML does not support infinite date values." msgstr "XML не підтримує безкінечні значення в датах." -#: utils/adt/xml.c:2493 utils/adt/xml.c:2520 +#: utils/adt/xml.c:2575 utils/adt/xml.c:2602 #, c-format msgid "XML does not support infinite timestamp values." msgstr "XML не підтримує безкінченні значення в позначках часу." -#: utils/adt/xml.c:2936 +#: utils/adt/xml.c:3018 #, c-format msgid "invalid query" msgstr "неприпустимий запит" -#: utils/adt/xml.c:3028 +#: utils/adt/xml.c:3110 #, c-format msgid "portal \"%s\" does not return tuples" msgstr "portal \"%s\" не повертає кортежі" -#: utils/adt/xml.c:4280 +#: utils/adt/xml.c:4362 #, c-format msgid "invalid array for XML namespace mapping" msgstr "неприпустимий масив з зіставленням простіру імен XML" -#: utils/adt/xml.c:4281 +#: utils/adt/xml.c:4363 #, c-format msgid "The array must be two-dimensional with length of the second axis equal to 2." msgstr "Масив повинен бути двовимірним і містити 2 елемента по другій вісі." -#: utils/adt/xml.c:4305 +#: utils/adt/xml.c:4387 #, c-format msgid "empty XPath expression" msgstr "пустий вираз XPath" -#: utils/adt/xml.c:4357 +#: utils/adt/xml.c:4439 #, c-format msgid "neither namespace name nor URI may be null" msgstr "ні ім'я простіру імен ні URI не можуть бути null" -#: utils/adt/xml.c:4364 +#: utils/adt/xml.c:4446 #, c-format msgid "could not register XML namespace with name \"%s\" and URI \"%s\"" msgstr "не вдалося зареєструвати простір імен XML з ім'ям \"%s\" і URI \"%s\"" -#: utils/adt/xml.c:4707 +#: utils/adt/xml.c:4795 #, c-format msgid "DEFAULT namespace is not supported" msgstr "Простір імен DEFAULT не підтримується" -#: utils/adt/xml.c:4736 +#: utils/adt/xml.c:4824 #, c-format msgid "row path filter must not be empty string" msgstr "шлях фільтруючих рядків не повинен бути пустим" -#: utils/adt/xml.c:4767 +#: utils/adt/xml.c:4858 #, c-format msgid "column path filter must not be empty string" msgstr "шлях фільтруючого стовпця не повинен бути пустим" -#: utils/adt/xml.c:4911 +#: utils/adt/xml.c:5005 #, c-format msgid "more than one value returned by column XPath expression" msgstr "вираз XPath, який відбирає стовпець, повернув більше одного значення" -#: utils/cache/lsyscache.c:1043 +#: utils/cache/lsyscache.c:1017 #, c-format msgid "cast from type %s to type %s does not exist" msgstr "приведення від типу %s до типу %s не існує" -#: utils/cache/lsyscache.c:2845 utils/cache/lsyscache.c:2878 -#: utils/cache/lsyscache.c:2911 utils/cache/lsyscache.c:2944 +#: utils/cache/lsyscache.c:2887 utils/cache/lsyscache.c:2920 +#: utils/cache/lsyscache.c:2953 utils/cache/lsyscache.c:2986 #, c-format msgid "type %s is only a shell" msgstr "тип %s лише оболонка" -#: utils/cache/lsyscache.c:2850 +#: utils/cache/lsyscache.c:2892 #, c-format msgid "no input function available for type %s" msgstr "для типу %s немає доступної функції введення" -#: utils/cache/lsyscache.c:2883 +#: utils/cache/lsyscache.c:2925 #, c-format msgid "no output function available for type %s" msgstr "для типу %s немає доступної функції виводу" -#: utils/cache/partcache.c:219 +#: utils/cache/partcache.c:216 #, c-format msgid "operator class \"%s\" of access method %s is missing support function %d for type %s" msgstr "в класі операторів \"%s\" методу доступу %s пропущено опорну функцію %d для типу %s" -#: utils/cache/plancache.c:724 +#: utils/cache/plancache.c:747 #, c-format msgid "cached plan must not change result type" msgstr "в кешованому плані не повинен змінюватись тип результату" -#: utils/cache/relcache.c:3741 +#: utils/cache/relcache.c:3800 #, c-format msgid "heap relfilenumber value not set when in binary upgrade mode" msgstr "значення relfilenumber не встановлене у режимі двійкового оновлення" -#: utils/cache/relcache.c:3749 +#: utils/cache/relcache.c:3808 #, c-format msgid "unexpected request for new relfilenumber in binary upgrade mode" msgstr "неочікуваний запит на новий relfilenumber в режимі двійкового оновлення" -#: utils/cache/relcache.c:6495 +#: utils/cache/relcache.c:6536 #, c-format msgid "could not create relation-cache initialization file \"%s\": %m" msgstr "не вдалося створити файл ініціалізації для кешу відношень \"%s\": %m" -#: utils/cache/relcache.c:6497 +#: utils/cache/relcache.c:6538 #, c-format msgid "Continuing anyway, but there's something wrong." msgstr "Продовжуємо усе одно, але щось не так." -#: utils/cache/relcache.c:6819 +#: utils/cache/relcache.c:6868 #, c-format msgid "could not remove cache file \"%s\": %m" msgstr "не вдалося видалити файл кешу \"%s\": %m" -#: utils/cache/relmapper.c:597 +#: utils/cache/relmapper.c:596 #, c-format msgid "cannot PREPARE a transaction that modified relation mapping" msgstr "виконати PREPARE для транзакції, яка змінила зіставлення відношень, не можна" -#: utils/cache/relmapper.c:853 +#: utils/cache/relmapper.c:852 #, c-format msgid "relation mapping file \"%s\" contains invalid data" msgstr "файл зіставлень відношень \"%s\" містить неприпустимі дані" -#: utils/cache/relmapper.c:863 +#: utils/cache/relmapper.c:862 #, c-format msgid "relation mapping file \"%s\" contains incorrect checksum" msgstr "файл зіставлень відношень \"%s\" містить неправильну контрольну суму" -#: utils/cache/typcache.c:1809 utils/fmgr/funcapi.c:566 +#: utils/cache/typcache.c:1812 utils/fmgr/funcapi.c:574 #, c-format msgid "record type has not been registered" msgstr "тип запису не зареєстрований" @@ -26159,102 +27228,102 @@ msgstr "TRAP: ExceptionalCondition: невірні аргументи в PID %d\ msgid "TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n" msgstr "TRAP: помилка Assert(\"%s\"), файл: \"%s\", рядок: %d, PID: %d\n" -#: utils/error/elog.c:416 +#: utils/error/elog.c:415 #, c-format msgid "error occurred before error message processing is available\n" msgstr "сталася помилка перед тим, як обробка повідомлення про помилку була доступна\n" -#: utils/error/elog.c:2096 +#: utils/error/elog.c:2134 #, c-format msgid "could not reopen file \"%s\" as stderr: %m" msgstr "не вдалося повторно відкрити файл \"%s\" як stderr: %m" -#: utils/error/elog.c:2109 +#: utils/error/elog.c:2147 #, c-format msgid "could not reopen file \"%s\" as stdout: %m" msgstr "не вдалося повторно відкрити файл \"%s\" як stdout: %m" -#: utils/error/elog.c:2145 +#: utils/error/elog.c:2183 #, c-format -msgid "invalid character" -msgstr "неприпустимий символ" +msgid "Invalid character" +msgstr "Неприпустимий символ" -#: utils/error/elog.c:2851 utils/error/elog.c:2878 utils/error/elog.c:2894 +#: utils/error/elog.c:2889 utils/error/elog.c:2916 utils/error/elog.c:2932 msgid "[unknown]" msgstr "[unknown]" -#: utils/error/elog.c:3167 utils/error/elog.c:3488 utils/error/elog.c:3595 +#: utils/error/elog.c:3202 utils/error/elog.c:3526 utils/error/elog.c:3633 msgid "missing error text" msgstr "пропущено текст помилки" -#: utils/error/elog.c:3170 utils/error/elog.c:3173 +#: utils/error/elog.c:3205 utils/error/elog.c:3208 #, c-format msgid " at character %d" msgstr " символ %d" -#: utils/error/elog.c:3183 utils/error/elog.c:3190 +#: utils/error/elog.c:3218 utils/error/elog.c:3225 msgid "DETAIL: " msgstr "ВІДОМОСТІ: " -#: utils/error/elog.c:3197 +#: utils/error/elog.c:3232 msgid "HINT: " msgstr "УКАЗІВКА: " -#: utils/error/elog.c:3204 +#: utils/error/elog.c:3239 msgid "QUERY: " msgstr "ЗАПИТ: " -#: utils/error/elog.c:3211 +#: utils/error/elog.c:3246 msgid "CONTEXT: " msgstr "КОНТЕКСТ: " -#: utils/error/elog.c:3221 +#: utils/error/elog.c:3256 #, c-format msgid "LOCATION: %s, %s:%d\n" msgstr "РОЗТАШУВАННЯ: %s, %s:%d\n" -#: utils/error/elog.c:3228 +#: utils/error/elog.c:3263 #, c-format msgid "LOCATION: %s:%d\n" msgstr "РОЗТАШУВАННЯ: %s:%d\n" -#: utils/error/elog.c:3235 +#: utils/error/elog.c:3270 msgid "BACKTRACE: " msgstr "ВІДСТЕЖУВАТИ: " -#: utils/error/elog.c:3247 +#: utils/error/elog.c:3282 msgid "STATEMENT: " msgstr "ІНСТРУКЦІЯ: " -#: utils/error/elog.c:3640 +#: utils/error/elog.c:3678 msgid "DEBUG" msgstr "НАЛАГОДЖЕННЯ" -#: utils/error/elog.c:3644 +#: utils/error/elog.c:3682 msgid "LOG" msgstr "ЗАПИСУВАННЯ" -#: utils/error/elog.c:3647 +#: utils/error/elog.c:3685 msgid "INFO" msgstr "ІНФОРМАЦІЯ" -#: utils/error/elog.c:3650 +#: utils/error/elog.c:3688 msgid "NOTICE" msgstr "ПОВІДОМЛЕННЯ" -#: utils/error/elog.c:3654 +#: utils/error/elog.c:3692 msgid "WARNING" msgstr "ПОПЕРЕДЖЕННЯ" -#: utils/error/elog.c:3657 +#: utils/error/elog.c:3695 msgid "ERROR" msgstr "ПОМИЛКА" -#: utils/error/elog.c:3660 +#: utils/error/elog.c:3698 msgid "FATAL" msgstr "ФАТАЛЬНО" -#: utils/error/elog.c:3663 +#: utils/error/elog.c:3701 msgid "PANIC" msgstr "ПАНІКА" @@ -26327,22 +27396,22 @@ msgstr "Магічний блок має неочікувану довжину msgid "incompatible library \"%s\": magic block mismatch" msgstr "несумісна бібліотка \"%s\": невідповідність магічного блоку" -#: utils/fmgr/dfmgr.c:492 +#: utils/fmgr/dfmgr.c:475 #, c-format msgid "access to library \"%s\" is not allowed" msgstr "доступ до бібліотеки \"%s\" не дозволений" -#: utils/fmgr/dfmgr.c:518 +#: utils/fmgr/dfmgr.c:501 #, c-format msgid "invalid macro name in dynamic library path: %s" msgstr "неприпустиме ім'я макросу в шляху динамічної бібліотеки: %s" -#: utils/fmgr/dfmgr.c:558 +#: utils/fmgr/dfmgr.c:541 #, c-format msgid "zero-length component in parameter \"dynamic_library_path\"" msgstr "параметр \"dynamic_library_path\" містить компонент нульової довжини" -#: utils/fmgr/dfmgr.c:577 +#: utils/fmgr/dfmgr.c:560 #, c-format msgid "component in parameter \"dynamic_library_path\" is not an absolute path" msgstr "параметр \"dynamic_library_path\" містить компонент, який не є абсолютним шляхом" @@ -26367,223 +27436,213 @@ msgstr "Функції, які викликаються з SQL, потребую msgid "unrecognized API version %d reported by info function \"%s\"" msgstr "нерозпізнана версія API %d, повідомлена інформаційною функцією \"%s\"" -#: utils/fmgr/fmgr.c:2080 +#: utils/fmgr/fmgr.c:2109 #, c-format msgid "operator class options info is absent in function call context" msgstr "в контексті виклику функції відсутня інформація стосовно параметрів класів операторів" -#: utils/fmgr/fmgr.c:2147 +#: utils/fmgr/fmgr.c:2176 #, c-format msgid "language validation function %u called for language %u instead of %u" msgstr "функція мовної перевірки %u викликана для мови %u замість %u" -#: utils/fmgr/funcapi.c:489 +#: utils/fmgr/funcapi.c:496 #, c-format msgid "could not determine actual result type for function \"%s\" declared to return type %s" msgstr "не вдалося визначити фактичний тип результату для функції \"%s\" оголошеної як, та, котра повертає тип %s" -#: utils/fmgr/funcapi.c:634 +#: utils/fmgr/funcapi.c:642 #, c-format msgid "argument declared %s does not contain a range type but type %s" msgstr "оголошений аргумент %s не містить тип діапазону, а тип %s" -#: utils/fmgr/funcapi.c:717 -#, c-format -msgid "could not find multirange type for data type %s" -msgstr "не вдалося знайти багатодіапазонний тип для типу даних %s" - -#: utils/fmgr/funcapi.c:1921 utils/fmgr/funcapi.c:1953 +#: utils/fmgr/funcapi.c:1929 utils/fmgr/funcapi.c:1961 #, c-format msgid "number of aliases does not match number of columns" msgstr "кількість псевдонімів не відповідає кількості стовпців" -#: utils/fmgr/funcapi.c:1947 +#: utils/fmgr/funcapi.c:1955 #, c-format msgid "no column alias was provided" msgstr "жодного псевдоніму для стовпця не було надано" -#: utils/fmgr/funcapi.c:1971 +#: utils/fmgr/funcapi.c:1979 #, c-format msgid "could not determine row description for function returning record" msgstr "не вдалося визначити опис рядка для функції, що повертає запис" -#: utils/init/miscinit.c:346 +#: utils/init/miscinit.c:352 #, c-format msgid "data directory \"%s\" does not exist" msgstr "каталог даних \"%s\" не існує" -#: utils/init/miscinit.c:351 +#: utils/init/miscinit.c:357 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "не вдалося прочитати дозволи на каталог \"%s\": %m" -#: utils/init/miscinit.c:359 +#: utils/init/miscinit.c:365 #, c-format msgid "specified data directory \"%s\" is not a directory" msgstr "вказаний каталог даних \"%s\" не є каталогом" -#: utils/init/miscinit.c:375 +#: utils/init/miscinit.c:381 #, c-format msgid "data directory \"%s\" has wrong ownership" msgstr "власник каталогу даних \"%s\" визначений неправильно" -#: utils/init/miscinit.c:377 +#: utils/init/miscinit.c:383 #, c-format msgid "The server must be started by the user that owns the data directory." msgstr "Сервер повинен запускати користувач, який володіє каталогом даних." -#: utils/init/miscinit.c:395 +#: utils/init/miscinit.c:401 #, c-format msgid "data directory \"%s\" has invalid permissions" msgstr "каталог даних \"%s\" має неприпустимі дозволи" -#: utils/init/miscinit.c:397 +#: utils/init/miscinit.c:403 #, c-format msgid "Permissions should be u=rwx (0700) or u=rwx,g=rx (0750)." msgstr "Дозволи повинні бути u=rwx (0700) або u=rwx,g=rx (0750)." -#: utils/init/miscinit.c:455 +#: utils/init/miscinit.c:461 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "не вдалося змінити каталог на \"%s\": %m" -#: utils/init/miscinit.c:692 utils/misc/guc.c:3557 +#: utils/init/miscinit.c:697 utils/misc/guc.c:3650 #, c-format msgid "cannot set parameter \"%s\" within security-restricted operation" msgstr "встановити параметр \"%s\" в межах операції з обмеженнями по безпеці, не можна" -#: utils/init/miscinit.c:764 +#: utils/init/miscinit.c:770 #, c-format msgid "role with OID %u does not exist" msgstr "роль з OID %u не існує" -#: utils/init/miscinit.c:794 +#: utils/init/miscinit.c:800 #, c-format msgid "role \"%s\" is not permitted to log in" msgstr "для ролі \"%s\" вхід не дозволений" -#: utils/init/miscinit.c:812 +#: utils/init/miscinit.c:818 #, c-format msgid "too many connections for role \"%s\"" msgstr "занадто багато підключень для ролі \"%s\"" -#: utils/init/miscinit.c:919 -#, c-format -msgid "permission denied to set session authorization" -msgstr "немає прав для встановлення авторизації в сеансі" - -#: utils/init/miscinit.c:1002 +#: utils/init/miscinit.c:991 #, c-format msgid "invalid role OID: %u" msgstr "неприпустимий OID ролі: %u" -#: utils/init/miscinit.c:1149 +#: utils/init/miscinit.c:1138 #, c-format msgid "database system is shut down" msgstr "система бази даних вимкнена" -#: utils/init/miscinit.c:1236 +#: utils/init/miscinit.c:1225 #, c-format msgid "could not create lock file \"%s\": %m" msgstr "не вдалося створити файл блокування \"%s\": %m" -#: utils/init/miscinit.c:1250 +#: utils/init/miscinit.c:1239 #, c-format msgid "could not open lock file \"%s\": %m" msgstr "не вдалося відкрити файл блокування \"%s\": %m" -#: utils/init/miscinit.c:1257 +#: utils/init/miscinit.c:1246 #, c-format msgid "could not read lock file \"%s\": %m" msgstr "не вдалося прочитати файл блокування \"%s\": %m" -#: utils/init/miscinit.c:1266 +#: utils/init/miscinit.c:1255 #, c-format msgid "lock file \"%s\" is empty" msgstr "файл блокування \"%s\" пустий" -#: utils/init/miscinit.c:1267 +#: utils/init/miscinit.c:1256 #, c-format msgid "Either another server is starting, or the lock file is the remnant of a previous server startup crash." msgstr "Або зараз запускається інший сервер, або цей файл блокування залишився в результаті збою під час попереднього запуску." -#: utils/init/miscinit.c:1311 +#: utils/init/miscinit.c:1300 #, c-format msgid "lock file \"%s\" already exists" msgstr "файл блокування \"%s\" вже існує" -#: utils/init/miscinit.c:1315 +#: utils/init/miscinit.c:1304 #, c-format msgid "Is another postgres (PID %d) running in data directory \"%s\"?" msgstr "Інший postgres (PID %d) працює з каталогом даних \"%s\"?" -#: utils/init/miscinit.c:1317 +#: utils/init/miscinit.c:1306 #, c-format msgid "Is another postmaster (PID %d) running in data directory \"%s\"?" msgstr "Інший postmaster (PID %d) працює з каталогом даних \"%s\"?" -#: utils/init/miscinit.c:1320 +#: utils/init/miscinit.c:1309 #, c-format msgid "Is another postgres (PID %d) using socket file \"%s\"?" msgstr "Інший postgres (PID %d) використовує файл сокету \"%s\"?" -#: utils/init/miscinit.c:1322 +#: utils/init/miscinit.c:1311 #, c-format msgid "Is another postmaster (PID %d) using socket file \"%s\"?" msgstr "Інший postmaster (PID %d) використовує файл сокету \"%s\"?" -#: utils/init/miscinit.c:1373 +#: utils/init/miscinit.c:1362 #, c-format msgid "could not remove old lock file \"%s\": %m" msgstr "не вдалося видалити старий файл блокування \"%s\": %m" -#: utils/init/miscinit.c:1375 +#: utils/init/miscinit.c:1364 #, c-format msgid "The file seems accidentally left over, but it could not be removed. Please remove the file by hand and try again." msgstr "Здається, файл залишився випадково, але видалити його не вийшло. Будь-ласка, видаліть файл вручну або спробуйте знову." -#: utils/init/miscinit.c:1412 utils/init/miscinit.c:1426 -#: utils/init/miscinit.c:1437 +#: utils/init/miscinit.c:1401 utils/init/miscinit.c:1415 +#: utils/init/miscinit.c:1426 #, c-format msgid "could not write lock file \"%s\": %m" msgstr "не вдалося записати файл блокування \"%s\": %m" -#: utils/init/miscinit.c:1548 utils/init/miscinit.c:1690 utils/misc/guc.c:5597 +#: utils/init/miscinit.c:1537 utils/init/miscinit.c:1679 utils/misc/guc.c:5724 #, c-format msgid "could not read from file \"%s\": %m" msgstr "не вдалося прочитати з файлу \"%s\": %m" -#: utils/init/miscinit.c:1678 +#: utils/init/miscinit.c:1667 #, c-format msgid "could not open file \"%s\": %m; continuing anyway" msgstr "не вдалося відкрити файл \"%s\": %m; все одно продовжується" -#: utils/init/miscinit.c:1703 +#: utils/init/miscinit.c:1692 #, c-format msgid "lock file \"%s\" contains wrong PID: %ld instead of %ld" msgstr "файл блокування \"%s\" містить неправильний PID: %ld замість %ld" -#: utils/init/miscinit.c:1742 utils/init/miscinit.c:1758 +#: utils/init/miscinit.c:1731 utils/init/miscinit.c:1747 #, c-format msgid "\"%s\" is not a valid data directory" msgstr "\"%s\" не є припустимим каталогом даних" -#: utils/init/miscinit.c:1744 +#: utils/init/miscinit.c:1733 #, c-format msgid "File \"%s\" is missing." msgstr "Файл \"%s\" пропущено." -#: utils/init/miscinit.c:1760 +#: utils/init/miscinit.c:1749 #, c-format msgid "File \"%s\" does not contain valid data." msgstr "Файл \"%s\" не містить припустимих даних." -#: utils/init/miscinit.c:1762 +#: utils/init/miscinit.c:1751 #, c-format msgid "You might need to initdb." msgstr "Можливо, вам слід виконати initdb." -#: utils/init/miscinit.c:1770 +#: utils/init/miscinit.c:1759 #, c-format msgid "The data directory was initialized by PostgreSQL version %s, which is not compatible with this version %s." msgstr "Каталог даних ініціалізований сервером PostgreSQL версії %s, не сумісною з цією версією %s." @@ -26685,72 +27744,72 @@ msgstr "Повторно створіть базу даних з іншою ло msgid "The database was initialized with LC_CTYPE \"%s\", which is not recognized by setlocale()." msgstr "База даних була ініціалізована з параметром LC_CTYPE \"%s\", але зараз setlocale() не розпізнає його." -#: utils/init/postinit.c:475 +#: utils/init/postinit.c:491 #, c-format msgid "database \"%s\" has a collation version mismatch" msgstr "база даних \"%s\" має невідповідність версії параметрів сортування" -#: utils/init/postinit.c:477 +#: utils/init/postinit.c:493 #, c-format msgid "The database was created using collation version %s, but the operating system provides version %s." msgstr "Базу даних було створено за допомогою параметрів сортування версії %s, але операційна система надає версію %s." -#: utils/init/postinit.c:480 +#: utils/init/postinit.c:496 #, c-format msgid "Rebuild all objects in this database that use the default collation and run ALTER DATABASE %s REFRESH COLLATION VERSION, or build PostgreSQL with the right library version." msgstr "Перебудуйте всі об'єкти бази даних, які використовують стандартний параметр сортування або виконайте ALTER DATABASE %s REFRESH COLLATION VERSION, або побудуйте PostgreSQL з правильною версією бібліотеки." -#: utils/init/postinit.c:891 +#: utils/init/postinit.c:902 #, c-format msgid "no roles are defined in this database system" msgstr "в цій системі баз даних не визначено жодної ролі" -#: utils/init/postinit.c:892 +#: utils/init/postinit.c:903 #, c-format msgid "You should immediately run CREATE USER \"%s\" SUPERUSER;." msgstr "Ви повинні негайно виконати CREATE USER \"%s\" SUPERUSER;." -#: utils/init/postinit.c:928 +#: utils/init/postinit.c:940 #, c-format msgid "must be superuser to connect in binary upgrade mode" msgstr "потрібно бути суперкористувачем, щоб підключитись в режимі двійкового оновлення" -#: utils/init/postinit.c:949 +#: utils/init/postinit.c:961 #, c-format msgid "remaining connection slots are reserved for roles with the %s attribute" msgstr "слоти підключення, що залишилися, зарезервовані для ролей з атрибутом %s" -#: utils/init/postinit.c:955 +#: utils/init/postinit.c:967 #, c-format msgid "remaining connection slots are reserved for roles with privileges of the \"%s\" role" msgstr "слоти підключення, що залишилися, зарезервовані для ролей з привілеями ролі \"%s\"" -#: utils/init/postinit.c:967 +#: utils/init/postinit.c:979 #, c-format msgid "permission denied to start WAL sender" msgstr "немає дозволу для запуску відправника WAL" -#: utils/init/postinit.c:968 +#: utils/init/postinit.c:980 #, c-format msgid "Only roles with the %s attribute may start a WAL sender process." msgstr "Тільки ролі з атрибутом %s можуть почати процес відправки WAL." -#: utils/init/postinit.c:1086 +#: utils/init/postinit.c:1098 #, c-format msgid "It seems to have just been dropped or renamed." msgstr "Схоже, вона щойно була видалена або перейменована." -#: utils/init/postinit.c:1090 +#: utils/init/postinit.c:1102 #, c-format msgid "database %u does not exist" msgstr "база даних %u не існує" -#: utils/init/postinit.c:1099 +#: utils/init/postinit.c:1111 #, c-format msgid "cannot connect to invalid database \"%s\"" msgstr "неможливо під'єднатися до невірної бази даних \"%s\"" -#: utils/init/postinit.c:1159 +#: utils/init/postinit.c:1172 #, c-format msgid "The database subdirectory \"%s\" is missing." msgstr "Підкаталог бази даних \"%s\" пропущений." @@ -26777,48 +27836,48 @@ msgstr "неочікуваний ідентифікатор кодування % msgid "unexpected encoding ID %d for WIN character sets" msgstr "неочікуваний ідентифікатор кодування %d для наборів символів WIN" -#: utils/mb/mbutils.c:298 utils/mb/mbutils.c:901 +#: utils/mb/mbutils.c:297 utils/mb/mbutils.c:900 #, c-format msgid "conversion between %s and %s is not supported" msgstr "перетворення між %s і %s не підтримується" -#: utils/mb/mbutils.c:403 utils/mb/mbutils.c:431 utils/mb/mbutils.c:816 -#: utils/mb/mbutils.c:843 +#: utils/mb/mbutils.c:402 utils/mb/mbutils.c:430 utils/mb/mbutils.c:815 +#: utils/mb/mbutils.c:842 #, c-format msgid "String of %d bytes is too long for encoding conversion." msgstr "Рядок з %d байт занадто довгий для перетворення кодування." -#: utils/mb/mbutils.c:569 +#: utils/mb/mbutils.c:568 #, c-format msgid "invalid source encoding name \"%s\"" msgstr "неприпустиме ім’я вихідного кодування \"%s\"" -#: utils/mb/mbutils.c:574 +#: utils/mb/mbutils.c:573 #, c-format msgid "invalid destination encoding name \"%s\"" msgstr "неприпустиме ім’я кодування результату \"%s\"" -#: utils/mb/mbutils.c:714 +#: utils/mb/mbutils.c:713 #, c-format msgid "invalid byte value for encoding \"%s\": 0x%02x" msgstr "неприпустиме значення байту для кодування \"%s\": 0x%02x" -#: utils/mb/mbutils.c:878 +#: utils/mb/mbutils.c:877 #, c-format msgid "invalid Unicode code point" msgstr "неприпустима кодова точка Unicode" -#: utils/mb/mbutils.c:1204 +#: utils/mb/mbutils.c:1201 #, c-format msgid "bind_textdomain_codeset failed" msgstr "помилка в bind_textdomain_codeset" -#: utils/mb/mbutils.c:1725 +#: utils/mb/mbutils.c:1718 #, c-format msgid "invalid byte sequence for encoding \"%s\": %s" msgstr "неприпустима послідовність байтів для кодування \"%s\": %s" -#: utils/mb/mbutils.c:1758 +#: utils/mb/mbutils.c:1751 #, c-format msgid "character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"" msgstr "символ з послідовністю байтів %s в кодуванні \"%s\" не має еквіваленту в кодуванні \"%s\"" @@ -26833,237 +27892,239 @@ msgstr "пуста назва каталогу конфігурації: \"%s\"" msgid "could not open configuration directory \"%s\": %m" msgstr "не вдалося відкрити каталог конфігурації \"%s\": %m" -#: utils/misc/guc.c:115 +#: utils/misc/guc.c:122 msgid "Valid units for this parameter are \"B\", \"kB\", \"MB\", \"GB\", and \"TB\"." msgstr "Припустимі одиниці для цього параметру: \"B\", \"kB\", \"MB\", \"GB\", і \"TB\"." -#: utils/misc/guc.c:152 +#: utils/misc/guc.c:159 msgid "Valid units for this parameter are \"us\", \"ms\", \"s\", \"min\", \"h\", and \"d\"." msgstr "Припустимі одиниці для цього параметру: \"us\", \"ms\", \"s\", \"min\", \"h\", і \"d\"." -#: utils/misc/guc.c:421 +#: utils/misc/guc.c:430 #, c-format msgid "unrecognized configuration parameter \"%s\" in file \"%s\" line %d" msgstr "нерозпізнаний параметр конфігурації \"%s\" у файлі \"%s\" рядок %d" -#: utils/misc/guc.c:461 utils/misc/guc.c:3411 utils/misc/guc.c:3655 -#: utils/misc/guc.c:3753 utils/misc/guc.c:3851 utils/misc/guc.c:3975 -#: utils/misc/guc.c:4078 +#: utils/misc/guc.c:470 utils/misc/guc.c:3504 utils/misc/guc.c:3748 +#: utils/misc/guc.c:3846 utils/misc/guc.c:3944 utils/misc/guc.c:4068 +#: utils/misc/guc.c:4171 #, c-format msgid "parameter \"%s\" cannot be changed without restarting the server" msgstr "параметр \"%s\" не може бути змінений, без перезавантаження сервера" -#: utils/misc/guc.c:497 +#: utils/misc/guc.c:506 #, c-format msgid "parameter \"%s\" removed from configuration file, reset to default" msgstr "параметр \"%s\" видалений з файла конфігурації, значення скинуто до \"за замовчуванням\"" -#: utils/misc/guc.c:562 +#: utils/misc/guc.c:571 #, c-format msgid "parameter \"%s\" changed to \"%s\"" msgstr "параметр \"%s\" змінено на \"%s\"" -#: utils/misc/guc.c:604 +#: utils/misc/guc.c:613 #, c-format msgid "configuration file \"%s\" contains errors" msgstr "файл конфігурації \"%s\" містить помилки" -#: utils/misc/guc.c:609 +#: utils/misc/guc.c:618 #, c-format msgid "configuration file \"%s\" contains errors; unaffected changes were applied" msgstr "файл конфігурації \"%s\" містить помилки; були застосовані не залежні зміни" -#: utils/misc/guc.c:614 +#: utils/misc/guc.c:623 #, c-format msgid "configuration file \"%s\" contains errors; no changes were applied" msgstr "файл конфігурації \"%s\" містить помилки; зміни не були застосовані" -#: utils/misc/guc.c:1211 utils/misc/guc.c:1227 +#: utils/misc/guc.c:1139 utils/misc/guc.c:1155 #, c-format msgid "invalid configuration parameter name \"%s\"" msgstr "неприпустима назва параметра конфігурації \"%s\"" -#: utils/misc/guc.c:1213 +#: utils/misc/guc.c:1141 #, c-format msgid "Custom parameter names must be two or more simple identifiers separated by dots." msgstr "Власні назви параметрів повинні містити два або більше простих ідентифікаторів, розділених крапками." -#: utils/misc/guc.c:1229 +#: utils/misc/guc.c:1157 #, c-format msgid "\"%s\" is a reserved prefix." msgstr "\"%s\" є зарезервованим префіксом." -#: utils/misc/guc.c:1243 +#: utils/misc/guc.c:1170 utils/misc/guc.c:1280 #, c-format msgid "unrecognized configuration parameter \"%s\"" msgstr "нерозпізнаний параметр конфігурації \"%s\"" -#: utils/misc/guc.c:1767 +#: utils/misc/guc.c:1802 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: немає доступу до каталогу \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: не вдалося отримати доступ до каталогу \"%s\": %m\n" -#: utils/misc/guc.c:1772 +#: utils/misc/guc.c:1806 #, c-format msgid "Run initdb or pg_basebackup to initialize a PostgreSQL data directory.\n" msgstr "Запустіть initdb або pg_basebackup для ініціалізації каталогу даних PostgreSQL.\n" -#: utils/misc/guc.c:1796 +#: utils/misc/guc.c:1830 #, c-format -msgid "" -"%s does not know where to find the server configuration file.\n" +msgid "%s does not know where to find the server configuration file.\n" "You must specify the --config-file or -D invocation option or set the PGDATA environment variable.\n" -msgstr "" -"%s не знає де знайти файл конфігурації сервера.\n" +msgstr "%s не знає де знайти файл конфігурації сервера.\n" "Ви повинні вказати його розташування в параметрі --config-file або -D, або встановити змінну середовища PGDATA.\n" -#: utils/misc/guc.c:1819 +#: utils/misc/guc.c:1853 #, c-format -msgid "%s: could not access the server configuration file \"%s\": %s\n" -msgstr "%s: не вдалося отримати доступ до файлу конфігурації сервера \"%s\": %s\n" +msgid "%s: could not access the server configuration file \"%s\": %m\n" +msgstr "%s: не вдалося отримати доступ до файлу конфігурації сервера \"%s\": %m\n" -#: utils/misc/guc.c:1847 +#: utils/misc/guc.c:1881 #, c-format -msgid "" -"%s does not know where to find the database system data.\n" +msgid "%s does not know where to find the database system data.\n" "This can be specified as \"data_directory\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n" -msgstr "" -"%s не знає де знайти дані системи бази даних.\n" +msgstr "%s не знає де знайти дані системи бази даних.\n" "Їх розташування може бути вказано як \"data_directory\" в \"%s\", або передано в параметрі -D, або встановлено змінну середовища PGDATA.\n" -#: utils/misc/guc.c:1899 +#: utils/misc/guc.c:1933 #, c-format -msgid "" -"%s does not know where to find the \"hba\" configuration file.\n" +msgid "%s does not know where to find the \"hba\" configuration file.\n" "This can be specified as \"hba_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n" -msgstr "" -"%s не знає де знайти файл конфігурації \"hba\".\n" +msgstr "%s не знає де знайти файл конфігурації \"hba\".\n" "Його розташування може бути вказано як \"hba_file\" в \"%s\", або передано в параметрі -D, або встановлено змінну середовища PGDATA.\n" -#: utils/misc/guc.c:1930 +#: utils/misc/guc.c:1964 #, c-format -msgid "" -"%s does not know where to find the \"ident\" configuration file.\n" +msgid "%s does not know where to find the \"ident\" configuration file.\n" "This can be specified as \"ident_file\" in \"%s\", or by the -D invocation option, or by the PGDATA environment variable.\n" -msgstr "" -"%s не знає де знайти файл конфігурації \"ident\".\n" +msgstr "%s не знає де знайти файл конфігурації \"ident\".\n" "Його розташування може бути вказано як \"ident_file\" в \"%s\", або передано в параметрі -D, або встановлено змінну середовища PGDATA.\n" -#: utils/misc/guc.c:2896 +#: utils/misc/guc.c:2943 msgid "Value exceeds integer range." msgstr "Значення перевищує діапазон цілих чисел." -#: utils/misc/guc.c:3132 +#: utils/misc/guc.c:3185 #, c-format -msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)" -msgstr "%d%s%s поза припустимим діапазоном для параметру \"%s\" (%d .. %d)" +msgid "%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)" +msgstr "%d%s%s поза припустимим діапазоном для параметру \"%s\" (%d%s%s .. %d%s%s)" -#: utils/misc/guc.c:3168 +#: utils/misc/guc.c:3226 #, c-format -msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)" -msgstr "%g%s%s поза припустимим діапазоном для параметру \"%s\" (%g .. %g)" +msgid "%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)" +msgstr "%g%s%s поза припустимим діапазоном для параметру \"%s\" (%g%s%s .. %g%s%s)" -#: utils/misc/guc.c:3369 utils/misc/guc_funcs.c:54 +#: utils/misc/guc.c:3465 #, c-format -msgid "cannot set parameters during a parallel operation" -msgstr "встановити параметри під час паралельної операції не можна" +msgid "parameter \"%s\" cannot be set during a parallel operation" +msgstr "параметр \"%s\" не можна встановити під час паралельних операцій" -#: utils/misc/guc.c:3388 utils/misc/guc.c:4539 +#: utils/misc/guc.c:3481 utils/misc/guc.c:4655 #, c-format msgid "parameter \"%s\" cannot be changed" msgstr "параметр \"%s\" не може бути змінений" -#: utils/misc/guc.c:3421 +#: utils/misc/guc.c:3514 #, c-format msgid "parameter \"%s\" cannot be changed now" msgstr "параметр \"%s\" не може бути змінений зараз" -#: utils/misc/guc.c:3448 utils/misc/guc.c:3510 utils/misc/guc.c:4515 -#: utils/misc/guc.c:6563 +#: utils/misc/guc.c:3541 utils/misc/guc.c:3603 utils/misc/guc.c:4630 +#: utils/misc/guc.c:6721 #, c-format msgid "permission denied to set parameter \"%s\"" msgstr "немає прав для встановлення параметру \"%s\"" -#: utils/misc/guc.c:3490 +#: utils/misc/guc.c:3583 #, c-format msgid "parameter \"%s\" cannot be set after connection start" msgstr "параметр \"%s\" не можна встановити після встановлення підключення" -#: utils/misc/guc.c:3549 +#: utils/misc/guc.c:3642 #, c-format msgid "cannot set parameter \"%s\" within security-definer function" msgstr "параметр \"%s\" не можна встановити в межах функції безпеки" -#: utils/misc/guc.c:3570 +#: utils/misc/guc.c:3663 #, c-format msgid "parameter \"%s\" cannot be reset" msgstr "параметр \"%s\" не можна скинути" -#: utils/misc/guc.c:3577 +#: utils/misc/guc.c:3670 #, c-format msgid "parameter \"%s\" cannot be set locally in functions" msgstr "параметр \"%s\" не може бути встановлений локально в функціях" -#: utils/misc/guc.c:4221 utils/misc/guc.c:4268 utils/misc/guc.c:5282 +#: utils/misc/guc.c:4329 utils/misc/guc.c:4377 utils/misc/guc.c:5409 #, c-format msgid "permission denied to examine \"%s\"" msgstr "немає дозволу для вивчення \"%s\"" -#: utils/misc/guc.c:4222 utils/misc/guc.c:4269 utils/misc/guc.c:5283 +#: utils/misc/guc.c:4330 utils/misc/guc.c:4378 utils/misc/guc.c:5410 #, c-format msgid "Only roles with privileges of the \"%s\" role may examine this parameter." msgstr "Тільки ролі з привілеями ролі \"%s\" можуть перевіряти цей параметр." -#: utils/misc/guc.c:4505 +#: utils/misc/guc.c:4588 +#, c-format +msgid "ALTER SYSTEM is not allowed in this environment" +msgstr "ALTER SYSTEM не допускається в цьому середовищі" + +#: utils/misc/guc.c:4620 #, c-format msgid "permission denied to perform ALTER SYSTEM RESET ALL" msgstr "немає дозволу для виконання ALTER SYSTEM RESET ALL" -#: utils/misc/guc.c:4571 +#: utils/misc/guc.c:4699 #, c-format msgid "parameter value for ALTER SYSTEM must not contain a newline" msgstr "значення параметру для ALTER SYSTEM не повинне містити нового рядка" -#: utils/misc/guc.c:4617 +#: utils/misc/guc.c:4744 #, c-format msgid "could not parse contents of file \"%s\"" msgstr "не вдалося аналізувати зміст файла \"%s\"" -#: utils/misc/guc.c:4799 +#: utils/misc/guc.c:4926 #, c-format msgid "attempt to redefine parameter \"%s\"" msgstr "спроба перевизначити параметр \"%s\"" -#: utils/misc/guc.c:5138 +#: utils/misc/guc.c:5265 #, c-format msgid "invalid configuration parameter name \"%s\", removing it" msgstr "неприпустима назва параметра конфігурації \"%s\", видаляємо" -#: utils/misc/guc.c:5140 +#: utils/misc/guc.c:5267 #, c-format msgid "\"%s\" is now a reserved prefix." msgstr "\"%s\" тепер є зарезервованим префіксом." -#: utils/misc/guc.c:6017 +#: utils/misc/guc.c:6144 #, c-format msgid "while setting parameter \"%s\" to \"%s\"" msgstr "під час налаштування параметру \"%s\" на \"%s\"" -#: utils/misc/guc.c:6186 +#: utils/misc/guc.c:6313 #, c-format msgid "parameter \"%s\" could not be set" msgstr "параметр \"%s\" не вдалося встановити" -#: utils/misc/guc.c:6276 +#: utils/misc/guc.c:6403 #, c-format msgid "could not parse setting for parameter \"%s\"" msgstr "не вдалося аналізувати налаштування параметру \"%s\"" -#: utils/misc/guc.c:6695 +#: utils/misc/guc.c:6853 #, c-format msgid "invalid value for parameter \"%s\": %g" msgstr "неприпустиме значення для параметра \"%s\": %g" +#: utils/misc/guc_funcs.c:54 +#, c-format +msgid "cannot set parameters during a parallel operation" +msgstr "встановити параметри під час паралельної операції не можна" + #: utils/misc/guc_funcs.c:130 #, c-format msgid "SET LOCAL TRANSACTION SNAPSHOT is not implemented" @@ -27079,59 +28140,59 @@ msgstr "SET %s приймає лише один аргумент" msgid "SET requires parameter name" msgstr "SET потребує ім'я параметра" -#: utils/misc/guc_tables.c:662 +#: utils/misc/guc_tables.c:676 msgid "Ungrouped" msgstr "Розгруповано" -#: utils/misc/guc_tables.c:664 +#: utils/misc/guc_tables.c:677 msgid "File Locations" msgstr "Розташування файлів" -#: utils/misc/guc_tables.c:666 +#: utils/misc/guc_tables.c:678 msgid "Connections and Authentication / Connection Settings" msgstr "Підключення і автентифікація / Параметри підключень" -#: utils/misc/guc_tables.c:668 +#: utils/misc/guc_tables.c:679 msgid "Connections and Authentication / TCP Settings" msgstr "Підключення і автентифікація / Налаштування TCP" -#: utils/misc/guc_tables.c:670 +#: utils/misc/guc_tables.c:680 msgid "Connections and Authentication / Authentication" msgstr "Підключення і автентифікація / Автентифікація" -#: utils/misc/guc_tables.c:672 +#: utils/misc/guc_tables.c:681 msgid "Connections and Authentication / SSL" msgstr "Підключення і автентифікація / SSL" -#: utils/misc/guc_tables.c:674 +#: utils/misc/guc_tables.c:682 msgid "Resource Usage / Memory" msgstr "Використання ресурсу / Пам'ять" -#: utils/misc/guc_tables.c:676 +#: utils/misc/guc_tables.c:683 msgid "Resource Usage / Disk" msgstr "Використання ресурсу / Диск" -#: utils/misc/guc_tables.c:678 +#: utils/misc/guc_tables.c:684 msgid "Resource Usage / Kernel Resources" msgstr "Використання ресурсу / Ресурси ядра" -#: utils/misc/guc_tables.c:680 +#: utils/misc/guc_tables.c:685 msgid "Resource Usage / Cost-Based Vacuum Delay" msgstr "Використання ресурсу / Затримка очистки по вартості" -#: utils/misc/guc_tables.c:682 +#: utils/misc/guc_tables.c:686 msgid "Resource Usage / Background Writer" msgstr "Використання ресурсу / Фоновий запис" -#: utils/misc/guc_tables.c:684 +#: utils/misc/guc_tables.c:687 msgid "Resource Usage / Asynchronous Behavior" msgstr "Використання ресурсу / Асинхронна поведінка" -#: utils/misc/guc_tables.c:686 +#: utils/misc/guc_tables.c:688 msgid "Write-Ahead Log / Settings" msgstr "Журнал WAL / Параметри" -#: utils/misc/guc_tables.c:688 +#: utils/misc/guc_tables.c:689 msgid "Write-Ahead Log / Checkpoints" msgstr "Журнал WAL / Контрольні точки" @@ -27139,458 +28200,474 @@ msgstr "Журнал WAL / Контрольні точки" msgid "Write-Ahead Log / Archiving" msgstr "Журнал WAL / Архівація" -#: utils/misc/guc_tables.c:692 +#: utils/misc/guc_tables.c:691 msgid "Write-Ahead Log / Recovery" msgstr "Журнал WAL / Відновлення" -#: utils/misc/guc_tables.c:694 +#: utils/misc/guc_tables.c:692 msgid "Write-Ahead Log / Archive Recovery" msgstr "Журнал WAL / Відновлення архіву" -#: utils/misc/guc_tables.c:696 +#: utils/misc/guc_tables.c:693 msgid "Write-Ahead Log / Recovery Target" msgstr "Журнал WAL / Мета відновлення" -#: utils/misc/guc_tables.c:698 +#: utils/misc/guc_tables.c:694 +msgid "Write-Ahead Log / Summarization" +msgstr "Журнал попереднього запису / Підсумки" + +#: utils/misc/guc_tables.c:695 msgid "Replication / Sending Servers" msgstr "Реплікація / Надсилання серверів" -#: utils/misc/guc_tables.c:700 +#: utils/misc/guc_tables.c:696 msgid "Replication / Primary Server" msgstr "Реплікація / Основний сервер" -#: utils/misc/guc_tables.c:702 +#: utils/misc/guc_tables.c:697 msgid "Replication / Standby Servers" msgstr "Реплікація / Резервні сервера" -#: utils/misc/guc_tables.c:704 +#: utils/misc/guc_tables.c:698 msgid "Replication / Subscribers" msgstr "Реплікація / Підписники" -#: utils/misc/guc_tables.c:706 +#: utils/misc/guc_tables.c:699 msgid "Query Tuning / Planner Method Configuration" msgstr "Налаштування запитів / Конфігурація методів планувальника" -#: utils/misc/guc_tables.c:708 +#: utils/misc/guc_tables.c:700 msgid "Query Tuning / Planner Cost Constants" msgstr "Налаштування запитів / Константи вартості для планувальника" -#: utils/misc/guc_tables.c:710 +#: utils/misc/guc_tables.c:701 msgid "Query Tuning / Genetic Query Optimizer" msgstr "Налаштування запитів / Генетичний оптимізатор запитів" -#: utils/misc/guc_tables.c:712 +#: utils/misc/guc_tables.c:702 msgid "Query Tuning / Other Planner Options" msgstr "Налаштування запитів / Інші параметри планувальника" -#: utils/misc/guc_tables.c:714 +#: utils/misc/guc_tables.c:703 msgid "Reporting and Logging / Where to Log" msgstr "Звіти і журналювання / Куди записувати" -#: utils/misc/guc_tables.c:716 +#: utils/misc/guc_tables.c:704 msgid "Reporting and Logging / When to Log" msgstr "Звіти і журналювання / Коли записувати" -#: utils/misc/guc_tables.c:718 +#: utils/misc/guc_tables.c:705 msgid "Reporting and Logging / What to Log" msgstr "Звіти і журналювання / Що записувати" -#: utils/misc/guc_tables.c:720 +#: utils/misc/guc_tables.c:706 msgid "Reporting and Logging / Process Title" msgstr "Звітування і журналювання / Назва процесу" -#: utils/misc/guc_tables.c:722 +#: utils/misc/guc_tables.c:707 msgid "Statistics / Monitoring" msgstr "Статистика / Моніторинг" -#: utils/misc/guc_tables.c:724 +#: utils/misc/guc_tables.c:708 msgid "Statistics / Cumulative Query and Index Statistics" msgstr "Статистика / Кумулятивна статистика запитів та індексів" -#: utils/misc/guc_tables.c:726 +#: utils/misc/guc_tables.c:709 msgid "Autovacuum" msgstr "Автоочистка" -#: utils/misc/guc_tables.c:728 +#: utils/misc/guc_tables.c:710 msgid "Client Connection Defaults / Statement Behavior" msgstr "Параметри клієнтських сеансів за замовчуванням / Поведінка декларацій" -#: utils/misc/guc_tables.c:730 +#: utils/misc/guc_tables.c:711 msgid "Client Connection Defaults / Locale and Formatting" msgstr "Параметри клієнтських сеансів за замовчуванням / Локалізація і форматування" -#: utils/misc/guc_tables.c:732 +#: utils/misc/guc_tables.c:712 msgid "Client Connection Defaults / Shared Library Preloading" msgstr "Параметри клієнтських сеансів за замовчуванням / Попереднє завантаження спільних бібліотек" -#: utils/misc/guc_tables.c:734 +#: utils/misc/guc_tables.c:713 msgid "Client Connection Defaults / Other Defaults" msgstr "Параметри клієнтських сеансів за замовчуванням / Інші параметри за замовчуванням" -#: utils/misc/guc_tables.c:736 +#: utils/misc/guc_tables.c:714 msgid "Lock Management" msgstr "Керування блокуванням" -#: utils/misc/guc_tables.c:738 +#: utils/misc/guc_tables.c:715 msgid "Version and Platform Compatibility / Previous PostgreSQL Versions" msgstr "Сумісність версій і платформ / Попередні версії PostgreSQL" -#: utils/misc/guc_tables.c:740 +#: utils/misc/guc_tables.c:716 msgid "Version and Platform Compatibility / Other Platforms and Clients" msgstr "Сумісність версій і платформ / Інші платформи і клієнти" -#: utils/misc/guc_tables.c:742 +#: utils/misc/guc_tables.c:717 msgid "Error Handling" msgstr "Обробка помилок" -#: utils/misc/guc_tables.c:744 +#: utils/misc/guc_tables.c:718 msgid "Preset Options" msgstr "Визначені параметри" -#: utils/misc/guc_tables.c:746 +#: utils/misc/guc_tables.c:719 msgid "Customized Options" msgstr "Настроєні параметри" -#: utils/misc/guc_tables.c:748 +#: utils/misc/guc_tables.c:720 msgid "Developer Options" msgstr "Параметри для розробників" -#: utils/misc/guc_tables.c:805 +#: utils/misc/guc_tables.c:775 msgid "Enables the planner's use of sequential-scan plans." msgstr "Дає змогу планувальнику використати плани послідовного сканування." -#: utils/misc/guc_tables.c:815 +#: utils/misc/guc_tables.c:785 msgid "Enables the planner's use of index-scan plans." msgstr "Дає змогу планувальнику використати плани сканування по індексу." -#: utils/misc/guc_tables.c:825 +#: utils/misc/guc_tables.c:795 msgid "Enables the planner's use of index-only-scan plans." msgstr "Дає змогу планувальнику використати плани сканування лише індекса." -#: utils/misc/guc_tables.c:835 +#: utils/misc/guc_tables.c:805 msgid "Enables the planner's use of bitmap-scan plans." msgstr "Дає змогу планувальнику використати плани сканування по точковому рисунку." -#: utils/misc/guc_tables.c:845 +#: utils/misc/guc_tables.c:815 msgid "Enables the planner's use of TID scan plans." msgstr "Дає змогу планувальнику використати плани сканування TID." -#: utils/misc/guc_tables.c:855 +#: utils/misc/guc_tables.c:825 msgid "Enables the planner's use of explicit sort steps." msgstr "Дає змогу планувальнику використати кроки з явним сортуванням." -#: utils/misc/guc_tables.c:865 +#: utils/misc/guc_tables.c:835 msgid "Enables the planner's use of incremental sort steps." msgstr "Дає змогу планувальнику використати кроки інкрементного сортування." -#: utils/misc/guc_tables.c:875 +#: utils/misc/guc_tables.c:845 msgid "Enables the planner's use of hashed aggregation plans." msgstr "Дає змогу планувальнику використовувати плани агрегації по гешу." -#: utils/misc/guc_tables.c:885 +#: utils/misc/guc_tables.c:855 msgid "Enables the planner's use of materialization." msgstr "Дає змогу планувальнику використовувати матеріалізацію." -#: utils/misc/guc_tables.c:895 +#: utils/misc/guc_tables.c:865 msgid "Enables the planner's use of memoization." msgstr "Дає змогу планувальнику використовувати мемоїзацію." -#: utils/misc/guc_tables.c:905 +#: utils/misc/guc_tables.c:875 msgid "Enables the planner's use of nested-loop join plans." msgstr "Дає змогу планувальнику використовувати плани з'єднання з вкладеними циклами." -#: utils/misc/guc_tables.c:915 +#: utils/misc/guc_tables.c:885 msgid "Enables the planner's use of merge join plans." msgstr "Дає змогу планувальнику використовувати плани з'єднання об'єднанням." -#: utils/misc/guc_tables.c:925 +#: utils/misc/guc_tables.c:895 msgid "Enables the planner's use of hash join plans." msgstr "Дає змогу планувальнику використовувати плани з'єднання по гешу." -#: utils/misc/guc_tables.c:935 +#: utils/misc/guc_tables.c:905 msgid "Enables the planner's use of gather merge plans." msgstr "Дає змогу планувальнику використовувати плани збору об'єднанням." -#: utils/misc/guc_tables.c:945 +#: utils/misc/guc_tables.c:915 msgid "Enables partitionwise join." msgstr "Вмикає з'єднання з урахуванням секціонування." -#: utils/misc/guc_tables.c:955 +#: utils/misc/guc_tables.c:925 msgid "Enables partitionwise aggregation and grouping." msgstr "Вмикає агрегацію і групування з урахуванням секціонування." -#: utils/misc/guc_tables.c:965 +#: utils/misc/guc_tables.c:935 msgid "Enables the planner's use of parallel append plans." msgstr "Дає змогу планувальнику використовувати плани паралельного додавання." -#: utils/misc/guc_tables.c:975 +#: utils/misc/guc_tables.c:945 msgid "Enables the planner's use of parallel hash plans." msgstr "Дає змогу планувальнику використовувати плани паралельного з'єднання по гешу." -#: utils/misc/guc_tables.c:985 +#: utils/misc/guc_tables.c:955 msgid "Enables plan-time and execution-time partition pruning." msgstr "Активує видалення розділу під час планування і виконання." -#: utils/misc/guc_tables.c:986 +#: utils/misc/guc_tables.c:956 msgid "Allows the query planner and executor to compare partition bounds to conditions in the query to determine which partitions must be scanned." msgstr "Дозволяє планувальнику і виконавцю запитів порівнювати границі секцій з умовами в запиті і визначати які секції повинні бути відскановані." -#: utils/misc/guc_tables.c:997 +#: utils/misc/guc_tables.c:967 msgid "Enables the planner's ability to produce plans that provide presorted input for ORDER BY / DISTINCT aggregate functions." msgstr "Дозволяє планувальнику створювати плани з попередньо відсортованими даними для агрегованих функцій ORDER BY / DISTINCT." -#: utils/misc/guc_tables.c:1000 +#: utils/misc/guc_tables.c:970 msgid "Allows the query planner to build plans that provide presorted input for aggregate functions with an ORDER BY / DISTINCT clause. When disabled, implicit sorts are always performed during execution." msgstr "Дозволяє планувальнику запитів створювати плани, які надають попередньо відсортовані дані для агрегованих функцій з реченням ORDER BY / DISTINCT. Якщо цей параметр вимкнено, під час виконання запиту завжди виконується неявне сортування." -#: utils/misc/guc_tables.c:1012 +#: utils/misc/guc_tables.c:982 msgid "Enables the planner's use of async append plans." msgstr "Дає змогу планувальнику використовувати асинхронні плани додавання." -#: utils/misc/guc_tables.c:1022 +#: utils/misc/guc_tables.c:992 +msgid "Enables reordering of GROUP BY keys." +msgstr "Дозволяє перевпорядкувати ключі GROUP BY." + +#: utils/misc/guc_tables.c:1002 msgid "Enables genetic query optimization." msgstr "Вмикає генетичну оптимізацію запитів." -#: utils/misc/guc_tables.c:1023 +#: utils/misc/guc_tables.c:1003 msgid "This algorithm attempts to do planning without exhaustive searching." msgstr "Цей алгоритм намагається побудувати план без повного перебору." -#: utils/misc/guc_tables.c:1034 +#: utils/misc/guc_tables.c:1017 msgid "Shows whether the current user is a superuser." msgstr "Показує, чи є поточний користувач суперкористувачем." -#: utils/misc/guc_tables.c:1044 +#: utils/misc/guc_tables.c:1032 +msgid "Allows running the ALTER SYSTEM command." +msgstr "Дозволяє запускати команду ALTER SYSTEM." + +#: utils/misc/guc_tables.c:1033 +msgid "Can be set to off for environments where global configuration changes should be made using a different method." +msgstr "" + +#: utils/misc/guc_tables.c:1043 msgid "Enables advertising the server via Bonjour." msgstr "Вмикає оголошення серверу через Bonjour." -#: utils/misc/guc_tables.c:1053 +#: utils/misc/guc_tables.c:1052 msgid "Collects transaction commit time." msgstr "Збирає час затвердження транзакцій." -#: utils/misc/guc_tables.c:1062 +#: utils/misc/guc_tables.c:1061 msgid "Enables SSL connections." msgstr "Вмикає SSL-підключення." -#: utils/misc/guc_tables.c:1071 -msgid "Controls whether ssl_passphrase_command is called during server reload." -msgstr "Визначає, чи викликається ssl_passphrase_command під час перезавантаження сервера." +#: utils/misc/guc_tables.c:1070 +msgid "Controls whether \"ssl_passphrase_command\" is called during server reload." +msgstr "" -#: utils/misc/guc_tables.c:1080 +#: utils/misc/guc_tables.c:1079 msgid "Give priority to server ciphersuite order." msgstr "Віддавати перевагу замовленню набору шрифтів сервера." -#: utils/misc/guc_tables.c:1089 +#: utils/misc/guc_tables.c:1088 msgid "Forces synchronization of updates to disk." msgstr "Примусова синхронізація оновлень на диск." -#: utils/misc/guc_tables.c:1090 +#: utils/misc/guc_tables.c:1089 msgid "The server will use the fsync() system call in several places to make sure that updates are physically written to disk. This ensures that a database cluster will recover to a consistent state after an operating system or hardware crash." msgstr "Сервер буде використовувати системний виклик fsync() в декількох місцях, щоб переконатися, що оновлення фізично записані на диск. Це гарантує, що кластер баз даних відновиться до узгодженого стану після аварійного завершення роботи операційної системи чи апаратного збою." -#: utils/misc/guc_tables.c:1101 +#: utils/misc/guc_tables.c:1100 msgid "Continues processing after a checksum failure." msgstr "Продовжує обробку після помилки контрольної суми." -#: utils/misc/guc_tables.c:1102 +#: utils/misc/guc_tables.c:1101 msgid "Detection of a checksum failure normally causes PostgreSQL to report an error, aborting the current transaction. Setting ignore_checksum_failure to true causes the system to ignore the failure (but still report a warning), and continue processing. This behavior could cause crashes or other serious problems. Only has an effect if checksums are enabled." msgstr "Виявляючи помилку контрольної суми, PostgreSQL звичайно повідомляє про помилку і перериває поточну транзакцію. Але якщо ignore_checksum_failure дорівнює true, система пропустить помилку (але видасть попередження) і продовжить обробку. Ця поведінка може бути причиною аварійних завершень роботи або інших серйозних проблем. Це має місце, лише якщо ввімкнен контроль цілосності сторінок." -#: utils/misc/guc_tables.c:1116 +#: utils/misc/guc_tables.c:1115 msgid "Continues processing past damaged page headers." msgstr "Продовжує обробку при пошкоджені заголовків сторінок." -#: utils/misc/guc_tables.c:1117 -msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting zero_damaged_pages to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." -msgstr "Виявляючи пошкоджений заголовок сторінки, PostgreSQL звичайно повідомляє про помилку, перериваючи поточну транзакцію. Але якщо zero_damaged_pages дорівнює true система видасть попередження, обнулить пошкоджену сторінку, і продовжить обробку. Ця поведінка знищить дані, а саме рядків в пошкодженій сторінці." +#: utils/misc/guc_tables.c:1116 +msgid "Detection of a damaged page header normally causes PostgreSQL to report an error, aborting the current transaction. Setting \"zero_damaged_pages\" to true causes the system to instead report a warning, zero out the damaged page, and continue processing. This behavior will destroy data, namely all the rows on the damaged page." +msgstr "" -#: utils/misc/guc_tables.c:1130 +#: utils/misc/guc_tables.c:1129 msgid "Continues recovery after an invalid pages failure." msgstr "Продовжує відновлення після помилки неприпустимих сторінок." -#: utils/misc/guc_tables.c:1131 -msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting ignore_invalid_pages to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." -msgstr "Виявлення WAL записів, які мають посилання на неприпустимі сторінки під час відновлення, змушує PostgreSQL підняти помилку на рівень PANIC, перериваючи відновлення. Встановлення параметру ignore_invalid_pages на true змусить систему ігнорувати неприпустимі посилання на сторінки в WAL записах (але все ще буде повідомляти про попередження), і продовжити відновлення. Ця поведінка може викликати збої, втрату даних, розповсюдження або приховання пошкоджень, або інші серйозні проблеми. Діє лише під час відновлення або в режимі очікування." +#: utils/misc/guc_tables.c:1130 +msgid "Detection of WAL records having references to invalid pages during recovery causes PostgreSQL to raise a PANIC-level error, aborting the recovery. Setting \"ignore_invalid_pages\" to true causes the system to ignore invalid page references in WAL records (but still report a warning), and continue recovery. This behavior may cause crashes, data loss, propagate or hide corruption, or other serious problems. Only has an effect during recovery or in standby mode." +msgstr "" -#: utils/misc/guc_tables.c:1149 +#: utils/misc/guc_tables.c:1148 msgid "Writes full pages to WAL when first modified after a checkpoint." msgstr "Запис повних сторінок до WAL при першій зміні після контрольної точки." -#: utils/misc/guc_tables.c:1150 +#: utils/misc/guc_tables.c:1149 msgid "A page write in process during an operating system crash might be only partially written to disk. During recovery, the row changes stored in WAL are not enough to recover. This option writes pages when first modified after a checkpoint to WAL so full recovery is possible." msgstr "Сторінка, записувана під час аварійного завершення роботи операційної системи може бути записаною на диск частково. Під час відновлення, журналу змін рядків в WAL буде недостатньо для відновлення. Цей параметр записує повні сторінки після першої зміни після контрольної точки, тож відновлення можливе." -#: utils/misc/guc_tables.c:1163 +#: utils/misc/guc_tables.c:1162 msgid "Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification." msgstr "Записує повні сторінки до WAL при першій зміні після контрольної точки, навіть при некритичних змінах." -#: utils/misc/guc_tables.c:1173 +#: utils/misc/guc_tables.c:1172 msgid "Writes zeroes to new WAL files before first use." msgstr "Перед першим використанням записує нулі до нових файлів WAL." -#: utils/misc/guc_tables.c:1183 +#: utils/misc/guc_tables.c:1182 msgid "Recycles WAL files by renaming them." msgstr "Перезаписує файли WAL, перейменувавши їх." -#: utils/misc/guc_tables.c:1193 +#: utils/misc/guc_tables.c:1192 msgid "Logs each checkpoint." msgstr "Журналювати кожну контрольну точку." -#: utils/misc/guc_tables.c:1202 +#: utils/misc/guc_tables.c:1201 msgid "Logs each successful connection." msgstr "Журналювати кожне успішне підключення." -#: utils/misc/guc_tables.c:1211 +#: utils/misc/guc_tables.c:1210 +msgid "Logs details of pre-authentication connection handshake." +msgstr "" + +#: utils/misc/guc_tables.c:1220 msgid "Logs end of a session, including duration." msgstr "Журналювати кінець сеансу, зокрема тривалість." -#: utils/misc/guc_tables.c:1220 +#: utils/misc/guc_tables.c:1229 msgid "Logs each replication command." msgstr "Журналювати кожну команду реплікації." -#: utils/misc/guc_tables.c:1229 +#: utils/misc/guc_tables.c:1238 msgid "Shows whether the running server has assertion checks enabled." msgstr "Показує, чи активовані перевірки твердження на працюючому сервері." -#: utils/misc/guc_tables.c:1240 +#: utils/misc/guc_tables.c:1249 msgid "Terminate session on any error." msgstr "Припиняти сеанси при будь-якій помилці." -#: utils/misc/guc_tables.c:1249 +#: utils/misc/guc_tables.c:1258 msgid "Reinitialize server after backend crash." msgstr "Повторити ініціалізацію сервера, після внутрішнього аварійного завершення роботи." -#: utils/misc/guc_tables.c:1258 +#: utils/misc/guc_tables.c:1267 msgid "Remove temporary files after backend crash." msgstr "Видалити тимчасові файли після аварійного завершення роботи внутрішнього сервера." -#: utils/misc/guc_tables.c:1268 +#: utils/misc/guc_tables.c:1277 msgid "Send SIGABRT not SIGQUIT to child processes after backend crash." msgstr "Надсилати SIGABRT, а не SIGQUIT дочірнім процесам після аварійного завершення роботи бекенда." -#: utils/misc/guc_tables.c:1278 +#: utils/misc/guc_tables.c:1287 msgid "Send SIGABRT not SIGKILL to stuck child processes." msgstr "Надсилати SIGABRT, а не SIGKILL до дочірніх процесів, що застрягли." -#: utils/misc/guc_tables.c:1289 +#: utils/misc/guc_tables.c:1298 msgid "Logs the duration of each completed SQL statement." msgstr "Журналювати тривалість кожного виконаного SQL-оператора." -#: utils/misc/guc_tables.c:1298 +#: utils/misc/guc_tables.c:1307 msgid "Logs each query's parse tree." msgstr "Журналювати дерево аналізу для кожного запиту." -#: utils/misc/guc_tables.c:1307 +#: utils/misc/guc_tables.c:1316 msgid "Logs each query's rewritten parse tree." msgstr "Журналювати переписане дерево аналізу для кожного запиту." -#: utils/misc/guc_tables.c:1316 +#: utils/misc/guc_tables.c:1325 msgid "Logs each query's execution plan." msgstr "Журналювати план виконання кожного запиту." -#: utils/misc/guc_tables.c:1325 +#: utils/misc/guc_tables.c:1334 msgid "Indents parse and plan tree displays." msgstr "Відступи при відображенні дерев аналізу і плану запитів." -#: utils/misc/guc_tables.c:1334 +#: utils/misc/guc_tables.c:1343 msgid "Writes parser performance statistics to the server log." msgstr "Запис статистики продуктивності аналізу до запису сервера." -#: utils/misc/guc_tables.c:1343 +#: utils/misc/guc_tables.c:1352 msgid "Writes planner performance statistics to the server log." msgstr "Запис статистики продуктивності планувальника до запису сервера." -#: utils/misc/guc_tables.c:1352 +#: utils/misc/guc_tables.c:1361 msgid "Writes executor performance statistics to the server log." msgstr "Запис статистики продуктивності виконувача до запису сервера." -#: utils/misc/guc_tables.c:1361 +#: utils/misc/guc_tables.c:1370 msgid "Writes cumulative performance statistics to the server log." msgstr "Запис сукупної статистики продуктивності до запису сервера." -#: utils/misc/guc_tables.c:1371 +#: utils/misc/guc_tables.c:1380 msgid "Logs system resource usage statistics (memory and CPU) on various B-tree operations." msgstr "Журналювати статистику використання системних ресурсів (пам'яті і ЦП) при різноманітних операціях з B-tree." -#: utils/misc/guc_tables.c:1383 +#: utils/misc/guc_tables.c:1392 msgid "Collects information about executing commands." msgstr "Збирати інформацію про команди які виконуються." -#: utils/misc/guc_tables.c:1384 +#: utils/misc/guc_tables.c:1393 msgid "Enables the collection of information on the currently executing command of each session, along with the time at which that command began execution." msgstr "Активує збір інформації про поточні команди, які виконуються в кожному сеансі, разом з часом запуску команди." -#: utils/misc/guc_tables.c:1394 +#: utils/misc/guc_tables.c:1403 msgid "Collects statistics on database activity." msgstr "Збирати статистику про активність бази даних." -#: utils/misc/guc_tables.c:1403 +#: utils/misc/guc_tables.c:1412 msgid "Collects timing statistics for database I/O activity." msgstr "Збирати статистику за часом активності введення/виведення для бази даних." -#: utils/misc/guc_tables.c:1412 +#: utils/misc/guc_tables.c:1421 msgid "Collects timing statistics for WAL I/O activity." msgstr "Збирає статистику часу для активності вводу/виводу WAL." -#: utils/misc/guc_tables.c:1422 +#: utils/misc/guc_tables.c:1431 msgid "Updates the process title to show the active SQL command." msgstr "Оновлення виводить в заголовок процесу активну SQL-команду." -#: utils/misc/guc_tables.c:1423 +#: utils/misc/guc_tables.c:1432 msgid "Enables updating of the process title every time a new SQL command is received by the server." msgstr "Відображає в заголовку процеса кожну SQL-команду, отриману сервером." -#: utils/misc/guc_tables.c:1432 +#: utils/misc/guc_tables.c:1441 msgid "Starts the autovacuum subprocess." msgstr "Запускає підпроцес автоочистки." -#: utils/misc/guc_tables.c:1442 +#: utils/misc/guc_tables.c:1451 msgid "Generates debugging output for LISTEN and NOTIFY." msgstr "Генерує налагодженні повідомлення для LISTEN і NOTIFY." -#: utils/misc/guc_tables.c:1454 +#: utils/misc/guc_tables.c:1463 msgid "Emits information about lock usage." msgstr "Видає інформацію про блокування, які використовуються." -#: utils/misc/guc_tables.c:1464 +#: utils/misc/guc_tables.c:1473 msgid "Emits information about user lock usage." msgstr "Видає інформацію про користувацькі блокування, які використовуються." -#: utils/misc/guc_tables.c:1474 +#: utils/misc/guc_tables.c:1483 msgid "Emits information about lightweight lock usage." msgstr "Видає інформацію про спрощені блокування, які використовуються." -#: utils/misc/guc_tables.c:1484 +#: utils/misc/guc_tables.c:1493 msgid "Dumps information about all current locks when a deadlock timeout occurs." msgstr "Виводить інформацію про всі поточні блокування, при тайм-ауті взаємного блокування." -#: utils/misc/guc_tables.c:1496 +#: utils/misc/guc_tables.c:1505 msgid "Logs long lock waits." msgstr "Журналювати тривалі очікування в блокуваннях." -#: utils/misc/guc_tables.c:1505 +#: utils/misc/guc_tables.c:1514 msgid "Logs standby recovery conflict waits." msgstr "Журналює очікування конфлікту відновлення." -#: utils/misc/guc_tables.c:1514 +#: utils/misc/guc_tables.c:1523 msgid "Logs the host name in the connection logs." msgstr "Журналювати ім’я хоста до записів підключення." -#: utils/misc/guc_tables.c:1515 +#: utils/misc/guc_tables.c:1524 msgid "By default, connection logs only show the IP address of the connecting host. If you want them to show the host name you can turn this on, but depending on your host name resolution setup it might impose a non-negligible performance penalty." msgstr "За замовчуванням, записи підключень показують лише IP-адреси хостів, які підключилися. Якщо ви хочете бачити імена хостів ви можете ввімкнути цей параметр, але врахуйте, що це може значно вплинути на продуктивність." -#: utils/misc/guc_tables.c:1526 +#: utils/misc/guc_tables.c:1535 msgid "Treats \"expr=NULL\" as \"expr IS NULL\"." msgstr "Вважати \"expr=NULL\" як \"expr IS NULL\"." -#: utils/misc/guc_tables.c:1527 +#: utils/misc/guc_tables.c:1536 msgid "When turned on, expressions of the form expr = NULL (or NULL = expr) are treated as expr IS NULL, that is, they return true if expr evaluates to the null value, and false otherwise. The correct behavior of expr = NULL is to always return null (unknown)." msgstr "Коли цей параметр ввімкнений, вирази форми expr = NULL (або NULL = expr) вважаються як expr IS NULL, тобто, повертають true, якщо expr співпадає зі значенням null, і false в іншому разі. Правильна поведінка expr = NULL - завжди повертати null (невідомо)." -#: utils/misc/guc_tables.c:1539 -msgid "Enables per-database user names." -msgstr "Вмикає зв'язування імен користувачів з базами даних." - #: utils/misc/guc_tables.c:1548 msgid "Sets the default read-only status of new transactions." msgstr "Встановлює статус \"лише читання\" за замовчуванням для нових транзакцій." @@ -27684,1366 +28761,1440 @@ msgid "Sets whether to include or exclude transaction with recovery target." msgstr "Встановлює, включати чи виключати транзакції з метою відновлення." #: utils/misc/guc_tables.c:1778 +msgid "Starts the WAL summarizer process to enable incremental backup." +msgstr "Запускає процес підсумовування WAL, щоб увімкнути інкрементне резервне копіювання." + +#: utils/misc/guc_tables.c:1788 msgid "Allows connections and queries during recovery." msgstr "Дозволяє підключення і запити під час відновлення." -#: utils/misc/guc_tables.c:1788 +#: utils/misc/guc_tables.c:1798 msgid "Allows feedback from a hot standby to the primary that will avoid query conflicts." msgstr "Дозволяє зворотній зв'язок серверу hot standby з основним для уникнення конфліктів запитів." -#: utils/misc/guc_tables.c:1798 +#: utils/misc/guc_tables.c:1808 msgid "Shows whether hot standby is currently active." msgstr "Показує, чи hot standby наразі активний." -#: utils/misc/guc_tables.c:1809 +#: utils/misc/guc_tables.c:1819 msgid "Allows modifications of the structure of system tables." msgstr "Дозволяє модифікації структури системних таблиць." -#: utils/misc/guc_tables.c:1820 +#: utils/misc/guc_tables.c:1830 msgid "Disables reading from system indexes." msgstr "Вимикає читання з системних індексів." -#: utils/misc/guc_tables.c:1821 +#: utils/misc/guc_tables.c:1831 msgid "It does not prevent updating the indexes, so it is safe to use. The worst consequence is slowness." msgstr "Це не забороняє оновлення індексів, тож дана поведінка безпечна. Найгірший наслідок це сповільнення." -#: utils/misc/guc_tables.c:1832 +#: utils/misc/guc_tables.c:1842 msgid "Allows tablespaces directly inside pg_tblspc, for testing." msgstr "Дозволяє табличні простори безпосередньо всередині pg_tblspc, для тестування." -#: utils/misc/guc_tables.c:1843 +#: utils/misc/guc_tables.c:1853 msgid "Enables backward compatibility mode for privilege checks on large objects." msgstr "Вмикає режим зворотньої сумісності при перевірці прав для великих об'єктів." -#: utils/misc/guc_tables.c:1844 +#: utils/misc/guc_tables.c:1854 msgid "Skips privilege checks when reading or modifying large objects, for compatibility with PostgreSQL releases prior to 9.0." msgstr "Пропускає перевірки прав при читанні або зміненні великих об'єктів, для сумісності з версіями PostgreSQL до 9.0." -#: utils/misc/guc_tables.c:1854 +#: utils/misc/guc_tables.c:1864 msgid "When generating SQL fragments, quote all identifiers." msgstr "Генеруючи SQL-фрагменти, включати всі ідентифікатори в лапки." -#: utils/misc/guc_tables.c:1864 +#: utils/misc/guc_tables.c:1874 msgid "Shows whether data checksums are turned on for this cluster." msgstr "Показує, чи ввімкнена контрольна сума даних для цього кластеру." -#: utils/misc/guc_tables.c:1875 +#: utils/misc/guc_tables.c:1885 msgid "Add sequence number to syslog messages to avoid duplicate suppression." msgstr "Додає послідовне число до повідомлень syslog, щоб уникнути ігнорування дублікатів." -#: utils/misc/guc_tables.c:1885 +#: utils/misc/guc_tables.c:1895 msgid "Split messages sent to syslog by lines and to fit into 1024 bytes." msgstr "Розділяє повідомлення, які передаються в syslog, рядками розміром не більше 1024 байт." -#: utils/misc/guc_tables.c:1895 +#: utils/misc/guc_tables.c:1905 msgid "Controls whether Gather and Gather Merge also run subplans." msgstr "Визначає, чи вузли зібрання і зібрання об'єднанням також виконають підплани." -#: utils/misc/guc_tables.c:1896 +#: utils/misc/guc_tables.c:1906 msgid "Should gather nodes also run subplans or just gather tuples?" msgstr "Чи повинні вузли збірки також виконувати підплани або тільки збирати кортежі?" -#: utils/misc/guc_tables.c:1906 +#: utils/misc/guc_tables.c:1916 msgid "Allow JIT compilation." msgstr "Дозволити JIT-компіляцію." -#: utils/misc/guc_tables.c:1917 +#: utils/misc/guc_tables.c:1927 msgid "Register JIT-compiled functions with debugger." msgstr "Зареєструйте функції JIT-compiled за допомогою налагоджувача." -#: utils/misc/guc_tables.c:1934 +#: utils/misc/guc_tables.c:1944 msgid "Write out LLVM bitcode to facilitate JIT debugging." msgstr "Виводити бітовий код LLVM для полегшення налагодження JIT." -#: utils/misc/guc_tables.c:1945 +#: utils/misc/guc_tables.c:1955 msgid "Allow JIT compilation of expressions." msgstr "Дозволити JIT-компіляцію виразів." -#: utils/misc/guc_tables.c:1956 +#: utils/misc/guc_tables.c:1966 msgid "Register JIT-compiled functions with perf profiler." msgstr "Зареєструйте функції JIT-compiled за допомогою профілювальника perf." -#: utils/misc/guc_tables.c:1973 +#: utils/misc/guc_tables.c:1983 msgid "Allow JIT compilation of tuple deforming." msgstr "Дозволити JIT-компіляцію перетворення кортежів." -#: utils/misc/guc_tables.c:1984 +#: utils/misc/guc_tables.c:1994 msgid "Whether to continue running after a failure to sync data files." msgstr "Чи продовжувати виконання після помилки синхронізації файлів даних на диску." -#: utils/misc/guc_tables.c:1993 +#: utils/misc/guc_tables.c:2003 msgid "Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured." msgstr "Встановлює чи повинен одержувач WAL створити тимчасовий слот реплікації, якщо постійний слот не налаштований." -#: utils/misc/guc_tables.c:2011 +#: utils/misc/guc_tables.c:2012 +msgid "Enables event triggers." +msgstr "Вмикає тригери подій." + +#: utils/misc/guc_tables.c:2013 +msgid "When enabled, event triggers will fire for all applicable statements." +msgstr "Якщо увімкнено, тригери подій спрацьовуватимуть для всіх застосовних операторів." + +#: utils/misc/guc_tables.c:2022 +msgid "Enables a physical standby to synchronize logical failover replication slots from the primary server." +msgstr "" + +#: utils/misc/guc_tables.c:2040 msgid "Sets the amount of time to wait before forcing a switch to the next WAL file." msgstr "Встановлює кількість часу очікування перед примусовим переходом на наступний файл WAL." -#: utils/misc/guc_tables.c:2022 +#: utils/misc/guc_tables.c:2051 msgid "Sets the amount of time to wait after authentication on connection startup." msgstr "Встановлює кількість часу для очікування після автенифікації під час запуску з'єднання." -#: utils/misc/guc_tables.c:2024 utils/misc/guc_tables.c:2658 +#: utils/misc/guc_tables.c:2053 utils/misc/guc_tables.c:2780 msgid "This allows attaching a debugger to the process." msgstr "Це дозволяє підключити налагоджувач до процесу." -#: utils/misc/guc_tables.c:2033 +#: utils/misc/guc_tables.c:2062 msgid "Sets the default statistics target." msgstr "Встановлює мету статистики за замовчуванням." -#: utils/misc/guc_tables.c:2034 +#: utils/misc/guc_tables.c:2063 msgid "This applies to table columns that have not had a column-specific target set via ALTER TABLE SET STATISTICS." msgstr "Це застосовується до стовпців таблиці, для котрих мета статистики не встановлена явно через ALTER TABLE SET STATISTICS." -#: utils/misc/guc_tables.c:2043 +#: utils/misc/guc_tables.c:2072 msgid "Sets the FROM-list size beyond which subqueries are not collapsed." msgstr "Встановлює розмір для списку FROM, при перевищені котрого вкладені запити не згортаються." -#: utils/misc/guc_tables.c:2045 +#: utils/misc/guc_tables.c:2074 msgid "The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items." msgstr "Планувальник об'єднає вкладені запити з зовнішніми, якщо в отриманому списку FROM буде не більше заданої кількості елементів." -#: utils/misc/guc_tables.c:2056 +#: utils/misc/guc_tables.c:2085 msgid "Sets the FROM-list size beyond which JOIN constructs are not flattened." msgstr "Встановлює розмір для списку FROM, при перевищенні котрого конструкції JOIN не подаються у вигляді рядка." -#: utils/misc/guc_tables.c:2058 +#: utils/misc/guc_tables.c:2087 msgid "The planner will flatten explicit JOIN constructs into lists of FROM items whenever a list of no more than this many items would result." msgstr "Планувальник буде подавати у вигляді рядка явні конструкції JOIN в списки FROM, допоки в отриманому списку не більше заданої кількості елементів." -#: utils/misc/guc_tables.c:2069 +#: utils/misc/guc_tables.c:2098 msgid "Sets the threshold of FROM items beyond which GEQO is used." msgstr "Встановлює граничне значення для елементів FROM, при перевищенні котрого використовується GEQO." -#: utils/misc/guc_tables.c:2079 +#: utils/misc/guc_tables.c:2108 msgid "GEQO: effort is used to set the default for other GEQO parameters." msgstr "GEQO: зусилля використовувались щоб встановити значення за замовчуванням для інших параметрів GEQO." -#: utils/misc/guc_tables.c:2089 +#: utils/misc/guc_tables.c:2118 msgid "GEQO: number of individuals in the population." msgstr "GEQO: кількість користувачів у популяції." -#: utils/misc/guc_tables.c:2090 utils/misc/guc_tables.c:2100 +#: utils/misc/guc_tables.c:2119 utils/misc/guc_tables.c:2129 msgid "Zero selects a suitable default value." msgstr "Нуль вибирає придатне значення за замовчуванням." -#: utils/misc/guc_tables.c:2099 +#: utils/misc/guc_tables.c:2128 msgid "GEQO: number of iterations of the algorithm." msgstr "GEQO: кількість ітерацій в алгоритмі." -#: utils/misc/guc_tables.c:2111 +#: utils/misc/guc_tables.c:2140 msgid "Sets the time to wait on a lock before checking for deadlock." msgstr "Встановлює час очікування в блокуванні до перевірки на взаємне блокування." -#: utils/misc/guc_tables.c:2122 +#: utils/misc/guc_tables.c:2151 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data." msgstr "Встановлює максимальну затримку до скасування запитів, коли hot standby сервер обробляє архівні дані WAL." -#: utils/misc/guc_tables.c:2133 +#: utils/misc/guc_tables.c:2162 msgid "Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data." msgstr "Встановлює максимальну затримку до скасування запитів, коли hot standby сервер обробляє дані WAL з потоку." -#: utils/misc/guc_tables.c:2144 +#: utils/misc/guc_tables.c:2173 msgid "Sets the minimum delay for applying changes during recovery." msgstr "Встановлює мінімальну затримку для застосування змін під час відновлення." -#: utils/misc/guc_tables.c:2155 +#: utils/misc/guc_tables.c:2184 msgid "Sets the maximum interval between WAL receiver status reports to the sending server." msgstr "Встановлює максимальний інтервал між звітами про стан одержувачів WAL для серверу надсилання." -#: utils/misc/guc_tables.c:2166 +#: utils/misc/guc_tables.c:2195 msgid "Sets the maximum wait time to receive data from the sending server." msgstr "Встановлює максимальний час очікування для отримання даних з серверу надсилання." -#: utils/misc/guc_tables.c:2177 +#: utils/misc/guc_tables.c:2206 msgid "Sets the maximum number of concurrent connections." msgstr "Встановлює максимальну кілкість паралельних підключень." -#: utils/misc/guc_tables.c:2188 +#: utils/misc/guc_tables.c:2217 msgid "Sets the number of connection slots reserved for superusers." msgstr "Встановлює кількість зарезервованих слотів підключень для суперкористувачів." -#: utils/misc/guc_tables.c:2198 +#: utils/misc/guc_tables.c:2227 msgid "Sets the number of connection slots reserved for roles with privileges of pg_use_reserved_connections." msgstr "Встановлює кількість слотів підключення, зарезервованих для ролей з правами pg_use_reserved_connections." -#: utils/misc/guc_tables.c:2209 +#: utils/misc/guc_tables.c:2238 msgid "Amount of dynamic shared memory reserved at startup." msgstr "Кількість динамічної спільної пам'яті, зарезервованої під час запуску." -#: utils/misc/guc_tables.c:2224 +#: utils/misc/guc_tables.c:2253 msgid "Sets the number of shared memory buffers used by the server." msgstr "Встановлює кількість буферів спільної пам'яті, використовуваних сервером." -#: utils/misc/guc_tables.c:2235 +#: utils/misc/guc_tables.c:2264 msgid "Sets the buffer pool size for VACUUM, ANALYZE, and autovacuum." msgstr "Встановлює розмір буферного пулу для VACUUM, ANALYZE та автоочистки." -#: utils/misc/guc_tables.c:2246 +#: utils/misc/guc_tables.c:2275 msgid "Shows the size of the server's main shared memory area (rounded up to the nearest MB)." msgstr "Показує розмір основної спільної пам'яті сервера (округлення до найближчого МБ)." -#: utils/misc/guc_tables.c:2257 +#: utils/misc/guc_tables.c:2286 msgid "Shows the number of huge pages needed for the main shared memory area." msgstr "Показує кількість величезних сторінок, потрібних для основної області спільної пам'яті." -#: utils/misc/guc_tables.c:2258 +#: utils/misc/guc_tables.c:2287 msgid "-1 indicates that the value could not be determined." msgstr "-1 вказує на те, що значення не може бути визначене." -#: utils/misc/guc_tables.c:2268 +#: utils/misc/guc_tables.c:2297 +msgid "Sets the size of the dedicated buffer pool used for the commit timestamp cache." +msgstr "" + +#: utils/misc/guc_tables.c:2298 utils/misc/guc_tables.c:2353 +#: utils/misc/guc_tables.c:2364 +msgid "Specify 0 to have this value determined as a fraction of shared_buffers." +msgstr "" + +#: utils/misc/guc_tables.c:2308 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact member cache." +msgstr "" + +#: utils/misc/guc_tables.c:2319 +msgid "Sets the size of the dedicated buffer pool used for the MultiXact offset cache." +msgstr "" + +#: utils/misc/guc_tables.c:2330 +msgid "Sets the size of the dedicated buffer pool used for the LISTEN/NOTIFY message cache." +msgstr "" + +#: utils/misc/guc_tables.c:2341 +msgid "Sets the size of the dedicated buffer pool used for the serializable transaction cache." +msgstr "" + +#: utils/misc/guc_tables.c:2352 +msgid "Sets the size of the dedicated buffer pool used for the subtransaction cache." +msgstr "" + +#: utils/misc/guc_tables.c:2363 +msgid "Sets the size of the dedicated buffer pool used for the transaction status cache." +msgstr "" + +#: utils/misc/guc_tables.c:2374 msgid "Sets the maximum number of temporary buffers used by each session." msgstr "Встановлює максимальну кількість використовуваних тимчасових буферів, для кожного сеансу." -#: utils/misc/guc_tables.c:2279 +#: utils/misc/guc_tables.c:2385 msgid "Sets the TCP port the server listens on." msgstr "Встановлює TCP-порт для роботи серверу." -#: utils/misc/guc_tables.c:2289 +#: utils/misc/guc_tables.c:2395 msgid "Sets the access permissions of the Unix-domain socket." msgstr "Встановлює дозволи на доступ для Unix-сокету." -#: utils/misc/guc_tables.c:2290 +#: utils/misc/guc_tables.c:2396 msgid "Unix-domain sockets use the usual Unix file system permission set. The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Для Unix-сокетів використовується звичний набір дозволів, як у файлових системах Unix. Очікується, що значення параметра вказується у формі, яка прийнята для системних викликів chmod і umask. (Щоб використати звичний вісімковий формат, додайте в початок 0 (нуль).)" -#: utils/misc/guc_tables.c:2304 +#: utils/misc/guc_tables.c:2410 msgid "Sets the file permissions for log files." msgstr "Встановлює права дозволу для файлів журналу." -#: utils/misc/guc_tables.c:2305 +#: utils/misc/guc_tables.c:2411 msgid "The parameter value is expected to be a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Очікується, що значення параметру буде вказано в числовому форматі, який сприймається системними викликами chmod і umask. (Щоб використати звичний вісімковий формат, додайте в початок 0 (нуль).)" -#: utils/misc/guc_tables.c:2319 +#: utils/misc/guc_tables.c:2425 msgid "Shows the mode of the data directory." msgstr "Показує режим каталогу даних." -#: utils/misc/guc_tables.c:2320 +#: utils/misc/guc_tables.c:2426 msgid "The parameter value is a numeric mode specification in the form accepted by the chmod and umask system calls. (To use the customary octal format the number must start with a 0 (zero).)" msgstr "Значення параметру вказується в числовому форматі, який сприймається системними викликами chmod і umask. (Щоб використати звичний вісімковий формат, додайте в початок 0 (нуль).)" -#: utils/misc/guc_tables.c:2333 +#: utils/misc/guc_tables.c:2439 msgid "Sets the maximum memory to be used for query workspaces." msgstr "Встановлює максимальний об'єм пам'яті для робочих просторів запитів." -#: utils/misc/guc_tables.c:2334 +#: utils/misc/guc_tables.c:2440 msgid "This much memory can be used by each internal sort operation and hash table before switching to temporary disk files." msgstr "Такий об'єм пам'яті може використовуватись кожною внутрішньою операцією сортування і таблицею гешування до переключення на тимчасові файли на диску." -#: utils/misc/guc_tables.c:2346 +#: utils/misc/guc_tables.c:2457 msgid "Sets the maximum memory to be used for maintenance operations." msgstr "Встановлює максимальний об'єм пам'яті для операцій по обслуговуванню." -#: utils/misc/guc_tables.c:2347 +#: utils/misc/guc_tables.c:2458 msgid "This includes operations such as VACUUM and CREATE INDEX." msgstr "Це включає такі операції як VACUUM і CREATE INDEX." -#: utils/misc/guc_tables.c:2357 +#: utils/misc/guc_tables.c:2468 msgid "Sets the maximum memory to be used for logical decoding." msgstr "Встановлює максимальний об'єм пам'яті для логічного декодування." -#: utils/misc/guc_tables.c:2358 +#: utils/misc/guc_tables.c:2469 msgid "This much memory can be used by each internal reorder buffer before spilling to disk." msgstr "Ця велика кількість пам'яті може бути використана кожним внутрішнім перевпорядковуючим буфером перед записом на диск." -#: utils/misc/guc_tables.c:2374 +#: utils/misc/guc_tables.c:2485 msgid "Sets the maximum stack depth, in kilobytes." msgstr "Встановлює максимальну глибину стека, в КБ." -#: utils/misc/guc_tables.c:2385 +#: utils/misc/guc_tables.c:2496 msgid "Limits the total size of all temporary files used by each process." msgstr "Обмежує загальний розмір всіх тимчасових файлів, які використовуються кожним процесом." -#: utils/misc/guc_tables.c:2386 +#: utils/misc/guc_tables.c:2497 msgid "-1 means no limit." msgstr "-1 вимикає обмеження." -#: utils/misc/guc_tables.c:2396 +#: utils/misc/guc_tables.c:2507 msgid "Vacuum cost for a page found in the buffer cache." msgstr "Вартість очистки для сторінки, яка була знайдена в буферному кеші." -#: utils/misc/guc_tables.c:2406 +#: utils/misc/guc_tables.c:2517 msgid "Vacuum cost for a page not found in the buffer cache." msgstr "Вартість очистки для сторінки, яка не була знайдена в буферному кеші." -#: utils/misc/guc_tables.c:2416 +#: utils/misc/guc_tables.c:2527 msgid "Vacuum cost for a page dirtied by vacuum." msgstr "Вартість очистки для сторінки, яка не була \"брудною\"." -#: utils/misc/guc_tables.c:2426 +#: utils/misc/guc_tables.c:2537 msgid "Vacuum cost amount available before napping." msgstr "Кількість доступних витрат вакууму перед від'єднанням." -#: utils/misc/guc_tables.c:2436 +#: utils/misc/guc_tables.c:2547 msgid "Vacuum cost amount available before napping, for autovacuum." msgstr "Кількість доступних витрат вакууму перед від'єднанням, для автовакууму." -#: utils/misc/guc_tables.c:2446 +#: utils/misc/guc_tables.c:2557 msgid "Sets the maximum number of simultaneously open files for each server process." msgstr "Встановлює максимальну кількість одночасно відкритих файлів для кожного процесу." -#: utils/misc/guc_tables.c:2459 +#: utils/misc/guc_tables.c:2570 msgid "Sets the maximum number of simultaneously prepared transactions." msgstr "Встановлює максимальну кількість одночасно підготовлених транзакцій." -#: utils/misc/guc_tables.c:2470 +#: utils/misc/guc_tables.c:2581 msgid "Sets the minimum OID of tables for tracking locks." msgstr "Встановлює мінімальний OID таблиць, для яких відстежуються блокування." -#: utils/misc/guc_tables.c:2471 +#: utils/misc/guc_tables.c:2582 msgid "Is used to avoid output on system tables." msgstr "Використовується для уникнення системних таблиць." -#: utils/misc/guc_tables.c:2480 +#: utils/misc/guc_tables.c:2591 msgid "Sets the OID of the table with unconditionally lock tracing." msgstr "Встановлює OID таблиці для безумовного трасування блокувань." -#: utils/misc/guc_tables.c:2492 +#: utils/misc/guc_tables.c:2603 msgid "Sets the maximum allowed duration of any statement." msgstr "Встановлює максимальну тривалість для будь-якого оператору." -#: utils/misc/guc_tables.c:2493 utils/misc/guc_tables.c:2504 -#: utils/misc/guc_tables.c:2515 utils/misc/guc_tables.c:2526 +#: utils/misc/guc_tables.c:2604 utils/misc/guc_tables.c:2615 +#: utils/misc/guc_tables.c:2626 utils/misc/guc_tables.c:2637 +#: utils/misc/guc_tables.c:2648 msgid "A value of 0 turns off the timeout." msgstr "Значення 0 (нуль) вимикає тайм-аут." -#: utils/misc/guc_tables.c:2503 +#: utils/misc/guc_tables.c:2614 msgid "Sets the maximum allowed duration of any wait for a lock." msgstr "Встановлює максимально дозволену тривалість очікування блокувань." -#: utils/misc/guc_tables.c:2514 +#: utils/misc/guc_tables.c:2625 msgid "Sets the maximum allowed idle time between queries, when in a transaction." msgstr "Встановлює максимально дозволений час очікування між запитами під час транзакції." -#: utils/misc/guc_tables.c:2525 +#: utils/misc/guc_tables.c:2636 +msgid "Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)." +msgstr "" + +#: utils/misc/guc_tables.c:2647 msgid "Sets the maximum allowed idle time between queries, when not in a transaction." msgstr "Встановлює максимально дозволений час очікування між запитами поза транзакцією." -#: utils/misc/guc_tables.c:2536 +#: utils/misc/guc_tables.c:2658 msgid "Minimum age at which VACUUM should freeze a table row." msgstr "Мінімальний вік рядків таблиці, при котрому VACUUM зможе їх закріпити." -#: utils/misc/guc_tables.c:2546 +#: utils/misc/guc_tables.c:2668 msgid "Age at which VACUUM should scan whole table to freeze tuples." msgstr "Вік, при котрому VACUUM повинен сканувати всю таблицю, щоб закріпити кортежі." -#: utils/misc/guc_tables.c:2556 +#: utils/misc/guc_tables.c:2678 msgid "Minimum age at which VACUUM should freeze a MultiXactId in a table row." msgstr "Мінімальний вік, при котрому VACUUM повинен закріпити MultiXactId в рядку таблиці." -#: utils/misc/guc_tables.c:2566 +#: utils/misc/guc_tables.c:2688 msgid "Multixact age at which VACUUM should scan whole table to freeze tuples." msgstr "Вік Multixact, при котрому VACUUM повинен сканувати всю таблицю, щоб закріпити кортежі." -#: utils/misc/guc_tables.c:2576 +#: utils/misc/guc_tables.c:2698 msgid "Age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "Вік, у якому VACUUM повинен спрацювати безпечно, щоб уникнути зациклення." -#: utils/misc/guc_tables.c:2585 +#: utils/misc/guc_tables.c:2707 msgid "Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage." msgstr "Вік Multixact, у якому VACUUM повинен спрацювати безпечно, щоб уникнути зациклення." -#: utils/misc/guc_tables.c:2598 +#: utils/misc/guc_tables.c:2720 msgid "Sets the maximum number of locks per transaction." msgstr "Встановлює максимальну кілкість блокувань на транзакцію." -#: utils/misc/guc_tables.c:2599 -msgid "The shared lock table is sized on the assumption that at most max_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "Розмір спільної таблиці блокування визначається з припущення, що в будь-який момент часу потрібно заблокувати не більше max_locks_per_transaction об'єктів на один серверний процес або підготовлену транзакцію." +#: utils/misc/guc_tables.c:2721 +msgid "The shared lock table is sized on the assumption that at most \"max_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "" -#: utils/misc/guc_tables.c:2610 +#: utils/misc/guc_tables.c:2732 msgid "Sets the maximum number of predicate locks per transaction." msgstr "Встановлює максимальну кількість предикатних блокувань на транзакцію." -#: utils/misc/guc_tables.c:2611 -msgid "The shared predicate lock table is sized on the assumption that at most max_pred_locks_per_transaction objects per server process or prepared transaction will need to be locked at any one time." -msgstr "Розмір спільної таблиці блокування предикатів визначається з припущення, що за один раз потрібно заблокувати не більше max_pred_locks_per_transaction об'єктів на один серверний процес або підготовлену транзакцію." +#: utils/misc/guc_tables.c:2733 +msgid "The shared predicate lock table is sized on the assumption that at most \"max_pred_locks_per_transaction\" objects per server process or prepared transaction will need to be locked at any one time." +msgstr "" -#: utils/misc/guc_tables.c:2622 +#: utils/misc/guc_tables.c:2744 msgid "Sets the maximum number of predicate-locked pages and tuples per relation." msgstr "Встановлює максимальну кількість сторінок і кортежів, блокованих предикатними блокуваннями в одному відношенні." -#: utils/misc/guc_tables.c:2623 +#: utils/misc/guc_tables.c:2745 msgid "If more than this total of pages and tuples in the same relation are locked by a connection, those locks are replaced by a relation-level lock." msgstr "Якщо одним підключенням блокується більше цієї загальної кількості сторінок і кортежів, ці блокування замінюються блокуванням на рівні відношення." -#: utils/misc/guc_tables.c:2633 +#: utils/misc/guc_tables.c:2755 msgid "Sets the maximum number of predicate-locked tuples per page." msgstr "Встановлює максимальну кількість кортежів, блокованих предикатними блокуваннями в одній сторінці." -#: utils/misc/guc_tables.c:2634 +#: utils/misc/guc_tables.c:2756 msgid "If more than this number of tuples on the same page are locked by a connection, those locks are replaced by a page-level lock." msgstr "Якщо одним підключенням блокується більше цієї кількості кортежів на одній і тій же сторінці, ці блокування замінюються блокуванням на рівні сторінки." -#: utils/misc/guc_tables.c:2644 +#: utils/misc/guc_tables.c:2766 msgid "Sets the maximum allowed time to complete client authentication." msgstr "Встановлює максимально допустимий час, за котрий клієнт повинен завершити автентифікацію." -#: utils/misc/guc_tables.c:2656 +#: utils/misc/guc_tables.c:2778 msgid "Sets the amount of time to wait before authentication on connection startup." msgstr "Встановлює кількість часу для очікування перед автенифікацією під час запуску з'єднання." -#: utils/misc/guc_tables.c:2668 +#: utils/misc/guc_tables.c:2790 +msgid "Sets the maximum number of allocated pages for NOTIFY / LISTEN queue." +msgstr "Встановлює максимальну кількість виділених сторінок для черги NOTIFY / LISTEN." + +#: utils/misc/guc_tables.c:2800 msgid "Buffer size for reading ahead in the WAL during recovery." msgstr "Розмір буфера для читання в WAL під час відновлення." -#: utils/misc/guc_tables.c:2669 +#: utils/misc/guc_tables.c:2801 msgid "Maximum distance to read ahead in the WAL to prefetch referenced data blocks." msgstr "Максимальна відстань до читання WAL, для попереднього отримання блоків, на які посилаються." -#: utils/misc/guc_tables.c:2679 +#: utils/misc/guc_tables.c:2811 msgid "Sets the size of WAL files held for standby servers." msgstr "Встановлює розмір WAL файлів, які потрібно зберігати для резервних серверів." -#: utils/misc/guc_tables.c:2690 +#: utils/misc/guc_tables.c:2822 msgid "Sets the minimum size to shrink the WAL to." msgstr "Встановлює мінімальний розмір WAL при стисканні." -#: utils/misc/guc_tables.c:2702 +#: utils/misc/guc_tables.c:2834 msgid "Sets the WAL size that triggers a checkpoint." msgstr "Встановлює розмір WAL, при котрому ініціюється контрольна точка." -#: utils/misc/guc_tables.c:2714 +#: utils/misc/guc_tables.c:2846 msgid "Sets the maximum time between automatic WAL checkpoints." msgstr "Встановлює максимальний час між автоматичними контрольними точками WAL." -#: utils/misc/guc_tables.c:2725 +#: utils/misc/guc_tables.c:2857 msgid "Sets the maximum time before warning if checkpoints triggered by WAL volume happen too frequently." msgstr "Встановлює максимальний час перед попередженням, якщо контрольні точки WAL відбуваються занадто часто." -#: utils/misc/guc_tables.c:2727 +#: utils/misc/guc_tables.c:2859 msgid "Write a message to the server log if checkpoints caused by the filling of WAL segment files happen more frequently than this amount of time. Zero turns off the warning." msgstr "Записує в журнал серверу повідомлення, якщо контрольні точки, викликані переповненням файлів сегментів контрольних точок, з'являються частіше ніж цей проміжок часу. Нуль вимикає попередження." -#: utils/misc/guc_tables.c:2740 utils/misc/guc_tables.c:2958 -#: utils/misc/guc_tables.c:2998 +#: utils/misc/guc_tables.c:2872 utils/misc/guc_tables.c:3090 +#: utils/misc/guc_tables.c:3144 msgid "Number of pages after which previously performed writes are flushed to disk." msgstr "Число сторінок, після досягнення якого раніше виконані операції запису скидаються на диск." -#: utils/misc/guc_tables.c:2751 +#: utils/misc/guc_tables.c:2883 msgid "Sets the number of disk-page buffers in shared memory for WAL." msgstr "Встановлює кількість буферів дискових сторінок в спільній пам'яті для WAL." -#: utils/misc/guc_tables.c:2762 +#: utils/misc/guc_tables.c:2884 +msgid "Specify -1 to have this value determined as a fraction of shared_buffers." +msgstr "" + +#: utils/misc/guc_tables.c:2894 msgid "Time between WAL flushes performed in the WAL writer." msgstr "Час між скиданням WAL в процесі, записуючого WAL." -#: utils/misc/guc_tables.c:2773 +#: utils/misc/guc_tables.c:2905 msgid "Amount of WAL written out by WAL writer that triggers a flush." msgstr "Обсяг WAL, оброблений пишучим WAL процесом, при котрому ініціюється скидання журналу на диск." -#: utils/misc/guc_tables.c:2784 +#: utils/misc/guc_tables.c:2916 msgid "Minimum size of new file to fsync instead of writing WAL." msgstr "Мінімальний розмір нового файлу для fsync замість записування WAL." -#: utils/misc/guc_tables.c:2795 +#: utils/misc/guc_tables.c:2927 msgid "Sets the maximum number of simultaneously running WAL sender processes." msgstr "Встановлює максимальну кількість одночасно працюючих процесів передачі WAL." -#: utils/misc/guc_tables.c:2806 +#: utils/misc/guc_tables.c:2938 msgid "Sets the maximum number of simultaneously defined replication slots." msgstr "Встановлює максимальну кількість одночасно визначених слотів реплікації." -#: utils/misc/guc_tables.c:2816 +#: utils/misc/guc_tables.c:2948 msgid "Sets the maximum WAL size that can be reserved by replication slots." msgstr "Встановлює максимальний розмір WAL, який може бути зарезервований слотами реплікації." -#: utils/misc/guc_tables.c:2817 +#: utils/misc/guc_tables.c:2949 msgid "Replication slots will be marked as failed, and segments released for deletion or recycling, if this much space is occupied by WAL on disk." msgstr "Слоти реплікації будуть позначені як невдалі, і розблоковані сегменти для видалення або переробки, якщо цю кількість місця на диску займає WAL." -#: utils/misc/guc_tables.c:2829 +#: utils/misc/guc_tables.c:2961 msgid "Sets the maximum time to wait for WAL replication." msgstr "Встановлює максимальний час очікування реплікації WAL." -#: utils/misc/guc_tables.c:2840 +#: utils/misc/guc_tables.c:2972 msgid "Sets the delay in microseconds between transaction commit and flushing WAL to disk." msgstr "Встановлює затримку в мілісекундах між затвердженням транзакцій і скиданням WAL на диск." -#: utils/misc/guc_tables.c:2852 -msgid "Sets the minimum number of concurrent open transactions required before performing commit_delay." -msgstr "Встановлює мінімальну кількість одночасно відкритих транзакцій, необхідних до виконання commit_delay." +#: utils/misc/guc_tables.c:2984 +msgid "Sets the minimum number of concurrent open transactions required before performing \"commit_delay\"." +msgstr "" -#: utils/misc/guc_tables.c:2863 +#: utils/misc/guc_tables.c:2995 msgid "Sets the number of digits displayed for floating-point values." msgstr "Встановлює кількість виведених чисел для значень з плаваючою точкою." -#: utils/misc/guc_tables.c:2864 +#: utils/misc/guc_tables.c:2996 msgid "This affects real, double precision, and geometric data types. A zero or negative parameter value is added to the standard number of digits (FLT_DIG or DBL_DIG as appropriate). Any value greater than zero selects precise output mode." msgstr "Це впливає на типи реальних, подвійної точності та геометричних даних. Нульове або від'ємне значення параметру додається до стандартної кількості цифр (FLT_DIG або DBL_DIG у відповідних випадках). Будь-яке значення більше нуля, обирає точний режим виводу." -#: utils/misc/guc_tables.c:2876 +#: utils/misc/guc_tables.c:3008 msgid "Sets the minimum execution time above which a sample of statements will be logged. Sampling is determined by log_statement_sample_rate." msgstr "Встановлює мінімальний час виконання, понад якого вибірка тверджень буде записуватись. Вибірка визначається log_statement_sample_rate." -#: utils/misc/guc_tables.c:2879 +#: utils/misc/guc_tables.c:3011 msgid "Zero logs a sample of all queries. -1 turns this feature off." msgstr "При 0 (нуль) фіксує зразок всіх запитів. -1 вимикає цю функцію." -#: utils/misc/guc_tables.c:2889 +#: utils/misc/guc_tables.c:3021 msgid "Sets the minimum execution time above which all statements will be logged." msgstr "Встановлює мінімальний час виконання, понад якого всі твердження будуть записуватись." -#: utils/misc/guc_tables.c:2891 +#: utils/misc/guc_tables.c:3023 msgid "Zero prints all queries. -1 turns this feature off." msgstr "При 0 (нуль) протоколюються всі запити. -1 вимикає цю функцію." -#: utils/misc/guc_tables.c:2901 +#: utils/misc/guc_tables.c:3033 msgid "Sets the minimum execution time above which autovacuum actions will be logged." msgstr "Встановлює мінімальний час виконання автоочистки, при перевищенні котрого ця дія фіксується в протоколі." -#: utils/misc/guc_tables.c:2903 +#: utils/misc/guc_tables.c:3035 msgid "Zero prints all actions. -1 turns autovacuum logging off." msgstr "При 0 (нуль) протоколюються всі дії автоочистки. -1 вимикає журналювання автоочистки." -#: utils/misc/guc_tables.c:2913 +#: utils/misc/guc_tables.c:3045 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements." msgstr "Встановлює максимальну довжину в байтах даних, що реєструються для значень параметрів під час журналювання операторів." -#: utils/misc/guc_tables.c:2915 utils/misc/guc_tables.c:2927 +#: utils/misc/guc_tables.c:3047 utils/misc/guc_tables.c:3059 msgid "-1 to print values in full." msgstr "-1 для друку значень в повному вигляді." -#: utils/misc/guc_tables.c:2925 +#: utils/misc/guc_tables.c:3057 msgid "Sets the maximum length in bytes of data logged for bind parameter values when logging statements, on error." msgstr "Встановлює максимальну довжину в байтах, даних, що реєструються для значень параметрів під час журналювання операторів, у разі помилки." -#: utils/misc/guc_tables.c:2937 +#: utils/misc/guc_tables.c:3069 msgid "Background writer sleep time between rounds." msgstr "Час призупинення в процесі фонового запису між підходами." -#: utils/misc/guc_tables.c:2948 +#: utils/misc/guc_tables.c:3080 msgid "Background writer maximum number of LRU pages to flush per round." msgstr "Максимальна кількість LRU-сторінок, які скидаються за один підхід, в процесі фонового запису." -#: utils/misc/guc_tables.c:2971 +#: utils/misc/guc_tables.c:3103 msgid "Number of simultaneous requests that can be handled efficiently by the disk subsystem." msgstr "Кількість одночасних запитів, які можуть бути ефективно оброблені дисковою підсистемою." -#: utils/misc/guc_tables.c:2985 -msgid "A variant of effective_io_concurrency that is used for maintenance work." -msgstr "Варіант effective_io_concurrency, що використовується для роботи з обслуговування." +#: utils/misc/guc_tables.c:3117 +msgid "A variant of \"effective_io_concurrency\" that is used for maintenance work." +msgstr "" -#: utils/misc/guc_tables.c:3011 +#: utils/misc/guc_tables.c:3132 +msgid "Limit on the size of data reads and writes." +msgstr "" + +#: utils/misc/guc_tables.c:3157 msgid "Maximum number of concurrent worker processes." msgstr "Максимальна кількість одночасно працюючих процесів." -#: utils/misc/guc_tables.c:3023 +#: utils/misc/guc_tables.c:3169 msgid "Maximum number of logical replication worker processes." msgstr "Максимальна кількість працюючих процесів логічної реплікації." -#: utils/misc/guc_tables.c:3035 +#: utils/misc/guc_tables.c:3181 msgid "Maximum number of table synchronization workers per subscription." msgstr "Максимальна кількість процесів синхронізації таблиць для однієї підписки." -#: utils/misc/guc_tables.c:3047 +#: utils/misc/guc_tables.c:3193 msgid "Maximum number of parallel apply workers per subscription." msgstr "Максимальна кількість паралельних процесів при підписці на одну підписку." -#: utils/misc/guc_tables.c:3057 +#: utils/misc/guc_tables.c:3203 msgid "Sets the amount of time to wait before forcing log file rotation." msgstr "Встановлює кількість часу для оновлення файлу журналу." -#: utils/misc/guc_tables.c:3069 +#: utils/misc/guc_tables.c:3215 msgid "Sets the maximum size a log file can reach before being rotated." msgstr "Встановлює максимальний розмір файлу журналу, якого він може досягнути, до ротації." -#: utils/misc/guc_tables.c:3081 +#: utils/misc/guc_tables.c:3227 msgid "Shows the maximum number of function arguments." msgstr "Показує максимальну кількість аргументів функції." -#: utils/misc/guc_tables.c:3092 +#: utils/misc/guc_tables.c:3238 msgid "Shows the maximum number of index keys." msgstr "Показує максимальну кількість ключів в індексі." -#: utils/misc/guc_tables.c:3103 +#: utils/misc/guc_tables.c:3249 msgid "Shows the maximum identifier length." msgstr "Показує максимальну довжину ідентифікатора." -#: utils/misc/guc_tables.c:3114 +#: utils/misc/guc_tables.c:3260 msgid "Shows the size of a disk block." msgstr "Показує розмір дискового блоку." -#: utils/misc/guc_tables.c:3125 +#: utils/misc/guc_tables.c:3271 msgid "Shows the number of pages per disk file." msgstr "Показує кількість сторінок в одному дисковому файлі." -#: utils/misc/guc_tables.c:3136 +#: utils/misc/guc_tables.c:3282 msgid "Shows the block size in the write ahead log." msgstr "Показує розмір блоку в журналі WAL." -#: utils/misc/guc_tables.c:3147 +#: utils/misc/guc_tables.c:3293 msgid "Sets the time to wait before retrying to retrieve WAL after a failed attempt." msgstr "Встановлює час очікування перед повторною спробою звертання до WAL після невдачі." -#: utils/misc/guc_tables.c:3159 +#: utils/misc/guc_tables.c:3305 msgid "Shows the size of write ahead log segments." msgstr "Показує розмір сегментів WAL." -#: utils/misc/guc_tables.c:3172 +#: utils/misc/guc_tables.c:3318 +msgid "Time for which WAL summary files should be kept." +msgstr "Час, протягом якого слід зберігати зведені файли WAL." + +#: utils/misc/guc_tables.c:3331 msgid "Time to sleep between autovacuum runs." msgstr "Час призупинення між запусками автоочистки." -#: utils/misc/guc_tables.c:3182 +#: utils/misc/guc_tables.c:3341 msgid "Minimum number of tuple updates or deletes prior to vacuum." msgstr "Мінімальна кількість оновлень або видалень кортежів перед очисткою." -#: utils/misc/guc_tables.c:3191 +#: utils/misc/guc_tables.c:3350 msgid "Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums." msgstr "Мінімальна кількість вставлених кортежів перед очищенням, або -1 щоб вимкнути очищення після вставки." -#: utils/misc/guc_tables.c:3200 +#: utils/misc/guc_tables.c:3359 msgid "Minimum number of tuple inserts, updates, or deletes prior to analyze." msgstr "Мінімальна кількість вставлень, оновлень або видалень кортежів перед аналізом." -#: utils/misc/guc_tables.c:3210 +#: utils/misc/guc_tables.c:3369 msgid "Age at which to autovacuum a table to prevent transaction ID wraparound." msgstr "Вік, при котрому необхідна автоочистка таблиці для запобігання зациклення ID транзакцій." -#: utils/misc/guc_tables.c:3222 +#: utils/misc/guc_tables.c:3381 msgid "Multixact age at which to autovacuum a table to prevent multixact wraparound." msgstr "Вік Multixact, при котрому необхідна автоочистка таблиці для запобігання зациклення multixact." -#: utils/misc/guc_tables.c:3232 +#: utils/misc/guc_tables.c:3391 msgid "Sets the maximum number of simultaneously running autovacuum worker processes." msgstr "Встановлює максимальну кількість одночасно працюючих робочих процесів автоочистки." -#: utils/misc/guc_tables.c:3242 +#: utils/misc/guc_tables.c:3401 msgid "Sets the maximum number of parallel processes per maintenance operation." msgstr "Встановлює максимальну кількість паралельних процесів на одну операцію обслуговування." -#: utils/misc/guc_tables.c:3252 +#: utils/misc/guc_tables.c:3411 msgid "Sets the maximum number of parallel processes per executor node." msgstr "Встановлює максимальну кількість паралельних процесів на вузол виконавця." -#: utils/misc/guc_tables.c:3263 +#: utils/misc/guc_tables.c:3422 msgid "Sets the maximum number of parallel workers that can be active at one time." msgstr "Встановлює максимальну кількість паралельних процесів, які можуть бути активні в один момент." -#: utils/misc/guc_tables.c:3274 +#: utils/misc/guc_tables.c:3433 msgid "Sets the maximum memory to be used by each autovacuum worker process." msgstr "Встановлює максимальний об'єм пам'яті для кожного робочого процесу автоочистки." -#: utils/misc/guc_tables.c:3285 -msgid "Time before a snapshot is too old to read pages changed after the snapshot was taken." -msgstr "Термін, після закінчення котрого знімок вважається занадто старим для отримання сторінок, змінених після створення знімку." - -#: utils/misc/guc_tables.c:3286 -msgid "A value of -1 disables this feature." -msgstr "Значення -1 вимикає цю функцію." - -#: utils/misc/guc_tables.c:3296 +#: utils/misc/guc_tables.c:3444 msgid "Time between issuing TCP keepalives." msgstr "Час між видачею TCP keepalives." -#: utils/misc/guc_tables.c:3297 utils/misc/guc_tables.c:3308 -#: utils/misc/guc_tables.c:3432 +#: utils/misc/guc_tables.c:3445 utils/misc/guc_tables.c:3456 +#: utils/misc/guc_tables.c:3580 msgid "A value of 0 uses the system default." msgstr "Значення 0 (нуль) використовує систему за замовчуванням." -#: utils/misc/guc_tables.c:3307 +#: utils/misc/guc_tables.c:3455 msgid "Time between TCP keepalive retransmits." msgstr "Час між повтореннями TCP keepalive." -#: utils/misc/guc_tables.c:3318 +#: utils/misc/guc_tables.c:3466 msgid "SSL renegotiation is no longer supported; this can only be 0." msgstr "Повторне узгодження SSL більше не підтримується; єдине допустиме значення - 0 (нуль)." -#: utils/misc/guc_tables.c:3329 +#: utils/misc/guc_tables.c:3477 msgid "Maximum number of TCP keepalive retransmits." msgstr "Максимальна кількість повторень TCP keepalive." -#: utils/misc/guc_tables.c:3330 +#: utils/misc/guc_tables.c:3478 msgid "Number of consecutive keepalive retransmits that can be lost before a connection is considered dead. A value of 0 uses the system default." msgstr "Кількість послідовних повторень keepalive може бути втрачена, перед тим як підключення буде вважатись \"мертвим\". Значення 0 (нуль) використовує систему за замовчуванням." -#: utils/misc/guc_tables.c:3341 +#: utils/misc/guc_tables.c:3489 msgid "Sets the maximum allowed result for exact search by GIN." msgstr "Встановлює максимально допустимий результат для точного пошуку з використанням GIN." -#: utils/misc/guc_tables.c:3352 +#: utils/misc/guc_tables.c:3500 msgid "Sets the planner's assumption about the total size of the data caches." msgstr "Встановлює планувальнику припустимий загальний розмір кешей даних." -#: utils/misc/guc_tables.c:3353 +#: utils/misc/guc_tables.c:3501 msgid "That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. This is measured in disk pages, which are normally 8 kB each." msgstr "Мається на увазі загальний розмір кешей (кеша ядра і спільних буферів), які використовуються для файлів даних PostgreSQL. Розмір задається в дискових сторінках, звичайно це 8 КБ." -#: utils/misc/guc_tables.c:3364 +#: utils/misc/guc_tables.c:3512 msgid "Sets the minimum amount of table data for a parallel scan." msgstr "Встановлює мінімальний обсяг даних в таблиці для паралельного сканування." -#: utils/misc/guc_tables.c:3365 +#: utils/misc/guc_tables.c:3513 msgid "If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered." msgstr "Якщо планувальник вважає, що він прочитає меньше сторінок таблиці, ніж задано цим обмеженням, паралельне сканування не буде розглядатись." -#: utils/misc/guc_tables.c:3375 +#: utils/misc/guc_tables.c:3523 msgid "Sets the minimum amount of index data for a parallel scan." msgstr "Встановлює мінімальний обсяг даних в індексі для паралельного сканування." -#: utils/misc/guc_tables.c:3376 +#: utils/misc/guc_tables.c:3524 msgid "If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered." msgstr "Якщо планувальник вважає, що він прочитає меньше сторінок індексу, ніж задано цим обмеженням, паралельне сканування не буде розглядатись." -#: utils/misc/guc_tables.c:3387 +#: utils/misc/guc_tables.c:3535 msgid "Shows the server version as an integer." msgstr "Показує версію сервера у вигляді цілого числа." -#: utils/misc/guc_tables.c:3398 +#: utils/misc/guc_tables.c:3546 msgid "Log the use of temporary files larger than this number of kilobytes." msgstr "Записує до журналу перевищення тимчасовими файлами заданого розміру в КБ." -#: utils/misc/guc_tables.c:3399 +#: utils/misc/guc_tables.c:3547 msgid "Zero logs all files. The default is -1 (turning this feature off)." msgstr "0 (нуль) фіксує всі файли. -1 вимикає цю функцію (за замовчуванням)." -#: utils/misc/guc_tables.c:3409 +#: utils/misc/guc_tables.c:3557 msgid "Sets the size reserved for pg_stat_activity.query, in bytes." msgstr "Встановлює розмір, зарезервований для pg_stat_activity.query, в байтах." -#: utils/misc/guc_tables.c:3420 +#: utils/misc/guc_tables.c:3568 msgid "Sets the maximum size of the pending list for GIN index." msgstr "Встановлює максимальний розмір списку-очікування для GIN-індексу." -#: utils/misc/guc_tables.c:3431 +#: utils/misc/guc_tables.c:3579 msgid "TCP user timeout." msgstr "Таймаут користувача TCP." -#: utils/misc/guc_tables.c:3442 +#: utils/misc/guc_tables.c:3590 msgid "The size of huge page that should be requested." msgstr "Розмір величезної сторінки, яку необхідно затребувати." -#: utils/misc/guc_tables.c:3453 +#: utils/misc/guc_tables.c:3601 msgid "Aggressively flush system caches for debugging purposes." msgstr "Агресивно скидати системні кеші для цілей налагодження." -#: utils/misc/guc_tables.c:3476 +#: utils/misc/guc_tables.c:3624 msgid "Sets the time interval between checks for disconnection while running queries." msgstr "Встановлює інтервал часу між перевірками відключення під час виконання запитів." -#: utils/misc/guc_tables.c:3487 +#: utils/misc/guc_tables.c:3635 msgid "Time between progress updates for long-running startup operations." msgstr "Час між оновленнями прогресу для довготриваючих операцій запуску." -#: utils/misc/guc_tables.c:3489 +#: utils/misc/guc_tables.c:3637 msgid "0 turns this feature off." msgstr "0 вимикає цю функцію." -#: utils/misc/guc_tables.c:3499 +#: utils/misc/guc_tables.c:3647 msgid "Sets the iteration count for SCRAM secret generation." msgstr "Встановлює кількість ітерацій для секретного генерування SCRAM." -#: utils/misc/guc_tables.c:3519 +#: utils/misc/guc_tables.c:3667 msgid "Sets the planner's estimate of the cost of a sequentially fetched disk page." msgstr "Встановлює для планувальника орієнтир вартості послідовного читання дискових сторінок." -#: utils/misc/guc_tables.c:3530 +#: utils/misc/guc_tables.c:3678 msgid "Sets the planner's estimate of the cost of a nonsequentially fetched disk page." msgstr "Встановлює для планувальника орієнтир вартості непослідовного читання дискових сторінок." -#: utils/misc/guc_tables.c:3541 +#: utils/misc/guc_tables.c:3689 msgid "Sets the planner's estimate of the cost of processing each tuple (row)." msgstr "Встановлює для планувальника орієнтир вартості обробки кожного кортежу (рядка)." -#: utils/misc/guc_tables.c:3552 +#: utils/misc/guc_tables.c:3700 msgid "Sets the planner's estimate of the cost of processing each index entry during an index scan." msgstr "Встановлює для планувальника орієнтир вартості обробки кожного елементу індекса під час сканування індексу." -#: utils/misc/guc_tables.c:3563 +#: utils/misc/guc_tables.c:3711 msgid "Sets the planner's estimate of the cost of processing each operator or function call." msgstr "Встановлює для планувальника орієнтир вартості обробки кожного оператора або виклику функції." -#: utils/misc/guc_tables.c:3574 +#: utils/misc/guc_tables.c:3722 msgid "Sets the planner's estimate of the cost of passing each tuple (row) from worker to leader backend." msgstr "Встановлює для планувальника приблизну вартість передавання кожного кортежу (рядка) від робочого процесу вихідному процесу." -#: utils/misc/guc_tables.c:3585 +#: utils/misc/guc_tables.c:3733 msgid "Sets the planner's estimate of the cost of starting up worker processes for parallel query." msgstr "Встановлює для планувальника орієнтир вартості запуску робочих процесів для паралельного запиту." -#: utils/misc/guc_tables.c:3597 +#: utils/misc/guc_tables.c:3745 msgid "Perform JIT compilation if query is more expensive." msgstr "Якщо запит дорожчий, виконується JIT-компіляція." -#: utils/misc/guc_tables.c:3598 +#: utils/misc/guc_tables.c:3746 msgid "-1 disables JIT compilation." msgstr "-1 вимикає JIT-компіляцію." -#: utils/misc/guc_tables.c:3608 +#: utils/misc/guc_tables.c:3756 msgid "Optimize JIT-compiled functions if query is more expensive." msgstr "Оптимізувати функції JIT-compiled, якщо запит дорожчий." -#: utils/misc/guc_tables.c:3609 +#: utils/misc/guc_tables.c:3757 msgid "-1 disables optimization." msgstr "-1 вимикає оптимізацію." -#: utils/misc/guc_tables.c:3619 +#: utils/misc/guc_tables.c:3767 msgid "Perform JIT inlining if query is more expensive." msgstr "Якщо запит дорожчий, виконується вбудовування JIT." -#: utils/misc/guc_tables.c:3620 +#: utils/misc/guc_tables.c:3768 msgid "-1 disables inlining." msgstr "-1 вимикає вбудовування." -#: utils/misc/guc_tables.c:3630 +#: utils/misc/guc_tables.c:3778 msgid "Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved." msgstr "Встановлює для планувальника орієнтир частки необхідних рядків курсора в загальній кількості." -#: utils/misc/guc_tables.c:3642 +#: utils/misc/guc_tables.c:3790 msgid "Sets the planner's estimate of the average size of a recursive query's working table." msgstr "Встановлює для планувальника орієнтир середнього розміру робочої таблиці рекурсивного запиту." -#: utils/misc/guc_tables.c:3654 +#: utils/misc/guc_tables.c:3802 msgid "GEQO: selective pressure within the population." msgstr "GEQO: вибірковий тиск в популяції." -#: utils/misc/guc_tables.c:3665 +#: utils/misc/guc_tables.c:3813 msgid "GEQO: seed for random path selection." msgstr "GEQO: відправна значення для випадкового вибору шляху." -#: utils/misc/guc_tables.c:3676 -msgid "Multiple of work_mem to use for hash tables." -msgstr "Декілька work_mem для використання геш-таблиць." +#: utils/misc/guc_tables.c:3824 +msgid "Multiple of \"work_mem\" to use for hash tables." +msgstr "" -#: utils/misc/guc_tables.c:3687 +#: utils/misc/guc_tables.c:3835 msgid "Multiple of the average buffer usage to free per round." msgstr "Множник для середньої кількості використаних буферів, який визначає кількість буферів, які звільняються за один підхід." -#: utils/misc/guc_tables.c:3697 +#: utils/misc/guc_tables.c:3845 msgid "Sets the seed for random-number generation." msgstr "Встановлює відправне значення для генератора випадкових чисел." -#: utils/misc/guc_tables.c:3708 +#: utils/misc/guc_tables.c:3856 msgid "Vacuum cost delay in milliseconds." msgstr "Затримка вартості очистки в мілісекундах." -#: utils/misc/guc_tables.c:3719 +#: utils/misc/guc_tables.c:3867 msgid "Vacuum cost delay in milliseconds, for autovacuum." msgstr "Затримка вартості очистки в мілісекундах, для автоочистки." -#: utils/misc/guc_tables.c:3730 +#: utils/misc/guc_tables.c:3878 msgid "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples." msgstr "Кількість оновлень або видалень кортежів до reltuples, яка визначає потребу в очистці." -#: utils/misc/guc_tables.c:3740 +#: utils/misc/guc_tables.c:3888 msgid "Number of tuple inserts prior to vacuum as a fraction of reltuples." msgstr "Кількість вставлень кортежів до reltuples, яка визначає потребу в очистці." -#: utils/misc/guc_tables.c:3750 +#: utils/misc/guc_tables.c:3898 msgid "Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples." msgstr "Кількість вставлень, оновлень або видалень кортежів до reltuples, яка визначає потребу в аналізі." -#: utils/misc/guc_tables.c:3760 +#: utils/misc/guc_tables.c:3908 msgid "Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval." msgstr "Час тривалості очищення \"брудних\" буферів під час контрольної точки до інтервалу контрольних точок." -#: utils/misc/guc_tables.c:3770 -msgid "Fraction of statements exceeding log_min_duration_sample to be logged." -msgstr "Частка тверджень, перевищує log_min_duration_sample, що підлягає запису." +#: utils/misc/guc_tables.c:3918 +msgid "Fraction of statements exceeding \"log_min_duration_sample\" to be logged." +msgstr "" -#: utils/misc/guc_tables.c:3771 +#: utils/misc/guc_tables.c:3919 msgid "Use a value between 0.0 (never log) and 1.0 (always log)." msgstr "Використайте значення між 0.0 (ніколи не записувати) і 1.0 (завжди записувати)." -#: utils/misc/guc_tables.c:3780 +#: utils/misc/guc_tables.c:3928 msgid "Sets the fraction of transactions from which to log all statements." msgstr "Встановлює частину транзакцій, від яких необхідно журналювати всі команди." -#: utils/misc/guc_tables.c:3781 +#: utils/misc/guc_tables.c:3929 msgid "Use a value between 0.0 (never log) and 1.0 (log all statements for all transactions)." msgstr "Використайте значення між 0.0 (ніколи не записувати) і 1.0 (записувати всі команди для всіх транзакцій)." -#: utils/misc/guc_tables.c:3800 +#: utils/misc/guc_tables.c:3948 msgid "Sets the shell command that will be called to archive a WAL file." msgstr "Встановлює команду оболонки, яка буде викликатись для архівації файлу WAL." -#: utils/misc/guc_tables.c:3801 +#: utils/misc/guc_tables.c:3949 msgid "This is used only if \"archive_library\" is not set." msgstr "Це використовується лише, якщо \"archive_library\" не встановлено." -#: utils/misc/guc_tables.c:3810 +#: utils/misc/guc_tables.c:3958 msgid "Sets the library that will be called to archive a WAL file." msgstr "Встановлює бібліотеку, яка буде викликана для архівування файлу WAL." -#: utils/misc/guc_tables.c:3811 +#: utils/misc/guc_tables.c:3959 msgid "An empty string indicates that \"archive_command\" should be used." msgstr "Порожній рядок вказує на те, що слід використовувати \"archive_command\"." -#: utils/misc/guc_tables.c:3820 +#: utils/misc/guc_tables.c:3968 msgid "Sets the shell command that will be called to retrieve an archived WAL file." msgstr "Встановлює команду оболонки, яка буде викликана для отримання архівованого файлу WAL." -#: utils/misc/guc_tables.c:3830 +#: utils/misc/guc_tables.c:3978 msgid "Sets the shell command that will be executed at every restart point." msgstr "Встановлює команду оболонки, яка буде виконуватися в кожній точці перезапуску." -#: utils/misc/guc_tables.c:3840 +#: utils/misc/guc_tables.c:3988 msgid "Sets the shell command that will be executed once at the end of recovery." msgstr "Встановлює команду оболонки, яка буде виконуватися один раз в кінці відновлення." -#: utils/misc/guc_tables.c:3850 +#: utils/misc/guc_tables.c:3998 msgid "Specifies the timeline to recover into." msgstr "Вказує лінію часу для відновлення." -#: utils/misc/guc_tables.c:3860 +#: utils/misc/guc_tables.c:4008 msgid "Set to \"immediate\" to end recovery as soon as a consistent state is reached." msgstr "Встановіть на \"негайно\" щоб закінчити відновлення як тільки буде досягнуто узгодженого стану." -#: utils/misc/guc_tables.c:3869 +#: utils/misc/guc_tables.c:4017 msgid "Sets the transaction ID up to which recovery will proceed." msgstr "Встановлює ідентифікатор транзакції, до якої буде продовжуватися відновлення." -#: utils/misc/guc_tables.c:3878 +#: utils/misc/guc_tables.c:4026 msgid "Sets the time stamp up to which recovery will proceed." msgstr "Встановлює позначку часу, до якої буде продовжуватися відновлення." -#: utils/misc/guc_tables.c:3887 +#: utils/misc/guc_tables.c:4035 msgid "Sets the named restore point up to which recovery will proceed." msgstr "Встановлює назву точки відновлення, до якої буде продовжуватися відновлення." -#: utils/misc/guc_tables.c:3896 +#: utils/misc/guc_tables.c:4044 msgid "Sets the LSN of the write-ahead log location up to which recovery will proceed." msgstr "Встановлює номер LSN розташування випереджувального журналювання, до якого буде продовжуватися відновлення." -#: utils/misc/guc_tables.c:3906 +#: utils/misc/guc_tables.c:4054 msgid "Sets the connection string to be used to connect to the sending server." msgstr "Встановлює рядок підключення який буде використовуватися для підключення до серверу надсилання." -#: utils/misc/guc_tables.c:3917 +#: utils/misc/guc_tables.c:4065 msgid "Sets the name of the replication slot to use on the sending server." msgstr "Встановлює назву слота реплікації, для використання на сервері надсилання." -#: utils/misc/guc_tables.c:3927 +#: utils/misc/guc_tables.c:4075 msgid "Sets the client's character set encoding." msgstr "Встановлює кодування символів, використовуване клієнтом." -#: utils/misc/guc_tables.c:3938 +#: utils/misc/guc_tables.c:4086 msgid "Controls information prefixed to each log line." msgstr "Визначає інформацію префікса кожного рядка протокола." -#: utils/misc/guc_tables.c:3939 +#: utils/misc/guc_tables.c:4087 msgid "If blank, no prefix is used." msgstr "При пустому значенні, префікс також відсутній." -#: utils/misc/guc_tables.c:3948 +#: utils/misc/guc_tables.c:4096 msgid "Sets the time zone to use in log messages." msgstr "Встановлює часовий пояс для виведення часу в повідомленях протокола." -#: utils/misc/guc_tables.c:3958 +#: utils/misc/guc_tables.c:4106 msgid "Sets the display format for date and time values." msgstr "Встановлює формат виведення значень часу і дат." -#: utils/misc/guc_tables.c:3959 +#: utils/misc/guc_tables.c:4107 msgid "Also controls interpretation of ambiguous date inputs." msgstr "Також визначає багатозначні задані дати, які вводяться." -#: utils/misc/guc_tables.c:3970 +#: utils/misc/guc_tables.c:4118 msgid "Sets the default table access method for new tables." msgstr "Встановлює метод доступу до таблиці за замовчуванням для нових таблиць." -#: utils/misc/guc_tables.c:3981 +#: utils/misc/guc_tables.c:4129 msgid "Sets the default tablespace to create tables and indexes in." msgstr "Встановлює табличний простір за замовчуванням, для створення таблиць і індексів." -#: utils/misc/guc_tables.c:3982 +#: utils/misc/guc_tables.c:4130 msgid "An empty string selects the database's default tablespace." msgstr "Пустий рядок вибирає табличний простір за замовчуванням бази даних." -#: utils/misc/guc_tables.c:3992 +#: utils/misc/guc_tables.c:4140 msgid "Sets the tablespace(s) to use for temporary tables and sort files." msgstr "Встановлює табличний простір(простори) для використання в тимчасових таблицях і файлах сортування." -#: utils/misc/guc_tables.c:4003 +#: utils/misc/guc_tables.c:4151 msgid "Sets whether a CREATEROLE user automatically grants the role to themselves, and with which options." msgstr "Задає, чи буде користувач CREATEROLE автоматично призначати собі цю роль і з якими параметрами." -#: utils/misc/guc_tables.c:4015 +#: utils/misc/guc_tables.c:4163 msgid "Sets the path for dynamically loadable modules." msgstr "Встановлює шлях для динамічно завантажуваних модулів." -#: utils/misc/guc_tables.c:4016 +#: utils/misc/guc_tables.c:4164 msgid "If a dynamically loadable module needs to be opened and the specified name does not have a directory component (i.e., the name does not contain a slash), the system will search this path for the specified file." msgstr "Якщо динамічно завантажений модуль потрібно відкрити і у вказаному імені немає компонента каталогу (наприклад, ім'я не містить символ \"/\"), система буде шукати цей шлях у вказаному файлі." -#: utils/misc/guc_tables.c:4029 +#: utils/misc/guc_tables.c:4177 msgid "Sets the location of the Kerberos server key file." msgstr "Встановлює розташування файлу з ключем Kerberos для даного сервера." -#: utils/misc/guc_tables.c:4040 +#: utils/misc/guc_tables.c:4188 msgid "Sets the Bonjour service name." msgstr "Встановлює ім'я служби Bonjour." -#: utils/misc/guc_tables.c:4050 +#: utils/misc/guc_tables.c:4198 msgid "Sets the language in which messages are displayed." msgstr "Встановлює мову виведених повідомлень." -#: utils/misc/guc_tables.c:4060 +#: utils/misc/guc_tables.c:4208 msgid "Sets the locale for formatting monetary amounts." msgstr "Встановлює локалізацію для форматування грошових сум." -#: utils/misc/guc_tables.c:4070 +#: utils/misc/guc_tables.c:4218 msgid "Sets the locale for formatting numbers." msgstr "Встановлює локалізацію для форматування чисел." -#: utils/misc/guc_tables.c:4080 +#: utils/misc/guc_tables.c:4228 msgid "Sets the locale for formatting date and time values." msgstr "Встановлює локалізацію для форматування значень дати і часу." -#: utils/misc/guc_tables.c:4090 +#: utils/misc/guc_tables.c:4238 msgid "Lists shared libraries to preload into each backend." msgstr "Список спільних бібліотек, попередньо завантажених до кожного внутрішнього серверу." -#: utils/misc/guc_tables.c:4101 +#: utils/misc/guc_tables.c:4249 msgid "Lists shared libraries to preload into server." msgstr "Список спільних бібліотек, попередньо завантажених до серверу." -#: utils/misc/guc_tables.c:4112 +#: utils/misc/guc_tables.c:4260 msgid "Lists unprivileged shared libraries to preload into each backend." msgstr "Список непривілейованих спільних бібліотек, попередньо завантажених до кожного внутрішнього серверу." -#: utils/misc/guc_tables.c:4123 +#: utils/misc/guc_tables.c:4271 msgid "Sets the schema search order for names that are not schema-qualified." msgstr "Встановлює порядок пошуку схеми для імен, які не є схемо-кваліфікованими." -#: utils/misc/guc_tables.c:4135 +#: utils/misc/guc_tables.c:4283 msgid "Shows the server (database) character set encoding." msgstr "Показує набір символів кодування сервера (бази даних)." -#: utils/misc/guc_tables.c:4147 +#: utils/misc/guc_tables.c:4295 msgid "Shows the server version." msgstr "Показує версію сервера." -#: utils/misc/guc_tables.c:4159 +#: utils/misc/guc_tables.c:4307 msgid "Sets the current role." msgstr "Встановлює чинну роль." -#: utils/misc/guc_tables.c:4171 +#: utils/misc/guc_tables.c:4319 msgid "Sets the session user name." msgstr "Встановлює ім'я користувача в сеансі." -#: utils/misc/guc_tables.c:4182 +#: utils/misc/guc_tables.c:4330 msgid "Sets the destination for server log output." msgstr "Встановлює, куди буде виводитися протокол серверу." -#: utils/misc/guc_tables.c:4183 +#: utils/misc/guc_tables.c:4331 msgid "Valid values are combinations of \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", and \"eventlog\", depending on the platform." msgstr "Дійсні значення - це комбінації \"stderr\", \"syslog\", \"csvlog\", \"jsonlog\", і \"eventlog\", в залежності від платформи." -#: utils/misc/guc_tables.c:4194 +#: utils/misc/guc_tables.c:4342 msgid "Sets the destination directory for log files." msgstr "Встановлює каталог призначення для файлів журналу." -#: utils/misc/guc_tables.c:4195 +#: utils/misc/guc_tables.c:4343 msgid "Can be specified as relative to the data directory or as absolute path." msgstr "Шлях може бути абсолютним або вказуватися відносно каталогу даних." -#: utils/misc/guc_tables.c:4205 +#: utils/misc/guc_tables.c:4353 msgid "Sets the file name pattern for log files." msgstr "Встановлює шаблон імені для файлів журналу." -#: utils/misc/guc_tables.c:4216 +#: utils/misc/guc_tables.c:4364 msgid "Sets the program name used to identify PostgreSQL messages in syslog." msgstr "Встановлює ім'я програми для ідентифікації повідомлень PostgreSQL в syslog." -#: utils/misc/guc_tables.c:4227 +#: utils/misc/guc_tables.c:4375 msgid "Sets the application name used to identify PostgreSQL messages in the event log." msgstr "Встановлює ім'я програми для ідентифікації повідомлень PostgreSQL в журналі подій." -#: utils/misc/guc_tables.c:4238 +#: utils/misc/guc_tables.c:4386 msgid "Sets the time zone for displaying and interpreting time stamps." msgstr "Встановлює часовий пояс для відображення та інтерпретації позначок часу." -#: utils/misc/guc_tables.c:4248 +#: utils/misc/guc_tables.c:4396 msgid "Selects a file of time zone abbreviations." msgstr "Вибирає файл з скороченими іменами часових поясів." -#: utils/misc/guc_tables.c:4258 +#: utils/misc/guc_tables.c:4406 msgid "Sets the owning group of the Unix-domain socket." msgstr "Встановлює відповідальну групу Unix-сокету." -#: utils/misc/guc_tables.c:4259 +#: utils/misc/guc_tables.c:4407 msgid "The owning user of the socket is always the user that starts the server." msgstr "Відповідальний користувач сокету це завжди той користувач який запустив сервер." -#: utils/misc/guc_tables.c:4269 +#: utils/misc/guc_tables.c:4417 msgid "Sets the directories where Unix-domain sockets will be created." msgstr "Встановлює каталоги, де будуть створюватись Unix-сокети." -#: utils/misc/guc_tables.c:4280 +#: utils/misc/guc_tables.c:4428 msgid "Sets the host name or IP address(es) to listen to." msgstr "Встановлює ім'я хосту або IP-адресу для прив'язки." -#: utils/misc/guc_tables.c:4295 +#: utils/misc/guc_tables.c:4443 msgid "Sets the server's data directory." msgstr "Встановлює каталог даних серверу." -#: utils/misc/guc_tables.c:4306 +#: utils/misc/guc_tables.c:4454 msgid "Sets the server's main configuration file." msgstr "Встановлює основний файл конфігурації серверу." -#: utils/misc/guc_tables.c:4317 +#: utils/misc/guc_tables.c:4465 msgid "Sets the server's \"hba\" configuration file." msgstr "Встановлює \"hba\" файл конфігурації серверу." -#: utils/misc/guc_tables.c:4328 +#: utils/misc/guc_tables.c:4476 msgid "Sets the server's \"ident\" configuration file." msgstr "Встановлює \"ident\" файл конфігурації серверу." -#: utils/misc/guc_tables.c:4339 +#: utils/misc/guc_tables.c:4487 msgid "Writes the postmaster PID to the specified file." msgstr "Записує ідентифікатор процесу (PID) postmaster у вказаний файл." -#: utils/misc/guc_tables.c:4350 +#: utils/misc/guc_tables.c:4498 msgid "Shows the name of the SSL library." msgstr "Показує назву бібліотеки SSL." -#: utils/misc/guc_tables.c:4365 +#: utils/misc/guc_tables.c:4513 msgid "Location of the SSL server certificate file." msgstr "Розташування файла сертифікату сервера для SSL." -#: utils/misc/guc_tables.c:4375 +#: utils/misc/guc_tables.c:4523 msgid "Location of the SSL server private key file." msgstr "Розташування файла з закритим ключем сервера для SSL." -#: utils/misc/guc_tables.c:4385 +#: utils/misc/guc_tables.c:4533 msgid "Location of the SSL certificate authority file." msgstr "Розташування файла центру сертифікації для SSL." -#: utils/misc/guc_tables.c:4395 +#: utils/misc/guc_tables.c:4543 msgid "Location of the SSL certificate revocation list file." msgstr "Розташування файла зі списком відкликаних сертфікатів для SSL." -#: utils/misc/guc_tables.c:4405 +#: utils/misc/guc_tables.c:4553 msgid "Location of the SSL certificate revocation list directory." msgstr "Розташування каталогу списку відкликаних сертифікатів SSL." -#: utils/misc/guc_tables.c:4415 +#: utils/misc/guc_tables.c:4563 msgid "Number of synchronous standbys and list of names of potential synchronous ones." msgstr "Кількість потенційно синхронних режимів очікування і список їх імен." -#: utils/misc/guc_tables.c:4426 +#: utils/misc/guc_tables.c:4574 msgid "Sets default text search configuration." msgstr "Встановлює конфігурацію текстового пошуку за замовчуванням." -#: utils/misc/guc_tables.c:4436 +#: utils/misc/guc_tables.c:4584 msgid "Sets the list of allowed SSL ciphers." msgstr "Встановлює список дозволених шифрів для SSL." -#: utils/misc/guc_tables.c:4451 +#: utils/misc/guc_tables.c:4599 msgid "Sets the curve to use for ECDH." msgstr "Встановлює криву для ECDH." -#: utils/misc/guc_tables.c:4466 +#: utils/misc/guc_tables.c:4614 msgid "Location of the SSL DH parameters file." msgstr "Розташування файла з параметрами SSL DH." -#: utils/misc/guc_tables.c:4477 +#: utils/misc/guc_tables.c:4625 msgid "Command to obtain passphrases for SSL." msgstr "Команда, що дозволяє отримати парольну фразу для SSL." -#: utils/misc/guc_tables.c:4488 +#: utils/misc/guc_tables.c:4636 msgid "Sets the application name to be reported in statistics and logs." msgstr "Встановлює ім'я програми, яке буде повідомлятись у статистиці і протоколах." -#: utils/misc/guc_tables.c:4499 +#: utils/misc/guc_tables.c:4647 msgid "Sets the name of the cluster, which is included in the process title." msgstr "Встановлює ім'я кластеру, яке буде включене до заголовка процесу." -#: utils/misc/guc_tables.c:4510 +#: utils/misc/guc_tables.c:4658 msgid "Sets the WAL resource managers for which WAL consistency checks are done." msgstr "Встановлює менеджерів ресурсу WAL, для яких виконано перевірки узгодженості WAL." -#: utils/misc/guc_tables.c:4511 +#: utils/misc/guc_tables.c:4659 msgid "Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay." msgstr "При цьому до журналу будуть записуватись зображення повнихс сторінок для всіх блоків даних для перевірки з результатами відтворення WAL." -#: utils/misc/guc_tables.c:4521 +#: utils/misc/guc_tables.c:4669 msgid "JIT provider to use." msgstr "Використовувати провайдер JIT." -#: utils/misc/guc_tables.c:4532 +#: utils/misc/guc_tables.c:4680 msgid "Log backtrace for errors in these functions." msgstr "Відстежувати записи помилок у ціх функціях." -#: utils/misc/guc_tables.c:4543 +#: utils/misc/guc_tables.c:4691 msgid "Use direct I/O for file access." msgstr "Використовувати прямий ввід для доступу до файлу." -#: utils/misc/guc_tables.c:4563 +#: utils/misc/guc_tables.c:4702 +msgid "Lists streaming replication standby server replication slot names that logical WAL sender processes will wait for." +msgstr "" + +#: utils/misc/guc_tables.c:4704 +msgid "Logical WAL sender processes will send decoded changes to output plugins only after the specified replication slots have confirmed receiving WAL." +msgstr "" + +#: utils/misc/guc_tables.c:4716 +msgid "Prohibits access to non-system relations of specified kinds." +msgstr "" + +#: utils/misc/guc_tables.c:4736 msgid "Sets whether \"\\'\" is allowed in string literals." msgstr "Встановлює, чи дозволене використання \"\\\" в текстових рядках." -#: utils/misc/guc_tables.c:4573 +#: utils/misc/guc_tables.c:4746 msgid "Sets the output format for bytea." msgstr "Встановлює формат виводу для типу bytea." -#: utils/misc/guc_tables.c:4583 +#: utils/misc/guc_tables.c:4756 msgid "Sets the message levels that are sent to the client." msgstr "Встановлює рівень повідомлень, переданих клієнту." -#: utils/misc/guc_tables.c:4584 utils/misc/guc_tables.c:4680 -#: utils/misc/guc_tables.c:4691 utils/misc/guc_tables.c:4763 +#: utils/misc/guc_tables.c:4757 utils/misc/guc_tables.c:4853 +#: utils/misc/guc_tables.c:4864 msgid "Each level includes all the levels that follow it. The later the level, the fewer messages are sent." msgstr "Кожен рівень включає всі наступні рівні. Чим вище рівень, тим менше повідомлень надіслано." -#: utils/misc/guc_tables.c:4594 +#: utils/misc/guc_tables.c:4767 msgid "Enables in-core computation of query identifiers." msgstr "Вмикає внутрішнє обчислення ідентифікаторів запиту." -#: utils/misc/guc_tables.c:4604 +#: utils/misc/guc_tables.c:4777 msgid "Enables the planner to use constraints to optimize queries." msgstr "Дає змогу планувальнику оптимізувати запити, використовуючи обмеження." -#: utils/misc/guc_tables.c:4605 +#: utils/misc/guc_tables.c:4778 msgid "Table scans will be skipped if their constraints guarantee that no rows match the query." msgstr "Сканування таблиці буде пропущено, якщо її обмеження гарантують, що запиту не відповідають ніякі рядки." -#: utils/misc/guc_tables.c:4616 +#: utils/misc/guc_tables.c:4789 msgid "Sets the default compression method for compressible values." msgstr "Встановлює метод стискання за замовчуванням для стисливих значень." -#: utils/misc/guc_tables.c:4627 +#: utils/misc/guc_tables.c:4800 msgid "Sets the transaction isolation level of each new transaction." msgstr "Встановлює рівень ізоляції транзакції для кожної нової транзакції." -#: utils/misc/guc_tables.c:4637 +#: utils/misc/guc_tables.c:4810 msgid "Sets the current transaction's isolation level." msgstr "Встановлює чинний рівень ізоляції транзакцій." -#: utils/misc/guc_tables.c:4648 +#: utils/misc/guc_tables.c:4821 msgid "Sets the display format for interval values." msgstr "Встановлює формат відображення внутрішніх значень." -#: utils/misc/guc_tables.c:4659 +#: utils/misc/guc_tables.c:4832 msgid "Log level for reporting invalid ICU locale strings." msgstr "Рівень протоколу для повідомлення про невірні рядки локалі ICU." -#: utils/misc/guc_tables.c:4669 +#: utils/misc/guc_tables.c:4842 msgid "Sets the verbosity of logged messages." msgstr "Встановлює детальність повідомлень, які протоколюються." -#: utils/misc/guc_tables.c:4679 +#: utils/misc/guc_tables.c:4852 msgid "Sets the message levels that are logged." msgstr "Встанолвює рівні повідомлень, які протоколюються." -#: utils/misc/guc_tables.c:4690 +#: utils/misc/guc_tables.c:4863 msgid "Causes all statements generating error at or above this level to be logged." msgstr "Вмикає протоколювання для всіх операторів, виконаних з помилкою цього або вище рівня." -#: utils/misc/guc_tables.c:4701 +#: utils/misc/guc_tables.c:4874 msgid "Sets the type of statements logged." msgstr "Встановлює тип операторів, які протоколюються." -#: utils/misc/guc_tables.c:4711 +#: utils/misc/guc_tables.c:4884 msgid "Sets the syslog \"facility\" to be used when syslog enabled." msgstr "Встановлює отримувача повідомлень, які відправляються до syslog." -#: utils/misc/guc_tables.c:4722 +#: utils/misc/guc_tables.c:4895 msgid "Sets the session's behavior for triggers and rewrite rules." msgstr "Встановлює поведінку для тригерів і правил перезапису для сеансу." -#: utils/misc/guc_tables.c:4732 +#: utils/misc/guc_tables.c:4905 msgid "Sets the current transaction's synchronization level." msgstr "Встановлює рівень синхронізації поточної транзакції." -#: utils/misc/guc_tables.c:4742 -msgid "Allows archiving of WAL files using archive_command." -msgstr "Дозволяє архівацію файлів WAL, використовуючи archive_command." +#: utils/misc/guc_tables.c:4915 +msgid "Allows archiving of WAL files using \"archive_command\"." +msgstr "" -#: utils/misc/guc_tables.c:4752 +#: utils/misc/guc_tables.c:4925 msgid "Sets the action to perform upon reaching the recovery target." msgstr "Встновлює дію яку потрібно виконати в разі досягнення мети відновлення." -#: utils/misc/guc_tables.c:4762 -msgid "Enables logging of recovery-related debugging information." -msgstr "Вмикає протоколювання налагодженної інформації, пов'язаної з відновленням." - -#: utils/misc/guc_tables.c:4779 +#: utils/misc/guc_tables.c:4935 msgid "Collects function-level statistics on database activity." msgstr "Збирає статистику активності в базі даних на рівні функцій." -#: utils/misc/guc_tables.c:4790 +#: utils/misc/guc_tables.c:4946 msgid "Sets the consistency of accesses to statistics data." msgstr "Встановлює послідовність доступу до даних статистики." -#: utils/misc/guc_tables.c:4800 +#: utils/misc/guc_tables.c:4956 msgid "Compresses full-page writes written in WAL file with specified method." msgstr "Стискає повносторінкові записи, записані у файлі WAL за допомогою вказаного методу." -#: utils/misc/guc_tables.c:4810 +#: utils/misc/guc_tables.c:4966 msgid "Sets the level of information written to the WAL." msgstr "Встановлює рівень інформації, яка записується до WAL." -#: utils/misc/guc_tables.c:4820 +#: utils/misc/guc_tables.c:4976 msgid "Selects the dynamic shared memory implementation used." msgstr "Вибирає використовуване впровадження динамічної спільної пам'яті." -#: utils/misc/guc_tables.c:4830 +#: utils/misc/guc_tables.c:4986 msgid "Selects the shared memory implementation used for the main shared memory region." msgstr "Вибирає впровадження спільної пам'яті, що використовується для основної області спільної пам'яті." -#: utils/misc/guc_tables.c:4840 +#: utils/misc/guc_tables.c:4996 msgid "Selects the method used for forcing WAL updates to disk." msgstr "Вибирає метод примусового запису оновлень в WAL на диск." -#: utils/misc/guc_tables.c:4850 +#: utils/misc/guc_tables.c:5006 msgid "Sets how binary values are to be encoded in XML." msgstr "Встановлює, як повинні кодуватись двійкові значення в XML." -#: utils/misc/guc_tables.c:4860 +#: utils/misc/guc_tables.c:5016 msgid "Sets whether XML data in implicit parsing and serialization operations is to be considered as documents or content fragments." msgstr "Встановлює, чи слід розглядати XML-дані в неявних операціях аналізу і серіалізації як документи або як фрагменти змісту." -#: utils/misc/guc_tables.c:4871 +#: utils/misc/guc_tables.c:5027 msgid "Use of huge pages on Linux or Windows." msgstr "Використовувати величезні сторінки в Linux або Windows." -#: utils/misc/guc_tables.c:4881 +#: utils/misc/guc_tables.c:5037 +msgid "Indicates the status of huge pages." +msgstr "Показує статус великих сторінок." + +#: utils/misc/guc_tables.c:5048 msgid "Prefetch referenced blocks during recovery." msgstr "Попередньо вибирати пов'язані блоки під час відновлення." -#: utils/misc/guc_tables.c:4882 +#: utils/misc/guc_tables.c:5049 msgid "Look ahead in the WAL to find references to uncached data." msgstr "Шукати в WAL посилання на незакешовані дані." -#: utils/misc/guc_tables.c:4891 +#: utils/misc/guc_tables.c:5058 msgid "Forces the planner's use parallel query nodes." msgstr "Змушує планувальник використовувати паралельні вузли запитів." -#: utils/misc/guc_tables.c:4892 +#: utils/misc/guc_tables.c:5059 msgid "This can be useful for testing the parallel query infrastructure by forcing the planner to generate plans that contain nodes that perform tuple communication between workers and the main process." msgstr "Це може бути корисно для тестування інфраструктури паралельних запитів, змушуючи планувальник генерувати плани, які містять вузли, що виконують зв'язок кортежів між робітниками та основним процесом." -#: utils/misc/guc_tables.c:4904 +#: utils/misc/guc_tables.c:5071 msgid "Chooses the algorithm for encrypting passwords." msgstr "Виберіть алгоритм для шифрування паролів." -#: utils/misc/guc_tables.c:4914 +#: utils/misc/guc_tables.c:5081 msgid "Controls the planner's selection of custom or generic plan." msgstr "Контролює вибір планувальником спеціального або загального плану." -#: utils/misc/guc_tables.c:4915 +#: utils/misc/guc_tables.c:5082 msgid "Prepared statements can have custom and generic plans, and the planner will attempt to choose which is better. This can be set to override the default behavior." msgstr "Підготовлені оператори можуть мати спеціальні або загальні плани, і планувальник спробує вибрати, який краще. Це може бути встановлено для зміни поведінки за замовчуванням." -#: utils/misc/guc_tables.c:4927 +#: utils/misc/guc_tables.c:5094 msgid "Sets the minimum SSL/TLS protocol version to use." msgstr "Встановлює мінімальну версію протоколу SSL/TLS для використання." -#: utils/misc/guc_tables.c:4939 +#: utils/misc/guc_tables.c:5106 msgid "Sets the maximum SSL/TLS protocol version to use." msgstr "Встановлює максимальну версію протоколу SSL/TLS для використання." -#: utils/misc/guc_tables.c:4951 +#: utils/misc/guc_tables.c:5118 msgid "Sets the method for synchronizing the data directory before crash recovery." msgstr "Встановлює метод для синхронізації каталогу даних перед аварійним відновленням." -#: utils/misc/guc_tables.c:4960 +#: utils/misc/guc_tables.c:5127 msgid "Forces immediate streaming or serialization of changes in large transactions." msgstr "Забезпечує негайну потокову передачу або серіалізацію змін у великих транзакціях." -#: utils/misc/guc_tables.c:4961 +#: utils/misc/guc_tables.c:5128 msgid "On the publisher, it allows streaming or serializing each change in logical decoding. On the subscriber, it allows serialization of all changes to files and notifies the parallel apply workers to read and apply them at the end of the transaction." msgstr "На стороні видавця це дозволяє передавати в потоковому режимі або серіалізувати кожну зміну в логічному декодуванні. На стороні абонента це дозволяє серіалізувати всі зміни у файлах і сповіщає працівників паралельних робочих процесів про необхідність прочитати і застосувати їх в кінці транзакції." @@ -29052,8 +30203,8 @@ msgstr "На стороні видавця це дозволяє передав msgid "internal error: unrecognized run-time parameter type\n" msgstr "внутрішня помилка: нерозпізнаний тип параметра часу виконання\n" -#: utils/misc/pg_controldata.c:51 utils/misc/pg_controldata.c:91 -#: utils/misc/pg_controldata.c:182 utils/misc/pg_controldata.c:223 +#: utils/misc/pg_controldata.c:50 utils/misc/pg_controldata.c:90 +#: utils/misc/pg_controldata.c:181 utils/misc/pg_controldata.c:222 #, c-format msgid "calculated CRC checksum does not match value stored in file" msgstr "обчислена контрольна сума CRC не відповідає значенню, збереженому у файлі" @@ -29073,145 +30224,143 @@ msgstr "запит буде обмежений політикою безпеки msgid "To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY." msgstr "Щоб вимкнути політику для власника таблиці, використайте ALTER TABLE NO FORCE ROW LEVEL SECURITY." -#: utils/misc/timeout.c:524 +#: utils/misc/timeout.c:520 #, c-format msgid "cannot add more timeout reasons" msgstr "додати більше причин тайм-ауту не можна" -#: utils/misc/tzparser.c:60 +#: utils/misc/tzparser.c:61 #, c-format msgid "time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d" msgstr "скорочення часового поясу \"%s\" занадто довге (максимум %d символів) у файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:72 +#: utils/misc/tzparser.c:73 #, c-format msgid "time zone offset %d is out of range in time zone file \"%s\", line %d" msgstr "зсув часового поясу %d поза діапазоном у файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:111 +#: utils/misc/tzparser.c:112 #, c-format msgid "missing time zone abbreviation in time zone file \"%s\", line %d" msgstr "пропущено скорочення часового поясу в файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:120 +#: utils/misc/tzparser.c:121 #, c-format msgid "missing time zone offset in time zone file \"%s\", line %d" msgstr "пропущено зсув часового поясу в файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:132 +#: utils/misc/tzparser.c:133 #, c-format msgid "invalid number for time zone offset in time zone file \"%s\", line %d" msgstr "неприпустиме число зсуву часового поясу в файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:168 +#: utils/misc/tzparser.c:169 #, c-format msgid "invalid syntax in time zone file \"%s\", line %d" msgstr "неприпустимий синтаксис у файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:236 +#: utils/misc/tzparser.c:237 #, c-format msgid "time zone abbreviation \"%s\" is multiply defined" msgstr "скорочення часового поясу \"%s\" визначено неодноразово" -#: utils/misc/tzparser.c:238 +#: utils/misc/tzparser.c:239 #, c-format msgid "Entry in time zone file \"%s\", line %d, conflicts with entry in file \"%s\", line %d." msgstr "Запис у файлі часового поясу \"%s\", рядок %d, конфліктує з записом у файлі \"%s\", рядок %d." -#: utils/misc/tzparser.c:300 +#: utils/misc/tzparser.c:301 #, c-format msgid "invalid time zone file name \"%s\"" msgstr "неприпустиме ім'я файла часового поясу \"%s\"" -#: utils/misc/tzparser.c:313 +#: utils/misc/tzparser.c:314 #, c-format msgid "time zone file recursion limit exceeded in file \"%s\"" msgstr "ліміт рекурсії файла часового поясу перевищено у файлі \"%s\"" -#: utils/misc/tzparser.c:352 utils/misc/tzparser.c:365 +#: utils/misc/tzparser.c:353 utils/misc/tzparser.c:366 #, c-format msgid "could not read time zone file \"%s\": %m" msgstr "не вдалося прочитати файл часового поясу \"%s\": %m" -#: utils/misc/tzparser.c:376 +#: utils/misc/tzparser.c:377 #, c-format msgid "line is too long in time zone file \"%s\", line %d" msgstr "занадто довгий рядок у файлі часового поясу \"%s\", рядок %d" -#: utils/misc/tzparser.c:400 +#: utils/misc/tzparser.c:401 #, c-format msgid "@INCLUDE without file name in time zone file \"%s\", line %d" msgstr "в @INCLUDE не вказано ім'я файла у файлі часового поясу \"%s\", рядок %d" -#: utils/mmgr/aset.c:446 utils/mmgr/generation.c:206 utils/mmgr/slab.c:367 +#: utils/mmgr/aset.c:452 utils/mmgr/bump.c:184 utils/mmgr/generation.c:216 +#: utils/mmgr/slab.c:371 #, c-format msgid "Failed while creating memory context \"%s\"." msgstr "Помилка під час створення контексту пам'яті \"%s\"." -#: utils/mmgr/dsa.c:532 utils/mmgr/dsa.c:1346 +#: utils/mmgr/dsa.c:523 utils/mmgr/dsa.c:1364 #, c-format msgid "could not attach to dynamic shared area" msgstr "не вдалося підключитись до динамічно-спільної області" -#: utils/mmgr/mcxt.c:1047 utils/mmgr/mcxt.c:1083 utils/mmgr/mcxt.c:1121 -#: utils/mmgr/mcxt.c:1159 utils/mmgr/mcxt.c:1247 utils/mmgr/mcxt.c:1278 -#: utils/mmgr/mcxt.c:1314 utils/mmgr/mcxt.c:1503 utils/mmgr/mcxt.c:1548 -#: utils/mmgr/mcxt.c:1605 +#: utils/mmgr/mcxt.c:1155 #, c-format msgid "Failed on request of size %zu in memory context \"%s\"." msgstr "Помилка в запиті розміру %zu в контексті пам'яті \"%s\"." -#: utils/mmgr/mcxt.c:1210 +#: utils/mmgr/mcxt.c:1299 #, c-format msgid "logging memory contexts of PID %d" msgstr "журналювання контекстів пам'яті PID %d" -#: utils/mmgr/portalmem.c:188 +#: utils/mmgr/portalmem.c:187 #, c-format msgid "cursor \"%s\" already exists" msgstr "курсор \"%s\" вже існує" -#: utils/mmgr/portalmem.c:192 +#: utils/mmgr/portalmem.c:191 #, c-format msgid "closing existing cursor \"%s\"" msgstr "існуючий курсор \"%s\" закривається" -#: utils/mmgr/portalmem.c:402 +#: utils/mmgr/portalmem.c:401 #, c-format msgid "portal \"%s\" cannot be run" msgstr "портал \"%s\" не можна запустити" -#: utils/mmgr/portalmem.c:480 +#: utils/mmgr/portalmem.c:479 #, c-format msgid "cannot drop pinned portal \"%s\"" msgstr "видалити закріплений портал \"%s\" не можна" -#: utils/mmgr/portalmem.c:488 +#: utils/mmgr/portalmem.c:487 #, c-format msgid "cannot drop active portal \"%s\"" msgstr "видалити активний портал \"%s\" не можна" -#: utils/mmgr/portalmem.c:739 +#: utils/mmgr/portalmem.c:738 #, c-format msgid "cannot PREPARE a transaction that has created a cursor WITH HOLD" msgstr "не можна виконати PREPARE для транзакції, яка створила курсор WITH HOLD" -#: utils/mmgr/portalmem.c:1230 +#: utils/mmgr/portalmem.c:1229 #, c-format msgid "cannot perform transaction commands inside a cursor loop that is not read-only" msgstr "виконати команди транзакції всередині циклу з курсором, який не є \"лише для читання\", не можна" #: utils/sort/logtape.c:266 utils/sort/logtape.c:287 #, c-format -msgid "could not seek to block %ld of temporary file" -msgstr "не вдалося знайти шлях до блокування %ld тимчасового файлу" +msgid "could not seek to block %lld of temporary file" +msgstr "не може намагатися заблокувати %lld тимчасового файлу" -#: utils/sort/sharedtuplestore.c:467 +#: utils/sort/sharedtuplestore.c:466 #, c-format msgid "unexpected chunk in shared tuplestore temporary file" msgstr "неочікуваний блок у тимчасовому файлі спільного сховища кортежів" -#: utils/sort/sharedtuplestore.c:549 +#: utils/sort/sharedtuplestore.c:548 #, c-format msgid "could not seek to block %u in shared tuplestore temporary file" msgstr "не вдалося знайти для блокування %u у тимчасовому файлі зі спільного сховища кортежів" @@ -29221,17 +30370,17 @@ msgstr "не вдалося знайти для блокування %u у ти msgid "cannot have more than %d runs for an external sort" msgstr "кількість виконуючих процесів для зовнішнього сортування не може перевищувати %d" -#: utils/sort/tuplesortvariants.c:1363 +#: utils/sort/tuplesortvariants.c:1552 #, c-format msgid "could not create unique index \"%s\"" msgstr "не вдалося створити унікальний індекс \"%s\"" -#: utils/sort/tuplesortvariants.c:1365 +#: utils/sort/tuplesortvariants.c:1554 #, c-format msgid "Key %s is duplicated." msgstr "Ключ %s дублюється." -#: utils/sort/tuplesortvariants.c:1366 +#: utils/sort/tuplesortvariants.c:1555 #, c-format msgid "Duplicate keys exist." msgstr "Дублікати ключів існують." @@ -29245,403 +30394,423 @@ msgstr "Дублікати ключів існують." msgid "could not seek in tuplestore temporary file" msgstr "не вдалося знайти у тимчасовому файлі зі сховища кортежів" -#: utils/time/snapmgr.c:571 +#: utils/time/snapmgr.c:536 #, c-format msgid "The source transaction is not running anymore." msgstr "Вихідна транзакція вже не виконується." -#: utils/time/snapmgr.c:1166 +#: utils/time/snapmgr.c:1136 #, c-format msgid "cannot export a snapshot from a subtransaction" msgstr "експортувати знімок з підтранзакції не можна" -#: utils/time/snapmgr.c:1325 utils/time/snapmgr.c:1330 -#: utils/time/snapmgr.c:1335 utils/time/snapmgr.c:1350 -#: utils/time/snapmgr.c:1355 utils/time/snapmgr.c:1360 -#: utils/time/snapmgr.c:1375 utils/time/snapmgr.c:1380 -#: utils/time/snapmgr.c:1385 utils/time/snapmgr.c:1487 -#: utils/time/snapmgr.c:1503 utils/time/snapmgr.c:1528 +#: utils/time/snapmgr.c:1296 utils/time/snapmgr.c:1301 +#: utils/time/snapmgr.c:1306 utils/time/snapmgr.c:1321 +#: utils/time/snapmgr.c:1326 utils/time/snapmgr.c:1331 +#: utils/time/snapmgr.c:1346 utils/time/snapmgr.c:1351 +#: utils/time/snapmgr.c:1356 utils/time/snapmgr.c:1470 +#: utils/time/snapmgr.c:1486 utils/time/snapmgr.c:1511 #, c-format msgid "invalid snapshot data in file \"%s\"" msgstr "неприпустимі дані знімку в файлі \"%s\"" -#: utils/time/snapmgr.c:1422 +#: utils/time/snapmgr.c:1393 #, c-format msgid "SET TRANSACTION SNAPSHOT must be called before any query" msgstr "SET TRANSACTION SNAPSHOT повинна викликатись перед будь-яким запитом" -#: utils/time/snapmgr.c:1431 +#: utils/time/snapmgr.c:1402 #, c-format msgid "a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ" msgstr "транзакція, яка імпортує знімок, повинна мати рівень ізоляції SERIALIZABLE або REPEATABLE READ" -#: utils/time/snapmgr.c:1440 utils/time/snapmgr.c:1449 +#: utils/time/snapmgr.c:1411 #, c-format msgid "invalid snapshot identifier: \"%s\"" msgstr "неприпустимий ідентифікатор знімка: \"%s\"" -#: utils/time/snapmgr.c:1541 +#: utils/time/snapmgr.c:1426 +#, c-format +msgid "snapshot \"%s\" does not exist" +msgstr "знімок \"%s\" не існує" + +#: utils/time/snapmgr.c:1524 #, c-format msgid "a serializable transaction cannot import a snapshot from a non-serializable transaction" msgstr "серіалізована транзакція не може імпортувати знімок з не серіалізованої транзакції" -#: utils/time/snapmgr.c:1545 +#: utils/time/snapmgr.c:1528 #, c-format msgid "a non-read-only serializable transaction cannot import a snapshot from a read-only transaction" msgstr "серіалізована транзакція в режимі \"читання-запис\" не може імпортувати знімок з транзакції в режимі \"тільки читання\"" -#: utils/time/snapmgr.c:1560 +#: utils/time/snapmgr.c:1543 #, c-format msgid "cannot import a snapshot from a different database" msgstr "імпортувати знімок з іншої бази даних не можна" -#: gram.y:1197 +#: gram.y:1231 #, c-format msgid "UNENCRYPTED PASSWORD is no longer supported" msgstr "UNENCRYPTED PASSWORD більше не підтримується" -#: gram.y:1198 +#: gram.y:1232 #, c-format msgid "Remove UNENCRYPTED to store the password in encrypted form instead." msgstr "Видаліть UNENCRYPTED, щоб зберегти пароль у зашифрованій формі." -#: gram.y:1525 gram.y:1541 +#: gram.y:1559 gram.y:1575 #, c-format msgid "CREATE SCHEMA IF NOT EXISTS cannot include schema elements" msgstr "CREATE SCHEMA IF NOT EXISTS не може включати елементи схеми" -#: gram.y:1693 +#: gram.y:1727 #, c-format msgid "current database cannot be changed" msgstr "поточна база даних не може бути змінена" -#: gram.y:1826 +#: gram.y:1860 #, c-format msgid "time zone interval must be HOUR or HOUR TO MINUTE" msgstr "інтервал, який задає часовий пояс, повинен бути HOUR або HOUR TO MINUTE" -#: gram.y:2443 +#: gram.y:2487 #, c-format msgid "column number must be in range from 1 to %d" msgstr "номер стовпця повинен бути в діапазоні від 1 до %d" -#: gram.y:3039 +#: gram.y:3083 #, c-format msgid "sequence option \"%s\" not supported here" msgstr "параметр послідовності \"%s\" тут не підтримується" -#: gram.y:3068 +#: gram.y:3122 #, c-format msgid "modulus for hash partition provided more than once" msgstr "модуль для геш-секції вказано неодноразово" -#: gram.y:3077 +#: gram.y:3131 #, c-format msgid "remainder for hash partition provided more than once" msgstr "решта для геш-секції вказана неодноразово" -#: gram.y:3084 +#: gram.y:3138 #, c-format msgid "unrecognized hash partition bound specification \"%s\"" msgstr "нерозпізнана специфікація границі геш-секції \"%s\"" -#: gram.y:3092 +#: gram.y:3146 #, c-format msgid "modulus for hash partition must be specified" msgstr "потрібно вказати модуль для геш-секції" -#: gram.y:3096 +#: gram.y:3150 #, c-format msgid "remainder for hash partition must be specified" msgstr "потрібно вказати решту для геш-секції" -#: gram.y:3304 gram.y:3338 +#: gram.y:3358 gram.y:3392 #, c-format msgid "STDIN/STDOUT not allowed with PROGRAM" msgstr "STDIN/STDOUT не допускається з PROGRAM" -#: gram.y:3310 +#: gram.y:3364 #, c-format msgid "WHERE clause not allowed with COPY TO" msgstr "Речення WHERE не дозволяється використовувати з COPY TO" -#: gram.y:3649 gram.y:3656 gram.y:12821 gram.y:12829 +#: gram.y:3712 gram.y:3719 gram.y:13023 gram.y:13031 #, c-format msgid "GLOBAL is deprecated in temporary table creation" msgstr "GLOBAL при створенні тимчасових таблиць застаріло" -#: gram.y:3932 +#: gram.y:3995 #, c-format msgid "for a generated column, GENERATED ALWAYS must be specified" msgstr "для згенерованого стовпця, потрібно вказати GENERATED ALWAYS" -#: gram.y:4315 +#: gram.y:4432 #, c-format msgid "a column list with %s is only supported for ON DELETE actions" msgstr "список стовпців з %s підтримується лише для дій ON DELETE" -#: gram.y:5027 +#: gram.y:5151 #, c-format msgid "CREATE EXTENSION ... FROM is no longer supported" msgstr "CREATE EXTENSION ... FROM більше не підтримується" -#: gram.y:5725 +#: gram.y:5849 #, c-format msgid "unrecognized row security option \"%s\"" msgstr "нерозпізнаний параметр безпеки рядка \"%s\"" -#: gram.y:5726 +#: gram.y:5850 #, c-format msgid "Only PERMISSIVE or RESTRICTIVE policies are supported currently." msgstr "Наразі підтримуються лише політики PERMISSIVE або RESTRICTIVE." -#: gram.y:5811 +#: gram.y:5935 #, c-format msgid "CREATE OR REPLACE CONSTRAINT TRIGGER is not supported" msgstr "CREATE OR REPLACE CONSTRAINT TRIGGER не підтримується" -#: gram.y:5848 +#: gram.y:5972 msgid "duplicate trigger events specified" msgstr "вказані події тригера повторюються" -#: gram.y:5997 +#: gram.y:6121 #, c-format msgid "conflicting constraint properties" msgstr "конфліктуючі властивості обмеження" -#: gram.y:6096 +#: gram.y:6220 #, c-format msgid "CREATE ASSERTION is not yet implemented" msgstr "CREATE ASSERTION ще не реалізований" -#: gram.y:6504 +#: gram.y:6537 +#, c-format +msgid "dropping an enum value is not implemented" +msgstr "відкидання значення переліку не реалізовано" + +#: gram.y:6655 #, c-format msgid "RECHECK is no longer required" msgstr "RECHECK більше не потребується" -#: gram.y:6505 +#: gram.y:6656 #, c-format msgid "Update your data type." msgstr "Поновіть ваш тип даних." -#: gram.y:8378 +#: gram.y:8529 #, c-format msgid "aggregates cannot have output arguments" msgstr "агрегатні функції не можуть мати вихідних аргументів" -#: gram.y:11054 gram.y:11073 +#: gram.y:11221 gram.y:11240 #, c-format msgid "WITH CHECK OPTION not supported on recursive views" msgstr "WITH CHECK OPTION не підтримується для рекурсивних подань" -#: gram.y:12960 +#: gram.y:13162 #, c-format msgid "LIMIT #,# syntax is not supported" msgstr "Синтаксис LIMIT #,# не підтримується" -#: gram.y:12961 +#: gram.y:13163 #, c-format msgid "Use separate LIMIT and OFFSET clauses." msgstr "Використайте окремі речення LIMIT і OFFSET." -#: gram.y:13821 +#: gram.y:14038 #, c-format msgid "only one DEFAULT value is allowed" msgstr "допускається лише одне значення DEFAULT" -#: gram.y:13830 +#: gram.y:14047 #, c-format msgid "only one PATH value per column is allowed" msgstr "для стовпця допускається лише одне значення PATH" -#: gram.y:13839 +#: gram.y:14056 #, c-format msgid "conflicting or redundant NULL / NOT NULL declarations for column \"%s\"" msgstr "конфліктуючі або надлишкові оголошення NULL / NOT NULL для стовпця \"%s\"" -#: gram.y:13848 +#: gram.y:14065 #, c-format msgid "unrecognized column option \"%s\"" msgstr "нерозпізнаний параметр стовпця \"%s\"" -#: gram.y:14102 +#: gram.y:14147 +#, c-format +msgid "only string constants are supported in JSON_TABLE path specification" +msgstr "" + +#: gram.y:14469 #, c-format msgid "precision for type float must be at least 1 bit" msgstr "точність для типу float повинна бути мінімум 1 біт" -#: gram.y:14111 +#: gram.y:14478 #, c-format msgid "precision for type float must be less than 54 bits" msgstr "точність для типу float повинна бути меньше 54 біт" -#: gram.y:14614 +#: gram.y:14995 #, c-format msgid "wrong number of parameters on left side of OVERLAPS expression" msgstr "неправильна кількість параметрів у лівій частині виразу OVERLAPS" -#: gram.y:14619 +#: gram.y:15000 #, c-format msgid "wrong number of parameters on right side of OVERLAPS expression" msgstr "неправильна кількість параметрів у правій частині виразу OVERLAPS" -#: gram.y:14796 +#: gram.y:15177 #, c-format msgid "UNIQUE predicate is not yet implemented" msgstr "Предикат UNIQUE ще не реалізований" -#: gram.y:15212 +#: gram.y:15591 #, c-format msgid "cannot use multiple ORDER BY clauses with WITHIN GROUP" msgstr "використовувати речення ORDER BY з WITHIN GROUP неодноразово, не можна" -#: gram.y:15217 +#: gram.y:15596 #, c-format msgid "cannot use DISTINCT with WITHIN GROUP" msgstr "використовувати DISTINCT з WITHIN GROUP не можна" -#: gram.y:15222 +#: gram.y:15601 #, c-format msgid "cannot use VARIADIC with WITHIN GROUP" msgstr "використовувати VARIADIC з WITHIN GROUP не можна" -#: gram.y:15856 gram.y:15880 +#: gram.y:16328 gram.y:16352 #, c-format msgid "frame start cannot be UNBOUNDED FOLLOWING" msgstr "початком рамки не може бути UNBOUNDED FOLLOWING" -#: gram.y:15861 +#: gram.y:16333 #, c-format msgid "frame starting from following row cannot end with current row" msgstr "рамка, яка починається з наступного рядка не можна закінчуватись поточним рядком" -#: gram.y:15885 +#: gram.y:16357 #, c-format msgid "frame end cannot be UNBOUNDED PRECEDING" msgstr "кінцем рамки не може бути UNBOUNDED PRECEDING" -#: gram.y:15891 +#: gram.y:16363 #, c-format msgid "frame starting from current row cannot have preceding rows" msgstr "рамка, яка починається з поточного рядка не може мати попередніх рядків" -#: gram.y:15898 +#: gram.y:16370 #, c-format msgid "frame starting from following row cannot have preceding rows" msgstr "рамка, яка починається з наступного рядка не може мати попередніх рядків" -#: gram.y:16659 +#: gram.y:16919 +#, c-format +msgid "unrecognized JSON encoding: %s" +msgstr "нерозпізнане кодування JSON: %s" + +#: gram.y:17243 #, c-format msgid "type modifier cannot have parameter name" msgstr "тип modifier не може мати ім'я параметра" -#: gram.y:16665 +#: gram.y:17249 #, c-format msgid "type modifier cannot have ORDER BY" msgstr "тип modifier не може мати ORDER BY" -#: gram.y:16733 gram.y:16740 gram.y:16747 +#: gram.y:17317 gram.y:17324 gram.y:17331 #, c-format msgid "%s cannot be used as a role name here" msgstr "%s не можна використовувати тут як ім'я ролі" -#: gram.y:16837 gram.y:18294 +#: gram.y:17421 gram.y:18906 #, c-format msgid "WITH TIES cannot be specified without ORDER BY clause" msgstr "WITH TIES не можна задати без оператора ORDER BY" -#: gram.y:17973 gram.y:18160 +#: gram.y:18597 gram.y:18772 msgid "improper use of \"*\"" msgstr "неправильне використання \"*\"" -#: gram.y:18224 +#: gram.y:18836 #, c-format msgid "an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type" msgstr "сортувальна агрегатна функція з прямим аргументом VARIADIC повинна мати один агрегатний аргумент VARIADIC того ж типу даних" -#: gram.y:18261 +#: gram.y:18873 #, c-format msgid "multiple ORDER BY clauses not allowed" msgstr "кілька речень ORDER BY не допускається" -#: gram.y:18272 +#: gram.y:18884 #, c-format msgid "multiple OFFSET clauses not allowed" msgstr "кілька речень OFFSET не допускається" -#: gram.y:18281 +#: gram.y:18893 #, c-format msgid "multiple LIMIT clauses not allowed" msgstr "кілька речень LIMIT не допускається" -#: gram.y:18290 +#: gram.y:18902 #, c-format msgid "multiple limit options not allowed" msgstr "використання декількох параметрів обмеження не дозволяється" -#: gram.y:18317 +#: gram.y:18929 #, c-format msgid "multiple WITH clauses not allowed" msgstr "кілька речень WITH не допускається" -#: gram.y:18510 +#: gram.y:19122 #, c-format msgid "OUT and INOUT arguments aren't allowed in TABLE functions" msgstr "В табличних функціях аргументи OUT і INOUT не дозволяються" -#: gram.y:18643 +#: gram.y:19255 #, c-format msgid "multiple COLLATE clauses not allowed" msgstr "кілька речень COLLATE не допускається" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18681 gram.y:18694 +#: gram.y:19293 gram.y:19306 #, c-format msgid "%s constraints cannot be marked DEFERRABLE" msgstr "обмеження %s не можуть бути позначені DEFERRABLE" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18707 +#: gram.y:19319 #, c-format msgid "%s constraints cannot be marked NOT VALID" msgstr "обмеження %s не можуть бути позначені NOT VALID" #. translator: %s is CHECK, UNIQUE, or similar -#: gram.y:18720 +#: gram.y:19332 #, c-format msgid "%s constraints cannot be marked NO INHERIT" msgstr "обмеження %s не можуть бути позначені NO INHERIT" -#: gram.y:18742 +#: gram.y:19354 #, c-format msgid "unrecognized partitioning strategy \"%s\"" msgstr "нерозпізнана стратегія секціонування \"%s\"" -#: gram.y:18766 +#: gram.y:19378 #, c-format msgid "invalid publication object list" msgstr "неприпустимий список об'єктів публікації" -#: gram.y:18767 +#: gram.y:19379 #, c-format msgid "One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name." msgstr "Одну з TABLE або TABLES IN SCHEMA необхідно вказати перед назвою автономної таблиці або схеми." -#: gram.y:18783 +#: gram.y:19395 #, c-format msgid "invalid table name" msgstr "неприпустиме ім'я таблиці" -#: gram.y:18804 +#: gram.y:19416 #, c-format msgid "WHERE clause not allowed for schema" msgstr "Речення WHERE не допускається для схеми" -#: gram.y:18811 +#: gram.y:19423 #, c-format msgid "column specification not allowed for schema" msgstr "специфікація стовпця не дозволена для схеми" -#: gram.y:18825 +#: gram.y:19437 #, c-format msgid "invalid schema name" msgstr "неприпустиме ім'я схеми" @@ -29686,12 +30855,17 @@ msgstr "синтаксична помилка у файлі \"%s\" рядок %u msgid "too many syntax errors found, abandoning file \"%s\"" msgstr "знайдено занадто багато синтаксичних помилок, переривання файла \"%s\"" -#: jsonpath_gram.y:529 +#: jsonpath_gram.y:267 +#, c-format +msgid ".decimal() can only have an optional precision[,scale]." +msgstr ".decimal() може мати лише необов'язковий параметр precision[,scale]." + +#: jsonpath_gram.y:599 #, c-format msgid "Unrecognized flag character \"%.*s\" in LIKE_REGEX predicate." msgstr "Нерозпізнаний символ позначки \"%.*s\" в предикаті LIKE_REGEX." -#: jsonpath_gram.y:607 +#: jsonpath_gram.y:677 #, c-format msgid "XQuery \"x\" flag (expanded regular expressions) is not implemented" msgstr "XQuery \"x\" позначка (розширені регулярні вирази) не реалізовано" @@ -29708,7 +30882,7 @@ msgstr "неприпустима шістнадцяткова послідовн msgid "unexpected end after backslash" msgstr "неочікуваний кінець після зворотного слеша" -#: jsonpath_scan.l:201 repl_scanner.l:209 scan.l:741 +#: jsonpath_scan.l:201 repl_scanner.l:211 scan.l:756 msgid "unterminated quoted string" msgstr "незавершений рядок в лапках" @@ -29720,8 +30894,8 @@ msgstr "неочікуваний кінець коментаря" msgid "invalid numeric literal" msgstr "невірна числова константа" -#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1049 -#: scan.l:1053 scan.l:1057 scan.l:1061 scan.l:1065 scan.l:1069 scan.l:1073 +#: jsonpath_scan.l:325 jsonpath_scan.l:331 jsonpath_scan.l:337 scan.l:1064 +#: scan.l:1068 scan.l:1072 scan.l:1076 msgid "trailing junk after numeric literal" msgstr "сміття після числового літерала" @@ -29737,139 +30911,140 @@ msgstr "%s в кінці введення jsonpath" msgid "%s at or near \"%s\" of jsonpath input" msgstr "%s в або біля \"%s\" введення jsonpath" -#: jsonpath_scan.l:557 +#: jsonpath_scan.l:568 msgid "invalid input" msgstr "неправильні вхідні дані" -#: jsonpath_scan.l:583 +#: jsonpath_scan.l:594 msgid "invalid hexadecimal digit" msgstr "неприпустима шістнадцяткова цифра" -#: jsonpath_scan.l:614 +#: jsonpath_scan.l:625 #, c-format msgid "could not convert Unicode to server encoding" msgstr "не вдалося перетворити Юнікод в серверне кодування" -#: repl_gram.y:301 repl_gram.y:333 +#: repl_gram.y:318 repl_gram.y:359 #, c-format msgid "invalid timeline %u" msgstr "неприпустима часова шкала %u" -#: repl_scanner.l:152 +#: repl_scanner.l:154 msgid "invalid streaming start location" msgstr "неприпустиме розташування початку потокового передавання" -#: scan.l:482 +#: scan.l:497 msgid "unterminated /* comment" msgstr "незавершений коментар /*" -#: scan.l:502 +#: scan.l:517 msgid "unterminated bit string literal" msgstr "незавершений бітовий рядок" -#: scan.l:516 +#: scan.l:531 msgid "unterminated hexadecimal string literal" msgstr "незавершений шістнадцятковий рядок" -#: scan.l:566 +#: scan.l:581 #, c-format msgid "unsafe use of string constant with Unicode escapes" msgstr "небезпечне використання рядкової констани зі спеціальними кодами Unicode" -#: scan.l:567 +#: scan.l:582 #, c-format -msgid "String constants with Unicode escapes cannot be used when standard_conforming_strings is off." -msgstr "Константи рядка зі спеціальними кодами Unicode не можна використовувати, коли параметр standard_conforming_strings вимкнений." +msgid "String constants with Unicode escapes cannot be used when \"standard_conforming_strings\" is off." +msgstr "" -#: scan.l:628 +#: scan.l:643 msgid "unhandled previous state in xqs" msgstr "необроблений попередній стан у xqs" -#: scan.l:702 +#: scan.l:717 #, c-format msgid "Unicode escapes must be \\uXXXX or \\UXXXXXXXX." msgstr "Спеціальні коди Unicode повинні бути \\uXXXX або \\UXXXXXXXX." -#: scan.l:713 +#: scan.l:728 #, c-format msgid "unsafe use of \\' in a string literal" msgstr "небезпечне використання символу \\' в рядку" -#: scan.l:714 +#: scan.l:729 #, c-format msgid "Use '' to write quotes in strings. \\' is insecure in client-only encodings." msgstr "Використайте \" щоб записати лапки в рядку. Запис \\' небезпечний лише для клієнтських кодувань." -#: scan.l:786 +#: scan.l:801 msgid "unterminated dollar-quoted string" msgstr "незавершений рядок з $" -#: scan.l:803 scan.l:813 +#: scan.l:818 scan.l:828 msgid "zero-length delimited identifier" msgstr "пустий ідентифікатор із роздільниками" -#: scan.l:824 syncrep_scanner.l:101 +#: scan.l:839 syncrep_scanner.l:101 msgid "unterminated quoted identifier" msgstr "незавершений ідентифікатор в лапках" -#: scan.l:987 +#: scan.l:1002 msgid "operator too long" msgstr "занадто довгий оператор" -#: scan.l:1000 +#: scan.l:1015 msgid "trailing junk after parameter" msgstr "сміття після параметру" -#: scan.l:1021 +#: scan.l:1036 msgid "invalid hexadecimal integer" msgstr "неприпустиме шістнадцяткове число" -#: scan.l:1025 +#: scan.l:1040 msgid "invalid octal integer" msgstr "помилкове вісімкове число" -#: scan.l:1029 +#: scan.l:1044 msgid "invalid binary integer" msgstr "неприпустиме двійкове ціле число" #. translator: %s is typically the translation of "syntax error" -#: scan.l:1236 +#: scan.l:1239 #, c-format msgid "%s at end of input" msgstr "%s в кінці введення" #. translator: first %s is typically the translation of "syntax error" -#: scan.l:1244 +#: scan.l:1247 #, c-format msgid "%s at or near \"%s\"" msgstr "%s в або поблизу \"%s\"" -#: scan.l:1434 +#: scan.l:1439 #, c-format msgid "nonstandard use of \\' in a string literal" msgstr "нестандартне використання \\' в рядку" -#: scan.l:1435 +#: scan.l:1440 #, c-format msgid "Use '' to write quotes in strings, or use the escape string syntax (E'...')." msgstr "Щоб записати лапки у рядку використовуйте \" або синтаксис спеціальних рядків (E'...')." -#: scan.l:1444 +#: scan.l:1449 #, c-format msgid "nonstandard use of \\\\ in a string literal" msgstr "нестандартне використання \\\\ в рядку" -#: scan.l:1445 +#: scan.l:1450 #, c-format msgid "Use the escape string syntax for backslashes, e.g., E'\\\\'." msgstr "Для запису зворотніх скісних рисок \"\\\" використовуйте синтаксис спеціальних рядків, наприклад E'\\\\'." -#: scan.l:1459 +#: scan.l:1464 #, c-format msgid "nonstandard use of escape in a string literal" msgstr "нестандартне використання спеціального символу в рядку" -#: scan.l:1460 +#: scan.l:1465 #, c-format msgid "Use the escape string syntax for escapes, e.g., E'\\r\\n'." msgstr "Для запису спеціальних символів використовуйте синтаксис спеціальних рядків E'\\r\\n'." + diff --git a/src/backend/port/atomics.c b/src/backend/port/atomics.c index 93789b4e0584b..1a96c6f5799a1 100644 --- a/src/backend/port/atomics.c +++ b/src/backend/port/atomics.c @@ -3,7 +3,7 @@ * atomics.c * Non-Inline parts of the atomics implementation * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -17,164 +17,6 @@ #include "port/atomics.h" #include "storage/spin.h" -#ifdef PG_HAVE_MEMORY_BARRIER_EMULATION -#ifdef WIN32 -#error "barriers are required (and provided) on WIN32 platforms" -#endif -#include -#endif - -#ifdef PG_HAVE_MEMORY_BARRIER_EMULATION -void -pg_spinlock_barrier(void) -{ - /* - * NB: we have to be reentrant here, some barriers are placed in signal - * handlers. - * - * We use kill(0) for the fallback barrier as we assume that kernels on - * systems old enough to require fallback barrier support will include an - * appropriate barrier while checking the existence of the postmaster pid. - */ - (void) kill(PostmasterPid, 0); -} -#endif - -#ifdef PG_HAVE_COMPILER_BARRIER_EMULATION -void -pg_extern_compiler_barrier(void) -{ - /* do nothing */ -} -#endif - - -#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION - -void -pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr) -{ - StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t), - "size mismatch of atomic_flag vs slock_t"); - -#ifndef HAVE_SPINLOCKS - - /* - * NB: If we're using semaphore based TAS emulation, be careful to use a - * separate set of semaphores. Otherwise we'd get in trouble if an atomic - * var would be manipulated while spinlock is held. - */ - s_init_lock_sema((slock_t *) &ptr->sema, true); -#else - SpinLockInit((slock_t *) &ptr->sema); -#endif - - ptr->value = false; -} - -bool -pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr) -{ - uint32 oldval; - - SpinLockAcquire((slock_t *) &ptr->sema); - oldval = ptr->value; - ptr->value = true; - SpinLockRelease((slock_t *) &ptr->sema); - - return oldval == 0; -} - -void -pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr) -{ - SpinLockAcquire((slock_t *) &ptr->sema); - ptr->value = false; - SpinLockRelease((slock_t *) &ptr->sema); -} - -bool -pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr) -{ - return ptr->value == 0; -} - -#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */ - -#ifdef PG_HAVE_ATOMIC_U32_SIMULATION -void -pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_) -{ - StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t), - "size mismatch of atomic_uint32 vs slock_t"); - - /* - * If we're using semaphore based atomic flags, be careful about nested - * usage of atomics while a spinlock is held. - */ -#ifndef HAVE_SPINLOCKS - s_init_lock_sema((slock_t *) &ptr->sema, true); -#else - SpinLockInit((slock_t *) &ptr->sema); -#endif - ptr->value = val_; -} - -void -pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val) -{ - /* - * One might think that an unlocked write doesn't need to acquire the - * spinlock, but one would be wrong. Even an unlocked write has to cause a - * concurrent pg_atomic_compare_exchange_u32() (et al) to fail. - */ - SpinLockAcquire((slock_t *) &ptr->sema); - ptr->value = val; - SpinLockRelease((slock_t *) &ptr->sema); -} - -bool -pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, - uint32 *expected, uint32 newval) -{ - bool ret; - - /* - * Do atomic op under a spinlock. It might look like we could just skip - * the cmpxchg if the lock isn't available, but that'd just emulate a - * 'weak' compare and swap. I.e. one that allows spurious failures. Since - * several algorithms rely on a strong variant and that is efficiently - * implementable on most major architectures let's emulate it here as - * well. - */ - SpinLockAcquire((slock_t *) &ptr->sema); - - /* perform compare/exchange logic */ - ret = ptr->value == *expected; - *expected = ptr->value; - if (ret) - ptr->value = newval; - - /* and release lock */ - SpinLockRelease((slock_t *) &ptr->sema); - - return ret; -} - -uint32 -pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_) -{ - uint32 oldval; - - SpinLockAcquire((slock_t *) &ptr->sema); - oldval = ptr->value; - ptr->value += add_; - SpinLockRelease((slock_t *) &ptr->sema); - return oldval; -} - -#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */ - #ifdef PG_HAVE_ATOMIC_U64_SIMULATION @@ -184,15 +26,7 @@ pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_) StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t), "size mismatch of atomic_uint64 vs slock_t"); - /* - * If we're using semaphore based atomic flags, be careful about nested - * usage of atomics while a spinlock is held. - */ -#ifndef HAVE_SPINLOCKS - s_init_lock_sema((slock_t *) &ptr->sema, true); -#else SpinLockInit((slock_t *) &ptr->sema); -#endif ptr->value = val_; } diff --git a/src/backend/port/meson.build b/src/backend/port/meson.build index 7820e86016dd4..09d54e01d1338 100644 --- a/src/backend/port/meson.build +++ b/src/backend/port/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'atomics.c', diff --git a/src/backend/port/posix_sema.c b/src/backend/port/posix_sema.c index 5886d2233f5bd..269c7460817ec 100644 --- a/src/backend/port/posix_sema.c +++ b/src/backend/port/posix_sema.c @@ -15,7 +15,7 @@ * forked backends, but they could not be accessed by exec'd backends. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -217,8 +217,7 @@ PGReserveSemaphores(int maxSemas) /* * We must use ShmemAllocUnlocked(), since the spinlock protecting - * ShmemAlloc() won't be ready yet. (This ordering is necessary when we - * are emulating spinlocks with semaphores.) + * ShmemAlloc() won't be ready yet. */ sharedSemas = (PGSemaphore) ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas)); diff --git a/src/backend/port/sysv_sema.c b/src/backend/port/sysv_sema.c index 1454f96b5f320..423b2b4f9d6d1 100644 --- a/src/backend/port/sysv_sema.c +++ b/src/backend/port/sysv_sema.c @@ -4,7 +4,7 @@ * Implement PGSemaphores using SysV semaphore facilities * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -325,8 +325,7 @@ PGReserveSemaphores(int maxSemas) /* * We must use ShmemAllocUnlocked(), since the spinlock protecting - * ShmemAlloc() won't be ready yet. (This ordering is necessary when we - * are emulating spinlocks with semaphores.) + * ShmemAlloc() won't be ready yet. */ sharedSemas = (PGSemaphore) ShmemAllocUnlocked(PGSemaphoreShmemSize(maxSemas)); diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index 362a37d3b3a21..197926d44f6bc 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -9,7 +9,7 @@ * exist, though, because mmap'd shmem provides no way to find out how * many processes are attached, which we need for interlocking purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -286,7 +286,7 @@ static void IpcMemoryDetach(int status, Datum shmaddr) { /* Detach System V shared memory block. */ - if (shmdt((void *) DatumGetPointer(shmaddr)) < 0) + if (shmdt(DatumGetPointer(shmaddr)) < 0) elog(LOG, "shmdt(%p) failed: %m", DatumGetPointer(shmaddr)); } @@ -320,7 +320,7 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2) IpcMemoryState state; state = PGSharedMemoryAttach((IpcMemoryId) id2, NULL, &memAddress); - if (memAddress && shmdt((void *) memAddress) < 0) + if (memAddress && shmdt(memAddress) < 0) elog(LOG, "shmdt(%p) failed: %m", memAddress); switch (state) { @@ -835,7 +835,7 @@ PGSharedMemoryCreate(Size size, break; } - if (oldhdr && shmdt((void *) oldhdr) < 0) + if (oldhdr && shmdt(oldhdr) < 0) elog(LOG, "shmdt(%p) failed: %m", oldhdr); } diff --git a/src/backend/port/tas/sunstudio_sparc.s b/src/backend/port/tas/sunstudio_sparc.s index 3400713afd556..8e0a0965b64ea 100644 --- a/src/backend/port/tas/sunstudio_sparc.s +++ b/src/backend/port/tas/sunstudio_sparc.s @@ -3,7 +3,7 @@ ! sunstudio_sparc.s ! compare and swap for Sun Studio on Sparc ! -! Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +! Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group ! Portions Copyright (c) 1994, Regents of the University of California ! ! IDENTIFICATION diff --git a/src/backend/port/tas/sunstudio_x86.s b/src/backend/port/tas/sunstudio_x86.s index b4608a9ceb267..0111ffde45c29 100644 --- a/src/backend/port/tas/sunstudio_x86.s +++ b/src/backend/port/tas/sunstudio_x86.s @@ -3,7 +3,7 @@ / sunstudio_x86.s / compare and swap for Sun Studio on x86 / -/ Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +/ Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group / Portions Copyright (c) 1994, Regents of the University of California / / IDENTIFICATION diff --git a/src/backend/port/win32/crashdump.c b/src/backend/port/win32/crashdump.c index f2af65676850f..5a8048be025a3 100644 --- a/src/backend/port/win32/crashdump.c +++ b/src/backend/port/win32/crashdump.c @@ -28,7 +28,7 @@ * be added, though at the cost of a greater chance of the crash dump failing. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32/crashdump.c diff --git a/src/backend/port/win32/meson.build b/src/backend/port/win32/meson.build index bca70f08e9fb3..af80071387932 100644 --- a/src/backend/port/win32/meson.build +++ b/src/backend/port/win32/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'crashdump.c', diff --git a/src/backend/port/win32/signal.c b/src/backend/port/win32/signal.c index 285cb611b4f09..d051b15c0ddb3 100644 --- a/src/backend/port/win32/signal.c +++ b/src/backend/port/win32/signal.c @@ -3,7 +3,7 @@ * signal.c * Microsoft Windows Win32 Signal Emulation Functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32/signal.c diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c index 0a819e07ae132..a8538afe68446 100644 --- a/src/backend/port/win32/socket.c +++ b/src/backend/port/win32/socket.c @@ -3,7 +3,7 @@ * socket.c * Microsoft Windows Win32 Socket Functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32/socket.c diff --git a/src/backend/port/win32/timer.c b/src/backend/port/win32/timer.c index b601603a2121c..4843e8bd498c6 100644 --- a/src/backend/port/win32/timer.c +++ b/src/backend/port/win32/timer.c @@ -8,7 +8,7 @@ * - Does not support interval timer (value->it_interval) * - Only supports ITIMER_REAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32/timer.c diff --git a/src/backend/port/win32_sema.c b/src/backend/port/win32_sema.c index f2b54bdfda08b..5854ad1f54d3d 100644 --- a/src/backend/port/win32_sema.c +++ b/src/backend/port/win32_sema.c @@ -3,7 +3,7 @@ * win32_sema.c * Microsoft Windows Win32 Semaphores Emulation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32_sema.c diff --git a/src/backend/port/win32_shmem.c b/src/backend/port/win32_shmem.c index 3bcce9d3b6329..4dee856d6bd69 100644 --- a/src/backend/port/win32_shmem.c +++ b/src/backend/port/win32_shmem.c @@ -3,7 +3,7 @@ * win32_shmem.c * Implement shared memory using win32 facilities * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/port/win32_shmem.c diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index db08543d19589..0f4435d2d97c7 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -22,6 +22,7 @@ OBJS = \ interrupt.o \ launch_backend.o \ pgarch.o \ + pmchild.o \ postmaster.o \ startup.o \ syslogger.o \ diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 4e4a0ccbefbed..451fb90a610a7 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -51,7 +51,7 @@ * holding the relation lock) during which a worker may choose a table that was * already vacuumed; this is a bug in the current design. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -88,6 +88,7 @@ #include "postmaster/autovacuum.h" #include "postmaster/interrupt.h" #include "postmaster/postmaster.h" +#include "storage/aio_subsys.h" #include "storage/bufmgr.h" #include "storage/ipc.h" #include "storage/latch.h" @@ -115,10 +116,12 @@ * GUC parameters */ bool autovacuum_start_daemon = false; +int autovacuum_worker_slots; int autovacuum_max_workers; int autovacuum_work_mem = -1; int autovacuum_naptime; int autovacuum_vac_thresh; +int autovacuum_vac_max_thresh; double autovacuum_vac_scale; int autovacuum_vac_ins_thresh; double autovacuum_vac_ins_scale; @@ -210,7 +213,7 @@ typedef struct autovac_table /*------------- * This struct holds information about a single worker's whereabouts. We keep * an array of these in shared memory, sized according to - * autovacuum_max_workers. + * autovacuum_worker_slots. * * wi_links entry into free list or running list * wi_dboid OID of the database this worker is supposed to work on @@ -247,9 +250,10 @@ typedef enum { AutoVacForkFailed, /* failed trying to start a worker */ AutoVacRebalance, /* rebalance the cost limits */ - AutoVacNumSignals, /* must be last */ } AutoVacuumSignal; +#define AutoVacNumSignals (AutoVacRebalance + 1) + /* * Autovacuum workitem array, stored in AutoVacuumShmem->av_workItems. This * list is mostly protected by AutovacuumLock, except that if an item is @@ -290,7 +294,7 @@ typedef struct { sig_atomic_t av_signal[AutoVacNumSignals]; pid_t av_launcherpid; - dlist_head av_freeWorkers; + dclist_head av_freeWorkers; dlist_head av_runningWorkers; WorkerInfo av_startingWorker; AutoVacuumWorkItem av_workItems[NUM_WORKITEMS]; @@ -313,8 +317,8 @@ static WorkerInfo MyWorkerInfo = NULL; int AutovacuumLauncherPid = 0; static Oid do_start_worker(void); -static void HandleAutoVacLauncherInterrupts(void); -static void AutoVacLauncherShutdown(void) pg_attribute_noreturn(); +static void ProcessAutoVacLauncherInterrupts(void); +pg_noreturn static void AutoVacLauncherShutdown(void); static void launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap); static void launch_worker(TimestampTz now); @@ -348,6 +352,8 @@ static void autovac_report_activity(autovac_table *tab); static void autovac_report_workitem(AutoVacuumWorkItem *workitem, const char *nspname, const char *relname); static void avl_sigusr2_handler(SIGNAL_ARGS); +static bool av_worker_available(void); +static void check_av_worker_gucs(void); @@ -359,7 +365,7 @@ static void avl_sigusr2_handler(SIGNAL_ARGS); * Main entry point for the autovacuum launcher process. */ void -AutoVacLauncherMain(char *startup_data, size_t startup_data_len) +AutoVacLauncherMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; @@ -460,6 +466,7 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) */ LWLockReleaseAll(); pgstat_report_wait_end(); + pgaio_error_cleanup(); UnlockBuffers(); /* this is probably dead code, but let's be safe: */ if (AuxProcessResourceOwner) @@ -576,8 +583,7 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) * wakening conditions. */ - launcher_determine_sleep(!dlist_is_empty(&AutoVacuumShmem->av_freeWorkers), - false, &nap); + launcher_determine_sleep(av_worker_available(), false, &nap); /* * Wait until naptime expires or we get some type of signal (all the @@ -590,7 +596,7 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) ResetLatch(MyLatch); - HandleAutoVacLauncherInterrupts(); + ProcessAutoVacLauncherInterrupts(); /* * a worker finished, or postmaster signaled failure to start a worker @@ -637,7 +643,7 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) current_time = GetCurrentTimestamp(); LWLockAcquire(AutovacuumLock, LW_SHARED); - can_launch = !dlist_is_empty(&AutoVacuumShmem->av_freeWorkers); + can_launch = av_worker_available(); if (AutoVacuumShmem->av_startingWorker != NULL) { @@ -680,8 +686,8 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) worker->wi_sharedrel = false; worker->wi_proc = NULL; worker->wi_launchtime = 0; - dlist_push_head(&AutoVacuumShmem->av_freeWorkers, - &worker->wi_links); + dclist_push_head(&AutoVacuumShmem->av_freeWorkers, + &worker->wi_links); AutoVacuumShmem->av_startingWorker = NULL; ereport(WARNING, errmsg("autovacuum worker took too long to start; canceled")); @@ -738,7 +744,7 @@ AutoVacLauncherMain(char *startup_data, size_t startup_data_len) * Process any new interrupts. */ static void -HandleAutoVacLauncherInterrupts(void) +ProcessAutoVacLauncherInterrupts(void) { /* the normal shutdown case */ if (ShutdownRequestPending) @@ -746,6 +752,8 @@ HandleAutoVacLauncherInterrupts(void) if (ConfigReloadPending) { + int autovacuum_max_workers_prev = autovacuum_max_workers; + ConfigReloadPending = false; ProcessConfigFile(PGC_SIGHUP); @@ -753,6 +761,14 @@ HandleAutoVacLauncherInterrupts(void) if (!AutoVacuumingActive()) AutoVacLauncherShutdown(); + /* + * If autovacuum_max_workers changed, emit a WARNING if + * autovacuum_worker_slots < autovacuum_max_workers. If it didn't + * change, skip this to avoid too many repeated log messages. + */ + if (autovacuum_max_workers_prev != autovacuum_max_workers) + check_av_worker_gucs(); + /* rebuild the list in case the naptime changed */ rebuild_database_list(InvalidOid); } @@ -1088,7 +1104,7 @@ do_start_worker(void) /* return quickly when there are no free workers */ LWLockAcquire(AutovacuumLock, LW_SHARED); - if (dlist_is_empty(&AutoVacuumShmem->av_freeWorkers)) + if (!av_worker_available()) { LWLockRelease(AutovacuumLock); return InvalidOid; @@ -1241,7 +1257,7 @@ do_start_worker(void) * Get a worker entry from the freelist. We checked above, so there * really should be a free slot. */ - wptr = dlist_pop_head_node(&AutoVacuumShmem->av_freeWorkers); + wptr = dclist_pop_head_node(&AutoVacuumShmem->av_freeWorkers); worker = dlist_container(WorkerInfoData, wi_links, wptr); worker->wi_dboid = avdb->adw_datid; @@ -1357,7 +1373,7 @@ avl_sigusr2_handler(SIGNAL_ARGS) * Main entry point for autovacuum worker processes. */ void -AutoVacWorkerMain(char *startup_data, size_t startup_data_len) +AutoVacWorkerMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; Oid dbid; @@ -1550,12 +1566,16 @@ AutoVacWorkerMain(char *startup_data, size_t startup_data_len) pgstat_report_autovac(dbid); /* - * Connect to the selected database, specifying no particular user + * Connect to the selected database, specifying no particular user, + * and ignoring datallowconn. Collect the database's name for + * display. * * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, 0, dbname); + InitPostgres(NULL, dbid, NULL, InvalidOid, + INIT_PG_OVERRIDE_ALLOW_CONNS, + dbname); SetProcessingMode(NormalProcessing); set_ps_display(dbname); ereport(DEBUG1, @@ -1610,8 +1630,8 @@ FreeWorkerInfo(int code, Datum arg) MyWorkerInfo->wi_proc = NULL; MyWorkerInfo->wi_launchtime = 0; pg_atomic_clear_flag(&MyWorkerInfo->wi_dobalance); - dlist_push_head(&AutoVacuumShmem->av_freeWorkers, - &MyWorkerInfo->wi_links); + dclist_push_head(&AutoVacuumShmem->av_freeWorkers, + &MyWorkerInfo->wi_links); /* not mine anymore */ MyWorkerInfo = NULL; @@ -1798,18 +1818,9 @@ get_database_list(void) resultcxt = CurrentMemoryContext; /* - * Start a transaction so we can access pg_database, and get a snapshot. - * We don't have a use for the snapshot itself, but we're interested in - * the secondary effect that it sets RecentGlobalXmin. (This is critical - * for anything that reads heap pages, because HOT may decide to prune - * them even if the process doesn't attempt to modify any tuples.) - * - * FIXME: This comment is inaccurate / the code buggy. A snapshot that is - * not pushed/active does not reliably prevent HOT pruning (->xmin could - * e.g. be cleared when cache invalidations are processed). + * Start a transaction so we can access pg_database. */ StartTransactionCommand(); - (void) GetTransactionSnapshot(); rel = table_open(DatabaseRelationId, AccessShareLock); scan = table_beginscan_catalog(rel, 0, NULL); @@ -1907,7 +1918,7 @@ do_autovacuum(void) * This injection point is put in a transaction block to work with a wait * that uses a condition variable. */ - INJECTION_POINT("autovacuum-worker-start"); + INJECTION_POINT("autovacuum-worker-start", NULL); /* * Compute the multixact age for which freezing is urgent. This is @@ -2062,6 +2073,12 @@ do_autovacuum(void) } } } + + /* Release stuff to avoid per-relation leakage */ + if (relopts) + pfree(relopts); + if (tabentry) + pfree(tabentry); } table_endscan(relScan); @@ -2078,7 +2095,8 @@ do_autovacuum(void) Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple); PgStat_StatTabEntry *tabentry; Oid relid; - AutoVacOpts *relopts = NULL; + AutoVacOpts *relopts; + bool free_relopts = false; bool dovacuum; bool doanalyze; bool wraparound; @@ -2096,7 +2114,9 @@ do_autovacuum(void) * main rel */ relopts = extract_autovac_opts(tuple, pg_class_desc); - if (relopts == NULL) + if (relopts) + free_relopts = true; + else { av_relation *hentry; bool found; @@ -2117,6 +2137,12 @@ do_autovacuum(void) /* ignore analyze for toast tables */ if (dovacuum) table_oids = lappend_oid(table_oids, relid); + + /* Release stuff to avoid leakage */ + if (free_relopts) + pfree(relopts); + if (tabentry) + pfree(tabentry); } table_endscan(relScan); @@ -2208,6 +2234,12 @@ do_autovacuum(void) get_namespace_name(classForm->relnamespace), NameStr(classForm->relname)))); + /* + * Deletion might involve TOAST table access, so ensure we have a + * valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + object.classId = RelationRelationId; object.objectId = relid; object.objectSubId = 0; @@ -2220,6 +2252,7 @@ do_autovacuum(void) * To commit the deletion, end current transaction and start a new * one. Note this also releases the locks we took. */ + PopActiveSnapshot(); CommitTransactionCommand(); StartTransactionCommand(); @@ -2488,6 +2521,8 @@ do_autovacuum(void) pg_atomic_test_set_flag(&MyWorkerInfo->wi_dobalance); } + list_free(table_oids); + /* * Perform additional work items, as requested by backends. */ @@ -2669,8 +2704,8 @@ perform_work_item(AutoVacuumWorkItem *workitem) /* * extract_autovac_opts * - * Given a relation's pg_class tuple, return the AutoVacOpts portion of - * reloptions, if set; otherwise, return NULL. + * Given a relation's pg_class tuple, return a palloc'd copy of the + * AutoVacOpts portion of reloptions, if set; otherwise, return NULL. * * Note: callers do not have a relation lock on the table at this point, * so the table could have been dropped, and its catalog rows gone, after @@ -2719,6 +2754,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, autovac_table *tab = NULL; bool wraparound; AutoVacOpts *avopts; + bool free_avopts = false; /* fetch the relation's relcache entry */ classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); @@ -2731,8 +2767,10 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, * main table reloptions if the toast table itself doesn't have. */ avopts = extract_autovac_opts(classTup, pg_class_desc); - if (classForm->relkind == RELKIND_TOASTVALUE && - avopts == NULL && table_toast_map != NULL) + if (avopts) + free_avopts = true; + else if (classForm->relkind == RELKIND_TOASTVALUE && + table_toast_map != NULL) { av_relation *hentry; bool found; @@ -2818,6 +2856,12 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, tab->at_params.is_wraparound = wraparound; tab->at_params.log_min_duration = log_min_duration; tab->at_params.toast_parent = InvalidOid; + + /* + * Later, in vacuum_rel(), we check reloptions for any + * vacuum_max_eager_freeze_failure_rate override. + */ + tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate; tab->at_storage_param_vac_cost_limit = avopts ? avopts->vacuum_cost_limit : 0; tab->at_storage_param_vac_cost_delay = avopts ? @@ -2835,6 +2879,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, avopts->vacuum_cost_delay >= 0)); } + if (free_avopts) + pfree(avopts); heap_freetuple(classTup); return tab; } @@ -2866,6 +2912,10 @@ recheck_relation_needs_vacanalyze(Oid relid, effective_multixact_freeze_max_age, dovacuum, doanalyze, wraparound); + /* Release tabentry to avoid leakage */ + if (tabentry) + pfree(tabentry); + /* ignore ANALYZE for toast tables */ if (classForm->relkind == RELKIND_TOASTVALUE) *doanalyze = false; @@ -2887,6 +2937,8 @@ recheck_relation_needs_vacanalyze(Oid relid, * threshold. This threshold is calculated as * * threshold = vac_base_thresh + vac_scale_factor * reltuples + * if (threshold > vac_max_thresh) + * threshold = vac_max_thresh; * * For analyze, the analysis done is that the number of tuples inserted, * deleted and updated since the last analyze exceeds a threshold calculated @@ -2921,10 +2973,10 @@ relation_needs_vacanalyze(Oid relid, { bool force_vacuum; bool av_enabled; - float4 reltuples; /* pg_class.reltuples */ /* constants from reloptions or GUC variables */ int vac_base_thresh, + vac_max_thresh, vac_ins_base_thresh, anl_base_thresh; float4 vac_scale_factor, @@ -2966,6 +3018,11 @@ relation_needs_vacanalyze(Oid relid, ? relopts->vacuum_threshold : autovacuum_vac_thresh; + /* -1 is used to disable max threshold */ + vac_max_thresh = (relopts && relopts->vacuum_max_threshold >= -1) + ? relopts->vacuum_max_threshold + : autovacuum_vac_max_thresh; + vac_ins_scale_factor = (relopts && relopts->vacuum_ins_scale_factor >= 0) ? relopts->vacuum_ins_scale_factor : autovacuum_vac_ins_scale; @@ -3029,7 +3086,11 @@ relation_needs_vacanalyze(Oid relid, */ if (PointerIsValid(tabentry) && AutoVacuumingActive()) { - reltuples = classForm->reltuples; + float4 pcnt_unfrozen = 1; + float4 reltuples = classForm->reltuples; + int32 relpages = classForm->relpages; + int32 relallfrozen = classForm->relallfrozen; + vactuples = tabentry->dead_tuples; instuples = tabentry->ins_since_vacuum; anltuples = tabentry->mod_since_analyze; @@ -3038,8 +3099,29 @@ relation_needs_vacanalyze(Oid relid, if (reltuples < 0) reltuples = 0; + /* + * If we have data for relallfrozen, calculate the unfrozen percentage + * of the table to modify insert scale factor. This helps us decide + * whether or not to vacuum an insert-heavy table based on the number + * of inserts to the more "active" part of the table. + */ + if (relpages > 0 && relallfrozen > 0) + { + /* + * It could be the stats were updated manually and relallfrozen > + * relpages. Clamp relallfrozen to relpages to avoid nonsensical + * calculations. + */ + relallfrozen = Min(relallfrozen, relpages); + pcnt_unfrozen = 1 - ((float4) relallfrozen / relpages); + } + vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples; - vacinsthresh = (float4) vac_ins_base_thresh + vac_ins_scale_factor * reltuples; + if (vac_max_thresh >= 0 && vacthresh > (float4) vac_max_thresh) + vacthresh = (float4) vac_max_thresh; + + vacinsthresh = (float4) vac_ins_base_thresh + + vac_ins_scale_factor * reltuples * pcnt_unfrozen; anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples; /* @@ -3091,18 +3173,22 @@ autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy) VacuumRelation *rel; List *rel_list; MemoryContext vac_context; + MemoryContext old_context; /* Let pgstat know what we're doing */ autovac_report_activity(tab); + /* Create a context that vacuum() can use as cross-transaction storage */ + vac_context = AllocSetContextCreate(CurrentMemoryContext, + "Vacuum", + ALLOCSET_DEFAULT_SIZES); + /* Set up one VacuumRelation target, identified by OID, for vacuum() */ + old_context = MemoryContextSwitchTo(vac_context); rangevar = makeRangeVar(tab->at_nspname, tab->at_relname, -1); rel = makeVacuumRelation(rangevar, tab->at_relid, NIL); rel_list = list_make1(rel); - - vac_context = AllocSetContextCreate(CurrentMemoryContext, - "Vacuum", - ALLOCSET_DEFAULT_SIZES); + MemoryContextSwitchTo(old_context); vacuum(rel_list, &tab->at_params, bstrategy, vac_context, true); @@ -3252,10 +3338,14 @@ AutoVacuumRequestWork(AutoVacuumWorkItemType type, Oid relationId, void autovac_init(void) { - if (autovacuum_start_daemon && !pgstat_track_counts) + if (!autovacuum_start_daemon) + return; + else if (!pgstat_track_counts) ereport(WARNING, (errmsg("autovacuum not started because of misconfiguration"), errhint("Enable the \"track_counts\" option."))); + else + check_av_worker_gucs(); } /* @@ -3272,7 +3362,7 @@ AutoVacuumShmemSize(void) */ size = sizeof(AutoVacuumShmemStruct); size = MAXALIGN(size); - size = add_size(size, mul_size(autovacuum_max_workers, + size = add_size(size, mul_size(autovacuum_worker_slots, sizeof(WorkerInfoData))); return size; } @@ -3299,7 +3389,7 @@ AutoVacuumShmemInit(void) Assert(!found); AutoVacuumShmem->av_launcherpid = 0; - dlist_init(&AutoVacuumShmem->av_freeWorkers); + dclist_init(&AutoVacuumShmem->av_freeWorkers); dlist_init(&AutoVacuumShmem->av_runningWorkers); AutoVacuumShmem->av_startingWorker = NULL; memset(AutoVacuumShmem->av_workItems, 0, @@ -3309,10 +3399,10 @@ AutoVacuumShmemInit(void) MAXALIGN(sizeof(AutoVacuumShmemStruct))); /* initialize the WorkerInfo free list */ - for (i = 0; i < autovacuum_max_workers; i++) + for (i = 0; i < autovacuum_worker_slots; i++) { - dlist_push_head(&AutoVacuumShmem->av_freeWorkers, - &worker[i].wi_links); + dclist_push_head(&AutoVacuumShmem->av_freeWorkers, + &worker[i].wi_links); pg_atomic_init_flag(&worker[i].wi_dobalance); } @@ -3339,12 +3429,44 @@ check_autovacuum_work_mem(int *newval, void **extra, GucSource source) return true; /* - * We clamp manually-set values to at least 1MB. Since + * We clamp manually-set values to at least 64kB. Since * maintenance_work_mem is always set to at least this value, do the same * here. */ - if (*newval < 1024) - *newval = 1024; + if (*newval < 64) + *newval = 64; return true; } + +/* + * Returns whether there is a free autovacuum worker slot available. + */ +static bool +av_worker_available(void) +{ + int free_slots; + int reserved_slots; + + free_slots = dclist_count(&AutoVacuumShmem->av_freeWorkers); + + reserved_slots = autovacuum_worker_slots - autovacuum_max_workers; + reserved_slots = Max(0, reserved_slots); + + return free_slots > reserved_slots; +} + +/* + * Emits a WARNING if autovacuum_worker_slots < autovacuum_max_workers. + */ +static void +check_av_worker_gucs(void) +{ + if (autovacuum_worker_slots < autovacuum_max_workers) + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"autovacuum_max_workers\" (%d) should be less than or equal to \"autovacuum_worker_slots\" (%d)", + autovacuum_max_workers, autovacuum_worker_slots), + errdetail("The server will only start up to \"autovacuum_worker_slots\" (%d) autovacuum workers at a given time.", + autovacuum_worker_slots))); +} diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c index b21eae7136833..a6d3630398f4d 100644 --- a/src/backend/postmaster/auxprocess.c +++ b/src/backend/postmaster/auxprocess.c @@ -3,7 +3,7 @@ * functions related to auxiliary processes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,11 +18,6 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/auxprocess.h" -#include "postmaster/bgwriter.h" -#include "postmaster/startup.h" -#include "postmaster/walsummarizer.h" -#include "postmaster/walwriter.h" -#include "replication/walreceiver.h" #include "storage/condition_variable.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -71,7 +66,7 @@ AuxiliaryProcessMainCommon(void) BaseInit(); - ProcSignalInit(); + ProcSignalInit(NULL, 0); /* * Auxiliary processes don't run transactions, but they may need a @@ -83,7 +78,8 @@ AuxiliaryProcessMainCommon(void) /* Initialize backend status information */ pgstat_beinit(); - pgstat_bestart(); + pgstat_bestart_initial(); + pgstat_bestart_final(); /* register a before-shutdown callback for LWLock cleanup */ before_shmem_exit(ShutdownAuxiliaryProcess, 0); diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index 77707bb384777..116ddf7b835f1 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -2,7 +2,7 @@ * bgworker.c * POSTGRES pluggable background workers implementation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/postmaster/bgworker.c @@ -37,7 +37,7 @@ /* * The postmaster's list of registered background workers, in private memory. */ -slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList); +dlist_head BackgroundWorkerList = DLIST_STATIC_INIT(BackgroundWorkerList); /* * BackgroundWorkerSlots exist in shared memory and can be accessed (via @@ -168,7 +168,7 @@ BackgroundWorkerShmemInit(void) &found); if (!IsUnderPostmaster) { - slist_iter siter; + dlist_iter iter; int slotno = 0; BackgroundWorkerData->total_slots = max_worker_processes; @@ -181,12 +181,12 @@ BackgroundWorkerShmemInit(void) * correspondence between the postmaster's private list and the array * in shared memory. */ - slist_foreach(siter, &BackgroundWorkerList) + dlist_foreach(iter, &BackgroundWorkerList) { BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno]; RegisteredBgWorker *rw; - rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); Assert(slotno < max_worker_processes); slot->in_use = true; slot->terminate = false; @@ -220,13 +220,13 @@ BackgroundWorkerShmemInit(void) static RegisteredBgWorker * FindRegisteredWorkerBySlotNumber(int slotno) { - slist_iter siter; + dlist_iter iter; - slist_foreach(siter, &BackgroundWorkerList) + dlist_foreach(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; - rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); if (rw->rw_shmem_slot == slotno) return rw; } @@ -257,7 +257,7 @@ BackgroundWorkerStateChange(bool allow_new_workers) if (max_worker_processes != BackgroundWorkerData->total_slots) { ereport(LOG, - (errmsg("inconsistent background worker state (max_worker_processes=%d, total_slots=%d)", + (errmsg("inconsistent background worker state (\"max_worker_processes\"=%d, total slots=%d)", max_worker_processes, BackgroundWorkerData->total_slots))); return; @@ -401,9 +401,7 @@ BackgroundWorkerStateChange(bool allow_new_workers) } /* Initialize postmaster bookkeeping. */ - rw->rw_backend = NULL; rw->rw_pid = 0; - rw->rw_child_slot = 0; rw->rw_crashed_at = 0; rw->rw_shmem_slot = slotno; rw->rw_terminate = false; @@ -413,29 +411,25 @@ BackgroundWorkerStateChange(bool allow_new_workers) (errmsg_internal("registering background worker \"%s\"", rw->rw_worker.bgw_name))); - slist_push_head(&BackgroundWorkerList, &rw->rw_lnode); + dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode); } } /* * Forget about a background worker that's no longer needed. * - * The worker must be identified by passing an slist_mutable_iter that - * points to it. This convention allows deletion of workers during - * searches of the worker list, and saves having to search the list again. + * NOTE: The entry is unlinked from BackgroundWorkerList. If the caller is + * iterating through it, better use a mutable iterator! * * Caller is responsible for notifying bgw_notify_pid, if appropriate. * * This function must be invoked only in the postmaster. */ void -ForgetBackgroundWorker(slist_mutable_iter *cur) +ForgetBackgroundWorker(RegisteredBgWorker *rw) { - RegisteredBgWorker *rw; BackgroundWorkerSlot *slot; - rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur); - Assert(rw->rw_shmem_slot < max_worker_processes); slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot]; Assert(slot->in_use); @@ -454,7 +448,7 @@ ForgetBackgroundWorker(slist_mutable_iter *cur) (errmsg_internal("unregistering background worker \"%s\"", rw->rw_worker.bgw_name))); - slist_delete_current(cur); + dlist_delete(&rw->rw_lnode); pfree(rw); } @@ -480,17 +474,17 @@ ReportBackgroundWorkerPID(RegisteredBgWorker *rw) * Report that the PID of a background worker is now zero because a * previously-running background worker has exited. * + * NOTE: The entry may be unlinked from BackgroundWorkerList. If the caller + * is iterating through it, better use a mutable iterator! + * * This function should only be called from the postmaster. */ void -ReportBackgroundWorkerExit(slist_mutable_iter *cur) +ReportBackgroundWorkerExit(RegisteredBgWorker *rw) { - RegisteredBgWorker *rw; BackgroundWorkerSlot *slot; int notify_pid; - rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur); - Assert(rw->rw_shmem_slot < max_worker_processes); slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot]; slot->pid = rw->rw_pid; @@ -505,7 +499,7 @@ ReportBackgroundWorkerExit(slist_mutable_iter *cur) */ if (rw->rw_terminate || rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART) - ForgetBackgroundWorker(cur); + ForgetBackgroundWorker(rw); if (notify_pid != 0) kill(notify_pid, SIGUSR1); @@ -519,13 +513,13 @@ ReportBackgroundWorkerExit(slist_mutable_iter *cur) void BackgroundWorkerStopNotifications(pid_t pid) { - slist_iter siter; + dlist_iter iter; - slist_foreach(siter, &BackgroundWorkerList) + dlist_foreach(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; - rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); if (rw->rw_worker.bgw_notify_pid == pid) rw->rw_worker.bgw_notify_pid = 0; } @@ -546,14 +540,14 @@ BackgroundWorkerStopNotifications(pid_t pid) void ForgetUnstartedBackgroundWorkers(void) { - slist_mutable_iter iter; + dlist_mutable_iter iter; - slist_foreach_modify(iter, &BackgroundWorkerList) + dlist_foreach_modify(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; BackgroundWorkerSlot *slot; - rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); Assert(rw->rw_shmem_slot < max_worker_processes); slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot]; @@ -564,7 +558,7 @@ ForgetUnstartedBackgroundWorkers(void) /* ... then zap it, and notify the waiter */ int notify_pid = rw->rw_worker.bgw_notify_pid; - ForgetBackgroundWorker(&iter); + ForgetBackgroundWorker(rw); if (notify_pid != 0) kill(notify_pid, SIGUSR1); } @@ -584,13 +578,13 @@ ForgetUnstartedBackgroundWorkers(void) void ResetBackgroundWorkerCrashTimes(void) { - slist_mutable_iter iter; + dlist_mutable_iter iter; - slist_foreach_modify(iter, &BackgroundWorkerList) + dlist_foreach_modify(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; - rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART) { @@ -601,7 +595,7 @@ ResetBackgroundWorkerCrashTimes(void) * parallel_terminate_count will get incremented after we've * already zeroed parallel_register_count, which would be bad.) */ - ForgetBackgroundWorker(&iter); + ForgetBackgroundWorker(rw); } else { @@ -720,7 +714,7 @@ bgworker_die(SIGNAL_ARGS) * Main entry point for background worker processes. */ void -BackgroundWorkerMain(char *startup_data, size_t startup_data_len) +BackgroundWorkerMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; BackgroundWorker *worker; @@ -860,7 +854,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username, u BackgroundWorker *worker = MyBgworkerEntry; bits32 init_flags = 0; /* never honor session_preload_libraries */ - /* ignore datallowconn? */ + /* ignore datallowconn and ACL_CONNECT? */ if (flags & BGWORKER_BYPASS_ALLOWCONN) init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS; /* ignore rolcanlogin? */ @@ -894,7 +888,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags) BackgroundWorker *worker = MyBgworkerEntry; bits32 init_flags = 0; /* never honor session_preload_libraries */ - /* ignore datallowconn? */ + /* ignore datallowconn and ACL_CONNECT? */ if (flags & BGWORKER_BYPASS_ALLOWCONN) init_flags |= INIT_PG_OVERRIDE_ALLOW_CONNS; /* ignore rolcanlogin? */ @@ -1030,13 +1024,11 @@ RegisterBackgroundWorker(BackgroundWorker *worker) } rw->rw_worker = *worker; - rw->rw_backend = NULL; rw->rw_pid = 0; - rw->rw_child_slot = 0; rw->rw_crashed_at = 0; rw->rw_terminate = false; - slist_push_head(&BackgroundWorkerList, &rw->rw_lnode); + dlist_push_head(&BackgroundWorkerList, &rw->rw_lnode); } /* diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index 0f75548759a36..72f5acceec78d 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -21,7 +21,7 @@ * should be killed by SIGQUIT and then a recovery cycle started. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -38,6 +38,7 @@ #include "postmaster/auxprocess.h" #include "postmaster/bgwriter.h" #include "postmaster/interrupt.h" +#include "storage/aio_subsys.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" @@ -84,7 +85,7 @@ static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr; * basic execution environment, but not enabled signals yet. */ void -BackgroundWriterMain(char *startup_data, size_t startup_data_len) +BackgroundWriterMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; MemoryContext bgwriter_context; @@ -168,6 +169,7 @@ BackgroundWriterMain(char *startup_data, size_t startup_data_len) */ LWLockReleaseAll(); ConditionVariableCancelSleep(); + pgaio_error_cleanup(); UnlockBuffers(); ReleaseAuxProcessResources(false); AtEOXact_Buffers(false); @@ -226,7 +228,7 @@ BackgroundWriterMain(char *startup_data, size_t startup_data_len) /* Clear any already-pending wakeups */ ResetLatch(MyLatch); - HandleMainLoopInterrupts(); + ProcessMainLoopInterrupts(); /* * Do one cycle of dirty-buffer writing. diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 199f008bcda81..fda91ffd1ce2d 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -10,10 +10,13 @@ * fill WAL segments; the checkpointer itself doesn't watch for the * condition.) * - * Normal termination is by SIGUSR2, which instructs the checkpointer to - * execute a shutdown checkpoint and then exit(0). (All backends must be - * stopped before SIGUSR2 is issued!) Emergency termination is by SIGQUIT; - * like any backend, the checkpointer will simply abort and exit on SIGQUIT. + * The normal termination sequence is that checkpointer is instructed to + * execute the shutdown checkpoint by SIGINT. After that checkpointer waits + * to be terminated via SIGUSR2, which instructs the checkpointer to exit(0). + * All backends must be stopped before SIGINT or SIGUSR2 is issued! + * + * Emergency termination is by SIGQUIT; like any backend, the checkpointer + * will simply abort and exit on SIGQUIT. * * If the checkpointer exits unexpectedly, the postmaster treats that the same * as a backend crash: shared memory may be corrupted, so remaining backends @@ -23,7 +26,7 @@ * restart needs to be forced.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -46,11 +49,13 @@ #include "postmaster/bgwriter.h" #include "postmaster/interrupt.h" #include "replication/syncrep.h" +#include "storage/aio_subsys.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/lwlock.h" +#include "storage/pmsignal.h" #include "storage/proc.h" #include "storage/procsignal.h" #include "storage/shmem.h" @@ -141,6 +146,7 @@ double CheckPointCompletionTarget = 0.9; * Private state */ static bool ckpt_active = false; +static volatile sig_atomic_t ShutdownXLOGPending = false; /* these values are valid when ckpt_active is true: */ static pg_time_t ckpt_start_time; @@ -152,7 +158,7 @@ static pg_time_t last_xlog_switch_time; /* Prototypes for private functions */ -static void HandleCheckpointerInterrupts(void); +static void ProcessCheckpointerInterrupts(void); static void CheckArchiveTimeout(void); static bool IsCheckpointOnSchedule(double progress); static bool ImmediateCheckpointRequested(void); @@ -160,7 +166,7 @@ static bool CompactCheckpointerRequestQueue(void); static void UpdateSharedMemoryConfig(void); /* Signal handlers */ -static void ReqCheckpointHandler(SIGNAL_ARGS); +static void ReqShutdownXLOG(SIGNAL_ARGS); /* @@ -170,7 +176,7 @@ static void ReqCheckpointHandler(SIGNAL_ARGS); * basic execution environment, but not enabled signals yet. */ void -CheckpointerMain(char *startup_data, size_t startup_data_len) +CheckpointerMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; MemoryContext checkpointer_context; @@ -191,7 +197,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) * tell us it's okay to shut down (via SIGUSR2). */ pqsignal(SIGHUP, SignalHandlerForConfigReload); - pqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */ + pqsignal(SIGINT, ReqShutdownXLOG); pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ /* SIGQUIT handler was already set up by InitPostmasterChild */ pqsignal(SIGALRM, SIG_IGN); @@ -214,8 +220,11 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) * process during a normal shutdown, and since checkpointer is shut down * very late... * - * Walsenders are shut down after the checkpointer, but currently don't - * report stats. If that changes, we need a more complicated solution. + * While e.g. walsenders are active after the shutdown checkpoint has been + * written (and thus could produce more stats), checkpointer stays around + * after the shutdown checkpoint has been written. postmaster will only + * signal checkpointer to exit after all processes that could emit stats + * have been shut down. */ before_shmem_exit(pgstat_before_server_shutdown, 0); @@ -268,6 +277,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) LWLockReleaseAll(); ConditionVariableCancelSleep(); pgstat_report_wait_end(); + pgaio_error_cleanup(); UnlockBuffers(); ReleaseAuxProcessResources(false); AtEOXact_Buffers(false); @@ -324,13 +334,14 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) UpdateSharedMemoryConfig(); /* - * Advertise our latch that backends can use to wake us up while we're - * sleeping. + * Advertise our proc number that backends can use to wake us up while + * we're sleeping. */ - ProcGlobal->checkpointerLatch = &MyProc->procLatch; + ProcGlobal->checkpointerProc = MyProcNumber; /* - * Loop forever + * Loop until we've been asked to write the shutdown checkpoint or + * terminate. */ for (;;) { @@ -349,7 +360,10 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) * Process any requests or signals received recently. */ AbsorbSyncRequests(); - HandleCheckpointerInterrupts(); + + ProcessCheckpointerInterrupts(); + if (ShutdownXLOGPending || ShutdownRequestPending) + break; /* * Detect a pending checkpoint request by checking whether the flags @@ -460,10 +474,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) * Do the checkpoint. */ if (!do_restartpoint) - { - CreateCheckPoint(flags); - ckpt_performed = true; - } + ckpt_performed = CreateCheckPoint(flags); else ckpt_performed = CreateRestartPoint(flags); @@ -484,7 +495,7 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) ConditionVariableBroadcast(&CheckpointerShmem->done_cv); - if (ckpt_performed) + if (!do_restartpoint) { /* * Note we record the checkpoint start time not end time as @@ -493,24 +504,43 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) */ last_checkpoint_time = now; - if (do_restartpoint) - PendingCheckpointerStats.restartpoints_performed++; + if (ckpt_performed) + PendingCheckpointerStats.num_performed++; } else { - /* - * We were not able to perform the restartpoint (checkpoints - * throw an ERROR in case of error). Most likely because we - * have not received any new checkpoint WAL records since the - * last restartpoint. Try again in 15 s. - */ - last_checkpoint_time = now - CheckPointTimeout + 15; + if (ckpt_performed) + { + /* + * The same as for checkpoint. Please see the + * corresponding comment. + */ + last_checkpoint_time = now; + + PendingCheckpointerStats.restartpoints_performed++; + } + else + { + /* + * We were not able to perform the restartpoint + * (checkpoints throw an ERROR in case of error). Most + * likely because we have not received any new checkpoint + * WAL records since the last restartpoint. Try again in + * 15 s. + */ + last_checkpoint_time = now - CheckPointTimeout + 15; + } } ckpt_active = false; - /* We may have received an interrupt during the checkpoint. */ - HandleCheckpointerInterrupts(); + /* + * We may have received an interrupt during the checkpoint and the + * latch might have been reset (e.g. in CheckpointWriteDelay). + */ + ProcessCheckpointerInterrupts(); + if (ShutdownXLOGPending || ShutdownRequestPending) + break; } /* Check for archive_timeout and switch xlog files if necessary. */ @@ -549,13 +579,64 @@ CheckpointerMain(char *startup_data, size_t startup_data_len) cur_timeout * 1000L /* convert to ms */ , WAIT_EVENT_CHECKPOINTER_MAIN); } + + /* + * From here on, elog(ERROR) should end with exit(1), not send control + * back to the sigsetjmp block above. + */ + ExitOnAnyError = true; + + if (ShutdownXLOGPending) + { + /* + * Close down the database. + * + * Since ShutdownXLOG() creates restartpoint or checkpoint, and + * updates the statistics, increment the checkpoint request and flush + * out pending statistic. + */ + PendingCheckpointerStats.num_requested++; + ShutdownXLOG(0, 0); + pgstat_report_checkpointer(); + pgstat_report_wal(true); + + /* + * Tell postmaster that we're done. + */ + SendPostmasterSignal(PMSIGNAL_XLOG_IS_SHUTDOWN); + ShutdownXLOGPending = false; + } + + /* + * Wait until we're asked to shut down. By separating the writing of the + * shutdown checkpoint from checkpointer exiting, checkpointer can perform + * some should-be-as-late-as-possible work like writing out stats. + */ + for (;;) + { + /* Clear any already-pending wakeups */ + ResetLatch(MyLatch); + + ProcessCheckpointerInterrupts(); + + if (ShutdownRequestPending) + break; + + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, + 0, + WAIT_EVENT_CHECKPOINTER_SHUTDOWN); + } + + /* Normal exit from the checkpointer is here */ + proc_exit(0); /* done */ } /* * Process any new interrupts. */ static void -HandleCheckpointerInterrupts(void) +ProcessCheckpointerInterrupts(void) { if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); @@ -578,29 +659,6 @@ HandleCheckpointerInterrupts(void) */ UpdateSharedMemoryConfig(); } - if (ShutdownRequestPending) - { - /* - * From here on, elog(ERROR) should end with exit(1), not send control - * back to the sigsetjmp block above - */ - ExitOnAnyError = true; - - /* - * Close down the database. - * - * Since ShutdownXLOG() creates restartpoint or checkpoint, and - * updates the statistics, increment the checkpoint request and flush - * out pending statistic. - */ - PendingCheckpointerStats.num_requested++; - ShutdownXLOG(0, 0); - pgstat_report_checkpointer(); - pgstat_report_wal(true); - - /* Normal exit from the checkpointer is here */ - proc_exit(0); /* done */ - } /* Perform logging of memory contexts of this process */ if (LogMemoryContextPending) @@ -663,7 +721,7 @@ CheckArchiveTimeout(void) * assume nothing happened. */ if (XLogSegmentOffset(switchpoint, wal_segment_size) != 0) - elog(DEBUG1, "write-ahead log switch forced (archive_timeout=%d)", + elog(DEBUG1, "write-ahead log switch forced (\"archive_timeout\"=%d)", XLogArchiveTimeout); } @@ -721,6 +779,7 @@ CheckpointWriteDelay(int flags, double progress) * in which case we just try to catch up as quickly as possible. */ if (!(flags & CHECKPOINT_IMMEDIATE) && + !ShutdownXLOGPending && !ShutdownRequestPending && !ImmediateCheckpointRequested() && IsCheckpointOnSchedule(progress)) @@ -854,14 +913,11 @@ IsCheckpointOnSchedule(double progress) * -------------------------------- */ -/* SIGINT: set flag to run a normal checkpoint right away */ +/* SIGINT: set flag to trigger writing of shutdown checkpoint */ static void -ReqCheckpointHandler(SIGNAL_ARGS) +ReqShutdownXLOG(SIGNAL_ARGS) { - /* - * The signaling process should have set ckpt_flags nonzero, so all we - * need do is ensure that our main loop gets kicked out of any wait. - */ + ShutdownXLOGPending = true; SetLatch(MyLatch); } @@ -979,38 +1035,36 @@ RequestCheckpoint(int flags) SpinLockRelease(&CheckpointerShmem->ckpt_lck); /* - * Send signal to request checkpoint. It's possible that the checkpointer - * hasn't started yet, or is in process of restarting, so we will retry a - * few times if needed. (Actually, more than a few times, since on slow - * or overloaded buildfarm machines, it's been observed that the - * checkpointer can take several seconds to start.) However, if not told - * to wait for the checkpoint to occur, we consider failure to send the - * signal to be nonfatal and merely LOG it. The checkpointer should see - * the request when it does start, with or without getting a signal. + * Set checkpointer's latch to request checkpoint. It's possible that the + * checkpointer hasn't started yet, so we will retry a few times if + * needed. (Actually, more than a few times, since on slow or overloaded + * buildfarm machines, it's been observed that the checkpointer can take + * several seconds to start.) However, if not told to wait for the + * checkpoint to occur, we consider failure to set the latch to be + * nonfatal and merely LOG it. The checkpointer should see the request + * when it does start, with or without the SetLatch(). */ #define MAX_SIGNAL_TRIES 600 /* max wait 60.0 sec */ for (ntries = 0;; ntries++) { - if (CheckpointerShmem->checkpointer_pid == 0) + volatile PROC_HDR *procglobal = ProcGlobal; + ProcNumber checkpointerProc = procglobal->checkpointerProc; + + if (checkpointerProc == INVALID_PROC_NUMBER) { if (ntries >= MAX_SIGNAL_TRIES || !(flags & CHECKPOINT_WAIT)) { elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG, - "could not signal for checkpoint: checkpointer is not running"); + "could not notify checkpoint: checkpointer is not running"); break; } } - else if (kill(CheckpointerShmem->checkpointer_pid, SIGINT) != 0) + else { - if (ntries >= MAX_SIGNAL_TRIES || !(flags & CHECKPOINT_WAIT)) - { - elog((flags & CHECKPOINT_WAIT) ? ERROR : LOG, - "could not signal for checkpoint: %m"); - break; - } + SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch); + /* notified successfully */ + break; } - else - break; /* signal sent successfully */ CHECK_FOR_INTERRUPTS(); pg_usleep(100000L); /* wait 0.1 sec, then retry */ @@ -1128,8 +1182,14 @@ ForwardSyncRequest(const FileTag *ftag, SyncRequestType type) LWLockRelease(CheckpointerCommLock); /* ... but not till after we release the lock */ - if (too_full && ProcGlobal->checkpointerLatch) - SetLatch(ProcGlobal->checkpointerLatch); + if (too_full) + { + volatile PROC_HDR *procglobal = ProcGlobal; + ProcNumber checkpointerProc = procglobal->checkpointerProc; + + if (checkpointerProc != INVALID_PROC_NUMBER) + SetLatch(&GetPGProcByNumber(checkpointerProc)->procLatch); + } return true; } diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c index 5e42a74ab5f47..a64eeb71b879a 100644 --- a/src/backend/postmaster/fork_process.c +++ b/src/backend/postmaster/fork_process.c @@ -4,7 +4,7 @@ * EXEC_BACKEND case; it might be extended to do so, but it would be * considerably more complex. * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/postmaster/fork_process.c @@ -19,6 +19,7 @@ #include #include "libpq/pqsignal.h" +#include "miscadmin.h" #include "postmaster/fork_process.h" #ifndef WIN32 @@ -66,6 +67,7 @@ fork_process(void) if (result == 0) { /* fork succeeded, in child */ + MyProcPid = getpid(); #ifdef LINUX_PROFILE setitimer(ITIMER_PROF, &prof_itimer, NULL); #endif diff --git a/src/backend/postmaster/interrupt.c b/src/backend/postmaster/interrupt.c index eedc0980cf113..0ae9bf906ec18 100644 --- a/src/backend/postmaster/interrupt.c +++ b/src/backend/postmaster/interrupt.c @@ -3,7 +3,7 @@ * interrupt.c * Interrupt handling routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -31,7 +31,7 @@ volatile sig_atomic_t ShutdownRequestPending = false; * Simple interrupt handler for main loops of background processes. */ void -HandleMainLoopInterrupts(void) +ProcessMainLoopInterrupts(void) { if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); @@ -55,7 +55,7 @@ HandleMainLoopInterrupts(void) * * Normally, this handler would be used for SIGHUP. The idea is that code * which uses it would arrange to check the ConfigReloadPending flag at - * convenient places inside main loops, or else call HandleMainLoopInterrupts. + * convenient places inside main loops, or else call ProcessMainLoopInterrupts. */ void SignalHandlerForConfigReload(SIGNAL_ARGS) @@ -99,7 +99,7 @@ SignalHandlerForCrashExit(SIGNAL_ARGS) * SIGINT or SIGTERM. * * ShutdownRequestPending should be checked at a convenient place within the - * main loop, or else the main loop should call HandleMainLoopInterrupts. + * main loop, or else the main loop should call ProcessMainLoopInterrupts. */ void SignalHandlerForShutdownRequest(SIGNAL_ARGS) diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c index fafe5feecc244..bf6b55ee83048 100644 --- a/src/backend/postmaster/launch_backend.c +++ b/src/backend/postmaster/launch_backend.c @@ -20,7 +20,7 @@ * same state as after fork() on a Unix system. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -33,15 +33,9 @@ #include -#include "access/xlog.h" -#include "common/file_utils.h" #include "libpq/libpq-be.h" -#include "libpq/pqsignal.h" #include "miscadmin.h" -#include "nodes/queryjumble.h" -#include "port.h" #include "postmaster/autovacuum.h" -#include "postmaster/auxprocess.h" #include "postmaster/bgworker_internals.h" #include "postmaster/bgwriter.h" #include "postmaster/fork_process.h" @@ -53,19 +47,11 @@ #include "postmaster/walwriter.h" #include "replication/slotsync.h" #include "replication/walreceiver.h" -#include "storage/fd.h" -#include "storage/ipc.h" +#include "storage/dsm.h" +#include "storage/io_worker.h" #include "storage/pg_shmem.h" -#include "storage/pmsignal.h" -#include "storage/proc.h" #include "tcop/backend_startup.h" -#include "tcop/tcopprot.h" -#include "utils/builtins.h" -#include "utils/datetime.h" -#include "utils/guc.h" -#include "utils/injection_point.h" #include "utils/memutils.h" -#include "utils/timestamp.h" #ifdef EXEC_BACKEND #include "nodes/queryjumble.h" @@ -76,6 +62,15 @@ #ifdef EXEC_BACKEND +#include "common/file_utils.h" +#include "storage/fd.h" +#include "storage/lwlock.h" +#include "storage/pmsignal.h" +#include "storage/proc.h" +#include "storage/procsignal.h" +#include "tcop/tcopprot.h" +#include "utils/injection_point.h" + /* Type for a socket that can be inherited to a client process */ #ifdef WIN32 typedef struct @@ -94,8 +89,6 @@ typedef int InheritableSocket; typedef struct { char DataDir[MAXPGPATH]; - int32 MyCancelKey; - int MyPMChildSlot; #ifndef WIN32 unsigned long UsedShmemSegID; #else @@ -104,12 +97,8 @@ typedef struct #endif void *UsedShmemSegAddr; slock_t *ShmemLock; - struct bkend *ShmemBackendArray; #ifdef USE_INJECTION_POINTS struct InjectionPointsCtl *ActiveInjectionPoints; -#endif -#ifndef HAVE_SPINLOCKS - PGSemaphore *SpinlockSemaArray; #endif int NamedLWLockTrancheRequests; NamedLWLockTranche *NamedLWLockTrancheArray; @@ -119,6 +108,7 @@ typedef struct PGPROC *AuxiliaryProcs; PGPROC *PreparedXactProcs; volatile PMSignalData *PMSignalState; + ProcSignalHeader *ProcSignal; pid_t PostmasterPid; TimestampTz PgStartTime; TimestampTz PgReloadTime; @@ -128,6 +118,7 @@ typedef struct bool query_id_enabled; int max_safe_fds; int MaxBackends; + int num_pmchild_slots; #ifdef WIN32 HANDLE PostmasterHandle; HANDLE initial_signal_pipe; @@ -139,6 +130,8 @@ typedef struct char my_exec_path[MAXPGPATH]; char pkglib_path[MAXPGPATH]; + int MyPMChildSlot; + /* * These are only used by backend processes, but are here because passing * a socket needs some special handling on Windows. 'client_sock' is an @@ -157,16 +150,19 @@ typedef struct #define SizeOfBackendParameters(startup_data_len) (offsetof(BackendParameters, startup_data) + startup_data_len) -static void read_backend_variables(char *id, char **startup_data, size_t *startup_data_len); +static void read_backend_variables(char *id, void **startup_data, size_t *startup_data_len); static void restore_backend_variables(BackendParameters *param); -static bool save_backend_variables(BackendParameters *param, ClientSocket *client_sock, +static bool save_backend_variables(BackendParameters *param, int child_slot, + ClientSocket *client_sock, #ifdef WIN32 HANDLE childProcess, pid_t childPid, #endif - char *startup_data, size_t startup_data_len); + const void *startup_data, size_t startup_data_len); -static pid_t internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock); +static pid_t internal_forkexec(const char *child_kind, int child_slot, + const void *startup_data, size_t startup_data_len, + ClientSocket *client_sock); #endif /* EXEC_BACKEND */ @@ -176,7 +172,7 @@ static pid_t internal_forkexec(const char *child_kind, char *startup_data, size_ typedef struct { const char *name; - void (*main_fn) (char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); + void (*main_fn) (const void *startup_data, size_t startup_data_len); bool shmem_attach; } child_process_kind; @@ -184,6 +180,7 @@ static child_process_kind child_process_kinds[] = { [B_INVALID] = {"invalid", NULL, false}, [B_BACKEND] = {"backend", BackendMain, true}, + [B_DEAD_END_BACKEND] = {"dead-end backend", BackendMain, true}, [B_AUTOVAC_LAUNCHER] = {"autovacuum launcher", AutoVacLauncherMain, true}, [B_AUTOVAC_WORKER] = {"autovacuum worker", AutoVacWorkerMain, true}, [B_BG_WORKER] = {"bgworker", BackgroundWorkerMain, true}, @@ -201,6 +198,7 @@ static child_process_kind child_process_kinds[] = { [B_ARCHIVER] = {"archiver", PgArchiverMain, true}, [B_BG_WRITER] = {"bgwriter", BackgroundWriterMain, true}, [B_CHECKPOINTER] = {"checkpointer", CheckpointerMain, true}, + [B_IO_WORKER] = {"io_worker", IoWorkerMain, true}, [B_STARTUP] = {"startup", StartupProcessMain, true}, [B_WAL_RECEIVER] = {"wal_receiver", WalReceiverMain, true}, [B_WAL_SUMMARIZER] = {"wal_summarizer", WalSummarizerMain, true}, @@ -219,36 +217,58 @@ PostmasterChildName(BackendType child_type) * Start a new postmaster child process. * * The child process will be restored to roughly the same state whether - * EXEC_BACKEND is used or not: it will be attached to shared memory, and fds - * and other resources that we've inherited from postmaster that are not - * needed in a child process have been closed. + * EXEC_BACKEND is used or not: it will be attached to shared memory if + * appropriate, and fds and other resources that we've inherited from + * postmaster that are not needed in a child process have been closed. * - * 'startup_data' is an optional contiguous chunk of data that is passed to - * the child process. + * 'child_slot' is the PMChildFlags array index reserved for the child + * process. 'startup_data' is an optional contiguous chunk of data that is + * passed to the child process. */ pid_t -postmaster_child_launch(BackendType child_type, - char *startup_data, size_t startup_data_len, +postmaster_child_launch(BackendType child_type, int child_slot, + const void *startup_data, size_t startup_data_len, ClientSocket *client_sock) { pid_t pid; Assert(IsPostmasterEnvironment && !IsUnderPostmaster); + /* Capture time Postmaster initiates process creation for logging */ + if (IsExternalConnectionBackend(child_type)) + ((BackendStartupData *) startup_data)->fork_started = GetCurrentTimestamp(); + #ifdef EXEC_BACKEND - pid = internal_forkexec(child_process_kinds[child_type].name, + pid = internal_forkexec(child_process_kinds[child_type].name, child_slot, startup_data, startup_data_len, client_sock); /* the child process will arrive in SubPostmasterMain */ #else /* !EXEC_BACKEND */ pid = fork_process(); if (pid == 0) /* child */ { + /* Capture and transfer timings that may be needed for logging */ + if (IsExternalConnectionBackend(child_type)) + { + conn_timing.socket_create = + ((BackendStartupData *) startup_data)->socket_created; + conn_timing.fork_start = + ((BackendStartupData *) startup_data)->fork_started; + conn_timing.fork_end = GetCurrentTimestamp(); + } + /* Close the postmaster's sockets */ ClosePostmasterPorts(child_type == B_LOGGER); /* Detangle from postmaster */ InitPostmasterChild(); + /* Detach shared memory if not needed. */ + if (!child_process_kinds[child_type].shmem_attach) + { + dsm_detach_all(); + PGSharedMemoryDetach(); + } + /* * Enter the Main function with TopMemoryContext. The startup data is * allocated in PostmasterContext, so we cannot release it here yet. @@ -257,6 +277,7 @@ postmaster_child_launch(BackendType child_type, */ MemoryContextSwitchTo(TopMemoryContext); + MyPMChildSlot = child_slot; if (client_sock) { MyClientSocket = palloc(sizeof(ClientSocket)); @@ -283,7 +304,8 @@ postmaster_child_launch(BackendType child_type, * - fork():s, and then exec():s the child process */ static pid_t -internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock) +internal_forkexec(const char *child_kind, int child_slot, + const void *startup_data, size_t startup_data_len, ClientSocket *client_sock) { static unsigned long tmpBackendFileNum = 0; pid_t pid; @@ -303,7 +325,7 @@ internal_forkexec(const char *child_kind, char *startup_data, size_t startup_dat */ paramsz = SizeOfBackendParameters(startup_data_len); param = palloc0(paramsz); - if (!save_backend_variables(param, client_sock, startup_data, startup_data_len)) + if (!save_backend_variables(param, child_slot, client_sock, startup_data, startup_data_len)) { pfree(param); return -1; /* log made by save_backend_variables */ @@ -392,7 +414,8 @@ internal_forkexec(const char *child_kind, char *startup_data, size_t startup_dat * file is complete. */ static pid_t -internal_forkexec(const char *child_kind, char *startup_data, size_t startup_data_len, ClientSocket *client_sock) +internal_forkexec(const char *child_kind, int child_slot, + const void *startup_data, size_t startup_data_len, ClientSocket *client_sock) { int retry_count = 0; STARTUPINFO si; @@ -473,7 +496,9 @@ internal_forkexec(const char *child_kind, char *startup_data, size_t startup_dat return -1; } - if (!save_backend_variables(param, client_sock, pi.hProcess, pi.dwProcessId, startup_data, startup_data_len)) + if (!save_backend_variables(param, child_slot, client_sock, + pi.hProcess, pi.dwProcessId, + startup_data, startup_data_len)) { /* * log made by save_backend_variables, but we have to clean up the @@ -572,16 +597,23 @@ internal_forkexec(const char *child_kind, char *startup_data, size_t startup_dat void SubPostmasterMain(int argc, char *argv[]) { - char *startup_data; + void *startup_data; size_t startup_data_len; char *child_kind; BackendType child_type; bool found = false; + TimestampTz fork_end; /* In EXEC_BACKEND case we will not have inherited these settings */ IsPostmasterEnvironment = true; whereToSendOutput = DestNone; + /* + * Capture the end of process creation for logging. We don't include the + * time spent copying data from shared memory and setting up the backend. + */ + fork_end = GetCurrentTimestamp(); + /* Setup essential subsystems (to ensure elog() behaves sanely) */ InitializeGUCOptions(); @@ -639,6 +671,16 @@ SubPostmasterMain(int argc, char *argv[]) /* Read in remaining GUC variables */ read_nondefault_variables(); + /* Capture and transfer timings that may be needed for log_connections */ + if (IsExternalConnectionBackend(child_type)) + { + conn_timing.socket_create = + ((BackendStartupData *) startup_data)->socket_created; + conn_timing.fork_start = + ((BackendStartupData *) startup_data)->fork_started; + conn_timing.fork_end = fork_end; + } + /* * Check that the data directory looks valid, which will also check the * privileges on the data directory and update our umask and file/group @@ -685,11 +727,12 @@ static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src); /* Save critical backend variables into the BackendParameters struct */ static bool -save_backend_variables(BackendParameters *param, ClientSocket *client_sock, +save_backend_variables(BackendParameters *param, + int child_slot, ClientSocket *client_sock, #ifdef WIN32 HANDLE childProcess, pid_t childPid, #endif - char *startup_data, size_t startup_data_len) + const void *startup_data, size_t startup_data_len) { if (client_sock) memcpy(¶m->client_sock, client_sock, sizeof(ClientSocket)); @@ -702,8 +745,7 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, strlcpy(param->DataDir, DataDir, MAXPGPATH); - param->MyCancelKey = MyCancelKey; - param->MyPMChildSlot = MyPMChildSlot; + param->MyPMChildSlot = child_slot; #ifdef WIN32 param->ShmemProtectiveRegion = ShmemProtectiveRegion; @@ -712,15 +754,11 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, param->UsedShmemSegAddr = UsedShmemSegAddr; param->ShmemLock = ShmemLock; - param->ShmemBackendArray = ShmemBackendArray; #ifdef USE_INJECTION_POINTS param->ActiveInjectionPoints = ActiveInjectionPoints; #endif -#ifndef HAVE_SPINLOCKS - param->SpinlockSemaArray = SpinlockSemaArray; -#endif param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests; param->NamedLWLockTrancheArray = NamedLWLockTrancheArray; param->MainLWLockArray = MainLWLockArray; @@ -729,6 +767,7 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, param->AuxiliaryProcs = AuxiliaryProcs; param->PreparedXactProcs = PreparedXactProcs; param->PMSignalState = PMSignalState; + param->ProcSignal = ProcSignal; param->PostmasterPid = PostmasterPid; param->PgStartTime = PgStartTime; @@ -741,6 +780,7 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, param->max_safe_fds = max_safe_fds; param->MaxBackends = MaxBackends; + param->num_pmchild_slots = num_pmchild_slots; #ifdef WIN32 param->PostmasterHandle = PostmasterHandle; @@ -860,7 +900,7 @@ read_inheritable_socket(SOCKET *dest, InheritableSocket *src) #endif static void -read_backend_variables(char *id, char **startup_data, size_t *startup_data_len) +read_backend_variables(char *id, void **startup_data, size_t *startup_data_len) { BackendParameters param; @@ -965,7 +1005,6 @@ restore_backend_variables(BackendParameters *param) SetDataDir(param->DataDir); - MyCancelKey = param->MyCancelKey; MyPMChildSlot = param->MyPMChildSlot; #ifdef WIN32 @@ -975,15 +1014,11 @@ restore_backend_variables(BackendParameters *param) UsedShmemSegAddr = param->UsedShmemSegAddr; ShmemLock = param->ShmemLock; - ShmemBackendArray = param->ShmemBackendArray; #ifdef USE_INJECTION_POINTS ActiveInjectionPoints = param->ActiveInjectionPoints; #endif -#ifndef HAVE_SPINLOCKS - SpinlockSemaArray = param->SpinlockSemaArray; -#endif NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests; NamedLWLockTrancheArray = param->NamedLWLockTrancheArray; MainLWLockArray = param->MainLWLockArray; @@ -992,6 +1027,7 @@ restore_backend_variables(BackendParameters *param) AuxiliaryProcs = param->AuxiliaryProcs; PreparedXactProcs = param->PreparedXactProcs; PMSignalState = param->PMSignalState; + ProcSignal = param->ProcSignal; PostmasterPid = param->PostmasterPid; PgStartTime = param->PgStartTime; @@ -1004,6 +1040,7 @@ restore_backend_variables(BackendParameters *param) max_safe_fds = param->max_safe_fds; MaxBackends = param->MaxBackends; + num_pmchild_slots = param->num_pmchild_slots; #ifdef WIN32 PostmasterHandle = param->PostmasterHandle; diff --git a/src/backend/postmaster/meson.build b/src/backend/postmaster/meson.build index 0ea4bbe084eaa..0008603cfee99 100644 --- a/src/backend/postmaster/meson.build +++ b/src/backend/postmaster/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'autovacuum.c', @@ -10,6 +10,7 @@ backend_sources += files( 'interrupt.c', 'launch_backend.c', 'pgarch.c', + 'pmchild.c', 'postmaster.c', 'startup.c', 'syslogger.c', diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 02f91431f5f3c..7e622ae4bd2a7 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -14,7 +14,7 @@ * * Initial author: Simon Riggs simon@2ndquadrant.com * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -40,6 +40,7 @@ #include "postmaster/interrupt.h" #include "postmaster/pgarch.h" #include "storage/condition_variable.h" +#include "storage/aio_subsys.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/latch.h" @@ -147,7 +148,7 @@ static bool pgarch_archiveXlog(char *xlog); static bool pgarch_readyXlog(char *xlog); static void pgarch_archiveDone(char *xlog); static void pgarch_die(int code, Datum arg); -static void HandlePgArchInterrupts(void); +static void ProcessPgArchInterrupts(void); static int ready_file_comparator(Datum a, Datum b, void *arg); static void LoadArchiveLibrary(void); static void pgarch_call_module_shutdown_cb(int code, Datum arg); @@ -214,7 +215,7 @@ PgArchCanRestart(void) /* Main entry point for archiver process */ void -PgArchiverMain(char *startup_data, size_t startup_data_len) +PgArchiverMain(const void *startup_data, size_t startup_data_len) { Assert(startup_data_len == 0); @@ -324,7 +325,7 @@ pgarch_MainLoop(void) time_to_stop = ready_to_stop; /* Check for barrier events and config update */ - HandlePgArchInterrupts(); + ProcessPgArchInterrupts(); /* * If we've gotten SIGTERM, we normally just sit and do nothing until @@ -415,7 +416,7 @@ pgarch_ArchiverCopyLoop(void) * we'll adopt a new setting for archive_command as soon as * possible, even if there is a backlog of files to be archived. */ - HandlePgArchInterrupts(); + ProcessPgArchInterrupts(); /* Reset variables that might be set by the callback */ arch_module_check_errdetail_string = NULL; @@ -568,6 +569,7 @@ pgarch_archiveXlog(char *xlog) LWLockReleaseAll(); ConditionVariableCancelSleep(); pgstat_report_wait_end(); + pgaio_error_cleanup(); ReleaseAuxProcessResources(false); AtEOXact_Files(false); AtEOXact_HashTables(false); @@ -856,7 +858,7 @@ pgarch_die(int code, Datum arg) * shutdown request is different between those loops. */ static void -HandlePgArchInterrupts(void) +ProcessPgArchInterrupts(void) { if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); diff --git a/src/backend/postmaster/pmchild.c b/src/backend/postmaster/pmchild.c new file mode 100644 index 0000000000000..cde1d23a4ca8b --- /dev/null +++ b/src/backend/postmaster/pmchild.c @@ -0,0 +1,286 @@ +/*------------------------------------------------------------------------- + * + * pmchild.c + * Functions for keeping track of postmaster child processes. + * + * Postmaster keeps track of all child processes so that when a process exits, + * it knows what kind of a process it was and can clean up accordingly. Every + * child process is allocated a PMChild struct from a fixed pool of structs. + * The size of the pool is determined by various settings that configure how + * many worker processes and backend connections are allowed, i.e. + * autovacuum_worker_slots, max_worker_processes, max_wal_senders, and + * max_connections. + * + * Dead-end backends are handled slightly differently. There is no limit + * on the number of dead-end backends, and they do not need unique IDs, so + * their PMChild structs are allocated dynamically, not from a pool. + * + * The structures and functions in this file are private to the postmaster + * process. But note that there is an array in shared memory, managed by + * pmsignal.c, that mirrors this. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/postmaster/pmchild.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "postmaster/autovacuum.h" +#include "postmaster/postmaster.h" +#include "replication/walsender.h" +#include "storage/pmsignal.h" +#include "storage/proc.h" + +/* + * Freelists for different kinds of child processes. We maintain separate + * pools for each, so that for example launching a lot of regular backends + * cannot prevent autovacuum or an aux process from launching. + */ +typedef struct PMChildPool +{ + int size; /* number of PMChild slots reserved for this + * kind of processes */ + int first_slotno; /* first slot belonging to this pool */ + dlist_head freelist; /* currently unused PMChild entries */ +} PMChildPool; + +static PMChildPool pmchild_pools[BACKEND_NUM_TYPES]; +NON_EXEC_STATIC int num_pmchild_slots = 0; + +/* + * List of active child processes. This includes dead-end children. + */ +dlist_head ActiveChildList; + +/* + * MaxLivePostmasterChildren + * + * This reports the number of postmaster child processes that can be active. + * It includes all children except for dead-end children. This allows the + * array in shared memory (PMChildFlags) to have a fixed maximum size. + */ +int +MaxLivePostmasterChildren(void) +{ + if (num_pmchild_slots == 0) + elog(ERROR, "PM child array not initialized yet"); + return num_pmchild_slots; +} + +/* + * Initialize at postmaster startup + * + * Note: This is not called on crash restart. We rely on PMChild entries to + * remain valid through the restart process. This is important because the + * syslogger survives through the crash restart process, so we must not + * invalidate its PMChild slot. + */ +void +InitPostmasterChildSlots(void) +{ + int slotno; + PMChild *slots; + + /* + * We allow more connections here than we can have backends because some + * might still be authenticating; they might fail auth, or some existing + * backend might exit before the auth cycle is completed. The exact + * MaxConnections limit is enforced when a new backend tries to join the + * PGPROC array. + * + * WAL senders start out as regular backends, so they share the same pool. + */ + pmchild_pools[B_BACKEND].size = 2 * (MaxConnections + max_wal_senders); + + pmchild_pools[B_AUTOVAC_WORKER].size = autovacuum_worker_slots; + pmchild_pools[B_BG_WORKER].size = max_worker_processes; + pmchild_pools[B_IO_WORKER].size = MAX_IO_WORKERS; + + /* + * There can be only one of each of these running at a time. They each + * get their own pool of just one entry. + */ + pmchild_pools[B_AUTOVAC_LAUNCHER].size = 1; + pmchild_pools[B_SLOTSYNC_WORKER].size = 1; + pmchild_pools[B_ARCHIVER].size = 1; + pmchild_pools[B_BG_WRITER].size = 1; + pmchild_pools[B_CHECKPOINTER].size = 1; + pmchild_pools[B_STARTUP].size = 1; + pmchild_pools[B_WAL_RECEIVER].size = 1; + pmchild_pools[B_WAL_SUMMARIZER].size = 1; + pmchild_pools[B_WAL_WRITER].size = 1; + pmchild_pools[B_LOGGER].size = 1; + + /* The rest of the pmchild_pools are left at zero size */ + + /* Count the total number of slots */ + num_pmchild_slots = 0; + for (int i = 0; i < BACKEND_NUM_TYPES; i++) + num_pmchild_slots += pmchild_pools[i].size; + + /* Initialize them */ + slots = palloc(num_pmchild_slots * sizeof(PMChild)); + slotno = 0; + for (int btype = 0; btype < BACKEND_NUM_TYPES; btype++) + { + pmchild_pools[btype].first_slotno = slotno + 1; + dlist_init(&pmchild_pools[btype].freelist); + + for (int j = 0; j < pmchild_pools[btype].size; j++) + { + slots[slotno].pid = 0; + slots[slotno].child_slot = slotno + 1; + slots[slotno].bkend_type = B_INVALID; + slots[slotno].rw = NULL; + slots[slotno].bgworker_notify = false; + dlist_push_tail(&pmchild_pools[btype].freelist, &slots[slotno].elem); + slotno++; + } + } + Assert(slotno == num_pmchild_slots); + + /* Initialize other structures */ + dlist_init(&ActiveChildList); +} + +/* + * Allocate a PMChild entry for a postmaster child process of given type. + * + * The entry is taken from the right pool for the type. + * + * pmchild->child_slot in the returned struct is unique among all active child + * processes. + */ +PMChild * +AssignPostmasterChildSlot(BackendType btype) +{ + dlist_head *freelist; + PMChild *pmchild; + + if (pmchild_pools[btype].size == 0) + elog(ERROR, "cannot allocate a PMChild slot for backend type %d", btype); + + freelist = &pmchild_pools[btype].freelist; + if (dlist_is_empty(freelist)) + return NULL; + + pmchild = dlist_container(PMChild, elem, dlist_pop_head_node(freelist)); + pmchild->pid = 0; + pmchild->bkend_type = btype; + pmchild->rw = NULL; + pmchild->bgworker_notify = true; + + /* + * pmchild->child_slot for each entry was initialized when the array of + * slots was allocated. Sanity check it. + */ + if (!(pmchild->child_slot >= pmchild_pools[btype].first_slotno && + pmchild->child_slot < pmchild_pools[btype].first_slotno + pmchild_pools[btype].size)) + { + elog(ERROR, "pmchild freelist for backend type %d is corrupt", + pmchild->bkend_type); + } + + dlist_push_head(&ActiveChildList, &pmchild->elem); + + /* Update the status in the shared memory array */ + MarkPostmasterChildSlotAssigned(pmchild->child_slot); + + elog(DEBUG2, "assigned pm child slot %d for %s", + pmchild->child_slot, PostmasterChildName(btype)); + + return pmchild; +} + +/* + * Allocate a PMChild struct for a dead-end backend. Dead-end children are + * not assigned a child_slot number. The struct is palloc'd; returns NULL if + * out of memory. + */ +PMChild * +AllocDeadEndChild(void) +{ + PMChild *pmchild; + + elog(DEBUG2, "allocating dead-end child"); + + pmchild = (PMChild *) palloc_extended(sizeof(PMChild), MCXT_ALLOC_NO_OOM); + if (pmchild) + { + pmchild->pid = 0; + pmchild->child_slot = 0; + pmchild->bkend_type = B_DEAD_END_BACKEND; + pmchild->rw = NULL; + pmchild->bgworker_notify = false; + + dlist_push_head(&ActiveChildList, &pmchild->elem); + } + + return pmchild; +} + +/* + * Release a PMChild slot, after the child process has exited. + * + * Returns true if the child detached cleanly from shared memory, false + * otherwise (see MarkPostmasterChildSlotUnassigned). + */ +bool +ReleasePostmasterChildSlot(PMChild *pmchild) +{ + dlist_delete(&pmchild->elem); + if (pmchild->bkend_type == B_DEAD_END_BACKEND) + { + elog(DEBUG2, "releasing dead-end backend"); + pfree(pmchild); + return true; + } + else + { + PMChildPool *pool; + + elog(DEBUG2, "releasing pm child slot %d", pmchild->child_slot); + + /* WAL senders start out as regular backends, and share the pool */ + if (pmchild->bkend_type == B_WAL_SENDER) + pool = &pmchild_pools[B_BACKEND]; + else + pool = &pmchild_pools[pmchild->bkend_type]; + + /* sanity check that we return the entry to the right pool */ + if (!(pmchild->child_slot >= pool->first_slotno && + pmchild->child_slot < pool->first_slotno + pool->size)) + { + elog(ERROR, "pmchild freelist for backend type %d is corrupt", + pmchild->bkend_type); + } + + dlist_push_head(&pool->freelist, &pmchild->elem); + return MarkPostmasterChildSlotUnassigned(pmchild->child_slot); + } +} + +/* + * Find the PMChild entry of a running child process by PID. + */ +PMChild * +FindPostmasterChildByPid(int pid) +{ + dlist_iter iter; + + dlist_foreach(iter, &ActiveChildList) + { + PMChild *bp = dlist_container(PMChild, elem, iter.cur); + + if (bp->pid == pid) + return bp; + } + return NULL; +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 6f974a8d21a8a..490f7ce36645b 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -32,7 +32,7 @@ * clients. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -90,10 +90,9 @@ #endif #include "access/xlog.h" +#include "access/xlog_internal.h" #include "access/xlogrecovery.h" #include "common/file_perm.h" -#include "common/file_utils.h" -#include "common/ip.h" #include "common/pg_prng.h" #include "lib/ilist.h" #include "libpq/libpq.h" @@ -102,7 +101,6 @@ #include "pgstat.h" #include "port/pg_bswap.h" #include "postmaster/autovacuum.h" -#include "postmaster/auxprocess.h" #include "postmaster/bgworker_internals.h" #include "postmaster/pgarch.h" #include "postmaster/postmaster.h" @@ -111,7 +109,9 @@ #include "replication/logicallauncher.h" #include "replication/slotsync.h" #include "replication/walsender.h" +#include "storage/aio_subsys.h" #include "storage/fd.h" +#include "storage/io_worker.h" #include "storage/ipc.h" #include "storage/pmsignal.h" #include "storage/proc.h" @@ -124,67 +124,80 @@ #include "utils/varlena.h" #ifdef EXEC_BACKEND +#include "common/file_utils.h" #include "storage/pg_shmem.h" #endif /* - * Possible types of a backend. Beyond being the possible bkend_type values in - * struct bkend, these are OR-able request flag bits for SignalSomeChildren() - * and CountChildren(). + * CountChildren and SignalChildren take a bitmask argument to represent + * BackendTypes to count or signal. Define a separate type and functions to + * work with the bitmasks, to avoid accidentally passing a plain BackendType + * in place of a bitmask or vice versa. */ -#define BACKEND_TYPE_NORMAL 0x0001 /* normal backend */ -#define BACKEND_TYPE_AUTOVAC 0x0002 /* autovacuum worker process */ -#define BACKEND_TYPE_WALSND 0x0004 /* walsender process */ -#define BACKEND_TYPE_BGWORKER 0x0008 /* bgworker process */ -#define BACKEND_TYPE_ALL 0x000F /* OR of all the above */ +typedef struct +{ + uint32 mask; +} BackendTypeMask; -/* - * List of active backends (or child processes anyway; we don't actually - * know whether a given child has become a backend or is still in the - * authorization phase). This is used mainly to keep track of how many - * children we have and send them appropriate signals when necessary. - * - * As shown in the above set of backend types, this list includes not only - * "normal" client sessions, but also autovacuum workers, walsenders, and - * background workers. (Note that at the time of launch, walsenders are - * labeled BACKEND_TYPE_NORMAL; we relabel them to BACKEND_TYPE_WALSND - * upon noticing they've changed their PMChildFlags entry. Hence that check - * must be done before any operation that needs to distinguish walsenders - * from normal backends.) - * - * Also, "dead_end" children are in it: these are children launched just for - * the purpose of sending a friendly rejection message to a would-be client. - * We must track them because they are attached to shared memory, but we know - * they will never become live backends. dead_end children are not assigned a - * PMChildSlot. dead_end children have bkend_type NORMAL. - * - * "Special" children such as the startup, bgwriter, autovacuum launcher, and - * slot sync worker tasks are not in this list. They are tracked via StartupPID - * and other pid_t variables below. (Thus, there can't be more than one of any - * given "special" child process type. We use BackendList entries for any - * child process there can be more than one of.) - */ -typedef struct bkend +StaticAssertDecl(BACKEND_NUM_TYPES < 32, "too many backend types for uint32"); + +static const BackendTypeMask BTYPE_MASK_ALL = {(1 << BACKEND_NUM_TYPES) - 1}; +static const BackendTypeMask BTYPE_MASK_NONE = {0}; + +static inline BackendTypeMask +btmask(BackendType t) { - pid_t pid; /* process id of backend */ - int32 cancel_key; /* cancel key for cancels for this backend */ - int child_slot; /* PMChildSlot for this backend, if any */ - int bkend_type; /* child process flavor, see above */ - bool dead_end; /* is it going to send an error and quit? */ - bool bgworker_notify; /* gets bgworker start/stop notifications */ - dlist_node elem; /* list link in BackendList */ -} Backend; + BackendTypeMask mask = {.mask = 1 << t}; -static dlist_head BackendList = DLIST_STATIC_INIT(BackendList); + return mask; +} -#ifdef EXEC_BACKEND -NON_EXEC_STATIC Backend *ShmemBackendArray; -#endif +static inline BackendTypeMask +btmask_add_n(BackendTypeMask mask, int nargs, BackendType *t) +{ + for (int i = 0; i < nargs; i++) + mask.mask |= 1 << t[i]; + return mask; +} -BackgroundWorker *MyBgworkerEntry = NULL; +#define btmask_add(mask, ...) \ + btmask_add_n(mask, \ + lengthof(((BackendType[]){__VA_ARGS__})), \ + (BackendType[]){__VA_ARGS__} \ + ) + +static inline BackendTypeMask +btmask_del(BackendTypeMask mask, BackendType t) +{ + mask.mask &= ~(1 << t); + return mask; +} + +static inline BackendTypeMask +btmask_all_except_n(int nargs, BackendType *t) +{ + BackendTypeMask mask = BTYPE_MASK_ALL; + + for (int i = 0; i < nargs; i++) + mask = btmask_del(mask, t[i]); + return mask; +} +#define btmask_all_except(...) \ + btmask_all_except_n( \ + lengthof(((BackendType[]){__VA_ARGS__})), \ + (BackendType[]){__VA_ARGS__} \ + ) +static inline bool +btmask_contains(BackendTypeMask mask, BackendType t) +{ + return (mask.mask & (1 << t)) != 0; +} + + +BackgroundWorker *MyBgworkerEntry = NULL; /* The socket number we are listening for connections on */ int PostPortNumber = DEF_PGPORT; @@ -228,26 +241,32 @@ int PreAuthDelay = 0; int AuthenticationTimeout = 60; bool log_hostname; /* for ps display and logging */ -bool Log_connections = false; bool enable_bonjour = false; char *bonjour_name; bool restart_after_crash = true; bool remove_temp_files_after_crash = true; + +/* + * When terminating child processes after fatal errors, like a crash of a + * child process, we normally send SIGQUIT -- and most other comments in this + * file are written on the assumption that we do -- but developers might + * prefer to use SIGABRT to collect per-child core dumps. + */ bool send_abort_for_crash = false; bool send_abort_for_kill = false; -/* PIDs of special child processes; 0 when not running */ -static pid_t StartupPID = 0, - BgWriterPID = 0, - CheckpointerPID = 0, - WalWriterPID = 0, - WalReceiverPID = 0, - WalSummarizerPID = 0, - AutoVacPID = 0, - PgArchPID = 0, - SysLoggerPID = 0, - SlotSyncWorkerPID = 0; +/* special child processes; NULL when not running */ +static PMChild *StartupPMChild = NULL, + *BgWriterPMChild = NULL, + *CheckpointerPMChild = NULL, + *WalWriterPMChild = NULL, + *WalReceiverPMChild = NULL, + *WalSummarizerPMChild = NULL, + *AutoVacLauncherPMChild = NULL, + *PgArchPMChild = NULL, + *SysLoggerPMChild = NULL, + *SlotSyncWorkerPMChild = NULL; /* Startup process's status */ typedef enum @@ -293,13 +312,13 @@ static bool FatalError = false; /* T if recovering from backend crash */ * * Normal child backends can only be launched when we are in PM_RUN or * PM_HOT_STANDBY state. (connsAllowed can also restrict launching.) - * In other states we handle connection requests by launching "dead_end" + * In other states we handle connection requests by launching "dead-end" * child processes, which will simply send the client an error message and - * quit. (We track these in the BackendList so that we can know when they + * quit. (We track these in the ActiveChildList so that we can know when they * are all gone; this is important because they're still connected to shared * memory, and would interfere with an attempt to destroy the shmem segment, * possibly leading to SHMALL failure when we try to make a new one.) - * In PM_WAIT_DEAD_END state we are waiting for all the dead_end children + * In PM_WAIT_DEAD_END state we are waiting for all the dead-end children * to drain out of the system, and therefore stop accepting connection * requests at all until the last existing child has quit (which hopefully * will not be very long). @@ -307,9 +326,10 @@ static bool FatalError = false; /* T if recovering from backend crash */ * Notice that this state variable does not distinguish *why* we entered * states later than PM_RUN --- Shutdown and FatalError must be consulted * to find that out. FatalError is never true in PM_RECOVERY, PM_HOT_STANDBY, - * or PM_RUN states, nor in PM_SHUTDOWN states (because we don't enter those - * states when trying to recover from a crash). It can be true in PM_STARTUP - * state, because we don't clear it until we've successfully started WAL redo. + * or PM_RUN states, nor in PM_WAIT_XLOG_SHUTDOWN states (because we don't + * enter those states when trying to recover from a crash). It can be true in + * PM_STARTUP state, because we don't clear it until we've successfully + * started WAL redo. */ typedef enum { @@ -320,11 +340,13 @@ typedef enum PM_RUN, /* normal "database is alive" state */ PM_STOP_BACKENDS, /* need to stop remaining backends */ PM_WAIT_BACKENDS, /* waiting for live backends to exit */ - PM_SHUTDOWN, /* waiting for checkpointer to do shutdown + PM_WAIT_XLOG_SHUTDOWN, /* waiting for checkpointer to do shutdown * ckpt */ - PM_SHUTDOWN_2, /* waiting for archiver and walsenders to + PM_WAIT_XLOG_ARCHIVAL, /* waiting for archiver and walsenders to * finish */ - PM_WAIT_DEAD_END, /* waiting for dead_end children to exit */ + PM_WAIT_IO_WORKERS, /* waiting for io workers to exit */ + PM_WAIT_CHECKPOINTER, /* waiting for checkpointer to shut down */ + PM_WAIT_DEAD_END, /* waiting for dead-end children to exit */ PM_NO_CHILDREN, /* all important children have exited */ } PMState; @@ -385,6 +407,10 @@ bool LoadedSSL = false; static DNSServiceRef bonjour_sdref = NULL; #endif +/* State for IO worker management. */ +static int io_worker_count = 0; +static PMChild *io_worker_children[MAX_IO_WORKERS]; + /* * postmaster.c - function prototypes */ @@ -401,50 +427,32 @@ static void process_pm_child_exit(void); static void process_pm_reload_request(void); static void process_pm_shutdown_request(void); static void dummy_handler(SIGNAL_ARGS); -static void CleanupBackend(int pid, int exitstatus); -static bool CleanupBackgroundWorker(int pid, int exitstatus); +static void CleanupBackend(PMChild *bp, int exitstatus); static void HandleChildCrash(int pid, int exitstatus, const char *procname); static void LogChildExit(int lev, const char *procname, int pid, int exitstatus); static void PostmasterStateMachine(void); +static void UpdatePMState(PMState newState); -static void ExitPostmaster(int status) pg_attribute_noreturn(); +pg_noreturn static void ExitPostmaster(int status); static int ServerLoop(void); static int BackendStartup(ClientSocket *client_sock); static void report_fork_failure_to_client(ClientSocket *client_sock, int errnum); -static CAC_state canAcceptConnections(int backend_type); -static bool RandomCancelKey(int32 *cancel_key); -static void signal_child(pid_t pid, int signal); -static void sigquit_child(pid_t pid); -static bool SignalSomeChildren(int signal, int target); +static CAC_state canAcceptConnections(BackendType backend_type); +static void signal_child(PMChild *pmchild, int signal); +static bool SignalChildren(int signal, BackendTypeMask targetMask); static void TerminateChildren(int signal); - -#define SignalChildren(sig) SignalSomeChildren(sig, BACKEND_TYPE_ALL) - -static int CountChildren(int target); -static bool assign_backendlist_entry(RegisteredBgWorker *rw); +static int CountChildren(BackendTypeMask targetMask); +static void LaunchMissingBackgroundProcesses(void); static void maybe_start_bgworkers(void); +static bool maybe_reap_io_worker(int pid); +static void maybe_adjust_io_workers(void); static bool CreateOptsFile(int argc, char *argv[], char *fullprogname); -static pid_t StartChildProcess(BackendType type); +static PMChild *StartChildProcess(BackendType type); +static void StartSysLogger(void); static void StartAutovacuumWorker(void); -static void MaybeStartWalReceiver(void); -static void MaybeStartWalSummarizer(void); +static bool StartBackgroundWorker(RegisteredBgWorker *rw); static void InitPostmasterDeathWatchHandle(void); -static void MaybeStartSlotSyncWorker(void); - -/* - * Archiver is allowed to start up at the current postmaster state? - * - * If WAL archiving is enabled always, we are allowed to start archiver - * even during recovery. - */ -#define PgArchStartupAllowed() \ - (((XLogArchivingActive() && pmState == PM_RUN) || \ - (XLogArchivingAlways() && \ - (pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY))) && \ - PgArchCanRestart()) - -#ifdef EXEC_BACKEND #ifdef WIN32 #define WNOHANG 0 /* ignored, so any integer value will do */ @@ -462,10 +470,6 @@ typedef struct } win32_deadchild_waitinfo; #endif /* WIN32 */ -static void ShmemBackendArrayAdd(Backend *bn); -static void ShmemBackendArrayRemove(Backend *bn); -#endif /* EXEC_BACKEND */ - /* Macros to check exit status of a child process */ #define EXIT_STATUS_0(st) ((st) == 0) #define EXIT_STATUS_1(st) (WIFEXITED(st) && WEXITSTATUS(st) == 1) @@ -554,7 +558,7 @@ PostmasterMain(int argc, char *argv[]) pqsignal(SIGCHLD, handle_pm_child_exit_signal); /* This may configure SIGURG, depending on platform. */ - InitializeLatchSupport(); + InitializeWaitEventSupport(); InitProcessLocalLatch(); /* @@ -608,8 +612,21 @@ PostmasterMain(int argc, char *argv[]) output_config_variable = strdup(optarg); break; - case 'c': case '-': + + /* + * Error if the user misplaced a special must-be-first option + * for dispatching to a subprogram. parse_dispatch_option() + * returns DISPATCH_POSTMASTER if it doesn't find a match, so + * error for anything else. + */ + if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("--%s must be first argument", optarg))); + + /* FALLTHROUGH */ + case 'c': { char *name, *value; @@ -858,20 +875,22 @@ PostmasterMain(int argc, char *argv[]) #endif /* For debugging: display postmaster environment */ + if (message_level_is_interesting(DEBUG3)) { +#if !defined(WIN32) || defined(_MSC_VER) extern char **environ; +#endif char **p; + StringInfoData si; + + initStringInfo(&si); - ereport(DEBUG3, - (errmsg_internal("%s: PostmasterMain: initial environment dump:", - progname))); - ereport(DEBUG3, - (errmsg_internal("-----------------------------------------"))); + appendStringInfoString(&si, "initial environment dump:"); for (p = environ; *p; ++p) - ereport(DEBUG3, - (errmsg_internal("\t%s", *p))); - ereport(DEBUG3, - (errmsg_internal("-----------------------------------------"))); + appendStringInfo(&si, "\n%s", *p); + + ereport(DEBUG3, errmsg_internal("%s", si.data)); + pfree(si.data); } /* @@ -925,9 +944,16 @@ PostmasterMain(int argc, char *argv[]) /* * Now that loadable modules have had their chance to alter any GUCs, - * calculate MaxBackends. + * calculate MaxBackends and initialize the machinery to track child + * processes. */ InitializeMaxBackends(); + InitPostmasterChildSlots(); + + /* + * Calculate the size of the PGPROC fast-path lock arrays. + */ + InitializeFastPathLocks(); /* * Give preloaded libraries a chance to request additional shared memory. @@ -982,11 +1008,6 @@ PostmasterMain(int argc, char *argv[]) */ set_max_safe_fds(); - /* - * Set reference point for stack-depth checking. - */ - (void) set_stack_base(); - /* * Initialize pipe (or process handle on Windows) that allows children to * wake up from sleep on postmaster death. @@ -1051,7 +1072,8 @@ PostmasterMain(int argc, char *argv[]) /* * If enabled, start up syslogger collection subprocess */ - SysLoggerPID = SysLogger_Start(); + if (Logging_collector) + StartSysLogger(); /* * Reset whereToSendOutput from DestDebug (its starting state) to @@ -1333,6 +1355,8 @@ PostmasterMain(int argc, char *argv[]) * calls fork() without an immediate exec(), both of which have undefined * behavior in a multithreaded program. A multithreaded postmaster is the * normal case on Windows, which offers neither fork() nor sigprocmask(). + * Currently, macOS is the only platform having pthread_is_threaded_np(), + * so we need not worry whether this HINT is appropriate elsewhere. */ if (pthread_is_threaded_np() != 0) ereport(FATAL, @@ -1352,19 +1376,23 @@ PostmasterMain(int argc, char *argv[]) */ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STARTING); + UpdatePMState(PM_STARTUP); + + /* Make sure we can perform I/O while starting up. */ + maybe_adjust_io_workers(); + /* Start bgwriter and checkpointer so they can help with recovery */ - if (CheckpointerPID == 0) - CheckpointerPID = StartChildProcess(B_CHECKPOINTER); - if (BgWriterPID == 0) - BgWriterPID = StartChildProcess(B_BG_WRITER); + if (CheckpointerPMChild == NULL) + CheckpointerPMChild = StartChildProcess(B_CHECKPOINTER); + if (BgWriterPMChild == NULL) + BgWriterPMChild = StartChildProcess(B_BG_WRITER); /* * We're ready to rock and roll... */ - StartupPID = StartChildProcess(B_STARTUP); - Assert(StartupPID != 0); + StartupPMChild = StartChildProcess(B_STARTUP); + Assert(StartupPMChild != NULL); StartupStatus = STARTUP_RUNNING; - pmState = PM_STARTUP; /* Some workers may be scheduled to start now */ maybe_start_bgworkers(); @@ -1489,7 +1517,7 @@ checkControlFile(void) char path[MAXPGPATH]; FILE *fp; - snprintf(path, sizeof(path), "%s/global/pg_control", DataDir); + snprintf(path, sizeof(path), "%s/%s", DataDir, XLOG_CONTROL_FILE); fp = AllocateFile(path, PG_BINARY_R); if (fp == NULL) @@ -1543,7 +1571,7 @@ DetermineSleepTime(void) if (HaveCrashedWorker) { - slist_mutable_iter siter; + dlist_mutable_iter iter; /* * When there are crashed bgworkers, we sleep just long enough that @@ -1551,12 +1579,12 @@ DetermineSleepTime(void) * determine the minimum of all wakeup times according to most recent * crash time and requested restart interval. */ - slist_foreach_modify(siter, &BackgroundWorkerList) + dlist_foreach_modify(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; TimestampTz this_wakeup; - rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); if (rw->rw_crashed_at == 0) continue; @@ -1564,7 +1592,7 @@ DetermineSleepTime(void) if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART || rw->rw_terminate) { - ForgetBackgroundWorker(&siter); + ForgetBackgroundWorker(rw); continue; } @@ -1682,73 +1710,20 @@ ServerLoop(void) } } - /* If we have lost the log collector, try to start a new one */ - if (SysLoggerPID == 0 && Logging_collector) - SysLoggerPID = SysLogger_Start(); - - /* - * If no background writer process is running, and we are not in a - * state that prevents it, start one. It doesn't matter if this - * fails, we'll just try again later. Likewise for the checkpointer. - */ - if (pmState == PM_RUN || pmState == PM_RECOVERY || - pmState == PM_HOT_STANDBY || pmState == PM_STARTUP) - { - if (CheckpointerPID == 0) - CheckpointerPID = StartChildProcess(B_CHECKPOINTER); - if (BgWriterPID == 0) - BgWriterPID = StartChildProcess(B_BG_WRITER); - } - - /* - * Likewise, if we have lost the walwriter process, try to start a new - * one. But this is needed only in normal operation (else we cannot - * be writing any new WAL). - */ - if (WalWriterPID == 0 && pmState == PM_RUN) - WalWriterPID = StartChildProcess(B_WAL_WRITER); - /* - * If we have lost the autovacuum launcher, try to start a new one. We - * don't want autovacuum to run in binary upgrade mode because - * autovacuum might update relfrozenxid for empty tables before the - * physical files are put in place. + * If we need to launch any background processes after changing state + * or because some exited, do so now. */ - if (!IsBinaryUpgrade && AutoVacPID == 0 && - (AutoVacuumingActive() || start_autovac_launcher) && - pmState == PM_RUN) - { - AutoVacPID = StartChildProcess(B_AUTOVAC_LAUNCHER); - if (AutoVacPID != 0) - start_autovac_launcher = false; /* signal processed */ - } - - /* If we have lost the archiver, try to start a new one. */ - if (PgArchPID == 0 && PgArchStartupAllowed()) - PgArchPID = StartChildProcess(B_ARCHIVER); - - /* If we need to start a slot sync worker, try to do that now */ - MaybeStartSlotSyncWorker(); + LaunchMissingBackgroundProcesses(); /* If we need to signal the autovacuum launcher, do so now */ if (avlauncher_needs_signal) { avlauncher_needs_signal = false; - if (AutoVacPID != 0) - kill(AutoVacPID, SIGUSR2); + if (AutoVacLauncherPMChild != NULL) + signal_child(AutoVacLauncherPMChild, SIGUSR2); } - /* If we need to start a WAL receiver, try to do that now */ - if (WalReceiverRequested) - MaybeStartWalReceiver(); - - /* If we need to start a WAL summarizer, try to do that now */ - MaybeStartWalSummarizer(); - - /* Get other worker processes running, if needed */ - if (StartWorkerNeeded || HaveCrashedWorker) - maybe_start_bgworkers(); - #ifdef HAVE_PTHREAD_IS_THREADED_NP /* @@ -1826,118 +1801,43 @@ ServerLoop(void) } } -/* - * The client has sent a cancel request packet, not a normal - * start-a-new-connection packet. Perform the necessary processing. - * Nothing is sent back to the client. - */ -void -processCancelRequest(int backendPID, int32 cancelAuthCode) -{ - Backend *bp; - -#ifndef EXEC_BACKEND - dlist_iter iter; -#else - int i; -#endif - - /* - * See if we have a matching backend. In the EXEC_BACKEND case, we can no - * longer access the postmaster's own backend list, and must rely on the - * duplicate array in shared memory. - */ -#ifndef EXEC_BACKEND - dlist_foreach(iter, &BackendList) - { - bp = dlist_container(Backend, elem, iter.cur); -#else - for (i = MaxLivePostmasterChildren() - 1; i >= 0; i--) - { - bp = (Backend *) &ShmemBackendArray[i]; -#endif - if (bp->pid == backendPID) - { - if (bp->cancel_key == cancelAuthCode) - { - /* Found a match; signal that backend to cancel current op */ - ereport(DEBUG2, - (errmsg_internal("processing cancel request: sending SIGINT to process %d", - backendPID))); - signal_child(bp->pid, SIGINT); - } - else - /* Right PID, wrong key: no way, Jose */ - ereport(LOG, - (errmsg("wrong key in cancel request for process %d", - backendPID))); - return; - } -#ifndef EXEC_BACKEND /* make GNU Emacs 26.1 see brace balance */ - } -#else - } -#endif - - /* No matching backend */ - ereport(LOG, - (errmsg("PID %d in cancel request did not match any process", - backendPID))); -} - /* * canAcceptConnections --- check to see if database state allows connections - * of the specified type. backend_type can be BACKEND_TYPE_NORMAL, - * BACKEND_TYPE_AUTOVAC, or BACKEND_TYPE_BGWORKER. (Note that we don't yet - * know whether a NORMAL connection might turn into a walsender.) + * of the specified type. backend_type can be B_BACKEND or B_AUTOVAC_WORKER. + * (Note that we don't yet know whether a normal B_BACKEND connection might + * turn into a walsender.) */ static CAC_state -canAcceptConnections(int backend_type) +canAcceptConnections(BackendType backend_type) { CAC_state result = CAC_OK; + Assert(backend_type == B_BACKEND || backend_type == B_AUTOVAC_WORKER); + /* * Can't start backends when in startup/shutdown/inconsistent recovery * state. We treat autovac workers the same as user backends for this - * purpose. However, bgworkers are excluded from this test; we expect - * bgworker_should_start_now() decided whether the DB state allows them. + * purpose. */ - if (pmState != PM_RUN && pmState != PM_HOT_STANDBY && - backend_type != BACKEND_TYPE_BGWORKER) + if (pmState != PM_RUN && pmState != PM_HOT_STANDBY) { if (Shutdown > NoShutdown) return CAC_SHUTDOWN; /* shutdown is pending */ else if (!FatalError && pmState == PM_STARTUP) return CAC_STARTUP; /* normal startup */ else if (!FatalError && pmState == PM_RECOVERY) - return CAC_NOTCONSISTENT; /* not yet at consistent recovery - * state */ + return CAC_NOTHOTSTANDBY; /* not yet ready for hot standby */ else return CAC_RECOVERY; /* else must be crash recovery */ } /* * "Smart shutdown" restrictions are applied only to normal connections, - * not to autovac workers or bgworkers. + * not to autovac workers. */ - if (!connsAllowed && backend_type == BACKEND_TYPE_NORMAL) + if (!connsAllowed && backend_type == B_BACKEND) return CAC_SHUTDOWN; /* shutdown is pending */ - /* - * Don't start too many children. - * - * We allow more connections here than we can have backends because some - * might still be authenticating; they might fail auth, or some existing - * backend might exit before the auth cycle is completed. The exact - * MaxBackends limit is enforced when a new backend tries to join the - * shared-inval backend array. - * - * The limit here must match the sizes of the per-child-process arrays; - * see comments for MaxLivePostmasterChildren(). - */ - if (CountChildren(BACKEND_TYPE_ALL) >= MaxLivePostmasterChildren()) - result = CAC_TOOMANY; - return result; } @@ -2024,14 +1924,13 @@ ClosePostmasterPorts(bool am_syslogger) /* - * InitProcessGlobals -- set MyProcPid, MyStartTime[stamp], random seeds + * InitProcessGlobals -- set MyStartTime[stamp], random seeds * * Called early in the postmaster and every backend. */ void InitProcessGlobals(void) { - MyProcPid = getpid(); MyStartTimestamp = GetCurrentTimestamp(); MyStartTime = timestamptz_to_time_t(MyStartTimestamp); @@ -2104,27 +2003,7 @@ process_pm_reload_request(void) ereport(LOG, (errmsg("received SIGHUP, reloading configuration files"))); ProcessConfigFile(PGC_SIGHUP); - SignalChildren(SIGHUP); - if (StartupPID != 0) - signal_child(StartupPID, SIGHUP); - if (BgWriterPID != 0) - signal_child(BgWriterPID, SIGHUP); - if (CheckpointerPID != 0) - signal_child(CheckpointerPID, SIGHUP); - if (WalWriterPID != 0) - signal_child(WalWriterPID, SIGHUP); - if (WalReceiverPID != 0) - signal_child(WalReceiverPID, SIGHUP); - if (WalSummarizerPID != 0) - signal_child(WalSummarizerPID, SIGHUP); - if (AutoVacPID != 0) - signal_child(AutoVacPID, SIGHUP); - if (PgArchPID != 0) - signal_child(PgArchPID, SIGHUP); - if (SysLoggerPID != 0) - signal_child(SysLoggerPID, SIGHUP); - if (SlotSyncWorkerPID != 0) - signal_child(SlotSyncWorkerPID, SIGHUP); + SignalChildren(SIGHUP, btmask_all_except(B_DEAD_END_BACKEND)); /* Reload authentication config files too */ if (!load_hba()) @@ -2248,7 +2127,7 @@ process_pm_shutdown_request(void) else if (pmState == PM_STARTUP || pmState == PM_RECOVERY) { /* There should be no clients, so proceed to stop children */ - pmState = PM_STOP_BACKENDS; + UpdatePMState(PM_STOP_BACKENDS); } /* @@ -2282,7 +2161,7 @@ process_pm_shutdown_request(void) if (pmState == PM_STARTUP || pmState == PM_RECOVERY) { /* Just shut down background processes silently */ - pmState = PM_STOP_BACKENDS; + UpdatePMState(PM_STOP_BACKENDS); } else if (pmState == PM_RUN || pmState == PM_HOT_STANDBY) @@ -2290,7 +2169,7 @@ process_pm_shutdown_request(void) /* Report that we're about to zap live client sessions */ ereport(LOG, (errmsg("aborting any active transactions"))); - pmState = PM_STOP_BACKENDS; + UpdatePMState(PM_STOP_BACKENDS); } /* @@ -2325,7 +2204,7 @@ process_pm_shutdown_request(void) /* (note we don't apply send_abort_for_crash here) */ SetQuitSignalReason(PMQUIT_FOR_STOP); TerminateChildren(SIGQUIT); - pmState = PM_WAIT_BACKENDS; + UpdatePMState(PM_WAIT_BACKENDS); /* set stopwatch for them to die */ AbortStartTime = time(NULL); @@ -2362,12 +2241,15 @@ process_pm_child_exit(void) while ((pid = waitpid(-1, &exitstatus, WNOHANG)) > 0) { + PMChild *pmchild; + /* * Check if this child was a startup process. */ - if (pid == StartupPID) + if (StartupPMChild && pid == StartupPMChild->pid) { - StartupPID = 0; + ReleasePostmasterChildSlot(StartupPMChild); + StartupPMChild = NULL; /* * Startup process exited in response to a shutdown request (or it @@ -2377,7 +2259,7 @@ process_pm_child_exit(void) (EXIT_STATUS_0(exitstatus) || EXIT_STATUS_1(exitstatus))) { StartupStatus = STARTUP_NOT_RUNNING; - pmState = PM_WAIT_BACKENDS; + UpdatePMState(PM_WAIT_BACKENDS); /* PostmasterStateMachine logic does the rest */ continue; } @@ -2389,7 +2271,7 @@ process_pm_child_exit(void) StartupStatus = STARTUP_NOT_RUNNING; Shutdown = Max(Shutdown, SmartShutdown); TerminateChildren(SIGTERM); - pmState = PM_WAIT_BACKENDS; + UpdatePMState(PM_WAIT_BACKENDS); /* PostmasterStateMachine logic does the rest */ continue; } @@ -2420,7 +2302,7 @@ process_pm_child_exit(void) * restart in that case. * * This stanza also handles the case where we sent a SIGQUIT - * during PM_STARTUP due to some dead_end child crashing: in that + * during PM_STARTUP due to some dead-end child crashing: in that * situation, if the startup process dies on the SIGQUIT, we need * to transition to PM_WAIT_BACKENDS state which will allow * PostmasterStateMachine to restart the startup process. (On the @@ -2434,7 +2316,7 @@ process_pm_child_exit(void) { StartupStatus = STARTUP_NOT_RUNNING; if (pmState == PM_STARTUP) - pmState = PM_WAIT_BACKENDS; + UpdatePMState(PM_WAIT_BACKENDS); } else StartupStatus = STARTUP_CRASHED; @@ -2450,34 +2332,15 @@ process_pm_child_exit(void) FatalError = false; AbortStartTime = 0; ReachedNormalRunning = true; - pmState = PM_RUN; + UpdatePMState(PM_RUN); connsAllowed = true; /* - * Crank up the background tasks, if we didn't do that already - * when we entered consistent recovery state. It doesn't matter - * if this fails, we'll just try again later. + * At the next iteration of the postmaster's main loop, we will + * crank up the background tasks like the autovacuum launcher and + * background workers that were not started earlier already. */ - if (CheckpointerPID == 0) - CheckpointerPID = StartChildProcess(B_CHECKPOINTER); - if (BgWriterPID == 0) - BgWriterPID = StartChildProcess(B_BG_WRITER); - if (WalWriterPID == 0) - WalWriterPID = StartChildProcess(B_WAL_WRITER); - MaybeStartWalSummarizer(); - - /* - * Likewise, start other special children as needed. In a restart - * situation, some of them may be alive already. - */ - if (!IsBinaryUpgrade && AutoVacuumingActive() && AutoVacPID == 0) - AutoVacPID = StartChildProcess(B_AUTOVAC_LAUNCHER); - if (PgArchStartupAllowed() && PgArchPID == 0) - PgArchPID = StartChildProcess(B_ARCHIVER); - MaybeStartSlotSyncWorker(); - - /* workers may be scheduled to start now */ - maybe_start_bgworkers(); + StartWorkerNeeded = true; /* at this point we are really open for business */ ereport(LOG, @@ -2497,9 +2360,10 @@ process_pm_child_exit(void) * one at the next iteration of the postmaster's main loop, if * necessary. Any other exit condition is treated as a crash. */ - if (pid == BgWriterPID) + if (BgWriterPMChild && pid == BgWriterPMChild->pid) { - BgWriterPID = 0; + ReleasePostmasterChildSlot(BgWriterPMChild); + BgWriterPMChild = NULL; if (!EXIT_STATUS_0(exitstatus)) HandleChildCrash(pid, exitstatus, _("background writer process")); @@ -2509,38 +2373,24 @@ process_pm_child_exit(void) /* * Was it the checkpointer? */ - if (pid == CheckpointerPID) + if (CheckpointerPMChild && pid == CheckpointerPMChild->pid) { - CheckpointerPID = 0; - if (EXIT_STATUS_0(exitstatus) && pmState == PM_SHUTDOWN) + ReleasePostmasterChildSlot(CheckpointerPMChild); + CheckpointerPMChild = NULL; + if (EXIT_STATUS_0(exitstatus) && pmState == PM_WAIT_CHECKPOINTER) { /* * OK, we saw normal exit of the checkpointer after it's been - * told to shut down. We expect that it wrote a shutdown - * checkpoint. (If for some reason it didn't, recovery will - * occur on next postmaster start.) + * told to shut down. We know checkpointer wrote a shutdown + * checkpoint, otherwise we'd still be in + * PM_WAIT_XLOG_SHUTDOWN state. * - * At this point we should have no normal backend children - * left (else we'd not be in PM_SHUTDOWN state) but we might - * have dead_end children to wait for. - * - * If we have an archiver subprocess, tell it to do a last - * archive cycle and quit. Likewise, if we have walsender - * processes, tell them to send any remaining WAL and quit. - */ - Assert(Shutdown > NoShutdown); - - /* Waken archiver for the last time */ - if (PgArchPID != 0) - signal_child(PgArchPID, SIGUSR2); - - /* - * Waken walsenders for the last time. No regular backends - * should be around anymore. + * At this point only dead-end children and logger should be + * left. */ - SignalChildren(SIGUSR2); - - pmState = PM_SHUTDOWN_2; + UpdatePMState(PM_WAIT_DEAD_END); + ConfigurePostmasterWaitSet(false); + SignalChildren(SIGTERM, btmask_all_except(B_LOGGER)); } else { @@ -2560,9 +2410,10 @@ process_pm_child_exit(void) * new one at the next iteration of the postmaster's main loop, if * necessary. Any other exit condition is treated as a crash. */ - if (pid == WalWriterPID) + if (WalWriterPMChild && pid == WalWriterPMChild->pid) { - WalWriterPID = 0; + ReleasePostmasterChildSlot(WalWriterPMChild); + WalWriterPMChild = NULL; if (!EXIT_STATUS_0(exitstatus)) HandleChildCrash(pid, exitstatus, _("WAL writer process")); @@ -2575,9 +2426,10 @@ process_pm_child_exit(void) * backends. (If we need a new wal receiver, we'll start one at the * next iteration of the postmaster's main loop.) */ - if (pid == WalReceiverPID) + if (WalReceiverPMChild && pid == WalReceiverPMChild->pid) { - WalReceiverPID = 0; + ReleasePostmasterChildSlot(WalReceiverPMChild); + WalReceiverPMChild = NULL; if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) HandleChildCrash(pid, exitstatus, _("WAL receiver process")); @@ -2589,9 +2441,10 @@ process_pm_child_exit(void) * a new one at the next iteration of the postmaster's main loop, if * necessary. Any other exit condition is treated as a crash. */ - if (pid == WalSummarizerPID) + if (WalSummarizerPMChild && pid == WalSummarizerPMChild->pid) { - WalSummarizerPID = 0; + ReleasePostmasterChildSlot(WalSummarizerPMChild); + WalSummarizerPMChild = NULL; if (!EXIT_STATUS_0(exitstatus)) HandleChildCrash(pid, exitstatus, _("WAL summarizer process")); @@ -2604,9 +2457,10 @@ process_pm_child_exit(void) * loop, if necessary. Any other exit condition is treated as a * crash. */ - if (pid == AutoVacPID) + if (AutoVacLauncherPMChild && pid == AutoVacLauncherPMChild->pid) { - AutoVacPID = 0; + ReleasePostmasterChildSlot(AutoVacLauncherPMChild); + AutoVacLauncherPMChild = NULL; if (!EXIT_STATUS_0(exitstatus)) HandleChildCrash(pid, exitstatus, _("autovacuum launcher process")); @@ -2616,29 +2470,29 @@ process_pm_child_exit(void) /* * Was it the archiver? If exit status is zero (normal) or one (FATAL * exit), we assume everything is all right just like normal backends - * and just try to restart a new one so that we immediately retry - * archiving remaining files. (If fail, we'll try again in future - * cycles of the postmaster's main loop.) Unless we were waiting for - * it to shut down; don't restart it in that case, and - * PostmasterStateMachine() will advance to the next shutdown step. + * and just try to start a new one on the next cycle of the + * postmaster's main loop, to retry archiving remaining files. */ - if (pid == PgArchPID) + if (PgArchPMChild && pid == PgArchPMChild->pid) { - PgArchPID = 0; + ReleasePostmasterChildSlot(PgArchPMChild); + PgArchPMChild = NULL; if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) HandleChildCrash(pid, exitstatus, _("archiver process")); - if (PgArchStartupAllowed()) - PgArchPID = StartChildProcess(B_ARCHIVER); continue; } /* Was it the system logger? If so, try to start a new one */ - if (pid == SysLoggerPID) + if (SysLoggerPMChild && pid == SysLoggerPMChild->pid) { - SysLoggerPID = 0; + ReleasePostmasterChildSlot(SysLoggerPMChild); + SysLoggerPMChild = NULL; + /* for safety's sake, launch new logger *first* */ - SysLoggerPID = SysLogger_Start(); + if (Logging_collector) + StartSysLogger(); + if (!EXIT_STATUS_0(exitstatus)) LogChildExit(LOG, _("system logger process"), pid, exitstatus); @@ -2652,27 +2506,46 @@ process_pm_child_exit(void) * start a new one at the next iteration of the postmaster's main * loop, if necessary. Any other exit condition is treated as a crash. */ - if (pid == SlotSyncWorkerPID) + if (SlotSyncWorkerPMChild && pid == SlotSyncWorkerPMChild->pid) { - SlotSyncWorkerPID = 0; + ReleasePostmasterChildSlot(SlotSyncWorkerPMChild); + SlotSyncWorkerPMChild = NULL; if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) HandleChildCrash(pid, exitstatus, _("slot sync worker process")); continue; } - /* Was it one of our background workers? */ - if (CleanupBackgroundWorker(pid, exitstatus)) + /* Was it an IO worker? */ + if (maybe_reap_io_worker(pid)) { - /* have it be restarted */ - HaveCrashedWorker = true; + if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) + HandleChildCrash(pid, exitstatus, _("io worker")); + + maybe_adjust_io_workers(); continue; } /* - * Else do standard backend child cleanup. + * Was it a backend or a background worker? + */ + pmchild = FindPostmasterChildByPid(pid); + if (pmchild) + { + CleanupBackend(pmchild, exitstatus); + } + + /* + * We don't know anything about this child process. That's highly + * unexpected, as we do track all the child processes that we fork. */ - CleanupBackend(pid, exitstatus); + else + { + if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) + HandleChildCrash(pid, exitstatus, _("untracked child process")); + else + LogChildExit(LOG, _("untracked child process"), pid, exitstatus); + } } /* loop over pending child-death reports */ /* @@ -2683,40 +2556,102 @@ process_pm_child_exit(void) } /* - * Scan the bgworkers list and see if the given PID (which has just stopped - * or crashed) is in it. Handle its shutdown if so, and return true. If not a - * bgworker, return false. + * CleanupBackend -- cleanup after terminated backend or background worker. * - * This is heavily based on CleanupBackend. One important difference is that - * we don't know yet that the dying process is a bgworker, so we must be silent - * until we're sure it is. + * Remove all local state associated with the child process and release its + * PMChild slot. */ -static bool -CleanupBackgroundWorker(int pid, - int exitstatus) /* child's exit status */ +static void +CleanupBackend(PMChild *bp, + int exitstatus) /* child's exit status. */ { char namebuf[MAXPGPATH]; - slist_mutable_iter iter; - - slist_foreach_modify(iter, &BackgroundWorkerList) + const char *procname; + bool crashed = false; + bool logged = false; + pid_t bp_pid; + bool bp_bgworker_notify; + BackendType bp_bkend_type; + RegisteredBgWorker *rw; + + /* Construct a process name for the log message */ + if (bp->bkend_type == B_BG_WORKER) { - RegisteredBgWorker *rw; - - rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur); + snprintf(namebuf, MAXPGPATH, _("background worker \"%s\""), + bp->rw->rw_worker.bgw_type); + procname = namebuf; + } + else + procname = _(GetBackendTypeDesc(bp->bkend_type)); - if (rw->rw_pid != pid) - continue; + /* + * If a backend dies in an ugly way then we must signal all other backends + * to quickdie. If exit status is zero (normal) or one (FATAL exit), we + * assume everything is all right and proceed to remove the backend from + * the active child list. + */ + if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) + crashed = true; #ifdef WIN32 - /* see CleanupBackend */ - if (exitstatus == ERROR_WAIT_NO_CHILDREN) - exitstatus = 0; + + /* + * On win32, also treat ERROR_WAIT_NO_CHILDREN (128) as nonfatal case, + * since that sometimes happens under load when the process fails to start + * properly (long before it starts using shared memory). Microsoft reports + * it is related to mutex failure: + * http://archives.postgresql.org/pgsql-hackers/2010-09/msg00790.php + */ + if (exitstatus == ERROR_WAIT_NO_CHILDREN) + { + LogChildExit(LOG, procname, bp->pid, exitstatus); + logged = true; + crashed = false; + } #endif - snprintf(namebuf, MAXPGPATH, _("background worker \"%s\""), - rw->rw_worker.bgw_type); + /* + * Release the PMChild entry. + * + * If the process attached to shared memory, this also checks that it + * detached cleanly. + */ + bp_pid = bp->pid; + bp_bgworker_notify = bp->bgworker_notify; + bp_bkend_type = bp->bkend_type; + rw = bp->rw; + if (!ReleasePostmasterChildSlot(bp)) + { + /* + * Uh-oh, the child failed to clean itself up. Treat as a crash after + * all. + */ + crashed = true; + } + bp = NULL; + if (crashed) + { + HandleChildCrash(bp_pid, exitstatus, procname); + return; + } + + /* + * This backend may have been slated to receive SIGUSR1 when some + * background worker started or stopped. Cancel those notifications, as + * we don't want to signal PIDs that are not PostgreSQL backends. This + * gets skipped in the (probably very common) case where the backend has + * never requested any such notifications. + */ + if (bp_bgworker_notify) + BackgroundWorkerStopNotifications(bp_pid); + /* + * If it was a background worker, also update its RegisteredBgWorker + * entry. + */ + if (bp_bkend_type == B_BG_WORKER) + { if (!EXIT_STATUS_0(exitstatus)) { /* Record timestamp, so we know when to restart the worker. */ @@ -2729,139 +2664,111 @@ CleanupBackgroundWorker(int pid, rw->rw_terminate = true; } - /* - * Additionally, just like a backend, any exit status other than 0 or - * 1 is considered a crash and causes a system-wide restart. - */ - if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) - { - HandleChildCrash(pid, exitstatus, namebuf); - return true; - } + rw->rw_pid = 0; + ReportBackgroundWorkerExit(rw); /* report child death */ - /* - * We must release the postmaster child slot. If the worker failed to - * do so, it did not clean up after itself, requiring a crash-restart - * cycle. - */ - if (!ReleasePostmasterChildSlot(rw->rw_child_slot)) + if (!logged) { - HandleChildCrash(pid, exitstatus, namebuf); - return true; + LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG, + procname, bp_pid, exitstatus); + logged = true; } - /* Get it out of the BackendList and clear out remaining data */ - dlist_delete(&rw->rw_backend->elem); -#ifdef EXEC_BACKEND - ShmemBackendArrayRemove(rw->rw_backend); -#endif - - /* - * It's possible that this background worker started some OTHER - * background worker and asked to be notified when that worker started - * or stopped. If so, cancel any notifications destined for the - * now-dead backend. - */ - if (rw->rw_backend->bgworker_notify) - BackgroundWorkerStopNotifications(rw->rw_pid); - pfree(rw->rw_backend); - rw->rw_backend = NULL; - rw->rw_pid = 0; - rw->rw_child_slot = 0; - ReportBackgroundWorkerExit(&iter); /* report child death */ - - LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG, - namebuf, pid, exitstatus); - - return true; + /* have it be restarted */ + HaveCrashedWorker = true; } - return false; + if (!logged) + LogChildExit(DEBUG2, procname, bp_pid, exitstatus); } /* - * CleanupBackend -- cleanup after terminated backend. - * - * Remove all local state associated with backend. + * Transition into FatalError state, in response to something bad having + * happened. Commonly the caller will have logged the reason for entering + * FatalError state. * - * If you change this, see also CleanupBackgroundWorker. + * This should only be called when not already in FatalError or + * ImmediateShutdown state. */ static void -CleanupBackend(int pid, - int exitstatus) /* child's exit status. */ +HandleFatalError(QuitSignalReason reason, bool consider_sigabrt) { - dlist_mutable_iter iter; + int sigtosend; + + Assert(!FatalError); + Assert(Shutdown != ImmediateShutdown); + + SetQuitSignalReason(reason); - LogChildExit(DEBUG2, _("server process"), pid, exitstatus); + if (consider_sigabrt && send_abort_for_crash) + sigtosend = SIGABRT; + else + sigtosend = SIGQUIT; /* - * If a backend dies in an ugly way then we must signal all other backends - * to quickdie. If exit status is zero (normal) or one (FATAL exit), we - * assume everything is all right and proceed to remove the backend from - * the active backend list. + * Signal all other child processes to exit. + * + * We could exclude dead-end children here, but at least when sending + * SIGABRT it seems better to include them. */ + TerminateChildren(sigtosend); -#ifdef WIN32 + FatalError = true; /* - * On win32, also treat ERROR_WAIT_NO_CHILDREN (128) as nonfatal case, - * since that sometimes happens under load when the process fails to start - * properly (long before it starts using shared memory). Microsoft reports - * it is related to mutex failure: - * http://archives.postgresql.org/pgsql-hackers/2010-09/msg00790.php + * Choose the appropriate new state to react to the fatal error. Unless we + * were already in the process of shutting down, we go through + * PM_WAIT_BACKENDS. For errors during the shutdown sequence, we directly + * switch to PM_WAIT_DEAD_END. */ - if (exitstatus == ERROR_WAIT_NO_CHILDREN) - { - LogChildExit(LOG, _("server process"), pid, exitstatus); - exitstatus = 0; - } -#endif - - if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) + switch (pmState) { - HandleChildCrash(pid, exitstatus, _("server process")); - return; - } + case PM_INIT: + /* shouldn't have any children */ + Assert(false); + break; + case PM_STARTUP: + /* should have been handled in process_pm_child_exit */ + Assert(false); + break; - dlist_foreach_modify(iter, &BackendList) - { - Backend *bp = dlist_container(Backend, elem, iter.cur); + /* wait for children to die */ + case PM_RECOVERY: + case PM_HOT_STANDBY: + case PM_RUN: + case PM_STOP_BACKENDS: + UpdatePMState(PM_WAIT_BACKENDS); + break; - if (bp->pid == pid) - { - if (!bp->dead_end) - { - if (!ReleasePostmasterChildSlot(bp->child_slot)) - { - /* - * Uh-oh, the child failed to clean itself up. Treat as a - * crash after all. - */ - HandleChildCrash(pid, exitstatus, _("server process")); - return; - } -#ifdef EXEC_BACKEND - ShmemBackendArrayRemove(bp); -#endif - } - if (bp->bgworker_notify) - { - /* - * This backend may have been slated to receive SIGUSR1 when - * some background worker started or stopped. Cancel those - * notifications, as we don't want to signal PIDs that are not - * PostgreSQL backends. This gets skipped in the (probably - * very common) case where the backend has never requested any - * such notifications. - */ - BackgroundWorkerStopNotifications(bp->pid); - } - dlist_delete(iter.cur); - pfree(bp); + case PM_WAIT_BACKENDS: + /* there might be more backends to wait for */ break; - } - } -} + + case PM_WAIT_XLOG_SHUTDOWN: + case PM_WAIT_XLOG_ARCHIVAL: + case PM_WAIT_CHECKPOINTER: + case PM_WAIT_IO_WORKERS: + + /* + * NB: Similar code exists in PostmasterStateMachine()'s handling + * of FatalError in PM_STOP_BACKENDS/PM_WAIT_BACKENDS states. + */ + ConfigurePostmasterWaitSet(false); + UpdatePMState(PM_WAIT_DEAD_END); + break; + + case PM_WAIT_DEAD_END: + case PM_NO_CHILDREN: + break; + } + + /* + * .. and if this doesn't happen quickly enough, now the clock is ticking + * for us to kill them without mercy. + */ + if (AbortStartTime == 0) + AbortStartTime = time(NULL); +} /* * HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer, @@ -2869,15 +2776,12 @@ CleanupBackend(int pid, * * The objectives here are to clean up our local state about the child * process, and to signal all other remaining children to quickdie. + * + * The caller has already released its PMChild slot. */ static void HandleChildCrash(int pid, int exitstatus, const char *procname) { - dlist_mutable_iter iter; - slist_iter siter; - Backend *bp; - bool take_action; - /* * We only log messages and send signals if this is the first process * crash and we're not doing an immediate shutdown; otherwise, we're only @@ -2885,173 +2789,18 @@ HandleChildCrash(int pid, int exitstatus, const char *procname) * signaled children, nonzero exit status is to be expected, so don't * clutter log. */ - take_action = !FatalError && Shutdown != ImmediateShutdown; - - if (take_action) - { - LogChildExit(LOG, procname, pid, exitstatus); - ereport(LOG, - (errmsg("terminating any other active server processes"))); - SetQuitSignalReason(PMQUIT_FOR_CRASH); - } - - /* Process background workers. */ - slist_foreach(siter, &BackgroundWorkerList) - { - RegisteredBgWorker *rw; - - rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); - if (rw->rw_pid == 0) - continue; /* not running */ - if (rw->rw_pid == pid) - { - /* - * Found entry for freshly-dead worker, so remove it. - */ - (void) ReleasePostmasterChildSlot(rw->rw_child_slot); - dlist_delete(&rw->rw_backend->elem); -#ifdef EXEC_BACKEND - ShmemBackendArrayRemove(rw->rw_backend); -#endif - pfree(rw->rw_backend); - rw->rw_backend = NULL; - rw->rw_pid = 0; - rw->rw_child_slot = 0; - /* don't reset crashed_at */ - /* don't report child stop, either */ - /* Keep looping so we can signal remaining workers */ - } - else - { - /* - * This worker is still alive. Unless we did so already, tell it - * to commit hara-kiri. - */ - if (take_action) - sigquit_child(rw->rw_pid); - } - } - - /* Process regular backends */ - dlist_foreach_modify(iter, &BackendList) - { - bp = dlist_container(Backend, elem, iter.cur); - - if (bp->pid == pid) - { - /* - * Found entry for freshly-dead backend, so remove it. - */ - if (!bp->dead_end) - { - (void) ReleasePostmasterChildSlot(bp->child_slot); -#ifdef EXEC_BACKEND - ShmemBackendArrayRemove(bp); -#endif - } - dlist_delete(iter.cur); - pfree(bp); - /* Keep looping so we can signal remaining backends */ - } - else - { - /* - * This backend is still alive. Unless we did so already, tell it - * to commit hara-kiri. - * - * We could exclude dead_end children here, but at least when - * sending SIGABRT it seems better to include them. - * - * Background workers were already processed above; ignore them - * here. - */ - if (bp->bkend_type == BACKEND_TYPE_BGWORKER) - continue; - - if (take_action) - sigquit_child(bp->pid); - } - } - - /* Take care of the startup process too */ - if (pid == StartupPID) - { - StartupPID = 0; - /* Caller adjusts StartupStatus, so don't touch it here */ - } - else if (StartupPID != 0 && take_action) - { - sigquit_child(StartupPID); - StartupStatus = STARTUP_SIGNALED; - } + if (FatalError || Shutdown == ImmediateShutdown) + return; - /* Take care of the bgwriter too */ - if (pid == BgWriterPID) - BgWriterPID = 0; - else if (BgWriterPID != 0 && take_action) - sigquit_child(BgWriterPID); - - /* Take care of the checkpointer too */ - if (pid == CheckpointerPID) - CheckpointerPID = 0; - else if (CheckpointerPID != 0 && take_action) - sigquit_child(CheckpointerPID); - - /* Take care of the walwriter too */ - if (pid == WalWriterPID) - WalWriterPID = 0; - else if (WalWriterPID != 0 && take_action) - sigquit_child(WalWriterPID); - - /* Take care of the walreceiver too */ - if (pid == WalReceiverPID) - WalReceiverPID = 0; - else if (WalReceiverPID != 0 && take_action) - sigquit_child(WalReceiverPID); - - /* Take care of the walsummarizer too */ - if (pid == WalSummarizerPID) - WalSummarizerPID = 0; - else if (WalSummarizerPID != 0 && take_action) - sigquit_child(WalSummarizerPID); - - /* Take care of the autovacuum launcher too */ - if (pid == AutoVacPID) - AutoVacPID = 0; - else if (AutoVacPID != 0 && take_action) - sigquit_child(AutoVacPID); - - /* Take care of the archiver too */ - if (pid == PgArchPID) - PgArchPID = 0; - else if (PgArchPID != 0 && take_action) - sigquit_child(PgArchPID); - - /* Take care of the slot sync worker too */ - if (pid == SlotSyncWorkerPID) - SlotSyncWorkerPID = 0; - else if (SlotSyncWorkerPID != 0 && take_action) - sigquit_child(SlotSyncWorkerPID); - - /* We do NOT restart the syslogger */ - - if (Shutdown != ImmediateShutdown) - FatalError = true; - - /* We now transit into a state of waiting for children to die */ - if (pmState == PM_RECOVERY || - pmState == PM_HOT_STANDBY || - pmState == PM_RUN || - pmState == PM_STOP_BACKENDS || - pmState == PM_SHUTDOWN) - pmState = PM_WAIT_BACKENDS; + LogChildExit(LOG, procname, pid, exitstatus); + ereport(LOG, + (errmsg("terminating any other active server processes"))); /* - * .. and if this doesn't happen quickly enough, now the clock is ticking - * for us to kill them without mercy. + * Switch into error state. The crashed process has already been removed + * from ActiveChildList. */ - if (AbortStartTime == 0) - AbortStartTime = time(NULL); + HandleFatalError(PMQUIT_FOR_CRASH, true); } /* @@ -3135,92 +2884,134 @@ PostmasterStateMachine(void) * This state ends when we have no normal client backends running. * Then we're ready to stop other children. */ - if (CountChildren(BACKEND_TYPE_NORMAL) == 0) - pmState = PM_STOP_BACKENDS; + if (CountChildren(btmask(B_BACKEND)) == 0) + UpdatePMState(PM_STOP_BACKENDS); } } /* - * If we're ready to do so, signal child processes to shut down. (This - * isn't a persistent state, but treating it as a distinct pmState allows - * us to share this code across multiple shutdown code paths.) + * In the PM_WAIT_BACKENDS state, wait for all the regular backends and + * processes like autovacuum and background workers that are comparable to + * backends to exit. + * + * PM_STOP_BACKENDS is a transient state that means the same as + * PM_WAIT_BACKENDS, but we signal the processes first, before waiting for + * them. Treating it as a distinct pmState allows us to share this code + * across multiple shutdown code paths. */ - if (pmState == PM_STOP_BACKENDS) + if (pmState == PM_STOP_BACKENDS || pmState == PM_WAIT_BACKENDS) { + BackendTypeMask targetMask = BTYPE_MASK_NONE; + /* - * Forget any pending requests for background workers, since we're no - * longer willing to launch any new workers. (If additional requests - * arrive, BackgroundWorkerStateChange will reject them.) + * PM_WAIT_BACKENDS state ends when we have no regular backends, no + * autovac launcher or workers, and no bgworkers (including + * unconnected ones). */ - ForgetUnstartedBackgroundWorkers(); - - /* Signal all backend children except walsenders */ - SignalSomeChildren(SIGTERM, - BACKEND_TYPE_ALL - BACKEND_TYPE_WALSND); - /* and the autovac launcher too */ - if (AutoVacPID != 0) - signal_child(AutoVacPID, SIGTERM); - /* and the bgwriter too */ - if (BgWriterPID != 0) - signal_child(BgWriterPID, SIGTERM); - /* and the walwriter too */ - if (WalWriterPID != 0) - signal_child(WalWriterPID, SIGTERM); + targetMask = btmask_add(targetMask, + B_BACKEND, + B_AUTOVAC_LAUNCHER, + B_AUTOVAC_WORKER, + B_BG_WORKER); + + /* + * No walwriter, bgwriter, slot sync worker, or WAL summarizer either. + */ + targetMask = btmask_add(targetMask, + B_WAL_WRITER, + B_BG_WRITER, + B_SLOTSYNC_WORKER, + B_WAL_SUMMARIZER); + /* If we're in recovery, also stop startup and walreceiver procs */ - if (StartupPID != 0) - signal_child(StartupPID, SIGTERM); - if (WalReceiverPID != 0) - signal_child(WalReceiverPID, SIGTERM); - if (WalSummarizerPID != 0) - signal_child(WalSummarizerPID, SIGTERM); - if (SlotSyncWorkerPID != 0) - signal_child(SlotSyncWorkerPID, SIGTERM); - /* checkpointer, archiver, stats, and syslogger may continue for now */ - - /* Now transition to PM_WAIT_BACKENDS state to wait for them to die */ - pmState = PM_WAIT_BACKENDS; - } + targetMask = btmask_add(targetMask, + B_STARTUP, + B_WAL_RECEIVER); - /* - * If we are in a state-machine state that implies waiting for backends to - * exit, see if they're all gone, and change state if so. - */ - if (pmState == PM_WAIT_BACKENDS) - { /* - * PM_WAIT_BACKENDS state ends when we have no regular backends - * (including autovac workers), no bgworkers (including unconnected - * ones), and no walwriter, autovac launcher, bgwriter or slot sync - * worker. If we are doing crash recovery or an immediate shutdown - * then we expect the checkpointer to exit as well, otherwise not. The - * stats and syslogger processes are disregarded since they are not - * connected to shared memory; we also disregard dead_end children - * here. Walsenders and archiver are also disregarded, they will be - * terminated later after writing the checkpoint record. + * If we are doing crash recovery or an immediate shutdown then we + * expect archiver, checkpointer, io workers and walsender to exit as + * well, otherwise not. */ - if (CountChildren(BACKEND_TYPE_ALL - BACKEND_TYPE_WALSND) == 0 && - StartupPID == 0 && - WalReceiverPID == 0 && - WalSummarizerPID == 0 && - BgWriterPID == 0 && - (CheckpointerPID == 0 || - (!FatalError && Shutdown < ImmediateShutdown)) && - WalWriterPID == 0 && - AutoVacPID == 0 && - SlotSyncWorkerPID == 0) + if (FatalError || Shutdown >= ImmediateShutdown) + targetMask = btmask_add(targetMask, + B_CHECKPOINTER, + B_ARCHIVER, + B_IO_WORKER, + B_WAL_SENDER); + + /* + * Normally archiver, checkpointer, IO workers and walsenders will + * continue running; they will be terminated later after writing the + * checkpoint record. We also let dead-end children to keep running + * for now. The syslogger process exits last. + * + * This assertion checks that we have covered all backend types, + * either by including them in targetMask, or by noting here that they + * are allowed to continue running. + */ +#ifdef USE_ASSERT_CHECKING + { + BackendTypeMask remainMask = BTYPE_MASK_NONE; + + remainMask = btmask_add(remainMask, + B_DEAD_END_BACKEND, + B_LOGGER); + + /* + * Archiver, checkpointer, IO workers, and walsender may or may + * not be in targetMask already. + */ + remainMask = btmask_add(remainMask, + B_ARCHIVER, + B_CHECKPOINTER, + B_IO_WORKER, + B_WAL_SENDER); + + /* these are not real postmaster children */ + remainMask = btmask_add(remainMask, + B_INVALID, + B_STANDALONE_BACKEND); + + /* All types should be included in targetMask or remainMask */ + Assert((remainMask.mask | targetMask.mask) == BTYPE_MASK_ALL.mask); + } +#endif + + /* If we had not yet signaled the processes to exit, do so now */ + if (pmState == PM_STOP_BACKENDS) + { + /* + * Forget any pending requests for background workers, since we're + * no longer willing to launch any new workers. (If additional + * requests arrive, BackgroundWorkerStateChange will reject them.) + */ + ForgetUnstartedBackgroundWorkers(); + + SignalChildren(SIGTERM, targetMask); + + UpdatePMState(PM_WAIT_BACKENDS); + } + + /* Are any of the target processes still running? */ + if (CountChildren(targetMask) == 0) { if (Shutdown >= ImmediateShutdown || FatalError) { /* - * Start waiting for dead_end children to die. This state - * change causes ServerLoop to stop creating new ones. + * Stop any dead-end children and stop creating new ones. + * + * NB: Similar code exists in HandleFatalError(), when the + * error happens in pmState > PM_WAIT_BACKENDS. */ - pmState = PM_WAIT_DEAD_END; + UpdatePMState(PM_WAIT_DEAD_END); + ConfigurePostmasterWaitSet(false); + SignalChildren(SIGQUIT, btmask(B_DEAD_END_BACKEND)); /* - * We already SIGQUIT'd the archiver and stats processes, if - * any, when we started immediate shutdown or entered - * FatalError state. + * We already SIGQUIT'd auxiliary processes (other than + * logger), if any, when we started immediate shutdown or + * entered FatalError state. */ } else @@ -3232,13 +3023,13 @@ PostmasterStateMachine(void) */ Assert(Shutdown > NoShutdown); /* Start the checkpointer if not running */ - if (CheckpointerPID == 0) - CheckpointerPID = StartChildProcess(B_CHECKPOINTER); - /* And tell it to shut down */ - if (CheckpointerPID != 0) + if (CheckpointerPMChild == NULL) + CheckpointerPMChild = StartChildProcess(B_CHECKPOINTER); + /* And tell it to write the shutdown checkpoint */ + if (CheckpointerPMChild != NULL) { - signal_child(CheckpointerPID, SIGUSR2); - pmState = PM_SHUTDOWN; + signal_child(CheckpointerPMChild, SIGINT); + UpdatePMState(PM_WAIT_XLOG_SHUTDOWN); } else { @@ -3251,63 +3042,96 @@ PostmasterStateMachine(void) * We don't consult send_abort_for_crash here, as it's * unlikely that dumping cores would illuminate the reason * for checkpointer fork failure. + * + * XXX: It may be worth to introduce a different PMQUIT + * value that signals that the cluster is in a bad state, + * without a process having crashed. But right now this + * path is very unlikely to be reached, so it isn't + * obviously worthwhile adding a distinct error message in + * quickdie(). */ - FatalError = true; - pmState = PM_WAIT_DEAD_END; - - /* Kill the walsenders and archiver too */ - SignalChildren(SIGQUIT); - if (PgArchPID != 0) - signal_child(PgArchPID, SIGQUIT); + HandleFatalError(PMQUIT_FOR_CRASH, false); } } } } - if (pmState == PM_SHUTDOWN_2) + /* + * The state transition from PM_WAIT_XLOG_SHUTDOWN to + * PM_WAIT_XLOG_ARCHIVAL is in process_pm_pmsignal(), in response to + * PMSIGNAL_XLOG_IS_SHUTDOWN. + */ + + if (pmState == PM_WAIT_XLOG_ARCHIVAL) { /* - * PM_SHUTDOWN_2 state ends when there's no other children than - * dead_end children left. There shouldn't be any regular backends - * left by now anyway; what we're really waiting for is walsenders and - * archiver. + * PM_WAIT_XLOG_ARCHIVAL state ends when there are no children other + * than checkpointer, io workers and dead-end children left. There + * shouldn't be any regular backends left by now anyway; what we're + * really waiting for is for walsenders and archiver to exit. */ - if (PgArchPID == 0 && CountChildren(BACKEND_TYPE_ALL) == 0) + if (CountChildren(btmask_all_except(B_CHECKPOINTER, B_IO_WORKER, + B_LOGGER, B_DEAD_END_BACKEND)) == 0) { - pmState = PM_WAIT_DEAD_END; + UpdatePMState(PM_WAIT_IO_WORKERS); + SignalChildren(SIGUSR2, btmask(B_IO_WORKER)); } } - if (pmState == PM_WAIT_DEAD_END) + if (pmState == PM_WAIT_IO_WORKERS) { - /* Don't allow any new socket connection events. */ - ConfigurePostmasterWaitSet(false); + /* + * PM_WAIT_IO_WORKERS state ends when there's only checkpointer and + * dead-end children left. + */ + if (io_worker_count == 0) + { + UpdatePMState(PM_WAIT_CHECKPOINTER); + /* + * Now that the processes mentioned above are gone, tell + * checkpointer to shut down too. That allows checkpointer to + * perform some last bits of cleanup without other processes + * interfering. + */ + if (CheckpointerPMChild != NULL) + signal_child(CheckpointerPMChild, SIGUSR2); + } + } + + /* + * The state transition from PM_WAIT_CHECKPOINTER to PM_WAIT_DEAD_END is + * in process_pm_child_exit(). + */ + + if (pmState == PM_WAIT_DEAD_END) + { /* - * PM_WAIT_DEAD_END state ends when the BackendList is entirely empty - * (ie, no dead_end children remain), and the archiver is gone too. - * - * The reason we wait for those two is to protect them against a new - * postmaster starting conflicting subprocesses; this isn't an - * ironclad protection, but it at least helps in the - * shutdown-and-immediately-restart scenario. Note that they have - * already been sent appropriate shutdown signals, either during a - * normal state transition leading up to PM_WAIT_DEAD_END, or during + * PM_WAIT_DEAD_END state ends when all other children are gone except + * for the logger. During normal shutdown, all that remains are + * dead-end backends, but in FatalError processing we jump straight + * here with more processes remaining. Note that they have already + * been sent appropriate shutdown signals, either during a normal + * state transition leading up to PM_WAIT_DEAD_END, or during * FatalError processing. + * + * The reason we wait is to protect against a new postmaster starting + * conflicting subprocesses; this isn't an ironclad protection, but it + * at least helps in the shutdown-and-immediately-restart scenario. */ - if (dlist_is_empty(&BackendList) && PgArchPID == 0) + if (CountChildren(btmask_all_except(B_LOGGER)) == 0) { /* These other guys should be dead already */ - Assert(StartupPID == 0); - Assert(WalReceiverPID == 0); - Assert(WalSummarizerPID == 0); - Assert(BgWriterPID == 0); - Assert(CheckpointerPID == 0); - Assert(WalWriterPID == 0); - Assert(AutoVacPID == 0); - Assert(SlotSyncWorkerPID == 0); + Assert(StartupPMChild == NULL); + Assert(WalReceiverPMChild == NULL); + Assert(WalSummarizerPMChild == NULL); + Assert(BgWriterPMChild == NULL); + Assert(CheckpointerPMChild == NULL); + Assert(WalWriterPMChild == NULL); + Assert(AutoVacLauncherPMChild == NULL); + Assert(SlotSyncWorkerPMChild == NULL); /* syslogger is not considered here */ - pmState = PM_NO_CHILDREN; + UpdatePMState(PM_NO_CHILDREN); } } @@ -3388,10 +3212,14 @@ PostmasterStateMachine(void) /* re-create shared memory and semaphores */ CreateSharedMemoryAndSemaphores(); - StartupPID = StartChildProcess(B_STARTUP); - Assert(StartupPID != 0); + UpdatePMState(PM_STARTUP); + + /* Make sure we can perform I/O while starting up. */ + maybe_adjust_io_workers(); + + StartupPMChild = StartChildProcess(B_STARTUP); + Assert(StartupPMChild != NULL); StartupStatus = STARTUP_RUNNING; - pmState = PM_STARTUP; /* crash recovery started, reset SIGKILL flag */ AbortStartTime = 0; @@ -3400,6 +3228,199 @@ PostmasterStateMachine(void) } } +static const char * +pmstate_name(PMState state) +{ +#define PM_TOSTR_CASE(sym) case sym: return #sym + switch (state) + { + PM_TOSTR_CASE(PM_INIT); + PM_TOSTR_CASE(PM_STARTUP); + PM_TOSTR_CASE(PM_RECOVERY); + PM_TOSTR_CASE(PM_HOT_STANDBY); + PM_TOSTR_CASE(PM_RUN); + PM_TOSTR_CASE(PM_STOP_BACKENDS); + PM_TOSTR_CASE(PM_WAIT_BACKENDS); + PM_TOSTR_CASE(PM_WAIT_XLOG_SHUTDOWN); + PM_TOSTR_CASE(PM_WAIT_XLOG_ARCHIVAL); + PM_TOSTR_CASE(PM_WAIT_IO_WORKERS); + PM_TOSTR_CASE(PM_WAIT_DEAD_END); + PM_TOSTR_CASE(PM_WAIT_CHECKPOINTER); + PM_TOSTR_CASE(PM_NO_CHILDREN); + } +#undef PM_TOSTR_CASE + + pg_unreachable(); + return ""; /* silence compiler */ +} + +/* + * Simple wrapper for updating pmState. The main reason to have this wrapper + * is that it makes it easy to log all state transitions. + */ +static void +UpdatePMState(PMState newState) +{ + elog(DEBUG1, "updating PMState from %s to %s", + pmstate_name(pmState), pmstate_name(newState)); + pmState = newState; +} + +/* + * Launch background processes after state change, or relaunch after an + * existing process has exited. + * + * Check the current pmState and the status of any background processes. If + * there are any background processes missing that should be running in the + * current state, but are not, launch them. + */ +static void +LaunchMissingBackgroundProcesses(void) +{ + /* Syslogger is active in all states */ + if (SysLoggerPMChild == NULL && Logging_collector) + StartSysLogger(); + + /* + * The number of configured workers might have changed, or a prior start + * of a worker might have failed. Check if we need to start/stop any + * workers. + * + * A config file change will always lead to this function being called, so + * we always will process the config change in a timely manner. + */ + maybe_adjust_io_workers(); + + /* + * The checkpointer and the background writer are active from the start, + * until shutdown is initiated. + * + * (If the checkpointer is not running when we enter the + * PM_WAIT_XLOG_SHUTDOWN state, it is launched one more time to perform + * the shutdown checkpoint. That's done in PostmasterStateMachine(), not + * here.) + */ + if (pmState == PM_RUN || pmState == PM_RECOVERY || + pmState == PM_HOT_STANDBY || pmState == PM_STARTUP) + { + if (CheckpointerPMChild == NULL) + CheckpointerPMChild = StartChildProcess(B_CHECKPOINTER); + if (BgWriterPMChild == NULL) + BgWriterPMChild = StartChildProcess(B_BG_WRITER); + } + + /* + * WAL writer is needed only in normal operation (else we cannot be + * writing any new WAL). + */ + if (WalWriterPMChild == NULL && pmState == PM_RUN) + WalWriterPMChild = StartChildProcess(B_WAL_WRITER); + + /* + * We don't want autovacuum to run in binary upgrade mode because + * autovacuum might update relfrozenxid for empty tables before the + * physical files are put in place. + */ + if (!IsBinaryUpgrade && AutoVacLauncherPMChild == NULL && + (AutoVacuumingActive() || start_autovac_launcher) && + pmState == PM_RUN) + { + AutoVacLauncherPMChild = StartChildProcess(B_AUTOVAC_LAUNCHER); + if (AutoVacLauncherPMChild != NULL) + start_autovac_launcher = false; /* signal processed */ + } + + /* + * If WAL archiving is enabled always, we are allowed to start archiver + * even during recovery. + */ + if (PgArchPMChild == NULL && + ((XLogArchivingActive() && pmState == PM_RUN) || + (XLogArchivingAlways() && (pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY))) && + PgArchCanRestart()) + PgArchPMChild = StartChildProcess(B_ARCHIVER); + + /* + * If we need to start a slot sync worker, try to do that now + * + * We allow to start the slot sync worker when we are on a hot standby, + * fast or immediate shutdown is not in progress, slot sync parameters are + * configured correctly, and it is the first time of worker's launch, or + * enough time has passed since the worker was launched last. + */ + if (SlotSyncWorkerPMChild == NULL && pmState == PM_HOT_STANDBY && + Shutdown <= SmartShutdown && sync_replication_slots && + ValidateSlotSyncParams(LOG) && SlotSyncWorkerCanRestart()) + SlotSyncWorkerPMChild = StartChildProcess(B_SLOTSYNC_WORKER); + + /* + * If we need to start a WAL receiver, try to do that now + * + * Note: if a walreceiver process is already running, it might seem that + * we should clear WalReceiverRequested. However, there's a race + * condition if the walreceiver terminates and the startup process + * immediately requests a new one: it's quite possible to get the signal + * for the request before reaping the dead walreceiver process. Better to + * risk launching an extra walreceiver than to miss launching one we need. + * (The walreceiver code has logic to recognize that it should go away if + * not needed.) + */ + if (WalReceiverRequested) + { + if (WalReceiverPMChild == NULL && + (pmState == PM_STARTUP || pmState == PM_RECOVERY || + pmState == PM_HOT_STANDBY) && + Shutdown <= SmartShutdown) + { + WalReceiverPMChild = StartChildProcess(B_WAL_RECEIVER); + if (WalReceiverPMChild != 0) + WalReceiverRequested = false; + /* else leave the flag set, so we'll try again later */ + } + } + + /* If we need to start a WAL summarizer, try to do that now */ + if (summarize_wal && WalSummarizerPMChild == NULL && + (pmState == PM_RUN || pmState == PM_HOT_STANDBY) && + Shutdown <= SmartShutdown) + WalSummarizerPMChild = StartChildProcess(B_WAL_SUMMARIZER); + + /* Get other worker processes running, if needed */ + if (StartWorkerNeeded || HaveCrashedWorker) + maybe_start_bgworkers(); +} + +/* + * Return string representation of signal. + * + * Because this is only implemented for signals we already rely on in this + * file we don't need to deal with unimplemented or same-numeric-value signals + * (as we'd e.g. have to for EWOULDBLOCK / EAGAIN). + */ +static const char * +pm_signame(int signal) +{ +#define PM_TOSTR_CASE(sym) case sym: return #sym + switch (signal) + { + PM_TOSTR_CASE(SIGABRT); + PM_TOSTR_CASE(SIGCHLD); + PM_TOSTR_CASE(SIGHUP); + PM_TOSTR_CASE(SIGINT); + PM_TOSTR_CASE(SIGKILL); + PM_TOSTR_CASE(SIGQUIT); + PM_TOSTR_CASE(SIGTERM); + PM_TOSTR_CASE(SIGUSR1); + PM_TOSTR_CASE(SIGUSR2); + default: + /* all signals sent by postmaster should be listed here */ + Assert(false); + return "(unknown)"; + } +#undef PM_TOSTR_CASE + + return ""; /* silence compiler */ +} /* * Send a signal to a postmaster child process @@ -3418,8 +3439,16 @@ PostmasterStateMachine(void) * child twice will not cause any problems. */ static void -signal_child(pid_t pid, int signal) +signal_child(PMChild *pmchild, int signal) { + pid_t pid = pmchild->pid; + + ereport(DEBUG3, + (errmsg_internal("sending signal %d/%s to %s process with pid %d", + signal, pm_signame(signal), + GetBackendTypeDesc(pmchild->bkend_type), + (int) pmchild->pid))); + if (kill(pid, signal) < 0) elog(DEBUG3, "kill(%ld,%d) failed: %m", (long) pid, signal); #ifdef HAVE_SETSID @@ -3440,62 +3469,34 @@ signal_child(pid_t pid, int signal) } /* - * Convenience function for killing a child process after a crash of some - * other child process. We log the action at a higher level than we would - * otherwise do, and we apply send_abort_for_crash to decide which signal - * to send. Normally it's SIGQUIT -- and most other comments in this file - * are written on the assumption that it is -- but developers might prefer - * to use SIGABRT to collect per-child core dumps. - */ -static void -sigquit_child(pid_t pid) -{ - ereport(DEBUG2, - (errmsg_internal("sending %s to process %d", - (send_abort_for_crash ? "SIGABRT" : "SIGQUIT"), - (int) pid))); - signal_child(pid, (send_abort_for_crash ? SIGABRT : SIGQUIT)); -} - -/* - * Send a signal to the targeted children (but NOT special children; - * dead_end children are never signaled, either). + * Send a signal to the targeted children. */ static bool -SignalSomeChildren(int signal, int target) +SignalChildren(int signal, BackendTypeMask targetMask) { dlist_iter iter; bool signaled = false; - dlist_foreach(iter, &BackendList) + dlist_foreach(iter, &ActiveChildList) { - Backend *bp = dlist_container(Backend, elem, iter.cur); - - if (bp->dead_end) - continue; + PMChild *bp = dlist_container(PMChild, elem, iter.cur); /* - * Since target == BACKEND_TYPE_ALL is the most common case, we test - * it first and avoid touching shared memory for every child. + * If we need to distinguish between B_BACKEND and B_WAL_SENDER, check + * if any B_BACKEND backends have recently announced that they are + * actually WAL senders. */ - if (target != BACKEND_TYPE_ALL) + if (btmask_contains(targetMask, B_WAL_SENDER) != btmask_contains(targetMask, B_BACKEND) && + bp->bkend_type == B_BACKEND) { - /* - * Assign bkend_type for any recently announced WAL Sender - * processes. - */ - if (bp->bkend_type == BACKEND_TYPE_NORMAL && - IsPostmasterChildWalSender(bp->child_slot)) - bp->bkend_type = BACKEND_TYPE_WALSND; - - if (!(target & bp->bkend_type)) - continue; + if (IsPostmasterChildWalSender(bp->child_slot)) + bp->bkend_type = B_WAL_SENDER; } - ereport(DEBUG4, - (errmsg_internal("sending signal %d to process %d", - signal, (int) bp->pid))); - signal_child(bp->pid, signal); + if (!btmask_contains(targetMask, bp->bkend_type)) + continue; + + signal_child(bp, signal); signaled = true; } return signaled; @@ -3503,34 +3504,17 @@ SignalSomeChildren(int signal, int target) /* * Send a termination signal to children. This considers all of our children - * processes, except syslogger and dead_end backends. + * processes, except syslogger. */ static void TerminateChildren(int signal) { - SignalChildren(signal); - if (StartupPID != 0) + SignalChildren(signal, btmask_all_except(B_LOGGER)); + if (StartupPMChild != NULL) { - signal_child(StartupPID, signal); if (signal == SIGQUIT || signal == SIGKILL || signal == SIGABRT) StartupStatus = STARTUP_SIGNALED; } - if (BgWriterPID != 0) - signal_child(BgWriterPID, signal); - if (CheckpointerPID != 0) - signal_child(CheckpointerPID, signal); - if (WalWriterPID != 0) - signal_child(WalWriterPID, signal); - if (WalReceiverPID != 0) - signal_child(WalReceiverPID, signal); - if (WalSummarizerPID != 0) - signal_child(WalSummarizerPID, signal); - if (AutoVacPID != 0) - signal_child(AutoVacPID, signal); - if (PgArchPID != 0) - signal_child(PgArchPID, signal); - if (SlotSyncWorkerPID != 0) - signal_child(SlotSyncWorkerPID, signal); } /* @@ -3538,69 +3522,70 @@ TerminateChildren(int signal) * * returns: STATUS_ERROR if the fork failed, STATUS_OK otherwise. * - * Note: if you change this code, also consider StartAutovacuumWorker. + * Note: if you change this code, also consider StartAutovacuumWorker and + * StartBackgroundWorker. */ static int BackendStartup(ClientSocket *client_sock) { - Backend *bn; /* for backend cleanup */ + PMChild *bn = NULL; pid_t pid; BackendStartupData startup_data; + CAC_state cac; /* - * Create backend data structure. Better before the fork() so we can - * handle failure cleanly. + * Capture time that Postmaster got a socket from accept (for logging + * connection establishment and setup total duration). */ - bn = (Backend *) palloc_extended(sizeof(Backend), MCXT_ALLOC_NO_OOM); - if (!bn) - { - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return STATUS_ERROR; - } + startup_data.socket_created = GetCurrentTimestamp(); /* - * Compute the cancel key that will be assigned to this backend. The - * backend will have its own copy in the forked-off process' value of - * MyCancelKey, so that it can transmit the key to the frontend. + * Allocate and assign the child slot. Note we must do this before + * forking, so that we can handle failures (out of memory or child-process + * slots) cleanly. */ - if (!RandomCancelKey(&MyCancelKey)) + cac = canAcceptConnections(B_BACKEND); + if (cac == CAC_OK) { - pfree(bn); - ereport(LOG, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate random cancel key"))); - return STATUS_ERROR; + /* Can change later to B_WAL_SENDER */ + bn = AssignPostmasterChildSlot(B_BACKEND); + if (!bn) + { + /* + * Too many regular child processes; launch a dead-end child + * process instead. + */ + cac = CAC_TOOMANY; + } + } + if (!bn) + { + bn = AllocDeadEndChild(); + if (!bn) + { + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + return STATUS_ERROR; + } } /* Pass down canAcceptConnections state */ - startup_data.canAcceptConnections = canAcceptConnections(BACKEND_TYPE_NORMAL); - bn->dead_end = (startup_data.canAcceptConnections != CAC_OK); - bn->cancel_key = MyCancelKey; - - /* - * Unless it's a dead_end child, assign it a child slot number - */ - if (!bn->dead_end) - bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); - else - bn->child_slot = 0; + startup_data.canAcceptConnections = cac; + bn->rw = NULL; /* Hasn't asked to be notified about any bgworkers yet */ bn->bgworker_notify = false; - pid = postmaster_child_launch(B_BACKEND, - (char *) &startup_data, sizeof(startup_data), + pid = postmaster_child_launch(bn->bkend_type, bn->child_slot, + &startup_data, sizeof(startup_data), client_sock); if (pid < 0) { /* in parent, fork failed */ int save_errno = errno; - if (!bn->dead_end) - (void) ReleasePostmasterChildSlot(bn->child_slot); - pfree(bn); + (void) ReleasePostmasterChildSlot(bn); errno = save_errno; ereport(LOG, (errmsg("could not fork new process for connection: %m"))); @@ -3610,7 +3595,8 @@ BackendStartup(ClientSocket *client_sock) /* in parent, successful fork */ ereport(DEBUG2, - (errmsg_internal("forked new backend, pid=%d socket=%d", + (errmsg_internal("forked new %s, pid=%d socket=%d", + GetBackendTypeDesc(bn->bkend_type), (int) pid, (int) client_sock->sock))); /* @@ -3618,14 +3604,6 @@ BackendStartup(ClientSocket *client_sock) * of backends. */ bn->pid = pid; - bn->bkend_type = BACKEND_TYPE_NORMAL; /* Can change later to WALSND */ - dlist_push_head(&BackendList, &bn->elem); - -#ifdef EXEC_BACKEND - if (!bn->dead_end) - ShmemBackendArrayAdd(bn); -#endif - return STATUS_OK; } @@ -3671,15 +3649,16 @@ ExitPostmaster(int status) /* * There is no known cause for a postmaster to become multithreaded after - * startup. Recheck to account for the possibility of unknown causes. + * startup. However, we might reach here via an error exit before + * reaching the test in PostmasterMain, so provide the same hint as there. * This message uses LOG level, because an unclean shutdown at this point * would usually not look much different from a clean shutdown. */ if (pthread_is_threaded_np() != 0) ereport(LOG, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg_internal("postmaster became multithreaded"), - errdetail("Please report this to <%s>.", PACKAGE_BUGREPORT))); + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("postmaster became multithreaded"), + errhint("Set the LC_ALL environment variable to a valid locale."))); #endif /* should cleanup shared memory and kill all backends */ @@ -3701,6 +3680,8 @@ ExitPostmaster(int status) static void process_pm_pmsignal(void) { + bool request_state_update = false; + pending_pm_pmsignal = false; ereport(DEBUG2, @@ -3718,14 +3699,15 @@ process_pm_pmsignal(void) /* WAL redo has started. We're out of reinitialization. */ FatalError = false; AbortStartTime = 0; + reachedConsistency = false; /* * Start the archiver if we're responsible for (re-)archiving received * files. */ - Assert(PgArchPID == 0); + Assert(PgArchPMChild == NULL); if (XLogArchivingAlways()) - PgArchPID = StartChildProcess(B_ARCHIVER); + PgArchPMChild = StartChildProcess(B_ARCHIVER); /* * If we aren't planning to enter hot standby mode later, treat @@ -3740,11 +3722,17 @@ process_pm_pmsignal(void) #endif } - pmState = PM_RECOVERY; + UpdatePMState(PM_RECOVERY); } - if (CheckPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY) && + if (CheckPostmasterSignal(PMSIGNAL_RECOVERY_CONSISTENT) && pmState == PM_RECOVERY && Shutdown == NoShutdown) + { + reachedConsistency = true; + } + + if (CheckPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY) && + (pmState == PM_RECOVERY && Shutdown == NoShutdown)) { ereport(LOG, (errmsg("database system is ready to accept read-only connections"))); @@ -3755,7 +3743,7 @@ process_pm_pmsignal(void) sd_notify(0, "READY=1"); #endif - pmState = PM_HOT_STANDBY; + UpdatePMState(PM_HOT_STANDBY); connsAllowed = true; /* Some workers may be scheduled to start now */ @@ -3770,20 +3758,17 @@ process_pm_pmsignal(void) StartWorkerNeeded = true; } - if (StartWorkerNeeded || HaveCrashedWorker) - maybe_start_bgworkers(); - /* Tell syslogger to rotate logfile if requested */ - if (SysLoggerPID != 0) + if (SysLoggerPMChild != NULL) { if (CheckLogrotateSignal()) { - signal_child(SysLoggerPID, SIGUSR1); + signal_child(SysLoggerPMChild, SIGUSR1); RemoveLogrotateSignalFiles(); } else if (CheckPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE)) { - signal_child(SysLoggerPID, SIGUSR1); + signal_child(SysLoggerPMChild, SIGUSR1); } } @@ -3812,14 +3797,70 @@ process_pm_pmsignal(void) if (CheckPostmasterSignal(PMSIGNAL_START_WALRECEIVER)) { /* Startup Process wants us to start the walreceiver process. */ - /* Start immediately if possible, else remember request for later. */ WalReceiverRequested = true; - MaybeStartWalReceiver(); + } + + if (CheckPostmasterSignal(PMSIGNAL_XLOG_IS_SHUTDOWN)) + { + /* Checkpointer completed the shutdown checkpoint */ + if (pmState == PM_WAIT_XLOG_SHUTDOWN) + { + /* + * If we have an archiver subprocess, tell it to do a last archive + * cycle and quit. Likewise, if we have walsender processes, tell + * them to send any remaining WAL and quit. + */ + Assert(Shutdown > NoShutdown); + + /* Waken archiver for the last time */ + if (PgArchPMChild != NULL) + signal_child(PgArchPMChild, SIGUSR2); + + /* + * Waken walsenders for the last time. No regular backends should + * be around anymore. + */ + SignalChildren(SIGUSR2, btmask(B_WAL_SENDER)); + + UpdatePMState(PM_WAIT_XLOG_ARCHIVAL); + } + else if (!FatalError && Shutdown != ImmediateShutdown) + { + /* + * Checkpointer only ought to perform the shutdown checkpoint + * during shutdown. If somehow checkpointer did so in another + * situation, we have no choice but to crash-restart. + * + * It's possible however that we get PMSIGNAL_XLOG_IS_SHUTDOWN + * outside of PM_WAIT_XLOG_SHUTDOWN if an orderly shutdown was + * "interrupted" by a crash or an immediate shutdown. + */ + ereport(LOG, + (errmsg("WAL was shut down unexpectedly"))); + + /* + * Doesn't seem likely to help to take send_abort_for_crash into + * account here. + */ + HandleFatalError(PMQUIT_FOR_CRASH, false); + } + + /* + * Need to run PostmasterStateMachine() to check if we already can go + * to the next state. + */ + request_state_update = true; } /* * Try to advance postmaster's state machine, if a child requests it. - * + */ + if (CheckPostmasterSignal(PMSIGNAL_ADVANCE_STATE_MACHINE)) + { + request_state_update = true; + } + + /* * Be careful about the order of this action relative to this function's * other actions. Generally, this should be after other actions, in case * they have effects PostmasterStateMachine would need to know about. @@ -3827,12 +3868,12 @@ process_pm_pmsignal(void) * cannot have any (immediate) effect on the state machine, but does * depend on what state we're in now. */ - if (CheckPostmasterSignal(PMSIGNAL_ADVANCE_STATE_MACHINE)) + if (request_state_update) { PostmasterStateMachine(); } - if (StartupPID != 0 && + if (StartupPMChild != NULL && (pmState == PM_STARTUP || pmState == PM_RECOVERY || pmState == PM_HOT_STANDBY) && CheckPromoteSignal()) @@ -3843,7 +3884,7 @@ process_pm_pmsignal(void) * Leave the promote signal file in place and let the Startup process * do the unlink. */ - signal_child(StartupPID, SIGUSR2); + signal_child(StartupPMChild, SIGUSR2); } } @@ -3862,49 +3903,37 @@ dummy_handler(SIGNAL_ARGS) } /* - * Generate a random cancel key. - */ -static bool -RandomCancelKey(int32 *cancel_key) -{ - return pg_strong_random(cancel_key, sizeof(int32)); -} - -/* - * Count up number of child processes of specified types (dead_end children - * are always excluded). + * Count up number of child processes of specified types. */ static int -CountChildren(int target) +CountChildren(BackendTypeMask targetMask) { dlist_iter iter; int cnt = 0; - dlist_foreach(iter, &BackendList) + dlist_foreach(iter, &ActiveChildList) { - Backend *bp = dlist_container(Backend, elem, iter.cur); - - if (bp->dead_end) - continue; + PMChild *bp = dlist_container(PMChild, elem, iter.cur); /* - * Since target == BACKEND_TYPE_ALL is the most common case, we test - * it first and avoid touching shared memory for every child. + * If we need to distinguish between B_BACKEND and B_WAL_SENDER, check + * if any B_BACKEND backends have recently announced that they are + * actually WAL senders. */ - if (target != BACKEND_TYPE_ALL) + if (btmask_contains(targetMask, B_WAL_SENDER) != btmask_contains(targetMask, B_BACKEND) && + bp->bkend_type == B_BACKEND) { - /* - * Assign bkend_type for any recently announced WAL Sender - * processes. - */ - if (bp->bkend_type == BACKEND_TYPE_NORMAL && - IsPostmasterChildWalSender(bp->child_slot)) - bp->bkend_type = BACKEND_TYPE_WALSND; - - if (!(target & bp->bkend_type)) - continue; + if (IsPostmasterChildWalSender(bp->child_slot)) + bp->bkend_type = B_WAL_SENDER; } + if (!btmask_contains(targetMask, bp->bkend_type)) + continue; + + ereport(DEBUG4, + (errmsg_internal("%s process %d is still running", + GetBackendTypeDesc(bp->bkend_type), (int) bp->pid))); + cnt++; } return cnt; @@ -3917,18 +3946,35 @@ CountChildren(int target) * "type" determines what kind of child will be started. All child types * initially go to AuxiliaryProcessMain, which will handle common setup. * - * Return value of StartChildProcess is subprocess' PID, or 0 if failed - * to start subprocess. + * Return value of StartChildProcess is subprocess' PMChild entry, or NULL on + * failure. */ -static pid_t +static PMChild * StartChildProcess(BackendType type) { + PMChild *pmchild; pid_t pid; - pid = postmaster_child_launch(type, NULL, 0, NULL); + pmchild = AssignPostmasterChildSlot(type); + if (!pmchild) + { + if (type == B_AUTOVAC_WORKER) + ereport(LOG, + (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), + errmsg("no slot available for new autovacuum worker process"))); + else + { + /* shouldn't happen because we allocate enough slots */ + elog(LOG, "no postmaster child slot available for aux process"); + } + return NULL; + } + + pid = postmaster_child_launch(type, pmchild->child_slot, NULL, 0, NULL); if (pid < 0) { /* in parent, fork failed */ + ReleasePostmasterChildSlot(pmchild); ereport(LOG, (errmsg("could not fork \"%s\" process: %m", PostmasterChildName(type)))); @@ -3938,13 +3984,31 @@ StartChildProcess(BackendType type) */ if (type == B_STARTUP) ExitPostmaster(1); - return 0; + return NULL; } - /* - * in parent, successful fork - */ - return pid; + /* in parent, successful fork */ + pmchild->pid = pid; + return pmchild; +} + +/* + * StartSysLogger -- start the syslogger process + */ +void +StartSysLogger(void) +{ + Assert(SysLoggerPMChild == NULL); + + SysLoggerPMChild = AssignPostmasterChildSlot(B_LOGGER); + if (!SysLoggerPMChild) + elog(PANIC, "no postmaster child slot available for syslogger"); + SysLoggerPMChild->pid = SysLogger_Start(SysLoggerPMChild->child_slot); + if (SysLoggerPMChild->pid == 0) + { + ReleasePostmasterChildSlot(SysLoggerPMChild); + SysLoggerPMChild = NULL; + } } /* @@ -3959,7 +4023,7 @@ StartChildProcess(BackendType type) static void StartAutovacuumWorker(void) { - Backend *bn; + PMChild *bn; /* * If not in condition to run a process, don't try, but handle it like a @@ -3968,55 +4032,22 @@ StartAutovacuumWorker(void) * we have to check to avoid race-condition problems during DB state * changes. */ - if (canAcceptConnections(BACKEND_TYPE_AUTOVAC) == CAC_OK) + if (canAcceptConnections(B_AUTOVAC_WORKER) == CAC_OK) { - /* - * Compute the cancel key that will be assigned to this session. We - * probably don't need cancel keys for autovac workers, but we'd - * better have something random in the field to prevent unfriendly - * people from sending cancels to them. - */ - if (!RandomCancelKey(&MyCancelKey)) + bn = StartChildProcess(B_AUTOVAC_WORKER); + if (bn) { - ereport(LOG, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate random cancel key"))); + bn->bgworker_notify = false; + bn->rw = NULL; return; } - - bn = (Backend *) palloc_extended(sizeof(Backend), MCXT_ALLOC_NO_OOM); - if (bn) + else { - bn->cancel_key = MyCancelKey; - - /* Autovac workers are not dead_end and need a child slot */ - bn->dead_end = false; - bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); - bn->bgworker_notify = false; - - bn->pid = StartChildProcess(B_AUTOVAC_WORKER); - if (bn->pid > 0) - { - bn->bkend_type = BACKEND_TYPE_AUTOVAC; - dlist_push_head(&BackendList, &bn->elem); -#ifdef EXEC_BACKEND - ShmemBackendArrayAdd(bn); -#endif - /* all OK */ - return; - } - /* * fork failed, fall through to report -- actual error message was * logged by StartChildProcess */ - (void) ReleasePostmasterChildSlot(bn->child_slot); - pfree(bn); } - else - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); } /* @@ -4028,71 +4059,13 @@ StartAutovacuumWorker(void) * quick succession between the autovac launcher and postmaster in case * things get ugly. */ - if (AutoVacPID != 0) + if (AutoVacLauncherPMChild != NULL) { AutoVacWorkerFailed(); avlauncher_needs_signal = true; } } -/* - * MaybeStartWalReceiver - * Start the WAL receiver process, if not running and our state allows. - * - * Note: if WalReceiverPID is already nonzero, it might seem that we should - * clear WalReceiverRequested. However, there's a race condition if the - * walreceiver terminates and the startup process immediately requests a new - * one: it's quite possible to get the signal for the request before reaping - * the dead walreceiver process. Better to risk launching an extra - * walreceiver than to miss launching one we need. (The walreceiver code - * has logic to recognize that it should go away if not needed.) - */ -static void -MaybeStartWalReceiver(void) -{ - if (WalReceiverPID == 0 && - (pmState == PM_STARTUP || pmState == PM_RECOVERY || - pmState == PM_HOT_STANDBY) && - Shutdown <= SmartShutdown) - { - WalReceiverPID = StartChildProcess(B_WAL_RECEIVER); - if (WalReceiverPID != 0) - WalReceiverRequested = false; - /* else leave the flag set, so we'll try again later */ - } -} - -/* - * MaybeStartWalSummarizer - * Start the WAL summarizer process, if not running and our state allows. - */ -static void -MaybeStartWalSummarizer(void) -{ - if (summarize_wal && WalSummarizerPID == 0 && - (pmState == PM_RUN || pmState == PM_HOT_STANDBY) && - Shutdown <= SmartShutdown) - WalSummarizerPID = StartChildProcess(B_WAL_SUMMARIZER); -} - - -/* - * MaybeStartSlotSyncWorker - * Start the slot sync worker, if not running and our state allows. - * - * We allow to start the slot sync worker when we are on a hot standby, - * fast or immediate shutdown is not in progress, slot sync parameters - * are configured correctly, and it is the first time of worker's launch, - * or enough time has passed since the worker was launched last. - */ -static void -MaybeStartSlotSyncWorker(void) -{ - if (SlotSyncWorkerPID == 0 && pmState == PM_HOT_STANDBY && - Shutdown <= SmartShutdown && sync_replication_slots && - ValidateSlotSyncParams(LOG) && SlotSyncWorkerCanRestart()) - SlotSyncWorkerPID = StartChildProcess(B_SLOTSYNC_WORKER); -} /* * Create the opts file @@ -4130,24 +4103,6 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname) } -/* - * MaxLivePostmasterChildren - * - * This reports the number of entries needed in per-child-process arrays - * (the PMChildFlags array, and if EXEC_BACKEND the ShmemBackendArray). - * These arrays include regular backends, autovac workers, walsenders - * and background workers, but not special children nor dead_end children. - * This allows the arrays to have a fixed maximum size, to wit the same - * too-many-children limit enforced by canAcceptConnections(). The exact value - * isn't too critical as long as it's more than MaxBackends. - */ -int -MaxLivePostmasterChildren(void) -{ - return 2 * (MaxConnections + autovacuum_max_workers + 1 + - max_wal_senders + max_worker_processes); -} - /* * Start a new bgworker. * Starting time conditions must have been checked already. @@ -4155,17 +4110,18 @@ MaxLivePostmasterChildren(void) * Returns true on success, false on failure. * In either case, update the RegisteredBgWorker's state appropriately. * - * This code is heavily based on autovacuum.c, q.v. + * NB -- this code very roughly matches BackendStartup. */ static bool -do_start_bgworker(RegisteredBgWorker *rw) +StartBackgroundWorker(RegisteredBgWorker *rw) { + PMChild *bn; pid_t worker_pid; Assert(rw->rw_pid == 0); /* - * Allocate and assign the Backend element. Note we must do this before + * Allocate and assign the child slot. Note we must do this before * forking, so that we can handle failures (out of memory or child-process * slots) cleanly. * @@ -4174,27 +4130,33 @@ do_start_bgworker(RegisteredBgWorker *rw) * tried again right away, most likely we'd find ourselves hitting the * same resource-exhaustion condition. */ - if (!assign_backendlist_entry(rw)) + bn = AssignPostmasterChildSlot(B_BG_WORKER); + if (bn == NULL) { + ereport(LOG, + (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), + errmsg("no slot available for new background worker process"))); rw->rw_crashed_at = GetCurrentTimestamp(); return false; } + bn->rw = rw; + bn->bkend_type = B_BG_WORKER; + bn->bgworker_notify = false; ereport(DEBUG1, (errmsg_internal("starting background worker process \"%s\"", rw->rw_worker.bgw_name))); - worker_pid = postmaster_child_launch(B_BG_WORKER, (char *) &rw->rw_worker, sizeof(BackgroundWorker), NULL); + worker_pid = postmaster_child_launch(B_BG_WORKER, bn->child_slot, + &rw->rw_worker, sizeof(BackgroundWorker), NULL); if (worker_pid == -1) { /* in postmaster, fork failed ... */ ereport(LOG, (errmsg("could not fork background worker process: %m"))); - /* undo what assign_backendlist_entry did */ - ReleasePostmasterChildSlot(rw->rw_child_slot); - rw->rw_child_slot = 0; - pfree(rw->rw_backend); - rw->rw_backend = NULL; + /* undo what AssignPostmasterChildSlot did */ + ReleasePostmasterChildSlot(bn); + /* mark entry as crashed, so we'll try again later */ rw->rw_crashed_at = GetCurrentTimestamp(); return false; @@ -4202,13 +4164,8 @@ do_start_bgworker(RegisteredBgWorker *rw) /* in postmaster, fork successful ... */ rw->rw_pid = worker_pid; - rw->rw_backend->pid = rw->rw_pid; + bn->pid = rw->rw_pid; ReportBackgroundWorkerPID(rw); - /* add new worker to lists of backends */ - dlist_push_head(&BackendList, &rw->rw_backend->elem); -#ifdef EXEC_BACKEND - ShmemBackendArrayAdd(rw->rw_backend); -#endif return true; } @@ -4222,9 +4179,11 @@ bgworker_should_start_now(BgWorkerStartTime start_time) switch (pmState) { case PM_NO_CHILDREN: + case PM_WAIT_CHECKPOINTER: case PM_WAIT_DEAD_END: - case PM_SHUTDOWN_2: - case PM_SHUTDOWN: + case PM_WAIT_XLOG_ARCHIVAL: + case PM_WAIT_XLOG_SHUTDOWN: + case PM_WAIT_IO_WORKERS: case PM_WAIT_BACKENDS: case PM_STOP_BACKENDS: break; @@ -4250,67 +4209,6 @@ bgworker_should_start_now(BgWorkerStartTime start_time) return false; } -/* - * Allocate the Backend struct for a connected background worker, but don't - * add it to the list of backends just yet. - * - * On failure, return false without changing any worker state. - * - * Some info from the Backend is copied into the passed rw. - */ -static bool -assign_backendlist_entry(RegisteredBgWorker *rw) -{ - Backend *bn; - - /* - * Check that database state allows another connection. Currently the - * only possible failure is CAC_TOOMANY, so we just log an error message - * based on that rather than checking the error code precisely. - */ - if (canAcceptConnections(BACKEND_TYPE_BGWORKER) != CAC_OK) - { - ereport(LOG, - (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), - errmsg("no slot available for new background worker process"))); - return false; - } - - /* - * Compute the cancel key that will be assigned to this session. We - * probably don't need cancel keys for background workers, but we'd better - * have something random in the field to prevent unfriendly people from - * sending cancels to them. - */ - if (!RandomCancelKey(&MyCancelKey)) - { - ereport(LOG, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("could not generate random cancel key"))); - return false; - } - - bn = palloc_extended(sizeof(Backend), MCXT_ALLOC_NO_OOM); - if (bn == NULL) - { - ereport(LOG, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return false; - } - - bn->cancel_key = MyCancelKey; - bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); - bn->bkend_type = BACKEND_TYPE_BGWORKER; - bn->dead_end = false; - bn->bgworker_notify = false; - - rw->rw_backend = bn; - rw->rw_child_slot = bn->child_slot; - - return true; -} - /* * If the time is right, start background worker(s). * @@ -4328,7 +4226,7 @@ maybe_start_bgworkers(void) #define MAX_BGWORKERS_TO_LAUNCH 100 int num_launched = 0; TimestampTz now = 0; - slist_mutable_iter iter; + dlist_mutable_iter iter; /* * During crash recovery, we have no need to be called until the state @@ -4345,11 +4243,11 @@ maybe_start_bgworkers(void) StartWorkerNeeded = false; HaveCrashedWorker = false; - slist_foreach_modify(iter, &BackgroundWorkerList) + dlist_foreach_modify(iter, &BackgroundWorkerList) { RegisteredBgWorker *rw; - rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur); + rw = dlist_container(RegisteredBgWorker, rw_lnode, iter.cur); /* ignore if already running */ if (rw->rw_pid != 0) @@ -4358,7 +4256,7 @@ maybe_start_bgworkers(void) /* if marked for death, clean up and remove from list */ if (rw->rw_terminate) { - ForgetBackgroundWorker(&iter); + ForgetBackgroundWorker(rw); continue; } @@ -4377,7 +4275,7 @@ maybe_start_bgworkers(void) notify_pid = rw->rw_worker.bgw_notify_pid; - ForgetBackgroundWorker(&iter); + ForgetBackgroundWorker(rw); /* Report worker is gone now. */ if (notify_pid != 0) @@ -4415,7 +4313,7 @@ maybe_start_bgworkers(void) * crashed, but there's no need because the next run of this * function will do that. */ - if (!do_start_bgworker(rw)) + if (!StartBackgroundWorker(rw)) { StartWorkerNeeded = true; return; @@ -4436,68 +4334,121 @@ maybe_start_bgworkers(void) } } -/* - * When a backend asks to be notified about worker state changes, we - * set a flag in its backend entry. The background worker machinery needs - * to know when such backends exit. - */ -bool -PostmasterMarkPIDForWorkerNotify(int pid) +static bool +maybe_reap_io_worker(int pid) { - dlist_iter iter; - Backend *bp; - - dlist_foreach(iter, &BackendList) + for (int id = 0; id < MAX_IO_WORKERS; ++id) { - bp = dlist_container(Backend, elem, iter.cur); - if (bp->pid == pid) + if (io_worker_children[id] && + io_worker_children[id]->pid == pid) { - bp->bgworker_notify = true; + ReleasePostmasterChildSlot(io_worker_children[id]); + + --io_worker_count; + io_worker_children[id] = NULL; return true; } } return false; } -#ifdef EXEC_BACKEND - -Size -ShmemBackendArraySize(void) +/* + * Start or stop IO workers, to close the gap between the number of running + * workers and the number of configured workers. Used to respond to change of + * the io_workers GUC (by increasing and decreasing the number of workers), as + * well as workers terminating in response to errors (by starting + * "replacement" workers). + */ +static void +maybe_adjust_io_workers(void) { - return mul_size(MaxLivePostmasterChildren(), sizeof(Backend)); -} + if (!pgaio_workers_enabled()) + return; -void -ShmemBackendArrayAllocation(void) -{ - Size size = ShmemBackendArraySize(); + /* + * If we're in final shutting down state, then we're just waiting for all + * processes to exit. + */ + if (pmState >= PM_WAIT_IO_WORKERS) + return; - ShmemBackendArray = (Backend *) ShmemAlloc(size); - /* Mark all slots as empty */ - memset(ShmemBackendArray, 0, size); -} + /* Don't start new workers during an immediate shutdown either. */ + if (Shutdown >= ImmediateShutdown) + return; -static void -ShmemBackendArrayAdd(Backend *bn) -{ - /* The array slot corresponding to my PMChildSlot should be free */ - int i = bn->child_slot - 1; + /* + * Don't start new workers if we're in the shutdown phase of a crash + * restart. But we *do* need to start if we're already starting up again. + */ + if (FatalError && pmState >= PM_STOP_BACKENDS) + return; + + Assert(pmState < PM_WAIT_IO_WORKERS); + + /* Not enough running? */ + while (io_worker_count < io_workers) + { + PMChild *child; + int id; + + /* find unused entry in io_worker_children array */ + for (id = 0; id < MAX_IO_WORKERS; ++id) + { + if (io_worker_children[id] == NULL) + break; + } + if (id == MAX_IO_WORKERS) + elog(ERROR, "could not find a free IO worker ID"); - Assert(ShmemBackendArray[i].pid == 0); - ShmemBackendArray[i] = *bn; + /* Try to launch one. */ + child = StartChildProcess(B_IO_WORKER); + if (child != NULL) + { + io_worker_children[id] = child; + ++io_worker_count; + } + else + break; /* try again next time */ + } + + /* Too many running? */ + if (io_worker_count > io_workers) + { + /* ask the IO worker in the highest slot to exit */ + for (int id = MAX_IO_WORKERS - 1; id >= 0; --id) + { + if (io_worker_children[id] != NULL) + { + kill(io_worker_children[id]->pid, SIGUSR2); + break; + } + } + } } -static void -ShmemBackendArrayRemove(Backend *bn) + +/* + * When a backend asks to be notified about worker state changes, we + * set a flag in its backend entry. The background worker machinery needs + * to know when such backends exit. + */ +bool +PostmasterMarkPIDForWorkerNotify(int pid) { - int i = bn->child_slot - 1; + dlist_iter iter; + PMChild *bp; - Assert(ShmemBackendArray[i].pid == bn->pid); - /* Mark the slot as empty */ - ShmemBackendArray[i].pid = 0; + dlist_foreach(iter, &ActiveChildList) + { + bp = dlist_container(PMChild, elem, iter.cur); + if (bp->pid == pid) + { + bp->bgworker_notify = true; + return true; + } + } + return false; } -#endif /* EXEC_BACKEND */ - #ifdef WIN32 diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index ef6f98ebcd794..27e86cf393f6f 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -9,7 +9,7 @@ * though.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -38,7 +38,7 @@ #ifndef USE_POSTMASTER_DEATH_SIGNAL /* * On systems that need to make a system call to find out if the postmaster has - * gone away, we'll do so only every Nth call to HandleStartupProcInterrupts(). + * gone away, we'll do so only every Nth call to ProcessStartupProcInterrupts(). * This only affects how long it takes us to detect the condition while we're * busy replaying WAL. Latch waits and similar which should react immediately * through the usual techniques. @@ -149,9 +149,9 @@ StartupRereadConfig(void) StartupRequestWalReceiverRestart(); } -/* Handle various signals that might be sent to the startup process */ +/* Process various signals that might be sent to the startup process */ void -HandleStartupProcInterrupts(void) +ProcessStartupProcInterrupts(void) { #ifdef POSTMASTER_POLL_RATE_LIMIT static uint32 postmaster_poll_count = 0; @@ -213,7 +213,7 @@ StartupProcExit(int code, Datum arg) * ---------------------------------- */ void -StartupProcessMain(char *startup_data, size_t startup_data_len) +StartupProcessMain(const void *startup_data, size_t startup_data_len) { Assert(startup_data_len == 0); diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 7951599fa87be..50c2edec1f611 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -13,7 +13,7 @@ * * Author: Andreas Pflug * - * Copyright (c) 2004-2024, PostgreSQL Global Development Group + * Copyright (c) 2004-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -162,7 +162,7 @@ typedef struct * argc/argv parameters are valid only in EXEC_BACKEND case. */ void -SysLoggerMain(char *startup_data, size_t startup_data_len) +SysLoggerMain(const void *startup_data, size_t startup_data_len) { #ifndef WIN32 char logbuffer[READ_BUF_SIZE]; @@ -183,7 +183,7 @@ SysLoggerMain(char *startup_data, size_t startup_data_len) */ #ifdef EXEC_BACKEND { - SysloggerStartupData *slsdata = (SysloggerStartupData *) startup_data; + const SysloggerStartupData *slsdata = startup_data; Assert(startup_data_len == sizeof(*slsdata)); syslogFile = syslogger_fdopen(slsdata->syslogFile); @@ -444,19 +444,19 @@ SysLoggerMain(char *startup_data, size_t startup_data_len) if (!rotation_requested && Log_RotationSize > 0 && !rotation_disabled) { /* Do a rotation if file is too big */ - if (ftell(syslogFile) >= Log_RotationSize * 1024L) + if (ftello(syslogFile) >= Log_RotationSize * (pgoff_t) 1024) { rotation_requested = true; size_rotation_for |= LOG_DESTINATION_STDERR; } if (csvlogFile != NULL && - ftell(csvlogFile) >= Log_RotationSize * 1024L) + ftello(csvlogFile) >= Log_RotationSize * (pgoff_t) 1024) { rotation_requested = true; size_rotation_for |= LOG_DESTINATION_CSVLOG; } if (jsonlogFile != NULL && - ftell(jsonlogFile) >= Log_RotationSize * 1024L) + ftello(jsonlogFile) >= Log_RotationSize * (pgoff_t) 1024) { rotation_requested = true; size_rotation_for |= LOG_DESTINATION_JSONLOG; @@ -590,7 +590,7 @@ SysLoggerMain(char *startup_data, size_t startup_data_len) * Postmaster subroutine to start a syslogger subprocess. */ int -SysLogger_Start(void) +SysLogger_Start(int child_slot) { pid_t sysloggerPid; char *filename; @@ -598,8 +598,7 @@ SysLogger_Start(void) SysloggerStartupData startup_data; #endif /* EXEC_BACKEND */ - if (!Logging_collector) - return 0; + Assert(Logging_collector); /* * If first time through, create the pipe which will receive stderr @@ -699,9 +698,11 @@ SysLogger_Start(void) startup_data.syslogFile = syslogger_fdget(syslogFile); startup_data.csvlogFile = syslogger_fdget(csvlogFile); startup_data.jsonlogFile = syslogger_fdget(jsonlogFile); - sysloggerPid = postmaster_child_launch(B_LOGGER, (char *) &startup_data, sizeof(startup_data), NULL); + sysloggerPid = postmaster_child_launch(B_LOGGER, child_slot, + &startup_data, sizeof(startup_data), NULL); #else - sysloggerPid = postmaster_child_launch(B_LOGGER, NULL, 0, NULL); + sysloggerPid = postmaster_child_launch(B_LOGGER, child_slot, + NULL, 0, NULL); #endif /* EXEC_BACKEND */ if (sysloggerPid == -1) @@ -1182,9 +1183,11 @@ pipeThread(void *arg) */ if (Log_RotationSize > 0) { - if (ftell(syslogFile) >= Log_RotationSize * 1024L || - (csvlogFile != NULL && ftell(csvlogFile) >= Log_RotationSize * 1024L) || - (jsonlogFile != NULL && ftell(jsonlogFile) >= Log_RotationSize * 1024L)) + if (ftello(syslogFile) >= Log_RotationSize * (pgoff_t) 1024 || + (csvlogFile != NULL && + ftello(csvlogFile) >= Log_RotationSize * (pgoff_t) 1024) || + (jsonlogFile != NULL && + ftello(jsonlogFile) >= Log_RotationSize * (pgoff_t) 1024)) SetLatch(MyLatch); } LeaveCriticalSection(&sysloggerSection); diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c index b62e2c36de901..0fec4f1f871ce 100644 --- a/src/backend/postmaster/walsummarizer.c +++ b/src/backend/postmaster/walsummarizer.c @@ -13,7 +13,7 @@ * summary files when the file timestamp is older than a configurable * threshold (but only if the WAL has been removed first). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/postmaster/walsummarizer.c @@ -33,10 +33,12 @@ #include "common/blkreftable.h" #include "libpq/pqsignal.h" #include "miscadmin.h" +#include "pgstat.h" #include "postmaster/auxprocess.h" #include "postmaster/interrupt.h" #include "postmaster/walsummarizer.h" #include "replication/walreceiver.h" +#include "storage/aio_subsys.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/latch.h" @@ -144,7 +146,7 @@ int wal_summary_keep_time = 10 * HOURS_PER_DAY * MINS_PER_HOUR; static void WalSummarizerShutdown(int code, Datum arg); static XLogRecPtr GetLatestLSN(TimeLineID *tli); -static void HandleWalSummarizerInterrupts(void); +static void ProcessWalSummarizerInterrupts(void); static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, XLogRecPtr switch_lsn, XLogRecPtr maximum_lsn); @@ -208,7 +210,7 @@ WalSummarizerShmemInit(void) * Entry point for walsummarizer process. */ void -WalSummarizerMain(char *startup_data, size_t startup_data_len) +WalSummarizerMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; MemoryContext context; @@ -288,6 +290,7 @@ WalSummarizerMain(char *startup_data, size_t startup_data_len) LWLockReleaseAll(); ConditionVariableCancelSleep(); pgstat_report_wait_end(); + pgaio_error_cleanup(); ReleaseAuxProcessResources(false); AtEOXact_Files(false); AtEOXact_HashTables(false); @@ -315,7 +318,7 @@ WalSummarizerMain(char *startup_data, size_t startup_data_len) * So a really fast retry time doesn't seem to be especially * beneficial, and it will clutter the logs. */ - (void) WaitLatch(MyLatch, + (void) WaitLatch(NULL, WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, 10000, WAIT_EVENT_WAL_SUMMARIZER_ERROR); @@ -355,7 +358,7 @@ WalSummarizerMain(char *startup_data, size_t startup_data_len) MemoryContextReset(context); /* Process any signals received recently. */ - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); /* If it's time to remove any old WAL summaries, do that now. */ MaybeRemoveOldWalSummaries(); @@ -382,8 +385,8 @@ WalSummarizerMain(char *startup_data, size_t startup_data_len) switch_lsn = tliSwitchPoint(current_tli, tles, &switch_tli); ereport(DEBUG1, - errmsg("switch point from TLI %u to TLI %u is at %X/%X", - current_tli, switch_tli, LSN_FORMAT_ARGS(switch_lsn))); + errmsg_internal("switch point from TLI %u to TLI %u is at %X/%X", + current_tli, switch_tli, LSN_FORMAT_ARGS(switch_lsn))); } /* @@ -626,7 +629,7 @@ GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact) } /* - * Attempt to set the WAL summarizer's latch. + * Wake up the WAL summarizer process. * * This might not work, because there's no guarantee that the WAL summarizer * process was successfully started, and it also might have started but @@ -634,7 +637,7 @@ GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact) * latch set, but there's no guarantee. */ void -SetWalSummarizerLatch(void) +WakeupWalSummarizer(void) { ProcNumber pgprocno; @@ -752,9 +755,11 @@ WaitForWalSummarization(XLogRecPtr lsn) current_time) / 1000; ereport(WARNING, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("still waiting for WAL summarization through %X/%X after %ld seconds", - LSN_FORMAT_ARGS(lsn), - elapsed_seconds), + errmsg_plural("still waiting for WAL summarization through %X/%X after %ld second", + "still waiting for WAL summarization through %X/%X after %ld seconds", + elapsed_seconds, + LSN_FORMAT_ARGS(lsn), + elapsed_seconds), errdetail("Summarization has reached %X/%X on disk and %X/%X in memory.", LSN_FORMAT_ARGS(summarized_lsn), LSN_FORMAT_ARGS(pending_lsn)))); @@ -853,7 +858,7 @@ GetLatestLSN(TimeLineID *tli) * Interrupt handler for main loop of WAL summarizer process. */ static void -HandleWalSummarizerInterrupts(void) +ProcessWalSummarizerInterrupts(void) { if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); @@ -1013,7 +1018,7 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, XLogRecord *record; uint8 rmid; - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); /* We shouldn't go backward. */ Assert(summary_start_lsn <= xlogreader->EndRecPtr); @@ -1217,10 +1222,10 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, /* Tell the user what we did. */ ereport(DEBUG1, - errmsg("summarized WAL on TLI %u from %X/%X to %X/%X", - tli, - LSN_FORMAT_ARGS(summary_start_lsn), - LSN_FORMAT_ARGS(summary_end_lsn))); + errmsg_internal("summarized WAL on TLI %u from %X/%X to %X/%X", + tli, + LSN_FORMAT_ARGS(summary_start_lsn), + LSN_FORMAT_ARGS(summary_end_lsn))); /* Durably rename the new summary into place. */ durable_rename(temp_path, final_path, ERROR); @@ -1229,10 +1234,10 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, /* If we skipped a non-zero amount of WAL, log a debug message. */ if (summary_end_lsn > summary_start_lsn && fast_forward) ereport(DEBUG1, - errmsg("skipped summarizing WAL on TLI %u from %X/%X to %X/%X", - tli, - LSN_FORMAT_ARGS(summary_start_lsn), - LSN_FORMAT_ARGS(summary_end_lsn))); + errmsg_internal("skipped summarizing WAL on TLI %u from %X/%X to %X/%X", + tli, + LSN_FORMAT_ARGS(summary_start_lsn), + LSN_FORMAT_ARGS(summary_end_lsn))); return summary_end_lsn; } @@ -1500,7 +1505,7 @@ summarizer_read_local_xlog_page(XLogReaderState *state, WALReadError errinfo; SummarizerReadLocalXLogPrivate *private_data; - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); private_data = (SummarizerReadLocalXLogPrivate *) state->private_data; @@ -1538,7 +1543,7 @@ summarizer_read_local_xlog_page(XLogReaderState *state, * current timeline, so more data might show up. Delay here * so we don't tight-loop. */ - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); summarizer_wait_for_wal(); /* Recheck end-of-WAL. */ @@ -1575,8 +1580,8 @@ summarizer_read_local_xlog_page(XLogReaderState *state, /* Debugging output. */ ereport(DEBUG1, - errmsg("timeline %u became historic, can read up to %X/%X", - private_data->tli, LSN_FORMAT_ARGS(private_data->read_upto))); + errmsg_internal("timeline %u became historic, can read up to %X/%X", + private_data->tli, LSN_FORMAT_ARGS(private_data->read_upto))); } /* Go around and try again. */ @@ -1634,6 +1639,9 @@ summarizer_wait_for_wal(void) sleep_quanta -= pages_read_since_last_sleep; } + /* Report pending statistics to the cumulative stats system. */ + pgstat_report_wal(false); + /* OK, now sleep. */ (void) WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, @@ -1686,7 +1694,7 @@ MaybeRemoveOldWalSummaries(void) XLogRecPtr oldest_lsn = InvalidXLogRecPtr; TimeLineID selected_tli; - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); /* * Pick a timeline for which some summary files still exist on disk, @@ -1705,7 +1713,7 @@ MaybeRemoveOldWalSummaries(void) { WalSummaryFile *ws = lfirst(lc); - HandleWalSummarizerInterrupts(); + ProcessWalSummarizerInterrupts(); /* If it's not on this timeline, it's not time to consider it. */ if (selected_tli != ws->tli) diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 6e7918a78d478..fd92c8b7a33e1 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -31,7 +31,7 @@ * should be killed by SIGQUIT and then a recovery cycle started. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -51,15 +51,14 @@ #include "postmaster/auxprocess.h" #include "postmaster/interrupt.h" #include "postmaster/walwriter.h" +#include "storage/aio_subsys.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" #include "storage/fd.h" -#include "storage/ipc.h" #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/procsignal.h" #include "storage/smgr.h" -#include "utils/guc.h" #include "utils/hsearch.h" #include "utils/memutils.h" #include "utils/resowner.h" @@ -86,7 +85,7 @@ int WalWriterFlushAfter = DEFAULT_WAL_WRITER_FLUSH_AFTER; * basic execution environment, but not enabled signals yet. */ void -WalWriterMain(char *startup_data, size_t startup_data_len) +WalWriterMain(const void *startup_data, size_t startup_data_len) { sigjmp_buf local_sigjmp_buf; MemoryContext walwriter_context; @@ -166,6 +165,7 @@ WalWriterMain(char *startup_data, size_t startup_data_len) LWLockReleaseAll(); ConditionVariableCancelSleep(); pgstat_report_wait_end(); + pgaio_error_cleanup(); UnlockBuffers(); ReleaseAuxProcessResources(false); AtEOXact_Buffers(false); @@ -210,10 +210,10 @@ WalWriterMain(char *startup_data, size_t startup_data_len) SetWalWriterSleeping(false); /* - * Advertise our latch that backends can use to wake us up while we're - * sleeping. + * Advertise our proc number that backends can use to wake us up while + * we're sleeping. */ - ProcGlobal->walwriterLatch = &MyProc->procLatch; + ProcGlobal->walwriterProc = MyProcNumber; /* * Loop forever @@ -241,7 +241,7 @@ WalWriterMain(char *startup_data, size_t startup_data_len) ResetLatch(MyLatch); /* Process any signals received recently */ - HandleMainLoopInterrupts(); + ProcessMainLoopInterrupts(); /* * Do what we're here for; then, if XLogBackgroundFlush() found useful diff --git a/src/backend/regex/meson.build b/src/backend/regex/meson.build index 1f7dcfb7a8ffa..8bcd195b42abd 100644 --- a/src/backend/regex/meson.build +++ b/src/backend/regex/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'regcomp.c', diff --git a/src/backend/regex/regc_color.c b/src/backend/regex/regc_color.c index 30bda0e5ad0ff..8ae788f519561 100644 --- a/src/backend/regex/regc_color.c +++ b/src/backend/regex/regc_color.c @@ -1075,9 +1075,19 @@ colorcomplement(struct nfa *nfa, assert(of != from); - /* A RAINBOW arc matches all colors, making the complement empty */ + /* + * A RAINBOW arc matches all colors, making the complement empty. But we + * can't just return without making any arcs, because that would leave the + * NFA disconnected which would break any future delsub(). Instead, make + * a CANTMATCH arc. Also set the HASCANTMATCH flag so we know we need to + * clean that up at the start of NFA optimization. + */ if (findarc(of, PLAIN, RAINBOW) != NULL) + { + newarc(nfa, CANTMATCH, 0, from, to); + nfa->flags |= HASCANTMATCH; return; + } /* Otherwise, transiently mark the colors that appear in of's out-arcs */ for (a = of->outs; a != NULL; a = a->outchain) @@ -1089,6 +1099,12 @@ colorcomplement(struct nfa *nfa, assert(!UNUSEDCOLOR(cd)); cd->flags |= COLMARK; } + + /* + * There's no syntax for re-complementing a color set, so we cannot + * see CANTMATCH arcs here. + */ + assert(a->type != CANTMATCH); } /* Scan colors, clear transient marks, add arcs for unmarked colors */ diff --git a/src/backend/regex/regc_nfa.c b/src/backend/regex/regc_nfa.c index f1819a24f6d32..acd2286defd50 100644 --- a/src/backend/regex/regc_nfa.c +++ b/src/backend/regex/regc_nfa.c @@ -1462,6 +1462,7 @@ removetraverse(struct nfa *nfa, { case PLAIN: case EMPTY: + case CANTMATCH: /* nothing to do */ break; case AHEAD: @@ -1599,6 +1600,12 @@ optimize(struct nfa *nfa, if (verbose) fprintf(f, "\ninitial cleanup:\n"); #endif + /* If we have any CANTMATCH arcs, drop them; but this is uncommon */ + if (nfa->flags & HASCANTMATCH) + { + removecantmatch(nfa); + nfa->flags &= ~HASCANTMATCH; + } cleanup(nfa); /* may simplify situation */ #ifdef REG_DEBUG if (verbose) @@ -2922,6 +2929,34 @@ clonesuccessorstates(struct nfa *nfa, } } +/* + * removecantmatch - remove CANTMATCH arcs, which are no longer useful + * once we are done with the parsing phase. (We need them only to + * preserve connectedness of NFA subgraphs during parsing.) + */ +static void +removecantmatch(struct nfa *nfa) +{ + struct state *s; + + for (s = nfa->states; s != NULL; s = s->next) + { + struct arc *a; + struct arc *nexta; + + for (a = s->outs; a != NULL; a = nexta) + { + nexta = a->outchain; + if (a->type == CANTMATCH) + { + freearc(nfa, a); + if (NISERR()) + return; + } + } + } +} + /* * cleanup - clean up NFA after optimizations */ @@ -3627,6 +3662,8 @@ dumpnfa(struct nfa *nfa, fprintf(f, ", eol [%ld]", (long) nfa->eos[1]); if (nfa->flags & HASLACONS) fprintf(f, ", haslacons"); + if (nfa->flags & HASCANTMATCH) + fprintf(f, ", hascantmatch"); if (nfa->flags & MATCHALL) { fprintf(f, ", minmatchall %d", nfa->minmatchall); @@ -3749,6 +3786,9 @@ dumparc(struct arc *a, break; case EMPTY: break; + case CANTMATCH: + fprintf(f, "X"); + break; default: fprintf(f, "0x%x/0%lo", a->type, (long) a->co); break; diff --git a/src/backend/regex/regc_pg_locale.c b/src/backend/regex/regc_pg_locale.c index 85f3238eb071a..78193cfb964e5 100644 --- a/src/backend/regex/regc_pg_locale.c +++ b/src/backend/regex/regc_pg_locale.c @@ -6,7 +6,7 @@ * * This file is #included by regcomp.c; it's not meant to compile standalone. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -21,22 +21,22 @@ #include "utils/pg_locale.h" /* - * To provide as much functionality as possible on a variety of platforms, - * without going so far as to implement everything from scratch, we use - * several implementation strategies depending on the situation: + * For the libc provider, to provide as much functionality as possible on a + * variety of platforms without going so far as to implement everything from + * scratch, we use several implementation strategies depending on the + * situation: * * 1. In C/POSIX collations, we use hard-wired code. We can't depend on * the functions since those will obey LC_CTYPE. Note that these * collations don't give a fig about multibyte characters. * - * 2. In the "default" collation (which is supposed to obey LC_CTYPE): - * - * 2a. When working in UTF8 encoding, we use the functions. + * 2. When working in UTF8 encoding, we use the functions. * This assumes that every platform uses Unicode codepoints directly - * as the wchar_t representation of Unicode. On some platforms + * as the wchar_t representation of Unicode. (XXX: ICU makes this assumption + * even for non-UTF8 encodings, which may be a problem.) On some platforms * wchar_t is only 16 bits wide, so we have to punt for codepoints > 0xFFFF. * - * 2b. In all other encodings, we use the functions for pg_wchar + * 3. In all other encodings, we use the functions for pg_wchar * values up to 255, and punt for values above that. This is 100% correct * only in single-byte encodings such as LATINn. However, non-Unicode * multibyte encodings are mostly Far Eastern character sets for which the @@ -46,14 +46,11 @@ * the platform's wchar_t representation matches what we do in pg_wchar * conversions. * - * 3. Here, we use the locale_t-extended forms of the and - * functions, under exactly the same cases as #2. - * - * There is one notable difference between cases 2 and 3: in the "default" - * collation we force ASCII letters to follow ASCII upcase/downcase rules, - * while in a non-default collation we just let the library functions do what - * they will. The case where this matters is treatment of I/i in Turkish, - * and the behavior is meant to match the upper()/lower() SQL functions. + * As a special case, in the "default" collation, (2) and (3) force ASCII + * letters to follow ASCII upcase/downcase rules, while in a non-default + * collation we just let the library functions do what they will. The case + * where this matters is treatment of I/i in Turkish, and the behavior is + * meant to match the upper()/lower() SQL functions. * * We store the active collation setting in static variables. In principle * it could be passed down to here via the regex library's "struct vars" data @@ -65,18 +62,15 @@ typedef enum { - PG_REGEX_LOCALE_C, /* C locale (encoding independent) */ - PG_REGEX_BUILTIN, /* built-in Unicode semantics */ - PG_REGEX_LOCALE_WIDE, /* Use functions */ - PG_REGEX_LOCALE_1BYTE, /* Use functions */ - PG_REGEX_LOCALE_WIDE_L, /* Use locale_t functions */ - PG_REGEX_LOCALE_1BYTE_L, /* Use locale_t functions */ - PG_REGEX_LOCALE_ICU, /* Use ICU uchar.h functions */ + PG_REGEX_STRATEGY_C, /* C locale (encoding independent) */ + PG_REGEX_STRATEGY_BUILTIN, /* built-in Unicode semantics */ + PG_REGEX_STRATEGY_LIBC_WIDE, /* Use locale_t functions */ + PG_REGEX_STRATEGY_LIBC_1BYTE, /* Use locale_t functions */ + PG_REGEX_STRATEGY_ICU, /* Use ICU uchar.h functions */ } PG_Locale_Strategy; static PG_Locale_Strategy pg_regex_strategy; static pg_locale_t pg_regex_locale; -static Oid pg_regex_collation; /* * Hard-wired character properties for C locale @@ -233,6 +227,9 @@ static const unsigned char pg_char_properties[128] = { void pg_set_regex_collation(Oid collation) { + pg_locale_t locale = 0; + PG_Locale_Strategy strategy; + if (!OidIsValid(collation)) { /* @@ -245,49 +242,57 @@ pg_set_regex_collation(Oid collation) errhint("Use the COLLATE clause to set the collation explicitly."))); } - if (lc_ctype_is_c(collation)) + if (collation == C_COLLATION_OID) { - /* C/POSIX collations use this path regardless of database encoding */ - pg_regex_strategy = PG_REGEX_LOCALE_C; - pg_regex_locale = 0; - pg_regex_collation = C_COLLATION_OID; + /* + * Some callers expect regexes to work for C_COLLATION_OID before + * catalog access is available, so we can't call + * pg_newlocale_from_collation(). + */ + strategy = PG_REGEX_STRATEGY_C; + locale = 0; } else { - pg_regex_locale = pg_newlocale_from_collation(collation); + locale = pg_newlocale_from_collation(collation); - if (!pg_locale_deterministic(pg_regex_locale)) + if (!locale->deterministic) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for regular expressions"))); + if (locale->ctype_is_c) + { + /* + * C/POSIX collations use this path regardless of database + * encoding + */ + strategy = PG_REGEX_STRATEGY_C; + locale = 0; + } + else if (locale->provider == COLLPROVIDER_BUILTIN) + { + Assert(GetDatabaseEncoding() == PG_UTF8); + strategy = PG_REGEX_STRATEGY_BUILTIN; + } #ifdef USE_ICU - if (pg_regex_locale && pg_regex_locale->provider == COLLPROVIDER_ICU) - pg_regex_strategy = PG_REGEX_LOCALE_ICU; - else -#endif - if (GetDatabaseEncoding() == PG_UTF8) + else if (locale->provider == COLLPROVIDER_ICU) { - if (pg_regex_locale) - { - if (pg_regex_locale->provider == COLLPROVIDER_BUILTIN) - pg_regex_strategy = PG_REGEX_BUILTIN; - else - pg_regex_strategy = PG_REGEX_LOCALE_WIDE_L; - } - else - pg_regex_strategy = PG_REGEX_LOCALE_WIDE; + strategy = PG_REGEX_STRATEGY_ICU; } +#endif else { - if (pg_regex_locale) - pg_regex_strategy = PG_REGEX_LOCALE_1BYTE_L; + Assert(locale->provider == COLLPROVIDER_LIBC); + if (GetDatabaseEncoding() == PG_UTF8) + strategy = PG_REGEX_STRATEGY_LIBC_WIDE; else - pg_regex_strategy = PG_REGEX_LOCALE_1BYTE; + strategy = PG_REGEX_STRATEGY_LIBC_1BYTE; } - - pg_regex_collation = collation; } + + pg_regex_strategy = strategy; + pg_regex_locale = locale; } static int @@ -295,27 +300,20 @@ pg_wc_isdigit(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISDIGIT)); - case PG_REGEX_BUILTIN: - return pg_u_isdigit(c, true); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswdigit((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isdigit((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_BUILTIN: + return pg_u_isdigit(c, !pg_regex_locale->info.builtin.casemap_full); + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswdigit_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isdigit_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isdigit(c); #endif @@ -329,27 +327,20 @@ pg_wc_isalpha(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISALPHA)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_isalpha(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswalpha((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isalpha((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswalpha_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isalpha_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isalpha(c); #endif @@ -363,27 +354,20 @@ pg_wc_isalnum(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISALNUM)); - case PG_REGEX_BUILTIN: - return pg_u_isalnum(c, true); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswalnum((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isalnum((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_BUILTIN: + return pg_u_isalnum(c, !pg_regex_locale->info.builtin.casemap_full); + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswalnum_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isalnum_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isalnum(c); #endif @@ -406,27 +390,20 @@ pg_wc_isupper(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISUPPER)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_isupper(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswupper((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isupper((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswupper_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isupper_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isupper(c); #endif @@ -440,27 +417,20 @@ pg_wc_islower(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISLOWER)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_islower(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswlower((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - islower((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswlower_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && islower_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_islower(c); #endif @@ -474,27 +444,20 @@ pg_wc_isgraph(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISGRAPH)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_isgraph(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswgraph((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isgraph((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswgraph_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isgraph_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isgraph(c); #endif @@ -508,27 +471,20 @@ pg_wc_isprint(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISPRINT)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_isprint(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswprint((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isprint((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswprint_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isprint_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isprint(c); #endif @@ -542,27 +498,20 @@ pg_wc_ispunct(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISPUNCT)); - case PG_REGEX_BUILTIN: - return pg_u_ispunct(c, true); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswpunct((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - ispunct((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_BUILTIN: + return pg_u_ispunct(c, !pg_regex_locale->info.builtin.casemap_full); + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswpunct_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && ispunct_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_ispunct(c); #endif @@ -576,27 +525,20 @@ pg_wc_isspace(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISSPACE)); - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return pg_u_isspace(c); - case PG_REGEX_LOCALE_WIDE: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return iswspace((wint_t) c); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: - return (c <= (pg_wchar) UCHAR_MAX && - isspace((unsigned char) c)); - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswspace_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isspace_l((unsigned char) c, pg_regex_locale->info.lt)); break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_isspace(c); #endif @@ -610,35 +552,27 @@ pg_wc_toupper(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: if (c <= (pg_wchar) 127) return pg_ascii_toupper((unsigned char) c); return c; - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return unicode_uppercase_simple(c); - case PG_REGEX_LOCALE_WIDE: + case PG_REGEX_STRATEGY_LIBC_WIDE: /* force C behavior for ASCII characters, per comments above */ - if (c <= (pg_wchar) 127) + if (pg_regex_locale->is_default && c <= (pg_wchar) 127) return pg_ascii_toupper((unsigned char) c); if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return towupper((wint_t) c); + return towupper_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: + case PG_REGEX_STRATEGY_LIBC_1BYTE: /* force C behavior for ASCII characters, per comments above */ - if (c <= (pg_wchar) 127) + if (pg_regex_locale->is_default && c <= (pg_wchar) 127) return pg_ascii_toupper((unsigned char) c); - if (c <= (pg_wchar) UCHAR_MAX) - return toupper((unsigned char) c); - return c; - case PG_REGEX_LOCALE_WIDE_L: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return towupper_l((wint_t) c, pg_regex_locale->info.lt); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: if (c <= (pg_wchar) UCHAR_MAX) return toupper_l((unsigned char) c, pg_regex_locale->info.lt); return c; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_toupper(c); #endif @@ -652,35 +586,27 @@ pg_wc_tolower(pg_wchar c) { switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: if (c <= (pg_wchar) 127) return pg_ascii_tolower((unsigned char) c); return c; - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: return unicode_lowercase_simple(c); - case PG_REGEX_LOCALE_WIDE: + case PG_REGEX_STRATEGY_LIBC_WIDE: /* force C behavior for ASCII characters, per comments above */ - if (c <= (pg_wchar) 127) + if (pg_regex_locale->is_default && c <= (pg_wchar) 127) return pg_ascii_tolower((unsigned char) c); if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return towlower((wint_t) c); + return towlower_l((wint_t) c, pg_regex_locale->info.lt); /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE: + case PG_REGEX_STRATEGY_LIBC_1BYTE: /* force C behavior for ASCII characters, per comments above */ - if (c <= (pg_wchar) 127) + if (pg_regex_locale->is_default && c <= (pg_wchar) 127) return pg_ascii_tolower((unsigned char) c); - if (c <= (pg_wchar) UCHAR_MAX) - return tolower((unsigned char) c); - return c; - case PG_REGEX_LOCALE_WIDE_L: - if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) - return towlower_l((wint_t) c, pg_regex_locale->info.lt); - /* FALL THRU */ - case PG_REGEX_LOCALE_1BYTE_L: if (c <= (pg_wchar) UCHAR_MAX) return tolower_l((unsigned char) c, pg_regex_locale->info.lt); return c; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: #ifdef USE_ICU return u_tolower(c); #endif @@ -708,7 +634,7 @@ typedef int (*pg_wc_probefunc) (pg_wchar c); typedef struct pg_ctype_cache { pg_wc_probefunc probefunc; /* pg_wc_isalpha or a sibling */ - Oid collation; /* collation this entry is for */ + pg_locale_t locale; /* locale this entry is for */ struct cvec cv; /* cache entry contents */ struct pg_ctype_cache *next; /* chain link */ } pg_ctype_cache; @@ -777,7 +703,7 @@ pg_ctype_get_cache(pg_wc_probefunc probefunc, int cclasscode) for (pcc = pg_ctype_cache_list; pcc != NULL; pcc = pcc->next) { if (pcc->probefunc == probefunc && - pcc->collation == pg_regex_collation) + pcc->locale == pg_regex_locale) return &pcc->cv; } @@ -788,7 +714,7 @@ pg_ctype_get_cache(pg_wc_probefunc probefunc, int cclasscode) if (pcc == NULL) return NULL; pcc->probefunc = probefunc; - pcc->collation = pg_regex_collation; + pcc->locale = pg_regex_locale; pcc->cv.nchrs = 0; pcc->cv.chrspace = 128; pcc->cv.chrs = (chr *) malloc(pcc->cv.chrspace * sizeof(chr)); @@ -814,7 +740,7 @@ pg_ctype_get_cache(pg_wc_probefunc probefunc, int cclasscode) */ switch (pg_regex_strategy) { - case PG_REGEX_LOCALE_C: + case PG_REGEX_STRATEGY_C: #if MAX_SIMPLE_CHR >= 127 max_chr = (pg_wchar) 127; pcc->cv.cclasscode = -1; @@ -822,15 +748,13 @@ pg_ctype_get_cache(pg_wc_probefunc probefunc, int cclasscode) max_chr = (pg_wchar) MAX_SIMPLE_CHR; #endif break; - case PG_REGEX_BUILTIN: + case PG_REGEX_STRATEGY_BUILTIN: max_chr = (pg_wchar) MAX_SIMPLE_CHR; break; - case PG_REGEX_LOCALE_WIDE: - case PG_REGEX_LOCALE_WIDE_L: + case PG_REGEX_STRATEGY_LIBC_WIDE: max_chr = (pg_wchar) MAX_SIMPLE_CHR; break; - case PG_REGEX_LOCALE_1BYTE: - case PG_REGEX_LOCALE_1BYTE_L: + case PG_REGEX_STRATEGY_LIBC_1BYTE: #if MAX_SIMPLE_CHR >= UCHAR_MAX max_chr = (pg_wchar) UCHAR_MAX; pcc->cv.cclasscode = -1; @@ -838,7 +762,7 @@ pg_ctype_get_cache(pg_wc_probefunc probefunc, int cclasscode) max_chr = (pg_wchar) MAX_SIMPLE_CHR; #endif break; - case PG_REGEX_LOCALE_ICU: + case PG_REGEX_STRATEGY_ICU: max_chr = (pg_wchar) MAX_SIMPLE_CHR; break; default: diff --git a/src/backend/regex/regcomp.c b/src/backend/regex/regcomp.c index 8a6cfb2973d8c..15b264e50f1a7 100644 --- a/src/backend/regex/regcomp.c +++ b/src/backend/regex/regcomp.c @@ -215,6 +215,7 @@ static void clonesuccessorstates(struct nfa *nfa, struct state *ssource, struct state *spredecessor, struct arc *refarc, char *curdonemap, char *outerdonemap, int nstates); +static void removecantmatch(struct nfa *nfa); static void cleanup(struct nfa *nfa); static void markreachable(struct nfa *nfa, struct state *s, struct state *okay, struct state *mark); @@ -342,6 +343,7 @@ struct vars #define BEHIND 'r' /* color-lookbehind arc */ #define WBDRY 'w' /* word boundary constraint */ #define NWBDRY 'W' /* non-word-boundary constraint */ +#define CANTMATCH 'x' /* arc that cannot match anything */ #define SBEGIN 'A' /* beginning of string (even if not BOL) */ #define SEND 'Z' /* end of string (even if not EOL) */ @@ -2368,6 +2370,7 @@ nfanode(struct vars *v, nfa = newnfa(v, v->cm, v->nfa); NOERRZ(); dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final); + nfa->flags = v->nfa->flags; if (!ISERR()) specialcolors(nfa); if (!ISERR()) diff --git a/src/backend/regex/regerror.c b/src/backend/regex/regerror.c index 4a27c2552cbb0..c69aaf2774741 100644 --- a/src/backend/regex/regerror.c +++ b/src/backend/regex/regerror.c @@ -46,7 +46,7 @@ static const struct rerr { /* the actual table is built from regex.h */ -#include "regex/regerrs.h" /* pgrminclude ignore */ +#include "regex/regerrs.h" { -1, "", "oops" }, /* explanation special-cased in code */ diff --git a/src/backend/regex/regexport.c b/src/backend/regex/regexport.c index 1c9563284c8d5..3866471c2a913 100644 --- a/src/backend/regex/regexport.c +++ b/src/backend/regex/regexport.c @@ -15,7 +15,7 @@ * allows the caller to decide how big is too big to bother with. * * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1998, 1999 Henry Spencer * * IDENTIFICATION diff --git a/src/backend/regex/regprefix.c b/src/backend/regex/regprefix.c index 47a8cebe075e2..8c07e963b8919 100644 --- a/src/backend/regex/regprefix.c +++ b/src/backend/regex/regprefix.c @@ -4,7 +4,7 @@ * Extract a common prefix, if any, from a compiled regex. * * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1998, 1999 Henry Spencer * * IDENTIFICATION diff --git a/src/backend/replication/README b/src/backend/replication/README index 8fcd78da9aade..f05d2aae5f96c 100644 --- a/src/backend/replication/README +++ b/src/backend/replication/README @@ -45,8 +45,8 @@ shutdown checkpoint and terminating pgarch and other auxiliary processes, but that's not desirable for walsenders, because we want the standby servers to receive all the WAL, including the shutdown checkpoint, before the primary is shut down. Therefore postmaster treats walsenders like the pgarch process, -and instructs them to terminate at PM_SHUTDOWN_2 phase, after all regular -backends have died and checkpointer has issued the shutdown checkpoint. +and instructs them to terminate at the PM_WAIT_XLOG_ARCHIVAL phase, after all +regular backends have died and checkpointer has issued the shutdown checkpoint. When postmaster accepts a connection, it immediately forks a new process to handle the handshake and authentication, and the process initializes to diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 97f957cd87b48..7b4ddf7a8f52f 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -9,7 +9,7 @@ * Apart from walreceiver, the libpq-specific routines are now being used by * logical replication workers and slot synchronization. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -25,17 +25,22 @@ #include "common/connect.h" #include "funcapi.h" #include "libpq-fe.h" +#include "libpq/libpq-be-fe-helpers.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "pgstat.h" #include "pqexpbuffer.h" #include "replication/walreceiver.h" +#include "storage/latch.h" #include "utils/builtins.h" #include "utils/memutils.h" #include "utils/pg_lsn.h" #include "utils/tuplestore.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "libpqwalreceiver", + .version = PG_VERSION +); struct WalReceiverConn { @@ -109,8 +114,6 @@ static WalReceiverFunctionsType PQWalReceiverFunctions = { }; /* Prototypes for private functions */ -static PGresult *libpqrcv_PQexec(PGconn *streamConn, const char *query); -static PGresult *libpqrcv_PQgetResult(PGconn *streamConn); static char *stringlist_to_identifierstr(PGconn *conn, List *strings); /* @@ -144,7 +147,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, bool must_use_password, const char *appname, char **err) { WalReceiverConn *conn; - PostgresPollingStatusType status; const char *keys[6]; const char *vals[6]; int i = 0; @@ -207,59 +209,20 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, keys[++i] = NULL; vals[i] = NULL; - Assert(i < sizeof(keys)); + Assert(i < lengthof(keys)); conn = palloc0(sizeof(WalReceiverConn)); - conn->streamConn = PQconnectStartParams(keys, vals, - /* expand_dbname = */ true); - if (PQstatus(conn->streamConn) == CONNECTION_BAD) - goto bad_connection_errmsg; - - /* - * Poll connection until we have OK or FAILED status. - * - * Per spec for PQconnectPoll, first wait till socket is write-ready. - */ - status = PGRES_POLLING_WRITING; - do - { - int io_flag; - int rc; - - if (status == PGRES_POLLING_READING) - io_flag = WL_SOCKET_READABLE; -#ifdef WIN32 - /* Windows needs a different test while waiting for connection-made */ - else if (PQstatus(conn->streamConn) == CONNECTION_STARTED) - io_flag = WL_SOCKET_CONNECTED; -#endif - else - io_flag = WL_SOCKET_WRITEABLE; - - rc = WaitLatchOrSocket(MyLatch, - WL_EXIT_ON_PM_DEATH | WL_LATCH_SET | io_flag, - PQsocket(conn->streamConn), - 0, - WAIT_EVENT_LIBPQWALRECEIVER_CONNECT); - - /* Interrupted? */ - if (rc & WL_LATCH_SET) - { - ResetLatch(MyLatch); - ProcessWalRcvInterrupts(); - } - - /* If socket is ready, advance the libpq state machine */ - if (rc & io_flag) - status = PQconnectPoll(conn->streamConn); - } while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED); + conn->streamConn = + libpqsrv_connect_params(keys, vals, + /* expand_dbname = */ true, + WAIT_EVENT_LIBPQWALRECEIVER_CONNECT); if (PQstatus(conn->streamConn) != CONNECTION_OK) goto bad_connection_errmsg; if (must_use_password && !PQconnectionUsedPassword(conn->streamConn)) { - PQfinish(conn->streamConn); + libpqsrv_disconnect(conn->streamConn); pfree(conn); ereport(ERROR, @@ -277,8 +240,9 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, { PGresult *res; - res = libpqrcv_PQexec(conn->streamConn, - ALWAYS_SECURE_SEARCH_PATH_SQL); + res = libpqsrv_exec(conn->streamConn, + ALWAYS_SECURE_SEARCH_PATH_SQL, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); @@ -299,7 +263,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical, /* error path, error already set */ bad_connection: - PQfinish(conn->streamConn); + libpqsrv_disconnect(conn->streamConn); pfree(conn); return NULL; } @@ -450,7 +414,9 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli) * Get the system identifier and timeline ID as a DataRow message from the * primary server. */ - res = libpqrcv_PQexec(conn->streamConn, "IDENTIFY_SYSTEM"); + res = libpqsrv_exec(conn->streamConn, + "IDENTIFY_SYSTEM", + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); @@ -627,7 +593,9 @@ libpqrcv_startstreaming(WalReceiverConn *conn, options->proto.physical.startpointTLI); /* Start streaming. */ - res = libpqrcv_PQexec(conn->streamConn, cmd.data); + res = libpqsrv_exec(conn->streamConn, + cmd.data, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); pfree(cmd.data); if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -657,7 +625,7 @@ libpqrcv_endstreaming(WalReceiverConn *conn, TimeLineID *next_tli) PGresult *res; /* - * Send copy-end message. As in libpqrcv_PQexec, this could theoretically + * Send copy-end message. As in libpqsrv_exec, this could theoretically * block, but the risk seems small. */ if (PQputCopyEnd(conn->streamConn, NULL) <= 0 || @@ -677,7 +645,8 @@ libpqrcv_endstreaming(WalReceiverConn *conn, TimeLineID *next_tli) * If we had not yet received CopyDone from the backend, PGRES_COPY_OUT is * also possible in case we aborted the copy in mid-stream. */ - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (PQresultStatus(res) == PGRES_TUPLES_OK) { /* @@ -692,7 +661,8 @@ libpqrcv_endstreaming(WalReceiverConn *conn, TimeLineID *next_tli) PQclear(res); /* the result set should be followed by CommandComplete */ - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); } else if (PQresultStatus(res) == PGRES_COPY_OUT) { @@ -706,7 +676,8 @@ libpqrcv_endstreaming(WalReceiverConn *conn, TimeLineID *next_tli) pchomp(PQerrorMessage(conn->streamConn))))); /* CommandComplete should follow */ - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); } if (PQresultStatus(res) != PGRES_COMMAND_OK) @@ -717,7 +688,8 @@ libpqrcv_endstreaming(WalReceiverConn *conn, TimeLineID *next_tli) PQclear(res); /* Verify that there are no more results */ - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (res != NULL) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), @@ -742,7 +714,9 @@ libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn, * Request the primary to send over the history file for given timeline. */ snprintf(cmd, sizeof(cmd), "TIMELINE_HISTORY %u", tli); - res = libpqrcv_PQexec(conn->streamConn, cmd); + res = libpqsrv_exec(conn->streamConn, + cmd, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); @@ -772,114 +746,13 @@ libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn, PQclear(res); } -/* - * Send a query and wait for the results by using the asynchronous libpq - * functions and socket readiness events. - * - * The function is modeled on libpqsrv_exec(), with the behavior difference - * being that it calls ProcessWalRcvInterrupts(). As an optimization, it - * skips try/catch, since all errors terminate the process. - * - * May return NULL, rather than an error result, on failure. - */ -static PGresult * -libpqrcv_PQexec(PGconn *streamConn, const char *query) -{ - PGresult *lastResult = NULL; - - /* - * PQexec() silently discards any prior query results on the connection. - * This is not required for this function as it's expected that the caller - * (which is this library in all cases) will behave correctly and we don't - * have to be backwards compatible with old libpq. - */ - - /* - * Submit the query. Since we don't use non-blocking mode, this could - * theoretically block. In practice, since we don't send very long query - * strings, the risk seems negligible. - */ - if (!PQsendQuery(streamConn, query)) - return NULL; - - for (;;) - { - /* Wait for, and collect, the next PGresult. */ - PGresult *result; - - result = libpqrcv_PQgetResult(streamConn); - if (result == NULL) - break; /* query is complete, or failure */ - - /* - * Emulate PQexec()'s behavior of returning the last result when there - * are many. We are fine with returning just last error message. - */ - PQclear(lastResult); - lastResult = result; - - if (PQresultStatus(lastResult) == PGRES_COPY_IN || - PQresultStatus(lastResult) == PGRES_COPY_OUT || - PQresultStatus(lastResult) == PGRES_COPY_BOTH || - PQstatus(streamConn) == CONNECTION_BAD) - break; - } - - return lastResult; -} - -/* - * Perform the equivalent of PQgetResult(), but watch for interrupts. - */ -static PGresult * -libpqrcv_PQgetResult(PGconn *streamConn) -{ - /* - * Collect data until PQgetResult is ready to get the result without - * blocking. - */ - while (PQisBusy(streamConn)) - { - int rc; - - /* - * We don't need to break down the sleep into smaller increments, - * since we'll get interrupted by signals and can handle any - * interrupts here. - */ - rc = WaitLatchOrSocket(MyLatch, - WL_EXIT_ON_PM_DEATH | WL_SOCKET_READABLE | - WL_LATCH_SET, - PQsocket(streamConn), - 0, - WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); - - /* Interrupted? */ - if (rc & WL_LATCH_SET) - { - ResetLatch(MyLatch); - ProcessWalRcvInterrupts(); - } - - /* Consume whatever data is available from the socket */ - if (PQconsumeInput(streamConn) == 0) - { - /* trouble; return NULL */ - return NULL; - } - } - - /* Now we can collect and return the next PGresult */ - return PQgetResult(streamConn); -} - /* * Disconnect connection to primary, if any. */ static void libpqrcv_disconnect(WalReceiverConn *conn) { - PQfinish(conn->streamConn); + libpqsrv_disconnect(conn->streamConn); PQfreemem(conn->recvBuf); pfree(conn); } @@ -933,13 +806,15 @@ libpqrcv_receive(WalReceiverConn *conn, char **buffer, { PGresult *res; - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); /* Verify that there are no more results. */ - res = libpqrcv_PQgetResult(conn->streamConn); + res = libpqsrv_get_result(conn->streamConn, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); if (res != NULL) { PQclear(res); @@ -1090,7 +965,9 @@ libpqrcv_create_slot(WalReceiverConn *conn, const char *slotname, appendStringInfoString(&cmd, " PHYSICAL RESERVE_WAL"); } - res = libpqrcv_PQexec(conn->streamConn, cmd.data); + res = libpqsrv_exec(conn->streamConn, + cmd.data, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); pfree(cmd.data); if (PQresultStatus(res) != PGRES_TUPLES_OK) @@ -1135,7 +1012,7 @@ libpqrcv_alter_slot(WalReceiverConn *conn, const char *slotname, *failover ? "true" : "false"); if (failover && two_phase) - appendStringInfo(&cmd, ", "); + appendStringInfoString(&cmd, ", "); if (two_phase) appendStringInfo(&cmd, "TWO_PHASE %s", @@ -1143,7 +1020,8 @@ libpqrcv_alter_slot(WalReceiverConn *conn, const char *slotname, appendStringInfoString(&cmd, " );"); - res = libpqrcv_PQexec(conn->streamConn, cmd.data); + res = libpqsrv_exec(conn->streamConn, cmd.data, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); pfree(cmd.data); if (PQresultStatus(res) != PGRES_COMMAND_OK) @@ -1210,7 +1088,7 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres, { char *cstrs[MaxTupleAttributeNumber]; - ProcessWalRcvInterrupts(); + CHECK_FOR_INTERRUPTS(); /* Do the allocations in temporary context. */ oldcontext = MemoryContextSwitchTo(rowcontext); @@ -1256,7 +1134,9 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("the query interface requires a database connection"))); - pgres = libpqrcv_PQexec(conn->streamConn, query); + pgres = libpqsrv_exec(conn->streamConn, + query, + WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE); switch (PQresultStatus(pgres)) { diff --git a/src/backend/replication/libpqwalreceiver/meson.build b/src/backend/replication/libpqwalreceiver/meson.build index f833a997e1cf1..2150f31cfa3df 100644 --- a/src/backend/replication/libpqwalreceiver/meson.build +++ b/src/backend/replication/libpqwalreceiver/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group libpqwalreceiver_sources = files( 'libpqwalreceiver.c', diff --git a/src/backend/replication/logical/Makefile b/src/backend/replication/logical/Makefile index ba03eeff1c6ee..1e08bbbd4eb15 100644 --- a/src/backend/replication/logical/Makefile +++ b/src/backend/replication/logical/Makefile @@ -16,6 +16,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) OBJS = \ applyparallelworker.o \ + conflict.o \ decode.o \ launcher.o \ logical.o \ diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c index e7f7d4c5e4bd3..d25085d351535 100644 --- a/src/backend/replication/logical/applyparallelworker.c +++ b/src/backend/replication/logical/applyparallelworker.c @@ -2,7 +2,7 @@ * applyparallelworker.c * Support routines for applying xact by parallel apply worker * - * Copyright (c) 2023-2024, PostgreSQL Global Development Group + * Copyright (c) 2023-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/applyparallelworker.c @@ -983,7 +983,7 @@ ParallelApplyWorkerMain(Datum main_arg) * * Note: this is called within a signal handler! All we can do is set a flag * that will cause the next CHECK_FOR_INTERRUPTS() to invoke - * HandleParallelApplyMessages(). + * ProcessParallelApplyMessages(). */ void HandleParallelApplyMessageInterrupt(void) @@ -994,11 +994,11 @@ HandleParallelApplyMessageInterrupt(void) } /* - * Handle a single protocol message received from a single parallel apply + * Process a single protocol message received from a single parallel apply * worker. */ static void -HandleParallelApplyMessage(StringInfo msg) +ProcessParallelApplyMessage(StringInfo msg) { char msgtype; @@ -1060,7 +1060,7 @@ HandleParallelApplyMessage(StringInfo msg) * Handle any queued protocol messages received from parallel apply workers. */ void -HandleParallelApplyMessages(void) +ProcessParallelApplyMessages(void) { ListCell *lc; MemoryContext oldcontext; @@ -1083,7 +1083,7 @@ HandleParallelApplyMessages(void) */ if (!hpam_context) /* first time through? */ hpam_context = AllocSetContextCreate(TopMemoryContext, - "HandleParallelApplyMessages", + "ProcessParallelApplyMessages", ALLOCSET_DEFAULT_SIZES); else MemoryContextReset(hpam_context); @@ -1118,7 +1118,7 @@ HandleParallelApplyMessages(void) initStringInfo(&msg); appendBinaryStringInfo(&msg, data, nbytes); - HandleParallelApplyMessage(&msg); + ProcessParallelApplyMessage(&msg); pfree(msg.data); } else diff --git a/src/backend/replication/logical/conflict.c b/src/backend/replication/logical/conflict.c new file mode 100644 index 0000000000000..97c4e26b58654 --- /dev/null +++ b/src/backend/replication/logical/conflict.c @@ -0,0 +1,505 @@ +/*------------------------------------------------------------------------- + * conflict.c + * Support routines for logging conflicts. + * + * Copyright (c) 2024-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/replication/logical/conflict.c + * + * This file contains the code for logging conflicts on the subscriber during + * logical replication. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/commit_ts.h" +#include "access/tableam.h" +#include "executor/executor.h" +#include "pgstat.h" +#include "replication/conflict.h" +#include "replication/worker_internal.h" +#include "storage/lmgr.h" +#include "utils/lsyscache.h" + +static const char *const ConflictTypeNames[] = { + [CT_INSERT_EXISTS] = "insert_exists", + [CT_UPDATE_ORIGIN_DIFFERS] = "update_origin_differs", + [CT_UPDATE_EXISTS] = "update_exists", + [CT_UPDATE_MISSING] = "update_missing", + [CT_DELETE_ORIGIN_DIFFERS] = "delete_origin_differs", + [CT_DELETE_MISSING] = "delete_missing", + [CT_MULTIPLE_UNIQUE_CONFLICTS] = "multiple_unique_conflicts" +}; + +static int errcode_apply_conflict(ConflictType type); +static void errdetail_apply_conflict(EState *estate, + ResultRelInfo *relinfo, + ConflictType type, + TupleTableSlot *searchslot, + TupleTableSlot *localslot, + TupleTableSlot *remoteslot, + Oid indexoid, TransactionId localxmin, + RepOriginId localorigin, + TimestampTz localts, StringInfo err_msg); +static char *build_tuple_value_details(EState *estate, ResultRelInfo *relinfo, + ConflictType type, + TupleTableSlot *searchslot, + TupleTableSlot *localslot, + TupleTableSlot *remoteslot, + Oid indexoid); +static char *build_index_value_desc(EState *estate, Relation localrel, + TupleTableSlot *slot, Oid indexoid); + +/* + * Get the xmin and commit timestamp data (origin and timestamp) associated + * with the provided local tuple. + * + * Return true if the commit timestamp data was found, false otherwise. + */ +bool +GetTupleTransactionInfo(TupleTableSlot *localslot, TransactionId *xmin, + RepOriginId *localorigin, TimestampTz *localts) +{ + Datum xminDatum; + bool isnull; + + xminDatum = slot_getsysattr(localslot, MinTransactionIdAttributeNumber, + &isnull); + *xmin = DatumGetTransactionId(xminDatum); + Assert(!isnull); + + /* + * The commit timestamp data is not available if track_commit_timestamp is + * disabled. + */ + if (!track_commit_timestamp) + { + *localorigin = InvalidRepOriginId; + *localts = 0; + return false; + } + + return TransactionIdGetCommitTsData(*xmin, localts, localorigin); +} + +/* + * This function is used to report a conflict while applying replication + * changes. + * + * 'searchslot' should contain the tuple used to search the local tuple to be + * updated or deleted. + * + * 'remoteslot' should contain the remote new tuple, if any. + * + * conflicttuples is a list of local tuples that caused the conflict and the + * conflict related information. See ConflictTupleInfo. + * + * The caller must ensure that all the indexes passed in ConflictTupleInfo are + * locked so that we can fetch and display the conflicting key values. + */ +void +ReportApplyConflict(EState *estate, ResultRelInfo *relinfo, int elevel, + ConflictType type, TupleTableSlot *searchslot, + TupleTableSlot *remoteslot, List *conflicttuples) +{ + Relation localrel = relinfo->ri_RelationDesc; + StringInfoData err_detail; + + initStringInfo(&err_detail); + + /* Form errdetail message by combining conflicting tuples information. */ + foreach_ptr(ConflictTupleInfo, conflicttuple, conflicttuples) + errdetail_apply_conflict(estate, relinfo, type, searchslot, + conflicttuple->slot, remoteslot, + conflicttuple->indexoid, + conflicttuple->xmin, + conflicttuple->origin, + conflicttuple->ts, + &err_detail); + + pgstat_report_subscription_conflict(MySubscription->oid, type); + + ereport(elevel, + errcode_apply_conflict(type), + errmsg("conflict detected on relation \"%s.%s\": conflict=%s", + get_namespace_name(RelationGetNamespace(localrel)), + RelationGetRelationName(localrel), + ConflictTypeNames[type]), + errdetail_internal("%s", err_detail.data)); +} + +/* + * Find all unique indexes to check for a conflict and store them into + * ResultRelInfo. + */ +void +InitConflictIndexes(ResultRelInfo *relInfo) +{ + List *uniqueIndexes = NIL; + + for (int i = 0; i < relInfo->ri_NumIndices; i++) + { + Relation indexRelation = relInfo->ri_IndexRelationDescs[i]; + + if (indexRelation == NULL) + continue; + + /* Detect conflict only for unique indexes */ + if (!relInfo->ri_IndexRelationInfo[i]->ii_Unique) + continue; + + /* Don't support conflict detection for deferrable index */ + if (!indexRelation->rd_index->indimmediate) + continue; + + uniqueIndexes = lappend_oid(uniqueIndexes, + RelationGetRelid(indexRelation)); + } + + relInfo->ri_onConflictArbiterIndexes = uniqueIndexes; +} + +/* + * Add SQLSTATE error code to the current conflict report. + */ +static int +errcode_apply_conflict(ConflictType type) +{ + switch (type) + { + case CT_INSERT_EXISTS: + case CT_UPDATE_EXISTS: + case CT_MULTIPLE_UNIQUE_CONFLICTS: + return errcode(ERRCODE_UNIQUE_VIOLATION); + case CT_UPDATE_ORIGIN_DIFFERS: + case CT_UPDATE_MISSING: + case CT_DELETE_ORIGIN_DIFFERS: + case CT_DELETE_MISSING: + return errcode(ERRCODE_T_R_SERIALIZATION_FAILURE); + } + + Assert(false); + return 0; /* silence compiler warning */ +} + +/* + * Add an errdetail() line showing conflict detail. + * + * The DETAIL line comprises of two parts: + * 1. Explanation of the conflict type, including the origin and commit + * timestamp of the existing local tuple. + * 2. Display of conflicting key, existing local tuple, remote new tuple, and + * replica identity columns, if any. The remote old tuple is excluded as its + * information is covered in the replica identity columns. + */ +static void +errdetail_apply_conflict(EState *estate, ResultRelInfo *relinfo, + ConflictType type, TupleTableSlot *searchslot, + TupleTableSlot *localslot, TupleTableSlot *remoteslot, + Oid indexoid, TransactionId localxmin, + RepOriginId localorigin, TimestampTz localts, + StringInfo err_msg) +{ + StringInfoData err_detail; + char *val_desc; + char *origin_name; + + initStringInfo(&err_detail); + + /* First, construct a detailed message describing the type of conflict */ + switch (type) + { + case CT_INSERT_EXISTS: + case CT_UPDATE_EXISTS: + case CT_MULTIPLE_UNIQUE_CONFLICTS: + Assert(OidIsValid(indexoid) && + CheckRelationOidLockedByMe(indexoid, RowExclusiveLock, true)); + + if (localts) + { + if (localorigin == InvalidRepOriginId) + appendStringInfo(&err_detail, _("Key already exists in unique index \"%s\", modified locally in transaction %u at %s."), + get_rel_name(indexoid), + localxmin, timestamptz_to_str(localts)); + else if (replorigin_by_oid(localorigin, true, &origin_name)) + appendStringInfo(&err_detail, _("Key already exists in unique index \"%s\", modified by origin \"%s\" in transaction %u at %s."), + get_rel_name(indexoid), origin_name, + localxmin, timestamptz_to_str(localts)); + + /* + * The origin that modified this row has been removed. This + * can happen if the origin was created by a different apply + * worker and its associated subscription and origin were + * dropped after updating the row, or if the origin was + * manually dropped by the user. + */ + else + appendStringInfo(&err_detail, _("Key already exists in unique index \"%s\", modified by a non-existent origin in transaction %u at %s."), + get_rel_name(indexoid), + localxmin, timestamptz_to_str(localts)); + } + else + appendStringInfo(&err_detail, _("Key already exists in unique index \"%s\", modified in transaction %u."), + get_rel_name(indexoid), localxmin); + + break; + + case CT_UPDATE_ORIGIN_DIFFERS: + if (localorigin == InvalidRepOriginId) + appendStringInfo(&err_detail, _("Updating the row that was modified locally in transaction %u at %s."), + localxmin, timestamptz_to_str(localts)); + else if (replorigin_by_oid(localorigin, true, &origin_name)) + appendStringInfo(&err_detail, _("Updating the row that was modified by a different origin \"%s\" in transaction %u at %s."), + origin_name, localxmin, timestamptz_to_str(localts)); + + /* The origin that modified this row has been removed. */ + else + appendStringInfo(&err_detail, _("Updating the row that was modified by a non-existent origin in transaction %u at %s."), + localxmin, timestamptz_to_str(localts)); + + break; + + case CT_UPDATE_MISSING: + appendStringInfoString(&err_detail, _("Could not find the row to be updated.")); + break; + + case CT_DELETE_ORIGIN_DIFFERS: + if (localorigin == InvalidRepOriginId) + appendStringInfo(&err_detail, _("Deleting the row that was modified locally in transaction %u at %s."), + localxmin, timestamptz_to_str(localts)); + else if (replorigin_by_oid(localorigin, true, &origin_name)) + appendStringInfo(&err_detail, _("Deleting the row that was modified by a different origin \"%s\" in transaction %u at %s."), + origin_name, localxmin, timestamptz_to_str(localts)); + + /* The origin that modified this row has been removed. */ + else + appendStringInfo(&err_detail, _("Deleting the row that was modified by a non-existent origin in transaction %u at %s."), + localxmin, timestamptz_to_str(localts)); + + break; + + case CT_DELETE_MISSING: + appendStringInfoString(&err_detail, _("Could not find the row to be deleted.")); + break; + } + + Assert(err_detail.len > 0); + + val_desc = build_tuple_value_details(estate, relinfo, type, searchslot, + localslot, remoteslot, indexoid); + + /* + * Next, append the key values, existing local tuple, remote tuple and + * replica identity columns after the message. + */ + if (val_desc) + appendStringInfo(&err_detail, "\n%s", val_desc); + + /* + * Insert a blank line to visually separate the new detail line from the + * existing ones. + */ + if (err_msg->len > 0) + appendStringInfoChar(err_msg, '\n'); + + appendStringInfoString(err_msg, err_detail.data); +} + +/* + * Helper function to build the additional details for conflicting key, + * existing local tuple, remote tuple, and replica identity columns. + * + * If the return value is NULL, it indicates that the current user lacks + * permissions to view the columns involved. + */ +static char * +build_tuple_value_details(EState *estate, ResultRelInfo *relinfo, + ConflictType type, + TupleTableSlot *searchslot, + TupleTableSlot *localslot, + TupleTableSlot *remoteslot, + Oid indexoid) +{ + Relation localrel = relinfo->ri_RelationDesc; + Oid relid = RelationGetRelid(localrel); + TupleDesc tupdesc = RelationGetDescr(localrel); + StringInfoData tuple_value; + char *desc = NULL; + + Assert(searchslot || localslot || remoteslot); + + initStringInfo(&tuple_value); + + /* + * Report the conflicting key values in the case of a unique constraint + * violation. + */ + if (type == CT_INSERT_EXISTS || type == CT_UPDATE_EXISTS || + type == CT_MULTIPLE_UNIQUE_CONFLICTS) + { + Assert(OidIsValid(indexoid) && localslot); + + desc = build_index_value_desc(estate, localrel, localslot, indexoid); + + if (desc) + appendStringInfo(&tuple_value, _("Key %s"), desc); + } + + if (localslot) + { + /* + * The 'modifiedCols' only applies to the new tuple, hence we pass + * NULL for the existing local tuple. + */ + desc = ExecBuildSlotValueDescription(relid, localslot, tupdesc, + NULL, 64); + + if (desc) + { + if (tuple_value.len > 0) + { + appendStringInfoString(&tuple_value, "; "); + appendStringInfo(&tuple_value, _("existing local tuple %s"), + desc); + } + else + { + appendStringInfo(&tuple_value, _("Existing local tuple %s"), + desc); + } + } + } + + if (remoteslot) + { + Bitmapset *modifiedCols; + + /* + * Although logical replication doesn't maintain the bitmap for the + * columns being inserted, we still use it to create 'modifiedCols' + * for consistency with other calls to ExecBuildSlotValueDescription. + * + * Note that generated columns are formed locally on the subscriber. + */ + modifiedCols = bms_union(ExecGetInsertedCols(relinfo, estate), + ExecGetUpdatedCols(relinfo, estate)); + desc = ExecBuildSlotValueDescription(relid, remoteslot, tupdesc, + modifiedCols, 64); + + if (desc) + { + if (tuple_value.len > 0) + { + appendStringInfoString(&tuple_value, "; "); + appendStringInfo(&tuple_value, _("remote tuple %s"), desc); + } + else + { + appendStringInfo(&tuple_value, _("Remote tuple %s"), desc); + } + } + } + + if (searchslot) + { + /* + * Note that while index other than replica identity may be used (see + * IsIndexUsableForReplicaIdentityFull for details) to find the tuple + * when applying update or delete, such an index scan may not result + * in a unique tuple and we still compare the complete tuple in such + * cases, thus such indexes are not used here. + */ + Oid replica_index = GetRelationIdentityOrPK(localrel); + + Assert(type != CT_INSERT_EXISTS); + + /* + * If the table has a valid replica identity index, build the index + * key value string. Otherwise, construct the full tuple value for + * REPLICA IDENTITY FULL cases. + */ + if (OidIsValid(replica_index)) + desc = build_index_value_desc(estate, localrel, searchslot, replica_index); + else + desc = ExecBuildSlotValueDescription(relid, searchslot, tupdesc, NULL, 64); + + if (desc) + { + if (tuple_value.len > 0) + { + appendStringInfoString(&tuple_value, "; "); + appendStringInfo(&tuple_value, OidIsValid(replica_index) + ? _("replica identity %s") + : _("replica identity full %s"), desc); + } + else + { + appendStringInfo(&tuple_value, OidIsValid(replica_index) + ? _("Replica identity %s") + : _("Replica identity full %s"), desc); + } + } + } + + if (tuple_value.len == 0) + return NULL; + + appendStringInfoChar(&tuple_value, '.'); + return tuple_value.data; +} + +/* + * Helper functions to construct a string describing the contents of an index + * entry. See BuildIndexValueDescription for details. + * + * The caller must ensure that the index with the OID 'indexoid' is locked so + * that we can fetch and display the conflicting key value. + */ +static char * +build_index_value_desc(EState *estate, Relation localrel, TupleTableSlot *slot, + Oid indexoid) +{ + char *index_value; + Relation indexDesc; + Datum values[INDEX_MAX_KEYS]; + bool isnull[INDEX_MAX_KEYS]; + TupleTableSlot *tableslot = slot; + + if (!tableslot) + return NULL; + + Assert(CheckRelationOidLockedByMe(indexoid, RowExclusiveLock, true)); + + indexDesc = index_open(indexoid, NoLock); + + /* + * If the slot is a virtual slot, copy it into a heap tuple slot as + * FormIndexDatum only works with heap tuple slots. + */ + if (TTS_IS_VIRTUAL(slot)) + { + tableslot = table_slot_create(localrel, &estate->es_tupleTable); + tableslot = ExecCopySlot(tableslot, slot); + } + + /* + * Initialize ecxt_scantuple for potential use in FormIndexDatum when + * index expressions are present. + */ + GetPerTupleExprContext(estate)->ecxt_scantuple = tableslot; + + /* + * The values/nulls arrays passed to BuildIndexValueDescription should be + * the results of FormIndexDatum, which are the "raw" input to the index + * AM. + */ + FormIndexDatum(BuildIndexInfo(indexDesc), tableslot, estate, values, isnull); + + index_value = BuildIndexValueDescription(indexDesc, values, isnull); + + index_close(indexDesc, NoLock); + + return index_value; +} diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index d687ceee339f8..cc03f0706e9c8 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -16,7 +16,7 @@ * contents of records in here except turning them into a more usable * format. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -412,19 +412,24 @@ heap2_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) /* * If we don't have snapshot or we are just fast-forwarding, there is no - * point in decoding changes. + * point in decoding data changes. However, it's crucial to build the base + * snapshot during fast-forward mode (as is done in + * SnapBuildProcessChange()) because we require the snapshot's xmin when + * determining the candidate catalog_xmin for the replication slot. See + * SnapBuildProcessRunningXacts(). */ - if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT || - ctx->fast_forward) + if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT) return; switch (info) { case XLOG_HEAP2_MULTI_INSERT: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeMultiInsert(ctx, buf); break; case XLOG_HEAP2_NEW_CID: + if (!ctx->fast_forward) { xl_heap_new_cid *xlrec; @@ -471,16 +476,20 @@ heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) /* * If we don't have snapshot or we are just fast-forwarding, there is no - * point in decoding data changes. + * point in decoding data changes. However, it's crucial to build the base + * snapshot during fast-forward mode (as is done in + * SnapBuildProcessChange()) because we require the snapshot's xmin when + * determining the candidate catalog_xmin for the replication slot. See + * SnapBuildProcessRunningXacts(). */ - if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT || - ctx->fast_forward) + if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT) return; switch (info) { case XLOG_HEAP_INSERT: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeInsert(ctx, buf); break; @@ -491,17 +500,20 @@ heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) */ case XLOG_HEAP_HOT_UPDATE: case XLOG_HEAP_UPDATE: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeUpdate(ctx, buf); break; case XLOG_HEAP_DELETE: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeDelete(ctx, buf); break; case XLOG_HEAP_TRUNCATE: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeTruncate(ctx, buf); break; @@ -509,27 +521,24 @@ heap_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) /* * Inplace updates are only ever performed on catalog tuples and - * can, per definition, not change tuple visibility. Since we - * don't decode catalog tuples, we're not interested in the - * record's contents. + * can, per definition, not change tuple visibility. Inplace + * updates don't affect storage or interpretation of table rows, + * so they don't affect logicalrep_write_tuple() outcomes. Hence, + * we don't process invalidations from the original operation. If + * inplace updates did affect those things, invalidations wouldn't + * make it work, since there are no snapshot-specific versions of + * inplace-updated values. Since we also don't decode catalog + * tuples, we're not interested in the record's contents. * - * In-place updates can be used either by XID-bearing transactions - * (e.g. in CREATE INDEX CONCURRENTLY) or by XID-less - * transactions (e.g. VACUUM). In the former case, the commit - * record will include cache invalidations, so we mark the - * transaction as catalog modifying here. Currently that's - * redundant because the commit will do that as well, but once we - * support decoding in-progress relations, this will be important. + * WAL contains likely-unnecessary commit-time invals from the + * CacheInvalidateHeapTuple() call in + * heap_inplace_update_and_unlock(). Excess invalidation is safe. */ - if (!TransactionIdIsValid(xid)) - break; - - (void) SnapBuildProcessChange(builder, xid, buf->origptr); - ReorderBufferXidSetCatalogChanges(ctx->reorder, xid, buf->origptr); break; case XLOG_HEAP_CONFIRM: - if (SnapBuildProcessChange(builder, xid, buf->origptr)) + if (SnapBuildProcessChange(builder, xid, buf->origptr) && + !ctx->fast_forward) DecodeSpecConfirm(ctx, buf); break; @@ -919,7 +928,7 @@ DecodeInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); if (!(xlrec->flags & XLH_INSERT_IS_SPECULATIVE)) change->action = REORDER_BUFFER_CHANGE_INSERT; else @@ -932,7 +941,7 @@ DecodeInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) tuplelen = datalen - SizeOfHeapHeader; change->data.tp.newtuple = - ReorderBufferGetTupleBuf(ctx->reorder, tuplelen); + ReorderBufferAllocTupleBuf(ctx->reorder, tuplelen); DecodeXLogTuple(tupledata, datalen, change->data.tp.newtuple); @@ -969,7 +978,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); change->action = REORDER_BUFFER_CHANGE_UPDATE; change->origin_id = XLogRecGetOrigin(r); memcpy(&change->data.tp.rlocator, &target_locator, sizeof(RelFileLocator)); @@ -984,7 +993,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) tuplelen = datalen - SizeOfHeapHeader; change->data.tp.newtuple = - ReorderBufferGetTupleBuf(ctx->reorder, tuplelen); + ReorderBufferAllocTupleBuf(ctx->reorder, tuplelen); DecodeXLogTuple(data, datalen, change->data.tp.newtuple); } @@ -1000,7 +1009,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) tuplelen = datalen - SizeOfHeapHeader; change->data.tp.oldtuple = - ReorderBufferGetTupleBuf(ctx->reorder, tuplelen); + ReorderBufferAllocTupleBuf(ctx->reorder, tuplelen); DecodeXLogTuple(data, datalen, change->data.tp.oldtuple); } @@ -1035,7 +1044,7 @@ DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); if (xlrec->flags & XLH_DELETE_IS_SUPER) change->action = REORDER_BUFFER_CHANGE_INTERNAL_SPEC_ABORT; @@ -1055,7 +1064,7 @@ DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) Assert(XLogRecGetDataLen(r) > (SizeOfHeapDelete + SizeOfHeapHeader)); change->data.tp.oldtuple = - ReorderBufferGetTupleBuf(ctx->reorder, tuplelen); + ReorderBufferAllocTupleBuf(ctx->reorder, tuplelen); DecodeXLogTuple((char *) xlrec + SizeOfHeapDelete, datalen, change->data.tp.oldtuple); @@ -1087,7 +1096,7 @@ DecodeTruncate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); change->action = REORDER_BUFFER_CHANGE_TRUNCATE; change->origin_id = XLogRecGetOrigin(r); if (xlrec->flags & XLH_TRUNCATE_CASCADE) @@ -1095,8 +1104,8 @@ DecodeTruncate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS) change->data.truncate.restart_seqs = true; change->data.truncate.nrelids = xlrec->nrelids; - change->data.truncate.relids = ReorderBufferGetRelids(ctx->reorder, - xlrec->nrelids); + change->data.truncate.relids = ReorderBufferAllocRelids(ctx->reorder, + xlrec->nrelids); memcpy(change->data.truncate.relids, xlrec->relids, xlrec->nrelids * sizeof(Oid)); ReorderBufferQueueChange(ctx->reorder, XLogRecGetXid(r), @@ -1153,7 +1162,7 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) HeapTuple tuple; HeapTupleHeader header; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); change->action = REORDER_BUFFER_CHANGE_INSERT; change->origin_id = XLogRecGetOrigin(r); @@ -1164,7 +1173,7 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) datalen = xlhdr->datalen; change->data.tp.newtuple = - ReorderBufferGetTupleBuf(ctx->reorder, datalen); + ReorderBufferAllocTupleBuf(ctx->reorder, datalen); tuple = change->data.tp.newtuple; header = tuple->t_data; @@ -1181,9 +1190,7 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) memset(header, 0, SizeofHeapTupleHeader); - memcpy((char *) tuple->t_data + SizeofHeapTupleHeader, - (char *) data, - datalen); + memcpy((char *) tuple->t_data + SizeofHeapTupleHeader, data, datalen); header->t_infomask = xlhdr->t_infomask; header->t_infomask2 = xlhdr->t_infomask2; header->t_hoff = xlhdr->t_hoff; @@ -1230,7 +1237,7 @@ DecodeSpecConfirm(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) if (FilterByOrigin(ctx, XLogRecGetOrigin(r))) return; - change = ReorderBufferGetChange(ctx->reorder); + change = ReorderBufferAllocChange(ctx->reorder); change->action = REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM; change->origin_id = XLogRecGetOrigin(r); @@ -1269,9 +1276,7 @@ DecodeXLogTuple(char *data, Size len, HeapTuple tuple) tuple->t_tableOid = InvalidOid; /* data is not stored aligned, copy to aligned storage */ - memcpy((char *) &xlhdr, - data, - SizeOfHeapHeader); + memcpy(&xlhdr, data, SizeOfHeapHeader); memset(header, 0, SizeofHeapTupleHeader); diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index c566d50a072b9..1c3c051403dd6 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -2,7 +2,7 @@ * launcher.c * PostgreSQL logical replication worker launcher process * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/launcher.c @@ -31,7 +31,7 @@ #include "postmaster/bgworker.h" #include "postmaster/interrupt.h" #include "replication/logicallauncher.h" -#include "replication/slot.h" +#include "replication/origin.h" #include "replication/walreceiver.h" #include "replication/worker_internal.h" #include "storage/ipc.h" @@ -121,18 +121,9 @@ get_subscription_list(void) resultcxt = CurrentMemoryContext; /* - * Start a transaction so we can access pg_database, and get a snapshot. - * We don't have a use for the snapshot itself, but we're interested in - * the secondary effect that it sets RecentGlobalXmin. (This is critical - * for anything that reads heap pages, because HOT may decide to prune - * them even if the process doesn't attempt to modify any tuples.) - * - * FIXME: This comment is inaccurate / the code buggy. A snapshot that is - * not pushed/active does not reliably prevent HOT pruning (->xmin could - * e.g. be cleared when cache invalidations are processed). + * Start a transaction so we can access pg_subscription. */ StartTransactionCommand(); - (void) GetTransactionSnapshot(); rel = table_open(SubscriptionRelationId, AccessShareLock); scan = table_beginscan_catalog(rel, 0, NULL); @@ -334,10 +325,10 @@ logicalrep_worker_launch(LogicalRepWorkerType wtype, subname))); /* Report this after the initial starting message for consistency. */ - if (max_replication_slots == 0) + if (max_active_replication_origins == 0) ereport(ERROR, (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), - errmsg("cannot start logical replication workers when max_replication_slots = 0"))); + errmsg("cannot start logical replication workers when \"max_active_replication_origins\"=0"))); /* * We need to do the modification of the shared memory under lock so that @@ -1025,7 +1016,7 @@ logicalrep_launcher_attach_dshmem(void) last_start_times_dsa = dsa_attach(LogicalRepCtx->last_start_dsa); dsa_pin_mapping(last_start_times_dsa); last_start_times = dshash_attach(last_start_times_dsa, &dsh_params, - LogicalRepCtx->last_start_dsh, 0); + LogicalRepCtx->last_start_dsh, NULL); } MemoryContextSwitchTo(oldcontext); diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c index f8ef5d56d2693..f1eb798f3e97a 100644 --- a/src/backend/replication/logical/logical.c +++ b/src/backend/replication/logical/logical.c @@ -2,7 +2,7 @@ * logical.c * PostgreSQL logical decoding coordination * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/logical.c @@ -29,6 +29,7 @@ #include "postgres.h" #include "access/xact.h" +#include "access/xlog_internal.h" #include "access/xlogutils.h" #include "fmgr.h" #include "miscadmin.h" @@ -41,6 +42,7 @@ #include "storage/proc.h" #include "storage/procarray.h" #include "utils/builtins.h" +#include "utils/injection_point.h" #include "utils/inval.h" #include "utils/memutils.h" @@ -539,31 +541,12 @@ CreateDecodingContext(XLogRecPtr start_lsn, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot use replication slot \"%s\" for logical decoding", NameStr(slot->data.name)), - errdetail("This slot is being synchronized from the primary server."), + errdetail("This replication slot is being synchronized from the primary server."), errhint("Specify another replication slot.")); - /* - * Check if slot has been invalidated due to max_slot_wal_keep_size. Avoid - * "cannot get changes" wording in this errmsg because that'd be - * confusingly ambiguous about no changes being available when called from - * pg_logical_slot_get_changes_guts(). - */ - if (MyReplicationSlot->data.invalidated == RS_INVAL_WAL_REMOVED) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("can no longer get changes from replication slot \"%s\"", - NameStr(MyReplicationSlot->data.name)), - errdetail("This slot has been invalidated because it exceeded the maximum reserved size."))); - - if (MyReplicationSlot->data.invalidated != RS_INVAL_NONE) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("can no longer get changes from replication slot \"%s\"", - NameStr(MyReplicationSlot->data.name)), - errdetail("This slot has been invalidated because it was conflicting with recovery."))); - - Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE); - Assert(MyReplicationSlot->data.restart_lsn != InvalidXLogRecPtr); + /* slot must be valid to allow decoding */ + Assert(slot->data.invalidated == RS_INVAL_NONE); + Assert(slot->data.restart_lsn != InvalidXLogRecPtr); if (start_lsn == InvalidXLogRecPtr) { @@ -800,7 +783,7 @@ startup_cb_wrapper(LogicalDecodingContext *ctx, OutputPluginOptions *opt, bool i state.callback_name = "startup"; state.report_location = InvalidXLogRecPtr; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -828,7 +811,7 @@ shutdown_cb_wrapper(LogicalDecodingContext *ctx) state.callback_name = "shutdown"; state.report_location = InvalidXLogRecPtr; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -862,7 +845,7 @@ begin_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn) state.callback_name = "begin"; state.report_location = txn->first_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -894,7 +877,7 @@ commit_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "commit"; state.report_location = txn->final_lsn; /* beginning of commit record */ errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -935,7 +918,7 @@ begin_prepare_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn) state.callback_name = "begin_prepare"; state.report_location = txn->first_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -980,7 +963,7 @@ prepare_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "prepare"; state.report_location = txn->final_lsn; /* beginning of prepare record */ errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1025,7 +1008,7 @@ commit_prepared_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "commit_prepared"; state.report_location = txn->final_lsn; /* beginning of commit record */ errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1071,7 +1054,7 @@ rollback_prepared_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "rollback_prepared"; state.report_location = txn->final_lsn; /* beginning of commit record */ errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1114,7 +1097,7 @@ change_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "change"; state.report_location = change->lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1156,7 +1139,7 @@ truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "truncate"; state.report_location = change->lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1195,7 +1178,7 @@ filter_prepare_cb_wrapper(LogicalDecodingContext *ctx, TransactionId xid, state.callback_name = "filter_prepare"; state.report_location = InvalidXLogRecPtr; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1226,7 +1209,7 @@ filter_by_origin_cb_wrapper(LogicalDecodingContext *ctx, RepOriginId origin_id) state.callback_name = "filter_by_origin"; state.report_location = InvalidXLogRecPtr; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1262,7 +1245,7 @@ message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "message"; state.report_location = message_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1298,7 +1281,7 @@ stream_start_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_start"; state.report_location = first_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1347,7 +1330,7 @@ stream_stop_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_stop"; state.report_location = last_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1396,7 +1379,7 @@ stream_abort_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_abort"; state.report_location = abort_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1441,7 +1424,7 @@ stream_prepare_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_prepare"; state.report_location = txn->final_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1482,7 +1465,7 @@ stream_commit_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_commit"; state.report_location = txn->final_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1523,7 +1506,7 @@ stream_change_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_change"; state.report_location = change->lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1577,7 +1560,7 @@ stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_message"; state.report_location = message_lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1618,7 +1601,7 @@ stream_truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "stream_truncate"; state.report_location = change->lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1657,7 +1640,7 @@ update_progress_txn_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, state.callback_name = "update_progress_txn"; state.report_location = lsn; errcallback.callback = output_plugin_error_callback; - errcallback.arg = (void *) &state; + errcallback.arg = &state; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -1774,6 +1757,7 @@ LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart /* don't overwrite if have a newer restart lsn */ if (restart_lsn <= slot->data.restart_lsn) { + SpinLockRelease(&slot->mutex); } /* @@ -1784,6 +1768,7 @@ LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart { slot->candidate_restart_valid = current_lsn; slot->candidate_restart_lsn = restart_lsn; + SpinLockRelease(&slot->mutex); /* our candidate can directly be used */ updated_lsn = true; @@ -1794,7 +1779,7 @@ LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart * might never end up updating if the receiver acks too slowly. A missed * value here will just cause some extra effort after reconnecting. */ - if (slot->candidate_restart_valid == InvalidXLogRecPtr) + else if (slot->candidate_restart_valid == InvalidXLogRecPtr) { slot->candidate_restart_valid = current_lsn; slot->candidate_restart_lsn = restart_lsn; @@ -1842,10 +1827,26 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn) { bool updated_xmin = false; bool updated_restart = false; + XLogRecPtr restart_lsn pg_attribute_unused(); SpinLockAcquire(&MyReplicationSlot->mutex); - MyReplicationSlot->data.confirmed_flush = lsn; + /* remember the old restart lsn */ + restart_lsn = MyReplicationSlot->data.restart_lsn; + + /* + * Prevent moving the confirmed_flush backwards, as this could lead to + * data duplication issues caused by replicating already replicated + * changes. + * + * This can happen when a client acknowledges an LSN it doesn't have + * to do anything for, and thus didn't store persistently. After a + * restart, the client can send the prior LSN that it stored + * persistently as an acknowledgement, but we need to ignore such an + * LSN. See similar case handling in CreateDecodingContext. + */ + if (lsn > MyReplicationSlot->data.confirmed_flush) + MyReplicationSlot->data.confirmed_flush = lsn; /* if we're past the location required for bumping xmin, do so */ if (MyReplicationSlot->candidate_xmin_lsn != InvalidXLogRecPtr && @@ -1886,6 +1887,18 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn) /* first write new xmin to disk, so we know what's up after a crash */ if (updated_xmin || updated_restart) { +#ifdef USE_INJECTION_POINTS + XLogSegNo seg1, + seg2; + + XLByteToSeg(restart_lsn, seg1, wal_segment_size); + XLByteToSeg(MyReplicationSlot->data.restart_lsn, seg2, wal_segment_size); + + /* trigger injection point, but only if segment changes */ + if (seg1 != seg2) + INJECTION_POINT("logical-replication-slot-advance-segment", NULL); +#endif + ReplicationSlotMarkDirty(); ReplicationSlotSave(); elog(DEBUG1, "updated xmin: %u restart: %u", updated_xmin, updated_restart); @@ -1910,7 +1923,14 @@ LogicalConfirmReceivedLocation(XLogRecPtr lsn) else { SpinLockAcquire(&MyReplicationSlot->mutex); - MyReplicationSlot->data.confirmed_flush = lsn; + + /* + * Prevent moving the confirmed_flush backwards. See comments above + * for the details. + */ + if (lsn > MyReplicationSlot->data.confirmed_flush) + MyReplicationSlot->data.confirmed_flush = lsn; + SpinLockRelease(&MyReplicationSlot->mutex); } } @@ -1938,16 +1958,16 @@ UpdateDecodingStats(LogicalDecodingContext *ctx) if (rb->spillBytes <= 0 && rb->streamBytes <= 0 && rb->totalBytes <= 0) return; - elog(DEBUG2, "UpdateDecodingStats: updating stats %p %lld %lld %lld %lld %lld %lld %lld %lld", + elog(DEBUG2, "UpdateDecodingStats: updating stats %p %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64, rb, - (long long) rb->spillTxns, - (long long) rb->spillCount, - (long long) rb->spillBytes, - (long long) rb->streamTxns, - (long long) rb->streamCount, - (long long) rb->streamBytes, - (long long) rb->totalTxns, - (long long) rb->totalBytes); + rb->spillTxns, + rb->spillCount, + rb->spillBytes, + rb->streamTxns, + rb->streamCount, + rb->streamBytes, + rb->totalTxns, + rb->totalBytes); repSlotStat.spill_txns = rb->spillTxns; repSlotStat.spill_count = rb->spillCount; diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c index b4dd5cce75ba5..ca53caac2f2f5 100644 --- a/src/backend/replication/logical/logicalfuncs.c +++ b/src/backend/replication/logical/logicalfuncs.c @@ -6,7 +6,7 @@ * logical replication slots via SQL. * * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/logicalfuncs.c @@ -197,7 +197,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin else end_of_wal = GetXLogReplayRecPtr(NULL); - ReplicationSlotAcquire(NameStr(*name), true); + ReplicationSlotAcquire(NameStr(*name), true, true); PG_TRY(); { diff --git a/src/backend/replication/logical/meson.build b/src/backend/replication/logical/meson.build index 3dec36a6de5f5..6f19614c79d8f 100644 --- a/src/backend/replication/logical/meson.build +++ b/src/backend/replication/logical/meson.build @@ -1,7 +1,8 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'applyparallelworker.c', + 'conflict.c', 'decode.c', 'launcher.c', 'logical.c', diff --git a/src/backend/replication/logical/message.c b/src/backend/replication/logical/message.c index 9e41aac28130d..ebc8454bad926 100644 --- a/src/backend/replication/logical/message.c +++ b/src/backend/replication/logical/message.c @@ -3,7 +3,7 @@ * message.c * Generic logical messages. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/message.c @@ -62,9 +62,9 @@ LogLogicalMessage(const char *prefix, const char *message, size_t size, xlrec.message_size = size; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfLogicalMessage); - XLogRegisterData(unconstify(char *, prefix), xlrec.prefix_size); - XLogRegisterData(unconstify(char *, message), size); + XLogRegisterData(&xlrec, SizeOfLogicalMessage); + XLogRegisterData(prefix, xlrec.prefix_size); + XLogRegisterData(message, size); /* allow origin filtering */ XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN); diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 419e4814f0577..a17bacf88e7f3 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -3,7 +3,7 @@ * origin.c * Logical replication progress tracking support. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/origin.c @@ -90,11 +90,19 @@ #include "storage/lmgr.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/guc.h" #include "utils/pg_lsn.h" #include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/syscache.h" +/* paths for replication origin checkpoint files */ +#define PG_REPLORIGIN_CHECKPOINT_FILENAME PG_LOGICAL_DIR "/replorigin_checkpoint" +#define PG_REPLORIGIN_CHECKPOINT_TMPFILE PG_REPLORIGIN_CHECKPOINT_FILENAME ".tmp" + +/* GUC variables */ +int max_active_replication_origins = 10; + /* * Replay progress of a single remote node. */ @@ -147,7 +155,7 @@ typedef struct ReplicationStateCtl { /* Tranche to use for per-origin LWLocks */ int tranche_id; - /* Array of length max_replication_slots */ + /* Array of length max_active_replication_origins */ ReplicationState states[FLEXIBLE_ARRAY_MEMBER]; } ReplicationStateCtl; @@ -158,10 +166,7 @@ TimestampTz replorigin_session_origin_timestamp = 0; /* * Base address into a shared memory array of replication states of size - * max_replication_slots. - * - * XXX: Should we use a separate variable to size this rather than - * max_replication_slots? + * max_active_replication_origins. */ static ReplicationState *replication_states; @@ -182,12 +187,12 @@ static ReplicationState *session_replication_state = NULL; #define REPLICATION_STATE_MAGIC ((uint32) 0x1257DADE) static void -replorigin_check_prerequisites(bool check_slots, bool recoveryOK) +replorigin_check_prerequisites(bool check_origins, bool recoveryOK) { - if (check_slots && max_replication_slots == 0) + if (check_origins && max_active_replication_origins == 0) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("cannot query or manipulate replication origin when \"max_replication_slots\" is 0"))); + errmsg("cannot query or manipulate replication origin when \"max_active_replication_origins\" is 0"))); if (!recoveryOK && RecoveryInProgress()) ereport(ERROR, @@ -259,6 +264,18 @@ replorigin_create(const char *roname) SysScanDesc scan; ScanKeyData key; + /* + * To avoid needing a TOAST table for pg_replication_origin, we limit + * replication origin names to 512 bytes. This should be more than enough + * for all practical use. + */ + if (strlen(roname) > MAX_RONAME_LEN) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("replication origin name is too long"), + errdetail("Replication origin names must be no longer than %d bytes.", + MAX_RONAME_LEN))); + roname_d = CStringGetTextDatum(roname); Assert(IsTransactionState()); @@ -282,6 +299,17 @@ replorigin_create(const char *roname) rel = table_open(ReplicationOriginRelationId, ExclusiveLock); + /* + * We want to be able to access pg_replication_origin without setting up a + * snapshot. To make that safe, it needs to not have a TOAST table, since + * TOASTed data cannot be fetched without a snapshot. As of this writing, + * its only varlena column is roname, which we limit to 512 bytes to avoid + * needing out-of-line storage. If you add a TOAST table to this catalog, + * be sure to set up a snapshot everywhere it might be needed. For more + * information, see https://postgr.es/m/ZvMSUPOqUU-VNADN%40nathan. + */ + Assert(!OidIsValid(rel->rd_rel->reltoastrelid)); + for (roident = InvalidOid + 1; roident < PG_UINT16_MAX; roident++) { bool nulls[Natts_pg_replication_origin]; @@ -348,7 +376,7 @@ replorigin_state_clear(RepOriginId roident, bool nowait) restart: LWLockAcquire(ReplicationOriginLock, LW_EXCLUSIVE); - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *state = &replication_states[i]; @@ -387,7 +415,7 @@ replorigin_state_clear(RepOriginId roident, bool nowait) xlrec.node_id = roident; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); XLogInsert(RM_REPLORIGIN_ID, XLOG_REPLORIGIN_DROP); } @@ -507,18 +535,13 @@ ReplicationOriginShmemSize(void) { Size size = 0; - /* - * XXX: max_replication_slots is arguably the wrong thing to use, as here - * we keep the replay state of *remote* transactions. But for now it seems - * sufficient to reuse it, rather than introduce a separate GUC. - */ - if (max_replication_slots == 0) + if (max_active_replication_origins == 0) return size; size = add_size(size, offsetof(ReplicationStateCtl, states)); size = add_size(size, - mul_size(max_replication_slots, sizeof(ReplicationState))); + mul_size(max_active_replication_origins, sizeof(ReplicationState))); return size; } @@ -527,7 +550,7 @@ ReplicationOriginShmemInit(void) { bool found; - if (max_replication_slots == 0) + if (max_active_replication_origins == 0) return; replication_states_ctl = (ReplicationStateCtl *) @@ -544,7 +567,7 @@ ReplicationOriginShmemInit(void) replication_states_ctl->tranche_id = LWTRANCHE_REPLICATION_ORIGIN_STATE; - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { LWLockInitialize(&replication_states[i].lock, replication_states_ctl->tranche_id); @@ -566,20 +589,20 @@ ReplicationOriginShmemInit(void) * * So its just the magic, followed by the statically sized * ReplicationStateOnDisk structs. Note that the maximum number of - * ReplicationState is determined by max_replication_slots. + * ReplicationState is determined by max_active_replication_origins. * --------------------------------------------------------------------------- */ void CheckPointReplicationOrigin(void) { - const char *tmppath = "pg_logical/replorigin_checkpoint.tmp"; - const char *path = "pg_logical/replorigin_checkpoint"; + const char *tmppath = PG_REPLORIGIN_CHECKPOINT_TMPFILE; + const char *path = PG_REPLORIGIN_CHECKPOINT_FILENAME; int tmpfd; int i; uint32 magic = REPLICATION_STATE_MAGIC; pg_crc32c crc; - if (max_replication_slots == 0) + if (max_active_replication_origins == 0) return; INIT_CRC32C(crc); @@ -621,7 +644,7 @@ CheckPointReplicationOrigin(void) LWLockAcquire(ReplicationOriginLock, LW_SHARED); /* write actual data */ - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationStateOnDisk disk_state; ReplicationState *curstate = &replication_states[i]; @@ -698,7 +721,7 @@ CheckPointReplicationOrigin(void) void StartupReplicationOrigin(void) { - const char *path = "pg_logical/replorigin_checkpoint"; + const char *path = PG_REPLORIGIN_CHECKPOINT_FILENAME; int fd; int readBytes; uint32 magic = REPLICATION_STATE_MAGIC; @@ -714,7 +737,7 @@ StartupReplicationOrigin(void) already_started = true; #endif - if (max_replication_slots == 0) + if (max_active_replication_origins == 0) return; INIT_CRC32C(crc); @@ -724,8 +747,8 @@ StartupReplicationOrigin(void) fd = OpenTransientFile(path, O_RDONLY | PG_BINARY); /* - * might have had max_replication_slots == 0 last run, or we just brought - * up a standby. + * might have had max_active_replication_origins == 0 last run, or we just + * brought up a standby. */ if (fd < 0 && errno == ENOENT) return; @@ -792,10 +815,10 @@ StartupReplicationOrigin(void) COMP_CRC32C(crc, &disk_state, sizeof(disk_state)); - if (last_state == max_replication_slots) + if (last_state == max_active_replication_origins) ereport(PANIC, (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), - errmsg("could not find free replication state, increase \"max_replication_slots\""))); + errmsg("could not find free replication state, increase \"max_active_replication_origins\""))); /* copy data to shared memory */ replication_states[last_state].roident = disk_state.roident; @@ -848,7 +871,7 @@ replorigin_redo(XLogReaderState *record) xlrec = (xl_replorigin_drop *) XLogRecGetData(record); - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *state = &replication_states[i]; @@ -913,7 +936,7 @@ replorigin_advance(RepOriginId node, * Search for either an existing slot for the origin, or a free one we can * use. */ - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *curstate = &replication_states[i]; @@ -954,7 +977,7 @@ replorigin_advance(RepOriginId node, (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), errmsg("could not find free replication state slot for replication origin with ID %d", node), - errhint("Increase \"max_replication_slots\" and try again."))); + errhint("Increase \"max_active_replication_origins\" and try again."))); if (replication_state == NULL) { @@ -982,7 +1005,7 @@ replorigin_advance(RepOriginId node, xlrec.force = go_backward; XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), sizeof(xlrec)); + XLogRegisterData(&xlrec, sizeof(xlrec)); XLogInsert(RM_REPLORIGIN_ID, XLOG_REPLORIGIN_SET); } @@ -1020,7 +1043,7 @@ replorigin_get_progress(RepOriginId node, bool flush) /* prevent slots from being concurrently dropped */ LWLockAcquire(ReplicationOriginLock, LW_SHARED); - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *state; @@ -1106,7 +1129,7 @@ replorigin_session_setup(RepOriginId node, int acquired_by) registered_cleanup = true; } - Assert(max_replication_slots > 0); + Assert(max_active_replication_origins > 0); if (session_replication_state != NULL) ereport(ERROR, @@ -1120,7 +1143,7 @@ replorigin_session_setup(RepOriginId node, int acquired_by) * Search for either an existing slot for the origin, or a free one we can * use. */ - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *curstate = &replication_states[i]; @@ -1155,7 +1178,7 @@ replorigin_session_setup(RepOriginId node, int acquired_by) (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), errmsg("could not find free replication state slot for replication origin with ID %d", node), - errhint("Increase \"max_replication_slots\" and try again."))); + errhint("Increase \"max_active_replication_origins\" and try again."))); else if (session_replication_state == NULL) { /* initialize new slot */ @@ -1191,7 +1214,7 @@ replorigin_session_reset(void) { ConditionVariable *cv; - Assert(max_replication_slots != 0); + Assert(max_active_replication_origins != 0); if (session_replication_state == NULL) ereport(ERROR, @@ -1532,7 +1555,7 @@ pg_show_replication_origin_status(PG_FUNCTION_ARGS) * filled. Note that we do not take any locks, so slightly corrupted/out * of date values are a possibility. */ - for (i = 0; i < max_replication_slots; i++) + for (i = 0; i < max_active_replication_origins; i++) { ReplicationState *state; Datum values[REPLICATION_ORIGIN_PROGRESS_COLS]; diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c index 980f6e2741046..1a352b542dc56 100644 --- a/src/backend/replication/logical/proto.c +++ b/src/backend/replication/logical/proto.c @@ -3,7 +3,7 @@ * proto.c * logical replication protocol functions * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/proto.c @@ -30,29 +30,18 @@ #define TRUNCATE_RESTART_SEQS (1<<1) static void logicalrep_write_attrs(StringInfo out, Relation rel, - Bitmapset *columns); + Bitmapset *columns, + PublishGencolsType include_gencols_type); static void logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot, - bool binary, Bitmapset *columns); + bool binary, Bitmapset *columns, + PublishGencolsType include_gencols_type); static void logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel); static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple); static void logicalrep_write_namespace(StringInfo out, Oid nspid); static const char *logicalrep_read_namespace(StringInfo in); -/* - * Check if a column is covered by a column list. - * - * Need to be careful about NULL, which is treated as a column list covering - * all columns. - */ -static bool -column_in_column_list(int attnum, Bitmapset *columns) -{ - return (columns == NULL || bms_is_member(attnum, columns)); -} - - /* * Write BEGIN to the output stream. */ @@ -175,7 +164,7 @@ logicalrep_write_prepare_common(StringInfo out, LogicalRepMsgType type, * which case we expect to have a valid GID. */ Assert(txn->gid != NULL); - Assert(rbtxn_prepared(txn)); + Assert(rbtxn_is_prepared(txn)); Assert(TransactionIdIsValid(txn->xid)); /* send the flags field */ @@ -412,7 +401,9 @@ logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn) */ void logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel, - TupleTableSlot *newslot, bool binary, Bitmapset *columns) + TupleTableSlot *newslot, bool binary, + Bitmapset *columns, + PublishGencolsType include_gencols_type) { pq_sendbyte(out, LOGICAL_REP_MSG_INSERT); @@ -424,7 +415,8 @@ logicalrep_write_insert(StringInfo out, TransactionId xid, Relation rel, pq_sendint32(out, RelationGetRelid(rel)); pq_sendbyte(out, 'N'); /* new tuple follows */ - logicalrep_write_tuple(out, rel, newslot, binary, columns); + logicalrep_write_tuple(out, rel, newslot, binary, columns, + include_gencols_type); } /* @@ -457,7 +449,8 @@ logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup) void logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, - bool binary, Bitmapset *columns) + bool binary, Bitmapset *columns, + PublishGencolsType include_gencols_type) { pq_sendbyte(out, LOGICAL_REP_MSG_UPDATE); @@ -478,11 +471,13 @@ logicalrep_write_update(StringInfo out, TransactionId xid, Relation rel, pq_sendbyte(out, 'O'); /* old tuple follows */ else pq_sendbyte(out, 'K'); /* old key follows */ - logicalrep_write_tuple(out, rel, oldslot, binary, columns); + logicalrep_write_tuple(out, rel, oldslot, binary, columns, + include_gencols_type); } pq_sendbyte(out, 'N'); /* new tuple follows */ - logicalrep_write_tuple(out, rel, newslot, binary, columns); + logicalrep_write_tuple(out, rel, newslot, binary, columns, + include_gencols_type); } /* @@ -532,7 +527,8 @@ logicalrep_read_update(StringInfo in, bool *has_oldtuple, void logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel, TupleTableSlot *oldslot, bool binary, - Bitmapset *columns) + Bitmapset *columns, + PublishGencolsType include_gencols_type) { Assert(rel->rd_rel->relreplident == REPLICA_IDENTITY_DEFAULT || rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL || @@ -552,7 +548,8 @@ logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel, else pq_sendbyte(out, 'K'); /* old key follows */ - logicalrep_write_tuple(out, rel, oldslot, binary, columns); + logicalrep_write_tuple(out, rel, oldslot, binary, columns, + include_gencols_type); } /* @@ -668,7 +665,8 @@ logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecPtr lsn, */ void logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel, - Bitmapset *columns) + Bitmapset *columns, + PublishGencolsType include_gencols_type) { char *relname; @@ -690,7 +688,7 @@ logicalrep_write_rel(StringInfo out, TransactionId xid, Relation rel, pq_sendbyte(out, rel->rd_rel->relreplident); /* send the attribute info */ - logicalrep_write_attrs(out, rel, columns); + logicalrep_write_attrs(out, rel, columns, include_gencols_type); } /* @@ -767,7 +765,8 @@ logicalrep_read_typ(StringInfo in, LogicalRepTyp *ltyp) */ static void logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot, - bool binary, Bitmapset *columns) + bool binary, Bitmapset *columns, + PublishGencolsType include_gencols_type) { TupleDesc desc; Datum *values; @@ -781,10 +780,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot, { Form_pg_attribute att = TupleDescAttr(desc, i); - if (att->attisdropped || att->attgenerated) - continue; - - if (!column_in_column_list(att->attnum, columns)) + if (!logicalrep_should_publish_column(att, columns, + include_gencols_type)) continue; nliveatts++; @@ -802,10 +799,8 @@ logicalrep_write_tuple(StringInfo out, Relation rel, TupleTableSlot *slot, Form_pg_type typclass; Form_pg_attribute att = TupleDescAttr(desc, i); - if (att->attisdropped || att->attgenerated) - continue; - - if (!column_in_column_list(att->attnum, columns)) + if (!logicalrep_should_publish_column(att, columns, + include_gencols_type)) continue; if (isnull[i]) @@ -923,7 +918,8 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple) * Write relation attribute metadata to the stream. */ static void -logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns) +logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns, + PublishGencolsType include_gencols_type) { TupleDesc desc; int i; @@ -938,10 +934,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns) { Form_pg_attribute att = TupleDescAttr(desc, i); - if (att->attisdropped || att->attgenerated) - continue; - - if (!column_in_column_list(att->attnum, columns)) + if (!logicalrep_should_publish_column(att, columns, + include_gencols_type)) continue; nliveatts++; @@ -959,10 +953,8 @@ logicalrep_write_attrs(StringInfo out, Relation rel, Bitmapset *columns) Form_pg_attribute att = TupleDescAttr(desc, i); uint8 flags = 0; - if (att->attisdropped || att->attgenerated) - continue; - - if (!column_in_column_list(att->attnum, columns)) + if (!logicalrep_should_publish_column(att, columns, + include_gencols_type)) continue; /* REPLICA IDENTITY FULL means all columns are sent as part of key. */ @@ -1269,3 +1261,41 @@ logicalrep_message_type(LogicalRepMsgType action) return err_unknown; } + +/* + * Check if the column 'att' of a table should be published. + * + * 'columns' represents the publication column list (if any) for that table. + * + * 'include_gencols_type' value indicates whether generated columns should be + * published when there is no column list. Typically, this will have the same + * value as the 'publish_generated_columns' publication parameter. + * + * Note that generated columns can be published only when present in a + * publication column list, or when include_gencols_type is + * PUBLISH_GENCOLS_STORED. + */ +bool +logicalrep_should_publish_column(Form_pg_attribute att, Bitmapset *columns, + PublishGencolsType include_gencols_type) +{ + if (att->attisdropped) + return false; + + /* If a column list is provided, publish only the cols in that list. */ + if (columns) + return bms_is_member(att->attnum, columns); + + /* All non-generated columns are always published. */ + if (!att->attgenerated) + return true; + + /* + * Stored generated columns are only published when the user sets + * publish_generated_columns as stored. + */ + if (att->attgenerated == ATTRIBUTE_GENERATED_STORED) + return include_gencols_type == PUBLISH_GENCOLS_STORED; + + return false; +} diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index f139e7b01e9c1..f59046ad620da 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -2,7 +2,7 @@ * relation.c * PostgreSQL logical replication relation mapping cache * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/relation.c @@ -17,9 +17,7 @@ #include "postgres.h" -#ifdef USE_ASSERT_CHECKING #include "access/amapi.h" -#endif #include "access/genam.h" #include "access/table.h" #include "catalog/namespace.h" @@ -29,6 +27,8 @@ #include "replication/logicalrelation.h" #include "replication/worker_internal.h" #include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" static MemoryContext LogicalRepRelMapContext = NULL; @@ -220,41 +220,63 @@ logicalrep_rel_att_by_name(LogicalRepRelation *remoterel, const char *attname) } /* - * Report error with names of the missing local relation column(s), if any. + * Returns a comma-separated string of attribute names based on the provided + * relation and bitmap indicating which attributes to include. */ -static void -logicalrep_report_missing_attrs(LogicalRepRelation *remoterel, - Bitmapset *missingatts) +static char * +logicalrep_get_attrs_str(LogicalRepRelation *remoterel, Bitmapset *atts) { - if (!bms_is_empty(missingatts)) + StringInfoData attsbuf; + int attcnt = 0; + int i = -1; + + Assert(!bms_is_empty(atts)); + + initStringInfo(&attsbuf); + + while ((i = bms_next_member(atts, i)) >= 0) { - StringInfoData missingattsbuf; - int missingattcnt = 0; - int i; + attcnt++; + if (attcnt > 1) + appendStringInfoString(&attsbuf, _(", ")); - initStringInfo(&missingattsbuf); + appendStringInfo(&attsbuf, _("\"%s\""), remoterel->attnames[i]); + } - i = -1; - while ((i = bms_next_member(missingatts, i)) >= 0) - { - missingattcnt++; - if (missingattcnt == 1) - appendStringInfo(&missingattsbuf, _("\"%s\""), - remoterel->attnames[i]); - else - appendStringInfo(&missingattsbuf, _(", \"%s\""), - remoterel->attnames[i]); - } + return attsbuf.data; +} +/* + * If attempting to replicate missing or generated columns, report an error. + * Prioritize 'missing' errors if both occur though the prioritization is + * arbitrary. + */ +static void +logicalrep_report_missing_or_gen_attrs(LogicalRepRelation *remoterel, + Bitmapset *missingatts, + Bitmapset *generatedatts) +{ + if (!bms_is_empty(missingatts)) ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s", - "logical replication target relation \"%s.%s\" is missing replicated columns: %s", - missingattcnt, - remoterel->nspname, - remoterel->relname, - missingattsbuf.data))); - } + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg_plural("logical replication target relation \"%s.%s\" is missing replicated column: %s", + "logical replication target relation \"%s.%s\" is missing replicated columns: %s", + bms_num_members(missingatts), + remoterel->nspname, + remoterel->relname, + logicalrep_get_attrs_str(remoterel, + missingatts))); + + if (!bms_is_empty(generatedatts)) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg_plural("logical replication target relation \"%s.%s\" has incompatible generated column: %s", + "logical replication target relation \"%s.%s\" has incompatible generated columns: %s", + bms_num_members(generatedatts), + remoterel->nspname, + remoterel->relname, + logicalrep_get_attrs_str(remoterel, + generatedatts))); } /* @@ -380,6 +402,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) MemoryContext oldctx; int i; Bitmapset *missingatts; + Bitmapset *generatedattrs = NULL; /* Release the no-longer-useful attrmap, if any. */ if (entry->attrmap) @@ -421,7 +444,7 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) int attnum; Form_pg_attribute attr = TupleDescAttr(desc, i); - if (attr->attisdropped || attr->attgenerated) + if (attr->attisdropped) { entry->attrmap->attnums[i] = -1; continue; @@ -432,12 +455,20 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) entry->attrmap->attnums[i] = attnum; if (attnum >= 0) + { + /* Remember which subscriber columns are generated. */ + if (attr->attgenerated) + generatedattrs = bms_add_member(generatedattrs, attnum); + missingatts = bms_del_member(missingatts, attnum); + } } - logicalrep_report_missing_attrs(remoterel, missingatts); + logicalrep_report_missing_or_gen_attrs(remoterel, missingatts, + generatedattrs); /* be tidy */ + bms_free(generatedattrs); bms_free(missingatts); /* @@ -750,11 +781,9 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap) { bool isUsableIdx; Relation idxRel; - IndexInfo *idxInfo; idxRel = index_open(idxoid, AccessShareLock); - idxInfo = BuildIndexInfo(idxRel); - isUsableIdx = IsIndexUsableForReplicaIdentityFull(idxInfo, attrmap); + isUsableIdx = IsIndexUsableForReplicaIdentityFull(idxRel, attrmap); index_close(idxRel, AccessShareLock); /* Return the first eligible index found */ @@ -768,9 +797,10 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap) /* * Returns true if the index is usable for replica identity full. * - * The index must be btree or hash, non-partial, and the leftmost field must be - * a column (not an expression) that references the remote relation column. These - * limitations help to keep the index scan similar to PK/RI index scans. + * The index must have an equal strategy for each key column, be non-partial, + * and the leftmost field must be a column (not an expression) that references + * the remote relation column. These limitations help to keep the index scan + * similar to PK/RI index scans. * * attrmap is a map of local attributes to remote ones. We can consult this * map to check whether the local index attribute has a corresponding remote @@ -783,40 +813,53 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap) * compare the tuples for non-PK/RI index scans. See * RelationFindReplTupleByIndex(). * - * The reasons why only Btree and Hash indexes can be considered as usable are: - * - * 1) Other index access methods don't have a fixed strategy for equality - * operation. Refer get_equal_strategy_number_for_am(). - * - * 2) For indexes other than PK and REPLICA IDENTITY, we need to match the - * local and remote tuples. The equality routine tuples_equal() cannot accept - * a datatype (e.g. point or box) that does not have a default operator class - * for Btree or Hash. - * - * XXX: Note that BRIN and GIN indexes do not implement "amgettuple" which - * will be used later to fetch the tuples. See RelationFindReplTupleByIndex(). - * * XXX: To support partial indexes, the required changes are likely to be larger. * If none of the tuples satisfy the expression for the index scan, we fall-back * to sequential execution, which might not be a good idea in some cases. */ bool -IsIndexUsableForReplicaIdentityFull(IndexInfo *indexInfo, AttrMap *attrmap) +IsIndexUsableForReplicaIdentityFull(Relation idxrel, AttrMap *attrmap) { AttrNumber keycol; - - /* Ensure that the index access method has a valid equal strategy */ - if (get_equal_strategy_number_for_am(indexInfo->ii_Am) == InvalidStrategy) - return false; + oidvector *indclass; /* The index must not be a partial index */ - if (indexInfo->ii_Predicate != NIL) + if (!heap_attisnull(idxrel->rd_indextuple, Anum_pg_index_indpred, NULL)) return false; - Assert(indexInfo->ii_NumIndexAttrs >= 1); + Assert(idxrel->rd_index->indnatts >= 1); + + indclass = (oidvector *) DatumGetPointer(SysCacheGetAttrNotNull(INDEXRELID, + idxrel->rd_indextuple, + Anum_pg_index_indclass)); + + /* Ensure that the index has a valid equal strategy for each key column */ + for (int i = 0; i < idxrel->rd_index->indnkeyatts; i++) + { + Oid opfamily; + + opfamily = get_opclass_family(indclass->values[i]); + if (IndexAmTranslateCompareType(COMPARE_EQ, idxrel->rd_rel->relam, opfamily, true) == InvalidStrategy) + return false; + } + + /* + * For indexes other than PK and REPLICA IDENTITY, we need to match the + * local and remote tuples. The equality routine tuples_equal() cannot + * accept a data type where the type cache cannot provide an equality + * operator. + */ + for (int i = 0; i < idxrel->rd_att->natts; i++) + { + TypeCacheEntry *typentry; + + typentry = lookup_type_cache(TupleDescAttr(idxrel->rd_att, i)->atttypid, TYPECACHE_EQ_OPR_FINFO); + if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) + return false; + } /* The leftmost index field must not be an expression */ - keycol = indexInfo->ii_IndexAttrNumbers[0]; + keycol = idxrel->rd_index->indkey.values[0]; if (!AttributeNumberIsValid(keycol)) return false; @@ -829,15 +872,12 @@ IsIndexUsableForReplicaIdentityFull(IndexInfo *indexInfo, AttrMap *attrmap) attrmap->attnums[AttrNumberGetAttrOffset(keycol)] < 0) return false; -#ifdef USE_ASSERT_CHECKING - { - IndexAmRoutine *amroutine; - - /* The given index access method must implement amgettuple. */ - amroutine = GetIndexAmRoutineByAmId(indexInfo->ii_Am, false); - Assert(amroutine->amgettuple != NULL); - } -#endif + /* + * The given index access method must implement "amgettuple", which will + * be used later to fetch the tuples. See RelationFindReplTupleByIndex(). + */ + if (GetIndexAmRoutineByAmId(idxrel->rd_rel->relam, false)->amgettuple == NULL) + return false; return true; } @@ -855,7 +895,7 @@ GetRelationIdentityOrPK(Relation rel) idxoid = RelationGetReplicaIndex(rel); if (!OidIsValid(idxoid)) - idxoid = RelationGetPrimaryKeyIndex(rel); + idxoid = RelationGetPrimaryKeyIndex(rel, false); return idxoid; } diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 00a8327e77153..c4299c76fb16b 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -4,7 +4,7 @@ * PostgreSQL logical replay/reorder buffer management * * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -106,12 +106,25 @@ #include "replication/snapbuild.h" /* just for SnapBuildSnapDecRefcount */ #include "storage/bufmgr.h" #include "storage/fd.h" +#include "storage/procarray.h" #include "storage/sinval.h" #include "utils/builtins.h" +#include "utils/inval.h" #include "utils/memutils.h" #include "utils/rel.h" #include "utils/relfilenumbermap.h" +/* + * Each transaction has an 8MB limit for invalidation messages distributed from + * other transactions. This limit is set considering scenarios with many + * concurrent logical decoding operations. When the distributed invalidation + * messages reach this threshold, the transaction is marked as + * RBTXN_DISTR_INVAL_OVERFLOWED to invalidate the complete cache as we have lost + * some inval messages and hence don't know what needs to be invalidated. + */ +#define MAX_DISTR_INVAL_MSG_PER_TXN \ + ((8 * 1024 * 1024) / sizeof(SharedInvalidationMessage)) + /* entry for a hash table we use to map from xid to our transaction state */ typedef struct ReorderBufferTXNByIdEnt { @@ -219,8 +232,8 @@ int debug_logical_replication_streaming = DEBUG_LOGICAL_REP_STREAMING_BUFFERED * primary reorderbuffer support routines * --------------------------------------- */ -static ReorderBufferTXN *ReorderBufferGetTXN(ReorderBuffer *rb); -static void ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn); +static ReorderBufferTXN *ReorderBufferAllocTXN(ReorderBuffer *rb); +static void ReorderBufferFreeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn); static ReorderBufferTXN *ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, bool *is_new, XLogRecPtr lsn, bool create_as_top); @@ -260,6 +273,8 @@ static void ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, static void ReorderBufferRestoreCleanup(ReorderBuffer *rb, ReorderBufferTXN *txn); static void ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prepared); +static void ReorderBufferMaybeMarkTXNStreamed(ReorderBuffer *rb, ReorderBufferTXN *txn); +static bool ReorderBufferCheckAndTruncateAbortedTXN(ReorderBuffer *rb, ReorderBufferTXN *txn); static void ReorderBufferCleanupSerializedTXNs(const char *slotname); static void ReorderBufferSerializedPath(char *path, ReplicationSlot *slot, TransactionId xid, XLogSegNo segno); @@ -337,15 +352,20 @@ ReorderBufferAllocate(void) sizeof(ReorderBufferTXN)); /* - * XXX the allocation sizes used below pre-date generation context's block - * growing code. These values should likely be benchmarked and set to - * more suitable values. + * To minimize memory fragmentation caused by long-running transactions + * with changes spanning multiple memory blocks, we use a single + * fixed-size memory block for decoded tuple storage. The performance + * testing showed that the default memory block size maintains logical + * decoding performance without causing fragmentation due to concurrent + * transactions. One might think that we can use the max size as + * SLAB_LARGE_BLOCK_SIZE but the test also showed it doesn't help resolve + * the memory fragmentation. */ buffer->tup_context = GenerationContextCreate(new_ctx, "Tuples", - SLAB_LARGE_BLOCK_SIZE, - SLAB_LARGE_BLOCK_SIZE, - SLAB_LARGE_BLOCK_SIZE); + SLAB_DEFAULT_BLOCK_SIZE, + SLAB_DEFAULT_BLOCK_SIZE, + SLAB_DEFAULT_BLOCK_SIZE); hash_ctl.keysize = sizeof(TransactionId); hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt); @@ -408,10 +428,10 @@ ReorderBufferFree(ReorderBuffer *rb) } /* - * Get an unused, possibly preallocated, ReorderBufferTXN. + * Allocate a new ReorderBufferTXN. */ static ReorderBufferTXN * -ReorderBufferGetTXN(ReorderBuffer *rb) +ReorderBufferAllocTXN(ReorderBuffer *rb) { ReorderBufferTXN *txn; @@ -435,7 +455,7 @@ ReorderBufferGetTXN(ReorderBuffer *rb) * Free a ReorderBufferTXN. */ static void -ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) +ReorderBufferFreeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) { /* clean the lookup cache if we were cached (quite likely) */ if (rb->by_txn_last_xid == txn->xid) @@ -464,17 +484,26 @@ ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) txn->invalidations = NULL; } + if (txn->invalidations_distributed) + { + pfree(txn->invalidations_distributed); + txn->invalidations_distributed = NULL; + } + /* Reset the toast hash */ ReorderBufferToastReset(rb, txn); + /* All changes must be deallocated */ + Assert(txn->size == 0); + pfree(txn); } /* - * Get a fresh ReorderBufferChange. + * Allocate a ReorderBufferChange. */ ReorderBufferChange * -ReorderBufferGetChange(ReorderBuffer *rb) +ReorderBufferAllocChange(ReorderBuffer *rb) { ReorderBufferChange *change; @@ -489,8 +518,8 @@ ReorderBufferGetChange(ReorderBuffer *rb) * Free a ReorderBufferChange and update memory accounting, if requested. */ void -ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change, - bool upd_mem) +ReorderBufferFreeChange(ReorderBuffer *rb, ReorderBufferChange *change, + bool upd_mem) { /* update memory accounting info */ if (upd_mem) @@ -506,13 +535,13 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change, case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT: if (change->data.tp.newtuple) { - ReorderBufferReturnTupleBuf(change->data.tp.newtuple); + ReorderBufferFreeTupleBuf(change->data.tp.newtuple); change->data.tp.newtuple = NULL; } if (change->data.tp.oldtuple) { - ReorderBufferReturnTupleBuf(change->data.tp.oldtuple); + ReorderBufferFreeTupleBuf(change->data.tp.oldtuple); change->data.tp.oldtuple = NULL; } break; @@ -540,7 +569,7 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change, case REORDER_BUFFER_CHANGE_TRUNCATE: if (change->data.truncate.relids != NULL) { - ReorderBufferReturnRelids(rb, change->data.truncate.relids); + ReorderBufferFreeRelids(rb, change->data.truncate.relids); change->data.truncate.relids = NULL; } break; @@ -555,11 +584,11 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change, } /* - * Get a fresh HeapTuple fitting a tuple of size tuple_len (excluding header + * Allocate a HeapTuple fitting a tuple of size tuple_len (excluding header * overhead). */ HeapTuple -ReorderBufferGetTupleBuf(ReorderBuffer *rb, Size tuple_len) +ReorderBufferAllocTupleBuf(ReorderBuffer *rb, Size tuple_len) { HeapTuple tuple; Size alloc_len; @@ -574,16 +603,16 @@ ReorderBufferGetTupleBuf(ReorderBuffer *rb, Size tuple_len) } /* - * Free a HeapTuple returned by ReorderBufferGetTupleBuf(). + * Free a HeapTuple returned by ReorderBufferAllocTupleBuf(). */ void -ReorderBufferReturnTupleBuf(HeapTuple tuple) +ReorderBufferFreeTupleBuf(HeapTuple tuple) { pfree(tuple); } /* - * Get an array for relids of truncated relations. + * Allocate an array for relids of truncated relations. * * We use the global memory context (for the whole reorder buffer), because * none of the existing ones seems like a good match (some are SLAB, so we @@ -592,7 +621,7 @@ ReorderBufferReturnTupleBuf(HeapTuple tuple) * not particularly common operation, so it does not seem worth it. */ Oid * -ReorderBufferGetRelids(ReorderBuffer *rb, int nrelids) +ReorderBufferAllocRelids(ReorderBuffer *rb, int nrelids) { Oid *relids; Size alloc_len; @@ -608,7 +637,7 @@ ReorderBufferGetRelids(ReorderBuffer *rb, int nrelids) * Free an array of relids. */ void -ReorderBufferReturnRelids(ReorderBuffer *rb, Oid *relids) +ReorderBufferFreeRelids(ReorderBuffer *rb, Oid *relids) { pfree(relids); } @@ -673,7 +702,7 @@ ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create, Assert(ent != NULL); Assert(lsn != InvalidXLogRecPtr); - ent->txn = ReorderBufferGetTXN(rb); + ent->txn = ReorderBufferAllocTXN(rb); ent->txn->xid = xid; txn = ent->txn; txn->first_lsn = lsn; @@ -785,17 +814,17 @@ ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true); /* - * While streaming the previous changes we have detected that the - * transaction is aborted. So there is no point in collecting further - * changes for it. + * If we have detected that the transaction is aborted while streaming the + * previous changes or by checking its CLOG, there is no point in + * collecting further changes for it. */ - if (txn->concurrent_abort) + if (rbtxn_is_aborted(txn)) { /* * We don't need to update memory accounting for this change as we * have not added it to the queue yet. */ - ReorderBufferReturnChange(rb, change, false); + ReorderBufferFreeChange(rb, change, false); return; } @@ -861,7 +890,7 @@ ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid, oldcontext = MemoryContextSwitchTo(rb->context); - change = ReorderBufferGetChange(rb); + change = ReorderBufferAllocChange(rb); change->action = REORDER_BUFFER_CHANGE_MESSAGE; change->data.msg.prefix = pstrdup(prefix); change->data.msg.message_size = message_size; @@ -1397,7 +1426,7 @@ ReorderBufferIterTXNNext(ReorderBuffer *rb, ReorderBufferIterTXNState *state) { change = dlist_container(ReorderBufferChange, node, dlist_pop_head_node(&state->old_change)); - ReorderBufferReturnChange(rb, change, true); + ReorderBufferFreeChange(rb, change, true); Assert(dlist_is_empty(&state->old_change)); } @@ -1489,7 +1518,7 @@ ReorderBufferIterTXNFinish(ReorderBuffer *rb, change = dlist_container(ReorderBufferChange, node, dlist_pop_head_node(&state->old_change)); - ReorderBufferReturnChange(rb, change, true); + ReorderBufferFreeChange(rb, change, true); Assert(dlist_is_empty(&state->old_change)); } @@ -1506,6 +1535,7 @@ ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) { bool found; dlist_mutable_iter iter; + Size mem_freed = 0; /* cleanup subtransactions & their changes */ dlist_foreach_modify(iter, &txn->subtxns) @@ -1535,9 +1565,20 @@ ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) /* Check we're not mixing changes from different transactions. */ Assert(change->txn == txn); - ReorderBufferReturnChange(rb, change, false); + /* + * Instead of updating the memory counter for individual changes, we + * sum up the size of memory to free so we can update the memory + * counter all together below. This saves costs of maintaining the + * max-heap. + */ + mem_freed += ReorderBufferChangeSize(change); + + ReorderBufferFreeChange(rb, change, false); } + /* Update the memory counter */ + ReorderBufferChangeMemoryUpdate(rb, NULL, txn, false, mem_freed); + /* * Cleanup the tuplecids we stored for decoding catalog snapshot access. * They are always stored in the toplevel transaction. @@ -1552,7 +1593,7 @@ ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) Assert(change->txn == txn); Assert(change->action == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID); - ReorderBufferReturnChange(rb, change, true); + ReorderBufferFreeChange(rb, change, true); } /* @@ -1594,17 +1635,15 @@ ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) if (rbtxn_is_serialized(txn)) ReorderBufferRestoreCleanup(rb, txn); - /* Update the memory counter */ - ReorderBufferChangeMemoryUpdate(rb, NULL, txn, false, txn->size); - /* deallocate */ - ReorderBufferReturnTXN(rb, txn); + ReorderBufferFreeTXN(rb, txn); } /* * Discard changes from a transaction (and subtransactions), either after - * streaming or decoding them at PREPARE. Keep the remaining info - - * transactions, tuplecids, invalidations and snapshots. + * streaming, decoding them at PREPARE, or detecting the transaction abort. + * Keep the remaining info - transactions, tuplecids, invalidations and + * snapshots. * * We additionally remove tuplecids after decoding the transaction at prepare * time as we only need to perform invalidation at rollback or commit prepared. @@ -1616,6 +1655,7 @@ static void ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prepared) { dlist_mutable_iter iter; + Size mem_freed = 0; /* cleanup subtransactions & their changes */ dlist_foreach_modify(iter, &txn->subtxns) @@ -1632,6 +1672,7 @@ ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prep Assert(rbtxn_is_known_subxact(subtxn)); Assert(subtxn->nsubtxns == 0); + ReorderBufferMaybeMarkTXNStreamed(rb, subtxn); ReorderBufferTruncateTXN(rb, subtxn, txn_prepared); } @@ -1645,32 +1686,22 @@ ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prep /* Check we're not mixing changes from different transactions. */ Assert(change->txn == txn); - /* remove the change from it's containing list */ + /* remove the change from its containing list */ dlist_delete(&change->node); - ReorderBufferReturnChange(rb, change, false); + /* + * Instead of updating the memory counter for individual changes, we + * sum up the size of memory to free so we can update the memory + * counter all together below. This saves costs of maintaining the + * max-heap. + */ + mem_freed += ReorderBufferChangeSize(change); + + ReorderBufferFreeChange(rb, change, false); } /* Update the memory counter */ - ReorderBufferChangeMemoryUpdate(rb, NULL, txn, false, txn->size); - - /* - * Mark the transaction as streamed. - * - * The top-level transaction, is marked as streamed always, even if it - * does not contain any changes (that is, when all the changes are in - * subtransactions). - * - * For subtransactions, we only mark them as streamed when there are - * changes in them. - * - * We do it this way because of aborts - we don't want to send aborts for - * XIDs the downstream is not aware of. And of course, it always knows - * about the toplevel xact (we send the XID in all messages), but we never - * stream XIDs of empty subxacts. - */ - if ((!txn_prepared) && (rbtxn_is_toptxn(txn) || (txn->nentries_mem != 0))) - txn->txn_flags |= RBTXN_IS_STREAMED; + ReorderBufferChangeMemoryUpdate(rb, NULL, txn, false, mem_freed); if (txn_prepared) { @@ -1692,7 +1723,7 @@ ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prep /* Remove the change from its containing list. */ dlist_delete(&change->node); - ReorderBufferReturnChange(rb, change, true); + ReorderBufferFreeChange(rb, change, true); } } @@ -1726,6 +1757,76 @@ ReorderBufferTruncateTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, bool txn_prep txn->nentries = 0; } +/* + * Check the transaction status by CLOG lookup and discard all changes if + * the transaction is aborted. The transaction status is cached in + * txn->txn_flags so we can skip future changes and avoid CLOG lookups on the + * next call. + * + * Return true if the transaction is aborted, otherwise return false. + * + * When the 'debug_logical_replication_streaming' is set to "immediate", we + * don't check the transaction status, meaning the caller will always process + * this transaction. + */ +static bool +ReorderBufferCheckAndTruncateAbortedTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) +{ + /* Quick return for regression tests */ + if (unlikely(debug_logical_replication_streaming == DEBUG_LOGICAL_REP_STREAMING_IMMEDIATE)) + return false; + + /* + * Quick return if the transaction status is already known. + */ + + if (rbtxn_is_committed(txn)) + return false; + if (rbtxn_is_aborted(txn)) + { + /* Already-aborted transactions should not have any changes */ + Assert(txn->size == 0); + + return true; + } + + /* Otherwise, check the transaction status using CLOG lookup */ + + if (TransactionIdIsInProgress(txn->xid)) + return false; + + if (TransactionIdDidCommit(txn->xid)) + { + /* + * Remember the transaction is committed so that we can skip CLOG + * check next time, avoiding the pressure on CLOG lookup. + */ + Assert(!rbtxn_is_aborted(txn)); + txn->txn_flags |= RBTXN_IS_COMMITTED; + return false; + } + + /* + * The transaction aborted. We discard both the changes collected so far + * and the toast reconstruction data. The full cleanup will happen as part + * of decoding ABORT record of this transaction. + */ + ReorderBufferTruncateTXN(rb, txn, rbtxn_is_prepared(txn)); + ReorderBufferToastReset(rb, txn); + + /* All changes should be discarded */ + Assert(txn->size == 0); + + /* + * Mark the transaction as aborted so we can ignore future changes of this + * transaction. + */ + Assert(!rbtxn_is_committed(txn)); + txn->txn_flags |= RBTXN_IS_ABORTED; + + return true; +} + /* * Build a hash with a (relfilelocator, ctid) -> (cmin, cmax) mapping for use by * HeapTupleSatisfiesHistoricMVCC. @@ -1835,9 +1936,9 @@ ReorderBufferCopySnap(ReorderBuffer *rb, Snapshot orig_snap, snap->subxip[i++] = txn->xid; /* - * subxcnt isn't decreased when subtransactions abort, so count manually. - * Since it's an upper boundary it is safe to use it for the allocation - * above. + * txn->nsubtxns isn't decreased when subtransactions abort, so count + * manually. Since it's an upper boundary it is safe to use it for the + * allocation above. */ snap->subxcnt = 1; @@ -1885,13 +1986,15 @@ ReorderBufferStreamCommit(ReorderBuffer *rb, ReorderBufferTXN *txn) ReorderBufferStreamTXN(rb, txn); - if (rbtxn_prepared(txn)) + if (rbtxn_is_prepared(txn)) { /* * Note, we send stream prepare even if a concurrent abort is * detected. See DecodePrepare for more information. */ + Assert(!rbtxn_sent_prepare(txn)); rb->stream_prepare(rb, txn, txn->final_lsn); + txn->txn_flags |= RBTXN_SENT_PREPARE; /* * This is a PREPARED transaction, part of a two-phase commit. The @@ -2026,6 +2129,30 @@ ReorderBufferSaveTXNSnapshot(ReorderBuffer *rb, ReorderBufferTXN *txn, txn, command_id); } +/* + * Mark the given transaction as streamed if it's a top-level transaction + * or has changes. + */ +static void +ReorderBufferMaybeMarkTXNStreamed(ReorderBuffer *rb, ReorderBufferTXN *txn) +{ + /* + * The top-level transaction, is marked as streamed always, even if it + * does not contain any changes (that is, when all the changes are in + * subtransactions). + * + * For subtransactions, we only mark them as streamed when there are + * changes in them. + * + * We do it this way because of aborts - we don't want to send aborts for + * XIDs the downstream is not aware of. And of course, it always knows + * about the top-level xact (we send the XID in all messages), but we + * never stream XIDs of empty subxacts. + */ + if (rbtxn_is_toptxn(txn) || (txn->nentries_mem != 0)) + txn->txn_flags |= RBTXN_IS_STREAMED; +} + /* * Helper function for ReorderBufferProcessTXN to handle the concurrent * abort of the streaming transaction. This resets the TXN such that it @@ -2041,7 +2168,7 @@ ReorderBufferResetTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, ReorderBufferChange *specinsert) { /* Discard the changes that we just streamed */ - ReorderBufferTruncateTXN(rb, txn, rbtxn_prepared(txn)); + ReorderBufferTruncateTXN(rb, txn, rbtxn_is_prepared(txn)); /* Free all resources allocated for toast reconstruction */ ReorderBufferToastReset(rb, txn); @@ -2049,7 +2176,7 @@ ReorderBufferResetTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, /* Return the spec insert change if it is not NULL */ if (specinsert != NULL) { - ReorderBufferReturnChange(rb, specinsert, true); + ReorderBufferFreeChange(rb, specinsert, true); specinsert = NULL; } @@ -2062,6 +2189,9 @@ ReorderBufferResetTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, rb->stream_stop(rb, txn, last_lsn); ReorderBufferSaveTXNSnapshot(rb, txn, snapshot_now, command_id); } + + /* All changes must be deallocated */ + Assert(txn->size == 0); } /* @@ -2126,7 +2256,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, */ if (!streaming) { - if (rbtxn_prepared(txn)) + if (rbtxn_is_prepared(txn)) rb->begin_prepare(rb, txn); else rb->begin(rb, txn); @@ -2168,7 +2298,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, * required for the cases when we decode the changes before the * COMMIT record is processed. */ - if (streaming || rbtxn_prepared(change->txn)) + if (streaming || rbtxn_is_prepared(change->txn)) { curtxn = change->txn; SetupCheckXidLive(curtxn->xid); @@ -2217,7 +2347,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, else if (reloid == InvalidOid) elog(ERROR, "could not map filenumber \"%s\" to relation OID", relpathperm(change->data.tp.rlocator, - MAIN_FORKNUM)); + MAIN_FORKNUM).str); relation = RelationIdGetRelation(reloid); @@ -2225,7 +2355,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, elog(ERROR, "could not open relation with OID %u (for filenumber \"%s\")", reloid, relpathperm(change->data.tp.rlocator, - MAIN_FORKNUM)); + MAIN_FORKNUM).str); if (!RelationIsLogicallyLogged(relation)) goto change_done; @@ -2287,7 +2417,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, */ if (specinsert != NULL) { - ReorderBufferReturnChange(rb, specinsert, true); + ReorderBufferFreeChange(rb, specinsert, true); specinsert = NULL; } @@ -2316,7 +2446,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, /* clear out a pending (and thus failed) speculation */ if (specinsert != NULL) { - ReorderBufferReturnChange(rb, specinsert, true); + ReorderBufferFreeChange(rb, specinsert, true); specinsert = NULL; } @@ -2346,7 +2476,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, ReorderBufferToastReset(rb, txn); /* We don't need this record anymore. */ - ReorderBufferReturnChange(rb, specinsert, true); + ReorderBufferFreeChange(rb, specinsert, true); specinsert = NULL; } break; @@ -2513,8 +2643,12 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, * Call either PREPARE (for two-phase transactions) or COMMIT (for * regular ones). */ - if (rbtxn_prepared(txn)) + if (rbtxn_is_prepared(txn)) + { + Assert(!rbtxn_sent_prepare(txn)); rb->prepare(rb, txn, commit_lsn); + txn->txn_flags |= RBTXN_SENT_PREPARE; + } else rb->commit(rb, txn, commit_lsn); } @@ -2545,7 +2679,17 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, AbortCurrentTransaction(); /* make sure there's no cache pollution */ - ReorderBufferExecuteInvalidations(txn->ninvalidations, txn->invalidations); + if (rbtxn_distr_inval_overflowed(txn)) + { + Assert(txn->ninvalidations_distributed == 0); + InvalidateSystemCaches(); + } + else + { + ReorderBufferExecuteInvalidations(txn->ninvalidations, txn->invalidations); + ReorderBufferExecuteInvalidations(txn->ninvalidations_distributed, + txn->invalidations_distributed); + } if (using_subtxn) RollbackAndReleaseCurrentSubTransaction(); @@ -2564,9 +2708,12 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, * For 4, as the entire txn has been decoded, we can fully clean up * the TXN reorder buffer. */ - if (streaming || rbtxn_prepared(txn)) + if (streaming || rbtxn_is_prepared(txn)) { - ReorderBufferTruncateTXN(rb, txn, rbtxn_prepared(txn)); + if (streaming) + ReorderBufferMaybeMarkTXNStreamed(rb, txn); + + ReorderBufferTruncateTXN(rb, txn, rbtxn_is_prepared(txn)); /* Reset the CheckXidAlive */ CheckXidAlive = InvalidTransactionId; } @@ -2591,8 +2738,17 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, AbortCurrentTransaction(); /* make sure there's no cache pollution */ - ReorderBufferExecuteInvalidations(txn->ninvalidations, - txn->invalidations); + if (rbtxn_distr_inval_overflowed(txn)) + { + Assert(txn->ninvalidations_distributed == 0); + InvalidateSystemCaches(); + } + else + { + ReorderBufferExecuteInvalidations(txn->ninvalidations, txn->invalidations); + ReorderBufferExecuteInvalidations(txn->ninvalidations_distributed, + txn->invalidations_distributed); + } if (using_subtxn) RollbackAndReleaseCurrentSubTransaction(); @@ -2610,7 +2766,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, * during a two-phase commit. */ if (errdata->sqlerrcode == ERRCODE_TRANSACTION_ROLLBACK && - (stream_started || rbtxn_prepared(txn))) + (stream_started || rbtxn_is_prepared(txn))) { /* curtxn must be set for streaming or prepared transactions */ Assert(curtxn); @@ -2619,7 +2775,14 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, FlushErrorState(); FreeErrorData(errdata); errdata = NULL; - curtxn->concurrent_abort = true; + + /* Remember the transaction is aborted. */ + Assert(!rbtxn_is_committed(curtxn)); + curtxn->txn_flags |= RBTXN_IS_ABORTED; + + /* Mark the transaction is streamed if appropriate */ + if (stream_started) + ReorderBufferMaybeMarkTXNStreamed(rb, txn); /* Reset the TXN so that it is allowed to stream remaining data. */ ReorderBufferResetTXN(rb, txn, snapshot_now, @@ -2690,7 +2853,7 @@ ReorderBufferReplay(ReorderBufferTXN *txn, * Removing this txn before a commit might result in the computation * of an incorrect restart_lsn. See SnapBuildProcessRunningXacts. */ - if (!rbtxn_prepared(txn)) + if (!rbtxn_is_prepared(txn)) ReorderBufferCleanupTXN(rb, txn); return; } @@ -2727,7 +2890,8 @@ ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid, } /* - * Record the prepare information for a transaction. + * Record the prepare information for a transaction. Also, mark the transaction + * as a prepared transaction. */ bool ReorderBufferRememberPrepareInfo(ReorderBuffer *rb, TransactionId xid, @@ -2753,6 +2917,10 @@ ReorderBufferRememberPrepareInfo(ReorderBuffer *rb, TransactionId xid, txn->origin_id = origin_id; txn->origin_lsn = origin_lsn; + /* Mark this transaction as a prepared transaction */ + Assert((txn->txn_flags & RBTXN_PREPARE_STATUS_MASK) == 0); + txn->txn_flags |= RBTXN_IS_PREPARED; + return true; } @@ -2768,6 +2936,8 @@ ReorderBufferSkipPrepare(ReorderBuffer *rb, TransactionId xid) if (txn == NULL) return; + /* txn must have been marked as a prepared transaction */ + Assert((txn->txn_flags & RBTXN_PREPARE_STATUS_MASK) == RBTXN_IS_PREPARED); txn->txn_flags |= RBTXN_SKIPPED_PREPARE; } @@ -2789,25 +2959,29 @@ ReorderBufferPrepare(ReorderBuffer *rb, TransactionId xid, if (txn == NULL) return; - txn->txn_flags |= RBTXN_PREPARE; - txn->gid = pstrdup(gid); - - /* The prepare info must have been updated in txn by now. */ + /* + * txn must have been marked as a prepared transaction and must have + * neither been skipped nor sent a prepare. Also, the prepare info must + * have been updated in it by now. + */ + Assert((txn->txn_flags & RBTXN_PREPARE_STATUS_MASK) == RBTXN_IS_PREPARED); Assert(txn->final_lsn != InvalidXLogRecPtr); + txn->gid = pstrdup(gid); + ReorderBufferReplay(txn, rb, xid, txn->final_lsn, txn->end_lsn, txn->xact_time.prepare_time, txn->origin_id, txn->origin_lsn); /* - * We send the prepare for the concurrently aborted xacts so that later - * when rollback prepared is decoded and sent, the downstream should be - * able to rollback such a xact. See comments atop DecodePrepare. - * - * Note, for the concurrent_abort + streaming case a stream_prepare was - * already sent within the ReorderBufferReplay call above. + * Send a prepare if not already done so. This might occur if we have + * detected a concurrent abort while replaying the non-streaming + * transaction. */ - if (txn->concurrent_abort && !rbtxn_is_streamed(txn)) + if (!rbtxn_sent_prepare(txn)) + { rb->prepare(rb, txn, txn->final_lsn); + txn->txn_flags |= RBTXN_SENT_PREPARE; + } } /* @@ -2850,12 +3024,13 @@ ReorderBufferFinishPrepared(ReorderBuffer *rb, TransactionId xid, */ if ((txn->final_lsn < two_phase_at) && is_commit) { - txn->txn_flags |= RBTXN_PREPARE; - /* - * The prepare info must have been updated in txn even if we skip - * prepare. + * txn must have been marked as a prepared transaction and skipped but + * not sent a prepare. Also, the prepare info must have been updated + * in txn even if we skip prepare. */ + Assert((txn->txn_flags & RBTXN_PREPARE_STATUS_MASK) == + (RBTXN_IS_PREPARED | RBTXN_SKIPPED_PREPARE)); Assert(txn->final_lsn != InvalidXLogRecPtr); /* @@ -2922,7 +3097,8 @@ ReorderBufferAbort(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, * We might have decoded changes for this transaction that could load * the cache as per the current transaction's view (consider DDL's * happened in this transaction). We don't want the decoding of future - * transactions to use those cache entries so execute invalidations. + * transactions to use those cache entries so execute only the inval + * messages in this transaction. */ if (txn->ninvalidations > 0) ReorderBufferImmediateInvalidation(rb, txn->ninvalidations, @@ -3009,9 +3185,10 @@ ReorderBufferForget(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn) txn->final_lsn = lsn; /* - * Process cache invalidation messages if there are any. Even if we're not - * interested in the transaction's contents, it could have manipulated the - * catalog and we need to update the caches according to that. + * Process only cache invalidation messages in this transaction if there + * are any. Even if we're not interested in the transaction's contents, it + * could have manipulated the catalog and we need to update the caches + * according to that. */ if (txn->base_snapshot != NULL && txn->ninvalidations > 0) ReorderBufferImmediateInvalidation(rb, txn->ninvalidations, @@ -3115,7 +3292,7 @@ void ReorderBufferAddSnapshot(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, Snapshot snap) { - ReorderBufferChange *change = ReorderBufferGetChange(rb); + ReorderBufferChange *change = ReorderBufferAllocChange(rb); change->data.snapshot = snap; change->action = REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT; @@ -3164,7 +3341,7 @@ void ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, CommandId cid) { - ReorderBufferChange *change = ReorderBufferGetChange(rb); + ReorderBufferChange *change = ReorderBufferAllocChange(rb); change->data.command_id = cid; change->action = REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID; @@ -3265,7 +3442,7 @@ ReorderBufferAddNewTupleCids(ReorderBuffer *rb, TransactionId xid, ItemPointerData tid, CommandId cmin, CommandId cmax, CommandId combocid) { - ReorderBufferChange *change = ReorderBufferGetChange(rb); + ReorderBufferChange *change = ReorderBufferAllocChange(rb); ReorderBufferTXN *txn; txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true); @@ -3283,6 +3460,57 @@ ReorderBufferAddNewTupleCids(ReorderBuffer *rb, TransactionId xid, txn->ntuplecids++; } +/* + * Add new invalidation messages to the reorder buffer queue. + */ +static void +ReorderBufferQueueInvalidations(ReorderBuffer *rb, TransactionId xid, + XLogRecPtr lsn, Size nmsgs, + SharedInvalidationMessage *msgs) +{ + ReorderBufferChange *change; + + change = ReorderBufferAllocChange(rb); + change->action = REORDER_BUFFER_CHANGE_INVALIDATION; + change->data.inval.ninvalidations = nmsgs; + change->data.inval.invalidations = (SharedInvalidationMessage *) + palloc(sizeof(SharedInvalidationMessage) * nmsgs); + memcpy(change->data.inval.invalidations, msgs, + sizeof(SharedInvalidationMessage) * nmsgs); + + ReorderBufferQueueChange(rb, xid, lsn, change, false); +} + +/* + * A helper function for ReorderBufferAddInvalidations() and + * ReorderBufferAddDistributedInvalidations() to accumulate the invalidation + * messages to the **invals_out. + */ +static void +ReorderBufferAccumulateInvalidations(SharedInvalidationMessage **invals_out, + uint32 *ninvals_out, + SharedInvalidationMessage *msgs_new, + Size nmsgs_new) +{ + if (*ninvals_out == 0) + { + *ninvals_out = nmsgs_new; + *invals_out = (SharedInvalidationMessage *) + palloc(sizeof(SharedInvalidationMessage) * nmsgs_new); + memcpy(*invals_out, msgs_new, sizeof(SharedInvalidationMessage) * nmsgs_new); + } + else + { + /* Enlarge the array of inval messages */ + *invals_out = (SharedInvalidationMessage *) + repalloc(*invals_out, sizeof(SharedInvalidationMessage) * + (*ninvals_out + nmsgs_new)); + memcpy(*invals_out + *ninvals_out, msgs_new, + nmsgs_new * sizeof(SharedInvalidationMessage)); + *ninvals_out += nmsgs_new; + } +} + /* * Accumulate the invalidations for executing them later. * @@ -3303,7 +3531,6 @@ ReorderBufferAddInvalidations(ReorderBuffer *rb, TransactionId xid, { ReorderBufferTXN *txn; MemoryContext oldcontext; - ReorderBufferChange *change; txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true); @@ -3318,35 +3545,76 @@ ReorderBufferAddInvalidations(ReorderBuffer *rb, TransactionId xid, Assert(nmsgs > 0); - /* Accumulate invalidations. */ - if (txn->ninvalidations == 0) - { - txn->ninvalidations = nmsgs; - txn->invalidations = (SharedInvalidationMessage *) - palloc(sizeof(SharedInvalidationMessage) * nmsgs); - memcpy(txn->invalidations, msgs, - sizeof(SharedInvalidationMessage) * nmsgs); - } - else + ReorderBufferAccumulateInvalidations(&txn->invalidations, + &txn->ninvalidations, + msgs, nmsgs); + + ReorderBufferQueueInvalidations(rb, xid, lsn, nmsgs, msgs); + + MemoryContextSwitchTo(oldcontext); +} + +/* + * Accumulate the invalidations distributed by other committed transactions + * for executing them later. + * + * This function is similar to ReorderBufferAddInvalidations() but stores + * the given inval messages to the txn->invalidations_distributed with the + * overflow check. + * + * This needs to be called by committed transactions to distribute their + * inval messages to in-progress transactions. + */ +void +ReorderBufferAddDistributedInvalidations(ReorderBuffer *rb, TransactionId xid, + XLogRecPtr lsn, Size nmsgs, + SharedInvalidationMessage *msgs) +{ + ReorderBufferTXN *txn; + MemoryContext oldcontext; + + txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true); + + oldcontext = MemoryContextSwitchTo(rb->context); + + /* + * Collect all the invalidations under the top transaction, if available, + * so that we can execute them all together. See comments + * ReorderBufferAddInvalidations. + */ + txn = rbtxn_get_toptxn(txn); + + Assert(nmsgs > 0); + + if (!rbtxn_distr_inval_overflowed(txn)) { - txn->invalidations = (SharedInvalidationMessage *) - repalloc(txn->invalidations, sizeof(SharedInvalidationMessage) * - (txn->ninvalidations + nmsgs)); + /* + * Check the transaction has enough space for storing distributed + * invalidation messages. + */ + if (txn->ninvalidations_distributed + nmsgs >= MAX_DISTR_INVAL_MSG_PER_TXN) + { + /* + * Mark the invalidation message as overflowed and free up the + * messages accumulated so far. + */ + txn->txn_flags |= RBTXN_DISTR_INVAL_OVERFLOWED; - memcpy(txn->invalidations + txn->ninvalidations, msgs, - nmsgs * sizeof(SharedInvalidationMessage)); - txn->ninvalidations += nmsgs; + if (txn->invalidations_distributed) + { + pfree(txn->invalidations_distributed); + txn->invalidations_distributed = NULL; + txn->ninvalidations_distributed = 0; + } + } + else + ReorderBufferAccumulateInvalidations(&txn->invalidations_distributed, + &txn->ninvalidations_distributed, + msgs, nmsgs); } - change = ReorderBufferGetChange(rb); - change->action = REORDER_BUFFER_CHANGE_INVALIDATION; - change->data.inval.ninvalidations = nmsgs; - change->data.inval.invalidations = (SharedInvalidationMessage *) - palloc(sizeof(SharedInvalidationMessage) * nmsgs); - memcpy(change->data.inval.invalidations, msgs, - sizeof(SharedInvalidationMessage) * nmsgs); - - ReorderBufferQueueChange(rb, xid, lsn, change, false); + /* Queue the invalidation messages into the transaction */ + ReorderBufferQueueInvalidations(rb, xid, lsn, nmsgs, msgs); MemoryContextSwitchTo(oldcontext); } @@ -3537,7 +3805,8 @@ ReorderBufferLargestTXN(ReorderBuffer *rb) } /* - * Find the largest streamable toplevel transaction to evict (by streaming). + * Find the largest streamable (and non-aborted) toplevel transaction to evict + * (by streaming). * * This can be seen as an optimized version of ReorderBufferLargestTXN, which * should give us the same transaction (because we don't update memory account @@ -3579,9 +3848,15 @@ ReorderBufferLargestStreamableTopTXN(ReorderBuffer *rb) /* base_snapshot must be set */ Assert(txn->base_snapshot != NULL); + /* Don't consider these kinds of transactions for eviction. */ + if (rbtxn_has_partial_change(txn) || + !rbtxn_has_streamable_change(txn) || + rbtxn_is_aborted(txn)) + continue; + + /* Find the largest of the eviction candidates. */ if ((largest == NULL || txn->total_size > largest_size) && - (txn->total_size > 0) && !(rbtxn_has_partial_change(txn)) && - rbtxn_has_streamable_change(txn)) + (txn->total_size > 0)) { largest = txn; largest_size = txn->total_size; @@ -3614,7 +3889,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb) * haven't exceeded the memory limit. */ if (debug_logical_replication_streaming == DEBUG_LOGICAL_REP_STREAMING_BUFFERED && - rb->size < logical_decoding_work_mem * 1024L) + rb->size < logical_decoding_work_mem * (Size) 1024) return; /* @@ -3627,13 +3902,13 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb) * because a user can reduce the logical_decoding_work_mem to a smaller * value before the most recent change. */ - while (rb->size >= logical_decoding_work_mem * 1024L || + while (rb->size >= logical_decoding_work_mem * (Size) 1024 || (debug_logical_replication_streaming == DEBUG_LOGICAL_REP_STREAMING_IMMEDIATE && rb->size > 0)) { /* - * Pick the largest transaction and evict it from memory by streaming, - * if possible. Otherwise, spill to disk. + * Pick the largest non-aborted transaction and evict it from memory + * by streaming, if possible. Otherwise, spill to disk. */ if (ReorderBufferCanStartStreaming(rb) && (txn = ReorderBufferLargestStreamableTopTXN(rb)) != NULL) @@ -3643,6 +3918,10 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb) Assert(txn->total_size > 0); Assert(rb->size >= txn->total_size); + /* skip the transaction if aborted */ + if (ReorderBufferCheckAndTruncateAbortedTXN(rb, txn)) + continue; + ReorderBufferStreamTXN(rb, txn); } else @@ -3658,6 +3937,10 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb) Assert(txn->size > 0); Assert(rb->size >= txn->size); + /* skip the transaction if aborted */ + if (ReorderBufferCheckAndTruncateAbortedTXN(rb, txn)) + continue; + ReorderBufferSerializeTXN(rb, txn); } @@ -3670,8 +3953,7 @@ ReorderBufferCheckMemoryLimit(ReorderBuffer *rb) } /* We must be under the memory limit now. */ - Assert(rb->size < logical_decoding_work_mem * 1024L); - + Assert(rb->size < logical_decoding_work_mem * (Size) 1024); } /* @@ -3739,7 +4021,7 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn) ReorderBufferSerializeChange(rb, txn, fd, change); dlist_delete(&change->node); - ReorderBufferReturnChange(rb, change, false); + ReorderBufferFreeChange(rb, change, false); spilled++; } @@ -4243,7 +4525,7 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn, dlist_container(ReorderBufferChange, node, cleanup_iter.cur); dlist_delete(&cleanup->node); - ReorderBufferReturnChange(rb, cleanup, true); + ReorderBufferFreeChange(rb, cleanup, true); } txn->nentries_mem = 0; Assert(dlist_is_empty(&txn->changes)); @@ -4376,7 +4658,7 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, ondisk = (ReorderBufferDiskChange *) data; - change = ReorderBufferGetChange(rb); + change = ReorderBufferAllocChange(rb); /* copy static part */ memcpy(change, &ondisk->change, sizeof(ReorderBufferChange)); @@ -4396,7 +4678,7 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, uint32 tuplelen = ((HeapTuple) data)->t_len; change->data.tp.oldtuple = - ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader); + ReorderBufferAllocTupleBuf(rb, tuplelen - SizeofHeapTupleHeader); /* restore ->tuple */ memcpy(change->data.tp.oldtuple, data, @@ -4421,7 +4703,7 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, sizeof(uint32)); change->data.tp.newtuple = - ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader); + ReorderBufferAllocTupleBuf(rb, tuplelen - SizeofHeapTupleHeader); /* restore ->tuple */ memcpy(change->data.tp.newtuple, data, @@ -4503,8 +4785,7 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn, { Oid *relids; - relids = ReorderBufferGetRelids(rb, - change->data.truncate.nrelids); + relids = ReorderBufferAllocRelids(rb, change->data.truncate.nrelids); memcpy(relids, data, change->data.truncate.nrelids * sizeof(Oid)); change->data.truncate.relids = relids; @@ -4571,9 +4852,9 @@ ReorderBufferCleanupSerializedTXNs(const char *slotname) DIR *spill_dir; struct dirent *spill_de; struct stat statbuf; - char path[MAXPGPATH * 2 + 12]; + char path[MAXPGPATH * 2 + sizeof(PG_REPLSLOT_DIR)]; - sprintf(path, "pg_replslot/%s", slotname); + sprintf(path, "%s/%s", PG_REPLSLOT_DIR, slotname); /* we're only handling directories here, skip if it's not ours */ if (lstat(path, &statbuf) == 0 && !S_ISDIR(statbuf.st_mode)) @@ -4586,14 +4867,14 @@ ReorderBufferCleanupSerializedTXNs(const char *slotname) if (strncmp(spill_de->d_name, "xid", 3) == 0) { snprintf(path, sizeof(path), - "pg_replslot/%s/%s", slotname, + "%s/%s/%s", PG_REPLSLOT_DIR, slotname, spill_de->d_name); if (unlink(path) != 0) ereport(ERROR, (errcode_for_file_access(), - errmsg("could not remove file \"%s\" during removal of pg_replslot/%s/xid*: %m", - path, slotname))); + errmsg("could not remove file \"%s\" during removal of %s/%s/xid*: %m", + path, PG_REPLSLOT_DIR, slotname))); } } FreeDir(spill_dir); @@ -4612,7 +4893,8 @@ ReorderBufferSerializedPath(char *path, ReplicationSlot *slot, TransactionId xid XLogSegNoOffsetToRecPtr(segno, 0, wal_segment_size, recptr); - snprintf(path, MAXPGPATH, "pg_replslot/%s/xid-%u-lsn-%X-%X.spill", + snprintf(path, MAXPGPATH, "%s/%s/xid-%u-lsn-%X-%X.spill", + PG_REPLSLOT_DIR, NameStr(MyReplicationSlot->data.name), xid, LSN_FORMAT_ARGS(recptr)); } @@ -4627,8 +4909,8 @@ StartupReorderBuffer(void) DIR *logical_dir; struct dirent *logical_de; - logical_dir = AllocateDir("pg_replslot"); - while ((logical_de = ReadDir(logical_dir, "pg_replslot")) != NULL) + logical_dir = AllocateDir(PG_REPLSLOT_DIR); + while ((logical_de = ReadDir(logical_dir, PG_REPLSLOT_DIR)) != NULL) { if (strcmp(logical_de->d_name, ".") == 0 || strcmp(logical_de->d_name, "..") == 0) @@ -4973,7 +5255,7 @@ ReorderBufferToastReset(ReorderBuffer *rb, ReorderBufferTXN *txn) dlist_container(ReorderBufferChange, node, it.cur); dlist_delete(&change->node); - ReorderBufferReturnChange(rb, change, true); + ReorderBufferFreeChange(rb, change, true); } } @@ -5056,7 +5338,7 @@ ApplyLogicalMappingFile(HTAB *tuplecid_data, Oid relid, const char *fname) int readBytes; LogicalRewriteMappingData map; - sprintf(path, "pg_logical/mappings/%s", fname); + sprintf(path, "%s/%s", PG_LOGICAL_MAPPINGS_DIR, fname); fd = OpenTransientFile(path, O_RDONLY | PG_BINARY); if (fd < 0) ereport(ERROR, @@ -5172,8 +5454,8 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot) ListCell *file; Oid dboid = IsSharedRelation(relid) ? InvalidOid : MyDatabaseId; - mapping_dir = AllocateDir("pg_logical/mappings"); - while ((mapping_de = ReadDir(mapping_dir, "pg_logical/mappings")) != NULL) + mapping_dir = AllocateDir(PG_LOGICAL_MAPPINGS_DIR); + while ((mapping_de = ReadDir(mapping_dir, PG_LOGICAL_MAPPINGS_DIR)) != NULL) { Oid f_dboid; Oid f_relid; @@ -5308,3 +5590,26 @@ ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data, *cmax = ent->cmax; return true; } + +/* + * Count invalidation messages of specified transaction. + * + * Returns number of messages, and msgs is set to the pointer of the linked + * list for the messages. + */ +uint32 +ReorderBufferGetInvalidations(ReorderBuffer *rb, TransactionId xid, + SharedInvalidationMessage **msgs) +{ + ReorderBufferTXN *txn; + + txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr, + false); + + if (txn == NULL) + return 0; + + *msgs = txn->invalidations; + + return txn->ninvalidations; +} diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c index 2d1914ce08551..656e66e0ae0a1 100644 --- a/src/backend/replication/logical/slotsync.c +++ b/src/backend/replication/logical/slotsync.c @@ -3,7 +3,7 @@ * Functionality for synchronizing slots to a standby server from the * primary server. * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/slotsync.c @@ -55,9 +55,7 @@ #include "commands/dbcommands.h" #include "libpq/pqsignal.h" #include "pgstat.h" -#include "postmaster/fork_process.h" #include "postmaster/interrupt.h" -#include "postmaster/postmaster.h" #include "replication/logical.h" #include "replication/slotsync.h" #include "replication/snapbuild.h" @@ -83,7 +81,7 @@ * this flag is set. Note that we don't need to reset this variable as after * promotion the slot sync worker won't be restarted because the pmState * changes to PM_RUN from PM_HOT_STANDBY and we don't support demoting - * primary without restarting the server. See MaybeStartSlotSyncWorker. + * primary without restarting the server. See LaunchMissingBackgroundProcesses. * * The 'syncing' flag is needed to prevent concurrent slot syncs to avoid slot * overwrites. @@ -141,6 +139,7 @@ typedef struct RemoteSlot bool failover; XLogRecPtr restart_lsn; XLogRecPtr confirmed_lsn; + XLogRecPtr two_phase_at; TransactionId catalog_xmin; /* RS_INVAL_NONE if valid, or the reason of invalidation */ @@ -197,14 +196,14 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, * restart_lsn or the initial xmin_horizon computed for the local slot * is ahead of the remote slot. * - * If the slot is persistent, restart_lsn of the synced slot could - * still be ahead of the remote slot. Since we use slot advance - * functionality to keep snapbuild/slot updated, it is possible that - * the restart_lsn is advanced to a later position than it has on the - * primary. This can happen when slot advancing machinery finds - * running xacts record after reaching the consistent state at a later - * point than the primary where it serializes the snapshot and updates - * the restart_lsn. + * If the slot is persistent, both restart_lsn and catalog_xmin of the + * synced slot could still be ahead of the remote slot. Since we use + * slot advance functionality to keep snapbuild/slot updated, it is + * possible that the restart_lsn and catalog_xmin are advanced to a + * later position than it has on the primary. This can happen when + * slot advancing machinery finds running xacts record after reaching + * the consistent state at a later point than the primary where it + * serializes the snapshot and updates the restart_lsn. * * We LOG the message if the slot is temporary as it can help the user * to understand why the slot is not sync-ready. In the case of a @@ -212,9 +211,9 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, * impact the users, so we used DEBUG1 level to log the message. */ ereport(slot->data.persistency == RS_TEMPORARY ? LOG : DEBUG1, - errmsg("could not sync slot \"%s\" as remote slot precedes local slot", + errmsg("could not synchronize replication slot \"%s\" because remote slot precedes local slot", remote_slot->name), - errdetail("Remote slot has LSN %X/%X and catalog xmin %u, but local slot has LSN %X/%X and catalog xmin %u.", + errdetail("The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u.", LSN_FORMAT_ARGS(remote_slot->restart_lsn), remote_slot->catalog_xmin, LSN_FORMAT_ARGS(slot->data.restart_lsn), @@ -222,16 +221,25 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, if (remote_slot_precedes) *remote_slot_precedes = true; + + /* + * Skip updating the configuration. This is required to avoid syncing + * two_phase_at without syncing confirmed_lsn. Otherwise, the prepared + * transaction between old confirmed_lsn and two_phase_at will + * unexpectedly get decoded and sent to the downstream after + * promotion. See comments in ReorderBufferFinishPrepared. + */ + return false; } /* * Attempt to sync LSNs and xmins only if remote slot is ahead of local * slot. */ - else if (remote_slot->confirmed_lsn > slot->data.confirmed_flush || - remote_slot->restart_lsn > slot->data.restart_lsn || - TransactionIdFollows(remote_slot->catalog_xmin, - slot->data.catalog_xmin)) + if (remote_slot->confirmed_lsn > slot->data.confirmed_flush || + remote_slot->restart_lsn > slot->data.restart_lsn || + TransactionIdFollows(remote_slot->catalog_xmin, + slot->data.catalog_xmin)) { /* * We can't directly copy the remote slot's LSN or xmin unless there @@ -278,7 +286,8 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, if (remote_dbid != slot->data.database || remote_slot->two_phase != slot->data.two_phase || remote_slot->failover != slot->data.failover || - strcmp(remote_slot->plugin, NameStr(slot->data.plugin)) != 0) + strcmp(remote_slot->plugin, NameStr(slot->data.plugin)) != 0 || + remote_slot->two_phase_at != slot->data.two_phase_at) { NameData plugin_name; @@ -289,10 +298,17 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid, slot->data.plugin = plugin_name; slot->data.database = remote_dbid; slot->data.two_phase = remote_slot->two_phase; + slot->data.two_phase_at = remote_slot->two_phase_at; slot->data.failover = remote_slot->failover; SpinLockRelease(&slot->mutex); updated_config = true; + + /* + * Ensure that there is no risk of sending prepared transactions + * unexpectedly after the promotion. + */ + Assert(slot->data.two_phase_at <= slot->data.confirmed_flush); } /* @@ -448,7 +464,7 @@ drop_local_obsolete_slots(List *remote_slot_list) if (synced_slot) { - ReplicationSlotAcquire(NameStr(local_slot->data.name), true); + ReplicationSlotAcquire(NameStr(local_slot->data.name), true, false); ReplicationSlotDropAcquired(); } @@ -456,7 +472,7 @@ drop_local_obsolete_slots(List *remote_slot_list) 0, AccessShareLock); ereport(LOG, - errmsg("dropped replication slot \"%s\" of dbid %u", + errmsg("dropped replication slot \"%s\" of database with OID %u", NameStr(local_slot->data.name), local_slot->data.database)); } @@ -576,8 +592,8 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid) if (!found_consistent_snapshot) { ereport(LOG, - errmsg("could not sync slot \"%s\"", remote_slot->name), - errdetail("Logical decoding cannot find consistent point from local slot's LSN %X/%X.", + errmsg("could not synchronize replication slot \"%s\"", remote_slot->name), + errdetail("Logical decoding could not find consistent point from local slot's LSN %X/%X.", LSN_FORMAT_ARGS(slot->data.restart_lsn))); return false; @@ -586,7 +602,7 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid) ReplicationSlotPersist(); ereport(LOG, - errmsg("newly created slot \"%s\" is sync-ready now", + errmsg("newly created replication slot \"%s\" is sync-ready now", remote_slot->name)); return true; @@ -625,7 +641,7 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid) */ ereport(AmLogicalSlotSyncWorkerProcess() ? LOG : ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("skipping slot synchronization as the received slot sync" + errmsg("skipping slot synchronization because the received slot sync" " LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X", LSN_FORMAT_ARGS(remote_slot->confirmed_lsn), remote_slot->name, @@ -667,7 +683,7 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid) * pre-check to ensure that at least one of the slot properties is * changed before acquiring the slot. */ - ReplicationSlotAcquire(remote_slot->name, true); + ReplicationSlotAcquire(remote_slot->name, true, false); Assert(slot == MyReplicationSlot); @@ -790,9 +806,9 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid) static bool synchronize_slots(WalReceiverConn *wrconn) { -#define SLOTSYNC_COLUMN_COUNT 9 +#define SLOTSYNC_COLUMN_COUNT 10 Oid slotRow[SLOTSYNC_COLUMN_COUNT] = {TEXTOID, TEXTOID, LSNOID, - LSNOID, XIDOID, BOOLOID, BOOLOID, TEXTOID, TEXTOID}; + LSNOID, XIDOID, BOOLOID, LSNOID, BOOLOID, TEXTOID, TEXTOID}; WalRcvExecResult *res; TupleTableSlot *tupslot; @@ -800,7 +816,7 @@ synchronize_slots(WalReceiverConn *wrconn) bool some_slot_updated = false; bool started_tx = false; const char *query = "SELECT slot_name, plugin, confirmed_flush_lsn," - " restart_lsn, catalog_xmin, two_phase, failover," + " restart_lsn, catalog_xmin, two_phase, two_phase_at, failover," " database, invalidation_reason" " FROM pg_catalog.pg_replication_slots" " WHERE failover and NOT temporary"; @@ -855,6 +871,9 @@ synchronize_slots(WalReceiverConn *wrconn) &isnull)); Assert(!isnull); + d = slot_getattr(tupslot, ++col, &isnull); + remote_slot->two_phase_at = isnull ? InvalidXLogRecPtr : DatumGetLSN(d); + remote_slot->failover = DatumGetBool(slot_getattr(tupslot, ++col, &isnull)); Assert(!isnull); @@ -962,14 +981,14 @@ validate_remote_info(WalReceiverConn *wrconn) if (res->status != WALRCV_OK_TUPLES) ereport(ERROR, - errmsg("could not fetch primary_slot_name \"%s\" info from the primary server: %s", + errmsg("could not fetch primary slot name \"%s\" info from the primary server: %s", PrimarySlotName, res->err), - errhint("Check if primary_slot_name is configured correctly.")); + errhint("Check if \"primary_slot_name\" is configured correctly.")); tupslot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple); if (!tuplestore_gettupleslot(res->tuplestore, true, false, tupslot)) elog(ERROR, - "failed to fetch tuple for the primary server slot specified by primary_slot_name"); + "failed to fetch tuple for the primary server slot specified by \"primary_slot_name\""); remote_in_recovery = DatumGetBool(slot_getattr(tupslot, 1, &isnull)); Assert(!isnull); @@ -992,10 +1011,9 @@ validate_remote_info(WalReceiverConn *wrconn) if (!primary_slot_valid) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires valid primary_slot_name"), /* translator: second %s is a GUC variable name */ - errdetail("The replication slot \"%s\" specified by %s does not exist on the primary server.", - PrimarySlotName, "primary_slot_name")); + errmsg("replication slot \"%s\" specified by \"%s\" does not exist on primary server", + PrimarySlotName, "primary_slot_name")); ExecClearTuple(tupslot); walrcv_clear_result(res); @@ -1021,13 +1039,14 @@ CheckAndGetDbnameFromConninfo(void) dbname = walrcv_get_dbname_from_conninfo(PrimaryConnInfo); if (dbname == NULL) ereport(ERROR, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), /* - * translator: dbname is a specific option; %s is a GUC variable name + * translator: first %s is a connection option; second %s is a GUC + * variable name */ - errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires dbname to be specified in %s", - "primary_conninfo")); + errmsg("replication slot synchronization requires \"%s\" to be specified in \"%s\"", + "dbname", "primary_conninfo")); return dbname; } @@ -1047,7 +1066,7 @@ ValidateSlotSyncParams(int elevel) if (wal_level < WAL_LEVEL_LOGICAL) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires \"wal_level\" >= \"logical\"")); + errmsg("replication slot synchronization requires \"wal_level\" >= \"logical\"")); /* * A physical replication slot(primary_slot_name) is required on the @@ -1058,9 +1077,9 @@ ValidateSlotSyncParams(int elevel) if (PrimarySlotName == NULL || *PrimarySlotName == '\0') { ereport(elevel, - /* translator: %s is a GUC variable name */ errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires %s to be defined", "primary_slot_name")); + /* translator: %s is a GUC variable name */ + errmsg("replication slot synchronization requires \"%s\" to be set", "primary_slot_name")); return false; } @@ -1072,9 +1091,9 @@ ValidateSlotSyncParams(int elevel) if (!hot_standby_feedback) { ereport(elevel, - /* translator: %s is a GUC variable name */ errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires %s to be enabled", + /* translator: %s is a GUC variable name */ + errmsg("replication slot synchronization requires \"%s\" to be enabled", "hot_standby_feedback")); return false; } @@ -1086,9 +1105,9 @@ ValidateSlotSyncParams(int elevel) if (PrimaryConnInfo == NULL || *PrimaryConnInfo == '\0') { ereport(elevel, - /* translator: %s is a GUC variable name */ errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("slot synchronization requires %s to be defined", + /* translator: %s is a GUC variable name */ + errmsg("replication slot synchronization requires \"%s\" to be set", "primary_conninfo")); return false; } @@ -1126,7 +1145,7 @@ slotsync_reread_config(void) { ereport(LOG, /* translator: %s is a GUC variable name */ - errmsg("slot sync worker will shutdown because %s is disabled", "sync_replication_slots")); + errmsg("replication slot synchronization worker will shut down because \"%s\" is disabled", "sync_replication_slots")); proc_exit(0); } @@ -1135,7 +1154,7 @@ slotsync_reread_config(void) (old_hot_standby_feedback != hot_standby_feedback)) { ereport(LOG, - errmsg("slot sync worker will restart because of a parameter change")); + errmsg("replication slot synchronization worker will restart because of a parameter change")); /* * Reset the last-start time for this worker so that the postmaster @@ -1159,7 +1178,7 @@ ProcessSlotSyncInterrupts(WalReceiverConn *wrconn) if (ShutdownRequestPending) { ereport(LOG, - errmsg("slot sync worker is shutting down on receiving SIGINT")); + errmsg("replication slot synchronization worker is shutting down on receiving SIGINT")); proc_exit(0); } @@ -1328,7 +1347,7 @@ reset_syncing_flag() * information periodically in order to create and sync the slots. */ void -ReplSlotSyncWorkerMain(char *startup_data, size_t startup_data_len) +ReplSlotSyncWorkerMain(const void *startup_data, size_t startup_data_len) { WalReceiverConn *wrconn = NULL; char *dbname; @@ -1517,7 +1536,7 @@ update_synced_slots_inactive_since(void) * correctly interpret the inactive_since if the standby gets promoted * without a restart. We don't want the slots to appear inactive for a * long time after promotion if they haven't been synchronized recently. - * Whoever acquires the slot i.e.makes the slot active will reset it. + * Whoever acquires the slot, i.e., makes the slot active, will reset it. */ if (!StandbyMode) return; @@ -1543,9 +1562,7 @@ update_synced_slots_inactive_since(void) if (now == 0) now = GetCurrentTimestamp(); - SpinLockAcquire(&s->mutex); - s->inactive_since = now; - SpinLockRelease(&s->mutex); + ReplicationSlotSetInactiveSince(s, now, true); } } diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index ae676145e602e..adf18c397db43 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -112,7 +112,7 @@ * is a convenient point to initialize replication from, which is why we * export a snapshot at that point, which *can* be used to read normal data. * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/snapbuild.c @@ -134,6 +134,7 @@ #include "replication/logical.h" #include "replication/reorderbuffer.h" #include "replication/snapbuild.h" +#include "replication/snapbuild_internal.h" #include "storage/fd.h" #include "storage/lmgr.h" #include "storage/proc.h" @@ -143,146 +144,6 @@ #include "utils/memutils.h" #include "utils/snapmgr.h" #include "utils/snapshot.h" - -/* - * This struct contains the current state of the snapshot building - * machinery. Besides a forward declaration in the header, it is not exposed - * to the public, so we can easily change its contents. - */ -struct SnapBuild -{ - /* how far are we along building our first full snapshot */ - SnapBuildState state; - - /* private memory context used to allocate memory for this module. */ - MemoryContext context; - - /* all transactions < than this have committed/aborted */ - TransactionId xmin; - - /* all transactions >= than this are uncommitted */ - TransactionId xmax; - - /* - * Don't replay commits from an LSN < this LSN. This can be set externally - * but it will also be advanced (never retreat) from within snapbuild.c. - */ - XLogRecPtr start_decoding_at; - - /* - * LSN at which two-phase decoding was enabled or LSN at which we found a - * consistent point at the time of slot creation. - * - * The prepared transactions, that were skipped because previously - * two-phase was not enabled or are not covered by initial snapshot, need - * to be sent later along with commit prepared and they must be before - * this point. - */ - XLogRecPtr two_phase_at; - - /* - * Don't start decoding WAL until the "xl_running_xacts" information - * indicates there are no running xids with an xid smaller than this. - */ - TransactionId initial_xmin_horizon; - - /* Indicates if we are building full snapshot or just catalog one. */ - bool building_full_snapshot; - - /* - * Indicates if we are using the snapshot builder for the creation of a - * logical replication slot. If it's true, the start point for decoding - * changes is not determined yet. So we skip snapshot restores to properly - * find the start point. See SnapBuildFindSnapshot() for details. - */ - bool in_slot_creation; - - /* - * Snapshot that's valid to see the catalog state seen at this moment. - */ - Snapshot snapshot; - - /* - * LSN of the last location we are sure a snapshot has been serialized to. - */ - XLogRecPtr last_serialized_snapshot; - - /* - * The reorderbuffer we need to update with usable snapshots et al. - */ - ReorderBuffer *reorder; - - /* - * TransactionId at which the next phase of initial snapshot building will - * happen. InvalidTransactionId if not known (i.e. SNAPBUILD_START), or - * when no next phase necessary (SNAPBUILD_CONSISTENT). - */ - TransactionId next_phase_at; - - /* - * Array of transactions which could have catalog changes that committed - * between xmin and xmax. - */ - struct - { - /* number of committed transactions */ - size_t xcnt; - - /* available space for committed transactions */ - size_t xcnt_space; - - /* - * Until we reach a CONSISTENT state, we record commits of all - * transactions, not just the catalog changing ones. Record when that - * changes so we know we cannot export a snapshot safely anymore. - */ - bool includes_all_transactions; - - /* - * Array of committed transactions that have modified the catalog. - * - * As this array is frequently modified we do *not* keep it in - * xidComparator order. Instead we sort the array when building & - * distributing a snapshot. - * - * TODO: It's unclear whether that reasoning has much merit. Every - * time we add something here after becoming consistent will also - * require distributing a snapshot. Storing them sorted would - * potentially also make it easier to purge (but more complicated wrt - * wraparound?). Should be improved if sorting while building the - * snapshot shows up in profiles. - */ - TransactionId *xip; - } committed; - - /* - * Array of transactions and subtransactions that had modified catalogs - * and were running when the snapshot was serialized. - * - * We normally rely on some WAL record types such as HEAP2_NEW_CID to know - * if the transaction has changed the catalog. But it could happen that - * the logical decoding decodes only the commit record of the transaction - * after restoring the previously serialized snapshot in which case we - * will miss adding the xid to the snapshot and end up looking at the - * catalogs with the wrong snapshot. - * - * Now to avoid the above problem, we serialize the transactions that had - * modified the catalogs and are still running at the time of snapshot - * serialization. We fill this array while restoring the snapshot and then - * refer it while decoding commit to ensure if the xact has modified the - * catalog. We discard this array when all the xids in the list become old - * enough to matter. See SnapBuildPurgeOlderTxn for details. - */ - struct - { - /* number of transactions */ - size_t xcnt; - - /* This array must be sorted in xidComparator order */ - TransactionId *xip; - } catchange; -}; - /* * Starting a transaction -- which we need to do while exporting a snapshot -- * removes knowledge about the previously used resowner, so we save it here. @@ -300,7 +161,7 @@ static void SnapBuildFreeSnapshot(Snapshot snap); static void SnapBuildSnapIncRefcount(Snapshot snap); -static void SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn); +static void SnapBuildDistributeSnapshotAndInval(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid); static inline bool SnapBuildXidHasCatalogChanges(SnapBuild *builder, TransactionId xid, uint32 xinfo); @@ -312,7 +173,7 @@ static void SnapBuildWaitSnapshot(xl_running_xacts *running, TransactionId cutof /* serialization functions */ static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn); static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn); -static void SnapBuildRestoreContents(int fd, char *dest, Size size, const char *path); +static void SnapBuildRestoreContents(int fd, void *dest, Size size, const char *path); /* * Allocate a new snapshot builder. @@ -859,15 +720,15 @@ SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid, } /* - * Add a new Snapshot to all transactions we're decoding that currently are - * in-progress so they can see new catalog contents made by the transaction - * that just committed. This is necessary because those in-progress - * transactions will use the new catalog's contents from here on (at the very - * least everything they do needs to be compatible with newer catalog - * contents). + * Add a new Snapshot and invalidation messages to all transactions we're + * decoding that currently are in-progress so they can see new catalog contents + * made by the transaction that just committed. This is necessary because those + * in-progress transactions will use the new catalog's contents from here on + * (at the very least everything they do needs to be compatible with newer + * catalog contents). */ static void -SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn) +SnapBuildDistributeSnapshotAndInval(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid) { dlist_iter txn_i; ReorderBufferTXN *txn; @@ -875,7 +736,8 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn) /* * Iterate through all toplevel transactions. This can include * subtransactions which we just don't yet know to be that, but that's - * fine, they will just get an unnecessary snapshot queued. + * fine, they will just get an unnecessary snapshot and invalidations + * queued. */ dlist_foreach(txn_i, &builder->reorder->toplevel_by_lsn) { @@ -888,6 +750,15 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn) * transaction which in turn implies we don't yet need a snapshot at * all. We'll add a snapshot when the first change gets queued. * + * Similarly, we don't need to add invalidations to a transaction + * whose base snapshot is not yet set. Once a base snapshot is built, + * it will include the xids of committed transactions that have + * modified the catalog, thus reflecting the new catalog contents. The + * existing catalog cache will have already been invalidated after + * processing the invalidations in the transaction that modified + * catalogs, ensuring that a fresh cache is constructed during + * decoding. + * * NB: This works correctly even for subtransactions because * ReorderBufferAssignChild() takes care to transfer the base snapshot * to the top-level transaction, and while iterating the changequeue @@ -897,13 +768,13 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn) continue; /* - * We don't need to add snapshot to prepared transactions as they - * should not see the new catalog contents. + * We don't need to add snapshot or invalidations to prepared + * transactions as they should not see the new catalog contents. */ - if (rbtxn_prepared(txn) || rbtxn_skip_prepared(txn)) + if (rbtxn_is_prepared(txn)) continue; - elog(DEBUG2, "adding a new snapshot to %u at %X/%X", + elog(DEBUG2, "adding a new snapshot and invalidations to %u at %X/%X", txn->xid, LSN_FORMAT_ARGS(lsn)); /* @@ -913,6 +784,41 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn) SnapBuildSnapIncRefcount(builder->snapshot); ReorderBufferAddSnapshot(builder->reorder, txn->xid, lsn, builder->snapshot); + + /* + * Add invalidation messages to the reorder buffer of in-progress + * transactions except the current committed transaction, for which we + * will execute invalidations at the end. + * + * It is required, otherwise, we will end up using the stale catcache + * contents built by the current transaction even after its decoding, + * which should have been invalidated due to concurrent catalog + * changing transaction. + * + * Distribute only the invalidation messages generated by the current + * committed transaction. Invalidation messages received from other + * transactions would have already been propagated to the relevant + * in-progress transactions. This transaction would have processed + * those invalidations, ensuring that subsequent transactions observe + * a consistent cache state. + */ + if (txn->xid != xid) + { + uint32 ninvalidations; + SharedInvalidationMessage *msgs = NULL; + + ninvalidations = ReorderBufferGetInvalidations(builder->reorder, + xid, &msgs); + + if (ninvalidations > 0) + { + Assert(msgs != NULL); + + ReorderBufferAddDistributedInvalidations(builder->reorder, + txn->xid, lsn, + ninvalidations, msgs); + } + } } } @@ -1184,8 +1090,11 @@ SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid, /* refcount of the snapshot builder for the new snapshot */ SnapBuildSnapIncRefcount(builder->snapshot); - /* add a new catalog snapshot to all currently running transactions */ - SnapBuildDistributeNewCatalogSnapshot(builder, lsn); + /* + * Add a new catalog snapshot and invalidations messages to all + * currently running transactions. + */ + SnapBuildDistributeSnapshotAndInval(builder, lsn, xid); } } @@ -1557,40 +1466,6 @@ SnapBuildWaitSnapshot(xl_running_xacts *running, TransactionId cutoff) } } -/* ----------------------------------- - * Snapshot serialization support - * ----------------------------------- - */ - -/* - * We store current state of struct SnapBuild on disk in the following manner: - * - * struct SnapBuildOnDisk; - * TransactionId * committed.xcnt; (*not xcnt_space*) - * TransactionId * catchange.xcnt; - * - */ -typedef struct SnapBuildOnDisk -{ - /* first part of this struct needs to be version independent */ - - /* data not covered by checksum */ - uint32 magic; - pg_crc32c checksum; - - /* data covered by checksum */ - - /* version, in case we want to support pg_upgrade */ - uint32 version; - /* how large is the on disk data, excluding the constant sized part */ - uint32 length; - - /* version dependent part */ - SnapBuild builder; - - /* variable amount of TransactionIds follows */ -} SnapBuildOnDisk; - #define SnapBuildOnDiskConstantSize \ offsetof(SnapBuildOnDisk, builder) #define SnapBuildOnDiskNotChecksummedSize \ @@ -1654,7 +1529,8 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) * unless the user used pg_resetwal or similar. If a user did so, there's * no hope continuing to decode anyway. */ - sprintf(path, "pg_logical/snapshots/%X-%X.snap", + sprintf(path, "%s/%X-%X.snap", + PG_LOGICAL_SNAPSHOTS_DIR, LSN_FORMAT_ARGS(lsn)); /* @@ -1681,7 +1557,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) * be safely on disk. */ fsync_fname(path, false); - fsync_fname("pg_logical/snapshots", true); + fsync_fname(PG_LOGICAL_SNAPSHOTS_DIR, true); builder->last_serialized_snapshot = lsn; goto out; @@ -1697,7 +1573,8 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) elog(DEBUG1, "serializing snapshot to %s", path); /* to make sure only we will write to this tempfile, include pid */ - sprintf(tmppath, "pg_logical/snapshots/%X-%X.snap.%d.tmp", + sprintf(tmppath, "%s/%X-%X.snap.%d.tmp", + PG_LOGICAL_SNAPSHOTS_DIR, LSN_FORMAT_ARGS(lsn), MyProcPid); /* @@ -1818,7 +1695,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) (errcode_for_file_access(), errmsg("could not close file \"%s\": %m", tmppath))); - fsync_fname("pg_logical/snapshots", true); + fsync_fname(PG_LOGICAL_SNAPSHOTS_DIR, true); /* * We may overwrite the work from some other backend, but that's ok, our @@ -1834,7 +1711,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) /* make sure we persist */ fsync_fname(path, false); - fsync_fname("pg_logical/snapshots", true); + fsync_fname(PG_LOGICAL_SNAPSHOTS_DIR, true); /* * Now there's no way we can lose the dumped state anymore, remember this @@ -1855,33 +1732,36 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn) } /* - * Restore a snapshot into 'builder' if previously one has been stored at the - * location indicated by 'lsn'. Returns true if successful, false otherwise. + * Restore the logical snapshot file contents to 'ondisk'. + * + * 'context' is the memory context where the catalog modifying/committed xid + * will live. + * If 'missing_ok' is true, will not throw an error if the file is not found. */ -static bool -SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) +bool +SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, XLogRecPtr lsn, + MemoryContext context, bool missing_ok) { - SnapBuildOnDisk ondisk; int fd; - char path[MAXPGPATH]; - Size sz; pg_crc32c checksum; + Size sz; + char path[MAXPGPATH]; - /* no point in loading a snapshot if we're already there */ - if (builder->state == SNAPBUILD_CONSISTENT) - return false; - - sprintf(path, "pg_logical/snapshots/%X-%X.snap", + sprintf(path, "%s/%X-%X.snap", + PG_LOGICAL_SNAPSHOTS_DIR, LSN_FORMAT_ARGS(lsn)); fd = OpenTransientFile(path, O_RDONLY | PG_BINARY); - if (fd < 0 && errno == ENOENT) - return false; - else if (fd < 0) + if (fd < 0) + { + if (missing_ok && errno == ENOENT) + return false; + ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", path))); + } /* ---- * Make sure the snapshot had been stored safely to disk, that's normally @@ -1892,49 +1772,48 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) * ---- */ fsync_fname(path, false); - fsync_fname("pg_logical/snapshots", true); - + fsync_fname(PG_LOGICAL_SNAPSHOTS_DIR, true); /* read statically sized portion of snapshot */ - SnapBuildRestoreContents(fd, (char *) &ondisk, SnapBuildOnDiskConstantSize, path); + SnapBuildRestoreContents(fd, ondisk, SnapBuildOnDiskConstantSize, path); - if (ondisk.magic != SNAPBUILD_MAGIC) + if (ondisk->magic != SNAPBUILD_MAGIC) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("snapbuild state file \"%s\" has wrong magic number: %u instead of %u", - path, ondisk.magic, SNAPBUILD_MAGIC))); + path, ondisk->magic, SNAPBUILD_MAGIC))); - if (ondisk.version != SNAPBUILD_VERSION) + if (ondisk->version != SNAPBUILD_VERSION) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("snapbuild state file \"%s\" has unsupported version: %u instead of %u", - path, ondisk.version, SNAPBUILD_VERSION))); + path, ondisk->version, SNAPBUILD_VERSION))); INIT_CRC32C(checksum); COMP_CRC32C(checksum, - ((char *) &ondisk) + SnapBuildOnDiskNotChecksummedSize, + ((char *) ondisk) + SnapBuildOnDiskNotChecksummedSize, SnapBuildOnDiskConstantSize - SnapBuildOnDiskNotChecksummedSize); /* read SnapBuild */ - SnapBuildRestoreContents(fd, (char *) &ondisk.builder, sizeof(SnapBuild), path); - COMP_CRC32C(checksum, &ondisk.builder, sizeof(SnapBuild)); + SnapBuildRestoreContents(fd, &ondisk->builder, sizeof(SnapBuild), path); + COMP_CRC32C(checksum, &ondisk->builder, sizeof(SnapBuild)); /* restore committed xacts information */ - if (ondisk.builder.committed.xcnt > 0) + if (ondisk->builder.committed.xcnt > 0) { - sz = sizeof(TransactionId) * ondisk.builder.committed.xcnt; - ondisk.builder.committed.xip = MemoryContextAllocZero(builder->context, sz); - SnapBuildRestoreContents(fd, (char *) ondisk.builder.committed.xip, sz, path); - COMP_CRC32C(checksum, ondisk.builder.committed.xip, sz); + sz = sizeof(TransactionId) * ondisk->builder.committed.xcnt; + ondisk->builder.committed.xip = MemoryContextAllocZero(context, sz); + SnapBuildRestoreContents(fd, ondisk->builder.committed.xip, sz, path); + COMP_CRC32C(checksum, ondisk->builder.committed.xip, sz); } /* restore catalog modifying xacts information */ - if (ondisk.builder.catchange.xcnt > 0) + if (ondisk->builder.catchange.xcnt > 0) { - sz = sizeof(TransactionId) * ondisk.builder.catchange.xcnt; - ondisk.builder.catchange.xip = MemoryContextAllocZero(builder->context, sz); - SnapBuildRestoreContents(fd, (char *) ondisk.builder.catchange.xip, sz, path); - COMP_CRC32C(checksum, ondisk.builder.catchange.xip, sz); + sz = sizeof(TransactionId) * ondisk->builder.catchange.xcnt; + ondisk->builder.catchange.xip = MemoryContextAllocZero(context, sz); + SnapBuildRestoreContents(fd, ondisk->builder.catchange.xip, sz, path); + COMP_CRC32C(checksum, ondisk->builder.catchange.xip, sz); } if (CloseTransientFile(fd) != 0) @@ -1945,11 +1824,31 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) FIN_CRC32C(checksum); /* verify checksum of what we've read */ - if (!EQ_CRC32C(checksum, ondisk.checksum)) + if (!EQ_CRC32C(checksum, ondisk->checksum)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("checksum mismatch for snapbuild state file \"%s\": is %u, should be %u", - path, checksum, ondisk.checksum))); + path, checksum, ondisk->checksum))); + + return true; +} + +/* + * Restore a snapshot into 'builder' if previously one has been stored at the + * location indicated by 'lsn'. Returns true if successful, false otherwise. + */ +static bool +SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) +{ + SnapBuildOnDisk ondisk; + + /* no point in loading a snapshot if we're already there */ + if (builder->state == SNAPBUILD_CONSISTENT) + return false; + + /* validate and restore the snapshot to 'ondisk' */ + if (!SnapBuildRestoreSnapshot(&ondisk, lsn, builder->context, true)) + return false; /* * ok, we now have a sensible snapshot here, figure out if it has more @@ -2031,7 +1930,7 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) * Read the contents of the serialized snapshot to 'dest'. */ static void -SnapBuildRestoreContents(int fd, char *dest, Size size, const char *path) +SnapBuildRestoreContents(int fd, void *dest, Size size, const char *path) { int readBytes; @@ -2074,7 +1973,7 @@ CheckPointSnapBuild(void) XLogRecPtr redo; DIR *snap_dir; struct dirent *snap_de; - char path[MAXPGPATH + 21]; + char path[MAXPGPATH + sizeof(PG_LOGICAL_SNAPSHOTS_DIR)]; /* * We start off with a minimum of the last redo pointer. No new @@ -2090,8 +1989,8 @@ CheckPointSnapBuild(void) if (redo < cutoff) cutoff = redo; - snap_dir = AllocateDir("pg_logical/snapshots"); - while ((snap_de = ReadDir(snap_dir, "pg_logical/snapshots")) != NULL) + snap_dir = AllocateDir(PG_LOGICAL_SNAPSHOTS_DIR); + while ((snap_de = ReadDir(snap_dir, PG_LOGICAL_SNAPSHOTS_DIR)) != NULL) { uint32 hi; uint32 lo; @@ -2102,7 +2001,7 @@ CheckPointSnapBuild(void) strcmp(snap_de->d_name, "..") == 0) continue; - snprintf(path, sizeof(path), "pg_logical/snapshots/%s", snap_de->d_name); + snprintf(path, sizeof(path), "%s/%s", PG_LOGICAL_SNAPSHOTS_DIR, snap_de->d_name); de_type = get_dirent_type(path, snap_de, false, DEBUG1); if (de_type != PGFILETYPE_ERROR && de_type != PGFILETYPE_REG) @@ -2162,7 +2061,8 @@ SnapBuildSnapshotExists(XLogRecPtr lsn) int ret; struct stat stat_buf; - sprintf(path, "pg_logical/snapshots/%X-%X.snap", + sprintf(path, "%s/%X-%X.snap", + PG_LOGICAL_SNAPSHOTS_DIR, LSN_FORMAT_ARGS(lsn)); ret = stat(path, &stat_buf); diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index e03e761392667..8e1e8762f6258 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -2,7 +2,7 @@ * tablesync.c * PostgreSQL logical replication: initial table data synchronization * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/tablesync.c @@ -139,8 +139,7 @@ static StringInfo copybuf = NULL; /* * Exit routine for synchronization worker. */ -static void -pg_attribute_noreturn() +pg_noreturn static void finish_sync_worker(void) { /* @@ -760,7 +759,7 @@ copy_read_data(void *outbuf, int minread, int maxread) if (avail > maxread) avail = maxread; memcpy(outbuf, ©buf->data[copybuf->cursor], avail); - outbuf = (void *) ((char *) outbuf + avail); + outbuf = (char *) outbuf + avail; copybuf->cursor += avail; maxread -= avail; bytesread += avail; @@ -787,23 +786,27 @@ copy_read_data(void *outbuf, int minread, int maxread) /* * Get information about remote relation in similar fashion the RELATION - * message provides during replication. This function also returns the relation - * qualifications to be used in the COPY command. + * message provides during replication. + * + * This function also returns (a) the relation qualifications to be used in + * the COPY command, and (b) whether the remote relation has published any + * generated column. */ static void -fetch_remote_table_info(char *nspname, char *relname, - LogicalRepRelation *lrel, List **qual) +fetch_remote_table_info(char *nspname, char *relname, LogicalRepRelation *lrel, + List **qual, bool *gencol_published) { WalRcvExecResult *res; StringInfoData cmd; TupleTableSlot *slot; Oid tableRow[] = {OIDOID, CHAROID, CHAROID}; - Oid attrRow[] = {INT2OID, TEXTOID, OIDOID, BOOLOID}; + Oid attrRow[] = {INT2OID, TEXTOID, OIDOID, BOOLOID, BOOLOID}; Oid qualRow[] = {TEXTOID}; bool isnull; int natt; - ListCell *lc; + StringInfo pub_names = NULL; Bitmapset *included_cols = NULL; + int server_version = walrcv_server_version(LogRepWorkerWalRcvConn); lrel->nspname = nspname; lrel->relname = relname; @@ -851,20 +854,15 @@ fetch_remote_table_info(char *nspname, char *relname, * We need to do this before fetching info about column names and types, * so that we can skip columns that should not be replicated. */ - if (walrcv_server_version(LogRepWorkerWalRcvConn) >= 150000) + if (server_version >= 150000) { WalRcvExecResult *pubres; TupleTableSlot *tslot; Oid attrsRow[] = {INT2VECTOROID}; - StringInfoData pub_names; - initStringInfo(&pub_names); - foreach(lc, MySubscription->publications) - { - if (foreach_current_index(lc) > 0) - appendStringInfoString(&pub_names, ", "); - appendStringInfoString(&pub_names, quote_literal_cstr(strVal(lfirst(lc)))); - } + /* Build the pub_names comma-separated string. */ + pub_names = makeStringInfo(); + GetPublicationsStr(MySubscription->publications, pub_names, true); /* * Fetch info about column lists for the relation (from all the @@ -881,7 +879,7 @@ fetch_remote_table_info(char *nspname, char *relname, " WHERE gpt.relid = %u AND c.oid = gpt.relid" " AND p.pubname IN ( %s )", lrel->remoteid, - pub_names.data); + pub_names->data); pubres = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data, lengthof(attrsRow), attrsRow); @@ -936,19 +934,23 @@ fetch_remote_table_info(char *nspname, char *relname, ExecDropSingleTupleTableSlot(tslot); walrcv_clear_result(pubres); - - pfree(pub_names.data); } /* * Now fetch column names and types. */ resetStringInfo(&cmd); + appendStringInfoString(&cmd, + "SELECT a.attnum," + " a.attname," + " a.atttypid," + " a.attnum = ANY(i.indkey)"); + + /* Generated columns can be replicated since version 18. */ + if (server_version >= 180000) + appendStringInfoString(&cmd, ", a.attgenerated != ''"); + appendStringInfo(&cmd, - "SELECT a.attnum," - " a.attname," - " a.atttypid," - " a.attnum = ANY(i.indkey)" " FROM pg_catalog.pg_attribute a" " LEFT JOIN pg_catalog.pg_index i" " ON (i.indexrelid = pg_get_replica_identity_index(%u))" @@ -957,11 +959,11 @@ fetch_remote_table_info(char *nspname, char *relname, " AND a.attrelid = %u" " ORDER BY a.attnum", lrel->remoteid, - (walrcv_server_version(LogRepWorkerWalRcvConn) >= 120000 ? + (server_version >= 120000 && server_version < 180000 ? "AND a.attgenerated = ''" : ""), lrel->remoteid); res = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data, - lengthof(attrRow), attrRow); + server_version >= 180000 ? lengthof(attrRow) : lengthof(attrRow) - 1, attrRow); if (res->status != WALRCV_OK_TUPLES) ereport(ERROR, @@ -1005,6 +1007,13 @@ fetch_remote_table_info(char *nspname, char *relname, if (DatumGetBool(slot_getattr(slot, 4, &isnull))) lrel->attkeys = bms_add_member(lrel->attkeys, natt); + /* Remember if the remote table has published any generated column. */ + if (server_version >= 180000 && !(*gencol_published)) + { + *gencol_published = DatumGetBool(slot_getattr(slot, 5, &isnull)); + Assert(!isnull); + } + /* Should never happen. */ if (++natt >= MaxTupleAttributeNumber) elog(ERROR, "too many columns in remote table \"%s.%s\"", @@ -1037,21 +1046,10 @@ fetch_remote_table_info(char *nspname, char *relname, * 3) one of the subscribed publications is declared as TABLES IN SCHEMA * that includes this relation */ - if (walrcv_server_version(LogRepWorkerWalRcvConn) >= 150000) + if (server_version >= 150000) { - StringInfoData pub_names; - - /* Build the pubname list. */ - initStringInfo(&pub_names); - foreach_node(String, pubstr, MySubscription->publications) - { - char *pubname = strVal(pubstr); - - if (foreach_current_index(pubstr) > 0) - appendStringInfoString(&pub_names, ", "); - - appendStringInfoString(&pub_names, quote_literal_cstr(pubname)); - } + /* Reuse the already-built pub_names. */ + Assert(pub_names != NULL); /* Check for row filters. */ resetStringInfo(&cmd); @@ -1062,7 +1060,7 @@ fetch_remote_table_info(char *nspname, char *relname, " WHERE gpt.relid = %u" " AND p.pubname IN ( %s )", lrel->remoteid, - pub_names.data); + pub_names->data); res = walrcv_exec(LogRepWorkerWalRcvConn, cmd.data, 1, qualRow); @@ -1101,6 +1099,7 @@ fetch_remote_table_info(char *nspname, char *relname, ExecDropSingleTupleTableSlot(slot); walrcv_clear_result(res); + destroyStringInfo(pub_names); } pfree(cmd.data); @@ -1123,10 +1122,12 @@ copy_table(Relation rel) List *attnamelist; ParseState *pstate; List *options = NIL; + bool gencol_published = false; /* Get the publisher relation info. */ fetch_remote_table_info(get_namespace_name(RelationGetNamespace(rel)), - RelationGetRelationName(rel), &lrel, &qual); + RelationGetRelationName(rel), &lrel, &qual, + &gencol_published); /* Put the relation into relmap. */ logicalrep_relmap_update(&lrel); @@ -1138,8 +1139,8 @@ copy_table(Relation rel) /* Start copy on the publisher. */ initStringInfo(&cmd); - /* Regular table with no row filter */ - if (lrel.relkind == RELKIND_RELATION && qual == NIL) + /* Regular table with no row filter or generated columns */ + if (lrel.relkind == RELKIND_RELATION && qual == NIL && !gencol_published) { appendStringInfo(&cmd, "COPY %s", quote_qualified_identifier(lrel.nspname, lrel.relname)); @@ -1170,9 +1171,14 @@ copy_table(Relation rel) { /* * For non-tables and tables with row filters, we need to do COPY - * (SELECT ...), but we can't just do SELECT * because we need to not - * copy generated columns. For tables with any row filters, build a - * SELECT query with OR'ed row filters for COPY. + * (SELECT ...), but we can't just do SELECT * because we may need to + * copy only subset of columns including generated columns. For tables + * with any row filters, build a SELECT query with OR'ed row filters + * for COPY. + * + * We also need to use this same COPY (SELECT ...) syntax when + * generated columns are published, because copy of generated columns + * is not supported by the normal COPY. */ appendStringInfoString(&cmd, "COPY (SELECT "); for (int i = 0; i < lrel.natts; i++) diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index ec96b5fe85e6d..a23262957acb5 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -2,7 +2,7 @@ * worker.c * PostgreSQL logical replication worker (apply) * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/logical/worker.c @@ -167,6 +167,7 @@ #include "postmaster/bgworker.h" #include "postmaster/interrupt.h" #include "postmaster/walwriter.h" +#include "replication/conflict.h" #include "replication/logicallauncher.h" #include "replication/logicalproto.h" #include "replication/logicalrelation.h" @@ -413,6 +414,8 @@ static inline void reset_apply_error_context_info(void); static TransApplyAction get_transaction_apply_action(TransactionId xid, ParallelApplyWorkerInfo **winfo); +static void replorigin_reset(int code, Datum arg); + /* * Form the origin name for the subscription. * @@ -667,7 +670,8 @@ create_edata_for_relation(LogicalRepRelMapEntry *rel) addRTEPermissionInfo(&perminfos, rte); - ExecInitRangeTable(estate, list_make1(rte), perminfos); + ExecInitRangeTable(estate, list_make1(rte), perminfos, + bms_make_singleton(1)); edata->targetRelInfo = resultRelInfo = makeNode(ResultRelInfo); @@ -1133,7 +1137,17 @@ apply_handle_prepare(StringInfo s) CommitTransactionCommand(); pgstat_report_stat(false); - store_flush_position(prepare_data.end_lsn, XactLastCommitEnd); + /* + * It is okay not to set the local_end LSN for the prepare because we + * always flush the prepare record. So, we can send the acknowledgment of + * the remote_end LSN as soon as prepare is finished. + * + * XXX For the sake of consistency with commit, we could have set it with + * the LSN of prepare but as of now we don't track that value similar to + * XactLastCommitEnd, and adding it for this purpose doesn't seems worth + * it. + */ + store_flush_position(prepare_data.end_lsn, InvalidXLogRecPtr); in_remote_transaction = false; @@ -1251,7 +1265,12 @@ apply_handle_rollback_prepared(StringInfo s) pgstat_report_stat(false); - store_flush_position(rollback_data.rollback_end_lsn, XactLastCommitEnd); + /* + * It is okay not to set the local_end LSN for the rollback of prepared + * transaction because we always flush the WAL record for it. See + * apply_handle_prepare. + */ + store_flush_position(rollback_data.rollback_end_lsn, InvalidXLogRecPtr); in_remote_transaction = false; /* Process any tables that are being synchronized in parallel. */ @@ -1306,7 +1325,11 @@ apply_handle_stream_prepare(StringInfo s) CommitTransactionCommand(); - store_flush_position(prepare_data.end_lsn, XactLastCommitEnd); + /* + * It is okay not to set the local_end LSN for the prepare because + * we always flush the prepare record. See apply_handle_prepare. + */ + store_flush_position(prepare_data.end_lsn, InvalidXLogRecPtr); in_remote_transaction = false; @@ -1364,7 +1387,11 @@ apply_handle_stream_prepare(StringInfo s) CommitTransactionCommand(); - MyParallelShared->last_commit_end = XactLastCommitEnd; + /* + * It is okay not to set the local_end LSN for the prepare because + * we always flush the prepare record. See apply_handle_prepare. + */ + MyParallelShared->last_commit_end = InvalidXLogRecPtr; pa_set_xact_state(MyParallelShared, PARALLEL_TRANS_FINISHED); pa_unlock_transaction(MyParallelShared->xid, AccessExclusiveLock); @@ -2429,8 +2456,13 @@ apply_handle_insert(StringInfo s) apply_handle_tuple_routing(edata, remoteslot, NULL, CMD_INSERT); else - apply_handle_insert_internal(edata, edata->targetRelInfo, - remoteslot); + { + ResultRelInfo *relinfo = edata->targetRelInfo; + + ExecOpenIndices(relinfo, false); + apply_handle_insert_internal(edata, relinfo, remoteslot); + ExecCloseIndices(relinfo); + } finish_edata(edata); @@ -2457,15 +2489,18 @@ apply_handle_insert_internal(ApplyExecutionData *edata, { EState *estate = edata->estate; - /* We must open indexes here. */ - ExecOpenIndices(relinfo, false); + /* Caller should have opened indexes already. */ + Assert(relinfo->ri_IndexRelationDescs != NULL || + !relinfo->ri_RelationDesc->rd_rel->relhasindex || + RelationGetIndexList(relinfo->ri_RelationDesc) == NIL); + + /* Caller will not have done this bit. */ + Assert(relinfo->ri_onConflictArbiterIndexes == NIL); + InitConflictIndexes(relinfo); /* Do the insert. */ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_INSERT); ExecSimpleRelationInsert(relinfo, estate, remoteslot); - - /* Cleanup. */ - ExecCloseIndices(relinfo); } /* @@ -2641,7 +2676,8 @@ apply_handle_update_internal(ApplyExecutionData *edata, LogicalRepRelMapEntry *relmapentry = edata->targetRel; Relation localrel = relinfo->ri_RelationDesc; EPQState epqstate; - TupleTableSlot *localslot; + TupleTableSlot *localslot = NULL; + ConflictTupleInfo conflicttuple = {0}; bool found; MemoryContext oldctx; @@ -2652,7 +2688,6 @@ apply_handle_update_internal(ApplyExecutionData *edata, &relmapentry->remoterel, localindexoid, remoteslot, &localslot); - ExecClearTuple(remoteslot); /* * Tuple found. @@ -2661,6 +2696,27 @@ apply_handle_update_internal(ApplyExecutionData *edata, */ if (found) { + /* + * Report the conflict if the tuple was modified by a different + * origin. + */ + if (GetTupleTransactionInfo(localslot, &conflicttuple.xmin, + &conflicttuple.origin, &conflicttuple.ts) && + conflicttuple.origin != replorigin_session_origin) + { + TupleTableSlot *newslot; + + /* Store the new tuple for conflict reporting */ + newslot = table_slot_create(localrel, &estate->es_tupleTable); + slot_store_data(newslot, relmapentry, newtup); + + conflicttuple.slot = localslot; + + ReportApplyConflict(estate, relinfo, LOG, CT_UPDATE_ORIGIN_DIFFERS, + remoteslot, newslot, + list_make1(&conflicttuple)); + } + /* Process and store remote tuple in the slot */ oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); slot_modify_data(remoteslot, localslot, relmapentry, newtup); @@ -2668,6 +2724,8 @@ apply_handle_update_internal(ApplyExecutionData *edata, EvalPlanQualSetSlot(&epqstate, remoteslot); + InitConflictIndexes(relinfo); + /* Do the actual update. */ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_UPDATE); ExecSimpleRelationUpdate(relinfo, estate, &epqstate, localslot, @@ -2675,16 +2733,17 @@ apply_handle_update_internal(ApplyExecutionData *edata, } else { + TupleTableSlot *newslot = localslot; + + /* Store the new tuple for conflict reporting */ + slot_store_data(newslot, relmapentry, newtup); + /* * The tuple to be updated could not be found. Do nothing except for * emitting a log message. - * - * XXX should this be promoted to ereport(LOG) perhaps? */ - elog(DEBUG1, - "logical replication did not find row to be updated " - "in replication target relation \"%s\"", - RelationGetRelationName(localrel)); + ReportApplyConflict(estate, relinfo, LOG, CT_UPDATE_MISSING, + remoteslot, newslot, list_make1(&conflicttuple)); } /* Cleanup. */ @@ -2764,8 +2823,14 @@ apply_handle_delete(StringInfo s) apply_handle_tuple_routing(edata, remoteslot, NULL, CMD_DELETE); else - apply_handle_delete_internal(edata, edata->targetRelInfo, + { + ResultRelInfo *relinfo = edata->targetRelInfo; + + ExecOpenIndices(relinfo, false); + apply_handle_delete_internal(edata, relinfo, remoteslot, rel->localindexoid); + ExecCloseIndices(relinfo); + } finish_edata(edata); @@ -2796,10 +2861,15 @@ apply_handle_delete_internal(ApplyExecutionData *edata, LogicalRepRelation *remoterel = &edata->targetRel->remoterel; EPQState epqstate; TupleTableSlot *localslot; + ConflictTupleInfo conflicttuple = {0}; bool found; EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1, NIL); - ExecOpenIndices(relinfo, false); + + /* Caller should have opened indexes already. */ + Assert(relinfo->ri_IndexRelationDescs != NULL || + !localrel->rd_rel->relhasindex || + RelationGetIndexList(localrel) == NIL); found = FindReplTupleInLocalRel(edata, localrel, remoterel, localindexoid, remoteslot, &localslot); @@ -2807,6 +2877,20 @@ apply_handle_delete_internal(ApplyExecutionData *edata, /* If found delete it. */ if (found) { + /* + * Report the conflict if the tuple was modified by a different + * origin. + */ + if (GetTupleTransactionInfo(localslot, &conflicttuple.xmin, + &conflicttuple.origin, &conflicttuple.ts) && + conflicttuple.origin != replorigin_session_origin) + { + conflicttuple.slot = localslot; + ReportApplyConflict(estate, relinfo, LOG, CT_DELETE_ORIGIN_DIFFERS, + remoteslot, NULL, + list_make1(&conflicttuple)); + } + EvalPlanQualSetSlot(&epqstate, localslot); /* Do the actual delete. */ @@ -2818,17 +2902,12 @@ apply_handle_delete_internal(ApplyExecutionData *edata, /* * The tuple to be deleted could not be found. Do nothing except for * emitting a log message. - * - * XXX should this be promoted to ereport(LOG) perhaps? */ - elog(DEBUG1, - "logical replication did not find row to be deleted " - "in replication target relation \"%s\"", - RelationGetRelationName(localrel)); + ReportApplyConflict(estate, relinfo, LOG, CT_DELETE_MISSING, + remoteslot, NULL, list_make1(&conflicttuple)); } /* Cleanup. */ - ExecCloseIndices(relinfo); EvalPlanQualEnd(&epqstate); } @@ -2866,9 +2945,10 @@ FindReplTupleInLocalRel(ApplyExecutionData *edata, Relation localrel, Relation idxrel = index_open(localidxoid, AccessShareLock); /* Index must be PK, RI, or usable for REPLICA IDENTITY FULL tables */ - Assert(GetRelationIdentityOrPK(idxrel) == localidxoid || - IsIndexUsableForReplicaIdentityFull(BuildIndexInfo(idxrel), - edata->targetRel->attrmap)); + Assert(GetRelationIdentityOrPK(localrel) == localidxoid || + (remoterel->replident == REPLICA_IDENTITY_FULL && + IsIndexUsableForReplicaIdentityFull(idxrel, + edata->targetRel->attrmap))); index_close(idxrel, AccessShareLock); #endif @@ -2991,6 +3071,8 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, ResultRelInfo *partrelinfo_new; Relation partrel_new; bool found; + EPQState epqstate; + ConflictTupleInfo conflicttuple = {0}; /* Get the matching local tuple from the partition. */ found = FindReplTupleInLocalRel(edata, partrel, @@ -2999,19 +3081,44 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, remoteslot_part, &localslot); if (!found) { + TupleTableSlot *newslot = localslot; + + /* Store the new tuple for conflict reporting */ + slot_store_data(newslot, part_entry, newtup); + /* * The tuple to be updated could not be found. Do nothing * except for emitting a log message. - * - * XXX should this be promoted to ereport(LOG) perhaps? */ - elog(DEBUG1, - "logical replication did not find row to be updated " - "in replication target relation's partition \"%s\"", - RelationGetRelationName(partrel)); + ReportApplyConflict(estate, partrelinfo, LOG, + CT_UPDATE_MISSING, remoteslot_part, + newslot, list_make1(&conflicttuple)); + return; } + /* + * Report the conflict if the tuple was modified by a + * different origin. + */ + if (GetTupleTransactionInfo(localslot, &conflicttuple.xmin, + &conflicttuple.origin, + &conflicttuple.ts) && + conflicttuple.origin != replorigin_session_origin) + { + TupleTableSlot *newslot; + + /* Store the new tuple for conflict reporting */ + newslot = table_slot_create(partrel, &estate->es_tupleTable); + slot_store_data(newslot, part_entry, newtup); + + conflicttuple.slot = localslot; + + ReportApplyConflict(estate, partrelinfo, LOG, CT_UPDATE_ORIGIN_DIFFERS, + remoteslot_part, newslot, + list_make1(&conflicttuple)); + } + /* * Apply the update to the local tuple, putting the result in * remoteslot_part. @@ -3021,6 +3128,8 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, newtup); MemoryContextSwitchTo(oldctx); + EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1, NIL); + /* * Does the updated tuple still satisfy the current * partition's constraint? @@ -3036,18 +3145,13 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, * work already done above to find the local tuple in the * partition. */ - EPQState epqstate; - - EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1, NIL); - ExecOpenIndices(partrelinfo, false); + InitConflictIndexes(partrelinfo); EvalPlanQualSetSlot(&epqstate, remoteslot_part); TargetPrivilegesCheck(partrelinfo->ri_RelationDesc, ACL_UPDATE); ExecSimpleRelationUpdate(partrelinfo, estate, &epqstate, localslot, remoteslot_part); - ExecCloseIndices(partrelinfo); - EvalPlanQualEnd(&epqstate); } else { @@ -3091,9 +3195,9 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, RelationGetRelationName(partrel_new)); /* DELETE old tuple found in the old partition. */ - apply_handle_delete_internal(edata, partrelinfo, - localslot, - part_entry->localindexoid); + EvalPlanQualSetSlot(&epqstate, localslot); + TargetPrivilegesCheck(partrelinfo->ri_RelationDesc, ACL_DELETE); + ExecSimpleRelationDelete(partrelinfo, estate, &epqstate, localslot); /* INSERT new tuple into the new partition. */ @@ -3123,6 +3227,8 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, apply_handle_insert_internal(edata, partrelinfo_new, remoteslot_part); } + + EvalPlanQualEnd(&epqstate); } break; @@ -3853,7 +3959,10 @@ apply_worker_exit(void) } /* - * Reread subscription info if needed. Most changes will be exit. + * Reread subscription info if needed. + * + * For significant changes, we react by exiting the current process; a new + * one will be launched afterwards if needed. */ void maybe_reread_subscription(void) @@ -3994,7 +4103,7 @@ subscription_change_cb(Datum arg, int cacheid, uint32 hashvalue) * subxact_info_write * Store information about subxacts for a toplevel transaction. * - * For each subxact we store offset of it's first change in the main file. + * For each subxact we store offset of its first change in the main file. * The file is always over-written as a whole. * * XXX We should only store subxacts that were not aborted yet. @@ -4409,6 +4518,14 @@ start_apply(XLogRecPtr origin_startpos) } PG_CATCH(); { + /* + * Reset the origin state to prevent the advancement of origin + * progress if we fail to apply. Otherwise, this will result in + * transaction loss as that transaction won't be sent again by the + * server. + */ + replorigin_reset(0, (Datum) 0); + if (MySubscription->disableonerr) DisableSubscriptionAndExit(); else @@ -4509,8 +4626,16 @@ run_apply_worker() walrcv_startstreaming(LogRepWorkerWalRcvConn, &options); StartTransactionCommand(); + + /* + * Updating pg_subscription might involve TOAST table access, so + * ensure we have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + UpdateTwoPhaseState(MySubscription->oid, LOGICALREP_TWOPHASE_STATE_ENABLED); MySubscription->twophasestate = LOGICALREP_TWOPHASE_STATE_ENABLED; + PopActiveSnapshot(); CommitTransactionCommand(); } else @@ -4619,6 +4744,17 @@ InitializeLogRepWorker(void) CommitTransactionCommand(); } +/* + * Reset the origin state. + */ +static void +replorigin_reset(int code, Datum arg) +{ + replorigin_session_origin = InvalidRepOriginId; + replorigin_session_origin_lsn = InvalidXLogRecPtr; + replorigin_session_origin_timestamp = 0; +} + /* Common function to setup the leader apply or tablesync worker. */ void SetupApplyOrSyncWorker(int worker_slot) @@ -4647,6 +4783,19 @@ SetupApplyOrSyncWorker(int worker_slot) InitializeLogRepWorker(); + /* + * Register a callback to reset the origin state before aborting any + * pending transaction during shutdown (see ShutdownPostgres()). This will + * avoid origin advancement for an in-complete transaction which could + * otherwise lead to its loss as such a transaction won't be sent by the + * server again. + * + * Note that even a LOG or DEBUG statement placed after setting the origin + * state may process a shutdown signal before committing the current apply + * operation. So, it is important to register such a callback here. + */ + before_shmem_exit(replorigin_reset, (Datum) 0); + /* Connect to the origin and start the replication. */ elog(DEBUG1, "connecting to publisher using connection string \"%s\"", MySubscription->conninfo); @@ -4702,7 +4851,15 @@ DisableSubscriptionAndExit(void) /* Disable the subscription */ StartTransactionCommand(); + + /* + * Updating pg_subscription might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + DisableSubscription(MySubscription->oid); + PopActiveSnapshot(); CommitTransactionCommand(); /* Ensure we remove no-longer-useful entry for worker's start time */ @@ -4806,6 +4963,12 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) started_tx = true; } + /* + * Updating pg_subscription might involve TOAST table access, so ensure we + * have a valid snapshot. + */ + PushActiveSnapshot(GetTransactionSnapshot()); + /* * Protect subskiplsn of pg_subscription from being concurrently updated * while clearing it. @@ -4864,6 +5027,8 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) heap_freetuple(tup); table_close(rel, NoLock); + PopActiveSnapshot(); + if (started_tx) CommitTransactionCommand(); } diff --git a/src/backend/replication/meson.build b/src/backend/replication/meson.build index c4f6c71a49e97..b0601498865b3 100644 --- a/src/backend/replication/meson.build +++ b/src/backend/replication/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'slot.c', diff --git a/src/backend/replication/pgoutput/meson.build b/src/backend/replication/pgoutput/meson.build index c0c7fec267ed8..14e2f03ada018 100644 --- a/src/backend/replication/pgoutput/meson.build +++ b/src/backend/replication/pgoutput/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgoutput_sources = files( 'pgoutput.c', diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index abef4eaf68bef..693a766e6d75f 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -3,7 +3,7 @@ * pgoutput.c * Logical Replication output plugin * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/pgoutput/pgoutput.c @@ -27,6 +27,7 @@ #include "replication/logicalproto.h" #include "replication/origin.h" #include "replication/pgoutput.h" +#include "rewrite/rewriteHandler.h" #include "utils/builtins.h" #include "utils/inval.h" #include "utils/lsyscache.h" @@ -35,7 +36,10 @@ #include "utils/syscache.h" #include "utils/varlena.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pgoutput", + .version = PG_VERSION +); static void pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt, bool is_init); @@ -84,9 +88,6 @@ static bool publications_valid; static List *LoadPublications(List *pubnames); static void publication_invalidation_cb(Datum arg, int cacheid, uint32 hashvalue); -static void send_relation_and_attrs(Relation relation, TransactionId xid, - LogicalDecodingContext *ctx, - Bitmapset *columns); static void send_repl_origin(LogicalDecodingContext *ctx, RepOriginId origin_id, XLogRecPtr origin_lsn, bool send_origin); @@ -129,6 +130,15 @@ typedef struct RelationSyncEntry bool replicate_valid; /* overall validity flag for entry */ bool schema_sent; + + /* + * This will be PUBLISH_GENCOLS_STORED if the relation contains generated + * columns and the 'publish_generated_columns' parameter is set to + * PUBLISH_GENCOLS_STORED. Otherwise, it will be PUBLISH_GENCOLS_NONE, + * indicating that no generated columns should be published, unless + * explicitly specified in the column list. + */ + PublishGencolsType include_gencols_type; List *streamed_txns; /* streamed toplevel transactions with this * schema */ @@ -213,6 +223,9 @@ static void init_rel_sync_cache(MemoryContext cachectx); static void cleanup_rel_sync_cache(TransactionId xid, bool is_commit); static RelationSyncEntry *get_rel_sync_entry(PGOutputData *data, Relation relation); +static void send_relation_and_attrs(Relation relation, TransactionId xid, + LogicalDecodingContext *ctx, + RelationSyncEntry *relentry); static void rel_sync_cache_relation_cb(Datum arg, Oid relid); static void rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue); @@ -404,11 +417,11 @@ parse_output_parameters(List *options, PGOutputData *data) if (!protocol_version_given) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("proto_version option missing")); + errmsg("option \"%s\" missing", "proto_version")); if (!publication_names_given) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("publication_names option missing")); + errmsg("option \"%s\" missing", "publication_names")); } /* @@ -430,6 +443,10 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt, "logical replication cache context", ALLOCSET_DEFAULT_SIZES); + data->pubctx = AllocSetContextCreate(ctx->context, + "logical replication publication list context", + ALLOCSET_SMALL_SIZES); + ctx->output_plugin_private = data; /* This plugin uses binary protocol. */ @@ -517,6 +534,8 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt, CacheRegisterSyscacheCallback(PUBLICATIONOID, publication_invalidation_cb, (Datum) 0); + CacheRegisterRelSyncCallback(rel_sync_cache_relation_cb, + (Datum) 0); publication_callback_registered = true; } @@ -731,11 +750,11 @@ maybe_send_schema(LogicalDecodingContext *ctx, { Relation ancestor = RelationIdGetRelation(relentry->publish_as_relid); - send_relation_and_attrs(ancestor, xid, ctx, relentry->columns); + send_relation_and_attrs(ancestor, xid, ctx, relentry); RelationClose(ancestor); } - send_relation_and_attrs(relation, xid, ctx, relentry->columns); + send_relation_and_attrs(relation, xid, ctx, relentry); if (data->in_streaming) set_schema_sent_in_streamed_txn(relentry, topxid); @@ -749,9 +768,11 @@ maybe_send_schema(LogicalDecodingContext *ctx, static void send_relation_and_attrs(Relation relation, TransactionId xid, LogicalDecodingContext *ctx, - Bitmapset *columns) + RelationSyncEntry *relentry) { TupleDesc desc = RelationGetDescr(relation); + Bitmapset *columns = relentry->columns; + PublishGencolsType include_gencols_type = relentry->include_gencols_type; int i; /* @@ -766,23 +787,21 @@ send_relation_and_attrs(Relation relation, TransactionId xid, { Form_pg_attribute att = TupleDescAttr(desc, i); - if (att->attisdropped || att->attgenerated) + if (!logicalrep_should_publish_column(att, columns, + include_gencols_type)) continue; if (att->atttypid < FirstGenbkiObjectId) continue; - /* Skip this attribute if it's not present in the column list */ - if (columns != NULL && !bms_is_member(att->attnum, columns)) - continue; - OutputPluginPrepareWrite(ctx, false); logicalrep_write_typ(ctx->out, xid, att->atttypid); OutputPluginWrite(ctx, false); } OutputPluginPrepareWrite(ctx, false); - logicalrep_write_rel(ctx->out, xid, relation, columns); + logicalrep_write_rel(ctx->out, xid, relation, columns, + include_gencols_type); OutputPluginWrite(ctx, false); } @@ -807,7 +826,8 @@ create_estate_for_relation(Relation rel) addRTEPermissionInfo(&perminfos, rte); - ExecInitRangeTable(estate, list_make1(rte), perminfos); + ExecInitRangeTable(estate, list_make1(rte), perminfos, + bms_make_singleton(1)); estate->es_output_cid = GetCurrentCommandId(false); @@ -996,7 +1016,7 @@ pgoutput_row_filter_init(PGOutputData *data, List *publications, continue; foreach(lc, rfnodes[idx]) - filters = lappend(filters, stringToNode((char *) lfirst(lc))); + filters = lappend(filters, expand_generated_columns_in_expr(stringToNode((char *) lfirst(lc)), relation, 1)); /* combine the row filter and cache the ExprState */ rfnode = make_orclause(filters); @@ -1008,6 +1028,66 @@ pgoutput_row_filter_init(PGOutputData *data, List *publications, } } +/* + * If the table contains a generated column, check for any conflicting + * values of 'publish_generated_columns' parameter in the publications. + */ +static void +check_and_init_gencol(PGOutputData *data, List *publications, + RelationSyncEntry *entry) +{ + Relation relation = RelationIdGetRelation(entry->publish_as_relid); + TupleDesc desc = RelationGetDescr(relation); + bool gencolpresent = false; + bool first = true; + + /* Check if there is any generated column present. */ + for (int i = 0; i < desc->natts; i++) + { + Form_pg_attribute att = TupleDescAttr(desc, i); + + if (att->attgenerated) + { + gencolpresent = true; + break; + } + } + + /* There are no generated columns to be published. */ + if (!gencolpresent) + { + entry->include_gencols_type = PUBLISH_GENCOLS_NONE; + return; + } + + /* + * There may be a conflicting value for 'publish_generated_columns' + * parameter in the publications. + */ + foreach_ptr(Publication, pub, publications) + { + /* + * The column list takes precedence over the + * 'publish_generated_columns' parameter. Those will be checked later, + * see pgoutput_column_list_init. + */ + if (check_and_fetch_column_list(pub, entry->publish_as_relid, NULL, NULL)) + continue; + + if (first) + { + entry->include_gencols_type = pub->pubgencols_type; + first = false; + } + else if (entry->include_gencols_type != pub->pubgencols_type) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot use different values of publish_generated_columns for table \"%s.%s\" in different publications", + get_namespace_name(RelationGetNamespace(relation)), + RelationGetRelationName(relation))); + } +} + /* * Initialize the column list. */ @@ -1018,6 +1098,10 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, ListCell *lc; bool first = true; Relation relation = RelationIdGetRelation(entry->publish_as_relid); + bool found_pub_collist = false; + Bitmapset *relcols = NULL; + + pgoutput_ensure_entry_cxt(data, entry); /* * Find if there are any column lists for this relation. If there are, @@ -1031,79 +1115,40 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, * fetch_table_list. But one can later change the publication so we still * need to check all the given publication-table mappings and report an * error if any publications have a different column list. - * - * FOR ALL TABLES and FOR TABLES IN SCHEMA imply "don't use column list". */ foreach(lc, publications) { Publication *pub = lfirst(lc); - HeapTuple cftuple = NULL; - Datum cfdatum = 0; Bitmapset *cols = NULL; + /* Retrieve the bitmap of columns for a column list publication. */ + found_pub_collist |= check_and_fetch_column_list(pub, + entry->publish_as_relid, + entry->entry_cxt, &cols); + /* - * If the publication is FOR ALL TABLES then it is treated the same as - * if there are no column lists (even if other publications have a - * list). + * For non-column list publications — e.g. TABLE (without a column + * list), ALL TABLES, or ALL TABLES IN SCHEMA, we consider all columns + * of the table (including generated columns when + * 'publish_generated_columns' parameter is true). */ - if (!pub->alltables) + if (!cols) { - bool pub_no_list = true; - /* - * Check for the presence of a column list in this publication. - * - * Note: If we find no pg_publication_rel row, it's a publication - * defined for a whole schema, so it can't have a column list, - * just like a FOR ALL TABLES publication. + * Cache the table columns for the first publication with no + * specified column list to detect publication with a different + * column list. */ - cftuple = SearchSysCache2(PUBLICATIONRELMAP, - ObjectIdGetDatum(entry->publish_as_relid), - ObjectIdGetDatum(pub->oid)); - - if (HeapTupleIsValid(cftuple)) + if (!relcols && (list_length(publications) > 1)) { - /* Lookup the column list attribute. */ - cfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, cftuple, - Anum_pg_publication_rel_prattrs, - &pub_no_list); - - /* Build the column list bitmap in the per-entry context. */ - if (!pub_no_list) /* when not null */ - { - int i; - int nliveatts = 0; - TupleDesc desc = RelationGetDescr(relation); - - pgoutput_ensure_entry_cxt(data, entry); - - cols = pub_collist_to_bitmapset(cols, cfdatum, - entry->entry_cxt); + MemoryContext oldcxt = MemoryContextSwitchTo(entry->entry_cxt); - /* Get the number of live attributes. */ - for (i = 0; i < desc->natts; i++) - { - Form_pg_attribute att = TupleDescAttr(desc, i); - - if (att->attisdropped || att->attgenerated) - continue; - - nliveatts++; - } - - /* - * If column list includes all the columns of the table, - * set it to NULL. - */ - if (bms_num_members(cols) == nliveatts) - { - bms_free(cols); - cols = NULL; - } - } - - ReleaseSysCache(cftuple); + relcols = pub_form_cols_map(relation, + entry->include_gencols_type); + MemoryContextSwitchTo(oldcxt); } + + cols = relcols; } if (first) @@ -1119,6 +1164,13 @@ pgoutput_column_list_init(PGOutputData *data, List *publications, RelationGetRelationName(relation))); } /* loop all subscribed publications */ + /* + * If no column list publications exist, columns to be published will be + * computed later according to the 'publish_generated_columns' parameter. + */ + if (!found_pub_collist) + entry->columns = NULL; + RelationClose(relation); } @@ -1158,8 +1210,8 @@ init_tuple_slot(PGOutputData *data, Relation relation, TupleDesc indesc = RelationGetDescr(relation); TupleDesc outdesc = RelationGetDescr(ancestor); - /* Map must live as long as the session does. */ - oldctx = MemoryContextSwitchTo(CacheMemoryContext); + /* Map must live as long as the logical decoding context. */ + oldctx = MemoryContextSwitchTo(data->cachectx); entry->attrmap = build_attrmap_by_name_if_req(indesc, outdesc, false); @@ -1305,7 +1357,7 @@ pgoutput_row_filter(Relation relation, TupleTableSlot *old_slot, */ for (i = 0; i < desc->natts; i++) { - Form_pg_attribute att = TupleDescAttr(desc, i); + CompactAttribute *att = TupleDescCompactAttr(desc, i); /* * if the column in the new tuple or old tuple is null, nothing to do @@ -1531,15 +1583,18 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, { case REORDER_BUFFER_CHANGE_INSERT: logicalrep_write_insert(ctx->out, xid, targetrel, new_slot, - data->binary, relentry->columns); + data->binary, relentry->columns, + relentry->include_gencols_type); break; case REORDER_BUFFER_CHANGE_UPDATE: logicalrep_write_update(ctx->out, xid, targetrel, old_slot, - new_slot, data->binary, relentry->columns); + new_slot, data->binary, relentry->columns, + relentry->include_gencols_type); break; case REORDER_BUFFER_CHANGE_DELETE: logicalrep_write_delete(ctx->out, xid, targetrel, old_slot, - data->binary, relentry->columns); + data->binary, relentry->columns, + relentry->include_gencols_type); break; default: Assert(false); @@ -1696,9 +1751,9 @@ pgoutput_origin_filter(LogicalDecodingContext *ctx, /* * Shutdown the output plugin. * - * Note, we don't need to clean the data->context and data->cachectx as - * they are child contexts of the ctx->context so they will be cleaned up by - * logical decoding machinery. + * Note, we don't need to clean the data->context, data->cachectx, and + * data->pubctx as they are child contexts of the ctx->context so they + * will be cleaned up by logical decoding machinery. */ static void pgoutput_shutdown(LogicalDecodingContext *ctx) @@ -1712,6 +1767,11 @@ pgoutput_shutdown(LogicalDecodingContext *ctx) /* * Load publications from the list of publication names. + * + * Here, we skip the publications that don't exist yet. This will allow us + * to silently continue the replication in the absence of a missing publication. + * This is required because we allow the users to create publications after they + * have specified the required publications at the time of replication start. */ static List * LoadPublications(List *pubnames) @@ -1722,9 +1782,16 @@ LoadPublications(List *pubnames) foreach(lc, pubnames) { char *pubname = (char *) lfirst(lc); - Publication *pub = GetPublicationByName(pubname, false); + Publication *pub = GetPublicationByName(pubname, true); - result = lappend(result, pub); + if (pub) + result = lappend(result, pub); + else + ereport(WARNING, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("skipped loading publication: %s", pubname), + errdetail("The publication does not exist at this point in the WAL."), + errhint("Create the publication if it does not exist.")); } return result; @@ -1739,12 +1806,6 @@ static void publication_invalidation_cb(Datum arg, int cacheid, uint32 hashvalue) { publications_valid = false; - - /* - * Also invalidate per-relation cache so that next time the filtering info - * is checked it will be updated with the new publication settings. - */ - rel_sync_cache_publication_cb(arg, cacheid, hashvalue); } /* @@ -1801,7 +1862,7 @@ pgoutput_stream_stop(struct LogicalDecodingContext *ctx, /* * Notify downstream to discard the streamed transaction (along with all - * it's subtransactions, if it's a toplevel transaction). + * its subtransactions, if it's a toplevel transaction). */ static void pgoutput_stream_abort(struct LogicalDecodingContext *ctx, @@ -1834,7 +1895,7 @@ pgoutput_stream_abort(struct LogicalDecodingContext *ctx, /* * Notify downstream to apply the streamed transaction (along with all - * it's subtransactions). + * its subtransactions). */ static void pgoutput_stream_commit(struct LogicalDecodingContext *ctx, @@ -1915,23 +1976,18 @@ init_rel_sync_cache(MemoryContext cachectx) /* * Flush all cache entries after a pg_namespace change, in case it was a * schema rename affecting a relation being replicated. + * + * XXX: It is not a good idea to invalidate all the relation entries in + * RelationSyncCache on schema rename. We can optimize it to invalidate + * only the required relations by either having a specific invalidation + * message containing impacted relations or by having schema information + * in each RelationSyncCache entry and using hashvalue of pg_namespace.oid + * passed to the callback. */ CacheRegisterSyscacheCallback(NAMESPACEOID, rel_sync_cache_publication_cb, (Datum) 0); - /* - * Flush all cache entries after any publication changes. (We need no - * callback entry for pg_publication, because publication_invalidation_cb - * will take care of it.) - */ - CacheRegisterSyscacheCallback(PUBLICATIONRELMAP, - rel_sync_cache_publication_cb, - (Datum) 0); - CacheRegisterSyscacheCallback(PUBLICATIONNAMESPACEMAP, - rel_sync_cache_publication_cb, - (Datum) 0); - relation_callbacks_registered = true; } @@ -1990,6 +2046,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) { entry->replicate_valid = false; entry->schema_sent = false; + entry->include_gencols_type = PUBLISH_GENCOLS_NONE; entry->streamed_txns = NIL; entry->pubactions.pubinsert = entry->pubactions.pubupdate = entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false; @@ -2024,12 +2081,9 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) /* Reload publications if needed before use. */ if (!publications_valid) { - oldctx = MemoryContextSwitchTo(CacheMemoryContext); - if (data->publications) - { - list_free_deep(data->publications); - data->publications = NIL; - } + MemoryContextReset(data->pubctx); + + oldctx = MemoryContextSwitchTo(data->pubctx); data->publications = LoadPublications(data->publication_names); MemoryContextSwitchTo(oldctx); publications_valid = true; @@ -2042,6 +2096,7 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) * earlier definition. */ entry->schema_sent = false; + entry->include_gencols_type = PUBLISH_GENCOLS_NONE; list_free(entry->streamed_txns); entry->streamed_txns = NIL; bms_free(entry->columns); @@ -2055,10 +2110,34 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) * Tuple slots cleanups. (Will be rebuilt later if needed). */ if (entry->old_slot) + { + TupleDesc desc = entry->old_slot->tts_tupleDescriptor; + + Assert(desc->tdrefcount == -1); + ExecDropSingleTupleTableSlot(entry->old_slot); + + /* + * ExecDropSingleTupleTableSlot() would not free the TupleDesc, so + * do it now to avoid any leaks. + */ + FreeTupleDesc(desc); + } if (entry->new_slot) + { + TupleDesc desc = entry->new_slot->tts_tupleDescriptor; + + Assert(desc->tdrefcount == -1); + ExecDropSingleTupleTableSlot(entry->new_slot); + /* + * ExecDropSingleTupleTableSlot() would not free the TupleDesc, so + * do it now to avoid any leaks. + */ + FreeTupleDesc(desc); + } + entry->old_slot = NULL; entry->new_slot = NULL; @@ -2213,6 +2292,9 @@ get_rel_sync_entry(PGOutputData *data, Relation relation) /* Initialize the row filter */ pgoutput_row_filter_init(data, rel_publications, entry); + /* Check whether to publish generated columns. */ + check_and_init_gencol(data, rel_publications, entry); + /* Initialize the column list */ pgoutput_column_list_init(data, rel_publications, entry); } @@ -2321,8 +2403,7 @@ rel_sync_cache_relation_cb(Datum arg, Oid relid) /* * Publication relation/schema map syscache invalidation callback * - * Called for invalidations on pg_publication, pg_publication_rel, - * pg_publication_namespace, and pg_namespace. + * Called for invalidations on pg_namespace. */ static void rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue) diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y index c46ca39526310..7440aae5a1a7e 100644 --- a/src/backend/replication/repl_gram.y +++ b/src/backend/replication/repl_gram.y @@ -3,7 +3,7 @@ * * repl_gram.y - Parser for the replication commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,14 +22,7 @@ #include "replication/walsender.h" #include "replication/walsender_private.h" - -/* silence -Wmissing-variable-declarations */ -extern int replication_yychar; -extern int replication_yynerrs; - - -/* Result of the parsing is returned here */ -Node *replication_parse_result; +#include "repl_gram.h" /* @@ -42,6 +35,10 @@ Node *replication_parse_result; %} +%parse-param {Node **replication_parse_result_p} +%parse-param {yyscan_t yyscanner} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="replication_yy" @@ -104,7 +101,9 @@ Node *replication_parse_result; firstcmd: command opt_semicolon { - replication_parse_result = $1; + *replication_parse_result_p = $1; + + (void) yynerrs; /* suppress compiler warning */ } ; diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l index e7def800655f3..014ea8d25c6b7 100644 --- a/src/backend/replication/repl_scanner.l +++ b/src/backend/replication/repl_scanner.l @@ -4,7 +4,7 @@ * repl_scanner.l * a lexical scanner for the replication commands * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -38,32 +38,38 @@ fprintf_to_ereport(const char *fmt, const char *msg) ereport(ERROR, (errmsg_internal("%s", msg))); } -/* Handle to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; - -/* Pushed-back token (we only handle one) */ -static int repl_pushed_back_token; +struct replication_yy_extra_type +{ + /* Pushed-back token (we only handle one) */ + int repl_pushed_back_token; -/* Work area for collecting literals */ -static StringInfoData litbuf; + /* Work area for collecting literals */ + StringInfoData litbuf; +}; -static void startlit(void); -static char *litbufdup(void); -static void addlit(char *ytext, int yleng); -static void addlitchar(unsigned char ychar); +static void startlit(yyscan_t yyscanner); +static char *litbufdup(yyscan_t yyscanner); +static void addlit(char *ytext, int yleng, yyscan_t yyscanner); +static void addlitchar(unsigned char ychar, yyscan_t yyscanner); /* LCOV_EXCL_START */ %} +%option reentrant +%option bison-bridge %option 8bit %option never-interactive %option nodefault %option noinput %option nounput %option noyywrap +%option noyyalloc +%option noyyrealloc +%option noyyfree %option warn %option prefix="replication_yy" +%option extra-type="struct replication_yy_extra_type *" /* * Exclusive states: @@ -108,11 +114,11 @@ identifier {ident_start}{ident_cont}* /* This code is inserted at the start of replication_yylex() */ /* If we have a pushed-back token, return that. */ - if (repl_pushed_back_token) + if (yyextra->repl_pushed_back_token) { - int result = repl_pushed_back_token; + int result = yyextra->repl_pushed_back_token; - repl_pushed_back_token = 0; + yyextra->repl_pushed_back_token = 0; return result; } %} @@ -142,7 +148,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } {space}+ { /* do nothing */ } {digit}+ { - replication_yylval.uintval = strtoul(yytext, NULL, 10); + yylval->uintval = strtoul(yytext, NULL, 10); return UCONST; } @@ -150,34 +156,34 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } uint32 hi, lo; if (sscanf(yytext, "%X/%X", &hi, &lo) != 2) - replication_yyerror("invalid streaming start location"); - replication_yylval.recptr = ((uint64) hi) << 32 | lo; + replication_yyerror(NULL, yyscanner, "invalid streaming start location"); + yylval->recptr = ((uint64) hi) << 32 | lo; return RECPTR; } {xqstart} { BEGIN(xq); - startlit(); + startlit(yyscanner); } {quotestop} { yyless(1); BEGIN(INITIAL); - replication_yylval.str = litbufdup(); + yylval->str = litbufdup(yyscanner); return SCONST; } {xqdouble} { - addlitchar('\''); + addlitchar('\'', yyscanner); } {xqinside} { - addlit(yytext, yyleng); + addlit(yytext, yyleng, yyscanner); } {xdstart} { BEGIN(xd); - startlit(); + startlit(yyscanner); } {xdstop} { @@ -185,20 +191,20 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } yyless(1); BEGIN(INITIAL); - replication_yylval.str = litbufdup(); - len = strlen(replication_yylval.str); - truncate_identifier(replication_yylval.str, len, true); + yylval->str = litbufdup(yyscanner); + len = strlen(yylval->str); + truncate_identifier(yylval->str, len, true); return IDENT; } {xdinside} { - addlit(yytext, yyleng); + addlit(yytext, yyleng, yyscanner); } {identifier} { int len = strlen(yytext); - replication_yylval.str = downcase_truncate_identifier(yytext, len, true); + yylval->str = downcase_truncate_identifier(yytext, len, true); return IDENT; } @@ -207,7 +213,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } return yytext[0]; } -<> { replication_yyerror("unterminated quoted string"); } +<> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); } <> { @@ -218,69 +224,67 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } /* LCOV_EXCL_STOP */ +/* see scan.l */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + static void -startlit(void) +startlit(yyscan_t yyscanner) { - initStringInfo(&litbuf); + initStringInfo(&yyextra->litbuf); } static char * -litbufdup(void) +litbufdup(yyscan_t yyscanner) { - return litbuf.data; + return yyextra->litbuf.data; } static void -addlit(char *ytext, int yleng) +addlit(char *ytext, int yleng, yyscan_t yyscanner) { - appendBinaryStringInfo(&litbuf, ytext, yleng); + appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng); } static void -addlitchar(unsigned char ychar) +addlitchar(unsigned char ychar, yyscan_t yyscanner) { - appendStringInfoChar(&litbuf, ychar); + appendStringInfoChar(&yyextra->litbuf, ychar); } +/* + * (The first argument is enforced by Bison to match the first argument of + * yyparse(), but it is not used here.) + */ void -replication_yyerror(const char *message) +replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg_internal("%s", message))); } - void -replication_scanner_init(const char *str) +replication_scanner_init(const char *str, yyscan_t *yyscannerp) { - Size slen = strlen(str); - char *scanbuf; - - /* - * Might be left over after ereport() - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); - - /* - * Make a scan buffer with special termination needed by flex. - */ - scanbuf = (char *) palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); - - /* Make sure we start in proper state */ - BEGIN(INITIAL); - repl_pushed_back_token = 0; + yyscan_t yyscanner; + struct replication_yy_extra_type *yyext = palloc0_object(struct replication_yy_extra_type); + + if (yylex_init(yyscannerp) != 0) + elog(ERROR, "yylex_init() failed: %m"); + + yyscanner = *yyscannerp; + + yyset_extra(yyext, yyscanner); + + yy_scan_string(str, yyscanner); } void -replication_scanner_finish(void) +replication_scanner_finish(yyscan_t yyscanner) { - yy_delete_buffer(scanbufhandle); - scanbufhandle = NULL; + pfree(yyextra); + yylex_destroy(yyscanner); } /* @@ -292,9 +296,10 @@ replication_scanner_finish(void) * IDENT token here, although some other cases are possible. */ bool -replication_scanner_is_replication_command(void) +replication_scanner_is_replication_command(yyscan_t yyscanner) { - int first_token = replication_yylex(); + YYSTYPE dummy; + int first_token = replication_yylex(&dummy, yyscanner); switch (first_token) { @@ -309,10 +314,37 @@ replication_scanner_is_replication_command(void) case K_UPLOAD_MANIFEST: case K_SHOW: /* Yes; push back the first token so we can parse later. */ - repl_pushed_back_token = first_token; + yyextra->repl_pushed_back_token = first_token; return true; default: /* Nope; we don't bother to push back the token. */ return false; } } + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + return palloc(size); +} + +void * +yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, size); + else + return palloc(size); +} + +void +yyfree(void *ptr, yyscan_t yyscanner) +{ + if (ptr) + pfree(ptr); +} diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index c290339af5f05..c64f020742f8f 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -4,7 +4,7 @@ * Replication slot management. * * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -20,11 +20,11 @@ * on standbys (to support cascading setups). The requirement that slots be * usable on standbys precludes storing them in the system catalogs. * - * Each replication slot gets its own directory inside the $PGDATA/pg_replslot - * directory. Inside that directory the state file will contain the slot's - * own data. Additional data can be stored alongside that file if required. - * While the server is running, the state data is also cached in memory for - * efficiency. + * Each replication slot gets its own directory inside the directory + * $PGDATA / PG_REPLSLOT_DIR. Inside that directory the state file will + * contain the slot's own data. Additional data can be stored alongside that + * file if required. While the server is running, the state data is also + * cached in memory for efficiency. * * ReplicationSlotAllocationLock must be taken in exclusive mode to allocate * or free a slot. ReplicationSlotControlLock must be taken in shared mode @@ -56,6 +56,7 @@ #include "storage/procarray.h" #include "utils/builtins.h" #include "utils/guc_hooks.h" +#include "utils/injection_point.h" #include "utils/varlena.h" /* @@ -102,16 +103,24 @@ typedef struct /* * Lookup table for slot invalidation causes. */ -const char *const SlotInvalidationCauses[] = { - [RS_INVAL_NONE] = "none", - [RS_INVAL_WAL_REMOVED] = "wal_removed", - [RS_INVAL_HORIZON] = "rows_removed", - [RS_INVAL_WAL_LEVEL] = "wal_level_insufficient", +typedef struct SlotInvalidationCauseMap +{ + ReplicationSlotInvalidationCause cause; + const char *cause_name; +} SlotInvalidationCauseMap; + +static const SlotInvalidationCauseMap SlotInvalidationCauses[] = { + {RS_INVAL_NONE, "none"}, + {RS_INVAL_WAL_REMOVED, "wal_removed"}, + {RS_INVAL_HORIZON, "rows_removed"}, + {RS_INVAL_WAL_LEVEL, "wal_level_insufficient"}, + {RS_INVAL_IDLE_TIMEOUT, "idle_timeout"}, }; -/* Maximum number of invalidation causes */ -#define RS_INVAL_MAX_CAUSES RS_INVAL_WAL_LEVEL - +/* + * Ensure that the lookup table is up-to-date with the enums defined in + * ReplicationSlotInvalidationCause. + */ StaticAssertDecl(lengthof(SlotInvalidationCauses) == (RS_INVAL_MAX_CAUSES + 1), "array length mismatch"); @@ -141,6 +150,12 @@ ReplicationSlot *MyReplicationSlot = NULL; int max_replication_slots = 10; /* the maximum number of replication * slots */ +/* + * Invalidate replication slots that have remained idle longer than this + * duration; '0' disables it. + */ +int idle_replication_slot_timeout_mins = 0; + /* * This GUC lists streaming replication standby server slot names that * logical WAL sender processes will wait for. @@ -409,6 +424,7 @@ ReplicationSlotCreate(const char *name, bool db_specific, slot->candidate_restart_valid = InvalidXLogRecPtr; slot->candidate_restart_lsn = InvalidXLogRecPtr; slot->last_saved_confirmed_flush = InvalidXLogRecPtr; + slot->last_saved_restart_lsn = InvalidXLogRecPtr; slot->inactive_since = 0; /* @@ -535,9 +551,13 @@ ReplicationSlotName(int index, Name name) * * An error is raised if nowait is true and the slot is currently in use. If * nowait is false, we sleep until the slot is released by the owning process. + * + * An error is raised if error_if_invalid is true and the slot is found to + * be invalid. It should always be set to true, except when we are temporarily + * acquiring the slot and don't intend to change it. */ void -ReplicationSlotAcquire(const char *name, bool nowait) +ReplicationSlotAcquire(const char *name, bool nowait, bool error_if_invalid) { ReplicationSlot *s; int active_pid; @@ -575,14 +595,23 @@ ReplicationSlotAcquire(const char *name, bool nowait) if (!nowait) ConditionVariablePrepareToSleep(&s->active_cv); + /* + * It is important to reset the inactive_since under spinlock here to + * avoid race conditions with slot invalidation. See comments related + * to inactive_since in InvalidatePossiblyObsoleteSlot. + */ SpinLockAcquire(&s->mutex); if (s->active_pid == 0) s->active_pid = MyProcPid; active_pid = s->active_pid; + ReplicationSlotSetInactiveSince(s, 0, false); SpinLockRelease(&s->mutex); } else + { active_pid = MyProcPid; + ReplicationSlotSetInactiveSince(s, 0, true); + } LWLockRelease(ReplicationSlotControlLock); /* @@ -609,12 +638,25 @@ ReplicationSlotAcquire(const char *name, bool nowait) else if (!nowait) ConditionVariableCancelSleep(); /* no sleep needed after all */ - /* Let everybody know we've modified this slot */ - ConditionVariableBroadcast(&s->active_cv); - /* We made this slot active, so it's ours now. */ MyReplicationSlot = s; + /* + * We need to check for invalidation after making the slot ours to avoid + * the possible race condition with the checkpointer that can otherwise + * invalidate the slot immediately after the check. + */ + if (error_if_invalid && s->data.invalidated != RS_INVAL_NONE) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("can no longer access replication slot \"%s\"", + NameStr(s->data.name)), + errdetail("This replication slot has been invalidated due to \"%s\".", + GetSlotInvalidationCauseName(s->data.invalidated))); + + /* Let everybody know we've modified this slot */ + ConditionVariableBroadcast(&s->active_cv); + /* * The call to pgstat_acquire_replslot() protects against stats for a * different slot, from before a restart or such, being present during @@ -623,13 +665,6 @@ ReplicationSlotAcquire(const char *name, bool nowait) if (SlotIsLogical(s)) pgstat_acquire_replslot(s); - /* - * Reset the time since the slot has become inactive as the slot is active - * now. - */ - SpinLockAcquire(&s->mutex); - s->inactive_since = 0; - SpinLockRelease(&s->mutex); if (am_walsender) { @@ -703,16 +738,12 @@ ReplicationSlotRelease(void) */ SpinLockAcquire(&slot->mutex); slot->active_pid = 0; - slot->inactive_since = now; + ReplicationSlotSetInactiveSince(slot, now, false); SpinLockRelease(&slot->mutex); ConditionVariableBroadcast(&slot->active_cv); } else - { - SpinLockAcquire(&slot->mutex); - slot->inactive_since = now; - SpinLockRelease(&slot->mutex); - } + ReplicationSlotSetInactiveSince(slot, now, true); MyReplicationSlot = NULL; @@ -785,7 +816,7 @@ ReplicationSlotDrop(const char *name, bool nowait) { Assert(MyReplicationSlot == NULL); - ReplicationSlotAcquire(name, nowait); + ReplicationSlotAcquire(name, nowait, false); /* * Do not allow users to drop the slots which are currently being synced @@ -795,7 +826,7 @@ ReplicationSlotDrop(const char *name, bool nowait) ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot drop replication slot \"%s\"", name), - errdetail("This slot is being synced from the primary server.")); + errdetail("This replication slot is being synchronized from the primary server.")); ReplicationSlotDropAcquired(); } @@ -812,7 +843,7 @@ ReplicationSlotAlter(const char *name, const bool *failover, Assert(MyReplicationSlot == NULL); Assert(failover || two_phase); - ReplicationSlotAcquire(name, false); + ReplicationSlotAcquire(name, false, true); if (SlotIsPhysical(MyReplicationSlot)) ereport(ERROR, @@ -830,7 +861,7 @@ ReplicationSlotAlter(const char *name, const bool *failover, ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot alter replication slot \"%s\"", name), - errdetail("This slot is being synced from the primary server.")); + errdetail("This replication slot is being synchronized from the primary server.")); /* * Do not allow users to enable failover on the standby as we do not @@ -916,8 +947,8 @@ ReplicationSlotDropPtr(ReplicationSlot *slot) LWLockAcquire(ReplicationSlotAllocationLock, LW_EXCLUSIVE); /* Generate pathnames. */ - sprintf(path, "pg_replslot/%s", NameStr(slot->data.name)); - sprintf(tmppath, "pg_replslot/%s.tmp", NameStr(slot->data.name)); + sprintf(path, "%s/%s", PG_REPLSLOT_DIR, NameStr(slot->data.name)); + sprintf(tmppath, "%s/%s.tmp", PG_REPLSLOT_DIR, NameStr(slot->data.name)); /* * Rename the slot directory on disk, so that we'll no longer recognize @@ -938,7 +969,7 @@ ReplicationSlotDropPtr(ReplicationSlot *slot) */ START_CRIT_SECTION(); fsync_fname(tmppath, true); - fsync_fname("pg_replslot", true); + fsync_fname(PG_REPLSLOT_DIR, true); END_CRIT_SECTION(); } else @@ -1016,7 +1047,7 @@ ReplicationSlotSave(void) Assert(MyReplicationSlot != NULL); - sprintf(path, "pg_replslot/%s", NameStr(MyReplicationSlot->data.name)); + sprintf(path, "%s/%s", PG_REPLSLOT_DIR, NameStr(MyReplicationSlot->data.name)); SaveSlotToPath(MyReplicationSlot, path, ERROR); } @@ -1135,20 +1166,41 @@ ReplicationSlotsComputeRequiredLSN(void) { ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i]; XLogRecPtr restart_lsn; + XLogRecPtr last_saved_restart_lsn; bool invalidated; + ReplicationSlotPersistency persistency; if (!s->in_use) continue; SpinLockAcquire(&s->mutex); + persistency = s->data.persistency; restart_lsn = s->data.restart_lsn; invalidated = s->data.invalidated != RS_INVAL_NONE; + last_saved_restart_lsn = s->last_saved_restart_lsn; SpinLockRelease(&s->mutex); /* invalidated slots need not apply */ if (invalidated) continue; + /* + * For persistent slot use last_saved_restart_lsn to compute the + * oldest LSN for removal of WAL segments. The segments between + * last_saved_restart_lsn and restart_lsn might be needed by a + * persistent slot in the case of database crash. Non-persistent + * slots can't survive the database crash, so we don't care about + * last_saved_restart_lsn for them. + */ + if (persistency == RS_PERSISTENT) + { + if (last_saved_restart_lsn != InvalidXLogRecPtr && + restart_lsn > last_saved_restart_lsn) + { + restart_lsn = last_saved_restart_lsn; + } + } + if (restart_lsn != InvalidXLogRecPtr && (min_required == InvalidXLogRecPtr || restart_lsn < min_required)) @@ -1186,7 +1238,9 @@ ReplicationSlotsComputeLogicalRestartLSN(void) { ReplicationSlot *s; XLogRecPtr restart_lsn; + XLogRecPtr last_saved_restart_lsn; bool invalidated; + ReplicationSlotPersistency persistency; s = &ReplicationSlotCtl->replication_slots[i]; @@ -1200,14 +1254,33 @@ ReplicationSlotsComputeLogicalRestartLSN(void) /* read once, it's ok if it increases while we're checking */ SpinLockAcquire(&s->mutex); + persistency = s->data.persistency; restart_lsn = s->data.restart_lsn; invalidated = s->data.invalidated != RS_INVAL_NONE; + last_saved_restart_lsn = s->last_saved_restart_lsn; SpinLockRelease(&s->mutex); /* invalidated slots need not apply */ if (invalidated) continue; + /* + * For persistent slot use last_saved_restart_lsn to compute the + * oldest LSN for removal of WAL segments. The segments between + * last_saved_restart_lsn and restart_lsn might be needed by a + * persistent slot in the case of database crash. Non-persistent + * slots can't survive the database crash, so we don't care about + * last_saved_restart_lsn for them. + */ + if (persistency == RS_PERSISTENT) + { + if (last_saved_restart_lsn != InvalidXLogRecPtr && + restart_lsn > last_saved_restart_lsn) + { + restart_lsn = last_saved_restart_lsn; + } + } + if (restart_lsn == InvalidXLogRecPtr) continue; @@ -1425,6 +1498,7 @@ ReplicationSlotReserveWal(void) Assert(slot != NULL); Assert(slot->data.restart_lsn == InvalidXLogRecPtr); + Assert(slot->last_saved_restart_lsn == InvalidXLogRecPtr); /* * The replication slot mechanism is used to prevent removal of required @@ -1501,26 +1575,30 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause, NameData slotname, XLogRecPtr restart_lsn, XLogRecPtr oldestLSN, - TransactionId snapshotConflictHorizon) + TransactionId snapshotConflictHorizon, + long slot_idle_seconds) { StringInfoData err_detail; - bool hint = false; + StringInfoData err_hint; initStringInfo(&err_detail); + initStringInfo(&err_hint); switch (cause) { case RS_INVAL_WAL_REMOVED: { - unsigned long long ex = oldestLSN - restart_lsn; + uint64 ex = oldestLSN - restart_lsn; - hint = true; appendStringInfo(&err_detail, - ngettext("The slot's restart_lsn %X/%X exceeds the limit by %llu byte.", - "The slot's restart_lsn %X/%X exceeds the limit by %llu bytes.", + ngettext("The slot's restart_lsn %X/%X exceeds the limit by %" PRIu64 " byte.", + "The slot's restart_lsn %X/%X exceeds the limit by %" PRIu64 " bytes.", ex), LSN_FORMAT_ARGS(restart_lsn), ex); + /* translator: %s is a GUC variable name */ + appendStringInfo(&err_hint, _("You might need to increase \"%s\"."), + "max_slot_wal_keep_size"); break; } case RS_INVAL_HORIZON: @@ -1531,6 +1609,21 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause, case RS_INVAL_WAL_LEVEL: appendStringInfoString(&err_detail, _("Logical decoding on standby requires \"wal_level\" >= \"logical\" on the primary server.")); break; + + case RS_INVAL_IDLE_TIMEOUT: + { + int minutes = slot_idle_seconds / SECS_PER_MINUTE; + int secs = slot_idle_seconds % SECS_PER_MINUTE; + + /* translator: %s is a GUC variable name */ + appendStringInfo(&err_detail, _("The slot's idle time of %dmin %02ds exceeds the configured \"%s\" duration of %dmin."), + minutes, secs, "idle_replication_slot_timeout", + idle_replication_slot_timeout_mins); + /* translator: %s is a GUC variable name */ + appendStringInfo(&err_hint, _("You might need to increase \"%s\"."), + "idle_replication_slot_timeout"); + break; + } case RS_INVAL_NONE: pg_unreachable(); } @@ -1542,9 +1635,114 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause, errmsg("invalidating obsolete replication slot \"%s\"", NameStr(slotname)), errdetail_internal("%s", err_detail.data), - hint ? errhint("You might need to increase \"%s\".", "max_slot_wal_keep_size") : 0); + err_hint.len ? errhint("%s", err_hint.data) : 0); pfree(err_detail.data); + pfree(err_hint.data); +} + +/* + * Can we invalidate an idle replication slot? + * + * Idle timeout invalidation is allowed only when: + * + * 1. Idle timeout is set + * 2. Slot has reserved WAL + * 3. Slot is inactive + * 4. The slot is not being synced from the primary while the server is in + * recovery. This is because synced slots are always considered to be + * inactive because they don't perform logical decoding to produce changes. + */ +static inline bool +CanInvalidateIdleSlot(ReplicationSlot *s) +{ + return (idle_replication_slot_timeout_mins != 0 && + !XLogRecPtrIsInvalid(s->data.restart_lsn) && + s->inactive_since > 0 && + !(RecoveryInProgress() && s->data.synced)); +} + +/* + * DetermineSlotInvalidationCause - Determine the cause for which a slot + * becomes invalid among the given possible causes. + * + * This function sequentially checks all possible invalidation causes and + * returns the first one for which the slot is eligible for invalidation. + */ +static ReplicationSlotInvalidationCause +DetermineSlotInvalidationCause(uint32 possible_causes, ReplicationSlot *s, + XLogRecPtr oldestLSN, Oid dboid, + TransactionId snapshotConflictHorizon, + TransactionId initial_effective_xmin, + TransactionId initial_catalog_effective_xmin, + XLogRecPtr initial_restart_lsn, + TimestampTz *inactive_since, TimestampTz now) +{ + Assert(possible_causes != RS_INVAL_NONE); + + if (possible_causes & RS_INVAL_WAL_REMOVED) + { + if (initial_restart_lsn != InvalidXLogRecPtr && + initial_restart_lsn < oldestLSN) + return RS_INVAL_WAL_REMOVED; + } + + if (possible_causes & RS_INVAL_HORIZON) + { + /* invalid DB oid signals a shared relation */ + if (SlotIsLogical(s) && + (dboid == InvalidOid || dboid == s->data.database)) + { + if (TransactionIdIsValid(initial_effective_xmin) && + TransactionIdPrecedesOrEquals(initial_effective_xmin, + snapshotConflictHorizon)) + return RS_INVAL_HORIZON; + else if (TransactionIdIsValid(initial_catalog_effective_xmin) && + TransactionIdPrecedesOrEquals(initial_catalog_effective_xmin, + snapshotConflictHorizon)) + return RS_INVAL_HORIZON; + } + } + + if (possible_causes & RS_INVAL_WAL_LEVEL) + { + if (SlotIsLogical(s)) + return RS_INVAL_WAL_LEVEL; + } + + if (possible_causes & RS_INVAL_IDLE_TIMEOUT) + { + Assert(now > 0); + + if (CanInvalidateIdleSlot(s)) + { + /* + * We simulate the invalidation due to idle_timeout as the minimum + * time idle time is one minute which makes tests take a long + * time. + */ +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("slot-timeout-inval")) + { + *inactive_since = 0; /* since the beginning of time */ + return RS_INVAL_IDLE_TIMEOUT; + } +#endif + + /* + * Check if the slot needs to be invalidated due to + * idle_replication_slot_timeout GUC. + */ + if (TimestampDifferenceExceedsSeconds(s->inactive_since, now, + idle_replication_slot_timeout_mins * SECS_PER_MINUTE)) + { + *inactive_since = s->inactive_since; + return RS_INVAL_IDLE_TIMEOUT; + } + } + } + + return RS_INVAL_NONE; } /* @@ -1561,7 +1759,7 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause, * for syscalls, so caller must restart if we return true. */ static bool -InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, +InvalidatePossiblyObsoleteSlot(uint32 possible_causes, ReplicationSlot *s, XLogRecPtr oldestLSN, Oid dboid, TransactionId snapshotConflictHorizon, @@ -1574,6 +1772,7 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, TransactionId initial_catalog_effective_xmin = InvalidTransactionId; XLogRecPtr initial_restart_lsn = InvalidXLogRecPtr; ReplicationSlotInvalidationCause invalidation_cause_prev PG_USED_FOR_ASSERTS_ONLY = RS_INVAL_NONE; + TimestampTz inactive_since = 0; for (;;) { @@ -1581,6 +1780,8 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, NameData slotname; int active_pid = 0; ReplicationSlotInvalidationCause invalidation_cause = RS_INVAL_NONE; + TimestampTz now = 0; + long slot_idle_secs = 0; Assert(LWLockHeldByMeInMode(ReplicationSlotControlLock, LW_SHARED)); @@ -1591,6 +1792,15 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, break; } + if (possible_causes & RS_INVAL_IDLE_TIMEOUT) + { + /* + * Assign the current time here to avoid system call overhead + * while holding the spinlock in subsequent code. + */ + now = GetCurrentTimestamp(); + } + /* * Check if the slot needs to be invalidated. If it needs to be * invalidated, and is not currently acquired, acquire it and mark it @@ -1600,6 +1810,8 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, */ SpinLockAcquire(&s->mutex); + Assert(s->data.restart_lsn >= s->last_saved_restart_lsn); + restart_lsn = s->data.restart_lsn; /* we do nothing if the slot is already invalid */ @@ -1610,6 +1822,11 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, * those values change since the process holding the slot has been * terminated (if any), so record them here to ensure that we * would report the correct invalidation cause. + * + * Unlike other slot attributes, slot's inactive_since can't be + * changed until the acquired slot is released or the owning + * process is terminated. So, the inactive slot can only be + * invalidated immediately without being terminated. */ if (!terminated) { @@ -1618,35 +1835,15 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, initial_catalog_effective_xmin = s->effective_catalog_xmin; } - switch (cause) - { - case RS_INVAL_WAL_REMOVED: - if (initial_restart_lsn != InvalidXLogRecPtr && - initial_restart_lsn < oldestLSN) - invalidation_cause = cause; - break; - case RS_INVAL_HORIZON: - if (!SlotIsLogical(s)) - break; - /* invalid DB oid signals a shared relation */ - if (dboid != InvalidOid && dboid != s->data.database) - break; - if (TransactionIdIsValid(initial_effective_xmin) && - TransactionIdPrecedesOrEquals(initial_effective_xmin, - snapshotConflictHorizon)) - invalidation_cause = cause; - else if (TransactionIdIsValid(initial_catalog_effective_xmin) && - TransactionIdPrecedesOrEquals(initial_catalog_effective_xmin, - snapshotConflictHorizon)) - invalidation_cause = cause; - break; - case RS_INVAL_WAL_LEVEL: - if (SlotIsLogical(s)) - invalidation_cause = cause; - break; - case RS_INVAL_NONE: - pg_unreachable(); - } + invalidation_cause = DetermineSlotInvalidationCause(possible_causes, + s, oldestLSN, + dboid, + snapshotConflictHorizon, + initial_effective_xmin, + initial_catalog_effective_xmin, + initial_restart_lsn, + &inactive_since, + now); } /* @@ -1684,7 +1881,10 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, * just rely on .invalidated. */ if (invalidation_cause == RS_INVAL_WAL_REMOVED) + { s->data.restart_lsn = InvalidXLogRecPtr; + s->last_saved_restart_lsn = InvalidXLogRecPtr; + } /* Let caller know */ *invalidated = true; @@ -1694,12 +1894,25 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, /* * The logical replication slots shouldn't be invalidated as GUC - * max_slot_wal_keep_size is set to -1 during the binary upgrade. See - * check_old_cluster_for_valid_slots() where we ensure that no - * invalidated before the upgrade. + * max_slot_wal_keep_size is set to -1 and + * idle_replication_slot_timeout is set to 0 during the binary + * upgrade. See check_old_cluster_for_valid_slots() where we ensure + * that no invalidated before the upgrade. */ Assert(!(*invalidated && SlotIsLogical(s) && IsBinaryUpgrade)); + /* + * Calculate the idle time duration of the slot if slot is marked + * invalidated with RS_INVAL_IDLE_TIMEOUT. + */ + if (invalidation_cause == RS_INVAL_IDLE_TIMEOUT) + { + int slot_idle_usecs; + + TimestampDifference(inactive_since, now, &slot_idle_secs, + &slot_idle_usecs); + } + if (active_pid != 0) { /* @@ -1728,7 +1941,8 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, { ReportSlotInvalidation(invalidation_cause, true, active_pid, slotname, restart_lsn, - oldestLSN, snapshotConflictHorizon); + oldestLSN, snapshotConflictHorizon, + slot_idle_secs); if (MyBackendType == B_STARTUP) (void) SendProcSignal(active_pid, @@ -1774,7 +1988,8 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, ReportSlotInvalidation(invalidation_cause, false, active_pid, slotname, restart_lsn, - oldestLSN, snapshotConflictHorizon); + oldestLSN, snapshotConflictHorizon, + slot_idle_secs); /* done with this slot for now */ break; @@ -1791,26 +2006,32 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlotInvalidationCause cause, * * Returns true when any slot have got invalidated. * - * Whether a slot needs to be invalidated depends on the cause. A slot is - * removed if it: + * Whether a slot needs to be invalidated depends on the invalidation cause. + * A slot is invalidated if it: * - RS_INVAL_WAL_REMOVED: requires a LSN older than the given segment * - RS_INVAL_HORIZON: requires a snapshot <= the given horizon in the given * db; dboid may be InvalidOid for shared relations - * - RS_INVAL_WAL_LEVEL: is logical + * - RS_INVAL_WAL_LEVEL: is logical and wal_level is insufficient + * - RS_INVAL_IDLE_TIMEOUT: has been idle longer than the configured + * "idle_replication_slot_timeout" duration. + * + * Note: This function attempts to invalidate the slot for multiple possible + * causes in a single pass, minimizing redundant iterations. The "cause" + * parameter can be a MASK representing one or more of the defined causes. * * NB - this runs as part of checkpoint, so avoid raising errors if possible. */ bool -InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, +InvalidateObsoleteReplicationSlots(uint32 possible_causes, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon) { XLogRecPtr oldestLSN; bool invalidated = false; - Assert(cause != RS_INVAL_HORIZON || TransactionIdIsValid(snapshotConflictHorizon)); - Assert(cause != RS_INVAL_WAL_REMOVED || oldestSegno > 0); - Assert(cause != RS_INVAL_NONE); + Assert(!(possible_causes & RS_INVAL_HORIZON) || TransactionIdIsValid(snapshotConflictHorizon)); + Assert(!(possible_causes & RS_INVAL_WAL_REMOVED) || oldestSegno > 0); + Assert(possible_causes != RS_INVAL_NONE); if (max_replication_slots == 0) return invalidated; @@ -1826,7 +2047,7 @@ InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, if (!s->in_use) continue; - if (InvalidatePossiblyObsoleteSlot(cause, s, oldestLSN, dboid, + if (InvalidatePossiblyObsoleteSlot(possible_causes, s, oldestLSN, dboid, snapshotConflictHorizon, &invalidated)) { @@ -1881,7 +2102,7 @@ CheckPointReplicationSlots(bool is_shutdown) continue; /* save the slot to disk, locking is handled in SaveSlotToPath() */ - sprintf(path, "pg_replslot/%s", NameStr(s->data.name)); + sprintf(path, "%s/%s", PG_REPLSLOT_DIR, NameStr(s->data.name)); /* * Slot's data is not flushed each time the confirmed_flush LSN is @@ -1907,6 +2128,12 @@ CheckPointReplicationSlots(bool is_shutdown) SaveSlotToPath(s, path, LOG); } LWLockRelease(ReplicationSlotAllocationLock); + + /* + * Recompute the required LSN as SaveSlotToPath() updated + * last_saved_restart_lsn for slots. + */ + ReplicationSlotsComputeRequiredLSN(); } /* @@ -1922,17 +2149,17 @@ StartupReplicationSlots(void) elog(DEBUG1, "starting up replication slots"); /* restore all slots by iterating over all on-disk entries */ - replication_dir = AllocateDir("pg_replslot"); - while ((replication_de = ReadDir(replication_dir, "pg_replslot")) != NULL) + replication_dir = AllocateDir(PG_REPLSLOT_DIR); + while ((replication_de = ReadDir(replication_dir, PG_REPLSLOT_DIR)) != NULL) { - char path[MAXPGPATH + 12]; + char path[MAXPGPATH + sizeof(PG_REPLSLOT_DIR)]; PGFileType de_type; if (strcmp(replication_de->d_name, ".") == 0 || strcmp(replication_de->d_name, "..") == 0) continue; - snprintf(path, sizeof(path), "pg_replslot/%s", replication_de->d_name); + snprintf(path, sizeof(path), "%s/%s", PG_REPLSLOT_DIR, replication_de->d_name); de_type = get_dirent_type(path, replication_de, false, DEBUG1); /* we're only creating directories here, skip if it's not our's */ @@ -1949,7 +2176,7 @@ StartupReplicationSlots(void) path))); continue; } - fsync_fname("pg_replslot", true); + fsync_fname(PG_REPLSLOT_DIR, true); continue; } @@ -1987,8 +2214,8 @@ CreateSlotOnDisk(ReplicationSlot *slot) * takes out the lock, if we'd take the lock here, we'd deadlock. */ - sprintf(path, "pg_replslot/%s", NameStr(slot->data.name)); - sprintf(tmppath, "pg_replslot/%s.tmp", NameStr(slot->data.name)); + sprintf(path, "%s/%s", PG_REPLSLOT_DIR, NameStr(slot->data.name)); + sprintf(tmppath, "%s/%s.tmp", PG_REPLSLOT_DIR, NameStr(slot->data.name)); /* * It's just barely possible that some previous effort to create or drop a @@ -2027,7 +2254,7 @@ CreateSlotOnDisk(ReplicationSlot *slot) START_CRIT_SECTION(); fsync_fname(path, true); - fsync_fname("pg_replslot", true); + fsync_fname(PG_REPLSLOT_DIR, true); END_CRIT_SECTION(); } @@ -2170,7 +2397,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) fsync_fname(path, false); fsync_fname(dir, true); - fsync_fname("pg_replslot", true); + fsync_fname(PG_REPLSLOT_DIR, true); END_CRIT_SECTION(); @@ -2182,6 +2409,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel) if (!slot->just_dirtied) slot->dirty = false; slot->last_saved_confirmed_flush = cp.slotdata.confirmed_flush; + slot->last_saved_restart_lsn = cp.slotdata.restart_lsn; SpinLockRelease(&slot->mutex); LWLockRelease(&slot->io_in_progress_lock); @@ -2195,17 +2423,18 @@ RestoreSlotFromDisk(const char *name) { ReplicationSlotOnDisk cp; int i; - char slotdir[MAXPGPATH + 12]; - char path[MAXPGPATH + 22]; + char slotdir[MAXPGPATH + sizeof(PG_REPLSLOT_DIR)]; + char path[MAXPGPATH + sizeof(PG_REPLSLOT_DIR) + 10]; int fd; bool restored = false; int readBytes; pg_crc32c checksum; + TimestampTz now = 0; /* no need to lock here, no concurrent access allowed yet */ /* delete temp file if it exists */ - sprintf(slotdir, "pg_replslot/%s", name); + sprintf(slotdir, "%s/%s", PG_REPLSLOT_DIR, name); sprintf(path, "%s/state.tmp", slotdir); if (unlink(path) < 0 && errno != ENOENT) ereport(PANIC, @@ -2332,7 +2561,7 @@ RestoreSlotFromDisk(const char *name) (errmsg("could not remove directory \"%s\"", slotdir))); } - fsync_fname("pg_replslot", true); + fsync_fname(PG_REPLSLOT_DIR, true); return; } @@ -2348,12 +2577,29 @@ RestoreSlotFromDisk(const char *name) * NB: Changing the requirements here also requires adapting * CheckSlotRequirements() and CheckLogicalDecodingRequirements(). */ - if (cp.slotdata.database != InvalidOid && wal_level < WAL_LEVEL_LOGICAL) - ereport(FATAL, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"", - NameStr(cp.slotdata.name)), - errhint("Change \"wal_level\" to be \"logical\" or higher."))); + if (cp.slotdata.database != InvalidOid) + { + if (wal_level < WAL_LEVEL_LOGICAL) + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("logical replication slot \"%s\" exists, but \"wal_level\" < \"logical\"", + NameStr(cp.slotdata.name)), + errhint("Change \"wal_level\" to be \"logical\" or higher."))); + + /* + * In standby mode, the hot standby must be enabled. This check is + * necessary to ensure logical slots are invalidated when they become + * incompatible due to insufficient wal_level. Otherwise, if the + * primary reduces wal_level < logical while hot standby is disabled, + * logical slots would remain valid even after promotion. + */ + if (StandbyMode && !EnableHotStandby) + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("logical replication slot \"%s\" exists on the standby, but \"hot_standby\" = \"off\"", + NameStr(cp.slotdata.name)), + errhint("Change \"hot_standby\" to be \"on\"."))); + } else if (wal_level < WAL_LEVEL_REPLICA) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), @@ -2379,6 +2625,7 @@ RestoreSlotFromDisk(const char *name) slot->effective_xmin = cp.slotdata.xmin; slot->effective_catalog_xmin = cp.slotdata.catalog_xmin; slot->last_saved_confirmed_flush = cp.slotdata.confirmed_flush; + slot->last_saved_restart_lsn = cp.slotdata.restart_lsn; slot->candidate_catalog_xmin = InvalidTransactionId; slot->candidate_xmin_lsn = InvalidXLogRecPtr; @@ -2391,9 +2638,13 @@ RestoreSlotFromDisk(const char *name) /* * Set the time since the slot has become inactive after loading the * slot from the disk into memory. Whoever acquires the slot i.e. - * makes the slot active will reset it. + * makes the slot active will reset it. Use the same inactive_since + * time for all the slots. */ - slot->inactive_since = GetCurrentTimestamp(); + if (now == 0) + now = GetCurrentTimestamp(); + + ReplicationSlotSetInactiveSince(slot, now, false); restored = true; break; @@ -2410,26 +2661,37 @@ RestoreSlotFromDisk(const char *name) * ReplicationSlotInvalidationCause. */ ReplicationSlotInvalidationCause -GetSlotInvalidationCause(const char *invalidation_reason) +GetSlotInvalidationCause(const char *cause_name) { - ReplicationSlotInvalidationCause cause; - ReplicationSlotInvalidationCause result = RS_INVAL_NONE; - bool found PG_USED_FOR_ASSERTS_ONLY = false; + Assert(cause_name); + + /* Search lookup table for the cause having this name */ + for (int i = 0; i <= RS_INVAL_MAX_CAUSES; i++) + { + if (strcmp(SlotInvalidationCauses[i].cause_name, cause_name) == 0) + return SlotInvalidationCauses[i].cause; + } - Assert(invalidation_reason); + Assert(false); + return RS_INVAL_NONE; /* to keep compiler quiet */ +} - for (cause = RS_INVAL_NONE; cause <= RS_INVAL_MAX_CAUSES; cause++) +/* + * Maps an ReplicationSlotInvalidationCause to the invalidation + * reason for a replication slot. + */ +const char * +GetSlotInvalidationCauseName(ReplicationSlotInvalidationCause cause) +{ + /* Search lookup table for the name of this cause */ + for (int i = 0; i <= RS_INVAL_MAX_CAUSES; i++) { - if (strcmp(SlotInvalidationCauses[cause], invalidation_reason) == 0) - { - found = true; - result = cause; - break; - } + if (SlotInvalidationCauses[i].cause == cause) + return SlotInvalidationCauses[i].cause_name; } - Assert(found); - return result; + Assert(false); + return "none"; /* to keep compiler quiet */ } /* @@ -2449,18 +2711,15 @@ validate_sync_standby_slots(char *rawname, List **elemlist) { GUC_check_errdetail("List syntax is invalid."); } - else if (!ReplicationSlotCtl) + else if (MyProc) { /* - * We cannot validate the replication slot if the replication slots' - * data has not been initialized. This is ok as we will anyway - * validate the specified slot when waiting for them to catch up. See - * StandbySlotsHaveCaughtup() for details. + * Check that each specified slot exist and is physical. + * + * Because we need an LWLock, we cannot do this on processes without a + * PGPROC, so we skip it there; but see comments in + * StandbySlotsHaveCaughtup() as to why that's not a problem. */ - } - else - { - /* Check that the specified slots exist and are logical slots */ LWLockAcquire(ReplicationSlotControlLock, LW_SHARED); foreach_ptr(char, name, *elemlist) @@ -2471,7 +2730,7 @@ validate_sync_standby_slots(char *rawname, List **elemlist) if (!slot) { - GUC_check_errdetail("replication slot \"%s\" does not exist", + GUC_check_errdetail("Replication slot \"%s\" does not exist.", name); ok = false; break; @@ -2479,7 +2738,7 @@ validate_sync_standby_slots(char *rawname, List **elemlist) if (!SlotIsPhysical(slot)) { - GUC_check_errdetail("\"%s\" is not a physical replication slot", + GUC_check_errdetail("\"%s\" is not a physical replication slot.", name); ok = false; break; @@ -2528,6 +2787,8 @@ check_synchronized_standby_slots(char **newval, void **extra, GucSource source) /* GUC extra value must be guc_malloc'd, not palloc'd */ config = (SyncStandbySlotsConfigData *) guc_malloc(LOG, size); + if (!config) + return false; /* Transform the data into SyncStandbySlotsConfigData */ config->nslotnames = list_length(elemlist); @@ -2539,7 +2800,7 @@ check_synchronized_standby_slots(char **newval, void **extra, GucSource source) ptr += strlen(slot_name) + 1; } - *extra = (void *) config; + *extra = config; pfree(rawname); list_free(elemlist); @@ -2642,46 +2903,39 @@ StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel) slot = SearchNamedReplicationSlot(name, false); + /* + * If a slot name provided in synchronized_standby_slots does not + * exist, report a message and exit the loop. + * + * Though validate_sync_standby_slots (the GUC check_hook) tries to + * avoid this, it can nonetheless happen because the user can specify + * a nonexistent slot name before server startup. That function cannot + * validate such a slot during startup, as ReplicationSlotCtl is not + * initialized by then. Also, the user might have dropped one slot. + */ if (!slot) { - /* - * If a slot name provided in synchronized_standby_slots does not - * exist, report a message and exit the loop. A user can specify a - * slot name that does not exist just before the server startup. - * The GUC check_hook(validate_sync_standby_slots) cannot validate - * such a slot during startup as the ReplicationSlotCtl shared - * memory is not initialized at that time. It is also possible for - * a user to drop the slot in synchronized_standby_slots - * afterwards. - */ ereport(elevel, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("replication slot \"%s\" specified in parameter %s does not exist", + errmsg("replication slot \"%s\" specified in parameter \"%s\" does not exist", name, "synchronized_standby_slots"), - errdetail("Logical replication is waiting on the standby associated with \"%s\".", + errdetail("Logical replication is waiting on the standby associated with replication slot \"%s\".", name), - errhint("Consider creating the slot \"%s\" or amend parameter %s.", + errhint("Create the replication slot \"%s\" or amend parameter \"%s\".", name, "synchronized_standby_slots")); break; } + /* Same as above: if a slot is not physical, exit the loop. */ if (SlotIsLogical(slot)) { - /* - * If a logical slot name is provided in - * synchronized_standby_slots, report a message and exit the loop. - * Similar to the non-existent case, a user can specify a logical - * slot name in synchronized_standby_slots before the server - * startup, or drop an existing physical slot and recreate a - * logical slot with the same name. - */ ereport(elevel, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("cannot have logical replication slot \"%s\" in parameter %s", + errmsg("cannot specify logical replication slot \"%s\" in parameter \"%s\"", name, "synchronized_standby_slots"), - errdetail("Logical replication is waiting for correction on \"%s\".", + errdetail("Logical replication is waiting for correction on replication slot \"%s\".", name), - errhint("Consider removing logical slot \"%s\" from parameter %s.", + errhint("Remove the logical replication slot \"%s\" from parameter \"%s\".", name, "synchronized_standby_slots")); break; } @@ -2697,11 +2951,11 @@ StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel) /* Specified physical slot has been invalidated */ ereport(elevel, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("physical slot \"%s\" specified in parameter %s has been invalidated", + errmsg("physical replication slot \"%s\" specified in parameter \"%s\" has been invalidated", name, "synchronized_standby_slots"), - errdetail("Logical replication is waiting on the standby associated with \"%s\".", + errdetail("Logical replication is waiting on the standby associated with replication slot \"%s\".", name), - errhint("Consider dropping and recreating the slot \"%s\" or amend parameter %s.", + errhint("Drop and recreate the replication slot \"%s\", or amend parameter \"%s\".", name, "synchronized_standby_slots")); break; } @@ -2712,11 +2966,11 @@ StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel) if (inactive) ereport(elevel, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("replication slot \"%s\" specified in parameter %s does not have active_pid", + errmsg("replication slot \"%s\" specified in parameter \"%s\" does not have active_pid", name, "synchronized_standby_slots"), - errdetail("Logical replication is waiting on the standby associated with \"%s\".", + errdetail("Logical replication is waiting on the standby associated with replication slot \"%s\".", name), - errhint("Consider starting standby associated with \"%s\" or amend parameter %s.", + errhint("Start the standby associated with the replication slot \"%s\", or amend parameter \"%s\".", name, "synchronized_standby_slots")); /* Continue if the current slot hasn't caught up. */ @@ -2796,3 +3050,22 @@ WaitForStandbyConfirmation(XLogRecPtr wait_for_lsn) ConditionVariableCancelSleep(); } + +/* + * GUC check_hook for idle_replication_slot_timeout + * + * The value of idle_replication_slot_timeout must be set to 0 during + * a binary upgrade. See start_postmaster() in pg_upgrade for more details. + */ +bool +check_idle_replication_slot_timeout(int *newval, void **extra, GucSource source) +{ + if (IsBinaryUpgrade && *newval != 0) + { + GUC_check_errdetail("\"%s\" must be set to 0 during binary upgrade mode.", + "idle_replication_slot_timeout"); + return false; + } + + return true; +} diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c index c7bfbb15e0a18..36cc2ed4e440f 100644 --- a/src/backend/replication/slotfuncs.c +++ b/src/backend/replication/slotfuncs.c @@ -3,7 +3,7 @@ * slotfuncs.c * Support functions for replication slots * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/slotfuncs.c @@ -17,16 +17,12 @@ #include "access/xlogrecovery.h" #include "access/xlogutils.h" #include "funcapi.h" -#include "miscadmin.h" -#include "replication/decode.h" #include "replication/logical.h" #include "replication/slot.h" #include "replication/slotsync.h" #include "utils/builtins.h" #include "utils/guc.h" -#include "utils/inval.h" #include "utils/pg_lsn.h" -#include "utils/resowner.h" /* * Helper function for creating a new physical replication slot with @@ -239,7 +235,7 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS) Datum pg_get_replication_slots(PG_FUNCTION_ARGS) { -#define PG_GET_REPLICATION_SLOTS_COLS 19 +#define PG_GET_REPLICATION_SLOTS_COLS 20 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; XLogRecPtr currlsn; int slotno; @@ -410,6 +406,12 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) values[i++] = BoolGetDatum(slot_contents.data.two_phase); + if (slot_contents.data.two_phase && + !XLogRecPtrIsInvalid(slot_contents.data.two_phase_at)) + values[i++] = LSNGetDatum(slot_contents.data.two_phase_at); + else + nulls[i++] = true; + if (slot_contents.inactive_since > 0) values[i++] = TimestampTzGetDatum(slot_contents.inactive_since); else @@ -435,7 +437,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS) if (cause == RS_INVAL_NONE) nulls[i++] = true; else - values[i++] = CStringGetTextDatum(SlotInvalidationCauses[cause]); + values[i++] = CStringGetTextDatum(GetSlotInvalidationCauseName(cause)); values[i++] = BoolGetDatum(slot_contents.data.failover); @@ -540,7 +542,7 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS) moveto = Min(moveto, GetXLogReplayRecPtr(NULL)); /* Acquire the slot so we "own" it */ - ReplicationSlotAcquire(NameStr(*slotname), true); + ReplicationSlotAcquire(NameStr(*slotname), true, true); /* A slot whose restart_lsn has never been reserved cannot be advanced */ if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn)) @@ -682,6 +684,13 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot copy a replication slot that doesn't reserve WAL"))); + /* Cannot copy an invalidated replication slot */ + if (first_slot_contents.data.invalidated != RS_INVAL_NONE) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot copy invalidated replication slot \"%s\"", + NameStr(*src_name))); + /* Overwrite params from optional arguments */ if (PG_NARGS() >= 3) temporary = PG_GETARG_BOOL(2); @@ -699,13 +708,18 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) * hence pass find_startpoint false. confirmed_flush will be set * below, by copying from the source slot. * - * To avoid potential issues with the slot synchronization where the - * restart_lsn of a replication slot can go backward, we set the - * failover option to false here. This situation occurs when a slot - * on the primary server is dropped and immediately replaced with a - * new slot of the same name, created by copying from another existing - * slot. However, the slot synchronization will only observe the - * restart_lsn of the same slot going backward. + * We don't copy the failover option to prevent potential issues with + * slot synchronization. For instance, if a slot was synchronized to + * the standby, then dropped on the primary, and immediately recreated + * by copying from another existing slot with much earlier restart_lsn + * and confirmed_flush_lsn, the slot synchronization would only + * observe the LSN of the same slot moving backward. As slot + * synchronization does not copy the restart_lsn and + * confirmed_flush_lsn backward (see update_local_synced_slot() for + * details), if a failover happens before the primary's slot catches + * up, logical replication cannot continue using the synchronized slot + * on the promoted standby because the slot retains the restart_lsn + * and confirmed_flush_lsn that are much later than expected. */ create_logical_replication_slot(NameStr(*dst_name), plugin, @@ -778,6 +792,20 @@ copy_replication_slot(FunctionCallInfo fcinfo, bool logical_slot) NameStr(*src_name)), errhint("Retry when the source replication slot's confirmed_flush_lsn is valid."))); + /* + * Copying an invalid slot doesn't make sense. Note that the source + * slot can become invalid after we create the new slot and copy the + * data of source slot. This is possible because the operations in + * InvalidateObsoleteReplicationSlots() are not serialized with this + * function. Even though we can't detect such a case here, the copied + * slot will become invalid in the next checkpoint cycle. + */ + if (second_slot_contents.data.invalidated != RS_INVAL_NONE) + ereport(ERROR, + errmsg("cannot copy replication slot \"%s\"", + NameStr(*src_name)), + errdetail("The source replication slot was invalidated during the copy operation.")); + /* Install copied values again */ SpinLockAcquire(&MyReplicationSlot->mutex); MyReplicationSlot->effective_xmin = copy_effective_xmin; diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c index fa5988c824ea0..cc35984ad0085 100644 --- a/src/backend/replication/syncrep.c +++ b/src/backend/replication/syncrep.c @@ -63,7 +63,7 @@ * the standbys which are considered as synchronous at that moment * will release waiters from the queue. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/syncrep.c @@ -161,16 +161,23 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit) * sync replication standby names defined. * * Since this routine gets called every commit time, it's important to - * exit quickly if sync replication is not requested. So we check - * WalSndCtl->sync_standbys_defined flag without the lock and exit - * immediately if it's false. If it's true, we need to check it again - * later while holding the lock, to check the flag and operate the sync - * rep queue atomically. This is necessary to avoid the race condition - * described in SyncRepUpdateSyncStandbysDefined(). On the other hand, if - * it's false, the lock is not necessary because we don't touch the queue. + * exit quickly if sync replication is not requested. + * + * We check WalSndCtl->sync_standbys_status flag without the lock and exit + * immediately if SYNC_STANDBY_INIT is set (the checkpointer has + * initialized this data) but SYNC_STANDBY_DEFINED is missing (no sync + * replication requested). + * + * If SYNC_STANDBY_DEFINED is set, we need to check the status again later + * while holding the lock, to check the flag and operate the sync rep + * queue atomically. This is necessary to avoid the race condition + * described in SyncRepUpdateSyncStandbysDefined(). On the other hand, if + * SYNC_STANDBY_DEFINED is not set, the lock is not necessary because we + * don't touch the queue. */ if (!SyncRepRequested() || - !((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_defined) + ((((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_status) & + (SYNC_STANDBY_INIT | SYNC_STANDBY_DEFINED)) == SYNC_STANDBY_INIT) return; /* Cap the level for anything other than commit to remote flush only. */ @@ -186,16 +193,52 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit) Assert(MyProc->syncRepState == SYNC_REP_NOT_WAITING); /* - * We don't wait for sync rep if WalSndCtl->sync_standbys_defined is not - * set. See SyncRepUpdateSyncStandbysDefined. + * We don't wait for sync rep if SYNC_STANDBY_DEFINED is not set. See + * SyncRepUpdateSyncStandbysDefined(). * * Also check that the standby hasn't already replied. Unlikely race * condition but we'll be fetching that cache line anyway so it's likely * to be a low cost check. + * + * If the sync standby data has not been initialized yet + * (SYNC_STANDBY_INIT is not set), fall back to a check based on the LSN, + * then do a direct GUC check. */ - if (!WalSndCtl->sync_standbys_defined || - lsn <= WalSndCtl->lsn[mode]) + if (WalSndCtl->sync_standbys_status & SYNC_STANDBY_INIT) + { + if ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_DEFINED) == 0 || + lsn <= WalSndCtl->lsn[mode]) + { + LWLockRelease(SyncRepLock); + return; + } + } + else if (lsn <= WalSndCtl->lsn[mode]) { + /* + * The LSN is older than what we need to wait for. The sync standby + * data has not been initialized yet, but we are OK to not wait + * because we know that there is no point in doing so based on the + * LSN. + */ + LWLockRelease(SyncRepLock); + return; + } + else if (!SyncStandbysDefined()) + { + /* + * If we are here, the sync standby data has not been initialized yet, + * and the LSN is newer than what need to wait for, so we have fallen + * back to the best thing we could do in this case: a check on + * SyncStandbysDefined() to see if the GUC is set or not. + * + * When the GUC has a value, we wait until the checkpointer updates + * the status data because we cannot be sure yet if we should wait or + * not. Here, the GUC has *no* value, we are sure that there is no + * point to wait; this matters for example when initializing a + * cluster, where we should never wait, and no sync standbys is the + * default behavior. + */ LWLockRelease(SyncRepLock); return; } @@ -912,7 +955,7 @@ SyncRepWakeQueue(bool all, int mode) /* * The checkpointer calls this as needed to update the shared - * sync_standbys_defined flag, so that backends don't remain permanently wedged + * sync_standbys_status flag, so that backends don't remain permanently wedged * if synchronous_standby_names is unset. It's safe to check the current value * without the lock, because it's only ever updated by one process. But we * must take the lock to change it. @@ -922,7 +965,8 @@ SyncRepUpdateSyncStandbysDefined(void) { bool sync_standbys_defined = SyncStandbysDefined(); - if (sync_standbys_defined != WalSndCtl->sync_standbys_defined) + if (sync_standbys_defined != + ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_DEFINED) != 0)) { LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); @@ -946,7 +990,30 @@ SyncRepUpdateSyncStandbysDefined(void) * backend that hasn't yet reloaded its config might go to sleep on * the queue (and never wake up). This prevents that. */ - WalSndCtl->sync_standbys_defined = sync_standbys_defined; + WalSndCtl->sync_standbys_status = SYNC_STANDBY_INIT | + (sync_standbys_defined ? SYNC_STANDBY_DEFINED : 0); + + LWLockRelease(SyncRepLock); + } + else if ((WalSndCtl->sync_standbys_status & SYNC_STANDBY_INIT) == 0) + { + LWLockAcquire(SyncRepLock, LW_EXCLUSIVE); + + /* + * Note that there is no need to wake up the queues here. We would + * reach this path only if SyncStandbysDefined() returns false, or it + * would mean that some backends are waiting with the GUC set. See + * SyncRepWaitForLSN(). + */ + Assert(!SyncStandbysDefined()); + + /* + * Even if there is no sync standby defined, let the readers of this + * information know that the sync standby data has been initialized. + * This can just be done once, hence the previous check on + * SYNC_STANDBY_INIT to avoid useless work. + */ + WalSndCtl->sync_standbys_status |= SYNC_STANDBY_INIT; LWLockRelease(SyncRepLock); } @@ -992,17 +1059,18 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source) { if (*newval != NULL && (*newval)[0] != '\0') { + yyscan_t scanner; int parse_rc; SyncRepConfigData *pconf; - /* Reset communication variables to ensure a fresh start */ - syncrep_parse_result = NULL; - syncrep_parse_error_msg = NULL; + /* Result of parsing is returned in one of these two variables */ + SyncRepConfigData *syncrep_parse_result = NULL; + char *syncrep_parse_error_msg = NULL; /* Parse the synchronous_standby_names string */ - syncrep_scanner_init(*newval); - parse_rc = syncrep_yyparse(); - syncrep_scanner_finish(); + syncrep_scanner_init(*newval, &scanner); + parse_rc = syncrep_yyparse(&syncrep_parse_result, &syncrep_parse_error_msg, scanner); + syncrep_scanner_finish(scanner); if (parse_rc != 0 || syncrep_parse_result == NULL) { @@ -1010,7 +1078,8 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source) if (syncrep_parse_error_msg) GUC_check_errdetail("%s", syncrep_parse_error_msg); else - GUC_check_errdetail("\"synchronous_standby_names\" parser failed"); + GUC_check_errdetail("\"%s\" parser failed.", + "synchronous_standby_names"); return false; } @@ -1028,7 +1097,7 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source) return false; memcpy(pconf, syncrep_parse_result, syncrep_parse_result->config_size); - *extra = (void *) pconf; + *extra = pconf; /* * We need not explicitly clean up syncrep_parse_result. It, and any diff --git a/src/backend/replication/syncrep_gram.y b/src/backend/replication/syncrep_gram.y index 5ce4f1bfe73c0..22297bb151a70 100644 --- a/src/backend/replication/syncrep_gram.y +++ b/src/backend/replication/syncrep_gram.y @@ -3,7 +3,7 @@ * * syncrep_gram.y - Parser for synchronous_standby_names * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -17,17 +17,11 @@ #include "nodes/pg_list.h" #include "replication/syncrep.h" -/* Result of parsing is returned in one of these two variables */ -SyncRepConfigData *syncrep_parse_result; -char *syncrep_parse_error_msg; +#include "syncrep_gram.h" static SyncRepConfigData *create_syncrep_config(const char *num_sync, List *members, uint8 syncrep_method); -/* silence -Wmissing-variable-declarations */ -extern int syncrep_yychar; -extern int syncrep_yynerrs; - /* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents @@ -38,6 +32,12 @@ extern int syncrep_yynerrs; %} +%parse-param {SyncRepConfigData **syncrep_parse_result_p} +%parse-param {char **syncrep_parse_error_msg_p} +%parse-param {yyscan_t yyscanner} +%lex-param {char **syncrep_parse_error_msg_p} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="syncrep_yy" @@ -58,7 +58,10 @@ extern int syncrep_yynerrs; %% result: - standby_config { syncrep_parse_result = $1; } + standby_config { + *syncrep_parse_result_p = $1; + (void) yynerrs; /* suppress compiler warning */ + } ; standby_config: diff --git a/src/backend/replication/syncrep_scanner.l b/src/backend/replication/syncrep_scanner.l index 6defb90f13bf0..7dec1f869c745 100644 --- a/src/backend/replication/syncrep_scanner.l +++ b/src/backend/replication/syncrep_scanner.l @@ -4,7 +4,7 @@ * syncrep_scanner.l * a lexical scanner for synchronous_standby_names * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -37,23 +37,36 @@ fprintf_to_ereport(const char *fmt, const char *msg) ereport(ERROR, (errmsg_internal("%s", msg))); } -/* Handles to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; +struct syncrep_yy_extra_type +{ + StringInfoData xdbuf; +}; -static StringInfoData xdbuf; +/* + * Better keep this definition here than put it in replication/syncrep.h and + * save a bit of duplication. Putting it in replication/syncrep.h would leak + * the definition to other parts and possibly affect other scanners. +*/ +#define YY_DECL extern int syncrep_yylex(union YYSTYPE *yylval_param, char **syncrep_parse_error_msg_p, yyscan_t yyscanner) /* LCOV_EXCL_START */ %} +%option reentrant +%option bison-bridge %option 8bit %option never-interactive %option nodefault %option noinput %option nounput %option noyywrap +%option noyyalloc +%option noyyrealloc +%option noyyfree %option warn %option prefix="syncrep_yy" +%option extra-type="struct syncrep_yy_extra_type *" /* * delimited identifiers (double-quoted identifiers) @@ -82,38 +95,38 @@ xdinside [^"]+ [Ff][Ii][Rr][Ss][Tt] { return FIRST; } {xdstart} { - initStringInfo(&xdbuf); + initStringInfo(&yyextra->xdbuf); BEGIN(xd); } {xddouble} { - appendStringInfoChar(&xdbuf, '"'); + appendStringInfoChar(&yyextra->xdbuf, '"'); } {xdinside} { - appendStringInfoString(&xdbuf, yytext); + appendStringInfoString(&yyextra->xdbuf, yytext); } {xdstop} { - syncrep_yylval.str = xdbuf.data; - xdbuf.data = NULL; + yylval->str = yyextra->xdbuf.data; + yyextra->xdbuf.data = NULL; BEGIN(INITIAL); return NAME; } <> { - syncrep_yyerror("unterminated quoted identifier"); + syncrep_yyerror(NULL, syncrep_parse_error_msg_p, yyscanner, "unterminated quoted identifier"); return JUNK; } {identifier} { - syncrep_yylval.str = pstrdup(yytext); + yylval->str = pstrdup(yytext); return NAME; } {digit}+ { - syncrep_yylval.str = pstrdup(yytext); + yylval->str = pstrdup(yytext); return NUM; } "*" { - syncrep_yylval.str = "*"; + yylval->str = "*"; return NAME; } @@ -126,10 +139,26 @@ xdinside [^"]+ /* LCOV_EXCL_STOP */ -/* Needs to be here for access to yytext */ +/* see scan.l */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + +/* + * This yyerror() function does not raise an error (elog or similar), it just + * collects the error message in *syncrep_parse_error_msg_p and leaves it to + * the ultimate caller of the syncrep parser to raise the error. (The + * ultimate caller will do that with special GUC error functions.) + * + * (The first argument is enforced by Bison to match the first argument of + * yyparse(), but it is not used here.) + */ void -syncrep_yyerror(const char *message) +syncrep_yyerror(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner, const char *message) { + struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext + * macro */ + char *syncrep_parse_error_msg = *syncrep_parse_error_msg_p; + /* report only the first error in a parse operation */ if (syncrep_parse_error_msg) return; @@ -142,32 +171,51 @@ syncrep_yyerror(const char *message) } void -syncrep_scanner_init(const char *str) +syncrep_scanner_init(const char *str, yyscan_t *yyscannerp) { - Size slen = strlen(str); - char *scanbuf; - - /* - * Might be left over after ereport() - */ - if (YY_CURRENT_BUFFER) - yy_delete_buffer(YY_CURRENT_BUFFER); - - /* - * Make a scan buffer with special termination needed by flex. - */ - scanbuf = (char *) palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); - - /* Make sure we start in proper state */ - BEGIN(INITIAL); + yyscan_t yyscanner; + struct syncrep_yy_extra_type *yyext = palloc0_object(struct syncrep_yy_extra_type); + + if (yylex_init(yyscannerp) != 0) + elog(ERROR, "yylex_init() failed: %m"); + + yyscanner = *yyscannerp; + + yyset_extra(yyext, yyscanner); + + yy_scan_string(str, yyscanner); +} + +void +syncrep_scanner_finish(yyscan_t yyscanner) +{ + pfree(yyextra); + yylex_destroy(yyscanner); +} + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +yyalloc(yy_size_t size, yyscan_t yyscanner) +{ + return palloc(size); +} + +void * +yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, size); + else + return palloc(size); } void -syncrep_scanner_finish(void) +yyfree(void *ptr, yyscan_t yyscanner) { - yy_delete_buffer(scanbufhandle); - scanbufhandle = NULL; + if (ptr) + pfree(ptr); } diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index a27aee63defca..8c4d0fd9aed2b 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -39,7 +39,7 @@ * specific parts are in the libpqwalreceiver module. It's loaded * dynamically to avoid linking the server with libpq. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -71,6 +71,7 @@ #include "storage/proc.h" #include "storage/procarray.h" #include "storage/procsignal.h" +#include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/guc.h" @@ -145,42 +146,10 @@ static void XLogWalRcvSendHSFeedback(bool immed); static void ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime); static void WalRcvComputeNextWakeup(WalRcvWakeupReason reason, TimestampTz now); -/* - * Process any interrupts the walreceiver process may have received. - * This should be called any time the process's latch has become set. - * - * Currently, only SIGTERM is of interest. We can't just exit(1) within the - * SIGTERM signal handler, because the signal might arrive in the middle of - * some critical operation, like while we're holding a spinlock. Instead, the - * signal handler sets a flag variable as well as setting the process's latch. - * We must check the flag (by calling ProcessWalRcvInterrupts) anytime the - * latch has become set. Operations that could block for a long time, such as - * reading from a remote server, must pay attention to the latch too; see - * libpqrcv_PQgetResult for example. - */ -void -ProcessWalRcvInterrupts(void) -{ - /* - * Although walreceiver interrupt handling doesn't use the same scheme as - * regular backends, call CHECK_FOR_INTERRUPTS() to make sure we receive - * any incoming signals on Win32, and also to make sure we process any - * barrier events. - */ - CHECK_FOR_INTERRUPTS(); - - if (ShutdownRequestPending) - { - ereport(FATAL, - (errcode(ERRCODE_ADMIN_SHUTDOWN), - errmsg("terminating walreceiver process due to administrator command"))); - } -} - /* Main entry point for walreceiver process */ void -WalReceiverMain(char *startup_data, size_t startup_data_len) +WalReceiverMain(const void *startup_data, size_t startup_data_len) { char conninfo[MAXCONNINFO]; char *tmp_conninfo; @@ -249,8 +218,8 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) /* Fetch information required to start streaming */ walrcv->ready_to_display = false; - strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO); - strlcpy(slotname, (char *) walrcv->slotname, NAMEDATALEN); + strlcpy(conninfo, walrcv->conninfo, MAXCONNINFO); + strlcpy(slotname, walrcv->slotname, NAMEDATALEN); is_temp_slot = walrcv->is_temp_slot; startpoint = walrcv->receiveStart; startpointTLI = walrcv->receiveStartTLI; @@ -266,8 +235,8 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) walrcv->lastMsgSendTime = walrcv->lastMsgReceiptTime = walrcv->latestWalEndTime = now; - /* Report the latch to use to awaken this process */ - walrcv->latch = &MyProc->procLatch; + /* Report our proc number so that others can wake us up */ + walrcv->procno = MyProcNumber; SpinLockRelease(&walrcv->mutex); @@ -280,7 +249,7 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) pqsignal(SIGHUP, SignalHandlerForConfigReload); /* set flag to read config * file */ pqsignal(SIGINT, SIG_IGN); - pqsignal(SIGTERM, SignalHandlerForShutdownRequest); /* request shutdown */ + pqsignal(SIGTERM, die); /* request shutdown */ /* SIGQUIT handler was already set up by InitPostmasterChild */ pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); @@ -317,11 +286,11 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) SpinLockAcquire(&walrcv->mutex); memset(walrcv->conninfo, 0, MAXCONNINFO); if (tmp_conninfo) - strlcpy((char *) walrcv->conninfo, tmp_conninfo, MAXCONNINFO); + strlcpy(walrcv->conninfo, tmp_conninfo, MAXCONNINFO); memset(walrcv->sender_host, 0, NI_MAXHOST); if (sender_host) - strlcpy((char *) walrcv->sender_host, sender_host, NI_MAXHOST); + strlcpy(walrcv->sender_host, sender_host, NI_MAXHOST); walrcv->sender_port = sender_port; walrcv->ready_to_display = true; @@ -459,7 +428,7 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) errmsg("cannot continue WAL streaming, recovery has already ended"))); /* Process any requests or signals received recently */ - ProcessWalRcvInterrupts(); + CHECK_FOR_INTERRUPTS(); if (ConfigReloadPending) { @@ -555,7 +524,7 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) if (rc & WL_LATCH_SET) { ResetLatch(MyLatch); - ProcessWalRcvInterrupts(); + CHECK_FOR_INTERRUPTS(); if (walrcv->force_reply) { @@ -583,6 +552,16 @@ WalReceiverMain(char *startup_data, size_t startup_data_len) */ bool requestReply = false; + /* + * Report pending statistics to the cumulative stats + * system. This location is useful for the report as it + * is not within a tight loop in the WAL receiver, to + * avoid bloating pgstats with requests, while also making + * sure that the reports happen each time a status update + * is sent. + */ + pgstat_report_wal(false); + /* * Check if time since last receive from primary has * reached the configured limit. @@ -694,7 +673,7 @@ WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI) { ResetLatch(MyLatch); - ProcessWalRcvInterrupts(); + CHECK_FOR_INTERRUPTS(); SpinLockAcquire(&walrcv->mutex); Assert(walrcv->walRcvState == WALRCV_RESTARTING || @@ -819,8 +798,8 @@ WalRcvDie(int code, Datum arg) Assert(walrcv->pid == MyProcPid); walrcv->walRcvState = WALRCV_STOPPED; walrcv->pid = 0; + walrcv->procno = INVALID_PROC_NUMBER; walrcv->ready_to_display = false; - walrcv->latch = NULL; SpinLockRelease(&walrcv->mutex); ConditionVariableBroadcast(&walrcv->walRcvStoppedCV); @@ -912,6 +891,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli) { int startoff; int byteswritten; + instr_time start; Assert(tli != 0); @@ -942,7 +922,18 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr, TimeLineID tli) /* OK to write the logs */ errno = 0; + /* + * Measure I/O timing to write WAL data, for pg_stat_io. + */ + start = pgstat_prepare_io_time(track_wal_io_timing); + + pgstat_report_wait_start(WAIT_EVENT_WAL_WRITE); byteswritten = pg_pwrite(recvFile, buf, segbytes, (off_t) startoff); + pgstat_report_wait_end(); + + pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, + IOOP_WRITE, start, 1, byteswritten); + if (byteswritten <= 0) { char xlogfname[MAXFNAMELEN]; @@ -1358,15 +1349,15 @@ WalRcvComputeNextWakeup(WalRcvWakeupReason reason, TimestampTz now) void WalRcvForceReply(void) { - Latch *latch; + ProcNumber procno; WalRcv->force_reply = true; - /* fetching the latch pointer might not be atomic, so use spinlock */ + /* fetching the proc number is probably atomic, but don't rely on it */ SpinLockAcquire(&WalRcv->mutex); - latch = WalRcv->latch; + procno = WalRcv->procno; SpinLockRelease(&WalRcv->mutex); - if (latch) - SetLatch(latch); + if (procno != INVALID_PROC_NUMBER) + SetLatch(&GetPGProcByNumber(procno)->procLatch); } /* @@ -1434,10 +1425,10 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) last_receipt_time = WalRcv->lastMsgReceiptTime; latest_end_lsn = WalRcv->latestWalEnd; latest_end_time = WalRcv->latestWalEndTime; - strlcpy(slotname, (char *) WalRcv->slotname, sizeof(slotname)); - strlcpy(sender_host, (char *) WalRcv->sender_host, sizeof(sender_host)); + strlcpy(slotname, WalRcv->slotname, sizeof(slotname)); + strlcpy(sender_host, WalRcv->sender_host, sizeof(sender_host)); sender_port = WalRcv->sender_port; - strlcpy(conninfo, (char *) WalRcv->conninfo, sizeof(conninfo)); + strlcpy(conninfo, WalRcv->conninfo, sizeof(conninfo)); SpinLockRelease(&WalRcv->mutex); /* diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c index 85a19cdfa5c63..8de2886ff0b59 100644 --- a/src/backend/replication/walreceiverfuncs.c +++ b/src/backend/replication/walreceiverfuncs.c @@ -6,7 +6,7 @@ * with the walreceiver process. Functions implementing walreceiver itself * are in walreceiver.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -27,6 +27,7 @@ #include "pgstat.h" #include "replication/walreceiver.h" #include "storage/pmsignal.h" +#include "storage/proc.h" #include "storage/shmem.h" #include "utils/timestamp.h" @@ -66,7 +67,7 @@ WalRcvShmemInit(void) ConditionVariableInit(&WalRcv->walRcvStoppedCV); SpinLockInit(&WalRcv->mutex); pg_atomic_init_u64(&WalRcv->writtenUpto, 0); - WalRcv->latch = NULL; + WalRcv->procno = INVALID_PROC_NUMBER; } } @@ -248,7 +249,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, WalRcvData *walrcv = WalRcv; bool launch = false; pg_time_t now = (pg_time_t) time(NULL); - Latch *latch; + ProcNumber walrcv_proc; /* * We always start at the beginning of the segment. That prevents a broken @@ -266,7 +267,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, walrcv->walRcvState == WALRCV_WAITING); if (conninfo != NULL) - strlcpy((char *) walrcv->conninfo, conninfo, MAXCONNINFO); + strlcpy(walrcv->conninfo, conninfo, MAXCONNINFO); else walrcv->conninfo[0] = '\0'; @@ -278,7 +279,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, */ if (slotname != NULL && slotname[0] != '\0') { - strlcpy((char *) walrcv->slotname, slotname, NAMEDATALEN); + strlcpy(walrcv->slotname, slotname, NAMEDATALEN); walrcv->is_temp_slot = false; } else @@ -309,14 +310,14 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo, walrcv->receiveStart = recptr; walrcv->receiveStartTLI = tli; - latch = walrcv->latch; + walrcv_proc = walrcv->procno; SpinLockRelease(&walrcv->mutex); if (launch) SendPostmasterSignal(PMSIGNAL_START_WALRECEIVER); - else if (latch) - SetLatch(latch); + else if (walrcv_proc != INVALID_PROC_NUMBER) + SetLatch(&GetPGProcByNumber(walrcv_proc)->procLatch); } /* diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index c5f1009f3706e..f2c33250e8b2f 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -37,7 +37,7 @@ * record, wait for it to be replicated to the standby, and then exit. * * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/replication/walsender.c @@ -79,6 +79,7 @@ #include "replication/walsender.h" #include "replication/walsender_private.h" #include "storage/condition_variable.h" +#include "storage/aio_subsys.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/pmsignal.h" @@ -90,10 +91,14 @@ #include "utils/guc.h" #include "utils/memutils.h" #include "utils/pg_lsn.h" +#include "utils/pgstat_internal.h" #include "utils/ps_status.h" #include "utils/timeout.h" #include "utils/timestamp.h" +/* Minimum interval used by walsender for stats flushes, in ms */ +#define WALSENDER_STATS_FLUSH_INTERVAL 1000 + /* * Maximum data payload in a WAL data message. Must be >= XLOG_BLCKSZ. * @@ -237,7 +242,7 @@ typedef void (*WalSndSendDataCallback) (void); static void WalSndLoop(WalSndSendDataCallback send_data); static void InitWalSenderSlot(void); static void WalSndKill(int code, Datum arg); -static void WalSndShutdown(void) pg_attribute_noreturn(); +pg_noreturn static void WalSndShutdown(void); static void XLogSendPhysical(void); static void XLogSendLogical(void); static void WalSndDone(WalSndSendDataCallback send_data); @@ -282,10 +287,8 @@ InitWalSender(void) /* Create a per-walsender data structure in shared memory */ InitWalSenderSlot(); - /* - * We don't currently need any ResourceOwner in a walsender process, but - * if we did, we could call CreateAuxProcessResourceOwner here. - */ + /* need resource owner for e.g. basebackups */ + CreateAuxProcessResourceOwner(); /* * Let postmaster know that we're a WAL sender. Once we've declared us as @@ -329,6 +332,7 @@ WalSndErrorCleanup(void) LWLockReleaseAll(); ConditionVariableCancelSleep(); pgstat_report_wait_end(); + pgaio_error_cleanup(); if (xlogreader != NULL && xlogreader->seg.ws_file >= 0) wal_segment_close(xlogreader); @@ -346,7 +350,7 @@ WalSndErrorCleanup(void) * without a transaction, we've got to clean that up now. */ if (!IsTransactionOrTransactionBlock()) - WalSndResourceCleanup(false); + ReleaseAuxProcessResources(false); if (got_STOPPING || got_SIGUSR2) proc_exit(0); @@ -355,34 +359,6 @@ WalSndErrorCleanup(void) WalSndSetState(WALSNDSTATE_STARTUP); } -/* - * Clean up any ResourceOwner we created. - */ -void -WalSndResourceCleanup(bool isCommit) -{ - ResourceOwner resowner; - - if (CurrentResourceOwner == NULL) - return; - - /* - * Deleting CurrentResourceOwner is not allowed, so we must save a pointer - * in a local variable and clear it first. - */ - resowner = CurrentResourceOwner; - CurrentResourceOwner = NULL; - - /* Now we can release resources and delete it. */ - ResourceOwnerRelease(resowner, - RESOURCE_RELEASE_BEFORE_LOCKS, isCommit, true); - ResourceOwnerRelease(resowner, - RESOURCE_RELEASE_LOCKS, isCommit, true); - ResourceOwnerRelease(resowner, - RESOURCE_RELEASE_AFTER_LOCKS, isCommit, true); - ResourceOwnerDelete(resowner); -} - /* * Handle a client's connection abort in an orderly manner. */ @@ -685,8 +661,10 @@ UploadManifest(void) * parsing the manifest will use the cryptohash stuff, which requires a * resource owner */ - Assert(CurrentResourceOwner == NULL); - CurrentResourceOwner = ResourceOwnerCreate(NULL, "base backup"); + Assert(AuxProcessResourceOwner != NULL); + Assert(CurrentResourceOwner == AuxProcessResourceOwner || + CurrentResourceOwner == NULL); + CurrentResourceOwner = AuxProcessResourceOwner; /* Prepare to read manifest data into a temporary context. */ mcxt = AllocSetContextCreate(CurrentMemoryContext, @@ -723,7 +701,7 @@ UploadManifest(void) uploaded_manifest_mcxt = mcxt; /* clean up the resource owner we created */ - WalSndResourceCleanup(true); + ReleaseAuxProcessResources(true); } /* @@ -844,7 +822,7 @@ StartReplication(StartReplicationCmd *cmd) if (cmd->slotname) { - ReplicationSlotAcquire(cmd->slotname, true); + ReplicationSlotAcquire(cmd->slotname, true, true); if (SlotIsLogical(MyReplicationSlot)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), @@ -1462,7 +1440,7 @@ StartLogicalReplication(StartReplicationCmd *cmd) Assert(!MyReplicationSlot); - ReplicationSlotAcquire(cmd->slotname, true); + ReplicationSlotAcquire(cmd->slotname, true, true); /* * Force a disconnect, so that the decoding code doesn't need to care @@ -1696,13 +1674,13 @@ WalSndUpdateProgress(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId * When skipping empty transactions in synchronous replication, we send a * keepalive message to avoid delaying such transactions. * - * It is okay to check sync_standbys_defined flag without lock here as in - * the worst case we will just send an extra keepalive message when it is + * It is okay to check sync_standbys_status without lock here as in the + * worst case we will just send an extra keepalive message when it is * really not required. */ if (skipped_xact && SyncRepRequested() && - ((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_defined) + (((volatile WalSndCtlData *) WalSndCtl)->sync_standbys_status & SYNC_STANDBY_DEFINED)) { WalSndKeepalive(false, lsn); @@ -1823,6 +1801,7 @@ WalSndWaitForWal(XLogRecPtr loc) int wakeEvents; uint32 wait_event = 0; static XLogRecPtr RecentFlushPtr = InvalidXLogRecPtr; + TimestampTz last_flush = 0; /* * Fast path to avoid acquiring the spinlock in case we already know we @@ -1843,6 +1822,7 @@ WalSndWaitForWal(XLogRecPtr loc) { bool wait_for_standby_at_stop = false; long sleeptime; + TimestampTz now; /* Clear any already-pending wakeups */ ResetLatch(MyLatch); @@ -1953,7 +1933,8 @@ WalSndWaitForWal(XLogRecPtr loc) * new WAL to be generated. (But if we have nothing to send, we don't * want to wake on socket-writable.) */ - sleeptime = WalSndComputeSleeptime(GetCurrentTimestamp()); + now = GetCurrentTimestamp(); + sleeptime = WalSndComputeSleeptime(now); wakeEvents = WL_SOCKET_READABLE; @@ -1962,6 +1943,15 @@ WalSndWaitForWal(XLogRecPtr loc) Assert(wait_event != 0); + /* Report IO statistics, if needed */ + if (TimestampDifferenceExceeds(last_flush, now, + WALSENDER_STATS_FLUSH_INTERVAL)) + { + pgstat_flush_io(false); + (void) pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO); + last_flush = now; + } + WalSndWait(wakeEvents, sleeptime, wait_event); } @@ -1979,11 +1969,14 @@ WalSndWaitForWal(XLogRecPtr loc) bool exec_replication_command(const char *cmd_string) { + yyscan_t scanner; int parse_rc; Node *cmd_node; const char *cmdtag; - MemoryContext cmd_context; - MemoryContext old_context; + MemoryContext old_context = CurrentMemoryContext; + + /* We save and re-use the cmd_context across calls */ + static MemoryContext cmd_context = NULL; /* * If WAL sender has been told that shutdown is getting close, switch its @@ -2012,24 +2005,43 @@ exec_replication_command(const char *cmd_string) /* * Prepare to parse and execute the command. + * + * Because replication command execution can involve beginning or ending + * transactions, we need a working context that will survive that, so we + * make it a child of TopMemoryContext. That in turn creates a hazard of + * long-lived memory leaks if we lose track of the working context. We + * deal with that by creating it only once per walsender, and resetting it + * for each new command. (Normally this reset is a no-op, but if the + * prior exec_replication_command call failed with an error, it won't be.) + * + * This is subtler than it looks. The transactions we manage can extend + * across replication commands, indeed SnapBuildClearExportedSnapshot + * might have just ended one. Because transaction exit will revert to the + * memory context that was current at transaction start, we need to be + * sure that that context is still valid. That motivates re-using the + * same cmd_context rather than making a new one each time. */ - cmd_context = AllocSetContextCreate(CurrentMemoryContext, - "Replication command context", - ALLOCSET_DEFAULT_SIZES); - old_context = MemoryContextSwitchTo(cmd_context); + if (cmd_context == NULL) + cmd_context = AllocSetContextCreate(TopMemoryContext, + "Replication command context", + ALLOCSET_DEFAULT_SIZES); + else + MemoryContextReset(cmd_context); + + MemoryContextSwitchTo(cmd_context); - replication_scanner_init(cmd_string); + replication_scanner_init(cmd_string, &scanner); /* * Is it a WalSender command? */ - if (!replication_scanner_is_replication_command()) + if (!replication_scanner_is_replication_command(scanner)) { /* Nope; clean up and get out. */ - replication_scanner_finish(); + replication_scanner_finish(scanner); MemoryContextSwitchTo(old_context); - MemoryContextDelete(cmd_context); + MemoryContextReset(cmd_context); /* XXX this is a pretty random place to make this check */ if (MyDatabaseId == InvalidOid) @@ -2044,15 +2056,13 @@ exec_replication_command(const char *cmd_string) /* * Looks like a WalSender command, so parse it. */ - parse_rc = replication_yyparse(); + parse_rc = replication_yyparse(&cmd_node, scanner); if (parse_rc != 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg_internal("replication command parser returned %d", parse_rc))); - replication_scanner_finish(); - - cmd_node = replication_parse_result; + replication_scanner_finish(scanner); /* * Report query to various monitoring facilities. For this purpose, we @@ -2191,9 +2201,12 @@ exec_replication_command(const char *cmd_string) cmd_node->type); } - /* done */ + /* + * Done. Revert to caller's memory context, and clean out the cmd_context + * to recover memory right away. + */ MemoryContextSwitchTo(old_context); - MemoryContextDelete(cmd_context); + MemoryContextReset(cmd_context); /* * We need not update ps display or pg_stat_activity, because PostgresMain @@ -2769,6 +2782,8 @@ WalSndCheckTimeOut(void) static void WalSndLoop(WalSndSendDataCallback send_data) { + TimestampTz last_flush = 0; + /* * Initialize the last reply timestamp. That enables timeout processing * from hereon. @@ -2863,6 +2878,9 @@ WalSndLoop(WalSndSendDataCallback send_data) * WalSndWaitForWal() handle any other blocking; idle receivers need * its additional actions. For physical replication, also block if * caught up; its send_data does not block. + * + * The IO statistics are reported in WalSndWaitForWal() for the + * logical WAL senders. */ if ((WalSndCaughtUp && send_data != XLogSendLogical && !streamingDoneSending) || @@ -2870,6 +2888,7 @@ WalSndLoop(WalSndSendDataCallback send_data) { long sleeptime; int wakeEvents; + TimestampTz now; if (!streamingDoneReceiving) wakeEvents = WL_SOCKET_READABLE; @@ -2880,11 +2899,21 @@ WalSndLoop(WalSndSendDataCallback send_data) * Use fresh timestamp, not last_processing, to reduce the chance * of reaching wal_sender_timeout before sending a keepalive. */ - sleeptime = WalSndComputeSleeptime(GetCurrentTimestamp()); + now = GetCurrentTimestamp(); + sleeptime = WalSndComputeSleeptime(now); if (pq_is_send_pending()) wakeEvents |= WL_SOCKET_WRITEABLE; + /* Report IO statistics, if needed */ + if (TimestampDifferenceExceeds(last_flush, now, + WALSENDER_STATS_FLUSH_INTERVAL)) + { + pgstat_flush_io(false); + (void) pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO); + last_flush = now; + } + /* Sleep until something happens or we time out */ WalSndWait(wakeEvents, sleeptime, WAIT_EVENT_WAL_SENDER_MAIN); } @@ -2935,7 +2964,6 @@ InitWalSenderSlot(void) walsnd->flushLag = -1; walsnd->applyLag = -1; walsnd->sync_standby_priority = 0; - walsnd->latch = &MyProc->procLatch; walsnd->replyTime = 0; /* @@ -2979,8 +3007,6 @@ WalSndKill(int code, Datum arg) MyWalSnd = NULL; SpinLockAcquire(&walsnd->mutex); - /* clear latch while holding the spinlock, so it can safely be read */ - walsnd->latch = NULL; /* Mark WalSnd struct as no longer being in use. */ walsnd->pid = 0; SpinLockRelease(&walsnd->mutex); @@ -3423,8 +3449,16 @@ XLogSendLogical(void) if (flushPtr == InvalidXLogRecPtr || logical_decoding_ctx->reader->EndRecPtr >= flushPtr) { + /* + * For cascading logical WAL senders, we use the replay LSN instead of + * the flush LSN, since logical decoding on a standby only processes + * WAL that has been replayed. This distinction becomes particularly + * important during shutdown, as new WAL is no longer replayed and the + * last replayed LSN marks the furthest point up to which decoding can + * proceed. + */ if (am_cascading_walsender) - flushPtr = GetStandbyFlushRecPtr(NULL); + flushPtr = GetXLogReplayRecPtr(NULL); else flushPtr = GetFlushRecPtr(NULL); } diff --git a/src/backend/rewrite/meson.build b/src/backend/rewrite/meson.build index 23043ca6e56d5..5615d085ba345 100644 --- a/src/backend/rewrite/meson.build +++ b/src/backend/rewrite/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'rewriteDefine.c', diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 6cc9a8d8bfe90..8aa90b0d6fb75 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -3,7 +3,7 @@ * rewriteDefine.c * routines for defining a rewrite rule * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -644,7 +644,7 @@ setRuleCheckAsUser_walker(Node *node, Oid *context) return false; } return expression_tree_walker(node, setRuleCheckAsUser_walker, - (void *) context); + context); } static void @@ -679,7 +679,7 @@ setRuleCheckAsUser_Query(Query *qry, Oid userid) /* If there are sublinks, search for them and process their RTEs */ if (qry->hasSubLinks) - query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid, + query_tree_walker(qry, setRuleCheckAsUser_walker, &userid, QTW_IGNORE_RC_SUBQUERIES); } diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index e1d805d113eda..2ef0e7fbf3a69 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -3,7 +3,7 @@ * rewriteHandler.c * Primary module of query rewriter. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -40,6 +40,7 @@ #include "rewrite/rewriteManip.h" #include "rewrite/rewriteSearchCycle.h" #include "rewrite/rowsecurity.h" +#include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -57,6 +58,12 @@ typedef struct acquireLocksOnSubLinks_context bool for_execute; /* AcquireRewriteLocks' forExecute param */ } acquireLocksOnSubLinks_context; +typedef struct fireRIRonSubLink_context +{ + List *activeRIRs; + bool hasRowSecurity; +} fireRIRonSubLink_context; + static bool acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context); static Query *rewriteRuleAction(Query *parsetree, @@ -89,6 +96,8 @@ static List *matchLocks(CmdType event, Relation relation, int varno, Query *parsetree, bool *hasUpdate); static Query *fireRIRrules(Query *parsetree, List *activeRIRs); static Bitmapset *adjust_view_column_set(Bitmapset *cols, List *targetlist); +static Node *expand_generated_columns_internal(Node *node, Relation rel, int rt_index, + RangeTblEntry *rte, int result_relation); /* @@ -634,6 +643,7 @@ rewriteRuleAction(Query *parsetree, 0, rt_fetch(new_varno, sub_action->rtable), parsetree->targetList, + sub_action->resultRelation, (event == CMD_UPDATE) ? REPLACEVARS_CHANGE_VARNO : REPLACEVARS_SUBSTITUTE_NULL, @@ -667,10 +677,15 @@ rewriteRuleAction(Query *parsetree, rt_fetch(parsetree->resultRelation, parsetree->rtable), rule_action->returningList, + rule_action->resultRelation, REPLACEVARS_REPORT_ERROR, 0, &rule_action->hasSubLinks); + /* use triggering query's aliases for OLD and NEW in RETURNING list */ + rule_action->returningOldAlias = parsetree->returningOldAlias; + rule_action->returningNewAlias = parsetree->returningNewAlias; + /* * There could have been some SubLinks in parsetree's returningList, * in which case we'd better mark the rule_action correctly. @@ -973,7 +988,8 @@ rewriteTargetListIU(List *targetList, if (att_tup->attgenerated) { /* - * stored generated column will be fixed in executor + * virtual generated column stores a null value; stored generated + * column will be fixed in executor */ new_tle = NULL; } @@ -995,23 +1011,11 @@ rewriteTargetListIU(List *targetList, if (commandType == CMD_INSERT) new_tle = NULL; else - { - new_expr = (Node *) makeConst(att_tup->atttypid, - -1, - att_tup->attcollation, - att_tup->attlen, - (Datum) 0, - true, /* isnull */ - att_tup->attbyval); - /* this is to catch a NOT NULL domain constraint */ - new_expr = coerce_to_domain(new_expr, - InvalidOid, -1, - att_tup->atttypid, - COERCION_IMPLICIT, - COERCE_IMPLICIT_CAST, - -1, - false); - } + new_expr = coerce_null_to_domain(att_tup->atttypid, + att_tup->atttypmod, + att_tup->attcollation, + att_tup->attlen, + att_tup->attbyval); } if (new_expr) @@ -1559,21 +1563,11 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti, continue; } - new_expr = (Node *) makeConst(att_tup->atttypid, - -1, - att_tup->attcollation, - att_tup->attlen, - (Datum) 0, - true, /* isnull */ - att_tup->attbyval); - /* this is to catch a NOT NULL domain constraint */ - new_expr = coerce_to_domain(new_expr, - InvalidOid, -1, - att_tup->atttypid, - COERCION_IMPLICIT, - COERCE_IMPLICIT_CAST, - -1, - false); + new_expr = coerce_null_to_domain(att_tup->atttypid, + att_tup->atttypmod, + att_tup->attcollation, + att_tup->attlen, + att_tup->attbyval); } newList = lappend(newList, new_expr); } @@ -1729,6 +1723,14 @@ ApplyRetrieveRule(Query *parsetree, if (rule->qual != NULL) elog(ERROR, "cannot handle qualified ON SELECT rule"); + /* Check if the expansion of non-system views are restricted */ + if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 && + RelationGetRelid(relation) >= FirstNormalObjectId)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access to non-system view \"%s\" is restricted", + RelationGetRelationName(relation)))); + if (rt_index == parsetree->resultRelation) { /* @@ -1830,6 +1832,12 @@ ApplyRetrieveRule(Query *parsetree, */ rule_action = fireRIRrules(rule_action, activeRIRs); + /* + * Make sure the query is marked as having row security if the view query + * does. + */ + parsetree->hasRowSecurity |= rule_action->hasRowSecurity; + /* * Now, plug the view query in as a subselect, converting the relation's * original RTE to a subquery RTE. @@ -1943,7 +1951,7 @@ markQueryForLocking(Query *qry, Node *jtnode, * the SubLink's subselect link with the possibly-rewritten subquery. */ static bool -fireRIRonSubLink(Node *node, List *activeRIRs) +fireRIRonSubLink(Node *node, fireRIRonSubLink_context *context) { if (node == NULL) return false; @@ -1953,7 +1961,13 @@ fireRIRonSubLink(Node *node, List *activeRIRs) /* Do what we came for */ sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect, - activeRIRs); + context->activeRIRs); + + /* + * Remember if any of the sublinks have row security. + */ + context->hasRowSecurity |= ((Query *) sub->subselect)->hasRowSecurity; + /* Fall through to process lefthand args of SubLink */ } @@ -1961,8 +1975,7 @@ fireRIRonSubLink(Node *node, List *activeRIRs) * Do NOT recurse into Query nodes, because fireRIRrules already processed * subselects of subselects for us. */ - return expression_tree_walker(node, fireRIRonSubLink, - (void *) activeRIRs); + return expression_tree_walker(node, fireRIRonSubLink, context); } @@ -2023,6 +2036,13 @@ fireRIRrules(Query *parsetree, List *activeRIRs) if (rte->rtekind == RTE_SUBQUERY) { rte->subquery = fireRIRrules(rte->subquery, activeRIRs); + + /* + * While we are here, make sure the query is marked as having row + * security if any of its subqueries do. + */ + parsetree->hasRowSecurity |= rte->subquery->hasRowSecurity; + continue; } @@ -2136,6 +2156,12 @@ fireRIRrules(Query *parsetree, List *activeRIRs) cte->ctequery = (Node *) fireRIRrules((Query *) cte->ctequery, activeRIRs); + + /* + * While we are here, make sure the query is marked as having row + * security if any of its CTEs do. + */ + parsetree->hasRowSecurity |= ((Query *) cte->ctequery)->hasRowSecurity; } /* @@ -2143,9 +2169,22 @@ fireRIRrules(Query *parsetree, List *activeRIRs) * the rtable and cteList. */ if (parsetree->hasSubLinks) - query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs, + { + fireRIRonSubLink_context context; + + context.activeRIRs = activeRIRs; + context.hasRowSecurity = false; + + query_tree_walker(parsetree, fireRIRonSubLink, &context, QTW_IGNORE_RC_SUBQUERIES); + /* + * Make sure the query is marked as having row security if any of its + * sublinks do. + */ + parsetree->hasRowSecurity |= context.hasRowSecurity; + } + /* * Apply any row-level security policies. We do this last because it * requires special recursion detection if the new quals have sublink @@ -2184,6 +2223,7 @@ fireRIRrules(Query *parsetree, List *activeRIRs) if (hasSubLinks) { acquireLocksOnSubLinks_context context; + fireRIRonSubLink_context fire_context; /* * Recursively process the new quals, checking for infinite @@ -2214,11 +2254,21 @@ fireRIRrules(Query *parsetree, List *activeRIRs) * Now that we have the locks on anything added by * get_row_security_policies, fire any RIR rules for them. */ + fire_context.activeRIRs = activeRIRs; + fire_context.hasRowSecurity = false; + expression_tree_walker((Node *) securityQuals, - fireRIRonSubLink, (void *) activeRIRs); + fireRIRonSubLink, &fire_context); expression_tree_walker((Node *) withCheckOptions, - fireRIRonSubLink, (void *) activeRIRs); + fireRIRonSubLink, &fire_context); + + /* + * We can ignore the value of fire_context.hasRowSecurity + * since we only reach this code in cases where hasRowSecurity + * is already true. + */ + Assert(hasRowSecurity); activeRIRs = list_delete_last(activeRIRs); } @@ -2295,6 +2345,7 @@ CopyAndAddInvertedQual(Query *parsetree, rt_fetch(rt_index, parsetree->rtable), parsetree->targetList, + parsetree->resultRelation, (event == CMD_UPDATE) ? REPLACEVARS_CHANGE_VARNO : REPLACEVARS_SUBSTITUTE_NULL, @@ -3212,6 +3263,14 @@ rewriteTargetView(Query *parsetree, Relation view) } } + /* Check if the expansion of non-system views are restricted */ + if (unlikely((restrict_nonsystem_relation_kind & RESTRICT_RELKIND_VIEW) != 0 && + RelationGetRelid(view) >= FirstNormalObjectId)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("access to non-system view \"%s\" is restricted", + RelationGetRelationName(view)))); + /* * The view must be updatable, else fail. * @@ -3345,7 +3404,7 @@ rewriteTargetView(Query *parsetree, Relation view) errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot merge into view \"%s\"", RelationGetRelationName(view)), - errdetail("MERGE is not supported for views with INSTEAD OF triggers for some actions, but not others."), + errdetail("MERGE is not supported for views with INSTEAD OF triggers for some actions but not all."), errhint("To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers.")); } } @@ -3511,6 +3570,7 @@ rewriteTargetView(Query *parsetree, Relation view) 0, view_rte, view_targetlist, + new_rt_index, REPLACEVARS_REPORT_ERROR, 0, NULL); @@ -3662,6 +3722,7 @@ rewriteTargetView(Query *parsetree, Relation view) 0, view_rte, tmp_tlist, + new_rt_index, REPLACEVARS_REPORT_ERROR, 0, &parsetree->hasSubLinks); @@ -4348,6 +4409,129 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length) } +/* + * Expand virtual generated columns + * + * If the table contains virtual generated columns, build a target list + * containing the expanded expressions and use ReplaceVarsFromTargetList() to + * do the replacements. + * + * Vars matching rt_index at the current query level are replaced by the + * virtual generated column expressions from rel, if there are any. + * + * The caller must also provide rte, the RTE describing the target relation, + * in order to handle any whole-row Vars referencing the target, and + * result_relation, the index of the result relation, if this is part of an + * INSERT/UPDATE/DELETE/MERGE query. + */ +static Node * +expand_generated_columns_internal(Node *node, Relation rel, int rt_index, + RangeTblEntry *rte, int result_relation) +{ + TupleDesc tupdesc; + + tupdesc = RelationGetDescr(rel); + if (tupdesc->constr && tupdesc->constr->has_generated_virtual) + { + List *tlist = NIL; + + for (int i = 0; i < tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + { + Node *defexpr; + TargetEntry *te; + + defexpr = build_generation_expression(rel, i + 1); + ChangeVarNodes(defexpr, 1, rt_index, 0); + + te = makeTargetEntry((Expr *) defexpr, i + 1, 0, false); + tlist = lappend(tlist, te); + } + } + + Assert(list_length(tlist) > 0); + + node = ReplaceVarsFromTargetList(node, rt_index, 0, rte, tlist, + result_relation, + REPLACEVARS_CHANGE_VARNO, rt_index, + NULL); + } + + return node; +} + +/* + * Expand virtual generated columns in an expression + * + * This is for expressions that are not part of a query, such as default + * expressions or index predicates. The rt_index is usually 1. + */ +Node * +expand_generated_columns_in_expr(Node *node, Relation rel, int rt_index) +{ + TupleDesc tupdesc = RelationGetDescr(rel); + + if (tupdesc->constr && tupdesc->constr->has_generated_virtual) + { + RangeTblEntry *rte; + + rte = makeNode(RangeTblEntry); + /* eref needs to be set, but the actual name doesn't matter */ + rte->eref = makeAlias(RelationGetRelationName(rel), NIL); + rte->rtekind = RTE_RELATION; + rte->relid = RelationGetRelid(rel); + + node = expand_generated_columns_internal(node, rel, rt_index, rte, 0); + } + + return node; +} + +/* + * Build the generation expression for the virtual generated column. + * + * Error out if there is no generation expression found for the given column. + */ +Node * +build_generation_expression(Relation rel, int attrno) +{ + TupleDesc rd_att = RelationGetDescr(rel); + Form_pg_attribute att_tup = TupleDescAttr(rd_att, attrno - 1); + Node *defexpr; + Oid attcollid; + + Assert(rd_att->constr && rd_att->constr->has_generated_virtual); + Assert(att_tup->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL); + + defexpr = build_column_default(rel, attrno); + if (defexpr == NULL) + elog(ERROR, "no generation expression found for column number %d of table \"%s\"", + attrno, RelationGetRelationName(rel)); + + /* + * If the column definition has a collation and it is different from the + * collation of the generation expression, put a COLLATE clause around the + * expression. + */ + attcollid = att_tup->attcollation; + if (attcollid && attcollid != exprCollation(defexpr)) + { + CollateExpr *ce = makeNode(CollateExpr); + + ce->arg = (Expr *) defexpr; + ce->collOid = attcollid; + ce->location = -1; + + defexpr = (Node *) ce; + } + + return defexpr; +} + + /* * QueryRewrite - * Primary entry point to the query rewriter. @@ -4360,7 +4544,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length) List * QueryRewrite(Query *parsetree) { - uint64 input_query_id = parsetree->queryId; + int64 input_query_id = parsetree->queryId; List *querylist; List *results; ListCell *l; diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 191f2dc0b1d8d..cd786aa4112b5 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -2,7 +2,7 @@ * * rewriteManip.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,6 +22,7 @@ #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "rewrite/rewriteManip.h" +#include "utils/lsyscache.h" typedef struct @@ -63,7 +64,6 @@ static bool locate_windowfunc_walker(Node *node, locate_windowfunc_context *context); static bool checkExprHasSubLink_walker(Node *node, void *context); static Relids offset_relid_set(Relids relids, int offset); -static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); static Node *add_nulling_relids_mutator(Node *node, add_nulling_relids_context *context); static Node *remove_nulling_relids_mutator(Node *node, @@ -94,7 +94,7 @@ contain_aggs_of_level(Node *node, int levelsup) */ return query_or_expression_tree_walker(node, contain_aggs_of_level_walker, - (void *) &context, + &context, 0); } @@ -124,12 +124,12 @@ contain_aggs_of_level_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, contain_aggs_of_level_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } return expression_tree_walker(node, contain_aggs_of_level_walker, - (void *) context); + context); } /* @@ -159,7 +159,7 @@ locate_agg_of_level(Node *node, int levelsup) */ (void) query_or_expression_tree_walker(node, locate_agg_of_level_walker, - (void *) &context, + &context, 0); return context.agg_location; @@ -198,12 +198,11 @@ locate_agg_of_level_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, locate_agg_of_level_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, locate_agg_of_level_walker, - (void *) context); + return expression_tree_walker(node, locate_agg_of_level_walker, context); } /* @@ -232,8 +231,7 @@ contain_windowfuncs_walker(Node *node, void *context) if (IsA(node, WindowFunc)) return true; /* abort the tree traversal and return true */ /* Mustn't recurse into subselects */ - return expression_tree_walker(node, contain_windowfuncs_walker, - (void *) context); + return expression_tree_walker(node, contain_windowfuncs_walker, context); } /* @@ -262,7 +260,7 @@ locate_windowfunc(Node *node) */ (void) query_or_expression_tree_walker(node, locate_windowfunc_walker, - (void *) &context, + &context, 0); return context.win_location; @@ -283,8 +281,7 @@ locate_windowfunc_walker(Node *node, locate_windowfunc_context *context) /* else fall through to examine argument */ } /* Mustn't recurse into subselects */ - return expression_tree_walker(node, locate_windowfunc_walker, - (void *) context); + return expression_tree_walker(node, locate_windowfunc_walker, context); } /* @@ -468,12 +465,11 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, OffsetVarNodes_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, OffsetVarNodes_walker, - (void *) context); + return expression_tree_walker(node, OffsetVarNodes_walker, context); } void @@ -521,8 +517,7 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) rc->rti += offset; } } - query_tree_walker(qry, OffsetVarNodes_walker, - (void *) &context, 0); + query_tree_walker(qry, OffsetVarNodes_walker, &context, 0); } else OffsetVarNodes_walker(node, &context); @@ -547,24 +542,23 @@ offset_relid_set(Relids relids, int offset) * (identified by sublevels_up and rt_index), and change their varno fields * to 'new_index'. The varnosyn fields are changed too. Also, adjust other * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr. + * Specifying 'change_RangeTblRef' to false allows skipping RangeTblRef. + * See ChangeVarNodesExtended for details. * * NOTE: although this has the form of a walker, we cheat and modify the * nodes in-place. The given expression tree should have been copied * earlier to ensure that no unwanted side-effects occur! */ -typedef struct -{ - int rt_index; - int new_index; - int sublevels_up; -} ChangeVarNodes_context; - static bool ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) { if (node == NULL) return false; + + if (context->callback && context->callback(node, context)) + return false; + if (IsA(node, Var)) { Var *var = (Var *) node; @@ -662,22 +656,36 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, ChangeVarNodes_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, ChangeVarNodes_walker, - (void *) context); + return expression_tree_walker(node, ChangeVarNodes_walker, context); } +/* + * ChangeVarNodesExtended - similar to ChangeVarNodes, but with an additional + * 'callback' param + * + * ChangeVarNodes changes a given node and all of its underlying nodes. + * This version of function additionally takes a callback, which has a + * chance to process a node before ChangeVarNodes_walker. A callback + * returns a boolean value indicating if given node should be skipped from + * further processing by ChangeVarNodes_walker. The callback is called + * only for expressions and other children nodes of a Query processed by + * a walker. Initial processing of the root Query doesn't involve the + * callback. + */ void -ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) +ChangeVarNodesExtended(Node *node, int rt_index, int new_index, + int sublevels_up, ChangeVarNodes_callback callback) { ChangeVarNodes_context context; context.rt_index = rt_index; context.new_index = new_index; context.sublevels_up = sublevels_up; + context.callback = callback; /* * Must be prepared to start with a Query or a bare expression tree; if @@ -718,22 +726,41 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) rc->rti = new_index; } } - query_tree_walker(qry, ChangeVarNodes_walker, - (void *) &context, 0); + query_tree_walker(qry, ChangeVarNodes_walker, &context, 0); } else ChangeVarNodes_walker(node, &context); } +void +ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) +{ + ChangeVarNodesExtended(node, rt_index, new_index, sublevels_up, NULL); +} + /* - * Substitute newrelid for oldrelid in a Relid set + * ChangeVarNodesWalkExpression - process expression within the custom + * callback provided to the + * ChangeVarNodesExtended. + */ +bool +ChangeVarNodesWalkExpression(Node *node, ChangeVarNodes_context *context) +{ + return expression_tree_walker(node, + ChangeVarNodes_walker, + (void *) context); +} + +/* + * adjust_relid_set - substitute newrelid for oldrelid in a Relid set * - * Note: some extensions may pass a special varno such as INDEX_VAR for - * oldrelid. bms_is_member won't like that, but we should tolerate it. - * (Perhaps newrelid could also be a special varno, but there had better - * not be a reason to inject that into a nullingrels or phrels set.) + * Attempt to remove oldrelid from a Relid set (as long as it's not a special + * varno). If oldrelid was found and removed, insert newrelid into a Relid + * set (as long as it's not a special varno). Therefore, when oldrelid is + * a special varno, this function does nothing. When newrelid is a special + * varno, this function behaves as delete. */ -static Relids +Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid) { if (!IS_SPECIAL_VARNO(oldrelid) && bms_is_member(oldrelid, relids)) @@ -742,7 +769,8 @@ adjust_relid_set(Relids relids, int oldrelid, int newrelid) relids = bms_copy(relids); /* Remove old, add new */ relids = bms_del_member(relids, oldrelid); - relids = bms_add_member(relids, newrelid); + if (!IS_SPECIAL_VARNO(newrelid)) + relids = bms_add_member(relids, newrelid); } return relids; } @@ -817,6 +845,14 @@ IncrementVarSublevelsUp_walker(Node *node, phv->phlevelsup += context->delta_sublevels_up; /* fall through to recurse into argument */ } + if (IsA(node, ReturningExpr)) + { + ReturningExpr *rexpr = (ReturningExpr *) node; + + if (rexpr->retlevelsup >= context->min_sublevels_up) + rexpr->retlevelsup += context->delta_sublevels_up; + /* fall through to recurse into argument */ + } if (IsA(node, RangeTblEntry)) { RangeTblEntry *rte = (RangeTblEntry *) node; @@ -836,13 +872,12 @@ IncrementVarSublevelsUp_walker(Node *node, context->min_sublevels_up++; result = query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, - (void *) context, + context, QTW_EXAMINE_RTES_BEFORE); context->min_sublevels_up--; return result; } - return expression_tree_walker(node, IncrementVarSublevelsUp_walker, - (void *) context); + return expression_tree_walker(node, IncrementVarSublevelsUp_walker, context); } void @@ -860,7 +895,7 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, */ query_or_expression_tree_walker(node, IncrementVarSublevelsUp_walker, - (void *) &context, + &context, QTW_EXAMINE_RTES_BEFORE); } @@ -879,10 +914,71 @@ IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up, range_table_walker(rtable, IncrementVarSublevelsUp_walker, - (void *) &context, + &context, QTW_EXAMINE_RTES_BEFORE); } +/* + * SetVarReturningType - adjust Var nodes for a specified varreturningtype. + * + * Find all Var nodes referring to the specified result relation in the given + * expression and set their varreturningtype to the specified value. + * + * NOTE: although this has the form of a walker, we cheat and modify the + * Var nodes in-place. The given expression tree should have been copied + * earlier to ensure that no unwanted side-effects occur! + */ + +typedef struct +{ + int result_relation; + int sublevels_up; + VarReturningType returning_type; +} SetVarReturningType_context; + +static bool +SetVarReturningType_walker(Node *node, SetVarReturningType_context *context) +{ + if (node == NULL) + return false; + if (IsA(node, Var)) + { + Var *var = (Var *) node; + + if (var->varno == context->result_relation && + var->varlevelsup == context->sublevels_up) + var->varreturningtype = context->returning_type; + + return false; + } + + if (IsA(node, Query)) + { + /* Recurse into subselects */ + bool result; + + context->sublevels_up++; + result = query_tree_walker((Query *) node, SetVarReturningType_walker, + context, 0); + context->sublevels_up--; + return result; + } + return expression_tree_walker(node, SetVarReturningType_walker, context); +} + +static void +SetVarReturningType(Node *node, int result_relation, int sublevels_up, + VarReturningType returning_type) +{ + SetVarReturningType_context context; + + context.result_relation = result_relation; + context.sublevels_up = sublevels_up; + context.returning_type = returning_type; + + /* Expect to start with an expression */ + SetVarReturningType_walker(node, &context); +} /* * rangeTableEntry_used - detect whether an RTE is referenced somewhere @@ -954,12 +1050,11 @@ rangeTableEntry_used_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, rangeTableEntry_used_walker, - (void *) context, 0); + context, 0); context->sublevels_up--; return result; } - return expression_tree_walker(node, rangeTableEntry_used_walker, - (void *) context); + return expression_tree_walker(node, rangeTableEntry_used_walker, context); } bool @@ -976,7 +1071,7 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) */ return query_or_expression_tree_walker(node, rangeTableEntry_used_walker, - (void *) &context, + &context, 0); } @@ -1141,7 +1236,8 @@ AddInvertedQual(Query *parsetree, Node *qual) /* * add_nulling_relids() finds Vars and PlaceHolderVars that belong to any * of the target_relids, and adds added_relids to their varnullingrels - * and phnullingrels fields. + * and phnullingrels fields. If target_relids is NULL, all level-zero + * Vars and PHVs are modified. */ Node * add_nulling_relids(Node *node, @@ -1170,7 +1266,8 @@ add_nulling_relids_mutator(Node *node, Var *var = (Var *) node; if (var->varlevelsup == context->sublevels_up && - bms_is_member(var->varno, context->target_relids)) + (context->target_relids == NULL || + bms_is_member(var->varno, context->target_relids))) { Relids newnullingrels = bms_union(var->varnullingrels, context->added_relids); @@ -1188,7 +1285,8 @@ add_nulling_relids_mutator(Node *node, PlaceHolderVar *phv = (PlaceHolderVar *) node; if (phv->phlevelsup == context->sublevels_up && - bms_overlap(phv->phrels, context->target_relids)) + (context->target_relids == NULL || + bms_overlap(phv->phrels, context->target_relids))) { Relids newnullingrels = bms_union(phv->phnullingrels, context->added_relids); @@ -1215,13 +1313,12 @@ add_nulling_relids_mutator(Node *node, context->sublevels_up++; newnode = query_tree_mutator((Query *) node, add_nulling_relids_mutator, - (void *) context, + context, 0); context->sublevels_up--; return (Node *) newnode; } - return expression_tree_mutator(node, add_nulling_relids_mutator, - (void *) context); + return expression_tree_mutator(node, add_nulling_relids_mutator, context); } /* @@ -1280,13 +1377,13 @@ remove_nulling_relids_mutator(Node *node, * Note: it might seem desirable to remove the PHV altogether if * phnullingrels goes to empty. Currently we dare not do that * because we use PHVs in some cases to enforce separate identity - * of subexpressions; see wrap_non_vars usages in prepjointree.c. + * of subexpressions; see wrap_option usages in prepjointree.c. */ /* Copy the PlaceHolderVar and mutate what's below ... */ phv = (PlaceHolderVar *) expression_tree_mutator(node, remove_nulling_relids_mutator, - (void *) context); + context); /* ... and replace the copy's phnullingrels field */ phv->phnullingrels = bms_difference(phv->phnullingrels, context->removable_relids); @@ -1306,13 +1403,12 @@ remove_nulling_relids_mutator(Node *node, context->sublevels_up++; newnode = query_tree_mutator((Query *) node, remove_nulling_relids_mutator, - (void *) context, + context, 0); context->sublevels_up--; return (Node *) newnode; } - return expression_tree_mutator(node, remove_nulling_relids_mutator, - (void *) context); + return expression_tree_mutator(node, remove_nulling_relids_mutator, context); } @@ -1369,7 +1465,7 @@ replace_rte_variables(Node *node, int target_varno, int sublevels_up, */ result = query_or_expression_tree_mutator(node, replace_rte_variables_mutator, - (void *) &context, + &context, 0); if (context.inserted_sublink) @@ -1439,15 +1535,14 @@ replace_rte_variables_mutator(Node *node, context->inserted_sublink = ((Query *) node)->hasSubLinks; newnode = query_tree_mutator((Query *) node, replace_rte_variables_mutator, - (void *) context, + context, 0); newnode->hasSubLinks |= context->inserted_sublink; context->inserted_sublink = save_inserted_sublink; context->sublevels_up--; return (Node *) newnode; } - return expression_tree_mutator(node, replace_rte_variables_mutator, - (void *) context); + return expression_tree_mutator(node, replace_rte_variables_mutator, context); } @@ -1598,13 +1693,12 @@ map_variable_attnos_mutator(Node *node, context->sublevels_up++; newnode = query_tree_mutator((Query *) node, map_variable_attnos_mutator, - (void *) context, + context, 0); context->sublevels_up--; return (Node *) newnode; } - return expression_tree_mutator(node, map_variable_attnos_mutator, - (void *) context); + return expression_tree_mutator(node, map_variable_attnos_mutator, context); } Node * @@ -1629,7 +1723,7 @@ map_variable_attnos(Node *node, */ return query_or_expression_tree_mutator(node, map_variable_attnos_mutator, - (void *) &context, + &context, 0); } @@ -1650,6 +1744,20 @@ map_variable_attnos(Node *node, * relation. This is needed to handle whole-row Vars referencing the target. * We expand such Vars into RowExpr constructs. * + * In addition, for INSERT/UPDATE/DELETE/MERGE queries, the caller must + * provide result_relation, the index of the result relation in the rewritten + * query. This is needed to handle OLD/NEW RETURNING list Vars referencing + * target_varno. When such Vars are expanded, their varreturningtype is + * copied onto any replacement Vars referencing result_relation. In addition, + * if the replacement expression from the targetlist is not simply a Var + * referencing result_relation, it is wrapped in a ReturningExpr node (causing + * the executor to return NULL if the OLD/NEW row doesn't exist). + * + * Note that ReplaceVarFromTargetList always generates the replacement + * expression with varlevelsup = 0. The caller is responsible for adjusting + * the varlevelsup if needed. This simplifies the caller's life if it wants to + * cache the replacement expressions. + * * outer_hasSubLinks works the same as for replace_rte_variables(). */ @@ -1657,6 +1765,7 @@ typedef struct { RangeTblEntry *target_rte; List *targetlist; + int result_relation; ReplaceVarsNoMatchOption nomatch_option; int nomatch_varno; } ReplaceVarsFromTargetList_context; @@ -1666,6 +1775,30 @@ ReplaceVarsFromTargetList_callback(Var *var, replace_rte_variables_context *context) { ReplaceVarsFromTargetList_context *rcon = (ReplaceVarsFromTargetList_context *) context->callback_arg; + Node *newnode; + + newnode = ReplaceVarFromTargetList(var, + rcon->target_rte, + rcon->targetlist, + rcon->result_relation, + rcon->nomatch_option, + rcon->nomatch_varno); + + /* Must adjust varlevelsup if replaced Var is within a subquery */ + if (var->varlevelsup > 0) + IncrementVarSublevelsUp(newnode, var->varlevelsup, 0); + + return newnode; +} + +Node * +ReplaceVarFromTargetList(Var *var, + RangeTblEntry *target_rte, + List *targetlist, + int result_relation, + ReplaceVarsNoMatchOption nomatch_option, + int nomatch_varno) +{ TargetEntry *tle; if (var->varattno == InvalidAttrNumber) @@ -1674,6 +1807,7 @@ ReplaceVarsFromTargetList_callback(Var *var, RowExpr *rowexpr; List *colnames; List *fields; + ListCell *lc; /* * If generating an expansion for a var of a named rowtype (ie, this @@ -1681,57 +1815,91 @@ ReplaceVarsFromTargetList_callback(Var *var, * dropped columns. If the var is RECORD (ie, this is a JOIN), then * omit dropped columns. In the latter case, attach column names to * the RowExpr for use of the executor and ruleutils.c. + * + * In order to be able to cache the results, we always generate the + * expansion with varlevelsup = 0. The caller is responsible for + * adjusting it if needed. + * + * The varreturningtype is copied onto each individual field Var, so + * that it is handled correctly when we recurse. */ - expandRTE(rcon->target_rte, - var->varno, var->varlevelsup, var->location, + expandRTE(target_rte, + var->varno, 0 /* not varlevelsup */ , + var->varreturningtype, var->location, (var->vartype != RECORDOID), &colnames, &fields); - /* Adjust the generated per-field Vars... */ - fields = (List *) replace_rte_variables_mutator((Node *) fields, - context); rowexpr = makeNode(RowExpr); - rowexpr->args = fields; + /* the fields will be set below */ + rowexpr->args = NIL; rowexpr->row_typeid = var->vartype; rowexpr->row_format = COERCE_IMPLICIT_CAST; rowexpr->colnames = (var->vartype == RECORDOID) ? colnames : NIL; rowexpr->location = var->location; + /* Adjust the generated per-field Vars... */ + foreach(lc, fields) + { + Node *field = lfirst(lc); + + if (field && IsA(field, Var)) + field = ReplaceVarFromTargetList((Var *) field, + target_rte, + targetlist, + result_relation, + nomatch_option, + nomatch_varno); + rowexpr->args = lappend(rowexpr->args, field); + } + + /* Wrap it in a ReturningExpr, if needed, per comments above */ + if (var->varreturningtype != VAR_RETURNING_DEFAULT) + { + ReturningExpr *rexpr = makeNode(ReturningExpr); + + rexpr->retlevelsup = 0; + rexpr->retold = (var->varreturningtype == VAR_RETURNING_OLD); + rexpr->retexpr = (Expr *) rowexpr; + + return (Node *) rexpr; + } return (Node *) rowexpr; } /* Normal case referencing one targetlist element */ - tle = get_tle_by_resno(rcon->targetlist, var->varattno); + tle = get_tle_by_resno(targetlist, var->varattno); if (tle == NULL || tle->resjunk) { /* Failed to find column in targetlist */ - switch (rcon->nomatch_option) + switch (nomatch_option) { case REPLACEVARS_REPORT_ERROR: /* fall through, throw error below */ break; case REPLACEVARS_CHANGE_VARNO: - var = (Var *) copyObject(var); - var->varno = rcon->nomatch_varno; + var = copyObject(var); + var->varno = nomatch_varno; + var->varlevelsup = 0; /* we leave the syntactic referent alone */ return (Node *) var; case REPLACEVARS_SUBSTITUTE_NULL: - - /* - * If Var is of domain type, we should add a CoerceToDomain - * node, in case there is a NOT NULL domain constraint. - */ - return coerce_to_domain((Node *) makeNullConst(var->vartype, - var->vartypmod, - var->varcollid), - InvalidOid, -1, - var->vartype, - COERCION_IMPLICIT, - COERCE_IMPLICIT_CAST, - -1, - false); + { + /* + * If Var is of domain type, we must add a CoerceToDomain + * node, in case there is a NOT NULL domain constraint. + */ + int16 vartyplen; + bool vartypbyval; + + get_typlenbyval(var->vartype, &vartyplen, &vartypbyval); + return coerce_null_to_domain(var->vartype, + var->vartypmod, + var->varcollid, + vartyplen, + vartypbyval); + } } elog(ERROR, "could not find replacement targetlist entry for attno %d", var->varattno); @@ -1742,10 +1910,6 @@ ReplaceVarsFromTargetList_callback(Var *var, /* Make a copy of the tlist item to return */ Expr *newnode = copyObject(tle->expr); - /* Must adjust varlevelsup if tlist item is from higher query */ - if (var->varlevelsup > 0) - IncrementVarSublevelsUp((Node *) newnode, var->varlevelsup, 0); - /* * Check to see if the tlist item contains a PARAM_MULTIEXPR Param, * and throw error if so. This case could only happen when expanding @@ -1761,6 +1925,34 @@ ReplaceVarsFromTargetList_callback(Var *var, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command"))); + /* Handle any OLD/NEW RETURNING list Vars */ + if (var->varreturningtype != VAR_RETURNING_DEFAULT) + { + /* + * Copy varreturningtype onto any Vars in the tlist item that + * refer to result_relation (which had better be non-zero). + */ + if (result_relation == 0) + elog(ERROR, "variable returning old/new found outside RETURNING list"); + + SetVarReturningType((Node *) newnode, result_relation, + 0, var->varreturningtype); + + /* Wrap it in a ReturningExpr, if needed, per comments above */ + if (!IsA(newnode, Var) || + ((Var *) newnode)->varno != result_relation || + ((Var *) newnode)->varlevelsup != 0) + { + ReturningExpr *rexpr = makeNode(ReturningExpr); + + rexpr->retlevelsup = 0; + rexpr->retold = (var->varreturningtype == VAR_RETURNING_OLD); + rexpr->retexpr = newnode; + + newnode = (Expr *) rexpr; + } + } + return (Node *) newnode; } } @@ -1770,6 +1962,7 @@ ReplaceVarsFromTargetList(Node *node, int target_varno, int sublevels_up, RangeTblEntry *target_rte, List *targetlist, + int result_relation, ReplaceVarsNoMatchOption nomatch_option, int nomatch_varno, bool *outer_hasSubLinks) @@ -1778,11 +1971,12 @@ ReplaceVarsFromTargetList(Node *node, context.target_rte = target_rte; context.targetlist = targetlist; + context.result_relation = result_relation; context.nomatch_option = nomatch_option; context.nomatch_varno = nomatch_varno; return replace_rte_variables(node, target_varno, sublevels_up, ReplaceVarsFromTargetList_callback, - (void *) &context, + &context, outer_hasSubLinks); } diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index cfa0aa9279edc..292c6e52cfc57 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -3,7 +3,7 @@ * rewriteRemove.c * routines for removing rewrite rules * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/rewrite/rewriteSearchCycle.c b/src/backend/rewrite/rewriteSearchCycle.c index 1c58003f9dc68..19b89dee0d096 100644 --- a/src/backend/rewrite/rewriteSearchCycle.c +++ b/src/backend/rewrite/rewriteSearchCycle.c @@ -3,7 +3,7 @@ * rewriteSearchCycle.c * Support for rewriting SEARCH and CYCLE clauses. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index c13be02a9a782..e401c19594902 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -3,7 +3,7 @@ * rewriteSupport.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c index 59fd305dd7bed..4dad384d04da3 100644 --- a/src/backend/rewrite/rowsecurity.c +++ b/src/backend/rewrite/rowsecurity.c @@ -29,7 +29,7 @@ * in the current environment, but that may change if the row_security GUC or * the current role changes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California */ #include "postgres.h" diff --git a/src/backend/snowball/Makefile b/src/backend/snowball/Makefile index efc4300eb976d..0398c9bb14ceb 100644 --- a/src/backend/snowball/Makefile +++ b/src/backend/snowball/Makefile @@ -40,7 +40,6 @@ OBJS += \ stem_ISO_8859_1_spanish.o \ stem_ISO_8859_1_swedish.o \ stem_ISO_8859_2_hungarian.o \ - stem_ISO_8859_2_romanian.o \ stem_KOI8_R_russian.o \ stem_UTF_8_arabic.o \ stem_UTF_8_armenian.o \ @@ -49,6 +48,7 @@ OBJS += \ stem_UTF_8_danish.o \ stem_UTF_8_dutch.o \ stem_UTF_8_english.o \ + stem_UTF_8_estonian.o \ stem_UTF_8_finnish.o \ stem_UTF_8_french.o \ stem_UTF_8_german.o \ diff --git a/src/backend/snowball/README b/src/backend/snowball/README index 675baff5c9704..2e41bee11423e 100644 --- a/src/backend/snowball/README +++ b/src/backend/snowball/README @@ -29,8 +29,8 @@ We choose to include the derived files in the PostgreSQL distribution because most installations will not have the Snowball compiler available. We are currently synced with the Snowball git commit -48a67a2831005f49c48ec29a5837640e23e54e6b (tag v2.2.0) -of 2021-11-10. +d19326ac6c1b9a417fc872f7c2f845265a5e9ece +of 2025-02-19. To update the PostgreSQL sources from a new Snowball version: @@ -44,8 +44,8 @@ do sed 's|\.\./runtime/header\.h|header.h|' $f >libstemmer/`basename $f` done -Do not copy stemmers that are listed in libstemmer/modules.txt as -nonstandard, such as "german2" or "lovins". +Do not copy stemmers that are listed in their libstemmer/modules.txt as +nonstandard, such as "kraaij_pohlmann" or "lovins". 2. Copy the *.c files in snowball/runtime/ to src/backend/snowball/libstemmer, and edit them to remove direct inclusions @@ -55,14 +55,18 @@ is sensitive to largefile compilation options.) 3. Copy the *.h files in snowball/src_c/ and snowball/runtime/ to src/include/snowball/libstemmer. At this writing the header files -do not require any changes. +do not require any changes. Again, omit the *.h files for nonstandard +stemmers. 4. Check whether any stemmer modules have been added or removed. If so, edit -the OBJS list in Makefile, the list of #include's in dict_snowball.c, and the -stemmer_modules[] table in dict_snowball.c, as well as the list in the -documentation in textsearch.sgml. You might also need to change -the LANGUAGES list in Makefile and tsearch_config_languages in initdb.c. +the OBJS list in Makefile, the dict_snowball_sources list in meson.build, +the list of #include's and the stemmer_modules[] table in dict_snowball.c, +and the sample \dFd output in the documentation in textsearch.sgml. +You might also need to change the @languages array in snowball_create.pl +and the tsearch_config_languages[] table in initdb.c. 5. The various stopword files in stopwords/ must be downloaded individually from pages on the snowballstem.org website. Be careful that these files must be stored in UTF-8 encoding. +Update the stop_files list in Makefile if any are added or removed +(the meson tooling does not require adjustment for that, though). diff --git a/src/backend/snowball/dict_snowball.c b/src/backend/snowball/dict_snowball.c index caf864906839a..e2b811a3806ec 100644 --- a/src/backend/snowball/dict_snowball.c +++ b/src/backend/snowball/dict_snowball.c @@ -3,7 +3,7 @@ * dict_snowball.c * Snowball dictionary * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/snowball/dict_snowball.c @@ -12,9 +12,11 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" #include "commands/defrem.h" -#include "tsearch/ts_locale.h" +#include "mb/pg_wchar.h" #include "tsearch/ts_public.h" +#include "utils/formatting.h" /* Some platforms define MAXINT and/or MININT, causing conflicts */ #ifdef MAXINT @@ -43,7 +45,6 @@ #include "snowball/libstemmer/stem_ISO_8859_1_spanish.h" #include "snowball/libstemmer/stem_ISO_8859_1_swedish.h" #include "snowball/libstemmer/stem_ISO_8859_2_hungarian.h" -#include "snowball/libstemmer/stem_ISO_8859_2_romanian.h" #include "snowball/libstemmer/stem_KOI8_R_russian.h" #include "snowball/libstemmer/stem_UTF_8_arabic.h" #include "snowball/libstemmer/stem_UTF_8_armenian.h" @@ -52,6 +53,7 @@ #include "snowball/libstemmer/stem_UTF_8_danish.h" #include "snowball/libstemmer/stem_UTF_8_dutch.h" #include "snowball/libstemmer/stem_UTF_8_english.h" +#include "snowball/libstemmer/stem_UTF_8_estonian.h" #include "snowball/libstemmer/stem_UTF_8_finnish.h" #include "snowball/libstemmer/stem_UTF_8_french.h" #include "snowball/libstemmer/stem_UTF_8_german.h" @@ -75,7 +77,10 @@ #include "snowball/libstemmer/stem_UTF_8_turkish.h" #include "snowball/libstemmer/stem_UTF_8_yiddish.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "dict_snowball", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(dsnowball_init); @@ -117,7 +122,6 @@ static const stemmer_module stemmer_modules[] = STEMMER_MODULE(spanish, PG_LATIN1, ISO_8859_1), STEMMER_MODULE(swedish, PG_LATIN1, ISO_8859_1), STEMMER_MODULE(hungarian, PG_LATIN2, ISO_8859_2), - STEMMER_MODULE(romanian, PG_LATIN2, ISO_8859_2), STEMMER_MODULE(russian, PG_KOI8R, KOI8_R), STEMMER_MODULE(arabic, PG_UTF8, UTF_8), STEMMER_MODULE(armenian, PG_UTF8, UTF_8), @@ -126,6 +130,7 @@ static const stemmer_module stemmer_modules[] = STEMMER_MODULE(danish, PG_UTF8, UTF_8), STEMMER_MODULE(dutch, PG_UTF8, UTF_8), STEMMER_MODULE(english, PG_UTF8, UTF_8), + STEMMER_MODULE(estonian, PG_UTF8, UTF_8), STEMMER_MODULE(finnish, PG_UTF8, UTF_8), STEMMER_MODULE(french, PG_UTF8, UTF_8), STEMMER_MODULE(german, PG_UTF8, UTF_8), @@ -236,7 +241,7 @@ dsnowball_init(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); - readstoplist(defGetString(defel), &d->stoplist, lowerstr); + readstoplist(defGetString(defel), &d->stoplist, str_tolower); stoploaded = true; } else if (strcmp(defel->defname, "language") == 0) @@ -272,7 +277,7 @@ dsnowball_lexize(PG_FUNCTION_ARGS) DictSnowball *d = (DictSnowball *) PG_GETARG_POINTER(0); char *in = (char *) PG_GETARG_POINTER(1); int32 len = PG_GETARG_INT32(2); - char *txt = lowerstr_with_len(in, len); + char *txt = str_tolower(in, len, DEFAULT_COLLATION_OID); TSLexeme *res = palloc0(sizeof(TSLexeme) * 2); /* diff --git a/src/backend/snowball/libstemmer/api.c b/src/backend/snowball/libstemmer/api.c index 375938e6d13fd..358f5633b28fe 100644 --- a/src/backend/snowball/libstemmer/api.c +++ b/src/backend/snowball/libstemmer/api.c @@ -34,7 +34,7 @@ extern struct SN_env * SN_create_env(int S_size, int I_size) extern void SN_close_env(struct SN_env * z, int S_size) { if (z == NULL) return; - if (S_size) + if (z->S) { int i; for (i = 0; i < S_size; i++) diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_basque.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_basque.c index 5089234ade4d3..ec2d4e7482ecc 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_basque.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_basque.c @@ -912,7 +912,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping(z, g_v, 97, 117, 0)) goto lab2; { int c3 = z->c; if (out_grouping(z, g_v, 97, 117, 0)) goto lab4; - { + + { int ret = out_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab4; z->c += ret; @@ -921,7 +922,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping(z, g_v, 97, 117, 0)) goto lab2; - { + + { int ret = in_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab2; z->c += ret; @@ -934,7 +936,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping(z, g_v, 97, 117, 0)) goto lab0; { int c4 = z->c; if (out_grouping(z, g_v, 97, 117, 0)) goto lab6; - { + + { int ret = out_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab6; z->c += ret; @@ -955,23 +958,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; @@ -984,18 +991,15 @@ static int r_mark_regions(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_aditzak(struct SN_env * z) { @@ -1003,7 +1007,7 @@ static int r_aditzak(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((70566434 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_0, 109); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1046,7 +1050,7 @@ static int r_izenak(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((71162402 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_1, 295); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1117,7 +1121,7 @@ static int r_adjetiboak(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((35362 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_2, 19); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1138,7 +1142,7 @@ static int r_adjetiboak(struct SN_env * z) { } extern int basque_ISO_8859_1_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_catalan.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_catalan.c index bdd3791541c7e..f2710534d6274 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_catalan.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_catalan.c @@ -1184,23 +1184,27 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; @@ -1218,7 +1222,6 @@ static int r_cleaning(struct SN_env * z) { int c1 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 13); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -1265,19 +1268,17 @@ static int r_cleaning(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1634850 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 39))) return 0; + if (!find_among_b(z, a_1, 39)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -1292,7 +1293,7 @@ static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_2, 200); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1343,7 +1344,7 @@ static int r_verb_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_3, 283); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1370,7 +1371,7 @@ static int r_residual_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_4, 22); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1394,7 +1395,7 @@ static int r_residual_suffix(struct SN_env * z) { } extern int catalan_ISO_8859_1_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_danish.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_danish.c index cb3df46b48904..372902d495c7b 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_danish.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_danish.c @@ -141,15 +141,17 @@ z->c = z->c + 3; z->I[0] = z->c; z->c = c_test1; } + if (out_grouping(z, g_v, 97, 248, 1) < 0) return 0; - { + + { int ret = in_grouping(z, g_v, 97, 248, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -164,7 +166,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851440 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 32); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -192,7 +194,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit2 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 116)) { z->lb = mlimit2; return 0; } - if (!(find_among_b(z, a_1, 4))) { z->lb = mlimit2; return 0; } + if (!find_among_b(z, a_1, 4)) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } @@ -227,7 +229,7 @@ static int r_other_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1572992 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit2; return 0; } among_var = find_among_b(z, a_2, 5); - if (!(among_var)) { z->lb = mlimit2; return 0; } + if (!among_var) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_dutch.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_dutch.c index efb8b60c7f69d..d2bc1baebef10 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_dutch.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_dutch.c @@ -152,7 +152,6 @@ static int r_prelude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || z->p[z->c + 0] >> 5 != 7 || !((340306450 >> (z->p[z->c + 0] & 0x1f)) & 1)) among_var = 6; else among_var = find_among(z, a_0, 11); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -244,34 +243,44 @@ static int r_prelude(struct SN_env * z) { } static int r_mark_regions(struct SN_env * z) { + z->I[2] = z->l; z->I[1] = z->l; - z->I[0] = z->l; - { + { int c_test1 = z->c; +z->c = z->c + 3; + if (z->c > z->l) return 0; + z->I[0] = z->c; + z->c = c_test1; + } + + { int ret = out_grouping(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - z->I[1] = z->c; - - if (!(z->I[1] < 3)) goto lab0; - z->I[1] = 3; + z->I[2] = z->c; + + if (z->I[2] >= z->I[0]) goto lab0; + z->I[2] = z->I[0]; lab0: - { + + { int ret = out_grouping(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - z->I[0] = z->c; + z->I[1] = z->c; return 1; } @@ -282,7 +291,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 89)) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -309,19 +317,17 @@ static int r_postlude(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_undouble(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1050640 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 3))) return 0; + if (!find_among_b(z, a_2, 3)) return 0; z->c = z->l - m_test1; } z->ket = z->c; @@ -335,7 +341,7 @@ static int r_undouble(struct SN_env * z) { } static int r_e_ending(struct SN_env * z) { - z->I[2] = 0; + z->I[3] = 0; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 'e') return 0; z->c--; @@ -350,7 +356,7 @@ static int r_e_ending(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - z->I[2] = 1; + z->I[3] = 1; { int ret = r_undouble(z); if (ret <= 0) return ret; } @@ -386,7 +392,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((540704 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab0; among_var = find_among_b(z, a_3, 5); - if (!(among_var)) goto lab0; + if (!among_var) goto lab0; z->bra = z->c; switch (among_var) { case 1: @@ -456,7 +462,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((264336 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; among_var = find_among_b(z, a_4, 6); - if (!(among_var)) goto lab3; + if (!among_var) goto lab3; z->bra = z->c; switch (among_var) { case 1: @@ -538,7 +544,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) goto lab3; if (ret < 0) return ret; } - if (!(z->I[2])) goto lab3; + if (!(z->I[3])) goto lab3; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -551,7 +557,7 @@ static int r_standard_suffix(struct SN_env * z) { if (out_grouping_b(z, g_v_I, 73, 232, 0)) goto lab8; { int m_test10 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((2129954 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab8; - if (!(find_among_b(z, a_5, 4))) goto lab8; + if (!find_among_b(z, a_5, 4)) goto lab8; if (out_grouping_b(z, g_v, 97, 232, 0)) goto lab8; z->c = z->l - m_test10; } @@ -583,7 +589,7 @@ extern int dutch_ISO_8859_1_stem(struct SN_env * z) { } z->lb = z->c; z->c = z->l; - + { int ret = r_standard_suffix(z); if (ret < 0) return ret; } @@ -597,7 +603,7 @@ extern int dutch_ISO_8859_1_stem(struct SN_env * z) { return 1; } -extern struct SN_env * dutch_ISO_8859_1_create_env(void) { return SN_create_env(0, 3); } +extern struct SN_env * dutch_ISO_8859_1_create_env(void) { return SN_create_env(0, 4); } extern void dutch_ISO_8859_1_close_env(struct SN_env * z) { SN_close_env(z, 0); } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_english.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_english.c index eac624ea272b9..ac36c163f9312 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_english.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_english.c @@ -310,6 +310,8 @@ static const struct among a_10[18] = { 4, s_10_17, -1, 8, 0} }; +static const unsigned char g_aeo[] = { 17, 64 }; + static const unsigned char g_v[] = { 17, 65, 16, 1 }; static const unsigned char g_v_WXY[] = { 1, 17, 65, 208, 1 }; @@ -418,16 +420,18 @@ static int r_mark_regions(struct SN_env * z) { { int c1 = z->c; { int c2 = z->c; if (z->c + 4 >= z->l || z->p[z->c + 4] >> 5 != 3 || !((2375680 >> (z->p[z->c + 4] & 0x1f)) & 1)) goto lab2; - if (!(find_among(z, a_0, 3))) goto lab2; + if (!find_among(z, a_0, 3)) goto lab2; goto lab1; lab2: z->c = c2; - { + + { int ret = out_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; @@ -435,12 +439,14 @@ static int r_mark_regions(struct SN_env * z) { } lab1: z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; @@ -469,13 +475,11 @@ static int r_shortv(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_Step_1a(struct SN_env * z) { @@ -483,7 +487,7 @@ static int r_Step_1a(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 39 && z->p[z->c - 1] != 115)) { z->c = z->l - m1; goto lab0; } - if (!(find_among_b(z, a_1, 3))) { z->c = z->l - m1; goto lab0; } + if (!find_among_b(z, a_1, 3)) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -494,7 +498,7 @@ static int r_Step_1a(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 115)) return 0; among_var = find_among_b(z, a_2, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -521,7 +525,8 @@ z->c = z->c - 2; case 3: if (z->c <= z->lb) return 0; z->c--; - { + + { int ret = out_grouping_b(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -539,7 +544,7 @@ static int r_Step_1b(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((33554576 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_4, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -552,7 +557,8 @@ static int r_Step_1b(struct SN_env * z) { break; case 2: { int m_test1 = z->l - z->c; - { + + { int ret = out_grouping_b(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -562,47 +568,49 @@ static int r_Step_1b(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } + z->ket = z->c; + z->bra = z->c; { int m_test2 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68514004 >> (z->p[z->c - 1] & 0x1f)) & 1)) among_var = 3; else among_var = find_among_b(z, a_3, 13); - if (!(among_var)) return 0; - z->c = z->l - m_test2; - } - switch (among_var) { - case 1: - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_6); - z->c = saved_c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 1, s_6); + if (ret < 0) return ret; } - if (ret < 0) return ret; - } - break; - case 2: - z->ket = z->c; - if (z->c <= z->lb) return 0; - z->c--; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 3: - if (z->c != z->I[1]) return 0; - { int m_test3 = z->l - z->c; - { int ret = r_shortv(z); - if (ret <= 0) return ret; + return 0; + break; + case 2: + { int m3 = z->l - z->c; (void)m3; + if (in_grouping_b(z, g_aeo, 97, 111, 0)) goto lab0; + if (z->c > z->lb) goto lab0; + return 0; + lab0: + z->c = z->l - m3; } - z->c = z->l - m_test3; - } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_7); - z->c = saved_c; + break; + case 3: + if (z->c != z->I[1]) return 0; + { int m_test4 = z->l - z->c; + { int ret = r_shortv(z); + if (ret <= 0) return ret; + } + z->c = z->l - m_test4; } - if (ret < 0) return ret; - } - break; + { int ret = slice_from_s(z, 1, s_7); + if (ret < 0) return ret; + } + return 0; + break; + } + z->c = z->l - m_test2; + } + z->ket = z->c; + if (z->c <= z->lb) return 0; + z->c--; + z->bra = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; } break; } @@ -623,7 +631,7 @@ static int r_Step_1c(struct SN_env * z) { lab0: z->bra = z->c; if (out_grouping_b(z, g_v, 97, 121, 0)) return 0; - + if (z->c > z->lb) goto lab2; return 0; lab2: @@ -638,7 +646,7 @@ static int r_Step_2(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((815616 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 24); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -731,7 +739,7 @@ static int r_Step_3(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((528928 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_6, 9); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -779,7 +787,7 @@ static int r_Step_4(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1864232 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_7, 18); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -814,30 +822,28 @@ static int r_Step_5(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 101 && z->p[z->c - 1] != 108)) return 0; among_var = find_among_b(z, a_8, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: + + { int ret = r_R2(z); + if (ret == 0) goto lab1; + if (ret < 0) return ret; + } + goto lab0; + lab1: + { int ret = r_R1(z); + if (ret <= 0) return ret; + } { int m1 = z->l - z->c; (void)m1; - { int ret = r_R2(z); - if (ret == 0) goto lab1; + { int ret = r_shortv(z); + if (ret == 0) goto lab2; if (ret < 0) return ret; } - goto lab0; - lab1: + return 0; + lab2: z->c = z->l - m1; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_shortv(z); - if (ret == 0) goto lab2; - if (ret < 0) return ret; - } - return 0; - lab2: - z->c = z->l - m2; - } } lab0: { int ret = slice_del(z); @@ -861,7 +867,7 @@ static int r_Step_5(struct SN_env * z) { static int r_exception2(struct SN_env * z) { z->ket = z->c; if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 103)) return 0; - if (!(find_among_b(z, a_9, 8))) return 0; + if (!find_among_b(z, a_9, 8)) return 0; z->bra = z->c; if (z->c > z->lb) return 0; return 1; @@ -872,7 +878,7 @@ static int r_exception1(struct SN_env * z) { z->bra = z->c; if (z->c + 2 >= z->l || z->p[z->c + 2] >> 5 != 3 || !((42750482 >> (z->p[z->c + 2] & 0x1f)) & 1)) return 0; among_var = find_among(z, a_10, 18); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; if (z->c < z->l) return 0; switch (among_var) { @@ -982,11 +988,11 @@ z->c = z->c + 3; goto lab0; lab2: z->c = c1; - + { int ret = r_prelude(z); if (ret < 0) return ret; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_finnish.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_finnish.c index 7835bd1fb2e6a..978ecb0227890 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_finnish.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_finnish.c @@ -277,15 +277,19 @@ static const symbol s_4[] = { 'p', 'o' }; static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; + if (out_grouping(z, g_V1, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping(z, g_V1, 97, 246, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; + if (out_grouping(z, g_V1, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping(z, g_V1, 97, 246, 1); if (ret < 0) return 0; z->c += ret; @@ -295,8 +299,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_particle_etc(struct SN_env * z) { @@ -307,7 +310,7 @@ static int r_particle_etc(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_0, 10); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -335,7 +338,7 @@ static int r_possessive(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_4, 9); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -370,21 +373,21 @@ static int r_possessive(struct SN_env * z) { break; case 4: if (z->c - 1 <= z->lb || z->p[z->c - 1] != 97) return 0; - if (!(find_among_b(z, a_1, 6))) return 0; + if (!find_among_b(z, a_1, 6)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 5: if (z->c - 1 <= z->lb || z->p[z->c - 1] != 228) return 0; - if (!(find_among_b(z, a_2, 6))) return 0; + if (!find_among_b(z, a_2, 6)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 6: if (z->c - 2 <= z->lb || z->p[z->c - 1] != 101) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -394,7 +397,7 @@ static int r_possessive(struct SN_env * z) { } static int r_LONG(struct SN_env * z) { - if (!(find_among_b(z, a_5, 7))) return 0; + if (!find_among_b(z, a_5, 7)) return 0; return 1; } @@ -413,7 +416,7 @@ static int r_case_ending(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_6, 30); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -485,7 +488,7 @@ static int r_other_endings(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[0]; z->ket = z->c; among_var = find_among_b(z, a_7, 14); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -512,7 +515,7 @@ static int r_i_plural(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 106)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_8, 2))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_8, 2)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -548,7 +551,7 @@ static int r_t_plural(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] != 97) { z->lb = mlimit3; return 0; } among_var = find_among_b(z, a_9, 2); - if (!(among_var)) { z->lb = mlimit3; return 0; } + if (!among_var) { z->lb = mlimit3; return 0; } z->bra = z->c; z->lb = mlimit3; } @@ -638,6 +641,7 @@ static int r_tidy(struct SN_env * z) { } z->lb = mlimit1; } + if (in_grouping_b(z, g_V1, 97, 246, 1) < 0) return 0; z->ket = z->c; if (in_grouping_b(z, g_C, 98, 122, 0)) return 0; @@ -685,7 +689,7 @@ extern int finnish_ISO_8859_1_stem(struct SN_env * z) { } z->c = z->l - m5; } - + if (!(z->I[2])) goto lab1; { int m6 = z->l - z->c; (void)m6; { int ret = r_i_plural(z); diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_french.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_french.c index 1951f0dbad5ca..5706a5296bb9b 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_french.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_french.c @@ -21,6 +21,7 @@ static int r_RV(struct SN_env * z); static int r_mark_regions(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_prelude(struct SN_env * z); +static int r_elisions(struct SN_env * z); #ifdef __cplusplus extern "C" { #endif @@ -371,43 +372,69 @@ static const struct among a_8[5] = static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 130, 103, 8, 5 }; +static const unsigned char g_elision_char[] = { 131, 14, 3 }; + static const unsigned char g_keep_with_s[] = { 1, 65, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 }; -static const symbol s_0[] = { 'U' }; -static const symbol s_1[] = { 'I' }; -static const symbol s_2[] = { 'Y' }; -static const symbol s_3[] = { 'H', 'e' }; -static const symbol s_4[] = { 'H', 'i' }; -static const symbol s_5[] = { 'Y' }; -static const symbol s_6[] = { 'U' }; -static const symbol s_7[] = { 'i' }; -static const symbol s_8[] = { 'u' }; -static const symbol s_9[] = { 'y' }; -static const symbol s_10[] = { 0xEB }; -static const symbol s_11[] = { 0xEF }; -static const symbol s_12[] = { 'i', 'c' }; -static const symbol s_13[] = { 'i', 'q', 'U' }; -static const symbol s_14[] = { 'l', 'o', 'g' }; -static const symbol s_15[] = { 'u' }; -static const symbol s_16[] = { 'e', 'n', 't' }; -static const symbol s_17[] = { 'a', 't' }; -static const symbol s_18[] = { 'e', 'u', 'x' }; -static const symbol s_19[] = { 'i' }; -static const symbol s_20[] = { 'a', 'b', 'l' }; -static const symbol s_21[] = { 'i', 'q', 'U' }; -static const symbol s_22[] = { 'a', 't' }; -static const symbol s_23[] = { 'i', 'c' }; -static const symbol s_24[] = { 'i', 'q', 'U' }; -static const symbol s_25[] = { 'e', 'a', 'u' }; -static const symbol s_26[] = { 'a', 'l' }; -static const symbol s_27[] = { 'e', 'u', 'x' }; -static const symbol s_28[] = { 'a', 'n', 't' }; -static const symbol s_29[] = { 'e', 'n', 't' }; -static const symbol s_30[] = { 'H', 'i' }; -static const symbol s_31[] = { 'i' }; -static const symbol s_32[] = { 'e' }; -static const symbol s_33[] = { 'i' }; -static const symbol s_34[] = { 'c' }; +static const symbol s_0[] = { 'q', 'u' }; +static const symbol s_1[] = { 'U' }; +static const symbol s_2[] = { 'I' }; +static const symbol s_3[] = { 'Y' }; +static const symbol s_4[] = { 'H', 'e' }; +static const symbol s_5[] = { 'H', 'i' }; +static const symbol s_6[] = { 'Y' }; +static const symbol s_7[] = { 'U' }; +static const symbol s_8[] = { 'i' }; +static const symbol s_9[] = { 'u' }; +static const symbol s_10[] = { 'y' }; +static const symbol s_11[] = { 0xEB }; +static const symbol s_12[] = { 0xEF }; +static const symbol s_13[] = { 'i', 'c' }; +static const symbol s_14[] = { 'i', 'q', 'U' }; +static const symbol s_15[] = { 'l', 'o', 'g' }; +static const symbol s_16[] = { 'u' }; +static const symbol s_17[] = { 'e', 'n', 't' }; +static const symbol s_18[] = { 'a', 't' }; +static const symbol s_19[] = { 'e', 'u', 'x' }; +static const symbol s_20[] = { 'i' }; +static const symbol s_21[] = { 'a', 'b', 'l' }; +static const symbol s_22[] = { 'i', 'q', 'U' }; +static const symbol s_23[] = { 'a', 't' }; +static const symbol s_24[] = { 'i', 'c' }; +static const symbol s_25[] = { 'i', 'q', 'U' }; +static const symbol s_26[] = { 'e', 'a', 'u' }; +static const symbol s_27[] = { 'a', 'l' }; +static const symbol s_28[] = { 'e', 'u', 'x' }; +static const symbol s_29[] = { 'a', 'n', 't' }; +static const symbol s_30[] = { 'e', 'n', 't' }; +static const symbol s_31[] = { 'H', 'i' }; +static const symbol s_32[] = { 'i' }; +static const symbol s_33[] = { 'e' }; +static const symbol s_34[] = { 'i' }; +static const symbol s_35[] = { 'c' }; + +static int r_elisions(struct SN_env * z) { + z->bra = z->c; + { int c1 = z->c; + if (in_grouping(z, g_elision_char, 99, 116, 0)) goto lab1; + goto lab0; + lab1: + z->c = c1; + if (!(eq_s(z, 2, s_0))) return 0; + } +lab0: + if (z->c == z->l || z->p[z->c] != '\'') return 0; + z->c++; + z->ket = z->c; + + if (z->c < z->l) goto lab2; + return 0; +lab2: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + return 1; +} static int r_prelude(struct SN_env * z) { while(1) { @@ -422,7 +449,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping(z, g_v, 97, 251, 0)) goto lab5; - { int ret = slice_from_s(z, 1, s_0); + { int ret = slice_from_s(z, 1, s_1); if (ret < 0) return ret; } goto lab4; @@ -432,7 +459,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping(z, g_v, 97, 251, 0)) goto lab6; - { int ret = slice_from_s(z, 1, s_1); + { int ret = slice_from_s(z, 1, s_2); if (ret < 0) return ret; } goto lab4; @@ -441,7 +468,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 'y') goto lab3; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 1, s_2); + { int ret = slice_from_s(z, 1, s_3); if (ret < 0) return ret; } } @@ -453,7 +480,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 0xEB) goto lab7; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 2, s_3); + { int ret = slice_from_s(z, 2, s_4); if (ret < 0) return ret; } goto lab2; @@ -463,7 +490,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 0xEF) goto lab8; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 2, s_4); + { int ret = slice_from_s(z, 2, s_5); if (ret < 0) return ret; } goto lab2; @@ -474,7 +501,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping(z, g_v, 97, 251, 0)) goto lab9; - { int ret = slice_from_s(z, 1, s_5); + { int ret = slice_from_s(z, 1, s_6); if (ret < 0) return ret; } goto lab2; @@ -486,7 +513,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 'u') goto lab1; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 1, s_6); + { int ret = slice_from_s(z, 1, s_7); if (ret < 0) return ret; } } @@ -520,13 +547,14 @@ static int r_mark_regions(struct SN_env * z) { lab2: z->c = c2; if (z->c + 2 >= z->l || z->p[z->c + 2] >> 5 != 3 || !((331776 >> (z->p[z->c + 2] & 0x1f)) & 1)) goto lab3; - if (!(find_among(z, a_0, 3))) goto lab3; + if (!find_among(z, a_0, 3)) goto lab3; goto lab1; lab3: z->c = c2; if (z->c >= z->l) goto lab0; z->c++; - { + + { int ret = out_grouping(z, g_v, 97, 251, 1); if (ret < 0) goto lab0; z->c += ret; @@ -538,23 +566,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c3 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; @@ -573,31 +605,30 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || z->p[z->c + 0] >> 5 != 2 || !((35652352 >> (z->p[z->c + 0] & 0x1f)) & 1)) among_var = 7; else among_var = find_among(z, a_1, 7); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: - { int ret = slice_from_s(z, 1, s_7); + { int ret = slice_from_s(z, 1, s_8); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 1, s_8); + { int ret = slice_from_s(z, 1, s_9); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 1, s_9); + { int ret = slice_from_s(z, 1, s_10); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 1, s_10); + { int ret = slice_from_s(z, 1, s_11); if (ret < 0) return ret; } break; case 5: - { int ret = slice_from_s(z, 1, s_11); + { int ret = slice_from_s(z, 1, s_12); if (ret < 0) return ret; } break; @@ -620,25 +651,22 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_4, 43); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -658,7 +686,7 @@ static int r_standard_suffix(struct SN_env * z) { } { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (!(eq_s_b(z, 2, s_12))) { z->c = z->l - m1; goto lab0; } + if (!(eq_s_b(z, 2, s_13))) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int m2 = z->l - z->c; (void)m2; { int ret = r_R2(z); @@ -671,7 +699,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab1; lab2: z->c = z->l - m2; - { int ret = slice_from_s(z, 3, s_13); + { int ret = slice_from_s(z, 3, s_14); if (ret < 0) return ret; } } @@ -684,7 +712,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_14); + { int ret = slice_from_s(z, 3, s_15); if (ret < 0) return ret; } break; @@ -692,7 +720,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 1, s_15); + { int ret = slice_from_s(z, 1, s_16); if (ret < 0) return ret; } break; @@ -700,7 +728,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_16); + { int ret = slice_from_s(z, 3, s_17); if (ret < 0) return ret; } break; @@ -714,7 +742,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; among_var = find_among_b(z, a_2, 6); - if (!(among_var)) { z->c = z->l - m3; goto lab3; } + if (!among_var) { z->c = z->l - m3; goto lab3; } z->bra = z->c; switch (among_var) { case 1: @@ -726,7 +754,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret < 0) return ret; } z->ket = z->c; - if (!(eq_s_b(z, 2, s_17))) { z->c = z->l - m3; goto lab3; } + if (!(eq_s_b(z, 2, s_18))) { z->c = z->l - m3; goto lab3; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab3; } @@ -752,7 +780,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) { z->c = z->l - m3; goto lab3; } if (ret < 0) return ret; } - { int ret = slice_from_s(z, 3, s_18); + { int ret = slice_from_s(z, 3, s_19); if (ret < 0) return ret; } } @@ -772,7 +800,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) { z->c = z->l - m3; goto lab3; } if (ret < 0) return ret; } - { int ret = slice_from_s(z, 1, s_19); + { int ret = slice_from_s(z, 1, s_20); if (ret < 0) return ret; } break; @@ -792,7 +820,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m5; goto lab6; } among_var = find_among_b(z, a_3, 3); - if (!(among_var)) { z->c = z->l - m5; goto lab6; } + if (!among_var) { z->c = z->l - m5; goto lab6; } z->bra = z->c; switch (among_var) { case 1: @@ -807,7 +835,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab7; lab8: z->c = z->l - m6; - { int ret = slice_from_s(z, 3, s_20); + { int ret = slice_from_s(z, 3, s_21); if (ret < 0) return ret; } } @@ -825,7 +853,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab9; lab10: z->c = z->l - m7; - { int ret = slice_from_s(z, 3, s_21); + { int ret = slice_from_s(z, 3, s_22); if (ret < 0) return ret; } } @@ -854,7 +882,7 @@ static int r_standard_suffix(struct SN_env * z) { } { int m8 = z->l - z->c; (void)m8; z->ket = z->c; - if (!(eq_s_b(z, 2, s_22))) { z->c = z->l - m8; goto lab11; } + if (!(eq_s_b(z, 2, s_23))) { z->c = z->l - m8; goto lab11; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m8; goto lab11; } @@ -864,7 +892,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret < 0) return ret; } z->ket = z->c; - if (!(eq_s_b(z, 2, s_23))) { z->c = z->l - m8; goto lab11; } + if (!(eq_s_b(z, 2, s_24))) { z->c = z->l - m8; goto lab11; } z->bra = z->c; { int m9 = z->l - z->c; (void)m9; { int ret = r_R2(z); @@ -877,7 +905,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab12; lab13: z->c = z->l - m9; - { int ret = slice_from_s(z, 3, s_24); + { int ret = slice_from_s(z, 3, s_25); if (ret < 0) return ret; } } @@ -887,7 +915,7 @@ static int r_standard_suffix(struct SN_env * z) { } break; case 9: - { int ret = slice_from_s(z, 3, s_25); + { int ret = slice_from_s(z, 3, s_26); if (ret < 0) return ret; } break; @@ -895,7 +923,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R1(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 2, s_26); + { int ret = slice_from_s(z, 2, s_27); if (ret < 0) return ret; } break; @@ -914,7 +942,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R1(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_27); + { int ret = slice_from_s(z, 3, s_28); if (ret < 0) return ret; } } @@ -933,7 +961,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_RV(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_28); + { int ret = slice_from_s(z, 3, s_29); if (ret < 0) return ret; } return 0; @@ -942,7 +970,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_RV(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_29); + { int ret = slice_from_s(z, 3, s_30); if (ret < 0) return ret; } return 0; @@ -971,7 +999,7 @@ static int r_i_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68944418 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_5, 35))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_5, 35)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int m2 = z->l - z->c; (void)m2; if (z->c <= z->lb || z->p[z->c - 1] != 'H') goto lab0; @@ -997,7 +1025,7 @@ static int r_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; among_var = find_among_b(z, a_6, 38); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; switch (among_var) { case 1: @@ -1045,7 +1073,7 @@ static int r_residual_suffix(struct SN_env * z) { z->bra = z->c; { int m_test2 = z->l - z->c; { int m3 = z->l - z->c; (void)m3; - if (!(eq_s_b(z, 2, s_30))) goto lab2; + if (!(eq_s_b(z, 2, s_31))) goto lab2; goto lab1; lab2: z->c = z->l - m3; @@ -1067,7 +1095,7 @@ static int r_residual_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((278560 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit4; return 0; } among_var = find_among_b(z, a_7, 6); - if (!(among_var)) { z->lb = mlimit4; return 0; } + if (!among_var) { z->lb = mlimit4; return 0; } z->bra = z->c; switch (among_var) { case 1: @@ -1090,7 +1118,7 @@ static int r_residual_suffix(struct SN_env * z) { } break; case 2: - { int ret = slice_from_s(z, 1, s_31); + { int ret = slice_from_s(z, 1, s_32); if (ret < 0) return ret; } break; @@ -1108,7 +1136,7 @@ static int r_residual_suffix(struct SN_env * z) { static int r_un_double(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1069056 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_8, 5))) return 0; + if (!find_among_b(z, a_8, 5)) return 0; z->c = z->l - m_test1; } z->ket = z->c; @@ -1144,7 +1172,7 @@ static int r_un_accent(struct SN_env * z) { } lab1: z->bra = z->c; - { int ret = slice_from_s(z, 1, s_32); + { int ret = slice_from_s(z, 1, s_33); if (ret < 0) return ret; } return 1; @@ -1152,58 +1180,64 @@ static int r_un_accent(struct SN_env * z) { extern int french_ISO_8859_1_stem(struct SN_env * z) { { int c1 = z->c; - { int ret = r_prelude(z); + { int ret = r_elisions(z); if (ret < 0) return ret; } z->c = c1; } - + { int c2 = z->c; + { int ret = r_prelude(z); + if (ret < 0) return ret; + } + z->c = c2; + } + { int ret = r_mark_regions(z); if (ret < 0) return ret; } z->lb = z->c; z->c = z->l; - { int m2 = z->l - z->c; (void)m2; - { int m3 = z->l - z->c; (void)m3; - { int m4 = z->l - z->c; (void)m4; - { int m5 = z->l - z->c; (void)m5; + { int m3 = z->l - z->c; (void)m3; + { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; + { int m6 = z->l - z->c; (void)m6; { int ret = r_standard_suffix(z); if (ret == 0) goto lab4; if (ret < 0) return ret; } goto lab3; lab4: - z->c = z->l - m5; + z->c = z->l - m6; { int ret = r_i_verb_suffix(z); if (ret == 0) goto lab5; if (ret < 0) return ret; } goto lab3; lab5: - z->c = z->l - m5; + z->c = z->l - m6; { int ret = r_verb_suffix(z); if (ret == 0) goto lab2; if (ret < 0) return ret; } } lab3: - z->c = z->l - m4; - { int m6 = z->l - z->c; (void)m6; + z->c = z->l - m5; + { int m7 = z->l - z->c; (void)m7; z->ket = z->c; - { int m7 = z->l - z->c; (void)m7; + { int m8 = z->l - z->c; (void)m8; if (z->c <= z->lb || z->p[z->c - 1] != 'Y') goto lab8; z->c--; z->bra = z->c; - { int ret = slice_from_s(z, 1, s_33); + { int ret = slice_from_s(z, 1, s_34); if (ret < 0) return ret; } goto lab7; lab8: - z->c = z->l - m7; - if (z->c <= z->lb || z->p[z->c - 1] != 0xE7) { z->c = z->l - m6; goto lab6; } + z->c = z->l - m8; + if (z->c <= z->lb || z->p[z->c - 1] != 0xE7) { z->c = z->l - m7; goto lab6; } z->c--; z->bra = z->c; - { int ret = slice_from_s(z, 1, s_34); + { int ret = slice_from_s(z, 1, s_35); if (ret < 0) return ret; } } @@ -1214,7 +1248,7 @@ extern int french_ISO_8859_1_stem(struct SN_env * z) { } goto lab1; lab2: - z->c = z->l - m3; + z->c = z->l - m4; { int ret = r_residual_suffix(z); if (ret == 0) goto lab0; if (ret < 0) return ret; @@ -1222,26 +1256,26 @@ extern int french_ISO_8859_1_stem(struct SN_env * z) { } lab1: lab0: - z->c = z->l - m2; + z->c = z->l - m3; } - { int m8 = z->l - z->c; (void)m8; + { int m9 = z->l - z->c; (void)m9; { int ret = r_un_double(z); if (ret < 0) return ret; } - z->c = z->l - m8; + z->c = z->l - m9; } - { int m9 = z->l - z->c; (void)m9; + { int m10 = z->l - z->c; (void)m10; { int ret = r_un_accent(z); if (ret < 0) return ret; } - z->c = z->l - m9; + z->c = z->l - m10; } z->c = z->lb; - { int c10 = z->c; + { int c11 = z->c; { int ret = r_postlude(z); if (ret < 0) return ret; } - z->c = c10; + z->c = c11; } return 1; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_german.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_german.c index c5cbd6fe547e3..c053b201d5503 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_german.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_german.c @@ -27,82 +27,106 @@ extern void german_ISO_8859_1_close_env(struct SN_env * z); #ifdef __cplusplus } #endif -static const symbol s_0_1[1] = { 'U' }; -static const symbol s_0_2[1] = { 'Y' }; -static const symbol s_0_3[1] = { 0xE4 }; -static const symbol s_0_4[1] = { 0xF6 }; -static const symbol s_0_5[1] = { 0xFC }; +static const symbol s_0_1[2] = { 'a', 'e' }; +static const symbol s_0_2[2] = { 'o', 'e' }; +static const symbol s_0_3[2] = { 'q', 'u' }; +static const symbol s_0_4[2] = { 'u', 'e' }; +static const symbol s_0_5[1] = { 0xDF }; static const struct among a_0[6] = { { 0, 0, -1, 5, 0}, -{ 1, s_0_1, 0, 2, 0}, -{ 1, s_0_2, 0, 1, 0}, -{ 1, s_0_3, 0, 3, 0}, -{ 1, s_0_4, 0, 4, 0}, -{ 1, s_0_5, 0, 2, 0} +{ 2, s_0_1, 0, 2, 0}, +{ 2, s_0_2, 0, 3, 0}, +{ 2, s_0_3, 0, -1, 0}, +{ 2, s_0_4, 0, 4, 0}, +{ 1, s_0_5, 0, 1, 0} }; -static const symbol s_1_0[1] = { 'e' }; -static const symbol s_1_1[2] = { 'e', 'm' }; -static const symbol s_1_2[2] = { 'e', 'n' }; -static const symbol s_1_3[3] = { 'e', 'r', 'n' }; -static const symbol s_1_4[2] = { 'e', 'r' }; -static const symbol s_1_5[1] = { 's' }; -static const symbol s_1_6[2] = { 'e', 's' }; +static const symbol s_1_1[1] = { 'U' }; +static const symbol s_1_2[1] = { 'Y' }; +static const symbol s_1_3[1] = { 0xE4 }; +static const symbol s_1_4[1] = { 0xF6 }; +static const symbol s_1_5[1] = { 0xFC }; -static const struct among a_1[7] = +static const struct among a_1[6] = { -{ 1, s_1_0, -1, 2, 0}, -{ 2, s_1_1, -1, 1, 0}, -{ 2, s_1_2, -1, 2, 0}, -{ 3, s_1_3, -1, 1, 0}, -{ 2, s_1_4, -1, 1, 0}, -{ 1, s_1_5, -1, 3, 0}, -{ 2, s_1_6, 5, 2, 0} +{ 0, 0, -1, 5, 0}, +{ 1, s_1_1, 0, 2, 0}, +{ 1, s_1_2, 0, 1, 0}, +{ 1, s_1_3, 0, 3, 0}, +{ 1, s_1_4, 0, 4, 0}, +{ 1, s_1_5, 0, 2, 0} }; -static const symbol s_2_0[2] = { 'e', 'n' }; -static const symbol s_2_1[2] = { 'e', 'r' }; -static const symbol s_2_2[2] = { 's', 't' }; -static const symbol s_2_3[3] = { 'e', 's', 't' }; +static const symbol s_2_0[1] = { 'e' }; +static const symbol s_2_1[2] = { 'e', 'm' }; +static const symbol s_2_2[2] = { 'e', 'n' }; +static const symbol s_2_3[7] = { 'e', 'r', 'i', 'n', 'n', 'e', 'n' }; +static const symbol s_2_4[4] = { 'e', 'r', 'i', 'n' }; +static const symbol s_2_5[2] = { 'l', 'n' }; +static const symbol s_2_6[3] = { 'e', 'r', 'n' }; +static const symbol s_2_7[2] = { 'e', 'r' }; +static const symbol s_2_8[1] = { 's' }; +static const symbol s_2_9[2] = { 'e', 's' }; +static const symbol s_2_10[3] = { 'l', 'n', 's' }; -static const struct among a_2[4] = +static const struct among a_2[11] = { -{ 2, s_2_0, -1, 1, 0}, +{ 1, s_2_0, -1, 3, 0}, { 2, s_2_1, -1, 1, 0}, -{ 2, s_2_2, -1, 2, 0}, -{ 3, s_2_3, 2, 1, 0} +{ 2, s_2_2, -1, 3, 0}, +{ 7, s_2_3, 2, 2, 0}, +{ 4, s_2_4, -1, 2, 0}, +{ 2, s_2_5, -1, 5, 0}, +{ 3, s_2_6, -1, 2, 0}, +{ 2, s_2_7, -1, 2, 0}, +{ 1, s_2_8, -1, 4, 0}, +{ 2, s_2_9, 8, 3, 0}, +{ 3, s_2_10, 8, 5, 0} }; -static const symbol s_3_0[2] = { 'i', 'g' }; -static const symbol s_3_1[4] = { 'l', 'i', 'c', 'h' }; +static const symbol s_3_0[2] = { 'e', 'n' }; +static const symbol s_3_1[2] = { 'e', 'r' }; +static const symbol s_3_2[2] = { 's', 't' }; +static const symbol s_3_3[3] = { 'e', 's', 't' }; -static const struct among a_3[2] = +static const struct among a_3[4] = { { 2, s_3_0, -1, 1, 0}, -{ 4, s_3_1, -1, 1, 0} +{ 2, s_3_1, -1, 1, 0}, +{ 2, s_3_2, -1, 2, 0}, +{ 3, s_3_3, 2, 1, 0} +}; + +static const symbol s_4_0[2] = { 'i', 'g' }; +static const symbol s_4_1[4] = { 'l', 'i', 'c', 'h' }; + +static const struct among a_4[2] = +{ +{ 2, s_4_0, -1, 1, 0}, +{ 4, s_4_1, -1, 1, 0} }; -static const symbol s_4_0[3] = { 'e', 'n', 'd' }; -static const symbol s_4_1[2] = { 'i', 'g' }; -static const symbol s_4_2[3] = { 'u', 'n', 'g' }; -static const symbol s_4_3[4] = { 'l', 'i', 'c', 'h' }; -static const symbol s_4_4[4] = { 'i', 's', 'c', 'h' }; -static const symbol s_4_5[2] = { 'i', 'k' }; -static const symbol s_4_6[4] = { 'h', 'e', 'i', 't' }; -static const symbol s_4_7[4] = { 'k', 'e', 'i', 't' }; +static const symbol s_5_0[3] = { 'e', 'n', 'd' }; +static const symbol s_5_1[2] = { 'i', 'g' }; +static const symbol s_5_2[3] = { 'u', 'n', 'g' }; +static const symbol s_5_3[4] = { 'l', 'i', 'c', 'h' }; +static const symbol s_5_4[4] = { 'i', 's', 'c', 'h' }; +static const symbol s_5_5[2] = { 'i', 'k' }; +static const symbol s_5_6[4] = { 'h', 'e', 'i', 't' }; +static const symbol s_5_7[4] = { 'k', 'e', 'i', 't' }; -static const struct among a_4[8] = +static const struct among a_5[8] = { -{ 3, s_4_0, -1, 1, 0}, -{ 2, s_4_1, -1, 2, 0}, -{ 3, s_4_2, -1, 1, 0}, -{ 4, s_4_3, -1, 3, 0}, -{ 4, s_4_4, -1, 2, 0}, -{ 2, s_4_5, -1, 2, 0}, -{ 4, s_4_6, -1, 3, 0}, -{ 4, s_4_7, -1, 4, 0} +{ 3, s_5_0, -1, 1, 0}, +{ 2, s_5_1, -1, 2, 0}, +{ 3, s_5_2, -1, 1, 0}, +{ 4, s_5_3, -1, 3, 0}, +{ 4, s_5_4, -1, 2, 0}, +{ 2, s_5_5, -1, 2, 0}, +{ 4, s_5_6, -1, 3, 0}, +{ 4, s_5_7, -1, 4, 0} }; static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 32, 8 }; @@ -111,37 +135,59 @@ static const unsigned char g_s_ending[] = { 117, 30, 5 }; static const unsigned char g_st_ending[] = { 117, 30, 4 }; -static const symbol s_0[] = { 's', 's' }; -static const symbol s_1[] = { 'U' }; -static const symbol s_2[] = { 'Y' }; -static const symbol s_3[] = { 'y' }; -static const symbol s_4[] = { 'u' }; -static const symbol s_5[] = { 'a' }; -static const symbol s_6[] = { 'o' }; -static const symbol s_7[] = { 'n', 'i', 's' }; -static const symbol s_8[] = { 'i', 'g' }; -static const symbol s_9[] = { 'e', 'r' }; -static const symbol s_10[] = { 'e', 'n' }; +static const symbol s_0[] = { 'U' }; +static const symbol s_1[] = { 'Y' }; +static const symbol s_2[] = { 's', 's' }; +static const symbol s_3[] = { 0xE4 }; +static const symbol s_4[] = { 0xF6 }; +static const symbol s_5[] = { 0xFC }; +static const symbol s_6[] = { 'y' }; +static const symbol s_7[] = { 'u' }; +static const symbol s_8[] = { 'a' }; +static const symbol s_9[] = { 'o' }; +static const symbol s_10[] = { 's', 'y', 's', 't' }; +static const symbol s_11[] = { 'n', 'i', 's' }; +static const symbol s_12[] = { 'l' }; +static const symbol s_13[] = { 'i', 'g' }; +static const symbol s_14[] = { 'e', 'r' }; +static const symbol s_15[] = { 'e', 'n' }; static int r_prelude(struct SN_env * z) { + int among_var; { int c_test1 = z->c; while(1) { int c2 = z->c; - { int c3 = z->c; + while(1) { + int c3 = z->c; + if (in_grouping(z, g_v, 97, 252, 0)) goto lab1; z->bra = z->c; - if (z->c == z->l || z->p[z->c] != 0xDF) goto lab2; - z->c++; - z->ket = z->c; - { int ret = slice_from_s(z, 2, s_0); - if (ret < 0) return ret; + { int c4 = z->c; + if (z->c == z->l || z->p[z->c] != 'u') goto lab3; + z->c++; + z->ket = z->c; + if (in_grouping(z, g_v, 97, 252, 0)) goto lab3; + { int ret = slice_from_s(z, 1, s_0); + if (ret < 0) return ret; + } + goto lab2; + lab3: + z->c = c4; + if (z->c == z->l || z->p[z->c] != 'y') goto lab1; + z->c++; + z->ket = z->c; + if (in_grouping(z, g_v, 97, 252, 0)) goto lab1; + { int ret = slice_from_s(z, 1, s_1); + if (ret < 0) return ret; + } } - goto lab1; lab2: + z->c = c3; + break; + lab1: z->c = c3; if (z->c >= z->l) goto lab0; z->c++; } - lab1: continue; lab0: z->c = c2; @@ -150,41 +196,39 @@ static int r_prelude(struct SN_env * z) { z->c = c_test1; } while(1) { - int c4 = z->c; - while(1) { - int c5 = z->c; - if (in_grouping(z, g_v, 97, 252, 0)) goto lab4; - z->bra = z->c; - { int c6 = z->c; - if (z->c == z->l || z->p[z->c] != 'u') goto lab6; - z->c++; - z->ket = z->c; - if (in_grouping(z, g_v, 97, 252, 0)) goto lab6; - { int ret = slice_from_s(z, 1, s_1); + int c5 = z->c; + z->bra = z->c; + among_var = find_among(z, a_0, 6); + z->ket = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 2, s_2); if (ret < 0) return ret; } - goto lab5; - lab6: - z->c = c6; - if (z->c == z->l || z->p[z->c] != 'y') goto lab4; - z->c++; - z->ket = z->c; - if (in_grouping(z, g_v, 97, 252, 0)) goto lab4; - { int ret = slice_from_s(z, 1, s_2); + break; + case 2: + { int ret = slice_from_s(z, 1, s_3); if (ret < 0) return ret; } - } - lab5: - z->c = c5; - break; - lab4: - z->c = c5; - if (z->c >= z->l) goto lab3; - z->c++; + break; + case 3: + { int ret = slice_from_s(z, 1, s_4); + if (ret < 0) return ret; + } + break; + case 4: + { int ret = slice_from_s(z, 1, s_5); + if (ret < 0) return ret; + } + break; + case 5: + if (z->c >= z->l) goto lab4; + z->c++; + break; } continue; - lab3: - z->c = c4; + lab4: + z->c = c5; break; } return 1; @@ -199,27 +243,31 @@ z->c = z->c + 3; z->I[0] = z->c; z->c = c_test1; } - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } z->I[2] = z->c; - - if (!(z->I[2] < z->I[0])) goto lab0; + + if (z->I[2] >= z->I[0]) goto lab0; z->I[2] = z->I[0]; lab0: - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; @@ -233,27 +281,26 @@ static int r_postlude(struct SN_env * z) { while(1) { int c1 = z->c; z->bra = z->c; - among_var = find_among(z, a_0, 6); - if (!(among_var)) goto lab0; + among_var = find_among(z, a_1, 6); z->ket = z->c; switch (among_var) { case 1: - { int ret = slice_from_s(z, 1, s_3); + { int ret = slice_from_s(z, 1, s_6); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 1, s_4); + { int ret = slice_from_s(z, 1, s_7); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 1, s_5); + { int ret = slice_from_s(z, 1, s_8); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 1, s_6); + { int ret = slice_from_s(z, 1, s_9); if (ret < 0) return ret; } break; @@ -271,13 +318,11 @@ static int r_postlude(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_standard_suffix(struct SN_env * z) { @@ -285,8 +330,8 @@ static int r_standard_suffix(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((811040 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab0; - among_var = find_among_b(z, a_1, 7); - if (!(among_var)) goto lab0; + among_var = find_among_b(z, a_2, 11); + if (!among_var) goto lab0; z->bra = z->c; { int ret = r_R1(z); if (ret == 0) goto lab0; @@ -294,6 +339,12 @@ static int r_standard_suffix(struct SN_env * z) { } switch (among_var) { case 1: + { int m2 = z->l - z->c; (void)m2; + if (!(eq_s_b(z, 4, s_10))) goto lab1; + goto lab0; + lab1: + z->c = z->l - m2; + } { int ret = slice_del(z); if (ret < 0) return ret; } @@ -302,37 +353,47 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - { int m2 = z->l - z->c; (void)m2; + break; + case 3: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + { int m3 = z->l - z->c; (void)m3; z->ket = z->c; - if (z->c <= z->lb || z->p[z->c - 1] != 's') { z->c = z->l - m2; goto lab1; } + if (z->c <= z->lb || z->p[z->c - 1] != 's') { z->c = z->l - m3; goto lab2; } z->c--; z->bra = z->c; - if (!(eq_s_b(z, 3, s_7))) { z->c = z->l - m2; goto lab1; } + if (!(eq_s_b(z, 3, s_11))) { z->c = z->l - m3; goto lab2; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab1: + lab2: ; } break; - case 3: + case 4: if (in_grouping_b(z, g_s_ending, 98, 116, 0)) goto lab0; { int ret = slice_del(z); if (ret < 0) return ret; } break; + case 5: + { int ret = slice_from_s(z, 1, s_12); + if (ret < 0) return ret; + } + break; } lab0: z->c = z->l - m1; } - { int m3 = z->l - z->c; (void)m3; + { int m4 = z->l - z->c; (void)m4; z->ket = z->c; - if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1327104 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab2; - among_var = find_among_b(z, a_2, 4); - if (!(among_var)) goto lab2; + if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1327104 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; + among_var = find_among_b(z, a_3, 4); + if (!among_var) goto lab3; z->bra = z->c; { int ret = r_R1(z); - if (ret == 0) goto lab2; + if (ret == 0) goto lab3; if (ret < 0) return ret; } switch (among_var) { @@ -342,25 +403,25 @@ static int r_standard_suffix(struct SN_env * z) { } break; case 2: - if (in_grouping_b(z, g_st_ending, 98, 116, 0)) goto lab2; + if (in_grouping_b(z, g_st_ending, 98, 116, 0)) goto lab3; z->c = z->c - 3; - if (z->c < z->lb) goto lab2; + if (z->c < z->lb) goto lab3; { int ret = slice_del(z); if (ret < 0) return ret; } break; } - lab2: - z->c = z->l - m3; + lab3: + z->c = z->l - m4; } - { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; z->ket = z->c; - if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1051024 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; - among_var = find_among_b(z, a_4, 8); - if (!(among_var)) goto lab3; + if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1051024 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab4; + among_var = find_among_b(z, a_5, 8); + if (!among_var) goto lab4; z->bra = z->c; { int ret = r_R2(z); - if (ret == 0) goto lab3; + if (ret == 0) goto lab4; if (ret < 0) return ret; } switch (among_var) { @@ -368,35 +429,35 @@ z->c = z->c - 3; { int ret = slice_del(z); if (ret < 0) return ret; } - { int m5 = z->l - z->c; (void)m5; + { int m6 = z->l - z->c; (void)m6; z->ket = z->c; - if (!(eq_s_b(z, 2, s_8))) { z->c = z->l - m5; goto lab4; } + if (!(eq_s_b(z, 2, s_13))) { z->c = z->l - m6; goto lab5; } z->bra = z->c; - { int m6 = z->l - z->c; (void)m6; - if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab5; + { int m7 = z->l - z->c; (void)m7; + if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab6; z->c--; - { z->c = z->l - m5; goto lab4; } - lab5: - z->c = z->l - m6; + { z->c = z->l - m6; goto lab5; } + lab6: + z->c = z->l - m7; } { int ret = r_R2(z); - if (ret == 0) { z->c = z->l - m5; goto lab4; } + if (ret == 0) { z->c = z->l - m6; goto lab5; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab4: + lab5: ; } break; case 2: - { int m7 = z->l - z->c; (void)m7; - if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab6; + { int m8 = z->l - z->c; (void)m8; + if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab7; z->c--; - goto lab3; - lab6: - z->c = z->l - m7; + goto lab4; + lab7: + z->c = z->l - m8; } { int ret = slice_del(z); if (ret < 0) return ret; @@ -406,25 +467,25 @@ z->c = z->c - 3; { int ret = slice_del(z); if (ret < 0) return ret; } - { int m8 = z->l - z->c; (void)m8; + { int m9 = z->l - z->c; (void)m9; z->ket = z->c; - { int m9 = z->l - z->c; (void)m9; - if (!(eq_s_b(z, 2, s_9))) goto lab9; - goto lab8; - lab9: - z->c = z->l - m9; - if (!(eq_s_b(z, 2, s_10))) { z->c = z->l - m8; goto lab7; } + { int m10 = z->l - z->c; (void)m10; + if (!(eq_s_b(z, 2, s_14))) goto lab10; + goto lab9; + lab10: + z->c = z->l - m10; + if (!(eq_s_b(z, 2, s_15))) { z->c = z->l - m9; goto lab8; } } - lab8: + lab9: z->bra = z->c; { int ret = r_R1(z); - if (ret == 0) { z->c = z->l - m8; goto lab7; } + if (ret == 0) { z->c = z->l - m9; goto lab8; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab7: + lab8: ; } break; @@ -432,25 +493,25 @@ z->c = z->c - 3; { int ret = slice_del(z); if (ret < 0) return ret; } - { int m10 = z->l - z->c; (void)m10; + { int m11 = z->l - z->c; (void)m11; z->ket = z->c; - if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 103 && z->p[z->c - 1] != 104)) { z->c = z->l - m10; goto lab10; } - if (!(find_among_b(z, a_3, 2))) { z->c = z->l - m10; goto lab10; } + if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 103 && z->p[z->c - 1] != 104)) { z->c = z->l - m11; goto lab11; } + if (!find_among_b(z, a_4, 2)) { z->c = z->l - m11; goto lab11; } z->bra = z->c; { int ret = r_R2(z); - if (ret == 0) { z->c = z->l - m10; goto lab10; } + if (ret == 0) { z->c = z->l - m11; goto lab11; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab10: + lab11: ; } break; } - lab3: - z->c = z->l - m4; + lab4: + z->c = z->l - m5; } return 1; } @@ -470,7 +531,7 @@ extern int german_ISO_8859_1_stem(struct SN_env * z) { } z->lb = z->c; z->c = z->l; - + { int ret = r_standard_suffix(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_indonesian.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_indonesian.c index f653ee4d7bb68..8624d0382ebde 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_indonesian.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_indonesian.c @@ -123,7 +123,7 @@ static const symbol s_6[] = { 'a', 'j', 'a', 'r' }; static int r_remove_particle(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 104 && z->p[z->c - 1] != 110)) return 0; - if (!(find_among_b(z, a_0, 3))) return 0; + if (!find_among_b(z, a_0, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -135,7 +135,7 @@ static int r_remove_particle(struct SN_env * z) { static int r_remove_possessive_pronoun(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 117)) return 0; - if (!(find_among_b(z, a_1, 3))) return 0; + if (!find_among_b(z, a_1, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -145,19 +145,18 @@ static int r_remove_possessive_pronoun(struct SN_env * z) { } static int r_SUFFIX_KAN_OK(struct SN_env * z) { - - if (!(z->I[0] != 3)) return 0; - if (!(z->I[0] != 2)) return 0; + + if (z->I[0] == 3) return 0; + if (z->I[0] == 2) return 0; return 1; } static int r_SUFFIX_AN_OK(struct SN_env * z) { - if (!(z->I[0] != 1)) return 0; - return 1; + return z->I[0] != 1; } static int r_SUFFIX_I_OK(struct SN_env * z) { - if (!(z->I[0] <= 2)) return 0; + if (z->I[0] > 2) return 0; { int m1 = z->l - z->c; (void)m1; if (z->c <= z->lb || z->p[z->c - 1] != 's') goto lab0; z->c--; @@ -171,7 +170,7 @@ static int r_SUFFIX_I_OK(struct SN_env * z) { static int r_remove_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 110)) return 0; - if (!(find_among_b(z, a_2, 3))) return 0; + if (!find_among_b(z, a_2, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -196,7 +195,7 @@ static int r_remove_first_order_prefix(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || (z->p[z->c + 1] != 105 && z->p[z->c + 1] != 101)) return 0; among_var = find_among(z, a_3, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -276,7 +275,7 @@ static int r_remove_second_order_prefix(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] != 101) return 0; among_var = find_among(z, a_4, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -315,7 +314,8 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { { int c1 = z->c; while(1) { int c2 = z->c; - { + + { int ret = out_grouping(z, g_vowel, 97, 117, 1); if (ret < 0) goto lab1; z->c += ret; @@ -328,7 +328,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { } z->c = c1; } - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; z->I[0] = 0; z->lb = z->c; z->c = z->l; @@ -338,7 +338,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { } z->c = z->l - m3; } - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; { int m4 = z->l - z->c; (void)m4; { int ret = r_remove_possessive_pronoun(z); if (ret < 0) return ret; @@ -346,7 +346,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { z->c = z->l - m4; } z->c = z->lb; - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; { int c5 = z->c; { int c_test6 = z->c; { int ret = r_remove_first_order_prefix(z); @@ -355,7 +355,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { } { int c7 = z->c; { int c_test8 = z->c; - if (!(z->I[1] > 2)) goto lab4; + if (z->I[1] <= 2) goto lab4; z->lb = z->c; z->c = z->l; { int ret = r_remove_suffix(z); @@ -365,7 +365,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { z->c = z->lb; z->c = c_test8; } - if (!(z->I[1] > 2)) goto lab4; + if (z->I[1] <= 2) goto lab4; { int ret = r_remove_second_order_prefix(z); if (ret == 0) goto lab4; if (ret < 0) return ret; @@ -385,7 +385,7 @@ extern int indonesian_ISO_8859_1_stem(struct SN_env * z) { z->c = c9; } { int c10 = z->c; - if (!(z->I[1] > 2)) goto lab5; + if (z->I[1] <= 2) goto lab5; z->lb = z->c; z->c = z->l; { int ret = r_remove_suffix(z); diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_irish.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_irish.c index c93d3216eb242..a61591eab3f95 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_irish.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_irish.c @@ -225,24 +225,28 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[2] = z->c; - { + + { int ret = in_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; @@ -258,7 +262,7 @@ static int r_initial_morph(struct SN_env * z) { int among_var; z->bra = z->c; among_var = find_among(z, a_0, 24); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -316,25 +320,22 @@ static int r_initial_morph(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_noun_sfx(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_1, 16); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -361,7 +362,7 @@ static int r_deriv(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_2, 25); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -406,7 +407,7 @@ static int r_verb_sfx(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((282896 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_3, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -436,7 +437,7 @@ extern int irish_ISO_8859_1_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_italian.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_italian.c index 7e9f6504876c4..122449e90a9a1 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_italian.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_italian.c @@ -19,6 +19,7 @@ static int r_RV(struct SN_env * z); static int r_mark_regions(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_prelude(struct SN_env * z); +static int r_exceptions(struct SN_env * z); #ifdef __cplusplus extern "C" { #endif @@ -487,6 +488,8 @@ static const symbol s_14[] = { 'e', 'n', 't', 'e' }; static const symbol s_15[] = { 'a', 't' }; static const symbol s_16[] = { 'a', 't' }; static const symbol s_17[] = { 'i', 'c' }; +static const symbol s_18[] = { 'd', 'i', 'v', 'a', 'n', 'o' }; +static const symbol s_19[] = { 'd', 'i', 'v', 'a', 'n' }; static int r_prelude(struct SN_env * z) { int among_var; @@ -495,7 +498,6 @@ static int r_prelude(struct SN_env * z) { int c2 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 7); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -590,7 +592,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping(z, g_v, 97, 249, 0)) goto lab2; { int c3 = z->c; if (out_grouping(z, g_v, 97, 249, 0)) goto lab4; - { + + { int ret = out_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab4; z->c += ret; @@ -599,7 +602,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping(z, g_v, 97, 249, 0)) goto lab2; - { + + { int ret = in_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab2; z->c += ret; @@ -612,7 +616,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping(z, g_v, 97, 249, 0)) goto lab0; { int c4 = z->c; if (out_grouping(z, g_v, 97, 249, 0)) goto lab6; - { + + { int ret = out_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab6; z->c += ret; @@ -633,23 +638,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; @@ -668,7 +677,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 85)) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -695,29 +703,26 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { int among_var; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((33314 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 37))) return 0; + if (!find_among_b(z, a_2, 37)) return 0; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 111 && z->p[z->c - 1] != 114)) return 0; among_var = find_among_b(z, a_3, 5); - if (!(among_var)) return 0; + if (!among_var) return 0; { int ret = r_RV(z); if (ret <= 0) return ret; } @@ -740,7 +745,7 @@ static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_6, 51); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -816,7 +821,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4722696 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m2; goto lab1; } among_var = find_among_b(z, a_4, 4); - if (!(among_var)) { z->c = z->l - m2; goto lab1; } + if (!among_var) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -853,7 +858,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_5, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_5, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -908,7 +913,7 @@ static int r_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_7, 87))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_7, 87)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -963,56 +968,77 @@ static int r_vowel_suffix(struct SN_env * z) { return 1; } +static int r_exceptions(struct SN_env * z) { + z->bra = z->c; + if (!(eq_s(z, 6, s_18))) return 0; + if (z->c < z->l) return 0; + z->ket = z->c; + { int ret = slice_from_s(z, 5, s_19); + if (ret < 0) return ret; + } + return 1; +} + extern int italian_ISO_8859_1_stem(struct SN_env * z) { { int c1 = z->c; - { int ret = r_prelude(z); + { int ret = r_exceptions(z); + if (ret == 0) goto lab1; if (ret < 0) return ret; } + goto lab0; + lab1: z->c = c1; - } - - { int ret = r_mark_regions(z); - if (ret < 0) return ret; - } - z->lb = z->c; z->c = z->l; + { int c2 = z->c; + { int ret = r_prelude(z); + if (ret < 0) return ret; + } + z->c = c2; + } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_attached_pronoun(z); + { int ret = r_mark_regions(z); if (ret < 0) return ret; } - z->c = z->l - m2; - } - { int m3 = z->l - z->c; (void)m3; - { int m4 = z->l - z->c; (void)m4; - { int ret = r_standard_suffix(z); - if (ret == 0) goto lab2; + z->lb = z->c; z->c = z->l; + + { int m3 = z->l - z->c; (void)m3; + { int ret = r_attached_pronoun(z); if (ret < 0) return ret; } - goto lab1; + z->c = z->l - m3; + } + { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; + { int ret = r_standard_suffix(z); + if (ret == 0) goto lab4; + if (ret < 0) return ret; + } + goto lab3; + lab4: + z->c = z->l - m5; + { int ret = r_verb_suffix(z); + if (ret == 0) goto lab2; + if (ret < 0) return ret; + } + } + lab3: lab2: z->c = z->l - m4; - { int ret = r_verb_suffix(z); - if (ret == 0) goto lab0; + } + { int m6 = z->l - z->c; (void)m6; + { int ret = r_vowel_suffix(z); if (ret < 0) return ret; } + z->c = z->l - m6; } - lab1: - lab0: - z->c = z->l - m3; - } - { int m5 = z->l - z->c; (void)m5; - { int ret = r_vowel_suffix(z); - if (ret < 0) return ret; - } - z->c = z->l - m5; - } - z->c = z->lb; - { int c6 = z->c; - { int ret = r_postlude(z); - if (ret < 0) return ret; + z->c = z->lb; + { int c7 = z->c; + { int ret = r_postlude(z); + if (ret < 0) return ret; + } + z->c = c7; } - z->c = c6; } +lab0: return 1; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_norwegian.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_norwegian.c index 820029004bb28..c10c0d761f1f5 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_norwegian.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_norwegian.c @@ -138,15 +138,17 @@ z->c = z->c + 3; z->I[0] = z->c; z->c = c_test1; } + if (out_grouping(z, g_v, 97, 248, 1) < 0) return 0; - { + + { int ret = in_grouping(z, g_v, 97, 248, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -161,7 +163,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851426 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 29); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -203,7 +205,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit2 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 116) { z->lb = mlimit2; return 0; } - if (!(find_among_b(z, a_1, 2))) { z->lb = mlimit2; return 0; } + if (!find_among_b(z, a_1, 2)) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } @@ -225,7 +227,7 @@ static int r_other_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718720 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_2, 11))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_2, 11)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_porter.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_porter.c index a782ce399687f..b8be0a26e4f0a 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_porter.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_porter.c @@ -230,13 +230,11 @@ static int r_shortv(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_Step_1a(struct SN_env * z) { @@ -244,7 +242,7 @@ static int r_Step_1a(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 115) return 0; among_var = find_among_b(z, a_0, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -271,7 +269,7 @@ static int r_Step_1b(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 103)) return 0; among_var = find_among_b(z, a_2, 3); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -284,7 +282,8 @@ static int r_Step_1b(struct SN_env * z) { break; case 2: { int m_test1 = z->l - z->c; - { + + { int ret = out_grouping_b(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -297,7 +296,6 @@ static int r_Step_1b(struct SN_env * z) { { int m_test2 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68514004 >> (z->p[z->c - 1] & 0x1f)) & 1)) among_var = 3; else among_var = find_among_b(z, a_1, 13); - if (!(among_var)) return 0; z->c = z->l - m_test2; } switch (among_var) { @@ -354,7 +352,8 @@ static int r_Step_1c(struct SN_env * z) { } lab0: z->bra = z->c; - { + + { int ret = out_grouping_b(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -370,7 +369,7 @@ static int r_Step_2(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((815616 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_3, 20); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -450,7 +449,7 @@ static int r_Step_3(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((528928 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_4, 7); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -480,7 +479,7 @@ static int r_Step_4(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((3961384 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 19); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -515,26 +514,24 @@ static int r_Step_5a(struct SN_env * z) { if (z->c <= z->lb || z->p[z->c - 1] != 'e') return 0; z->c--; z->bra = z->c; + + { int ret = r_R2(z); + if (ret == 0) goto lab1; + if (ret < 0) return ret; + } + goto lab0; +lab1: + { int ret = r_R1(z); + if (ret <= 0) return ret; + } { int m1 = z->l - z->c; (void)m1; - { int ret = r_R2(z); - if (ret == 0) goto lab1; + { int ret = r_shortv(z); + if (ret == 0) goto lab2; if (ret < 0) return ret; } - goto lab0; - lab1: + return 0; + lab2: z->c = z->l - m1; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_shortv(z); - if (ret == 0) goto lab2; - if (ret < 0) return ret; - } - return 0; - lab2: - z->c = z->l - m2; - } } lab0: { int ret = slice_del(z); @@ -604,23 +601,27 @@ extern int porter_ISO_8859_1_stem(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c5 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_portuguese.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_portuguese.c index c27db66e1efe7..33aae89f7322b 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_portuguese.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_portuguese.c @@ -479,7 +479,6 @@ static int r_prelude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 227 && z->p[z->c + 0] != 245)) among_var = 3; else among_var = find_among(z, a_0, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -514,7 +513,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping(z, g_v, 97, 250, 0)) goto lab2; { int c3 = z->c; if (out_grouping(z, g_v, 97, 250, 0)) goto lab4; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab4; z->c += ret; @@ -523,7 +523,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping(z, g_v, 97, 250, 0)) goto lab2; - { + + { int ret = in_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab2; z->c += ret; @@ -536,7 +537,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping(z, g_v, 97, 250, 0)) goto lab0; { int c4 = z->c; if (out_grouping(z, g_v, 97, 250, 0)) goto lab6; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab6; z->c += ret; @@ -557,23 +559,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; @@ -592,7 +598,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] != 126) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -619,18 +624,15 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_standard_suffix(struct SN_env * z) { @@ -638,7 +640,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((823330 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 45); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -684,7 +686,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718616 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m1; goto lab0; } among_var = find_among_b(z, a_2, 4); - if (!(among_var)) { z->c = z->l - m1; goto lab0; } + if (!among_var) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m1; goto lab0; } @@ -721,7 +723,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m2 = z->l - z->c; (void)m2; z->ket = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 101 && z->p[z->c - 1] != 108)) { z->c = z->l - m2; goto lab1; } - if (!(find_among_b(z, a_3, 3))) { z->c = z->l - m2; goto lab1; } + if (!find_among_b(z, a_3, 3)) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -744,7 +746,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_4, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_4, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -799,7 +801,7 @@ static int r_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_6, 120))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_6, 120)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -811,7 +813,7 @@ static int r_verb_suffix(struct SN_env * z) { static int r_residual_suffix(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_7, 7))) return 0; + if (!find_among_b(z, a_7, 7)) return 0; z->bra = z->c; { int ret = r_RV(z); if (ret <= 0) return ret; @@ -826,7 +828,7 @@ static int r_residual_form(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_8, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -882,7 +884,7 @@ extern int portuguese_ISO_8859_1_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_spanish.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_spanish.c index 9fb6d3b660aa8..252bb28cd3c43 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_spanish.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_spanish.c @@ -512,7 +512,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping(z, g_v, 97, 252, 0)) goto lab2; { int c3 = z->c; if (out_grouping(z, g_v, 97, 252, 0)) goto lab4; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab4; z->c += ret; @@ -521,7 +522,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping(z, g_v, 97, 252, 0)) goto lab2; - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab2; z->c += ret; @@ -534,7 +536,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping(z, g_v, 97, 252, 0)) goto lab0; { int c4 = z->c; if (out_grouping(z, g_v, 97, 252, 0)) goto lab6; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab6; z->c += ret; @@ -555,23 +558,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; @@ -590,7 +597,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || z->p[z->c + 0] >> 5 != 7 || !((67641858 >> (z->p[z->c + 0] & 0x1f)) & 1)) among_var = 6; else among_var = find_among(z, a_0, 6); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -632,29 +638,26 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { int among_var; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((557090 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 13))) return 0; + if (!find_among_b(z, a_1, 13)) return 0; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 111 && z->p[z->c - 1] != 114)) return 0; among_var = find_among_b(z, a_2, 11); - if (!(among_var)) return 0; + if (!among_var) return 0; { int ret = r_RV(z); if (ret <= 0) return ret; } @@ -710,7 +713,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((835634 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_6, 46); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -778,7 +781,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718616 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m2; goto lab1; } among_var = find_among_b(z, a_3, 4); - if (!(among_var)) { z->c = z->l - m2; goto lab1; } + if (!among_var) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -815,7 +818,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 101) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_4, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_4, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -838,7 +841,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m4 = z->l - z->c; (void)m4; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m4; goto lab3; } - if (!(find_among_b(z, a_5, 3))) { z->c = z->l - m4; goto lab3; } + if (!find_among_b(z, a_5, 3)) { z->c = z->l - m4; goto lab3; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m4; goto lab3; } @@ -883,7 +886,7 @@ static int r_y_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_7, 12))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_7, 12)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -903,7 +906,7 @@ static int r_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; among_var = find_among_b(z, a_8, 96); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -938,7 +941,7 @@ static int r_residual_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_9, 8); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -982,7 +985,7 @@ static int r_residual_suffix(struct SN_env * z) { } extern int spanish_ISO_8859_1_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_1_swedish.c b/src/backend/snowball/libstemmer/stem_ISO_8859_1_swedish.c index 27b710c175bff..6cf715d14c4d7 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_1_swedish.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_1_swedish.c @@ -127,7 +127,7 @@ static const symbol s_2_0[2] = { 'i', 'g' }; static const symbol s_2_1[3] = { 'l', 'i', 'g' }; static const symbol s_2_2[3] = { 'e', 'l', 's' }; static const symbol s_2_3[5] = { 'f', 'u', 'l', 'l', 't' }; -static const symbol s_2_4[4] = { 'l', 0xF6, 's', 't' }; +static const symbol s_2_4[3] = { 0xF6, 's', 't' }; static const struct among a_2[5] = { @@ -135,14 +135,16 @@ static const struct among a_2[5] = { 3, s_2_1, 0, 1, 0}, { 3, s_2_2, -1, 1, 0}, { 5, s_2_3, -1, 3, 0}, -{ 4, s_2_4, -1, 2, 0} +{ 3, s_2_4, -1, 2, 0} }; static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 32 }; static const unsigned char g_s_ending[] = { 119, 127, 149 }; -static const symbol s_0[] = { 'l', 0xF6, 's' }; +static const unsigned char g_ost_ending[] = { 173, 58 }; + +static const symbol s_0[] = { 0xF6, 's' }; static const symbol s_1[] = { 'f', 'u', 'l', 'l' }; static int r_mark_regions(struct SN_env * z) { @@ -153,15 +155,17 @@ z->c = z->c + 3; z->I[0] = z->c; z->c = c_test1; } + if (out_grouping(z, g_v, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping(z, g_v, 97, 246, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -176,7 +180,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851442 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 37); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -203,7 +207,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; { int m2 = z->l - z->c; (void)m2; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1064976 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_1, 7))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_1, 7)) { z->lb = mlimit1; return 0; } z->c = z->l - m2; z->ket = z->c; if (z->c <= z->lb) { z->lb = mlimit1; return 0; } @@ -227,27 +231,28 @@ static int r_other_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1572992 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_2, 5); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; - switch (among_var) { - case 1: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 3, s_0); - if (ret < 0) return ret; - } - break; - case 3: - { int ret = slice_from_s(z, 4, s_1); - if (ret < 0) return ret; - } - break; - } z->lb = mlimit1; } + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + if (in_grouping_b(z, g_ost_ending, 105, 118, 0)) return 0; + { int ret = slice_from_s(z, 2, s_0); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 4, s_1); + if (ret < 0) return ret; + } + break; + } return 1; } diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_2_hungarian.c b/src/backend/snowball/libstemmer/stem_ISO_8859_2_hungarian.c index 4650bd17ea359..7308963105d3f 100644 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_2_hungarian.c +++ b/src/backend/snowball/libstemmer/stem_ISO_8859_2_hungarian.c @@ -480,10 +480,11 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->l; { int c1 = z->c; if (in_grouping(z, g_v, 97, 252, 0)) goto lab1; + if (in_grouping(z, g_v, 97, 252, 1) < 0) goto lab1; { int c2 = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 3 || !((101187584 >> (z->p[z->c + 1] & 0x1f)) & 1)) goto lab3; - if (!(find_among(z, a_0, 8))) goto lab3; + if (!find_among(z, a_0, 8)) goto lab3; goto lab2; lab3: z->c = c2; @@ -496,7 +497,8 @@ static int r_mark_regions(struct SN_env * z) { lab1: z->c = c1; if (out_grouping(z, g_v, 97, 252, 0)) return 0; - { + + { int ret = out_grouping(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; @@ -508,8 +510,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_v_ending(struct SN_env * z) { @@ -517,7 +518,7 @@ static int r_v_ending(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 225 && z->p[z->c - 1] != 233)) return 0; among_var = find_among_b(z, a_1, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -540,7 +541,7 @@ static int r_v_ending(struct SN_env * z) { static int r_double(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((106790108 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 23))) return 0; + if (!find_among_b(z, a_2, 23)) return 0; z->c = z->l - m_test1; } return 1; @@ -562,7 +563,7 @@ z->c = z->c - 1; static int r_instrum(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 108) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -581,7 +582,7 @@ static int r_instrum(struct SN_env * z) { static int r_case(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_4, 44))) return 0; + if (!find_among_b(z, a_4, 44)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -600,7 +601,7 @@ static int r_case_special(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 110 && z->p[z->c - 1] != 116)) return 0; among_var = find_among_b(z, a_5, 3); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -625,7 +626,7 @@ static int r_case_other(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 108) return 0; among_var = find_among_b(z, a_6, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -653,7 +654,7 @@ static int r_case_other(struct SN_env * z) { static int r_factive(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 225 && z->p[z->c - 1] != 233)) return 0; - if (!(find_among_b(z, a_7, 2))) return 0; + if (!find_among_b(z, a_7, 2)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -675,7 +676,7 @@ static int r_plural(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 107) return 0; among_var = find_among_b(z, a_8, 7); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -705,7 +706,7 @@ static int r_owned(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 233)) return 0; among_var = find_among_b(z, a_9, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -734,7 +735,7 @@ static int r_sing_owner(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_10, 31); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -764,7 +765,7 @@ static int r_plur_owner(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((10768 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_11, 42); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; diff --git a/src/backend/snowball/libstemmer/stem_ISO_8859_2_romanian.c b/src/backend/snowball/libstemmer/stem_ISO_8859_2_romanian.c deleted file mode 100644 index 0f3eb2c333fb0..0000000000000 --- a/src/backend/snowball/libstemmer/stem_ISO_8859_2_romanian.c +++ /dev/null @@ -1,965 +0,0 @@ -/* Generated by Snowball 2.2.0 - https://snowballstem.org/ */ - -#include "header.h" - -#ifdef __cplusplus -extern "C" { -#endif -extern int romanian_ISO_8859_2_stem(struct SN_env * z); -#ifdef __cplusplus -} -#endif -static int r_vowel_suffix(struct SN_env * z); -static int r_verb_suffix(struct SN_env * z); -static int r_combo_suffix(struct SN_env * z); -static int r_standard_suffix(struct SN_env * z); -static int r_step_0(struct SN_env * z); -static int r_R2(struct SN_env * z); -static int r_R1(struct SN_env * z); -static int r_RV(struct SN_env * z); -static int r_mark_regions(struct SN_env * z); -static int r_postlude(struct SN_env * z); -static int r_prelude(struct SN_env * z); -#ifdef __cplusplus -extern "C" { -#endif - - -extern struct SN_env * romanian_ISO_8859_2_create_env(void); -extern void romanian_ISO_8859_2_close_env(struct SN_env * z); - - -#ifdef __cplusplus -} -#endif -static const symbol s_0_1[1] = { 'I' }; -static const symbol s_0_2[1] = { 'U' }; - -static const struct among a_0[3] = -{ -{ 0, 0, -1, 3, 0}, -{ 1, s_0_1, 0, 1, 0}, -{ 1, s_0_2, 0, 2, 0} -}; - -static const symbol s_1_0[2] = { 'e', 'a' }; -static const symbol s_1_1[4] = { 'a', 0xFE, 'i', 'a' }; -static const symbol s_1_2[3] = { 'a', 'u', 'a' }; -static const symbol s_1_3[3] = { 'i', 'u', 'a' }; -static const symbol s_1_4[4] = { 'a', 0xFE, 'i', 'e' }; -static const symbol s_1_5[3] = { 'e', 'l', 'e' }; -static const symbol s_1_6[3] = { 'i', 'l', 'e' }; -static const symbol s_1_7[4] = { 'i', 'i', 'l', 'e' }; -static const symbol s_1_8[3] = { 'i', 'e', 'i' }; -static const symbol s_1_9[4] = { 'a', 't', 'e', 'i' }; -static const symbol s_1_10[2] = { 'i', 'i' }; -static const symbol s_1_11[4] = { 'u', 'l', 'u', 'i' }; -static const symbol s_1_12[2] = { 'u', 'l' }; -static const symbol s_1_13[4] = { 'e', 'l', 'o', 'r' }; -static const symbol s_1_14[4] = { 'i', 'l', 'o', 'r' }; -static const symbol s_1_15[5] = { 'i', 'i', 'l', 'o', 'r' }; - -static const struct among a_1[16] = -{ -{ 2, s_1_0, -1, 3, 0}, -{ 4, s_1_1, -1, 7, 0}, -{ 3, s_1_2, -1, 2, 0}, -{ 3, s_1_3, -1, 4, 0}, -{ 4, s_1_4, -1, 7, 0}, -{ 3, s_1_5, -1, 3, 0}, -{ 3, s_1_6, -1, 5, 0}, -{ 4, s_1_7, 6, 4, 0}, -{ 3, s_1_8, -1, 4, 0}, -{ 4, s_1_9, -1, 6, 0}, -{ 2, s_1_10, -1, 4, 0}, -{ 4, s_1_11, -1, 1, 0}, -{ 2, s_1_12, -1, 1, 0}, -{ 4, s_1_13, -1, 3, 0}, -{ 4, s_1_14, -1, 4, 0}, -{ 5, s_1_15, 14, 4, 0} -}; - -static const symbol s_2_0[5] = { 'i', 'c', 'a', 'l', 'a' }; -static const symbol s_2_1[5] = { 'i', 'c', 'i', 'v', 'a' }; -static const symbol s_2_2[5] = { 'a', 't', 'i', 'v', 'a' }; -static const symbol s_2_3[5] = { 'i', 't', 'i', 'v', 'a' }; -static const symbol s_2_4[5] = { 'i', 'c', 'a', 'l', 'e' }; -static const symbol s_2_5[6] = { 'a', 0xFE, 'i', 'u', 'n', 'e' }; -static const symbol s_2_6[6] = { 'i', 0xFE, 'i', 'u', 'n', 'e' }; -static const symbol s_2_7[6] = { 'a', 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_8[6] = { 'i', 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_9[6] = { 0xE3, 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_10[7] = { 'i', 'c', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_11[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_12[9] = { 'i', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_13[7] = { 'i', 'v', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_14[5] = { 'i', 'c', 'i', 'v', 'e' }; -static const symbol s_2_15[5] = { 'a', 't', 'i', 'v', 'e' }; -static const symbol s_2_16[5] = { 'i', 't', 'i', 'v', 'e' }; -static const symbol s_2_17[5] = { 'i', 'c', 'a', 'l', 'i' }; -static const symbol s_2_18[5] = { 'a', 't', 'o', 'r', 'i' }; -static const symbol s_2_19[7] = { 'i', 'c', 'a', 't', 'o', 'r', 'i' }; -static const symbol s_2_20[5] = { 'i', 't', 'o', 'r', 'i' }; -static const symbol s_2_21[5] = { 0xE3, 't', 'o', 'r', 'i' }; -static const symbol s_2_22[7] = { 'i', 'c', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_23[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_24[7] = { 'i', 'v', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_25[5] = { 'i', 'c', 'i', 'v', 'i' }; -static const symbol s_2_26[5] = { 'a', 't', 'i', 'v', 'i' }; -static const symbol s_2_27[5] = { 'i', 't', 'i', 'v', 'i' }; -static const symbol s_2_28[6] = { 'i', 'c', 'i', 't', 0xE3, 'i' }; -static const symbol s_2_29[8] = { 'a', 'b', 'i', 'l', 'i', 't', 0xE3, 'i' }; -static const symbol s_2_30[6] = { 'i', 'v', 'i', 't', 0xE3, 'i' }; -static const symbol s_2_31[7] = { 'i', 'c', 'i', 't', 0xE3, 0xFE, 'i' }; -static const symbol s_2_32[9] = { 'a', 'b', 'i', 'l', 'i', 't', 0xE3, 0xFE, 'i' }; -static const symbol s_2_33[7] = { 'i', 'v', 'i', 't', 0xE3, 0xFE, 'i' }; -static const symbol s_2_34[4] = { 'i', 'c', 'a', 'l' }; -static const symbol s_2_35[4] = { 'a', 't', 'o', 'r' }; -static const symbol s_2_36[6] = { 'i', 'c', 'a', 't', 'o', 'r' }; -static const symbol s_2_37[4] = { 'i', 't', 'o', 'r' }; -static const symbol s_2_38[4] = { 0xE3, 't', 'o', 'r' }; -static const symbol s_2_39[4] = { 'i', 'c', 'i', 'v' }; -static const symbol s_2_40[4] = { 'a', 't', 'i', 'v' }; -static const symbol s_2_41[4] = { 'i', 't', 'i', 'v' }; -static const symbol s_2_42[5] = { 'i', 'c', 'a', 'l', 0xE3 }; -static const symbol s_2_43[5] = { 'i', 'c', 'i', 'v', 0xE3 }; -static const symbol s_2_44[5] = { 'a', 't', 'i', 'v', 0xE3 }; -static const symbol s_2_45[5] = { 'i', 't', 'i', 'v', 0xE3 }; - -static const struct among a_2[46] = -{ -{ 5, s_2_0, -1, 4, 0}, -{ 5, s_2_1, -1, 4, 0}, -{ 5, s_2_2, -1, 5, 0}, -{ 5, s_2_3, -1, 6, 0}, -{ 5, s_2_4, -1, 4, 0}, -{ 6, s_2_5, -1, 5, 0}, -{ 6, s_2_6, -1, 6, 0}, -{ 6, s_2_7, -1, 5, 0}, -{ 6, s_2_8, -1, 6, 0}, -{ 6, s_2_9, -1, 5, 0}, -{ 7, s_2_10, -1, 4, 0}, -{ 9, s_2_11, -1, 1, 0}, -{ 9, s_2_12, -1, 2, 0}, -{ 7, s_2_13, -1, 3, 0}, -{ 5, s_2_14, -1, 4, 0}, -{ 5, s_2_15, -1, 5, 0}, -{ 5, s_2_16, -1, 6, 0}, -{ 5, s_2_17, -1, 4, 0}, -{ 5, s_2_18, -1, 5, 0}, -{ 7, s_2_19, 18, 4, 0}, -{ 5, s_2_20, -1, 6, 0}, -{ 5, s_2_21, -1, 5, 0}, -{ 7, s_2_22, -1, 4, 0}, -{ 9, s_2_23, -1, 1, 0}, -{ 7, s_2_24, -1, 3, 0}, -{ 5, s_2_25, -1, 4, 0}, -{ 5, s_2_26, -1, 5, 0}, -{ 5, s_2_27, -1, 6, 0}, -{ 6, s_2_28, -1, 4, 0}, -{ 8, s_2_29, -1, 1, 0}, -{ 6, s_2_30, -1, 3, 0}, -{ 7, s_2_31, -1, 4, 0}, -{ 9, s_2_32, -1, 1, 0}, -{ 7, s_2_33, -1, 3, 0}, -{ 4, s_2_34, -1, 4, 0}, -{ 4, s_2_35, -1, 5, 0}, -{ 6, s_2_36, 35, 4, 0}, -{ 4, s_2_37, -1, 6, 0}, -{ 4, s_2_38, -1, 5, 0}, -{ 4, s_2_39, -1, 4, 0}, -{ 4, s_2_40, -1, 5, 0}, -{ 4, s_2_41, -1, 6, 0}, -{ 5, s_2_42, -1, 4, 0}, -{ 5, s_2_43, -1, 4, 0}, -{ 5, s_2_44, -1, 5, 0}, -{ 5, s_2_45, -1, 6, 0} -}; - -static const symbol s_3_0[3] = { 'i', 'c', 'a' }; -static const symbol s_3_1[5] = { 'a', 'b', 'i', 'l', 'a' }; -static const symbol s_3_2[5] = { 'i', 'b', 'i', 'l', 'a' }; -static const symbol s_3_3[4] = { 'o', 'a', 's', 'a' }; -static const symbol s_3_4[3] = { 'a', 't', 'a' }; -static const symbol s_3_5[3] = { 'i', 't', 'a' }; -static const symbol s_3_6[4] = { 'a', 'n', 't', 'a' }; -static const symbol s_3_7[4] = { 'i', 's', 't', 'a' }; -static const symbol s_3_8[3] = { 'u', 't', 'a' }; -static const symbol s_3_9[3] = { 'i', 'v', 'a' }; -static const symbol s_3_10[2] = { 'i', 'c' }; -static const symbol s_3_11[3] = { 'i', 'c', 'e' }; -static const symbol s_3_12[5] = { 'a', 'b', 'i', 'l', 'e' }; -static const symbol s_3_13[5] = { 'i', 'b', 'i', 'l', 'e' }; -static const symbol s_3_14[4] = { 'i', 's', 'm', 'e' }; -static const symbol s_3_15[4] = { 'i', 'u', 'n', 'e' }; -static const symbol s_3_16[4] = { 'o', 'a', 's', 'e' }; -static const symbol s_3_17[3] = { 'a', 't', 'e' }; -static const symbol s_3_18[5] = { 'i', 't', 'a', 't', 'e' }; -static const symbol s_3_19[3] = { 'i', 't', 'e' }; -static const symbol s_3_20[4] = { 'a', 'n', 't', 'e' }; -static const symbol s_3_21[4] = { 'i', 's', 't', 'e' }; -static const symbol s_3_22[3] = { 'u', 't', 'e' }; -static const symbol s_3_23[3] = { 'i', 'v', 'e' }; -static const symbol s_3_24[3] = { 'i', 'c', 'i' }; -static const symbol s_3_25[5] = { 'a', 'b', 'i', 'l', 'i' }; -static const symbol s_3_26[5] = { 'i', 'b', 'i', 'l', 'i' }; -static const symbol s_3_27[4] = { 'i', 'u', 'n', 'i' }; -static const symbol s_3_28[5] = { 'a', 't', 'o', 'r', 'i' }; -static const symbol s_3_29[3] = { 'o', 's', 'i' }; -static const symbol s_3_30[3] = { 'a', 't', 'i' }; -static const symbol s_3_31[5] = { 'i', 't', 'a', 't', 'i' }; -static const symbol s_3_32[3] = { 'i', 't', 'i' }; -static const symbol s_3_33[4] = { 'a', 'n', 't', 'i' }; -static const symbol s_3_34[4] = { 'i', 's', 't', 'i' }; -static const symbol s_3_35[3] = { 'u', 't', 'i' }; -static const symbol s_3_36[4] = { 'i', 0xBA, 't', 'i' }; -static const symbol s_3_37[3] = { 'i', 'v', 'i' }; -static const symbol s_3_38[3] = { 'o', 0xBA, 'i' }; -static const symbol s_3_39[4] = { 'i', 't', 0xE3, 'i' }; -static const symbol s_3_40[5] = { 'i', 't', 0xE3, 0xFE, 'i' }; -static const symbol s_3_41[4] = { 'a', 'b', 'i', 'l' }; -static const symbol s_3_42[4] = { 'i', 'b', 'i', 'l' }; -static const symbol s_3_43[3] = { 'i', 's', 'm' }; -static const symbol s_3_44[4] = { 'a', 't', 'o', 'r' }; -static const symbol s_3_45[2] = { 'o', 's' }; -static const symbol s_3_46[2] = { 'a', 't' }; -static const symbol s_3_47[2] = { 'i', 't' }; -static const symbol s_3_48[3] = { 'a', 'n', 't' }; -static const symbol s_3_49[3] = { 'i', 's', 't' }; -static const symbol s_3_50[2] = { 'u', 't' }; -static const symbol s_3_51[2] = { 'i', 'v' }; -static const symbol s_3_52[3] = { 'i', 'c', 0xE3 }; -static const symbol s_3_53[5] = { 'a', 'b', 'i', 'l', 0xE3 }; -static const symbol s_3_54[5] = { 'i', 'b', 'i', 'l', 0xE3 }; -static const symbol s_3_55[4] = { 'o', 'a', 's', 0xE3 }; -static const symbol s_3_56[3] = { 'a', 't', 0xE3 }; -static const symbol s_3_57[3] = { 'i', 't', 0xE3 }; -static const symbol s_3_58[4] = { 'a', 'n', 't', 0xE3 }; -static const symbol s_3_59[4] = { 'i', 's', 't', 0xE3 }; -static const symbol s_3_60[3] = { 'u', 't', 0xE3 }; -static const symbol s_3_61[3] = { 'i', 'v', 0xE3 }; - -static const struct among a_3[62] = -{ -{ 3, s_3_0, -1, 1, 0}, -{ 5, s_3_1, -1, 1, 0}, -{ 5, s_3_2, -1, 1, 0}, -{ 4, s_3_3, -1, 1, 0}, -{ 3, s_3_4, -1, 1, 0}, -{ 3, s_3_5, -1, 1, 0}, -{ 4, s_3_6, -1, 1, 0}, -{ 4, s_3_7, -1, 3, 0}, -{ 3, s_3_8, -1, 1, 0}, -{ 3, s_3_9, -1, 1, 0}, -{ 2, s_3_10, -1, 1, 0}, -{ 3, s_3_11, -1, 1, 0}, -{ 5, s_3_12, -1, 1, 0}, -{ 5, s_3_13, -1, 1, 0}, -{ 4, s_3_14, -1, 3, 0}, -{ 4, s_3_15, -1, 2, 0}, -{ 4, s_3_16, -1, 1, 0}, -{ 3, s_3_17, -1, 1, 0}, -{ 5, s_3_18, 17, 1, 0}, -{ 3, s_3_19, -1, 1, 0}, -{ 4, s_3_20, -1, 1, 0}, -{ 4, s_3_21, -1, 3, 0}, -{ 3, s_3_22, -1, 1, 0}, -{ 3, s_3_23, -1, 1, 0}, -{ 3, s_3_24, -1, 1, 0}, -{ 5, s_3_25, -1, 1, 0}, -{ 5, s_3_26, -1, 1, 0}, -{ 4, s_3_27, -1, 2, 0}, -{ 5, s_3_28, -1, 1, 0}, -{ 3, s_3_29, -1, 1, 0}, -{ 3, s_3_30, -1, 1, 0}, -{ 5, s_3_31, 30, 1, 0}, -{ 3, s_3_32, -1, 1, 0}, -{ 4, s_3_33, -1, 1, 0}, -{ 4, s_3_34, -1, 3, 0}, -{ 3, s_3_35, -1, 1, 0}, -{ 4, s_3_36, -1, 3, 0}, -{ 3, s_3_37, -1, 1, 0}, -{ 3, s_3_38, -1, 1, 0}, -{ 4, s_3_39, -1, 1, 0}, -{ 5, s_3_40, -1, 1, 0}, -{ 4, s_3_41, -1, 1, 0}, -{ 4, s_3_42, -1, 1, 0}, -{ 3, s_3_43, -1, 3, 0}, -{ 4, s_3_44, -1, 1, 0}, -{ 2, s_3_45, -1, 1, 0}, -{ 2, s_3_46, -1, 1, 0}, -{ 2, s_3_47, -1, 1, 0}, -{ 3, s_3_48, -1, 1, 0}, -{ 3, s_3_49, -1, 3, 0}, -{ 2, s_3_50, -1, 1, 0}, -{ 2, s_3_51, -1, 1, 0}, -{ 3, s_3_52, -1, 1, 0}, -{ 5, s_3_53, -1, 1, 0}, -{ 5, s_3_54, -1, 1, 0}, -{ 4, s_3_55, -1, 1, 0}, -{ 3, s_3_56, -1, 1, 0}, -{ 3, s_3_57, -1, 1, 0}, -{ 4, s_3_58, -1, 1, 0}, -{ 4, s_3_59, -1, 3, 0}, -{ 3, s_3_60, -1, 1, 0}, -{ 3, s_3_61, -1, 1, 0} -}; - -static const symbol s_4_0[2] = { 'e', 'a' }; -static const symbol s_4_1[2] = { 'i', 'a' }; -static const symbol s_4_2[3] = { 'e', 's', 'c' }; -static const symbol s_4_3[3] = { 0xE3, 's', 'c' }; -static const symbol s_4_4[3] = { 'i', 'n', 'd' }; -static const symbol s_4_5[3] = { 0xE2, 'n', 'd' }; -static const symbol s_4_6[3] = { 'a', 'r', 'e' }; -static const symbol s_4_7[3] = { 'e', 'r', 'e' }; -static const symbol s_4_8[3] = { 'i', 'r', 'e' }; -static const symbol s_4_9[3] = { 0xE2, 'r', 'e' }; -static const symbol s_4_10[2] = { 's', 'e' }; -static const symbol s_4_11[3] = { 'a', 's', 'e' }; -static const symbol s_4_12[4] = { 's', 'e', 's', 'e' }; -static const symbol s_4_13[3] = { 'i', 's', 'e' }; -static const symbol s_4_14[3] = { 'u', 's', 'e' }; -static const symbol s_4_15[3] = { 0xE2, 's', 'e' }; -static const symbol s_4_16[4] = { 'e', 0xBA, 't', 'e' }; -static const symbol s_4_17[4] = { 0xE3, 0xBA, 't', 'e' }; -static const symbol s_4_18[3] = { 'e', 'z', 'e' }; -static const symbol s_4_19[2] = { 'a', 'i' }; -static const symbol s_4_20[3] = { 'e', 'a', 'i' }; -static const symbol s_4_21[3] = { 'i', 'a', 'i' }; -static const symbol s_4_22[3] = { 's', 'e', 'i' }; -static const symbol s_4_23[4] = { 'e', 0xBA, 't', 'i' }; -static const symbol s_4_24[4] = { 0xE3, 0xBA, 't', 'i' }; -static const symbol s_4_25[2] = { 'u', 'i' }; -static const symbol s_4_26[3] = { 'e', 'z', 'i' }; -static const symbol s_4_27[3] = { 'a', 0xBA, 'i' }; -static const symbol s_4_28[4] = { 's', 'e', 0xBA, 'i' }; -static const symbol s_4_29[5] = { 'a', 's', 'e', 0xBA, 'i' }; -static const symbol s_4_30[6] = { 's', 'e', 's', 'e', 0xBA, 'i' }; -static const symbol s_4_31[5] = { 'i', 's', 'e', 0xBA, 'i' }; -static const symbol s_4_32[5] = { 'u', 's', 'e', 0xBA, 'i' }; -static const symbol s_4_33[5] = { 0xE2, 's', 'e', 0xBA, 'i' }; -static const symbol s_4_34[3] = { 'i', 0xBA, 'i' }; -static const symbol s_4_35[3] = { 'u', 0xBA, 'i' }; -static const symbol s_4_36[3] = { 0xE2, 0xBA, 'i' }; -static const symbol s_4_37[2] = { 0xE2, 'i' }; -static const symbol s_4_38[3] = { 'a', 0xFE, 'i' }; -static const symbol s_4_39[4] = { 'e', 'a', 0xFE, 'i' }; -static const symbol s_4_40[4] = { 'i', 'a', 0xFE, 'i' }; -static const symbol s_4_41[3] = { 'e', 0xFE, 'i' }; -static const symbol s_4_42[3] = { 'i', 0xFE, 'i' }; -static const symbol s_4_43[3] = { 0xE2, 0xFE, 'i' }; -static const symbol s_4_44[5] = { 'a', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_45[6] = { 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_46[7] = { 'a', 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_47[8] = { 's', 'e', 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_48[7] = { 'i', 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_49[7] = { 'u', 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_50[7] = { 0xE2, 's', 'e', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_51[5] = { 'i', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_52[5] = { 'u', 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_53[5] = { 0xE2, 'r', 0xE3, 0xFE, 'i' }; -static const symbol s_4_54[2] = { 'a', 'm' }; -static const symbol s_4_55[3] = { 'e', 'a', 'm' }; -static const symbol s_4_56[3] = { 'i', 'a', 'm' }; -static const symbol s_4_57[2] = { 'e', 'm' }; -static const symbol s_4_58[4] = { 'a', 's', 'e', 'm' }; -static const symbol s_4_59[5] = { 's', 'e', 's', 'e', 'm' }; -static const symbol s_4_60[4] = { 'i', 's', 'e', 'm' }; -static const symbol s_4_61[4] = { 'u', 's', 'e', 'm' }; -static const symbol s_4_62[4] = { 0xE2, 's', 'e', 'm' }; -static const symbol s_4_63[2] = { 'i', 'm' }; -static const symbol s_4_64[2] = { 0xE2, 'm' }; -static const symbol s_4_65[2] = { 0xE3, 'm' }; -static const symbol s_4_66[4] = { 'a', 'r', 0xE3, 'm' }; -static const symbol s_4_67[5] = { 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_68[6] = { 'a', 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_69[7] = { 's', 'e', 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_70[6] = { 'i', 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_71[6] = { 'u', 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_72[6] = { 0xE2, 's', 'e', 'r', 0xE3, 'm' }; -static const symbol s_4_73[4] = { 'i', 'r', 0xE3, 'm' }; -static const symbol s_4_74[4] = { 'u', 'r', 0xE3, 'm' }; -static const symbol s_4_75[4] = { 0xE2, 'r', 0xE3, 'm' }; -static const symbol s_4_76[2] = { 'a', 'u' }; -static const symbol s_4_77[3] = { 'e', 'a', 'u' }; -static const symbol s_4_78[3] = { 'i', 'a', 'u' }; -static const symbol s_4_79[4] = { 'i', 'n', 'd', 'u' }; -static const symbol s_4_80[4] = { 0xE2, 'n', 'd', 'u' }; -static const symbol s_4_81[2] = { 'e', 'z' }; -static const symbol s_4_82[5] = { 'e', 'a', 's', 'c', 0xE3 }; -static const symbol s_4_83[3] = { 'a', 'r', 0xE3 }; -static const symbol s_4_84[4] = { 's', 'e', 'r', 0xE3 }; -static const symbol s_4_85[5] = { 'a', 's', 'e', 'r', 0xE3 }; -static const symbol s_4_86[6] = { 's', 'e', 's', 'e', 'r', 0xE3 }; -static const symbol s_4_87[5] = { 'i', 's', 'e', 'r', 0xE3 }; -static const symbol s_4_88[5] = { 'u', 's', 'e', 'r', 0xE3 }; -static const symbol s_4_89[5] = { 0xE2, 's', 'e', 'r', 0xE3 }; -static const symbol s_4_90[3] = { 'i', 'r', 0xE3 }; -static const symbol s_4_91[3] = { 'u', 'r', 0xE3 }; -static const symbol s_4_92[3] = { 0xE2, 'r', 0xE3 }; -static const symbol s_4_93[4] = { 'e', 'a', 'z', 0xE3 }; - -static const struct among a_4[94] = -{ -{ 2, s_4_0, -1, 1, 0}, -{ 2, s_4_1, -1, 1, 0}, -{ 3, s_4_2, -1, 1, 0}, -{ 3, s_4_3, -1, 1, 0}, -{ 3, s_4_4, -1, 1, 0}, -{ 3, s_4_5, -1, 1, 0}, -{ 3, s_4_6, -1, 1, 0}, -{ 3, s_4_7, -1, 1, 0}, -{ 3, s_4_8, -1, 1, 0}, -{ 3, s_4_9, -1, 1, 0}, -{ 2, s_4_10, -1, 2, 0}, -{ 3, s_4_11, 10, 1, 0}, -{ 4, s_4_12, 10, 2, 0}, -{ 3, s_4_13, 10, 1, 0}, -{ 3, s_4_14, 10, 1, 0}, -{ 3, s_4_15, 10, 1, 0}, -{ 4, s_4_16, -1, 1, 0}, -{ 4, s_4_17, -1, 1, 0}, -{ 3, s_4_18, -1, 1, 0}, -{ 2, s_4_19, -1, 1, 0}, -{ 3, s_4_20, 19, 1, 0}, -{ 3, s_4_21, 19, 1, 0}, -{ 3, s_4_22, -1, 2, 0}, -{ 4, s_4_23, -1, 1, 0}, -{ 4, s_4_24, -1, 1, 0}, -{ 2, s_4_25, -1, 1, 0}, -{ 3, s_4_26, -1, 1, 0}, -{ 3, s_4_27, -1, 1, 0}, -{ 4, s_4_28, -1, 2, 0}, -{ 5, s_4_29, 28, 1, 0}, -{ 6, s_4_30, 28, 2, 0}, -{ 5, s_4_31, 28, 1, 0}, -{ 5, s_4_32, 28, 1, 0}, -{ 5, s_4_33, 28, 1, 0}, -{ 3, s_4_34, -1, 1, 0}, -{ 3, s_4_35, -1, 1, 0}, -{ 3, s_4_36, -1, 1, 0}, -{ 2, s_4_37, -1, 1, 0}, -{ 3, s_4_38, -1, 2, 0}, -{ 4, s_4_39, 38, 1, 0}, -{ 4, s_4_40, 38, 1, 0}, -{ 3, s_4_41, -1, 2, 0}, -{ 3, s_4_42, -1, 2, 0}, -{ 3, s_4_43, -1, 2, 0}, -{ 5, s_4_44, -1, 1, 0}, -{ 6, s_4_45, -1, 2, 0}, -{ 7, s_4_46, 45, 1, 0}, -{ 8, s_4_47, 45, 2, 0}, -{ 7, s_4_48, 45, 1, 0}, -{ 7, s_4_49, 45, 1, 0}, -{ 7, s_4_50, 45, 1, 0}, -{ 5, s_4_51, -1, 1, 0}, -{ 5, s_4_52, -1, 1, 0}, -{ 5, s_4_53, -1, 1, 0}, -{ 2, s_4_54, -1, 1, 0}, -{ 3, s_4_55, 54, 1, 0}, -{ 3, s_4_56, 54, 1, 0}, -{ 2, s_4_57, -1, 2, 0}, -{ 4, s_4_58, 57, 1, 0}, -{ 5, s_4_59, 57, 2, 0}, -{ 4, s_4_60, 57, 1, 0}, -{ 4, s_4_61, 57, 1, 0}, -{ 4, s_4_62, 57, 1, 0}, -{ 2, s_4_63, -1, 2, 0}, -{ 2, s_4_64, -1, 2, 0}, -{ 2, s_4_65, -1, 2, 0}, -{ 4, s_4_66, 65, 1, 0}, -{ 5, s_4_67, 65, 2, 0}, -{ 6, s_4_68, 67, 1, 0}, -{ 7, s_4_69, 67, 2, 0}, -{ 6, s_4_70, 67, 1, 0}, -{ 6, s_4_71, 67, 1, 0}, -{ 6, s_4_72, 67, 1, 0}, -{ 4, s_4_73, 65, 1, 0}, -{ 4, s_4_74, 65, 1, 0}, -{ 4, s_4_75, 65, 1, 0}, -{ 2, s_4_76, -1, 1, 0}, -{ 3, s_4_77, 76, 1, 0}, -{ 3, s_4_78, 76, 1, 0}, -{ 4, s_4_79, -1, 1, 0}, -{ 4, s_4_80, -1, 1, 0}, -{ 2, s_4_81, -1, 1, 0}, -{ 5, s_4_82, -1, 1, 0}, -{ 3, s_4_83, -1, 1, 0}, -{ 4, s_4_84, -1, 2, 0}, -{ 5, s_4_85, 84, 1, 0}, -{ 6, s_4_86, 84, 2, 0}, -{ 5, s_4_87, 84, 1, 0}, -{ 5, s_4_88, 84, 1, 0}, -{ 5, s_4_89, 84, 1, 0}, -{ 3, s_4_90, -1, 1, 0}, -{ 3, s_4_91, -1, 1, 0}, -{ 3, s_4_92, -1, 1, 0}, -{ 4, s_4_93, -1, 1, 0} -}; - -static const symbol s_5_0[1] = { 'a' }; -static const symbol s_5_1[1] = { 'e' }; -static const symbol s_5_2[2] = { 'i', 'e' }; -static const symbol s_5_3[1] = { 'i' }; -static const symbol s_5_4[1] = { 0xE3 }; - -static const struct among a_5[5] = -{ -{ 1, s_5_0, -1, 1, 0}, -{ 1, s_5_1, -1, 1, 0}, -{ 2, s_5_2, 1, 1, 0}, -{ 1, s_5_3, -1, 1, 0}, -{ 1, s_5_4, -1, 1, 0} -}; - -static const unsigned char g_v[] = { 17, 65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 32 }; - -static const symbol s_0[] = { 'U' }; -static const symbol s_1[] = { 'I' }; -static const symbol s_2[] = { 'i' }; -static const symbol s_3[] = { 'u' }; -static const symbol s_4[] = { 'a' }; -static const symbol s_5[] = { 'e' }; -static const symbol s_6[] = { 'i' }; -static const symbol s_7[] = { 'a', 'b' }; -static const symbol s_8[] = { 'i' }; -static const symbol s_9[] = { 'a', 't' }; -static const symbol s_10[] = { 'a', 0xFE, 'i' }; -static const symbol s_11[] = { 'a', 'b', 'i', 'l' }; -static const symbol s_12[] = { 'i', 'b', 'i', 'l' }; -static const symbol s_13[] = { 'i', 'v' }; -static const symbol s_14[] = { 'i', 'c' }; -static const symbol s_15[] = { 'a', 't' }; -static const symbol s_16[] = { 'i', 't' }; -static const symbol s_17[] = { 't' }; -static const symbol s_18[] = { 'i', 's', 't' }; - -static int r_prelude(struct SN_env * z) { - while(1) { - int c1 = z->c; - while(1) { - int c2 = z->c; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab1; - z->bra = z->c; - { int c3 = z->c; - if (z->c == z->l || z->p[z->c] != 'u') goto lab3; - z->c++; - z->ket = z->c; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab3; - { int ret = slice_from_s(z, 1, s_0); - if (ret < 0) return ret; - } - goto lab2; - lab3: - z->c = c3; - if (z->c == z->l || z->p[z->c] != 'i') goto lab1; - z->c++; - z->ket = z->c; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab1; - { int ret = slice_from_s(z, 1, s_1); - if (ret < 0) return ret; - } - } - lab2: - z->c = c2; - break; - lab1: - z->c = c2; - if (z->c >= z->l) goto lab0; - z->c++; - } - continue; - lab0: - z->c = c1; - break; - } - return 1; -} - -static int r_mark_regions(struct SN_env * z) { - z->I[2] = z->l; - z->I[1] = z->l; - z->I[0] = z->l; - { int c1 = z->c; - { int c2 = z->c; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab2; - { int c3 = z->c; - if (out_grouping(z, g_v, 97, 238, 0)) goto lab4; - { - int ret = out_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab4; - z->c += ret; - } - goto lab3; - lab4: - z->c = c3; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab2; - { - int ret = in_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab2; - z->c += ret; - } - } - lab3: - goto lab1; - lab2: - z->c = c2; - if (out_grouping(z, g_v, 97, 238, 0)) goto lab0; - { int c4 = z->c; - if (out_grouping(z, g_v, 97, 238, 0)) goto lab6; - { - int ret = out_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab6; - z->c += ret; - } - goto lab5; - lab6: - z->c = c4; - if (in_grouping(z, g_v, 97, 238, 0)) goto lab0; - if (z->c >= z->l) goto lab0; - z->c++; - } - lab5: - ; - } - lab1: - z->I[2] = z->c; - lab0: - z->c = c1; - } - { int c5 = z->c; - { - int ret = out_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab7; - z->c += ret; - } - { - int ret = in_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab7; - z->c += ret; - } - z->I[1] = z->c; - { - int ret = out_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab7; - z->c += ret; - } - { - int ret = in_grouping(z, g_v, 97, 238, 1); - if (ret < 0) goto lab7; - z->c += ret; - } - z->I[0] = z->c; - lab7: - z->c = c5; - } - return 1; -} - -static int r_postlude(struct SN_env * z) { - int among_var; - while(1) { - int c1 = z->c; - z->bra = z->c; - if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 85)) among_var = 3; else - among_var = find_among(z, a_0, 3); - if (!(among_var)) goto lab0; - z->ket = z->c; - switch (among_var) { - case 1: - { int ret = slice_from_s(z, 1, s_2); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 1, s_3); - if (ret < 0) return ret; - } - break; - case 3: - if (z->c >= z->l) goto lab0; - z->c++; - break; - } - continue; - lab0: - z->c = c1; - break; - } - return 1; -} - -static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; -} - -static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; -} - -static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; -} - -static int r_step_0(struct SN_env * z) { - int among_var; - z->ket = z->c; - if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((266786 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - among_var = find_among_b(z, a_1, 16); - if (!(among_var)) return 0; - z->bra = z->c; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - switch (among_var) { - case 1: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 1, s_4); - if (ret < 0) return ret; - } - break; - case 3: - { int ret = slice_from_s(z, 1, s_5); - if (ret < 0) return ret; - } - break; - case 4: - { int ret = slice_from_s(z, 1, s_6); - if (ret < 0) return ret; - } - break; - case 5: - { int m1 = z->l - z->c; (void)m1; - if (!(eq_s_b(z, 2, s_7))) goto lab0; - return 0; - lab0: - z->c = z->l - m1; - } - { int ret = slice_from_s(z, 1, s_8); - if (ret < 0) return ret; - } - break; - case 6: - { int ret = slice_from_s(z, 2, s_9); - if (ret < 0) return ret; - } - break; - case 7: - { int ret = slice_from_s(z, 3, s_10); - if (ret < 0) return ret; - } - break; - } - return 1; -} - -static int r_combo_suffix(struct SN_env * z) { - int among_var; - { int m_test1 = z->l - z->c; - z->ket = z->c; - among_var = find_among_b(z, a_2, 46); - if (!(among_var)) return 0; - z->bra = z->c; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - switch (among_var) { - case 1: - { int ret = slice_from_s(z, 4, s_11); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 4, s_12); - if (ret < 0) return ret; - } - break; - case 3: - { int ret = slice_from_s(z, 2, s_13); - if (ret < 0) return ret; - } - break; - case 4: - { int ret = slice_from_s(z, 2, s_14); - if (ret < 0) return ret; - } - break; - case 5: - { int ret = slice_from_s(z, 2, s_15); - if (ret < 0) return ret; - } - break; - case 6: - { int ret = slice_from_s(z, 2, s_16); - if (ret < 0) return ret; - } - break; - } - z->I[3] = 1; - z->c = z->l - m_test1; - } - return 1; -} - -static int r_standard_suffix(struct SN_env * z) { - int among_var; - z->I[3] = 0; - while(1) { - int m1 = z->l - z->c; (void)m1; - { int ret = r_combo_suffix(z); - if (ret == 0) goto lab0; - if (ret < 0) return ret; - } - continue; - lab0: - z->c = z->l - m1; - break; - } - z->ket = z->c; - among_var = find_among_b(z, a_3, 62); - if (!(among_var)) return 0; - z->bra = z->c; - { int ret = r_R2(z); - if (ret <= 0) return ret; - } - switch (among_var) { - case 1: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 2: - if (z->c <= z->lb || z->p[z->c - 1] != 0xFE) return 0; - z->c--; - z->bra = z->c; - { int ret = slice_from_s(z, 1, s_17); - if (ret < 0) return ret; - } - break; - case 3: - { int ret = slice_from_s(z, 3, s_18); - if (ret < 0) return ret; - } - break; - } - z->I[3] = 1; - return 1; -} - -static int r_verb_suffix(struct SN_env * z) { - int among_var; - - { int mlimit1; - if (z->c < z->I[2]) return 0; - mlimit1 = z->lb; z->lb = z->I[2]; - z->ket = z->c; - among_var = find_among_b(z, a_4, 94); - if (!(among_var)) { z->lb = mlimit1; return 0; } - z->bra = z->c; - switch (among_var) { - case 1: - { int m2 = z->l - z->c; (void)m2; - if (out_grouping_b(z, g_v, 97, 238, 0)) goto lab1; - goto lab0; - lab1: - z->c = z->l - m2; - if (z->c <= z->lb || z->p[z->c - 1] != 'u') { z->lb = mlimit1; return 0; } - z->c--; - } - lab0: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - } - z->lb = mlimit1; - } - return 1; -} - -static int r_vowel_suffix(struct SN_env * z) { - z->ket = z->c; - if (!(find_among_b(z, a_5, 5))) return 0; - z->bra = z->c; - { int ret = r_RV(z); - if (ret <= 0) return ret; - } - { int ret = slice_del(z); - if (ret < 0) return ret; - } - return 1; -} - -extern int romanian_ISO_8859_2_stem(struct SN_env * z) { - { int c1 = z->c; - { int ret = r_prelude(z); - if (ret < 0) return ret; - } - z->c = c1; - } - - { int ret = r_mark_regions(z); - if (ret < 0) return ret; - } - z->lb = z->c; z->c = z->l; - - { int m2 = z->l - z->c; (void)m2; - { int ret = r_step_0(z); - if (ret < 0) return ret; - } - z->c = z->l - m2; - } - { int m3 = z->l - z->c; (void)m3; - { int ret = r_standard_suffix(z); - if (ret < 0) return ret; - } - z->c = z->l - m3; - } - { int m4 = z->l - z->c; (void)m4; - { int m5 = z->l - z->c; (void)m5; - if (!(z->I[3])) goto lab2; - goto lab1; - lab2: - z->c = z->l - m5; - { int ret = r_verb_suffix(z); - if (ret == 0) goto lab0; - if (ret < 0) return ret; - } - } - lab1: - lab0: - z->c = z->l - m4; - } - { int m6 = z->l - z->c; (void)m6; - { int ret = r_vowel_suffix(z); - if (ret < 0) return ret; - } - z->c = z->l - m6; - } - z->c = z->lb; - { int c7 = z->c; - { int ret = r_postlude(z); - if (ret < 0) return ret; - } - z->c = c7; - } - return 1; -} - -extern struct SN_env * romanian_ISO_8859_2_create_env(void) { return SN_create_env(0, 4); } - -extern void romanian_ISO_8859_2_close_env(struct SN_env * z) { SN_close_env(z, 0); } - diff --git a/src/backend/snowball/libstemmer/stem_KOI8_R_russian.c b/src/backend/snowball/libstemmer/stem_KOI8_R_russian.c index 3bd2f71376df2..f9f0973b3935e 100644 --- a/src/backend/snowball/libstemmer/stem_KOI8_R_russian.c +++ b/src/backend/snowball/libstemmer/stem_KOI8_R_russian.c @@ -345,23 +345,27 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping(z, g_v, 192, 220, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = in_grouping(z, g_v, 192, 220, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = out_grouping(z, g_v, 192, 220, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping(z, g_v, 192, 220, 1); if (ret < 0) goto lab0; z->c += ret; @@ -374,8 +378,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_perfective_gerund(struct SN_env * z) { @@ -383,7 +386,7 @@ static int r_perfective_gerund(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((25166336 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_0, 9); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -413,7 +416,7 @@ static int r_perfective_gerund(struct SN_env * z) { static int r_adjective(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((2271009 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 26))) return 0; + if (!find_among_b(z, a_1, 26)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -430,7 +433,7 @@ static int r_adjectival(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((671113216 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m1; goto lab0; } among_var = find_among_b(z, a_2, 8); - if (!(among_var)) { z->c = z->l - m1; goto lab0; } + if (!among_var) { z->c = z->l - m1; goto lab0; } z->bra = z->c; switch (among_var) { case 1: @@ -463,7 +466,7 @@ static int r_adjectival(struct SN_env * z) { static int r_reflexive(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 209 && z->p[z->c - 1] != 216)) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -476,7 +479,7 @@ static int r_verb(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((51443235 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_4, 46); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -506,7 +509,7 @@ static int r_verb(struct SN_env * z) { static int r_noun(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((60991267 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_5, 36))) return 0; + if (!find_among_b(z, a_5, 36)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -517,7 +520,7 @@ static int r_noun(struct SN_env * z) { static int r_derivational(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 212 && z->p[z->c - 1] != 216)) return 0; - if (!(find_among_b(z, a_6, 2))) return 0; + if (!find_among_b(z, a_6, 2)) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -533,7 +536,7 @@ static int r_tidy_up(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 6 || !((151011360 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_7, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -593,7 +596,7 @@ extern int russian_KOI8_R_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_arabic.c b/src/backend/snowball/libstemmer/stem_UTF_8_arabic.c index 51d443ef239d2..1f00dd95c89e5 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_arabic.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_arabic.c @@ -680,7 +680,7 @@ static int r_Normalize_pre(struct SN_env * z) { { int c3 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 144); - if (!(among_var)) goto lab3; + if (!among_var) goto lab3; z->ket = z->c; switch (among_var) { case 1: @@ -965,7 +965,7 @@ static int r_Normalize_post(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 5 || !((124 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab0; - if (!(find_among_b(z, a_1, 5))) goto lab0; + if (!find_among_b(z, a_1, 5)) goto lab0; z->bra = z->c; { int ret = slice_from_s(z, 2, s_50); if (ret < 0) return ret; @@ -981,7 +981,7 @@ static int r_Normalize_post(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 5 || !((124 >> (z->p[z->c + 1] & 0x1f)) & 1)) goto lab4; among_var = find_among(z, a_2, 5); - if (!(among_var)) goto lab4; + if (!among_var) goto lab4; z->ket = z->c; switch (among_var) { case 1: @@ -1024,17 +1024,17 @@ static int r_Checks1(struct SN_env * z) { z->bra = z->c; if (z->c + 3 >= z->l || (z->p[z->c + 3] != 132 && z->p[z->c + 3] != 167)) return 0; among_var = find_among(z, a_3, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; z->I[2] = 1; z->I[1] = 0; z->I[0] = 1; break; case 2: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; z->I[2] = 1; z->I[1] = 0; z->I[0] = 1; @@ -1048,29 +1048,29 @@ static int r_Prefix_Step1(struct SN_env * z) { z->bra = z->c; if (z->c + 3 >= z->l || z->p[z->c + 3] >> 5 != 5 || !((188 >> (z->p[z->c + 3] & 0x1f)) & 1)) return 0; among_var = find_among(z, a_4, 5); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_54); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_55); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_56); if (ret < 0) return ret; } break; case 4: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_57); if (ret < 0) return ret; } @@ -1082,9 +1082,9 @@ static int r_Prefix_Step1(struct SN_env * z) { static int r_Prefix_Step2(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || (z->p[z->c + 1] != 129 && z->p[z->c + 1] != 136)) return 0; - if (!(find_among(z, a_5, 2))) return 0; + if (!find_among(z, a_5, 2)) return 0; z->ket = z->c; - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int c1 = z->c; if (!(eq_s(z, 2, s_58))) goto lab0; return 0; @@ -1102,17 +1102,17 @@ static int r_Prefix_Step3a_Noun(struct SN_env * z) { z->bra = z->c; if (z->c + 3 >= z->l || (z->p[z->c + 3] != 132 && z->p[z->c + 3] != 167)) return 0; among_var = find_among(z, a_6, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) > 5)) return 0; + if (len_utf8(z->p) <= 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1126,23 +1126,23 @@ static int r_Prefix_Step3b_Noun(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || (z->p[z->c + 1] != 168 && z->p[z->c + 1] != 131)) return 0; among_var = find_among(z, a_7, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_59); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) > 3)) return 0; + if (len_utf8(z->p) <= 3) return 0; { int ret = slice_from_s(z, 2, s_60); if (ret < 0) return ret; } @@ -1155,29 +1155,29 @@ static int r_Prefix_Step3_Verb(struct SN_env * z) { int among_var; z->bra = z->c; among_var = find_among(z, a_8, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_from_s(z, 2, s_61); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_from_s(z, 2, s_62); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_from_s(z, 2, s_63); if (ret < 0) return ret; } break; case 4: - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_from_s(z, 2, s_64); if (ret < 0) return ret; } @@ -1189,9 +1189,9 @@ static int r_Prefix_Step3_Verb(struct SN_env * z) { static int r_Prefix_Step4_Verb(struct SN_env * z) { z->bra = z->c; if (z->c + 5 >= z->l || z->p[z->c + 5] != 170) return 0; - if (!(find_among(z, a_9, 3))) return 0; + if (!find_among(z, a_9, 3)) return 0; z->ket = z->c; - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; z->I[1] = 1; z->I[2] = 0; { int ret = slice_from_s(z, 6, s_65); @@ -1204,23 +1204,23 @@ static int r_Suffix_Noun_Step1a(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_10, 10); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) >= 5)) return 0; + if (len_utf8(z->p) < 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) >= 6)) return 0; + if (len_utf8(z->p) < 6) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1232,9 +1232,9 @@ static int r_Suffix_Noun_Step1a(struct SN_env * z) { static int r_Suffix_Noun_Step1b(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 134) return 0; - if (!(find_among_b(z, a_11, 1))) return 0; + if (!find_among_b(z, a_11, 1)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) > 5)) return 0; + if (len_utf8(z->p) <= 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1243,9 +1243,9 @@ static int r_Suffix_Noun_Step1b(struct SN_env * z) { static int r_Suffix_Noun_Step2a(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_12, 3))) return 0; + if (!find_among_b(z, a_12, 3)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) > 4)) return 0; + if (len_utf8(z->p) <= 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1255,9 +1255,9 @@ static int r_Suffix_Noun_Step2a(struct SN_env * z) { static int r_Suffix_Noun_Step2b(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 170) return 0; - if (!(find_among_b(z, a_13, 1))) return 0; + if (!find_among_b(z, a_13, 1)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) >= 5)) return 0; + if (len_utf8(z->p) < 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1267,9 +1267,9 @@ static int r_Suffix_Noun_Step2b(struct SN_env * z) { static int r_Suffix_Noun_Step2c1(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 170) return 0; - if (!(find_among_b(z, a_14, 1))) return 0; + if (!find_among_b(z, a_14, 1)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1279,9 +1279,9 @@ static int r_Suffix_Noun_Step2c1(struct SN_env * z) { static int r_Suffix_Noun_Step2c2(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 169) return 0; - if (!(find_among_b(z, a_15, 1))) return 0; + if (!find_among_b(z, a_15, 1)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1291,9 +1291,9 @@ static int r_Suffix_Noun_Step2c2(struct SN_env * z) { static int r_Suffix_Noun_Step3(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 138) return 0; - if (!(find_among_b(z, a_16, 1))) return 0; + if (!find_among_b(z, a_16, 1)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) >= 3)) return 0; + if (len_utf8(z->p) < 3) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1304,23 +1304,23 @@ static int r_Suffix_Verb_Step1(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_17, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) >= 5)) return 0; + if (len_utf8(z->p) < 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) >= 6)) return 0; + if (len_utf8(z->p) < 6) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1333,29 +1333,29 @@ static int r_Suffix_Verb_Step2a(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_18, 11); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) >= 5)) return 0; + if (len_utf8(z->p) < 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 3: - if (!(len_utf8(z->p) > 5)) return 0; + if (len_utf8(z->p) <= 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 4: - if (!(len_utf8(z->p) >= 6)) return 0; + if (len_utf8(z->p) < 6) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1367,9 +1367,9 @@ static int r_Suffix_Verb_Step2a(struct SN_env * z) { static int r_Suffix_Verb_Step2b(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 133 && z->p[z->c - 1] != 167)) return 0; - if (!(find_among_b(z, a_19, 2))) return 0; + if (!find_among_b(z, a_19, 2)) return 0; z->bra = z->c; - if (!(len_utf8(z->p) >= 5)) return 0; + if (len_utf8(z->p) < 5) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1381,17 +1381,17 @@ static int r_Suffix_Verb_Step2c(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 136) return 0; among_var = find_among_b(z, a_20, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: - if (!(len_utf8(z->p) >= 4)) return 0; + if (len_utf8(z->p) < 4) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 2: - if (!(len_utf8(z->p) >= 6)) return 0; + if (len_utf8(z->p) < 6) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -1403,7 +1403,7 @@ static int r_Suffix_Verb_Step2c(struct SN_env * z) { static int r_Suffix_All_alef_maqsura(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 137) return 0; - if (!(find_among_b(z, a_21, 1))) return 0; + if (!find_among_b(z, a_21, 1)) return 0; z->bra = z->c; { int ret = slice_from_s(z, 2, s_66); if (ret < 0) return ret; @@ -1421,7 +1421,7 @@ extern int arabic_UTF_8_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_Normalize_pre(z); if (ret < 0) return ret; } @@ -1496,7 +1496,7 @@ extern int arabic_UTF_8_stem(struct SN_env * z) { goto lab12; lab13: z->c = z->l - m8; - + if (!(z->I[0])) goto lab15; goto lab14; lab15: @@ -1563,7 +1563,7 @@ extern int arabic_UTF_8_stem(struct SN_env * z) { goto lab12; lab20: z->c = z->l - m8; - + if (!(z->I[0])) goto lab25; goto lab24; lab25: @@ -1651,7 +1651,7 @@ extern int arabic_UTF_8_stem(struct SN_env * z) { lab26: z->c = c11; } - + { int ret = r_Normalize_post(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_armenian.c b/src/backend/snowball/libstemmer/stem_UTF_8_armenian.c index 27f9f19f89815..81ec52fef2b2e 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_armenian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_armenian.c @@ -436,23 +436,27 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 1377, 1413, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = in_grouping_U(z, g_v, 1377, 1413, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = out_grouping_U(z, g_v, 1377, 1413, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 1377, 1413, 1); if (ret < 0) goto lab0; z->c += ret; @@ -465,13 +469,12 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_adjective(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_0, 23))) return 0; + if (!find_among_b(z, a_0, 23)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -481,7 +484,7 @@ static int r_adjective(struct SN_env * z) { static int r_verb(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_1, 71))) return 0; + if (!find_among_b(z, a_1, 71)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -491,7 +494,7 @@ static int r_verb(struct SN_env * z) { static int r_noun(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_2, 40))) return 0; + if (!find_among_b(z, a_2, 40)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -501,7 +504,7 @@ static int r_noun(struct SN_env * z) { static int r_ending(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_3, 57))) return 0; + if (!find_among_b(z, a_3, 57)) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -513,7 +516,7 @@ static int r_ending(struct SN_env * z) { } extern int armenian_UTF_8_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_basque.c b/src/backend/snowball/libstemmer/stem_UTF_8_basque.c index 03316b1da43e1..67b5b4835b872 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_basque.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_basque.c @@ -912,7 +912,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping_U(z, g_v, 97, 117, 0)) goto lab2; { int c3 = z->c; if (out_grouping_U(z, g_v, 97, 117, 0)) goto lab4; - { + + { int ret = out_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab4; z->c += ret; @@ -921,7 +922,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping_U(z, g_v, 97, 117, 0)) goto lab2; - { + + { int ret = in_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab2; z->c += ret; @@ -934,7 +936,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping_U(z, g_v, 97, 117, 0)) goto lab0; { int c4 = z->c; if (out_grouping_U(z, g_v, 97, 117, 0)) goto lab6; - { + + { int ret = out_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab6; z->c += ret; @@ -957,23 +960,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab7; z->c += ret; @@ -986,18 +993,15 @@ static int r_mark_regions(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_aditzak(struct SN_env * z) { @@ -1005,7 +1009,7 @@ static int r_aditzak(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((70566434 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_0, 109); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1048,7 +1052,7 @@ static int r_izenak(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((71162402 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_1, 295); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1119,7 +1123,7 @@ static int r_adjetiboak(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((35362 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_2, 19); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1140,7 +1144,7 @@ static int r_adjetiboak(struct SN_env * z) { } extern int basque_UTF_8_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_catalan.c b/src/backend/snowball/libstemmer/stem_UTF_8_catalan.c index a215aab712171..d261407883b15 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_catalan.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_catalan.c @@ -1184,23 +1184,27 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab0; z->c += ret; @@ -1219,7 +1223,6 @@ static int r_cleaning(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 5 || !((344765187 >> (z->p[z->c + 1] & 0x1f)) & 1)) among_var = 7; else among_var = find_among(z, a_0, 13); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -1268,19 +1271,17 @@ static int r_cleaning(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1634850 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 39))) return 0; + if (!find_among_b(z, a_1, 39)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -1295,7 +1296,7 @@ static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_2, 200); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1346,7 +1347,7 @@ static int r_verb_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_3, 283); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1373,7 +1374,7 @@ static int r_residual_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_4, 22); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1397,7 +1398,7 @@ static int r_residual_suffix(struct SN_env * z) { } extern int catalan_UTF_8_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_danish.c b/src/backend/snowball/libstemmer/stem_UTF_8_danish.c index 3d60ffcdb99f8..b16c6e67423ea 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_danish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_danish.c @@ -143,15 +143,17 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->c; z->c = c_test1; } + if (out_grouping_U(z, g_v, 97, 248, 1) < 0) return 0; - { + + { int ret = in_grouping_U(z, g_v, 97, 248, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -166,7 +168,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851440 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 32); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -194,7 +196,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit2 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 116)) { z->lb = mlimit2; return 0; } - if (!(find_among_b(z, a_1, 4))) { z->lb = mlimit2; return 0; } + if (!find_among_b(z, a_1, 4)) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } @@ -231,7 +233,7 @@ static int r_other_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1572992 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit2; return 0; } among_var = find_among_b(z, a_2, 5); - if (!(among_var)) { z->lb = mlimit2; return 0; } + if (!among_var) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_dutch.c b/src/backend/snowball/libstemmer/stem_UTF_8_dutch.c index 7a307effe5430..8fde5390f4dce 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_dutch.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_dutch.c @@ -152,7 +152,6 @@ static int r_prelude(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 5 || !((340306450 >> (z->p[z->c + 1] & 0x1f)) & 1)) among_var = 6; else among_var = find_among(z, a_0, 11); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -248,34 +247,46 @@ static int r_prelude(struct SN_env * z) { } static int r_mark_regions(struct SN_env * z) { + z->I[2] = z->l; z->I[1] = z->l; - z->I[0] = z->l; - { + { int c_test1 = z->c; + { int ret = skip_utf8(z->p, z->c, z->l, 3); + if (ret < 0) return 0; + z->c = ret; + } + z->I[0] = z->c; + z->c = c_test1; + } + + { int ret = out_grouping_U(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - z->I[1] = z->c; - - if (!(z->I[1] < 3)) goto lab0; - z->I[1] = 3; + z->I[2] = z->c; + + if (z->I[2] >= z->I[0]) goto lab0; + z->I[2] = z->I[0]; lab0: - { + + { int ret = out_grouping_U(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 232, 1); if (ret < 0) return 0; z->c += ret; } - z->I[0] = z->c; + z->I[1] = z->c; return 1; } @@ -286,7 +297,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 89)) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -315,19 +325,17 @@ static int r_postlude(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_undouble(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1050640 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 3))) return 0; + if (!find_among_b(z, a_2, 3)) return 0; z->c = z->l - m_test1; } z->ket = z->c; @@ -343,7 +351,7 @@ static int r_undouble(struct SN_env * z) { } static int r_e_ending(struct SN_env * z) { - z->I[2] = 0; + z->I[3] = 0; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 'e') return 0; z->c--; @@ -358,7 +366,7 @@ static int r_e_ending(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - z->I[2] = 1; + z->I[3] = 1; { int ret = r_undouble(z); if (ret <= 0) return ret; } @@ -394,7 +402,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((540704 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab0; among_var = find_among_b(z, a_3, 5); - if (!(among_var)) goto lab0; + if (!among_var) goto lab0; z->bra = z->c; switch (among_var) { case 1: @@ -464,7 +472,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((264336 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; among_var = find_among_b(z, a_4, 6); - if (!(among_var)) goto lab3; + if (!among_var) goto lab3; z->bra = z->c; switch (among_var) { case 1: @@ -546,7 +554,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) goto lab3; if (ret < 0) return ret; } - if (!(z->I[2])) goto lab3; + if (!(z->I[3])) goto lab3; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -559,7 +567,7 @@ static int r_standard_suffix(struct SN_env * z) { if (out_grouping_b_U(z, g_v_I, 73, 232, 0)) goto lab8; { int m_test10 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((2129954 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab8; - if (!(find_among_b(z, a_5, 4))) goto lab8; + if (!find_among_b(z, a_5, 4)) goto lab8; if (out_grouping_b_U(z, g_v, 97, 232, 0)) goto lab8; z->c = z->l - m_test10; } @@ -593,7 +601,7 @@ extern int dutch_UTF_8_stem(struct SN_env * z) { } z->lb = z->c; z->c = z->l; - + { int ret = r_standard_suffix(z); if (ret < 0) return ret; } @@ -607,7 +615,7 @@ extern int dutch_UTF_8_stem(struct SN_env * z) { return 1; } -extern struct SN_env * dutch_UTF_8_create_env(void) { return SN_create_env(0, 3); } +extern struct SN_env * dutch_UTF_8_create_env(void) { return SN_create_env(0, 4); } extern void dutch_UTF_8_close_env(struct SN_env * z) { SN_close_env(z, 0); } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_english.c b/src/backend/snowball/libstemmer/stem_UTF_8_english.c index bc6eae1674a72..25144ad24afd2 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_english.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_english.c @@ -310,6 +310,8 @@ static const struct among a_10[18] = { 4, s_10_17, -1, 8, 0} }; +static const unsigned char g_aeo[] = { 17, 64 }; + static const unsigned char g_v[] = { 17, 65, 16, 1 }; static const unsigned char g_v_WXY[] = { 1, 17, 65, 208, 1 }; @@ -420,16 +422,18 @@ static int r_mark_regions(struct SN_env * z) { { int c1 = z->c; { int c2 = z->c; if (z->c + 4 >= z->l || z->p[z->c + 4] >> 5 != 3 || !((2375680 >> (z->p[z->c + 4] & 0x1f)) & 1)) goto lab2; - if (!(find_among(z, a_0, 3))) goto lab2; + if (!find_among(z, a_0, 3)) goto lab2; goto lab1; lab2: z->c = c2; - { + + { int ret = out_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; @@ -437,12 +441,14 @@ static int r_mark_regions(struct SN_env * z) { } lab1: z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab0; z->c += ret; @@ -471,13 +477,11 @@ static int r_shortv(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_Step_1a(struct SN_env * z) { @@ -485,7 +489,7 @@ static int r_Step_1a(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 39 && z->p[z->c - 1] != 115)) { z->c = z->l - m1; goto lab0; } - if (!(find_among_b(z, a_1, 3))) { z->c = z->l - m1; goto lab0; } + if (!find_among_b(z, a_1, 3)) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -496,7 +500,7 @@ static int r_Step_1a(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 115)) return 0; among_var = find_among_b(z, a_2, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -527,7 +531,8 @@ static int r_Step_1a(struct SN_env * z) { if (ret < 0) return 0; z->c = ret; } - { + + { int ret = out_grouping_b_U(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -545,7 +550,7 @@ static int r_Step_1b(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((33554576 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_4, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -558,7 +563,8 @@ static int r_Step_1b(struct SN_env * z) { break; case 2: { int m_test1 = z->l - z->c; - { + + { int ret = out_grouping_b_U(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -568,49 +574,51 @@ static int r_Step_1b(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } + z->ket = z->c; + z->bra = z->c; { int m_test2 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68514004 >> (z->p[z->c - 1] & 0x1f)) & 1)) among_var = 3; else among_var = find_among_b(z, a_3, 13); - if (!(among_var)) return 0; - z->c = z->l - m_test2; - } - switch (among_var) { - case 1: - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_6); - z->c = saved_c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 1, s_6); + if (ret < 0) return ret; + } + return 0; + break; + case 2: + { int m3 = z->l - z->c; (void)m3; + if (in_grouping_b_U(z, g_aeo, 97, 111, 0)) goto lab0; + if (z->c > z->lb) goto lab0; + return 0; + lab0: + z->c = z->l - m3; } - if (ret < 0) return ret; - } - break; - case 2: - z->ket = z->c; - { int ret = skip_b_utf8(z->p, z->c, z->lb, 1); - if (ret < 0) return 0; - z->c = ret; - } - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 3: - if (z->c != z->I[1]) return 0; - { int m_test3 = z->l - z->c; - { int ret = r_shortv(z); - if (ret <= 0) return ret; + break; + case 3: + if (z->c != z->I[1]) return 0; + { int m_test4 = z->l - z->c; + { int ret = r_shortv(z); + if (ret <= 0) return ret; + } + z->c = z->l - m_test4; } - z->c = z->l - m_test3; - } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_7); - z->c = saved_c; + { int ret = slice_from_s(z, 1, s_7); + if (ret < 0) return ret; } - if (ret < 0) return ret; - } - break; + return 0; + break; + } + z->c = z->l - m_test2; + } + z->ket = z->c; + { int ret = skip_b_utf8(z->p, z->c, z->lb, 1); + if (ret < 0) return 0; + z->c = ret; + } + z->bra = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; } break; } @@ -631,7 +639,7 @@ static int r_Step_1c(struct SN_env * z) { lab0: z->bra = z->c; if (out_grouping_b_U(z, g_v, 97, 121, 0)) return 0; - + if (z->c > z->lb) goto lab2; return 0; lab2: @@ -646,7 +654,7 @@ static int r_Step_2(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((815616 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 24); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -739,7 +747,7 @@ static int r_Step_3(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((528928 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_6, 9); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -787,7 +795,7 @@ static int r_Step_4(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1864232 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_7, 18); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -822,30 +830,28 @@ static int r_Step_5(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 101 && z->p[z->c - 1] != 108)) return 0; among_var = find_among_b(z, a_8, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: + + { int ret = r_R2(z); + if (ret == 0) goto lab1; + if (ret < 0) return ret; + } + goto lab0; + lab1: + { int ret = r_R1(z); + if (ret <= 0) return ret; + } { int m1 = z->l - z->c; (void)m1; - { int ret = r_R2(z); - if (ret == 0) goto lab1; + { int ret = r_shortv(z); + if (ret == 0) goto lab2; if (ret < 0) return ret; } - goto lab0; - lab1: + return 0; + lab2: z->c = z->l - m1; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_shortv(z); - if (ret == 0) goto lab2; - if (ret < 0) return ret; - } - return 0; - lab2: - z->c = z->l - m2; - } } lab0: { int ret = slice_del(z); @@ -869,7 +875,7 @@ static int r_Step_5(struct SN_env * z) { static int r_exception2(struct SN_env * z) { z->ket = z->c; if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 103)) return 0; - if (!(find_among_b(z, a_9, 8))) return 0; + if (!find_among_b(z, a_9, 8)) return 0; z->bra = z->c; if (z->c > z->lb) return 0; return 1; @@ -880,7 +886,7 @@ static int r_exception1(struct SN_env * z) { z->bra = z->c; if (z->c + 2 >= z->l || z->p[z->c + 2] >> 5 != 3 || !((42750482 >> (z->p[z->c + 2] & 0x1f)) & 1)) return 0; among_var = find_among(z, a_10, 18); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; if (z->c < z->l) return 0; switch (among_var) { @@ -994,11 +1000,11 @@ extern int english_UTF_8_stem(struct SN_env * z) { goto lab0; lab2: z->c = c1; - + { int ret = r_prelude(z); if (ret < 0) return ret; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_estonian.c b/src/backend/snowball/libstemmer/stem_UTF_8_estonian.c new file mode 100644 index 0000000000000..168239919184f --- /dev/null +++ b/src/backend/snowball/libstemmer/stem_UTF_8_estonian.c @@ -0,0 +1,1416 @@ +/* Generated by Snowball 2.2.0 - https://snowballstem.org/ */ + +#include "header.h" + +#ifdef __cplusplus +extern "C" { +#endif +extern int estonian_UTF_8_stem(struct SN_env * z); +#ifdef __cplusplus +} +#endif +static int r_nu(struct SN_env * z); +static int r_verb(struct SN_env * z); +static int r_verb_exceptions(struct SN_env * z); +static int r_substantive(struct SN_env * z); +static int r_degrees(struct SN_env * z); +static int r_i_plural(struct SN_env * z); +static int r_undouble_kpt(struct SN_env * z); +static int r_plural_three_first_cases(struct SN_env * z); +static int r_emphasis(struct SN_env * z); +static int r_case_ending(struct SN_env * z); +static int r_special_noun_endings(struct SN_env * z); +static int r_LONGV(struct SN_env * z); +static int r_mark_regions(struct SN_env * z); +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct SN_env * estonian_UTF_8_create_env(void); +extern void estonian_UTF_8_close_env(struct SN_env * z); + + +#ifdef __cplusplus +} +#endif +static const symbol s_0_0[2] = { 'g', 'i' }; +static const symbol s_0_1[2] = { 'k', 'i' }; + +static const struct among a_0[2] = +{ +{ 2, s_0_0, -1, 1, 0}, +{ 2, s_0_1, -1, 2, 0} +}; + +static const symbol s_1_0[2] = { 'd', 'a' }; +static const symbol s_1_1[4] = { 'm', 'a', 't', 'a' }; +static const symbol s_1_2[1] = { 'b' }; +static const symbol s_1_3[4] = { 'k', 's', 'i', 'd' }; +static const symbol s_1_4[6] = { 'n', 'u', 'k', 's', 'i', 'd' }; +static const symbol s_1_5[2] = { 'm', 'e' }; +static const symbol s_1_6[4] = { 's', 'i', 'm', 'e' }; +static const symbol s_1_7[5] = { 'k', 's', 'i', 'm', 'e' }; +static const symbol s_1_8[7] = { 'n', 'u', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_1_9[4] = { 'a', 'k', 's', 'e' }; +static const symbol s_1_10[5] = { 'd', 'a', 'k', 's', 'e' }; +static const symbol s_1_11[5] = { 't', 'a', 'k', 's', 'e' }; +static const symbol s_1_12[4] = { 's', 'i', 't', 'e' }; +static const symbol s_1_13[5] = { 'k', 's', 'i', 't', 'e' }; +static const symbol s_1_14[7] = { 'n', 'u', 'k', 's', 'i', 't', 'e' }; +static const symbol s_1_15[1] = { 'n' }; +static const symbol s_1_16[3] = { 's', 'i', 'n' }; +static const symbol s_1_17[4] = { 'k', 's', 'i', 'n' }; +static const symbol s_1_18[6] = { 'n', 'u', 'k', 's', 'i', 'n' }; +static const symbol s_1_19[4] = { 'd', 'a', 'k', 's' }; +static const symbol s_1_20[4] = { 't', 'a', 'k', 's' }; + +static const struct among a_1[21] = +{ +{ 2, s_1_0, -1, 3, 0}, +{ 4, s_1_1, -1, 1, 0}, +{ 1, s_1_2, -1, 3, 0}, +{ 4, s_1_3, -1, 1, 0}, +{ 6, s_1_4, 3, 1, 0}, +{ 2, s_1_5, -1, 3, 0}, +{ 4, s_1_6, 5, 1, 0}, +{ 5, s_1_7, 6, 1, 0}, +{ 7, s_1_8, 7, 1, 0}, +{ 4, s_1_9, -1, 2, 0}, +{ 5, s_1_10, 9, 1, 0}, +{ 5, s_1_11, 9, 1, 0}, +{ 4, s_1_12, -1, 1, 0}, +{ 5, s_1_13, 12, 1, 0}, +{ 7, s_1_14, 13, 1, 0}, +{ 1, s_1_15, -1, 3, 0}, +{ 3, s_1_16, 15, 1, 0}, +{ 4, s_1_17, 16, 1, 0}, +{ 6, s_1_18, 17, 1, 0}, +{ 4, s_1_19, -1, 1, 0}, +{ 4, s_1_20, -1, 1, 0} +}; + +static const symbol s_2_0[2] = { 'a', 'a' }; +static const symbol s_2_1[2] = { 'e', 'e' }; +static const symbol s_2_2[2] = { 'i', 'i' }; +static const symbol s_2_3[2] = { 'o', 'o' }; +static const symbol s_2_4[2] = { 'u', 'u' }; +static const symbol s_2_5[4] = { 0xC3, 0xA4, 0xC3, 0xA4 }; +static const symbol s_2_6[4] = { 0xC3, 0xB5, 0xC3, 0xB5 }; +static const symbol s_2_7[4] = { 0xC3, 0xB6, 0xC3, 0xB6 }; +static const symbol s_2_8[4] = { 0xC3, 0xBC, 0xC3, 0xBC }; + +static const struct among a_2[9] = +{ +{ 2, s_2_0, -1, -1, 0}, +{ 2, s_2_1, -1, -1, 0}, +{ 2, s_2_2, -1, -1, 0}, +{ 2, s_2_3, -1, -1, 0}, +{ 2, s_2_4, -1, -1, 0}, +{ 4, s_2_5, -1, -1, 0}, +{ 4, s_2_6, -1, -1, 0}, +{ 4, s_2_7, -1, -1, 0}, +{ 4, s_2_8, -1, -1, 0} +}; + +static const symbol s_3_0[1] = { 'i' }; + +static const struct among a_3[1] = +{ +{ 1, s_3_0, -1, 1, 0} +}; + +static const symbol s_4_0[4] = { 'l', 'a', 'n', 'e' }; +static const symbol s_4_1[4] = { 'l', 'i', 'n', 'e' }; +static const symbol s_4_2[4] = { 'm', 'i', 'n', 'e' }; +static const symbol s_4_3[5] = { 'l', 'a', 's', 's', 'e' }; +static const symbol s_4_4[5] = { 'l', 'i', 's', 's', 'e' }; +static const symbol s_4_5[5] = { 'm', 'i', 's', 's', 'e' }; +static const symbol s_4_6[4] = { 'l', 'a', 's', 'i' }; +static const symbol s_4_7[4] = { 'l', 'i', 's', 'i' }; +static const symbol s_4_8[4] = { 'm', 'i', 's', 'i' }; +static const symbol s_4_9[4] = { 'l', 'a', 's', 't' }; +static const symbol s_4_10[4] = { 'l', 'i', 's', 't' }; +static const symbol s_4_11[4] = { 'm', 'i', 's', 't' }; + +static const struct among a_4[12] = +{ +{ 4, s_4_0, -1, 1, 0}, +{ 4, s_4_1, -1, 3, 0}, +{ 4, s_4_2, -1, 2, 0}, +{ 5, s_4_3, -1, 1, 0}, +{ 5, s_4_4, -1, 3, 0}, +{ 5, s_4_5, -1, 2, 0}, +{ 4, s_4_6, -1, 1, 0}, +{ 4, s_4_7, -1, 3, 0}, +{ 4, s_4_8, -1, 2, 0}, +{ 4, s_4_9, -1, 1, 0}, +{ 4, s_4_10, -1, 3, 0}, +{ 4, s_4_11, -1, 2, 0} +}; + +static const symbol s_5_0[2] = { 'g', 'a' }; +static const symbol s_5_1[2] = { 't', 'a' }; +static const symbol s_5_2[2] = { 'l', 'e' }; +static const symbol s_5_3[3] = { 's', 's', 'e' }; +static const symbol s_5_4[1] = { 'l' }; +static const symbol s_5_5[1] = { 's' }; +static const symbol s_5_6[2] = { 'k', 's' }; +static const symbol s_5_7[1] = { 't' }; +static const symbol s_5_8[2] = { 'l', 't' }; +static const symbol s_5_9[2] = { 's', 't' }; + +static const struct among a_5[10] = +{ +{ 2, s_5_0, -1, 1, 0}, +{ 2, s_5_1, -1, 1, 0}, +{ 2, s_5_2, -1, 1, 0}, +{ 3, s_5_3, -1, 1, 0}, +{ 1, s_5_4, -1, 1, 0}, +{ 1, s_5_5, -1, 1, 0}, +{ 2, s_5_6, 5, 1, 0}, +{ 1, s_5_7, -1, 2, 0}, +{ 2, s_5_8, 7, 1, 0}, +{ 2, s_5_9, 7, 1, 0} +}; + +static const symbol s_6_1[3] = { 'l', 'a', 's' }; +static const symbol s_6_2[3] = { 'l', 'i', 's' }; +static const symbol s_6_3[3] = { 'm', 'i', 's' }; +static const symbol s_6_4[1] = { 't' }; + +static const struct among a_6[5] = +{ +{ 0, 0, -1, 2, 0}, +{ 3, s_6_1, 0, 1, 0}, +{ 3, s_6_2, 0, 1, 0}, +{ 3, s_6_3, 0, 1, 0}, +{ 1, s_6_4, 0, -1, 0} +}; + +static const symbol s_7_0[1] = { 'd' }; +static const symbol s_7_1[3] = { 's', 'i', 'd' }; +static const symbol s_7_2[2] = { 'd', 'e' }; +static const symbol s_7_3[6] = { 'i', 'k', 'k', 'u', 'd', 'e' }; +static const symbol s_7_4[3] = { 'i', 'k', 'e' }; +static const symbol s_7_5[4] = { 'i', 'k', 'k', 'e' }; +static const symbol s_7_6[2] = { 't', 'e' }; + +static const struct among a_7[7] = +{ +{ 1, s_7_0, -1, 4, 0}, +{ 3, s_7_1, 0, 2, 0}, +{ 2, s_7_2, -1, 4, 0}, +{ 6, s_7_3, 2, 1, 0}, +{ 3, s_7_4, -1, 1, 0}, +{ 4, s_7_5, -1, 1, 0}, +{ 2, s_7_6, -1, 3, 0} +}; + +static const symbol s_8_0[2] = { 'v', 'a' }; +static const symbol s_8_1[2] = { 'd', 'u' }; +static const symbol s_8_2[2] = { 'n', 'u' }; +static const symbol s_8_3[2] = { 't', 'u' }; + +static const struct among a_8[4] = +{ +{ 2, s_8_0, -1, -1, 0}, +{ 2, s_8_1, -1, -1, 0}, +{ 2, s_8_2, -1, -1, 0}, +{ 2, s_8_3, -1, -1, 0} +}; + +static const symbol s_9_0[2] = { 'k', 'k' }; +static const symbol s_9_1[2] = { 'p', 'p' }; +static const symbol s_9_2[2] = { 't', 't' }; + +static const struct among a_9[3] = +{ +{ 2, s_9_0, -1, 1, 0}, +{ 2, s_9_1, -1, 2, 0}, +{ 2, s_9_2, -1, 3, 0} +}; + +static const symbol s_10_0[2] = { 'm', 'a' }; +static const symbol s_10_1[3] = { 'm', 'a', 'i' }; +static const symbol s_10_2[1] = { 'm' }; + +static const struct among a_10[3] = +{ +{ 2, s_10_0, -1, 2, 0}, +{ 3, s_10_1, -1, 1, 0}, +{ 1, s_10_2, -1, 1, 0} +}; + +static const symbol s_11_0[4] = { 'j', 'o', 'o', 'b' }; +static const symbol s_11_1[4] = { 'j', 'o', 'o', 'd' }; +static const symbol s_11_2[8] = { 'j', 'o', 'o', 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_3[5] = { 'j', 'o', 'o', 'm', 'a' }; +static const symbol s_11_4[7] = { 'j', 'o', 'o', 'm', 'a', 't', 'a' }; +static const symbol s_11_5[5] = { 'j', 'o', 'o', 'm', 'e' }; +static const symbol s_11_6[4] = { 'j', 'o', 'o', 'n' }; +static const symbol s_11_7[5] = { 'j', 'o', 'o', 't', 'e' }; +static const symbol s_11_8[6] = { 'j', 'o', 'o', 'v', 'a', 'd' }; +static const symbol s_11_9[4] = { 'j', 'u', 'u', 'a' }; +static const symbol s_11_10[7] = { 'j', 'u', 'u', 'a', 'k', 's', 'e' }; +static const symbol s_11_11[4] = { 'j', 0xC3, 0xA4, 'i' }; +static const symbol s_11_12[5] = { 'j', 0xC3, 0xA4, 'i', 'd' }; +static const symbol s_11_13[6] = { 'j', 0xC3, 0xA4, 'i', 'm', 'e' }; +static const symbol s_11_14[5] = { 'j', 0xC3, 0xA4, 'i', 'n' }; +static const symbol s_11_15[6] = { 'j', 0xC3, 0xA4, 'i', 't', 'e' }; +static const symbol s_11_16[6] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'b' }; +static const symbol s_11_17[6] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'd' }; +static const symbol s_11_18[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'd', 'a' }; +static const symbol s_11_19[10] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_20[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'd', 'i' }; +static const symbol s_11_21[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'k', 's' }; +static const symbol s_11_22[9] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'k', 's', 'i', 'd' }; +static const symbol s_11_23[10] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_24[9] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'k', 's', 'i', 'n' }; +static const symbol s_11_25[10] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_26[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'm', 'a' }; +static const symbol s_11_27[9] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'm', 'a', 't', 'a' }; +static const symbol s_11_28[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'm', 'e' }; +static const symbol s_11_29[6] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'n' }; +static const symbol s_11_30[7] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 't', 'e' }; +static const symbol s_11_31[8] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'v', 'a', 'd' }; +static const symbol s_11_32[4] = { 'j', 0xC3, 0xB5, 'i' }; +static const symbol s_11_33[5] = { 'j', 0xC3, 0xB5, 'i', 'd' }; +static const symbol s_11_34[6] = { 'j', 0xC3, 0xB5, 'i', 'm', 'e' }; +static const symbol s_11_35[5] = { 'j', 0xC3, 0xB5, 'i', 'n' }; +static const symbol s_11_36[6] = { 'j', 0xC3, 0xB5, 'i', 't', 'e' }; +static const symbol s_11_37[4] = { 'k', 'e', 'e', 'b' }; +static const symbol s_11_38[4] = { 'k', 'e', 'e', 'd' }; +static const symbol s_11_39[8] = { 'k', 'e', 'e', 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_40[5] = { 'k', 'e', 'e', 'k', 's' }; +static const symbol s_11_41[7] = { 'k', 'e', 'e', 'k', 's', 'i', 'd' }; +static const symbol s_11_42[8] = { 'k', 'e', 'e', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_43[7] = { 'k', 'e', 'e', 'k', 's', 'i', 'n' }; +static const symbol s_11_44[8] = { 'k', 'e', 'e', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_45[5] = { 'k', 'e', 'e', 'm', 'a' }; +static const symbol s_11_46[7] = { 'k', 'e', 'e', 'm', 'a', 't', 'a' }; +static const symbol s_11_47[5] = { 'k', 'e', 'e', 'm', 'e' }; +static const symbol s_11_48[4] = { 'k', 'e', 'e', 'n' }; +static const symbol s_11_49[4] = { 'k', 'e', 'e', 's' }; +static const symbol s_11_50[5] = { 'k', 'e', 'e', 't', 'a' }; +static const symbol s_11_51[5] = { 'k', 'e', 'e', 't', 'e' }; +static const symbol s_11_52[6] = { 'k', 'e', 'e', 'v', 'a', 'd' }; +static const symbol s_11_53[5] = { 'k', 0xC3, 0xA4, 'i', 'a' }; +static const symbol s_11_54[8] = { 'k', 0xC3, 0xA4, 'i', 'a', 'k', 's', 'e' }; +static const symbol s_11_55[5] = { 'k', 0xC3, 0xA4, 'i', 'b' }; +static const symbol s_11_56[5] = { 'k', 0xC3, 0xA4, 'i', 'd' }; +static const symbol s_11_57[6] = { 'k', 0xC3, 0xA4, 'i', 'd', 'i' }; +static const symbol s_11_58[6] = { 'k', 0xC3, 0xA4, 'i', 'k', 's' }; +static const symbol s_11_59[8] = { 'k', 0xC3, 0xA4, 'i', 'k', 's', 'i', 'd' }; +static const symbol s_11_60[9] = { 'k', 0xC3, 0xA4, 'i', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_61[8] = { 'k', 0xC3, 0xA4, 'i', 'k', 's', 'i', 'n' }; +static const symbol s_11_62[9] = { 'k', 0xC3, 0xA4, 'i', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_63[6] = { 'k', 0xC3, 0xA4, 'i', 'm', 'a' }; +static const symbol s_11_64[8] = { 'k', 0xC3, 0xA4, 'i', 'm', 'a', 't', 'a' }; +static const symbol s_11_65[6] = { 'k', 0xC3, 0xA4, 'i', 'm', 'e' }; +static const symbol s_11_66[5] = { 'k', 0xC3, 0xA4, 'i', 'n' }; +static const symbol s_11_67[5] = { 'k', 0xC3, 0xA4, 'i', 's' }; +static const symbol s_11_68[6] = { 'k', 0xC3, 0xA4, 'i', 't', 'e' }; +static const symbol s_11_69[7] = { 'k', 0xC3, 0xA4, 'i', 'v', 'a', 'd' }; +static const symbol s_11_70[4] = { 'l', 'a', 'o', 'b' }; +static const symbol s_11_71[4] = { 'l', 'a', 'o', 'd' }; +static const symbol s_11_72[5] = { 'l', 'a', 'o', 'k', 's' }; +static const symbol s_11_73[7] = { 'l', 'a', 'o', 'k', 's', 'i', 'd' }; +static const symbol s_11_74[8] = { 'l', 'a', 'o', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_75[7] = { 'l', 'a', 'o', 'k', 's', 'i', 'n' }; +static const symbol s_11_76[8] = { 'l', 'a', 'o', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_77[5] = { 'l', 'a', 'o', 'm', 'e' }; +static const symbol s_11_78[4] = { 'l', 'a', 'o', 'n' }; +static const symbol s_11_79[5] = { 'l', 'a', 'o', 't', 'e' }; +static const symbol s_11_80[6] = { 'l', 'a', 'o', 'v', 'a', 'd' }; +static const symbol s_11_81[4] = { 'l', 'o', 'e', 'b' }; +static const symbol s_11_82[4] = { 'l', 'o', 'e', 'd' }; +static const symbol s_11_83[5] = { 'l', 'o', 'e', 'k', 's' }; +static const symbol s_11_84[7] = { 'l', 'o', 'e', 'k', 's', 'i', 'd' }; +static const symbol s_11_85[8] = { 'l', 'o', 'e', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_86[7] = { 'l', 'o', 'e', 'k', 's', 'i', 'n' }; +static const symbol s_11_87[8] = { 'l', 'o', 'e', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_88[5] = { 'l', 'o', 'e', 'm', 'e' }; +static const symbol s_11_89[4] = { 'l', 'o', 'e', 'n' }; +static const symbol s_11_90[5] = { 'l', 'o', 'e', 't', 'e' }; +static const symbol s_11_91[6] = { 'l', 'o', 'e', 'v', 'a', 'd' }; +static const symbol s_11_92[4] = { 'l', 'o', 'o', 'b' }; +static const symbol s_11_93[4] = { 'l', 'o', 'o', 'd' }; +static const symbol s_11_94[5] = { 'l', 'o', 'o', 'd', 'i' }; +static const symbol s_11_95[5] = { 'l', 'o', 'o', 'k', 's' }; +static const symbol s_11_96[7] = { 'l', 'o', 'o', 'k', 's', 'i', 'd' }; +static const symbol s_11_97[8] = { 'l', 'o', 'o', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_98[7] = { 'l', 'o', 'o', 'k', 's', 'i', 'n' }; +static const symbol s_11_99[8] = { 'l', 'o', 'o', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_100[5] = { 'l', 'o', 'o', 'm', 'a' }; +static const symbol s_11_101[7] = { 'l', 'o', 'o', 'm', 'a', 't', 'a' }; +static const symbol s_11_102[5] = { 'l', 'o', 'o', 'm', 'e' }; +static const symbol s_11_103[4] = { 'l', 'o', 'o', 'n' }; +static const symbol s_11_104[5] = { 'l', 'o', 'o', 't', 'e' }; +static const symbol s_11_105[6] = { 'l', 'o', 'o', 'v', 'a', 'd' }; +static const symbol s_11_106[4] = { 'l', 'u', 'u', 'a' }; +static const symbol s_11_107[7] = { 'l', 'u', 'u', 'a', 'k', 's', 'e' }; +static const symbol s_11_108[4] = { 'l', 0xC3, 0xB5, 'i' }; +static const symbol s_11_109[5] = { 'l', 0xC3, 0xB5, 'i', 'd' }; +static const symbol s_11_110[6] = { 'l', 0xC3, 0xB5, 'i', 'm', 'e' }; +static const symbol s_11_111[5] = { 'l', 0xC3, 0xB5, 'i', 'n' }; +static const symbol s_11_112[6] = { 'l', 0xC3, 0xB5, 'i', 't', 'e' }; +static const symbol s_11_113[6] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'b' }; +static const symbol s_11_114[6] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'd' }; +static const symbol s_11_115[10] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_116[7] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'd', 'i' }; +static const symbol s_11_117[7] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's' }; +static const symbol s_11_118[9] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'd' }; +static const symbol s_11_119[10] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_120[9] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'n' }; +static const symbol s_11_121[10] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_122[7] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'a' }; +static const symbol s_11_123[9] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'a', 't', 'a' }; +static const symbol s_11_124[7] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'e' }; +static const symbol s_11_125[6] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'n' }; +static const symbol s_11_126[7] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 't', 'e' }; +static const symbol s_11_127[8] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6, 'v', 'a', 'd' }; +static const symbol s_11_128[6] = { 'l', 0xC3, 0xBC, 0xC3, 0xBC, 'a' }; +static const symbol s_11_129[9] = { 'l', 0xC3, 0xBC, 0xC3, 0xBC, 'a', 'k', 's', 'e' }; +static const symbol s_11_130[6] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'a' }; +static const symbol s_11_131[9] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'a', 'k', 's', 'e' }; +static const symbol s_11_132[6] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'b' }; +static const symbol s_11_133[6] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'd' }; +static const symbol s_11_134[7] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'd', 'i' }; +static const symbol s_11_135[7] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'k', 's' }; +static const symbol s_11_136[9] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'k', 's', 'i', 'd' }; +static const symbol s_11_137[10] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_138[9] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'k', 's', 'i', 'n' }; +static const symbol s_11_139[10] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_140[7] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'm', 'a' }; +static const symbol s_11_141[9] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'm', 'a', 't', 'a' }; +static const symbol s_11_142[7] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'm', 'e' }; +static const symbol s_11_143[6] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'n' }; +static const symbol s_11_144[6] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 's' }; +static const symbol s_11_145[7] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 't', 'e' }; +static const symbol s_11_146[8] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 'v', 'a', 'd' }; +static const symbol s_11_147[5] = { 'n', 0xC3, 0xA4, 'e', 'b' }; +static const symbol s_11_148[5] = { 'n', 0xC3, 0xA4, 'e', 'd' }; +static const symbol s_11_149[6] = { 'n', 0xC3, 0xA4, 'e', 'k', 's' }; +static const symbol s_11_150[8] = { 'n', 0xC3, 0xA4, 'e', 'k', 's', 'i', 'd' }; +static const symbol s_11_151[9] = { 'n', 0xC3, 0xA4, 'e', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_152[8] = { 'n', 0xC3, 0xA4, 'e', 'k', 's', 'i', 'n' }; +static const symbol s_11_153[9] = { 'n', 0xC3, 0xA4, 'e', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_154[6] = { 'n', 0xC3, 0xA4, 'e', 'm', 'e' }; +static const symbol s_11_155[5] = { 'n', 0xC3, 0xA4, 'e', 'n' }; +static const symbol s_11_156[6] = { 'n', 0xC3, 0xA4, 'e', 't', 'e' }; +static const symbol s_11_157[7] = { 'n', 0xC3, 0xA4, 'e', 'v', 'a', 'd' }; +static const symbol s_11_158[7] = { 'n', 0xC3, 0xA4, 'g', 'e', 'm', 'a' }; +static const symbol s_11_159[9] = { 'n', 0xC3, 0xA4, 'g', 'e', 'm', 'a', 't', 'a' }; +static const symbol s_11_160[5] = { 'n', 0xC3, 0xA4, 'h', 'a' }; +static const symbol s_11_161[8] = { 'n', 0xC3, 0xA4, 'h', 'a', 'k', 's', 'e' }; +static const symbol s_11_162[6] = { 'n', 0xC3, 0xA4, 'h', 't', 'i' }; +static const symbol s_11_163[5] = { 'p', 0xC3, 0xB5, 'e', 'b' }; +static const symbol s_11_164[5] = { 'p', 0xC3, 0xB5, 'e', 'd' }; +static const symbol s_11_165[6] = { 'p', 0xC3, 0xB5, 'e', 'k', 's' }; +static const symbol s_11_166[8] = { 'p', 0xC3, 0xB5, 'e', 'k', 's', 'i', 'd' }; +static const symbol s_11_167[9] = { 'p', 0xC3, 0xB5, 'e', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_168[8] = { 'p', 0xC3, 0xB5, 'e', 'k', 's', 'i', 'n' }; +static const symbol s_11_169[9] = { 'p', 0xC3, 0xB5, 'e', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_170[6] = { 'p', 0xC3, 0xB5, 'e', 'm', 'e' }; +static const symbol s_11_171[5] = { 'p', 0xC3, 0xB5, 'e', 'n' }; +static const symbol s_11_172[6] = { 'p', 0xC3, 0xB5, 'e', 't', 'e' }; +static const symbol s_11_173[7] = { 'p', 0xC3, 0xB5, 'e', 'v', 'a', 'd' }; +static const symbol s_11_174[4] = { 's', 'a', 'a', 'b' }; +static const symbol s_11_175[4] = { 's', 'a', 'a', 'd' }; +static const symbol s_11_176[5] = { 's', 'a', 'a', 'd', 'a' }; +static const symbol s_11_177[8] = { 's', 'a', 'a', 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_178[5] = { 's', 'a', 'a', 'd', 'i' }; +static const symbol s_11_179[5] = { 's', 'a', 'a', 'k', 's' }; +static const symbol s_11_180[7] = { 's', 'a', 'a', 'k', 's', 'i', 'd' }; +static const symbol s_11_181[8] = { 's', 'a', 'a', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_182[7] = { 's', 'a', 'a', 'k', 's', 'i', 'n' }; +static const symbol s_11_183[8] = { 's', 'a', 'a', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_184[5] = { 's', 'a', 'a', 'm', 'a' }; +static const symbol s_11_185[7] = { 's', 'a', 'a', 'm', 'a', 't', 'a' }; +static const symbol s_11_186[5] = { 's', 'a', 'a', 'm', 'e' }; +static const symbol s_11_187[4] = { 's', 'a', 'a', 'n' }; +static const symbol s_11_188[5] = { 's', 'a', 'a', 't', 'e' }; +static const symbol s_11_189[6] = { 's', 'a', 'a', 'v', 'a', 'd' }; +static const symbol s_11_190[3] = { 's', 'a', 'i' }; +static const symbol s_11_191[4] = { 's', 'a', 'i', 'd' }; +static const symbol s_11_192[5] = { 's', 'a', 'i', 'm', 'e' }; +static const symbol s_11_193[4] = { 's', 'a', 'i', 'n' }; +static const symbol s_11_194[5] = { 's', 'a', 'i', 't', 'e' }; +static const symbol s_11_195[4] = { 's', 0xC3, 0xB5, 'i' }; +static const symbol s_11_196[5] = { 's', 0xC3, 0xB5, 'i', 'd' }; +static const symbol s_11_197[6] = { 's', 0xC3, 0xB5, 'i', 'm', 'e' }; +static const symbol s_11_198[5] = { 's', 0xC3, 0xB5, 'i', 'n' }; +static const symbol s_11_199[6] = { 's', 0xC3, 0xB5, 'i', 't', 'e' }; +static const symbol s_11_200[6] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'b' }; +static const symbol s_11_201[6] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'd' }; +static const symbol s_11_202[10] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_203[7] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'd', 'i' }; +static const symbol s_11_204[7] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's' }; +static const symbol s_11_205[9] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'd' }; +static const symbol s_11_206[10] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_207[9] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 'n' }; +static const symbol s_11_208[10] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_209[7] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'a' }; +static const symbol s_11_210[9] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'a', 't', 'a' }; +static const symbol s_11_211[7] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'm', 'e' }; +static const symbol s_11_212[6] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'n' }; +static const symbol s_11_213[7] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 't', 'e' }; +static const symbol s_11_214[8] = { 's', 0xC3, 0xB6, 0xC3, 0xB6, 'v', 'a', 'd' }; +static const symbol s_11_215[6] = { 's', 0xC3, 0xBC, 0xC3, 0xBC, 'a' }; +static const symbol s_11_216[9] = { 's', 0xC3, 0xBC, 0xC3, 0xBC, 'a', 'k', 's', 'e' }; +static const symbol s_11_217[4] = { 't', 'e', 'e', 'b' }; +static const symbol s_11_218[4] = { 't', 'e', 'e', 'd' }; +static const symbol s_11_219[5] = { 't', 'e', 'e', 'k', 's' }; +static const symbol s_11_220[7] = { 't', 'e', 'e', 'k', 's', 'i', 'd' }; +static const symbol s_11_221[8] = { 't', 'e', 'e', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_222[7] = { 't', 'e', 'e', 'k', 's', 'i', 'n' }; +static const symbol s_11_223[8] = { 't', 'e', 'e', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_224[5] = { 't', 'e', 'e', 'm', 'e' }; +static const symbol s_11_225[4] = { 't', 'e', 'e', 'n' }; +static const symbol s_11_226[5] = { 't', 'e', 'e', 't', 'e' }; +static const symbol s_11_227[6] = { 't', 'e', 'e', 'v', 'a', 'd' }; +static const symbol s_11_228[6] = { 't', 'e', 'g', 'e', 'm', 'a' }; +static const symbol s_11_229[8] = { 't', 'e', 'g', 'e', 'm', 'a', 't', 'a' }; +static const symbol s_11_230[4] = { 't', 'e', 'h', 'a' }; +static const symbol s_11_231[7] = { 't', 'e', 'h', 'a', 'k', 's', 'e' }; +static const symbol s_11_232[5] = { 't', 'e', 'h', 't', 'i' }; +static const symbol s_11_233[4] = { 't', 'o', 'o', 'b' }; +static const symbol s_11_234[4] = { 't', 'o', 'o', 'd' }; +static const symbol s_11_235[5] = { 't', 'o', 'o', 'd', 'i' }; +static const symbol s_11_236[5] = { 't', 'o', 'o', 'k', 's' }; +static const symbol s_11_237[7] = { 't', 'o', 'o', 'k', 's', 'i', 'd' }; +static const symbol s_11_238[8] = { 't', 'o', 'o', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_239[7] = { 't', 'o', 'o', 'k', 's', 'i', 'n' }; +static const symbol s_11_240[8] = { 't', 'o', 'o', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_241[5] = { 't', 'o', 'o', 'm', 'a' }; +static const symbol s_11_242[7] = { 't', 'o', 'o', 'm', 'a', 't', 'a' }; +static const symbol s_11_243[5] = { 't', 'o', 'o', 'm', 'e' }; +static const symbol s_11_244[4] = { 't', 'o', 'o', 'n' }; +static const symbol s_11_245[5] = { 't', 'o', 'o', 't', 'e' }; +static const symbol s_11_246[6] = { 't', 'o', 'o', 'v', 'a', 'd' }; +static const symbol s_11_247[4] = { 't', 'u', 'u', 'a' }; +static const symbol s_11_248[7] = { 't', 'u', 'u', 'a', 'k', 's', 'e' }; +static const symbol s_11_249[4] = { 't', 0xC3, 0xB5, 'i' }; +static const symbol s_11_250[5] = { 't', 0xC3, 0xB5, 'i', 'd' }; +static const symbol s_11_251[6] = { 't', 0xC3, 0xB5, 'i', 'm', 'e' }; +static const symbol s_11_252[5] = { 't', 0xC3, 0xB5, 'i', 'n' }; +static const symbol s_11_253[6] = { 't', 0xC3, 0xB5, 'i', 't', 'e' }; +static const symbol s_11_254[4] = { 'v', 'i', 'i', 'a' }; +static const symbol s_11_255[7] = { 'v', 'i', 'i', 'a', 'k', 's', 'e' }; +static const symbol s_11_256[4] = { 'v', 'i', 'i', 'b' }; +static const symbol s_11_257[4] = { 'v', 'i', 'i', 'd' }; +static const symbol s_11_258[5] = { 'v', 'i', 'i', 'd', 'i' }; +static const symbol s_11_259[5] = { 'v', 'i', 'i', 'k', 's' }; +static const symbol s_11_260[7] = { 'v', 'i', 'i', 'k', 's', 'i', 'd' }; +static const symbol s_11_261[8] = { 'v', 'i', 'i', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_262[7] = { 'v', 'i', 'i', 'k', 's', 'i', 'n' }; +static const symbol s_11_263[8] = { 'v', 'i', 'i', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_264[5] = { 'v', 'i', 'i', 'm', 'a' }; +static const symbol s_11_265[7] = { 'v', 'i', 'i', 'm', 'a', 't', 'a' }; +static const symbol s_11_266[5] = { 'v', 'i', 'i', 'm', 'e' }; +static const symbol s_11_267[4] = { 'v', 'i', 'i', 'n' }; +static const symbol s_11_268[7] = { 'v', 'i', 'i', 's', 'i', 'm', 'e' }; +static const symbol s_11_269[6] = { 'v', 'i', 'i', 's', 'i', 'n' }; +static const symbol s_11_270[7] = { 'v', 'i', 'i', 's', 'i', 't', 'e' }; +static const symbol s_11_271[5] = { 'v', 'i', 'i', 't', 'e' }; +static const symbol s_11_272[6] = { 'v', 'i', 'i', 'v', 'a', 'd' }; +static const symbol s_11_273[5] = { 'v', 0xC3, 0xB5, 'i', 'b' }; +static const symbol s_11_274[5] = { 'v', 0xC3, 0xB5, 'i', 'd' }; +static const symbol s_11_275[6] = { 'v', 0xC3, 0xB5, 'i', 'd', 'a' }; +static const symbol s_11_276[9] = { 'v', 0xC3, 0xB5, 'i', 'd', 'a', 'k', 's', 'e' }; +static const symbol s_11_277[6] = { 'v', 0xC3, 0xB5, 'i', 'd', 'i' }; +static const symbol s_11_278[6] = { 'v', 0xC3, 0xB5, 'i', 'k', 's' }; +static const symbol s_11_279[8] = { 'v', 0xC3, 0xB5, 'i', 'k', 's', 'i', 'd' }; +static const symbol s_11_280[9] = { 'v', 0xC3, 0xB5, 'i', 'k', 's', 'i', 'm', 'e' }; +static const symbol s_11_281[8] = { 'v', 0xC3, 0xB5, 'i', 'k', 's', 'i', 'n' }; +static const symbol s_11_282[9] = { 'v', 0xC3, 0xB5, 'i', 'k', 's', 'i', 't', 'e' }; +static const symbol s_11_283[6] = { 'v', 0xC3, 0xB5, 'i', 'm', 'a' }; +static const symbol s_11_284[8] = { 'v', 0xC3, 0xB5, 'i', 'm', 'a', 't', 'a' }; +static const symbol s_11_285[6] = { 'v', 0xC3, 0xB5, 'i', 'm', 'e' }; +static const symbol s_11_286[5] = { 'v', 0xC3, 0xB5, 'i', 'n' }; +static const symbol s_11_287[5] = { 'v', 0xC3, 0xB5, 'i', 's' }; +static const symbol s_11_288[6] = { 'v', 0xC3, 0xB5, 'i', 't', 'e' }; +static const symbol s_11_289[7] = { 'v', 0xC3, 0xB5, 'i', 'v', 'a', 'd' }; + +static const struct among a_11[290] = +{ +{ 4, s_11_0, -1, 1, 0}, +{ 4, s_11_1, -1, 1, 0}, +{ 8, s_11_2, 1, 1, 0}, +{ 5, s_11_3, -1, 1, 0}, +{ 7, s_11_4, 3, 1, 0}, +{ 5, s_11_5, -1, 1, 0}, +{ 4, s_11_6, -1, 1, 0}, +{ 5, s_11_7, -1, 1, 0}, +{ 6, s_11_8, -1, 1, 0}, +{ 4, s_11_9, -1, 1, 0}, +{ 7, s_11_10, 9, 1, 0}, +{ 4, s_11_11, -1, 12, 0}, +{ 5, s_11_12, 11, 12, 0}, +{ 6, s_11_13, 11, 12, 0}, +{ 5, s_11_14, 11, 12, 0}, +{ 6, s_11_15, 11, 12, 0}, +{ 6, s_11_16, -1, 12, 0}, +{ 6, s_11_17, -1, 12, 0}, +{ 7, s_11_18, 17, 12, 0}, +{ 10, s_11_19, 18, 12, 0}, +{ 7, s_11_20, 17, 12, 0}, +{ 7, s_11_21, -1, 12, 0}, +{ 9, s_11_22, 21, 12, 0}, +{ 10, s_11_23, 21, 12, 0}, +{ 9, s_11_24, 21, 12, 0}, +{ 10, s_11_25, 21, 12, 0}, +{ 7, s_11_26, -1, 12, 0}, +{ 9, s_11_27, 26, 12, 0}, +{ 7, s_11_28, -1, 12, 0}, +{ 6, s_11_29, -1, 12, 0}, +{ 7, s_11_30, -1, 12, 0}, +{ 8, s_11_31, -1, 12, 0}, +{ 4, s_11_32, -1, 1, 0}, +{ 5, s_11_33, 32, 1, 0}, +{ 6, s_11_34, 32, 1, 0}, +{ 5, s_11_35, 32, 1, 0}, +{ 6, s_11_36, 32, 1, 0}, +{ 4, s_11_37, -1, 4, 0}, +{ 4, s_11_38, -1, 4, 0}, +{ 8, s_11_39, 38, 4, 0}, +{ 5, s_11_40, -1, 4, 0}, +{ 7, s_11_41, 40, 4, 0}, +{ 8, s_11_42, 40, 4, 0}, +{ 7, s_11_43, 40, 4, 0}, +{ 8, s_11_44, 40, 4, 0}, +{ 5, s_11_45, -1, 4, 0}, +{ 7, s_11_46, 45, 4, 0}, +{ 5, s_11_47, -1, 4, 0}, +{ 4, s_11_48, -1, 4, 0}, +{ 4, s_11_49, -1, 4, 0}, +{ 5, s_11_50, -1, 4, 0}, +{ 5, s_11_51, -1, 4, 0}, +{ 6, s_11_52, -1, 4, 0}, +{ 5, s_11_53, -1, 8, 0}, +{ 8, s_11_54, 53, 8, 0}, +{ 5, s_11_55, -1, 8, 0}, +{ 5, s_11_56, -1, 8, 0}, +{ 6, s_11_57, 56, 8, 0}, +{ 6, s_11_58, -1, 8, 0}, +{ 8, s_11_59, 58, 8, 0}, +{ 9, s_11_60, 58, 8, 0}, +{ 8, s_11_61, 58, 8, 0}, +{ 9, s_11_62, 58, 8, 0}, +{ 6, s_11_63, -1, 8, 0}, +{ 8, s_11_64, 63, 8, 0}, +{ 6, s_11_65, -1, 8, 0}, +{ 5, s_11_66, -1, 8, 0}, +{ 5, s_11_67, -1, 8, 0}, +{ 6, s_11_68, -1, 8, 0}, +{ 7, s_11_69, -1, 8, 0}, +{ 4, s_11_70, -1, 16, 0}, +{ 4, s_11_71, -1, 16, 0}, +{ 5, s_11_72, -1, 16, 0}, +{ 7, s_11_73, 72, 16, 0}, +{ 8, s_11_74, 72, 16, 0}, +{ 7, s_11_75, 72, 16, 0}, +{ 8, s_11_76, 72, 16, 0}, +{ 5, s_11_77, -1, 16, 0}, +{ 4, s_11_78, -1, 16, 0}, +{ 5, s_11_79, -1, 16, 0}, +{ 6, s_11_80, -1, 16, 0}, +{ 4, s_11_81, -1, 14, 0}, +{ 4, s_11_82, -1, 14, 0}, +{ 5, s_11_83, -1, 14, 0}, +{ 7, s_11_84, 83, 14, 0}, +{ 8, s_11_85, 83, 14, 0}, +{ 7, s_11_86, 83, 14, 0}, +{ 8, s_11_87, 83, 14, 0}, +{ 5, s_11_88, -1, 14, 0}, +{ 4, s_11_89, -1, 14, 0}, +{ 5, s_11_90, -1, 14, 0}, +{ 6, s_11_91, -1, 14, 0}, +{ 4, s_11_92, -1, 7, 0}, +{ 4, s_11_93, -1, 7, 0}, +{ 5, s_11_94, 93, 7, 0}, +{ 5, s_11_95, -1, 7, 0}, +{ 7, s_11_96, 95, 7, 0}, +{ 8, s_11_97, 95, 7, 0}, +{ 7, s_11_98, 95, 7, 0}, +{ 8, s_11_99, 95, 7, 0}, +{ 5, s_11_100, -1, 7, 0}, +{ 7, s_11_101, 100, 7, 0}, +{ 5, s_11_102, -1, 7, 0}, +{ 4, s_11_103, -1, 7, 0}, +{ 5, s_11_104, -1, 7, 0}, +{ 6, s_11_105, -1, 7, 0}, +{ 4, s_11_106, -1, 7, 0}, +{ 7, s_11_107, 106, 7, 0}, +{ 4, s_11_108, -1, 6, 0}, +{ 5, s_11_109, 108, 6, 0}, +{ 6, s_11_110, 108, 6, 0}, +{ 5, s_11_111, 108, 6, 0}, +{ 6, s_11_112, 108, 6, 0}, +{ 6, s_11_113, -1, 5, 0}, +{ 6, s_11_114, -1, 5, 0}, +{ 10, s_11_115, 114, 5, 0}, +{ 7, s_11_116, 114, 5, 0}, +{ 7, s_11_117, -1, 5, 0}, +{ 9, s_11_118, 117, 5, 0}, +{ 10, s_11_119, 117, 5, 0}, +{ 9, s_11_120, 117, 5, 0}, +{ 10, s_11_121, 117, 5, 0}, +{ 7, s_11_122, -1, 5, 0}, +{ 9, s_11_123, 122, 5, 0}, +{ 7, s_11_124, -1, 5, 0}, +{ 6, s_11_125, -1, 5, 0}, +{ 7, s_11_126, -1, 5, 0}, +{ 8, s_11_127, -1, 5, 0}, +{ 6, s_11_128, -1, 5, 0}, +{ 9, s_11_129, 128, 5, 0}, +{ 6, s_11_130, -1, 13, 0}, +{ 9, s_11_131, 130, 13, 0}, +{ 6, s_11_132, -1, 13, 0}, +{ 6, s_11_133, -1, 13, 0}, +{ 7, s_11_134, 133, 13, 0}, +{ 7, s_11_135, -1, 13, 0}, +{ 9, s_11_136, 135, 13, 0}, +{ 10, s_11_137, 135, 13, 0}, +{ 9, s_11_138, 135, 13, 0}, +{ 10, s_11_139, 135, 13, 0}, +{ 7, s_11_140, -1, 13, 0}, +{ 9, s_11_141, 140, 13, 0}, +{ 7, s_11_142, -1, 13, 0}, +{ 6, s_11_143, -1, 13, 0}, +{ 6, s_11_144, -1, 13, 0}, +{ 7, s_11_145, -1, 13, 0}, +{ 8, s_11_146, -1, 13, 0}, +{ 5, s_11_147, -1, 18, 0}, +{ 5, s_11_148, -1, 18, 0}, +{ 6, s_11_149, -1, 18, 0}, +{ 8, s_11_150, 149, 18, 0}, +{ 9, s_11_151, 149, 18, 0}, +{ 8, s_11_152, 149, 18, 0}, +{ 9, s_11_153, 149, 18, 0}, +{ 6, s_11_154, -1, 18, 0}, +{ 5, s_11_155, -1, 18, 0}, +{ 6, s_11_156, -1, 18, 0}, +{ 7, s_11_157, -1, 18, 0}, +{ 7, s_11_158, -1, 18, 0}, +{ 9, s_11_159, 158, 18, 0}, +{ 5, s_11_160, -1, 18, 0}, +{ 8, s_11_161, 160, 18, 0}, +{ 6, s_11_162, -1, 18, 0}, +{ 5, s_11_163, -1, 15, 0}, +{ 5, s_11_164, -1, 15, 0}, +{ 6, s_11_165, -1, 15, 0}, +{ 8, s_11_166, 165, 15, 0}, +{ 9, s_11_167, 165, 15, 0}, +{ 8, s_11_168, 165, 15, 0}, +{ 9, s_11_169, 165, 15, 0}, +{ 6, s_11_170, -1, 15, 0}, +{ 5, s_11_171, -1, 15, 0}, +{ 6, s_11_172, -1, 15, 0}, +{ 7, s_11_173, -1, 15, 0}, +{ 4, s_11_174, -1, 2, 0}, +{ 4, s_11_175, -1, 2, 0}, +{ 5, s_11_176, 175, 2, 0}, +{ 8, s_11_177, 176, 2, 0}, +{ 5, s_11_178, 175, 2, 0}, +{ 5, s_11_179, -1, 2, 0}, +{ 7, s_11_180, 179, 2, 0}, +{ 8, s_11_181, 179, 2, 0}, +{ 7, s_11_182, 179, 2, 0}, +{ 8, s_11_183, 179, 2, 0}, +{ 5, s_11_184, -1, 2, 0}, +{ 7, s_11_185, 184, 2, 0}, +{ 5, s_11_186, -1, 2, 0}, +{ 4, s_11_187, -1, 2, 0}, +{ 5, s_11_188, -1, 2, 0}, +{ 6, s_11_189, -1, 2, 0}, +{ 3, s_11_190, -1, 2, 0}, +{ 4, s_11_191, 190, 2, 0}, +{ 5, s_11_192, 190, 2, 0}, +{ 4, s_11_193, 190, 2, 0}, +{ 5, s_11_194, 190, 2, 0}, +{ 4, s_11_195, -1, 9, 0}, +{ 5, s_11_196, 195, 9, 0}, +{ 6, s_11_197, 195, 9, 0}, +{ 5, s_11_198, 195, 9, 0}, +{ 6, s_11_199, 195, 9, 0}, +{ 6, s_11_200, -1, 9, 0}, +{ 6, s_11_201, -1, 9, 0}, +{ 10, s_11_202, 201, 9, 0}, +{ 7, s_11_203, 201, 9, 0}, +{ 7, s_11_204, -1, 9, 0}, +{ 9, s_11_205, 204, 9, 0}, +{ 10, s_11_206, 204, 9, 0}, +{ 9, s_11_207, 204, 9, 0}, +{ 10, s_11_208, 204, 9, 0}, +{ 7, s_11_209, -1, 9, 0}, +{ 9, s_11_210, 209, 9, 0}, +{ 7, s_11_211, -1, 9, 0}, +{ 6, s_11_212, -1, 9, 0}, +{ 7, s_11_213, -1, 9, 0}, +{ 8, s_11_214, -1, 9, 0}, +{ 6, s_11_215, -1, 9, 0}, +{ 9, s_11_216, 215, 9, 0}, +{ 4, s_11_217, -1, 17, 0}, +{ 4, s_11_218, -1, 17, 0}, +{ 5, s_11_219, -1, 17, 0}, +{ 7, s_11_220, 219, 17, 0}, +{ 8, s_11_221, 219, 17, 0}, +{ 7, s_11_222, 219, 17, 0}, +{ 8, s_11_223, 219, 17, 0}, +{ 5, s_11_224, -1, 17, 0}, +{ 4, s_11_225, -1, 17, 0}, +{ 5, s_11_226, -1, 17, 0}, +{ 6, s_11_227, -1, 17, 0}, +{ 6, s_11_228, -1, 17, 0}, +{ 8, s_11_229, 228, 17, 0}, +{ 4, s_11_230, -1, 17, 0}, +{ 7, s_11_231, 230, 17, 0}, +{ 5, s_11_232, -1, 17, 0}, +{ 4, s_11_233, -1, 10, 0}, +{ 4, s_11_234, -1, 10, 0}, +{ 5, s_11_235, 234, 10, 0}, +{ 5, s_11_236, -1, 10, 0}, +{ 7, s_11_237, 236, 10, 0}, +{ 8, s_11_238, 236, 10, 0}, +{ 7, s_11_239, 236, 10, 0}, +{ 8, s_11_240, 236, 10, 0}, +{ 5, s_11_241, -1, 10, 0}, +{ 7, s_11_242, 241, 10, 0}, +{ 5, s_11_243, -1, 10, 0}, +{ 4, s_11_244, -1, 10, 0}, +{ 5, s_11_245, -1, 10, 0}, +{ 6, s_11_246, -1, 10, 0}, +{ 4, s_11_247, -1, 10, 0}, +{ 7, s_11_248, 247, 10, 0}, +{ 4, s_11_249, -1, 10, 0}, +{ 5, s_11_250, 249, 10, 0}, +{ 6, s_11_251, 249, 10, 0}, +{ 5, s_11_252, 249, 10, 0}, +{ 6, s_11_253, 249, 10, 0}, +{ 4, s_11_254, -1, 3, 0}, +{ 7, s_11_255, 254, 3, 0}, +{ 4, s_11_256, -1, 3, 0}, +{ 4, s_11_257, -1, 3, 0}, +{ 5, s_11_258, 257, 3, 0}, +{ 5, s_11_259, -1, 3, 0}, +{ 7, s_11_260, 259, 3, 0}, +{ 8, s_11_261, 259, 3, 0}, +{ 7, s_11_262, 259, 3, 0}, +{ 8, s_11_263, 259, 3, 0}, +{ 5, s_11_264, -1, 3, 0}, +{ 7, s_11_265, 264, 3, 0}, +{ 5, s_11_266, -1, 3, 0}, +{ 4, s_11_267, -1, 3, 0}, +{ 7, s_11_268, -1, 3, 0}, +{ 6, s_11_269, -1, 3, 0}, +{ 7, s_11_270, -1, 3, 0}, +{ 5, s_11_271, -1, 3, 0}, +{ 6, s_11_272, -1, 3, 0}, +{ 5, s_11_273, -1, 11, 0}, +{ 5, s_11_274, -1, 11, 0}, +{ 6, s_11_275, 274, 11, 0}, +{ 9, s_11_276, 275, 11, 0}, +{ 6, s_11_277, 274, 11, 0}, +{ 6, s_11_278, -1, 11, 0}, +{ 8, s_11_279, 278, 11, 0}, +{ 9, s_11_280, 278, 11, 0}, +{ 8, s_11_281, 278, 11, 0}, +{ 9, s_11_282, 278, 11, 0}, +{ 6, s_11_283, -1, 11, 0}, +{ 8, s_11_284, 283, 11, 0}, +{ 6, s_11_285, -1, 11, 0}, +{ 5, s_11_286, -1, 11, 0}, +{ 5, s_11_287, -1, 11, 0}, +{ 6, s_11_288, -1, 11, 0}, +{ 7, s_11_289, -1, 11, 0} +}; + +static const unsigned char g_V1[] = { 17, 65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 48, 8 }; + +static const unsigned char g_RV[] = { 17, 65, 16 }; + +static const unsigned char g_KI[] = { 117, 66, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 16 }; + +static const unsigned char g_GI[] = { 21, 123, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 48, 8 }; + +static const symbol s_0[] = { 'a' }; +static const symbol s_1[] = { 'l', 'a', 's', 'e' }; +static const symbol s_2[] = { 'm', 'i', 's', 'e' }; +static const symbol s_3[] = { 'l', 'i', 's', 'e' }; +static const symbol s_4[] = { 'i', 'k', 'u' }; +static const symbol s_5[] = { 'e' }; +static const symbol s_6[] = { 't' }; +static const symbol s_7[] = { 'k' }; +static const symbol s_8[] = { 'p' }; +static const symbol s_9[] = { 't' }; +static const symbol s_10[] = { 'j', 'o', 'o' }; +static const symbol s_11[] = { 's', 'a', 'a' }; +static const symbol s_12[] = { 'v', 'i', 'i', 'm', 'a' }; +static const symbol s_13[] = { 'k', 'e', 'e', 's', 'i' }; +static const symbol s_14[] = { 'l', 0xC3, 0xB6, 0xC3, 0xB6 }; +static const symbol s_15[] = { 'l', 0xC3, 0xB5, 'i' }; +static const symbol s_16[] = { 'l', 'o', 'o' }; +static const symbol s_17[] = { 'k', 0xC3, 0xA4, 'i', 's', 'i' }; +static const symbol s_18[] = { 's', 0xC3, 0xB6, 0xC3, 0xB6 }; +static const symbol s_19[] = { 't', 'o', 'o' }; +static const symbol s_20[] = { 'v', 0xC3, 0xB5, 'i', 's', 'i' }; +static const symbol s_21[] = { 'j', 0xC3, 0xA4, 0xC3, 0xA4, 'm', 'a' }; +static const symbol s_22[] = { 'm', 0xC3, 0xBC, 0xC3, 0xBC, 's', 'i' }; +static const symbol s_23[] = { 'l', 'u', 'g', 'e' }; +static const symbol s_24[] = { 'p', 0xC3, 0xB5, 'd', 'e' }; +static const symbol s_25[] = { 'l', 'a', 'd', 'u' }; +static const symbol s_26[] = { 't', 'e', 'g', 'i' }; +static const symbol s_27[] = { 'n', 0xC3, 0xA4, 'g', 'i' }; + +static int r_mark_regions(struct SN_env * z) { + z->I[0] = z->l; + + if (out_grouping_U(z, g_V1, 97, 252, 1) < 0) return 0; + + { + int ret = in_grouping_U(z, g_V1, 97, 252, 1); + if (ret < 0) return 0; + z->c += ret; + } + z->I[0] = z->c; + return 1; +} + +static int r_emphasis(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c - 1 <= z->lb || z->p[z->c - 1] != 105) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_0, 2); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + { int m_test2 = z->l - z->c; + { int ret = skip_b_utf8(z->p, z->c, z->lb, 4); + if (ret < 0) return 0; + z->c = ret; + } + z->c = z->l - m_test2; + } + switch (among_var) { + case 1: + { int m3 = z->l - z->c; (void)m3; + if (in_grouping_b_U(z, g_GI, 97, 252, 0)) return 0; + z->c = z->l - m3; + { int m4 = z->l - z->c; (void)m4; + { int ret = r_LONGV(z); + if (ret == 0) goto lab0; + if (ret < 0) return ret; + } + return 0; + lab0: + z->c = z->l - m4; + } + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + if (in_grouping_b_U(z, g_KI, 98, 382, 0)) return 0; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_verb(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((540726 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_1, 21); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 1, s_0); + if (ret < 0) return ret; + } + break; + case 3: + if (in_grouping_b_U(z, g_V1, 97, 252, 0)) return 0; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_LONGV(struct SN_env * z) { + if (!find_among_b(z, a_2, 9)) return 0; + return 1; +} + +static int r_i_plural(struct SN_env * z) { + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c <= z->lb || z->p[z->c - 1] != 105) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_3, 1)) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + if (in_grouping_b_U(z, g_RV, 97, 117, 0)) return 0; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + return 1; +} + +static int r_special_noun_endings(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c - 3 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1049120 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_4, 12); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 4, s_1); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 4, s_2); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 4, s_3); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_case_ending(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1576994 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_5, 10); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + switch (among_var) { + case 1: + { int m2 = z->l - z->c; (void)m2; + if (in_grouping_b_U(z, g_RV, 97, 117, 0)) goto lab1; + goto lab0; + lab1: + z->c = z->l - m2; + { int ret = r_LONGV(z); + if (ret <= 0) return ret; + } + } + lab0: + break; + case 2: + { int m_test3 = z->l - z->c; + { int ret = skip_b_utf8(z->p, z->c, z->lb, 4); + if (ret < 0) return 0; + z->c = ret; + } + z->c = z->l - m_test3; + } + break; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + return 1; +} + +static int r_plural_three_first_cases(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 101)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_7, 7); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 3, s_4); + if (ret < 0) return ret; + } + break; + case 2: + { int m2 = z->l - z->c; (void)m2; + { int ret = r_LONGV(z); + if (ret == 0) goto lab0; + if (ret < 0) return ret; + } + return 0; + lab0: + z->c = z->l - m2; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 3: + { int m3 = z->l - z->c; (void)m3; + { int m_test4 = z->l - z->c; + { int ret = skip_b_utf8(z->p, z->c, z->lb, 4); + if (ret < 0) goto lab2; + z->c = ret; + } + z->c = z->l - m_test4; + } + if (z->c <= z->lb || (z->p[z->c - 1] != 115 && z->p[z->c - 1] != 116)) among_var = 2; else + among_var = find_among_b(z, a_6, 5); + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 1, s_5); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + } + goto lab1; + lab2: + z->c = z->l - m3; + { int ret = slice_from_s(z, 1, s_6); + if (ret < 0) return ret; + } + } + lab1: + break; + case 4: + { int m5 = z->l - z->c; (void)m5; + if (in_grouping_b_U(z, g_RV, 97, 117, 0)) goto lab4; + goto lab3; + lab4: + z->c = z->l - m5; + { int ret = r_LONGV(z); + if (ret <= 0) return ret; + } + } + lab3: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_nu(struct SN_env * z) { + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 117)) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_8, 4)) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + return 1; +} + +static int r_undouble_kpt(struct SN_env * z) { + int among_var; + if (in_grouping_b_U(z, g_V1, 97, 252, 0)) return 0; + if (z->I[0] > z->c) return 0; + z->ket = z->c; + if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1116160 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; + among_var = find_among_b(z, a_9, 3); + if (!among_var) return 0; + z->bra = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 1, s_7); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 1, s_8); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 1, s_9); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_degrees(struct SN_env * z) { + int among_var; + + { int mlimit1; + if (z->c < z->I[0]) return 0; + mlimit1 = z->lb; z->lb = z->I[0]; + z->ket = z->c; + if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((8706 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_10, 3); + if (!among_var) { z->lb = mlimit1; return 0; } + z->bra = z->c; + z->lb = mlimit1; + } + switch (among_var) { + case 1: + if (in_grouping_b_U(z, g_RV, 97, 117, 0)) return 0; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +static int r_substantive(struct SN_env * z) { + { int m1 = z->l - z->c; (void)m1; + { int ret = r_special_noun_endings(z); + if (ret < 0) return ret; + } + z->c = z->l - m1; + } + { int m2 = z->l - z->c; (void)m2; + { int ret = r_case_ending(z); + if (ret < 0) return ret; + } + z->c = z->l - m2; + } + { int m3 = z->l - z->c; (void)m3; + { int ret = r_plural_three_first_cases(z); + if (ret < 0) return ret; + } + z->c = z->l - m3; + } + { int m4 = z->l - z->c; (void)m4; + { int ret = r_degrees(z); + if (ret < 0) return ret; + } + z->c = z->l - m4; + } + { int m5 = z->l - z->c; (void)m5; + { int ret = r_i_plural(z); + if (ret < 0) return ret; + } + z->c = z->l - m5; + } + { int m6 = z->l - z->c; (void)m6; + { int ret = r_nu(z); + if (ret < 0) return ret; + } + z->c = z->l - m6; + } + return 1; +} + +static int r_verb_exceptions(struct SN_env * z) { + int among_var; + z->bra = z->c; + among_var = find_among(z, a_11, 290); + if (!among_var) return 0; + z->ket = z->c; + if (z->c < z->l) return 0; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 3, s_10); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 3, s_11); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 5, s_12); + if (ret < 0) return ret; + } + break; + case 4: + { int ret = slice_from_s(z, 5, s_13); + if (ret < 0) return ret; + } + break; + case 5: + { int ret = slice_from_s(z, 5, s_14); + if (ret < 0) return ret; + } + break; + case 6: + { int ret = slice_from_s(z, 4, s_15); + if (ret < 0) return ret; + } + break; + case 7: + { int ret = slice_from_s(z, 3, s_16); + if (ret < 0) return ret; + } + break; + case 8: + { int ret = slice_from_s(z, 6, s_17); + if (ret < 0) return ret; + } + break; + case 9: + { int ret = slice_from_s(z, 5, s_18); + if (ret < 0) return ret; + } + break; + case 10: + { int ret = slice_from_s(z, 3, s_19); + if (ret < 0) return ret; + } + break; + case 11: + { int ret = slice_from_s(z, 6, s_20); + if (ret < 0) return ret; + } + break; + case 12: + { int ret = slice_from_s(z, 7, s_21); + if (ret < 0) return ret; + } + break; + case 13: + { int ret = slice_from_s(z, 7, s_22); + if (ret < 0) return ret; + } + break; + case 14: + { int ret = slice_from_s(z, 4, s_23); + if (ret < 0) return ret; + } + break; + case 15: + { int ret = slice_from_s(z, 5, s_24); + if (ret < 0) return ret; + } + break; + case 16: + { int ret = slice_from_s(z, 4, s_25); + if (ret < 0) return ret; + } + break; + case 17: + { int ret = slice_from_s(z, 4, s_26); + if (ret < 0) return ret; + } + break; + case 18: + { int ret = slice_from_s(z, 5, s_27); + if (ret < 0) return ret; + } + break; + } + return 1; +} + +extern int estonian_UTF_8_stem(struct SN_env * z) { + { int c1 = z->c; + { int ret = r_verb_exceptions(z); + if (ret == 0) goto lab0; + if (ret < 0) return ret; + } + return 0; + lab0: + z->c = c1; + } + { int c2 = z->c; + { int ret = r_mark_regions(z); + if (ret < 0) return ret; + } + z->c = c2; + } + z->lb = z->c; z->c = z->l; + + { int m3 = z->l - z->c; (void)m3; + { int ret = r_emphasis(z); + if (ret < 0) return ret; + } + z->c = z->l - m3; + } + { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; + { int ret = r_verb(z); + if (ret == 0) goto lab3; + if (ret < 0) return ret; + } + goto lab2; + lab3: + z->c = z->l - m5; + { int ret = r_substantive(z); + if (ret < 0) return ret; + } + } + lab2: + z->c = z->l - m4; + } + { int m6 = z->l - z->c; (void)m6; + { int ret = r_undouble_kpt(z); + if (ret < 0) return ret; + } + z->c = z->l - m6; + } + z->c = z->lb; + return 1; +} + +extern struct SN_env * estonian_UTF_8_create_env(void) { return SN_create_env(0, 1); } + +extern void estonian_UTF_8_close_env(struct SN_env * z) { SN_close_env(z, 0); } + diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_finnish.c b/src/backend/snowball/libstemmer/stem_UTF_8_finnish.c index 385933ddcc538..bd8f9520fa847 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_finnish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_finnish.c @@ -279,15 +279,19 @@ static const symbol s_6[] = { 'p', 'o' }; static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; + if (out_grouping_U(z, g_V1, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping_U(z, g_V1, 97, 246, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; + if (out_grouping_U(z, g_V1, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping_U(z, g_V1, 97, 246, 1); if (ret < 0) return 0; z->c += ret; @@ -297,8 +301,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_particle_etc(struct SN_env * z) { @@ -309,7 +312,7 @@ static int r_particle_etc(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_0, 10); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -337,7 +340,7 @@ static int r_possessive(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_4, 9); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -372,21 +375,21 @@ static int r_possessive(struct SN_env * z) { break; case 4: if (z->c - 1 <= z->lb || z->p[z->c - 1] != 97) return 0; - if (!(find_among_b(z, a_1, 6))) return 0; + if (!find_among_b(z, a_1, 6)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 5: if (z->c - 2 <= z->lb || z->p[z->c - 1] != 164) return 0; - if (!(find_among_b(z, a_2, 6))) return 0; + if (!find_among_b(z, a_2, 6)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } break; case 6: if (z->c - 2 <= z->lb || z->p[z->c - 1] != 101) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; { int ret = slice_del(z); if (ret < 0) return ret; } @@ -396,7 +399,7 @@ static int r_possessive(struct SN_env * z) { } static int r_LONG(struct SN_env * z) { - if (!(find_among_b(z, a_5, 7))) return 0; + if (!find_among_b(z, a_5, 7)) return 0; return 1; } @@ -415,7 +418,7 @@ static int r_case_ending(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; among_var = find_among_b(z, a_6, 30); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -487,7 +490,7 @@ static int r_other_endings(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[0]; z->ket = z->c; among_var = find_among_b(z, a_7, 14); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -514,7 +517,7 @@ static int r_i_plural(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 106)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_8, 2))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_8, 2)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -550,7 +553,7 @@ static int r_t_plural(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] != 97) { z->lb = mlimit3; return 0; } among_var = find_among_b(z, a_9, 2); - if (!(among_var)) { z->lb = mlimit3; return 0; } + if (!among_var) { z->lb = mlimit3; return 0; } z->bra = z->c; z->lb = mlimit3; } @@ -642,6 +645,7 @@ static int r_tidy(struct SN_env * z) { } z->lb = mlimit1; } + if (in_grouping_b_U(z, g_V1, 97, 246, 1) < 0) return 0; z->ket = z->c; if (in_grouping_b_U(z, g_C, 98, 122, 0)) return 0; @@ -689,7 +693,7 @@ extern int finnish_UTF_8_stem(struct SN_env * z) { } z->c = z->l - m5; } - + if (!(z->I[2])) goto lab1; { int m6 = z->l - z->c; (void)m6; { int ret = r_i_plural(z); diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_french.c b/src/backend/snowball/libstemmer/stem_UTF_8_french.c index 049d7c353b06a..de8685977ad40 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_french.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_french.c @@ -21,6 +21,7 @@ static int r_RV(struct SN_env * z); static int r_mark_regions(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_prelude(struct SN_env * z); +static int r_elisions(struct SN_env * z); #ifdef __cplusplus extern "C" { #endif @@ -371,48 +372,74 @@ static const struct among a_8[5] = static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 130, 103, 8, 5 }; +static const unsigned char g_elision_char[] = { 131, 14, 3 }; + static const unsigned char g_keep_with_s[] = { 1, 65, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 }; -static const symbol s_0[] = { 'U' }; -static const symbol s_1[] = { 'I' }; -static const symbol s_2[] = { 'Y' }; -static const symbol s_3[] = { 0xC3, 0xAB }; -static const symbol s_4[] = { 'H', 'e' }; -static const symbol s_5[] = { 0xC3, 0xAF }; -static const symbol s_6[] = { 'H', 'i' }; -static const symbol s_7[] = { 'Y' }; -static const symbol s_8[] = { 'U' }; -static const symbol s_9[] = { 'i' }; -static const symbol s_10[] = { 'u' }; -static const symbol s_11[] = { 'y' }; -static const symbol s_12[] = { 0xC3, 0xAB }; -static const symbol s_13[] = { 0xC3, 0xAF }; -static const symbol s_14[] = { 'i', 'c' }; -static const symbol s_15[] = { 'i', 'q', 'U' }; -static const symbol s_16[] = { 'l', 'o', 'g' }; -static const symbol s_17[] = { 'u' }; -static const symbol s_18[] = { 'e', 'n', 't' }; -static const symbol s_19[] = { 'a', 't' }; -static const symbol s_20[] = { 'e', 'u', 'x' }; -static const symbol s_21[] = { 'i' }; -static const symbol s_22[] = { 'a', 'b', 'l' }; -static const symbol s_23[] = { 'i', 'q', 'U' }; -static const symbol s_24[] = { 'a', 't' }; -static const symbol s_25[] = { 'i', 'c' }; -static const symbol s_26[] = { 'i', 'q', 'U' }; -static const symbol s_27[] = { 'e', 'a', 'u' }; -static const symbol s_28[] = { 'a', 'l' }; -static const symbol s_29[] = { 'e', 'u', 'x' }; -static const symbol s_30[] = { 'a', 'n', 't' }; -static const symbol s_31[] = { 'e', 'n', 't' }; -static const symbol s_32[] = { 'H', 'i' }; -static const symbol s_33[] = { 'i' }; -static const symbol s_34[] = { 0xC3, 0xA9 }; -static const symbol s_35[] = { 0xC3, 0xA8 }; -static const symbol s_36[] = { 'e' }; -static const symbol s_37[] = { 'i' }; -static const symbol s_38[] = { 0xC3, 0xA7 }; -static const symbol s_39[] = { 'c' }; +static const symbol s_0[] = { 'q', 'u' }; +static const symbol s_1[] = { 'U' }; +static const symbol s_2[] = { 'I' }; +static const symbol s_3[] = { 'Y' }; +static const symbol s_4[] = { 0xC3, 0xAB }; +static const symbol s_5[] = { 'H', 'e' }; +static const symbol s_6[] = { 0xC3, 0xAF }; +static const symbol s_7[] = { 'H', 'i' }; +static const symbol s_8[] = { 'Y' }; +static const symbol s_9[] = { 'U' }; +static const symbol s_10[] = { 'i' }; +static const symbol s_11[] = { 'u' }; +static const symbol s_12[] = { 'y' }; +static const symbol s_13[] = { 0xC3, 0xAB }; +static const symbol s_14[] = { 0xC3, 0xAF }; +static const symbol s_15[] = { 'i', 'c' }; +static const symbol s_16[] = { 'i', 'q', 'U' }; +static const symbol s_17[] = { 'l', 'o', 'g' }; +static const symbol s_18[] = { 'u' }; +static const symbol s_19[] = { 'e', 'n', 't' }; +static const symbol s_20[] = { 'a', 't' }; +static const symbol s_21[] = { 'e', 'u', 'x' }; +static const symbol s_22[] = { 'i' }; +static const symbol s_23[] = { 'a', 'b', 'l' }; +static const symbol s_24[] = { 'i', 'q', 'U' }; +static const symbol s_25[] = { 'a', 't' }; +static const symbol s_26[] = { 'i', 'c' }; +static const symbol s_27[] = { 'i', 'q', 'U' }; +static const symbol s_28[] = { 'e', 'a', 'u' }; +static const symbol s_29[] = { 'a', 'l' }; +static const symbol s_30[] = { 'e', 'u', 'x' }; +static const symbol s_31[] = { 'a', 'n', 't' }; +static const symbol s_32[] = { 'e', 'n', 't' }; +static const symbol s_33[] = { 'H', 'i' }; +static const symbol s_34[] = { 'i' }; +static const symbol s_35[] = { 0xC3, 0xA9 }; +static const symbol s_36[] = { 0xC3, 0xA8 }; +static const symbol s_37[] = { 'e' }; +static const symbol s_38[] = { 'i' }; +static const symbol s_39[] = { 0xC3, 0xA7 }; +static const symbol s_40[] = { 'c' }; + +static int r_elisions(struct SN_env * z) { + z->bra = z->c; + { int c1 = z->c; + if (in_grouping_U(z, g_elision_char, 99, 116, 0)) goto lab1; + goto lab0; + lab1: + z->c = c1; + if (!(eq_s(z, 2, s_0))) return 0; + } +lab0: + if (z->c == z->l || z->p[z->c] != '\'') return 0; + z->c++; + z->ket = z->c; + + if (z->c < z->l) goto lab2; + return 0; +lab2: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + return 1; +} static int r_prelude(struct SN_env * z) { while(1) { @@ -427,7 +454,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping_U(z, g_v, 97, 251, 0)) goto lab5; - { int ret = slice_from_s(z, 1, s_0); + { int ret = slice_from_s(z, 1, s_1); if (ret < 0) return ret; } goto lab4; @@ -437,7 +464,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping_U(z, g_v, 97, 251, 0)) goto lab6; - { int ret = slice_from_s(z, 1, s_1); + { int ret = slice_from_s(z, 1, s_2); if (ret < 0) return ret; } goto lab4; @@ -446,7 +473,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 'y') goto lab3; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 1, s_2); + { int ret = slice_from_s(z, 1, s_3); if (ret < 0) return ret; } } @@ -455,18 +482,18 @@ static int r_prelude(struct SN_env * z) { lab3: z->c = c3; z->bra = z->c; - if (!(eq_s(z, 2, s_3))) goto lab7; + if (!(eq_s(z, 2, s_4))) goto lab7; z->ket = z->c; - { int ret = slice_from_s(z, 2, s_4); + { int ret = slice_from_s(z, 2, s_5); if (ret < 0) return ret; } goto lab2; lab7: z->c = c3; z->bra = z->c; - if (!(eq_s(z, 2, s_5))) goto lab8; + if (!(eq_s(z, 2, s_6))) goto lab8; z->ket = z->c; - { int ret = slice_from_s(z, 2, s_6); + { int ret = slice_from_s(z, 2, s_7); if (ret < 0) return ret; } goto lab2; @@ -477,7 +504,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping_U(z, g_v, 97, 251, 0)) goto lab9; - { int ret = slice_from_s(z, 1, s_7); + { int ret = slice_from_s(z, 1, s_8); if (ret < 0) return ret; } goto lab2; @@ -489,7 +516,7 @@ static int r_prelude(struct SN_env * z) { if (z->c == z->l || z->p[z->c] != 'u') goto lab1; z->c++; z->ket = z->c; - { int ret = slice_from_s(z, 1, s_8); + { int ret = slice_from_s(z, 1, s_9); if (ret < 0) return ret; } } @@ -527,7 +554,7 @@ static int r_mark_regions(struct SN_env * z) { lab2: z->c = c2; if (z->c + 2 >= z->l || z->p[z->c + 2] >> 5 != 3 || !((331776 >> (z->p[z->c + 2] & 0x1f)) & 1)) goto lab3; - if (!(find_among(z, a_0, 3))) goto lab3; + if (!find_among(z, a_0, 3)) goto lab3; goto lab1; lab3: z->c = c2; @@ -535,7 +562,8 @@ static int r_mark_regions(struct SN_env * z) { if (ret < 0) goto lab0; z->c = ret; } - { + + { int ret = out_grouping_U(z, g_v, 97, 251, 1); if (ret < 0) goto lab0; z->c += ret; @@ -547,23 +575,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c3 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 251, 1); if (ret < 0) goto lab4; z->c += ret; @@ -582,31 +614,30 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || z->p[z->c + 0] >> 5 != 2 || !((35652352 >> (z->p[z->c + 0] & 0x1f)) & 1)) among_var = 7; else among_var = find_among(z, a_1, 7); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: - { int ret = slice_from_s(z, 1, s_9); + { int ret = slice_from_s(z, 1, s_10); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 1, s_10); + { int ret = slice_from_s(z, 1, s_11); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 1, s_11); + { int ret = slice_from_s(z, 1, s_12); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 2, s_12); + { int ret = slice_from_s(z, 2, s_13); if (ret < 0) return ret; } break; case 5: - { int ret = slice_from_s(z, 2, s_13); + { int ret = slice_from_s(z, 2, s_14); if (ret < 0) return ret; } break; @@ -631,25 +662,22 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_4, 43); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -669,7 +697,7 @@ static int r_standard_suffix(struct SN_env * z) { } { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (!(eq_s_b(z, 2, s_14))) { z->c = z->l - m1; goto lab0; } + if (!(eq_s_b(z, 2, s_15))) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int m2 = z->l - z->c; (void)m2; { int ret = r_R2(z); @@ -682,7 +710,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab1; lab2: z->c = z->l - m2; - { int ret = slice_from_s(z, 3, s_15); + { int ret = slice_from_s(z, 3, s_16); if (ret < 0) return ret; } } @@ -695,7 +723,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_16); + { int ret = slice_from_s(z, 3, s_17); if (ret < 0) return ret; } break; @@ -703,7 +731,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 1, s_17); + { int ret = slice_from_s(z, 1, s_18); if (ret < 0) return ret; } break; @@ -711,7 +739,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R2(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_18); + { int ret = slice_from_s(z, 3, s_19); if (ret < 0) return ret; } break; @@ -725,7 +753,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; among_var = find_among_b(z, a_2, 6); - if (!(among_var)) { z->c = z->l - m3; goto lab3; } + if (!among_var) { z->c = z->l - m3; goto lab3; } z->bra = z->c; switch (among_var) { case 1: @@ -737,7 +765,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret < 0) return ret; } z->ket = z->c; - if (!(eq_s_b(z, 2, s_19))) { z->c = z->l - m3; goto lab3; } + if (!(eq_s_b(z, 2, s_20))) { z->c = z->l - m3; goto lab3; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab3; } @@ -763,7 +791,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) { z->c = z->l - m3; goto lab3; } if (ret < 0) return ret; } - { int ret = slice_from_s(z, 3, s_20); + { int ret = slice_from_s(z, 3, s_21); if (ret < 0) return ret; } } @@ -783,7 +811,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret == 0) { z->c = z->l - m3; goto lab3; } if (ret < 0) return ret; } - { int ret = slice_from_s(z, 1, s_21); + { int ret = slice_from_s(z, 1, s_22); if (ret < 0) return ret; } break; @@ -803,7 +831,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m5; goto lab6; } among_var = find_among_b(z, a_3, 3); - if (!(among_var)) { z->c = z->l - m5; goto lab6; } + if (!among_var) { z->c = z->l - m5; goto lab6; } z->bra = z->c; switch (among_var) { case 1: @@ -818,7 +846,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab7; lab8: z->c = z->l - m6; - { int ret = slice_from_s(z, 3, s_22); + { int ret = slice_from_s(z, 3, s_23); if (ret < 0) return ret; } } @@ -836,7 +864,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab9; lab10: z->c = z->l - m7; - { int ret = slice_from_s(z, 3, s_23); + { int ret = slice_from_s(z, 3, s_24); if (ret < 0) return ret; } } @@ -865,7 +893,7 @@ static int r_standard_suffix(struct SN_env * z) { } { int m8 = z->l - z->c; (void)m8; z->ket = z->c; - if (!(eq_s_b(z, 2, s_24))) { z->c = z->l - m8; goto lab11; } + if (!(eq_s_b(z, 2, s_25))) { z->c = z->l - m8; goto lab11; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m8; goto lab11; } @@ -875,7 +903,7 @@ static int r_standard_suffix(struct SN_env * z) { if (ret < 0) return ret; } z->ket = z->c; - if (!(eq_s_b(z, 2, s_25))) { z->c = z->l - m8; goto lab11; } + if (!(eq_s_b(z, 2, s_26))) { z->c = z->l - m8; goto lab11; } z->bra = z->c; { int m9 = z->l - z->c; (void)m9; { int ret = r_R2(z); @@ -888,7 +916,7 @@ static int r_standard_suffix(struct SN_env * z) { goto lab12; lab13: z->c = z->l - m9; - { int ret = slice_from_s(z, 3, s_26); + { int ret = slice_from_s(z, 3, s_27); if (ret < 0) return ret; } } @@ -898,7 +926,7 @@ static int r_standard_suffix(struct SN_env * z) { } break; case 9: - { int ret = slice_from_s(z, 3, s_27); + { int ret = slice_from_s(z, 3, s_28); if (ret < 0) return ret; } break; @@ -906,7 +934,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R1(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 2, s_28); + { int ret = slice_from_s(z, 2, s_29); if (ret < 0) return ret; } break; @@ -925,7 +953,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_R1(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_29); + { int ret = slice_from_s(z, 3, s_30); if (ret < 0) return ret; } } @@ -944,7 +972,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_RV(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_30); + { int ret = slice_from_s(z, 3, s_31); if (ret < 0) return ret; } return 0; @@ -953,7 +981,7 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = r_RV(z); if (ret <= 0) return ret; } - { int ret = slice_from_s(z, 3, s_31); + { int ret = slice_from_s(z, 3, s_32); if (ret < 0) return ret; } return 0; @@ -982,7 +1010,7 @@ static int r_i_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68944418 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_5, 35))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_5, 35)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int m2 = z->l - z->c; (void)m2; if (z->c <= z->lb || z->p[z->c - 1] != 'H') goto lab0; @@ -1008,7 +1036,7 @@ static int r_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; among_var = find_among_b(z, a_6, 38); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; switch (among_var) { case 1: @@ -1056,7 +1084,7 @@ static int r_residual_suffix(struct SN_env * z) { z->bra = z->c; { int m_test2 = z->l - z->c; { int m3 = z->l - z->c; (void)m3; - if (!(eq_s_b(z, 2, s_32))) goto lab2; + if (!(eq_s_b(z, 2, s_33))) goto lab2; goto lab1; lab2: z->c = z->l - m3; @@ -1078,7 +1106,7 @@ static int r_residual_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((278560 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit4; return 0; } among_var = find_among_b(z, a_7, 6); - if (!(among_var)) { z->lb = mlimit4; return 0; } + if (!among_var) { z->lb = mlimit4; return 0; } z->bra = z->c; switch (among_var) { case 1: @@ -1101,7 +1129,7 @@ static int r_residual_suffix(struct SN_env * z) { } break; case 2: - { int ret = slice_from_s(z, 1, s_33); + { int ret = slice_from_s(z, 1, s_34); if (ret < 0) return ret; } break; @@ -1119,7 +1147,7 @@ static int r_residual_suffix(struct SN_env * z) { static int r_un_double(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1069056 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_8, 5))) return 0; + if (!find_among_b(z, a_8, 5)) return 0; z->c = z->l - m_test1; } z->ket = z->c; @@ -1147,15 +1175,15 @@ static int r_un_accent(struct SN_env * z) { } z->ket = z->c; { int m1 = z->l - z->c; (void)m1; - if (!(eq_s_b(z, 2, s_34))) goto lab2; + if (!(eq_s_b(z, 2, s_35))) goto lab2; goto lab1; lab2: z->c = z->l - m1; - if (!(eq_s_b(z, 2, s_35))) return 0; + if (!(eq_s_b(z, 2, s_36))) return 0; } lab1: z->bra = z->c; - { int ret = slice_from_s(z, 1, s_36); + { int ret = slice_from_s(z, 1, s_37); if (ret < 0) return ret; } return 1; @@ -1163,57 +1191,63 @@ static int r_un_accent(struct SN_env * z) { extern int french_UTF_8_stem(struct SN_env * z) { { int c1 = z->c; - { int ret = r_prelude(z); + { int ret = r_elisions(z); if (ret < 0) return ret; } z->c = c1; } - + { int c2 = z->c; + { int ret = r_prelude(z); + if (ret < 0) return ret; + } + z->c = c2; + } + { int ret = r_mark_regions(z); if (ret < 0) return ret; } z->lb = z->c; z->c = z->l; - { int m2 = z->l - z->c; (void)m2; - { int m3 = z->l - z->c; (void)m3; - { int m4 = z->l - z->c; (void)m4; - { int m5 = z->l - z->c; (void)m5; + { int m3 = z->l - z->c; (void)m3; + { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; + { int m6 = z->l - z->c; (void)m6; { int ret = r_standard_suffix(z); if (ret == 0) goto lab4; if (ret < 0) return ret; } goto lab3; lab4: - z->c = z->l - m5; + z->c = z->l - m6; { int ret = r_i_verb_suffix(z); if (ret == 0) goto lab5; if (ret < 0) return ret; } goto lab3; lab5: - z->c = z->l - m5; + z->c = z->l - m6; { int ret = r_verb_suffix(z); if (ret == 0) goto lab2; if (ret < 0) return ret; } } lab3: - z->c = z->l - m4; - { int m6 = z->l - z->c; (void)m6; + z->c = z->l - m5; + { int m7 = z->l - z->c; (void)m7; z->ket = z->c; - { int m7 = z->l - z->c; (void)m7; + { int m8 = z->l - z->c; (void)m8; if (z->c <= z->lb || z->p[z->c - 1] != 'Y') goto lab8; z->c--; z->bra = z->c; - { int ret = slice_from_s(z, 1, s_37); + { int ret = slice_from_s(z, 1, s_38); if (ret < 0) return ret; } goto lab7; lab8: - z->c = z->l - m7; - if (!(eq_s_b(z, 2, s_38))) { z->c = z->l - m6; goto lab6; } + z->c = z->l - m8; + if (!(eq_s_b(z, 2, s_39))) { z->c = z->l - m7; goto lab6; } z->bra = z->c; - { int ret = slice_from_s(z, 1, s_39); + { int ret = slice_from_s(z, 1, s_40); if (ret < 0) return ret; } } @@ -1224,7 +1258,7 @@ extern int french_UTF_8_stem(struct SN_env * z) { } goto lab1; lab2: - z->c = z->l - m3; + z->c = z->l - m4; { int ret = r_residual_suffix(z); if (ret == 0) goto lab0; if (ret < 0) return ret; @@ -1232,26 +1266,26 @@ extern int french_UTF_8_stem(struct SN_env * z) { } lab1: lab0: - z->c = z->l - m2; + z->c = z->l - m3; } - { int m8 = z->l - z->c; (void)m8; + { int m9 = z->l - z->c; (void)m9; { int ret = r_un_double(z); if (ret < 0) return ret; } - z->c = z->l - m8; + z->c = z->l - m9; } - { int m9 = z->l - z->c; (void)m9; + { int m10 = z->l - z->c; (void)m10; { int ret = r_un_accent(z); if (ret < 0) return ret; } - z->c = z->l - m9; + z->c = z->l - m10; } z->c = z->lb; - { int c10 = z->c; + { int c11 = z->c; { int ret = r_postlude(z); if (ret < 0) return ret; } - z->c = c10; + z->c = c11; } return 1; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_german.c b/src/backend/snowball/libstemmer/stem_UTF_8_german.c index 13ce77e7c0bab..6bb0ac050b431 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_german.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_german.c @@ -27,82 +27,106 @@ extern void german_UTF_8_close_env(struct SN_env * z); #ifdef __cplusplus } #endif -static const symbol s_0_1[1] = { 'U' }; -static const symbol s_0_2[1] = { 'Y' }; -static const symbol s_0_3[2] = { 0xC3, 0xA4 }; -static const symbol s_0_4[2] = { 0xC3, 0xB6 }; -static const symbol s_0_5[2] = { 0xC3, 0xBC }; +static const symbol s_0_1[2] = { 'a', 'e' }; +static const symbol s_0_2[2] = { 'o', 'e' }; +static const symbol s_0_3[2] = { 'q', 'u' }; +static const symbol s_0_4[2] = { 'u', 'e' }; +static const symbol s_0_5[2] = { 0xC3, 0x9F }; static const struct among a_0[6] = { { 0, 0, -1, 5, 0}, -{ 1, s_0_1, 0, 2, 0}, -{ 1, s_0_2, 0, 1, 0}, -{ 2, s_0_3, 0, 3, 0}, +{ 2, s_0_1, 0, 2, 0}, +{ 2, s_0_2, 0, 3, 0}, +{ 2, s_0_3, 0, -1, 0}, { 2, s_0_4, 0, 4, 0}, -{ 2, s_0_5, 0, 2, 0} +{ 2, s_0_5, 0, 1, 0} }; -static const symbol s_1_0[1] = { 'e' }; -static const symbol s_1_1[2] = { 'e', 'm' }; -static const symbol s_1_2[2] = { 'e', 'n' }; -static const symbol s_1_3[3] = { 'e', 'r', 'n' }; -static const symbol s_1_4[2] = { 'e', 'r' }; -static const symbol s_1_5[1] = { 's' }; -static const symbol s_1_6[2] = { 'e', 's' }; +static const symbol s_1_1[1] = { 'U' }; +static const symbol s_1_2[1] = { 'Y' }; +static const symbol s_1_3[2] = { 0xC3, 0xA4 }; +static const symbol s_1_4[2] = { 0xC3, 0xB6 }; +static const symbol s_1_5[2] = { 0xC3, 0xBC }; -static const struct among a_1[7] = +static const struct among a_1[6] = { -{ 1, s_1_0, -1, 2, 0}, -{ 2, s_1_1, -1, 1, 0}, -{ 2, s_1_2, -1, 2, 0}, -{ 3, s_1_3, -1, 1, 0}, -{ 2, s_1_4, -1, 1, 0}, -{ 1, s_1_5, -1, 3, 0}, -{ 2, s_1_6, 5, 2, 0} +{ 0, 0, -1, 5, 0}, +{ 1, s_1_1, 0, 2, 0}, +{ 1, s_1_2, 0, 1, 0}, +{ 2, s_1_3, 0, 3, 0}, +{ 2, s_1_4, 0, 4, 0}, +{ 2, s_1_5, 0, 2, 0} }; -static const symbol s_2_0[2] = { 'e', 'n' }; -static const symbol s_2_1[2] = { 'e', 'r' }; -static const symbol s_2_2[2] = { 's', 't' }; -static const symbol s_2_3[3] = { 'e', 's', 't' }; +static const symbol s_2_0[1] = { 'e' }; +static const symbol s_2_1[2] = { 'e', 'm' }; +static const symbol s_2_2[2] = { 'e', 'n' }; +static const symbol s_2_3[7] = { 'e', 'r', 'i', 'n', 'n', 'e', 'n' }; +static const symbol s_2_4[4] = { 'e', 'r', 'i', 'n' }; +static const symbol s_2_5[2] = { 'l', 'n' }; +static const symbol s_2_6[3] = { 'e', 'r', 'n' }; +static const symbol s_2_7[2] = { 'e', 'r' }; +static const symbol s_2_8[1] = { 's' }; +static const symbol s_2_9[2] = { 'e', 's' }; +static const symbol s_2_10[3] = { 'l', 'n', 's' }; -static const struct among a_2[4] = +static const struct among a_2[11] = { -{ 2, s_2_0, -1, 1, 0}, +{ 1, s_2_0, -1, 3, 0}, { 2, s_2_1, -1, 1, 0}, -{ 2, s_2_2, -1, 2, 0}, -{ 3, s_2_3, 2, 1, 0} +{ 2, s_2_2, -1, 3, 0}, +{ 7, s_2_3, 2, 2, 0}, +{ 4, s_2_4, -1, 2, 0}, +{ 2, s_2_5, -1, 5, 0}, +{ 3, s_2_6, -1, 2, 0}, +{ 2, s_2_7, -1, 2, 0}, +{ 1, s_2_8, -1, 4, 0}, +{ 2, s_2_9, 8, 3, 0}, +{ 3, s_2_10, 8, 5, 0} }; -static const symbol s_3_0[2] = { 'i', 'g' }; -static const symbol s_3_1[4] = { 'l', 'i', 'c', 'h' }; +static const symbol s_3_0[2] = { 'e', 'n' }; +static const symbol s_3_1[2] = { 'e', 'r' }; +static const symbol s_3_2[2] = { 's', 't' }; +static const symbol s_3_3[3] = { 'e', 's', 't' }; -static const struct among a_3[2] = +static const struct among a_3[4] = { { 2, s_3_0, -1, 1, 0}, -{ 4, s_3_1, -1, 1, 0} +{ 2, s_3_1, -1, 1, 0}, +{ 2, s_3_2, -1, 2, 0}, +{ 3, s_3_3, 2, 1, 0} +}; + +static const symbol s_4_0[2] = { 'i', 'g' }; +static const symbol s_4_1[4] = { 'l', 'i', 'c', 'h' }; + +static const struct among a_4[2] = +{ +{ 2, s_4_0, -1, 1, 0}, +{ 4, s_4_1, -1, 1, 0} }; -static const symbol s_4_0[3] = { 'e', 'n', 'd' }; -static const symbol s_4_1[2] = { 'i', 'g' }; -static const symbol s_4_2[3] = { 'u', 'n', 'g' }; -static const symbol s_4_3[4] = { 'l', 'i', 'c', 'h' }; -static const symbol s_4_4[4] = { 'i', 's', 'c', 'h' }; -static const symbol s_4_5[2] = { 'i', 'k' }; -static const symbol s_4_6[4] = { 'h', 'e', 'i', 't' }; -static const symbol s_4_7[4] = { 'k', 'e', 'i', 't' }; +static const symbol s_5_0[3] = { 'e', 'n', 'd' }; +static const symbol s_5_1[2] = { 'i', 'g' }; +static const symbol s_5_2[3] = { 'u', 'n', 'g' }; +static const symbol s_5_3[4] = { 'l', 'i', 'c', 'h' }; +static const symbol s_5_4[4] = { 'i', 's', 'c', 'h' }; +static const symbol s_5_5[2] = { 'i', 'k' }; +static const symbol s_5_6[4] = { 'h', 'e', 'i', 't' }; +static const symbol s_5_7[4] = { 'k', 'e', 'i', 't' }; -static const struct among a_4[8] = +static const struct among a_5[8] = { -{ 3, s_4_0, -1, 1, 0}, -{ 2, s_4_1, -1, 2, 0}, -{ 3, s_4_2, -1, 1, 0}, -{ 4, s_4_3, -1, 3, 0}, -{ 4, s_4_4, -1, 2, 0}, -{ 2, s_4_5, -1, 2, 0}, -{ 4, s_4_6, -1, 3, 0}, -{ 4, s_4_7, -1, 4, 0} +{ 3, s_5_0, -1, 1, 0}, +{ 2, s_5_1, -1, 2, 0}, +{ 3, s_5_2, -1, 1, 0}, +{ 4, s_5_3, -1, 3, 0}, +{ 4, s_5_4, -1, 2, 0}, +{ 2, s_5_5, -1, 2, 0}, +{ 4, s_5_6, -1, 3, 0}, +{ 4, s_5_7, -1, 4, 0} }; static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 32, 8 }; @@ -111,39 +135,61 @@ static const unsigned char g_s_ending[] = { 117, 30, 5 }; static const unsigned char g_st_ending[] = { 117, 30, 4 }; -static const symbol s_0[] = { 0xC3, 0x9F }; -static const symbol s_1[] = { 's', 's' }; -static const symbol s_2[] = { 'U' }; -static const symbol s_3[] = { 'Y' }; -static const symbol s_4[] = { 'y' }; -static const symbol s_5[] = { 'u' }; -static const symbol s_6[] = { 'a' }; -static const symbol s_7[] = { 'o' }; -static const symbol s_8[] = { 'n', 'i', 's' }; -static const symbol s_9[] = { 'i', 'g' }; -static const symbol s_10[] = { 'e', 'r' }; -static const symbol s_11[] = { 'e', 'n' }; +static const symbol s_0[] = { 'U' }; +static const symbol s_1[] = { 'Y' }; +static const symbol s_2[] = { 's', 's' }; +static const symbol s_3[] = { 0xC3, 0xA4 }; +static const symbol s_4[] = { 0xC3, 0xB6 }; +static const symbol s_5[] = { 0xC3, 0xBC }; +static const symbol s_6[] = { 'y' }; +static const symbol s_7[] = { 'u' }; +static const symbol s_8[] = { 'a' }; +static const symbol s_9[] = { 'o' }; +static const symbol s_10[] = { 's', 'y', 's', 't' }; +static const symbol s_11[] = { 'n', 'i', 's' }; +static const symbol s_12[] = { 'l' }; +static const symbol s_13[] = { 'i', 'g' }; +static const symbol s_14[] = { 'e', 'r' }; +static const symbol s_15[] = { 'e', 'n' }; static int r_prelude(struct SN_env * z) { + int among_var; { int c_test1 = z->c; while(1) { int c2 = z->c; - { int c3 = z->c; + while(1) { + int c3 = z->c; + if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab1; z->bra = z->c; - if (!(eq_s(z, 2, s_0))) goto lab2; - z->ket = z->c; - { int ret = slice_from_s(z, 2, s_1); - if (ret < 0) return ret; + { int c4 = z->c; + if (z->c == z->l || z->p[z->c] != 'u') goto lab3; + z->c++; + z->ket = z->c; + if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab3; + { int ret = slice_from_s(z, 1, s_0); + if (ret < 0) return ret; + } + goto lab2; + lab3: + z->c = c4; + if (z->c == z->l || z->p[z->c] != 'y') goto lab1; + z->c++; + z->ket = z->c; + if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab1; + { int ret = slice_from_s(z, 1, s_1); + if (ret < 0) return ret; + } } - goto lab1; lab2: + z->c = c3; + break; + lab1: z->c = c3; { int ret = skip_utf8(z->p, z->c, z->l, 1); if (ret < 0) goto lab0; z->c = ret; } } - lab1: continue; lab0: z->c = c2; @@ -152,43 +198,41 @@ static int r_prelude(struct SN_env * z) { z->c = c_test1; } while(1) { - int c4 = z->c; - while(1) { - int c5 = z->c; - if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab4; - z->bra = z->c; - { int c6 = z->c; - if (z->c == z->l || z->p[z->c] != 'u') goto lab6; - z->c++; - z->ket = z->c; - if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab6; - { int ret = slice_from_s(z, 1, s_2); + int c5 = z->c; + z->bra = z->c; + among_var = find_among(z, a_0, 6); + z->ket = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 2, s_2); if (ret < 0) return ret; } - goto lab5; - lab6: - z->c = c6; - if (z->c == z->l || z->p[z->c] != 'y') goto lab4; - z->c++; - z->ket = z->c; - if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab4; - { int ret = slice_from_s(z, 1, s_3); + break; + case 2: + { int ret = slice_from_s(z, 2, s_3); if (ret < 0) return ret; } - } - lab5: - z->c = c5; - break; - lab4: - z->c = c5; - { int ret = skip_utf8(z->p, z->c, z->l, 1); - if (ret < 0) goto lab3; - z->c = ret; - } + break; + case 3: + { int ret = slice_from_s(z, 2, s_4); + if (ret < 0) return ret; + } + break; + case 4: + { int ret = slice_from_s(z, 2, s_5); + if (ret < 0) return ret; + } + break; + case 5: + { int ret = skip_utf8(z->p, z->c, z->l, 1); + if (ret < 0) goto lab4; + z->c = ret; + } + break; } continue; - lab3: - z->c = c4; + lab4: + z->c = c5; break; } return 1; @@ -205,27 +249,31 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->c; z->c = c_test1; } - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } z->I[2] = z->c; - - if (!(z->I[2] < z->I[0])) goto lab0; + + if (z->I[2] >= z->I[0]) goto lab0; z->I[2] = z->I[0]; lab0: - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) return 0; z->c += ret; @@ -239,27 +287,26 @@ static int r_postlude(struct SN_env * z) { while(1) { int c1 = z->c; z->bra = z->c; - among_var = find_among(z, a_0, 6); - if (!(among_var)) goto lab0; + among_var = find_among(z, a_1, 6); z->ket = z->c; switch (among_var) { case 1: - { int ret = slice_from_s(z, 1, s_4); + { int ret = slice_from_s(z, 1, s_6); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 1, s_5); + { int ret = slice_from_s(z, 1, s_7); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 1, s_6); + { int ret = slice_from_s(z, 1, s_8); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 1, s_7); + { int ret = slice_from_s(z, 1, s_9); if (ret < 0) return ret; } break; @@ -279,13 +326,11 @@ static int r_postlude(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_standard_suffix(struct SN_env * z) { @@ -293,8 +338,8 @@ static int r_standard_suffix(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((811040 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab0; - among_var = find_among_b(z, a_1, 7); - if (!(among_var)) goto lab0; + among_var = find_among_b(z, a_2, 11); + if (!among_var) goto lab0; z->bra = z->c; { int ret = r_R1(z); if (ret == 0) goto lab0; @@ -302,6 +347,12 @@ static int r_standard_suffix(struct SN_env * z) { } switch (among_var) { case 1: + { int m2 = z->l - z->c; (void)m2; + if (!(eq_s_b(z, 4, s_10))) goto lab1; + goto lab0; + lab1: + z->c = z->l - m2; + } { int ret = slice_del(z); if (ret < 0) return ret; } @@ -310,37 +361,47 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - { int m2 = z->l - z->c; (void)m2; + break; + case 3: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + { int m3 = z->l - z->c; (void)m3; z->ket = z->c; - if (z->c <= z->lb || z->p[z->c - 1] != 's') { z->c = z->l - m2; goto lab1; } + if (z->c <= z->lb || z->p[z->c - 1] != 's') { z->c = z->l - m3; goto lab2; } z->c--; z->bra = z->c; - if (!(eq_s_b(z, 3, s_8))) { z->c = z->l - m2; goto lab1; } + if (!(eq_s_b(z, 3, s_11))) { z->c = z->l - m3; goto lab2; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab1: + lab2: ; } break; - case 3: + case 4: if (in_grouping_b_U(z, g_s_ending, 98, 116, 0)) goto lab0; { int ret = slice_del(z); if (ret < 0) return ret; } break; + case 5: + { int ret = slice_from_s(z, 1, s_12); + if (ret < 0) return ret; + } + break; } lab0: z->c = z->l - m1; } - { int m3 = z->l - z->c; (void)m3; + { int m4 = z->l - z->c; (void)m4; z->ket = z->c; - if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1327104 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab2; - among_var = find_among_b(z, a_2, 4); - if (!(among_var)) goto lab2; + if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1327104 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; + among_var = find_among_b(z, a_3, 4); + if (!among_var) goto lab3; z->bra = z->c; { int ret = r_R1(z); - if (ret == 0) goto lab2; + if (ret == 0) goto lab3; if (ret < 0) return ret; } switch (among_var) { @@ -350,9 +411,9 @@ static int r_standard_suffix(struct SN_env * z) { } break; case 2: - if (in_grouping_b_U(z, g_st_ending, 98, 116, 0)) goto lab2; + if (in_grouping_b_U(z, g_st_ending, 98, 116, 0)) goto lab3; { int ret = skip_b_utf8(z->p, z->c, z->lb, 3); - if (ret < 0) goto lab2; + if (ret < 0) goto lab3; z->c = ret; } { int ret = slice_del(z); @@ -360,17 +421,17 @@ static int r_standard_suffix(struct SN_env * z) { } break; } - lab2: - z->c = z->l - m3; + lab3: + z->c = z->l - m4; } - { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; z->ket = z->c; - if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1051024 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab3; - among_var = find_among_b(z, a_4, 8); - if (!(among_var)) goto lab3; + if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1051024 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab4; + among_var = find_among_b(z, a_5, 8); + if (!among_var) goto lab4; z->bra = z->c; { int ret = r_R2(z); - if (ret == 0) goto lab3; + if (ret == 0) goto lab4; if (ret < 0) return ret; } switch (among_var) { @@ -378,35 +439,35 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - { int m5 = z->l - z->c; (void)m5; + { int m6 = z->l - z->c; (void)m6; z->ket = z->c; - if (!(eq_s_b(z, 2, s_9))) { z->c = z->l - m5; goto lab4; } + if (!(eq_s_b(z, 2, s_13))) { z->c = z->l - m6; goto lab5; } z->bra = z->c; - { int m6 = z->l - z->c; (void)m6; - if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab5; + { int m7 = z->l - z->c; (void)m7; + if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab6; z->c--; - { z->c = z->l - m5; goto lab4; } - lab5: - z->c = z->l - m6; + { z->c = z->l - m6; goto lab5; } + lab6: + z->c = z->l - m7; } { int ret = r_R2(z); - if (ret == 0) { z->c = z->l - m5; goto lab4; } + if (ret == 0) { z->c = z->l - m6; goto lab5; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab4: + lab5: ; } break; case 2: - { int m7 = z->l - z->c; (void)m7; - if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab6; + { int m8 = z->l - z->c; (void)m8; + if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab7; z->c--; - goto lab3; - lab6: - z->c = z->l - m7; + goto lab4; + lab7: + z->c = z->l - m8; } { int ret = slice_del(z); if (ret < 0) return ret; @@ -416,25 +477,25 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - { int m8 = z->l - z->c; (void)m8; + { int m9 = z->l - z->c; (void)m9; z->ket = z->c; - { int m9 = z->l - z->c; (void)m9; - if (!(eq_s_b(z, 2, s_10))) goto lab9; - goto lab8; - lab9: - z->c = z->l - m9; - if (!(eq_s_b(z, 2, s_11))) { z->c = z->l - m8; goto lab7; } + { int m10 = z->l - z->c; (void)m10; + if (!(eq_s_b(z, 2, s_14))) goto lab10; + goto lab9; + lab10: + z->c = z->l - m10; + if (!(eq_s_b(z, 2, s_15))) { z->c = z->l - m9; goto lab8; } } - lab8: + lab9: z->bra = z->c; { int ret = r_R1(z); - if (ret == 0) { z->c = z->l - m8; goto lab7; } + if (ret == 0) { z->c = z->l - m9; goto lab8; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab7: + lab8: ; } break; @@ -442,25 +503,25 @@ static int r_standard_suffix(struct SN_env * z) { { int ret = slice_del(z); if (ret < 0) return ret; } - { int m10 = z->l - z->c; (void)m10; + { int m11 = z->l - z->c; (void)m11; z->ket = z->c; - if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 103 && z->p[z->c - 1] != 104)) { z->c = z->l - m10; goto lab10; } - if (!(find_among_b(z, a_3, 2))) { z->c = z->l - m10; goto lab10; } + if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 103 && z->p[z->c - 1] != 104)) { z->c = z->l - m11; goto lab11; } + if (!find_among_b(z, a_4, 2)) { z->c = z->l - m11; goto lab11; } z->bra = z->c; { int ret = r_R2(z); - if (ret == 0) { z->c = z->l - m10; goto lab10; } + if (ret == 0) { z->c = z->l - m11; goto lab11; } if (ret < 0) return ret; } { int ret = slice_del(z); if (ret < 0) return ret; } - lab10: + lab11: ; } break; } - lab3: - z->c = z->l - m4; + lab4: + z->c = z->l - m5; } return 1; } @@ -480,7 +541,7 @@ extern int german_UTF_8_stem(struct SN_env * z) { } z->lb = z->c; z->c = z->l; - + { int ret = r_standard_suffix(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_greek.c b/src/backend/snowball/libstemmer/stem_UTF_8_greek.c index 7b3e017b90c9e..33e5465267ca4 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_greek.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_greek.c @@ -2,38 +2,38 @@ #include "header.h" -static int r_step7(struct SN_env * z); -static int r_step6(struct SN_env * z); -static int r_step5m(struct SN_env * z); -static int r_step5l(struct SN_env * z); -static int r_step5k(struct SN_env * z); -static int r_step5j(struct SN_env * z); -static int r_step5i(struct SN_env * z); -static int r_step5h(struct SN_env * z); -static int r_step5g(struct SN_env * z); -static int r_step5f(struct SN_env * z); -static int r_step5e(struct SN_env * z); -static int r_step5d(struct SN_env * z); -static int r_step5c(struct SN_env * z); -static int r_step5b(struct SN_env * z); -static int r_step5a(struct SN_env * z); -static int r_step4(struct SN_env * z); -static int r_step3(struct SN_env * z); -static int r_step2d(struct SN_env * z); -static int r_step2c(struct SN_env * z); -static int r_step2b(struct SN_env * z); -static int r_step2a(struct SN_env * z); -static int r_step1(struct SN_env * z); -static int r_steps10(struct SN_env * z); -static int r_steps9(struct SN_env * z); -static int r_steps8(struct SN_env * z); -static int r_steps7(struct SN_env * z); -static int r_steps6(struct SN_env * z); -static int r_steps5(struct SN_env * z); -static int r_steps4(struct SN_env * z); -static int r_steps3(struct SN_env * z); -static int r_steps2(struct SN_env * z); -static int r_steps1(struct SN_env * z); +static int r_step_7(struct SN_env * z); +static int r_step_6(struct SN_env * z); +static int r_step_5m(struct SN_env * z); +static int r_step_5l(struct SN_env * z); +static int r_step_5k(struct SN_env * z); +static int r_step_5j(struct SN_env * z); +static int r_step_5i(struct SN_env * z); +static int r_step_5h(struct SN_env * z); +static int r_step_5g(struct SN_env * z); +static int r_step_5f(struct SN_env * z); +static int r_step_5e(struct SN_env * z); +static int r_step_5d(struct SN_env * z); +static int r_step_5c(struct SN_env * z); +static int r_step_5b(struct SN_env * z); +static int r_step_5a(struct SN_env * z); +static int r_step_4(struct SN_env * z); +static int r_step_3(struct SN_env * z); +static int r_step_2d(struct SN_env * z); +static int r_step_2c(struct SN_env * z); +static int r_step_2b(struct SN_env * z); +static int r_step_2a(struct SN_env * z); +static int r_step_1(struct SN_env * z); +static int r_step_s10(struct SN_env * z); +static int r_step_s9(struct SN_env * z); +static int r_step_s8(struct SN_env * z); +static int r_step_s7(struct SN_env * z); +static int r_step_s6(struct SN_env * z); +static int r_step_s5(struct SN_env * z); +static int r_step_s4(struct SN_env * z); +static int r_step_s3(struct SN_env * z); +static int r_step_s2(struct SN_env * z); +static int r_step_s1(struct SN_env * z); static int r_has_min_length(struct SN_env * z); static int r_tolower(struct SN_env * z); #ifdef __cplusplus @@ -2323,8 +2323,7 @@ static const symbol s_105[] = { 0xCE, 0xBF, 0xCF, 0x85, 0xCE, 0xBC }; static const symbol s_106[] = { 0xCE, 0xBC, 0xCE, 0xB1 }; static int r_has_min_length(struct SN_env * z) { - if (!(len_utf8(z->p) >= 3)) return 0; - return 1; + return len_utf8(z->p) >= 3; } static int r_tolower(struct SN_env * z) { @@ -2333,7 +2332,6 @@ static int r_tolower(struct SN_env * z) { int m1 = z->l - z->c; (void)m1; z->ket = z->c; among_var = find_among_b(z, a_0, 46); - if (!(among_var)) goto lab0; z->bra = z->c; switch (among_var) { case 1: @@ -2471,11 +2469,11 @@ static int r_tolower(struct SN_env * z) { return 1; } -static int r_step1(struct SN_env * z) { +static int r_step_1(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_1, 40); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -2538,10 +2536,10 @@ static int r_step1(struct SN_env * z) { return 1; } -static int r_steps1(struct SN_env * z) { +static int r_step_s1(struct SN_env * z) { int among_var; z->ket = z->c; - if (!(find_among_b(z, a_3, 14))) return 0; + if (!find_among_b(z, a_3, 14)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2550,7 +2548,7 @@ static int r_steps1(struct SN_env * z) { z->ket = z->c; z->bra = z->c; among_var = find_among_b(z, a_2, 31); - if (!(among_var)) return 0; + if (!among_var) return 0; if (z->c > z->lb) return 0; switch (among_var) { case 1: @@ -2567,9 +2565,9 @@ static int r_steps1(struct SN_env * z) { return 1; } -static int r_steps2(struct SN_env * z) { +static int r_step_s2(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_5, 7))) return 0; + if (!find_among_b(z, a_5, 7)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2577,7 +2575,7 @@ static int r_steps2(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_4, 8))) return 0; + if (!find_among_b(z, a_4, 8)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_37); if (ret < 0) return ret; @@ -2585,17 +2583,12 @@ static int r_steps2(struct SN_env * z) { return 1; } -static int r_steps3(struct SN_env * z) { +static int r_step_s3(struct SN_env * z) { int among_var; - z->ket = z->c; - if (!(find_among_b(z, a_7, 7))) return 0; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->I[0] = 0; { int m1 = z->l - z->c; (void)m1; + z->ket = z->c; if (!(eq_s_b(z, 6, s_38))) goto lab1; + z->bra = z->c; if (z->c > z->lb) goto lab1; { int ret = slice_from_s(z, 4, s_39); if (ret < 0) return ret; @@ -2604,30 +2597,37 @@ static int r_steps3(struct SN_env * z) { lab1: z->c = z->l - m1; z->ket = z->c; - z->bra = z->c; - among_var = find_among_b(z, a_6, 32); - if (!(among_var)) return 0; - if (z->c > z->lb) return 0; - switch (among_var) { - case 1: - { int ret = slice_from_s(z, 2, s_40); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 4, s_41); - if (ret < 0) return ret; - } - break; - } } lab0: + if (!find_among_b(z, a_7, 7)) return 0; + z->bra = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + z->I[0] = 0; + z->ket = z->c; + z->bra = z->c; + among_var = find_among_b(z, a_6, 32); + if (!among_var) return 0; + if (z->c > z->lb) return 0; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 2, s_40); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 4, s_41); + if (ret < 0) return ret; + } + break; + } return 1; } -static int r_steps4(struct SN_env * z) { +static int r_step_s4(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_9, 7))) return 0; + if (!find_among_b(z, a_9, 7)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2636,7 +2636,7 @@ static int r_steps4(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] >> 5 != 5 || !((-2145255424 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_8, 19))) return 0; + if (!find_among_b(z, a_8, 19)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 2, s_42); if (ret < 0) return ret; @@ -2644,10 +2644,10 @@ static int r_steps4(struct SN_env * z) { return 1; } -static int r_steps5(struct SN_env * z) { +static int r_step_s5(struct SN_env * z) { int among_var; z->ket = z->c; - if (!(find_among_b(z, a_11, 11))) return 0; + if (!find_among_b(z, a_11, 11)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2656,7 +2656,7 @@ static int r_steps5(struct SN_env * z) { z->ket = z->c; z->bra = z->c; among_var = find_among_b(z, a_10, 40); - if (!(among_var)) return 0; + if (!among_var) return 0; if (z->c > z->lb) return 0; switch (among_var) { case 1: @@ -2673,10 +2673,10 @@ static int r_steps5(struct SN_env * z) { return 1; } -static int r_steps6(struct SN_env * z) { +static int r_step_s6(struct SN_env * z) { int among_var; z->ket = z->c; - if (!(find_among_b(z, a_14, 6))) return 0; + if (!find_among_b(z, a_14, 6)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2687,7 +2687,7 @@ static int r_steps6(struct SN_env * z) { z->bra = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 181) goto lab1; among_var = find_among_b(z, a_12, 7); - if (!(among_var)) goto lab1; + if (!among_var) goto lab1; if (z->c > z->lb) goto lab1; switch (among_var) { case 1: @@ -2707,7 +2707,7 @@ static int r_steps6(struct SN_env * z) { z->ket = z->c; if (z->c - 9 <= z->lb || (z->p[z->c - 1] != 186 && z->p[z->c - 1] != 189)) return 0; among_var = find_among_b(z, a_13, 10); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -2766,10 +2766,10 @@ static int r_steps6(struct SN_env * z) { return 1; } -static int r_steps7(struct SN_env * z) { +static int r_step_s7(struct SN_env * z) { z->ket = z->c; if (z->c - 9 <= z->lb || (z->p[z->c - 1] != 177 && z->p[z->c - 1] != 185)) return 0; - if (!(find_among_b(z, a_16, 4))) return 0; + if (!find_among_b(z, a_16, 4)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2778,7 +2778,7 @@ static int r_steps7(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 131 && z->p[z->c - 1] != 135)) return 0; - if (!(find_among_b(z, a_15, 2))) return 0; + if (!find_among_b(z, a_15, 2)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 8, s_57); if (ret < 0) return ret; @@ -2786,10 +2786,10 @@ static int r_steps7(struct SN_env * z) { return 1; } -static int r_steps8(struct SN_env * z) { +static int r_step_s8(struct SN_env * z) { int among_var; z->ket = z->c; - if (!(find_among_b(z, a_18, 8))) return 0; + if (!find_among_b(z, a_18, 8)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2799,7 +2799,7 @@ static int r_steps8(struct SN_env * z) { z->ket = z->c; z->bra = z->c; among_var = find_among_b(z, a_17, 46); - if (!(among_var)) goto lab1; + if (!among_var) goto lab1; if (z->c > z->lb) goto lab1; switch (among_var) { case 1: @@ -2827,10 +2827,10 @@ static int r_steps8(struct SN_env * z) { return 1; } -static int r_steps9(struct SN_env * z) { +static int r_step_s9(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || z->p[z->c - 1] >> 5 != 5 || !((-1610481664 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_21, 3))) return 0; + if (!find_among_b(z, a_21, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2839,7 +2839,7 @@ static int r_steps9(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_19, 4))) goto lab1; + if (!find_among_b(z, a_19, 4)) goto lab1; if (z->c > z->lb) goto lab1; { int ret = slice_from_s(z, 4, s_62); if (ret < 0) return ret; @@ -2850,7 +2850,7 @@ static int r_steps9(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 181 && z->p[z->c - 1] != 189)) return 0; - if (!(find_among_b(z, a_20, 2))) return 0; + if (!find_among_b(z, a_20, 2)) return 0; { int ret = slice_from_s(z, 4, s_63); if (ret < 0) return ret; } @@ -2859,9 +2859,9 @@ static int r_steps9(struct SN_env * z) { return 1; } -static int r_steps10(struct SN_env * z) { +static int r_step_s10(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_23, 4))) return 0; + if (!find_among_b(z, a_23, 4)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2869,7 +2869,7 @@ static int r_steps10(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_22, 7))) return 0; + if (!find_among_b(z, a_22, 7)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 6, s_64); if (ret < 0) return ret; @@ -2877,16 +2877,16 @@ static int r_steps10(struct SN_env * z) { return 1; } -static int r_step2a(struct SN_env * z) { +static int r_step_2a(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || (z->p[z->c - 1] != 131 && z->p[z->c - 1] != 189)) return 0; - if (!(find_among_b(z, a_24, 2))) return 0; + if (!find_among_b(z, a_24, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; } { int m1 = z->l - z->c; (void)m1; - if (!(find_among_b(z, a_25, 10))) goto lab0; + if (!find_among_b(z, a_25, 10)) goto lab0; return 0; lab0: z->c = z->l - m1; @@ -2901,10 +2901,10 @@ static int r_step2a(struct SN_env * z) { return 1; } -static int r_step2b(struct SN_env * z) { +static int r_step_2b(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || (z->p[z->c - 1] != 131 && z->p[z->c - 1] != 189)) return 0; - if (!(find_among_b(z, a_26, 2))) return 0; + if (!find_among_b(z, a_26, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2912,34 +2912,34 @@ static int r_step2b(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 128 && z->p[z->c - 1] != 187)) return 0; - if (!(find_among_b(z, a_27, 8))) return 0; + if (!find_among_b(z, a_27, 8)) return 0; { int ret = slice_from_s(z, 4, s_66); if (ret < 0) return ret; } return 1; } -static int r_step2c(struct SN_env * z) { +static int r_step_2c(struct SN_env * z) { z->ket = z->c; if (z->c - 9 <= z->lb || (z->p[z->c - 1] != 131 && z->p[z->c - 1] != 189)) return 0; - if (!(find_among_b(z, a_28, 2))) return 0; + if (!find_among_b(z, a_28, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; } z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_29, 15))) return 0; + if (!find_among_b(z, a_29, 15)) return 0; { int ret = slice_from_s(z, 6, s_67); if (ret < 0) return ret; } return 1; } -static int r_step2d(struct SN_env * z) { +static int r_step_2d(struct SN_env * z) { z->ket = z->c; if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 131 && z->p[z->c - 1] != 189)) return 0; - if (!(find_among_b(z, a_30, 2))) return 0; + if (!find_among_b(z, a_30, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2947,7 +2947,7 @@ static int r_step2d(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_31, 8))) return 0; + if (!find_among_b(z, a_31, 8)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 2, s_68); if (ret < 0) return ret; @@ -2955,9 +2955,9 @@ static int r_step2d(struct SN_env * z) { return 1; } -static int r_step3(struct SN_env * z) { +static int r_step_3(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_32, 3))) return 0; + if (!find_among_b(z, a_32, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2972,9 +2972,9 @@ static int r_step3(struct SN_env * z) { return 1; } -static int r_step4(struct SN_env * z) { +static int r_step_4(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_33, 4))) return 0; + if (!find_among_b(z, a_33, 4)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -2994,7 +2994,7 @@ static int r_step4(struct SN_env * z) { } lab0: z->bra = z->c; - if (!(find_among_b(z, a_34, 36))) return 0; + if (!find_among_b(z, a_34, 36)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_71); if (ret < 0) return ret; @@ -3002,9 +3002,11 @@ static int r_step4(struct SN_env * z) { return 1; } -static int r_step5a(struct SN_env * z) { +static int r_step_5a(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; + z->ket = z->c; if (!(eq_s_b(z, 10, s_72))) goto lab0; + z->bra = z->c; if (z->c > z->lb) goto lab0; { int ret = slice_from_s(z, 8, s_73); if (ret < 0) return ret; @@ -3015,7 +3017,7 @@ static int r_step5a(struct SN_env * z) { { int m2 = z->l - z->c; (void)m2; z->ket = z->c; if (z->c - 9 <= z->lb || z->p[z->c - 1] != 181) goto lab1; - if (!(find_among_b(z, a_35, 5))) goto lab1; + if (!find_among_b(z, a_35, 5)) goto lab1; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3033,7 +3035,7 @@ static int r_step5a(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_36, 12))) return 0; + if (!find_among_b(z, a_36, 12)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_75); if (ret < 0) return ret; @@ -3041,11 +3043,11 @@ static int r_step5a(struct SN_env * z) { return 1; } -static int r_step5b(struct SN_env * z) { +static int r_step_5b(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c - 9 <= z->lb || z->p[z->c - 1] != 181) goto lab0; - if (!(find_among_b(z, a_38, 11))) goto lab0; + if (!find_among_b(z, a_38, 11)) goto lab0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3054,7 +3056,7 @@ static int r_step5b(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 129 && z->p[z->c - 1] != 131)) goto lab0; - if (!(find_among_b(z, a_37, 2))) goto lab0; + if (!find_among_b(z, a_37, 2)) goto lab0; if (z->c > z->lb) goto lab0; { int ret = slice_from_s(z, 8, s_76); if (ret < 0) return ret; @@ -3083,7 +3085,7 @@ static int r_step5b(struct SN_env * z) { } lab1: z->bra = z->c; - if (!(find_among_b(z, a_39, 95))) return 0; + if (!find_among_b(z, a_39, 95)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_79); if (ret < 0) return ret; @@ -3091,11 +3093,11 @@ static int r_step5b(struct SN_env * z) { return 1; } -static int r_step5c(struct SN_env * z) { +static int r_step_5c(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (z->c - 9 <= z->lb || z->p[z->c - 1] != 181) goto lab0; - if (!(find_among_b(z, a_40, 1))) goto lab0; + if (!find_among_b(z, a_40, 1)) goto lab0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3123,7 +3125,7 @@ static int r_step5c(struct SN_env * z) { z->c = z->l - m2; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_41, 31))) goto lab3; + if (!find_among_b(z, a_41, 31)) goto lab3; { int ret = slice_from_s(z, 4, s_82); if (ret < 0) return ret; } @@ -3134,7 +3136,7 @@ static int r_step5c(struct SN_env * z) { } lab1: z->bra = z->c; - if (!(find_among_b(z, a_42, 25))) return 0; + if (!find_among_b(z, a_42, 25)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_83); if (ret < 0) return ret; @@ -3142,10 +3144,10 @@ static int r_step5c(struct SN_env * z) { return 1; } -static int r_step5d(struct SN_env * z) { +static int r_step_5d(struct SN_env * z) { z->ket = z->c; if (z->c - 9 <= z->lb || z->p[z->c - 1] != 131) return 0; - if (!(find_among_b(z, a_43, 2))) return 0; + if (!find_among_b(z, a_43, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3173,10 +3175,10 @@ static int r_step5d(struct SN_env * z) { return 1; } -static int r_step5e(struct SN_env * z) { +static int r_step_5e(struct SN_env * z) { z->ket = z->c; if (z->c - 11 <= z->lb || z->p[z->c - 1] != 181) return 0; - if (!(find_among_b(z, a_44, 2))) return 0; + if (!find_among_b(z, a_44, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3192,7 +3194,7 @@ static int r_step5e(struct SN_env * z) { return 1; } -static int r_step5f(struct SN_env * z) { +static int r_step_5f(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; if (!(eq_s_b(z, 10, s_90))) goto lab0; @@ -3204,7 +3206,7 @@ static int r_step5f(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 128 && z->p[z->c - 1] != 134)) goto lab0; - if (!(find_among_b(z, a_45, 6))) goto lab0; + if (!find_among_b(z, a_45, 6)) goto lab0; if (z->c > z->lb) goto lab0; { int ret = slice_from_s(z, 8, s_91); if (ret < 0) return ret; @@ -3221,7 +3223,7 @@ static int r_step5f(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_46, 9))) return 0; + if (!find_among_b(z, a_46, 9)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 8, s_93); if (ret < 0) return ret; @@ -3229,10 +3231,10 @@ static int r_step5f(struct SN_env * z) { return 1; } -static int r_step5g(struct SN_env * z) { +static int r_step_5g(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (!(find_among_b(z, a_47, 3))) goto lab0; + if (!find_among_b(z, a_47, 3)) goto lab0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3242,7 +3244,7 @@ static int r_step5g(struct SN_env * z) { z->c = z->l - m1; } z->ket = z->c; - if (!(find_among_b(z, a_50, 3))) return 0; + if (!find_among_b(z, a_50, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3251,7 +3253,7 @@ static int r_step5g(struct SN_env * z) { { int m2 = z->l - z->c; (void)m2; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_48, 6))) goto lab2; + if (!find_among_b(z, a_48, 6)) goto lab2; { int ret = slice_from_s(z, 4, s_94); if (ret < 0) return ret; } @@ -3261,7 +3263,7 @@ static int r_step5g(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 184) return 0; - if (!(find_among_b(z, a_49, 5))) return 0; + if (!find_among_b(z, a_49, 5)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_95); if (ret < 0) return ret; @@ -3271,9 +3273,9 @@ static int r_step5g(struct SN_env * z) { return 1; } -static int r_step5h(struct SN_env * z) { +static int r_step_5h(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_53, 3))) return 0; + if (!find_among_b(z, a_53, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3282,7 +3284,7 @@ static int r_step5h(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_51, 12))) goto lab1; + if (!find_among_b(z, a_51, 12)) goto lab1; { int ret = slice_from_s(z, 6, s_96); if (ret < 0) return ret; } @@ -3291,7 +3293,7 @@ static int r_step5h(struct SN_env * z) { z->c = z->l - m1; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_52, 25))) return 0; + if (!find_among_b(z, a_52, 25)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 6, s_97); if (ret < 0) return ret; @@ -3301,10 +3303,10 @@ static int r_step5h(struct SN_env * z) { return 1; } -static int r_step5i(struct SN_env * z) { +static int r_step_5i(struct SN_env * z) { int among_var; z->ket = z->c; - if (!(find_among_b(z, a_56, 3))) return 0; + if (!find_among_b(z, a_56, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3324,7 +3326,7 @@ static int r_step5i(struct SN_env * z) { z->ket = z->c; z->bra = z->c; among_var = find_among_b(z, a_54, 12); - if (!(among_var)) goto lab3; + if (!among_var) goto lab3; switch (among_var) { case 1: { int ret = slice_from_s(z, 4, s_100); @@ -3337,7 +3339,7 @@ static int r_step5i(struct SN_env * z) { z->c = z->l - m2; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_55, 44))) return 0; + if (!find_among_b(z, a_55, 44)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_101); if (ret < 0) return ret; @@ -3350,9 +3352,9 @@ static int r_step5i(struct SN_env * z) { return 1; } -static int r_step5j(struct SN_env * z) { +static int r_step_5j(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_57, 3))) return 0; + if (!find_among_b(z, a_57, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3361,7 +3363,7 @@ static int r_step5j(struct SN_env * z) { z->ket = z->c; z->bra = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 189) return 0; - if (!(find_among_b(z, a_58, 6))) return 0; + if (!find_among_b(z, a_58, 6)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 4, s_102); if (ret < 0) return ret; @@ -3369,10 +3371,10 @@ static int r_step5j(struct SN_env * z) { return 1; } -static int r_step5k(struct SN_env * z) { +static int r_step_5k(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || z->p[z->c - 1] != 181) return 0; - if (!(find_among_b(z, a_59, 1))) return 0; + if (!find_among_b(z, a_59, 1)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3380,7 +3382,7 @@ static int r_step5k(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_60, 10))) return 0; + if (!find_among_b(z, a_60, 10)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 6, s_103); if (ret < 0) return ret; @@ -3388,10 +3390,10 @@ static int r_step5k(struct SN_env * z) { return 1; } -static int r_step5l(struct SN_env * z) { +static int r_step_5l(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || z->p[z->c - 1] != 181) return 0; - if (!(find_among_b(z, a_61, 3))) return 0; + if (!find_among_b(z, a_61, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3399,7 +3401,7 @@ static int r_step5l(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_62, 6))) return 0; + if (!find_among_b(z, a_62, 6)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 6, s_104); if (ret < 0) return ret; @@ -3407,10 +3409,10 @@ static int r_step5l(struct SN_env * z) { return 1; } -static int r_step5m(struct SN_env * z) { +static int r_step_5m(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || z->p[z->c - 1] != 181) return 0; - if (!(find_among_b(z, a_63, 3))) return 0; + if (!find_among_b(z, a_63, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3418,7 +3420,7 @@ static int r_step5m(struct SN_env * z) { z->I[0] = 0; z->ket = z->c; z->bra = z->c; - if (!(find_among_b(z, a_64, 7))) return 0; + if (!find_among_b(z, a_64, 7)) return 0; if (z->c > z->lb) return 0; { int ret = slice_from_s(z, 6, s_105); if (ret < 0) return ret; @@ -3426,10 +3428,10 @@ static int r_step5m(struct SN_env * z) { return 1; } -static int r_step6(struct SN_env * z) { +static int r_step_6(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (!(find_among_b(z, a_65, 3))) goto lab0; + if (!find_among_b(z, a_65, 3)) goto lab0; z->bra = z->c; { int ret = slice_from_s(z, 4, s_106); if (ret < 0) return ret; @@ -3439,7 +3441,7 @@ static int r_step6(struct SN_env * z) { } if (!(z->I[0])) return 0; z->ket = z->c; - if (!(find_among_b(z, a_66, 84))) return 0; + if (!find_among_b(z, a_66, 84)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3447,10 +3449,10 @@ static int r_step6(struct SN_env * z) { return 1; } -static int r_step7(struct SN_env * z) { +static int r_step_7(struct SN_env * z) { z->ket = z->c; if (z->c - 7 <= z->lb || (z->p[z->c - 1] != 129 && z->p[z->c - 1] != 132)) return 0; - if (!(find_among_b(z, a_67, 8))) return 0; + if (!find_among_b(z, a_67, 8)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -3472,193 +3474,193 @@ extern int greek_UTF_8_stem(struct SN_env * z) { } z->I[0] = 1; { int m2 = z->l - z->c; (void)m2; - { int ret = r_step1(z); + { int ret = r_step_1(z); if (ret < 0) return ret; } z->c = z->l - m2; } { int m3 = z->l - z->c; (void)m3; - { int ret = r_steps1(z); + { int ret = r_step_s1(z); if (ret < 0) return ret; } z->c = z->l - m3; } { int m4 = z->l - z->c; (void)m4; - { int ret = r_steps2(z); + { int ret = r_step_s2(z); if (ret < 0) return ret; } z->c = z->l - m4; } { int m5 = z->l - z->c; (void)m5; - { int ret = r_steps3(z); + { int ret = r_step_s3(z); if (ret < 0) return ret; } z->c = z->l - m5; } { int m6 = z->l - z->c; (void)m6; - { int ret = r_steps4(z); + { int ret = r_step_s4(z); if (ret < 0) return ret; } z->c = z->l - m6; } { int m7 = z->l - z->c; (void)m7; - { int ret = r_steps5(z); + { int ret = r_step_s5(z); if (ret < 0) return ret; } z->c = z->l - m7; } { int m8 = z->l - z->c; (void)m8; - { int ret = r_steps6(z); + { int ret = r_step_s6(z); if (ret < 0) return ret; } z->c = z->l - m8; } { int m9 = z->l - z->c; (void)m9; - { int ret = r_steps7(z); + { int ret = r_step_s7(z); if (ret < 0) return ret; } z->c = z->l - m9; } { int m10 = z->l - z->c; (void)m10; - { int ret = r_steps8(z); + { int ret = r_step_s8(z); if (ret < 0) return ret; } z->c = z->l - m10; } { int m11 = z->l - z->c; (void)m11; - { int ret = r_steps9(z); + { int ret = r_step_s9(z); if (ret < 0) return ret; } z->c = z->l - m11; } { int m12 = z->l - z->c; (void)m12; - { int ret = r_steps10(z); + { int ret = r_step_s10(z); if (ret < 0) return ret; } z->c = z->l - m12; } { int m13 = z->l - z->c; (void)m13; - { int ret = r_step2a(z); + { int ret = r_step_2a(z); if (ret < 0) return ret; } z->c = z->l - m13; } { int m14 = z->l - z->c; (void)m14; - { int ret = r_step2b(z); + { int ret = r_step_2b(z); if (ret < 0) return ret; } z->c = z->l - m14; } { int m15 = z->l - z->c; (void)m15; - { int ret = r_step2c(z); + { int ret = r_step_2c(z); if (ret < 0) return ret; } z->c = z->l - m15; } { int m16 = z->l - z->c; (void)m16; - { int ret = r_step2d(z); + { int ret = r_step_2d(z); if (ret < 0) return ret; } z->c = z->l - m16; } { int m17 = z->l - z->c; (void)m17; - { int ret = r_step3(z); + { int ret = r_step_3(z); if (ret < 0) return ret; } z->c = z->l - m17; } { int m18 = z->l - z->c; (void)m18; - { int ret = r_step4(z); + { int ret = r_step_4(z); if (ret < 0) return ret; } z->c = z->l - m18; } { int m19 = z->l - z->c; (void)m19; - { int ret = r_step5a(z); + { int ret = r_step_5a(z); if (ret < 0) return ret; } z->c = z->l - m19; } { int m20 = z->l - z->c; (void)m20; - { int ret = r_step5b(z); + { int ret = r_step_5b(z); if (ret < 0) return ret; } z->c = z->l - m20; } { int m21 = z->l - z->c; (void)m21; - { int ret = r_step5c(z); + { int ret = r_step_5c(z); if (ret < 0) return ret; } z->c = z->l - m21; } { int m22 = z->l - z->c; (void)m22; - { int ret = r_step5d(z); + { int ret = r_step_5d(z); if (ret < 0) return ret; } z->c = z->l - m22; } { int m23 = z->l - z->c; (void)m23; - { int ret = r_step5e(z); + { int ret = r_step_5e(z); if (ret < 0) return ret; } z->c = z->l - m23; } { int m24 = z->l - z->c; (void)m24; - { int ret = r_step5f(z); + { int ret = r_step_5f(z); if (ret < 0) return ret; } z->c = z->l - m24; } { int m25 = z->l - z->c; (void)m25; - { int ret = r_step5g(z); + { int ret = r_step_5g(z); if (ret < 0) return ret; } z->c = z->l - m25; } { int m26 = z->l - z->c; (void)m26; - { int ret = r_step5h(z); + { int ret = r_step_5h(z); if (ret < 0) return ret; } z->c = z->l - m26; } { int m27 = z->l - z->c; (void)m27; - { int ret = r_step5j(z); + { int ret = r_step_5j(z); if (ret < 0) return ret; } z->c = z->l - m27; } { int m28 = z->l - z->c; (void)m28; - { int ret = r_step5i(z); + { int ret = r_step_5i(z); if (ret < 0) return ret; } z->c = z->l - m28; } { int m29 = z->l - z->c; (void)m29; - { int ret = r_step5k(z); + { int ret = r_step_5k(z); if (ret < 0) return ret; } z->c = z->l - m29; } { int m30 = z->l - z->c; (void)m30; - { int ret = r_step5l(z); + { int ret = r_step_5l(z); if (ret < 0) return ret; } z->c = z->l - m30; } { int m31 = z->l - z->c; (void)m31; - { int ret = r_step5m(z); + { int ret = r_step_5m(z); if (ret < 0) return ret; } z->c = z->l - m31; } { int m32 = z->l - z->c; (void)m32; - { int ret = r_step6(z); + { int ret = r_step_6(z); if (ret < 0) return ret; } z->c = z->l - m32; } { int m33 = z->l - z->c; (void)m33; - { int ret = r_step7(z); + { int ret = r_step_7(z); if (ret < 0) return ret; } z->c = z->l - m33; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_hindi.c b/src/backend/snowball/libstemmer/stem_UTF_8_hindi.c index ddd7201e1cfec..a2f2ec7f20fee 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_hindi.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_hindi.c @@ -307,7 +307,7 @@ extern int hindi_UTF_8_stem(struct SN_env * z) { z->lb = z->c; z->c = z->l; z->ket = z->c; - if (!(find_among_b(z, a_0, 132))) return 0; + if (!find_among_b(z, a_0, 132)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_hungarian.c b/src/backend/snowball/libstemmer/stem_UTF_8_hungarian.c index 90bee21699c1a..ff193a4d336d6 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_hungarian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_hungarian.c @@ -480,10 +480,11 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->l; { int c1 = z->c; if (in_grouping_U(z, g_v, 97, 369, 0)) goto lab1; + if (in_grouping_U(z, g_v, 97, 369, 1) < 0) goto lab1; { int c2 = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 3 || !((101187584 >> (z->p[z->c + 1] & 0x1f)) & 1)) goto lab3; - if (!(find_among(z, a_0, 8))) goto lab3; + if (!find_among(z, a_0, 8)) goto lab3; goto lab2; lab3: z->c = c2; @@ -498,7 +499,8 @@ static int r_mark_regions(struct SN_env * z) { lab1: z->c = c1; if (out_grouping_U(z, g_v, 97, 369, 0)) return 0; - { + + { int ret = out_grouping_U(z, g_v, 97, 369, 1); if (ret < 0) return 0; z->c += ret; @@ -510,8 +512,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_v_ending(struct SN_env * z) { @@ -519,7 +520,7 @@ static int r_v_ending(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 161 && z->p[z->c - 1] != 169)) return 0; among_var = find_among_b(z, a_1, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -542,7 +543,7 @@ static int r_v_ending(struct SN_env * z) { static int r_double(struct SN_env * z) { { int m_test1 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((106790108 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 23))) return 0; + if (!find_among_b(z, a_2, 23)) return 0; z->c = z->l - m_test1; } return 1; @@ -568,7 +569,7 @@ static int r_undouble(struct SN_env * z) { static int r_instrum(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 108) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -587,7 +588,7 @@ static int r_instrum(struct SN_env * z) { static int r_case(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_4, 44))) return 0; + if (!find_among_b(z, a_4, 44)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -606,7 +607,7 @@ static int r_case_special(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 110 && z->p[z->c - 1] != 116)) return 0; among_var = find_among_b(z, a_5, 3); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -631,7 +632,7 @@ static int r_case_other(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 108) return 0; among_var = find_among_b(z, a_6, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -659,7 +660,7 @@ static int r_case_other(struct SN_env * z) { static int r_factive(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 161 && z->p[z->c - 1] != 169)) return 0; - if (!(find_among_b(z, a_7, 2))) return 0; + if (!find_among_b(z, a_7, 2)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -681,7 +682,7 @@ static int r_plural(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 107) return 0; among_var = find_among_b(z, a_8, 7); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -711,7 +712,7 @@ static int r_owned(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 169)) return 0; among_var = find_among_b(z, a_9, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -740,7 +741,7 @@ static int r_sing_owner(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_10, 31); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -770,7 +771,7 @@ static int r_plur_owner(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((10768 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_11, 42); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_indonesian.c b/src/backend/snowball/libstemmer/stem_UTF_8_indonesian.c index ee9473a056365..2c0e5904951c6 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_indonesian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_indonesian.c @@ -123,7 +123,7 @@ static const symbol s_6[] = { 'a', 'j', 'a', 'r' }; static int r_remove_particle(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 104 && z->p[z->c - 1] != 110)) return 0; - if (!(find_among_b(z, a_0, 3))) return 0; + if (!find_among_b(z, a_0, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -135,7 +135,7 @@ static int r_remove_particle(struct SN_env * z) { static int r_remove_possessive_pronoun(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 117)) return 0; - if (!(find_among_b(z, a_1, 3))) return 0; + if (!find_among_b(z, a_1, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -145,19 +145,18 @@ static int r_remove_possessive_pronoun(struct SN_env * z) { } static int r_SUFFIX_KAN_OK(struct SN_env * z) { - - if (!(z->I[0] != 3)) return 0; - if (!(z->I[0] != 2)) return 0; + + if (z->I[0] == 3) return 0; + if (z->I[0] == 2) return 0; return 1; } static int r_SUFFIX_AN_OK(struct SN_env * z) { - if (!(z->I[0] != 1)) return 0; - return 1; + return z->I[0] != 1; } static int r_SUFFIX_I_OK(struct SN_env * z) { - if (!(z->I[0] <= 2)) return 0; + if (z->I[0] > 2) return 0; { int m1 = z->l - z->c; (void)m1; if (z->c <= z->lb || z->p[z->c - 1] != 's') goto lab0; z->c--; @@ -171,7 +170,7 @@ static int r_SUFFIX_I_OK(struct SN_env * z) { static int r_remove_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 110)) return 0; - if (!(find_among_b(z, a_2, 3))) return 0; + if (!find_among_b(z, a_2, 3)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -196,7 +195,7 @@ static int r_remove_first_order_prefix(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || (z->p[z->c + 1] != 105 && z->p[z->c + 1] != 101)) return 0; among_var = find_among(z, a_3, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -276,7 +275,7 @@ static int r_remove_second_order_prefix(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] != 101) return 0; among_var = find_among(z, a_4, 6); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -315,7 +314,8 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { { int c1 = z->c; while(1) { int c2 = z->c; - { + + { int ret = out_grouping_U(z, g_vowel, 97, 117, 1); if (ret < 0) goto lab1; z->c += ret; @@ -328,7 +328,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { } z->c = c1; } - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; z->I[0] = 0; z->lb = z->c; z->c = z->l; @@ -338,7 +338,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { } z->c = z->l - m3; } - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; { int m4 = z->l - z->c; (void)m4; { int ret = r_remove_possessive_pronoun(z); if (ret < 0) return ret; @@ -346,7 +346,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { z->c = z->l - m4; } z->c = z->lb; - if (!(z->I[1] > 2)) return 0; + if (z->I[1] <= 2) return 0; { int c5 = z->c; { int c_test6 = z->c; { int ret = r_remove_first_order_prefix(z); @@ -355,7 +355,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { } { int c7 = z->c; { int c_test8 = z->c; - if (!(z->I[1] > 2)) goto lab4; + if (z->I[1] <= 2) goto lab4; z->lb = z->c; z->c = z->l; { int ret = r_remove_suffix(z); @@ -365,7 +365,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { z->c = z->lb; z->c = c_test8; } - if (!(z->I[1] > 2)) goto lab4; + if (z->I[1] <= 2) goto lab4; { int ret = r_remove_second_order_prefix(z); if (ret == 0) goto lab4; if (ret < 0) return ret; @@ -385,7 +385,7 @@ extern int indonesian_UTF_8_stem(struct SN_env * z) { z->c = c9; } { int c10 = z->c; - if (!(z->I[1] > 2)) goto lab5; + if (z->I[1] <= 2) goto lab5; z->lb = z->c; z->c = z->l; { int ret = r_remove_suffix(z); diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_irish.c b/src/backend/snowball/libstemmer/stem_UTF_8_irish.c index 9410819dd9862..c79b9ee57e64a 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_irish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_irish.c @@ -225,24 +225,28 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[2] = z->c; - { + + { int ret = in_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab0; z->c += ret; @@ -258,7 +262,7 @@ static int r_initial_morph(struct SN_env * z) { int among_var; z->bra = z->c; among_var = find_among(z, a_0, 24); - if (!(among_var)) return 0; + if (!among_var) return 0; z->ket = z->c; switch (among_var) { case 1: @@ -316,25 +320,22 @@ static int r_initial_morph(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_noun_sfx(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_1, 16); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -361,7 +362,7 @@ static int r_deriv(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_2, 25); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -406,7 +407,7 @@ static int r_verb_sfx(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((282896 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_3, 12); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -436,7 +437,7 @@ extern int irish_UTF_8_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_italian.c b/src/backend/snowball/libstemmer/stem_UTF_8_italian.c index 8a05ce411aa21..cd4db27c84d3c 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_italian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_italian.c @@ -19,6 +19,7 @@ static int r_RV(struct SN_env * z); static int r_mark_regions(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_prelude(struct SN_env * z); +static int r_exceptions(struct SN_env * z); #ifdef __cplusplus extern "C" { #endif @@ -487,6 +488,8 @@ static const symbol s_14[] = { 'e', 'n', 't', 'e' }; static const symbol s_15[] = { 'a', 't' }; static const symbol s_16[] = { 'a', 't' }; static const symbol s_17[] = { 'i', 'c' }; +static const symbol s_18[] = { 'd', 'i', 'v', 'a', 'n', 'o' }; +static const symbol s_19[] = { 'd', 'i', 'v', 'a', 'n' }; static int r_prelude(struct SN_env * z) { int among_var; @@ -495,7 +498,6 @@ static int r_prelude(struct SN_env * z) { int c2 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 7); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -594,7 +596,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping_U(z, g_v, 97, 249, 0)) goto lab2; { int c3 = z->c; if (out_grouping_U(z, g_v, 97, 249, 0)) goto lab4; - { + + { int ret = out_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab4; z->c += ret; @@ -603,7 +606,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping_U(z, g_v, 97, 249, 0)) goto lab2; - { + + { int ret = in_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab2; z->c += ret; @@ -616,7 +620,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping_U(z, g_v, 97, 249, 0)) goto lab0; { int c4 = z->c; if (out_grouping_U(z, g_v, 97, 249, 0)) goto lab6; - { + + { int ret = out_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab6; z->c += ret; @@ -639,23 +644,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 249, 1); if (ret < 0) goto lab7; z->c += ret; @@ -674,7 +683,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 85)) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -703,29 +711,26 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { int among_var; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((33314 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_2, 37))) return 0; + if (!find_among_b(z, a_2, 37)) return 0; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 111 && z->p[z->c - 1] != 114)) return 0; among_var = find_among_b(z, a_3, 5); - if (!(among_var)) return 0; + if (!among_var) return 0; { int ret = r_RV(z); if (ret <= 0) return ret; } @@ -748,7 +753,7 @@ static int r_standard_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_6, 51); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -824,7 +829,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4722696 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m2; goto lab1; } among_var = find_among_b(z, a_4, 4); - if (!(among_var)) { z->c = z->l - m2; goto lab1; } + if (!among_var) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -861,7 +866,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_5, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_5, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -916,7 +921,7 @@ static int r_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_7, 87))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_7, 87)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -971,56 +976,77 @@ static int r_vowel_suffix(struct SN_env * z) { return 1; } +static int r_exceptions(struct SN_env * z) { + z->bra = z->c; + if (!(eq_s(z, 6, s_18))) return 0; + if (z->c < z->l) return 0; + z->ket = z->c; + { int ret = slice_from_s(z, 5, s_19); + if (ret < 0) return ret; + } + return 1; +} + extern int italian_UTF_8_stem(struct SN_env * z) { { int c1 = z->c; - { int ret = r_prelude(z); + { int ret = r_exceptions(z); + if (ret == 0) goto lab1; if (ret < 0) return ret; } + goto lab0; + lab1: z->c = c1; - } - - { int ret = r_mark_regions(z); - if (ret < 0) return ret; - } - z->lb = z->c; z->c = z->l; + { int c2 = z->c; + { int ret = r_prelude(z); + if (ret < 0) return ret; + } + z->c = c2; + } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_attached_pronoun(z); + { int ret = r_mark_regions(z); if (ret < 0) return ret; } - z->c = z->l - m2; - } - { int m3 = z->l - z->c; (void)m3; - { int m4 = z->l - z->c; (void)m4; - { int ret = r_standard_suffix(z); - if (ret == 0) goto lab2; + z->lb = z->c; z->c = z->l; + + { int m3 = z->l - z->c; (void)m3; + { int ret = r_attached_pronoun(z); if (ret < 0) return ret; } - goto lab1; + z->c = z->l - m3; + } + { int m4 = z->l - z->c; (void)m4; + { int m5 = z->l - z->c; (void)m5; + { int ret = r_standard_suffix(z); + if (ret == 0) goto lab4; + if (ret < 0) return ret; + } + goto lab3; + lab4: + z->c = z->l - m5; + { int ret = r_verb_suffix(z); + if (ret == 0) goto lab2; + if (ret < 0) return ret; + } + } + lab3: lab2: z->c = z->l - m4; - { int ret = r_verb_suffix(z); - if (ret == 0) goto lab0; + } + { int m6 = z->l - z->c; (void)m6; + { int ret = r_vowel_suffix(z); if (ret < 0) return ret; } + z->c = z->l - m6; } - lab1: - lab0: - z->c = z->l - m3; - } - { int m5 = z->l - z->c; (void)m5; - { int ret = r_vowel_suffix(z); - if (ret < 0) return ret; - } - z->c = z->l - m5; - } - z->c = z->lb; - { int c6 = z->c; - { int ret = r_postlude(z); - if (ret < 0) return ret; + z->c = z->lb; + { int c7 = z->c; + { int ret = r_postlude(z); + if (ret < 0) return ret; + } + z->c = c7; } - z->c = c6; } +lab0: return 1; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_lithuanian.c b/src/backend/snowball/libstemmer/stem_UTF_8_lithuanian.c index 505b92e23873e..5dd8b038fd48d 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_lithuanian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_lithuanian.c @@ -6,7 +6,6 @@ static int r_fix_conflicts(struct SN_env * z); static int r_fix_gd(struct SN_env * z); static int r_fix_chdz(struct SN_env * z); static int r_step1(struct SN_env * z); -static int r_R1(struct SN_env * z); static int r_step2(struct SN_env * z); #ifdef __cplusplus extern "C" { @@ -626,24 +625,16 @@ static const symbol s_8[] = { 't' }; static const symbol s_9[] = { 'd' }; static const symbol s_10[] = { 'g' }; -static int r_R1(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; -} - static int r_step1(struct SN_env * z) { { int mlimit1; if (z->c < z->I[0]) return 0; mlimit1 = z->lb; z->lb = z->I[0]; z->ket = z->c; - if (!(find_among_b(z, a_0, 204))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_0, 204)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } - { int ret = r_R1(z); - if (ret <= 0) return ret; - } { int ret = slice_del(z); if (ret < 0) return ret; } @@ -658,7 +649,7 @@ static int r_step2(struct SN_env * z) { if (z->c < z->I[0]) goto lab0; mlimit2 = z->lb; z->lb = z->I[0]; z->ket = z->c; - if (!(find_among_b(z, a_1, 62))) { z->lb = mlimit2; goto lab0; } + if (!find_among_b(z, a_1, 62)) { z->lb = mlimit2; goto lab0; } z->bra = z->c; z->lb = mlimit2; } @@ -678,7 +669,7 @@ static int r_fix_conflicts(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((2621472 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_2, 11); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -730,7 +721,7 @@ static int r_fix_chdz(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 141 && z->p[z->c - 1] != 190)) return 0; among_var = find_among_b(z, a_3, 2); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -750,7 +741,7 @@ static int r_fix_chdz(struct SN_env * z) { static int r_fix_gd(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 100) return 0; - if (!(find_among_b(z, a_4, 1))) return 0; + if (!find_among_b(z, a_4, 1)) return 0; z->bra = z->c; { int ret = slice_from_s(z, 1, s_10); if (ret < 0) return ret; @@ -767,7 +758,7 @@ extern int lithuanian_UTF_8_stem(struct SN_env * z) { z->c++; z->c = c_test3; } - if (!(len_utf8(z->p) > 6)) { z->c = c2; goto lab1; } + if (len_utf8(z->p) <= 6) { z->c = c2; goto lab1; } { int ret = skip_utf8(z->p, z->c, z->l, 1); if (ret < 0) { z->c = c2; goto lab1; } z->c = ret; @@ -775,12 +766,14 @@ extern int lithuanian_UTF_8_stem(struct SN_env * z) { lab1: ; } - { + + { int ret = out_grouping_U(z, g_v, 97, 371, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 371, 1); if (ret < 0) goto lab0; z->c += ret; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_nepali.c b/src/backend/snowball/libstemmer/stem_UTF_8_nepali.c index b1810c55cb141..7cec8523cfa1f 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_nepali.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_nepali.c @@ -285,7 +285,7 @@ static int r_remove_category_1(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_0, 17); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -319,7 +319,7 @@ static int r_remove_category_1(struct SN_env * z) { static int r_check_category_2(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((262 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 3))) return 0; + if (!find_among_b(z, a_1, 3)) return 0; z->bra = z->c; return 1; } @@ -329,7 +329,7 @@ static int r_remove_category_2(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((262 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_2, 3); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -365,7 +365,7 @@ static int r_remove_category_2(struct SN_env * z) { static int r_remove_category_3(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_3, 91))) return 0; + if (!find_among_b(z, a_3, 91)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_norwegian.c b/src/backend/snowball/libstemmer/stem_UTF_8_norwegian.c index 41aa668a968f9..8d50961d50bf1 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_norwegian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_norwegian.c @@ -140,15 +140,17 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->c; z->c = c_test1; } + if (out_grouping_U(z, g_v, 97, 248, 1) < 0) return 0; - { + + { int ret = in_grouping_U(z, g_v, 97, 248, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -163,7 +165,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851426 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 29); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -205,7 +207,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit2 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] != 116) { z->lb = mlimit2; return 0; } - if (!(find_among_b(z, a_1, 2))) { z->lb = mlimit2; return 0; } + if (!find_among_b(z, a_1, 2)) { z->lb = mlimit2; return 0; } z->bra = z->c; z->lb = mlimit2; } @@ -229,7 +231,7 @@ static int r_other_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718720 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_2, 11))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_2, 11)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_porter.c b/src/backend/snowball/libstemmer/stem_UTF_8_porter.c index fb44f5626a754..297ce1405009c 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_porter.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_porter.c @@ -230,13 +230,11 @@ static int r_shortv(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_Step_1a(struct SN_env * z) { @@ -244,7 +242,7 @@ static int r_Step_1a(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] != 115) return 0; among_var = find_among_b(z, a_0, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -271,7 +269,7 @@ static int r_Step_1b(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 100 && z->p[z->c - 1] != 103)) return 0; among_var = find_among_b(z, a_2, 3); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -284,7 +282,8 @@ static int r_Step_1b(struct SN_env * z) { break; case 2: { int m_test1 = z->l - z->c; - { + + { int ret = out_grouping_b_U(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -297,7 +296,6 @@ static int r_Step_1b(struct SN_env * z) { { int m_test2 = z->l - z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((68514004 >> (z->p[z->c - 1] & 0x1f)) & 1)) among_var = 3; else among_var = find_among_b(z, a_1, 13); - if (!(among_var)) return 0; z->c = z->l - m_test2; } switch (among_var) { @@ -356,7 +354,8 @@ static int r_Step_1c(struct SN_env * z) { } lab0: z->bra = z->c; - { + + { int ret = out_grouping_b_U(z, g_v, 97, 121, 1); if (ret < 0) return 0; z->c -= ret; @@ -372,7 +371,7 @@ static int r_Step_2(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((815616 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_3, 20); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -452,7 +451,7 @@ static int r_Step_3(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((528928 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_4, 7); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -482,7 +481,7 @@ static int r_Step_4(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((3961384 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 19); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -517,26 +516,24 @@ static int r_Step_5a(struct SN_env * z) { if (z->c <= z->lb || z->p[z->c - 1] != 'e') return 0; z->c--; z->bra = z->c; + + { int ret = r_R2(z); + if (ret == 0) goto lab1; + if (ret < 0) return ret; + } + goto lab0; +lab1: + { int ret = r_R1(z); + if (ret <= 0) return ret; + } { int m1 = z->l - z->c; (void)m1; - { int ret = r_R2(z); - if (ret == 0) goto lab1; + { int ret = r_shortv(z); + if (ret == 0) goto lab2; if (ret < 0) return ret; } - goto lab0; - lab1: + return 0; + lab2: z->c = z->l - m1; - { int ret = r_R1(z); - if (ret <= 0) return ret; - } - { int m2 = z->l - z->c; (void)m2; - { int ret = r_shortv(z); - if (ret == 0) goto lab2; - if (ret < 0) return ret; - } - return 0; - lab2: - z->c = z->l - m2; - } } lab0: { int ret = slice_del(z); @@ -608,23 +605,27 @@ extern int porter_UTF_8_stem(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 121, 1); if (ret < 0) goto lab4; z->c += ret; diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_portuguese.c b/src/backend/snowball/libstemmer/stem_UTF_8_portuguese.c index af0a8e1764adb..3ccf24cd735e9 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_portuguese.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_portuguese.c @@ -479,7 +479,6 @@ static int r_prelude(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || (z->p[z->c + 1] != 163 && z->p[z->c + 1] != 181)) among_var = 3; else among_var = find_among(z, a_0, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -516,7 +515,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping_U(z, g_v, 97, 250, 0)) goto lab2; { int c3 = z->c; if (out_grouping_U(z, g_v, 97, 250, 0)) goto lab4; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab4; z->c += ret; @@ -525,7 +525,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping_U(z, g_v, 97, 250, 0)) goto lab2; - { + + { int ret = in_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab2; z->c += ret; @@ -538,7 +539,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping_U(z, g_v, 97, 250, 0)) goto lab0; { int c4 = z->c; if (out_grouping_U(z, g_v, 97, 250, 0)) goto lab6; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab6; z->c += ret; @@ -561,23 +563,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 250, 1); if (ret < 0) goto lab7; z->c += ret; @@ -596,7 +602,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] != 126) among_var = 3; else among_var = find_among(z, a_1, 3); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -625,18 +630,15 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_standard_suffix(struct SN_env * z) { @@ -644,7 +646,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((823330 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_5, 45); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -690,7 +692,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718616 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m1; goto lab0; } among_var = find_among_b(z, a_2, 4); - if (!(among_var)) { z->c = z->l - m1; goto lab0; } + if (!among_var) { z->c = z->l - m1; goto lab0; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m1; goto lab0; } @@ -727,7 +729,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m2 = z->l - z->c; (void)m2; z->ket = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 101 && z->p[z->c - 1] != 108)) { z->c = z->l - m2; goto lab1; } - if (!(find_among_b(z, a_3, 3))) { z->c = z->l - m2; goto lab1; } + if (!find_among_b(z, a_3, 3)) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -750,7 +752,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_4, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_4, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -805,7 +807,7 @@ static int r_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_6, 120))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_6, 120)) { z->lb = mlimit1; return 0; } z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -817,7 +819,7 @@ static int r_verb_suffix(struct SN_env * z) { static int r_residual_suffix(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_7, 7))) return 0; + if (!find_among_b(z, a_7, 7)) return 0; z->bra = z->c; { int ret = r_RV(z); if (ret <= 0) return ret; @@ -832,7 +834,7 @@ static int r_residual_form(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_8, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -888,7 +890,7 @@ extern int portuguese_UTF_8_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_romanian.c b/src/backend/snowball/libstemmer/stem_UTF_8_romanian.c index d4bbbf53a4e46..f0d688a9413f5 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_romanian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_romanian.c @@ -20,6 +20,7 @@ static int r_RV(struct SN_env * z); static int r_mark_regions(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_prelude(struct SN_env * z); +static int r_norm(struct SN_env * z); #ifdef __cplusplus extern "C" { #endif @@ -32,509 +33,563 @@ extern void romanian_UTF_8_close_env(struct SN_env * z); #ifdef __cplusplus } #endif -static const symbol s_0_1[1] = { 'I' }; -static const symbol s_0_2[1] = { 'U' }; +static const symbol s_0_0[2] = { 0xC5, 0x9F }; +static const symbol s_0_1[2] = { 0xC5, 0xA3 }; -static const struct among a_0[3] = +static const struct among a_0[2] = { -{ 0, 0, -1, 3, 0}, -{ 1, s_0_1, 0, 1, 0}, -{ 1, s_0_2, 0, 2, 0} +{ 2, s_0_0, -1, 1, 0}, +{ 2, s_0_1, -1, 2, 0} }; -static const symbol s_1_0[2] = { 'e', 'a' }; -static const symbol s_1_1[5] = { 'a', 0xC5, 0xA3, 'i', 'a' }; -static const symbol s_1_2[3] = { 'a', 'u', 'a' }; -static const symbol s_1_3[3] = { 'i', 'u', 'a' }; -static const symbol s_1_4[5] = { 'a', 0xC5, 0xA3, 'i', 'e' }; -static const symbol s_1_5[3] = { 'e', 'l', 'e' }; -static const symbol s_1_6[3] = { 'i', 'l', 'e' }; -static const symbol s_1_7[4] = { 'i', 'i', 'l', 'e' }; -static const symbol s_1_8[3] = { 'i', 'e', 'i' }; -static const symbol s_1_9[4] = { 'a', 't', 'e', 'i' }; -static const symbol s_1_10[2] = { 'i', 'i' }; -static const symbol s_1_11[4] = { 'u', 'l', 'u', 'i' }; -static const symbol s_1_12[2] = { 'u', 'l' }; -static const symbol s_1_13[4] = { 'e', 'l', 'o', 'r' }; -static const symbol s_1_14[4] = { 'i', 'l', 'o', 'r' }; -static const symbol s_1_15[5] = { 'i', 'i', 'l', 'o', 'r' }; - -static const struct among a_1[16] = +static const symbol s_1_1[1] = { 'I' }; +static const symbol s_1_2[1] = { 'U' }; + +static const struct among a_1[3] = { -{ 2, s_1_0, -1, 3, 0}, -{ 5, s_1_1, -1, 7, 0}, -{ 3, s_1_2, -1, 2, 0}, -{ 3, s_1_3, -1, 4, 0}, -{ 5, s_1_4, -1, 7, 0}, -{ 3, s_1_5, -1, 3, 0}, -{ 3, s_1_6, -1, 5, 0}, -{ 4, s_1_7, 6, 4, 0}, -{ 3, s_1_8, -1, 4, 0}, -{ 4, s_1_9, -1, 6, 0}, -{ 2, s_1_10, -1, 4, 0}, -{ 4, s_1_11, -1, 1, 0}, -{ 2, s_1_12, -1, 1, 0}, -{ 4, s_1_13, -1, 3, 0}, -{ 4, s_1_14, -1, 4, 0}, -{ 5, s_1_15, 14, 4, 0} +{ 0, 0, -1, 3, 0}, +{ 1, s_1_1, 0, 1, 0}, +{ 1, s_1_2, 0, 2, 0} }; -static const symbol s_2_0[5] = { 'i', 'c', 'a', 'l', 'a' }; -static const symbol s_2_1[5] = { 'i', 'c', 'i', 'v', 'a' }; -static const symbol s_2_2[5] = { 'a', 't', 'i', 'v', 'a' }; -static const symbol s_2_3[5] = { 'i', 't', 'i', 'v', 'a' }; -static const symbol s_2_4[5] = { 'i', 'c', 'a', 'l', 'e' }; -static const symbol s_2_5[7] = { 'a', 0xC5, 0xA3, 'i', 'u', 'n', 'e' }; -static const symbol s_2_6[7] = { 'i', 0xC5, 0xA3, 'i', 'u', 'n', 'e' }; -static const symbol s_2_7[6] = { 'a', 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_8[6] = { 'i', 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_9[7] = { 0xC4, 0x83, 't', 'o', 'a', 'r', 'e' }; -static const symbol s_2_10[7] = { 'i', 'c', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_11[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_12[9] = { 'i', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_13[7] = { 'i', 'v', 'i', 't', 'a', 't', 'e' }; -static const symbol s_2_14[5] = { 'i', 'c', 'i', 'v', 'e' }; -static const symbol s_2_15[5] = { 'a', 't', 'i', 'v', 'e' }; -static const symbol s_2_16[5] = { 'i', 't', 'i', 'v', 'e' }; -static const symbol s_2_17[5] = { 'i', 'c', 'a', 'l', 'i' }; -static const symbol s_2_18[5] = { 'a', 't', 'o', 'r', 'i' }; -static const symbol s_2_19[7] = { 'i', 'c', 'a', 't', 'o', 'r', 'i' }; -static const symbol s_2_20[5] = { 'i', 't', 'o', 'r', 'i' }; -static const symbol s_2_21[6] = { 0xC4, 0x83, 't', 'o', 'r', 'i' }; -static const symbol s_2_22[7] = { 'i', 'c', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_23[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_24[7] = { 'i', 'v', 'i', 't', 'a', 't', 'i' }; -static const symbol s_2_25[5] = { 'i', 'c', 'i', 'v', 'i' }; -static const symbol s_2_26[5] = { 'a', 't', 'i', 'v', 'i' }; -static const symbol s_2_27[5] = { 'i', 't', 'i', 'v', 'i' }; -static const symbol s_2_28[7] = { 'i', 'c', 'i', 't', 0xC4, 0x83, 'i' }; -static const symbol s_2_29[9] = { 'a', 'b', 'i', 'l', 'i', 't', 0xC4, 0x83, 'i' }; -static const symbol s_2_30[7] = { 'i', 'v', 'i', 't', 0xC4, 0x83, 'i' }; -static const symbol s_2_31[9] = { 'i', 'c', 'i', 't', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_2_32[11] = { 'a', 'b', 'i', 'l', 'i', 't', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_2_33[9] = { 'i', 'v', 'i', 't', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_2_34[4] = { 'i', 'c', 'a', 'l' }; -static const symbol s_2_35[4] = { 'a', 't', 'o', 'r' }; -static const symbol s_2_36[6] = { 'i', 'c', 'a', 't', 'o', 'r' }; -static const symbol s_2_37[4] = { 'i', 't', 'o', 'r' }; -static const symbol s_2_38[5] = { 0xC4, 0x83, 't', 'o', 'r' }; -static const symbol s_2_39[4] = { 'i', 'c', 'i', 'v' }; -static const symbol s_2_40[4] = { 'a', 't', 'i', 'v' }; -static const symbol s_2_41[4] = { 'i', 't', 'i', 'v' }; -static const symbol s_2_42[6] = { 'i', 'c', 'a', 'l', 0xC4, 0x83 }; -static const symbol s_2_43[6] = { 'i', 'c', 'i', 'v', 0xC4, 0x83 }; -static const symbol s_2_44[6] = { 'a', 't', 'i', 'v', 0xC4, 0x83 }; -static const symbol s_2_45[6] = { 'i', 't', 'i', 'v', 0xC4, 0x83 }; - -static const struct among a_2[46] = +static const symbol s_2_0[2] = { 'e', 'a' }; +static const symbol s_2_1[5] = { 'a', 0xC8, 0x9B, 'i', 'a' }; +static const symbol s_2_2[3] = { 'a', 'u', 'a' }; +static const symbol s_2_3[3] = { 'i', 'u', 'a' }; +static const symbol s_2_4[5] = { 'a', 0xC8, 0x9B, 'i', 'e' }; +static const symbol s_2_5[3] = { 'e', 'l', 'e' }; +static const symbol s_2_6[3] = { 'i', 'l', 'e' }; +static const symbol s_2_7[4] = { 'i', 'i', 'l', 'e' }; +static const symbol s_2_8[3] = { 'i', 'e', 'i' }; +static const symbol s_2_9[4] = { 'a', 't', 'e', 'i' }; +static const symbol s_2_10[2] = { 'i', 'i' }; +static const symbol s_2_11[4] = { 'u', 'l', 'u', 'i' }; +static const symbol s_2_12[2] = { 'u', 'l' }; +static const symbol s_2_13[4] = { 'e', 'l', 'o', 'r' }; +static const symbol s_2_14[4] = { 'i', 'l', 'o', 'r' }; +static const symbol s_2_15[5] = { 'i', 'i', 'l', 'o', 'r' }; + +static const struct among a_2[16] = { -{ 5, s_2_0, -1, 4, 0}, -{ 5, s_2_1, -1, 4, 0}, -{ 5, s_2_2, -1, 5, 0}, -{ 5, s_2_3, -1, 6, 0}, -{ 5, s_2_4, -1, 4, 0}, -{ 7, s_2_5, -1, 5, 0}, -{ 7, s_2_6, -1, 6, 0}, -{ 6, s_2_7, -1, 5, 0}, -{ 6, s_2_8, -1, 6, 0}, -{ 7, s_2_9, -1, 5, 0}, -{ 7, s_2_10, -1, 4, 0}, -{ 9, s_2_11, -1, 1, 0}, -{ 9, s_2_12, -1, 2, 0}, -{ 7, s_2_13, -1, 3, 0}, -{ 5, s_2_14, -1, 4, 0}, -{ 5, s_2_15, -1, 5, 0}, -{ 5, s_2_16, -1, 6, 0}, -{ 5, s_2_17, -1, 4, 0}, -{ 5, s_2_18, -1, 5, 0}, -{ 7, s_2_19, 18, 4, 0}, -{ 5, s_2_20, -1, 6, 0}, -{ 6, s_2_21, -1, 5, 0}, -{ 7, s_2_22, -1, 4, 0}, -{ 9, s_2_23, -1, 1, 0}, -{ 7, s_2_24, -1, 3, 0}, -{ 5, s_2_25, -1, 4, 0}, -{ 5, s_2_26, -1, 5, 0}, -{ 5, s_2_27, -1, 6, 0}, -{ 7, s_2_28, -1, 4, 0}, -{ 9, s_2_29, -1, 1, 0}, -{ 7, s_2_30, -1, 3, 0}, -{ 9, s_2_31, -1, 4, 0}, -{ 11, s_2_32, -1, 1, 0}, -{ 9, s_2_33, -1, 3, 0}, -{ 4, s_2_34, -1, 4, 0}, -{ 4, s_2_35, -1, 5, 0}, -{ 6, s_2_36, 35, 4, 0}, -{ 4, s_2_37, -1, 6, 0}, -{ 5, s_2_38, -1, 5, 0}, -{ 4, s_2_39, -1, 4, 0}, -{ 4, s_2_40, -1, 5, 0}, -{ 4, s_2_41, -1, 6, 0}, -{ 6, s_2_42, -1, 4, 0}, -{ 6, s_2_43, -1, 4, 0}, -{ 6, s_2_44, -1, 5, 0}, -{ 6, s_2_45, -1, 6, 0} +{ 2, s_2_0, -1, 3, 0}, +{ 5, s_2_1, -1, 7, 0}, +{ 3, s_2_2, -1, 2, 0}, +{ 3, s_2_3, -1, 4, 0}, +{ 5, s_2_4, -1, 7, 0}, +{ 3, s_2_5, -1, 3, 0}, +{ 3, s_2_6, -1, 5, 0}, +{ 4, s_2_7, 6, 4, 0}, +{ 3, s_2_8, -1, 4, 0}, +{ 4, s_2_9, -1, 6, 0}, +{ 2, s_2_10, -1, 4, 0}, +{ 4, s_2_11, -1, 1, 0}, +{ 2, s_2_12, -1, 1, 0}, +{ 4, s_2_13, -1, 3, 0}, +{ 4, s_2_14, -1, 4, 0}, +{ 5, s_2_15, 14, 4, 0} }; -static const symbol s_3_0[3] = { 'i', 'c', 'a' }; -static const symbol s_3_1[5] = { 'a', 'b', 'i', 'l', 'a' }; -static const symbol s_3_2[5] = { 'i', 'b', 'i', 'l', 'a' }; -static const symbol s_3_3[4] = { 'o', 'a', 's', 'a' }; -static const symbol s_3_4[3] = { 'a', 't', 'a' }; -static const symbol s_3_5[3] = { 'i', 't', 'a' }; -static const symbol s_3_6[4] = { 'a', 'n', 't', 'a' }; -static const symbol s_3_7[4] = { 'i', 's', 't', 'a' }; -static const symbol s_3_8[3] = { 'u', 't', 'a' }; -static const symbol s_3_9[3] = { 'i', 'v', 'a' }; -static const symbol s_3_10[2] = { 'i', 'c' }; -static const symbol s_3_11[3] = { 'i', 'c', 'e' }; -static const symbol s_3_12[5] = { 'a', 'b', 'i', 'l', 'e' }; -static const symbol s_3_13[5] = { 'i', 'b', 'i', 'l', 'e' }; -static const symbol s_3_14[4] = { 'i', 's', 'm', 'e' }; -static const symbol s_3_15[4] = { 'i', 'u', 'n', 'e' }; -static const symbol s_3_16[4] = { 'o', 'a', 's', 'e' }; -static const symbol s_3_17[3] = { 'a', 't', 'e' }; -static const symbol s_3_18[5] = { 'i', 't', 'a', 't', 'e' }; -static const symbol s_3_19[3] = { 'i', 't', 'e' }; -static const symbol s_3_20[4] = { 'a', 'n', 't', 'e' }; -static const symbol s_3_21[4] = { 'i', 's', 't', 'e' }; -static const symbol s_3_22[3] = { 'u', 't', 'e' }; -static const symbol s_3_23[3] = { 'i', 'v', 'e' }; -static const symbol s_3_24[3] = { 'i', 'c', 'i' }; -static const symbol s_3_25[5] = { 'a', 'b', 'i', 'l', 'i' }; -static const symbol s_3_26[5] = { 'i', 'b', 'i', 'l', 'i' }; -static const symbol s_3_27[4] = { 'i', 'u', 'n', 'i' }; -static const symbol s_3_28[5] = { 'a', 't', 'o', 'r', 'i' }; -static const symbol s_3_29[3] = { 'o', 's', 'i' }; -static const symbol s_3_30[3] = { 'a', 't', 'i' }; -static const symbol s_3_31[5] = { 'i', 't', 'a', 't', 'i' }; -static const symbol s_3_32[3] = { 'i', 't', 'i' }; -static const symbol s_3_33[4] = { 'a', 'n', 't', 'i' }; -static const symbol s_3_34[4] = { 'i', 's', 't', 'i' }; -static const symbol s_3_35[3] = { 'u', 't', 'i' }; -static const symbol s_3_36[5] = { 'i', 0xC5, 0x9F, 't', 'i' }; -static const symbol s_3_37[3] = { 'i', 'v', 'i' }; -static const symbol s_3_38[5] = { 'i', 't', 0xC4, 0x83, 'i' }; -static const symbol s_3_39[4] = { 'o', 0xC5, 0x9F, 'i' }; -static const symbol s_3_40[7] = { 'i', 't', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_3_41[4] = { 'a', 'b', 'i', 'l' }; -static const symbol s_3_42[4] = { 'i', 'b', 'i', 'l' }; -static const symbol s_3_43[3] = { 'i', 's', 'm' }; -static const symbol s_3_44[4] = { 'a', 't', 'o', 'r' }; -static const symbol s_3_45[2] = { 'o', 's' }; -static const symbol s_3_46[2] = { 'a', 't' }; -static const symbol s_3_47[2] = { 'i', 't' }; -static const symbol s_3_48[3] = { 'a', 'n', 't' }; -static const symbol s_3_49[3] = { 'i', 's', 't' }; -static const symbol s_3_50[2] = { 'u', 't' }; -static const symbol s_3_51[2] = { 'i', 'v' }; -static const symbol s_3_52[4] = { 'i', 'c', 0xC4, 0x83 }; -static const symbol s_3_53[6] = { 'a', 'b', 'i', 'l', 0xC4, 0x83 }; -static const symbol s_3_54[6] = { 'i', 'b', 'i', 'l', 0xC4, 0x83 }; -static const symbol s_3_55[5] = { 'o', 'a', 's', 0xC4, 0x83 }; -static const symbol s_3_56[4] = { 'a', 't', 0xC4, 0x83 }; -static const symbol s_3_57[4] = { 'i', 't', 0xC4, 0x83 }; -static const symbol s_3_58[5] = { 'a', 'n', 't', 0xC4, 0x83 }; -static const symbol s_3_59[5] = { 'i', 's', 't', 0xC4, 0x83 }; -static const symbol s_3_60[4] = { 'u', 't', 0xC4, 0x83 }; -static const symbol s_3_61[4] = { 'i', 'v', 0xC4, 0x83 }; - -static const struct among a_3[62] = +static const symbol s_3_0[5] = { 'i', 'c', 'a', 'l', 'a' }; +static const symbol s_3_1[5] = { 'i', 'c', 'i', 'v', 'a' }; +static const symbol s_3_2[5] = { 'a', 't', 'i', 'v', 'a' }; +static const symbol s_3_3[5] = { 'i', 't', 'i', 'v', 'a' }; +static const symbol s_3_4[5] = { 'i', 'c', 'a', 'l', 'e' }; +static const symbol s_3_5[7] = { 'a', 0xC8, 0x9B, 'i', 'u', 'n', 'e' }; +static const symbol s_3_6[7] = { 'i', 0xC8, 0x9B, 'i', 'u', 'n', 'e' }; +static const symbol s_3_7[6] = { 'a', 't', 'o', 'a', 'r', 'e' }; +static const symbol s_3_8[6] = { 'i', 't', 'o', 'a', 'r', 'e' }; +static const symbol s_3_9[7] = { 0xC4, 0x83, 't', 'o', 'a', 'r', 'e' }; +static const symbol s_3_10[7] = { 'i', 'c', 'i', 't', 'a', 't', 'e' }; +static const symbol s_3_11[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; +static const symbol s_3_12[9] = { 'i', 'b', 'i', 'l', 'i', 't', 'a', 't', 'e' }; +static const symbol s_3_13[7] = { 'i', 'v', 'i', 't', 'a', 't', 'e' }; +static const symbol s_3_14[5] = { 'i', 'c', 'i', 'v', 'e' }; +static const symbol s_3_15[5] = { 'a', 't', 'i', 'v', 'e' }; +static const symbol s_3_16[5] = { 'i', 't', 'i', 'v', 'e' }; +static const symbol s_3_17[5] = { 'i', 'c', 'a', 'l', 'i' }; +static const symbol s_3_18[5] = { 'a', 't', 'o', 'r', 'i' }; +static const symbol s_3_19[7] = { 'i', 'c', 'a', 't', 'o', 'r', 'i' }; +static const symbol s_3_20[5] = { 'i', 't', 'o', 'r', 'i' }; +static const symbol s_3_21[6] = { 0xC4, 0x83, 't', 'o', 'r', 'i' }; +static const symbol s_3_22[7] = { 'i', 'c', 'i', 't', 'a', 't', 'i' }; +static const symbol s_3_23[9] = { 'a', 'b', 'i', 'l', 'i', 't', 'a', 't', 'i' }; +static const symbol s_3_24[7] = { 'i', 'v', 'i', 't', 'a', 't', 'i' }; +static const symbol s_3_25[5] = { 'i', 'c', 'i', 'v', 'i' }; +static const symbol s_3_26[5] = { 'a', 't', 'i', 'v', 'i' }; +static const symbol s_3_27[5] = { 'i', 't', 'i', 'v', 'i' }; +static const symbol s_3_28[7] = { 'i', 'c', 'i', 't', 0xC4, 0x83, 'i' }; +static const symbol s_3_29[9] = { 'a', 'b', 'i', 'l', 'i', 't', 0xC4, 0x83, 'i' }; +static const symbol s_3_30[7] = { 'i', 'v', 'i', 't', 0xC4, 0x83, 'i' }; +static const symbol s_3_31[9] = { 'i', 'c', 'i', 't', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_3_32[11] = { 'a', 'b', 'i', 'l', 'i', 't', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_3_33[9] = { 'i', 'v', 'i', 't', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_3_34[4] = { 'i', 'c', 'a', 'l' }; +static const symbol s_3_35[4] = { 'a', 't', 'o', 'r' }; +static const symbol s_3_36[6] = { 'i', 'c', 'a', 't', 'o', 'r' }; +static const symbol s_3_37[4] = { 'i', 't', 'o', 'r' }; +static const symbol s_3_38[5] = { 0xC4, 0x83, 't', 'o', 'r' }; +static const symbol s_3_39[4] = { 'i', 'c', 'i', 'v' }; +static const symbol s_3_40[4] = { 'a', 't', 'i', 'v' }; +static const symbol s_3_41[4] = { 'i', 't', 'i', 'v' }; +static const symbol s_3_42[6] = { 'i', 'c', 'a', 'l', 0xC4, 0x83 }; +static const symbol s_3_43[6] = { 'i', 'c', 'i', 'v', 0xC4, 0x83 }; +static const symbol s_3_44[6] = { 'a', 't', 'i', 'v', 0xC4, 0x83 }; +static const symbol s_3_45[6] = { 'i', 't', 'i', 'v', 0xC4, 0x83 }; + +static const struct among a_3[46] = { -{ 3, s_3_0, -1, 1, 0}, -{ 5, s_3_1, -1, 1, 0}, -{ 5, s_3_2, -1, 1, 0}, -{ 4, s_3_3, -1, 1, 0}, -{ 3, s_3_4, -1, 1, 0}, -{ 3, s_3_5, -1, 1, 0}, -{ 4, s_3_6, -1, 1, 0}, -{ 4, s_3_7, -1, 3, 0}, -{ 3, s_3_8, -1, 1, 0}, -{ 3, s_3_9, -1, 1, 0}, -{ 2, s_3_10, -1, 1, 0}, -{ 3, s_3_11, -1, 1, 0}, -{ 5, s_3_12, -1, 1, 0}, -{ 5, s_3_13, -1, 1, 0}, -{ 4, s_3_14, -1, 3, 0}, -{ 4, s_3_15, -1, 2, 0}, -{ 4, s_3_16, -1, 1, 0}, -{ 3, s_3_17, -1, 1, 0}, -{ 5, s_3_18, 17, 1, 0}, -{ 3, s_3_19, -1, 1, 0}, -{ 4, s_3_20, -1, 1, 0}, -{ 4, s_3_21, -1, 3, 0}, -{ 3, s_3_22, -1, 1, 0}, -{ 3, s_3_23, -1, 1, 0}, -{ 3, s_3_24, -1, 1, 0}, -{ 5, s_3_25, -1, 1, 0}, -{ 5, s_3_26, -1, 1, 0}, -{ 4, s_3_27, -1, 2, 0}, -{ 5, s_3_28, -1, 1, 0}, -{ 3, s_3_29, -1, 1, 0}, -{ 3, s_3_30, -1, 1, 0}, -{ 5, s_3_31, 30, 1, 0}, -{ 3, s_3_32, -1, 1, 0}, -{ 4, s_3_33, -1, 1, 0}, -{ 4, s_3_34, -1, 3, 0}, -{ 3, s_3_35, -1, 1, 0}, -{ 5, s_3_36, -1, 3, 0}, -{ 3, s_3_37, -1, 1, 0}, -{ 5, s_3_38, -1, 1, 0}, -{ 4, s_3_39, -1, 1, 0}, -{ 7, s_3_40, -1, 1, 0}, -{ 4, s_3_41, -1, 1, 0}, -{ 4, s_3_42, -1, 1, 0}, -{ 3, s_3_43, -1, 3, 0}, -{ 4, s_3_44, -1, 1, 0}, -{ 2, s_3_45, -1, 1, 0}, -{ 2, s_3_46, -1, 1, 0}, -{ 2, s_3_47, -1, 1, 0}, -{ 3, s_3_48, -1, 1, 0}, -{ 3, s_3_49, -1, 3, 0}, -{ 2, s_3_50, -1, 1, 0}, -{ 2, s_3_51, -1, 1, 0}, -{ 4, s_3_52, -1, 1, 0}, -{ 6, s_3_53, -1, 1, 0}, -{ 6, s_3_54, -1, 1, 0}, -{ 5, s_3_55, -1, 1, 0}, -{ 4, s_3_56, -1, 1, 0}, -{ 4, s_3_57, -1, 1, 0}, -{ 5, s_3_58, -1, 1, 0}, -{ 5, s_3_59, -1, 3, 0}, -{ 4, s_3_60, -1, 1, 0}, -{ 4, s_3_61, -1, 1, 0} +{ 5, s_3_0, -1, 4, 0}, +{ 5, s_3_1, -1, 4, 0}, +{ 5, s_3_2, -1, 5, 0}, +{ 5, s_3_3, -1, 6, 0}, +{ 5, s_3_4, -1, 4, 0}, +{ 7, s_3_5, -1, 5, 0}, +{ 7, s_3_6, -1, 6, 0}, +{ 6, s_3_7, -1, 5, 0}, +{ 6, s_3_8, -1, 6, 0}, +{ 7, s_3_9, -1, 5, 0}, +{ 7, s_3_10, -1, 4, 0}, +{ 9, s_3_11, -1, 1, 0}, +{ 9, s_3_12, -1, 2, 0}, +{ 7, s_3_13, -1, 3, 0}, +{ 5, s_3_14, -1, 4, 0}, +{ 5, s_3_15, -1, 5, 0}, +{ 5, s_3_16, -1, 6, 0}, +{ 5, s_3_17, -1, 4, 0}, +{ 5, s_3_18, -1, 5, 0}, +{ 7, s_3_19, 18, 4, 0}, +{ 5, s_3_20, -1, 6, 0}, +{ 6, s_3_21, -1, 5, 0}, +{ 7, s_3_22, -1, 4, 0}, +{ 9, s_3_23, -1, 1, 0}, +{ 7, s_3_24, -1, 3, 0}, +{ 5, s_3_25, -1, 4, 0}, +{ 5, s_3_26, -1, 5, 0}, +{ 5, s_3_27, -1, 6, 0}, +{ 7, s_3_28, -1, 4, 0}, +{ 9, s_3_29, -1, 1, 0}, +{ 7, s_3_30, -1, 3, 0}, +{ 9, s_3_31, -1, 4, 0}, +{ 11, s_3_32, -1, 1, 0}, +{ 9, s_3_33, -1, 3, 0}, +{ 4, s_3_34, -1, 4, 0}, +{ 4, s_3_35, -1, 5, 0}, +{ 6, s_3_36, 35, 4, 0}, +{ 4, s_3_37, -1, 6, 0}, +{ 5, s_3_38, -1, 5, 0}, +{ 4, s_3_39, -1, 4, 0}, +{ 4, s_3_40, -1, 5, 0}, +{ 4, s_3_41, -1, 6, 0}, +{ 6, s_3_42, -1, 4, 0}, +{ 6, s_3_43, -1, 4, 0}, +{ 6, s_3_44, -1, 5, 0}, +{ 6, s_3_45, -1, 6, 0} }; -static const symbol s_4_0[2] = { 'e', 'a' }; -static const symbol s_4_1[2] = { 'i', 'a' }; -static const symbol s_4_2[3] = { 'e', 's', 'c' }; -static const symbol s_4_3[4] = { 0xC4, 0x83, 's', 'c' }; -static const symbol s_4_4[3] = { 'i', 'n', 'd' }; -static const symbol s_4_5[4] = { 0xC3, 0xA2, 'n', 'd' }; -static const symbol s_4_6[3] = { 'a', 'r', 'e' }; -static const symbol s_4_7[3] = { 'e', 'r', 'e' }; -static const symbol s_4_8[3] = { 'i', 'r', 'e' }; -static const symbol s_4_9[4] = { 0xC3, 0xA2, 'r', 'e' }; -static const symbol s_4_10[2] = { 's', 'e' }; -static const symbol s_4_11[3] = { 'a', 's', 'e' }; -static const symbol s_4_12[4] = { 's', 'e', 's', 'e' }; -static const symbol s_4_13[3] = { 'i', 's', 'e' }; -static const symbol s_4_14[3] = { 'u', 's', 'e' }; -static const symbol s_4_15[4] = { 0xC3, 0xA2, 's', 'e' }; -static const symbol s_4_16[5] = { 'e', 0xC5, 0x9F, 't', 'e' }; -static const symbol s_4_17[6] = { 0xC4, 0x83, 0xC5, 0x9F, 't', 'e' }; -static const symbol s_4_18[3] = { 'e', 'z', 'e' }; -static const symbol s_4_19[2] = { 'a', 'i' }; -static const symbol s_4_20[3] = { 'e', 'a', 'i' }; -static const symbol s_4_21[3] = { 'i', 'a', 'i' }; -static const symbol s_4_22[3] = { 's', 'e', 'i' }; -static const symbol s_4_23[5] = { 'e', 0xC5, 0x9F, 't', 'i' }; -static const symbol s_4_24[6] = { 0xC4, 0x83, 0xC5, 0x9F, 't', 'i' }; -static const symbol s_4_25[2] = { 'u', 'i' }; -static const symbol s_4_26[3] = { 'e', 'z', 'i' }; -static const symbol s_4_27[4] = { 'a', 0xC5, 0x9F, 'i' }; -static const symbol s_4_28[5] = { 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_29[6] = { 'a', 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_30[7] = { 's', 'e', 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_31[6] = { 'i', 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_32[6] = { 'u', 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_33[7] = { 0xC3, 0xA2, 's', 'e', 0xC5, 0x9F, 'i' }; -static const symbol s_4_34[4] = { 'i', 0xC5, 0x9F, 'i' }; -static const symbol s_4_35[4] = { 'u', 0xC5, 0x9F, 'i' }; -static const symbol s_4_36[5] = { 0xC3, 0xA2, 0xC5, 0x9F, 'i' }; -static const symbol s_4_37[3] = { 0xC3, 0xA2, 'i' }; -static const symbol s_4_38[4] = { 'a', 0xC5, 0xA3, 'i' }; -static const symbol s_4_39[5] = { 'e', 'a', 0xC5, 0xA3, 'i' }; -static const symbol s_4_40[5] = { 'i', 'a', 0xC5, 0xA3, 'i' }; -static const symbol s_4_41[4] = { 'e', 0xC5, 0xA3, 'i' }; -static const symbol s_4_42[4] = { 'i', 0xC5, 0xA3, 'i' }; -static const symbol s_4_43[7] = { 'a', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_44[8] = { 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_45[9] = { 'a', 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_46[10] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_47[9] = { 'i', 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_48[9] = { 'u', 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_49[10] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_50[7] = { 'i', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_51[7] = { 'u', 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_52[8] = { 0xC3, 0xA2, 'r', 0xC4, 0x83, 0xC5, 0xA3, 'i' }; -static const symbol s_4_53[5] = { 0xC3, 0xA2, 0xC5, 0xA3, 'i' }; -static const symbol s_4_54[2] = { 'a', 'm' }; -static const symbol s_4_55[3] = { 'e', 'a', 'm' }; -static const symbol s_4_56[3] = { 'i', 'a', 'm' }; -static const symbol s_4_57[2] = { 'e', 'm' }; -static const symbol s_4_58[4] = { 'a', 's', 'e', 'm' }; -static const symbol s_4_59[5] = { 's', 'e', 's', 'e', 'm' }; -static const symbol s_4_60[4] = { 'i', 's', 'e', 'm' }; -static const symbol s_4_61[4] = { 'u', 's', 'e', 'm' }; -static const symbol s_4_62[5] = { 0xC3, 0xA2, 's', 'e', 'm' }; -static const symbol s_4_63[2] = { 'i', 'm' }; -static const symbol s_4_64[3] = { 0xC4, 0x83, 'm' }; -static const symbol s_4_65[5] = { 'a', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_66[6] = { 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_67[7] = { 'a', 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_68[8] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_69[7] = { 'i', 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_70[7] = { 'u', 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_71[8] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_72[5] = { 'i', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_73[5] = { 'u', 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_74[6] = { 0xC3, 0xA2, 'r', 0xC4, 0x83, 'm' }; -static const symbol s_4_75[3] = { 0xC3, 0xA2, 'm' }; -static const symbol s_4_76[2] = { 'a', 'u' }; -static const symbol s_4_77[3] = { 'e', 'a', 'u' }; -static const symbol s_4_78[3] = { 'i', 'a', 'u' }; -static const symbol s_4_79[4] = { 'i', 'n', 'd', 'u' }; -static const symbol s_4_80[5] = { 0xC3, 0xA2, 'n', 'd', 'u' }; -static const symbol s_4_81[2] = { 'e', 'z' }; -static const symbol s_4_82[6] = { 'e', 'a', 's', 'c', 0xC4, 0x83 }; -static const symbol s_4_83[4] = { 'a', 'r', 0xC4, 0x83 }; -static const symbol s_4_84[5] = { 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_85[6] = { 'a', 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_86[7] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_87[6] = { 'i', 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_88[6] = { 'u', 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_89[7] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83 }; -static const symbol s_4_90[4] = { 'i', 'r', 0xC4, 0x83 }; -static const symbol s_4_91[4] = { 'u', 'r', 0xC4, 0x83 }; -static const symbol s_4_92[5] = { 0xC3, 0xA2, 'r', 0xC4, 0x83 }; -static const symbol s_4_93[5] = { 'e', 'a', 'z', 0xC4, 0x83 }; - -static const struct among a_4[94] = +static const symbol s_4_0[3] = { 'i', 'c', 'a' }; +static const symbol s_4_1[5] = { 'a', 'b', 'i', 'l', 'a' }; +static const symbol s_4_2[5] = { 'i', 'b', 'i', 'l', 'a' }; +static const symbol s_4_3[4] = { 'o', 'a', 's', 'a' }; +static const symbol s_4_4[3] = { 'a', 't', 'a' }; +static const symbol s_4_5[3] = { 'i', 't', 'a' }; +static const symbol s_4_6[4] = { 'a', 'n', 't', 'a' }; +static const symbol s_4_7[4] = { 'i', 's', 't', 'a' }; +static const symbol s_4_8[3] = { 'u', 't', 'a' }; +static const symbol s_4_9[3] = { 'i', 'v', 'a' }; +static const symbol s_4_10[2] = { 'i', 'c' }; +static const symbol s_4_11[3] = { 'i', 'c', 'e' }; +static const symbol s_4_12[5] = { 'a', 'b', 'i', 'l', 'e' }; +static const symbol s_4_13[5] = { 'i', 'b', 'i', 'l', 'e' }; +static const symbol s_4_14[4] = { 'i', 's', 'm', 'e' }; +static const symbol s_4_15[4] = { 'i', 'u', 'n', 'e' }; +static const symbol s_4_16[4] = { 'o', 'a', 's', 'e' }; +static const symbol s_4_17[3] = { 'a', 't', 'e' }; +static const symbol s_4_18[5] = { 'i', 't', 'a', 't', 'e' }; +static const symbol s_4_19[3] = { 'i', 't', 'e' }; +static const symbol s_4_20[4] = { 'a', 'n', 't', 'e' }; +static const symbol s_4_21[4] = { 'i', 's', 't', 'e' }; +static const symbol s_4_22[3] = { 'u', 't', 'e' }; +static const symbol s_4_23[3] = { 'i', 'v', 'e' }; +static const symbol s_4_24[3] = { 'i', 'c', 'i' }; +static const symbol s_4_25[5] = { 'a', 'b', 'i', 'l', 'i' }; +static const symbol s_4_26[5] = { 'i', 'b', 'i', 'l', 'i' }; +static const symbol s_4_27[4] = { 'i', 'u', 'n', 'i' }; +static const symbol s_4_28[5] = { 'a', 't', 'o', 'r', 'i' }; +static const symbol s_4_29[3] = { 'o', 's', 'i' }; +static const symbol s_4_30[3] = { 'a', 't', 'i' }; +static const symbol s_4_31[5] = { 'i', 't', 'a', 't', 'i' }; +static const symbol s_4_32[3] = { 'i', 't', 'i' }; +static const symbol s_4_33[4] = { 'a', 'n', 't', 'i' }; +static const symbol s_4_34[4] = { 'i', 's', 't', 'i' }; +static const symbol s_4_35[3] = { 'u', 't', 'i' }; +static const symbol s_4_36[5] = { 'i', 0xC8, 0x99, 't', 'i' }; +static const symbol s_4_37[3] = { 'i', 'v', 'i' }; +static const symbol s_4_38[5] = { 'i', 't', 0xC4, 0x83, 'i' }; +static const symbol s_4_39[4] = { 'o', 0xC8, 0x99, 'i' }; +static const symbol s_4_40[7] = { 'i', 't', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_4_41[4] = { 'a', 'b', 'i', 'l' }; +static const symbol s_4_42[4] = { 'i', 'b', 'i', 'l' }; +static const symbol s_4_43[3] = { 'i', 's', 'm' }; +static const symbol s_4_44[4] = { 'a', 't', 'o', 'r' }; +static const symbol s_4_45[2] = { 'o', 's' }; +static const symbol s_4_46[2] = { 'a', 't' }; +static const symbol s_4_47[2] = { 'i', 't' }; +static const symbol s_4_48[3] = { 'a', 'n', 't' }; +static const symbol s_4_49[3] = { 'i', 's', 't' }; +static const symbol s_4_50[2] = { 'u', 't' }; +static const symbol s_4_51[2] = { 'i', 'v' }; +static const symbol s_4_52[4] = { 'i', 'c', 0xC4, 0x83 }; +static const symbol s_4_53[6] = { 'a', 'b', 'i', 'l', 0xC4, 0x83 }; +static const symbol s_4_54[6] = { 'i', 'b', 'i', 'l', 0xC4, 0x83 }; +static const symbol s_4_55[5] = { 'o', 'a', 's', 0xC4, 0x83 }; +static const symbol s_4_56[4] = { 'a', 't', 0xC4, 0x83 }; +static const symbol s_4_57[4] = { 'i', 't', 0xC4, 0x83 }; +static const symbol s_4_58[5] = { 'a', 'n', 't', 0xC4, 0x83 }; +static const symbol s_4_59[5] = { 'i', 's', 't', 0xC4, 0x83 }; +static const symbol s_4_60[4] = { 'u', 't', 0xC4, 0x83 }; +static const symbol s_4_61[4] = { 'i', 'v', 0xC4, 0x83 }; + +static const struct among a_4[62] = { -{ 2, s_4_0, -1, 1, 0}, -{ 2, s_4_1, -1, 1, 0}, -{ 3, s_4_2, -1, 1, 0}, +{ 3, s_4_0, -1, 1, 0}, +{ 5, s_4_1, -1, 1, 0}, +{ 5, s_4_2, -1, 1, 0}, { 4, s_4_3, -1, 1, 0}, { 3, s_4_4, -1, 1, 0}, -{ 4, s_4_5, -1, 1, 0}, -{ 3, s_4_6, -1, 1, 0}, -{ 3, s_4_7, -1, 1, 0}, +{ 3, s_4_5, -1, 1, 0}, +{ 4, s_4_6, -1, 1, 0}, +{ 4, s_4_7, -1, 3, 0}, { 3, s_4_8, -1, 1, 0}, -{ 4, s_4_9, -1, 1, 0}, -{ 2, s_4_10, -1, 2, 0}, -{ 3, s_4_11, 10, 1, 0}, -{ 4, s_4_12, 10, 2, 0}, -{ 3, s_4_13, 10, 1, 0}, -{ 3, s_4_14, 10, 1, 0}, -{ 4, s_4_15, 10, 1, 0}, -{ 5, s_4_16, -1, 1, 0}, -{ 6, s_4_17, -1, 1, 0}, -{ 3, s_4_18, -1, 1, 0}, -{ 2, s_4_19, -1, 1, 0}, -{ 3, s_4_20, 19, 1, 0}, -{ 3, s_4_21, 19, 1, 0}, -{ 3, s_4_22, -1, 2, 0}, -{ 5, s_4_23, -1, 1, 0}, -{ 6, s_4_24, -1, 1, 0}, -{ 2, s_4_25, -1, 1, 0}, -{ 3, s_4_26, -1, 1, 0}, -{ 4, s_4_27, -1, 1, 0}, -{ 5, s_4_28, -1, 2, 0}, -{ 6, s_4_29, 28, 1, 0}, -{ 7, s_4_30, 28, 2, 0}, -{ 6, s_4_31, 28, 1, 0}, -{ 6, s_4_32, 28, 1, 0}, -{ 7, s_4_33, 28, 1, 0}, -{ 4, s_4_34, -1, 1, 0}, -{ 4, s_4_35, -1, 1, 0}, -{ 5, s_4_36, -1, 1, 0}, +{ 3, s_4_9, -1, 1, 0}, +{ 2, s_4_10, -1, 1, 0}, +{ 3, s_4_11, -1, 1, 0}, +{ 5, s_4_12, -1, 1, 0}, +{ 5, s_4_13, -1, 1, 0}, +{ 4, s_4_14, -1, 3, 0}, +{ 4, s_4_15, -1, 2, 0}, +{ 4, s_4_16, -1, 1, 0}, +{ 3, s_4_17, -1, 1, 0}, +{ 5, s_4_18, 17, 1, 0}, +{ 3, s_4_19, -1, 1, 0}, +{ 4, s_4_20, -1, 1, 0}, +{ 4, s_4_21, -1, 3, 0}, +{ 3, s_4_22, -1, 1, 0}, +{ 3, s_4_23, -1, 1, 0}, +{ 3, s_4_24, -1, 1, 0}, +{ 5, s_4_25, -1, 1, 0}, +{ 5, s_4_26, -1, 1, 0}, +{ 4, s_4_27, -1, 2, 0}, +{ 5, s_4_28, -1, 1, 0}, +{ 3, s_4_29, -1, 1, 0}, +{ 3, s_4_30, -1, 1, 0}, +{ 5, s_4_31, 30, 1, 0}, +{ 3, s_4_32, -1, 1, 0}, +{ 4, s_4_33, -1, 1, 0}, +{ 4, s_4_34, -1, 3, 0}, +{ 3, s_4_35, -1, 1, 0}, +{ 5, s_4_36, -1, 3, 0}, { 3, s_4_37, -1, 1, 0}, -{ 4, s_4_38, -1, 2, 0}, -{ 5, s_4_39, 38, 1, 0}, -{ 5, s_4_40, 38, 1, 0}, -{ 4, s_4_41, -1, 2, 0}, -{ 4, s_4_42, -1, 2, 0}, -{ 7, s_4_43, -1, 1, 0}, -{ 8, s_4_44, -1, 2, 0}, -{ 9, s_4_45, 44, 1, 0}, -{ 10, s_4_46, 44, 2, 0}, -{ 9, s_4_47, 44, 1, 0}, -{ 9, s_4_48, 44, 1, 0}, -{ 10, s_4_49, 44, 1, 0}, -{ 7, s_4_50, -1, 1, 0}, -{ 7, s_4_51, -1, 1, 0}, -{ 8, s_4_52, -1, 1, 0}, -{ 5, s_4_53, -1, 2, 0}, -{ 2, s_4_54, -1, 1, 0}, -{ 3, s_4_55, 54, 1, 0}, -{ 3, s_4_56, 54, 1, 0}, -{ 2, s_4_57, -1, 2, 0}, -{ 4, s_4_58, 57, 1, 0}, -{ 5, s_4_59, 57, 2, 0}, -{ 4, s_4_60, 57, 1, 0}, -{ 4, s_4_61, 57, 1, 0}, -{ 5, s_4_62, 57, 1, 0}, -{ 2, s_4_63, -1, 2, 0}, -{ 3, s_4_64, -1, 2, 0}, -{ 5, s_4_65, 64, 1, 0}, -{ 6, s_4_66, 64, 2, 0}, -{ 7, s_4_67, 66, 1, 0}, -{ 8, s_4_68, 66, 2, 0}, -{ 7, s_4_69, 66, 1, 0}, -{ 7, s_4_70, 66, 1, 0}, -{ 8, s_4_71, 66, 1, 0}, -{ 5, s_4_72, 64, 1, 0}, -{ 5, s_4_73, 64, 1, 0}, -{ 6, s_4_74, 64, 1, 0}, -{ 3, s_4_75, -1, 2, 0}, -{ 2, s_4_76, -1, 1, 0}, -{ 3, s_4_77, 76, 1, 0}, -{ 3, s_4_78, 76, 1, 0}, -{ 4, s_4_79, -1, 1, 0}, -{ 5, s_4_80, -1, 1, 0}, -{ 2, s_4_81, -1, 1, 0}, -{ 6, s_4_82, -1, 1, 0}, -{ 4, s_4_83, -1, 1, 0}, -{ 5, s_4_84, -1, 2, 0}, -{ 6, s_4_85, 84, 1, 0}, -{ 7, s_4_86, 84, 2, 0}, -{ 6, s_4_87, 84, 1, 0}, -{ 6, s_4_88, 84, 1, 0}, -{ 7, s_4_89, 84, 1, 0}, -{ 4, s_4_90, -1, 1, 0}, -{ 4, s_4_91, -1, 1, 0}, -{ 5, s_4_92, -1, 1, 0}, -{ 5, s_4_93, -1, 1, 0} +{ 5, s_4_38, -1, 1, 0}, +{ 4, s_4_39, -1, 1, 0}, +{ 7, s_4_40, -1, 1, 0}, +{ 4, s_4_41, -1, 1, 0}, +{ 4, s_4_42, -1, 1, 0}, +{ 3, s_4_43, -1, 3, 0}, +{ 4, s_4_44, -1, 1, 0}, +{ 2, s_4_45, -1, 1, 0}, +{ 2, s_4_46, -1, 1, 0}, +{ 2, s_4_47, -1, 1, 0}, +{ 3, s_4_48, -1, 1, 0}, +{ 3, s_4_49, -1, 3, 0}, +{ 2, s_4_50, -1, 1, 0}, +{ 2, s_4_51, -1, 1, 0}, +{ 4, s_4_52, -1, 1, 0}, +{ 6, s_4_53, -1, 1, 0}, +{ 6, s_4_54, -1, 1, 0}, +{ 5, s_4_55, -1, 1, 0}, +{ 4, s_4_56, -1, 1, 0}, +{ 4, s_4_57, -1, 1, 0}, +{ 5, s_4_58, -1, 1, 0}, +{ 5, s_4_59, -1, 3, 0}, +{ 4, s_4_60, -1, 1, 0}, +{ 4, s_4_61, -1, 1, 0} }; -static const symbol s_5_0[1] = { 'a' }; -static const symbol s_5_1[1] = { 'e' }; -static const symbol s_5_2[2] = { 'i', 'e' }; -static const symbol s_5_3[1] = { 'i' }; -static const symbol s_5_4[2] = { 0xC4, 0x83 }; +static const symbol s_5_0[2] = { 'e', 'a' }; +static const symbol s_5_1[2] = { 'i', 'a' }; +static const symbol s_5_2[3] = { 'e', 's', 'c' }; +static const symbol s_5_3[4] = { 0xC4, 0x83, 's', 'c' }; +static const symbol s_5_4[3] = { 'i', 'n', 'd' }; +static const symbol s_5_5[4] = { 0xC3, 0xA2, 'n', 'd' }; +static const symbol s_5_6[3] = { 'a', 'r', 'e' }; +static const symbol s_5_7[3] = { 'e', 'r', 'e' }; +static const symbol s_5_8[3] = { 'i', 'r', 'e' }; +static const symbol s_5_9[4] = { 0xC3, 0xA2, 'r', 'e' }; +static const symbol s_5_10[2] = { 's', 'e' }; +static const symbol s_5_11[3] = { 'a', 's', 'e' }; +static const symbol s_5_12[4] = { 's', 'e', 's', 'e' }; +static const symbol s_5_13[3] = { 'i', 's', 'e' }; +static const symbol s_5_14[3] = { 'u', 's', 'e' }; +static const symbol s_5_15[4] = { 0xC3, 0xA2, 's', 'e' }; +static const symbol s_5_16[5] = { 'e', 0xC8, 0x99, 't', 'e' }; +static const symbol s_5_17[6] = { 0xC4, 0x83, 0xC8, 0x99, 't', 'e' }; +static const symbol s_5_18[3] = { 'e', 'z', 'e' }; +static const symbol s_5_19[2] = { 'a', 'i' }; +static const symbol s_5_20[3] = { 'e', 'a', 'i' }; +static const symbol s_5_21[3] = { 'i', 'a', 'i' }; +static const symbol s_5_22[3] = { 's', 'e', 'i' }; +static const symbol s_5_23[5] = { 'e', 0xC8, 0x99, 't', 'i' }; +static const symbol s_5_24[6] = { 0xC4, 0x83, 0xC8, 0x99, 't', 'i' }; +static const symbol s_5_25[2] = { 'u', 'i' }; +static const symbol s_5_26[3] = { 'e', 'z', 'i' }; +static const symbol s_5_27[4] = { 'a', 0xC8, 0x99, 'i' }; +static const symbol s_5_28[5] = { 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_29[6] = { 'a', 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_30[7] = { 's', 'e', 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_31[6] = { 'i', 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_32[6] = { 'u', 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_33[7] = { 0xC3, 0xA2, 's', 'e', 0xC8, 0x99, 'i' }; +static const symbol s_5_34[4] = { 'i', 0xC8, 0x99, 'i' }; +static const symbol s_5_35[4] = { 'u', 0xC8, 0x99, 'i' }; +static const symbol s_5_36[5] = { 0xC3, 0xA2, 0xC8, 0x99, 'i' }; +static const symbol s_5_37[4] = { 'a', 0xC8, 0x9B, 'i' }; +static const symbol s_5_38[5] = { 'e', 'a', 0xC8, 0x9B, 'i' }; +static const symbol s_5_39[5] = { 'i', 'a', 0xC8, 0x9B, 'i' }; +static const symbol s_5_40[4] = { 'e', 0xC8, 0x9B, 'i' }; +static const symbol s_5_41[4] = { 'i', 0xC8, 0x9B, 'i' }; +static const symbol s_5_42[7] = { 'a', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_43[8] = { 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_44[9] = { 'a', 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_45[10] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_46[9] = { 'i', 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_47[9] = { 'u', 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_48[10] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_49[7] = { 'i', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_50[7] = { 'u', 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_51[8] = { 0xC3, 0xA2, 'r', 0xC4, 0x83, 0xC8, 0x9B, 'i' }; +static const symbol s_5_52[5] = { 0xC3, 0xA2, 0xC8, 0x9B, 'i' }; +static const symbol s_5_53[3] = { 0xC3, 0xA2, 'i' }; +static const symbol s_5_54[2] = { 'a', 'm' }; +static const symbol s_5_55[3] = { 'e', 'a', 'm' }; +static const symbol s_5_56[3] = { 'i', 'a', 'm' }; +static const symbol s_5_57[2] = { 'e', 'm' }; +static const symbol s_5_58[4] = { 'a', 's', 'e', 'm' }; +static const symbol s_5_59[5] = { 's', 'e', 's', 'e', 'm' }; +static const symbol s_5_60[4] = { 'i', 's', 'e', 'm' }; +static const symbol s_5_61[4] = { 'u', 's', 'e', 'm' }; +static const symbol s_5_62[5] = { 0xC3, 0xA2, 's', 'e', 'm' }; +static const symbol s_5_63[2] = { 'i', 'm' }; +static const symbol s_5_64[3] = { 0xC4, 0x83, 'm' }; +static const symbol s_5_65[5] = { 'a', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_66[6] = { 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_67[7] = { 'a', 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_68[8] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_69[7] = { 'i', 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_70[7] = { 'u', 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_71[8] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_72[5] = { 'i', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_73[5] = { 'u', 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_74[6] = { 0xC3, 0xA2, 'r', 0xC4, 0x83, 'm' }; +static const symbol s_5_75[3] = { 0xC3, 0xA2, 'm' }; +static const symbol s_5_76[2] = { 'a', 'u' }; +static const symbol s_5_77[3] = { 'e', 'a', 'u' }; +static const symbol s_5_78[3] = { 'i', 'a', 'u' }; +static const symbol s_5_79[4] = { 'i', 'n', 'd', 'u' }; +static const symbol s_5_80[5] = { 0xC3, 0xA2, 'n', 'd', 'u' }; +static const symbol s_5_81[2] = { 'e', 'z' }; +static const symbol s_5_82[6] = { 'e', 'a', 's', 'c', 0xC4, 0x83 }; +static const symbol s_5_83[4] = { 'a', 'r', 0xC4, 0x83 }; +static const symbol s_5_84[5] = { 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_85[6] = { 'a', 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_86[7] = { 's', 'e', 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_87[6] = { 'i', 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_88[6] = { 'u', 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_89[7] = { 0xC3, 0xA2, 's', 'e', 'r', 0xC4, 0x83 }; +static const symbol s_5_90[4] = { 'i', 'r', 0xC4, 0x83 }; +static const symbol s_5_91[4] = { 'u', 'r', 0xC4, 0x83 }; +static const symbol s_5_92[5] = { 0xC3, 0xA2, 'r', 0xC4, 0x83 }; +static const symbol s_5_93[5] = { 'e', 'a', 'z', 0xC4, 0x83 }; -static const struct among a_5[5] = +static const struct among a_5[94] = { -{ 1, s_5_0, -1, 1, 0}, -{ 1, s_5_1, -1, 1, 0}, -{ 2, s_5_2, 1, 1, 0}, -{ 1, s_5_3, -1, 1, 0}, -{ 2, s_5_4, -1, 1, 0} +{ 2, s_5_0, -1, 1, 0}, +{ 2, s_5_1, -1, 1, 0}, +{ 3, s_5_2, -1, 1, 0}, +{ 4, s_5_3, -1, 1, 0}, +{ 3, s_5_4, -1, 1, 0}, +{ 4, s_5_5, -1, 1, 0}, +{ 3, s_5_6, -1, 1, 0}, +{ 3, s_5_7, -1, 1, 0}, +{ 3, s_5_8, -1, 1, 0}, +{ 4, s_5_9, -1, 1, 0}, +{ 2, s_5_10, -1, 2, 0}, +{ 3, s_5_11, 10, 1, 0}, +{ 4, s_5_12, 10, 2, 0}, +{ 3, s_5_13, 10, 1, 0}, +{ 3, s_5_14, 10, 1, 0}, +{ 4, s_5_15, 10, 1, 0}, +{ 5, s_5_16, -1, 1, 0}, +{ 6, s_5_17, -1, 1, 0}, +{ 3, s_5_18, -1, 1, 0}, +{ 2, s_5_19, -1, 1, 0}, +{ 3, s_5_20, 19, 1, 0}, +{ 3, s_5_21, 19, 1, 0}, +{ 3, s_5_22, -1, 2, 0}, +{ 5, s_5_23, -1, 1, 0}, +{ 6, s_5_24, -1, 1, 0}, +{ 2, s_5_25, -1, 1, 0}, +{ 3, s_5_26, -1, 1, 0}, +{ 4, s_5_27, -1, 1, 0}, +{ 5, s_5_28, -1, 2, 0}, +{ 6, s_5_29, 28, 1, 0}, +{ 7, s_5_30, 28, 2, 0}, +{ 6, s_5_31, 28, 1, 0}, +{ 6, s_5_32, 28, 1, 0}, +{ 7, s_5_33, 28, 1, 0}, +{ 4, s_5_34, -1, 1, 0}, +{ 4, s_5_35, -1, 1, 0}, +{ 5, s_5_36, -1, 1, 0}, +{ 4, s_5_37, -1, 2, 0}, +{ 5, s_5_38, 37, 1, 0}, +{ 5, s_5_39, 37, 1, 0}, +{ 4, s_5_40, -1, 2, 0}, +{ 4, s_5_41, -1, 2, 0}, +{ 7, s_5_42, -1, 1, 0}, +{ 8, s_5_43, -1, 2, 0}, +{ 9, s_5_44, 43, 1, 0}, +{ 10, s_5_45, 43, 2, 0}, +{ 9, s_5_46, 43, 1, 0}, +{ 9, s_5_47, 43, 1, 0}, +{ 10, s_5_48, 43, 1, 0}, +{ 7, s_5_49, -1, 1, 0}, +{ 7, s_5_50, -1, 1, 0}, +{ 8, s_5_51, -1, 1, 0}, +{ 5, s_5_52, -1, 2, 0}, +{ 3, s_5_53, -1, 1, 0}, +{ 2, s_5_54, -1, 1, 0}, +{ 3, s_5_55, 54, 1, 0}, +{ 3, s_5_56, 54, 1, 0}, +{ 2, s_5_57, -1, 2, 0}, +{ 4, s_5_58, 57, 1, 0}, +{ 5, s_5_59, 57, 2, 0}, +{ 4, s_5_60, 57, 1, 0}, +{ 4, s_5_61, 57, 1, 0}, +{ 5, s_5_62, 57, 1, 0}, +{ 2, s_5_63, -1, 2, 0}, +{ 3, s_5_64, -1, 2, 0}, +{ 5, s_5_65, 64, 1, 0}, +{ 6, s_5_66, 64, 2, 0}, +{ 7, s_5_67, 66, 1, 0}, +{ 8, s_5_68, 66, 2, 0}, +{ 7, s_5_69, 66, 1, 0}, +{ 7, s_5_70, 66, 1, 0}, +{ 8, s_5_71, 66, 1, 0}, +{ 5, s_5_72, 64, 1, 0}, +{ 5, s_5_73, 64, 1, 0}, +{ 6, s_5_74, 64, 1, 0}, +{ 3, s_5_75, -1, 2, 0}, +{ 2, s_5_76, -1, 1, 0}, +{ 3, s_5_77, 76, 1, 0}, +{ 3, s_5_78, 76, 1, 0}, +{ 4, s_5_79, -1, 1, 0}, +{ 5, s_5_80, -1, 1, 0}, +{ 2, s_5_81, -1, 1, 0}, +{ 6, s_5_82, -1, 1, 0}, +{ 4, s_5_83, -1, 1, 0}, +{ 5, s_5_84, -1, 2, 0}, +{ 6, s_5_85, 84, 1, 0}, +{ 7, s_5_86, 84, 2, 0}, +{ 6, s_5_87, 84, 1, 0}, +{ 6, s_5_88, 84, 1, 0}, +{ 7, s_5_89, 84, 1, 0}, +{ 4, s_5_90, -1, 1, 0}, +{ 4, s_5_91, -1, 1, 0}, +{ 5, s_5_92, -1, 1, 0}, +{ 5, s_5_93, -1, 1, 0} +}; + +static const symbol s_6_0[1] = { 'a' }; +static const symbol s_6_1[1] = { 'e' }; +static const symbol s_6_2[2] = { 'i', 'e' }; +static const symbol s_6_3[1] = { 'i' }; +static const symbol s_6_4[2] = { 0xC4, 0x83 }; + +static const struct among a_6[5] = +{ +{ 1, s_6_0, -1, 1, 0}, +{ 1, s_6_1, -1, 1, 0}, +{ 2, s_6_2, 1, 1, 0}, +{ 1, s_6_3, -1, 1, 0}, +{ 2, s_6_4, -1, 1, 0} }; static const unsigned char g_v[] = { 17, 65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 4 }; -static const symbol s_0[] = { 'U' }; -static const symbol s_1[] = { 'I' }; -static const symbol s_2[] = { 'i' }; -static const symbol s_3[] = { 'u' }; -static const symbol s_4[] = { 'a' }; -static const symbol s_5[] = { 'e' }; -static const symbol s_6[] = { 'i' }; -static const symbol s_7[] = { 'a', 'b' }; +static const symbol s_0[] = { 0xC8, 0x99 }; +static const symbol s_1[] = { 0xC8, 0x9B }; +static const symbol s_2[] = { 'U' }; +static const symbol s_3[] = { 'I' }; +static const symbol s_4[] = { 'i' }; +static const symbol s_5[] = { 'u' }; +static const symbol s_6[] = { 'a' }; +static const symbol s_7[] = { 'e' }; static const symbol s_8[] = { 'i' }; -static const symbol s_9[] = { 'a', 't' }; -static const symbol s_10[] = { 'a', 0xC5, 0xA3, 'i' }; -static const symbol s_11[] = { 'a', 'b', 'i', 'l' }; -static const symbol s_12[] = { 'i', 'b', 'i', 'l' }; -static const symbol s_13[] = { 'i', 'v' }; -static const symbol s_14[] = { 'i', 'c' }; -static const symbol s_15[] = { 'a', 't' }; -static const symbol s_16[] = { 'i', 't' }; -static const symbol s_17[] = { 0xC5, 0xA3 }; -static const symbol s_18[] = { 't' }; -static const symbol s_19[] = { 'i', 's', 't' }; +static const symbol s_9[] = { 'a', 'b' }; +static const symbol s_10[] = { 'i' }; +static const symbol s_11[] = { 'a', 't' }; +static const symbol s_12[] = { 'a', 0xC8, 0x9B, 'i' }; +static const symbol s_13[] = { 'a', 'b', 'i', 'l' }; +static const symbol s_14[] = { 'i', 'b', 'i', 'l' }; +static const symbol s_15[] = { 'i', 'v' }; +static const symbol s_16[] = { 'i', 'c' }; +static const symbol s_17[] = { 'a', 't' }; +static const symbol s_18[] = { 'i', 't' }; +static const symbol s_19[] = { 0xC8, 0x9B }; +static const symbol s_20[] = { 't' }; +static const symbol s_21[] = { 'i', 's', 't' }; + +static int r_norm(struct SN_env * z) { + int among_var; + { int c1 = z->c; + while(1) { + int c2 = z->c; + while(1) { + int c3 = z->c; + z->bra = z->c; + if (z->c + 1 >= z->l || (z->p[z->c + 1] != 159 && z->p[z->c + 1] != 163)) goto lab2; + among_var = find_among(z, a_0, 2); + if (!among_var) goto lab2; + z->ket = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 2, s_0); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 2, s_1); + if (ret < 0) return ret; + } + break; + } + z->c = c3; + break; + lab2: + z->c = c3; + { int ret = skip_utf8(z->p, z->c, z->l, 1); + if (ret < 0) goto lab1; + z->c = ret; + } + } + continue; + lab1: + z->c = c2; + break; + } + z->c = c1; + } + return 1; +} static int r_prelude(struct SN_env * z) { while(1) { @@ -548,7 +603,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping_U(z, g_v, 97, 259, 0)) goto lab3; - { int ret = slice_from_s(z, 1, s_0); + { int ret = slice_from_s(z, 1, s_2); if (ret < 0) return ret; } goto lab2; @@ -558,7 +613,7 @@ static int r_prelude(struct SN_env * z) { z->c++; z->ket = z->c; if (in_grouping_U(z, g_v, 97, 259, 0)) goto lab1; - { int ret = slice_from_s(z, 1, s_1); + { int ret = slice_from_s(z, 1, s_3); if (ret < 0) return ret; } } @@ -589,7 +644,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping_U(z, g_v, 97, 259, 0)) goto lab2; { int c3 = z->c; if (out_grouping_U(z, g_v, 97, 259, 0)) goto lab4; - { + + { int ret = out_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab4; z->c += ret; @@ -598,7 +654,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping_U(z, g_v, 97, 259, 0)) goto lab2; - { + + { int ret = in_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab2; z->c += ret; @@ -611,7 +668,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping_U(z, g_v, 97, 259, 0)) goto lab0; { int c4 = z->c; if (out_grouping_U(z, g_v, 97, 259, 0)) goto lab6; - { + + { int ret = out_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab6; z->c += ret; @@ -634,23 +692,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 259, 1); if (ret < 0) goto lab7; z->c += ret; @@ -668,17 +730,16 @@ static int r_postlude(struct SN_env * z) { int c1 = z->c; z->bra = z->c; if (z->c >= z->l || (z->p[z->c + 0] != 73 && z->p[z->c + 0] != 85)) among_var = 3; else - among_var = find_among(z, a_0, 3); - if (!(among_var)) goto lab0; + among_var = find_among(z, a_1, 3); z->ket = z->c; switch (among_var) { case 1: - { int ret = slice_from_s(z, 1, s_2); + { int ret = slice_from_s(z, 1, s_4); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 1, s_3); + { int ret = slice_from_s(z, 1, s_5); if (ret < 0) return ret; } break; @@ -698,26 +759,23 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_step_0(struct SN_env * z) { int among_var; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((266786 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - among_var = find_among_b(z, a_1, 16); - if (!(among_var)) return 0; + among_var = find_among_b(z, a_2, 16); + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -729,38 +787,38 @@ static int r_step_0(struct SN_env * z) { } break; case 2: - { int ret = slice_from_s(z, 1, s_4); + { int ret = slice_from_s(z, 1, s_6); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 1, s_5); + { int ret = slice_from_s(z, 1, s_7); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 1, s_6); + { int ret = slice_from_s(z, 1, s_8); if (ret < 0) return ret; } break; case 5: { int m1 = z->l - z->c; (void)m1; - if (!(eq_s_b(z, 2, s_7))) goto lab0; + if (!(eq_s_b(z, 2, s_9))) goto lab0; return 0; lab0: z->c = z->l - m1; } - { int ret = slice_from_s(z, 1, s_8); + { int ret = slice_from_s(z, 1, s_10); if (ret < 0) return ret; } break; case 6: - { int ret = slice_from_s(z, 2, s_9); + { int ret = slice_from_s(z, 2, s_11); if (ret < 0) return ret; } break; case 7: - { int ret = slice_from_s(z, 4, s_10); + { int ret = slice_from_s(z, 4, s_12); if (ret < 0) return ret; } break; @@ -772,40 +830,40 @@ static int r_combo_suffix(struct SN_env * z) { int among_var; { int m_test1 = z->l - z->c; z->ket = z->c; - among_var = find_among_b(z, a_2, 46); - if (!(among_var)) return 0; + among_var = find_among_b(z, a_3, 46); + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; } switch (among_var) { case 1: - { int ret = slice_from_s(z, 4, s_11); + { int ret = slice_from_s(z, 4, s_13); if (ret < 0) return ret; } break; case 2: - { int ret = slice_from_s(z, 4, s_12); + { int ret = slice_from_s(z, 4, s_14); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 2, s_13); + { int ret = slice_from_s(z, 2, s_15); if (ret < 0) return ret; } break; case 4: - { int ret = slice_from_s(z, 2, s_14); + { int ret = slice_from_s(z, 2, s_16); if (ret < 0) return ret; } break; case 5: - { int ret = slice_from_s(z, 2, s_15); + { int ret = slice_from_s(z, 2, s_17); if (ret < 0) return ret; } break; case 6: - { int ret = slice_from_s(z, 2, s_16); + { int ret = slice_from_s(z, 2, s_18); if (ret < 0) return ret; } break; @@ -831,8 +889,8 @@ static int r_standard_suffix(struct SN_env * z) { break; } z->ket = z->c; - among_var = find_among_b(z, a_3, 62); - if (!(among_var)) return 0; + among_var = find_among_b(z, a_4, 62); + if (!among_var) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -844,14 +902,14 @@ static int r_standard_suffix(struct SN_env * z) { } break; case 2: - if (!(eq_s_b(z, 2, s_17))) return 0; + if (!(eq_s_b(z, 2, s_19))) return 0; z->bra = z->c; - { int ret = slice_from_s(z, 1, s_18); + { int ret = slice_from_s(z, 1, s_20); if (ret < 0) return ret; } break; case 3: - { int ret = slice_from_s(z, 3, s_19); + { int ret = slice_from_s(z, 3, s_21); if (ret < 0) return ret; } break; @@ -867,8 +925,8 @@ static int r_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - among_var = find_among_b(z, a_4, 94); - if (!(among_var)) { z->lb = mlimit1; return 0; } + among_var = find_among_b(z, a_5, 94); + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; switch (among_var) { case 1: @@ -898,7 +956,7 @@ static int r_verb_suffix(struct SN_env * z) { static int r_vowel_suffix(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_5, 5))) return 0; + if (!find_among_b(z, a_6, 5)) return 0; z->bra = z->c; { int ret = r_RV(z); if (ret <= 0) return ret; @@ -910,13 +968,17 @@ static int r_vowel_suffix(struct SN_env * z) { } extern int romanian_UTF_8_stem(struct SN_env * z) { + + { int ret = r_norm(z); + if (ret < 0) return ret; + } { int c1 = z->c; { int ret = r_prelude(z); if (ret < 0) return ret; } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_russian.c b/src/backend/snowball/libstemmer/stem_UTF_8_russian.c index 1d1b831426e06..815af215e87a5 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_russian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_russian.c @@ -356,23 +356,27 @@ static int r_mark_regions(struct SN_env * z) { z->I[1] = z->l; z->I[0] = z->l; { int c1 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 1072, 1103, 1); if (ret < 0) goto lab0; z->c += ret; } z->I[1] = z->c; - { + + { int ret = in_grouping_U(z, g_v, 1072, 1103, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = out_grouping_U(z, g_v, 1072, 1103, 1); if (ret < 0) goto lab0; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 1072, 1103, 1); if (ret < 0) goto lab0; z->c += ret; @@ -385,15 +389,14 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_perfective_gerund(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_0, 9); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -420,7 +423,7 @@ static int r_perfective_gerund(struct SN_env * z) { static int r_adjective(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_1, 26))) return 0; + if (!find_among_b(z, a_1, 26)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -436,7 +439,7 @@ static int r_adjectival(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; among_var = find_among_b(z, a_2, 8); - if (!(among_var)) { z->c = z->l - m1; goto lab0; } + if (!among_var) { z->c = z->l - m1; goto lab0; } z->bra = z->c; switch (among_var) { case 1: @@ -467,7 +470,7 @@ static int r_adjectival(struct SN_env * z) { static int r_reflexive(struct SN_env * z) { z->ket = z->c; if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 140 && z->p[z->c - 1] != 143)) return 0; - if (!(find_among_b(z, a_3, 2))) return 0; + if (!find_among_b(z, a_3, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -479,7 +482,7 @@ static int r_verb(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_4, 46); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -506,7 +509,7 @@ static int r_verb(struct SN_env * z) { static int r_noun(struct SN_env * z) { z->ket = z->c; - if (!(find_among_b(z, a_5, 36))) return 0; + if (!find_among_b(z, a_5, 36)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -517,7 +520,7 @@ static int r_noun(struct SN_env * z) { static int r_derivational(struct SN_env * z) { z->ket = z->c; if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 130 && z->p[z->c - 1] != 140)) return 0; - if (!(find_among_b(z, a_6, 2))) return 0; + if (!find_among_b(z, a_6, 2)) return 0; z->bra = z->c; { int ret = r_R2(z); if (ret <= 0) return ret; @@ -532,7 +535,7 @@ static int r_tidy_up(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_7, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -590,7 +593,7 @@ extern int russian_UTF_8_stem(struct SN_env * z) { } z->c = c1; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_serbian.c b/src/backend/snowball/libstemmer/stem_UTF_8_serbian.c index d2d206e0fa772..e20301b72ffb6 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_serbian.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_serbian.c @@ -4799,7 +4799,7 @@ static int r_cyr_to_lat(struct SN_env * z) { int c3 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 30); - if (!(among_var)) goto lab2; + if (!among_var) goto lab2; z->ket = z->c; switch (among_var) { case 1: @@ -5064,7 +5064,8 @@ static int r_prelude(struct SN_env * z) { static int r_mark_regions(struct SN_env * z) { z->I[1] = 1; { int c1 = z->c; - { + + { int ret = out_grouping_U(z, g_sa, 263, 382, 1); if (ret < 0) goto lab0; z->c += ret; @@ -5075,14 +5076,16 @@ static int r_mark_regions(struct SN_env * z) { } z->I[0] = z->l; { int c2 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab1; z->c += ret; } z->I[0] = z->c; - if (!(z->I[0] < 2)) goto lab1; - { + if (z->I[0] >= 2) goto lab1; + + { int ret = in_grouping_U(z, g_v, 97, 117, 1); if (ret < 0) goto lab1; z->c += ret; @@ -5103,18 +5106,19 @@ static int r_mark_regions(struct SN_env * z) { } } { int c4 = z->c; - if (!(z->c >= 2)) goto lab5; + if (z->c < 2) goto lab5; goto lab4; lab5: z->c = c4; - { + + { int ret = in_grouping_U(z, g_rg, 114, 114, 1); if (ret < 0) goto lab2; z->c += ret; } } lab4: - if (!((z->I[0] - z->c) > 1)) goto lab2; + if ((z->I[0] - z->c) <= 1) goto lab2; z->I[0] = z->c; lab2: z->c = c3; @@ -5123,8 +5127,7 @@ static int r_mark_regions(struct SN_env * z) { } static int r_R1(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_Step_1(struct SN_env * z) { @@ -5132,7 +5135,7 @@ static int r_Step_1(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((3435050 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_1, 130); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -5606,7 +5609,7 @@ static int r_Step_2(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_2, 2035); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -6483,7 +6486,7 @@ static int r_Step_2(struct SN_env * z) { static int r_Step_3(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((3188642 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_3, 26))) return 0; + if (!find_among_b(z, a_3, 26)) return 0; z->bra = z->c; { int ret = r_R1(z); if (ret <= 0) return ret; @@ -6495,15 +6498,15 @@ static int r_Step_3(struct SN_env * z) { } extern int serbian_UTF_8_stem(struct SN_env * z) { - + { int ret = r_cyr_to_lat(z); if (ret < 0) return ret; } - + { int ret = r_prelude(z); if (ret < 0) return ret; } - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_spanish.c b/src/backend/snowball/libstemmer/stem_UTF_8_spanish.c index 27698e1d82660..1b2e27bcc7241 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_spanish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_spanish.c @@ -512,7 +512,8 @@ static int r_mark_regions(struct SN_env * z) { if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab2; { int c3 = z->c; if (out_grouping_U(z, g_v, 97, 252, 0)) goto lab4; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab4; z->c += ret; @@ -521,7 +522,8 @@ static int r_mark_regions(struct SN_env * z) { lab4: z->c = c3; if (in_grouping_U(z, g_v, 97, 252, 0)) goto lab2; - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab2; z->c += ret; @@ -534,7 +536,8 @@ static int r_mark_regions(struct SN_env * z) { if (out_grouping_U(z, g_v, 97, 252, 0)) goto lab0; { int c4 = z->c; if (out_grouping_U(z, g_v, 97, 252, 0)) goto lab6; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab6; z->c += ret; @@ -557,23 +560,27 @@ static int r_mark_regions(struct SN_env * z) { z->c = c1; } { int c5 = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } z->I[1] = z->c; - { + + { int ret = out_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; } - { + + { int ret = in_grouping_U(z, g_v, 97, 252, 1); if (ret < 0) goto lab7; z->c += ret; @@ -592,7 +599,6 @@ static int r_postlude(struct SN_env * z) { z->bra = z->c; if (z->c + 1 >= z->l || z->p[z->c + 1] >> 5 != 5 || !((67641858 >> (z->p[z->c + 1] & 0x1f)) & 1)) among_var = 6; else among_var = find_among(z, a_0, 6); - if (!(among_var)) goto lab0; z->ket = z->c; switch (among_var) { case 1: @@ -636,29 +642,26 @@ static int r_postlude(struct SN_env * z) { } static int r_RV(struct SN_env * z) { - if (!(z->I[2] <= z->c)) return 0; - return 1; + return z->I[2] <= z->c; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R2(struct SN_env * z) { - if (!(z->I[0] <= z->c)) return 0; - return 1; + return z->I[0] <= z->c; } static int r_attached_pronoun(struct SN_env * z) { int among_var; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((557090 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_1, 13))) return 0; + if (!find_among_b(z, a_1, 13)) return 0; z->bra = z->c; if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 111 && z->p[z->c - 1] != 114)) return 0; among_var = find_among_b(z, a_2, 11); - if (!(among_var)) return 0; + if (!among_var) return 0; { int ret = r_RV(z); if (ret <= 0) return ret; } @@ -714,7 +717,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((835634 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; among_var = find_among_b(z, a_6, 46); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -782,7 +785,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4718616 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m2; goto lab1; } among_var = find_among_b(z, a_3, 4); - if (!(among_var)) { z->c = z->l - m2; goto lab1; } + if (!among_var) { z->c = z->l - m2; goto lab1; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m2; goto lab1; } @@ -819,7 +822,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m3 = z->l - z->c; (void)m3; z->ket = z->c; if (z->c - 3 <= z->lb || z->p[z->c - 1] != 101) { z->c = z->l - m3; goto lab2; } - if (!(find_among_b(z, a_4, 3))) { z->c = z->l - m3; goto lab2; } + if (!find_among_b(z, a_4, 3)) { z->c = z->l - m3; goto lab2; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m3; goto lab2; } @@ -842,7 +845,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m4 = z->l - z->c; (void)m4; z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((4198408 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->c = z->l - m4; goto lab3; } - if (!(find_among_b(z, a_5, 3))) { z->c = z->l - m4; goto lab3; } + if (!find_among_b(z, a_5, 3)) { z->c = z->l - m4; goto lab3; } z->bra = z->c; { int ret = r_R2(z); if (ret == 0) { z->c = z->l - m4; goto lab3; } @@ -887,7 +890,7 @@ static int r_y_verb_suffix(struct SN_env * z) { if (z->c < z->I[2]) return 0; mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; - if (!(find_among_b(z, a_7, 12))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_7, 12)) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -907,7 +910,7 @@ static int r_verb_suffix(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[2]; z->ket = z->c; among_var = find_among_b(z, a_8, 96); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -942,7 +945,7 @@ static int r_residual_suffix(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_9, 8); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -986,7 +989,7 @@ static int r_residual_suffix(struct SN_env * z) { } extern int spanish_UTF_8_stem(struct SN_env * z) { - + { int ret = r_mark_regions(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_swedish.c b/src/backend/snowball/libstemmer/stem_UTF_8_swedish.c index 2631862863297..c082cb0778dc0 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_swedish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_swedish.c @@ -127,7 +127,7 @@ static const symbol s_2_0[2] = { 'i', 'g' }; static const symbol s_2_1[3] = { 'l', 'i', 'g' }; static const symbol s_2_2[3] = { 'e', 'l', 's' }; static const symbol s_2_3[5] = { 'f', 'u', 'l', 'l', 't' }; -static const symbol s_2_4[5] = { 'l', 0xC3, 0xB6, 's', 't' }; +static const symbol s_2_4[4] = { 0xC3, 0xB6, 's', 't' }; static const struct among a_2[5] = { @@ -135,14 +135,16 @@ static const struct among a_2[5] = { 3, s_2_1, 0, 1, 0}, { 3, s_2_2, -1, 1, 0}, { 5, s_2_3, -1, 3, 0}, -{ 5, s_2_4, -1, 2, 0} +{ 4, s_2_4, -1, 2, 0} }; static const unsigned char g_v[] = { 17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 32 }; static const unsigned char g_s_ending[] = { 119, 127, 149 }; -static const symbol s_0[] = { 'l', 0xC3, 0xB6, 's' }; +static const unsigned char g_ost_ending[] = { 173, 58 }; + +static const symbol s_0[] = { 0xC3, 0xB6, 's' }; static const symbol s_1[] = { 'f', 'u', 'l', 'l' }; static int r_mark_regions(struct SN_env * z) { @@ -155,15 +157,17 @@ static int r_mark_regions(struct SN_env * z) { z->I[0] = z->c; z->c = c_test1; } + if (out_grouping_U(z, g_v, 97, 246, 1) < 0) return 0; - { + + { int ret = in_grouping_U(z, g_v, 97, 246, 1); if (ret < 0) return 0; z->c += ret; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab0; + + if (z->I[1] >= z->I[0]) goto lab0; z->I[1] = z->I[0]; lab0: return 1; @@ -178,7 +182,7 @@ static int r_main_suffix(struct SN_env * z) { z->ket = z->c; if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1851442 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_0, 37); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; z->lb = mlimit1; } @@ -205,7 +209,7 @@ static int r_consonant_pair(struct SN_env * z) { mlimit1 = z->lb; z->lb = z->I[1]; { int m2 = z->l - z->c; (void)m2; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1064976 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } - if (!(find_among_b(z, a_1, 7))) { z->lb = mlimit1; return 0; } + if (!find_among_b(z, a_1, 7)) { z->lb = mlimit1; return 0; } z->c = z->l - m2; z->ket = z->c; { int ret = skip_b_utf8(z->p, z->c, z->lb, 1); @@ -231,27 +235,28 @@ static int r_other_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((1572992 >> (z->p[z->c - 1] & 0x1f)) & 1)) { z->lb = mlimit1; return 0; } among_var = find_among_b(z, a_2, 5); - if (!(among_var)) { z->lb = mlimit1; return 0; } + if (!among_var) { z->lb = mlimit1; return 0; } z->bra = z->c; - switch (among_var) { - case 1: - { int ret = slice_del(z); - if (ret < 0) return ret; - } - break; - case 2: - { int ret = slice_from_s(z, 4, s_0); - if (ret < 0) return ret; - } - break; - case 3: - { int ret = slice_from_s(z, 4, s_1); - if (ret < 0) return ret; - } - break; - } z->lb = mlimit1; } + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + if (in_grouping_b_U(z, g_ost_ending, 105, 118, 0)) return 0; + { int ret = slice_from_s(z, 3, s_0); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 4, s_1); + if (ret < 0) return ret; + } + break; + } return 1; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_tamil.c b/src/backend/snowball/libstemmer/stem_UTF_8_tamil.c index 44cbdbaec749d..72e610fdb1ea8 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_tamil.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_tamil.c @@ -35,40 +35,42 @@ extern void tamil_UTF_8_close_env(struct SN_env * z); #ifdef __cplusplus } #endif -static const symbol s_0_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_0_1[3] = { 0xE0, 0xAE, 0x99 }; -static const symbol s_0_2[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_0_3[3] = { 0xE0, 0xAE, 0x9E }; -static const symbol s_0_4[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_0_5[3] = { 0xE0, 0xAE, 0xA8 }; -static const symbol s_0_6[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_0_7[3] = { 0xE0, 0xAE, 0xAE }; -static const symbol s_0_8[3] = { 0xE0, 0xAE, 0xAF }; -static const symbol s_0_9[3] = { 0xE0, 0xAE, 0xB5 }; - -static const struct among a_0[10] = +static const symbol s_0_0[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x81 }; +static const symbol s_0_1[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x82 }; +static const symbol s_0_2[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8A }; +static const symbol s_0_3[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8B }; + +static const struct among a_0[4] = { -{ 3, s_0_0, -1, -1, 0}, -{ 3, s_0_1, -1, -1, 0}, -{ 3, s_0_2, -1, -1, 0}, -{ 3, s_0_3, -1, -1, 0}, -{ 3, s_0_4, -1, -1, 0}, -{ 3, s_0_5, -1, -1, 0}, -{ 3, s_0_6, -1, -1, 0}, -{ 3, s_0_7, -1, -1, 0}, -{ 3, s_0_8, -1, -1, 0}, -{ 3, s_0_9, -1, -1, 0} +{ 6, s_0_0, -1, 3, 0}, +{ 6, s_0_1, -1, 4, 0}, +{ 6, s_0_2, -1, 2, 0}, +{ 6, s_0_3, -1, 1, 0} }; -static const symbol s_1_0[12] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D }; -static const symbol s_1_1[6] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D }; -static const symbol s_1_2[9] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4 }; - -static const struct among a_1[3] = +static const symbol s_1_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_1_1[3] = { 0xE0, 0xAE, 0x99 }; +static const symbol s_1_2[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_1_3[3] = { 0xE0, 0xAE, 0x9E }; +static const symbol s_1_4[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_1_5[3] = { 0xE0, 0xAE, 0xA8 }; +static const symbol s_1_6[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_1_7[3] = { 0xE0, 0xAE, 0xAE }; +static const symbol s_1_8[3] = { 0xE0, 0xAE, 0xAF }; +static const symbol s_1_9[3] = { 0xE0, 0xAE, 0xB5 }; + +static const struct among a_1[10] = { -{ 12, s_1_0, -1, -1, 0}, -{ 6, s_1_1, -1, -1, 0}, -{ 9, s_1_2, -1, -1, 0} +{ 3, s_1_0, -1, -1, 0}, +{ 3, s_1_1, -1, -1, 0}, +{ 3, s_1_2, -1, -1, 0}, +{ 3, s_1_3, -1, -1, 0}, +{ 3, s_1_4, -1, -1, 0}, +{ 3, s_1_5, -1, -1, 0}, +{ 3, s_1_6, -1, -1, 0}, +{ 3, s_1_7, -1, -1, 0}, +{ 3, s_1_8, -1, -1, 0}, +{ 3, s_1_9, -1, -1, 0} }; static const symbol s_2_0[3] = { 0xE0, 0xAF, 0x80 }; @@ -82,63 +84,82 @@ static const struct among a_2[3] = { 3, s_2_2, -1, -1, 0} }; -static const symbol s_3_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_3_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_3_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_3_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_3_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_3_5[3] = { 0xE0, 0xAE, 0xB1 }; +static const symbol s_3_0[3] = { 0xE0, 0xAF, 0x80 }; +static const symbol s_3_1[3] = { 0xE0, 0xAF, 0x81 }; +static const symbol s_3_2[3] = { 0xE0, 0xAF, 0x82 }; +static const symbol s_3_3[3] = { 0xE0, 0xAF, 0x86 }; +static const symbol s_3_4[3] = { 0xE0, 0xAF, 0x87 }; +static const symbol s_3_5[3] = { 0xE0, 0xAF, 0x88 }; +static const symbol s_3_6[3] = { 0xE0, 0xAE, 0xBE }; +static const symbol s_3_7[3] = { 0xE0, 0xAE, 0xBF }; -static const struct among a_3[6] = +static const struct among a_3[8] = { { 3, s_3_0, -1, -1, 0}, { 3, s_3_1, -1, -1, 0}, { 3, s_3_2, -1, -1, 0}, { 3, s_3_3, -1, -1, 0}, { 3, s_3_4, -1, -1, 0}, -{ 3, s_3_5, -1, -1, 0} +{ 3, s_3_5, -1, -1, 0}, +{ 3, s_3_6, -1, -1, 0}, +{ 3, s_3_7, -1, -1, 0} }; -static const symbol s_4_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_4_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_4_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_4_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_4_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_4_5[3] = { 0xE0, 0xAE, 0xB1 }; +static const symbol s_4_1[3] = { 0xE0, 0xAF, 0x88 }; +static const symbol s_4_2[3] = { 0xE0, 0xAF, 0x8D }; -static const struct among a_4[6] = +static const struct among a_4[3] = { -{ 3, s_4_0, -1, -1, 0}, -{ 3, s_4_1, -1, -1, 0}, -{ 3, s_4_2, -1, -1, 0}, -{ 3, s_4_3, -1, -1, 0}, -{ 3, s_4_4, -1, -1, 0}, -{ 3, s_4_5, -1, -1, 0} +{ 0, 0, -1, 2, 0}, +{ 3, s_4_1, 0, 1, 0}, +{ 3, s_4_2, 0, 1, 0} }; -static const symbol s_5_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_5_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_5_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_5_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_5_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_5_5[3] = { 0xE0, 0xAE, 0xB1 }; - -static const struct among a_5[6] = +static const symbol s_5_0[6] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x81 }; +static const symbol s_5_1[9] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_2[15] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_3[12] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_4[12] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_5[6] = { 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_6[12] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_7[12] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_8[12] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_9[6] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_10[12] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xAA, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_11[6] = { 0xE0, 0xAE, 0xAF, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_12[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_13[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8D }; +static const symbol s_5_14[9] = { 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4 }; +static const symbol s_5_15[3] = { 0xE0, 0xAE, 0xAF }; +static const symbol s_5_16[3] = { 0xE0, 0xAE, 0xB5 }; + +static const struct among a_5[17] = { -{ 3, s_5_0, -1, -1, 0}, -{ 3, s_5_1, -1, -1, 0}, -{ 3, s_5_2, -1, -1, 0}, -{ 3, s_5_3, -1, -1, 0}, -{ 3, s_5_4, -1, -1, 0}, -{ 3, s_5_5, -1, -1, 0} +{ 6, s_5_0, -1, 8, 0}, +{ 9, s_5_1, -1, 7, 0}, +{ 15, s_5_2, -1, 7, 0}, +{ 12, s_5_3, -1, 3, 0}, +{ 12, s_5_4, -1, 4, 0}, +{ 6, s_5_5, -1, 9, 0}, +{ 12, s_5_6, -1, 5, 0}, +{ 12, s_5_7, -1, 6, 0}, +{ 12, s_5_8, -1, 1, 0}, +{ 6, s_5_9, -1, 1, 0}, +{ 12, s_5_10, -1, 3, 0}, +{ 6, s_5_11, -1, 2, 0}, +{ 12, s_5_12, -1, 4, 0}, +{ 6, s_5_13, -1, 1, 0}, +{ 9, s_5_14, -1, 1, 0}, +{ 3, s_5_15, -1, 1, 0}, +{ 3, s_5_16, -1, 1, 0} }; -static const symbol s_6_0[3] = { 0xE0, 0xAE, 0xAF }; -static const symbol s_6_1[3] = { 0xE0, 0xAE, 0xB0 }; -static const symbol s_6_2[3] = { 0xE0, 0xAE, 0xB2 }; -static const symbol s_6_3[3] = { 0xE0, 0xAE, 0xB3 }; -static const symbol s_6_4[3] = { 0xE0, 0xAE, 0xB4 }; -static const symbol s_6_5[3] = { 0xE0, 0xAE, 0xB5 }; +static const symbol s_6_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_6_1[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_6_2[3] = { 0xE0, 0xAE, 0x9F }; +static const symbol s_6_3[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_6_4[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_6_5[3] = { 0xE0, 0xAE, 0xB1 }; static const struct among a_6[6] = { @@ -150,12 +171,12 @@ static const struct among a_6[6] = { 3, s_6_5, -1, -1, 0} }; -static const symbol s_7_0[3] = { 0xE0, 0xAE, 0x99 }; -static const symbol s_7_1[3] = { 0xE0, 0xAE, 0x9E }; -static const symbol s_7_2[3] = { 0xE0, 0xAE, 0xA3 }; -static const symbol s_7_3[3] = { 0xE0, 0xAE, 0xA8 }; -static const symbol s_7_4[3] = { 0xE0, 0xAE, 0xA9 }; -static const symbol s_7_5[3] = { 0xE0, 0xAE, 0xAE }; +static const symbol s_7_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_7_1[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_7_2[3] = { 0xE0, 0xAE, 0x9F }; +static const symbol s_7_3[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_7_4[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_7_5[3] = { 0xE0, 0xAE, 0xB1 }; static const struct among a_7[6] = { @@ -167,15 +188,31 @@ static const struct among a_7[6] = { 3, s_7_5, -1, -1, 0} }; -static const symbol s_8_0[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8D }; -static const symbol s_8_1[3] = { 0xE0, 0xAE, 0xAF }; -static const symbol s_8_2[3] = { 0xE0, 0xAE, 0xB5 }; - -static const struct among a_8[3] = +static const symbol s_8_0[3] = { 0xE0, 0xAE, 0x9E }; +static const symbol s_8_1[3] = { 0xE0, 0xAE, 0xA3 }; +static const symbol s_8_2[3] = { 0xE0, 0xAE, 0xA8 }; +static const symbol s_8_3[3] = { 0xE0, 0xAE, 0xA9 }; +static const symbol s_8_4[3] = { 0xE0, 0xAE, 0xAE }; +static const symbol s_8_5[3] = { 0xE0, 0xAE, 0xAF }; +static const symbol s_8_6[3] = { 0xE0, 0xAE, 0xB0 }; +static const symbol s_8_7[3] = { 0xE0, 0xAE, 0xB2 }; +static const symbol s_8_8[3] = { 0xE0, 0xAE, 0xB3 }; +static const symbol s_8_9[3] = { 0xE0, 0xAE, 0xB4 }; +static const symbol s_8_10[3] = { 0xE0, 0xAE, 0xB5 }; + +static const struct among a_8[11] = { -{ 6, s_8_0, -1, -1, 0}, +{ 3, s_8_0, -1, -1, 0}, { 3, s_8_1, -1, -1, 0}, -{ 3, s_8_2, -1, -1, 0} +{ 3, s_8_2, -1, -1, 0}, +{ 3, s_8_3, -1, -1, 0}, +{ 3, s_8_4, -1, -1, 0}, +{ 3, s_8_5, -1, -1, 0}, +{ 3, s_8_6, -1, -1, 0}, +{ 3, s_8_7, -1, -1, 0}, +{ 3, s_8_8, -1, -1, 0}, +{ 3, s_8_9, -1, -1, 0}, +{ 3, s_8_10, -1, -1, 0} }; static const symbol s_9_0[3] = { 0xE0, 0xAF, 0x80 }; @@ -184,10 +221,11 @@ static const symbol s_9_2[3] = { 0xE0, 0xAF, 0x82 }; static const symbol s_9_3[3] = { 0xE0, 0xAF, 0x86 }; static const symbol s_9_4[3] = { 0xE0, 0xAF, 0x87 }; static const symbol s_9_5[3] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_9_6[3] = { 0xE0, 0xAE, 0xBE }; -static const symbol s_9_7[3] = { 0xE0, 0xAE, 0xBF }; +static const symbol s_9_6[3] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_9_7[3] = { 0xE0, 0xAE, 0xBE }; +static const symbol s_9_8[3] = { 0xE0, 0xAE, 0xBF }; -static const struct among a_9[8] = +static const struct among a_9[9] = { { 3, s_9_0, -1, -1, 0}, { 3, s_9_1, -1, -1, 0}, @@ -196,81 +234,74 @@ static const struct among a_9[8] = { 3, s_9_4, -1, -1, 0}, { 3, s_9_5, -1, -1, 0}, { 3, s_9_6, -1, -1, 0}, -{ 3, s_9_7, -1, -1, 0} +{ 3, s_9_7, -1, -1, 0}, +{ 3, s_9_8, -1, -1, 0} }; -static const symbol s_10_0[3] = { 0xE0, 0xAF, 0x80 }; -static const symbol s_10_1[3] = { 0xE0, 0xAF, 0x81 }; -static const symbol s_10_2[3] = { 0xE0, 0xAF, 0x82 }; -static const symbol s_10_3[3] = { 0xE0, 0xAF, 0x86 }; -static const symbol s_10_4[3] = { 0xE0, 0xAF, 0x87 }; -static const symbol s_10_5[3] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_10_6[3] = { 0xE0, 0xAE, 0xBE }; -static const symbol s_10_7[3] = { 0xE0, 0xAE, 0xBF }; +static const symbol s_10_0[3] = { 0xE0, 0xAE, 0x85 }; +static const symbol s_10_1[3] = { 0xE0, 0xAE, 0x87 }; +static const symbol s_10_2[3] = { 0xE0, 0xAE, 0x89 }; -static const struct among a_10[8] = +static const struct among a_10[3] = { { 3, s_10_0, -1, -1, 0}, { 3, s_10_1, -1, -1, 0}, -{ 3, s_10_2, -1, -1, 0}, -{ 3, s_10_3, -1, -1, 0}, -{ 3, s_10_4, -1, -1, 0}, -{ 3, s_10_5, -1, -1, 0}, -{ 3, s_10_6, -1, -1, 0}, -{ 3, s_10_7, -1, -1, 0} +{ 3, s_10_2, -1, -1, 0} }; -static const symbol s_11_0[3] = { 0xE0, 0xAE, 0x85 }; -static const symbol s_11_1[3] = { 0xE0, 0xAE, 0x87 }; -static const symbol s_11_2[3] = { 0xE0, 0xAE, 0x89 }; - -static const struct among a_11[3] = +static const symbol s_11_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_11_1[3] = { 0xE0, 0xAE, 0x99 }; +static const symbol s_11_2[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_11_3[3] = { 0xE0, 0xAE, 0x9E }; +static const symbol s_11_4[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_11_5[3] = { 0xE0, 0xAE, 0xA8 }; +static const symbol s_11_6[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_11_7[3] = { 0xE0, 0xAE, 0xAE }; +static const symbol s_11_8[3] = { 0xE0, 0xAE, 0xAF }; +static const symbol s_11_9[3] = { 0xE0, 0xAE, 0xB5 }; + +static const struct among a_11[10] = { { 3, s_11_0, -1, -1, 0}, { 3, s_11_1, -1, -1, 0}, -{ 3, s_11_2, -1, -1, 0} +{ 3, s_11_2, -1, -1, 0}, +{ 3, s_11_3, -1, -1, 0}, +{ 3, s_11_4, -1, -1, 0}, +{ 3, s_11_5, -1, -1, 0}, +{ 3, s_11_6, -1, -1, 0}, +{ 3, s_11_7, -1, -1, 0}, +{ 3, s_11_8, -1, -1, 0}, +{ 3, s_11_9, -1, -1, 0} }; static const symbol s_12_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_12_1[3] = { 0xE0, 0xAE, 0x99 }; -static const symbol s_12_2[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_12_3[3] = { 0xE0, 0xAE, 0x9E }; -static const symbol s_12_4[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_12_5[3] = { 0xE0, 0xAE, 0xA8 }; -static const symbol s_12_6[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_12_7[3] = { 0xE0, 0xAE, 0xAE }; -static const symbol s_12_8[3] = { 0xE0, 0xAE, 0xAF }; -static const symbol s_12_9[3] = { 0xE0, 0xAE, 0xB5 }; - -static const struct among a_12[10] = +static const symbol s_12_1[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_12_2[3] = { 0xE0, 0xAE, 0x9F }; +static const symbol s_12_3[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_12_4[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_12_5[3] = { 0xE0, 0xAE, 0xB1 }; + +static const struct among a_12[6] = { { 3, s_12_0, -1, -1, 0}, { 3, s_12_1, -1, -1, 0}, { 3, s_12_2, -1, -1, 0}, { 3, s_12_3, -1, -1, 0}, { 3, s_12_4, -1, -1, 0}, -{ 3, s_12_5, -1, -1, 0}, -{ 3, s_12_6, -1, -1, 0}, -{ 3, s_12_7, -1, -1, 0}, -{ 3, s_12_8, -1, -1, 0}, -{ 3, s_12_9, -1, -1, 0} +{ 3, s_12_5, -1, -1, 0} }; -static const symbol s_13_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_13_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_13_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_13_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_13_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_13_5[3] = { 0xE0, 0xAE, 0xB1 }; +static const symbol s_13_0[9] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_13_1[18] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_13_2[15] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_13_3[15] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const struct among a_13[6] = +static const struct among a_13[4] = { -{ 3, s_13_0, -1, -1, 0}, -{ 3, s_13_1, -1, -1, 0}, -{ 3, s_13_2, -1, -1, 0}, -{ 3, s_13_3, -1, -1, 0}, -{ 3, s_13_4, -1, -1, 0}, -{ 3, s_13_5, -1, -1, 0} +{ 9, s_13_0, -1, 4, 0}, +{ 18, s_13_1, 0, 1, 0}, +{ 15, s_13_2, 0, 3, 0}, +{ 15, s_13_3, 0, 2, 0} }; static const symbol s_14_0[3] = { 0xE0, 0xAF, 0x87 }; @@ -319,115 +350,181 @@ static const symbol s_17_1[18] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xBF, 0xE0, 0xA static const symbol s_17_2[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; static const symbol s_17_3[12] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; static const symbol s_17_4[18] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; -static const symbol s_17_5[21] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_17_6[12] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F }; -static const symbol s_17_7[15] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xA3 }; -static const symbol s_17_8[9] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9 }; -static const symbol s_17_9[18] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA4, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9 }; -static const symbol s_17_10[15] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB0, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xAF }; -static const symbol s_17_11[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF }; -static const symbol s_17_12[15] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAE, 0xBF }; - -static const struct among a_17[13] = +static const symbol s_17_5[15] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; +static const symbol s_17_6[9] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88 }; +static const symbol s_17_7[15] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x88 }; +static const symbol s_17_8[12] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_17_9[15] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_17_10[12] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_17_11[21] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_17_12[12] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F }; +static const symbol s_17_13[15] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xA3 }; +static const symbol s_17_14[6] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9 }; +static const symbol s_17_15[9] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9 }; +static const symbol s_17_16[18] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA4, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9 }; +static const symbol s_17_17[12] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88, 0xE0, 0xAE, 0xAF }; +static const symbol s_17_18[12] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xAF }; +static const symbol s_17_19[15] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB0, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xAF }; +static const symbol s_17_20[9] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2 }; +static const symbol s_17_21[12] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB3 }; +static const symbol s_17_22[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF }; +static const symbol s_17_23[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF }; +static const symbol s_17_24[15] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAE, 0xBF }; +static const symbol s_17_25[15] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAE, 0xBF }; + +static const struct among a_17[26] = { -{ 15, s_17_0, -1, -1, 0}, -{ 18, s_17_1, -1, -1, 0}, -{ 9, s_17_2, -1, -1, 0}, -{ 12, s_17_3, -1, -1, 0}, -{ 18, s_17_4, -1, -1, 0}, -{ 21, s_17_5, -1, -1, 0}, -{ 12, s_17_6, -1, -1, 0}, -{ 15, s_17_7, -1, -1, 0}, -{ 9, s_17_8, -1, -1, 0}, -{ 18, s_17_9, 8, -1, 0}, -{ 15, s_17_10, -1, -1, 0}, -{ 9, s_17_11, -1, -1, 0}, -{ 15, s_17_12, -1, -1, 0} +{ 15, s_17_0, -1, 3, 0}, +{ 18, s_17_1, -1, 3, 0}, +{ 9, s_17_2, -1, 3, 0}, +{ 12, s_17_3, -1, 3, 0}, +{ 18, s_17_4, -1, 3, 0}, +{ 15, s_17_5, -1, 1, 0}, +{ 9, s_17_6, -1, 1, 0}, +{ 15, s_17_7, -1, 1, 0}, +{ 12, s_17_8, -1, 1, 0}, +{ 15, s_17_9, -1, 1, 0}, +{ 12, s_17_10, -1, 1, 0}, +{ 21, s_17_11, -1, 3, 0}, +{ 12, s_17_12, -1, 3, 0}, +{ 15, s_17_13, -1, 3, 0}, +{ 6, s_17_14, -1, 1, 0}, +{ 9, s_17_15, -1, 3, 0}, +{ 18, s_17_16, 15, 3, 0}, +{ 12, s_17_17, -1, 1, 0}, +{ 12, s_17_18, -1, 1, 0}, +{ 15, s_17_19, -1, 3, 0}, +{ 9, s_17_20, -1, 2, 0}, +{ 12, s_17_21, -1, 1, 0}, +{ 9, s_17_22, -1, 1, 0}, +{ 9, s_17_23, -1, 3, 0}, +{ 15, s_17_24, -1, 1, 0}, +{ 15, s_17_25, -1, 3, 0} }; -static const symbol s_18_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_18_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_18_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_18_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_18_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_18_5[3] = { 0xE0, 0xAE, 0xB1 }; +static const symbol s_18_0[3] = { 0xE0, 0xAF, 0x80 }; +static const symbol s_18_1[3] = { 0xE0, 0xAF, 0x81 }; +static const symbol s_18_2[3] = { 0xE0, 0xAF, 0x82 }; +static const symbol s_18_3[3] = { 0xE0, 0xAF, 0x86 }; +static const symbol s_18_4[3] = { 0xE0, 0xAF, 0x87 }; +static const symbol s_18_5[3] = { 0xE0, 0xAF, 0x88 }; +static const symbol s_18_6[3] = { 0xE0, 0xAE, 0xBE }; +static const symbol s_18_7[3] = { 0xE0, 0xAE, 0xBF }; -static const struct among a_18[6] = +static const struct among a_18[8] = { { 3, s_18_0, -1, -1, 0}, { 3, s_18_1, -1, -1, 0}, { 3, s_18_2, -1, -1, 0}, { 3, s_18_3, -1, -1, 0}, { 3, s_18_4, -1, -1, 0}, -{ 3, s_18_5, -1, -1, 0} +{ 3, s_18_5, -1, -1, 0}, +{ 3, s_18_6, -1, -1, 0}, +{ 3, s_18_7, -1, -1, 0} }; -static const symbol s_19_0[3] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_19_1[3] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_19_2[3] = { 0xE0, 0xAE, 0x9F }; -static const symbol s_19_3[3] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_19_4[3] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_19_5[3] = { 0xE0, 0xAE, 0xB1 }; +static const symbol s_19_0[3] = { 0xE0, 0xAF, 0x80 }; +static const symbol s_19_1[3] = { 0xE0, 0xAF, 0x81 }; +static const symbol s_19_2[3] = { 0xE0, 0xAF, 0x82 }; +static const symbol s_19_3[3] = { 0xE0, 0xAF, 0x86 }; +static const symbol s_19_4[3] = { 0xE0, 0xAF, 0x87 }; +static const symbol s_19_5[3] = { 0xE0, 0xAF, 0x88 }; +static const symbol s_19_6[3] = { 0xE0, 0xAE, 0xBE }; +static const symbol s_19_7[3] = { 0xE0, 0xAE, 0xBF }; -static const struct among a_19[6] = +static const struct among a_19[8] = { { 3, s_19_0, -1, -1, 0}, { 3, s_19_1, -1, -1, 0}, { 3, s_19_2, -1, -1, 0}, { 3, s_19_3, -1, -1, 0}, { 3, s_19_4, -1, -1, 0}, -{ 3, s_19_5, -1, -1, 0} +{ 3, s_19_5, -1, -1, 0}, +{ 3, s_19_6, -1, -1, 0}, +{ 3, s_19_7, -1, -1, 0} }; static const symbol s_20_0[3] = { 0xE0, 0xAF, 0x80 }; -static const symbol s_20_1[3] = { 0xE0, 0xAF, 0x81 }; -static const symbol s_20_2[3] = { 0xE0, 0xAF, 0x82 }; -static const symbol s_20_3[3] = { 0xE0, 0xAF, 0x86 }; -static const symbol s_20_4[3] = { 0xE0, 0xAF, 0x87 }; -static const symbol s_20_5[3] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_20_6[3] = { 0xE0, 0xAE, 0xBE }; -static const symbol s_20_7[3] = { 0xE0, 0xAE, 0xBF }; - -static const struct among a_20[8] = +static const symbol s_20_1[9] = { 0xE0, 0xAF, 0x8A, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; +static const symbol s_20_2[9] = { 0xE0, 0xAF, 0x8B, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; +static const symbol s_20_3[6] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; +static const symbol s_20_4[21] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; +static const symbol s_20_5[15] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; +static const symbol s_20_6[9] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88 }; +static const symbol s_20_7[6] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x88 }; +static const symbol s_20_8[9] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xA3, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_9[12] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_10[9] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_11[12] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_12[12] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_13[9] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_14[6] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_15[12] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_16[12] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_17[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_18[9] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_19[9] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_20[12] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xB4, 0xE0, 0xAF, 0x8D }; +static const symbol s_20_21[9] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F }; + +static const struct among a_20[22] = { -{ 3, s_20_0, -1, -1, 0}, -{ 3, s_20_1, -1, -1, 0}, -{ 3, s_20_2, -1, -1, 0}, -{ 3, s_20_3, -1, -1, 0}, -{ 3, s_20_4, -1, -1, 0}, -{ 3, s_20_5, -1, -1, 0}, -{ 3, s_20_6, -1, -1, 0}, -{ 3, s_20_7, -1, -1, 0} +{ 3, s_20_0, -1, 7, 0}, +{ 9, s_20_1, -1, 2, 0}, +{ 9, s_20_2, -1, 2, 0}, +{ 6, s_20_3, -1, 6, 0}, +{ 21, s_20_4, 3, 2, 0}, +{ 15, s_20_5, -1, 2, 0}, +{ 9, s_20_6, -1, 2, 0}, +{ 6, s_20_7, -1, 1, 0}, +{ 9, s_20_8, -1, 1, 0}, +{ 12, s_20_9, -1, 1, 0}, +{ 9, s_20_10, -1, 3, 0}, +{ 12, s_20_11, -1, 4, 0}, +{ 12, s_20_12, -1, 1, 0}, +{ 9, s_20_13, -1, 2, 0}, +{ 6, s_20_14, -1, 5, 0}, +{ 12, s_20_15, 14, 1, 0}, +{ 12, s_20_16, 14, 2, 0}, +{ 9, s_20_17, 14, 2, 0}, +{ 9, s_20_18, 14, 2, 0}, +{ 9, s_20_19, -1, 2, 0}, +{ 12, s_20_20, -1, 1, 0}, +{ 9, s_20_21, -1, 2, 0} }; -static const symbol s_21_0[3] = { 0xE0, 0xAF, 0x80 }; -static const symbol s_21_1[3] = { 0xE0, 0xAF, 0x81 }; -static const symbol s_21_2[3] = { 0xE0, 0xAF, 0x82 }; -static const symbol s_21_3[3] = { 0xE0, 0xAF, 0x86 }; -static const symbol s_21_4[3] = { 0xE0, 0xAF, 0x87 }; -static const symbol s_21_5[3] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_21_6[3] = { 0xE0, 0xAE, 0xBE }; -static const symbol s_21_7[3] = { 0xE0, 0xAE, 0xBF }; +static const symbol s_21_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_21_1[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_21_2[3] = { 0xE0, 0xAE, 0x9F }; +static const symbol s_21_3[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_21_4[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_21_5[3] = { 0xE0, 0xAE, 0xB1 }; -static const struct among a_21[8] = +static const struct among a_21[6] = { { 3, s_21_0, -1, -1, 0}, { 3, s_21_1, -1, -1, 0}, { 3, s_21_2, -1, -1, 0}, { 3, s_21_3, -1, -1, 0}, { 3, s_21_4, -1, -1, 0}, -{ 3, s_21_5, -1, -1, 0}, -{ 3, s_21_6, -1, -1, 0}, -{ 3, s_21_7, -1, -1, 0} +{ 3, s_21_5, -1, -1, 0} }; -static const symbol s_22_0[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; -static const symbol s_22_1[24] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8A, 0xE0, 0xAE, 0xA3, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_22_0[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_22_1[3] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_22_2[3] = { 0xE0, 0xAE, 0x9F }; +static const symbol s_22_3[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_22_4[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_22_5[3] = { 0xE0, 0xAE, 0xB1 }; -static const struct among a_22[2] = +static const struct among a_22[6] = { -{ 9, s_22_0, -1, -1, 0}, -{ 24, s_22_1, -1, -1, 0} +{ 3, s_22_0, -1, -1, 0}, +{ 3, s_22_1, -1, -1, 0}, +{ 3, s_22_2, -1, -1, 0}, +{ 3, s_22_3, -1, -1, 0}, +{ 3, s_22_4, -1, -1, 0}, +{ 3, s_22_5, -1, -1, 0} }; static const symbol s_23_0[3] = { 0xE0, 0xAE, 0x85 }; @@ -480,254 +577,195 @@ static const struct among a_24[8] = { 3, s_24_7, -1, -1, 0} }; -static const symbol s_25_0[18] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; -static const symbol s_25_1[21] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA8, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; -static const symbol s_25_2[12] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; -static const symbol s_25_3[15] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1 }; -static const symbol s_25_4[18] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA8, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1 }; -static const symbol s_25_5[9] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1 }; +static const symbol s_25_0[6] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81 }; +static const symbol s_25_1[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; +static const symbol s_25_2[6] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; +static const symbol s_25_3[15] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; +static const symbol s_25_4[6] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x88 }; +static const symbol s_25_5[6] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x88 }; +static const symbol s_25_6[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_7[9] = { 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_8[9] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_9[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_10[9] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_11[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_12[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_13[12] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_14[12] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_15[12] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_16[12] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_17[12] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_18[9] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_19[9] = { 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_20[9] = { 0xE0, 0xAF, 0x8B, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_21[9] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_22[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_23[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_24[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAF, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_25[9] = { 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_26[9] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_27[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_28[12] = { 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xAF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_29[9] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_30[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_31[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_32[12] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_33[24] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8A, 0xE0, 0xAE, 0xA3, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_34[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_35[9] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_36[9] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_37[9] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_38[9] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_39[12] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_25_40[3] = { 0xE0, 0xAE, 0x95 }; +static const symbol s_25_41[3] = { 0xE0, 0xAE, 0xA4 }; +static const symbol s_25_42[3] = { 0xE0, 0xAE, 0xA9 }; +static const symbol s_25_43[3] = { 0xE0, 0xAE, 0xAA }; +static const symbol s_25_44[3] = { 0xE0, 0xAE, 0xAF }; +static const symbol s_25_45[3] = { 0xE0, 0xAE, 0xBE }; + +static const struct among a_25[46] = +{ +{ 6, s_25_0, -1, 6, 0}, +{ 9, s_25_1, -1, 1, 0}, +{ 6, s_25_2, -1, 3, 0}, +{ 15, s_25_3, -1, 1, 0}, +{ 6, s_25_4, -1, 1, 0}, +{ 6, s_25_5, -1, 1, 0}, +{ 12, s_25_6, -1, 1, 0}, +{ 9, s_25_7, -1, 5, 0}, +{ 9, s_25_8, -1, 1, 0}, +{ 9, s_25_9, -1, 1, 0}, +{ 9, s_25_10, -1, 2, 0}, +{ 9, s_25_11, -1, 4, 0}, +{ 12, s_25_12, 11, 1, 0}, +{ 12, s_25_13, -1, 1, 0}, +{ 12, s_25_14, -1, 1, 0}, +{ 12, s_25_15, -1, 5, 0}, +{ 12, s_25_16, -1, 1, 0}, +{ 12, s_25_17, -1, 1, 0}, +{ 9, s_25_18, -1, 5, 0}, +{ 9, s_25_19, -1, 5, 0}, +{ 9, s_25_20, -1, 5, 0}, +{ 9, s_25_21, -1, 1, 0}, +{ 9, s_25_22, -1, 1, 0}, +{ 9, s_25_23, -1, 5, 0}, +{ 9, s_25_24, -1, 5, 0}, +{ 9, s_25_25, -1, 5, 0}, +{ 9, s_25_26, -1, 1, 0}, +{ 9, s_25_27, -1, 1, 0}, +{ 12, s_25_28, -1, 5, 0}, +{ 9, s_25_29, -1, 1, 0}, +{ 9, s_25_30, -1, 5, 0}, +{ 12, s_25_31, 30, 1, 0}, +{ 12, s_25_32, 30, 1, 0}, +{ 24, s_25_33, -1, 1, 0}, +{ 12, s_25_34, -1, 5, 0}, +{ 9, s_25_35, -1, 1, 0}, +{ 9, s_25_36, -1, 1, 0}, +{ 9, s_25_37, -1, 1, 0}, +{ 9, s_25_38, -1, 5, 0}, +{ 12, s_25_39, 38, 1, 0}, +{ 3, s_25_40, -1, 1, 0}, +{ 3, s_25_41, -1, 1, 0}, +{ 3, s_25_42, -1, 1, 0}, +{ 3, s_25_43, -1, 1, 0}, +{ 3, s_25_44, -1, 1, 0}, +{ 3, s_25_45, -1, 5, 0} +}; + +static const symbol s_26_0[18] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_26_1[21] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA8, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_26_2[12] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_26_3[15] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1 }; +static const symbol s_26_4[18] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA8, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1 }; +static const symbol s_26_5[9] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1 }; -static const struct among a_25[6] = +static const struct among a_26[6] = { -{ 18, s_25_0, -1, -1, 0}, -{ 21, s_25_1, -1, -1, 0}, -{ 12, s_25_2, -1, -1, 0}, -{ 15, s_25_3, -1, -1, 0}, -{ 18, s_25_4, -1, -1, 0}, -{ 9, s_25_5, -1, -1, 0} +{ 18, s_26_0, -1, -1, 0}, +{ 21, s_26_1, -1, -1, 0}, +{ 12, s_26_2, -1, -1, 0}, +{ 15, s_26_3, -1, -1, 0}, +{ 18, s_26_4, -1, -1, 0}, +{ 9, s_26_5, -1, -1, 0} }; -static const symbol s_0[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8B }; -static const symbol s_1[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8B }; -static const symbol s_2[] = { 0xE0, 0xAE, 0x93 }; -static const symbol s_3[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8A }; -static const symbol s_4[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x8A }; -static const symbol s_5[] = { 0xE0, 0xAE, 0x92 }; -static const symbol s_6[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x81 }; -static const symbol s_7[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x81 }; -static const symbol s_8[] = { 0xE0, 0xAE, 0x89 }; -static const symbol s_9[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x82 }; -static const symbol s_10[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x82 }; -static const symbol s_11[] = { 0xE0, 0xAE, 0x8A }; -static const symbol s_12[] = { 0xE0, 0xAE, 0x8E }; +static const symbol s_0[] = { 0xE0, 0xAE, 0x93 }; +static const symbol s_1[] = { 0xE0, 0xAE, 0x92 }; +static const symbol s_2[] = { 0xE0, 0xAE, 0x89 }; +static const symbol s_3[] = { 0xE0, 0xAE, 0x8A }; +static const symbol s_4[] = { 0xE0, 0xAE, 0x8E }; +static const symbol s_5[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_6[] = { 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_7[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; +static const symbol s_8[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; +static const symbol s_9[] = { 0xE0, 0xAF, 0x88 }; +static const symbol s_10[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_11[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_12[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; static const symbol s_13[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_14[] = { 0xE0, 0xAE, 0xAF, 0xE0, 0xAF, 0x8D }; -static const symbol s_15[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xAA, 0xE0, 0xAF, 0x8D }; -static const symbol s_16[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; -static const symbol s_17[] = { 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_18[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; +static const symbol s_14[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_15[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_16[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_17[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D }; +static const symbol s_18[] = { 0xE0, 0xAF, 0x8D }; static const symbol s_19[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_20[] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; -static const symbol s_21[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_22[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D }; -static const symbol s_23[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; -static const symbol s_24[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x8D }; -static const symbol s_25[] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_26[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_27[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; -static const symbol s_28[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_20[] = { 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; +static const symbol s_21[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_22[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; +static const symbol s_23[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_24[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_25[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_26[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_27[] = { 0xE0, 0xAE, 0xAE }; +static const symbol s_28[] = { 0xE0, 0xAF, 0x8D }; static const symbol s_29[] = { 0xE0, 0xAF, 0x8D }; static const symbol s_30[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_31[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_32[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x8D }; +static const symbol s_31[] = { 0xE0, 0xAE, 0xBF }; +static const symbol s_32[] = { 0xE0, 0xAF, 0x88 }; static const symbol s_33[] = { 0xE0, 0xAF, 0x8D }; static const symbol s_34[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_35[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_35[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; static const symbol s_36[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_37[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_38[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x81 }; -static const symbol s_39[] = { 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D }; -static const symbol s_40[] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_41[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_42[] = { 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D }; -static const symbol s_43[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_44[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_45[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_46[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x99, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_47[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_48[] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_49[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_50[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_51[] = { 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_52[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_53[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_54[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_55[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_56[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_57[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x88 }; -static const symbol s_58[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_59[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAE, 0xBF }; -static const symbol s_60[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF }; -static const symbol s_61[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xAF }; -static const symbol s_62[] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; -static const symbol s_63[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB3 }; -static const symbol s_64[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88, 0xE0, 0xAE, 0xAF }; -static const symbol s_65[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88 }; -static const symbol s_66[] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_67[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB2 }; -static const symbol s_68[] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9 }; -static const symbol s_69[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xBF }; -static const symbol s_70[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_71[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x88 }; -static const symbol s_72[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x88 }; -static const symbol s_73[] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_74[] = { 0xE0, 0xAF, 0x88 }; -static const symbol s_75[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_76[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_77[] = { 0xE0, 0xAF, 0x8A, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; -static const symbol s_78[] = { 0xE0, 0xAF, 0x8B, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81 }; -static const symbol s_79[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_80[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; -static const symbol s_81[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_82[] = { 0xE0, 0xAE, 0xAE }; -static const symbol s_83[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; -static const symbol s_84[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xA8, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; -static const symbol s_85[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F }; -static const symbol s_86[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0x9F, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_87[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_88[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x88 }; -static const symbol s_89[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_90[] = { 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_91[] = { 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_92[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_93[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAE, 0xA3, 0xE0, 0xAF, 0x8D }; -static const symbol s_94[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_95[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xB2, 0xE0, 0xAF, 0x8D }; -static const symbol s_96[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D }; -static const symbol s_97[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xB4, 0xE0, 0xAF, 0x8D }; -static const symbol s_98[] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_99[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; -static const symbol s_100[] = { 0xE0, 0xAF, 0x80 }; -static const symbol s_101[] = { 0xE0, 0xAE, 0xBF }; -static const symbol s_102[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_103[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_104[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_105[] = { 0xE0, 0xAE, 0xAE, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_106[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_107[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_108[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_109[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_110[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_111[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_112[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_113[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_114[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_115[] = { 0xE0, 0xAE, 0xA9 }; -static const symbol s_116[] = { 0xE0, 0xAE, 0xAA }; -static const symbol s_117[] = { 0xE0, 0xAE, 0x95 }; -static const symbol s_118[] = { 0xE0, 0xAE, 0xA4 }; -static const symbol s_119[] = { 0xE0, 0xAE, 0xAF }; -static const symbol s_120[] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_121[] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_122[] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_123[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; -static const symbol s_124[] = { 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x8D, 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81 }; -static const symbol s_125[] = { 0xE0, 0xAE, 0xAA, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_126[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_127[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_128[] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_129[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_130[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_131[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x88 }; -static const symbol s_132[] = { 0xE0, 0xAE, 0xB5, 0xE0, 0xAF, 0x88 }; -static const symbol s_133[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_134[] = { 0xE0, 0xAE, 0x9A }; -static const symbol s_135[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB3, 0xE0, 0xAF, 0x8D }; -static const symbol s_136[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_137[] = { 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_138[] = { 0xE0, 0xAE, 0xBE }; -static const symbol s_139[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_140[] = { 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_141[] = { 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_142[] = { 0xE0, 0xAF, 0x8B, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_143[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_144[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_145[] = { 0xE0, 0xAE, 0x9F, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_146[] = { 0xE0, 0xAE, 0xB1, 0xE0, 0xAF, 0x81, 0xE0, 0xAE, 0xAE, 0xE0, 0xAF, 0x8D }; -static const symbol s_147[] = { 0xE0, 0xAE, 0xBE, 0xE0, 0xAE, 0xAF, 0xE0, 0xAF, 0x8D }; -static const symbol s_148[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xA9, 0xE0, 0xAF, 0x8D }; -static const symbol s_149[] = { 0xE0, 0xAE, 0xA9, 0xE0, 0xAE, 0xBF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_150[] = { 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_151[] = { 0xE0, 0xAF, 0x80, 0xE0, 0xAE, 0xAF, 0xE0, 0xAE, 0xB0, 0xE0, 0xAF, 0x8D }; -static const symbol s_152[] = { 0xE0, 0xAF, 0x8D }; -static const symbol s_153[] = { 0xE0, 0xAE, 0x95, 0xE0, 0xAF, 0x81 }; -static const symbol s_154[] = { 0xE0, 0xAE, 0xA4, 0xE0, 0xAF, 0x81 }; -static const symbol s_155[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_37[] = { 0xE0, 0xAE, 0x9A }; +static const symbol s_38[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_39[] = { 0xE0, 0xAF, 0x8D }; +static const symbol s_40[] = { 0xE0, 0xAF, 0x8D }; static int r_has_min_length(struct SN_env * z) { - if (!(len_utf8(z->p) > 4)) return 0; - return 1; + return len_utf8(z->p) > 4; } static int r_fix_va_start(struct SN_env * z) { - { int c1 = z->c; - { int c2 = z->c; - { int c3 = z->c; - if (!(eq_s(z, 6, s_0))) { z->c = c3; goto lab2; } - lab2: - ; + int among_var; + z->bra = z->c; + if (z->c + 5 >= z->l || z->p[z->c + 5] >> 5 != 4 || !((3078 >> (z->p[z->c + 5] & 0x1f)) & 1)) return 0; + among_var = find_among(z, a_0, 4); + if (!among_var) return 0; + z->ket = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 3, s_0); + if (ret < 0) return ret; } - z->c = c2; - z->bra = z->c; - } - if (!(eq_s(z, 6, s_1))) goto lab1; - z->ket = z->c; - { int ret = slice_from_s(z, 3, s_2); - if (ret < 0) return ret; - } - goto lab0; - lab1: - z->c = c1; - { int c4 = z->c; - { int c5 = z->c; - if (!(eq_s(z, 6, s_3))) { z->c = c5; goto lab4; } - lab4: - ; + break; + case 2: + { int ret = slice_from_s(z, 3, s_1); + if (ret < 0) return ret; } - z->c = c4; - z->bra = z->c; - } - if (!(eq_s(z, 6, s_4))) goto lab3; - z->ket = z->c; - { int ret = slice_from_s(z, 3, s_5); - if (ret < 0) return ret; - } - goto lab0; - lab3: - z->c = c1; - { int c6 = z->c; - { int c7 = z->c; - if (!(eq_s(z, 6, s_6))) { z->c = c7; goto lab6; } - lab6: - ; + break; + case 3: + { int ret = slice_from_s(z, 3, s_2); + if (ret < 0) return ret; } - z->c = c6; - z->bra = z->c; - } - if (!(eq_s(z, 6, s_7))) goto lab5; - z->ket = z->c; - { int ret = slice_from_s(z, 3, s_8); - if (ret < 0) return ret; - } - goto lab0; - lab5: - z->c = c1; - { int c8 = z->c; - { int c9 = z->c; - if (!(eq_s(z, 6, s_9))) { z->c = c9; goto lab7; } - lab7: - ; + break; + case 4: + { int ret = slice_from_s(z, 3, s_3); + if (ret < 0) return ret; } - z->c = c8; - z->bra = z->c; - } - if (!(eq_s(z, 6, s_10))) return 0; - z->ket = z->c; - { int ret = slice_from_s(z, 3, s_11); - if (ret < 0) return ret; - } + break; } -lab0: return 1; } @@ -751,9 +789,9 @@ static int r_fix_endings(struct SN_env * z) { static int r_remove_question_prefixes(struct SN_env * z) { z->bra = z->c; - if (!(eq_s(z, 3, s_12))) return 0; - if (!(find_among(z, a_0, 10))) return 0; - if (!(eq_s(z, 3, s_13))) return 0; + if (!(eq_s(z, 3, s_4))) return 0; + if (!find_among(z, a_1, 10)) return 0; + if (!(eq_s(z, 3, s_5))) return 0; z->ket = z->c; { int ret = slice_del(z); if (ret < 0) return ret; @@ -768,233 +806,130 @@ static int r_remove_question_prefixes(struct SN_env * z) { } static int r_fix_ending(struct SN_env * z) { - if (!(len_utf8(z->p) > 3)) return 0; + int among_var; + if (len_utf8(z->p) <= 3) return 0; z->lb = z->c; z->c = z->l; { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 141 && z->p[z->c - 1] != 164)) goto lab1; - if (!(find_among_b(z, a_1, 3))) goto lab1; + among_var = find_among_b(z, a_5, 17); + if (!among_var) goto lab1; z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + { int m_test2 = z->l - z->c; + if (!find_among_b(z, a_2, 3)) goto lab1; + z->c = z->l - m_test2; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 6, s_6); + if (ret < 0) return ret; + } + break; + case 4: + { int ret = slice_from_s(z, 6, s_7); + if (ret < 0) return ret; + } + break; + case 5: + { int ret = slice_from_s(z, 6, s_8); + if (ret < 0) return ret; + } + break; + case 6: + if (!(z->I[0])) goto lab1; + { int m3 = z->l - z->c; (void)m3; + if (!(eq_s_b(z, 3, s_9))) goto lab2; + goto lab1; + lab2: + z->c = z->l - m3; + } + { int ret = slice_from_s(z, 6, s_10); + if (ret < 0) return ret; + } + break; + case 7: + { int ret = slice_from_s(z, 3, s_11); + if (ret < 0) return ret; + } + break; + case 8: + { int m4 = z->l - z->c; (void)m4; + if (!find_among_b(z, a_3, 8)) goto lab3; + goto lab1; + lab3: + z->c = z->l - m4; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 9: + if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 136 && z->p[z->c - 1] != 141)) among_var = 2; else + among_var = find_among_b(z, a_4, 3); + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + { int ret = slice_from_s(z, 6, s_12); + if (ret < 0) return ret; + } + break; + } + break; } goto lab0; lab1: z->c = z->l - m1; z->ket = z->c; - if (!(eq_s_b(z, 6, s_14))) goto lab2; - { int m_test2 = z->l - z->c; - if (!(find_among_b(z, a_2, 3))) goto lab2; - z->c = z->l - m_test2; - } - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab2: - z->c = z->l - m1; - z->ket = z->c; - { int m3 = z->l - z->c; (void)m3; - if (!(eq_s_b(z, 12, s_15))) goto lab5; + if (!(eq_s_b(z, 3, s_13))) return 0; + { int m5 = z->l - z->c; (void)m5; + if (!find_among_b(z, a_6, 6)) goto lab5; + { int m6 = z->l - z->c; (void)m6; + if (!(eq_s_b(z, 3, s_14))) { z->c = z->l - m6; goto lab6; } + if (!find_among_b(z, a_7, 6)) { z->c = z->l - m6; goto lab6; } + lab6: + ; + } + z->bra = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; + } goto lab4; lab5: - z->c = z->l - m3; - if (!(eq_s_b(z, 12, s_16))) goto lab3; - } - lab4: - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_17); - if (ret < 0) return ret; - } - goto lab0; - lab3: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 12, s_18))) goto lab6; - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_19); - if (ret < 0) return ret; - } - goto lab0; - lab6: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 12, s_20))) goto lab7; - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_21); - if (ret < 0) return ret; - } - goto lab0; - lab7: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 12, s_22))) goto lab8; - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_23); - if (ret < 0) return ret; - } - goto lab0; - lab8: - z->c = z->l - m1; - if (!(z->I[0])) goto lab9; - z->ket = z->c; - if (!(eq_s_b(z, 12, s_24))) goto lab9; - { int m_test4 = z->l - z->c; - { int m5 = z->l - z->c; (void)m5; - if (!(eq_s_b(z, 3, s_25))) goto lab10; - goto lab9; - lab10: - z->c = z->l - m5; - } - z->c = z->l - m_test4; - } - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_26); - if (ret < 0) return ret; - } - z->bra = z->c; - goto lab0; - lab9: - z->c = z->l - m1; - z->ket = z->c; - { int m6 = z->l - z->c; (void)m6; - if (!(eq_s_b(z, 9, s_27))) goto lab13; - goto lab12; - lab13: - z->c = z->l - m6; - if (!(eq_s_b(z, 15, s_28))) goto lab11; - } - lab12: - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_29); - if (ret < 0) return ret; - } - goto lab0; - lab11: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 3, s_30))) goto lab14; - if (!(find_among_b(z, a_3, 6))) goto lab14; - if (!(eq_s_b(z, 3, s_31))) goto lab14; - if (!(find_among_b(z, a_4, 6))) goto lab14; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab14: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 9, s_32))) goto lab15; - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_33); - if (ret < 0) return ret; - } - goto lab0; - lab15: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 3, s_34))) goto lab16; - if (!(find_among_b(z, a_5, 6))) goto lab16; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab16: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 3, s_35))) goto lab17; - { int m7 = z->l - z->c; (void)m7; - if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 5 || !((4030464 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab19; - if (!(find_among_b(z, a_6, 6))) goto lab19; - goto lab18; - lab19: - z->c = z->l - m7; - if (!(find_among_b(z, a_7, 6))) goto lab17; - } - lab18: - if (!(eq_s_b(z, 3, s_36))) goto lab17; - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_37); - if (ret < 0) return ret; - } - goto lab0; - lab17: - z->c = z->l - m1; - z->ket = z->c; - if (!(find_among_b(z, a_8, 3))) goto lab20; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab20: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 6, s_38))) goto lab21; - { int m_test8 = z->l - z->c; - { int m9 = z->l - z->c; (void)m9; - if (!(find_among_b(z, a_9, 8))) goto lab22; - goto lab21; - lab22: - z->c = z->l - m9; + z->c = z->l - m5; + if (!find_among_b(z, a_8, 11)) goto lab7; + z->bra = z->c; + if (!(eq_s_b(z, 3, s_15))) goto lab7; + { int ret = slice_del(z); + if (ret < 0) return ret; } - z->c = z->l - m_test8; - } - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab21: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 6, s_39))) goto lab23; - { int m_test10 = z->l - z->c; - { int m11 = z->l - z->c; (void)m11; - if (!(eq_s_b(z, 3, s_40))) goto lab24; - goto lab23; - lab24: - z->c = z->l - m11; + goto lab4; + lab7: + z->c = z->l - m5; + { int m_test7 = z->l - z->c; + if (!find_among_b(z, a_9, 9)) return 0; + z->c = z->l - m_test7; } - z->c = z->l - m_test10; - } - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_41); - if (ret < 0) return ret; - } - goto lab0; - lab23: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 6, s_42))) goto lab25; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - goto lab0; - lab25: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 3, s_43))) return 0; - { int m_test12 = z->l - z->c; - { int m13 = z->l - z->c; (void)m13; - if (!(find_among_b(z, a_10, 8))) goto lab27; - goto lab26; - lab27: - z->c = z->l - m13; - if (!(eq_s_b(z, 3, s_44))) return 0; + z->bra = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; } - lab26: - z->c = z->l - m_test12; - } - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; } + lab4: + ; } lab0: z->c = z->lb; @@ -1002,17 +937,15 @@ static int r_fix_ending(struct SN_env * z) { } static int r_remove_pronoun_prefixes(struct SN_env * z) { - z->I[1] = 0; z->bra = z->c; if (z->c + 2 >= z->l || z->p[z->c + 2] >> 5 != 4 || !((672 >> (z->p[z->c + 2] & 0x1f)) & 1)) return 0; - if (!(find_among(z, a_11, 3))) return 0; - if (!(find_among(z, a_12, 10))) return 0; - if (!(eq_s(z, 3, s_45))) return 0; + if (!find_among(z, a_10, 3)) return 0; + if (!find_among(z, a_11, 10)) return 0; + if (!(eq_s(z, 3, s_16))) return 0; z->ket = z->c; { int ret = slice_del(z); if (ret < 0) return ret; } - z->I[1] = 1; { int c1 = z->c; { int ret = r_fix_va_start(z); if (ret < 0) return ret; @@ -1023,55 +956,46 @@ static int r_remove_pronoun_prefixes(struct SN_env * z) { } static int r_remove_plural_suffix(struct SN_env * z) { - z->I[1] = 0; + int among_var; z->lb = z->c; z->c = z->l; - { int m1 = z->l - z->c; (void)m1; - z->ket = z->c; - if (!(eq_s_b(z, 18, s_46))) goto lab1; - { int m_test2 = z->l - z->c; - { int m3 = z->l - z->c; (void)m3; - if (!(find_among_b(z, a_13, 6))) goto lab2; - goto lab1; - lab2: - z->c = z->l - m3; + z->ket = z->c; + if (z->c - 8 <= z->lb || z->p[z->c - 1] != 141) return 0; + among_var = find_among_b(z, a_13, 4); + if (!among_var) return 0; + z->bra = z->c; + switch (among_var) { + case 1: + { int m1 = z->l - z->c; (void)m1; + if (!find_among_b(z, a_12, 6)) goto lab1; + { int ret = slice_from_s(z, 9, s_17); + if (ret < 0) return ret; + } + goto lab0; + lab1: + z->c = z->l - m1; + { int ret = slice_from_s(z, 3, s_18); + if (ret < 0) return ret; + } } - z->c = z->l - m_test2; - } - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_47); - if (ret < 0) return ret; - } - goto lab0; - lab1: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 15, s_48))) goto lab3; - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_49); - if (ret < 0) return ret; - } - goto lab0; - lab3: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 15, s_50))) goto lab4; - z->bra = z->c; - { int ret = slice_from_s(z, 6, s_51); - if (ret < 0) return ret; - } - goto lab0; - lab4: - z->c = z->l - m1; - z->ket = z->c; - if (!(eq_s_b(z, 9, s_52))) return 0; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } + lab0: + break; + case 2: + { int ret = slice_from_s(z, 6, s_19); + if (ret < 0) return ret; + } + break; + case 3: + { int ret = slice_from_s(z, 6, s_20); + if (ret < 0) return ret; + } + break; + case 4: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; } -lab0: - z->I[1] = 1; z->c = z->lb; return 1; } @@ -1080,22 +1004,20 @@ static int r_remove_question_suffixes(struct SN_env * z) { { int ret = r_has_min_length(z); if (ret <= 0) return ret; } - z->I[1] = 0; z->lb = z->c; z->c = z->l; { int m1 = z->l - z->c; (void)m1; z->ket = z->c; - if (!(find_among_b(z, a_14, 3))) goto lab0; + if (!find_among_b(z, a_14, 3)) goto lab0; z->bra = z->c; - { int ret = slice_from_s(z, 3, s_53); + { int ret = slice_from_s(z, 3, s_21); if (ret < 0) return ret; } - z->I[1] = 1; lab0: z->c = z->l - m1; } z->c = z->lb; - + { int ret = r_fix_endings(z); if (ret < 0) return ret; } @@ -1106,35 +1028,31 @@ static int r_remove_command_suffixes(struct SN_env * z) { { int ret = r_has_min_length(z); if (ret <= 0) return ret; } - z->I[1] = 0; z->lb = z->c; z->c = z->l; z->ket = z->c; if (z->c - 5 <= z->lb || z->p[z->c - 1] != 191) return 0; - if (!(find_among_b(z, a_15, 2))) return 0; + if (!find_among_b(z, a_15, 2)) return 0; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; } - z->I[1] = 1; z->c = z->lb; return 1; } static int r_remove_um(struct SN_env * z) { - z->I[1] = 0; { int ret = r_has_min_length(z); if (ret <= 0) return ret; } z->lb = z->c; z->c = z->l; z->ket = z->c; - if (!(eq_s_b(z, 9, s_54))) return 0; + if (!(eq_s_b(z, 9, s_22))) return 0; z->bra = z->c; - { int ret = slice_from_s(z, 3, s_55); + { int ret = slice_from_s(z, 3, s_23); if (ret < 0) return ret; } - z->I[1] = 1; z->c = z->lb; { int c1 = z->c; { int ret = r_fix_ending(z); @@ -1146,104 +1064,41 @@ static int r_remove_um(struct SN_env * z) { } static int r_remove_common_word_endings(struct SN_env * z) { - z->I[1] = 0; + int among_var; { int ret = r_has_min_length(z); if (ret <= 0) return ret; } z->lb = z->c; z->c = z->l; - { int m1 = z->l - z->c; (void)m1; - { int m_test2 = z->l - z->c; - z->ket = z->c; - { int m3 = z->l - z->c; (void)m3; - if (!(eq_s_b(z, 12, s_56))) goto lab3; - goto lab2; - lab3: - z->c = z->l - m3; - if (!(eq_s_b(z, 15, s_57))) goto lab4; - goto lab2; - lab4: - z->c = z->l - m3; - if (!(eq_s_b(z, 12, s_58))) goto lab5; - goto lab2; - lab5: - z->c = z->l - m3; - if (!(eq_s_b(z, 15, s_59))) goto lab6; - goto lab2; - lab6: - z->c = z->l - m3; - if (!(eq_s_b(z, 9, s_60))) goto lab7; - goto lab2; - lab7: - z->c = z->l - m3; - if (!(eq_s_b(z, 12, s_61))) goto lab8; - goto lab2; - lab8: - z->c = z->l - m3; - if (!(eq_s_b(z, 15, s_62))) goto lab9; - goto lab2; - lab9: - z->c = z->l - m3; - if (!(eq_s_b(z, 12, s_63))) goto lab10; - goto lab2; - lab10: - z->c = z->l - m3; - if (!(eq_s_b(z, 12, s_64))) goto lab11; - goto lab2; - lab11: - z->c = z->l - m3; - if (!(eq_s_b(z, 9, s_65))) goto lab12; - goto lab2; - lab12: - z->c = z->l - m3; - if (!(eq_s_b(z, 15, s_66))) goto lab13; - goto lab2; - lab13: - z->c = z->l - m3; - if (!(eq_s_b(z, 9, s_67))) goto lab14; - { int m_test4 = z->l - z->c; - { int m5 = z->l - z->c; (void)m5; - if (!(find_among_b(z, a_16, 8))) goto lab15; - goto lab14; - lab15: - z->c = z->l - m5; - } - z->c = z->l - m_test4; - } - goto lab2; - lab14: - z->c = z->l - m3; - if (!(eq_s_b(z, 6, s_68))) goto lab16; - goto lab2; - lab16: - z->c = z->l - m3; - if (!(eq_s_b(z, 9, s_69))) goto lab1; + z->ket = z->c; + among_var = find_among_b(z, a_17, 26); + if (!among_var) return 0; + z->bra = z->c; + switch (among_var) { + case 1: + { int ret = slice_from_s(z, 3, s_24); + if (ret < 0) return ret; } - lab2: - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_70); + break; + case 2: + { int m1 = z->l - z->c; (void)m1; + if (!find_among_b(z, a_16, 8)) goto lab0; + return 0; + lab0: + z->c = z->l - m1; + } + { int ret = slice_from_s(z, 3, s_25); if (ret < 0) return ret; } - z->I[1] = 1; - z->c = z->l - m_test2; - } - goto lab0; - lab1: - z->c = z->l - m1; - { int m_test6 = z->l - z->c; - z->ket = z->c; - if (!(find_among_b(z, a_17, 13))) return 0; - z->bra = z->c; + break; + case 3: { int ret = slice_del(z); if (ret < 0) return ret; } - z->I[1] = 1; - z->c = z->l - m_test6; - } + break; } -lab0: z->c = z->lb; - + { int ret = r_fix_endings(z); if (ret < 0) return ret; } @@ -1251,7 +1106,7 @@ static int r_remove_common_word_endings(struct SN_env * z) { } static int r_remove_vetrumai_urupukal(struct SN_env * z) { - z->I[1] = 0; + int among_var; z->I[0] = 0; { int ret = r_has_min_length(z); if (ret <= 0) return ret; @@ -1261,215 +1116,112 @@ static int r_remove_vetrumai_urupukal(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; { int m_test2 = z->l - z->c; z->ket = z->c; - if (!(eq_s_b(z, 6, s_71))) goto lab1; + if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((-2147475197 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab1; + among_var = find_among_b(z, a_20, 22); + if (!among_var) goto lab1; z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->c = z->l - m_test2; - } - goto lab0; - lab1: - z->c = z->l - m1; - { int m_test3 = z->l - z->c; - z->ket = z->c; - { int m4 = z->l - z->c; (void)m4; - { int m5 = z->l - z->c; (void)m5; - if (!(eq_s_b(z, 9, s_72))) goto lab6; - goto lab5; - lab6: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_73))) goto lab4; - } - lab5: - { int m_test6 = z->l - z->c; - { int m7 = z->l - z->c; (void)m7; - if (!(find_among_b(z, a_18, 6))) goto lab7; - goto lab4; - lab7: - z->c = z->l - m7; + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; } - z->c = z->l - m_test6; - } - goto lab3; - lab4: - z->c = z->l - m4; - if (!(eq_s_b(z, 3, s_74))) goto lab2; - { int m_test8 = z->l - z->c; - if (!(find_among_b(z, a_19, 6))) goto lab2; - if (!(eq_s_b(z, 3, s_75))) goto lab2; - z->c = z->l - m_test8; - } - } - lab3: - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_76); - if (ret < 0) return ret; - } - z->c = z->l - m_test3; - } - goto lab0; - lab2: - z->c = z->l - m1; - { int m_test9 = z->l - z->c; - z->ket = z->c; - { int m10 = z->l - z->c; (void)m10; - if (!(eq_s_b(z, 9, s_77))) goto lab10; - goto lab9; - lab10: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_78))) goto lab11; - goto lab9; - lab11: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_79))) goto lab12; - goto lab9; - lab12: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_80))) goto lab13; - goto lab9; - lab13: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_81))) goto lab14; - { int m_test11 = z->l - z->c; - { int m12 = z->l - z->c; (void)m12; - if (!(eq_s_b(z, 3, s_82))) goto lab15; - goto lab14; - lab15: - z->c = z->l - m12; + break; + case 2: + { int ret = slice_from_s(z, 3, s_26); + if (ret < 0) return ret; } - z->c = z->l - m_test11; - } - goto lab9; - lab14: - z->c = z->l - m10; - if (!(eq_s_b(z, 15, s_83))) goto lab16; - goto lab9; - lab16: - z->c = z->l - m10; - if (!(eq_s_b(z, 21, s_84))) goto lab17; - goto lab9; - lab17: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_85))) goto lab18; - goto lab9; - lab18: - z->c = z->l - m10; - if (!(len_utf8(z->p) >= 7)) goto lab19; - if (!(eq_s_b(z, 12, s_86))) goto lab19; - goto lab9; - lab19: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_87))) goto lab20; - goto lab9; - lab20: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_88))) goto lab21; - goto lab9; - lab21: - z->c = z->l - m10; - if (!(eq_s_b(z, 12, s_89))) goto lab22; - goto lab9; - lab22: - z->c = z->l - m10; - if (!(eq_s_b(z, 6, s_90))) goto lab23; - { int m_test13 = z->l - z->c; - { int m14 = z->l - z->c; (void)m14; - if (!(find_among_b(z, a_20, 8))) goto lab24; - goto lab23; - lab24: - z->c = z->l - m14; + break; + case 3: + { int m3 = z->l - z->c; (void)m3; + if (!(eq_s_b(z, 3, s_27))) goto lab2; + goto lab1; + lab2: + z->c = z->l - m3; } - z->c = z->l - m_test13; - } - goto lab9; - lab23: - z->c = z->l - m10; - if (!(eq_s_b(z, 9, s_91))) goto lab8; - } - lab9: - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_92); - if (ret < 0) return ret; + { int ret = slice_from_s(z, 3, s_28); + if (ret < 0) return ret; + } + break; + case 4: + if (len_utf8(z->p) < 7) goto lab1; + { int ret = slice_from_s(z, 3, s_29); + if (ret < 0) return ret; + } + break; + case 5: + { int m4 = z->l - z->c; (void)m4; + if (!find_among_b(z, a_18, 8)) goto lab3; + goto lab1; + lab3: + z->c = z->l - m4; + } + { int ret = slice_from_s(z, 3, s_30); + if (ret < 0) return ret; + } + break; + case 6: + { int m5 = z->l - z->c; (void)m5; + if (!find_among_b(z, a_19, 8)) goto lab4; + goto lab1; + lab4: + z->c = z->l - m5; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 7: + { int ret = slice_from_s(z, 3, s_31); + if (ret < 0) return ret; + } + break; } - z->c = z->l - m_test9; + z->c = z->l - m_test2; } goto lab0; - lab8: + lab1: z->c = z->l - m1; - { int m_test15 = z->l - z->c; + { int m_test6 = z->l - z->c; z->ket = z->c; - { int m16 = z->l - z->c; (void)m16; - if (!(eq_s_b(z, 9, s_93))) goto lab27; - goto lab26; - lab27: - z->c = z->l - m16; - if (!(eq_s_b(z, 12, s_94))) goto lab28; - goto lab26; - lab28: - z->c = z->l - m16; - if (!(eq_s_b(z, 12, s_95))) goto lab29; - goto lab26; - lab29: - z->c = z->l - m16; - if (!(eq_s_b(z, 12, s_96))) goto lab30; - goto lab26; - lab30: - z->c = z->l - m16; - if (!(eq_s_b(z, 12, s_97))) goto lab31; - goto lab26; - lab31: - z->c = z->l - m16; - if (!(eq_s_b(z, 12, s_98))) goto lab32; - goto lab26; - lab32: - z->c = z->l - m16; - if (!(eq_s_b(z, 6, s_99))) goto lab25; - { int m_test17 = z->l - z->c; - { int m18 = z->l - z->c; (void)m18; - if (!(find_among_b(z, a_21, 8))) goto lab33; - goto lab25; - lab33: - z->c = z->l - m18; - } - z->c = z->l - m_test17; + if (!(eq_s_b(z, 3, s_32))) return 0; + { int m7 = z->l - z->c; (void)m7; + { int m8 = z->l - z->c; (void)m8; + if (!find_among_b(z, a_21, 6)) goto lab7; + goto lab6; + lab7: + z->c = z->l - m8; + } + goto lab5; + lab6: + z->c = z->l - m7; + { int m_test9 = z->l - z->c; + if (!find_among_b(z, a_22, 6)) return 0; + if (!(eq_s_b(z, 3, s_33))) return 0; + z->c = z->l - m_test9; } } - lab26: - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->c = z->l - m_test15; - } - goto lab0; - lab25: - z->c = z->l - m1; - { int m_test19 = z->l - z->c; - z->ket = z->c; - if (!(eq_s_b(z, 3, s_100))) return 0; + lab5: z->bra = z->c; - { int ret = slice_from_s(z, 3, s_101); + { int ret = slice_from_s(z, 3, s_34); if (ret < 0) return ret; } - z->c = z->l - m_test19; + z->c = z->l - m_test6; } } lab0: - z->I[1] = 1; z->I[0] = 1; - { int m20 = z->l - z->c; (void)m20; + { int m10 = z->l - z->c; (void)m10; z->ket = z->c; - if (!(eq_s_b(z, 9, s_102))) goto lab34; + if (!(eq_s_b(z, 9, s_35))) goto lab8; z->bra = z->c; - { int ret = slice_from_s(z, 3, s_103); + { int ret = slice_from_s(z, 3, s_36); if (ret < 0) return ret; } - lab34: - z->c = z->l - m20; + lab8: + z->c = z->l - m10; } z->c = z->lb; - + { int ret = r_fix_endings(z); if (ret < 0) return ret; } @@ -1496,6 +1248,7 @@ static int r_remove_tense_suffixes(struct SN_env * z) { } static int r_remove_tense_suffix(struct SN_env * z) { + int among_var; z->I[1] = 0; { int ret = r_has_min_length(z); if (ret <= 0) return ret; @@ -1503,301 +1256,86 @@ static int r_remove_tense_suffix(struct SN_env * z) { z->lb = z->c; z->c = z->l; { int m1 = z->l - z->c; (void)m1; - { int m2 = z->l - z->c; (void)m2; - { int m_test3 = z->l - z->c; - z->ket = z->c; - if (z->c - 8 <= z->lb || (z->p[z->c - 1] != 129 && z->p[z->c - 1] != 141)) goto lab2; - if (!(find_among_b(z, a_22, 2))) goto lab2; - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->I[1] = 1; - z->c = z->l - m_test3; - } - goto lab1; - lab2: - z->c = z->l - m2; - { int m_test4 = z->l - z->c; - z->ket = z->c; - { int m5 = z->l - z->c; (void)m5; - if (!(eq_s_b(z, 12, s_104))) goto lab5; - goto lab4; - lab5: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_105))) goto lab6; - goto lab4; - lab6: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_106))) goto lab7; - goto lab4; - lab7: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_107))) goto lab8; - goto lab4; - lab8: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_108))) goto lab9; - goto lab4; - lab9: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_109))) goto lab10; - goto lab4; - lab10: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_110))) goto lab11; + { int m_test2 = z->l - z->c; + z->ket = z->c; + among_var = find_among_b(z, a_25, 46); + if (!among_var) goto lab0; + z->bra = z->c; + switch (among_var) { + case 1: + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 2: + { int m3 = z->l - z->c; (void)m3; + if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((1951712 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab1; + if (!find_among_b(z, a_23, 12)) goto lab1; + goto lab0; + lab1: + z->c = z->l - m3; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 3: + { int m4 = z->l - z->c; (void)m4; + if (!find_among_b(z, a_24, 8)) goto lab2; + goto lab0; + lab2: + z->c = z->l - m4; + } + { int ret = slice_del(z); + if (ret < 0) return ret; + } + break; + case 4: + { int m5 = z->l - z->c; (void)m5; + if (!(eq_s_b(z, 3, s_37))) goto lab3; + goto lab0; + lab3: + z->c = z->l - m5; + } + { int ret = slice_from_s(z, 3, s_38); + if (ret < 0) return ret; + } + break; + case 5: + { int ret = slice_from_s(z, 3, s_39); + if (ret < 0) return ret; + } + break; + case 6: { int m_test6 = z->l - z->c; - { int m7 = z->l - z->c; (void)m7; - if (z->c - 2 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((1951712 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab12; - if (!(find_among_b(z, a_23, 12))) goto lab12; - goto lab11; - lab12: - z->c = z->l - m7; - } + if (!(eq_s_b(z, 3, s_40))) goto lab0; z->c = z->l - m_test6; } - goto lab4; - lab11: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_111))) goto lab13; - goto lab4; - lab13: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_112))) goto lab14; - goto lab4; - lab14: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_113))) goto lab15; - goto lab4; - lab15: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_114))) goto lab16; - goto lab4; - lab16: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_115))) goto lab17; - goto lab4; - lab17: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_116))) goto lab18; - goto lab4; - lab18: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_117))) goto lab19; - goto lab4; - lab19: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_118))) goto lab20; - goto lab4; - lab20: - z->c = z->l - m5; - if (!(eq_s_b(z, 3, s_119))) goto lab21; - goto lab4; - lab21: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_120))) goto lab22; - goto lab4; - lab22: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_121))) goto lab23; - goto lab4; - lab23: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_122))) goto lab24; - goto lab4; - lab24: - z->c = z->l - m5; - if (!(eq_s_b(z, 6, s_123))) goto lab25; - { int m_test8 = z->l - z->c; - { int m9 = z->l - z->c; (void)m9; - if (!(find_among_b(z, a_24, 8))) goto lab26; - goto lab25; - lab26: - z->c = z->l - m9; - } - z->c = z->l - m_test8; - } - goto lab4; - lab25: - z->c = z->l - m5; - if (!(eq_s_b(z, 15, s_124))) goto lab27; - goto lab4; - lab27: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_125))) goto lab28; - goto lab4; - lab28: - z->c = z->l - m5; - if (!(eq_s_b(z, 9, s_126))) goto lab29; - goto lab4; - lab29: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_127))) goto lab30; - goto lab4; - lab30: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_128))) goto lab31; - goto lab4; - lab31: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_129))) goto lab32; - goto lab4; - lab32: - z->c = z->l - m5; - if (!(eq_s_b(z, 12, s_130))) goto lab33; - goto lab4; - lab33: - z->c = z->l - m5; - if (!(eq_s_b(z, 6, s_131))) goto lab34; - goto lab4; - lab34: - z->c = z->l - m5; - if (!(eq_s_b(z, 6, s_132))) goto lab3; - } - lab4: - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->I[1] = 1; - z->c = z->l - m_test4; - } - goto lab1; - lab3: - z->c = z->l - m2; - { int m_test10 = z->l - z->c; - z->ket = z->c; - { int m11 = z->l - z->c; (void)m11; - if (!(eq_s_b(z, 9, s_133))) goto lab37; - { int m_test12 = z->l - z->c; - { int m13 = z->l - z->c; (void)m13; - if (!(eq_s_b(z, 3, s_134))) goto lab38; - goto lab37; - lab38: - z->c = z->l - m13; - } - z->c = z->l - m_test12; + { int ret = slice_del(z); + if (ret < 0) return ret; } - goto lab36; - lab37: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_135))) goto lab39; - goto lab36; - lab39: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_136))) goto lab40; - goto lab36; - lab40: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_137))) goto lab41; - goto lab36; - lab41: - z->c = z->l - m11; - if (!(eq_s_b(z, 3, s_138))) goto lab42; - goto lab36; - lab42: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_139))) goto lab43; - goto lab36; - lab43: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_140))) goto lab44; - goto lab36; - lab44: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_141))) goto lab45; - goto lab36; - lab45: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_142))) goto lab46; - goto lab36; - lab46: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_143))) goto lab47; - goto lab36; - lab47: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_144))) goto lab48; - goto lab36; - lab48: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_145))) goto lab49; - goto lab36; - lab49: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_146))) goto lab50; - goto lab36; - lab50: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_147))) goto lab51; - goto lab36; - lab51: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_148))) goto lab52; - goto lab36; - lab52: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_149))) goto lab53; - goto lab36; - lab53: - z->c = z->l - m11; - if (!(eq_s_b(z, 9, s_150))) goto lab54; - goto lab36; - lab54: - z->c = z->l - m11; - if (!(eq_s_b(z, 12, s_151))) goto lab35; - } - lab36: - z->bra = z->c; - { int ret = slice_from_s(z, 3, s_152); - if (ret < 0) return ret; - } - z->I[1] = 1; - z->c = z->l - m_test10; - } - goto lab1; - lab35: - z->c = z->l - m2; - { int m_test14 = z->l - z->c; - z->ket = z->c; - { int m15 = z->l - z->c; (void)m15; - if (!(eq_s_b(z, 6, s_153))) goto lab56; - goto lab55; - lab56: - z->c = z->l - m15; - if (!(eq_s_b(z, 6, s_154))) goto lab0; - } - lab55: - { int m_test16 = z->l - z->c; - if (!(eq_s_b(z, 3, s_155))) goto lab0; - z->c = z->l - m_test16; - } - z->bra = z->c; - { int ret = slice_del(z); - if (ret < 0) return ret; - } - z->I[1] = 1; - z->c = z->l - m_test14; + break; } + z->I[1] = 1; + z->c = z->l - m_test2; } - lab1: lab0: z->c = z->l - m1; } - { int m17 = z->l - z->c; (void)m17; + { int m7 = z->l - z->c; (void)m7; z->ket = z->c; - if (z->c - 8 <= z->lb || (z->p[z->c - 1] != 141 && z->p[z->c - 1] != 177)) goto lab57; - if (!(find_among_b(z, a_25, 6))) goto lab57; + if (z->c - 8 <= z->lb || (z->p[z->c - 1] != 141 && z->p[z->c - 1] != 177)) goto lab4; + if (!find_among_b(z, a_26, 6)) goto lab4; z->bra = z->c; { int ret = slice_del(z); if (ret < 0) return ret; } z->I[1] = 1; - lab57: - z->c = z->l - m17; + lab4: + z->c = z->l - m7; } z->c = z->lb; - + { int ret = r_fix_endings(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_turkish.c b/src/backend/snowball/libstemmer/stem_UTF_8_turkish.c index 3d0403278776f..efb1b30604b17 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_turkish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_turkish.c @@ -12,6 +12,7 @@ extern int turkish_UTF_8_stem(struct SN_env * z); static int r_stem_suffix_chain_before_ki(struct SN_env * z); static int r_stem_noun_suffixes(struct SN_env * z); static int r_stem_nominal_verb_suffixes(struct SN_env * z); +static int r_remove_proper_noun_suffix(struct SN_env * z); static int r_postlude(struct SN_env * z); static int r_post_process_last_consonants(struct SN_env * z); static int r_more_than_one_syllable_word(struct SN_env * z); @@ -458,49 +459,58 @@ static const symbol s_17[] = { 's', 'o', 'y' }; static int r_check_vowel_harmony(struct SN_env * z) { { int m_test1 = z->l - z->c; + if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) return 0; { int m2 = z->l - z->c; (void)m2; if (z->c <= z->lb || z->p[z->c - 1] != 'a') goto lab1; z->c--; + if (out_grouping_b_U(z, g_vowel1, 97, 305, 1) < 0) goto lab1; goto lab0; lab1: z->c = z->l - m2; if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab2; z->c--; + if (out_grouping_b_U(z, g_vowel2, 101, 252, 1) < 0) goto lab2; goto lab0; lab2: z->c = z->l - m2; if (!(eq_s_b(z, 2, s_0))) goto lab3; + if (out_grouping_b_U(z, g_vowel3, 97, 305, 1) < 0) goto lab3; goto lab0; lab3: z->c = z->l - m2; if (z->c <= z->lb || z->p[z->c - 1] != 'i') goto lab4; z->c--; + if (out_grouping_b_U(z, g_vowel4, 101, 105, 1) < 0) goto lab4; goto lab0; lab4: z->c = z->l - m2; if (z->c <= z->lb || z->p[z->c - 1] != 'o') goto lab5; z->c--; + if (out_grouping_b_U(z, g_vowel5, 111, 117, 1) < 0) goto lab5; goto lab0; lab5: z->c = z->l - m2; if (!(eq_s_b(z, 2, s_1))) goto lab6; + if (out_grouping_b_U(z, g_vowel6, 246, 252, 1) < 0) goto lab6; goto lab0; lab6: z->c = z->l - m2; if (z->c <= z->lb || z->p[z->c - 1] != 'u') goto lab7; z->c--; + if (out_grouping_b_U(z, g_vowel5, 111, 117, 1) < 0) goto lab7; goto lab0; lab7: z->c = z->l - m2; if (!(eq_s_b(z, 2, s_2))) return 0; + if (out_grouping_b_U(z, g_vowel6, 246, 252, 1) < 0) return 0; } lab0: @@ -645,7 +655,7 @@ static int r_mark_suffix_with_optional_U_vowel(struct SN_env * z) { static int r_mark_possessives(struct SN_env * z) { if (z->c <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((67133440 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_0, 10))) return 0; + if (!find_among_b(z, a_0, 10)) return 0; { int ret = r_mark_suffix_with_optional_U_vowel(z); if (ret <= 0) return ret; } @@ -665,7 +675,7 @@ static int r_mark_sU(struct SN_env * z) { static int r_mark_lArI(struct SN_env * z) { if (z->c - 3 <= z->lb || (z->p[z->c - 1] != 105 && z->p[z->c - 1] != 177)) return 0; - if (!(find_among_b(z, a_1, 2))) return 0; + if (!find_among_b(z, a_1, 2)) return 0; return 1; } @@ -684,7 +694,7 @@ static int r_mark_nU(struct SN_env * z) { { int ret = r_check_vowel_harmony(z); if (ret <= 0) return ret; } - if (!(find_among_b(z, a_2, 4))) return 0; + if (!find_among_b(z, a_2, 4)) return 0; return 1; } @@ -693,7 +703,7 @@ static int r_mark_nUn(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || z->p[z->c - 1] != 110) return 0; - if (!(find_among_b(z, a_3, 4))) return 0; + if (!find_among_b(z, a_3, 4)) return 0; { int ret = r_mark_suffix_with_optional_n_consonant(z); if (ret <= 0) return ret; } @@ -705,7 +715,7 @@ static int r_mark_yA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_4, 2))) return 0; + if (!find_among_b(z, a_4, 2)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -717,7 +727,7 @@ static int r_mark_nA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_5, 2))) return 0; + if (!find_among_b(z, a_5, 2)) return 0; return 1; } @@ -726,7 +736,7 @@ static int r_mark_DA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_6, 4))) return 0; + if (!find_among_b(z, a_6, 4)) return 0; return 1; } @@ -735,7 +745,7 @@ static int r_mark_ndA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_7, 2))) return 0; + if (!find_among_b(z, a_7, 2)) return 0; return 1; } @@ -744,7 +754,7 @@ static int r_mark_DAn(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || z->p[z->c - 1] != 110) return 0; - if (!(find_among_b(z, a_8, 4))) return 0; + if (!find_among_b(z, a_8, 4)) return 0; return 1; } @@ -753,7 +763,7 @@ static int r_mark_ndAn(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 3 <= z->lb || z->p[z->c - 1] != 110) return 0; - if (!(find_among_b(z, a_9, 2))) return 0; + if (!find_among_b(z, a_9, 2)) return 0; return 1; } @@ -762,7 +772,7 @@ static int r_mark_ylA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_10, 2))) return 0; + if (!find_among_b(z, a_10, 2)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -779,7 +789,7 @@ static int r_mark_ncA(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_11, 2))) return 0; + if (!find_among_b(z, a_11, 2)) return 0; { int ret = r_mark_suffix_with_optional_n_consonant(z); if (ret <= 0) return ret; } @@ -791,7 +801,7 @@ static int r_mark_yUm(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || z->p[z->c - 1] != 109) return 0; - if (!(find_among_b(z, a_12, 4))) return 0; + if (!find_among_b(z, a_12, 4)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -803,7 +813,7 @@ static int r_mark_sUn(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || z->p[z->c - 1] != 110) return 0; - if (!(find_among_b(z, a_13, 4))) return 0; + if (!find_among_b(z, a_13, 4)) return 0; return 1; } @@ -812,7 +822,7 @@ static int r_mark_yUz(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 1 <= z->lb || z->p[z->c - 1] != 122) return 0; - if (!(find_among_b(z, a_14, 4))) return 0; + if (!find_among_b(z, a_14, 4)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -821,7 +831,7 @@ static int r_mark_yUz(struct SN_env * z) { static int r_mark_sUnUz(struct SN_env * z) { if (z->c - 4 <= z->lb || z->p[z->c - 1] != 122) return 0; - if (!(find_among_b(z, a_15, 4))) return 0; + if (!find_among_b(z, a_15, 4)) return 0; return 1; } @@ -830,7 +840,7 @@ static int r_mark_lAr(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || z->p[z->c - 1] != 114) return 0; - if (!(find_among_b(z, a_16, 2))) return 0; + if (!find_among_b(z, a_16, 2)) return 0; return 1; } @@ -839,7 +849,7 @@ static int r_mark_nUz(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || z->p[z->c - 1] != 122) return 0; - if (!(find_among_b(z, a_17, 4))) return 0; + if (!find_among_b(z, a_17, 4)) return 0; return 1; } @@ -848,13 +858,13 @@ static int r_mark_DUr(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 2 <= z->lb || z->p[z->c - 1] != 114) return 0; - if (!(find_among_b(z, a_18, 8))) return 0; + if (!find_among_b(z, a_18, 8)) return 0; return 1; } static int r_mark_cAsInA(struct SN_env * z) { if (z->c - 5 <= z->lb || (z->p[z->c - 1] != 97 && z->p[z->c - 1] != 101)) return 0; - if (!(find_among_b(z, a_19, 2))) return 0; + if (!find_among_b(z, a_19, 2)) return 0; return 1; } @@ -862,7 +872,7 @@ static int r_mark_yDU(struct SN_env * z) { { int ret = r_check_vowel_harmony(z); if (ret <= 0) return ret; } - if (!(find_among_b(z, a_20, 32))) return 0; + if (!find_among_b(z, a_20, 32)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -871,7 +881,7 @@ static int r_mark_yDU(struct SN_env * z) { static int r_mark_ysA(struct SN_env * z) { if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 3 || !((26658 >> (z->p[z->c - 1] & 0x1f)) & 1)) return 0; - if (!(find_among_b(z, a_21, 8))) return 0; + if (!find_among_b(z, a_21, 8)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -883,7 +893,7 @@ static int r_mark_ymUs_(struct SN_env * z) { if (ret <= 0) return ret; } if (z->c - 3 <= z->lb || z->p[z->c - 1] != 159) return 0; - if (!(find_among_b(z, a_22, 4))) return 0; + if (!find_among_b(z, a_22, 4)) return 0; { int ret = r_mark_suffix_with_optional_y_consonant(z); if (ret <= 0) return ret; } @@ -1865,7 +1875,7 @@ static int r_post_process_last_consonants(struct SN_env * z) { int among_var; z->ket = z->c; among_var = find_among_b(z, a_23, 4); - if (!(among_var)) return 0; + if (!among_var) return 0; z->bra = z->c; switch (among_var) { case 1: @@ -1893,108 +1903,77 @@ static int r_post_process_last_consonants(struct SN_env * z) { } static int r_append_U_to_stems_ending_with_d_or_g(struct SN_env * z) { - { int m_test1 = z->l - z->c; - { int m2 = z->l - z->c; (void)m2; - if (z->c <= z->lb || z->p[z->c - 1] != 'd') goto lab1; - z->c--; - goto lab0; - lab1: - z->c = z->l - m2; - if (z->c <= z->lb || z->p[z->c - 1] != 'g') return 0; - z->c--; - } - lab0: - z->c = z->l - m_test1; + z->ket = z->c; + z->bra = z->c; + { int m1 = z->l - z->c; (void)m1; + if (z->c <= z->lb || z->p[z->c - 1] != 'd') goto lab1; + z->c--; + goto lab0; + lab1: + z->c = z->l - m1; + if (z->c <= z->lb || z->p[z->c - 1] != 'g') return 0; + z->c--; } - { int m3 = z->l - z->c; (void)m3; - { int m_test4 = z->l - z->c; - if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) goto lab3; - { int m5 = z->l - z->c; (void)m5; - if (z->c <= z->lb || z->p[z->c - 1] != 'a') goto lab5; - z->c--; - goto lab4; - lab5: - z->c = z->l - m5; - if (!(eq_s_b(z, 2, s_9))) goto lab3; - } - lab4: - z->c = z->l - m_test4; +lab0: + + if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) return 0; + { int m2 = z->l - z->c; (void)m2; + { int m3 = z->l - z->c; (void)m3; + if (z->c <= z->lb || z->p[z->c - 1] != 'a') goto lab5; + z->c--; + goto lab4; + lab5: + z->c = z->l - m3; + if (!(eq_s_b(z, 2, s_9))) goto lab3; } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 2, s_10); - z->c = saved_c; - } + lab4: + { int ret = slice_from_s(z, 2, s_10); if (ret < 0) return ret; } goto lab2; lab3: - z->c = z->l - m3; - { int m_test6 = z->l - z->c; - if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) goto lab6; - { int m7 = z->l - z->c; (void)m7; - if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab8; - z->c--; - goto lab7; - lab8: - z->c = z->l - m7; - if (z->c <= z->lb || z->p[z->c - 1] != 'i') goto lab6; - z->c--; - } - lab7: - z->c = z->l - m_test6; + z->c = z->l - m2; + { int m4 = z->l - z->c; (void)m4; + if (z->c <= z->lb || z->p[z->c - 1] != 'e') goto lab8; + z->c--; + goto lab7; + lab8: + z->c = z->l - m4; + if (z->c <= z->lb || z->p[z->c - 1] != 'i') goto lab6; + z->c--; } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_11); - z->c = saved_c; - } + lab7: + { int ret = slice_from_s(z, 1, s_11); if (ret < 0) return ret; } goto lab2; lab6: - z->c = z->l - m3; - { int m_test8 = z->l - z->c; - if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) goto lab9; - { int m9 = z->l - z->c; (void)m9; - if (z->c <= z->lb || z->p[z->c - 1] != 'o') goto lab11; - z->c--; - goto lab10; - lab11: - z->c = z->l - m9; - if (z->c <= z->lb || z->p[z->c - 1] != 'u') goto lab9; - z->c--; - } - lab10: - z->c = z->l - m_test8; + z->c = z->l - m2; + { int m5 = z->l - z->c; (void)m5; + if (z->c <= z->lb || z->p[z->c - 1] != 'o') goto lab11; + z->c--; + goto lab10; + lab11: + z->c = z->l - m5; + if (z->c <= z->lb || z->p[z->c - 1] != 'u') goto lab9; + z->c--; } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 1, s_12); - z->c = saved_c; - } + lab10: + { int ret = slice_from_s(z, 1, s_12); if (ret < 0) return ret; } goto lab2; lab9: - z->c = z->l - m3; - { int m_test10 = z->l - z->c; - if (out_grouping_b_U(z, g_vowel, 97, 305, 1) < 0) return 0; - { int m11 = z->l - z->c; (void)m11; - if (!(eq_s_b(z, 2, s_13))) goto lab13; - goto lab12; - lab13: - z->c = z->l - m11; - if (!(eq_s_b(z, 2, s_14))) return 0; - } - lab12: - z->c = z->l - m_test10; + z->c = z->l - m2; + { int m6 = z->l - z->c; (void)m6; + if (!(eq_s_b(z, 2, s_13))) goto lab13; + goto lab12; + lab13: + z->c = z->l - m6; + if (!(eq_s_b(z, 2, s_14))) return 0; } - { int ret; - { int saved_c = z->c; - ret = insert_s(z, z->c, z->c, 2, s_15); - z->c = saved_c; - } + lab12: + { int ret = slice_from_s(z, 2, s_15); if (ret < 0) return ret; } } @@ -2013,23 +1992,43 @@ static int r_is_reserved_word(struct SN_env * z) { return 1; } +static int r_remove_proper_noun_suffix(struct SN_env * z) { + { int c1 = z->c; + while(1) { + int c2 = z->c; + if (z->c == z->l || z->p[z->c] != '\'') goto lab1; + z->c++; + z->c = c2; + break; + lab1: + z->c = c2; + { int ret = skip_utf8(z->p, z->c, z->l, 1); + if (ret < 0) goto lab0; + z->c = ret; + } + } + z->bra = z->c; + z->c = z->l; + z->ket = z->c; + { int ret = slice_del(z); + if (ret < 0) return ret; + } + lab0: + z->c = c1; + } + return 1; +} + static int r_more_than_one_syllable_word(struct SN_env * z) { { int c_test1 = z->c; - { int i = 2; - while(1) { - int c2 = z->c; - { + { int i; for (i = 2; i > 0; i--) + { + { int ret = out_grouping_U(z, g_vowel, 97, 305, 1); - if (ret < 0) goto lab0; + if (ret < 0) return 0; z->c += ret; } - i--; - continue; - lab0: - z->c = c2; - break; } - if (i > 0) return 0; } z->c = c_test1; } @@ -2065,6 +2064,10 @@ static int r_postlude(struct SN_env * z) { } extern int turkish_UTF_8_stem(struct SN_env * z) { + + { int ret = r_remove_proper_noun_suffix(z); + if (ret < 0) return ret; + } { int ret = r_more_than_one_syllable_word(z); if (ret <= 0) return ret; } diff --git a/src/backend/snowball/libstemmer/stem_UTF_8_yiddish.c b/src/backend/snowball/libstemmer/stem_UTF_8_yiddish.c index f169e056072ed..d98347407d606 100644 --- a/src/backend/snowball/libstemmer/stem_UTF_8_yiddish.c +++ b/src/backend/snowball/libstemmer/stem_UTF_8_yiddish.c @@ -508,7 +508,7 @@ static int r_prelude(struct SN_env * z) { int c3 = z->c; z->bra = z->c; among_var = find_among(z, a_0, 8); - if (!(among_var)) goto lab2; + if (!among_var) goto lab2; z->ket = z->c; switch (among_var) { case 1: @@ -628,7 +628,11 @@ static int r_mark_regions(struct SN_env * z) { goto lab2; lab3: z->c = c3; - if (!(eq_s(z, 4, s_13))) goto lab1; + if (!(eq_s(z, 4, s_13))) goto lab4; + goto lab2; + lab4: + z->c = c3; + if (z->c < z->l) goto lab1; } lab2: { z->c = c1; goto lab0; } @@ -642,52 +646,52 @@ static int r_mark_regions(struct SN_env * z) { ; } { int c4 = z->c; - if (!(find_among(z, a_1, 40))) { z->c = c4; goto lab4; } + if (!find_among(z, a_1, 40)) { z->c = c4; goto lab5; } { int c5 = z->c; { int c_test6 = z->c; { int c7 = z->c; - if (!(eq_s(z, 8, s_15))) goto lab8; - goto lab7; - lab8: - z->c = c7; - if (!(eq_s(z, 8, s_16))) goto lab9; - goto lab7; + if (!(eq_s(z, 8, s_15))) goto lab9; + goto lab8; lab9: z->c = c7; - if (!(eq_s(z, 8, s_17))) goto lab6; + if (!(eq_s(z, 8, s_16))) goto lab10; + goto lab8; + lab10: + z->c = c7; + if (!(eq_s(z, 8, s_17))) goto lab7; } - lab7: - if (z->c < z->l) goto lab6; + lab8: + if (z->c < z->l) goto lab7; z->c = c_test6; } - goto lab5; - lab6: + goto lab6; + lab7: z->c = c5; { int c_test8 = z->c; - if (!(eq_s(z, 8, s_18))) goto lab10; + if (!(eq_s(z, 8, s_18))) goto lab11; z->c = c_test8; } - goto lab5; - lab10: + goto lab6; + lab11: z->c = c5; z->bra = z->c; - if (!(eq_s(z, 4, s_19))) goto lab11; + if (!(eq_s(z, 4, s_19))) goto lab12; z->ket = z->c; { int ret = slice_from_s(z, 2, s_20); if (ret < 0) return ret; } - goto lab5; - lab11: + goto lab6; + lab12: z->c = c5; z->bra = z->c; - if (!(eq_s(z, 4, s_21))) { z->c = c4; goto lab4; } + if (!(eq_s(z, 4, s_21))) { z->c = c4; goto lab5; } z->ket = z->c; { int ret = slice_from_s(z, 3, s_22); if (ret < 0) return ret; } } + lab6: lab5: - lab4: ; } { int c_test9 = z->c; @@ -699,43 +703,42 @@ static int r_mark_regions(struct SN_env * z) { z->c = c_test9; } { int c10 = z->c; - if (z->c + 5 >= z->l || (z->p[z->c + 5] != 169 && z->p[z->c + 5] != 168)) { z->c = c10; goto lab12; } - if (!(find_among(z, a_2, 4))) { z->c = c10; goto lab12; } - lab12: + if (z->c + 5 >= z->l || (z->p[z->c + 5] != 169 && z->p[z->c + 5] != 168)) { z->c = c10; goto lab13; } + if (!find_among(z, a_2, 4)) { z->c = c10; goto lab13; } + lab13: ; } { int c11 = z->c; - if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab13; - if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab13; - if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab13; + if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab14; + if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab14; + if (in_grouping_U(z, g_consonant, 1489, 1520, 0)) goto lab14; z->I[1] = z->c; return 0; - lab13: + lab14: z->c = c11; } + if (out_grouping_U(z, g_vowel, 1488, 1522, 1) < 0) return 0; while(1) { - if (in_grouping_U(z, g_vowel, 1488, 1522, 0)) goto lab14; + if (in_grouping_U(z, g_vowel, 1488, 1522, 0)) goto lab15; continue; - lab14: + lab15: break; } z->I[1] = z->c; - - if (!(z->I[1] < z->I[0])) goto lab15; + + if (z->I[1] >= z->I[0]) goto lab16; z->I[1] = z->I[0]; -lab15: +lab16: return 1; } static int r_R1(struct SN_env * z) { - if (!(z->I[1] <= z->c)) return 0; - return 1; + return z->I[1] <= z->c; } static int r_R1plus3(struct SN_env * z) { - if (!(z->I[1] <= (z->c + 6))) return 0; - return 1; + return z->I[1] <= (z->c + 6); } static int r_standard_suffix(struct SN_env * z) { @@ -743,7 +746,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m1 = z->l - z->c; (void)m1; z->ket = z->c; among_var = find_among_b(z, a_4, 79); - if (!(among_var)) goto lab0; + if (!among_var) goto lab0; z->bra = z->c; switch (among_var) { case 1: @@ -774,7 +777,7 @@ static int r_standard_suffix(struct SN_env * z) { } z->ket = z->c; among_var = find_among_b(z, a_3, 26); - if (!(among_var)) goto lab0; + if (!among_var) goto lab0; z->bra = z->c; switch (among_var) { case 1: @@ -1124,7 +1127,7 @@ static int r_standard_suffix(struct SN_env * z) { z->ket = z->c; if (z->c - 1 <= z->lb || z->p[z->c - 1] >> 5 != 4 || !((285474816 >> (z->p[z->c - 1] & 0x1f)) & 1)) goto lab9; among_var = find_among_b(z, a_5, 6); - if (!(among_var)) goto lab9; + if (!among_var) goto lab9; z->bra = z->c; switch (among_var) { case 1: @@ -1153,7 +1156,7 @@ static int r_standard_suffix(struct SN_env * z) { { int m8 = z->l - z->c; (void)m8; z->ket = z->c; among_var = find_among_b(z, a_6, 9); - if (!(among_var)) goto lab10; + if (!among_var) goto lab10; z->bra = z->c; switch (among_var) { case 1: @@ -1207,7 +1210,7 @@ static int r_standard_suffix(struct SN_env * z) { } extern int yiddish_UTF_8_stem(struct SN_env * z) { - + { int ret = r_prelude(z); if (ret < 0) return ret; } @@ -1219,7 +1222,7 @@ extern int yiddish_UTF_8_stem(struct SN_env * z) { } z->lb = z->c; z->c = z->l; - + { int ret = r_standard_suffix(z); if (ret < 0) return ret; } diff --git a/src/backend/snowball/libstemmer/utilities.c b/src/backend/snowball/libstemmer/utilities.c index 1ecd2410fe7e6..8acc18541d5a8 100644 --- a/src/backend/snowball/libstemmer/utilities.c +++ b/src/backend/snowball/libstemmer/utilities.c @@ -281,7 +281,7 @@ extern int find_among(struct SN_env * z, const struct among * v, int v_size) { w = v + i; if (common_i >= w->s_size) { z->c = c + w->s_size; - if (w->function == 0) return w->result; + if (w->function == NULL) return w->result; { int res = w->function(z); z->c = c + w->s_size; @@ -336,7 +336,7 @@ extern int find_among_b(struct SN_env * z, const struct among * v, int v_size) { w = v + i; if (common_i >= w->s_size) { z->c = c - w->s_size; - if (w->function == 0) return w->result; + if (w->function == NULL) return w->result; { int res = w->function(z); z->c = c - w->s_size; @@ -429,7 +429,7 @@ extern int slice_from_v(struct SN_env * z, const symbol * p) { } extern int slice_del(struct SN_env * z) { - return slice_from_s(z, 0, 0); + return slice_from_s(z, 0, NULL); } extern int insert_s(struct SN_env * z, int bra, int ket, int s_size, const symbol * s) { diff --git a/src/backend/snowball/meson.build b/src/backend/snowball/meson.build index 02a94557e2885..8e73d9d736823 100644 --- a/src/backend/snowball/meson.build +++ b/src/backend/snowball/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dict_snowball_sources = files( 'libstemmer/api.c', @@ -24,7 +24,6 @@ dict_snowball_sources += files( 'libstemmer/stem_ISO_8859_1_spanish.c', 'libstemmer/stem_ISO_8859_1_swedish.c', 'libstemmer/stem_ISO_8859_2_hungarian.c', - 'libstemmer/stem_ISO_8859_2_romanian.c', 'libstemmer/stem_KOI8_R_russian.c', 'libstemmer/stem_UTF_8_arabic.c', 'libstemmer/stem_UTF_8_armenian.c', @@ -33,6 +32,7 @@ dict_snowball_sources += files( 'libstemmer/stem_UTF_8_danish.c', 'libstemmer/stem_UTF_8_dutch.c', 'libstemmer/stem_UTF_8_english.c', + 'libstemmer/stem_UTF_8_estonian.c', 'libstemmer/stem_UTF_8_finnish.c', 'libstemmer/stem_UTF_8_french.c', 'libstemmer/stem_UTF_8_german.c', diff --git a/src/backend/snowball/snowball.sql.in b/src/backend/snowball/snowball.sql.in index bc07a7cee6172..c0692a7750840 100644 --- a/src/backend/snowball/snowball.sql.in +++ b/src/backend/snowball/snowball.sql.in @@ -1,7 +1,7 @@ /* * text search configuration for _LANGNAME_ language * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/backend/snowball/snowball.sql.in * diff --git a/src/backend/snowball/snowball_create.pl b/src/backend/snowball/snowball_create.pl index 95b38650db975..dffa8feb76900 100644 --- a/src/backend/snowball/snowball_create.pl +++ b/src/backend/snowball/snowball_create.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -19,6 +19,7 @@ danish dutch english + estonian finnish french german diff --git a/src/backend/snowball/snowball_func.sql.in b/src/backend/snowball/snowball_func.sql.in index de480ab9f91e6..4e94f46bf1812 100644 --- a/src/backend/snowball/snowball_func.sql.in +++ b/src/backend/snowball/snowball_func.sql.in @@ -1,7 +1,7 @@ /* * Create underlying C functions for Snowball stemmers * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/backend/snowball/snowball_func.sql.in * diff --git a/src/backend/statistics/Makefile b/src/backend/statistics/Makefile index 89cf8c27973db..4672bd90f225b 100644 --- a/src/backend/statistics/Makefile +++ b/src/backend/statistics/Makefile @@ -13,9 +13,12 @@ top_builddir = ../../.. include $(top_builddir)/src/Makefile.global OBJS = \ + attribute_stats.o \ dependencies.o \ extended_stats.o \ mcv.o \ - mvdistinct.o + mvdistinct.o \ + relation_stats.o \ + stat_utils.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c new file mode 100644 index 0000000000000..ab198076401b0 --- /dev/null +++ b/src/backend/statistics/attribute_stats.c @@ -0,0 +1,1000 @@ +/*------------------------------------------------------------------------- + * attribute_stats.c + * + * PostgreSQL relation attribute statistics manipulation. + * + * Code supporting the direct import of relation attribute statistics, similar + * to what is done by the ANALYZE command. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/statistics/attribute_stats.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "catalog/indexing.h" +#include "catalog/pg_collation.h" +#include "catalog/pg_operator.h" +#include "nodes/nodeFuncs.h" +#include "statistics/statistics.h" +#include "statistics/stat_utils.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + +#define DEFAULT_NULL_FRAC Float4GetDatum(0.0) +#define DEFAULT_AVG_WIDTH Int32GetDatum(0) /* unknown */ +#define DEFAULT_N_DISTINCT Float4GetDatum(0.0) /* unknown */ + +enum attribute_stats_argnum +{ + ATTRELSCHEMA_ARG = 0, + ATTRELNAME_ARG, + ATTNAME_ARG, + ATTNUM_ARG, + INHERITED_ARG, + NULL_FRAC_ARG, + AVG_WIDTH_ARG, + N_DISTINCT_ARG, + MOST_COMMON_VALS_ARG, + MOST_COMMON_FREQS_ARG, + HISTOGRAM_BOUNDS_ARG, + CORRELATION_ARG, + MOST_COMMON_ELEMS_ARG, + MOST_COMMON_ELEM_FREQS_ARG, + ELEM_COUNT_HISTOGRAM_ARG, + RANGE_LENGTH_HISTOGRAM_ARG, + RANGE_EMPTY_FRAC_ARG, + RANGE_BOUNDS_HISTOGRAM_ARG, + NUM_ATTRIBUTE_STATS_ARGS +}; + +static struct StatsArgInfo attarginfo[] = +{ + [ATTRELSCHEMA_ARG] = {"schemaname", TEXTOID}, + [ATTRELNAME_ARG] = {"relname", TEXTOID}, + [ATTNAME_ARG] = {"attname", TEXTOID}, + [ATTNUM_ARG] = {"attnum", INT2OID}, + [INHERITED_ARG] = {"inherited", BOOLOID}, + [NULL_FRAC_ARG] = {"null_frac", FLOAT4OID}, + [AVG_WIDTH_ARG] = {"avg_width", INT4OID}, + [N_DISTINCT_ARG] = {"n_distinct", FLOAT4OID}, + [MOST_COMMON_VALS_ARG] = {"most_common_vals", TEXTOID}, + [MOST_COMMON_FREQS_ARG] = {"most_common_freqs", FLOAT4ARRAYOID}, + [HISTOGRAM_BOUNDS_ARG] = {"histogram_bounds", TEXTOID}, + [CORRELATION_ARG] = {"correlation", FLOAT4OID}, + [MOST_COMMON_ELEMS_ARG] = {"most_common_elems", TEXTOID}, + [MOST_COMMON_ELEM_FREQS_ARG] = {"most_common_elem_freqs", FLOAT4ARRAYOID}, + [ELEM_COUNT_HISTOGRAM_ARG] = {"elem_count_histogram", FLOAT4ARRAYOID}, + [RANGE_LENGTH_HISTOGRAM_ARG] = {"range_length_histogram", TEXTOID}, + [RANGE_EMPTY_FRAC_ARG] = {"range_empty_frac", FLOAT4OID}, + [RANGE_BOUNDS_HISTOGRAM_ARG] = {"range_bounds_histogram", TEXTOID}, + [NUM_ATTRIBUTE_STATS_ARGS] = {0} +}; + +enum clear_attribute_stats_argnum +{ + C_ATTRELSCHEMA_ARG = 0, + C_ATTRELNAME_ARG, + C_ATTNAME_ARG, + C_INHERITED_ARG, + C_NUM_ATTRIBUTE_STATS_ARGS +}; + +static struct StatsArgInfo cleararginfo[] = +{ + [C_ATTRELSCHEMA_ARG] = {"relation", TEXTOID}, + [C_ATTRELNAME_ARG] = {"relation", TEXTOID}, + [C_ATTNAME_ARG] = {"attname", TEXTOID}, + [C_INHERITED_ARG] = {"inherited", BOOLOID}, + [C_NUM_ATTRIBUTE_STATS_ARGS] = {0} +}; + +static bool attribute_statistics_update(FunctionCallInfo fcinfo); +static Node *get_attr_expr(Relation rel, int attnum); +static void get_attr_stat_type(Oid reloid, AttrNumber attnum, + Oid *atttypid, int32 *atttypmod, + char *atttyptype, Oid *atttypcoll, + Oid *eq_opr, Oid *lt_opr); +static bool get_elem_stat_type(Oid atttypid, char atttyptype, + Oid *elemtypid, Oid *elem_eq_opr); +static Datum text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, + Oid typid, int32 typmod, bool *ok); +static void set_stats_slot(Datum *values, bool *nulls, bool *replaces, + int16 stakind, Oid staop, Oid stacoll, + Datum stanumbers, bool stanumbers_isnull, + Datum stavalues, bool stavalues_isnull); +static void upsert_pg_statistic(Relation starel, HeapTuple oldtup, + Datum *values, bool *nulls, bool *replaces); +static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit); +static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, + Datum *values, bool *nulls, bool *replaces); + +/* + * Insert or Update Attribute Statistics + * + * See pg_statistic.h for an explanation of how each statistic kind is + * stored. Custom statistics kinds are not supported. + * + * Depending on the statistics kind, we need to derive information from the + * attribute for which we're storing the stats. For instance, the MCVs are + * stored as an anyarray, and the representation of the array needs to store + * the correct element type, which must be derived from the attribute. + * + * Major errors, such as the table not existing, the attribute not existing, + * or a permissions failure are always reported at ERROR. Other errors, such + * as a conversion failure on one statistic kind, are reported as a WARNING + * and other statistic kinds may still be updated. + */ +static bool +attribute_statistics_update(FunctionCallInfo fcinfo) +{ + char *nspname; + char *relname; + Oid reloid; + char *attname; + AttrNumber attnum; + bool inherited; + + Relation starel; + HeapTuple statup; + + Oid atttypid = InvalidOid; + int32 atttypmod; + char atttyptype; + Oid atttypcoll = InvalidOid; + Oid eq_opr = InvalidOid; + Oid lt_opr = InvalidOid; + + Oid elemtypid = InvalidOid; + Oid elem_eq_opr = InvalidOid; + + FmgrInfo array_in_fn; + + bool do_mcv = !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) && + !PG_ARGISNULL(MOST_COMMON_VALS_ARG); + bool do_histogram = !PG_ARGISNULL(HISTOGRAM_BOUNDS_ARG); + bool do_correlation = !PG_ARGISNULL(CORRELATION_ARG); + bool do_mcelem = !PG_ARGISNULL(MOST_COMMON_ELEMS_ARG) && + !PG_ARGISNULL(MOST_COMMON_ELEM_FREQS_ARG); + bool do_dechist = !PG_ARGISNULL(ELEM_COUNT_HISTOGRAM_ARG); + bool do_bounds_histogram = !PG_ARGISNULL(RANGE_BOUNDS_HISTOGRAM_ARG); + bool do_range_length_histogram = !PG_ARGISNULL(RANGE_LENGTH_HISTOGRAM_ARG) && + !PG_ARGISNULL(RANGE_EMPTY_FRAC_ARG); + + Datum values[Natts_pg_statistic] = {0}; + bool nulls[Natts_pg_statistic] = {0}; + bool replaces[Natts_pg_statistic] = {0}; + + bool result = true; + + stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG); + stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG); + + nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELSCHEMA_ARG)); + relname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELNAME_ARG)); + + reloid = stats_lookup_relid(nspname, relname); + + if (RecoveryInProgress()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is in progress"), + errhint("Statistics cannot be modified during recovery."))); + + /* lock before looking up attribute */ + stats_lock_check_privileges(reloid); + + /* user can specify either attname or attnum, but not both */ + if (!PG_ARGISNULL(ATTNAME_ARG)) + { + if (!PG_ARGISNULL(ATTNUM_ARG)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot specify both attname and attnum"))); + attname = TextDatumGetCString(PG_GETARG_DATUM(ATTNAME_ARG)); + attnum = get_attnum(reloid, attname); + /* note that this test covers attisdropped cases too: */ + if (attnum == InvalidAttrNumber) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + attname, relname))); + } + else if (!PG_ARGISNULL(ATTNUM_ARG)) + { + attnum = PG_GETARG_INT16(ATTNUM_ARG); + attname = get_attname(reloid, attnum, true); + /* annoyingly, get_attname doesn't check attisdropped */ + if (attname == NULL || + !SearchSysCacheExistsAttName(reloid, attname)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column %d of relation \"%s\" does not exist", + attnum, relname))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("must specify either attname or attnum"))); + attname = NULL; /* keep compiler quiet */ + attnum = 0; + } + + if (attnum < 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot modify statistics on system column \"%s\"", + attname))); + + stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG); + inherited = PG_GETARG_BOOL(INHERITED_ARG); + + /* + * Check argument sanity. If some arguments are unusable, emit a WARNING + * and set the corresponding argument to NULL in fcinfo. + */ + + if (!stats_check_arg_array(fcinfo, attarginfo, MOST_COMMON_FREQS_ARG)) + { + do_mcv = false; + result = false; + } + + if (!stats_check_arg_array(fcinfo, attarginfo, MOST_COMMON_ELEM_FREQS_ARG)) + { + do_mcelem = false; + result = false; + } + if (!stats_check_arg_array(fcinfo, attarginfo, ELEM_COUNT_HISTOGRAM_ARG)) + { + do_dechist = false; + result = false; + } + + if (!stats_check_arg_pair(fcinfo, attarginfo, + MOST_COMMON_VALS_ARG, MOST_COMMON_FREQS_ARG)) + { + do_mcv = false; + result = false; + } + + if (!stats_check_arg_pair(fcinfo, attarginfo, + MOST_COMMON_ELEMS_ARG, + MOST_COMMON_ELEM_FREQS_ARG)) + { + do_mcelem = false; + result = false; + } + + if (!stats_check_arg_pair(fcinfo, attarginfo, + RANGE_LENGTH_HISTOGRAM_ARG, + RANGE_EMPTY_FRAC_ARG)) + { + do_range_length_histogram = false; + result = false; + } + + /* derive information from attribute */ + get_attr_stat_type(reloid, attnum, + &atttypid, &atttypmod, + &atttyptype, &atttypcoll, + &eq_opr, <_opr); + + /* if needed, derive element type */ + if (do_mcelem || do_dechist) + { + if (!get_elem_stat_type(atttypid, atttyptype, + &elemtypid, &elem_eq_opr)) + { + ereport(WARNING, + (errmsg("unable to determine element type of attribute \"%s\"", attname), + errdetail("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST."))); + elemtypid = InvalidOid; + elem_eq_opr = InvalidOid; + + do_mcelem = false; + do_dechist = false; + result = false; + } + } + + /* histogram and correlation require less-than operator */ + if ((do_histogram || do_correlation) && !OidIsValid(lt_opr)) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine less-than operator for attribute \"%s\"", attname), + errdetail("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION."))); + + do_histogram = false; + do_correlation = false; + result = false; + } + + /* only range types can have range stats */ + if ((do_range_length_histogram || do_bounds_histogram) && + !(atttyptype == TYPTYPE_RANGE || atttyptype == TYPTYPE_MULTIRANGE)) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("attribute \"%s\" is not a range type", attname), + errdetail("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM."))); + + do_bounds_histogram = false; + do_range_length_histogram = false; + result = false; + } + + fmgr_info(F_ARRAY_IN, &array_in_fn); + + starel = table_open(StatisticRelationId, RowExclusiveLock); + + statup = SearchSysCache3(STATRELATTINH, reloid, attnum, inherited); + + /* initialize from existing tuple if exists */ + if (HeapTupleIsValid(statup)) + heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls); + else + init_empty_stats_tuple(reloid, attnum, inherited, values, nulls, + replaces); + + /* if specified, set to argument values */ + if (!PG_ARGISNULL(NULL_FRAC_ARG)) + { + values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG); + replaces[Anum_pg_statistic_stanullfrac - 1] = true; + } + if (!PG_ARGISNULL(AVG_WIDTH_ARG)) + { + values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG); + replaces[Anum_pg_statistic_stawidth - 1] = true; + } + if (!PG_ARGISNULL(N_DISTINCT_ARG)) + { + values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG); + replaces[Anum_pg_statistic_stadistinct - 1] = true; + } + + /* STATISTIC_KIND_MCV */ + if (do_mcv) + { + bool converted; + Datum stanumbers = PG_GETARG_DATUM(MOST_COMMON_FREQS_ARG); + Datum stavalues = text_to_stavalues("most_common_vals", + &array_in_fn, + PG_GETARG_DATUM(MOST_COMMON_VALS_ARG), + atttypid, atttypmod, + &converted); + + if (converted) + { + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_MCV, + eq_opr, atttypcoll, + stanumbers, false, stavalues, false); + } + else + result = false; + } + + /* STATISTIC_KIND_HISTOGRAM */ + if (do_histogram) + { + Datum stavalues; + bool converted = false; + + stavalues = text_to_stavalues("histogram_bounds", + &array_in_fn, + PG_GETARG_DATUM(HISTOGRAM_BOUNDS_ARG), + atttypid, atttypmod, + &converted); + + if (converted) + { + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_HISTOGRAM, + lt_opr, atttypcoll, + 0, true, stavalues, false); + } + else + result = false; + } + + /* STATISTIC_KIND_CORRELATION */ + if (do_correlation) + { + Datum elems[] = {PG_GETARG_DATUM(CORRELATION_ARG)}; + ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID); + Datum stanumbers = PointerGetDatum(arry); + + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_CORRELATION, + lt_opr, atttypcoll, + stanumbers, false, 0, true); + } + + /* STATISTIC_KIND_MCELEM */ + if (do_mcelem) + { + Datum stanumbers = PG_GETARG_DATUM(MOST_COMMON_ELEM_FREQS_ARG); + bool converted = false; + Datum stavalues; + + stavalues = text_to_stavalues("most_common_elems", + &array_in_fn, + PG_GETARG_DATUM(MOST_COMMON_ELEMS_ARG), + elemtypid, atttypmod, + &converted); + + if (converted) + { + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_MCELEM, + elem_eq_opr, atttypcoll, + stanumbers, false, stavalues, false); + } + else + result = false; + } + + /* STATISTIC_KIND_DECHIST */ + if (do_dechist) + { + Datum stanumbers = PG_GETARG_DATUM(ELEM_COUNT_HISTOGRAM_ARG); + + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_DECHIST, + elem_eq_opr, atttypcoll, + stanumbers, false, 0, true); + } + + /* + * STATISTIC_KIND_BOUNDS_HISTOGRAM + * + * This stakind appears before STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM even + * though it is numerically greater, and all other stakinds appear in + * numerical order. We duplicate this quirk for consistency. + */ + if (do_bounds_histogram) + { + bool converted = false; + Datum stavalues; + + stavalues = text_to_stavalues("range_bounds_histogram", + &array_in_fn, + PG_GETARG_DATUM(RANGE_BOUNDS_HISTOGRAM_ARG), + atttypid, atttypmod, + &converted); + + if (converted) + { + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_BOUNDS_HISTOGRAM, + InvalidOid, InvalidOid, + 0, true, stavalues, false); + } + else + result = false; + } + + /* STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM */ + if (do_range_length_histogram) + { + /* The anyarray is always a float8[] for this stakind */ + Datum elems[] = {PG_GETARG_DATUM(RANGE_EMPTY_FRAC_ARG)}; + ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID); + Datum stanumbers = PointerGetDatum(arry); + + bool converted = false; + Datum stavalues; + + stavalues = text_to_stavalues("range_length_histogram", + &array_in_fn, + PG_GETARG_DATUM(RANGE_LENGTH_HISTOGRAM_ARG), + FLOAT8OID, 0, &converted); + + if (converted) + { + set_stats_slot(values, nulls, replaces, + STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM, + Float8LessOperator, InvalidOid, + stanumbers, false, stavalues, false); + } + else + result = false; + } + + upsert_pg_statistic(starel, statup, values, nulls, replaces); + + if (HeapTupleIsValid(statup)) + ReleaseSysCache(statup); + table_close(starel, RowExclusiveLock); + + return result; +} + +/* + * If this relation is an index and that index has expressions in it, and + * the attnum specified is known to be an expression, then we must walk + * the list attributes up to the specified attnum to get the right + * expression. + */ +static Node * +get_attr_expr(Relation rel, int attnum) +{ + List *index_exprs; + ListCell *indexpr_item; + + /* relation is not an index */ + if (rel->rd_rel->relkind != RELKIND_INDEX && + rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX) + return NULL; + + index_exprs = RelationGetIndexExpressions(rel); + + /* index has no expressions to give */ + if (index_exprs == NIL) + return NULL; + + /* + * The index attnum points directly to a relation attnum, then it's not an + * expression attribute. + */ + if (rel->rd_index->indkey.values[attnum - 1] != 0) + return NULL; + + indexpr_item = list_head(rel->rd_indexprs); + + for (int i = 0; i < attnum - 1; i++) + if (rel->rd_index->indkey.values[i] == 0) + indexpr_item = lnext(rel->rd_indexprs, indexpr_item); + + if (indexpr_item == NULL) /* shouldn't happen */ + elog(ERROR, "too few entries in indexprs list"); + + return (Node *) lfirst(indexpr_item); +} + +/* + * Derive type information from the attribute. + */ +static void +get_attr_stat_type(Oid reloid, AttrNumber attnum, + Oid *atttypid, int32 *atttypmod, + char *atttyptype, Oid *atttypcoll, + Oid *eq_opr, Oid *lt_opr) +{ + Relation rel = relation_open(reloid, AccessShareLock); + Form_pg_attribute attr; + HeapTuple atup; + Node *expr; + TypeCacheEntry *typcache; + + atup = SearchSysCache2(ATTNUM, ObjectIdGetDatum(reloid), + Int16GetDatum(attnum)); + + /* Attribute not found */ + if (!HeapTupleIsValid(atup)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("attribute %d of relation \"%s\" does not exist", + attnum, RelationGetRelationName(rel)))); + + attr = (Form_pg_attribute) GETSTRUCT(atup); + + if (attr->attisdropped) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("attribute %d of relation \"%s\" does not exist", + attnum, RelationGetRelationName(rel)))); + + expr = get_attr_expr(rel, attr->attnum); + + /* + * When analyzing an expression index, believe the expression tree's type + * not the column datatype --- the latter might be the opckeytype storage + * type of the opclass, which is not interesting for our purposes. This + * mimics the behavior of examine_attribute(). + */ + if (expr == NULL) + { + *atttypid = attr->atttypid; + *atttypmod = attr->atttypmod; + *atttypcoll = attr->attcollation; + } + else + { + *atttypid = exprType(expr); + *atttypmod = exprTypmod(expr); + + if (OidIsValid(attr->attcollation)) + *atttypcoll = attr->attcollation; + else + *atttypcoll = exprCollation(expr); + } + ReleaseSysCache(atup); + + /* + * If it's a multirange, step down to the range type, as is done by + * multirange_typanalyze(). + */ + if (type_is_multirange(*atttypid)) + *atttypid = get_multirange_range(*atttypid); + + /* finds the right operators even if atttypid is a domain */ + typcache = lookup_type_cache(*atttypid, TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR); + *atttyptype = typcache->typtype; + *eq_opr = typcache->eq_opr; + *lt_opr = typcache->lt_opr; + + /* + * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See + * compute_tsvector_stats(). + */ + if (*atttypid == TSVECTOROID) + *atttypcoll = DEFAULT_COLLATION_OID; + + relation_close(rel, NoLock); +} + +/* + * Derive element type information from the attribute type. + */ +static bool +get_elem_stat_type(Oid atttypid, char atttyptype, + Oid *elemtypid, Oid *elem_eq_opr) +{ + TypeCacheEntry *elemtypcache; + + if (atttypid == TSVECTOROID) + { + /* + * Special case: element type for tsvector is text. See + * compute_tsvector_stats(). + */ + *elemtypid = TEXTOID; + } + else + { + /* find underlying element type through any domain */ + *elemtypid = get_base_element_type(atttypid); + } + + if (!OidIsValid(*elemtypid)) + return false; + + /* finds the right operator even if elemtypid is a domain */ + elemtypcache = lookup_type_cache(*elemtypid, TYPECACHE_EQ_OPR); + if (!OidIsValid(elemtypcache->eq_opr)) + return false; + + *elem_eq_opr = elemtypcache->eq_opr; + + return true; +} + +/* + * Cast a text datum into an array with element type elemtypid. + * + * If an error is encountered, capture it and re-throw a WARNING, and set ok + * to false. If the resulting array contains NULLs, raise a WARNING and set ok + * to false. Otherwise, set ok to true. + */ +static Datum +text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid, + int32 typmod, bool *ok) +{ + LOCAL_FCINFO(fcinfo, 8); + char *s; + Datum result; + ErrorSaveContext escontext = {T_ErrorSaveContext}; + + escontext.details_wanted = true; + + s = TextDatumGetCString(d); + + InitFunctionCallInfoData(*fcinfo, array_in, 3, InvalidOid, + (Node *) &escontext, NULL); + + fcinfo->args[0].value = CStringGetDatum(s); + fcinfo->args[0].isnull = false; + fcinfo->args[1].value = ObjectIdGetDatum(typid); + fcinfo->args[1].isnull = false; + fcinfo->args[2].value = Int32GetDatum(typmod); + fcinfo->args[2].isnull = false; + + result = FunctionCallInvoke(fcinfo); + + pfree(s); + + if (escontext.error_occurred) + { + escontext.error_data->elevel = WARNING; + ThrowErrorData(escontext.error_data); + *ok = false; + return (Datum) 0; + } + + if (array_contains_nulls(DatumGetArrayTypeP(result))) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" array cannot contain NULL values", staname))); + *ok = false; + return (Datum) 0; + } + + *ok = true; + + return result; +} + +/* + * Find and update the slot with the given stakind, or use the first empty + * slot. + */ +static void +set_stats_slot(Datum *values, bool *nulls, bool *replaces, + int16 stakind, Oid staop, Oid stacoll, + Datum stanumbers, bool stanumbers_isnull, + Datum stavalues, bool stavalues_isnull) +{ + int slotidx; + int first_empty = -1; + AttrNumber stakind_attnum; + AttrNumber staop_attnum; + AttrNumber stacoll_attnum; + + /* find existing slot with given stakind */ + for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++) + { + stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx; + + if (first_empty < 0 && + DatumGetInt16(values[stakind_attnum]) == 0) + first_empty = slotidx; + if (DatumGetInt16(values[stakind_attnum]) == stakind) + break; + } + + if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0) + slotidx = first_empty; + + if (slotidx >= STATISTIC_NUM_SLOTS) + ereport(ERROR, + (errmsg("maximum number of statistics slots exceeded: %d", + slotidx + 1))); + + stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx; + staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx; + stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx; + + if (DatumGetInt16(values[stakind_attnum]) != stakind) + { + values[stakind_attnum] = Int16GetDatum(stakind); + replaces[stakind_attnum] = true; + } + if (DatumGetObjectId(values[staop_attnum]) != staop) + { + values[staop_attnum] = ObjectIdGetDatum(staop); + replaces[staop_attnum] = true; + } + if (DatumGetObjectId(values[stacoll_attnum]) != stacoll) + { + values[stacoll_attnum] = ObjectIdGetDatum(stacoll); + replaces[stacoll_attnum] = true; + } + if (!stanumbers_isnull) + { + values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers; + nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false; + replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true; + } + if (!stavalues_isnull) + { + values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues; + nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false; + replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true; + } +} + +/* + * Upsert the pg_statistic record. + */ +static void +upsert_pg_statistic(Relation starel, HeapTuple oldtup, + Datum *values, bool *nulls, bool *replaces) +{ + HeapTuple newtup; + + if (HeapTupleIsValid(oldtup)) + { + newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel), + values, nulls, replaces); + CatalogTupleUpdate(starel, &newtup->t_self, newtup); + } + else + { + newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls); + CatalogTupleInsert(starel, newtup); + } + + heap_freetuple(newtup); + + CommandCounterIncrement(); +} + +/* + * Delete pg_statistic record. + */ +static bool +delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit) +{ + Relation sd = table_open(StatisticRelationId, RowExclusiveLock); + HeapTuple oldtup; + bool result = false; + + /* Is there already a pg_statistic tuple for this attribute? */ + oldtup = SearchSysCache3(STATRELATTINH, + ObjectIdGetDatum(reloid), + Int16GetDatum(attnum), + BoolGetDatum(stainherit)); + + if (HeapTupleIsValid(oldtup)) + { + CatalogTupleDelete(sd, &oldtup->t_self); + ReleaseSysCache(oldtup); + result = true; + } + + table_close(sd, RowExclusiveLock); + + CommandCounterIncrement(); + + return result; +} + +/* + * Initialize values and nulls for a new stats tuple. + */ +static void +init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, + Datum *values, bool *nulls, bool *replaces) +{ + memset(nulls, true, sizeof(bool) * Natts_pg_statistic); + memset(replaces, true, sizeof(bool) * Natts_pg_statistic); + + /* must initialize non-NULL attributes */ + + values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid); + nulls[Anum_pg_statistic_starelid - 1] = false; + values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum); + nulls[Anum_pg_statistic_staattnum - 1] = false; + values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited); + nulls[Anum_pg_statistic_stainherit - 1] = false; + + values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_NULL_FRAC; + nulls[Anum_pg_statistic_stanullfrac - 1] = false; + values[Anum_pg_statistic_stawidth - 1] = DEFAULT_AVG_WIDTH; + nulls[Anum_pg_statistic_stawidth - 1] = false; + values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_N_DISTINCT; + nulls[Anum_pg_statistic_stadistinct - 1] = false; + + /* initialize stakind, staop, and stacoll slots */ + for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++) + { + values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0; + nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false; + values[Anum_pg_statistic_staop1 + slotnum - 1] = InvalidOid; + nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false; + values[Anum_pg_statistic_stacoll1 + slotnum - 1] = InvalidOid; + nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false; + } +} + +/* + * Delete statistics for the given attribute. + */ +Datum +pg_clear_attribute_stats(PG_FUNCTION_ARGS) +{ + char *nspname; + char *relname; + Oid reloid; + char *attname; + AttrNumber attnum; + bool inherited; + + stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELSCHEMA_ARG); + stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELNAME_ARG); + stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG); + stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG); + + nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELSCHEMA_ARG)); + relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELNAME_ARG)); + + reloid = stats_lookup_relid(nspname, relname); + + if (RecoveryInProgress()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is in progress"), + errhint("Statistics cannot be modified during recovery."))); + + stats_lock_check_privileges(reloid); + + attname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTNAME_ARG)); + attnum = get_attnum(reloid, attname); + + if (attnum < 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot clear statistics on system column \"%s\"", + attname))); + + if (attnum == InvalidAttrNumber) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + attname, get_rel_name(reloid)))); + + inherited = PG_GETARG_BOOL(C_INHERITED_ARG); + + delete_pg_statistic(reloid, attnum, inherited); + PG_RETURN_VOID(); +} + +/* + * Import statistics for a given relation attribute. + * + * Inserts or replaces a row in pg_statistic for the given relation and + * attribute name or number. It takes input parameters that correspond to + * columns in the view pg_stats. + * + * Parameters are given in a pseudo named-attribute style: they must be + * pairs of parameter names (as text) and values (of appropriate types). + * We do that, rather than using regular named-parameter notation, so + * that we can add or change parameters without fear of breaking + * carelessly-written calls. + * + * Parameters null_frac, avg_width, and n_distinct all correspond to NOT NULL + * columns in pg_statistic. The remaining parameters all belong to a specific + * stakind. Some stakinds require multiple parameters, which must be specified + * together (or neither specified). + * + * Parameters are only superficially validated. Omitting a parameter or + * passing NULL leaves the statistic unchanged. + * + * Parameters corresponding to ANYARRAY columns are instead passed in as text + * values, which is a valid input string for an array of the type or element + * type of the attribute. Any error generated by the array_in() function will + * in turn fail the function. + */ +Datum +pg_restore_attribute_stats(PG_FUNCTION_ARGS) +{ + LOCAL_FCINFO(positional_fcinfo, NUM_ATTRIBUTE_STATS_ARGS); + bool result = true; + + InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_ATTRIBUTE_STATS_ARGS, + InvalidOid, NULL, NULL); + + if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, + attarginfo)) + result = false; + + if (!attribute_statistics_update(positional_fcinfo)) + result = false; + + PG_RETURN_BOOL(result); +} diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c index 8d01a93b30967..eb2fc4366b4a7 100644 --- a/src/backend/statistics/dependencies.c +++ b/src/backend/statistics/dependencies.c @@ -3,7 +3,7 @@ * dependencies.c * POSTGRES functional dependencies * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 99fdf208dba1c..a8b63ec0884a9 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -6,7 +6,7 @@ * Generic code supporting statistics objects created via CREATE STATISTICS. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -74,7 +74,7 @@ typedef struct StatExtEntry static List *fetch_statentries_for_relation(Relation pg_statext, Oid relid); -static VacAttrStats **lookup_var_attr_stats(Relation rel, Bitmapset *attrs, List *exprs, +static VacAttrStats **lookup_var_attr_stats(Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts); static void statext_store(Oid statOid, bool inh, MVNDistinct *ndistinct, MVDependencies *dependencies, @@ -89,9 +89,8 @@ typedef struct AnlExprData VacAttrStats *vacattrstat; /* statistics attrs to analyze */ } AnlExprData; -static void compute_expr_stats(Relation onerel, double totalrows, - AnlExprData *exprdata, int nexprs, - HeapTuple *rows, int numrows); +static void compute_expr_stats(Relation onerel, AnlExprData *exprdata, + int nexprs, HeapTuple *rows, int numrows); static Datum serialize_expr_stats(AnlExprData *exprdata, int nexprs); static Datum expr_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull); static AnlExprData *build_expr_data(List *exprs, int stattarget); @@ -166,7 +165,7 @@ BuildRelationExtStatistics(Relation onerel, bool inh, double totalrows, * Check if we can build these stats based on the column analyzed. If * not, report this fact (except in autovacuum) and move on. */ - stats = lookup_var_attr_stats(onerel, stat->columns, stat->exprs, + stats = lookup_var_attr_stats(stat->columns, stat->exprs, natts, vacattrstats); if (!stats) { @@ -220,9 +219,7 @@ BuildRelationExtStatistics(Relation onerel, bool inh, double totalrows, exprdata = build_expr_data(stat->exprs, stattarget); nexprs = list_length(stat->exprs); - compute_expr_stats(onerel, totalrows, - exprdata, nexprs, - rows, numrows); + compute_expr_stats(onerel, exprdata, nexprs, rows, numrows); exprstats = serialize_expr_stats(exprdata, nexprs); } @@ -296,7 +293,7 @@ ComputeExtStatisticsRows(Relation onerel, * analyzed. If not, ignore it (don't report anything, we'll do that * during the actual build BuildRelationExtStatistics). */ - stats = lookup_var_attr_stats(onerel, stat->columns, stat->exprs, + stats = lookup_var_attr_stats(stat->columns, stat->exprs, natts, vacattrstats); if (!stats) @@ -690,7 +687,7 @@ examine_expression(Node *expr, int stattarget) * indicate to the caller that the stats should not be built. */ static VacAttrStats ** -lookup_var_attr_stats(Relation rel, Bitmapset *attrs, List *exprs, +lookup_var_attr_stats(Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts) { int i = 0; @@ -1400,7 +1397,7 @@ statext_is_compatible_clause_internal(PlannerInfo *root, Node *clause, /* * If there are any securityQuals on the RTE from security barrier * views or RLS policies, then the user may not have access to all the - * table's data, and we must check that the operator is leak-proof. + * table's data, and we must check that the operator is leakproof. * * If the operator is leaky, then we must ignore this clause for the * purposes of estimating with MCV lists, otherwise the operator might @@ -1467,7 +1464,7 @@ statext_is_compatible_clause_internal(PlannerInfo *root, Node *clause, /* * If there are any securityQuals on the RTE from security barrier * views or RLS policies, then the user may not have access to all the - * table's data, and we must check that the operator is leak-proof. + * table's data, and we must check that the operator is leakproof. * * If the operator is leaky, then we must ignore this clause for the * purposes of estimating with MCV lists, otherwise the operator might @@ -2107,8 +2104,7 @@ examine_opclause_args(List *args, Node **exprp, Const **cstp, * Compute statistics about expressions of a relation. */ static void -compute_expr_stats(Relation onerel, double totalrows, - AnlExprData *exprdata, int nexprs, +compute_expr_stats(Relation onerel, AnlExprData *exprdata, int nexprs, HeapTuple *rows, int numrows) { MemoryContext expr_context, diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index b0e9aead84e97..d98cda698d941 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -4,7 +4,7 @@ * POSTGRES multivariate MCV lists * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/statistics/meson.build b/src/backend/statistics/meson.build index 73b29a3d50aed..07cfacd8c39ff 100644 --- a/src/backend/statistics/meson.build +++ b/src/backend/statistics/meson.build @@ -1,8 +1,11 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( + 'attribute_stats.c', 'dependencies.c', 'extended_stats.c', 'mcv.c', 'mvdistinct.c', + 'relation_stats.c', + 'stat_utils.c' ) diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c index e8eb6a398fea3..7e7a63405c8ba 100644 --- a/src/backend/statistics/mvdistinct.c +++ b/src/backend/statistics/mvdistinct.c @@ -13,7 +13,7 @@ * estimates are already available in pg_statistic. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c new file mode 100644 index 0000000000000..cd3a75b621a0c --- /dev/null +++ b/src/backend/statistics/relation_stats.c @@ -0,0 +1,241 @@ +/*------------------------------------------------------------------------- + * relation_stats.c + * + * PostgreSQL relation statistics manipulation + * + * Code supporting the direct import of relation statistics, similar to + * what is done by the ANALYZE command. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/statistics/relation_stats.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "catalog/indexing.h" +#include "catalog/namespace.h" +#include "statistics/stat_utils.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/fmgrprotos.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + + +/* + * Positional argument numbers, names, and types for + * relation_statistics_update(). + */ + +enum relation_stats_argnum +{ + RELSCHEMA_ARG = 0, + RELNAME_ARG, + RELPAGES_ARG, + RELTUPLES_ARG, + RELALLVISIBLE_ARG, + RELALLFROZEN_ARG, + NUM_RELATION_STATS_ARGS +}; + +static struct StatsArgInfo relarginfo[] = +{ + [RELSCHEMA_ARG] = {"schemaname", TEXTOID}, + [RELNAME_ARG] = {"relname", TEXTOID}, + [RELPAGES_ARG] = {"relpages", INT4OID}, + [RELTUPLES_ARG] = {"reltuples", FLOAT4OID}, + [RELALLVISIBLE_ARG] = {"relallvisible", INT4OID}, + [RELALLFROZEN_ARG] = {"relallfrozen", INT4OID}, + [NUM_RELATION_STATS_ARGS] = {0} +}; + +static bool relation_statistics_update(FunctionCallInfo fcinfo); + +/* + * Internal function for modifying statistics for a relation. + */ +static bool +relation_statistics_update(FunctionCallInfo fcinfo) +{ + bool result = true; + char *nspname; + char *relname; + Oid reloid; + Relation crel; + BlockNumber relpages = 0; + bool update_relpages = false; + float reltuples = 0; + bool update_reltuples = false; + BlockNumber relallvisible = 0; + bool update_relallvisible = false; + BlockNumber relallfrozen = 0; + bool update_relallfrozen = false; + HeapTuple ctup; + Form_pg_class pgcform; + int replaces[4] = {0}; + Datum values[4] = {0}; + bool nulls[4] = {0}; + int nreplaces = 0; + + stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG); + stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG); + + nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG)); + relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG)); + + reloid = stats_lookup_relid(nspname, relname); + + if (RecoveryInProgress()) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("recovery is in progress"), + errhint("Statistics cannot be modified during recovery."))); + + stats_lock_check_privileges(reloid); + + if (!PG_ARGISNULL(RELPAGES_ARG)) + { + relpages = PG_GETARG_UINT32(RELPAGES_ARG); + update_relpages = true; + } + + if (!PG_ARGISNULL(RELTUPLES_ARG)) + { + reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG); + if (reltuples < -1.0) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("reltuples cannot be < -1.0"))); + result = false; + } + else + update_reltuples = true; + } + + if (!PG_ARGISNULL(RELALLVISIBLE_ARG)) + { + relallvisible = PG_GETARG_UINT32(RELALLVISIBLE_ARG); + update_relallvisible = true; + } + + if (!PG_ARGISNULL(RELALLFROZEN_ARG)) + { + relallfrozen = PG_GETARG_UINT32(RELALLFROZEN_ARG); + update_relallfrozen = true; + } + + /* + * Take RowExclusiveLock on pg_class, consistent with + * vac_update_relstats(). + */ + crel = table_open(RelationRelationId, RowExclusiveLock); + + ctup = SearchSysCache1(RELOID, ObjectIdGetDatum(reloid)); + if (!HeapTupleIsValid(ctup)) + elog(ERROR, "pg_class entry for relid %u not found", reloid); + + pgcform = (Form_pg_class) GETSTRUCT(ctup); + + if (update_relpages && relpages != pgcform->relpages) + { + replaces[nreplaces] = Anum_pg_class_relpages; + values[nreplaces] = UInt32GetDatum(relpages); + nreplaces++; + } + + if (update_reltuples && reltuples != pgcform->reltuples) + { + replaces[nreplaces] = Anum_pg_class_reltuples; + values[nreplaces] = Float4GetDatum(reltuples); + nreplaces++; + } + + if (update_relallvisible && relallvisible != pgcform->relallvisible) + { + replaces[nreplaces] = Anum_pg_class_relallvisible; + values[nreplaces] = UInt32GetDatum(relallvisible); + nreplaces++; + } + + if (update_relallfrozen && relallfrozen != pgcform->relallfrozen) + { + replaces[nreplaces] = Anum_pg_class_relallfrozen; + values[nreplaces] = UInt32GetDatum(relallfrozen); + nreplaces++; + } + + if (nreplaces > 0) + { + TupleDesc tupdesc = RelationGetDescr(crel); + HeapTuple newtup; + + newtup = heap_modify_tuple_by_cols(ctup, tupdesc, nreplaces, + replaces, values, nulls); + CatalogTupleUpdate(crel, &newtup->t_self, newtup); + heap_freetuple(newtup); + } + + ReleaseSysCache(ctup); + + /* release the lock, consistent with vac_update_relstats() */ + table_close(crel, RowExclusiveLock); + + CommandCounterIncrement(); + + return result; +} + +/* + * Clear statistics for a given pg_class entry; that is, set back to initial + * stats for a newly-created table. + */ +Datum +pg_clear_relation_stats(PG_FUNCTION_ARGS) +{ + LOCAL_FCINFO(newfcinfo, 6); + + InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL); + + newfcinfo->args[0].value = PG_GETARG_DATUM(0); + newfcinfo->args[0].isnull = PG_ARGISNULL(0); + newfcinfo->args[1].value = PG_GETARG_DATUM(1); + newfcinfo->args[1].isnull = PG_ARGISNULL(1); + newfcinfo->args[2].value = UInt32GetDatum(0); + newfcinfo->args[2].isnull = false; + newfcinfo->args[3].value = Float4GetDatum(-1.0); + newfcinfo->args[3].isnull = false; + newfcinfo->args[4].value = UInt32GetDatum(0); + newfcinfo->args[4].isnull = false; + newfcinfo->args[5].value = UInt32GetDatum(0); + newfcinfo->args[5].isnull = false; + + relation_statistics_update(newfcinfo); + PG_RETURN_VOID(); +} + +Datum +pg_restore_relation_stats(PG_FUNCTION_ARGS) +{ + LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS); + bool result = true; + + InitFunctionCallInfoData(*positional_fcinfo, NULL, + NUM_RELATION_STATS_ARGS, + InvalidOid, NULL, NULL); + + if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, + relarginfo)) + result = false; + + if (!relation_statistics_update(positional_fcinfo)) + result = false; + + PG_RETURN_BOOL(result); +} diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c new file mode 100644 index 0000000000000..a9a3224efe6fd --- /dev/null +++ b/src/backend/statistics/stat_utils.c @@ -0,0 +1,359 @@ +/*------------------------------------------------------------------------- + * stat_utils.c + * + * PostgreSQL statistics manipulation utilities. + * + * Code supporting the direct manipulation of statistics. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/statistics/stat_utils.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/relation.h" +#include "catalog/index.h" +#include "catalog/namespace.h" +#include "catalog/pg_database.h" +#include "funcapi.h" +#include "miscadmin.h" +#include "statistics/stat_utils.h" +#include "storage/lmgr.h" +#include "utils/acl.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" + +/* + * Ensure that a given argument is not null. + */ +void +stats_check_required_arg(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, + int argnum) +{ + if (PG_ARGISNULL(argnum)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" cannot be NULL", + arginfo[argnum].argname))); +} + +/* + * Check that argument is either NULL or a one dimensional array with no + * NULLs. + * + * If a problem is found, emit a WARNING, and return false. Otherwise return + * true. + */ +bool +stats_check_arg_array(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, + int argnum) +{ + ArrayType *arr; + + if (PG_ARGISNULL(argnum)) + return true; + + arr = DatumGetArrayTypeP(PG_GETARG_DATUM(argnum)); + + if (ARR_NDIM(arr) != 1) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" cannot be a multidimensional array", + arginfo[argnum].argname))); + return false; + } + + if (array_contains_nulls(arr)) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" array cannot contain NULL values", + arginfo[argnum].argname))); + return false; + } + + return true; +} + +/* + * Enforce parameter pairs that must be specified together (or not at all) for + * a particular stakind, such as most_common_vals and most_common_freqs for + * STATISTIC_KIND_MCV. + * + * If a problem is found, emit a WARNING, and return false. Otherwise return + * true. + */ +bool +stats_check_arg_pair(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, + int argnum1, int argnum2) +{ + if (PG_ARGISNULL(argnum1) && PG_ARGISNULL(argnum2)) + return true; + + if (PG_ARGISNULL(argnum1) || PG_ARGISNULL(argnum2)) + { + int nullarg = PG_ARGISNULL(argnum1) ? argnum1 : argnum2; + int otherarg = PG_ARGISNULL(argnum1) ? argnum2 : argnum1; + + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"%s\" must be specified when \"%s\" is specified", + arginfo[nullarg].argname, + arginfo[otherarg].argname))); + + return false; + } + + return true; +} + +/* + * Lock relation in ShareUpdateExclusive mode, check privileges, and close the + * relation (but retain the lock). + * + * A role has privileges to set statistics on the relation if any of the + * following are true: + * - the role owns the current database and the relation is not shared + * - the role has the MAINTAIN privilege on the relation + */ +void +stats_lock_check_privileges(Oid reloid) +{ + Relation table; + Oid table_oid = reloid; + Oid index_oid = InvalidOid; + LOCKMODE index_lockmode = NoLock; + + /* + * For indexes, we follow the locking behavior in do_analyze_rel() and + * check_lock_if_inplace_updateable_rel(), which is to lock the table + * first in ShareUpdateExclusive mode and then the index in AccessShare + * mode. + * + * Partitioned indexes are treated differently than normal indexes in + * check_lock_if_inplace_updateable_rel(), so we take a + * ShareUpdateExclusive lock on both the partitioned table and the + * partitioned index. + */ + switch (get_rel_relkind(reloid)) + { + case RELKIND_INDEX: + index_oid = reloid; + table_oid = IndexGetRelation(index_oid, false); + index_lockmode = AccessShareLock; + break; + case RELKIND_PARTITIONED_INDEX: + index_oid = reloid; + table_oid = IndexGetRelation(index_oid, false); + index_lockmode = ShareUpdateExclusiveLock; + break; + default: + break; + } + + table = relation_open(table_oid, ShareUpdateExclusiveLock); + + /* the relkinds that can be used with ANALYZE */ + switch (table->rd_rel->relkind) + { + case RELKIND_RELATION: + case RELKIND_MATVIEW: + case RELKIND_FOREIGN_TABLE: + case RELKIND_PARTITIONED_TABLE: + break; + default: + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot modify statistics for relation \"%s\"", + RelationGetRelationName(table)), + errdetail_relkind_not_supported(table->rd_rel->relkind))); + } + + if (OidIsValid(index_oid)) + { + Relation index; + + Assert(index_lockmode != NoLock); + index = relation_open(index_oid, index_lockmode); + + Assert(index->rd_index && index->rd_index->indrelid == table_oid); + + /* retain lock on index */ + relation_close(index, NoLock); + } + + if (table->rd_rel->relisshared) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot modify statistics for shared relation"))); + + if (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId())) + { + AclResult aclresult = pg_class_aclcheck(RelationGetRelid(table), + GetUserId(), + ACL_MAINTAIN); + + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, + get_relkind_objtype(table->rd_rel->relkind), + NameStr(table->rd_rel->relname)); + } + + /* retain lock on table */ + relation_close(table, NoLock); +} + +/* + * Lookup relation oid from schema and relation name. + */ +Oid +stats_lookup_relid(const char *nspname, const char *relname) +{ + Oid nspoid; + Oid reloid; + + nspoid = LookupExplicitNamespace(nspname, false); + reloid = get_relname_relid(relname, nspoid); + if (!OidIsValid(reloid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("relation \"%s.%s\" does not exist", + nspname, relname))); + + return reloid; +} + + +/* + * Find the argument number for the given argument name, returning -1 if not + * found. + */ +static int +get_arg_by_name(const char *argname, struct StatsArgInfo *arginfo) +{ + int argnum; + + for (argnum = 0; arginfo[argnum].argname != NULL; argnum++) + if (pg_strcasecmp(argname, arginfo[argnum].argname) == 0) + return argnum; + + ereport(WARNING, + (errmsg("unrecognized argument name: \"%s\"", argname))); + + return -1; +} + +/* + * Ensure that a given argument matched the expected type. + */ +static bool +stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype) +{ + if (argtype != expectedtype) + { + ereport(WARNING, + (errmsg("argument \"%s\" has type \"%s\", expected type \"%s\"", + argname, format_type_be(argtype), + format_type_be(expectedtype)))); + return false; + } + + return true; +} + +/* + * Translate variadic argument pairs from 'pairs_fcinfo' into a + * 'positional_fcinfo' appropriate for calling relation_statistics_update() or + * attribute_statistics_update() with positional arguments. + * + * Caller should have already initialized positional_fcinfo with a size + * appropriate for calling the intended positional function, and arginfo + * should also match the intended positional function. + */ +bool +stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, + FunctionCallInfo positional_fcinfo, + struct StatsArgInfo *arginfo) +{ + Datum *args; + bool *argnulls; + Oid *types; + int nargs; + bool result = true; + + /* clear positional args */ + for (int i = 0; arginfo[i].argname != NULL; i++) + { + positional_fcinfo->args[i].value = (Datum) 0; + positional_fcinfo->args[i].isnull = true; + } + + nargs = extract_variadic_args(pairs_fcinfo, 0, true, + &args, &types, &argnulls); + + if (nargs % 2 != 0) + ereport(ERROR, + errmsg("variadic arguments must be name/value pairs"), + errhint("Provide an even number of variadic arguments that can be divided into pairs.")); + + /* + * For each argument name/value pair, find corresponding positional + * argument for the argument name, and assign the argument value to + * positional_fcinfo. + */ + for (int i = 0; i < nargs; i += 2) + { + int argnum; + char *argname; + + if (argnulls[i]) + ereport(ERROR, + (errmsg("name at variadic position %d is NULL", i + 1))); + + if (types[i] != TEXTOID) + ereport(ERROR, + (errmsg("name at variadic position %d has type \"%s\", expected type \"%s\"", + i + 1, format_type_be(types[i]), + format_type_be(TEXTOID)))); + + if (argnulls[i + 1]) + continue; + + argname = TextDatumGetCString(args[i]); + + /* + * The 'version' argument is a special case, not handled by arginfo + * because it's not a valid positional argument. + * + * For now, 'version' is accepted but ignored. In the future it can be + * used to interpret older statistics properly. + */ + if (pg_strcasecmp(argname, "version") == 0) + continue; + + argnum = get_arg_by_name(argname, arginfo); + + if (argnum < 0 || !stats_check_arg_type(argname, types[i + 1], + arginfo[argnum].argtype)) + { + result = false; + continue; + } + + positional_fcinfo->args[argnum].value = args[i + 1]; + positional_fcinfo->args[argnum].isnull = false; + } + + return result; +} diff --git a/src/backend/storage/aio/Makefile b/src/backend/storage/aio/Makefile index 2f29a9ec4d171..3f2469cc39945 100644 --- a/src/backend/storage/aio/Makefile +++ b/src/backend/storage/aio/Makefile @@ -9,6 +9,15 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = \ + aio.o \ + aio_callback.o \ + aio_funcs.o \ + aio_init.o \ + aio_io.o \ + aio_target.o \ + method_io_uring.o \ + method_sync.o \ + method_worker.o \ read_stream.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/storage/aio/README.md b/src/backend/storage/aio/README.md new file mode 100644 index 0000000000000..f10b5c7e31ec7 --- /dev/null +++ b/src/backend/storage/aio/README.md @@ -0,0 +1,424 @@ +# Asynchronous & Direct IO + +## Motivation + +### Why Asynchronous IO + +Until the introduction of asynchronous IO postgres relied on the operating +system to hide the cost of synchronous IO from postgres. While this worked +surprisingly well in a lot of workloads, it does not do as good a job on +prefetching and controlled writeback as we would like. + +There are important expensive operations like `fdatasync()` where the operating +system cannot hide the storage latency. This is particularly important for WAL +writes, where the ability to asynchronously issue `fdatasync()` or O_DSYNC +writes can yield significantly higher throughput. + + +### Why Direct / unbuffered IO + +The main reasons to want to use Direct IO are: + +- Lower CPU usage / higher throughput. Particularly on modern storage buffered + writes are bottlenecked by the operating system having to copy data from the + kernel's page cache to postgres buffer pool using the CPU. Whereas direct IO + can often move the data directly between the storage devices and postgres' + buffer cache, using DMA. While that transfer is ongoing, the CPU is free to + perform other work. +- Reduced latency - Direct IO can have substantially lower latency than + buffered IO, which can be impactful for OLTP workloads bottlenecked by WAL + write latency. +- Avoiding double buffering between operating system cache and postgres' + shared_buffers. +- Better control over the timing and pace of dirty data writeback. + + +The main reasons *not* to use Direct IO are: + +- Without AIO, Direct IO is unusably slow for most purposes. +- Even with AIO, many parts of postgres need to be modified to perform + explicit prefetching. +- In situations where shared_buffers cannot be set appropriately large, + e.g. because there are many different postgres instances hosted on shared + hardware, performance will often be worse than when using buffered IO. + + +## AIO Usage Example + +In many cases code that can benefit from AIO does not directly have to +interact with the AIO interface, but can use AIO via higher-level +abstractions. See [Helpers](#helpers). + +In this example, a buffer will be read into shared buffers. + +```C +/* + * Result of the operation, only to be accessed in this backend. + */ +PgAioReturn ioret; + +/* + * Acquire an AIO Handle, ioret will get result upon completion. + * + * Note that ioret needs to stay alive until the IO completes or + * CurrentResourceOwner is released (i.e. an error is thrown). + */ +PgAioHandle *ioh = pgaio_io_acquire(CurrentResourceOwner, &ioret); + +/* + * Reference that can be used to wait for the IO we initiate below. This + * reference can reside in local or shared memory and waited upon by any + * process. An arbitrary number of references can be made for each IO. + */ +PgAioWaitRef iow; + +pgaio_io_get_wref(ioh, &iow); + +/* + * Arrange for shared buffer completion callbacks to be called upon completion + * of the IO. This callback will update the buffer descriptors associated with + * the AioHandle, which e.g. allows other backends to access the buffer. + * + * A callback can be passed a small bit of data, e.g. to indicate whether to + * zero a buffer if it is invalid. + * + * Multiple completion callbacks can be registered for each handle. + */ +pgaio_io_register_callbacks(ioh, PGAIO_HCB_SHARED_BUFFER_READV, 0); + +/* + * The completion callback needs to know which buffers to update when the IO + * completes. As the AIO subsystem does not know about buffers, we have to + * associate this information with the AioHandle, for use by the completion + * callback registered above. + * + * In this example we're reading only a single buffer, hence the 1. + */ +pgaio_io_set_handle_data_32(ioh, (uint32 *) buffer, 1); + +/* + * Pass the AIO handle to lower-level function. When operating on the level of + * buffers, we don't know how exactly the IO is performed, that is the + * responsibility of the storage manager implementation. + * + * E.g. md.c needs to translate block numbers into offsets in segments. + * + * Once the IO handle has been handed off to smgrstartreadv(), it may not + * further be used, as the IO may immediately get executed below + * smgrstartreadv() and the handle reused for another IO. + * + * To issue multiple IOs in an efficient way, a caller can call + * pgaio_enter_batchmode() before starting multiple IOs, and end that batch + * with pgaio_exit_batchmode(). Note that one needs to be careful while there + * may be unsubmitted IOs, as another backend may need to wait for one of the + * unsubmitted IOs. If this backend then had to wait for the other backend, + * it'd end in an undetected deadlock. See pgaio_enter_batchmode() for more + * details. + * + * Note that even while in batchmode an IO might get submitted immediately, + * e.g. due to reaching a limit on the number of unsubmitted IOs, and even + * complete before smgrstartreadv() returns. + */ +smgrstartreadv(ioh, operation->smgr, forknum, blkno, + BufferGetBlock(buffer), 1); + +/* + * To benefit from AIO, it is beneficial to perform other work, including + * submitting other IOs, before waiting for the IO to complete. Otherwise + * we could just have used synchronous, blocking IO. + */ +perform_other_work(); + +/* + * We did some other work and now need the IO operation to have completed to + * continue. + */ +pgaio_wref_wait(&iow); + +/* + * At this point the IO has completed. We do not yet know whether it succeeded + * or failed, however. The buffer's state has been updated, which allows other + * backends to use the buffer (if the IO succeeded), or retry the IO (if it + * failed). + * + * Note that in case the IO has failed, a LOG message may have been emitted, + * but no ERROR has been raised. This is crucial, as another backend waiting + * for this IO should not see an ERROR. + * + * To check whether the operation succeeded, and to raise an ERROR, or if more + * appropriate LOG, the PgAioReturn we passed to pgaio_io_acquire() is used. + */ +if (ioret.result.status == PGAIO_RS_ERROR) + pgaio_result_report(ioret.result, &ioret.target_data, ERROR); + +/* + * Besides having succeeded completely, the IO could also have a) partially + * completed or b) succeeded with a warning (e.g. due to zero_damaged_pages). + * If we e.g. tried to read many blocks at once, the read might have + * only succeeded for the first few blocks. + * + * If the IO partially succeeded and this backend needs all blocks to have + * completed, this backend needs to reissue the IO for the remaining buffers. + * The AIO subsystem cannot handle this retry transparently. + * + * As this example is already long, and we only read a single block, we'll just + * error out if there's a partial read or a warning. + */ +if (ioret.result.status != PGAIO_RS_OK) + pgaio_result_report(ioret.result, &ioret.target_data, ERROR); + +/* + * The IO succeeded, so we can use the buffer now. + */ +``` + + +## Design Criteria & Motivation + +### Deadlock and Starvation Dangers due to AIO + +Using AIO in a naive way can easily lead to deadlocks in an environment where +the source/target of AIO are shared resources, like pages in postgres' +shared_buffers. + +Consider one backend performing readahead on a table, initiating IO for a +number of buffers ahead of the current "scan position". If that backend then +performs some operation that blocks, or even just is slow, the IO completion +for the asynchronously initiated read may not be processed. + +This AIO implementation solves this problem by requiring that AIO methods +either allow AIO completions to be processed by any backend in the system +(e.g. io_uring), or to guarantee that AIO processing will happen even when the +issuing backend is blocked (e.g. worker mode, which offloads completion +processing to the AIO workers). + + +### IO can be started in critical sections + +Using AIO for WAL writes can reduce the overhead of WAL logging substantially: + +- AIO allows to start WAL writes eagerly, so they complete before needing to + wait +- AIO allows to have multiple WAL flushes in progress at the same time +- AIO makes it more realistic to use O\_DIRECT + O\_DSYNC, which can reduce + the number of roundtrips to storage on some OSs and storage HW (buffered IO + and direct IO without O_DSYNC needs to issue a write and after the write's + completion a cache flush, whereas O\_DIRECT + O\_DSYNC can use a single + Force Unit Access (FUA) write). + +The need to be able to execute IO in critical sections has substantial design +implication on the AIO subsystem. Mainly because completing IOs (see prior +section) needs to be possible within a critical section, even if the +to-be-completed IO itself was not issued in a critical section. Consider +e.g. the case of a backend first starting a number of writes from shared +buffers and then starting to flush the WAL. Because only a limited amount of +IO can be in-progress at the same time, initiating IO for flushing the WAL may +require to first complete IO that was started earlier. + + +### State for AIO needs to live in shared memory + +Because postgres uses a process model and because AIOs need to be +complete-able by any backend much of the state of the AIO subsystem needs to +live in shared memory. + +In an `EXEC_BACKEND` build, a backend's executable code and other process +local state is not necessarily mapped to the same addresses in each process +due to ASLR. This means that the shared memory cannot contain pointers to +callbacks. + + +## Design of the AIO Subsystem + + +### AIO Methods + +To achieve portability and performance, multiple methods of performing AIO are +implemented and others are likely worth adding in the future. + + +#### Synchronous Mode + +`io_method=sync` does not actually perform AIO but allows to use the AIO API +while performing synchronous IO. This can be useful for debugging. The code +for the synchronous mode is also used as a fallback by e.g. the [worker +mode](#worker) uses it to execute IO that cannot be executed by workers. + + +#### Worker + +`io_method=worker` is available on every platform postgres runs on, and +implements asynchronous IO - from the view of the issuing process - by +dispatching the IO to one of several worker processes performing the IO in a +synchronous manner. + + +#### io_uring + +`io_method=io_uring` is available on Linux 5.1+. In contrast to worker mode it +dispatches all IO from within the process, lowering context switch rate / +latency. + + +### AIO Handles + +The central API piece for postgres' AIO abstraction are AIO handles. To +execute an IO one first has to acquire an IO handle (`pgaio_io_acquire()`) and +then "define" it, i.e. associate an IO operation with the handle. + +Often AIO handles are acquired on a higher level and then passed to a lower +level to be fully defined. E.g., for IO to/from shared buffers, bufmgr.c +routines acquire the handle, which is then passed through smgr.c, md.c to be +finally fully defined in fd.c. + +The functions used at the lowest level to define the operation are +`pgaio_io_start_*()`. + +Because acquisition of an IO handle +[must always succeed](#io-can-be-started-in-critical-sections) +and the number of AIO Handles +[has to be limited](#state-for-aio-needs-to-live-in-shared-memory) +AIO handles can be reused as soon as they have completed. Obviously code needs +to be able to react to IO completion. State can be updated using +[AIO Completion callbacks](#aio-callbacks) +and the issuing backend can provide a backend local variable to receive the +result of the IO, as described in +[AIO Result](#aio-results). +An IO can be waited for, by both the issuing and any other backend, using +[AIO References](#aio-wait-references). + + +Because an AIO Handle is not executable just after calling +`pgaio_io_acquire()` and because `pgaio_io_acquire()` needs to always succeed +(absent a PANIC), only a single AIO Handle may be acquired (i.e. returned by +`pgaio_io_acquire()`) without causing the IO to have been defined (by, +potentially indirectly, causing `pgaio_io_start_*()` to have been +called). Otherwise a backend could trivially self-deadlock by using up all AIO +Handles without the ability to wait for some of the IOs to complete. + +If it turns out that an AIO Handle is not needed, e.g., because the handle was +acquired before holding a contended lock, it can be released without being +defined using `pgaio_io_release()`. + + +### AIO Callbacks + +Commonly several layers need to react to completion of an IO. E.g. for a read +md.c needs to check if the IO outright failed or was shorter than needed, +bufmgr.c needs to verify the page looks valid and bufmgr.c needs to update the +BufferDesc to update the buffer's state. + +The fact that several layers / subsystems need to react to IO completion poses +a few challenges: + +- Upper layers should not need to know details of lower layers. E.g. bufmgr.c + should not assume the IO will pass through md.c. Therefore upper levels + cannot know what lower layers would consider an error. + +- Lower layers should not need to know about upper layers. E.g. smgr APIs are + used going through shared buffers but are also used bypassing shared + buffers. This means that e.g. md.c is not in a position to validate + checksums. + +- Having code in the AIO subsystem for every possible combination of layers + would lead to a lot of duplication. + +The "solution" to this is the ability to associate multiple completion +callbacks with a handle. E.g. bufmgr.c can have a callback to update the +BufferDesc state and to verify the page and md.c can have another callback to +check if the IO operation was successful. + +As [mentioned](#state-for-aio-needs-to-live-in-shared-memory), shared memory +currently cannot contain function pointers. Because of that completion +callbacks are not directly identified by function pointers but by IDs +(`PgAioHandleCallbackID`). A substantial added benefit is that that +allows callbacks to be identified by much smaller amount of memory (a single +byte currently). + +In addition to completion, AIO callbacks also are called to "stage" an +IO. This is, e.g., used to increase buffer reference counts to account for the +AIO subsystem referencing the buffer, which is required to handle the case +where the issuing backend errors out and releases its own pins while the IO is +still ongoing. + +As [explained earlier](#io-can-be-started-in-critical-sections) IO completions +need to be safe to execute in critical sections. To allow the backend that +issued the IO to error out in case of failure [AIO Result](#aio-results) can +be used. + + +### AIO Targets + +In addition to the completion callbacks describe above, each AIO Handle has +exactly one "target". Each target has some space inside an AIO Handle with +information specific to the target and can provide callbacks to allow to +reopen the underlying file (required for worker mode) and to describe the IO +operation (used for debug logging and error messages). + +I.e., if two different uses of AIO can describe the identity of the file being +operated on the same way, it likely makes sense to use the same +target. E.g. different smgr implementations can describe IO with +RelFileLocator, ForkNumber and BlockNumber and can thus share a target. In +contrast, IO for a WAL file would be described with TimeLineID and XLogRecPtr +and it would not make sense to use the same target for smgr and WAL. + + +### AIO Wait References + +As [described above](#aio-handles), AIO Handles can be reused immediately +after completion and therefore cannot be used to wait for completion of the +IO. Waiting is enabled using AIO wait references, which do not just identify +an AIO Handle but also include the handles "generation". + +A reference to an AIO Handle can be acquired using `pgaio_io_get_wref()` and +then waited upon using `pgaio_wref_wait()`. + + +### AIO Results + +As AIO completion callbacks +[are executed in critical sections](#io-can-be-started-in-critical-sections) +and [may be executed by any backend](#deadlock-and-starvation-dangers-due-to-aio) +completion callbacks cannot be used to, e.g., make the query that triggered an +IO ERROR out. + +To allow to react to failing IOs the issuing backend can pass a pointer to a +`PgAioReturn` in backend local memory. Before an AIO Handle is reused the +`PgAioReturn` is filled with information about the IO. This includes +information about whether the IO was successful (as a value of +`PgAioResultStatus`) and enough information to raise an error in case of a +failure (via `pgaio_result_report()`, with the error details encoded in +`PgAioResult`). + + +### AIO Errors + +It would be very convenient to have shared completion callbacks encode the +details of errors as an `ErrorData` that could be raised at a later +time. Unfortunately doing so would require allocating memory. While elog.c can +guarantee (well, kinda) that logging a message will not run out of memory, +that only works because a very limited number of messages are in the process +of being logged. With AIO a large number of concurrently issued AIOs might +fail. + +To avoid the need for preallocating a potentially large amount of memory (in +shared memory no less!), completion callbacks instead have to encode errors in +a more compact format that can be converted into an error message. + + +## Helpers + +Using the low-level AIO API introduces too much complexity to do so all over +the tree. Most uses of AIO should be done via reusable, higher-level, +helpers. + + +### Read Stream + +A common and very beneficial use of AIO are reads where a substantial number +of to-be-read locations are known ahead of time. E.g., for a sequential scan +the set of blocks that need to be read can be determined solely by knowing the +current position and checking the buffer mapping table. + +The [Read Stream](../../../include/storage/read_stream.h) interface makes it +comparatively easy to use AIO for such use cases. diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c new file mode 100644 index 0000000000000..3643f27ad6e1b --- /dev/null +++ b/src/backend/storage/aio/aio.c @@ -0,0 +1,1345 @@ +/*------------------------------------------------------------------------- + * + * aio.c + * AIO - Core Logic + * + * For documentation about how AIO works on a higher level, including a + * schematic example, see README.md. + * + * + * AIO is a complicated subsystem. To keep things navigable, it is split + * across a number of files: + * + * - method_*.c - different ways of executing AIO (e.g. worker process) + * + * - aio_target.c - IO on different kinds of targets + * + * - aio_io.c - method-independent code for specific IO ops (e.g. readv) + * + * - aio_callback.c - callbacks at IO operation lifecycle events + * + * - aio_init.c - per-server and per-backend initialization + * + * - aio.c - all other topics + * + * - read_stream.c - helper for reading buffered relation data + * + * - README.md - higher-level overview over AIO + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "lib/ilist.h" +#include "miscadmin.h" +#include "port/atomics.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/aio_subsys.h" +#include "utils/guc.h" +#include "utils/guc_hooks.h" +#include "utils/injection_point.h" +#include "utils/resowner.h" +#include "utils/wait_event_types.h" + + +static inline void pgaio_io_update_state(PgAioHandle *ioh, PgAioHandleState new_state); +static void pgaio_io_reclaim(PgAioHandle *ioh); +static void pgaio_io_resowner_register(PgAioHandle *ioh); +static void pgaio_io_wait_for_free(void); +static PgAioHandle *pgaio_io_from_wref(PgAioWaitRef *iow, uint64 *ref_generation); +static const char *pgaio_io_state_get_name(PgAioHandleState s); +static void pgaio_io_wait(PgAioHandle *ioh, uint64 ref_generation); + + +/* Options for io_method. */ +const struct config_enum_entry io_method_options[] = { + {"sync", IOMETHOD_SYNC, false}, + {"worker", IOMETHOD_WORKER, false}, +#ifdef IOMETHOD_IO_URING_ENABLED + {"io_uring", IOMETHOD_IO_URING, false}, +#endif + {NULL, 0, false} +}; + +/* GUCs */ +int io_method = DEFAULT_IO_METHOD; +int io_max_concurrency = -1; + +/* global control for AIO */ +PgAioCtl *pgaio_ctl; + +/* current backend's per-backend state */ +PgAioBackend *pgaio_my_backend; + + +static const IoMethodOps *const pgaio_method_ops_table[] = { + [IOMETHOD_SYNC] = &pgaio_sync_ops, + [IOMETHOD_WORKER] = &pgaio_worker_ops, +#ifdef IOMETHOD_IO_URING_ENABLED + [IOMETHOD_IO_URING] = &pgaio_uring_ops, +#endif +}; + +/* callbacks for the configured io_method, set by assign_io_method */ +const IoMethodOps *pgaio_method_ops; + + +/* -------------------------------------------------------------------------------- + * Public Functions related to PgAioHandle + * -------------------------------------------------------------------------------- + */ + +/* + * Acquire an AioHandle, waiting for IO completion if necessary. + * + * Each backend can only have one AIO handle that has been "handed out" to + * code, but not yet submitted or released. This restriction is necessary to + * ensure that it is possible for code to wait for an unused handle by waiting + * for in-flight IO to complete. There is a limited number of handles in each + * backend, if multiple handles could be handed out without being submitted, + * waiting for all in-flight IO to complete would not guarantee that handles + * free up. + * + * It is cheap to acquire an IO handle, unless all handles are in use. In that + * case this function waits for the oldest IO to complete. If that is not + * desirable, use pgaio_io_acquire_nb(). + * + * If a handle was acquired but then does not turn out to be needed, + * e.g. because pgaio_io_acquire() is called before starting an IO in a + * critical section, the handle needs to be released with pgaio_io_release(). + * + * + * To react to the completion of the IO as soon as it is known to have + * completed, callbacks can be registered with pgaio_io_register_callbacks(). + * + * To actually execute IO using the returned handle, the pgaio_io_start_*() + * family of functions is used. In many cases the pgaio_io_start_*() call will + * not be done directly by code that acquired the handle, but by lower level + * code that gets passed the handle. E.g. if code in bufmgr.c wants to perform + * AIO, it typically will pass the handle to smgr.c, which will pass it on to + * md.c, on to fd.c, which then finally calls pgaio_io_start_*(). This + * forwarding allows the various layers to react to the IO's completion by + * registering callbacks. These callbacks in turn can translate a lower + * layer's result into a result understandable by a higher layer. + * + * During pgaio_io_start_*() the IO is staged (i.e. prepared for execution but + * not submitted to the kernel). Unless in batchmode + * (c.f. pgaio_enter_batchmode()), the IO will also get submitted for + * execution. Note that, whether in batchmode or not, the IO might even + * complete before the functions return. + * + * After pgaio_io_start_*() the AioHandle is "consumed" and may not be + * referenced by the IO issuing code. To e.g. wait for IO, references to the + * IO can be established with pgaio_io_get_wref() *before* pgaio_io_start_*() + * is called. pgaio_wref_wait() can be used to wait for the IO to complete. + * + * + * To know if the IO [partially] succeeded or failed, a PgAioReturn * can be + * passed to pgaio_io_acquire(). Once the issuing backend has called + * pgaio_wref_wait(), the PgAioReturn contains information about whether the + * operation succeeded and details about the first failure, if any. The error + * can be raised / logged with pgaio_result_report(). + * + * The lifetime of the memory pointed to be *ret needs to be at least as long + * as the passed in resowner. If the resowner releases resources before the IO + * completes (typically due to an error), the reference to *ret will be + * cleared. In case of resowner cleanup *ret will not be updated with the + * results of the IO operation. + */ +PgAioHandle * +pgaio_io_acquire(struct ResourceOwnerData *resowner, PgAioReturn *ret) +{ + PgAioHandle *h; + + while (true) + { + h = pgaio_io_acquire_nb(resowner, ret); + + if (h != NULL) + return h; + + /* + * Evidently all handles by this backend are in use. Just wait for + * some to complete. + */ + pgaio_io_wait_for_free(); + } +} + +/* + * Acquire an AioHandle, returning NULL if no handles are free. + * + * See pgaio_io_acquire(). The only difference is that this function will return + * NULL if there are no idle handles, instead of blocking. + */ +PgAioHandle * +pgaio_io_acquire_nb(struct ResourceOwnerData *resowner, PgAioReturn *ret) +{ + PgAioHandle *ioh = NULL; + + if (pgaio_my_backend->num_staged_ios >= PGAIO_SUBMIT_BATCH_SIZE) + { + Assert(pgaio_my_backend->num_staged_ios == PGAIO_SUBMIT_BATCH_SIZE); + pgaio_submit_staged(); + } + + if (pgaio_my_backend->handed_out_io) + elog(ERROR, "API violation: Only one IO can be handed out"); + + /* + * Probably not needed today, as interrupts should not process this IO, + * but... + */ + HOLD_INTERRUPTS(); + + if (!dclist_is_empty(&pgaio_my_backend->idle_ios)) + { + dlist_node *ion = dclist_pop_head_node(&pgaio_my_backend->idle_ios); + + ioh = dclist_container(PgAioHandle, node, ion); + + Assert(ioh->state == PGAIO_HS_IDLE); + Assert(ioh->owner_procno == MyProcNumber); + + pgaio_io_update_state(ioh, PGAIO_HS_HANDED_OUT); + pgaio_my_backend->handed_out_io = ioh; + + if (resowner) + pgaio_io_resowner_register(ioh); + + if (ret) + { + ioh->report_return = ret; + ret->result.status = PGAIO_RS_UNKNOWN; + } + } + + RESUME_INTERRUPTS(); + + return ioh; +} + +/* + * Release IO handle that turned out to not be required. + * + * See pgaio_io_acquire() for more details. + */ +void +pgaio_io_release(PgAioHandle *ioh) +{ + if (ioh == pgaio_my_backend->handed_out_io) + { + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(ioh->resowner); + + pgaio_my_backend->handed_out_io = NULL; + + /* + * Note that no interrupts are processed between the handed_out_io + * check and the call to reclaim - that's important as otherwise an + * interrupt could have already reclaimed the handle. + */ + pgaio_io_reclaim(ioh); + } + else + { + elog(ERROR, "release in unexpected state"); + } +} + +/* + * Release IO handle during resource owner cleanup. + */ +void +pgaio_io_release_resowner(dlist_node *ioh_node, bool on_error) +{ + PgAioHandle *ioh = dlist_container(PgAioHandle, resowner_node, ioh_node); + + Assert(ioh->resowner); + + /* + * Otherwise an interrupt, in the middle of releasing the IO, could end up + * trying to wait for the IO, leading to state confusion. + */ + HOLD_INTERRUPTS(); + + ResourceOwnerForgetAioHandle(ioh->resowner, &ioh->resowner_node); + ioh->resowner = NULL; + + switch (ioh->state) + { + case PGAIO_HS_IDLE: + elog(ERROR, "unexpected"); + break; + case PGAIO_HS_HANDED_OUT: + Assert(ioh == pgaio_my_backend->handed_out_io || pgaio_my_backend->handed_out_io == NULL); + + if (ioh == pgaio_my_backend->handed_out_io) + { + pgaio_my_backend->handed_out_io = NULL; + if (!on_error) + elog(WARNING, "leaked AIO handle"); + } + + pgaio_io_reclaim(ioh); + break; + case PGAIO_HS_DEFINED: + case PGAIO_HS_STAGED: + if (!on_error) + elog(WARNING, "AIO handle was not submitted"); + pgaio_submit_staged(); + break; + case PGAIO_HS_SUBMITTED: + case PGAIO_HS_COMPLETED_IO: + case PGAIO_HS_COMPLETED_SHARED: + case PGAIO_HS_COMPLETED_LOCAL: + /* this is expected to happen */ + break; + } + + /* + * Need to unregister the reporting of the IO's result, the memory it's + * referencing likely has gone away. + */ + if (ioh->report_return) + ioh->report_return = NULL; + + RESUME_INTERRUPTS(); +} + +/* + * Add a [set of] flags to the IO. + * + * Note that this combines flags with already set flags, rather than set flags + * to explicitly the passed in parameters. This is to allow multiple callsites + * to set flags. + */ +void +pgaio_io_set_flag(PgAioHandle *ioh, PgAioHandleFlags flag) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + + ioh->flags |= flag; +} + +/* + * Returns an ID uniquely identifying the IO handle. This is only really + * useful for logging, as handles are reused across multiple IOs. + */ +int +pgaio_io_get_id(PgAioHandle *ioh) +{ + Assert(ioh >= pgaio_ctl->io_handles && + ioh < (pgaio_ctl->io_handles + pgaio_ctl->io_handle_count)); + return ioh - pgaio_ctl->io_handles; +} + +/* + * Return the ProcNumber for the process that can use an IO handle. The + * mapping from IO handles to PGPROCs is static, therefore this even works + * when the corresponding PGPROC is not in use. + */ +ProcNumber +pgaio_io_get_owner(PgAioHandle *ioh) +{ + return ioh->owner_procno; +} + +/* + * Return a wait reference for the IO. Only wait references can be used to + * wait for an IOs completion, as handles themselves can be reused after + * completion. See also the comment above pgaio_io_acquire(). + */ +void +pgaio_io_get_wref(PgAioHandle *ioh, PgAioWaitRef *iow) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT || + ioh->state == PGAIO_HS_DEFINED || + ioh->state == PGAIO_HS_STAGED); + Assert(ioh->generation != 0); + + iow->aio_index = ioh - pgaio_ctl->io_handles; + iow->generation_upper = (uint32) (ioh->generation >> 32); + iow->generation_lower = (uint32) ioh->generation; +} + + + +/* -------------------------------------------------------------------------------- + * Internal Functions related to PgAioHandle + * -------------------------------------------------------------------------------- + */ + +static inline void +pgaio_io_update_state(PgAioHandle *ioh, PgAioHandleState new_state) +{ + /* + * All callers need to have held interrupts in some form, otherwise + * interrupt processing could wait for the IO to complete, while in an + * intermediary state. + */ + Assert(!INTERRUPTS_CAN_BE_PROCESSED()); + + pgaio_debug_io(DEBUG5, ioh, + "updating state to %s", + pgaio_io_state_get_name(new_state)); + + /* + * Ensure the changes signified by the new state are visible before the + * new state becomes visible. + */ + pg_write_barrier(); + + ioh->state = new_state; +} + +static void +pgaio_io_resowner_register(PgAioHandle *ioh) +{ + Assert(!ioh->resowner); + Assert(CurrentResourceOwner); + + ResourceOwnerRememberAioHandle(CurrentResourceOwner, &ioh->resowner_node); + ioh->resowner = CurrentResourceOwner; +} + +/* + * Stage IO for execution and, if appropriate, submit it immediately. + * + * Should only be called from pgaio_io_start_*(). + */ +void +pgaio_io_stage(PgAioHandle *ioh, PgAioOp op) +{ + bool needs_synchronous; + + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(pgaio_my_backend->handed_out_io == ioh); + Assert(pgaio_io_has_target(ioh)); + + /* + * Otherwise an interrupt, in the middle of staging and possibly executing + * the IO, could end up trying to wait for the IO, leading to state + * confusion. + */ + HOLD_INTERRUPTS(); + + ioh->op = op; + ioh->result = 0; + + pgaio_io_update_state(ioh, PGAIO_HS_DEFINED); + + /* allow a new IO to be staged */ + pgaio_my_backend->handed_out_io = NULL; + + pgaio_io_call_stage(ioh); + + pgaio_io_update_state(ioh, PGAIO_HS_STAGED); + + /* + * Synchronous execution has to be executed, well, synchronously, so check + * that first. + */ + needs_synchronous = pgaio_io_needs_synchronous_execution(ioh); + + pgaio_debug_io(DEBUG3, ioh, + "staged (synchronous: %d, in_batch: %d)", + needs_synchronous, pgaio_my_backend->in_batchmode); + + if (!needs_synchronous) + { + pgaio_my_backend->staged_ios[pgaio_my_backend->num_staged_ios++] = ioh; + Assert(pgaio_my_backend->num_staged_ios <= PGAIO_SUBMIT_BATCH_SIZE); + + /* + * Unless code explicitly opted into batching IOs, submit the IO + * immediately. + */ + if (!pgaio_my_backend->in_batchmode) + pgaio_submit_staged(); + } + else + { + pgaio_io_prepare_submit(ioh); + pgaio_io_perform_synchronously(ioh); + } + + RESUME_INTERRUPTS(); +} + +bool +pgaio_io_needs_synchronous_execution(PgAioHandle *ioh) +{ + /* + * If the caller said to execute the IO synchronously, do so. + * + * XXX: We could optimize the logic when to execute synchronously by first + * checking if there are other IOs in flight and only synchronously + * executing if not. Unclear whether that'll be sufficiently common to be + * worth worrying about. + */ + if (ioh->flags & PGAIO_HF_SYNCHRONOUS) + return true; + + /* Check if the IO method requires synchronous execution of IO */ + if (pgaio_method_ops->needs_synchronous_execution) + return pgaio_method_ops->needs_synchronous_execution(ioh); + + return false; +} + +/* + * Handle IO being processed by IO method. + * + * Should be called by IO methods / synchronous IO execution, just before the + * IO is performed. + */ +void +pgaio_io_prepare_submit(PgAioHandle *ioh) +{ + pgaio_io_update_state(ioh, PGAIO_HS_SUBMITTED); + + dclist_push_tail(&pgaio_my_backend->in_flight_ios, &ioh->node); +} + +/* + * Handle IO getting completed by a method. + * + * Should be called by IO methods / synchronous IO execution, just after the + * IO has been performed. + * + * Expects to be called in a critical section. We expect IOs to be usable for + * WAL etc, which requires being able to execute completion callbacks in a + * critical section. + */ +void +pgaio_io_process_completion(PgAioHandle *ioh, int result) +{ + Assert(ioh->state == PGAIO_HS_SUBMITTED); + + Assert(CritSectionCount > 0); + + ioh->result = result; + + pgaio_io_update_state(ioh, PGAIO_HS_COMPLETED_IO); + + INJECTION_POINT("aio-process-completion-before-shared", ioh); + + pgaio_io_call_complete_shared(ioh); + + pgaio_io_update_state(ioh, PGAIO_HS_COMPLETED_SHARED); + + /* condition variable broadcast ensures state is visible before wakeup */ + ConditionVariableBroadcast(&ioh->cv); + + /* contains call to pgaio_io_call_complete_local() */ + if (ioh->owner_procno == MyProcNumber) + pgaio_io_reclaim(ioh); +} + +/* + * Has the IO completed and thus the IO handle been reused? + * + * This is useful when waiting for IO completion at a low level (e.g. in an IO + * method's ->wait_one() callback). + */ +bool +pgaio_io_was_recycled(PgAioHandle *ioh, uint64 ref_generation, PgAioHandleState *state) +{ + *state = ioh->state; + + /* + * Ensure that we don't see an earlier state of the handle than ioh->state + * due to compiler or CPU reordering. This protects both ->generation as + * directly used here, and other fields in the handle accessed in the + * caller if the handle was not reused. + */ + pg_read_barrier(); + + return ioh->generation != ref_generation; +} + +/* + * Wait for IO to complete. External code should never use this, outside of + * the AIO subsystem waits are only allowed via pgaio_wref_wait(). + */ +static void +pgaio_io_wait(PgAioHandle *ioh, uint64 ref_generation) +{ + PgAioHandleState state; + bool am_owner; + + am_owner = ioh->owner_procno == MyProcNumber; + + if (pgaio_io_was_recycled(ioh, ref_generation, &state)) + return; + + if (am_owner) + { + if (state != PGAIO_HS_SUBMITTED + && state != PGAIO_HS_COMPLETED_IO + && state != PGAIO_HS_COMPLETED_SHARED + && state != PGAIO_HS_COMPLETED_LOCAL) + { + elog(PANIC, "waiting for own IO %d in wrong state: %s", + pgaio_io_get_id(ioh), pgaio_io_get_state_name(ioh)); + } + } + + while (true) + { + if (pgaio_io_was_recycled(ioh, ref_generation, &state)) + return; + + switch (state) + { + case PGAIO_HS_IDLE: + case PGAIO_HS_HANDED_OUT: + elog(ERROR, "IO in wrong state: %d", state); + break; + + case PGAIO_HS_SUBMITTED: + + /* + * If we need to wait via the IO method, do so now. Don't + * check via the IO method if the issuing backend is executing + * the IO synchronously. + */ + if (pgaio_method_ops->wait_one && !(ioh->flags & PGAIO_HF_SYNCHRONOUS)) + { + pgaio_method_ops->wait_one(ioh, ref_generation); + continue; + } + /* fallthrough */ + + /* waiting for owner to submit */ + case PGAIO_HS_DEFINED: + case PGAIO_HS_STAGED: + /* waiting for reaper to complete */ + /* fallthrough */ + case PGAIO_HS_COMPLETED_IO: + /* shouldn't be able to hit this otherwise */ + Assert(IsUnderPostmaster); + /* ensure we're going to get woken up */ + ConditionVariablePrepareToSleep(&ioh->cv); + + while (!pgaio_io_was_recycled(ioh, ref_generation, &state)) + { + if (state == PGAIO_HS_COMPLETED_SHARED || + state == PGAIO_HS_COMPLETED_LOCAL) + break; + ConditionVariableSleep(&ioh->cv, WAIT_EVENT_AIO_IO_COMPLETION); + } + + ConditionVariableCancelSleep(); + break; + + case PGAIO_HS_COMPLETED_SHARED: + case PGAIO_HS_COMPLETED_LOCAL: + + /* + * Note that no interrupts are processed between + * pgaio_io_was_recycled() and this check - that's important + * as otherwise an interrupt could have already reclaimed the + * handle. + */ + if (am_owner) + pgaio_io_reclaim(ioh); + return; + } + } +} + +/* + * Make IO handle ready to be reused after IO has completed or after the + * handle has been released without being used. + * + * Note that callers need to be careful about only calling this in the right + * state and that no interrupts can be processed between the state check and + * the call to pgaio_io_reclaim(). Otherwise interrupt processing could + * already have reclaimed the handle. + */ +static void +pgaio_io_reclaim(PgAioHandle *ioh) +{ + /* This is only ok if it's our IO */ + Assert(ioh->owner_procno == MyProcNumber); + Assert(ioh->state != PGAIO_HS_IDLE); + + /* see comment in function header */ + HOLD_INTERRUPTS(); + + /* + * It's a bit ugly, but right now the easiest place to put the execution + * of local completion callbacks is this function, as we need to execute + * local callbacks just before reclaiming at multiple callsites. + */ + if (ioh->state == PGAIO_HS_COMPLETED_SHARED) + { + PgAioResult local_result; + + local_result = pgaio_io_call_complete_local(ioh); + pgaio_io_update_state(ioh, PGAIO_HS_COMPLETED_LOCAL); + + if (ioh->report_return) + { + ioh->report_return->result = local_result; + ioh->report_return->target_data = ioh->target_data; + } + } + + pgaio_debug_io(DEBUG4, ioh, + "reclaiming: distilled_result: (status %s, id %u, error_data %d), raw_result: %d", + pgaio_result_status_string(ioh->distilled_result.status), + ioh->distilled_result.id, + ioh->distilled_result.error_data, + ioh->result); + + /* if the IO has been defined, it's on the in-flight list, remove */ + if (ioh->state != PGAIO_HS_HANDED_OUT) + dclist_delete_from(&pgaio_my_backend->in_flight_ios, &ioh->node); + + if (ioh->resowner) + { + ResourceOwnerForgetAioHandle(ioh->resowner, &ioh->resowner_node); + ioh->resowner = NULL; + } + + Assert(!ioh->resowner); + + /* + * Update generation & state first, before resetting the IO's fields, + * otherwise a concurrent "viewer" could think the fields are valid, even + * though they are being reset. Increment the generation first, so that + * we can assert elsewhere that we never wait for an IDLE IO. While it's + * a bit weird for the state to go backwards for a generation, it's OK + * here, as there cannot be references to the "reborn" IO yet. Can't + * update both at once, so something has to give. + */ + ioh->generation++; + pgaio_io_update_state(ioh, PGAIO_HS_IDLE); + + /* ensure the state update is visible before we reset fields */ + pg_write_barrier(); + + ioh->op = PGAIO_OP_INVALID; + ioh->target = PGAIO_TID_INVALID; + ioh->flags = 0; + ioh->num_callbacks = 0; + ioh->handle_data_len = 0; + ioh->report_return = NULL; + ioh->result = 0; + ioh->distilled_result.status = PGAIO_RS_UNKNOWN; + + /* + * We push the IO to the head of the idle IO list, that seems more cache + * efficient in cases where only a few IOs are used. + */ + dclist_push_head(&pgaio_my_backend->idle_ios, &ioh->node); + + RESUME_INTERRUPTS(); +} + +/* + * Wait for an IO handle to become usable. + * + * This only really is useful for pgaio_io_acquire(). + */ +static void +pgaio_io_wait_for_free(void) +{ + int reclaimed = 0; + + pgaio_debug(DEBUG2, "waiting for free IO with %d pending, %u in-flight, %u idle IOs", + pgaio_my_backend->num_staged_ios, + dclist_count(&pgaio_my_backend->in_flight_ios), + dclist_count(&pgaio_my_backend->idle_ios)); + + /* + * First check if any of our IOs actually have completed - when using + * worker, that'll often be the case. We could do so as part of the loop + * below, but that'd potentially lead us to wait for some IO submitted + * before. + */ + for (int i = 0; i < io_max_concurrency; i++) + { + PgAioHandle *ioh = &pgaio_ctl->io_handles[pgaio_my_backend->io_handle_off + i]; + + if (ioh->state == PGAIO_HS_COMPLETED_SHARED) + { + /* + * Note that no interrupts are processed between the state check + * and the call to reclaim - that's important as otherwise an + * interrupt could have already reclaimed the handle. + * + * Need to ensure that there's no reordering, in the more common + * paths, where we wait for IO, that's done by + * pgaio_io_was_recycled(). + */ + pg_read_barrier(); + pgaio_io_reclaim(ioh); + reclaimed++; + } + } + + if (reclaimed > 0) + return; + + /* + * If we have any unsubmitted IOs, submit them now. We'll start waiting in + * a second, so it's better they're in flight. This also addresses the + * edge-case that all IOs are unsubmitted. + */ + if (pgaio_my_backend->num_staged_ios > 0) + pgaio_submit_staged(); + + /* possibly some IOs finished during submission */ + if (!dclist_is_empty(&pgaio_my_backend->idle_ios)) + return; + + if (dclist_count(&pgaio_my_backend->in_flight_ios) == 0) + ereport(ERROR, + errmsg_internal("no free IOs despite no in-flight IOs"), + errdetail_internal("%d pending, %u in-flight, %u idle IOs", + pgaio_my_backend->num_staged_ios, + dclist_count(&pgaio_my_backend->in_flight_ios), + dclist_count(&pgaio_my_backend->idle_ios))); + + /* + * Wait for the oldest in-flight IO to complete. + * + * XXX: Reusing the general IO wait is suboptimal, we don't need to wait + * for that specific IO to complete, we just need *any* IO to complete. + */ + { + PgAioHandle *ioh = dclist_head_element(PgAioHandle, node, + &pgaio_my_backend->in_flight_ios); + uint64 generation = ioh->generation; + + switch (ioh->state) + { + /* should not be in in-flight list */ + case PGAIO_HS_IDLE: + case PGAIO_HS_DEFINED: + case PGAIO_HS_HANDED_OUT: + case PGAIO_HS_STAGED: + case PGAIO_HS_COMPLETED_LOCAL: + elog(ERROR, "shouldn't get here with io:%d in state %d", + pgaio_io_get_id(ioh), ioh->state); + break; + + case PGAIO_HS_COMPLETED_IO: + case PGAIO_HS_SUBMITTED: + pgaio_debug_io(DEBUG2, ioh, + "waiting for free io with %u in flight", + dclist_count(&pgaio_my_backend->in_flight_ios)); + + /* + * In a more general case this would be racy, because the + * generation could increase after we read ioh->state above. + * But we are only looking at IOs by the current backend and + * the IO can only be recycled by this backend. Even this is + * only OK because we get the handle's generation before + * potentially processing interrupts, e.g. as part of + * pgaio_debug_io(). + */ + pgaio_io_wait(ioh, generation); + break; + + case PGAIO_HS_COMPLETED_SHARED: + + /* + * It's possible that another backend just finished this IO. + * + * Note that no interrupts are processed between the state + * check and the call to reclaim - that's important as + * otherwise an interrupt could have already reclaimed the + * handle. + * + * Need to ensure that there's no reordering, in the more + * common paths, where we wait for IO, that's done by + * pgaio_io_was_recycled(). + */ + pg_read_barrier(); + pgaio_io_reclaim(ioh); + break; + } + + if (dclist_count(&pgaio_my_backend->idle_ios) == 0) + elog(PANIC, "no idle IO after waiting for IO to terminate"); + return; + } +} + +/* + * Internal - code outside of AIO should never need this and it'd be hard for + * such code to be safe. + */ +static PgAioHandle * +pgaio_io_from_wref(PgAioWaitRef *iow, uint64 *ref_generation) +{ + PgAioHandle *ioh; + + Assert(iow->aio_index < pgaio_ctl->io_handle_count); + + ioh = &pgaio_ctl->io_handles[iow->aio_index]; + + *ref_generation = ((uint64) iow->generation_upper) << 32 | + iow->generation_lower; + + Assert(*ref_generation != 0); + + return ioh; +} + +static const char * +pgaio_io_state_get_name(PgAioHandleState s) +{ +#define PGAIO_HS_TOSTR_CASE(sym) case PGAIO_HS_##sym: return #sym + switch (s) + { + PGAIO_HS_TOSTR_CASE(IDLE); + PGAIO_HS_TOSTR_CASE(HANDED_OUT); + PGAIO_HS_TOSTR_CASE(DEFINED); + PGAIO_HS_TOSTR_CASE(STAGED); + PGAIO_HS_TOSTR_CASE(SUBMITTED); + PGAIO_HS_TOSTR_CASE(COMPLETED_IO); + PGAIO_HS_TOSTR_CASE(COMPLETED_SHARED); + PGAIO_HS_TOSTR_CASE(COMPLETED_LOCAL); + } +#undef PGAIO_HS_TOSTR_CASE + + return NULL; /* silence compiler */ +} + +const char * +pgaio_io_get_state_name(PgAioHandle *ioh) +{ + return pgaio_io_state_get_name(ioh->state); +} + +const char * +pgaio_result_status_string(PgAioResultStatus rs) +{ + switch (rs) + { + case PGAIO_RS_UNKNOWN: + return "UNKNOWN"; + case PGAIO_RS_OK: + return "OK"; + case PGAIO_RS_WARNING: + return "WARNING"; + case PGAIO_RS_PARTIAL: + return "PARTIAL"; + case PGAIO_RS_ERROR: + return "ERROR"; + } + + return NULL; /* silence compiler */ +} + + + +/* -------------------------------------------------------------------------------- + * Functions primarily related to IO Wait References + * -------------------------------------------------------------------------------- + */ + +/* + * Mark a wait reference as invalid + */ +void +pgaio_wref_clear(PgAioWaitRef *iow) +{ + iow->aio_index = PG_UINT32_MAX; +} + +/* Is the wait reference valid? */ +bool +pgaio_wref_valid(PgAioWaitRef *iow) +{ + return iow->aio_index != PG_UINT32_MAX; +} + +/* + * Similar to pgaio_io_get_id(), just for wait references. + */ +int +pgaio_wref_get_id(PgAioWaitRef *iow) +{ + Assert(pgaio_wref_valid(iow)); + return iow->aio_index; +} + +/* + * Wait for the IO to have completed. Can be called in any process, not just + * in the issuing backend. + */ +void +pgaio_wref_wait(PgAioWaitRef *iow) +{ + uint64 ref_generation; + PgAioHandle *ioh; + + ioh = pgaio_io_from_wref(iow, &ref_generation); + + pgaio_io_wait(ioh, ref_generation); +} + +/* + * Check if the referenced IO completed, without blocking. + */ +bool +pgaio_wref_check_done(PgAioWaitRef *iow) +{ + uint64 ref_generation; + PgAioHandleState state; + bool am_owner; + PgAioHandle *ioh; + + ioh = pgaio_io_from_wref(iow, &ref_generation); + + if (pgaio_io_was_recycled(ioh, ref_generation, &state)) + return true; + + if (state == PGAIO_HS_IDLE) + return true; + + am_owner = ioh->owner_procno == MyProcNumber; + + if (state == PGAIO_HS_COMPLETED_SHARED || + state == PGAIO_HS_COMPLETED_LOCAL) + { + /* + * Note that no interrupts are processed between + * pgaio_io_was_recycled() and this check - that's important as + * otherwise an interrupt could have already reclaimed the handle. + */ + if (am_owner) + pgaio_io_reclaim(ioh); + return true; + } + + /* + * XXX: It likely would be worth checking in with the io method, to give + * the IO method a chance to check if there are completion events queued. + */ + + return false; +} + + + +/* -------------------------------------------------------------------------------- + * Actions on multiple IOs. + * -------------------------------------------------------------------------------- + */ + +/* + * Submit IOs in batches going forward. + * + * Submitting multiple IOs at once can be substantially faster than doing so + * one-by-one. At the same time, submitting multiple IOs at once requires more + * care to avoid deadlocks. + * + * Consider backend A staging an IO for buffer 1 and then trying to start IO + * on buffer 2, while backend B does the inverse. If A submitted the IO before + * moving on to buffer 2, this works just fine, B will wait for the IO to + * complete. But if batching were used, each backend will wait for IO that has + * not yet been submitted to complete, i.e. forever. + * + * End batch submission mode with pgaio_exit_batchmode(). (Throwing errors is + * allowed; error recovery will end the batch.) + * + * To avoid deadlocks, code needs to ensure that it will not wait for another + * backend while there is unsubmitted IO. E.g. by using conditional lock + * acquisition when acquiring buffer locks. To check if there currently are + * staged IOs, call pgaio_have_staged() and to submit all staged IOs call + * pgaio_submit_staged(). + * + * It is not allowed to enter batchmode while already in batchmode, it's + * unlikely to ever be needed, as code needs to be explicitly aware of being + * called in batchmode, to avoid the deadlock risks explained above. + * + * Note that IOs may get submitted before pgaio_exit_batchmode() is called, + * e.g. because too many IOs have been staged or because pgaio_submit_staged() + * was called. + */ +void +pgaio_enter_batchmode(void) +{ + if (pgaio_my_backend->in_batchmode) + elog(ERROR, "starting batch while batch already in progress"); + pgaio_my_backend->in_batchmode = true; +} + +/* + * Stop submitting IOs in batches. + */ +void +pgaio_exit_batchmode(void) +{ + Assert(pgaio_my_backend->in_batchmode); + + pgaio_submit_staged(); + pgaio_my_backend->in_batchmode = false; +} + +/* + * Are there staged but unsubmitted IOs? + * + * See comment above pgaio_enter_batchmode() for why code may need to check if + * there is IO in that state. + */ +bool +pgaio_have_staged(void) +{ + Assert(pgaio_my_backend->in_batchmode || + pgaio_my_backend->num_staged_ios == 0); + return pgaio_my_backend->num_staged_ios > 0; +} + +/* + * Submit all staged but not yet submitted IOs. + * + * Unless in batch mode, this never needs to be called, as IOs get submitted + * as soon as possible. While in batchmode pgaio_submit_staged() can be called + * before waiting on another backend, to avoid the risk of deadlocks. See + * pgaio_enter_batchmode(). + */ +void +pgaio_submit_staged(void) +{ + int total_submitted = 0; + int did_submit; + + if (pgaio_my_backend->num_staged_ios == 0) + return; + + + START_CRIT_SECTION(); + + did_submit = pgaio_method_ops->submit(pgaio_my_backend->num_staged_ios, + pgaio_my_backend->staged_ios); + + END_CRIT_SECTION(); + + total_submitted += did_submit; + + Assert(total_submitted == did_submit); + + pgaio_my_backend->num_staged_ios = 0; + + pgaio_debug(DEBUG4, + "aio: submitted %d IOs", + total_submitted); +} + + + +/* -------------------------------------------------------------------------------- + * Other + * -------------------------------------------------------------------------------- + */ + + +/* + * Perform AIO related cleanup after an error. + * + * This should be called early in the error recovery paths, as later steps may + * need to issue AIO (e.g. to record a transaction abort WAL record). + */ +void +pgaio_error_cleanup(void) +{ + /* + * It is possible that code errored out after pgaio_enter_batchmode() but + * before pgaio_exit_batchmode() was called. In that case we need to + * submit the IO now. + */ + if (pgaio_my_backend->in_batchmode) + { + pgaio_my_backend->in_batchmode = false; + + pgaio_submit_staged(); + } + + /* + * As we aren't in batchmode, there shouldn't be any unsubmitted IOs. + */ + Assert(pgaio_my_backend->num_staged_ios == 0); +} + +/* + * Perform AIO related checks at (sub-)transactional boundaries. + * + * This should be called late during (sub-)transactional commit/abort, after + * all steps that might need to perform AIO, so that we can verify that the + * AIO subsystem is in a valid state at the end of a transaction. + */ +void +AtEOXact_Aio(bool is_commit) +{ + /* + * We should never be in batch mode at transactional boundaries. In case + * an error was thrown while in batch mode, pgaio_error_cleanup() should + * have exited batchmode. + * + * In case we are in batchmode somehow, make sure to submit all staged + * IOs, other backends may need them to complete to continue. + */ + if (pgaio_my_backend->in_batchmode) + { + pgaio_error_cleanup(); + elog(WARNING, "open AIO batch at end of (sub-)transaction"); + } + + /* + * As we aren't in batchmode, there shouldn't be any unsubmitted IOs. + */ + Assert(pgaio_my_backend->num_staged_ios == 0); +} + +/* + * Need to submit staged but not yet submitted IOs using the fd, otherwise + * the IO would end up targeting something bogus. + */ +void +pgaio_closing_fd(int fd) +{ + /* + * Might be called before AIO is initialized or in a subprocess that + * doesn't use AIO. + */ + if (!pgaio_my_backend) + return; + + /* + * For now just submit all staged IOs - we could be more selective, but + * it's probably not worth it. + */ + if (pgaio_my_backend->num_staged_ios > 0) + { + pgaio_debug(DEBUG2, + "submitting %d IOs before FD %d gets closed", + pgaio_my_backend->num_staged_ios, fd); + pgaio_submit_staged(); + } + + /* + * If requested by the IO method, wait for all IOs that use the + * to-be-closed FD. + */ + if (pgaio_method_ops->wait_on_fd_before_close) + { + /* + * As waiting for one IO to complete may complete multiple IOs, we + * can't just use a mutable list iterator. The maximum number of + * in-flight IOs is fairly small, so just restart the loop after + * waiting for an IO. + */ + while (!dclist_is_empty(&pgaio_my_backend->in_flight_ios)) + { + dlist_iter iter; + PgAioHandle *ioh = NULL; + uint64 generation; + + dclist_foreach(iter, &pgaio_my_backend->in_flight_ios) + { + ioh = dclist_container(PgAioHandle, node, iter.cur); + + generation = ioh->generation; + + if (pgaio_io_uses_fd(ioh, fd)) + break; + else + ioh = NULL; + } + + if (!ioh) + break; + + pgaio_debug_io(DEBUG2, ioh, + "waiting for IO before FD %d gets closed, %u in-flight IOs", + fd, dclist_count(&pgaio_my_backend->in_flight_ios)); + + /* see comment in pgaio_io_wait_for_free() about raciness */ + pgaio_io_wait(ioh, generation); + } + } +} + +/* + * Registered as before_shmem_exit() callback in pgaio_init_backend() + */ +void +pgaio_shutdown(int code, Datum arg) +{ + Assert(pgaio_my_backend); + Assert(!pgaio_my_backend->handed_out_io); + + /* first clean up resources as we would at a transaction boundary */ + AtEOXact_Aio(code == 0); + + /* + * Before exiting, make sure that all IOs are finished. That has two main + * purposes: + * + * - Some kernel-level AIO mechanisms don't deal well with the issuer of + * an AIO exiting before IO completed + * + * - It'd be confusing to see partially finished IOs in stats views etc + */ + while (!dclist_is_empty(&pgaio_my_backend->in_flight_ios)) + { + PgAioHandle *ioh = dclist_head_element(PgAioHandle, node, &pgaio_my_backend->in_flight_ios); + uint64 generation = ioh->generation; + + pgaio_debug_io(DEBUG2, ioh, + "waiting for IO to complete during shutdown, %u in-flight IOs", + dclist_count(&pgaio_my_backend->in_flight_ios)); + + /* see comment in pgaio_io_wait_for_free() about raciness */ + pgaio_io_wait(ioh, generation); + } + + pgaio_my_backend = NULL; +} + +void +assign_io_method(int newval, void *extra) +{ + Assert(pgaio_method_ops_table[newval] != NULL); + Assert(newval < lengthof(io_method_options)); + + pgaio_method_ops = pgaio_method_ops_table[newval]; +} + +bool +check_io_max_concurrency(int *newval, void **extra, GucSource source) +{ + if (*newval == -1) + { + /* + * Auto-tuning will be applied later during startup, as auto-tuning + * depends on the value of various GUCs. + */ + return true; + } + else if (*newval == 0) + { + GUC_check_errdetail("Only -1 or values bigger than 0 are valid."); + return false; + } + + return true; +} diff --git a/src/backend/storage/aio/aio_callback.c b/src/backend/storage/aio/aio_callback.c new file mode 100644 index 0000000000000..03c9bba080267 --- /dev/null +++ b/src/backend/storage/aio/aio_callback.c @@ -0,0 +1,333 @@ +/*------------------------------------------------------------------------- + * + * aio_callback.c + * AIO - Functionality related to callbacks that can be registered on IO + * Handles + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio_callback.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/bufmgr.h" +#include "storage/md.h" + + +/* just to have something to put into aio_handle_cbs */ +static const PgAioHandleCallbacks aio_invalid_cb = {0}; + +typedef struct PgAioHandleCallbacksEntry +{ + const PgAioHandleCallbacks *const cb; + const char *const name; +} PgAioHandleCallbacksEntry; + +/* + * Callback definition for the callbacks that can be registered on an IO + * handle. See PgAioHandleCallbackID's definition for an explanation for why + * callbacks are not identified by a pointer. + */ +static const PgAioHandleCallbacksEntry aio_handle_cbs[] = { +#define CALLBACK_ENTRY(id, callback) [id] = {.cb = &callback, .name = #callback} + CALLBACK_ENTRY(PGAIO_HCB_INVALID, aio_invalid_cb), + + CALLBACK_ENTRY(PGAIO_HCB_MD_READV, aio_md_readv_cb), + + CALLBACK_ENTRY(PGAIO_HCB_SHARED_BUFFER_READV, aio_shared_buffer_readv_cb), + + CALLBACK_ENTRY(PGAIO_HCB_LOCAL_BUFFER_READV, aio_local_buffer_readv_cb), +#undef CALLBACK_ENTRY +}; + + + +/* -------------------------------------------------------------------------------- + * Public callback related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +/* + * Register callback for the IO handle. + * + * Only a limited number (PGAIO_HANDLE_MAX_CALLBACKS) of callbacks can be + * registered for each IO. + * + * Callbacks need to be registered before [indirectly] calling + * pgaio_io_start_*(), as the IO may be executed immediately. + * + * A callback can be passed a small bit of data, e.g. to indicate whether to + * zero a buffer if it is invalid. + * + * + * Note that callbacks are executed in critical sections. This is necessary + * to be able to execute IO in critical sections (consider e.g. WAL + * logging). To perform AIO we first need to acquire a handle, which, if there + * are no free handles, requires waiting for IOs to complete and to execute + * their completion callbacks. + * + * Callbacks may be executed in the issuing backend but also in another + * backend (because that backend is waiting for the IO) or in IO workers (if + * io_method=worker is used). + * + * + * See PgAioHandleCallbackID's definition for an explanation for why + * callbacks are not identified by a pointer. + */ +void +pgaio_io_register_callbacks(PgAioHandle *ioh, PgAioHandleCallbackID cb_id, + uint8 cb_data) +{ + const PgAioHandleCallbacksEntry *ce = &aio_handle_cbs[cb_id]; + + Assert(cb_id <= PGAIO_HCB_MAX); + if (cb_id >= lengthof(aio_handle_cbs)) + elog(ERROR, "callback %d is out of range", cb_id); + if (aio_handle_cbs[cb_id].cb->complete_shared == NULL && + aio_handle_cbs[cb_id].cb->complete_local == NULL) + elog(ERROR, "callback %d does not have a completion callback", cb_id); + if (ioh->num_callbacks >= PGAIO_HANDLE_MAX_CALLBACKS) + elog(PANIC, "too many callbacks, the max is %d", + PGAIO_HANDLE_MAX_CALLBACKS); + ioh->callbacks[ioh->num_callbacks] = cb_id; + ioh->callbacks_data[ioh->num_callbacks] = cb_data; + + pgaio_debug_io(DEBUG3, ioh, + "adding cb #%d, id %d/%s", + ioh->num_callbacks + 1, + cb_id, ce->name); + + ioh->num_callbacks++; +} + +/* + * Associate an array of data with the Handle. This is e.g. useful to the + * transport knowledge about which buffers a multi-block IO affects to + * completion callbacks. + * + * Right now this can be done only once for each IO, even though multiple + * callbacks can be registered. There aren't any known usecases requiring more + * and the required amount of shared memory does add up, so it doesn't seem + * worth multiplying memory usage by PGAIO_HANDLE_MAX_CALLBACKS. + */ +void +pgaio_io_set_handle_data_64(PgAioHandle *ioh, uint64 *data, uint8 len) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(ioh->handle_data_len == 0); + Assert(len <= PG_IOV_MAX); + Assert(len <= io_max_combine_limit); + + for (int i = 0; i < len; i++) + pgaio_ctl->handle_data[ioh->iovec_off + i] = data[i]; + ioh->handle_data_len = len; +} + +/* + * Convenience version of pgaio_io_set_handle_data_64() that converts a 32bit + * array to a 64bit array. Without it callers would end up needing to + * open-code equivalent code. + */ +void +pgaio_io_set_handle_data_32(PgAioHandle *ioh, uint32 *data, uint8 len) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(ioh->handle_data_len == 0); + Assert(len <= PG_IOV_MAX); + Assert(len <= io_max_combine_limit); + + for (int i = 0; i < len; i++) + pgaio_ctl->handle_data[ioh->iovec_off + i] = data[i]; + ioh->handle_data_len = len; +} + +/* + * Return data set with pgaio_io_set_handle_data_*(). + */ +uint64 * +pgaio_io_get_handle_data(PgAioHandle *ioh, uint8 *len) +{ + Assert(ioh->handle_data_len > 0); + + *len = ioh->handle_data_len; + + return &pgaio_ctl->handle_data[ioh->iovec_off]; +} + + + +/* -------------------------------------------------------------------------------- + * Public IO Result related functions + * -------------------------------------------------------------------------------- + */ + +void +pgaio_result_report(PgAioResult result, const PgAioTargetData *target_data, int elevel) +{ + PgAioHandleCallbackID cb_id = result.id; + const PgAioHandleCallbacksEntry *ce = &aio_handle_cbs[cb_id]; + + Assert(result.status != PGAIO_RS_UNKNOWN); + Assert(result.status != PGAIO_RS_OK); + + if (ce->cb->report == NULL) + elog(ERROR, "callback %d/%s does not have report callback", + result.id, ce->name); + + ce->cb->report(result, target_data, elevel); +} + + + +/* -------------------------------------------------------------------------------- + * Internal callback related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +/* + * Internal function which invokes ->stage for all the registered callbacks. + */ +void +pgaio_io_call_stage(PgAioHandle *ioh) +{ + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + Assert(ioh->op > PGAIO_OP_INVALID && ioh->op < PGAIO_OP_COUNT); + + for (int i = ioh->num_callbacks; i > 0; i--) + { + PgAioHandleCallbackID cb_id = ioh->callbacks[i - 1]; + uint8 cb_data = ioh->callbacks_data[i - 1]; + const PgAioHandleCallbacksEntry *ce = &aio_handle_cbs[cb_id]; + + if (!ce->cb->stage) + continue; + + pgaio_debug_io(DEBUG3, ioh, + "calling cb #%d %d/%s->stage(%u)", + i, cb_id, ce->name, cb_data); + ce->cb->stage(ioh, cb_data); + } +} + +/* + * Internal function which invokes ->complete_shared for all the registered + * callbacks. + */ +void +pgaio_io_call_complete_shared(PgAioHandle *ioh) +{ + PgAioResult result; + + START_CRIT_SECTION(); + + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + Assert(ioh->op > PGAIO_OP_INVALID && ioh->op < PGAIO_OP_COUNT); + + result.status = PGAIO_RS_OK; /* low level IO is always considered OK */ + result.result = ioh->result; + result.id = PGAIO_HCB_INVALID; + result.error_data = 0; + + /* + * Call callbacks with the last registered (innermost) callback first. + * Each callback can modify the result forwarded to the next callback. + */ + for (int i = ioh->num_callbacks; i > 0; i--) + { + PgAioHandleCallbackID cb_id = ioh->callbacks[i - 1]; + uint8 cb_data = ioh->callbacks_data[i - 1]; + const PgAioHandleCallbacksEntry *ce = &aio_handle_cbs[cb_id]; + + if (!ce->cb->complete_shared) + continue; + + pgaio_debug_io(DEBUG4, ioh, + "calling cb #%d, id %d/%s->complete_shared(%u) with distilled result: (status %s, id %u, error_data %d, result %d)", + i, cb_id, ce->name, + cb_data, + pgaio_result_status_string(result.status), + result.id, result.error_data, result.result); + result = ce->cb->complete_shared(ioh, result, cb_data); + + /* the callback should never transition to unknown */ + Assert(result.status != PGAIO_RS_UNKNOWN); + } + + ioh->distilled_result = result; + + pgaio_debug_io(DEBUG3, ioh, + "after shared completion: distilled result: (status %s, id %u, error_data: %d, result %d), raw_result: %d", + pgaio_result_status_string(result.status), + result.id, result.error_data, result.result, + ioh->result); + + END_CRIT_SECTION(); +} + +/* + * Internal function which invokes ->complete_local for all the registered + * callbacks. + * + * Returns ioh->distilled_result after, possibly, being modified by local + * callbacks. + * + * XXX: It'd be nice to deduplicate with pgaio_io_call_complete_shared(). + */ +PgAioResult +pgaio_io_call_complete_local(PgAioHandle *ioh) +{ + PgAioResult result; + + START_CRIT_SECTION(); + + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + Assert(ioh->op > PGAIO_OP_INVALID && ioh->op < PGAIO_OP_COUNT); + + /* start with distilled result from shared callback */ + result = ioh->distilled_result; + Assert(result.status != PGAIO_RS_UNKNOWN); + + for (int i = ioh->num_callbacks; i > 0; i--) + { + PgAioHandleCallbackID cb_id = ioh->callbacks[i - 1]; + uint8 cb_data = ioh->callbacks_data[i - 1]; + const PgAioHandleCallbacksEntry *ce = &aio_handle_cbs[cb_id]; + + if (!ce->cb->complete_local) + continue; + + pgaio_debug_io(DEBUG4, ioh, + "calling cb #%d, id %d/%s->complete_local(%u) with distilled result: status %s, id %u, error_data %d, result %d", + i, cb_id, ce->name, cb_data, + pgaio_result_status_string(result.status), + result.id, result.error_data, result.result); + result = ce->cb->complete_local(ioh, result, cb_data); + + /* the callback should never transition to unknown */ + Assert(result.status != PGAIO_RS_UNKNOWN); + } + + /* + * Note that we don't save the result in ioh->distilled_result, the local + * callback's result should not ever matter to other waiters. However, the + * local backend does care, so we return the result as modified by local + * callbacks, which then can be passed to ioh->report_return->result. + */ + pgaio_debug_io(DEBUG3, ioh, + "after local completion: result: (status %s, id %u, error_data %d, result %d), raw_result: %d", + pgaio_result_status_string(result.status), + result.id, result.error_data, result.result, + ioh->result); + + END_CRIT_SECTION(); + + return result; +} diff --git a/src/backend/storage/aio/aio_funcs.c b/src/backend/storage/aio/aio_funcs.c new file mode 100644 index 0000000000000..584e683371a31 --- /dev/null +++ b/src/backend/storage/aio/aio_funcs.c @@ -0,0 +1,230 @@ +/*------------------------------------------------------------------------- + * + * aio_funcs.c + * AIO - SQL interface for AIO + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio_funcs.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "funcapi.h" +#include "nodes/execnodes.h" +#include "port/atomics.h" +#include "storage/aio_internal.h" +#include "storage/lock.h" +#include "storage/proc.h" +#include "storage/procnumber.h" +#include "utils/builtins.h" +#include "utils/fmgrprotos.h" +#include "utils/tuplestore.h" + + +/* + * Byte length of an iovec. + */ +static size_t +iov_byte_length(const struct iovec *iov, int cnt) +{ + size_t len = 0; + + for (int i = 0; i < cnt; i++) + { + len += iov[i].iov_len; + } + + return len; +} + +Datum +pg_get_aios(PG_FUNCTION_ARGS) +{ + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + + InitMaterializedSRF(fcinfo, 0); + +#define PG_GET_AIOS_COLS 15 + + for (uint64 i = 0; i < pgaio_ctl->io_handle_count; i++) + { + PgAioHandle *live_ioh = &pgaio_ctl->io_handles[i]; + uint32 ioh_id = pgaio_io_get_id(live_ioh); + Datum values[PG_GET_AIOS_COLS] = {0}; + bool nulls[PG_GET_AIOS_COLS] = {0}; + ProcNumber owner; + PGPROC *owner_proc; + int32 owner_pid; + PgAioHandleState start_state; + uint64 start_generation; + PgAioHandle ioh_copy; + struct iovec iov_copy[PG_IOV_MAX]; + + + /* + * There is no lock that could prevent the state of the IO to advance + * concurrently - and we don't want to introduce one, as that would + * introduce atomics into a very common path. Instead we + * + * 1) Determine the state + generation of the IO. + * + * 2) Copy the IO to local memory. + * + * 3) Check if state or generation of the IO changed. If the state + * changed, retry, if the generation changed don't display the IO. + */ + + /* 1) from above */ + start_generation = live_ioh->generation; + + /* + * Retry at this point, so we can accept changing states, but not + * changing generations. + */ +retry: + pg_read_barrier(); + start_state = live_ioh->state; + + if (start_state == PGAIO_HS_IDLE) + continue; + + /* 2) from above */ + memcpy(&ioh_copy, live_ioh, sizeof(PgAioHandle)); + + /* + * Safe to copy even if no iovec is used - we always reserve the + * required space. + */ + memcpy(&iov_copy, &pgaio_ctl->iovecs[ioh_copy.iovec_off], + PG_IOV_MAX * sizeof(struct iovec)); + + /* + * Copy information about owner before 3) below, if the process exited + * it'd have to wait for the IO to finish first, which we would detect + * in 3). + */ + owner = ioh_copy.owner_procno; + owner_proc = GetPGProcByNumber(owner); + owner_pid = owner_proc->pid; + + /* 3) from above */ + pg_read_barrier(); + + /* + * The IO completed and a new one was started with the same ID. Don't + * display it - it really started after this function was called. + * There be a risk of a livelock if we just retried endlessly, if IOs + * complete very quickly. + */ + if (live_ioh->generation != start_generation) + continue; + + /* + * The IO's state changed while we were "rendering" it. Just start + * from scratch. There's no risk of a livelock here, as an IO has a + * limited sets of states it can be in, and state changes go only in a + * single direction. + */ + if (live_ioh->state != start_state) + goto retry; + + /* + * Now that we have copied the IO into local memory and checked that + * it's still in the same state, we are not allowed to access "live" + * memory anymore. To make it slightly easier to catch such cases, set + * the "live" pointers to NULL. + */ + live_ioh = NULL; + owner_proc = NULL; + + + /* column: owning pid */ + if (owner_pid != 0) + values[0] = Int32GetDatum(owner_pid); + else + nulls[0] = false; + + /* column: IO's id */ + values[1] = ioh_id; + + /* column: IO's generation */ + values[2] = Int64GetDatum(start_generation); + + /* column: IO's state */ + values[3] = CStringGetTextDatum(pgaio_io_get_state_name(&ioh_copy)); + + /* + * If the IO is in PGAIO_HS_HANDED_OUT state, none of the following + * fields are valid yet (or are in the process of being set). + * Therefore we don't want to display any other columns. + */ + if (start_state == PGAIO_HS_HANDED_OUT) + { + memset(nulls + 4, 1, (lengthof(nulls) - 4) * sizeof(bool)); + goto display; + } + + /* column: IO's operation */ + values[4] = CStringGetTextDatum(pgaio_io_get_op_name(&ioh_copy)); + + /* columns: details about the IO's operation (offset, length) */ + switch (ioh_copy.op) + { + case PGAIO_OP_INVALID: + nulls[5] = true; + nulls[6] = true; + break; + case PGAIO_OP_READV: + values[5] = Int64GetDatum(ioh_copy.op_data.read.offset); + values[6] = + Int64GetDatum(iov_byte_length(iov_copy, ioh_copy.op_data.read.iov_length)); + break; + case PGAIO_OP_WRITEV: + values[5] = Int64GetDatum(ioh_copy.op_data.write.offset); + values[6] = + Int64GetDatum(iov_byte_length(iov_copy, ioh_copy.op_data.write.iov_length)); + break; + } + + /* column: IO's target */ + values[7] = CStringGetTextDatum(pgaio_io_get_target_name(&ioh_copy)); + + /* column: length of IO's data array */ + values[8] = Int16GetDatum(ioh_copy.handle_data_len); + + /* column: raw result (i.e. some form of syscall return value) */ + if (start_state == PGAIO_HS_COMPLETED_IO + || start_state == PGAIO_HS_COMPLETED_SHARED + || start_state == PGAIO_HS_COMPLETED_LOCAL) + values[9] = Int32GetDatum(ioh_copy.result); + else + nulls[9] = true; + + /* + * column: result in the higher level representation (unknown if not + * finished) + */ + values[10] = + CStringGetTextDatum(pgaio_result_status_string(ioh_copy.distilled_result.status)); + + /* column: target description */ + values[11] = CStringGetTextDatum(pgaio_io_get_target_description(&ioh_copy)); + + /* columns: one for each flag */ + values[12] = BoolGetDatum(ioh_copy.flags & PGAIO_HF_SYNCHRONOUS); + values[13] = BoolGetDatum(ioh_copy.flags & PGAIO_HF_REFERENCES_LOCAL); + values[14] = BoolGetDatum(ioh_copy.flags & PGAIO_HF_BUFFERED); + +display: + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); + } + + return (Datum) 0; +} diff --git a/src/backend/storage/aio/aio_init.c b/src/backend/storage/aio/aio_init.c new file mode 100644 index 0000000000000..885c3940c6626 --- /dev/null +++ b/src/backend/storage/aio/aio_init.c @@ -0,0 +1,239 @@ +/*------------------------------------------------------------------------- + * + * aio_init.c + * AIO - Subsystem Initialization + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio_init.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/aio_subsys.h" +#include "storage/bufmgr.h" +#include "storage/io_worker.h" +#include "storage/ipc.h" +#include "storage/proc.h" +#include "storage/shmem.h" +#include "utils/guc.h" + + + +static Size +AioCtlShmemSize(void) +{ + Size sz; + + /* pgaio_ctl itself */ + sz = offsetof(PgAioCtl, io_handles); + + return sz; +} + +static uint32 +AioProcs(void) +{ + /* + * While AIO workers don't need their own AIO context, we can't currently + * guarantee nothing gets assigned to the a ProcNumber for an IO worker if + * we just subtracted MAX_IO_WORKERS. + */ + return MaxBackends + NUM_AUXILIARY_PROCS; +} + +static Size +AioBackendShmemSize(void) +{ + return mul_size(AioProcs(), sizeof(PgAioBackend)); +} + +static Size +AioHandleShmemSize(void) +{ + Size sz; + + /* verify AioChooseMaxConcurrency() did its thing */ + Assert(io_max_concurrency > 0); + + /* io handles */ + sz = mul_size(AioProcs(), + mul_size(io_max_concurrency, sizeof(PgAioHandle))); + + return sz; +} + +static Size +AioHandleIOVShmemSize(void) +{ + /* each IO handle can have up to io_max_combine_limit iovec objects */ + return mul_size(sizeof(struct iovec), + mul_size(mul_size(io_max_combine_limit, AioProcs()), + io_max_concurrency)); +} + +static Size +AioHandleDataShmemSize(void) +{ + /* each buffer referenced by an iovec can have associated data */ + return mul_size(sizeof(uint64), + mul_size(mul_size(io_max_combine_limit, AioProcs()), + io_max_concurrency)); +} + +/* + * Choose a suitable value for io_max_concurrency. + * + * It's unlikely that we could have more IOs in flight than buffers that we + * would be allowed to pin. + * + * On the upper end, apply a cap too - just because shared_buffers is large, + * it doesn't make sense have millions of buffers undergo IO concurrently. + */ +static int +AioChooseMaxConcurrency(void) +{ + uint32 max_backends; + int max_proportional_pins; + + /* Similar logic to LimitAdditionalPins() */ + max_backends = MaxBackends + NUM_AUXILIARY_PROCS; + max_proportional_pins = NBuffers / max_backends; + + max_proportional_pins = Max(max_proportional_pins, 1); + + /* apply upper limit */ + return Min(max_proportional_pins, 64); +} + +Size +AioShmemSize(void) +{ + Size sz = 0; + + /* + * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT. + * However, if the DBA explicitly set io_max_concurrency = -1 in the + * config file, then PGC_S_DYNAMIC_DEFAULT will fail to override that and + * we must force the matter with PGC_S_OVERRIDE. + */ + if (io_max_concurrency == -1) + { + char buf[32]; + + snprintf(buf, sizeof(buf), "%d", AioChooseMaxConcurrency()); + SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER, + PGC_S_DYNAMIC_DEFAULT); + if (io_max_concurrency == -1) /* failed to apply it? */ + SetConfigOption("io_max_concurrency", buf, PGC_POSTMASTER, + PGC_S_OVERRIDE); + } + + sz = add_size(sz, AioCtlShmemSize()); + sz = add_size(sz, AioBackendShmemSize()); + sz = add_size(sz, AioHandleShmemSize()); + sz = add_size(sz, AioHandleIOVShmemSize()); + sz = add_size(sz, AioHandleDataShmemSize()); + + /* Reserve space for method specific resources. */ + if (pgaio_method_ops->shmem_size) + sz = add_size(sz, pgaio_method_ops->shmem_size()); + + return sz; +} + +void +AioShmemInit(void) +{ + bool found; + uint32 io_handle_off = 0; + uint32 iovec_off = 0; + uint32 per_backend_iovecs = io_max_concurrency * io_max_combine_limit; + + pgaio_ctl = (PgAioCtl *) + ShmemInitStruct("AioCtl", AioCtlShmemSize(), &found); + + if (found) + goto out; + + memset(pgaio_ctl, 0, AioCtlShmemSize()); + + pgaio_ctl->io_handle_count = AioProcs() * io_max_concurrency; + pgaio_ctl->iovec_count = AioProcs() * per_backend_iovecs; + + pgaio_ctl->backend_state = (PgAioBackend *) + ShmemInitStruct("AioBackend", AioBackendShmemSize(), &found); + + pgaio_ctl->io_handles = (PgAioHandle *) + ShmemInitStruct("AioHandle", AioHandleShmemSize(), &found); + + pgaio_ctl->iovecs = (struct iovec *) + ShmemInitStruct("AioHandleIOV", AioHandleIOVShmemSize(), &found); + pgaio_ctl->handle_data = (uint64 *) + ShmemInitStruct("AioHandleData", AioHandleDataShmemSize(), &found); + + for (int procno = 0; procno < AioProcs(); procno++) + { + PgAioBackend *bs = &pgaio_ctl->backend_state[procno]; + + bs->io_handle_off = io_handle_off; + io_handle_off += io_max_concurrency; + + dclist_init(&bs->idle_ios); + memset(bs->staged_ios, 0, sizeof(PgAioHandle *) * PGAIO_SUBMIT_BATCH_SIZE); + dclist_init(&bs->in_flight_ios); + + /* initialize per-backend IOs */ + for (int i = 0; i < io_max_concurrency; i++) + { + PgAioHandle *ioh = &pgaio_ctl->io_handles[bs->io_handle_off + i]; + + ioh->generation = 1; + ioh->owner_procno = procno; + ioh->iovec_off = iovec_off; + ioh->handle_data_len = 0; + ioh->report_return = NULL; + ioh->resowner = NULL; + ioh->num_callbacks = 0; + ioh->distilled_result.status = PGAIO_RS_UNKNOWN; + ioh->flags = 0; + + ConditionVariableInit(&ioh->cv); + + dclist_push_tail(&bs->idle_ios, &ioh->node); + iovec_off += io_max_combine_limit; + } + } + +out: + /* Initialize IO method specific resources. */ + if (pgaio_method_ops->shmem_init) + pgaio_method_ops->shmem_init(!found); +} + +void +pgaio_init_backend(void) +{ + /* shouldn't be initialized twice */ + Assert(!pgaio_my_backend); + + if (MyBackendType == B_IO_WORKER) + return; + + if (MyProc == NULL || MyProcNumber >= AioProcs()) + elog(ERROR, "aio requires a normal PGPROC"); + + pgaio_my_backend = &pgaio_ctl->backend_state[MyProcNumber]; + + if (pgaio_method_ops->init_backend) + pgaio_method_ops->init_backend(); + + before_shmem_exit(pgaio_shutdown, 0); +} diff --git a/src/backend/storage/aio/aio_io.c b/src/backend/storage/aio/aio_io.c new file mode 100644 index 0000000000000..520b5077df25a --- /dev/null +++ b/src/backend/storage/aio/aio_io.c @@ -0,0 +1,235 @@ +/*------------------------------------------------------------------------- + * + * aio_io.c + * AIO - Low Level IO Handling + * + * Functions related to associating IO operations to IO Handles and IO-method + * independent support functions for actually performing IO. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio_io.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/fd.h" +#include "utils/wait_event.h" + + +static void pgaio_io_before_start(PgAioHandle *ioh); + + + +/* -------------------------------------------------------------------------------- + * Public IO related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +/* + * Scatter/gather IO needs to associate an iovec with the Handle. To support + * worker mode this data needs to be in shared memory. + */ +int +pgaio_io_get_iovec(PgAioHandle *ioh, struct iovec **iov) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + + *iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + + return PG_IOV_MAX; +} + +PgAioOp +pgaio_io_get_op(PgAioHandle *ioh) +{ + return ioh->op; +} + +PgAioOpData * +pgaio_io_get_op_data(PgAioHandle *ioh) +{ + return &ioh->op_data; +} + + + +/* -------------------------------------------------------------------------------- + * "Start" routines for individual IO operations + * + * These are called by the code actually initiating an IO, to associate the IO + * specific data with an AIO handle. + * + * Each of the "start" routines first needs to call pgaio_io_before_start(), + * then fill IO specific fields in the handle and then finally call + * pgaio_io_stage(). + * -------------------------------------------------------------------------------- + */ + +void +pgaio_io_start_readv(PgAioHandle *ioh, + int fd, int iovcnt, uint64 offset) +{ + pgaio_io_before_start(ioh); + + ioh->op_data.read.fd = fd; + ioh->op_data.read.offset = offset; + ioh->op_data.read.iov_length = iovcnt; + + pgaio_io_stage(ioh, PGAIO_OP_READV); +} + +void +pgaio_io_start_writev(PgAioHandle *ioh, + int fd, int iovcnt, uint64 offset) +{ + pgaio_io_before_start(ioh); + + ioh->op_data.write.fd = fd; + ioh->op_data.write.offset = offset; + ioh->op_data.write.iov_length = iovcnt; + + pgaio_io_stage(ioh, PGAIO_OP_WRITEV); +} + + + +/* -------------------------------------------------------------------------------- + * Internal IO related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +/* + * Execute IO operation synchronously. This is implemented here, not in + * method_sync.c, because other IO methods also might use it / fall back to + * it. + */ +void +pgaio_io_perform_synchronously(PgAioHandle *ioh) +{ + ssize_t result = 0; + struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + + START_CRIT_SECTION(); + + /* Perform IO. */ + switch (ioh->op) + { + case PGAIO_OP_READV: + pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_READ); + result = pg_preadv(ioh->op_data.read.fd, iov, + ioh->op_data.read.iov_length, + ioh->op_data.read.offset); + pgstat_report_wait_end(); + break; + case PGAIO_OP_WRITEV: + pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_WRITE); + result = pg_pwritev(ioh->op_data.write.fd, iov, + ioh->op_data.write.iov_length, + ioh->op_data.write.offset); + pgstat_report_wait_end(); + break; + case PGAIO_OP_INVALID: + elog(ERROR, "trying to execute invalid IO operation"); + } + + ioh->result = result < 0 ? -errno : result; + + pgaio_io_process_completion(ioh, ioh->result); + + END_CRIT_SECTION(); +} + +/* + * Helper function to be called by IO operation preparation functions, before + * any data in the handle is set. Mostly to centralize assertions. + */ +static void +pgaio_io_before_start(PgAioHandle *ioh) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(pgaio_my_backend->handed_out_io == ioh); + Assert(pgaio_io_has_target(ioh)); + Assert(ioh->op == PGAIO_OP_INVALID); + + /* + * Otherwise the FDs referenced by the IO could be closed due to interrupt + * processing. + */ + Assert(!INTERRUPTS_CAN_BE_PROCESSED()); +} + +/* + * Could be made part of the public interface, but it's not clear there's + * really a use case for that. + */ +const char * +pgaio_io_get_op_name(PgAioHandle *ioh) +{ + Assert(ioh->op >= 0 && ioh->op < PGAIO_OP_COUNT); + + switch (ioh->op) + { + case PGAIO_OP_INVALID: + return "invalid"; + case PGAIO_OP_READV: + return "readv"; + case PGAIO_OP_WRITEV: + return "writev"; + } + + return NULL; /* silence compiler */ +} + +/* + * Used to determine if an IO needs to be waited upon before the file + * descriptor can be closed. + */ +bool +pgaio_io_uses_fd(PgAioHandle *ioh, int fd) +{ + Assert(ioh->state >= PGAIO_HS_DEFINED); + + switch (ioh->op) + { + case PGAIO_OP_READV: + return ioh->op_data.read.fd == fd; + case PGAIO_OP_WRITEV: + return ioh->op_data.write.fd == fd; + case PGAIO_OP_INVALID: + return false; + } + + return false; /* silence compiler */ +} + +/* + * Return the iovec and its length. Currently only expected to be used by + * debugging infrastructure + */ +int +pgaio_io_get_iovec_length(PgAioHandle *ioh, struct iovec **iov) +{ + Assert(ioh->state >= PGAIO_HS_DEFINED); + + *iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + + switch (ioh->op) + { + case PGAIO_OP_READV: + return ioh->op_data.read.iov_length; + case PGAIO_OP_WRITEV: + return ioh->op_data.write.iov_length; + default: + pg_unreachable(); + return 0; + } +} diff --git a/src/backend/storage/aio/aio_target.c b/src/backend/storage/aio/aio_target.c new file mode 100644 index 0000000000000..161f0f1edf68c --- /dev/null +++ b/src/backend/storage/aio/aio_target.c @@ -0,0 +1,122 @@ +/*------------------------------------------------------------------------- + * + * aio_target.c + * AIO - Functionality related to executing IO for different targets + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/aio_target.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/smgr.h" + + +/* + * Registry for entities that can be the target of AIO. + */ +static const PgAioTargetInfo *pgaio_target_info[] = { + [PGAIO_TID_INVALID] = &(PgAioTargetInfo) { + .name = "invalid", + }, + [PGAIO_TID_SMGR] = &aio_smgr_target_info, +}; + + + +/* -------------------------------------------------------------------------------- + * Public target related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +bool +pgaio_io_has_target(PgAioHandle *ioh) +{ + return ioh->target != PGAIO_TID_INVALID; +} + +/* + * Return the name for the target associated with the IO. Mostly useful for + * debugging/logging. + */ +const char * +pgaio_io_get_target_name(PgAioHandle *ioh) +{ + /* explicitly allow INVALID here, function used by debug messages */ + Assert(ioh->target >= PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + + return pgaio_target_info[ioh->target]->name; +} + +/* + * Assign a target to the IO. + * + * This has to be called exactly once before pgaio_io_start_*() is called. + */ +void +pgaio_io_set_target(PgAioHandle *ioh, PgAioTargetID targetid) +{ + Assert(ioh->state == PGAIO_HS_HANDED_OUT); + Assert(ioh->target == PGAIO_TID_INVALID); + + ioh->target = targetid; +} + +PgAioTargetData * +pgaio_io_get_target_data(PgAioHandle *ioh) +{ + return &ioh->target_data; +} + +/* + * Return a stringified description of the IO's target. + * + * The string is localized and allocated in the current memory context. + */ +char * +pgaio_io_get_target_description(PgAioHandle *ioh) +{ + /* disallow INVALID, there wouldn't be a description */ + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + + return pgaio_target_info[ioh->target]->describe_identity(&ioh->target_data); +} + + + +/* -------------------------------------------------------------------------------- + * Internal target related functions operating on IO Handles + * -------------------------------------------------------------------------------- + */ + +/* + * Internal: Check if pgaio_io_reopen() is available for the IO. + */ +bool +pgaio_io_can_reopen(PgAioHandle *ioh) +{ + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + + return pgaio_target_info[ioh->target]->reopen != NULL; +} + +/* + * Internal: Before executing an IO outside of the context of the process the + * IO has been staged in, the file descriptor has to be reopened - any FD + * referenced in the IO itself, won't be valid in the separate process. + */ +void +pgaio_io_reopen(PgAioHandle *ioh) +{ + Assert(ioh->target > PGAIO_TID_INVALID && ioh->target < PGAIO_TID_COUNT); + Assert(ioh->op > PGAIO_OP_INVALID && ioh->op < PGAIO_OP_COUNT); + + pgaio_target_info[ioh->target]->reopen(ioh); +} diff --git a/src/backend/storage/aio/meson.build b/src/backend/storage/aio/meson.build index 10e1aa3b20b64..da6df2d3654f9 100644 --- a/src/backend/storage/aio/meson.build +++ b/src/backend/storage/aio/meson.build @@ -1,5 +1,14 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group backend_sources += files( + 'aio.c', + 'aio_callback.c', + 'aio_funcs.c', + 'aio_init.c', + 'aio_io.c', + 'aio_target.c', + 'method_io_uring.c', + 'method_sync.c', + 'method_worker.c', 'read_stream.c', ) diff --git a/src/backend/storage/aio/method_io_uring.c b/src/backend/storage/aio/method_io_uring.c new file mode 100644 index 0000000000000..b78048328e113 --- /dev/null +++ b/src/backend/storage/aio/method_io_uring.c @@ -0,0 +1,515 @@ +/*------------------------------------------------------------------------- + * + * method_io_uring.c + * AIO - perform AIO using Linux' io_uring + * + * For now we create one io_uring instance for each backend. These io_uring + * instances have to be created in postmaster, during startup, to allow other + * backends to process IO completions, if the issuing backend is currently + * busy doing other things. Other backends may not use another backend's + * io_uring instance to submit IO, that'd require additional locking that + * would likely be harmful for performance. + * + * We likely will want to introduce a backend-local io_uring instance in the + * future, e.g. for FE/BE network IO. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/method_io_uring.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +/* included early, for IOMETHOD_IO_URING_ENABLED */ +#include "storage/aio.h" + +#ifdef IOMETHOD_IO_URING_ENABLED + +#include + +#include "miscadmin.h" +#include "storage/aio_internal.h" +#include "storage/fd.h" +#include "storage/proc.h" +#include "storage/shmem.h" +#include "storage/lwlock.h" +#include "storage/procnumber.h" +#include "utils/wait_event.h" + + +/* number of completions processed at once */ +#define PGAIO_MAX_LOCAL_COMPLETED_IO 32 + + +/* Entry points for IoMethodOps. */ +static size_t pgaio_uring_shmem_size(void); +static void pgaio_uring_shmem_init(bool first_time); +static void pgaio_uring_init_backend(void); +static int pgaio_uring_submit(uint16 num_staged_ios, PgAioHandle **staged_ios); +static void pgaio_uring_wait_one(PgAioHandle *ioh, uint64 ref_generation); + +/* helper functions */ +static void pgaio_uring_sq_from_io(PgAioHandle *ioh, struct io_uring_sqe *sqe); + + +const IoMethodOps pgaio_uring_ops = { + /* + * While io_uring mostly is OK with FDs getting closed while the IO is in + * flight, that is not true for IOs submitted with IOSQE_ASYNC. + * + * See + * https://postgr.es/m/5ons2rtmwarqqhhexb3dnqulw5rjgwgoct57vpdau4rujlrffj%403fls6d2mkiwc + */ + .wait_on_fd_before_close = true, + + .shmem_size = pgaio_uring_shmem_size, + .shmem_init = pgaio_uring_shmem_init, + .init_backend = pgaio_uring_init_backend, + + .submit = pgaio_uring_submit, + .wait_one = pgaio_uring_wait_one, +}; + +/* + * Per-backend state when using io_method=io_uring + * + * Align the whole struct to a cacheline boundary, to prevent false sharing + * between completion_lock and prior backend's io_uring_ring. + */ +typedef struct pg_attribute_aligned (PG_CACHE_LINE_SIZE) +PgAioUringContext +{ + /* + * Multiple backends can process completions for this backend's io_uring + * instance (e.g. when the backend issuing IO is busy doing something + * else). To make that safe we have to ensure that only a single backend + * gets io completions from the io_uring instance at a time. + */ + LWLock completion_lock; + + struct io_uring io_uring_ring; +} PgAioUringContext; + +/* PgAioUringContexts for all backends */ +static PgAioUringContext *pgaio_uring_contexts; + +/* the current backend's context */ +static PgAioUringContext *pgaio_my_uring_context; + + +static uint32 +pgaio_uring_procs(void) +{ + /* + * We can subtract MAX_IO_WORKERS here as io workers are never used at the + * same time as io_method=io_uring. + */ + return MaxBackends + NUM_AUXILIARY_PROCS - MAX_IO_WORKERS; +} + +static Size +pgaio_uring_context_shmem_size(void) +{ + return mul_size(pgaio_uring_procs(), sizeof(PgAioUringContext)); +} + +static size_t +pgaio_uring_shmem_size(void) +{ + return pgaio_uring_context_shmem_size(); +} + +static void +pgaio_uring_shmem_init(bool first_time) +{ + int TotalProcs = pgaio_uring_procs(); + bool found; + + pgaio_uring_contexts = (PgAioUringContext *) + ShmemInitStruct("AioUring", pgaio_uring_shmem_size(), &found); + + if (found) + return; + + for (int contextno = 0; contextno < TotalProcs; contextno++) + { + PgAioUringContext *context = &pgaio_uring_contexts[contextno]; + int ret; + + /* + * Right now a high TotalProcs will cause problems in two ways: + * + * - RLIMIT_NOFILE needs to be big enough to allow all + * io_uring_queue_init() calls to succeed. + * + * - RLIMIT_NOFILE needs to be big enough to still have enough file + * descriptors to satisfy set_max_safe_fds() left over. Or, even + * better, have max_files_per_process left over FDs. + * + * We probably should adjust the soft RLIMIT_NOFILE to ensure that. + * + * + * XXX: Newer versions of io_uring support sharing the workers that + * execute some asynchronous IOs between io_uring instances. It might + * be worth using that - also need to evaluate if that causes + * noticeable additional contention? + */ + ret = io_uring_queue_init(io_max_concurrency, &context->io_uring_ring, 0); + if (ret < 0) + { + char *hint = NULL; + int err = ERRCODE_INTERNAL_ERROR; + + /* add hints for some failures that errno explains sufficiently */ + if (-ret == EPERM) + { + err = ERRCODE_INSUFFICIENT_PRIVILEGE; + hint = _("Check if io_uring is disabled via /proc/sys/kernel/io_uring_disabled."); + } + else if (-ret == EMFILE) + { + err = ERRCODE_INSUFFICIENT_RESOURCES; + hint = psprintf(_("Consider increasing \"ulimit -n\" to at least %d."), + TotalProcs + max_files_per_process); + } + else if (-ret == ENOSYS) + { + err = ERRCODE_FEATURE_NOT_SUPPORTED; + hint = _("Kernel does not support io_uring."); + } + + /* update errno to allow %m to work */ + errno = -ret; + + ereport(ERROR, + errcode(err), + errmsg("could not setup io_uring queue: %m"), + hint != NULL ? errhint("%s", hint) : 0); + } + + LWLockInitialize(&context->completion_lock, LWTRANCHE_AIO_URING_COMPLETION); + } +} + +static void +pgaio_uring_init_backend(void) +{ + Assert(MyProcNumber < pgaio_uring_procs()); + + pgaio_my_uring_context = &pgaio_uring_contexts[MyProcNumber]; +} + +static int +pgaio_uring_submit(uint16 num_staged_ios, PgAioHandle **staged_ios) +{ + struct io_uring *uring_instance = &pgaio_my_uring_context->io_uring_ring; + int in_flight_before = dclist_count(&pgaio_my_backend->in_flight_ios); + + Assert(num_staged_ios <= PGAIO_SUBMIT_BATCH_SIZE); + + for (int i = 0; i < num_staged_ios; i++) + { + PgAioHandle *ioh = staged_ios[i]; + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(uring_instance); + + if (!sqe) + elog(ERROR, "io_uring submission queue is unexpectedly full"); + + pgaio_io_prepare_submit(ioh); + pgaio_uring_sq_from_io(ioh, sqe); + + /* + * io_uring executes IO in process context if possible. That's + * generally good, as it reduces context switching. When performing a + * lot of buffered IO that means that copying between page cache and + * userspace memory happens in the foreground, as it can't be + * offloaded to DMA hardware as is possible when using direct IO. When + * executing a lot of buffered IO this causes io_uring to be slower + * than worker mode, as worker mode parallelizes the copying. io_uring + * can be told to offload work to worker threads instead. + * + * If an IO is buffered IO and we already have IOs in flight or + * multiple IOs are being submitted, we thus tell io_uring to execute + * the IO in the background. We don't do so for the first few IOs + * being submitted as executing in this process' context has lower + * latency. + */ + if (in_flight_before > 4 && (ioh->flags & PGAIO_HF_BUFFERED)) + io_uring_sqe_set_flags(sqe, IOSQE_ASYNC); + + in_flight_before++; + } + + while (true) + { + int ret; + + pgstat_report_wait_start(WAIT_EVENT_AIO_IO_URING_SUBMIT); + ret = io_uring_submit(uring_instance); + pgstat_report_wait_end(); + + if (ret == -EINTR) + { + pgaio_debug(DEBUG3, + "aio method uring: submit EINTR, nios: %d", + num_staged_ios); + } + else if (ret < 0) + { + /* + * The io_uring_enter() manpage suggests that the appropriate + * reaction to EAGAIN is: + * + * "The application should wait for some completions and try + * again" + * + * However, it seems unlikely that that would help in our case, as + * we apply a low limit to the number of outstanding IOs and thus + * also outstanding completions, making it unlikely that we'd get + * EAGAIN while the OS is in good working order. + * + * Additionally, it would be problematic to just wait here, our + * caller might hold critical locks. It'd possibly lead to + * delaying the crash-restart that seems likely to occur when the + * kernel is under such heavy memory pressure. + * + * Update errno to allow %m to work. + */ + errno = -ret; + elog(PANIC, "io_uring submit failed: %m"); + } + else if (ret != num_staged_ios) + { + /* likely unreachable, but if it is, we would need to re-submit */ + elog(PANIC, "io_uring submit submitted only %d of %d", + ret, num_staged_ios); + } + else + { + pgaio_debug(DEBUG4, + "aio method uring: submitted %d IOs", + num_staged_ios); + break; + } + } + + return num_staged_ios; +} + +static void +pgaio_uring_completion_error_callback(void *arg) +{ + ProcNumber owner; + PGPROC *owner_proc; + int32 owner_pid; + PgAioHandle *ioh = arg; + + if (!ioh) + return; + + /* No need for context if a backend is completing the IO for itself */ + if (ioh->owner_procno == MyProcNumber) + return; + + owner = ioh->owner_procno; + owner_proc = GetPGProcByNumber(owner); + owner_pid = owner_proc->pid; + + errcontext("completing I/O on behalf of process %d", owner_pid); +} + +static void +pgaio_uring_drain_locked(PgAioUringContext *context) +{ + int ready; + int orig_ready; + ErrorContextCallback errcallback = {0}; + + Assert(LWLockHeldByMeInMode(&context->completion_lock, LW_EXCLUSIVE)); + + errcallback.callback = pgaio_uring_completion_error_callback; + errcallback.previous = error_context_stack; + error_context_stack = &errcallback; + + /* + * Don't drain more events than available right now. Otherwise it's + * plausible that one backend could get stuck, for a while, receiving CQEs + * without actually processing them. + */ + orig_ready = ready = io_uring_cq_ready(&context->io_uring_ring); + + while (ready > 0) + { + struct io_uring_cqe *cqes[PGAIO_MAX_LOCAL_COMPLETED_IO]; + uint32 ncqes; + + START_CRIT_SECTION(); + ncqes = + io_uring_peek_batch_cqe(&context->io_uring_ring, + cqes, + Min(PGAIO_MAX_LOCAL_COMPLETED_IO, ready)); + Assert(ncqes <= ready); + + ready -= ncqes; + + for (int i = 0; i < ncqes; i++) + { + struct io_uring_cqe *cqe = cqes[i]; + PgAioHandle *ioh; + + ioh = io_uring_cqe_get_data(cqe); + errcallback.arg = ioh; + io_uring_cqe_seen(&context->io_uring_ring, cqe); + + pgaio_io_process_completion(ioh, cqe->res); + errcallback.arg = NULL; + } + + END_CRIT_SECTION(); + + pgaio_debug(DEBUG3, + "drained %d/%d, now expecting %d", + ncqes, orig_ready, io_uring_cq_ready(&context->io_uring_ring)); + } + + error_context_stack = errcallback.previous; +} + +static void +pgaio_uring_wait_one(PgAioHandle *ioh, uint64 ref_generation) +{ + PgAioHandleState state; + ProcNumber owner_procno = ioh->owner_procno; + PgAioUringContext *owner_context = &pgaio_uring_contexts[owner_procno]; + bool expect_cqe; + int waited = 0; + + /* + * XXX: It would be nice to have a smarter locking scheme, nearly all the + * time the backend owning the ring will consume the completions, making + * the locking unnecessarily expensive. + */ + LWLockAcquire(&owner_context->completion_lock, LW_EXCLUSIVE); + + while (true) + { + pgaio_debug_io(DEBUG3, ioh, + "wait_one io_gen: %" PRIu64 ", ref_gen: %" PRIu64 ", cycle %d", + ioh->generation, + ref_generation, + waited); + + if (pgaio_io_was_recycled(ioh, ref_generation, &state) || + state != PGAIO_HS_SUBMITTED) + { + /* the IO was completed by another backend */ + break; + } + else if (io_uring_cq_ready(&owner_context->io_uring_ring)) + { + /* no need to wait in the kernel, io_uring has a completion */ + expect_cqe = true; + } + else + { + int ret; + struct io_uring_cqe *cqes; + + /* need to wait in the kernel */ + pgstat_report_wait_start(WAIT_EVENT_AIO_IO_URING_EXECUTION); + ret = io_uring_wait_cqes(&owner_context->io_uring_ring, &cqes, 1, NULL, NULL); + pgstat_report_wait_end(); + + if (ret == -EINTR) + { + continue; + } + else if (ret != 0) + { + /* see comment after io_uring_submit() */ + errno = -ret; + elog(PANIC, "io_uring wait failed: %m"); + } + else + { + Assert(cqes != NULL); + expect_cqe = true; + waited++; + } + } + + if (expect_cqe) + { + pgaio_uring_drain_locked(owner_context); + } + } + + LWLockRelease(&owner_context->completion_lock); + + pgaio_debug(DEBUG3, + "wait_one with %d sleeps", + waited); +} + +static void +pgaio_uring_sq_from_io(PgAioHandle *ioh, struct io_uring_sqe *sqe) +{ + struct iovec *iov; + + switch (ioh->op) + { + case PGAIO_OP_READV: + iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + if (ioh->op_data.read.iov_length == 1) + { + io_uring_prep_read(sqe, + ioh->op_data.read.fd, + iov->iov_base, + iov->iov_len, + ioh->op_data.read.offset); + } + else + { + io_uring_prep_readv(sqe, + ioh->op_data.read.fd, + iov, + ioh->op_data.read.iov_length, + ioh->op_data.read.offset); + + } + break; + + case PGAIO_OP_WRITEV: + iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + if (ioh->op_data.write.iov_length == 1) + { + io_uring_prep_write(sqe, + ioh->op_data.write.fd, + iov->iov_base, + iov->iov_len, + ioh->op_data.write.offset); + } + else + { + io_uring_prep_writev(sqe, + ioh->op_data.write.fd, + iov, + ioh->op_data.write.iov_length, + ioh->op_data.write.offset); + } + break; + + case PGAIO_OP_INVALID: + elog(ERROR, "trying to prepare invalid IO operation for execution"); + } + + io_uring_sqe_set_data(sqe, ioh); +} + +#endif /* IOMETHOD_IO_URING_ENABLED */ diff --git a/src/backend/storage/aio/method_sync.c b/src/backend/storage/aio/method_sync.c new file mode 100644 index 0000000000000..902c2428d4158 --- /dev/null +++ b/src/backend/storage/aio/method_sync.c @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * method_sync.c + * AIO - perform "AIO" by executing it synchronously + * + * This method is mainly to check if AIO use causes regressions. Other IO + * methods might also fall back to the synchronous method for functionality + * they cannot provide. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/method_sync.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "storage/aio.h" +#include "storage/aio_internal.h" + +static bool pgaio_sync_needs_synchronous_execution(PgAioHandle *ioh); +static int pgaio_sync_submit(uint16 num_staged_ios, PgAioHandle **staged_ios); + + +const IoMethodOps pgaio_sync_ops = { + .needs_synchronous_execution = pgaio_sync_needs_synchronous_execution, + .submit = pgaio_sync_submit, +}; + + + +static bool +pgaio_sync_needs_synchronous_execution(PgAioHandle *ioh) +{ + return true; +} + +static int +pgaio_sync_submit(uint16 num_staged_ios, PgAioHandle **staged_ios) +{ + elog(ERROR, "IO should have been executed synchronously"); + + return 0; +} diff --git a/src/backend/storage/aio/method_worker.c b/src/backend/storage/aio/method_worker.c new file mode 100644 index 0000000000000..36be179678d7a --- /dev/null +++ b/src/backend/storage/aio/method_worker.c @@ -0,0 +1,586 @@ +/*------------------------------------------------------------------------- + * + * method_worker.c + * AIO - perform AIO using worker processes + * + * IO workers consume IOs from a shared memory submission queue, run + * traditional synchronous system calls, and perform the shared completion + * handling immediately. Client code submits most requests by pushing IOs + * into the submission queue, and waits (if necessary) using condition + * variables. Some IOs cannot be performed in another process due to lack of + * infrastructure for reopening the file, and must processed synchronously by + * the client code when submitted. + * + * So that the submitter can make just one system call when submitting a batch + * of IOs, wakeups "fan out"; each woken IO worker can wake two more. XXX This + * could be improved by using futexes instead of latches to wake N waiters. + * + * This method of AIO is available in all builds on all operating systems, and + * is the default. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/aio/method_worker.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "libpq/pqsignal.h" +#include "miscadmin.h" +#include "port/pg_bitutils.h" +#include "postmaster/auxprocess.h" +#include "postmaster/interrupt.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/aio_subsys.h" +#include "storage/io_worker.h" +#include "storage/ipc.h" +#include "storage/latch.h" +#include "storage/proc.h" +#include "tcop/tcopprot.h" +#include "utils/injection_point.h" +#include "utils/memdebug.h" +#include "utils/ps_status.h" +#include "utils/wait_event.h" + + +/* How many workers should each worker wake up if needed? */ +#define IO_WORKER_WAKEUP_FANOUT 2 + + +typedef struct AioWorkerSubmissionQueue +{ + uint32 size; + uint32 mask; + uint32 head; + uint32 tail; + uint32 ios[FLEXIBLE_ARRAY_MEMBER]; +} AioWorkerSubmissionQueue; + +typedef struct AioWorkerSlot +{ + Latch *latch; + bool in_use; +} AioWorkerSlot; + +typedef struct AioWorkerControl +{ + uint64 idle_worker_mask; + AioWorkerSlot workers[FLEXIBLE_ARRAY_MEMBER]; +} AioWorkerControl; + + +static size_t pgaio_worker_shmem_size(void); +static void pgaio_worker_shmem_init(bool first_time); + +static bool pgaio_worker_needs_synchronous_execution(PgAioHandle *ioh); +static int pgaio_worker_submit(uint16 num_staged_ios, PgAioHandle **staged_ios); + + +const IoMethodOps pgaio_worker_ops = { + .shmem_size = pgaio_worker_shmem_size, + .shmem_init = pgaio_worker_shmem_init, + + .needs_synchronous_execution = pgaio_worker_needs_synchronous_execution, + .submit = pgaio_worker_submit, +}; + + +/* GUCs */ +int io_workers = 3; + + +static int io_worker_queue_size = 64; +static int MyIoWorkerId; +static AioWorkerSubmissionQueue *io_worker_submission_queue; +static AioWorkerControl *io_worker_control; + + +static size_t +pgaio_worker_queue_shmem_size(int *queue_size) +{ + /* Round size up to next power of two so we can make a mask. */ + *queue_size = pg_nextpower2_32(io_worker_queue_size); + + return offsetof(AioWorkerSubmissionQueue, ios) + + sizeof(uint32) * *queue_size; +} + +static size_t +pgaio_worker_control_shmem_size(void) +{ + return offsetof(AioWorkerControl, workers) + + sizeof(AioWorkerSlot) * MAX_IO_WORKERS; +} + +static size_t +pgaio_worker_shmem_size(void) +{ + size_t sz; + int queue_size; + + sz = pgaio_worker_queue_shmem_size(&queue_size); + sz = add_size(sz, pgaio_worker_control_shmem_size()); + + return sz; +} + +static void +pgaio_worker_shmem_init(bool first_time) +{ + bool found; + int queue_size; + + io_worker_submission_queue = + ShmemInitStruct("AioWorkerSubmissionQueue", + pgaio_worker_queue_shmem_size(&queue_size), + &found); + if (!found) + { + io_worker_submission_queue->size = queue_size; + io_worker_submission_queue->head = 0; + io_worker_submission_queue->tail = 0; + } + + io_worker_control = + ShmemInitStruct("AioWorkerControl", + pgaio_worker_control_shmem_size(), + &found); + if (!found) + { + io_worker_control->idle_worker_mask = 0; + for (int i = 0; i < MAX_IO_WORKERS; ++i) + { + io_worker_control->workers[i].latch = NULL; + io_worker_control->workers[i].in_use = false; + } + } +} + +static int +pgaio_choose_idle_worker(void) +{ + int worker; + + if (io_worker_control->idle_worker_mask == 0) + return -1; + + /* Find the lowest bit position, and clear it. */ + worker = pg_rightmost_one_pos64(io_worker_control->idle_worker_mask); + io_worker_control->idle_worker_mask &= ~(UINT64_C(1) << worker); + + return worker; +} + +static bool +pgaio_worker_submission_queue_insert(PgAioHandle *ioh) +{ + AioWorkerSubmissionQueue *queue; + uint32 new_head; + + queue = io_worker_submission_queue; + new_head = (queue->head + 1) & (queue->size - 1); + if (new_head == queue->tail) + { + pgaio_debug(DEBUG3, "io queue is full, at %u elements", + io_worker_submission_queue->size); + return false; /* full */ + } + + queue->ios[queue->head] = pgaio_io_get_id(ioh); + queue->head = new_head; + + return true; +} + +static uint32 +pgaio_worker_submission_queue_consume(void) +{ + AioWorkerSubmissionQueue *queue; + uint32 result; + + queue = io_worker_submission_queue; + if (queue->tail == queue->head) + return UINT32_MAX; /* empty */ + + result = queue->ios[queue->tail]; + queue->tail = (queue->tail + 1) & (queue->size - 1); + + return result; +} + +static uint32 +pgaio_worker_submission_queue_depth(void) +{ + uint32 head; + uint32 tail; + + head = io_worker_submission_queue->head; + tail = io_worker_submission_queue->tail; + + if (tail > head) + head += io_worker_submission_queue->size; + + Assert(head >= tail); + + return head - tail; +} + +static bool +pgaio_worker_needs_synchronous_execution(PgAioHandle *ioh) +{ + return + !IsUnderPostmaster + || ioh->flags & PGAIO_HF_REFERENCES_LOCAL + || !pgaio_io_can_reopen(ioh); +} + +static void +pgaio_worker_submit_internal(int nios, PgAioHandle *ios[]) +{ + PgAioHandle *synchronous_ios[PGAIO_SUBMIT_BATCH_SIZE]; + int nsync = 0; + Latch *wakeup = NULL; + int worker; + + Assert(nios <= PGAIO_SUBMIT_BATCH_SIZE); + + LWLockAcquire(AioWorkerSubmissionQueueLock, LW_EXCLUSIVE); + for (int i = 0; i < nios; ++i) + { + Assert(!pgaio_worker_needs_synchronous_execution(ios[i])); + if (!pgaio_worker_submission_queue_insert(ios[i])) + { + /* + * We'll do it synchronously, but only after we've sent as many as + * we can to workers, to maximize concurrency. + */ + synchronous_ios[nsync++] = ios[i]; + continue; + } + + if (wakeup == NULL) + { + /* Choose an idle worker to wake up if we haven't already. */ + worker = pgaio_choose_idle_worker(); + if (worker >= 0) + wakeup = io_worker_control->workers[worker].latch; + + pgaio_debug_io(DEBUG4, ios[i], + "choosing worker %d", + worker); + } + } + LWLockRelease(AioWorkerSubmissionQueueLock); + + if (wakeup) + SetLatch(wakeup); + + /* Run whatever is left synchronously. */ + if (nsync > 0) + { + for (int i = 0; i < nsync; ++i) + { + pgaio_io_perform_synchronously(synchronous_ios[i]); + } + } +} + +static int +pgaio_worker_submit(uint16 num_staged_ios, PgAioHandle **staged_ios) +{ + for (int i = 0; i < num_staged_ios; i++) + { + PgAioHandle *ioh = staged_ios[i]; + + pgaio_io_prepare_submit(ioh); + } + + pgaio_worker_submit_internal(num_staged_ios, staged_ios); + + return num_staged_ios; +} + +/* + * on_shmem_exit() callback that releases the worker's slot in + * io_worker_control. + */ +static void +pgaio_worker_die(int code, Datum arg) +{ + LWLockAcquire(AioWorkerSubmissionQueueLock, LW_EXCLUSIVE); + Assert(io_worker_control->workers[MyIoWorkerId].in_use); + Assert(io_worker_control->workers[MyIoWorkerId].latch == MyLatch); + + io_worker_control->workers[MyIoWorkerId].in_use = false; + io_worker_control->workers[MyIoWorkerId].latch = NULL; + LWLockRelease(AioWorkerSubmissionQueueLock); +} + +/* + * Register the worker in shared memory, assign MyIoWorkerId and register a + * shutdown callback to release registration. + */ +static void +pgaio_worker_register(void) +{ + MyIoWorkerId = -1; + + /* + * XXX: This could do with more fine-grained locking. But it's also not + * very common for the number of workers to change at the moment... + */ + LWLockAcquire(AioWorkerSubmissionQueueLock, LW_EXCLUSIVE); + + for (int i = 0; i < MAX_IO_WORKERS; ++i) + { + if (!io_worker_control->workers[i].in_use) + { + Assert(io_worker_control->workers[i].latch == NULL); + io_worker_control->workers[i].in_use = true; + MyIoWorkerId = i; + break; + } + else + Assert(io_worker_control->workers[i].latch != NULL); + } + + if (MyIoWorkerId == -1) + elog(ERROR, "couldn't find a free worker slot"); + + io_worker_control->idle_worker_mask |= (UINT64_C(1) << MyIoWorkerId); + io_worker_control->workers[MyIoWorkerId].latch = MyLatch; + LWLockRelease(AioWorkerSubmissionQueueLock); + + on_shmem_exit(pgaio_worker_die, 0); +} + +static void +pgaio_worker_error_callback(void *arg) +{ + ProcNumber owner; + PGPROC *owner_proc; + int32 owner_pid; + PgAioHandle *ioh = arg; + + if (!ioh) + return; + + Assert(ioh->owner_procno != MyProcNumber); + Assert(MyBackendType == B_IO_WORKER); + + owner = ioh->owner_procno; + owner_proc = GetPGProcByNumber(owner); + owner_pid = owner_proc->pid; + + errcontext("I/O worker executing I/O on behalf of process %d", owner_pid); +} + +void +IoWorkerMain(const void *startup_data, size_t startup_data_len) +{ + sigjmp_buf local_sigjmp_buf; + PgAioHandle *volatile error_ioh = NULL; + ErrorContextCallback errcallback = {0}; + volatile int error_errno = 0; + char cmd[128]; + + MyBackendType = B_IO_WORKER; + AuxiliaryProcessMainCommon(); + + pqsignal(SIGHUP, SignalHandlerForConfigReload); + pqsignal(SIGINT, die); /* to allow manually triggering worker restart */ + + /* + * Ignore SIGTERM, will get explicit shutdown via SIGUSR2 later in the + * shutdown sequence, similar to checkpointer. + */ + pqsignal(SIGTERM, SIG_IGN); + /* SIGQUIT handler was already set up by InitPostmasterChild */ + pqsignal(SIGALRM, SIG_IGN); + pqsignal(SIGPIPE, SIG_IGN); + pqsignal(SIGUSR1, procsignal_sigusr1_handler); + pqsignal(SIGUSR2, SignalHandlerForShutdownRequest); + + /* also registers a shutdown callback to unregister */ + pgaio_worker_register(); + + sprintf(cmd, "%d", MyIoWorkerId); + set_ps_display(cmd); + + errcallback.callback = pgaio_worker_error_callback; + errcallback.previous = error_context_stack; + error_context_stack = &errcallback; + + /* see PostgresMain() */ + if (sigsetjmp(local_sigjmp_buf, 1) != 0) + { + error_context_stack = NULL; + HOLD_INTERRUPTS(); + + EmitErrorReport(); + + /* + * In the - very unlikely - case that the IO failed in a way that + * raises an error we need to mark the IO as failed. + * + * Need to do just enough error recovery so that we can mark the IO as + * failed and then exit (postmaster will start a new worker). + */ + LWLockReleaseAll(); + + if (error_ioh != NULL) + { + /* should never fail without setting error_errno */ + Assert(error_errno != 0); + + errno = error_errno; + + START_CRIT_SECTION(); + pgaio_io_process_completion(error_ioh, -error_errno); + END_CRIT_SECTION(); + } + + proc_exit(1); + } + + /* We can now handle ereport(ERROR) */ + PG_exception_stack = &local_sigjmp_buf; + + sigprocmask(SIG_SETMASK, &UnBlockSig, NULL); + + while (!ShutdownRequestPending) + { + uint32 io_index; + Latch *latches[IO_WORKER_WAKEUP_FANOUT]; + int nlatches = 0; + int nwakeups = 0; + int worker; + + /* + * Try to get a job to do. + * + * The lwlock acquisition also provides the necessary memory barrier + * to ensure that we don't see an outdated data in the handle. + */ + LWLockAcquire(AioWorkerSubmissionQueueLock, LW_EXCLUSIVE); + if ((io_index = pgaio_worker_submission_queue_consume()) == UINT32_MAX) + { + /* + * Nothing to do. Mark self idle. + * + * XXX: Invent some kind of back pressure to reduce useless + * wakeups? + */ + io_worker_control->idle_worker_mask |= (UINT64_C(1) << MyIoWorkerId); + } + else + { + /* Got one. Clear idle flag. */ + io_worker_control->idle_worker_mask &= ~(UINT64_C(1) << MyIoWorkerId); + + /* See if we can wake up some peers. */ + nwakeups = Min(pgaio_worker_submission_queue_depth(), + IO_WORKER_WAKEUP_FANOUT); + for (int i = 0; i < nwakeups; ++i) + { + if ((worker = pgaio_choose_idle_worker()) < 0) + break; + latches[nlatches++] = io_worker_control->workers[worker].latch; + } + } + LWLockRelease(AioWorkerSubmissionQueueLock); + + for (int i = 0; i < nlatches; ++i) + SetLatch(latches[i]); + + if (io_index != UINT32_MAX) + { + PgAioHandle *ioh = NULL; + + ioh = &pgaio_ctl->io_handles[io_index]; + error_ioh = ioh; + errcallback.arg = ioh; + + pgaio_debug_io(DEBUG4, ioh, + "worker %d processing IO", + MyIoWorkerId); + + /* + * Prevent interrupts between pgaio_io_reopen() and + * pgaio_io_perform_synchronously() that otherwise could lead to + * the FD getting closed in that window. + */ + HOLD_INTERRUPTS(); + + /* + * It's very unlikely, but possible, that reopen fails. E.g. due + * to memory allocations failing or file permissions changing or + * such. In that case we need to fail the IO. + * + * There's not really a good errno we can report here. + */ + error_errno = ENOENT; + pgaio_io_reopen(ioh); + + /* + * To be able to exercise the reopen-fails path, allow injection + * points to trigger a failure at this point. + */ + INJECTION_POINT("aio-worker-after-reopen", ioh); + + error_errno = 0; + error_ioh = NULL; + + /* + * As part of IO completion the buffer will be marked as NOACCESS, + * until the buffer is pinned again - which never happens in io + * workers. Therefore the next time there is IO for the same + * buffer, the memory will be considered inaccessible. To avoid + * that, explicitly allow access to the memory before reading data + * into it. + */ +#ifdef USE_VALGRIND + { + struct iovec *iov; + uint16 iov_length = pgaio_io_get_iovec_length(ioh, &iov); + + for (int i = 0; i < iov_length; i++) + VALGRIND_MAKE_MEM_UNDEFINED(iov[i].iov_base, iov[i].iov_len); + } +#endif + + /* + * We don't expect this to ever fail with ERROR or FATAL, no need + * to keep error_ioh set to the IO. + * pgaio_io_perform_synchronously() contains a critical section to + * ensure we don't accidentally fail. + */ + pgaio_io_perform_synchronously(ioh); + + RESUME_INTERRUPTS(); + errcallback.arg = NULL; + } + else + { + WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, -1, + WAIT_EVENT_IO_WORKER_MAIN); + ResetLatch(MyLatch); + } + + CHECK_FOR_INTERRUPTS(); + } + + error_context_stack = errcallback.previous; + proc_exit(0); +} + +bool +pgaio_workers_enabled(void) +{ + return io_method == IOMETHOD_WORKER; +} diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c index 684b6d6fc0c9f..0e7f5557f5cb9 100644 --- a/src/backend/storage/aio/read_stream.c +++ b/src/backend/storage/aio/read_stream.c @@ -17,29 +17,12 @@ * pending read. When that isn't possible, the existing pending read is sent * to StartReadBuffers() so that a new one can begin to form. * - * The algorithm for controlling the look-ahead distance tries to classify the - * stream into three ideal behaviors: - * - * A) No I/O is necessary, because the requested blocks are fully cached - * already. There is no benefit to looking ahead more than one block, so - * distance is 1. This is the default initial assumption. - * - * B) I/O is necessary, but fadvise is undesirable because the access is - * sequential, or impossible because direct I/O is enabled or the system - * doesn't support fadvise. There is no benefit in looking ahead more than - * io_combine_limit, because in this case the only goal is larger read system - * calls. Looking further ahead would pin many buffers and perform - * speculative work looking ahead for no benefit. - * - * C) I/O is necessary, it appears random, and this system supports fadvise. - * We'll look further ahead in order to reach the configured level of I/O - * concurrency. - * - * The distance increases rapidly and decays slowly, so that it moves towards - * those levels as different I/O patterns are discovered. For example, a - * sequential scan of fully cached data doesn't bother looking ahead, but a - * sequential scan that hits a region of uncached blocks will start issuing - * increasingly wide read calls until it plateaus at io_combine_limit. + * The algorithm for controlling the look-ahead distance is based on recent + * cache hit and miss history. When no I/O is necessary, there is no benefit + * in looking ahead more than one block. This is the default initial + * assumption, but when blocks needing I/O are streamed, the distance is + * increased rapidly to try to benefit from I/O combining and concurrency. It + * is reduced gradually when cached blocks are streamed. * * The main data structure is a circular queue of buffers of size * max_pinned_buffers plus some extra space for technical reasons, ready to be @@ -51,7 +34,7 @@ * I/Os that have been started with StartReadBuffers(), and for which * WaitReadBuffers() must be called before returning the buffer. * - * For example, if the callback return block numbers 10, 42, 43, 60 in + * For example, if the callback returns block numbers 10, 42, 43, 44, 60 in * successive calls, then these data structures might appear as follows: * * buffers buf/data ios @@ -78,7 +61,7 @@ * does block 60. * * - * Portions Copyright (c) 2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2024-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -88,8 +71,8 @@ */ #include "postgres.h" -#include "catalog/pg_tablespace.h" #include "miscadmin.h" +#include "storage/aio.h" #include "storage/fd.h" #include "storage/smgr.h" #include "storage/read_stream.h" @@ -109,21 +92,25 @@ typedef struct InProgressIO struct ReadStream { int16 max_ios; + int16 io_combine_limit; int16 ios_in_progress; int16 queue_size; int16 max_pinned_buffers; + int16 forwarded_buffers; int16 pinned_buffers; int16 distance; + int16 initialized_buffers; + int read_buffers_flags; + bool sync_mode; /* using io_method=sync */ + bool batch_mode; /* READ_STREAM_USE_BATCHING */ bool advice_enabled; + bool temporary; /* - * Small buffer of block numbers, useful for 'ungetting' to resolve flow - * control problems when I/Os are split. Also useful for batch-loading - * block numbers in the fast path. + * One-block buffer to support 'ungetting' a block number, to resolve flow + * control problems when I/Os are split. */ - BlockNumber blocknums[16]; - int16 blocknums_count; - int16 blocknums_next; + BlockNumber buffered_blocknum; /* * The callback that will tell us which block numbers to read, and an @@ -134,6 +121,7 @@ struct ReadStream /* Next expected block, for detecting sequential access. */ BlockNumber seq_blocknum; + BlockNumber seq_until_processed; /* The read operation we are currently preparing. */ BlockNumber pending_read_blocknum; @@ -167,83 +155,95 @@ get_per_buffer_data(ReadStream *stream, int16 buffer_index) } /* - * Ask the callback which block it would like us to read next, with a small - * buffer in front to allow read_stream_unget_block() to work and to allow the - * fast path to skip this function and work directly from the array. + * General-use ReadStreamBlockNumberCB for block range scans. Loops over the + * blocks [current_blocknum, last_exclusive). */ -static inline BlockNumber -read_stream_get_block(ReadStream *stream, void *per_buffer_data) +BlockNumber +block_range_read_stream_cb(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data) { - if (stream->blocknums_next < stream->blocknums_count) - return stream->blocknums[stream->blocknums_next++]; + BlockRangeReadStreamPrivate *p = callback_private_data; - /* - * We only bother to fetch one at a time here (but see the fast path which - * uses more). - */ - return stream->callback(stream, - stream->callback_private_data, - per_buffer_data); + if (p->current_blocknum < p->last_exclusive) + return p->current_blocknum++; + + return InvalidBlockNumber; } /* - * In order to deal with short reads in StartReadBuffers(), we sometimes need - * to defer handling of a block until later. + * Ask the callback which block it would like us to read next, with a one block + * buffer in front to allow read_stream_unget_block() to work. */ -static inline void -read_stream_unget_block(ReadStream *stream, BlockNumber blocknum) +static inline BlockNumber +read_stream_get_block(ReadStream *stream, void *per_buffer_data) { - if (stream->blocknums_next == stream->blocknums_count) - { - /* Never initialized or entirely consumed. Re-initialize. */ - stream->blocknums[0] = blocknum; - stream->blocknums_count = 1; - stream->blocknums_next = 0; - } + BlockNumber blocknum; + + blocknum = stream->buffered_blocknum; + if (blocknum != InvalidBlockNumber) + stream->buffered_blocknum = InvalidBlockNumber; else { - /* Must be the last value return from blocknums array. */ - Assert(stream->blocknums_next > 0); - stream->blocknums_next--; - Assert(stream->blocknums[stream->blocknums_next] == blocknum); + /* + * Tell Valgrind that the per-buffer data is undefined. That replaces + * the "noaccess" state that was set when the consumer moved past this + * entry last time around the queue, and should also catch callbacks + * that fail to initialize data that the buffer consumer later + * accesses. On the first go around, it is undefined already. + */ + VALGRIND_MAKE_MEM_UNDEFINED(per_buffer_data, + stream->per_buffer_data_size); + blocknum = stream->callback(stream, + stream->callback_private_data, + per_buffer_data); } + + return blocknum; } -#ifndef READ_STREAM_DISABLE_FAST_PATH -static void -read_stream_fill_blocknums(ReadStream *stream) +/* + * In order to deal with buffer shortages and I/O limits after short reads, we + * sometimes need to defer handling of a block we've already consumed from the + * registered callback until later. + */ +static inline void +read_stream_unget_block(ReadStream *stream, BlockNumber blocknum) { - BlockNumber blocknum; - int i = 0; - - do - { - blocknum = stream->callback(stream, - stream->callback_private_data, - NULL); - stream->blocknums[i++] = blocknum; - } while (i < lengthof(stream->blocknums) && - blocknum != InvalidBlockNumber); - stream->blocknums_count = i; - stream->blocknums_next = 0; + /* We shouldn't ever unget more than one block. */ + Assert(stream->buffered_blocknum == InvalidBlockNumber); + Assert(blocknum != InvalidBlockNumber); + stream->buffered_blocknum = blocknum; } -#endif -static void -read_stream_start_pending_read(ReadStream *stream, bool suppress_advice) +/* + * Start as much of the current pending read as we can. If we have to split it + * because of the per-backend buffer limit, or the buffer manager decides to + * split it, then the pending read is adjusted to hold the remaining portion. + * + * We can always start a read of at least size one if we have no progress yet. + * Otherwise it's possible that we can't start a read at all because of a lack + * of buffers, and then false is returned. Buffer shortages also reduce the + * distance to a level that prevents look-ahead until buffers are released. + */ +static bool +read_stream_start_pending_read(ReadStream *stream) { bool need_wait; + int requested_nblocks; int nblocks; int flags; + int forwarded; int16 io_index; int16 overflow; int16 buffer_index; + int buffer_limit; /* This should only be called with a pending read. */ Assert(stream->pending_read_nblocks > 0); - Assert(stream->pending_read_nblocks <= io_combine_limit); + Assert(stream->pending_read_nblocks <= stream->io_combine_limit); - /* We had better not exceed the pin limit by starting this read. */ + /* We had better not exceed the per-stream buffer limit with this read. */ Assert(stream->pinned_buffers + stream->pending_read_nblocks <= stream->max_pinned_buffers); @@ -253,21 +253,85 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice) else Assert(stream->next_buffer_index == stream->oldest_buffer_index); + /* Do we need to issue read-ahead advice? */ + flags = stream->read_buffers_flags; + if (stream->advice_enabled) + { + if (stream->pending_read_blocknum == stream->seq_blocknum) + { + /* + * Sequential: Issue advice until the preadv() calls have caught + * up with the first advice issued for this sequential region, and + * then stay of the way of the kernel's own read-ahead. + */ + if (stream->seq_until_processed != InvalidBlockNumber) + flags |= READ_BUFFERS_ISSUE_ADVICE; + } + else + { + /* + * Random jump: Note the starting location of a new potential + * sequential region and start issuing advice. Skip it this time + * if the preadv() follows immediately, eg first block in stream. + */ + stream->seq_until_processed = stream->pending_read_blocknum; + if (stream->pinned_buffers > 0) + flags |= READ_BUFFERS_ISSUE_ADVICE; + } + } + /* - * If advice hasn't been suppressed, this system supports it, and this - * isn't a strictly sequential pattern, then we'll issue advice. + * How many more buffers is this backend allowed? + * + * Forwarded buffers are already pinned and map to the leading blocks of + * the pending read (the remaining portion of an earlier short read that + * we're about to continue). They are not counted in pinned_buffers, but + * they are counted as pins already held by this backend according to the + * buffer manager, so they must be added to the limit it grants us. */ - if (!suppress_advice && - stream->advice_enabled && - stream->pending_read_blocknum != stream->seq_blocknum) - flags = READ_BUFFERS_ISSUE_ADVICE; + if (stream->temporary) + buffer_limit = Min(GetAdditionalLocalPinLimit(), PG_INT16_MAX); else - flags = 0; + buffer_limit = Min(GetAdditionalPinLimit(), PG_INT16_MAX); + Assert(stream->forwarded_buffers <= stream->pending_read_nblocks); - /* We say how many blocks we want to read, but may be smaller on return. */ + buffer_limit += stream->forwarded_buffers; + buffer_limit = Min(buffer_limit, PG_INT16_MAX); + + if (buffer_limit == 0 && stream->pinned_buffers == 0) + buffer_limit = 1; /* guarantee progress */ + + /* Does the per-backend limit affect this read? */ + nblocks = stream->pending_read_nblocks; + if (buffer_limit < nblocks) + { + int16 new_distance; + + /* Shrink distance: no more look-ahead until buffers are released. */ + new_distance = stream->pinned_buffers + buffer_limit; + if (stream->distance > new_distance) + stream->distance = new_distance; + + /* Unless we have nothing to give the consumer, stop here. */ + if (stream->pinned_buffers > 0) + return false; + + /* A short read is required to make progress. */ + nblocks = buffer_limit; + } + + /* + * We say how many blocks we want to read, but it may be smaller on return + * if the buffer manager decides to shorten the read. Initialize buffers + * to InvalidBuffer (= not a forwarded buffer) as input on first use only, + * and keep the original nblocks number so we can check for forwarded + * buffers as output, below. + */ buffer_index = stream->next_buffer_index; io_index = stream->next_io_index; - nblocks = stream->pending_read_nblocks; + while (stream->initialized_buffers < buffer_index + nblocks) + stream->buffers[stream->initialized_buffers++] = InvalidBuffer; + requested_nblocks = nblocks; need_wait = StartReadBuffers(&stream->ios[io_index].op, &stream->buffers[buffer_index], stream->pending_read_blocknum, @@ -278,7 +342,7 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice) /* Remember whether we need to wait before returning this buffer. */ if (!need_wait) { - /* Look-ahead distance decays, no I/O necessary (behavior A). */ + /* Look-ahead distance decays, no I/O necessary. */ if (stream->distance > 1) stream->distance--; } @@ -296,16 +360,35 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice) stream->seq_blocknum = stream->pending_read_blocknum + nblocks; } + /* + * How many pins were acquired but forwarded to the next call? These need + * to be passed to the next StartReadBuffers() call by leaving them + * exactly where they are in the queue, or released if the stream ends + * early. We need the number for accounting purposes, since they are not + * counted in stream->pinned_buffers but we already hold them. + */ + forwarded = 0; + while (nblocks + forwarded < requested_nblocks && + stream->buffers[buffer_index + nblocks + forwarded] != InvalidBuffer) + forwarded++; + stream->forwarded_buffers = forwarded; + /* * We gave a contiguous range of buffer space to StartReadBuffers(), but - * we want it to wrap around at queue_size. Slide overflowing buffers to - * the front of the array. + * we want it to wrap around at queue_size. Copy overflowing buffers to + * the front of the array where they'll be consumed, but also leave a copy + * in the overflow zone which the I/O operation has a pointer to (it needs + * a contiguous array). Both copies will be cleared when the buffers are + * handed to the consumer. */ - overflow = (buffer_index + nblocks) - stream->queue_size; + overflow = (buffer_index + nblocks + forwarded) - stream->queue_size; if (overflow > 0) - memmove(&stream->buffers[0], - &stream->buffers[stream->queue_size], - sizeof(stream->buffers[0]) * overflow); + { + Assert(overflow < stream->queue_size); /* can't overlap */ + memcpy(&stream->buffers[0], + &stream->buffers[stream->queue_size], + sizeof(stream->buffers[0]) * overflow); + } /* Compute location of start of next read, without using % operator. */ buffer_index += nblocks; @@ -317,11 +400,22 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice) /* Adjust the pending read to cover the remaining portion, if any. */ stream->pending_read_blocknum += nblocks; stream->pending_read_nblocks -= nblocks; + + return true; } static void -read_stream_look_ahead(ReadStream *stream, bool suppress_advice) +read_stream_look_ahead(ReadStream *stream) { + /* + * Allow amortizing the cost of submitting IO over multiple IOs. This + * requires that we don't do any operations that could lead to a deadlock + * with staged-but-unsubmitted IO. The callback needs to opt-in to being + * careful. + */ + if (stream->batch_mode) + pgaio_enter_batchmode(); + while (stream->ios_in_progress < stream->max_ios && stream->pinned_buffers + stream->pending_read_nblocks < stream->distance) { @@ -329,10 +423,9 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice) int16 buffer_index; void *per_buffer_data; - if (stream->pending_read_nblocks == io_combine_limit) + if (stream->pending_read_nblocks == stream->io_combine_limit) { - read_stream_start_pending_read(stream, suppress_advice); - suppress_advice = false; + read_stream_start_pending_read(stream); continue; } @@ -365,12 +458,13 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice) /* We have to start the pending read before we can build another. */ while (stream->pending_read_nblocks > 0) { - read_stream_start_pending_read(stream, suppress_advice); - suppress_advice = false; - if (stream->ios_in_progress == stream->max_ios) + if (!read_stream_start_pending_read(stream) || + stream->ios_in_progress == stream->max_ios) { - /* And we've hit the limit. Rewind, and stop here. */ + /* We've hit the buffer or I/O limit. Rewind and stop here. */ read_stream_unget_block(stream, blocknum); + if (stream->batch_mode) + pgaio_exit_batchmode(); return; } } @@ -386,15 +480,28 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice) * io_combine_limit size once more buffers have been consumed. However, * if we've already reached io_combine_limit, or we've reached the * distance limit and there isn't anything pinned yet, or the callback has - * signaled end-of-stream, we start the read immediately. + * signaled end-of-stream, we start the read immediately. Note that the + * pending read can exceed the distance goal, if the latter was reduced + * after hitting the per-backend buffer limit. */ if (stream->pending_read_nblocks > 0 && - (stream->pending_read_nblocks == io_combine_limit || - (stream->pending_read_nblocks == stream->distance && + (stream->pending_read_nblocks == stream->io_combine_limit || + (stream->pending_read_nblocks >= stream->distance && stream->pinned_buffers == 0) || stream->distance == 0) && stream->ios_in_progress < stream->max_ios) - read_stream_start_pending_read(stream, suppress_advice); + read_stream_start_pending_read(stream); + + /* + * There should always be something pinned when we leave this function, + * whether started by this call or not, unless we've hit the end of the + * stream. In the worst case we can always make progress one buffer at a + * time. + */ + Assert(stream->pinned_buffers > 0 || stream->distance == 0); + + if (stream->batch_mode) + pgaio_exit_batchmode(); } /* @@ -420,9 +527,11 @@ read_stream_begin_impl(int flags, ReadStream *stream; size_t size; int16 queue_size; + int16 queue_overflow; int max_ios; int strategy_pin_limit; uint32 max_pinned_buffers; + uint32 max_possible_buffer_limit; Oid tablespace_id; /* @@ -450,28 +559,52 @@ read_stream_begin_impl(int flags, /* Cap to INT16_MAX to avoid overflowing below */ max_ios = Min(max_ios, PG_INT16_MAX); + /* + * If starting a multi-block I/O near the end of the queue, we might + * temporarily need extra space for overflowing buffers before they are + * moved to regular circular position. This is the maximum extra space we + * could need. + */ + queue_overflow = io_combine_limit - 1; + /* * Choose the maximum number of buffers we're prepared to pin. We try to - * pin fewer if we can, though. We clamp it to at least io_combine_limit - * so that we can have a chance to build up a full io_combine_limit sized - * read, even when max_ios is zero. Be careful not to allow int16 to - * overflow (even though that's not possible with the current GUC range - * limits), allowing also for the spare entry and the overflow space. + * pin fewer if we can, though. We add one so that we can make progress + * even if max_ios is set to 0 (see also further down). For max_ios > 0, + * this also allows an extra full I/O's worth of buffers: after an I/O + * finishes we don't want to have to wait for its buffers to be consumed + * before starting a new one. + * + * Be careful not to allow int16 to overflow. That is possible with the + * current GUC range limits, so this is an artificial limit of ~32k + * buffers and we'd need to adjust the types to exceed that. We also have + * to allow for the spare entry and the overflow space. */ - max_pinned_buffers = Max(max_ios * 4, io_combine_limit); + max_pinned_buffers = (max_ios + 1) * io_combine_limit; max_pinned_buffers = Min(max_pinned_buffers, - PG_INT16_MAX - io_combine_limit - 1); + PG_INT16_MAX - queue_overflow - 1); /* Give the strategy a chance to limit the number of buffers we pin. */ strategy_pin_limit = GetAccessStrategyPinLimit(strategy); max_pinned_buffers = Min(strategy_pin_limit, max_pinned_buffers); - /* Don't allow this backend to pin more than its share of buffers. */ + /* + * Also limit our queue to the maximum number of pins we could ever be + * allowed to acquire according to the buffer manager. We may not really + * be able to use them all due to other pins held by this backend, but + * we'll check that later in read_stream_start_pending_read(). + */ if (SmgrIsTemp(smgr)) - LimitAdditionalLocalPins(&max_pinned_buffers); + max_possible_buffer_limit = GetLocalPinLimit(); else - LimitAdditionalPins(&max_pinned_buffers); - Assert(max_pinned_buffers > 0); + max_possible_buffer_limit = GetPinLimit(); + max_pinned_buffers = Min(max_pinned_buffers, max_possible_buffer_limit); + + /* + * The limit might be zero on a system configured with too few buffers for + * the number of connections. We need at least one to make progress. + */ + max_pinned_buffers = Max(1, max_pinned_buffers); /* * We need one extra entry for buffers and per-buffer data, because users @@ -482,62 +615,79 @@ read_stream_begin_impl(int flags, queue_size = max_pinned_buffers + 1; /* - * Allocate the object, the buffers, the ios and per_data_data space in + * Allocate the object, the buffers, the ios and per_buffer_data space in * one big chunk. Though we have queue_size buffers, we want to be able * to assume that all the buffers for a single read are contiguous (i.e. * don't wrap around halfway through), so we allow temporary overflows of - * up to the maximum possible read size by allocating an extra - * io_combine_limit - 1 elements. + * up to the maximum possible overflow size. */ size = offsetof(ReadStream, buffers); - size += sizeof(Buffer) * (queue_size + io_combine_limit - 1); + size += sizeof(Buffer) * (queue_size + queue_overflow); size += sizeof(InProgressIO) * Max(1, max_ios); size += per_buffer_data_size * queue_size; size += MAXIMUM_ALIGNOF * 2; stream = (ReadStream *) palloc(size); memset(stream, 0, offsetof(ReadStream, buffers)); stream->ios = (InProgressIO *) - MAXALIGN(&stream->buffers[queue_size + io_combine_limit - 1]); + MAXALIGN(&stream->buffers[queue_size + queue_overflow]); if (per_buffer_data_size > 0) stream->per_buffer_data = (void *) MAXALIGN(&stream->ios[Max(1, max_ios)]); + stream->sync_mode = io_method == IOMETHOD_SYNC; + stream->batch_mode = flags & READ_STREAM_USE_BATCHING; + #ifdef USE_PREFETCH /* - * This system supports prefetching advice. We can use it as long as - * direct I/O isn't enabled, the caller hasn't promised sequential access - * (overriding our detection heuristics), and max_ios hasn't been set to - * zero. + * Read-ahead advice simulating asynchronous I/O with synchronous calls. + * Issue advice only if AIO is not used, direct I/O isn't enabled, the + * caller hasn't promised sequential access (overriding our detection + * heuristics), and max_ios hasn't been set to zero. */ - if ((io_direct_flags & IO_DIRECT_DATA) == 0 && + if (stream->sync_mode && + (io_direct_flags & IO_DIRECT_DATA) == 0 && (flags & READ_STREAM_SEQUENTIAL) == 0 && max_ios > 0) stream->advice_enabled = true; #endif /* - * For now, max_ios = 0 is interpreted as max_ios = 1 with advice disabled - * above. If we had real asynchronous I/O we might need a slightly - * different definition. + * Setting max_ios to zero disables AIO and advice-based pseudo AIO, but + * we still need to allocate space to combine and run one I/O. Bump it up + * to one, and remember to ask for synchronous I/O only. */ if (max_ios == 0) + { max_ios = 1; + stream->read_buffers_flags = READ_BUFFERS_SYNCHRONOUSLY; + } + /* + * Capture stable values for these two GUC-derived numbers for the + * lifetime of this stream, so we don't have to worry about the GUCs + * changing underneath us beyond this point. + */ stream->max_ios = max_ios; + stream->io_combine_limit = io_combine_limit; + stream->per_buffer_data_size = per_buffer_data_size; stream->max_pinned_buffers = max_pinned_buffers; stream->queue_size = queue_size; stream->callback = callback; stream->callback_private_data = callback_private_data; + stream->buffered_blocknum = InvalidBlockNumber; + stream->seq_blocknum = InvalidBlockNumber; + stream->seq_until_processed = InvalidBlockNumber; + stream->temporary = SmgrIsTemp(smgr); /* * Skip the initial ramp-up phase if the caller says we're going to be * reading the whole relation. This way we start out assuming we'll be - * doing full io_combine_limit sized reads (behavior B). + * doing full io_combine_limit sized reads. */ if (flags & READ_STREAM_FULL) - stream->distance = Min(max_pinned_buffers, io_combine_limit); + stream->distance = Min(max_pinned_buffers, stream->io_combine_limit); else stream->distance = 1; @@ -625,10 +775,10 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) #ifndef READ_STREAM_DISABLE_FAST_PATH /* - * A fast path for all-cached scans (behavior A). This is the same as the - * usual algorithm, but it is specialized for no I/O and no per-buffer - * data, so we can skip the queue management code, stay in the same buffer - * slot and use singular StartReadBuffer(). + * A fast path for all-cached scans. This is the same as the usual + * algorithm, but it is specialized for no I/O and no per-buffer data, so + * we can skip the queue management code, stay in the same buffer slot and + * use singular StartReadBuffer(). */ if (likely(stream->fast_path)) { @@ -636,10 +786,12 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) /* Fast path assumptions. */ Assert(stream->ios_in_progress == 0); + Assert(stream->forwarded_buffers == 0); Assert(stream->pinned_buffers == 1); Assert(stream->distance == 1); Assert(stream->pending_read_nblocks == 0); Assert(stream->per_buffer_data_size == 0); + Assert(stream->initialized_buffers > stream->oldest_buffer_index); /* We're going to return the buffer we pinned last time. */ oldest_buffer_index = stream->oldest_buffer_index; @@ -649,23 +801,31 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) Assert(buffer != InvalidBuffer); /* Choose the next block to pin. */ - if (unlikely(stream->blocknums_next == stream->blocknums_count)) - read_stream_fill_blocknums(stream); - next_blocknum = stream->blocknums[stream->blocknums_next++]; + next_blocknum = read_stream_get_block(stream, NULL); if (likely(next_blocknum != InvalidBlockNumber)) { + int flags = stream->read_buffers_flags; + + if (stream->advice_enabled) + flags |= READ_BUFFERS_ISSUE_ADVICE; + /* * Pin a buffer for the next call. Same buffer entry, and * arbitrary I/O entry (they're all free). We don't have to * adjust pinned_buffers because we're transferring one to caller * but pinning one more. + * + * In the fast path we don't need to check the pin limit. We're + * always allowed at least one pin so that progress can be made, + * and that's all we need here. Although two pins are momentarily + * held at the same time, the model used here is that the stream + * holds only one, and the other now belongs to the caller. */ if (likely(!StartReadBuffer(&stream->ios[0].op, &stream->buffers[oldest_buffer_index], next_blocknum, - stream->advice_enabled ? - READ_BUFFERS_ISSUE_ADVICE : 0))) + flags))) { /* Fast return. */ return buffer; @@ -684,6 +844,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) stream->distance = 0; stream->oldest_buffer_index = stream->next_buffer_index; stream->pinned_buffers = 0; + stream->buffers[oldest_buffer_index] = InvalidBuffer; } stream->fast_path = false; @@ -705,7 +866,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) * space for more, but if we're just starting up we'll need to crank * the handle to get started. */ - read_stream_look_ahead(stream, true); + read_stream_look_ahead(stream); /* End of stream reached? */ if (stream->pinned_buffers == 0) @@ -731,7 +892,7 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) stream->ios[stream->oldest_io_index].buffer_index == oldest_buffer_index) { int16 io_index = stream->oldest_io_index; - int16 distance; + int32 distance; /* wider temporary value, clamped below */ /* Sanity check that we still agree on the buffers. */ Assert(stream->ios[io_index].op.buffers == @@ -744,33 +905,32 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) if (++stream->oldest_io_index == stream->max_ios) stream->oldest_io_index = 0; - if (stream->ios[io_index].op.flags & READ_BUFFERS_ISSUE_ADVICE) - { - /* Distance ramps up fast (behavior C). */ - distance = stream->distance * 2; - distance = Min(distance, stream->max_pinned_buffers); - stream->distance = distance; - } - else - { - /* No advice; move towards io_combine_limit (behavior B). */ - if (stream->distance > io_combine_limit) - { - stream->distance--; - } - else - { - distance = stream->distance * 2; - distance = Min(distance, io_combine_limit); - distance = Min(distance, stream->max_pinned_buffers); - stream->distance = distance; - } - } + /* Look-ahead distance ramps up rapidly after we do I/O. */ + distance = stream->distance * 2; + distance = Min(distance, stream->max_pinned_buffers); + stream->distance = distance; + + /* + * If we've reached the first block of a sequential region we're + * issuing advice for, cancel that until the next jump. The kernel + * will see the sequential preadv() pattern starting here. + */ + if (stream->advice_enabled && + stream->ios[io_index].op.blocknum == stream->seq_until_processed) + stream->seq_until_processed = InvalidBlockNumber; } -#ifdef CLOBBER_FREED_MEMORY - /* Clobber old buffer and per-buffer data for debugging purposes. */ + /* + * We must zap this queue entry, or else it would appear as a forwarded + * buffer. If it's potentially in the overflow zone (ie from a + * multi-block I/O that wrapped around the queue), also zap the copy. + */ stream->buffers[oldest_buffer_index] = InvalidBuffer; + if (oldest_buffer_index < stream->io_combine_limit - 1) + stream->buffers[stream->queue_size + oldest_buffer_index] = + InvalidBuffer; + +#if defined(CLOBBER_FREED_MEMORY) || defined(USE_VALGRIND) /* * The caller will get access to the per-buffer data, until the next call. @@ -779,11 +939,23 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) * that is holding a dangling pointer to it. */ if (stream->per_buffer_data) - wipe_mem(get_per_buffer_data(stream, - oldest_buffer_index == 0 ? - stream->queue_size - 1 : - oldest_buffer_index - 1), - stream->per_buffer_data_size); + { + void *per_buffer_data; + + per_buffer_data = get_per_buffer_data(stream, + oldest_buffer_index == 0 ? + stream->queue_size - 1 : + oldest_buffer_index - 1); + +#if defined(CLOBBER_FREED_MEMORY) + /* This also tells Valgrind the memory is "noaccess". */ + wipe_mem(per_buffer_data, stream->per_buffer_data_size); +#elif defined(USE_VALGRIND) + /* Tell it ourselves. */ + VALGRIND_MAKE_MEM_NOACCESS(per_buffer_data, + stream->per_buffer_data_size); +#endif + } #endif /* Pin transferred to caller. */ @@ -796,11 +968,12 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) stream->oldest_buffer_index = 0; /* Prepare for the next call. */ - read_stream_look_ahead(stream, false); + read_stream_look_ahead(stream); #ifndef READ_STREAM_DISABLE_FAST_PATH /* See if we can take the fast path for all-cached scans next time. */ if (stream->ios_in_progress == 0 && + stream->forwarded_buffers == 0 && stream->pinned_buffers == 1 && stream->distance == 1 && stream->pending_read_nblocks == 0 && @@ -813,6 +986,20 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) return buffer; } +/* + * Transitional support for code that would like to perform or skip reads + * itself, without using the stream. Returns, and consumes, the next block + * number that would be read by the stream's look-ahead algorithm, or + * InvalidBlockNumber if the end of the stream is reached. Also reports the + * strategy that would be used to read it. + */ +BlockNumber +read_stream_next_block(ReadStream *stream, BufferAccessStrategy *strategy) +{ + *strategy = stream->ios[0].op.strategy; + return read_stream_get_block(stream, NULL); +} + /* * Reset a read stream by releasing any queued up buffers, allowing the stream * to be used again for different blocks. This can be used to clear an @@ -822,20 +1009,38 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) void read_stream_reset(ReadStream *stream) { + int16 index; Buffer buffer; /* Stop looking ahead. */ stream->distance = 0; - /* Forget buffered block numbers and fast path state. */ - stream->blocknums_next = 0; - stream->blocknums_count = 0; + /* Forget buffered block number and fast path state. */ + stream->buffered_blocknum = InvalidBlockNumber; stream->fast_path = false; /* Unpin anything that wasn't consumed. */ while ((buffer = read_stream_next_buffer(stream, NULL)) != InvalidBuffer) ReleaseBuffer(buffer); + /* Unpin any unused forwarded buffers. */ + index = stream->next_buffer_index; + while (index < stream->initialized_buffers && + (buffer = stream->buffers[index]) != InvalidBuffer) + { + Assert(stream->forwarded_buffers > 0); + stream->forwarded_buffers--; + ReleaseBuffer(buffer); + + stream->buffers[index] = InvalidBuffer; + if (index < stream->io_combine_limit - 1) + stream->buffers[stream->queue_size + index] = InvalidBuffer; + + if (++index == stream->queue_size) + index = 0; + } + + Assert(stream->forwarded_buffers == 0); Assert(stream->pinned_buffers == 0); Assert(stream->ios_in_progress == 0); diff --git a/src/backend/storage/buffer/README b/src/backend/storage/buffer/README index 011af7aff3e30..a182fcd660ccb 100644 --- a/src/backend/storage/buffer/README +++ b/src/backend/storage/buffer/README @@ -147,9 +147,12 @@ in the buffer. It is used per the rules above. * The BM_IO_IN_PROGRESS flag acts as a kind of lock, used to wait for I/O on a buffer to complete (and in releases before 14, it was accompanied by a -per-buffer LWLock). The process doing a read or write sets the flag for the -duration, and processes that need to wait for it to be cleared sleep on a -condition variable. +per-buffer LWLock). The process starting a read or write sets the flag. When +the I/O is completed, be it by the process that initiated the I/O or by +another process, the flag is removed and the Buffer's condition variable is +signalled. Processes that need to wait for the I/O to complete can wait for +asynchronous I/O by using BufferDesc->io_wref and for BM_IO_IN_PROGRESS to be +unset by sleeping on the buffer's condition variable. Normal Buffer Replacement Strategy diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index 46116a1f64be1..ed1dc488a42b4 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -3,7 +3,7 @@ * buf_init.c * buffer manager initialization routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,9 +14,9 @@ */ #include "postgres.h" +#include "storage/aio.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" -#include "storage/proc.h" BufferDescPadded *BufferDescriptors; char *BufferBlocks; @@ -65,7 +65,7 @@ CkptSortItem *CkptBufferIds; * postmaster, or in a standalone backend). */ void -InitBufferPool(void) +BufferManagerShmemInit(void) { bool foundBufs, foundDescs, @@ -126,6 +126,8 @@ InitBufferPool(void) buf->buf_id = i; + pgaio_wref_clear(&buf->io_wref); + /* * Initially link all the buffers together as unused. Subsequent * management of this list is done by freelist.c. @@ -151,13 +153,13 @@ InitBufferPool(void) } /* - * BufferShmemSize + * BufferManagerShmemSize * * compute the size of shared memory for the buffer pool including * data pages, buffer descriptors, hash tables, etc. */ Size -BufferShmemSize(void) +BufferManagerShmemSize(void) { Size size = 0; diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c index 0fa54689303a9..a50955d5286ca 100644 --- a/src/backend/storage/buffer/buf_table.c +++ b/src/backend/storage/buffer/buf_table.c @@ -10,7 +10,7 @@ * before the lock is released (see notes in README). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -77,7 +77,7 @@ InitBufTable(int size) uint32 BufTableHashCode(BufferTag *tagPtr) { - return get_hash_value(SharedBufHash, (void *) tagPtr); + return get_hash_value(SharedBufHash, tagPtr); } /* diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 4415ba648ae43..667aa0c0c78d4 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -3,7 +3,7 @@ * bufmgr.c * buffer manager interface routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -40,6 +40,9 @@ #include "access/tableam.h" #include "access/xloginsert.h" #include "access/xlogutils.h" +#ifdef USE_ASSERT_CHECKING +#include "catalog/pg_tablespace_d.h" +#endif #include "catalog/storage.h" #include "catalog/storage_xlog.h" #include "executor/instrument.h" @@ -48,6 +51,7 @@ #include "pg_trace.h" #include "pgstat.h" #include "postmaster/bgwriter.h" +#include "storage/aio.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/fd.h" @@ -136,33 +140,6 @@ typedef struct SMgrSortArray SMgrRelation srel; } SMgrSortArray; -/* - * Helper struct for read stream object used in - * RelationCopyStorageUsingBuffer() function. - */ -struct copy_storage_using_buffer_read_stream_private -{ - BlockNumber blocknum; - BlockNumber nblocks; -}; - -/* - * Callback function to get next block for read stream object used in - * RelationCopyStorageUsingBuffer() function. - */ -static BlockNumber -copy_storage_using_buffer_read_stream_next_block(ReadStream *stream, - void *callback_private_data, - void *per_buffer_data) -{ - struct copy_storage_using_buffer_read_stream_private *p = callback_private_data; - - if (p->blocknum < p->nblocks) - return p->blocknum++; - - return InvalidBlockNumber; -} - /* GUC variables */ bool zero_damaged_pages = false; int bgwriter_lru_maxpages = 100; @@ -187,9 +164,12 @@ int maintenance_io_concurrency = DEFAULT_MAINTENANCE_IO_CONCURRENCY; /* * Limit on how many blocks should be handled in single I/O operations. * StartReadBuffers() callers should respect it, as should other operations - * that call smgr APIs directly. + * that call smgr APIs directly. It is computed as the minimum of underlying + * GUCs io_combine_limit_guc and io_max_combine_limit. */ int io_combine_limit = DEFAULT_IO_COMBINE_LIMIT; +int io_combine_limit_guc = DEFAULT_IO_COMBINE_LIMIT; +int io_max_combine_limit = DEFAULT_IO_COMBINE_LIMIT; /* * GUC variables about triggering kernel writeback for buffers written; OS @@ -238,6 +218,8 @@ static int32 PrivateRefCountOverflowed = 0; static uint32 PrivateRefCountClock = 0; static PrivateRefCountEntry *ReservedRefCountEntry = NULL; +static uint32 MaxProportionalPins; + static void ReservePrivateRefCountEntry(void); static PrivateRefCountEntry *NewPrivateRefCountEntry(Buffer buffer); static PrivateRefCountEntry *GetPrivateRefCountEntry(Buffer buffer, bool do_move); @@ -539,9 +521,6 @@ static uint32 WaitBufHdrUnlocked(BufferDesc *buf); static int SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context); static void WaitIO(BufferDesc *buf); -static bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait); -static void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, - uint32 set_flag_bits, bool forget_owner); static void AbortBufferIO(Buffer buffer); static void shared_buffer_write_error_callback(void *arg); static void local_buffer_write_error_callback(void *arg); @@ -551,6 +530,8 @@ static inline BufferDesc *BufferAlloc(SMgrRelation smgr, BlockNumber blockNum, BufferAccessStrategy strategy, bool *foundPtr, IOContext io_context); +static bool AsyncReadBuffers(ReadBuffersOperation *operation, int *nblocks_progress); +static void CheckReadBuffersOperation(ReadBuffersOperation *operation, bool is_complete); static Buffer GetVictimBuffer(BufferAccessStrategy strategy, IOContext io_context); static void FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, IOContext io_context); @@ -563,6 +544,10 @@ static void RelationCopyStorageUsingBuffer(RelFileLocator srclocator, ForkNumber forkNum, bool permanent); static void AtProcExit_Buffers(int code, Datum arg); static void CheckForBufferLeaks(void); +#ifdef USE_ASSERT_CHECKING +static void AssertNotCatalogBufferLock(LWLock *lock, LWLockMode mode, + void *unused_context); +#endif static int rlocator_comparator(const void *p1, const void *p2); static inline int buffertag_comparator(const BufferTag *ba, const BufferTag *bb); static inline int ckpt_buforder_comparator(const CkptSortItem *a, const CkptSortItem *b); @@ -792,7 +777,7 @@ ReadBuffer(Relation reln, BlockNumber blockNum) * In RBM_NORMAL mode, the page is read from disk, and the page header is * validated. An error is thrown if the page header is not valid. (But * note that an all-zero page is considered "valid"; see - * PageIsVerifiedExtended().) + * PageIsVerified().) * * RBM_ZERO_ON_ERROR is like the normal mode, but if the page header is not * valid, the page is zeroed instead of throwing an error. This is intended @@ -1063,7 +1048,7 @@ ZeroAndLockBuffer(Buffer buffer, ReadBufferMode mode, bool already_valid) { /* Simple case for non-shared buffers. */ bufHdr = GetLocalBufferDescriptor(-buffer - 1); - need_to_zero = (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0; + need_to_zero = StartLocalBufferIO(bufHdr, true, false); } else { @@ -1097,19 +1082,11 @@ ZeroAndLockBuffer(Buffer buffer, ReadBufferMode mode, bool already_valid) if (!isLocalBuf) LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_EXCLUSIVE); + /* Set BM_VALID, terminate IO, and wake up any waiters */ if (isLocalBuf) - { - /* Only need to adjust flags */ - uint32 buf_state = pg_atomic_read_u32(&bufHdr->state); - - buf_state |= BM_VALID; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); - } + TerminateLocalBufferIO(bufHdr, false, BM_VALID, false); else - { - /* Set BM_VALID, terminate IO, and wake up any waiters */ - TerminateBufferIO(bufHdr, false, BM_VALID, true); - } + TerminateBufferIO(bufHdr, false, BM_VALID, true, false); } else if (!isLocalBuf) { @@ -1192,8 +1169,7 @@ PinBufferForBlock(Relation rel, } if (*foundPtr) { - VacuumPageHit++; - pgstat_count_io_op(io_object, io_context, IOOP_HIT); + pgstat_count_io_op(io_object, io_context, IOOP_HIT, 1, 0); if (VacuumCostActive) VacuumCostBalance += VacuumCostPageHit; @@ -1260,10 +1236,14 @@ ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence, return buffer; } + /* + * Signal that we are going to immediately wait. If we're immediately + * waiting, there is no benefit in actually executing the IO + * asynchronously, it would just add dispatch overhead. + */ + flags = READ_BUFFERS_SYNCHRONOUSLY; if (mode == RBM_ZERO_ON_ERROR) - flags = READ_BUFFERS_ZERO_ON_ERROR; - else - flags = 0; + flags |= READ_BUFFERS_ZERO_ON_ERROR; operation.smgr = smgr; operation.rel = rel; operation.persistence = persistence; @@ -1283,11 +1263,14 @@ StartReadBuffersImpl(ReadBuffersOperation *operation, Buffer *buffers, BlockNumber blockNum, int *nblocks, - int flags) + int flags, + bool allow_forwarding) { int actual_nblocks = *nblocks; - int io_buffers_len = 0; + int maxcombine = 0; + bool did_start_io; + Assert(*nblocks == 1 || allow_forwarding); Assert(*nblocks > 0); Assert(*nblocks <= MAX_IO_COMBINE_LIMIT); @@ -1295,78 +1278,212 @@ StartReadBuffersImpl(ReadBuffersOperation *operation, { bool found; - buffers[i] = PinBufferForBlock(operation->rel, - operation->smgr, - operation->persistence, - operation->forknum, - blockNum + i, - operation->strategy, - &found); + if (allow_forwarding && buffers[i] != InvalidBuffer) + { + BufferDesc *bufHdr; + + /* + * This is a buffer that was pinned by an earlier call to + * StartReadBuffers(), but couldn't be handled in one operation at + * that time. The operation was split, and the caller has passed + * an already pinned buffer back to us to handle the rest of the + * operation. It must continue at the expected block number. + */ + Assert(BufferGetBlockNumber(buffers[i]) == blockNum + i); + + /* + * It might be an already valid buffer (a hit) that followed the + * final contiguous block of an earlier I/O (a miss) marking the + * end of it, or a buffer that some other backend has since made + * valid by performing the I/O for us, in which case we can handle + * it as a hit now. It is safe to check for a BM_VALID flag with + * a relaxed load, because we got a fresh view of it while pinning + * it in the previous call. + * + * On the other hand if we don't see BM_VALID yet, it must be an + * I/O that was split by the previous call and we need to try to + * start a new I/O from this block. We're also racing against any + * other backend that might start the I/O or even manage to mark + * it BM_VALID after this check, but StartBufferIO() will handle + * those cases. + */ + if (BufferIsLocal(buffers[i])) + bufHdr = GetLocalBufferDescriptor(-buffers[i] - 1); + else + bufHdr = GetBufferDescriptor(buffers[i] - 1); + Assert(pg_atomic_read_u32(&bufHdr->state) & BM_TAG_VALID); + found = pg_atomic_read_u32(&bufHdr->state) & BM_VALID; + } + else + { + buffers[i] = PinBufferForBlock(operation->rel, + operation->smgr, + operation->persistence, + operation->forknum, + blockNum + i, + operation->strategy, + &found); + } if (found) { /* - * Terminate the read as soon as we get a hit. It could be a - * single buffer hit, or it could be a hit that follows a readable - * range. We don't want to create more than one readable range, - * so we stop here. + * We have a hit. If it's the first block in the requested range, + * we can return it immediately and report that WaitReadBuffers() + * does not need to be called. If the initial value of *nblocks + * was larger, the caller will have to call again for the rest. + */ + if (i == 0) + { + *nblocks = 1; + +#ifdef USE_ASSERT_CHECKING + + /* + * Initialize enough of ReadBuffersOperation to make + * CheckReadBuffersOperation() work. Outside of assertions + * that's not necessary when no IO is issued. + */ + operation->buffers = buffers; + operation->blocknum = blockNum; + operation->nblocks = 1; + operation->nblocks_done = 1; + CheckReadBuffersOperation(operation, true); +#endif + return false; + } + + /* + * Otherwise we already have an I/O to perform, but this block + * can't be included as it is already valid. Split the I/O here. + * There may or may not be more blocks requiring I/O after this + * one, we haven't checked, but they can't be contiguous with this + * one in the way. We'll leave this buffer pinned, forwarding it + * to the next call, avoiding the need to unpin it here and re-pin + * it in the next call. */ - actual_nblocks = i + 1; + actual_nblocks = i; break; } else { - /* Extend the readable range to cover this block. */ - io_buffers_len++; + /* + * Check how many blocks we can cover with the same IO. The smgr + * implementation might e.g. be limited due to a segment boundary. + */ + if (i == 0 && actual_nblocks > 1) + { + maxcombine = smgrmaxcombine(operation->smgr, + operation->forknum, + blockNum); + if (unlikely(maxcombine < actual_nblocks)) + { + elog(DEBUG2, "limiting nblocks at %u from %u to %u", + blockNum, actual_nblocks, maxcombine); + actual_nblocks = maxcombine; + } + } } } *nblocks = actual_nblocks; - if (likely(io_buffers_len == 0)) - return false; - /* Populate information needed for I/O. */ operation->buffers = buffers; operation->blocknum = blockNum; operation->flags = flags; operation->nblocks = actual_nblocks; - operation->io_buffers_len = io_buffers_len; + operation->nblocks_done = 0; + pgaio_wref_clear(&operation->io_wref); + + /* + * When using AIO, start the IO in the background. If not, issue prefetch + * requests if desired by the caller. + * + * The reason we have a dedicated path for IOMETHOD_SYNC here is to + * de-risk the introduction of AIO somewhat. It's a large architectural + * change, with lots of chances for unanticipated performance effects. + * + * Use of IOMETHOD_SYNC already leads to not actually performing IO + * asynchronously, but without the check here we'd execute IO earlier than + * we used to. Eventually this IOMETHOD_SYNC specific path should go away. + */ + if (io_method != IOMETHOD_SYNC) + { + /* + * Try to start IO asynchronously. It's possible that no IO needs to + * be started, if another backend already performed the IO. + * + * Note that if an IO is started, it might not cover the entire + * requested range, e.g. because an intermediary block has been read + * in by another backend. In that case any "trailing" buffers we + * already pinned above will be "forwarded" by read_stream.c to the + * next call to StartReadBuffers(). + * + * This is signalled to the caller by decrementing *nblocks *and* + * reducing operation->nblocks. The latter is done here, but not below + * WaitReadBuffers(), as in WaitReadBuffers() we can't "shorten" the + * overall read size anymore, we need to retry until done in its + * entirety or until failed. + */ + did_start_io = AsyncReadBuffers(operation, nblocks); - if (flags & READ_BUFFERS_ISSUE_ADVICE) + operation->nblocks = *nblocks; + } + else { + operation->flags |= READ_BUFFERS_SYNCHRONOUSLY; + + if (flags & READ_BUFFERS_ISSUE_ADVICE) + { + /* + * In theory we should only do this if PinBufferForBlock() had to + * allocate new buffers above. That way, if two calls to + * StartReadBuffers() were made for the same blocks before + * WaitReadBuffers(), only the first would issue the advice. + * That'd be a better simulation of true asynchronous I/O, which + * would only start the I/O once, but isn't done here for + * simplicity. + */ + smgrprefetch(operation->smgr, + operation->forknum, + blockNum, + actual_nblocks); + } + /* - * In theory we should only do this if PinBufferForBlock() had to - * allocate new buffers above. That way, if two calls to - * StartReadBuffers() were made for the same blocks before - * WaitReadBuffers(), only the first would issue the advice. That'd be - * a better simulation of true asynchronous I/O, which would only - * start the I/O once, but isn't done here for simplicity. Note also - * that the following call might actually issue two advice calls if we - * cross a segment boundary; in a true asynchronous version we might - * choose to process only one real I/O at a time in that case. + * Indicate that WaitReadBuffers() should be called. WaitReadBuffers() + * will initiate the necessary IO. */ - smgrprefetch(operation->smgr, - operation->forknum, - blockNum, - operation->io_buffers_len); + did_start_io = true; } - /* Indicate that WaitReadBuffers() should be called. */ - return true; + CheckReadBuffersOperation(operation, !did_start_io); + + return did_start_io; } /* * Begin reading a range of blocks beginning at blockNum and extending for - * *nblocks. On return, up to *nblocks pinned buffers holding those blocks - * are written into the buffers array, and *nblocks is updated to contain the - * actual number, which may be fewer than requested. Caller sets some of the - * members of operation; see struct definition. - * - * If false is returned, no I/O is necessary. If true is returned, one I/O - * has been started, and WaitReadBuffers() must be called with the same - * operation object before the buffers are accessed. Along with the operation - * object, the caller-supplied array of buffers must remain valid until - * WaitReadBuffers() is called. + * *nblocks. *nblocks and the buffers array are in/out parameters. On entry, + * the buffers elements covered by *nblocks must hold either InvalidBuffer or + * buffers forwarded by an earlier call to StartReadBuffers() that was split + * and is now being continued. On return, *nblocks holds the number of blocks + * accepted by this operation. If it is less than the original number then + * this operation has been split, but buffer elements up to the original + * requested size may hold forwarded buffers to be used for a continuing + * operation. The caller must either start a new I/O beginning at the block + * immediately following the blocks accepted by this call and pass those + * buffers back in, or release them if it chooses not to. It shouldn't make + * any other use of or assumptions about forwarded buffers. + * + * If false is returned, no I/O is necessary and the buffers covered by + * *nblocks on exit are valid and ready to be accessed. If true is returned, + * an I/O has been started, and WaitReadBuffers() must be called with the same + * operation object before the buffers covered by *nblocks on exit can be + * accessed. Along with the operation object, the caller-supplied array of + * buffers must remain valid until WaitReadBuffers() is called, and any + * forwarded buffers must also be preserved for a continuing call unless + * they are explicitly released. * * Currently the I/O is only started with optional operating system advice if * requested by the caller with READ_BUFFERS_ISSUE_ADVICE, and the real I/O @@ -1380,13 +1497,17 @@ StartReadBuffers(ReadBuffersOperation *operation, int *nblocks, int flags) { - return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags); + return StartReadBuffersImpl(operation, buffers, blockNum, nblocks, flags, + true /* expect forwarded buffers */ ); } /* * Single block version of the StartReadBuffers(). This might save a few * instructions when called from another translation unit, because it is * specialized for nblocks == 1. + * + * This version does not support "forwarded" buffers: they cannot be created + * by reading only one block and *buffer is ignored on entry. */ bool StartReadBuffer(ReadBuffersOperation *operation, @@ -1397,55 +1518,129 @@ StartReadBuffer(ReadBuffersOperation *operation, int nblocks = 1; bool result; - result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags); + result = StartReadBuffersImpl(operation, buffer, blocknum, &nblocks, flags, + false /* single block, no forwarding */ ); Assert(nblocks == 1); /* single block can't be short */ return result; } -static inline bool -WaitReadBuffersCanStartIO(Buffer buffer, bool nowait) +/* + * Perform sanity checks on the ReadBuffersOperation. + */ +static void +CheckReadBuffersOperation(ReadBuffersOperation *operation, bool is_complete) { - if (BufferIsLocal(buffer)) +#ifdef USE_ASSERT_CHECKING + Assert(operation->nblocks_done <= operation->nblocks); + Assert(!is_complete || operation->nblocks == operation->nblocks_done); + + for (int i = 0; i < operation->nblocks; i++) { - BufferDesc *bufHdr = GetLocalBufferDescriptor(-buffer - 1); + Buffer buffer = operation->buffers[i]; + BufferDesc *buf_hdr = BufferIsLocal(buffer) ? + GetLocalBufferDescriptor(-buffer - 1) : + GetBufferDescriptor(buffer - 1); - return (pg_atomic_read_u32(&bufHdr->state) & BM_VALID) == 0; + Assert(BufferGetBlockNumber(buffer) == operation->blocknum + i); + Assert(pg_atomic_read_u32(&buf_hdr->state) & BM_TAG_VALID); + + if (i < operation->nblocks_done) + Assert(pg_atomic_read_u32(&buf_hdr->state) & BM_VALID); } +#endif +} + +/* helper for ReadBuffersCanStartIO(), to avoid repetition */ +static inline bool +ReadBuffersCanStartIOOnce(Buffer buffer, bool nowait) +{ + if (BufferIsLocal(buffer)) + return StartLocalBufferIO(GetLocalBufferDescriptor(-buffer - 1), + true, nowait); else return StartBufferIO(GetBufferDescriptor(buffer - 1), true, nowait); } -void -WaitReadBuffers(ReadBuffersOperation *operation) +/* + * Helper for AsyncReadBuffers that tries to get the buffer ready for IO. + */ +static inline bool +ReadBuffersCanStartIO(Buffer buffer, bool nowait) { - Buffer *buffers; - int nblocks; - BlockNumber blocknum; - ForkNumber forknum; - IOContext io_context; - IOObject io_object; - char persistence; + /* + * If this backend currently has staged IO, we need to submit the pending + * IO before waiting for the right to issue IO, to avoid the potential for + * deadlocks (and, more commonly, unnecessary delays for other backends). + */ + if (!nowait && pgaio_have_staged()) + { + if (ReadBuffersCanStartIOOnce(buffer, true)) + return true; + + /* + * Unfortunately StartBufferIO() returning false doesn't allow to + * distinguish between the buffer already being valid and IO already + * being in progress. Since IO already being in progress is quite + * rare, this approach seems fine. + */ + pgaio_submit_staged(); + } + + return ReadBuffersCanStartIOOnce(buffer, nowait); +} + +/* + * Helper for WaitReadBuffers() that processes the results of a readv + * operation, raising an error if necessary. + */ +static void +ProcessReadBuffersResult(ReadBuffersOperation *operation) +{ + PgAioReturn *aio_ret = &operation->io_return; + PgAioResultStatus rs = aio_ret->result.status; + int newly_read_blocks = 0; + + Assert(pgaio_wref_valid(&operation->io_wref)); + Assert(aio_ret->result.status != PGAIO_RS_UNKNOWN); /* - * Currently operations are only allowed to include a read of some range, - * with an optional extra buffer that is already pinned at the end. So - * nblocks can be at most one more than io_buffers_len. + * SMGR reports the number of blocks successfully read as the result of + * the IO operation. Thus we can simply add that to ->nblocks_done. */ - Assert((operation->nblocks == operation->io_buffers_len) || - (operation->nblocks == operation->io_buffers_len + 1)); - /* Find the range of the physical read we need to perform. */ - nblocks = operation->io_buffers_len; - if (nblocks == 0) - return; /* nothing to do */ + if (likely(rs != PGAIO_RS_ERROR)) + newly_read_blocks = aio_ret->result.result; - buffers = &operation->buffers[0]; - blocknum = operation->blocknum; - forknum = operation->forknum; - persistence = operation->persistence; + if (rs == PGAIO_RS_ERROR || rs == PGAIO_RS_WARNING) + pgaio_result_report(aio_ret->result, &aio_ret->target_data, + rs == PGAIO_RS_ERROR ? ERROR : WARNING); + else if (aio_ret->result.status == PGAIO_RS_PARTIAL) + { + /* + * We'll retry, so we just emit a debug message to the server log (or + * not even that in prod scenarios). + */ + pgaio_result_report(aio_ret->result, &aio_ret->target_data, DEBUG1); + elog(DEBUG3, "partial read, will retry"); + } - if (persistence == RELPERSISTENCE_TEMP) + Assert(newly_read_blocks > 0); + Assert(newly_read_blocks <= MAX_IO_COMBINE_LIMIT); + + operation->nblocks_done += newly_read_blocks; + + Assert(operation->nblocks_done <= operation->nblocks); +} + +void +WaitReadBuffers(ReadBuffersOperation *operation) +{ + PgAioReturn *aio_ret = &operation->io_return; + IOContext io_context; + IOObject io_object; + + if (operation->persistence == RELPERSISTENCE_TEMP) { io_context = IOCONTEXT_NORMAL; io_object = IOOBJECT_TEMP_RELATION; @@ -1457,199 +1652,392 @@ WaitReadBuffers(ReadBuffersOperation *operation) } /* - * We count all these blocks as read by this backend. This is traditional - * behavior, but might turn out to be not true if we find that someone - * else has beaten us and completed the read of some of these blocks. In - * that case the system globally double-counts, but we traditionally don't - * count this as a "hit", and we don't have a separate counter for "miss, - * but another backend completed the read". + * If we get here without an IO operation having been issued, the + * io_method == IOMETHOD_SYNC path must have been used. Otherwise the + * caller should not have called WaitReadBuffers(). + * + * In the case of IOMETHOD_SYNC, we start - as we used to before the + * introducing of AIO - the IO in WaitReadBuffers(). This is done as part + * of the retry logic below, no extra code is required. + * + * This path is expected to eventually go away. */ - if (persistence == RELPERSISTENCE_TEMP) - pgBufferUsage.local_blks_read += nblocks; - else - pgBufferUsage.shared_blks_read += nblocks; + if (!pgaio_wref_valid(&operation->io_wref) && io_method != IOMETHOD_SYNC) + elog(ERROR, "waiting for read operation that didn't read"); - for (int i = 0; i < nblocks; ++i) + /* + * To handle partial reads, and IOMETHOD_SYNC, we re-issue IO until we're + * done. We may need multiple retries, not just because we could get + * multiple partial reads, but also because some of the remaining + * to-be-read buffers may have been read in by other backends, limiting + * the IO size. + */ + while (true) { - int io_buffers_len; - Buffer io_buffers[MAX_IO_COMBINE_LIMIT]; - void *io_pages[MAX_IO_COMBINE_LIMIT]; - instr_time io_start; - BlockNumber io_first_block; + int ignored_nblocks_progress; + + CheckReadBuffersOperation(operation, false); /* - * Skip this block if someone else has already completed it. If an - * I/O is already in progress in another backend, this will wait for - * the outcome: either done, or something went wrong and we will - * retry. + * If there is an IO associated with the operation, we may need to + * wait for it. */ - if (!WaitReadBuffersCanStartIO(buffers[i], false)) + if (pgaio_wref_valid(&operation->io_wref)) { /* - * Report this as a 'hit' for this backend, even though it must - * have started out as a miss in PinBufferForBlock(). + * Track the time spent waiting for the IO to complete. As + * tracking a wait even if we don't actually need to wait + * + * a) is not cheap, due to the timestamping overhead + * + * b) reports some time as waiting, even if we never waited + * + * we first check if we already know the IO is complete. */ - TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i, - operation->smgr->smgr_rlocator.locator.spcOid, - operation->smgr->smgr_rlocator.locator.dbOid, - operation->smgr->smgr_rlocator.locator.relNumber, - operation->smgr->smgr_rlocator.backend, - true); - continue; - } - - /* We found a buffer that we need to read in. */ - io_buffers[0] = buffers[i]; - io_pages[0] = BufferGetBlock(buffers[i]); - io_first_block = blocknum + i; - io_buffers_len = 1; - - /* - * How many neighboring-on-disk blocks can we can scatter-read into - * other buffers at the same time? In this case we don't wait if we - * see an I/O already in progress. We already hold BM_IO_IN_PROGRESS - * for the head block, so we should get on with that I/O as soon as - * possible. We'll come back to this block again, above. - */ - while ((i + 1) < nblocks && - WaitReadBuffersCanStartIO(buffers[i + 1], true)) - { - /* Must be consecutive block numbers. */ - Assert(BufferGetBlockNumber(buffers[i + 1]) == - BufferGetBlockNumber(buffers[i]) + 1); - - io_buffers[io_buffers_len] = buffers[++i]; - io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]); - } - - io_start = pgstat_prepare_io_time(track_io_timing); - smgrreadv(operation->smgr, forknum, io_first_block, io_pages, io_buffers_len); - pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start, - io_buffers_len); - - /* Verify each block we read, and terminate the I/O. */ - for (int j = 0; j < io_buffers_len; ++j) - { - BufferDesc *bufHdr; - Block bufBlock; - - if (persistence == RELPERSISTENCE_TEMP) - { - bufHdr = GetLocalBufferDescriptor(-io_buffers[j] - 1); - bufBlock = LocalBufHdrGetBlock(bufHdr); - } - else + if (aio_ret->result.status == PGAIO_RS_UNKNOWN && + !pgaio_wref_check_done(&operation->io_wref)) { - bufHdr = GetBufferDescriptor(io_buffers[j] - 1); - bufBlock = BufHdrGetBlock(bufHdr); - } - - /* check for garbage data */ - if (!PageIsVerifiedExtended((Page) bufBlock, io_first_block + j, - PIV_LOG_WARNING | PIV_REPORT_STAT)) - { - if ((operation->flags & READ_BUFFERS_ZERO_ON_ERROR) || zero_damaged_pages) - { - ereport(WARNING, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid page in block %u of relation %s; zeroing out page", - io_first_block + j, - relpath(operation->smgr->smgr_rlocator, forknum)))); - memset(bufBlock, 0, BLCKSZ); - } - else - ereport(ERROR, - (errcode(ERRCODE_DATA_CORRUPTED), - errmsg("invalid page in block %u of relation %s", - io_first_block + j, - relpath(operation->smgr->smgr_rlocator, forknum)))); - } + instr_time io_start = pgstat_prepare_io_time(track_io_timing); - /* Terminate I/O and set BM_VALID. */ - if (persistence == RELPERSISTENCE_TEMP) - { - uint32 buf_state = pg_atomic_read_u32(&bufHdr->state); + pgaio_wref_wait(&operation->io_wref); - buf_state |= BM_VALID; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + /* + * The IO operation itself was already counted earlier, in + * AsyncReadBuffers(), this just accounts for the wait time. + */ + pgstat_count_io_op_time(io_object, io_context, IOOP_READ, + io_start, 0, 0); } else { - /* Set BM_VALID, terminate IO, and wake up any waiters */ - TerminateBufferIO(bufHdr, false, BM_VALID, true); + Assert(pgaio_wref_check_done(&operation->io_wref)); } - /* Report I/Os as completing individually. */ - TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j, - operation->smgr->smgr_rlocator.locator.spcOid, - operation->smgr->smgr_rlocator.locator.dbOid, - operation->smgr->smgr_rlocator.locator.relNumber, - operation->smgr->smgr_rlocator.backend, - false); + /* + * We now are sure the IO completed. Check the results. This + * includes reporting on errors if there were any. + */ + ProcessReadBuffersResult(operation); } - VacuumPageMiss += io_buffers_len; - if (VacuumCostActive) - VacuumCostBalance += VacuumCostPageMiss * io_buffers_len; + /* + * Most of the time, the one IO we already started, will read in + * everything. But we need to deal with partial reads and buffers not + * needing IO anymore. + */ + if (operation->nblocks_done == operation->nblocks) + break; + + CHECK_FOR_INTERRUPTS(); + + /* + * This may only complete the IO partially, either because some + * buffers were already valid, or because of a partial read. + * + * NB: In contrast to after the AsyncReadBuffers() call in + * StartReadBuffers(), we do *not* reduce + * ReadBuffersOperation->nblocks here, callers expect the full + * operation to be completed at this point (as more operations may + * have been queued). + */ + AsyncReadBuffers(operation, &ignored_nblocks_progress); } + + CheckReadBuffersOperation(operation, true); + + /* NB: READ_DONE tracepoint was already executed in completion callback */ } /* - * BufferAlloc -- subroutine for PinBufferForBlock. Handles lookup of a shared - * buffer. If no buffer exists already, selects a replacement victim and - * evicts the old page, but does NOT read in new page. + * Initiate IO for the ReadBuffersOperation * - * "strategy" can be a buffer replacement strategy object, or NULL for - * the default strategy. The selected buffer's usage_count is advanced when - * using the default strategy, but otherwise possibly not (see PinBuffer). + * This function only starts a single IO at a time. The size of the IO may be + * limited to below the to-be-read blocks, if one of the buffers has + * concurrently been read in. If the first to-be-read buffer is already valid, + * no IO will be issued. * - * The returned buffer is pinned and is already marked as holding the - * desired page. If it already did have the desired page, *foundPtr is - * set true. Otherwise, *foundPtr is set false. + * To support retries after partial reads, the first operation->nblocks_done + * buffers are skipped. * - * io_context is passed as an output parameter to avoid calling - * IOContextForStrategy() when there is a shared buffers hit and no IO - * statistics need be captured. + * On return *nblocks_progress is updated to reflect the number of buffers + * affected by the call. If the first buffer is valid, *nblocks_progress is + * set to 1 and operation->nblocks_done is incremented. * - * No locks are held either at entry or exit. + * Returns true if IO was initiated, false if no IO was necessary. */ -static pg_attribute_always_inline BufferDesc * -BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, - BlockNumber blockNum, - BufferAccessStrategy strategy, - bool *foundPtr, IOContext io_context) +static bool +AsyncReadBuffers(ReadBuffersOperation *operation, int *nblocks_progress) { - BufferTag newTag; /* identity of requested block */ - uint32 newHash; /* hash value for newTag */ - LWLock *newPartitionLock; /* buffer partition lock for it */ - int existing_buf_id; - Buffer victim_buffer; - BufferDesc *victim_buf_hdr; - uint32 victim_buf_state; - - /* Make sure we will have room to remember the buffer pin */ - ResourceOwnerEnlarge(CurrentResourceOwner); - ReservePrivateRefCountEntry(); - - /* create a tag so we can lookup the buffer */ - InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum); + Buffer *buffers = &operation->buffers[0]; + int flags = operation->flags; + BlockNumber blocknum = operation->blocknum; + ForkNumber forknum = operation->forknum; + char persistence = operation->persistence; + int16 nblocks_done = operation->nblocks_done; + Buffer *io_buffers = &operation->buffers[nblocks_done]; + int io_buffers_len = 0; + PgAioHandle *ioh; + uint32 ioh_flags = 0; + void *io_pages[MAX_IO_COMBINE_LIMIT]; + IOContext io_context; + IOObject io_object; + bool did_start_io; - /* determine its hash code and partition lock ID */ - newHash = BufTableHashCode(&newTag); - newPartitionLock = BufMappingPartitionLock(newHash); + /* + * When this IO is executed synchronously, either because the caller will + * immediately block waiting for the IO or because IOMETHOD_SYNC is used, + * the AIO subsystem needs to know. + */ + if (flags & READ_BUFFERS_SYNCHRONOUSLY) + ioh_flags |= PGAIO_HF_SYNCHRONOUS; - /* see if the block is in the buffer pool already */ - LWLockAcquire(newPartitionLock, LW_SHARED); - existing_buf_id = BufTableLookup(&newTag, newHash); - if (existing_buf_id >= 0) + if (persistence == RELPERSISTENCE_TEMP) { - BufferDesc *buf; - bool valid; + io_context = IOCONTEXT_NORMAL; + io_object = IOOBJECT_TEMP_RELATION; + ioh_flags |= PGAIO_HF_REFERENCES_LOCAL; + } + else + { + io_context = IOContextForStrategy(operation->strategy); + io_object = IOOBJECT_RELATION; + } - /* - * Found it. Now, pin the buffer so no one can steal it from the - * buffer pool, and check to see if the correct data has been loaded - * into the buffer. + /* + * If zero_damaged_pages is enabled, add the READ_BUFFERS_ZERO_ON_ERROR + * flag. The reason for that is that, hopefully, zero_damaged_pages isn't + * set globally, but on a per-session basis. The completion callback, + * which may be run in other processes, e.g. in IO workers, may have a + * different value of the zero_damaged_pages GUC. + * + * XXX: We probably should eventually use a different flag for + * zero_damaged_pages, so we can report different log levels / error codes + * for zero_damaged_pages and ZERO_ON_ERROR. + */ + if (zero_damaged_pages) + flags |= READ_BUFFERS_ZERO_ON_ERROR; + + /* + * For the same reason as with zero_damaged_pages we need to use this + * backend's ignore_checksum_failure value. + */ + if (ignore_checksum_failure) + flags |= READ_BUFFERS_IGNORE_CHECKSUM_FAILURES; + + + /* + * To be allowed to report stats in the local completion callback we need + * to prepare to report stats now. This ensures we can safely report the + * checksum failure even in a critical section. + */ + pgstat_prepare_report_checksum_failure(operation->smgr->smgr_rlocator.locator.dbOid); + + /* + * Get IO handle before ReadBuffersCanStartIO(), as pgaio_io_acquire() + * might block, which we don't want after setting IO_IN_PROGRESS. + * + * If we need to wait for IO before we can get a handle, submit + * already-staged IO first, so that other backends don't need to wait. + * There wouldn't be a deadlock risk, as pgaio_io_acquire() just needs to + * wait for already submitted IO, which doesn't require additional locks, + * but it could still cause undesirable waits. + * + * A secondary benefit is that this would allow us to measure the time in + * pgaio_io_acquire() without causing undue timer overhead in the common, + * non-blocking, case. However, currently the pgstats infrastructure + * doesn't really allow that, as it a) asserts that an operation can't + * have time without operations b) doesn't have an API to report + * "accumulated" time. + */ + ioh = pgaio_io_acquire_nb(CurrentResourceOwner, &operation->io_return); + if (unlikely(!ioh)) + { + pgaio_submit_staged(); + + ioh = pgaio_io_acquire(CurrentResourceOwner, &operation->io_return); + } + + /* + * Check if we can start IO on the first to-be-read buffer. + * + * If an I/O is already in progress in another backend, we want to wait + * for the outcome: either done, or something went wrong and we will + * retry. + */ + if (!ReadBuffersCanStartIO(buffers[nblocks_done], false)) + { + /* + * Someone else has already completed this block, we're done. + * + * When IO is necessary, ->nblocks_done is updated in + * ProcessReadBuffersResult(), but that is not called if no IO is + * necessary. Thus update here. + */ + operation->nblocks_done += 1; + *nblocks_progress = 1; + + pgaio_io_release(ioh); + pgaio_wref_clear(&operation->io_wref); + did_start_io = false; + + /* + * Report and track this as a 'hit' for this backend, even though it + * must have started out as a miss in PinBufferForBlock(). The other + * backend will track this as a 'read'. + */ + TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + operation->nblocks_done, + operation->smgr->smgr_rlocator.locator.spcOid, + operation->smgr->smgr_rlocator.locator.dbOid, + operation->smgr->smgr_rlocator.locator.relNumber, + operation->smgr->smgr_rlocator.backend, + true); + + if (persistence == RELPERSISTENCE_TEMP) + pgBufferUsage.local_blks_hit += 1; + else + pgBufferUsage.shared_blks_hit += 1; + + if (operation->rel) + pgstat_count_buffer_hit(operation->rel); + + pgstat_count_io_op(io_object, io_context, IOOP_HIT, 1, 0); + + if (VacuumCostActive) + VacuumCostBalance += VacuumCostPageHit; + } + else + { + instr_time io_start; + + /* We found a buffer that we need to read in. */ + Assert(io_buffers[0] == buffers[nblocks_done]); + io_pages[0] = BufferGetBlock(buffers[nblocks_done]); + io_buffers_len = 1; + + /* + * How many neighboring-on-disk blocks can we scatter-read into other + * buffers at the same time? In this case we don't wait if we see an + * I/O already in progress. We already set BM_IO_IN_PROGRESS for the + * head block, so we should get on with that I/O as soon as possible. + */ + for (int i = nblocks_done + 1; i < operation->nblocks; i++) + { + if (!ReadBuffersCanStartIO(buffers[i], true)) + break; + /* Must be consecutive block numbers. */ + Assert(BufferGetBlockNumber(buffers[i - 1]) == + BufferGetBlockNumber(buffers[i]) - 1); + Assert(io_buffers[io_buffers_len] == buffers[i]); + + io_pages[io_buffers_len++] = BufferGetBlock(buffers[i]); + } + + /* get a reference to wait for in WaitReadBuffers() */ + pgaio_io_get_wref(ioh, &operation->io_wref); + + /* provide the list of buffers to the completion callbacks */ + pgaio_io_set_handle_data_32(ioh, (uint32 *) io_buffers, io_buffers_len); + + pgaio_io_register_callbacks(ioh, + persistence == RELPERSISTENCE_TEMP ? + PGAIO_HCB_LOCAL_BUFFER_READV : + PGAIO_HCB_SHARED_BUFFER_READV, + flags); + + pgaio_io_set_flag(ioh, ioh_flags); + + /* --- + * Even though we're trying to issue IO asynchronously, track the time + * in smgrstartreadv(): + * - if io_method == IOMETHOD_SYNC, we will always perform the IO + * immediately + * - the io method might not support the IO (e.g. worker IO for a temp + * table) + * --- + */ + io_start = pgstat_prepare_io_time(track_io_timing); + smgrstartreadv(ioh, operation->smgr, forknum, + blocknum + nblocks_done, + io_pages, io_buffers_len); + pgstat_count_io_op_time(io_object, io_context, IOOP_READ, + io_start, 1, io_buffers_len * BLCKSZ); + + if (persistence == RELPERSISTENCE_TEMP) + pgBufferUsage.local_blks_read += io_buffers_len; + else + pgBufferUsage.shared_blks_read += io_buffers_len; + + /* + * Track vacuum cost when issuing IO, not after waiting for it. + * Otherwise we could end up issuing a lot of IO in a short timespan, + * despite a low cost limit. + */ + if (VacuumCostActive) + VacuumCostBalance += VacuumCostPageMiss * io_buffers_len; + + *nblocks_progress = io_buffers_len; + did_start_io = true; + } + + return did_start_io; +} + +/* + * BufferAlloc -- subroutine for PinBufferForBlock. Handles lookup of a shared + * buffer. If no buffer exists already, selects a replacement victim and + * evicts the old page, but does NOT read in new page. + * + * "strategy" can be a buffer replacement strategy object, or NULL for + * the default strategy. The selected buffer's usage_count is advanced when + * using the default strategy, but otherwise possibly not (see PinBuffer). + * + * The returned buffer is pinned and is already marked as holding the + * desired page. If it already did have the desired page, *foundPtr is + * set true. Otherwise, *foundPtr is set false. + * + * io_context is passed as an output parameter to avoid calling + * IOContextForStrategy() when there is a shared buffers hit and no IO + * statistics need be captured. + * + * No locks are held either at entry or exit. + */ +static pg_attribute_always_inline BufferDesc * +BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, + BlockNumber blockNum, + BufferAccessStrategy strategy, + bool *foundPtr, IOContext io_context) +{ + BufferTag newTag; /* identity of requested block */ + uint32 newHash; /* hash value for newTag */ + LWLock *newPartitionLock; /* buffer partition lock for it */ + int existing_buf_id; + Buffer victim_buffer; + BufferDesc *victim_buf_hdr; + uint32 victim_buf_state; + + /* Make sure we will have room to remember the buffer pin */ + ResourceOwnerEnlarge(CurrentResourceOwner); + ReservePrivateRefCountEntry(); + + /* create a tag so we can lookup the buffer */ + InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum); + + /* determine its hash code and partition lock ID */ + newHash = BufTableHashCode(&newTag); + newPartitionLock = BufMappingPartitionLock(newHash); + + /* see if the block is in the buffer pool already */ + LWLockAcquire(newPartitionLock, LW_SHARED); + existing_buf_id = BufTableLookup(&newTag, newHash); + if (existing_buf_id >= 0) + { + BufferDesc *buf; + bool valid; + + /* + * Found it. Now, pin the buffer so no one can steal it from the + * buffer pool, and check to see if the correct data has been loaded + * into the buffer. */ buf = GetBufferDescriptor(existing_buf_id); @@ -1835,13 +2223,14 @@ InvalidateBuffer(BufferDesc *buf) } /* - * We assume the only reason for it to be pinned is that someone else is - * flushing the page out. Wait for them to finish. (This could be an - * infinite loop if the refcount is messed up... it would be nice to time - * out after awhile, but there seems no way to be sure how many loops may - * be needed. Note that if the other guy has pinned the buffer but not - * yet done StartBufferIO, WaitIO will fall through and we'll effectively - * be busy-looping here.) + * We assume the reason for it to be pinned is that either we were + * asynchronously reading the page in before erroring out or someone else + * is flushing the page out. Wait for the IO to finish. (This could be + * an infinite loop if the refcount is messed up... it would be nice to + * time out after awhile, but there seems no way to be sure how many loops + * may be needed. Note that if the other guy has pinned the buffer but + * not yet done StartBufferIO, WaitIO will fall through and we'll + * effectively be busy-looping here.) */ if (BUF_STATE_GET_REFCOUNT(buf_state) != 0) { @@ -2084,7 +2473,7 @@ GetVictimBuffer(BufferAccessStrategy strategy, IOContext io_context) * pinners or erroring out. */ pgstat_count_io_op(IOOBJECT_RELATION, io_context, - from_ring ? IOOP_REUSE : IOOP_EVICT); + from_ring ? IOOP_REUSE : IOOP_EVICT, 1, 0); } /* @@ -2111,43 +2500,62 @@ GetVictimBuffer(BufferAccessStrategy strategy, IOContext io_context) return buf; } +/* + * Return the maximum number of buffers that a backend should try to pin once, + * to avoid exceeding its fair share. This is the highest value that + * GetAdditionalPinLimit() could ever return. Note that it may be zero on a + * system with a very small buffer pool relative to max_connections. + */ +uint32 +GetPinLimit(void) +{ + return MaxProportionalPins; +} + +/* + * Return the maximum number of additional buffers that this backend should + * pin if it wants to stay under the per-backend limit, considering the number + * of buffers it has already pinned. Unlike LimitAdditionalPins(), the limit + * return by this function can be zero. + */ +uint32 +GetAdditionalPinLimit(void) +{ + uint32 estimated_pins_held; + + /* + * We get the number of "overflowed" pins for free, but don't know the + * number of pins in PrivateRefCountArray. The cost of calculating that + * exactly doesn't seem worth it, so just assume the max. + */ + estimated_pins_held = PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES; + + /* Is this backend already holding more than its fair share? */ + if (estimated_pins_held > MaxProportionalPins) + return 0; + + return MaxProportionalPins - estimated_pins_held; +} + /* * Limit the number of pins a batch operation may additionally acquire, to * avoid running out of pinnable buffers. * - * One additional pin is always allowed, as otherwise the operation likely - * cannot be performed at all. - * - * The number of allowed pins for a backend is computed based on - * shared_buffers and the maximum number of connections possible. That's very - * pessimistic, but outside of toy-sized shared_buffers it should allow - * sufficient pins. + * One additional pin is always allowed, on the assumption that the operation + * requires at least one to make progress. */ void LimitAdditionalPins(uint32 *additional_pins) { - uint32 max_backends; - int max_proportional_pins; + uint32 limit; if (*additional_pins <= 1) return; - max_backends = MaxBackends + NUM_AUXILIARY_PROCS; - max_proportional_pins = NBuffers / max_backends; - - /* - * Subtract the approximate number of buffers already pinned by this - * backend. We get the number of "overflowed" pins for free, but don't - * know the number of pins in PrivateRefCountArray. The cost of - * calculating that exactly doesn't seem worth it, so just assume the max. - */ - max_proportional_pins -= PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES; - - if (max_proportional_pins <= 0) - max_proportional_pins = 1; - - if (*additional_pins > max_proportional_pins) - *additional_pins = max_proportional_pins; + limit = GetAdditionalPinLimit(); + limit = Max(limit, 1); + if (limit < *additional_pins) + *additional_pins = limit; } /* @@ -2232,7 +2640,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, buf_block = BufHdrGetBlock(GetBufferDescriptor(buffers[i] - 1)); /* new buffers are zero-filled */ - MemSet((char *) buf_block, 0, BLCKSZ); + MemSet(buf_block, 0, BLCKSZ); } /* @@ -2298,7 +2706,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend relation %s beyond %u blocks", - relpath(bmr.smgr->smgr_rlocator, fork), + relpath(bmr.smgr->smgr_rlocator, fork).str, MaxBlockNumber))); /* @@ -2369,7 +2777,8 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, if (valid && !PageIsNew((Page) buf_block)) ereport(ERROR, (errmsg("unexpected data beyond EOF in block %u of relation %s", - existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)), + existing_hdr->tag.blockNum, + relpath(bmr.smgr->smgr_rlocator, fork).str), errhint("This has been seen to occur with buggy kernels; consider updating your system."))); /* @@ -2440,7 +2849,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, UnlockRelationForExtension(bmr.rel, ExclusiveLock); pgstat_count_io_op_time(IOOBJECT_RELATION, io_context, IOOP_EXTEND, - io_start, extend_by); + io_start, 1, extend_by * BLCKSZ); /* Set BM_VALID, terminate IO, and wake up any waiters */ for (uint32 i = 0; i < extend_by; i++) @@ -2461,7 +2870,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr, if (lock) LWLockAcquire(BufferDescriptorGetContentLock(buf_hdr), LW_EXCLUSIVE); - TerminateBufferIO(buf_hdr, false, BM_VALID, true); + TerminateBufferIO(buf_hdr, false, BM_VALID, true, false); } pgBufferUsage.shared_blks_written += extend_by; @@ -2483,20 +2892,19 @@ BufferIsExclusiveLocked(Buffer buffer) { BufferDesc *bufHdr; + Assert(BufferIsPinned(buffer)); + if (BufferIsLocal(buffer)) { - int bufid = -buffer - 1; - - bufHdr = GetLocalBufferDescriptor(bufid); + /* Content locks are not maintained for local buffers. */ + return true; } else { bufHdr = GetBufferDescriptor(buffer - 1); + return LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr), + LW_EXCLUSIVE); } - - Assert(BufferIsPinned(buffer)); - return LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr), - LW_EXCLUSIVE); } /* @@ -2512,21 +2920,22 @@ BufferIsDirty(Buffer buffer) { BufferDesc *bufHdr; + Assert(BufferIsPinned(buffer)); + if (BufferIsLocal(buffer)) { int bufid = -buffer - 1; bufHdr = GetLocalBufferDescriptor(bufid); + /* Content locks are not maintained for local buffers. */ } else { bufHdr = GetBufferDescriptor(buffer - 1); + Assert(LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr), + LW_EXCLUSIVE)); } - Assert(BufferIsPinned(buffer)); - Assert(LWLockHeldByMeInMode(BufferDescriptorGetContentLock(bufHdr), - LW_EXCLUSIVE)); - return pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY; } @@ -2582,7 +2991,6 @@ MarkBufferDirty(Buffer buffer) */ if (!(old_buf_state & BM_DIRTY)) { - VacuumPageDirty++; pgBufferUsage.shared_blks_dirtied++; if (VacuumCostActive) VacuumCostBalance += VacuumCostPageDirty; @@ -2808,6 +3216,44 @@ PinBuffer_Locked(BufferDesc *buf) ResourceOwnerRememberBuffer(CurrentResourceOwner, b); } +/* + * Support for waking up another backend that is waiting for the cleanup lock + * to be released using BM_PIN_COUNT_WAITER. + * + * See LockBufferForCleanup(). + * + * Expected to be called just after releasing a buffer pin (in a BufferDesc, + * not just reducing the backend-local pincount for the buffer). + */ +static void +WakePinCountWaiter(BufferDesc *buf) +{ + /* + * Acquire the buffer header lock, re-check that there's a waiter. Another + * backend could have unpinned this buffer, and already woken up the + * waiter. + * + * There's no danger of the buffer being replaced after we unpinned it + * above, as it's pinned by the waiter. The waiter removes + * BM_PIN_COUNT_WAITER if it stops waiting for a reason other than this + * backend waking it up. + */ + uint32 buf_state = LockBufHdr(buf); + + if ((buf_state & BM_PIN_COUNT_WAITER) && + BUF_STATE_GET_REFCOUNT(buf_state) == 1) + { + /* we just released the last pin other than the waiter's */ + int wait_backend_pgprocno = buf->wait_backend_pgprocno; + + buf_state &= ~BM_PIN_COUNT_WAITER; + UnlockBufHdr(buf, buf_state); + ProcSendSignal(wait_backend_pgprocno); + } + else + UnlockBufHdr(buf, buf_state); +} + /* * UnpinBuffer -- make buffer available for replacement. * @@ -2876,29 +3322,8 @@ UnpinBufferNoOwner(BufferDesc *buf) /* Support LockBufferForCleanup() */ if (buf_state & BM_PIN_COUNT_WAITER) - { - /* - * Acquire the buffer header lock, re-check that there's a waiter. - * Another backend could have unpinned this buffer, and already - * woken up the waiter. There's no danger of the buffer being - * replaced after we unpinned it above, as it's pinned by the - * waiter. - */ - buf_state = LockBufHdr(buf); + WakePinCountWaiter(buf); - if ((buf_state & BM_PIN_COUNT_WAITER) && - BUF_STATE_GET_REFCOUNT(buf_state) == 1) - { - /* we just released the last pin other than the waiter's */ - int wait_backend_pgprocno = buf->wait_backend_pgprocno; - - buf_state &= ~BM_PIN_COUNT_WAITER; - UnlockBufHdr(buf, buf_state); - ProcSendSignal(wait_backend_pgprocno); - } - else - UnlockBufHdr(buf, buf_state); - } ForgetPrivateRefCountEntry(ref); } } @@ -2908,7 +3333,7 @@ UnpinBufferNoOwner(BufferDesc *buf) #define ST_COMPARE(a, b) ckpt_buforder_comparator(a, b) #define ST_SCOPE static #define ST_DEFINE -#include +#include "lib/sort_template.h" /* * BufferSync -- Write out all dirty buffers in the pool. @@ -3585,10 +4010,19 @@ AtEOXact_Buffers(bool isCommit) * buffer pool. */ void -InitBufferPoolAccess(void) +InitBufferManagerAccess(void) { HASHCTL hash_ctl; + /* + * An advisory limit on the number of pins each backend should hold, based + * on shared_buffers and the maximum number of connections possible. + * That's very pessimistic, but outside toy-sized shared_buffers it should + * allow plenty of pins. LimitAdditionalPins() and + * GetAdditionalPinLimit() can be used to check the remaining balance. + */ + MaxProportionalPins = NBuffers / (MaxBackends + NUM_AUXILIARY_PROCS); + memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray)); hash_ctl.keysize = sizeof(int32); @@ -3670,6 +4104,67 @@ CheckForBufferLeaks(void) #endif } +#ifdef USE_ASSERT_CHECKING +/* + * Check for exclusive-locked catalog buffers. This is the core of + * AssertCouldGetRelation(). + * + * A backend would self-deadlock on LWLocks if the catalog scan read the + * exclusive-locked buffer. The main threat is exclusive-locked buffers of + * catalogs used in relcache, because a catcache search on any catalog may + * build that catalog's relcache entry. We don't have an inventory of + * catalogs relcache uses, so just check buffers of most catalogs. + * + * It's better to minimize waits while holding an exclusive buffer lock, so it + * would be nice to broaden this check not to be catalog-specific. However, + * bttextcmp() accesses pg_collation, and non-core opclasses might similarly + * read tables. That is deadlock-free as long as there's no loop in the + * dependency graph: modifying table A may cause an opclass to read table B, + * but it must not cause a read of table A. + */ +void +AssertBufferLocksPermitCatalogRead(void) +{ + ForEachLWLockHeldByMe(AssertNotCatalogBufferLock, NULL); +} + +static void +AssertNotCatalogBufferLock(LWLock *lock, LWLockMode mode, + void *unused_context) +{ + BufferDesc *bufHdr; + BufferTag tag; + Oid relid; + + if (mode != LW_EXCLUSIVE) + return; + + if (!((BufferDescPadded *) lock > BufferDescriptors && + (BufferDescPadded *) lock < BufferDescriptors + NBuffers)) + return; /* not a buffer lock */ + + bufHdr = (BufferDesc *) + ((char *) lock - offsetof(BufferDesc, content_lock)); + tag = bufHdr->tag; + + /* + * This relNumber==relid assumption holds until a catalog experiences + * VACUUM FULL or similar. After a command like that, relNumber will be + * in the normal (non-catalog) range, and we lose the ability to detect + * hazardous access to that catalog. Calling RelidByRelfilenumber() would + * close that gap, but RelidByRelfilenumber() might then deadlock with a + * held lock. + */ + relid = tag.relNumber; + + if (IsCatalogTextUniqueIndexOid(relid)) /* see comments at the callee */ + return; + + Assert(!IsCatalogRelationOid(relid)); +} +#endif + + /* * Helper routine to issue warnings when a buffer is unexpectedly pinned */ @@ -3678,7 +4173,6 @@ DebugPrintBufferRefcount(Buffer buffer) { BufferDesc *buf; int32 loccount; - char *path; char *result; ProcNumber backend; uint32 buf_state; @@ -3698,15 +4192,14 @@ DebugPrintBufferRefcount(Buffer buffer) } /* theoretically we should lock the bufhdr here */ - path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend, - BufTagGetForkNum(&buf->tag)); buf_state = pg_atomic_read_u32(&buf->state); result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)", - buffer, path, + buffer, + relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend, + BufTagGetForkNum(&buf->tag)).str, buf->tag.blockNum, buf_state & BUF_FLAG_MASK, BUF_STATE_GET_REFCOUNT(buf_state), loccount); - pfree(path); return result; } @@ -3813,7 +4306,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, /* Setup error traceback support for ereport() */ errcallback.callback = shared_buffer_write_error_callback; - errcallback.arg = (void *) buf; + errcallback.arg = buf; errcallback.previous = error_context_stack; error_context_stack = &errcallback; @@ -3860,9 +4353,10 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, XLogFlush(recptr); /* - * Now it's safe to write buffer to disk. Note that no one else should - * have been able to write it while we were busy with log flushing because - * only one process at a time can set the BM_IO_IN_PROGRESS bit. + * Now it's safe to write the buffer to disk. Note that no one else should + * have been able to write it, while we were busy with log flushing, + * because we got the exclusive right to perform I/O by setting the + * BM_IO_IN_PROGRESS bit. */ bufBlock = BufHdrGetBlock(buf); @@ -3903,7 +4397,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, * of a dirty shared buffer (IOCONTEXT_NORMAL IOOP_WRITE). */ pgstat_count_io_op_time(IOOBJECT_RELATION, io_context, - IOOP_WRITE, io_start, 1); + IOOP_WRITE, io_start, 1, BLCKSZ); pgBufferUsage.shared_blks_written++; @@ -3911,7 +4405,7 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object, * Mark the buffer as clean (unless BM_JUST_DIRTIED has become set) and * end the BM_IO_IN_PROGRESS state. */ - TerminateBufferIO(buf, true, 0, true); + TerminateBufferIO(buf, true, 0, true, false); TRACE_POSTGRESQL_BUFFER_FLUSH_DONE(BufTagGetForkNum(&buf->tag), buf->tag.blockNum, @@ -3996,8 +4490,8 @@ BufferIsPermanent(Buffer buffer) XLogRecPtr BufferGetLSNAtomic(Buffer buffer) { - BufferDesc *bufHdr = GetBufferDescriptor(buffer - 1); char *page = BufferGetPage(buffer); + BufferDesc *bufHdr; XLogRecPtr lsn; uint32 buf_state; @@ -4011,6 +4505,7 @@ BufferGetLSNAtomic(Buffer buffer) Assert(BufferIsValid(buffer)); Assert(BufferIsPinned(buffer)); + bufHdr = GetBufferDescriptor(buffer - 1); buf_state = LockBufHdr(bufHdr); lsn = PageGetLSN(page); UnlockBufHdr(bufHdr, buf_state); @@ -4304,7 +4799,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators) RelFileLocator locator; locator = BufTagGetRelFileLocator(&bufHdr->tag); - rlocator = bsearch((const void *) &(locator), + rlocator = bsearch(&locator, locators, n, sizeof(RelFileLocator), rlocator_comparator); } @@ -4424,64 +4919,6 @@ DropDatabaseBuffers(Oid dbid) } } -/* ----------------------------------------------------------------- - * PrintBufferDescs - * - * this function prints all the buffer descriptors, for debugging - * use only. - * ----------------------------------------------------------------- - */ -#ifdef NOT_USED -void -PrintBufferDescs(void) -{ - int i; - - for (i = 0; i < NBuffers; ++i) - { - BufferDesc *buf = GetBufferDescriptor(i); - Buffer b = BufferDescriptorGetBuffer(buf); - - /* theoretically we should lock the bufhdr here */ - elog(LOG, - "[%02d] (freeNext=%d, rel=%s, " - "blockNum=%u, flags=0x%x, refcount=%u %d)", - i, buf->freeNext, - relpathbackend(BufTagGetRelFileLocator(&buf->tag), - INVALID_PROC_NUMBER, BufTagGetForkNum(&buf->tag)), - buf->tag.blockNum, buf->flags, - buf->refcount, GetPrivateRefCount(b)); - } -} -#endif - -#ifdef NOT_USED -void -PrintPinnedBufs(void) -{ - int i; - - for (i = 0; i < NBuffers; ++i) - { - BufferDesc *buf = GetBufferDescriptor(i); - Buffer b = BufferDescriptorGetBuffer(buf); - - if (GetPrivateRefCount(b) > 0) - { - /* theoretically we should lock the bufhdr here */ - elog(LOG, - "[%02d] (freeNext=%d, rel=%s, " - "blockNum=%u, flags=0x%x, refcount=%u %d)", - i, buf->freeNext, - relpathperm(BufTagGetRelFileLocator(&buf->tag), - BufTagGetForkNum(&buf->tag)), - buf->tag.blockNum, buf->flags, - buf->refcount, GetPrivateRefCount(b)); - } - } -} -#endif - /* --------------------------------------------------------------------- * FlushRelationBuffers * @@ -4512,7 +4949,6 @@ FlushRelationBuffers(Relation rel) for (i = 0; i < NLocBuffer; i++) { uint32 buf_state; - instr_time io_start; bufHdr = GetLocalBufferDescriptor(i); if (BufTagMatchesRelFileLocator(&bufHdr->tag, &rel->rd_locator) && @@ -4520,34 +4956,27 @@ FlushRelationBuffers(Relation rel) (BM_VALID | BM_DIRTY)) == (BM_VALID | BM_DIRTY)) { ErrorContextCallback errcallback; - Page localpage; - - localpage = (char *) LocalBufHdrGetBlock(bufHdr); /* Setup error traceback support for ereport() */ errcallback.callback = local_buffer_write_error_callback; - errcallback.arg = (void *) bufHdr; + errcallback.arg = bufHdr; errcallback.previous = error_context_stack; error_context_stack = &errcallback; - PageSetChecksumInplace(localpage, bufHdr->tag.blockNum); - - io_start = pgstat_prepare_io_time(track_io_timing); + /* Make sure we can handle the pin */ + ReservePrivateRefCountEntry(); + ResourceOwnerEnlarge(CurrentResourceOwner); - smgrwrite(srel, - BufTagGetForkNum(&bufHdr->tag), - bufHdr->tag.blockNum, - localpage, - false); + /* + * Pin/unpin mostly to make valgrind work, but it also seems + * like the right thing to do. + */ + PinLocalBuffer(bufHdr, false); - pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, - IOCONTEXT_NORMAL, IOOP_WRITE, - io_start, 1); - buf_state &= ~(BM_DIRTY | BM_JUST_DIRTIED); - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + FlushLocalBuffer(bufHdr, srel); - pgBufferUsage.local_blks_written++; + UnpinLocalBuffer(BufferDescriptorGetBuffer(bufHdr)); /* Pop the error context stack */ error_context_stack = errcallback.previous; @@ -4658,7 +5087,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels) RelFileLocator rlocator; rlocator = BufTagGetRelFileLocator(&bufHdr->tag); - srelent = bsearch((const void *) &(rlocator), + srelent = bsearch(&rlocator, srels, nrels, sizeof(SMgrSortArray), rlocator_comparator); } @@ -4713,7 +5142,7 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator, PGIOAlignedBlock buf; BufferAccessStrategy bstrategy_src; BufferAccessStrategy bstrategy_dst; - struct copy_storage_using_buffer_read_stream_private p; + BlockRangeReadStreamPrivate p; ReadStream *src_stream; SMgrRelation src_smgr; @@ -4744,16 +5173,22 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator, bstrategy_src = GetAccessStrategy(BAS_BULKREAD); bstrategy_dst = GetAccessStrategy(BAS_BULKWRITE); - /* Initalize streaming read */ - p.blocknum = 0; - p.nblocks = nblocks; + /* Initialize streaming read */ + p.current_blocknum = 0; + p.last_exclusive = nblocks; src_smgr = smgropen(srclocator, INVALID_PROC_NUMBER); - src_stream = read_stream_begin_smgr_relation(READ_STREAM_FULL, + + /* + * It is safe to use batchmode as block_range_read_stream_cb takes no + * locks. + */ + src_stream = read_stream_begin_smgr_relation(READ_STREAM_FULL | + READ_STREAM_USE_BATCHING, bstrategy_src, src_smgr, permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED, forkNum, - copy_storage_using_buffer_read_stream_next_block, + block_range_read_stream_cb, &p, 0); @@ -5122,7 +5557,6 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std) if (dirtied) { - VacuumPageDirty++; pgBufferUsage.shared_blks_dirtied++; if (VacuumCostActive) VacuumCostBalance += VacuumCostPageDirty; @@ -5260,7 +5694,14 @@ LockBufferForCleanup(Buffer buffer) CheckBufferIsPinnedOnce(buffer); - /* Nobody else to wait for */ + /* + * We do not yet need to be worried about in-progress AIOs holding a pin, + * as we, so far, only support doing reads via AIO and this function can + * only be called once the buffer is valid (i.e. no read can be in + * flight). + */ + + /* Nobody else to wait for */ if (BufferIsLocal(buffer)) return; @@ -5417,6 +5858,8 @@ ConditionalLockBufferForCleanup(Buffer buffer) Assert(BufferIsValid(buffer)); + /* see AIO related comment in LockBufferForCleanup() */ + if (BufferIsLocal(buffer)) { refcount = LocalRefCount[-buffer - 1]; @@ -5472,6 +5915,8 @@ IsBufferCleanupOK(Buffer buffer) Assert(BufferIsValid(buffer)); + /* see AIO related comment in LockBufferForCleanup() */ + if (BufferIsLocal(buffer)) { /* There should be exactly one pin */ @@ -5509,9 +5954,6 @@ IsBufferCleanupOK(Buffer buffer) /* * Functions for buffer I/O handling * - * Note: We assume that nested buffer I/O never occurs. - * i.e at most one BM_IO_IN_PROGRESS bit is set per proc. - * * Also note that these are used only for shared buffers, not local ones. */ @@ -5527,6 +5969,7 @@ WaitIO(BufferDesc *buf) for (;;) { uint32 buf_state; + PgAioWaitRef iow; /* * It may not be necessary to acquire the spinlock to check the flag @@ -5534,10 +5977,40 @@ WaitIO(BufferDesc *buf) * play it safe. */ buf_state = LockBufHdr(buf); + + /* + * Copy the wait reference while holding the spinlock. This protects + * against a concurrent TerminateBufferIO() in another backend from + * clearing the wref while it's being read. + */ + iow = buf->io_wref; UnlockBufHdr(buf, buf_state); + /* no IO in progress, we don't need to wait */ if (!(buf_state & BM_IO_IN_PROGRESS)) break; + + /* + * The buffer has asynchronous IO in progress, wait for it to + * complete. + */ + if (pgaio_wref_valid(&iow)) + { + pgaio_wref_wait(&iow); + + /* + * The AIO subsystem internally uses condition variables and thus + * might remove this backend from the BufferDesc's CV. While that + * wouldn't cause a correctness issue (the first CV sleep just + * immediately returns if not already registered), it seems worth + * avoiding unnecessary loop iterations, given that we take care + * to do so at the start of the function. + */ + ConditionVariablePrepareToSleep(cv); + continue; + } + + /* wait on BufferDesc->cv, e.g. for concurrent synchronous IO */ ConditionVariableSleep(cv, WAIT_EVENT_BUFFER_IO); } ConditionVariableCancelSleep(); @@ -5546,13 +6019,12 @@ WaitIO(BufferDesc *buf) /* * StartBufferIO: begin I/O on this buffer * (Assumptions) - * My process is executing no IO + * My process is executing no IO on this buffer * The buffer is Pinned * - * In some scenarios there are race conditions in which multiple backends - * could attempt the same I/O operation concurrently. If someone else - * has already started I/O on this buffer then we will block on the - * I/O condition variable until he's done. + * In some scenarios multiple backends could attempt the same I/O operation + * concurrently. If someone else has already started I/O on this buffer then + * we will wait for completion of the IO using WaitIO(). * * Input operations are only attempted on buffers that are not BM_VALID, * and output operations only on buffers that are BM_VALID and BM_DIRTY, @@ -5567,7 +6039,7 @@ WaitIO(BufferDesc *buf) * find out if they can perform the I/O as part of a larger operation, without * waiting for the answer or distinguishing the reasons why not. */ -static bool +bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait) { uint32 buf_state; @@ -5588,9 +6060,9 @@ StartBufferIO(BufferDesc *buf, bool forInput, bool nowait) /* Once we get here, there is definitely no I/O active on this buffer */ + /* Check if someone else already did the I/O */ if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY)) { - /* someone else already did the I/O */ UnlockBufHdr(buf, buf_state); return false; } @@ -5624,20 +6096,31 @@ StartBufferIO(BufferDesc *buf, bool forInput, bool nowait) * resource owner. (forget_owner=false is used when the resource owner itself * is being released) */ -static void +void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, - bool forget_owner) + bool forget_owner, bool release_aio) { uint32 buf_state; buf_state = LockBufHdr(buf); Assert(buf_state & BM_IO_IN_PROGRESS); + buf_state &= ~BM_IO_IN_PROGRESS; + + /* Clear earlier errors, if this IO failed, it'll be marked again */ + buf_state &= ~BM_IO_ERROR; - buf_state &= ~(BM_IO_IN_PROGRESS | BM_IO_ERROR); if (clear_dirty && !(buf_state & BM_JUST_DIRTIED)) buf_state &= ~(BM_DIRTY | BM_CHECKPOINT_NEEDED); + if (release_aio) + { + /* release ownership by the AIO subsystem */ + Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0); + buf_state -= BUF_REFCOUNT_ONE; + pgaio_wref_clear(&buf->io_wref); + } + buf_state |= set_flag_bits; UnlockBufHdr(buf, buf_state); @@ -5646,6 +6129,17 @@ TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, BufferDescriptorGetBuffer(buf)); ConditionVariableBroadcast(BufferDescriptorGetIOCV(buf)); + + /* + * Support LockBufferForCleanup() + * + * We may have just released the last pin other than the waiter's. In most + * cases, this backend holds another pin on the buffer. But, if, for + * example, this backend is completing an IO issued by another backend, it + * may be time to wake the waiter. + */ + if (release_aio && (buf_state & BM_PIN_COUNT_WAITER)) + WakePinCountWaiter(buf); } /* @@ -5684,20 +6178,17 @@ AbortBufferIO(Buffer buffer) if (buf_state & BM_IO_ERROR) { /* Buffer is pinned, so we can read tag without spinlock */ - char *path; - - path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag), - BufTagGetForkNum(&buf_hdr->tag)); ereport(WARNING, (errcode(ERRCODE_IO_ERROR), errmsg("could not write block %u of %s", - buf_hdr->tag.blockNum, path), + buf_hdr->tag.blockNum, + relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag), + BufTagGetForkNum(&buf_hdr->tag)).str), errdetail("Multiple failures --- write error might be permanent."))); - pfree(path); } } - TerminateBufferIO(buf_hdr, false, BM_IO_ERROR, false); + TerminateBufferIO(buf_hdr, false, BM_IO_ERROR, false, false); } /* @@ -5710,14 +6201,10 @@ shared_buffer_write_error_callback(void *arg) /* Buffer is pinned, so we can read the tag without locking the spinlock */ if (bufHdr != NULL) - { - char *path = relpathperm(BufTagGetRelFileLocator(&bufHdr->tag), - BufTagGetForkNum(&bufHdr->tag)); - errcontext("writing block %u of relation %s", - bufHdr->tag.blockNum, path); - pfree(path); - } + bufHdr->tag.blockNum, + relpathperm(BufTagGetRelFileLocator(&bufHdr->tag), + BufTagGetForkNum(&bufHdr->tag)).str); } /* @@ -5729,15 +6216,11 @@ local_buffer_write_error_callback(void *arg) BufferDesc *bufHdr = (BufferDesc *) arg; if (bufHdr != NULL) - { - char *path = relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag), - MyProcNumber, - BufTagGetForkNum(&bufHdr->tag)); - errcontext("writing block %u of relation %s", - bufHdr->tag.blockNum, path); - pfree(path); - } + bufHdr->tag.blockNum, + relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag), + MyProcNumber, + BufTagGetForkNum(&bufHdr->tag)).str); } /* @@ -5930,7 +6413,12 @@ ScheduleBufferTagForWriteback(WritebackContext *wb_context, IOContext io_context { PendingWriteback *pending; - if (io_direct_flags & IO_DIRECT_DATA) + /* + * As pg_flush_data() doesn't do anything with fsync disabled, there's no + * point in tracking in that case. + */ + if (io_direct_flags & IO_DIRECT_DATA || + !enableFsync) return; /* @@ -5960,7 +6448,7 @@ ScheduleBufferTagForWriteback(WritebackContext *wb_context, IOContext io_context #define ST_COMPARE(a, b) buffertag_comparator(&a->tag, &b->tag) #define ST_SCOPE static #define ST_DEFINE -#include +#include "lib/sort_template.h" /* * Issue all pending writeback requests, previously scheduled with @@ -6045,7 +6533,7 @@ IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_context) * blocks of permanent relations. */ pgstat_count_io_op_time(IOOBJECT_RELATION, io_context, - IOOP_WRITEBACK, io_start, wb_context->nr_pending); + IOOP_WRITEBACK, io_start, wb_context->nr_pending, 0); wb_context->nr_pending = 0; } @@ -6089,6 +6577,53 @@ ResOwnerPrintBufferPin(Datum res) return DebugPrintBufferRefcount(DatumGetInt32(res)); } +/* + * Helper function to evict unpinned buffer whose buffer header lock is + * already acquired. + */ +static bool +EvictUnpinnedBufferInternal(BufferDesc *desc, bool *buffer_flushed) +{ + uint32 buf_state; + bool result; + + *buffer_flushed = false; + + buf_state = pg_atomic_read_u32(&(desc->state)); + Assert(buf_state & BM_LOCKED); + + if ((buf_state & BM_VALID) == 0) + { + UnlockBufHdr(desc, buf_state); + return false; + } + + /* Check that it's not pinned already. */ + if (BUF_STATE_GET_REFCOUNT(buf_state) > 0) + { + UnlockBufHdr(desc, buf_state); + return false; + } + + PinBuffer_Locked(desc); /* releases spinlock */ + + /* If it was dirty, try to clean it once. */ + if (buf_state & BM_DIRTY) + { + LWLockAcquire(BufferDescriptorGetContentLock(desc), LW_SHARED); + FlushBuffer(desc, NULL, IOOBJECT_RELATION, IOCONTEXT_NORMAL); + *buffer_flushed = true; + LWLockRelease(BufferDescriptorGetContentLock(desc)); + } + + /* This will return false if it becomes dirty or someone else pins it. */ + result = InvalidateVictimBuffer(desc); + + UnpinBuffer(desc); + + return result; +} + /* * Try to evict the current block in a shared buffer. * @@ -6101,53 +6636,820 @@ ResOwnerPrintBufferPin(Datum res) * even by the same block. This inherent raciness without other interlocking * makes the function unsuitable for non-testing usage. * + * *buffer_flushed is set to true if the buffer was dirty and has been + * flushed, false otherwise. However, *buffer_flushed=true does not + * necessarily mean that we flushed the buffer, it could have been flushed by + * someone else. + * * Returns true if the buffer was valid and it has now been made invalid. * Returns false if it wasn't valid, if it couldn't be evicted due to a pin, * or if the buffer becomes dirty again while we're trying to write it out. */ bool -EvictUnpinnedBuffer(Buffer buf) +EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed) { BufferDesc *desc; - uint32 buf_state; - bool result; + + Assert(BufferIsValid(buf) && !BufferIsLocal(buf)); /* Make sure we can pin the buffer. */ ResourceOwnerEnlarge(CurrentResourceOwner); ReservePrivateRefCountEntry(); - Assert(!BufferIsLocal(buf)); desc = GetBufferDescriptor(buf - 1); + LockBufHdr(desc); - /* Lock the header and check if it's valid. */ - buf_state = LockBufHdr(desc); - if ((buf_state & BM_VALID) == 0) + return EvictUnpinnedBufferInternal(desc, buffer_flushed); +} + +/* + * Try to evict all the shared buffers. + * + * This function is intended for testing/development use only! See + * EvictUnpinnedBuffer(). + * + * The buffers_* parameters are mandatory and indicate the total count of + * buffers that: + * - buffers_evicted - were evicted + * - buffers_flushed - were flushed + * - buffers_skipped - could not be evicted + */ +void +EvictAllUnpinnedBuffers(int32 *buffers_evicted, int32 *buffers_flushed, + int32 *buffers_skipped) +{ + *buffers_evicted = 0; + *buffers_skipped = 0; + *buffers_flushed = 0; + + for (int buf = 1; buf <= NBuffers; buf++) { - UnlockBufHdr(desc, buf_state); - return false; + BufferDesc *desc = GetBufferDescriptor(buf - 1); + uint32 buf_state; + bool buffer_flushed; + + buf_state = pg_atomic_read_u32(&desc->state); + if (!(buf_state & BM_VALID)) + continue; + + ResourceOwnerEnlarge(CurrentResourceOwner); + ReservePrivateRefCountEntry(); + + LockBufHdr(desc); + + if (EvictUnpinnedBufferInternal(desc, &buffer_flushed)) + (*buffers_evicted)++; + else + (*buffers_skipped)++; + + if (buffer_flushed) + (*buffers_flushed)++; } +} - /* Check that it's not pinned already. */ - if (BUF_STATE_GET_REFCOUNT(buf_state) > 0) +/* + * Try to evict all the shared buffers containing provided relation's pages. + * + * This function is intended for testing/development use only! See + * EvictUnpinnedBuffer(). + * + * The caller must hold at least AccessShareLock on the relation to prevent + * the relation from being dropped. + * + * The buffers_* parameters are mandatory and indicate the total count of + * buffers that: + * - buffers_evicted - were evicted + * - buffers_flushed - were flushed + * - buffers_skipped - could not be evicted + */ +void +EvictRelUnpinnedBuffers(Relation rel, int32 *buffers_evicted, + int32 *buffers_flushed, int32 *buffers_skipped) +{ + Assert(!RelationUsesLocalBuffers(rel)); + + *buffers_skipped = 0; + *buffers_evicted = 0; + *buffers_flushed = 0; + + for (int buf = 1; buf <= NBuffers; buf++) { - UnlockBufHdr(desc, buf_state); - return false; + BufferDesc *desc = GetBufferDescriptor(buf - 1); + uint32 buf_state = pg_atomic_read_u32(&(desc->state)); + bool buffer_flushed; + + /* An unlocked precheck should be safe and saves some cycles. */ + if ((buf_state & BM_VALID) == 0 || + !BufTagMatchesRelFileLocator(&desc->tag, &rel->rd_locator)) + continue; + + /* Make sure we can pin the buffer. */ + ResourceOwnerEnlarge(CurrentResourceOwner); + ReservePrivateRefCountEntry(); + + buf_state = LockBufHdr(desc); + + /* recheck, could have changed without the lock */ + if ((buf_state & BM_VALID) == 0 || + !BufTagMatchesRelFileLocator(&desc->tag, &rel->rd_locator)) + { + UnlockBufHdr(desc, buf_state); + continue; + } + + if (EvictUnpinnedBufferInternal(desc, &buffer_flushed)) + (*buffers_evicted)++; + else + (*buffers_skipped)++; + + if (buffer_flushed) + (*buffers_flushed)++; } +} - PinBuffer_Locked(desc); /* releases spinlock */ +/* + * Generic implementation of the AIO handle staging callback for readv/writev + * on local/shared buffers. + * + * Each readv/writev can target multiple buffers. The buffers have already + * been registered with the IO handle. + * + * To make the IO ready for execution ("staging"), we need to ensure that the + * targeted buffers are in an appropriate state while the IO is ongoing. For + * that the AIO subsystem needs to have its own buffer pin, otherwise an error + * in this backend could lead to this backend's buffer pin being released as + * part of error handling, which in turn could lead to the buffer being + * replaced while IO is ongoing. + */ +static pg_attribute_always_inline void +buffer_stage_common(PgAioHandle *ioh, bool is_write, bool is_temp) +{ + uint64 *io_data; + uint8 handle_data_len; + PgAioWaitRef io_ref; + BufferTag first PG_USED_FOR_ASSERTS_ONLY = {0}; - /* If it was dirty, try to clean it once. */ - if (buf_state & BM_DIRTY) + io_data = pgaio_io_get_handle_data(ioh, &handle_data_len); + + pgaio_io_get_wref(ioh, &io_ref); + + /* iterate over all buffers affected by the vectored readv/writev */ + for (int i = 0; i < handle_data_len; i++) { - LWLockAcquire(BufferDescriptorGetContentLock(desc), LW_SHARED); - FlushBuffer(desc, NULL, IOOBJECT_RELATION, IOCONTEXT_NORMAL); - LWLockRelease(BufferDescriptorGetContentLock(desc)); + Buffer buffer = (Buffer) io_data[i]; + BufferDesc *buf_hdr = is_temp ? + GetLocalBufferDescriptor(-buffer - 1) + : GetBufferDescriptor(buffer - 1); + uint32 buf_state; + + /* + * Check that all the buffers are actually ones that could conceivably + * be done in one IO, i.e. are sequential. This is the last + * buffer-aware code before IO is actually executed and confusion + * about which buffers are targeted by IO can be hard to debug, making + * it worth doing extra-paranoid checks. + */ + if (i == 0) + first = buf_hdr->tag; + else + { + Assert(buf_hdr->tag.relNumber == first.relNumber); + Assert(buf_hdr->tag.blockNum == first.blockNum + i); + } + + if (is_temp) + buf_state = pg_atomic_read_u32(&buf_hdr->state); + else + buf_state = LockBufHdr(buf_hdr); + + /* verify the buffer is in the expected state */ + Assert(buf_state & BM_TAG_VALID); + if (is_write) + { + Assert(buf_state & BM_VALID); + Assert(buf_state & BM_DIRTY); + } + else + { + Assert(!(buf_state & BM_VALID)); + Assert(!(buf_state & BM_DIRTY)); + } + + /* temp buffers don't use BM_IO_IN_PROGRESS */ + if (!is_temp) + Assert(buf_state & BM_IO_IN_PROGRESS); + + Assert(BUF_STATE_GET_REFCOUNT(buf_state) >= 1); + + /* + * Reflect that the buffer is now owned by the AIO subsystem. + * + * For local buffers: This can't be done just via LocalRefCount, as + * one might initially think, as this backend could error out while + * AIO is still in progress, releasing all the pins by the backend + * itself. + * + * This pin is released again in TerminateBufferIO(). + */ + buf_state += BUF_REFCOUNT_ONE; + buf_hdr->io_wref = io_ref; + + if (is_temp) + pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state); + else + UnlockBufHdr(buf_hdr, buf_state); + + /* + * Ensure the content lock that prevents buffer modifications while + * the buffer is being written out is not released early due to an + * error. + */ + if (is_write && !is_temp) + { + LWLock *content_lock; + + content_lock = BufferDescriptorGetContentLock(buf_hdr); + + Assert(LWLockHeldByMe(content_lock)); + + /* + * Lock is now owned by AIO subsystem. + */ + LWLockDisown(content_lock); + } + + /* + * Stop tracking this buffer via the resowner - the AIO system now + * keeps track. + */ + if (!is_temp) + ResourceOwnerForgetBufferIO(CurrentResourceOwner, buffer); } +} - /* This will return false if it becomes dirty or someone else pins it. */ - result = InvalidateVictimBuffer(desc); +/* + * Decode readv errors as encoded by buffer_readv_encode_error(). + */ +static inline void +buffer_readv_decode_error(PgAioResult result, + bool *zeroed_any, + bool *ignored_any, + uint8 *zeroed_or_error_count, + uint8 *checkfail_count, + uint8 *first_off) +{ + uint32 rem_error = result.error_data; - UnpinBuffer(desc); + /* see static asserts in buffer_readv_encode_error */ +#define READV_COUNT_BITS 7 +#define READV_COUNT_MASK ((1 << READV_COUNT_BITS) - 1) + + *zeroed_any = rem_error & 1; + rem_error >>= 1; + + *ignored_any = rem_error & 1; + rem_error >>= 1; + + *zeroed_or_error_count = rem_error & READV_COUNT_MASK; + rem_error >>= READV_COUNT_BITS; + + *checkfail_count = rem_error & READV_COUNT_MASK; + rem_error >>= READV_COUNT_BITS; + + *first_off = rem_error & READV_COUNT_MASK; + rem_error >>= READV_COUNT_BITS; +} + +/* + * Helper to encode errors for buffer_readv_complete() + * + * Errors are encoded as follows: + * - bit 0 indicates whether any page was zeroed (1) or not (0) + * - bit 1 indicates whether any checksum failure was ignored (1) or not (0) + * - next READV_COUNT_BITS bits indicate the number of errored or zeroed pages + * - next READV_COUNT_BITS bits indicate the number of checksum failures + * - next READV_COUNT_BITS bits indicate the first offset of the first page + * that was errored or zeroed or, if no errors/zeroes, the first ignored + * checksum + */ +static inline void +buffer_readv_encode_error(PgAioResult *result, + bool is_temp, + bool zeroed_any, + bool ignored_any, + uint8 error_count, + uint8 zeroed_count, + uint8 checkfail_count, + uint8 first_error_off, + uint8 first_zeroed_off, + uint8 first_ignored_off) +{ + + uint8 shift = 0; + uint8 zeroed_or_error_count = + error_count > 0 ? error_count : zeroed_count; + uint8 first_off; + + StaticAssertStmt(PG_IOV_MAX <= 1 << READV_COUNT_BITS, + "PG_IOV_MAX is bigger than reserved space for error data"); + StaticAssertStmt((1 + 1 + 3 * READV_COUNT_BITS) <= PGAIO_RESULT_ERROR_BITS, + "PGAIO_RESULT_ERROR_BITS is insufficient for buffer_readv"); + + /* + * We only have space to encode one offset - but luckily that's good + * enough. If there is an error, the error is the interesting offset, same + * with a zeroed buffer vs an ignored buffer. + */ + if (error_count > 0) + first_off = first_error_off; + else if (zeroed_count > 0) + first_off = first_zeroed_off; + else + first_off = first_ignored_off; + + Assert(!zeroed_any || error_count == 0); + + result->error_data = 0; + + result->error_data |= zeroed_any << shift; + shift += 1; + + result->error_data |= ignored_any << shift; + shift += 1; + + result->error_data |= ((uint32) zeroed_or_error_count) << shift; + shift += READV_COUNT_BITS; + + result->error_data |= ((uint32) checkfail_count) << shift; + shift += READV_COUNT_BITS; + + result->error_data |= ((uint32) first_off) << shift; + shift += READV_COUNT_BITS; + + result->id = is_temp ? PGAIO_HCB_LOCAL_BUFFER_READV : + PGAIO_HCB_SHARED_BUFFER_READV; + + if (error_count > 0) + result->status = PGAIO_RS_ERROR; + else + result->status = PGAIO_RS_WARNING; + + /* + * The encoding is complicated enough to warrant cross-checking it against + * the decode function. + */ +#ifdef USE_ASSERT_CHECKING + { + bool zeroed_any_2, + ignored_any_2; + uint8 zeroed_or_error_count_2, + checkfail_count_2, + first_off_2; + + buffer_readv_decode_error(*result, + &zeroed_any_2, &ignored_any_2, + &zeroed_or_error_count_2, + &checkfail_count_2, + &first_off_2); + Assert(zeroed_any == zeroed_any_2); + Assert(ignored_any == ignored_any_2); + Assert(zeroed_or_error_count == zeroed_or_error_count_2); + Assert(checkfail_count == checkfail_count_2); + Assert(first_off == first_off_2); + } +#endif + +#undef READV_COUNT_BITS +#undef READV_COUNT_MASK +} + +/* + * Helper for AIO readv completion callbacks, supporting both shared and temp + * buffers. Gets called once for each buffer in a multi-page read. + */ +static pg_attribute_always_inline void +buffer_readv_complete_one(PgAioTargetData *td, uint8 buf_off, Buffer buffer, + uint8 flags, bool failed, bool is_temp, + bool *buffer_invalid, + bool *failed_checksum, + bool *ignored_checksum, + bool *zeroed_buffer) +{ + BufferDesc *buf_hdr = is_temp ? + GetLocalBufferDescriptor(-buffer - 1) + : GetBufferDescriptor(buffer - 1); + BufferTag tag = buf_hdr->tag; + char *bufdata = BufferGetBlock(buffer); + uint32 set_flag_bits; + int piv_flags; + + /* check that the buffer is in the expected state for a read */ +#ifdef USE_ASSERT_CHECKING + { + uint32 buf_state = pg_atomic_read_u32(&buf_hdr->state); + + Assert(buf_state & BM_TAG_VALID); + Assert(!(buf_state & BM_VALID)); + /* temp buffers don't use BM_IO_IN_PROGRESS */ + if (!is_temp) + Assert(buf_state & BM_IO_IN_PROGRESS); + Assert(!(buf_state & BM_DIRTY)); + } +#endif + + *buffer_invalid = false; + *failed_checksum = false; + *ignored_checksum = false; + *zeroed_buffer = false; + + /* + * We ask PageIsVerified() to only log the message about checksum errors, + * as the completion might be run in any backend (or IO workers). We will + * report checksum errors in buffer_readv_report(). + */ + piv_flags = PIV_LOG_LOG; + + /* the local zero_damaged_pages may differ from the definer's */ + if (flags & READ_BUFFERS_IGNORE_CHECKSUM_FAILURES) + piv_flags |= PIV_IGNORE_CHECKSUM_FAILURE; + + /* Check for garbage data. */ + if (!failed) + { + /* + * If the buffer is not currently pinned by this backend, e.g. because + * we're completing this IO after an error, the buffer data will have + * been marked as inaccessible when the buffer was unpinned. The AIO + * subsystem holds a pin, but that doesn't prevent the buffer from + * having been marked as inaccessible. The completion might also be + * executed in a different process. + */ +#ifdef USE_VALGRIND + if (!BufferIsPinned(buffer)) + VALGRIND_MAKE_MEM_DEFINED(bufdata, BLCKSZ); +#endif + + if (!PageIsVerified((Page) bufdata, tag.blockNum, piv_flags, + failed_checksum)) + { + if (flags & READ_BUFFERS_ZERO_ON_ERROR) + { + memset(bufdata, 0, BLCKSZ); + *zeroed_buffer = true; + } + else + { + *buffer_invalid = true; + /* mark buffer as having failed */ + failed = true; + } + } + else if (*failed_checksum) + *ignored_checksum = true; + + /* undo what we did above */ +#ifdef USE_VALGRIND + if (!BufferIsPinned(buffer)) + VALGRIND_MAKE_MEM_NOACCESS(bufdata, BLCKSZ); +#endif + + /* + * Immediately log a message about the invalid page, but only to the + * server log. The reason to do so immediately is that this may be + * executed in a different backend than the one that originated the + * request. The reason to do so immediately is that the originator + * might not process the query result immediately (because it is busy + * doing another part of query processing) or at all (e.g. if it was + * cancelled or errored out due to another IO also failing). The + * definer of the IO will emit an ERROR or WARNING when processing the + * IO's results + * + * To avoid duplicating the code to emit these log messages, we reuse + * buffer_readv_report(). + */ + if (*buffer_invalid || *failed_checksum || *zeroed_buffer) + { + PgAioResult result_one = {0}; + + buffer_readv_encode_error(&result_one, is_temp, + *zeroed_buffer, + *ignored_checksum, + *buffer_invalid, + *zeroed_buffer ? 1 : 0, + *failed_checksum ? 1 : 0, + buf_off, buf_off, buf_off); + pgaio_result_report(result_one, td, LOG_SERVER_ONLY); + } + } + + /* Terminate I/O and set BM_VALID. */ + set_flag_bits = failed ? BM_IO_ERROR : BM_VALID; + if (is_temp) + TerminateLocalBufferIO(buf_hdr, false, set_flag_bits, true); + else + TerminateBufferIO(buf_hdr, false, set_flag_bits, false, true); + + /* + * Call the BUFFER_READ_DONE tracepoint in the callback, even though the + * callback may not be executed in the same backend that called + * BUFFER_READ_START. The alternative would be to defer calling the + * tracepoint to a later point (e.g. the local completion callback for + * shared buffer reads), which seems even less helpful. + */ + TRACE_POSTGRESQL_BUFFER_READ_DONE(tag.forkNum, + tag.blockNum, + tag.spcOid, + tag.dbOid, + tag.relNumber, + is_temp ? MyProcNumber : INVALID_PROC_NUMBER, + false); +} + +/* + * Perform completion handling of a single AIO read. This read may cover + * multiple blocks / buffers. + * + * Shared between shared and local buffers, to reduce code duplication. + */ +static pg_attribute_always_inline PgAioResult +buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, + uint8 cb_data, bool is_temp) +{ + PgAioResult result = prior_result; + PgAioTargetData *td = pgaio_io_get_target_data(ioh); + uint8 first_error_off = 0; + uint8 first_zeroed_off = 0; + uint8 first_ignored_off = 0; + uint8 error_count = 0; + uint8 zeroed_count = 0; + uint8 ignored_count = 0; + uint8 checkfail_count = 0; + uint64 *io_data; + uint8 handle_data_len; + + if (is_temp) + { + Assert(td->smgr.is_temp); + Assert(pgaio_io_get_owner(ioh) == MyProcNumber); + } + else + Assert(!td->smgr.is_temp); + + /* + * Iterate over all the buffers affected by this IO and call the + * per-buffer completion function for each buffer. + */ + io_data = pgaio_io_get_handle_data(ioh, &handle_data_len); + for (uint8 buf_off = 0; buf_off < handle_data_len; buf_off++) + { + Buffer buf = io_data[buf_off]; + bool failed; + bool failed_verification = false; + bool failed_checksum = false; + bool zeroed_buffer = false; + bool ignored_checksum = false; + + Assert(BufferIsValid(buf)); + + /* + * If the entire I/O failed on a lower-level, each buffer needs to be + * marked as failed. In case of a partial read, the first few buffers + * may be ok. + */ + failed = + prior_result.status == PGAIO_RS_ERROR + || prior_result.result <= buf_off; + + buffer_readv_complete_one(td, buf_off, buf, cb_data, failed, is_temp, + &failed_verification, + &failed_checksum, + &ignored_checksum, + &zeroed_buffer); + + /* + * Track information about the number of different kinds of error + * conditions across all pages, as there can be multiple pages failing + * verification as part of one IO. + */ + if (failed_verification && !zeroed_buffer && error_count++ == 0) + first_error_off = buf_off; + if (zeroed_buffer && zeroed_count++ == 0) + first_zeroed_off = buf_off; + if (ignored_checksum && ignored_count++ == 0) + first_ignored_off = buf_off; + if (failed_checksum) + checkfail_count++; + } + + /* + * If the smgr read succeeded [partially] and page verification failed for + * some of the pages, adjust the IO's result state appropriately. + */ + if (prior_result.status != PGAIO_RS_ERROR && + (error_count > 0 || ignored_count > 0 || zeroed_count > 0)) + { + buffer_readv_encode_error(&result, is_temp, + zeroed_count > 0, ignored_count > 0, + error_count, zeroed_count, checkfail_count, + first_error_off, first_zeroed_off, + first_ignored_off); + pgaio_result_report(result, td, DEBUG1); + } + + /* + * For shared relations this reporting is done in + * shared_buffer_readv_complete_local(). + */ + if (is_temp && checkfail_count > 0) + pgstat_report_checksum_failures_in_db(td->smgr.rlocator.dbOid, + checkfail_count); return result; } + +/* + * AIO error reporting callback for aio_shared_buffer_readv_cb and + * aio_local_buffer_readv_cb. + * + * The error is encoded / decoded in buffer_readv_encode_error() / + * buffer_readv_decode_error(). + */ +static void +buffer_readv_report(PgAioResult result, const PgAioTargetData *td, + int elevel) +{ + int nblocks = td->smgr.nblocks; + BlockNumber first = td->smgr.blockNum; + BlockNumber last = first + nblocks - 1; + ProcNumber errProc = + td->smgr.is_temp ? MyProcNumber : INVALID_PROC_NUMBER; + RelPathStr rpath = + relpathbackend(td->smgr.rlocator, errProc, td->smgr.forkNum); + bool zeroed_any, + ignored_any; + uint8 zeroed_or_error_count, + checkfail_count, + first_off; + uint8 affected_count; + const char *msg_one, + *msg_mult, + *det_mult, + *hint_mult; + + buffer_readv_decode_error(result, &zeroed_any, &ignored_any, + &zeroed_or_error_count, + &checkfail_count, + &first_off); + + /* + * Treat a read that had both zeroed buffers *and* ignored checksums as a + * special case, it's too irregular to be emitted the same way as the + * other cases. + */ + if (zeroed_any && ignored_any) + { + Assert(zeroed_any && ignored_any); + Assert(nblocks > 1); /* same block can't be both zeroed and ignored */ + Assert(result.status != PGAIO_RS_ERROR); + affected_count = zeroed_or_error_count; + + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + errmsg("zeroing %u page(s) and ignoring %u checksum failure(s) among blocks %u..%u of relation %s", + affected_count, checkfail_count, first, last, rpath.str), + affected_count > 1 ? + errdetail("Block %u held first zeroed page.", + first + first_off) : 0, + errhint("See server log for details about the other %d invalid block(s).", + affected_count + checkfail_count - 1)); + return; + } + + /* + * The other messages are highly repetitive. To avoid duplicating a long + * and complicated ereport(), gather the translated format strings + * separately and then do one common ereport. + */ + if (result.status == PGAIO_RS_ERROR) + { + Assert(!zeroed_any); /* can't have invalid pages when zeroing them */ + affected_count = zeroed_or_error_count; + msg_one = _("invalid page in block %u of relation %s"); + msg_mult = _("%u invalid pages among blocks %u..%u of relation %s"); + det_mult = _("Block %u held first invalid page."); + hint_mult = _("See server log for the other %u invalid block(s)."); + } + else if (zeroed_any && !ignored_any) + { + affected_count = zeroed_or_error_count; + msg_one = _("invalid page in block %u of relation %s; zeroing out page"); + msg_mult = _("zeroing out %u invalid pages among blocks %u..%u of relation %s"); + det_mult = _("Block %u held first zeroed page."); + hint_mult = _("See server log for the other %u zeroed block(s)."); + } + else if (!zeroed_any && ignored_any) + { + affected_count = checkfail_count; + msg_one = _("ignoring checksum failure in block %u of relation %s"); + msg_mult = _("ignoring %u checksum failures among blocks %u..%u of relation %s"); + det_mult = _("Block %u held first ignored page."); + hint_mult = _("See server log for the other %u ignored block(s)."); + } + else + pg_unreachable(); + + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + affected_count == 1 ? + errmsg_internal(msg_one, first + first_off, rpath.str) : + errmsg_internal(msg_mult, affected_count, first, last, rpath.str), + affected_count > 1 ? errdetail_internal(det_mult, first + first_off) : 0, + affected_count > 1 ? errhint_internal(hint_mult, affected_count - 1) : 0); +} + +static void +shared_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data) +{ + buffer_stage_common(ioh, false, false); +} + +static PgAioResult +shared_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, + uint8 cb_data) +{ + return buffer_readv_complete(ioh, prior_result, cb_data, false); +} + +/* + * We need a backend-local completion callback for shared buffers, to be able + * to report checksum errors correctly. Unfortunately that can only safely + * happen if the reporting backend has previously called + * pgstat_prepare_report_checksum_failure(), which we can only guarantee in + * the backend that started the IO. Hence this callback. + */ +static PgAioResult +shared_buffer_readv_complete_local(PgAioHandle *ioh, PgAioResult prior_result, + uint8 cb_data) +{ + bool zeroed_any, + ignored_any; + uint8 zeroed_or_error_count, + checkfail_count, + first_off; + + if (prior_result.status == PGAIO_RS_OK) + return prior_result; + + buffer_readv_decode_error(prior_result, + &zeroed_any, + &ignored_any, + &zeroed_or_error_count, + &checkfail_count, + &first_off); + + if (checkfail_count) + { + PgAioTargetData *td = pgaio_io_get_target_data(ioh); + + pgstat_report_checksum_failures_in_db(td->smgr.rlocator.dbOid, + checkfail_count); + } + + return prior_result; +} + +static void +local_buffer_readv_stage(PgAioHandle *ioh, uint8 cb_data) +{ + buffer_stage_common(ioh, false, true); +} + +static PgAioResult +local_buffer_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, + uint8 cb_data) +{ + return buffer_readv_complete(ioh, prior_result, cb_data, true); +} + +/* readv callback is passed READ_BUFFERS_* flags as callback data */ +const PgAioHandleCallbacks aio_shared_buffer_readv_cb = { + .stage = shared_buffer_readv_stage, + .complete_shared = shared_buffer_readv_complete, + /* need a local callback to report checksum failures */ + .complete_local = shared_buffer_readv_complete_local, + .report = buffer_readv_report, +}; + +/* readv callback is passed READ_BUFFERS_* flags as callback data */ +const PgAioHandleCallbacks aio_local_buffer_readv_cb = { + .stage = local_buffer_readv_stage, + + /* + * Note that this, in contrast to the shared_buffers case, uses + * complete_local, as only the issuing backend has access to the required + * datastructures. This is important in case the IO completion may be + * consumed incidentally by another backend. + */ + .complete_local = local_buffer_readv_complete, + .report = buffer_readv_report, +}; diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 19797de31a9c8..01909be027258 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -4,7 +4,7 @@ * routines for managing the buffer pool's replacement strategy. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -380,10 +380,10 @@ StrategyFreeBuffer(BufferDesc *buf) } /* - * StrategySyncStart -- tell BufferSync where to start syncing + * StrategySyncStart -- tell BgBufferSync where to start syncing * * The result is the buffer index of the best buffer to sync first. - * BufferSync() will proceed circularly around the buffer array from there. + * BgBufferSync() will proceed circularly around the buffer array from there. * * In addition, we return the completed-pass count (which is effectively * the higher-order bits of nextVictimBuffer) and the count of recent buffer @@ -506,7 +506,7 @@ StrategyInitialize(bool init) /* * Grab the whole linked list of free buffers for our strategy. We - * assume it was previously set up by InitBufferPool(). + * assume it was previously set up by BufferManagerShmemInit(). */ StrategyControl->firstFreeBuffer = 0; StrategyControl->lastFreeBuffer = NBuffers - 1; @@ -555,8 +555,50 @@ GetAccessStrategy(BufferAccessStrategyType btype) return NULL; case BAS_BULKREAD: - ring_size_kb = 256; - break; + { + int ring_max_kb; + + /* + * The ring always needs to be large enough to allow some + * separation in time between providing a buffer to the user + * of the strategy and that buffer being reused. Otherwise the + * user's pin will prevent reuse of the buffer, even without + * concurrent activity. + * + * We also need to ensure the ring always is large enough for + * SYNC_SCAN_REPORT_INTERVAL, as noted above. + * + * Thus we start out a minimal size and increase the size + * further if appropriate. + */ + ring_size_kb = 256; + + /* + * There's no point in a larger ring if we won't be allowed to + * pin sufficiently many buffers. But we never limit to less + * than the minimal size above. + */ + ring_max_kb = GetPinLimit() * (BLCKSZ / 1024); + ring_max_kb = Max(ring_size_kb, ring_max_kb); + + /* + * We would like the ring to additionally have space for the + * configured degree of IO concurrency. While being read in, + * buffers can obviously not yet be reused. + * + * Each IO can be up to io_combine_limit blocks large, and we + * want to start up to effective_io_concurrency IOs. + * + * Note that effective_io_concurrency may be 0, which disables + * AIO. + */ + ring_size_kb += (BLCKSZ / 1024) * + io_combine_limit * effective_io_concurrency; + + if (ring_size_kb > ring_max_kb) + ring_size_kb = ring_max_kb; + break; + } case BAS_BULKWRITE: ring_size_kb = 16 * 1024; break; diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 8da7dd6c98ae4..ba26627f7b00d 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -4,7 +4,7 @@ * local buffer manager. Fast buffer manager for temporary tables, * which never need to be WAL-logged or checkpointed, etc. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * @@ -18,10 +18,12 @@ #include "access/parallel.h" #include "executor/instrument.h" #include "pgstat.h" +#include "storage/aio.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/fd.h" #include "utils/guc_hooks.h" +#include "utils/memdebug.h" #include "utils/memutils.h" #include "utils/resowner.h" @@ -173,12 +175,55 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, return bufHdr; } +/* + * Like FlushBuffer(), just for local buffers. + */ +void +FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln) +{ + instr_time io_start; + Page localpage = (char *) LocalBufHdrGetBlock(bufHdr); + + Assert(LocalRefCount[-BufferDescriptorGetBuffer(bufHdr) - 1] > 0); + + /* + * Try to start an I/O operation. There currently are no reasons for + * StartLocalBufferIO to return false, so we raise an error in that case. + */ + if (!StartLocalBufferIO(bufHdr, false, false)) + elog(ERROR, "failed to start write IO on local buffer"); + + /* Find smgr relation for buffer */ + if (reln == NULL) + reln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), + MyProcNumber); + + PageSetChecksumInplace(localpage, bufHdr->tag.blockNum); + + io_start = pgstat_prepare_io_time(track_io_timing); + + /* And write... */ + smgrwrite(reln, + BufTagGetForkNum(&bufHdr->tag), + bufHdr->tag.blockNum, + localpage, + false); + + /* Temporary table I/O does not use Buffer Access Strategies */ + pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, + IOOP_WRITE, io_start, 1, BLCKSZ); + + /* Mark not-dirty */ + TerminateLocalBufferIO(bufHdr, true, 0, false); + + pgBufferUsage.local_blks_written++; +} + static Buffer GetLocalVictimBuffer(void) { int victim_bufid; int trycounter; - uint32 buf_state; BufferDesc *bufHdr; ResourceOwnerEnlarge(CurrentResourceOwner); @@ -199,7 +244,7 @@ GetLocalVictimBuffer(void) if (LocalRefCount[victim_bufid] == 0) { - buf_state = pg_atomic_read_u32(&bufHdr->state); + uint32 buf_state = pg_atomic_read_u32(&bufHdr->state); if (BUF_STATE_GET_USAGECOUNT(buf_state) > 0) { @@ -207,6 +252,13 @@ GetLocalVictimBuffer(void) pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); trycounter = NLocBuffer; } + else if (BUF_STATE_GET_REFCOUNT(buf_state) > 0) + { + /* + * This can be reached if the backend initiated AIO for this + * buffer and then errored out. + */ + } else { /* Found a usable buffer */ @@ -233,58 +285,38 @@ GetLocalVictimBuffer(void) * this buffer is not referenced but it might still be dirty. if that's * the case, write it out before reusing it! */ - if (buf_state & BM_DIRTY) - { - instr_time io_start; - SMgrRelation oreln; - Page localpage = (char *) LocalBufHdrGetBlock(bufHdr); - - /* Find smgr relation for buffer */ - oreln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), MyProcNumber); - - PageSetChecksumInplace(localpage, bufHdr->tag.blockNum); - - io_start = pgstat_prepare_io_time(track_io_timing); - - /* And write... */ - smgrwrite(oreln, - BufTagGetForkNum(&bufHdr->tag), - bufHdr->tag.blockNum, - localpage, - false); - - /* Temporary table I/O does not use Buffer Access Strategies */ - pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, - IOOP_WRITE, io_start, 1); - - /* Mark not-dirty now in case we error out below */ - buf_state &= ~BM_DIRTY; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); - - pgBufferUsage.local_blks_written++; - } + if (pg_atomic_read_u32(&bufHdr->state) & BM_DIRTY) + FlushLocalBuffer(bufHdr, NULL); /* * Remove the victim buffer from the hashtable and mark as invalid. */ - if (buf_state & BM_TAG_VALID) + if (pg_atomic_read_u32(&bufHdr->state) & BM_TAG_VALID) { - LocalBufferLookupEnt *hresult; + InvalidateLocalBuffer(bufHdr, false); - hresult = (LocalBufferLookupEnt *) - hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL); - if (!hresult) /* shouldn't happen */ - elog(ERROR, "local buffer hash table corrupted"); - /* mark buffer invalid just in case hash insert fails */ - ClearBufferTag(&bufHdr->tag); - buf_state &= ~(BUF_FLAG_MASK | BUF_USAGECOUNT_MASK); - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); - pgstat_count_io_op(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EVICT); + pgstat_count_io_op(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EVICT, 1, 0); } return BufferDescriptorGetBuffer(bufHdr); } +/* see GetPinLimit() */ +uint32 +GetLocalPinLimit(void) +{ + /* Every backend has its own temporary buffers, and can pin them all. */ + return num_temp_buffers; +} + +/* see GetAdditionalPinLimit() */ +uint32 +GetAdditionalLocalPinLimit(void) +{ + Assert(NLocalPinnedBuffers <= num_temp_buffers); + return num_temp_buffers - NLocalPinnedBuffers; +} + /* see LimitAdditionalPins() */ void LimitAdditionalLocalPins(uint32 *additional_pins) @@ -337,7 +369,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, buf_block = LocalBufHdrGetBlock(buf_hdr); /* new buffers are zero-filled */ - MemSet((char *) buf_block, 0, BLCKSZ); + MemSet(buf_block, 0, BLCKSZ); } first_block = smgrnblocks(bmr.smgr, fork); @@ -359,7 +391,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend relation %s beyond %u blocks", - relpath(bmr.smgr->smgr_rlocator, fork), + relpath(bmr.smgr->smgr_rlocator, fork).str, MaxBlockNumber))); for (uint32 i = 0; i < extend_by; i++) @@ -379,7 +411,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i); hresult = (LocalBufferLookupEnt *) - hash_search(LocalBufHash, (void *) &tag, HASH_ENTER, &found); + hash_search(LocalBufHash, &tag, HASH_ENTER, &found); if (found) { BufferDesc *existing_hdr; @@ -391,11 +423,17 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, PinLocalBuffer(existing_hdr, false); buffers[i] = BufferDescriptorGetBuffer(existing_hdr); + /* + * Clear the BM_VALID bit, do StartLocalBufferIO() and proceed. + */ buf_state = pg_atomic_read_u32(&existing_hdr->state); Assert(buf_state & BM_TAG_VALID); Assert(!(buf_state & BM_DIRTY)); buf_state &= ~BM_VALID; pg_atomic_unlocked_write_u32(&existing_hdr->state, buf_state); + + /* no need to loop for local buffers */ + StartLocalBufferIO(existing_hdr, true, false); } else { @@ -410,6 +448,8 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, pg_atomic_unlocked_write_u32(&victim_buf_hdr->state, buf_state); hresult->id = victim_buf_id; + + StartLocalBufferIO(victim_buf_hdr, true, false); } } @@ -419,7 +459,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr, smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false); pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EXTEND, - io_start, extend_by); + io_start, 1, extend_by * BLCKSZ); for (uint32 i = 0; i < extend_by; i++) { @@ -474,6 +514,140 @@ MarkLocalBufferDirty(Buffer buffer) pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); } +/* + * Like StartBufferIO, but for local buffers + */ +bool +StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait) +{ + uint32 buf_state; + + /* + * With AIO the buffer could have IO in progress, e.g. when there are two + * scans of the same relation. Either wait for the other IO or return + * false. + */ + if (pgaio_wref_valid(&bufHdr->io_wref)) + { + PgAioWaitRef iow = bufHdr->io_wref; + + if (nowait) + return false; + + pgaio_wref_wait(&iow); + } + + /* Once we get here, there is definitely no I/O active on this buffer */ + + /* Check if someone else already did the I/O */ + buf_state = pg_atomic_read_u32(&bufHdr->state); + if (forInput ? (buf_state & BM_VALID) : !(buf_state & BM_DIRTY)) + { + return false; + } + + /* BM_IO_IN_PROGRESS isn't currently used for local buffers */ + + /* local buffers don't track IO using resowners */ + + return true; +} + +/* + * Like TerminateBufferIO, but for local buffers + */ +void +TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, uint32 set_flag_bits, + bool release_aio) +{ + /* Only need to adjust flags */ + uint32 buf_state = pg_atomic_read_u32(&bufHdr->state); + + /* BM_IO_IN_PROGRESS isn't currently used for local buffers */ + + /* Clear earlier errors, if this IO failed, it'll be marked again */ + buf_state &= ~BM_IO_ERROR; + + if (clear_dirty) + buf_state &= ~BM_DIRTY; + + if (release_aio) + { + /* release pin held by IO subsystem, see also buffer_stage_common() */ + Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0); + buf_state -= BUF_REFCOUNT_ONE; + pgaio_wref_clear(&bufHdr->io_wref); + } + + buf_state |= set_flag_bits; + pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + + /* local buffers don't track IO using resowners */ + + /* local buffers don't use the IO CV, as no other process can see buffer */ + + /* local buffers don't use BM_PIN_COUNT_WAITER, so no need to wake */ +} + +/* + * InvalidateLocalBuffer -- mark a local buffer invalid. + * + * If check_unreferenced is true, error out if the buffer is still + * pinned. Passing false is appropriate when calling InvalidateLocalBuffer() + * as part of changing the identity of a buffer, instead of just dropping the + * buffer. + * + * See also InvalidateBuffer(). + */ +void +InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced) +{ + Buffer buffer = BufferDescriptorGetBuffer(bufHdr); + int bufid = -buffer - 1; + uint32 buf_state; + LocalBufferLookupEnt *hresult; + + /* + * It's possible that we started IO on this buffer before e.g. aborting + * the transaction that created a table. We need to wait for that IO to + * complete before removing / reusing the buffer. + */ + if (pgaio_wref_valid(&bufHdr->io_wref)) + { + PgAioWaitRef iow = bufHdr->io_wref; + + pgaio_wref_wait(&iow); + Assert(!pgaio_wref_valid(&bufHdr->io_wref)); + } + + buf_state = pg_atomic_read_u32(&bufHdr->state); + + /* + * We need to test not just LocalRefCount[bufid] but also the BufferDesc + * itself, as the latter is used to represent a pin by the AIO subsystem. + * This can happen if AIO is initiated and then the query errors out. + */ + if (check_unreferenced && + (LocalRefCount[bufid] != 0 || BUF_STATE_GET_REFCOUNT(buf_state) != 0)) + elog(ERROR, "block %u of %s is still referenced (local %d)", + bufHdr->tag.blockNum, + relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag), + MyProcNumber, + BufTagGetForkNum(&bufHdr->tag)).str, + LocalRefCount[bufid]); + + /* Remove entry from hashtable */ + hresult = (LocalBufferLookupEnt *) + hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL); + if (!hresult) /* shouldn't happen */ + elog(ERROR, "local buffer hash table corrupted"); + /* Mark buffer invalid */ + ClearBufferTag(&bufHdr->tag); + buf_state &= ~BUF_FLAG_MASK; + buf_state &= ~BUF_USAGECOUNT_MASK; + pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); +} + /* * DropRelationLocalBuffers * This function removes from the buffer pool all the pages of the @@ -494,7 +668,6 @@ DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, for (i = 0; i < NLocBuffer; i++) { BufferDesc *bufHdr = GetLocalBufferDescriptor(i); - LocalBufferLookupEnt *hresult; uint32 buf_state; buf_state = pg_atomic_read_u32(&bufHdr->state); @@ -504,24 +677,7 @@ DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, BufTagGetForkNum(&bufHdr->tag) == forkNum && bufHdr->tag.blockNum >= firstDelBlock) { - if (LocalRefCount[i] != 0) - elog(ERROR, "block %u of %s is still referenced (local %u)", - bufHdr->tag.blockNum, - relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag), - MyProcNumber, - BufTagGetForkNum(&bufHdr->tag)), - LocalRefCount[i]); - - /* Remove entry from hashtable */ - hresult = (LocalBufferLookupEnt *) - hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL); - if (!hresult) /* shouldn't happen */ - elog(ERROR, "local buffer hash table corrupted"); - /* Mark buffer invalid */ - ClearBufferTag(&bufHdr->tag); - buf_state &= ~BUF_FLAG_MASK; - buf_state &= ~BUF_USAGECOUNT_MASK; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + InvalidateLocalBuffer(bufHdr, true); } } } @@ -541,7 +697,6 @@ DropRelationAllLocalBuffers(RelFileLocator rlocator) for (i = 0; i < NLocBuffer; i++) { BufferDesc *bufHdr = GetLocalBufferDescriptor(i); - LocalBufferLookupEnt *hresult; uint32 buf_state; buf_state = pg_atomic_read_u32(&bufHdr->state); @@ -549,23 +704,7 @@ DropRelationAllLocalBuffers(RelFileLocator rlocator) if ((buf_state & BM_TAG_VALID) && BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator)) { - if (LocalRefCount[i] != 0) - elog(ERROR, "block %u of %s is still referenced (local %u)", - bufHdr->tag.blockNum, - relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag), - MyProcNumber, - BufTagGetForkNum(&bufHdr->tag)), - LocalRefCount[i]); - /* Remove entry from hashtable */ - hresult = (LocalBufferLookupEnt *) - hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL); - if (!hresult) /* shouldn't happen */ - elog(ERROR, "local buffer hash table corrupted"); - /* Mark buffer invalid */ - ClearBufferTag(&bufHdr->tag); - buf_state &= ~BUF_FLAG_MASK; - buf_state &= ~BUF_USAGECOUNT_MASK; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + InvalidateLocalBuffer(bufHdr, true); } } } @@ -620,6 +759,8 @@ InitLocalBuffers(void) */ buf->buf_id = -i - 2; + pgaio_wref_clear(&buf->io_wref); + /* * Intentionally do not initialize the buffer's atomic variable * (besides zeroing the underlying memory above). That way we get @@ -663,12 +804,22 @@ PinLocalBuffer(BufferDesc *buf_hdr, bool adjust_usagecount) if (LocalRefCount[bufid] == 0) { NLocalPinnedBuffers++; + buf_state += BUF_REFCOUNT_ONE; if (adjust_usagecount && BUF_STATE_GET_USAGECOUNT(buf_state) < BM_MAX_USAGE_COUNT) { buf_state += BUF_USAGECOUNT_ONE; - pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state); } + pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state); + + /* + * See comment in PinBuffer(). + * + * If the buffer isn't allocated yet, it'll be marked as defined in + * GetLocalBufferStorage(). + */ + if (LocalBufHdrGetBlock(buf_hdr) != NULL) + VALGRIND_MAKE_MEM_DEFINED(LocalBufHdrGetBlock(buf_hdr), BLCKSZ); } LocalRefCount[bufid]++; ResourceOwnerRememberBuffer(CurrentResourceOwner, @@ -694,7 +845,20 @@ UnpinLocalBufferNoOwner(Buffer buffer) Assert(NLocalPinnedBuffers > 0); if (--LocalRefCount[buffid] == 0) + { + BufferDesc *buf_hdr = GetLocalBufferDescriptor(buffid); + uint32 buf_state; + NLocalPinnedBuffers--; + + buf_state = pg_atomic_read_u32(&buf_hdr->state); + Assert(BUF_STATE_GET_REFCOUNT(buf_state) > 0); + buf_state -= BUF_REFCOUNT_ONE; + pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state); + + /* see comment in UnpinBufferNoOwner */ + VALGRIND_MAKE_MEM_NOACCESS(LocalBufHdrGetBlock(buf_hdr), BLCKSZ); + } } /* @@ -774,6 +938,16 @@ GetLocalBufferStorage(void) next_buf_in_block++; total_bufs_allocated++; + /* + * Caller's PinLocalBuffer() was too early for Valgrind updates, so do it + * here. The block is actually undefined, but we want consistency with + * the regular case of not needing to allocate memory. This is + * specifically needed when method_io_uring.c fills the block, because + * Valgrind doesn't recognize io_uring reads causing undefined memory to + * become defined. + */ + VALGRIND_MAKE_MEM_DEFINED(this_buf, BLCKSZ); + return (Block) this_buf; } diff --git a/src/backend/storage/buffer/meson.build b/src/backend/storage/buffer/meson.build index f152dbb0702e3..448976d2400bd 100644 --- a/src/backend/storage/buffer/meson.build +++ b/src/backend/storage/buffer/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'buf_init.c', diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index a27f51f62207e..366d70d38a195 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -3,7 +3,7 @@ * buffile.c * Management of large buffered temporary files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -97,7 +97,7 @@ struct BufFile int nbytes; /* total # of valid bytes in buffer */ /* - * XXX Should ideally us PGIOAlignedBlock, but might need a way to avoid + * XXX Should ideally use PGIOAlignedBlock, but might need a way to avoid * wasting per-file alignment padding when some users create many files. */ PGAlignedBlock buffer; @@ -459,7 +459,7 @@ BufFileLoadBuffer(BufFile *file) */ file->nbytes = FileRead(thisfile, file->buffer.data, - sizeof(file->buffer), + sizeof(file->buffer.data), file->curOffset, WAIT_EVENT_BUFFILE_READ); if (file->nbytes < 0) diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c index d4fbe542077f1..aa8c64a2c9eb5 100644 --- a/src/backend/storage/file/copydir.c +++ b/src/backend/storage/file/copydir.c @@ -3,7 +3,7 @@ * copydir.c * copies a directory * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * While "xcopy /e /i /q" works fine for copying directories, on Windows XP @@ -18,6 +18,9 @@ #include "postgres.h" +#ifdef HAVE_COPYFILE_H +#include +#endif #include #include @@ -27,11 +30,19 @@ #include "storage/copydir.h" #include "storage/fd.h" +/* GUCs */ +int file_copy_method = FILE_COPY_METHOD_COPY; + +static void clone_file(const char *fromfile, const char *tofile); + /* * copydir: copy a directory * * If recurse is false, subdirectories are ignored. Anything that's not * a directory or a regular file is ignored. + * + * This function uses the file_copy_method GUC. New uses of this function must + * be documented in doc/src/sgml/config.sgml. */ void copydir(const char *fromdir, const char *todir, bool recurse) @@ -71,7 +82,12 @@ copydir(const char *fromdir, const char *todir, bool recurse) copydir(fromfile, tofile, true); } else if (xlde_type == PGFILETYPE_REG) - copy_file(fromfile, tofile); + { + if (file_copy_method == FILE_COPY_METHOD_CLONE) + clone_file(fromfile, tofile); + else + copy_file(fromfile, tofile); + } } FreeDir(xldir); @@ -214,3 +230,65 @@ copy_file(const char *fromfile, const char *tofile) pfree(buffer); } + +/* + * clone one file + */ +static void +clone_file(const char *fromfile, const char *tofile) +{ +#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE) + if (copyfile(fromfile, tofile, NULL, COPYFILE_CLONE_FORCE) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not clone file \"%s\" to \"%s\": %m", + fromfile, tofile))); +#elif defined(HAVE_COPY_FILE_RANGE) + int srcfd; + int dstfd; + ssize_t nbytes; + + srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY); + if (srcfd < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", fromfile))); + + dstfd = OpenTransientFile(tofile, O_WRONLY | O_CREAT | O_EXCL | PG_BINARY); + if (dstfd < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not create file \"%s\": %m", tofile))); + + do + { + /* + * Don't copy too much at once, so we can check for interrupts from + * time to time if it falls back to a slow copy. + */ + CHECK_FOR_INTERRUPTS(); + pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_COPY); + nbytes = copy_file_range(srcfd, NULL, dstfd, NULL, 1024 * 1024, 0); + if (nbytes < 0 && errno != EINTR) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not clone file \"%s\" to \"%s\": %m", + fromfile, tofile))); + pgstat_report_wait_end(); + } + while (nbytes != 0); + + if (CloseTransientFile(dstfd) != 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", tofile))); + + if (CloseTransientFile(srcfd) != 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", fromfile))); +#else + /* If there is no CLONE support this function should not be called. */ + pg_unreachable(); +#endif +} diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 3944321ff3776..0e8299dd55646 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -3,7 +3,7 @@ * fd.c * Virtual file descriptor code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -93,8 +93,8 @@ #include "common/pg_prng.h" #include "miscadmin.h" #include "pgstat.h" -#include "portability/mem.h" #include "postmaster/startup.h" +#include "storage/aio.h" #include "storage/fd.h" #include "storage/ipc.h" #include "utils/guc.h" @@ -911,7 +911,7 @@ InitFileAccess(void) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); - MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd)); + MemSet(&(VfdCache[0]), 0, sizeof(Vfd)); VfdCache->fd = VFD_CLOSED; SizeVfdCache = 1; @@ -1048,16 +1048,17 @@ set_max_safe_fds(void) /*---------- * We want to set max_safe_fds to - * MIN(usable_fds, max_files_per_process - already_open) + * MIN(usable_fds, max_files_per_process) * less the slop factor for files that are opened without consulting - * fd.c. This ensures that we won't exceed either max_files_per_process - * or the experimentally-determined EMFILE limit. + * fd.c. This ensures that we won't allow to open more than + * max_files_per_process, or the experimentally-determined EMFILE limit, + * additional files. *---------- */ count_usable_fds(max_files_per_process, &usable_fds, &already_open); - max_safe_fds = Min(usable_fds, max_files_per_process - already_open); + max_safe_fds = Min(usable_fds, max_files_per_process); /* * Take off the FDs reserved for system() etc. @@ -1071,9 +1072,10 @@ set_max_safe_fds(void) ereport(FATAL, (errcode(ERRCODE_INSUFFICIENT_RESOURCES), errmsg("insufficient file descriptors available to start server process"), - errdetail("System allows %d, server needs at least %d.", + errdetail("System allows %d, server needs at least %d, %d files are already open.", max_safe_fds + NUM_RESERVED_FDS, - FD_MINFREE + NUM_RESERVED_FDS))); + FD_MINFREE + NUM_RESERVED_FDS, + already_open))); elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d", max_safe_fds, usable_fds, already_open); @@ -1295,6 +1297,8 @@ LruDelete(File file) vfdP = &VfdCache[file]; + pgaio_closing_fd(vfdP->fd); + /* * Close the file. We aren't expecting this to fail; if it does, better * to leak the FD than to mess up our internal state. @@ -1448,7 +1452,7 @@ AllocateVfd(void) */ for (i = SizeVfdCache; i < newCacheSize; i++) { - MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd)); + MemSet(&(VfdCache[i]), 0, sizeof(Vfd)); VfdCache[i].nextFree = i + 1; VfdCache[i].fd = VFD_CLOSED; } @@ -1790,8 +1794,8 @@ TempTablespacePath(char *path, Oid tablespace) else { /* All other tablespaces are accessed via symlinks */ - snprintf(path, MAXPGPATH, "pg_tblspc/%u/%s/%s", - tablespace, TABLESPACE_VERSION_DIRECTORY, + snprintf(path, MAXPGPATH, "%s/%u/%s/%s", + PG_TBLSPC_DIR, tablespace, TABLESPACE_VERSION_DIRECTORY, PG_TEMP_FILES_DIR); } } @@ -1988,6 +1992,8 @@ FileClose(File file) if (!FileIsNotOpen(file)) { + pgaio_closing_fd(vfdP->fd); + /* close the file */ if (close(vfdP->fd) != 0) { @@ -2068,40 +2074,63 @@ FileClose(File file) /* * FilePrefetch - initiate asynchronous read of a given range of the file. * - * Currently the only implementation of this function is using posix_fadvise - * which is the simplest standardized interface that accomplishes this. - * We could add an implementation using libaio in the future; but note that - * this API is inappropriate for libaio, which wants to have a buffer provided - * to read into. + * Returns 0 on success, otherwise an errno error code (like posix_fadvise()). + * + * posix_fadvise() is the simplest standardized interface that accomplishes + * this. */ int FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info) { -#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED) - int returnCode; - Assert(FileIsValid(file)); DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " " INT64_FORMAT, file, VfdCache[file].fileName, (int64) offset, (int64) amount)); - returnCode = FileAccess(file); - if (returnCode < 0) - return returnCode; +#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED) + { + int returnCode; + + returnCode = FileAccess(file); + if (returnCode < 0) + return returnCode; retry: - pgstat_report_wait_start(wait_event_info); - returnCode = posix_fadvise(VfdCache[file].fd, offset, amount, - POSIX_FADV_WILLNEED); - pgstat_report_wait_end(); + pgstat_report_wait_start(wait_event_info); + returnCode = posix_fadvise(VfdCache[file].fd, offset, amount, + POSIX_FADV_WILLNEED); + pgstat_report_wait_end(); - if (returnCode == EINTR) - goto retry; + if (returnCode == EINTR) + goto retry; - return returnCode; + return returnCode; + } +#elif defined(__darwin__) + { + struct radvisory + { + off_t ra_offset; /* offset into the file */ + int ra_count; /* size of the read */ + } ra; + int returnCode; + + returnCode = FileAccess(file); + if (returnCode < 0) + return returnCode; + + ra.ra_offset = offset; + ra.ra_count = amount; + pgstat_report_wait_start(wait_event_info); + returnCode = fcntl(VfdCache[file].fd, F_RDADVISE, &ra); + pgstat_report_wait_end(); + if (returnCode != -1) + return 0; + else + return errno; + } #else - Assert(FileIsValid(file)); return 0; #endif } @@ -2188,6 +2217,32 @@ FileReadV(File file, const struct iovec *iov, int iovcnt, off_t offset, return returnCode; } +int +FileStartReadV(PgAioHandle *ioh, File file, + int iovcnt, off_t offset, + uint32 wait_event_info) +{ + int returnCode; + Vfd *vfdP; + + Assert(FileIsValid(file)); + + DO_DB(elog(LOG, "FileStartReadV: %d (%s) " INT64_FORMAT " %d", + file, VfdCache[file].fileName, + (int64) offset, + iovcnt)); + + returnCode = FileAccess(file); + if (returnCode < 0) + return returnCode; + + vfdP = &VfdCache[file]; + + pgaio_io_start_readv(ioh, vfdP->fd, iovcnt, offset); + + return 0; +} + ssize_t FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset, uint32 wait_event_info) @@ -2231,7 +2286,7 @@ FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset, if (newTotal > (uint64) temp_file_limit * (uint64) 1024) ereport(ERROR, (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), - errmsg("temporary file size exceeds temp_file_limit (%dkB)", + errmsg("temporary file size exceeds \"temp_file_limit\" (%dkB)", temp_file_limit))); } } @@ -2476,6 +2531,12 @@ FilePathName(File file) int FileGetRawDesc(File file) { + int returnCode; + + returnCode = FileAccess(file); + if (returnCode < 0) + return returnCode; + Assert(FileIsValid(file)); return VfdCache[file].fd; } @@ -2756,6 +2817,7 @@ FreeDesc(AllocateDesc *desc) result = closedir(desc->desc.dir); break; case AllocateDescRawFD: + pgaio_closing_fd(desc->desc.fd); result = close(desc->desc.fd); break; default: @@ -2824,6 +2886,8 @@ CloseTransientFile(int fd) /* Only get here if someone passes us a file not in allocatedDescs */ elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile"); + pgaio_closing_fd(fd); + return close(fd); } @@ -3273,7 +3337,7 @@ CleanupTempFiles(bool isCommit, bool isProcExit) void RemovePgTempFiles(void) { - char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)]; + char temp_path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)]; DIR *spc_dir; struct dirent *spc_de; @@ -3287,20 +3351,21 @@ RemovePgTempFiles(void) /* * Cycle through temp directories for all non-default tablespaces. */ - spc_dir = AllocateDir("pg_tblspc"); + spc_dir = AllocateDir(PG_TBLSPC_DIR); - while ((spc_de = ReadDirExtended(spc_dir, "pg_tblspc", LOG)) != NULL) + while ((spc_de = ReadDirExtended(spc_dir, PG_TBLSPC_DIR, LOG)) != NULL) { if (strcmp(spc_de->d_name, ".") == 0 || strcmp(spc_de->d_name, "..") == 0) continue; - snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s", - spc_de->d_name, TABLESPACE_VERSION_DIRECTORY, PG_TEMP_FILES_DIR); + snprintf(temp_path, sizeof(temp_path), "%s/%s/%s/%s", + PG_TBLSPC_DIR, spc_de->d_name, TABLESPACE_VERSION_DIRECTORY, + PG_TEMP_FILES_DIR); RemovePgTempFilesInDir(temp_path, true, false); - snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s", - spc_de->d_name, TABLESPACE_VERSION_DIRECTORY); + snprintf(temp_path, sizeof(temp_path), "%s/%s/%s", + PG_TBLSPC_DIR, spc_de->d_name, TABLESPACE_VERSION_DIRECTORY); RemovePgTempRelationFiles(temp_path); } @@ -3587,15 +3652,15 @@ SyncDataDirectory(void) /* Sync the top level pgdata directory. */ do_syncfs("."); /* If any tablespaces are configured, sync each of those. */ - dir = AllocateDir("pg_tblspc"); - while ((de = ReadDirExtended(dir, "pg_tblspc", LOG))) + dir = AllocateDir(PG_TBLSPC_DIR); + while ((de = ReadDirExtended(dir, PG_TBLSPC_DIR, LOG))) { char path[MAXPGPATH]; if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; - snprintf(path, MAXPGPATH, "pg_tblspc/%s", de->d_name); + snprintf(path, MAXPGPATH, "%s/%s", PG_TBLSPC_DIR, de->d_name); do_syncfs(path); } FreeDir(dir); @@ -3618,7 +3683,7 @@ SyncDataDirectory(void) walkdir(".", pre_sync_fname, false, DEBUG1); if (xlog_is_symlink) walkdir("pg_wal", pre_sync_fname, false, DEBUG1); - walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1); + walkdir(PG_TBLSPC_DIR, pre_sync_fname, true, DEBUG1); #endif /* Prepare to report progress syncing the data directory via fsync. */ @@ -3636,7 +3701,7 @@ SyncDataDirectory(void) walkdir(".", datadir_fsync_fname, false, LOG); if (xlog_is_symlink) walkdir("pg_wal", datadir_fsync_fname, false, LOG); - walkdir("pg_tblspc", datadir_fsync_fname, true, LOG); + walkdir(PG_TBLSPC_DIR, datadir_fsync_fname, true, LOG); } /* @@ -3947,7 +4012,8 @@ check_debug_io_direct(char **newval, void **extra, GucSource source) #if PG_O_DIRECT == 0 if (strcmp(*newval, "") != 0) { - GUC_check_errdetail("\"debug_io_direct\" is not supported on this platform."); + GUC_check_errdetail("\"%s\" is not supported on this platform.", + "debug_io_direct"); result = false; } flags = 0; @@ -3961,7 +4027,7 @@ check_debug_io_direct(char **newval, void **extra, GucSource source) if (!SplitGUCList(rawstring, ',', &elemlist)) { - GUC_check_errdetail("Invalid list syntax in parameter \"%s\"", + GUC_check_errdetail("Invalid list syntax in parameter \"%s\".", "debug_io_direct"); pfree(rawstring); list_free(elemlist); @@ -3981,7 +4047,7 @@ check_debug_io_direct(char **newval, void **extra, GucSource source) flags |= IO_DIRECT_WAL_INIT; else { - GUC_check_errdetail("Invalid option \"%s\"", item); + GUC_check_errdetail("Invalid option \"%s\".", item); result = false; break; } @@ -3994,14 +4060,16 @@ check_debug_io_direct(char **newval, void **extra, GucSource source) #if XLOG_BLCKSZ < PG_IO_ALIGN_SIZE if (result && (flags & (IO_DIRECT_WAL | IO_DIRECT_WAL_INIT))) { - GUC_check_errdetail("\"debug_io_direct\" is not supported for WAL because XLOG_BLCKSZ is too small"); + GUC_check_errdetail("\"%s\" is not supported for WAL because %s is too small.", + "debug_io_direct", "XLOG_BLCKSZ"); result = false; } #endif #if BLCKSZ < PG_IO_ALIGN_SIZE if (result && (flags & IO_DIRECT_DATA)) { - GUC_check_errdetail("\"debug_io_direct\" is not supported for data because BLCKSZ is too small"); + GUC_check_errdetail("\"%s\" is not supported for data because %s is too small.", + "debug_io_direct", "BLCKSZ"); result = false; } #endif @@ -4014,7 +4082,9 @@ check_debug_io_direct(char **newval, void **extra, GucSource source) return result; /* Save the flags in *extra, for use by assign_debug_io_direct */ - *extra = guc_malloc(ERROR, sizeof(int)); + *extra = guc_malloc(LOG, sizeof(int)); + if (!*extra) + return false; *((int *) *extra) = flags; return result; diff --git a/src/backend/storage/file/fileset.c b/src/backend/storage/file/fileset.c index 5746b8f935f9b..64141c7cb91c9 100644 --- a/src/backend/storage/file/fileset.c +++ b/src/backend/storage/file/fileset.c @@ -3,7 +3,7 @@ * fileset.c * Management of named temporary files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/storage/file/meson.build b/src/backend/storage/file/meson.build index 662bb1f4d372c..d1a939a2ad95d 100644 --- a/src/backend/storage/file/meson.build +++ b/src/backend/storage/file/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'buffile.c', diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c index f1cd1a38d95d4..5c8275cf53653 100644 --- a/src/backend/storage/file/reinit.c +++ b/src/backend/storage/file/reinit.c @@ -3,7 +3,7 @@ * reinit.c * Reinitialization of unlogged relations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -46,7 +46,7 @@ typedef struct void ResetUnloggedRelations(int op) { - char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)]; + char temp_path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)]; DIR *spc_dir; struct dirent *spc_de; MemoryContext tmpctx, @@ -77,16 +77,16 @@ ResetUnloggedRelations(int op) /* * Cycle through directories for all non-default tablespaces. */ - spc_dir = AllocateDir("pg_tblspc"); + spc_dir = AllocateDir(PG_TBLSPC_DIR); - while ((spc_de = ReadDir(spc_dir, "pg_tblspc")) != NULL) + while ((spc_de = ReadDir(spc_dir, PG_TBLSPC_DIR)) != NULL) { if (strcmp(spc_de->d_name, ".") == 0 || strcmp(spc_de->d_name, "..") == 0) continue; - snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s", - spc_de->d_name, TABLESPACE_VERSION_DIRECTORY); + snprintf(temp_path, sizeof(temp_path), "%s/%s/%s", + PG_TBLSPC_DIR, spc_de->d_name, TABLESPACE_VERSION_DIRECTORY); ResetUnloggedRelationsInTablespaceDir(temp_path, op); } diff --git a/src/backend/storage/file/sharedfileset.c b/src/backend/storage/file/sharedfileset.c index 00bdbc726071f..43e4c72aab3ae 100644 --- a/src/backend/storage/file/sharedfileset.c +++ b/src/backend/storage/file/sharedfileset.c @@ -3,7 +3,7 @@ * sharedfileset.c * Shared temporary file management. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index b1262ac3b69dd..4773a9cc65e6c 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -4,7 +4,7 @@ * POSTGRES free space map for quickly finding free space in relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/storage/freespace/fsmpage.c b/src/backend/storage/freespace/fsmpage.c index ba85cad0697f5..66a5c80b5a6c6 100644 --- a/src/backend/storage/freespace/fsmpage.c +++ b/src/backend/storage/freespace/fsmpage.c @@ -4,7 +4,7 @@ * routines to search and manipulate one FSM page. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/storage/freespace/indexfsm.c b/src/backend/storage/freespace/indexfsm.c index 35fb41ea7d604..614261e4e22fc 100644 --- a/src/backend/storage/freespace/indexfsm.c +++ b/src/backend/storage/freespace/indexfsm.c @@ -4,7 +4,7 @@ * POSTGRES free space map for quickly finding free pages in relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -16,7 +16,7 @@ * This is similar to the FSM used for heap, in freespace.c, but instead * of tracking the amount of free space on pages, we only track whether * pages are completely free or in-use. We use the same FSM implementation - * as for heaps, using BLCKSZ - 1 to denote used pages, and 0 for unused. + * as for heaps, using 0 to denote used pages, and (BLCKSZ - 1) for unused. * *------------------------------------------------------------------------- */ diff --git a/src/backend/storage/freespace/meson.build b/src/backend/storage/freespace/meson.build index db1c33a82886d..16cfae0e5dd0a 100644 --- a/src/backend/storage/freespace/meson.build +++ b/src/backend/storage/freespace/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'freespace.c', diff --git a/src/backend/storage/ipc/Makefile b/src/backend/storage/ipc/Makefile index d8a1653eb6a62..9a07f6e1d92ab 100644 --- a/src/backend/storage/ipc/Makefile +++ b/src/backend/storage/ipc/Makefile @@ -25,6 +25,7 @@ OBJS = \ signalfuncs.o \ sinval.o \ sinvaladt.o \ - standby.o + standby.o \ + waiteventset.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/storage/ipc/barrier.c b/src/backend/storage/ipc/barrier.c index 5b52e060bae9e..cb99c5f06b042 100644 --- a/src/backend/storage/ipc/barrier.c +++ b/src/backend/storage/ipc/barrier.c @@ -3,7 +3,7 @@ * barrier.c * Barriers for synchronizing cooperating processes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * From Wikipedia[1]: "In parallel computing, a barrier is a type of diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index c2e33a7e43305..f92a52a00e68d 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -14,7 +14,7 @@ * hard postmaster crash, remaining segments will be removed, if they * still exist, at the next postmaster startup. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 8dd669e0ce943..6bf8ab5bb5b5e 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -36,7 +36,7 @@ * * As ever, Windows requires its own implementation. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c index 9f58ea611b913..1d4fd31ffedbc 100644 --- a/src/backend/storage/ipc/dsm_registry.c +++ b/src/backend/storage/ipc/dsm_registry.c @@ -15,7 +15,7 @@ * current backend. This function guarantees that only one backend * initializes the segment and that all other backends just attach it. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c index b06e4b845288e..567739b5be93a 100644 --- a/src/backend/storage/ipc/ipc.c +++ b/src/backend/storage/ipc/ipc.c @@ -8,7 +8,7 @@ * exit-time cleanup for either a postmaster or a backend. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -399,8 +399,8 @@ cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg) before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg) --before_shmem_exit_index; else - elog(ERROR, "before_shmem_exit callback (%p,0x%llx) is not the latest entry", - function, (long long) arg); + elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIxPTR ") is not the latest entry", + function, arg); } /* ---------------------------------------------------------------- diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index ca930af08f2dc..2fa045e6b0f66 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -3,7 +3,7 @@ * ipci.c * POSTGRES inter-process communication initialization code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -30,7 +30,6 @@ #include "postmaster/autovacuum.h" #include "postmaster/bgworker_internals.h" #include "postmaster/bgwriter.h" -#include "postmaster/postmaster.h" #include "postmaster/walsummarizer.h" #include "replication/logicallauncher.h" #include "replication/origin.h" @@ -38,6 +37,7 @@ #include "replication/slotsync.h" #include "replication/walreceiver.h" #include "replication/walsender.h" +#include "storage/aio_subsys.h" #include "storage/bufmgr.h" #include "storage/dsm.h" #include "storage/dsm_registry.h" @@ -49,7 +49,6 @@ #include "storage/procarray.h" #include "storage/procsignal.h" #include "storage/sinvaladt.h" -#include "storage/spin.h" #include "utils/guc.h" #include "utils/injection_point.h" @@ -94,7 +93,6 @@ CalculateShmemSize(int *num_semaphores) /* Compute number of semaphores we'll need */ numSemas = ProcGlobalSemas(); - numSemas += SpinlockSemas(); /* Return the number of semaphores if requested by the caller */ if (num_semaphores) @@ -111,13 +109,12 @@ CalculateShmemSize(int *num_semaphores) */ size = 100000; size = add_size(size, PGSemaphoreShmemSize(numSemas)); - size = add_size(size, SpinlockSemaSize()); size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE, sizeof(ShmemIndexEnt))); size = add_size(size, dsm_estimate_size()); size = add_size(size, DSMRegistryShmemSize()); - size = add_size(size, BufferShmemSize()); - size = add_size(size, LockShmemSize()); + size = add_size(size, BufferManagerShmemSize()); + size = add_size(size, LockManagerShmemSize()); size = add_size(size, PredicateLockShmemSize()); size = add_size(size, ProcGlobalShmemSize()); size = add_size(size, XLogPrefetchShmemSize()); @@ -133,7 +130,7 @@ CalculateShmemSize(int *num_semaphores) size = add_size(size, LWLockShmemSize()); size = add_size(size, ProcArrayShmemSize()); size = add_size(size, BackendStatusShmemSize()); - size = add_size(size, SInvalShmemSize()); + size = add_size(size, SharedInvalShmemSize()); size = add_size(size, PMSignalShmemSize()); size = add_size(size, ProcSignalShmemSize()); size = add_size(size, CheckpointerShmemSize()); @@ -152,9 +149,7 @@ CalculateShmemSize(int *num_semaphores) size = add_size(size, WaitEventCustomShmemSize()); size = add_size(size, InjectionPointShmemSize()); size = add_size(size, SlotSyncShmemSize()); -#ifdef EXEC_BACKEND - size = add_size(size, ShmemBackendArraySize()); -#endif + size = add_size(size, AioShmemSize()); /* include additional requested shmem from preload libraries */ size = add_size(size, total_addin_request); @@ -181,6 +176,12 @@ AttachSharedMemoryStructs(void) Assert(MyProc != NULL); Assert(IsUnderPostmaster); + /* + * In EXEC_BACKEND mode, backends don't inherit the number of fast-path + * groups we calculated before setting the shmem up, so recalculate it. + */ + InitializeFastPathLocks(); + CreateOrAttachShmemStructs(); /* @@ -228,14 +229,6 @@ CreateSharedMemoryAndSemaphores(void) */ PGReserveSemaphores(numSemas); - /* - * If spinlocks are disabled, initialize emulation layer (which depends on - * semaphores, so the order is important here). - */ -#ifndef HAVE_SPINLOCKS - SpinlockSemaInit(); -#endif - /* * Set up shared memory allocation mechanism */ @@ -244,14 +237,6 @@ CreateSharedMemoryAndSemaphores(void) /* Initialize subsystems */ CreateOrAttachShmemStructs(); -#ifdef EXEC_BACKEND - - /* - * Alloc the win32 shared backend array - */ - ShmemBackendArrayAllocation(); -#endif - /* Initialize dynamic shared memory facilities. */ dsm_postmaster_startup(shim); @@ -305,32 +290,32 @@ CreateOrAttachShmemStructs(void) CommitTsShmemInit(); SUBTRANSShmemInit(); MultiXactShmemInit(); - InitBufferPool(); + BufferManagerShmemInit(); /* * Set up lock manager */ - InitLocks(); + LockManagerShmemInit(); /* * Set up predicate lock manager */ - InitPredicateLocks(); + PredicateLockShmemInit(); /* * Set up process table */ if (!IsUnderPostmaster) InitProcGlobal(); - CreateSharedProcArray(); - CreateSharedBackendStatus(); + ProcArrayShmemInit(); + BackendStatusShmemInit(); TwoPhaseShmemInit(); BackgroundWorkerShmemInit(); /* * Set up shared-inval messaging */ - CreateSharedInvalidationState(); + SharedInvalShmemInit(); /* * Set up interprocess signaling mechanisms @@ -357,6 +342,7 @@ CreateOrAttachShmemStructs(void) StatsShmemInit(); WaitEventCustomShmemInit(); InjectionPointShmemInit(); + AioShmemInit(); } /* diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index 608eb66abedf3..c6aefd2f688dd 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -3,27 +3,12 @@ * latch.c * Routines for inter-process latches * - * The poll() implementation uses the so-called self-pipe trick to overcome the - * race condition involved with poll() and setting a global flag in the signal - * handler. When a latch is set and the current process is waiting for it, the - * signal handler wakes up the poll() in WaitLatch by writing a byte to a pipe. - * A signal by itself doesn't interrupt poll() on all platforms, and even on - * platforms where it does, a signal that arrives just before the poll() call - * does not prevent poll() from entering sleep. An incoming byte on a pipe - * however reliably interrupts the sleep, and causes poll() to return - * immediately even if the signal arrives before poll() begins. + * The latch interface is a reliable replacement for the common pattern of + * using pg_usleep() or select() to wait until a signal arrives, where the + * signal handler sets a flag variable. See latch.h for more information + * on how to use them. * - * The epoll() implementation overcomes the race with a different technique: it - * keeps SIGURG blocked and consumes from a signalfd() descriptor instead. We - * don't need to register a signal handler or create our own self-pipe. We - * assume that any system that has Linux epoll() also has Linux signalfd(). - * - * The kqueue() implementation waits for SIGURG with EVFILT_SIGNAL. - * - * The Windows implementation uses Windows events that are inherited by all - * postmaster child processes. There's no need for the self-pipe trick there. - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -33,314 +18,18 @@ */ #include "postgres.h" -#include -#include -#include -#include -#ifdef HAVE_SYS_EPOLL_H -#include -#endif -#ifdef HAVE_SYS_EVENT_H -#include -#endif -#ifdef HAVE_SYS_SIGNALFD_H -#include -#endif -#ifdef HAVE_POLL_H -#include -#endif - -#include "libpq/pqsignal.h" #include "miscadmin.h" -#include "pgstat.h" #include "port/atomics.h" -#include "portability/instr_time.h" -#include "postmaster/postmaster.h" -#include "storage/fd.h" -#include "storage/ipc.h" #include "storage/latch.h" -#include "storage/pmsignal.h" -#include "utils/memutils.h" +#include "storage/waiteventset.h" #include "utils/resowner.h" -/* - * Select the fd readiness primitive to use. Normally the "most modern" - * primitive supported by the OS will be used, but for testing it can be - * useful to manually specify the used primitive. If desired, just add a - * define somewhere before this block. - */ -#if defined(WAIT_USE_EPOLL) || defined(WAIT_USE_POLL) || \ - defined(WAIT_USE_KQUEUE) || defined(WAIT_USE_WIN32) -/* don't overwrite manual choice */ -#elif defined(HAVE_SYS_EPOLL_H) -#define WAIT_USE_EPOLL -#elif defined(HAVE_KQUEUE) -#define WAIT_USE_KQUEUE -#elif defined(HAVE_POLL) -#define WAIT_USE_POLL -#elif WIN32 -#define WAIT_USE_WIN32 -#else -#error "no wait set implementation available" -#endif - -/* - * By default, we use a self-pipe with poll() and a signalfd with epoll(), if - * available. For testing the choice can also be manually specified. - */ -#if defined(WAIT_USE_POLL) || defined(WAIT_USE_EPOLL) -#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) -/* don't overwrite manual choice */ -#elif defined(WAIT_USE_EPOLL) && defined(HAVE_SYS_SIGNALFD_H) -#define WAIT_USE_SIGNALFD -#else -#define WAIT_USE_SELF_PIPE -#endif -#endif - -/* typedef in latch.h */ -struct WaitEventSet -{ - ResourceOwner owner; - - int nevents; /* number of registered events */ - int nevents_space; /* maximum number of events in this set */ - - /* - * Array, of nevents_space length, storing the definition of events this - * set is waiting for. - */ - WaitEvent *events; - - /* - * If WL_LATCH_SET is specified in any wait event, latch is a pointer to - * said latch, and latch_pos the offset in the ->events array. This is - * useful because we check the state of the latch before performing doing - * syscalls related to waiting. - */ - Latch *latch; - int latch_pos; - - /* - * WL_EXIT_ON_PM_DEATH is converted to WL_POSTMASTER_DEATH, but this flag - * is set so that we'll exit immediately if postmaster death is detected, - * instead of returning. - */ - bool exit_on_postmaster_death; - -#if defined(WAIT_USE_EPOLL) - int epoll_fd; - /* epoll_wait returns events in a user provided arrays, allocate once */ - struct epoll_event *epoll_ret_events; -#elif defined(WAIT_USE_KQUEUE) - int kqueue_fd; - /* kevent returns events in a user provided arrays, allocate once */ - struct kevent *kqueue_ret_events; - bool report_postmaster_not_running; -#elif defined(WAIT_USE_POLL) - /* poll expects events to be waited on every poll() call, prepare once */ - struct pollfd *pollfds; -#elif defined(WAIT_USE_WIN32) - - /* - * Array of windows events. The first element always contains - * pgwin32_signal_event, so the remaining elements are offset by one (i.e. - * event->pos + 1). - */ - HANDLE *handles; -#endif -}; - /* A common WaitEventSet used to implement WaitLatch() */ static WaitEventSet *LatchWaitSet; -/* The position of the latch in LatchWaitSet. */ +/* The positions of the latch and PM death events in LatchWaitSet */ #define LatchWaitSetLatchPos 0 - -#ifndef WIN32 -/* Are we currently in WaitLatch? The signal handler would like to know. */ -static volatile sig_atomic_t waiting = false; -#endif - -#ifdef WAIT_USE_SIGNALFD -/* On Linux, we'll receive SIGURG via a signalfd file descriptor. */ -static int signal_fd = -1; -#endif - -#ifdef WAIT_USE_SELF_PIPE -/* Read and write ends of the self-pipe */ -static int selfpipe_readfd = -1; -static int selfpipe_writefd = -1; - -/* Process owning the self-pipe --- needed for checking purposes */ -static int selfpipe_owner_pid = 0; - -/* Private function prototypes */ -static void latch_sigurg_handler(SIGNAL_ARGS); -static void sendSelfPipeByte(void); -#endif - -#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) -static void drain(void); -#endif - -#if defined(WAIT_USE_EPOLL) -static void WaitEventAdjustEpoll(WaitEventSet *set, WaitEvent *event, int action); -#elif defined(WAIT_USE_KQUEUE) -static void WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events); -#elif defined(WAIT_USE_POLL) -static void WaitEventAdjustPoll(WaitEventSet *set, WaitEvent *event); -#elif defined(WAIT_USE_WIN32) -static void WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event); -#endif - -static inline int WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, - WaitEvent *occurred_events, int nevents); - -/* ResourceOwner support to hold WaitEventSets */ -static void ResOwnerReleaseWaitEventSet(Datum res); - -static const ResourceOwnerDesc wait_event_set_resowner_desc = -{ - .name = "WaitEventSet", - .release_phase = RESOURCE_RELEASE_AFTER_LOCKS, - .release_priority = RELEASE_PRIO_WAITEVENTSETS, - .ReleaseResource = ResOwnerReleaseWaitEventSet, - .DebugPrint = NULL -}; - -/* Convenience wrappers over ResourceOwnerRemember/Forget */ -static inline void -ResourceOwnerRememberWaitEventSet(ResourceOwner owner, WaitEventSet *set) -{ - ResourceOwnerRemember(owner, PointerGetDatum(set), &wait_event_set_resowner_desc); -} -static inline void -ResourceOwnerForgetWaitEventSet(ResourceOwner owner, WaitEventSet *set) -{ - ResourceOwnerForget(owner, PointerGetDatum(set), &wait_event_set_resowner_desc); -} - - -/* - * Initialize the process-local latch infrastructure. - * - * This must be called once during startup of any process that can wait on - * latches, before it issues any InitLatch() or OwnLatch() calls. - */ -void -InitializeLatchSupport(void) -{ -#if defined(WAIT_USE_SELF_PIPE) - int pipefd[2]; - - if (IsUnderPostmaster) - { - /* - * We might have inherited connections to a self-pipe created by the - * postmaster. It's critical that child processes create their own - * self-pipes, of course, and we really want them to close the - * inherited FDs for safety's sake. - */ - if (selfpipe_owner_pid != 0) - { - /* Assert we go through here but once in a child process */ - Assert(selfpipe_owner_pid != MyProcPid); - /* Release postmaster's pipe FDs; ignore any error */ - (void) close(selfpipe_readfd); - (void) close(selfpipe_writefd); - /* Clean up, just for safety's sake; we'll set these below */ - selfpipe_readfd = selfpipe_writefd = -1; - selfpipe_owner_pid = 0; - /* Keep fd.c's accounting straight */ - ReleaseExternalFD(); - ReleaseExternalFD(); - } - else - { - /* - * Postmaster didn't create a self-pipe ... or else we're in an - * EXEC_BACKEND build, in which case it doesn't matter since the - * postmaster's pipe FDs were closed by the action of FD_CLOEXEC. - * fd.c won't have state to clean up, either. - */ - Assert(selfpipe_readfd == -1); - } - } - else - { - /* In postmaster or standalone backend, assert we do this but once */ - Assert(selfpipe_readfd == -1); - Assert(selfpipe_owner_pid == 0); - } - - /* - * Set up the self-pipe that allows a signal handler to wake up the - * poll()/epoll_wait() in WaitLatch. Make the write-end non-blocking, so - * that SetLatch won't block if the event has already been set many times - * filling the kernel buffer. Make the read-end non-blocking too, so that - * we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK. - * Also, make both FDs close-on-exec, since we surely do not want any - * child processes messing with them. - */ - if (pipe(pipefd) < 0) - elog(FATAL, "pipe() failed: %m"); - if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) - elog(FATAL, "fcntl(F_SETFL) failed on read-end of self-pipe: %m"); - if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) == -1) - elog(FATAL, "fcntl(F_SETFL) failed on write-end of self-pipe: %m"); - if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1) - elog(FATAL, "fcntl(F_SETFD) failed on read-end of self-pipe: %m"); - if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1) - elog(FATAL, "fcntl(F_SETFD) failed on write-end of self-pipe: %m"); - - selfpipe_readfd = pipefd[0]; - selfpipe_writefd = pipefd[1]; - selfpipe_owner_pid = MyProcPid; - - /* Tell fd.c about these two long-lived FDs */ - ReserveExternalFD(); - ReserveExternalFD(); - - pqsignal(SIGURG, latch_sigurg_handler); -#endif - -#ifdef WAIT_USE_SIGNALFD - sigset_t signalfd_mask; - - if (IsUnderPostmaster) - { - /* - * It would probably be safe to re-use the inherited signalfd since - * signalfds only see the current process's pending signals, but it - * seems less surprising to close it and create our own. - */ - if (signal_fd != -1) - { - /* Release postmaster's signal FD; ignore any error */ - (void) close(signal_fd); - signal_fd = -1; - ReleaseExternalFD(); - } - } - - /* Block SIGURG, because we'll receive it through a signalfd. */ - sigaddset(&UnBlockSig, SIGURG); - - /* Set up the signalfd to receive SIGURG notifications. */ - sigemptyset(&signalfd_mask); - sigaddset(&signalfd_mask, SIGURG); - signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (signal_fd < 0) - elog(FATAL, "signalfd() failed"); - ReserveExternalFD(); -#endif - -#ifdef WAIT_USE_KQUEUE - /* Ignore SIGURG, because we'll receive it via kqueue. */ - pqsignal(SIGURG, SIG_IGN); -#endif -} +#define LatchWaitSetPostmasterDeathPos 1 void InitializeLatchWaitSet(void) @@ -353,38 +42,18 @@ InitializeLatchWaitSet(void) LatchWaitSet = CreateWaitEventSet(NULL, 2); latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET, MyLatch, NULL); - if (IsUnderPostmaster) - AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH, - PGINVALID_SOCKET, NULL, NULL); - Assert(latch_pos == LatchWaitSetLatchPos); -} - -void -ShutdownLatchSupport(void) -{ -#if defined(WAIT_USE_POLL) - pqsignal(SIGURG, SIG_IGN); -#endif - if (LatchWaitSet) + /* + * WaitLatch will modify this to WL_EXIT_ON_PM_DEATH or + * WL_POSTMASTER_DEATH on each call. + */ + if (IsUnderPostmaster) { - FreeWaitEventSet(LatchWaitSet); - LatchWaitSet = NULL; + latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH, + PGINVALID_SOCKET, NULL, NULL); + Assert(latch_pos == LatchWaitSetPostmasterDeathPos); } - -#if defined(WAIT_USE_SELF_PIPE) - close(selfpipe_readfd); - close(selfpipe_writefd); - selfpipe_readfd = -1; - selfpipe_writefd = -1; - selfpipe_owner_pid = InvalidPid; -#endif - -#if defined(WAIT_USE_SIGNALFD) - close(signal_fd); - signal_fd = -1; -#endif } /* @@ -398,13 +67,7 @@ InitLatch(Latch *latch) latch->owner_pid = MyProcPid; latch->is_shared = false; -#if defined(WAIT_USE_SELF_PIPE) - /* Assert InitializeLatchSupport has been called in this process */ - Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid); -#elif defined(WAIT_USE_SIGNALFD) - /* Assert InitializeLatchSupport has been called in this process */ - Assert(signal_fd >= 0); -#elif defined(WAIT_USE_WIN32) +#ifdef WIN32 latch->event = CreateEvent(NULL, TRUE, FALSE, NULL); if (latch->event == NULL) elog(ERROR, "CreateEvent failed: error code %lu", GetLastError()); @@ -467,14 +130,6 @@ OwnLatch(Latch *latch) /* Sanity checks */ Assert(latch->is_shared); -#if defined(WAIT_USE_SELF_PIPE) - /* Assert InitializeLatchSupport has been called in this process */ - Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid); -#elif defined(WAIT_USE_SIGNALFD) - /* Assert InitializeLatchSupport has been called in this process */ - Assert(signal_fd >= 0); -#endif - owner_pid = latch->owner_pid; if (owner_pid != 0) elog(PANIC, "latch already owned by PID %d", owner_pid); @@ -532,8 +187,9 @@ WaitLatch(Latch *latch, int wakeEvents, long timeout, if (!(wakeEvents & WL_LATCH_SET)) latch = NULL; ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch); - LatchWaitSet->exit_on_postmaster_death = - ((wakeEvents & WL_EXIT_ON_PM_DEATH) != 0); + ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos, + (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)), + NULL); if (WaitEventSetWait(LatchWaitSet, (wakeEvents & WL_TIMEOUT) ? timeout : -1, @@ -682,17 +338,9 @@ SetLatch(Latch *latch) if (owner_pid == 0) return; else if (owner_pid == MyProcPid) - { -#if defined(WAIT_USE_SELF_PIPE) - if (waiting) - sendSelfPipeByte(); -#else - if (waiting) - kill(MyProcPid, SIGURG); -#endif - } + WakeupMyProc(); else - kill(owner_pid, SIGURG); + WakeupOtherProc(owner_pid); #else @@ -737,1647 +385,3 @@ ResetLatch(Latch *latch) */ pg_memory_barrier(); } - -/* - * Create a WaitEventSet with space for nevents different events to wait for. - * - * These events can then be efficiently waited upon together, using - * WaitEventSetWait(). - * - * The WaitEventSet is tracked by the given 'resowner'. Use NULL for session - * lifetime. - */ -WaitEventSet * -CreateWaitEventSet(ResourceOwner resowner, int nevents) -{ - WaitEventSet *set; - char *data; - Size sz = 0; - - /* - * Use MAXALIGN size/alignment to guarantee that later uses of memory are - * aligned correctly. E.g. epoll_event might need 8 byte alignment on some - * platforms, but earlier allocations like WaitEventSet and WaitEvent - * might not be sized to guarantee that when purely using sizeof(). - */ - sz += MAXALIGN(sizeof(WaitEventSet)); - sz += MAXALIGN(sizeof(WaitEvent) * nevents); - -#if defined(WAIT_USE_EPOLL) - sz += MAXALIGN(sizeof(struct epoll_event) * nevents); -#elif defined(WAIT_USE_KQUEUE) - sz += MAXALIGN(sizeof(struct kevent) * nevents); -#elif defined(WAIT_USE_POLL) - sz += MAXALIGN(sizeof(struct pollfd) * nevents); -#elif defined(WAIT_USE_WIN32) - /* need space for the pgwin32_signal_event */ - sz += MAXALIGN(sizeof(HANDLE) * (nevents + 1)); -#endif - - if (resowner != NULL) - ResourceOwnerEnlarge(resowner); - - data = (char *) MemoryContextAllocZero(TopMemoryContext, sz); - - set = (WaitEventSet *) data; - data += MAXALIGN(sizeof(WaitEventSet)); - - set->events = (WaitEvent *) data; - data += MAXALIGN(sizeof(WaitEvent) * nevents); - -#if defined(WAIT_USE_EPOLL) - set->epoll_ret_events = (struct epoll_event *) data; - data += MAXALIGN(sizeof(struct epoll_event) * nevents); -#elif defined(WAIT_USE_KQUEUE) - set->kqueue_ret_events = (struct kevent *) data; - data += MAXALIGN(sizeof(struct kevent) * nevents); -#elif defined(WAIT_USE_POLL) - set->pollfds = (struct pollfd *) data; - data += MAXALIGN(sizeof(struct pollfd) * nevents); -#elif defined(WAIT_USE_WIN32) - set->handles = (HANDLE) data; - data += MAXALIGN(sizeof(HANDLE) * nevents); -#endif - - set->latch = NULL; - set->nevents_space = nevents; - set->exit_on_postmaster_death = false; - - if (resowner != NULL) - { - ResourceOwnerRememberWaitEventSet(resowner, set); - set->owner = resowner; - } - -#if defined(WAIT_USE_EPOLL) - if (!AcquireExternalFD()) - { - /* treat this as though epoll_create1 itself returned EMFILE */ - elog(ERROR, "epoll_create1 failed: %m"); - } - set->epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (set->epoll_fd < 0) - { - ReleaseExternalFD(); - elog(ERROR, "epoll_create1 failed: %m"); - } -#elif defined(WAIT_USE_KQUEUE) - if (!AcquireExternalFD()) - { - /* treat this as though kqueue itself returned EMFILE */ - elog(ERROR, "kqueue failed: %m"); - } - set->kqueue_fd = kqueue(); - if (set->kqueue_fd < 0) - { - ReleaseExternalFD(); - elog(ERROR, "kqueue failed: %m"); - } - if (fcntl(set->kqueue_fd, F_SETFD, FD_CLOEXEC) == -1) - { - int save_errno = errno; - - close(set->kqueue_fd); - ReleaseExternalFD(); - errno = save_errno; - elog(ERROR, "fcntl(F_SETFD) failed on kqueue descriptor: %m"); - } - set->report_postmaster_not_running = false; -#elif defined(WAIT_USE_WIN32) - - /* - * To handle signals while waiting, we need to add a win32 specific event. - * We accounted for the additional event at the top of this routine. See - * port/win32/signal.c for more details. - * - * Note: pgwin32_signal_event should be first to ensure that it will be - * reported when multiple events are set. We want to guarantee that - * pending signals are serviced. - */ - set->handles[0] = pgwin32_signal_event; - StaticAssertStmt(WSA_INVALID_EVENT == NULL, ""); -#endif - - return set; -} - -/* - * Free a previously created WaitEventSet. - * - * Note: preferably, this shouldn't have to free any resources that could be - * inherited across an exec(). If it did, we'd likely leak those resources in - * many scenarios. For the epoll case, we ensure that by setting EPOLL_CLOEXEC - * when the FD is created. For the Windows case, we assume that the handles - * involved are non-inheritable. - */ -void -FreeWaitEventSet(WaitEventSet *set) -{ - if (set->owner) - { - ResourceOwnerForgetWaitEventSet(set->owner, set); - set->owner = NULL; - } - -#if defined(WAIT_USE_EPOLL) - close(set->epoll_fd); - ReleaseExternalFD(); -#elif defined(WAIT_USE_KQUEUE) - close(set->kqueue_fd); - ReleaseExternalFD(); -#elif defined(WAIT_USE_WIN32) - for (WaitEvent *cur_event = set->events; - cur_event < (set->events + set->nevents); - cur_event++) - { - if (cur_event->events & WL_LATCH_SET) - { - /* uses the latch's HANDLE */ - } - else if (cur_event->events & WL_POSTMASTER_DEATH) - { - /* uses PostmasterHandle */ - } - else - { - /* Clean up the event object we created for the socket */ - WSAEventSelect(cur_event->fd, NULL, 0); - WSACloseEvent(set->handles[cur_event->pos + 1]); - } - } -#endif - - pfree(set); -} - -/* - * Free a previously created WaitEventSet in a child process after a fork(). - */ -void -FreeWaitEventSetAfterFork(WaitEventSet *set) -{ -#if defined(WAIT_USE_EPOLL) - close(set->epoll_fd); - ReleaseExternalFD(); -#elif defined(WAIT_USE_KQUEUE) - /* kqueues are not normally inherited by child processes */ - ReleaseExternalFD(); -#endif - - pfree(set); -} - -/* --- - * Add an event to the set. Possible events are: - * - WL_LATCH_SET: Wait for the latch to be set - * - WL_POSTMASTER_DEATH: Wait for postmaster to die - * - WL_SOCKET_READABLE: Wait for socket to become readable, - * can be combined in one event with other WL_SOCKET_* events - * - WL_SOCKET_WRITEABLE: Wait for socket to become writeable, - * can be combined with other WL_SOCKET_* events - * - WL_SOCKET_CONNECTED: Wait for socket connection to be established, - * can be combined with other WL_SOCKET_* events (on non-Windows - * platforms, this is the same as WL_SOCKET_WRITEABLE) - * - WL_SOCKET_ACCEPT: Wait for new connection to a server socket, - * can be combined with other WL_SOCKET_* events (on non-Windows - * platforms, this is the same as WL_SOCKET_READABLE) - * - WL_SOCKET_CLOSED: Wait for socket to be closed by remote peer. - * - WL_EXIT_ON_PM_DEATH: Exit immediately if the postmaster dies - * - * Returns the offset in WaitEventSet->events (starting from 0), which can be - * used to modify previously added wait events using ModifyWaitEvent(). - * - * In the WL_LATCH_SET case the latch must be owned by the current process, - * i.e. it must be a process-local latch initialized with InitLatch, or a - * shared latch associated with the current process by calling OwnLatch. - * - * In the WL_SOCKET_READABLE/WRITEABLE/CONNECTED/ACCEPT cases, EOF and error - * conditions cause the socket to be reported as readable/writable/connected, - * so that the caller can deal with the condition. - * - * The user_data pointer specified here will be set for the events returned - * by WaitEventSetWait(), allowing to easily associate additional data with - * events. - */ -int -AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, - void *user_data) -{ - WaitEvent *event; - - /* not enough space */ - Assert(set->nevents < set->nevents_space); - - if (events == WL_EXIT_ON_PM_DEATH) - { - events = WL_POSTMASTER_DEATH; - set->exit_on_postmaster_death = true; - } - - if (latch) - { - if (latch->owner_pid != MyProcPid) - elog(ERROR, "cannot wait on a latch owned by another process"); - if (set->latch) - elog(ERROR, "cannot wait on more than one latch"); - if ((events & WL_LATCH_SET) != WL_LATCH_SET) - elog(ERROR, "latch events only support being set"); - } - else - { - if (events & WL_LATCH_SET) - elog(ERROR, "cannot wait on latch without a specified latch"); - } - - /* waiting for socket readiness without a socket indicates a bug */ - if (fd == PGINVALID_SOCKET && (events & WL_SOCKET_MASK)) - elog(ERROR, "cannot wait on socket event without a socket"); - - event = &set->events[set->nevents]; - event->pos = set->nevents++; - event->fd = fd; - event->events = events; - event->user_data = user_data; -#ifdef WIN32 - event->reset = false; -#endif - - if (events == WL_LATCH_SET) - { - set->latch = latch; - set->latch_pos = event->pos; -#if defined(WAIT_USE_SELF_PIPE) - event->fd = selfpipe_readfd; -#elif defined(WAIT_USE_SIGNALFD) - event->fd = signal_fd; -#else - event->fd = PGINVALID_SOCKET; -#ifdef WAIT_USE_EPOLL - return event->pos; -#endif -#endif - } - else if (events == WL_POSTMASTER_DEATH) - { -#ifndef WIN32 - event->fd = postmaster_alive_fds[POSTMASTER_FD_WATCH]; -#endif - } - - /* perform wait primitive specific initialization, if needed */ -#if defined(WAIT_USE_EPOLL) - WaitEventAdjustEpoll(set, event, EPOLL_CTL_ADD); -#elif defined(WAIT_USE_KQUEUE) - WaitEventAdjustKqueue(set, event, 0); -#elif defined(WAIT_USE_POLL) - WaitEventAdjustPoll(set, event); -#elif defined(WAIT_USE_WIN32) - WaitEventAdjustWin32(set, event); -#endif - - return event->pos; -} - -/* - * Change the event mask and, in the WL_LATCH_SET case, the latch associated - * with the WaitEvent. The latch may be changed to NULL to disable the latch - * temporarily, and then set back to a latch later. - * - * 'pos' is the id returned by AddWaitEventToSet. - */ -void -ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch) -{ - WaitEvent *event; -#if defined(WAIT_USE_KQUEUE) - int old_events; -#endif - - Assert(pos < set->nevents); - - event = &set->events[pos]; -#if defined(WAIT_USE_KQUEUE) - old_events = event->events; -#endif - - /* - * If neither the event mask nor the associated latch changes, return - * early. That's an important optimization for some sockets, where - * ModifyWaitEvent is frequently used to switch from waiting for reads to - * waiting on writes. - */ - if (events == event->events && - (!(event->events & WL_LATCH_SET) || set->latch == latch)) - return; - - if (event->events & WL_LATCH_SET && - events != event->events) - { - elog(ERROR, "cannot modify latch event"); - } - - if (event->events & WL_POSTMASTER_DEATH) - { - elog(ERROR, "cannot modify postmaster death event"); - } - - /* FIXME: validate event mask */ - event->events = events; - - if (events == WL_LATCH_SET) - { - if (latch && latch->owner_pid != MyProcPid) - elog(ERROR, "cannot wait on a latch owned by another process"); - set->latch = latch; - - /* - * On Unix, we don't need to modify the kernel object because the - * underlying pipe (if there is one) is the same for all latches so we - * can return immediately. On Windows, we need to update our array of - * handles, but we leave the old one in place and tolerate spurious - * wakeups if the latch is disabled. - */ -#if defined(WAIT_USE_WIN32) - if (!latch) - return; -#else - return; -#endif - } - -#if defined(WAIT_USE_EPOLL) - WaitEventAdjustEpoll(set, event, EPOLL_CTL_MOD); -#elif defined(WAIT_USE_KQUEUE) - WaitEventAdjustKqueue(set, event, old_events); -#elif defined(WAIT_USE_POLL) - WaitEventAdjustPoll(set, event); -#elif defined(WAIT_USE_WIN32) - WaitEventAdjustWin32(set, event); -#endif -} - -#if defined(WAIT_USE_EPOLL) -/* - * action can be one of EPOLL_CTL_ADD | EPOLL_CTL_MOD | EPOLL_CTL_DEL - */ -static void -WaitEventAdjustEpoll(WaitEventSet *set, WaitEvent *event, int action) -{ - struct epoll_event epoll_ev; - int rc; - - /* pointer to our event, returned by epoll_wait */ - epoll_ev.data.ptr = event; - /* always wait for errors */ - epoll_ev.events = EPOLLERR | EPOLLHUP; - - /* prepare pollfd entry once */ - if (event->events == WL_LATCH_SET) - { - Assert(set->latch != NULL); - epoll_ev.events |= EPOLLIN; - } - else if (event->events == WL_POSTMASTER_DEATH) - { - epoll_ev.events |= EPOLLIN; - } - else - { - Assert(event->fd != PGINVALID_SOCKET); - Assert(event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED)); - - if (event->events & WL_SOCKET_READABLE) - epoll_ev.events |= EPOLLIN; - if (event->events & WL_SOCKET_WRITEABLE) - epoll_ev.events |= EPOLLOUT; - if (event->events & WL_SOCKET_CLOSED) - epoll_ev.events |= EPOLLRDHUP; - } - - /* - * Even though unused, we also pass epoll_ev as the data argument if - * EPOLL_CTL_DEL is passed as action. There used to be an epoll bug - * requiring that, and actually it makes the code simpler... - */ - rc = epoll_ctl(set->epoll_fd, action, event->fd, &epoll_ev); - - if (rc < 0) - ereport(ERROR, - (errcode_for_socket_access(), - errmsg("%s() failed: %m", - "epoll_ctl"))); -} -#endif - -#if defined(WAIT_USE_POLL) -static void -WaitEventAdjustPoll(WaitEventSet *set, WaitEvent *event) -{ - struct pollfd *pollfd = &set->pollfds[event->pos]; - - pollfd->revents = 0; - pollfd->fd = event->fd; - - /* prepare pollfd entry once */ - if (event->events == WL_LATCH_SET) - { - Assert(set->latch != NULL); - pollfd->events = POLLIN; - } - else if (event->events == WL_POSTMASTER_DEATH) - { - pollfd->events = POLLIN; - } - else - { - Assert(event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED)); - pollfd->events = 0; - if (event->events & WL_SOCKET_READABLE) - pollfd->events |= POLLIN; - if (event->events & WL_SOCKET_WRITEABLE) - pollfd->events |= POLLOUT; -#ifdef POLLRDHUP - if (event->events & WL_SOCKET_CLOSED) - pollfd->events |= POLLRDHUP; -#endif - } - - Assert(event->fd != PGINVALID_SOCKET); -} -#endif - -#if defined(WAIT_USE_KQUEUE) - -/* - * On most BSD family systems, the udata member of struct kevent is of type - * void *, so we could directly convert to/from WaitEvent *. Unfortunately, - * NetBSD has it as intptr_t, so here we wallpaper over that difference with - * an lvalue cast. - */ -#define AccessWaitEvent(k_ev) (*((WaitEvent **)(&(k_ev)->udata))) - -static inline void -WaitEventAdjustKqueueAdd(struct kevent *k_ev, int filter, int action, - WaitEvent *event) -{ - k_ev->ident = event->fd; - k_ev->filter = filter; - k_ev->flags = action; - k_ev->fflags = 0; - k_ev->data = 0; - AccessWaitEvent(k_ev) = event; -} - -static inline void -WaitEventAdjustKqueueAddPostmaster(struct kevent *k_ev, WaitEvent *event) -{ - /* For now postmaster death can only be added, not removed. */ - k_ev->ident = PostmasterPid; - k_ev->filter = EVFILT_PROC; - k_ev->flags = EV_ADD; - k_ev->fflags = NOTE_EXIT; - k_ev->data = 0; - AccessWaitEvent(k_ev) = event; -} - -static inline void -WaitEventAdjustKqueueAddLatch(struct kevent *k_ev, WaitEvent *event) -{ - /* For now latch can only be added, not removed. */ - k_ev->ident = SIGURG; - k_ev->filter = EVFILT_SIGNAL; - k_ev->flags = EV_ADD; - k_ev->fflags = 0; - k_ev->data = 0; - AccessWaitEvent(k_ev) = event; -} - -/* - * old_events is the previous event mask, used to compute what has changed. - */ -static void -WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events) -{ - int rc; - struct kevent k_ev[2]; - int count = 0; - bool new_filt_read = false; - bool old_filt_read = false; - bool new_filt_write = false; - bool old_filt_write = false; - - if (old_events == event->events) - return; - - Assert(event->events != WL_LATCH_SET || set->latch != NULL); - Assert(event->events == WL_LATCH_SET || - event->events == WL_POSTMASTER_DEATH || - (event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED))); - - if (event->events == WL_POSTMASTER_DEATH) - { - /* - * Unlike all the other implementations, we detect postmaster death - * using process notification instead of waiting on the postmaster - * alive pipe. - */ - WaitEventAdjustKqueueAddPostmaster(&k_ev[count++], event); - } - else if (event->events == WL_LATCH_SET) - { - /* We detect latch wakeup using a signal event. */ - WaitEventAdjustKqueueAddLatch(&k_ev[count++], event); - } - else - { - /* - * We need to compute the adds and deletes required to get from the - * old event mask to the new event mask, since kevent treats readable - * and writable as separate events. - */ - if (old_events & (WL_SOCKET_READABLE | WL_SOCKET_CLOSED)) - old_filt_read = true; - if (event->events & (WL_SOCKET_READABLE | WL_SOCKET_CLOSED)) - new_filt_read = true; - if (old_events & WL_SOCKET_WRITEABLE) - old_filt_write = true; - if (event->events & WL_SOCKET_WRITEABLE) - new_filt_write = true; - if (old_filt_read && !new_filt_read) - WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_READ, EV_DELETE, - event); - else if (!old_filt_read && new_filt_read) - WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_READ, EV_ADD, - event); - if (old_filt_write && !new_filt_write) - WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_WRITE, EV_DELETE, - event); - else if (!old_filt_write && new_filt_write) - WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_WRITE, EV_ADD, - event); - } - - /* For WL_SOCKET_READ -> WL_SOCKET_CLOSED, no change needed. */ - if (count == 0) - return; - - Assert(count <= 2); - - rc = kevent(set->kqueue_fd, &k_ev[0], count, NULL, 0, NULL); - - /* - * When adding the postmaster's pid, we have to consider that it might - * already have exited and perhaps even been replaced by another process - * with the same pid. If so, we have to defer reporting this as an event - * until the next call to WaitEventSetWaitBlock(). - */ - - if (rc < 0) - { - if (event->events == WL_POSTMASTER_DEATH && - (errno == ESRCH || errno == EACCES)) - set->report_postmaster_not_running = true; - else - ereport(ERROR, - (errcode_for_socket_access(), - errmsg("%s() failed: %m", - "kevent"))); - } - else if (event->events == WL_POSTMASTER_DEATH && - PostmasterPid != getppid() && - !PostmasterIsAlive()) - { - /* - * The extra PostmasterIsAliveInternal() check prevents false alarms - * on systems that give a different value for getppid() while being - * traced by a debugger. - */ - set->report_postmaster_not_running = true; - } -} - -#endif - -#if defined(WAIT_USE_WIN32) -static void -WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event) -{ - HANDLE *handle = &set->handles[event->pos + 1]; - - if (event->events == WL_LATCH_SET) - { - Assert(set->latch != NULL); - *handle = set->latch->event; - } - else if (event->events == WL_POSTMASTER_DEATH) - { - *handle = PostmasterHandle; - } - else - { - int flags = FD_CLOSE; /* always check for errors/EOF */ - - if (event->events & WL_SOCKET_READABLE) - flags |= FD_READ; - if (event->events & WL_SOCKET_WRITEABLE) - flags |= FD_WRITE; - if (event->events & WL_SOCKET_CONNECTED) - flags |= FD_CONNECT; - if (event->events & WL_SOCKET_ACCEPT) - flags |= FD_ACCEPT; - - if (*handle == WSA_INVALID_EVENT) - { - *handle = WSACreateEvent(); - if (*handle == WSA_INVALID_EVENT) - elog(ERROR, "failed to create event for socket: error code %d", - WSAGetLastError()); - } - if (WSAEventSelect(event->fd, *handle, flags) != 0) - elog(ERROR, "failed to set up event for socket: error code %d", - WSAGetLastError()); - - Assert(event->fd != PGINVALID_SOCKET); - } -} -#endif - -/* - * Wait for events added to the set to happen, or until the timeout is - * reached. At most nevents occurred events are returned. - * - * If timeout = -1, block until an event occurs; if 0, check sockets for - * readiness, but don't block; if > 0, block for at most timeout milliseconds. - * - * Returns the number of events occurred, or 0 if the timeout was reached. - * - * Returned events will have the fd, pos, user_data fields set to the - * values associated with the registered event. - */ -int -WaitEventSetWait(WaitEventSet *set, long timeout, - WaitEvent *occurred_events, int nevents, - uint32 wait_event_info) -{ - int returned_events = 0; - instr_time start_time; - instr_time cur_time; - long cur_timeout = -1; - - Assert(nevents > 0); - - /* - * Initialize timeout if requested. We must record the current time so - * that we can determine the remaining timeout if interrupted. - */ - if (timeout >= 0) - { - INSTR_TIME_SET_CURRENT(start_time); - Assert(timeout >= 0 && timeout <= INT_MAX); - cur_timeout = timeout; - } - else - INSTR_TIME_SET_ZERO(start_time); - - pgstat_report_wait_start(wait_event_info); - -#ifndef WIN32 - waiting = true; -#else - /* Ensure that signals are serviced even if latch is already set */ - pgwin32_dispatch_queued_signals(); -#endif - while (returned_events == 0) - { - int rc; - - /* - * Check if the latch is set already. If so, leave the loop - * immediately, avoid blocking again. We don't attempt to report any - * other events that might also be satisfied. - * - * If someone sets the latch between this and the - * WaitEventSetWaitBlock() below, the setter will write a byte to the - * pipe (or signal us and the signal handler will do that), and the - * readiness routine will return immediately. - * - * On unix, If there's a pending byte in the self pipe, we'll notice - * whenever blocking. Only clearing the pipe in that case avoids - * having to drain it every time WaitLatchOrSocket() is used. Should - * the pipe-buffer fill up we're still ok, because the pipe is in - * nonblocking mode. It's unlikely for that to happen, because the - * self pipe isn't filled unless we're blocking (waiting = true), or - * from inside a signal handler in latch_sigurg_handler(). - * - * On windows, we'll also notice if there's a pending event for the - * latch when blocking, but there's no danger of anything filling up, - * as "Setting an event that is already set has no effect.". - * - * Note: we assume that the kernel calls involved in latch management - * will provide adequate synchronization on machines with weak memory - * ordering, so that we cannot miss seeing is_set if a notification - * has already been queued. - */ - if (set->latch && !set->latch->is_set) - { - /* about to sleep on a latch */ - set->latch->maybe_sleeping = true; - pg_memory_barrier(); - /* and recheck */ - } - - if (set->latch && set->latch->is_set) - { - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->pos = set->latch_pos; - occurred_events->user_data = - set->events[set->latch_pos].user_data; - occurred_events->events = WL_LATCH_SET; - occurred_events++; - returned_events++; - - /* could have been set above */ - set->latch->maybe_sleeping = false; - - break; - } - - /* - * Wait for events using the readiness primitive chosen at the top of - * this file. If -1 is returned, a timeout has occurred, if 0 we have - * to retry, everything >= 1 is the number of returned events. - */ - rc = WaitEventSetWaitBlock(set, cur_timeout, - occurred_events, nevents); - - if (set->latch) - { - Assert(set->latch->maybe_sleeping); - set->latch->maybe_sleeping = false; - } - - if (rc == -1) - break; /* timeout occurred */ - else - returned_events = rc; - - /* If we're not done, update cur_timeout for next iteration */ - if (returned_events == 0 && timeout >= 0) - { - INSTR_TIME_SET_CURRENT(cur_time); - INSTR_TIME_SUBTRACT(cur_time, start_time); - cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); - if (cur_timeout <= 0) - break; - } - } -#ifndef WIN32 - waiting = false; -#endif - - pgstat_report_wait_end(); - - return returned_events; -} - - -#if defined(WAIT_USE_EPOLL) - -/* - * Wait using linux's epoll_wait(2). - * - * This is the preferable wait method, as several readiness notifications are - * delivered, without having to iterate through all of set->events. The return - * epoll_event struct contain a pointer to our events, making association - * easy. - */ -static inline int -WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, - WaitEvent *occurred_events, int nevents) -{ - int returned_events = 0; - int rc; - WaitEvent *cur_event; - struct epoll_event *cur_epoll_event; - - /* Sleep */ - rc = epoll_wait(set->epoll_fd, set->epoll_ret_events, - Min(nevents, set->nevents_space), cur_timeout); - - /* Check return code */ - if (rc < 0) - { - /* EINTR is okay, otherwise complain */ - if (errno != EINTR) - { - waiting = false; - ereport(ERROR, - (errcode_for_socket_access(), - errmsg("%s() failed: %m", - "epoll_wait"))); - } - return 0; - } - else if (rc == 0) - { - /* timeout exceeded */ - return -1; - } - - /* - * At least one event occurred, iterate over the returned epoll events - * until they're either all processed, or we've returned all the events - * the caller desired. - */ - for (cur_epoll_event = set->epoll_ret_events; - cur_epoll_event < (set->epoll_ret_events + rc) && - returned_events < nevents; - cur_epoll_event++) - { - /* epoll's data pointer is set to the associated WaitEvent */ - cur_event = (WaitEvent *) cur_epoll_event->data.ptr; - - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = 0; - - if (cur_event->events == WL_LATCH_SET && - cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - { - /* Drain the signalfd. */ - drain(); - - if (set->latch && set->latch->is_set) - { - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_LATCH_SET; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events == WL_POSTMASTER_DEATH && - cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - { - /* - * We expect an EPOLLHUP when the remote end is closed, but - * because we don't expect the pipe to become readable or to have - * any errors either, treat those cases as postmaster death, too. - * - * Be paranoid about a spurious event signaling the postmaster as - * being dead. There have been reports about that happening with - * older primitives (select(2) to be specific), and a spurious - * WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't - * cost much. - */ - if (!PostmasterIsAliveInternal()) - { - if (set->exit_on_postmaster_death) - proc_exit(1); - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_POSTMASTER_DEATH; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED)) - { - Assert(cur_event->fd != PGINVALID_SOCKET); - - if ((cur_event->events & WL_SOCKET_READABLE) && - (cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP))) - { - /* data available in socket, or EOF */ - occurred_events->events |= WL_SOCKET_READABLE; - } - - if ((cur_event->events & WL_SOCKET_WRITEABLE) && - (cur_epoll_event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) - { - /* writable, or EOF */ - occurred_events->events |= WL_SOCKET_WRITEABLE; - } - - if ((cur_event->events & WL_SOCKET_CLOSED) && - (cur_epoll_event->events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))) - { - /* remote peer shut down, or error */ - occurred_events->events |= WL_SOCKET_CLOSED; - } - - if (occurred_events->events != 0) - { - occurred_events->fd = cur_event->fd; - occurred_events++; - returned_events++; - } - } - } - - return returned_events; -} - -#elif defined(WAIT_USE_KQUEUE) - -/* - * Wait using kevent(2) on BSD-family systems and macOS. - * - * For now this mirrors the epoll code, but in future it could modify the fd - * set in the same call to kevent as it uses for waiting instead of doing that - * with separate system calls. - */ -static int -WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, - WaitEvent *occurred_events, int nevents) -{ - int returned_events = 0; - int rc; - WaitEvent *cur_event; - struct kevent *cur_kqueue_event; - struct timespec timeout; - struct timespec *timeout_p; - - if (cur_timeout < 0) - timeout_p = NULL; - else - { - timeout.tv_sec = cur_timeout / 1000; - timeout.tv_nsec = (cur_timeout % 1000) * 1000000; - timeout_p = &timeout; - } - - /* - * Report postmaster events discovered by WaitEventAdjustKqueue() or an - * earlier call to WaitEventSetWait(). - */ - if (unlikely(set->report_postmaster_not_running)) - { - if (set->exit_on_postmaster_death) - proc_exit(1); - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_POSTMASTER_DEATH; - return 1; - } - - /* Sleep */ - rc = kevent(set->kqueue_fd, NULL, 0, - set->kqueue_ret_events, - Min(nevents, set->nevents_space), - timeout_p); - - /* Check return code */ - if (rc < 0) - { - /* EINTR is okay, otherwise complain */ - if (errno != EINTR) - { - waiting = false; - ereport(ERROR, - (errcode_for_socket_access(), - errmsg("%s() failed: %m", - "kevent"))); - } - return 0; - } - else if (rc == 0) - { - /* timeout exceeded */ - return -1; - } - - /* - * At least one event occurred, iterate over the returned kqueue events - * until they're either all processed, or we've returned all the events - * the caller desired. - */ - for (cur_kqueue_event = set->kqueue_ret_events; - cur_kqueue_event < (set->kqueue_ret_events + rc) && - returned_events < nevents; - cur_kqueue_event++) - { - /* kevent's udata points to the associated WaitEvent */ - cur_event = AccessWaitEvent(cur_kqueue_event); - - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = 0; - - if (cur_event->events == WL_LATCH_SET && - cur_kqueue_event->filter == EVFILT_SIGNAL) - { - if (set->latch && set->latch->is_set) - { - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_LATCH_SET; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events == WL_POSTMASTER_DEATH && - cur_kqueue_event->filter == EVFILT_PROC && - (cur_kqueue_event->fflags & NOTE_EXIT) != 0) - { - /* - * The kernel will tell this kqueue object only once about the - * exit of the postmaster, so let's remember that for next time so - * that we provide level-triggered semantics. - */ - set->report_postmaster_not_running = true; - - if (set->exit_on_postmaster_death) - proc_exit(1); - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_POSTMASTER_DEATH; - occurred_events++; - returned_events++; - } - else if (cur_event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED)) - { - Assert(cur_event->fd >= 0); - - if ((cur_event->events & WL_SOCKET_READABLE) && - (cur_kqueue_event->filter == EVFILT_READ)) - { - /* readable, or EOF */ - occurred_events->events |= WL_SOCKET_READABLE; - } - - if ((cur_event->events & WL_SOCKET_CLOSED) && - (cur_kqueue_event->filter == EVFILT_READ) && - (cur_kqueue_event->flags & EV_EOF)) - { - /* the remote peer has shut down */ - occurred_events->events |= WL_SOCKET_CLOSED; - } - - if ((cur_event->events & WL_SOCKET_WRITEABLE) && - (cur_kqueue_event->filter == EVFILT_WRITE)) - { - /* writable, or EOF */ - occurred_events->events |= WL_SOCKET_WRITEABLE; - } - - if (occurred_events->events != 0) - { - occurred_events->fd = cur_event->fd; - occurred_events++; - returned_events++; - } - } - } - - return returned_events; -} - -#elif defined(WAIT_USE_POLL) - -/* - * Wait using poll(2). - * - * This allows to receive readiness notifications for several events at once, - * but requires iterating through all of set->pollfds. - */ -static inline int -WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, - WaitEvent *occurred_events, int nevents) -{ - int returned_events = 0; - int rc; - WaitEvent *cur_event; - struct pollfd *cur_pollfd; - - /* Sleep */ - rc = poll(set->pollfds, set->nevents, (int) cur_timeout); - - /* Check return code */ - if (rc < 0) - { - /* EINTR is okay, otherwise complain */ - if (errno != EINTR) - { - waiting = false; - ereport(ERROR, - (errcode_for_socket_access(), - errmsg("%s() failed: %m", - "poll"))); - } - return 0; - } - else if (rc == 0) - { - /* timeout exceeded */ - return -1; - } - - for (cur_event = set->events, cur_pollfd = set->pollfds; - cur_event < (set->events + set->nevents) && - returned_events < nevents; - cur_event++, cur_pollfd++) - { - /* no activity on this FD, skip */ - if (cur_pollfd->revents == 0) - continue; - - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = 0; - - if (cur_event->events == WL_LATCH_SET && - (cur_pollfd->revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL))) - { - /* There's data in the self-pipe, clear it. */ - drain(); - - if (set->latch && set->latch->is_set) - { - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_LATCH_SET; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events == WL_POSTMASTER_DEATH && - (cur_pollfd->revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL))) - { - /* - * We expect an POLLHUP when the remote end is closed, but because - * we don't expect the pipe to become readable or to have any - * errors either, treat those cases as postmaster death, too. - * - * Be paranoid about a spurious event signaling the postmaster as - * being dead. There have been reports about that happening with - * older primitives (select(2) to be specific), and a spurious - * WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't - * cost much. - */ - if (!PostmasterIsAliveInternal()) - { - if (set->exit_on_postmaster_death) - proc_exit(1); - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_POSTMASTER_DEATH; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events & (WL_SOCKET_READABLE | - WL_SOCKET_WRITEABLE | - WL_SOCKET_CLOSED)) - { - int errflags = POLLHUP | POLLERR | POLLNVAL; - - Assert(cur_event->fd >= PGINVALID_SOCKET); - - if ((cur_event->events & WL_SOCKET_READABLE) && - (cur_pollfd->revents & (POLLIN | errflags))) - { - /* data available in socket, or EOF */ - occurred_events->events |= WL_SOCKET_READABLE; - } - - if ((cur_event->events & WL_SOCKET_WRITEABLE) && - (cur_pollfd->revents & (POLLOUT | errflags))) - { - /* writeable, or EOF */ - occurred_events->events |= WL_SOCKET_WRITEABLE; - } - -#ifdef POLLRDHUP - if ((cur_event->events & WL_SOCKET_CLOSED) && - (cur_pollfd->revents & (POLLRDHUP | errflags))) - { - /* remote peer closed, or error */ - occurred_events->events |= WL_SOCKET_CLOSED; - } -#endif - - if (occurred_events->events != 0) - { - occurred_events->fd = cur_event->fd; - occurred_events++; - returned_events++; - } - } - } - return returned_events; -} - -#elif defined(WAIT_USE_WIN32) - -/* - * Wait using Windows' WaitForMultipleObjects(). Each call only "consumes" one - * event, so we keep calling until we've filled up our output buffer to match - * the behavior of the other implementations. - * - * https://blogs.msdn.microsoft.com/oldnewthing/20150409-00/?p=44273 - */ -static inline int -WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, - WaitEvent *occurred_events, int nevents) -{ - int returned_events = 0; - DWORD rc; - WaitEvent *cur_event; - - /* Reset any wait events that need it */ - for (cur_event = set->events; - cur_event < (set->events + set->nevents); - cur_event++) - { - if (cur_event->reset) - { - WaitEventAdjustWin32(set, cur_event); - cur_event->reset = false; - } - - /* - * We associate the socket with a new event handle for each - * WaitEventSet. FD_CLOSE is only generated once if the other end - * closes gracefully. Therefore we might miss the FD_CLOSE - * notification, if it was delivered to another event after we stopped - * waiting for it. Close that race by peeking for EOF after setting - * up this handle to receive notifications, and before entering the - * sleep. - * - * XXX If we had one event handle for the lifetime of a socket, we - * wouldn't need this. - */ - if (cur_event->events & WL_SOCKET_READABLE) - { - char c; - WSABUF buf; - DWORD received; - DWORD flags; - - buf.buf = &c; - buf.len = 1; - flags = MSG_PEEK; - if (WSARecv(cur_event->fd, &buf, 1, &received, &flags, NULL, NULL) == 0) - { - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = WL_SOCKET_READABLE; - occurred_events->fd = cur_event->fd; - return 1; - } - } - - /* - * Windows does not guarantee to log an FD_WRITE network event - * indicating that more data can be sent unless the previous send() - * failed with WSAEWOULDBLOCK. While our caller might well have made - * such a call, we cannot assume that here. Therefore, if waiting for - * write-ready, force the issue by doing a dummy send(). If the dummy - * send() succeeds, assume that the socket is in fact write-ready, and - * return immediately. Also, if it fails with something other than - * WSAEWOULDBLOCK, return a write-ready indication to let our caller - * deal with the error condition. - */ - if (cur_event->events & WL_SOCKET_WRITEABLE) - { - char c; - WSABUF buf; - DWORD sent; - int r; - - buf.buf = &c; - buf.len = 0; - - r = WSASend(cur_event->fd, &buf, 1, &sent, 0, NULL, NULL); - if (r == 0 || WSAGetLastError() != WSAEWOULDBLOCK) - { - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = WL_SOCKET_WRITEABLE; - occurred_events->fd = cur_event->fd; - return 1; - } - } - } - - /* - * Sleep. - * - * Need to wait for ->nevents + 1, because signal handle is in [0]. - */ - rc = WaitForMultipleObjects(set->nevents + 1, set->handles, FALSE, - cur_timeout); - - /* Check return code */ - if (rc == WAIT_FAILED) - elog(ERROR, "WaitForMultipleObjects() failed: error code %lu", - GetLastError()); - else if (rc == WAIT_TIMEOUT) - { - /* timeout exceeded */ - return -1; - } - - if (rc == WAIT_OBJECT_0) - { - /* Service newly-arrived signals */ - pgwin32_dispatch_queued_signals(); - return 0; /* retry */ - } - - /* - * With an offset of one, due to the always present pgwin32_signal_event, - * the handle offset directly corresponds to a wait event. - */ - cur_event = (WaitEvent *) &set->events[rc - WAIT_OBJECT_0 - 1]; - - for (;;) - { - int next_pos; - int count; - - occurred_events->pos = cur_event->pos; - occurred_events->user_data = cur_event->user_data; - occurred_events->events = 0; - - if (cur_event->events == WL_LATCH_SET) - { - /* - * We cannot use set->latch->event to reset the fired event if we - * aren't waiting on this latch now. - */ - if (!ResetEvent(set->handles[cur_event->pos + 1])) - elog(ERROR, "ResetEvent failed: error code %lu", GetLastError()); - - if (set->latch && set->latch->is_set) - { - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_LATCH_SET; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events == WL_POSTMASTER_DEATH) - { - /* - * Postmaster apparently died. Since the consequences of falsely - * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we - * take the trouble to positively verify this with - * PostmasterIsAlive(), even though there is no known reason to - * think that the event could be falsely set on Windows. - */ - if (!PostmasterIsAliveInternal()) - { - if (set->exit_on_postmaster_death) - proc_exit(1); - occurred_events->fd = PGINVALID_SOCKET; - occurred_events->events = WL_POSTMASTER_DEATH; - occurred_events++; - returned_events++; - } - } - else if (cur_event->events & WL_SOCKET_MASK) - { - WSANETWORKEVENTS resEvents; - HANDLE handle = set->handles[cur_event->pos + 1]; - - Assert(cur_event->fd); - - occurred_events->fd = cur_event->fd; - - ZeroMemory(&resEvents, sizeof(resEvents)); - if (WSAEnumNetworkEvents(cur_event->fd, handle, &resEvents) != 0) - elog(ERROR, "failed to enumerate network events: error code %d", - WSAGetLastError()); - if ((cur_event->events & WL_SOCKET_READABLE) && - (resEvents.lNetworkEvents & FD_READ)) - { - /* data available in socket */ - occurred_events->events |= WL_SOCKET_READABLE; - - /*------ - * WaitForMultipleObjects doesn't guarantee that a read event - * will be returned if the latch is set at the same time. Even - * if it did, the caller might drop that event expecting it to - * reoccur on next call. So, we must force the event to be - * reset if this WaitEventSet is used again in order to avoid - * an indefinite hang. - * - * Refer - * https://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx - * for the behavior of socket events. - *------ - */ - cur_event->reset = true; - } - if ((cur_event->events & WL_SOCKET_WRITEABLE) && - (resEvents.lNetworkEvents & FD_WRITE)) - { - /* writeable */ - occurred_events->events |= WL_SOCKET_WRITEABLE; - } - if ((cur_event->events & WL_SOCKET_CONNECTED) && - (resEvents.lNetworkEvents & FD_CONNECT)) - { - /* connected */ - occurred_events->events |= WL_SOCKET_CONNECTED; - } - if ((cur_event->events & WL_SOCKET_ACCEPT) && - (resEvents.lNetworkEvents & FD_ACCEPT)) - { - /* incoming connection could be accepted */ - occurred_events->events |= WL_SOCKET_ACCEPT; - } - if (resEvents.lNetworkEvents & FD_CLOSE) - { - /* EOF/error, so signal all caller-requested socket flags */ - occurred_events->events |= (cur_event->events & WL_SOCKET_MASK); - } - - if (occurred_events->events != 0) - { - occurred_events++; - returned_events++; - } - } - - /* Is the output buffer full? */ - if (returned_events == nevents) - break; - - /* Have we run out of possible events? */ - next_pos = cur_event->pos + 1; - if (next_pos == set->nevents) - break; - - /* - * Poll the rest of the event handles in the array starting at - * next_pos being careful to skip over the initial signal handle too. - * This time we use a zero timeout. - */ - count = set->nevents - next_pos; - rc = WaitForMultipleObjects(count, - set->handles + 1 + next_pos, - false, - 0); - - /* - * We don't distinguish between errors and WAIT_TIMEOUT here because - * we already have events to report. - */ - if (rc < WAIT_OBJECT_0 || rc >= WAIT_OBJECT_0 + count) - break; - - /* We have another event to decode. */ - cur_event = &set->events[next_pos + (rc - WAIT_OBJECT_0)]; - } - - return returned_events; -} -#endif - -/* - * Return whether the current build options can report WL_SOCKET_CLOSED. - */ -bool -WaitEventSetCanReportClosed(void) -{ -#if (defined(WAIT_USE_POLL) && defined(POLLRDHUP)) || \ - defined(WAIT_USE_EPOLL) || \ - defined(WAIT_USE_KQUEUE) - return true; -#else - return false; -#endif -} - -/* - * Get the number of wait events registered in a given WaitEventSet. - */ -int -GetNumRegisteredWaitEvents(WaitEventSet *set) -{ - return set->nevents; -} - -#if defined(WAIT_USE_SELF_PIPE) - -/* - * SetLatch uses SIGURG to wake up the process waiting on the latch. - * - * Wake up WaitLatch, if we're waiting. - */ -static void -latch_sigurg_handler(SIGNAL_ARGS) -{ - if (waiting) - sendSelfPipeByte(); -} - -/* Send one byte to the self-pipe, to wake up WaitLatch */ -static void -sendSelfPipeByte(void) -{ - int rc; - char dummy = 0; - -retry: - rc = write(selfpipe_writefd, &dummy, 1); - if (rc < 0) - { - /* If interrupted by signal, just retry */ - if (errno == EINTR) - goto retry; - - /* - * If the pipe is full, we don't need to retry, the data that's there - * already is enough to wake up WaitLatch. - */ - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; - - /* - * Oops, the write() failed for some other reason. We might be in a - * signal handler, so it's not safe to elog(). We have no choice but - * silently ignore the error. - */ - return; - } -} - -#endif - -#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) - -/* - * Read all available data from self-pipe or signalfd. - * - * Note: this is only called when waiting = true. If it fails and doesn't - * return, it must reset that flag first (though ideally, this will never - * happen). - */ -static void -drain(void) -{ - char buf[1024]; - int rc; - int fd; - -#ifdef WAIT_USE_SELF_PIPE - fd = selfpipe_readfd; -#else - fd = signal_fd; -#endif - - for (;;) - { - rc = read(fd, buf, sizeof(buf)); - if (rc < 0) - { - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; /* the descriptor is empty */ - else if (errno == EINTR) - continue; /* retry */ - else - { - waiting = false; -#ifdef WAIT_USE_SELF_PIPE - elog(ERROR, "read() on self-pipe failed: %m"); -#else - elog(ERROR, "read() on signalfd failed: %m"); -#endif - } - } - else if (rc == 0) - { - waiting = false; -#ifdef WAIT_USE_SELF_PIPE - elog(ERROR, "unexpected EOF on self-pipe"); -#else - elog(ERROR, "unexpected EOF on signalfd"); -#endif - } - else if (rc < sizeof(buf)) - { - /* we successfully drained the pipe; no need to read() again */ - break; - } - /* else buffer wasn't big enough, so read again */ - } -} - -#endif - -static void -ResOwnerReleaseWaitEventSet(Datum res) -{ - WaitEventSet *set = (WaitEventSet *) DatumGetPointer(res); - - Assert(set->owner != NULL); - set->owner = NULL; - FreeWaitEventSet(set); -} diff --git a/src/backend/storage/ipc/meson.build b/src/backend/storage/ipc/meson.build index 5a936171f7341..b1b73dac3bed6 100644 --- a/src/backend/storage/ipc/meson.build +++ b/src/backend/storage/ipc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'barrier.c', @@ -18,5 +18,6 @@ backend_sources += files( 'sinval.c', 'sinvaladt.c', 'standby.c', + 'waiteventset.c', ) diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 27844b46a2b1e..f2ea01622f9f4 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -4,7 +4,7 @@ * routines for signaling between the postmaster and its child processes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -24,6 +24,7 @@ #include "miscadmin.h" #include "postmaster/postmaster.h" #include "replication/walsender.h" +#include "storage/ipc.h" #include "storage/pmsignal.h" #include "storage/shmem.h" #include "utils/memutils.h" @@ -46,11 +47,11 @@ * exited without performing proper shutdown. The per-child-process flags * have three possible states: UNUSED, ASSIGNED, ACTIVE. An UNUSED slot is * available for assignment. An ASSIGNED slot is associated with a postmaster - * child process, but either the process has not touched shared memory yet, - * or it has successfully cleaned up after itself. A ACTIVE slot means the - * process is actively using shared memory. The slots are assigned to - * child processes at random, and postmaster.c is responsible for tracking - * which one goes with which PID. + * child process, but either the process has not touched shared memory yet, or + * it has successfully cleaned up after itself. An ACTIVE slot means the + * process is actively using shared memory. The slots are assigned to child + * processes by postmaster, and pmchild.c is responsible for tracking which + * one goes with which PID. * * Actually there is a fourth state, WALSENDER. This is just like ACTIVE, * but carries the extra information that the child is a WAL sender. @@ -83,13 +84,11 @@ struct PMSignalData NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL; /* - * These static variables are valid only in the postmaster. We keep a - * duplicative private array so that we can trust its state even if some - * failing child has clobbered the PMSignalData struct in shared memory. + * Local copy of PMSignalState->num_child_flags, only valid in the + * postmaster. Postmaster keeps a local copy so that it doesn't need to + * trust the value in shared memory. */ -static int num_child_inuse; /* # of entries in PMChildInUse[] */ -static int next_child_inuse; /* next slot to try to assign */ -static bool *PMChildInUse; /* true if i'th flag slot is assigned */ +static int num_child_flags; /* * Signal handler to be notified if postmaster dies. @@ -121,6 +120,8 @@ postmaster_death_handler(SIGNAL_ARGS) #endif /* USE_POSTMASTER_DEATH_SIGNAL */ +static void MarkPostmasterChildInactive(int code, Datum arg); + /* * PMSignalShmemSize * Compute space needed for pmsignal.c's shared memory @@ -152,25 +153,8 @@ PMSignalShmemInit(void) { /* initialize all flags to zeroes */ MemSet(unvolatize(PMSignalData *, PMSignalState), 0, PMSignalShmemSize()); - num_child_inuse = MaxLivePostmasterChildren(); - PMSignalState->num_child_flags = num_child_inuse; - - /* - * Also allocate postmaster's private PMChildInUse[] array. We - * might've already done that in a previous shared-memory creation - * cycle, in which case free the old array to avoid a leak. (Do it - * like this to support the possibility that MaxLivePostmasterChildren - * changed.) In a standalone backend, we do not need this. - */ - if (PostmasterContext != NULL) - { - if (PMChildInUse) - pfree(PMChildInUse); - PMChildInUse = (bool *) - MemoryContextAllocZero(PostmasterContext, - num_child_inuse * sizeof(bool)); - } - next_child_inuse = 0; + num_child_flags = MaxLivePostmasterChildren(); + PMSignalState->num_child_flags = num_child_flags; } } @@ -236,56 +220,37 @@ GetQuitSignalReason(void) /* - * AssignPostmasterChildSlot - select an unused slot for a new postmaster - * child process, and set its state to ASSIGNED. Returns a slot number - * (one to N). + * MarkPostmasterChildSlotAssigned - mark the given slot as ASSIGNED for a + * new postmaster child process. * * Only the postmaster is allowed to execute this routine, so we need no * special locking. */ -int -AssignPostmasterChildSlot(void) +void +MarkPostmasterChildSlotAssigned(int slot) { - int slot = next_child_inuse; - int n; + Assert(slot > 0 && slot <= num_child_flags); + slot--; - /* - * Scan for a free slot. Notice that we trust nothing about the contents - * of PMSignalState, but use only postmaster-local data for this decision. - * We track the last slot assigned so as not to waste time repeatedly - * rescanning low-numbered slots. - */ - for (n = num_child_inuse; n > 0; n--) - { - if (--slot < 0) - slot = num_child_inuse - 1; - if (!PMChildInUse[slot]) - { - PMChildInUse[slot] = true; - PMSignalState->PMChildFlags[slot] = PM_CHILD_ASSIGNED; - next_child_inuse = slot; - return slot + 1; - } - } + if (PMSignalState->PMChildFlags[slot] != PM_CHILD_UNUSED) + elog(FATAL, "postmaster child slot is already in use"); - /* Out of slots ... should never happen, else postmaster.c messed up */ - elog(FATAL, "no free slots in PMChildFlags array"); - return 0; /* keep compiler quiet */ + PMSignalState->PMChildFlags[slot] = PM_CHILD_ASSIGNED; } /* - * ReleasePostmasterChildSlot - release a slot after death of a postmaster - * child process. This must be called in the postmaster process. + * MarkPostmasterChildSlotUnassigned - release a slot after death of a + * postmaster child process. This must be called in the postmaster process. * * Returns true if the slot had been in ASSIGNED state (the expected case), * false otherwise (implying that the child failed to clean itself up). */ bool -ReleasePostmasterChildSlot(int slot) +MarkPostmasterChildSlotUnassigned(int slot) { bool result; - Assert(slot > 0 && slot <= num_child_inuse); + Assert(slot > 0 && slot <= num_child_flags); slot--; /* @@ -295,7 +260,6 @@ ReleasePostmasterChildSlot(int slot) */ result = (PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED); PMSignalState->PMChildFlags[slot] = PM_CHILD_UNUSED; - PMChildInUse[slot] = false; return result; } @@ -306,7 +270,7 @@ ReleasePostmasterChildSlot(int slot) bool IsPostmasterChildWalSender(int slot) { - Assert(slot > 0 && slot <= num_child_inuse); + Assert(slot > 0 && slot <= num_child_flags); slot--; if (PMSignalState->PMChildFlags[slot] == PM_CHILD_WALSENDER) @@ -316,11 +280,14 @@ IsPostmasterChildWalSender(int slot) } /* - * MarkPostmasterChildActive - mark a postmaster child as about to begin + * RegisterPostmasterChildActive - mark a postmaster child as about to begin * actively using shared memory. This is called in the child process. + * + * This register an shmem exit hook to mark us as inactive again when the + * process exits normally. */ void -MarkPostmasterChildActive(void) +RegisterPostmasterChildActive(void) { int slot = MyPMChildSlot; @@ -328,6 +295,9 @@ MarkPostmasterChildActive(void) slot--; Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED); PMSignalState->PMChildFlags[slot] = PM_CHILD_ACTIVE; + + /* Arrange to clean up at exit. */ + on_shmem_exit(MarkPostmasterChildInactive, 0); } /* @@ -352,8 +322,8 @@ MarkPostmasterChildWalSender(void) * MarkPostmasterChildInactive - mark a postmaster child as done using * shared memory. This is called in the child process. */ -void -MarkPostmasterChildInactive(void) +static void +MarkPostmasterChildInactive(int code, Datum arg) { int slot = MyPMChildSlot; diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index af3b15e93dfff..e5b945a9ee39c 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -34,7 +34,7 @@ * happen, it would tie up KnownAssignedXids indefinitely, so we protect * ourselves by pruning the array when a valid list of running XIDs arrives. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -370,7 +370,7 @@ static inline FullTransactionId FullXidRelativeTo(FullTransactionId rel, static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons); /* - * Report shared-memory space needed by CreateSharedProcArray. + * Report shared-memory space needed by ProcArrayShmemInit */ Size ProcArrayShmemSize(void) @@ -415,7 +415,7 @@ ProcArrayShmemSize(void) * Initialize the shared PGPROC array during postmaster startup. */ void -CreateSharedProcArray(void) +ProcArrayShmemInit(void) { bool found; @@ -2135,8 +2135,6 @@ GetSnapshotDataReuse(Snapshot snapshot) snapshot->active_count = 0; snapshot->regd_count = 0; snapshot->copied = false; - snapshot->lsn = InvalidXLogRecPtr; - snapshot->whenTaken = 0; return true; } @@ -2516,8 +2514,6 @@ GetSnapshotData(Snapshot snapshot) snapshot->active_count = 0; snapshot->regd_count = 0; snapshot->copied = false; - snapshot->lsn = InvalidXLogRecPtr; - snapshot->whenTaken = 0; return snapshot; } @@ -3626,8 +3622,7 @@ CountDBBackends(Oid databaseid) } /* - * CountDBConnections --- counts database backends ignoring any background - * worker processes + * CountDBConnections --- counts database backends (only regular backends) */ int CountDBConnections(Oid databaseid) @@ -3645,8 +3640,8 @@ CountDBConnections(Oid databaseid) if (proc->pid == 0) continue; /* do not count prepared xacts */ - if (proc->isBackgroundWorker) - continue; /* do not count background workers */ + if (!proc->isRegularBackend) + continue; /* count only regular backend processes */ if (!OidIsValid(databaseid) || proc->databaseId == databaseid) count++; @@ -3699,6 +3694,7 @@ CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending) /* * CountUserBackends --- count backends that are used by specified user + * (only regular backends, not any type of background worker) */ int CountUserBackends(Oid roleid) @@ -3716,8 +3712,8 @@ CountUserBackends(Oid roleid) if (proc->pid == 0) continue; /* do not count prepared xacts */ - if (proc->isBackgroundWorker) - continue; /* do not count background workers */ + if (!proc->isRegularBackend) + continue; /* count only regular backend processes */ if (proc->roleId == roleid) count++; } @@ -4501,9 +4497,23 @@ ExpireTreeKnownAssignedTransactionIds(TransactionId xid, int nsubxids, void ExpireAllKnownAssignedTransactionIds(void) { + FullTransactionId latestXid; + LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); KnownAssignedXidsRemovePreceding(InvalidTransactionId); + /* Reset latestCompletedXid to nextXid - 1 */ + Assert(FullTransactionIdIsValid(TransamVariables->nextXid)); + latestXid = TransamVariables->nextXid; + FullTransactionIdRetreat(&latestXid); + TransamVariables->latestCompletedXid = latestXid; + + /* + * Any transactions that were in-progress were effectively aborted, so + * advance xactCompletionCount. + */ + TransamVariables->xactCompletionCount++; + /* * Reset lastOverflowedXid. Currently, lastOverflowedXid has no use after * the call of this function. But do this for unification with what @@ -4521,8 +4531,18 @@ ExpireAllKnownAssignedTransactionIds(void) void ExpireOldKnownAssignedTransactionIds(TransactionId xid) { + TransactionId latestXid; + LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); + /* As in ProcArrayEndTransaction, advance latestCompletedXid */ + latestXid = xid; + TransactionIdRetreat(latestXid); + MaintainLatestCompletedXidRecovery(latestXid); + + /* ... and xactCompletionCount */ + TransamVariables->xactCompletionCount++; + /* * Reset lastOverflowedXid if we know all transactions that have been * possibly running are being gone. Not doing so could cause an incorrect diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index 4ed9cedcdd4e5..a9bb540b55ac2 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -4,7 +4,7 @@ * Routines for interprocess signaling * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -47,9 +47,9 @@ * know the ProcNumber of the process you're signaling. (We do support * signaling without ProcNumber, but it's a bit less efficient.) * - * The flags are actually declared as "volatile sig_atomic_t" for maximum - * portability. This should ensure that loads and stores of the flag - * values are atomic, allowing us to dispense with any explicit locking. + * The fields in each slot are protected by a spinlock, pss_mutex. pss_pid can + * also be read without holding the spinlock, as a quick preliminary check + * when searching for a particular PID in the array. * * pss_signalFlags are intended to be set in cases where we don't need to * keep track of whether or not the target process has handled the signal, @@ -62,8 +62,13 @@ */ typedef struct { - volatile pid_t pss_pid; + pg_atomic_uint32 pss_pid; + int pss_cancel_key_len; /* 0 means no cancellation is possible */ + uint8 pss_cancel_key[MAX_CANCEL_KEY_LENGTH]; volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]; + slock_t pss_mutex; /* protects the above fields */ + + /* Barrier-related fields (not protected by pss_mutex) */ pg_atomic_uint64 pss_barrierGeneration; pg_atomic_uint32 pss_barrierCheckMask; ConditionVariable pss_barrierCV; @@ -75,16 +80,17 @@ typedef struct * * psh_barrierGeneration is the highest barrier generation in existence. */ -typedef struct +struct ProcSignalHeader { pg_atomic_uint64 psh_barrierGeneration; ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]; -} ProcSignalHeader; +}; /* * We reserve a slot for each possible ProcNumber, plus one for each * possible auxiliary process type. (This scheme assumes there is not - * more than one of any auxiliary process type at a time.) + * more than one of any auxiliary process type at a time, except for + * IO workers.) */ #define NumProcSignalSlots (MaxBackends + NUM_AUXILIARY_PROCS) @@ -96,7 +102,7 @@ typedef struct #define BARRIER_CLEAR_BIT(flags, type) \ ((flags) &= ~(((uint32) 1) << (uint32) (type))) -static ProcSignalHeader *ProcSignal = NULL; +NON_EXEC_STATIC ProcSignalHeader *ProcSignal = NULL; static ProcSignalSlot *MyProcSignalSlot = NULL; static bool CheckProcSignal(ProcSignalReason reason); @@ -141,7 +147,9 @@ ProcSignalShmemInit(void) { ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; - slot->pss_pid = 0; + SpinLockInit(&slot->pss_mutex); + pg_atomic_init_u32(&slot->pss_pid, 0); + slot->pss_cancel_key_len = 0; MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags)); pg_atomic_init_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX); pg_atomic_init_u32(&slot->pss_barrierCheckMask, 0); @@ -155,21 +163,23 @@ ProcSignalShmemInit(void) * Register the current process in the ProcSignal array */ void -ProcSignalInit(void) +ProcSignalInit(const uint8 *cancel_key, int cancel_key_len) { ProcSignalSlot *slot; uint64 barrier_generation; + uint32 old_pss_pid; + Assert(cancel_key_len >= 0 && cancel_key_len <= MAX_CANCEL_KEY_LENGTH); if (MyProcNumber < 0) elog(ERROR, "MyProcNumber not set"); if (MyProcNumber >= NumProcSignalSlots) elog(ERROR, "unexpected MyProcNumber %d in ProcSignalInit (max %d)", MyProcNumber, NumProcSignalSlots); slot = &ProcSignal->psh_slot[MyProcNumber]; - /* sanity check */ - if (slot->pss_pid != 0) - elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty", - MyProcPid, MyProcNumber); + SpinLockAcquire(&slot->pss_mutex); + + /* Value used for sanity check below */ + old_pss_pid = pg_atomic_read_u32(&slot->pss_pid); /* Clear out any leftover signal reasons */ MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t)); @@ -189,10 +199,18 @@ ProcSignalInit(void) barrier_generation = pg_atomic_read_u64(&ProcSignal->psh_barrierGeneration); pg_atomic_write_u64(&slot->pss_barrierGeneration, barrier_generation); - pg_memory_barrier(); - /* Mark slot with my PID */ - slot->pss_pid = MyProcPid; + if (cancel_key_len > 0) + memcpy(slot->pss_cancel_key, cancel_key, cancel_key_len); + slot->pss_cancel_key_len = cancel_key_len; + pg_atomic_write_u32(&slot->pss_pid, MyProcPid); + + SpinLockRelease(&slot->pss_mutex); + + /* Spinlock is released, do the check */ + if (old_pss_pid != 0) + elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty", + MyProcPid, MyProcNumber); /* Remember slot location for CheckProcSignal */ MyProcSignalSlot = slot; @@ -210,6 +228,7 @@ ProcSignalInit(void) static void CleanupProcSignalState(int status, Datum arg) { + pid_t old_pid; ProcSignalSlot *slot = MyProcSignalSlot; /* @@ -221,25 +240,33 @@ CleanupProcSignalState(int status, Datum arg) MyProcSignalSlot = NULL; /* sanity check */ - if (slot->pss_pid != MyProcPid) + SpinLockAcquire(&slot->pss_mutex); + old_pid = pg_atomic_read_u32(&slot->pss_pid); + if (old_pid != MyProcPid) { /* * don't ERROR here. We're exiting anyway, and don't want to get into * infinite loop trying to exit */ + SpinLockRelease(&slot->pss_mutex); elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d", - MyProcPid, (int) (slot - ProcSignal->psh_slot), (int) slot->pss_pid); + MyProcPid, (int) (slot - ProcSignal->psh_slot), (int) old_pid); return; /* XXX better to zero the slot anyway? */ } + /* Mark the slot as unused */ + pg_atomic_write_u32(&slot->pss_pid, 0); + slot->pss_cancel_key_len = 0; + /* * Make this slot look like it's absorbed all possible barriers, so that * no barrier waits block on it. */ pg_atomic_write_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX); - ConditionVariableBroadcast(&slot->pss_barrierCV); - slot->pss_pid = 0; + SpinLockRelease(&slot->pss_mutex); + + ConditionVariableBroadcast(&slot->pss_barrierCV); } /* @@ -260,28 +287,24 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) if (procNumber != INVALID_PROC_NUMBER) { + Assert(procNumber < NumProcSignalSlots); slot = &ProcSignal->psh_slot[procNumber]; - /* - * Note: Since there's no locking, it's possible that the target - * process detaches from shared memory and exits right after this - * test, before we set the flag and send signal. And the signal slot - * might even be recycled by a new process, so it's remotely possible - * that we set a flag for a wrong process. That's OK, all the signals - * are such that no harm is done if they're mistakenly fired. - */ - if (slot->pss_pid == pid) + SpinLockAcquire(&slot->pss_mutex); + if (pg_atomic_read_u32(&slot->pss_pid) == pid) { /* Atomically set the proper flag */ slot->pss_signalFlags[reason] = true; + SpinLockRelease(&slot->pss_mutex); /* Send signal */ return kill(pid, SIGUSR1); } + SpinLockRelease(&slot->pss_mutex); } else { /* - * Pronumber not provided, so search the array using pid. We search + * procNumber not provided, so search the array using pid. We search * the array back to front so as to reduce search overhead. Passing * INVALID_PROC_NUMBER means that the target is most likely an * auxiliary process, which will have a slot near the end of the @@ -293,14 +316,18 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber) { slot = &ProcSignal->psh_slot[i]; - if (slot->pss_pid == pid) + if (pg_atomic_read_u32(&slot->pss_pid) == pid) { - /* the above note about race conditions applies here too */ - - /* Atomically set the proper flag */ - slot->pss_signalFlags[reason] = true; - /* Send signal */ - return kill(pid, SIGUSR1); + SpinLockAcquire(&slot->pss_mutex); + if (pg_atomic_read_u32(&slot->pss_pid) == pid) + { + /* Atomically set the proper flag */ + slot->pss_signalFlags[reason] = true; + SpinLockRelease(&slot->pss_mutex); + /* Send signal */ + return kill(pid, SIGUSR1); + } + SpinLockRelease(&slot->pss_mutex); } } } @@ -368,13 +395,21 @@ EmitProcSignalBarrier(ProcSignalBarrierType type) for (int i = NumProcSignalSlots - 1; i >= 0; i--) { volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; - pid_t pid = slot->pss_pid; + pid_t pid = pg_atomic_read_u32(&slot->pss_pid); if (pid != 0) { - /* see SendProcSignal for details */ - slot->pss_signalFlags[PROCSIG_BARRIER] = true; - kill(pid, SIGUSR1); + SpinLockAcquire(&slot->pss_mutex); + pid = pg_atomic_read_u32(&slot->pss_pid); + if (pid != 0) + { + /* see SendProcSignal for details */ + slot->pss_signalFlags[PROCSIG_BARRIER] = true; + SpinLockRelease(&slot->pss_mutex); + kill(pid, SIGUSR1); + } + else + SpinLockRelease(&slot->pss_mutex); } } @@ -414,7 +449,7 @@ WaitForProcSignalBarrier(uint64 generation) WAIT_EVENT_PROC_SIGNAL_BARRIER)) ereport(LOG, (errmsg("still waiting for backend with PID %d to accept ProcSignalBarrier", - (int) slot->pss_pid))); + (int) pg_atomic_read_u32(&slot->pss_pid)))); oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration); } ConditionVariableCancelSleep(); @@ -617,7 +652,11 @@ CheckProcSignal(ProcSignalReason reason) if (slot != NULL) { - /* Careful here --- don't clear flag if we haven't seen it set */ + /* + * Careful here --- don't clear flag if we haven't seen it set. + * pss_signalFlags is of type "volatile sig_atomic_t" to allow us to + * read it here safely, without holding the spinlock. + */ if (slot->pss_signalFlags[reason]) { slot->pss_signalFlags[reason] = false; @@ -678,3 +717,79 @@ procsignal_sigusr1_handler(SIGNAL_ARGS) SetLatch(MyLatch); } + +/* + * Send a query cancellation signal to backend. + * + * Note: This is called from a backend process before authentication. We + * cannot take LWLocks yet, but that's OK; we rely on atomic reads of the + * fields in the ProcSignal slots. + */ +void +SendCancelRequest(int backendPID, const uint8 *cancel_key, int cancel_key_len) +{ + Assert(backendPID != 0); + + /* + * See if we have a matching backend. Reading the pss_pid and + * pss_cancel_key fields is racy, a backend might die and remove itself + * from the array at any time. The probability of the cancellation key + * matching wrong process is miniscule, however, so we can live with that. + * PIDs are reused too, so sending the signal based on PID is inherently + * racy anyway, although OS's avoid reusing PIDs too soon. + */ + for (int i = 0; i < NumProcSignalSlots; i++) + { + ProcSignalSlot *slot = &ProcSignal->psh_slot[i]; + bool match; + + if (pg_atomic_read_u32(&slot->pss_pid) != backendPID) + continue; + + /* Acquire the spinlock and re-check */ + SpinLockAcquire(&slot->pss_mutex); + if (pg_atomic_read_u32(&slot->pss_pid) != backendPID) + { + SpinLockRelease(&slot->pss_mutex); + continue; + } + else + { + match = slot->pss_cancel_key_len == cancel_key_len && + timingsafe_bcmp(slot->pss_cancel_key, cancel_key, cancel_key_len) == 0; + + SpinLockRelease(&slot->pss_mutex); + + if (match) + { + /* Found a match; signal that backend to cancel current op */ + ereport(DEBUG2, + (errmsg_internal("processing cancel request: sending SIGINT to process %d", + backendPID))); + + /* + * If we have setsid(), signal the backend's whole process + * group + */ +#ifdef HAVE_SETSID + kill(-backendPID, SIGINT); +#else + kill(backendPID, SIGINT); +#endif + } + else + { + /* Right PID, wrong key: no way, Jose */ + ereport(LOG, + (errmsg("wrong key in cancel request for process %d", + backendPID))); + } + return; + } + } + + /* No matching backend */ + ereport(LOG, + (errmsg("PID %d in cancel request did not match any process", + backendPID))); +} diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c index 9235fcd08ec21..2c79a649f4632 100644 --- a/src/backend/storage/ipc/shm_mq.c +++ b/src/backend/storage/ipc/shm_mq.c @@ -8,7 +8,7 @@ * and only the receiver may receive. This is intended to allow a user * backend to communicate with worker backends that it has registered. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/storage/ipc/shm_mq.c diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c index 8db9d25aac241..0ad466e5705b4 100644 --- a/src/backend/storage/ipc/shm_toc.c +++ b/src/backend/storage/ipc/shm_toc.c @@ -3,7 +3,7 @@ * shm_toc.c * shared memory segment table of contents * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/storage/ipc/shm_toc.c diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 6d5f08398641c..c9ae3b45b76b1 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -3,7 +3,7 @@ * shmem.c * create shared memory and initialize shared memory data structures. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -68,6 +68,7 @@ #include "fmgr.h" #include "funcapi.h" #include "miscadmin.h" +#include "port/pg_numa.h" #include "storage/lwlock.h" #include "storage/pg_shmem.h" #include "storage/shmem.h" @@ -89,21 +90,20 @@ slock_t *ShmemLock; /* spinlock for shared memory and LWLock static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */ +/* To get reliable results for NUMA inquiry we need to "touch pages" once */ +static bool firstNumaTouch = true; + +Datum pg_numa_available(PG_FUNCTION_ARGS); /* * InitShmemAccess() --- set up basic pointers to shared memory. - * - * Note: the argument should be declared "PGShmemHeader *seghdr", - * but we use void to avoid having to include ipc.h in shmem.h. */ void -InitShmemAccess(void *seghdr) +InitShmemAccess(PGShmemHeader *seghdr) { - PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; - - ShmemSegHdr = shmhdr; - ShmemBase = (void *) shmhdr; - ShmemEnd = (char *) ShmemBase + shmhdr->totalsize; + ShmemSegHdr = seghdr; + ShmemBase = seghdr; + ShmemEnd = (char *) ShmemBase + seghdr->totalsize; } /* @@ -212,7 +212,7 @@ ShmemAllocRaw(Size size, Size *allocated_size) newFree = newStart + size; if (newFree <= ShmemSegHdr->totalsize) { - newSpace = (void *) ((char *) ShmemBase + newStart); + newSpace = (char *) ShmemBase + newStart; ShmemSegHdr->freeoffset = newFree; } else @@ -258,7 +258,7 @@ ShmemAllocUnlocked(Size size) size))); ShmemSegHdr->freeoffset = newFree; - newSpace = (void *) ((char *) ShmemBase + newStart); + newSpace = (char *) ShmemBase + newStart; Assert(newSpace == (void *) MAXALIGN(newSpace)); @@ -573,3 +573,195 @@ pg_get_shmem_allocations(PG_FUNCTION_ARGS) return (Datum) 0; } + +/* + * SQL SRF showing NUMA memory nodes for allocated shared memory + * + * Compared to pg_get_shmem_allocations(), this function does not return + * information about shared anonymous allocations and unused shared memory. + */ +Datum +pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS) +{ +#define PG_GET_SHMEM_NUMA_SIZES_COLS 3 + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + HASH_SEQ_STATUS hstat; + ShmemIndexEnt *ent; + Datum values[PG_GET_SHMEM_NUMA_SIZES_COLS]; + bool nulls[PG_GET_SHMEM_NUMA_SIZES_COLS]; + Size os_page_size; + void **page_ptrs; + int *pages_status; + uint64 shm_total_page_count, + shm_ent_page_count, + max_nodes; + Size *nodes; + + if (pg_numa_init() == -1) + elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform"); + + InitMaterializedSRF(fcinfo, 0); + + max_nodes = pg_numa_get_max_node(); + nodes = palloc(sizeof(Size) * (max_nodes + 1)); + + /* + * Different database block sizes (4kB, 8kB, ..., 32kB) can be used, while + * the OS may have different memory page sizes. + * + * To correctly map between them, we need to: 1. Determine the OS memory + * page size 2. Calculate how many OS pages are used by all buffer blocks + * 3. Calculate how many OS pages are contained within each database + * block. + * + * This information is needed before calling move_pages() for NUMA memory + * node inquiry. + */ + os_page_size = pg_get_shmem_pagesize(); + + /* + * Allocate memory for page pointers and status based on total shared + * memory size. This simplified approach allocates enough space for all + * pages in shared memory rather than calculating the exact requirements + * for each segment. + * + * Add 1, because we don't know how exactly the segments align to OS + * pages, so the allocation might use one more memory page. In practice + * this is not very likely, and moreover we have more entries, each of + * them using only fraction of the total pages. + */ + shm_total_page_count = (ShmemSegHdr->totalsize / os_page_size) + 1; + page_ptrs = palloc0(sizeof(void *) * shm_total_page_count); + pages_status = palloc(sizeof(int) * shm_total_page_count); + + if (firstNumaTouch) + elog(DEBUG1, "NUMA: page-faulting shared memory segments for proper NUMA readouts"); + + LWLockAcquire(ShmemIndexLock, LW_SHARED); + + hash_seq_init(&hstat, ShmemIndex); + + /* output all allocated entries */ + memset(nulls, 0, sizeof(nulls)); + while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL) + { + int i; + char *startptr, + *endptr; + Size total_len; + + /* + * Calculate the range of OS pages used by this segment. The segment + * may start / end half-way through a page, we want to count these + * pages too. So we align the start/end pointers down/up, and then + * calculate the number of pages from that. + */ + startptr = (char *) TYPEALIGN_DOWN(os_page_size, ent->location); + endptr = (char *) TYPEALIGN(os_page_size, + (char *) ent->location + ent->allocated_size); + total_len = (endptr - startptr); + + shm_ent_page_count = total_len / os_page_size; + + /* + * If we ever get 0xff (-1) back from kernel inquiry, then we probably + * have a bug in mapping buffers to OS pages. + */ + memset(pages_status, 0xff, sizeof(int) * shm_ent_page_count); + + /* + * Setup page_ptrs[] with pointers to all OS pages for this segment, + * and get the NUMA status using pg_numa_query_pages. + * + * In order to get reliable results we also need to touch memory + * pages, so that inquiry about NUMA memory node doesn't return -2 + * (ENOENT, which indicates unmapped/unallocated pages). + */ + for (i = 0; i < shm_ent_page_count; i++) + { + volatile uint64 touch pg_attribute_unused(); + + page_ptrs[i] = startptr + (i * os_page_size); + + if (firstNumaTouch) + pg_numa_touch_mem_if_required(touch, page_ptrs[i]); + + CHECK_FOR_INTERRUPTS(); + } + + if (pg_numa_query_pages(0, shm_ent_page_count, page_ptrs, pages_status) == -1) + elog(ERROR, "failed NUMA pages inquiry status: %m"); + + /* Count number of NUMA nodes used for this shared memory entry */ + memset(nodes, 0, sizeof(Size) * (max_nodes + 1)); + + for (i = 0; i < shm_ent_page_count; i++) + { + int s = pages_status[i]; + + /* Ensure we are adding only valid index to the array */ + if (s < 0 || s > max_nodes) + { + elog(ERROR, "invalid NUMA node id outside of allowed range " + "[0, " UINT64_FORMAT "]: %d", max_nodes, s); + } + + nodes[s]++; + } + + /* + * Add one entry for each NUMA node, including those without allocated + * memory for this segment. + */ + for (i = 0; i <= max_nodes; i++) + { + values[0] = CStringGetTextDatum(ent->key); + values[1] = i; + values[2] = Int64GetDatum(nodes[i] * os_page_size); + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, + values, nulls); + } + } + + LWLockRelease(ShmemIndexLock); + firstNumaTouch = false; + + return (Datum) 0; +} + +/* + * Determine the memory page size used for the shared memory segment. + * + * If the shared segment was allocated using huge pages, returns the size of + * a huge page. Otherwise returns the size of regular memory page. + * + * This should be used only after the server is started. + */ +Size +pg_get_shmem_pagesize(void) +{ + Size os_page_size; +#ifdef WIN32 + SYSTEM_INFO sysinfo; + + GetSystemInfo(&sysinfo); + os_page_size = sysinfo.dwPageSize; +#else + os_page_size = sysconf(_SC_PAGESIZE); +#endif + + Assert(IsUnderPostmaster); + Assert(huge_pages_status != HUGE_PAGES_UNKNOWN); + + if (huge_pages_status == HUGE_PAGES_ON) + GetHugePageSize(&os_page_size, NULL); + + return os_page_size; +} + +Datum +pg_numa_available(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(pg_numa_init() != -1); +} diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c index aa729a36e3921..a3a670ba24741 100644 --- a/src/backend/storage/ipc/signalfuncs.c +++ b/src/backend/storage/ipc/signalfuncs.c @@ -3,7 +3,7 @@ * signalfuncs.c * Functions for signaling backends * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -88,9 +88,9 @@ pg_signal_backend(int pid, int sig) if (!OidIsValid(proc->roleId) || superuser_arg(proc->roleId)) { ProcNumber procNumber = GetNumberFromPGProc(proc); - PgBackendStatus *procStatus = pgstat_get_beentry_by_proc_number(procNumber); + BackendType backendType = pgstat_get_backend_type_by_proc_number(procNumber); - if (procStatus && procStatus->st_backendType == B_AUTOVAC_WORKER) + if (backendType == B_AUTOVAC_WORKER) { if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM_WORKER)) return SIGNAL_BACKEND_NOAUTOVAC; @@ -215,10 +215,10 @@ pg_wait_until_termination(int pid, int64 timeout) } while (remainingtime > 0); ereport(WARNING, - (errmsg_plural("backend with PID %d did not terminate within %lld millisecond", - "backend with PID %d did not terminate within %lld milliseconds", + (errmsg_plural("backend with PID %d did not terminate within %" PRId64 " millisecond", + "backend with PID %d did not terminate within %" PRId64 " milliseconds", timeout, - pid, (long long int) timeout))); + pid, timeout))); return false; } diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index d9b16f84d19e1..6eea8e8716918 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -3,7 +3,7 @@ * sinval.c * POSTGRES shared cache invalidation communication code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index b486d8ddd1df6..c5748b690f408 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -3,7 +3,7 @@ * sinvaladt.c * POSTGRES shared cache invalidation data manager. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -17,7 +17,6 @@ #include #include -#include "access/transam.h" #include "miscadmin.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -199,7 +198,8 @@ typedef struct SISeg /* * We reserve a slot for each possible ProcNumber, plus one for each * possible auxiliary process type. (This scheme assumes there is not - * more than one of any auxiliary process type at a time.) + * more than one of any auxiliary process type at a time, except for + * IO workers.) */ #define NumProcStateSlots (MaxBackends + NUM_AUXILIARY_PROCS) @@ -212,10 +212,10 @@ static void CleanupInvalidationState(int status, Datum arg); /* - * SInvalShmemSize --- return shared-memory space needed + * SharedInvalShmemSize --- return shared-memory space needed */ Size -SInvalShmemSize(void) +SharedInvalShmemSize(void) { Size size; @@ -227,18 +227,18 @@ SInvalShmemSize(void) } /* - * CreateSharedInvalidationState + * SharedInvalShmemInit * Create and initialize the SI message buffer */ void -CreateSharedInvalidationState(void) +SharedInvalShmemInit(void) { int i; bool found; /* Allocate space in shared memory */ shmInvalBuffer = (SISeg *) - ShmemInitStruct("shmInvalBuffer", SInvalShmemSize(), &found); + ShmemInitStruct("shmInvalBuffer", SharedInvalShmemSize(), &found); if (found) return; diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 872679ca44788..7fa8d9247e097 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -7,7 +7,7 @@ * AccessExclusiveLocks and starting snapshots for Hot Standby mode. * Plus conflict recovery processing. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -31,6 +31,7 @@ #include "storage/sinvaladt.h" #include "storage/standby.h" #include "utils/hsearch.h" +#include "utils/injection_point.h" #include "utils/ps_status.h" #include "utils/timeout.h" #include "utils/timestamp.h" @@ -1121,6 +1122,9 @@ StandbyReleaseAllLocks(void) * StandbyReleaseOldLocks * Release standby locks held by top-level XIDs that aren't running, * as long as they're not prepared transactions. + * + * This is needed to prune the locks of crashed transactions, which didn't + * write an ABORT/COMMIT record. */ void StandbyReleaseOldLocks(TransactionId oldxid) @@ -1266,13 +1270,6 @@ standby_redo(XLogReaderState *record) * transactions already committed, since those commits raced ahead when * making WAL entries. * - * The loose timing also means that locks may be recorded that have a - * zero xid, since xids are removed from procs before locks are removed. - * So we must prune the lock list down to ensure we hold locks only for - * currently running xids, performed by StandbyReleaseOldLocks(). - * Zero xids should no longer be possible, but we may be replaying WAL - * from a time when they were possible. - * * For logical decoding only the running xacts information is needed; * there's no need to look at the locking information, but it's logged anyway, * as there's no independent knob to just enable logical decoding. For @@ -1291,6 +1288,17 @@ LogStandbySnapshot(void) Assert(XLogStandbyInfoActive()); +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("skip-log-running-xacts")) + { + /* + * This record could move slot's xmin forward during decoding, leading + * to unpredictable results, so skip it when requested by the test. + */ + return GetInsertRecPtr(); + } +#endif + /* * Get details of any AccessExclusiveLocks being held at the moment. */ @@ -1357,11 +1365,11 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts) /* Header */ XLogBeginInsert(); XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT); - XLogRegisterData((char *) (&xlrec), MinSizeOfXactRunningXacts); + XLogRegisterData(&xlrec, MinSizeOfXactRunningXacts); /* array of TransactionIds */ if (xlrec.xcnt > 0) - XLogRegisterData((char *) CurrRunningXacts->xids, + XLogRegisterData(CurrRunningXacts->xids, (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId)); recptr = XLogInsert(RM_STANDBY_ID, XLOG_RUNNING_XACTS); @@ -1409,8 +1417,8 @@ LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks) xlrec.nlocks = nlocks; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, offsetof(xl_standby_locks, locks)); - XLogRegisterData((char *) locks, nlocks * sizeof(xl_standby_lock)); + XLogRegisterData(&xlrec, offsetof(xl_standby_locks, locks)); + XLogRegisterData(locks, nlocks * sizeof(xl_standby_lock)); XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT); (void) XLogInsert(RM_STANDBY_ID, XLOG_STANDBY_LOCK); @@ -1473,8 +1481,8 @@ LogStandbyInvalidations(int nmsgs, SharedInvalidationMessage *msgs, /* perform insertion */ XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), MinSizeOfInvalidations); - XLogRegisterData((char *) msgs, + XLogRegisterData(&xlrec, MinSizeOfInvalidations); + XLogRegisterData(msgs, nmsgs * sizeof(SharedInvalidationMessage)); XLogInsert(RM_STANDBY_ID, XLOG_INVALIDATIONS); } diff --git a/src/backend/storage/ipc/waiteventset.c b/src/backend/storage/ipc/waiteventset.c new file mode 100644 index 0000000000000..7c0e66900f98d --- /dev/null +++ b/src/backend/storage/ipc/waiteventset.c @@ -0,0 +1,2036 @@ +/*------------------------------------------------------------------------- + * + * waiteventset.c + * ppoll()/pselect() like abstraction + * + * WaitEvents are an abstraction for waiting for one or more events at a time. + * The waiting can be done in a race free fashion, similar ppoll() or + * pselect() (as opposed to plain poll()/select()). + * + * You can wait for: + * - a latch being set from another process or from signal handler in the same + * process (WL_LATCH_SET) + * - data to become readable or writeable on a socket (WL_SOCKET_*) + * - postmaster death (WL_POSTMASTER_DEATH or WL_EXIT_ON_PM_DEATH) + * - timeout (WL_TIMEOUT) + * + * Implementation + * -------------- + * + * The poll() implementation uses the so-called self-pipe trick to overcome the + * race condition involved with poll() and setting a global flag in the signal + * handler. When a latch is set and the current process is waiting for it, the + * signal handler wakes up the poll() in WaitLatch by writing a byte to a pipe. + * A signal by itself doesn't interrupt poll() on all platforms, and even on + * platforms where it does, a signal that arrives just before the poll() call + * does not prevent poll() from entering sleep. An incoming byte on a pipe + * however reliably interrupts the sleep, and causes poll() to return + * immediately even if the signal arrives before poll() begins. + * + * The epoll() implementation overcomes the race with a different technique: it + * keeps SIGURG blocked and consumes from a signalfd() descriptor instead. We + * don't need to register a signal handler or create our own self-pipe. We + * assume that any system that has Linux epoll() also has Linux signalfd(). + * + * The kqueue() implementation waits for SIGURG with EVFILT_SIGNAL. + * + * The Windows implementation uses Windows events that are inherited by all + * postmaster child processes. There's no need for the self-pipe trick there. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/storage/ipc/waiteventset.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include +#include +#include +#ifdef HAVE_SYS_EPOLL_H +#include +#endif +#ifdef HAVE_SYS_EVENT_H +#include +#endif +#ifdef HAVE_SYS_SIGNALFD_H +#include +#endif +#ifdef HAVE_POLL_H +#include +#endif + +#include "libpq/pqsignal.h" +#include "miscadmin.h" +#include "pgstat.h" +#include "portability/instr_time.h" +#include "postmaster/postmaster.h" +#include "storage/fd.h" +#include "storage/ipc.h" +#include "storage/pmsignal.h" +#include "storage/latch.h" +#include "storage/waiteventset.h" +#include "utils/memutils.h" +#include "utils/resowner.h" + +/* + * Select the fd readiness primitive to use. Normally the "most modern" + * primitive supported by the OS will be used, but for testing it can be + * useful to manually specify the used primitive. If desired, just add a + * define somewhere before this block. + */ +#if defined(WAIT_USE_EPOLL) || defined(WAIT_USE_POLL) || \ + defined(WAIT_USE_KQUEUE) || defined(WAIT_USE_WIN32) +/* don't overwrite manual choice */ +#elif defined(HAVE_SYS_EPOLL_H) +#define WAIT_USE_EPOLL +#elif defined(HAVE_KQUEUE) +#define WAIT_USE_KQUEUE +#elif defined(HAVE_POLL) +#define WAIT_USE_POLL +#elif WIN32 +#define WAIT_USE_WIN32 +#else +#error "no wait set implementation available" +#endif + +/* + * By default, we use a self-pipe with poll() and a signalfd with epoll(), if + * available. For testing the choice can also be manually specified. + */ +#if defined(WAIT_USE_POLL) || defined(WAIT_USE_EPOLL) +#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) +/* don't overwrite manual choice */ +#elif defined(WAIT_USE_EPOLL) && defined(HAVE_SYS_SIGNALFD_H) +#define WAIT_USE_SIGNALFD +#else +#define WAIT_USE_SELF_PIPE +#endif +#endif + +/* typedef in waiteventset.h */ +struct WaitEventSet +{ + ResourceOwner owner; + + int nevents; /* number of registered events */ + int nevents_space; /* maximum number of events in this set */ + + /* + * Array, of nevents_space length, storing the definition of events this + * set is waiting for. + */ + WaitEvent *events; + + /* + * If WL_LATCH_SET is specified in any wait event, latch is a pointer to + * said latch, and latch_pos the offset in the ->events array. This is + * useful because we check the state of the latch before performing doing + * syscalls related to waiting. + */ + Latch *latch; + int latch_pos; + + /* + * WL_EXIT_ON_PM_DEATH is converted to WL_POSTMASTER_DEATH, but this flag + * is set so that we'll exit immediately if postmaster death is detected, + * instead of returning. + */ + bool exit_on_postmaster_death; + +#if defined(WAIT_USE_EPOLL) + int epoll_fd; + /* epoll_wait returns events in a user provided arrays, allocate once */ + struct epoll_event *epoll_ret_events; +#elif defined(WAIT_USE_KQUEUE) + int kqueue_fd; + /* kevent returns events in a user provided arrays, allocate once */ + struct kevent *kqueue_ret_events; + bool report_postmaster_not_running; +#elif defined(WAIT_USE_POLL) + /* poll expects events to be waited on every poll() call, prepare once */ + struct pollfd *pollfds; +#elif defined(WAIT_USE_WIN32) + + /* + * Array of windows events. The first element always contains + * pgwin32_signal_event, so the remaining elements are offset by one (i.e. + * event->pos + 1). + */ + HANDLE *handles; +#endif +}; + +#ifndef WIN32 +/* Are we currently in WaitLatch? The signal handler would like to know. */ +static volatile sig_atomic_t waiting = false; +#endif + +#ifdef WAIT_USE_SIGNALFD +/* On Linux, we'll receive SIGURG via a signalfd file descriptor. */ +static int signal_fd = -1; +#endif + +#ifdef WAIT_USE_SELF_PIPE +/* Read and write ends of the self-pipe */ +static int selfpipe_readfd = -1; +static int selfpipe_writefd = -1; + +/* Process owning the self-pipe --- needed for checking purposes */ +static int selfpipe_owner_pid = 0; + +/* Private function prototypes */ +static void latch_sigurg_handler(SIGNAL_ARGS); +static void sendSelfPipeByte(void); +#endif + +#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) +static void drain(void); +#endif + +#if defined(WAIT_USE_EPOLL) +static void WaitEventAdjustEpoll(WaitEventSet *set, WaitEvent *event, int action); +#elif defined(WAIT_USE_KQUEUE) +static void WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events); +#elif defined(WAIT_USE_POLL) +static void WaitEventAdjustPoll(WaitEventSet *set, WaitEvent *event); +#elif defined(WAIT_USE_WIN32) +static void WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event); +#endif + +static inline int WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, + WaitEvent *occurred_events, int nevents); + +/* ResourceOwner support to hold WaitEventSets */ +static void ResOwnerReleaseWaitEventSet(Datum res); + +static const ResourceOwnerDesc wait_event_set_resowner_desc = +{ + .name = "WaitEventSet", + .release_phase = RESOURCE_RELEASE_AFTER_LOCKS, + .release_priority = RELEASE_PRIO_WAITEVENTSETS, + .ReleaseResource = ResOwnerReleaseWaitEventSet, + .DebugPrint = NULL +}; + +/* Convenience wrappers over ResourceOwnerRemember/Forget */ +static inline void +ResourceOwnerRememberWaitEventSet(ResourceOwner owner, WaitEventSet *set) +{ + ResourceOwnerRemember(owner, PointerGetDatum(set), &wait_event_set_resowner_desc); +} +static inline void +ResourceOwnerForgetWaitEventSet(ResourceOwner owner, WaitEventSet *set) +{ + ResourceOwnerForget(owner, PointerGetDatum(set), &wait_event_set_resowner_desc); +} + + +/* + * Initialize the process-local wait event infrastructure. + * + * This must be called once during startup of any process that can wait on + * latches, before it issues any InitLatch() or OwnLatch() calls. + */ +void +InitializeWaitEventSupport(void) +{ +#if defined(WAIT_USE_SELF_PIPE) + int pipefd[2]; + + if (IsUnderPostmaster) + { + /* + * We might have inherited connections to a self-pipe created by the + * postmaster. It's critical that child processes create their own + * self-pipes, of course, and we really want them to close the + * inherited FDs for safety's sake. + */ + if (selfpipe_owner_pid != 0) + { + /* Assert we go through here but once in a child process */ + Assert(selfpipe_owner_pid != MyProcPid); + /* Release postmaster's pipe FDs; ignore any error */ + (void) close(selfpipe_readfd); + (void) close(selfpipe_writefd); + /* Clean up, just for safety's sake; we'll set these below */ + selfpipe_readfd = selfpipe_writefd = -1; + selfpipe_owner_pid = 0; + /* Keep fd.c's accounting straight */ + ReleaseExternalFD(); + ReleaseExternalFD(); + } + else + { + /* + * Postmaster didn't create a self-pipe ... or else we're in an + * EXEC_BACKEND build, in which case it doesn't matter since the + * postmaster's pipe FDs were closed by the action of FD_CLOEXEC. + * fd.c won't have state to clean up, either. + */ + Assert(selfpipe_readfd == -1); + } + } + else + { + /* In postmaster or standalone backend, assert we do this but once */ + Assert(selfpipe_readfd == -1); + Assert(selfpipe_owner_pid == 0); + } + + /* + * Set up the self-pipe that allows a signal handler to wake up the + * poll()/epoll_wait() in WaitLatch. Make the write-end non-blocking, so + * that SetLatch won't block if the event has already been set many times + * filling the kernel buffer. Make the read-end non-blocking too, so that + * we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK. + * Also, make both FDs close-on-exec, since we surely do not want any + * child processes messing with them. + */ + if (pipe(pipefd) < 0) + elog(FATAL, "pipe() failed: %m"); + if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1) + elog(FATAL, "fcntl(F_SETFL) failed on read-end of self-pipe: %m"); + if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) == -1) + elog(FATAL, "fcntl(F_SETFL) failed on write-end of self-pipe: %m"); + if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1) + elog(FATAL, "fcntl(F_SETFD) failed on read-end of self-pipe: %m"); + if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1) + elog(FATAL, "fcntl(F_SETFD) failed on write-end of self-pipe: %m"); + + selfpipe_readfd = pipefd[0]; + selfpipe_writefd = pipefd[1]; + selfpipe_owner_pid = MyProcPid; + + /* Tell fd.c about these two long-lived FDs */ + ReserveExternalFD(); + ReserveExternalFD(); + + pqsignal(SIGURG, latch_sigurg_handler); +#endif + +#ifdef WAIT_USE_SIGNALFD + sigset_t signalfd_mask; + + if (IsUnderPostmaster) + { + /* + * It would probably be safe to re-use the inherited signalfd since + * signalfds only see the current process's pending signals, but it + * seems less surprising to close it and create our own. + */ + if (signal_fd != -1) + { + /* Release postmaster's signal FD; ignore any error */ + (void) close(signal_fd); + signal_fd = -1; + ReleaseExternalFD(); + } + } + + /* Block SIGURG, because we'll receive it through a signalfd. */ + sigaddset(&UnBlockSig, SIGURG); + + /* Set up the signalfd to receive SIGURG notifications. */ + sigemptyset(&signalfd_mask); + sigaddset(&signalfd_mask, SIGURG); + signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); + if (signal_fd < 0) + elog(FATAL, "signalfd() failed"); + ReserveExternalFD(); +#endif + +#ifdef WAIT_USE_KQUEUE + /* Ignore SIGURG, because we'll receive it via kqueue. */ + pqsignal(SIGURG, SIG_IGN); +#endif +} + +/* + * Create a WaitEventSet with space for nevents different events to wait for. + * + * These events can then be efficiently waited upon together, using + * WaitEventSetWait(). + * + * The WaitEventSet is tracked by the given 'resowner'. Use NULL for session + * lifetime. + */ +WaitEventSet * +CreateWaitEventSet(ResourceOwner resowner, int nevents) +{ + WaitEventSet *set; + char *data; + Size sz = 0; + + /* + * Use MAXALIGN size/alignment to guarantee that later uses of memory are + * aligned correctly. E.g. epoll_event might need 8 byte alignment on some + * platforms, but earlier allocations like WaitEventSet and WaitEvent + * might not be sized to guarantee that when purely using sizeof(). + */ + sz += MAXALIGN(sizeof(WaitEventSet)); + sz += MAXALIGN(sizeof(WaitEvent) * nevents); + +#if defined(WAIT_USE_EPOLL) + sz += MAXALIGN(sizeof(struct epoll_event) * nevents); +#elif defined(WAIT_USE_KQUEUE) + sz += MAXALIGN(sizeof(struct kevent) * nevents); +#elif defined(WAIT_USE_POLL) + sz += MAXALIGN(sizeof(struct pollfd) * nevents); +#elif defined(WAIT_USE_WIN32) + /* need space for the pgwin32_signal_event */ + sz += MAXALIGN(sizeof(HANDLE) * (nevents + 1)); +#endif + + if (resowner != NULL) + ResourceOwnerEnlarge(resowner); + + data = (char *) MemoryContextAllocZero(TopMemoryContext, sz); + + set = (WaitEventSet *) data; + data += MAXALIGN(sizeof(WaitEventSet)); + + set->events = (WaitEvent *) data; + data += MAXALIGN(sizeof(WaitEvent) * nevents); + +#if defined(WAIT_USE_EPOLL) + set->epoll_ret_events = (struct epoll_event *) data; + data += MAXALIGN(sizeof(struct epoll_event) * nevents); +#elif defined(WAIT_USE_KQUEUE) + set->kqueue_ret_events = (struct kevent *) data; + data += MAXALIGN(sizeof(struct kevent) * nevents); +#elif defined(WAIT_USE_POLL) + set->pollfds = (struct pollfd *) data; + data += MAXALIGN(sizeof(struct pollfd) * nevents); +#elif defined(WAIT_USE_WIN32) + set->handles = (HANDLE) data; + data += MAXALIGN(sizeof(HANDLE) * nevents); +#endif + + set->latch = NULL; + set->nevents_space = nevents; + set->exit_on_postmaster_death = false; + + if (resowner != NULL) + { + ResourceOwnerRememberWaitEventSet(resowner, set); + set->owner = resowner; + } + +#if defined(WAIT_USE_EPOLL) + if (!AcquireExternalFD()) + elog(ERROR, "AcquireExternalFD, for epoll_create1, failed: %m"); + set->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (set->epoll_fd < 0) + { + ReleaseExternalFD(); + elog(ERROR, "epoll_create1 failed: %m"); + } +#elif defined(WAIT_USE_KQUEUE) + if (!AcquireExternalFD()) + elog(ERROR, "AcquireExternalFD, for kqueue, failed: %m"); + set->kqueue_fd = kqueue(); + if (set->kqueue_fd < 0) + { + ReleaseExternalFD(); + elog(ERROR, "kqueue failed: %m"); + } + if (fcntl(set->kqueue_fd, F_SETFD, FD_CLOEXEC) == -1) + { + int save_errno = errno; + + close(set->kqueue_fd); + ReleaseExternalFD(); + errno = save_errno; + elog(ERROR, "fcntl(F_SETFD) failed on kqueue descriptor: %m"); + } + set->report_postmaster_not_running = false; +#elif defined(WAIT_USE_WIN32) + + /* + * To handle signals while waiting, we need to add a win32 specific event. + * We accounted for the additional event at the top of this routine. See + * port/win32/signal.c for more details. + * + * Note: pgwin32_signal_event should be first to ensure that it will be + * reported when multiple events are set. We want to guarantee that + * pending signals are serviced. + */ + set->handles[0] = pgwin32_signal_event; + StaticAssertStmt(WSA_INVALID_EVENT == NULL, ""); +#endif + + return set; +} + +/* + * Free a previously created WaitEventSet. + * + * Note: preferably, this shouldn't have to free any resources that could be + * inherited across an exec(). If it did, we'd likely leak those resources in + * many scenarios. For the epoll case, we ensure that by setting EPOLL_CLOEXEC + * when the FD is created. For the Windows case, we assume that the handles + * involved are non-inheritable. + */ +void +FreeWaitEventSet(WaitEventSet *set) +{ + if (set->owner) + { + ResourceOwnerForgetWaitEventSet(set->owner, set); + set->owner = NULL; + } + +#if defined(WAIT_USE_EPOLL) + close(set->epoll_fd); + ReleaseExternalFD(); +#elif defined(WAIT_USE_KQUEUE) + close(set->kqueue_fd); + ReleaseExternalFD(); +#elif defined(WAIT_USE_WIN32) + for (WaitEvent *cur_event = set->events; + cur_event < (set->events + set->nevents); + cur_event++) + { + if (cur_event->events & WL_LATCH_SET) + { + /* uses the latch's HANDLE */ + } + else if (cur_event->events & WL_POSTMASTER_DEATH) + { + /* uses PostmasterHandle */ + } + else + { + /* Clean up the event object we created for the socket */ + WSAEventSelect(cur_event->fd, NULL, 0); + WSACloseEvent(set->handles[cur_event->pos + 1]); + } + } +#endif + + pfree(set); +} + +/* + * Free a previously created WaitEventSet in a child process after a fork(). + */ +void +FreeWaitEventSetAfterFork(WaitEventSet *set) +{ +#if defined(WAIT_USE_EPOLL) + close(set->epoll_fd); + ReleaseExternalFD(); +#elif defined(WAIT_USE_KQUEUE) + /* kqueues are not normally inherited by child processes */ + ReleaseExternalFD(); +#endif + + pfree(set); +} + +/* --- + * Add an event to the set. Possible events are: + * - WL_LATCH_SET: Wait for the latch to be set + * - WL_POSTMASTER_DEATH: Wait for postmaster to die + * - WL_SOCKET_READABLE: Wait for socket to become readable, + * can be combined in one event with other WL_SOCKET_* events + * - WL_SOCKET_WRITEABLE: Wait for socket to become writeable, + * can be combined with other WL_SOCKET_* events + * - WL_SOCKET_CONNECTED: Wait for socket connection to be established, + * can be combined with other WL_SOCKET_* events (on non-Windows + * platforms, this is the same as WL_SOCKET_WRITEABLE) + * - WL_SOCKET_ACCEPT: Wait for new connection to a server socket, + * can be combined with other WL_SOCKET_* events (on non-Windows + * platforms, this is the same as WL_SOCKET_READABLE) + * - WL_SOCKET_CLOSED: Wait for socket to be closed by remote peer. + * - WL_EXIT_ON_PM_DEATH: Exit immediately if the postmaster dies + * + * Returns the offset in WaitEventSet->events (starting from 0), which can be + * used to modify previously added wait events using ModifyWaitEvent(). + * + * In the WL_LATCH_SET case the latch must be owned by the current process, + * i.e. it must be a process-local latch initialized with InitLatch, or a + * shared latch associated with the current process by calling OwnLatch. + * + * In the WL_SOCKET_READABLE/WRITEABLE/CONNECTED/ACCEPT cases, EOF and error + * conditions cause the socket to be reported as readable/writable/connected, + * so that the caller can deal with the condition. + * + * The user_data pointer specified here will be set for the events returned + * by WaitEventSetWait(), allowing to easily associate additional data with + * events. + */ +int +AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, + void *user_data) +{ + WaitEvent *event; + + /* not enough space */ + Assert(set->nevents < set->nevents_space); + + if (events == WL_EXIT_ON_PM_DEATH) + { + events = WL_POSTMASTER_DEATH; + set->exit_on_postmaster_death = true; + } + + if (latch) + { + if (latch->owner_pid != MyProcPid) + elog(ERROR, "cannot wait on a latch owned by another process"); + if (set->latch) + elog(ERROR, "cannot wait on more than one latch"); + if ((events & WL_LATCH_SET) != WL_LATCH_SET) + elog(ERROR, "latch events only support being set"); + } + else + { + if (events & WL_LATCH_SET) + elog(ERROR, "cannot wait on latch without a specified latch"); + } + + /* waiting for socket readiness without a socket indicates a bug */ + if (fd == PGINVALID_SOCKET && (events & WL_SOCKET_MASK)) + elog(ERROR, "cannot wait on socket event without a socket"); + + event = &set->events[set->nevents]; + event->pos = set->nevents++; + event->fd = fd; + event->events = events; + event->user_data = user_data; +#ifdef WIN32 + event->reset = false; +#endif + + if (events == WL_LATCH_SET) + { + set->latch = latch; + set->latch_pos = event->pos; +#if defined(WAIT_USE_SELF_PIPE) + event->fd = selfpipe_readfd; +#elif defined(WAIT_USE_SIGNALFD) + event->fd = signal_fd; +#else + event->fd = PGINVALID_SOCKET; +#ifdef WAIT_USE_EPOLL + return event->pos; +#endif +#endif + } + else if (events == WL_POSTMASTER_DEATH) + { +#ifndef WIN32 + event->fd = postmaster_alive_fds[POSTMASTER_FD_WATCH]; +#endif + } + + /* perform wait primitive specific initialization, if needed */ +#if defined(WAIT_USE_EPOLL) + WaitEventAdjustEpoll(set, event, EPOLL_CTL_ADD); +#elif defined(WAIT_USE_KQUEUE) + WaitEventAdjustKqueue(set, event, 0); +#elif defined(WAIT_USE_POLL) + WaitEventAdjustPoll(set, event); +#elif defined(WAIT_USE_WIN32) + WaitEventAdjustWin32(set, event); +#endif + + return event->pos; +} + +/* + * Change the event mask and, in the WL_LATCH_SET case, the latch associated + * with the WaitEvent. The latch may be changed to NULL to disable the latch + * temporarily, and then set back to a latch later. + * + * 'pos' is the id returned by AddWaitEventToSet. + */ +void +ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch) +{ + WaitEvent *event; +#if defined(WAIT_USE_KQUEUE) + int old_events; +#endif + + Assert(pos < set->nevents); + + event = &set->events[pos]; +#if defined(WAIT_USE_KQUEUE) + old_events = event->events; +#endif + + /* + * Allow switching between WL_POSTMASTER_DEATH and WL_EXIT_ON_PM_DEATH. + * + * Note that because WL_EXIT_ON_PM_DEATH is mapped to WL_POSTMASTER_DEATH + * in AddWaitEventToSet(), this needs to be checked before the fast-path + * below that checks if 'events' has changed. + */ + if (event->events == WL_POSTMASTER_DEATH) + { + if (events != WL_POSTMASTER_DEATH && events != WL_EXIT_ON_PM_DEATH) + elog(ERROR, "cannot remove postmaster death event"); + set->exit_on_postmaster_death = ((events & WL_EXIT_ON_PM_DEATH) != 0); + return; + } + + /* + * If neither the event mask nor the associated latch changes, return + * early. That's an important optimization for some sockets, where + * ModifyWaitEvent is frequently used to switch from waiting for reads to + * waiting on writes. + */ + if (events == event->events && + (!(event->events & WL_LATCH_SET) || set->latch == latch)) + return; + + if (event->events & WL_LATCH_SET && events != event->events) + elog(ERROR, "cannot modify latch event"); + + /* FIXME: validate event mask */ + event->events = events; + + if (events == WL_LATCH_SET) + { + if (latch && latch->owner_pid != MyProcPid) + elog(ERROR, "cannot wait on a latch owned by another process"); + set->latch = latch; + + /* + * On Unix, we don't need to modify the kernel object because the + * underlying pipe (if there is one) is the same for all latches so we + * can return immediately. On Windows, we need to update our array of + * handles, but we leave the old one in place and tolerate spurious + * wakeups if the latch is disabled. + */ +#if defined(WAIT_USE_WIN32) + if (!latch) + return; +#else + return; +#endif + } + +#if defined(WAIT_USE_EPOLL) + WaitEventAdjustEpoll(set, event, EPOLL_CTL_MOD); +#elif defined(WAIT_USE_KQUEUE) + WaitEventAdjustKqueue(set, event, old_events); +#elif defined(WAIT_USE_POLL) + WaitEventAdjustPoll(set, event); +#elif defined(WAIT_USE_WIN32) + WaitEventAdjustWin32(set, event); +#endif +} + +#if defined(WAIT_USE_EPOLL) +/* + * action can be one of EPOLL_CTL_ADD | EPOLL_CTL_MOD | EPOLL_CTL_DEL + */ +static void +WaitEventAdjustEpoll(WaitEventSet *set, WaitEvent *event, int action) +{ + struct epoll_event epoll_ev; + int rc; + + /* pointer to our event, returned by epoll_wait */ + epoll_ev.data.ptr = event; + /* always wait for errors */ + epoll_ev.events = EPOLLERR | EPOLLHUP; + + /* prepare pollfd entry once */ + if (event->events == WL_LATCH_SET) + { + Assert(set->latch != NULL); + epoll_ev.events |= EPOLLIN; + } + else if (event->events == WL_POSTMASTER_DEATH) + { + epoll_ev.events |= EPOLLIN; + } + else + { + Assert(event->fd != PGINVALID_SOCKET); + Assert(event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED)); + + if (event->events & WL_SOCKET_READABLE) + epoll_ev.events |= EPOLLIN; + if (event->events & WL_SOCKET_WRITEABLE) + epoll_ev.events |= EPOLLOUT; + if (event->events & WL_SOCKET_CLOSED) + epoll_ev.events |= EPOLLRDHUP; + } + + /* + * Even though unused, we also pass epoll_ev as the data argument if + * EPOLL_CTL_DEL is passed as action. There used to be an epoll bug + * requiring that, and actually it makes the code simpler... + */ + rc = epoll_ctl(set->epoll_fd, action, event->fd, &epoll_ev); + + if (rc < 0) + ereport(ERROR, + (errcode_for_socket_access(), + errmsg("%s() failed: %m", + "epoll_ctl"))); +} +#endif + +#if defined(WAIT_USE_POLL) +static void +WaitEventAdjustPoll(WaitEventSet *set, WaitEvent *event) +{ + struct pollfd *pollfd = &set->pollfds[event->pos]; + + pollfd->revents = 0; + pollfd->fd = event->fd; + + /* prepare pollfd entry once */ + if (event->events == WL_LATCH_SET) + { + Assert(set->latch != NULL); + pollfd->events = POLLIN; + } + else if (event->events == WL_POSTMASTER_DEATH) + { + pollfd->events = POLLIN; + } + else + { + Assert(event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED)); + pollfd->events = 0; + if (event->events & WL_SOCKET_READABLE) + pollfd->events |= POLLIN; + if (event->events & WL_SOCKET_WRITEABLE) + pollfd->events |= POLLOUT; +#ifdef POLLRDHUP + if (event->events & WL_SOCKET_CLOSED) + pollfd->events |= POLLRDHUP; +#endif + } + + Assert(event->fd != PGINVALID_SOCKET); +} +#endif + +#if defined(WAIT_USE_KQUEUE) + +/* + * On most BSD family systems, the udata member of struct kevent is of type + * void *, so we could directly convert to/from WaitEvent *. Unfortunately, + * NetBSD has it as intptr_t, so here we wallpaper over that difference with + * an lvalue cast. + */ +#define AccessWaitEvent(k_ev) (*((WaitEvent **)(&(k_ev)->udata))) + +static inline void +WaitEventAdjustKqueueAdd(struct kevent *k_ev, int filter, int action, + WaitEvent *event) +{ + k_ev->ident = event->fd; + k_ev->filter = filter; + k_ev->flags = action; + k_ev->fflags = 0; + k_ev->data = 0; + AccessWaitEvent(k_ev) = event; +} + +static inline void +WaitEventAdjustKqueueAddPostmaster(struct kevent *k_ev, WaitEvent *event) +{ + /* For now postmaster death can only be added, not removed. */ + k_ev->ident = PostmasterPid; + k_ev->filter = EVFILT_PROC; + k_ev->flags = EV_ADD; + k_ev->fflags = NOTE_EXIT; + k_ev->data = 0; + AccessWaitEvent(k_ev) = event; +} + +static inline void +WaitEventAdjustKqueueAddLatch(struct kevent *k_ev, WaitEvent *event) +{ + /* For now latch can only be added, not removed. */ + k_ev->ident = SIGURG; + k_ev->filter = EVFILT_SIGNAL; + k_ev->flags = EV_ADD; + k_ev->fflags = 0; + k_ev->data = 0; + AccessWaitEvent(k_ev) = event; +} + +/* + * old_events is the previous event mask, used to compute what has changed. + */ +static void +WaitEventAdjustKqueue(WaitEventSet *set, WaitEvent *event, int old_events) +{ + int rc; + struct kevent k_ev[2]; + int count = 0; + bool new_filt_read = false; + bool old_filt_read = false; + bool new_filt_write = false; + bool old_filt_write = false; + + if (old_events == event->events) + return; + + Assert(event->events != WL_LATCH_SET || set->latch != NULL); + Assert(event->events == WL_LATCH_SET || + event->events == WL_POSTMASTER_DEATH || + (event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED))); + + if (event->events == WL_POSTMASTER_DEATH) + { + /* + * Unlike all the other implementations, we detect postmaster death + * using process notification instead of waiting on the postmaster + * alive pipe. + */ + WaitEventAdjustKqueueAddPostmaster(&k_ev[count++], event); + } + else if (event->events == WL_LATCH_SET) + { + /* We detect latch wakeup using a signal event. */ + WaitEventAdjustKqueueAddLatch(&k_ev[count++], event); + } + else + { + /* + * We need to compute the adds and deletes required to get from the + * old event mask to the new event mask, since kevent treats readable + * and writable as separate events. + */ + if (old_events & (WL_SOCKET_READABLE | WL_SOCKET_CLOSED)) + old_filt_read = true; + if (event->events & (WL_SOCKET_READABLE | WL_SOCKET_CLOSED)) + new_filt_read = true; + if (old_events & WL_SOCKET_WRITEABLE) + old_filt_write = true; + if (event->events & WL_SOCKET_WRITEABLE) + new_filt_write = true; + if (old_filt_read && !new_filt_read) + WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_READ, EV_DELETE, + event); + else if (!old_filt_read && new_filt_read) + WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_READ, EV_ADD, + event); + if (old_filt_write && !new_filt_write) + WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_WRITE, EV_DELETE, + event); + else if (!old_filt_write && new_filt_write) + WaitEventAdjustKqueueAdd(&k_ev[count++], EVFILT_WRITE, EV_ADD, + event); + } + + /* For WL_SOCKET_READ -> WL_SOCKET_CLOSED, no change needed. */ + if (count == 0) + return; + + Assert(count <= 2); + + rc = kevent(set->kqueue_fd, &k_ev[0], count, NULL, 0, NULL); + + /* + * When adding the postmaster's pid, we have to consider that it might + * already have exited and perhaps even been replaced by another process + * with the same pid. If so, we have to defer reporting this as an event + * until the next call to WaitEventSetWaitBlock(). + */ + + if (rc < 0) + { + if (event->events == WL_POSTMASTER_DEATH && + (errno == ESRCH || errno == EACCES)) + set->report_postmaster_not_running = true; + else + ereport(ERROR, + (errcode_for_socket_access(), + errmsg("%s() failed: %m", + "kevent"))); + } + else if (event->events == WL_POSTMASTER_DEATH && + PostmasterPid != getppid() && + !PostmasterIsAlive()) + { + /* + * The extra PostmasterIsAliveInternal() check prevents false alarms + * on systems that give a different value for getppid() while being + * traced by a debugger. + */ + set->report_postmaster_not_running = true; + } +} + +#endif + +#if defined(WAIT_USE_WIN32) +static void +WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event) +{ + HANDLE *handle = &set->handles[event->pos + 1]; + + if (event->events == WL_LATCH_SET) + { + Assert(set->latch != NULL); + *handle = set->latch->event; + } + else if (event->events == WL_POSTMASTER_DEATH) + { + *handle = PostmasterHandle; + } + else + { + int flags = FD_CLOSE; /* always check for errors/EOF */ + + if (event->events & WL_SOCKET_READABLE) + flags |= FD_READ; + if (event->events & WL_SOCKET_WRITEABLE) + flags |= FD_WRITE; + if (event->events & WL_SOCKET_CONNECTED) + flags |= FD_CONNECT; + if (event->events & WL_SOCKET_ACCEPT) + flags |= FD_ACCEPT; + + if (*handle == WSA_INVALID_EVENT) + { + *handle = WSACreateEvent(); + if (*handle == WSA_INVALID_EVENT) + elog(ERROR, "failed to create event for socket: error code %d", + WSAGetLastError()); + } + if (WSAEventSelect(event->fd, *handle, flags) != 0) + elog(ERROR, "failed to set up event for socket: error code %d", + WSAGetLastError()); + + Assert(event->fd != PGINVALID_SOCKET); + } +} +#endif + +/* + * Wait for events added to the set to happen, or until the timeout is + * reached. At most nevents occurred events are returned. + * + * If timeout = -1, block until an event occurs; if 0, check sockets for + * readiness, but don't block; if > 0, block for at most timeout milliseconds. + * + * Returns the number of events occurred, or 0 if the timeout was reached. + * + * Returned events will have the fd, pos, user_data fields set to the + * values associated with the registered event. + */ +int +WaitEventSetWait(WaitEventSet *set, long timeout, + WaitEvent *occurred_events, int nevents, + uint32 wait_event_info) +{ + int returned_events = 0; + instr_time start_time; + instr_time cur_time; + long cur_timeout = -1; + + Assert(nevents > 0); + + /* + * Initialize timeout if requested. We must record the current time so + * that we can determine the remaining timeout if interrupted. + */ + if (timeout >= 0) + { + INSTR_TIME_SET_CURRENT(start_time); + Assert(timeout >= 0 && timeout <= INT_MAX); + cur_timeout = timeout; + } + else + INSTR_TIME_SET_ZERO(start_time); + + pgstat_report_wait_start(wait_event_info); + +#ifndef WIN32 + waiting = true; +#else + /* Ensure that signals are serviced even if latch is already set */ + pgwin32_dispatch_queued_signals(); +#endif + while (returned_events == 0) + { + int rc; + + /* + * Check if the latch is set already first. If so, we either exit + * immediately or ask the kernel for further events available right + * now without waiting, depending on how many events the caller wants. + * + * If someone sets the latch between this and the + * WaitEventSetWaitBlock() below, the setter will write a byte to the + * pipe (or signal us and the signal handler will do that), and the + * readiness routine will return immediately. + * + * On unix, If there's a pending byte in the self pipe, we'll notice + * whenever blocking. Only clearing the pipe in that case avoids + * having to drain it every time WaitLatchOrSocket() is used. Should + * the pipe-buffer fill up we're still ok, because the pipe is in + * nonblocking mode. It's unlikely for that to happen, because the + * self pipe isn't filled unless we're blocking (waiting = true), or + * from inside a signal handler in latch_sigurg_handler(). + * + * On windows, we'll also notice if there's a pending event for the + * latch when blocking, but there's no danger of anything filling up, + * as "Setting an event that is already set has no effect.". + * + * Note: we assume that the kernel calls involved in latch management + * will provide adequate synchronization on machines with weak memory + * ordering, so that we cannot miss seeing is_set if a notification + * has already been queued. + */ + if (set->latch && !set->latch->is_set) + { + /* about to sleep on a latch */ + set->latch->maybe_sleeping = true; + pg_memory_barrier(); + /* and recheck */ + } + + if (set->latch && set->latch->is_set) + { + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->pos = set->latch_pos; + occurred_events->user_data = + set->events[set->latch_pos].user_data; + occurred_events->events = WL_LATCH_SET; + occurred_events++; + returned_events++; + + /* could have been set above */ + set->latch->maybe_sleeping = false; + + if (returned_events == nevents) + break; /* output buffer full already */ + + /* + * Even though we already have an event, we'll poll just once with + * zero timeout to see what non-latch events we can fit into the + * output buffer at the same time. + */ + cur_timeout = 0; + timeout = 0; + } + + /* + * Wait for events using the readiness primitive chosen at the top of + * this file. If -1 is returned, a timeout has occurred, if 0 we have + * to retry, everything >= 1 is the number of returned events. + */ + rc = WaitEventSetWaitBlock(set, cur_timeout, + occurred_events, nevents - returned_events); + + if (set->latch && + set->latch->maybe_sleeping) + set->latch->maybe_sleeping = false; + + if (rc == -1) + break; /* timeout occurred */ + else + returned_events += rc; + + /* If we're not done, update cur_timeout for next iteration */ + if (returned_events == 0 && timeout >= 0) + { + INSTR_TIME_SET_CURRENT(cur_time); + INSTR_TIME_SUBTRACT(cur_time, start_time); + cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + if (cur_timeout <= 0) + break; + } + } +#ifndef WIN32 + waiting = false; +#endif + + pgstat_report_wait_end(); + + return returned_events; +} + + +#if defined(WAIT_USE_EPOLL) + +/* + * Wait using linux's epoll_wait(2). + * + * This is the preferable wait method, as several readiness notifications are + * delivered, without having to iterate through all of set->events. The return + * epoll_event struct contain a pointer to our events, making association + * easy. + */ +static inline int +WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, + WaitEvent *occurred_events, int nevents) +{ + int returned_events = 0; + int rc; + WaitEvent *cur_event; + struct epoll_event *cur_epoll_event; + + /* Sleep */ + rc = epoll_wait(set->epoll_fd, set->epoll_ret_events, + Min(nevents, set->nevents_space), cur_timeout); + + /* Check return code */ + if (rc < 0) + { + /* EINTR is okay, otherwise complain */ + if (errno != EINTR) + { + waiting = false; + ereport(ERROR, + (errcode_for_socket_access(), + errmsg("%s() failed: %m", + "epoll_wait"))); + } + return 0; + } + else if (rc == 0) + { + /* timeout exceeded */ + return -1; + } + + /* + * At least one event occurred, iterate over the returned epoll events + * until they're either all processed, or we've returned all the events + * the caller desired. + */ + for (cur_epoll_event = set->epoll_ret_events; + cur_epoll_event < (set->epoll_ret_events + rc) && + returned_events < nevents; + cur_epoll_event++) + { + /* epoll's data pointer is set to the associated WaitEvent */ + cur_event = (WaitEvent *) cur_epoll_event->data.ptr; + + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = 0; + + if (cur_event->events == WL_LATCH_SET && + cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) + { + /* Drain the signalfd. */ + drain(); + + if (set->latch && set->latch->maybe_sleeping && set->latch->is_set) + { + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_LATCH_SET; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events == WL_POSTMASTER_DEATH && + cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) + { + /* + * We expect an EPOLLHUP when the remote end is closed, but + * because we don't expect the pipe to become readable or to have + * any errors either, treat those cases as postmaster death, too. + * + * Be paranoid about a spurious event signaling the postmaster as + * being dead. There have been reports about that happening with + * older primitives (select(2) to be specific), and a spurious + * WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't + * cost much. + */ + if (!PostmasterIsAliveInternal()) + { + if (set->exit_on_postmaster_death) + proc_exit(1); + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_POSTMASTER_DEATH; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED)) + { + Assert(cur_event->fd != PGINVALID_SOCKET); + + if ((cur_event->events & WL_SOCKET_READABLE) && + (cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP))) + { + /* data available in socket, or EOF */ + occurred_events->events |= WL_SOCKET_READABLE; + } + + if ((cur_event->events & WL_SOCKET_WRITEABLE) && + (cur_epoll_event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) + { + /* writable, or EOF */ + occurred_events->events |= WL_SOCKET_WRITEABLE; + } + + if ((cur_event->events & WL_SOCKET_CLOSED) && + (cur_epoll_event->events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))) + { + /* remote peer shut down, or error */ + occurred_events->events |= WL_SOCKET_CLOSED; + } + + if (occurred_events->events != 0) + { + occurred_events->fd = cur_event->fd; + occurred_events++; + returned_events++; + } + } + } + + return returned_events; +} + +#elif defined(WAIT_USE_KQUEUE) + +/* + * Wait using kevent(2) on BSD-family systems and macOS. + * + * For now this mirrors the epoll code, but in future it could modify the fd + * set in the same call to kevent as it uses for waiting instead of doing that + * with separate system calls. + */ +static int +WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, + WaitEvent *occurred_events, int nevents) +{ + int returned_events = 0; + int rc; + WaitEvent *cur_event; + struct kevent *cur_kqueue_event; + struct timespec timeout; + struct timespec *timeout_p; + + if (cur_timeout < 0) + timeout_p = NULL; + else + { + timeout.tv_sec = cur_timeout / 1000; + timeout.tv_nsec = (cur_timeout % 1000) * 1000000; + timeout_p = &timeout; + } + + /* + * Report postmaster events discovered by WaitEventAdjustKqueue() or an + * earlier call to WaitEventSetWait(). + */ + if (unlikely(set->report_postmaster_not_running)) + { + if (set->exit_on_postmaster_death) + proc_exit(1); + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_POSTMASTER_DEATH; + return 1; + } + + /* Sleep */ + rc = kevent(set->kqueue_fd, NULL, 0, + set->kqueue_ret_events, + Min(nevents, set->nevents_space), + timeout_p); + + /* Check return code */ + if (rc < 0) + { + /* EINTR is okay, otherwise complain */ + if (errno != EINTR) + { + waiting = false; + ereport(ERROR, + (errcode_for_socket_access(), + errmsg("%s() failed: %m", + "kevent"))); + } + return 0; + } + else if (rc == 0) + { + /* timeout exceeded */ + return -1; + } + + /* + * At least one event occurred, iterate over the returned kqueue events + * until they're either all processed, or we've returned all the events + * the caller desired. + */ + for (cur_kqueue_event = set->kqueue_ret_events; + cur_kqueue_event < (set->kqueue_ret_events + rc) && + returned_events < nevents; + cur_kqueue_event++) + { + /* kevent's udata points to the associated WaitEvent */ + cur_event = AccessWaitEvent(cur_kqueue_event); + + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = 0; + + if (cur_event->events == WL_LATCH_SET && + cur_kqueue_event->filter == EVFILT_SIGNAL) + { + if (set->latch && set->latch->maybe_sleeping && set->latch->is_set) + { + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_LATCH_SET; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events == WL_POSTMASTER_DEATH && + cur_kqueue_event->filter == EVFILT_PROC && + (cur_kqueue_event->fflags & NOTE_EXIT) != 0) + { + /* + * The kernel will tell this kqueue object only once about the + * exit of the postmaster, so let's remember that for next time so + * that we provide level-triggered semantics. + */ + set->report_postmaster_not_running = true; + + if (set->exit_on_postmaster_death) + proc_exit(1); + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_POSTMASTER_DEATH; + occurred_events++; + returned_events++; + } + else if (cur_event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED)) + { + Assert(cur_event->fd >= 0); + + if ((cur_event->events & WL_SOCKET_READABLE) && + (cur_kqueue_event->filter == EVFILT_READ)) + { + /* readable, or EOF */ + occurred_events->events |= WL_SOCKET_READABLE; + } + + if ((cur_event->events & WL_SOCKET_CLOSED) && + (cur_kqueue_event->filter == EVFILT_READ) && + (cur_kqueue_event->flags & EV_EOF)) + { + /* the remote peer has shut down */ + occurred_events->events |= WL_SOCKET_CLOSED; + } + + if ((cur_event->events & WL_SOCKET_WRITEABLE) && + (cur_kqueue_event->filter == EVFILT_WRITE)) + { + /* writable, or EOF */ + occurred_events->events |= WL_SOCKET_WRITEABLE; + } + + if (occurred_events->events != 0) + { + occurred_events->fd = cur_event->fd; + occurred_events++; + returned_events++; + } + } + } + + return returned_events; +} + +#elif defined(WAIT_USE_POLL) + +/* + * Wait using poll(2). + * + * This allows to receive readiness notifications for several events at once, + * but requires iterating through all of set->pollfds. + */ +static inline int +WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, + WaitEvent *occurred_events, int nevents) +{ + int returned_events = 0; + int rc; + WaitEvent *cur_event; + struct pollfd *cur_pollfd; + + /* Sleep */ + rc = poll(set->pollfds, set->nevents, (int) cur_timeout); + + /* Check return code */ + if (rc < 0) + { + /* EINTR is okay, otherwise complain */ + if (errno != EINTR) + { + waiting = false; + ereport(ERROR, + (errcode_for_socket_access(), + errmsg("%s() failed: %m", + "poll"))); + } + return 0; + } + else if (rc == 0) + { + /* timeout exceeded */ + return -1; + } + + for (cur_event = set->events, cur_pollfd = set->pollfds; + cur_event < (set->events + set->nevents) && + returned_events < nevents; + cur_event++, cur_pollfd++) + { + /* no activity on this FD, skip */ + if (cur_pollfd->revents == 0) + continue; + + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = 0; + + if (cur_event->events == WL_LATCH_SET && + (cur_pollfd->revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL))) + { + /* There's data in the self-pipe, clear it. */ + drain(); + + if (set->latch && set->latch->maybe_sleeping && set->latch->is_set) + { + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_LATCH_SET; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events == WL_POSTMASTER_DEATH && + (cur_pollfd->revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL))) + { + /* + * We expect an POLLHUP when the remote end is closed, but because + * we don't expect the pipe to become readable or to have any + * errors either, treat those cases as postmaster death, too. + * + * Be paranoid about a spurious event signaling the postmaster as + * being dead. There have been reports about that happening with + * older primitives (select(2) to be specific), and a spurious + * WL_POSTMASTER_DEATH event would be painful. Re-checking doesn't + * cost much. + */ + if (!PostmasterIsAliveInternal()) + { + if (set->exit_on_postmaster_death) + proc_exit(1); + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_POSTMASTER_DEATH; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events & (WL_SOCKET_READABLE | + WL_SOCKET_WRITEABLE | + WL_SOCKET_CLOSED)) + { + int errflags = POLLHUP | POLLERR | POLLNVAL; + + Assert(cur_event->fd >= PGINVALID_SOCKET); + + if ((cur_event->events & WL_SOCKET_READABLE) && + (cur_pollfd->revents & (POLLIN | errflags))) + { + /* data available in socket, or EOF */ + occurred_events->events |= WL_SOCKET_READABLE; + } + + if ((cur_event->events & WL_SOCKET_WRITEABLE) && + (cur_pollfd->revents & (POLLOUT | errflags))) + { + /* writeable, or EOF */ + occurred_events->events |= WL_SOCKET_WRITEABLE; + } + +#ifdef POLLRDHUP + if ((cur_event->events & WL_SOCKET_CLOSED) && + (cur_pollfd->revents & (POLLRDHUP | errflags))) + { + /* remote peer closed, or error */ + occurred_events->events |= WL_SOCKET_CLOSED; + } +#endif + + if (occurred_events->events != 0) + { + occurred_events->fd = cur_event->fd; + occurred_events++; + returned_events++; + } + } + } + return returned_events; +} + +#elif defined(WAIT_USE_WIN32) + +/* + * Wait using Windows' WaitForMultipleObjects(). Each call only "consumes" one + * event, so we keep calling until we've filled up our output buffer to match + * the behavior of the other implementations. + * + * https://blogs.msdn.microsoft.com/oldnewthing/20150409-00/?p=44273 + */ +static inline int +WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, + WaitEvent *occurred_events, int nevents) +{ + int returned_events = 0; + DWORD rc; + WaitEvent *cur_event; + + /* Reset any wait events that need it */ + for (cur_event = set->events; + cur_event < (set->events + set->nevents); + cur_event++) + { + if (cur_event->reset) + { + WaitEventAdjustWin32(set, cur_event); + cur_event->reset = false; + } + + /* + * We associate the socket with a new event handle for each + * WaitEventSet. FD_CLOSE is only generated once if the other end + * closes gracefully. Therefore we might miss the FD_CLOSE + * notification, if it was delivered to another event after we stopped + * waiting for it. Close that race by peeking for EOF after setting + * up this handle to receive notifications, and before entering the + * sleep. + * + * XXX If we had one event handle for the lifetime of a socket, we + * wouldn't need this. + */ + if (cur_event->events & WL_SOCKET_READABLE) + { + char c; + WSABUF buf; + DWORD received; + DWORD flags; + + buf.buf = &c; + buf.len = 1; + flags = MSG_PEEK; + if (WSARecv(cur_event->fd, &buf, 1, &received, &flags, NULL, NULL) == 0) + { + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = WL_SOCKET_READABLE; + occurred_events->fd = cur_event->fd; + return 1; + } + } + + /* + * Windows does not guarantee to log an FD_WRITE network event + * indicating that more data can be sent unless the previous send() + * failed with WSAEWOULDBLOCK. While our caller might well have made + * such a call, we cannot assume that here. Therefore, if waiting for + * write-ready, force the issue by doing a dummy send(). If the dummy + * send() succeeds, assume that the socket is in fact write-ready, and + * return immediately. Also, if it fails with something other than + * WSAEWOULDBLOCK, return a write-ready indication to let our caller + * deal with the error condition. + */ + if (cur_event->events & WL_SOCKET_WRITEABLE) + { + char c; + WSABUF buf; + DWORD sent; + int r; + + buf.buf = &c; + buf.len = 0; + + r = WSASend(cur_event->fd, &buf, 1, &sent, 0, NULL, NULL); + if (r == 0 || WSAGetLastError() != WSAEWOULDBLOCK) + { + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = WL_SOCKET_WRITEABLE; + occurred_events->fd = cur_event->fd; + return 1; + } + } + } + + /* + * Sleep. + * + * Need to wait for ->nevents + 1, because signal handle is in [0]. + */ + rc = WaitForMultipleObjects(set->nevents + 1, set->handles, FALSE, + cur_timeout); + + /* Check return code */ + if (rc == WAIT_FAILED) + elog(ERROR, "WaitForMultipleObjects() failed: error code %lu", + GetLastError()); + else if (rc == WAIT_TIMEOUT) + { + /* timeout exceeded */ + return -1; + } + + if (rc == WAIT_OBJECT_0) + { + /* Service newly-arrived signals */ + pgwin32_dispatch_queued_signals(); + return 0; /* retry */ + } + + /* + * With an offset of one, due to the always present pgwin32_signal_event, + * the handle offset directly corresponds to a wait event. + */ + cur_event = (WaitEvent *) &set->events[rc - WAIT_OBJECT_0 - 1]; + + for (;;) + { + int next_pos; + int count; + + occurred_events->pos = cur_event->pos; + occurred_events->user_data = cur_event->user_data; + occurred_events->events = 0; + + if (cur_event->events == WL_LATCH_SET) + { + /* + * We cannot use set->latch->event to reset the fired event if we + * aren't waiting on this latch now. + */ + if (!ResetEvent(set->handles[cur_event->pos + 1])) + elog(ERROR, "ResetEvent failed: error code %lu", GetLastError()); + + if (set->latch && set->latch->maybe_sleeping && set->latch->is_set) + { + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_LATCH_SET; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events == WL_POSTMASTER_DEATH) + { + /* + * Postmaster apparently died. Since the consequences of falsely + * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we + * take the trouble to positively verify this with + * PostmasterIsAlive(), even though there is no known reason to + * think that the event could be falsely set on Windows. + */ + if (!PostmasterIsAliveInternal()) + { + if (set->exit_on_postmaster_death) + proc_exit(1); + occurred_events->fd = PGINVALID_SOCKET; + occurred_events->events = WL_POSTMASTER_DEATH; + occurred_events++; + returned_events++; + } + } + else if (cur_event->events & WL_SOCKET_MASK) + { + WSANETWORKEVENTS resEvents; + HANDLE handle = set->handles[cur_event->pos + 1]; + + Assert(cur_event->fd); + + occurred_events->fd = cur_event->fd; + + ZeroMemory(&resEvents, sizeof(resEvents)); + if (WSAEnumNetworkEvents(cur_event->fd, handle, &resEvents) != 0) + elog(ERROR, "failed to enumerate network events: error code %d", + WSAGetLastError()); + if ((cur_event->events & WL_SOCKET_READABLE) && + (resEvents.lNetworkEvents & FD_READ)) + { + /* data available in socket */ + occurred_events->events |= WL_SOCKET_READABLE; + + /*------ + * WaitForMultipleObjects doesn't guarantee that a read event + * will be returned if the latch is set at the same time. Even + * if it did, the caller might drop that event expecting it to + * reoccur on next call. So, we must force the event to be + * reset if this WaitEventSet is used again in order to avoid + * an indefinite hang. + * + * Refer + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx + * for the behavior of socket events. + *------ + */ + cur_event->reset = true; + } + if ((cur_event->events & WL_SOCKET_WRITEABLE) && + (resEvents.lNetworkEvents & FD_WRITE)) + { + /* writeable */ + occurred_events->events |= WL_SOCKET_WRITEABLE; + } + if ((cur_event->events & WL_SOCKET_CONNECTED) && + (resEvents.lNetworkEvents & FD_CONNECT)) + { + /* connected */ + occurred_events->events |= WL_SOCKET_CONNECTED; + } + if ((cur_event->events & WL_SOCKET_ACCEPT) && + (resEvents.lNetworkEvents & FD_ACCEPT)) + { + /* incoming connection could be accepted */ + occurred_events->events |= WL_SOCKET_ACCEPT; + } + if (resEvents.lNetworkEvents & FD_CLOSE) + { + /* EOF/error, so signal all caller-requested socket flags */ + occurred_events->events |= (cur_event->events & WL_SOCKET_MASK); + } + + if (occurred_events->events != 0) + { + occurred_events++; + returned_events++; + } + } + + /* Is the output buffer full? */ + if (returned_events == nevents) + break; + + /* Have we run out of possible events? */ + next_pos = cur_event->pos + 1; + if (next_pos == set->nevents) + break; + + /* + * Poll the rest of the event handles in the array starting at + * next_pos being careful to skip over the initial signal handle too. + * This time we use a zero timeout. + */ + count = set->nevents - next_pos; + rc = WaitForMultipleObjects(count, + set->handles + 1 + next_pos, + false, + 0); + + /* + * We don't distinguish between errors and WAIT_TIMEOUT here because + * we already have events to report. + */ + if (rc < WAIT_OBJECT_0 || rc >= WAIT_OBJECT_0 + count) + break; + + /* We have another event to decode. */ + cur_event = &set->events[next_pos + (rc - WAIT_OBJECT_0)]; + } + + return returned_events; +} +#endif + +/* + * Return whether the current build options can report WL_SOCKET_CLOSED. + */ +bool +WaitEventSetCanReportClosed(void) +{ +#if (defined(WAIT_USE_POLL) && defined(POLLRDHUP)) || \ + defined(WAIT_USE_EPOLL) || \ + defined(WAIT_USE_KQUEUE) + return true; +#else + return false; +#endif +} + +/* + * Get the number of wait events registered in a given WaitEventSet. + */ +int +GetNumRegisteredWaitEvents(WaitEventSet *set) +{ + return set->nevents; +} + +#if defined(WAIT_USE_SELF_PIPE) + +/* + * SetLatch uses SIGURG to wake up the process waiting on the latch. + * + * Wake up WaitLatch, if we're waiting. + */ +static void +latch_sigurg_handler(SIGNAL_ARGS) +{ + if (waiting) + sendSelfPipeByte(); +} + +/* Send one byte to the self-pipe, to wake up WaitLatch */ +static void +sendSelfPipeByte(void) +{ + int rc; + char dummy = 0; + +retry: + rc = write(selfpipe_writefd, &dummy, 1); + if (rc < 0) + { + /* If interrupted by signal, just retry */ + if (errno == EINTR) + goto retry; + + /* + * If the pipe is full, we don't need to retry, the data that's there + * already is enough to wake up WaitLatch. + */ + if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + + /* + * Oops, the write() failed for some other reason. We might be in a + * signal handler, so it's not safe to elog(). We have no choice but + * silently ignore the error. + */ + return; + } +} + +#endif + +#if defined(WAIT_USE_SELF_PIPE) || defined(WAIT_USE_SIGNALFD) + +/* + * Read all available data from self-pipe or signalfd. + * + * Note: this is only called when waiting = true. If it fails and doesn't + * return, it must reset that flag first (though ideally, this will never + * happen). + */ +static void +drain(void) +{ + char buf[1024]; + int rc; + int fd; + +#ifdef WAIT_USE_SELF_PIPE + fd = selfpipe_readfd; +#else + fd = signal_fd; +#endif + + for (;;) + { + rc = read(fd, buf, sizeof(buf)); + if (rc < 0) + { + if (errno == EAGAIN || errno == EWOULDBLOCK) + break; /* the descriptor is empty */ + else if (errno == EINTR) + continue; /* retry */ + else + { + waiting = false; +#ifdef WAIT_USE_SELF_PIPE + elog(ERROR, "read() on self-pipe failed: %m"); +#else + elog(ERROR, "read() on signalfd failed: %m"); +#endif + } + } + else if (rc == 0) + { + waiting = false; +#ifdef WAIT_USE_SELF_PIPE + elog(ERROR, "unexpected EOF on self-pipe"); +#else + elog(ERROR, "unexpected EOF on signalfd"); +#endif + } + else if (rc < sizeof(buf)) + { + /* we successfully drained the pipe; no need to read() again */ + break; + } + /* else buffer wasn't big enough, so read again */ + } +} + +#endif + +static void +ResOwnerReleaseWaitEventSet(Datum res) +{ + WaitEventSet *set = (WaitEventSet *) DatumGetPointer(res); + + Assert(set->owner != NULL); + set->owner = NULL; + FreeWaitEventSet(set); +} + +#ifndef WIN32 +/* + * Wake up my process if it's currently sleeping in WaitEventSetWaitBlock() + * + * NB: be sure to save and restore errno around it. (That's standard practice + * in most signal handlers, of course, but we used to omit it in handlers that + * only set a flag.) XXX + * + * NB: this function is called from critical sections and signal handlers so + * throwing an error is not a good idea. + * + * On Windows, Latch uses SetEvent directly and this is not used. + */ +void +WakeupMyProc(void) +{ +#if defined(WAIT_USE_SELF_PIPE) + if (waiting) + sendSelfPipeByte(); +#else + if (waiting) + kill(MyProcPid, SIGURG); +#endif +} + +/* Similar to WakeupMyProc, but wake up another process */ +void +WakeupOtherProc(int pid) +{ + kill(pid, SIGURG); +} +#endif diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index f9510833241bb..68b76f2cc18a0 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -19,7 +19,7 @@ * memory context given to inv_open (for LargeObjectDesc structs). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -41,7 +41,6 @@ #include "catalog/indexing.h" #include "catalog/objectaccess.h" #include "catalog/pg_largeobject.h" -#include "catalog/pg_largeobject_metadata.h" #include "libpq/libpq-fs.h" #include "miscadmin.h" #include "storage/large_object.h" @@ -123,43 +122,6 @@ close_lo_relation(bool isCommit) } -/* - * Same as pg_largeobject.c's LargeObjectExists(), except snapshot to - * read with can be specified. - */ -static bool -myLargeObjectExists(Oid loid, Snapshot snapshot) -{ - Relation pg_lo_meta; - ScanKeyData skey[1]; - SysScanDesc sd; - HeapTuple tuple; - bool retval = false; - - ScanKeyInit(&skey[0], - Anum_pg_largeobject_metadata_oid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(loid)); - - pg_lo_meta = table_open(LargeObjectMetadataRelationId, - AccessShareLock); - - sd = systable_beginscan(pg_lo_meta, - LargeObjectMetadataOidIndexId, true, - snapshot, 1, skey); - - tuple = systable_getnext(sd); - if (HeapTupleIsValid(tuple)) - retval = true; - - systable_endscan(sd); - - table_close(pg_lo_meta, AccessShareLock); - - return retval; -} - - /* * Extract data field from a pg_largeobject tuple, detoasting if needed * and verifying that the length is sane. Returns data pointer (a bytea *), @@ -279,7 +241,7 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt) snapshot = GetActiveSnapshot(); /* Can't use LargeObjectExists here because we need to specify snapshot */ - if (!myLargeObjectExists(lobjId, snapshot)) + if (!LargeObjectExistsWithSnapshot(lobjId, snapshot)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("large object %u does not exist", lobjId))); diff --git a/src/backend/storage/large_object/meson.build b/src/backend/storage/large_object/meson.build index 0440af4f88282..1d94b44419255 100644 --- a/src/backend/storage/large_object/meson.build +++ b/src/backend/storage/large_object/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'inv_api.c', diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile index 3f89548bde68d..6cbaf23b855f6 100644 --- a/src/backend/storage/lmgr/Makefile +++ b/src/backend/storage/lmgr/Makefile @@ -21,7 +21,6 @@ OBJS = \ predicate.o \ proc.o \ s_lock.o \ - spin.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 112a518bae072..228303e77f7ca 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -8,7 +8,7 @@ * interrupted, unlike LWLock waits. Condition variables are safe * to use within dynamic shared memory segments. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/storage/lmgr/condition_variable.c diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c index fcb874d234f01..c4bfaaa67ac8c 100644 --- a/src/backend/storage/lmgr/deadlock.c +++ b/src/backend/storage/lmgr/deadlock.c @@ -7,7 +7,7 @@ * detection and resolution algorithms. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -30,6 +30,7 @@ #include "pgstat.h" #include "storage/lmgr.h" #include "storage/proc.h" +#include "storage/procnumber.h" #include "utils/memutils.h" @@ -191,6 +192,8 @@ InitDeadLockChecking(void) * last MaxBackends entries in possibleConstraints[] are reserved as * output workspace for FindLockCycle. */ + StaticAssertStmt(MAX_BACKENDS_BITS <= (32 - 3), + "MAX_BACKENDS_BITS too big for * 4"); maxPossibleConstraints = MaxBackends * 4; possibleConstraints = (EDGE *) palloc(maxPossibleConstraints * sizeof(EDGE)); diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl index eaddd9d3b976f..4441b7cba0c5f 100644 --- a/src/backend/storage/lmgr/generate-lwlocknames.pl +++ b/src/backend/storage/lmgr/generate-lwlocknames.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate lwlocknames.h from lwlocklist.h -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -107,7 +107,9 @@ $lastlockidx = $lockidx; $continue = ",\n"; - print $h "#define ${lockname}Lock (&MainLWLockArray[$lockidx].lock)\n"; + # Add a "Lock" suffix to each lock name, as the C code depends on that + printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n", + $lockname . "Lock"; } die diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 094522acb414d..3f6bf70bd3c24 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -3,7 +3,7 @@ * lmgr.c * POSTGRES lock manager code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -24,7 +24,6 @@ #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" -#include "storage/sinvaladt.h" #include "utils/inval.h" @@ -113,7 +112,8 @@ LockRelationOid(Oid relid, LOCKMODE lockmode) SetLocktagRelationOid(&tag, relid); - res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock, + false); /* * Now that we have the lock, check for invalidation messages, so that we @@ -156,7 +156,8 @@ ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode) SetLocktagRelationOid(&tag, relid); - res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock, + false); if (res == LOCKACQUIRE_NOT_AVAIL) return false; @@ -189,7 +190,8 @@ LockRelationId(LockRelId *relid, LOCKMODE lockmode) SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId); - res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock, + false); /* * Now that we have the lock, check for invalidation messages; see notes @@ -251,7 +253,8 @@ LockRelation(Relation relation, LOCKMODE lockmode) relation->rd_lockInfo.lockRelId.dbId, relation->rd_lockInfo.lockRelId.relId); - res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, false, true, &locallock, + false); /* * Now that we have the lock, check for invalidation messages; see notes @@ -282,7 +285,8 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode) relation->rd_lockInfo.lockRelId.dbId, relation->rd_lockInfo.lockRelId.relId); - res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock, + false); if (res == LOCKACQUIRE_NOT_AVAIL) return false; @@ -575,7 +579,8 @@ LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode) * Returns true iff the lock was acquired. */ bool -ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode) +ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode, + bool logLockFailure) { LOCKTAG tag; @@ -585,7 +590,8 @@ ConditionalLockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode) ItemPointerGetBlockNumber(tid), ItemPointerGetOffsetNumber(tid)); - return (LockAcquire(&tag, lockmode, false, true) != LOCKACQUIRE_NOT_AVAIL); + return (LockAcquireExtended(&tag, lockmode, false, true, true, NULL, + logLockFailure) != LOCKACQUIRE_NOT_AVAIL); } /* @@ -711,7 +717,10 @@ XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, * through, to avoid slowing down the normal case.) */ if (!first) + { + CHECK_FOR_INTERRUPTS(); pg_usleep(1000L); + } first = false; xid = SubTransGetTopmostTransaction(xid); } @@ -727,7 +736,7 @@ XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, * Returns true if the lock was acquired. */ bool -ConditionalXactLockTableWait(TransactionId xid) +ConditionalXactLockTableWait(TransactionId xid, bool logLockFailure) { LOCKTAG tag; bool first = true; @@ -739,7 +748,9 @@ ConditionalXactLockTableWait(TransactionId xid) SET_LOCKTAG_TRANSACTION(tag, xid); - if (LockAcquire(&tag, ShareLock, false, true) == LOCKACQUIRE_NOT_AVAIL) + if (LockAcquireExtended(&tag, ShareLock, false, true, true, NULL, + logLockFailure) + == LOCKACQUIRE_NOT_AVAIL) return false; LockRelease(&tag, ShareLock, false); @@ -749,7 +760,10 @@ ConditionalXactLockTableWait(TransactionId xid) /* See XactLockTableWait about this case */ if (!first) + { + CHECK_FOR_INTERRUPTS(); pg_usleep(1000L); + } first = false; xid = SubTransGetTopmostTransaction(xid); } @@ -1028,7 +1042,8 @@ ConditionalLockDatabaseObject(Oid classid, Oid objid, uint16 objsubid, objid, objsubid); - res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock, + false); if (res == LOCKACQUIRE_NOT_AVAIL) return false; @@ -1107,7 +1122,8 @@ ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid, objid, objsubid); - res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock); + res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock, + false); if (res == LOCKACQUIRE_NOT_AVAIL) return false; diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 0400a5077799f..2776ceb295be4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -3,7 +3,7 @@ * lock.c * POSTGRES primary lock mechanism * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -21,7 +21,7 @@ * * Interface: * - * InitLocks(), GetLocksMethodTable(), GetLockTagsMethodTable(), + * LockManagerShmemInit(), GetLocksMethodTable(), GetLockTagsMethodTable(), * LockAcquire(), LockRelease(), LockReleaseAll(), * LockCheckConflicts(), GrantLock() * @@ -39,9 +39,9 @@ #include "access/xlogutils.h" #include "miscadmin.h" #include "pg_trace.h" +#include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" -#include "storage/sinvaladt.h" #include "storage/spin.h" #include "storage/standby.h" #include "utils/memutils.h" @@ -49,8 +49,9 @@ #include "utils/resowner.h" -/* This configuration variable is used to set the lock table size */ -int max_locks_per_xact; /* set by guc.c */ +/* GUC variables */ +int max_locks_per_xact; /* used to set the lock table size */ +bool log_lock_failures = false; #define NLOCKENTS() \ mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts)) @@ -166,8 +167,13 @@ typedef struct TwoPhaseLockRecord * might be higher than the real number if another backend has transferred * our locks to the primary lock table, but it can never be lower than the * real value, since only we can acquire locks on our own behalf. + * + * XXX Allocate a static array of the maximum size. We could use a pointer + * and then allocate just the right size to save a couple kB, but then we + * would have to initialize that, while for the static array that happens + * automatically. Doesn't seem worth the extra complexity. */ -static int FastPathLocalUseCount = 0; +static int FastPathLocalUseCounts[FP_LOCK_GROUPS_PER_BACKEND_MAX]; /* * Flag to indicate if the relation extension lock is held by this backend. @@ -184,23 +190,71 @@ static int FastPathLocalUseCount = 0; */ static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY = false; +/* + * Number of fast-path locks per backend - size of the arrays in PGPROC. + * This is set only once during start, before initializing shared memory, + * and remains constant after that. + * + * We set the limit based on max_locks_per_transaction GUC, because that's + * the best information about expected number of locks per backend we have. + * See InitializeFastPathLocks() for details. + */ +int FastPathLockGroupsPerBackend = 0; + +/* + * Macros to calculate the fast-path group and index for a relation. + * + * The formula is a simple hash function, designed to spread the OIDs a bit, + * so that even contiguous values end up in different groups. In most cases + * there will be gaps anyway, but the multiplication should help a bit. + * + * The selected constant (49157) is a prime not too close to 2^k, and it's + * small enough to not cause overflows (in 64-bit). + * + * We can assume that FastPathLockGroupsPerBackend is a power-of-two per + * InitializeFastPathLocks(). + */ +#define FAST_PATH_REL_GROUP(rel) \ + (((uint64) (rel) * 49157) & (FastPathLockGroupsPerBackend - 1)) + +/* + * Given the group/slot indexes, calculate the slot index in the whole array + * of fast-path lock slots. + */ +#define FAST_PATH_SLOT(group, index) \ + (AssertMacro((uint32) (group) < FastPathLockGroupsPerBackend), \ + AssertMacro((uint32) (index) < FP_LOCK_SLOTS_PER_GROUP), \ + ((group) * FP_LOCK_SLOTS_PER_GROUP + (index))) + +/* + * Given a slot index (into the whole per-backend array), calculated using + * the FAST_PATH_SLOT macro, split it into group and index (in the group). + */ +#define FAST_PATH_GROUP(index) \ + (AssertMacro((uint32) (index) < FastPathLockSlotsPerBackend()), \ + ((index) / FP_LOCK_SLOTS_PER_GROUP)) +#define FAST_PATH_INDEX(index) \ + (AssertMacro((uint32) (index) < FastPathLockSlotsPerBackend()), \ + ((index) % FP_LOCK_SLOTS_PER_GROUP)) + /* Macros for manipulating proc->fpLockBits */ #define FAST_PATH_BITS_PER_SLOT 3 #define FAST_PATH_LOCKNUMBER_OFFSET 1 #define FAST_PATH_MASK ((1 << FAST_PATH_BITS_PER_SLOT) - 1) +#define FAST_PATH_BITS(proc, n) (proc)->fpLockBits[FAST_PATH_GROUP(n)] #define FAST_PATH_GET_BITS(proc, n) \ - (((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK) + ((FAST_PATH_BITS(proc, n) >> (FAST_PATH_BITS_PER_SLOT * FAST_PATH_INDEX(n))) & FAST_PATH_MASK) #define FAST_PATH_BIT_POSITION(n, l) \ (AssertMacro((l) >= FAST_PATH_LOCKNUMBER_OFFSET), \ AssertMacro((l) < FAST_PATH_BITS_PER_SLOT+FAST_PATH_LOCKNUMBER_OFFSET), \ - AssertMacro((n) < FP_LOCK_SLOTS_PER_BACKEND), \ - ((l) - FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT * (n))) + AssertMacro((n) < FastPathLockSlotsPerBackend()), \ + ((l) - FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT * (FAST_PATH_INDEX(n)))) #define FAST_PATH_SET_LOCKMODE(proc, n, l) \ - (proc)->fpLockBits |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l) + FAST_PATH_BITS(proc, n) |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l) #define FAST_PATH_CLEAR_LOCKMODE(proc, n, l) \ - (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)) + FAST_PATH_BITS(proc, n) &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)) #define FAST_PATH_CHECK_LOCKMODE(proc, n, l) \ - ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))) + (FAST_PATH_BITS(proc, n) & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))) /* * The fast-path lock mechanism is concerned only with relation locks on @@ -360,8 +414,7 @@ static PROCLOCK *SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner); static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode); static void FinishStrongLockAcquire(void); -static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner, - bool dontWait); +static ProcWaitStatus WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner); static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock); static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent); static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, @@ -377,19 +430,17 @@ static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, /* - * InitLocks -- Initialize the lock manager's data structures. + * Initialize the lock manager's shmem data structures. * - * This is called from CreateSharedMemoryAndSemaphores(), which see for - * more comments. In the normal postmaster case, the shared hash tables - * are created here, as well as a locallock hash table that will remain - * unused and empty in the postmaster itself. Backends inherit the pointers - * to the shared tables via fork(), and also inherit an image of the locallock - * hash table, which they proceed to use. In the EXEC_BACKEND case, each - * backend re-executes this code to obtain pointers to the already existing - * shared hash tables and to create its locallock hash table. + * This is called from CreateSharedMemoryAndSemaphores(), which see for more + * comments. In the normal postmaster case, the shared hash tables are + * created here, and backends inherit pointers to them via fork(). In the + * EXEC_BACKEND case, each backend re-executes this code to obtain pointers to + * the already existing shared hash tables. In either case, each backend must + * also call InitLockManagerAccess() to create the locallock hash table. */ void -InitLocks(void) +LockManagerShmemInit(void) { HASHCTL info; long init_table_size, @@ -398,7 +449,7 @@ InitLocks(void) /* * Compute init/max size to request for lock hashtables. Note these - * calculations must agree with LockShmemSize! + * calculations must agree with LockManagerShmemSize! */ max_table_size = NLOCKENTS(); init_table_size = max_table_size / 2; @@ -444,18 +495,19 @@ InitLocks(void) sizeof(FastPathStrongRelationLockData), &found); if (!found) SpinLockInit(&FastPathStrongRelationLocks->mutex); +} +/* + * Initialize the lock manager's backend-private data structures. + */ +void +InitLockManagerAccess(void) +{ /* * Allocate non-shared hash table for LOCALLOCK structs. This stores lock * counts and resource owner information. - * - * The non-shared table could already exist in this process (this occurs - * when the postmaster is recreating shared memory after a backend crash). - * If so, delete and recreate it. (We could simply leave it, since it - * ought to be empty in the postmaster, but for safety let's zap it.) */ - if (LockMethodLocalHash) - hash_destroy(LockMethodLocalHash); + HASHCTL info; info.keysize = sizeof(LOCALLOCKTAG); info.entrysize = sizeof(LOCALLOCK); @@ -503,7 +555,7 @@ GetLockTagsMethodTable(const LOCKTAG *locktag) uint32 LockTagHashCode(const LOCKTAG *locktag) { - return get_hash_value(LockMethodLockHash, (const void *) locktag); + return get_hash_value(LockMethodLockHash, locktag); } /* @@ -759,7 +811,7 @@ LockAcquire(const LOCKTAG *locktag, bool dontWait) { return LockAcquireExtended(locktag, lockmode, sessionLock, dontWait, - true, NULL); + true, NULL, false); } /* @@ -775,6 +827,9 @@ LockAcquire(const LOCKTAG *locktag, * * If locallockp isn't NULL, *locallockp receives a pointer to the LOCALLOCK * table entry if a lock is successfully acquired, or NULL if not. + * + * logLockFailure indicates whether to log details when a lock acquisition + * fails with dontWait = true. */ LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, @@ -782,7 +837,8 @@ LockAcquireExtended(const LOCKTAG *locktag, bool sessionLock, bool dontWait, bool reportMemoryError, - LOCALLOCK **locallockp) + LOCALLOCK **locallockp, + bool logLockFailure) { LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid; LockMethod lockMethodTable; @@ -795,6 +851,7 @@ LockAcquireExtended(const LOCKTAG *locktag, uint32 hashcode; LWLock *partitionLock; bool found_conflict; + ProcWaitStatus waitResult; bool log_lock = false; if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods)) @@ -927,7 +984,7 @@ LockAcquireExtended(const LOCKTAG *locktag, * for now we don't worry about that case either. */ if (EligibleForRelationFastPath(locktag, lockmode) && - FastPathLocalUseCount < FP_LOCK_SLOTS_PER_BACKEND) + FastPathLocalUseCounts[FAST_PATH_REL_GROUP(locktag->locktag_field2)] < FP_LOCK_SLOTS_PER_GROUP) { uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode); bool acquired; @@ -1043,36 +1100,124 @@ LockAcquireExtended(const LOCKTAG *locktag, { /* No conflict with held or previously requested locks */ GrantLock(lock, proclock, lockmode); - GrantLockLocal(locallock, owner); + waitResult = PROC_WAIT_STATUS_OK; } else { /* - * Set bitmask of locks this process already holds on this object. + * Join the lock's wait queue. We call this even in the dontWait + * case, because JoinWaitQueue() may discover that we can acquire the + * lock immediately after all. */ - MyProc->heldLocks = proclock->holdMask; + waitResult = JoinWaitQueue(locallock, lockMethodTable, dontWait); + } + if (waitResult == PROC_WAIT_STATUS_ERROR) + { /* - * Sleep till someone wakes me up. We do this even in the dontWait - * case, because while trying to go to sleep, we may discover that we - * can acquire the lock immediately after all. + * We're not getting the lock because a deadlock was detected already + * while trying to join the wait queue, or because we would have to + * wait but the caller requested no blocking. + * + * Undo the changes to shared entries before releasing the partition + * lock. */ + AbortStrongLockAcquire(); - TRACE_POSTGRESQL_LOCK_WAIT_START(locktag->locktag_field1, - locktag->locktag_field2, - locktag->locktag_field3, - locktag->locktag_field4, - locktag->locktag_type, - lockmode); + if (proclock->holdMask == 0) + { + uint32 proclock_hashcode; - WaitOnLock(locallock, owner, dontWait); + proclock_hashcode = ProcLockHashCode(&proclock->tag, + hashcode); + dlist_delete(&proclock->lockLink); + dlist_delete(&proclock->procLink); + if (!hash_search_with_hash_value(LockMethodProcLockHash, + &(proclock->tag), + proclock_hashcode, + HASH_REMOVE, + NULL)) + elog(PANIC, "proclock table corrupted"); + } + else + PROCLOCK_PRINT("LockAcquire: did not join wait queue", proclock); + lock->nRequested--; + lock->requested[lockmode]--; + LOCK_PRINT("LockAcquire: did not join wait queue", + lock, lockmode); + Assert((lock->nRequested > 0) && + (lock->requested[lockmode] >= 0)); + Assert(lock->nGranted <= lock->nRequested); + LWLockRelease(partitionLock); + if (locallock->nLocks == 0) + RemoveLocalLock(locallock); - TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1, - locktag->locktag_field2, - locktag->locktag_field3, - locktag->locktag_field4, - locktag->locktag_type, - lockmode); + if (dontWait) + { + /* + * Log lock holders and waiters as a detail log message if + * logLockFailure = true and lock acquisition fails with dontWait + * = true + */ + if (logLockFailure) + { + StringInfoData buf, + lock_waiters_sbuf, + lock_holders_sbuf; + const char *modename; + int lockHoldersNum = 0; + + initStringInfo(&buf); + initStringInfo(&lock_waiters_sbuf); + initStringInfo(&lock_holders_sbuf); + + DescribeLockTag(&buf, &locallock->tag.lock); + modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid, + lockmode); + + /* Gather a list of all lock holders and waiters */ + LWLockAcquire(partitionLock, LW_SHARED); + GetLockHoldersAndWaiters(locallock, &lock_holders_sbuf, + &lock_waiters_sbuf, &lockHoldersNum); + LWLockRelease(partitionLock); + + ereport(LOG, + (errmsg("process %d could not obtain %s on %s", + MyProcPid, modename, buf.data), + errdetail_log_plural( + "Process holding the lock: %s, Wait queue: %s.", + "Processes holding the lock: %s, Wait queue: %s.", + lockHoldersNum, + lock_holders_sbuf.data, + lock_waiters_sbuf.data))); + + pfree(buf.data); + pfree(lock_holders_sbuf.data); + pfree(lock_waiters_sbuf.data); + } + if (locallockp) + *locallockp = NULL; + return LOCKACQUIRE_NOT_AVAIL; + } + else + { + DeadLockReport(); + /* DeadLockReport() will not return */ + } + } + + /* + * We are now in the lock queue, or the lock was already granted. If + * queued, go to sleep. + */ + if (waitResult == PROC_WAIT_STATUS_WAITING) + { + Assert(!dontWait); + PROCLOCK_PRINT("LockAcquire: sleeping on lock", proclock); + LOCK_PRINT("LockAcquire: sleeping on lock", lock, lockmode); + LWLockRelease(partitionLock); + + waitResult = WaitOnLock(locallock, owner); /* * NOTE: do not do any material change of state between here and @@ -1080,68 +1225,24 @@ LockAcquireExtended(const LOCKTAG *locktag, * done when the lock was granted to us --- see notes in WaitOnLock. */ - /* - * Check the proclock entry status. If dontWait = true, this is an - * expected case; otherwise, it will only happen if something in the - * ipc communication doesn't work correctly. - */ - if (!(proclock->holdMask & LOCKBIT_ON(lockmode))) + if (waitResult == PROC_WAIT_STATUS_ERROR) { - AbortStrongLockAcquire(); - - if (dontWait) - { - /* - * We can't acquire the lock immediately. If caller specified - * no blocking, remove useless table entries and return - * LOCKACQUIRE_NOT_AVAIL without waiting. - */ - if (proclock->holdMask == 0) - { - uint32 proclock_hashcode; - - proclock_hashcode = ProcLockHashCode(&proclock->tag, - hashcode); - dlist_delete(&proclock->lockLink); - dlist_delete(&proclock->procLink); - if (!hash_search_with_hash_value(LockMethodProcLockHash, - &(proclock->tag), - proclock_hashcode, - HASH_REMOVE, - NULL)) - elog(PANIC, "proclock table corrupted"); - } - else - PROCLOCK_PRINT("LockAcquire: NOWAIT", proclock); - lock->nRequested--; - lock->requested[lockmode]--; - LOCK_PRINT("LockAcquire: conditional lock failed", - lock, lockmode); - Assert((lock->nRequested > 0) && - (lock->requested[lockmode] >= 0)); - Assert(lock->nGranted <= lock->nRequested); - LWLockRelease(partitionLock); - if (locallock->nLocks == 0) - RemoveLocalLock(locallock); - if (locallockp) - *locallockp = NULL; - return LOCKACQUIRE_NOT_AVAIL; - } - else - { - /* - * We should have gotten the lock, but somehow that didn't - * happen. If we get here, it's a bug. - */ - PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock); - LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode); - LWLockRelease(partitionLock); - elog(ERROR, "LockAcquire failed"); - } + /* + * We failed as a result of a deadlock, see CheckDeadLock(). Quit + * now. + */ + Assert(!dontWait); + DeadLockReport(); + /* DeadLockReport() will not return */ } - PROCLOCK_PRINT("LockAcquire: granted", proclock); - LOCK_PRINT("LockAcquire: granted", lock, lockmode); } + else + LWLockRelease(partitionLock); + Assert(waitResult == PROC_WAIT_STATUS_OK); + + /* The lock was granted to us. Update the local lock entry accordingly */ + Assert((proclock->holdMask & LOCKBIT_ON(lockmode)) != 0); + GrantLockLocal(locallock, owner); /* * Lock state is fully up-to-date now; if we error out after this, no @@ -1149,8 +1250,6 @@ LockAcquireExtended(const LOCKTAG *locktag, */ FinishStrongLockAcquire(); - LWLockRelease(partitionLock); - /* * Emit a WAL record if acquisition of this lock needs to be replayed in a * standby server. @@ -1274,7 +1373,7 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, * on our own behalf, in which case our group leader isn't changing * because the group leader for a process can only ever be changed by * the process itself; or else we are transferring a fast-path lock to - * the main lock table, in which case that process can't change it's + * the main lock table, in which case that process can't change its * lock group leader without first releasing all of its locks (and in * particular the one we are currently transferring). */ @@ -1791,6 +1890,24 @@ GrantAwaitedLock(void) GrantLockLocal(awaitedLock, awaitedOwner); } +/* + * GetAwaitedLock -- Return the lock we're currently doing WaitOnLock on. + */ +LOCALLOCK * +GetAwaitedLock(void) +{ + return awaitedLock; +} + +/* + * ResetAwaitedLock -- Forget that we are waiting on a lock. + */ +void +ResetAwaitedLock(void) +{ + awaitedLock = NULL; +} + /* * MarkLockClear -- mark an acquired lock as "clear" * @@ -1808,24 +1925,27 @@ MarkLockClear(LOCALLOCK *locallock) /* * WaitOnLock -- wait to acquire a lock * - * Caller must have set MyProc->heldLocks to reflect locks already held - * on the lockable object by this process. - * - * The appropriate partition lock must be held at entry, and will still be - * held at exit. + * This is a wrapper around ProcSleep, with extra tracing and bookkeeping. */ -static void -WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner, bool dontWait) +static ProcWaitStatus +WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner) { - LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD(*locallock); - LockMethod lockMethodTable = LockMethods[lockmethodid]; + ProcWaitStatus result; - LOCK_PRINT("WaitOnLock: sleeping on lock", - locallock->lock, locallock->tag.mode); + TRACE_POSTGRESQL_LOCK_WAIT_START(locallock->tag.lock.locktag_field1, + locallock->tag.lock.locktag_field2, + locallock->tag.lock.locktag_field3, + locallock->tag.lock.locktag_field4, + locallock->tag.lock.locktag_type, + locallock->tag.mode); /* adjust the process title to indicate that it's waiting */ set_ps_display_suffix("waiting"); + /* + * Record the fact that we are waiting for a lock, so that + * LockErrorCleanup will clean up if cancel/die happens. + */ awaitedLock = locallock; awaitedOwner = owner; @@ -1848,30 +1968,7 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner, bool dontWait) */ PG_TRY(); { - /* - * If dontWait = true, we handle success and failure in the same way - * here. The caller will be able to sort out what has happened. - */ - if (ProcSleep(locallock, lockMethodTable, dontWait) != PROC_WAIT_STATUS_OK - && !dontWait) - { - - /* - * We failed as a result of a deadlock, see CheckDeadLock(). Quit - * now. - */ - awaitedLock = NULL; - LOCK_PRINT("WaitOnLock: aborting on lock", - locallock->lock, locallock->tag.mode); - LWLockRelease(LockHashPartitionLock(locallock->hashcode)); - - /* - * Now that we aren't holding the partition lock, we can give an - * error report including details about the detected deadlock. - */ - DeadLockReport(); - /* not reached */ - } + result = ProcSleep(locallock); } PG_CATCH(); { @@ -1885,13 +1982,22 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner, bool dontWait) } PG_END_TRY(); + /* + * We no longer want LockErrorCleanup to do anything. + */ awaitedLock = NULL; /* reset ps display to remove the suffix */ set_ps_display_remove_suffix(); - LOCK_PRINT("WaitOnLock: wakeup on lock", - locallock->lock, locallock->tag.mode); + TRACE_POSTGRESQL_LOCK_WAIT_DONE(locallock->tag.lock.locktag_field1, + locallock->tag.lock.locktag_field2, + locallock->tag.lock.locktag_field3, + locallock->tag.lock.locktag_field4, + locallock->tag.lock.locktag_type, + locallock->tag.mode); + + return result; } /* @@ -2066,7 +2172,7 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock) /* Attempt fast release of any lock eligible for the fast path. */ if (EligibleForRelationFastPath(locktag, lockmode) && - FastPathLocalUseCount > 0) + FastPathLocalUseCounts[FAST_PATH_REL_GROUP(locktag->locktag_field2)] > 0) { bool released; @@ -2210,9 +2316,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL) { /* - * If the LOCALLOCK entry is unused, we must've run out of shared - * memory while trying to set up this lock. Just forget the local - * entry. + * If the LOCALLOCK entry is unused, something must've gone wrong + * while trying to acquire this lock. Just forget the local entry. */ if (locallock->nLocks == 0) { @@ -2256,6 +2361,16 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) locallock->numLockOwners = 0; } +#ifdef USE_ASSERT_CHECKING + + /* + * Tuple locks are currently held only for short durations within a + * transaction. Check that we didn't forget to release one. + */ + if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_TUPLE && !allLocks) + elog(WARNING, "tuple lock held at commit"); +#endif + /* * If the lock or proclock pointers are NULL, this lock was taken via * the relation fast-path (and is not known to have been transferred). @@ -2634,12 +2749,18 @@ LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent) static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode) { - uint32 f; - uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND; + uint32 i; + uint32 unused_slot = FastPathLockSlotsPerBackend(); + + /* fast-path group the lock belongs to */ + uint32 group = FAST_PATH_REL_GROUP(relid); /* Scan for existing entry for this relid, remembering empty slot. */ - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++) + for (i = 0; i < FP_LOCK_SLOTS_PER_GROUP; i++) { + /* index into the whole per-backend array */ + uint32 f = FAST_PATH_SLOT(group, i); + if (FAST_PATH_GET_BITS(MyProc, f) == 0) unused_slot = f; else if (MyProc->fpRelId[f] == relid) @@ -2651,11 +2772,11 @@ FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode) } /* If no existing entry, use any empty slot. */ - if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND) + if (unused_slot < FastPathLockSlotsPerBackend()) { MyProc->fpRelId[unused_slot] = relid; FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode); - ++FastPathLocalUseCount; + ++FastPathLocalUseCounts[group]; return true; } @@ -2671,12 +2792,18 @@ FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode) static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode) { - uint32 f; + uint32 i; bool result = false; - FastPathLocalUseCount = 0; - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++) + /* fast-path group the lock belongs to */ + uint32 group = FAST_PATH_REL_GROUP(relid); + + FastPathLocalUseCounts[group] = 0; + for (i = 0; i < FP_LOCK_SLOTS_PER_GROUP; i++) { + /* index into the whole per-backend array */ + uint32 f = FAST_PATH_SLOT(group, i); + if (MyProc->fpRelId[f] == relid && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode)) { @@ -2686,7 +2813,7 @@ FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode) /* we continue iterating so as to update FastPathLocalUseCount */ } if (FAST_PATH_GET_BITS(MyProc, f) != 0) - ++FastPathLocalUseCount; + ++FastPathLocalUseCounts[group]; } return result; } @@ -2706,6 +2833,9 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag Oid relid = locktag->locktag_field2; uint32 i; + /* fast-path group the lock belongs to */ + uint32 group = FAST_PATH_REL_GROUP(relid); + /* * Every PGPROC that can potentially hold a fast-path lock is present in * ProcGlobal->allProcs. Prepared transactions are not, but any @@ -2715,7 +2845,7 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag for (i = 0; i < ProcGlobal->allProcCount; i++) { PGPROC *proc = &ProcGlobal->allProcs[i]; - uint32 f; + uint32 j; LWLockAcquire(&proc->fpInfoLock, LW_EXCLUSIVE); @@ -2733,17 +2863,23 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag * less clear that our backend is certain to have performed a memory * fencing operation since the other backend set proc->databaseId. So * for now, we test it after acquiring the LWLock just to be safe. + * + * Also skip groups without any registered fast-path locks. */ - if (proc->databaseId != locktag->locktag_field1) + if (proc->databaseId != locktag->locktag_field1 || + proc->fpLockBits[group] == 0) { LWLockRelease(&proc->fpInfoLock); continue; } - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++) + for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) { uint32 lockmode; + /* index into the whole per-backend array */ + uint32 f = FAST_PATH_SLOT(group, j); + /* Look for an allocated slot matching the given relid. */ if (relid != proc->fpRelId[f] || FAST_PATH_GET_BITS(proc, f) == 0) continue; @@ -2794,14 +2930,21 @@ FastPathGetRelationLockEntry(LOCALLOCK *locallock) PROCLOCK *proclock = NULL; LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode); Oid relid = locktag->locktag_field2; - uint32 f; + uint32 i, + group; + + /* fast-path group the lock belongs to */ + group = FAST_PATH_REL_GROUP(relid); LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE); - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++) + for (i = 0; i < FP_LOCK_SLOTS_PER_GROUP; i++) { uint32 lockmode; + /* index into the whole per-backend array */ + uint32 f = FAST_PATH_SLOT(group, i); + /* Look for an allocated slot matching the given relid. */ if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0) continue; @@ -2945,6 +3088,9 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp) Oid relid = locktag->locktag_field2; VirtualTransactionId vxid; + /* fast-path group the lock belongs to */ + uint32 group = FAST_PATH_REL_GROUP(relid); + /* * Iterate over relevant PGPROCs. Anything held by a prepared * transaction will have been transferred to the primary lock table, @@ -2958,7 +3104,7 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp) for (i = 0; i < ProcGlobal->allProcCount; i++) { PGPROC *proc = &ProcGlobal->allProcs[i]; - uint32 f; + uint32 j; /* A backend never blocks itself */ if (proc == MyProc) @@ -2973,17 +3119,23 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp) * * See FastPathTransferRelationLocks() for discussion of why we do * this test after acquiring the lock. + * + * Also skip groups without any registered fast-path locks. */ - if (proc->databaseId != locktag->locktag_field1) + if (proc->databaseId != locktag->locktag_field1 || + proc->fpLockBits[group] == 0) { LWLockRelease(&proc->fpInfoLock); continue; } - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++) + for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) { uint32 lockmask; + /* index into the whole per-backend array */ + uint32 f = FAST_PATH_SLOT(group, j); + /* Look for an allocated slot matching the given relid. */ if (relid != proc->fpRelId[f]) continue; @@ -3571,7 +3723,7 @@ PostPrepare_Locks(TransactionId xid) * Estimate shared-memory space used for lock tables */ Size -LockShmemSize(void) +LockManagerShmemSize(void) { Size size = 0; long max_table_size; @@ -3639,44 +3791,55 @@ GetLockStatusData(void) for (i = 0; i < ProcGlobal->allProcCount; ++i) { PGPROC *proc = &ProcGlobal->allProcs[i]; - uint32 f; + + /* Skip backends with pid=0, as they don't hold fast-path locks */ + if (proc->pid == 0) + continue; LWLockAcquire(&proc->fpInfoLock, LW_SHARED); - for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f) + for (uint32 g = 0; g < FastPathLockGroupsPerBackend; g++) { - LockInstanceData *instance; - uint32 lockbits = FAST_PATH_GET_BITS(proc, f); - - /* Skip unallocated slots. */ - if (!lockbits) + /* Skip groups without registered fast-path locks */ + if (proc->fpLockBits[g] == 0) continue; - if (el >= els) + for (int j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) { - els += MaxBackends; - data->locks = (LockInstanceData *) - repalloc(data->locks, sizeof(LockInstanceData) * els); - } + LockInstanceData *instance; + uint32 f = FAST_PATH_SLOT(g, j); + uint32 lockbits = FAST_PATH_GET_BITS(proc, f); - instance = &data->locks[el]; - SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId, - proc->fpRelId[f]); - instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET; - instance->waitLockMode = NoLock; - instance->vxid.procNumber = proc->vxid.procNumber; - instance->vxid.localTransactionId = proc->vxid.lxid; - instance->pid = proc->pid; - instance->leaderPid = proc->pid; - instance->fastpath = true; + /* Skip unallocated slots */ + if (!lockbits) + continue; - /* - * Successfully taking fast path lock means there were no - * conflicting locks. - */ - instance->waitStart = 0; + if (el >= els) + { + els += MaxBackends; + data->locks = (LockInstanceData *) + repalloc(data->locks, sizeof(LockInstanceData) * els); + } - el++; + instance = &data->locks[el]; + SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId, + proc->fpRelId[f]); + instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET; + instance->waitLockMode = NoLock; + instance->vxid.procNumber = proc->vxid.procNumber; + instance->vxid.localTransactionId = proc->vxid.lxid; + instance->pid = proc->pid; + instance->leaderPid = proc->pid; + instance->fastpath = true; + + /* + * Successfully taking fast path lock means there were no + * conflicting locks. + */ + instance->waitStart = 0; + + el++; + } } if (proc->fpVXIDLock) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index e765754d80546..46f44bc45113f 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -20,7 +20,7 @@ * appropriate value for a free lock. The meaning of the variable is up to * the caller, the lightweight lock code just assigns and compares it. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -60,7 +60,7 @@ * The attentive reader might have noticed that naively doing the above has a * glaring race condition: We try to lock using the atomic operations and * notice that we have to wait. Unfortunately by the time we have finished - * queuing, the former locker very well might have already finished it's + * queuing, the former locker very well might have already finished its * work. That's problematic because we're now stuck waiting inside the OS. * To mitigate those races we use a two phased attempt at locking: @@ -80,9 +80,9 @@ #include "pg_trace.h" #include "pgstat.h" #include "port/pg_bitutils.h" -#include "postmaster/postmaster.h" #include "storage/proc.h" #include "storage/proclist.h" +#include "storage/procnumber.h" #include "storage/spin.h" #include "utils/memutils.h" @@ -91,24 +91,34 @@ #endif -#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 30) -#define LW_FLAG_RELEASE_OK ((uint32) 1 << 29) -#define LW_FLAG_LOCKED ((uint32) 1 << 28) +#define LW_FLAG_HAS_WAITERS ((uint32) 1 << 31) +#define LW_FLAG_RELEASE_OK ((uint32) 1 << 30) +#define LW_FLAG_LOCKED ((uint32) 1 << 29) +#define LW_FLAG_BITS 3 +#define LW_FLAG_MASK (((1< (uint32) MAX_BACKENDS, - "MAX_BACKENDS too big for lwlock.c"); + +StaticAssertDecl(((MAX_BACKENDS + 1) & MAX_BACKENDS) == 0, + "MAX_BACKENDS + 1 needs to be a power of 2"); + +StaticAssertDecl((MAX_BACKENDS & LW_FLAG_MASK) == 0, + "MAX_BACKENDS and LW_FLAG_MASK overlap"); + +StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0, + "LW_VAL_EXCLUSIVE and LW_FLAG_MASK overlap"); /* * There are three sorts of LWLock "tranches": * - * 1. The individually-named locks defined in lwlocknames.h each have their + * 1. The individually-named locks defined in lwlocklist.h each have their * own tranche. We absorb the names of these tranches from there into * BuiltinTrancheNames here. * @@ -124,7 +134,7 @@ StaticAssertDecl(LW_VAL_EXCLUSIVE > (uint32) MAX_BACKENDS, * ... and do not forget to update the documentation's list of wait events. */ static const char *const BuiltinTrancheNames[] = { -#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname) "Lock", +#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname), #include "storage/lwlocklist.h" #undef PG_LWLOCK [LWTRANCHE_XACT_BUFFER] = "XactBuffer", @@ -143,6 +153,7 @@ static const char *const BuiltinTrancheNames[] = { [LWTRANCHE_LOCK_MANAGER] = "LockManager", [LWTRANCHE_PREDICATE_LOCK_MANAGER] = "PredicateLockManager", [LWTRANCHE_PARALLEL_HASH_JOIN] = "ParallelHashJoin", + [LWTRANCHE_PARALLEL_BTREE_SCAN] = "ParallelBtreeScan", [LWTRANCHE_PARALLEL_QUERY_DSA] = "ParallelQueryDSA", [LWTRANCHE_PER_SESSION_DSA] = "PerSessionDSA", [LWTRANCHE_PER_SESSION_RECORD_TYPE] = "PerSessionRecordType", @@ -158,7 +169,7 @@ static const char *const BuiltinTrancheNames[] = { [LWTRANCHE_LAUNCHER_HASH] = "LogicalRepLauncherHash", [LWTRANCHE_DSM_REGISTRY_DSA] = "DSMRegistryDSA", [LWTRANCHE_DSM_REGISTRY_HASH] = "DSMRegistryHash", - [LWTRANCHE_COMMITTS_SLRU] = "CommitTSSLRU", + [LWTRANCHE_COMMITTS_SLRU] = "CommitTsSLRU", [LWTRANCHE_MULTIXACTOFFSET_SLRU] = "MultixactOffsetSLRU", [LWTRANCHE_MULTIXACTMEMBER_SLRU] = "MultixactMemberSLRU", [LWTRANCHE_NOTIFY_SLRU] = "NotifySLRU", @@ -166,6 +177,7 @@ static const char *const BuiltinTrancheNames[] = { [LWTRANCHE_SUBTRANS_SLRU] = "SubtransSLRU", [LWTRANCHE_XACT_SLRU] = "XactSLRU", [LWTRANCHE_PARALLEL_VACUUM_DSA] = "ParallelVacuumDSA", + [LWTRANCHE_AIO_URING_COMPLETION] = "AioUringCompletion", }; StaticAssertDecl(lengthof(BuiltinTrancheNames) == @@ -1775,14 +1787,25 @@ LWLockUpdateVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val) /* - * LWLockRelease - release a previously acquired lock + * Stop treating lock as held by current backend. + * + * This is the code that can be shared between actually releasing a lock + * (LWLockRelease()) and just not tracking ownership of the lock anymore + * without releasing the lock (LWLockDisown()). + * + * Returns the mode in which the lock was held by the current backend. + * + * NB: This does not call RESUME_INTERRUPTS(), but leaves that responsibility + * of the caller. + * + * NB: This will leave lock->owner pointing to the current backend (if + * LOCK_DEBUG is set). This is somewhat intentional, as it makes it easier to + * debug cases of missing wakeups during lock release. */ -void -LWLockRelease(LWLock *lock) +static inline LWLockMode +LWLockDisownInternal(LWLock *lock) { LWLockMode mode; - uint32 oldstate; - bool check_waiters; int i; /* @@ -1802,7 +1825,18 @@ LWLockRelease(LWLock *lock) for (; i < num_held_lwlocks; i++) held_lwlocks[i] = held_lwlocks[i + 1]; - PRINT_LWDEBUG("LWLockRelease", lock, mode); + return mode; +} + +/* + * Helper function to release lock, shared between LWLockRelease() and + * LWLockReleaseDisowned(). + */ +static void +LWLockReleaseInternal(LWLock *lock, LWLockMode mode) +{ + uint32 oldstate; + bool check_waiters; /* * Release my hold on lock, after that it can immediately be acquired by @@ -1840,6 +1874,38 @@ LWLockRelease(LWLock *lock) LOG_LWDEBUG("LWLockRelease", lock, "releasing waiters"); LWLockWakeup(lock); } +} + + +/* + * Stop treating lock as held by current backend. + * + * After calling this function it's the callers responsibility to ensure that + * the lock gets released (via LWLockReleaseDisowned()), even in case of an + * error. This only is desirable if the lock is going to be released in a + * different process than the process that acquired it. + */ +void +LWLockDisown(LWLock *lock) +{ + LWLockDisownInternal(lock); + + RESUME_INTERRUPTS(); +} + +/* + * LWLockRelease - release a previously acquired lock + */ +void +LWLockRelease(LWLock *lock) +{ + LWLockMode mode; + + mode = LWLockDisownInternal(lock); + + PRINT_LWDEBUG("LWLockRelease", lock, mode); + + LWLockReleaseInternal(lock, mode); /* * Now okay to allow cancel/die interrupts. @@ -1847,6 +1913,15 @@ LWLockRelease(LWLock *lock) RESUME_INTERRUPTS(); } +/* + * Release lock previously disowned with LWLockDisown(). + */ +void +LWLockReleaseDisowned(LWLock *lock, LWLockMode mode) +{ + LWLockReleaseInternal(lock, mode); +} + /* * LWLockReleaseClearVar - release a previously acquired lock, reset variable */ @@ -1884,6 +1959,21 @@ LWLockReleaseAll(void) } +/* + * ForEachLWLockHeldByMe - run a callback for each held lock + * + * This is meant as debug support only. + */ +void +ForEachLWLockHeldByMe(void (*callback) (LWLock *, LWLockMode, void *), + void *context) +{ + int i; + + for (i = 0; i < num_held_lwlocks; i++) + callback(held_lwlocks[i].lock, held_lwlocks[i].mode, context); +} + /* * LWLockHeldByMe - test whether my process holds a lock in any mode * diff --git a/src/backend/storage/lmgr/meson.build b/src/backend/storage/lmgr/meson.build index 05ac41e809a81..a5490c1047fae 100644 --- a/src/backend/storage/lmgr/meson.build +++ b/src/backend/storage/lmgr/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'condition_variable.c', @@ -9,5 +9,4 @@ backend_sources += files( 'predicate.c', 'proc.c', 's_lock.c', - 'spin.c', ) diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index b455b78f9f706..d82114ffca165 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -140,7 +140,7 @@ * SLRU per-bank locks * - Protects SerialSlruCtl * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -153,7 +153,7 @@ * INTERFACE ROUTINES * * housekeeping for setting up shared memory predicate lock structures - * InitPredicateLocks(void) + * PredicateLockShmemInit(void) * PredicateLockShmemSize(void) * * predicate lock reporting @@ -877,12 +877,17 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo) LWLockAcquire(SerialControlLock, LW_EXCLUSIVE); /* - * If no serializable transactions are active, there shouldn't be anything - * to push out to the SLRU. Hitting this assert would mean there's - * something wrong with the earlier cleanup logic. + * If 'xid' is older than the global xmin (== tailXid), there's no need to + * store it, after all. This can happen if the oldest transaction holding + * back the global xmin just finished, making 'xid' uninteresting, but + * ClearOldPredicateLocks() has not yet run. */ tailXid = serialControl->tailXid; - Assert(TransactionIdIsValid(tailXid)); + if (!TransactionIdIsValid(tailXid) || TransactionIdPrecedes(xid, tailXid)) + { + LWLockRelease(SerialControlLock); + return; + } /* * If the SLRU is currently unused, zero out the whole active region from @@ -1127,7 +1132,7 @@ CheckPointPredicate(void) /*------------------------------------------------------------------------*/ /* - * InitPredicateLocks -- Initialize the predicate locking data structures. + * PredicateLockShmemInit -- Initialize the predicate locking data structures. * * This is called from CreateSharedMemoryAndSemaphores(), which see for * more comments. In the normal postmaster case, the shared hash tables @@ -1137,7 +1142,7 @@ CheckPointPredicate(void) * shared hash tables. */ void -InitPredicateLocks(void) +PredicateLockShmemInit(void) { HASHCTL info; long max_table_size; @@ -1221,14 +1226,21 @@ InitPredicateLocks(void) */ max_table_size *= 10; + requestSize = add_size(PredXactListDataSize, + (mul_size((Size) max_table_size, + sizeof(SERIALIZABLEXACT)))); + PredXact = ShmemInitStruct("PredXactList", - PredXactListDataSize, + requestSize, &found); Assert(found == IsUnderPostmaster); if (!found) { int i; + /* clean everything, both the header and the element */ + memset(PredXact, 0, requestSize); + dlist_init(&PredXact->availableList); dlist_init(&PredXact->activeList); PredXact->SxactGlobalXmin = InvalidTransactionId; @@ -1237,11 +1249,9 @@ InitPredicateLocks(void) PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1; PredXact->CanPartialClearThrough = 0; PredXact->HavePartialClearedThrough = 0; - requestSize = mul_size((Size) max_table_size, - sizeof(SERIALIZABLEXACT)); - PredXact->element = ShmemAlloc(requestSize); + PredXact->element + = (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize); /* Add all elements to available list, clean. */ - memset(PredXact->element, 0, requestSize); for (i = 0; i < max_table_size; i++) { LWLockInitialize(&PredXact->element[i].perXactPredicateListLock, @@ -1295,20 +1305,25 @@ InitPredicateLocks(void) */ max_table_size *= 5; + requestSize = RWConflictPoolHeaderDataSize + + mul_size((Size) max_table_size, + RWConflictDataSize); + RWConflictPool = ShmemInitStruct("RWConflictPool", - RWConflictPoolHeaderDataSize, + requestSize, &found); Assert(found == IsUnderPostmaster); if (!found) { int i; + /* clean everything, including the elements */ + memset(RWConflictPool, 0, requestSize); + dlist_init(&RWConflictPool->availableList); - requestSize = mul_size((Size) max_table_size, - RWConflictDataSize); - RWConflictPool->element = ShmemAlloc(requestSize); + RWConflictPool->element = (RWConflict) ((char *) RWConflictPool + + RWConflictPoolHeaderDataSize); /* Add all elements to available list, clean. */ - memset(RWConflictPool->element, 0, requestSize); for (i = 0; i < max_table_size; i++) { dlist_push_tail(&RWConflictPool->availableList, diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 1b23efb26f35b..e9ef0fbfe32cb 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -3,7 +3,7 @@ * proc.c * routines to manage per-process shared memory data structure * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -14,7 +14,7 @@ */ /* * Interface (a): - * ProcSleep(), ProcWakeup(), + * JoinWaitQueue(), ProcSleep(), ProcWakeup() * * Waiting for a lock causes the backend to be put to sleep. Whoever releases * the lock wakes the process up again (and gives it an error code so it knows @@ -79,9 +79,6 @@ PROC_HDR *ProcGlobal = NULL; NON_EXEC_STATIC PGPROC *AuxiliaryProcs = NULL; PGPROC *PreparedXactProcs = NULL; -/* If we are waiting for a lock, this points to the associated LOCALLOCK */ -static LOCALLOCK *lockAwaited = NULL; - static DeadLockState deadlock_state = DS_NOT_YET_CHECKED; /* Is a deadlock check pending? */ @@ -93,6 +90,48 @@ static void AuxiliaryProcKill(int code, Datum arg); static void CheckDeadLock(void); +/* + * Report shared-memory space needed by PGPROC. + */ +static Size +PGProcShmemSize(void) +{ + Size size = 0; + Size TotalProcs = + add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); + + size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); + size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); + size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); + size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + + return size; +} + +/* + * Report shared-memory space needed by Fast-Path locks. + */ +static Size +FastPathLockShmemSize(void) +{ + Size size = 0; + Size TotalProcs = + add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); + Size fpLockBitsSize, + fpRelIdSize; + + /* + * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are + * nicely aligned in each backend. + */ + fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64)); + fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid)); + + size = add_size(size, mul_size(TotalProcs, (fpLockBitsSize + fpRelIdSize))); + + return size; +} + /* * Report shared-memory space needed by InitProcGlobal. */ @@ -100,17 +139,13 @@ Size ProcGlobalShmemSize(void) { Size size = 0; - Size TotalProcs = - add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts)); /* ProcGlobal */ size = add_size(size, sizeof(PROC_HDR)); - size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC))); size = add_size(size, sizeof(slock_t)); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates))); - size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags))); + size = add_size(size, PGProcShmemSize()); + size = add_size(size, FastPathLockShmemSize()); return size; } @@ -142,7 +177,7 @@ ProcGlobalSemas(void) * So, now we grab enough semaphores to support the desired max number * of backends immediately at initialization --- if the sysadmin has set * MaxConnections, max_worker_processes, max_wal_senders, or - * autovacuum_max_workers higher than his kernel will support, he'll + * autovacuum_worker_slots higher than his kernel will support, he'll * find out sooner rather than later. * * Another reason for creating semaphores here is that the semaphore @@ -162,6 +197,14 @@ InitProcGlobal(void) bool found; uint32 TotalProcs = MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts; + /* Used for setup of per-backend fast-path slots. */ + char *fpPtr, + *fpEndPtr PG_USED_FOR_ASSERTS_ONLY; + Size fpLockBitsSize, + fpRelIdSize; + Size requestSize; + char *ptr; + /* Create the ProcGlobal shared structure */ ProcGlobal = (PROC_HDR *) ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found); @@ -176,21 +219,31 @@ InitProcGlobal(void) dlist_init(&ProcGlobal->bgworkerFreeProcs); dlist_init(&ProcGlobal->walsenderFreeProcs); ProcGlobal->startupBufferPinWaitBufId = -1; - ProcGlobal->walwriterLatch = NULL; - ProcGlobal->checkpointerLatch = NULL; + ProcGlobal->walwriterProc = INVALID_PROC_NUMBER; + ProcGlobal->checkpointerProc = INVALID_PROC_NUMBER; pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER); pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER); /* * Create and initialize all the PGPROC structures we'll need. There are - * five separate consumers: (1) normal backends, (2) autovacuum workers - * and the autovacuum launcher, (3) background workers, (4) auxiliary - * processes, and (5) prepared transactions. Each PGPROC structure is - * dedicated to exactly one of these purposes, and they do not move - * between groups. + * six separate consumers: (1) normal backends, (2) autovacuum workers and + * special workers, (3) background workers, (4) walsenders, (5) auxiliary + * processes, and (6) prepared transactions. (For largely-historical + * reasons, we combine autovacuum and special workers into one category + * with a single freelist.) Each PGPROC structure is dedicated to exactly + * one of these purposes, and they do not move between groups. */ - procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); - MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); + requestSize = PGProcShmemSize(); + + ptr = ShmemInitStruct("PGPROC structures", + requestSize, + &found); + + MemSet(ptr, 0, requestSize); + + procs = (PGPROC *) ptr; + ptr = (char *) ptr + TotalProcs * sizeof(PGPROC); + ProcGlobal->allProcs = procs; /* XXX allProcCount isn't really all of them; it excludes prepared xacts */ ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS; @@ -202,13 +255,36 @@ InitProcGlobal(void) * XXX: It might make sense to increase padding for these arrays, given * how hotly they are accessed. */ - ProcGlobal->xids = - (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids)); - MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids)); - ProcGlobal->subxidStates = (XidCacheStatus *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->subxidStates)); - MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates)); - ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags)); - MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags)); + ProcGlobal->xids = (TransactionId *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->xids)); + + ProcGlobal->subxidStates = (XidCacheStatus *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates)); + + ProcGlobal->statusFlags = (uint8 *) ptr; + ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags)); + + /* make sure wer didn't overflow */ + Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize)); + + /* + * Allocate arrays for fast-path locks. Those are variable-length, so + * can't be included in PGPROC directly. We allocate a separate piece of + * shared memory and then divide that between backends. + */ + fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64)); + fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid)); + + requestSize = FastPathLockShmemSize(); + + fpPtr = ShmemInitStruct("Fast-Path Lock Array", + requestSize, + &found); + + MemSet(fpPtr, 0, requestSize); + + /* For asserts checking we did not overflow. */ + fpEndPtr = fpPtr + requestSize; for (i = 0; i < TotalProcs; i++) { @@ -216,6 +292,18 @@ InitProcGlobal(void) /* Common initialization for all PGPROCs, regardless of type. */ + /* + * Set the fast-path lock arrays, and move the pointer. We interleave + * the two arrays, to (hopefully) get some locality for each backend. + */ + proc->fpLockBits = (uint64 *) fpPtr; + fpPtr += fpLockBitsSize; + + proc->fpRelId = (Oid *) fpPtr; + fpPtr += fpRelIdSize; + + Assert(fpPtr <= fpEndPtr); + /* * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact * dummy PGPROCs don't need these though - they're never associated @@ -229,12 +317,13 @@ InitProcGlobal(void) } /* - * Newly created PGPROCs for normal backends, autovacuum and bgworkers - * must be queued up on the appropriate free list. Because there can - * only ever be a small, fixed number of auxiliary processes, no free - * list is used in that case; InitAuxiliaryProcess() instead uses a - * linear search. PGPROCs for prepared transactions are added to a - * free list by TwoPhaseShmemInit(). + * Newly created PGPROCs for normal backends, autovacuum workers, + * special workers, bgworkers, and walsenders must be queued up on the + * appropriate free list. Because there can only ever be a small, + * fixed number of auxiliary processes, no free list is used in that + * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs + * for prepared transactions are added to a free list by + * TwoPhaseShmemInit(). */ if (i < MaxConnections) { @@ -242,13 +331,13 @@ InitProcGlobal(void) dlist_push_tail(&ProcGlobal->freeProcs, &proc->links); proc->procgloballist = &ProcGlobal->freeProcs; } - else if (i < MaxConnections + autovacuum_max_workers + 1) + else if (i < MaxConnections + autovacuum_worker_slots + NUM_SPECIAL_WORKER_PROCS) { - /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */ + /* PGPROC for AV or special worker, add to autovacFreeProcs list */ dlist_push_tail(&ProcGlobal->autovacFreeProcs, &proc->links); proc->procgloballist = &ProcGlobal->autovacFreeProcs; } - else if (i < MaxConnections + autovacuum_max_workers + 1 + max_worker_processes) + else if (i < MaxConnections + autovacuum_worker_slots + NUM_SPECIAL_WORKER_PROCS + max_worker_processes) { /* PGPROC for bgworker, add to bgworkerFreeProcs list */ dlist_push_tail(&ProcGlobal->bgworkerFreeProcs, &proc->links); @@ -277,6 +366,9 @@ InitProcGlobal(void) pg_atomic_init_u64(&(proc->waitStart), 0); } + /* Should have consumed exactly the expected amount of fast-path memory. */ + Assert(fpPtr == fpEndPtr); + /* * Save pointers to the blocks of PGPROC structures reserved for auxiliary * processes and prepared transactions. @@ -285,7 +377,9 @@ InitProcGlobal(void) PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS]; /* Create ProcStructLock spinlock, too */ - ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); + ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock", + sizeof(slock_t), + &found); SpinLockInit(ProcStructLock); } @@ -307,8 +401,19 @@ InitProcess(void) if (MyProc != NULL) elog(ERROR, "you already exist"); - /* Decide which list should supply our PGPROC. */ - if (AmAutoVacuumLauncherProcess() || AmAutoVacuumWorkerProcess()) + /* + * Before we start accessing the shared memory in a serious way, mark + * ourselves as an active postmaster child; this is so that the postmaster + * can detect it if we exit without cleaning up. + */ + if (IsUnderPostmaster) + RegisterPostmasterChildActive(); + + /* + * Decide which list should supply our PGPROC. This logic must match the + * way the freelists were constructed in InitProcGlobal(). + */ + if (AmAutoVacuumWorkerProcess() || AmSpecialWorkerProcess()) procgloballist = &ProcGlobal->autovacFreeProcs; else if (AmBackgroundWorkerProcess()) procgloballist = &ProcGlobal->bgworkerFreeProcs; @@ -359,19 +464,6 @@ InitProcess(void) */ Assert(MyProc->procgloballist == procgloballist); - /* - * Now that we have a PGPROC, mark ourselves as an active postmaster - * child; this is so that the postmaster can detect it if we exit without - * cleaning up. (XXX autovac launcher currently doesn't participate in - * this; it probably should.) - * - * Slot sync worker also does not participate in it, see comments atop - * 'struct bkend' in postmaster.c. - */ - if (IsUnderPostmaster && !AmAutoVacuumLauncherProcess() && - !AmLogicalSlotSyncWorkerProcess()) - MarkPostmasterChildActive(); - /* * Initialize all fields of MyProc, except for those previously * initialized by InitProcGlobal. @@ -389,7 +481,7 @@ InitProcess(void) MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->tempNamespaceId = InvalidOid; - MyProc->isBackgroundWorker = AmBackgroundWorkerProcess(); + MyProc->isRegularBackend = AmRegularBackendProcess(); MyProc->delayChkptFlags = 0; MyProc->statusFlags = 0; /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */ @@ -535,6 +627,9 @@ InitAuxiliaryProcess(void) if (MyProc != NULL) elog(ERROR, "you already exist"); + if (IsUnderPostmaster) + RegisterPostmasterChildActive(); + /* * We use the ProcStructLock to protect assignment and releasing of * AuxiliaryProcs entries. @@ -585,7 +680,7 @@ InitAuxiliaryProcess(void) MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->tempNamespaceId = InvalidOid; - MyProc->isBackgroundWorker = AmBackgroundWorkerProcess(); + MyProc->isRegularBackend = false; MyProc->delayChkptFlags = 0; MyProc->statusFlags = 0; MyProc->lwWaiting = LW_WS_NOT_WAITING; @@ -706,18 +801,6 @@ HaveNFreeProcs(int n, int *nfree) return (*nfree == n); } -/* - * Check if the current process is awaiting a lock. - */ -bool -IsWaitingForLock(void) -{ - if (lockAwaited == NULL) - return false; - - return true; -} - /* * Cancel any pending wait for lock, when aborting a transaction, and revert * any strong lock count acquisition for a lock being acquired. @@ -729,6 +812,7 @@ IsWaitingForLock(void) void LockErrorCleanup(void) { + LOCALLOCK *lockAwaited; LWLock *partitionLock; DisableTimeoutParams timeouts[2]; @@ -737,6 +821,7 @@ LockErrorCleanup(void) AbortStrongLockAcquire(); /* Nothing to do if we weren't waiting for a lock */ + lockAwaited = GetAwaitedLock(); if (lockAwaited == NULL) { RESUME_INTERRUPTS(); @@ -778,7 +863,7 @@ LockErrorCleanup(void) GrantAwaitedLock(); } - lockAwaited = NULL; + ResetAwaitedLock(); LWLockRelease(partitionLock); @@ -941,18 +1026,6 @@ ProcKill(int code, Datum arg) SpinLockRelease(ProcStructLock); - /* - * This process is no longer present in shared memory in any meaningful - * way, so tell the postmaster we've cleaned up acceptably well. (XXX - * autovac launcher should be included here someday) - * - * Slot sync worker is also not a postmaster child, so skip this shared - * memory related processing here. - */ - if (IsUnderPostmaster && !AmAutoVacuumLauncherProcess() && - !AmLogicalSlotSyncWorkerProcess()) - MarkPostmasterChildInactive(); - /* wake autovac launcher if needed -- see comments in FreeWorkerInfo */ if (AutovacuumLauncherPid != 0) kill(AutovacuumLauncherPid, SIGUSR2); @@ -1038,10 +1111,7 @@ AuxiliaryPidGetProc(int pid) /* - * ProcSleep -- put a process to sleep on the specified lock - * - * Caller must have set MyProc->heldLocks to reflect locks already held - * on the lockable object by this process (under all XIDs). + * JoinWaitQueue -- join the wait queue on the specified lock * * It's not actually guaranteed that we need to wait when this function is * called, because it could be that when we try to find a position at which @@ -1050,37 +1120,47 @@ AuxiliaryPidGetProc(int pid) * we get the lock immediately. Because of this, it's sensible for this function * to have a dontWait argument, despite the name. * - * The lock table's partition lock must be held at entry, and will be held - * at exit. + * On entry, the caller has already set up LOCK and PROCLOCK entries to + * reflect that we have "requested" the lock. The caller is responsible for + * cleaning that up, if we end up not joining the queue after all. + * + * The lock table's partition lock must be held at entry, and is still held + * at exit. The caller must release it before calling ProcSleep(). * - * Result: PROC_WAIT_STATUS_OK if we acquired the lock, PROC_WAIT_STATUS_ERROR - * if not (if dontWait = true, we would have had to wait; if dontWait = false, - * this is a deadlock). + * Result is one of the following: * - * ASSUME: that no one will fiddle with the queue until after - * we release the partition lock. + * PROC_WAIT_STATUS_OK - lock was immediately granted + * PROC_WAIT_STATUS_WAITING - joined the wait queue; call ProcSleep() + * PROC_WAIT_STATUS_ERROR - immediate deadlock was detected, or would + * need to wait and dontWait == true * * NOTES: The process queue is now a priority queue for locking. */ ProcWaitStatus -ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) +JoinWaitQueue(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) { LOCKMODE lockmode = locallock->tag.mode; LOCK *lock = locallock->lock; PROCLOCK *proclock = locallock->proclock; uint32 hashcode = locallock->hashcode; - LWLock *partitionLock = LockHashPartitionLock(hashcode); + LWLock *partitionLock PG_USED_FOR_ASSERTS_ONLY = LockHashPartitionLock(hashcode); dclist_head *waitQueue = &lock->waitProcs; PGPROC *insert_before = NULL; - LOCKMASK myHeldLocks = MyProc->heldLocks; - TimestampTz standbyWaitStart = 0; + LOCKMASK myProcHeldLocks; + LOCKMASK myHeldLocks; bool early_deadlock = false; - bool allow_autovacuum_cancel = true; - bool logged_recovery_conflict = false; - ProcWaitStatus myWaitStatus; PGPROC *leader = MyProc->lockGroupLeader; + Assert(LWLockHeldByMeInMode(partitionLock, LW_EXCLUSIVE)); + /* + * Set bitmask of locks this process already holds on this object. + */ + myHeldLocks = MyProc->heldLocks = proclock->holdMask; + + /* + * Determine which locks we're already holding. + * * If group locking is in use, locks held by members of my locking group * need to be included in myHeldLocks. This is not required for relation * extension lock which conflict among group members. However, including @@ -1090,6 +1170,8 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) * that kind of locks, but there doesn't appear to be a clear advantage of * the same. */ + myProcHeldLocks = proclock->holdMask; + myHeldLocks = myProcHeldLocks; if (leader != NULL) { dlist_iter iter; @@ -1163,7 +1245,6 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) { /* Skip the wait and just grant myself the lock. */ GrantLock(lock, proclock, lockmode); - GrantAwaitedLock(); return PROC_WAIT_STATUS_OK; } @@ -1176,6 +1257,13 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) } } + /* + * If we detected deadlock, give up without waiting. This must agree with + * CheckDeadLock's recovery code. + */ + if (early_deadlock) + return PROC_WAIT_STATUS_ERROR; + /* * At this point we know that we'd really need to sleep. If we've been * commanded not to do that, bail out. @@ -1194,40 +1282,50 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) lock->waitMask |= LOCKBIT_ON(lockmode); /* Set up wait information in PGPROC object, too */ + MyProc->heldLocks = myProcHeldLocks; MyProc->waitLock = lock; MyProc->waitProcLock = proclock; MyProc->waitLockMode = lockmode; MyProc->waitStatus = PROC_WAIT_STATUS_WAITING; - /* - * If we detected deadlock, give up without waiting. This must agree with - * CheckDeadLock's recovery code. - */ - if (early_deadlock) - { - RemoveFromWaitQueue(MyProc, hashcode); - return PROC_WAIT_STATUS_ERROR; - } + return PROC_WAIT_STATUS_WAITING; +} - /* mark that we are waiting for a lock */ - lockAwaited = locallock; +/* + * ProcSleep -- put process to sleep waiting on lock + * + * This must be called when JoinWaitQueue() returns PROC_WAIT_STATUS_WAITING. + * Returns after the lock has been granted, or if a deadlock is detected. Can + * also bail out with ereport(ERROR), if some other error condition, or a + * timeout or cancellation is triggered. + * + * Result is one of the following: + * + * PROC_WAIT_STATUS_OK - lock was granted + * PROC_WAIT_STATUS_ERROR - a deadlock was detected + */ +ProcWaitStatus +ProcSleep(LOCALLOCK *locallock) +{ + LOCKMODE lockmode = locallock->tag.mode; + LOCK *lock = locallock->lock; + uint32 hashcode = locallock->hashcode; + LWLock *partitionLock = LockHashPartitionLock(hashcode); + TimestampTz standbyWaitStart = 0; + bool allow_autovacuum_cancel = true; + bool logged_recovery_conflict = false; + ProcWaitStatus myWaitStatus; - /* - * Release the lock table's partition lock. - * - * NOTE: this may also cause us to exit critical-section state, possibly - * allowing a cancel/die interrupt to be accepted. This is OK because we - * have recorded the fact that we are waiting for a lock, and so - * LockErrorCleanup will clean up if cancel/die happens. - */ - LWLockRelease(partitionLock); + /* The caller must've armed the on-error cleanup mechanism */ + Assert(GetAwaitedLock() == locallock); + Assert(!LWLockHeldByMe(partitionLock)); /* - * Also, now that we will successfully clean up after an ereport, it's - * safe to check to see if there's a buffer pin deadlock against the - * Startup process. Of course, that's only necessary if we're doing Hot - * Standby and are not the Startup process ourselves. + * Now that we will successfully clean up after an ereport, it's safe to + * check to see if there's a buffer pin deadlock against the Startup + * process. Of course, that's only necessary if we're doing Hot Standby + * and are not the Startup process ourselves. */ if (RecoveryInProgress() && !InRecovery) CheckRecoveryConflictDeadlock(); @@ -1467,10 +1565,6 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) long secs; int usecs; long msecs; - dlist_iter proc_iter; - PROCLOCK *curproclock; - bool first_holder = true, - first_waiter = true; int lockHoldersNum = 0; initStringInfo(&buf); @@ -1486,54 +1580,10 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) msecs = secs * 1000 + usecs / 1000; usecs = usecs % 1000; - /* - * we loop over the lock's procLocks to gather a list of all - * holders and waiters. Thus we will be able to provide more - * detailed information for lock debugging purposes. - * - * lock->procLocks contains all processes which hold or wait for - * this lock. - */ - + /* Gather a list of all lock holders and waiters */ LWLockAcquire(partitionLock, LW_SHARED); - - dlist_foreach(proc_iter, &lock->procLocks) - { - curproclock = - dlist_container(PROCLOCK, lockLink, proc_iter.cur); - - /* - * we are a waiter if myProc->waitProcLock == curproclock; we - * are a holder if it is NULL or something different - */ - if (curproclock->tag.myProc->waitProcLock == curproclock) - { - if (first_waiter) - { - appendStringInfo(&lock_waiters_sbuf, "%d", - curproclock->tag.myProc->pid); - first_waiter = false; - } - else - appendStringInfo(&lock_waiters_sbuf, ", %d", - curproclock->tag.myProc->pid); - } - else - { - if (first_holder) - { - appendStringInfo(&lock_holders_sbuf, "%d", - curproclock->tag.myProc->pid); - first_holder = false; - } - else - appendStringInfo(&lock_holders_sbuf, ", %d", - curproclock->tag.myProc->pid); - - lockHoldersNum++; - } - } - + GetLockHoldersAndWaiters(locallock, &lock_holders_sbuf, + &lock_waiters_sbuf, &lockHoldersNum); LWLockRelease(partitionLock); if (deadlock_state == DS_SOFT_DEADLOCK) @@ -1636,29 +1686,12 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait) standbyWaitStart, GetCurrentTimestamp(), NULL, false); - /* - * Re-acquire the lock table's partition lock. We have to do this to hold - * off cancel/die interrupts before we can mess with lockAwaited (else we - * might have a missed or duplicated locallock update). - */ - LWLockAcquire(partitionLock, LW_EXCLUSIVE); - - /* - * We no longer want LockErrorCleanup to do anything. - */ - lockAwaited = NULL; - - /* - * If we got the lock, be sure to remember it in the locallock table. - */ - if (MyProc->waitStatus == PROC_WAIT_STATUS_OK) - GrantAwaitedLock(); - /* * We don't have to do anything else, because the awaker did all the - * necessary update of the lock table and MyProc. + * necessary updates of the lock table and MyProc. (The caller is + * responsible for updating the local lock table.) */ - return MyProc->waitStatus; + return myWaitStatus; } @@ -1855,6 +1888,81 @@ CheckDeadLockAlert(void) errno = save_errno; } +/* + * GetLockHoldersAndWaiters - get lock holders and waiters for a lock + * + * Fill lock_holders_sbuf and lock_waiters_sbuf with the PIDs of processes holding + * and waiting for the lock, and set lockHoldersNum to the number of lock holders. + * + * The lock table's partition lock must be held on entry and remains held on exit. + */ +void +GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, + StringInfo lock_waiters_sbuf, int *lockHoldersNum) +{ + dlist_iter proc_iter; + PROCLOCK *curproclock; + LOCK *lock = locallock->lock; + bool first_holder = true, + first_waiter = true; + +#ifdef USE_ASSERT_CHECKING + { + uint32 hashcode = locallock->hashcode; + LWLock *partitionLock = LockHashPartitionLock(hashcode); + + Assert(LWLockHeldByMe(partitionLock)); + } +#endif + + *lockHoldersNum = 0; + + /* + * Loop over the lock's procLocks to gather a list of all holders and + * waiters. Thus we will be able to provide more detailed information for + * lock debugging purposes. + * + * lock->procLocks contains all processes which hold or wait for this + * lock. + */ + dlist_foreach(proc_iter, &lock->procLocks) + { + curproclock = + dlist_container(PROCLOCK, lockLink, proc_iter.cur); + + /* + * We are a waiter if myProc->waitProcLock == curproclock; we are a + * holder if it is NULL or something different. + */ + if (curproclock->tag.myProc->waitProcLock == curproclock) + { + if (first_waiter) + { + appendStringInfo(lock_waiters_sbuf, "%d", + curproclock->tag.myProc->pid); + first_waiter = false; + } + else + appendStringInfo(lock_waiters_sbuf, ", %d", + curproclock->tag.myProc->pid); + } + else + { + if (first_holder) + { + appendStringInfo(lock_holders_sbuf, "%d", + curproclock->tag.myProc->pid); + first_holder = false; + } + else + appendStringInfo(lock_holders_sbuf, ", %d", + curproclock->tag.myProc->pid); + + (*lockHoldersNum)++; + } + } +} + /* * ProcWaitForSignal - wait for a signal from another backend. * diff --git a/src/backend/storage/lmgr/s_lock.c b/src/backend/storage/lmgr/s_lock.c index cba48b3e778d7..d26e192f4bc5f 100644 --- a/src/backend/storage/lmgr/s_lock.c +++ b/src/backend/storage/lmgr/s_lock.c @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * * s_lock.c - * Hardware-dependent implementation of spinlocks. + * Implementation of spinlocks. * * When waiting for a contended spinlock we loop tightly for awhile, then * delay using pg_usleep() and try again. Preferably, "awhile" should be a @@ -36,7 +36,7 @@ * the probability of unintended failure) than to fix the total time * spent. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -51,7 +51,6 @@ #include #include "common/pg_prng.h" -#include "port/atomics.h" #include "storage/s_lock.h" #include "utils/wait_event.h" diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c deleted file mode 100644 index 50cb99cd3b67f..0000000000000 --- a/src/backend/storage/lmgr/spin.c +++ /dev/null @@ -1,180 +0,0 @@ -/*------------------------------------------------------------------------- - * - * spin.c - * Hardware-independent implementation of spinlocks. - * - * - * For machines that have test-and-set (TAS) instructions, s_lock.h/.c - * define the spinlock implementation. This file contains only a stub - * implementation for spinlocks using PGSemaphores. Unless semaphores - * are implemented in a way that doesn't involve a kernel call, this - * is too slow to be very useful :-( - * - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/storage/lmgr/spin.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "storage/pg_sema.h" -#include "storage/shmem.h" -#include "storage/spin.h" - - -#ifndef HAVE_SPINLOCKS - -/* - * No TAS, so spinlocks are implemented as PGSemaphores. - */ - -#ifndef HAVE_ATOMICS -#define NUM_EMULATION_SEMAPHORES (NUM_SPINLOCK_SEMAPHORES + NUM_ATOMICS_SEMAPHORES) -#else -#define NUM_EMULATION_SEMAPHORES (NUM_SPINLOCK_SEMAPHORES) -#endif /* HAVE_ATOMICS */ - -PGSemaphore *SpinlockSemaArray; - -#else /* !HAVE_SPINLOCKS */ - -#define NUM_EMULATION_SEMAPHORES 0 - -#endif /* HAVE_SPINLOCKS */ - -/* - * Report the amount of shared memory needed to store semaphores for spinlock - * support. - */ -Size -SpinlockSemaSize(void) -{ - return NUM_EMULATION_SEMAPHORES * sizeof(PGSemaphore); -} - -/* - * Report number of semaphores needed to support spinlocks. - */ -int -SpinlockSemas(void) -{ - return NUM_EMULATION_SEMAPHORES; -} - -#ifndef HAVE_SPINLOCKS - -/* - * Initialize spinlock emulation. - * - * This must be called after PGReserveSemaphores(). - */ -void -SpinlockSemaInit(void) -{ - PGSemaphore *spinsemas; - int nsemas = SpinlockSemas(); - int i; - - /* - * We must use ShmemAllocUnlocked(), since the spinlock protecting - * ShmemAlloc() obviously can't be ready yet. - */ - spinsemas = (PGSemaphore *) ShmemAllocUnlocked(SpinlockSemaSize()); - for (i = 0; i < nsemas; ++i) - spinsemas[i] = PGSemaphoreCreate(); - SpinlockSemaArray = spinsemas; -} - -/* - * s_lock.h hardware-spinlock emulation using semaphores - * - * We map all spinlocks onto NUM_EMULATION_SEMAPHORES semaphores. It's okay to - * map multiple spinlocks onto one semaphore because no process should ever - * hold more than one at a time. We just need enough semaphores so that we - * aren't adding too much extra contention from that. - * - * There is one exception to the restriction of only holding one spinlock at a - * time, which is that it's ok if emulated atomic operations are nested inside - * spinlocks. To avoid the danger of spinlocks and atomic using the same sema, - * we make sure "normal" spinlocks and atomics backed by spinlocks use - * distinct semaphores (see the nested argument to s_init_lock_sema). - * - * slock_t is just an int for this implementation; it holds the spinlock - * number from 1..NUM_EMULATION_SEMAPHORES. We intentionally ensure that 0 - * is not a valid value, so that testing with this code can help find - * failures to initialize spinlocks. - */ - -static inline void -s_check_valid(int lockndx) -{ - if (unlikely(lockndx <= 0 || lockndx > NUM_EMULATION_SEMAPHORES)) - elog(ERROR, "invalid spinlock number: %d", lockndx); -} - -void -s_init_lock_sema(volatile slock_t *lock, bool nested) -{ - static uint32 counter = 0; - uint32 offset; - uint32 sema_total; - uint32 idx; - - if (nested) - { - /* - * To allow nesting atomics inside spinlocked sections, use a - * different spinlock. See comment above. - */ - offset = 1 + NUM_SPINLOCK_SEMAPHORES; - sema_total = NUM_ATOMICS_SEMAPHORES; - } - else - { - offset = 1; - sema_total = NUM_SPINLOCK_SEMAPHORES; - } - - idx = (counter++ % sema_total) + offset; - - /* double check we did things correctly */ - s_check_valid(idx); - - *lock = idx; -} - -void -s_unlock_sema(volatile slock_t *lock) -{ - int lockndx = *lock; - - s_check_valid(lockndx); - - PGSemaphoreUnlock(SpinlockSemaArray[lockndx - 1]); -} - -bool -s_lock_free_sema(volatile slock_t *lock) -{ - /* We don't currently use S_LOCK_FREE anyway */ - elog(ERROR, "spin.c does not support S_LOCK_FREE()"); - return false; -} - -int -tas_sema(volatile slock_t *lock) -{ - int lockndx = *lock; - - s_check_valid(lockndx); - - /* Note that TAS macros return 0 if *success* */ - return !PGSemaphoreTryLock(SpinlockSemaArray[lockndx - 1]); -} - -#endif /* !HAVE_SPINLOCKS */ diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build index 739d13293fb0e..0cd48844f1d9b 100644 --- a/src/backend/storage/meson.build +++ b/src/backend/storage/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('aio') subdir('buffer') diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index be6f1f62d292f..dbb49ed9197d7 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -3,7 +3,7 @@ * bufpage.c * POSTGRES standard buffer page code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -61,7 +61,7 @@ PageInit(Page page, Size pageSize, Size specialSize) /* - * PageIsVerifiedExtended + * PageIsVerified * Check that the page header and checksum (if any) appear valid. * * This is called when a page has just been read in from disk. The idea is @@ -78,23 +78,30 @@ PageInit(Page page, Size pageSize, Size specialSize) * treat such a page as empty and without free space. Eventually, VACUUM * will clean up such a page and make it usable. * - * If flag PIV_LOG_WARNING is set, a WARNING is logged in the event of - * a checksum failure. + * If flag PIV_LOG_WARNING/PIV_LOG_LOG is set, a WARNING/LOG message is logged + * in the event of a checksum failure. * - * If flag PIV_REPORT_STAT is set, a checksum failure is reported directly - * to pgstat. + * If flag PIV_IGNORE_CHECKSUM_FAILURE is set, checksum failures will cause a + * message about the failure to be emitted, but will not cause + * PageIsVerified() to return false. + * + * To allow the caller to report statistics about checksum failures, + * *checksum_failure_p can be passed in. Note that there may be checksum + * failures even if this function returns true, due to + * PIV_IGNORE_CHECKSUM_FAILURE. */ bool -PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) +PageIsVerified(PageData *page, BlockNumber blkno, int flags, bool *checksum_failure_p) { - PageHeader p = (PageHeader) page; + const PageHeaderData *p = (const PageHeaderData *) page; size_t *pagebytes; - int i; bool checksum_failure = false; bool header_sane = false; - bool all_zeroes = false; uint16 checksum = 0; + if (checksum_failure_p) + *checksum_failure_p = false; + /* * Don't verify page data unless the page passes basic non-zero test */ @@ -102,10 +109,14 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) { if (DataChecksumsEnabled()) { - checksum = pg_checksum_page((char *) page, blkno); + checksum = pg_checksum_page(page, blkno); if (checksum != p->pd_checksum) + { checksum_failure = true; + if (checksum_failure_p) + *checksum_failure_p = true; + } } /* @@ -126,36 +137,24 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) } /* Check all-zeroes case */ - all_zeroes = true; pagebytes = (size_t *) page; - for (i = 0; i < (BLCKSZ / sizeof(size_t)); i++) - { - if (pagebytes[i] != 0) - { - all_zeroes = false; - break; - } - } - if (all_zeroes) + if (pg_memory_is_all_zeros(pagebytes, BLCKSZ)) return true; /* - * Throw a WARNING if the checksum fails, but only after we've checked for - * the all-zeroes case. + * Throw a WARNING/LOG, as instructed by PIV_LOG_*, if the checksum fails, + * but only after we've checked for the all-zeroes case. */ if (checksum_failure) { - if ((flags & PIV_LOG_WARNING) != 0) - ereport(WARNING, + if ((flags & (PIV_LOG_WARNING | PIV_LOG_LOG)) != 0) + ereport(flags & PIV_LOG_WARNING ? WARNING : LOG, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("page verification failed, calculated checksum %u but expected %u", checksum, p->pd_checksum))); - if ((flags & PIV_REPORT_STAT) != 0) - pgstat_report_checksum_failure(); - - if (header_sane && ignore_checksum_failure) + if (header_sane && (flags & PIV_IGNORE_CHECKSUM_FAILURE)) return true; } @@ -362,7 +361,7 @@ PageAddItemExtended(Page page, * The returned page is not initialized at all; caller must do that. */ Page -PageGetTempPage(Page page) +PageGetTempPage(const PageData *page) { Size pageSize; Page temp; @@ -379,7 +378,7 @@ PageGetTempPage(Page page) * The page is initialized by copying the contents of the given page. */ Page -PageGetTempPageCopy(Page page) +PageGetTempPageCopy(const PageData *page) { Size pageSize; Page temp; @@ -399,7 +398,7 @@ PageGetTempPageCopy(Page page) * given page, and the special space is copied from the given page. */ Page -PageGetTempPageCopySpecial(Page page) +PageGetTempPageCopySpecial(const PageData *page) { Size pageSize; Page temp; @@ -426,7 +425,7 @@ PageRestoreTempPage(Page tempPage, Page oldPage) Size pageSize; pageSize = PageGetPageSize(tempPage); - memcpy((char *) oldPage, (char *) tempPage, pageSize); + memcpy(oldPage, tempPage, pageSize); pfree(tempPage); } @@ -904,16 +903,16 @@ PageTruncateLinePointerArray(Page page) * PageGetHeapFreeSpace on heap pages. */ Size -PageGetFreeSpace(Page page) +PageGetFreeSpace(const PageData *page) { + const PageHeaderData *phdr = (const PageHeaderData *) page; int space; /* * Use signed arithmetic here so that we behave sensibly if pd_lower > * pd_upper. */ - space = (int) ((PageHeader) page)->pd_upper - - (int) ((PageHeader) page)->pd_lower; + space = (int) phdr->pd_upper - (int) phdr->pd_lower; if (space < (int) sizeof(ItemIdData)) return 0; @@ -931,16 +930,16 @@ PageGetFreeSpace(Page page) * PageGetHeapFreeSpace on heap pages. */ Size -PageGetFreeSpaceForMultipleTuples(Page page, int ntups) +PageGetFreeSpaceForMultipleTuples(const PageData *page, int ntups) { + const PageHeaderData *phdr = (const PageHeaderData *) page; int space; /* * Use signed arithmetic here so that we behave sensibly if pd_lower > * pd_upper. */ - space = (int) ((PageHeader) page)->pd_upper - - (int) ((PageHeader) page)->pd_lower; + space = (int) phdr->pd_upper - (int) phdr->pd_lower; if (space < (int) (ntups * sizeof(ItemIdData))) return 0; @@ -955,16 +954,16 @@ PageGetFreeSpaceForMultipleTuples(Page page, int ntups) * without any consideration for adding/removing line pointers. */ Size -PageGetExactFreeSpace(Page page) +PageGetExactFreeSpace(const PageData *page) { + const PageHeaderData *phdr = (const PageHeaderData *) page; int space; /* * Use signed arithmetic here so that we behave sensibly if pd_lower > * pd_upper. */ - space = (int) ((PageHeader) page)->pd_upper - - (int) ((PageHeader) page)->pd_lower; + space = (int) phdr->pd_upper - (int) phdr->pd_lower; if (space < 0) return 0; @@ -988,7 +987,7 @@ PageGetExactFreeSpace(Page page) * on the number of line pointers, we make this extra check.) */ Size -PageGetHeapFreeSpace(Page page) +PageGetHeapFreeSpace(const PageData *page) { Size space; @@ -1012,7 +1011,7 @@ PageGetHeapFreeSpace(Page page) */ for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum)) { - ItemId lp = PageGetItemId(page, offnum); + ItemId lp = PageGetItemId(unconstify(PageData *, page), offnum); if (!ItemIdIsUsed(lp)) break; @@ -1105,8 +1104,8 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum) ((char *) &phdr->pd_linp[offidx + 1] - (char *) phdr); if (nbytes > 0) - memmove((char *) &(phdr->pd_linp[offidx]), - (char *) &(phdr->pd_linp[offidx + 1]), + memmove(&(phdr->pd_linp[offidx]), + &(phdr->pd_linp[offidx + 1]), nbytes); /* @@ -1513,7 +1512,7 @@ PageSetChecksumCopy(Page page, BlockNumber blkno) /* If we don't need a checksum, just return the passed-in data */ if (PageIsNew(page) || !DataChecksumsEnabled()) - return (char *) page; + return page; /* * We allocate the copy space once and use it over on each subsequent @@ -1527,7 +1526,7 @@ PageSetChecksumCopy(Page page, BlockNumber blkno) PG_IO_ALIGN_SIZE, 0); - memcpy(pageCopy, (char *) page, BLCKSZ); + memcpy(pageCopy, page, BLCKSZ); ((PageHeader) pageCopy)->pd_checksum = pg_checksum_page(pageCopy, blkno); return pageCopy; } @@ -1545,5 +1544,5 @@ PageSetChecksumInplace(Page page, BlockNumber blkno) if (PageIsNew(page) || !DataChecksumsEnabled()) return; - ((PageHeader) page)->pd_checksum = pg_checksum_page((char *) page, blkno); + ((PageHeader) page)->pd_checksum = pg_checksum_page(page, blkno); } diff --git a/src/backend/storage/page/checksum.c b/src/backend/storage/page/checksum.c index 243878fe9e06f..c913459b5a375 100644 --- a/src/backend/storage/page/checksum.c +++ b/src/backend/storage/page/checksum.c @@ -3,7 +3,7 @@ * checksum.c * Checksum implementation for data pages. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,4 +19,4 @@ * external programs can incorporate the checksum code by #include'ing * that file from the exported Postgres headers. (Compare our CRC code.) */ -#include "storage/checksum_impl.h" +#include "storage/checksum_impl.h" /* IWYU pragma: keep */ diff --git a/src/backend/storage/page/itemptr.c b/src/backend/storage/page/itemptr.c index af21170307934..ad65821572194 100644 --- a/src/backend/storage/page/itemptr.c +++ b/src/backend/storage/page/itemptr.c @@ -3,7 +3,7 @@ * itemptr.c * POSTGRES disk item pointer code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/storage/page/meson.build b/src/backend/storage/page/meson.build index 8caba30bad7aa..c3e4a805862a9 100644 --- a/src/backend/storage/page/meson.build +++ b/src/backend/storage/page/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bufpage.c', diff --git a/src/backend/storage/smgr/bulk_write.c b/src/backend/storage/smgr/bulk_write.c index 4a10ece4c396b..b958be1571645 100644 --- a/src/backend/storage/smgr/bulk_write.c +++ b/src/backend/storage/smgr/bulk_write.c @@ -4,8 +4,10 @@ * Efficiently and reliably populate a new relation * * The assumption is that no other backends access the relation while we are - * loading it, so we can take some shortcuts. Do not mix operations through - * the regular buffer manager and the bulk loading interface! + * loading it, so we can take some shortcuts. Pages already present in the + * indicated fork when the bulk write operation is started are not modified + * unless explicitly written to. Do not mix operations through the regular + * buffer manager and the bulk loading interface! * * We bypass the buffer manager to avoid the locking overhead, and call * smgrextend() directly. A downside is that the pages will need to be @@ -23,7 +25,7 @@ * even if a checkpoint happens concurrently. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -36,7 +38,6 @@ #include "access/xloginsert.h" #include "access/xlogrecord.h" -#include "storage/bufmgr.h" #include "storage/bufpage.h" #include "storage/bulk_write.h" #include "storage/proc.h" @@ -45,7 +46,7 @@ #define MAX_PENDING_WRITES XLR_MAX_BLOCK_ID -static const PGIOAlignedBlock zero_buffer = {{0}}; /* worth BLCKSZ */ +static const PGIOAlignedBlock zero_buffer = {0}; /* worth BLCKSZ */ typedef struct PendingWrite { @@ -69,7 +70,7 @@ struct BulkWriteState PendingWrite pending_writes[MAX_PENDING_WRITES]; /* Current size of the relation */ - BlockNumber pages_written; + BlockNumber relsize; /* The RedoRecPtr at the time that the bulk operation started */ XLogRecPtr start_RedoRecPtr; @@ -106,7 +107,7 @@ smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal) state->use_wal = use_wal; state->npending = 0; - state->pages_written = 0; + state->relsize = smgrnblocks(smgr, forknum); state->start_RedoRecPtr = GetRedoRecPtr(); @@ -132,19 +133,69 @@ smgr_bulk_finish(BulkWriteState *bulkstate) smgr_bulk_flush(bulkstate); /* - * When we wrote out the pages, we passed skipFsync=true to avoid the - * overhead of registering all the writes with the checkpointer. Register - * the whole relation now. - * - * There is one hole in that idea: If a checkpoint occurred while we were - * writing the pages, it already missed fsyncing the pages we had written - * before the checkpoint started. A crash later on would replay the WAL - * starting from the checkpoint, therefore it wouldn't replay our earlier - * WAL records. So if a checkpoint started after the bulk write, fsync - * the files now. + * Fsync the relation, or register it for the next checkpoint, if + * necessary. */ - if (!SmgrIsTemp(bulkstate->smgr)) + if (SmgrIsTemp(bulkstate->smgr)) { + /* Temporary relations don't need to be fsync'd, ever */ + } + else if (!bulkstate->use_wal) + { + /*---------- + * This is either an unlogged relation, or a permanent relation but we + * skipped WAL-logging because wal_level=minimal: + * + * A) Unlogged relation + * + * Unlogged relations will go away on crash, but they need to be + * fsync'd on a clean shutdown. It's sufficient to call + * smgrregistersync(), that ensures that the checkpointer will + * flush it at the shutdown checkpoint. (It will flush it on the + * next online checkpoint too, which is not strictly necessary.) + * + * Note that the init-fork of an unlogged relation is not + * considered unlogged for our purposes. It's treated like a + * regular permanent relation. The callers will pass use_wal=true + * for the init fork. + * + * B) Permanent relation, WAL-logging skipped because wal_level=minimal + * + * This is a new relation, and we didn't WAL-log the pages as we + * wrote, but they need to be fsync'd before commit. + * + * We don't need to do that here, however. The fsync() is done at + * commit, by smgrDoPendingSyncs() (*). + * + * (*) smgrDoPendingSyncs() might decide to WAL-log the whole + * relation at commit instead of fsyncing it, if the relation was + * very small, but it's smgrDoPendingSyncs() responsibility in any + * case. + * + * We cannot distinguish the two here, so conservatively assume it's + * an unlogged relation. A permanent relation with wal_level=minimal + * would require no actions, see above. + */ + smgrregistersync(bulkstate->smgr, bulkstate->forknum); + } + else + { + /* + * Permanent relation, WAL-logged normally. + * + * We already WAL-logged all the pages, so they will be replayed from + * WAL on crash. However, when we wrote out the pages, we passed + * skipFsync=true to avoid the overhead of registering all the writes + * with the checkpointer. Register the whole relation now. + * + * There is one hole in that idea: If a checkpoint occurred while we + * were writing the pages, it already missed fsyncing the pages we had + * written before the checkpoint started. A crash later on would + * replay the WAL starting from the checkpoint, therefore it wouldn't + * replay our earlier WAL records. So if a checkpoint started after + * the bulk write, fsync the files now. + */ + /* * Prevent a checkpoint from starting between the GetRedoRecPtr() and * smgrregistersync() calls. @@ -230,7 +281,7 @@ smgr_bulk_flush(BulkWriteState *bulkstate) PageSetChecksumInplace(page, blkno); - if (blkno >= bulkstate->pages_written) + if (blkno >= bulkstate->relsize) { /* * If we have to write pages nonsequentially, fill in the space @@ -239,17 +290,18 @@ smgr_bulk_flush(BulkWriteState *bulkstate) * space will read as zeroes anyway), but it should help to avoid * fragmentation. The dummy pages aren't WAL-logged though. */ - while (blkno > bulkstate->pages_written) + while (blkno > bulkstate->relsize) { /* don't set checksum for all-zero page */ smgrextend(bulkstate->smgr, bulkstate->forknum, - bulkstate->pages_written++, + bulkstate->relsize, &zero_buffer, true); + bulkstate->relsize++; } smgrextend(bulkstate->smgr, bulkstate->forknum, blkno, page, true); - bulkstate->pages_written = pending_writes[i].blkno + 1; + bulkstate->relsize++; } else smgrwrite(bulkstate->smgr, bulkstate->forknum, blkno, page, true); diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 6796756358f34..2ccb0faceb5b6 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -10,7 +10,7 @@ * It doesn't matter whether the bits are on spinning rust or some other * storage technology. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -31,6 +31,7 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" +#include "storage/aio.h" #include "storage/bufmgr.h" #include "storage/fd.h" #include "storage/md.h" @@ -106,18 +107,30 @@ static MemoryContext MdCxt; /* context for all MdfdVec objects */ #define EXTENSION_CREATE (1 << 2) /* create new segments if needed during recovery */ #define EXTENSION_CREATE_RECOVERY (1 << 3) -/* - * Allow opening segments which are preceded by segments smaller than - * RELSEG_SIZE, e.g. inactive segments (see above). Note that this breaks - * mdnblocks() and related functionality henceforth - which currently is ok, - * because this is only required in the checkpointer which never uses - * mdnblocks(). - */ -#define EXTENSION_DONT_CHECK_SIZE (1 << 4) /* don't try to open a segment, if not already open */ #define EXTENSION_DONT_OPEN (1 << 5) +/* + * Fixed-length string to represent paths to files that need to be built by + * md.c. + * + * The maximum number of segments is MaxBlockNumber / RELSEG_SIZE, where + * RELSEG_SIZE can be set to 1 (for testing only). + */ +#define SEGMENT_CHARS OIDCHARS +#define MD_PATH_STR_MAXLEN \ + (\ + REL_PATH_STR_MAXLEN \ + + sizeof((char)'.') \ + + SEGMENT_CHARS \ + ) +typedef struct MdPathStr +{ + char str[MD_PATH_STR_MAXLEN + 1]; +} MdPathStr; + + /* local routines */ static void mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo); @@ -131,8 +144,8 @@ static void register_forget_request(RelFileLocatorBackend rlocator, ForkNumber f static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg); -static char *_mdfd_segpath(SMgrRelation reln, ForkNumber forknum, - BlockNumber segno); +static MdPathStr _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, + BlockNumber segno); static MdfdVec *_mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno, int oflags); static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forknum, @@ -140,6 +153,15 @@ static MdfdVec *_mdfd_getseg(SMgrRelation reln, ForkNumber forknum, static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg); +static PgAioResult md_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data); +static void md_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel); + +const PgAioHandleCallbacks aio_md_readv_cb = { + .complete_shared = md_readv_complete, + .report = md_readv_report, +}; + + static inline int _mdfd_open_flags(void) { @@ -190,7 +212,7 @@ void mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) { MdfdVec *mdfd; - char *path; + RelPathStr path; File fd; if (isRedo && reln->md_num_open_segs[forknum] > 0) @@ -213,26 +235,24 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) path = relpath(reln->smgr_rlocator, forknum); - fd = PathNameOpenFile(path, _mdfd_open_flags() | O_CREAT | O_EXCL); + fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL); if (fd < 0) { int save_errno = errno; if (isRedo) - fd = PathNameOpenFile(path, _mdfd_open_flags()); + fd = PathNameOpenFile(path.str, _mdfd_open_flags()); if (fd < 0) { /* be sure to report the error reported by create, not open */ errno = save_errno; ereport(ERROR, (errcode_for_file_access(), - errmsg("could not create file \"%s\": %m", path))); + errmsg("could not create file \"%s\": %m", path.str))); } } - pfree(path); - _fdvec_resize(reln, forknum, 1); mdfd = &reln->md_seg_fds[forknum][0]; mdfd->mdfd_vfd = fd; @@ -343,7 +363,7 @@ do_truncate(const char *path) static void mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) { - char *path; + RelPathStr path; int ret; int save_errno; @@ -359,7 +379,7 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) if (!RelFileLocatorBackendIsTemp(rlocator)) { /* Prevent other backends' fds from holding on to the disk space */ - ret = do_truncate(path); + ret = do_truncate(path.str); /* Forget any pending sync requests for the first segment */ save_errno = errno; @@ -372,13 +392,13 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) /* Next unlink the file, unless it was already found to be missing */ if (ret >= 0 || errno != ENOENT) { - ret = unlink(path); + ret = unlink(path.str); if (ret < 0 && errno != ENOENT) { save_errno = errno; ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", path))); + errmsg("could not remove file \"%s\": %m", path.str))); errno = save_errno; } } @@ -386,7 +406,7 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) else { /* Prevent other backends' fds from holding on to the disk space */ - ret = do_truncate(path); + ret = do_truncate(path.str); /* Register request to unlink first segment later */ save_errno = errno; @@ -408,12 +428,12 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) */ if (ret >= 0 || errno != ENOENT) { - char *segpath = (char *) palloc(strlen(path) + 12); + MdPathStr segpath; BlockNumber segno; for (segno = 1;; segno++) { - sprintf(segpath, "%s.%u", path, segno); + sprintf(segpath.str, "%s.%u", path.str, segno); if (!RelFileLocatorBackendIsTemp(rlocator)) { @@ -421,7 +441,7 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) * Prevent other backends' fds from holding on to the disk * space. We're done if we see ENOENT, though. */ - if (do_truncate(segpath) < 0 && errno == ENOENT) + if (do_truncate(segpath.str) < 0 && errno == ENOENT) break; /* @@ -431,20 +451,17 @@ mdunlinkfork(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo) register_forget_request(rlocator, forknum, segno); } - if (unlink(segpath) < 0) + if (unlink(segpath.str) < 0) { /* ENOENT is expected after the last segment... */ if (errno != ENOENT) ereport(WARNING, (errcode_for_file_access(), - errmsg("could not remove file \"%s\": %m", segpath))); + errmsg("could not remove file \"%s\": %m", segpath.str))); break; } } - pfree(segpath); } - - pfree(path); } /* @@ -483,7 +500,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend file \"%s\" beyond %u blocks", - relpath(reln->smgr_rlocator, forknum), + relpath(reln->smgr_rlocator, forknum).str, InvalidBlockNumber))); v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE); @@ -545,7 +562,7 @@ mdzeroextend(SMgrRelation reln, ForkNumber forknum, ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot extend file \"%s\" beyond %u blocks", - relpath(reln->smgr_rlocator, forknum), + relpath(reln->smgr_rlocator, forknum).str, InvalidBlockNumber))); while (remblocks > 0) @@ -637,7 +654,7 @@ static MdfdVec * mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior) { MdfdVec *mdfd; - char *path; + RelPathStr path; File fd; /* No work if already open */ @@ -646,23 +663,18 @@ mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior) path = relpath(reln->smgr_rlocator, forknum); - fd = PathNameOpenFile(path, _mdfd_open_flags()); + fd = PathNameOpenFile(path.str, _mdfd_open_flags()); if (fd < 0) { if ((behavior & EXTENSION_RETURN_NULL) && FILE_POSSIBLY_DELETED(errno)) - { - pfree(path); return NULL; - } ereport(ERROR, (errcode_for_file_access(), - errmsg("could not open file \"%s\": %m", path))); + errmsg("could not open file \"%s\": %m", path.str))); } - pfree(path); - _fdvec_resize(reln, forknum, 1); mdfd = &reln->md_seg_fds[forknum][0]; mdfd->mdfd_vfd = fd; @@ -803,6 +815,21 @@ buffers_to_iovec(struct iovec *iov, void **buffers, int nblocks) return iovcnt; } +/* + * mdmaxcombine() -- Return the maximum number of total blocks that can be + * combined with an IO starting at blocknum. + */ +uint32 +mdmaxcombine(SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum) +{ + BlockNumber segoff; + + segoff = blocknum % ((BlockNumber) RELSEG_SIZE); + + return RELSEG_SIZE - segoff; +} + /* * mdreadv() -- Read the specified blocks from a relation. */ @@ -833,6 +860,9 @@ mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE))); nblocks_this_segment = Min(nblocks_this_segment, lengthof(iov)); + if (nblocks_this_segment != nblocks) + elog(ERROR, "read crosses segment boundary"); + iovcnt = buffers_to_iovec(iov, buffers, nblocks_this_segment); size_this_segment = nblocks_this_segment * BLCKSZ; transferred_this_segment = 0; @@ -880,9 +910,30 @@ mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, * is ON or we are InRecovery, we should instead return zeroes * without complaining. This allows, for example, the case of * trying to update a block that was later truncated away. + * + * NB: We think that this codepath is unreachable in recovery + * and incomplete with zero_damaged_pages, as missing segments + * are not created. Putting blocks into the buffer-pool that + * do not exist on disk is rather problematic, as it will not + * be found by scans that rely on smgrnblocks(), as they are + * beyond EOF. It also can cause weird problems with relation + * extension, as relation extension does not expect blocks + * beyond EOF to exist. + * + * Therefore we do not want to copy the logic into + * mdstartreadv(), where it would have to be more complicated + * due to potential differences in the zero_damaged_pages + * setting between the definer and completor of IO. + * + * For PG 18, we are putting an Assert(false) in mdreadv() + * (triggering failures in assertion-enabled builds, but + * continuing to work in production builds). Afterwards we + * plan to remove this code entirely. */ if (zero_damaged_pages || InRecovery) { + Assert(false); /* see comment above */ + for (BlockNumber i = transferred_this_segment / BLCKSZ; i < nblocks_this_segment; ++i) @@ -917,6 +968,76 @@ mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, } } +/* + * mdstartreadv() -- Asynchronous version of mdreadv(). + */ +void +mdstartreadv(PgAioHandle *ioh, + SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, + void **buffers, BlockNumber nblocks) +{ + off_t seekpos; + MdfdVec *v; + BlockNumber nblocks_this_segment; + struct iovec *iov; + int iovcnt; + int ret; + + v = _mdfd_getseg(reln, forknum, blocknum, false, + EXTENSION_FAIL | EXTENSION_CREATE_RECOVERY); + + seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); + + Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE); + + nblocks_this_segment = + Min(nblocks, + RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE))); + + if (nblocks_this_segment != nblocks) + elog(ERROR, "read crossing segment boundary"); + + iovcnt = pgaio_io_get_iovec(ioh, &iov); + + Assert(nblocks <= iovcnt); + + iovcnt = buffers_to_iovec(iov, buffers, nblocks_this_segment); + + Assert(iovcnt <= nblocks_this_segment); + + if (!(io_direct_flags & IO_DIRECT_DATA)) + pgaio_io_set_flag(ioh, PGAIO_HF_BUFFERED); + + pgaio_io_set_target_smgr(ioh, + reln, + forknum, + blocknum, + nblocks, + false); + pgaio_io_register_callbacks(ioh, PGAIO_HCB_MD_READV, 0); + + ret = FileStartReadV(ioh, v->mdfd_vfd, iovcnt, seekpos, WAIT_EVENT_DATA_FILE_READ); + if (ret != 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not start reading blocks %u..%u in file \"%s\": %m", + blocknum, + blocknum + nblocks_this_segment - 1, + FilePathName(v->mdfd_vfd)))); + + /* + * The error checks corresponding to the post-read checks in mdreadv() are + * in md_readv_complete(). + * + * However we chose, at least for now, to not implement the + * zero_damaged_pages logic present in mdreadv(). As outlined in mdreadv() + * that logic is rather problematic, and we want to get rid of it. Here + * equivalent logic would have to be more complicated due to potential + * differences in the zero_damaged_pages setting between the definer and + * completor of IO. + */ +} + /* * mdwritev() -- Write the supplied blocks at the appropriate location. * @@ -956,6 +1077,9 @@ mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE))); nblocks_this_segment = Min(nblocks_this_segment, lengthof(iov)); + if (nblocks_this_segment != nblocks) + elog(ERROR, "write crosses segment boundary"); + iovcnt = buffers_to_iovec(iov, (void **) buffers, nblocks_this_segment); size_this_segment = nblocks_this_segment * BLCKSZ; transferred_this_segment = 0; @@ -1141,19 +1265,21 @@ mdnblocks(SMgrRelation reln, ForkNumber forknum) /* * mdtruncate() -- Truncate relation to specified number of blocks. + * + * Guaranteed not to allocate memory, so it can be used in a critical section. + * Caller must have called smgrnblocks() to obtain curnblk while holding a + * sufficient lock to prevent a change in relation size, and not used any smgr + * functions for this relation or handled interrupts in between. This makes + * sure we have opened all active segments, so that truncate loop will get + * them all! */ void -mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) +mdtruncate(SMgrRelation reln, ForkNumber forknum, + BlockNumber curnblk, BlockNumber nblocks) { - BlockNumber curnblk; BlockNumber priorblocks; int curopensegs; - /* - * NOTE: mdnblocks makes sure we have opened all active segments, so that - * truncation loop will get them all! - */ - curnblk = mdnblocks(reln, forknum); if (nblocks > curnblk) { /* Bogus request ... but no complaint if InRecovery */ @@ -1161,7 +1287,7 @@ mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) return; ereport(ERROR, (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now", - relpath(reln->smgr_rlocator, forknum), + relpath(reln->smgr_rlocator, forknum).str, nblocks, curnblk))); } if (nblocks == curnblk) @@ -1340,6 +1466,21 @@ mdimmedsync(SMgrRelation reln, ForkNumber forknum) } } +int +mdfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off) +{ + MdfdVec *v = mdopenfork(reln, forknum, EXTENSION_FAIL); + + v = _mdfd_getseg(reln, forknum, blocknum, false, + EXTENSION_FAIL); + + *off = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); + + Assert(*off < (off_t) BLCKSZ * RELSEG_SIZE); + + return FileGetRawDesc(v->mdfd_vfd); +} + /* * register_dirty_segment() -- Mark a relation segment as needing fsync * @@ -1386,7 +1527,7 @@ register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg) * backend fsyncs. */ pgstat_count_io_op_time(IOOBJECT_RELATION, IOCONTEXT_NORMAL, - IOOP_FSYNC, io_start, 1); + IOOP_FSYNC, io_start, 1, 0); } } @@ -1492,7 +1633,7 @@ _fdvec_resize(SMgrRelation reln, reln->md_seg_fds[forknum] = MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg); } - else + else if (nseg > reln->md_num_open_segs[forknum]) { /* * It doesn't seem worthwhile complicating the code to amortize @@ -1504,6 +1645,16 @@ _fdvec_resize(SMgrRelation reln, repalloc(reln->md_seg_fds[forknum], sizeof(MdfdVec) * nseg); } + else + { + /* + * We don't reallocate a smaller array, because we want mdtruncate() + * to be able to promise that it won't allocate memory, so that it is + * allowed in a critical section. This means that a bit of space in + * the array is now wasted, until the next time we add a segment and + * reallocate. + */ + } reln->md_num_open_segs[forknum] = nseg; } @@ -1512,21 +1663,18 @@ _fdvec_resize(SMgrRelation reln, * Return the filename for the specified segment of the relation. The * returned string is palloc'd. */ -static char * +static MdPathStr _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno) { - char *path, - *fullpath; + RelPathStr path; + MdPathStr fullpath; path = relpath(reln->smgr_rlocator, forknum); if (segno > 0) - { - fullpath = psprintf("%s.%u", path, segno); - pfree(path); - } + sprintf(fullpath.str, "%s.%u", path.str, segno); else - fullpath = path; + strcpy(fullpath.str, path.str); return fullpath; } @@ -1541,14 +1689,12 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno, { MdfdVec *v; File fd; - char *fullpath; + MdPathStr fullpath; fullpath = _mdfd_segpath(reln, forknum, segno); /* open the file */ - fd = PathNameOpenFile(fullpath, _mdfd_open_flags() | oflags); - - pfree(fullpath); + fd = PathNameOpenFile(fullpath.str, _mdfd_open_flags() | oflags); if (fd < 0) return NULL; @@ -1662,14 +1808,12 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno, } flags = O_CREAT; } - else if (!(behavior & EXTENSION_DONT_CHECK_SIZE) && - nblocks < ((BlockNumber) RELSEG_SIZE)) + else if (nblocks < ((BlockNumber) RELSEG_SIZE)) { /* - * When not extending (or explicitly including truncated - * segments), only open the next segment if the current one is - * exactly RELSEG_SIZE. If not (this branch), either return NULL - * or fail. + * When not extending, only open the next segment if the current + * one is exactly RELSEG_SIZE. If not (this branch), either + * return NULL or fail. */ if (behavior & EXTENSION_RETURN_NULL) { @@ -1686,7 +1830,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno, ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\" (target block %u): previous segment is only %u blocks", - _mdfd_segpath(reln, forknum, nextsegno), + _mdfd_segpath(reln, forknum, nextsegno).str, blkno, nblocks))); } @@ -1700,7 +1844,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno, ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\" (target block %u): %m", - _mdfd_segpath(reln, forknum, nextsegno), + _mdfd_segpath(reln, forknum, nextsegno).str, blkno))); } } @@ -1751,11 +1895,10 @@ mdsyncfiletag(const FileTag *ftag, char *path) } else { - char *p; + MdPathStr p; p = _mdfd_segpath(reln, ftag->forknum, ftag->segno); - strlcpy(path, p, MAXPGPATH); - pfree(p); + strlcpy(path, p.str, MD_PATH_STR_MAXLEN); file = PathNameOpenFile(path, _mdfd_open_flags()); if (file < 0) @@ -1773,7 +1916,7 @@ mdsyncfiletag(const FileTag *ftag, char *path) FileClose(file); pgstat_count_io_op_time(IOOBJECT_RELATION, IOCONTEXT_NORMAL, - IOOP_FSYNC, io_start, 1); + IOOP_FSYNC, io_start, 1, 0); errno = save_errno; return result; @@ -1788,12 +1931,11 @@ mdsyncfiletag(const FileTag *ftag, char *path) int mdunlinkfiletag(const FileTag *ftag, char *path) { - char *p; + RelPathStr p; /* Compute the path. */ p = relpathperm(ftag->rlocator, MAIN_FORKNUM); - strlcpy(path, p, MAXPGPATH); - pfree(p); + strlcpy(path, p.str, MAXPGPATH); /* Try to unlink the file. */ return unlink(path); @@ -1815,3 +1957,111 @@ mdfiletagmatches(const FileTag *ftag, const FileTag *candidate) */ return ftag->rlocator.dbOid == candidate->rlocator.dbOid; } + +/* + * AIO completion callback for mdstartreadv(). + */ +static PgAioResult +md_readv_complete(PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_data) +{ + PgAioTargetData *td = pgaio_io_get_target_data(ioh); + PgAioResult result = prior_result; + + if (prior_result.result < 0) + { + result.status = PGAIO_RS_ERROR; + result.id = PGAIO_HCB_MD_READV; + /* For "hard" errors, track the error number in error_data */ + result.error_data = -prior_result.result; + result.result = 0; + + /* + * Immediately log a message about the IO error, but only to the + * server log. The reason to do so immediately is that the originator + * might not process the query result immediately (because it is busy + * doing another part of query processing) or at all (e.g. if it was + * cancelled or errored out due to another IO also failing). The + * definer of the IO will emit an ERROR when processing the IO's + * results + */ + pgaio_result_report(result, td, LOG_SERVER_ONLY); + + return result; + } + + /* + * As explained above smgrstartreadv(), the smgr API operates on the level + * of blocks, rather than bytes. Convert. + */ + result.result /= BLCKSZ; + + Assert(result.result <= td->smgr.nblocks); + + if (result.result == 0) + { + /* consider 0 blocks read a failure */ + result.status = PGAIO_RS_ERROR; + result.id = PGAIO_HCB_MD_READV; + result.error_data = 0; + + /* see comment above the "hard error" case */ + pgaio_result_report(result, td, LOG_SERVER_ONLY); + + return result; + } + + if (result.status != PGAIO_RS_ERROR && + result.result < td->smgr.nblocks) + { + /* partial reads should be retried at upper level */ + result.status = PGAIO_RS_PARTIAL; + result.id = PGAIO_HCB_MD_READV; + } + + return result; +} + +/* + * AIO error reporting callback for mdstartreadv(). + * + * Errors are encoded as follows: + * - PgAioResult.error_data != 0 encodes IO that failed with that errno + * - PgAioResult.error_data == 0 encodes IO that didn't read all data + */ +static void +md_readv_report(PgAioResult result, const PgAioTargetData *td, int elevel) +{ + RelPathStr path; + + path = relpathbackend(td->smgr.rlocator, + td->smgr.is_temp ? MyProcNumber : INVALID_PROC_NUMBER, + td->smgr.forkNum); + + if (result.error_data != 0) + { + /* for errcode_for_file_access() and %m */ + errno = result.error_data; + + ereport(elevel, + errcode_for_file_access(), + errmsg("could not read blocks %u..%u in file \"%s\": %m", + td->smgr.blockNum, + td->smgr.blockNum + td->smgr.nblocks - 1, + path.str)); + } + else + { + /* + * NB: This will typically only be output in debug messages, while + * retrying a partial IO. + */ + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + errmsg("could not read blocks %u..%u in file \"%s\": read only %zu of %zu bytes", + td->smgr.blockNum, + td->smgr.blockNum + td->smgr.nblocks - 1, + path.str, + result.result * (size_t) BLCKSZ, + td->smgr.nblocks * (size_t) BLCKSZ)); + } +} diff --git a/src/backend/storage/smgr/meson.build b/src/backend/storage/smgr/meson.build index 6d91b18fe6792..9288e35a8529c 100644 --- a/src/backend/storage/smgr/meson.build +++ b/src/backend/storage/smgr/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'bulk_write.c', diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index a691aed1f405f..bce37a36d51ba 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -40,7 +40,19 @@ * themselves, as there could pointers to them in active use. See * smgrrelease() and smgrreleaseall(). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * NB: We need to hold interrupts across most of the functions in this file, + * as otherwise interrupt processing, e.g. due to a < ERROR elog/ereport, can + * trigger procsignal processing, which in turn can trigger + * smgrreleaseall(). Most of the relevant code is not reentrant. It seems + * better to put the HOLD_INTERRUPTS()/RESUME_INTERRUPTS() here, instead of + * trying to push them down to md.c where possible: For one, every smgr + * implementation would be vulnerable, for another, a good bit of smgr.c code + * itself is affected too. Eventually we might want a more targeted solution, + * allowing e.g. a networked smgr implementation to be interrupted, but many + * other, more complicated, problems would need to be fixed for that to be + * viable (e.g. smgr.c is often called with interrupts already held). + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -53,6 +65,8 @@ #include "access/xlogutils.h" #include "lib/ilist.h" +#include "miscadmin.h" +#include "storage/aio.h" #include "storage/bufmgr.h" #include "storage/ipc.h" #include "storage/md.h" @@ -88,9 +102,15 @@ typedef struct f_smgr BlockNumber blocknum, int nblocks, bool skipFsync); bool (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks); + uint32 (*smgr_maxcombine) (SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum); void (*smgr_readv) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks); + void (*smgr_startreadv) (PgAioHandle *ioh, + SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum, + void **buffers, BlockNumber nblocks); void (*smgr_writev) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void **buffers, BlockNumber nblocks, @@ -99,9 +119,10 @@ typedef struct f_smgr BlockNumber blocknum, BlockNumber nblocks); BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum); void (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum, - BlockNumber nblocks); + BlockNumber old_blocks, BlockNumber nblocks); void (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum); void (*smgr_registersync) (SMgrRelation reln, ForkNumber forknum); + int (*smgr_fd) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off); } f_smgr; static const f_smgr smgrsw[] = { @@ -117,13 +138,16 @@ static const f_smgr smgrsw[] = { .smgr_extend = mdextend, .smgr_zeroextend = mdzeroextend, .smgr_prefetch = mdprefetch, + .smgr_maxcombine = mdmaxcombine, .smgr_readv = mdreadv, + .smgr_startreadv = mdstartreadv, .smgr_writev = mdwritev, .smgr_writeback = mdwriteback, .smgr_nblocks = mdnblocks, .smgr_truncate = mdtruncate, .smgr_immedsync = mdimmedsync, .smgr_registersync = mdregistersync, + .smgr_fd = mdfd, } }; @@ -141,6 +165,16 @@ static dlist_head unpinned_relns; static void smgrshutdown(int code, Datum arg); static void smgrdestroy(SMgrRelation reln); +static void smgr_aio_reopen(PgAioHandle *ioh); +static char *smgr_aio_describe_identity(const PgAioTargetData *sd); + + +const PgAioTargetInfo aio_smgr_target_info = { + .name = "smgr", + .reopen = smgr_aio_reopen, + .describe_identity = smgr_aio_describe_identity, +}; + /* * smgrinit(), smgrshutdown() -- Initialize or shut down storage @@ -155,12 +189,16 @@ smgrinit(void) { int i; + HOLD_INTERRUPTS(); + for (i = 0; i < NSmgr; i++) { if (smgrsw[i].smgr_init) smgrsw[i].smgr_init(); } + RESUME_INTERRUPTS(); + /* register the shutdown proc */ on_proc_exit(smgrshutdown, 0); } @@ -173,11 +211,15 @@ smgrshutdown(int code, Datum arg) { int i; + HOLD_INTERRUPTS(); + for (i = 0; i < NSmgr; i++) { if (smgrsw[i].smgr_shutdown) smgrsw[i].smgr_shutdown(); } + + RESUME_INTERRUPTS(); } /* @@ -203,6 +245,8 @@ smgropen(RelFileLocator rlocator, ProcNumber backend) Assert(RelFileNumberIsValid(rlocator.relNumber)); + HOLD_INTERRUPTS(); + if (SMgrRelationHash == NULL) { /* First time through: initialize the hash table */ @@ -231,14 +275,16 @@ smgropen(RelFileLocator rlocator, ProcNumber backend) reln->smgr_cached_nblocks[i] = InvalidBlockNumber; reln->smgr_which = 0; /* we only have md.c at present */ - /* implementation-specific initialization */ - smgrsw[reln->smgr_which].smgr_open(reln); - /* it is not pinned yet */ reln->pincount = 0; dlist_push_tail(&unpinned_relns, &reln->node); + + /* implementation-specific initialization */ + smgrsw[reln->smgr_which].smgr_open(reln); } + RESUME_INTERRUPTS(); + return reln; } @@ -280,6 +326,8 @@ smgrdestroy(SMgrRelation reln) Assert(reln->pincount == 0); + HOLD_INTERRUPTS(); + for (forknum = 0; forknum <= MAX_FORKNUM; forknum++) smgrsw[reln->smgr_which].smgr_close(reln, forknum); @@ -289,6 +337,8 @@ smgrdestroy(SMgrRelation reln) &(reln->smgr_rlocator), HASH_REMOVE, NULL) == NULL) elog(ERROR, "SMgrRelation hashtable corrupted"); + + RESUME_INTERRUPTS(); } /* @@ -299,12 +349,16 @@ smgrdestroy(SMgrRelation reln) void smgrrelease(SMgrRelation reln) { + HOLD_INTERRUPTS(); + for (ForkNumber forknum = 0; forknum <= MAX_FORKNUM; forknum++) { smgrsw[reln->smgr_which].smgr_close(reln, forknum); reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber; } reln->smgr_targblock = InvalidBlockNumber; + + RESUME_INTERRUPTS(); } /* @@ -333,6 +387,9 @@ smgrdestroyall(void) { dlist_mutable_iter iter; + /* seems unsafe to accept interrupts while in a dlist_foreach_modify() */ + HOLD_INTERRUPTS(); + /* * Zap all unpinned SMgrRelations. We rely on smgrdestroy() to remove * each one from the list. @@ -344,6 +401,8 @@ smgrdestroyall(void) smgrdestroy(rel); } + + RESUME_INTERRUPTS(); } /* @@ -359,12 +418,17 @@ smgrreleaseall(void) if (SMgrRelationHash == NULL) return; + /* seems unsafe to accept interrupts while iterating */ + HOLD_INTERRUPTS(); + hash_seq_init(&status, SMgrRelationHash); while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL) { smgrrelease(reln); } + + RESUME_INTERRUPTS(); } /* @@ -397,7 +461,13 @@ smgrreleaserellocator(RelFileLocatorBackend rlocator) bool smgrexists(SMgrRelation reln, ForkNumber forknum) { - return smgrsw[reln->smgr_which].smgr_exists(reln, forknum); + bool ret; + + HOLD_INTERRUPTS(); + ret = smgrsw[reln->smgr_which].smgr_exists(reln, forknum); + RESUME_INTERRUPTS(); + + return ret; } /* @@ -410,7 +480,9 @@ smgrexists(SMgrRelation reln, ForkNumber forknum) void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo); + RESUME_INTERRUPTS(); } /* @@ -433,6 +505,8 @@ smgrdosyncall(SMgrRelation *rels, int nrels) FlushRelationsAllBuffers(rels, nrels); + HOLD_INTERRUPTS(); + /* * Sync the physical file(s). */ @@ -446,6 +520,8 @@ smgrdosyncall(SMgrRelation *rels, int nrels) smgrsw[which].smgr_immedsync(rels[i], forknum); } } + + RESUME_INTERRUPTS(); } /* @@ -468,6 +544,13 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo) if (nrels == 0) return; + /* + * It would be unsafe to process interrupts between DropRelationBuffers() + * and unlinking the underlying files. This probably should be a critical + * section, but we're not there yet. + */ + HOLD_INTERRUPTS(); + /* * Get rid of any remaining buffers for the relations. bufmgr will just * drop them without bothering to write the contents. @@ -519,6 +602,8 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo) } pfree(rlocators); + + RESUME_INTERRUPTS(); } @@ -535,6 +620,8 @@ void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync) { + HOLD_INTERRUPTS(); + smgrsw[reln->smgr_which].smgr_extend(reln, forknum, blocknum, buffer, skipFsync); @@ -547,6 +634,8 @@ smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, reln->smgr_cached_nblocks[forknum] = blocknum + 1; else reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber; + + RESUME_INTERRUPTS(); } /* @@ -560,6 +649,8 @@ void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync) { + HOLD_INTERRUPTS(); + smgrsw[reln->smgr_which].smgr_zeroextend(reln, forknum, blocknum, nblocks, skipFsync); @@ -572,6 +663,8 @@ smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, reln->smgr_cached_nblocks[forknum] = blocknum + nblocks; else reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber; + + RESUME_INTERRUPTS(); } /* @@ -585,7 +678,32 @@ bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks) { - return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum, nblocks); + bool ret; + + HOLD_INTERRUPTS(); + ret = smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum, nblocks); + RESUME_INTERRUPTS(); + + return ret; +} + +/* + * smgrmaxcombine() - Return the maximum number of total blocks that can be + * combined with an IO starting at blocknum. + * + * The returned value includes the IO for blocknum itself. + */ +uint32 +smgrmaxcombine(SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum) +{ + uint32 ret; + + HOLD_INTERRUPTS(); + ret = smgrsw[reln->smgr_which].smgr_maxcombine(reln, forknum, blocknum); + RESUME_INTERRUPTS(); + + return ret; } /* @@ -595,13 +713,52 @@ smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, * This routine is called from the buffer manager in order to * instantiate pages in the shared buffer cache. All storage managers * return pages in the format that POSTGRES expects. + * + * If more than one block is intended to be read, callers need to use + * smgrmaxcombine() to check how many blocks can be combined into one IO. */ void smgrreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_readv(reln, forknum, blocknum, buffers, nblocks); + RESUME_INTERRUPTS(); +} + +/* + * smgrstartreadv() -- asynchronous version of smgrreadv() + * + * This starts an asynchronous readv IO using the IO handle `ioh`. Other than + * `ioh` all parameters are the same as smgrreadv(). + * + * Completion callbacks above smgr will be passed the result as the number of + * successfully read blocks if the read [partially] succeeds (Buffers for + * blocks not successfully read might bear unspecified modifications, up to + * the full nblocks). This maintains the abstraction that smgr operates on the + * level of blocks, rather than bytes. + * + * Compared to smgrreadv(), more responsibilities fall on the caller: + * - Partial reads need to be handled by the caller re-issuing IO for the + * unread blocks + * - smgr will ereport(LOG_SERVER_ONLY) some problems, but higher layers are + * responsible for pgaio_result_report() to mirror that news to the user (if + * the IO results in PGAIO_RS_WARNING) or abort the (sub)transaction (if + * PGAIO_RS_ERROR). + * - Under Valgrind, the "buffers" memory may or may not change status to + * DEFINED, depending on io_method and concurrent activity. + */ +void +smgrstartreadv(PgAioHandle *ioh, + SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, + void **buffers, BlockNumber nblocks) +{ + HOLD_INTERRUPTS(); + smgrsw[reln->smgr_which].smgr_startreadv(ioh, + reln, forknum, blocknum, buffers, + nblocks); + RESUME_INTERRUPTS(); } /* @@ -626,13 +783,18 @@ smgrreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, * skipFsync indicates that the caller will make other provisions to * fsync the relation, so we needn't bother. Temporary relations also * do not require fsync. + * + * If more than one block is intended to be read, callers need to use + * smgrmaxcombine() to check how many blocks can be combined into one IO. */ void smgrwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void **buffers, BlockNumber nblocks, bool skipFsync) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_writev(reln, forknum, blocknum, buffers, nblocks, skipFsync); + RESUME_INTERRUPTS(); } /* @@ -643,8 +805,10 @@ void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_writeback(reln, forknum, blocknum, nblocks); + RESUME_INTERRUPTS(); } /* @@ -661,10 +825,14 @@ smgrnblocks(SMgrRelation reln, ForkNumber forknum) if (result != InvalidBlockNumber) return result; + HOLD_INTERRUPTS(); + result = smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum); reln->smgr_cached_nblocks[forknum] = result; + RESUME_INTERRUPTS(); + return result; } @@ -697,10 +865,15 @@ smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum) * * The caller must hold AccessExclusiveLock on the relation, to ensure that * other backends receive the smgr invalidation event that this function sends - * before they access any forks of the relation again. + * before they access any forks of the relation again. The current size of + * the forks should be provided in old_nblocks. This function should normally + * be called in a critical section, but the current size must be checked + * outside the critical section, and no interrupts or smgr functions relating + * to this relation should be called in between. */ void -smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks) +smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, + BlockNumber *old_nblocks, BlockNumber *nblocks) { int i; @@ -728,14 +901,15 @@ smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nb /* Make the cached size is invalid if we encounter an error. */ reln->smgr_cached_nblocks[forknum[i]] = InvalidBlockNumber; - smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], nblocks[i]); + smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], + old_nblocks[i], nblocks[i]); /* * We might as well update the local smgr_cached_nblocks values. The * smgr cache inval message that this function sent will cause other - * backends to invalidate their copies of smgr_fsm_nblocks and - * smgr_vm_nblocks, and these ones too at the next command boundary. - * But these ensure they aren't outright wrong until then. + * backends to invalidate their copies of smgr_cached_nblocks, and + * these ones too at the next command boundary. But ensure they aren't + * outright wrong until then. */ reln->smgr_cached_nblocks[forknum[i]] = nblocks[i]; } @@ -756,7 +930,9 @@ smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nb void smgrregistersync(SMgrRelation reln, ForkNumber forknum) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_registersync(reln, forknum); + RESUME_INTERRUPTS(); } /* @@ -788,7 +964,32 @@ smgrregistersync(SMgrRelation reln, ForkNumber forknum) void smgrimmedsync(SMgrRelation reln, ForkNumber forknum) { + HOLD_INTERRUPTS(); smgrsw[reln->smgr_which].smgr_immedsync(reln, forknum); + RESUME_INTERRUPTS(); +} + +/* + * Return fd for the specified block number and update *off to the appropriate + * position. + * + * This is only to be used for when AIO needs to perform the IO in a different + * process than where it was issued (e.g. in an IO worker). + */ +static int +smgrfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off) +{ + int fd; + + /* + * The caller needs to prevent interrupts from being processed, otherwise + * the FD could be closed prematurely. + */ + Assert(!INTERRUPTS_CAN_BE_PROCESSED()); + + fd = smgrsw[reln->smgr_which].smgr_fd(reln, forknum, blocknum, off); + + return fd; } /* @@ -819,3 +1020,99 @@ ProcessBarrierSmgrRelease(void) smgrreleaseall(); return true; } + +/* + * Set target of the IO handle to be smgr and initialize all the relevant + * pieces of data. + */ +void +pgaio_io_set_target_smgr(PgAioHandle *ioh, + SMgrRelationData *smgr, + ForkNumber forknum, + BlockNumber blocknum, + int nblocks, + bool skip_fsync) +{ + PgAioTargetData *sd = pgaio_io_get_target_data(ioh); + + pgaio_io_set_target(ioh, PGAIO_TID_SMGR); + + /* backend is implied via IO owner */ + sd->smgr.rlocator = smgr->smgr_rlocator.locator; + sd->smgr.forkNum = forknum; + sd->smgr.blockNum = blocknum; + sd->smgr.nblocks = nblocks; + sd->smgr.is_temp = SmgrIsTemp(smgr); + /* Temp relations should never be fsync'd */ + sd->smgr.skip_fsync = skip_fsync && !SmgrIsTemp(smgr); +} + +/* + * Callback for the smgr AIO target, to reopen the file (e.g. because the IO + * is executed in a worker). + */ +static void +smgr_aio_reopen(PgAioHandle *ioh) +{ + PgAioTargetData *sd = pgaio_io_get_target_data(ioh); + PgAioOpData *od = pgaio_io_get_op_data(ioh); + SMgrRelation reln; + ProcNumber procno; + uint32 off; + + /* + * The caller needs to prevent interrupts from being processed, otherwise + * the FD could be closed again before we get to executing the IO. + */ + Assert(!INTERRUPTS_CAN_BE_PROCESSED()); + + if (sd->smgr.is_temp) + procno = pgaio_io_get_owner(ioh); + else + procno = INVALID_PROC_NUMBER; + + reln = smgropen(sd->smgr.rlocator, procno); + switch (pgaio_io_get_op(ioh)) + { + case PGAIO_OP_INVALID: + pg_unreachable(); + break; + case PGAIO_OP_READV: + od->read.fd = smgrfd(reln, sd->smgr.forkNum, sd->smgr.blockNum, &off); + Assert(off == od->read.offset); + break; + case PGAIO_OP_WRITEV: + od->write.fd = smgrfd(reln, sd->smgr.forkNum, sd->smgr.blockNum, &off); + Assert(off == od->write.offset); + break; + } +} + +/* + * Callback for the smgr AIO target, describing the target of the IO. + */ +static char * +smgr_aio_describe_identity(const PgAioTargetData *sd) +{ + RelPathStr path; + char *desc; + + path = relpathbackend(sd->smgr.rlocator, + sd->smgr.is_temp ? + MyProcNumber : INVALID_PROC_NUMBER, + sd->smgr.forkNum); + + if (sd->smgr.nblocks == 0) + desc = psprintf(_("file \"%s\""), path.str); + else if (sd->smgr.nblocks == 1) + desc = psprintf(_("block %u in file \"%s\""), + sd->smgr.blockNum, + path.str); + else + desc = psprintf(_("blocks %u..%u in file \"%s\""), + sd->smgr.blockNum, + sd->smgr.blockNum + sd->smgr.nblocks - 1, + path.str); + + return desc; +} diff --git a/src/backend/storage/sync/meson.build b/src/backend/storage/sync/meson.build index 299dd63e3d428..52cd52afd1791 100644 --- a/src/backend/storage/sync/meson.build +++ b/src/backend/storage/sync/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'sync.c', diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c index ab7137d0fffcc..fc16db90133bb 100644 --- a/src/backend/storage/sync/sync.c +++ b/src/backend/storage/sync/sync.c @@ -3,7 +3,7 @@ * sync.c * File synchronization management code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/tcop/backend_startup.c b/src/backend/tcop/backend_startup.c index b840d95e4d1e1..a7d1fec981f88 100644 --- a/src/backend/tcop/backend_startup.c +++ b/src/backend/tcop/backend_startup.c @@ -3,7 +3,7 @@ * backend_startup.c * Backend startup code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -18,6 +18,7 @@ #include #include "access/xlog.h" +#include "access/xlogrecovery.h" #include "common/ip.h" #include "common/string.h" #include "libpq/libpq.h" @@ -29,24 +30,41 @@ #include "replication/walsender.h" #include "storage/fd.h" #include "storage/ipc.h" +#include "storage/procsignal.h" #include "storage/proc.h" #include "tcop/backend_startup.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" +#include "utils/guc_hooks.h" #include "utils/injection_point.h" #include "utils/memutils.h" #include "utils/ps_status.h" #include "utils/timeout.h" +#include "utils/varlena.h" /* GUCs */ bool Trace_connection_negotiation = false; +uint32 log_connections = 0; +char *log_connections_string = NULL; + +/* Other globals */ + +/* + * ConnectionTiming stores timestamps of various points in connection + * establishment and setup. + * ready_for_use is initialized to a special value here so we can check if + * we've already set it before doing so in PostgresMain(). + */ +ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY}; static void BackendInitialize(ClientSocket *client_sock, CAC_state cac); static int ProcessSSLStartup(Port *port); static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done); +static void ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen); static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options); static void process_startup_packet_die(SIGNAL_ARGS); static void StartupPacketTimeoutHandler(void); +static bool validate_log_connections_options(List *elemlist, uint32 *flags); /* * Entry point for a new backend process. @@ -55,9 +73,9 @@ static void StartupPacketTimeoutHandler(void); * client, and start the main processing loop. */ void -BackendMain(char *startup_data, size_t startup_data_len) +BackendMain(const void *startup_data, size_t startup_data_len) { - BackendStartupData *bsdata = (BackendStartupData *) startup_data; + const BackendStartupData *bsdata = startup_data; Assert(startup_data_len == sizeof(BackendStartupData)); Assert(MyClientSocket != NULL); @@ -200,8 +218,8 @@ BackendInitialize(ClientSocket *client_sock, CAC_state cac) port->remote_host = MemoryContextStrdup(TopMemoryContext, remote_host); port->remote_port = MemoryContextStrdup(TopMemoryContext, remote_port); - /* And now we can issue the Log_connections message, if wanted */ - if (Log_connections) + /* And now we can log that the connection was received, if enabled */ + if (log_connections & LOG_CONNECTION_RECEIPT) { if (remote_port[0]) ereport(LOG, @@ -216,7 +234,7 @@ BackendInitialize(ClientSocket *client_sock, CAC_state cac) /* For testing client error handling */ #ifdef USE_INJECTION_POINTS - INJECTION_POINT("backend-initialize"); + INJECTION_POINT("backend-initialize", NULL); if (IS_INJECTION_POINT_ATTACHED("backend-initialize-v2-error")) { /* @@ -290,17 +308,24 @@ BackendInitialize(ClientSocket *client_sock, CAC_state cac) (errcode(ERRCODE_CANNOT_CONNECT_NOW), errmsg("the database system is starting up"))); break; - case CAC_NOTCONSISTENT: - if (EnableHotStandby) + case CAC_NOTHOTSTANDBY: + if (!EnableHotStandby) + ereport(FATAL, + (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the database system is not accepting connections"), + errdetail("Hot standby mode is disabled."))); + else if (reachedConsistency) ereport(FATAL, (errcode(ERRCODE_CANNOT_CONNECT_NOW), errmsg("the database system is not yet accepting connections"), - errdetail("Consistent recovery state has not been yet reached."))); + errdetail("Recovery snapshot is not yet ready for hot standby."), + errhint("To enable hot standby, close write transactions with more than %d subtransactions on the primary server.", + PGPROC_MAX_CACHED_SUBXIDS))); else ereport(FATAL, (errcode(ERRCODE_CANNOT_CONNECT_NOW), - errmsg("the database system is not accepting connections"), - errdetail("Hot standby mode is disabled."))); + errmsg("the database system is not yet accepting connections"), + errdetail("Consistent recovery state has not been yet reached."))); break; case CAC_SHUTDOWN: ereport(FATAL, @@ -479,7 +504,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) * sound inefficient, but it's not really, because of buffering in * pqcomm.c.) */ - if (pq_getbytes((char *) &len, 1) == EOF) + if (pq_getbytes(&len, 1) == EOF) { /* * If we get no data at all, don't clutter the log with a complaint; @@ -541,22 +566,7 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) if (proto == CANCEL_REQUEST_CODE) { - CancelRequestPacket *canc; - int backendPID; - int32 cancelAuthCode; - - if (len != sizeof(CancelRequestPacket)) - { - ereport(COMMERROR, - (errcode(ERRCODE_PROTOCOL_VIOLATION), - errmsg("invalid length of startup packet"))); - return STATUS_ERROR; - } - canc = (CancelRequestPacket *) buf; - backendPID = (int) pg_ntoh32(canc->backendPID); - cancelAuthCode = (int32) pg_ntoh32(canc->cancelAuthCode); - - processCancelRequest(backendPID, cancelAuthCode); + ProcessCancelRequestPacket(port, buf, len); /* Not really an error, but we don't want to proceed further */ return STATUS_ERROR; } @@ -683,9 +693,13 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) /* * Set FrontendProtocol now so that ereport() knows what format to send if - * we fail during startup. + * we fail during startup. We use the protocol version requested by the + * client unless it's higher than the latest version we support. It's + * possible that error message fields might look different in newer + * protocol versions, but that's something those new clients should be + * able to deal with. */ - FrontendProtocol = proto; + FrontendProtocol = Min(proto, PG_PROTOCOL_LATEST); /* Check that the major protocol version is in range. */ if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) || @@ -819,6 +833,15 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) if (port->database_name == NULL || port->database_name[0] == '\0') port->database_name = pstrdup(port->user_name); + /* + * Truncate given database and user names to length of a Postgres name. + * This avoids lookup failures when overlength names are given. + */ + if (strlen(port->database_name) >= NAMEDATALEN) + port->database_name[NAMEDATALEN - 1] = '\0'; + if (strlen(port->user_name) >= NAMEDATALEN) + port->user_name[NAMEDATALEN - 1] = '\0'; + if (am_walsender) MyBackendType = B_WAL_SENDER; else @@ -843,11 +866,45 @@ ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done) return STATUS_OK; } +/* + * The client has sent a cancel request packet, not a normal + * start-a-new-connection packet. Perform the necessary processing. Nothing + * is sent back to the client. + */ +static void +ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen) +{ + CancelRequestPacket *canc; + int len; + + if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode)) + { + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid length of query cancel packet"))); + return; + } + len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode); + if (len == 0 || len > 256) + { + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid length of query cancel key"))); + return; + } + + canc = (CancelRequestPacket *) pkt; + SendCancelRequest(pg_ntoh32(canc->backendPID), canc->cancelAuthCode, len); +} + /* * Send a NegotiateProtocolVersion to the client. This lets the client know - * that they have requested a newer minor protocol version than we are able - * to speak. We'll speak the highest version we know about; the client can, - * of course, abandon the connection if that's a problem. + * that they have either requested a newer minor protocol version than we are + * able to speak, or at least one protocol option that we don't understand, or + * possibly both. FrontendProtocol has already been set to the version + * requested by the client or the highest version we know how to speak, + * whichever is older. If the highest version that we know how to speak is too + * old for the client, it can abandon the connection. * * We also include in the response a list of protocol options we didn't * understand. This allows clients to include optional parameters that might @@ -863,7 +920,7 @@ SendNegotiateProtocolVersion(List *unrecognized_protocol_options) ListCell *lc; pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion); - pq_sendint32(&buf, PG_PROTOCOL_LATEST); + pq_sendint32(&buf, FrontendProtocol); pq_sendint32(&buf, list_length(unrecognized_protocol_options)); foreach(lc, unrecognized_protocol_options) pq_sendstring(&buf, lfirst(lc)); @@ -901,3 +958,158 @@ StartupPacketTimeoutHandler(void) { _exit(1); } + +/* + * Helper for the log_connections GUC check hook. + * + * `elemlist` is a listified version of the string input passed to the + * log_connections GUC check hook, check_log_connections(). + * check_log_connections() is responsible for cleaning up `elemlist`. + * + * validate_log_connections_options() returns false if an error was + * encountered and the GUC input could not be validated and true otherwise. + * + * `flags` returns the flags that should be stored in the log_connections GUC + * by its assign hook. + */ +static bool +validate_log_connections_options(List *elemlist, uint32 *flags) +{ + ListCell *l; + char *item; + + /* + * For backwards compatibility, we accept these tokens by themselves. + * + * Prior to PostgreSQL 18, log_connections was a boolean GUC that accepted + * any unambiguous substring of 'true', 'false', 'yes', 'no', 'on', and + * 'off'. Since log_connections became a list of strings in 18, we only + * accept complete option strings. + */ + static const struct config_enum_entry compat_options[] = { + {"off", 0}, + {"false", 0}, + {"no", 0}, + {"0", 0}, + {"on", LOG_CONNECTION_ON}, + {"true", LOG_CONNECTION_ON}, + {"yes", LOG_CONNECTION_ON}, + {"1", LOG_CONNECTION_ON}, + }; + + *flags = 0; + + /* If an empty string was passed, we're done */ + if (list_length(elemlist) == 0) + return true; + + /* + * Now check for the backwards compatibility options. They must always be + * specified on their own, so we error out if the first option is a + * backwards compatibility option and other options are also specified. + */ + item = linitial(elemlist); + + for (size_t i = 0; i < lengthof(compat_options); i++) + { + struct config_enum_entry option = compat_options[i]; + + if (pg_strcasecmp(item, option.name) != 0) + continue; + + if (list_length(elemlist) > 1) + { + GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.", + item); + return false; + } + + *flags = option.val; + return true; + } + + /* Now check the aspect options. The empty string was already handled */ + foreach(l, elemlist) + { + static const struct config_enum_entry options[] = { + {"receipt", LOG_CONNECTION_RECEIPT}, + {"authentication", LOG_CONNECTION_AUTHENTICATION}, + {"authorization", LOG_CONNECTION_AUTHORIZATION}, + {"setup_durations", LOG_CONNECTION_SETUP_DURATIONS}, + {"all", LOG_CONNECTION_ALL}, + }; + + item = lfirst(l); + for (size_t i = 0; i < lengthof(options); i++) + { + struct config_enum_entry option = options[i]; + + if (pg_strcasecmp(item, option.name) == 0) + { + *flags |= option.val; + goto next; + } + } + + GUC_check_errdetail("Invalid option \"%s\".", item); + return false; + +next: ; + } + + return true; +} + + +/* + * GUC check hook for log_connections + */ +bool +check_log_connections(char **newval, void **extra, GucSource source) +{ + uint32 flags; + char *rawstring; + List *elemlist; + bool success; + + /* Need a modifiable copy of string */ + rawstring = pstrdup(*newval); + + if (!SplitIdentifierString(rawstring, ',', &elemlist)) + { + GUC_check_errdetail("Invalid list syntax in parameter \"log_connections\"."); + pfree(rawstring); + list_free(elemlist); + return false; + } + + /* Validation logic is all in the helper */ + success = validate_log_connections_options(elemlist, &flags); + + /* Time for cleanup */ + pfree(rawstring); + list_free(elemlist); + + if (!success) + return false; + + /* + * We succeeded, so allocate `extra` and save the flags there for use by + * assign_log_connections(). + */ + *extra = guc_malloc(LOG, sizeof(int)); + if (!*extra) + return false; + *((int *) *extra) = flags; + + return true; +} + +/* + * GUC assign hook for log_connections + */ +void +assign_log_connections(const char *newval, void *extra) +{ + log_connections = *((int *) extra); +} diff --git a/src/backend/tcop/cmdtag.c b/src/backend/tcop/cmdtag.c index 0870064fdd83b..fa556187eecba 100644 --- a/src/backend/tcop/cmdtag.c +++ b/src/backend/tcop/cmdtag.c @@ -3,7 +3,7 @@ * cmdtag.c * Data and routines for commandtag names and enumeration. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c index 96f80b3046346..b620766c93888 100644 --- a/src/backend/tcop/dest.c +++ b/src/backend/tcop/dest.c @@ -4,7 +4,7 @@ * support for communication destinations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -33,7 +33,7 @@ #include "access/xact.h" #include "commands/copy.h" #include "commands/createas.h" -#include "commands/explain.h" +#include "commands/explain_dr.h" #include "commands/matview.h" #include "executor/functions.h" #include "executor/tqueue.h" diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index deac71335c2ef..62f9ffa0dc088 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -3,7 +3,7 @@ * fastpath.c * routines to handle function requests from the frontend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,7 +26,6 @@ #include "libpq/protocol.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "port/pg_bswap.h" #include "tcop/fastpath.h" #include "tcop/tcopprot.h" #include "utils/acl.h" diff --git a/src/backend/tcop/meson.build b/src/backend/tcop/meson.build index 19a97bbf55ea7..a312d93087bd0 100644 --- a/src/backend/tcop/meson.build +++ b/src/backend/tcop/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'backend_startup.c', diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ea517f4b9bb59..2f8c3d5f91822 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3,7 +3,7 @@ * postgres.c * POSTGRES C Backend Interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -53,7 +53,6 @@ #include "pg_getopt.h" #include "pg_trace.h" #include "pgstat.h" -#include "postmaster/autovacuum.h" #include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "replication/logicallauncher.h" @@ -67,6 +66,7 @@ #include "storage/proc.h" #include "storage/procsignal.h" #include "storage/sinval.h" +#include "tcop/backend_startup.h" #include "tcop/fastpath.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" @@ -79,6 +79,7 @@ #include "utils/snapmgr.h" #include "utils/timeout.h" #include "utils/timestamp.h" +#include "utils/varlena.h" /* ---------------- * global variables @@ -94,15 +95,15 @@ bool Log_disconnections = false; int log_statement = LOGSTMT_NONE; -/* GUC variable for maximum stack depth (measured in kilobytes) */ -int max_stack_depth = 100; - /* wait N seconds to allow attach from a debugger */ int PostAuthDelay = 0; /* Time between checks that the client is still connected. */ int client_connection_check_interval = 0; +/* flags for non-system relation kinds to restrict use */ +int restrict_nonsystem_relation_kind; + /* ---------------- * private typedefs etc * ---------------- @@ -121,15 +122,6 @@ typedef struct BindParamCbData * ---------------- */ -/* max_stack_depth converted to bytes for speed of checking */ -static long max_stack_depth_bytes = 100 * 1024L; - -/* - * Stack base pointer -- initialized by PostmasterMain and inherited by - * subprocesses (but see also InitPostmasterChild). - */ -static char *stack_base_ptr = NULL; - /* * Flag to keep track of whether we have started a transaction. * For extended query protocol this has to be remembered across messages. @@ -319,7 +311,7 @@ InteractiveBackend(StringInfo inBuf) printf("statement: %s\n", inBuf->data); fflush(stdout); - return 'Q'; + return PqMsg_Query; } /* @@ -622,8 +614,10 @@ pg_parse_query(const char *query_string) if (log_parser_stats) ShowUsage("PARSER STATISTICS"); -#ifdef COPY_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED + /* Optional debugging check: pass raw parsetrees through copyObject() */ + if (Debug_copy_parse_plan_trees) { List *new_list = copyObject(raw_parsetree_list); @@ -633,13 +627,12 @@ pg_parse_query(const char *query_string) else raw_parsetree_list = new_list; } -#endif /* * Optional debugging check: pass raw parsetrees through * outfuncs/readfuncs */ -#ifdef WRITE_READ_PARSE_PLAN_TREES + if (Debug_write_read_parse_plan_trees) { char *str = nodeToStringWithLocations(raw_parsetree_list); List *new_list = stringToNodeWithLocations(str); @@ -651,7 +644,8 @@ pg_parse_query(const char *query_string) else raw_parsetree_list = new_list; } -#endif + +#endif /* DEBUG_NODE_TESTS_ENABLED */ TRACE_POSTGRESQL_QUERY_PARSE_DONE(query_string); @@ -826,8 +820,10 @@ pg_rewrite_query(Query *query) if (log_parser_stats) ShowUsage("REWRITER STATISTICS"); -#ifdef COPY_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED + /* Optional debugging check: pass querytree through copyObject() */ + if (Debug_copy_parse_plan_trees) { List *new_list; @@ -838,10 +834,9 @@ pg_rewrite_query(Query *query) else querytree_list = new_list; } -#endif -#ifdef WRITE_READ_PARSE_PLAN_TREES /* Optional debugging check: pass querytree through outfuncs/readfuncs */ + if (Debug_write_read_parse_plan_trees) { List *new_list = NIL; ListCell *lc; @@ -868,7 +863,8 @@ pg_rewrite_query(Query *query) else querytree_list = new_list; } -#endif + +#endif /* DEBUG_NODE_TESTS_ENABLED */ if (Debug_print_rewritten) elog_node_display(LOG, "rewritten parse tree", querytree_list, @@ -906,8 +902,10 @@ pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, if (log_planner_stats) ShowUsage("PLANNER STATISTICS"); -#ifdef COPY_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED + /* Optional debugging check: pass plan tree through copyObject() */ + if (Debug_copy_parse_plan_trees) { PlannedStmt *new_plan = copyObject(plan); @@ -923,10 +921,9 @@ pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, #endif plan = new_plan; } -#endif -#ifdef WRITE_READ_PARSE_PLAN_TREES /* Optional debugging check: pass plan tree through outfuncs/readfuncs */ + if (Debug_write_read_parse_plan_trees) { char *str; PlannedStmt *new_plan; @@ -947,7 +944,8 @@ pg_plan_query(Query *querytree, const char *query_string, int cursorOptions, #endif plan = new_plan; } -#endif + +#endif /* DEBUG_NODE_TESTS_ENABLED */ /* * Print plan if debugging. @@ -1109,6 +1107,7 @@ exec_simple_query(const char *query_string) size_t cmdtaglen; pgstat_report_query_id(0, true); + pgstat_report_plan_id(0, true); /* * Get the command name for use in status display (it also becomes the @@ -1274,7 +1273,6 @@ exec_simple_query(const char *query_string) (void) PortalRun(portal, FETCH_ALL, true, /* always top level */ - true, receiver, receiver, &qc); @@ -1644,6 +1642,7 @@ exec_bind_message(StringInfo input_message) char msec_str[32]; ParamsErrorCbData params_data; ErrorContextCallback params_errcxt; + ListCell *lc; /* Get the fixed part of the message */ portal_name = pq_getmsgstring(input_message); @@ -1679,6 +1678,17 @@ exec_bind_message(StringInfo input_message) pgstat_report_activity(STATE_RUNNING, psrc->query_string); + foreach(lc, psrc->query_list) + { + Query *query = lfirst_node(Query, lc); + + if (query->queryId != INT64CONST(0)) + { + pgstat_report_query_id(query->queryId, false); + break; + } + } + set_ps_display("BIND"); if (save_log_statement_stats) @@ -1795,7 +1805,7 @@ exec_bind_message(StringInfo input_message) one_param_data.paramval = NULL; params_errcxt.previous = error_context_stack; params_errcxt.callback = bind_param_error_callback; - params_errcxt.arg = (void *) &one_param_data; + params_errcxt.arg = &one_param_data; error_context_stack = ¶ms_errcxt; params = makeParamList(numParams); @@ -1985,7 +1995,7 @@ exec_bind_message(StringInfo input_message) params_data.params = params; params_errcxt.previous = error_context_stack; params_errcxt.callback = ParamsErrorCallback; - params_errcxt.arg = (void *) ¶ms_data; + params_errcxt.arg = ¶ms_data; error_context_stack = ¶ms_errcxt; /* Get the result format codes */ @@ -2019,6 +2029,18 @@ exec_bind_message(StringInfo input_message) cplan->stmt_list, cplan); + /* Portal is defined, set the plan ID based on its contents. */ + foreach(lc, portal->stmts) + { + PlannedStmt *plan = lfirst_node(PlannedStmt, lc); + + if (plan->planId != INT64CONST(0)) + { + pgstat_report_plan_id(plan->planId, false); + break; + } + } + /* Done with the snapshot used for parameter I/O and parsing/planning */ if (snapshot_set) PopActiveSnapshot(); @@ -2101,6 +2123,7 @@ exec_execute_message(const char *portal_name, long max_rows) ErrorContextCallback params_errcxt; const char *cmdtagname; size_t cmdtaglen; + ListCell *lc; /* Adjust destination to tell printtup.c what to do */ dest = whereToSendOutput; @@ -2147,6 +2170,28 @@ exec_execute_message(const char *portal_name, long max_rows) pgstat_report_activity(STATE_RUNNING, sourceText); + foreach(lc, portal->stmts) + { + PlannedStmt *stmt = lfirst_node(PlannedStmt, lc); + + if (stmt->queryId != INT64CONST(0)) + { + pgstat_report_query_id(stmt->queryId, false); + break; + } + } + + foreach(lc, portal->stmts) + { + PlannedStmt *stmt = lfirst_node(PlannedStmt, lc); + + if (stmt->planId != INT64CONST(0)) + { + pgstat_report_plan_id(stmt->planId, false); + break; + } + } + cmdtagname = GetCommandTagNameAndLen(portal->commandTag, &cmdtaglen); set_ps_display_with_len(cmdtagname, cmdtaglen); @@ -2218,7 +2263,7 @@ exec_execute_message(const char *portal_name, long max_rows) params_data.params = portalParams; params_errcxt.previous = error_context_stack; params_errcxt.callback = ParamsErrorCallback; - params_errcxt.arg = (void *) ¶ms_data; + params_errcxt.arg = ¶ms_data; error_context_stack = ¶ms_errcxt; if (max_rows <= 0) @@ -2227,7 +2272,6 @@ exec_execute_message(const char *portal_name, long max_rows) completed = PortalRun(portal, max_rows, true, /* always top level */ - !execute_is_fetch && max_rows == FETCH_ALL, receiver, receiver, &qc); @@ -2747,6 +2791,17 @@ start_xact_command(void) xact_started = true; } + else if (MyXactFlags & XACT_FLAGS_PIPELINING) + { + /* + * When the first Execute message is completed, following commands + * will be done in an implicit transaction block created via + * pipelining. The transaction state needs to be updated to an + * implicit block if we're not already in a transaction block (like + * one started by an explicit BEGIN). + */ + BeginImplicitTransactionBlock(); + } /* * Start statement timeout if necessary. Note that this'll intentionally @@ -3052,7 +3107,7 @@ ProcessRecoveryConflictInterrupt(ProcSignalReason reason) /* * If we aren't waiting for a lock we can never deadlock. */ - if (!IsWaitingForLock()) + if (GetAwaitedLock() == NULL) return; /* Intentional fall through to check wait for pin */ @@ -3278,11 +3333,22 @@ ProcessInterrupts(void) */ proc_exit(1); } + else if (AmWalReceiverProcess()) + ereport(FATAL, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating walreceiver process due to administrator command"))); else if (AmBackgroundWorkerProcess()) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating background worker \"%s\" due to administrator command", MyBgworkerEntry->bgw_type))); + else if (AmIoWorkerProcess()) + { + ereport(DEBUG1, + (errmsg_internal("io worker shutting down due to administrator command"))); + + proc_exit(0); + } else ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), @@ -3414,7 +3480,7 @@ ProcessInterrupts(void) IdleInTransactionSessionTimeoutPending = false; if (IdleInTransactionSessionTimeout > 0) { - INJECTION_POINT("idle-in-transaction-session-timeout"); + INJECTION_POINT("idle-in-transaction-session-timeout", NULL); ereport(FATAL, (errcode(ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT), errmsg("terminating connection due to idle-in-transaction timeout"))); @@ -3427,7 +3493,7 @@ ProcessInterrupts(void) TransactionTimeoutPending = false; if (TransactionTimeout > 0) { - INJECTION_POINT("transaction-timeout"); + INJECTION_POINT("transaction-timeout", NULL); ereport(FATAL, (errcode(ERRCODE_TRANSACTION_TIMEOUT), errmsg("terminating connection due to transaction timeout"))); @@ -3440,7 +3506,7 @@ ProcessInterrupts(void) IdleSessionTimeoutPending = false; if (IdleSessionTimeout > 0) { - INJECTION_POINT("idle-session-timeout"); + INJECTION_POINT("idle-session-timeout", NULL); ereport(FATAL, (errcode(ERRCODE_IDLE_SESSION_TIMEOUT), errmsg("terminating connection due to idle-session timeout"))); @@ -3462,140 +3528,13 @@ ProcessInterrupts(void) ProcessProcSignalBarrier(); if (ParallelMessagePending) - HandleParallelMessages(); + ProcessParallelMessages(); if (LogMemoryContextPending) ProcessLogMemoryContextInterrupt(); if (ParallelApplyMessagePending) - HandleParallelApplyMessages(); -} - -/* - * set_stack_base: set up reference point for stack depth checking - * - * Returns the old reference point, if any. - */ -pg_stack_base_t -set_stack_base(void) -{ -#ifndef HAVE__BUILTIN_FRAME_ADDRESS - char stack_base; -#endif - pg_stack_base_t old; - - old = stack_base_ptr; - - /* - * Set up reference point for stack depth checking. On recent gcc we use - * __builtin_frame_address() to avoid a warning about storing a local - * variable's address in a long-lived variable. - */ -#ifdef HAVE__BUILTIN_FRAME_ADDRESS - stack_base_ptr = __builtin_frame_address(0); -#else - stack_base_ptr = &stack_base; -#endif - - return old; -} - -/* - * restore_stack_base: restore reference point for stack depth checking - * - * This can be used after set_stack_base() to restore the old value. This - * is currently only used in PL/Java. When PL/Java calls a backend function - * from different thread, the thread's stack is at a different location than - * the main thread's stack, so it sets the base pointer before the call, and - * restores it afterwards. - */ -void -restore_stack_base(pg_stack_base_t base) -{ - stack_base_ptr = base; -} - -/* - * check_stack_depth/stack_is_too_deep: check for excessively deep recursion - * - * This should be called someplace in any recursive routine that might possibly - * recurse deep enough to overflow the stack. Most Unixen treat stack - * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves - * before hitting the hardware limit. - * - * check_stack_depth() just throws an error summarily. stack_is_too_deep() - * can be used by code that wants to handle the error condition itself. - */ -void -check_stack_depth(void) -{ - if (stack_is_too_deep()) - { - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - errmsg("stack depth limit exceeded"), - errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), " - "after ensuring the platform's stack depth limit is adequate.", - max_stack_depth))); - } -} - -bool -stack_is_too_deep(void) -{ - char stack_top_loc; - long stack_depth; - - /* - * Compute distance from reference point to my local variables - */ - stack_depth = (long) (stack_base_ptr - &stack_top_loc); - - /* - * Take abs value, since stacks grow up on some machines, down on others - */ - if (stack_depth < 0) - stack_depth = -stack_depth; - - /* - * Trouble? - * - * The test on stack_base_ptr prevents us from erroring out if called - * during process setup or in a non-backend process. Logically it should - * be done first, but putting it here avoids wasting cycles during normal - * cases. - */ - if (stack_depth > max_stack_depth_bytes && - stack_base_ptr != NULL) - return true; - - return false; -} - -/* GUC check hook for max_stack_depth */ -bool -check_max_stack_depth(int *newval, void **extra, GucSource source) -{ - long newval_bytes = *newval * 1024L; - long stack_rlimit = get_stack_depth_rlimit(); - - if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP) - { - GUC_check_errdetail("\"max_stack_depth\" must not exceed %ldkB.", - (stack_rlimit - STACK_DEPTH_SLOP) / 1024L); - GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."); - return false; - } - return true; -} - -/* GUC assign hook for max_stack_depth */ -void -assign_max_stack_depth(int newval, void *extra) -{ - long newval_bytes = newval * 1024L; - - max_stack_depth_bytes = newval_bytes; + ProcessParallelApplyMessages(); } /* @@ -3667,6 +3606,68 @@ assign_transaction_timeout(int newval, void *extra) } } +/* + * GUC check_hook for restrict_nonsystem_relation_kind + */ +bool +check_restrict_nonsystem_relation_kind(char **newval, void **extra, GucSource source) +{ + char *rawstring; + List *elemlist; + ListCell *l; + int flags = 0; + + /* Need a modifiable copy of string */ + rawstring = pstrdup(*newval); + + if (!SplitIdentifierString(rawstring, ',', &elemlist)) + { + /* syntax error in list */ + GUC_check_errdetail("List syntax is invalid."); + pfree(rawstring); + list_free(elemlist); + return false; + } + + foreach(l, elemlist) + { + char *tok = (char *) lfirst(l); + + if (pg_strcasecmp(tok, "view") == 0) + flags |= RESTRICT_RELKIND_VIEW; + else if (pg_strcasecmp(tok, "foreign-table") == 0) + flags |= RESTRICT_RELKIND_FOREIGN_TABLE; + else + { + GUC_check_errdetail("Unrecognized key word: \"%s\".", tok); + pfree(rawstring); + list_free(elemlist); + return false; + } + } + + pfree(rawstring); + list_free(elemlist); + + /* Save the flags in *extra, for use by the assign function */ + *extra = guc_malloc(LOG, sizeof(int)); + if (!*extra) + return false; + *((int *) *extra) = flags; + + return true; +} + +/* + * GUC assign_hook for restrict_nonsystem_relation_kind + */ +void +assign_restrict_nonsystem_relation_kind(const char *newval, void *extra) +{ + int *flags = (int *) extra; + + restrict_nonsystem_relation_kind = *flags; +} /* * set_debug_options --- apply "-d N" command line option @@ -3689,7 +3690,7 @@ set_debug_options(int debug_flag, GucContext context, GucSource source) if (debug_flag >= 1 && context == PGC_POSTMASTER) { - SetConfigOption("log_connections", "true", context, source); + SetConfigOption("log_connections", "all", context, source); SetConfigOption("log_disconnections", "true", context, source); } if (debug_flag >= 2) @@ -3843,8 +3844,21 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, /* ignored for consistency with the postmaster */ break; - case 'c': case '-': + + /* + * Error if the user misplaced a special must-be-first option + * for dispatching to a subprogram. parse_dispatch_option() + * returns DISPATCH_POSTMASTER if it doesn't find a match, so + * error for anything else. + */ + if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("--%s must be first argument", optarg))); + + /* FALLTHROUGH */ + case 'c': { char *name, *value; @@ -4096,6 +4110,15 @@ PostgresSingleUserMain(int argc, char *argv[], /* Initialize MaxBackends */ InitializeMaxBackends(); + /* + * We don't need postmaster child slots in single-user mode, but + * initialize them anyway to avoid having special handling. + */ + InitPostmasterChildSlots(); + + /* Initialize size of fast-path lock cache. */ + InitializeFastPathLocks(); + /* * Give preloaded libraries a chance to request additional shared memory. */ @@ -4114,8 +4137,18 @@ PostgresSingleUserMain(int argc, char *argv[], */ InitializeWalConsistencyChecking(); + /* + * Create shared memory etc. (Nothing's really "shared" in single-user + * mode, but we must have these data structures anyway.) + */ CreateSharedMemoryAndSemaphores(); + /* + * Estimate number of openable files. This must happen after setting up + * semaphores, because on some platforms semaphores count as open files. + */ + set_max_safe_fds(); + /* * Remember stand-alone backend startup time,roughly at the same point * during startup that postmaster does so. @@ -4224,6 +4257,26 @@ PostgresMain(const char *dbname, const char *username) /* We need to allow SIGINT, etc during the initial transaction */ sigprocmask(SIG_SETMASK, &UnBlockSig, NULL); + /* + * Generate a random cancel key, if this is a backend serving a + * connection. InitPostgres() will advertise it in shared memory. + */ + Assert(MyCancelKeyLength == 0); + if (whereToSendOutput == DestRemote) + { + int len; + + len = (MyProcPort == NULL || MyProcPort->proto >= PG_PROTOCOL(3, 2)) + ? MAX_CANCEL_KEY_LENGTH : 4; + if (!pg_strong_random(&MyCancelKey, len)) + { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("could not generate random cancel key"))); + } + MyCancelKeyLength = len; + } + /* * General initialization. * @@ -4276,9 +4329,11 @@ PostgresMain(const char *dbname, const char *username) { StringInfoData buf; + Assert(MyCancelKeyLength > 0); pq_beginmessage(&buf, PqMsg_BackendKeyData); pq_sendint32(&buf, (int32) MyProcPid); - pq_sendint32(&buf, (int32) MyCancelKey); + + pq_sendbytes(&buf, MyCancelKey, MyCancelKeyLength); pq_endmessage(&buf); /* Need not flush since ReadyForQuery will do it. */ } @@ -4593,6 +4648,38 @@ PostgresMain(const char *dbname, const char *username) /* Report any recently-changed GUC options */ ReportChangedGUCOptions(); + /* + * The first time this backend is ready for query, log the + * durations of the different components of connection + * establishment and setup. + */ + if (conn_timing.ready_for_use == TIMESTAMP_MINUS_INFINITY && + (log_connections & LOG_CONNECTION_SETUP_DURATIONS) && + IsExternalConnectionBackend(MyBackendType)) + { + uint64 total_duration, + fork_duration, + auth_duration; + + conn_timing.ready_for_use = GetCurrentTimestamp(); + + total_duration = + TimestampDifferenceMicroseconds(conn_timing.socket_create, + conn_timing.ready_for_use); + fork_duration = + TimestampDifferenceMicroseconds(conn_timing.fork_start, + conn_timing.fork_end); + auth_duration = + TimestampDifferenceMicroseconds(conn_timing.auth_start, + conn_timing.auth_end); + + ereport(LOG, + errmsg("connection ready: setup total=%.3f ms, fork=%.3f ms, authentication=%.3f ms", + (double) total_duration / NS_PER_US, + (double) fork_duration / NS_PER_US, + (double) auth_duration / NS_PER_US)); + } + ReadyForQuery(whereToSendOutput); send_ready_for_query = false; } @@ -4872,15 +4959,22 @@ PostgresMain(const char *dbname, const char *username) case PqMsg_Sync: pq_getmsgend(&input_message); + + /* + * If pipelining was used, we may be in an implicit + * transaction block. Close it before calling + * finish_xact_command. + */ + EndImplicitTransactionBlock(); finish_xact_command(); valgrind_report_error_query("SYNC message"); send_ready_for_query = true; break; /* - * 'X' means that the frontend is closing down the socket. EOF - * means unexpected loss of frontend connection. Either way, - * perform normal shutdown. + * PqMsg_Terminate means that the frontend is closing down the + * socket. EOF means unexpected loss of frontend connection. + * Either way, perform normal shutdown. */ case EOF: @@ -4951,40 +5045,6 @@ forbidden_in_wal_sender(char firstchar) } -/* - * Obtain platform stack depth limit (in bytes) - * - * Return -1 if unknown - */ -long -get_stack_depth_rlimit(void) -{ -#if defined(HAVE_GETRLIMIT) - static long val = 0; - - /* This won't change after process launch, so check just once */ - if (val == 0) - { - struct rlimit rlim; - - if (getrlimit(RLIMIT_STACK, &rlim) < 0) - val = -1; - else if (rlim.rlim_cur == RLIM_INFINITY) - val = LONG_MAX; - /* rlim_cur is probably of an unsigned type, so check for overflow */ - else if (rlim.rlim_cur >= LONG_MAX) - val = LONG_MAX; - else - val = rlim.rlim_cur; - } - return val; -#else - /* On Windows we set the backend stack size in src/backend/Makefile */ - return WIN32_STACK_RLIMIT; -#endif -} - - static struct rusage Save_r; static struct timeval Save_t; @@ -5006,8 +5066,8 @@ ShowUsage(const char *title) getrusage(RUSAGE_SELF, &r); gettimeofday(&elapse_t, NULL); - memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user)); - memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys)); + memcpy(&user, &r.ru_utime, sizeof(user)); + memcpy(&sys, &r.ru_stime, sizeof(sys)); if (elapse_t.tv_usec < Save_t.tv_usec) { elapse_t.tv_sec--; diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 0c45fcf318f7f..d1593f38b35fd 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -3,7 +3,7 @@ * pquery.c * POSTGRES process query command code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,6 +19,7 @@ #include "access/xact.h" #include "commands/prepare.h" +#include "executor/executor.h" #include "executor/tstoreReceiver.h" #include "miscadmin.h" #include "pg_trace.h" @@ -157,7 +158,7 @@ ProcessQuery(PlannedStmt *plan, /* * Run the plan to completion. */ - ExecutorRun(queryDesc, ForwardScanDirection, 0, true); + ExecutorRun(queryDesc, ForwardScanDirection, 0); /* * Build command completion status data, if caller wants one. @@ -681,7 +682,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats) * suspended due to exhaustion of the count parameter. */ bool -PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, +PortalRun(Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc) { @@ -714,10 +715,6 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, */ MarkPortalActive(portal); - /* Set run_once flag. Shouldn't be clear if previously set. */ - Assert(!portal->run_once || run_once); - portal->run_once = run_once; - /* * Set up global portal context pointers. * @@ -921,8 +918,7 @@ PortalRunSelect(Portal portal, else { PushActiveSnapshot(queryDesc->snapshot); - ExecutorRun(queryDesc, direction, (uint64) count, - portal->run_once); + ExecutorRun(queryDesc, direction, (uint64) count); nprocessed = queryDesc->estate->es_processed; PopActiveSnapshot(); } @@ -961,8 +957,7 @@ PortalRunSelect(Portal portal, else { PushActiveSnapshot(queryDesc->snapshot); - ExecutorRun(queryDesc, direction, (uint64) count, - portal->run_once); + ExecutorRun(queryDesc, direction, (uint64) count); nprocessed = queryDesc->estate->es_processed; PopActiveSnapshot(); } @@ -1406,9 +1401,6 @@ PortalRunFetch(Portal portal, */ MarkPortalActive(portal); - /* If supporting FETCH, portal can't be run-once. */ - Assert(!portal->run_once); - /* * Set up global portal context pointers. */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index fa66b8017edea..25fe3d5801665 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -5,7 +5,7 @@ * commands. At one time acted as an interface between the Lisp and C * systems. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -122,7 +122,7 @@ CommandIsReadOnly(PlannedStmt *pstmt) /* * Determine the degree to which a utility command is read only. * - * Note the definitions of the relevant flags in src/include/utility/tcop.h. + * Note the definitions of the relevant flags in src/include/tcop/utility.h. */ static int ClassifyUtilityCommandAsReadOnly(Node *parsetree) @@ -535,6 +535,9 @@ ProcessUtility(PlannedStmt *pstmt, * event trigger code not be invoked when doing START TRANSACTION for * example, because we might need to refresh the event trigger cache, * which requires being in a valid transaction. + * + * When adding or moving utility commands, check that the documentation in + * event-trigger.sgml is kept up to date. */ void standard_ProcessUtility(PlannedStmt *pstmt, @@ -1155,7 +1158,7 @@ ProcessUtilitySlow(ParseState *pstate, { CreateStmt *cstmt = (CreateStmt *) stmt; Datum toast_options; - static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; /* Remember transformed RangeVar for LIKE */ table_rv = cstmt->relation; @@ -1688,7 +1691,7 @@ ProcessUtilitySlow(ParseState *pstate, PG_TRY(2); { address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree, - queryString, params, qc); + queryString, qc); } PG_FINALLY(2); { @@ -1709,7 +1712,7 @@ ProcessUtilitySlow(ParseState *pstate, break; case T_CreateDomainStmt: - address = DefineDomain((CreateDomainStmt *) parsetree); + address = DefineDomain(pstate, (CreateDomainStmt *) parsetree); break; case T_CreateConversionStmt: diff --git a/src/backend/tsearch/Makefile b/src/backend/tsearch/Makefile index 2e4286dd50cb5..921411ecf9199 100644 --- a/src/backend/tsearch/Makefile +++ b/src/backend/tsearch/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/tsearch # -# Copyright (c) 2006-2024, PostgreSQL Global Development Group +# Copyright (c) 2006-2025, PostgreSQL Global Development Group # # src/backend/tsearch/Makefile # diff --git a/src/backend/tsearch/dict.c b/src/backend/tsearch/dict.c index e89f508213918..eb968858683de 100644 --- a/src/backend/tsearch/dict.c +++ b/src/backend/tsearch/dict.c @@ -3,7 +3,7 @@ * dict.c * Standard interface to dictionary * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/tsearch/dict_ispell.c b/src/backend/tsearch/dict_ispell.c index 07b9ad794de08..63bd193a78a89 100644 --- a/src/backend/tsearch/dict_ispell.c +++ b/src/backend/tsearch/dict_ispell.c @@ -3,7 +3,7 @@ * dict_ispell.c * Ispell dictionary interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -13,11 +13,12 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" #include "commands/defrem.h" #include "tsearch/dicts/spell.h" -#include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" #include "utils/fmgrprotos.h" +#include "utils/formatting.h" typedef struct @@ -72,7 +73,7 @@ dispell_init(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); - readstoplist(defGetString(defel), &(d->stoplist), lowerstr); + readstoplist(defGetString(defel), &(d->stoplist), str_tolower); stoploaded = true; } else @@ -121,7 +122,7 @@ dispell_lexize(PG_FUNCTION_ARGS) if (len <= 0) PG_RETURN_POINTER(NULL); - txt = lowerstr_with_len(in, len); + txt = str_tolower(in, len, DEFAULT_COLLATION_OID); res = NINormalizeWord(&(d->obj), txt); if (res == NULL) diff --git a/src/backend/tsearch/dict_simple.c b/src/backend/tsearch/dict_simple.c index b0c9fd7946fc0..2c972fc053870 100644 --- a/src/backend/tsearch/dict_simple.c +++ b/src/backend/tsearch/dict_simple.c @@ -3,7 +3,7 @@ * dict_simple.c * Simple dictionary: just lowercase and check for stopword * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -13,10 +13,11 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" #include "commands/defrem.h" -#include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" #include "utils/fmgrprotos.h" +#include "utils/formatting.h" typedef struct @@ -47,7 +48,7 @@ dsimple_init(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple StopWords parameters"))); - readstoplist(defGetString(defel), &d->stoplist, lowerstr); + readstoplist(defGetString(defel), &d->stoplist, str_tolower); stoploaded = true; } else if (strcmp(defel->defname, "accept") == 0) @@ -80,7 +81,7 @@ dsimple_lexize(PG_FUNCTION_ARGS) char *txt; TSLexeme *res; - txt = lowerstr_with_len(in, len); + txt = str_tolower(in, len, DEFAULT_COLLATION_OID); if (*txt == '\0' || searchstoplist(&(d->stoplist), txt)) { diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c index 77cd511ee51ec..0da5a9d686802 100644 --- a/src/backend/tsearch/dict_synonym.c +++ b/src/backend/tsearch/dict_synonym.c @@ -3,7 +3,7 @@ * dict_synonym.c * Synonym dictionary: replace word by its synonym * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -13,10 +13,12 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" #include "commands/defrem.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" #include "utils/fmgrprotos.h" +#include "utils/formatting.h" typedef struct { @@ -47,7 +49,7 @@ findwrd(char *in, char **end, uint16 *flags) char *lastchar; /* Skip leading spaces */ - while (*in && t_isspace(in)) + while (*in && isspace((unsigned char) *in)) in += pg_mblen(in); /* Return NULL on empty lines */ @@ -60,7 +62,7 @@ findwrd(char *in, char **end, uint16 *flags) lastchar = start = in; /* Find end of word */ - while (*in && !t_isspace(in)) + while (*in && !isspace((unsigned char) *in)) { lastchar = in; in += pg_mblen(in); @@ -183,8 +185,8 @@ dsynonym_init(PG_FUNCTION_ARGS) } else { - d->syn[cur].in = lowerstr(starti); - d->syn[cur].out = lowerstr(starto); + d->syn[cur].in = str_tolower(starti, strlen(starti), DEFAULT_COLLATION_OID); + d->syn[cur].out = str_tolower(starto, strlen(starto), DEFAULT_COLLATION_OID); } d->syn[cur].outlen = strlen(starto); @@ -223,7 +225,7 @@ dsynonym_lexize(PG_FUNCTION_ARGS) if (d->case_sensitive) key.in = pnstrdup(in, len); else - key.in = lowerstr_with_len(in, len); + key.in = str_tolower(in, len, DEFAULT_COLLATION_OID); key.out = NULL; diff --git a/src/backend/tsearch/dict_thesaurus.c b/src/backend/tsearch/dict_thesaurus.c index 259f2e9901d85..1bebe36a6910e 100644 --- a/src/backend/tsearch/dict_thesaurus.c +++ b/src/backend/tsearch/dict_thesaurus.c @@ -3,7 +3,7 @@ * dict_thesaurus.c * Thesaurus dictionary: phrase to phrase substitution * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -190,7 +190,7 @@ thesaurusRead(const char *filename, DictThesaurus *d) ptr = line; /* is it a comment? */ - while (*ptr && t_isspace(ptr)) + while (*ptr && isspace((unsigned char) *ptr)) ptr += pg_mblen(ptr); if (t_iseq(ptr, '#') || *ptr == '\0' || @@ -212,7 +212,7 @@ thesaurusRead(const char *filename, DictThesaurus *d) errmsg("unexpected delimiter"))); state = TR_WAITSUBS; } - else if (!t_isspace(ptr)) + else if (!isspace((unsigned char) *ptr)) { beginwrd = ptr; state = TR_INLEX; @@ -225,7 +225,7 @@ thesaurusRead(const char *filename, DictThesaurus *d) newLexeme(d, beginwrd, ptr, idsubst, posinsubst++); state = TR_WAITSUBS; } - else if (t_isspace(ptr)) + else if (isspace((unsigned char) *ptr)) { newLexeme(d, beginwrd, ptr, idsubst, posinsubst++); state = TR_WAITLEX; @@ -245,7 +245,7 @@ thesaurusRead(const char *filename, DictThesaurus *d) state = TR_INSUBS; beginwrd = ptr + pg_mblen(ptr); } - else if (!t_isspace(ptr)) + else if (!isspace((unsigned char) *ptr)) { useasis = false; beginwrd = ptr; @@ -254,7 +254,7 @@ thesaurusRead(const char *filename, DictThesaurus *d) } else if (state == TR_INSUBS) { - if (t_isspace(ptr)) + if (isspace((unsigned char) *ptr)) { if (ptr == beginwrd) ereport(ERROR, @@ -859,7 +859,7 @@ thesaurus_lexize(PG_FUNCTION_ARGS) info = NULL; /* word isn't recognized */ } - dstate->private_state = (void *) info; + dstate->private_state = info; if (!info) { diff --git a/src/backend/tsearch/meson.build b/src/backend/tsearch/meson.build index 1df7f6fcdae62..c109b21c3a257 100644 --- a/src/backend/tsearch/meson.build +++ b/src/backend/tsearch/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'dict.c', diff --git a/src/backend/tsearch/regis.c b/src/backend/tsearch/regis.c index 0390a097004c6..e59a8f0970994 100644 --- a/src/backend/tsearch/regis.c +++ b/src/backend/tsearch/regis.c @@ -3,7 +3,7 @@ * regis.c * Fast regex subset * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index 9b1441fa1adae..146801885d738 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -3,7 +3,7 @@ * spell.c * Normalizing word with ISpell * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * Ispell dictionary * ----------------- @@ -66,6 +66,7 @@ #include "miscadmin.h" #include "tsearch/dicts/spell.h" #include "tsearch/ts_locale.h" +#include "utils/formatting.h" #include "utils/memutils.h" @@ -148,7 +149,7 @@ compact_palloc0(IspellDict *Conf, size_t size) Conf->avail = COMPACT_ALLOC_CHUNK; } - result = (void *) Conf->firstfree; + result = Conf->firstfree; Conf->firstfree += size; Conf->avail -= size; @@ -169,7 +170,7 @@ cpstrdup(IspellDict *Conf, const char *str) /* - * Apply lowerstr(), producing a temporary result (in the buildCxt). + * Apply str_tolower(), producing a temporary result (in the buildCxt). */ static char * lowerstr_ctx(IspellDict *Conf, const char *src) @@ -178,7 +179,7 @@ lowerstr_ctx(IspellDict *Conf, const char *src) char *dst; saveCtx = MemoryContextSwitchTo(Conf->buildCxt); - dst = lowerstr(src); + dst = str_tolower(src, strlen(src), DEFAULT_COLLATION_OID); MemoryContextSwitchTo(saveCtx); return dst; @@ -191,7 +192,7 @@ lowerstr_ctx(IspellDict *Conf, const char *src) #define GETWCHAR(W,L,N,T) ( ((const uint8*)(W))[ ((T)==FF_PREFIX) ? (N) : ( (L) - 1 - (N) ) ] ) #define GETCHAR(A,N,T) GETWCHAR( (A)->repl, (A)->replen, N, T ) -static char *VoidString = ""; +static const char *VoidString = ""; static int cmpspell(const void *s1, const void *s2) @@ -346,11 +347,11 @@ cmpaffix(const void *s1, const void *s2) * sflag: returns an affix flag from sflagset. */ static void -getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag) +getNextFlagFromString(IspellDict *Conf, const char **sflagset, char *sflag) { int32 s; - char *next, - *sbuf = *sflagset; + char *next; + const char *sbuf = *sflagset; int maxstep; bool stop = false; bool met_comma = false; @@ -374,6 +375,7 @@ getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag) stop = (maxstep == 0); break; case FM_NUM: + errno = 0; s = strtol(*sflagset, &next, 10); if (*sflagset == next || errno == ERANGE) ereport(ERROR, @@ -390,7 +392,7 @@ getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag) *sflagset = next; while (**sflagset) { - if (t_isdigit(*sflagset)) + if (isdigit((unsigned char) **sflagset)) { if (!met_comma) ereport(ERROR, @@ -408,7 +410,7 @@ getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag) *sflagset))); met_comma = true; } - else if (!t_isspace(*sflagset)) + else if (!isspace((unsigned char) **sflagset)) { ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), @@ -453,7 +455,7 @@ getNextFlagFromString(IspellDict *Conf, char **sflagset, char *sflag) static bool IsAffixFlagInUse(IspellDict *Conf, int affix, const char *affixflag) { - char *flagcur; + const char *flagcur; char flag[BUFSIZ]; if (*affixflag == 0) @@ -542,7 +544,7 @@ NIImportDictionary(IspellDict *Conf, const char *filename) while (*s) { /* we allow only single encoded flags for faster works */ - if (pg_mblen(s) == 1 && t_isprint(s) && !t_isspace(s)) + if (pg_mblen(s) == 1 && isprint((unsigned char) *s) && !isspace((unsigned char) *s)) s++; else { @@ -558,7 +560,7 @@ NIImportDictionary(IspellDict *Conf, const char *filename) s = line; while (*s) { - if (t_isspace(s)) + if (isspace((unsigned char) *s)) { *s = '\0'; break; @@ -799,7 +801,7 @@ get_nextfield(char **str, char *next) { if (t_iseq(*str, '#')) return false; - else if (!t_isspace(*str)) + else if (!isspace((unsigned char) **str)) { int clen = pg_mblen(*str); @@ -814,7 +816,7 @@ get_nextfield(char **str, char *next) } else /* state == PAE_INMASK */ { - if (t_isspace(*str)) + if (isspace((unsigned char) **str)) { *next = '\0'; return true; @@ -925,7 +927,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) { if (t_iseq(str, '#')) return false; - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) { COPYCHAR(pmask, str); pmask += pg_mblen(str); @@ -939,7 +941,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) *pmask = '\0'; state = PAE_WAIT_FIND; } - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) { COPYCHAR(pmask, str); pmask += pg_mblen(str); @@ -957,7 +959,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) prepl += pg_mblen(str); state = PAE_INREPL; } - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("syntax error"))); @@ -974,7 +976,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) COPYCHAR(pfind, str); pfind += pg_mblen(str); } - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("syntax error"))); @@ -991,7 +993,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) prepl += pg_mblen(str); state = PAE_INREPL; } - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("syntax error"))); @@ -1008,7 +1010,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl) COPYCHAR(prepl, str); prepl += pg_mblen(str); } - else if (!t_isspace(str)) + else if (!isspace((unsigned char) *str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("syntax error"))); @@ -1036,6 +1038,7 @@ setCompoundAffixFlagValue(IspellDict *Conf, CompoundAffixFlag *entry, char *next; int i; + errno = 0; i = strtol(s, &next, 10); if (s == next || errno == ERANGE) ereport(ERROR, @@ -1070,7 +1073,7 @@ addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val) char *sflag; int clen; - while (*s && t_isspace(s)) + while (*s && isspace((unsigned char) *s)) s += pg_mblen(s); if (!*s) @@ -1080,7 +1083,7 @@ addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val) /* Get flag without \n */ sflag = sbuf; - while (*s && !t_isspace(s) && *s != '\n') + while (*s && !isspace((unsigned char) *s) && *s != '\n') { clen = pg_mblen(s); COPYCHAR(sflag, s); @@ -1120,13 +1123,13 @@ addCompoundAffixFlagValue(IspellDict *Conf, char *s, uint32 val) * flags s. */ static int -getCompoundAffixFlagValue(IspellDict *Conf, char *s) +getCompoundAffixFlagValue(IspellDict *Conf, const char *s) { uint32 flag = 0; CompoundAffixFlag *found, key; char sflag[BUFSIZ]; - char *flagcur; + const char *flagcur; if (Conf->nCompoundAffixFlag == 0) return 0; @@ -1155,7 +1158,7 @@ getCompoundAffixFlagValue(IspellDict *Conf, char *s) * Conf->AffixData array and function returns its entry. * Else function returns the s parameter. */ -static char * +static const char * getAffixFlagSet(IspellDict *Conf, char *s) { if (Conf->useFlagAliases && *s != '\0') @@ -1163,6 +1166,7 @@ getAffixFlagSet(IspellDict *Conf, char *s) int curaffix; char *end; + errno = 0; curaffix = strtol(s, &end, 10); if (s == end || errno == ERANGE) ereport(ERROR, @@ -1225,7 +1229,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) while ((recoded = tsearch_readline(&trst)) != NULL) { - if (*recoded == '\0' || t_isspace(recoded) || t_iseq(recoded, '#')) + if (*recoded == '\0' || isspace((unsigned char) *recoded) || t_iseq(recoded, '#')) { pfree(recoded); continue; @@ -1262,7 +1266,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) { char *s = recoded + strlen("FLAG"); - while (*s && t_isspace(s)) + while (*s && isspace((unsigned char) *s)) s += pg_mblen(s); if (*s) @@ -1298,7 +1302,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) { int fields_read; - if (*recoded == '\0' || t_isspace(recoded) || t_iseq(recoded, '#')) + if (*recoded == '\0' || isspace((unsigned char) *recoded) || t_iseq(recoded, '#')) goto nextline; fields_read = parse_ooaffentry(recoded, type, sflag, find, repl, mask); @@ -1323,7 +1327,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) /* Also reserve place for empty flag set */ naffix++; - Conf->AffixData = (char **) palloc0(naffix * sizeof(char *)); + Conf->AffixData = (const char **) palloc0(naffix * sizeof(char *)); Conf->lenAffixData = Conf->nAffixData = naffix; /* Add empty flag set into AffixData */ @@ -1449,7 +1453,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) while ((recoded = tsearch_readline(&trst)) != NULL) { - pstr = lowerstr(recoded); + pstr = str_tolower(recoded, strlen(recoded), DEFAULT_COLLATION_OID); /* Skip comments and empty lines */ if (*pstr == '#' || *pstr == '\n') @@ -1461,9 +1465,9 @@ NIImportAffixes(IspellDict *Conf, const char *filename) s = findchar2(recoded, 'l', 'L'); if (s) { - while (*s && !t_isspace(s)) + while (*s && !isspace((unsigned char) *s)) s += pg_mblen(s); - while (*s && t_isspace(s)) + while (*s && isspace((unsigned char) *s)) s += pg_mblen(s); if (*s && pg_mblen(s) == 1) @@ -1494,7 +1498,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) s = recoded + 4; /* we need non-lowercased string */ flagflags = 0; - while (*s && t_isspace(s)) + while (*s && isspace((unsigned char) *s)) s += pg_mblen(s); if (*s == '*') @@ -1523,7 +1527,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) s++; if (*s == '\0' || *s == '#' || *s == '\n' || *s == ':' || - t_isspace(s)) + isspace((unsigned char) *s)) { oldformat = true; goto nextline; @@ -1571,7 +1575,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) static int MergeAffix(IspellDict *Conf, int a1, int a2) { - char **ptr; + const char **ptr; Assert(a1 < Conf->nAffixData && a2 < Conf->nAffixData); @@ -1585,24 +1589,28 @@ MergeAffix(IspellDict *Conf, int a1, int a2) if (Conf->nAffixData + 1 >= Conf->lenAffixData) { Conf->lenAffixData *= 2; - Conf->AffixData = (char **) repalloc(Conf->AffixData, - sizeof(char *) * Conf->lenAffixData); + Conf->AffixData = (const char **) repalloc(Conf->AffixData, + sizeof(char *) * Conf->lenAffixData); } ptr = Conf->AffixData + Conf->nAffixData; if (Conf->flagMode == FM_NUM) { - *ptr = cpalloc(strlen(Conf->AffixData[a1]) + - strlen(Conf->AffixData[a2]) + - 1 /* comma */ + 1 /* \0 */ ); - sprintf(*ptr, "%s,%s", Conf->AffixData[a1], Conf->AffixData[a2]); + char *p = cpalloc(strlen(Conf->AffixData[a1]) + + strlen(Conf->AffixData[a2]) + + 1 /* comma */ + 1 /* \0 */ ); + + sprintf(p, "%s,%s", Conf->AffixData[a1], Conf->AffixData[a2]); + *ptr = p; } else { - *ptr = cpalloc(strlen(Conf->AffixData[a1]) + - strlen(Conf->AffixData[a2]) + - 1 /* \0 */ ); - sprintf(*ptr, "%s%s", Conf->AffixData[a1], Conf->AffixData[a2]); + char *p = cpalloc(strlen(Conf->AffixData[a1]) + + strlen(Conf->AffixData[a2]) + + 1 /* \0 */ ); + + sprintf(p, "%s%s", Conf->AffixData[a1], Conf->AffixData[a2]); + *ptr = p; } ptr++; *ptr = NULL; @@ -1735,6 +1743,7 @@ NISortDictionary(IspellDict *Conf) if (*Conf->Spell[i]->p.flag != '\0') { + errno = 0; curaffix = strtol(Conf->Spell[i]->p.flag, &end, 10); if (Conf->Spell[i]->p.flag == end || errno == ERANGE) ereport(ERROR, @@ -1746,7 +1755,7 @@ NISortDictionary(IspellDict *Conf) (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid affix alias \"%s\"", Conf->Spell[i]->p.flag))); - if (*end != '\0' && !t_isdigit(end) && !t_isspace(end)) + if (*end != '\0' && !isdigit((unsigned char) *end) && !isspace((unsigned char) *end)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid affix alias \"%s\"", @@ -1785,7 +1794,7 @@ NISortDictionary(IspellDict *Conf) * dictionary. Replace textual flag-field of Conf->Spell entries with * indexes into Conf->AffixData array. */ - Conf->AffixData = (char **) palloc0(naffix * sizeof(char *)); + Conf->AffixData = (const char **) palloc0(naffix * sizeof(const char *)); curaffix = -1; for (i = 0; i < Conf->nspell; i++) @@ -1954,7 +1963,7 @@ mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix) * returns false. */ static bool -isAffixInUse(IspellDict *Conf, char *affixflag) +isAffixInUse(IspellDict *Conf, const char *affixflag) { int i; @@ -2169,7 +2178,7 @@ addToResult(char **forms, char **cur, char *word) } static char ** -NormalizeSubWord(IspellDict *Conf, char *word, int flag) +NormalizeSubWord(IspellDict *Conf, const char *word, int flag) { AffixNodeData *suffix = NULL, *prefix = NULL; @@ -2255,7 +2264,7 @@ NormalizeSubWord(IspellDict *Conf, char *word, int flag) if (CheckAffix(newword, swrdlen, prefix->aff[j], flag, pnewword, &baselen)) { /* prefix success */ - char *ff = (prefix->aff[j]->flagflags & suffix->aff[i]->flagflags & FF_CROSSPRODUCT) ? + const char *ff = (prefix->aff[j]->flagflags & suffix->aff[i]->flagflags & FF_CROSSPRODUCT) ? VoidString : prefix->aff[j]->flag; if (FindWord(Conf, pnewword, ff, flag)) @@ -2287,7 +2296,7 @@ typedef struct SplitVar } SplitVar; static int -CheckCompoundAffixes(CMPDAffix **ptr, char *word, int len, bool CheckInPlace) +CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPlace) { bool issuffix; @@ -2367,7 +2376,7 @@ AddStem(SplitVar *v, char *word) } static SplitVar * -SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, char *word, int wordlen, int startpos, int minpos) +SplitToVariants(IspellDict *Conf, SPNode *snode, SplitVar *orig, const char *word, int wordlen, int startpos, int minpos) { SplitVar *var = NULL; SPNodeData *StopLow, @@ -2533,7 +2542,7 @@ addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant } TSLexeme * -NINormalizeWord(IspellDict *Conf, char *word) +NINormalizeWord(IspellDict *Conf, const char *word) { char **res; TSLexeme *lcur = NULL, diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c index 88cba58cbab09..4dfcc2cd3bd7e 100644 --- a/src/backend/tsearch/to_tsany.c +++ b/src/backend/tsearch/to_tsany.c @@ -3,7 +3,7 @@ * to_tsany.c * to_ts* function definitions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c index bc44599de6aa5..b77d8c23d3694 100644 --- a/src/backend/tsearch/ts_locale.c +++ b/src/backend/tsearch/ts_locale.c @@ -3,7 +3,7 @@ * ts_locale.c * locale compatibility layer for tsearch * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -31,36 +31,6 @@ static void tsearch_readline_callback(void *arg); */ #define WC_BUF_LEN 3 -int -t_isdigit(const char *ptr) -{ - int clen = pg_mblen(ptr); - wchar_t character[WC_BUF_LEN]; - pg_locale_t mylocale = 0; /* TODO */ - - if (clen == 1 || database_ctype_is_c) - return isdigit(TOUCHAR(ptr)); - - char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale); - - return iswdigit((wint_t) character[0]); -} - -int -t_isspace(const char *ptr) -{ - int clen = pg_mblen(ptr); - wchar_t character[WC_BUF_LEN]; - pg_locale_t mylocale = 0; /* TODO */ - - if (clen == 1 || database_ctype_is_c) - return isspace(TOUCHAR(ptr)); - - char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale); - - return iswspace((wint_t) character[0]); -} - int t_isalpha(const char *ptr) { @@ -91,21 +61,6 @@ t_isalnum(const char *ptr) return iswalnum((wint_t) character[0]); } -int -t_isprint(const char *ptr) -{ - int clen = pg_mblen(ptr); - wchar_t character[WC_BUF_LEN]; - pg_locale_t mylocale = 0; /* TODO */ - - if (clen == 1 || database_ctype_is_c) - return isprint(TOUCHAR(ptr)); - - char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale); - - return iswprint((wint_t) character[0]); -} - /* * Set up to read a file using tsearch_readline(). This facility is @@ -142,7 +97,7 @@ tsearch_readline_begin(tsearch_readline_state *stp, stp->curline = NULL; /* Setup error traceback support for ereport() */ stp->cb.callback = tsearch_readline_callback; - stp->cb.arg = (void *) stp; + stp->cb.arg = stp; stp->cb.previous = error_context_stack; error_context_stack = &stp->cb; return true; @@ -242,92 +197,3 @@ tsearch_readline_callback(void *arg) stp->lineno, stp->filename); } - - -/* - * lowerstr --- fold null-terminated string to lower case - * - * Returned string is palloc'd - */ -char * -lowerstr(const char *str) -{ - return lowerstr_with_len(str, strlen(str)); -} - -/* - * lowerstr_with_len --- fold string to lower case - * - * Input string need not be null-terminated. - * - * Returned string is palloc'd - */ -char * -lowerstr_with_len(const char *str, int len) -{ - char *out; - pg_locale_t mylocale = 0; /* TODO */ - - if (len == 0) - return pstrdup(""); - - /* - * Use wide char code only when max encoding length > 1 and ctype != C. - * Some operating systems fail with multi-byte encodings and a C locale. - * Also, for a C locale there is no need to process as multibyte. From - * backend/utils/adt/oracle_compat.c Teodor - */ - if (pg_database_encoding_max_length() > 1 && !database_ctype_is_c) - { - wchar_t *wstr, - *wptr; - int wlen; - - /* - * alloc number of wchar_t for worst case, len contains number of - * bytes >= number of characters and alloc 1 wchar_t for 0, because - * wchar2char wants zero-terminated string - */ - wptr = wstr = (wchar_t *) palloc(sizeof(wchar_t) * (len + 1)); - - wlen = char2wchar(wstr, len + 1, str, len, mylocale); - Assert(wlen <= len); - - while (*wptr) - { - *wptr = towlower((wint_t) *wptr); - wptr++; - } - - /* - * Alloc result string for worst case + '\0' - */ - len = pg_database_encoding_max_length() * wlen + 1; - out = (char *) palloc(len); - - wlen = wchar2char(out, wstr, len, mylocale); - - pfree(wstr); - - if (wlen < 0) - ereport(ERROR, - (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), - errmsg("conversion from wchar_t to server encoding failed: %m"))); - Assert(wlen < len); - } - else - { - const char *ptr = str; - char *outptr; - - outptr = out = (char *) palloc(sizeof(char) * (len + 1)); - while ((ptr - str) < len && *ptr) - { - *outptr++ = tolower(TOUCHAR(ptr)); - ptr++; - } - *outptr = '\0'; - } - - return out; -} diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c index 517f200a9b451..e5da6cf17ec19 100644 --- a/src/backend/tsearch/ts_parse.c +++ b/src/backend/tsearch/ts_parse.c @@ -3,7 +3,7 @@ * ts_parse.c * main parse functions for tsearch * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -366,9 +366,9 @@ parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen) cfg = lookup_ts_config_cache(cfgId); prsobj = lookup_ts_parser_cache(cfg->prsId); - prsdata = (void *) DatumGetPointer(FunctionCall2(&prsobj->prsstart, - PointerGetDatum(buf), - Int32GetDatum(buflen))); + prsdata = DatumGetPointer(FunctionCall2(&prsobj->prsstart, + PointerGetDatum(buf), + Int32GetDatum(buflen))); LexizeInit(&ldata, cfg); @@ -552,9 +552,9 @@ hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query, char *buf, int bu cfg = lookup_ts_config_cache(cfgId); prsobj = lookup_ts_parser_cache(cfg->prsId); - prsdata = (void *) DatumGetPointer(FunctionCall2(&(prsobj->prsstart), - PointerGetDatum(buf), - Int32GetDatum(buflen))); + prsdata = DatumGetPointer(FunctionCall2(&(prsobj->prsstart), + PointerGetDatum(buf), + Int32GetDatum(buflen))); LexizeInit(&ldata, cfg); diff --git a/src/backend/tsearch/ts_selfuncs.c b/src/backend/tsearch/ts_selfuncs.c index c549231dc617a..0c1d2bc1109da 100644 --- a/src/backend/tsearch/ts_selfuncs.c +++ b/src/backend/tsearch/ts_selfuncs.c @@ -3,7 +3,7 @@ * ts_selfuncs.c * Selectivity estimation functions for text search operators. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c index ccafe42729764..c5a71331ce8a0 100644 --- a/src/backend/tsearch/ts_typanalyze.c +++ b/src/backend/tsearch/ts_typanalyze.c @@ -3,7 +3,7 @@ * ts_typanalyze.c * functions for gathering statistics from tsvector columns * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -204,7 +204,7 @@ compute_tsvector_stats(VacAttrStats *stats, char *lexemesptr; int j; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, vector_no, &isnull); diff --git a/src/backend/tsearch/ts_utils.c b/src/backend/tsearch/ts_utils.c index 81967d29e9aad..0b4a57866448d 100644 --- a/src/backend/tsearch/ts_utils.c +++ b/src/backend/tsearch/ts_utils.c @@ -3,7 +3,7 @@ * ts_utils.c * various support functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -16,6 +16,7 @@ #include +#include "catalog/pg_collation_d.h" #include "miscadmin.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" @@ -65,7 +66,7 @@ get_tsearch_config_filename(const char *basename, * or palloc a new version. */ void -readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *)) +readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *, size_t, Oid)) { char **stop = NULL; @@ -88,7 +89,7 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *)) char *pbuf = line; /* Trim trailing space */ - while (*pbuf && !t_isspace(pbuf)) + while (*pbuf && !isspace((unsigned char) *pbuf)) pbuf += pg_mblen(pbuf); *pbuf = '\0'; @@ -115,7 +116,7 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *)) if (wordop) { - stop[s->len] = wordop(line); + stop[s->len] = wordop(line, strlen(line), DEFAULT_COLLATION_OID); if (stop[s->len] != line) pfree(line); } diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c index bc9fb38426c66..a8ddb6109910e 100644 --- a/src/backend/tsearch/wparser.c +++ b/src/backend/tsearch/wparser.c @@ -3,7 +3,7 @@ * wparser.c * Standard interface to word parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -63,7 +63,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, /* lextype takes one dummy argument */ st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid, (Datum) 0)); - funcctx->user_fctx = (void *) st; + funcctx->user_fctx = st; if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); @@ -178,9 +178,9 @@ prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, st->len = 16; st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len); - prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart, - PointerGetDatum(VARDATA_ANY(txt)), - Int32GetDatum(VARSIZE_ANY_EXHDR(txt)))); + prsdata = DatumGetPointer(FunctionCall2(&prs->prsstart, + PointerGetDatum(VARDATA_ANY(txt)), + Int32GetDatum(VARSIZE_ANY_EXHDR(txt)))); while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken, PointerGetDatum(prsdata), diff --git a/src/backend/tsearch/wparser_def.c b/src/backend/tsearch/wparser_def.c index 3919ef27b57d7..79bcd32a0639e 100644 --- a/src/backend/tsearch/wparser_def.c +++ b/src/backend/tsearch/wparser_def.c @@ -3,7 +3,7 @@ * wparser_def.c * Default text search parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -2671,19 +2671,19 @@ prsd_headline(PG_FUNCTION_ARGS) if (min_words >= max_words) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MinWords should be less than MaxWords"))); + errmsg("%s must be less than %s", "MinWords", "MaxWords"))); if (min_words <= 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MinWords should be positive"))); + errmsg("%s must be positive", "MinWords"))); if (shortword < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("ShortWord should be >= 0"))); + errmsg("%s must be >= 0", "ShortWord"))); if (max_fragments < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("MaxFragments should be >= 0"))); + errmsg("%s must be >= 0", "MaxFragments"))); } /* Locate words and phrases matching the query */ diff --git a/src/backend/utils/Gen_dummy_probes.pl b/src/backend/utils/Gen_dummy_probes.pl index 137f58b85b628..489cccf3ece12 100644 --- a/src/backend/utils/Gen_dummy_probes.pl +++ b/src/backend/utils/Gen_dummy_probes.pl @@ -1,7 +1,7 @@ #------------------------------------------------------------------------- # Perl script to create dummy probes.h file when dtrace is not available # -# Copyright (c) 2008-2024, PostgreSQL Global Development Group +# Copyright (c) 2008-2025, PostgreSQL Global Development Group # # src/backend/utils/Gen_dummy_probes.pl #------------------------------------------------------------------------- diff --git a/src/backend/utils/Gen_fmgrtab.pl b/src/backend/utils/Gen_fmgrtab.pl index 37628a85c73c3..247e1c6ab4c0d 100644 --- a/src/backend/utils/Gen_fmgrtab.pl +++ b/src/backend/utils/Gen_fmgrtab.pl @@ -5,7 +5,7 @@ # Perl script that generates fmgroids.h, fmgrprotos.h, and fmgrtab.c # from pg_proc.dat # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # @@ -109,7 +109,7 @@ * These macros can be used to avoid a catalog lookup when a specific * fmgr-callable function needs to be referenced. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -140,7 +140,7 @@ * fmgrprotos.h * Prototypes for built-in functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -166,7 +166,7 @@ * fmgrtab.c * The function manager's table of internal functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -182,7 +182,6 @@ #include "postgres.h" -#include "access/transam.h" #include "utils/fmgrtab.h" #include "utils/fmgrprotos.h" diff --git a/src/backend/utils/Makefile b/src/backend/utils/Makefile index 394c130d64fcd..140fbba5c222a 100644 --- a/src/backend/utils/Makefile +++ b/src/backend/utils/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/utils # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/utils/Makefile diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile index b9fd66ea17cea..9c2443e1ecd37 100644 --- a/src/backend/utils/activity/Makefile +++ b/src/backend/utils/activity/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/utils/activity # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/utils/activity/Makefile @@ -20,6 +20,7 @@ OBJS = \ backend_status.o \ pgstat.o \ pgstat_archiver.o \ + pgstat_backend.o \ pgstat_bgwriter.o \ pgstat_checkpointer.o \ pgstat_database.o \ diff --git a/src/backend/utils/activity/backend_progress.c b/src/backend/utils/activity/backend_progress.c index c78c5eb507642..99a8c73bf0470 100644 --- a/src/backend/utils/activity/backend_progress.c +++ b/src/backend/utils/activity/backend_progress.c @@ -3,7 +3,7 @@ * * Command progress reporting infrastructure. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/backend/utils/activity/backend_progress.c * ---------- @@ -12,7 +12,6 @@ #include "access/parallel.h" #include "libpq/pqformat.h" -#include "port/atomics.h" /* for memory barriers */ #include "utils/backend_progress.h" #include "utils/backend_status.h" diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c index 1ccf4c6d839e1..a290cc4c97501 100644 --- a/src/backend/utils/activity/backend_status.c +++ b/src/backend/utils/activity/backend_status.c @@ -2,7 +2,7 @@ * backend_status.c * Backend status reporting infrastructure. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -16,11 +16,9 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" -#include "port/atomics.h" /* for memory barriers */ #include "storage/ipc.h" #include "storage/proc.h" /* for MyProc */ #include "storage/procarray.h" -#include "storage/sinvaladt.h" #include "utils/ascii.h" #include "utils/guc.h" /* for application_name */ #include "utils/memutils.h" @@ -77,7 +75,7 @@ static void pgstat_setup_backend_status_context(void); /* - * Report shared-memory space needed by CreateSharedBackendStatus. + * Report shared-memory space needed by BackendStatusShmemInit. */ Size BackendStatusShmemSize(void) @@ -113,7 +111,7 @@ BackendStatusShmemSize(void) * during postmaster startup. */ void -CreateSharedBackendStatus(void) +BackendStatusShmemInit(void) { Size size; bool found; @@ -257,29 +255,22 @@ pgstat_beinit(void) /* ---------- - * pgstat_bestart() - + * pgstat_bestart_initial() - * - * Initialize this backend's entry in the PgBackendStatus array. - * Called from InitPostgres. + * Initialize this backend's entry in the PgBackendStatus array. Called + * from InitPostgres and AuxiliaryProcessMain. * - * Apart from auxiliary processes, MyDatabaseId, session userid, and - * application_name must already be set (hence, this cannot be combined - * with pgstat_beinit). Note also that we must be inside a transaction - * if this isn't an aux process, as we may need to do encoding conversion - * on some strings. - *---------- + * Clears out a new pgstat entry, initializing it to suitable defaults and + * reporting STATE_STARTING. Backends should continue filling in any + * transport security details as needed with pgstat_bestart_security(), and + * must finally exit STATE_STARTING by calling pgstat_bestart_final(). + * ---------- */ void -pgstat_bestart(void) +pgstat_bestart_initial(void) { volatile PgBackendStatus *vbeentry = MyBEEntry; PgBackendStatus lbeentry; -#ifdef USE_SSL - PgBackendSSLStatus lsslstatus; -#endif -#ifdef ENABLE_GSS - PgBackendGSSStatus lgssstatus; -#endif /* pgstats state must be initialized from pgstat_beinit() */ Assert(vbeentry != NULL); @@ -299,14 +290,6 @@ pgstat_bestart(void) unvolatize(PgBackendStatus *, vbeentry), sizeof(PgBackendStatus)); - /* These structs can just start from zeroes each time, though */ -#ifdef USE_SSL - memset(&lsslstatus, 0, sizeof(lsslstatus)); -#endif -#ifdef ENABLE_GSS - memset(&lgssstatus, 0, sizeof(lgssstatus)); -#endif - /* * Now fill in all the fields of lbeentry, except for strings that are * out-of-line data. Those have to be handled separately, below. @@ -317,15 +300,8 @@ pgstat_bestart(void) lbeentry.st_activity_start_timestamp = 0; lbeentry.st_state_start_timestamp = 0; lbeentry.st_xact_start_timestamp = 0; - lbeentry.st_databaseid = MyDatabaseId; - - /* We have userid for client-backends, wal-sender and bgworker processes */ - if (lbeentry.st_backendType == B_BACKEND - || lbeentry.st_backendType == B_WAL_SENDER - || lbeentry.st_backendType == B_BG_WORKER) - lbeentry.st_userid = GetSessionUserId(); - else - lbeentry.st_userid = InvalidOid; + lbeentry.st_databaseid = InvalidOid; + lbeentry.st_userid = InvalidOid; /* * We may not have a MyProcPort (eg, if this is the autovacuum process). @@ -338,49 +314,14 @@ pgstat_bestart(void) else MemSet(&lbeentry.st_clientaddr, 0, sizeof(lbeentry.st_clientaddr)); -#ifdef USE_SSL - if (MyProcPort && MyProcPort->ssl_in_use) - { - lbeentry.st_ssl = true; - lsslstatus.ssl_bits = be_tls_get_cipher_bits(MyProcPort); - strlcpy(lsslstatus.ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN); - strlcpy(lsslstatus.ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN); - be_tls_get_peer_subject_name(MyProcPort, lsslstatus.ssl_client_dn, NAMEDATALEN); - be_tls_get_peer_serial(MyProcPort, lsslstatus.ssl_client_serial, NAMEDATALEN); - be_tls_get_peer_issuer_name(MyProcPort, lsslstatus.ssl_issuer_dn, NAMEDATALEN); - } - else - { - lbeentry.st_ssl = false; - } -#else lbeentry.st_ssl = false; -#endif - -#ifdef ENABLE_GSS - if (MyProcPort && MyProcPort->gss != NULL) - { - const char *princ = be_gssapi_get_princ(MyProcPort); - - lbeentry.st_gss = true; - lgssstatus.gss_auth = be_gssapi_get_auth(MyProcPort); - lgssstatus.gss_enc = be_gssapi_get_enc(MyProcPort); - lgssstatus.gss_delegation = be_gssapi_get_delegation(MyProcPort); - if (princ) - strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN); - } - else - { - lbeentry.st_gss = false; - } -#else lbeentry.st_gss = false; -#endif - lbeentry.st_state = STATE_UNDEFINED; + lbeentry.st_state = STATE_STARTING; lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID; lbeentry.st_progress_command_target = InvalidOid; - lbeentry.st_query_id = UINT64CONST(0); + lbeentry.st_query_id = INT64CONST(0); + lbeentry.st_plan_id = INT64CONST(0); /* * we don't zero st_progress_param here to save cycles; nobody should @@ -419,14 +360,142 @@ pgstat_bestart(void) lbeentry.st_clienthostname[NAMEDATALEN - 1] = '\0'; lbeentry.st_activity_raw[pgstat_track_activity_query_size - 1] = '\0'; + /* These structs can just start from zeroes each time */ #ifdef USE_SSL - memcpy(lbeentry.st_sslstatus, &lsslstatus, sizeof(PgBackendSSLStatus)); + memset(lbeentry.st_sslstatus, 0, sizeof(PgBackendSSLStatus)); #endif #ifdef ENABLE_GSS - memcpy(lbeentry.st_gssstatus, &lgssstatus, sizeof(PgBackendGSSStatus)); + memset(lbeentry.st_gssstatus, 0, sizeof(PgBackendGSSStatus)); #endif PGSTAT_END_WRITE_ACTIVITY(vbeentry); +} + +/* ---------- + * pgstat_bestart_security() - + * + * Fill in SSL and GSS information for the pgstat entry. This is the second + * optional step taken when filling a backend's entry, not required for + * auxiliary processes. + * + * This should only be called from backends with a MyProcPort. + * ---------- + */ +void +pgstat_bestart_security(void) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + bool ssl = false; + bool gss = false; +#ifdef USE_SSL + PgBackendSSLStatus lsslstatus; + PgBackendSSLStatus *st_sslstatus; +#endif +#ifdef ENABLE_GSS + PgBackendGSSStatus lgssstatus; + PgBackendGSSStatus *st_gssstatus; +#endif + + /* pgstats state must be initialized from pgstat_beinit() */ + Assert(beentry != NULL); + Assert(MyProcPort); /* otherwise there's no point */ + +#ifdef USE_SSL + st_sslstatus = beentry->st_sslstatus; + memset(&lsslstatus, 0, sizeof(lsslstatus)); + + if (MyProcPort->ssl_in_use) + { + ssl = true; + lsslstatus.ssl_bits = be_tls_get_cipher_bits(MyProcPort); + strlcpy(lsslstatus.ssl_version, be_tls_get_version(MyProcPort), NAMEDATALEN); + strlcpy(lsslstatus.ssl_cipher, be_tls_get_cipher(MyProcPort), NAMEDATALEN); + be_tls_get_peer_subject_name(MyProcPort, lsslstatus.ssl_client_dn, NAMEDATALEN); + be_tls_get_peer_serial(MyProcPort, lsslstatus.ssl_client_serial, NAMEDATALEN); + be_tls_get_peer_issuer_name(MyProcPort, lsslstatus.ssl_issuer_dn, NAMEDATALEN); + } +#endif + +#ifdef ENABLE_GSS + st_gssstatus = beentry->st_gssstatus; + memset(&lgssstatus, 0, sizeof(lgssstatus)); + + if (MyProcPort->gss != NULL) + { + const char *princ = be_gssapi_get_princ(MyProcPort); + + gss = true; + lgssstatus.gss_auth = be_gssapi_get_auth(MyProcPort); + lgssstatus.gss_enc = be_gssapi_get_enc(MyProcPort); + lgssstatus.gss_delegation = be_gssapi_get_delegation(MyProcPort); + if (princ) + strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN); + } +#endif + + /* + * Update my status entry, following the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); + + beentry->st_ssl = ssl; + beentry->st_gss = gss; + +#ifdef USE_SSL + memcpy(st_sslstatus, &lsslstatus, sizeof(PgBackendSSLStatus)); +#endif +#ifdef ENABLE_GSS + memcpy(st_gssstatus, &lgssstatus, sizeof(PgBackendGSSStatus)); +#endif + + PGSTAT_END_WRITE_ACTIVITY(beentry); +} + +/* ---------- + * pgstat_bestart_final() - + * + * Finalizes the state of this backend's entry by filling in the user and + * database IDs, clearing STATE_STARTING, and reporting the application_name. + * + * We must be inside a transaction if this is not an auxiliary process, as + * we may need to do encoding conversion. + * ---------- + */ +void +pgstat_bestart_final(void) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + Oid userid; + + /* pgstats state must be initialized from pgstat_beinit() */ + Assert(beentry != NULL); + + /* We have userid for client-backends, wal-sender and bgworker processes */ + if (MyBackendType == B_BACKEND + || MyBackendType == B_WAL_SENDER + || MyBackendType == B_BG_WORKER) + userid = GetSessionUserId(); + else + userid = InvalidOid; + + /* + * Update my status entry, following the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); + + beentry->st_databaseid = MyDatabaseId; + beentry->st_userid = userid; + beentry->st_state = STATE_UNDEFINED; + + PGSTAT_END_WRITE_ACTIVITY(beentry); + + /* Create the backend statistics entry */ + if (pgstat_tracks_backend_bktype(MyBackendType)) + pgstat_create_backend(MyProcNumber); /* Update app name to current GUC setting */ if (application_name) @@ -530,7 +599,8 @@ pgstat_report_activity(BackendState state, const char *cmd_str) beentry->st_activity_start_timestamp = 0; /* st_xact_start_timestamp and wait_event_info are also disabled */ beentry->st_xact_start_timestamp = 0; - beentry->st_query_id = UINT64CONST(0); + beentry->st_query_id = INT64CONST(0); + beentry->st_plan_id = INT64CONST(0); proc->wait_event_info = 0; PGSTAT_END_WRITE_ACTIVITY(beentry); } @@ -591,11 +661,14 @@ pgstat_report_activity(BackendState state, const char *cmd_str) * identifier. */ if (state == STATE_RUNNING) - beentry->st_query_id = UINT64CONST(0); + { + beentry->st_query_id = INT64CONST(0); + beentry->st_plan_id = INT64CONST(0); + } if (cmd_str != NULL) { - memcpy((char *) beentry->st_activity_raw, cmd_str, len); + memcpy(beentry->st_activity_raw, cmd_str, len); beentry->st_activity_raw[len] = '\0'; beentry->st_activity_start_timestamp = start_timestamp; } @@ -610,7 +683,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str) * -------- */ void -pgstat_report_query_id(uint64 query_id, bool force) +pgstat_report_query_id(int64 query_id, bool force) { volatile PgBackendStatus *beentry = MyBEEntry; @@ -629,7 +702,7 @@ pgstat_report_query_id(uint64 query_id, bool force) * command, so ignore the one provided unless it's an explicit call to * reset the identifier. */ - if (beentry->st_query_id != 0 && !force) + if (beentry->st_query_id != INT64CONST(0) && !force) return; /* @@ -642,6 +715,44 @@ pgstat_report_query_id(uint64 query_id, bool force) PGSTAT_END_WRITE_ACTIVITY(beentry); } +/* -------- + * pgstat_report_plan_id() - + * + * Called to update top-level plan identifier. + * -------- + */ +void +pgstat_report_plan_id(int64 plan_id, bool force) +{ + volatile PgBackendStatus *beentry = MyBEEntry; + + /* + * if track_activities is disabled, st_plan_id should already have been + * reset + */ + if (!beentry || !pgstat_track_activities) + return; + + /* + * We only report the top-level plan identifiers. The stored plan_id is + * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or + * with an explicit call to this function using the force flag. If the + * saved plan identifier is not zero it means that it's not a top-level + * command, so ignore the one provided unless it's an explicit call to + * reset the identifier. + */ + if (beentry->st_plan_id != 0 && !force) + return; + + /* + * Update my status entry, following the protocol of bumping + * st_changecount before and after. We use a volatile pointer here to + * ensure the compiler doesn't try to get cute. + */ + PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); + beentry->st_plan_id = plan_id; + PGSTAT_END_WRITE_ACTIVITY(beentry); +} /* ---------- * pgstat_report_appname() - @@ -668,7 +779,7 @@ pgstat_report_appname(const char *appname) */ PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); - memcpy((char *) beentry->st_appname, appname, len); + memcpy(beentry->st_appname, appname, len); beentry->st_appname[len] = '\0'; PGSTAT_END_WRITE_ACTIVITY(beentry); @@ -793,11 +904,11 @@ pgstat_read_current_status(void) * strcpy is safe even if the string is modified concurrently, * because there's always a \0 at the end of the buffer. */ - strcpy(localappname, (char *) beentry->st_appname); + strcpy(localappname, beentry->st_appname); localentry->backendStatus.st_appname = localappname; - strcpy(localclienthostname, (char *) beentry->st_clienthostname); + strcpy(localclienthostname, beentry->st_clienthostname); localentry->backendStatus.st_clienthostname = localclienthostname; - strcpy(localactivity, (char *) beentry->st_activity_raw); + strcpy(localactivity, beentry->st_activity_raw); localentry->backendStatus.st_activity_raw = localactivity; #ifdef USE_SSL if (beentry->st_ssl) @@ -1023,7 +1134,7 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen) * * Return current backend's query identifier. */ -uint64 +int64 pgstat_get_my_query_id(void) { if (!MyBEEntry) @@ -1038,6 +1149,46 @@ pgstat_get_my_query_id(void) return MyBEEntry->st_query_id; } +/* ---------- + * pgstat_get_my_plan_id() - + * + * Return current backend's plan identifier. + */ +int64 +pgstat_get_my_plan_id(void) +{ + if (!MyBEEntry) + return 0; + + /* No need for a lock, for roughly the same reasons as above. */ + return MyBEEntry->st_plan_id; +} + +/* ---------- + * pgstat_get_backend_type_by_proc_number() - + * + * Return the type of the backend with the specified ProcNumber. This looks + * directly at the BackendStatusArray, so the return value may be out of date. + * The only current use of this function is in pg_signal_backend(), which is + * inherently racy, so we don't worry too much about this. + * + * It is the caller's responsibility to use this wisely; at minimum, callers + * should ensure that procNumber is valid and perform the required permissions + * checks. + * ---------- + */ +BackendType +pgstat_get_backend_type_by_proc_number(ProcNumber procNumber) +{ + volatile PgBackendStatus *status = &BackendStatusArray[procNumber]; + + /* + * We bypass the changecount mechanism since fetching and storing an int + * is almost certainly atomic. + */ + return status->st_backendType; +} + /* ---------- * cmp_lbestatus * diff --git a/src/backend/utils/activity/generate-wait_event_types.pl b/src/backend/utils/activity/generate-wait_event_types.pl index 2f2fa5bb8f418..424ad9f115d34 100644 --- a/src/backend/utils/activity/generate-wait_event_types.pl +++ b/src/backend/utils/activity/generate-wait_event_types.pl @@ -7,7 +7,7 @@ # - wait_event_funcs_data.c (if --code is passed) # - wait_event_types.sgml (if --docs is passed) # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/utils/activity/generate-wait_event_types.pl @@ -150,7 +150,7 @@ * %s * Generated wait events infrastructure code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -168,7 +168,7 @@ printf $h $header_comment, 'wait_event_types.h'; printf $h "#ifndef WAIT_EVENT_TYPES_H\n"; printf $h "#define WAIT_EVENT_TYPES_H\n\n"; - printf $h "#include \"utils/wait_event.h\"\n\n"; + printf $h "#include \"utils/wait_classes.h\"\n\n"; printf $c $header_comment, 'pgstat_wait_event.c'; diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build index f73c22905c272..d8e56b49c247d 100644 --- a/src/backend/utils/activity/meson.build +++ b/src/backend/utils/activity/meson.build @@ -1,10 +1,11 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'backend_progress.c', 'backend_status.c', 'pgstat.c', 'pgstat_archiver.c', + 'pgstat_backend.c', 'pgstat_bgwriter.c', 'pgstat_checkpointer.c', 'pgstat_database.c', diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 2e22bf270781a..8b57845e8709f 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -12,7 +12,8 @@ * Statistics are loaded from the filesystem during startup (by the startup * process), unless preceded by a crash, in which case all stats are * discarded. They are written out by the checkpointer process just before - * shutting down, except when shutting down in immediate mode. + * shutting down (if the stats kind allows it), except when shutting down in + * immediate mode. * * Fixed-numbered stats are stored in plain (non-dynamic) shared memory. * @@ -49,8 +50,16 @@ * pgStatPending list. Pending statistics updates are flushed out by * pgstat_report_stat(). * + * It is possible for external modules to define custom statistics kinds, + * that can use the same properties as any built-in stats kinds. Each custom + * stats kind needs to assign a unique ID to ensure that it does not overlap + * with other extensions. In order to reserve a unique stats kind ID, refer + * to https://wiki.postgresql.org/wiki/CustomCumulativeStats. + * * The behavior of different kinds of statistics is determined by the kind's - * entry in pgstat_kind_infos, see PgStat_KindInfo for details. + * entry in pgstat_kind_builtin_infos for all the built-in statistics kinds + * defined, and pgstat_kind_custom_infos for custom kinds registered at + * startup by pgstat_register_kind(). See PgStat_KindInfo for details. * * The consistency of read accesses to statistics can be configured using the * stats_fetch_consistency GUC (see config.sgml and monitoring.sgml for the @@ -68,6 +77,7 @@ * * Each statistics kind is handled in a dedicated file: * - pgstat_archiver.c + * - pgstat_backend.c * - pgstat_bgwriter.c * - pgstat_checkpointer.c * - pgstat_database.c @@ -83,7 +93,7 @@ * specific kinds of stats. * * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat.c @@ -96,7 +106,6 @@ #include "access/xact.h" #include "lib/dshash.h" #include "pgstat.h" -#include "port/atomics.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/lwlock.h" @@ -174,6 +183,8 @@ typedef struct PgStat_SnapshotEntry static void pgstat_write_statsfile(void); static void pgstat_read_statsfile(void); +static void pgstat_init_snapshot_fixed(void); + static void pgstat_reset_after_failure(void); static bool pgstat_flush_pending_entries(bool nowait); @@ -182,7 +193,7 @@ static void pgstat_prep_snapshot(void); static void pgstat_build_snapshot(void); static void pgstat_build_snapshot_fixed(PgStat_Kind kind); -static inline bool pgstat_is_kind_valid(int ikind); +static inline bool pgstat_is_kind_valid(PgStat_Kind kind); /* ---------- @@ -251,7 +262,7 @@ static bool pgstat_is_shutdown = false; /* - * The different kinds of statistics. + * The different kinds of built-in statistics. * * If reasonably possible, handling specific to one kind of stats should go * through this abstraction, rather than making more of pgstat.c aware. @@ -263,7 +274,7 @@ static bool pgstat_is_shutdown = false; * seem to be a great way of doing that, given the split across multiple * files. */ -static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { +static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE] = { /* stats kinds for variable-numbered objects */ @@ -271,6 +282,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "database", .fixed_amount = false, + .write_to_file = true, /* so pg_stat_database entries can be seen in all databases */ .accessed_across_databases = true, @@ -287,6 +299,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "relation", .fixed_amount = false, + .write_to_file = true, .shared_size = sizeof(PgStatShared_Relation), .shared_data_off = offsetof(PgStatShared_Relation, stats), @@ -301,6 +314,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "function", .fixed_amount = false, + .write_to_file = true, .shared_size = sizeof(PgStatShared_Function), .shared_data_off = offsetof(PgStatShared_Function, stats), @@ -314,6 +328,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "replslot", .fixed_amount = false, + .write_to_file = true, .accessed_across_databases = true, @@ -330,6 +345,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "subscription", .fixed_amount = false, + .write_to_file = true, /* so pg_stat_subscription_stats entries can be seen in all databases */ .accessed_across_databases = true, @@ -342,6 +358,22 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .reset_timestamp_cb = pgstat_subscription_reset_timestamp_cb, }, + [PGSTAT_KIND_BACKEND] = { + .name = "backend", + + .fixed_amount = false, + .write_to_file = false, + + .accessed_across_databases = true, + + .shared_size = sizeof(PgStatShared_Backend), + .shared_data_off = offsetof(PgStatShared_Backend, stats), + .shared_data_len = sizeof(((PgStatShared_Backend *) 0)->stats), + + .have_static_pending_cb = pgstat_backend_have_pending_cb, + .flush_static_cb = pgstat_backend_flush_cb, + .reset_timestamp_cb = pgstat_backend_reset_timestamp_cb, + }, /* stats for fixed-numbered (mostly 1) objects */ @@ -349,6 +381,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "archiver", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, archiver), .shared_ctl_off = offsetof(PgStat_ShmemControl, archiver), @@ -364,6 +397,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "bgwriter", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, bgwriter), .shared_ctl_off = offsetof(PgStat_ShmemControl, bgwriter), @@ -379,6 +413,7 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "checkpointer", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, checkpointer), .shared_ctl_off = offsetof(PgStat_ShmemControl, checkpointer), @@ -394,12 +429,15 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "io", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, io), .shared_ctl_off = offsetof(PgStat_ShmemControl, io), .shared_data_off = offsetof(PgStatShared_IO, stats), .shared_data_len = sizeof(((PgStatShared_IO *) 0)->stats), + .flush_static_cb = pgstat_io_flush_cb, + .have_static_pending_cb = pgstat_io_have_pending_cb, .init_shmem_cb = pgstat_io_init_shmem_cb, .reset_all_cb = pgstat_io_reset_all_cb, .snapshot_cb = pgstat_io_snapshot_cb, @@ -409,12 +447,15 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "slru", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, slru), .shared_ctl_off = offsetof(PgStat_ShmemControl, slru), .shared_data_off = offsetof(PgStatShared_SLRU, stats), .shared_data_len = sizeof(((PgStatShared_SLRU *) 0)->stats), + .flush_static_cb = pgstat_slru_flush_cb, + .have_static_pending_cb = pgstat_slru_have_pending_cb, .init_shmem_cb = pgstat_slru_init_shmem_cb, .reset_all_cb = pgstat_slru_reset_all_cb, .snapshot_cb = pgstat_slru_snapshot_cb, @@ -424,18 +465,31 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = { .name = "wal", .fixed_amount = true, + .write_to_file = true, .snapshot_ctl_off = offsetof(PgStat_Snapshot, wal), .shared_ctl_off = offsetof(PgStat_ShmemControl, wal), .shared_data_off = offsetof(PgStatShared_Wal, stats), .shared_data_len = sizeof(((PgStatShared_Wal *) 0)->stats), + .init_backend_cb = pgstat_wal_init_backend_cb, + .flush_static_cb = pgstat_wal_flush_cb, + .have_static_pending_cb = pgstat_wal_have_pending_cb, .init_shmem_cb = pgstat_wal_init_shmem_cb, .reset_all_cb = pgstat_wal_reset_all_cb, .snapshot_cb = pgstat_wal_snapshot_cb, }, }; +/* + * Information about custom statistics kinds. + * + * These are saved in a different array than the built-in kinds to save + * in clarity with the initializations. + * + * Indexed by PGSTAT_KIND_CUSTOM_MIN, of size PGSTAT_KIND_CUSTOM_SIZE. + */ +static const PgStat_KindInfo **pgstat_kind_custom_infos = NULL; /* ------------------------------------------------------------ * Functions managing the state of the stats system for all backends. @@ -564,6 +618,10 @@ pgstat_shutdown_hook(int code, Datum arg) Assert(dlist_is_empty(&pgStatPending)); dlist_init(&pgStatPending); + /* drop the backend stats entry */ + if (!pgstat_drop_entry(PGSTAT_KIND_BACKEND, InvalidOid, MyProcNumber)) + pgstat_request_entry_refs_gc(); + pgstat_detach_shmem(); #ifdef USE_ASSERT_CHECKING @@ -584,7 +642,18 @@ pgstat_initialize(void) pgstat_attach_shmem(); - pgstat_init_wal(); + pgstat_init_snapshot_fixed(); + + /* Backend initialization callbacks */ + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (kind_info == NULL || kind_info->init_backend_cb == NULL) + continue; + + kind_info->init_backend_cb(); + } /* Set up a process-exit hook to clean up */ before_shmem_exit(pgstat_shutdown_hook, 0); @@ -639,13 +708,29 @@ pgstat_report_stat(bool force) } /* Don't expend a clock check if nothing to do */ - if (dlist_is_empty(&pgStatPending) && - !have_iostats && - !have_slrustats && - !pgstat_have_pending_wal()) + if (dlist_is_empty(&pgStatPending)) { - Assert(pending_since == 0); - return 0; + bool do_flush = false; + + /* Check for pending stats */ + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (!kind_info) + continue; + if (!kind_info->have_static_pending_cb) + continue; + + if (kind_info->have_static_pending_cb()) + { + do_flush = true; + break; + } + } + + if (!do_flush) + return 0; } /* @@ -695,17 +780,21 @@ pgstat_report_stat(bool force) partial_flush = false; - /* flush database / relation / function / ... stats */ + /* flush of variable-numbered stats tracked in pending entries list */ partial_flush |= pgstat_flush_pending_entries(nowait); - /* flush IO stats */ - partial_flush |= pgstat_flush_io(nowait); + /* flush of other stats kinds */ + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); - /* flush wal stats */ - partial_flush |= pgstat_flush_wal(nowait); + if (!kind_info) + continue; + if (!kind_info->flush_static_cb) + continue; - /* flush SLRU stats */ - partial_flush |= pgstat_slru_flush(nowait); + partial_flush |= kind_info->flush_static_cb(nowait); + } last_flush = now; @@ -775,7 +864,7 @@ pgstat_reset_counters(void) * GRANT system. */ void -pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); TimestampTz ts = GetCurrentTimestamp(); @@ -784,7 +873,7 @@ pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid) Assert(!pgstat_get_kind_info(kind)->fixed_amount); /* reset the "single counter" */ - pgstat_reset_entry(kind, dboid, objoid, ts); + pgstat_reset_entry(kind, dboid, objid, ts); if (!kind_info->accessed_across_databases) pgstat_reset_database_timestamp(dboid, ts); @@ -829,6 +918,8 @@ pgstat_clear_snapshot(void) memset(&pgStatLocal.snapshot.fixed_valid, 0, sizeof(pgStatLocal.snapshot.fixed_valid)); + memset(&pgStatLocal.snapshot.custom_valid, 0, + sizeof(pgStatLocal.snapshot.custom_valid)); pgStatLocal.snapshot.stats = NULL; pgStatLocal.snapshot.mode = PGSTAT_FETCH_CONSISTENCY_NONE; @@ -853,7 +944,7 @@ pgstat_clear_snapshot(void) } void * -pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid) { PgStat_HashKey key; PgStat_EntryRef *entry_ref; @@ -866,9 +957,12 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid) pgstat_prep_snapshot(); + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + key.kind = kind; key.dboid = dboid; - key.objoid = objoid; + key.objid = objid; /* if we need to build a full snapshot, do so */ if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT) @@ -894,7 +988,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid) pgStatLocal.snapshot.mode = pgstat_fetch_consistency; - entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL); + entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL); if (entry_ref == NULL || entry_ref->shared_entry->dropped) { @@ -922,7 +1016,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid) stats_data = MemoryContextAlloc(pgStatLocal.snapshot.context, kind_info->shared_data_len); - pgstat_lock_entry_shared(entry_ref, false); + (void) pgstat_lock_entry_shared(entry_ref, false); memcpy(stats_data, pgstat_get_entry_data(kind, entry_ref->shared_stats), kind_info->shared_data_len); @@ -963,13 +1057,13 @@ pgstat_get_stat_snapshot_timestamp(bool *have_snapshot) } bool -pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_have_entry(PgStat_Kind kind, Oid dboid, uint64 objid) { /* fixed-numbered stats always exist */ if (pgstat_get_kind_info(kind)->fixed_amount) return true; - return pgstat_get_entry_ref(kind, dboid, objoid, false, NULL) != NULL; + return pgstat_get_entry_ref(kind, dboid, objid, false, NULL) != NULL; } /* @@ -992,7 +1086,29 @@ pgstat_snapshot_fixed(PgStat_Kind kind) else pgstat_build_snapshot_fixed(kind); - Assert(pgStatLocal.snapshot.fixed_valid[kind]); + if (pgstat_is_kind_builtin(kind)) + Assert(pgStatLocal.snapshot.fixed_valid[kind]); + else if (pgstat_is_kind_custom(kind)) + Assert(pgStatLocal.snapshot.custom_valid[kind - PGSTAT_KIND_CUSTOM_MIN]); +} + +static void +pgstat_init_snapshot_fixed(void) +{ + /* + * Initialize fixed-numbered statistics data in snapshots, only for custom + * stats kinds. + */ + for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (!kind_info || !kind_info->fixed_amount) + continue; + + pgStatLocal.snapshot.custom_data[kind - PGSTAT_KIND_CUSTOM_MIN] = + MemoryContextAlloc(TopMemoryContext, kind_info->shared_data_len); + } } static void @@ -1071,7 +1187,7 @@ pgstat_build_snapshot(void) Assert(!found); entry->data = MemoryContextAlloc(pgStatLocal.snapshot.context, - kind_info->shared_size); + pgstat_get_entry_len(kind)); /* * Acquire the LWLock directly instead of using @@ -1080,7 +1196,7 @@ pgstat_build_snapshot(void) LWLockAcquire(&stats_data->lock, LW_SHARED); memcpy(entry->data, pgstat_get_entry_data(kind, stats_data), - kind_info->shared_size); + pgstat_get_entry_len(kind)); LWLockRelease(&stats_data->lock); } dshash_seq_term(&hstat); @@ -1088,10 +1204,12 @@ pgstat_build_snapshot(void) /* * Build snapshot of all fixed-numbered stats. */ - for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++) + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + if (!kind_info) + continue; if (!kind_info->fixed_amount) { Assert(kind_info->snapshot_cb == NULL); @@ -1108,6 +1226,20 @@ static void pgstat_build_snapshot_fixed(PgStat_Kind kind) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + int idx; + bool *valid; + + /* Position in fixed_valid or custom_valid */ + if (pgstat_is_kind_builtin(kind)) + { + idx = kind; + valid = pgStatLocal.snapshot.fixed_valid; + } + else + { + idx = kind - PGSTAT_KIND_CUSTOM_MIN; + valid = pgStatLocal.snapshot.custom_valid; + } Assert(kind_info->fixed_amount); Assert(kind_info->snapshot_cb != NULL); @@ -1115,21 +1247,21 @@ pgstat_build_snapshot_fixed(PgStat_Kind kind) if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_NONE) { /* rebuild every time */ - pgStatLocal.snapshot.fixed_valid[kind] = false; + valid[idx] = false; } - else if (pgStatLocal.snapshot.fixed_valid[kind]) + else if (valid[idx]) { /* in snapshot mode we shouldn't get called again */ Assert(pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_CACHE); return; } - Assert(!pgStatLocal.snapshot.fixed_valid[kind]); + Assert(!valid[idx]); kind_info->snapshot_cb(); - Assert(!pgStatLocal.snapshot.fixed_valid[kind]); - pgStatLocal.snapshot.fixed_valid[kind] = true; + Assert(!valid[idx]); + valid[idx] = true; } @@ -1146,7 +1278,7 @@ pgstat_build_snapshot_fixed(PgStat_Kind kind) * created, false otherwise. */ PgStat_EntryRef * -pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry) +pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *created_entry) { PgStat_EntryRef *entry_ref; @@ -1161,7 +1293,7 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created ALLOCSET_SMALL_SIZES); } - entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, + entry_ref = pgstat_get_entry_ref(kind, dboid, objid, true, created_entry); if (entry_ref->pending == NULL) @@ -1184,11 +1316,11 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created * that it shouldn't be needed. */ PgStat_EntryRef * -pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid) { PgStat_EntryRef *entry_ref; - entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL); + entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL); if (entry_ref == NULL || entry_ref->pending == NULL) return NULL; @@ -1217,8 +1349,7 @@ pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref) } /* - * Flush out pending stats for database objects (databases, relations, - * functions). + * Flush out pending variable-numbered stats. */ static bool pgstat_flush_pending_entries(bool nowait) @@ -1285,30 +1416,131 @@ pgstat_flush_pending_entries(bool nowait) PgStat_Kind pgstat_get_kind_from_str(char *kind_str) { - for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++) + for (PgStat_Kind kind = PGSTAT_KIND_BUILTIN_MIN; kind <= PGSTAT_KIND_BUILTIN_MAX; kind++) { - if (pg_strcasecmp(kind_str, pgstat_kind_infos[kind].name) == 0) + if (pg_strcasecmp(kind_str, pgstat_kind_builtin_infos[kind].name) == 0) return kind; } + /* Check the custom set of cumulative stats */ + if (pgstat_kind_custom_infos) + { + for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++) + { + uint32 idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + if (pgstat_kind_custom_infos[idx] && + pg_strcasecmp(kind_str, pgstat_kind_custom_infos[idx]->name) == 0) + return kind; + } + } + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid statistics kind: \"%s\"", kind_str))); - return PGSTAT_KIND_DATABASE; /* avoid compiler warnings */ + return PGSTAT_KIND_INVALID; /* avoid compiler warnings */ } static inline bool -pgstat_is_kind_valid(int ikind) +pgstat_is_kind_valid(PgStat_Kind kind) { - return ikind >= PGSTAT_KIND_FIRST_VALID && ikind <= PGSTAT_KIND_LAST; + return pgstat_is_kind_builtin(kind) || pgstat_is_kind_custom(kind); } const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind) { - Assert(pgstat_is_kind_valid(kind)); + if (pgstat_is_kind_builtin(kind)) + return &pgstat_kind_builtin_infos[kind]; - return &pgstat_kind_infos[kind]; + if (pgstat_is_kind_custom(kind)) + { + uint32 idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + if (pgstat_kind_custom_infos == NULL || + pgstat_kind_custom_infos[idx] == NULL) + return NULL; + return pgstat_kind_custom_infos[idx]; + } + + return NULL; +} + +/* + * Register a new stats kind. + * + * PgStat_Kinds must be globally unique across all extensions. Refer + * to https://wiki.postgresql.org/wiki/CustomCumulativeStats to reserve a + * unique ID for your extension, to avoid conflicts with other extension + * developers. During development, use PGSTAT_KIND_EXPERIMENTAL to avoid + * needlessly reserving a new ID. + */ +void +pgstat_register_kind(PgStat_Kind kind, const PgStat_KindInfo *kind_info) +{ + uint32 idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + if (kind_info->name == NULL || strlen(kind_info->name) == 0) + ereport(ERROR, + (errmsg("custom cumulative statistics name is invalid"), + errhint("Provide a non-empty name for the custom cumulative statistics."))); + + if (!pgstat_is_kind_custom(kind)) + ereport(ERROR, (errmsg("custom cumulative statistics ID %u is out of range", kind), + errhint("Provide a custom cumulative statistics ID between %u and %u.", + PGSTAT_KIND_CUSTOM_MIN, PGSTAT_KIND_CUSTOM_MAX))); + + if (!process_shared_preload_libraries_in_progress) + ereport(ERROR, + (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind), + errdetail("Custom cumulative statistics must be registered while initializing modules in \"shared_preload_libraries\"."))); + + /* + * Check some data for fixed-numbered stats. + */ + if (kind_info->fixed_amount) + { + if (kind_info->shared_size == 0) + ereport(ERROR, + (errmsg("custom cumulative statistics property is invalid"), + errhint("Custom cumulative statistics require a shared memory size for fixed-numbered objects."))); + } + + /* + * If pgstat_kind_custom_infos is not available yet, allocate it. + */ + if (pgstat_kind_custom_infos == NULL) + { + pgstat_kind_custom_infos = (const PgStat_KindInfo **) + MemoryContextAllocZero(TopMemoryContext, + sizeof(PgStat_KindInfo *) * PGSTAT_KIND_CUSTOM_SIZE); + } + + if (pgstat_kind_custom_infos[idx] != NULL && + pgstat_kind_custom_infos[idx]->name != NULL) + ereport(ERROR, + (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind), + errdetail("Custom cumulative statistics \"%s\" already registered with the same ID.", + pgstat_kind_custom_infos[idx]->name))); + + /* check for existing custom stats with the same name */ + for (PgStat_Kind existing_kind = PGSTAT_KIND_CUSTOM_MIN; existing_kind <= PGSTAT_KIND_CUSTOM_MAX; existing_kind++) + { + uint32 existing_idx = existing_kind - PGSTAT_KIND_CUSTOM_MIN; + + if (pgstat_kind_custom_infos[existing_idx] == NULL) + continue; + if (!pg_strcasecmp(pgstat_kind_custom_infos[existing_idx]->name, kind_info->name)) + ereport(ERROR, + (errmsg("failed to register custom cumulative statistics \"%s\" with ID %u", kind_info->name, kind), + errdetail("Existing cumulative statistics with ID %u has the same name.", existing_kind))); + } + + /* Register it */ + pgstat_kind_custom_infos[idx] = kind_info; + ereport(LOG, + (errmsg("registered custom cumulative statistics \"%s\" with ID %u", + kind_info->name, kind))); } /* @@ -1388,18 +1620,26 @@ pgstat_write_statsfile(void) write_chunk_s(fpout, &format_id); /* Write various stats structs for fixed number of objects */ - for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++) + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) { char *ptr; const PgStat_KindInfo *info = pgstat_get_kind_info(kind); - if (!info->fixed_amount) + if (!info || !info->fixed_amount) continue; - Assert(info->snapshot_ctl_off != 0); + if (pgstat_is_kind_builtin(kind)) + Assert(info->snapshot_ctl_off != 0); + + /* skip if no need to write to file */ + if (!info->write_to_file) + continue; pgstat_build_snapshot_fixed(kind); - ptr = ((char *) &pgStatLocal.snapshot) + info->snapshot_ctl_off; + if (pgstat_is_kind_builtin(kind)) + ptr = ((char *) &pgStatLocal.snapshot) + info->snapshot_ctl_off; + else + ptr = pgStatLocal.snapshot.custom_data[kind - PGSTAT_KIND_CUSTOM_MIN]; fputc(PGSTAT_FILE_ENTRY_FIXED, fpout); write_chunk_s(fpout, &kind); @@ -1417,11 +1657,31 @@ pgstat_write_statsfile(void) CHECK_FOR_INTERRUPTS(); - /* we may have some "dropped" entries not yet removed, skip them */ + /* + * We should not see any "dropped" entries when writing the stats + * file, as all backends and auxiliary processes should have cleaned + * up their references before they terminated. + * + * However, since we are already shutting down, it is not worth + * crashing the server over any potential cleanup issues, so we simply + * skip such entries if encountered. + */ Assert(!ps->dropped); if (ps->dropped) continue; + /* + * This discards data related to custom stats kinds that are unknown + * to this process. + */ + if (!pgstat_is_kind_valid(ps->key.kind)) + { + elog(WARNING, "found unknown stats entry %u/%u/%" PRIu64, + ps->key.kind, ps->key.dboid, + ps->key.objid); + continue; + } + shstats = (PgStatShared_Common *) dsa_get_address(pgStatLocal.dsa, ps->body); kind_info = pgstat_get_kind_info(ps->key.kind); @@ -1429,6 +1689,10 @@ pgstat_write_statsfile(void) /* if not dropped the valid-entry refcount should exist */ Assert(pg_atomic_read_u32(&ps->refcount) > 0); + /* skip if no need to write to file */ + if (!kind_info->write_to_file) + continue; + if (!kind_info->to_serialized_name) { /* normal stats entry, identified by PgStat_HashKey */ @@ -1537,9 +1801,18 @@ pgstat_read_statsfile(void) /* * Verify it's of the expected format. */ - if (!read_chunk_s(fpin, &format_id) || - format_id != PGSTAT_FILE_FORMAT_ID) + if (!read_chunk_s(fpin, &format_id)) + { + elog(WARNING, "could not read format ID"); goto error; + } + + if (format_id != PGSTAT_FILE_FORMAT_ID) + { + elog(WARNING, "found incorrect format ID %d (expected %d)", + format_id, PGSTAT_FILE_FORMAT_ID); + goto error; + } /* * We found an existing statistics file. Read it and put all the stats @@ -1559,22 +1832,51 @@ pgstat_read_statsfile(void) /* entry for fixed-numbered stats */ if (!read_chunk_s(fpin, &kind)) + { + elog(WARNING, "could not read stats kind for entry of type %c", t); goto error; + } if (!pgstat_is_kind_valid(kind)) + { + elog(WARNING, "invalid stats kind %u for entry of type %c", + kind, t); goto error; + } info = pgstat_get_kind_info(kind); + if (!info) + { + elog(WARNING, "could not find information of kind %u for entry of type %c", + kind, t); + goto error; + } if (!info->fixed_amount) + { + elog(WARNING, "invalid fixed_amount in stats kind %u for entry of type %c", + kind, t); goto error; + } /* Load back stats into shared memory */ - ptr = ((char *) shmem) + info->shared_ctl_off + - info->shared_data_off; + if (pgstat_is_kind_builtin(kind)) + ptr = ((char *) shmem) + info->shared_ctl_off + + info->shared_data_off; + else + { + int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + ptr = ((char *) shmem->custom_data[idx]) + + info->shared_data_off; + } if (!read_chunk(fpin, ptr, info->shared_data_len)) + { + elog(WARNING, "could not read data of stats kind %u for entry of type %c with size %u", + kind, t, info->shared_data_len); goto error; + } break; } @@ -1591,10 +1893,26 @@ pgstat_read_statsfile(void) { /* normal stats entry, identified by PgStat_HashKey */ if (!read_chunk_s(fpin, &key)) + { + elog(WARNING, "could not read key for entry of type %c", t); goto error; + } if (!pgstat_is_kind_valid(key.kind)) + { + elog(WARNING, "invalid stats kind for entry %u/%u/%" PRIu64 " of type %c", + key.kind, key.dboid, + key.objid, t); goto error; + } + + if (!pgstat_get_kind_info(key.kind)) + { + elog(WARNING, "could not find information of kind for entry %u/%u/%" PRIu64 " of type %c", + key.kind, key.dboid, + key.objid, t); + goto error; + } } else { @@ -1604,22 +1922,47 @@ pgstat_read_statsfile(void) NameData name; if (!read_chunk_s(fpin, &kind)) + { + elog(WARNING, "could not read stats kind for entry of type %c", t); goto error; + } if (!read_chunk_s(fpin, &name)) + { + elog(WARNING, "could not read name of stats kind %u for entry of type %c", + kind, t); goto error; + } if (!pgstat_is_kind_valid(kind)) + { + elog(WARNING, "invalid stats kind %u for entry of type %c", + kind, t); goto error; + } kind_info = pgstat_get_kind_info(kind); + if (!kind_info) + { + elog(WARNING, "could not find information of kind %u for entry of type %c", + kind, t); + goto error; + } if (!kind_info->from_serialized_name) + { + elog(WARNING, "invalid from_serialized_name in stats kind %u for entry of type %c", + kind, t); goto error; + } if (!kind_info->from_serialized_name(&name, &key)) { /* skip over data for entry we don't care about */ if (fseek(fpin, pgstat_get_entry_len(kind), SEEK_CUR) != 0) + { + elog(WARNING, "could not seek \"%s\" of stats kind %u for entry of type %c", + NameStr(name), kind, t); goto error; + } continue; } @@ -1638,8 +1981,9 @@ pgstat_read_statsfile(void) if (found) { dshash_release_lock(pgStatLocal.shared_hash, p); - elog(WARNING, "found duplicate stats entry %d/%u/%u", - key.kind, key.dboid, key.objoid); + elog(WARNING, "found duplicate stats entry %u/%u/%" PRIu64 " of type %c", + key.kind, key.dboid, + key.objid, t); goto error; } @@ -1649,7 +1993,12 @@ pgstat_read_statsfile(void) if (!read_chunk(fpin, pgstat_get_entry_data(key.kind, header), pgstat_get_entry_len(key.kind))) + { + elog(WARNING, "could not read data for entry %u/%u/%" PRIu64 " of type %c", + key.kind, key.dboid, + key.objid, t); goto error; + } break; } @@ -1660,11 +2009,15 @@ pgstat_read_statsfile(void) * file */ if (fgetc(fpin) != EOF) + { + elog(WARNING, "could not read end-of-file"); goto error; + } goto done; default: + elog(WARNING, "could not read entry of type %c", t); goto error; } } @@ -1696,11 +2049,11 @@ pgstat_reset_after_failure(void) TimestampTz ts = GetCurrentTimestamp(); /* reset fixed-numbered stats */ - for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++) + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); - if (!kind_info->fixed_amount) + if (!kind_info || !kind_info->fixed_amount) continue; kind_info->reset_all_cb(ts); diff --git a/src/backend/utils/activity/pgstat_archiver.c b/src/backend/utils/activity/pgstat_archiver.c index 60e04711c44f7..c2ba2b31972e0 100644 --- a/src/backend/utils/activity/pgstat_archiver.c +++ b/src/backend/utils/activity/pgstat_archiver.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_archiver.c diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c new file mode 100644 index 0000000000000..51256277e8d37 --- /dev/null +++ b/src/backend/utils/activity/pgstat_backend.c @@ -0,0 +1,412 @@ +/* ------------------------------------------------------------------------- + * + * pgstat_backend.c + * Implementation of backend statistics. + * + * This file contains the implementation of backend statistics. It is kept + * separate from pgstat.c to enforce the line between the statistics access / + * storage implementation and the details about individual types of + * statistics. + * + * This statistics kind uses a proc number as object ID for the hash table + * of pgstats. Entries are created each time a process is spawned, and are + * dropped when the process exits. These are not written to the pgstats file + * on disk. Pending statistics are managed without direct interactions with + * PgStat_EntryRef->pending, relying on PendingBackendStats instead so as it + * is possible to report data within critical sections. + * + * Copyright (c) 2001-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/utils/activity/pgstat_backend.c + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/xlog.h" +#include "storage/bufmgr.h" +#include "storage/proc.h" +#include "storage/procarray.h" +#include "utils/memutils.h" +#include "utils/pgstat_internal.h" + +/* + * Backend statistics counts waiting to be flushed out. These counters may be + * reported within critical sections so we use static memory in order to avoid + * memory allocation. + */ +static PgStat_BackendPending PendingBackendStats; +static bool backend_has_iostats = false; + +/* + * WAL usage counters saved from pgWalUsage at the previous call to + * pgstat_report_wal(). This is used to calculate how much WAL usage + * happens between pgstat_report_wal() calls, by subtracting the previous + * counters from the current ones. + */ +static WalUsage prevBackendWalUsage; + +/* + * Utility routines to report I/O stats for backends, kept here to avoid + * exposing PendingBackendStats to the outside world. + */ +void +pgstat_count_backend_io_op_time(IOObject io_object, IOContext io_context, + IOOp io_op, instr_time io_time) +{ + Assert(track_io_timing || track_wal_io_timing); + + if (!pgstat_tracks_backend_bktype(MyBackendType)) + return; + + Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op)); + + INSTR_TIME_ADD(PendingBackendStats.pending_io.pending_times[io_object][io_context][io_op], + io_time); + + backend_has_iostats = true; +} + +void +pgstat_count_backend_io_op(IOObject io_object, IOContext io_context, + IOOp io_op, uint32 cnt, uint64 bytes) +{ + if (!pgstat_tracks_backend_bktype(MyBackendType)) + return; + + Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op)); + + PendingBackendStats.pending_io.counts[io_object][io_context][io_op] += cnt; + PendingBackendStats.pending_io.bytes[io_object][io_context][io_op] += bytes; + + backend_has_iostats = true; +} + +/* + * Returns statistics of a backend by proc number. + */ +PgStat_Backend * +pgstat_fetch_stat_backend(ProcNumber procNumber) +{ + PgStat_Backend *backend_entry; + + backend_entry = (PgStat_Backend *) pgstat_fetch_entry(PGSTAT_KIND_BACKEND, + InvalidOid, procNumber); + + return backend_entry; +} + +/* + * Returns statistics of a backend by pid. + * + * This routine includes sanity checks to ensure that the backend exists and + * is running. "bktype" can be optionally defined to return the BackendType + * of the backend whose statistics are returned. + */ +PgStat_Backend * +pgstat_fetch_stat_backend_by_pid(int pid, BackendType *bktype) +{ + PGPROC *proc; + PgBackendStatus *beentry; + ProcNumber procNumber; + PgStat_Backend *backend_stats; + + proc = BackendPidGetProc(pid); + if (bktype) + *bktype = B_INVALID; + + /* this could be an auxiliary process */ + if (!proc) + proc = AuxiliaryPidGetProc(pid); + + if (!proc) + return NULL; + + procNumber = GetNumberFromPGProc(proc); + + beentry = pgstat_get_beentry_by_proc_number(procNumber); + if (!beentry) + return NULL; + + /* check if the backend type tracks statistics */ + if (!pgstat_tracks_backend_bktype(beentry->st_backendType)) + return NULL; + + /* if PID does not match, leave */ + if (beentry->st_procpid != pid) + return NULL; + + if (bktype) + *bktype = beentry->st_backendType; + + /* + * Retrieve the entry. Note that "beentry" may be freed depending on the + * value of stats_fetch_consistency, so do not access it from this point. + */ + backend_stats = pgstat_fetch_stat_backend(procNumber); + if (!backend_stats) + { + if (bktype) + *bktype = B_INVALID; + return NULL; + } + + return backend_stats; +} + +/* + * Flush out locally pending backend IO statistics. Locking is managed + * by the caller. + */ +static void +pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref) +{ + PgStatShared_Backend *shbackendent; + PgStat_BktypeIO *bktype_shstats; + PgStat_PendingIO pending_io; + + /* + * This function can be called even if nothing at all has happened for IO + * statistics. In this case, avoid unnecessarily modifying the stats + * entry. + */ + if (!backend_has_iostats) + return; + + shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats; + bktype_shstats = &shbackendent->stats.io_stats; + pending_io = PendingBackendStats.pending_io; + + for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++) + { + for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++) + { + for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++) + { + instr_time time; + + bktype_shstats->counts[io_object][io_context][io_op] += + pending_io.counts[io_object][io_context][io_op]; + bktype_shstats->bytes[io_object][io_context][io_op] += + pending_io.bytes[io_object][io_context][io_op]; + time = pending_io.pending_times[io_object][io_context][io_op]; + + bktype_shstats->times[io_object][io_context][io_op] += + INSTR_TIME_GET_MICROSEC(time); + } + } + } + + /* + * Clear out the statistics buffer, so it can be re-used. + */ + MemSet(&PendingBackendStats.pending_io, 0, sizeof(PgStat_PendingIO)); + + backend_has_iostats = false; +} + +/* + * To determine whether WAL usage happened. + */ +static inline bool +pgstat_backend_wal_have_pending(void) +{ + return (pgWalUsage.wal_records != prevBackendWalUsage.wal_records); +} + +/* + * Flush out locally pending backend WAL statistics. Locking is managed + * by the caller. + */ +static void +pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref) +{ + PgStatShared_Backend *shbackendent; + PgStat_WalCounters *bktype_shstats; + WalUsage wal_usage_diff = {0}; + + /* + * This function can be called even if nothing at all has happened for WAL + * statistics. In this case, avoid unnecessarily modifying the stats + * entry. + */ + if (!pgstat_backend_wal_have_pending()) + return; + + shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats; + bktype_shstats = &shbackendent->stats.wal_counters; + + /* + * Calculate how much WAL usage counters were increased by subtracting the + * previous counters from the current ones. + */ + WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevBackendWalUsage); + +#define WALSTAT_ACC(fld, var_to_add) \ + (bktype_shstats->fld += var_to_add.fld) + WALSTAT_ACC(wal_buffers_full, wal_usage_diff); + WALSTAT_ACC(wal_records, wal_usage_diff); + WALSTAT_ACC(wal_fpi, wal_usage_diff); + WALSTAT_ACC(wal_bytes, wal_usage_diff); +#undef WALSTAT_ACC + + /* + * Save the current counters for the subsequent calculation of WAL usage. + */ + prevBackendWalUsage = pgWalUsage; +} + +/* + * Flush out locally pending backend statistics + * + * "flags" parameter controls which statistics to flush. Returns true + * if some statistics could not be flushed due to lock contention. + */ +bool +pgstat_flush_backend(bool nowait, bits32 flags) +{ + PgStat_EntryRef *entry_ref; + bool has_pending_data = false; + + if (!pgstat_tracks_backend_bktype(MyBackendType)) + return false; + + /* Some IO data pending? */ + if ((flags & PGSTAT_BACKEND_FLUSH_IO) && backend_has_iostats) + has_pending_data = true; + + /* Some WAL data pending? */ + if ((flags & PGSTAT_BACKEND_FLUSH_WAL) && + pgstat_backend_wal_have_pending()) + has_pending_data = true; + + if (!has_pending_data) + return false; + + entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_BACKEND, InvalidOid, + MyProcNumber, nowait); + if (!entry_ref) + return true; + + /* Flush requested statistics */ + if (flags & PGSTAT_BACKEND_FLUSH_IO) + pgstat_flush_backend_entry_io(entry_ref); + + if (flags & PGSTAT_BACKEND_FLUSH_WAL) + pgstat_flush_backend_entry_wal(entry_ref); + + pgstat_unlock_entry(entry_ref); + + return false; +} + +/* + * Check if there are any backend stats waiting for flush. + */ +bool +pgstat_backend_have_pending_cb(void) +{ + if (!pgstat_tracks_backend_bktype(MyBackendType)) + return false; + + return (backend_has_iostats || pgstat_backend_wal_have_pending()); +} + +/* + * Callback to flush out locally pending backend statistics. + * + * If some stats could not be flushed due to lock contention, return true. + */ +bool +pgstat_backend_flush_cb(bool nowait) +{ + return pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_ALL); +} + +/* + * Create backend statistics entry for proc number. + */ +void +pgstat_create_backend(ProcNumber procnum) +{ + PgStat_EntryRef *entry_ref; + PgStatShared_Backend *shstatent; + + entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_BACKEND, InvalidOid, + MyProcNumber, false); + shstatent = (PgStatShared_Backend *) entry_ref->shared_stats; + + /* + * NB: need to accept that there might be stats from an older backend, + * e.g. if we previously used this proc number. + */ + memset(&shstatent->stats, 0, sizeof(shstatent->stats)); + pgstat_unlock_entry(entry_ref); + + MemSet(&PendingBackendStats, 0, sizeof(PgStat_BackendPending)); + backend_has_iostats = false; + + /* + * Initialize prevBackendWalUsage with pgWalUsage so that + * pgstat_backend_flush_cb() can calculate how much pgWalUsage counters + * are increased by subtracting prevBackendWalUsage from pgWalUsage. + */ + prevBackendWalUsage = pgWalUsage; +} + +/* + * Backend statistics are not collected for all BackendTypes. + * + * The following BackendTypes do not participate in the backend stats + * subsystem: + * - The same and for the same reasons as in pgstat_tracks_io_bktype(). + * - B_BG_WRITER, B_CHECKPOINTER, B_STARTUP and B_AUTOVAC_LAUNCHER because their + * I/O stats are already visible in pg_stat_io and there is only one of those. + * + * Function returns true if BackendType participates in the backend stats + * subsystem and false if it does not. + * + * When adding a new BackendType, also consider adding relevant restrictions to + * pgstat_tracks_io_object() and pgstat_tracks_io_op(). + */ +bool +pgstat_tracks_backend_bktype(BackendType bktype) +{ + /* + * List every type so that new backend types trigger a warning about + * needing to adjust this switch. + */ + switch (bktype) + { + case B_INVALID: + case B_AUTOVAC_LAUNCHER: + case B_DEAD_END_BACKEND: + case B_ARCHIVER: + case B_LOGGER: + case B_BG_WRITER: + case B_CHECKPOINTER: + case B_IO_WORKER: + case B_STARTUP: + return false; + + case B_AUTOVAC_WORKER: + case B_BACKEND: + case B_BG_WORKER: + case B_STANDALONE_BACKEND: + case B_SLOTSYNC_WORKER: + case B_WAL_RECEIVER: + case B_WAL_SENDER: + case B_WAL_SUMMARIZER: + case B_WAL_WRITER: + return true; + } + + return false; +} + +void +pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts) +{ + ((PgStatShared_Backend *) header)->stats.stat_reset_timestamp = ts; +} diff --git a/src/backend/utils/activity/pgstat_bgwriter.c b/src/backend/utils/activity/pgstat_bgwriter.c index 364a7a2024a31..41eabc1d8bb03 100644 --- a/src/backend/utils/activity/pgstat_bgwriter.c +++ b/src/backend/utils/activity/pgstat_bgwriter.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_bgwriter.c @@ -17,6 +17,7 @@ #include "postgres.h" +#include "utils/memutils.h" #include "utils/pgstat_internal.h" @@ -30,7 +31,6 @@ void pgstat_report_bgwriter(void) { PgStatShared_BgWriter *stats_shmem = &pgStatLocal.shmem->bgwriter; - static const PgStat_BgWriterStats all_zeroes; Assert(!pgStatLocal.shmem->is_shutdown); pgstat_assert_is_up(); @@ -39,7 +39,8 @@ pgstat_report_bgwriter(void) * This function can be called even if nothing at all has happened. In * this case, avoid unnecessarily modifying the stats entry. */ - if (memcmp(&PendingBgWriterStats, &all_zeroes, sizeof(all_zeroes)) == 0) + if (pg_memory_is_all_zeros(&PendingBgWriterStats, + sizeof(struct PgStat_BgWriterStats))) return; pgstat_begin_changecount_write(&stats_shmem->changecount); diff --git a/src/backend/utils/activity/pgstat_checkpointer.c b/src/backend/utils/activity/pgstat_checkpointer.c index bbfc9c7e1833c..e65034a30a638 100644 --- a/src/backend/utils/activity/pgstat_checkpointer.c +++ b/src/backend/utils/activity/pgstat_checkpointer.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_checkpointer.c @@ -17,6 +17,7 @@ #include "postgres.h" +#include "utils/memutils.h" #include "utils/pgstat_internal.h" @@ -29,8 +30,6 @@ PgStat_CheckpointerStats PendingCheckpointerStats = {0}; void pgstat_report_checkpointer(void) { - /* We assume this initializes to zeroes */ - static const PgStat_CheckpointerStats all_zeroes; PgStatShared_Checkpointer *stats_shmem = &pgStatLocal.shmem->checkpointer; Assert(!pgStatLocal.shmem->is_shutdown); @@ -40,8 +39,8 @@ pgstat_report_checkpointer(void) * This function can be called even if nothing at all has happened. In * this case, avoid unnecessarily modifying the stats entry. */ - if (memcmp(&PendingCheckpointerStats, &all_zeroes, - sizeof(all_zeroes)) == 0) + if (pg_memory_is_all_zeros(&PendingCheckpointerStats, + sizeof(struct PgStat_CheckpointerStats))) return; pgstat_begin_changecount_write(&stats_shmem->changecount); @@ -49,12 +48,14 @@ pgstat_report_checkpointer(void) #define CHECKPOINTER_ACC(fld) stats_shmem->stats.fld += PendingCheckpointerStats.fld CHECKPOINTER_ACC(num_timed); CHECKPOINTER_ACC(num_requested); + CHECKPOINTER_ACC(num_performed); CHECKPOINTER_ACC(restartpoints_timed); CHECKPOINTER_ACC(restartpoints_requested); CHECKPOINTER_ACC(restartpoints_performed); CHECKPOINTER_ACC(write_time); CHECKPOINTER_ACC(sync_time); CHECKPOINTER_ACC(buffers_written); + CHECKPOINTER_ACC(slru_written); #undef CHECKPOINTER_ACC pgstat_end_changecount_write(&stats_shmem->changecount); @@ -127,11 +128,13 @@ pgstat_checkpointer_snapshot_cb(void) #define CHECKPOINTER_COMP(fld) pgStatLocal.snapshot.checkpointer.fld -= reset.fld; CHECKPOINTER_COMP(num_timed); CHECKPOINTER_COMP(num_requested); + CHECKPOINTER_COMP(num_performed); CHECKPOINTER_COMP(restartpoints_timed); CHECKPOINTER_COMP(restartpoints_requested); CHECKPOINTER_COMP(restartpoints_performed); CHECKPOINTER_COMP(write_time); CHECKPOINTER_COMP(sync_time); CHECKPOINTER_COMP(buffers_written); + CHECKPOINTER_COMP(slru_written); #undef CHECKPOINTER_COMP } diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c index 29bc090974803..b31f20d41bcc5 100644 --- a/src/backend/utils/activity/pgstat_database.c +++ b/src/backend/utils/activity/pgstat_database.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_database.c @@ -133,8 +133,34 @@ pgstat_report_deadlock(void) dbent->deadlocks++; } +/* + * Allow this backend to later report checksum failures for dboid, even if in + * a critical section at the time of the report. + * + * Without this function having been called first, the backend might need to + * allocate an EntryRef or might need to map in DSM segments. Neither should + * happen in a critical section. + */ +void +pgstat_prepare_report_checksum_failure(Oid dboid) +{ + Assert(!CritSectionCount); + + /* + * Just need to ensure this backend has an entry ref for the database. + * That will allows us to report checksum failures without e.g. needing to + * map in DSM segments. + */ + pgstat_get_entry_ref(PGSTAT_KIND_DATABASE, dboid, InvalidOid, + true, NULL); +} + /* * Report one or more checksum failures. + * + * To be allowed to report checksum failures in critical sections, we require + * pgstat_prepare_report_checksum_failure() to have been called before this + * function is called. */ void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount) @@ -147,10 +173,29 @@ pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount) /* * Update the shared stats directly - checksum failures should never be - * common enough for that to be a problem. + * common enough for that to be a problem. Note that we pass create=false + * here, as we want to be sure to not require memory allocations, so this + * can be called in critical sections. + */ + entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_DATABASE, dboid, InvalidOid, + false, NULL); + + /* + * Should always have been created by + * pgstat_prepare_report_checksum_failure(). + * + * When not using assertions, we don't want to crash should something have + * gone wrong, so just return. */ - entry_ref = - pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid, false); + Assert(entry_ref); + if (!entry_ref) + { + elog(WARNING, "could not report %d conflicts for DB %u", + failurecount, dboid); + return; + } + + (void) pgstat_lock_entry(entry_ref, false); sharedent = (PgStatShared_Database *) entry_ref->shared_stats; sharedent->stats.checksum_failures += failurecount; @@ -159,15 +204,6 @@ pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount) pgstat_unlock_entry(entry_ref); } -/* - * Report one checksum failure in the current database. - */ -void -pgstat_report_checksum_failure(void) -{ - pgstat_report_checksum_failures_in_db(MyDatabaseId, 1); -} - /* * Report creation of temporary file. */ @@ -262,6 +298,23 @@ AtEOXact_PgStat_Database(bool isCommit, bool parallel) } } +/* + * Notify the stats system about parallel worker information. + */ +void +pgstat_update_parallel_workers_stats(PgStat_Counter workers_to_launch, + PgStat_Counter workers_launched) +{ + PgStat_StatDBEntry *dbentry; + + if (!OidIsValid(MyDatabaseId)) + return; + + dbentry = pgstat_prep_database_pending(MyDatabaseId); + dbentry->parallel_workers_to_launch += workers_to_launch; + dbentry->parallel_workers_launched += workers_launched; +} + /* * Subroutine for pgstat_report_stat(): Handle xact commit/rollback and I/O * timings. @@ -368,8 +421,8 @@ pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts) /* * Flush out pending stats for the entry * - * If nowait is true, this function returns false if lock could not - * immediately acquired, otherwise true is returned. + * If nowait is true and the lock could not be immediately acquired, returns + * false without flushing the entry. Otherwise returns true. */ bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) @@ -425,6 +478,8 @@ pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) PGSTAT_ACCUM_DBCOUNT(sessions_abandoned); PGSTAT_ACCUM_DBCOUNT(sessions_fatal); PGSTAT_ACCUM_DBCOUNT(sessions_killed); + PGSTAT_ACCUM_DBCOUNT(parallel_workers_to_launch); + PGSTAT_ACCUM_DBCOUNT(parallel_workers_launched); #undef PGSTAT_ACCUM_DBCOUNT pgstat_unlock_entry(entry_ref); diff --git a/src/backend/utils/activity/pgstat_function.c b/src/backend/utils/activity/pgstat_function.c index d26da551a4e6c..6214f93d36e0c 100644 --- a/src/backend/utils/activity/pgstat_function.c +++ b/src/backend/utils/activity/pgstat_function.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_function.c @@ -186,8 +186,8 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize) /* * Flush out pending stats for the entry * - * If nowait is true, this function returns false if lock could not - * immediately acquired, otherwise true is returned. + * If nowait is true and the lock could not be immediately acquired, returns + * false without flushing the entry. Otherwise returns true. */ bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) diff --git a/src/backend/utils/activity/pgstat_io.c b/src/backend/utils/activity/pgstat_io.c index 8af55989eed83..d8d26379a571e 100644 --- a/src/backend/utils/activity/pgstat_io.c +++ b/src/backend/utils/activity/pgstat_io.c @@ -7,7 +7,7 @@ * from pgstat.c to enforce the line between the statistics access / storage * implementation and the details about individual types of statistics. * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_io.c @@ -20,17 +20,8 @@ #include "storage/bufmgr.h" #include "utils/pgstat_internal.h" - -typedef struct PgStat_PendingIO -{ - PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; - instr_time pending_times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; -} PgStat_PendingIO; - - static PgStat_PendingIO PendingIOStats; -bool have_iostats = false; - +static bool have_iostats = false; /* * Check that stats have not been counted for any combination of IOObject, @@ -74,20 +65,19 @@ pgstat_bktype_io_stats_valid(PgStat_BktypeIO *backend_io, } void -pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op) -{ - pgstat_count_io_op_n(io_object, io_context, io_op, 1); -} - -void -pgstat_count_io_op_n(IOObject io_object, IOContext io_context, IOOp io_op, uint32 cnt) +pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op, + uint32 cnt, uint64 bytes) { Assert((unsigned int) io_object < IOOBJECT_NUM_TYPES); Assert((unsigned int) io_context < IOCONTEXT_NUM_TYPES); - Assert((unsigned int) io_op < IOOP_NUM_TYPES); + Assert(pgstat_is_ioop_tracked_in_bytes(io_op) || bytes == 0); Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op)); PendingIOStats.counts[io_object][io_context][io_op] += cnt; + PendingIOStats.bytes[io_object][io_context][io_op] += bytes; + + /* Add the per-backend counts */ + pgstat_count_backend_io_op(io_object, io_context, io_op, cnt, bytes); have_iostats = true; } @@ -106,8 +96,9 @@ pgstat_prepare_io_time(bool track_io_guc) else { /* - * There is no need to set io_start when an IO timing GUC is disabled, - * still initialize it to zero to avoid compiler warnings. + * There is no need to set io_start when an IO timing GUC is disabled. + * Initialize it to zero to avoid compiler warnings and to let + * pgstat_count_io_op_time() know that timings should be ignored. */ INSTR_TIME_SET_ZERO(io_start); } @@ -116,41 +107,56 @@ pgstat_prepare_io_time(bool track_io_guc) } /* - * Like pgstat_count_io_op_n() except it also accumulates time. + * Like pgstat_count_io_op() except it also accumulates time. + * + * The calls related to pgstat_count_buffer_*() are for pgstat_database. As + * pg_stat_database only counts block read and write times, these are done for + * IOOP_READ, IOOP_WRITE and IOOP_EXTEND. + * + * pgBufferUsage is used for EXPLAIN. pgBufferUsage has write and read stats + * for shared, local and temporary blocks. pg_stat_io does not track the + * activity of temporary blocks, so these are ignored here. */ void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, - instr_time start_time, uint32 cnt) + instr_time start_time, uint32 cnt, uint64 bytes) { - if (track_io_timing) + if (!INSTR_TIME_IS_ZERO(start_time)) { instr_time io_time; INSTR_TIME_SET_CURRENT(io_time); INSTR_TIME_SUBTRACT(io_time, start_time); - if (io_op == IOOP_WRITE || io_op == IOOP_EXTEND) + if (io_object != IOOBJECT_WAL) { - pgstat_count_buffer_write_time(INSTR_TIME_GET_MICROSEC(io_time)); - if (io_object == IOOBJECT_RELATION) - INSTR_TIME_ADD(pgBufferUsage.shared_blk_write_time, io_time); - else if (io_object == IOOBJECT_TEMP_RELATION) - INSTR_TIME_ADD(pgBufferUsage.local_blk_write_time, io_time); - } - else if (io_op == IOOP_READ) - { - pgstat_count_buffer_read_time(INSTR_TIME_GET_MICROSEC(io_time)); - if (io_object == IOOBJECT_RELATION) - INSTR_TIME_ADD(pgBufferUsage.shared_blk_read_time, io_time); - else if (io_object == IOOBJECT_TEMP_RELATION) - INSTR_TIME_ADD(pgBufferUsage.local_blk_read_time, io_time); + if (io_op == IOOP_WRITE || io_op == IOOP_EXTEND) + { + pgstat_count_buffer_write_time(INSTR_TIME_GET_MICROSEC(io_time)); + if (io_object == IOOBJECT_RELATION) + INSTR_TIME_ADD(pgBufferUsage.shared_blk_write_time, io_time); + else if (io_object == IOOBJECT_TEMP_RELATION) + INSTR_TIME_ADD(pgBufferUsage.local_blk_write_time, io_time); + } + else if (io_op == IOOP_READ) + { + pgstat_count_buffer_read_time(INSTR_TIME_GET_MICROSEC(io_time)); + if (io_object == IOOBJECT_RELATION) + INSTR_TIME_ADD(pgBufferUsage.shared_blk_read_time, io_time); + else if (io_object == IOOBJECT_TEMP_RELATION) + INSTR_TIME_ADD(pgBufferUsage.local_blk_read_time, io_time); + } } INSTR_TIME_ADD(PendingIOStats.pending_times[io_object][io_context][io_op], io_time); + + /* Add the per-backend count */ + pgstat_count_backend_io_op_time(io_object, io_context, io_op, + io_time); } - pgstat_count_io_op_n(io_object, io_context, io_op, cnt); + pgstat_count_io_op(io_object, io_context, io_op, cnt, bytes); } PgStat_IO * @@ -161,6 +167,24 @@ pgstat_fetch_stat_io(void) return &pgStatLocal.snapshot.io; } +/* + * Check if there any IO stats waiting for flush. + */ +bool +pgstat_io_have_pending_cb(void) +{ + return have_iostats; +} + +/* + * Simpler wrapper of pgstat_io_flush_cb() + */ +void +pgstat_flush_io(bool nowait) +{ + (void) pgstat_io_flush_cb(nowait); +} + /* * Flush out locally pending IO statistics * @@ -170,7 +194,7 @@ pgstat_fetch_stat_io(void) * acquired. Otherwise, return false. */ bool -pgstat_flush_io(bool nowait) +pgstat_io_flush_cb(bool nowait) { LWLock *bktype_lock; PgStat_BktypeIO *bktype_shstats; @@ -198,6 +222,9 @@ pgstat_flush_io(bool nowait) bktype_shstats->counts[io_object][io_context][io_op] += PendingIOStats.counts[io_object][io_context][io_op]; + bktype_shstats->bytes[io_object][io_context][io_op] += + PendingIOStats.bytes[io_object][io_context][io_op]; + time = PendingIOStats.pending_times[io_object][io_context][io_op]; bktype_shstats->times[io_object][io_context][io_op] += @@ -226,6 +253,8 @@ pgstat_get_io_context_name(IOContext io_context) return "bulkread"; case IOCONTEXT_BULKWRITE: return "bulkwrite"; + case IOCONTEXT_INIT: + return "init"; case IOCONTEXT_NORMAL: return "normal"; case IOCONTEXT_VACUUM: @@ -245,6 +274,8 @@ pgstat_get_io_object_name(IOObject io_object) return "relation"; case IOOBJECT_TEMP_RELATION: return "temp relation"; + case IOOBJECT_WAL: + return "wal"; } elog(ERROR, "unrecognized IOObject value: %d", io_object); @@ -312,11 +343,11 @@ pgstat_io_snapshot_cb(void) * * The following BackendTypes do not participate in the cumulative stats * subsystem or do not perform IO on which we currently track: +* - Dead-end backend because it is not connected to shared memory and +* doesn't do any IO * - Syslogger because it is not connected to shared memory * - Archiver because most relevant archiving IO is delegated to a * specialized command or module -* - WAL Receiver, WAL Writer, and WAL Summarizer IO are not tracked in -* pg_stat_io for now * * Function returns true if BackendType participates in the cumulative stats * subsystem for IO and false if it does not. @@ -334,11 +365,9 @@ pgstat_tracks_io_bktype(BackendType bktype) switch (bktype) { case B_INVALID: + case B_DEAD_END_BACKEND: case B_ARCHIVER: case B_LOGGER: - case B_WAL_RECEIVER: - case B_WAL_WRITER: - case B_WAL_SUMMARIZER: return false; case B_AUTOVAC_LAUNCHER: @@ -347,10 +376,14 @@ pgstat_tracks_io_bktype(BackendType bktype) case B_BG_WORKER: case B_BG_WRITER: case B_CHECKPOINTER: + case B_IO_WORKER: case B_SLOTSYNC_WORKER: case B_STANDALONE_BACKEND: case B_STARTUP: + case B_WAL_RECEIVER: case B_WAL_SENDER: + case B_WAL_SUMMARIZER: + case B_WAL_WRITER: return true; } @@ -376,6 +409,15 @@ pgstat_tracks_io_object(BackendType bktype, IOObject io_object, if (!pgstat_tracks_io_bktype(bktype)) return false; + /* + * Currently, IO on IOOBJECT_WAL objects can only occur in the + * IOCONTEXT_NORMAL and IOCONTEXT_INIT IOContexts. + */ + if (io_object == IOOBJECT_WAL && + (io_context != IOCONTEXT_NORMAL && + io_context != IOCONTEXT_INIT)) + return false; + /* * Currently, IO on temporary relations can only occur in the * IOCONTEXT_NORMAL IOContext. @@ -394,12 +436,22 @@ pgstat_tracks_io_object(BackendType bktype, IOObject io_object, */ no_temp_rel = bktype == B_AUTOVAC_LAUNCHER || bktype == B_BG_WRITER || bktype == B_CHECKPOINTER || bktype == B_AUTOVAC_WORKER || - bktype == B_STANDALONE_BACKEND || bktype == B_STARTUP; + bktype == B_STANDALONE_BACKEND || bktype == B_STARTUP || + bktype == B_WAL_SUMMARIZER || bktype == B_WAL_WRITER || + bktype == B_WAL_RECEIVER; if (no_temp_rel && io_context == IOCONTEXT_NORMAL && io_object == IOOBJECT_TEMP_RELATION) return false; + /* + * Some BackendTypes only perform IO under IOOBJECT_WAL, hence exclude all + * rows for all the other objects for these. + */ + if ((bktype == B_WAL_SUMMARIZER || bktype == B_WAL_RECEIVER || + bktype == B_WAL_WRITER) && io_object != IOOBJECT_WAL) + return false; + /* * Some BackendTypes do not currently perform any IO in certain * IOContexts, and, while it may not be inherently incorrect for them to @@ -442,14 +494,28 @@ pgstat_tracks_io_op(BackendType bktype, IOObject io_object, /* * Some BackendTypes will not do certain IOOps. */ - if ((bktype == B_BG_WRITER || bktype == B_CHECKPOINTER) && + if (bktype == B_BG_WRITER && (io_op == IOOP_READ || io_op == IOOP_EVICT || io_op == IOOP_HIT)) return false; + if (bktype == B_CHECKPOINTER && + ((io_object != IOOBJECT_WAL && io_op == IOOP_READ) || + (io_op == IOOP_EVICT || io_op == IOOP_HIT))) + return false; + if ((bktype == B_AUTOVAC_LAUNCHER || bktype == B_BG_WRITER || bktype == B_CHECKPOINTER) && io_op == IOOP_EXTEND) return false; + /* + * Some BackendTypes do not perform reads with IOOBJECT_WAL. + */ + if (io_object == IOOBJECT_WAL && io_op == IOOP_READ && + (bktype == B_WAL_RECEIVER || bktype == B_BG_WRITER || + bktype == B_AUTOVAC_LAUNCHER || bktype == B_AUTOVAC_WORKER || + bktype == B_WAL_WRITER)) + return false; + /* * Temporary tables are not logged and thus do not require fsync'ing. * Writeback is not requested for temporary tables. @@ -474,6 +540,17 @@ pgstat_tracks_io_op(BackendType bktype, IOObject io_object, if (!strategy_io_context && io_op == IOOP_REUSE) return false; + /* + * IOOBJECT_WAL IOObject will not do certain IOOps depending on IOContext. + */ + if (io_object == IOOBJECT_WAL && io_context == IOCONTEXT_INIT && + !(io_op == IOOP_WRITE || io_op == IOOP_FSYNC)) + return false; + + if (io_object == IOOBJECT_WAL && io_context == IOCONTEXT_NORMAL && + !(io_op == IOOP_WRITE || io_op == IOOP_READ || io_op == IOOP_FSYNC)) + return false; + /* * IOOP_FSYNC IOOps done by a backend using a BufferAccessStrategy are * counted in the IOCONTEXT_NORMAL IOContext. See comment in diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 8a3f7d434cfa9..28587e2916b1d 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_relation.c @@ -20,7 +20,6 @@ #include "access/twophase_rmgr.h" #include "access/xact.h" #include "catalog/catalog.h" -#include "postmaster/autovacuum.h" #include "utils/memutils.h" #include "utils/pgstat_internal.h" #include "utils/rel.h" @@ -209,19 +208,22 @@ pgstat_drop_relation(Relation rel) */ void pgstat_report_vacuum(Oid tableoid, bool shared, - PgStat_Counter livetuples, PgStat_Counter deadtuples) + PgStat_Counter livetuples, PgStat_Counter deadtuples, + TimestampTz starttime) { PgStat_EntryRef *entry_ref; PgStatShared_Relation *shtabentry; PgStat_StatTabEntry *tabentry; Oid dboid = (shared ? InvalidOid : MyDatabaseId); TimestampTz ts; + PgStat_Counter elapsedtime; if (!pgstat_track_counts) return; /* Store the data in the table's hash table entry. */ ts = GetCurrentTimestamp(); + elapsedtime = TimestampDifferenceMilliseconds(starttime, ts); /* block acquiring lock for the same reason as pgstat_report_autovac() */ entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, @@ -249,11 +251,13 @@ pgstat_report_vacuum(Oid tableoid, bool shared, { tabentry->last_autovacuum_time = ts; tabentry->autovacuum_count++; + tabentry->total_autovacuum_time += elapsedtime; } else { tabentry->last_vacuum_time = ts; tabentry->vacuum_count++; + tabentry->total_vacuum_time += elapsedtime; } pgstat_unlock_entry(entry_ref); @@ -265,6 +269,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared, * VACUUM command has processed all tables and committed. */ pgstat_flush_io(false); + (void) pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO); } /* @@ -276,12 +281,14 @@ pgstat_report_vacuum(Oid tableoid, bool shared, void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, - bool resetcounter) + bool resetcounter, TimestampTz starttime) { PgStat_EntryRef *entry_ref; PgStatShared_Relation *shtabentry; PgStat_StatTabEntry *tabentry; Oid dboid = (rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId); + TimestampTz ts; + PgStat_Counter elapsedtime; if (!pgstat_track_counts) return; @@ -315,6 +322,10 @@ pgstat_report_analyze(Relation rel, deadtuples = Max(deadtuples, 0); } + /* Store the data in the table's hash table entry. */ + ts = GetCurrentTimestamp(); + elapsedtime = TimestampDifferenceMilliseconds(starttime, ts); + /* block acquiring lock for the same reason as pgstat_report_autovac() */ entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, dboid, RelationGetRelid(rel), @@ -338,19 +349,22 @@ pgstat_report_analyze(Relation rel, if (AmAutoVacuumWorkerProcess()) { - tabentry->last_autoanalyze_time = GetCurrentTimestamp(); + tabentry->last_autoanalyze_time = ts; tabentry->autoanalyze_count++; + tabentry->total_autoanalyze_time += elapsedtime; } else { - tabentry->last_analyze_time = GetCurrentTimestamp(); + tabentry->last_analyze_time = ts; tabentry->analyze_count++; + tabentry->total_analyze_time += elapsedtime; } pgstat_unlock_entry(entry_ref); /* see pgstat_report_vacuum() */ pgstat_flush_io(false); + (void) pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO); } /* @@ -792,8 +806,8 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info, /* * Flush out pending stats for the entry * - * If nowait is true, this function returns false if lock could not - * immediately acquired, otherwise true is returned. + * If nowait is true and the lock could not be immediately acquired, returns + * false without flushing the entry. Otherwise returns true. * * Some of the stats are copied to the corresponding pending database stats * entry when successfully flushing. @@ -801,7 +815,6 @@ pgstat_twophase_postabort(TransactionId xid, uint16 info, bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) { - static const PgStat_TableCounts all_zeroes; Oid dboid; PgStat_TableStatus *lstats; /* pending stats entry */ PgStatShared_Relation *shtabstats; @@ -816,11 +829,9 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) * Ignore entries that didn't accumulate any actual counts, such as * indexes that were opened by the planner but not used. */ - if (memcmp(&lstats->counts, &all_zeroes, - sizeof(PgStat_TableCounts)) == 0) - { + if (pg_memory_is_all_zeros(&lstats->counts, + sizeof(struct PgStat_TableCounts))) return true; - } if (!pgstat_lock_entry(entry_ref, nowait)) return false; @@ -857,7 +868,16 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) tabentry->live_tuples += lstats->counts.delta_live_tuples; tabentry->dead_tuples += lstats->counts.delta_dead_tuples; tabentry->mod_since_analyze += lstats->counts.changed_tuples; + + /* + * Using tuples_inserted to update ins_since_vacuum does mean that we'll + * track aborted inserts too. This isn't ideal, but otherwise probably + * not worth adding an extra field for. It may just amount to autovacuums + * triggering for inserts more often than they maybe should, which is + * probably not going to be common enough to be too concerned about here. + */ tabentry->ins_since_vacuum += lstats->counts.tuples_inserted; + tabentry->blocks_fetched += lstats->counts.blocks_fetched; tabentry->blocks_hit += lstats->counts.blocks_hit; diff --git a/src/backend/utils/activity/pgstat_replslot.c b/src/backend/utils/activity/pgstat_replslot.c index da11b86744595..ccfb11c49bf82 100644 --- a/src/backend/utils/activity/pgstat_replslot.c +++ b/src/backend/utils/activity/pgstat_replslot.c @@ -16,7 +16,7 @@ * dropped while shut down, which is addressed by not restoring stats for * slots that cannot be found by name when starting up. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_replslot.c @@ -193,9 +193,9 @@ pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatSha * isn't allowed to change at this point, we can assume that a slot exists * at the offset. */ - if (!ReplicationSlotName(key->objoid, name)) - elog(ERROR, "could not find name for replication slot index %u", - key->objoid); + if (!ReplicationSlotName(key->objid, name)) + elog(ERROR, "could not find name for replication slot index %" PRIu64, + key->objid); } bool @@ -209,7 +209,7 @@ pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *ke key->kind = PGSTAT_KIND_REPLSLOT; key->dboid = InvalidOid; - key->objoid = idx; + key->objid = idx; return true; } diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c index 1c2b69d563469..53e7d534270ac 100644 --- a/src/backend/utils/activity/pgstat_shmem.c +++ b/src/backend/utils/activity/pgstat_shmem.c @@ -3,7 +3,7 @@ * pgstat_shmem.c * Storage of stats entries in shared memory * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_shmem.c @@ -80,7 +80,7 @@ static const dshash_parameters dsh_params = { * compares to their copy of pgStatSharedRefAge on a regular basis. */ static pgstat_entry_ref_hash_hash *pgStatEntryRefHash = NULL; -static int pgStatSharedRefAge = 0; /* cache age of pgStatShmLookupCache */ +static int pgStatSharedRefAge = 0; /* cache age of pgStatLocal.shmem */ /* * Memory contexts containing the pgStatEntryRefHash table and the @@ -131,6 +131,21 @@ StatsShmemSize(void) sz = MAXALIGN(sizeof(PgStat_ShmemControl)); sz = add_size(sz, pgstat_dsa_init_size()); + /* Add shared memory for all the custom fixed-numbered statistics */ + for (PgStat_Kind kind = PGSTAT_KIND_CUSTOM_MIN; kind <= PGSTAT_KIND_CUSTOM_MAX; kind++) + { + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (!kind_info) + continue; + if (!kind_info->fixed_amount) + continue; + + Assert(kind_info->shared_size != 0); + + sz += MAXALIGN(kind_info->shared_size); + } + return sz; } @@ -168,7 +183,7 @@ StatsShmemInit(void) p += MAXALIGN(pgstat_dsa_init_size()); dsa = dsa_create_in_place(ctl->raw_dsa_area, pgstat_dsa_init_size(), - LWTRANCHE_PGSTATS_DSA, 0); + LWTRANCHE_PGSTATS_DSA, NULL); dsa_pin(dsa); /* @@ -197,15 +212,25 @@ StatsShmemInit(void) pg_atomic_init_u64(&ctl->gc_request_count, 1); /* initialize fixed-numbered stats */ - for (int kind = PGSTAT_KIND_FIRST_VALID; kind <= PGSTAT_KIND_LAST; kind++) + for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++) { const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); char *ptr; - if (!kind_info->fixed_amount) + if (!kind_info || !kind_info->fixed_amount) continue; - ptr = ((char *) ctl) + kind_info->shared_ctl_off; + if (pgstat_is_kind_builtin(kind)) + ptr = ((char *) ctl) + kind_info->shared_ctl_off; + else + { + int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + Assert(kind_info->shared_size != 0); + ctl->custom_data[idx] = ShmemAlloc(kind_info->shared_size); + ptr = ctl->custom_data[idx]; + } + kind_info->init_shmem_cb(ptr); } } @@ -230,7 +255,8 @@ pgstat_attach_shmem(void) dsa_pin_mapping(pgStatLocal.dsa); pgStatLocal.shared_hash = dshash_attach(pgStatLocal.dsa, &dsh_params, - pgStatLocal.shmem->hash_handle, 0); + pgStatLocal.shmem->hash_handle, + NULL); MemoryContextSwitchTo(oldcontext); } @@ -279,6 +305,11 @@ pgstat_init_entry(PgStat_Kind kind, * further if a longer lived reference is needed. */ pg_atomic_init_u32(&shhashent->refcount, 1); + + /* + * Initialize "generation" to 0, as freshly created. + */ + pg_atomic_init_u32(&shhashent->generation, 0); shhashent->dropped = false; chunk = dsa_allocate0(pgStatLocal.dsa, pgstat_get_kind_info(kind)->shared_size); @@ -302,6 +333,12 @@ pgstat_reinit_entry(PgStat_Kind kind, PgStatShared_HashEntry *shhashent) /* mark as not dropped anymore */ pg_atomic_fetch_add_u32(&shhashent->refcount, 1); + + /* + * Increment "generation", to let any backend with local references know + * that what they point to is outdated. + */ + pg_atomic_fetch_add_u32(&shhashent->generation, 1); shhashent->dropped = false; /* reinitialize content */ @@ -342,6 +379,7 @@ pgstat_acquire_entry_ref(PgStat_EntryRef *entry_ref, entry_ref->shared_stats = shheader; entry_ref->shared_entry = shhashent; + entry_ref->generation = pg_atomic_read_u32(&shhashent->generation); } /* @@ -404,14 +442,21 @@ pgstat_get_entry_ref_cached(PgStat_HashKey key, PgStat_EntryRef **entry_ref_p) * if the entry is newly created, false otherwise. */ PgStat_EntryRef * -pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, bool create, +pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry) { - PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid}; + PgStat_HashKey key; PgStatShared_HashEntry *shhashent; PgStatShared_Common *shheader = NULL; PgStat_EntryRef *entry_ref; + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + + key.kind = kind; + key.dboid = dboid; + key.objid = objid; + /* * passing in created_entry only makes sense if we possibly could create * entry. @@ -500,7 +545,8 @@ pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, bool create, * case are replication slot stats, where a new slot can be * created with the same index just after dropping. But oid * wraparound can lead to other cases as well. We just reset the - * stats to their plain state. + * stats to their plain state, while incrementing its "generation" + * in the shared entry for any remaining local references. */ shheader = pgstat_reinit_entry(kind, shhashent); pgstat_acquire_entry_ref(entry_ref, shhashent, shheader); @@ -567,10 +613,27 @@ pgstat_release_entry_ref(PgStat_HashKey key, PgStat_EntryRef *entry_ref, if (!shent) elog(ERROR, "could not find just referenced shared stats entry"); - Assert(pg_atomic_read_u32(&entry_ref->shared_entry->refcount) == 0); - Assert(entry_ref->shared_entry == shent); - - pgstat_free_entry(shent, NULL); + /* + * This entry may have been reinitialized while trying to release + * it, so double-check that it has not been reused while holding a + * lock on its shared entry. + */ + if (pg_atomic_read_u32(&entry_ref->shared_entry->generation) == + entry_ref->generation) + { + /* Same "generation", so we're OK with the removal */ + Assert(pg_atomic_read_u32(&entry_ref->shared_entry->refcount) == 0); + Assert(entry_ref->shared_entry == shent); + pgstat_free_entry(shent, NULL); + } + else + { + /* + * Shared stats entry has been reinitialized, so do not drop + * its shared entry, only release its lock. + */ + dshash_release_lock(pgStatLocal.shared_hash, shent); + } } } @@ -581,6 +644,13 @@ pgstat_release_entry_ref(PgStat_HashKey key, PgStat_EntryRef *entry_ref, pfree(entry_ref); } +/* + * Acquire exclusive lock on the entry. + * + * If nowait is true, it's just a conditional acquire, and the result + * *must* be checked to verify success. + * If nowait is false, waits as necessary, always returning true. + */ bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait) { @@ -594,8 +664,10 @@ pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait) } /* + * Acquire shared lock on the entry. + * * Separate from pgstat_lock_entry() as most callers will need to lock - * exclusively. + * exclusively. The wait semantics are identical. */ bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait) @@ -619,13 +691,13 @@ pgstat_unlock_entry(PgStat_EntryRef *entry_ref) * Helper function to fetch and lock shared stats. */ PgStat_EntryRef * -pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid, +pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait) { PgStat_EntryRef *entry_ref; /* find shared table stats entry corresponding to the local entry */ - entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, true, NULL); + entry_ref = pgstat_get_entry_ref(kind, dboid, objid, true, NULL); /* lock the shared entry to protect the content, skip if failed */ if (!pgstat_lock_entry(entry_ref, nowait)) @@ -667,7 +739,8 @@ pgstat_gc_entry_refs(void) Assert(curage != 0); /* - * Some entries have been dropped. Invalidate cache pointer to them. + * Some entries have been dropped or reinitialized. Invalidate cache + * pointer to them. */ pgstat_entry_ref_hash_start_iterate(pgStatEntryRefHash, &i); while ((ent = pgstat_entry_ref_hash_iterate(pgStatEntryRefHash, &i)) != NULL) @@ -677,7 +750,13 @@ pgstat_gc_entry_refs(void) Assert(!entry_ref->shared_stats || entry_ref->shared_stats->magic == 0xdeadbeef); - if (!entry_ref->shared_entry->dropped) + /* + * "generation" checks for the case of entries being reinitialized, + * and "dropped" for the case where these are.. dropped. + */ + if (!entry_ref->shared_entry->dropped && + pg_atomic_read_u32(&entry_ref->shared_entry->generation) == + entry_ref->generation) continue; /* cannot gc shared ref that has pending data */ @@ -795,9 +874,10 @@ pgstat_drop_entry_internal(PgStatShared_HashEntry *shent, */ if (shent->dropped) elog(ERROR, - "trying to drop stats entry already dropped: kind=%s dboid=%u objoid=%u refcount=%u", + "trying to drop stats entry already dropped: kind=%s dboid=%u objid=%" PRIu64 " refcount=%u", pgstat_get_kind_info(shent->key.kind)->name, - shent->key.dboid, shent->key.objoid, + shent->key.dboid, + shent->key.objid, pg_atomic_read_u32(&shent->refcount)); shent->dropped = true; @@ -862,7 +942,7 @@ pgstat_drop_database_and_contents(Oid dboid) /* * If some of the stats data could not be freed, signal the reference - * holders to run garbage collection of their cached pgStatShmLookupCache. + * holders to run garbage collection of their cached pgStatLocal.shmem. */ if (not_freed_count > 0) pgstat_request_entry_refs_gc(); @@ -880,12 +960,19 @@ pgstat_drop_database_and_contents(Oid dboid) * pgstat_gc_entry_refs(). */ bool -pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid) { - PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid}; + PgStat_HashKey key; PgStatShared_HashEntry *shent; bool freed = true; + /* clear padding */ + memset(&key, 0, sizeof(struct PgStat_HashKey)); + + key.kind = kind; + key.dboid = dboid; + key.objid = objid; + /* delete local reference */ if (pgStatEntryRefHash) { @@ -916,19 +1003,39 @@ pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid) return freed; } +/* + * Scan through the shared hashtable of stats, dropping statistics if + * approved by the optional do_drop() function. + */ void -pgstat_drop_all_entries(void) +pgstat_drop_matching_entries(bool (*do_drop) (PgStatShared_HashEntry *, Datum), + Datum match_data) { dshash_seq_status hstat; PgStatShared_HashEntry *ps; uint64 not_freed_count = 0; + /* entries are removed, take an exclusive lock */ dshash_seq_init(&hstat, pgStatLocal.shared_hash, true); while ((ps = dshash_seq_next(&hstat)) != NULL) { if (ps->dropped) continue; + if (do_drop != NULL && !do_drop(ps, match_data)) + continue; + + /* delete local reference */ + if (pgStatEntryRefHash) + { + PgStat_EntryRefHashEntry *lohashent = + pgstat_entry_ref_hash_lookup(pgStatEntryRefHash, ps->key); + + if (lohashent) + pgstat_release_entry_ref(lohashent->key, lohashent->entry_ref, + true); + } + if (!pgstat_drop_entry_internal(ps, &hstat)) not_freed_count++; } @@ -938,6 +1045,15 @@ pgstat_drop_all_entries(void) pgstat_request_entry_refs_gc(); } +/* + * Scan through the shared hashtable of stats and drop all entries. + */ +void +pgstat_drop_all_entries(void) +{ + pgstat_drop_matching_entries(NULL, 0); +} + static void shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header, TimestampTz ts) @@ -955,13 +1071,13 @@ shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header, * Reset one variable-numbered stats entry. */ void -pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts) +pgstat_reset_entry(PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts) { PgStat_EntryRef *entry_ref; Assert(!pgstat_get_kind_info(kind)->fixed_amount); - entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL); + entry_ref = pgstat_get_entry_ref(kind, dboid, objid, false, NULL); if (!entry_ref || entry_ref->shared_entry->dropped) return; diff --git a/src/backend/utils/activity/pgstat_slru.c b/src/backend/utils/activity/pgstat_slru.c index 6f922a85bfc69..b9e940dde45b6 100644 --- a/src/backend/utils/activity/pgstat_slru.c +++ b/src/backend/utils/activity/pgstat_slru.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_slru.c @@ -32,7 +32,7 @@ static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts); * in order to avoid memory allocation. */ static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS]; -bool have_slrustats = false; +static bool have_slrustats = false; /* @@ -143,6 +143,15 @@ pgstat_get_slru_index(const char *name) return (SLRU_NUM_ELEMENTS - 1); } +/* + * Check if there are any SLRU stats entries waiting for flush. + */ +bool +pgstat_slru_have_pending_cb(void) +{ + return have_slrustats; +} + /* * Flush out locally pending SLRU stats entries * @@ -153,7 +162,7 @@ pgstat_get_slru_index(const char *name) * acquired. Otherwise return false. */ bool -pgstat_slru_flush(bool nowait) +pgstat_slru_flush_cb(bool nowait) { PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru; int i; diff --git a/src/backend/utils/activity/pgstat_subscription.c b/src/backend/utils/activity/pgstat_subscription.c index d9af8de6587e8..f9a1c831a07e6 100644 --- a/src/backend/utils/activity/pgstat_subscription.c +++ b/src/backend/utils/activity/pgstat_subscription.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_subscription.c @@ -39,6 +39,21 @@ pgstat_report_subscription_error(Oid subid, bool is_apply_error) pending->sync_error_count++; } +/* + * Report a subscription conflict. + */ +void +pgstat_report_subscription_conflict(Oid subid, ConflictType type) +{ + PgStat_EntryRef *entry_ref; + PgStat_BackendSubEntry *pending; + + entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_SUBSCRIPTION, + InvalidOid, subid, NULL); + pending = entry_ref->pending; + pending->conflict_count[type]++; +} + /* * Report creating the subscription. */ @@ -81,8 +96,8 @@ pgstat_fetch_stat_subscription(Oid subid) /* * Flush out pending stats for the entry * - * If nowait is true, this function returns false if lock could not - * immediately acquired, otherwise true is returned. + * If nowait is true and the lock could not be immediately acquired, returns + * false without flushing the entry. Otherwise returns true. */ bool pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) @@ -101,6 +116,8 @@ pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) #define SUB_ACC(fld) shsubent->stats.fld += localent->fld SUB_ACC(apply_error_count); SUB_ACC(sync_error_count); + for (int i = 0; i < CONFLICT_NUM_TYPES; i++) + SUB_ACC(conflict_count[i]); #undef SUB_ACC pgstat_unlock_entry(entry_ref); diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c index e2a3f6b865c21..16a1ecb4d90d2 100644 --- a/src/backend/utils/activity/pgstat_wal.c +++ b/src/backend/utils/activity/pgstat_wal.c @@ -8,7 +8,7 @@ * storage implementation and the details about individual types of * statistics. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_wal.c @@ -21,8 +21,6 @@ #include "utils/pgstat_internal.h" -PgStat_PendingWalStats PendingWalStats = {0}; - /* * WAL usage counters saved from pgWalUsage at the previous call to * pgstat_report_wal(). This is used to calculate how much WAL usage @@ -53,10 +51,12 @@ pgstat_report_wal(bool force) nowait = !force; /* flush wal stats */ - pgstat_flush_wal(nowait); + (void) pgstat_wal_flush_cb(nowait); + pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_WAL); /* flush IO stats */ pgstat_flush_io(nowait); + (void) pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_IO); } /* @@ -79,7 +79,7 @@ pgstat_fetch_stat_wal(void) * acquired. Otherwise return false. */ bool -pgstat_flush_wal(bool nowait) +pgstat_wal_flush_cb(bool nowait) { PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal; WalUsage wal_usage_diff = {0}; @@ -92,7 +92,7 @@ pgstat_flush_wal(bool nowait) * This function can be called even if nothing at all has happened. Avoid * taking lock for nothing in that case. */ - if (!pgstat_have_pending_wal()) + if (!pgstat_wal_have_pending_cb()) return false; /* @@ -108,18 +108,11 @@ pgstat_flush_wal(bool nowait) return true; #define WALSTAT_ACC(fld, var_to_add) \ - (stats_shmem->stats.fld += var_to_add.fld) -#define WALSTAT_ACC_INSTR_TIME(fld) \ - (stats_shmem->stats.fld += INSTR_TIME_GET_MICROSEC(PendingWalStats.fld)) + (stats_shmem->stats.wal_counters.fld += var_to_add.fld) WALSTAT_ACC(wal_records, wal_usage_diff); WALSTAT_ACC(wal_fpi, wal_usage_diff); WALSTAT_ACC(wal_bytes, wal_usage_diff); - WALSTAT_ACC(wal_buffers_full, PendingWalStats); - WALSTAT_ACC(wal_write, PendingWalStats); - WALSTAT_ACC(wal_sync, PendingWalStats); - WALSTAT_ACC_INSTR_TIME(wal_write_time); - WALSTAT_ACC_INSTR_TIME(wal_sync_time); -#undef WALSTAT_ACC_INSTR_TIME + WALSTAT_ACC(wal_buffers_full, wal_usage_diff); #undef WALSTAT_ACC LWLockRelease(&stats_shmem->lock); @@ -129,38 +122,27 @@ pgstat_flush_wal(bool nowait) */ prevWalUsage = pgWalUsage; - /* - * Clear out the statistics buffer, so it can be re-used. - */ - MemSet(&PendingWalStats, 0, sizeof(PendingWalStats)); - return false; } void -pgstat_init_wal(void) +pgstat_wal_init_backend_cb(void) { /* - * Initialize prevWalUsage with pgWalUsage so that pgstat_flush_wal() can - * calculate how much pgWalUsage counters are increased by subtracting + * Initialize prevWalUsage with pgWalUsage so that pgstat_wal_flush_cb() + * can calculate how much pgWalUsage counters are increased by subtracting * prevWalUsage from pgWalUsage. */ prevWalUsage = pgWalUsage; } /* - * To determine whether any WAL activity has occurred since last time, not - * only the number of generated WAL records but also the numbers of WAL - * writes and syncs need to be checked. Because even transaction that - * generates no WAL records can write or sync WAL data when flushing the - * data pages. + * To determine whether WAL usage happened. */ bool -pgstat_have_pending_wal(void) +pgstat_wal_have_pending_cb(void) { - return pgWalUsage.wal_records != prevWalUsage.wal_records || - PendingWalStats.wal_write != 0 || - PendingWalStats.wal_sync != 0; + return pgWalUsage.wal_records != prevWalUsage.wal_records; } void diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c index 1877d22f146bc..bc9864bd8d9d0 100644 --- a/src/backend/utils/activity/pgstat_xact.c +++ b/src/backend/utils/activity/pgstat_xact.c @@ -3,7 +3,7 @@ * pgstat_xact.c * Transactional integration for the cumulative statistics system. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/activity/pgstat_xact.c @@ -77,6 +77,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit) PgStat_PendingDroppedStatsItem *pending = dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur); xl_xact_stats_item *it = &pending->item; + uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo; if (isCommit && !pending->is_create) { @@ -84,7 +85,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit) * Transaction that dropped an object committed. Drop the stats * too. */ - if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid)) + if (!pgstat_drop_entry(it->kind, it->dboid, objid)) not_freed_count++; } else if (!isCommit && pending->is_create) @@ -93,7 +94,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit) * Transaction that created an object aborted. Drop the stats * associated with the object. */ - if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid)) + if (!pgstat_drop_entry(it->kind, it->dboid, objid)) not_freed_count++; } @@ -149,6 +150,7 @@ AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, PgStat_PendingDroppedStatsItem *pending = dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur); xl_xact_stats_item *it = &pending->item; + uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo; dclist_delete_from(&xact_state->pending_drops, &pending->node); @@ -158,7 +160,7 @@ AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, * Subtransaction creating a new stats object aborted. Drop the * stats object. */ - if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid)) + if (!pgstat_drop_entry(it->kind, it->dboid, objid)) not_freed_count++; pfree(pending); } @@ -319,8 +321,9 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items, for (int i = 0; i < ndrops; i++) { xl_xact_stats_item *it = &items[i]; + uint64 objid = ((uint64) it->objid_hi) << 32 | it->objid_lo; - if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid)) + if (!pgstat_drop_entry(it->kind, it->dboid, objid)) not_freed_count++; } @@ -329,7 +332,7 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items, } static void -create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool is_create) +create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, uint64 objid, bool is_create) { int nest_level = GetCurrentTransactionNestLevel(); PgStat_SubXactStatus *xact_state; @@ -341,7 +344,8 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool drop->is_create = is_create; drop->item.kind = kind; drop->item.dboid = dboid; - drop->item.objoid = objoid; + drop->item.objid_lo = (uint32) objid; + drop->item.objid_hi = (uint32) (objid >> 32); dclist_push_tail(&xact_state->pending_drops, &drop->node); } @@ -354,18 +358,19 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool * dropped. */ void -pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_create_transactional(PgStat_Kind kind, Oid dboid, uint64 objid) { - if (pgstat_get_entry_ref(kind, dboid, objoid, false, NULL)) + if (pgstat_get_entry_ref(kind, dboid, objid, false, NULL)) { ereport(WARNING, - errmsg("resetting existing statistics for kind %s, db=%u, oid=%u", - (pgstat_get_kind_info(kind))->name, dboid, objoid)); + errmsg("resetting existing statistics for kind %s, db=%u, oid=%" PRIu64, + (pgstat_get_kind_info(kind))->name, dboid, + objid)); - pgstat_reset(kind, dboid, objoid); + pgstat_reset(kind, dboid, objid); } - create_drop_transactional_internal(kind, dboid, objoid, /* create */ true); + create_drop_transactional_internal(kind, dboid, objid, /* create */ true); } /* @@ -376,7 +381,7 @@ pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid) * alive. */ void -pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid) +pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, uint64 objid) { - create_drop_transactional_internal(kind, dboid, objoid, /* create */ false); + create_drop_transactional_internal(kind, dboid, objid, /* create */ false); } diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c index bbf59482be196..d9b8f34a3559d 100644 --- a/src/backend/utils/activity/wait_event.c +++ b/src/backend/utils/activity/wait_event.c @@ -2,7 +2,7 @@ * wait_event.c * Wait event reporting infrastructure. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -22,7 +22,6 @@ */ #include "postgres.h" -#include "port/pg_bitutils.h" #include "storage/lmgr.h" /* for GetLockNameFromTagType */ #include "storage/lwlock.h" /* for GetLWLockIdentifier */ #include "storage/spin.h" diff --git a/src/backend/utils/activity/wait_event_funcs.c b/src/backend/utils/activity/wait_event_funcs.c index fa8bc05c0c73f..ffbb57a80780f 100644 --- a/src/backend/utils/activity/wait_event_funcs.c +++ b/src/backend/utils/activity/wait_event_funcs.c @@ -3,7 +3,7 @@ * wait_event_funcs.c * Functions for accessing wait event data. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt index db37beeaae610..4da68312b5f97 100644 --- a/src/backend/utils/activity/wait_event_names.txt +++ b/src/backend/utils/activity/wait_event_names.txt @@ -2,7 +2,7 @@ # wait_event_names.txt # PostgreSQL wait events # -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # This list serves as the basis for generating source and documentation files # related to wait events. @@ -56,6 +56,8 @@ AUTOVACUUM_MAIN "Waiting in main loop of autovacuum launcher process." BGWRITER_HIBERNATE "Waiting in background writer process, hibernating." BGWRITER_MAIN "Waiting in main loop of background writer process." CHECKPOINTER_MAIN "Waiting in main loop of checkpointer process." +CHECKPOINTER_SHUTDOWN "Waiting for checkpointer process to be terminated." +IO_WORKER_MAIN "Waiting in main loop of IO Worker process." LOGICAL_APPLY_MAIN "Waiting in main loop of logical replication apply process." LOGICAL_LAUNCHER_MAIN "Waiting in main loop of logical replication launcher process." LOGICAL_PARALLEL_APPLY_MAIN "Waiting in main loop of logical replication parallel apply process." @@ -142,7 +144,7 @@ MULTIXACT_CREATION "Waiting for a multixact creation to complete." PARALLEL_BITMAP_SCAN "Waiting for parallel bitmap scan to become initialized." PARALLEL_CREATE_INDEX_SCAN "Waiting for parallel CREATE INDEX workers to finish heap scan." PARALLEL_FINISH "Waiting for parallel workers to finish computing." -PROCARRAY_GROUP_UPDATE "Waiting for the group leader to clear the transaction ID at end of a parallel operation." +PROCARRAY_GROUP_UPDATE "Waiting for the group leader to clear the transaction ID at transaction end." PROC_SIGNAL_BARRIER "Waiting for a barrier event to be processed by all backends." PROMOTE "Waiting for standby promotion." RECOVERY_CONFLICT_SNAPSHOT "Waiting for recovery conflict resolution for a vacuum cleanup." @@ -154,10 +156,11 @@ REPLICATION_SLOT_DROP "Waiting for a replication slot to become inactive so it c RESTORE_COMMAND "Waiting for to complete." SAFE_SNAPSHOT "Waiting to obtain a valid snapshot for a READ ONLY DEFERRABLE transaction." SYNC_REP "Waiting for confirmation from a remote server during synchronous replication." +WAL_BUFFER_INIT "Waiting on WAL buffer to be initialized." WAL_RECEIVER_EXIT "Waiting for the WAL receiver to exit." WAL_RECEIVER_WAIT_START "Waiting for startup process to send initial data for streaming replication." WAL_SUMMARY_READY "Waiting for a new WAL summary to be generated." -XACT_GROUP_UPDATE "Waiting for the group leader to update transaction status at end of a parallel operation." +XACT_GROUP_UPDATE "Waiting for the group leader to update transaction status at transaction end." ABI_compatibility: @@ -190,6 +193,9 @@ ABI_compatibility: Section: ClassName - WaitEventIO +AIO_IO_COMPLETION "Waiting for another process to complete IO." +AIO_IO_URING_SUBMIT "Waiting for IO submission via io_uring." +AIO_IO_URING_EXECUTION "Waiting for IO execution via io_uring." BASEBACKUP_READ "Waiting for base backup to read from a file." BASEBACKUP_SYNC "Waiting for data written by a base backup to reach durable storage." BASEBACKUP_WRITE "Waiting for base backup to write to a file." @@ -201,6 +207,7 @@ CONTROL_FILE_SYNC "Waiting for the pg_control file to reach CONTROL_FILE_SYNC_UPDATE "Waiting for an update to the pg_control file to reach durable storage." CONTROL_FILE_WRITE "Waiting for a write to the pg_control file." CONTROL_FILE_WRITE_UPDATE "Waiting for a write to update the pg_control file." +COPY_FILE_COPY "Waiting for a file copy operation." COPY_FILE_READ "Waiting for a read during a file copy operation." COPY_FILE_WRITE "Waiting for a write during a file copy operation." DATA_FILE_EXTEND "Waiting for a relation data file to be extended." @@ -309,7 +316,6 @@ XidGen "Waiting to allocate a new transaction ID." ProcArray "Waiting to access the shared per-process data structures (typically, to get a snapshot or report a session's transaction ID)." SInvalRead "Waiting to retrieve messages from the shared catalog invalidation queue." SInvalWrite "Waiting to add a message to the shared catalog invalidation queue." -WALBufMapping "Waiting to replace a page in WAL buffers." WALWrite "Waiting for WAL buffers to be written to disk." ControlFile "Waiting to read or update the pg_control file or create a new WAL file." MultiXactGen "Waiting to read or update shared multixact state." @@ -345,6 +351,7 @@ WALSummarizer "Waiting to read or update WAL summarization state." DSMRegistry "Waiting to read or update the dynamic shared memory registry." InjectionPoint "Waiting to read or update information related to injection points." SerialControl "Waiting to read or update shared pg_serial state." +AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue." # # END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE) @@ -370,6 +377,7 @@ BufferMapping "Waiting to associate a data block with a buffer in the buffer poo LockManager "Waiting to read or update information about heavyweight locks." PredicateLockManager "Waiting to access predicate lock information used by serializable transactions." ParallelHashJoin "Waiting to synchronize workers during Parallel Hash Join plan execution." +ParallelBtreeScan "Waiting to synchronize workers during Parallel B-tree scan plan execution." ParallelQueryDSA "Waiting for parallel query dynamic shared memory allocation." PerSessionDSA "Waiting for parallel query dynamic shared memory allocation." PerSessionRecordType "Waiting to access a parallel query's information about composite types." @@ -393,6 +401,7 @@ SerialSLRU "Waiting to access the serializable transaction conflict SLRU cache." SubtransSLRU "Waiting to access the sub-transaction SLRU cache." XactSLRU "Waiting to access the transaction status SLRU cache." ParallelVacuumDSA "Waiting for parallel vacuum dynamic shared memory allocation." +AioUringCompletion "Waiting for another process to complete IO via io_uring." # No "ABI_compatibility" region here as WaitEventLWLock has its own C code. diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index edb09d4e35622..4a233b63c3280 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -79,6 +79,9 @@ OBJS = \ orderedsetaggs.o \ partitionfuncs.o \ pg_locale.o \ + pg_locale_builtin.o \ + pg_locale_icu.o \ + pg_locale_libc.o \ pg_lsn.o \ pg_upgrade_support.o \ pgstatfuncs.o \ @@ -96,6 +99,7 @@ OBJS = \ rowtypes.o \ ruleutils.o \ selfuncs.o \ + skipsupport.o \ tid.o \ timestamp.o \ trigfuncs.o \ diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index d7b39140b3d22..ca3c5ee3df3ae 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -3,7 +3,7 @@ * acl.c * Basic access control list data structures manipulation routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,6 +26,7 @@ #include "catalog/pg_foreign_data_wrapper.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_language.h" +#include "catalog/pg_largeobject.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_tablespace.h" @@ -39,6 +40,7 @@ #include "lib/bloomfilter.h" #include "lib/qunique.h" #include "miscadmin.h" +#include "storage/large_object.h" #include "utils/acl.h" #include "utils/array.h" #include "utils/builtins.h" @@ -46,6 +48,7 @@ #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/snapmgr.h" #include "utils/syscache.h" #include "utils/varlena.h" @@ -124,6 +127,7 @@ static AclMode convert_tablespace_priv_string(text *priv_type_text); static Oid convert_type_name(text *typename); static AclMode convert_type_priv_string(text *priv_type_text); static AclMode convert_parameter_priv_string(text *priv_text); +static AclMode convert_largeobject_priv_string(text *priv_type_text); static AclMode convert_role_priv_string(text *priv_type_text); static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode); @@ -341,9 +345,6 @@ aclparse(const char *s, AclItem *aip, Node *escontext) case ACL_MAINTAIN_CHR: read = ACL_MAINTAIN; break; - case 'R': /* ignore old RULE privileges */ - read = 0; - break; default: ereturn(escontext, NULL, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), @@ -1639,7 +1640,6 @@ makeaclitem(PG_FUNCTION_ARGS) {"SET", ACL_SET}, {"ALTER SYSTEM", ACL_ALTER_SYSTEM}, {"MAINTAIN", ACL_MAINTAIN}, - {"RULE", 0}, /* ignore old RULE privileges */ {NULL, 0} }; @@ -1808,7 +1808,7 @@ aclexplode(PG_FUNCTION_ARGS) idx = (int *) palloc(sizeof(int[2])); idx[0] = 0; /* ACL array item index */ idx[1] = -1; /* privilege type counter */ - funcctx->user_fctx = (void *) idx; + funcctx->user_fctx = idx; MemoryContextSwitchTo(oldcontext); } @@ -2063,8 +2063,6 @@ convert_table_priv_string(text *priv_type_text) {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)}, {"MAINTAIN", ACL_MAINTAIN}, {"MAINTAIN WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_MAINTAIN)}, - {"RULE", 0}, /* ignore old RULE privileges */ - {"RULE WITH GRANT OPTION", 0}, {NULL, 0} }; @@ -4669,6 +4667,142 @@ convert_parameter_priv_string(text *priv_text) return convert_any_priv_string(priv_text, parameter_priv_map); } +/* + * has_largeobject_privilege variants + * These are all named "has_largeobject_privilege" at the SQL level. + * They take various combinations of large object OID with + * user name, user OID, or implicit user = current_user. + * + * The result is a boolean value: true if user has the indicated + * privilege, false if not, or NULL if object doesn't exist. + */ + +/* + * has_lo_priv_byid + * + * Helper function to check user privileges on a large object given the + * role by Oid, large object by Oid, and privileges as AclMode. + */ +static bool +has_lo_priv_byid(Oid roleid, Oid lobjId, AclMode priv, bool *is_missing) +{ + Snapshot snapshot = NULL; + AclResult aclresult; + + if (priv & ACL_UPDATE) + snapshot = NULL; + else + snapshot = GetActiveSnapshot(); + + if (!LargeObjectExistsWithSnapshot(lobjId, snapshot)) + { + Assert(is_missing != NULL); + *is_missing = true; + return false; + } + + if (lo_compat_privileges) + return true; + + aclresult = pg_largeobject_aclcheck_snapshot(lobjId, + roleid, + priv, + snapshot); + return aclresult == ACLCHECK_OK; +} + +/* + * has_largeobject_privilege_name_id + * Check user privileges on a large object given + * name username, large object oid, and text priv name. + */ +Datum +has_largeobject_privilege_name_id(PG_FUNCTION_ARGS) +{ + Name username = PG_GETARG_NAME(0); + Oid roleid = get_role_oid_or_public(NameStr(*username)); + Oid lobjId = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_PP(2); + AclMode mode; + bool is_missing = false; + bool result; + + mode = convert_largeobject_priv_string(priv_type_text); + result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing); + + if (is_missing) + PG_RETURN_NULL(); + + PG_RETURN_BOOL(result); +} + +/* + * has_largeobject_privilege_id + * Check user privileges on a large object given + * large object oid, and text priv name. + * current_user is assumed + */ +Datum +has_largeobject_privilege_id(PG_FUNCTION_ARGS) +{ + Oid lobjId = PG_GETARG_OID(0); + Oid roleid = GetUserId(); + text *priv_type_text = PG_GETARG_TEXT_PP(1); + AclMode mode; + bool is_missing = false; + bool result; + + mode = convert_largeobject_priv_string(priv_type_text); + result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing); + + if (is_missing) + PG_RETURN_NULL(); + + PG_RETURN_BOOL(result); +} + +/* + * has_largeobject_privilege_id_id + * Check user privileges on a large object given + * roleid, large object oid, and text priv name. + */ +Datum +has_largeobject_privilege_id_id(PG_FUNCTION_ARGS) +{ + Oid roleid = PG_GETARG_OID(0); + Oid lobjId = PG_GETARG_OID(1); + text *priv_type_text = PG_GETARG_TEXT_PP(2); + AclMode mode; + bool is_missing = false; + bool result; + + mode = convert_largeobject_priv_string(priv_type_text); + result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing); + + if (is_missing) + PG_RETURN_NULL(); + + PG_RETURN_BOOL(result); +} + +/* + * convert_largeobject_priv_string + * Convert text string to AclMode value. + */ +static AclMode +convert_largeobject_priv_string(text *priv_type_text) +{ + static const priv_map largeobject_priv_map[] = { + {"SELECT", ACL_SELECT}, + {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)}, + {"UPDATE", ACL_UPDATE}, + {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)}, + {NULL, 0} + }; + + return convert_any_priv_string(priv_type_text, largeobject_priv_map); +} + /* * pg_has_role variants * These are all named "pg_has_role" at the SQL level. @@ -5298,24 +5432,6 @@ select_best_admin(Oid member, Oid role) return admin_role; } - -/* does what it says ... */ -static int -count_one_bits(AclMode mask) -{ - int nbits = 0; - - /* this code relies on AclMode being an unsigned type */ - while (mask) - { - if (mask & 1) - nbits++; - mask >>= 1; - } - return nbits; -} - - /* * Select the effective grantor ID for a GRANT or REVOKE operation. * @@ -5398,7 +5514,7 @@ select_best_grantor(Oid roleId, AclMode privileges, */ if (otherprivs != ACL_NO_RIGHTS) { - int nnewrights = count_one_bits(otherprivs); + int nnewrights = pg_popcount64(otherprivs); if (nnewrights > nrights) { diff --git a/src/backend/utils/adt/amutils.c b/src/backend/utils/adt/amutils.c index dd39a994c8df0..0af26d6acfab8 100644 --- a/src/backend/utils/adt/amutils.c +++ b/src/backend/utils/adt/amutils.c @@ -3,7 +3,7 @@ * amutils.c * SQL-level APIs related to index access methods. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/array_expanded.c b/src/backend/utils/adt/array_expanded.c index cc3713b97b71e..fc036d1eb3007 100644 --- a/src/backend/utils/adt/array_expanded.c +++ b/src/backend/utils/adt/array_expanded.c @@ -3,7 +3,7 @@ * array_expanded.c * Basic functions for manipulating expanded arrays. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c index e2af89f5cc557..a69a84c2aee33 100644 --- a/src/backend/utils/adt/array_selfuncs.c +++ b/src/backend/utils/adt/array_selfuncs.c @@ -3,7 +3,7 @@ * array_selfuncs.c * Functions for selectivity estimation of array operators * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c index 2c633bee6b1c6..6f61629b9778d 100644 --- a/src/backend/utils/adt/array_typanalyze.c +++ b/src/backend/utils/adt/array_typanalyze.c @@ -3,7 +3,7 @@ * array_typanalyze.c * Functions for gathering statistics from array columns * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -314,7 +314,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, int distinct_count; bool count_item_found; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, array_no, &isnull); if (isnull) diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c index 6599be2ec5e88..8eb342e33823a 100644 --- a/src/backend/utils/adt/array_userfuncs.c +++ b/src/backend/utils/adt/array_userfuncs.c @@ -3,7 +3,7 @@ * array_userfuncs.c * Misc user-visible array support functions * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/array_userfuncs.c @@ -12,15 +12,19 @@ */ #include "postgres.h" +#include "catalog/pg_operator_d.h" #include "catalog/pg_type.h" #include "common/int.h" #include "common/pg_prng.h" #include "libpq/pqformat.h" +#include "miscadmin.h" +#include "nodes/supportnodes.h" #include "port/pg_bitutils.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/datum.h" #include "utils/lsyscache.h" +#include "utils/tuplesort.h" #include "utils/typcache.h" /* @@ -42,6 +46,18 @@ typedef struct DeserialIOData Oid typioparam; } DeserialIOData; +/* + * ArraySortCachedInfo + * Used for caching catalog data in array_sort + */ +typedef struct ArraySortCachedInfo +{ + ArrayMetaState array_meta; /* metadata for array_create_iterator */ + Oid elem_lt_opr; /* "<" operator for element type */ + Oid elem_gt_opr; /* ">" operator for element type */ + Oid array_type; /* pg_type OID of array type */ +} ArraySortCachedInfo; + static Datum array_position_common(FunctionCallInfo fcinfo); @@ -167,6 +183,36 @@ array_append(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } +/* + * array_append_support() + * + * Planner support function for array_append() + */ +Datum +array_append_support(PG_FUNCTION_ARGS) +{ + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestModifyInPlace)) + { + /* + * We can optimize in-place appends if the function's array argument + * is the array being assigned to. We don't need to worry about array + * references within the other argument. + */ + SupportRequestModifyInPlace *req = (SupportRequestModifyInPlace *) rawreq; + Param *arg = (Param *) linitial(req->args); + + if (arg && IsA(arg, Param) && + arg->paramkind == PARAM_EXTERN && + arg->paramid == req->paramid) + ret = (Node *) arg; + } + + PG_RETURN_POINTER(ret); +} + /*----------------------------------------------------------------------------- * array_prepend : * push an element onto the front of a one-dimensional array @@ -230,6 +276,36 @@ array_prepend(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } +/* + * array_prepend_support() + * + * Planner support function for array_prepend() + */ +Datum +array_prepend_support(PG_FUNCTION_ARGS) +{ + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestModifyInPlace)) + { + /* + * We can optimize in-place prepends if the function's array argument + * is the array being assigned to. We don't need to worry about array + * references within the other argument. + */ + SupportRequestModifyInPlace *req = (SupportRequestModifyInPlace *) rawreq; + Param *arg = (Param *) lsecond(req->args); + + if (arg && IsA(arg, Param) && + arg->paramkind == PARAM_EXTERN && + arg->paramid == req->paramid) + ret = (Node *) arg; + } + + PG_RETURN_POINTER(ret); +} + /*----------------------------------------------------------------------------- * array_cat : * concatenate two nD arrays to form an nD array, or @@ -685,7 +761,7 @@ array_agg_serialize(PG_FUNCTION_ARGS) &typisvarlena); fmgr_info_cxt(typsend, &iodata->typsend, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) iodata; + fcinfo->flinfo->fn_extra = iodata; } for (i = 0; i < state->nelems; i++) @@ -776,7 +852,7 @@ array_agg_deserialize(PG_FUNCTION_ARGS) &iodata->typioparam); fmgr_info_cxt(typreceive, &iodata->typreceive, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) iodata; + fcinfo->flinfo->fn_extra = iodata; } for (int i = 0; i < nelems; i++) @@ -1642,7 +1718,7 @@ array_shuffle(PG_FUNCTION_ARGS) if (typentry == NULL || typentry->type_id != elmtyp) { typentry = lookup_type_cache(elmtyp, 0); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } result = array_shuffle_n(array, ARR_DIMS(array)[0], true, elmtyp, typentry); @@ -1678,10 +1754,285 @@ array_sample(PG_FUNCTION_ARGS) if (typentry == NULL || typentry->type_id != elmtyp) { typentry = lookup_type_cache(elmtyp, 0); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } result = array_shuffle_n(array, n, false, elmtyp, typentry); PG_RETURN_ARRAYTYPE_P(result); } + + +/* + * array_reverse_n + * Return a copy of array with reversed items. + * + * NOTE: it would be cleaner to look up the elmlen/elmbval/elmalign info + * from the system catalogs, given only the elmtyp. However, the caller is + * in a better position to cache this info across multiple calls. + */ +static ArrayType * +array_reverse_n(ArrayType *array, Oid elmtyp, TypeCacheEntry *typentry) +{ + ArrayType *result; + int ndim, + *dims, + *lbs, + nelm, + nitem, + rdims[MAXDIM], + rlbs[MAXDIM]; + int16 elmlen; + bool elmbyval; + char elmalign; + Datum *elms, + *ielms; + bool *nuls, + *inuls; + + ndim = ARR_NDIM(array); + dims = ARR_DIMS(array); + lbs = ARR_LBOUND(array); + + elmlen = typentry->typlen; + elmbyval = typentry->typbyval; + elmalign = typentry->typalign; + + deconstruct_array(array, elmtyp, elmlen, elmbyval, elmalign, + &elms, &nuls, &nelm); + + nitem = dims[0]; /* total number of items */ + nelm /= nitem; /* number of elements per item */ + + /* Reverse the array */ + ielms = elms; + inuls = nuls; + for (int i = 0; i < nitem / 2; i++) + { + int j = (nitem - i - 1) * nelm; + Datum *jelms = elms + j; + bool *jnuls = nuls + j; + + /* Swap i'th and j'th items; advance ielms/inuls to next item */ + for (int k = 0; k < nelm; k++) + { + Datum elm = *ielms; + bool nul = *inuls; + + *ielms++ = *jelms; + *inuls++ = *jnuls; + *jelms++ = elm; + *jnuls++ = nul; + } + } + + /* Set up dimensions of the result */ + memcpy(rdims, dims, ndim * sizeof(int)); + memcpy(rlbs, lbs, ndim * sizeof(int)); + rdims[0] = nitem; + + result = construct_md_array(elms, nuls, ndim, rdims, rlbs, + elmtyp, elmlen, elmbyval, elmalign); + + pfree(elms); + pfree(nuls); + + return result; +} + +/* + * array_reverse + * + * Returns an array with the same dimensions as the input array, with its + * first-dimension elements in reverse order. + */ +Datum +array_reverse(PG_FUNCTION_ARGS) +{ + ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); + ArrayType *result; + Oid elmtyp; + TypeCacheEntry *typentry; + + /* + * There is no point in reversing empty arrays or arrays with less than + * two items. + */ + if (ARR_NDIM(array) < 1 || ARR_DIMS(array)[0] < 2) + PG_RETURN_ARRAYTYPE_P(array); + + elmtyp = ARR_ELEMTYPE(array); + typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; + if (typentry == NULL || typentry->type_id != elmtyp) + { + typentry = lookup_type_cache(elmtyp, 0); + fcinfo->flinfo->fn_extra = (void *) typentry; + } + + result = array_reverse_n(array, elmtyp, typentry); + + PG_RETURN_ARRAYTYPE_P(result); +} + +/* + * array_sort + * + * Sorts the first dimension of the array. + */ +static ArrayType * +array_sort_internal(ArrayType *array, bool descending, bool nulls_first, + FunctionCallInfo fcinfo) +{ + ArrayType *newarray; + Oid collation = PG_GET_COLLATION(); + int ndim, + *dims, + *lbs; + ArraySortCachedInfo *cache_info; + Oid elmtyp; + Oid sort_typ; + Oid sort_opr; + Tuplesortstate *tuplesortstate; + ArrayIterator array_iterator; + Datum value; + bool isnull; + ArrayBuildStateAny *astate = NULL; + + ndim = ARR_NDIM(array); + dims = ARR_DIMS(array); + lbs = ARR_LBOUND(array); + + /* Quick exit if we don't need to sort */ + if (ndim < 1 || dims[0] < 2) + return array; + + /* Set up cache area if we didn't already */ + cache_info = (ArraySortCachedInfo *) fcinfo->flinfo->fn_extra; + if (cache_info == NULL) + { + cache_info = (ArraySortCachedInfo *) + MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, + sizeof(ArraySortCachedInfo)); + fcinfo->flinfo->fn_extra = cache_info; + } + + /* Fetch and cache required data if we don't have it */ + elmtyp = ARR_ELEMTYPE(array); + if (elmtyp != cache_info->array_meta.element_type) + { + TypeCacheEntry *typentry; + + typentry = lookup_type_cache(elmtyp, + TYPECACHE_LT_OPR | TYPECACHE_GT_OPR); + cache_info->array_meta.element_type = elmtyp; + cache_info->array_meta.typlen = typentry->typlen; + cache_info->array_meta.typbyval = typentry->typbyval; + cache_info->array_meta.typalign = typentry->typalign; + cache_info->elem_lt_opr = typentry->lt_opr; + cache_info->elem_gt_opr = typentry->gt_opr; + cache_info->array_type = typentry->typarray; + } + + /* Identify the sort operator to use */ + if (ndim == 1) + { + /* Need to sort the element type */ + sort_typ = elmtyp; + sort_opr = (descending ? cache_info->elem_gt_opr : cache_info->elem_lt_opr); + } + else + { + /* Otherwise we're sorting arrays */ + sort_typ = cache_info->array_type; + if (!OidIsValid(sort_typ)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("could not find array type for data type %s", + format_type_be(elmtyp)))); + /* We know what operators to use for arrays */ + sort_opr = (descending ? ARRAY_GT_OP : ARRAY_LT_OP); + } + + /* + * Fail if we don't know how to sort. The error message is chosen to + * match what array_lt()/array_gt() will say in the multidimensional case. + */ + if (!OidIsValid(sort_opr)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("could not identify a comparison function for type %s", + format_type_be(elmtyp))); + + /* Put the things to be sorted (elements or sub-arrays) into a tuplesort */ + tuplesortstate = tuplesort_begin_datum(sort_typ, + sort_opr, + collation, + nulls_first, + work_mem, + NULL, + TUPLESORT_NONE); + + array_iterator = array_create_iterator(array, ndim - 1, + &cache_info->array_meta); + while (array_iterate(array_iterator, &value, &isnull)) + { + tuplesort_putdatum(tuplesortstate, value, isnull); + } + array_free_iterator(array_iterator); + + /* Do the sort */ + tuplesort_performsort(tuplesortstate); + + /* Extract results into a new array */ + while (tuplesort_getdatum(tuplesortstate, true, false, &value, &isnull, NULL)) + { + astate = accumArrayResultAny(astate, value, isnull, + sort_typ, CurrentMemoryContext); + } + tuplesort_end(tuplesortstate); + + newarray = DatumGetArrayTypeP(makeArrayResultAny(astate, + CurrentMemoryContext, + true)); + + /* Adjust lower bound to match the input */ + ARR_LBOUND(newarray)[0] = lbs[0]; + + return newarray; +} + +Datum +array_sort(PG_FUNCTION_ARGS) +{ + ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); + + PG_RETURN_ARRAYTYPE_P(array_sort_internal(array, + false, + false, + fcinfo)); +} + +Datum +array_sort_order(PG_FUNCTION_ARGS) +{ + ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); + bool descending = PG_GETARG_BOOL(1); + + PG_RETURN_ARRAYTYPE_P(array_sort_internal(array, + descending, + descending, + fcinfo)); +} + +Datum +array_sort_order_nulls_first(PG_FUNCTION_ARGS) +{ + ArrayType *array = PG_GETARG_ARRAYTYPE_P(0); + bool descending = PG_GETARG_BOOL(1); + bool nulls_first = PG_GETARG_BOOL(2); + + PG_RETURN_ARRAYTYPE_P(array_sort_internal(array, + descending, + nulls_first, + fcinfo)); +} diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index e5c7e57a5decf..c8f53c6fbe788 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3,7 +3,7 @@ * arrayfuncs.c * Support functions for arrays. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -3404,6 +3404,12 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype) elmalign = TYPALIGN_INT; break; + case FLOAT8OID: + elmlen = sizeof(float8); + elmbyval = FLOAT8PASSBYVAL; + elmalign = TYPALIGN_DOUBLE; + break; + case INT2OID: elmlen = sizeof(int16); elmbyval = true; @@ -3447,6 +3453,12 @@ construct_array_builtin(Datum *elems, int nelems, Oid elmtype) elmalign = TYPALIGN_SHORT; break; + case XIDOID: + elmlen = sizeof(TransactionId); + elmbyval = true; + elmalign = TYPALIGN_INT; + break; + default: elog(ERROR, "type %u not supported by construct_array_builtin()", elmtype); /* keep compiler quiet */ @@ -3851,7 +3863,7 @@ array_eq(PG_FUNCTION_ARGS) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -4015,7 +4027,7 @@ array_cmp(FunctionCallInfo fcinfo) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a comparison function for type %s", format_type_be(element_type)))); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -4210,7 +4222,7 @@ hash_array(PG_FUNCTION_ARGS) typentry = record_typentry; } - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } typlen = typentry->typlen; @@ -4304,7 +4316,7 @@ hash_array_extended(PG_FUNCTION_ARGS) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an extended hash function for type %s", format_type_be(element_type)))); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -4406,7 +4418,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); - *fn_extra = (void *) typentry; + *fn_extra = typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -5770,9 +5782,14 @@ ArrayBuildStateAny * initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext) { ArrayBuildStateAny *astate; - Oid element_type = get_element_type(input_type); - if (OidIsValid(element_type)) + /* + * int2vector and oidvector will satisfy both get_element_type and + * get_array_type. We prefer to treat them as scalars, to be consistent + * with get_promoted_array_type. Hence, check get_array_type not + * get_element_type. + */ + if (!OidIsValid(get_array_type(input_type))) { /* Array case */ ArrayBuildStateArr *arraystate; @@ -5789,9 +5806,6 @@ initArrayResultAny(Oid input_type, MemoryContext rcontext, bool subcontext) /* Scalar case */ ArrayBuildState *scalarstate; - /* Let's just check that we have a type that can be put into arrays */ - Assert(OidIsValid(get_array_type(input_type))); - scalarstate = initArrayResult(input_type, rcontext, subcontext); astate = (ArrayBuildStateAny *) MemoryContextAlloc(scalarstate->mcontext, @@ -6425,7 +6439,7 @@ array_replace_internal(ArrayType *array, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -6711,7 +6725,7 @@ width_bucket_array(PG_FUNCTION_ARGS) (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a comparison function for type %s", format_type_be(element_type)))); - fcinfo->flinfo->fn_extra = (void *) typentry; + fcinfo->flinfo->fn_extra = typentry; } /* diff --git a/src/backend/utils/adt/arraysubs.c b/src/backend/utils/adt/arraysubs.c index 6f68dfa5b23f9..2940fb8e8d737 100644 --- a/src/backend/utils/adt/arraysubs.c +++ b/src/backend/utils/adt/arraysubs.c @@ -3,7 +3,7 @@ * arraysubs.c * Subscripting support functions for arrays. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -18,6 +18,7 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "nodes/subscripting.h" +#include "nodes/supportnodes.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "utils/array.h" @@ -575,3 +576,36 @@ raw_array_subscript_handler(PG_FUNCTION_ARGS) PG_RETURN_POINTER(&sbsroutines); } + +/* + * array_subscript_handler_support() + * + * Planner support function for array_subscript_handler() + */ +Datum +array_subscript_handler_support(PG_FUNCTION_ARGS) +{ + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestModifyInPlace)) + { + /* + * We can optimize in-place subscripted assignment if the refexpr is + * the array being assigned to. We don't need to worry about array + * references within the refassgnexpr or the subscripts; however, if + * there's no refassgnexpr then it's a fetch which there's no need to + * optimize. + */ + SupportRequestModifyInPlace *req = (SupportRequestModifyInPlace *) rawreq; + Param *refexpr = (Param *) linitial(req->args); + + if (refexpr && IsA(refexpr, Param) && + refexpr->paramkind == PARAM_EXTERN && + refexpr->paramid == req->paramid && + lsecond(req->args) != NULL) + ret = (Node *) refexpr; + } + + PG_RETURN_POINTER(ret); +} diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c index 8c3a637cdb788..650bb51d4cdb3 100644 --- a/src/backend/utils/adt/arrayutils.c +++ b/src/backend/utils/adt/arrayutils.c @@ -3,7 +3,7 @@ * arrayutils.c * This file contains some support routines required for array functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/ascii.c b/src/backend/utils/adt/ascii.c index 40887e3699245..e3654dc7f3f22 100644 --- a/src/backend/utils/adt/ascii.c +++ b/src/backend/utils/adt/ascii.c @@ -2,7 +2,7 @@ * ascii.c * The PostgreSQL routine for string to ascii conversion. * - * Portions Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1999-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/ascii.c diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c index 85e6786563e79..474653797b55b 100644 --- a/src/backend/utils/adt/bool.c +++ b/src/backend/utils/adt/bool.c @@ -3,7 +3,7 @@ * bool.c * Functions for the built-in type "bool". * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -17,6 +17,7 @@ #include +#include "common/hashfn.h" #include "libpq/pqformat.h" #include "utils/builtins.h" @@ -273,6 +274,18 @@ boolge(PG_FUNCTION_ARGS) PG_RETURN_BOOL(arg1 >= arg2); } +Datum +hashbool(PG_FUNCTION_ARGS) +{ + return hash_uint32((int32) PG_GETARG_BOOL(0)); +} + +Datum +hashboolextended(PG_FUNCTION_ARGS) +{ + return hash_uint32_extended((int32) PG_GETARG_BOOL(0), PG_GETARG_INT64(1)); +} + /* * boolean-and and boolean-or aggregates. */ diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index b20c358486dc2..611d23f3cb0d8 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -35,10 +35,9 @@ * Private routines ************************************************************************/ -static const char * -num_word(Cash value) +static void +append_num_word(StringInfo buf, Cash value) { - static char buf[128]; static const char *const small[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", @@ -50,13 +49,16 @@ num_word(Cash value) /* deal with the simple cases first */ if (value <= 20) - return small[value]; + { + appendStringInfoString(buf, small[value]); + return; + } /* is it an even multiple of 100? */ if (!tu) { - sprintf(buf, "%s hundred", small[value / 100]); - return buf; + appendStringInfo(buf, "%s hundred", small[value / 100]); + return; } /* more than 99? */ @@ -64,28 +66,26 @@ num_word(Cash value) { /* is it an even multiple of 10 other than 10? */ if (value % 10 == 0 && tu > 10) - sprintf(buf, "%s hundred %s", - small[value / 100], big[tu / 10]); + appendStringInfo(buf, "%s hundred %s", + small[value / 100], big[tu / 10]); else if (tu < 20) - sprintf(buf, "%s hundred and %s", - small[value / 100], small[tu]); + appendStringInfo(buf, "%s hundred and %s", + small[value / 100], small[tu]); else - sprintf(buf, "%s hundred %s %s", - small[value / 100], big[tu / 10], small[tu % 10]); + appendStringInfo(buf, "%s hundred %s %s", + small[value / 100], big[tu / 10], small[tu % 10]); } else { /* is it an even multiple of 10 other than 10? */ if (value % 10 == 0 && tu > 10) - sprintf(buf, "%s", big[tu / 10]); + appendStringInfoString(buf, big[tu / 10]); else if (tu < 20) - sprintf(buf, "%s", small[tu]); + appendStringInfoString(buf, small[tu]); else - sprintf(buf, "%s %s", big[tu / 10], small[tu % 10]); + appendStringInfo(buf, "%s %s", big[tu / 10], small[tu % 10]); } - - return buf; -} /* num_word() */ +} static inline Cash cash_pl_cash(Cash c1, Cash c2) @@ -387,6 +387,7 @@ Datum cash_out(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); + uint64 uvalue; char *result; char buf[128]; char *bufptr; @@ -429,8 +430,6 @@ cash_out(PG_FUNCTION_ARGS) if (value < 0) { - /* make the amount positive for digit-reconstruction loop */ - value = -value; /* set up formatting data */ signsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-"; sign_posn = lconvert->n_sign_posn; @@ -445,6 +444,9 @@ cash_out(PG_FUNCTION_ARGS) sep_by_space = lconvert->p_sep_by_space; } + /* make the amount positive for digit-reconstruction loop */ + uvalue = pg_abs_s64(value); + /* we build the digits+decimal-point+sep string right-to-left in buf[] */ bufptr = buf + sizeof(buf) - 1; *bufptr = '\0'; @@ -470,10 +472,10 @@ cash_out(PG_FUNCTION_ARGS) memcpy(bufptr, ssymbol, strlen(ssymbol)); } - *(--bufptr) = ((uint64) value % 10) + '0'; - value = ((uint64) value) / 10; + *(--bufptr) = (uvalue % 10) + '0'; + uvalue = uvalue / 10; digit_pos--; - } while (value || digit_pos >= 0); + } while (uvalue || digit_pos >= 0); /*---------- * Now, attach currency symbol and sign symbol in the correct order. @@ -960,8 +962,9 @@ cash_words(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); uint64 val; - char buf[256]; - char *p = buf; + StringInfoData buf; + text *res; + Cash dollars; Cash m0; Cash m1; Cash m2; @@ -970,19 +973,19 @@ cash_words(PG_FUNCTION_ARGS) Cash m5; Cash m6; + initStringInfo(&buf); + /* work with positive numbers */ if (value < 0) { value = -value; - strcpy(buf, "minus "); - p += 6; + appendStringInfoString(&buf, "minus "); } - else - buf[0] = '\0'; /* Now treat as unsigned, to avoid trouble at INT_MIN */ val = (uint64) value; + dollars = val / INT64CONST(100); m0 = val % INT64CONST(100); /* cents */ m1 = (val / INT64CONST(100)) % 1000; /* hundreds */ m2 = (val / INT64CONST(100000)) % 1000; /* thousands */ @@ -993,49 +996,51 @@ cash_words(PG_FUNCTION_ARGS) if (m6) { - strcat(buf, num_word(m6)); - strcat(buf, " quadrillion "); + append_num_word(&buf, m6); + appendStringInfoString(&buf, " quadrillion "); } if (m5) { - strcat(buf, num_word(m5)); - strcat(buf, " trillion "); + append_num_word(&buf, m5); + appendStringInfoString(&buf, " trillion "); } if (m4) { - strcat(buf, num_word(m4)); - strcat(buf, " billion "); + append_num_word(&buf, m4); + appendStringInfoString(&buf, " billion "); } if (m3) { - strcat(buf, num_word(m3)); - strcat(buf, " million "); + append_num_word(&buf, m3); + appendStringInfoString(&buf, " million "); } if (m2) { - strcat(buf, num_word(m2)); - strcat(buf, " thousand "); + append_num_word(&buf, m2); + appendStringInfoString(&buf, " thousand "); } if (m1) - strcat(buf, num_word(m1)); + append_num_word(&buf, m1); - if (!*p) - strcat(buf, "zero"); + if (dollars == 0) + appendStringInfoString(&buf, "zero"); - strcat(buf, (val / 100) == 1 ? " dollar and " : " dollars and "); - strcat(buf, num_word(m0)); - strcat(buf, m0 == 1 ? " cent" : " cents"); + appendStringInfoString(&buf, dollars == 1 ? " dollar and " : " dollars and "); + append_num_word(&buf, m0); + appendStringInfoString(&buf, m0 == 1 ? " cent" : " cents"); /* capitalize output */ - buf[0] = pg_toupper((unsigned char) buf[0]); + buf.data[0] = pg_toupper((unsigned char) buf.data[0]); /* return as text datum */ - PG_RETURN_TEXT_P(cstring_to_text(buf)); + res = cstring_to_text_with_len(buf.data, buf.len); + pfree(buf.data); + PG_RETURN_TEXT_P(res); } diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c index 5ee94be0d1e96..22dbfc950b1fd 100644 --- a/src/backend/utils/adt/char.c +++ b/src/backend/utils/adt/char.c @@ -4,7 +4,7 @@ * Functions for the built-in type "char" (not to be confused with * bpchar, which is the SQL CHAR(n) type). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/cryptohashfuncs.c b/src/backend/utils/adt/cryptohashfuncs.c index cc8bc96ad6fc3..1cc7ddae3b56b 100644 --- a/src/backend/utils/adt/cryptohashfuncs.c +++ b/src/backend/utils/adt/cryptohashfuncs.c @@ -3,7 +3,7 @@ * cryptohashfuncs.c * Cryptographic hash functions * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 9c854e0e5c35a..4227ab1a72bfb 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -3,7 +3,7 @@ * date.c * implements DATE and TIME data types specified in SQL standard * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * @@ -34,6 +34,7 @@ #include "utils/date.h" #include "utils/datetime.h" #include "utils/numeric.h" +#include "utils/skipsupport.h" #include "utils/sortsupport.h" /* @@ -256,8 +257,15 @@ make_date(PG_FUNCTION_ARGS) /* Handle negative years as BC */ if (tm.tm_year < 0) { + int year = tm.tm_year; + bc = true; - tm.tm_year = -tm.tm_year; + if (pg_neg_s32_overflow(year, &year)) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW), + errmsg("date field value out of range: %d-%02d-%02d", + tm.tm_year, tm.tm_mon, tm.tm_mday))); + tm.tm_year = year; } dterr = ValidateDate(DTK_DATE_M, false, false, bc, &tm); @@ -455,6 +463,63 @@ date_sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +static Datum +date_decrement(Relation rel, Datum existing, bool *underflow) +{ + DateADT dexisting = DatumGetDateADT(existing); + + if (dexisting == DATEVAL_NOBEGIN) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return DateADTGetDatum(dexisting - 1); +} + +static Datum +date_increment(Relation rel, Datum existing, bool *overflow) +{ + DateADT dexisting = DatumGetDateADT(existing); + + if (dexisting == DATEVAL_NOEND) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return DateADTGetDatum(dexisting + 1); +} + +Datum +date_skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = date_decrement; + sksup->increment = date_increment; + sksup->low_elem = DateADTGetDatum(DATEVAL_NOBEGIN); + sksup->high_elem = DateADTGetDatum(DATEVAL_NOEND); + + PG_RETURN_VOID(); +} + +Datum +hashdate(PG_FUNCTION_ARGS) +{ + return hash_uint32(PG_GETARG_DATEADT(0)); +} + +Datum +hashdateextended(PG_FUNCTION_ARGS) +{ + return hash_uint32_extended(PG_GETARG_DATEADT(0), PG_GETARG_INT64(1)); +} + Datum date_finite(PG_FUNCTION_ARGS) { diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 7abdc62f41df7..680fee2a8447e 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -3,7 +3,7 @@ * datetime.c * Support functions for date/time types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -259,7 +259,17 @@ static const datetkn *datecache[MAXDATEFIELDS] = {NULL}; static const datetkn *deltacache[MAXDATEFIELDS] = {NULL}; -static const datetkn *abbrevcache[MAXDATEFIELDS] = {NULL}; +/* Cache for results of timezone abbreviation lookups */ + +typedef struct TzAbbrevCache +{ + char abbrev[TOKMAXLEN + 1]; /* always NUL-terminated */ + char ftype; /* TZ, DTZ, or DYNTZ */ + int offset; /* GMT offset, if fixed-offset */ + pg_tz *tz; /* relevant zone, if variable-offset */ +} TzAbbrevCache; + +static TzAbbrevCache tzabbrevcache[MAXDATEFIELDS]; /* @@ -692,9 +702,18 @@ ParseFraction(char *cp, double *frac) } else { + /* + * On the other hand, let's reject anything that's not digits after + * the ".". strtod is happy with input like ".123e9", but that'd + * break callers' expectation that the result is in 0..1. (It's quite + * difficult to get here with such input, but not impossible.) + */ + if (strspn(cp + 1, "0123456789") != strlen(cp + 1)) + return DTERR_BAD_FORMAT; + errno = 0; *frac = strtod(cp, &cp); - /* check for parse failure */ + /* check for parse failure (probably redundant given prior check) */ if (*cp != '\0' || errno != 0) return DTERR_BAD_FORMAT; } @@ -1845,6 +1864,40 @@ DetermineTimeZoneAbbrevOffsetInternal(pg_time_t t, const char *abbr, pg_tz *tzp, } +/* TimeZoneAbbrevIsKnown() + * + * Detect whether the given string is a time zone abbreviation that's known + * in the specified TZDB timezone, and if so whether it's fixed or varying + * meaning. The match is not case-sensitive. + */ +static bool +TimeZoneAbbrevIsKnown(const char *abbr, pg_tz *tzp, + bool *isfixed, int *offset, int *isdst) +{ + char upabbr[TZ_STRLEN_MAX + 1]; + unsigned char *p; + long int gmtoff; + + /* We need to force the abbrev to upper case */ + strlcpy(upabbr, abbr, sizeof(upabbr)); + for (p = (unsigned char *) upabbr; *p; p++) + *p = pg_toupper(*p); + + /* Look up the abbrev's meaning in this zone */ + if (pg_timezone_abbrev_is_known(upabbr, + isfixed, + &gmtoff, + isdst, + tzp)) + { + /* Change sign to agree with DetermineTimeZoneOffset() */ + *offset = (int) -gmtoff; + return true; + } + return false; +} + + /* DecodeTimeOnly() * Interpret parsed string as time fields only. * Returns 0 if successful, DTERR code if bogus input detected. @@ -2914,31 +2967,28 @@ DecodeNumberField(int len, char *str, int fmask, { char *cp; + /* + * This function was originally meant to cope only with DTK_NUMBER fields, + * but we now sometimes abuse it to parse (parts of) DTK_DATE fields, + * which can contain letters and other punctuation. Reject if it's not a + * valid DTK_NUMBER, that is digits and decimal point(s). (ParseFraction + * will reject if there's more than one decimal point.) + */ + if (strspn(str, "0123456789.") != len) + return DTERR_BAD_FORMAT; + /* * Have a decimal point? Then this is a date or something with a seconds * field... */ if ((cp = strchr(str, '.')) != NULL) { - /* - * Can we use ParseFractionalSecond here? Not clear whether trailing - * junk should be rejected ... - */ - if (cp[1] == '\0') - { - /* avoid assuming that strtod will accept "." */ - *fsec = 0; - } - else - { - double frac; + int dterr; - errno = 0; - frac = strtod(cp, NULL); - if (errno != 0) - return DTERR_BAD_FORMAT; - *fsec = rint(frac * 1000000); - } + /* Convert the fraction and store at *fsec */ + dterr = ParseFractionalSecond(cp, fsec); + if (dterr) + return dterr; /* Now truncate off the fraction for further processing */ *cp = '\0'; len = strlen(str); @@ -3092,27 +3142,60 @@ DecodeTimezoneAbbrev(int field, const char *lowtoken, int *ftype, int *offset, pg_tz **tz, DateTimeErrorExtra *extra) { + TzAbbrevCache *tzc = &tzabbrevcache[field]; + bool isfixed; + int isdst; const datetkn *tp; - tp = abbrevcache[field]; - /* use strncmp so that we match truncated tokens */ - if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0) + /* + * Do we have a cached result? Use strncmp so that we match truncated + * names, although we shouldn't really see that happen with normal + * abbreviations. + */ + if (strncmp(lowtoken, tzc->abbrev, TOKMAXLEN) == 0) { - if (zoneabbrevtbl) - tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs, - zoneabbrevtbl->numabbrevs); - else - tp = NULL; + *ftype = tzc->ftype; + *offset = tzc->offset; + *tz = tzc->tz; + return 0; } + + /* + * See if the current session_timezone recognizes it. Checking this + * before zoneabbrevtbl allows us to correctly handle abbreviations whose + * meaning varies across zones, such as "LMT". + */ + if (session_timezone && + TimeZoneAbbrevIsKnown(lowtoken, session_timezone, + &isfixed, offset, &isdst)) + { + *ftype = (isfixed ? (isdst ? DTZ : TZ) : DYNTZ); + *tz = (isfixed ? NULL : session_timezone); + /* flip sign to agree with the convention used in zoneabbrevtbl */ + *offset = -(*offset); + /* cache result; use strlcpy to truncate name if necessary */ + strlcpy(tzc->abbrev, lowtoken, TOKMAXLEN + 1); + tzc->ftype = *ftype; + tzc->offset = *offset; + tzc->tz = *tz; + return 0; + } + + /* Nope, so look in zoneabbrevtbl */ + if (zoneabbrevtbl) + tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs, + zoneabbrevtbl->numabbrevs); + else + tp = NULL; if (tp == NULL) { *ftype = UNKNOWN_FIELD; *offset = 0; *tz = NULL; + /* failure results are not cached */ } else { - abbrevcache[field] = tp; *ftype = tp->type; if (tp->type == DYNTZ) { @@ -3126,11 +3209,26 @@ DecodeTimezoneAbbrev(int field, const char *lowtoken, *offset = tp->value; *tz = NULL; } + + /* cache result; use strlcpy to truncate name if necessary */ + strlcpy(tzc->abbrev, lowtoken, TOKMAXLEN + 1); + tzc->ftype = *ftype; + tzc->offset = *offset; + tzc->tz = *tz; } return 0; } +/* + * Reset tzabbrevcache after a change in session_timezone. + */ +void +ClearTimeZoneAbbrevCache(void) +{ + memset(tzabbrevcache, 0, sizeof(tzabbrevcache)); +} + /* DecodeSpecial() * Decode text string using lookup table. @@ -3278,9 +3376,6 @@ DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz) *offset = 0; /* avoid uninitialized vars on failure */ *tz = NULL; - if (!zoneabbrevtbl) - return -1; /* no abbrevs known, so fail immediately */ - /* Downcase as much of the string as we could need */ for (len = 0; len < TOKMAXLEN; len++) { @@ -3299,9 +3394,34 @@ DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz) */ while (len > 0) { - const datetkn *tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs, - zoneabbrevtbl->numabbrevs); + bool isfixed; + int isdst; + const datetkn *tp; + + /* See if the current session_timezone recognizes it. */ + if (session_timezone && + TimeZoneAbbrevIsKnown(lowtoken, session_timezone, + &isfixed, offset, &isdst)) + { + if (isfixed) + { + /* flip sign to agree with the convention in zoneabbrevtbl */ + *offset = -(*offset); + } + else + { + /* Caller must resolve the abbrev's current meaning */ + *tz = session_timezone; + } + return len; + } + /* Known in zoneabbrevtbl? */ + if (zoneabbrevtbl) + tp = datebsearch(lowtoken, zoneabbrevtbl->abbrevs, + zoneabbrevtbl->numabbrevs); + else + tp = NULL; if (tp != NULL) { if (tp->type == DYNTZ) @@ -3324,6 +3444,8 @@ DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz) return len; } } + + /* Nope, try the next shorter string. */ lowtoken[--len] = '\0'; } @@ -4107,7 +4229,7 @@ DateTimeParseError(int dterr, DateTimeErrorExtra *extra, (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW), errmsg("date/time field value out of range: \"%s\"", str), - errhint("Perhaps you need a different \"datestyle\" setting."))); + errhint("Perhaps you need a different \"DateStyle\" setting."))); break; case DTERR_INTERVAL_OVERFLOW: errsave(escontext, @@ -4514,7 +4636,7 @@ AddISO8601IntPart(char *cp, int64 value, char units) { if (value == 0) return cp; - sprintf(cp, "%lld%c", (long long) value, units); + sprintf(cp, "%" PRId64 "%c", value, units); return cp + strlen(cp); } @@ -4525,10 +4647,10 @@ AddPostgresIntPart(char *cp, int64 value, const char *units, { if (value == 0) return cp; - sprintf(cp, "%s%s%lld %s%s", + sprintf(cp, "%s%s%" PRId64 " %s%s", (!*is_zero) ? " " : "", (*is_before && value > 0) ? "+" : "", - (long long) value, + value, units, (value != 1) ? "s" : ""); @@ -4556,7 +4678,7 @@ AddVerboseIntPart(char *cp, int64 value, const char *units, } else if (*is_before) value = -value; - sprintf(cp, " %lld %s%s", (long long) value, units, (value == 1) ? "" : "s"); + sprintf(cp, " %" PRId64 " %s%s", value, units, (value == 1) ? "" : "s"); *is_zero = false; return cp + strlen(cp); } @@ -4651,10 +4773,10 @@ EncodeInterval(struct pg_itm *itm, int style, char *str) char sec_sign = (hour < 0 || min < 0 || sec < 0 || fsec < 0) ? '-' : '+'; - sprintf(cp, "%c%d-%d %c%lld %c%lld:%02d:", + sprintf(cp, "%c%d-%d %c%" PRId64 " %c%" PRId64 ":%02d:", year_sign, abs(year), abs(mon), - day_sign, (long long) i64abs(mday), - sec_sign, (long long) i64abs(hour), abs(min)); + day_sign, i64abs(mday), + sec_sign, i64abs(hour), abs(min)); cp += strlen(cp); cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true); *cp = '\0'; @@ -4665,15 +4787,15 @@ EncodeInterval(struct pg_itm *itm, int style, char *str) } else if (has_day) { - sprintf(cp, "%lld %lld:%02d:", - (long long) mday, (long long) hour, min); + sprintf(cp, "%" PRId64 " %" PRId64 ":%02d:", + mday, hour, min); cp += strlen(cp); cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true); *cp = '\0'; } else { - sprintf(cp, "%lld:%02d:", (long long) hour, min); + sprintf(cp, "%" PRId64 ":%02d:", hour, min); cp += strlen(cp); cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true); *cp = '\0'; @@ -4723,10 +4845,10 @@ EncodeInterval(struct pg_itm *itm, int style, char *str) { bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0); - sprintf(cp, "%s%s%02lld:%02d:", + sprintf(cp, "%s%s%02" PRId64 ":%02d:", is_zero ? "" : " ", (minus ? "-" : (is_before ? "+" : "")), - (long long) i64abs(hour), abs(min)); + i64abs(hour), abs(min)); cp += strlen(cp); cp = AppendSeconds(cp, sec, fsec, MAX_INTERVAL_PRECISION, true); *cp = '\0'; @@ -4957,8 +5079,8 @@ void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl) { zoneabbrevtbl = tbl; - /* reset abbrevcache, which may contain pointers into old table */ - memset(abbrevcache, 0, sizeof(abbrevcache)); + /* reset tzabbrevcache, which may contain results from old table */ + memset(tzabbrevcache, 0, sizeof(tzabbrevcache)); } /* @@ -4994,11 +5116,99 @@ FetchDynamicTimeZone(TimeZoneAbbrevTable *tbl, const datetkn *tp, /* - * This set-returning function reads all the available time zone abbreviations + * This set-returning function reads all the time zone abbreviations + * defined by the IANA data for the current timezone setting, + * and returns a set of (abbrev, utc_offset, is_dst). + */ +Datum +pg_timezone_abbrevs_zone(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + int *pindex; + Datum result; + HeapTuple tuple; + Datum values[3]; + bool nulls[3] = {0}; + TimestampTz now = GetCurrentTransactionStartTimestamp(); + pg_time_t t = timestamptz_to_time_t(now); + const char *abbrev; + long int gmtoff; + int isdst; + struct pg_itm_in itm_in; + Interval *resInterval; + + /* stuff done only on the first call of the function */ + if (SRF_IS_FIRSTCALL()) + { + TupleDesc tupdesc; + MemoryContext oldcontext; + + /* create a function context for cross-call persistence */ + funcctx = SRF_FIRSTCALL_INIT(); + + /* + * switch to memory context appropriate for multiple function calls + */ + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /* allocate memory for user context */ + pindex = (int *) palloc(sizeof(int)); + *pindex = 0; + funcctx->user_fctx = pindex; + + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; + + MemoryContextSwitchTo(oldcontext); + } + + /* stuff done on every call of the function */ + funcctx = SRF_PERCALL_SETUP(); + pindex = (int *) funcctx->user_fctx; + + while ((abbrev = pg_get_next_timezone_abbrev(pindex, + session_timezone)) != NULL) + { + /* Ignore abbreviations that aren't all-alphabetic */ + if (strspn(abbrev, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != strlen(abbrev)) + continue; + + /* Determine the current meaning of the abbrev */ + if (!pg_interpret_timezone_abbrev(abbrev, + &t, + &gmtoff, + &isdst, + session_timezone)) + continue; /* hm, not actually used in this zone? */ + + values[0] = CStringGetTextDatum(abbrev); + + /* Convert offset (in seconds) to an interval; can't overflow */ + MemSet(&itm_in, 0, sizeof(struct pg_itm_in)); + itm_in.tm_usec = (int64) gmtoff * USECS_PER_SEC; + resInterval = (Interval *) palloc(sizeof(Interval)); + (void) itmin2interval(&itm_in, resInterval); + values[1] = IntervalPGetDatum(resInterval); + + values[2] = BoolGetDatum(isdst); + + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + result = HeapTupleGetDatum(tuple); + + SRF_RETURN_NEXT(funcctx, result); + } + + SRF_RETURN_DONE(funcctx); +} + +/* + * This set-returning function reads all the time zone abbreviations + * defined by the timezone_abbreviations setting, * and returns a set of (abbrev, utc_offset, is_dst). */ Datum -pg_timezone_abbrevs(PG_FUNCTION_ARGS) +pg_timezone_abbrevs_abbrevs(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int *pindex; @@ -5031,7 +5241,7 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS) /* allocate memory for user context */ pindex = (int *) palloc(sizeof(int)); *pindex = 0; - funcctx->user_fctx = (void *) pindex; + funcctx->user_fctx = pindex; if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c index 45b854a0ae737..fcd5b1653dd3e 100644 --- a/src/backend/utils/adt/datum.c +++ b/src/backend/utils/adt/datum.c @@ -3,7 +3,7 @@ * datum.c * POSTGRES Datum (abstract data type) manipulation routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -149,7 +149,7 @@ datumCopy(Datum value, bool typByVal, int typLen) resultsize = EOH_get_flat_size(eoh); resultptr = (char *) palloc(resultsize); - EOH_flatten_into(eoh, (void *) resultptr, resultsize); + EOH_flatten_into(eoh, resultptr, resultsize); res = PointerGetDatum(resultptr); } else @@ -495,7 +495,7 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen, * so we can't store directly to *start_address. */ tmp = (char *) palloc(header); - EOH_flatten_into(eoh, (void *) tmp, header); + EOH_flatten_into(eoh, tmp, header); memcpy(*start_address, tmp, header); *start_address += header; diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 25d7110c130a8..25865b660ef83 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -2,7 +2,7 @@ * dbsize.c * Database object size functions, and related inquiries * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/dbsize.c @@ -143,7 +143,7 @@ calculate_database_size(Oid dbOid) totalsize = db_dir_size(pathname); /* Scan the non-default tablespaces */ - snprintf(dirpath, MAXPGPATH, "pg_tblspc"); + snprintf(dirpath, MAXPGPATH, PG_TBLSPC_DIR); dirdesc = AllocateDir(dirpath); while ((direntry = ReadDir(dirdesc, dirpath)) != NULL) @@ -154,8 +154,8 @@ calculate_database_size(Oid dbOid) strcmp(direntry->d_name, "..") == 0) continue; - snprintf(pathname, sizeof(pathname), "pg_tblspc/%s/%s/%u", - direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid); + snprintf(pathname, sizeof(pathname), "%s/%s/%s/%u", + PG_TBLSPC_DIR, direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid); totalsize += db_dir_size(pathname); } @@ -170,6 +170,15 @@ pg_database_size_oid(PG_FUNCTION_ARGS) Oid dbOid = PG_GETARG_OID(0); int64 size; + /* + * Not needed for correctness, but avoid non-user-facing error message + * later if the database doesn't exist. + */ + if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(dbOid))) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("database with OID %u does not exist", dbOid)); + size = calculate_database_size(dbOid); if (size == 0) @@ -227,7 +236,7 @@ calculate_tablespace_size(Oid tblspcOid) else if (tblspcOid == GLOBALTABLESPACE_OID) snprintf(tblspcPath, MAXPGPATH, "global"); else - snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u/%s", tblspcOid, + snprintf(tblspcPath, MAXPGPATH, "%s/%u/%s", PG_TBLSPC_DIR, tblspcOid, TABLESPACE_VERSION_DIRECTORY); dirdesc = AllocateDir(tblspcPath); @@ -274,6 +283,15 @@ pg_tablespace_size_oid(PG_FUNCTION_ARGS) Oid tblspcOid = PG_GETARG_OID(0); int64 size; + /* + * Not needed for correctness, but avoid non-user-facing error message + * later if the tablespace doesn't exist. + */ + if (!SearchSysCacheExists1(TABLESPACEOID, ObjectIdGetDatum(tblspcOid))) + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tablespace with OID %u does not exist", tblspcOid)); + size = calculate_tablespace_size(tblspcOid); if (size < 0) @@ -308,7 +326,7 @@ static int64 calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum) { int64 totalsize = 0; - char *relationpath; + RelPathStr relationpath; char pathname[MAXPGPATH]; unsigned int segcount = 0; @@ -322,10 +340,10 @@ calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber fork if (segcount == 0) snprintf(pathname, MAXPGPATH, "%s", - relationpath); + relationpath.str); else snprintf(pathname, MAXPGPATH, "%s.%u", - relationpath, segcount); + relationpath.str, segcount); if (stat(pathname, &fst) < 0) { @@ -575,9 +593,13 @@ pg_size_pretty(PG_FUNCTION_ARGS) for (unit = size_pretty_units; unit->name != NULL; unit++) { uint8 bits; + uint64 abs_size = size < 0 ? 0 - (uint64) size : (uint64) size; - /* use this unit if there are no more units or we're below the limit */ - if (unit[1].name == NULL || i64abs(size) < unit->limit) + /* + * Use this unit if there are no more units or the absolute size is + * below the limit for the current unit. + */ + if (unit[1].name == NULL || abs_size < unit->limit) { if (unit->round) size = half_rounded(size); @@ -951,7 +973,7 @@ pg_relation_filepath(PG_FUNCTION_ARGS) Form_pg_class relform; RelFileLocator rlocator; ProcNumber backend; - char *path; + RelPathStr path; tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) @@ -1017,5 +1039,5 @@ pg_relation_filepath(PG_FUNCTION_ARGS) path = relpathbackend(rlocator, backend, MAIN_FORKNUM); - PG_RETURN_TEXT_P(cstring_to_text(path)); + PG_RETURN_TEXT_P(cstring_to_text(path.str)); } diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c index 21791105da877..e755b70e17ec9 100644 --- a/src/backend/utils/adt/domains.c +++ b/src/backend/utils/adt/domains.c @@ -19,7 +19,7 @@ * to evaluate them in. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -255,7 +255,7 @@ domain_in(PG_FUNCTION_ARGS) { my_extra = domain_state_setup(domainType, false, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) my_extra; + fcinfo->flinfo->fn_extra = my_extra; } /* @@ -314,7 +314,7 @@ domain_recv(PG_FUNCTION_ARGS) { my_extra = domain_state_setup(domainType, true, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) my_extra; + fcinfo->flinfo->fn_extra = my_extra; } /* @@ -388,7 +388,7 @@ domain_check_internal(Datum value, bool isnull, Oid domainType, { my_extra = domain_state_setup(domainType, true, mcxt); if (extra) - *extra = (void *) my_extra; + *extra = my_extra; } /* diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c index d1a6358b951c7..4ccaed815d17e 100644 --- a/src/backend/utils/adt/encode.c +++ b/src/backend/utils/adt/encode.c @@ -3,7 +3,7 @@ * encode.c * Various data encoding/decoding things. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -145,7 +145,26 @@ binary_decode(PG_FUNCTION_ARGS) * HEX */ -static const char hextbl[] = "0123456789abcdef"; +/* + * The hex expansion of each possible byte value (two chars per value). + */ +static const char hextbl[512] = +"000102030405060708090a0b0c0d0e0f" +"101112131415161718191a1b1c1d1e1f" +"202122232425262728292a2b2c2d2e2f" +"303132333435363738393a3b3c3d3e3f" +"404142434445464748494a4b4c4d4e4f" +"505152535455565758595a5b5c5d5e5f" +"606162636465666768696a6b6c6d6e6f" +"707172737475767778797a7b7c7d7e7f" +"808182838485868788898a8b8c8d8e8f" +"909192939495969798999a9b9c9d9e9f" +"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" +"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" +"e0e1e2e3e4e5e6e7e8e9eaebecedeeef" +"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; static const int8 hexlookup[128] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -165,9 +184,11 @@ hex_encode(const char *src, size_t len, char *dst) while (src < end) { - *dst++ = hextbl[(*src >> 4) & 0xF]; - *dst++ = hextbl[*src & 0xF]; + unsigned char usrc = *((const unsigned char *) src); + + memcpy(dst, &hextbl[2 * usrc], 2); src++; + dst += 2; } return (uint64) len * 2; } diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c index 814c7fb4e3e21..fcc6981632bac 100644 --- a/src/backend/utils/adt/enum.c +++ b/src/backend/utils/adt/enum.c @@ -3,7 +3,7 @@ * enum.c * I/O functions, operators, aggregates etc for enum types * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -295,7 +295,7 @@ enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo) ReleaseSysCache(enum_tup); /* Now locate and remember the typcache entry */ tcache = lookup_type_cache(typeoid, 0); - fcinfo->flinfo->fn_extra = (void *) tcache; + fcinfo->flinfo->fn_extra = tcache; } /* The remaining comparison logic is in typcache.c */ diff --git a/src/backend/utils/adt/expandeddatum.c b/src/backend/utils/adt/expandeddatum.c index 2cf7e001094a8..6b4b8eaf005ce 100644 --- a/src/backend/utils/adt/expandeddatum.c +++ b/src/backend/utils/adt/expandeddatum.c @@ -3,7 +3,7 @@ * expandeddatum.c * Support functions for "expanded" value representations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/expandedrecord.c b/src/backend/utils/adt/expandedrecord.c index 7e85ae3825eea..13752db44e839 100644 --- a/src/backend/utils/adt/expandedrecord.c +++ b/src/backend/utils/adt/expandedrecord.c @@ -7,7 +7,7 @@ * store values of named composite types, domains over named composite types, * and record types (registered or anonymous). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -161,7 +161,7 @@ make_expanded_record_from_typeid(Oid type_id, int32 typmod, { /* Register callback to release the refcount */ erh->er_mcb.func = ER_mc_callback; - erh->er_mcb.arg = (void *) erh; + erh->er_mcb.arg = erh; MemoryContextRegisterResetCallback(erh->hdr.eoh_context, &erh->er_mcb); @@ -289,7 +289,7 @@ make_expanded_record_from_tupdesc(TupleDesc tupdesc, { /* Register callback to release the refcount */ erh->er_mcb.func = ER_mc_callback; - erh->er_mcb.arg = (void *) erh; + erh->er_mcb.arg = erh; MemoryContextRegisterResetCallback(erh->hdr.eoh_context, &erh->er_mcb); @@ -385,7 +385,7 @@ make_expanded_record_from_exprecord(ExpandedRecordHeader *olderh, { /* Register callback to release the refcount */ erh->er_mcb.func = ER_mc_callback; - erh->er_mcb.arg = (void *) erh; + erh->er_mcb.arg = erh; MemoryContextRegisterResetCallback(erh->hdr.eoh_context, &erh->er_mcb); @@ -699,7 +699,7 @@ ER_get_flat_size(ExpandedObjectHeader *eohptr) { for (i = 0; i < erh->nfields; i++) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, i); if (!erh->dnulls[i] && !attr->attbyval && attr->attlen == -1 && @@ -844,7 +844,7 @@ expanded_record_fetch_tupdesc(ExpandedRecordHeader *erh) if (erh->er_mcb.arg == NULL) { erh->er_mcb.func = ER_mc_callback; - erh->er_mcb.arg = (void *) erh; + erh->er_mcb.arg = erh; MemoryContextRegisterResetCallback(erh->hdr.eoh_context, &erh->er_mcb); } @@ -1115,7 +1115,7 @@ expanded_record_set_field_internal(ExpandedRecordHeader *erh, int fnumber, bool check_constraints) { TupleDesc tupdesc; - Form_pg_attribute attr; + CompactAttribute *attr; Datum *dvalues; bool *dnulls; char *oldValue; @@ -1146,7 +1146,7 @@ expanded_record_set_field_internal(ExpandedRecordHeader *erh, int fnumber, * Copy new field value into record's context, and deal with detoasting, * if needed. */ - attr = TupleDescAttr(tupdesc, fnumber - 1); + attr = TupleDescCompactAttr(tupdesc, fnumber - 1); if (!isnull && !attr->attbyval) { MemoryContext oldcxt; @@ -1279,7 +1279,7 @@ expanded_record_set_fields(ExpandedRecordHeader *erh, for (fnumber = 0; fnumber < erh->nfields; fnumber++) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, fnumber); + CompactAttribute *attr = TupleDescCompactAttr(tupdesc, fnumber); Datum newValue; bool isnull; @@ -1541,7 +1541,7 @@ check_domain_for_new_field(ExpandedRecordHeader *erh, int fnumber, */ if (!isnull) { - Form_pg_attribute attr = TupleDescAttr(erh->er_tupdesc, fnumber - 1); + CompactAttribute *attr = TupleDescCompactAttr(erh->er_tupdesc, fnumber - 1); if (!attr->attbyval && attr->attlen == -1 && VARATT_IS_EXTERNAL(DatumGetPointer(newValue))) diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index f709c21e1fe36..6d20ae07ae7b0 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -3,7 +3,7 @@ * float.c * Functions for the built-in floating-point types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -27,7 +27,6 @@ #include "utils/float.h" #include "utils/fmgrprotos.h" #include "utils/sortsupport.h" -#include "utils/timestamp.h" /* @@ -2787,6 +2786,94 @@ derfc(PG_FUNCTION_ARGS) } +/* ========== GAMMA FUNCTIONS ========== */ + + +/* + * dgamma - returns the gamma function of arg1 + */ +Datum +dgamma(PG_FUNCTION_ARGS) +{ + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 result; + + /* + * Handle NaN and Inf cases explicitly. This simplifies the overflow + * checks on platforms that do not set errno. + */ + if (isnan(arg1)) + result = arg1; + else if (isinf(arg1)) + { + /* Per POSIX, an input of -Inf causes a domain error */ + if (arg1 < 0) + { + float_overflow_error(); + result = get_float8_nan(); /* keep compiler quiet */ + } + else + result = arg1; + } + else + { + /* + * Note: the POSIX/C99 gamma function is called "tgamma", not "gamma". + * + * On some platforms, tgamma() will not set errno but just return Inf, + * NaN, or zero to report overflow/underflow; therefore, test those + * cases explicitly (note that, like the exponential function, the + * gamma function has no zeros). + */ + errno = 0; + result = tgamma(arg1); + + if (errno != 0 || isinf(result) || isnan(result)) + { + if (result != 0.0) + float_overflow_error(); + else + float_underflow_error(); + } + else if (result == 0.0) + float_underflow_error(); + } + + PG_RETURN_FLOAT8(result); +} + + +/* + * dlgamma - natural logarithm of absolute value of gamma of arg1 + */ +Datum +dlgamma(PG_FUNCTION_ARGS) +{ + float8 arg1 = PG_GETARG_FLOAT8(0); + float8 result; + + /* + * Note: lgamma may not be thread-safe because it may write to a global + * variable signgam, which may not be thread-local. However, this doesn't + * matter to us, since we don't use signgam. + */ + errno = 0; + result = lgamma(arg1); + + /* + * If an ERANGE error occurs, it means there was an overflow or a pole + * error (which happens for zero and negative integer inputs). + * + * On some platforms, lgamma() will not set errno but just return infinity + * to report overflow, but it should never underflow. + */ + if (errno == ERANGE || (isinf(result) && !isinf(arg1))) + float_overflow_error(); + + PG_RETURN_FLOAT8(result); +} + + /* * ========================= @@ -2946,9 +3033,7 @@ float8_combine(PG_FUNCTION_ARGS) transdatums[1] = Float8GetDatumFast(Sx); transdatums[2] = Float8GetDatumFast(Sxx); - result = construct_array(transdatums, 3, - FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); + result = construct_array_builtin(transdatums, 3, FLOAT8OID); PG_RETURN_ARRAYTYPE_P(result); } @@ -3029,9 +3114,7 @@ float8_accum(PG_FUNCTION_ARGS) transdatums[1] = Float8GetDatumFast(Sx); transdatums[2] = Float8GetDatumFast(Sxx); - result = construct_array(transdatums, 3, - FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); + result = construct_array_builtin(transdatums, 3, FLOAT8OID); PG_RETURN_ARRAYTYPE_P(result); } @@ -3114,9 +3197,7 @@ float4_accum(PG_FUNCTION_ARGS) transdatums[1] = Float8GetDatumFast(Sx); transdatums[2] = Float8GetDatumFast(Sxx); - result = construct_array(transdatums, 3, - FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); + result = construct_array_builtin(transdatums, 3, FLOAT8OID); PG_RETURN_ARRAYTYPE_P(result); } @@ -3359,9 +3440,7 @@ float8_regr_accum(PG_FUNCTION_ARGS) transdatums[4] = Float8GetDatumFast(Syy); transdatums[5] = Float8GetDatumFast(Sxy); - result = construct_array(transdatums, 6, - FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); + result = construct_array_builtin(transdatums, 6, FLOAT8OID); PG_RETURN_ARRAYTYPE_P(result); } @@ -3500,9 +3579,7 @@ float8_regr_combine(PG_FUNCTION_ARGS) transdatums[4] = Float8GetDatumFast(Syy); transdatums[5] = Float8GetDatumFast(Sxy); - result = construct_array(transdatums, 6, - FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); + result = construct_array_builtin(transdatums, 6, FLOAT8OID); PG_RETURN_ARRAYTYPE_P(result); } diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index 28ba0fbd1929a..9948c26e76cd5 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -4,7 +4,7 @@ * Display type names "nicely". * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 8736ada4be296..5bd1e01f7e463 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -4,7 +4,7 @@ * src/backend/utils/adt/formatting.c * * - * Portions Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1999-2025, PostgreSQL Global Development Group * * * TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER(); @@ -49,7 +49,6 @@ * - better number building (formatting) / parsing, now it isn't * ideal code * - use Assert() - * - add support for roman number to standard number conversion * - add support for number spelling * - add support for string to string formatting (we must be better * than Oracle :-), @@ -77,6 +76,7 @@ #include "catalog/pg_collation.h" #include "catalog/pg_type.h" +#include "common/int.h" #include "common/unicode_case.h" #include "common/unicode_category.h" #include "mb/pg_wchar.h" @@ -256,13 +256,39 @@ static const char *const rm_months_lower[] = {"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL}; /* ---------- - * Roman numbers + * Roman numerals * ---------- */ static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL}; static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL}; static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL}; +/* + * MACRO: Check if the current and next characters form a valid subtraction + * combination for roman numerals. + */ +#define IS_VALID_SUB_COMB(curr, next) \ + (((curr) == 'I' && ((next) == 'V' || (next) == 'X')) || \ + ((curr) == 'X' && ((next) == 'L' || (next) == 'C')) || \ + ((curr) == 'C' && ((next) == 'D' || (next) == 'M'))) + +/* + * MACRO: Roman numeral value, or 0 if character isn't a roman numeral. + */ +#define ROMAN_VAL(r) \ + ((r) == 'I' ? 1 : \ + (r) == 'V' ? 5 : \ + (r) == 'X' ? 10 : \ + (r) == 'L' ? 50 : \ + (r) == 'C' ? 100 : \ + (r) == 'D' ? 500 : \ + (r) == 'M' ? 1000 : 0) + +/* + * 'MMMDCCCLXXXVIII' (3888) is the longest valid roman numeral (15 characters). + */ +#define MAX_ROMAN_LEN 15 + /* ---------- * Ordinal postfixes * ---------- @@ -622,7 +648,7 @@ typedef enum DCH_Day, DCH_Dy, DCH_D, - DCH_FF1, + DCH_FF1, /* FFn codes must be consecutive */ DCH_FF2, DCH_FF3, DCH_FF4, @@ -788,12 +814,12 @@ static const KeyWord DCH_keywords[] = { {"Day", 3, DCH_Day, false, FROM_CHAR_DATE_NONE}, {"Dy", 2, DCH_Dy, false, FROM_CHAR_DATE_NONE}, {"D", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN}, - {"FF1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* F */ - {"FF2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE}, - {"FF3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE}, - {"FF4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE}, - {"FF5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE}, - {"FF6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE}, + {"FF1", 3, DCH_FF1, true, FROM_CHAR_DATE_NONE}, /* F */ + {"FF2", 3, DCH_FF2, true, FROM_CHAR_DATE_NONE}, + {"FF3", 3, DCH_FF3, true, FROM_CHAR_DATE_NONE}, + {"FF4", 3, DCH_FF4, true, FROM_CHAR_DATE_NONE}, + {"FF5", 3, DCH_FF5, true, FROM_CHAR_DATE_NONE}, + {"FF6", 3, DCH_FF6, true, FROM_CHAR_DATE_NONE}, {"FX", 2, DCH_FX, false, FROM_CHAR_DATE_NONE}, {"HH24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* H */ {"HH12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE}, @@ -844,12 +870,12 @@ static const KeyWord DCH_keywords[] = { {"dd", 2, DCH_DD, true, FROM_CHAR_DATE_GREGORIAN}, {"dy", 2, DCH_dy, false, FROM_CHAR_DATE_NONE}, {"d", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN}, - {"ff1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* f */ - {"ff2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE}, - {"ff3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE}, - {"ff4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE}, - {"ff5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE}, - {"ff6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE}, + {"ff1", 3, DCH_FF1, true, FROM_CHAR_DATE_NONE}, /* f */ + {"ff2", 3, DCH_FF2, true, FROM_CHAR_DATE_NONE}, + {"ff3", 3, DCH_FF3, true, FROM_CHAR_DATE_NONE}, + {"ff4", 3, DCH_FF4, true, FROM_CHAR_DATE_NONE}, + {"ff5", 3, DCH_FF5, true, FROM_CHAR_DATE_NONE}, + {"ff6", 3, DCH_FF6, true, FROM_CHAR_DATE_NONE}, {"fx", 2, DCH_FX, false, FROM_CHAR_DATE_NONE}, {"hh24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* h */ {"hh12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE}, @@ -1027,6 +1053,15 @@ typedef struct NUMProc #define DCH_TIMED 0x02 #define DCH_ZONED 0x04 +/* + * These macros are used in NUM_processor() and its subsidiary routines. + * OVERLOAD_TEST: true if we've reached end of input string + * AMOUNT_TEST(s): true if at least s bytes remain in string + */ +#define OVERLOAD_TEST (Np->inout_p >= Np->inout + input_len) +#define AMOUNT_TEST(s) (Np->inout_p <= Np->inout + (input_len - (s))) + + /* ---------- * Functions * ---------- @@ -1074,6 +1109,7 @@ static bool do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, static char *fill_str(char *str, int c, int max); static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree); static char *int_to_roman(int number); +static int roman_to_int(NUMProc *Np, int input_len); static void NUM_prepare_locale(NUMProc *Np); static char *get_last_relevant_decnum(char *num); static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len); @@ -1284,6 +1320,10 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n) case NUM_rn: case NUM_RN: + if (IS_ROMAN(num)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("cannot use \"RN\" twice"))); num->flag |= NUM_F_ROMAN; break; @@ -1315,6 +1355,13 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n) num->flag |= NUM_F_EEEE; break; } + + if (IS_ROMAN(num) && + (num->flag & ~(NUM_F_ROMAN | NUM_F_FILLMODE)) != 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("\"RN\" is incompatible with other formats"), + errdetail("\"RN\" may only be used together with \"FM\"."))); } /* ---------- @@ -1570,52 +1617,6 @@ str_numth(char *dest, char *num, int type) * upper/lower/initcap functions *****************************************************************************/ -#ifdef USE_ICU - -typedef int32_t (*ICU_Convert_Func) (UChar *dest, int32_t destCapacity, - const UChar *src, int32_t srcLength, - const char *locale, - UErrorCode *pErrorCode); - -static int32_t -icu_convert_case(ICU_Convert_Func func, pg_locale_t mylocale, - UChar **buff_dest, UChar *buff_source, int32_t len_source) -{ - UErrorCode status; - int32_t len_dest; - - len_dest = len_source; /* try first with same length */ - *buff_dest = palloc(len_dest * sizeof(**buff_dest)); - status = U_ZERO_ERROR; - len_dest = func(*buff_dest, len_dest, buff_source, len_source, - mylocale->info.icu.locale, &status); - if (status == U_BUFFER_OVERFLOW_ERROR) - { - /* try again with adjusted length */ - pfree(*buff_dest); - *buff_dest = palloc(len_dest * sizeof(**buff_dest)); - status = U_ZERO_ERROR; - len_dest = func(*buff_dest, len_dest, buff_source, len_source, - mylocale->info.icu.locale, &status); - } - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("case conversion failed: %s", u_errorName(status)))); - return len_dest; -} - -static int32_t -u_strToTitle_default_BI(UChar *dest, int32_t destCapacity, - const UChar *src, int32_t srcLength, - const char *locale, - UErrorCode *pErrorCode) -{ - return u_strToTitle(dest, destCapacity, src, srcLength, - NULL, locale, pErrorCode); -} - -#endif /* USE_ICU */ - /* * If the system provides the needed functions for wide-character manipulation * (which are all standardized by C99), then we implement upper/lower/initcap @@ -1636,6 +1637,7 @@ char * str_tolower(const char *buff, size_t nbytes, Oid collid) { char *result; + pg_locale_t mylocale; if (!buff) return NULL; @@ -1653,122 +1655,37 @@ str_tolower(const char *buff, size_t nbytes, Oid collid) errhint("Use the COLLATE clause to set the collation explicitly."))); } + mylocale = pg_newlocale_from_collation(collid); + /* C/POSIX collations use this path regardless of database encoding */ - if (lc_ctype_is_c(collid)) + if (mylocale->ctype_is_c) { result = asc_tolower(buff, nbytes); } else { - pg_locale_t mylocale; - - mylocale = pg_newlocale_from_collation(collid); - -#ifdef USE_ICU - if (mylocale && mylocale->provider == COLLPROVIDER_ICU) + const char *src = buff; + size_t srclen = nbytes; + size_t dstsize; + char *dst; + size_t needed; + + /* first try buffer of equal size plus terminating NUL */ + dstsize = srclen + 1; + dst = palloc(dstsize); + + needed = pg_strlower(dst, dstsize, src, srclen, mylocale); + if (needed + 1 > dstsize) { - int32_t len_uchar; - int32_t len_conv; - UChar *buff_uchar; - UChar *buff_conv; - - len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes); - len_conv = icu_convert_case(u_strToLower, mylocale, - &buff_conv, buff_uchar, len_uchar); - icu_from_uchar(&result, buff_conv, len_conv); - pfree(buff_uchar); - pfree(buff_conv); + /* grow buffer if needed and retry */ + dstsize = needed + 1; + dst = repalloc(dst, dstsize); + needed = pg_strlower(dst, dstsize, src, srclen, mylocale); + Assert(needed + 1 <= dstsize); } - else -#endif - if (mylocale && mylocale->provider == COLLPROVIDER_BUILTIN) - { - const char *src = buff; - size_t srclen = nbytes; - size_t dstsize; - char *dst; - size_t needed; - - Assert(GetDatabaseEncoding() == PG_UTF8); - - /* first try buffer of equal size plus terminating NUL */ - dstsize = srclen + 1; - dst = palloc(dstsize); - needed = unicode_strlower(dst, dstsize, src, srclen); - if (needed + 1 > dstsize) - { - /* grow buffer if needed and retry */ - dstsize = needed + 1; - dst = repalloc(dst, dstsize); - needed = unicode_strlower(dst, dstsize, src, srclen); - Assert(needed + 1 == dstsize); - } - - Assert(dst[needed] == '\0'); - result = dst; - } - else - { - Assert(!mylocale || mylocale->provider == COLLPROVIDER_LIBC); - - if (pg_database_encoding_max_length() > 1) - { - wchar_t *workspace; - size_t curr_char; - size_t result_size; - - /* Overflow paranoia */ - if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t))) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - - /* Output workspace cannot have more codes than input bytes */ - workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t)); - - char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale); - - for (curr_char = 0; workspace[curr_char] != 0; curr_char++) - { - if (mylocale) - workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt); - else - workspace[curr_char] = towlower(workspace[curr_char]); - } - - /* - * Make result large enough; case change might change number - * of bytes - */ - result_size = curr_char * pg_database_encoding_max_length() + 1; - result = palloc(result_size); - - wchar2char(result, workspace, result_size, mylocale); - pfree(workspace); - } - else - { - char *p; - - result = pnstrdup(buff, nbytes); - - /* - * Note: we assume that tolower_l() will not be so broken as - * to need an isupper_l() guard test. When using the default - * collation, we apply the traditional Postgres behavior that - * forces ASCII-style treatment of I/i, but in non-default - * collations you get exactly what the collation says. - */ - for (p = result; *p; p++) - { - if (mylocale) - *p = tolower_l((unsigned char) *p, mylocale->info.lt); - else - *p = pg_tolower((unsigned char) *p); - } - } - } + Assert(dst[needed] == '\0'); + result = dst; } return result; @@ -1784,6 +1701,7 @@ char * str_toupper(const char *buff, size_t nbytes, Oid collid) { char *result; + pg_locale_t mylocale; if (!buff) return NULL; @@ -1801,179 +1719,117 @@ str_toupper(const char *buff, size_t nbytes, Oid collid) errhint("Use the COLLATE clause to set the collation explicitly."))); } + mylocale = pg_newlocale_from_collation(collid); + /* C/POSIX collations use this path regardless of database encoding */ - if (lc_ctype_is_c(collid)) + if (mylocale->ctype_is_c) { result = asc_toupper(buff, nbytes); } else { - pg_locale_t mylocale; - - mylocale = pg_newlocale_from_collation(collid); - -#ifdef USE_ICU - if (mylocale && mylocale->provider == COLLPROVIDER_ICU) + const char *src = buff; + size_t srclen = nbytes; + size_t dstsize; + char *dst; + size_t needed; + + /* first try buffer of equal size plus terminating NUL */ + dstsize = srclen + 1; + dst = palloc(dstsize); + + needed = pg_strupper(dst, dstsize, src, srclen, mylocale); + if (needed + 1 > dstsize) { - int32_t len_uchar, - len_conv; - UChar *buff_uchar; - UChar *buff_conv; - - len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes); - len_conv = icu_convert_case(u_strToUpper, mylocale, - &buff_conv, buff_uchar, len_uchar); - icu_from_uchar(&result, buff_conv, len_conv); - pfree(buff_uchar); - pfree(buff_conv); + /* grow buffer if needed and retry */ + dstsize = needed + 1; + dst = repalloc(dst, dstsize); + needed = pg_strupper(dst, dstsize, src, srclen, mylocale); + Assert(needed + 1 <= dstsize); } - else -#endif - if (mylocale && mylocale->provider == COLLPROVIDER_BUILTIN) - { - const char *src = buff; - size_t srclen = nbytes; - size_t dstsize; - char *dst; - size_t needed; - - Assert(GetDatabaseEncoding() == PG_UTF8); - - /* first try buffer of equal size plus terminating NUL */ - dstsize = srclen + 1; - dst = palloc(dstsize); - - needed = unicode_strupper(dst, dstsize, src, srclen); - if (needed + 1 > dstsize) - { - /* grow buffer if needed and retry */ - dstsize = needed + 1; - dst = repalloc(dst, dstsize); - needed = unicode_strupper(dst, dstsize, src, srclen); - Assert(needed + 1 == dstsize); - } - - Assert(dst[needed] == '\0'); - result = dst; - } - else - { - Assert(!mylocale || mylocale->provider == COLLPROVIDER_LIBC); - if (pg_database_encoding_max_length() > 1) - { - wchar_t *workspace; - size_t curr_char; - size_t result_size; - - /* Overflow paranoia */ - if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t))) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - - /* Output workspace cannot have more codes than input bytes */ - workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t)); - - char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale); - - for (curr_char = 0; workspace[curr_char] != 0; curr_char++) - { - if (mylocale) - workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt); - else - workspace[curr_char] = towupper(workspace[curr_char]); - } - - /* - * Make result large enough; case change might change number - * of bytes - */ - result_size = curr_char * pg_database_encoding_max_length() + 1; - result = palloc(result_size); - - wchar2char(result, workspace, result_size, mylocale); - pfree(workspace); - } - else - { - char *p; - - result = pnstrdup(buff, nbytes); - - /* - * Note: we assume that toupper_l() will not be so broken as - * to need an islower_l() guard test. When using the default - * collation, we apply the traditional Postgres behavior that - * forces ASCII-style treatment of I/i, but in non-default - * collations you get exactly what the collation says. - */ - for (p = result; *p; p++) - { - if (mylocale) - *p = toupper_l((unsigned char) *p, mylocale->info.lt); - else - *p = pg_toupper((unsigned char) *p); - } - } - } + Assert(dst[needed] == '\0'); + result = dst; } return result; } -struct WordBoundaryState -{ - const char *str; - size_t len; - size_t offset; - bool init; - bool prev_alnum; -}; - /* - * Simple word boundary iterator that draws boundaries each time the result of - * pg_u_isalnum() changes. + * collation-aware, wide-character-aware initcap function + * + * We pass the number of bytes so we can pass varlena and char* + * to this function. The result is a palloc'd, null-terminated string. */ -static size_t -initcap_wbnext(void *state) +char * +str_initcap(const char *buff, size_t nbytes, Oid collid) { - struct WordBoundaryState *wbstate = (struct WordBoundaryState *) state; + char *result; + pg_locale_t mylocale; - while (wbstate->offset < wbstate->len && - wbstate->str[wbstate->offset] != '\0') + if (!buff) + return NULL; + + if (!OidIsValid(collid)) { - pg_wchar u = utf8_to_unicode((unsigned char *) wbstate->str + - wbstate->offset); - bool curr_alnum = pg_u_isalnum(u, true); + /* + * This typically means that the parser could not resolve a conflict + * of implicit collations, so report it that way. + */ + ereport(ERROR, + (errcode(ERRCODE_INDETERMINATE_COLLATION), + errmsg("could not determine which collation to use for %s function", + "initcap()"), + errhint("Use the COLLATE clause to set the collation explicitly."))); + } - if (!wbstate->init || curr_alnum != wbstate->prev_alnum) - { - size_t prev_offset = wbstate->offset; + mylocale = pg_newlocale_from_collation(collid); - wbstate->init = true; - wbstate->offset += unicode_utf8len(u); - wbstate->prev_alnum = curr_alnum; - return prev_offset; + /* C/POSIX collations use this path regardless of database encoding */ + if (mylocale->ctype_is_c) + { + result = asc_initcap(buff, nbytes); + } + else + { + const char *src = buff; + size_t srclen = nbytes; + size_t dstsize; + char *dst; + size_t needed; + + /* first try buffer of equal size plus terminating NUL */ + dstsize = srclen + 1; + dst = palloc(dstsize); + + needed = pg_strtitle(dst, dstsize, src, srclen, mylocale); + if (needed + 1 > dstsize) + { + /* grow buffer if needed and retry */ + dstsize = needed + 1; + dst = repalloc(dst, dstsize); + needed = pg_strtitle(dst, dstsize, src, srclen, mylocale); + Assert(needed + 1 <= dstsize); } - wbstate->offset += unicode_utf8len(u); + Assert(dst[needed] == '\0'); + result = dst; } - return wbstate->len; + return result; } /* - * collation-aware, wide-character-aware initcap function + * collation-aware, wide-character-aware case folding * * We pass the number of bytes so we can pass varlena and char* * to this function. The result is a palloc'd, null-terminated string. */ char * -str_initcap(const char *buff, size_t nbytes, Oid collid) +str_casefold(const char *buff, size_t nbytes, Oid collid) { char *result; - int wasalnum = false; + pg_locale_t mylocale; if (!buff) return NULL; @@ -1987,162 +1843,46 @@ str_initcap(const char *buff, size_t nbytes, Oid collid) ereport(ERROR, (errcode(ERRCODE_INDETERMINATE_COLLATION), errmsg("could not determine which collation to use for %s function", - "initcap()"), + "lower()"), errhint("Use the COLLATE clause to set the collation explicitly."))); } + if (GetDatabaseEncoding() != PG_UTF8) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Unicode case folding can only be performed if server encoding is UTF8"))); + + mylocale = pg_newlocale_from_collation(collid); + /* C/POSIX collations use this path regardless of database encoding */ - if (lc_ctype_is_c(collid)) + if (mylocale->ctype_is_c) { - result = asc_initcap(buff, nbytes); + result = asc_tolower(buff, nbytes); } else { - pg_locale_t mylocale; - - mylocale = pg_newlocale_from_collation(collid); - -#ifdef USE_ICU - if (mylocale && mylocale->provider == COLLPROVIDER_ICU) - { - int32_t len_uchar, - len_conv; - UChar *buff_uchar; - UChar *buff_conv; - - len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes); - len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale, - &buff_conv, buff_uchar, len_uchar); - icu_from_uchar(&result, buff_conv, len_conv); - pfree(buff_uchar); - pfree(buff_conv); - } - else -#endif - if (mylocale && mylocale->provider == COLLPROVIDER_BUILTIN) + const char *src = buff; + size_t srclen = nbytes; + size_t dstsize; + char *dst; + size_t needed; + + /* first try buffer of equal size plus terminating NUL */ + dstsize = srclen + 1; + dst = palloc(dstsize); + + needed = pg_strfold(dst, dstsize, src, srclen, mylocale); + if (needed + 1 > dstsize) { - const char *src = buff; - size_t srclen = nbytes; - size_t dstsize; - char *dst; - size_t needed; - struct WordBoundaryState wbstate = { - .str = src, - .len = srclen, - .offset = 0, - .init = false, - .prev_alnum = false, - }; - - Assert(GetDatabaseEncoding() == PG_UTF8); - - /* first try buffer of equal size plus terminating NUL */ - dstsize = srclen + 1; - dst = palloc(dstsize); - - needed = unicode_strtitle(dst, dstsize, src, srclen, - initcap_wbnext, &wbstate); - if (needed + 1 > dstsize) - { - /* reset iterator */ - wbstate.offset = 0; - wbstate.init = false; - - /* grow buffer if needed and retry */ - dstsize = needed + 1; - dst = repalloc(dst, dstsize); - needed = unicode_strtitle(dst, dstsize, src, srclen, - initcap_wbnext, &wbstate); - Assert(needed + 1 == dstsize); - } - - result = dst; + /* grow buffer if needed and retry */ + dstsize = needed + 1; + dst = repalloc(dst, dstsize); + needed = pg_strfold(dst, dstsize, src, srclen, mylocale); + Assert(needed + 1 <= dstsize); } - else - { - Assert(!mylocale || mylocale->provider == COLLPROVIDER_LIBC); - if (pg_database_encoding_max_length() > 1) - { - wchar_t *workspace; - size_t curr_char; - size_t result_size; - - /* Overflow paranoia */ - if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t))) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - - /* Output workspace cannot have more codes than input bytes */ - workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t)); - - char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale); - - for (curr_char = 0; workspace[curr_char] != 0; curr_char++) - { - if (mylocale) - { - if (wasalnum) - workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt); - else - workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt); - wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt); - } - else - { - if (wasalnum) - workspace[curr_char] = towlower(workspace[curr_char]); - else - workspace[curr_char] = towupper(workspace[curr_char]); - wasalnum = iswalnum(workspace[curr_char]); - } - } - - /* - * Make result large enough; case change might change number - * of bytes - */ - result_size = curr_char * pg_database_encoding_max_length() + 1; - result = palloc(result_size); - - wchar2char(result, workspace, result_size, mylocale); - pfree(workspace); - } - else - { - char *p; - - result = pnstrdup(buff, nbytes); - - /* - * Note: we assume that toupper_l()/tolower_l() will not be so - * broken as to need guard tests. When using the default - * collation, we apply the traditional Postgres behavior that - * forces ASCII-style treatment of I/i, but in non-default - * collations you get exactly what the collation says. - */ - for (p = result; *p; p++) - { - if (mylocale) - { - if (wasalnum) - *p = tolower_l((unsigned char) *p, mylocale->info.lt); - else - *p = toupper_l((unsigned char) *p, mylocale->info.lt); - wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt); - } - else - { - if (wasalnum) - *p = pg_tolower((unsigned char) *p); - else - *p = pg_toupper((unsigned char) *p); - wasalnum = isalnum((unsigned char) *p); - } - } - } - } + Assert(dst[needed] == '\0'); + result = dst; } return result; @@ -2663,7 +2403,7 @@ seq_search_localized(const char *name, char **array, int *len, Oid collid) * Fold to upper case, then to lower case, so that we can match reliably * even in languages in which case conversions are not injective. */ - upper_name = str_toupper(unconstify(char *, name), strlen(name), collid); + upper_name = str_toupper(name, strlen(name), collid); lower_name = str_tolower(upper_name, strlen(upper_name), collid); pfree(upper_name); @@ -3851,7 +3591,14 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out, ereturn(escontext,, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input string for \"Y,YYY\""))); - years += (millennia * 1000); + + /* years += (millennia * 1000); */ + if (pg_mul_s32_overflow(millennia, 1000, &millennia) || + pg_add_s32_overflow(years, millennia, &years)) + ereturn(escontext,, + (errcode(ERRCODE_DATETIME_FIELD_OVERFLOW), + errmsg("value for \"Y,YYY\" in source string is out of range"))); + if (!from_char_set_int(&out->year, years, n, escontext)) return; out->yysz = 4; @@ -4810,10 +4557,35 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, tm->tm_year = tmfc.year % 100; if (tm->tm_year) { + int tmp; + if (tmfc.cc >= 0) - tm->tm_year += (tmfc.cc - 1) * 100; + { + /* tm->tm_year += (tmfc.cc - 1) * 100; */ + tmp = tmfc.cc - 1; + if (pg_mul_s32_overflow(tmp, 100, &tmp) || + pg_add_s32_overflow(tm->tm_year, tmp, &tm->tm_year)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + text_to_cstring(date_txt), "timestamp", + escontext); + goto fail; + } + } else - tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1; + { + /* tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1; */ + tmp = tmfc.cc + 1; + if (pg_mul_s32_overflow(tmp, 100, &tmp) || + pg_sub_s32_overflow(tmp, tm->tm_year, &tmp) || + pg_add_s32_overflow(tmp, 1, &tm->tm_year)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + text_to_cstring(date_txt), "timestamp", + escontext); + goto fail; + } + } } else { @@ -4839,11 +4611,31 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, if (tmfc.bc) tmfc.cc = -tmfc.cc; if (tmfc.cc >= 0) + { /* +1 because 21st century started in 2001 */ - tm->tm_year = (tmfc.cc - 1) * 100 + 1; + /* tm->tm_year = (tmfc.cc - 1) * 100 + 1; */ + if (pg_mul_s32_overflow(tmfc.cc - 1, 100, &tm->tm_year) || + pg_add_s32_overflow(tm->tm_year, 1, &tm->tm_year)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + text_to_cstring(date_txt), "timestamp", + escontext); + goto fail; + } + } else + { /* +1 because year == 599 is 600 BC */ - tm->tm_year = tmfc.cc * 100 + 1; + /* tm->tm_year = tmfc.cc * 100 + 1; */ + if (pg_mul_s32_overflow(tmfc.cc, 100, &tm->tm_year) || + pg_add_s32_overflow(tm->tm_year, 1, &tm->tm_year)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + text_to_cstring(date_txt), "timestamp", + escontext); + goto fail; + } + } fmask |= DTK_M(YEAR); } @@ -4868,11 +4660,31 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, fmask |= DTK_DATE_M; } else - tmfc.ddd = (tmfc.ww - 1) * 7 + 1; + { + /* tmfc.ddd = (tmfc.ww - 1) * 7 + 1; */ + if (pg_sub_s32_overflow(tmfc.ww, 1, &tmfc.ddd) || + pg_mul_s32_overflow(tmfc.ddd, 7, &tmfc.ddd) || + pg_add_s32_overflow(tmfc.ddd, 1, &tmfc.ddd)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + date_str, "timestamp", escontext); + goto fail; + } + } } if (tmfc.w) - tmfc.dd = (tmfc.w - 1) * 7 + 1; + { + /* tmfc.dd = (tmfc.w - 1) * 7 + 1; */ + if (pg_sub_s32_overflow(tmfc.w, 1, &tmfc.dd) || + pg_mul_s32_overflow(tmfc.dd, 7, &tmfc.dd) || + pg_add_s32_overflow(tmfc.dd, 1, &tmfc.dd)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + date_str, "timestamp", escontext); + goto fail; + } + } if (tmfc.dd) { tm->tm_mday = tmfc.dd; @@ -4937,7 +4749,18 @@ do_to_timestamp(text *date_txt, text *fmt, Oid collid, bool std, } if (tmfc.ms) - *fsec += tmfc.ms * 1000; + { + int tmp = 0; + + /* *fsec += tmfc.ms * 1000; */ + if (pg_mul_s32_overflow(tmfc.ms, 1000, &tmp) || + pg_add_s32_overflow(*fsec, tmp, fsec)) + { + DateTimeParseError(DTERR_FIELD_OVERFLOW, NULL, + date_str, "timestamp", escontext); + goto fail; + } + } if (tmfc.us) *fsec += tmfc.us; if (fprec) @@ -5234,6 +5057,11 @@ NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree) } +/* + * Convert integer to Roman numerals + * Result is upper-case and not blank-padded (NUM_processor converts as needed) + * If input is out-of-range, produce '###############' + */ static char * int_to_roman(int number) { @@ -5243,40 +5071,201 @@ int_to_roman(int number) *result, numstr[12]; - result = (char *) palloc(16); + result = (char *) palloc(MAX_ROMAN_LEN + 1); *result = '\0'; + /* + * This range limit is the same as in Oracle(TM). The difficulty with + * handling 4000 or more is that we'd need to use more than 3 "M"'s, and + * more than 3 of the same digit isn't considered a valid Roman string. + */ if (number > 3999 || number < 1) { - fill_str(result, '#', 15); + fill_str(result, '#', MAX_ROMAN_LEN); return result; } + + /* Convert to decimal, then examine each digit */ len = snprintf(numstr, sizeof(numstr), "%d", number); + Assert(len > 0 && len <= 4); for (p = numstr; *p != '\0'; p++, --len) { num = *p - ('0' + 1); if (num < 0) - continue; - - if (len > 3) - { - while (num-- != -1) - strcat(result, "M"); - } - else + continue; /* ignore zeroes */ + /* switch on current column position */ + switch (len) { - if (len == 3) + case 4: + while (num-- >= 0) + strcat(result, "M"); + break; + case 3: strcat(result, rm100[num]); - else if (len == 2) + break; + case 2: strcat(result, rm10[num]); - else if (len == 1) + break; + case 1: strcat(result, rm1[num]); + break; } } return result; } +/* + * Convert a roman numeral (standard form) to an integer. + * Result is an integer between 1 and 3999. + * Np->inout_p is advanced past the characters consumed. + * + * If input is invalid, return -1. + */ +static int +roman_to_int(NUMProc *Np, int input_len) +{ + int result = 0; + int len; + char romanChars[MAX_ROMAN_LEN]; + int romanValues[MAX_ROMAN_LEN]; + int repeatCount = 1; + int vCount = 0, + lCount = 0, + dCount = 0; + bool subtractionEncountered = false; + int lastSubtractedValue = 0; + + /* + * Skip any leading whitespace. Perhaps we should limit the amount of + * space skipped to MAX_ROMAN_LEN, but that seems unnecessarily picky. + */ + while (!OVERLOAD_TEST && isspace((unsigned char) *Np->inout_p)) + Np->inout_p++; + + /* + * Collect and decode valid roman numerals, consuming at most + * MAX_ROMAN_LEN characters. We do this in a separate loop to avoid + * repeated decoding and because the main loop needs to know when it's at + * the last numeral. + */ + for (len = 0; len < MAX_ROMAN_LEN && !OVERLOAD_TEST; len++) + { + char currChar = pg_ascii_toupper(*Np->inout_p); + int currValue = ROMAN_VAL(currChar); + + if (currValue == 0) + break; /* Not a valid roman numeral. */ + romanChars[len] = currChar; + romanValues[len] = currValue; + Np->inout_p++; + } + + if (len == 0) + return -1; /* No valid roman numerals. */ + + /* Check for valid combinations and compute the represented value. */ + for (int i = 0; i < len; i++) + { + char currChar = romanChars[i]; + int currValue = romanValues[i]; + + /* + * Ensure no numeral greater than or equal to the subtracted numeral + * appears after a subtraction. + */ + if (subtractionEncountered && currValue >= lastSubtractedValue) + return -1; + + /* + * V, L, and D should not appear before a larger numeral, nor should + * they be repeated. + */ + if ((vCount && currValue >= ROMAN_VAL('V')) || + (lCount && currValue >= ROMAN_VAL('L')) || + (dCount && currValue >= ROMAN_VAL('D'))) + return -1; + if (currChar == 'V') + vCount++; + else if (currChar == 'L') + lCount++; + else if (currChar == 'D') + dCount++; + + if (i < len - 1) + { + /* Compare current numeral to next numeral. */ + char nextChar = romanChars[i + 1]; + int nextValue = romanValues[i + 1]; + + /* + * If the current value is less than the next value, handle + * subtraction. Verify valid subtractive combinations and update + * the result accordingly. + */ + if (currValue < nextValue) + { + if (!IS_VALID_SUB_COMB(currChar, nextChar)) + return -1; + + /* + * Reject cases where same numeral is repeated with + * subtraction (e.g. 'MCCM' or 'DCCCD'). + */ + if (repeatCount > 1) + return -1; + + /* + * We are going to skip nextChar, so first make checks needed + * for V, L, and D. These are the same as we'd have applied + * if we reached nextChar without a subtraction. + */ + if ((vCount && nextValue >= ROMAN_VAL('V')) || + (lCount && nextValue >= ROMAN_VAL('L')) || + (dCount && nextValue >= ROMAN_VAL('D'))) + return -1; + if (nextChar == 'V') + vCount++; + else if (nextChar == 'L') + lCount++; + else if (nextChar == 'D') + dCount++; + + /* + * Skip the next numeral as it is part of the subtractive + * combination. + */ + i++; + + /* Update state. */ + repeatCount = 1; + subtractionEncountered = true; + lastSubtractedValue = currValue; + result += (nextValue - currValue); + } + else + { + /* For same numerals, check for repetition. */ + if (currChar == nextChar) + { + repeatCount++; + if (repeatCount > 3) + return -1; + } + else + repeatCount = 1; + result += currValue; + } + } + else + { + /* This is the last numeral; just add it to the result. */ + result += currValue; + } + } + + return result; +} /* ---------- @@ -5389,14 +5378,6 @@ get_last_relevant_decnum(char *num) return result; } -/* - * These macros are used in NUM_processor() and its subsidiary routines. - * OVERLOAD_TEST: true if we've reached end of input string - * AMOUNT_TEST(s): true if at least s bytes remain in string - */ -#define OVERLOAD_TEST (Np->inout_p >= Np->inout + input_len) -#define AMOUNT_TEST(s) (Np->inout_p <= Np->inout + (input_len - (s))) - /* ---------- * Number extraction for TO_NUMBER() * ---------- @@ -5580,7 +5561,7 @@ NUM_numpart_from_char(NUMProc *Np, int id, int input_len) } /* - * try read non-locale sign, it's happen only if format is not exact + * try read non-locale sign, which happens only if format is not exact * and we cannot determine sign position of MI/PL/SG, an example: * * FM9.999999MI -> 5.01- @@ -5853,29 +5834,6 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, return strcpy(inout, number); } - /* - * Roman correction - */ - if (IS_ROMAN(Np->Num)) - { - if (!Np->is_to_char) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("\"RN\" not supported for input"))); - - Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post = - Np->Num->pre = Np->out_pre_spaces = Np->sign = 0; - - if (IS_FILLMODE(Np->Num)) - { - Np->Num->flag = 0; - Np->Num->flag |= NUM_F_FILLMODE; - } - else - Np->Num->flag = 0; - Np->Num->flag |= NUM_F_ROMAN; - } - /* * Sign */ @@ -6126,28 +6084,35 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, break; case NUM_RN: - if (IS_FILLMODE(Np->Num)) - { - strcpy(Np->inout_p, Np->number_p); - Np->inout_p += strlen(Np->inout_p) - 1; - } - else - { - sprintf(Np->inout_p, "%15s", Np->number_p); - Np->inout_p += strlen(Np->inout_p) - 1; - } - break; - case NUM_rn: - if (IS_FILLMODE(Np->Num)) + if (Np->is_to_char) { - strcpy(Np->inout_p, asc_tolower_z(Np->number_p)); + const char *number_p; + + if (n->key->id == NUM_rn) + number_p = asc_tolower_z(Np->number_p); + else + number_p = Np->number_p; + if (IS_FILLMODE(Np->Num)) + strcpy(Np->inout_p, number_p); + else + sprintf(Np->inout_p, "%15s", number_p); Np->inout_p += strlen(Np->inout_p) - 1; } else { - sprintf(Np->inout_p, "%15s", asc_tolower_z(Np->number_p)); - Np->inout_p += strlen(Np->inout_p) - 1; + int roman_result = roman_to_int(Np, input_len); + int numlen; + + if (roman_result < 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid Roman numeral"))); + numlen = sprintf(Np->number_p, "%d", roman_result); + Np->number_p += numlen; + Np->Num->pre = numlen; + Np->Num->post = 0; + continue; /* roman_to_int ate all the chars */ } break; @@ -6412,7 +6377,6 @@ numeric_to_char(PG_FUNCTION_ARGS) char *numstr, *orgnum, *p; - Numeric x; NUM_TOCHAR_prepare; @@ -6421,12 +6385,15 @@ numeric_to_char(PG_FUNCTION_ARGS) */ if (IS_ROMAN(&Num)) { - x = DatumGetNumeric(DirectFunctionCall2(numeric_round, - NumericGetDatum(value), - Int32GetDatum(0))); - numstr = - int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4, - NumericGetDatum(x)))); + int32 intvalue; + bool err; + + /* Round and convert to int */ + intvalue = numeric_int4_opt_error(value, &err); + /* On overflow, just use PG_INT32_MAX; int_to_roman will cope */ + if (err) + intvalue = PG_INT32_MAX; + numstr = int_to_roman(intvalue); } else if (IS_EEEE(&Num)) { @@ -6466,6 +6433,7 @@ numeric_to_char(PG_FUNCTION_ARGS) { int numstr_pre_len; Numeric val = value; + Numeric x; if (IS_MULTI(&Num)) { @@ -6634,12 +6602,18 @@ int8_to_char(PG_FUNCTION_ARGS) NUM_TOCHAR_prepare; /* - * On DateType depend part (int32) + * On DateType depend part (int64) */ if (IS_ROMAN(&Num)) { - /* Currently don't support int8 conversion to roman... */ - numstr = int_to_roman(DatumGetInt32(DirectFunctionCall1(int84, Int64GetDatum(value)))); + int32 intvalue; + + /* On overflow, just use PG_INT32_MAX; int_to_roman will cope */ + if (value <= PG_INT32_MAX && value >= PG_INT32_MIN) + intvalue = (int32) value; + else + intvalue = PG_INT32_MAX; + numstr = int_to_roman(intvalue); } else if (IS_EEEE(&Num)) { @@ -6740,7 +6714,18 @@ float4_to_char(PG_FUNCTION_ARGS) NUM_TOCHAR_prepare; if (IS_ROMAN(&Num)) - numstr = int_to_roman((int) rint(value)); + { + int32 intvalue; + + /* See notes in ftoi4() */ + value = rint(value); + /* On overflow, just use PG_INT32_MAX; int_to_roman will cope */ + if (!isnan(value) && FLOAT4_FITS_IN_INT32(value)) + intvalue = (int32) value; + else + intvalue = PG_INT32_MAX; + numstr = int_to_roman(intvalue); + } else if (IS_EEEE(&Num)) { if (isnan(value) || isinf(value)) @@ -6842,7 +6827,18 @@ float8_to_char(PG_FUNCTION_ARGS) NUM_TOCHAR_prepare; if (IS_ROMAN(&Num)) - numstr = int_to_roman((int) rint(value)); + { + int32 intvalue; + + /* See notes in dtoi4() */ + value = rint(value); + /* On overflow, just use PG_INT32_MAX; int_to_roman will cope */ + if (!isnan(value) && FLOAT8_FITS_IN_INT32(value)) + intvalue = (int32) value; + else + intvalue = PG_INT32_MAX; + numstr = int_to_roman(intvalue); + } else if (IS_EEEE(&Num)) { if (isnan(value) || isinf(value)) diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index 0d82557417991..80bb807fbe932 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -4,7 +4,7 @@ * Functions for direct access to files * * - * Copyright (c) 2004-2024, PostgreSQL Global Development Group + * Copyright (c) 2004-2025, PostgreSQL Global Development Group * * Author: Andreas Pflug * @@ -690,25 +690,36 @@ pg_ls_archive_statusdir(PG_FUNCTION_ARGS) } /* - * Function to return the list of files in the pg_logical/snapshots directory. + * Function to return the list of files in the WAL summaries directory. + */ +Datum +pg_ls_summariesdir(PG_FUNCTION_ARGS) +{ + return pg_ls_dir_files(fcinfo, XLOGDIR "/summaries", true); +} + +/* + * Function to return the list of files in the PG_LOGICAL_SNAPSHOTS_DIR + * directory. */ Datum pg_ls_logicalsnapdir(PG_FUNCTION_ARGS) { - return pg_ls_dir_files(fcinfo, "pg_logical/snapshots", false); + return pg_ls_dir_files(fcinfo, PG_LOGICAL_SNAPSHOTS_DIR, false); } /* - * Function to return the list of files in the pg_logical/mappings directory. + * Function to return the list of files in the PG_LOGICAL_MAPPINGS_DIR + * directory. */ Datum pg_ls_logicalmapdir(PG_FUNCTION_ARGS) { - return pg_ls_dir_files(fcinfo, "pg_logical/mappings", false); + return pg_ls_dir_files(fcinfo, PG_LOGICAL_MAPPINGS_DIR, false); } /* - * Function to return the list of files in the pg_replslot/ + * Function to return the list of files in the PG_REPLSLOT_DIR/ * directory. */ Datum @@ -728,6 +739,7 @@ pg_ls_replslotdir(PG_FUNCTION_ARGS) errmsg("replication slot \"%s\" does not exist", slotname))); - snprintf(path, sizeof(path), "pg_replslot/%s", slotname); + snprintf(path, sizeof(path), "%s/%s", PG_REPLSLOT_DIR, slotname); + return pg_ls_dir_files(fcinfo, path, false); } diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 07d1649c7b659..377a1b3f3ade1 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -13,7 +13,7 @@ * - circle * - polygon * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/geo_selfuncs.c b/src/backend/utils/adt/geo_selfuncs.c index 340d3065f838c..034585176608c 100644 --- a/src/backend/utils/adt/geo_selfuncs.c +++ b/src/backend/utils/adt/geo_selfuncs.c @@ -4,7 +4,7 @@ * Selectivity routines registered in the operator catalog in the * "oprrest" and "oprjoin" attributes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c index 51378dca5baa6..fec33e9537243 100644 --- a/src/backend/utils/adt/geo_spgist.c +++ b/src/backend/utils/adt/geo_spgist.c @@ -62,7 +62,7 @@ * except the root. For the root node, we are setting the boundaries * that we don't yet have as infinity. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/hbafuncs.c b/src/backend/utils/adt/hbafuncs.c index beaae88e5416d..b62c3d944cf1a 100644 --- a/src/backend/utils/adt/hbafuncs.c +++ b/src/backend/utils/adt/hbafuncs.c @@ -3,7 +3,7 @@ * hbafuncs.c * Support functions for SQL views of authentication files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -37,12 +37,12 @@ static void fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc); /* * This macro specifies the maximum number of authentication options * that are possible with any given authentication method that is supported. - * Currently LDAP supports 11, and there are 3 that are not dependent on + * Currently LDAP supports 12, and there are 3 that are not dependent on * the auth method here. It may not actually be possible to set all of them * at the same time, but we'll set the macro value high enough to be * conservative and avoid warnings from static analysis tools. */ -#define MAX_HBA_OPTIONS 14 +#define MAX_HBA_OPTIONS 15 /* * Create a text array listing the options specified in the HBA line. @@ -89,6 +89,10 @@ get_hba_options(HbaLine *hba) options[noptions++] = CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport)); + if (hba->ldapscheme) + options[noptions++] = + CStringGetTextDatum(psprintf("ldapscheme=%s", hba->ldapscheme)); + if (hba->ldaptls) options[noptions++] = CStringGetTextDatum("ldaptls=true"); @@ -148,6 +152,25 @@ get_hba_options(HbaLine *hba) CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s)); } + if (hba->auth_method == uaOAuth) + { + if (hba->oauth_issuer) + options[noptions++] = + CStringGetTextDatum(psprintf("issuer=%s", hba->oauth_issuer)); + + if (hba->oauth_scope) + options[noptions++] = + CStringGetTextDatum(psprintf("scope=%s", hba->oauth_scope)); + + if (hba->oauth_validator) + options[noptions++] = + CStringGetTextDatum(psprintf("validator=%s", hba->oauth_validator)); + + if (hba->oauth_skip_usermap) + options[noptions++] = + CStringGetTextDatum(psprintf("delegate_ident_mapping=true")); + } + /* If you add more options, consider increasing MAX_HBA_OPTIONS. */ Assert(noptions <= MAX_HBA_OPTIONS); diff --git a/src/backend/utils/adt/inet_net_pton.c b/src/backend/utils/adt/inet_net_pton.c index d3221a13139bb..ef2236d9f0430 100644 --- a/src/backend/utils/adt/inet_net_pton.c +++ b/src/backend/utils/adt/inet_net_pton.c @@ -29,8 +29,7 @@ static const char rcsid[] = "Id: inet_net_pton.c,v 1.4.2.3 2004/03/17 00:40:11 m #include #include -#include "utils/builtins.h" /* pgrminclude ignore */ /* needed on some - * platforms */ +#include "utils/builtins.h" /* needed on some platforms */ #include "utils/inet.h" diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 234f20796b761..b5781989a64d5 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -3,7 +3,7 @@ * int.c * Functions for the built-in integer types (except int8). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 54fa3bc379999..9dd5889f34c62 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -3,7 +3,7 @@ * int8.c * Internal 64-bit integer operations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index be7bc46038f67..51452755f5868 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -3,7 +3,7 @@ * json.c * JSON data type support. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,6 +19,7 @@ #include "funcapi.h" #include "libpq/pqformat.h" #include "miscadmin.h" +#include "port/simd.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/date.h" @@ -1110,7 +1111,14 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo, if (unique_keys) { - const char *key = &out->data[key_offset]; + /* + * Copy the key first, instead of pointing into the buffer. It will be + * added to the hash table, but the buffer may get reallocated as + * we're appending more data to it. That would invalidate pointers to + * keys in the current buffer. + */ + const char *key = MemoryContextStrdup(aggcontext, + &out->data[key_offset]); if (!json_unique_check_key(&state->unique_check.check, key, 0)) ereport(ERROR, @@ -1273,8 +1281,15 @@ json_build_object_worker(int nargs, const Datum *args, const bool *nulls, const if (unique_keys) { - /* check key uniqueness after key appending */ - const char *key = &out->data[key_offset]; + /* + * check key uniqueness after key appending + * + * Copy the key first, instead of pointing into the buffer. It + * will be added to the hash table, but the buffer may get + * reallocated as we're appending more data to it. That would + * invalidate pointers to keys in the current buffer. + */ + const char *key = pstrdup(&out->data[key_offset]); if (!json_unique_check_key(&unique_check.check, key, 0)) ereport(ERROR, @@ -1594,6 +1609,18 @@ escape_json(StringInfo buf, const char *str) appendStringInfoCharMacro(buf, '"'); } +/* + * Define the number of bytes that escape_json_with_len will look ahead in the + * input string before flushing the input string to the destination buffer. + * Looking ahead too far could result in cachelines being evicted that will + * need to be reloaded in order to perform the appendBinaryStringInfo call. + * Smaller values will result in a larger number of calls to + * appendBinaryStringInfo and introduce additional function call overhead. + * Values larger than the size of L1d cache will likely result in worse + * performance. + */ +#define ESCAPE_JSON_FLUSH_AFTER 512 + /* * escape_json_with_len * Produce a JSON string literal, properly escaping the possibly not @@ -1603,11 +1630,98 @@ escape_json(StringInfo buf, const char *str) void escape_json_with_len(StringInfo buf, const char *str, int len) { + int vlen; + + Assert(len >= 0); + + /* + * Since we know the minimum length we'll need to append, let's just + * enlarge the buffer now rather than incrementally making more space when + * we run out. Add two extra bytes for the enclosing quotes. + */ + enlargeStringInfo(buf, len + 2); + + /* + * Figure out how many bytes to process using SIMD. Round 'len' down to + * the previous multiple of sizeof(Vector8), assuming that's a power-of-2. + */ + vlen = len & (int) (~(sizeof(Vector8) - 1)); + appendStringInfoCharMacro(buf, '"'); - for (int i = 0; i < len; i++) - escape_json_char(buf, str[i]); + for (int i = 0, copypos = 0;;) + { + /* + * To speed this up, try searching sizeof(Vector8) bytes at once for + * special characters that we need to escape. When we find one, we + * fall out of the Vector8 loop and copy the portion we've vector + * searched and then we process sizeof(Vector8) bytes one byte at a + * time. Once done, come back and try doing vector searching again. + * We'll also process any remaining bytes at the tail end of the + * string byte-by-byte. This optimization assumes that most chunks of + * sizeof(Vector8) bytes won't contain any special characters. + */ + for (; i < vlen; i += sizeof(Vector8)) + { + Vector8 chunk; + + vector8_load(&chunk, (const uint8 *) &str[i]); + + /* + * Break on anything less than ' ' or if we find a '"' or '\\'. + * Those need special handling. That's done in the per-byte loop. + */ + if (vector8_has_le(chunk, (unsigned char) 0x1F) || + vector8_has(chunk, (unsigned char) '"') || + vector8_has(chunk, (unsigned char) '\\')) + break; + +#ifdef ESCAPE_JSON_FLUSH_AFTER + + /* + * Flush what's been checked so far out to the destination buffer + * every so often to avoid having to re-read cachelines when + * escaping large strings. + */ + if (i - copypos >= ESCAPE_JSON_FLUSH_AFTER) + { + appendBinaryStringInfo(buf, &str[copypos], i - copypos); + copypos = i; + } +#endif + } + + /* + * Write to the destination up to the point that we've vector searched + * so far. Do this only when switching into per-byte mode rather than + * once every sizeof(Vector8) bytes. + */ + if (copypos < i) + { + appendBinaryStringInfo(buf, &str[copypos], i - copypos); + copypos = i; + } + + /* + * Per-byte loop for Vector8s containing special chars and for + * processing the tail of the string. + */ + for (int b = 0; b < sizeof(Vector8); b++) + { + /* check if we've finished */ + if (i == len) + goto done; + + Assert(i < len); + + escape_json_char(buf, str[i++]); + } + + copypos = i; + /* We're not done yet. Try the vector search again. */ + } +done: appendStringInfoCharMacro(buf, '"'); } diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 928552d551406..da94d424d617f 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -3,7 +3,7 @@ * jsonb.c * I/O routines for jsonb type * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/jsonb.c @@ -257,7 +257,7 @@ jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext) state.unique_keys = unique_keys; state.escontext = escontext; - sem.semstate = (void *) &state; + sem.semstate = &state; sem.object_start = jsonb_in_object_start; sem.array_start = jsonb_in_array_start; @@ -657,7 +657,7 @@ datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result, tcategory == JSONTYPE_COMPOSITE || tcategory == JSONTYPE_JSON || tcategory == JSONTYPE_JSONB || - tcategory == JSONTYPE_JSON)) + tcategory == JSONTYPE_CAST)) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -758,7 +758,7 @@ datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result, memset(&sem, 0, sizeof(sem)); - sem.semstate = (void *) result; + sem.semstate = result; sem.object_start = jsonb_in_object_start; sem.array_start = jsonb_in_array_start; @@ -2040,7 +2040,16 @@ jsonb_bool(PG_FUNCTION_ARGS) Jsonb *in = PG_GETARG_JSONB_P(0); JsonbValue v; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "boolean"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvBool) cannotCastJsonbValue(v.type, "boolean"); PG_FREE_IF_COPY(in, 0); @@ -2055,7 +2064,16 @@ jsonb_numeric(PG_FUNCTION_ARGS) JsonbValue v; Numeric retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "numeric"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "numeric"); /* @@ -2076,7 +2094,16 @@ jsonb_int2(PG_FUNCTION_ARGS) JsonbValue v; Datum retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "smallint"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "smallint"); retValue = DirectFunctionCall1(numeric_int2, @@ -2094,7 +2121,16 @@ jsonb_int4(PG_FUNCTION_ARGS) JsonbValue v; Datum retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "integer"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "integer"); retValue = DirectFunctionCall1(numeric_int4, @@ -2112,7 +2148,16 @@ jsonb_int8(PG_FUNCTION_ARGS) JsonbValue v; Datum retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "bigint"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "bigint"); retValue = DirectFunctionCall1(numeric_int8, @@ -2130,7 +2175,16 @@ jsonb_float4(PG_FUNCTION_ARGS) JsonbValue v; Datum retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "real"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "real"); retValue = DirectFunctionCall1(numeric_float4, @@ -2148,7 +2202,16 @@ jsonb_float8(PG_FUNCTION_ARGS) JsonbValue v; Datum retValue; - if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric) + if (!JsonbExtractScalar(&in->root, &v)) + cannotCastJsonbValue(v.type, "double precision"); + + if (v.type == jbvNull) + { + PG_FREE_IF_COPY(in, 0); + PG_RETURN_NULL(); + } + + if (v.type != jbvNumeric) cannotCastJsonbValue(v.type, "double precision"); retValue = DirectFunctionCall1(numeric_float8, diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c index b03d94f82b8e2..c1950792b5aea 100644 --- a/src/backend/utils/adt/jsonb_gin.c +++ b/src/backend/utils/adt/jsonb_gin.c @@ -3,7 +3,7 @@ * jsonb_gin.c * GIN support functions for jsonb * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * We provide two opclasses for jsonb indexing: jsonb_ops and jsonb_path_ops. * For their description see json.sgml and comments in jsonb.h. diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c index da0d13992ca0a..fa5603f26e1d6 100644 --- a/src/backend/utils/adt/jsonb_op.c +++ b/src/backend/utils/adt/jsonb_op.c @@ -3,7 +3,7 @@ * jsonb_op.c * Special operators for jsonb only, used by various index access methods * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c index 9941daad2bc0b..c8b6c15e05975 100644 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@ -3,7 +3,7 @@ * jsonb_util.c * converting between Jsonb and JsonbValues, and iterating. * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -48,8 +48,8 @@ static void convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *va static void convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal); static int reserveFromBuffer(StringInfo buffer, int len); -static void appendToBuffer(StringInfo buffer, const char *data, int len); -static void copyToBuffer(StringInfo buffer, int offset, const char *data, int len); +static void appendToBuffer(StringInfo buffer, const void *data, int len); +static void copyToBuffer(StringInfo buffer, int offset, const void *data, int len); static short padBufferToInt(StringInfo buffer); static JsonbIterator *iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent); @@ -246,6 +246,13 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b) */ if (va.val.array.rawScalar != vb.val.array.rawScalar) res = (va.val.array.rawScalar) ? -1 : 1; + + /* + * There should be an "else" here, to prevent us from + * overriding the above, but we can't change the sort + * order now, so there is a mild anomaly that an empty + * top level array sorts less than null. + */ if (va.val.array.nElems != vb.val.array.nElems) res = (va.val.array.nElems > vb.val.array.nElems) ? 1 : -1; break; @@ -1501,7 +1508,7 @@ reserveFromBuffer(StringInfo buffer, int len) * Copy 'len' bytes to a previously reserved area in buffer. */ static void -copyToBuffer(StringInfo buffer, int offset, const char *data, int len) +copyToBuffer(StringInfo buffer, int offset, const void *data, int len) { memcpy(buffer->data + offset, data, len); } @@ -1510,7 +1517,7 @@ copyToBuffer(StringInfo buffer, int offset, const char *data, int len) * A shorthand for reserveFromBuffer + copyToBuffer. */ static void -appendToBuffer(StringInfo buffer, const char *data, int len) +appendToBuffer(StringInfo buffer, const void *data, int len) { int offset; @@ -1639,7 +1646,7 @@ convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level) containerhead |= JB_FSCALAR; } - appendToBuffer(buffer, (char *) &containerhead, sizeof(uint32)); + appendToBuffer(buffer, &containerhead, sizeof(uint32)); /* Reserve space for the JEntries of the elements. */ jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nElems); @@ -1677,7 +1684,7 @@ convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level) if ((i % JB_OFFSET_STRIDE) == 0) meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF; - copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry)); + copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry)); jentry_offset += sizeof(JEntry); } @@ -1716,7 +1723,7 @@ convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level * variable-length payload. */ containerheader = nPairs | JB_FOBJECT; - appendToBuffer(buffer, (char *) &containerheader, sizeof(uint32)); + appendToBuffer(buffer, &containerheader, sizeof(uint32)); /* Reserve space for the JEntries of the keys and values. */ jentry_offset = reserveFromBuffer(buffer, sizeof(JEntry) * nPairs * 2); @@ -1758,7 +1765,7 @@ convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level if ((i % JB_OFFSET_STRIDE) == 0) meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF; - copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry)); + copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry)); jentry_offset += sizeof(JEntry); } for (i = 0; i < nPairs; i++) @@ -1793,7 +1800,7 @@ convertJsonbObject(StringInfo buffer, JEntry *header, JsonbValue *val, int level if (((i + nPairs) % JB_OFFSET_STRIDE) == 0) meta = (meta & JENTRY_TYPEMASK) | totallen | JENTRY_HAS_OFF; - copyToBuffer(buffer, jentry_offset, (char *) &meta, sizeof(JEntry)); + copyToBuffer(buffer, jentry_offset, &meta, sizeof(JEntry)); jentry_offset += sizeof(JEntry); } @@ -1833,7 +1840,7 @@ convertJsonbScalar(StringInfo buffer, JEntry *header, JsonbValue *scalarVal) numlen = VARSIZE_ANY(scalarVal->val.numeric); padlen = padBufferToInt(buffer); - appendToBuffer(buffer, (char *) scalarVal->val.numeric, numlen); + appendToBuffer(buffer, scalarVal->val.numeric, numlen); *header = JENTRY_ISNUMERIC | (padlen + numlen); break; diff --git a/src/backend/utils/adt/jsonbsubs.c b/src/backend/utils/adt/jsonbsubs.c index 2b037131c9115..de64d49851251 100644 --- a/src/backend/utils/adt/jsonbsubs.c +++ b/src/backend/utils/adt/jsonbsubs.c @@ -3,7 +3,7 @@ * jsonbsubs.c * Subscripting support functions for jsonb. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 7076b344b7be1..bcb1720b6cde2 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -3,7 +3,7 @@ * jsonfuncs.c * Functions to process JSON data types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,6 +18,7 @@ #include "access/htup_details.h" #include "catalog/pg_type.h" +#include "common/int.h" #include "common/jsonapi.h" #include "common/string.h" #include "fmgr.h" @@ -285,6 +286,7 @@ typedef struct StripnullState JsonLexContext *lex; StringInfo strval; bool skip_next_null; + bool strip_in_arrays; } StripnullState; /* structure for generalized json/jsonb value passing */ @@ -514,7 +516,7 @@ static JsonParseErrorType transform_string_values_scalar(void *state, char *toke * returned when escontext is an ErrorSaveContext). */ bool -pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, +pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext) { JsonParseErrorType result; @@ -616,7 +618,7 @@ jsonb_object_keys(PG_FUNCTION_ARGS) } MemoryContextSwitchTo(oldcontext); - funcctx->user_fctx = (void *) state; + funcctx->user_fctx = state; } funcctx = SRF_PERCALL_SETUP(); @@ -751,7 +753,7 @@ json_object_keys(PG_FUNCTION_ARGS) state->sent_count = 0; state->result = palloc(256 * sizeof(char *)); - sem->semstate = (void *) state; + sem->semstate = state; sem->array_start = okeys_array_start; sem->scalar = okeys_scalar; sem->object_field_start = okeys_object_field_start; @@ -764,7 +766,7 @@ json_object_keys(PG_FUNCTION_ARGS) pfree(sem); MemoryContextSwitchTo(oldcontext); - funcctx->user_fctx = (void *) state; + funcctx->user_fctx = state; } funcctx = SRF_PERCALL_SETUP(); @@ -946,7 +948,7 @@ jsonb_array_element(PG_FUNCTION_ARGS) { uint32 nelements = JB_ROOT_COUNT(jb); - if (-element > nelements) + if (pg_abs_s32(element) > nelements) PG_RETURN_NULL(); else element += nelements; @@ -989,7 +991,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS) { uint32 nelements = JB_ROOT_COUNT(jb); - if (-element > nelements) + if (pg_abs_s32(element) > nelements) PG_RETURN_NULL(); else element += nelements; @@ -1122,7 +1124,7 @@ get_worker(text *json, if (npath > 0) state->pathok[0] = true; - sem->semstate = (void *) state; + sem->semstate = state; /* * Not all variants need all the semantic routines. Only set the ones that @@ -1721,9 +1723,9 @@ push_path(JsonbParseState **st, int level, Datum *path_elems, { /* * tpath contains expected type of an empty jsonb created at each level - * higher or equal than the current one, either jbvObject or jbvArray. - * Since it contains only information about path slice from level to the - * end, the access index must be normalized by level. + * higher or equal to the current one, either jbvObject or jbvArray. Since + * it contains only information about path slice from level to the end, + * the access index must be normalized by level. */ enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType)); JsonbValue newkey; @@ -1862,7 +1864,7 @@ json_array_length(PG_FUNCTION_ARGS) #endif sem = palloc0(sizeof(JsonSemAction)); - sem->semstate = (void *) state; + sem->semstate = state; sem->object_start = alen_object_start; sem->scalar = alen_scalar; sem->array_element_start = alen_array_element_start; @@ -2070,7 +2072,7 @@ each_worker(FunctionCallInfo fcinfo, bool as_text) state->tuple_store = rsi->setResult; state->ret_tdesc = rsi->setDesc; - sem->semstate = (void *) state; + sem->semstate = state; sem->array_start = each_array_start; sem->scalar = each_scalar; sem->object_field_start = each_object_field_start; @@ -2322,7 +2324,7 @@ elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text) state->tuple_store = rsi->setResult; state->ret_tdesc = rsi->setDesc; - sem->semstate = (void *) state; + sem->semstate = state; sem->object_start = elements_object_start; sem->scalar = elements_scalar; sem->array_element_start = elements_array_element_start; @@ -2794,7 +2796,7 @@ populate_array_json(PopulateArrayContext *ctx, const char *json, int len) state.ctx = ctx; memset(&sem, 0, sizeof(sem)); - sem.semstate = (void *) &state; + sem.semstate = &state; sem.object_start = populate_array_object_start; sem.array_end = populate_array_array_end; sem.array_element_start = populate_array_element_start; @@ -3830,7 +3832,7 @@ get_json_object_as_hash(const char *json, int len, const char *funcname, state->lex = makeJsonLexContextCstringLen(NULL, json, len, GetDatabaseEncoding(), true); - sem->semstate = (void *) state; + sem->semstate = state; sem->array_start = hash_array_start; sem->scalar = hash_scalar; sem->object_field_start = hash_object_field_start; @@ -4143,7 +4145,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, makeJsonLexContext(&lex, json, true); - sem->semstate = (void *) state; + sem->semstate = state; sem->array_start = populate_recordset_array_start; sem->array_element_start = populate_recordset_array_element_start; sem->scalar = populate_recordset_scalar; @@ -4459,8 +4461,19 @@ sn_array_element_start(void *state, bool isnull) { StripnullState *_state = (StripnullState *) state; - if (_state->strval->data[_state->strval->len - 1] != '[') + /* If strip_in_arrays is enabled and this is a null, mark it for skipping */ + if (isnull && _state->strip_in_arrays) + { + _state->skip_next_null = true; + return JSON_SUCCESS; + } + + /* Only add a comma if this is not the first valid element */ + if (_state->strval->len > 0 && + _state->strval->data[_state->strval->len - 1] != '[') + { appendStringInfoCharMacro(_state->strval, ','); + } return JSON_SUCCESS; } @@ -4492,6 +4505,7 @@ Datum json_strip_nulls(PG_FUNCTION_ARGS) { text *json = PG_GETARG_TEXT_PP(0); + bool strip_in_arrays = PG_NARGS() == 2 ? PG_GETARG_BOOL(1) : false; StripnullState *state; JsonLexContext lex; JsonSemAction *sem; @@ -4502,8 +4516,9 @@ json_strip_nulls(PG_FUNCTION_ARGS) state->lex = makeJsonLexContext(&lex, json, true); state->strval = makeStringInfo(); state->skip_next_null = false; + state->strip_in_arrays = strip_in_arrays; - sem->semstate = (void *) state; + sem->semstate = state; sem->object_start = sn_object_start; sem->object_end = sn_object_end; sem->array_start = sn_array_start; @@ -4519,12 +4534,13 @@ json_strip_nulls(PG_FUNCTION_ARGS) } /* - * SQL function jsonb_strip_nulls(jsonb) -> jsonb + * SQL function jsonb_strip_nulls(jsonb, bool) -> jsonb */ Datum jsonb_strip_nulls(PG_FUNCTION_ARGS) { Jsonb *jb = PG_GETARG_JSONB_P(0); + bool strip_in_arrays = false; JsonbIterator *it; JsonbParseState *parseState = NULL; JsonbValue *res = NULL; @@ -4533,6 +4549,9 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) JsonbIteratorToken type; bool last_was_key = false; + if (PG_NARGS() == 2) + strip_in_arrays = PG_GETARG_BOOL(1); + if (JB_ROOT_IS_SCALAR(jb)) PG_RETURN_POINTER(jb); @@ -4563,6 +4582,11 @@ jsonb_strip_nulls(PG_FUNCTION_ARGS) (void) pushJsonbValue(&parseState, WJB_KEY, &k); } + /* if strip_in_arrays is set, also skip null array elements */ + if (strip_in_arrays) + if (type == WJB_ELEM && v.type == jbvNull) + continue; + if (type == WJB_VALUE || type == WJB_ELEM) res = pushJsonbValue(&parseState, type, &v); else @@ -4810,7 +4834,7 @@ jsonb_delete_idx(PG_FUNCTION_ARGS) if (idx < 0) { - if (-idx > n) + if (pg_abs_s32(idx) > n) idx = n; else idx = n + idx; @@ -5426,7 +5450,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls, if (idx < 0) { - if (-idx > nelems) + if (pg_abs_s32(idx) > nelems) { /* * If asked to keep elements position consistent, it's not allowed @@ -5438,7 +5462,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls, errmsg("path element at position %d is out of range: %d", level + 1, idx))); else - idx = INT_MIN; + idx = PG_INT32_MIN; } else idx = nelems + idx; @@ -5717,7 +5741,7 @@ iterate_json_values(text *json, uint32 flags, void *action_state, state->action_state = action_state; state->flags = flags; - sem->semstate = (void *) state; + sem->semstate = state; sem->scalar = iterate_values_scalar; sem->object_field_start = iterate_values_object_field_start; @@ -5838,7 +5862,7 @@ transform_json_string_values(text *json, void *action_state, state->action = transform_action; state->action_state = action_state; - sem->semstate = (void *) state; + sem->semstate = state; sem->object_start = transform_string_values_object_start; sem->object_end = transform_string_values_object_end; sem->array_start = transform_string_values_array_start; diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c index 0f691bc5f0f9a..762f7e8a09d39 100644 --- a/src/backend/utils/adt/jsonpath.c +++ b/src/backend/utils/adt/jsonpath.c @@ -53,7 +53,7 @@ * | |__| |__||________________________||___________________| | * |_______________________________________________________________________| * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/jsonpath.c diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c index d79c9298227a0..dbab24737ef1f 100644 --- a/src/backend/utils/adt/jsonpath_exec.c +++ b/src/backend/utils/adt/jsonpath_exec.c @@ -49,7 +49,7 @@ * we calculate operands first. Then we check that results are numeric * singleton lists, calculate the result and pass it to the next path item. * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/jsonpath_exec.c @@ -61,7 +61,6 @@ #include "catalog/pg_collation.h" #include "catalog/pg_type.h" -#include "executor/execExpr.h" #include "funcapi.h" #include "miscadmin.h" #include "nodes/miscnodes.h" @@ -72,13 +71,13 @@ #include "utils/datetime.h" #include "utils/float.h" #include "utils/formatting.h" +#include "utils/json.h" #include "utils/jsonpath.h" -#include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/timestamp.h" /* - * Represents "base object" and it's "id" for .keyvalue() evaluation. + * Represents "base object" and its "id" for .keyvalue() evaluation. */ typedef struct JsonBaseObjectInfo { @@ -1163,8 +1162,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type double precision", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "double precision")))); if (isinf(val) || isnan(val)) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), @@ -1189,8 +1188,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type double precision", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "double precision")))); if (isinf(val) || isnan(val)) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), @@ -1277,10 +1276,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (have_error) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type bigint", + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(jb->val.numeric))), - jspOperationName(jsp->type))))); + jspOperationName(jsp->type), + "bigint")))); datum = Int64GetDatum(val); res = jperOk; @@ -1301,8 +1301,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!noerr || escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type bigint", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "bigint")))); res = jperOk; } @@ -1353,8 +1353,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!noerr || escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type boolean", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "boolean")))); ival = DatumGetInt32(datum); if (ival == 0) @@ -1373,8 +1373,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!parse_bool(tmp, &bval)) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type boolean", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "boolean")))); res = jperOk; } @@ -1382,7 +1382,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (res == jperNotFound) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("jsonpath item method .%s() can only be applied to a bool, string, or numeric value", + errmsg("jsonpath item method .%s() can only be applied to a boolean, string, or numeric value", jspOperationName(jsp->type))))); jb = &jbv; @@ -1435,8 +1435,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!noerr || escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type numeric", - numstr, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + numstr, jspOperationName(jsp->type), "numeric")))); num = DatumGetNumeric(datum); if (numeric_is_nan(num) || numeric_is_inf(num)) @@ -1524,8 +1524,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!noerr || escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type numeric", - numstr, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + numstr, jspOperationName(jsp->type), "numeric")))); num = DatumGetNumeric(numdatum); pfree(arrtypmod); @@ -1557,10 +1557,10 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (have_error) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type integer", + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(jb->val.numeric))), - jspOperationName(jsp->type))))); + jspOperationName(jsp->type), "integer")))); datum = Int32GetDatum(val); res = jperOk; @@ -1581,8 +1581,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, if (!noerr || escontext.error_occurred) RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type integer", - tmp, jspOperationName(jsp->type))))); + errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s", + tmp, jspOperationName(jsp->type), "integer")))); res = jperOk; } @@ -1629,32 +1629,13 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, break; case jbvDatetime: { - switch (jb->val.datetime.typid) - { - case DATEOID: - tmp = DatumGetCString(DirectFunctionCall1(date_out, - jb->val.datetime.value)); - break; - case TIMEOID: - tmp = DatumGetCString(DirectFunctionCall1(time_out, - jb->val.datetime.value)); - break; - case TIMETZOID: - tmp = DatumGetCString(DirectFunctionCall1(timetz_out, - jb->val.datetime.value)); - break; - case TIMESTAMPOID: - tmp = DatumGetCString(DirectFunctionCall1(timestamp_out, - jb->val.datetime.value)); - break; - case TIMESTAMPTZOID: - tmp = DatumGetCString(DirectFunctionCall1(timestamptz_out, - jb->val.datetime.value)); - break; - default: - elog(ERROR, "unrecognized SQL/JSON datetime type oid: %u", - jb->val.datetime.typid); - } + char buf[MAXDATELEN + 1]; + + JsonEncodeDateTime(buf, + jb->val.datetime.value, + jb->val.datetime.typid, + &jb->val.datetime.tz); + tmp = pstrdup(buf); } break; case jbvNull: @@ -1663,7 +1644,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp, case jbvBinary: RETURN_ERROR(ereport(ERROR, (errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM), - errmsg("jsonpath item method .%s() can only be applied to a bool, string, numeric, or datetime value", + errmsg("jsonpath item method .%s() can only be applied to a boolean, string, numeric, or datetime value", jspOperationName(jsp->type))))); break; } @@ -2707,12 +2688,27 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, break; case jpiTimestampTz: { + struct pg_tm tm; + fsec_t fsec; + /* Convert result type to timestamp with time zone */ switch (typid) { case DATEOID: checkTimezoneIsUsedForCast(cxt->useTz, "date", "timestamptz"); + + /* + * Get the timezone value explicitly since JsonbValue + * keeps that separate. + */ + j2date(DatumGetDateADT(value) + POSTGRES_EPOCH_JDATE, + &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday)); + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tz = DetermineTimeZoneOffset(&tm, session_timezone); + value = DirectFunctionCall1(date_timestamptz, value); break; @@ -2726,6 +2722,16 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp, case TIMESTAMPOID: checkTimezoneIsUsedForCast(cxt->useTz, "timestamp", "timestamptz"); + + /* + * Get the timezone value explicitly since JsonbValue + * keeps that separate. + */ + if (timestamp2tm(DatumGetTimestamp(value), NULL, &tm, + &fsec, NULL, NULL) == 0) + tz = DetermineTimeZoneOffset(&tm, + session_timezone); + value = DirectFunctionCall1(timestamp_timestamptz, value); break; @@ -3610,7 +3616,7 @@ JsonbType(JsonbValue *jb) if (jb->type == jbvBinary) { - JsonbContainer *jbc = (void *) jb->val.binary.data; + JsonbContainer *jbc = jb->val.binary.data; /* Scalars should be always extracted during jsonpath execution. */ Assert(!JsonContainerIsScalar(jbc)); @@ -3922,7 +3928,24 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, return (Datum) 0; } - /* WRAP or not? */ + /* + * Determine whether to wrap the result in a JSON array or not. + * + * First, count the number of SQL/JSON items in the returned + * JsonValueList. If the list is empty (singleton == NULL), no wrapping is + * necessary. + * + * If the wrapper mode is JSW_NONE or JSW_UNSPEC, wrapping is explicitly + * disabled. This enforces a WITHOUT WRAPPER clause, which is also the + * default when no WRAPPER clause is specified. + * + * If the mode is JSW_UNCONDITIONAL, wrapping is enforced regardless of + * the number of SQL/JSON items, enforcing a WITH WRAPPER or WITH + * UNCONDITIONAL WRAPPER clause. + * + * For JSW_CONDITIONAL, wrapping occurs only if there is more than one + * SQL/JSON item in the list, enforcing a WITH CONDITIONAL WRAPPER clause. + */ count = JsonValueListLength(&found); singleton = count > 0 ? JsonValueListHead(&found) : NULL; if (singleton == NULL) @@ -3932,10 +3955,7 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, else if (wrapper == JSW_UNCONDITIONAL) wrap = true; else if (wrapper == JSW_CONDITIONAL) - wrap = count > 1 || - IsAJsonbScalar(singleton) || - (singleton->type == jbvBinary && - JsonContainerIsScalar(singleton->val.binary.data)); + wrap = count > 1; else { elog(ERROR, "unrecognized json wrapper %d", (int) wrapper); @@ -3957,14 +3977,14 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty, if (column_name) ereport(ERROR, (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM), - errmsg("JSON path expression for column \"%s\" should return single item without wrapper", + errmsg("JSON path expression for column \"%s\" must return single item when no wrapper is requested", column_name), - errhint("Use WITH WRAPPER clause to wrap SQL/JSON items into array."))); + errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array."))); else ereport(ERROR, (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM), - errmsg("JSON path expression in JSON_QUERY should return single item without wrapper"), - errhint("Use WITH WRAPPER clause to wrap SQL/JSON items into array."))); + errmsg("JSON path expression in JSON_QUERY must return single item when no wrapper is requested"), + errhint("Use the WITH WRAPPER clause to wrap SQL/JSON items into an array."))); } if (singleton) @@ -4021,12 +4041,12 @@ JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars, if (column_name) ereport(ERROR, (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM), - errmsg("JSON path expression for column \"%s\" should return single scalar item", + errmsg("JSON path expression for column \"%s\" must return single scalar item", column_name))); else ereport(ERROR, (errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM), - errmsg("JSON path expression in JSON_VALUE should return single scalar item"))); + errmsg("JSON path expression in JSON_VALUE must return single scalar item"))); } res = JsonValueListHead(&found); @@ -4045,12 +4065,12 @@ JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars, if (column_name) ereport(ERROR, (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED), - errmsg("JSON path expression for column \"%s\" should return single scalar item", + errmsg("JSON path expression for column \"%s\" must return single scalar item", column_name))); else ereport(ERROR, (errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED), - errmsg("JSON path expression in JSON_VALUE should return single scalar item"))); + errmsg("JSON path expression in JSON_VALUE must return single scalar item"))); } if (res->type == jbvNull) diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y index 8733a0eac6605..499745a8fef65 100644 --- a/src/backend/utils/adt/jsonpath_gram.y +++ b/src/backend/utils/adt/jsonpath_gram.y @@ -6,7 +6,7 @@ * * Transforms tokenized jsonpath into tree of JsonPathParseItem structs. * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/jsonpath_gram.y @@ -60,8 +60,10 @@ static bool makeItemLikeRegex(JsonPathParseItem *expr, %name-prefix="jsonpath_yy" %parse-param {JsonPathParseResult **result} %parse-param {struct Node *escontext} +%parse-param {yyscan_t yyscanner} %lex-param {JsonPathParseResult **result} %lex-param {struct Node *escontext} +%lex-param {yyscan_t yyscanner} %union { @@ -560,7 +562,7 @@ makeAny(int first, int last) static bool makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, - JsonPathString *flags, JsonPathParseItem ** result, + JsonPathString *flags, JsonPathParseItem **result, struct Node *escontext) { JsonPathParseItem *v = makeItemType(jpiLikeRegex); @@ -603,15 +605,15 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, } /* Convert flags to what pg_regcomp needs */ - if ( !jspConvertRegexFlags(v->value.like_regex.flags, &cflags, escontext)) - return false; + if (!jspConvertRegexFlags(v->value.like_regex.flags, &cflags, escontext)) + return false; /* check regex validity */ { - regex_t re_tmp; + regex_t re_tmp; pg_wchar *wpattern; - int wpattern_len; - int re_result; + int wpattern_len; + int re_result; wpattern = (pg_wchar *) palloc((pattern->len + 1) * sizeof(pg_wchar)); wpattern_len = pg_mb2wchar_with_len(pattern->val, @@ -621,7 +623,7 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern, if ((re_result = pg_regcomp(&re_tmp, wpattern, wpattern_len, cflags, DEFAULT_COLLATION_OID)) != REG_OKAY) { - char errMsg[100]; + char errMsg[100]; pg_regerror(re_result, &re_tmp, errMsg, sizeof(errMsg)); ereturn(escontext, false, diff --git a/src/backend/utils/adt/jsonpath_internal.h b/src/backend/utils/adt/jsonpath_internal.h index 6cd6d8b652da4..f78069857d02b 100644 --- a/src/backend/utils/adt/jsonpath_internal.h +++ b/src/backend/utils/adt/jsonpath_internal.h @@ -3,7 +3,7 @@ * jsonpath_internal.h * Private definitions for jsonpath scanner & parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/utils/adt/jsonpath_internal.h @@ -22,17 +22,25 @@ typedef struct JsonPathString int total; } JsonPathString; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif + #include "utils/jsonpath.h" #include "jsonpath_gram.h" #define YY_DECL extern int jsonpath_yylex(YYSTYPE *yylval_param, \ JsonPathParseResult **result, \ - struct Node *escontext) + struct Node *escontext, \ + yyscan_t yyscanner) YY_DECL; extern int jsonpath_yyparse(JsonPathParseResult **result, - struct Node *escontext); + struct Node *escontext, + yyscan_t yyscanner); extern void jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext, + yyscan_t yyscanner, const char *message); #endif /* JSONPATH_INTERNAL_H */ diff --git a/src/backend/utils/adt/jsonpath_scan.l b/src/backend/utils/adt/jsonpath_scan.l index 7acda7783752a..c7aab83eeb4f6 100644 --- a/src/backend/utils/adt/jsonpath_scan.l +++ b/src/backend/utils/adt/jsonpath_scan.l @@ -7,7 +7,7 @@ * Splits jsonpath string into tokens represented as JsonPathString structs. * Decodes unicode and hex escaped strings. * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/jsonpath_scan.l @@ -30,18 +30,16 @@ } %{ -static JsonPathString scanstring; - -/* Handles to the buffer that the lexer uses internally */ -static YY_BUFFER_STATE scanbufhandle; -static char *scanbuf; -static int scanbuflen; +struct jsonpath_yy_extra_type +{ + JsonPathString scanstring; +}; -static void addstring(bool init, char *s, int l); -static void addchar(bool init, char c); -static enum yytokentype checkKeyword(void); -static bool parseUnicode(char *s, int l, struct Node *escontext); -static bool parseHexChar(char *s, struct Node *escontext); +static void addstring(bool init, char *s, int l, yyscan_t yyscanner); +static void addchar(bool init, char c, yyscan_t yyscanner); +static enum yytokentype checkKeyword(yyscan_t yyscanner); +static bool parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner); +static bool parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner); /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ #undef fprintf @@ -65,6 +63,8 @@ fprintf_to_ereport(const char *fmt, const char *msg) %option noyywrap %option warn %option prefix="jsonpath_yy" +%option extra-type="struct jsonpath_yy_extra_type *" +%option reentrant %option bison-bridge %option noyyalloc %option noyyrealloc @@ -120,63 +120,63 @@ hex_fail \\x{hexdigit}{0,1} %% {other}+ { - addstring(false, yytext, yyleng); + addstring(false, yytext, yyleng, yyscanner); } {blank}+ { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; BEGIN INITIAL; - return checkKeyword(); + return checkKeyword(yyscanner); } \/\* { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; BEGIN xc; } ({special}|\") { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; yyless(0); BEGIN INITIAL; - return checkKeyword(); + return checkKeyword(yyscanner); } <> { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; BEGIN INITIAL; - return checkKeyword(); + return checkKeyword(yyscanner); } -\\b { addchar(false, '\b'); } +\\b { addchar(false, '\b', yyscanner); } -\\f { addchar(false, '\f'); } +\\f { addchar(false, '\f', yyscanner); } -\\n { addchar(false, '\n'); } +\\n { addchar(false, '\n', yyscanner); } -\\r { addchar(false, '\r'); } +\\r { addchar(false, '\r', yyscanner); } -\\t { addchar(false, '\t'); } +\\t { addchar(false, '\t', yyscanner); } -\\v { addchar(false, '\v'); } +\\v { addchar(false, '\v', yyscanner); } {unicode}+ { - if (!parseUnicode(yytext, yyleng, escontext)) + if (!parseUnicode(yytext, yyleng, escontext, yyscanner)) yyterminate(); } {hex_char} { - if (!parseHexChar(yytext, escontext)) + if (!parseHexChar(yytext, escontext, yyscanner)) yyterminate(); } {unicode}*{unicodefail} { - jsonpath_yyerror(NULL, escontext, + jsonpath_yyerror(NULL, escontext, yyscanner, "invalid Unicode escape sequence"); yyterminate(); } {hex_fail} { - jsonpath_yyerror(NULL, escontext, + jsonpath_yyerror(NULL, escontext, yyscanner, "invalid hexadecimal character sequence"); yyterminate(); } @@ -184,37 +184,37 @@ hex_fail \\x{hexdigit}{0,1} {unicode}+\\ { /* throw back the \\, and treat as unicode */ yyless(yyleng - 1); - if (!parseUnicode(yytext, yyleng, escontext)) + if (!parseUnicode(yytext, yyleng, escontext, yyscanner)) yyterminate(); } -\\. { addchar(false, yytext[1]); } +\\. { addchar(false, yytext[1], yyscanner); } \\ { - jsonpath_yyerror(NULL, escontext, - "unexpected end after backslash"); - yyterminate(); + jsonpath_yyerror(NULL, escontext, yyscanner, + "unexpected end after backslash"); + yyterminate(); } <> { - jsonpath_yyerror(NULL, escontext, - "unterminated quoted string"); - yyterminate(); + jsonpath_yyerror(NULL, escontext, yyscanner, + "unterminated quoted string"); + yyterminate(); } \" { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; BEGIN INITIAL; return STRING_P; } \" { - yylval->str = scanstring; + yylval->str = yyextra->scanstring; BEGIN INITIAL; return VARIABLE_P; } -[^\\\"]+ { addstring(false, yytext, yyleng); } +[^\\\"]+ { addstring(false, yytext, yyleng, yyscanner); } \*\/ { BEGIN INITIAL; } @@ -223,9 +223,8 @@ hex_fail \\x{hexdigit}{0,1} \* { } <> { - jsonpath_yyerror( - NULL, escontext, - "unexpected end of comment"); + jsonpath_yyerror(NULL, escontext, yyscanner, + "unexpected end of comment"); yyterminate(); } \&\& { return AND_P; } @@ -251,14 +250,14 @@ hex_fail \\x{hexdigit}{0,1} \> { return GREATER_P; } \${other}+ { - addstring(true, yytext + 1, yyleng - 1); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext + 1, yyleng - 1, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return VARIABLE_P; } \$\" { - addchar(true, '\0'); + addchar(true, '\0', yyscanner); BEGIN xvq; } @@ -267,89 +266,85 @@ hex_fail \\x{hexdigit}{0,1} {blank}+ { /* ignore */ } \/\* { - addchar(true, '\0'); + addchar(true, '\0', yyscanner); BEGIN xc; } {real} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return NUMERIC_P; } {decimal} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return NUMERIC_P; } {decinteger} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return INT_P; } {hexinteger} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return INT_P; } {octinteger} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return INT_P; } {bininteger} { - addstring(true, yytext, yyleng); - addchar(false, '\0'); - yylval->str = scanstring; + addstring(true, yytext, yyleng, yyscanner); + addchar(false, '\0', yyscanner); + yylval->str = yyextra->scanstring; return INT_P; } {realfail} { - jsonpath_yyerror( - NULL, escontext, - "invalid numeric literal"); + jsonpath_yyerror(NULL, escontext, yyscanner, + "invalid numeric literal"); yyterminate(); } {decinteger_junk} { - jsonpath_yyerror( - NULL, escontext, - "trailing junk after numeric literal"); + jsonpath_yyerror(NULL, escontext, yyscanner, + "trailing junk after numeric literal"); yyterminate(); } {decimal_junk} { - jsonpath_yyerror( - NULL, escontext, - "trailing junk after numeric literal"); + jsonpath_yyerror(NULL, escontext, yyscanner, + "trailing junk after numeric literal"); yyterminate(); } {real_junk} { - jsonpath_yyerror( - NULL, escontext, - "trailing junk after numeric literal"); + jsonpath_yyerror(NULL, escontext, yyscanner, + "trailing junk after numeric literal"); yyterminate(); } \" { - addchar(true, '\0'); + addchar(true, '\0', yyscanner); BEGIN xq; } \\ { yyless(0); - addchar(true, '\0'); + addchar(true, '\0', yyscanner); BEGIN xnq; } {other}+ { - addstring(true, yytext, yyleng); + addstring(true, yytext, yyleng, yyscanner); BEGIN xnq; } @@ -359,10 +354,18 @@ hex_fail \\x{hexdigit}{0,1} /* LCOV_EXCL_STOP */ +/* see scan.l */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + void jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext, + yyscan_t yyscanner, const char *message) { + struct yyguts_t *yyg = (struct yyguts_t *) yyscanner; /* needed for yytext + * macro */ + /* don't overwrite escontext if it's already been set */ if (SOFT_ERROR_OCCURRED(escontext)) return; @@ -371,14 +374,14 @@ jsonpath_yyerror(JsonPathParseResult **result, struct Node *escontext, { errsave(escontext, (errcode(ERRCODE_SYNTAX_ERROR), - /* translator: %s is typically "syntax error" */ + /* translator: %s is typically "syntax error" */ errmsg("%s at end of jsonpath input", _(message)))); } else { errsave(escontext, (errcode(ERRCODE_SYNTAX_ERROR), - /* translator: first %s is typically "syntax error" */ + /* translator: first %s is typically "syntax error" */ errmsg("%s at or near \"%s\" of jsonpath input", _(message), yytext))); } @@ -397,63 +400,65 @@ typedef struct JsonPathKeyword * alphabetical order */ static const JsonPathKeyword keywords[] = { - { 2, false, IS_P, "is"}, - { 2, false, TO_P, "to"}, - { 3, false, ABS_P, "abs"}, - { 3, false, LAX_P, "lax"}, - { 4, false, DATE_P, "date"}, - { 4, false, FLAG_P, "flag"}, - { 4, false, LAST_P, "last"}, - { 4, true, NULL_P, "null"}, - { 4, false, SIZE_P, "size"}, - { 4, false, TIME_P, "time"}, - { 4, true, TRUE_P, "true"}, - { 4, false, TYPE_P, "type"}, - { 4, false, WITH_P, "with"}, - { 5, true, FALSE_P, "false"}, - { 5, false, FLOOR_P, "floor"}, - { 6, false, BIGINT_P, "bigint"}, - { 6, false, DOUBLE_P, "double"}, - { 6, false, EXISTS_P, "exists"}, - { 6, false, NUMBER_P, "number"}, - { 6, false, STARTS_P, "starts"}, - { 6, false, STRICT_P, "strict"}, - { 6, false, STRINGFUNC_P, "string"}, - { 7, false, BOOLEAN_P, "boolean"}, - { 7, false, CEILING_P, "ceiling"}, - { 7, false, DECIMAL_P, "decimal"}, - { 7, false, INTEGER_P, "integer"}, - { 7, false, TIME_TZ_P, "time_tz"}, - { 7, false, UNKNOWN_P, "unknown"}, - { 8, false, DATETIME_P, "datetime"}, - { 8, false, KEYVALUE_P, "keyvalue"}, - { 9, false, TIMESTAMP_P, "timestamp"}, - { 10,false, LIKE_REGEX_P, "like_regex"}, - { 12,false, TIMESTAMP_TZ_P, "timestamp_tz"}, + {2, false, IS_P, "is"}, + {2, false, TO_P, "to"}, + {3, false, ABS_P, "abs"}, + {3, false, LAX_P, "lax"}, + {4, false, DATE_P, "date"}, + {4, false, FLAG_P, "flag"}, + {4, false, LAST_P, "last"}, + {4, true, NULL_P, "null"}, + {4, false, SIZE_P, "size"}, + {4, false, TIME_P, "time"}, + {4, true, TRUE_P, "true"}, + {4, false, TYPE_P, "type"}, + {4, false, WITH_P, "with"}, + {5, true, FALSE_P, "false"}, + {5, false, FLOOR_P, "floor"}, + {6, false, BIGINT_P, "bigint"}, + {6, false, DOUBLE_P, "double"}, + {6, false, EXISTS_P, "exists"}, + {6, false, NUMBER_P, "number"}, + {6, false, STARTS_P, "starts"}, + {6, false, STRICT_P, "strict"}, + {6, false, STRINGFUNC_P, "string"}, + {7, false, BOOLEAN_P, "boolean"}, + {7, false, CEILING_P, "ceiling"}, + {7, false, DECIMAL_P, "decimal"}, + {7, false, INTEGER_P, "integer"}, + {7, false, TIME_TZ_P, "time_tz"}, + {7, false, UNKNOWN_P, "unknown"}, + {8, false, DATETIME_P, "datetime"}, + {8, false, KEYVALUE_P, "keyvalue"}, + {9, false, TIMESTAMP_P, "timestamp"}, + {10, false, LIKE_REGEX_P, "like_regex"}, + {12, false, TIMESTAMP_TZ_P, "timestamp_tz"}, }; -/* Check if current scanstring value is a keyword */ +/* + * Check if current scanstring value is a keyword + */ static enum yytokentype -checkKeyword() +checkKeyword(yyscan_t yyscanner) { int res = IDENT_P; int diff; - const JsonPathKeyword *StopLow = keywords, - *StopHigh = keywords + lengthof(keywords), - *StopMiddle; + const JsonPathKeyword *StopLow = keywords, + *StopHigh = keywords + lengthof(keywords), + *StopMiddle; - if (scanstring.len > keywords[lengthof(keywords) - 1].len) + if (yyextra->scanstring.len > keywords[lengthof(keywords) - 1].len) return res; while (StopLow < StopHigh) { StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); - if (StopMiddle->len == scanstring.len) - diff = pg_strncasecmp(StopMiddle->keyword, scanstring.val, - scanstring.len); + if (StopMiddle->len == yyextra->scanstring.len) + diff = pg_strncasecmp(StopMiddle->keyword, yyextra->scanstring.val, + yyextra->scanstring.len); else - diff = StopMiddle->len - scanstring.len; + diff = StopMiddle->len - yyextra->scanstring.len; if (diff < 0) StopLow = StopMiddle + 1; @@ -462,8 +467,8 @@ checkKeyword() else { if (StopMiddle->lowercase) - diff = strncmp(StopMiddle->keyword, scanstring.val, - scanstring.len); + diff = strncmp(StopMiddle->keyword, yyextra->scanstring.val, + yyextra->scanstring.len); if (diff == 0) res = StopMiddle->val; @@ -475,106 +480,78 @@ checkKeyword() return res; } -/* - * Called before any actual parsing is done - */ -static void -jsonpath_scanner_init(const char *str, int slen) -{ - if (slen <= 0) - slen = strlen(str); - - /* - * Might be left over after ereport() - */ - yy_init_globals(); - - /* - * Make a scan buffer with special termination needed by flex. - */ - - scanbuflen = slen; - scanbuf = palloc(slen + 2); - memcpy(scanbuf, str, slen); - scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); - - BEGIN(INITIAL); -} - - -/* - * Called after parsing is done to clean up after jsonpath_scanner_init() - */ -static void -jsonpath_scanner_finish(void) -{ - yy_delete_buffer(scanbufhandle); - pfree(scanbuf); -} - /* * Resize scanstring so that it can append string of given length. * Reinitialize if required. */ static void -resizeString(bool init, int appendLen) +resizeString(bool init, int appendLen, yyscan_t yyscanner) { if (init) { - scanstring.total = Max(32, appendLen); - scanstring.val = (char *) palloc(scanstring.total); - scanstring.len = 0; + yyextra->scanstring.total = Max(32, appendLen); + yyextra->scanstring.val = (char *) palloc(yyextra->scanstring.total); + yyextra->scanstring.len = 0; } else { - if (scanstring.len + appendLen >= scanstring.total) + if (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total) { - while (scanstring.len + appendLen >= scanstring.total) - scanstring.total *= 2; - scanstring.val = repalloc(scanstring.val, scanstring.total); + while (yyextra->scanstring.len + appendLen >= yyextra->scanstring.total) + yyextra->scanstring.total *= 2; + yyextra->scanstring.val = repalloc(yyextra->scanstring.val, yyextra->scanstring.total); } } } /* Add set of bytes at "s" of length "l" to scanstring */ static void -addstring(bool init, char *s, int l) +addstring(bool init, char *s, int l, yyscan_t yyscanner) { - resizeString(init, l + 1); - memcpy(scanstring.val + scanstring.len, s, l); - scanstring.len += l; + resizeString(init, l + 1, yyscanner); + memcpy(yyextra->scanstring.val + yyextra->scanstring.len, s, l); + yyextra->scanstring.len += l; } /* Add single byte "c" to scanstring */ static void -addchar(bool init, char c) +addchar(bool init, char c, yyscan_t yyscanner) { - resizeString(init, 1); - scanstring.val[scanstring.len] = c; + resizeString(init, 1, yyscanner); + yyextra->scanstring.val[yyextra->scanstring.len] = c; if (c != '\0') - scanstring.len++; + yyextra->scanstring.len++; } /* Interface to jsonpath parser */ JsonPathParseResult * parsejsonpath(const char *str, int len, struct Node *escontext) { - JsonPathParseResult *parseresult; + JsonPathParseResult *parseresult; + yyscan_t scanner; + struct jsonpath_yy_extra_type yyext; + + if (jsonpath_yylex_init(&scanner) != 0) + elog(ERROR, "yylex_init() failed: %m"); - jsonpath_scanner_init(str, len); + yyset_extra(&yyext, scanner); - if (jsonpath_yyparse((void *) &parseresult, escontext) != 0) - jsonpath_yyerror(NULL, escontext, "invalid input"); /* shouldn't happen */ + if (len <= 0) + len = strlen(str); - jsonpath_scanner_finish(); + jsonpath_yy_scan_bytes(str, len, scanner); + + if (jsonpath_yyparse(&parseresult, escontext, scanner) != 0) + jsonpath_yyerror(NULL, escontext, scanner, "invalid input"); /* shouldn't happen */ + + jsonpath_yylex_destroy(scanner); return parseresult; } /* Turn hex character into integer */ static bool -hexval(char c, int *result, struct Node *escontext) +hexval(char c, int *result, struct Node *escontext, yyscan_t yyscanner) { if (c >= '0' && c <= '9') { @@ -591,13 +568,13 @@ hexval(char c, int *result, struct Node *escontext) *result = c - 'A' + 0xA; return true; } - jsonpath_yyerror(NULL, escontext, "invalid hexadecimal digit"); + jsonpath_yyerror(NULL, escontext, yyscanner, "invalid hexadecimal digit"); return false; } /* Add given unicode character to scanstring */ static bool -addUnicodeChar(int ch, struct Node *escontext) +addUnicodeChar(int ch, struct Node *escontext, yyscan_t yyscanner) { if (ch == 0) { @@ -605,7 +582,7 @@ addUnicodeChar(int ch, struct Node *escontext) ereturn(escontext, false, (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), errmsg("unsupported Unicode escape sequence"), - errdetail("\\u0000 cannot be converted to text."))); + errdetail("\\u0000 cannot be converted to text."))); } else { @@ -617,20 +594,20 @@ addUnicodeChar(int ch, struct Node *escontext) * more detailed errors. */ - if (! escontext || ! IsA(escontext, ErrorSaveContext)) + if (!escontext || !IsA(escontext, ErrorSaveContext)) pg_unicode_to_server(ch, (unsigned char *) cbuf); else if (!pg_unicode_to_server_noerror(ch, (unsigned char *) cbuf)) ereturn(escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("could not convert Unicode to server encoding"))); - addstring(false, cbuf, strlen(cbuf)); + addstring(false, cbuf, strlen(cbuf), yyscanner); } return true; } /* Add unicode character, processing any surrogate pairs */ static bool -addUnicode(int ch, int *hi_surrogate, struct Node *escontext) +addUnicode(int ch, int *hi_surrogate, struct Node *escontext, yyscan_t yyscanner) { if (is_utf16_surrogate_first(ch)) { @@ -663,7 +640,7 @@ addUnicode(int ch, int *hi_surrogate, struct Node *escontext) "surrogate."))); } - return addUnicodeChar(ch, escontext); + return addUnicodeChar(ch, escontext, yyscanner); } /* @@ -671,7 +648,7 @@ addUnicode(int ch, int *hi_surrogate, struct Node *escontext) * src/backend/utils/adt/json.c */ static bool -parseUnicode(char *s, int l, struct Node *escontext) +parseUnicode(char *s, int l, struct Node *escontext, yyscan_t yyscanner) { int i = 2; int hi_surrogate = -1; @@ -679,29 +656,30 @@ parseUnicode(char *s, int l, struct Node *escontext) for (i = 2; i < l; i += 2) /* skip '\u' */ { int ch = 0; - int j, si; + int j, + si; - if (s[i] == '{') /* parse '\u{XX...}' */ + if (s[i] == '{') /* parse '\u{XX...}' */ { while (s[++i] != '}' && i < l) { - if (!hexval(s[i], &si, escontext)) + if (!hexval(s[i], &si, escontext, yyscanner)) return false; ch = (ch << 4) | si; } - i++; /* skip '}' */ + i++; /* skip '}' */ } - else /* parse '\uXXXX' */ + else /* parse '\uXXXX' */ { for (j = 0; j < 4 && i < l; j++) { - if (!hexval(s[i++], &si, escontext)) + if (!hexval(s[i++], &si, escontext, yyscanner)) return false; ch = (ch << 4) | si; } } - if (! addUnicode(ch, &hi_surrogate, escontext)) + if (!addUnicode(ch, &hi_surrogate, escontext, yyscanner)) return false; } @@ -719,17 +697,20 @@ parseUnicode(char *s, int l, struct Node *escontext) /* Parse sequence of hex-encoded characters */ static bool -parseHexChar(char *s, struct Node *escontext) +parseHexChar(char *s, struct Node *escontext, yyscan_t yyscanner) { - int s2, s3, ch; - if (!hexval(s[2], &s2, escontext)) + int s2, + s3, + ch; + + if (!hexval(s[2], &s2, escontext, yyscanner)) return false; - if (!hexval(s[3], &s3, escontext)) + if (!hexval(s[3], &s3, escontext, yyscanner)) return false; ch = (s2 << 4) | s3; - return addUnicodeChar(ch, escontext); + return addUnicodeChar(ch, escontext, yyscanner); } /* @@ -738,13 +719,13 @@ parseHexChar(char *s, struct Node *escontext) */ void * -jsonpath_yyalloc(yy_size_t bytes) +jsonpath_yyalloc(yy_size_t bytes, yyscan_t yyscanner) { return palloc(bytes); } void * -jsonpath_yyrealloc(void *ptr, yy_size_t bytes) +jsonpath_yyrealloc(void *ptr, yy_size_t bytes, yyscan_t yyscanner) { if (ptr) return repalloc(ptr, bytes); @@ -753,7 +734,7 @@ jsonpath_yyrealloc(void *ptr, yy_size_t bytes) } void -jsonpath_yyfree(void *ptr) +jsonpath_yyfree(void *ptr, yyscan_t yyscanner) { if (ptr) pfree(ptr); diff --git a/src/backend/utils/adt/levenshtein.c b/src/backend/utils/adt/levenshtein.c index 91ffdc0042230..15a90f6f50c8a 100644 --- a/src/backend/utils/adt/levenshtein.c +++ b/src/backend/utils/adt/levenshtein.c @@ -16,7 +16,7 @@ * PHP 4.0.6 distribution for inspiration. Configurable penalty costs * extension is introduced by Volkan YAZICI (7/95). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -33,18 +33,18 @@ static int SB_MatchText(const char *t, int tlen, const char *p, int plen, - pg_locale_t locale, bool locale_is_c); + pg_locale_t locale); static text *SB_do_like_escape(text *pat, text *esc); static int MB_MatchText(const char *t, int tlen, const char *p, int plen, - pg_locale_t locale, bool locale_is_c); + pg_locale_t locale); static text *MB_do_like_escape(text *pat, text *esc); static int UTF8_MatchText(const char *t, int tlen, const char *p, int plen, - pg_locale_t locale, bool locale_is_c); + pg_locale_t locale); static int SB_IMatchText(const char *t, int tlen, const char *p, int plen, - pg_locale_t locale, bool locale_is_c); + pg_locale_t locale); static int GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation); static int Generic_Text_IC_like(text *str, text *pat, Oid collation); @@ -91,14 +91,14 @@ wchareq(const char *p1, const char *p2) * fold-on-the-fly processing, however. */ static char -SB_lower_char(unsigned char c, pg_locale_t locale, bool locale_is_c) +SB_lower_char(unsigned char c, pg_locale_t locale) { - if (locale_is_c) + if (locale->ctype_is_c) return pg_ascii_tolower(c); - else if (locale) - return tolower_l(c, locale->info.lt); - else + else if (locale->is_default) return pg_tolower(c); + else + return tolower_l(c, locale->info.lt); } @@ -131,7 +131,7 @@ SB_lower_char(unsigned char c, pg_locale_t locale, bool locale_is_c) #include "like_match.c" /* setup to compile like_match.c for single byte case insensitive matches */ -#define MATCH_LOWER(t) SB_lower_char((unsigned char) (t), locale, locale_is_c) +#define MATCH_LOWER(t, locale) SB_lower_char((unsigned char) (t), locale) #define NextChar(p, plen) NextByte((p), (plen)) #define MatchText SB_IMatchText @@ -149,22 +149,28 @@ SB_lower_char(unsigned char c, pg_locale_t locale, bool locale_is_c) static inline int GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation) { - if (collation && !lc_ctype_is_c(collation)) - { - pg_locale_t locale = pg_newlocale_from_collation(collation); + pg_locale_t locale; - if (!pg_locale_deterministic(locale)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("nondeterministic collations are not supported for LIKE"))); + if (!OidIsValid(collation)) + { + /* + * This typically means that the parser could not resolve a conflict + * of implicit collations, so report it that way. + */ + ereport(ERROR, + (errcode(ERRCODE_INDETERMINATE_COLLATION), + errmsg("could not determine which collation to use for LIKE"), + errhint("Use the COLLATE clause to set the collation explicitly."))); } + locale = pg_newlocale_from_collation(collation); + if (pg_database_encoding_max_length() == 1) - return SB_MatchText(s, slen, p, plen, 0, true); + return SB_MatchText(s, slen, p, plen, locale); else if (GetDatabaseEncoding() == PG_UTF8) - return UTF8_MatchText(s, slen, p, plen, 0, true); + return UTF8_MatchText(s, slen, p, plen, locale); else - return MB_MatchText(s, slen, p, plen, 0, true); + return MB_MatchText(s, slen, p, plen, locale); } static inline int @@ -174,8 +180,7 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) *p; int slen, plen; - pg_locale_t locale = 0; - bool locale_is_c = false; + pg_locale_t locale; if (!OidIsValid(collation)) { @@ -189,12 +194,9 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) errhint("Use the COLLATE clause to set the collation explicitly."))); } - if (lc_ctype_is_c(collation)) - locale_is_c = true; - else - locale = pg_newlocale_from_collation(collation); + locale = pg_newlocale_from_collation(collation); - if (!pg_locale_deterministic(locale)) + if (!locale->deterministic) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for ILIKE"))); @@ -207,7 +209,7 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) * way. */ - if (pg_database_encoding_max_length() > 1 || (locale && locale->provider == COLLPROVIDER_ICU)) + if (pg_database_encoding_max_length() > 1 || (locale->provider == COLLPROVIDER_ICU)) { pat = DatumGetTextPP(DirectFunctionCall1Coll(lower, collation, PointerGetDatum(pat))); @@ -218,9 +220,9 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) s = VARDATA_ANY(str); slen = VARSIZE_ANY_EXHDR(str); if (GetDatabaseEncoding() == PG_UTF8) - return UTF8_MatchText(s, slen, p, plen, 0, true); + return UTF8_MatchText(s, slen, p, plen, 0); else - return MB_MatchText(s, slen, p, plen, 0, true); + return MB_MatchText(s, slen, p, plen, 0); } else { @@ -228,7 +230,7 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) plen = VARSIZE_ANY_EXHDR(pat); s = VARDATA_ANY(str); slen = VARSIZE_ANY_EXHDR(str); - return SB_IMatchText(s, slen, p, plen, locale, locale_is_c); + return SB_IMatchText(s, slen, p, plen, locale); } } @@ -336,7 +338,7 @@ bytealike(PG_FUNCTION_ARGS) p = VARDATA_ANY(pat); plen = VARSIZE_ANY_EXHDR(pat); - result = (SB_MatchText(s, slen, p, plen, 0, true) == LIKE_TRUE); + result = (SB_MatchText(s, slen, p, plen, 0) == LIKE_TRUE); PG_RETURN_BOOL(result); } @@ -357,7 +359,7 @@ byteanlike(PG_FUNCTION_ARGS) p = VARDATA_ANY(pat); plen = VARSIZE_ANY_EXHDR(pat); - result = (SB_MatchText(s, slen, p, plen, 0, true) != LIKE_TRUE); + result = (SB_MatchText(s, slen, p, plen, 0) != LIKE_TRUE); PG_RETURN_BOOL(result); } diff --git a/src/backend/utils/adt/like_match.c b/src/backend/utils/adt/like_match.c index f2990edff7ed3..892f8a745ea43 100644 --- a/src/backend/utils/adt/like_match.c +++ b/src/backend/utils/adt/like_match.c @@ -16,7 +16,7 @@ * do_like_escape - name of function if wanted - needs CHAREQ and CopyAdvChar * MATCH_LOWER - define for case (4) to specify case folding for 1-byte chars * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/like_match.c @@ -71,14 +71,13 @@ */ #ifdef MATCH_LOWER -#define GETCHAR(t) MATCH_LOWER(t) +#define GETCHAR(t, locale) MATCH_LOWER(t, locale) #else -#define GETCHAR(t) (t) +#define GETCHAR(t, locale) (t) #endif static int -MatchText(const char *t, int tlen, const char *p, int plen, - pg_locale_t locale, bool locale_is_c) +MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale) { /* Fast path for match-everything pattern */ if (plen == 1 && *p == '%') @@ -106,7 +105,7 @@ MatchText(const char *t, int tlen, const char *p, int plen, ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), errmsg("LIKE pattern must not end with escape character"))); - if (GETCHAR(*p) != GETCHAR(*t)) + if (GETCHAR(*p, locale) != GETCHAR(*t, locale)) return LIKE_FALSE; } else if (*p == '%') @@ -158,7 +157,9 @@ MatchText(const char *t, int tlen, const char *p, int plen, * the first pattern byte to each text byte to avoid recursing * more than we have to. This fact also guarantees that we don't * have to consider a match to the zero-length substring at the - * end of the text. + * end of the text. With a nondeterministic collation, we can't + * rely on the first bytes being equal, so we have to recurse in + * any case. */ if (*p == '\\') { @@ -166,17 +167,16 @@ MatchText(const char *t, int tlen, const char *p, int plen, ereport(ERROR, (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), errmsg("LIKE pattern must not end with escape character"))); - firstpat = GETCHAR(p[1]); + firstpat = GETCHAR(p[1], locale); } else - firstpat = GETCHAR(*p); + firstpat = GETCHAR(*p, locale); while (tlen > 0) { - if (GETCHAR(*t) == firstpat) + if (GETCHAR(*t, locale) == firstpat || (locale && !locale->deterministic)) { - int matched = MatchText(t, tlen, p, plen, - locale, locale_is_c); + int matched = MatchText(t, tlen, p, plen, locale); if (matched != LIKE_FALSE) return matched; /* TRUE or ABORT */ @@ -198,7 +198,151 @@ MatchText(const char *t, int tlen, const char *p, int plen, NextByte(p, plen); continue; } - else if (GETCHAR(*p) != GETCHAR(*t)) + else if (locale && !locale->deterministic) + { + /* + * For nondeterministic locales, we find the next substring of the + * pattern that does not contain wildcards and try to find a + * matching substring in the text. Crucially, we cannot do this + * character by character, as in the normal case, but must do it + * substring by substring, partitioned by the wildcard characters. + * (This is per SQL standard.) + */ + const char *p1; + size_t p1len; + const char *t1; + size_t t1len; + bool found_escape; + const char *subpat; + size_t subpatlen; + char *buf = NULL; + + /* + * Determine next substring of pattern without wildcards. p is + * the start of the subpattern, p1 is one past the last byte. Also + * track if we found an escape character. + */ + p1 = p; + p1len = plen; + found_escape = false; + while (p1len > 0) + { + if (*p1 == '\\') + { + found_escape = true; + NextByte(p1, p1len); + if (p1len == 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE), + errmsg("LIKE pattern must not end with escape character"))); + } + else if (*p1 == '_' || *p1 == '%') + break; + NextByte(p1, p1len); + } + + /* + * If we found an escape character, then make an unescaped copy of + * the subpattern. + */ + if (found_escape) + { + char *b; + + b = buf = palloc(p1 - p); + for (const char *c = p; c < p1; c++) + { + if (*c == '\\') + ; + else + *(b++) = *c; + } + + subpat = buf; + subpatlen = b - buf; + } + else + { + subpat = p; + subpatlen = p1 - p; + } + + /* + * Shortcut: If this is the end of the pattern, then the rest of + * the text has to match the rest of the pattern. + */ + if (p1len == 0) + { + int cmp; + + cmp = pg_strncoll(subpat, subpatlen, t, tlen, locale); + + if (buf) + pfree(buf); + if (cmp == 0) + return LIKE_TRUE; + else + return LIKE_FALSE; + } + + /* + * Now build a substring of the text and try to match it against + * the subpattern. t is the start of the text, t1 is one past the + * last byte. We start with a zero-length string. + */ + t1 = t; + t1len = tlen; + for (;;) + { + int cmp; + + CHECK_FOR_INTERRUPTS(); + + cmp = pg_strncoll(subpat, subpatlen, t, (t1 - t), locale); + + /* + * If we found a match, we have to test if the rest of pattern + * can match against the rest of the string. Otherwise we + * have to continue here try matching with a longer substring. + * (This is similar to the recursion for the '%' wildcard + * above.) + * + * Note that we can't just wind forward p and t and continue + * with the main loop. This would fail for example with + * + * U&'\0061\0308bc' LIKE U&'\00E4_c' COLLATE ignore_accents + * + * You'd find that t=\0061 matches p=\00E4, but then the rest + * won't match; but t=\0061\0308 also matches p=\00E4, and + * then the rest will match. + */ + if (cmp == 0) + { + int matched = MatchText(t1, t1len, p1, p1len, locale); + + if (matched == LIKE_TRUE) + { + if (buf) + pfree(buf); + return matched; + } + } + + /* + * Didn't match. If we used up the whole text, then the match + * fails. Otherwise, try again with a longer substring. + */ + if (t1len == 0) + { + if (buf) + pfree(buf); + return LIKE_FALSE; + } + else + NextChar(t1, t1len); + } + } + else if (GETCHAR(*p, locale) != GETCHAR(*t, locale)) { /* non-wildcard pattern char fails to match text char */ return LIKE_FALSE; diff --git a/src/backend/utils/adt/like_support.c b/src/backend/utils/adt/like_support.c index 2635050861f97..8fdc677371f4d 100644 --- a/src/backend/utils/adt/like_support.c +++ b/src/backend/utils/adt/like_support.c @@ -23,7 +23,7 @@ * from LIKE to indexscan limits rather harder than one might think ... * but that's the basic idea.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -100,7 +100,7 @@ static Selectivity regex_selectivity(const char *patt, int pattlen, bool case_insensitive, int fixed_prefix_len); static int pattern_char_isalpha(char c, bool is_multibyte, - pg_locale_t locale, bool locale_is_c); + pg_locale_t locale); static Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation); static Datum string_to_datum(const char *str, Oid datatype); @@ -272,22 +272,6 @@ match_pattern_prefix(Node *leftop, return NIL; patt = (Const *) rightop; - /* - * Not supported if the expression collation is nondeterministic. The - * optimized equality or prefix tests use bytewise comparisons, which is - * not consistent with nondeterministic collations. The actual - * pattern-matching implementation functions will later error out that - * pattern-matching is not supported with nondeterministic collations. (We - * could also error out here, but by doing it later we get more precise - * error messages.) (It should be possible to support at least - * Pattern_Prefix_Exact, but no point as long as the actual - * pattern-matching implementations don't support it.) - * - * expr_coll is not set for a non-collation-aware data type such as bytea. - */ - if (expr_coll && !get_collation_isdeterministic(expr_coll)) - return NIL; - /* * Try to extract a fixed prefix from the pattern. */ @@ -404,6 +388,8 @@ match_pattern_prefix(Node *leftop, { if (!op_in_opfamily(eqopr, opfamily)) return NIL; + if (indexcollation != expr_coll) + return NIL; expr = make_opclause(eqopr, BOOLOID, false, (Expr *) leftop, (Expr *) prefix, InvalidOid, indexcollation); @@ -411,6 +397,17 @@ match_pattern_prefix(Node *leftop, return result; } + /* + * Anything other than Pattern_Prefix_Exact is not supported if the + * expression collation is nondeterministic. The optimized equality or + * prefix tests use bytewise comparisons, which is not consistent with + * nondeterministic collations. + * + * expr_coll is not set for a non-collation-aware data type such as bytea. + */ + if (expr_coll && !get_collation_isdeterministic(expr_coll)) + return NIL; + /* * Otherwise, we have a nonempty required prefix of the values. Some * opclasses support prefix checks directly, otherwise we'll try to @@ -433,7 +430,7 @@ match_pattern_prefix(Node *leftop, * collation. */ if (collation_aware && - !lc_collate_is_c(indexcollation)) + !pg_newlocale_from_collation(indexcollation)->collate_is_c) return NIL; /* @@ -1000,7 +997,6 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation, match_pos; bool is_multibyte = (pg_database_encoding_max_length() > 1); pg_locale_t locale = 0; - bool locale_is_c = false; /* the right-hand const is type text or bytea */ Assert(typeid == BYTEAOID || typeid == TEXTOID); @@ -1024,11 +1020,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation, errhint("Use the COLLATE clause to set the collation explicitly."))); } - /* If case-insensitive, we need locale info */ - if (lc_ctype_is_c(collation)) - locale_is_c = true; - else - locale = pg_newlocale_from_collation(collation); + locale = pg_newlocale_from_collation(collation); } if (typeid != BYTEAOID) @@ -1065,7 +1057,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation, /* Stop if case-varying character (it's sort of a wildcard) */ if (case_insensitive && - pattern_char_isalpha(patt[pos], is_multibyte, locale, locale_is_c)) + pattern_char_isalpha(patt[pos], is_multibyte, locale)) break; match[match_pos++] = patt[pos]; @@ -1499,19 +1491,17 @@ regex_selectivity(const char *patt, int pattlen, bool case_insensitive, */ static int pattern_char_isalpha(char c, bool is_multibyte, - pg_locale_t locale, bool locale_is_c) + pg_locale_t locale) { - if (locale_is_c) + if (locale->ctype_is_c) return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); else if (is_multibyte && IS_HIGHBIT_SET(c)) return true; - else if (locale && locale->provider == COLLPROVIDER_ICU) + else if (locale->provider != COLLPROVIDER_LIBC) return IS_HIGHBIT_SET(c) || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - else if (locale && locale->provider == COLLPROVIDER_LIBC) - return isalpha_l((unsigned char) c, locale->info.lt); else - return isalpha((unsigned char) c); + return isalpha_l((unsigned char) c, locale->info.lt); } @@ -1603,7 +1593,7 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation) else workstr = TextDatumGetCString(str_const->constvalue); len = strlen(workstr); - if (lc_collate_is_c(collation) || len == 0) + if (len == 0 || pg_newlocale_from_collation(collation)->collate_is_c) cmpstr = str_const->constvalue; else { diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index e790f856ab370..00e67fb46d074 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -3,7 +3,7 @@ * lockfuncs.c * Functions for SQL access to various lock-manager capabilities. * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/lockfuncs.c @@ -153,7 +153,7 @@ pg_lock_status(PG_FUNCTION_ARGS) * out as a result set. */ mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status)); - funcctx->user_fctx = (void *) mystatus; + funcctx->user_fctx = mystatus; mystatus->lockData = GetLockStatusData(); mystatus->currIdx = 0; diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c index ae4caedef5054..3644e9735f5d0 100644 --- a/src/backend/utils/adt/mac.c +++ b/src/backend/utils/adt/mac.c @@ -3,7 +3,7 @@ * mac.c * PostgreSQL type definitions for 6 byte, EUI-48, MAC addresses. * - * Portions Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1998-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/mac.c @@ -430,13 +430,11 @@ macaddr_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card > 100000.0) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "macaddr_abbrev: estimation ends at cardinality %f" " after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif uss->estimating = false; return false; } @@ -449,23 +447,19 @@ macaddr_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card < uss->input_count / 2000.0 + 0.5) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "macaddr_abbrev: aborting abbreviation at cardinality %f" " below threshold %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count / 2000.0 + 0.5, uss->input_count, memtupcount); -#endif return true; } -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "macaddr_abbrev: cardinality %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif return false; } diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c index 996d912e8d06c..08e41ba4eeabc 100644 --- a/src/backend/utils/adt/mac8.c +++ b/src/backend/utils/adt/mac8.c @@ -11,7 +11,7 @@ * The following code is written with the assumption that the OUI field * size is 24 bits. * - * Portions Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1998-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/mac8.c diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c index 199e68c1ae508..fe6dce9cba3ec 100644 --- a/src/backend/utils/adt/mcxtfuncs.c +++ b/src/backend/utils/adt/mcxtfuncs.c @@ -3,7 +3,7 @@ * mcxtfuncs.c * Functions to show backend memory context. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -38,29 +38,7 @@ typedef struct MemoryContextId { MemoryContext context; int context_id; -} MemoryContextId; - -/* - * get_memory_context_name_and_ident - * Populate *name and *ident from the name and ident from 'context'. - */ -static void -get_memory_context_name_and_ident(MemoryContext context, const char **const name, - const char **const ident) -{ - *name = context->name; - *ident = context->ident; - - /* - * To be consistent with logging output, we label dynahash contexts with - * just the hash table name as with MemoryContextStatsPrint(). - */ - if (ident && strcmp(*name, "dynahash") == 0) - { - *name = *ident; - *ident = NULL; - } -} +} MemoryContextId; /* * int_list_to_array @@ -93,7 +71,7 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, HTAB *context_id_lookup) { -#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 11 +#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 10 Datum values[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS]; bool nulls[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS]; @@ -128,7 +106,18 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, memset(values, 0, sizeof(values)); memset(nulls, 0, sizeof(nulls)); - get_memory_context_name_and_ident(context, &name, &ident); + name = context->name; + ident = context->ident; + + /* + * To be consistent with logging output, we label dynahash contexts with + * just the hash table name as with MemoryContextStatsPrint(). + */ + if (ident && strcmp(name, "dynahash") == 0) + { + name = ident; + ident = NULL; + } if (name) values[0] = CStringGetTextDatum(name); @@ -154,18 +143,6 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, else nulls[1] = true; - if (context->parent) - { - const char *parent_name, - *parent_ident; - - get_memory_context_name_and_ident(context->parent, &parent_name, - &parent_ident); - values[2] = CStringGetTextDatum(parent_name); - } - else - nulls[2] = true; - switch (context->type) { case T_AllocSetContext: @@ -185,14 +162,14 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, break; } - values[3] = CStringGetTextDatum(type); - values[4] = Int32GetDatum(list_length(path)); /* level */ - values[5] = int_list_to_array(path); - values[6] = Int64GetDatum(stat.totalspace); - values[7] = Int64GetDatum(stat.nblocks); - values[8] = Int64GetDatum(stat.freespace); - values[9] = Int64GetDatum(stat.freechunks); - values[10] = Int64GetDatum(stat.totalspace - stat.freespace); + values[2] = CStringGetTextDatum(type); + values[3] = Int32GetDatum(list_length(path)); /* level */ + values[4] = int_list_to_array(path); + values[5] = Int64GetDatum(stat.totalspace); + values[6] = Int64GetDatum(stat.nblocks); + values[7] = Int64GetDatum(stat.freespace); + values[8] = Int64GetDatum(stat.freechunks); + values[9] = Int64GetDatum(stat.totalspace - stat.freespace); tuplestore_putvalues(tupstore, tupdesc, values, nulls); list_free(path); diff --git a/src/backend/utils/adt/meson.build b/src/backend/utils/adt/meson.build index 8c6fc80c373b2..244f48f4fd711 100644 --- a/src/backend/utils/adt/meson.build +++ b/src/backend/utils/adt/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'acl.c', @@ -66,6 +66,9 @@ backend_sources += files( 'orderedsetaggs.c', 'partitionfuncs.c', 'pg_locale.c', + 'pg_locale_builtin.c', + 'pg_locale_icu.c', + 'pg_locale_libc.c', 'pg_lsn.c', 'pg_upgrade_support.c', 'pgstatfuncs.c', @@ -83,6 +86,7 @@ backend_sources += files( 'rowtypes.c', 'ruleutils.c', 'selfuncs.c', + 'skipsupport.c', 'tid.c', 'timestamp.c', 'trigfuncs.c', diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 0e6c45807a1ec..6fcfd031428ed 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -3,7 +3,7 @@ * misc.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -242,7 +242,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS) if (tablespaceOid == DEFAULTTABLESPACE_OID) location = "base"; else - location = psprintf("pg_tblspc/%u/%s", tablespaceOid, + location = psprintf("%s/%u/%s", PG_TBLSPC_DIR, tablespaceOid, TABLESPACE_VERSION_DIRECTORY); dirdesc = AllocateDir(location); @@ -325,7 +325,7 @@ pg_tablespace_location(PG_FUNCTION_ARGS) * Find the location of the tablespace by reading the symbolic link that * is in pg_tblspc/. */ - snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid); + snprintf(sourcepath, sizeof(sourcepath), "%s/%u", PG_TBLSPC_DIR, tablespaceOid); /* * Before reading the link, check if the source path is a link or a diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c index 558c6c18c3466..cd84ced5b487c 100644 --- a/src/backend/utils/adt/multirangetypes.c +++ b/src/backend/utils/adt/multirangetypes.c @@ -21,7 +21,7 @@ * for a particular range index. Offsets are counted starting from the end of * flags aligned to the bound type. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -458,7 +458,7 @@ get_multirange_io_data(FunctionCallInfo fcinfo, Oid mltrngtypid, IOFuncSelector fmgr_info_cxt(typiofunc, &cache->typioproc, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) cache; + fcinfo->flinfo->fn_extra = cache; } return cache; @@ -555,7 +555,7 @@ multirange_get_typcache(FunctionCallInfo fcinfo, Oid mltrngtypid) typcache = lookup_type_cache(mltrngtypid, TYPECACHE_MULTIRANGE_INFO); if (typcache->rngtype == NULL) elog(ERROR, "type %u is not a multirange type", mltrngtypid); - fcinfo->flinfo->fn_extra = (void *) typcache; + fcinfo->flinfo->fn_extra = typcache; } return typcache; diff --git a/src/backend/utils/adt/multirangetypes_selfuncs.c b/src/backend/utils/adt/multirangetypes_selfuncs.c index 9e8558b599288..b87bcf3ea306c 100644 --- a/src/backend/utils/adt/multirangetypes_selfuncs.c +++ b/src/backend/utils/adt/multirangetypes_selfuncs.c @@ -6,7 +6,7 @@ * Estimates are based on histograms of lower and upper bounds, and the * fraction of empty multiranges. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index 85c9db85f3123..b2487881d54ab 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -9,7 +9,7 @@ * always use NAMEDATALEN as the symbolic constant! - jolly 8/21/95 * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index 640fc37dc8319..f03fcc1147bb0 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -279,8 +279,6 @@ network_send(inet *addr, bool is_cidr) pq_sendbyte(&buf, ip_bits(addr)); pq_sendbyte(&buf, is_cidr); nb = ip_addrsize(addr); - if (nb < 0) - nb = 0; pq_sendbyte(&buf, nb); addrptr = (char *) ip_addr(addr); for (i = 0; i < nb; i++) @@ -503,13 +501,11 @@ network_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card > 100000.0) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "network_abbrev: estimation ends at cardinality %f" " after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif uss->estimating = false; return false; } @@ -522,23 +518,19 @@ network_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card < uss->input_count / 2000.0 + 0.5) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "network_abbrev: aborting abbreviation at cardinality %f" " below threshold %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count / 2000.0 + 0.5, uss->input_count, memtupcount); -#endif return true; } -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "network_abbrev: cardinality %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif return false; } @@ -1099,39 +1091,13 @@ match_network_subset(Node *leftop, return NIL; rightopval = ((Const *) rightop)->constvalue; - /* - * Must check that index's opfamily supports the operators we will want to - * apply. - * - * We insist on the opfamily being the specific one we expect, else we'd - * do the wrong thing if someone were to make a reverse-sort opfamily with - * the same operators. - */ - if (opfamily != NETWORK_BTREE_FAM_OID) - return NIL; - /* * create clause "key >= network_scan_first( rightopval )", or ">" if the * operator disallows equality. - * - * Note: seeing that this function supports only fixed values for opfamily - * and datatype, we could just hard-wire the operator OIDs instead of - * looking them up. But for now it seems better to be general. */ - if (is_eq) - { - opr1oid = get_opfamily_member(opfamily, datatype, datatype, - BTGreaterEqualStrategyNumber); - if (opr1oid == InvalidOid) - elog(ERROR, "no >= operator for opfamily %u", opfamily); - } - else - { - opr1oid = get_opfamily_member(opfamily, datatype, datatype, - BTGreaterStrategyNumber); - if (opr1oid == InvalidOid) - elog(ERROR, "no > operator for opfamily %u", opfamily); - } + opr1oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, is_eq ? COMPARE_GE : COMPARE_GT); + if (opr1oid == InvalidOid) + return NIL; opr1right = network_scan_first(rightopval); @@ -1146,10 +1112,9 @@ match_network_subset(Node *leftop, /* create clause "key <= network_scan_last( rightopval )" */ - opr2oid = get_opfamily_member(opfamily, datatype, datatype, - BTLessEqualStrategyNumber); + opr2oid = get_opfamily_member_for_cmptype(opfamily, datatype, datatype, COMPARE_LE); if (opr2oid == InvalidOid) - elog(ERROR, "no <= operator for opfamily %u", opfamily); + return NIL; opr2right = network_scan_last(rightopval); diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c index 15feb449b554e..a08c495378919 100644 --- a/src/backend/utils/adt/network_gist.c +++ b/src/backend/utils/adt/network_gist.c @@ -34,7 +34,7 @@ * twice as fast as for a simpler design in which a single field doubles as * the common prefix length and the minimum ip_bits value. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/network_selfuncs.c b/src/backend/utils/adt/network_selfuncs.c index 98eec81b09c0a..940cdafa54619 100644 --- a/src/backend/utils/adt/network_selfuncs.c +++ b/src/backend/utils/adt/network_selfuncs.c @@ -7,7 +7,7 @@ * operators. Estimates are based on null fraction, most common values, * and histogram of inet/cidr columns. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/network_spgist.c b/src/backend/utils/adt/network_spgist.c index d18cf64c341d3..a84747d927586 100644 --- a/src/backend/utils/adt/network_spgist.c +++ b/src/backend/utils/adt/network_spgist.c @@ -21,7 +21,7 @@ * the address family, everything goes into node 0 (which will probably * lead to creating an allTheSame tuple). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index d0f09237100d8..40dcbc7b6710b 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -11,7 +11,7 @@ * Transactions on Mathematical Software, Vol. 24, No. 4, December 1998, * pages 359-367. * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/numeric.c @@ -34,6 +34,7 @@ #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "nodes/supportnodes.h" +#include "optimizer/optimizer.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/float.h" @@ -60,7 +61,7 @@ * NBASE that's less than sqrt(INT_MAX), in practice we are only interested * in NBASE a power of ten, so that I/O conversions and decimal rounding * are easy. Also, it's actually more efficient if NBASE is rather less than - * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var_fast to + * sqrt(INT_MAX), so that there is "headroom" for mul_var and div_var to * postpone processing carries. * * Values of NBASE other than 10000 are considered of historical interest only @@ -101,6 +102,8 @@ typedef signed char NumericDigit; typedef int16 NumericDigit; #endif +#define NBASE_SQR (NBASE * NBASE) + /* * The Numeric type as stored on disk. * @@ -561,10 +564,7 @@ static void mul_var(const NumericVar *var1, const NumericVar *var2, static void mul_var_short(const NumericVar *var1, const NumericVar *var2, NumericVar *result); static void div_var(const NumericVar *var1, const NumericVar *var2, - NumericVar *result, - int rscale, bool round); -static void div_var_fast(const NumericVar *var1, const NumericVar *var2, - NumericVar *result, int rscale, bool round); + NumericVar *result, int rscale, bool round, bool exact); static void div_var_int(const NumericVar *var, int ival, int ival_weight, NumericVar *result, int rscale, bool round); #ifdef HAVE_INT128 @@ -1828,6 +1828,126 @@ generate_series_step_numeric(PG_FUNCTION_ARGS) SRF_RETURN_DONE(funcctx); } +/* + * Planner support function for generate_series(numeric, numeric [, numeric]) + */ +Datum +generate_series_numeric_support(PG_FUNCTION_ARGS) +{ + Node *rawreq = (Node *) PG_GETARG_POINTER(0); + Node *ret = NULL; + + if (IsA(rawreq, SupportRequestRows)) + { + /* Try to estimate the number of rows returned */ + SupportRequestRows *req = (SupportRequestRows *) rawreq; + + if (is_funcclause(req->node)) /* be paranoid */ + { + List *args = ((FuncExpr *) req->node)->args; + Node *arg1, + *arg2, + *arg3; + + /* We can use estimated argument values here */ + arg1 = estimate_expression_value(req->root, linitial(args)); + arg2 = estimate_expression_value(req->root, lsecond(args)); + if (list_length(args) >= 3) + arg3 = estimate_expression_value(req->root, lthird(args)); + else + arg3 = NULL; + + /* + * If any argument is constant NULL, we can safely assume that + * zero rows are returned. Otherwise, if they're all non-NULL + * constants, we can calculate the number of rows that will be + * returned. + */ + if ((IsA(arg1, Const) && + ((Const *) arg1)->constisnull) || + (IsA(arg2, Const) && + ((Const *) arg2)->constisnull) || + (arg3 != NULL && IsA(arg3, Const) && + ((Const *) arg3)->constisnull)) + { + req->rows = 0; + ret = (Node *) req; + } + else if (IsA(arg1, Const) && + IsA(arg2, Const) && + (arg3 == NULL || IsA(arg3, Const))) + { + Numeric start_num; + Numeric stop_num; + NumericVar step = const_one; + + /* + * If any argument is NaN or infinity, generate_series() will + * error out, so we needn't produce an estimate. + */ + start_num = DatumGetNumeric(((Const *) arg1)->constvalue); + stop_num = DatumGetNumeric(((Const *) arg2)->constvalue); + + if (NUMERIC_IS_SPECIAL(start_num) || + NUMERIC_IS_SPECIAL(stop_num)) + PG_RETURN_POINTER(NULL); + + if (arg3) + { + Numeric step_num; + + step_num = DatumGetNumeric(((Const *) arg3)->constvalue); + + if (NUMERIC_IS_SPECIAL(step_num)) + PG_RETURN_POINTER(NULL); + + init_var_from_num(step_num, &step); + } + + /* + * The number of rows that will be returned is given by + * floor((stop - start) / step) + 1, if the sign of step + * matches the sign of stop - start. Otherwise, no rows will + * be returned. + */ + if (cmp_var(&step, &const_zero) != 0) + { + NumericVar start; + NumericVar stop; + NumericVar res; + + init_var_from_num(start_num, &start); + init_var_from_num(stop_num, &stop); + + init_var(&res); + sub_var(&stop, &start, &res); + + if (step.sign != res.sign) + { + /* no rows will be returned */ + req->rows = 0; + ret = (Node *) req; + } + else + { + if (arg3) + div_var(&res, &step, &res, 0, false, false); + else + trunc_var(&res, 0); /* step = 1 */ + + req->rows = numericvar_to_double_no_overflow(&res) + 1; + ret = (Node *) req; + } + + free_var(&res); + } + } + } + } + + PG_RETURN_POINTER(ret); +} + /* * Implements the numeric version of the width_bucket() function @@ -1956,7 +2076,7 @@ compute_bucket(Numeric operand, Numeric bound1, Numeric bound2, mul_var(&operand_var, count_var, &operand_var, operand_var.dscale + count_var->dscale); - div_var(&operand_var, &bound2_var, result_var, 0, false); + div_var(&operand_var, &bound2_var, result_var, 0, false, true); add_var(result_var, &const_one, result_var); free_var(&bound1_var); @@ -2127,13 +2247,11 @@ numeric_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card > 100000.0) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "numeric_abbrev: estimation ends at cardinality %f" " after " INT64_FORMAT " values (%d rows)", abbr_card, nss->input_count, memtupcount); -#endif nss->estimating = false; return false; } @@ -2149,24 +2267,20 @@ numeric_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card < nss->input_count / 10000.0 + 0.5) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "numeric_abbrev: aborting abbreviation at cardinality %f" " below threshold %f after " INT64_FORMAT " values (%d rows)", abbr_card, nss->input_count / 10000.0 + 0.5, nss->input_count, memtupcount); -#endif return true; } -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "numeric_abbrev: cardinality %f" " after " INT64_FORMAT " values (%d rows)", abbr_card, nss->input_count, memtupcount); -#endif return false; } @@ -3244,7 +3358,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error) /* * Do the divide and return the result */ - div_var(&arg1, &arg2, &result, rscale, true); + div_var(&arg1, &arg2, &result, rscale, true, true); res = make_result_opt_error(&result, have_error); @@ -3333,7 +3447,7 @@ numeric_div_trunc(PG_FUNCTION_ARGS) /* * Do the divide and return the result */ - div_var(&arg1, &arg2, &result, 0, false); + div_var(&arg1, &arg2, &result, 0, false, true); res = make_result(&result); @@ -3604,7 +3718,7 @@ numeric_lcm(PG_FUNCTION_ARGS) else { gcd_var(&arg1, &arg2, &result); - div_var(&arg1, &result, &result, 0, false); + div_var(&arg1, &result, &result, 0, false, true); mul_var(&arg2, &result, &result, arg2.dscale); result.sign = NUMERIC_POS; } @@ -6276,7 +6390,7 @@ numeric_stddev_internal(NumericAggState *state, else mul_var(&vN, &vN, &vNminus1, 0); /* N * N */ rscale = select_div_scale(&vsumX2, &vNminus1); - div_var(&vsumX2, &vNminus1, &vsumX, rscale, true); /* variance */ + div_var(&vsumX2, &vNminus1, &vsumX, rscale, true, true); /* variance */ if (!variance) sqrt_var(&vsumX, &vsumX, rscale); /* stddev */ @@ -7694,7 +7808,7 @@ get_str_from_var_sci(const NumericVar *var, int rscale) init_var(&tmp_var); power_ten_int(exponent, &tmp_var); - div_var(var, &tmp_var, &tmp_var, rscale, true); + div_var(var, &tmp_var, &tmp_var, rscale, true, true); sig_out = get_str_from_var(&tmp_var); free_var(&tmp_var); @@ -8117,7 +8231,7 @@ int64_to_numericvar(int64 val, NumericVar *var) if (val < 0) { var->sign = NUMERIC_NEG; - uval = -val; + uval = pg_abs_s64(val); } else { @@ -8674,21 +8788,30 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, int rscale) { int res_ndigits; + int res_ndigitpairs; int res_sign; int res_weight; + int pair_offset; int maxdigits; - int *dig; - int carry; - int maxdig; - int newdig; + int maxdigitpairs; + uint64 *dig, + *dig_i1_off; + uint64 maxdig; + uint64 carry; + uint64 newdig; int var1ndigits; int var2ndigits; + int var1ndigitpairs; + int var2ndigitpairs; NumericDigit *var1digits; NumericDigit *var2digits; + uint32 var1digitpair; + uint32 *var2digitpairs; NumericDigit *res_digits; int i, i1, - i2; + i2, + i2limit; /* * Arrange for var1 to be the shorter of the two numbers. This improves @@ -8720,95 +8843,173 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, } /* - * If var1 has 1-4 digits and the exact result was requested, delegate to + * If var1 has 1-6 digits and the exact result was requested, delegate to * mul_var_short() which uses a faster direct multiplication algorithm. */ - if (var1ndigits <= 4 && rscale == var1->dscale + var2->dscale) + if (var1ndigits <= 6 && rscale == var1->dscale + var2->dscale) { mul_var_short(var1, var2, result); return; } - /* Determine result sign and (maximum possible) weight */ + /* Determine result sign */ if (var1->sign == var2->sign) res_sign = NUMERIC_POS; else res_sign = NUMERIC_NEG; - res_weight = var1->weight + var2->weight + 2; /* - * Determine the number of result digits to compute. If the exact result - * would have more than rscale fractional digits, truncate the computation - * with MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that - * would only contribute to the right of that. (This will give the exact + * Determine the number of result digits to compute and the (maximum + * possible) result weight. If the exact result would have more than + * rscale fractional digits, truncate the computation with + * MUL_GUARD_DIGITS guard digits, i.e., ignore input digits that would + * only contribute to the right of that. (This will give the exact * rounded-to-rscale answer unless carries out of the ignored positions * would have propagated through more than MUL_GUARD_DIGITS digits.) * * Note: an exact computation could not produce more than var1ndigits + - * var2ndigits digits, but we allocate one extra output digit in case - * rscale-driven rounding produces a carry out of the highest exact digit. + * var2ndigits digits, but we allocate at least one extra output digit in + * case rscale-driven rounding produces a carry out of the highest exact + * digit. + * + * The computation itself is done using base-NBASE^2 arithmetic, so we + * actually process the input digits in pairs, producing a base-NBASE^2 + * intermediate result. This significantly improves performance, since + * schoolbook multiplication is O(N^2) in the number of input digits, and + * working in base NBASE^2 effectively halves "N". + * + * Note: in a truncated computation, we must compute at least one extra + * output digit to ensure that all the guard digits are fully computed. */ - res_ndigits = var1ndigits + var2ndigits + 1; + /* digit pairs in each input */ + var1ndigitpairs = (var1ndigits + 1) / 2; + var2ndigitpairs = (var2ndigits + 1) / 2; + + /* digits in exact result */ + res_ndigits = var1ndigits + var2ndigits; + + /* digit pairs in exact result with at least one extra output digit */ + res_ndigitpairs = res_ndigits / 2 + 1; + + /* pair offset to align result to end of dig[] */ + pair_offset = res_ndigitpairs - var1ndigitpairs - var2ndigitpairs + 1; + + /* maximum possible result weight (odd-length inputs shifted up below) */ + res_weight = var1->weight + var2->weight + 1 + 2 * res_ndigitpairs - + res_ndigits - (var1ndigits & 1) - (var2ndigits & 1); + + /* rscale-based truncation with at least one extra output digit */ maxdigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS + MUL_GUARD_DIGITS; - res_ndigits = Min(res_ndigits, maxdigits); + maxdigitpairs = maxdigits / 2 + 1; - if (res_ndigits < 3) + res_ndigitpairs = Min(res_ndigitpairs, maxdigitpairs); + res_ndigits = 2 * res_ndigitpairs; + + /* + * In the computation below, digit pair i1 of var1 and digit pair i2 of + * var2 are multiplied and added to digit i1+i2+pair_offset of dig[]. Thus + * input digit pairs with index >= res_ndigitpairs - pair_offset don't + * contribute to the result, and can be ignored. + */ + if (res_ndigitpairs <= pair_offset) { /* All input digits will be ignored; so result is zero */ zero_var(result); result->dscale = rscale; return; } + var1ndigitpairs = Min(var1ndigitpairs, res_ndigitpairs - pair_offset); + var2ndigitpairs = Min(var2ndigitpairs, res_ndigitpairs - pair_offset); /* - * We do the arithmetic in an array "dig[]" of signed int's. Since - * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom - * to avoid normalizing carries immediately. + * We do the arithmetic in an array "dig[]" of unsigned 64-bit integers. + * Since PG_UINT64_MAX is much larger than NBASE^4, this gives us a lot of + * headroom to avoid normalizing carries immediately. * * maxdig tracks the maximum possible value of any dig[] entry; when this - * threatens to exceed INT_MAX, we take the time to propagate carries. - * Furthermore, we need to ensure that overflow doesn't occur during the - * carry propagation passes either. The carry values could be as much as - * INT_MAX/NBASE, so really we must normalize when digits threaten to - * exceed INT_MAX - INT_MAX/NBASE. + * threatens to exceed PG_UINT64_MAX, we take the time to propagate + * carries. Furthermore, we need to ensure that overflow doesn't occur + * during the carry propagation passes either. The carry values could be + * as much as PG_UINT64_MAX / NBASE^2, so really we must normalize when + * digits threaten to exceed PG_UINT64_MAX - PG_UINT64_MAX / NBASE^2. * - * To avoid overflow in maxdig itself, it actually represents the max - * possible value divided by NBASE-1, ie, at the top of the loop it is - * known that no dig[] entry exceeds maxdig * (NBASE-1). + * To avoid overflow in maxdig itself, it actually represents the maximum + * possible value divided by NBASE^2-1, i.e., at the top of the loop it is + * known that no dig[] entry exceeds maxdig * (NBASE^2-1). + * + * The conversion of var1 to base NBASE^2 is done on the fly, as each new + * digit is required. The digits of var2 are converted upfront, and + * stored at the end of dig[]. To avoid loss of precision, the input + * digits are aligned with the start of digit pair array, effectively + * shifting them up (multiplying by NBASE) if the inputs have an odd + * number of NBASE digits. */ - dig = (int *) palloc0(res_ndigits * sizeof(int)); - maxdig = 0; + dig = (uint64 *) palloc(res_ndigitpairs * sizeof(uint64) + + var2ndigitpairs * sizeof(uint32)); + + /* convert var2 to base NBASE^2, shifting up if its length is odd */ + var2digitpairs = (uint32 *) (dig + res_ndigitpairs); + + for (i2 = 0; i2 < var2ndigitpairs - 1; i2++) + var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1]; + + if (2 * i2 + 1 < var2ndigits) + var2digitpairs[i2] = var2digits[2 * i2] * NBASE + var2digits[2 * i2 + 1]; + else + var2digitpairs[i2] = var2digits[2 * i2] * NBASE; /* - * The least significant digits of var1 should be ignored if they don't - * contribute directly to the first res_ndigits digits of the result that - * we are computing. + * Start by multiplying var2 by the least significant contributing digit + * pair from var1, storing the results at the end of dig[], and filling + * the leading digits with zeros. * - * Digit i1 of var1 and digit i2 of var2 are multiplied and added to digit - * i1+i2+2 of the accumulator array, so we need only consider digits of - * var1 for which i1 <= res_ndigits - 3. + * The loop here is the same as the inner loop below, except that we set + * the results in dig[], rather than adding to them. This is the + * performance bottleneck for multiplication, so we want to keep it simple + * enough so that it can be auto-vectorized. Accordingly, process the + * digits left-to-right even though schoolbook multiplication would + * suggest right-to-left. Since we aren't propagating carries in this + * loop, the order does not matter. + */ + i1 = var1ndigitpairs - 1; + if (2 * i1 + 1 < var1ndigits) + var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1]; + else + var1digitpair = var1digits[2 * i1] * NBASE; + maxdig = var1digitpair; + + i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset); + dig_i1_off = &dig[i1 + pair_offset]; + + memset(dig, 0, (i1 + pair_offset) * sizeof(uint64)); + for (i2 = 0; i2 < i2limit; i2++) + dig_i1_off[i2] = (uint64) var1digitpair * var2digitpairs[i2]; + + /* + * Next, multiply var2 by the remaining digit pairs from var1, adding the + * results to dig[] at the appropriate offsets, and normalizing whenever + * there is a risk of any dig[] entry overflowing. */ - for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--) + for (i1 = i1 - 1; i1 >= 0; i1--) { - NumericDigit var1digit = var1digits[i1]; - - if (var1digit == 0) + var1digitpair = var1digits[2 * i1] * NBASE + var1digits[2 * i1 + 1]; + if (var1digitpair == 0) continue; /* Time to normalize? */ - maxdig += var1digit; - if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1)) + maxdig += var1digitpair; + if (maxdig > (PG_UINT64_MAX - PG_UINT64_MAX / NBASE_SQR) / (NBASE_SQR - 1)) { - /* Yes, do it */ + /* Yes, do it (to base NBASE^2) */ carry = 0; - for (i = res_ndigits - 1; i >= 0; i--) + for (i = res_ndigitpairs - 1; i >= 0; i--) { newdig = dig[i] + carry; - if (newdig >= NBASE) + if (newdig >= NBASE_SQR) { - carry = newdig / NBASE; - newdig -= carry * NBASE; + carry = newdig / NBASE_SQR; + newdig -= carry * NBASE_SQR; } else carry = 0; @@ -8816,50 +9017,37 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, } Assert(carry == 0); /* Reset maxdig to indicate new worst-case */ - maxdig = 1 + var1digit; + maxdig = 1 + var1digitpair; } - /* - * Add the appropriate multiple of var2 into the accumulator. - * - * As above, digits of var2 can be ignored if they don't contribute, - * so we only include digits for which i1+i2+2 < res_ndigits. - * - * This inner loop is the performance bottleneck for multiplication, - * so we want to keep it simple enough so that it can be - * auto-vectorized. Accordingly, process the digits left-to-right - * even though schoolbook multiplication would suggest right-to-left. - * Since we aren't propagating carries in this loop, the order does - * not matter. - */ - { - int i2limit = Min(var2ndigits, res_ndigits - i1 - 2); - int *dig_i1_2 = &dig[i1 + 2]; + /* Multiply and add */ + i2limit = Min(var2ndigitpairs, res_ndigitpairs - i1 - pair_offset); + dig_i1_off = &dig[i1 + pair_offset]; - for (i2 = 0; i2 < i2limit; i2++) - dig_i1_2[i2] += var1digit * var2digits[i2]; - } + for (i2 = 0; i2 < i2limit; i2++) + dig_i1_off[i2] += (uint64) var1digitpair * var2digitpairs[i2]; } /* - * Now we do a final carry propagation pass to normalize the result, which - * we combine with storing the result digits into the output. Note that - * this is still done at full precision w/guard digits. + * Now we do a final carry propagation pass to normalize back to base + * NBASE^2, and construct the base-NBASE result digits. Note that this is + * still done at full precision w/guard digits. */ alloc_var(result, res_ndigits); res_digits = result->digits; carry = 0; - for (i = res_ndigits - 1; i >= 0; i--) + for (i = res_ndigitpairs - 1; i >= 0; i--) { newdig = dig[i] + carry; - if (newdig >= NBASE) + if (newdig >= NBASE_SQR) { - carry = newdig / NBASE; - newdig -= carry * NBASE; + carry = newdig / NBASE_SQR; + newdig -= carry * NBASE_SQR; } else carry = 0; - res_digits[i] = newdig; + res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE); + res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE); } Assert(carry == 0); @@ -8882,7 +9070,7 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, /* * mul_var_short() - * - * Special-case multiplication function used when var1 has 1-4 digits, var2 + * Special-case multiplication function used when var1 has 1-6 digits, var2 * has at least as many digits as var1, and the exact product var1 * var2 is * requested. */ @@ -8899,12 +9087,12 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, int res_ndigits; NumericDigit *res_buf; NumericDigit *res_digits; - uint32 carry; + uint32 carry = 0; uint32 term; /* Check preconditions */ Assert(var1ndigits >= 1); - Assert(var1ndigits <= 4); + Assert(var1ndigits <= 6); Assert(var2ndigits >= var1ndigits); /* @@ -8931,6 +9119,13 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, * carry up as we go. The i'th result digit consists of the sum of the * products var1digits[i1] * var2digits[i2] for which i = i1 + i2 + 1. */ +#define PRODSUM1(v1,i1,v2,i2) ((v1)[(i1)] * (v2)[(i2)]) +#define PRODSUM2(v1,i1,v2,i2) (PRODSUM1(v1,i1,v2,i2) + (v1)[(i1)+1] * (v2)[(i2)-1]) +#define PRODSUM3(v1,i1,v2,i2) (PRODSUM2(v1,i1,v2,i2) + (v1)[(i1)+2] * (v2)[(i2)-2]) +#define PRODSUM4(v1,i1,v2,i2) (PRODSUM3(v1,i1,v2,i2) + (v1)[(i1)+3] * (v2)[(i2)-3]) +#define PRODSUM5(v1,i1,v2,i2) (PRODSUM4(v1,i1,v2,i2) + (v1)[(i1)+4] * (v2)[(i2)-4]) +#define PRODSUM6(v1,i1,v2,i2) (PRODSUM5(v1,i1,v2,i2) + (v1)[(i1)+5] * (v2)[(i2)-5]) + switch (var1ndigits) { case 1: @@ -8941,10 +9136,9 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, * res_ndigits = var2ndigits + 1 * ---------- */ - carry = 0; - for (int i = res_ndigits - 2; i >= 0; i--) + for (int i = var2ndigits - 1; i >= 0; i--) { - term = (uint32) var1digits[0] * var2digits[i] + carry; + term = PRODSUM1(var1digits, 0, var2digits, i) + carry; res_digits[i + 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; } @@ -8960,23 +9154,17 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, * ---------- */ /* last result digit and carry */ - term = (uint32) var1digits[1] * var2digits[res_ndigits - 3]; + term = PRODSUM1(var1digits, 1, var2digits, var2ndigits - 1); res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; /* remaining digits, except for the first two */ - for (int i = res_ndigits - 3; i >= 1; i--) + for (int i = var2ndigits - 1; i >= 1; i--) { - term = (uint32) var1digits[0] * var2digits[i] + - (uint32) var1digits[1] * var2digits[i - 1] + carry; + term = PRODSUM2(var1digits, 0, var2digits, i) + carry; res_digits[i + 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; } - - /* first two digits */ - term = (uint32) var1digits[0] * var2digits[0] + carry; - res_digits[1] = (NumericDigit) (term % NBASE); - res_digits[0] = (NumericDigit) (term / NBASE); break; case 3: @@ -8988,34 +9176,21 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, * ---------- */ /* last two result digits */ - term = (uint32) var1digits[2] * var2digits[res_ndigits - 4]; + term = PRODSUM1(var1digits, 2, var2digits, var2ndigits - 1); res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; - term = (uint32) var1digits[1] * var2digits[res_ndigits - 4] + - (uint32) var1digits[2] * var2digits[res_ndigits - 5] + carry; + term = PRODSUM2(var1digits, 1, var2digits, var2ndigits - 1) + carry; res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); carry = term / NBASE; /* remaining digits, except for the first three */ - for (int i = res_ndigits - 4; i >= 2; i--) + for (int i = var2ndigits - 1; i >= 2; i--) { - term = (uint32) var1digits[0] * var2digits[i] + - (uint32) var1digits[1] * var2digits[i - 1] + - (uint32) var1digits[2] * var2digits[i - 2] + carry; + term = PRODSUM3(var1digits, 0, var2digits, i) + carry; res_digits[i + 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; } - - /* first three digits */ - term = (uint32) var1digits[0] * var2digits[1] + - (uint32) var1digits[1] * var2digits[0] + carry; - res_digits[2] = (NumericDigit) (term % NBASE); - carry = term / NBASE; - - term = (uint32) var1digits[0] * var2digits[0] + carry; - res_digits[1] = (NumericDigit) (term % NBASE); - res_digits[0] = (NumericDigit) (term / NBASE); break; case 4: @@ -9027,45 +9202,128 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, * ---------- */ /* last three result digits */ - term = (uint32) var1digits[3] * var2digits[res_ndigits - 5]; + term = PRODSUM1(var1digits, 3, var2digits, var2ndigits - 1); res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; - term = (uint32) var1digits[2] * var2digits[res_ndigits - 5] + - (uint32) var1digits[3] * var2digits[res_ndigits - 6] + carry; + term = PRODSUM2(var1digits, 2, var2digits, var2ndigits - 1) + carry; res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); carry = term / NBASE; - term = (uint32) var1digits[1] * var2digits[res_ndigits - 5] + - (uint32) var1digits[2] * var2digits[res_ndigits - 6] + - (uint32) var1digits[3] * var2digits[res_ndigits - 7] + carry; + term = PRODSUM3(var1digits, 1, var2digits, var2ndigits - 1) + carry; res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); carry = term / NBASE; /* remaining digits, except for the first four */ - for (int i = res_ndigits - 5; i >= 3; i--) + for (int i = var2ndigits - 1; i >= 3; i--) { - term = (uint32) var1digits[0] * var2digits[i] + - (uint32) var1digits[1] * var2digits[i - 1] + - (uint32) var1digits[2] * var2digits[i - 2] + - (uint32) var1digits[3] * var2digits[i - 3] + carry; + term = PRODSUM4(var1digits, 0, var2digits, i) + carry; res_digits[i + 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; } + break; - /* first four digits */ - term = (uint32) var1digits[0] * var2digits[2] + - (uint32) var1digits[1] * var2digits[1] + - (uint32) var1digits[2] * var2digits[0] + carry; - res_digits[3] = (NumericDigit) (term % NBASE); + case 5: + /* --------- + * 5-digit case: + * var1ndigits = 5 + * var2ndigits >= 5 + * res_ndigits = var2ndigits + 5 + * ---------- + */ + /* last four result digits */ + term = PRODSUM1(var1digits, 4, var2digits, var2ndigits - 1); + res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); carry = term / NBASE; - term = (uint32) var1digits[0] * var2digits[1] + - (uint32) var1digits[1] * var2digits[0] + carry; - res_digits[2] = (NumericDigit) (term % NBASE); + term = PRODSUM2(var1digits, 3, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + term = PRODSUM3(var1digits, 2, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + term = PRODSUM4(var1digits, 1, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + /* remaining digits, except for the first five */ + for (int i = var2ndigits - 1; i >= 4; i--) + { + term = PRODSUM5(var1digits, 0, var2digits, i) + carry; + res_digits[i + 1] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + } + break; + + case 6: + /* --------- + * 6-digit case: + * var1ndigits = 6 + * var2ndigits >= 6 + * res_ndigits = var2ndigits + 6 + * ---------- + */ + /* last five result digits */ + term = PRODSUM1(var1digits, 5, var2digits, var2ndigits - 1); + res_digits[res_ndigits - 1] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + term = PRODSUM2(var1digits, 4, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 2] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + term = PRODSUM3(var1digits, 3, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 3] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + term = PRODSUM4(var1digits, 2, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 4] = (NumericDigit) (term % NBASE); carry = term / NBASE; - term = (uint32) var1digits[0] * var2digits[0] + carry; + term = PRODSUM5(var1digits, 1, var2digits, var2ndigits - 1) + carry; + res_digits[res_ndigits - 5] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + + /* remaining digits, except for the first six */ + for (int i = var2ndigits - 1; i >= 5; i--) + { + term = PRODSUM6(var1digits, 0, var2digits, i) + carry; + res_digits[i + 1] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + } + break; + } + + /* + * Finally, for var1ndigits > 1, compute the remaining var1ndigits most + * significant result digits. + */ + switch (var1ndigits) + { + case 6: + term = PRODSUM5(var1digits, 0, var2digits, 4) + carry; + res_digits[5] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + /* FALLTHROUGH */ + case 5: + term = PRODSUM4(var1digits, 0, var2digits, 3) + carry; + res_digits[4] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + /* FALLTHROUGH */ + case 4: + term = PRODSUM3(var1digits, 0, var2digits, 2) + carry; + res_digits[3] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + /* FALLTHROUGH */ + case 3: + term = PRODSUM2(var1digits, 0, var2digits, 1) + carry; + res_digits[2] = (NumericDigit) (term % NBASE); + carry = term / NBASE; + /* FALLTHROUGH */ + case 2: + term = PRODSUM1(var1digits, 0, var2digits, 0) + carry; res_digits[1] = (NumericDigit) (term % NBASE); res_digits[0] = (NumericDigit) (term / NBASE); break; @@ -9088,32 +9346,48 @@ mul_var_short(const NumericVar *var1, const NumericVar *var2, /* * div_var() - * - * Division on variable level. Quotient of var1 / var2 is stored in result. - * The quotient is figured to exactly rscale fractional digits. - * If round is true, it is rounded at the rscale'th digit; if false, it - * is truncated (towards zero) at that digit. + * Compute the quotient var1 / var2 to rscale fractional digits. + * + * If "round" is true, the result is rounded at the rscale'th digit; if + * false, it is truncated (towards zero) at that digit. + * + * If "exact" is true, the exact result is computed to the specified rscale; + * if false, successive quotient digits are approximated up to rscale plus + * DIV_GUARD_DIGITS extra digits, ignoring all contributions from digits to + * the right of that, before rounding or truncating to the specified rscale. + * This can be significantly faster, and usually gives the same result as the + * exact computation, but it may occasionally be off by one in the final + * digit, if contributions from the ignored digits would have propagated + * through the guard digits. This is good enough for the transcendental + * functions, where small errors are acceptable. */ static void div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, - int rscale, bool round) + int rscale, bool round, bool exact) { - int div_ndigits; - int res_ndigits; + int var1ndigits = var1->ndigits; + int var2ndigits = var2->ndigits; int res_sign; int res_weight; - int carry; - int borrow; - int divisor1; - int divisor2; - NumericDigit *dividend; - NumericDigit *divisor; + int res_ndigits; + int var1ndigitpairs; + int var2ndigitpairs; + int res_ndigitpairs; + int div_ndigitpairs; + int64 *dividend; + int32 *divisor; + double fdivisor, + fdivisorinverse, + fdividend, + fquotient; + int64 maxdiv; + int qi; + int32 qdigit; + int64 carry; + int64 newdig; + int64 *remainder; NumericDigit *res_digits; int i; - int j; - - /* copy these values into local vars for speed in inner loop */ - int var1ndigits = var1->ndigits; - int var2ndigits = var2->ndigits; /* * First of all division by zero check; we must not be handed an @@ -9182,6 +9456,22 @@ div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, return; } + /* + * The approximate computation can be significantly faster than the exact + * one, since the working dividend is var2ndigitpairs base-NBASE^2 digits + * shorter below. However, that comes with the tradeoff of computing + * DIV_GUARD_DIGITS extra base-NBASE result digits. Ignoring all other + * overheads, that suggests that, in theory, the approximate computation + * will only be faster than the exact one when var2ndigits is greater than + * 2 * (DIV_GUARD_DIGITS + 1), independent of the size of var1. + * + * Thus, we're better off doing an exact computation when var2 is shorter + * than this. Empirically, it has been found that the exact threshold is + * a little higher, due to other overheads in the outer division loop. + */ + if (var2ndigits <= 2 * (DIV_GUARD_DIGITS + 2)) + exact = true; + /* * Determine the result sign, weight and number of digits to calculate. * The weight figured here is correct if the emitted quotient has no @@ -9191,7 +9481,7 @@ div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, res_sign = NUMERIC_POS; else res_sign = NUMERIC_NEG; - res_weight = var1->weight - var2->weight; + res_weight = var1->weight - var2->weight + 1; /* The number of accurate result digits we need to produce: */ res_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; /* ... but always at least 1 */ @@ -9199,476 +9489,209 @@ div_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result, /* If rounding needed, figure one more digit to ensure correct result */ if (round) res_ndigits++; + /* Add guard digits for roundoff error when producing approx result */ + if (!exact) + res_ndigits += DIV_GUARD_DIGITS; /* - * The working dividend normally requires res_ndigits + var2ndigits - * digits, but make it at least var1ndigits so we can load all of var1 - * into it. (There will be an additional digit dividend[0] in the - * dividend space, but for consistency with Knuth's notation we don't - * count that in div_ndigits.) + * The computation itself is done using base-NBASE^2 arithmetic, so we + * actually process the input digits in pairs, producing a base-NBASE^2 + * intermediate result. This significantly improves performance, since + * the computation is O(N^2) in the number of input digits, and working in + * base NBASE^2 effectively halves "N". */ - div_ndigits = res_ndigits + var2ndigits; - div_ndigits = Max(div_ndigits, var1ndigits); - - /* - * We need a workspace with room for the working dividend (div_ndigits+1 - * digits) plus room for the possibly-normalized divisor (var2ndigits - * digits). It is convenient also to have a zero at divisor[0] with the - * actual divisor data in divisor[1 .. var2ndigits]. Transferring the - * digits into the workspace also allows us to realloc the result (which - * might be the same as either input var) before we begin the main loop. - * Note that we use palloc0 to ensure that divisor[0], dividend[0], and - * any additional dividend positions beyond var1ndigits, start out 0. - */ - dividend = (NumericDigit *) - palloc0((div_ndigits + var2ndigits + 2) * sizeof(NumericDigit)); - divisor = dividend + (div_ndigits + 1); - memcpy(dividend + 1, var1->digits, var1ndigits * sizeof(NumericDigit)); - memcpy(divisor + 1, var2->digits, var2ndigits * sizeof(NumericDigit)); - - /* - * Now we can realloc the result to hold the generated quotient digits. - */ - alloc_var(result, res_ndigits); - res_digits = result->digits; + var1ndigitpairs = (var1ndigits + 1) / 2; + var2ndigitpairs = (var2ndigits + 1) / 2; + res_ndigitpairs = (res_ndigits + 1) / 2; + res_ndigits = 2 * res_ndigitpairs; /* - * The full multiple-place algorithm is taken from Knuth volume 2, - * Algorithm 4.3.1D. + * We do the arithmetic in an array "dividend[]" of signed 64-bit + * integers. Since PG_INT64_MAX is much larger than NBASE^4, this gives + * us a lot of headroom to avoid normalizing carries immediately. + * + * When performing an exact computation, the working dividend requires + * res_ndigitpairs + var2ndigitpairs digits. If var1 is larger than that, + * the extra digits do not contribute to the result, and are ignored. * - * We need the first divisor digit to be >= NBASE/2. If it isn't, make it - * so by scaling up both the divisor and dividend by the factor "d". (The - * reason for allocating dividend[0] above is to leave room for possible - * carry here.) + * When performing an approximate computation, the working dividend only + * requires res_ndigitpairs digits (which includes the extra guard + * digits). All input digits beyond that are ignored. */ - if (divisor[1] < HALF_NBASE) + if (exact) { - int d = NBASE / (divisor[1] + 1); - - carry = 0; - for (i = var2ndigits; i > 0; i--) - { - carry += divisor[i] * d; - divisor[i] = carry % NBASE; - carry = carry / NBASE; - } - Assert(carry == 0); - carry = 0; - /* at this point only var1ndigits of dividend can be nonzero */ - for (i = var1ndigits; i >= 0; i--) - { - carry += dividend[i] * d; - dividend[i] = carry % NBASE; - carry = carry / NBASE; - } - Assert(carry == 0); - Assert(divisor[1] >= HALF_NBASE); + div_ndigitpairs = res_ndigitpairs + var2ndigitpairs; + var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs); } - /* First 2 divisor digits are used repeatedly in main loop */ - divisor1 = divisor[1]; - divisor2 = divisor[2]; - - /* - * Begin the main loop. Each iteration of this loop produces the j'th - * quotient digit by dividing dividend[j .. j + var2ndigits] by the - * divisor; this is essentially the same as the common manual procedure - * for long division. - */ - for (j = 0; j < res_ndigits; j++) + else { - /* Estimate quotient digit from the first two dividend digits */ - int next2digits = dividend[j] * NBASE + dividend[j + 1]; - int qhat; - - /* - * If next2digits are 0, then quotient digit must be 0 and there's no - * need to adjust the working dividend. It's worth testing here to - * fall out ASAP when processing trailing zeroes in a dividend. - */ - if (next2digits == 0) - { - res_digits[j] = 0; - continue; - } - - if (dividend[j] == divisor1) - qhat = NBASE - 1; - else - qhat = next2digits / divisor1; - - /* - * Adjust quotient digit if it's too large. Knuth proves that after - * this step, the quotient digit will be either correct or just one - * too large. (Note: it's OK to use dividend[j+2] here because we - * know the divisor length is at least 2.) - */ - while (divisor2 * qhat > - (next2digits - qhat * divisor1) * NBASE + dividend[j + 2]) - qhat--; - - /* As above, need do nothing more when quotient digit is 0 */ - if (qhat > 0) - { - NumericDigit *dividend_j = ÷nd[j]; - - /* - * Multiply the divisor by qhat, and subtract that from the - * working dividend. The multiplication and subtraction are - * folded together here, noting that qhat <= NBASE (since it might - * be one too large), and so the intermediate result "tmp_result" - * is in the range [-NBASE^2, NBASE - 1], and "borrow" is in the - * range [0, NBASE]. - */ - borrow = 0; - for (i = var2ndigits; i >= 0; i--) - { - int tmp_result; - - tmp_result = dividend_j[i] - borrow - divisor[i] * qhat; - borrow = (NBASE - 1 - tmp_result) / NBASE; - dividend_j[i] = tmp_result + borrow * NBASE; - } - - /* - * If we got a borrow out of the top dividend digit, then indeed - * qhat was one too large. Fix it, and add back the divisor to - * correct the working dividend. (Knuth proves that this will - * occur only about 3/NBASE of the time; hence, it's a good idea - * to test this code with small NBASE to be sure this section gets - * exercised.) - */ - if (borrow) - { - qhat--; - carry = 0; - for (i = var2ndigits; i >= 0; i--) - { - carry += dividend_j[i] + divisor[i]; - if (carry >= NBASE) - { - dividend_j[i] = carry - NBASE; - carry = 1; - } - else - { - dividend_j[i] = carry; - carry = 0; - } - } - /* A carry should occur here to cancel the borrow above */ - Assert(carry == 1); - } - } - - /* And we're done with this quotient digit */ - res_digits[j] = qhat; + div_ndigitpairs = res_ndigitpairs; + var1ndigitpairs = Min(var1ndigitpairs, div_ndigitpairs); + var2ndigitpairs = Min(var2ndigitpairs, div_ndigitpairs); } - pfree(dividend); - - /* - * Finally, round or truncate the result to the requested precision. - */ - result->weight = res_weight; - result->sign = res_sign; - - /* Round or truncate to target rscale (and set result->dscale) */ - if (round) - round_var(result, rscale); - else - trunc_var(result, rscale); - - /* Strip leading and trailing zeroes */ - strip_var(result); -} - - -/* - * div_var_fast() - - * - * This has the same API as div_var, but is implemented using the division - * algorithm from the "FM" library, rather than Knuth's schoolbook-division - * approach. This is significantly faster but can produce inaccurate - * results, because it sometimes has to propagate rounding to the left, - * and so we can never be entirely sure that we know the requested digits - * exactly. We compute DIV_GUARD_DIGITS extra digits, but there is - * no certainty that that's enough. We use this only in the transcendental - * function calculation routines, where everything is approximate anyway. - * - * Although we provide a "round" argument for consistency with div_var, - * it is unwise to use this function with round=false. In truncation mode - * it is possible to get a result with no significant digits, for example - * with rscale=0 we might compute 0.99999... and truncate that to 0 when - * the correct answer is 1. - */ -static void -div_var_fast(const NumericVar *var1, const NumericVar *var2, - NumericVar *result, int rscale, bool round) -{ - int div_ndigits; - int load_ndigits; - int res_sign; - int res_weight; - int *div; - int qdigit; - int carry; - int maxdiv; - int newdig; - NumericDigit *res_digits; - double fdividend, - fdivisor, - fdivisorinverse, - fquotient; - int qi; - int i; - - /* copy these values into local vars for speed in inner loop */ - int var1ndigits = var1->ndigits; - int var2ndigits = var2->ndigits; - NumericDigit *var1digits = var1->digits; - NumericDigit *var2digits = var2->digits; - - /* - * First of all division by zero check; we must not be handed an - * unnormalized divisor. - */ - if (var2ndigits == 0 || var2digits[0] == 0) - ereport(ERROR, - (errcode(ERRCODE_DIVISION_BY_ZERO), - errmsg("division by zero"))); - /* - * If the divisor has just one or two digits, delegate to div_var_int(), - * which uses fast short division. + * Allocate room for the working dividend (div_ndigitpairs 64-bit digits) + * plus the divisor (var2ndigitpairs 32-bit base-NBASE^2 digits). * - * Similarly, on platforms with 128-bit integer support, delegate to - * div_var_int64() for divisors with three or four digits. + * For convenience, we allocate one extra dividend digit, which is set to + * zero and not counted in div_ndigitpairs, so that the main loop below + * can safely read and write the (qi+1)'th digit in the approximate case. */ - if (var2ndigits <= 2) - { - int idivisor; - int idivisor_weight; - - idivisor = var2->digits[0]; - idivisor_weight = var2->weight; - if (var2ndigits == 2) - { - idivisor = idivisor * NBASE + var2->digits[1]; - idivisor_weight--; - } - if (var2->sign == NUMERIC_NEG) - idivisor = -idivisor; - - div_var_int(var1, idivisor, idivisor_weight, result, rscale, round); - return; - } -#ifdef HAVE_INT128 - if (var2ndigits <= 4) - { - int64 idivisor; - int idivisor_weight; + dividend = (int64 *) palloc((div_ndigitpairs + 1) * sizeof(int64) + + var2ndigitpairs * sizeof(int32)); + divisor = (int32 *) (dividend + div_ndigitpairs + 1); - idivisor = var2->digits[0]; - idivisor_weight = var2->weight; - for (i = 1; i < var2ndigits; i++) - { - idivisor = idivisor * NBASE + var2->digits[i]; - idivisor_weight--; - } - if (var2->sign == NUMERIC_NEG) - idivisor = -idivisor; + /* load var1 into dividend[0 .. var1ndigitpairs-1], zeroing the rest */ + for (i = 0; i < var1ndigitpairs - 1; i++) + dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1]; - div_var_int64(var1, idivisor, idivisor_weight, result, rscale, round); - return; - } -#endif + if (2 * i + 1 < var1ndigits) + dividend[i] = var1->digits[2 * i] * NBASE + var1->digits[2 * i + 1]; + else + dividend[i] = var1->digits[2 * i] * NBASE; - /* - * Otherwise, perform full long division. - */ + memset(dividend + i + 1, 0, (div_ndigitpairs - i) * sizeof(int64)); - /* Result zero check */ - if (var1ndigits == 0) - { - zero_var(result); - result->dscale = rscale; - return; - } + /* load var2 into divisor[0 .. var2ndigitpairs-1] */ + for (i = 0; i < var2ndigitpairs - 1; i++) + divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1]; - /* - * Determine the result sign, weight and number of digits to calculate - */ - if (var1->sign == var2->sign) - res_sign = NUMERIC_POS; + if (2 * i + 1 < var2ndigits) + divisor[i] = var2->digits[2 * i] * NBASE + var2->digits[2 * i + 1]; else - res_sign = NUMERIC_NEG; - res_weight = var1->weight - var2->weight + 1; - /* The number of accurate result digits we need to produce: */ - div_ndigits = res_weight + 1 + (rscale + DEC_DIGITS - 1) / DEC_DIGITS; - /* Add guard digits for roundoff error */ - div_ndigits += DIV_GUARD_DIGITS; - if (div_ndigits < DIV_GUARD_DIGITS) - div_ndigits = DIV_GUARD_DIGITS; - - /* - * We do the arithmetic in an array "div[]" of signed int's. Since - * INT_MAX is noticeably larger than NBASE*NBASE, this gives us headroom - * to avoid normalizing carries immediately. - * - * We start with div[] containing one zero digit followed by the - * dividend's digits (plus appended zeroes to reach the desired precision - * including guard digits). Each step of the main loop computes an - * (approximate) quotient digit and stores it into div[], removing one - * position of dividend space. A final pass of carry propagation takes - * care of any mistaken quotient digits. - * - * Note that div[] doesn't necessarily contain all of the digits from the - * dividend --- the desired precision plus guard digits might be less than - * the dividend's precision. This happens, for example, in the square - * root algorithm, where we typically divide a 2N-digit number by an - * N-digit number, and only require a result with N digits of precision. - */ - div = (int *) palloc0((div_ndigits + 1) * sizeof(int)); - load_ndigits = Min(div_ndigits, var1ndigits); - for (i = 0; i < load_ndigits; i++) - div[i + 1] = var1digits[i]; + divisor[i] = var2->digits[2 * i] * NBASE; /* * We estimate each quotient digit using floating-point arithmetic, taking - * the first four digits of the (current) dividend and divisor. This must - * be float to avoid overflow. The quotient digits will generally be off - * by no more than one from the exact answer. - */ - fdivisor = (double) var2digits[0]; - for (i = 1; i < 4; i++) - { - fdivisor *= NBASE; - if (i < var2ndigits) - fdivisor += (double) var2digits[i]; - } + * the first 2 base-NBASE^2 digits of the (current) dividend and divisor. + * This must be float to avoid overflow. + * + * Since the floating-point dividend and divisor use 4 base-NBASE input + * digits, they include roughly 40-53 bits of information from their + * respective inputs (assuming NBASE is 10000), which fits well in IEEE + * double-precision variables. The relative error in the floating-point + * quotient digit will then be less than around 2/NBASE^3, so the + * estimated base-NBASE^2 quotient digit will typically be correct, and + * should not be off by more than one from the correct value. + */ + fdivisor = (double) divisor[0] * NBASE_SQR; + if (var2ndigitpairs > 1) + fdivisor += (double) divisor[1]; fdivisorinverse = 1.0 / fdivisor; /* - * maxdiv tracks the maximum possible absolute value of any div[] entry; - * when this threatens to exceed INT_MAX, we take the time to propagate - * carries. Furthermore, we need to ensure that overflow doesn't occur - * during the carry propagation passes either. The carry values may have - * an absolute value as high as INT_MAX/NBASE + 1, so really we must - * normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1. + * maxdiv tracks the maximum possible absolute value of any dividend[] + * entry; when this threatens to exceed PG_INT64_MAX, we take the time to + * propagate carries. Furthermore, we need to ensure that overflow + * doesn't occur during the carry propagation passes either. The carry + * values may have an absolute value as high as PG_INT64_MAX/NBASE^2 + 1, + * so really we must normalize when digits threaten to exceed PG_INT64_MAX + * - PG_INT64_MAX/NBASE^2 - 1. * * To avoid overflow in maxdiv itself, it represents the max absolute - * value divided by NBASE-1, ie, at the top of the loop it is known that - * no div[] entry has an absolute value exceeding maxdiv * (NBASE-1). + * value divided by NBASE^2-1, i.e., at the top of the loop it is known + * that no dividend[] entry has an absolute value exceeding maxdiv * + * (NBASE^2-1). * - * Actually, though, that holds good only for div[] entries after div[qi]; - * the adjustment done at the bottom of the loop may cause div[qi + 1] to - * exceed the maxdiv limit, so that div[qi] in the next iteration is - * beyond the limit. This does not cause problems, as explained below. + * Actually, though, that holds good only for dividend[] entries after + * dividend[qi]; the adjustment done at the bottom of the loop may cause + * dividend[qi + 1] to exceed the maxdiv limit, so that dividend[qi] in + * the next iteration is beyond the limit. This does not cause problems, + * as explained below. */ maxdiv = 1; /* - * Outer loop computes next quotient digit, which will go into div[qi] + * Outer loop computes next quotient digit, which goes in dividend[qi]. */ - for (qi = 0; qi < div_ndigits; qi++) + for (qi = 0; qi < res_ndigitpairs; qi++) { /* Approximate the current dividend value */ - fdividend = (double) div[qi]; - for (i = 1; i < 4; i++) - { - fdividend *= NBASE; - if (qi + i <= div_ndigits) - fdividend += (double) div[qi + i]; - } + fdividend = (double) dividend[qi] * NBASE_SQR; + fdividend += (double) dividend[qi + 1]; + /* Compute the (approximate) quotient digit */ fquotient = fdividend * fdivisorinverse; - qdigit = (fquotient >= 0.0) ? ((int) fquotient) : - (((int) fquotient) - 1); /* truncate towards -infinity */ + qdigit = (fquotient >= 0.0) ? ((int32) fquotient) : + (((int32) fquotient) - 1); /* truncate towards -infinity */ if (qdigit != 0) { /* Do we need to normalize now? */ - maxdiv += abs(qdigit); - if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1)) + maxdiv += i64abs(qdigit); + if (maxdiv > (PG_INT64_MAX - PG_INT64_MAX / NBASE_SQR - 1) / (NBASE_SQR - 1)) { /* - * Yes, do it. Note that if var2ndigits is much smaller than - * div_ndigits, we can save a significant amount of effort - * here by noting that we only need to normalise those div[] - * entries touched where prior iterations subtracted multiples - * of the divisor. + * Yes, do it. Note that if var2ndigitpairs is much smaller + * than div_ndigitpairs, we can save a significant amount of + * effort here by noting that we only need to normalise those + * dividend[] entries touched where prior iterations + * subtracted multiples of the divisor. */ carry = 0; - for (i = Min(qi + var2ndigits - 2, div_ndigits); i > qi; i--) + for (i = Min(qi + var2ndigitpairs - 2, div_ndigitpairs - 1); i > qi; i--) { - newdig = div[i] + carry; + newdig = dividend[i] + carry; if (newdig < 0) { - carry = -((-newdig - 1) / NBASE) - 1; - newdig -= carry * NBASE; + carry = -((-newdig - 1) / NBASE_SQR) - 1; + newdig -= carry * NBASE_SQR; } - else if (newdig >= NBASE) + else if (newdig >= NBASE_SQR) { - carry = newdig / NBASE; - newdig -= carry * NBASE; + carry = newdig / NBASE_SQR; + newdig -= carry * NBASE_SQR; } else carry = 0; - div[i] = newdig; + dividend[i] = newdig; } - newdig = div[qi] + carry; - div[qi] = newdig; + dividend[qi] += carry; /* - * All the div[] digits except possibly div[qi] are now in the - * range 0..NBASE-1. We do not need to consider div[qi] in - * the maxdiv value anymore, so we can reset maxdiv to 1. + * All the dividend[] digits except possibly dividend[qi] are + * now in the range 0..NBASE^2-1. We do not need to consider + * dividend[qi] in the maxdiv value anymore, so we can reset + * maxdiv to 1. */ maxdiv = 1; /* * Recompute the quotient digit since new info may have - * propagated into the top four dividend digits + * propagated into the top two dividend digits. */ - fdividend = (double) div[qi]; - for (i = 1; i < 4; i++) - { - fdividend *= NBASE; - if (qi + i <= div_ndigits) - fdividend += (double) div[qi + i]; - } - /* Compute the (approximate) quotient digit */ + fdividend = (double) dividend[qi] * NBASE_SQR; + fdividend += (double) dividend[qi + 1]; fquotient = fdividend * fdivisorinverse; - qdigit = (fquotient >= 0.0) ? ((int) fquotient) : - (((int) fquotient) - 1); /* truncate towards -infinity */ - maxdiv += abs(qdigit); + qdigit = (fquotient >= 0.0) ? ((int32) fquotient) : + (((int32) fquotient) - 1); /* truncate towards -infinity */ + + maxdiv += i64abs(qdigit); } /* * Subtract off the appropriate multiple of the divisor. * - * The digits beyond div[qi] cannot overflow, because we know they - * will fall within the maxdiv limit. As for div[qi] itself, note - * that qdigit is approximately trunc(div[qi] / vardigits[0]), - * which would make the new value simply div[qi] mod vardigits[0]. - * The lower-order terms in qdigit can change this result by not - * more than about twice INT_MAX/NBASE, so overflow is impossible. + * The digits beyond dividend[qi] cannot overflow, because we know + * they will fall within the maxdiv limit. As for dividend[qi] + * itself, note that qdigit is approximately trunc(dividend[qi] / + * divisor[0]), which would make the new value simply dividend[qi] + * mod divisor[0]. The lower-order terms in qdigit can change + * this result by not more than about twice PG_INT64_MAX/NBASE^2, + * so overflow is impossible. * * This inner loop is the performance bottleneck for division, so * code it in the same way as the inner loop of mul_var() so that - * it can be auto-vectorized. We cast qdigit to NumericDigit - * before multiplying to allow the compiler to generate more - * efficient code (using 16-bit multiplication), which is safe - * since we know that the quotient digit is off by at most one, so - * there is no overflow risk. + * it can be auto-vectorized. */ if (qdigit != 0) { - int istop = Min(var2ndigits, div_ndigits - qi + 1); - int *div_qi = &div[qi]; + int istop = Min(var2ndigitpairs, div_ndigitpairs - qi); + int64 *dividend_qi = ÷nd[qi]; for (i = 0; i < istop; i++) - div_qi[i] -= ((NumericDigit) qdigit) * var2digits[i]; + dividend_qi[i] -= (int64) qdigit * divisor[i]; } } @@ -9677,78 +9700,192 @@ div_var_fast(const NumericVar *var1, const NumericVar *var2, * Fold it into the next digit position. * * There is no risk of overflow here, although proving that requires - * some care. Much as with the argument for div[qi] not overflowing, - * if we consider the first two terms in the numerator and denominator - * of qdigit, we can see that the final value of div[qi + 1] will be - * approximately a remainder mod (vardigits[0]*NBASE + vardigits[1]). - * Accounting for the lower-order terms is a bit complicated but ends - * up adding not much more than INT_MAX/NBASE to the possible range. - * Thus, div[qi + 1] cannot overflow here, and in its role as div[qi] - * in the next loop iteration, it can't be large enough to cause - * overflow in the carry propagation step (if any), either. + * some care. Much as with the argument for dividend[qi] not + * overflowing, if we consider the first two terms in the numerator + * and denominator of qdigit, we can see that the final value of + * dividend[qi + 1] will be approximately a remainder mod + * (divisor[0]*NBASE^2 + divisor[1]). Accounting for the lower-order + * terms is a bit complicated but ends up adding not much more than + * PG_INT64_MAX/NBASE^2 to the possible range. Thus, dividend[qi + 1] + * cannot overflow here, and in its role as dividend[qi] in the next + * loop iteration, it can't be large enough to cause overflow in the + * carry propagation step (if any), either. * - * But having said that: div[qi] can be more than INT_MAX/NBASE, as - * noted above, which means that the product div[qi] * NBASE *can* - * overflow. When that happens, adding it to div[qi + 1] will always - * cause a canceling overflow so that the end result is correct. We - * could avoid the intermediate overflow by doing the multiplication - * and addition in int64 arithmetic, but so far there appears no need. + * But having said that: dividend[qi] can be more than + * PG_INT64_MAX/NBASE^2, as noted above, which means that the product + * dividend[qi] * NBASE^2 *can* overflow. When that happens, adding + * it to dividend[qi + 1] will always cause a canceling overflow so + * that the end result is correct. We could avoid the intermediate + * overflow by doing the multiplication and addition using unsigned + * int64 arithmetic, which is modulo 2^64, but so far there appears no + * need. */ - div[qi + 1] += div[qi] * NBASE; + dividend[qi + 1] += dividend[qi] * NBASE_SQR; - div[qi] = qdigit; + dividend[qi] = qdigit; } /* - * Approximate and store the last quotient digit (div[div_ndigits]) + * If an exact result was requested, use the remainder to correct the + * approximate quotient. The remainder is in dividend[], immediately + * after the quotient digits. Note, however, that although the remainder + * starts at dividend[qi = res_ndigitpairs], the first digit is the result + * of folding two remainder digits into one above, and the remainder + * currently only occupies var2ndigitpairs - 1 digits (the last digit of + * the working dividend was untouched by the computation above). Thus we + * expand the remainder down by one base-NBASE^2 digit when we normalize + * it, so that it completely fills the last var2ndigitpairs digits of the + * dividend array. */ - fdividend = (double) div[qi]; - for (i = 1; i < 4; i++) - fdividend *= NBASE; - fquotient = fdividend * fdivisorinverse; - qdigit = (fquotient >= 0.0) ? ((int) fquotient) : - (((int) fquotient) - 1); /* truncate towards -infinity */ - div[qi] = qdigit; + if (exact) + { + /* Normalize the remainder, expanding it down by one digit */ + remainder = ÷nd[qi]; + carry = 0; + for (i = var2ndigitpairs - 2; i >= 0; i--) + { + newdig = remainder[i] + carry; + if (newdig < 0) + { + carry = -((-newdig - 1) / NBASE_SQR) - 1; + newdig -= carry * NBASE_SQR; + } + else if (newdig >= NBASE_SQR) + { + carry = newdig / NBASE_SQR; + newdig -= carry * NBASE_SQR; + } + else + carry = 0; + remainder[i + 1] = newdig; + } + remainder[0] = carry; + + if (remainder[0] < 0) + { + /* + * The remainder is negative, so the approximate quotient is too + * large. Correct by reducing the quotient by one and adding the + * divisor to the remainder until the remainder is positive. We + * expect the quotient to be off by at most one, which has been + * borne out in all testing, but not conclusively proven, so we + * allow for larger corrections, just in case. + */ + do + { + /* Add the divisor to the remainder */ + carry = 0; + for (i = var2ndigitpairs - 1; i > 0; i--) + { + newdig = remainder[i] + divisor[i] + carry; + if (newdig >= NBASE_SQR) + { + remainder[i] = newdig - NBASE_SQR; + carry = 1; + } + else + { + remainder[i] = newdig; + carry = 0; + } + } + remainder[0] += divisor[0] + carry; + + /* Subtract 1 from the quotient (propagating carries later) */ + dividend[qi - 1]--; + + } while (remainder[0] < 0); + } + else + { + /* + * The remainder is nonnegative. If it's greater than or equal to + * the divisor, then the approximate quotient is too small and + * must be corrected. As above, we don't expect to have to apply + * more than one correction, but allow for it just in case. + */ + while (true) + { + bool less = false; + + /* Is remainder < divisor? */ + for (i = 0; i < var2ndigitpairs; i++) + { + if (remainder[i] < divisor[i]) + { + less = true; + break; + } + if (remainder[i] > divisor[i]) + break; /* remainder > divisor */ + } + if (less) + break; /* quotient is correct */ + + /* Subtract the divisor from the remainder */ + carry = 0; + for (i = var2ndigitpairs - 1; i > 0; i--) + { + newdig = remainder[i] - divisor[i] + carry; + if (newdig < 0) + { + remainder[i] = newdig + NBASE_SQR; + carry = -1; + } + else + { + remainder[i] = newdig; + carry = 0; + } + } + remainder[0] = remainder[0] - divisor[0] + carry; + + /* Add 1 to the quotient (propagating carries later) */ + dividend[qi - 1]++; + } + } + } /* - * Because the quotient digits might be off by one, some of them might be - * -1 or NBASE at this point. The represented value is correct in a - * mathematical sense, but it doesn't look right. We do a final carry - * propagation pass to normalize the digits, which we combine with storing - * the result digits into the output. Note that this is still done at - * full precision w/guard digits. + * Because the quotient digits were estimates that might have been off by + * one (and we didn't bother propagating carries when adjusting the + * quotient above), some quotient digits might be out of range, so do a + * final carry propagation pass to normalize back to base NBASE^2, and + * construct the base-NBASE result digits. Note that this is still done + * at full precision w/guard digits. */ - alloc_var(result, div_ndigits + 1); + alloc_var(result, res_ndigits); res_digits = result->digits; carry = 0; - for (i = div_ndigits; i >= 0; i--) + for (i = res_ndigitpairs - 1; i >= 0; i--) { - newdig = div[i] + carry; + newdig = dividend[i] + carry; if (newdig < 0) { - carry = -((-newdig - 1) / NBASE) - 1; - newdig -= carry * NBASE; + carry = -((-newdig - 1) / NBASE_SQR) - 1; + newdig -= carry * NBASE_SQR; } - else if (newdig >= NBASE) + else if (newdig >= NBASE_SQR) { - carry = newdig / NBASE; - newdig -= carry * NBASE; + carry = newdig / NBASE_SQR; + newdig -= carry * NBASE_SQR; } else carry = 0; - res_digits[i] = newdig; + res_digits[2 * i + 1] = (NumericDigit) ((uint32) newdig % NBASE); + res_digits[2 * i] = (NumericDigit) ((uint32) newdig / NBASE); } Assert(carry == 0); - pfree(div); + pfree(dividend); /* - * Finally, round the result to the requested precision. + * Finally, round or truncate the result to the requested precision. */ result->weight = res_weight; result->sign = res_sign; - /* Round to target rscale (and set result->dscale) */ + /* Round or truncate to target rscale (and set result->dscale) */ if (round) round_var(result, rscale); else @@ -10075,7 +10212,7 @@ mod_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result) * div_var can be persuaded to give us trunc(x/y) directly. * ---------- */ - div_var(var1, var2, &tmp, 0, false); + div_var(var1, var2, &tmp, 0, false, true); mul_var(var2, &tmp, &tmp, var2->dscale); @@ -10102,11 +10239,11 @@ div_mod_var(const NumericVar *var1, const NumericVar *var2, init_var(&r); /* - * Use div_var_fast() to get an initial estimate for the integer quotient. - * This might be inaccurate (per the warning in div_var_fast's comments), - * but we can correct it below. + * Use div_var() with exact = false to get an initial estimate for the + * integer quotient (truncated towards zero). This might be slightly + * inaccurate, but we correct it below. */ - div_var_fast(var1, var2, &q, 0, false); + div_var(var1, var2, &q, 0, false, false); /* Compute initial estimate of remainder using the quotient estimate. */ mul_var(var2, &q, &r, var2->dscale); @@ -11049,7 +11186,7 @@ ln_var(const NumericVar *arg, NumericVar *result, int rscale) sub_var(&x, &const_one, result); add_var(&x, &const_one, &elem); - div_var_fast(result, &elem, result, local_rscale, true); + div_var(result, &elem, result, local_rscale, true, false); set_var_from_var(result, &xx); mul_var(result, result, &x, local_rscale); @@ -11133,7 +11270,7 @@ log_var(const NumericVar *base, const NumericVar *num, NumericVar *result) ln_var(num, &ln_num, ln_num_rscale); /* Divide and round to the required scale */ - div_var_fast(&ln_num, &ln_base, result, rscale, true); + div_var(&ln_num, &ln_base, result, rscale, true, false); free_var(&ln_num); free_var(&ln_base); @@ -11395,7 +11532,7 @@ power_var_int(const NumericVar *base, int exp, int exp_dscale, round_var(result, rscale); return; case -1: - div_var(&const_one, base, result, rscale, true); + div_var(&const_one, base, result, rscale, true, true); return; case 2: mul_var(base, base, result, rscale); @@ -11443,7 +11580,7 @@ power_var_int(const NumericVar *base, int exp, int exp_dscale, * Now we can proceed with the multiplications. */ neg = (exp < 0); - mask = abs(exp); + mask = pg_abs_s32(exp); init_var(&base_prod); set_var_from_var(base, &base_prod); @@ -11503,7 +11640,7 @@ power_var_int(const NumericVar *base, int exp, int exp_dscale, /* Compensate for input sign, and round to requested rscale */ if (neg) - div_var_fast(&const_one, result, result, rscale, true); + div_var(&const_one, result, result, rscale, true, false); else round_var(result, rscale); } diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c index adc1e8a4cba20..3bf30774a0c94 100644 --- a/src/backend/utils/adt/numutils.c +++ b/src/backend/utils/adt/numutils.c @@ -3,7 +3,7 @@ * numutils.c * utility functions for I/O of built-in numeric types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -18,6 +18,7 @@ #include #include +#include "common/int.h" #include "port/pg_bitutils.h" #include "utils/builtins.h" @@ -131,6 +132,7 @@ pg_strtoint16_safe(const char *s, Node *escontext) uint16 tmp = 0; bool neg = false; unsigned char digit; + int16 result; /* * The majority of cases are likely to be base-10 digits without any @@ -190,10 +192,9 @@ pg_strtoint16_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1)) + if (unlikely(pg_neg_u16_overflow(tmp, &result))) goto out_of_range; - return -((int16) tmp); + return result; } if (unlikely(tmp > PG_INT16_MAX)) @@ -333,10 +334,9 @@ pg_strtoint16_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint16) (-(PG_INT16_MIN + 1)) + 1) + if (unlikely(pg_neg_u16_overflow(tmp, &result))) goto out_of_range; - return -((int16) tmp); + return result; } if (tmp > PG_INT16_MAX) @@ -393,6 +393,7 @@ pg_strtoint32_safe(const char *s, Node *escontext) uint32 tmp = 0; bool neg = false; unsigned char digit; + int32 result; /* * The majority of cases are likely to be base-10 digits without any @@ -452,10 +453,9 @@ pg_strtoint32_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1)) + if (unlikely(pg_neg_u32_overflow(tmp, &result))) goto out_of_range; - return -((int32) tmp); + return result; } if (unlikely(tmp > PG_INT32_MAX)) @@ -595,10 +595,9 @@ pg_strtoint32_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint32) (-(PG_INT32_MIN + 1)) + 1) + if (unlikely(pg_neg_u32_overflow(tmp, &result))) goto out_of_range; - return -((int32) tmp); + return result; } if (tmp > PG_INT32_MAX) @@ -655,6 +654,7 @@ pg_strtoint64_safe(const char *s, Node *escontext) uint64 tmp = 0; bool neg = false; unsigned char digit; + int64 result; /* * The majority of cases are likely to be base-10 digits without any @@ -714,10 +714,9 @@ pg_strtoint64_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (unlikely(tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1)) + if (unlikely(pg_neg_u64_overflow(tmp, &result))) goto out_of_range; - return -((int64) tmp); + return result; } if (unlikely(tmp > PG_INT64_MAX)) @@ -857,10 +856,9 @@ pg_strtoint64_safe(const char *s, Node *escontext) if (neg) { - /* check the negative equivalent will fit without overflowing */ - if (tmp > (uint64) (-(PG_INT64_MIN + 1)) + 1) + if (unlikely(pg_neg_u64_overflow(tmp, &result))) goto out_of_range; - return -((int64) tmp); + return result; } if (tmp > PG_INT64_MAX) diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index 56fb1fd77cee5..4e880e7623273 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -3,7 +3,7 @@ * oid.c * Functions for the built-in type Oid ... also oidvector. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index b126a7d460dc3..a24a2d208fba7 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -2,7 +2,7 @@ * oracle_compat.c * Oracle compatible functions. * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * Author: Edmund Mergl * Multibyte enhancement: Tatsuo Ishii @@ -126,6 +126,22 @@ initcap(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(result); } +Datum +casefold(PG_FUNCTION_ARGS) +{ + text *in_string = PG_GETARG_TEXT_PP(0); + char *out_string; + text *result; + + out_string = str_casefold(VARDATA_ANY(in_string), + VARSIZE_ANY_EXHDR(in_string), + PG_GET_COLLATION()); + result = cstring_to_text(out_string); + pfree(out_string); + + PG_RETURN_TEXT_P(result); +} + /******************************************************************** * diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index 04b3f31827e53..9457d23971581 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -3,7 +3,7 @@ * orderedsetaggs.c * Ordered-set aggregate functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -270,7 +270,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) &qstate->typAlign); } - fcinfo->flinfo->fn_extra = (void *) qstate; + fcinfo->flinfo->fn_extra = qstate; MemoryContextSwitchTo(oldcontext); } diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index fe19007970d28..61f07ac08b94d 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -3,7 +3,7 @@ * partitionfuncs.c * Functions for accessing partition-related metadata * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -92,7 +92,7 @@ pg_partition_tree(PG_FUNCTION_ARGS) funcctx->tuple_desc = tupdesc; /* The only state we need is the partition list */ - funcctx->user_fctx = (void *) partitions; + funcctx->user_fctx = partitions; MemoryContextSwitchTo(oldcxt); } @@ -219,7 +219,7 @@ pg_partition_ancestors(PG_FUNCTION_ARGS) ancestors = lcons_oid(relid, ancestors); /* The only state we need is the ancestors list */ - funcctx->user_fctx = (void *) ancestors; + funcctx->user_fctx = ancestors; MemoryContextSwitchTo(oldcxt); } diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 38c40a4048976..f5e31c433a0de 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -2,7 +2,7 @@ * * PostgreSQL locale utilities * - * Portions Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2002-2025, PostgreSQL Global Development Group * * src/backend/utils/adt/pg_locale.c * @@ -18,34 +18,13 @@ * LC_MESSAGES is settable at run time and will take effect * immediately. * - * The other categories, LC_MONETARY, LC_NUMERIC, and LC_TIME are also - * settable at run-time. However, we don't actually set those locale - * categories permanently. This would have bizarre effects like no - * longer accepting standard floating-point literals in some locales. - * Instead, we only set these locale categories briefly when needed, - * cache the required information obtained from localeconv() or - * strftime(), and then set the locale categories back to "C". + * The other categories, LC_MONETARY, LC_NUMERIC, and LC_TIME are + * permanently set to "C", and then we use temporary locale_t + * objects when we need to look up locale data based on the GUCs + * of the same name. Information is cached when the GUCs change. * The cached information is only used by the formatting functions * (to_char, etc.) and the money type. For the user, this should all be * transparent. - * - * !!! NOW HEAR THIS !!! - * - * We've been bitten repeatedly by this bug, so let's try to keep it in - * mind in future: on some platforms, the locale functions return pointers - * to static data that will be overwritten by any later locale function. - * Thus, for example, the obvious-looking sequence - * save = setlocale(category, NULL); - * if (!setlocale(category, value)) - * fail = true; - * setlocale(category, save); - * DOES NOT WORK RELIABLY: on some platforms the second setlocale() call - * will change the memory save is pointing at. To do this sort of thing - * safely, you *must* pstrdup what setlocale returns the first time. - * - * The POSIX locale standard is available here: - * - * http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html *---------- */ @@ -56,26 +35,20 @@ #include "access/htup_details.h" #include "catalog/pg_collation.h" +#include "catalog/pg_database.h" +#include "common/hashfn.h" +#include "common/string.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/formatting.h" #include "utils/guc_hooks.h" -#include "utils/hsearch.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/pg_locale.h" +#include "utils/relcache.h" #include "utils/syscache.h" -#ifdef USE_ICU -#include -#include -#endif - -#ifdef __GLIBC__ -#include -#endif - #ifdef WIN32 #include #endif @@ -92,6 +65,45 @@ #define MAX_L10N_DATA 80 +/* pg_locale_builtin.c */ +extern pg_locale_t create_pg_locale_builtin(Oid collid, MemoryContext context); +extern char *get_collation_actual_version_builtin(const char *collcollate); + +/* pg_locale_icu.c */ +#ifdef USE_ICU +extern UCollator *pg_ucol_open(const char *loc_str); +extern char *get_collation_actual_version_icu(const char *collcollate); +#endif +extern pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context); + +/* pg_locale_libc.c */ +extern pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context); +extern char *get_collation_actual_version_libc(const char *collcollate); + +extern size_t strlower_builtin(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_builtin(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_builtin(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strfold_builtin(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); + +extern size_t strlower_icu(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_icu(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_icu(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strfold_icu(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); + +extern size_t strlower_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); /* GUC settings */ char *locale_messages; @@ -116,6 +128,8 @@ char *localized_full_months[12 + 1]; /* is the databases's LC_CTYPE the C locale? */ bool database_ctype_is_c = false; +static pg_locale_t default_locale = NULL; + /* indicates whether locale information cache is valid */ static bool CurrentLocaleConvValid = false; static bool CurrentLCTimeValid = false; @@ -125,73 +139,38 @@ static bool CurrentLCTimeValid = false; typedef struct { Oid collid; /* hash key: pg_collation OID */ - bool collate_is_c; /* is collation's LC_COLLATE C? */ - bool ctype_is_c; /* is collation's LC_CTYPE C? */ - bool flags_valid; /* true if above flags are valid */ pg_locale_t locale; /* locale_t struct, or 0 if not valid */ -} collation_cache_entry; - -static HTAB *collation_cache = NULL; - -#if defined(WIN32) && defined(LC_MESSAGES) -static char *IsoLocaleName(const char *); -#endif + /* needed for simplehash */ + uint32 hash; + char status; +} collation_cache_entry; -#ifdef USE_ICU -/* - * Converter object for converting between ICU's UChar strings and C strings - * in database encoding. Since the database encoding doesn't change, we only - * need one of these per session. - */ -static UConverter *icu_converter = NULL; - -static UCollator *pg_ucol_open(const char *loc_str); -static void init_icu_converter(void); -static size_t uchar_length(UConverter *converter, - const char *str, int32_t len); -static int32_t uchar_convert(UConverter *converter, - UChar *dest, int32_t destlen, - const char *src, int32_t srclen); -static void icu_set_collation_attributes(UCollator *collator, const char *loc, - UErrorCode *status); -#endif +#define SH_PREFIX collation_cache +#define SH_ELEMENT_TYPE collation_cache_entry +#define SH_KEY_TYPE Oid +#define SH_KEY collid +#define SH_HASH_KEY(tb, key) murmurhash32((uint32) key) +#define SH_EQUAL(tb, a, b) (a == b) +#define SH_GET_HASH(tb, a) a->hash +#define SH_SCOPE static inline +#define SH_STORE_HASH +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" + +static MemoryContext CollationCacheContext = NULL; +static collation_cache_hash *CollationCache = NULL; /* - * POSIX doesn't define _l-variants of these functions, but several systems - * have them. We provide our own replacements here. + * The collation cache is often accessed repeatedly for the same collation, so + * remember the last one used. */ -#ifndef HAVE_MBSTOWCS_L -static size_t -mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc) -{ -#ifdef WIN32 - return _mbstowcs_l(dest, src, n, loc); -#else - size_t result; - locale_t save_locale = uselocale(loc); - - result = mbstowcs(dest, src, n); - uselocale(save_locale); - return result; -#endif -} -#endif -#ifndef HAVE_WCSTOMBS_L -static size_t -wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc) -{ -#ifdef WIN32 - return _wcstombs_l(dest, src, n, loc); -#else - size_t result; - locale_t save_locale = uselocale(loc); +static Oid last_collation_cache_oid = InvalidOid; +static pg_locale_t last_collation_cache_locale = NULL; - result = wcstombs(dest, src, n); - uselocale(save_locale); - return result; -#endif -} +#if defined(WIN32) && defined(LC_MESSAGES) +static char *IsoLocaleName(const char *); #endif /* @@ -317,6 +296,16 @@ check_locale(int category, const char *locale, char **canonname) char *save; char *res; + /* Don't let Windows' non-ASCII locale names in. */ + if (!pg_is_ascii(locale)) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("locale name \"%s\" contains non-ASCII characters", + locale))); + return false; + } + if (canonname) *canonname = NULL; /* in case of failure */ @@ -339,6 +328,18 @@ check_locale(int category, const char *locale, char **canonname) elog(WARNING, "failed to restore old locale \"%s\"", save); pfree(save); + /* Don't let Windows' non-ASCII locale names out. */ + if (canonname && *canonname && !pg_is_ascii(*canonname)) + { + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("locale name \"%s\" contains non-ASCII characters", + *canonname))); + pfree(*canonname); + *canonname = NULL; + return false; + } + return (res != NULL); } @@ -526,12 +527,8 @@ PGLC_localeconv(void) static struct lconv CurrentLocaleConv; static bool CurrentLocaleConvAllocated = false; struct lconv *extlconv; - struct lconv worklconv; - char *save_lc_monetary; - char *save_lc_numeric; -#ifdef WIN32 - char *save_lc_ctype; -#endif + struct lconv tmp; + struct lconv worklconv = {0}; /* Did we do it already? */ if (CurrentLocaleConvValid) @@ -545,77 +542,21 @@ PGLC_localeconv(void) } /* - * This is tricky because we really don't want to risk throwing error - * while the locale is set to other than our usual settings. Therefore, - * the process is: collect the usual settings, set locale to special - * setting, copy relevant data into worklconv using strdup(), restore - * normal settings, convert data to desired encoding, and finally stash - * the collected data in CurrentLocaleConv. This makes it safe if we - * throw an error during encoding conversion or run out of memory anywhere - * in the process. All data pointed to by struct lconv members is - * allocated with strdup, to avoid premature elog(ERROR) and to allow - * using a single cleanup routine. - */ - memset(&worklconv, 0, sizeof(worklconv)); - - /* Save prevailing values of monetary and numeric locales */ - save_lc_monetary = setlocale(LC_MONETARY, NULL); - if (!save_lc_monetary) - elog(ERROR, "setlocale(NULL) failed"); - save_lc_monetary = pstrdup(save_lc_monetary); - - save_lc_numeric = setlocale(LC_NUMERIC, NULL); - if (!save_lc_numeric) - elog(ERROR, "setlocale(NULL) failed"); - save_lc_numeric = pstrdup(save_lc_numeric); - -#ifdef WIN32 - - /* - * The POSIX standard explicitly says that it is undefined what happens if - * LC_MONETARY or LC_NUMERIC imply an encoding (codeset) different from - * that implied by LC_CTYPE. In practice, all Unix-ish platforms seem to - * believe that localeconv() should return strings that are encoded in the - * codeset implied by the LC_MONETARY or LC_NUMERIC locale name. Hence, - * once we have successfully collected the localeconv() results, we will - * convert them from that codeset to the desired server encoding. - * - * Windows, of course, resolutely does things its own way; on that - * platform LC_CTYPE has to match LC_MONETARY/LC_NUMERIC to get sane - * results. Hence, we must temporarily set that category as well. + * Use thread-safe method of obtaining a copy of lconv from the operating + * system. */ - - /* Save prevailing value of ctype locale */ - save_lc_ctype = setlocale(LC_CTYPE, NULL); - if (!save_lc_ctype) - elog(ERROR, "setlocale(NULL) failed"); - save_lc_ctype = pstrdup(save_lc_ctype); - - /* Here begins the critical section where we must not throw error */ - - /* use numeric to set the ctype */ - setlocale(LC_CTYPE, locale_numeric); -#endif - - /* Get formatting information for numeric */ - setlocale(LC_NUMERIC, locale_numeric); - extlconv = localeconv(); - - /* Must copy data now in case setlocale() overwrites it */ + if (pg_localeconv_r(locale_monetary, + locale_numeric, + &tmp) != 0) + elog(ERROR, + "could not get lconv for LC_MONETARY = \"%s\", LC_NUMERIC = \"%s\": %m", + locale_monetary, locale_numeric); + + /* Must copy data now so we can re-encode it. */ + extlconv = &tmp; worklconv.decimal_point = strdup(extlconv->decimal_point); worklconv.thousands_sep = strdup(extlconv->thousands_sep); worklconv.grouping = strdup(extlconv->grouping); - -#ifdef WIN32 - /* use monetary to set the ctype */ - setlocale(LC_CTYPE, locale_monetary); -#endif - - /* Get formatting information for monetary */ - setlocale(LC_MONETARY, locale_monetary); - extlconv = localeconv(); - - /* Must copy data now in case setlocale() overwrites it */ worklconv.int_curr_symbol = strdup(extlconv->int_curr_symbol); worklconv.currency_symbol = strdup(extlconv->currency_symbol); worklconv.mon_decimal_point = strdup(extlconv->mon_decimal_point); @@ -633,45 +574,19 @@ PGLC_localeconv(void) worklconv.p_sign_posn = extlconv->p_sign_posn; worklconv.n_sign_posn = extlconv->n_sign_posn; - /* - * Restore the prevailing locale settings; failure to do so is fatal. - * Possibly we could limp along with nondefault LC_MONETARY or LC_NUMERIC, - * but proceeding with the wrong value of LC_CTYPE would certainly be bad - * news; and considering that the prevailing LC_MONETARY and LC_NUMERIC - * are almost certainly "C", there's really no reason that restoring those - * should fail. - */ -#ifdef WIN32 - if (!setlocale(LC_CTYPE, save_lc_ctype)) - elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype); -#endif - if (!setlocale(LC_MONETARY, save_lc_monetary)) - elog(FATAL, "failed to restore LC_MONETARY to \"%s\"", save_lc_monetary); - if (!setlocale(LC_NUMERIC, save_lc_numeric)) - elog(FATAL, "failed to restore LC_NUMERIC to \"%s\"", save_lc_numeric); + /* Free the contents of the object populated by pg_localeconv_r(). */ + pg_localeconv_free(&tmp); + + /* If any of the preceding strdup calls failed, complain now. */ + if (!struct_lconv_is_valid(&worklconv)) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); - /* - * At this point we've done our best to clean up, and can call functions - * that might possibly throw errors with a clean conscience. But let's - * make sure we don't leak any already-strdup'd fields in worklconv. - */ PG_TRY(); { int encoding; - /* Release the pstrdup'd locale names */ - pfree(save_lc_monetary); - pfree(save_lc_numeric); -#ifdef WIN32 - pfree(save_lc_ctype); -#endif - - /* If any of the preceding strdup calls failed, complain now. */ - if (!struct_lconv_is_valid(&worklconv)) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - /* * Now we must perform encoding conversion from whatever's associated * with the locales into the database encoding. If we can't identify @@ -732,8 +647,8 @@ PGLC_localeconv(void) * pg_strftime(), which isn't locale-aware and does not need to be replaced. */ static size_t -strftime_win32(char *dst, size_t dstlen, - const char *format, const struct tm *tm) +strftime_l_win32(char *dst, size_t dstlen, + const char *format, const struct tm *tm, locale_t locale) { size_t len; wchar_t wformat[8]; /* formats used below need 3 chars */ @@ -749,7 +664,7 @@ strftime_win32(char *dst, size_t dstlen, elog(ERROR, "could not convert format string from UTF-8: error code %lu", GetLastError()); - len = wcsftime(wbuf, MAX_L10N_DATA, wformat, tm); + len = _wcsftime_l(wbuf, MAX_L10N_DATA, wformat, tm, locale); if (len == 0) { /* @@ -770,8 +685,8 @@ strftime_win32(char *dst, size_t dstlen, return len; } -/* redefine strftime() */ -#define strftime(a,b,c,d) strftime_win32(a,b,c,d) +/* redefine strftime_l() */ +#define strftime_l(a,b,c,d,e) strftime_l_win32(a,b,c,d,e) #endif /* WIN32 */ /* @@ -809,13 +724,11 @@ cache_locale_time(void) char *bufptr; time_t timenow; struct tm *timeinfo; + struct tm timeinfobuf; bool strftimefail = false; int encoding; int i; - char *save_lc_time; -#ifdef WIN32 - char *save_lc_ctype; -#endif + locale_t locale; /* did we do this already? */ if (CurrentLCTimeValid) @@ -823,43 +736,20 @@ cache_locale_time(void) elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time); - /* - * As in PGLC_localeconv(), it's critical that we not throw error while - * libc's locale settings have nondefault values. Hence, we just call - * strftime() within the critical section, and then convert and save its - * results afterwards. - */ - - /* Save prevailing value of time locale */ - save_lc_time = setlocale(LC_TIME, NULL); - if (!save_lc_time) - elog(ERROR, "setlocale(NULL) failed"); - save_lc_time = pstrdup(save_lc_time); - + errno = ENOENT; #ifdef WIN32 - - /* - * On Windows, it appears that wcsftime() internally uses LC_CTYPE, so we - * must set it here. This code looks the same as what PGLC_localeconv() - * does, but the underlying reason is different: this does NOT determine - * the encoding we'll get back from strftime_win32(). - */ - - /* Save prevailing value of ctype locale */ - save_lc_ctype = setlocale(LC_CTYPE, NULL); - if (!save_lc_ctype) - elog(ERROR, "setlocale(NULL) failed"); - save_lc_ctype = pstrdup(save_lc_ctype); - - /* use lc_time to set the ctype */ - setlocale(LC_CTYPE, locale_time); + locale = _create_locale(LC_ALL, locale_time); + if (locale == (locale_t) 0) + _dosmaperr(GetLastError()); +#else + locale = newlocale(LC_ALL_MASK, locale_time, (locale_t) 0); #endif - - setlocale(LC_TIME, locale_time); + if (!locale) + report_newlocale_failure(locale_time); /* We use times close to current time as data for strftime(). */ timenow = time(NULL); - timeinfo = localtime(&timenow); + timeinfo = gmtime_r(&timenow, &timeinfobuf); /* Store the strftime results in MAX_L10N_DATA-sized portions of buf[] */ bufptr = buf; @@ -878,10 +768,10 @@ cache_locale_time(void) for (i = 0; i < 7; i++) { timeinfo->tm_wday = i; - if (strftime(bufptr, MAX_L10N_DATA, "%a", timeinfo) <= 0) + if (strftime_l(bufptr, MAX_L10N_DATA, "%a", timeinfo, locale) <= 0) strftimefail = true; bufptr += MAX_L10N_DATA; - if (strftime(bufptr, MAX_L10N_DATA, "%A", timeinfo) <= 0) + if (strftime_l(bufptr, MAX_L10N_DATA, "%A", timeinfo, locale) <= 0) strftimefail = true; bufptr += MAX_L10N_DATA; } @@ -891,37 +781,26 @@ cache_locale_time(void) { timeinfo->tm_mon = i; timeinfo->tm_mday = 1; /* make sure we don't have invalid date */ - if (strftime(bufptr, MAX_L10N_DATA, "%b", timeinfo) <= 0) + if (strftime_l(bufptr, MAX_L10N_DATA, "%b", timeinfo, locale) <= 0) strftimefail = true; bufptr += MAX_L10N_DATA; - if (strftime(bufptr, MAX_L10N_DATA, "%B", timeinfo) <= 0) + if (strftime_l(bufptr, MAX_L10N_DATA, "%B", timeinfo, locale) <= 0) strftimefail = true; bufptr += MAX_L10N_DATA; } - /* - * Restore the prevailing locale settings; as in PGLC_localeconv(), - * failure to do so is fatal. - */ #ifdef WIN32 - if (!setlocale(LC_CTYPE, save_lc_ctype)) - elog(FATAL, "failed to restore LC_CTYPE to \"%s\"", save_lc_ctype); + _free_locale(locale); +#else + freelocale(locale); #endif - if (!setlocale(LC_TIME, save_lc_time)) - elog(FATAL, "failed to restore LC_TIME to \"%s\"", save_lc_time); /* * At this point we've done our best to clean up, and can throw errors, or * call functions that might throw errors, with a clean conscience. */ if (strftimefail) - elog(ERROR, "strftime() failed: %m"); - - /* Release the pstrdup'd locale names */ - pfree(save_lc_time); -#ifdef WIN32 - pfree(save_lc_ctype); -#endif + elog(ERROR, "strftime_l() failed"); #ifndef WIN32 @@ -1005,13 +884,6 @@ cache_locale_time(void) * get ISO Locale name directly by using GetLocaleInfoEx() with LCType as * LOCALE_SNAME. * - * MinGW headers declare _create_locale(), but msvcrt.dll lacks that symbol in - * releases before Windows 8. IsoLocaleName() always fails in a MinGW-built - * postgres.exe, so only Unix-style values of the lc_messages GUC can elicit - * localized messages. In particular, every lc_messages setting that initdb - * can select automatically will yield only C-locale messages. XXX This could - * be fixed by running the fully-qualified locale name through a lookup table. - * * This function returns a pointer to a static buffer bearing the converted * name or NULL if conversion fails. * @@ -1019,8 +891,6 @@ cache_locale_time(void) * [2] https://docs.microsoft.com/en-us/windows/win32/intl/locale-names */ -#if defined(_MSC_VER) - /* * Callback function for EnumSystemLocalesEx() in get_iso_localename(). * @@ -1189,1211 +1059,336 @@ IsoLocaleName(const char *winlocname) return get_iso_localename(winlocname); } -#else /* !defined(_MSC_VER) */ +#endif /* WIN32 && LC_MESSAGES */ -static char * -IsoLocaleName(const char *winlocname) +/* + * Create a new pg_locale_t struct for the given collation oid. + */ +static pg_locale_t +create_pg_locale(Oid collid, MemoryContext context) { - return NULL; /* Not supported on MinGW */ + HeapTuple tp; + Form_pg_collation collform; + pg_locale_t result; + Datum datum; + bool isnull; + + tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for collation %u", collid); + collform = (Form_pg_collation) GETSTRUCT(tp); + + if (collform->collprovider == COLLPROVIDER_BUILTIN) + result = create_pg_locale_builtin(collid, context); + else if (collform->collprovider == COLLPROVIDER_ICU) + result = create_pg_locale_icu(collid, context); + else if (collform->collprovider == COLLPROVIDER_LIBC) + result = create_pg_locale_libc(collid, context); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(collform->collprovider); + + result->is_default = false; + + Assert((result->collate_is_c && result->collate == NULL) || + (!result->collate_is_c && result->collate != NULL)); + + datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion, + &isnull); + if (!isnull) + { + char *actual_versionstr; + char *collversionstr; + + collversionstr = TextDatumGetCString(datum); + + if (collform->collprovider == COLLPROVIDER_LIBC) + datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate); + else + datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); + + actual_versionstr = get_collation_actual_version(collform->collprovider, + TextDatumGetCString(datum)); + if (!actual_versionstr) + { + /* + * This could happen when specifying a version in CREATE COLLATION + * but the provider does not support versioning, or manually + * creating a mess in the catalogs. + */ + ereport(ERROR, + (errmsg("collation \"%s\" has no actual version, but a version was recorded", + NameStr(collform->collname)))); + } + + if (strcmp(actual_versionstr, collversionstr) != 0) + ereport(WARNING, + (errmsg("collation \"%s\" has version mismatch", + NameStr(collform->collname)), + errdetail("The collation in the database was created using version %s, " + "but the operating system provides version %s.", + collversionstr, actual_versionstr), + errhint("Rebuild all objects affected by this collation and run " + "ALTER COLLATION %s REFRESH VERSION, " + "or build PostgreSQL with the right library version.", + quote_qualified_identifier(get_namespace_name(collform->collnamespace), + NameStr(collform->collname))))); + } + + ReleaseSysCache(tp); + + return result; } -#endif /* defined(_MSC_VER) */ +/* + * Initialize default_locale with database locale settings. + */ +void +init_database_collation(void) +{ + HeapTuple tup; + Form_pg_database dbform; + pg_locale_t result; + + Assert(default_locale == NULL); + + /* Fetch our pg_database row normally, via syscache */ + tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + dbform = (Form_pg_database) GETSTRUCT(tup); + + if (dbform->datlocprovider == COLLPROVIDER_BUILTIN) + result = create_pg_locale_builtin(DEFAULT_COLLATION_OID, + TopMemoryContext); + else if (dbform->datlocprovider == COLLPROVIDER_ICU) + result = create_pg_locale_icu(DEFAULT_COLLATION_OID, + TopMemoryContext); + else if (dbform->datlocprovider == COLLPROVIDER_LIBC) + result = create_pg_locale_libc(DEFAULT_COLLATION_OID, + TopMemoryContext); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(dbform->datlocprovider); -#endif /* WIN32 && LC_MESSAGES */ + result->is_default = true; + ReleaseSysCache(tup); + default_locale = result; +} /* - * Cache mechanism for collation information. - * - * We cache two flags: whether the collation's LC_COLLATE or LC_CTYPE is C - * (or POSIX), so we can optimize a few code paths in various places. - * For the built-in C and POSIX collations, we can know that without even - * doing a cache lookup, but we want to support aliases for C/POSIX too. - * For the "default" collation, there are separate static cache variables, - * since consulting the pg_collation catalog doesn't tell us what we need. - * - * Also, if a pg_locale_t has been requested for a collation, we cache that - * for the life of a backend. - * - * Note that some code relies on the flags not reporting false negatives - * (that is, saying it's not C when it is). For example, char2wchar() - * could fail if the locale is C, so str_tolower() shouldn't call it - * in that case. + * Create a pg_locale_t from a collation OID. Results are cached for the + * lifetime of the backend. Thus, do not free the result with freelocale(). * - * Note that we currently lack any way to flush the cache. Since we don't - * support ALTER COLLATION, this is OK. The worst case is that someone - * drops a collation, and a useless cache entry hangs around in existing - * backends. + * For simplicity, we always generate COLLATE + CTYPE even though we + * might only need one of them. Since this is called only once per session, + * it shouldn't cost much. */ - -static collation_cache_entry * -lookup_collation_cache(Oid collation, bool set_flags) +pg_locale_t +pg_newlocale_from_collation(Oid collid) { collation_cache_entry *cache_entry; bool found; - Assert(OidIsValid(collation)); - Assert(collation != DEFAULT_COLLATION_OID); + if (collid == DEFAULT_COLLATION_OID) + return default_locale; - if (collation_cache == NULL) - { - /* First time through, initialize the hash table */ - HASHCTL ctl; + if (!OidIsValid(collid)) + elog(ERROR, "cache lookup failed for collation %u", collid); + + AssertCouldGetRelation(); + + if (last_collation_cache_oid == collid) + return last_collation_cache_locale; - ctl.keysize = sizeof(Oid); - ctl.entrysize = sizeof(collation_cache_entry); - collation_cache = hash_create("Collation cache", 100, &ctl, - HASH_ELEM | HASH_BLOBS); + if (CollationCache == NULL) + { + CollationCacheContext = AllocSetContextCreate(TopMemoryContext, + "collation cache", + ALLOCSET_DEFAULT_SIZES); + CollationCache = collation_cache_create(CollationCacheContext, + 16, NULL); } - cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found); + cache_entry = collation_cache_insert(CollationCache, collid, &found); if (!found) { /* * Make sure cache entry is marked invalid, in case we fail before * setting things. */ - cache_entry->flags_valid = false; cache_entry->locale = 0; } - if (set_flags && !cache_entry->flags_valid) + if (cache_entry->locale == 0) { - /* Attempt to set the flags */ - HeapTuple tp; - Form_pg_collation collform; - - tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation)); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for collation %u", collation); - collform = (Form_pg_collation) GETSTRUCT(tp); + cache_entry->locale = create_pg_locale(collid, CollationCacheContext); + } - if (collform->collprovider == COLLPROVIDER_BUILTIN) - { - Datum datum; - const char *colllocale; + last_collation_cache_oid = collid; + last_collation_cache_locale = cache_entry->locale; - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); - colllocale = TextDatumGetCString(datum); + return cache_entry->locale; +} - cache_entry->collate_is_c = true; - cache_entry->ctype_is_c = (strcmp(colllocale, "C") == 0); - } - else if (collform->collprovider == COLLPROVIDER_LIBC) - { - Datum datum; - const char *collcollate; - const char *collctype; +/* + * Get provider-specific collation version string for the given collation from + * the operating system/library. + */ +char * +get_collation_actual_version(char collprovider, const char *collcollate) +{ + char *collversion = NULL; - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate); - collcollate = TextDatumGetCString(datum); - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype); - collctype = TextDatumGetCString(datum); - - cache_entry->collate_is_c = ((strcmp(collcollate, "C") == 0) || - (strcmp(collcollate, "POSIX") == 0)); - cache_entry->ctype_is_c = ((strcmp(collctype, "C") == 0) || - (strcmp(collctype, "POSIX") == 0)); - } - else - { - cache_entry->collate_is_c = false; - cache_entry->ctype_is_c = false; - } + if (collprovider == COLLPROVIDER_BUILTIN) + collversion = get_collation_actual_version_builtin(collcollate); +#ifdef USE_ICU + else if (collprovider == COLLPROVIDER_ICU) + collversion = get_collation_actual_version_icu(collcollate); +#endif + else if (collprovider == COLLPROVIDER_LIBC) + collversion = get_collation_actual_version_libc(collcollate); - cache_entry->flags_valid = true; + return collversion; +} - ReleaseSysCache(tp); - } +size_t +pg_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (locale->provider == COLLPROVIDER_BUILTIN) + return strlower_builtin(dst, dstsize, src, srclen, locale); +#ifdef USE_ICU + else if (locale->provider == COLLPROVIDER_ICU) + return strlower_icu(dst, dstsize, src, srclen, locale); +#endif + else if (locale->provider == COLLPROVIDER_LIBC) + return strlower_libc(dst, dstsize, src, srclen, locale); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(locale->provider); - return cache_entry; + return 0; /* keep compiler quiet */ } - -/* - * Detect whether collation's LC_COLLATE property is C - */ -bool -lc_collate_is_c(Oid collation) +size_t +pg_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, + pg_locale_t locale) { - /* - * If we're asked about "collation 0", return false, so that the code will - * go into the non-C path and report that the collation is bogus. - */ - if (!OidIsValid(collation)) - return false; - - /* - * If we're asked about the default collation, we have to inquire of the C - * library. Cache the result so we only have to compute it once. - */ - if (collation == DEFAULT_COLLATION_OID) - { - static int result = -1; - const char *localeptr; + if (locale->provider == COLLPROVIDER_BUILTIN) + return strtitle_builtin(dst, dstsize, src, srclen, locale); +#ifdef USE_ICU + else if (locale->provider == COLLPROVIDER_ICU) + return strtitle_icu(dst, dstsize, src, srclen, locale); +#endif + else if (locale->provider == COLLPROVIDER_LIBC) + return strtitle_libc(dst, dstsize, src, srclen, locale); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(locale->provider); - if (result >= 0) - return (bool) result; + return 0; /* keep compiler quiet */ +} - if (default_locale.provider == COLLPROVIDER_BUILTIN) - { - result = true; - return (bool) result; - } - else if (default_locale.provider == COLLPROVIDER_ICU) - { - result = false; - return (bool) result; - } - else if (default_locale.provider == COLLPROVIDER_LIBC) - { - localeptr = setlocale(LC_CTYPE, NULL); - if (!localeptr) - elog(ERROR, "invalid LC_CTYPE setting"); - } - else - elog(ERROR, "unexpected collation provider '%c'", - default_locale.provider); +size_t +pg_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (locale->provider == COLLPROVIDER_BUILTIN) + return strupper_builtin(dst, dstsize, src, srclen, locale); +#ifdef USE_ICU + else if (locale->provider == COLLPROVIDER_ICU) + return strupper_icu(dst, dstsize, src, srclen, locale); +#endif + else if (locale->provider == COLLPROVIDER_LIBC) + return strupper_libc(dst, dstsize, src, srclen, locale); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(locale->provider); - if (strcmp(localeptr, "C") == 0) - result = true; - else if (strcmp(localeptr, "POSIX") == 0) - result = true; - else - result = false; - return (bool) result; - } + return 0; /* keep compiler quiet */ +} - /* - * If we're asked about the built-in C/POSIX collations, we know that. - */ - if (collation == C_COLLATION_OID || - collation == POSIX_COLLATION_OID) - return true; +size_t +pg_strfold(char *dst, size_t dstsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (locale->provider == COLLPROVIDER_BUILTIN) + return strfold_builtin(dst, dstsize, src, srclen, locale); +#ifdef USE_ICU + else if (locale->provider == COLLPROVIDER_ICU) + return strfold_icu(dst, dstsize, src, srclen, locale); +#endif + /* for libc, just use strlower */ + else if (locale->provider == COLLPROVIDER_LIBC) + return strlower_libc(dst, dstsize, src, srclen, locale); + else + /* shouldn't happen */ + PGLOCALE_SUPPORT_ERROR(locale->provider); - /* - * Otherwise, we have to consult pg_collation, but we cache that. - */ - return (lookup_collation_cache(collation, true))->collate_is_c; + return 0; /* keep compiler quiet */ } /* - * Detect whether collation's LC_CTYPE property is C - */ -bool -lc_ctype_is_c(Oid collation) -{ - /* - * If we're asked about "collation 0", return false, so that the code will - * go into the non-C path and report that the collation is bogus. - */ - if (!OidIsValid(collation)) - return false; - - /* - * If we're asked about the default collation, we have to inquire of the C - * library. Cache the result so we only have to compute it once. - */ - if (collation == DEFAULT_COLLATION_OID) - { - static int result = -1; - const char *localeptr; - - if (result >= 0) - return (bool) result; - - if (default_locale.provider == COLLPROVIDER_BUILTIN) - { - localeptr = default_locale.info.builtin.locale; - } - else if (default_locale.provider == COLLPROVIDER_ICU) - { - result = false; - return (bool) result; - } - else if (default_locale.provider == COLLPROVIDER_LIBC) - { - localeptr = setlocale(LC_CTYPE, NULL); - if (!localeptr) - elog(ERROR, "invalid LC_CTYPE setting"); - } - else - elog(ERROR, "unexpected collation provider '%c'", - default_locale.provider); - - if (strcmp(localeptr, "C") == 0) - result = true; - else if (strcmp(localeptr, "POSIX") == 0) - result = true; - else - result = false; - return (bool) result; - } - - /* - * If we're asked about the built-in C/POSIX collations, we know that. - */ - if (collation == C_COLLATION_OID || - collation == POSIX_COLLATION_OID) - return true; - - /* - * Otherwise, we have to consult pg_collation, but we cache that. - */ - return (lookup_collation_cache(collation, true))->ctype_is_c; -} - -struct pg_locale_struct default_locale; - -void -make_icu_collator(const char *iculocstr, - const char *icurules, - struct pg_locale_struct *resultp) -{ -#ifdef USE_ICU - UCollator *collator; - - collator = pg_ucol_open(iculocstr); - - /* - * If rules are specified, we extract the rules of the standard collation, - * add our own rules, and make a new collator with the combined rules. - */ - if (icurules) - { - const UChar *default_rules; - UChar *agg_rules; - UChar *my_rules; - UErrorCode status; - int32_t length; - - default_rules = ucol_getRules(collator, &length); - icu_to_uchar(&my_rules, icurules, strlen(icurules)); - - agg_rules = palloc_array(UChar, u_strlen(default_rules) + u_strlen(my_rules) + 1); - u_strcpy(agg_rules, default_rules); - u_strcat(agg_rules, my_rules); - - ucol_close(collator); - - status = U_ZERO_ERROR; - collator = ucol_openRules(agg_rules, u_strlen(agg_rules), - UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL, &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s", - iculocstr, icurules, u_errorName(status)))); - } - - /* We will leak this string if the caller errors later :-( */ - resultp->info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr); - resultp->info.icu.ucol = collator; -#else /* not USE_ICU */ - /* could get here if a collation was created by a build with ICU */ - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("ICU is not supported in this build"))); -#endif /* not USE_ICU */ -} - - -/* simple subroutine for reporting errors from newlocale() */ -static void -report_newlocale_failure(const char *localename) -{ - int save_errno; - - /* - * Windows doesn't provide any useful error indication from - * _create_locale(), and BSD-derived platforms don't seem to feel they - * need to set errno either (even though POSIX is pretty clear that - * newlocale should do so). So, if errno hasn't been set, assume ENOENT - * is what to report. - */ - if (errno == 0) - errno = ENOENT; - - /* - * ENOENT means "no such locale", not "no such file", so clarify that - * errno with an errdetail message. - */ - save_errno = errno; /* auxiliary funcs might change errno */ - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not create locale \"%s\": %m", - localename), - (save_errno == ENOENT ? - errdetail("The operating system could not find any locale data for the locale name \"%s\".", - localename) : 0))); -} - -bool -pg_locale_deterministic(pg_locale_t locale) -{ - /* default locale must always be deterministic */ - if (locale == NULL) - return true; - else - return locale->deterministic; -} - -/* - * Create a locale_t from a collation OID. Results are cached for the - * lifetime of the backend. Thus, do not free the result with freelocale(). - * - * As a special optimization, the default/database collation returns 0. - * - * For simplicity, we always generate COLLATE + CTYPE even though we - * might only need one of them. Since this is called only once per session, - * it shouldn't cost much. - */ -pg_locale_t -pg_newlocale_from_collation(Oid collid) -{ - collation_cache_entry *cache_entry; - - /* Callers must pass a valid OID */ - Assert(OidIsValid(collid)); - - if (collid == DEFAULT_COLLATION_OID) - { - if (default_locale.provider == COLLPROVIDER_LIBC) - return (pg_locale_t) 0; - else - return &default_locale; - } - - cache_entry = lookup_collation_cache(collid, false); - - if (cache_entry->locale == 0) - { - /* We haven't computed this yet in this session, so do it */ - HeapTuple tp; - Form_pg_collation collform; - struct pg_locale_struct result; - pg_locale_t resultp; - Datum datum; - bool isnull; - - tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); - if (!HeapTupleIsValid(tp)) - elog(ERROR, "cache lookup failed for collation %u", collid); - collform = (Form_pg_collation) GETSTRUCT(tp); - - /* We'll fill in the result struct locally before allocating memory */ - memset(&result, 0, sizeof(result)); - result.provider = collform->collprovider; - result.deterministic = collform->collisdeterministic; - - if (collform->collprovider == COLLPROVIDER_BUILTIN) - { - const char *locstr; - - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); - locstr = TextDatumGetCString(datum); - - builtin_validate_locale(GetDatabaseEncoding(), locstr); - - result.info.builtin.locale = MemoryContextStrdup(TopMemoryContext, - locstr); - } - else if (collform->collprovider == COLLPROVIDER_LIBC) - { - const char *collcollate; - const char *collctype pg_attribute_unused(); - locale_t loc; - - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate); - collcollate = TextDatumGetCString(datum); - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype); - collctype = TextDatumGetCString(datum); - - if (strcmp(collcollate, collctype) == 0) - { - /* Normal case where they're the same */ - errno = 0; -#ifndef WIN32 - loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collcollate, - NULL); -#else - loc = _create_locale(LC_ALL, collcollate); -#endif - if (!loc) - report_newlocale_failure(collcollate); - } - else - { -#ifndef WIN32 - /* We need two newlocale() steps */ - locale_t loc1; - - errno = 0; - loc1 = newlocale(LC_COLLATE_MASK, collcollate, NULL); - if (!loc1) - report_newlocale_failure(collcollate); - errno = 0; - loc = newlocale(LC_CTYPE_MASK, collctype, loc1); - if (!loc) - report_newlocale_failure(collctype); -#else - - /* - * XXX The _create_locale() API doesn't appear to support - * this. Could perhaps be worked around by changing - * pg_locale_t to contain two separate fields. - */ - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("collations with different collate and ctype values are not supported on this platform"))); -#endif - } - - result.info.lt = loc; - } - else if (collform->collprovider == COLLPROVIDER_ICU) - { - const char *iculocstr; - const char *icurules; - - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); - iculocstr = TextDatumGetCString(datum); - - datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull); - if (!isnull) - icurules = TextDatumGetCString(datum); - else - icurules = NULL; - - make_icu_collator(iculocstr, icurules, &result); - } - - datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion, - &isnull); - if (!isnull) - { - char *actual_versionstr; - char *collversionstr; - - collversionstr = TextDatumGetCString(datum); - - if (collform->collprovider == COLLPROVIDER_LIBC) - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate); - else - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); - - actual_versionstr = get_collation_actual_version(collform->collprovider, - TextDatumGetCString(datum)); - if (!actual_versionstr) - { - /* - * This could happen when specifying a version in CREATE - * COLLATION but the provider does not support versioning, or - * manually creating a mess in the catalogs. - */ - ereport(ERROR, - (errmsg("collation \"%s\" has no actual version, but a version was recorded", - NameStr(collform->collname)))); - } - - if (strcmp(actual_versionstr, collversionstr) != 0) - ereport(WARNING, - (errmsg("collation \"%s\" has version mismatch", - NameStr(collform->collname)), - errdetail("The collation in the database was created using version %s, " - "but the operating system provides version %s.", - collversionstr, actual_versionstr), - errhint("Rebuild all objects affected by this collation and run " - "ALTER COLLATION %s REFRESH VERSION, " - "or build PostgreSQL with the right library version.", - quote_qualified_identifier(get_namespace_name(collform->collnamespace), - NameStr(collform->collname))))); - } - - ReleaseSysCache(tp); - - /* We'll keep the pg_locale_t structures in TopMemoryContext */ - resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp)); - *resultp = result; - - cache_entry->locale = resultp; - } - - return cache_entry->locale; -} - -/* - * Get provider-specific collation version string for the given collation from - * the operating system/library. - */ -char * -get_collation_actual_version(char collprovider, const char *collcollate) -{ - char *collversion = NULL; - - /* - * The only two supported locales (C and C.UTF-8) are both based on memcmp - * and are not expected to change, but track the version anyway. - * - * Note that the character semantics may change for some locales, but the - * collation version only tracks changes to sort order. - */ - if (collprovider == COLLPROVIDER_BUILTIN) - { - if (strcmp(collcollate, "C") == 0) - return "1"; - else if (strcmp(collcollate, "C.UTF-8") == 0) - return "1"; - else - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("invalid locale name \"%s\" for builtin provider", - collcollate))); - } - -#ifdef USE_ICU - if (collprovider == COLLPROVIDER_ICU) - { - UCollator *collator; - UVersionInfo versioninfo; - char buf[U_MAX_VERSION_STRING_LENGTH]; - - collator = pg_ucol_open(collcollate); - - ucol_getVersion(collator, versioninfo); - ucol_close(collator); - - u_versionToString(versioninfo, buf); - collversion = pstrdup(buf); - } - else -#endif - if (collprovider == COLLPROVIDER_LIBC && - pg_strcasecmp("C", collcollate) != 0 && - pg_strncasecmp("C.", collcollate, 2) != 0 && - pg_strcasecmp("POSIX", collcollate) != 0) - { -#if defined(__GLIBC__) - /* Use the glibc version because we don't have anything better. */ - collversion = pstrdup(gnu_get_libc_version()); -#elif defined(LC_VERSION_MASK) - locale_t loc; - - /* Look up FreeBSD collation version. */ - loc = newlocale(LC_COLLATE, collcollate, NULL); - if (loc) - { - collversion = - pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc)); - freelocale(loc); - } - else - ereport(ERROR, - (errmsg("could not load locale \"%s\"", collcollate))); -#elif defined(WIN32) - /* - * If we are targeting Windows Vista and above, we can ask for a name - * given a collation name (earlier versions required a location code - * that we don't have). - */ - NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)}; - WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH]; - - MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate, - LOCALE_NAME_MAX_LENGTH); - if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version)) - { - /* - * GetNLSVersionEx() wants a language tag such as "en-US", not a - * locale name like "English_United States.1252". Until those - * values can be prevented from entering the system, or 100% - * reliably converted to the more useful tag format, tolerate the - * resulting error and report that we have no version data. - */ - if (GetLastError() == ERROR_INVALID_PARAMETER) - return NULL; - - ereport(ERROR, - (errmsg("could not get collation version for locale \"%s\": error code %lu", - collcollate, - GetLastError()))); - } - collversion = psprintf("%lu.%lu,%lu.%lu", - (version.dwNLSVersion >> 8) & 0xFFFF, - version.dwNLSVersion & 0xFF, - (version.dwDefinedVersion >> 8) & 0xFFFF, - version.dwDefinedVersion & 0xFF); -#endif - } - - return collversion; -} - -/* - * pg_strncoll_libc_win32_utf8 - * - * Win32 does not have UTF-8. Convert UTF8 arguments to wide characters and - * invoke wcscoll() or wcscoll_l(). - */ -#ifdef WIN32 -static int -pg_strncoll_libc_win32_utf8(const char *arg1, size_t len1, const char *arg2, - size_t len2, pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - char *a1p, - *a2p; - int a1len = len1 * 2 + 2; - int a2len = len2 * 2 + 2; - int r; - int result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - Assert(GetDatabaseEncoding() == PG_UTF8); -#ifndef WIN32 - Assert(false); -#endif - - if (a1len + a2len > TEXTBUFLEN) - buf = palloc(a1len + a2len); - - a1p = buf; - a2p = buf + a1len; - - /* API does not work for zero-length input */ - if (len1 == 0) - r = 0; - else - { - r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1, - (LPWSTR) a1p, a1len / 2); - if (!r) - ereport(ERROR, - (errmsg("could not convert string to UTF-16: error code %lu", - GetLastError()))); - } - ((LPWSTR) a1p)[r] = 0; - - if (len2 == 0) - r = 0; - else - { - r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2, - (LPWSTR) a2p, a2len / 2); - if (!r) - ereport(ERROR, - (errmsg("could not convert string to UTF-16: error code %lu", - GetLastError()))); - } - ((LPWSTR) a2p)[r] = 0; - - errno = 0; - if (locale) - result = wcscoll_l((LPWSTR) a1p, (LPWSTR) a2p, locale->info.lt); - else - result = wcscoll((LPWSTR) a1p, (LPWSTR) a2p); - if (result == 2147483647) /* _NLSCMPERROR; missing from mingw headers */ - ereport(ERROR, - (errmsg("could not compare Unicode strings: %m"))); - - if (buf != sbuf) - pfree(buf); - - return result; -} -#endif /* WIN32 */ - -/* - * pg_strcoll_libc - * - * Call strcoll(), strcoll_l(), wcscoll(), or wcscoll_l() as appropriate for - * the given locale, platform, and database encoding. If the locale is NULL, - * use the database collation. - * - * Arguments must be encoded in the database encoding and nul-terminated. - */ -static int -pg_strcoll_libc(const char *arg1, const char *arg2, pg_locale_t locale) -{ - int result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); -#ifdef WIN32 - if (GetDatabaseEncoding() == PG_UTF8) - { - size_t len1 = strlen(arg1); - size_t len2 = strlen(arg2); - - result = pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale); - } - else -#endif /* WIN32 */ - if (locale) - result = strcoll_l(arg1, arg2, locale->info.lt); - else - result = strcoll(arg1, arg2); - - return result; -} - -/* - * pg_strncoll_libc - * - * Nul-terminate the arguments and call pg_strcoll_libc(). - */ -static int -pg_strncoll_libc(const char *arg1, size_t len1, const char *arg2, size_t len2, - pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - size_t bufsize1 = len1 + 1; - size_t bufsize2 = len2 + 1; - char *arg1n; - char *arg2n; - int result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - -#ifdef WIN32 - /* check for this case before doing the work for nul-termination */ - if (GetDatabaseEncoding() == PG_UTF8) - return pg_strncoll_libc_win32_utf8(arg1, len1, arg2, len2, locale); -#endif /* WIN32 */ - - if (bufsize1 + bufsize2 > TEXTBUFLEN) - buf = palloc(bufsize1 + bufsize2); - - arg1n = buf; - arg2n = buf + bufsize1; - - /* nul-terminate arguments */ - memcpy(arg1n, arg1, len1); - arg1n[len1] = '\0'; - memcpy(arg2n, arg2, len2); - arg2n[len2] = '\0'; - - result = pg_strcoll_libc(arg1n, arg2n, locale); - - if (buf != sbuf) - pfree(buf); - - return result; -} - -#ifdef USE_ICU - -/* - * pg_strncoll_icu_no_utf8 - * - * Convert the arguments from the database encoding to UChar strings, then - * call ucol_strcoll(). An argument length of -1 means that the string is - * NUL-terminated. - * - * When the database encoding is UTF-8, and ICU supports ucol_strcollUTF8(), - * caller should call that instead. - */ -static int -pg_strncoll_icu_no_utf8(const char *arg1, int32_t len1, - const char *arg2, int32_t len2, pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - int32_t ulen1; - int32_t ulen2; - size_t bufsize1; - size_t bufsize2; - UChar *uchar1, - *uchar2; - int result; - - Assert(locale->provider == COLLPROVIDER_ICU); -#ifdef HAVE_UCOL_STRCOLLUTF8 - Assert(GetDatabaseEncoding() != PG_UTF8); -#endif - - init_icu_converter(); - - ulen1 = uchar_length(icu_converter, arg1, len1); - ulen2 = uchar_length(icu_converter, arg2, len2); - - bufsize1 = (ulen1 + 1) * sizeof(UChar); - bufsize2 = (ulen2 + 1) * sizeof(UChar); - - if (bufsize1 + bufsize2 > TEXTBUFLEN) - buf = palloc(bufsize1 + bufsize2); - - uchar1 = (UChar *) buf; - uchar2 = (UChar *) (buf + bufsize1); - - ulen1 = uchar_convert(icu_converter, uchar1, ulen1 + 1, arg1, len1); - ulen2 = uchar_convert(icu_converter, uchar2, ulen2 + 1, arg2, len2); - - result = ucol_strcoll(locale->info.icu.ucol, - uchar1, ulen1, - uchar2, ulen2); - - if (buf != sbuf) - pfree(buf); - - return result; -} - -/* - * pg_strncoll_icu - * - * Call ucol_strcollUTF8() or ucol_strcoll() as appropriate for the given - * database encoding. An argument length of -1 means the string is - * NUL-terminated. - * - * Arguments must be encoded in the database encoding. - */ -static int -pg_strncoll_icu(const char *arg1, int32_t len1, const char *arg2, int32_t len2, - pg_locale_t locale) -{ - int result; - - Assert(locale->provider == COLLPROVIDER_ICU); - -#ifdef HAVE_UCOL_STRCOLLUTF8 - if (GetDatabaseEncoding() == PG_UTF8) - { - UErrorCode status; - - status = U_ZERO_ERROR; - result = ucol_strcollUTF8(locale->info.icu.ucol, - arg1, len1, - arg2, len2, - &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("collation failed: %s", u_errorName(status)))); - } - else -#endif - { - result = pg_strncoll_icu_no_utf8(arg1, len1, arg2, len2, locale); - } - - return result; -} - -#endif /* USE_ICU */ - -/* - * pg_strcoll - * - * Call ucol_strcollUTF8(), ucol_strcoll(), strcoll(), strcoll_l(), wcscoll(), - * or wcscoll_l() as appropriate for the given locale, platform, and database - * encoding. If the locale is not specified, use the database collation. - * - * Arguments must be encoded in the database encoding and nul-terminated. - * - * The caller is responsible for breaking ties if the collation is - * deterministic; this maintains consistency with pg_strxfrm(), which cannot - * easily account for deterministic collations. + * pg_strcoll + * + * Like pg_strncoll for NUL-terminated input strings. */ int pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale) { - int result; - - if (!locale || locale->provider == COLLPROVIDER_LIBC) - result = pg_strcoll_libc(arg1, arg2, locale); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strncoll_icu(arg1, -1, arg2, -1, locale); -#endif - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + return locale->collate->strncoll(arg1, -1, arg2, -1, locale); } /* * pg_strncoll * - * Call ucol_strcollUTF8(), ucol_strcoll(), strcoll(), strcoll_l(), wcscoll(), - * or wcscoll_l() as appropriate for the given locale, platform, and database - * encoding. If the locale is not specified, use the database collation. + * Call ucol_strcollUTF8(), ucol_strcoll(), strcoll_l() or wcscoll_l() as + * appropriate for the given locale, platform, and database encoding. If the + * locale is not specified, use the database collation. * - * Arguments must be encoded in the database encoding. - * - * This function may need to nul-terminate the arguments for libc functions; - * so if the caller already has nul-terminated strings, it should call - * pg_strcoll() instead. + * The input strings must be encoded in the database encoding. If an input + * string is NUL-terminated, its length may be specified as -1. * * The caller is responsible for breaking ties if the collation is * deterministic; this maintains consistency with pg_strnxfrm(), which cannot * easily account for deterministic collations. */ int -pg_strncoll(const char *arg1, size_t len1, const char *arg2, size_t len2, +pg_strncoll(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale) { - int result; - - if (!locale || locale->provider == COLLPROVIDER_LIBC) - result = pg_strncoll_libc(arg1, len1, arg2, len2, locale); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strncoll_icu(arg1, len1, arg2, len2, locale); -#endif - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + return locale->collate->strncoll(arg1, len1, arg2, len2, locale); } - -static size_t -pg_strxfrm_libc(char *dest, const char *src, size_t destsize, - pg_locale_t locale) -{ - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - -#ifdef TRUST_STRXFRM - if (locale) - return strxfrm_l(dest, src, destsize, locale->info.lt); - else - return strxfrm(dest, src, destsize); -#else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - return 0; /* keep compiler quiet */ -#endif -} - -static size_t -pg_strnxfrm_libc(char *dest, const char *src, size_t srclen, size_t destsize, - pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - size_t bufsize = srclen + 1; - size_t result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - - if (bufsize > TEXTBUFLEN) - buf = palloc(bufsize); - - /* nul-terminate arguments */ - memcpy(buf, src, srclen); - buf[srclen] = '\0'; - - result = pg_strxfrm_libc(dest, buf, destsize, locale); - - if (buf != sbuf) - pfree(buf); - - /* if dest is defined, it should be nul-terminated */ - Assert(result >= destsize || dest[result] == '\0'); - - return result; -} - -#ifdef USE_ICU - -/* 'srclen' of -1 means the strings are NUL-terminated */ -static size_t -pg_strnxfrm_icu(char *dest, const char *src, int32_t srclen, int32_t destsize, - pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - UChar *uchar; - int32_t ulen; - size_t uchar_bsize; - Size result_bsize; - - Assert(locale->provider == COLLPROVIDER_ICU); - - init_icu_converter(); - - ulen = uchar_length(icu_converter, src, srclen); - - uchar_bsize = (ulen + 1) * sizeof(UChar); - - if (uchar_bsize > TEXTBUFLEN) - buf = palloc(uchar_bsize); - - uchar = (UChar *) buf; - - ulen = uchar_convert(icu_converter, uchar, ulen + 1, src, srclen); - - result_bsize = ucol_getSortKey(locale->info.icu.ucol, - uchar, ulen, - (uint8_t *) dest, destsize); - - /* - * ucol_getSortKey() counts the nul-terminator in the result length, but - * this function should not. - */ - Assert(result_bsize > 0); - result_bsize--; - - if (buf != sbuf) - pfree(buf); - - /* if dest is defined, it should be nul-terminated */ - Assert(result_bsize >= destsize || dest[result_bsize] == '\0'); - - return result_bsize; -} - -/* 'srclen' of -1 means the strings are NUL-terminated */ -static size_t -pg_strnxfrm_prefix_icu_no_utf8(char *dest, const char *src, int32_t srclen, - int32_t destsize, pg_locale_t locale) -{ - char sbuf[TEXTBUFLEN]; - char *buf = sbuf; - UCharIterator iter; - uint32_t state[2]; - UErrorCode status; - int32_t ulen = -1; - UChar *uchar = NULL; - size_t uchar_bsize; - Size result_bsize; - - Assert(locale->provider == COLLPROVIDER_ICU); - Assert(GetDatabaseEncoding() != PG_UTF8); - - init_icu_converter(); - - ulen = uchar_length(icu_converter, src, srclen); - - uchar_bsize = (ulen + 1) * sizeof(UChar); - - if (uchar_bsize > TEXTBUFLEN) - buf = palloc(uchar_bsize); - - uchar = (UChar *) buf; - - ulen = uchar_convert(icu_converter, uchar, ulen + 1, src, srclen); - - uiter_setString(&iter, uchar, ulen); - state[0] = state[1] = 0; /* won't need that again */ - status = U_ZERO_ERROR; - result_bsize = ucol_nextSortKeyPart(locale->info.icu.ucol, - &iter, - state, - (uint8_t *) dest, - destsize, - &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("sort key generation failed: %s", - u_errorName(status)))); - - return result_bsize; -} - -/* 'srclen' of -1 means the strings are NUL-terminated */ -static size_t -pg_strnxfrm_prefix_icu(char *dest, const char *src, int32_t srclen, - int32_t destsize, pg_locale_t locale) -{ - size_t result; - - Assert(locale->provider == COLLPROVIDER_ICU); - - if (GetDatabaseEncoding() == PG_UTF8) - { - UCharIterator iter; - uint32_t state[2]; - UErrorCode status; - - uiter_setUTF8(&iter, src, srclen); - state[0] = state[1] = 0; /* won't need that again */ - status = U_ZERO_ERROR; - result = ucol_nextSortKeyPart(locale->info.icu.ucol, - &iter, - state, - (uint8_t *) dest, - destsize, - &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("sort key generation failed: %s", - u_errorName(status)))); - } - else - result = pg_strnxfrm_prefix_icu_no_utf8(dest, src, srclen, destsize, - locale); - - return result; -} - -#endif - /* * Return true if the collation provider supports pg_strxfrm() and * pg_strnxfrm(); otherwise false. * - * Unfortunately, it seems that strxfrm() for non-C collations is broken on - * many common platforms; testing of multiple versions of glibc reveals that, - * for many locales, strcoll() and strxfrm() do not return consistent - * results. While no other libc other than Cygwin has so far been shown to - * have a problem, we take the conservative course of action for right now and - * disable this categorically. (Users who are certain this isn't a problem on - * their system can define TRUST_STRXFRM.) * * No similar problem is known for the ICU provider. */ bool pg_strxfrm_enabled(pg_locale_t locale) { - if (!locale || locale->provider == COLLPROVIDER_LIBC) -#ifdef TRUST_STRXFRM - return true; -#else - return false; -#endif - else if (locale->provider == COLLPROVIDER_ICU) - return true; - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return false; /* keep compiler quiet */ + /* + * locale->collate->strnxfrm is still a required method, even if it may + * have the wrong behavior, because the planner uses it for estimates in + * some cases. + */ + return locale->collate->strxfrm_is_safe; } /* * pg_strxfrm * - * Transforms 'src' to a nul-terminated string stored in 'dest' such that - * ordinary strcmp() on transformed strings is equivalent to pg_strcoll() on - * untransformed strings. - * - * The provided 'src' must be nul-terminated. If 'destsize' is zero, 'dest' - * may be NULL. - * - * Returns the number of bytes needed to store the transformed string, - * excluding the terminating nul byte. If the value returned is 'destsize' or - * greater, the resulting contents of 'dest' are undefined. + * Like pg_strnxfrm for a NUL-terminated input string. */ size_t pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) { - size_t result = 0; /* keep compiler quiet */ - - if (!locale || locale->provider == COLLPROVIDER_LIBC) - result = pg_strxfrm_libc(dest, src, destsize, locale); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strnxfrm_icu(dest, src, -1, destsize, locale); -#endif - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + return locale->collate->strnxfrm(dest, destsize, src, -1, locale); } /* @@ -2401,36 +1396,25 @@ pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale) * * Transforms 'src' to a nul-terminated string stored in 'dest' such that * ordinary strcmp() on transformed strings is equivalent to pg_strcoll() on - * untransformed strings. - * - * 'src' does not need to be nul-terminated. If 'destsize' is zero, 'dest' may - * be NULL. - * - * Returns the number of bytes needed to store the transformed string, - * excluding the terminating nul byte. If the value returned is 'destsize' or - * greater, the resulting contents of 'dest' are undefined. - * - * This function may need to nul-terminate the argument for libc functions; - * so if the caller already has a nul-terminated string, it should call - * pg_strxfrm() instead. - */ -size_t -pg_strnxfrm(char *dest, size_t destsize, const char *src, size_t srclen, - pg_locale_t locale) -{ - size_t result = 0; /* keep compiler quiet */ - - if (!locale || locale->provider == COLLPROVIDER_LIBC) - result = pg_strnxfrm_libc(dest, src, srclen, destsize, locale); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strnxfrm_icu(dest, src, srclen, destsize, locale); -#endif - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + * untransformed strings. + * + * The input string must be encoded in the database encoding. If the input + * string is NUL-terminated, its length may be specified as -1. If 'destsize' + * is zero, 'dest' may be NULL. + * + * Not all providers support pg_strnxfrm() safely. The caller should check + * pg_strxfrm_enabled() first, otherwise this function may return wrong + * results or an error. + * + * Returns the number of bytes needed (or more) to store the transformed + * string, excluding the terminating nul byte. If the value returned is + * 'destsize' or greater, the resulting contents of 'dest' are undefined. + */ +size_t +pg_strnxfrm(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + return locale->collate->strnxfrm(dest, destsize, src, srclen, locale); } /* @@ -2440,81 +1424,44 @@ pg_strnxfrm(char *dest, size_t destsize, const char *src, size_t srclen, bool pg_strxfrm_prefix_enabled(pg_locale_t locale) { - if (!locale || locale->provider == COLLPROVIDER_LIBC) - return false; - else if (locale->provider == COLLPROVIDER_ICU) - return true; - else - /* shouldn't happen */ - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return false; /* keep compiler quiet */ + return (locale->collate->strnxfrm_prefix != NULL); } /* * pg_strxfrm_prefix * - * Transforms 'src' to a byte sequence stored in 'dest' such that ordinary - * memcmp() on the byte sequence is equivalent to pg_strcoll() on - * untransformed strings. The result is not nul-terminated. - * - * The provided 'src' must be nul-terminated. - * - * If destsize is not large enough to hold the resulting byte sequence, stores - * only the first destsize bytes in 'dest'. Returns the number of bytes - * actually copied to 'dest'. + * Like pg_strnxfrm_prefix for a NUL-terminated input string. */ size_t pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, pg_locale_t locale) { - size_t result = 0; /* keep compiler quiet */ - - if (!locale) - PGLOCALE_SUPPORT_ERROR(COLLPROVIDER_LIBC); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale); -#endif - else - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + return locale->collate->strnxfrm_prefix(dest, destsize, src, -1, locale); } /* * pg_strnxfrm_prefix * * Transforms 'src' to a byte sequence stored in 'dest' such that ordinary - * memcmp() on the byte sequence is equivalent to pg_strcoll() on + * memcmp() on the byte sequence is equivalent to pg_strncoll() on * untransformed strings. The result is not nul-terminated. * - * The provided 'src' must be nul-terminated. + * The input string must be encoded in the database encoding. If the input + * string is NUL-terminated, its length may be specified as -1. + * + * Not all providers support pg_strnxfrm_prefix() safely. The caller should + * check pg_strxfrm_prefix_enabled() first, otherwise this function may return + * wrong results or an error. * * If destsize is not large enough to hold the resulting byte sequence, stores * only the first destsize bytes in 'dest'. Returns the number of bytes * actually copied to 'dest'. - * - * This function may need to nul-terminate the argument for libc functions; - * so if the caller already has a nul-terminated string, it should call - * pg_strxfrm_prefix() instead. */ size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, - size_t srclen, pg_locale_t locale) + ssize_t srclen, pg_locale_t locale) { - size_t result = 0; /* keep compiler quiet */ - - if (!locale) - PGLOCALE_SUPPORT_ERROR(COLLPROVIDER_LIBC); -#ifdef USE_ICU - else if (locale->provider == COLLPROVIDER_ICU) - result = pg_strnxfrm_prefix_icu(dest, src, -1, destsize, locale); -#endif - else - PGLOCALE_SUPPORT_ERROR(locale->provider); - - return result; + return locale->collate->strnxfrm_prefix(dest, destsize, src, srclen, locale); } /* @@ -2526,9 +1473,12 @@ builtin_locale_encoding(const char *locale) { if (strcmp(locale, "C") == 0) return -1; - if (strcmp(locale, "C.UTF-8") == 0) + else if (strcmp(locale, "C.UTF-8") == 0) + return PG_UTF8; + else if (strcmp(locale, "PG_UNICODE_FAST") == 0) return PG_UTF8; + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("invalid locale name \"%s\" for builtin provider", @@ -2552,6 +1502,8 @@ builtin_validate_locale(int encoding, const char *locale) canonical_name = "C"; else if (strcmp(locale, "C.UTF-8") == 0 || strcmp(locale, "C.UTF8") == 0) canonical_name = "C.UTF-8"; + else if (strcmp(locale, "PG_UNICODE_FAST") == 0) + canonical_name = "PG_UNICODE_FAST"; if (!canonical_name) ereport(ERROR, @@ -2570,348 +1522,6 @@ builtin_validate_locale(int encoding, const char *locale) } -#ifdef USE_ICU - -/* - * Wrapper around ucol_open() to handle API differences for older ICU - * versions. - */ -static UCollator * -pg_ucol_open(const char *loc_str) -{ - UCollator *collator; - UErrorCode status; - const char *orig_str = loc_str; - char *fixed_str = NULL; - - /* - * Must never open default collator, because it depends on the environment - * and may change at any time. Should not happen, but check here to catch - * bugs that might be hard to catch otherwise. - * - * NB: the default collator is not the same as the collator for the root - * locale. The root locale may be specified as the empty string, "und", or - * "root". The default collator is opened by passing NULL to ucol_open(). - */ - if (loc_str == NULL) - elog(ERROR, "opening default collator is not supported"); - - /* - * In ICU versions 54 and earlier, "und" is not a recognized spelling of - * the root locale. If the first component of the locale is "und", replace - * with "root" before opening. - */ - if (U_ICU_VERSION_MAJOR_NUM < 55) - { - char lang[ULOC_LANG_CAPACITY]; - - status = U_ZERO_ERROR; - uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status); - if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not get language from locale \"%s\": %s", - loc_str, u_errorName(status)))); - } - - if (strcmp(lang, "und") == 0) - { - const char *remainder = loc_str + strlen("und"); - - fixed_str = palloc(strlen("root") + strlen(remainder) + 1); - strcpy(fixed_str, "root"); - strcat(fixed_str, remainder); - - loc_str = fixed_str; - } - } - - status = U_ZERO_ERROR; - collator = ucol_open(loc_str, &status); - if (U_FAILURE(status)) - ereport(ERROR, - /* use original string for error report */ - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not open collator for locale \"%s\": %s", - orig_str, u_errorName(status)))); - - if (U_ICU_VERSION_MAJOR_NUM < 54) - { - status = U_ZERO_ERROR; - icu_set_collation_attributes(collator, loc_str, &status); - - /* - * Pretend the error came from ucol_open(), for consistent error - * message across ICU versions. - */ - if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) - { - ucol_close(collator); - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not open collator for locale \"%s\": %s", - orig_str, u_errorName(status)))); - } - } - - if (fixed_str != NULL) - pfree(fixed_str); - - return collator; -} - -static void -init_icu_converter(void) -{ - const char *icu_encoding_name; - UErrorCode status; - UConverter *conv; - - if (icu_converter) - return; /* already done */ - - icu_encoding_name = get_encoding_name_for_icu(GetDatabaseEncoding()); - if (!icu_encoding_name) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("encoding \"%s\" not supported by ICU", - pg_encoding_to_char(GetDatabaseEncoding())))); - - status = U_ZERO_ERROR; - conv = ucnv_open(icu_encoding_name, &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("could not open ICU converter for encoding \"%s\": %s", - icu_encoding_name, u_errorName(status)))); - - icu_converter = conv; -} - -/* - * Find length, in UChars, of given string if converted to UChar string. - */ -static size_t -uchar_length(UConverter *converter, const char *str, int32_t len) -{ - UErrorCode status = U_ZERO_ERROR; - int32_t ulen; - - ulen = ucnv_toUChars(converter, NULL, 0, str, len, &status); - if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) - ereport(ERROR, - (errmsg("%s failed: %s", "ucnv_toUChars", u_errorName(status)))); - return ulen; -} - -/* - * Convert the given source string into a UChar string, stored in dest, and - * return the length (in UChars). - */ -static int32_t -uchar_convert(UConverter *converter, UChar *dest, int32_t destlen, - const char *src, int32_t srclen) -{ - UErrorCode status = U_ZERO_ERROR; - int32_t ulen; - - status = U_ZERO_ERROR; - ulen = ucnv_toUChars(converter, dest, destlen, src, srclen, &status); - if (U_FAILURE(status)) - ereport(ERROR, - (errmsg("%s failed: %s", "ucnv_toUChars", u_errorName(status)))); - return ulen; -} - -/* - * Convert a string in the database encoding into a string of UChars. - * - * The source string at buff is of length nbytes - * (it needn't be nul-terminated) - * - * *buff_uchar receives a pointer to the palloc'd result string, and - * the function's result is the number of UChars generated. - * - * The result string is nul-terminated, though most callers rely on the - * result length instead. - */ -int32_t -icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes) -{ - int32_t len_uchar; - - init_icu_converter(); - - len_uchar = uchar_length(icu_converter, buff, nbytes); - - *buff_uchar = palloc((len_uchar + 1) * sizeof(**buff_uchar)); - len_uchar = uchar_convert(icu_converter, - *buff_uchar, len_uchar + 1, buff, nbytes); - - return len_uchar; -} - -/* - * Convert a string of UChars into the database encoding. - * - * The source string at buff_uchar is of length len_uchar - * (it needn't be nul-terminated) - * - * *result receives a pointer to the palloc'd result string, and the - * function's result is the number of bytes generated (not counting nul). - * - * The result string is nul-terminated. - */ -int32_t -icu_from_uchar(char **result, const UChar *buff_uchar, int32_t len_uchar) -{ - UErrorCode status; - int32_t len_result; - - init_icu_converter(); - - status = U_ZERO_ERROR; - len_result = ucnv_fromUChars(icu_converter, NULL, 0, - buff_uchar, len_uchar, &status); - if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) - ereport(ERROR, - (errmsg("%s failed: %s", "ucnv_fromUChars", - u_errorName(status)))); - - *result = palloc(len_result + 1); - - status = U_ZERO_ERROR; - len_result = ucnv_fromUChars(icu_converter, *result, len_result + 1, - buff_uchar, len_uchar, &status); - if (U_FAILURE(status) || - status == U_STRING_NOT_TERMINATED_WARNING) - ereport(ERROR, - (errmsg("%s failed: %s", "ucnv_fromUChars", - u_errorName(status)))); - - return len_result; -} - -/* - * Parse collation attributes from the given locale string and apply them to - * the open collator. - * - * First, the locale string is canonicalized to an ICU format locale ID such - * as "und@colStrength=primary;colCaseLevel=yes". Then, it parses and applies - * the key-value arguments. - * - * Starting with ICU version 54, the attributes are processed automatically by - * ucol_open(), so this is only necessary for emulating this behavior on older - * versions. - */ -pg_attribute_unused() -static void -icu_set_collation_attributes(UCollator *collator, const char *loc, - UErrorCode *status) -{ - int32_t len; - char *icu_locale_id; - char *lower_str; - char *str; - char *token; - - /* - * The input locale may be a BCP 47 language tag, e.g. - * "und-u-kc-ks-level1", which expresses the same attributes in a - * different form. It will be converted to the equivalent ICU format - * locale ID, e.g. "und@colcaselevel=yes;colstrength=primary", by - * uloc_canonicalize(). - */ - *status = U_ZERO_ERROR; - len = uloc_canonicalize(loc, NULL, 0, status); - icu_locale_id = palloc(len + 1); - *status = U_ZERO_ERROR; - len = uloc_canonicalize(loc, icu_locale_id, len + 1, status); - if (U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) - return; - - lower_str = asc_tolower(icu_locale_id, strlen(icu_locale_id)); - - pfree(icu_locale_id); - - str = strchr(lower_str, '@'); - if (!str) - return; - str++; - - while ((token = strsep(&str, ";"))) - { - char *e = strchr(token, '='); - - if (e) - { - char *name; - char *value; - UColAttribute uattr; - UColAttributeValue uvalue; - - *status = U_ZERO_ERROR; - - *e = '\0'; - name = token; - value = e + 1; - - /* - * See attribute name and value lists in ICU i18n/coll.cpp - */ - if (strcmp(name, "colstrength") == 0) - uattr = UCOL_STRENGTH; - else if (strcmp(name, "colbackwards") == 0) - uattr = UCOL_FRENCH_COLLATION; - else if (strcmp(name, "colcaselevel") == 0) - uattr = UCOL_CASE_LEVEL; - else if (strcmp(name, "colcasefirst") == 0) - uattr = UCOL_CASE_FIRST; - else if (strcmp(name, "colalternate") == 0) - uattr = UCOL_ALTERNATE_HANDLING; - else if (strcmp(name, "colnormalization") == 0) - uattr = UCOL_NORMALIZATION_MODE; - else if (strcmp(name, "colnumeric") == 0) - uattr = UCOL_NUMERIC_COLLATION; - else - /* ignore if unknown */ - continue; - - if (strcmp(value, "primary") == 0) - uvalue = UCOL_PRIMARY; - else if (strcmp(value, "secondary") == 0) - uvalue = UCOL_SECONDARY; - else if (strcmp(value, "tertiary") == 0) - uvalue = UCOL_TERTIARY; - else if (strcmp(value, "quaternary") == 0) - uvalue = UCOL_QUATERNARY; - else if (strcmp(value, "identical") == 0) - uvalue = UCOL_IDENTICAL; - else if (strcmp(value, "no") == 0) - uvalue = UCOL_OFF; - else if (strcmp(value, "yes") == 0) - uvalue = UCOL_ON; - else if (strcmp(value, "shifted") == 0) - uvalue = UCOL_SHIFTED; - else if (strcmp(value, "non-ignorable") == 0) - uvalue = UCOL_NON_IGNORABLE; - else if (strcmp(value, "lower") == 0) - uvalue = UCOL_LOWER_FIRST; - else if (strcmp(value, "upper") == 0) - uvalue = UCOL_UPPER_FIRST; - else - { - *status = U_ILLEGAL_ARGUMENT_ERROR; - break; - } - - ucol_setAttribute(collator, uattr, uvalue, status); - } - } - - pfree(lower_str); -} -#endif /* * Return the BCP47 language tag representation of the requested locale. @@ -3050,145 +1660,3 @@ icu_validate_locale(const char *loc_str) errmsg("ICU is not supported in this build"))); #endif /* not USE_ICU */ } - -/* - * These functions convert from/to libc's wchar_t, *not* pg_wchar_t. - * Therefore we keep them here rather than with the mbutils code. - */ - -/* - * wchar2char --- convert wide characters to multibyte format - * - * This has the same API as the standard wcstombs_l() function; in particular, - * tolen is the maximum number of bytes to store at *to, and *from must be - * zero-terminated. The output will be zero-terminated iff there is room. - */ -size_t -wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale) -{ - size_t result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - - if (tolen == 0) - return 0; - -#ifdef WIN32 - - /* - * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and - * for some reason mbstowcs and wcstombs won't do this for us, so we use - * MultiByteToWideChar(). - */ - if (GetDatabaseEncoding() == PG_UTF8) - { - result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen, - NULL, NULL); - /* A zero return is failure */ - if (result <= 0) - result = -1; - else - { - Assert(result <= tolen); - /* Microsoft counts the zero terminator in the result */ - result--; - } - } - else -#endif /* WIN32 */ - if (locale == (pg_locale_t) 0) - { - /* Use wcstombs directly for the default locale */ - result = wcstombs(to, from, tolen); - } - else - { - /* Use wcstombs_l for nondefault locales */ - result = wcstombs_l(to, from, tolen, locale->info.lt); - } - - return result; -} - -/* - * char2wchar --- convert multibyte characters to wide characters - * - * This has almost the API of mbstowcs_l(), except that *from need not be - * null-terminated; instead, the number of input bytes is specified as - * fromlen. Also, we ereport() rather than returning -1 for invalid - * input encoding. tolen is the maximum number of wchar_t's to store at *to. - * The output will be zero-terminated iff there is room. - */ -size_t -char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, - pg_locale_t locale) -{ - size_t result; - - Assert(!locale || locale->provider == COLLPROVIDER_LIBC); - - if (tolen == 0) - return 0; - -#ifdef WIN32 - /* See WIN32 "Unicode" comment above */ - if (GetDatabaseEncoding() == PG_UTF8) - { - /* Win32 API does not work for zero-length input */ - if (fromlen == 0) - result = 0; - else - { - result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1); - /* A zero return is failure */ - if (result == 0) - result = -1; - } - - if (result != -1) - { - Assert(result < tolen); - /* Append trailing null wchar (MultiByteToWideChar() does not) */ - to[result] = 0; - } - } - else -#endif /* WIN32 */ - { - /* mbstowcs requires ending '\0' */ - char *str = pnstrdup(from, fromlen); - - if (locale == (pg_locale_t) 0) - { - /* Use mbstowcs directly for the default locale */ - result = mbstowcs(to, str, tolen); - } - else - { - /* Use mbstowcs_l for nondefault locales */ - result = mbstowcs_l(to, str, tolen, locale->info.lt); - } - - pfree(str); - } - - if (result == -1) - { - /* - * Invalid multibyte character encountered. We try to give a useful - * error message by letting pg_verifymbstr check the string. But it's - * possible that the string is OK to us, and not OK to mbstowcs --- - * this suggests that the LC_CTYPE locale is different from the - * database encoding. Give a generic error message if pg_verifymbstr - * can't find anything wrong. - */ - pg_verifymbstr(from, fromlen, false); /* might not return */ - /* but if it does ... */ - ereport(ERROR, - (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), - errmsg("invalid multibyte character for locale"), - errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding."))); - } - - return result; -} diff --git a/src/backend/utils/adt/pg_locale_builtin.c b/src/backend/utils/adt/pg_locale_builtin.c new file mode 100644 index 0000000000000..f51768830cd7b --- /dev/null +++ b/src/backend/utils/adt/pg_locale_builtin.c @@ -0,0 +1,192 @@ +/*----------------------------------------------------------------------- + * + * PostgreSQL locale utilities for builtin provider + * + * Portions Copyright (c) 2002-2025, PostgreSQL Global Development Group + * + * src/backend/utils/adt/pg_locale_builtin.c + * + *----------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "catalog/pg_database.h" +#include "catalog/pg_collation.h" +#include "common/unicode_case.h" +#include "common/unicode_category.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/memutils.h" +#include "utils/pg_locale.h" +#include "utils/syscache.h" + +extern pg_locale_t create_pg_locale_builtin(Oid collid, + MemoryContext context); +extern char *get_collation_actual_version_builtin(const char *collcollate); +extern size_t strlower_builtin(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_builtin(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_builtin(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strfold_builtin(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); + + +struct WordBoundaryState +{ + const char *str; + size_t len; + size_t offset; + bool posix; + bool init; + bool prev_alnum; +}; + +/* + * Simple word boundary iterator that draws boundaries each time the result of + * pg_u_isalnum() changes. + */ +static size_t +initcap_wbnext(void *state) +{ + struct WordBoundaryState *wbstate = (struct WordBoundaryState *) state; + + while (wbstate->offset < wbstate->len && + wbstate->str[wbstate->offset] != '\0') + { + pg_wchar u = utf8_to_unicode((unsigned char *) wbstate->str + + wbstate->offset); + bool curr_alnum = pg_u_isalnum(u, wbstate->posix); + + if (!wbstate->init || curr_alnum != wbstate->prev_alnum) + { + size_t prev_offset = wbstate->offset; + + wbstate->init = true; + wbstate->offset += unicode_utf8len(u); + wbstate->prev_alnum = curr_alnum; + return prev_offset; + } + + wbstate->offset += unicode_utf8len(u); + } + + return wbstate->len; +} + +size_t +strlower_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + return unicode_strlower(dest, destsize, src, srclen, + locale->info.builtin.casemap_full); +} + +size_t +strtitle_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + struct WordBoundaryState wbstate = { + .str = src, + .len = srclen, + .offset = 0, + .posix = !locale->info.builtin.casemap_full, + .init = false, + .prev_alnum = false, + }; + + return unicode_strtitle(dest, destsize, src, srclen, + locale->info.builtin.casemap_full, + initcap_wbnext, &wbstate); +} + +size_t +strupper_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + return unicode_strupper(dest, destsize, src, srclen, + locale->info.builtin.casemap_full); +} + +size_t +strfold_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + return unicode_strfold(dest, destsize, src, srclen, + locale->info.builtin.casemap_full); +} + +pg_locale_t +create_pg_locale_builtin(Oid collid, MemoryContext context) +{ + const char *locstr; + pg_locale_t result; + + if (collid == DEFAULT_COLLATION_OID) + { + HeapTuple tp; + Datum datum; + + tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + datum = SysCacheGetAttrNotNull(DATABASEOID, tp, + Anum_pg_database_datlocale); + locstr = TextDatumGetCString(datum); + ReleaseSysCache(tp); + } + else + { + HeapTuple tp; + Datum datum; + + tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for collation %u", collid); + datum = SysCacheGetAttrNotNull(COLLOID, tp, + Anum_pg_collation_colllocale); + locstr = TextDatumGetCString(datum); + ReleaseSysCache(tp); + } + + builtin_validate_locale(GetDatabaseEncoding(), locstr); + + result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct)); + + result->info.builtin.locale = MemoryContextStrdup(context, locstr); + result->info.builtin.casemap_full = (strcmp(locstr, "PG_UNICODE_FAST") == 0); + result->provider = COLLPROVIDER_BUILTIN; + result->deterministic = true; + result->collate_is_c = true; + result->ctype_is_c = (strcmp(locstr, "C") == 0); + + return result; +} + +char * +get_collation_actual_version_builtin(const char *collcollate) +{ + /* + * The only two supported locales (C and C.UTF-8) are both based on memcmp + * and are not expected to change, but track the version anyway. + * + * Note that the character semantics may change for some locales, but the + * collation version only tracks changes to sort order. + */ + if (strcmp(collcollate, "C") == 0) + return "1"; + else if (strcmp(collcollate, "C.UTF-8") == 0) + return "1"; + else if (strcmp(collcollate, "PG_UNICODE_FAST") == 0) + return "1"; + else + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid locale name \"%s\" for builtin provider", + collcollate))); + + return NULL; /* keep compiler quiet */ +} diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c new file mode 100644 index 0000000000000..a32c32a0744bd --- /dev/null +++ b/src/backend/utils/adt/pg_locale_icu.c @@ -0,0 +1,1023 @@ +/*----------------------------------------------------------------------- + * + * PostgreSQL locale utilities for ICU + * + * Portions Copyright (c) 2002-2025, PostgreSQL Global Development Group + * + * src/backend/utils/adt/pg_locale_icu.c + * + *----------------------------------------------------------------------- + */ + +#include "postgres.h" + +#ifdef USE_ICU +#include +#include + +/* + * ucol_strcollUTF8() was introduced in ICU 50, but it is buggy before ICU 53. + * (see + * ) + */ +#if U_ICU_VERSION_MAJOR_NUM >= 53 +#define HAVE_UCOL_STRCOLLUTF8 1 +#else +#undef HAVE_UCOL_STRCOLLUTF8 +#endif + +#endif + +#include "access/htup_details.h" +#include "catalog/pg_database.h" +#include "catalog/pg_collation.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/formatting.h" +#include "utils/memutils.h" +#include "utils/pg_locale.h" +#include "utils/syscache.h" + +/* + * Size of stack buffer to use for string transformations, used to avoid heap + * allocations in typical cases. This should be large enough that most strings + * will fit, but small enough that we feel comfortable putting it on the + * stack. + */ +#define TEXTBUFLEN 1024 + +extern pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context); +extern size_t strlower_icu(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_icu(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_icu(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strfold_icu(char *dest, size_t destsize, const char *src, + ssize_t srclen, pg_locale_t locale); + +#ifdef USE_ICU + +extern UCollator *pg_ucol_open(const char *loc_str); + +static size_t strnxfrm_icu(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +extern char *get_collation_actual_version_icu(const char *collcollate); + +typedef int32_t (*ICU_Convert_Func) (UChar *dest, int32_t destCapacity, + const UChar *src, int32_t srcLength, + const char *locale, + UErrorCode *pErrorCode); + +/* + * Converter object for converting between ICU's UChar strings and C strings + * in database encoding. Since the database encoding doesn't change, we only + * need one of these per session. + */ +static UConverter *icu_converter = NULL; + +static UCollator *make_icu_collator(const char *iculocstr, + const char *icurules); +static int strncoll_icu(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, + pg_locale_t locale); +static size_t strnxfrm_prefix_icu(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +#ifdef HAVE_UCOL_STRCOLLUTF8 +static int strncoll_icu_utf8(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, + pg_locale_t locale); +#endif +static size_t strnxfrm_prefix_icu_utf8(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static void init_icu_converter(void); +static size_t uchar_length(UConverter *converter, + const char *str, int32_t len); +static int32_t uchar_convert(UConverter *converter, + UChar *dest, int32_t destlen, + const char *src, int32_t srclen); +static int32_t icu_to_uchar(UChar **buff_uchar, const char *buff, + size_t nbytes); +static size_t icu_from_uchar(char *dest, size_t destsize, + const UChar *buff_uchar, int32_t len_uchar); +static void icu_set_collation_attributes(UCollator *collator, const char *loc, + UErrorCode *status); +static int32_t icu_convert_case(ICU_Convert_Func func, pg_locale_t mylocale, + UChar **buff_dest, UChar *buff_source, + int32_t len_source); +static int32_t u_strToTitle_default_BI(UChar *dest, int32_t destCapacity, + const UChar *src, int32_t srcLength, + const char *locale, + UErrorCode *pErrorCode); +static int32_t u_strFoldCase_default(UChar *dest, int32_t destCapacity, + const UChar *src, int32_t srcLength, + const char *locale, + UErrorCode *pErrorCode); + +static const struct collate_methods collate_methods_icu = { + .strncoll = strncoll_icu, + .strnxfrm = strnxfrm_icu, + .strnxfrm_prefix = strnxfrm_prefix_icu, + .strxfrm_is_safe = true, +}; + +static const struct collate_methods collate_methods_icu_utf8 = { +#ifdef HAVE_UCOL_STRCOLLUTF8 + .strncoll = strncoll_icu_utf8, +#else + .strncoll = strncoll_icu, +#endif + .strnxfrm = strnxfrm_icu, + .strnxfrm_prefix = strnxfrm_prefix_icu_utf8, + .strxfrm_is_safe = true, +}; + +#endif + +pg_locale_t +create_pg_locale_icu(Oid collid, MemoryContext context) +{ +#ifdef USE_ICU + bool deterministic; + const char *iculocstr; + const char *icurules = NULL; + UCollator *collator; + pg_locale_t result; + + if (collid == DEFAULT_COLLATION_OID) + { + HeapTuple tp; + Datum datum; + bool isnull; + + tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + + /* default database collation is always deterministic */ + deterministic = true; + datum = SysCacheGetAttrNotNull(DATABASEOID, tp, + Anum_pg_database_datlocale); + iculocstr = TextDatumGetCString(datum); + datum = SysCacheGetAttr(DATABASEOID, tp, + Anum_pg_database_daticurules, &isnull); + if (!isnull) + icurules = TextDatumGetCString(datum); + + ReleaseSysCache(tp); + } + else + { + Form_pg_collation collform; + HeapTuple tp; + Datum datum; + bool isnull; + + tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for collation %u", collid); + collform = (Form_pg_collation) GETSTRUCT(tp); + deterministic = collform->collisdeterministic; + datum = SysCacheGetAttrNotNull(COLLOID, tp, + Anum_pg_collation_colllocale); + iculocstr = TextDatumGetCString(datum); + datum = SysCacheGetAttr(COLLOID, tp, + Anum_pg_collation_collicurules, &isnull); + if (!isnull) + icurules = TextDatumGetCString(datum); + + ReleaseSysCache(tp); + } + + collator = make_icu_collator(iculocstr, icurules); + + result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct)); + result->info.icu.locale = MemoryContextStrdup(context, iculocstr); + result->info.icu.ucol = collator; + result->provider = COLLPROVIDER_ICU; + result->deterministic = deterministic; + result->collate_is_c = false; + result->ctype_is_c = false; + if (GetDatabaseEncoding() == PG_UTF8) + result->collate = &collate_methods_icu_utf8; + else + result->collate = &collate_methods_icu; + + return result; +#else + /* could get here if a collation was created by a build with ICU */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ICU is not supported in this build"))); + + return NULL; +#endif +} + +#ifdef USE_ICU + +/* + * Wrapper around ucol_open() to handle API differences for older ICU + * versions. + * + * Ensure that no path leaks a UCollator. + */ +UCollator * +pg_ucol_open(const char *loc_str) +{ + UCollator *collator; + UErrorCode status; + const char *orig_str = loc_str; + char *fixed_str = NULL; + + /* + * Must never open default collator, because it depends on the environment + * and may change at any time. Should not happen, but check here to catch + * bugs that might be hard to catch otherwise. + * + * NB: the default collator is not the same as the collator for the root + * locale. The root locale may be specified as the empty string, "und", or + * "root". The default collator is opened by passing NULL to ucol_open(). + */ + if (loc_str == NULL) + elog(ERROR, "opening default collator is not supported"); + + /* + * In ICU versions 54 and earlier, "und" is not a recognized spelling of + * the root locale. If the first component of the locale is "und", replace + * with "root" before opening. + */ + if (U_ICU_VERSION_MAJOR_NUM < 55) + { + char lang[ULOC_LANG_CAPACITY]; + + status = U_ZERO_ERROR; + uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status); + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not get language from locale \"%s\": %s", + loc_str, u_errorName(status)))); + } + + if (strcmp(lang, "und") == 0) + { + const char *remainder = loc_str + strlen("und"); + + fixed_str = palloc(strlen("root") + strlen(remainder) + 1); + strcpy(fixed_str, "root"); + strcat(fixed_str, remainder); + + loc_str = fixed_str; + } + } + + status = U_ZERO_ERROR; + collator = ucol_open(loc_str, &status); + if (U_FAILURE(status)) + ereport(ERROR, + /* use original string for error report */ + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not open collator for locale \"%s\": %s", + orig_str, u_errorName(status)))); + + if (U_ICU_VERSION_MAJOR_NUM < 54) + { + status = U_ZERO_ERROR; + icu_set_collation_attributes(collator, loc_str, &status); + + /* + * Pretend the error came from ucol_open(), for consistent error + * message across ICU versions. + */ + if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) + { + ucol_close(collator); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not open collator for locale \"%s\": %s", + orig_str, u_errorName(status)))); + } + } + + if (fixed_str != NULL) + pfree(fixed_str); + + return collator; +} + +/* + * Create a UCollator with the given locale string and rules. + * + * Ensure that no path leaks a UCollator. + */ +static UCollator * +make_icu_collator(const char *iculocstr, const char *icurules) +{ + if (!icurules) + { + /* simple case without rules */ + return pg_ucol_open(iculocstr); + } + else + { + UCollator *collator_std_rules; + UCollator *collator_all_rules; + const UChar *std_rules; + UChar *my_rules; + UChar *all_rules; + int32_t length; + int32_t total; + UErrorCode status; + + /* + * If rules are specified, we extract the rules of the standard + * collation, add our own rules, and make a new collator with the + * combined rules. + */ + icu_to_uchar(&my_rules, icurules, strlen(icurules)); + + collator_std_rules = pg_ucol_open(iculocstr); + + std_rules = ucol_getRules(collator_std_rules, &length); + + total = u_strlen(std_rules) + u_strlen(my_rules) + 1; + + /* avoid leaking collator on OOM */ + all_rules = palloc_extended(sizeof(UChar) * total, MCXT_ALLOC_NO_OOM); + if (!all_rules) + { + ucol_close(collator_std_rules); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + } + + u_strcpy(all_rules, std_rules); + u_strcat(all_rules, my_rules); + + ucol_close(collator_std_rules); + + status = U_ZERO_ERROR; + collator_all_rules = ucol_openRules(all_rules, u_strlen(all_rules), + UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, + NULL, &status); + if (U_FAILURE(status)) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not open collator for locale \"%s\" with rules \"%s\": %s", + iculocstr, icurules, u_errorName(status)))); + } + + return collator_all_rules; + } +} + +size_t +strlower_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + int32_t len_uchar; + int32_t len_conv; + UChar *buff_uchar; + UChar *buff_conv; + size_t result_len; + + len_uchar = icu_to_uchar(&buff_uchar, src, srclen); + len_conv = icu_convert_case(u_strToLower, locale, + &buff_conv, buff_uchar, len_uchar); + result_len = icu_from_uchar(dest, destsize, buff_conv, len_conv); + pfree(buff_uchar); + pfree(buff_conv); + + return result_len; +} + +size_t +strtitle_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + int32_t len_uchar; + int32_t len_conv; + UChar *buff_uchar; + UChar *buff_conv; + size_t result_len; + + len_uchar = icu_to_uchar(&buff_uchar, src, srclen); + len_conv = icu_convert_case(u_strToTitle_default_BI, locale, + &buff_conv, buff_uchar, len_uchar); + result_len = icu_from_uchar(dest, destsize, buff_conv, len_conv); + pfree(buff_uchar); + pfree(buff_conv); + + return result_len; +} + +size_t +strupper_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + int32_t len_uchar; + int32_t len_conv; + UChar *buff_uchar; + UChar *buff_conv; + size_t result_len; + + len_uchar = icu_to_uchar(&buff_uchar, src, srclen); + len_conv = icu_convert_case(u_strToUpper, locale, + &buff_conv, buff_uchar, len_uchar); + result_len = icu_from_uchar(dest, destsize, buff_conv, len_conv); + pfree(buff_uchar); + pfree(buff_conv); + + return result_len; +} + +size_t +strfold_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + int32_t len_uchar; + int32_t len_conv; + UChar *buff_uchar; + UChar *buff_conv; + size_t result_len; + + len_uchar = icu_to_uchar(&buff_uchar, src, srclen); + len_conv = icu_convert_case(u_strFoldCase_default, locale, + &buff_conv, buff_uchar, len_uchar); + result_len = icu_from_uchar(dest, destsize, buff_conv, len_conv); + pfree(buff_uchar); + pfree(buff_conv); + + return result_len; +} + +/* + * strncoll_icu_utf8 + * + * Call ucol_strcollUTF8() or ucol_strcoll() as appropriate for the given + * database encoding. An argument length of -1 means the string is + * NUL-terminated. + */ +#ifdef HAVE_UCOL_STRCOLLUTF8 +int +strncoll_icu_utf8(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, + pg_locale_t locale) +{ + int result; + UErrorCode status; + + Assert(locale->provider == COLLPROVIDER_ICU); + + Assert(GetDatabaseEncoding() == PG_UTF8); + + status = U_ZERO_ERROR; + result = ucol_strcollUTF8(locale->info.icu.ucol, + arg1, len1, + arg2, len2, + &status); + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("collation failed: %s", u_errorName(status)))); + + return result; +} +#endif + +/* 'srclen' of -1 means the strings are NUL-terminated */ +size_t +strnxfrm_icu(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + UChar *uchar; + int32_t ulen; + size_t uchar_bsize; + Size result_bsize; + + Assert(locale->provider == COLLPROVIDER_ICU); + + init_icu_converter(); + + ulen = uchar_length(icu_converter, src, srclen); + + uchar_bsize = (ulen + 1) * sizeof(UChar); + + if (uchar_bsize > TEXTBUFLEN) + buf = palloc(uchar_bsize); + + uchar = (UChar *) buf; + + ulen = uchar_convert(icu_converter, uchar, ulen + 1, src, srclen); + + result_bsize = ucol_getSortKey(locale->info.icu.ucol, + uchar, ulen, + (uint8_t *) dest, destsize); + + /* + * ucol_getSortKey() counts the nul-terminator in the result length, but + * this function should not. + */ + Assert(result_bsize > 0); + result_bsize--; + + if (buf != sbuf) + pfree(buf); + + /* if dest is defined, it should be nul-terminated */ + Assert(result_bsize >= destsize || dest[result_bsize] == '\0'); + + return result_bsize; +} + +/* 'srclen' of -1 means the strings are NUL-terminated */ +size_t +strnxfrm_prefix_icu_utf8(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale) +{ + size_t result; + UCharIterator iter; + uint32_t state[2]; + UErrorCode status; + + Assert(locale->provider == COLLPROVIDER_ICU); + + Assert(GetDatabaseEncoding() == PG_UTF8); + + uiter_setUTF8(&iter, src, srclen); + state[0] = state[1] = 0; /* won't need that again */ + status = U_ZERO_ERROR; + result = ucol_nextSortKeyPart(locale->info.icu.ucol, + &iter, + state, + (uint8_t *) dest, + destsize, + &status); + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("sort key generation failed: %s", + u_errorName(status)))); + + return result; +} + +char * +get_collation_actual_version_icu(const char *collcollate) +{ + UCollator *collator; + UVersionInfo versioninfo; + char buf[U_MAX_VERSION_STRING_LENGTH]; + + collator = pg_ucol_open(collcollate); + + ucol_getVersion(collator, versioninfo); + ucol_close(collator); + + u_versionToString(versioninfo, buf); + return pstrdup(buf); +} + +/* + * Convert a string in the database encoding into a string of UChars. + * + * The source string at buff is of length nbytes + * (it needn't be nul-terminated) + * + * *buff_uchar receives a pointer to the palloc'd result string, and + * the function's result is the number of UChars generated. + * + * The result string is nul-terminated, though most callers rely on the + * result length instead. + */ +static int32_t +icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes) +{ + int32_t len_uchar; + + init_icu_converter(); + + len_uchar = uchar_length(icu_converter, buff, nbytes); + + *buff_uchar = palloc((len_uchar + 1) * sizeof(**buff_uchar)); + len_uchar = uchar_convert(icu_converter, + *buff_uchar, len_uchar + 1, buff, nbytes); + + return len_uchar; +} + +/* + * Convert a string of UChars into the database encoding. + * + * The source string at buff_uchar is of length len_uchar + * (it needn't be nul-terminated) + * + * *result receives a pointer to the palloc'd result string, and the + * function's result is the number of bytes generated (not counting nul). + * + * The result string is nul-terminated. + */ +static size_t +icu_from_uchar(char *dest, size_t destsize, const UChar *buff_uchar, int32_t len_uchar) +{ + UErrorCode status; + int32_t len_result; + + init_icu_converter(); + + status = U_ZERO_ERROR; + len_result = ucnv_fromUChars(icu_converter, NULL, 0, + buff_uchar, len_uchar, &status); + if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) + ereport(ERROR, + (errmsg("%s failed: %s", "ucnv_fromUChars", + u_errorName(status)))); + + if (len_result + 1 > destsize) + return len_result; + + status = U_ZERO_ERROR; + len_result = ucnv_fromUChars(icu_converter, dest, len_result + 1, + buff_uchar, len_uchar, &status); + if (U_FAILURE(status) || + status == U_STRING_NOT_TERMINATED_WARNING) + ereport(ERROR, + (errmsg("%s failed: %s", "ucnv_fromUChars", + u_errorName(status)))); + + return len_result; +} + +static int32_t +icu_convert_case(ICU_Convert_Func func, pg_locale_t mylocale, + UChar **buff_dest, UChar *buff_source, int32_t len_source) +{ + UErrorCode status; + int32_t len_dest; + + len_dest = len_source; /* try first with same length */ + *buff_dest = palloc(len_dest * sizeof(**buff_dest)); + status = U_ZERO_ERROR; + len_dest = func(*buff_dest, len_dest, buff_source, len_source, + mylocale->info.icu.locale, &status); + if (status == U_BUFFER_OVERFLOW_ERROR) + { + /* try again with adjusted length */ + pfree(*buff_dest); + *buff_dest = palloc(len_dest * sizeof(**buff_dest)); + status = U_ZERO_ERROR; + len_dest = func(*buff_dest, len_dest, buff_source, len_source, + mylocale->info.icu.locale, &status); + } + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("case conversion failed: %s", u_errorName(status)))); + return len_dest; +} + +static int32_t +u_strToTitle_default_BI(UChar *dest, int32_t destCapacity, + const UChar *src, int32_t srcLength, + const char *locale, + UErrorCode *pErrorCode) +{ + return u_strToTitle(dest, destCapacity, src, srcLength, + NULL, locale, pErrorCode); +} + +static int32_t +u_strFoldCase_default(UChar *dest, int32_t destCapacity, + const UChar *src, int32_t srcLength, + const char *locale, + UErrorCode *pErrorCode) +{ + uint32 options = U_FOLD_CASE_DEFAULT; + char lang[3]; + UErrorCode status; + + /* + * Unlike the ICU APIs for lowercasing, titlecasing, and uppercasing, case + * folding does not accept a locale. Instead it just supports a single + * option relevant to Turkic languages 'az' and 'tr'; check for those + * languages to enable the option. + */ + status = U_ZERO_ERROR; + uloc_getLanguage(locale, lang, 3, &status); + if (U_SUCCESS(status)) + { + /* + * The option name is confusing, but it causes u_strFoldCase to use + * the 'T' mappings, which are ignored for U_FOLD_CASE_DEFAULT. + */ + if (strcmp(lang, "tr") == 0 || strcmp(lang, "az") == 0) + options = U_FOLD_CASE_EXCLUDE_SPECIAL_I; + } + + return u_strFoldCase(dest, destCapacity, src, srcLength, + options, pErrorCode); +} + +/* + * strncoll_icu + * + * Convert the arguments from the database encoding to UChar strings, then + * call ucol_strcoll(). An argument length of -1 means that the string is + * NUL-terminated. + * + * When the database encoding is UTF-8, and ICU supports ucol_strcollUTF8(), + * caller should call that instead. + */ +static int +strncoll_icu(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + int32_t ulen1; + int32_t ulen2; + size_t bufsize1; + size_t bufsize2; + UChar *uchar1, + *uchar2; + int result; + + Assert(locale->provider == COLLPROVIDER_ICU); + + /* if encoding is UTF8, use more efficient strncoll_icu_utf8 */ +#ifdef HAVE_UCOL_STRCOLLUTF8 + Assert(GetDatabaseEncoding() != PG_UTF8); +#endif + + init_icu_converter(); + + ulen1 = uchar_length(icu_converter, arg1, len1); + ulen2 = uchar_length(icu_converter, arg2, len2); + + bufsize1 = (ulen1 + 1) * sizeof(UChar); + bufsize2 = (ulen2 + 1) * sizeof(UChar); + + if (bufsize1 + bufsize2 > TEXTBUFLEN) + buf = palloc(bufsize1 + bufsize2); + + uchar1 = (UChar *) buf; + uchar2 = (UChar *) (buf + bufsize1); + + ulen1 = uchar_convert(icu_converter, uchar1, ulen1 + 1, arg1, len1); + ulen2 = uchar_convert(icu_converter, uchar2, ulen2 + 1, arg2, len2); + + result = ucol_strcoll(locale->info.icu.ucol, + uchar1, ulen1, + uchar2, ulen2); + + if (buf != sbuf) + pfree(buf); + + return result; +} + +/* 'srclen' of -1 means the strings are NUL-terminated */ +static size_t +strnxfrm_prefix_icu(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + UCharIterator iter; + uint32_t state[2]; + UErrorCode status; + int32_t ulen = -1; + UChar *uchar = NULL; + size_t uchar_bsize; + Size result_bsize; + + Assert(locale->provider == COLLPROVIDER_ICU); + + /* if encoding is UTF8, use more efficient strnxfrm_prefix_icu_utf8 */ + Assert(GetDatabaseEncoding() != PG_UTF8); + + init_icu_converter(); + + ulen = uchar_length(icu_converter, src, srclen); + + uchar_bsize = (ulen + 1) * sizeof(UChar); + + if (uchar_bsize > TEXTBUFLEN) + buf = palloc(uchar_bsize); + + uchar = (UChar *) buf; + + ulen = uchar_convert(icu_converter, uchar, ulen + 1, src, srclen); + + uiter_setString(&iter, uchar, ulen); + state[0] = state[1] = 0; /* won't need that again */ + status = U_ZERO_ERROR; + result_bsize = ucol_nextSortKeyPart(locale->info.icu.ucol, + &iter, + state, + (uint8_t *) dest, + destsize, + &status); + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("sort key generation failed: %s", + u_errorName(status)))); + + return result_bsize; +} + +static void +init_icu_converter(void) +{ + const char *icu_encoding_name; + UErrorCode status; + UConverter *conv; + + if (icu_converter) + return; /* already done */ + + icu_encoding_name = get_encoding_name_for_icu(GetDatabaseEncoding()); + if (!icu_encoding_name) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("encoding \"%s\" not supported by ICU", + pg_encoding_to_char(GetDatabaseEncoding())))); + + status = U_ZERO_ERROR; + conv = ucnv_open(icu_encoding_name, &status); + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("could not open ICU converter for encoding \"%s\": %s", + icu_encoding_name, u_errorName(status)))); + + icu_converter = conv; +} + +/* + * Find length, in UChars, of given string if converted to UChar string. + * + * A length of -1 indicates that the input string is NUL-terminated. + */ +static size_t +uchar_length(UConverter *converter, const char *str, int32_t len) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t ulen; + + ulen = ucnv_toUChars(converter, NULL, 0, str, len, &status); + if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) + ereport(ERROR, + (errmsg("%s failed: %s", "ucnv_toUChars", u_errorName(status)))); + return ulen; +} + +/* + * Convert the given source string into a UChar string, stored in dest, and + * return the length (in UChars). + * + * A srclen of -1 indicates that the input string is NUL-terminated. + */ +static int32_t +uchar_convert(UConverter *converter, UChar *dest, int32_t destlen, + const char *src, int32_t srclen) +{ + UErrorCode status = U_ZERO_ERROR; + int32_t ulen; + + status = U_ZERO_ERROR; + ulen = ucnv_toUChars(converter, dest, destlen, src, srclen, &status); + if (U_FAILURE(status)) + ereport(ERROR, + (errmsg("%s failed: %s", "ucnv_toUChars", u_errorName(status)))); + return ulen; +} + +/* + * Parse collation attributes from the given locale string and apply them to + * the open collator. + * + * First, the locale string is canonicalized to an ICU format locale ID such + * as "und@colStrength=primary;colCaseLevel=yes". Then, it parses and applies + * the key-value arguments. + * + * Starting with ICU version 54, the attributes are processed automatically by + * ucol_open(), so this is only necessary for emulating this behavior on older + * versions. + */ +pg_attribute_unused() +static void +icu_set_collation_attributes(UCollator *collator, const char *loc, + UErrorCode *status) +{ + int32_t len; + char *icu_locale_id; + char *lower_str; + char *str; + char *token; + + /* + * The input locale may be a BCP 47 language tag, e.g. + * "und-u-kc-ks-level1", which expresses the same attributes in a + * different form. It will be converted to the equivalent ICU format + * locale ID, e.g. "und@colcaselevel=yes;colstrength=primary", by + * uloc_canonicalize(). + */ + *status = U_ZERO_ERROR; + len = uloc_canonicalize(loc, NULL, 0, status); + icu_locale_id = palloc(len + 1); + *status = U_ZERO_ERROR; + len = uloc_canonicalize(loc, icu_locale_id, len + 1, status); + if (U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) + return; + + lower_str = asc_tolower(icu_locale_id, strlen(icu_locale_id)); + + pfree(icu_locale_id); + + str = strchr(lower_str, '@'); + if (!str) + return; + str++; + + while ((token = strsep(&str, ";"))) + { + char *e = strchr(token, '='); + + if (e) + { + char *name; + char *value; + UColAttribute uattr; + UColAttributeValue uvalue; + + *status = U_ZERO_ERROR; + + *e = '\0'; + name = token; + value = e + 1; + + /* + * See attribute name and value lists in ICU i18n/coll.cpp + */ + if (strcmp(name, "colstrength") == 0) + uattr = UCOL_STRENGTH; + else if (strcmp(name, "colbackwards") == 0) + uattr = UCOL_FRENCH_COLLATION; + else if (strcmp(name, "colcaselevel") == 0) + uattr = UCOL_CASE_LEVEL; + else if (strcmp(name, "colcasefirst") == 0) + uattr = UCOL_CASE_FIRST; + else if (strcmp(name, "colalternate") == 0) + uattr = UCOL_ALTERNATE_HANDLING; + else if (strcmp(name, "colnormalization") == 0) + uattr = UCOL_NORMALIZATION_MODE; + else if (strcmp(name, "colnumeric") == 0) + uattr = UCOL_NUMERIC_COLLATION; + else + /* ignore if unknown */ + continue; + + if (strcmp(value, "primary") == 0) + uvalue = UCOL_PRIMARY; + else if (strcmp(value, "secondary") == 0) + uvalue = UCOL_SECONDARY; + else if (strcmp(value, "tertiary") == 0) + uvalue = UCOL_TERTIARY; + else if (strcmp(value, "quaternary") == 0) + uvalue = UCOL_QUATERNARY; + else if (strcmp(value, "identical") == 0) + uvalue = UCOL_IDENTICAL; + else if (strcmp(value, "no") == 0) + uvalue = UCOL_OFF; + else if (strcmp(value, "yes") == 0) + uvalue = UCOL_ON; + else if (strcmp(value, "shifted") == 0) + uvalue = UCOL_SHIFTED; + else if (strcmp(value, "non-ignorable") == 0) + uvalue = UCOL_NON_IGNORABLE; + else if (strcmp(value, "lower") == 0) + uvalue = UCOL_LOWER_FIRST; + else if (strcmp(value, "upper") == 0) + uvalue = UCOL_UPPER_FIRST; + else + { + *status = U_ILLEGAL_ARGUMENT_ERROR; + break; + } + + ucol_setAttribute(collator, uattr, uvalue, status); + } + } + + pfree(lower_str); +} + +#endif /* USE_ICU */ diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c new file mode 100644 index 0000000000000..199857e22dbec --- /dev/null +++ b/src/backend/utils/adt/pg_locale_libc.c @@ -0,0 +1,1005 @@ +/*----------------------------------------------------------------------- + * + * PostgreSQL locale utilities for libc + * + * Portions Copyright (c) 2002-2025, PostgreSQL Global Development Group + * + * src/backend/utils/adt/pg_locale_libc.c + * + *----------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include + +#include "access/htup_details.h" +#include "catalog/pg_database.h" +#include "catalog/pg_collation.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" +#include "utils/builtins.h" +#include "utils/formatting.h" +#include "utils/memutils.h" +#include "utils/pg_locale.h" +#include "utils/syscache.h" + +#ifdef __GLIBC__ +#include +#endif + +#ifdef WIN32 +#include +#endif + +/* + * Size of stack buffer to use for string transformations, used to avoid heap + * allocations in typical cases. This should be large enough that most strings + * will fit, but small enough that we feel comfortable putting it on the + * stack. + */ +#define TEXTBUFLEN 1024 + +extern pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context); + +extern size_t strlower_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strtitle_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); +extern size_t strupper_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale); + +static int strncoll_libc(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, + pg_locale_t locale); +static size_t strnxfrm_libc(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +extern char *get_collation_actual_version_libc(const char *collcollate); +static locale_t make_libc_collator(const char *collate, + const char *ctype); + +#ifdef WIN32 +static int strncoll_libc_win32_utf8(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, + pg_locale_t locale); +#endif + +static size_t strlower_libc_sb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static size_t strlower_libc_mb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static size_t strtitle_libc_sb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static size_t strtitle_libc_mb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static size_t strupper_libc_sb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +static size_t strupper_libc_mb(char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); + +static const struct collate_methods collate_methods_libc = { + .strncoll = strncoll_libc, + .strnxfrm = strnxfrm_libc, + .strnxfrm_prefix = NULL, + + /* + * Unfortunately, it seems that strxfrm() for non-C collations is broken + * on many common platforms; testing of multiple versions of glibc reveals + * that, for many locales, strcoll() and strxfrm() do not return + * consistent results. While no other libc other than Cygwin has so far + * been shown to have a problem, we take the conservative course of action + * for right now and disable this categorically. (Users who are certain + * this isn't a problem on their system can define TRUST_STRXFRM.) + */ +#ifdef TRUST_STRXFRM + .strxfrm_is_safe = true, +#else + .strxfrm_is_safe = false, +#endif +}; + +#ifdef WIN32 +static const struct collate_methods collate_methods_libc_win32_utf8 = { + .strncoll = strncoll_libc_win32_utf8, + .strnxfrm = strnxfrm_libc, + .strnxfrm_prefix = NULL, +#ifdef TRUST_STRXFRM + .strxfrm_is_safe = true, +#else + .strxfrm_is_safe = false, +#endif +}; +#endif + +size_t +strlower_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale) +{ + if (pg_database_encoding_max_length() > 1) + return strlower_libc_mb(dst, dstsize, src, srclen, locale); + else + return strlower_libc_sb(dst, dstsize, src, srclen, locale); +} + +size_t +strtitle_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale) +{ + if (pg_database_encoding_max_length() > 1) + return strtitle_libc_mb(dst, dstsize, src, srclen, locale); + else + return strtitle_libc_sb(dst, dstsize, src, srclen, locale); +} + +size_t +strupper_libc(char *dst, size_t dstsize, const char *src, + ssize_t srclen, pg_locale_t locale) +{ + if (pg_database_encoding_max_length() > 1) + return strupper_libc_mb(dst, dstsize, src, srclen, locale); + else + return strupper_libc_sb(dst, dstsize, src, srclen, locale); +} + +static size_t +strlower_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (srclen < 0) + srclen = strlen(src); + + if (srclen + 1 <= destsize) + { + locale_t loc = locale->info.lt; + char *p; + + if (srclen + 1 > destsize) + return srclen; + + memcpy(dest, src, srclen); + dest[srclen] = '\0'; + + /* + * Note: we assume that tolower_l() will not be so broken as to need + * an isupper_l() guard test. When using the default collation, we + * apply the traditional Postgres behavior that forces ASCII-style + * treatment of I/i, but in non-default collations you get exactly + * what the collation says. + */ + for (p = dest; *p; p++) + { + if (locale->is_default) + *p = pg_tolower((unsigned char) *p); + else + *p = tolower_l((unsigned char) *p, loc); + } + } + + return srclen; +} + +static size_t +strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + locale_t loc = locale->info.lt; + size_t result_size; + wchar_t *workspace; + char *result; + size_t curr_char; + size_t max_size; + + if (srclen < 0) + srclen = strlen(src); + + /* Overflow paranoia */ + if ((srclen + 1) > (INT_MAX / sizeof(wchar_t))) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + /* Output workspace cannot have more codes than input bytes */ + workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t)); + + char2wchar(workspace, srclen + 1, src, srclen, locale); + + for (curr_char = 0; workspace[curr_char] != 0; curr_char++) + workspace[curr_char] = towlower_l(workspace[curr_char], loc); + + /* + * Make result large enough; case change might change number of bytes + */ + max_size = curr_char * pg_database_encoding_max_length(); + result = palloc(max_size + 1); + + result_size = wchar2char(result, workspace, max_size + 1, locale); + + if (result_size + 1 > destsize) + return result_size; + + memcpy(dest, result, result_size); + dest[result_size] = '\0'; + + pfree(workspace); + pfree(result); + + return result_size; +} + +static size_t +strtitle_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (srclen < 0) + srclen = strlen(src); + + if (srclen + 1 <= destsize) + { + locale_t loc = locale->info.lt; + int wasalnum = false; + char *p; + + memcpy(dest, src, srclen); + dest[srclen] = '\0'; + + /* + * Note: we assume that toupper_l()/tolower_l() will not be so broken + * as to need guard tests. When using the default collation, we apply + * the traditional Postgres behavior that forces ASCII-style treatment + * of I/i, but in non-default collations you get exactly what the + * collation says. + */ + for (p = dest; *p; p++) + { + if (locale->is_default) + { + if (wasalnum) + *p = pg_tolower((unsigned char) *p); + else + *p = pg_toupper((unsigned char) *p); + } + else + { + if (wasalnum) + *p = tolower_l((unsigned char) *p, loc); + else + *p = toupper_l((unsigned char) *p, loc); + } + wasalnum = isalnum_l((unsigned char) *p, loc); + } + } + + return srclen; +} + +static size_t +strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + locale_t loc = locale->info.lt; + int wasalnum = false; + size_t result_size; + wchar_t *workspace; + char *result; + size_t curr_char; + size_t max_size; + + if (srclen < 0) + srclen = strlen(src); + + /* Overflow paranoia */ + if ((srclen + 1) > (INT_MAX / sizeof(wchar_t))) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + /* Output workspace cannot have more codes than input bytes */ + workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t)); + + char2wchar(workspace, srclen + 1, src, srclen, locale); + + for (curr_char = 0; workspace[curr_char] != 0; curr_char++) + { + if (wasalnum) + workspace[curr_char] = towlower_l(workspace[curr_char], loc); + else + workspace[curr_char] = towupper_l(workspace[curr_char], loc); + wasalnum = iswalnum_l(workspace[curr_char], loc); + } + + /* + * Make result large enough; case change might change number of bytes + */ + max_size = curr_char * pg_database_encoding_max_length(); + result = palloc(max_size + 1); + + result_size = wchar2char(result, workspace, max_size + 1, locale); + + if (result_size + 1 > destsize) + return result_size; + + memcpy(dest, result, result_size); + dest[result_size] = '\0'; + + pfree(workspace); + pfree(result); + + return result_size; +} + +static size_t +strupper_libc_sb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + if (srclen < 0) + srclen = strlen(src); + + if (srclen + 1 <= destsize) + { + locale_t loc = locale->info.lt; + char *p; + + memcpy(dest, src, srclen); + dest[srclen] = '\0'; + + /* + * Note: we assume that toupper_l() will not be so broken as to need + * an islower_l() guard test. When using the default collation, we + * apply the traditional Postgres behavior that forces ASCII-style + * treatment of I/i, but in non-default collations you get exactly + * what the collation says. + */ + for (p = dest; *p; p++) + { + if (locale->is_default) + *p = pg_toupper((unsigned char) *p); + else + *p = toupper_l((unsigned char) *p, loc); + } + } + + return srclen; +} + +static size_t +strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + locale_t loc = locale->info.lt; + size_t result_size; + wchar_t *workspace; + char *result; + size_t curr_char; + size_t max_size; + + if (srclen < 0) + srclen = strlen(src); + + /* Overflow paranoia */ + if ((srclen + 1) > (INT_MAX / sizeof(wchar_t))) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + /* Output workspace cannot have more codes than input bytes */ + workspace = (wchar_t *) palloc((srclen + 1) * sizeof(wchar_t)); + + char2wchar(workspace, srclen + 1, src, srclen, locale); + + for (curr_char = 0; workspace[curr_char] != 0; curr_char++) + workspace[curr_char] = towupper_l(workspace[curr_char], loc); + + /* + * Make result large enough; case change might change number of bytes + */ + max_size = curr_char * pg_database_encoding_max_length(); + result = palloc(max_size + 1); + + result_size = wchar2char(result, workspace, max_size + 1, locale); + + if (result_size + 1 > destsize) + return result_size; + + memcpy(dest, result, result_size); + dest[result_size] = '\0'; + + pfree(workspace); + pfree(result); + + return result_size; +} + +pg_locale_t +create_pg_locale_libc(Oid collid, MemoryContext context) +{ + const char *collate; + const char *ctype; + locale_t loc; + pg_locale_t result; + + if (collid == DEFAULT_COLLATION_OID) + { + HeapTuple tp; + Datum datum; + + tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + datum = SysCacheGetAttrNotNull(DATABASEOID, tp, + Anum_pg_database_datcollate); + collate = TextDatumGetCString(datum); + datum = SysCacheGetAttrNotNull(DATABASEOID, tp, + Anum_pg_database_datctype); + ctype = TextDatumGetCString(datum); + + ReleaseSysCache(tp); + } + else + { + HeapTuple tp; + Datum datum; + + tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for collation %u", collid); + + datum = SysCacheGetAttrNotNull(COLLOID, tp, + Anum_pg_collation_collcollate); + collate = TextDatumGetCString(datum); + datum = SysCacheGetAttrNotNull(COLLOID, tp, + Anum_pg_collation_collctype); + ctype = TextDatumGetCString(datum); + + ReleaseSysCache(tp); + } + + + loc = make_libc_collator(collate, ctype); + + result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct)); + result->provider = COLLPROVIDER_LIBC; + result->deterministic = true; + result->collate_is_c = (strcmp(collate, "C") == 0) || + (strcmp(collate, "POSIX") == 0); + result->ctype_is_c = (strcmp(ctype, "C") == 0) || + (strcmp(ctype, "POSIX") == 0); + result->info.lt = loc; + if (!result->collate_is_c) + { +#ifdef WIN32 + if (GetDatabaseEncoding() == PG_UTF8) + result->collate = &collate_methods_libc_win32_utf8; + else +#endif + result->collate = &collate_methods_libc; + } + + return result; +} + +/* + * Create a locale_t with the given collation and ctype. + * + * The "C" and "POSIX" locales are not actually handled by libc, so return + * NULL. + * + * Ensure that no path leaks a locale_t. + */ +static locale_t +make_libc_collator(const char *collate, const char *ctype) +{ + locale_t loc = 0; + + if (strcmp(collate, ctype) == 0) + { + if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0) + { + /* Normal case where they're the same */ + errno = 0; +#ifndef WIN32 + loc = newlocale(LC_COLLATE_MASK | LC_CTYPE_MASK, collate, + NULL); +#else + loc = _create_locale(LC_ALL, collate); +#endif + if (!loc) + report_newlocale_failure(collate); + } + } + else + { +#ifndef WIN32 + /* We need two newlocale() steps */ + locale_t loc1 = 0; + + if (strcmp(collate, "C") != 0 && strcmp(collate, "POSIX") != 0) + { + errno = 0; + loc1 = newlocale(LC_COLLATE_MASK, collate, NULL); + if (!loc1) + report_newlocale_failure(collate); + } + + if (strcmp(ctype, "C") != 0 && strcmp(ctype, "POSIX") != 0) + { + errno = 0; + loc = newlocale(LC_CTYPE_MASK, ctype, loc1); + if (!loc) + { + if (loc1) + freelocale(loc1); + report_newlocale_failure(ctype); + } + } + else + loc = loc1; +#else + + /* + * XXX The _create_locale() API doesn't appear to support this. Could + * perhaps be worked around by changing pg_locale_t to contain two + * separate fields. + */ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("collations with different collate and ctype values are not supported on this platform"))); +#endif + } + + return loc; +} + +/* + * strncoll_libc + * + * NUL-terminate arguments, if necessary, and pass to strcoll_l(). + * + * An input string length of -1 means that it's already NUL-terminated. + */ +int +strncoll_libc(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, + pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + size_t bufsize1 = (len1 == -1) ? 0 : len1 + 1; + size_t bufsize2 = (len2 == -1) ? 0 : len2 + 1; + const char *arg1n; + const char *arg2n; + int result; + + Assert(locale->provider == COLLPROVIDER_LIBC); + + if (bufsize1 + bufsize2 > TEXTBUFLEN) + buf = palloc(bufsize1 + bufsize2); + + /* nul-terminate arguments if necessary */ + if (len1 == -1) + { + arg1n = arg1; + } + else + { + char *buf1 = buf; + + memcpy(buf1, arg1, len1); + buf1[len1] = '\0'; + arg1n = buf1; + } + + if (len2 == -1) + { + arg2n = arg2; + } + else + { + char *buf2 = buf + bufsize1; + + memcpy(buf2, arg2, len2); + buf2[len2] = '\0'; + arg2n = buf2; + } + + result = strcoll_l(arg1n, arg2n, locale->info.lt); + + if (buf != sbuf) + pfree(buf); + + return result; +} + +/* + * strnxfrm_libc + * + * NUL-terminate src, if necessary, and pass to strxfrm_l(). + * + * A source length of -1 means that it's already NUL-terminated. + */ +size_t +strnxfrm_libc(char *dest, size_t destsize, const char *src, ssize_t srclen, + pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + size_t bufsize = srclen + 1; + size_t result; + + Assert(locale->provider == COLLPROVIDER_LIBC); + + if (srclen == -1) + return strxfrm_l(dest, src, destsize, locale->info.lt); + + if (bufsize > TEXTBUFLEN) + buf = palloc(bufsize); + + /* nul-terminate argument */ + memcpy(buf, src, srclen); + buf[srclen] = '\0'; + + result = strxfrm_l(dest, buf, destsize, locale->info.lt); + + if (buf != sbuf) + pfree(buf); + + /* if dest is defined, it should be nul-terminated */ + Assert(result >= destsize || dest[result] == '\0'); + + return result; +} + +char * +get_collation_actual_version_libc(const char *collcollate) +{ + char *collversion = NULL; + + if (pg_strcasecmp("C", collcollate) != 0 && + pg_strncasecmp("C.", collcollate, 2) != 0 && + pg_strcasecmp("POSIX", collcollate) != 0) + { +#if defined(__GLIBC__) + /* Use the glibc version because we don't have anything better. */ + collversion = pstrdup(gnu_get_libc_version()); +#elif defined(LC_VERSION_MASK) + locale_t loc; + + /* Look up FreeBSD collation version. */ + loc = newlocale(LC_COLLATE_MASK, collcollate, NULL); + if (loc) + { + collversion = + pstrdup(querylocale(LC_COLLATE_MASK | LC_VERSION_MASK, loc)); + freelocale(loc); + } + else + ereport(ERROR, + (errmsg("could not load locale \"%s\"", collcollate))); +#elif defined(WIN32) + /* + * If we are targeting Windows Vista and above, we can ask for a name + * given a collation name (earlier versions required a location code + * that we don't have). + */ + NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)}; + WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH]; + + MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate, + LOCALE_NAME_MAX_LENGTH); + if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version)) + { + /* + * GetNLSVersionEx() wants a language tag such as "en-US", not a + * locale name like "English_United States.1252". Until those + * values can be prevented from entering the system, or 100% + * reliably converted to the more useful tag format, tolerate the + * resulting error and report that we have no version data. + */ + if (GetLastError() == ERROR_INVALID_PARAMETER) + return NULL; + + ereport(ERROR, + (errmsg("could not get collation version for locale \"%s\": error code %lu", + collcollate, + GetLastError()))); + } + collversion = psprintf("%lu.%lu,%lu.%lu", + (version.dwNLSVersion >> 8) & 0xFFFF, + version.dwNLSVersion & 0xFF, + (version.dwDefinedVersion >> 8) & 0xFFFF, + version.dwDefinedVersion & 0xFF); +#endif + } + + return collversion; +} + +/* + * strncoll_libc_win32_utf8 + * + * Win32 does not have UTF-8. Convert UTF8 arguments to wide characters and + * invoke wcscoll_l(). + * + * An input string length of -1 means that it's NUL-terminated. + */ +#ifdef WIN32 +static int +strncoll_libc_win32_utf8(const char *arg1, ssize_t len1, const char *arg2, + ssize_t len2, pg_locale_t locale) +{ + char sbuf[TEXTBUFLEN]; + char *buf = sbuf; + char *a1p, + *a2p; + int a1len; + int a2len; + int r; + int result; + + Assert(locale->provider == COLLPROVIDER_LIBC); + Assert(GetDatabaseEncoding() == PG_UTF8); + + if (len1 == -1) + len1 = strlen(arg1); + if (len2 == -1) + len2 = strlen(arg2); + + a1len = len1 * 2 + 2; + a2len = len2 * 2 + 2; + + if (a1len + a2len > TEXTBUFLEN) + buf = palloc(a1len + a2len); + + a1p = buf; + a2p = buf + a1len; + + /* API does not work for zero-length input */ + if (len1 == 0) + r = 0; + else + { + r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1, + (LPWSTR) a1p, a1len / 2); + if (!r) + ereport(ERROR, + (errmsg("could not convert string to UTF-16: error code %lu", + GetLastError()))); + } + ((LPWSTR) a1p)[r] = 0; + + if (len2 == 0) + r = 0; + else + { + r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2, + (LPWSTR) a2p, a2len / 2); + if (!r) + ereport(ERROR, + (errmsg("could not convert string to UTF-16: error code %lu", + GetLastError()))); + } + ((LPWSTR) a2p)[r] = 0; + + errno = 0; + result = wcscoll_l((LPWSTR) a1p, (LPWSTR) a2p, locale->info.lt); + if (result == 2147483647) /* _NLSCMPERROR; missing from mingw headers */ + ereport(ERROR, + (errmsg("could not compare Unicode strings: %m"))); + + if (buf != sbuf) + pfree(buf); + + return result; +} +#endif /* WIN32 */ + +/* simple subroutine for reporting errors from newlocale() */ +void +report_newlocale_failure(const char *localename) +{ + int save_errno; + + /* + * Windows doesn't provide any useful error indication from + * _create_locale(), and BSD-derived platforms don't seem to feel they + * need to set errno either (even though POSIX is pretty clear that + * newlocale should do so). So, if errno hasn't been set, assume ENOENT + * is what to report. + */ + if (errno == 0) + errno = ENOENT; + + /* + * ENOENT means "no such locale", not "no such file", so clarify that + * errno with an errdetail message. + */ + save_errno = errno; /* auxiliary funcs might change errno */ + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not create locale \"%s\": %m", + localename), + (save_errno == ENOENT ? + errdetail("The operating system could not find any locale data for the locale name \"%s\".", + localename) : 0))); +} + +/* + * POSIX doesn't define _l-variants of these functions, but several systems + * have them. We provide our own replacements here. + */ +#ifndef HAVE_MBSTOWCS_L +static size_t +mbstowcs_l(wchar_t *dest, const char *src, size_t n, locale_t loc) +{ +#ifdef WIN32 + return _mbstowcs_l(dest, src, n, loc); +#else + size_t result; + locale_t save_locale = uselocale(loc); + + result = mbstowcs(dest, src, n); + uselocale(save_locale); + return result; +#endif +} +#endif +#ifndef HAVE_WCSTOMBS_L +static size_t +wcstombs_l(char *dest, const wchar_t *src, size_t n, locale_t loc) +{ +#ifdef WIN32 + return _wcstombs_l(dest, src, n, loc); +#else + size_t result; + locale_t save_locale = uselocale(loc); + + result = wcstombs(dest, src, n); + uselocale(save_locale); + return result; +#endif +} +#endif + +/* + * These functions convert from/to libc's wchar_t, *not* pg_wchar_t. + * Therefore we keep them here rather than with the mbutils code. + */ + +/* + * wchar2char --- convert wide characters to multibyte format + * + * This has the same API as the standard wcstombs_l() function; in particular, + * tolen is the maximum number of bytes to store at *to, and *from must be + * zero-terminated. The output will be zero-terminated iff there is room. + */ +size_t +wchar2char(char *to, const wchar_t *from, size_t tolen, pg_locale_t locale) +{ + size_t result; + + if (tolen == 0) + return 0; + +#ifdef WIN32 + + /* + * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding, and + * for some reason mbstowcs and wcstombs won't do this for us, so we use + * MultiByteToWideChar(). + */ + if (GetDatabaseEncoding() == PG_UTF8) + { + result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen, + NULL, NULL); + /* A zero return is failure */ + if (result <= 0) + result = -1; + else + { + Assert(result <= tolen); + /* Microsoft counts the zero terminator in the result */ + result--; + } + } + else +#endif /* WIN32 */ + if (locale == (pg_locale_t) 0) + { + /* Use wcstombs directly for the default locale */ + result = wcstombs(to, from, tolen); + } + else + { + /* Use wcstombs_l for nondefault locales */ + result = wcstombs_l(to, from, tolen, locale->info.lt); + } + + return result; +} + +/* + * char2wchar --- convert multibyte characters to wide characters + * + * This has almost the API of mbstowcs_l(), except that *from need not be + * null-terminated; instead, the number of input bytes is specified as + * fromlen. Also, we ereport() rather than returning -1 for invalid + * input encoding. tolen is the maximum number of wchar_t's to store at *to. + * The output will be zero-terminated iff there is room. + */ +size_t +char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen, + pg_locale_t locale) +{ + size_t result; + + if (tolen == 0) + return 0; + +#ifdef WIN32 + /* See WIN32 "Unicode" comment above */ + if (GetDatabaseEncoding() == PG_UTF8) + { + /* Win32 API does not work for zero-length input */ + if (fromlen == 0) + result = 0; + else + { + result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1); + /* A zero return is failure */ + if (result == 0) + result = -1; + } + + if (result != -1) + { + Assert(result < tolen); + /* Append trailing null wchar (MultiByteToWideChar() does not) */ + to[result] = 0; + } + } + else +#endif /* WIN32 */ + { + /* mbstowcs requires ending '\0' */ + char *str = pnstrdup(from, fromlen); + + if (locale == (pg_locale_t) 0) + { + /* Use mbstowcs directly for the default locale */ + result = mbstowcs(to, str, tolen); + } + else + { + /* Use mbstowcs_l for nondefault locales */ + result = mbstowcs_l(to, str, tolen, locale->info.lt); + } + + pfree(str); + } + + if (result == -1) + { + /* + * Invalid multibyte character encountered. We try to give a useful + * error message by letting pg_verifymbstr check the string. But it's + * possible that the string is OK to us, and not OK to mbstowcs --- + * this suggests that the LC_CTYPE locale is different from the + * database encoding. Give a generic error message if pg_verifymbstr + * can't find anything wrong. + */ + pg_verifymbstr(from, fromlen, false); /* might not return */ + /* but if it does ... */ + ereport(ERROR, + (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), + errmsg("invalid multibyte character for locale"), + errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding."))); + } + + return result; +} diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c index e8b68ef156a32..16311590a14a0 100644 --- a/src/backend/utils/adt/pg_lsn.c +++ b/src/backend/utils/adt/pg_lsn.c @@ -3,7 +3,7 @@ * pg_lsn.c * Operations for the pg_lsn datatype. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c index c54b08fe180ba..d44f8c262baa2 100644 --- a/src/backend/utils/adt/pg_upgrade_support.c +++ b/src/backend/utils/adt/pg_upgrade_support.c @@ -5,7 +5,7 @@ * to control oid and relfilenumber assignment, and do other special * hacks needed for pg_upgrade. * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/backend/utils/adt/pg_upgrade_support.c */ @@ -28,7 +28,6 @@ #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/pg_lsn.h" -#include "utils/syscache.h" #define CHECK_IS_BINARY_UPGRADE \ @@ -299,7 +298,7 @@ binary_upgrade_logical_slot_has_caught_up(PG_FUNCTION_ARGS) slot_name = PG_GETARG_NAME(0); /* Acquire the given slot */ - ReplicationSlotAcquire(NameStr(*slot_name), true); + ReplicationSlotAcquire(NameStr(*slot_name), true, true); Assert(SlotIsLogical(MyReplicationSlot)); diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 3876339ee1b4b..1c12ddbae493c 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -3,7 +3,7 @@ * pgstatfuncs.c * Functions for accessing various forms of statistics data * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -106,6 +106,34 @@ PG_STAT_GET_RELENTRY_INT64(tuples_updated) /* pg_stat_get_vacuum_count */ PG_STAT_GET_RELENTRY_INT64(vacuum_count) +#define PG_STAT_GET_RELENTRY_FLOAT8(stat) \ +Datum \ +CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS) \ +{ \ + Oid relid = PG_GETARG_OID(0); \ + double result; \ + PgStat_StatTabEntry *tabentry; \ + \ + if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \ + result = 0; \ + else \ + result = (double) (tabentry->stat); \ + \ + PG_RETURN_FLOAT8(result); \ +} + +/* pg_stat_get_total_vacuum_time */ +PG_STAT_GET_RELENTRY_FLOAT8(total_vacuum_time) + +/* pg_stat_get_total_autovacuum_time */ +PG_STAT_GET_RELENTRY_FLOAT8(total_autovacuum_time) + +/* pg_stat_get_total_analyze_time */ +PG_STAT_GET_RELENTRY_FLOAT8(total_analyze_time) + +/* pg_stat_get_total_autoanalyze_time */ +PG_STAT_GET_RELENTRY_FLOAT8(total_autoanalyze_time) + #define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat) \ Datum \ CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS) \ @@ -361,11 +389,13 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) /* Values only available to role member or pg_read_all_stats */ if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid)) { - SockAddr zero_clientaddr; char *clipped_activity; switch (beentry->st_state) { + case STATE_STARTING: + values[4] = CStringGetTextDatum("starting"); + break; case STATE_IDLE: values[4] = CStringGetTextDatum("idle"); break; @@ -483,9 +513,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) nulls[11] = true; /* A zeroed client addr means we don't know */ - memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); - if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, - sizeof(zero_clientaddr)) == 0) + if (pg_memory_is_all_zeros(&beentry->st_clientaddr, + sizeof(beentry->st_clientaddr))) { nulls[12] = true; nulls[13] = true; @@ -611,10 +640,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) values[28] = BoolGetDatum(false); /* GSS credentials not * delegated */ } - if (beentry->st_query_id == 0) + if (beentry->st_query_id == INT64CONST(0)) nulls[30] = true; else - values[30] = UInt64GetDatum(beentry->st_query_id); + values[30] = Int64GetDatum(beentry->st_query_id); } else { @@ -880,7 +909,6 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS) { int32 procNumber = PG_GETARG_INT32(0); PgBackendStatus *beentry; - SockAddr zero_clientaddr; char remote_host[NI_MAXHOST]; int ret; @@ -891,9 +919,8 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS) PG_RETURN_NULL(); /* A zeroed client addr means we don't know */ - memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); - if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, - sizeof(zero_clientaddr)) == 0) + if (pg_memory_is_all_zeros(&beentry->st_clientaddr, + sizeof(beentry->st_clientaddr))) PG_RETURN_NULL(); switch (beentry->st_clientaddr.addr.ss_family) @@ -925,7 +952,6 @@ pg_stat_get_backend_client_port(PG_FUNCTION_ARGS) { int32 procNumber = PG_GETARG_INT32(0); PgBackendStatus *beentry; - SockAddr zero_clientaddr; char remote_port[NI_MAXSERV]; int ret; @@ -936,9 +962,8 @@ pg_stat_get_backend_client_port(PG_FUNCTION_ARGS) PG_RETURN_NULL(); /* A zeroed client addr means we don't know */ - memset(&zero_clientaddr, 0, sizeof(zero_clientaddr)); - if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr, - sizeof(zero_clientaddr)) == 0) + if (pg_memory_is_all_zeros(&beentry->st_clientaddr, + sizeof(beentry->st_clientaddr))) PG_RETURN_NULL(); switch (beentry->st_clientaddr.addr.ss_family) @@ -1039,6 +1064,12 @@ PG_STAT_GET_DBENTRY_INT64(sessions_fatal) /* pg_stat_get_db_sessions_killed */ PG_STAT_GET_DBENTRY_INT64(sessions_killed) +/* pg_stat_get_db_parallel_workers_to_launch */ +PG_STAT_GET_DBENTRY_INT64(parallel_workers_to_launch) + +/* pg_stat_get_db_parallel_workers_launched */ +PG_STAT_GET_DBENTRY_INT64(parallel_workers_launched) + /* pg_stat_get_db_temp_bytes */ PG_STAT_GET_DBENTRY_INT64(temp_bytes) @@ -1191,6 +1222,12 @@ pg_stat_get_checkpointer_num_requested(PG_FUNCTION_ARGS) PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->num_requested); } +Datum +pg_stat_get_checkpointer_num_performed(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->num_performed); +} + Datum pg_stat_get_checkpointer_restartpoints_timed(PG_FUNCTION_ARGS) { @@ -1215,6 +1252,12 @@ pg_stat_get_checkpointer_buffers_written(PG_FUNCTION_ARGS) PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buffers_written); } +Datum +pg_stat_get_checkpointer_slru_written(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->slru_written); +} + Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS) { @@ -1262,8 +1305,9 @@ pg_stat_get_buf_alloc(PG_FUNCTION_ARGS) } /* -* When adding a new column to the pg_stat_io view, add a new enum value -* here above IO_NUM_COLUMNS. +* When adding a new column to the pg_stat_io view and the +* pg_stat_get_backend_io() function, add a new enum value here above +* IO_NUM_COLUMNS. */ typedef enum io_stat_col { @@ -1272,14 +1316,16 @@ typedef enum io_stat_col IO_COL_OBJECT, IO_COL_CONTEXT, IO_COL_READS, + IO_COL_READ_BYTES, IO_COL_READ_TIME, IO_COL_WRITES, + IO_COL_WRITE_BYTES, IO_COL_WRITE_TIME, IO_COL_WRITEBACKS, IO_COL_WRITEBACK_TIME, IO_COL_EXTENDS, + IO_COL_EXTEND_BYTES, IO_COL_EXTEND_TIME, - IO_COL_CONVERSION, IO_COL_HITS, IO_COL_EVICTIONS, IO_COL_REUSES, @@ -1320,11 +1366,36 @@ pgstat_get_io_op_index(IOOp io_op) pg_unreachable(); } +/* + * Get the number of the column containing IO bytes for the specified IOOp. + * If an IOOp is not tracked in bytes, IO_COL_INVALID is returned. + */ +static io_stat_col +pgstat_get_io_byte_index(IOOp io_op) +{ + switch (io_op) + { + case IOOP_EXTEND: + return IO_COL_EXTEND_BYTES; + case IOOP_READ: + return IO_COL_READ_BYTES; + case IOOP_WRITE: + return IO_COL_WRITE_BYTES; + case IOOP_EVICT: + case IOOP_FSYNC: + case IOOP_HIT: + case IOOP_REUSE: + case IOOP_WRITEBACK: + return IO_COL_INVALID; + } + + elog(ERROR, "unrecognized IOOp value: %d", io_op); + pg_unreachable(); +} + /* * Get the number of the column containing IO times for the specified IOOp. - * This function encodes our assumption that IO time for an IOOp is displayed - * in the view in the column directly after the IOOp counts. If an op has no - * associated time, IO_COL_INVALID is returned. + * If an op has no associated time, IO_COL_INVALID is returned. */ static io_stat_col pgstat_get_io_time_index(IOOp io_op) @@ -1332,11 +1403,15 @@ pgstat_get_io_time_index(IOOp io_op) switch (io_op) { case IOOP_READ: + return IO_COL_READ_TIME; case IOOP_WRITE: + return IO_COL_WRITE_TIME; case IOOP_WRITEBACK: + return IO_COL_WRITEBACK_TIME; case IOOP_EXTEND: + return IO_COL_EXTEND_TIME; case IOOP_FSYNC: - return pgstat_get_io_op_index(io_op) + 1; + return IO_COL_FSYNC_TIME; case IOOP_EVICT: case IOOP_HIT: case IOOP_REUSE: @@ -1353,29 +1428,130 @@ pg_stat_us_to_ms(PgStat_Counter val_ms) return val_ms * (double) 0.001; } +/* + * pg_stat_io_build_tuples + * + * Helper routine for pg_stat_get_io() and pg_stat_get_backend_io() + * filling a result tuplestore with one tuple for each object and each + * context supported by the caller, based on the contents of bktype_stats. + */ +static void +pg_stat_io_build_tuples(ReturnSetInfo *rsinfo, + PgStat_BktypeIO *bktype_stats, + BackendType bktype, + TimestampTz stat_reset_timestamp) +{ + Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype)); + + for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++) + { + const char *obj_name = pgstat_get_io_object_name(io_obj); + + for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++) + { + const char *context_name = pgstat_get_io_context_name(io_context); + + Datum values[IO_NUM_COLUMNS] = {0}; + bool nulls[IO_NUM_COLUMNS] = {0}; + + /* + * Some combinations of BackendType, IOObject, and IOContext are + * not valid for any type of IOOp. In such cases, omit the entire + * row from the view. + */ + if (!pgstat_tracks_io_object(bktype, io_obj, io_context)) + continue; + + values[IO_COL_BACKEND_TYPE] = bktype_desc; + values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name); + values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name); + if (stat_reset_timestamp != 0) + values[IO_COL_RESET_TIME] = TimestampTzGetDatum(stat_reset_timestamp); + else + nulls[IO_COL_RESET_TIME] = true; + + for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++) + { + int op_idx = pgstat_get_io_op_index(io_op); + int time_idx = pgstat_get_io_time_index(io_op); + int byte_idx = pgstat_get_io_byte_index(io_op); + + /* + * Some combinations of BackendType and IOOp, of IOContext and + * IOOp, and of IOObject and IOOp are not tracked. Set these + * cells in the view NULL. + */ + if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op)) + { + PgStat_Counter count = + bktype_stats->counts[io_obj][io_context][io_op]; + + values[op_idx] = Int64GetDatum(count); + } + else + nulls[op_idx] = true; + + if (!nulls[op_idx]) + { + /* not every operation is timed */ + if (time_idx != IO_COL_INVALID) + { + PgStat_Counter time = + bktype_stats->times[io_obj][io_context][io_op]; + + values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time)); + } + + /* not every IO is tracked in bytes */ + if (byte_idx != IO_COL_INVALID) + { + char buf[256]; + PgStat_Counter byte = + bktype_stats->bytes[io_obj][io_context][io_op]; + + /* Convert to numeric */ + snprintf(buf, sizeof buf, INT64_FORMAT, byte); + values[byte_idx] = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + } + } + else + { + if (time_idx != IO_COL_INVALID) + nulls[time_idx] = true; + if (byte_idx != IO_COL_INVALID) + nulls[byte_idx] = true; + } + } + + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, + values, nulls); + } + } +} + Datum pg_stat_get_io(PG_FUNCTION_ARGS) { ReturnSetInfo *rsinfo; PgStat_IO *backends_io_stats; - Datum reset_time; InitMaterializedSRF(fcinfo, 0); rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; backends_io_stats = pgstat_fetch_stat_io(); - reset_time = TimestampTzGetDatum(backends_io_stats->stat_reset_timestamp); - for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++) { - Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype)); PgStat_BktypeIO *bktype_stats = &backends_io_stats->stats[bktype]; /* * In Assert builds, we can afford an extra loop through all of the - * counters checking that only expected stats are non-zero, since it - * keeps the non-Assert code cleaner. + * counters (in pg_stat_io_build_tuples()), checking that only + * expected stats are non-zero, since it keeps the non-Assert code + * cleaner. */ Assert(pgstat_bktype_io_stats_valid(bktype_stats, bktype)); @@ -1386,97 +1562,68 @@ pg_stat_get_io(PG_FUNCTION_ARGS) if (!pgstat_tracks_io_bktype(bktype)) continue; - for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++) - { - const char *obj_name = pgstat_get_io_object_name(io_obj); - - for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++) - { - const char *context_name = pgstat_get_io_context_name(io_context); - - Datum values[IO_NUM_COLUMNS] = {0}; - bool nulls[IO_NUM_COLUMNS] = {0}; - - /* - * Some combinations of BackendType, IOObject, and IOContext - * are not valid for any type of IOOp. In such cases, omit the - * entire row from the view. - */ - if (!pgstat_tracks_io_object(bktype, io_obj, io_context)) - continue; - - values[IO_COL_BACKEND_TYPE] = bktype_desc; - values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name); - values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name); - values[IO_COL_RESET_TIME] = TimestampTzGetDatum(reset_time); + /* save tuples with data from this PgStat_BktypeIO */ + pg_stat_io_build_tuples(rsinfo, bktype_stats, bktype, + backends_io_stats->stat_reset_timestamp); + } - /* - * Hard-code this to the value of BLCKSZ for now. Future - * values could include XLOG_BLCKSZ, once WAL IO is tracked, - * and constant multipliers, once non-block-oriented IO (e.g. - * temporary file IO) is tracked. - */ - values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ); + return (Datum) 0; +} - for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++) - { - int op_idx = pgstat_get_io_op_index(io_op); - int time_idx = pgstat_get_io_time_index(io_op); +/* + * Returns I/O statistics for a backend with given PID. + */ +Datum +pg_stat_get_backend_io(PG_FUNCTION_ARGS) +{ + ReturnSetInfo *rsinfo; + BackendType bktype; + int pid; + PgStat_Backend *backend_stats; + PgStat_BktypeIO *bktype_stats; - /* - * Some combinations of BackendType and IOOp, of IOContext - * and IOOp, and of IOObject and IOOp are not tracked. Set - * these cells in the view NULL. - */ - if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op)) - { - PgStat_Counter count = - bktype_stats->counts[io_obj][io_context][io_op]; + InitMaterializedSRF(fcinfo, 0); + rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; - values[op_idx] = Int64GetDatum(count); - } - else - nulls[op_idx] = true; + pid = PG_GETARG_INT32(0); + backend_stats = pgstat_fetch_stat_backend_by_pid(pid, &bktype); - /* not every operation is timed */ - if (time_idx == IO_COL_INVALID) - continue; + if (!backend_stats) + return (Datum) 0; - if (!nulls[op_idx]) - { - PgStat_Counter time = - bktype_stats->times[io_obj][io_context][io_op]; + bktype_stats = &backend_stats->io_stats; - values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time)); - } - else - nulls[time_idx] = true; - } - - tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, - values, nulls); - } - } - } + /* + * In Assert builds, we can afford an extra loop through all of the + * counters (in pg_stat_io_build_tuples()), checking that only expected + * stats are non-zero, since it keeps the non-Assert code cleaner. + */ + Assert(pgstat_bktype_io_stats_valid(bktype_stats, bktype)); + /* save tuples with data from this PgStat_BktypeIO */ + pg_stat_io_build_tuples(rsinfo, bktype_stats, bktype, + backend_stats->stat_reset_timestamp); return (Datum) 0; } /* - * Returns statistics of WAL activity + * pg_stat_wal_build_tuple + * + * Helper routine for pg_stat_get_wal() and pg_stat_get_backend_wal() + * returning one tuple based on the contents of wal_counters. */ -Datum -pg_stat_get_wal(PG_FUNCTION_ARGS) +static Datum +pg_stat_wal_build_tuple(PgStat_WalCounters wal_counters, + TimestampTz stat_reset_timestamp) { -#define PG_STAT_GET_WAL_COLS 9 +#define PG_STAT_WAL_COLS 5 TupleDesc tupdesc; - Datum values[PG_STAT_GET_WAL_COLS] = {0}; - bool nulls[PG_STAT_GET_WAL_COLS] = {0}; + Datum values[PG_STAT_WAL_COLS] = {0}; + bool nulls[PG_STAT_WAL_COLS] = {0}; char buf[256]; - PgStat_WalStats *wal_stats; /* Initialise attributes information in the tuple descriptor */ - tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_WAL_COLS); + tupdesc = CreateTemplateTupleDesc(PG_STAT_WAL_COLS); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "wal_records", INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "wal_fpi", @@ -1485,47 +1632,70 @@ pg_stat_get_wal(PG_FUNCTION_ARGS) NUMERICOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_buffers_full", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "wal_write", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "wal_sync", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "wal_write_time", - FLOAT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "wal_sync_time", - FLOAT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "stats_reset", + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "stats_reset", TIMESTAMPTZOID, -1, 0); BlessTupleDesc(tupdesc); - /* Get statistics about WAL activity */ - wal_stats = pgstat_fetch_stat_wal(); - /* Fill values and NULLs */ - values[0] = Int64GetDatum(wal_stats->wal_records); - values[1] = Int64GetDatum(wal_stats->wal_fpi); + values[0] = Int64GetDatum(wal_counters.wal_records); + values[1] = Int64GetDatum(wal_counters.wal_fpi); /* Convert to numeric. */ - snprintf(buf, sizeof buf, UINT64_FORMAT, wal_stats->wal_bytes); + snprintf(buf, sizeof buf, UINT64_FORMAT, wal_counters.wal_bytes); values[2] = DirectFunctionCall3(numeric_in, CStringGetDatum(buf), ObjectIdGetDatum(0), Int32GetDatum(-1)); - values[3] = Int64GetDatum(wal_stats->wal_buffers_full); - values[4] = Int64GetDatum(wal_stats->wal_write); - values[5] = Int64GetDatum(wal_stats->wal_sync); + values[3] = Int64GetDatum(wal_counters.wal_buffers_full); - /* Convert counters from microsec to millisec for display */ - values[6] = Float8GetDatum(((double) wal_stats->wal_write_time) / 1000.0); - values[7] = Float8GetDatum(((double) wal_stats->wal_sync_time) / 1000.0); - - values[8] = TimestampTzGetDatum(wal_stats->stat_reset_timestamp); + if (stat_reset_timestamp != 0) + values[4] = TimestampTzGetDatum(stat_reset_timestamp); + else + nulls[4] = true; /* Returns the record as Datum */ PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); } +/* + * Returns WAL statistics for a backend with given PID. + */ +Datum +pg_stat_get_backend_wal(PG_FUNCTION_ARGS) +{ + int pid; + PgStat_Backend *backend_stats; + PgStat_WalCounters bktype_stats; + + pid = PG_GETARG_INT32(0); + backend_stats = pgstat_fetch_stat_backend_by_pid(pid, NULL); + + if (!backend_stats) + PG_RETURN_NULL(); + + bktype_stats = backend_stats->wal_counters; + + /* save tuples with data from this PgStat_WalCounters */ + return (pg_stat_wal_build_tuple(bktype_stats, backend_stats->stat_reset_timestamp)); +} + +/* + * Returns statistics of WAL activity + */ +Datum +pg_stat_get_wal(PG_FUNCTION_ARGS) +{ + PgStat_WalStats *wal_stats; + + /* Get statistics about WAL activity */ + wal_stats = pgstat_fetch_stat_wal(); + + return (pg_stat_wal_build_tuple(wal_stats->wal_counters, + wal_stats->stat_reset_timestamp)); +} + /* * Returns statistics of SLRU caches. */ @@ -1696,7 +1866,7 @@ pg_stat_reset(PG_FUNCTION_ARGS) * Reset some shared cluster-wide counters * * When adding a new reset target, ideally the name should match that in - * pgstat_kind_infos, if relevant. + * pgstat_kind_builtin_infos, if relevant. */ Datum pg_stat_reset_shared(PG_FUNCTION_ARGS) @@ -1767,6 +1937,41 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * Reset statistics of backend with given PID. + */ +Datum +pg_stat_reset_backend_stats(PG_FUNCTION_ARGS) +{ + PGPROC *proc; + PgBackendStatus *beentry; + ProcNumber procNumber; + int backend_pid = PG_GETARG_INT32(0); + + proc = BackendPidGetProc(backend_pid); + + /* This could be an auxiliary process */ + if (!proc) + proc = AuxiliaryPidGetProc(backend_pid); + + if (!proc) + PG_RETURN_VOID(); + + procNumber = GetNumberFromPGProc(proc); + + beentry = pgstat_get_beentry_by_proc_number(procNumber); + if (!beentry) + PG_RETURN_VOID(); + + /* Check if the backend type tracks statistics */ + if (!pgstat_tracks_backend_bktype(beentry->st_backendType)) + PG_RETURN_VOID(); + + pgstat_reset(PGSTAT_KIND_BACKEND, InvalidOid, procNumber); + + PG_RETURN_VOID(); +} + /* Reset SLRU counters (a specific one or all of them). */ Datum pg_stat_reset_slru(PG_FUNCTION_ARGS) @@ -1966,13 +2171,14 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS) Datum pg_stat_get_subscription_stats(PG_FUNCTION_ARGS) { -#define PG_STAT_GET_SUBSCRIPTION_STATS_COLS 4 +#define PG_STAT_GET_SUBSCRIPTION_STATS_COLS 11 Oid subid = PG_GETARG_OID(0); TupleDesc tupdesc; Datum values[PG_STAT_GET_SUBSCRIPTION_STATS_COLS] = {0}; bool nulls[PG_STAT_GET_SUBSCRIPTION_STATS_COLS] = {0}; PgStat_StatSubEntry *subentry; PgStat_StatSubEntry allzero; + int i = 0; /* Get subscription stats */ subentry = pgstat_fetch_stat_subscription(subid); @@ -1985,7 +2191,21 @@ pg_stat_get_subscription_stats(PG_FUNCTION_ARGS) INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "sync_error_count", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "stats_reset", + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "confl_insert_exists", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "confl_update_origin_differs", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "confl_update_exists", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "confl_update_missing", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "confl_delete_origin_differs", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "confl_delete_missing", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "confl_multiple_unique_conflicts", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "stats_reset", TIMESTAMPTZOID, -1, 0); BlessTupleDesc(tupdesc); @@ -1997,19 +2217,25 @@ pg_stat_get_subscription_stats(PG_FUNCTION_ARGS) } /* subid */ - values[0] = ObjectIdGetDatum(subid); + values[i++] = ObjectIdGetDatum(subid); /* apply_error_count */ - values[1] = Int64GetDatum(subentry->apply_error_count); + values[i++] = Int64GetDatum(subentry->apply_error_count); /* sync_error_count */ - values[2] = Int64GetDatum(subentry->sync_error_count); + values[i++] = Int64GetDatum(subentry->sync_error_count); + + /* conflict count */ + for (int nconflict = 0; nconflict < CONFLICT_NUM_TYPES; nconflict++) + values[i++] = Int64GetDatum(subentry->conflict_count[nconflict]); /* stats_reset */ if (subentry->stat_reset_timestamp == 0) - nulls[3] = true; + nulls[i] = true; else - values[3] = TimestampTzGetDatum(subentry->stat_reset_timestamp); + values[i] = TimestampTzGetDatum(subentry->stat_reset_timestamp); + + Assert(i + 1 == PG_STAT_GET_SUBSCRIPTION_STATS_COLS); /* Returns the record as Datum */ PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); @@ -2027,8 +2253,8 @@ pg_stat_have_stats(PG_FUNCTION_ARGS) { char *stats_type = text_to_cstring(PG_GETARG_TEXT_P(0)); Oid dboid = PG_GETARG_OID(1); - Oid objoid = PG_GETARG_OID(2); + uint64 objid = PG_GETARG_INT64(2); PgStat_Kind kind = pgstat_get_kind_from_str(stats_type); - PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid)); + PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objid)); } diff --git a/src/backend/utils/adt/pseudorandomfuncs.c b/src/backend/utils/adt/pseudorandomfuncs.c index 8e82c7078c5df..e7b8045f92508 100644 --- a/src/backend/utils/adt/pseudorandomfuncs.c +++ b/src/backend/utils/adt/pseudorandomfuncs.c @@ -3,7 +3,7 @@ * pseudorandomfuncs.c * Functions giving SQL access to a pseudorandom number generator. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index e189e9b79d297..317a1f2b282f9 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -11,7 +11,7 @@ * we do better?) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/quote.c b/src/backend/utils/adt/quote.c index 7cf18b93cd9e9..551de59a07f35 100644 --- a/src/backend/utils/adt/quote.c +++ b/src/backend/utils/adt/quote.c @@ -3,7 +3,7 @@ * quote.c * Functions for quoting identifiers and literals * - * Portions Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2000-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -108,7 +108,12 @@ quote_literal_cstr(const char *rawstr) len = strlen(rawstr); /* We make a worst-case result area; wasting a little space is OK */ - result = palloc(len * 2 + 3 + 1); + result = palloc( + (len * 2) /* doubling for every character if each one is + * a quote */ + + 3 /* two outer quotes + possibly 'E' if needed */ + + 1 /* null terminator */ + ); newlen = quote_literal_internal(result, rawstr, len); result[newlen] = '\0'; diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c index 2d94a6b877456..66cc0acf4a712 100644 --- a/src/backend/utils/adt/rangetypes.c +++ b/src/backend/utils/adt/rangetypes.c @@ -19,7 +19,7 @@ * value; we must detoast it first. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -43,6 +43,7 @@ #include "utils/date.h" #include "utils/lsyscache.h" #include "utils/rangetypes.h" +#include "utils/sortsupport.h" #include "utils/timestamp.h" @@ -57,6 +58,7 @@ typedef struct RangeIOData static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func); +static int range_fast_cmp(Datum a, Datum b, SortSupport ssup); static char range_parse_flags(const char *flags_str); static bool range_parse(const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext); @@ -359,7 +361,7 @@ get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func) fmgr_info_cxt(typiofunc, &cache->typioproc, fcinfo->flinfo->fn_mcxt); - fcinfo->flinfo->fn_extra = (void *) cache; + fcinfo->flinfo->fn_extra = cache; } return cache; @@ -1290,6 +1292,68 @@ range_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(cmp); } +/* Sort support strategy routine */ +Datum +range_sortsupport(PG_FUNCTION_ARGS) +{ + SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0); + + ssup->comparator = range_fast_cmp; + ssup->ssup_extra = NULL; + + PG_RETURN_VOID(); +} + +/* like range_cmp, but uses the new sortsupport interface */ +static int +range_fast_cmp(Datum a, Datum b, SortSupport ssup) +{ + RangeType *range_a = DatumGetRangeTypeP(a); + RangeType *range_b = DatumGetRangeTypeP(b); + TypeCacheEntry *typcache; + RangeBound lower1, + lower2; + RangeBound upper1, + upper2; + bool empty1, + empty2; + int cmp; + + /* cache the range info between calls */ + if (ssup->ssup_extra == NULL) + { + Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b)); + ssup->ssup_extra = + lookup_type_cache(RangeTypeGetOid(range_a), TYPECACHE_RANGE_INFO); + } + typcache = ssup->ssup_extra; + + range_deserialize(typcache, range_a, &lower1, &upper1, &empty1); + range_deserialize(typcache, range_b, &lower2, &upper2, &empty2); + + /* For b-tree use, empty ranges sort before all else */ + if (empty1 && empty2) + cmp = 0; + else if (empty1) + cmp = -1; + else if (empty2) + cmp = 1; + else + { + cmp = range_cmp_bounds(typcache, &lower1, &lower2); + if (cmp == 0) + cmp = range_cmp_bounds(typcache, &upper1, &upper2); + } + + if ((Datum) range_a != a) + pfree(range_a); + if ((Datum) range_b != b) + pfree(range_b); + + return cmp; +} + + /* inequality operators using the range_cmp function */ Datum range_lt(PG_FUNCTION_ARGS) @@ -1710,7 +1774,7 @@ range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid) typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO); if (typcache->rngelemtype == NULL) elog(ERROR, "type %u is not a range type", rngtypid); - fcinfo->flinfo->fn_extra = (void *) typcache; + fcinfo->flinfo->fn_extra = typcache; } return typcache; diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c index cb28e9859abb4..a60ee985e746b 100644 --- a/src/backend/utils/adt/rangetypes_gist.c +++ b/src/backend/utils/adt/rangetypes_gist.c @@ -3,7 +3,7 @@ * rangetypes_gist.c * GiST support for range types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c index 6d35ecd33d0e4..d126abc5a82ee 100644 --- a/src/backend/utils/adt/rangetypes_selfuncs.c +++ b/src/backend/utils/adt/rangetypes_selfuncs.c @@ -6,7 +6,7 @@ * Estimates are based on histograms of lower and upper bounds, and the * fraction of empty ranges. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c index 5121835f6b5da..9b6d7061a1812 100644 --- a/src/backend/utils/adt/rangetypes_spgist.c +++ b/src/backend/utils/adt/rangetypes_spgist.c @@ -25,7 +25,7 @@ * This implementation only uses the comparison function of the range element * datatype, therefore it works for any range type. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c index 3773f98115287..a18196d8a34a5 100644 --- a/src/backend/utils/adt/rangetypes_typanalyze.c +++ b/src/backend/utils/adt/rangetypes_typanalyze.c @@ -13,7 +13,7 @@ * come from different tuples. In theory, the standard scalar selectivity * functions could be used with the combined histogram. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -167,7 +167,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, upper; float8 length; - vacuum_delay_point(); + vacuum_delay_point(true); value = fetchfunc(stats, range_no, &isnull); if (isnull) diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c index 0e2519bfd5772..6e2864cbbda8c 100644 --- a/src/backend/utils/adt/regexp.c +++ b/src/backend/utils/adt/regexp.c @@ -3,7 +3,7 @@ * regexp.c * Postgres' interface to the regular expression package. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -773,8 +773,11 @@ similar_escape_internal(text *pat_text, text *esc_text) int plen, elen; bool afterescape = false; - bool incharclass = false; int nquotes = 0; + int charclass_depth = 0; /* Nesting level of character classes, + * encompassed by square brackets */ + int charclass_start = 0; /* State of the character class start, + * for carets */ p = VARDATA_ANY(pat_text); plen = VARSIZE_ANY_EXHDR(pat_text); @@ -904,7 +907,7 @@ similar_escape_internal(text *pat_text, text *esc_text) /* fast path */ if (afterescape) { - if (pchar == '"' && !incharclass) /* escape-double-quote? */ + if (pchar == '"' && charclass_depth < 1) /* escape-double-quote? */ { /* emit appropriate part separator, per notes above */ if (nquotes == 0) @@ -953,18 +956,41 @@ similar_escape_internal(text *pat_text, text *esc_text) /* SQL escape character; do not send to output */ afterescape = true; } - else if (incharclass) + else if (charclass_depth > 0) { if (pchar == '\\') *r++ = '\\'; *r++ = pchar; - if (pchar == ']') - incharclass = false; + + /* + * Ignore a closing bracket at the start of a character class. + * Such a bracket is taken literally rather than closing the + * class. "charclass_start" is 1 right at the beginning of a + * class and 2 after an initial caret. + */ + if (pchar == ']' && charclass_start > 2) + charclass_depth--; + else if (pchar == '[') + charclass_depth++; + + /* + * If there is a caret right after the opening bracket, it negates + * the character class, but a following closing bracket should + * still be treated as a normal character. That holds only for + * the first caret, so only the values 1 and 2 mean that closing + * brackets should be taken literally. + */ + if (pchar == '^') + charclass_start++; + else + charclass_start = 3; /* definitely past the start */ } else if (pchar == '[') { + /* start of a character class */ *r++ = pchar; - incharclass = true; + charclass_depth++; + charclass_start = 1; } else if (pchar == '%') { @@ -1367,7 +1393,7 @@ regexp_matches(PG_FUNCTION_ARGS) matchctx->nulls = (bool *) palloc(sizeof(bool) * matchctx->npatterns); MemoryContextSwitchTo(oldcontext); - funcctx->user_fctx = (void *) matchctx; + funcctx->user_fctx = matchctx; } funcctx = SRF_PERCALL_SETUP(); @@ -1707,7 +1733,7 @@ regexp_split_to_table(PG_FUNCTION_ARGS) false, true, true); MemoryContextSwitchTo(oldcontext); - funcctx->user_fctx = (void *) splitctx; + funcctx->user_fctx = splitctx; } funcctx = SRF_PERCALL_SETUP(); diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 18d5b7d166c48..5ee608a2b3921 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -8,7 +8,7 @@ * special I/O conversion routines. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 62601a6d80c7b..6239900fa2892 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -14,7 +14,7 @@ * plan --- consider improving this someday. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/backend/utils/adt/ri_triggers.c * @@ -30,6 +30,7 @@ #include "access/xact.h" #include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" +#include "catalog/pg_proc.h" #include "commands/trigger.h" #include "executor/executor.h" #include "executor/spi.h" @@ -45,6 +46,7 @@ #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/rangetypes.h" #include "utils/rel.h" #include "utils/rls.h" #include "utils/ruleutils.h" @@ -72,12 +74,13 @@ /* these queries are executed against the FK (referencing) table: */ #define RI_PLAN_CASCADE_ONDELETE 3 #define RI_PLAN_CASCADE_ONUPDATE 4 +#define RI_PLAN_NO_ACTION 5 /* For RESTRICT, the same plan can be used for both ON DELETE and ON UPDATE triggers. */ -#define RI_PLAN_RESTRICT 5 -#define RI_PLAN_SETNULL_ONDELETE 6 -#define RI_PLAN_SETNULL_ONUPDATE 7 -#define RI_PLAN_SETDEFAULT_ONDELETE 8 -#define RI_PLAN_SETDEFAULT_ONUPDATE 9 +#define RI_PLAN_RESTRICT 6 +#define RI_PLAN_SETNULL_ONDELETE 7 +#define RI_PLAN_SETNULL_ONUPDATE 8 +#define RI_PLAN_SETDEFAULT_ONDELETE 9 +#define RI_PLAN_SETDEFAULT_ONUPDATE 10 #define MAX_QUOTED_NAME_LEN (NAMEDATALEN*2+3) #define MAX_QUOTED_REL_NAME_LEN (MAX_QUOTED_NAME_LEN*2) @@ -96,6 +99,9 @@ * * Information extracted from an FK pg_constraint entry. This is cached in * ri_constraint_cache. + * + * Note that pf/pp/ff_eq_oprs may hold the overlaps operator instead of equals + * for the PERIOD part of a temporal foreign key. */ typedef struct RI_ConstraintInfo { @@ -115,12 +121,16 @@ typedef struct RI_ConstraintInfo int16 confdelsetcols[RI_MAX_NUMKEYS]; /* attnums of cols to set on * delete */ char confmatchtype; /* foreign key's match type */ + bool hasperiod; /* if the foreign key uses PERIOD */ int nkeys; /* number of key columns */ int16 pk_attnums[RI_MAX_NUMKEYS]; /* attnums of referenced cols */ int16 fk_attnums[RI_MAX_NUMKEYS]; /* attnums of referencing cols */ Oid pf_eq_oprs[RI_MAX_NUMKEYS]; /* equality operators (PK = FK) */ Oid pp_eq_oprs[RI_MAX_NUMKEYS]; /* equality operators (PK = PK) */ Oid ff_eq_oprs[RI_MAX_NUMKEYS]; /* equality operators (FK = FK) */ + Oid period_contained_by_oper; /* anyrange <@ anyrange */ + Oid agged_period_contained_by_oper; /* fkattr <@ range_agg(pkattr) */ + Oid period_intersect_oper; /* anyrange * anyrange */ dlist_node valid_link; /* Link in list of valid entries */ } RI_ConstraintInfo; @@ -199,8 +209,8 @@ static void ri_BuildQueryKey(RI_QueryKey *key, int32 constr_queryno); static bool ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, const RI_ConstraintInfo *riinfo, bool rel_is_pk); -static bool ri_AttributesEqual(Oid eq_opr, Oid typeid, - Datum oldvalue, Datum newvalue); +static bool ri_CompareWithCast(Oid eq_opr, Oid typeid, Oid collid, + Datum lhs, Datum rhs); static void ri_InitHashTables(void); static void InvalidateConstraintCacheCallBack(Datum arg, int cacheid, uint32 hashvalue); @@ -220,14 +230,15 @@ static bool ri_PerformCheck(const RI_ConstraintInfo *riinfo, RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, + bool is_restrict, bool detectNewRows, int expect_OK); static void ri_ExtractValues(Relation rel, TupleTableSlot *slot, const RI_ConstraintInfo *riinfo, bool rel_is_pk, Datum *vals, char *nulls); -static void ri_ReportViolation(const RI_ConstraintInfo *riinfo, - Relation pk_rel, Relation fk_rel, - TupleTableSlot *violatorslot, TupleDesc tupdesc, - int queryno, bool partgone) pg_attribute_noreturn(); +pg_noreturn static void ri_ReportViolation(const RI_ConstraintInfo *riinfo, + Relation pk_rel, Relation fk_rel, + TupleTableSlot *violatorslot, TupleDesc tupdesc, + int queryno, bool is_restrict, bool partgone); /* @@ -340,8 +351,7 @@ RI_FKey_check(TriggerData *trigdata) break; } - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* Fetch or prepare a saved plan for the real check */ ri_BuildQueryKey(&qkey, riinfo, RI_PLAN_CHECK_LOOKUPPK); @@ -362,14 +372,41 @@ RI_FKey_check(TriggerData *trigdata) * FOR KEY SHARE OF x * The type id's for the $ parameters are those of the * corresponding FK attributes. + * + * But for temporal FKs we need to make sure + * the FK's range is completely covered. + * So we use this query instead: + * SELECT 1 + * FROM ( + * SELECT pkperiodatt AS r + * FROM [ONLY] pktable x + * WHERE pkatt1 = $1 [AND ...] + * AND pkperiodatt && $n + * FOR KEY SHARE OF x + * ) x1 + * HAVING $n <@ range_agg(x1.r) + * Note if FOR KEY SHARE ever allows GROUP BY and HAVING + * we can make this a bit simpler. * ---------- */ initStringInfo(&querybuf); pk_only = pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY "; quoteRelationName(pkrelname, pk_rel); - appendStringInfo(&querybuf, "SELECT 1 FROM %s%s x", - pk_only, pkrelname); + if (riinfo->hasperiod) + { + quoteOneName(attname, + RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1])); + + appendStringInfo(&querybuf, + "SELECT 1 FROM (SELECT %s AS r FROM %s%s x", + attname, pk_only, pkrelname); + } + else + { + appendStringInfo(&querybuf, "SELECT 1 FROM %s%s x", + pk_only, pkrelname); + } querysep = "WHERE"; for (int i = 0; i < riinfo->nkeys; i++) { @@ -387,6 +424,18 @@ RI_FKey_check(TriggerData *trigdata) queryoids[i] = fk_type; } appendStringInfoString(&querybuf, " FOR KEY SHARE OF x"); + if (riinfo->hasperiod) + { + Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1]); + + appendStringInfoString(&querybuf, ") x1 HAVING "); + sprintf(paramname, "$%d", riinfo->nkeys); + ri_GenerateQual(&querybuf, "", + paramname, fk_type, + riinfo->agged_period_contained_by_oper, + "pg_catalog.range_agg", ANYMULTIRANGEOID); + appendStringInfoString(&querybuf, "(x1.r)"); + } /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo->nkeys, queryoids, @@ -403,6 +452,7 @@ RI_FKey_check(TriggerData *trigdata) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, NULL, newslot, + false, pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE, SPI_OK_SELECT); @@ -469,8 +519,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, /* Only called for non-null rows */ Assert(ri_NullCheck(RelationGetDescr(pk_rel), oldslot, riinfo, true) == RI_KEYS_NONE_NULL); - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * Fetch or prepare a saved plan for checking PK table with values coming @@ -494,14 +543,40 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, * FOR KEY SHARE OF x * The type id's for the $ parameters are those of the * PK attributes themselves. + * + * But for temporal FKs we need to make sure + * the old PK's range is completely covered. + * So we use this query instead: + * SELECT 1 + * FROM ( + * SELECT pkperiodatt AS r + * FROM [ONLY] pktable x + * WHERE pkatt1 = $1 [AND ...] + * AND pkperiodatt && $n + * FOR KEY SHARE OF x + * ) x1 + * HAVING $n <@ range_agg(x1.r) + * Note if FOR KEY SHARE ever allows GROUP BY and HAVING + * we can make this a bit simpler. * ---------- */ initStringInfo(&querybuf); pk_only = pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY "; quoteRelationName(pkrelname, pk_rel); - appendStringInfo(&querybuf, "SELECT 1 FROM %s%s x", - pk_only, pkrelname); + if (riinfo->hasperiod) + { + quoteOneName(attname, RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1])); + + appendStringInfo(&querybuf, + "SELECT 1 FROM (SELECT %s AS r FROM %s%s x", + attname, pk_only, pkrelname); + } + else + { + appendStringInfo(&querybuf, "SELECT 1 FROM %s%s x", + pk_only, pkrelname); + } querysep = "WHERE"; for (int i = 0; i < riinfo->nkeys; i++) { @@ -518,6 +593,18 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, queryoids[i] = pk_type; } appendStringInfoString(&querybuf, " FOR KEY SHARE OF x"); + if (riinfo->hasperiod) + { + Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1]); + + appendStringInfoString(&querybuf, ") x1 HAVING "); + sprintf(paramname, "$%d", riinfo->nkeys); + ri_GenerateQual(&querybuf, "", + paramname, fk_type, + riinfo->agged_period_contained_by_oper, + "pg_catalog.range_agg", ANYMULTIRANGEOID); + appendStringInfoString(&querybuf, "(x1.r)"); + } /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo->nkeys, queryoids, @@ -530,6 +617,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, result = ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + false, true, /* treat like update */ SPI_OK_SELECT); @@ -648,28 +736,32 @@ ri_restrict(TriggerData *trigdata, bool is_no_action) * not do anything. However, this check should only be made in the NO * ACTION case; in RESTRICT cases we don't wish to allow another row to be * substituted. + * + * If the foreign key has PERIOD, we incorporate looking for replacement + * rows in the main SQL query below, so we needn't do it here. */ - if (is_no_action && + if (is_no_action && !riinfo->hasperiod && ri_Check_Pk_Match(pk_rel, fk_rel, oldslot, riinfo)) { table_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); } - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * Fetch or prepare a saved plan for the restrict lookup (it's the same * query for delete and update cases) */ - ri_BuildQueryKey(&qkey, riinfo, RI_PLAN_RESTRICT); + ri_BuildQueryKey(&qkey, riinfo, is_no_action ? RI_PLAN_NO_ACTION : RI_PLAN_RESTRICT); if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL) { StringInfoData querybuf; + char pkrelname[MAX_QUOTED_REL_NAME_LEN]; char fkrelname[MAX_QUOTED_REL_NAME_LEN]; char attname[MAX_QUOTED_NAME_LEN]; + char periodattname[MAX_QUOTED_NAME_LEN]; char paramname[16]; const char *querysep; Oid queryoids[RI_MAX_NUMKEYS]; @@ -694,8 +786,6 @@ ri_restrict(TriggerData *trigdata, bool is_no_action) { Oid pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]); Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]); - Oid pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]); - Oid fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]); quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[i])); @@ -704,11 +794,92 @@ ri_restrict(TriggerData *trigdata, bool is_no_action) paramname, pk_type, riinfo->pf_eq_oprs[i], attname, fk_type); - if (pk_coll != fk_coll && !get_collation_isdeterministic(pk_coll)) - ri_GenerateQualCollation(&querybuf, pk_coll); querysep = "AND"; queryoids[i] = pk_type; } + + /*---------- + * For temporal foreign keys, a reference could still be valid if the + * referenced range didn't change too much. Also if a referencing + * range extends past the current PK row, we don't want to check that + * part: some other PK row should fulfill it. We only want to check + * the part matching the PK record we've changed. Therefore to find + * invalid records we do this: + * + * SELECT 1 FROM [ONLY] x WHERE $1 = x.fkatt1 [AND ...] + * -- begin temporal + * AND $n && x.fkperiod + * AND NOT coalesce((x.fkperiod * $n) <@ + * (SELECT range_agg(r) + * FROM (SELECT y.pkperiod r + * FROM [ONLY] y + * WHERE $1 = y.pkatt1 [AND ...] AND $n && y.pkperiod + * FOR KEY SHARE OF y) y2), false) + * -- end temporal + * FOR KEY SHARE OF x + * + * We need the coalesce in case the first subquery returns no rows. + * We need the second subquery because FOR KEY SHARE doesn't support + * aggregate queries. + */ + if (riinfo->hasperiod && is_no_action) + { + Oid pk_period_type = RIAttType(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1]); + Oid fk_period_type = RIAttType(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1]); + StringInfoData intersectbuf; + StringInfoData replacementsbuf; + char *pk_only = pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ? + "" : "ONLY "; + + quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[riinfo->nkeys - 1])); + sprintf(paramname, "$%d", riinfo->nkeys); + + appendStringInfoString(&querybuf, " AND NOT coalesce("); + + /* Intersect the fk with the old pk range */ + initStringInfo(&intersectbuf); + appendStringInfoChar(&intersectbuf, '('); + ri_GenerateQual(&intersectbuf, "", + attname, fk_period_type, + riinfo->period_intersect_oper, + paramname, pk_period_type); + appendStringInfoChar(&intersectbuf, ')'); + + /* Find the remaining history */ + initStringInfo(&replacementsbuf); + appendStringInfoString(&replacementsbuf, "(SELECT pg_catalog.range_agg(r) FROM "); + + quoteOneName(periodattname, RIAttName(pk_rel, riinfo->pk_attnums[riinfo->nkeys - 1])); + quoteRelationName(pkrelname, pk_rel); + appendStringInfo(&replacementsbuf, "(SELECT y.%s r FROM %s%s y", + periodattname, pk_only, pkrelname); + + /* Restrict pk rows to what matches */ + querysep = "WHERE"; + for (int i = 0; i < riinfo->nkeys; i++) + { + Oid pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]); + + quoteOneName(attname, + RIAttName(pk_rel, riinfo->pk_attnums[i])); + sprintf(paramname, "$%d", i + 1); + ri_GenerateQual(&replacementsbuf, querysep, + paramname, pk_type, + riinfo->pp_eq_oprs[i], + attname, pk_type); + querysep = "AND"; + queryoids[i] = pk_type; + } + appendStringInfoString(&replacementsbuf, " FOR KEY SHARE OF y) y2)"); + + ri_GenerateQual(&querybuf, "", + intersectbuf.data, fk_period_type, + riinfo->agged_period_contained_by_oper, + replacementsbuf.data, ANYMULTIRANGEOID); + /* end of coalesce: */ + appendStringInfoString(&querybuf, ", false)"); + } + appendStringInfoString(&querybuf, " FOR KEY SHARE OF x"); /* Prepare and save the plan */ @@ -722,6 +893,7 @@ ri_restrict(TriggerData *trigdata, bool is_no_action) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + !is_no_action, true, /* must detect new rows */ SPI_OK_SELECT); @@ -766,8 +938,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) pk_rel = trigdata->tg_relation; oldslot = trigdata->tg_trigslot; - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* Fetch or prepare a saved plan for the cascaded delete */ ri_BuildQueryKey(&qkey, riinfo, RI_PLAN_CASCADE_ONDELETE); @@ -800,8 +971,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) { Oid pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]); Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]); - Oid pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]); - Oid fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]); quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[i])); @@ -810,8 +979,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) paramname, pk_type, riinfo->pf_eq_oprs[i], attname, fk_type); - if (pk_coll != fk_coll && !get_collation_isdeterministic(pk_coll)) - ri_GenerateQualCollation(&querybuf, pk_coll); querysep = "AND"; queryoids[i] = pk_type; } @@ -828,6 +995,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + false, true, /* must detect new rows */ SPI_OK_DELETE); @@ -875,8 +1043,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) newslot = trigdata->tg_newslot; oldslot = trigdata->tg_trigslot; - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* Fetch or prepare a saved plan for the cascaded update */ ri_BuildQueryKey(&qkey, riinfo, RI_PLAN_CASCADE_ONUPDATE); @@ -916,8 +1083,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) { Oid pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]); Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]); - Oid pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]); - Oid fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]); quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[i])); @@ -929,8 +1094,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) paramname, pk_type, riinfo->pf_eq_oprs[i], attname, fk_type); - if (pk_coll != fk_coll && !get_collation_isdeterministic(pk_coll)) - ri_GenerateQualCollation(&querybuf, pk_coll); querysep = ","; qualsep = "AND"; queryoids[i] = pk_type; @@ -949,6 +1112,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, newslot, + false, true, /* must detect new rows */ SPI_OK_UPDATE); @@ -1051,8 +1215,7 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind) pk_rel = trigdata->tg_relation; oldslot = trigdata->tg_trigslot; - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * Fetch or prepare a saved plan for the trigger. @@ -1153,8 +1316,6 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind) { Oid pk_type = RIAttType(pk_rel, riinfo->pk_attnums[i]); Oid fk_type = RIAttType(fk_rel, riinfo->fk_attnums[i]); - Oid pk_coll = RIAttCollation(pk_rel, riinfo->pk_attnums[i]); - Oid fk_coll = RIAttCollation(fk_rel, riinfo->fk_attnums[i]); quoteOneName(attname, RIAttName(fk_rel, riinfo->fk_attnums[i])); @@ -1164,8 +1325,6 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind) paramname, pk_type, riinfo->pf_eq_oprs[i], attname, fk_type); - if (pk_coll != fk_coll && !get_collation_isdeterministic(pk_coll)) - ri_GenerateQualCollation(&querybuf, pk_coll); qualsep = "AND"; queryoids[i] = pk_type; } @@ -1181,6 +1340,7 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind) ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, oldslot, NULL, + false, true, /* must detect new rows */ SPI_OK_UPDATE); @@ -1547,8 +1707,7 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) PGC_USERSET, PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * Generate the plan. We don't need to cache it, and there are no @@ -1628,7 +1787,7 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) ri_ReportViolation(&fake_riinfo, pk_rel, fk_rel, slot, tupdesc, - RI_PLAN_CHECK_LOOKUPPK, false); + RI_PLAN_CHECK_LOOKUPPK, false, false); ExecDropSingleTupleTableSlot(slot); } @@ -1787,8 +1946,7 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) PGC_USERSET, PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * Generate the plan. We don't need to cache it, and there are no @@ -1845,7 +2003,7 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) fake_riinfo.pk_attnums[i] = i + 1; ri_ReportViolation(&fake_riinfo, pk_rel, fk_rel, - slot, tupdesc, 0, true); + slot, tupdesc, 0, false, true); } if (SPI_finish() != SPI_OK_FINISH) @@ -1921,19 +2079,17 @@ ri_GenerateQual(StringInfo buf, /* * ri_GenerateQualCollation --- add a COLLATE spec to a WHERE clause * - * At present, we intentionally do not use this function for RI queries that - * compare a variable to a $n parameter. Since parameter symbols always have - * default collation, the effect will be to use the variable's collation. - * Now that is only strictly correct when testing the referenced column, since - * the SQL standard specifies that RI comparisons should use the referenced - * column's collation. However, so long as all collations have the same - * notion of equality (which they do, because texteq reduces to bitwise - * equality), there's no visible semantic impact from using the referencing - * column's collation when testing it, and this is a good thing to do because - * it lets us use a normal index on the referencing column. However, we do - * have to use this function when directly comparing the referencing and - * referenced columns, if they are of different collations; else the parser - * will fail to resolve the collation to use. + * We only have to use this function when directly comparing the referencing + * and referenced columns, if they are of different collations; else the + * parser will fail to resolve the collation to use. We don't need to use + * this function for RI queries that compare a variable to a $n parameter. + * Since parameter symbols always have default collation, the effect will be + * to use the variable's collation. + * + * Note that we require that the collations of the referencing and the + * referenced column have the same notion of equality: Either they have to + * both be deterministic or else they both have to be the same. (See also + * ATAddForeignKeyConstraint().) */ static void ri_GenerateQualCollation(StringInfo buf, Oid collation) @@ -2162,6 +2318,7 @@ ri_LoadConstraintInfo(Oid constraintOid) riinfo->confupdtype = conForm->confupdtype; riinfo->confdeltype = conForm->confdeltype; riinfo->confmatchtype = conForm->confmatchtype; + riinfo->hasperiod = conForm->conperiod; DeconstructFkConstraintRow(tup, &riinfo->nkeys, @@ -2173,6 +2330,21 @@ ri_LoadConstraintInfo(Oid constraintOid) &riinfo->ndelsetcols, riinfo->confdelsetcols); + /* + * For temporal FKs, get the operators and functions we need. We ask the + * opclass of the PK element for these. This all gets cached (as does the + * generated plan), so there's no performance issue. + */ + if (riinfo->hasperiod) + { + Oid opclass = get_index_column_opclass(conForm->conindid, riinfo->nkeys); + + FindFKPeriodOpers(opclass, + &riinfo->period_contained_by_oper, + &riinfo->agged_period_contained_by_oper, + &riinfo->period_intersect_oper); + } + ReleaseSysCache(tup); /* @@ -2313,6 +2485,7 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo, RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, + bool is_restrict, bool detectNewRows, int expect_OK) { Relation query_rel, @@ -2437,7 +2610,7 @@ ri_PerformCheck(const RI_ConstraintInfo *riinfo, pk_rel, fk_rel, newslot ? newslot : oldslot, NULL, - qkey->constr_queryno, false); + qkey->constr_queryno, is_restrict, false); return SPI_processed != 0; } @@ -2478,7 +2651,7 @@ static void ri_ReportViolation(const RI_ConstraintInfo *riinfo, Relation pk_rel, Relation fk_rel, TupleTableSlot *violatorslot, TupleDesc tupdesc, - int queryno, bool partgone) + int queryno, bool is_restrict, bool partgone) { StringInfoData key_names; StringInfoData key_values; @@ -2608,6 +2781,20 @@ ri_ReportViolation(const RI_ConstraintInfo *riinfo, errdetail("Key is not present in table \"%s\".", RelationGetRelationName(pk_rel)), errtableconstraint(fk_rel, NameStr(riinfo->conname)))); + else if (is_restrict) + ereport(ERROR, + (errcode(ERRCODE_RESTRICT_VIOLATION), + errmsg("update or delete on table \"%s\" violates RESTRICT setting of foreign key constraint \"%s\" on table \"%s\"", + RelationGetRelationName(pk_rel), + NameStr(riinfo->conname), + RelationGetRelationName(fk_rel)), + has_perm ? + errdetail("Key (%s)=(%s) is referenced from table \"%s\".", + key_names.data, key_values.data, + RelationGetRelationName(fk_rel)) : + errdetail("Key is referenced from table \"%s\".", + RelationGetRelationName(fk_rel)), + errtableconstraint(fk_rel, NameStr(riinfo->conname)))); else ereport(ERROR, (errcode(ERRCODE_FOREIGN_KEY_VIOLATION), @@ -2784,7 +2971,10 @@ ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan) /* * ri_KeysEqual - * - * Check if all key values in OLD and NEW are equal. + * Check if all key values in OLD and NEW are "equivalent": + * For normal FKs we check for equality. + * For temporal FKs we check that the PK side is a superset of its old value, + * or the FK side is a subset of its old value. * * Note: at some point we might wish to redefine this as checking for * "IS NOT DISTINCT" rather than "=", that is, allow two nulls to be @@ -2833,20 +3023,32 @@ ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, * difference for ON UPDATE CASCADE, but for consistency we treat * all changes to the PK the same. */ - Form_pg_attribute att = TupleDescAttr(oldslot->tts_tupleDescriptor, attnums[i] - 1); + CompactAttribute *att = TupleDescCompactAttr(oldslot->tts_tupleDescriptor, attnums[i] - 1); if (!datum_image_eq(oldvalue, newvalue, att->attbyval, att->attlen)) return false; } else { + Oid eq_opr; + + /* + * When comparing the PERIOD columns we can skip the check + * whenever the referencing column stayed equal or shrank, so test + * with the contained-by operator instead. + */ + if (riinfo->hasperiod && i == riinfo->nkeys - 1) + eq_opr = riinfo->period_contained_by_oper; + else + eq_opr = riinfo->ff_eq_oprs[i]; + /* * For the FK table, compare with the appropriate equality * operator. Changes that compare equal will still satisfy the * constraint after the update. */ - if (!ri_AttributesEqual(riinfo->ff_eq_oprs[i], RIAttType(rel, attnums[i]), - oldvalue, newvalue)) + if (!ri_CompareWithCast(eq_opr, RIAttType(rel, attnums[i]), RIAttCollation(rel, attnums[i]), + newvalue, oldvalue)) return false; } } @@ -2856,29 +3058,32 @@ ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot, /* - * ri_AttributesEqual - + * ri_CompareWithCast - * - * Call the appropriate equality comparison operator for two values. + * Call the appropriate comparison operator for two values. + * Normally this is equality, but for the PERIOD part of foreign keys + * it is ContainedBy, so the order of lhs vs rhs is significant. + * See below for how the collation is applied. * * NB: we have already checked that neither value is null. */ static bool -ri_AttributesEqual(Oid eq_opr, Oid typeid, - Datum oldvalue, Datum newvalue) +ri_CompareWithCast(Oid eq_opr, Oid typeid, Oid collid, + Datum lhs, Datum rhs) { RI_CompareHashEntry *entry = ri_HashCompareOp(eq_opr, typeid); /* Do we need to cast the values? */ if (OidIsValid(entry->cast_func_finfo.fn_oid)) { - oldvalue = FunctionCall3(&entry->cast_func_finfo, - oldvalue, - Int32GetDatum(-1), /* typmod */ - BoolGetDatum(false)); /* implicit coercion */ - newvalue = FunctionCall3(&entry->cast_func_finfo, - newvalue, - Int32GetDatum(-1), /* typmod */ - BoolGetDatum(false)); /* implicit coercion */ + lhs = FunctionCall3(&entry->cast_func_finfo, + lhs, + Int32GetDatum(-1), /* typmod */ + BoolGetDatum(false)); /* implicit coercion */ + rhs = FunctionCall3(&entry->cast_func_finfo, + rhs, + Int32GetDatum(-1), /* typmod */ + BoolGetDatum(false)); /* implicit coercion */ } /* @@ -2889,13 +3094,17 @@ ri_AttributesEqual(Oid eq_opr, Oid typeid, * on the other side of a foreign-key constraint. Therefore, the * comparison here would need to be done with the collation of the *other* * table. For simplicity (e.g., we might not even have the other table - * open), we'll just use the default collation here, which could lead to - * some false negatives. All this would break if we ever allow - * database-wide collations to be nondeterministic. + * open), we'll use our own collation. This is fine because we require + * that both collations have the same notion of equality (either they are + * both deterministic or else they are both the same). + * + * With range/multirangetypes, the collation of the base type is stored as + * part of the rangetype (pg_range.rngcollation), and always used, so + * there is no danger of inconsistency even using a non-equals operator. + * But if we support arbitrary types with PERIOD, we should perhaps just + * always force a re-check. */ - return DatumGetBool(FunctionCall2Coll(&entry->eq_opr_finfo, - DEFAULT_COLLATION_OID, - oldvalue, newvalue)); + return DatumGetBool(FunctionCall2Coll(&entry->eq_opr_finfo, collid, lhs, rhs)); } /* @@ -2950,7 +3159,7 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid) * the cast function to get to the operator's input type. * * XXX eventually it would be good to support array-coercion cases - * here and in ri_AttributesEqual(). At the moment there is no point + * here and in ri_CompareWithCast(). At the moment there is no point * because cases involving nonidentical array types will be rejected * at constraint creation time. * diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 18bbb62e9a11d..fe5edc0027da3 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -3,7 +3,7 @@ * rowtypes.c * I/O and comparison functions for generic composite types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 653685bffc5ea..3d6e6bdbfd21b 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -4,7 +4,7 @@ * Functions to convert stored expressions/querytrees back to * source text * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -50,7 +50,6 @@ #include "optimizer/optimizer.h" #include "parser/parse_agg.h" #include "parser/parse_func.h" -#include "parser/parse_node.h" #include "parser/parse_oper.h" #include "parser/parse_relation.h" #include "parser/parser.h" @@ -114,14 +113,16 @@ typedef struct { StringInfo buf; /* output buffer to append to */ List *namespaces; /* List of deparse_namespace nodes */ + TupleDesc resultDesc; /* if top level of a view, the view's tupdesc */ + List *targetList; /* Current query level's SELECT targetlist */ List *windowClause; /* Current query level's WINDOW clause */ - List *windowTList; /* targetlist for resolving WINDOW clause */ int prettyFlags; /* enabling of pretty-print functions */ int wrapColumn; /* max line length, or -1 for no limit */ int indentLevel; /* current indent level for pretty-print */ bool varprefix; /* true to print prefixes on Vars */ - ParseExprKind special_exprkind; /* set only for exprkinds needing special - * handling */ + bool colNamesVisible; /* do we care about output column names? */ + bool inGroupBy; /* deparsing GROUP BY clause? */ + bool varInOrderBy; /* deparsing simple Var in ORDER BY? */ Bitmapset *appendparents; /* if not null, map child Vars of these relids * back to the parent rel */ } deparse_context; @@ -166,6 +167,8 @@ typedef struct List *subplans; /* List of Plan trees for SubPlans */ List *ctes; /* List of CommonTableExpr nodes */ AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */ + char *ret_old_alias; /* alias for OLD in RETURNING list */ + char *ret_new_alias; /* alias for NEW in RETURNING list */ /* Workspace for column alias assignment: */ bool unique_using; /* Are we making USING names globally unique */ List *using_names; /* List of assigned names for USING columns */ @@ -223,6 +226,10 @@ typedef struct * of aliases to columns of the right input. Thus, positions in the printable * column alias list are not necessarily one-for-one with varattnos of the * JOIN, so we need a separate new_colnames[] array for printing purposes. + * + * Finally, when dealing with wide tables we risk O(N^2) costs in assigning + * non-duplicate column names. We ameliorate that by using a hash table that + * holds all the strings appearing in colnames, new_colnames, and parentUsing. */ typedef struct { @@ -290,6 +297,15 @@ typedef struct int *leftattnos; /* left-child varattnos of join cols, or 0 */ int *rightattnos; /* right-child varattnos of join cols, or 0 */ List *usingNames; /* names assigned to merged columns */ + + /* + * Hash table holding copies of all the strings appearing in this struct's + * colnames, new_colnames, and parentUsing. We use a hash table only for + * sufficiently wide relations, and only during the colname-assignment + * functions set_relation_column_names and set_join_column_names; + * otherwise, names_hash is NULL. + */ + HTAB *names_hash; /* entries are just strings */ } deparse_columns; /* This macro is analogous to rt_fetch(), but for deparse_columns structs */ @@ -338,7 +354,7 @@ static char *pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn); static char *pg_get_triggerdef_worker(Oid trigid, bool pretty); static int decompile_column_index_array(Datum column_index_array, Oid relId, - StringInfo buf); + bool withPeriod, StringInfo buf); static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags); static char *pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, @@ -375,6 +391,9 @@ static bool colname_is_unique(const char *colname, deparse_namespace *dpns, static char *make_colname_unique(char *colname, deparse_namespace *dpns, deparse_columns *colinfo); static void expand_colnames_array_to(deparse_columns *colinfo, int n); +static void build_colinfo_names_hash(deparse_columns *colinfo); +static void add_to_names_hash(deparse_columns *colinfo, const char *name); +static void destroy_colinfo_names_hash(deparse_columns *colinfo); static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, deparse_columns *colinfo); static char *get_rtable_name(int rtindex, deparse_context *context); @@ -398,27 +417,20 @@ static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, int prettyFlags, int wrapColumn, int startIndent); static void get_values_def(List *values_lists, deparse_context *context); static void get_with_clause(Query *query, deparse_context *context); -static void get_select_query_def(Query *query, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible); -static void get_insert_query_def(Query *query, deparse_context *context, - bool colNamesVisible); -static void get_update_query_def(Query *query, deparse_context *context, - bool colNamesVisible); +static void get_select_query_def(Query *query, deparse_context *context); +static void get_insert_query_def(Query *query, deparse_context *context); +static void get_update_query_def(Query *query, deparse_context *context); static void get_update_query_targetlist_def(Query *query, List *targetList, deparse_context *context, RangeTblEntry *rte); -static void get_delete_query_def(Query *query, deparse_context *context, - bool colNamesVisible); -static void get_merge_query_def(Query *query, deparse_context *context, - bool colNamesVisible); +static void get_delete_query_def(Query *query, deparse_context *context); +static void get_merge_query_def(Query *query, deparse_context *context); static void get_utility_query_def(Query *query, deparse_context *context); -static void get_basic_select_query(Query *query, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible); -static void get_target_list(List *targetList, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible); +static void get_basic_select_query(Query *query, deparse_context *context); +static void get_target_list(List *targetList, deparse_context *context); +static void get_returning_clause(Query *query, deparse_context *context); static void get_setop_query(Node *setOp, Query *query, - deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible); + deparse_context *context); static Node *get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, deparse_context *context); @@ -429,6 +441,9 @@ static void get_rule_orderby(List *orderList, List *targetList, static void get_rule_windowclause(Query *query, deparse_context *context); static void get_rule_windowspec(WindowClause *wc, List *targetList, deparse_context *context); +static void get_window_frame_options(int frameOptions, + Node *startOffset, Node *endOffset, + deparse_context *context); static char *get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context); static void get_special_variable(Node *node, deparse_context *context, @@ -515,7 +530,7 @@ static char *generate_qualified_relation_name(Oid relid); static char *generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, - ParseExprKind special_exprkind); + bool inGroupBy); static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); static void add_cast_to(StringInfo buf, Oid typid); static char *generate_qualified_type_name(Oid typid); @@ -596,8 +611,7 @@ pg_get_ruledef_worker(Oid ruleoid, int prettyFlags) /* * Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * On the first call prepare the plan to lookup pg_rewrite. We read @@ -789,8 +803,7 @@ pg_get_viewdef_worker(Oid viewoid, int prettyFlags, int wrapColumn) /* * Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * On the first call prepare the plan to lookup pg_rewrite. We read @@ -1094,13 +1107,16 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) /* Set up context with one-deep namespace stack */ context.buf = &buf; context.namespaces = list_make1(&dpns); + context.resultDesc = NULL; + context.targetList = NIL; context.windowClause = NIL; - context.windowTList = NIL; context.varprefix = true; context.prettyFlags = GET_PRETTY_FLAGS(pretty); context.wrapColumn = WRAP_COLUMN_DEFAULT; context.indentLevel = PRETTYINDENT_STD; - context.special_exprkind = EXPR_KIND_NONE; + context.colNamesVisible = true; + context.inGroupBy = false; + context.varInOrderBy = false; context.appendparents = NULL; get_rule_expr(qual, &context, false); @@ -1111,7 +1127,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) appendStringInfo(&buf, "EXECUTE FUNCTION %s(", generate_function_name(trigrec->tgfoid, 0, NIL, NULL, - false, NULL, EXPR_KIND_NONE)); + false, NULL, false)); if (trigrec->tgnargs > 0) { @@ -2260,7 +2276,8 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, val = SysCacheGetAttrNotNull(CONSTROID, tup, Anum_pg_constraint_conkey); - decompile_column_index_array(val, conForm->conrelid, &buf); + /* If it is a temporal foreign key then it uses PERIOD. */ + decompile_column_index_array(val, conForm->conrelid, conForm->conperiod, &buf); /* add foreign relation name */ appendStringInfo(&buf, ") REFERENCES %s(", @@ -2271,7 +2288,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, val = SysCacheGetAttrNotNull(CONSTROID, tup, Anum_pg_constraint_confkey); - decompile_column_index_array(val, conForm->confrelid, &buf); + decompile_column_index_array(val, conForm->confrelid, conForm->conperiod, &buf); appendStringInfoChar(&buf, ')'); @@ -2357,7 +2374,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, if (!isnull) { appendStringInfoString(&buf, " ("); - decompile_column_index_array(val, conForm->conrelid, &buf); + decompile_column_index_array(val, conForm->conrelid, false, &buf); appendStringInfoChar(&buf, ')'); } @@ -2392,7 +2409,9 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, val = SysCacheGetAttrNotNull(CONSTROID, tup, Anum_pg_constraint_conkey); - keyatts = decompile_column_index_array(val, conForm->conrelid, &buf); + keyatts = decompile_column_index_array(val, conForm->conrelid, false, &buf); + if (conForm->conperiod) + appendStringInfoString(&buf, " WITHOUT OVERLAPS"); appendStringInfoChar(&buf, ')'); @@ -2503,6 +2522,28 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, conForm->connoinherit ? " NO INHERIT" : ""); break; } + case CONSTRAINT_NOTNULL: + { + if (conForm->conrelid) + { + AttrNumber attnum; + + attnum = extractNotNullColumn(tup); + + appendStringInfo(&buf, "NOT NULL %s", + quote_identifier(get_attname(conForm->conrelid, + attnum, false))); + if (((Form_pg_constraint) GETSTRUCT(tup))->connoinherit) + appendStringInfoString(&buf, " NO INHERIT"); + } + else if (conForm->contypid) + { + /* conkey is null for domain not-null constraints */ + appendStringInfoString(&buf, "NOT NULL"); + } + break; + } + case CONSTRAINT_TRIGGER: /* @@ -2556,7 +2597,11 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, appendStringInfoString(&buf, " DEFERRABLE"); if (conForm->condeferred) appendStringInfoString(&buf, " INITIALLY DEFERRED"); - if (!conForm->convalidated) + + /* Validated status is irrelevant when the constraint is NOT ENFORCED. */ + if (!conForm->conenforced) + appendStringInfoString(&buf, " NOT ENFORCED"); + else if (!conForm->convalidated) appendStringInfoString(&buf, " NOT VALID"); /* Cleanup */ @@ -2574,7 +2619,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, */ static int decompile_column_index_array(Datum column_index_array, Oid relId, - StringInfo buf) + bool withPeriod, StringInfo buf) { Datum *keys; int nKeys; @@ -2593,7 +2638,9 @@ decompile_column_index_array(Datum column_index_array, Oid relId, if (j == 0) appendStringInfoString(buf, quote_identifier(colName)); else - appendStringInfo(buf, ", %s", quote_identifier(colName)); + appendStringInfo(buf, ", %s%s", + (withPeriod && j == nKeys - 1) ? "PERIOD " : "", + quote_identifier(colName)); } return nKeys; @@ -2992,7 +3039,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS) appendStringInfo(&buf, " SUPPORT %s", generate_function_name(proc->prosupport, 1, NIL, argtypes, - false, NULL, EXPR_KIND_NONE)); + false, NULL, false)); } if (oldlen != buf.len) @@ -3632,13 +3679,16 @@ deparse_expression_pretty(Node *expr, List *dpcontext, initStringInfo(&buf); context.buf = &buf; context.namespaces = dpcontext; + context.resultDesc = NULL; + context.targetList = NIL; context.windowClause = NIL; - context.windowTList = NIL; context.varprefix = forceprefix; context.prettyFlags = prettyFlags; context.wrapColumn = WRAP_COLUMN_DEFAULT; context.indentLevel = startIndent; - context.special_exprkind = EXPR_KIND_NONE; + context.colNamesVisible = true; + context.inGroupBy = false; + context.varInOrderBy = false; context.appendparents = NULL; get_rule_expr(expr, &context, showimplicit); @@ -3733,9 +3783,8 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names) dpns->appendrels = NULL; /* don't need it */ /* - * Set up column name aliases. We will get rather bogus results for join - * RTEs, but that doesn't matter because plan trees don't contain any join - * alias Vars. + * Set up column name aliases, ignoring any join RTEs; they don't matter + * because plan trees don't contain any join alias Vars. */ set_simple_column_names(dpns); @@ -3761,6 +3810,10 @@ deparse_context_for_plan_tree(PlannedStmt *pstmt, List *rtable_names) * the most-closely-nested first. This is needed to resolve PARAM_EXEC * Params. Note we assume that all the Plan nodes share the same rtable. * + * For a ModifyTable plan, we might also need to resolve references to OLD/NEW + * variables in the RETURNING list, so we copy the alias names of the OLD and + * NEW rows from the ModifyTable plan node. + * * Once this function has been called, deparse_expression() can be called on * subsidiary expression(s) of the specified Plan node. To deparse * expressions of a different Plan node in the same Plan tree, re-call this @@ -3781,6 +3834,13 @@ set_deparse_context_plan(List *dpcontext, Plan *plan, List *ancestors) dpns->ancestors = ancestors; set_deparse_plan(dpns, plan); + /* For ModifyTable, set aliases for OLD and NEW in RETURNING */ + if (IsA(plan, ModifyTable)) + { + dpns->ret_old_alias = ((ModifyTable *) plan)->returningOldAlias; + dpns->ret_new_alias = ((ModifyTable *) plan)->returningNewAlias; + } + return dpcontext; } @@ -3978,6 +4038,8 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query, dpns->subplans = NIL; dpns->ctes = query->cteList; dpns->appendrels = NULL; + dpns->ret_old_alias = query->returningOldAlias; + dpns->ret_new_alias = query->returningNewAlias; /* Assign a unique relation alias to each RTE */ set_rtable_names(dpns, parent_namespaces, NULL); @@ -4027,8 +4089,10 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query, * * This handles EXPLAIN and cases where we only have relation RTEs. Without * a join tree, we can't do anything smart about join RTEs, but we don't - * need to (note that EXPLAIN should never see join alias Vars anyway). - * If we do hit a join RTE we'll just process it like a non-table base RTE. + * need to, because EXPLAIN should never see join alias Vars anyway. + * If we find a join RTE we'll just skip it, leaving its deparse_columns + * struct all-zero. If somehow we try to deparse a join alias Var, we'll + * error out cleanly because the struct's num_cols will be zero. */ static void set_simple_column_names(deparse_namespace *dpns) @@ -4042,13 +4106,14 @@ set_simple_column_names(deparse_namespace *dpns) dpns->rtable_columns = lappend(dpns->rtable_columns, palloc0(sizeof(deparse_columns))); - /* Assign unique column aliases within each RTE */ + /* Assign unique column aliases within each non-join RTE */ forboth(lc, dpns->rtable, lc2, dpns->rtable_columns) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); deparse_columns *colinfo = (deparse_columns *) lfirst(lc2); - set_relation_column_names(dpns, rte, colinfo); + if (rte->rtekind != RTE_JOIN) + set_relation_column_names(dpns, rte, colinfo); } } @@ -4136,6 +4201,10 @@ has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode) * * parentUsing is a list of all USING aliases assigned in parent joins of * the current jointree node. (The passed-in list must not be modified.) + * + * Note that we do not use per-deparse_columns hash tables in this function. + * The number of names that need to be assigned should be small enough that + * we don't need to trouble with that. */ static void set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing) @@ -4365,8 +4434,8 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, if (rte->rtekind == RTE_FUNCTION && rte->functions != NIL) { /* Since we're not creating Vars, rtindex etc. don't matter */ - expandRTE(rte, 1, 0, -1, true /* include dropped */ , - &colnames, NULL); + expandRTE(rte, 1, 0, VAR_RETURNING_DEFAULT, -1, + true /* include dropped */ , &colnames, NULL); } else colnames = rte->eref->colnames; @@ -4411,6 +4480,9 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *)); colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool)); + /* If the RTE is wide enough, use a hash table to avoid O(N^2) costs */ + build_colinfo_names_hash(colinfo); + /* * Scan the columns, select a unique alias for each one, and store it in * colinfo->colnames and colinfo->new_colnames. The former array has NULL @@ -4446,6 +4518,7 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, colname = make_colname_unique(colname, dpns, colinfo); colinfo->colnames[i] = colname; + add_to_names_hash(colinfo, colname); } /* Put names of non-dropped columns in new_colnames[] too */ @@ -4459,6 +4532,9 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, changed_any = true; } + /* We're now done needing the colinfo's names_hash */ + destroy_colinfo_names_hash(colinfo); + /* * Set correct length for new_colnames[] array. (Note: if columns have * been added, colinfo->num_cols includes them, which is not really quite @@ -4529,6 +4605,9 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, expand_colnames_array_to(colinfo, noldcolumns); Assert(colinfo->num_cols == noldcolumns); + /* If the RTE is wide enough, use a hash table to avoid O(N^2) costs */ + build_colinfo_names_hash(colinfo); + /* * Scan the join output columns, select an alias for each one, and store * it in colinfo->colnames. If there are USING columns, set_using_names() @@ -4566,6 +4645,7 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, if (rte->alias == NULL) { colinfo->colnames[i] = real_colname; + add_to_names_hash(colinfo, real_colname); continue; } @@ -4582,6 +4662,7 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, colname = make_colname_unique(colname, dpns, colinfo); colinfo->colnames[i] = colname; + add_to_names_hash(colinfo, colname); } /* Remember if any assigned aliases differ from "real" name */ @@ -4680,6 +4761,7 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, } else colinfo->new_colnames[j] = child_colname; + add_to_names_hash(colinfo, colinfo->new_colnames[j]); } colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc]; @@ -4729,6 +4811,7 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, } else colinfo->new_colnames[j] = child_colname; + add_to_names_hash(colinfo, colinfo->new_colnames[j]); } colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc]; @@ -4743,6 +4826,9 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, Assert(j == nnewcolumns); #endif + /* We're now done needing the colinfo's names_hash */ + destroy_colinfo_names_hash(colinfo); + /* * For a named join, print column aliases if we changed any from the child * names. Unnamed joins cannot print aliases. @@ -4765,38 +4851,59 @@ colname_is_unique(const char *colname, deparse_namespace *dpns, int i; ListCell *lc; - /* Check against already-assigned column aliases within RTE */ - for (i = 0; i < colinfo->num_cols; i++) - { - char *oldname = colinfo->colnames[i]; - - if (oldname && strcmp(oldname, colname) == 0) - return false; - } - /* - * If we're building a new_colnames array, check that too (this will be - * partially but not completely redundant with the previous checks) + * If we have a hash table, consult that instead of linearly scanning the + * colinfo's strings. */ - for (i = 0; i < colinfo->num_new_cols; i++) + if (colinfo->names_hash) { - char *oldname = colinfo->new_colnames[i]; - - if (oldname && strcmp(oldname, colname) == 0) + if (hash_search(colinfo->names_hash, + colname, + HASH_FIND, + NULL) != NULL) return false; } - - /* Also check against USING-column names that must be globally unique */ - foreach(lc, dpns->using_names) + else { - char *oldname = (char *) lfirst(lc); + /* Check against already-assigned column aliases within RTE */ + for (i = 0; i < colinfo->num_cols; i++) + { + char *oldname = colinfo->colnames[i]; - if (strcmp(oldname, colname) == 0) - return false; + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* + * If we're building a new_colnames array, check that too (this will + * be partially but not completely redundant with the previous checks) + */ + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *oldname = colinfo->new_colnames[i]; + + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* + * Also check against names already assigned for parent-join USING + * cols + */ + foreach(lc, colinfo->parentUsing) + { + char *oldname = (char *) lfirst(lc); + + if (strcmp(oldname, colname) == 0) + return false; + } } - /* Also check against names already assigned for parent-join USING cols */ - foreach(lc, colinfo->parentUsing) + /* + * Also check against USING-column names that must be globally unique. + * These are not hashed, but there should be few of them. + */ + foreach(lc, dpns->using_names) { char *oldname = (char *) lfirst(lc); @@ -4864,6 +4971,90 @@ expand_colnames_array_to(deparse_columns *colinfo, int n) } } +/* + * build_colinfo_names_hash: optionally construct a hash table for colinfo + */ +static void +build_colinfo_names_hash(deparse_columns *colinfo) +{ + HASHCTL hash_ctl; + int i; + ListCell *lc; + + /* + * Use a hash table only for RTEs with at least 32 columns. (The cutoff + * is somewhat arbitrary, but let's choose it so that this code does get + * exercised in the regression tests.) + */ + if (colinfo->num_cols < 32) + return; + + /* + * Set up the hash table. The entries are just strings with no other + * payload. + */ + hash_ctl.keysize = NAMEDATALEN; + hash_ctl.entrysize = NAMEDATALEN; + hash_ctl.hcxt = CurrentMemoryContext; + colinfo->names_hash = hash_create("deparse_columns names", + colinfo->num_cols + colinfo->num_new_cols, + &hash_ctl, + HASH_ELEM | HASH_STRINGS | HASH_CONTEXT); + + /* + * Preload the hash table with any names already present (these would have + * come from set_using_names). + */ + for (i = 0; i < colinfo->num_cols; i++) + { + char *oldname = colinfo->colnames[i]; + + if (oldname) + add_to_names_hash(colinfo, oldname); + } + + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *oldname = colinfo->new_colnames[i]; + + if (oldname) + add_to_names_hash(colinfo, oldname); + } + + foreach(lc, colinfo->parentUsing) + { + char *oldname = (char *) lfirst(lc); + + add_to_names_hash(colinfo, oldname); + } +} + +/* + * add_to_names_hash: add a string to the names_hash, if we're using one + */ +static void +add_to_names_hash(deparse_columns *colinfo, const char *name) +{ + if (colinfo->names_hash) + (void) hash_search(colinfo->names_hash, + name, + HASH_ENTER, + NULL); +} + +/* + * destroy_colinfo_names_hash: destroy hash table when done with it + */ +static void +destroy_colinfo_names_hash(deparse_columns *colinfo) +{ + if (colinfo->names_hash) + { + hash_destroy(colinfo->names_hash); + colinfo->names_hash = NULL; + } +} + /* * identify_join_columns: figure out where columns of a join come from * @@ -5283,13 +5474,16 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, context.buf = buf; context.namespaces = list_make1(&dpns); + context.resultDesc = NULL; + context.targetList = NIL; context.windowClause = NIL; - context.windowTList = NIL; context.varprefix = (list_length(query->rtable) != 1); context.prettyFlags = prettyFlags; context.wrapColumn = WRAP_COLUMN_DEFAULT; context.indentLevel = PRETTYINDENT_STD; - context.special_exprkind = EXPR_KIND_NONE; + context.colNamesVisible = true; + context.inGroupBy = false; + context.varInOrderBy = false; context.appendparents = NULL; set_deparse_for_query(&dpns, query, NIL); @@ -5433,11 +5627,28 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace, { deparse_context context; deparse_namespace dpns; + int rtable_size; /* Guard against excessively long or deeply-nested queries */ CHECK_FOR_INTERRUPTS(); check_stack_depth(); + rtable_size = query->hasGroupRTE ? + list_length(query->rtable) - 1 : + list_length(query->rtable); + + /* + * Replace any Vars in the query's targetlist and havingQual that + * reference GROUP outputs with the underlying grouping expressions. + */ + if (query->hasGroupRTE) + { + query->targetList = (List *) + flatten_group_exprs(NULL, query, (Node *) query->targetList); + query->havingQual = + flatten_group_exprs(NULL, query, query->havingQual); + } + /* * Before we begin to examine the query, acquire locks on referenced * relations, and fix up deleted columns in JOIN RTEs. This ensures @@ -5451,14 +5662,17 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace, context.buf = buf; context.namespaces = lcons(&dpns, list_copy(parentnamespace)); + context.resultDesc = NULL; + context.targetList = NIL; context.windowClause = NIL; - context.windowTList = NIL; context.varprefix = (parentnamespace != NIL || - list_length(query->rtable) != 1); + rtable_size != 1); context.prettyFlags = prettyFlags; context.wrapColumn = wrapColumn; context.indentLevel = startIndent; - context.special_exprkind = EXPR_KIND_NONE; + context.colNamesVisible = colNamesVisible; + context.inGroupBy = false; + context.varInOrderBy = false; context.appendparents = NULL; set_deparse_for_query(&dpns, query, parentnamespace); @@ -5466,23 +5680,25 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace, switch (query->commandType) { case CMD_SELECT: - get_select_query_def(query, &context, resultDesc, colNamesVisible); + /* We set context.resultDesc only if it's a SELECT */ + context.resultDesc = resultDesc; + get_select_query_def(query, &context); break; case CMD_UPDATE: - get_update_query_def(query, &context, colNamesVisible); + get_update_query_def(query, &context); break; case CMD_INSERT: - get_insert_query_def(query, &context, colNamesVisible); + get_insert_query_def(query, &context); break; case CMD_DELETE: - get_delete_query_def(query, &context, colNamesVisible); + get_delete_query_def(query, &context); break; case CMD_MERGE: - get_merge_query_def(query, &context, colNamesVisible); + get_merge_query_def(query, &context); break; case CMD_NOTHING: @@ -5687,23 +5903,18 @@ get_with_clause(Query *query, deparse_context *context) * ---------- */ static void -get_select_query_def(Query *query, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible) +get_select_query_def(Query *query, deparse_context *context) { StringInfo buf = context->buf; - List *save_windowclause; - List *save_windowtlist; bool force_colno; ListCell *l; /* Insert the WITH clause if given */ get_with_clause(query, context); - /* Set up context for possible window functions */ - save_windowclause = context->windowClause; + /* Subroutines may need to consult the SELECT targetlist and windowClause */ + context->targetList = query->targetList; context->windowClause = query->windowClause; - save_windowtlist = context->windowTList; - context->windowTList = query->targetList; /* * If the Query node has a setOperations tree, then it's the top level of @@ -5712,14 +5923,13 @@ get_select_query_def(Query *query, deparse_context *context, */ if (query->setOperations) { - get_setop_query(query->setOperations, query, context, resultDesc, - colNamesVisible); + get_setop_query(query->setOperations, query, context); /* ORDER BY clauses must be simple in this case */ force_colno = true; } else { - get_basic_select_query(query, context, resultDesc, colNamesVisible); + get_basic_select_query(query, context); force_colno = false; } @@ -5746,9 +5956,19 @@ get_select_query_def(Query *query, deparse_context *context, { if (query->limitOption == LIMIT_OPTION_WITH_TIES) { + /* + * The limitCount arg is a c_expr, so it needs parens. Simple + * literals and function expressions would not need parens, but + * unfortunately it's hard to tell if the expression will be + * printed as a simple literal like 123 or as a typecast + * expression, like '-123'::int4. The grammar accepts the former + * without quoting, but not the latter. + */ appendContextKeyword(context, " FETCH FIRST ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + appendStringInfoChar(buf, '('); get_rule_expr(query->limitCount, context, false); + appendStringInfoChar(buf, ')'); appendStringInfoString(buf, " ROWS WITH TIES"); } else @@ -5808,9 +6028,6 @@ get_select_query_def(Query *query, deparse_context *context, appendStringInfoString(buf, " SKIP LOCKED"); } } - - context->windowClause = save_windowclause; - context->windowTList = save_windowtlist; } /* @@ -5888,8 +6105,7 @@ get_simple_values_rte(Query *query, TupleDesc resultDesc) } static void -get_basic_select_query(Query *query, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible) +get_basic_select_query(Query *query, deparse_context *context) { StringInfo buf = context->buf; RangeTblEntry *values_rte; @@ -5907,7 +6123,7 @@ get_basic_select_query(Query *query, deparse_context *context, * VALUES part. This reverses what transformValuesClause() did at parse * time. */ - values_rte = get_simple_values_rte(query, resultDesc); + values_rte = get_simple_values_rte(query, context->resultDesc); if (values_rte) { get_values_def(values_rte->values_lists, context); @@ -5945,7 +6161,7 @@ get_basic_select_query(Query *query, deparse_context *context, } /* Then we tell what to select (the targetlist) */ - get_target_list(query->targetList, context, resultDesc, colNamesVisible); + get_target_list(query->targetList, context); /* Add the FROM clause if needed */ get_from_clause(query, " FROM ", context); @@ -5961,15 +6177,15 @@ get_basic_select_query(Query *query, deparse_context *context, /* Add the GROUP BY clause if given */ if (query->groupClause != NULL || query->groupingSets != NULL) { - ParseExprKind save_exprkind; + bool save_ingroupby; appendContextKeyword(context, " GROUP BY ", -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); if (query->groupDistinct) appendStringInfoString(buf, "DISTINCT "); - save_exprkind = context->special_exprkind; - context->special_exprkind = EXPR_KIND_GROUP_BY; + save_ingroupby = context->inGroupBy; + context->inGroupBy = true; if (query->groupingSets == NIL) { @@ -5997,7 +6213,7 @@ get_basic_select_query(Query *query, deparse_context *context, } } - context->special_exprkind = save_exprkind; + context->inGroupBy = save_ingroupby; } /* Add the HAVING clause if given */ @@ -6017,13 +6233,10 @@ get_basic_select_query(Query *query, deparse_context *context, * get_target_list - Parse back a SELECT target list * * This is also used for RETURNING lists in INSERT/UPDATE/DELETE/MERGE. - * - * resultDesc and colNamesVisible are as for get_query_def() * ---------- */ static void -get_target_list(List *targetList, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible) +get_target_list(List *targetList, deparse_context *context) { StringInfo buf = context->buf; StringInfoData targetbuf; @@ -6080,7 +6293,7 @@ get_target_list(List *targetList, deparse_context *context, * assigned column name explicitly. Otherwise, show it only if * it's not FigureColname's fallback. */ - attname = colNamesVisible ? NULL : "?column?"; + attname = context->colNamesVisible ? NULL : "?column?"; } /* @@ -6089,8 +6302,9 @@ get_target_list(List *targetList, deparse_context *context, * effects of any column RENAME that's been done on the view). * Otherwise, just use what we can find in the TLE. */ - if (resultDesc && colno <= resultDesc->natts) - colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); + if (context->resultDesc && colno <= context->resultDesc->natts) + colname = NameStr(TupleDescAttr(context->resultDesc, + colno - 1)->attname); else colname = tle->resname; @@ -6158,8 +6372,46 @@ get_target_list(List *targetList, deparse_context *context, } static void -get_setop_query(Node *setOp, Query *query, deparse_context *context, - TupleDesc resultDesc, bool colNamesVisible) +get_returning_clause(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + + if (query->returningList) + { + bool have_with = false; + + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + + /* Add WITH (OLD/NEW) options, if they're not the defaults */ + if (query->returningOldAlias && strcmp(query->returningOldAlias, "old") != 0) + { + appendStringInfo(buf, " WITH (OLD AS %s", + quote_identifier(query->returningOldAlias)); + have_with = true; + } + if (query->returningNewAlias && strcmp(query->returningNewAlias, "new") != 0) + { + if (have_with) + appendStringInfo(buf, ", NEW AS %s", + quote_identifier(query->returningNewAlias)); + else + { + appendStringInfo(buf, " WITH (NEW AS %s", + quote_identifier(query->returningNewAlias)); + have_with = true; + } + } + if (have_with) + appendStringInfoChar(buf, ')'); + + /* Add the returning expressions themselves */ + get_target_list(query->returningList, context); + } +} + +static void +get_setop_query(Node *setOp, Query *query, deparse_context *context) { StringInfo buf = context->buf; bool need_paren; @@ -6175,17 +6427,23 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context, Query *subquery = rte->subquery; Assert(subquery != NULL); - Assert(subquery->setOperations == NULL); - /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */ + + /* + * We need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y. + * Also add parens if the leaf query contains its own set operations. + * (That shouldn't happen unless one of the other clauses is also + * present, see transformSetOperationTree; but let's be safe.) + */ need_paren = (subquery->cteList || subquery->sortClause || subquery->rowMarks || subquery->limitOffset || - subquery->limitCount); + subquery->limitCount || + subquery->setOperations); if (need_paren) appendStringInfoChar(buf, '('); - get_query_def(subquery, buf, context->namespaces, resultDesc, - colNamesVisible, + get_query_def(subquery, buf, context->namespaces, + context->resultDesc, context->colNamesVisible, context->prettyFlags, context->wrapColumn, context->indentLevel); if (need_paren) @@ -6195,6 +6453,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context, { SetOperationStmt *op = (SetOperationStmt *) setOp; int subindent; + bool save_colnamesvisible; /* * We force parens when nesting two SetOperationStmts, except when the @@ -6228,7 +6487,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context, else subindent = 0; - get_setop_query(op->larg, query, context, resultDesc, colNamesVisible); + get_setop_query(op->larg, query, context); if (need_paren) appendContextKeyword(context, ") ", -subindent, 0, 0); @@ -6272,7 +6531,15 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context, subindent = 0; appendContextKeyword(context, "", subindent, 0, 0); - get_setop_query(op->rarg, query, context, resultDesc, false); + /* + * The output column names of the RHS sub-select don't matter. + */ + save_colnamesvisible = context->colNamesVisible; + context->colNamesVisible = false; + + get_setop_query(op->rarg, query, context); + + context->colNamesVisible = save_colnamesvisible; if (PRETTY_INDENT(context)) context->indentLevel -= subindent; @@ -6306,20 +6573,32 @@ get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, * Use column-number form if requested by caller. Otherwise, if * expression is a constant, force it to be dumped with an explicit cast * as decoration --- this is because a simple integer constant is - * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we - * dump it without any decoration. If it's anything more complex than a - * simple Var, then force extra parens around it, to ensure it can't be - * misinterpreted as a cube() or rollup() construct. + * ambiguous (and will be misinterpreted by findTargetlistEntrySQL92()) if + * we dump it without any decoration. Similarly, if it's just a Var, + * there is risk of misinterpretation if the column name is reassigned in + * the SELECT list, so we may need to force table qualification. And, if + * it's anything more complex than a simple Var, then force extra parens + * around it, to ensure it can't be misinterpreted as a cube() or rollup() + * construct. */ if (force_colno) { Assert(!tle->resjunk); appendStringInfo(buf, "%d", tle->resno); } - else if (expr && IsA(expr, Const)) + else if (!expr) + /* do nothing, probably can't happen */ ; + else if (IsA(expr, Const)) get_const_expr((Const *) expr, context, 1); - else if (!expr || IsA(expr, Var)) - get_rule_expr(expr, context, true); + else if (IsA(expr, Var)) + { + /* Tell get_variable to check for name conflict */ + bool save_varinorderby = context->varInOrderBy; + + context->varInOrderBy = true; + (void) get_variable((Var *) expr, 0, false, context); + context->varInOrderBy = save_varinorderby; + } else { /* @@ -6545,45 +6824,64 @@ get_rule_windowspec(WindowClause *wc, List *targetList, { if (needspace) appendStringInfoChar(buf, ' '); - if (wc->frameOptions & FRAMEOPTION_RANGE) + get_window_frame_options(wc->frameOptions, + wc->startOffset, wc->endOffset, + context); + } + appendStringInfoChar(buf, ')'); +} + +/* + * Append the description of a window's framing options to context->buf + */ +static void +get_window_frame_options(int frameOptions, + Node *startOffset, Node *endOffset, + deparse_context *context) +{ + StringInfo buf = context->buf; + + if (frameOptions & FRAMEOPTION_NONDEFAULT) + { + if (frameOptions & FRAMEOPTION_RANGE) appendStringInfoString(buf, "RANGE "); - else if (wc->frameOptions & FRAMEOPTION_ROWS) + else if (frameOptions & FRAMEOPTION_ROWS) appendStringInfoString(buf, "ROWS "); - else if (wc->frameOptions & FRAMEOPTION_GROUPS) + else if (frameOptions & FRAMEOPTION_GROUPS) appendStringInfoString(buf, "GROUPS "); else Assert(false); - if (wc->frameOptions & FRAMEOPTION_BETWEEN) + if (frameOptions & FRAMEOPTION_BETWEEN) appendStringInfoString(buf, "BETWEEN "); - if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) + if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) appendStringInfoString(buf, "UNBOUNDED PRECEDING "); - else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW) + else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) appendStringInfoString(buf, "CURRENT ROW "); - else if (wc->frameOptions & FRAMEOPTION_START_OFFSET) + else if (frameOptions & FRAMEOPTION_START_OFFSET) { - get_rule_expr(wc->startOffset, context, false); - if (wc->frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) + get_rule_expr(startOffset, context, false); + if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) appendStringInfoString(buf, " PRECEDING "); - else if (wc->frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) + else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING) appendStringInfoString(buf, " FOLLOWING "); else Assert(false); } else Assert(false); - if (wc->frameOptions & FRAMEOPTION_BETWEEN) + if (frameOptions & FRAMEOPTION_BETWEEN) { appendStringInfoString(buf, "AND "); - if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) + if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) appendStringInfoString(buf, "UNBOUNDED FOLLOWING "); - else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW) + else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) appendStringInfoString(buf, "CURRENT ROW "); - else if (wc->frameOptions & FRAMEOPTION_END_OFFSET) + else if (frameOptions & FRAMEOPTION_END_OFFSET) { - get_rule_expr(wc->endOffset, context, false); - if (wc->frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) + get_rule_expr(endOffset, context, false); + if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) appendStringInfoString(buf, " PRECEDING "); - else if (wc->frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING) + else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING) appendStringInfoString(buf, " FOLLOWING "); else Assert(false); @@ -6591,16 +6889,46 @@ get_rule_windowspec(WindowClause *wc, List *targetList, else Assert(false); } - if (wc->frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) + if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) appendStringInfoString(buf, "EXCLUDE CURRENT ROW "); - else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_GROUP) + else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) appendStringInfoString(buf, "EXCLUDE GROUP "); - else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES) + else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) appendStringInfoString(buf, "EXCLUDE TIES "); /* we will now have a trailing space; remove it */ - buf->len--; + buf->data[--(buf->len)] = '\0'; } - appendStringInfoChar(buf, ')'); +} + +/* + * Return the description of a window's framing options as a palloc'd string + */ +char * +get_window_frame_options_for_explain(int frameOptions, + Node *startOffset, Node *endOffset, + List *dpcontext, bool forceprefix) +{ + StringInfoData buf; + deparse_context context; + + initStringInfo(&buf); + context.buf = &buf; + context.namespaces = dpcontext; + context.resultDesc = NULL; + context.targetList = NIL; + context.windowClause = NIL; + context.varprefix = forceprefix; + context.prettyFlags = 0; + context.wrapColumn = WRAP_COLUMN_DEFAULT; + context.indentLevel = 0; + context.colNamesVisible = true; + context.inGroupBy = false; + context.varInOrderBy = false; + context.appendparents = NULL; + + get_window_frame_options(frameOptions, startOffset, endOffset, &context); + + return buf.data; } /* ---------- @@ -6608,8 +6936,7 @@ get_rule_windowspec(WindowClause *wc, List *targetList, * ---------- */ static void -get_insert_query_def(Query *query, deparse_context *context, - bool colNamesVisible) +get_insert_query_def(Query *query, deparse_context *context) { StringInfo buf = context->buf; RangeTblEntry *select_rte = NULL; @@ -6812,11 +7139,7 @@ get_insert_query_def(Query *query, deparse_context *context, /* Add RETURNING if present */ if (query->returningList) - { - appendContextKeyword(context, " RETURNING", - -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); - get_target_list(query->returningList, context, NULL, colNamesVisible); - } + get_returning_clause(query, context); } @@ -6825,8 +7148,7 @@ get_insert_query_def(Query *query, deparse_context *context, * ---------- */ static void -get_update_query_def(Query *query, deparse_context *context, - bool colNamesVisible) +get_update_query_def(Query *query, deparse_context *context) { StringInfo buf = context->buf; RangeTblEntry *rte; @@ -6869,11 +7191,7 @@ get_update_query_def(Query *query, deparse_context *context, /* Add RETURNING if present */ if (query->returningList) - { - appendContextKeyword(context, " RETURNING", - -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); - get_target_list(query->returningList, context, NULL, colNamesVisible); - } + get_returning_clause(query, context); } @@ -7034,8 +7352,7 @@ get_update_query_targetlist_def(Query *query, List *targetList, * ---------- */ static void -get_delete_query_def(Query *query, deparse_context *context, - bool colNamesVisible) +get_delete_query_def(Query *query, deparse_context *context) { StringInfo buf = context->buf; RangeTblEntry *rte; @@ -7073,11 +7390,7 @@ get_delete_query_def(Query *query, deparse_context *context, /* Add RETURNING if present */ if (query->returningList) - { - appendContextKeyword(context, " RETURNING", - -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); - get_target_list(query->returningList, context, NULL, colNamesVisible); - } + get_returning_clause(query, context); } @@ -7086,8 +7399,7 @@ get_delete_query_def(Query *query, deparse_context *context, * ---------- */ static void -get_merge_query_def(Query *query, deparse_context *context, - bool colNamesVisible) +get_merge_query_def(Query *query, deparse_context *context) { StringInfo buf = context->buf; RangeTblEntry *rte; @@ -7237,11 +7549,7 @@ get_merge_query_def(Query *query, deparse_context *context, /* Add RETURNING if present */ if (query->returningList) - { - appendContextKeyword(context, " RETURNING", - -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); - get_target_list(query->returningList, context, NULL, colNamesVisible); - } + get_returning_clause(query, context); } @@ -7307,6 +7615,7 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) deparse_columns *colinfo; char *refname; char *attname; + bool need_prefix; /* Find appropriate nesting depth */ netlevelsup = var->varlevelsup + levelsup; @@ -7388,7 +7697,15 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) } rte = rt_fetch(varno, dpns->rtable); - refname = (char *) list_nth(dpns->rtable_names, varno - 1); + + /* might be returning old/new column value */ + if (var->varreturningtype == VAR_RETURNING_OLD) + refname = dpns->ret_old_alias; + else if (var->varreturningtype == VAR_RETURNING_NEW) + refname = dpns->ret_new_alias; + else + refname = (char *) list_nth(dpns->rtable_names, varno - 1); + colinfo = deparse_columns_fetch(varno, dpns); attnum = varattno; } @@ -7502,7 +7819,46 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) attname = get_rte_attribute_name(rte, attnum); } - if (refname && (context->varprefix || attname == NULL)) + need_prefix = (context->varprefix || attname == NULL || + var->varreturningtype != VAR_RETURNING_DEFAULT); + + /* + * If we're considering a plain Var in an ORDER BY (but not GROUP BY) + * clause, we may need to add a table-name prefix to prevent + * findTargetlistEntrySQL92 from misinterpreting the name as an + * output-column name. To avoid cluttering the output with unnecessary + * prefixes, do so only if there is a name match to a SELECT tlist item + * that is different from the Var. + */ + if (context->varInOrderBy && !context->inGroupBy && !need_prefix) + { + int colno = 0; + + foreach_node(TargetEntry, tle, context->targetList) + { + char *colname; + + if (tle->resjunk) + continue; /* ignore junk entries */ + colno++; + + /* This must match colname-choosing logic in get_target_list() */ + if (context->resultDesc && colno <= context->resultDesc->natts) + colname = NameStr(TupleDescAttr(context->resultDesc, + colno - 1)->attname); + else + colname = tle->resname; + + if (colname && strcmp(colname, attname) == 0 && + !equal(var, tle->expr)) + { + need_prefix = true; + break; + } + } + } + + if (refname && need_prefix) { appendStringInfoString(buf, quote_identifier(refname)); appendStringInfoChar(buf, '.'); @@ -7895,17 +8251,31 @@ get_name_for_var_field(Var *var, int fieldno, /* * We're deparsing a Plan tree so we don't have complete * RTE entries (in particular, rte->subquery is NULL). But - * the only place we'd see a Var directly referencing a - * SUBQUERY RTE is in a SubqueryScan plan node, and we can - * look into the child plan's tlist instead. + * the only place we'd normally see a Var directly + * referencing a SUBQUERY RTE is in a SubqueryScan plan + * node, and we can look into the child plan's tlist + * instead. An exception occurs if the subquery was + * proven empty and optimized away: then we'd find such a + * Var in a childless Result node, and there's nothing in + * the plan tree that would let us figure out what it had + * originally referenced. In that case, fall back on + * printing "fN", analogously to the default column names + * for RowExprs. */ TargetEntry *tle; deparse_namespace save_dpns; const char *result; if (!dpns->inner_plan) - elog(ERROR, "failed to find plan for subquery %s", - rte->eref->aliasname); + { + char *dummy_name = palloc(32); + + Assert(dpns->plan && IsA(dpns->plan, Result)); + snprintf(dummy_name, 32, "f%d", fieldno); + return dummy_name; + } + Assert(dpns->plan && IsA(dpns->plan, SubqueryScan)); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); if (!tle) elog(ERROR, "bogus varattno for subquery var: %d", @@ -8014,20 +8384,30 @@ get_name_for_var_field(Var *var, int fieldno, { /* * We're deparsing a Plan tree so we don't have a CTE - * list. But the only places we'd see a Var directly - * referencing a CTE RTE are in CteScan or WorkTableScan - * plan nodes. For those cases, set_deparse_plan arranged - * for dpns->inner_plan to be the plan node that emits the - * CTE or RecursiveUnion result, and we can look at its - * tlist instead. + * list. But the only places we'd normally see a Var + * directly referencing a CTE RTE are in CteScan or + * WorkTableScan plan nodes. For those cases, + * set_deparse_plan arranged for dpns->inner_plan to be + * the plan node that emits the CTE or RecursiveUnion + * result, and we can look at its tlist instead. As + * above, this can fail if the CTE has been proven empty, + * in which case fall back to "fN". */ TargetEntry *tle; deparse_namespace save_dpns; const char *result; if (!dpns->inner_plan) - elog(ERROR, "failed to find plan for CTE %s", - rte->eref->aliasname); + { + char *dummy_name = palloc(32); + + Assert(dpns->plan && IsA(dpns->plan, Result)); + snprintf(dummy_name, 32, "f%d", fieldno); + return dummy_name; + } + Assert(dpns->plan && (IsA(dpns->plan, CteScan) || + IsA(dpns->plan, WorkTableScan))); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); if (!tle) elog(ERROR, "bogus varattno for subquery var: %d", @@ -8043,6 +8423,14 @@ get_name_for_var_field(Var *var, int fieldno, } } break; + case RTE_GROUP: + + /* + * We couldn't get here: any Vars that reference the RTE_GROUP RTE + * should have been replaced with the underlying grouping + * expressions. + */ + break; } /* @@ -8529,6 +8917,9 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) case T_ConvertRowtypeExpr: return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg, node, prettyFlags); + case T_ReturningExpr: + return isSimpleNode((Node *) ((ReturningExpr *) node)->retexpr, + node, prettyFlags); case T_OpExpr: { @@ -9813,9 +10204,16 @@ get_rule_expr(Node *node, deparse_context *context, } } if (xexpr->op == IS_XMLSERIALIZE) + { appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type, xexpr->typmod)); + if (xexpr->indent) + appendStringInfoString(buf, " INDENT"); + else + appendStringInfoString(buf, " NO INDENT"); + } + if (xexpr->op == IS_DOCUMENT) appendStringInfoString(buf, " IS DOCUMENT"); else @@ -10014,6 +10412,20 @@ get_rule_expr(Node *node, deparse_context *context, } break; + case T_ReturningExpr: + { + ReturningExpr *retExpr = (ReturningExpr *) node; + + /* + * We cannot see a ReturningExpr in rule deparsing, only while + * EXPLAINing a query plan (ReturningExpr nodes are only ever + * adding during query rewriting). Just display the expression + * returned (an expanded view column). + */ + get_rule_expr((Node *) retExpr->retexpr, context, showimplicit); + } + break; + case T_PartitionBoundSpec: { PartitionBoundSpec *spec = (PartitionBoundSpec *) node; @@ -10165,7 +10577,7 @@ get_rule_expr(Node *node, deparse_context *context, get_rule_expr((Node *) lfirst(lc2), context, showimplicit); appendStringInfo(buf, " AS %s", - ((String *) lfirst_node(String, lc1))->sval); + quote_identifier(lfirst_node(String, lc1)->sval)); } } @@ -10439,7 +10851,7 @@ get_func_expr(FuncExpr *expr, deparse_context *context, argnames, argtypes, expr->funcvariadic, &use_variadic, - context->special_exprkind)); + context->inGroupBy)); nargs = 0; foreach(l, expr->args) { @@ -10509,7 +10921,7 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context, funcname = generate_function_name(aggref->aggfnoid, nargs, NIL, argtypes, aggref->aggvariadic, &use_variadic, - context->special_exprkind); + context->inGroupBy); /* Print the aggregate name, schema-qualified if needed */ appendStringInfo(buf, "%s(%s", funcname, @@ -10650,7 +11062,7 @@ get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context, if (!funcname) funcname = generate_function_name(wfunc->winfnoid, nargs, argnames, argtypes, false, NULL, - context->special_exprkind); + context->inGroupBy); appendStringInfo(buf, "%s(", funcname); @@ -10680,30 +11092,50 @@ get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context, appendStringInfoString(buf, ") OVER "); - foreach(l, context->windowClause) + if (context->windowClause) { - WindowClause *wc = (WindowClause *) lfirst(l); - - if (wc->winref == wfunc->winref) + /* Query-decompilation case: search the windowClause list */ + foreach(l, context->windowClause) { - if (wc->name) - appendStringInfoString(buf, quote_identifier(wc->name)); - else - get_rule_windowspec(wc, context->windowTList, context); - break; + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->winref == wfunc->winref) + { + if (wc->name) + appendStringInfoString(buf, quote_identifier(wc->name)); + else + get_rule_windowspec(wc, context->targetList, context); + break; + } } - } - if (l == NULL) - { - if (context->windowClause) + if (l == NULL) elog(ERROR, "could not find window clause for winref %u", wfunc->winref); - + } + else + { /* - * In EXPLAIN, we don't have window context information available, so - * we have to settle for this: + * In EXPLAIN, search the namespace stack for a matching WindowAgg + * node (probably it's always the first entry), and print winname. */ - appendStringInfoString(buf, "(?)"); + foreach(l, context->namespaces) + { + deparse_namespace *dpns = (deparse_namespace *) lfirst(l); + + if (dpns->plan && IsA(dpns->plan, WindowAgg)) + { + WindowAgg *wagg = (WindowAgg *) dpns->plan; + + if (wagg->winref == wfunc->winref) + { + appendStringInfoString(buf, quote_identifier(wagg->winname)); + break; + } + } + } + if (l == NULL) + elog(ERROR, "could not find window clause for winref %u", + wfunc->winref); } } @@ -11536,7 +11968,8 @@ get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit) if (ns_node != NULL) { get_rule_expr(expr, context, showimplicit); - appendStringInfo(buf, " AS %s", strVal(ns_node)); + appendStringInfo(buf, " AS %s", + quote_identifier(strVal(ns_node))); } else { @@ -11645,7 +12078,6 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, bool showimplicit) { StringInfo buf = context->buf; - JsonExpr *jexpr = castNode(JsonExpr, tf->docexpr); ListCell *lc_colname; ListCell *lc_coltype; ListCell *lc_coltypmod; @@ -11698,6 +12130,10 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, if (ordinality) continue; + /* + * Set default_behavior to guide get_json_expr_options() on whether to + * emit the ON ERROR / EMPTY clauses. + */ if (colexpr->op == JSON_EXISTS_OP) { appendStringInfoString(buf, " EXISTS"); @@ -11721,9 +12157,6 @@ get_json_table_columns(TableFunc *tf, JsonTablePathScan *scan, default_behavior = JSON_BEHAVIOR_NULL; } - if (jexpr->on_error->btype == JSON_BEHAVIOR_ERROR) - default_behavior = JSON_BEHAVIOR_ERROR; - appendStringInfoString(buf, " PATH "); get_json_path_spec(colexpr->path_spec, context, showimplicit); @@ -11801,7 +12234,7 @@ get_json_table(TableFunc *tf, deparse_context *context, bool showimplicit) get_json_table_columns(tf, castNode(JsonTablePathScan, tf->plan), context, showimplicit); - if (jexpr->on_error->btype != JSON_BEHAVIOR_EMPTY) + if (jexpr->on_error->btype != JSON_BEHAVIOR_EMPTY_ARRAY) get_json_behavior(jexpr->on_error, context, "ERROR"); if (PRETTY_INDENT(context)) @@ -12396,7 +12829,7 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) appendStringInfo(buf, " TABLESAMPLE %s (", generate_function_name(tablesample->tsmhandler, 1, NIL, argtypes, - false, NULL, EXPR_KIND_NONE)); + false, NULL, false)); nargs = 0; foreach(l, tablesample->args) @@ -12816,12 +13249,14 @@ generate_qualified_relation_name(Oid relid) * the output. For non-FuncExpr cases, has_variadic should be false and * use_variadic_p can be NULL. * + * inGroupBy must be true if we're deparsing a GROUP BY clause. + * * The result includes all necessary quoting and schema-prefixing. */ static char * generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p, - ParseExprKind special_exprkind) + bool inGroupBy) { char *result; HeapTuple proctup; @@ -12846,9 +13281,9 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, /* * Due to parser hacks to avoid needing to reserve CUBE, we need to force - * qualification in some special cases. + * qualification of some function names within GROUP BY. */ - if (special_exprkind == EXPR_KIND_GROUP_BY) + if (inGroupBy) { if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0) force_qualify = true; @@ -13272,21 +13707,3 @@ get_range_partbound_string(List *bound_datums) return buf->data; } - -/* - * get_list_partvalue_string - * A C string representation of one list partition value - */ -char * -get_list_partvalue_string(Const *val) -{ - deparse_context context; - StringInfo buf = makeStringInfo(); - - memset(&context, 0, sizeof(deparse_context)); - context.buf = buf; - - get_const_expr(val, &context, -1); - - return buf->data; -} diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 5f5d7959d8eba..a96b1b9c0bc69 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -10,7 +10,7 @@ * Index cost functions are located via the index AM's API struct, * which is obtained from the handler function registered in pg_am. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -121,6 +121,7 @@ #include "parser/parse_clause.h" #include "parser/parse_relation.h" #include "parser/parsetree.h" +#include "rewrite/rewriteManip.h" #include "statistics/statistics.h" #include "storage/bufmgr.h" #include "utils/acl.h" @@ -192,6 +193,8 @@ static double convert_timevalue_to_scalar(Datum value, Oid typid, bool *failure); static void examine_simple_variable(PlannerInfo *root, Var *var, VariableStatData *vardata); +static void examine_indexcol_variable(PlannerInfo *root, IndexOptInfo *index, + int indexcol, VariableStatData *vardata); static bool get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Oid collation, Datum *min, Datum *max); @@ -213,6 +216,8 @@ static bool get_actual_variable_endpoint(Relation heapRel, MemoryContext outercontext, Datum *endpointDatum); static RelOptInfo *find_join_input_rel(PlannerInfo *root, Relids relids); +static double btcost_correlation(IndexOptInfo *index, + VariableStatData *vardata); /* @@ -321,10 +326,10 @@ var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, } /* - * If we matched the var to a unique index or DISTINCT clause, assume - * there is exactly one match regardless of anything else. (This is - * slightly bogus, since the index or clause's equality operator might be - * different from ours, but it's much more likely to be right than + * If we matched the var to a unique index, DISTINCT or GROUP-BY clause, + * assume there is exactly one match regardless of anything else. (This + * is slightly bogus, since the index or clause's equality operator might + * be different from ours, but it's much more likely to be right than * ignoring the information.) */ if (vardata->isunique && vardata->rel && vardata->rel->tuples >= 1.0) @@ -483,10 +488,10 @@ var_eq_non_const(VariableStatData *vardata, Oid oproid, Oid collation, } /* - * If we matched the var to a unique index or DISTINCT clause, assume - * there is exactly one match regardless of anything else. (This is - * slightly bogus, since the index or clause's equality operator might be - * different from ours, but it's much more likely to be right than + * If we matched the var to a unique index, DISTINCT or GROUP-BY clause, + * assume there is exactly one match regardless of anything else. (This + * is slightly bogus, since the index or clause's equality operator might + * be different from ours, but it's much more likely to be right than * ignoring the information.) */ if (vardata->isunique && vardata->rel && vardata->rel->tuples >= 1.0) @@ -2131,6 +2136,9 @@ scalararraysel(PlannerInfo *root, * * Note: the result is integral, but we use "double" to avoid overflow * concerns. Most callers will use it in double-type expressions anyway. + * + * Note: in some code paths root can be passed as NULL, resulting in + * slightly worse estimates. */ double estimate_array_length(PlannerInfo *root, Node *arrayexpr) @@ -2154,7 +2162,7 @@ estimate_array_length(PlannerInfo *root, Node *arrayexpr) { return list_length(((ArrayExpr *) arrayexpr)->elements); } - else if (arrayexpr) + else if (arrayexpr && root) { /* See if we can find any statistics about it */ VariableStatData vardata; @@ -2939,7 +2947,7 @@ scalargejoinsel(PG_FUNCTION_ARGS) * first join pair is found, which will affect the join's startup time. * * clause should be a clause already known to be mergejoinable. opfamily, - * strategy, and nulls_first specify the sort ordering being used. + * cmptype, and nulls_first specify the sort ordering being used. * * The outputs are: * *leftstart is set to the fraction of the left-hand variable expected @@ -2950,7 +2958,7 @@ scalargejoinsel(PG_FUNCTION_ARGS) */ void mergejoinscansel(PlannerInfo *root, Node *clause, - Oid opfamily, int strategy, bool nulls_first, + Oid opfamily, CompareType cmptype, bool nulls_first, Selectivity *leftstart, Selectivity *leftend, Selectivity *rightstart, Selectivity *rightend) { @@ -2958,6 +2966,7 @@ mergejoinscansel(PlannerInfo *root, Node *clause, *right; VariableStatData leftvar, rightvar; + Oid opmethod; int op_strategy; Oid op_lefttype; Oid op_righttype; @@ -2971,6 +2980,10 @@ mergejoinscansel(PlannerInfo *root, Node *clause, leop, revltop, revleop; + StrategyNumber ltstrat, + lestrat, + gtstrat, + gestrat; bool isgt; Datum leftmin, leftmax, @@ -2997,12 +3010,14 @@ mergejoinscansel(PlannerInfo *root, Node *clause, examine_variable(root, left, 0, &leftvar); examine_variable(root, right, 0, &rightvar); + opmethod = get_opfamily_method(opfamily); + /* Extract the operator's declared left/right datatypes */ get_op_opfamily_properties(opno, opfamily, false, &op_strategy, &op_lefttype, &op_righttype); - Assert(op_strategy == BTEqualStrategyNumber); + Assert(IndexAmTranslateStrategy(op_strategy, opmethod, opfamily, true) == COMPARE_EQ); /* * Look up the various operators we need. If we don't find them all, it @@ -3011,19 +3026,21 @@ mergejoinscansel(PlannerInfo *root, Node *clause, * Note: we expect that pg_statistic histograms will be sorted by the '<' * operator, regardless of which sort direction we are considering. */ - switch (strategy) + switch (cmptype) { - case BTLessStrategyNumber: + case COMPARE_LT: isgt = false; + ltstrat = IndexAmTranslateCompareType(COMPARE_LT, opmethod, opfamily, true); + lestrat = IndexAmTranslateCompareType(COMPARE_LE, opmethod, opfamily, true); if (op_lefttype == op_righttype) { /* easy case */ ltop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTLessStrategyNumber); + ltstrat); leop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTLessEqualStrategyNumber); + lestrat); lsortop = ltop; rsortop = ltop; lstatop = lsortop; @@ -3035,43 +3052,46 @@ mergejoinscansel(PlannerInfo *root, Node *clause, { ltop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTLessStrategyNumber); + ltstrat); leop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTLessEqualStrategyNumber); + lestrat); lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype, - BTLessStrategyNumber); + ltstrat); rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype, - BTLessStrategyNumber); + ltstrat); lstatop = lsortop; rstatop = rsortop; revltop = get_opfamily_member(opfamily, op_righttype, op_lefttype, - BTLessStrategyNumber); + ltstrat); revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype, - BTLessEqualStrategyNumber); + lestrat); } break; - case BTGreaterStrategyNumber: + case COMPARE_GT: /* descending-order case */ isgt = true; + ltstrat = IndexAmTranslateCompareType(COMPARE_LT, opmethod, opfamily, true); + gtstrat = IndexAmTranslateCompareType(COMPARE_GT, opmethod, opfamily, true); + gestrat = IndexAmTranslateCompareType(COMPARE_GE, opmethod, opfamily, true); if (op_lefttype == op_righttype) { /* easy case */ ltop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTGreaterStrategyNumber); + gtstrat); leop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTGreaterEqualStrategyNumber); + gestrat); lsortop = ltop; rsortop = ltop; lstatop = get_opfamily_member(opfamily, op_lefttype, op_lefttype, - BTLessStrategyNumber); + ltstrat); rstatop = lstatop; revltop = ltop; revleop = leop; @@ -3080,28 +3100,28 @@ mergejoinscansel(PlannerInfo *root, Node *clause, { ltop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTGreaterStrategyNumber); + gtstrat); leop = get_opfamily_member(opfamily, op_lefttype, op_righttype, - BTGreaterEqualStrategyNumber); + gestrat); lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype, - BTGreaterStrategyNumber); + gtstrat); rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype, - BTGreaterStrategyNumber); + gtstrat); lstatop = get_opfamily_member(opfamily, op_lefttype, op_lefttype, - BTLessStrategyNumber); + ltstrat); rstatop = get_opfamily_member(opfamily, op_righttype, op_righttype, - BTLessStrategyNumber); + ltstrat); revltop = get_opfamily_member(opfamily, op_righttype, op_lefttype, - BTGreaterStrategyNumber); + gtstrat); revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype, - BTGreaterEqualStrategyNumber); + gestrat); } break; default: @@ -3303,6 +3323,15 @@ add_unique_group_var(PlannerInfo *root, List *varinfos, ndistinct = get_variable_numdistinct(vardata, &isdefault); + /* + * The nullingrels bits within the var could cause the same var to be + * counted multiple times if it's marked with different nullingrels. They + * could also prevent us from matching the var to the expressions in + * extended statistics (see estimate_multivariate_ndistinct). So strip + * them out first. + */ + var = remove_nulling_relids(var, root->outer_join_rels, NULL); + foreach(lc, varinfos) { varinfo = (GroupVarInfo *) lfirst(lc); @@ -3313,10 +3342,11 @@ add_unique_group_var(PlannerInfo *root, List *varinfos, /* * Drop known-equal vars, but only if they belong to different - * relations (see comments for estimate_num_groups) + * relations (see comments for estimate_num_groups). We aren't too + * fussy about the semantics of "equal" here. */ if (vardata->rel != varinfo->rel && - exprs_known_equal(root, var, varinfo->var)) + exprs_known_equal(root, var, varinfo->var, InvalidOid)) { if (varinfo->ndistinct <= ndistinct) { @@ -3751,6 +3781,235 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, return numdistinct; } +/* + * Try to estimate the bucket size of the hash join inner side when the join + * condition contains two or more clauses by employing extended statistics. + * + * The main idea of this approach is that the distinct value generated by + * multivariate estimation on two or more columns would provide less bucket size + * than estimation on one separate column. + * + * IMPORTANT: It is crucial to synchronize the approach of combining different + * estimations with the caller's method. + * + * Return a list of clauses that didn't fetch any extended statistics. + */ +List * +estimate_multivariate_bucketsize(PlannerInfo *root, RelOptInfo *inner, + List *hashclauses, + Selectivity *innerbucketsize) +{ + List *clauses = list_copy(hashclauses); + List *otherclauses = NIL; + double ndistinct = 1.0; + + if (list_length(hashclauses) <= 1) + + /* + * Nothing to do for a single clause. Could we employ univariate + * extended stat here? + */ + return hashclauses; + + while (clauses != NIL) + { + ListCell *lc; + int relid = -1; + List *varinfos = NIL; + List *origin_rinfos = NIL; + double mvndistinct; + List *origin_varinfos; + int group_relid = -1; + RelOptInfo *group_rel = NULL; + ListCell *lc1, + *lc2; + + /* + * Find clauses, referencing the same single base relation and try to + * estimate such a group with extended statistics. Create varinfo for + * an approved clause, push it to otherclauses, if it can't be + * estimated here or ignore to process at the next iteration. + */ + foreach(lc, clauses) + { + RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc); + Node *expr; + Relids relids; + GroupVarInfo *varinfo; + + /* + * Find the inner side of the join, which we need to estimate the + * number of buckets. Use outer_is_left because the + * clause_sides_match_join routine has called on hash clauses. + */ + relids = rinfo->outer_is_left ? + rinfo->right_relids : rinfo->left_relids; + expr = rinfo->outer_is_left ? + get_rightop(rinfo->clause) : get_leftop(rinfo->clause); + + if (bms_get_singleton_member(relids, &relid) && + root->simple_rel_array[relid]->statlist != NIL) + { + bool is_duplicate = false; + + /* + * This inner-side expression references only one relation. + * Extended statistics on this clause can exist. + */ + if (group_relid < 0) + { + RangeTblEntry *rte = root->simple_rte_array[relid]; + + if (!rte || (rte->relkind != RELKIND_RELATION && + rte->relkind != RELKIND_MATVIEW && + rte->relkind != RELKIND_FOREIGN_TABLE && + rte->relkind != RELKIND_PARTITIONED_TABLE)) + { + /* Extended statistics can't exist in principle */ + otherclauses = lappend(otherclauses, rinfo); + clauses = foreach_delete_current(clauses, lc); + continue; + } + + group_relid = relid; + group_rel = root->simple_rel_array[relid]; + } + else if (group_relid != relid) + + /* + * Being in the group forming state we don't need other + * clauses. + */ + continue; + + /* + * We're going to add the new clause to the varinfos list. We + * might re-use add_unique_group_var(), but we don't do so for + * two reasons. + * + * 1) We must keep the origin_rinfos list ordered exactly the + * same way as varinfos. + * + * 2) add_unique_group_var() is designed for + * estimate_num_groups(), where a larger number of groups is + * worse. While estimating the number of hash buckets, we + * have the opposite: a lesser number of groups is worse. + * Therefore, we don't have to remove "known equal" vars: the + * removed var may valuably contribute to the multivariate + * statistics to grow the number of groups. + */ + + /* + * Clear nullingrels to correctly match hash keys. See + * add_unique_group_var()'s comment for details. + */ + expr = remove_nulling_relids(expr, root->outer_join_rels, NULL); + + /* + * Detect and exclude exact duplicates from the list of hash + * keys (like add_unique_group_var does). + */ + foreach(lc1, varinfos) + { + varinfo = (GroupVarInfo *) lfirst(lc1); + + if (!equal(expr, varinfo->var)) + continue; + + is_duplicate = true; + break; + } + + if (is_duplicate) + { + /* + * Skip exact duplicates. Adding them to the otherclauses + * list also doesn't make sense. + */ + continue; + } + + /* + * Initialize GroupVarInfo. We only use it to call + * estimate_multivariate_ndistinct(), which doesn't care about + * ndistinct and isdefault fields. Thus, skip these fields. + */ + varinfo = (GroupVarInfo *) palloc0(sizeof(GroupVarInfo)); + varinfo->var = expr; + varinfo->rel = root->simple_rel_array[relid]; + varinfos = lappend(varinfos, varinfo); + + /* + * Remember the link to RestrictInfo for the case the clause + * is failed to be estimated. + */ + origin_rinfos = lappend(origin_rinfos, rinfo); + } + else + { + /* This clause can't be estimated with extended statistics */ + otherclauses = lappend(otherclauses, rinfo); + } + + clauses = foreach_delete_current(clauses, lc); + } + + if (list_length(varinfos) < 2) + { + /* + * Multivariate statistics doesn't apply to single columns except + * for expressions, but it has not been implemented yet. + */ + otherclauses = list_concat(otherclauses, origin_rinfos); + list_free_deep(varinfos); + list_free(origin_rinfos); + continue; + } + + Assert(group_rel != NULL); + + /* Employ the extended statistics. */ + origin_varinfos = varinfos; + for (;;) + { + bool estimated = estimate_multivariate_ndistinct(root, + group_rel, + &varinfos, + &mvndistinct); + + if (!estimated) + break; + + /* + * We've got an estimation. Use ndistinct value in a consistent + * way - according to the caller's logic (see + * final_cost_hashjoin). + */ + if (ndistinct < mvndistinct) + ndistinct = mvndistinct; + Assert(ndistinct >= 1.0); + } + + Assert(list_length(origin_varinfos) == list_length(origin_rinfos)); + + /* Collect unmatched clauses as otherclauses. */ + forboth(lc1, origin_varinfos, lc2, origin_rinfos) + { + GroupVarInfo *vinfo = lfirst(lc1); + + if (!list_member_ptr(varinfos, vinfo)) + /* Already estimated */ + continue; + + /* Can't be estimated here - push to the returning list */ + otherclauses = lappend(otherclauses, lfirst(lc2)); + } + } + + *innerbucketsize = 1.0 / ndistinct; + return otherclauses; +} + /* * Estimate hash bucket statistics when the specified expression is used * as a hash key for the given number of buckets. @@ -3941,14 +4200,18 @@ estimate_hashagg_tablesize(PlannerInfo *root, Path *path, */ /* - * Find applicable ndistinct statistics for the given list of VarInfos (which - * must all belong to the given rel), and update *ndistinct to the estimate of - * the MVNDistinctItem that best matches. If a match it found, *varinfos is - * updated to remove the list of matched varinfos. + * Find the best matching ndistinct extended statistics for the given list of + * GroupVarInfos. * - * Varinfos that aren't for simple Vars are ignored. + * Callers must ensure that the given GroupVarInfos all belong to 'rel' and + * the GroupVarInfos list does not contain any duplicate Vars or expressions. * - * Return true if we're able to find a match, false otherwise. + * When statistics are found that match > 1 of the given GroupVarInfo, the + * *ndistinct parameter is set according to the ndistinct estimate and a new + * list is built with the matching GroupVarInfos removed, which is output via + * the *varinfos parameter before returning true. When no matching stats are + * found, false is returned and the *varinfos and *ndistinct parameters are + * left untouched. */ static bool estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel, @@ -4029,15 +4292,22 @@ estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel, } } + /* + * The ndistinct extended statistics contain estimates for a minimum + * of pairs of columns which the statistics are defined on and + * certainly not single columns. Here we skip unless we managed to + * match to at least two columns. + */ if (nshared_vars + nshared_exprs < 2) continue; /* - * Does this statistics object match more columns than the currently - * best object? If so, use this one instead. + * Check if these statistics are a better match than the previous best + * match and if so, take note of the StatisticExtInfo. * - * XXX This should break ties using name of the object, or something - * like that, to make the outcome stable. + * The statslist is sorted by statOid, so the StatisticExtInfo we + * select as the best match is deterministic even when multiple sets + * of statistics match equally as well. */ if ((nshared_exprs > nmatches_exprs) || (((nshared_exprs == nmatches_exprs)) && (nshared_vars > nmatches_vars))) @@ -4638,13 +4908,14 @@ convert_one_string_to_scalar(char *value, int rangelo, int rangehi) * On failure (e.g., unsupported typid), set *failure to true; * otherwise, that variable is not changed. (We'll return NULL on failure.) * - * When using a non-C locale, we must pass the string through strxfrm() + * When using a non-C locale, we must pass the string through pg_strxfrm() * before continuing, so as to generate correct locale-specific results. */ static char * convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure) { char *val; + pg_locale_t mylocale; switch (typid) { @@ -4670,7 +4941,9 @@ convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure) return NULL; } - if (!lc_collate_is_c(collid)) + mylocale = pg_newlocale_from_collation(collid); + + if (!mylocale->collate_is_c) { char *xfrmstr; size_t xfrmlen; @@ -4678,14 +4951,18 @@ convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure) /* * XXX: We could guess at a suitable output buffer size and only call - * strxfrm twice if our guess is too small. + * pg_strxfrm() twice if our guess is too small. * * XXX: strxfrm doesn't support UTF-8 encoding on Win32, it can return * bogus data or set an error. This is not really a problem unless it * crashes since it will only give an estimation error and nothing * fatal. + * + * XXX: we do not check pg_strxfrm_enabled(). On some platforms and in + * some cases, libc strxfrm() may return the wrong results, but that + * will only lead to an estimation error. */ - xfrmlen = strxfrm(NULL, val, 0); + xfrmlen = pg_strxfrm(NULL, val, 0, mylocale); #ifdef WIN32 /* @@ -4697,7 +4974,7 @@ convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure) return val; #endif xfrmstr = (char *) palloc(xfrmlen + 1); - xfrmlen2 = strxfrm(xfrmstr, val, xfrmlen + 1); + xfrmlen2 = pg_strxfrm(xfrmstr, val, xfrmlen + 1, mylocale); /* * Some systems (e.g., glibc) can return a smaller value from the @@ -4997,11 +5274,11 @@ ReleaseDummy(HeapTuple tuple) * atttype, atttypmod: actual type/typmod of the "var" expression. This is * commonly the same as the exposed type of the variable argument, * but can be different in binary-compatible-type cases. - * isunique: true if we were able to match the var to a unique index or a - * single-column DISTINCT clause, implying its values are unique for - * this query. (Caution: this should be trusted for statistical - * purposes only, since we do not check indimmediate nor verify that - * the exact same definition of equality applies.) + * isunique: true if we were able to match the var to a unique index, a + * single-column DISTINCT or GROUP-BY clause, implying its values are + * unique for this query. (Caution: this should be trusted for + * statistical purposes only, since we do not check indimmediate nor + * verify that the exact same definition of equality applies.) * acl_ok: true if current user has permission to read the column(s) * underlying the pg_statistic entry. This is consulted by * statistic_proc_security_check(). @@ -5014,6 +5291,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, { Node *basenode; Relids varnos; + Relids basevarnos; RelOptInfo *onerel; /* Make sure we don't return dangling pointers in vardata */ @@ -5055,10 +5333,11 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, * relation are considered "real" vars. */ varnos = pull_varnos(root, basenode); + basevarnos = bms_difference(varnos, root->outer_join_rels); onerel = NULL; - if (bms_is_empty(varnos)) + if (bms_is_empty(basevarnos)) { /* No Vars at all ... must be pseudo-constant clause */ } @@ -5066,7 +5345,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, { int relid; - if (bms_get_singleton_member(varnos, &relid)) + /* Check if the expression is in vars of a single base relation */ + if (bms_get_singleton_member(basevarnos, &relid)) { if (varRelid == 0 || varRelid == relid) { @@ -5096,7 +5376,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, } } - bms_free(varnos); + bms_free(basevarnos); vardata->var = node; vardata->atttype = exprType(node); @@ -5121,6 +5401,14 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, ListCell *slist; Oid userid; + /* + * The nullingrels bits within the expression could prevent us from + * matching it to expressional index columns or to the expressions in + * extended statistics. So strip them out first. + */ + if (bms_overlap(varnos, root->outer_join_rels)) + node = remove_nulling_relids(node, root->outer_join_rels, NULL); + /* * Determine the user ID to use for privilege checks: either * onerel->userid if it's set (e.g., in case we're accessing the table @@ -5391,6 +5679,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid, } } } + + bms_free(varnos); } /* @@ -5646,15 +5936,14 @@ examine_simple_variable(PlannerInfo *root, Var *var, Assert(IsA(subquery, Query)); /* - * Punt if subquery uses set operations or GROUP BY, as these will - * mash underlying columns' stats beyond recognition. (Set ops are - * particularly nasty; if we forged ahead, we would return stats + * Punt if subquery uses set operations or grouping sets, as these + * will mash underlying columns' stats beyond recognition. (Set ops + * are particularly nasty; if we forged ahead, we would return stats * relevant to only the leftmost subselect...) DISTINCT is also * problematic, but we check that later because there is a possibility * of learning something even with it. */ if (subquery->setOperations || - subquery->groupClause || subquery->groupingSets) return; @@ -5684,6 +5973,16 @@ examine_simple_variable(PlannerInfo *root, Var *var, return; } + /* The same idea as with DISTINCT clause works for a GROUP-BY too */ + if (subquery->groupClause) + { + if (list_length(subquery->groupClause) == 1 && + targetIsInSortList(ste, InvalidOid, subquery->groupClause)) + vardata->isunique = true; + /* cannot go further */ + return; + } + /* * If the sub-query originated from a view with the security_barrier * attribute, we must not look at the variable's statistics, though it @@ -5725,11 +6024,97 @@ examine_simple_variable(PlannerInfo *root, Var *var, } } +/* + * examine_indexcol_variable + * Try to look up statistical data about an index column/expression. + * Fill in a VariableStatData struct to describe the column. + * + * Inputs: + * root: the planner info + * index: the index whose column we're interested in + * indexcol: 0-based index column number (subscripts index->indexkeys[]) + * + * Outputs: *vardata is filled as follows: + * var: the input expression (with any binary relabeling stripped, if + * it is or contains a variable; but otherwise the type is preserved) + * rel: RelOptInfo for table relation containing variable. + * statsTuple: the pg_statistic entry for the variable, if one exists; + * otherwise NULL. + * freefunc: pointer to a function to release statsTuple with. + * + * Caller is responsible for doing ReleaseVariableStats() before exiting. + */ +static void +examine_indexcol_variable(PlannerInfo *root, IndexOptInfo *index, + int indexcol, VariableStatData *vardata) +{ + AttrNumber colnum; + Oid relid; + + if (index->indexkeys[indexcol] != 0) + { + /* Simple variable --- look to stats for the underlying table */ + RangeTblEntry *rte = planner_rt_fetch(index->rel->relid, root); + + Assert(rte->rtekind == RTE_RELATION); + relid = rte->relid; + Assert(relid != InvalidOid); + colnum = index->indexkeys[indexcol]; + vardata->rel = index->rel; + + if (get_relation_stats_hook && + (*get_relation_stats_hook) (root, rte, colnum, vardata)) + { + /* + * The hook took control of acquiring a stats tuple. If it did + * supply a tuple, it'd better have supplied a freefunc. + */ + if (HeapTupleIsValid(vardata->statsTuple) && + !vardata->freefunc) + elog(ERROR, "no function provided to release variable stats with"); + } + else + { + vardata->statsTuple = SearchSysCache3(STATRELATTINH, + ObjectIdGetDatum(relid), + Int16GetDatum(colnum), + BoolGetDatum(rte->inh)); + vardata->freefunc = ReleaseSysCache; + } + } + else + { + /* Expression --- maybe there are stats for the index itself */ + relid = index->indexoid; + colnum = indexcol + 1; + + if (get_index_stats_hook && + (*get_index_stats_hook) (root, relid, colnum, vardata)) + { + /* + * The hook took control of acquiring a stats tuple. If it did + * supply a tuple, it'd better have supplied a freefunc. + */ + if (HeapTupleIsValid(vardata->statsTuple) && + !vardata->freefunc) + elog(ERROR, "no function provided to release variable stats with"); + } + else + { + vardata->statsTuple = SearchSysCache3(STATRELATTINH, + ObjectIdGetDatum(relid), + Int16GetDatum(colnum), + BoolGetDatum(false)); + vardata->freefunc = ReleaseSysCache; + } + } +} + /* * Check whether it is permitted to call func_oid passing some of the * pg_statistic data in vardata. We allow this either if the user has SELECT * privileges on the table or column underlying the pg_statistic data or if - * the function is marked leak-proof. + * the function is marked leakproof. */ bool statistic_proc_security_check(VariableStatData *vardata, Oid func_oid) @@ -5744,7 +6129,7 @@ statistic_proc_security_check(VariableStatData *vardata, Oid func_oid) return true; ereport(DEBUG2, - (errmsg_internal("not using statistics because function \"%s\" is not leak-proof", + (errmsg_internal("not using statistics because function \"%s\" is not leakproof", get_func_name(func_oid)))); return false; } @@ -5835,11 +6220,11 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault) } /* - * If there is a unique index or DISTINCT clause for the variable, assume - * it is unique no matter what pg_statistic says; the statistics could be - * out of date, or we might have found a partial unique index that proves - * the var is unique for this query. However, we'd better still believe - * the null-fraction statistic. + * If there is a unique index, DISTINCT or GROUP-BY clause for the + * variable, assume it is unique no matter what pg_statistic says; the + * statistics could be out of date, or we might have found a partial + * unique index that proves the var is unique for this query. However, + * we'd better still believe the null-fraction statistic. */ if (vardata->isunique) stadistinct = -1.0 * (1.0 - stanullfrac); @@ -6109,9 +6494,10 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, { IndexOptInfo *index = (IndexOptInfo *) lfirst(lc); ScanDirection indexscandir; + StrategyNumber strategy; - /* Ignore non-btree indexes */ - if (index->relam != BTREE_AM_OID) + /* Ignore non-ordering indexes */ + if (index->sortopfamily == NULL) continue; /* @@ -6136,15 +6522,16 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, continue; /* test first 'cause it's cheapest */ if (!match_index_to_operand(vardata->var, 0, index)) continue; - switch (get_op_opfamily_strategy(sortop, index->sortopfamily[0])) + strategy = get_op_opfamily_strategy(sortop, index->sortopfamily[0]); + switch (IndexAmTranslateStrategy(strategy, index->relam, index->sortopfamily[0], true)) { - case BTLessStrategyNumber: + case COMPARE_LT: if (index->reverse_sort[0]) indexscandir = BackwardScanDirection; else indexscandir = ForwardScanDirection; break; - case BTGreaterStrategyNumber: + case COMPARE_GT: if (index->reverse_sort[0]) indexscandir = ForwardScanDirection; else @@ -6333,7 +6720,7 @@ get_actual_variable_endpoint(Relation heapRel, GlobalVisTestFor(heapRel)); index_scan = index_beginscan(heapRel, indexRel, - &SnapshotNonVacuumable, + &SnapshotNonVacuumable, NULL, 1, 0); /* Set it up for index-only scan */ index_scan->xs_want_itup = true; @@ -6384,13 +6771,17 @@ get_actual_variable_endpoint(Relation heapRel, } /* - * We expect that btree will return data in IndexTuple not HeapTuple - * format. It's not lossy either. + * We expect that the index will return data in IndexTuple not + * HeapTuple format. */ if (!index_scan->xs_itup) elog(ERROR, "no data returned for index-only scan"); + + /* + * We do not yet support recheck here. + */ if (index_scan->xs_recheck) - elog(ERROR, "unexpected recheck indication from btree"); + break; /* OK to deconstruct the index tuple */ index_deform_tuple(index_scan->xs_itup, @@ -6783,6 +7174,53 @@ add_predicate_to_index_quals(IndexOptInfo *index, List *indexQuals) return list_concat(predExtraQuals, indexQuals); } +/* + * Estimate correlation of btree index's first column. + * + * If we can get an estimate of the first column's ordering correlation C + * from pg_statistic, estimate the index correlation as C for a single-column + * index, or C * 0.75 for multiple columns. The idea here is that multiple + * columns dilute the importance of the first column's ordering, but don't + * negate it entirely. + * + * We already filled in the stats tuple for *vardata when called. + */ +static double +btcost_correlation(IndexOptInfo *index, VariableStatData *vardata) +{ + Oid sortop; + AttStatsSlot sslot; + double indexCorrelation = 0; + + Assert(HeapTupleIsValid(vardata->statsTuple)); + + sortop = get_opfamily_member(index->opfamily[0], + index->opcintype[0], + index->opcintype[0], + BTLessStrategyNumber); + if (OidIsValid(sortop) && + get_attstatsslot(&sslot, vardata->statsTuple, + STATISTIC_KIND_CORRELATION, sortop, + ATTSTATSSLOT_NUMBERS)) + { + double varCorrelation; + + Assert(sslot.nnumbers == 1); + varCorrelation = sslot.numbers[0]; + + if (index->reverse_sort[0]) + varCorrelation = -varCorrelation; + + if (index->nkeycolumns > 1) + indexCorrelation = varCorrelation * 0.75; + else + indexCorrelation = varCorrelation; + + free_attstatsslot(&sslot); + } + + return indexCorrelation; +} void btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, @@ -6792,17 +7230,19 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, { IndexOptInfo *index = path->indexinfo; GenericCosts costs = {0}; - Oid relid; - AttrNumber colnum; VariableStatData vardata = {0}; double numIndexTuples; Cost descentCost; List *indexBoundQuals; + List *indexSkipQuals; int indexcol; bool eqQualHere; - bool found_saop; + bool found_row_compare; + bool found_array; bool found_is_null_op; + bool have_correlation = false; double num_sa_scans; + double correlation = 0.0; ListCell *lc; /* @@ -6813,19 +7253,24 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, * it's OK to count them in indexSelectivity, but they should not count * for estimating numIndexTuples. So we must examine the given indexquals * to find out which ones count as boundary quals. We rely on the - * knowledge that they are given in index column order. + * knowledge that they are given in index column order. Note that nbtree + * preprocessing can add skip arrays that act as leading '=' quals in the + * absence of ordinary input '=' quals, so in practice _most_ input quals + * are able to act as index bound quals (which we take into account here). * * For a RowCompareExpr, we consider only the first column, just as * rowcomparesel() does. * - * If there's a ScalarArrayOpExpr in the quals, we'll actually perform up - * to N index descents (not just one), but the ScalarArrayOpExpr's + * If there's a SAOP or skip array in the quals, we'll actually perform up + * to N index descents (not just one), but the underlying array key's * operator can be considered to act the same as it normally does. */ indexBoundQuals = NIL; + indexSkipQuals = NIL; indexcol = 0; eqQualHere = false; - found_saop = false; + found_row_compare = false; + found_array = false; found_is_null_op = false; num_sa_scans = 1; foreach(lc, path->indexclauses) @@ -6833,17 +7278,203 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, IndexClause *iclause = lfirst_node(IndexClause, lc); ListCell *lc2; - if (indexcol != iclause->indexcol) + if (indexcol < iclause->indexcol) { - /* Beginning of a new column's quals */ - if (!eqQualHere) - break; /* done if no '=' qual for indexcol */ + double num_sa_scans_prev_cols = num_sa_scans; + + /* + * Beginning of a new column's quals. + * + * Skip scans use skip arrays, which are ScalarArrayOp style + * arrays that generate their elements procedurally and on demand. + * Given a multi-column index on "(a, b)", and an SQL WHERE clause + * "WHERE b = 42", a skip scan will effectively use an indexqual + * "WHERE a = ANY('{every col a value}') AND b = 42". (Obviously, + * the array on "a" must also return "IS NULL" matches, since our + * WHERE clause used no strict operator on "a"). + * + * Here we consider how nbtree will backfill skip arrays for any + * index columns that lacked an '=' qual. This maintains our + * num_sa_scans estimate, and determines if this new column (the + * "iclause->indexcol" column, not the prior "indexcol" column) + * can have its RestrictInfos/quals added to indexBoundQuals. + * + * We'll need to handle columns that have inequality quals, where + * the skip array generates values from a range constrained by the + * quals (not every possible value). We've been maintaining + * indexSkipQuals to help with this; it will now contain all of + * the prior column's quals (that is, indexcol's quals) when they + * might be used for this. + */ + if (found_row_compare) + { + /* + * Skip arrays can't be added after a RowCompare input qual + * due to limitations in nbtree + */ + break; + } + if (eqQualHere) + { + /* + * Don't need to add a skip array for an indexcol that already + * has an '=' qual/equality constraint + */ + indexcol++; + indexSkipQuals = NIL; + } eqQualHere = false; - indexcol++; + + while (indexcol < iclause->indexcol) + { + double ndistinct; + bool isdefault = true; + + found_array = true; + + /* + * A skipped attribute's ndistinct forms the basis of our + * estimate of the total number of "array elements" used by + * its skip array at runtime. Look that up first. + */ + examine_indexcol_variable(root, index, indexcol, &vardata); + ndistinct = get_variable_numdistinct(&vardata, &isdefault); + + if (indexcol == 0) + { + /* + * Get an estimate of the leading column's correlation in + * passing (avoids rereading variable stats below) + */ + if (HeapTupleIsValid(vardata.statsTuple)) + correlation = btcost_correlation(index, &vardata); + have_correlation = true; + } + + ReleaseVariableStats(vardata); + + /* + * If ndistinct is a default estimate, conservatively assume + * that no skipping will happen at runtime + */ + if (isdefault) + { + num_sa_scans = num_sa_scans_prev_cols; + break; /* done building indexBoundQuals */ + } + + /* + * Apply indexcol's indexSkipQuals selectivity to ndistinct + */ + if (indexSkipQuals != NIL) + { + List *partialSkipQuals; + Selectivity ndistinctfrac; + + /* + * If the index is partial, AND the index predicate with + * the index-bound quals to produce a more accurate idea + * of the number of distinct values for prior indexcol + */ + partialSkipQuals = add_predicate_to_index_quals(index, + indexSkipQuals); + + ndistinctfrac = clauselist_selectivity(root, partialSkipQuals, + index->rel->relid, + JOIN_INNER, + NULL); + + /* + * If ndistinctfrac is selective (on its own), the scan is + * unlikely to benefit from repositioning itself using + * later quals. Do not allow iclause->indexcol's quals to + * be added to indexBoundQuals (it would increase descent + * costs, without lowering numIndexTuples costs by much). + */ + if (ndistinctfrac < DEFAULT_RANGE_INEQ_SEL) + { + num_sa_scans = num_sa_scans_prev_cols; + break; /* done building indexBoundQuals */ + } + + /* Adjust ndistinct downward */ + ndistinct = rint(ndistinct * ndistinctfrac); + ndistinct = Max(ndistinct, 1); + } + + /* + * When there's no inequality quals, account for the need to + * find an initial value by counting -inf/+inf as a value. + * + * We don't charge anything extra for possible next/prior key + * index probes, which are sometimes used to find the next + * valid skip array element (ahead of using the located + * element value to relocate the scan to the next position + * that might contain matching tuples). It seems hard to do + * better here. Use of the skip support infrastructure often + * avoids most next/prior key probes. But even when it can't, + * there's a decent chance that most individual next/prior key + * probes will locate a leaf page whose key space overlaps all + * of the scan's keys (even the lower-order keys) -- which + * also avoids the need for a separate, extra index descent. + * Note also that these probes are much cheaper than non-probe + * primitive index scans: they're reliably very selective. + */ + if (indexSkipQuals == NIL) + ndistinct += 1; + + /* + * Update num_sa_scans estimate by multiplying by ndistinct. + * + * We make the pessimistic assumption that there is no + * naturally occurring cross-column correlation. This is + * often wrong, but it seems best to err on the side of not + * expecting skipping to be helpful... + */ + num_sa_scans *= ndistinct; + + /* + * ...but back out of adding this latest group of 1 or more + * skip arrays when num_sa_scans exceeds the total number of + * index pages (revert to num_sa_scans from before indexcol). + * This causes a sharp discontinuity in cost (as a function of + * the indexcol's ndistinct), but that is representative of + * actual runtime costs. + * + * Note that skipping is helpful when each primitive index + * scan only manages to skip over 1 or 2 irrelevant leaf pages + * on average. Skip arrays bring savings in CPU costs due to + * the scan not needing to evaluate indexquals against every + * tuple, which can greatly exceed any savings in I/O costs. + * This test is a test of whether num_sa_scans implies that + * we're past the point where the ability to skip ceases to + * lower the scan's costs (even qual evaluation CPU costs). + */ + if (index->pages < num_sa_scans) + { + num_sa_scans = num_sa_scans_prev_cols; + break; /* done building indexBoundQuals */ + } + + indexcol++; + indexSkipQuals = NIL; + } + + /* + * Finished considering the need to add skip arrays to bridge an + * initial eqQualHere gap between the old and new index columns + * (or there was no initial eqQualHere gap in the first place). + * + * If an initial gap could not be bridged, then new column's quals + * (i.e. iclause->indexcol's quals) won't go into indexBoundQuals, + * and so won't affect our final numIndexTuples estimate. + */ if (indexcol != iclause->indexcol) - break; /* no quals at all for indexcol */ + break; /* done building indexBoundQuals */ } + Assert(indexcol == iclause->indexcol); + /* Examine each indexqual associated with this index clause */ foreach(lc2, iclause->indexquals) { @@ -6863,6 +7494,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, RowCompareExpr *rc = (RowCompareExpr *) clause; clause_op = linitial_oid(rc->opnos); + found_row_compare = true; } else if (IsA(clause, ScalarArrayOpExpr)) { @@ -6871,7 +7503,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, double alength = estimate_array_length(root, other_operand); clause_op = saop->opno; - found_saop = true; + found_array = true; /* estimate SA descents by indexBoundQuals only */ if (alength > 1) num_sa_scans *= alength; @@ -6883,7 +7515,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, if (nt->nulltesttype == IS_NULL) { found_is_null_op = true; - /* IS NULL is like = for selectivity purposes */ + /* IS NULL is like = for selectivity/skip scan purposes */ eqQualHere = true; } } @@ -6902,19 +7534,28 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, } indexBoundQuals = lappend(indexBoundQuals, rinfo); + + /* + * We apply inequality selectivities to estimate index descent + * costs with scans that use skip arrays. Save this indexcol's + * RestrictInfos if it looks like they'll be needed for that. + */ + if (!eqQualHere && !found_row_compare && + indexcol < index->nkeycolumns - 1) + indexSkipQuals = lappend(indexSkipQuals, rinfo); } } /* * If index is unique and we found an '=' clause for each column, we can * just assume numIndexTuples = 1 and skip the expensive - * clauselist_selectivity calculations. However, a ScalarArrayOp or - * NullTest invalidates that theory, even though it sets eqQualHere. + * clauselist_selectivity calculations. However, an array or NullTest + * always invalidates that theory (even when eqQualHere has been set). */ if (index->unique && indexcol == index->nkeycolumns - 1 && eqQualHere && - !found_saop && + !found_array && !found_is_null_op) numIndexTuples = 1.0; else @@ -6936,7 +7577,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, numIndexTuples = btreeSelectivity * index->rel->tuples; /* - * btree automatically combines individual ScalarArrayOpExpr primitive + * btree automatically combines individual array element primitive * index scans whenever the tuples covered by the next set of array * keys are close to tuples covered by the current set. That puts a * natural ceiling on the worst case number of descents -- there @@ -6954,16 +7595,18 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, * of leaf pages (we make it 1/3 the total number of pages instead) to * give the btree code credit for its ability to continue on the leaf * level with low selectivity scans. + * + * Note: num_sa_scans includes both ScalarArrayOp array elements and + * skip array elements whose qual affects our numIndexTuples estimate. */ num_sa_scans = Min(num_sa_scans, ceil(index->pages * 0.3333333)); num_sa_scans = Max(num_sa_scans, 1); /* - * As in genericcostestimate(), we have to adjust for any - * ScalarArrayOpExpr quals included in indexBoundQuals, and then round - * to integer. + * As in genericcostestimate(), we have to adjust for any array quals + * included in indexBoundQuals, and then round to integer. * - * It is tempting to make genericcostestimate behave as if SAOP + * It is tempting to make genericcostestimate behave as if array * clauses work in almost the same way as scalar operators during * btree scans, making the top-level scan look like a continuous scan * (as opposed to num_sa_scans-many primitive index scans). After @@ -6996,7 +7639,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, * comparisons to descend a btree of N leaf tuples. We charge one * cpu_operator_cost per comparison. * - * If there are ScalarArrayOpExprs, charge this once per estimated SA + * If there are SAOP or skip array keys, charge this once per estimated * index descent. The ones after the first one are not startup cost so * far as the overall plan goes, so just add them to "total" cost. */ @@ -7016,110 +7659,25 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, * cost is somewhat arbitrarily set at 50x cpu_operator_cost per page * touched. The number of such pages is btree tree height plus one (ie, * we charge for the leaf page too). As above, charge once per estimated - * SA index descent. + * SAOP/skip array descent. */ descentCost = (index->tree_height + 1) * DEFAULT_PAGE_CPU_MULTIPLIER * cpu_operator_cost; costs.indexStartupCost += descentCost; costs.indexTotalCost += costs.num_sa_scans * descentCost; - /* - * If we can get an estimate of the first column's ordering correlation C - * from pg_statistic, estimate the index correlation as C for a - * single-column index, or C * 0.75 for multiple columns. (The idea here - * is that multiple columns dilute the importance of the first column's - * ordering, but don't negate it entirely. Before 8.0 we divided the - * correlation by the number of columns, but that seems too strong.) - */ - if (index->indexkeys[0] != 0) + if (!have_correlation) { - /* Simple variable --- look to stats for the underlying table */ - RangeTblEntry *rte = planner_rt_fetch(index->rel->relid, root); - - Assert(rte->rtekind == RTE_RELATION); - relid = rte->relid; - Assert(relid != InvalidOid); - colnum = index->indexkeys[0]; - - if (get_relation_stats_hook && - (*get_relation_stats_hook) (root, rte, colnum, &vardata)) - { - /* - * The hook took control of acquiring a stats tuple. If it did - * supply a tuple, it'd better have supplied a freefunc. - */ - if (HeapTupleIsValid(vardata.statsTuple) && - !vardata.freefunc) - elog(ERROR, "no function provided to release variable stats with"); - } - else - { - vardata.statsTuple = SearchSysCache3(STATRELATTINH, - ObjectIdGetDatum(relid), - Int16GetDatum(colnum), - BoolGetDatum(rte->inh)); - vardata.freefunc = ReleaseSysCache; - } + examine_indexcol_variable(root, index, 0, &vardata); + if (HeapTupleIsValid(vardata.statsTuple)) + costs.indexCorrelation = btcost_correlation(index, &vardata); + ReleaseVariableStats(vardata); } else { - /* Expression --- maybe there are stats for the index itself */ - relid = index->indexoid; - colnum = 1; - - if (get_index_stats_hook && - (*get_index_stats_hook) (root, relid, colnum, &vardata)) - { - /* - * The hook took control of acquiring a stats tuple. If it did - * supply a tuple, it'd better have supplied a freefunc. - */ - if (HeapTupleIsValid(vardata.statsTuple) && - !vardata.freefunc) - elog(ERROR, "no function provided to release variable stats with"); - } - else - { - vardata.statsTuple = SearchSysCache3(STATRELATTINH, - ObjectIdGetDatum(relid), - Int16GetDatum(colnum), - BoolGetDatum(false)); - vardata.freefunc = ReleaseSysCache; - } - } - - if (HeapTupleIsValid(vardata.statsTuple)) - { - Oid sortop; - AttStatsSlot sslot; - - sortop = get_opfamily_member(index->opfamily[0], - index->opcintype[0], - index->opcintype[0], - BTLessStrategyNumber); - if (OidIsValid(sortop) && - get_attstatsslot(&sslot, vardata.statsTuple, - STATISTIC_KIND_CORRELATION, sortop, - ATTSTATSSLOT_NUMBERS)) - { - double varCorrelation; - - Assert(sslot.nnumbers == 1); - varCorrelation = sslot.numbers[0]; - - if (index->reverse_sort[0]) - varCorrelation = -varCorrelation; - - if (index->nkeycolumns > 1) - costs.indexCorrelation = varCorrelation * 0.75; - else - costs.indexCorrelation = varCorrelation; - - free_attstatsslot(&sslot); - } + /* btcost_correlation already called earlier on */ + costs.indexCorrelation = correlation; } - ReleaseVariableStats(vardata); - *indexStartupCost = costs.indexStartupCost; *indexTotalCost = costs.indexTotalCost; *indexSelectivity = costs.indexSelectivity; diff --git a/src/backend/utils/adt/skipsupport.c b/src/backend/utils/adt/skipsupport.c new file mode 100644 index 0000000000000..2bd35d2d27221 --- /dev/null +++ b/src/backend/utils/adt/skipsupport.c @@ -0,0 +1,61 @@ +/*------------------------------------------------------------------------- + * + * skipsupport.c + * Support routines for B-Tree skip scan. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/utils/adt/skipsupport.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/nbtree.h" +#include "utils/lsyscache.h" +#include "utils/skipsupport.h" + +/* + * Fill in SkipSupport given an operator class (opfamily + opcintype). + * + * On success, returns skip support struct, allocating in caller's memory + * context. Otherwise returns NULL, indicating that operator class has no + * skip support function. + */ +SkipSupport +PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype, bool reverse) +{ + Oid skipSupportFunction; + SkipSupport sksup; + + /* Look for a skip support function */ + skipSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype, + BTSKIPSUPPORT_PROC); + if (!OidIsValid(skipSupportFunction)) + return NULL; + + sksup = palloc(sizeof(SkipSupportData)); + OidFunctionCall1(skipSupportFunction, PointerGetDatum(sksup)); + + if (reverse) + { + /* + * DESC/reverse case: swap low_elem with high_elem, and swap decrement + * with increment + */ + Datum low_elem = sksup->low_elem; + SkipSupportIncDec decrement = sksup->decrement; + + sksup->low_elem = sksup->high_elem; + sksup->decrement = sksup->increment; + + sksup->high_elem = low_elem; + sksup->increment = decrement; + } + + return sksup; +} diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c index dd46001a4eba5..1b0df1117171a 100644 --- a/src/backend/utils/adt/tid.c +++ b/src/backend/utils/adt/tid.c @@ -3,7 +3,7 @@ * tid.c * Functions for the built-in type tuple id * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 69fe7860ede06..347089b762646 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -3,7 +3,7 @@ * timestamp.c * Functions for the built-in SQL types "timestamp" and "interval". * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -27,9 +27,9 @@ #include "funcapi.h" #include "libpq/pqformat.h" #include "miscadmin.h" -#include "optimizer/optimizer.h" #include "nodes/nodeFuncs.h" #include "nodes/supportnodes.h" +#include "optimizer/optimizer.h" #include "parser/scansup.h" #include "utils/array.h" #include "utils/builtins.h" @@ -37,6 +37,7 @@ #include "utils/datetime.h" #include "utils/float.h" #include "utils/numeric.h" +#include "utils/skipsupport.h" #include "utils/sortsupport.h" /* @@ -618,19 +619,8 @@ make_timestamp_internal(int year, int month, int day, time = (((hour * MINS_PER_HOUR + min) * SECS_PER_MINUTE) * USECS_PER_SEC) + (int64) rint(sec * USECS_PER_SEC); - result = date * USECS_PER_DAY + time; - /* check for major overflow */ - if ((result - time) / USECS_PER_DAY != date) - ereport(ERROR, - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), - errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g", - year, month, day, - hour, min, sec))); - - /* check for just-barely overflow (okay except time-of-day wraps) */ - /* caution: we want to allow 1999-12-31 24:00:00 */ - if ((result < 0 && date > 0) || - (result > 0 && date < -1)) + if (unlikely(pg_mul_s64_overflow(date, USECS_PER_DAY, &result) || + pg_add_s64_overflow(result, time, &result))) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range: %d-%02d-%02d %d:%02d:%02g", @@ -1797,6 +1787,24 @@ TimestampDifferenceExceeds(TimestampTz start_time, return (diff >= msec * INT64CONST(1000)); } +/* + * Check if the difference between two timestamps is >= a given + * threshold (expressed in seconds). + */ +bool +TimestampDifferenceExceedsSeconds(TimestampTz start_time, + TimestampTz stop_time, + int threshold_sec) +{ + long secs; + int usecs; + + /* Calculate the difference in seconds */ + TimestampDifference(start_time, stop_time, &secs, &usecs); + + return (secs >= threshold_sec); +} + /* * Convert a time_t to TimestampTz. * @@ -2010,17 +2018,8 @@ tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result) date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); - *result = date * USECS_PER_DAY + time; - /* check for major overflow */ - if ((*result - time) / USECS_PER_DAY != date) - { - *result = 0; /* keep compiler quiet */ - return -1; - } - /* check for just-barely overflow (okay except time-of-day wraps) */ - /* caution: we want to allow 1999-12-31 24:00:00 */ - if ((*result < 0 && date > 0) || - (*result > 0 && date < -1)) + if (unlikely(pg_mul_s64_overflow(date, USECS_PER_DAY, result) || + pg_add_s64_overflow(*result, time, result))) { *result = 0; /* keep compiler quiet */ return -1; @@ -2306,6 +2305,53 @@ timestamp_sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* note: this is used for timestamptz also */ +static Datum +timestamp_decrement(Relation rel, Datum existing, bool *underflow) +{ + Timestamp texisting = DatumGetTimestamp(existing); + + if (texisting == PG_INT64_MIN) + { + /* return value is undefined */ + *underflow = true; + return (Datum) 0; + } + + *underflow = false; + return TimestampGetDatum(texisting - 1); +} + +/* note: this is used for timestamptz also */ +static Datum +timestamp_increment(Relation rel, Datum existing, bool *overflow) +{ + Timestamp texisting = DatumGetTimestamp(existing); + + if (texisting == PG_INT64_MAX) + { + /* return value is undefined */ + *overflow = true; + return (Datum) 0; + } + + *overflow = false; + return TimestampGetDatum(texisting + 1); +} + +Datum +timestamp_skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + + sksup->decrement = timestamp_decrement; + sksup->increment = timestamp_increment; + sksup->low_elem = TimestampGetDatum(PG_INT64_MIN); + sksup->high_elem = TimestampGetDatum(PG_INT64_MAX); + + PG_RETURN_VOID(); +} + Datum timestamp_hash(PG_FUNCTION_ARGS) { @@ -2318,6 +2364,18 @@ timestamp_hash_extended(PG_FUNCTION_ARGS) return hashint8extended(fcinfo); } +Datum +timestamptz_hash(PG_FUNCTION_ARGS) +{ + return hashint8(fcinfo); +} + +Datum +timestamptz_hash_extended(PG_FUNCTION_ARGS) +{ + return hashint8extended(fcinfo); +} + /* * Cross-type comparison functions for timestamp vs timestamptz */ @@ -4628,9 +4686,6 @@ timestamp_trunc(PG_FUNCTION_ARGS) struct pg_tm tt, *tm = &tt; - if (TIMESTAMP_NOT_FINITE(timestamp)) - PG_RETURN_TIMESTAMP(timestamp); - lowunits = downcase_truncate_identifier(VARDATA_ANY(units), VARSIZE_ANY_EXHDR(units), false); @@ -4639,6 +4694,39 @@ timestamp_trunc(PG_FUNCTION_ARGS) if (type == UNITS) { + if (TIMESTAMP_NOT_FINITE(timestamp)) + { + /* + * Errors thrown here for invalid units should exactly match those + * below, else there will be unexpected discrepancies between + * finite- and infinite-input cases. + */ + switch (val) + { + case DTK_WEEK: + case DTK_MILLENNIUM: + case DTK_CENTURY: + case DTK_DECADE: + case DTK_YEAR: + case DTK_QUARTER: + case DTK_MONTH: + case DTK_DAY: + case DTK_HOUR: + case DTK_MINUTE: + case DTK_SECOND: + case DTK_MILLISEC: + case DTK_MICROSEC: + PG_RETURN_TIMESTAMP(timestamp); + break; + default: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unit \"%s\" not supported for type %s", + lowunits, format_type_be(TIMESTAMPOID)))); + result = 0; + } + } + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), @@ -4844,6 +4932,40 @@ timestamptz_trunc_internal(text *units, TimestampTz timestamp, pg_tz *tzp) if (type == UNITS) { + if (TIMESTAMP_NOT_FINITE(timestamp)) + { + /* + * Errors thrown here for invalid units should exactly match those + * below, else there will be unexpected discrepancies between + * finite- and infinite-input cases. + */ + switch (val) + { + case DTK_WEEK: + case DTK_MILLENNIUM: + case DTK_CENTURY: + case DTK_DECADE: + case DTK_YEAR: + case DTK_QUARTER: + case DTK_MONTH: + case DTK_DAY: + case DTK_HOUR: + case DTK_MINUTE: + case DTK_SECOND: + case DTK_MILLISEC: + case DTK_MICROSEC: + PG_RETURN_TIMESTAMPTZ(timestamp); + break; + + default: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unit \"%s\" not supported for type %s", + lowunits, format_type_be(TIMESTAMPTZOID)))); + result = 0; + } + } + if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, tzp) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), @@ -4974,9 +5096,6 @@ timestamptz_trunc(PG_FUNCTION_ARGS) TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1); TimestampTz result; - if (TIMESTAMP_NOT_FINITE(timestamp)) - PG_RETURN_TIMESTAMPTZ(timestamp); - result = timestamptz_trunc_internal(units, timestamp, session_timezone); PG_RETURN_TIMESTAMPTZ(result); @@ -4994,13 +5113,6 @@ timestamptz_trunc_zone(PG_FUNCTION_ARGS) TimestampTz result; pg_tz *tzp; - /* - * timestamptz_zone() doesn't look up the zone for infinite inputs, so we - * don't do so here either. - */ - if (TIMESTAMP_NOT_FINITE(timestamp)) - PG_RETURN_TIMESTAMP(timestamp); - /* * Look up the requested timezone. */ @@ -5028,12 +5140,6 @@ interval_trunc(PG_FUNCTION_ARGS) result = (Interval *) palloc(sizeof(Interval)); - if (INTERVAL_NOT_FINITE(interval)) - { - memcpy(result, interval, sizeof(Interval)); - PG_RETURN_INTERVAL_P(result); - } - lowunits = downcase_truncate_identifier(VARDATA_ANY(units), VARSIZE_ANY_EXHDR(units), false); @@ -5042,6 +5148,41 @@ interval_trunc(PG_FUNCTION_ARGS) if (type == UNITS) { + if (INTERVAL_NOT_FINITE(interval)) + { + /* + * Errors thrown here for invalid units should exactly match those + * below, else there will be unexpected discrepancies between + * finite- and infinite-input cases. + */ + switch (val) + { + case DTK_MILLENNIUM: + case DTK_CENTURY: + case DTK_DECADE: + case DTK_YEAR: + case DTK_QUARTER: + case DTK_MONTH: + case DTK_DAY: + case DTK_HOUR: + case DTK_MINUTE: + case DTK_SECOND: + case DTK_MILLISEC: + case DTK_MICROSEC: + memcpy(result, interval, sizeof(Interval)); + PG_RETURN_INTERVAL_P(result); + break; + + default: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unit \"%s\" not supported for type %s", + lowunits, format_type_be(INTERVALOID)), + (val == DTK_WEEK) ? errdetail("Months usually have fractional weeks.") : 0)); + result = 0; + } + } + interval2itm(*interval, tm); switch (val) { @@ -5112,6 +5253,10 @@ interval_trunc(PG_FUNCTION_ARGS) * * Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week. * Julian days are used to convert between ISO week dates and Gregorian dates. + * + * XXX: This function has integer overflow hazards, but restructuring it to + * work with the soft-error handling that its callers do is likely more + * trouble than it's worth. */ int isoweek2j(int year, int week) @@ -5919,6 +6064,7 @@ NonFiniteIntervalPart(int type, int unit, char *lowunits, bool isNegative) case DTK_MILLISEC: case DTK_SECOND: case DTK_MINUTE: + case DTK_WEEK: case DTK_MONTH: case DTK_QUARTER: return 0.0; @@ -6038,12 +6184,27 @@ interval_part_common(PG_FUNCTION_ARGS, bool retnumeric) intresult = tm->tm_mday; break; + case DTK_WEEK: + intresult = tm->tm_mday / 7; + break; + case DTK_MONTH: intresult = tm->tm_mon; break; case DTK_QUARTER: - intresult = (tm->tm_mon / 3) + 1; + + /* + * We want to maintain the rule that a field extracted from a + * negative interval is the negative of the field's value for + * the sign-reversed interval. The broken-down tm_year and + * tm_mon aren't very helpful for that, so work from + * interval->month. + */ + if (interval->month >= 0) + intresult = (tm->tm_mon / 3) + 1; + else + intresult = -(((-interval->month % MONTHS_PER_YEAR) / 3) + 1); break; case DTK_YEAR: diff --git a/src/backend/utils/adt/trigfuncs.c b/src/backend/utils/adt/trigfuncs.c index a132082722366..8371b7eb9f565 100644 --- a/src/backend/utils/adt/trigfuncs.c +++ b/src/backend/utils/adt/trigfuncs.c @@ -4,7 +4,7 @@ * Builtin functions for useful trigger support. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/utils/adt/trigfuncs.c diff --git a/src/backend/utils/adt/tsginidx.c b/src/backend/utils/adt/tsginidx.c index 0d9b0d590137d..2712fd89df095 100644 --- a/src/backend/utils/adt/tsginidx.c +++ b/src/backend/utils/adt/tsginidx.c @@ -3,7 +3,7 @@ * tsginidx.c * GIN support functions for tsvector_ops * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c index 5698ee5502b00..935187b37c749 100644 --- a/src/backend/utils/adt/tsgistidx.c +++ b/src/backend/utils/adt/tsgistidx.c @@ -3,7 +3,7 @@ * tsgistidx.c * GiST support functions for tsvector_ops * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -96,34 +96,25 @@ gtsvectorin(PG_FUNCTION_ARGS) PG_RETURN_VOID(); /* keep compiler quiet */ } -#define SINGOUTSTR "%d true bits, %d false bits" -#define ARROUTSTR "%d unique words" -#define EXTRALEN ( 2*13 ) - -static int outbuf_maxlen = 0; - Datum gtsvectorout(PG_FUNCTION_ARGS) { SignTSVector *key = (SignTSVector *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); char *outbuf; - if (outbuf_maxlen == 0) - outbuf_maxlen = 2 * EXTRALEN + Max(strlen(SINGOUTSTR), strlen(ARROUTSTR)) + 1; - outbuf = palloc(outbuf_maxlen); - if (ISARRKEY(key)) - sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key)); + outbuf = psprintf("%d unique words", (int) ARRNELEM(key)); else { if (ISALLTRUE(key)) - sprintf(outbuf, "all true bits"); + outbuf = pstrdup("all true bits"); else { int siglen = GETSIGLEN(key); int cnttrue = sizebitvec(GETSIGN(key), siglen); - sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT(siglen) - cnttrue); + outbuf = psprintf("%d true bits, %d false bits", + cnttrue, (int) SIGLENBIT(siglen) - cnttrue); } } @@ -364,7 +355,7 @@ gtsvector_consistent(PG_FUNCTION_ARGS) chkval.arrb = GETARR(key); chkval.arre = chkval.arrb + ARRNELEM(key); PG_RETURN_BOOL(TS_execute(GETQUERY(query), - (void *) &chkval, + &chkval, TS_EXEC_PHRASE_NO_POS, checkcondition_arr)); } diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c index 6f532188392d3..717de8073d58d 100644 --- a/src/backend/utils/adt/tsquery.c +++ b/src/backend/utils/adt/tsquery.c @@ -3,7 +3,7 @@ * tsquery.c * I/O functions for tsquery * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -197,7 +197,7 @@ parse_phrase_operator(TSQueryParserState pstate, int16 *distance) continue; } - if (!t_isdigit(ptr)) + if (!isdigit((unsigned char) *ptr)) return false; errno = 0; @@ -274,7 +274,7 @@ parse_or_operator(TSQueryParserState pstate) * So we still treat OR literal as operation with possibly incorrect * operand and will not search it as lexeme */ - if (!t_isspace(ptr)) + if (!isspace((unsigned char) *ptr)) break; } @@ -315,7 +315,7 @@ gettoken_query_standard(TSQueryParserState state, int8 *operator, /* generic syntax error message is fine */ return PT_ERR; } - else if (!t_isspace(state->buf)) + else if (!isspace((unsigned char) *state->buf)) { /* * We rely on the tsvector parser to parse the value for @@ -383,7 +383,7 @@ gettoken_query_standard(TSQueryParserState state, int8 *operator, { return (state->count) ? PT_ERR : PT_END; } - else if (!t_isspace(state->buf)) + else if (!isspace((unsigned char) *state->buf)) { return PT_ERR; } @@ -444,7 +444,7 @@ gettoken_query_websearch(TSQueryParserState state, int8 *operator, state->state = WAITOPERAND; continue; } - else if (!t_isspace(state->buf)) + else if (!isspace((unsigned char) *state->buf)) { /* * We rely on the tsvector parser to parse the value for @@ -492,7 +492,7 @@ gettoken_query_websearch(TSQueryParserState state, int8 *operator, state->buf++; continue; } - else if (!t_isspace(state->buf)) + else if (!isspace((unsigned char) *state->buf)) { /* insert implicit AND between operands */ state->state = WAITOPERAND; @@ -1176,10 +1176,11 @@ tsqueryout(PG_FUNCTION_ARGS) * * uint8 type, QI_VAL * uint8 weight - * operand text in client encoding, null-terminated * uint8 prefix + * operand text in client encoding, null-terminated * * For each operator: + * * uint8 type, QI_OPR * uint8 operator, one of OP_AND, OP_PHRASE OP_OR, OP_NOT. * uint16 distance (only for OP_PHRASE) diff --git a/src/backend/utils/adt/tsquery_cleanup.c b/src/backend/utils/adt/tsquery_cleanup.c index aa46be701ee23..590d7c7989c7e 100644 --- a/src/backend/utils/adt/tsquery_cleanup.c +++ b/src/backend/utils/adt/tsquery_cleanup.c @@ -4,7 +4,7 @@ * Cleanup query from NOT values and/or stopword * Utility functions to correct work. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsquery_gist.c b/src/backend/utils/adt/tsquery_gist.c index a19ed4cf37600..f7f94c1c760f5 100644 --- a/src/backend/utils/adt/tsquery_gist.c +++ b/src/backend/utils/adt/tsquery_gist.c @@ -3,7 +3,7 @@ * tsquery_gist.c * GiST index support for tsquery * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsquery_op.c b/src/backend/utils/adt/tsquery_op.c index 6f6dc12a118e4..bb77e923062cf 100644 --- a/src/backend/utils/adt/tsquery_op.c +++ b/src/backend/utils/adt/tsquery_op.c @@ -3,7 +3,7 @@ * tsquery_op.c * Various operations with tsquery * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsquery_rewrite.c b/src/backend/utils/adt/tsquery_rewrite.c index 8a587be929661..2f9e81fbfea25 100644 --- a/src/backend/utils/adt/tsquery_rewrite.c +++ b/src/backend/utils/adt/tsquery_rewrite.c @@ -3,7 +3,7 @@ * tsquery_rewrite.c * Utilities for reconstructing tsquery * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c index 63760080b2671..1c24b041aa29c 100644 --- a/src/backend/utils/adt/tsquery_util.c +++ b/src/backend/utils/adt/tsquery_util.c @@ -3,7 +3,7 @@ * tsquery_util.c * Utilities for tsquery datatype * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/tsrank.c b/src/backend/utils/adt/tsrank.c index c2285cf27e9fd..e863aa586535d 100644 --- a/src/backend/utils/adt/tsrank.c +++ b/src/backend/utils/adt/tsrank.c @@ -3,7 +3,7 @@ * tsrank.c * rank tsvector by tsquery * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -21,7 +21,8 @@ #include "utils/array.h" #include "utils/fmgrprotos.h" -static const float weights[] = {0.1f, 0.2f, 0.4f, 1.0f}; +#define NUM_WEIGHTS 4 +static const float default_weights[NUM_WEIGHTS] = {0.1f, 0.2f, 0.4f, 1.0f}; #define wpos(wep) ( w[ WEP_GETWEIGHT(wep) ] ) @@ -184,7 +185,7 @@ SortAndUniqItems(TSQuery q, int *size) /* remove duplicates */ while (ptr - res < *size) { - if (compareQueryOperand((void *) ptr, (void *) prevptr, (void *) operand) != 0) + if (compareQueryOperand(ptr, prevptr, operand) != 0) { prevptr++; *prevptr = *ptr; @@ -396,22 +397,24 @@ calc_rank(const float *w, TSVector t, TSQuery q, int32 method) return res; } -static const float * -getWeights(ArrayType *win) +/* + * Extract weights from an array. The weights are stored in *ws, which must + * have space for NUM_WEIGHTS elements. + */ +static void +getWeights(ArrayType *win, float *ws) { - static float ws[lengthof(weights)]; int i; float4 *arrdata; - if (win == NULL) - return weights; + Assert(win != NULL); if (ARR_NDIM(win) != 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array of weight must be one-dimensional"))); - if (ArrayGetNItems(ARR_NDIM(win), ARR_DIMS(win)) < lengthof(weights)) + if (ArrayGetNItems(ARR_NDIM(win), ARR_DIMS(win)) < NUM_WEIGHTS) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array of weight is too short"))); @@ -422,16 +425,14 @@ getWeights(ArrayType *win) errmsg("array of weight must not contain nulls"))); arrdata = (float4 *) ARR_DATA_PTR(win); - for (i = 0; i < lengthof(weights); i++) + for (i = 0; i < NUM_WEIGHTS; i++) { - ws[i] = (arrdata[i] >= 0) ? arrdata[i] : weights[i]; + ws[i] = (arrdata[i] >= 0) ? arrdata[i] : default_weights[i]; if (ws[i] > 1.0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("weight out of range"))); } - - return ws; } Datum @@ -441,9 +442,11 @@ ts_rank_wttf(PG_FUNCTION_ARGS) TSVector txt = PG_GETARG_TSVECTOR(1); TSQuery query = PG_GETARG_TSQUERY(2); int method = PG_GETARG_INT32(3); + float weights[NUM_WEIGHTS]; float res; - res = calc_rank(getWeights(win), txt, query, method); + getWeights(win, weights); + res = calc_rank(weights, txt, query, method); PG_FREE_IF_COPY(win, 0); PG_FREE_IF_COPY(txt, 1); @@ -457,9 +460,11 @@ ts_rank_wtt(PG_FUNCTION_ARGS) ArrayType *win = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); TSVector txt = PG_GETARG_TSVECTOR(1); TSQuery query = PG_GETARG_TSQUERY(2); + float weights[NUM_WEIGHTS]; float res; - res = calc_rank(getWeights(win), txt, query, DEF_NORM_METHOD); + getWeights(win, weights); + res = calc_rank(weights, txt, query, DEF_NORM_METHOD); PG_FREE_IF_COPY(win, 0); PG_FREE_IF_COPY(txt, 1); @@ -475,7 +480,7 @@ ts_rank_ttf(PG_FUNCTION_ARGS) int method = PG_GETARG_INT32(2); float res; - res = calc_rank(getWeights(NULL), txt, query, method); + res = calc_rank(default_weights, txt, query, method); PG_FREE_IF_COPY(txt, 0); PG_FREE_IF_COPY(query, 1); @@ -489,7 +494,7 @@ ts_rank_tt(PG_FUNCTION_ARGS) TSQuery query = PG_GETARG_TSQUERY(1); float res; - res = calc_rank(getWeights(NULL), txt, query, DEF_NORM_METHOD); + res = calc_rank(default_weights, txt, query, DEF_NORM_METHOD); PG_FREE_IF_COPY(txt, 0); PG_FREE_IF_COPY(query, 1); @@ -666,7 +671,7 @@ Cover(DocRepresentation *doc, int len, QueryRepresentation *qr, CoverExt *ext) { fillQueryRepresentationData(qr, ptr); - if (TS_execute(GETQUERY(qr->query), (void *) qr, + if (TS_execute(GETQUERY(qr->query), qr, TS_EXEC_EMPTY, checkcondition_QueryOperand)) { if (WEP_GETPOS(ptr->pos) > ext->q) @@ -696,7 +701,7 @@ Cover(DocRepresentation *doc, int len, QueryRepresentation *qr, CoverExt *ext) */ fillQueryRepresentationData(qr, ptr); - if (TS_execute(GETQUERY(qr->query), (void *) qr, + if (TS_execute(GETQUERY(qr->query), qr, TS_EXEC_EMPTY, checkcondition_QueryOperand)) { if (WEP_GETPOS(ptr->pos) < ext->p) @@ -807,7 +812,7 @@ get_docrep(TSVector txt, QueryRepresentation *qr, int *doclen) qsort(doc, cur, sizeof(DocRepresentation), compareDocR); /* - * Join QueryItem per WordEntry and it's position + * Join QueryItem per WordEntry and its position */ storage.pos = doc->pos; storage.data.query.items = palloc(sizeof(QueryItem *) * qr->query->size); @@ -855,16 +860,16 @@ calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method) doclen = 0; CoverExt ext; double Wdoc = 0.0; - double invws[lengthof(weights)]; + double invws[NUM_WEIGHTS]; double SumDist = 0.0, PrevExtPos = 0.0; int NExtent = 0; QueryRepresentation qr; - for (i = 0; i < lengthof(weights); i++) + for (i = 0; i < NUM_WEIGHTS; i++) { - invws[i] = ((double) ((arrdata[i] >= 0) ? arrdata[i] : weights[i])); + invws[i] = ((double) ((arrdata[i] >= 0) ? arrdata[i] : default_weights[i])); if (invws[i] > 1.0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -956,9 +961,11 @@ ts_rankcd_wttf(PG_FUNCTION_ARGS) TSVector txt = PG_GETARG_TSVECTOR(1); TSQuery query = PG_GETARG_TSQUERY(2); int method = PG_GETARG_INT32(3); + float weights[NUM_WEIGHTS]; float res; - res = calc_rank_cd(getWeights(win), txt, query, method); + getWeights(win, weights); + res = calc_rank_cd(weights, txt, query, method); PG_FREE_IF_COPY(win, 0); PG_FREE_IF_COPY(txt, 1); @@ -972,9 +979,11 @@ ts_rankcd_wtt(PG_FUNCTION_ARGS) ArrayType *win = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); TSVector txt = PG_GETARG_TSVECTOR(1); TSQuery query = PG_GETARG_TSQUERY(2); + float weights[NUM_WEIGHTS]; float res; - res = calc_rank_cd(getWeights(win), txt, query, DEF_NORM_METHOD); + getWeights(win, weights); + res = calc_rank_cd(weights, txt, query, DEF_NORM_METHOD); PG_FREE_IF_COPY(win, 0); PG_FREE_IF_COPY(txt, 1); @@ -990,7 +999,7 @@ ts_rankcd_ttf(PG_FUNCTION_ARGS) int method = PG_GETARG_INT32(2); float res; - res = calc_rank_cd(getWeights(NULL), txt, query, method); + res = calc_rank_cd(default_weights, txt, query, method); PG_FREE_IF_COPY(txt, 0); PG_FREE_IF_COPY(query, 1); @@ -1004,7 +1013,7 @@ ts_rankcd_tt(PG_FUNCTION_ARGS) TSQuery query = PG_GETARG_TSQUERY(1); float res; - res = calc_rank_cd(getWeights(NULL), txt, query, DEF_NORM_METHOD); + res = calc_rank_cd(default_weights, txt, query, DEF_NORM_METHOD); PG_FREE_IF_COPY(txt, 0); PG_FREE_IF_COPY(query, 1); diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c index 4c6a15757a73e..1fa2e3729bfab 100644 --- a/src/backend/utils/adt/tsvector.c +++ b/src/backend/utils/adt/tsvector.c @@ -3,7 +3,7 @@ * tsvector.c * I/O functions for tsvector * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -25,7 +25,7 @@ typedef struct { - WordEntry entry; /* must be first! */ + WordEntry entry; /* must be first, see compareentry */ WordEntryPos *pos; int poslen; /* number of elements in pos */ } WordEntryIN; @@ -79,16 +79,19 @@ uniquePos(WordEntryPos *a, int l) return res + 1 - a; } -/* Compare two WordEntryIN values for qsort */ +/* + * Compare two WordEntry structs for qsort_arg. This can also be used on + * WordEntryIN structs, since those have WordEntry as their first field. + */ static int compareentry(const void *va, const void *vb, void *arg) { - const WordEntryIN *a = (const WordEntryIN *) va; - const WordEntryIN *b = (const WordEntryIN *) vb; + const WordEntry *a = (const WordEntry *) va; + const WordEntry *b = (const WordEntry *) vb; char *BufferStr = (char *) arg; - return tsCompareString(&BufferStr[a->entry.pos], a->entry.len, - &BufferStr[b->entry.pos], b->entry.len, + return tsCompareString(&BufferStr[a->pos], a->len, + &BufferStr[b->pos], b->len, false); } @@ -167,12 +170,6 @@ uniqueentry(WordEntryIN *a, int l, char *buf, int *outbuflen) return res + 1 - a; } -static int -WordEntryCMP(WordEntry *a, WordEntry *b, char *buf) -{ - return compareentry(a, b, buf); -} - Datum tsvectorin(PG_FUNCTION_ARGS) @@ -511,7 +508,7 @@ tsvectorrecv(PG_FUNCTION_ARGS) datalen += lex_len; - if (i > 0 && WordEntryCMP(&vec->entries[i], + if (i > 0 && compareentry(&vec->entries[i], &vec->entries[i - 1], STRPTR(vec)) <= 0) needSort = true; diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 687adcbd69f30..1fa1275ca63b2 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -3,7 +3,7 @@ * tsvector_op.c * operations over tsvector * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -2452,7 +2452,7 @@ ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx, MemoryContext oldcontext; StatEntry *node; - funcctx->user_fctx = (void *) stat; + funcctx->user_fctx = stat; oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); diff --git a/src/backend/utils/adt/tsvector_parser.c b/src/backend/utils/adt/tsvector_parser.c index ea961bb8a4a71..e1620d3ed1f2d 100644 --- a/src/backend/utils/adt/tsvector_parser.c +++ b/src/backend/utils/adt/tsvector_parser.c @@ -3,7 +3,7 @@ * tsvector_parser.c * Parser for tsvector * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -206,7 +206,7 @@ gettoken_tsvector(TSVectorParseState state, else if ((state->oprisdelim && ISOPERATOR(state->prsbuf)) || (state->is_web && t_iseq(state->prsbuf, '"'))) PRSSYNTAXERROR; - else if (!t_isspace(state->prsbuf)) + else if (!isspace((unsigned char) *state->prsbuf)) { COPYCHAR(curpos, state->prsbuf); curpos += pg_mblen(state->prsbuf); @@ -236,7 +236,7 @@ gettoken_tsvector(TSVectorParseState state, statecode = WAITNEXTCHAR; oldstate = WAITENDWORD; } - else if (t_isspace(state->prsbuf) || *(state->prsbuf) == '\0' || + else if (isspace((unsigned char) *state->prsbuf) || *(state->prsbuf) == '\0' || (state->oprisdelim && ISOPERATOR(state->prsbuf)) || (state->is_web && t_iseq(state->prsbuf, '"'))) { @@ -317,7 +317,7 @@ gettoken_tsvector(TSVectorParseState state, } else if (statecode == INPOSINFO) { - if (t_isdigit(state->prsbuf)) + if (isdigit((unsigned char) *state->prsbuf)) { if (posalen == 0) { @@ -372,10 +372,10 @@ gettoken_tsvector(TSVectorParseState state, PRSSYNTAXERROR; WEP_SETWEIGHT(pos[npos - 1], 0); } - else if (t_isspace(state->prsbuf) || + else if (isspace((unsigned char) *state->prsbuf) || *(state->prsbuf) == '\0') RETURN_TOKEN; - else if (!t_isdigit(state->prsbuf)) + else if (!isdigit((unsigned char) *state->prsbuf)) PRSSYNTAXERROR; } else /* internal error */ diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c index 45eb1b2fea9f8..bce7309c1833a 100644 --- a/src/backend/utils/adt/uuid.c +++ b/src/backend/utils/adt/uuid.c @@ -3,7 +3,7 @@ * uuid.c * Functions for the built-in type "uuid". * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/uuid.c @@ -13,16 +13,49 @@ #include "postgres.h" +#include +#include /* for clock_gettime() */ + #include "common/hashfn.h" #include "lib/hyperloglog.h" #include "libpq/pqformat.h" #include "port/pg_bswap.h" #include "utils/fmgrprotos.h" #include "utils/guc.h" +#include "utils/skipsupport.h" #include "utils/sortsupport.h" #include "utils/timestamp.h" #include "utils/uuid.h" +/* helper macros */ +#define NS_PER_S INT64CONST(1000000000) +#define NS_PER_MS INT64CONST(1000000) +#define NS_PER_US INT64CONST(1000) +#define US_PER_MS INT64CONST(1000) + +/* + * UUID version 7 uses 12 bits in "rand_a" to store 1/4096 (or 2^12) fractions of + * sub-millisecond. While most Unix-like platforms provide nanosecond-precision + * timestamps, some systems only offer microsecond precision, limiting us to 10 + * bits of sub-millisecond information. For example, on macOS, real time is + * truncated to microseconds. Additionally, MSVC uses the ported version of + * gettimeofday() that returns microsecond precision. + * + * On systems with only 10 bits of sub-millisecond precision, we still use + * 1/4096 parts of a millisecond, but fill lower 2 bits with random numbers + * (see generate_uuidv7() for details). + * + * SUBMS_MINIMAL_STEP_NS defines the minimum number of nanoseconds that guarantees + * an increase in the UUID's clock precision. + */ +#if defined(__darwin__) || defined(_MSC_VER) +#define SUBMS_MINIMAL_STEP_BITS 10 +#else +#define SUBMS_MINIMAL_STEP_BITS 12 +#endif +#define SUBMS_BITS 12 +#define SUBMS_MINIMAL_STEP_NS ((NS_PER_MS / (1 << SUBMS_MINIMAL_STEP_BITS)) + 1) + /* sortsupport for uuid */ typedef struct { @@ -37,6 +70,9 @@ static int uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2); static int uuid_fast_cmp(Datum x, Datum y, SortSupport ssup); static bool uuid_abbrev_abort(int memtupcount, SortSupport ssup); static Datum uuid_abbrev_convert(Datum original, SortSupport ssup); +static inline void uuid_set_version(pg_uuid_t *uuid, unsigned char version); +static inline int64 get_real_time_ns_ascending(); +static pg_uuid_t *generate_uuidv7(uint64 unix_ts_ms, uint32 sub_ms); Datum uuid_in(PG_FUNCTION_ARGS) @@ -307,13 +343,11 @@ uuid_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card > 100000.0) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "uuid_abbrev: estimation ends at cardinality %f" " after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif uss->estimating = false; return false; } @@ -326,23 +360,19 @@ uuid_abbrev_abort(int memtupcount, SortSupport ssup) */ if (abbr_card < uss->input_count / 2000.0 + 0.5) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "uuid_abbrev: aborting abbreviation at cardinality %f" " below threshold %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count / 2000.0 + 0.5, uss->input_count, memtupcount); -#endif return true; } -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "uuid_abbrev: cardinality %f after " INT64_FORMAT " values (%d rows)", abbr_card, uss->input_count, memtupcount); -#endif return false; } @@ -390,6 +420,74 @@ uuid_abbrev_convert(Datum original, SortSupport ssup) return res; } +static Datum +uuid_decrement(Relation rel, Datum existing, bool *underflow) +{ + pg_uuid_t *uuid; + + uuid = (pg_uuid_t *) palloc(UUID_LEN); + memcpy(uuid, DatumGetUUIDP(existing), UUID_LEN); + for (int i = UUID_LEN - 1; i >= 0; i--) + { + if (uuid->data[i] > 0) + { + uuid->data[i]--; + *underflow = false; + return UUIDPGetDatum(uuid); + } + uuid->data[i] = UCHAR_MAX; + } + + pfree(uuid); /* cannot leak memory */ + + /* return value is undefined */ + *underflow = true; + return (Datum) 0; +} + +static Datum +uuid_increment(Relation rel, Datum existing, bool *overflow) +{ + pg_uuid_t *uuid; + + uuid = (pg_uuid_t *) palloc(UUID_LEN); + memcpy(uuid, DatumGetUUIDP(existing), UUID_LEN); + for (int i = UUID_LEN - 1; i >= 0; i--) + { + if (uuid->data[i] < UCHAR_MAX) + { + uuid->data[i]++; + *overflow = false; + return UUIDPGetDatum(uuid); + } + uuid->data[i] = 0; + } + + pfree(uuid); /* cannot leak memory */ + + /* return value is undefined */ + *overflow = true; + return (Datum) 0; +} + +Datum +uuid_skipsupport(PG_FUNCTION_ARGS) +{ + SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0); + pg_uuid_t *uuid_min = palloc(UUID_LEN); + pg_uuid_t *uuid_max = palloc(UUID_LEN); + + memset(uuid_min->data, 0x00, UUID_LEN); + memset(uuid_max->data, 0xFF, UUID_LEN); + + sksup->decrement = uuid_decrement; + sksup->increment = uuid_increment; + sksup->low_elem = UUIDPGetDatum(uuid_min); + sksup->high_elem = UUIDPGetDatum(uuid_max); + + PG_RETURN_VOID(); +} + /* hash index support */ Datum uuid_hash(PG_FUNCTION_ARGS) @@ -407,6 +505,25 @@ uuid_hash_extended(PG_FUNCTION_ARGS) return hash_any_extended(key->data, UUID_LEN, PG_GETARG_INT64(1)); } +/* + * Set the given UUID version and the variant bits + */ +static inline void +uuid_set_version(pg_uuid_t *uuid, unsigned char version) +{ + /* set version field, top four bits */ + uuid->data[6] = (uuid->data[6] & 0x0f) | (version << 4); + + /* set variant field, top two bits are 1, 0 */ + uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80; +} + +/* + * Generate UUID version 4. + * + * All UUID bytes are filled with strong random numbers except version and + * variant bits. + */ Datum gen_random_uuid(PG_FUNCTION_ARGS) { @@ -418,21 +535,181 @@ gen_random_uuid(PG_FUNCTION_ARGS) errmsg("could not generate random values"))); /* - * Set magic numbers for a "version 4" (pseudorandom) UUID, see - * http://tools.ietf.org/html/rfc4122#section-4.4 + * Set magic numbers for a "version 4" (pseudorandom) UUID and variant, + * see https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-4 + */ + uuid_set_version(uuid, 4); + + PG_RETURN_UUID_P(uuid); +} + +/* + * Get the current timestamp with nanosecond precision for UUID generation. + * The returned timestamp is ensured to be at least SUBMS_MINIMAL_STEP greater + * than the previous returned timestamp (on this backend). + */ +static inline int64 +get_real_time_ns_ascending() +{ + static int64 previous_ns = 0; + int64 ns; + + /* Get the current real timestamp */ + +#ifdef _MSC_VER + struct timeval tmp; + + gettimeofday(&tmp, NULL); + ns = tmp.tv_sec * NS_PER_S + tmp.tv_usec * NS_PER_US; +#else + struct timespec tmp; + + /* + * We don't use gettimeofday(), instead use clock_gettime() with + * CLOCK_REALTIME where available in order to get a high-precision + * (nanoseconds) real timestamp. + * + * Note while a timestamp returned by clock_gettime() with CLOCK_REALTIME + * is nanosecond-precision on most Unix-like platforms, on some platforms + * such as macOS it's restricted to microsecond-precision. + */ + clock_gettime(CLOCK_REALTIME, &tmp); + ns = tmp.tv_sec * NS_PER_S + tmp.tv_nsec; +#endif + + /* Guarantee the minimal step advancement of the timestamp */ + if (previous_ns + SUBMS_MINIMAL_STEP_NS >= ns) + ns = previous_ns + SUBMS_MINIMAL_STEP_NS; + previous_ns = ns; + + return ns; +} + +/* + * Generate UUID version 7 per RFC 9562, with the given timestamp. + * + * UUID version 7 consists of a Unix timestamp in milliseconds (48 bits) and + * 74 random bits, excluding the required version and variant bits. To ensure + * monotonicity in scenarios of high-frequency UUID generation, we employ the + * method "Replace Leftmost Random Bits with Increased Clock Precision (Method 3)", + * described in the RFC. This method utilizes 12 bits from the "rand_a" bits + * to store a 1/4096 (or 2^12) fraction of sub-millisecond precision. + * + * unix_ts_ms is a number of milliseconds since start of the UNIX epoch, + * and sub_ms is a number of nanoseconds within millisecond. These values are + * used for time-dependent bits of UUID. + * + * NB: all numbers here are unsigned, unix_ts_ms cannot be negative per RFC. + */ +static pg_uuid_t * +generate_uuidv7(uint64 unix_ts_ms, uint32 sub_ms) +{ + pg_uuid_t *uuid = palloc(UUID_LEN); + uint32 increased_clock_precision; + + /* Fill in time part */ + uuid->data[0] = (unsigned char) (unix_ts_ms >> 40); + uuid->data[1] = (unsigned char) (unix_ts_ms >> 32); + uuid->data[2] = (unsigned char) (unix_ts_ms >> 24); + uuid->data[3] = (unsigned char) (unix_ts_ms >> 16); + uuid->data[4] = (unsigned char) (unix_ts_ms >> 8); + uuid->data[5] = (unsigned char) unix_ts_ms; + + /* + * sub-millisecond timestamp fraction (SUBMS_BITS bits, not + * SUBMS_MINIMAL_STEP_BITS) + */ + increased_clock_precision = (sub_ms * (1 << SUBMS_BITS)) / NS_PER_MS; + + /* Fill the increased clock precision to "rand_a" bits */ + uuid->data[6] = (unsigned char) (increased_clock_precision >> 8); + uuid->data[7] = (unsigned char) (increased_clock_precision); + + /* fill everything after the increased clock precision with random bytes */ + if (!pg_strong_random(&uuid->data[8], UUID_LEN - 8)) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("could not generate random values"))); + +#if SUBMS_MINIMAL_STEP_BITS == 10 + + /* + * On systems that have only 10 bits of sub-ms precision, 2 least + * significant are dependent on other time-specific bits, and they do not + * contribute to uniqueness. To make these bit random we mix in two bits + * from CSPRNG. SUBMS_MINIMAL_STEP is chosen so that we still guarantee + * monotonicity despite altering these bits. + */ + uuid->data[7] = uuid->data[7] ^ (uuid->data[8] >> 6); +#endif + + /* + * Set magic numbers for a "version 7" (pseudorandom) UUID and variant, + * see https://www.rfc-editor.org/rfc/rfc9562#name-version-field */ - uuid->data[6] = (uuid->data[6] & 0x0f) | 0x40; /* time_hi_and_version */ - uuid->data[8] = (uuid->data[8] & 0x3f) | 0x80; /* clock_seq_hi_and_reserved */ + uuid_set_version(uuid, 7); + + return uuid; +} + +/* + * Generate UUID version 7 with the current timestamp. + */ +Datum +uuidv7(PG_FUNCTION_ARGS) +{ + int64 ns = get_real_time_ns_ascending(); + pg_uuid_t *uuid = generate_uuidv7(ns / NS_PER_MS, ns % NS_PER_MS); PG_RETURN_UUID_P(uuid); } -#define UUIDV1_EPOCH_JDATE 2299161 /* == date2j(1582,10,15) */ +/* + * Similar to uuidv7() but with the timestamp adjusted by the given interval. + */ +Datum +uuidv7_interval(PG_FUNCTION_ARGS) +{ + Interval *shift = PG_GETARG_INTERVAL_P(0); + TimestampTz ts; + pg_uuid_t *uuid; + int64 ns = get_real_time_ns_ascending(); + int64 us; + + /* + * Shift the current timestamp by the given interval. To calculate time + * shift correctly, we convert the UNIX epoch to TimestampTz and use + * timestamptz_pl_interval(). This calculation is done with microsecond + * precision. + */ + + ts = (TimestampTz) (ns / NS_PER_US) - + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; + + /* Compute time shift */ + ts = DatumGetTimestampTz(DirectFunctionCall2(timestamptz_pl_interval, + TimestampTzGetDatum(ts), + IntervalPGetDatum(shift))); + + /* Convert a TimestampTz value back to an UNIX epoch timestamp */ + us = ts + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; + + /* Generate an UUIDv7 */ + uuid = generate_uuidv7(us / US_PER_MS, (us % US_PER_MS) * NS_PER_US + ns % NS_PER_US); + + PG_RETURN_UUID_P(uuid); +} + +/* + * Start of a Gregorian epoch == date2j(1582,10,15) + * We cast it to 64-bit because it's used in overflow-prone computations + */ +#define GREGORIAN_EPOCH_JDATE INT64CONST(2299161) /* * Extract timestamp from UUID. * - * Returns null if not RFC 4122 variant or not a version that has a timestamp. + * Returns null if not RFC 9562 variant or not a version that has a timestamp. */ Datum uuid_extract_timestamp(PG_FUNCTION_ARGS) @@ -442,7 +719,7 @@ uuid_extract_timestamp(PG_FUNCTION_ARGS) uint64 tms; TimestampTz ts; - /* check if RFC 4122 variant */ + /* check if RFC 9562 variant */ if ((uuid->data[8] & 0xc0) != 0x80) PG_RETURN_NULL(); @@ -461,7 +738,22 @@ uuid_extract_timestamp(PG_FUNCTION_ARGS) /* convert 100-ns intervals to us, then adjust */ ts = (TimestampTz) (tms / 10) - - ((uint64) POSTGRES_EPOCH_JDATE - UUIDV1_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; + ((uint64) POSTGRES_EPOCH_JDATE - GREGORIAN_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; + PG_RETURN_TIMESTAMPTZ(ts); + } + + if (version == 7) + { + tms = (uuid->data[5]) + + (((uint64) uuid->data[4]) << 8) + + (((uint64) uuid->data[3]) << 16) + + (((uint64) uuid->data[2]) << 24) + + (((uint64) uuid->data[1]) << 32) + + (((uint64) uuid->data[0]) << 40); + + /* convert ms to us, then adjust */ + ts = (TimestampTz) (tms * NS_PER_US) - + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; PG_RETURN_TIMESTAMPTZ(ts); } @@ -473,7 +765,7 @@ uuid_extract_timestamp(PG_FUNCTION_ARGS) /* * Extract UUID version. * - * Returns null if not RFC 4122 variant. + * Returns null if not RFC 9562 variant. */ Datum uuid_extract_version(PG_FUNCTION_ARGS) @@ -481,7 +773,7 @@ uuid_extract_version(PG_FUNCTION_ARGS) pg_uuid_t *uuid = PG_GETARG_UUID_P(0); uint16 version; - /* check if RFC 4122 variant */ + /* check if RFC 9562 variant */ if ((uuid->data[8] & 0xc0) != 0x80) PG_RETURN_NULL(); diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 8fcf3fb731e55..205a67dafc56b 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -20,7 +20,7 @@ * * Code originally contributed by Adriaan Joubert. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -361,7 +361,7 @@ bit_recv(PG_FUNCTION_ARGS) SET_VARSIZE(result, len); VARBITLEN(result) = bitlen; - pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result)); + pq_copymsgbytes(buf, VARBITS(result), VARBITBYTES(result)); /* Make sure last byte is correctly zero-padded */ VARBIT_PAD(result); @@ -666,7 +666,7 @@ varbit_recv(PG_FUNCTION_ARGS) SET_VARSIZE(result, len); VARBITLEN(result) = bitlen; - pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result)); + pq_copymsgbytes(buf, VARBITS(result), VARBITBYTES(result)); /* Make sure last byte is correctly zero-padded */ VARBIT_PAD(result); diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 02dfe219f5463..3f40c9da1a0d5 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -3,7 +3,7 @@ * varchar.c * Functions for the built-in types char(n) and varchar(n). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -748,20 +748,16 @@ bpchareq(PG_FUNCTION_ARGS) len2; bool result; Oid collid = PG_GET_COLLATION(); - bool locale_is_c = false; - pg_locale_t mylocale = 0; + pg_locale_t mylocale; check_collation_set(collid); len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); - if (lc_collate_is_c(collid)) - locale_is_c = true; - else - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { /* * Since we only care about equality or not-equality, we can avoid all @@ -793,20 +789,16 @@ bpcharne(PG_FUNCTION_ARGS) len2; bool result; Oid collid = PG_GET_COLLATION(); - bool locale_is_c = false; - pg_locale_t mylocale = 0; + pg_locale_t mylocale; check_collation_set(collid); len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); - if (lc_collate_is_c(collid)) - locale_is_c = true; - else - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { /* * Since we only care about equality or not-equality, we can avoid all @@ -999,7 +991,7 @@ hashbpchar(PG_FUNCTION_ARGS) Oid collid = PG_GET_COLLATION(); char *keydata; int keylen; - pg_locale_t mylocale = 0; + pg_locale_t mylocale; Datum result; if (!collid) @@ -1011,10 +1003,9 @@ hashbpchar(PG_FUNCTION_ARGS) keydata = VARDATA_ANY(key); keylen = bcTruelen(key); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { result = hash_any((unsigned char *) keydata, keylen); } @@ -1028,7 +1019,9 @@ hashbpchar(PG_FUNCTION_ARGS) buf = palloc(bsize + 1); rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale); - if (rsize != bsize) + + /* the second call may return a smaller value than the first */ + if (rsize > bsize) elog(ERROR, "pg_strnxfrm() returned unexpected result"); /* @@ -1054,7 +1047,7 @@ hashbpcharextended(PG_FUNCTION_ARGS) Oid collid = PG_GET_COLLATION(); char *keydata; int keylen; - pg_locale_t mylocale = 0; + pg_locale_t mylocale; Datum result; if (!collid) @@ -1066,10 +1059,9 @@ hashbpcharextended(PG_FUNCTION_ARGS) keydata = VARDATA_ANY(key); keylen = bcTruelen(key); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { result = hash_any_extended((unsigned char *) keydata, keylen, PG_GETARG_INT64(1)); @@ -1084,7 +1076,9 @@ hashbpcharextended(PG_FUNCTION_ARGS) buf = palloc(bsize + 1); rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale); - if (rsize != bsize) + + /* the second call may return a smaller value than the first */ + if (rsize > bsize) elog(ERROR, "pg_strnxfrm() returned unexpected result"); /* diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index d2e2e9bbba0b3..3e4d5568bde89 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -3,7 +3,7 @@ * varlena.c * Functions for the variable-length built-in types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -54,7 +54,9 @@ typedef struct varlena VarString; */ typedef struct { + pg_locale_t locale; /* collation used for substring matching */ bool is_multibyte_char_in_char; /* need to check char boundaries? */ + bool greedy; /* find longest possible substring? */ char *str1; /* haystack string */ char *str2; /* needle string */ @@ -65,7 +67,13 @@ typedef struct int skiptablemask; /* mask for ANDing with skiptable subscripts */ int skiptable[256]; /* skip distance for given mismatched char */ + /* + * Note that with nondeterministic collations, the length of the last + * match is not necessarily equal to the length of the "needle" passed in. + */ char *last_match; /* pointer to last match in 'str1' */ + int last_match_len; /* length of last match */ + int last_match_len_tmp; /* same but for internal use */ /* * Sometimes we need to convert the byte position of a match to a @@ -1178,15 +1186,21 @@ text_position(text *t1, text *t2, Oid collid) TextPositionState state; int result; + check_collation_set(collid); + /* Empty needle always matches at position 1 */ if (VARSIZE_ANY_EXHDR(t2) < 1) return 1; /* Otherwise, can't match if haystack is shorter than needle */ - if (VARSIZE_ANY_EXHDR(t1) < VARSIZE_ANY_EXHDR(t2)) + if (VARSIZE_ANY_EXHDR(t1) < VARSIZE_ANY_EXHDR(t2) && + pg_newlocale_from_collation(collid)->deterministic) return 0; text_position_setup(t1, t2, collid, &state); + /* don't need greedy mode here */ + state.greedy = false; + if (!text_position_next(&state)) result = 0; else @@ -1217,19 +1231,17 @@ text_position_setup(text *t1, text *t2, Oid collid, TextPositionState *state) { int len1 = VARSIZE_ANY_EXHDR(t1); int len2 = VARSIZE_ANY_EXHDR(t2); - pg_locale_t mylocale = 0; check_collation_set(collid); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + state->locale = pg_newlocale_from_collation(collid); - if (!pg_locale_deterministic(mylocale)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("nondeterministic collations are not supported for substring searches"))); + /* + * Most callers need greedy mode, but some might want to unset this to + * optimize. + */ + state->greedy = true; - Assert(len1 > 0); Assert(len2 > 0); /* @@ -1265,8 +1277,11 @@ text_position_setup(text *t1, text *t2, Oid collid, TextPositionState *state) * point in wasting cycles initializing the table. We also choose not to * use B-M-H for needles of length 1, since the skip table can't possibly * save anything in that case. + * + * (With nondeterministic collations, the search is already + * multibyte-aware, so we don't need this.) */ - if (len1 >= len2 && len2 > 1) + if (len1 >= len2 && len2 > 1 && state->locale->deterministic) { int searchlength = len1 - len2; int skiptablemask; @@ -1344,7 +1359,7 @@ text_position_next(TextPositionState *state) /* Start from the point right after the previous match. */ if (state->last_match) - start_ptr = state->last_match + needle_len; + start_ptr = state->last_match + state->last_match_len; else start_ptr = state->str1; @@ -1360,7 +1375,7 @@ text_position_next(TextPositionState *state) * multi-byte character, we need to verify that the match was at a * character boundary, not in the middle of a multi-byte character. */ - if (state->is_multibyte_char_in_char) + if (state->is_multibyte_char_in_char && state->locale->deterministic) { /* Walk one character at a time, until we reach the match. */ @@ -1388,6 +1403,7 @@ text_position_next(TextPositionState *state) } state->last_match = matchptr; + state->last_match_len = state->last_match_len_tmp; return true; } @@ -1409,7 +1425,62 @@ text_position_next_internal(char *start_ptr, TextPositionState *state) Assert(start_ptr >= haystack && start_ptr <= haystack_end); - if (needle_len == 1) + state->last_match_len_tmp = needle_len; + + if (!state->locale->deterministic) + { + /* + * With a nondeterministic collation, we have to use an unoptimized + * route. We walk through the haystack and see if at each position + * there is a substring of the remaining string that is equal to the + * needle under the given collation. + * + * Note, the found substring could have a different length than the + * needle, including being empty. Callers that want to skip over the + * found string need to read the length of the found substring from + * last_match_len rather than just using the length of their needle. + * + * Most callers will require "greedy" semantics, meaning that we need + * to find the longest such substring, not the shortest. For callers + * that don't need greedy semantics, we can finish on the first match. + */ + const char *result_hptr = NULL; + + hptr = start_ptr; + while (hptr < haystack_end) + { + /* + * First check the common case that there is a match in the + * haystack of exactly the length of the needle. + */ + if (!state->greedy && + haystack_end - hptr >= needle_len && + pg_strncoll(hptr, needle_len, needle, needle_len, state->locale) == 0) + return (char *) hptr; + + /* + * Else check if any of the possible substrings starting at hptr + * are equal to the needle. + */ + for (const char *test_end = hptr; test_end < haystack_end; test_end += pg_mblen(test_end)) + { + if (pg_strncoll(hptr, (test_end - hptr), needle, needle_len, state->locale) == 0) + { + state->last_match_len_tmp = (test_end - hptr); + result_hptr = hptr; + if (!state->greedy) + break; + } + } + if (result_hptr) + break; + + hptr += pg_mblen(hptr); + } + + return (char *) result_hptr; + } + else if (needle_len == 1) { /* No point in using B-M-H for a one-character needle */ char nchar = *needle; @@ -1522,12 +1593,12 @@ check_collation_set(Oid collid) } } -/* varstr_cmp() - * Comparison function for text strings with given lengths. - * Includes locale support, but must copy strings to temporary memory - * to allow null-termination for inputs to strcoll(). - * Returns an integer less than, equal to, or greater than zero, indicating - * whether arg1 is less than, equal to, or greater than arg2. +/* + * varstr_cmp() + * + * Comparison function for text strings with given lengths, using the + * appropriate locale. Returns an integer less than, equal to, or greater than + * zero, indicating whether arg1 is less than, equal to, or greater than arg2. * * Note: many functions that depend on this are marked leakproof; therefore, * avoid reporting the actual contents of the input when throwing errors. @@ -1539,16 +1610,13 @@ int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid) { int result; + pg_locale_t mylocale; check_collation_set(collid); - /* - * Unfortunately, there is no strncoll(), so in the non-C locale case we - * have to do some memory copying. This turns out to be significantly - * slower, so we optimize the case where LC_COLLATE is C. We also try to - * optimize relatively-short strings by avoiding palloc/pfree overhead. - */ - if (lc_collate_is_c(collid)) + mylocale = pg_newlocale_from_collation(collid); + + if (mylocale->collate_is_c) { result = memcmp(arg1, arg2, Min(len1, len2)); if ((result == 0) && (len1 != len2)) @@ -1556,10 +1624,6 @@ varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid) } else { - pg_locale_t mylocale; - - mylocale = pg_newlocale_from_collation(collid); - /* * memcmp() can't tell us which of two unequal strings sorts first, * but it's a cheap way to tell if they're equal. Testing shows that @@ -1575,7 +1639,7 @@ varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid) result = pg_strncoll(arg1, len1, arg2, len2, mylocale); /* Break tie if necessary. */ - if (result == 0 && pg_locale_deterministic(mylocale)) + if (result == 0 && mylocale->deterministic) { result = memcmp(arg1, arg2, Min(len1, len2)); if ((result == 0) && (len1 != len2)) @@ -1619,18 +1683,14 @@ Datum texteq(PG_FUNCTION_ARGS) { Oid collid = PG_GET_COLLATION(); - bool locale_is_c = false; pg_locale_t mylocale = 0; bool result; check_collation_set(collid); - if (lc_collate_is_c(collid)) - locale_is_c = true; - else - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); @@ -1678,18 +1738,14 @@ Datum textne(PG_FUNCTION_ARGS) { Oid collid = PG_GET_COLLATION(); - bool locale_is_c = false; - pg_locale_t mylocale = 0; + pg_locale_t mylocale; bool result; check_collation_set(collid); - if (lc_collate_is_c(collid)) - locale_is_c = true; - else - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || pg_locale_deterministic(mylocale)) + if (mylocale->deterministic) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); @@ -1793,17 +1849,16 @@ text_starts_with(PG_FUNCTION_ARGS) Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); Oid collid = PG_GET_COLLATION(); - pg_locale_t mylocale = 0; + pg_locale_t mylocale; bool result; Size len1, len2; check_collation_set(collid); - if (!lc_collate_is_c(collid)) - mylocale = pg_newlocale_from_collation(collid); + mylocale = pg_newlocale_from_collation(collid); - if (!pg_locale_deterministic(mylocale)) + if (!mylocale->deterministic) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for substring searches"))); @@ -1875,10 +1930,12 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid) bool abbreviate = ssup->abbreviate; bool collate_c = false; VarStringSortSupport *sss; - pg_locale_t locale = 0; + pg_locale_t locale; check_collation_set(collid); + locale = pg_newlocale_from_collation(collid); + /* * If possible, set ssup->comparator to a function which can be used to * directly compare two datums. If we can do this, we'll avoid the @@ -1892,7 +1949,7 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid) * varstrfastcmp_c, bpcharfastcmp_c, or namefastcmp_c, all of which use * memcmp() rather than strcoll(). */ - if (lc_collate_is_c(collid)) + if (locale->collate_is_c) { if (typid == BPCHAROID) ssup->comparator = bpcharfastcmp_c; @@ -1909,13 +1966,6 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid) } else { - /* - * We need a collation-sensitive comparison. To make things faster, - * we'll figure out the collation based on the locale id and cache the - * result. - */ - locale = pg_newlocale_from_collation(collid); - /* * We use varlenafastcmp_locale except for type NAME. */ @@ -1927,25 +1977,25 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid) } else ssup->comparator = varlenafastcmp_locale; - } - /* - * Unfortunately, it seems that abbreviation for non-C collations is - * broken on many common platforms; see pg_strxfrm_enabled(). - * - * Even apart from the risk of broken locales, it's possible that there - * are platforms where the use of abbreviated keys should be disabled at - * compile time. Having only 4 byte datums could make worst-case - * performance drastically more likely, for example. Moreover, macOS's - * strxfrm() implementation is known to not effectively concentrate a - * significant amount of entropy from the original string in earlier - * transformed blobs. It's possible that other supported platforms are - * similarly encumbered. So, if we ever get past disabling this - * categorically, we may still want or need to disable it for particular - * platforms. - */ - if (!collate_c && !pg_strxfrm_enabled(locale)) - abbreviate = false; + /* + * Unfortunately, it seems that abbreviation for non-C collations is + * broken on many common platforms; see pg_strxfrm_enabled(). + * + * Even apart from the risk of broken locales, it's possible that + * there are platforms where the use of abbreviated keys should be + * disabled at compile time. Having only 4 byte datums could make + * worst-case performance drastically more likely, for example. + * Moreover, macOS's strxfrm() implementation is known to not + * effectively concentrate a significant amount of entropy from the + * original string in earlier transformed blobs. It's possible that + * other supported platforms are similarly encumbered. So, if we ever + * get past disabling this categorically, we may still want or need to + * disable it for particular platforms. + */ + if (!pg_strxfrm_enabled(locale)) + abbreviate = false; + } /* * If we're using abbreviated keys, or if we're using a locale-aware @@ -1966,7 +2016,10 @@ varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid) sss->last_len2 = -1; /* Initialize */ sss->last_returned = 0; - sss->locale = locale; + if (collate_c) + sss->locale = NULL; + else + sss->locale = locale; /* * To avoid somehow confusing a strxfrm() blob and an original string, @@ -2219,7 +2272,7 @@ varstrfastcmp_locale(char *a1p, int len1, char *a2p, int len2, SortSupport ssup) result = pg_strcoll(sss->buf1, sss->buf2, sss->locale); /* Break tie if necessary. */ - if (result == 0 && pg_locale_deterministic(sss->locale)) + if (result == 0 && sss->locale->deterministic) result = strcmp(sss->buf1, sss->buf2); /* Cache result, perhaps saving an expensive strcoll() call next time */ @@ -2465,7 +2518,6 @@ varstr_abbrev_abort(int memtupcount, SortSupport ssup) * time there are differences within full key strings not captured in * abbreviations. */ -#ifdef TRACE_SORT if (trace_sort) { double norm_abbrev_card = abbrev_distinct / (double) memtupcount; @@ -2475,7 +2527,6 @@ varstr_abbrev_abort(int memtupcount, SortSupport ssup) memtupcount, abbrev_distinct, key_distinct, norm_abbrev_card, sss->prop_card); } -#endif /* * If the number of distinct abbreviated keys approximately matches the @@ -2537,12 +2588,10 @@ varstr_abbrev_abort(int memtupcount, SortSupport ssup) * of moderately high to high abbreviated cardinality. There is little to * lose but much to gain, which our strategy reflects. */ -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "varstr_abbrev: aborted abbreviation at %d " "(abbrev_distinct: %f, key_distinct: %f, prop_card: %f)", memtupcount, abbrev_distinct, key_distinct, sss->prop_card); -#endif return true; } @@ -2556,15 +2605,13 @@ btvarstrequalimage(PG_FUNCTION_ARGS) { /* Oid opcintype = PG_GETARG_OID(0); */ Oid collid = PG_GET_COLLATION(); + pg_locale_t locale; check_collation_set(collid); - if (lc_collate_is_c(collid) || - collid == DEFAULT_COLLATION_OID || - get_collation_isdeterministic(collid)) - PG_RETURN_BOOL(true); - else - PG_RETURN_BOOL(false); + locale = pg_newlocale_from_collation(collid); + + PG_RETURN_BOOL(locale->deterministic); } Datum @@ -3249,8 +3296,8 @@ byteaGetBit(PG_FUNCTION_ARGS) if (n < 0 || n >= (int64) len * 8) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("index %lld out of valid range, 0..%lld", - (long long) n, (long long) len * 8 - 1))); + errmsg("index %" PRId64 " out of valid range, 0..%" PRId64, + n, (int64) len * 8 - 1))); /* n/8 is now known < len, so safe to cast to int */ byteNo = (int) (n / 8); @@ -3321,8 +3368,8 @@ byteaSetBit(PG_FUNCTION_ARGS) if (n < 0 || n >= (int64) len * 8) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("index %lld out of valid range, 0..%lld", - (long long) n, (long long) len * 8 - 1))); + errmsg("index %" PRId64 " out of valid range, 0..%" PRId64, + n, (int64) len * 8 - 1))); /* n/8 is now known < len, so safe to cast to int */ byteNo = (int) (n / 8); @@ -3351,6 +3398,27 @@ byteaSetBit(PG_FUNCTION_ARGS) PG_RETURN_BYTEA_P(res); } +/* + * Return reversed bytea + */ +Datum +bytea_reverse(PG_FUNCTION_ARGS) +{ + bytea *v = PG_GETARG_BYTEA_PP(0); + const char *p = VARDATA_ANY(v); + int len = VARSIZE_ANY_EXHDR(v); + const char *endp = p + len; + bytea *result = palloc(len + VARHDRSZ); + char *dst = (char *) VARDATA(result) + len; + + SET_VARSIZE(result, len + VARHDRSZ); + + while (p < endp) + *(--dst) = *p++; + + PG_RETURN_BYTEA_P(result); +} + /* text_name() * Converts a text type to a Name type. @@ -3956,6 +4024,44 @@ byteacmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(cmp); } +Datum +bytea_larger(PG_FUNCTION_ARGS) +{ + bytea *arg1 = PG_GETARG_BYTEA_PP(0); + bytea *arg2 = PG_GETARG_BYTEA_PP(1); + bytea *result; + int len1, + len2; + int cmp; + + len1 = VARSIZE_ANY_EXHDR(arg1); + len2 = VARSIZE_ANY_EXHDR(arg2); + + cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2)); + result = ((cmp > 0) || ((cmp == 0) && (len1 > len2)) ? arg1 : arg2); + + PG_RETURN_BYTEA_P(result); +} + +Datum +bytea_smaller(PG_FUNCTION_ARGS) +{ + bytea *arg1 = PG_GETARG_BYTEA_PP(0); + bytea *arg2 = PG_GETARG_BYTEA_PP(1); + bytea *result; + int len1, + len2; + int cmp; + + len1 = VARSIZE_ANY_EXHDR(arg1); + len2 = VARSIZE_ANY_EXHDR(arg2); + + cmp = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2)); + result = ((cmp < 0) || ((cmp == 0) && (len1 < len2)) ? arg1 : arg2); + + PG_RETURN_BYTEA_P(result); +} + Datum bytea_sortsupport(PG_FUNCTION_ARGS) { @@ -3972,6 +4078,102 @@ bytea_sortsupport(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* Cast bytea -> int2 */ +Datum +bytea_int2(PG_FUNCTION_ARGS) +{ + bytea *v = PG_GETARG_BYTEA_PP(0); + int len = VARSIZE_ANY_EXHDR(v); + uint16 result; + + /* Check that the byte array is not too long */ + if (len > sizeof(result)) + ereport(ERROR, + errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("smallint out of range")); + + /* Convert it to an integer; most significant bytes come first */ + result = 0; + for (int i = 0; i < len; i++) + { + result <<= BITS_PER_BYTE; + result |= ((unsigned char *) VARDATA_ANY(v))[i]; + } + + PG_RETURN_INT16(result); +} + +/* Cast bytea -> int4 */ +Datum +bytea_int4(PG_FUNCTION_ARGS) +{ + bytea *v = PG_GETARG_BYTEA_PP(0); + int len = VARSIZE_ANY_EXHDR(v); + uint32 result; + + /* Check that the byte array is not too long */ + if (len > sizeof(result)) + ereport(ERROR, + errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("integer out of range")); + + /* Convert it to an integer; most significant bytes come first */ + result = 0; + for (int i = 0; i < len; i++) + { + result <<= BITS_PER_BYTE; + result |= ((unsigned char *) VARDATA_ANY(v))[i]; + } + + PG_RETURN_INT32(result); +} + +/* Cast bytea -> int8 */ +Datum +bytea_int8(PG_FUNCTION_ARGS) +{ + bytea *v = PG_GETARG_BYTEA_PP(0); + int len = VARSIZE_ANY_EXHDR(v); + uint64 result; + + /* Check that the byte array is not too long */ + if (len > sizeof(result)) + ereport(ERROR, + errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("bigint out of range")); + + /* Convert it to an integer; most significant bytes come first */ + result = 0; + for (int i = 0; i < len; i++) + { + result <<= BITS_PER_BYTE; + result |= ((unsigned char *) VARDATA_ANY(v))[i]; + } + + PG_RETURN_INT64(result); +} + +/* Cast int2 -> bytea; can just use int2send() */ +Datum +int2_bytea(PG_FUNCTION_ARGS) +{ + return int2send(fcinfo); +} + +/* Cast int4 -> bytea; can just use int4send() */ +Datum +int4_bytea(PG_FUNCTION_ARGS) +{ + return int4send(fcinfo); +} + +/* Cast int8 -> bytea; can just use int8send() */ +Datum +int8_bytea(PG_FUNCTION_ARGS) +{ + return int8send(fcinfo); +} + /* * appendStringInfoText * @@ -4042,7 +4244,7 @@ replace_text(PG_FUNCTION_ARGS) appendStringInfoText(&str, to_sub_text); - start_ptr = curr_ptr + from_sub_text_len; + start_ptr = curr_ptr + state.last_match_len; found = text_position_next(&state); if (found) @@ -4432,7 +4634,7 @@ split_part(PG_FUNCTION_ARGS) /* special case of last field does not require an extra pass */ if (fldnum == -1) { - start_ptr = text_position_get_match_ptr(&state) + fldsep_len; + start_ptr = text_position_get_match_ptr(&state) + state.last_match_len; end_ptr = VARDATA_ANY(inputstring) + inputstring_len; text_position_cleanup(&state); PG_RETURN_TEXT_P(cstring_to_text_with_len(start_ptr, @@ -4462,7 +4664,7 @@ split_part(PG_FUNCTION_ARGS) while (found && --fldnum > 0) { /* identify bounds of next field */ - start_ptr = end_ptr + fldsep_len; + start_ptr = end_ptr + state.last_match_len; found = text_position_next(&state); if (found) end_ptr = text_position_get_match_ptr(&state); @@ -4678,7 +4880,7 @@ split_text(FunctionCallInfo fcinfo, SplitTextOutputData *tstate) if (!found) break; - start_ptr = end_ptr + fldsep_len; + start_ptr = end_ptr + state.last_match_len; } text_position_cleanup(&state); diff --git a/src/backend/utils/adt/version.c b/src/backend/utils/adt/version.c index 28db1f636a12f..9f56ef3fb8ffc 100644 --- a/src/backend/utils/adt/version.c +++ b/src/backend/utils/adt/version.c @@ -3,7 +3,7 @@ * version.c * Returns the PostgreSQL version string * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * IDENTIFICATION * diff --git a/src/backend/utils/adt/waitfuncs.c b/src/backend/utils/adt/waitfuncs.c index e135c9e5e45f9..ddd0a57c0c597 100644 --- a/src/backend/utils/adt/waitfuncs.c +++ b/src/backend/utils/adt/waitfuncs.c @@ -3,7 +3,7 @@ * waitfuncs.c * Functions for SQL access to syntheses of multiple contention types. * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/adt/waitfuncs.c @@ -17,7 +17,7 @@ #include "storage/proc.h" #include "storage/procarray.h" #include "utils/array.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/wait_event.h" #define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var)))) diff --git a/src/backend/utils/adt/windowfuncs.c b/src/backend/utils/adt/windowfuncs.c index 473c61569f5d8..bb35f3bc4a981 100644 --- a/src/backend/utils/adt/windowfuncs.c +++ b/src/backend/utils/adt/windowfuncs.c @@ -3,7 +3,7 @@ * windowfuncs.c * Standard window functions defined in SQL spec. * - * Portions Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2000-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c index ae273b1961074..3d0c48769cce8 100644 --- a/src/backend/utils/adt/xid.c +++ b/src/backend/utils/adt/xid.c @@ -3,7 +3,7 @@ * xid.c * POSTGRES transaction identifier and command identifier datatypes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,6 +19,7 @@ #include "access/multixact.h" #include "access/transam.h" #include "access/xact.h" +#include "common/hashfn.h" #include "common/int.h" #include "libpq/pqformat.h" #include "utils/builtins.h" @@ -97,6 +98,18 @@ xidneq(PG_FUNCTION_ARGS) PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2)); } +Datum +hashxid(PG_FUNCTION_ARGS) +{ + return hash_uint32(PG_GETARG_TRANSACTIONID(0)); +} + +Datum +hashxidextended(PG_FUNCTION_ARGS) +{ + return hash_uint32_extended(PG_GETARG_TRANSACTIONID(0), PG_GETARG_INT64(1)); +} + /* * xid_age - compute age of an XID (relative to latest stable xid) */ @@ -287,6 +300,18 @@ xid8cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(-1); } +Datum +hashxid8(PG_FUNCTION_ARGS) +{ + return hashint8(fcinfo); +} + +Datum +hashxid8extended(PG_FUNCTION_ARGS) +{ + return hashint8extended(fcinfo); +} + Datum xid8_larger(PG_FUNCTION_ARGS) { @@ -374,3 +399,15 @@ cideq(PG_FUNCTION_ARGS) PG_RETURN_BOOL(arg1 == arg2); } + +Datum +hashcid(PG_FUNCTION_ARGS) +{ + return hash_uint32(PG_GETARG_COMMANDID(0)); +} + +Datum +hashcidextended(PG_FUNCTION_ARGS) +{ + return hash_uint32_extended(PG_GETARG_COMMANDID(0), PG_GETARG_INT64(1)); +} diff --git a/src/backend/utils/adt/xid8funcs.c b/src/backend/utils/adt/xid8funcs.c index 12d20b72a0388..1da3964ca6fb8 100644 --- a/src/backend/utils/adt/xid8funcs.c +++ b/src/backend/utils/adt/xid8funcs.c @@ -15,7 +15,7 @@ * to users. The txid_XXX variants should eventually be dropped. * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * Author: Jan Wieck, Afilias USA INC. * 64-bit txids: Marko Kreen, Skype Technologies * @@ -32,9 +32,9 @@ #include "lib/qunique.h" #include "libpq/pqformat.h" #include "miscadmin.h" -#include "postmaster/postmaster.h" #include "storage/lwlock.h" #include "storage/procarray.h" +#include "storage/procnumber.h" #include "utils/builtins.h" #include "utils/memutils.h" #include "utils/snapmgr.h" @@ -97,15 +97,11 @@ static bool TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid) { TransactionId xid = XidFromFullTransactionId(fxid); - uint32 now_epoch; - TransactionId now_epoch_next_xid; FullTransactionId now_fullxid; - TransactionId oldest_xid; - FullTransactionId oldest_fxid; + TransactionId oldest_clog_xid; + FullTransactionId oldest_clog_fxid; now_fullxid = ReadNextFullTransactionId(); - now_epoch_next_xid = XidFromFullTransactionId(now_fullxid); - now_epoch = EpochFromFullTransactionId(now_fullxid); if (extracted_xid != NULL) *extracted_xid = xid; @@ -121,8 +117,8 @@ TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid) if (!FullTransactionIdPrecedes(fxid, now_fullxid)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("transaction ID %llu is in the future", - (unsigned long long) U64FromFullTransactionId(fxid)))); + errmsg("transaction ID %" PRIu64 " is in the future", + U64FromFullTransactionId(fxid)))); /* * TransamVariables->oldestClogXid is protected by XactTruncationLock, but @@ -135,52 +131,19 @@ TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid) /* * If fxid is not older than TransamVariables->oldestClogXid, the relevant - * CLOG entry is guaranteed to still exist. Convert - * TransamVariables->oldestClogXid into a FullTransactionId to compare it - * with fxid. Determine the right epoch knowing that oldest_fxid - * shouldn't be more than 2^31 older than now_fullxid. - */ - oldest_xid = TransamVariables->oldestClogXid; - Assert(TransactionIdPrecedesOrEquals(oldest_xid, now_epoch_next_xid)); - if (oldest_xid <= now_epoch_next_xid) - { - oldest_fxid = FullTransactionIdFromEpochAndXid(now_epoch, oldest_xid); - } - else - { - Assert(now_epoch > 0); - oldest_fxid = FullTransactionIdFromEpochAndXid(now_epoch - 1, oldest_xid); - } - return !FullTransactionIdPrecedes(fxid, oldest_fxid); -} - -/* - * Convert a TransactionId obtained from a snapshot held by the caller to a - * FullTransactionId. Use next_fxid as a reference FullTransactionId, so that - * we can compute the high order bits. It must have been obtained by the - * caller with ReadNextFullTransactionId() after the snapshot was created. - */ -static FullTransactionId -widen_snapshot_xid(TransactionId xid, FullTransactionId next_fxid) -{ - TransactionId next_xid = XidFromFullTransactionId(next_fxid); - uint32 epoch = EpochFromFullTransactionId(next_fxid); - - /* Special transaction ID. */ - if (!TransactionIdIsNormal(xid)) - return FullTransactionIdFromEpochAndXid(0, xid); - - /* - * The 64 bit result must be <= next_fxid, since next_fxid hadn't been - * issued yet when the snapshot was created. Every TransactionId in the - * snapshot must therefore be from the same epoch as next_fxid, or the - * epoch before. We know this because next_fxid is never allow to get - * more than one epoch ahead of the TransactionIds in any snapshot. + * CLOG entry is guaranteed to still exist. + * + * TransamVariables->oldestXid governs allowable XIDs. Usually, + * oldestClogXid==oldestXid. It's also possible for oldestClogXid to + * follow oldestXid, in which case oldestXid might advance after our + * ReadNextFullTransactionId() call. If oldestXid has advanced, that + * advancement reinstated the usual oldestClogXid==oldestXid. Whether or + * not that happened, oldestClogXid is allowable relative to now_fullxid. */ - if (xid > next_xid) - epoch--; - - return FullTransactionIdFromEpochAndXid(epoch, xid); + oldest_clog_xid = TransamVariables->oldestClogXid; + oldest_clog_fxid = + FullTransactionIdFromAllowableAt(now_fullxid, oldest_clog_xid); + return !FullTransactionIdPrecedes(fxid, oldest_clog_fxid); } /* @@ -420,12 +383,18 @@ pg_current_snapshot(PG_FUNCTION_ARGS) nxip = cur->xcnt; snap = palloc(PG_SNAPSHOT_SIZE(nxip)); - /* fill */ - snap->xmin = widen_snapshot_xid(cur->xmin, next_fxid); - snap->xmax = widen_snapshot_xid(cur->xmax, next_fxid); + /* + * Fill. This is the current backend's active snapshot, so MyProc->xmin + * is <= all these XIDs. As long as that remains so, oldestXid can't + * advance past any of these XIDs. Hence, these XIDs remain allowable + * relative to next_fxid. + */ + snap->xmin = FullTransactionIdFromAllowableAt(next_fxid, cur->xmin); + snap->xmax = FullTransactionIdFromAllowableAt(next_fxid, cur->xmax); snap->nxip = nxip; for (i = 0; i < nxip; i++) - snap->xip[i] = widen_snapshot_xid(cur->xip[i], next_fxid); + snap->xip[i] = + FullTransactionIdFromAllowableAt(next_fxid, cur->xip[i]); /* * We want them guaranteed to be in ascending order. This also removes diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 447e72b21eb44..a4150bff2eaea 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -4,7 +4,7 @@ * XML data type support. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/utils/adt/xml.c @@ -344,7 +344,7 @@ xml_out_internal(xmltype *x, pg_enc target_encoding) } ereport(WARNING, - errcode(ERRCODE_INTERNAL_ERROR), + errcode(ERRCODE_DATA_CORRUPTED), errmsg_internal("could not parse XML declaration in stored value"), errdetail_for_xml_code(res_code)); #endif @@ -677,8 +677,14 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) } #ifdef USE_LIBXML - /* Parse the input according to the xmloption */ - doc = xml_parse(data, xmloption_arg, true, GetDatabaseEncoding(), + + /* + * Parse the input according to the xmloption. + * + * preserve_whitespace is set to false in case we are indenting, otherwise + * libxml2 will fail to indent elements that have whitespace between them. + */ + doc = xml_parse(data, xmloption_arg, !indent, GetDatabaseEncoding(), &parsed_xmloptiontype, &content_nodes, (Node *) &escontext); if (doc == NULL || escontext.error_occurred) @@ -736,7 +742,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) { /* If it's a document, saving is easy. */ if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not save document to xmlBuffer"); } else if (content_nodes != NULL) @@ -748,6 +754,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) * content nodes, and then iterate over the nodes. */ xmlNodePtr root; + xmlNodePtr oldroot; xmlNodePtr newline; root = xmlNewNode(NULL, (const xmlChar *) "content-root"); @@ -755,8 +762,14 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not allocate xml node"); - /* This attaches root to doc, so we need not free it separately. */ - xmlDocSetRootElement(doc, root); + /* + * This attaches root to doc, so we need not free it separately... + * but instead, we have to free the old root if there was one. + */ + oldroot = xmlDocSetRootElement(doc, root); + if (oldroot != NULL) + xmlFreeNode(oldroot); + xmlAddChildList(root, content_nodes); /* @@ -779,7 +792,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred) { xmlFreeNode(newline); - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not save newline to xmlBuffer"); } } @@ -787,7 +800,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred) { xmlFreeNode(newline); - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not save content to xmlBuffer"); } } @@ -802,7 +815,22 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) "could not close xmlSaveCtxtPtr"); } - result = (text *) xmlBuffer_to_xmltype(buf); + /* + * xmlDocContentDumpOutput may add a trailing newline, so remove that. + */ + if (xmloption_arg == XMLOPTION_DOCUMENT) + { + const char *str = (const char *) xmlBufferContent(buf); + int len = xmlBufferLength(buf); + + while (len > 0 && (str[len - 1] == '\n' || + str[len - 1] == '\r')) + len--; + + result = cstring_to_text_with_len(str, len); + } + else + result = (text *) xmlBuffer_to_xmltype(buf); } PG_CATCH(); { @@ -983,7 +1011,7 @@ xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null) if (pg_strcasecmp(target, "xml") == 0) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), /* really */ + (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION), errmsg("invalid XML processing instruction"), errdetail("XML processing instruction target name cannot be \"%s\".", target))); @@ -1205,7 +1233,7 @@ pg_xml_init(PgXmlStrictness strictness) errcxt->saved_errcxt = xmlGenericErrorContext; #endif - xmlSetStructuredErrorFunc((void *) errcxt, xml_errorHandler); + xmlSetStructuredErrorFunc(errcxt, xml_errorHandler); /* * Verify that xmlSetStructuredErrorFunc set the context variable we @@ -1227,7 +1255,7 @@ pg_xml_init(PgXmlStrictness strictness) new_errcxt = xmlGenericErrorContext; #endif - if (new_errcxt != (void *) errcxt) + if (new_errcxt != errcxt) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("could not set up XML error handler"), @@ -1281,7 +1309,7 @@ pg_xml_done(PgXmlErrorContext *errcxt, bool isError) cur_errcxt = xmlGenericErrorContext; #endif - if (cur_errcxt != (void *) errcxt) + if (cur_errcxt != errcxt) elog(WARNING, "libxml error handling state is out of sync with xml.c"); /* Restore the saved handlers */ @@ -1829,6 +1857,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg, else { xmlNodePtr root; + xmlNodePtr oldroot PG_USED_FOR_ASSERTS_ONLY; /* set up document with empty root node to be the context node */ doc = xmlNewDoc(version); @@ -1847,8 +1876,13 @@ xml_parse(text *data, XmlOptionType xmloption_arg, if (root == NULL || xmlerrcxt->err_occurred) xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not allocate xml node"); - /* This attaches root to doc, so we need not free it separately. */ - xmlDocSetRootElement(doc, root); + + /* + * This attaches root to doc, so we need not free it separately; + * and there can't yet be any old root to free. + */ + oldroot = xmlDocSetRootElement(doc, root); + Assert(oldroot == NULL); /* allow empty content */ if (*(utf8string + count)) @@ -2176,7 +2210,7 @@ xml_errorHandler(void *data, PgXmlErrorPtr error) xmlGenericErrorFunc errFuncSaved = xmlGenericError; void *errCtxSaved = xmlGenericErrorContext; - xmlSetGenericErrorFunc((void *) errorBuf, + xmlSetGenericErrorFunc(errorBuf, (xmlGenericErrorFunc) appendStringInfo); /* Add context information to errorBuf */ @@ -4362,7 +4396,7 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces, xpath_len = VARSIZE_ANY_EXHDR(xpath_expr_text); if (xpath_len == 0) ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), + (errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY), errmsg("empty XPath expression"))); string = pg_xmlCharStrndup(datastr, len); @@ -4427,9 +4461,15 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces, } } - xpathcomp = xmlXPathCompile(xpath_expr); + /* + * Note: here and elsewhere, be careful to use xmlXPathCtxtCompile not + * xmlXPathCompile. In libxml2 2.13.3 and older, the latter function + * fails to defend itself against recursion-to-stack-overflow. See + * https://gitlab.gnome.org/GNOME/libxml2/-/issues/799 + */ + xpathcomp = xmlXPathCtxtCompile(xpathctx, xpath_expr); if (xpathcomp == NULL || xmlerrcxt->err_occurred) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "invalid XPath expression"); /* @@ -4441,7 +4481,7 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces, */ xpathobj = xmlXPathCompiledEval(xpathcomp, xpathctx); if (xpathobj == NULL || xmlerrcxt->err_occurred) - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "could not create XPath object"); /* @@ -4771,7 +4811,7 @@ XmlTableSetNamespace(TableFuncScanState *state, const char *name, const char *ur if (xmlXPathRegisterNs(xtCxt->xpathcxt, pg_xmlCharStrndup(name, strlen(name)), pg_xmlCharStrndup(uri, strlen(uri)))) - xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_DATA_EXCEPTION, + xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "could not set XML namespace"); #else NO_XML_SUPPORT(); @@ -4793,14 +4833,17 @@ XmlTableSetRowFilter(TableFuncScanState *state, const char *path) if (*path == '\0') ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), + (errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY), errmsg("row path filter must not be empty string"))); xstr = pg_xmlCharStrndup(path, strlen(path)); - xtCxt->xpathcomp = xmlXPathCompile(xstr); + /* We require XmlTableSetDocument to have been done already */ + Assert(xtCxt->xpathcxt != NULL); + + xtCxt->xpathcomp = xmlXPathCtxtCompile(xtCxt->xpathcxt, xstr); if (xtCxt->xpathcomp == NULL || xtCxt->xmlerrcxt->err_occurred) - xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_SYNTAX_ERROR, + xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "invalid XPath expression"); #else NO_XML_SUPPORT(); @@ -4824,14 +4867,17 @@ XmlTableSetColumnFilter(TableFuncScanState *state, const char *path, int colnum) if (*path == '\0') ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), + (errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY), errmsg("column path filter must not be empty string"))); xstr = pg_xmlCharStrndup(path, strlen(path)); - xtCxt->xpathscomp[colnum] = xmlXPathCompile(xstr); + /* We require XmlTableSetDocument to have been done already */ + Assert(xtCxt->xpathcxt != NULL); + + xtCxt->xpathscomp[colnum] = xmlXPathCtxtCompile(xtCxt->xpathcxt, xstr); if (xtCxt->xpathscomp[colnum] == NULL || xtCxt->xmlerrcxt->err_occurred) - xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_DATA_EXCEPTION, + xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "invalid XPath expression"); #else NO_XML_SUPPORT(); @@ -4852,13 +4898,13 @@ XmlTableFetchRow(TableFuncScanState *state) xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableFetchRow"); /* Propagate our own error context to libxml2 */ - xmlSetStructuredErrorFunc((void *) xtCxt->xmlerrcxt, xml_errorHandler); + xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler); if (xtCxt->xpathobj == NULL) { xtCxt->xpathobj = xmlXPathCompiledEval(xtCxt->xpathcomp, xtCxt->xpathcxt); if (xtCxt->xpathobj == NULL || xtCxt->xmlerrcxt->err_occurred) - xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "could not create XPath object"); xtCxt->row_count = 0; @@ -4893,10 +4939,8 @@ XmlTableGetValue(TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull) { #ifdef USE_LIBXML - XmlTableBuilderData *xtCxt; Datum result = (Datum) 0; - xmlNodePtr cur; - char *cstr = NULL; + XmlTableBuilderData *xtCxt; volatile xmlXPathObjectPtr xpathobj = NULL; xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableGetValue"); @@ -4906,23 +4950,25 @@ XmlTableGetValue(TableFuncScanState *state, int colnum, xtCxt->xpathobj->nodesetval != NULL); /* Propagate our own error context to libxml2 */ - xmlSetStructuredErrorFunc((void *) xtCxt->xmlerrcxt, xml_errorHandler); + xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler); *isnull = false; - cur = xtCxt->xpathobj->nodesetval->nodeTab[xtCxt->row_count - 1]; - Assert(xtCxt->xpathscomp[colnum] != NULL); PG_TRY(); { + xmlNodePtr cur; + char *cstr = NULL; + /* Set current node as entry point for XPath evaluation */ + cur = xtCxt->xpathobj->nodesetval->nodeTab[xtCxt->row_count - 1]; xtCxt->xpathcxt->node = cur; /* Evaluate column path */ xpathobj = xmlXPathCompiledEval(xtCxt->xpathscomp[colnum], xtCxt->xpathcxt); if (xpathobj == NULL || xtCxt->xmlerrcxt->err_occurred) - xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR, + xml_ereport(xtCxt->xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, "could not create XPath object"); /* @@ -5049,7 +5095,7 @@ XmlTableDestroyOpaque(TableFuncScanState *state) xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableDestroyOpaque"); /* Propagate our own error context to libxml2 */ - xmlSetStructuredErrorFunc((void *) xtCxt->xmlerrcxt, xml_errorHandler); + xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler); if (xtCxt->xpathscomp != NULL) { diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile index 5105018cb79c8..77b3e1a037b9b 100644 --- a/src/backend/utils/cache/Makefile +++ b/src/backend/utils/cache/Makefile @@ -16,6 +16,7 @@ OBJS = \ attoptcache.o \ catcache.o \ evtcache.o \ + funccache.o \ inval.o \ lsyscache.o \ partcache.o \ diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c index af978ccd4b1ef..5c8360c08b5f8 100644 --- a/src/backend/utils/cache/attoptcache.c +++ b/src/backend/utils/cache/attoptcache.c @@ -6,7 +6,7 @@ * Attribute options are cached separately from the fixed-size portion of * pg_attribute entries, which are handled by the relcache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -44,12 +44,10 @@ typedef struct /* * InvalidateAttoptCacheCallback - * Flush all cache entries when pg_attribute is updated. + * Flush cache entry (or entries) when pg_attribute is updated. * * When pg_attribute is updated, we must flush the cache entry at least - * for that attribute. Currently, we just flush them all. Since attribute - * options are not currently used in performance-critical paths (such as - * query execution), this seems OK. + * for that attribute. */ static void InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue) @@ -57,7 +55,16 @@ InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue) HASH_SEQ_STATUS status; AttoptCacheEntry *attopt; - hash_seq_init(&status, AttoptCacheHash); + /* + * By convention, zero hash value is passed to the callback as a sign that + * it's time to invalidate the whole cache. See sinval.c, inval.c and + * InvalidateSystemCachesExtended(). + */ + if (hashvalue == 0) + hash_seq_init(&status, AttoptCacheHash); + else + hash_seq_init_with_hash_value(&status, AttoptCacheHash, hashvalue); + while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL) { if (attopt->opts) @@ -70,6 +77,18 @@ InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue) } } +/* + * Hash function compatible with two-arg system cache hash function. + */ +static uint32 +relatt_cache_syshash(const void *key, Size keysize) +{ + const AttoptCacheKey *ckey = key; + + Assert(keysize == sizeof(*ckey)); + return GetSysCacheHashValue2(ATTNUM, ckey->attrelid, ckey->attnum); +} + /* * InitializeAttoptCache * Initialize the attribute options cache. @@ -82,9 +101,17 @@ InitializeAttoptCache(void) /* Initialize the hash table. */ ctl.keysize = sizeof(AttoptCacheKey); ctl.entrysize = sizeof(AttoptCacheEntry); + + /* + * AttoptCacheEntry takes hash value from the system cache. For + * AttoptCacheHash we use the same hash in order to speedup search by hash + * value. This is used by hash_seq_init_with_hash_value(). + */ + ctl.hash = relatt_cache_syshash; + AttoptCacheHash = hash_create("Attopt cache", 256, &ctl, - HASH_ELEM | HASH_BLOBS); + HASH_ELEM | HASH_FUNCTION); /* Make sure we've initialized CacheMemoryContext. */ if (!CacheMemoryContext) diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 111d8a280a092..657648996c235 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -3,7 +3,7 @@ * catcache.c * System catalog cache for tuples matching a key. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -34,12 +34,31 @@ #include "utils/catcache.h" #include "utils/datum.h" #include "utils/fmgroids.h" +#include "utils/injection_point.h" #include "utils/inval.h" #include "utils/memutils.h" #include "utils/rel.h" #include "utils/resowner.h" #include "utils/syscache.h" +/* + * If a catcache invalidation is processed while we are in the middle of + * creating a catcache entry (or list), it might apply to the entry we're + * creating, making it invalid before it's been inserted to the catcache. To + * catch such cases, we have a stack of "create-in-progress" entries. Cache + * invalidation marks any matching entries in the stack as dead, in addition + * to the actual CatCTup and CatCList entries. + */ +typedef struct CatCInProgress +{ + CatCache *cache; /* cache that the entry belongs to */ + uint32 hash_value; /* hash of the entry; ignored for lists */ + bool list; /* is it a list entry? */ + bool dead; /* set when the entry is invalidated */ + struct CatCInProgress *next; +} CatCInProgress; + +static CatCInProgress *catcache_in_progress_stack = NULL; /* #define CACHEDEBUG */ /* turns DEBUG elogs on */ @@ -92,8 +111,7 @@ static void CatCacheRemoveCList(CatCache *cache, CatCList *cl); static void RehashCatCache(CatCache *cp); static void RehashCatCacheLists(CatCache *cp); static void CatalogCacheInitializeCache(CatCache *cache); -static CatCTup *CatalogCacheCreateEntry(CatCache *cache, - HeapTuple ntp, SysScanDesc scandesc, +static CatCTup *CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex); @@ -661,6 +679,16 @@ CatCacheInvalidate(CatCache *cache, uint32 hashValue) /* could be multiple matches, so keep looking! */ } } + + /* Also invalidate any entries that are being built */ + for (CatCInProgress *e = catcache_in_progress_stack; e != NULL; e = e->next) + { + if (e->cache == cache) + { + if (e->list || e->hash_value == hashValue) + e->dead = true; + } + } } /* ---------------------------------------------------------------- @@ -697,9 +725,15 @@ CreateCacheMemoryContext(void) * * This is not very efficient if the target cache is nearly empty. * However, it shouldn't need to be efficient; we don't invoke it often. + * + * If 'debug_discard' is true, we are being called as part of + * debug_discard_caches. In that case, the cache is not reset for + * correctness, but just to get more testing of cache invalidation. We skip + * resetting in-progress build entries in that case, or we'd never make any + * progress. */ static void -ResetCatalogCache(CatCache *cache) +ResetCatalogCache(CatCache *cache, bool debug_discard) { dlist_mutable_iter iter; int i; @@ -743,6 +777,16 @@ ResetCatalogCache(CatCache *cache) #endif } } + + /* Also invalidate any entries that are being built */ + if (!debug_discard) + { + for (CatCInProgress *e = catcache_in_progress_stack; e != NULL; e = e->next) + { + if (e->cache == cache) + e->dead = true; + } + } } /* @@ -752,6 +796,12 @@ ResetCatalogCache(CatCache *cache) */ void ResetCatalogCaches(void) +{ + ResetCatalogCachesExt(false); +} + +void +ResetCatalogCachesExt(bool debug_discard) { slist_iter iter; @@ -761,7 +811,7 @@ ResetCatalogCaches(void) { CatCache *cache = slist_container(CatCache, cc_next, iter.cur); - ResetCatalogCache(cache); + ResetCatalogCache(cache, debug_discard); } CACHE_elog(DEBUG2, "end of ResetCatalogCaches call"); @@ -795,7 +845,7 @@ CatalogCacheFlushCatalog(Oid catId) if (cache->cc_reloid == catId) { /* Yes, so flush all its contents */ - ResetCatalogCache(cache); + ResetCatalogCache(cache, false); /* Tell inval.c to call syscache callbacks for this cache */ CallSyscacheCallbacks(cache->id, 0); @@ -1004,12 +1054,41 @@ RehashCatCacheLists(CatCache *cp) cp->cc_lbucket = newbucket; } +/* + * ConditionalCatalogCacheInitializeCache + * + * Call CatalogCacheInitializeCache() if not yet done. + */ +pg_attribute_always_inline +static void +ConditionalCatalogCacheInitializeCache(CatCache *cache) +{ +#ifdef USE_ASSERT_CHECKING + /* + * TypeCacheRelCallback() runs outside transactions and relies on TYPEOID + * for hashing. This isn't ideal. Since lookup_type_cache() both + * registers the callback and searches TYPEOID, reaching trouble likely + * requires OOM at an unlucky moment. + * + * InvalidateAttoptCacheCallback() runs outside transactions and likewise + * relies on ATTNUM. InitPostgres() initializes ATTNUM, so it's reliable. + */ + if (!(cache->id == TYPEOID || cache->id == ATTNUM) || + IsTransactionState()) + AssertCouldGetRelation(); + else + Assert(cache->cc_tupdesc != NULL); +#endif + + if (unlikely(cache->cc_tupdesc == NULL)) + CatalogCacheInitializeCache(cache); +} + /* * CatalogCacheInitializeCache * * This function does final initialization of a catcache: obtain the tuple - * descriptor and set up the hash and equality function links. We assume - * that the relcache entry can be opened at this point! + * descriptor and set up the hash and equality function links. */ #ifdef CACHEDEBUG #define CatalogCacheInitializeCache_DEBUG1 \ @@ -1144,8 +1223,7 @@ CatalogCacheInitializeCache(CatCache *cache) void InitCatCachePhase2(CatCache *cache, bool touch_index) { - if (cache->cc_tupdesc == NULL) - CatalogCacheInitializeCache(cache); + ConditionalCatalogCacheInitializeCache(cache); if (touch_index && cache->id != AMOID && @@ -1194,7 +1272,7 @@ InitCatCachePhase2(CatCache *cache, bool touch_index) * catalogs' indexes. */ static bool -IndexScanOK(CatCache *cache, ScanKey cur_skey) +IndexScanOK(CatCache *cache) { switch (cache->id) { @@ -1324,16 +1402,12 @@ SearchCatCacheInternal(CatCache *cache, dlist_head *bucket; CatCTup *ct; - /* Make sure we're in an xact, even if this ends up being a cache hit */ - Assert(IsTransactionState()); - Assert(cache->cc_nkeys == nkeys); /* * one-time startup overhead for each cache */ - if (unlikely(cache->cc_tupdesc == NULL)) - CatalogCacheInitializeCache(cache); + ConditionalCatalogCacheInitializeCache(cache); #ifdef CATCACHE_STATS cache->cc_searches++; @@ -1468,22 +1542,21 @@ SearchCatCacheMiss(CatCache *cache, */ relation = table_open(cache->cc_reloid, AccessShareLock); + /* + * Ok, need to make a lookup in the relation, copy the scankey and fill + * out any per-call fields. + */ + memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys); + cur_skey[0].sk_argument = v1; + cur_skey[1].sk_argument = v2; + cur_skey[2].sk_argument = v3; + cur_skey[3].sk_argument = v4; + do { - /* - * Ok, need to make a lookup in the relation, copy the scankey and - * fill out any per-call fields. (We must re-do this when retrying, - * because systable_beginscan scribbles on the scankey.) - */ - memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys); - cur_skey[0].sk_argument = v1; - cur_skey[1].sk_argument = v2; - cur_skey[2].sk_argument = v3; - cur_skey[3].sk_argument = v4; - scandesc = systable_beginscan(relation, cache->cc_indexoid, - IndexScanOK(cache, cur_skey), + IndexScanOK(cache), NULL, nkeys, cur_skey); @@ -1493,7 +1566,7 @@ SearchCatCacheMiss(CatCache *cache, while (HeapTupleIsValid(ntp = systable_getnext(scandesc))) { - ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL, + ct = CatalogCacheCreateEntry(cache, ntp, NULL, hashValue, hashIndex); /* upon failure, we must start the scan over */ if (ct == NULL) @@ -1528,7 +1601,7 @@ SearchCatCacheMiss(CatCache *cache, if (IsBootstrapProcessingMode()) return NULL; - ct = CatalogCacheCreateEntry(cache, NULL, NULL, arguments, + ct = CatalogCacheCreateEntry(cache, NULL, arguments, hashValue, hashIndex); /* Creating a negative cache entry shouldn't fail */ @@ -1619,8 +1692,7 @@ GetCatCacheHashValue(CatCache *cache, /* * one-time startup overhead for each cache */ - if (cache->cc_tupdesc == NULL) - CatalogCacheInitializeCache(cache); + ConditionalCatalogCacheInitializeCache(cache); /* * calculate the hash value @@ -1665,12 +1737,13 @@ SearchCatCacheList(CatCache *cache, HeapTuple ntp; MemoryContext oldcxt; int i; + CatCInProgress *save_in_progress; + CatCInProgress in_progress_ent; /* * one-time startup overhead for each cache */ - if (unlikely(cache->cc_tupdesc == NULL)) - CatalogCacheInitializeCache(cache); + ConditionalCatalogCacheInitializeCache(cache); Assert(nkeys > 0 && nkeys < cache->cc_nkeys); @@ -1779,31 +1852,70 @@ SearchCatCacheList(CatCache *cache, */ ctlist = NIL; + /* + * Cache invalidation can happen while we're building the list. + * CatalogCacheCreateEntry() handles concurrent invalidation of individual + * tuples, but it's also possible that a new entry is concurrently added + * that should be part of the list we're building. Register an + * "in-progress" entry that will receive the invalidation, until we have + * built the final list entry. + */ + save_in_progress = catcache_in_progress_stack; + in_progress_ent.next = catcache_in_progress_stack; + in_progress_ent.cache = cache; + in_progress_ent.hash_value = lHashValue; + in_progress_ent.list = true; + in_progress_ent.dead = false; + catcache_in_progress_stack = &in_progress_ent; + PG_TRY(); { ScanKeyData cur_skey[CATCACHE_MAXKEYS]; Relation relation; SysScanDesc scandesc; - bool stale; + bool first_iter = true; relation = table_open(cache->cc_reloid, AccessShareLock); + /* + * Ok, need to make a lookup in the relation, copy the scankey and + * fill out any per-call fields. + */ + memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys); + cur_skey[0].sk_argument = v1; + cur_skey[1].sk_argument = v2; + cur_skey[2].sk_argument = v3; + cur_skey[3].sk_argument = v4; + + /* + * Scan the table for matching entries. If an invalidation arrives + * mid-build, we will loop back here to retry. + */ do { /* - * Ok, need to make a lookup in the relation, copy the scankey and - * fill out any per-call fields. (We must re-do this when - * retrying, because systable_beginscan scribbles on the scankey.) + * If we are retrying, release refcounts on any items created on + * the previous iteration. We dare not try to free them if + * they're now unreferenced, since an error while doing that would + * result in the PG_CATCH below doing extra refcount decrements. + * Besides, we'll likely re-adopt those items in the next + * iteration, so it's not worth complicating matters to try to get + * rid of them. */ - memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys); - cur_skey[0].sk_argument = v1; - cur_skey[1].sk_argument = v2; - cur_skey[2].sk_argument = v3; - cur_skey[3].sk_argument = v4; + foreach(ctlist_item, ctlist) + { + ct = (CatCTup *) lfirst(ctlist_item); + Assert(ct->c_list == NULL); + Assert(ct->refcount > 0); + ct->refcount--; + } + /* Reset ctlist in preparation for new try */ + ctlist = NIL; + in_progress_ent.dead = false; scandesc = systable_beginscan(relation, cache->cc_indexoid, - IndexScanOK(cache, cur_skey), + IndexScanOK(cache), NULL, nkeys, cur_skey); @@ -1811,9 +1923,15 @@ SearchCatCacheList(CatCache *cache, /* The list will be ordered iff we are doing an index scan */ ordered = (scandesc->irel != NULL); - stale = false; + /* Injection point to help testing the recursive invalidation case */ + if (first_iter) + { + INJECTION_POINT("catcache-list-miss-systable-scan-started", NULL); + first_iter = false; + } - while (HeapTupleIsValid(ntp = systable_getnext(scandesc))) + while (HeapTupleIsValid(ntp = systable_getnext(scandesc)) && + !in_progress_ent.dead) { uint32 hashValue; Index hashIndex; @@ -1855,30 +1973,13 @@ SearchCatCacheList(CatCache *cache, if (!found) { /* We didn't find a usable entry, so make a new one */ - ct = CatalogCacheCreateEntry(cache, ntp, scandesc, NULL, + ct = CatalogCacheCreateEntry(cache, ntp, NULL, hashValue, hashIndex); + /* upon failure, we must start the scan over */ if (ct == NULL) { - /* - * Release refcounts on any items we already had. We - * dare not try to free them if they're now - * unreferenced, since an error while doing that would - * result in the PG_CATCH below doing extra refcount - * decrements. Besides, we'll likely re-adopt those - * items in the next iteration, so it's not worth - * complicating matters to try to get rid of them. - */ - foreach(ctlist_item, ctlist) - { - ct = (CatCTup *) lfirst(ctlist_item); - Assert(ct->c_list == NULL); - Assert(ct->refcount > 0); - ct->refcount--; - } - /* Reset ctlist in preparation for new try */ - ctlist = NIL; - stale = true; + in_progress_ent.dead = true; break; } } @@ -1890,7 +1991,7 @@ SearchCatCacheList(CatCache *cache, } systable_endscan(scandesc); - } while (stale); + } while (in_progress_ent.dead); table_close(relation, AccessShareLock); @@ -1918,6 +2019,9 @@ SearchCatCacheList(CatCache *cache, } PG_CATCH(); { + Assert(catcache_in_progress_stack == &in_progress_ent); + catcache_in_progress_stack = save_in_progress; + foreach(ctlist_item, ctlist) { ct = (CatCTup *) lfirst(ctlist_item); @@ -1936,6 +2040,8 @@ SearchCatCacheList(CatCache *cache, PG_RE_THROW(); } PG_END_TRY(); + Assert(catcache_in_progress_stack == &in_progress_ent); + catcache_in_progress_stack = save_in_progress; cl->cl_magic = CL_MAGIC; cl->my_cache = cache; @@ -2008,23 +2114,6 @@ ReleaseCatCacheListWithOwner(CatCList *list, ResourceOwner resowner) } -/* - * equalTuple - * Are these tuples memcmp()-equal? - */ -static bool -equalTuple(HeapTuple a, HeapTuple b) -{ - uint32 alen; - uint32 blen; - - alen = a->t_len; - blen = b->t_len; - return (alen == blen && - memcmp((char *) a->t_data, - (char *) b->t_data, blen) == 0); -} - /* * CatalogCacheCreateEntry * Create a new CatCTup entry, copying the given HeapTuple and other @@ -2032,34 +2121,33 @@ equalTuple(HeapTuple a, HeapTuple b) * * To create a normal cache entry, ntp must be the HeapTuple just fetched * from scandesc, and "arguments" is not used. To create a negative cache - * entry, pass NULL for ntp and scandesc; then "arguments" is the cache - * keys to use. In either case, hashValue/hashIndex are the hash values - * computed from the cache keys. + * entry, pass NULL for ntp; then "arguments" is the cache keys to use. + * In either case, hashValue/hashIndex are the hash values computed from + * the cache keys. * * Returns NULL if we attempt to detoast the tuple and observe that it * became stale. (This cannot happen for a negative entry.) Caller must * retry the tuple lookup in that case. */ static CatCTup * -CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, - Datum *arguments, +CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, Datum *arguments, uint32 hashValue, Index hashIndex) { CatCTup *ct; - HeapTuple dtp; MemoryContext oldcxt; if (ntp) { int i; + HeapTuple dtp = NULL; /* - * The visibility recheck below essentially never fails during our - * regression tests, and there's no easy way to force it to fail for - * testing purposes. To ensure we have test coverage for the retry - * paths in our callers, make debug builds randomly fail about 0.1% of - * the times through this code path, even when there's no toasted - * fields. + * The invalidation of the in-progress entry essentially never happens + * during our regression tests, and there's no easy way to force it to + * fail for testing purposes. To ensure we have test coverage for the + * retry paths in our callers, make debug builds randomly fail about + * 0.1% of the times through this code path, even when there's no + * toasted fields. */ #ifdef USE_ASSERT_CHECKING if (pg_prng_uint32(&pg_global_prng_state) <= (PG_UINT32_MAX / 1000)) @@ -2075,34 +2163,34 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, */ if (HeapTupleHasExternal(ntp)) { - bool need_cmp = IsInplaceUpdateOid(cache->cc_reloid); - HeapTuple before = NULL; - bool matches = true; - - if (need_cmp) - before = heap_copytuple(ntp); - dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc); + CatCInProgress *save_in_progress; + CatCInProgress in_progress_ent; /* * The tuple could become stale while we are doing toast table - * access (since AcceptInvalidationMessages can run then). - * equalTuple() detects staleness from inplace updates, while - * systable_recheck_tuple() detects staleness from normal updates. - * - * While this equalTuple() follows the usual rule of reading with - * a pin and no buffer lock, it warrants suspicion since an - * inplace update could appear at any moment. It's safe because - * the inplace update sends an invalidation that can't reorder - * before the inplace heap change. If the heap change reaches - * this process just after equalTuple() looks, we've not missed - * its inval. + * access (since AcceptInvalidationMessages can run then). The + * invalidation will mark our in-progress entry as dead. */ - if (need_cmp) + save_in_progress = catcache_in_progress_stack; + in_progress_ent.next = catcache_in_progress_stack; + in_progress_ent.cache = cache; + in_progress_ent.hash_value = hashValue; + in_progress_ent.list = false; + in_progress_ent.dead = false; + catcache_in_progress_stack = &in_progress_ent; + + PG_TRY(); { - matches = equalTuple(before, ntp); - heap_freetuple(before); + dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc); } - if (!matches || !systable_recheck_tuple(scandesc, ntp)) + PG_FINALLY(); + { + Assert(catcache_in_progress_stack == &in_progress_ent); + catcache_in_progress_stack = save_in_progress; + } + PG_END_TRY(); + + if (in_progress_ent.dead) { heap_freetuple(dtp); return NULL; @@ -2288,7 +2376,8 @@ void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, - void (*function) (int, uint32, Oid)) + void (*function) (int, uint32, Oid, void *), + void *context) { slist_iter iter; Oid reloid; @@ -2323,13 +2412,12 @@ PrepareToInvalidateCacheTuple(Relation relation, continue; /* Just in case cache hasn't finished initialization yet... */ - if (ccp->cc_tupdesc == NULL) - CatalogCacheInitializeCache(ccp); + ConditionalCatalogCacheInitializeCache(ccp); hashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, tuple); dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId; - (*function) (ccp->id, hashvalue, dbid); + (*function) (ccp->id, hashvalue, dbid, context); if (newtuple) { @@ -2338,7 +2426,7 @@ PrepareToInvalidateCacheTuple(Relation relation, newhashvalue = CatalogCacheComputeTupleHashValue(ccp, ccp->cc_nkeys, newtuple); if (newhashvalue != hashvalue) - (*function) (ccp->id, newhashvalue, dbid); + (*function) (ccp->id, newhashvalue, dbid, context); } } } diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c index 185b52e669dea..ce596bf563856 100644 --- a/src/backend/utils/cache/evtcache.c +++ b/src/backend/utils/cache/evtcache.c @@ -3,7 +3,7 @@ * evtcache.c * Special-purpose cache for event trigger data. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/cache/funccache.c b/src/backend/utils/cache/funccache.c new file mode 100644 index 0000000000000..afc048a051ead --- /dev/null +++ b/src/backend/utils/cache/funccache.c @@ -0,0 +1,634 @@ +/*------------------------------------------------------------------------- + * + * funccache.c + * Function cache management. + * + * funccache.c manages a cache of function execution data. The cache + * is used by SQL-language and PL/pgSQL functions, and could be used by + * other function languages. Each cache entry is specific to the execution + * of a particular function (identified by OID) with specific input data + * types; so a polymorphic function could have many associated cache entries. + * Trigger functions similarly have a cache entry per trigger. These rules + * allow the cached data to be specific to the particular data types the + * function call will be dealing with. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/utils/cache/funccache.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "catalog/pg_proc.h" +#include "commands/event_trigger.h" +#include "commands/trigger.h" +#include "common/hashfn.h" +#include "funcapi.h" +#include "utils/funccache.h" +#include "utils/hsearch.h" +#include "utils/syscache.h" + + +/* + * Hash table for cached functions + */ +static HTAB *cfunc_hashtable = NULL; + +typedef struct CachedFunctionHashEntry +{ + CachedFunctionHashKey key; /* hash key, must be first */ + CachedFunction *function; /* points to data of language-specific size */ +} CachedFunctionHashEntry; + +#define FUNCS_PER_USER 128 /* initial table size */ + +static uint32 cfunc_hash(const void *key, Size keysize); +static int cfunc_match(const void *key1, const void *key2, Size keysize); + + +/* + * Initialize the hash table on first use. + * + * The hash table will be in TopMemoryContext regardless of caller's context. + */ +static void +cfunc_hashtable_init(void) +{ + HASHCTL ctl; + + /* don't allow double-initialization */ + Assert(cfunc_hashtable == NULL); + + ctl.keysize = sizeof(CachedFunctionHashKey); + ctl.entrysize = sizeof(CachedFunctionHashEntry); + ctl.hash = cfunc_hash; + ctl.match = cfunc_match; + cfunc_hashtable = hash_create("Cached function hash", + FUNCS_PER_USER, + &ctl, + HASH_ELEM | HASH_FUNCTION | HASH_COMPARE); +} + +/* + * cfunc_hash: hash function for cfunc hash table + * + * We need special hash and match functions to deal with the optional + * presence of a TupleDesc in the hash keys. As long as we have to do + * that, we might as well also be smart about not comparing unused + * elements of the argtypes arrays. + */ +static uint32 +cfunc_hash(const void *key, Size keysize) +{ + const CachedFunctionHashKey *k = (const CachedFunctionHashKey *) key; + uint32 h; + + Assert(keysize == sizeof(CachedFunctionHashKey)); + /* Hash all the fixed fields except callResultType */ + h = DatumGetUInt32(hash_any((const unsigned char *) k, + offsetof(CachedFunctionHashKey, callResultType))); + /* Incorporate input argument types */ + if (k->nargs > 0) + h = hash_combine(h, + DatumGetUInt32(hash_any((const unsigned char *) k->argtypes, + k->nargs * sizeof(Oid)))); + /* Incorporate callResultType if present */ + if (k->callResultType) + h = hash_combine(h, hashRowType(k->callResultType)); + return h; +} + +/* + * cfunc_match: match function to use with cfunc_hash + */ +static int +cfunc_match(const void *key1, const void *key2, Size keysize) +{ + const CachedFunctionHashKey *k1 = (const CachedFunctionHashKey *) key1; + const CachedFunctionHashKey *k2 = (const CachedFunctionHashKey *) key2; + + Assert(keysize == sizeof(CachedFunctionHashKey)); + /* Compare all the fixed fields except callResultType */ + if (memcmp(k1, k2, offsetof(CachedFunctionHashKey, callResultType)) != 0) + return 1; /* not equal */ + /* Compare input argument types (we just verified that nargs matches) */ + if (k1->nargs > 0 && + memcmp(k1->argtypes, k2->argtypes, k1->nargs * sizeof(Oid)) != 0) + return 1; /* not equal */ + /* Compare callResultType */ + if (k1->callResultType) + { + if (k2->callResultType) + { + if (!equalRowTypes(k1->callResultType, k2->callResultType)) + return 1; /* not equal */ + } + else + return 1; /* not equal */ + } + else + { + if (k2->callResultType) + return 1; /* not equal */ + } + return 0; /* equal */ +} + +/* + * Look up the CachedFunction for the given hash key. + * Returns NULL if not present. + */ +static CachedFunction * +cfunc_hashtable_lookup(CachedFunctionHashKey *func_key) +{ + CachedFunctionHashEntry *hentry; + + if (cfunc_hashtable == NULL) + return NULL; + + hentry = (CachedFunctionHashEntry *) hash_search(cfunc_hashtable, + func_key, + HASH_FIND, + NULL); + if (hentry) + return hentry->function; + else + return NULL; +} + +/* + * Insert a hash table entry. + */ +static void +cfunc_hashtable_insert(CachedFunction *function, + CachedFunctionHashKey *func_key) +{ + CachedFunctionHashEntry *hentry; + bool found; + + if (cfunc_hashtable == NULL) + cfunc_hashtable_init(); + + hentry = (CachedFunctionHashEntry *) hash_search(cfunc_hashtable, + func_key, + HASH_ENTER, + &found); + if (found) + elog(WARNING, "trying to insert a function that already exists"); + + /* + * If there's a callResultType, copy it into TopMemoryContext. If we're + * unlucky enough for that to fail, leave the entry with null + * callResultType, which will probably never match anything. + */ + if (func_key->callResultType) + { + MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext); + + hentry->key.callResultType = NULL; + hentry->key.callResultType = CreateTupleDescCopy(func_key->callResultType); + MemoryContextSwitchTo(oldcontext); + } + + hentry->function = function; + + /* Set back-link from function to hashtable key */ + function->fn_hashkey = &hentry->key; +} + +/* + * Delete a hash table entry. + */ +static void +cfunc_hashtable_delete(CachedFunction *function) +{ + CachedFunctionHashEntry *hentry; + TupleDesc tupdesc; + + /* do nothing if not in table */ + if (function->fn_hashkey == NULL) + return; + + /* + * We need to free the callResultType if present, which is slightly tricky + * because it has to be valid during the hashtable search. Fortunately, + * because we have the hashkey back-link, we can grab that pointer before + * deleting the hashtable entry. + */ + tupdesc = function->fn_hashkey->callResultType; + + hentry = (CachedFunctionHashEntry *) hash_search(cfunc_hashtable, + function->fn_hashkey, + HASH_REMOVE, + NULL); + if (hentry == NULL) + elog(WARNING, "trying to delete function that does not exist"); + + /* Remove back link, which no longer points to allocated storage */ + function->fn_hashkey = NULL; + + /* Release the callResultType if present */ + if (tupdesc) + FreeTupleDesc(tupdesc); +} + +/* + * Compute the hashkey for a given function invocation + * + * The hashkey is returned into the caller-provided storage at *hashkey. + * Note however that if a callResultType is incorporated, we've not done + * anything about copying that. + */ +static void +compute_function_hashkey(FunctionCallInfo fcinfo, + Form_pg_proc procStruct, + CachedFunctionHashKey *hashkey, + Size cacheEntrySize, + bool includeResultType, + bool forValidator) +{ + /* Make sure pad bytes within fixed part of the struct are zero */ + memset(hashkey, 0, offsetof(CachedFunctionHashKey, argtypes)); + + /* get function OID */ + hashkey->funcOid = fcinfo->flinfo->fn_oid; + + /* get call context */ + hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo); + hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo); + + /* record cacheEntrySize so multiple languages can share hash table */ + hashkey->cacheEntrySize = cacheEntrySize; + + /* + * If DML trigger, include trigger's OID in the hash, so that each trigger + * usage gets a different hash entry, allowing for e.g. different relation + * rowtypes or transition table names. In validation mode we do not know + * what relation or transition table names are intended to be used, so we + * leave trigOid zero; the hash entry built in this case will never be + * used for any actual calls. + * + * We don't currently need to distinguish different event trigger usages + * in the same way, since the special parameter variables don't vary in + * type in that case. + */ + if (hashkey->isTrigger && !forValidator) + { + TriggerData *trigdata = (TriggerData *) fcinfo->context; + + hashkey->trigOid = trigdata->tg_trigger->tgoid; + } + + /* get input collation, if known */ + hashkey->inputCollation = fcinfo->fncollation; + + /* + * We include only input arguments in the hash key, since output argument + * types can be deduced from those, and it would require extra cycles to + * include the output arguments. But we have to resolve any polymorphic + * argument types to the real types for the call. + */ + if (procStruct->pronargs > 0) + { + hashkey->nargs = procStruct->pronargs; + memcpy(hashkey->argtypes, procStruct->proargtypes.values, + procStruct->pronargs * sizeof(Oid)); + cfunc_resolve_polymorphic_argtypes(procStruct->pronargs, + hashkey->argtypes, + NULL, /* all args are inputs */ + fcinfo->flinfo->fn_expr, + forValidator, + NameStr(procStruct->proname)); + } + + /* + * While regular OUT arguments are sufficiently represented by the + * resolved input arguments, a function returning composite has additional + * variability: ALTER TABLE/ALTER TYPE could affect what it returns. Also, + * a function returning RECORD may depend on a column definition list to + * determine its output rowtype. If the caller needs the exact result + * type to be part of the hash lookup key, we must run + * get_call_result_type() to find that out. + */ + if (includeResultType) + { + Oid resultTypeId; + TupleDesc tupdesc; + + switch (get_call_result_type(fcinfo, &resultTypeId, &tupdesc)) + { + case TYPEFUNC_COMPOSITE: + case TYPEFUNC_COMPOSITE_DOMAIN: + hashkey->callResultType = tupdesc; + break; + default: + /* scalar result, or indeterminate rowtype */ + break; + } + } +} + +/* + * This is the same as the standard resolve_polymorphic_argtypes() function, + * except that: + * 1. We go ahead and report the error if we can't resolve the types. + * 2. We treat RECORD-type input arguments (not output arguments) as if + * they were polymorphic, replacing their types with the actual input + * types if we can determine those. This allows us to create a separate + * function cache entry for each named composite type passed to such an + * argument. + * 3. In validation mode, we have no inputs to look at, so assume that + * polymorphic arguments are integer, integer-array or integer-range. + */ +void +cfunc_resolve_polymorphic_argtypes(int numargs, + Oid *argtypes, char *argmodes, + Node *call_expr, bool forValidator, + const char *proname) +{ + int i; + + if (!forValidator) + { + int inargno; + + /* normal case, pass to standard routine */ + if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes, + call_expr)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("could not determine actual argument " + "type for polymorphic function \"%s\"", + proname))); + /* also, treat RECORD inputs (but not outputs) as polymorphic */ + inargno = 0; + for (i = 0; i < numargs; i++) + { + char argmode = argmodes ? argmodes[i] : PROARGMODE_IN; + + if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE) + continue; + if (argtypes[i] == RECORDOID || argtypes[i] == RECORDARRAYOID) + { + Oid resolvedtype = get_call_expr_argtype(call_expr, + inargno); + + if (OidIsValid(resolvedtype)) + argtypes[i] = resolvedtype; + } + inargno++; + } + } + else + { + /* special validation case (no need to do anything for RECORD) */ + for (i = 0; i < numargs; i++) + { + switch (argtypes[i]) + { + case ANYELEMENTOID: + case ANYNONARRAYOID: + case ANYENUMOID: /* XXX dubious */ + case ANYCOMPATIBLEOID: + case ANYCOMPATIBLENONARRAYOID: + argtypes[i] = INT4OID; + break; + case ANYARRAYOID: + case ANYCOMPATIBLEARRAYOID: + argtypes[i] = INT4ARRAYOID; + break; + case ANYRANGEOID: + case ANYCOMPATIBLERANGEOID: + argtypes[i] = INT4RANGEOID; + break; + case ANYMULTIRANGEOID: + argtypes[i] = INT4MULTIRANGEOID; + break; + default: + break; + } + } + } +} + +/* + * delete_function - clean up as much as possible of a stale function cache + * + * We can't release the CachedFunction struct itself, because of the + * possibility that there are fn_extra pointers to it. We can release + * the subsidiary storage, but only if there are no active evaluations + * in progress. Otherwise we'll just leak that storage. Since the + * case would only occur if a pg_proc update is detected during a nested + * recursive call on the function, a leak seems acceptable. + * + * Note that this can be called more than once if there are multiple fn_extra + * pointers to the same function cache. Hence be careful not to do things + * twice. + */ +static void +delete_function(CachedFunction *func) +{ + /* remove function from hash table (might be done already) */ + cfunc_hashtable_delete(func); + + /* release the function's storage if safe and not done already */ + if (func->use_count == 0 && + func->dcallback != NULL) + { + func->dcallback(func); + func->dcallback = NULL; + } +} + +/* + * Compile a cached function, if no existing cache entry is suitable. + * + * fcinfo is the current call information. + * + * function should be NULL or the result of a previous call of + * cached_function_compile() for the same fcinfo. The caller will + * typically save the result in fcinfo->flinfo->fn_extra, or in a + * field of a struct pointed to by fn_extra, to re-use in later + * calls within the same query. + * + * ccallback and dcallback are function-language-specific callbacks to + * compile and delete a cached function entry. dcallback can be NULL + * if there's nothing for it to do. + * + * cacheEntrySize is the function-language-specific size of the cache entry + * (which embeds a CachedFunction struct and typically has many more fields + * after that). + * + * If includeResultType is true and the function returns composite, + * include the actual result descriptor in the cache lookup key. + * + * If forValidator is true, we're only compiling for validation purposes, + * and so some checks are skipped. + * + * Note: it's important for this to fall through quickly if the function + * has already been compiled. + * + * Note: this function leaves the "use_count" field as zero. The caller + * is expected to increment the use_count and decrement it when done with + * the cache entry. + */ +CachedFunction * +cached_function_compile(FunctionCallInfo fcinfo, + CachedFunction *function, + CachedFunctionCompileCallback ccallback, + CachedFunctionDeleteCallback dcallback, + Size cacheEntrySize, + bool includeResultType, + bool forValidator) +{ + Oid funcOid = fcinfo->flinfo->fn_oid; + HeapTuple procTup; + Form_pg_proc procStruct; + CachedFunctionHashKey hashkey; + bool function_valid = false; + bool hashkey_valid = false; + bool new_function = false; + + /* + * Lookup the pg_proc tuple by Oid; we'll need it in any case + */ + procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid)); + if (!HeapTupleIsValid(procTup)) + elog(ERROR, "cache lookup failed for function %u", funcOid); + procStruct = (Form_pg_proc) GETSTRUCT(procTup); + + /* + * Do we already have a cache entry for the current FmgrInfo? If not, try + * to find one in the hash table. + */ +recheck: + if (!function) + { + /* Compute hashkey using function signature and actual arg types */ + compute_function_hashkey(fcinfo, procStruct, &hashkey, + cacheEntrySize, includeResultType, + forValidator); + hashkey_valid = true; + + /* And do the lookup */ + function = cfunc_hashtable_lookup(&hashkey); + } + + if (function) + { + /* We have a compiled function, but is it still valid? */ + if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) && + ItemPointerEquals(&function->fn_tid, &procTup->t_self)) + function_valid = true; + else + { + /* + * Nope, so remove it from hashtable and try to drop associated + * storage (if not done already). + */ + delete_function(function); + + /* + * If the function isn't in active use then we can overwrite the + * func struct with new data, allowing any other existing fn_extra + * pointers to make use of the new definition on their next use. + * If it is in use then just leave it alone and make a new one. + * (The active invocations will run to completion using the + * previous definition, and then the cache entry will just be + * leaked; doesn't seem worth adding code to clean it up, given + * what a corner case this is.) + * + * If we found the function struct via fn_extra then it's possible + * a replacement has already been made, so go back and recheck the + * hashtable. + */ + if (function->use_count != 0) + { + function = NULL; + if (!hashkey_valid) + goto recheck; + } + } + } + + /* + * If the function wasn't found or was out-of-date, we have to compile it. + */ + if (!function_valid) + { + /* + * Calculate hashkey if we didn't already; we'll need it to store the + * completed function. + */ + if (!hashkey_valid) + compute_function_hashkey(fcinfo, procStruct, &hashkey, + cacheEntrySize, includeResultType, + forValidator); + + /* + * Create the new function struct, if not done already. The function + * cache entry will be kept for the life of the backend, so put it in + * TopMemoryContext. + */ + Assert(cacheEntrySize >= sizeof(CachedFunction)); + if (function == NULL) + { + function = (CachedFunction *) + MemoryContextAllocZero(TopMemoryContext, cacheEntrySize); + new_function = true; + } + else + { + /* re-using a previously existing struct, so clear it out */ + memset(function, 0, cacheEntrySize); + } + + /* + * However, if function compilation fails, we'd like not to leak the + * function struct, so use a PG_TRY block to prevent that. (It's up + * to the compile callback function to avoid its own internal leakage + * in such cases.) Unfortunately, freeing the struct is only safe if + * we just allocated it: otherwise there are probably fn_extra + * pointers to it. + */ + PG_TRY(); + { + /* + * Do the hard, language-specific part. + */ + ccallback(fcinfo, procTup, &hashkey, function, forValidator); + } + PG_CATCH(); + { + if (new_function) + pfree(function); + PG_RE_THROW(); + } + PG_END_TRY(); + + /* + * Fill in the CachedFunction part. (We do this last to prevent the + * function from looking valid before it's fully built.) fn_hashkey + * will be set by cfunc_hashtable_insert; use_count remains zero. + */ + function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data); + function->fn_tid = procTup->t_self; + function->dcallback = dcallback; + + /* + * Add the completed struct to the hash table. + */ + cfunc_hashtable_insert(function, &hashkey); + } + + ReleaseSysCache(procTup); + + /* + * Finally return the compiled function + */ + return function; +} diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 603aa4157bef1..02505c88b8e4c 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -94,11 +94,15 @@ * worth trying to avoid sending such inval traffic in the future, if those * problems can be overcome cheaply. * + * When making a nontransactional change to a cacheable object, we must + * likewise send the invalidation immediately, before ending the change's + * critical section. This includes inplace heap updates, relmap, and smgr. + * * When wal_level=logical, write invalidations into WAL at each command end to * support the decoding of the in-progress transactions. See * CommandEndInvalidationMessages. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -116,9 +120,11 @@ #include "catalog/catalog.h" #include "catalog/pg_constraint.h" #include "miscadmin.h" +#include "storage/procnumber.h" #include "storage/sinval.h" #include "storage/smgr.h" #include "utils/catcache.h" +#include "utils/injection_point.h" #include "utils/inval.h" #include "utils/memdebug.h" #include "utils/memutils.h" @@ -130,13 +136,15 @@ /* * Pending requests are stored as ready-to-send SharedInvalidationMessages. - * We keep the messages themselves in arrays in TopTransactionContext - * (there are separate arrays for catcache and relcache messages). Control - * information is kept in a chain of TransInvalidationInfo structs, also - * allocated in TopTransactionContext. (We could keep a subtransaction's - * TransInvalidationInfo in its CurTransactionContext; but that's more - * wasteful not less so, since in very many scenarios it'd be the only - * allocation in the subtransaction's CurTransactionContext.) + * We keep the messages themselves in arrays in TopTransactionContext (there + * are separate arrays for catcache and relcache messages). For transactional + * messages, control information is kept in a chain of TransInvalidationInfo + * structs, also allocated in TopTransactionContext. (We could keep a + * subtransaction's TransInvalidationInfo in its CurTransactionContext; but + * that's more wasteful not less so, since in very many scenarios it'd be the + * only allocation in the subtransaction's CurTransactionContext.) For + * inplace update messages, control information appears in an + * InvalidationInfo, allocated in CurrentMemoryContext. * * We can store the message arrays densely, and yet avoid moving data around * within an array, because within any one subtransaction we need only @@ -147,7 +155,9 @@ * struct. Similarly, we need distinguish messages of prior subtransactions * from those of the current subtransaction only until the subtransaction * completes, after which we adjust the array indexes in the parent's - * TransInvalidationInfo to include the subtransaction's messages. + * TransInvalidationInfo to include the subtransaction's messages. Inplace + * invalidations don't need a concept of command or subtransaction boundaries, + * since we send them during the WAL insertion critical section. * * The ordering of the individual messages within a command's or * subtransaction's output is not considered significant, although this @@ -200,7 +210,7 @@ typedef struct InvalidationMsgsGroup /*---------------- - * Invalidation messages are divided into two groups: + * Transactional invalidation messages are divided into two groups: * 1) events so far in current command, not yet reflected to caches. * 2) events in previous commands of current transaction; these have * been reflected to local caches, and must be either broadcast to @@ -216,26 +226,36 @@ typedef struct InvalidationMsgsGroup *---------------- */ -typedef struct TransInvalidationInfo +/* fields common to both transactional and inplace invalidation */ +typedef struct InvalidationInfo { - /* Back link to parent transaction's info */ - struct TransInvalidationInfo *parent; - - /* Subtransaction nesting depth */ - int my_level; - /* Events emitted by current command */ InvalidationMsgsGroup CurrentCmdInvalidMsgs; + /* init file must be invalidated? */ + bool RelcacheInitFileInval; +} InvalidationInfo; + +/* subclass adding fields specific to transactional invalidation */ +typedef struct TransInvalidationInfo +{ + /* Base class */ + struct InvalidationInfo ii; + /* Events emitted by previous commands of this (sub)transaction */ InvalidationMsgsGroup PriorCmdInvalidMsgs; - /* init file must be invalidated? */ - bool RelcacheInitFileInval; + /* Back link to parent transaction's info */ + struct TransInvalidationInfo *parent; + + /* Subtransaction nesting depth */ + int my_level; } TransInvalidationInfo; static TransInvalidationInfo *transInvalInfo = NULL; +static InvalidationInfo *inplaceInvalInfo = NULL; + /* GUC storage */ int debug_discard_caches = 0; @@ -251,6 +271,7 @@ int debug_discard_caches = 0; #define MAX_SYSCACHE_CALLBACKS 64 #define MAX_RELCACHE_CALLBACKS 10 +#define MAX_RELSYNC_CALLBACKS 10 static struct SYSCACHECALLBACK { @@ -272,6 +293,15 @@ static struct RELCACHECALLBACK static int relcache_callback_count = 0; +static struct RELSYNCCALLBACK +{ + RelSyncCallbackFunction function; + Datum arg; +} relsync_callback_list[MAX_RELSYNC_CALLBACKS]; + +static int relsync_callback_count = 0; + + /* ---------------------------------------------------------------- * Invalidation subgroup support functions * ---------------------------------------------------------------- @@ -464,6 +494,36 @@ AddRelcacheInvalidationMessage(InvalidationMsgsGroup *group, AddInvalidationMessage(group, RelCacheMsgs, &msg); } +/* + * Add a relsync inval entry + * + * We put these into the relcache subgroup for simplicity. This message is the + * same as AddRelcacheInvalidationMessage() except that it is for + * RelationSyncCache maintained by decoding plugin pgoutput. + */ +static void +AddRelsyncInvalidationMessage(InvalidationMsgsGroup *group, + Oid dbId, Oid relId) +{ + SharedInvalidationMessage msg; + + /* Don't add a duplicate item. */ + ProcessMessageSubGroup(group, RelCacheMsgs, + if (msg->rc.id == SHAREDINVALRELSYNC_ID && + (msg->rc.relId == relId || + msg->rc.relId == InvalidOid)) + return); + + /* OK, add the item */ + msg.rc.id = SHAREDINVALRELSYNC_ID; + msg.rc.dbId = dbId; + msg.rc.relId = relId; + /* check AddCatcacheInvalidationMessage() for an explanation */ + VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg)); + + AddInvalidationMessage(group, RelCacheMsgs, &msg); +} + /* * Add a snapshot inval entry * @@ -543,9 +603,12 @@ ProcessInvalidationMessagesMulti(InvalidationMsgsGroup *group, static void RegisterCatcacheInvalidation(int cacheId, uint32 hashValue, - Oid dbId) + Oid dbId, + void *context) { - AddCatcacheInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs, + InvalidationInfo *info = (InvalidationInfo *) context; + + AddCatcacheInvalidationMessage(&info->CurrentCmdInvalidMsgs, cacheId, hashValue, dbId); } @@ -555,10 +618,9 @@ RegisterCatcacheInvalidation(int cacheId, * Register an invalidation event for all catcache entries from a catalog. */ static void -RegisterCatalogInvalidation(Oid dbId, Oid catId) +RegisterCatalogInvalidation(InvalidationInfo *info, Oid dbId, Oid catId) { - AddCatalogInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs, - dbId, catId); + AddCatalogInvalidationMessage(&info->CurrentCmdInvalidMsgs, dbId, catId); } /* @@ -567,10 +629,9 @@ RegisterCatalogInvalidation(Oid dbId, Oid catId) * As above, but register a relcache invalidation event. */ static void -RegisterRelcacheInvalidation(Oid dbId, Oid relId) +RegisterRelcacheInvalidation(InvalidationInfo *info, Oid dbId, Oid relId) { - AddRelcacheInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs, - dbId, relId); + AddRelcacheInvalidationMessage(&info->CurrentCmdInvalidMsgs, dbId, relId); /* * Most of the time, relcache invalidation is associated with system @@ -587,7 +648,18 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId) * as well. Also zap when we are invalidating whole relcache. */ if (relId == InvalidOid || RelationIdIsInInitFile(relId)) - transInvalInfo->RelcacheInitFileInval = true; + info->RelcacheInitFileInval = true; +} + +/* + * RegisterRelsyncInvalidation + * + * As above, but register a relsynccache invalidation event. + */ +static void +RegisterRelsyncInvalidation(InvalidationInfo *info, Oid dbId, Oid relId) +{ + AddRelsyncInvalidationMessage(&info->CurrentCmdInvalidMsgs, dbId, relId); } /* @@ -597,24 +669,28 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId) * Only needed for catalogs that don't have catcaches. */ static void -RegisterSnapshotInvalidation(Oid dbId, Oid relId) +RegisterSnapshotInvalidation(InvalidationInfo *info, Oid dbId, Oid relId) { - AddSnapshotInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs, - dbId, relId); + AddSnapshotInvalidationMessage(&info->CurrentCmdInvalidMsgs, dbId, relId); } /* * PrepareInvalidationState * Initialize inval data for the current (sub)transaction. */ -static void +static InvalidationInfo * PrepareInvalidationState(void) { TransInvalidationInfo *myInfo; + /* PrepareToInvalidateCacheTuple() needs relcache */ + AssertCouldGetRelation(); + /* Can't queue transactional message while collecting inplace messages. */ + Assert(inplaceInvalInfo == NULL); + if (transInvalInfo != NULL && transInvalInfo->my_level == GetCurrentTransactionNestLevel()) - return; + return (InvalidationInfo *) transInvalInfo; myInfo = (TransInvalidationInfo *) MemoryContextAllocZero(TopTransactionContext, @@ -637,7 +713,7 @@ PrepareInvalidationState(void) * counter. This is a convenient place to check for that, as well as * being important to keep management of the message arrays simple. */ - if (NumMessagesInGroup(&transInvalInfo->CurrentCmdInvalidMsgs) != 0) + if (NumMessagesInGroup(&transInvalInfo->ii.CurrentCmdInvalidMsgs) != 0) elog(ERROR, "cannot start a subtransaction when there are unprocessed inval messages"); /* @@ -646,8 +722,8 @@ PrepareInvalidationState(void) * to update them to follow whatever is already in the arrays. */ SetGroupToFollow(&myInfo->PriorCmdInvalidMsgs, - &transInvalInfo->CurrentCmdInvalidMsgs); - SetGroupToFollow(&myInfo->CurrentCmdInvalidMsgs, + &transInvalInfo->ii.CurrentCmdInvalidMsgs); + SetGroupToFollow(&myInfo->ii.CurrentCmdInvalidMsgs, &myInfo->PriorCmdInvalidMsgs); } else @@ -663,6 +739,41 @@ PrepareInvalidationState(void) } transInvalInfo = myInfo; + return (InvalidationInfo *) myInfo; +} + +/* + * PrepareInplaceInvalidationState + * Initialize inval data for an inplace update. + * + * See previous function for more background. + */ +static InvalidationInfo * +PrepareInplaceInvalidationState(void) +{ + InvalidationInfo *myInfo; + + AssertCouldGetRelation(); + /* limit of one inplace update under assembly */ + Assert(inplaceInvalInfo == NULL); + + /* gone after WAL insertion CritSection ends, so use current context */ + myInfo = (InvalidationInfo *) palloc0(sizeof(InvalidationInfo)); + + /* Stash our messages past end of the transactional messages, if any. */ + if (transInvalInfo != NULL) + SetGroupToFollow(&myInfo->CurrentCmdInvalidMsgs, + &transInvalInfo->ii.CurrentCmdInvalidMsgs); + else + { + InvalMessageArrays[CatCacheMsgs].msgs = NULL; + InvalMessageArrays[CatCacheMsgs].maxmsgs = 0; + InvalMessageArrays[RelCacheMsgs].msgs = NULL; + InvalMessageArrays[RelCacheMsgs].maxmsgs = 0; + } + + inplaceInvalInfo = myInfo; + return myInfo; } /* ---------------------------------------------------------------- @@ -676,7 +787,7 @@ InvalidateSystemCachesExtended(bool debug_discard) int i; InvalidateCatalogSnapshot(); - ResetCatalogCaches(); + ResetCatalogCachesExt(debug_discard); RelationCacheInvalidate(debug_discard); /* gets smgr and relmap too */ for (i = 0; i < syscache_callback_count; i++) @@ -692,6 +803,13 @@ InvalidateSystemCachesExtended(bool debug_discard) ccitem->function(ccitem->arg, InvalidOid); } + + for (i = 0; i < relsync_callback_count; i++) + { + struct RELSYNCCALLBACK *ccitem = relsync_callback_list + i; + + ccitem->function(ccitem->arg, InvalidOid); + } } /* @@ -773,6 +891,12 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg) else if (msg->sn.dbId == MyDatabaseId) InvalidateCatalogSnapshot(); } + else if (msg->id == SHAREDINVALRELSYNC_ID) + { + /* We only care about our own database */ + if (msg->rs.dbId == MyDatabaseId) + CallRelSyncCallbacks(msg->rs.relid); + } else elog(FATAL, "unrecognized SI message ID: %d", msg->id); } @@ -805,6 +929,12 @@ InvalidateSystemCaches(void) void AcceptInvalidationMessages(void) { +#ifdef USE_ASSERT_CHECKING + /* message handlers shall access catalogs only during transactions */ + if (IsTransactionState()) + AssertCouldGetRelation(); +#endif + ReceiveSharedInvalidMessages(LocalExecuteInvalidationMessage, InvalidateSystemCaches); @@ -902,7 +1032,7 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, * after we send the SI messages. However, we need not do anything unless * we committed. */ - *RelcacheInitFileInval = transInvalInfo->RelcacheInitFileInval; + *RelcacheInitFileInval = transInvalInfo->ii.RelcacheInitFileInval; /* * Collect all the pending messages into a single contiguous array of @@ -913,7 +1043,7 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, * not new ones. */ nummsgs = NumMessagesInGroup(&transInvalInfo->PriorCmdInvalidMsgs) + - NumMessagesInGroup(&transInvalInfo->CurrentCmdInvalidMsgs); + NumMessagesInGroup(&transInvalInfo->ii.CurrentCmdInvalidMsgs); *msgs = msgarray = (SharedInvalidationMessage *) MemoryContextAlloc(CurTransactionContext, @@ -926,7 +1056,7 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, msgs, n * sizeof(SharedInvalidationMessage)), nmsgs += n)); - ProcessMessageSubGroupMulti(&transInvalInfo->CurrentCmdInvalidMsgs, + ProcessMessageSubGroupMulti(&transInvalInfo->ii.CurrentCmdInvalidMsgs, CatCacheMsgs, (memcpy(msgarray + nmsgs, msgs, @@ -938,7 +1068,51 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, msgs, n * sizeof(SharedInvalidationMessage)), nmsgs += n)); - ProcessMessageSubGroupMulti(&transInvalInfo->CurrentCmdInvalidMsgs, + ProcessMessageSubGroupMulti(&transInvalInfo->ii.CurrentCmdInvalidMsgs, + RelCacheMsgs, + (memcpy(msgarray + nmsgs, + msgs, + n * sizeof(SharedInvalidationMessage)), + nmsgs += n)); + Assert(nmsgs == nummsgs); + + return nmsgs; +} + +/* + * inplaceGetInvalidationMessages() is called by the inplace update to collect + * invalidation messages to add to its WAL record. Like the previous + * function, we might still fail. + */ +int +inplaceGetInvalidationMessages(SharedInvalidationMessage **msgs, + bool *RelcacheInitFileInval) +{ + SharedInvalidationMessage *msgarray; + int nummsgs; + int nmsgs; + + /* Quick exit if we haven't done anything with invalidation messages. */ + if (inplaceInvalInfo == NULL) + { + *RelcacheInitFileInval = false; + *msgs = NULL; + return 0; + } + + *RelcacheInitFileInval = inplaceInvalInfo->RelcacheInitFileInval; + nummsgs = NumMessagesInGroup(&inplaceInvalInfo->CurrentCmdInvalidMsgs); + *msgs = msgarray = (SharedInvalidationMessage *) + palloc(nummsgs * sizeof(SharedInvalidationMessage)); + + nmsgs = 0; + ProcessMessageSubGroupMulti(&inplaceInvalInfo->CurrentCmdInvalidMsgs, + CatCacheMsgs, + (memcpy(msgarray + nmsgs, + msgs, + n * sizeof(SharedInvalidationMessage)), + nmsgs += n)); + ProcessMessageSubGroupMulti(&inplaceInvalInfo->CurrentCmdInvalidMsgs, RelCacheMsgs, (memcpy(msgarray + nmsgs, msgs, @@ -1024,13 +1198,17 @@ ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, void AtEOXact_Inval(bool isCommit) { - /* Quick exit if no messages */ + inplaceInvalInfo = NULL; + + /* Quick exit if no transactional messages */ if (transInvalInfo == NULL) return; /* Must be at top of stack */ Assert(transInvalInfo->my_level == 1 && transInvalInfo->parent == NULL); + INJECTION_POINT("transaction-end-process-inval", NULL); + if (isCommit) { /* @@ -1038,16 +1216,16 @@ AtEOXact_Inval(bool isCommit) * after we send the SI messages. However, we need not do anything * unless we committed. */ - if (transInvalInfo->RelcacheInitFileInval) + if (transInvalInfo->ii.RelcacheInitFileInval) RelationCacheInitFilePreInvalidate(); AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, - &transInvalInfo->CurrentCmdInvalidMsgs); + &transInvalInfo->ii.CurrentCmdInvalidMsgs); ProcessInvalidationMessagesMulti(&transInvalInfo->PriorCmdInvalidMsgs, SendSharedInvalidMessages); - if (transInvalInfo->RelcacheInitFileInval) + if (transInvalInfo->ii.RelcacheInitFileInval) RelationCacheInitFilePostInvalidate(); } else @@ -1060,6 +1238,56 @@ AtEOXact_Inval(bool isCommit) transInvalInfo = NULL; } +/* + * PreInplace_Inval + * Process queued-up invalidation before inplace update critical section. + * + * Tasks belong here if they are safe even if the inplace update does not + * complete. Currently, this just unlinks a cache file, which can fail. The + * sum of this and AtInplace_Inval() mirrors AtEOXact_Inval(isCommit=true). + */ +void +PreInplace_Inval(void) +{ + Assert(CritSectionCount == 0); + + if (inplaceInvalInfo && inplaceInvalInfo->RelcacheInitFileInval) + RelationCacheInitFilePreInvalidate(); +} + +/* + * AtInplace_Inval + * Process queued-up invalidations after inplace update buffer mutation. + */ +void +AtInplace_Inval(void) +{ + Assert(CritSectionCount > 0); + + if (inplaceInvalInfo == NULL) + return; + + ProcessInvalidationMessagesMulti(&inplaceInvalInfo->CurrentCmdInvalidMsgs, + SendSharedInvalidMessages); + + if (inplaceInvalInfo->RelcacheInitFileInval) + RelationCacheInitFilePostInvalidate(); + + inplaceInvalInfo = NULL; +} + +/* + * ForgetInplace_Inval + * Alternative to PreInplace_Inval()+AtInplace_Inval(): discard queued-up + * invalidations. This lets inplace update enumerate invalidations + * optimistically, before locking the buffer. + */ +void +ForgetInplace_Inval(void) +{ + inplaceInvalInfo = NULL; +} + /* * AtEOSubXact_Inval * Process queued-up invalidation messages at end of subtransaction. @@ -1082,9 +1310,20 @@ void AtEOSubXact_Inval(bool isCommit) { int my_level; - TransInvalidationInfo *myInfo = transInvalInfo; + TransInvalidationInfo *myInfo; - /* Quick exit if no messages. */ + /* + * Successful inplace update must clear this, but we clear it on abort. + * Inplace updates allocate this in CurrentMemoryContext, which has + * lifespan <= subtransaction lifespan. Hence, don't free it explicitly. + */ + if (isCommit) + Assert(inplaceInvalInfo == NULL); + else + inplaceInvalInfo = NULL; + + /* Quick exit if no transactional messages. */ + myInfo = transInvalInfo; if (myInfo == NULL) return; @@ -1125,12 +1364,12 @@ AtEOSubXact_Inval(bool isCommit) &myInfo->PriorCmdInvalidMsgs); /* Must readjust parent's CurrentCmdInvalidMsgs indexes now */ - SetGroupToFollow(&myInfo->parent->CurrentCmdInvalidMsgs, + SetGroupToFollow(&myInfo->parent->ii.CurrentCmdInvalidMsgs, &myInfo->parent->PriorCmdInvalidMsgs); /* Pending relcache inval becomes parent's problem too */ - if (myInfo->RelcacheInitFileInval) - myInfo->parent->RelcacheInitFileInval = true; + if (myInfo->ii.RelcacheInitFileInval) + myInfo->parent->ii.RelcacheInitFileInval = true; /* Pop the transaction state stack */ transInvalInfo = myInfo->parent; @@ -1177,7 +1416,7 @@ CommandEndInvalidationMessages(void) if (transInvalInfo == NULL) return; - ProcessInvalidationMessages(&transInvalInfo->CurrentCmdInvalidMsgs, + ProcessInvalidationMessages(&transInvalInfo->ii.CurrentCmdInvalidMsgs, LocalExecuteInvalidationMessage); /* WAL Log per-command invalidation messages for wal_level=logical */ @@ -1185,30 +1424,28 @@ CommandEndInvalidationMessages(void) LogLogicalInvalidations(); AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs, - &transInvalInfo->CurrentCmdInvalidMsgs); + &transInvalInfo->ii.CurrentCmdInvalidMsgs); } /* - * CacheInvalidateHeapTuple - * Register the given tuple for invalidation at end of command - * (ie, current command is creating or outdating this tuple). - * Also, detect whether a relcache invalidation is implied. - * - * For an insert or delete, tuple is the target tuple and newtuple is NULL. - * For an update, we are called just once, with tuple being the old tuple - * version and newtuple the new version. This allows avoidance of duplicate - * effort during an update. + * CacheInvalidateHeapTupleCommon + * Common logic for end-of-command and inplace variants. */ -void -CacheInvalidateHeapTuple(Relation relation, - HeapTuple tuple, - HeapTuple newtuple) +static void +CacheInvalidateHeapTupleCommon(Relation relation, + HeapTuple tuple, + HeapTuple newtuple, + InvalidationInfo *(*prepare_callback) (void)) { + InvalidationInfo *info; Oid tupleRelId; Oid databaseId; Oid relationId; + /* PrepareToInvalidateCacheTuple() needs relcache */ + AssertCouldGetRelation(); + /* Do nothing during bootstrap */ if (IsBootstrapProcessingMode()) return; @@ -1228,11 +1465,8 @@ CacheInvalidateHeapTuple(Relation relation, if (IsToastRelation(relation)) return; - /* - * If we're not prepared to queue invalidation messages for this - * subtransaction level, get ready now. - */ - PrepareInvalidationState(); + /* Allocate any required resources. */ + info = prepare_callback(); /* * First let the catcache do its thing @@ -1241,11 +1475,12 @@ CacheInvalidateHeapTuple(Relation relation, if (RelationInvalidatesSnapshotsOnly(tupleRelId)) { databaseId = IsSharedRelation(tupleRelId) ? InvalidOid : MyDatabaseId; - RegisterSnapshotInvalidation(databaseId, tupleRelId); + RegisterSnapshotInvalidation(info, databaseId, tupleRelId); } else PrepareToInvalidateCacheTuple(relation, tuple, newtuple, - RegisterCatcacheInvalidation); + RegisterCatcacheInvalidation, + (void *) info); /* * Now, is this tuple one of the primary definers of a relcache entry? See @@ -1318,7 +1553,44 @@ CacheInvalidateHeapTuple(Relation relation, /* * Yes. We need to register a relcache invalidation event. */ - RegisterRelcacheInvalidation(databaseId, relationId); + RegisterRelcacheInvalidation(info, databaseId, relationId); +} + +/* + * CacheInvalidateHeapTuple + * Register the given tuple for invalidation at end of command + * (ie, current command is creating or outdating this tuple) and end of + * transaction. Also, detect whether a relcache invalidation is implied. + * + * For an insert or delete, tuple is the target tuple and newtuple is NULL. + * For an update, we are called just once, with tuple being the old tuple + * version and newtuple the new version. This allows avoidance of duplicate + * effort during an update. + */ +void +CacheInvalidateHeapTuple(Relation relation, + HeapTuple tuple, + HeapTuple newtuple) +{ + CacheInvalidateHeapTupleCommon(relation, tuple, newtuple, + PrepareInvalidationState); +} + +/* + * CacheInvalidateHeapTupleInplace + * Register the given tuple for nontransactional invalidation pertaining + * to an inplace update. Also, detect whether a relcache invalidation is + * implied. + * + * Like CacheInvalidateHeapTuple(), but for inplace updates. + */ +void +CacheInvalidateHeapTupleInplace(Relation relation, + HeapTuple tuple, + HeapTuple newtuple) +{ + CacheInvalidateHeapTupleCommon(relation, tuple, newtuple, + PrepareInplaceInvalidationState); } /* @@ -1337,14 +1609,13 @@ CacheInvalidateCatalog(Oid catalogId) { Oid databaseId; - PrepareInvalidationState(); - if (IsSharedRelation(catalogId)) databaseId = InvalidOid; else databaseId = MyDatabaseId; - RegisterCatalogInvalidation(databaseId, catalogId); + RegisterCatalogInvalidation(PrepareInvalidationState(), + databaseId, catalogId); } /* @@ -1362,15 +1633,14 @@ CacheInvalidateRelcache(Relation relation) Oid databaseId; Oid relationId; - PrepareInvalidationState(); - relationId = RelationGetRelid(relation); if (relation->rd_rel->relisshared) databaseId = InvalidOid; else databaseId = MyDatabaseId; - RegisterRelcacheInvalidation(databaseId, relationId); + RegisterRelcacheInvalidation(PrepareInvalidationState(), + databaseId, relationId); } /* @@ -1383,9 +1653,8 @@ CacheInvalidateRelcache(Relation relation) void CacheInvalidateRelcacheAll(void) { - PrepareInvalidationState(); - - RegisterRelcacheInvalidation(InvalidOid, InvalidOid); + RegisterRelcacheInvalidation(PrepareInvalidationState(), + InvalidOid, InvalidOid); } /* @@ -1399,14 +1668,13 @@ CacheInvalidateRelcacheByTuple(HeapTuple classTuple) Oid databaseId; Oid relationId; - PrepareInvalidationState(); - relationId = classtup->oid; if (classtup->relisshared) databaseId = InvalidOid; else databaseId = MyDatabaseId; - RegisterRelcacheInvalidation(databaseId, relationId); + RegisterRelcacheInvalidation(PrepareInvalidationState(), + databaseId, relationId); } /* @@ -1420,8 +1688,6 @@ CacheInvalidateRelcacheByRelid(Oid relid) { HeapTuple tup; - PrepareInvalidationState(); - tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for relation %u", relid); @@ -1429,6 +1695,32 @@ CacheInvalidateRelcacheByRelid(Oid relid) ReleaseSysCache(tup); } +/* + * CacheInvalidateRelSync + * Register invalidation of the cache in logical decoding output plugin + * for a database. + * + * This type of invalidation message is used for the specific purpose of output + * plugins. Processes which do not decode WALs would do nothing even when it + * receives the message. + */ +void +CacheInvalidateRelSync(Oid relid) +{ + RegisterRelsyncInvalidation(PrepareInvalidationState(), + MyDatabaseId, relid); +} + +/* + * CacheInvalidateRelSyncAll + * Register invalidation of the whole cache in logical decoding output + * plugin. + */ +void +CacheInvalidateRelSyncAll(void) +{ + CacheInvalidateRelSync(InvalidOid); +} /* * CacheInvalidateSmgr @@ -1460,6 +1752,10 @@ CacheInvalidateSmgr(RelFileLocatorBackend rlocator) { SharedInvalidationMessage msg; + /* verify optimization stated above stays valid */ + StaticAssertStmt(MAX_BACKENDS_BITS <= 23, + "MAX_BACKENDS_BITS is too big for inval.c"); + msg.sm.id = SHAREDINVALSMGR_ID; msg.sm.backend_hi = rlocator.backend >> 16; msg.sm.backend_lo = rlocator.backend & 0xffff; @@ -1567,6 +1863,27 @@ CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, ++relcache_callback_count; } +/* + * CacheRegisterRelSyncCallback + * Register the specified function to be called for all future + * relsynccache invalidation events. + * + * This function is intended to be call from the logical decoding output + * plugins. + */ +void +CacheRegisterRelSyncCallback(RelSyncCallbackFunction func, + Datum arg) +{ + if (relsync_callback_count >= MAX_RELSYNC_CALLBACKS) + elog(FATAL, "out of relsync_callback_list slots"); + + relsync_callback_list[relsync_callback_count].function = func; + relsync_callback_list[relsync_callback_count].arg = arg; + + ++relsync_callback_count; +} + /* * CallSyscacheCallbacks * @@ -1592,6 +1909,20 @@ CallSyscacheCallbacks(int cacheid, uint32 hashvalue) } } +/* + * CallSyscacheCallbacks + */ +void +CallRelSyncCallbacks(Oid relid) +{ + for (int i = 0; i < relsync_callback_count; i++) + { + struct RELSYNCCALLBACK *ccitem = relsync_callback_list + i; + + ccitem->function(ccitem->arg, relid); + } +} + /* * LogLogicalInvalidations * @@ -1611,7 +1942,7 @@ LogLogicalInvalidations(void) if (transInvalInfo == NULL) return; - group = &transInvalInfo->CurrentCmdInvalidMsgs; + group = &transInvalInfo->ii.CurrentCmdInvalidMsgs; nmsgs = NumMessagesInGroup(group); if (nmsgs > 0) @@ -1622,12 +1953,12 @@ LogLogicalInvalidations(void) /* perform insertion */ XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), MinSizeOfXactInvals); + XLogRegisterData(&xlrec, MinSizeOfXactInvals); ProcessMessageSubGroupMulti(group, CatCacheMsgs, - XLogRegisterData((char *) msgs, + XLogRegisterData(msgs, n * sizeof(SharedInvalidationMessage))); ProcessMessageSubGroupMulti(group, RelCacheMsgs, - XLogRegisterData((char *) msgs, + XLogRegisterData(msgs, n * sizeof(SharedInvalidationMessage))); XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS); } diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 48a280d089b70..c460a72b75d90 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -3,7 +3,7 @@ * lsyscache.c * Convenience routines for common queries in the system catalog cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -30,6 +30,7 @@ #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" +#include "catalog/pg_opfamily.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" #include "catalog/pg_publication.h" @@ -183,11 +184,68 @@ get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, return result; } +/* + * get_opfamily_member_for_cmptype + * Get the OID of the operator that implements the specified comparison + * type with the specified datatypes for the specified opfamily. + * + * Returns InvalidOid if there is no mapping for the comparison type or no + * pg_amop entry for the given keys. + */ +Oid +get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, + CompareType cmptype) +{ + Oid opmethod; + StrategyNumber strategy; + + opmethod = get_opfamily_method(opfamily); + strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, true); + if (!strategy) + return InvalidOid; + return get_opfamily_member(opfamily, lefttype, righttype, strategy); +} + +/* + * get_opmethod_canorder + * Return amcanorder field for given index AM. + * + * To speed things up in the common cases, we're hardcoding the results from + * the built-in index types. Note that we also need to hardcode the negative + * results from the built-in non-btree index types, since you'll usually get a + * few hits for those as well. It would be nice to organize and cache this a + * bit differently to avoid the hardcoding. + */ +static bool +get_opmethod_canorder(Oid amoid) +{ + switch (amoid) + { + case BTREE_AM_OID: + return true; + case HASH_AM_OID: + case GIST_AM_OID: + case GIN_AM_OID: + case SPGIST_AM_OID: + case BRIN_AM_OID: + return false; + default: + { + bool result; + IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false); + + result = amroutine->amcanorder; + pfree(amroutine); + return result; + } + } +} + /* * get_ordering_op_properties - * Given the OID of an ordering operator (a btree "<" or ">" operator), + * Given the OID of an ordering operator (a "<" or ">" operator), * determine its opfamily, its declared input datatype, and its - * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber). + * comparison type. * * Returns true if successful, false if no matching pg_amop entry exists. * (This indicates that the operator is not a valid ordering operator.) @@ -205,7 +263,7 @@ get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, */ bool get_ordering_op_properties(Oid opno, - Oid *opfamily, Oid *opcintype, int16 *strategy) + Oid *opfamily, Oid *opcintype, CompareType *cmptype) { bool result = false; CatCList *catlist; @@ -214,7 +272,7 @@ get_ordering_op_properties(Oid opno, /* ensure outputs are initialized on failure */ *opfamily = InvalidOid; *opcintype = InvalidOid; - *strategy = 0; + *cmptype = COMPARE_INVALID; /* * Search pg_amop to see if the target operator is registered as the "<" @@ -226,13 +284,18 @@ get_ordering_op_properties(Oid opno, { HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); + CompareType am_cmptype; - /* must be btree */ - if (aform->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!get_opmethod_canorder(aform->amopmethod)) continue; - if (aform->amopstrategy == BTLessStrategyNumber || - aform->amopstrategy == BTGreaterStrategyNumber) + am_cmptype = IndexAmTranslateStrategy(aform->amopstrategy, + aform->amopmethod, + aform->amopfamily, + true); + + if (am_cmptype == COMPARE_LT || am_cmptype == COMPARE_GT) { /* Found it ... should have consistent input types */ if (aform->amoplefttype == aform->amoprighttype) @@ -240,7 +303,7 @@ get_ordering_op_properties(Oid opno, /* Found a suitable opfamily, return info */ *opfamily = aform->amopfamily; *opcintype = aform->amoplefttype; - *strategy = aform->amopstrategy; + *cmptype = am_cmptype; result = true; break; } @@ -254,7 +317,7 @@ get_ordering_op_properties(Oid opno, /* * get_equality_op_for_ordering_op - * Get the OID of the datatype-specific btree equality operator + * Get the OID of the datatype-specific equality operator * associated with an ordering operator (a "<" or ">" operator). * * If "reverse" isn't NULL, also set *reverse to false if the operator is "<", @@ -269,19 +332,19 @@ get_equality_op_for_ordering_op(Oid opno, bool *reverse) Oid result = InvalidOid; Oid opfamily; Oid opcintype; - int16 strategy; + CompareType cmptype; /* Find the operator in pg_amop */ if (get_ordering_op_properties(opno, - &opfamily, &opcintype, &strategy)) + &opfamily, &opcintype, &cmptype)) { /* Found a suitable opfamily, get matching equality operator */ - result = get_opfamily_member(opfamily, - opcintype, - opcintype, - BTEqualStrategyNumber); + result = get_opfamily_member_for_cmptype(opfamily, + opcintype, + opcintype, + COMPARE_EQ); if (reverse) - *reverse = (strategy == BTGreaterStrategyNumber); + *reverse = (cmptype == COMPARE_GT); } return result; @@ -289,7 +352,7 @@ get_equality_op_for_ordering_op(Oid opno, bool *reverse) /* * get_ordering_op_for_equality_op - * Get the OID of a datatype-specific btree ordering operator + * Get the OID of a datatype-specific "less than" ordering operator * associated with an equality operator. (If there are multiple * possibilities, assume any one will do.) * @@ -318,20 +381,25 @@ get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type) { HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); + CompareType cmptype; - /* must be btree */ - if (aform->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!get_opmethod_canorder(aform->amopmethod)) continue; - if (aform->amopstrategy == BTEqualStrategyNumber) + cmptype = IndexAmTranslateStrategy(aform->amopstrategy, + aform->amopmethod, + aform->amopfamily, + true); + if (cmptype == COMPARE_EQ) { /* Found a suitable opfamily, get matching ordering operator */ Oid typid; typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype; - result = get_opfamily_member(aform->amopfamily, - typid, typid, - BTLessStrategyNumber); + result = get_opfamily_member_for_cmptype(aform->amopfamily, + typid, typid, + COMPARE_LT); if (OidIsValid(result)) break; /* failure probably shouldn't happen, but keep looking if so */ @@ -346,7 +414,7 @@ get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type) /* * get_mergejoin_opfamilies * Given a putatively mergejoinable operator, return a list of the OIDs - * of the btree opfamilies in which it represents equality. + * of the amcanorder opfamilies in which it represents equality. * * It is possible (though at present unusual) for an operator to be equality * in more than one opfamily, hence the result is a list. This also lets us @@ -371,7 +439,7 @@ get_mergejoin_opfamilies(Oid opno) /* * Search pg_amop to see if the target operator is registered as the "=" - * operator of any btree opfamily. + * operator of any opfamily of an ordering index type. */ catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno)); @@ -380,9 +448,12 @@ get_mergejoin_opfamilies(Oid opno) HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); - /* must be btree equality */ - if (aform->amopmethod == BTREE_AM_OID && - aform->amopstrategy == BTEqualStrategyNumber) + /* must be ordering index equality */ + if (get_opmethod_canorder(aform->amopmethod) && + IndexAmTranslateStrategy(aform->amopstrategy, + aform->amopmethod, + aform->amopfamily, + true) == COMPARE_EQ) result = lappend_oid(result, aform->amopfamily); } @@ -588,20 +659,20 @@ get_op_hash_functions(Oid opno, } /* - * get_op_btree_interpretation - * Given an operator's OID, find out which btree opfamilies it belongs to, + * get_op_index_interpretation + * Given an operator's OID, find out which amcanorder opfamilies it belongs to, * and what properties it has within each one. The results are returned - * as a palloc'd list of OpBtreeInterpretation structs. + * as a palloc'd list of OpIndexInterpretation structs. * * In addition to the normal btree operators, we consider a <> operator to be * a "member" of an opfamily if its negator is an equality operator of the - * opfamily. ROWCOMPARE_NE is returned as the strategy number for this case. + * opfamily. COMPARE_NE is returned as the strategy number for this case. */ List * -get_op_btree_interpretation(Oid opno) +get_op_index_interpretation(Oid opno) { List *result = NIL; - OpBtreeInterpretation *thisresult; + OpIndexInterpretation *thisresult; CatCList *catlist; int i; @@ -614,20 +685,26 @@ get_op_btree_interpretation(Oid opno) { HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); - StrategyNumber op_strategy; + CompareType cmptype; - /* must be btree */ - if (op_form->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!get_opmethod_canorder(op_form->amopmethod)) continue; - /* Get the operator's btree strategy number */ - op_strategy = (StrategyNumber) op_form->amopstrategy; - Assert(op_strategy >= 1 && op_strategy <= 5); + /* Get the operator's comparision type */ + cmptype = IndexAmTranslateStrategy(op_form->amopstrategy, + op_form->amopmethod, + op_form->amopfamily, + true); - thisresult = (OpBtreeInterpretation *) - palloc(sizeof(OpBtreeInterpretation)); + /* should not happen */ + if (cmptype == COMPARE_INVALID) + continue; + + thisresult = (OpIndexInterpretation *) + palloc(sizeof(OpIndexInterpretation)); thisresult->opfamily_id = op_form->amopfamily; - thisresult->strategy = op_strategy; + thisresult->cmptype = cmptype; thisresult->oplefttype = op_form->amoplefttype; thisresult->oprighttype = op_form->amoprighttype; result = lappend(result, thisresult); @@ -652,25 +729,28 @@ get_op_btree_interpretation(Oid opno) { HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); - StrategyNumber op_strategy; + IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false); + CompareType cmptype; - /* must be btree */ - if (op_form->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!amroutine->amcanorder) continue; - /* Get the operator's btree strategy number */ - op_strategy = (StrategyNumber) op_form->amopstrategy; - Assert(op_strategy >= 1 && op_strategy <= 5); + /* Get the operator's comparision type */ + cmptype = IndexAmTranslateStrategy(op_form->amopstrategy, + op_form->amopmethod, + op_form->amopfamily, + true); /* Only consider negators that are = */ - if (op_strategy != BTEqualStrategyNumber) + if (cmptype != COMPARE_EQ) continue; - /* OK, report it with "strategy" ROWCOMPARE_NE */ - thisresult = (OpBtreeInterpretation *) - palloc(sizeof(OpBtreeInterpretation)); + /* OK, report it as COMPARE_NE */ + thisresult = (OpIndexInterpretation *) + palloc(sizeof(OpIndexInterpretation)); thisresult->opfamily_id = op_form->amopfamily; - thisresult->strategy = ROWCOMPARE_NE; + thisresult->cmptype = COMPARE_NE; thisresult->oplefttype = op_form->amoplefttype; thisresult->oprighttype = op_form->amoprighttype; result = lappend(result, thisresult); @@ -689,10 +769,11 @@ get_op_btree_interpretation(Oid opno) * semantics. * * This is trivially true if they are the same operator. Otherwise, - * we look to see if they can be found in the same btree or hash opfamily. - * Either finding allows us to assume that they have compatible notions - * of equality. (The reason we need to do these pushups is that one might - * be a cross-type operator; for instance int24eq vs int4eq.) + * Otherwise, we look to see if they both belong to an opfamily that + * guarantees compatible semantics for equality. Either finding allows us to + * assume that they have compatible notions of equality. (The reason we need + * to do these pushups is that one might be a cross-type operator; for + * instance int24eq vs int4eq.) */ bool equality_ops_are_compatible(Oid opno1, Oid opno2) @@ -716,11 +797,15 @@ equality_ops_are_compatible(Oid opno1, Oid opno2) HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); - /* must be btree or hash */ - if (op_form->amopmethod == BTREE_AM_OID || - op_form->amopmethod == HASH_AM_OID) + /* + * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so + * check it first + */ + if (op_in_opfamily(opno2, op_form->amopfamily)) { - if (op_in_opfamily(opno2, op_form->amopfamily)) + IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false); + + if (amroutine->amconsistentequality) { result = true; break; @@ -738,12 +823,13 @@ equality_ops_are_compatible(Oid opno1, Oid opno2) * Return true if the two given comparison operators have compatible * semantics. * - * This is trivially true if they are the same operator. Otherwise, - * we look to see if they can be found in the same btree opfamily. - * For example, '<' and '>=' ops match if they belong to the same family. + * This is trivially true if they are the same operator. Otherwise, we look + * to see if they both belong to an opfamily that guarantees compatible + * semantics for ordering. (For example, for btree, '<' and '>=' ops match if + * they belong to the same family.) * - * (This is identical to equality_ops_are_compatible(), except that we - * don't bother to examine hash opclasses.) + * (This is identical to equality_ops_are_compatible(), except that we check + * amconsistentordering instead of amconsistentequality.) */ bool comparison_ops_are_compatible(Oid opno1, Oid opno2) @@ -767,9 +853,15 @@ comparison_ops_are_compatible(Oid opno1, Oid opno2) HeapTuple op_tuple = &catlist->members[i]->tuple; Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple); - if (op_form->amopmethod == BTREE_AM_OID) + /* + * op_in_opfamily() is cheaper than GetIndexAmRoutineByAmId(), so + * check it first + */ + if (op_in_opfamily(opno2, op_form->amopfamily)) { - if (op_in_opfamily(opno2, op_form->amopfamily)) + IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(op_form->amopmethod, false); + + if (amroutine->amconsistentordering) { result = true; break; @@ -1273,6 +1365,54 @@ get_opclass_method(Oid opclass) return result; } +/* ---------- OPFAMILY CACHE ---------- */ + +/* + * get_opfamily_method + * + * Returns the OID of the index access method the opfamily is for. + */ +Oid +get_opfamily_method(Oid opfid) +{ + HeapTuple tp; + Form_pg_opfamily opfform; + Oid result; + + tp = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for operator family %u", opfid); + opfform = (Form_pg_opfamily) GETSTRUCT(tp); + + result = opfform->opfmethod; + ReleaseSysCache(tp); + return result; +} + +char * +get_opfamily_name(Oid opfid, bool missing_ok) +{ + HeapTuple tup; + char *opfname; + Form_pg_opfamily opfform; + + tup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid)); + + if (!HeapTupleIsValid(tup)) + { + if (!missing_ok) + elog(ERROR, "cache lookup failed for operator family %u", opfid); + return NULL; + } + + opfform = (Form_pg_opfamily) GETSTRUCT(tup); + opfname = pstrdup(NameStr(opfform->opfname)); + + ReleaseSysCache(tup); + + return opfname; +} + /* ---------- OPERATOR CACHE ---------- */ /* diff --git a/src/backend/utils/cache/meson.build b/src/backend/utils/cache/meson.build index a4c5074b32caf..a1784dce5855b 100644 --- a/src/backend/utils/cache/meson.build +++ b/src/backend/utils/cache/meson.build @@ -1,9 +1,10 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'attoptcache.c', 'catcache.c', 'evtcache.c', + 'funccache.c', 'inval.c', 'lsyscache.c', 'partcache.c', diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index beec6cddbc44f..f5d7d70def0e8 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -4,7 +4,7 @@ * Support routines for manipulating partition information cached in * relcache * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 5af1a168ec2f7..89a1c79e984d1 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -14,7 +14,7 @@ * Cache invalidation is driven off sinval events. Any CachedPlanSource * that matches the event is marked invalid, as is its generic CachedPlan * if it has one. When (and if) the next demand for a cached plan occurs, - * parse analysis and rewrite is repeated to build a new valid query tree, + * parse analysis and/or rewrite is repeated to build a new valid query tree, * and then planning is performed as normal. We also force re-analysis and * re-planning if the active search_path is different from the previous time * or, if RLS is involved, if the user changes or the RLS environment changes. @@ -44,7 +44,7 @@ * if the old one gets invalidated. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -63,6 +63,7 @@ #include "nodes/nodeFuncs.h" #include "optimizer/optimizer.h" #include "parser/analyze.h" +#include "rewrite/rewriteHandler.h" #include "storage/lmgr.h" #include "tcop/pquery.h" #include "tcop/utility.h" @@ -74,18 +75,6 @@ #include "utils/syscache.h" -/* - * We must skip "overhead" operations that involve database access when the - * cached plan's subject statement is a transaction control command or one - * that requires a snapshot not to be set yet (such as SET or LOCK). More - * generally, statements that do not require parse analysis/rewrite/plan - * activity never need to be revalidated, so we can treat them all like that. - * For the convenience of postgres.c, treat empty statements that way too. - */ -#define StmtPlanRequiresRevalidation(plansource) \ - ((plansource)->raw_parse_tree != NULL && \ - stmt_requires_parse_analysis((plansource)->raw_parse_tree)) - /* * This is the head of the backend's list of "saved" CachedPlanSources (i.e., * those that are in long-lived storage and are examined for sinval events). @@ -100,6 +89,8 @@ static dlist_head saved_plan_list = DLIST_STATIC_INIT(saved_plan_list); static dlist_head cached_expression_list = DLIST_STATIC_INIT(cached_expression_list); static void ReleaseGenericPlan(CachedPlanSource *plansource); +static bool StmtPlanRequiresRevalidation(CachedPlanSource *plansource); +static bool BuildingPlanRequiresSnapshot(CachedPlanSource *plansource); static List *RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv); static bool CheckCachedPlan(CachedPlanSource *plansource); @@ -165,7 +156,7 @@ InitPlanCache(void) } /* - * CreateCachedPlan: initially create a plan cache entry. + * CreateCachedPlan: initially create a plan cache entry for a raw parse tree. * * Creation of a cached plan is divided into two steps, CreateCachedPlan and * CompleteCachedPlan. CreateCachedPlan should be called after running the @@ -219,6 +210,7 @@ CreateCachedPlan(RawStmt *raw_parse_tree, plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource)); plansource->magic = CACHEDPLANSOURCE_MAGIC; plansource->raw_parse_tree = copyObject(raw_parse_tree); + plansource->analyzed_parse_tree = NULL; plansource->query_string = pstrdup(query_string); MemoryContextSetIdentifier(source_context, plansource->query_string); plansource->commandTag = commandTag; @@ -226,6 +218,8 @@ CreateCachedPlan(RawStmt *raw_parse_tree, plansource->num_params = 0; plansource->parserSetup = NULL; plansource->parserSetupArg = NULL; + plansource->postRewrite = NULL; + plansource->postRewriteArg = NULL; plansource->cursor_options = 0; plansource->fixed_result = false; plansource->resultDesc = NULL; @@ -254,6 +248,34 @@ CreateCachedPlan(RawStmt *raw_parse_tree, return plansource; } +/* + * CreateCachedPlanForQuery: initially create a plan cache entry for a Query. + * + * This is used in the same way as CreateCachedPlan, except that the source + * query has already been through parse analysis, and the plancache will never + * try to re-do that step. + * + * Currently this is used only for new-style SQL functions, where we have a + * Query from the function's prosqlbody, but no source text. The query_string + * is typically empty, but is required anyway. + */ +CachedPlanSource * +CreateCachedPlanForQuery(Query *analyzed_parse_tree, + const char *query_string, + CommandTag commandTag) +{ + CachedPlanSource *plansource; + MemoryContext oldcxt; + + /* Rather than duplicating CreateCachedPlan, just do this: */ + plansource = CreateCachedPlan(NULL, query_string, commandTag); + oldcxt = MemoryContextSwitchTo(plansource->context); + plansource->analyzed_parse_tree = copyObject(analyzed_parse_tree); + MemoryContextSwitchTo(oldcxt); + + return plansource; +} + /* * CreateOneShotCachedPlan: initially create a one-shot plan cache entry. * @@ -288,12 +310,15 @@ CreateOneShotCachedPlan(RawStmt *raw_parse_tree, plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource)); plansource->magic = CACHEDPLANSOURCE_MAGIC; plansource->raw_parse_tree = raw_parse_tree; + plansource->analyzed_parse_tree = NULL; plansource->query_string = query_string; plansource->commandTag = commandTag; plansource->param_types = NULL; plansource->num_params = 0; plansource->parserSetup = NULL; plansource->parserSetupArg = NULL; + plansource->postRewrite = NULL; + plansource->postRewriteArg = NULL; plansource->cursor_options = 0; plansource->fixed_result = false; plansource->resultDesc = NULL; @@ -463,6 +488,29 @@ CompleteCachedPlan(CachedPlanSource *plansource, plansource->is_valid = true; } +/* + * SetPostRewriteHook: set a hook to modify post-rewrite query trees + * + * Some callers have a need to modify the query trees between rewriting and + * planning. In the initial call to CompleteCachedPlan, it's assumed such + * work was already done on the querytree_list. However, if we're forced + * to replan, it will need to be done over. The caller can set this hook + * to provide code to make that happen. + * + * postRewriteArg is just passed verbatim to the hook. As with parserSetupArg, + * it is caller's responsibility that the referenced data remains + * valid for as long as the CachedPlanSource exists. + */ +void +SetPostRewriteHook(CachedPlanSource *plansource, + PostRewriteHook postRewrite, + void *postRewriteArg) +{ + Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); + plansource->postRewrite = postRewrite; + plansource->postRewriteArg = postRewriteArg; +} + /* * SaveCachedPlan: save a cached plan permanently * @@ -565,6 +613,42 @@ ReleaseGenericPlan(CachedPlanSource *plansource) } } +/* + * We must skip "overhead" operations that involve database access when the + * cached plan's subject statement is a transaction control command or one + * that requires a snapshot not to be set yet (such as SET or LOCK). More + * generally, statements that do not require parse analysis/rewrite/plan + * activity never need to be revalidated, so we can treat them all like that. + * For the convenience of postgres.c, treat empty statements that way too. + */ +static bool +StmtPlanRequiresRevalidation(CachedPlanSource *plansource) +{ + if (plansource->raw_parse_tree != NULL) + return stmt_requires_parse_analysis(plansource->raw_parse_tree); + else if (plansource->analyzed_parse_tree != NULL) + return query_requires_rewrite_plan(plansource->analyzed_parse_tree); + /* empty query never needs revalidation */ + return false; +} + +/* + * Determine if creating a plan for this CachedPlanSource requires a snapshot. + * In fact this function matches StmtPlanRequiresRevalidation(), but we want + * to preserve the distinction between stmt_requires_parse_analysis() and + * analyze_requires_snapshot(). + */ +static bool +BuildingPlanRequiresSnapshot(CachedPlanSource *plansource) +{ + if (plansource->raw_parse_tree != NULL) + return analyze_requires_snapshot(plansource->raw_parse_tree); + else if (plansource->analyzed_parse_tree != NULL) + return query_requires_rewrite_plan(plansource->analyzed_parse_tree); + /* empty query never needs a snapshot */ + return false; +} + /* * RevalidateCachedQuery: ensure validity of analyzed-and-rewritten query tree. * @@ -584,7 +668,6 @@ RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv) { bool snapshot_set; - RawStmt *rawtree; List *tlist; /* transient query-tree list */ List *qlist; /* permanent query-tree list */ TupleDesc resultDesc; @@ -607,7 +690,10 @@ RevalidateCachedQuery(CachedPlanSource *plansource, /* * If the query is currently valid, we should have a saved search_path --- * check to see if that matches the current environment. If not, we want - * to force replan. + * to force replan. (We could almost ignore this consideration when + * working from an analyzed parse tree; but there are scenarios where + * planning can have search_path-dependent results, for example if it + * inlines an old-style SQL function.) */ if (plansource->is_valid) { @@ -654,9 +740,9 @@ RevalidateCachedQuery(CachedPlanSource *plansource, } /* - * Discard the no-longer-useful query tree. (Note: we don't want to do - * this any earlier, else we'd not have been able to release locks - * correctly in the race condition case.) + * Discard the no-longer-useful rewritten query tree. (Note: we don't + * want to do this any earlier, else we'd not have been able to release + * locks correctly in the race condition case.) */ plansource->is_valid = false; plansource->query_list = NIL; @@ -702,25 +788,52 @@ RevalidateCachedQuery(CachedPlanSource *plansource, } /* - * Run parse analysis and rule rewriting. The parser tends to scribble on - * its input, so we must copy the raw parse tree to prevent corruption of - * the cache. + * Run parse analysis (if needed) and rule rewriting. */ - rawtree = copyObject(plansource->raw_parse_tree); - if (rawtree == NULL) - tlist = NIL; - else if (plansource->parserSetup != NULL) - tlist = pg_analyze_and_rewrite_withcb(rawtree, - plansource->query_string, - plansource->parserSetup, - plansource->parserSetupArg, - queryEnv); + if (plansource->raw_parse_tree != NULL) + { + /* Source is raw parse tree */ + RawStmt *rawtree; + + /* + * The parser tends to scribble on its input, so we must copy the raw + * parse tree to prevent corruption of the cache. + */ + rawtree = copyObject(plansource->raw_parse_tree); + if (plansource->parserSetup != NULL) + tlist = pg_analyze_and_rewrite_withcb(rawtree, + plansource->query_string, + plansource->parserSetup, + plansource->parserSetupArg, + queryEnv); + else + tlist = pg_analyze_and_rewrite_fixedparams(rawtree, + plansource->query_string, + plansource->param_types, + plansource->num_params, + queryEnv); + } + else if (plansource->analyzed_parse_tree != NULL) + { + /* Source is pre-analyzed query, so we only need to rewrite */ + Query *analyzed_tree; + + /* The rewriter scribbles on its input, too, so copy */ + analyzed_tree = copyObject(plansource->analyzed_parse_tree); + /* Acquire locks needed before rewriting ... */ + AcquireRewriteLocks(analyzed_tree, true, false); + /* ... and do it */ + tlist = pg_rewrite_query(analyzed_tree); + } else - tlist = pg_analyze_and_rewrite_fixedparams(rawtree, - plansource->query_string, - plansource->param_types, - plansource->num_params, - queryEnv); + { + /* Empty query, nothing to do */ + tlist = NIL; + } + + /* Apply post-rewrite callback if there is one */ + if (plansource->postRewrite != NULL) + plansource->postRewrite(tlist, plansource->postRewriteArg); /* Release snapshot if we got one */ if (snapshot_set) @@ -949,8 +1062,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist, */ snapshot_set = false; if (!ActiveSnapshotSet() && - plansource->raw_parse_tree && - analyze_requires_snapshot(plansource->raw_parse_tree)) + BuildingPlanRequiresSnapshot(plansource)) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; @@ -1559,6 +1671,7 @@ CopyCachedPlan(CachedPlanSource *plansource) newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource)); newsource->magic = CACHEDPLANSOURCE_MAGIC; newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree); + newsource->analyzed_parse_tree = copyObject(plansource->analyzed_parse_tree); newsource->query_string = pstrdup(plansource->query_string); MemoryContextSetIdentifier(source_context, newsource->query_string); newsource->commandTag = plansource->commandTag; @@ -1574,6 +1687,8 @@ CopyCachedPlan(CachedPlanSource *plansource) newsource->num_params = plansource->num_params; newsource->parserSetup = plansource->parserSetup; newsource->parserSetupArg = plansource->parserSetupArg; + newsource->postRewrite = plansource->postRewrite; + newsource->postRewriteArg = plansource->postRewriteArg; newsource->cursor_options = plansource->cursor_options; newsource->fixed_result = plansource->fixed_result; if (plansource->resultDesc) @@ -1907,8 +2022,7 @@ ScanQueryForLocks(Query *parsetree, bool acquire) */ if (parsetree->hasSubLinks) { - query_tree_walker(parsetree, ScanQueryWalker, - (void *) &acquire, + query_tree_walker(parsetree, ScanQueryWalker, &acquire, QTW_IGNORE_RC_SUBQUERIES); } } @@ -1934,8 +2048,7 @@ ScanQueryWalker(Node *node, bool *acquire) * Do NOT recurse into Query nodes, because ScanQueryForLocks already * processed subselects of subselects for us. */ - return expression_tree_walker(node, ScanQueryWalker, - (void *) acquire); + return expression_tree_walker(node, ScanQueryWalker, acquire); } /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 66ed24e401276..559ba9cdb2cde 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -3,7 +3,7 @@ * relcache.c * POSTGRES relation descriptor cache code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -276,7 +276,8 @@ static HTAB *OpClassCache = NULL; static void RelationCloseCleanup(Relation relation); static void RelationDestroyRelation(Relation relation, bool remember_tupdesc); static void RelationInvalidateRelation(Relation relation); -static void RelationClearRelation(Relation relation, bool rebuild); +static void RelationClearRelation(Relation relation); +static void RelationRebuildRelation(Relation relation); static void RelationReloadIndexInfo(Relation relation); static void RelationReloadNailed(Relation relation); @@ -306,7 +307,7 @@ static TupleDesc GetPgClassDescriptor(void); static TupleDesc GetPgIndexDescriptor(void); static void AttrDefaultFetch(Relation relation, int ndef); static int AttrDefaultCmp(const void *a, const void *b); -static void CheckConstraintFetch(Relation relation); +static void CheckNNConstraintFetch(Relation relation); static int CheckConstraintCmp(const void *a, const void *b); static void InitIndexAmRoutine(Relation relation); static void IndexSupportInitialize(oidvector *indclass, @@ -370,14 +371,13 @@ ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic) pg_class_desc = table_open(RelationRelationId, AccessShareLock); /* - * The caller might need a tuple that's newer than the one the historic - * snapshot; currently the only case requiring to do so is looking up the - * relfilenumber of non mapped system relations during decoding. That - * snapshot can't change in the midst of a relcache build, so there's no - * need to register the snapshot. + * The caller might need a tuple that's newer than what's visible to the + * historic snapshot; currently the only case requiring to do so is + * looking up the relfilenumber of non mapped system relations during + * decoding. */ if (force_non_historic) - snapshot = GetNonHistoricCatalogSnapshot(RelationRelationId); + snapshot = RegisterSnapshot(GetNonHistoricCatalogSnapshot(RelationRelationId)); pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId, indexOK && criticalRelcachesBuilt, @@ -394,6 +394,10 @@ ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic) /* all done */ systable_endscan(pg_class_scan); + + if (snapshot) + UnregisterSnapshot(snapshot); + table_close(pg_class_desc, AccessShareLock); return pg_class_tuple; @@ -584,11 +588,15 @@ RelationBuildTupleDesc(Relation relation) attp, ATTRIBUTE_FIXED_PART_SIZE); + populate_compact_attribute(relation->rd_att, attnum - 1); + /* Update constraint/default info */ if (attp->attnotnull) constr->has_not_null = true; if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED) constr->has_generated_stored = true; + if (attp->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + constr->has_generated_virtual = true; if (attp->atthasdef) ndef++; @@ -659,36 +667,25 @@ RelationBuildTupleDesc(Relation relation) need, RelationGetRelid(relation)); /* - * The attcacheoff values we read from pg_attribute should all be -1 - * ("unknown"). Verify this if assert checking is on. They will be - * computed when and if needed during tuple access. - */ -#ifdef USE_ASSERT_CHECKING - { - int i; - - for (i = 0; i < RelationGetNumberOfAttributes(relation); i++) - Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1); - } -#endif - - /* - * However, we can easily set the attcacheoff value for the first - * attribute: it must be zero. This eliminates the need for special cases - * for attnum=1 that used to exist in fastgetattr() and index_getattr(). + * We can easily set the attcacheoff value for the first attribute: it + * must be zero. This eliminates the need for special cases for attnum=1 + * that used to exist in fastgetattr() and index_getattr(). */ if (RelationGetNumberOfAttributes(relation) > 0) - TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0; + TupleDescCompactAttr(relation->rd_att, 0)->attcacheoff = 0; /* * Set up constraint/default info */ if (constr->has_not_null || constr->has_generated_stored || + constr->has_generated_virtual || ndef > 0 || attrmiss || relation->rd_rel->relchecks > 0) { + bool is_catalog = IsCatalogRelation(relation); + relation->rd_att->constr = constr; if (ndef > 0) /* DEFAULTs */ @@ -698,9 +695,33 @@ RelationBuildTupleDesc(Relation relation) constr->missing = attrmiss; - if (relation->rd_rel->relchecks > 0) /* CHECKs */ - CheckConstraintFetch(relation); - else + /* CHECK and NOT NULLs */ + if (relation->rd_rel->relchecks > 0 || + (!is_catalog && constr->has_not_null)) + CheckNNConstraintFetch(relation); + + /* + * Any not-null constraint that wasn't marked invalid by + * CheckNNConstraintFetch must necessarily be valid; make it so in the + * CompactAttribute array. + */ + if (!is_catalog) + { + for (int i = 0; i < relation->rd_rel->relnatts; i++) + { + CompactAttribute *attr; + + attr = TupleDescCompactAttr(relation->rd_att, i); + + if (attr->attnullability == ATTNULLABLE_UNKNOWN) + attr->attnullability = ATTNULLABLE_VALID; + else + Assert(attr->attnullability == ATTNULLABLE_INVALID || + attr->attnullability == ATTNULLABLE_UNRESTRICTED); + } + } + + if (relation->rd_rel->relchecks == 0) constr->num_check = 0; } else @@ -721,7 +742,7 @@ RelationBuildTupleDesc(Relation relation) * we make a private memory context to hold the RuleLock information for * each relcache entry that has associated rules. The context is used * just for rule info, not for any other subsidiary data of the relcache - * entry, because that keeps the update logic in RelationClearRelation() + * entry, because that keeps the update logic in RelationRebuildRelation() * manageable. The other subsidiary data structures are simple enough * to be easy to free explicitly, anyway. * @@ -1936,9 +1957,9 @@ formrdesc(const char *relationName, Oid relationReltype, relation->rd_rel->relpages = 0; relation->rd_rel->reltuples = -1; relation->rd_rel->relallvisible = 0; + relation->rd_rel->relallfrozen = 0; relation->rd_rel->relkind = RELKIND_RELATION; relation->rd_rel->relnatts = (int16) natts; - relation->rd_rel->relam = HEAP_TABLE_AM_OID; /* * initialize attribute tuple form @@ -1963,12 +1984,12 @@ formrdesc(const char *relationName, Oid relationReltype, &attrs[i], ATTRIBUTE_FIXED_PART_SIZE); has_not_null |= attrs[i].attnotnull; - /* make sure attcacheoff is valid */ - TupleDescAttr(relation->rd_att, i)->attcacheoff = -1; + + populate_compact_attribute(relation->rd_att, i); } /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ - TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0; + TupleDescCompactAttr(relation->rd_att, 0)->attcacheoff = 0; /* mark not-null status */ if (has_not_null) @@ -2035,6 +2056,23 @@ formrdesc(const char *relationName, Oid relationReltype, relation->rd_isvalid = true; } +#ifdef USE_ASSERT_CHECKING +/* + * AssertCouldGetRelation + * + * Check safety of calling RelationIdGetRelation(). + * + * In code that reads catalogs in the event of a cache miss, call this + * before checking the cache. + */ +void +AssertCouldGetRelation(void) +{ + Assert(IsTransactionState()); + AssertBufferLocksPermitCatalogRead(); +} +#endif + /* ---------------------------------------------------------------- * Relation Descriptor Lookup Interface @@ -2062,8 +2100,7 @@ RelationIdGetRelation(Oid relationId) { Relation rd; - /* Make sure we're in an xact, even if this ends up being a cache hit */ - Assert(IsTransactionState()); + AssertCouldGetRelation(); /* * first try to find reldesc in the cache @@ -2083,16 +2120,7 @@ RelationIdGetRelation(Oid relationId) /* revalidate cache entry if necessary */ if (!rd->rd_isvalid) { - /* - * Indexes only have a limited number of possible schema changes, - * and we don't want to use the full-blown procedure because it's - * a headache for indexes that reload itself depends on. - */ - if (rd->rd_rel->relkind == RELKIND_INDEX || - rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) - RelationReloadIndexInfo(rd); - else - RelationClearRelation(rd, true); + RelationRebuildRelation(rd); /* * Normally entries need to be valid here, but before the relcache @@ -2220,7 +2248,7 @@ RelationCloseCleanup(Relation relation) if (RelationHasReferenceCountZero(relation) && relation->rd_createSubid == InvalidSubTransactionId && relation->rd_firstRelfilelocatorSubid == InvalidSubTransactionId) - RelationClearRelation(relation, false); + RelationClearRelation(relation); #endif } @@ -2235,15 +2263,8 @@ RelationCloseCleanup(Relation relation) * and/or in active use. We support full replacement of the pg_class row, * as well as updates of a few simple fields of the pg_index row. * - * We can't necessarily reread the catalog rows right away; we might be - * in a failed transaction when we receive the SI notification. If so, - * RelationClearRelation just marks the entry as invalid by setting - * rd_isvalid to false. This routine is called to fix the entry when it - * is next needed. - * * We assume that at the time we are called, we have at least AccessShareLock - * on the target index. (Note: in the calls from RelationClearRelation, - * this is legitimate because we know the rel has positive refcount.) + * on the target index. * * If the target index is an index on pg_class or pg_index, we'd better have * previously gotten at least AccessShareLock on its underlying catalog, @@ -2264,23 +2285,18 @@ RelationReloadIndexInfo(Relation relation) !relation->rd_isvalid && relation->rd_droppedSubid == InvalidSubTransactionId); - /* Ensure it's closed at smgr level */ - RelationCloseSmgr(relation); - - /* Must free any AM cached data upon relcache flush */ - if (relation->rd_amcache) - pfree(relation->rd_amcache); - relation->rd_amcache = NULL; - /* * If it's a shared index, we might be called before backend startup has * finished selecting a database, in which case we have no way to read * pg_class yet. However, a shared index can never have any significant - * schema updates, so it's okay to ignore the invalidation signal. Just - * mark it valid and return without doing anything more. + * schema updates, so it's okay to mostly ignore the invalidation signal. + * Its physical relfilenumber might've changed, but that's all. Update + * the physical relfilenumber, mark it valid and return without doing + * anything more. */ if (relation->rd_rel->relisshared && !criticalRelcachesBuilt) { + RelationInitPhysicalAddr(relation); relation->rd_isvalid = true; return; } @@ -2368,7 +2384,12 @@ RelationReloadIndexInfo(Relation relation) static void RelationReloadNailed(Relation relation) { + /* Should be called only for invalidated, nailed relations */ + Assert(!relation->rd_isvalid); Assert(relation->rd_isnailed); + /* nailed indexes are handled by RelationReloadIndexInfo() */ + Assert(relation->rd_rel->relkind == RELKIND_RELATION); + AssertCouldGetRelation(); /* * Redo RelationInitPhysicalAddr in case it is a mapped relation whose @@ -2376,58 +2397,35 @@ RelationReloadNailed(Relation relation) */ RelationInitPhysicalAddr(relation); - /* flag as needing to be revalidated */ - relation->rd_isvalid = false; - /* - * Can only reread catalog contents if in a transaction. If the relation - * is currently open (not counting the nailed refcount), do so - * immediately. Otherwise we've already marked the entry as possibly - * invalid, and it'll be fixed when next opened. + * Reload a non-index entry. We can't easily do so if relcaches aren't + * yet built, but that's fine because at that stage the attributes that + * need to be current (like relfrozenxid) aren't yet accessed. To ensure + * the entry will later be revalidated, we leave it in invalid state, but + * allow use (cf. RelationIdGetRelation()). */ - if (!IsTransactionState() || relation->rd_refcnt <= 1) - return; - - if (relation->rd_rel->relkind == RELKIND_INDEX) - { - /* - * If it's a nailed-but-not-mapped index, then we need to re-read the - * pg_class row to see if its relfilenumber changed. - */ - RelationReloadIndexInfo(relation); - } - else + if (criticalRelcachesBuilt) { + HeapTuple pg_class_tuple; + Form_pg_class relp; + /* - * Reload a non-index entry. We can't easily do so if relcaches - * aren't yet built, but that's fine because at that stage the - * attributes that need to be current (like relfrozenxid) aren't yet - * accessed. To ensure the entry will later be revalidated, we leave - * it in invalid state, but allow use (cf. RelationIdGetRelation()). + * NB: Mark the entry as valid before starting to scan, to avoid + * self-recursion when re-building pg_class. */ - if (criticalRelcachesBuilt) - { - HeapTuple pg_class_tuple; - Form_pg_class relp; - - /* - * NB: Mark the entry as valid before starting to scan, to avoid - * self-recursion when re-building pg_class. - */ - relation->rd_isvalid = true; + relation->rd_isvalid = true; - pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), - true, false); - relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); - memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE); - heap_freetuple(pg_class_tuple); + pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), + true, false); + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE); + heap_freetuple(pg_class_tuple); - /* - * Again mark as valid, to protect against concurrently arriving - * invalidations. - */ - relation->rd_isvalid = true; - } + /* + * Again mark as valid, to protect against concurrently arriving + * invalidations. + */ + relation->rd_isvalid = true; } } @@ -2537,120 +2535,85 @@ RelationInvalidateRelation(Relation relation) } /* - * RelationClearRelation - * - * Physically blow away a relation cache entry, or reset it and rebuild - * it from scratch (that is, from catalog entries). The latter path is - * used when we are notified of a change to an open relation (one with - * refcount > 0). - * - * NB: when rebuilding, we'd better hold some lock on the relation, - * else the catalog data we need to read could be changing under us. - * Also, a rel to be rebuilt had better have refcnt > 0. This is because - * a sinval reset could happen while we're accessing the catalogs, and - * the rel would get blown away underneath us by RelationCacheInvalidate - * if it has zero refcnt. - * - * The "rebuild" parameter is redundant in current usage because it has - * to match the relation's refcnt status, but we keep it as a crosscheck - * that we're doing what the caller expects. + * RelationClearRelation - physically blow away a relation cache entry + * + * The caller must ensure that the entry is no longer needed, i.e. its + * reference count is zero. Also, the rel or its storage must not be created + * in the current transaction (rd_createSubid and rd_firstRelfilelocatorSubid + * must not be set). */ static void -RelationClearRelation(Relation relation, bool rebuild) +RelationClearRelation(Relation relation) { - /* - * As per notes above, a rel to be rebuilt MUST have refcnt > 0; while of - * course it would be an equally bad idea to blow away one with nonzero - * refcnt, since that would leave someone somewhere with a dangling - * pointer. All callers are expected to have verified that this holds. - */ - Assert(rebuild ? - !RelationHasReferenceCountZero(relation) : - RelationHasReferenceCountZero(relation)); + Assert(RelationHasReferenceCountZero(relation)); + Assert(!relation->rd_isnailed); /* - * Make sure smgr and lower levels close the relation's files, if they - * weren't closed already. If the relation is not getting deleted, the - * next smgr access should reopen the files automatically. This ensures - * that the low-level file access state is updated after, say, a vacuum - * truncation. + * Relations created in the same transaction must never be removed, see + * RelationFlushRelation. */ - RelationCloseSmgr(relation); + Assert(relation->rd_createSubid == InvalidSubTransactionId); + Assert(relation->rd_firstRelfilelocatorSubid == InvalidSubTransactionId); + Assert(relation->rd_droppedSubid == InvalidSubTransactionId); - /* Free AM cached data, if any */ - if (relation->rd_amcache) - pfree(relation->rd_amcache); - relation->rd_amcache = NULL; + /* first mark it as invalid */ + RelationInvalidateRelation(relation); - /* - * Treat nailed-in system relations separately, they always need to be - * accessible, so we can't blow them away. - */ - if (relation->rd_isnailed) - { - RelationReloadNailed(relation); - return; - } + /* Remove it from the hash table */ + RelationCacheDelete(relation); - /* Mark it invalid until we've finished rebuild */ - relation->rd_isvalid = false; + /* And release storage */ + RelationDestroyRelation(relation, false); +} - /* See RelationForgetRelation(). */ - if (relation->rd_droppedSubid != InvalidSubTransactionId) - return; +/* + * RelationRebuildRelation - rebuild a relation cache entry in place + * + * Reset and rebuild a relation cache entry from scratch (that is, from + * catalog entries). This is used when we are notified of a change to an open + * relation (one with refcount > 0). The entry is reconstructed without + * moving the physical RelationData record, so that the refcount holder's + * pointer is still valid. + * + * NB: when rebuilding, we'd better hold some lock on the relation, else the + * catalog data we need to read could be changing under us. Also, a rel to be + * rebuilt had better have refcnt > 0. This is because a sinval reset could + * happen while we're accessing the catalogs, and the rel would get blown away + * underneath us by RelationCacheInvalidate if it has zero refcnt. + */ +static void +RelationRebuildRelation(Relation relation) +{ + Assert(!RelationHasReferenceCountZero(relation)); + AssertCouldGetRelation(); + /* there is no reason to ever rebuild a dropped relation */ + Assert(relation->rd_droppedSubid == InvalidSubTransactionId); + + /* Close and mark it as invalid until we've finished the rebuild */ + RelationInvalidateRelation(relation); /* - * Even non-system indexes should not be blown away if they are open and - * have valid index support information. This avoids problems with active - * use of the index support information. As with nailed indexes, we - * re-read the pg_class row to handle possible physical relocation of the - * index, and we check for pg_index updates too. + * Indexes only have a limited number of possible schema changes, and we + * don't want to use the full-blown procedure because it's a headache for + * indexes that reload itself depends on. + * + * As an exception, use the full procedure if the index access info hasn't + * been initialized yet. Index creation relies on that: it first builds + * the relcache entry with RelationBuildLocalRelation(), creates the + * pg_index tuple only after that, and then relies on + * CommandCounterIncrement to load the pg_index contents. */ if ((relation->rd_rel->relkind == RELKIND_INDEX || relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) && - relation->rd_refcnt > 0 && relation->rd_indexcxt != NULL) { - if (IsTransactionState()) - RelationReloadIndexInfo(relation); + RelationReloadIndexInfo(relation); return; } - - /* - * If we're really done with the relcache entry, blow it away. But if - * someone is still using it, reconstruct the whole deal without moving - * the physical RelationData record (so that the someone's pointer is - * still valid). - */ - if (!rebuild) + /* Nailed relations are handled separately. */ + else if (relation->rd_isnailed) { - /* Remove it from the hash table */ - RelationCacheDelete(relation); - - /* And release storage */ - RelationDestroyRelation(relation, false); - } - else if (!IsTransactionState()) - { - /* - * If we're not inside a valid transaction, we can't do any catalog - * access so it's not possible to rebuild yet. Just exit, leaving - * rd_isvalid = false so that the rebuild will occur when the entry is - * next opened. - * - * Note: it's possible that we come here during subtransaction abort, - * and the reason for wanting to rebuild is that the rel is open in - * the outer transaction. In that case it might seem unsafe to not - * rebuild immediately, since whatever code has the rel already open - * will keep on using the relcache entry as-is. However, in such a - * case the outer transaction should be holding a lock that's - * sufficient to prevent any significant change in the rel's schema, - * so the existing entry contents should be good enough for its - * purposes; at worst we might be behind on statistics updates or the - * like. (See also CheckTableNotInUse() and its callers.) These same - * remarks also apply to the cases above where we exit without having - * done RelationReloadIndexInfo() yet. - */ + RelationReloadNailed(relation); return; } else @@ -2879,28 +2842,47 @@ RelationFlushRelation(Relation relation) * that the current transaction has some lock on the rel already. */ RelationIncrementReferenceCount(relation); - RelationClearRelation(relation, true); + RelationRebuildRelation(relation); RelationDecrementReferenceCount(relation); } else - { - /* - * During abort processing, the current resource owner is not - * valid and we cannot hold a refcnt. Without a valid - * transaction, RelationClearRelation() would just mark the rel as - * invalid anyway, so we can do the same directly. - */ RelationInvalidateRelation(relation); - } } else { /* * Pre-existing rels can be dropped from the relcache if not open. + * + * If the entry is in use, rebuild it if possible. If we're not + * inside a valid transaction, we can't do any catalog access so it's + * not possible to rebuild yet. Just mark it as invalid in that case, + * so that the rebuild will occur when the entry is next opened. + * + * Note: it's possible that we come here during subtransaction abort, + * and the reason for wanting to rebuild is that the rel is open in + * the outer transaction. In that case it might seem unsafe to not + * rebuild immediately, since whatever code has the rel already open + * will keep on using the relcache entry as-is. However, in such a + * case the outer transaction should be holding a lock that's + * sufficient to prevent any significant change in the rel's schema, + * so the existing entry contents should be good enough for its + * purposes; at worst we might be behind on statistics updates or the + * like. (See also CheckTableNotInUse() and its callers.) */ - bool rebuild = !RelationHasReferenceCountZero(relation); - - RelationClearRelation(relation, rebuild); + if (RelationHasReferenceCountZero(relation)) + RelationClearRelation(relation); + else if (!IsTransactionState()) + RelationInvalidateRelation(relation); + else if (relation->rd_isnailed && relation->rd_refcnt == 1) + { + /* + * A nailed relation with refcnt == 1 is unused. We cannot clear + * it, but there's also no need no need to rebuild it immediately. + */ + RelationInvalidateRelation(relation); + } + else + RelationRebuildRelation(relation); } } @@ -2926,14 +2908,15 @@ RelationForgetRelation(Oid rid) { /* * In the event of subtransaction rollback, we must not forget - * rd_*Subid. Mark the entry "dropped" so RelationClearRelation() - * invalidates it in lieu of destroying it. (If we're in a top - * transaction, we could opt to destroy the entry.) + * rd_*Subid. Mark the entry "dropped" and invalidate it, instead of + * destroying it right away. (If we're in a top transaction, we could + * opt to destroy the entry.) */ relation->rd_droppedSubid = GetCurrentSubTransactionId(); + RelationInvalidateRelation(relation); } - - RelationClearRelation(relation, false); + else + RelationClearRelation(relation); } /* @@ -3045,8 +3028,7 @@ RelationCacheInvalidate(bool debug_discard) if (RelationHasReferenceCountZero(relation)) { /* Delete this entry immediately */ - Assert(!relation->rd_isnailed); - RelationClearRelation(relation, false); + RelationClearRelation(relation); } else { @@ -3089,17 +3071,26 @@ RelationCacheInvalidate(bool debug_discard) */ smgrreleaseall(); - /* Phase 2: rebuild the items found to need rebuild in phase 1 */ + /* + * Phase 2: rebuild (or invalidate) the items found to need rebuild in + * phase 1 + */ foreach(l, rebuildFirstList) { relation = (Relation) lfirst(l); - RelationClearRelation(relation, true); + if (!IsTransactionState() || (relation->rd_isnailed && relation->rd_refcnt == 1)) + RelationInvalidateRelation(relation); + else + RelationRebuildRelation(relation); } list_free(rebuildFirstList); foreach(l, rebuildList) { relation = (Relation) lfirst(l); - RelationClearRelation(relation, true); + if (!IsTransactionState() || (relation->rd_isnailed && relation->rd_refcnt == 1)) + RelationInvalidateRelation(relation); + else + RelationRebuildRelation(relation); } list_free(rebuildList); @@ -3357,7 +3348,7 @@ AtEOXact_cleanup(Relation relation, bool isCommit) { if (RelationHasReferenceCountZero(relation)) { - RelationClearRelation(relation, false); + RelationClearRelation(relation); return; } else @@ -3467,7 +3458,7 @@ AtEOSubXact_cleanup(Relation relation, bool isCommit, relation->rd_newRelfilelocatorSubid = InvalidSubTransactionId; relation->rd_firstRelfilelocatorSubid = InvalidSubTransactionId; relation->rd_droppedSubid = InvalidSubTransactionId; - RelationClearRelation(relation, false); + RelationClearRelation(relation); return; } else @@ -3623,6 +3614,15 @@ RelationBuildLocalRelation(const char *relname, datt->attgenerated = satt->attgenerated; datt->attnotnull = satt->attnotnull; has_not_null |= satt->attnotnull; + populate_compact_attribute(rel->rd_att, i); + + if (satt->attnotnull) + { + CompactAttribute *scatt = TupleDescCompactAttr(tupDesc, i); + CompactAttribute *dcatt = TupleDescCompactAttr(rel->rd_att, i); + + dcatt->attnullability = scatt->attnullability; + } } if (has_not_null) @@ -3720,6 +3720,12 @@ RelationBuildLocalRelation(const char *relname, if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE) RelationInitTableAccessMethod(rel); + /* + * Leave index access method uninitialized, because the pg_index row has + * not been inserted at this stage of index creation yet. The cache + * invalidation after pg_index row has been inserted will initialize it. + */ + /* * Okay to insert into the relcache hash table. * @@ -3768,6 +3774,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) { RelFileNumber newrelfilenumber; Relation pg_class; + ItemPointerData otid; HeapTuple tuple; Form_pg_class classform; MultiXactId minmulti = InvalidMultiXactId; @@ -3810,11 +3817,12 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) */ pg_class = table_open(RelationRelationId, RowExclusiveLock); - tuple = SearchSysCacheCopy1(RELOID, - ObjectIdGetDatum(RelationGetRelid(relation))); + tuple = SearchSysCacheLockedCopy1(RELOID, + ObjectIdGetDatum(RelationGetRelid(relation))); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for relation %u", RelationGetRelid(relation)); + otid = tuple->t_self; classform = (Form_pg_class) GETSTRUCT(tuple); /* @@ -3929,14 +3937,16 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) classform->relpages = 0; /* it's empty until further notice */ classform->reltuples = -1; classform->relallvisible = 0; + classform->relallfrozen = 0; } classform->relfrozenxid = freezeXid; classform->relminmxid = minmulti; classform->relpersistence = persistence; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_class, &otid, tuple); } + UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); heap_freetuple(tuple); table_close(pg_class, RowExclusiveLock); @@ -4432,12 +4442,12 @@ BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs) for (i = 0; i < natts; i++) { memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE); - /* make sure attcacheoff is valid */ - TupleDescAttr(result, i)->attcacheoff = -1; + + populate_compact_attribute(result, i); } /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ - TupleDescAttr(result, 0)->attcacheoff = 0; + TupleDescCompactAttr(result, 0)->attcacheoff = 0; /* Note: we don't bother to set up a TupleConstr entry */ @@ -4571,13 +4581,14 @@ AttrDefaultCmp(const void *a, const void *b) } /* - * Load any check constraints for the relation. + * Load any check constraints for the relation, and update not-null validity + * of invalid constraints. * * As with defaults, if we don't find the expected number of them, just warn * here. The executor should throw an error if an INSERT/UPDATE is attempted. */ static void -CheckConstraintFetch(Relation relation) +CheckNNConstraintFetch(Relation relation) { ConstrCheck *check; int ncheck = relation->rd_rel->relchecks; @@ -4587,10 +4598,13 @@ CheckConstraintFetch(Relation relation) HeapTuple htup; int found = 0; - /* Allocate array with room for as many entries as expected */ - check = (ConstrCheck *) - MemoryContextAllocZero(CacheMemoryContext, - ncheck * sizeof(ConstrCheck)); + /* Allocate array with room for as many entries as expected, if needed */ + if (ncheck > 0) + check = (ConstrCheck *) + MemoryContextAllocZero(CacheMemoryContext, + ncheck * sizeof(ConstrCheck)); + else + check = NULL; /* Search pg_constraint for relevant entries */ ScanKeyInit(&skey[0], @@ -4608,7 +4622,31 @@ CheckConstraintFetch(Relation relation) Datum val; bool isnull; - /* We want check constraints only */ + /* + * If this is a not-null constraint, then only look at it if it's + * invalid, and if so, mark the TupleDesc entry as known invalid. + * Otherwise move on. We'll mark any remaining columns that are still + * in UNKNOWN state as known valid later. This allows us not to have + * to extract the attnum from this constraint tuple in the vast + * majority of cases. + */ + if (conform->contype == CONSTRAINT_NOTNULL) + { + if (!conform->convalidated) + { + AttrNumber attnum; + + attnum = extractNotNullColumn(htup); + Assert(relation->rd_att->compact_attrs[attnum - 1].attnullability == + ATTNULLABLE_UNKNOWN); + relation->rd_att->compact_attrs[attnum - 1].attnullability = + ATTNULLABLE_INVALID; + } + + continue; + } + + /* For what follows, consider check constraints only */ if (conform->contype != CONSTRAINT_CHECK) continue; @@ -4620,6 +4658,7 @@ CheckConstraintFetch(Relation relation) break; } + check[found].ccenforced = conform->conenforced; check[found].ccvalid = conform->convalidated; check[found].ccnoinherit = conform->connoinherit; check[found].ccname = MemoryContextStrdup(CacheMemoryContext, @@ -4703,11 +4742,6 @@ RelationGetFKeyList(Relation relation) if (relation->rd_fkeyvalid) return relation->rd_fkeylist; - /* Fast path: non-partitioned tables without triggers can't have FKs */ - if (!relation->rd_rel->relhastriggers && - relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) - return NIL; - /* * We build the list we intend to return (in the caller's context) while * doing the scan. After successfully completing the scan, we copy that @@ -4739,6 +4773,7 @@ RelationGetFKeyList(Relation relation) info->conoid = constraint->oid; info->conrelid = constraint->conrelid; info->confrelid = constraint->confrelid; + info->conenforced = constraint->conenforced; DeconstructFkConstraintRow(htup, &info->nkeys, info->conkey, @@ -4851,18 +4886,38 @@ RelationGetIndexList(Relation relation) result = lappend_oid(result, index->indexrelid); /* - * Invalid, non-unique, non-immediate or predicate indexes aren't - * interesting for either oid indexes or replication identity indexes, - * so don't check them. + * Non-unique or predicate indexes aren't interesting for either oid + * indexes or replication identity indexes, so don't check them. + * Deferred ones are not useful for replication identity either; but + * we do include them if they are PKs. */ - if (!index->indisvalid || !index->indisunique || - !index->indimmediate || + if (!index->indisunique || !heap_attisnull(htup, Anum_pg_index_indpred, NULL)) continue; - /* remember primary key index if any */ - if (index->indisprimary) + /* + * Remember primary key index, if any. For regular tables we do this + * only if the index is valid; but for partitioned tables, then we do + * it even if it's invalid. + * + * The reason for returning invalid primary keys for partitioned + * tables is that we need it to prevent drop of not-null constraints + * that may underlie such a primary key, which is only a problem for + * partitioned tables. + */ + if (index->indisprimary && + (index->indisvalid || + relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)) + { pkeyIndex = index->indexrelid; + pkdeferrable = !index->indimmediate; + } + + if (!index->indimmediate) + continue; + + if (!index->indisvalid) + continue; /* remember explicitly chosen replica index */ if (index->indisreplident) @@ -4986,10 +5041,10 @@ RelationGetStatExtList(Relation relation) * RelationGetPrimaryKeyIndex -- get OID of the relation's primary key index * * Returns InvalidOid if there is no such index, or if the primary key is - * DEFERRABLE. + * DEFERRABLE and the caller isn't OK with that. */ Oid -RelationGetPrimaryKeyIndex(Relation relation) +RelationGetPrimaryKeyIndex(Relation relation, bool deferrable_ok) { List *ilist; @@ -5001,7 +5056,11 @@ RelationGetPrimaryKeyIndex(Relation relation) Assert(relation->rd_indexvalid); } - return relation->rd_ispkdeferrable ? InvalidOid : relation->rd_pkindex; + if (deferrable_ok) + return relation->rd_pkindex; + else if (relation->rd_ispkdeferrable) + return InvalidOid; + return relation->rd_pkindex; } /* @@ -5581,11 +5640,14 @@ RelationGetIdentityKeyBitmap(Relation relation) /* * RelationGetExclusionInfo -- get info about index's exclusion constraint * - * This should be called only for an index that is known to have an - * associated exclusion constraint. It returns arrays (palloc'd in caller's - * context) of the exclusion operator OIDs, their underlying functions' - * OIDs, and their strategy numbers in the index's opclasses. We cache - * all this information since it requires a fair amount of work to get. + * This should be called only for an index that is known to have an associated + * exclusion constraint or primary key/unique constraint using WITHOUT + * OVERLAPS. + + * It returns arrays (palloc'd in caller's context) of the exclusion operator + * OIDs, their underlying functions' OIDs, and their strategy numbers in the + * index's opclasses. We cache all this information since it requires a fair + * amount of work to get. */ void RelationGetExclusionInfo(Relation indexRelation, @@ -5649,7 +5711,9 @@ RelationGetExclusionInfo(Relation indexRelation, int nelem; /* We want the exclusion constraint owning the index */ - if (conform->contype != CONSTRAINT_EXCLUSION || + if ((conform->contype != CONSTRAINT_EXCLUSION && + !(conform->conperiod && (conform->contype == CONSTRAINT_PRIMARY + || conform->contype == CONSTRAINT_UNIQUE))) || conform->conindid != RelationGetRelid(indexRelation)) continue; @@ -5712,12 +5776,19 @@ RelationGetExclusionInfo(Relation indexRelation, * Get the publication information for the given relation. * * Traverse all the publications which the relation is in to get the - * publication actions and validate the row filter expressions for such - * publications if any. We consider the row filter expression as invalid if it - * references any column which is not part of REPLICA IDENTITY. + * publication actions and validate: + * 1. The row filter expressions for such publications if any. We consider the + * row filter expression as invalid if it references any column which is not + * part of REPLICA IDENTITY. + * 2. The column list for such publication if any. We consider the column list + * invalid if REPLICA IDENTITY contains any column that is not part of it. + * 3. The generated columns of the relation for such publications. We consider + * any reference of an unpublished generated column in REPLICA IDENTITY as + * invalid. * * To avoid fetching the publication information repeatedly, we cache the - * publication actions and row filter validation information. + * publication actions, row filter validation information, column list + * validation information, and generated column validation information. */ void RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) @@ -5740,6 +5811,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) pubdesc->rf_valid_for_delete = true; pubdesc->cols_valid_for_update = true; pubdesc->cols_valid_for_delete = true; + pubdesc->gencols_valid_for_update = true; + pubdesc->gencols_valid_for_delete = true; return; } @@ -5754,6 +5827,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) pubdesc->rf_valid_for_delete = true; pubdesc->cols_valid_for_update = true; pubdesc->cols_valid_for_delete = true; + pubdesc->gencols_valid_for_update = true; + pubdesc->gencols_valid_for_delete = true; /* Fetch the publication membership info. */ puboids = GetRelationPublications(relid); @@ -5783,6 +5858,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) Oid pubid = lfirst_oid(lc); HeapTuple tup; Form_pg_publication pubform; + bool invalid_column_list; + bool invalid_gen_col; tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid)); @@ -5817,18 +5894,27 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) /* * Check if all columns are part of the REPLICA IDENTITY index or not. * - * If the publication is FOR ALL TABLES then it means the table has no - * column list and we can skip the validation. + * Check if all generated columns included in the REPLICA IDENTITY are + * published. */ - if (!pubform->puballtables && - (pubform->pubupdate || pubform->pubdelete) && - pub_collist_contains_invalid_column(pubid, relation, ancestors, - pubform->pubviaroot)) + if ((pubform->pubupdate || pubform->pubdelete) && + pub_contains_invalid_column(pubid, relation, ancestors, + pubform->pubviaroot, + pubform->pubgencols, + &invalid_column_list, + &invalid_gen_col)) { if (pubform->pubupdate) - pubdesc->cols_valid_for_update = false; + { + pubdesc->cols_valid_for_update = !invalid_column_list; + pubdesc->gencols_valid_for_update = !invalid_gen_col; + } + if (pubform->pubdelete) - pubdesc->cols_valid_for_delete = false; + { + pubdesc->cols_valid_for_delete = !invalid_column_list; + pubdesc->gencols_valid_for_delete = !invalid_gen_col; + } } ReleaseSysCache(tup); @@ -5852,6 +5938,17 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc) pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate && !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete) break; + + /* + * If we know everything is replicated and replica identity has an + * unpublished generated column, there is no point to check for other + * publications. + */ + if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate && + pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate && + !pubdesc->gencols_valid_for_update && + !pubdesc->gencols_valid_for_delete) + break; } if (relation->rd_pubdesc) @@ -6172,6 +6269,8 @@ load_relcache_init_file(bool shared) goto read_failed; has_not_null |= attr->attnotnull; + + populate_compact_attribute(rel->rd_att, i); } /* next read the access method specific field */ @@ -6800,10 +6899,10 @@ RelationCacheInitFilePostInvalidate(void) void RelationCacheInitFileRemove(void) { - const char *tblspcdir = "pg_tblspc"; + const char *tblspcdir = PG_TBLSPC_DIR; DIR *dir; struct dirent *de; - char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)]; + char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)]; snprintf(path, sizeof(path), "global/%s", RELCACHE_INIT_FILENAME); diff --git a/src/backend/utils/cache/relfilenumbermap.c b/src/backend/utils/cache/relfilenumbermap.c index 9e76f74529713..8a2f6f8c69318 100644 --- a/src/backend/utils/cache/relfilenumbermap.c +++ b/src/backend/utils/cache/relfilenumbermap.c @@ -3,7 +3,7 @@ * relfilenumbermap.c * relfilenumber to oid mapping cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -141,7 +141,6 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber) SysScanDesc scandesc; Relation relation; HeapTuple ntp; - ScanKeyData skey[2]; Oid relid; if (RelfilenumberMapHash == NULL) @@ -181,6 +180,8 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber) } else { + ScanKeyData skey[2]; + /* * Not a shared table, could either be a plain relation or a * non-shared, nailed one, like e.g. pg_class. @@ -189,10 +190,8 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber) /* check for plain relations by looking in pg_class */ relation = table_open(RelationRelationId, AccessShareLock); - /* copy scankey to local copy, it will be modified during the scan */ + /* copy scankey to local copy and set scan arguments */ memcpy(skey, relfilenumber_skey, sizeof(skey)); - - /* set scan arguments */ skey[0].sk_argument = ObjectIdGetDatum(reltablespace); skey[1].sk_argument = ObjectIdGetDatum(relfilenumber); diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index 48d344ae3ff82..abf89f0776e99 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -28,7 +28,7 @@ * all these files commit in a single map file update rather than being tied * to transaction commit. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -854,7 +854,7 @@ read_relmap_file(RelMapFile *map, char *dbpath, bool lock_held, int elevel) /* verify the CRC */ INIT_CRC32C(crc); - COMP_CRC32C(crc, (char *) map, offsetof(RelMapFile, crc)); + COMP_CRC32C(crc, map, offsetof(RelMapFile, crc)); FIN_CRC32C(crc); if (!EQ_CRC32C(crc, map->crc)) @@ -910,7 +910,7 @@ write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval, elog(ERROR, "attempt to write bogus relation mapping"); INIT_CRC32C(newmap->crc); - COMP_CRC32C(newmap->crc, (char *) newmap, offsetof(RelMapFile, crc)); + COMP_CRC32C(newmap->crc, newmap, offsetof(RelMapFile, crc)); FIN_CRC32C(newmap->crc); /* @@ -969,8 +969,8 @@ write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval, xlrec.nbytes = sizeof(RelMapFile); XLogBeginInsert(); - XLogRegisterData((char *) (&xlrec), MinSizeOfRelmapUpdate); - XLogRegisterData((char *) newmap, sizeof(RelMapFile)); + XLogRegisterData(&xlrec, MinSizeOfRelmapUpdate); + XLogRegisterData(newmap, sizeof(RelMapFile)); lsn = XLogInsert(RM_RELMAP_ID, XLOG_RELMAP_UPDATE); diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c index ec63cdc8e52a6..2345859929833 100644 --- a/src/backend/utils/cache/spccache.c +++ b/src/backend/utils/cache/spccache.c @@ -8,7 +8,7 @@ * be a measurable performance gain from doing this, but that might change * in the future as we add more options. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 3e03dfc9910e3..f944453a1d884 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -3,7 +3,7 @@ * syscache.c * System cache management routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -30,7 +30,10 @@ #include "catalog/pg_shseclabel_d.h" #include "common/int.h" #include "lib/qunique.h" +#include "miscadmin.h" +#include "storage/lmgr.h" #include "utils/catcache.h" +#include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -268,6 +271,102 @@ ReleaseSysCache(HeapTuple tuple) ReleaseCatCache(tuple); } +/* + * SearchSysCacheLocked1 + * + * Combine SearchSysCache1() with acquiring a LOCKTAG_TUPLE at mode + * InplaceUpdateTupleLock. This is a tool for complying with the + * README.tuplock section "Locking to write inplace-updated tables". After + * the caller's heap_update(), it should UnlockTuple(InplaceUpdateTupleLock) + * and ReleaseSysCache(). + * + * The returned tuple may be the subject of an uncommitted update, so this + * doesn't prevent the "tuple concurrently updated" error. + */ +HeapTuple +SearchSysCacheLocked1(int cacheId, + Datum key1) +{ + CatCache *cache = SysCache[cacheId]; + ItemPointerData tid; + LOCKTAG tag; + + /*---------- + * Since inplace updates may happen just before our LockTuple(), we must + * return content acquired after LockTuple() of the TID we return. If we + * just fetched twice instead of looping, the following sequence would + * defeat our locking: + * + * GRANT: SearchSysCache1() = TID (1,5) + * GRANT: LockTuple(pg_class, (1,5)) + * [no more inplace update of (1,5) until we release the lock] + * CLUSTER: SearchSysCache1() = TID (1,5) + * CLUSTER: heap_update() = TID (1,8) + * CLUSTER: COMMIT + * GRANT: SearchSysCache1() = TID (1,8) + * GRANT: return (1,8) from SearchSysCacheLocked1() + * VACUUM: SearchSysCache1() = TID (1,8) + * VACUUM: LockTuple(pg_class, (1,8)) # two TIDs now locked for one rel + * VACUUM: inplace update + * GRANT: heap_update() = (1,9) # lose inplace update + * + * In the happy case, this takes two fetches, one to determine the TID to + * lock and another to get the content and confirm the TID didn't change. + * + * This is valid even if the row gets updated to a new TID, the old TID + * becomes LP_UNUSED, and the row gets updated back to its old TID. We'd + * still hold the right LOCKTAG_TUPLE and a copy of the row captured after + * the LOCKTAG_TUPLE. + */ + ItemPointerSetInvalid(&tid); + for (;;) + { + HeapTuple tuple; + LOCKMODE lockmode = InplaceUpdateTupleLock; + + tuple = SearchSysCache1(cacheId, key1); + if (ItemPointerIsValid(&tid)) + { + if (!HeapTupleIsValid(tuple)) + { + LockRelease(&tag, lockmode, false); + return tuple; + } + if (ItemPointerEquals(&tid, &tuple->t_self)) + return tuple; + LockRelease(&tag, lockmode, false); + } + else if (!HeapTupleIsValid(tuple)) + return tuple; + + tid = tuple->t_self; + ReleaseSysCache(tuple); + + /* + * Do like LockTuple(rel, &tid, lockmode). While cc_relisshared won't + * change from one iteration to another, it may have been a temporary + * "false" until our first SearchSysCache1(). + */ + SET_LOCKTAG_TUPLE(tag, + cache->cc_relisshared ? InvalidOid : MyDatabaseId, + cache->cc_reloid, + ItemPointerGetBlockNumber(&tid), + ItemPointerGetOffsetNumber(&tid)); + (void) LockAcquire(&tag, lockmode, false, false); + + /* + * If an inplace update just finished, ensure we process the syscache + * inval. + * + * If a heap_update() call just released its LOCKTAG_TUPLE, we'll + * probably find the old tuple and reach "tuple concurrently updated". + * If that heap_update() aborts, our LOCKTAG_TUPLE blocks inplace + * updates while our caller works. + */ + AcceptInvalidationMessages(); + } +} + /* * SearchSysCacheCopy * @@ -294,6 +393,28 @@ SearchSysCacheCopy(int cacheId, return newtuple; } +/* + * SearchSysCacheLockedCopy1 + * + * Meld SearchSysCacheLocked1 with SearchSysCacheCopy(). After the + * caller's heap_update(), it should UnlockTuple(InplaceUpdateTupleLock) and + * heap_freetuple(). + */ +HeapTuple +SearchSysCacheLockedCopy1(int cacheId, + Datum key1) +{ + HeapTuple tuple, + newtuple; + + tuple = SearchSysCacheLocked1(cacheId, key1); + if (!HeapTupleIsValid(tuple)) + return tuple; + newtuple = heap_copytuple(tuple); + ReleaseSysCache(tuple); + return newtuple; +} + /* * SearchSysCacheExists * diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c index 54de33eadd27f..18cccd778fd8c 100644 --- a/src/backend/utils/cache/ts_cache.c +++ b/src/backend/utils/cache/ts_cache.c @@ -17,7 +17,7 @@ * any database access. * * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/cache/ts_cache.c diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index aa4720cb5985c..f9aec38a11fb3 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -31,7 +31,7 @@ * constraint changes are also tracked properly. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -66,6 +66,7 @@ #include "utils/builtins.h" #include "utils/catcache.h" #include "utils/fmgroids.h" +#include "utils/injection_point.h" #include "utils/inval.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -77,6 +78,20 @@ /* The main type cache hashtable searched by lookup_type_cache */ static HTAB *TypeCacheHash = NULL; +/* + * The mapping of relation's OID to the corresponding composite type OID. + * We're keeping the map entry when the corresponding typentry has something + * to clear i.e it has either TCFLAGS_HAVE_PG_TYPE_DATA, or + * TCFLAGS_OPERATOR_FLAGS, or tupdesc. + */ +static HTAB *RelIdToTypeIdCacheHash = NULL; + +typedef struct RelIdToTypeIdCacheEntry +{ + Oid relid; /* OID of the relation */ + Oid composite_typid; /* OID of the relation's composite type */ +} RelIdToTypeIdCacheEntry; + /* List of type cache entries for domain types */ static TypeCacheEntry *firstDomainTypeEntry = NULL; @@ -208,6 +223,10 @@ typedef struct SharedTypmodTableEntry dsa_pointer shared_tupdesc; } SharedTypmodTableEntry; +static Oid *in_progress_list; +static int in_progress_list_len; +static int in_progress_list_maxlen; + /* * A comparator function for SharedRecordTableKey. */ @@ -329,8 +348,20 @@ static void shared_record_typmod_registry_detach(dsm_segment *segment, static TupleDesc find_or_make_matching_shared_tupledesc(TupleDesc tupdesc); static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, uint32 typmod); +static void insert_rel_type_cache_if_needed(TypeCacheEntry *typentry); +static void delete_rel_type_cache_if_needed(TypeCacheEntry *typentry); +/* + * Hash function compatible with one-arg system cache hash function. + */ +static uint32 +type_cache_syshash(const void *key, Size keysize) +{ + Assert(keysize == sizeof(Oid)); + return GetSysCacheHashValue1(TYPEOID, ObjectIdGetDatum(*(const Oid *) key)); +} + /* * lookup_type_cache * @@ -341,22 +372,48 @@ static dsa_pointer share_tupledesc(dsa_area *area, TupleDesc tupdesc, * invalid. Note however that we may fail to find one or more of the * values requested by 'flags'; the caller needs to check whether the fields * are InvalidOid or not. + * + * Note that while filling TypeCacheEntry we might process concurrent + * invalidation messages, causing our not-yet-filled TypeCacheEntry to be + * invalidated. In this case, we typically only clear flags while values are + * still available for the caller. It's expected that the caller holds + * enough locks on type-depending objects that the values are still relevant. + * It's also important that the tupdesc is filled after all other + * TypeCacheEntry items for TYPTYPE_COMPOSITE. So, tupdesc can't get + * invalidated during the lookup_type_cache() call. */ TypeCacheEntry * lookup_type_cache(Oid type_id, int flags) { TypeCacheEntry *typentry; bool found; + int in_progress_offset; if (TypeCacheHash == NULL) { /* First time through: initialize the hash table */ HASHCTL ctl; + int allocsize; ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(TypeCacheEntry); + + /* + * TypeCacheEntry takes hash value from the system cache. For + * TypeCacheHash we use the same hash in order to speedup search by + * hash value. This is used by hash_seq_init_with_hash_value(). + */ + ctl.hash = type_cache_syshash; + TypeCacheHash = hash_create("Type information cache", 64, - &ctl, HASH_ELEM | HASH_BLOBS); + &ctl, HASH_ELEM | HASH_FUNCTION); + + Assert(RelIdToTypeIdCacheHash == NULL); + + ctl.keysize = sizeof(Oid); + ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry); + RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64, + &ctl, HASH_ELEM | HASH_BLOBS); /* Also set up callbacks for SI invalidations */ CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0); @@ -367,7 +424,31 @@ lookup_type_cache(Oid type_id, int flags) /* Also make sure CacheMemoryContext exists */ if (!CacheMemoryContext) CreateCacheMemoryContext(); + + /* + * reserve enough in_progress_list slots for many cases + */ + allocsize = 4; + in_progress_list = + MemoryContextAlloc(CacheMemoryContext, + allocsize * sizeof(*in_progress_list)); + in_progress_list_maxlen = allocsize; + } + + Assert(TypeCacheHash != NULL && RelIdToTypeIdCacheHash != NULL); + + /* Register to catch invalidation messages */ + if (in_progress_list_len >= in_progress_list_maxlen) + { + int allocsize; + + allocsize = in_progress_list_maxlen * 2; + in_progress_list = repalloc(in_progress_list, + allocsize * sizeof(*in_progress_list)); + in_progress_list_maxlen = allocsize; } + in_progress_offset = in_progress_list_len++; + in_progress_list[in_progress_offset] = type_id; /* Try to look up an existing entry */ typentry = (TypeCacheEntry *) hash_search(TypeCacheHash, @@ -407,8 +488,7 @@ lookup_type_cache(Oid type_id, int flags) /* These fields can never change, by definition */ typentry->type_id = type_id; - typentry->type_id_hash = GetSysCacheHashValue1(TYPEOID, - ObjectIdGetDatum(type_id)); + typentry->type_id_hash = get_hash_value(TypeCacheHash, &type_id); /* Keep this part in sync with the code below */ typentry->typlen = typtup->typlen; @@ -419,6 +499,7 @@ lookup_type_cache(Oid type_id, int flags) typentry->typrelid = typtup->typrelid; typentry->typsubscript = typtup->typsubscript; typentry->typelem = typtup->typelem; + typentry->typarray = typtup->typarray; typentry->typcollation = typtup->typcollation; typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA; @@ -464,6 +545,7 @@ lookup_type_cache(Oid type_id, int flags) typentry->typrelid = typtup->typrelid; typentry->typsubscript = typtup->typsubscript; typentry->typelem = typtup->typelem; + typentry->typarray = typtup->typarray; typentry->typcollation = typtup->typcollation; typentry->flags |= TCFLAGS_HAVE_PG_TYPE_DATA; @@ -870,6 +952,13 @@ lookup_type_cache(Oid type_id, int flags) load_domaintype_info(typentry); } + INJECTION_POINT("typecache-before-rel-type-cache-insert", NULL); + + Assert(in_progress_offset + 1 == in_progress_list_len); + in_progress_list_len--; + + insert_rel_type_cache_if_needed(typentry); + return typentry; } @@ -1320,7 +1409,7 @@ InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref, ref->refctx = refctx; ref->dcc = NULL; ref->callback.func = dccref_deletion_callback; - ref->callback.arg = (void *) ref; + ref->callback.arg = ref; MemoryContextRegisterResetCallback(refctx, &ref->callback); /* Acquire refcount if there are constraints, and set up exported list */ if (ref->tcache->domainData) @@ -2264,6 +2353,56 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry) CurrentSession->shared_typmod_table = typmod_table; } +/* + * InvalidateCompositeTypeCacheEntry + * Invalidate particular TypeCacheEntry on Relcache inval callback + * + * Delete the cached tuple descriptor (if any) for the given composite + * type, and reset whatever info we have cached about the composite type's + * comparability. + */ +static void +InvalidateCompositeTypeCacheEntry(TypeCacheEntry *typentry) +{ + bool hadTupDescOrOpclass; + + Assert(typentry->typtype == TYPTYPE_COMPOSITE && + OidIsValid(typentry->typrelid)); + + hadTupDescOrOpclass = (typentry->tupDesc != NULL) || + (typentry->flags & TCFLAGS_OPERATOR_FLAGS); + + /* Delete tupdesc if we have it */ + if (typentry->tupDesc != NULL) + { + /* + * Release our refcount and free the tupdesc if none remain. We can't + * use DecrTupleDescRefCount here because this reference is not logged + * by the current resource owner. + */ + Assert(typentry->tupDesc->tdrefcount > 0); + if (--typentry->tupDesc->tdrefcount == 0) + FreeTupleDesc(typentry->tupDesc); + typentry->tupDesc = NULL; + + /* + * Also clear tupDesc_identifier, so that anyone watching it will + * realize that the tupdesc has changed. + */ + typentry->tupDesc_identifier = 0; + } + + /* Reset equality/comparison/hashing validity information */ + typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS; + + /* + * Call delete_rel_type_cache_if_needed() if we actually cleared + * something. + */ + if (hadTupDescOrOpclass) + delete_rel_type_cache_if_needed(typentry); +} + /* * TypeCacheRelCallback * Relcache inval callback function @@ -2273,63 +2412,55 @@ SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *registry) * whatever info we have cached about the composite type's comparability. * * This is called when a relcache invalidation event occurs for the given - * relid. We must scan the whole typcache hash since we don't know the - * type OID corresponding to the relid. We could do a direct search if this - * were a syscache-flush callback on pg_type, but then we would need all - * ALTER-TABLE-like commands that could modify a rowtype to issue syscache - * invals against the rel's pg_type OID. The extra SI signaling could very - * well cost more than we'd save, since in most usages there are not very - * many entries in a backend's typcache. The risk of bugs-of-omission seems - * high, too. - * - * Another possibility, with only localized impact, is to maintain a second - * hashtable that indexes composite-type typcache entries by their typrelid. - * But it's still not clear it's worth the trouble. + * relid. We can't use syscache to find a type corresponding to the given + * relation because the code can be called outside of transaction. Thus, we + * use the RelIdToTypeIdCacheHash map to locate appropriate typcache entry. */ static void TypeCacheRelCallback(Datum arg, Oid relid) { - HASH_SEQ_STATUS status; TypeCacheEntry *typentry; - /* TypeCacheHash must exist, else this callback wouldn't be registered */ - hash_seq_init(&status, TypeCacheHash); - while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL) + /* + * RelIdToTypeIdCacheHash and TypeCacheHash should exist, otherwise this + * callback wouldn't be registered + */ + if (OidIsValid(relid)) { - if (typentry->typtype == TYPTYPE_COMPOSITE) + RelIdToTypeIdCacheEntry *relentry; + + /* + * Find an RelIdToTypeIdCacheHash entry, which should exist as soon as + * corresponding typcache entry has something to clean. + */ + relentry = (RelIdToTypeIdCacheEntry *) hash_search(RelIdToTypeIdCacheHash, + &relid, + HASH_FIND, NULL); + + if (relentry != NULL) { - /* Skip if no match, unless we're zapping all composite types */ - if (relid != typentry->typrelid && relid != InvalidOid) - continue; + typentry = (TypeCacheEntry *) hash_search(TypeCacheHash, + &relentry->composite_typid, + HASH_FIND, NULL); - /* Delete tupdesc if we have it */ - if (typentry->tupDesc != NULL) + if (typentry != NULL) { - /* - * Release our refcount, and free the tupdesc if none remain. - * (Can't use DecrTupleDescRefCount because this reference is - * not logged in current resource owner.) - */ - Assert(typentry->tupDesc->tdrefcount > 0); - if (--typentry->tupDesc->tdrefcount == 0) - FreeTupleDesc(typentry->tupDesc); - typentry->tupDesc = NULL; + Assert(typentry->typtype == TYPTYPE_COMPOSITE); + Assert(relid == typentry->typrelid); - /* - * Also clear tupDesc_identifier, so that anything watching - * that will realize that the tupdesc has possibly changed. - * (Alternatively, we could specify that to detect possible - * tupdesc change, one must check for tupDesc != NULL as well - * as tupDesc_identifier being the same as what was previously - * seen. That seems error-prone.) - */ - typentry->tupDesc_identifier = 0; + InvalidateCompositeTypeCacheEntry(typentry); } - - /* Reset equality/comparison/hashing validity information */ - typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS; } - else if (typentry->typtype == TYPTYPE_DOMAIN) + + /* + * Visit all the domain types sequentially. Typically, this shouldn't + * affect performance since domain types are less tended to bloat. + * Domain types are created manually, unlike composite types which are + * automatically created for every temporary table. + */ + for (typentry = firstDomainTypeEntry; + typentry != NULL; + typentry = typentry->nextDomain) { /* * If it's domain over composite, reset flags. (We don't bother @@ -2341,6 +2472,36 @@ TypeCacheRelCallback(Datum arg, Oid relid) typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS; } } + else + { + HASH_SEQ_STATUS status; + + /* + * Relid is invalid. By convention, we need to reset all composite + * types in cache. Also, we should reset flags for domain types, and + * we loop over all entries in hash, so, do it in a single scan. + */ + hash_seq_init(&status, TypeCacheHash); + while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL) + { + if (typentry->typtype == TYPTYPE_COMPOSITE) + { + InvalidateCompositeTypeCacheEntry(typentry); + } + else if (typentry->typtype == TYPTYPE_DOMAIN) + { + /* + * If it's domain over composite, reset flags. (We don't + * bother trying to determine whether the specific base type + * needs a reset.) Note that if we haven't determined whether + * the base type is composite, we don't need to reset + * anything. + */ + if (typentry->flags & TCFLAGS_DOMAIN_BASE_IS_COMPOSITE) + typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS; + } + } + } } /* @@ -2358,20 +2519,37 @@ TypeCacheTypCallback(Datum arg, int cacheid, uint32 hashvalue) TypeCacheEntry *typentry; /* TypeCacheHash must exist, else this callback wouldn't be registered */ - hash_seq_init(&status, TypeCacheHash); + + /* + * By convention, zero hash value is passed to the callback as a sign that + * it's time to invalidate the whole cache. See sinval.c, inval.c and + * InvalidateSystemCachesExtended(). + */ + if (hashvalue == 0) + hash_seq_init(&status, TypeCacheHash); + else + hash_seq_init_with_hash_value(&status, TypeCacheHash, hashvalue); + while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL) { - /* Is this the targeted type row (or it's a total cache flush)? */ - if (hashvalue == 0 || typentry->type_id_hash == hashvalue) - { - /* - * Mark the data obtained directly from pg_type as invalid. Also, - * if it's a domain, typnotnull might've changed, so we'll need to - * recalculate its constraints. - */ - typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA | - TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS); - } + bool hadPgTypeData = (typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA); + + Assert(hashvalue == 0 || typentry->type_id_hash == hashvalue); + + /* + * Mark the data obtained directly from pg_type as invalid. Also, if + * it's a domain, typnotnull might've changed, so we'll need to + * recalculate its constraints. + */ + typentry->flags &= ~(TCFLAGS_HAVE_PG_TYPE_DATA | + TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS); + + /* + * Call delete_rel_type_cache_if_needed() if we cleaned + * TCFLAGS_HAVE_PG_TYPE_DATA flag previously. + */ + if (hadPgTypeData) + delete_rel_type_cache_if_needed(typentry); } } @@ -2401,8 +2579,17 @@ TypeCacheOpcCallback(Datum arg, int cacheid, uint32 hashvalue) hash_seq_init(&status, TypeCacheHash); while ((typentry = (TypeCacheEntry *) hash_seq_search(&status)) != NULL) { + bool hadOpclass = (typentry->flags & TCFLAGS_OPERATOR_FLAGS); + /* Reset equality/comparison/hashing validity information */ typentry->flags &= ~TCFLAGS_OPERATOR_FLAGS; + + /* + * Call delete_rel_type_cache_if_needed() if we actually cleared some + * of TCFLAGS_OPERATOR_FLAGS. + */ + if (hadOpclass) + delete_rel_type_cache_if_needed(typentry); } } @@ -2880,3 +3067,135 @@ shared_record_typmod_registry_detach(dsm_segment *segment, Datum datum) } CurrentSession->shared_typmod_registry = NULL; } + +/* + * Insert RelIdToTypeIdCacheHash entry if needed. + */ +static void +insert_rel_type_cache_if_needed(TypeCacheEntry *typentry) +{ + /* Immediately quit for non-composite types */ + if (typentry->typtype != TYPTYPE_COMPOSITE) + return; + + /* typrelid should be given for composite types */ + Assert(OidIsValid(typentry->typrelid)); + + /* + * Insert a RelIdToTypeIdCacheHash entry if the typentry have any + * information indicating it should be here. + */ + if ((typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA) || + (typentry->flags & TCFLAGS_OPERATOR_FLAGS) || + typentry->tupDesc != NULL) + { + RelIdToTypeIdCacheEntry *relentry; + bool found; + + relentry = (RelIdToTypeIdCacheEntry *) hash_search(RelIdToTypeIdCacheHash, + &typentry->typrelid, + HASH_ENTER, &found); + relentry->relid = typentry->typrelid; + relentry->composite_typid = typentry->type_id; + } +} + +/* + * Delete entry RelIdToTypeIdCacheHash if needed after resetting of the + * TCFLAGS_HAVE_PG_TYPE_DATA flag, or any of TCFLAGS_OPERATOR_FLAGS, + * or tupDesc. + */ +static void +delete_rel_type_cache_if_needed(TypeCacheEntry *typentry) +{ +#ifdef USE_ASSERT_CHECKING + int i; + bool is_in_progress = false; + + for (i = 0; i < in_progress_list_len; i++) + { + if (in_progress_list[i] == typentry->type_id) + { + is_in_progress = true; + break; + } + } +#endif + + /* Immediately quit for non-composite types */ + if (typentry->typtype != TYPTYPE_COMPOSITE) + return; + + /* typrelid should be given for composite types */ + Assert(OidIsValid(typentry->typrelid)); + + /* + * Delete a RelIdToTypeIdCacheHash entry if the typentry doesn't have any + * information indicating entry should be still there. + */ + if (!(typentry->flags & TCFLAGS_HAVE_PG_TYPE_DATA) && + !(typentry->flags & TCFLAGS_OPERATOR_FLAGS) && + typentry->tupDesc == NULL) + { + bool found; + + (void) hash_search(RelIdToTypeIdCacheHash, + &typentry->typrelid, + HASH_REMOVE, &found); + Assert(found || is_in_progress); + } + else + { +#ifdef USE_ASSERT_CHECKING + /* + * In assert-enabled builds otherwise check for RelIdToTypeIdCacheHash + * entry if it should exist. + */ + bool found; + + if (!is_in_progress) + { + (void) hash_search(RelIdToTypeIdCacheHash, + &typentry->typrelid, + HASH_FIND, &found); + Assert(found); + } +#endif + } +} + +/* + * Add possibly missing RelIdToTypeId entries related to TypeCacheHash + * entries, marked as in-progress by lookup_type_cache(). It may happen + * in case of an error or interruption during the lookup_type_cache() call. + */ +static void +finalize_in_progress_typentries(void) +{ + int i; + + for (i = 0; i < in_progress_list_len; i++) + { + TypeCacheEntry *typentry; + + typentry = (TypeCacheEntry *) hash_search(TypeCacheHash, + &in_progress_list[i], + HASH_FIND, NULL); + if (typentry) + insert_rel_type_cache_if_needed(typentry); + } + + in_progress_list_len = 0; +} + +void +AtEOXact_TypeCache(void) +{ + finalize_in_progress_typentries(); +} + +void +AtEOSubXact_TypeCache(void) +{ + finalize_in_progress_typentries(); +} diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt index b43a24d4bcdb9..c96aa7c49efeb 100644 --- a/src/backend/utils/errcodes.txt +++ b/src/backend/utils/errcodes.txt @@ -2,7 +2,7 @@ # errcodes.txt # PostgreSQL error codes # -# Copyright (c) 2003-2024, PostgreSQL Global Development Group +# Copyright (c) 2003-2025, PostgreSQL Global Development Group # # This list serves as the basis for generating source files containing error # codes. It is kept in a common format to make sure all these source files have @@ -141,6 +141,12 @@ Section: Class 0Z - Diagnostics Exception 0Z000 E ERRCODE_DIAGNOSTICS_EXCEPTION diagnostics_exception 0Z002 E ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER stacked_diagnostics_accessed_without_active_handler +Section: Class 10 - XQuery Error + +# recent SQL versions define quite a few codes in this class, but for now +# we are only using this generic one +10608 E ERRCODE_INVALID_ARGUMENT_FOR_XQUERY invalid_argument_for_xquery + Section: Class 20 - Case Not Found 20000 E ERRCODE_CASE_NOT_FOUND case_not_found diff --git a/src/backend/utils/error/assert.c b/src/backend/utils/error/assert.c index d312ba032e3a0..84b94f5e5f472 100644 --- a/src/backend/utils/error/assert.c +++ b/src/backend/utils/error/assert.c @@ -3,7 +3,7 @@ * assert.c * Assert support code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/error/csvlog.c b/src/backend/utils/error/csvlog.c index 855e130a97dbb..fdac3c048e36a 100644 --- a/src/backend/utils/error/csvlog.c +++ b/src/backend/utils/error/csvlog.c @@ -3,7 +3,7 @@ * csvlog.c * CSV logging * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -120,7 +120,7 @@ write_csvlog(ErrorData *edata) appendStringInfoChar(&buf, ','); /* session id */ - appendStringInfo(&buf, "%lx.%x", (long) MyStartTime, MyProcPid); + appendStringInfo(&buf, INT64_HEX_FORMAT ".%x", MyStartTime, MyProcPid); appendStringInfoChar(&buf, ','); /* Line number */ @@ -248,7 +248,7 @@ write_csvlog(ErrorData *edata) appendStringInfoChar(&buf, ','); /* query id */ - appendStringInfo(&buf, "%lld", (long long) pgstat_get_my_query_id()); + appendStringInfo(&buf, "%" PRId64, pgstat_get_my_query_id()); appendStringInfoChar(&buf, '\n'); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 943d8588f3d64..47af743990fe9 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -43,7 +43,7 @@ * overflow.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -67,6 +67,7 @@ #endif #include "access/xact.h" +#include "common/ip.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" #include "mb/pg_wchar.h" @@ -1330,6 +1331,27 @@ errhint(const char *fmt,...) return 0; /* return value does not matter */ } +/* + * errhint_internal --- add a hint error message text to the current error + * + * Non-translated version of errhint(), see also errmsg_internal(). + */ +int +errhint_internal(const char *fmt,...) +{ + ErrorData *edata = &errordata[errordata_stack_depth]; + MemoryContext oldcontext; + + recursion_depth++; + CHECK_STACK_DEPTH(); + oldcontext = MemoryContextSwitchTo(edata->assoc_context); + + EVALUATE_MESSAGE(edata->domain, hint, false, false); + + MemoryContextSwitchTo(oldcontext); + recursion_depth--; + return 0; /* return value does not matter */ +} /* * errhint_plural --- add a hint error message text to the current error, @@ -1864,12 +1886,15 @@ FlushErrorState(void) /* * ThrowErrorData --- report an error described by an ErrorData structure * - * This is somewhat like ReThrowError, but it allows elevels besides ERROR, - * and the boolean flags such as output_to_server are computed via the - * default rules rather than being copied from the given ErrorData. - * This is primarily used to re-report errors originally reported by - * background worker processes and then propagated (with or without - * modification) to the backend responsible for them. + * This function should be called on an ErrorData structure that isn't stored + * on the errordata stack and hasn't been processed yet. It will call + * errstart() and errfinish() as needed, so those should not have already been + * called. + * + * ThrowErrorData() is useful for handling soft errors. It's also useful for + * re-reporting errors originally reported by background worker processes and + * then propagated (with or without modification) to the backend responsible + * for them. */ void ThrowErrorData(ErrorData *edata) @@ -2163,7 +2188,7 @@ check_backtrace_functions(char **newval, void **extra, GucSource source) ", \n\t"); if (validlen != newvallen) { - GUC_check_errdetail("Invalid character"); + GUC_check_errdetail("Invalid character."); return false; } @@ -2178,7 +2203,9 @@ check_backtrace_functions(char **newval, void **extra, GucSource source) * whitespace chars to save some memory, but it doesn't seem worth the * trouble. */ - someval = guc_malloc(ERROR, newvallen + 1 + 1); + someval = guc_malloc(LOG, newvallen + 1 + 1); + if (!someval) + return false; for (i = 0, j = 0; i < newvallen; i++) { if ((*newval)[i] == ',') @@ -2263,9 +2290,11 @@ check_log_destination(char **newval, void **extra, GucSource source) pfree(rawstring); list_free(elemlist); - myextra = (int *) guc_malloc(ERROR, sizeof(int)); + myextra = (int *) guc_malloc(LOG, sizeof(int)); + if (!myextra) + return false; *myextra = newlogdest; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -2927,12 +2956,12 @@ log_status_format(StringInfo buf, const char *format, ErrorData *edata) { char strfbuf[128]; - snprintf(strfbuf, sizeof(strfbuf) - 1, "%lx.%x", - (long) (MyStartTime), MyProcPid); + snprintf(strfbuf, sizeof(strfbuf) - 1, INT64_HEX_FORMAT ".%x", + MyStartTime, MyProcPid); appendStringInfo(buf, "%*s", padding, strfbuf); } else - appendStringInfo(buf, "%lx.%x", (long) (MyStartTime), MyProcPid); + appendStringInfo(buf, INT64_HEX_FORMAT ".%x", MyStartTime, MyProcPid); break; case 'p': if (padding != 0) @@ -3039,6 +3068,38 @@ log_status_format(StringInfo buf, const char *format, ErrorData *edata) appendStringInfoSpaces(buf, padding > 0 ? padding : -padding); break; + case 'L': + { + const char *local_host; + + if (MyProcPort) + { + if (MyProcPort->local_host[0] == '\0') + { + /* + * First time through: cache the lookup, since it + * might not have trivial cost. + */ + (void) pg_getnameinfo_all(&MyProcPort->laddr.addr, + MyProcPort->laddr.salen, + MyProcPort->local_host, + sizeof(MyProcPort->local_host), + NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + } + local_host = MyProcPort->local_host; + } + else + { + /* Background process, or connection not yet made */ + local_host = "[none]"; + } + if (padding != 0) + appendStringInfo(buf, "%*s", padding, local_host); + else + appendStringInfoString(buf, local_host); + } + break; case 'r': if (MyProcPort && MyProcPort->remote_host) { @@ -3128,11 +3189,11 @@ log_status_format(StringInfo buf, const char *format, ErrorData *edata) break; case 'Q': if (padding != 0) - appendStringInfo(buf, "%*lld", padding, - (long long) pgstat_get_my_query_id()); + appendStringInfo(buf, "%*" PRId64, padding, + pgstat_get_my_query_id()); else - appendStringInfo(buf, "%lld", - (long long) pgstat_get_my_query_id()); + appendStringInfo(buf, "%" PRId64, + pgstat_get_my_query_id()); break; default: /* format error - ignore it */ diff --git a/src/backend/utils/error/jsonlog.c b/src/backend/utils/error/jsonlog.c index bd0124869d5e0..519eacf17f83c 100644 --- a/src/backend/utils/error/jsonlog.c +++ b/src/backend/utils/error/jsonlog.c @@ -3,7 +3,7 @@ * jsonlog.c * JSON logging * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -168,8 +168,8 @@ write_jsonlog(ErrorData *edata) } /* Session id */ - appendJSONKeyValueFmt(&buf, "session_id", true, "%lx.%x", - (long) MyStartTime, MyProcPid); + appendJSONKeyValueFmt(&buf, "session_id", true, INT64_HEX_FORMAT ".%x", + MyStartTime, MyProcPid); /* Line number */ appendJSONKeyValueFmt(&buf, "line_num", false, "%ld", log_line_number); @@ -206,7 +206,7 @@ write_jsonlog(ErrorData *edata) /* Error severity */ if (edata->elevel) appendJSONKeyValue(&buf, "error_severity", - (char *) error_severity(edata->elevel), true); + error_severity(edata->elevel), true); /* SQL state code */ if (edata->sqlerrcode) @@ -284,8 +284,8 @@ write_jsonlog(ErrorData *edata) } /* query id */ - appendJSONKeyValueFmt(&buf, "query_id", false, "%lld", - (long long) pgstat_get_my_query_id()); + appendJSONKeyValueFmt(&buf, "query_id", false, "%" PRId64, + pgstat_get_my_query_id()); /* Finish string */ appendStringInfoChar(&buf, '}'); diff --git a/src/backend/utils/error/meson.build b/src/backend/utils/error/meson.build index 1079d1de5483c..15a502bb6bec2 100644 --- a/src/backend/utils/error/meson.build +++ b/src/backend/utils/error/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'assert.c', diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 092004dcf3b3f..4bb84ff70870f 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -3,7 +3,7 @@ * dfmgr.c * Dynamic function manager code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -18,16 +18,6 @@ #ifndef WIN32 #include - -/* - * On macOS, insists on including . If we're not - * using stdbool, undef bool to undo the damage. - */ -#ifndef PG_USE_STDBOOL -#ifdef bool -#undef bool -#endif -#endif #endif /* !WIN32 */ #include "fmgr.h" @@ -50,19 +40,21 @@ typedef struct /* * List of dynamically loaded files (kept in malloc'd memory). + * + * Note: "typedef struct DynamicFileList DynamicFileList" appears in fmgr.h. */ - -typedef struct df_files +struct DynamicFileList { - struct df_files *next; /* List link */ + DynamicFileList *next; /* List link */ dev_t device; /* Device file is on */ #ifndef WIN32 /* ensures we never again depend on this under * win32 */ ino_t inode; /* Inode number of file */ #endif void *handle; /* a handle for pg_dl* functions */ + const Pg_magic_struct *magic; /* Location of module's magic block */ char filename[FLEXIBLE_ARRAY_MEMBER]; /* Full pathname of file */ -} DynamicFileList; +}; static DynamicFileList *file_list = NULL; static DynamicFileList *file_tail = NULL; @@ -77,15 +69,13 @@ static DynamicFileList *file_tail = NULL; char *Dynamic_library_path; static void *internal_load_library(const char *libname); -static void incompatible_module_error(const char *libname, - const Pg_magic_struct *module_magic_data) pg_attribute_noreturn(); +pg_noreturn static void incompatible_module_error(const char *libname, + const Pg_abi_values *module_magic_data); static char *expand_dynamic_library_name(const char *name); static void check_restricted_library_name(const char *name); -static char *substitute_libpath_macro(const char *name); -static char *find_in_dynamic_libpath(const char *basename); -/* Magic structure that module needs to match to be accepted */ -static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA; +/* ABI values that module needs to match to be accepted */ +static const Pg_abi_values magic_data = PG_MODULE_ABI_DATA; /* @@ -109,6 +99,14 @@ load_external_function(const char *filename, const char *funcname, void *lib_handle; void *retval; + /* + * If the value starts with "$libdir/", strip that. This is because many + * extensions have hardcoded '$libdir/foo' as their library name, which + * prevents using the path. + */ + if (strncmp(filename, "$libdir/", 8) == 0) + filename += 8; + /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); @@ -135,7 +133,7 @@ load_external_function(const char *filename, const char *funcname, /* * This function loads a shlib file without looking up any particular * function in it. If the same shlib has previously been loaded, - * unload and reload it. + * we do not load it again. * * When 'restricted' is true, only libraries in the presumed-secure * directory $libdir/plugins may be referenced. @@ -152,7 +150,7 @@ load_file(const char *filename, bool restricted) /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); - /* Load the shared library */ + /* Load the shared library, unless we already did */ (void) internal_load_library(fullname); pfree(fullname); @@ -255,8 +253,10 @@ internal_load_library(const char *libname) { const Pg_magic_struct *magic_data_ptr = (*magic_func) (); - if (magic_data_ptr->len != magic_data.len || - memcmp(magic_data_ptr, &magic_data, magic_data.len) != 0) + /* Check ABI compatibility fields */ + if (magic_data_ptr->len != sizeof(Pg_magic_struct) || + memcmp(&magic_data_ptr->abi_fields, &magic_data, + sizeof(Pg_abi_values)) != 0) { /* copy data block before unlinking library */ Pg_magic_struct module_magic_data = *magic_data_ptr; @@ -266,8 +266,11 @@ internal_load_library(const char *libname) free(file_scanner); /* issue suitable complaint */ - incompatible_module_error(libname, &module_magic_data); + incompatible_module_error(libname, &module_magic_data.abi_fields); } + + /* Remember the magic block's location for future use */ + file_scanner->magic = magic_data_ptr; } else { @@ -304,7 +307,7 @@ internal_load_library(const char *libname) */ static void incompatible_module_error(const char *libname, - const Pg_magic_struct *module_magic_data) + const Pg_abi_values *module_magic_data) { StringInfoData details; @@ -358,8 +361,9 @@ incompatible_module_error(const char *libname, if (details.len) appendStringInfoChar(&details, '\n'); appendStringInfo(&details, - _("Server has FUNC_MAX_ARGS = %d, library has %d."), - magic_data.funcmaxargs, + /* translator: %s is a variable name and %d its values */ + _("Server has %s = %d, library has %d."), + "FUNC_MAX_ARGS", magic_data.funcmaxargs, module_magic_data->funcmaxargs); } if (module_magic_data->indexmaxkeys != magic_data.indexmaxkeys) @@ -367,8 +371,9 @@ incompatible_module_error(const char *libname, if (details.len) appendStringInfoChar(&details, '\n'); appendStringInfo(&details, - _("Server has INDEX_MAX_KEYS = %d, library has %d."), - magic_data.indexmaxkeys, + /* translator: %s is a variable name and %d its values */ + _("Server has %s = %d, library has %d."), + "INDEX_MAX_KEYS", magic_data.indexmaxkeys, module_magic_data->indexmaxkeys); } if (module_magic_data->namedatalen != magic_data.namedatalen) @@ -376,8 +381,9 @@ incompatible_module_error(const char *libname, if (details.len) appendStringInfoChar(&details, '\n'); appendStringInfo(&details, - _("Server has NAMEDATALEN = %d, library has %d."), - magic_data.namedatalen, + /* translator: %s is a variable name and %d its values */ + _("Server has %s = %d, library has %d."), + "NAMEDATALEN", magic_data.namedatalen, module_magic_data->namedatalen); } if (module_magic_data->float8byval != magic_data.float8byval) @@ -385,8 +391,9 @@ incompatible_module_error(const char *libname, if (details.len) appendStringInfoChar(&details, '\n'); appendStringInfo(&details, - _("Server has FLOAT8PASSBYVAL = %s, library has %s."), - magic_data.float8byval ? "true" : "false", + /* translator: %s is a variable name and %d its values */ + _("Server has %s = %s, library has %s."), + "FLOAT8PASSBYVAL", magic_data.float8byval ? "true" : "false", module_magic_data->float8byval ? "true" : "false"); } @@ -401,10 +408,48 @@ incompatible_module_error(const char *libname, } +/* + * Iterator functions to allow callers to scan the list of loaded modules. + * + * Note: currently, there is no special provision for dealing with changes + * in the list while a scan is happening. Current callers don't need it. + */ +DynamicFileList * +get_first_loaded_module(void) +{ + return file_list; +} + +DynamicFileList * +get_next_loaded_module(DynamicFileList *dfptr) +{ + return dfptr->next; +} + +/* + * Return some details about the specified module. + * + * Note that module_name and module_version could be returned as NULL. + * + * We could dispense with this function by exposing struct DynamicFileList + * globally, but this way seems preferable. + */ +void +get_loaded_module_details(DynamicFileList *dfptr, + const char **library_path, + const char **module_name, + const char **module_version) +{ + *library_path = dfptr->filename; + *module_name = dfptr->magic->name; + *module_version = dfptr->magic->version; +} + + /* * If name contains a slash, check if the file exists, if so return * the name. Else (no slash) try to expand using search path (see - * find_in_dynamic_libpath below); if that works, return the fully + * find_in_path below); if that works, return the fully * expanded file name. If the previous failed, append DLSUFFIX and * try again. If all fails, just return the original name. * @@ -423,13 +468,13 @@ expand_dynamic_library_name(const char *name) if (!have_slash) { - full = find_in_dynamic_libpath(name); + full = find_in_path(name, Dynamic_library_path, "dynamic_library_path", "$libdir", pkglib_path); if (full) return full; } else { - full = substitute_libpath_macro(name); + full = substitute_path_macro(name, "$libdir", pkglib_path); if (pg_file_exists(full)) return full; pfree(full); @@ -439,14 +484,14 @@ expand_dynamic_library_name(const char *name) if (!have_slash) { - full = find_in_dynamic_libpath(new); + full = find_in_path(new, Dynamic_library_path, "dynamic_library_path", "$libdir", pkglib_path); pfree(new); if (full) return full; } else { - full = substitute_libpath_macro(new); + full = substitute_path_macro(new, "$libdir", pkglib_path); pfree(new); if (pg_file_exists(full)) return full; @@ -480,48 +525,61 @@ check_restricted_library_name(const char *name) * Substitute for any macros appearing in the given string. * Result is always freshly palloc'd. */ -static char * -substitute_libpath_macro(const char *name) +char * +substitute_path_macro(const char *str, const char *macro, const char *value) { const char *sep_ptr; - Assert(name != NULL); + Assert(str != NULL); + Assert(macro[0] == '$'); - /* Currently, we only recognize $libdir at the start of the string */ - if (name[0] != '$') - return pstrdup(name); + /* Currently, we only recognize $macro at the start of the string */ + if (str[0] != '$') + return pstrdup(str); - if ((sep_ptr = first_dir_separator(name)) == NULL) - sep_ptr = name + strlen(name); + if ((sep_ptr = first_dir_separator(str)) == NULL) + sep_ptr = str + strlen(str); - if (strlen("$libdir") != sep_ptr - name || - strncmp(name, "$libdir", strlen("$libdir")) != 0) + if (strlen(macro) != sep_ptr - str || + strncmp(str, macro, strlen(macro)) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), - errmsg("invalid macro name in dynamic library path: %s", - name))); + errmsg("invalid macro name in path: %s", + str))); - return psprintf("%s%s", pkglib_path, sep_ptr); + return psprintf("%s%s", value, sep_ptr); } /* * Search for a file called 'basename' in the colon-separated search - * path Dynamic_library_path. If the file is found, the full file name + * path given. If the file is found, the full file name * is returned in freshly palloc'd memory. If the file is not found, * return NULL. + * + * path_param is the name of the parameter that path came from, for error + * messages. + * + * macro and macro_val allow substituting a macro; see + * substitute_path_macro(). */ -static char * -find_in_dynamic_libpath(const char *basename) +char * +find_in_path(const char *basename, const char *path, const char *path_param, + const char *macro, const char *macro_val) { const char *p; size_t baselen; Assert(basename != NULL); Assert(first_dir_separator(basename) == NULL); - Assert(Dynamic_library_path != NULL); + Assert(path != NULL); + Assert(path_param != NULL); + + p = path; - p = Dynamic_library_path; + /* + * If the path variable is empty, don't do a path search. + */ if (strlen(p) == 0) return NULL; @@ -538,7 +596,7 @@ find_in_dynamic_libpath(const char *basename) if (piece == p) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), - errmsg("zero-length component in parameter \"dynamic_library_path\""))); + errmsg("zero-length component in parameter \"%s\"", path_param))); if (piece == NULL) len = strlen(p); @@ -548,7 +606,7 @@ find_in_dynamic_libpath(const char *basename) piece = palloc(len + 1); strlcpy(piece, p, len + 1); - mangled = substitute_libpath_macro(piece); + mangled = substitute_path_macro(piece, macro, macro_val); pfree(piece); canonicalize_path(mangled); @@ -557,13 +615,13 @@ find_in_dynamic_libpath(const char *basename) if (!is_absolute_path(mangled)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), - errmsg("component in parameter \"dynamic_library_path\" is not an absolute path"))); + errmsg("component in parameter \"%s\" is not an absolute path", path_param))); full = palloc(strlen(mangled) + 1 + baselen + 1); sprintf(full, "%s/%s", mangled, basename); pfree(mangled); - elog(DEBUG3, "find_in_dynamic_libpath: trying \"%s\"", full); + elog(DEBUG3, "%s: trying \"%s\"", __func__, full); if (pg_file_exists(full)) return full; diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index e48a86be54b0d..782291d999832 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -3,7 +3,7 @@ * fmgr.c * The Postgres function manager. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -639,7 +639,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS) ListCell *lc1, *lc2, *lc3; - volatile int save_nestlevel; + int save_nestlevel; PgStat_FunctionCallUsage fcusage; if (!fcinfo->flinfo->fn_extra) diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 05d763fa06e4c..5f2317211c9d4 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -4,7 +4,7 @@ * Utility and convenience functions for fmgr functions that return * sets and/or composite types, or deal with VARIADIC inputs. * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/fmgr/funcapi.c diff --git a/src/backend/utils/fmgr/meson.build b/src/backend/utils/fmgr/meson.build index 42afa9c4a848e..b1dcab93e7093 100644 --- a/src/backend/utils/fmgr/meson.build +++ b/src/backend/utils/fmgr/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'dfmgr.c', diff --git a/src/backend/utils/generate-errcodes.pl b/src/backend/utils/generate-errcodes.pl index 68fb2f3f28796..95dc365af1d28 100644 --- a/src/backend/utils/generate-errcodes.pl +++ b/src/backend/utils/generate-errcodes.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the errcodes.h header from errcodes.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c index 145e058fe675b..1ad155d446e51 100644 --- a/src/backend/utils/hash/dynahash.c +++ b/src/backend/utils/hash/dynahash.c @@ -52,7 +52,7 @@ * dynahash has better performance for large entries. * - Guarantees stable pointers to entries. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -272,7 +272,7 @@ static HASHBUCKET get_hash_entry(HTAB *hashp, int freelist_idx); static void hdefault(HTAB *hashp); static int choose_nelem_alloc(Size entrysize); static bool init_htab(HTAB *hashp, long nelem); -static void hash_corrupted(HTAB *hashp) pg_attribute_noreturn(); +pg_noreturn static void hash_corrupted(HTAB *hashp); static uint32 hash_initial_lookup(HTAB *hashp, uint32 hashvalue, HASHBUCKET **bucketptr); static long next_pow2_long(long num); @@ -390,7 +390,8 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags) } /* Initialize the hash header, plus a copy of the table name */ - hashp = (HTAB *) DynaHashAlloc(sizeof(HTAB) + strlen(tabname) + 1); + hashp = (HTAB *) MemoryContextAlloc(CurrentDynaHashCxt, + sizeof(HTAB) + strlen(tabname) + 1); MemSet(hashp, 0, sizeof(HTAB)); hashp->tabname = (char *) (hashp + 1); @@ -1038,7 +1039,7 @@ hash_search_with_hash_value(HTAB *hashp, { case HASH_FIND: if (currBucket != NULL) - return (void *) ELEMENTKEY(currBucket); + return ELEMENTKEY(currBucket); return NULL; case HASH_REMOVE: @@ -1067,7 +1068,7 @@ hash_search_with_hash_value(HTAB *hashp, * element, because someone else is going to reuse it the next * time something is added to the table */ - return (void *) ELEMENTKEY(currBucket); + return ELEMENTKEY(currBucket); } return NULL; @@ -1075,7 +1076,7 @@ hash_search_with_hash_value(HTAB *hashp, case HASH_ENTER_NULL: /* Return existing element if found, else create one */ if (currBucket != NULL) - return (void *) ELEMENTKEY(currBucket); + return ELEMENTKEY(currBucket); /* disallow inserts if frozen */ if (hashp->frozen) @@ -1114,7 +1115,7 @@ hash_search_with_hash_value(HTAB *hashp, * caller's data structure. */ - return (void *) ELEMENTKEY(currBucket); + return ELEMENTKEY(currBucket); } elog(ERROR, "unrecognized hash action code: %d", (int) action); @@ -1387,10 +1388,35 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp) status->hashp = hashp; status->curBucket = 0; status->curEntry = NULL; + status->hasHashvalue = false; if (!hashp->frozen) register_seq_scan(hashp); } +/* + * Same as above but scan by the given hash value. + * See also hash_seq_search(). + * + * NOTE: the default hash function doesn't match syscache hash function. + * Thus, if you're going to use this function in syscache callback, make sure + * you're using custom hash function. See relatt_cache_syshash() + * for example. + */ +void +hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status, HTAB *hashp, + uint32 hashvalue) +{ + HASHBUCKET *bucketPtr; + + hash_seq_init(status, hashp); + + status->hasHashvalue = true; + status->hashvalue = hashvalue; + + status->curBucket = hash_initial_lookup(hashp, hashvalue, &bucketPtr); + status->curEntry = *bucketPtr; +} + void * hash_seq_search(HASH_SEQ_STATUS *status) { @@ -1404,13 +1430,31 @@ hash_seq_search(HASH_SEQ_STATUS *status) uint32 curBucket; HASHELEMENT *curElem; + if (status->hasHashvalue) + { + /* + * Scan entries only in the current bucket because only this bucket + * can contain entries with the given hash value. + */ + while ((curElem = status->curEntry) != NULL) + { + status->curEntry = curElem->link; + if (status->hashvalue != curElem->hashvalue) + continue; + return (void *) ELEMENTKEY(curElem); + } + + hash_seq_term(status); + return NULL; + } + if ((curElem = status->curEntry) != NULL) { /* Continuing scan of curBucket... */ status->curEntry = curElem->link; if (status->curEntry == NULL) /* end of this bucket */ ++status->curBucket; - return (void *) ELEMENTKEY(curElem); + return ELEMENTKEY(curElem); } /* @@ -1464,7 +1508,7 @@ hash_seq_search(HASH_SEQ_STATUS *status) if (status->curEntry == NULL) /* end of this bucket */ ++curBucket; status->curBucket = curBucket; - return (void *) ELEMENTKEY(curElem); + return ELEMENTKEY(curElem); } void diff --git a/src/backend/utils/hash/meson.build b/src/backend/utils/hash/meson.build index 5fefb9aaedf27..f67efb4c6b78b 100644 --- a/src/backend/utils/hash/meson.build +++ b/src/backend/utils/hash/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'dynahash.c', diff --git a/src/backend/utils/hash/pg_crc.c b/src/backend/utils/hash/pg_crc.c index 3595938dc4fb2..e67a74ef85250 100644 --- a/src/backend/utils/hash/pg_crc.c +++ b/src/backend/utils/hash/pg_crc.c @@ -7,7 +7,7 @@ * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from * http://ross.net/crc/download/crc_v3.txt or several other net sites. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -17,9 +17,12 @@ *------------------------------------------------------------------------- */ -#include "c.h" +#include "postgres.h" +#include "port/pg_crc32c.h" +#include "utils/fmgrprotos.h" #include "utils/pg_crc.h" +#include "varatt.h" /* * Lookup table for calculating CRC-32 using Sarwate's algorithm. @@ -95,3 +98,33 @@ const uint32 pg_crc32_table[256] = { 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; + +/* + * SQL-callable functions + */ + +Datum +crc32_bytea(PG_FUNCTION_ARGS) +{ + bytea *in = PG_GETARG_BYTEA_PP(0); + pg_crc32 crc; + + INIT_TRADITIONAL_CRC32(crc); + COMP_TRADITIONAL_CRC32(crc, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in)); + FIN_TRADITIONAL_CRC32(crc); + + PG_RETURN_INT64(crc); +} + +Datum +crc32c_bytea(PG_FUNCTION_ARGS) +{ + bytea *in = PG_GETARG_BYTEA_PP(0); + pg_crc32c crc; + + INIT_CRC32C(crc); + COMP_CRC32C(crc, VARDATA_ANY(in), VARSIZE_ANY_EXHDR(in)); + FIN_CRC32C(crc); + + PG_RETURN_INT64(crc); +} diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 927bccfbea875..d31cb45a0588a 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -3,7 +3,7 @@ * globals.c * global variable declarations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -24,6 +24,7 @@ #include "miscadmin.h" #include "postmaster/postmaster.h" #include "storage/procnumber.h" +#include "storage/procsignal.h" ProtocolVersion FrontendProtocol; @@ -48,7 +49,8 @@ pg_time_t MyStartTime; TimestampTz MyStartTimestamp; struct ClientSocket *MyClientSocket; struct Port *MyProcPort; -int32 MyCancelKey; +uint8 MyCancelKey[MAX_CANCEL_KEY_LENGTH]; +int MyCancelKeyLength = 0; int MyPMChildSlot; /* @@ -152,10 +154,6 @@ int VacuumCostPageDirty = 20; int VacuumCostLimit = 200; double VacuumCostDelay = 0; -int64 VacuumPageHit = 0; -int64 VacuumPageMiss = 0; -int64 VacuumPageDirty = 0; - int VacuumCostBalance = 0; /* working state for vacuum */ bool VacuumCostActive = false; diff --git a/src/backend/utils/init/meson.build b/src/backend/utils/init/meson.build index e8af32861f511..c5d42e6305e15 100644 --- a/src/backend/utils/init/meson.build +++ b/src/backend/utils/init/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'globals.c', diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 537d92c0cfde2..43b4dbccc3de6 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -3,7 +3,7 @@ * miscinit.c * miscellaneous initialization support stuff * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -29,6 +29,7 @@ #include #include "access/htup_details.h" +#include "access/parallel.h" #include "catalog/pg_authid.h" #include "common/file_perm.h" #include "libpq/libpq.h" @@ -105,13 +106,6 @@ InitPostmasterChild(void) pgwin32_signal_initialize(); #endif - /* - * Set reference point for stack-depth checking. This might seem - * redundant in !EXEC_BACKEND builds, but it's better to keep the depth - * logic the same with and without that build option. - */ - (void) set_stack_base(); - InitProcessGlobals(); /* @@ -133,7 +127,7 @@ InitPostmasterChild(void) #endif /* Initialize process-local latch support */ - InitializeLatchSupport(); + InitializeWaitEventSupport(); InitProcessLocalLatch(); InitializeLatchWaitSet(); @@ -194,7 +188,7 @@ InitStandaloneProcess(const char *argv0) InitProcessGlobals(); /* Initialize process-local latch support */ - InitializeLatchSupport(); + InitializeWaitEventSupport(); InitProcessLocalLatch(); InitializeLatchWaitSet(); @@ -259,60 +253,72 @@ SwitchBackToLocalLatch(void) SetLatch(MyLatch); } +/* + * Return a human-readable string representation of a BackendType. + * + * The string is not localized here, but we mark the strings for translation + * so that callers can invoke _() on the result. + */ const char * GetBackendTypeDesc(BackendType backendType) { - const char *backendDesc = "unknown process type"; + const char *backendDesc = gettext_noop("unknown process type"); switch (backendType) { case B_INVALID: - backendDesc = "not initialized"; + backendDesc = gettext_noop("not initialized"); break; case B_ARCHIVER: - backendDesc = "archiver"; + backendDesc = gettext_noop("archiver"); break; case B_AUTOVAC_LAUNCHER: - backendDesc = "autovacuum launcher"; + backendDesc = gettext_noop("autovacuum launcher"); break; case B_AUTOVAC_WORKER: - backendDesc = "autovacuum worker"; + backendDesc = gettext_noop("autovacuum worker"); break; case B_BACKEND: - backendDesc = "client backend"; + backendDesc = gettext_noop("client backend"); + break; + case B_DEAD_END_BACKEND: + backendDesc = gettext_noop("dead-end client backend"); break; case B_BG_WORKER: - backendDesc = "background worker"; + backendDesc = gettext_noop("background worker"); break; case B_BG_WRITER: - backendDesc = "background writer"; + backendDesc = gettext_noop("background writer"); break; case B_CHECKPOINTER: - backendDesc = "checkpointer"; + backendDesc = gettext_noop("checkpointer"); + break; + case B_IO_WORKER: + backendDesc = gettext_noop("io worker"); break; case B_LOGGER: - backendDesc = "logger"; + backendDesc = gettext_noop("logger"); break; case B_SLOTSYNC_WORKER: - backendDesc = "slotsync worker"; + backendDesc = gettext_noop("slotsync worker"); break; case B_STANDALONE_BACKEND: - backendDesc = "standalone backend"; + backendDesc = gettext_noop("standalone backend"); break; case B_STARTUP: - backendDesc = "startup"; + backendDesc = gettext_noop("startup"); break; case B_WAL_RECEIVER: - backendDesc = "walreceiver"; + backendDesc = gettext_noop("walreceiver"); break; case B_WAL_SENDER: - backendDesc = "walsender"; + backendDesc = gettext_noop("walsender"); break; case B_WAL_SUMMARIZER: - backendDesc = "walsummarizer"; + backendDesc = gettext_noop("walsummarizer"); break; case B_WAL_WRITER: - backendDesc = "walwriter"; + backendDesc = gettext_noop("walwriter"); break; } @@ -530,7 +536,7 @@ GetOuterUserId(void) static void -SetOuterUserId(Oid userid) +SetOuterUserId(Oid userid, bool is_superuser) { Assert(SecurityRestrictionContext == 0); Assert(OidIsValid(userid)); @@ -538,6 +544,11 @@ SetOuterUserId(Oid userid) /* We force the effective user ID to match, too */ CurrentUserId = userid; + + /* Also update the is_superuser GUC to match OuterUserId's property */ + SetConfigOption("is_superuser", + is_superuser ? "on" : "off", + PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); } @@ -551,6 +562,12 @@ GetSessionUserId(void) return SessionUserId; } +bool +GetSessionUserIsSuperuser(void) +{ + Assert(OidIsValid(SessionUserId)); + return SessionUserIsSuperuser; +} static void SetSessionUserId(Oid userid, bool is_superuser) @@ -559,11 +576,6 @@ SetSessionUserId(Oid userid, bool is_superuser) Assert(OidIsValid(userid)); SessionUserId = userid; SessionUserIsSuperuser = is_superuser; - SetRoleIsActive = false; - - /* We force the effective user IDs to match, too */ - OuterUserId = userid; - CurrentUserId = userid; } /* @@ -577,7 +589,8 @@ GetSystemUser(void) } /* - * GetAuthenticatedUserId - get the authenticated user ID + * GetAuthenticatedUserId/SetAuthenticatedUserId - get/set the authenticated + * user ID */ Oid GetAuthenticatedUserId(void) @@ -586,6 +599,21 @@ GetAuthenticatedUserId(void) return AuthenticatedUserId; } +void +SetAuthenticatedUserId(Oid userid) +{ + Assert(OidIsValid(userid)); + + /* call only once */ + Assert(!OidIsValid(AuthenticatedUserId)); + + AuthenticatedUserId = userid; + + /* Also mark our PGPROC entry with the authenticated user id */ + /* (We assume this is an atomic store so no lock is needed) */ + MyProc->roleId = userid; +} + /* * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID @@ -730,22 +758,33 @@ has_rolreplication(Oid roleid) * Initialize user identity during normal backend startup */ void -InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_check) +InitializeSessionUserId(const char *rolename, Oid roleid, + bool bypass_login_check) { HeapTuple roleTup; Form_pg_authid rform; char *rname; bool is_superuser; + /* + * In a parallel worker, we don't have to do anything here. + * ParallelWorkerMain already set our output variables, and we aren't + * going to enforce either rolcanlogin or rolconnlimit. Furthermore, we + * don't really want to perform a catalog lookup for the role: we don't + * want to fail if it's been dropped. + */ + if (InitializingParallelWorker) + { + Assert(bypass_login_check); + return; + } + /* * Don't do scans if we're bootstrapping, none of the system catalogs * exist yet, and they should be owned by postgres anyway. */ Assert(!IsBootstrapProcessingMode()); - /* call only once */ - Assert(!OidIsValid(AuthenticatedUserId)); - /* * Make sure syscache entries are flushed for recent catalog changes. This * allows us to find roles that were created on-the-fly during @@ -753,6 +792,9 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec */ AcceptInvalidationMessages(); + /* + * Look up the role, either by name if that's given or by OID if not. + */ if (rolename != NULL) { roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename)); @@ -773,16 +815,31 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec rform = (Form_pg_authid) GETSTRUCT(roleTup); roleid = rform->oid; rname = NameStr(rform->rolname); - - AuthenticatedUserId = roleid; is_superuser = rform->rolsuper; - /* This sets OuterUserId/CurrentUserId too */ - SetSessionUserId(roleid, is_superuser); + SetAuthenticatedUserId(roleid); - /* Also mark our PGPROC entry with the authenticated user id */ - /* (We assume this is an atomic store so no lock is needed) */ - MyProc->roleId = roleid; + /* + * Set SessionUserId and related variables, including "role", via the GUC + * mechanisms. + * + * Note: ideally we would use PGC_S_DYNAMIC_DEFAULT here, so that + * session_authorization could subsequently be changed from + * pg_db_role_setting entries. Instead, session_authorization in + * pg_db_role_setting has no effect. Changing that would require solving + * two problems: + * + * 1. If pg_db_role_setting has values for both session_authorization and + * role, we could not be sure which order those would be applied in, and + * it would matter. + * + * 2. Sites may have years-old session_authorization entries. There's not + * been any particular reason to remove them. Ending the dormancy of + * those entries could seriously change application behavior, so only a + * major release should do that. + */ + SetConfigOption("session_authorization", rname, + PGC_BACKEND, PGC_S_OVERRIDE); /* * These next checks are not enforced when in standalone mode, so that @@ -792,7 +849,8 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec if (IsUnderPostmaster) { /* - * Is role allowed to login at all? + * Is role allowed to login at all? (But background workers can + * override this by setting bypass_login_check.) */ if (!bypass_login_check && !rform->rolcanlogin) ereport(FATAL, @@ -801,7 +859,9 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec rname))); /* - * Check connection limit for this role. + * Check connection limit for this role. We enforce the limit only + * for regular backends, since other process types have their own + * PGPROC pools. * * There is a race condition here --- we create our PGPROC before * checking for other PGPROCs. If two backends did this at about the @@ -811,6 +871,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec * just document that the connection limit is approximate. */ if (rform->rolconnlimit >= 0 && + AmRegularBackendProcess() && !is_superuser && CountUserBackends(roleid) > rform->rolconnlimit) ereport(FATAL, @@ -819,13 +880,6 @@ InitializeSessionUserId(const char *rolename, Oid roleid, bool bypass_login_chec rname))); } - /* Record username and superuser status as GUC settings too */ - SetConfigOption("session_authorization", rname, - PGC_BACKEND, PGC_S_OVERRIDE); - SetConfigOption("is_superuser", - is_superuser ? "on" : "off", - PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); - ReleaseSysCache(roleTup); } @@ -847,15 +901,19 @@ InitializeSessionUserIdStandalone(void) Assert(!OidIsValid(AuthenticatedUserId)); AuthenticatedUserId = BOOTSTRAP_SUPERUSERID; - SetSessionUserId(BOOTSTRAP_SUPERUSERID, true); /* - * XXX This should set SetConfigOption("session_authorization"), too. - * Since we don't, C code will get NULL, and current_setting() will get an - * empty string. + * XXX Ideally we'd do this via SetConfigOption("session_authorization"), + * but we lack the role name needed to do that, and we can't fetch it + * because one reason for this special case is to be able to start up even + * if something's happened to the BOOTSTRAP_SUPERUSERID's pg_authid row. + * Since we don't set the GUC itself, C code will see the value as NULL, + * and current_setting() will report an empty string within this session. */ - SetConfigOption("is_superuser", "on", - PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); + SetSessionAuthorization(BOOTSTRAP_SUPERUSERID, true); + + /* We could do SetConfigOption("role"), but let's be consistent */ + SetCurrentRoleId(InvalidOid, false); } /* @@ -901,17 +959,21 @@ system_user(PG_FUNCTION_ARGS) /* * Change session auth ID while running * - * Note that we set the GUC variable is_superuser to indicate whether the - * current role is a superuser. + * The SQL standard says that SET SESSION AUTHORIZATION implies SET ROLE NONE. + * We mechanize that at higher levels not here, because this is the GUC + * assign hook for "session_authorization", and it must be commutative with + * SetCurrentRoleId (the hook for "role") because guc.c provides no guarantees + * which will run first during cases such as transaction rollback. Therefore, + * we update derived state (OuterUserId/CurrentUserId/is_superuser) only if + * !SetRoleIsActive. */ void SetSessionAuthorization(Oid userid, bool is_superuser) { SetSessionUserId(userid, is_superuser); - SetConfigOption("is_superuser", - is_superuser ? "on" : "off", - PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); + if (!SetRoleIsActive) + SetOuterUserId(userid, is_superuser); } /* @@ -947,28 +1009,25 @@ SetCurrentRoleId(Oid roleid, bool is_superuser) /* * Get correct info if it's SET ROLE NONE * - * If SessionUserId hasn't been set yet, just do nothing --- the eventual - * SetSessionUserId call will fix everything. This is needed since we - * will get called during GUC initialization. + * If SessionUserId hasn't been set yet, do nothing beyond updating + * SetRoleIsActive --- the eventual SetSessionAuthorization call will + * update the derived state. This is needed since we will get called + * during GUC initialization. */ if (!OidIsValid(roleid)) { + SetRoleIsActive = false; + if (!OidIsValid(SessionUserId)) return; roleid = SessionUserId; is_superuser = SessionUserIsSuperuser; - - SetRoleIsActive = false; } else SetRoleIsActive = true; - SetOuterUserId(roleid); - - SetConfigOption("is_superuser", - is_superuser ? "on" : "off", - PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); + SetOuterUserId(roleid, is_superuser); } @@ -1372,10 +1431,10 @@ CreateLockFile(const char *filename, bool amPostmaster, * both datadir and socket lockfiles; although more stuff may get added to * the datadir lockfile later. */ - snprintf(buffer, sizeof(buffer), "%d\n%s\n%ld\n%d\n%s\n", + snprintf(buffer, sizeof(buffer), "%d\n%s\n" INT64_FORMAT "\n%d\n%s\n", amPostmaster ? (int) my_pid : -((int) my_pid), DataDir, - (long) MyStartTime, + MyStartTime, PostPortNumber, socketDir); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 25867c8bd5b96..c86ceefda940b 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -3,7 +3,7 @@ * postinit.c * postgres initialization utilities * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -43,21 +43,25 @@ #include "replication/slot.h" #include "replication/slotsync.h" #include "replication/walsender.h" +#include "storage/aio_subsys.h" #include "storage/bufmgr.h" #include "storage/fd.h" #include "storage/ipc.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/procarray.h" +#include "storage/procnumber.h" #include "storage/procsignal.h" #include "storage/sinvaladt.h" #include "storage/smgr.h" #include "storage/sync.h" +#include "tcop/backend_startup.h" #include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/guc_hooks.h" +#include "utils/injection_point.h" #include "utils/memutils.h" #include "utils/pg_locale.h" #include "utils/portal.h" @@ -232,6 +236,9 @@ PerformAuthentication(Port *port) } #endif + /* Capture authentication start time for logging */ + conn_timing.auth_start = GetCurrentTimestamp(); + /* * Set up a timeout in case a buggy or malicious client fails to respond * during authentication. Since we're inside a transaction and might do @@ -250,7 +257,10 @@ PerformAuthentication(Port *port) */ disable_timeout(STATEMENT_TIMEOUT, false); - if (Log_connections) + /* Capture authentication end time for logging */ + conn_timing.auth_end = GetCurrentTimestamp(); + + if (log_connections & LOG_CONNECTION_AUTHORIZATION) { StringInfoData logmsg; @@ -318,7 +328,6 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect bool isnull; char *collate; char *ctype; - char *datlocale; /* Fetch our pg_database row normally, via syscache */ tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); @@ -341,13 +350,13 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect * These checks are not enforced when in standalone mode, so that there is * a way to recover from disabling all access to all databases, for * example "UPDATE pg_database SET datallowconn = false;". - * - * We do not enforce them for autovacuum worker processes either. */ - if (IsUnderPostmaster && !AmAutoVacuumWorkerProcess()) + if (IsUnderPostmaster) { /* * Check that the database is currently allowing connections. + * (Background processes can override this test and the next one by + * setting override_allow_connections.) */ if (!dbform->datallowconn && !override_allow_connections) ereport(FATAL, @@ -360,7 +369,7 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect * is redundant, but since we have the flag, might as well check it * and save a few cycles.) */ - if (!am_superuser && + if (!am_superuser && !override_allow_connections && object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CONNECT) != ACLCHECK_OK) ereport(FATAL, @@ -369,7 +378,9 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect errdetail("User does not have CONNECT privilege."))); /* - * Check connection limit for this database. + * Check connection limit for this database. We enforce the limit + * only for regular backends, since other process types have their own + * PGPROC pools. * * There is a race condition here --- we create our PGPROC before * checking for other PGPROCs. If two backends did this at about the @@ -379,6 +390,7 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect * just document that the connection limit is approximate. */ if (dbform->datconnlimit >= 0 && + AmRegularBackendProcess() && !am_superuser && CountDBConnections(MyDatabaseId) > dbform->datconnlimit) ereport(FATAL, @@ -423,42 +435,7 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect strcmp(ctype, "POSIX") == 0) database_ctype_is_c = true; - if (dbform->datlocprovider == COLLPROVIDER_BUILTIN) - { - datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale); - datlocale = TextDatumGetCString(datum); - - builtin_validate_locale(dbform->encoding, datlocale); - - default_locale.info.builtin.locale = MemoryContextStrdup( - TopMemoryContext, datlocale); - } - else if (dbform->datlocprovider == COLLPROVIDER_ICU) - { - char *icurules; - - datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale); - datlocale = TextDatumGetCString(datum); - - datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticurules, &isnull); - if (!isnull) - icurules = TextDatumGetCString(datum); - else - icurules = NULL; - - make_icu_collator(datlocale, icurules, &default_locale); - } - else - datlocale = NULL; - - default_locale.provider = dbform->datlocprovider; - - /* - * Default locale is currently always deterministic. Nondeterministic - * locales currently don't support pattern matching, which would break a - * lot of things if applied globally. - */ - default_locale.deterministic = true; + init_database_collation(); /* * Check collation version. See similar code in @@ -478,7 +455,10 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect if (dbform->datlocprovider == COLLPROVIDER_LIBC) locale = collate; else - locale = datlocale; + { + datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale); + locale = TextDatumGetCString(datum); + } actual_versionstr = get_collation_actual_version(dbform->datlocprovider, locale); if (!actual_versionstr) @@ -576,18 +556,48 @@ InitializeMaxBackends(void) { Assert(MaxBackends == 0); - /* the extra unit accounts for the autovacuum launcher */ - MaxBackends = MaxConnections + autovacuum_max_workers + 1 + - max_worker_processes + max_wal_senders; + /* Note that this does not include "auxiliary" processes */ + MaxBackends = MaxConnections + autovacuum_worker_slots + + max_worker_processes + max_wal_senders + NUM_SPECIAL_WORKER_PROCS; if (MaxBackends > MAX_BACKENDS) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("too many server processes configured"), - errdetail("\"max_connections\" (%d) plus \"autovacuum_max_workers\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.", - MaxConnections, autovacuum_max_workers, + errdetail("\"max_connections\" (%d) plus \"autovacuum_worker_slots\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.", + MaxConnections, autovacuum_worker_slots, max_worker_processes, max_wal_senders, - MAX_BACKENDS))); + MAX_BACKENDS - (NUM_SPECIAL_WORKER_PROCS - 1)))); +} + +/* + * Initialize the number of fast-path lock slots in PGPROC. + * + * This must be called after modules have had the chance to alter GUCs in + * shared_preload_libraries and before shared memory size is determined. + */ +void +InitializeFastPathLocks(void) +{ + /* Should be initialized only once. */ + Assert(FastPathLockGroupsPerBackend == 0); + + /* + * Based on the max_locks_per_transaction GUC, as that's a good indicator + * of the expected number of locks, figure out the value for + * FastPathLockGroupsPerBackend. This must be a power-of-two. We cap the + * value at FP_LOCK_GROUPS_PER_BACKEND_MAX and insist the value is at + * least 1. + * + * The default max_locks_per_transaction = 64 means 4 groups by default. + */ + FastPathLockGroupsPerBackend = + Max(Min(pg_nextpower2_32(max_locks_per_xact) / FP_LOCK_SLOTS_PER_GROUP, + FP_LOCK_GROUPS_PER_BACKEND_MAX), 1); + + /* Validate we did get a power-of-two */ + Assert(FastPathLockGroupsPerBackend == + pg_nextpower2_32(FastPathLockGroupsPerBackend)); } /* @@ -622,10 +632,16 @@ BaseInit(void) */ pgstat_initialize(); + /* + * Initialize AIO before infrastructure that might need to actually + * execute AIO. + */ + pgaio_init_backend(); + /* Do local initialization of storage and buffer managers */ InitSync(); smgrinit(); - InitBufferPoolAccess(); + InitBufferManagerAccess(); /* * Initialize temporary file access after pgstat, so that the temporary @@ -639,6 +655,9 @@ BaseInit(void) */ InitXLogInsert(); + /* Initialize lock manager's local structs */ + InitLockManagerAccess(); + /* * Initialize replication slots after pgstat. The exit hook might need to * drop ephemeral slots, which in turn triggers stats reporting. @@ -710,13 +729,27 @@ InitPostgres(const char *in_dbname, Oid dboid, */ InitProcessPhase2(); + /* Initialize status reporting */ + pgstat_beinit(); + + /* + * And initialize an entry in the PgBackendStatus array. That way, if + * LWLocks or third-party authentication should happen to hang, it is + * possible to retrieve some information about what is going on. + */ + if (!bootstrap) + { + pgstat_bestart_initial(); + INJECTION_POINT("init-pre-auth", NULL); + } + /* * Initialize my entry in the shared-invalidation manager's array of * per-backend data. */ SharedInvalBackendInit(false); - ProcSignalInit(); + ProcSignalInit(MyCancelKey, MyCancelKeyLength); /* * Also set up timeout handlers needed for backend operation. We need @@ -778,9 +811,6 @@ InitPostgres(const char *in_dbname, Oid dboid, /* Initialize portal manager */ EnablePortalManager(); - /* Initialize status reporting */ - pgstat_beinit(); - /* * Load relcache entries for the shared system catalogs. This must create * at least entries for pg_database and catalogs used for authentication. @@ -801,23 +831,14 @@ InitPostgres(const char *in_dbname, Oid dboid, /* The autovacuum launcher is done here */ if (AmAutoVacuumLauncherProcess()) { - /* report this backend in the PgBackendStatus array */ - pgstat_bestart(); + /* fill in the remainder of this entry in the PgBackendStatus array */ + pgstat_bestart_final(); return; } /* - * Start a new transaction here before first access to db, and get a - * snapshot. We don't have a use for the snapshot itself, but we're - * interested in the secondary effect that it sets RecentGlobalXmin. (This - * is critical for anything that reads heap pages, because HOT may decide - * to prune them even if the process doesn't attempt to modify any - * tuples.) - * - * FIXME: This comment is inaccurate / the code buggy. A snapshot that is - * not pushed/active does not reliably prevent HOT pruning (->xmin could - * e.g. be cleared when cache invalidations are processed). + * Start a new transaction here before first access to db. */ if (!bootstrap) { @@ -832,8 +853,6 @@ InitPostgres(const char *in_dbname, Oid dboid, * Fortunately, "read committed" is plenty good enough. */ XactIsoLevel = XACT_READ_COMMITTED; - - (void) GetTransactionSnapshot(); } /* @@ -887,6 +906,14 @@ InitPostgres(const char *in_dbname, Oid dboid, am_superuser = superuser(); } + /* Report any SSL/GSS details for the session. */ + if (MyProcPort != NULL) + { + Assert(!bootstrap); + + pgstat_bestart_security(); + } + /* * Binary upgrades only allowed super-user connections */ @@ -898,17 +925,16 @@ InitPostgres(const char *in_dbname, Oid dboid, } /* - * The last few connection slots are reserved for superusers and roles - * with privileges of pg_use_reserved_connections. Replication - * connections are drawn from slots reserved with max_wal_senders and are - * not limited by max_connections, superuser_reserved_connections, or - * reserved_connections. + * The last few regular connection slots are reserved for superusers and + * roles with privileges of pg_use_reserved_connections. We do not apply + * these limits to background processes, since they all have their own + * pools of PGPROC slots. * * Note: At this point, the new backend has already claimed a proc struct, * so we must check whether the number of free slots is strictly less than * the reserved connection limits. */ - if (!am_superuser && !am_walsender && + if (AmRegularBackendProcess() && !am_superuser && (SuperuserReservedConnections + ReservedConnections) > 0 && !HaveNFreeProcs(SuperuserReservedConnections + ReservedConnections, &nfree)) { @@ -957,8 +983,8 @@ InitPostgres(const char *in_dbname, Oid dboid, /* initialize client encoding */ InitializeClientEncoding(); - /* report this backend in the PgBackendStatus array */ - pgstat_bestart(); + /* fill in the remainder of this entry in the PgBackendStatus array */ + pgstat_bestart_final(); /* close the transaction we started above */ CommitTransactionCommand(); @@ -1001,7 +1027,7 @@ InitPostgres(const char *in_dbname, Oid dboid, */ if (!bootstrap) { - pgstat_bestart(); + pgstat_bestart_final(); CommitTransactionCommand(); } return; @@ -1201,9 +1227,9 @@ InitPostgres(const char *in_dbname, Oid dboid, if ((flags & INIT_PG_LOAD_SESSION_LIBS) != 0) process_session_preload_libraries(); - /* report this backend in the PgBackendStatus array */ + /* fill in the remainder of this entry in the PgBackendStatus array */ if (!bootstrap) - pgstat_bestart(); + pgstat_bestart_final(); /* close the transaction we started above */ if (!bootstrap) diff --git a/src/backend/utils/init/usercontext.c b/src/backend/utils/init/usercontext.c index 9772420e3c237..2cc42ea1b7746 100644 --- a/src/backend/utils/init/usercontext.c +++ b/src/backend/utils/init/usercontext.c @@ -3,7 +3,7 @@ * usercontext.c * Convenience functions for running code as a different database user. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/mb/README b/src/backend/utils/mb/README index ef3662689135b..4447881ead07d 100644 --- a/src/backend/utils/mb/README +++ b/src/backend/utils/mb/README @@ -8,9 +8,6 @@ mbutils.c: public functions for the backend only. stringinfo_mb.c: public backend-only multibyte-aware stringinfo functions wstrcmp.c: strcmp for mb wstrncmp.c: strncmp for mb -win866.c: a tool to generate KOI8 <--> CP866 conversion table -iso.c: a tool to generate KOI8 <--> ISO8859-5 conversion table -win1251.c: a tool to generate KOI8 <--> CP1251 conversion table See also in src/common/: diff --git a/src/backend/utils/mb/Unicode/Makefile b/src/backend/utils/mb/Unicode/Makefile index 266bc118dc41a..ad789b31e54b5 100644 --- a/src/backend/utils/mb/Unicode/Makefile +++ b/src/backend/utils/mb/Unicode/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/backend/utils/mb/Unicode # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/Makefile # diff --git a/src/backend/utils/mb/Unicode/UCS_to_BIG5.pl b/src/backend/utils/mb/Unicode/UCS_to_BIG5.pl index 6c99f726a8f80..abd73721c9628 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_BIG5.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_BIG5.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_BIG5.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_EUC_CN.pl b/src/backend/utils/mb/Unicode/UCS_to_EUC_CN.pl index c3b5bef55aea7..f7776631e4c18 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_EUC_CN.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_EUC_CN.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_GB18030.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl b/src/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl index 53c5370ace75e..cc3b65abc67b3 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_EUC_JIS_2004.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl b/src/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl index 561d355379b94..c74c5e6a98fa2 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_EUC_JP.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl b/src/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl index 32f544f59cddb..43f0ee75d6f4b 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_EUC_KR.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl b/src/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl index cd54a8f4ec7ca..19da4b410f422 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_EUC_TW.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_GB18030.pl b/src/backend/utils/mb/Unicode/UCS_to_GB18030.pl index 68308133b29fb..ddcbd6ef0c478 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_GB18030.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_GB18030.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_GB18030.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_JOHAB.pl b/src/backend/utils/mb/Unicode/UCS_to_JOHAB.pl index 07ca11d164705..cd70e66628aee 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_JOHAB.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_JOHAB.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_JOHAB.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl b/src/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl index e8e7914cdb521..41a4334cf3977 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_SHIFT_JIS_2004.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_SJIS.pl b/src/backend/utils/mb/Unicode/UCS_to_SJIS.pl index 9b5ab429afaed..66d0fe43ddf5e 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_SJIS.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_SJIS.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_SJIS.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_UHC.pl b/src/backend/utils/mb/Unicode/UCS_to_UHC.pl index 37ca3fcace7ae..c6087b5c38270 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_UHC.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_UHC.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_GB18030.pl # diff --git a/src/backend/utils/mb/Unicode/UCS_to_most.pl b/src/backend/utils/mb/Unicode/UCS_to_most.pl index 50f54d6832e9a..b0009692521a2 100755 --- a/src/backend/utils/mb/Unicode/UCS_to_most.pl +++ b/src/backend/utils/mb/Unicode/UCS_to_most.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/UCS_to_most.pl # diff --git a/src/backend/utils/mb/Unicode/convutils.pm b/src/backend/utils/mb/Unicode/convutils.pm index ee780acbe386f..99a397a0c37fa 100644 --- a/src/backend/utils/mb/Unicode/convutils.pm +++ b/src/backend/utils/mb/Unicode/convutils.pm @@ -1,5 +1,5 @@ # -# Copyright (c) 2001-2024, PostgreSQL Global Development Group +# Copyright (c) 2001-2025, PostgreSQL Global Development Group # # src/backend/utils/mb/Unicode/convutils.pm diff --git a/src/backend/utils/mb/conv.c b/src/backend/utils/mb/conv.c index cc539bf439c17..4a312ab429b6f 100644 --- a/src/backend/utils/mb/conv.c +++ b/src/backend/utils/mb/conv.c @@ -2,7 +2,7 @@ * * Utility functions for conversion procs. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/mb/conversion_procs/Makefile b/src/backend/utils/mb/conversion_procs/Makefile index 8ee4642a179ea..e1919eff6d1ae 100644 --- a/src/backend/utils/mb/conversion_procs/Makefile +++ b/src/backend/utils/mb/conversion_procs/Makefile @@ -2,7 +2,7 @@ # # Makefile for backend/utils/mb/conversion_procs # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/backend/utils/mb/conversion_procs/Makefile diff --git a/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c b/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c index aa61902a82588..f00432a698126 100644 --- a/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c +++ b/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c @@ -2,7 +2,7 @@ * * Cyrillic and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "cyrillic_and_mic", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(koi8r_to_mic); PG_FUNCTION_INFO_V1(mic_to_koi8r); diff --git a/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c b/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c index 8f5fa90070731..14bd66e16f2b2 100644 --- a/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c +++ b/src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c @@ -2,7 +2,7 @@ * * EUC_JIS_2004, SHIFT_JIS_2004 * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/mb/conversion_procs/euc2004_sjis2004/euc2004_sjis2004.c @@ -14,7 +14,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "euc2004_sjis2004", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_jis_2004_to_shift_jis_2004); PG_FUNCTION_INFO_V1(shift_jis_2004_to_euc_jis_2004); diff --git a/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c b/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c index 9551761a7570a..14e157e14f5b2 100644 --- a/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c +++ b/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c @@ -2,7 +2,7 @@ * * EUC_CN and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "euc_cn_and_mic", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_cn_to_mic); PG_FUNCTION_INFO_V1(mic_to_euc_cn); diff --git a/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c b/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c index daf6eac97498f..d2744bd69b290 100644 --- a/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c +++ b/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c @@ -2,7 +2,7 @@ * * EUC_JP, SJIS and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -27,7 +27,10 @@ */ #include "sjis.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "euc_jp_and_sjis", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_jp_to_sjis); PG_FUNCTION_INFO_V1(sjis_to_euc_jp); diff --git a/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c b/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c index 631766898f734..0213768c452b2 100644 --- a/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c +++ b/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c @@ -2,7 +2,7 @@ * * EUC_KR and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "euc_kr_and_mic", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_kr_to_mic); PG_FUNCTION_INFO_V1(mic_to_euc_kr); diff --git a/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c b/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c index ed71678c989a4..c1834ca41819e 100644 --- a/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c +++ b/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c @@ -2,7 +2,7 @@ * * EUC_TW, BIG5 and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "euc_tw_and_big5", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_tw_to_big5); PG_FUNCTION_INFO_V1(big5_to_euc_tw); diff --git a/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c b/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c index a2f6c3f7236fe..803705282643a 100644 --- a/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c +++ b/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c @@ -2,7 +2,7 @@ * * LATIN2 and WIN1250 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "latin2_and_win1250", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(latin2_to_mic); PG_FUNCTION_INFO_V1(mic_to_latin2); diff --git a/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c b/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c index e00aa382284d8..19757afa2d91f 100644 --- a/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c +++ b/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c @@ -2,7 +2,7 @@ * * LATINn and MULE_INTERNAL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "latin_and_mic", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(latin1_to_mic); PG_FUNCTION_INFO_V1(mic_to_latin1); diff --git a/src/backend/utils/mb/conversion_procs/meson.build b/src/backend/utils/mb/conversion_procs/meson.build index df2db81e51bf8..0e8273e0b615e 100644 --- a/src/backend/utils/mb/conversion_procs/meson.build +++ b/src/backend/utils/mb/conversion_procs/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group encodings = { 'cyrillic_and_mic': ['cyrillic_and_mic/cyrillic_and_mic.c'], diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c b/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c index 62643aaa296d5..eae2d2d69f305 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c @@ -2,7 +2,7 @@ * * BIG5 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/big5_to_utf8.map" #include "../../Unicode/utf8_to_big5.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_big5", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(big5_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_big5); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c b/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c index 9672954c8b944..5addade582fd3 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c @@ -2,7 +2,7 @@ * * UTF8 and Cyrillic * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -19,7 +19,10 @@ #include "../../Unicode/utf8_to_koi8u.map" #include "../../Unicode/koi8u_to_utf8.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_cyrillic", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(utf8_to_koi8r); PG_FUNCTION_INFO_V1(koi8r_to_utf8); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_euc2004/utf8_and_euc2004.c b/src/backend/utils/mb/conversion_procs/utf8_and_euc2004/utf8_and_euc2004.c index 25bc45cf378a2..3e660da89b846 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_euc2004/utf8_and_euc2004.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_euc2004/utf8_and_euc2004.c @@ -2,7 +2,7 @@ * * EUC_JIS_2004 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/euc_jis_2004_to_utf8.map" #include "../../Unicode/utf8_to_euc_jis_2004.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_euc2004", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_jis_2004_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_euc_jis_2004); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c b/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c index 3f5d2f3cb7344..260b75c6bc5f4 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c @@ -2,7 +2,7 @@ * * EUC_CN <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/euc_cn_to_utf8.map" #include "../../Unicode/utf8_to_euc_cn.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_euc_cn", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_cn_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_euc_cn); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c b/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c index 837e7e98e918a..ad11594753deb 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c @@ -2,7 +2,7 @@ * * EUC_JP <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/euc_jp_to_utf8.map" #include "../../Unicode/utf8_to_euc_jp.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_euc_jp", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_jp_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_euc_jp); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c b/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c index 7ad7f26397749..e3f953263f3ab 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c @@ -2,7 +2,7 @@ * * EUC_KR <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/euc_kr_to_utf8.map" #include "../../Unicode/utf8_to_euc_kr.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_euc_kr", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_kr_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_euc_kr); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c b/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c index 9e56f1fe249f9..25663bbda5d45 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c @@ -2,7 +2,7 @@ * * EUC_TW <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/euc_tw_to_utf8.map" #include "../../Unicode/utf8_to_euc_tw.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_euc_tw", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(euc_tw_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_euc_tw); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c b/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c index c64c6d2b313e3..ffc9c58cd130b 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c @@ -2,7 +2,7 @@ * * GB18030 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/gb18030_to_utf8.map" #include "../../Unicode/utf8_to_gb18030.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_gb18030", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(gb18030_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_gb18030); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c b/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c index 696d741e91aff..9adc0ce7d8963 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c @@ -2,7 +2,7 @@ * * GBK <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/gbk_to_utf8.map" #include "../../Unicode/utf8_to_gbk.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_gbk", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(gbk_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_gbk); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c b/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c index 20558de029eb4..5a15981b2dee3 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c @@ -2,7 +2,7 @@ * * ISO 8859 2-16 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -41,7 +41,10 @@ #include "../../Unicode/utf8_to_iso8859_9.map" #include "../../Unicode/iso8859_16_to_utf8.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_iso8859", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(iso8859_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_iso8859); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c b/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c index 45d1504098285..c077b986bcdf0 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c @@ -2,7 +2,7 @@ * * ISO8859_1 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,10 @@ #include "fmgr.h" #include "mb/pg_wchar.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_iso8859_1", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(iso8859_1_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_iso8859_1); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c b/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c index a0c13ae228b46..08e38026a408b 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c @@ -2,7 +2,7 @@ * * JOHAB <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/johab_to_utf8.map" #include "../../Unicode/utf8_to_johab.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_johab", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(johab_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_johab); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c b/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c index e619fd932d4b3..911a6342c602e 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c @@ -2,7 +2,7 @@ * * SJIS <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/sjis_to_utf8.map" #include "../../Unicode/utf8_to_sjis.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_sjis", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(sjis_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_sjis); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_sjis2004/utf8_and_sjis2004.c b/src/backend/utils/mb/conversion_procs/utf8_and_sjis2004/utf8_and_sjis2004.c index 5078475762ccf..d0361784a3952 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_sjis2004/utf8_and_sjis2004.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_sjis2004/utf8_and_sjis2004.c @@ -2,7 +2,7 @@ * * SHIFT_JIS_2004 <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/shift_jis_2004_to_utf8.map" #include "../../Unicode/utf8_to_shift_jis_2004.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_sjis2004", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(shift_jis_2004_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_shift_jis_2004); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c b/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c index d6475c2197baa..891a17014a105 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c @@ -2,7 +2,7 @@ * * UHC <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,10 @@ #include "../../Unicode/uhc_to_utf8.map" #include "../../Unicode/utf8_to_uhc.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_uhc", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(uhc_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_uhc); diff --git a/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c b/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c index e813d894f96c8..24c0dd9a5524d 100644 --- a/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c +++ b/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c @@ -2,7 +2,7 @@ * * WIN <--> UTF8 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -37,7 +37,10 @@ #include "../../Unicode/win874_to_utf8.map" #include "../../Unicode/win1258_to_utf8.map" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "utf8_and_win", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(win_to_utf8); PG_FUNCTION_INFO_V1(utf8_to_win); diff --git a/src/backend/utils/mb/iso.c b/src/backend/utils/mb/iso.c deleted file mode 100644 index d5dae56339f15..0000000000000 --- a/src/backend/utils/mb/iso.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * make KOI8->ISO8859-5 and ISO8859-5->KOI8 translation table - * from koi-iso.tab. - * - * Tatsuo Ishii - * - * src/backend/utils/mb/iso.c - */ - -#include - - -main() -{ - int i; - char koitab[128], - isotab[128]; - char buf[4096]; - int koi, - iso; - - for (i = 0; i < 128; i++) - koitab[i] = isotab[i] = 0; - - while (fgets(buf, sizeof(buf), stdin) != NULL) - { - if (*buf == '#') - continue; - sscanf(buf, "%d %x", &koi, &iso); - if (koi < 128 || koi > 255 || iso < 128 || iso > 255) - { - fprintf(stderr, "invalid value %d\n", koi); - exit(1); - } - koitab[koi - 128] = iso; - isotab[iso - 128] = koi; - } - - i = 0; - printf("static char koi2iso[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", koitab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); - - i = 0; - printf("static char iso2koi[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", isotab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); -} diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c index 62777b14c9bb5..886ecbad87183 100644 --- a/src/backend/utils/mb/mbutils.c +++ b/src/backend/utils/mb/mbutils.c @@ -23,7 +23,7 @@ * the result is validly encoded according to the destination encoding. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -39,6 +39,7 @@ #include "mb/pg_wchar.h" #include "utils/fmgrprotos.h" #include "utils/memutils.h" +#include "utils/relcache.h" #include "varatt.h" /* @@ -310,7 +311,7 @@ InitializeClientEncoding(void) { Oid utf8_to_server_proc; - Assert(IsTransactionState()); + AssertCouldGetRelation(); utf8_to_server_proc = FindDefaultConversionProc(PG_UTF8, current_server_encoding); @@ -1087,7 +1088,7 @@ pg_mbcliplen(const char *mbstr, int len, int limit) } /* - * pg_mbcliplen with specified encoding + * pg_mbcliplen with specified encoding; string must be valid in encoding */ int pg_encoding_mbcliplen(int encoding, const char *mbstr, @@ -1692,12 +1693,12 @@ check_encoding_conversion_args(int src_encoding, * report_invalid_encoding: complain about invalid multibyte character * * note: len is remaining length of string, not length of character; - * len must be greater than zero, as we always examine the first byte. + * len must be greater than zero (or we'd neglect initializing "buf"). */ void report_invalid_encoding(int encoding, const char *mbstr, int len) { - int l = pg_encoding_mblen(encoding, mbstr); + int l = pg_encoding_mblen_or_incomplete(encoding, mbstr, len); char buf[8 * 5 + 1]; char *p = buf; int j, @@ -1724,18 +1725,26 @@ report_invalid_encoding(int encoding, const char *mbstr, int len) * report_untranslatable_char: complain about untranslatable character * * note: len is remaining length of string, not length of character; - * len must be greater than zero, as we always examine the first byte. + * len must be greater than zero (or we'd neglect initializing "buf"). */ void report_untranslatable_char(int src_encoding, int dest_encoding, const char *mbstr, int len) { - int l = pg_encoding_mblen(src_encoding, mbstr); + int l; char buf[8 * 5 + 1]; char *p = buf; int j, jlimit; + /* + * We probably could use plain pg_encoding_mblen(), because + * gb18030_to_utf8() verifies before it converts. All conversions should. + * For src_encoding!=GB18030, len>0 meets pg_encoding_mblen() needs. Even + * so, be defensive, since a buggy conversion might pass invalid data. + * This is not a performance-critical path. + */ + l = pg_encoding_mblen_or_incomplete(src_encoding, mbstr, len); jlimit = Min(l, len); jlimit = Min(jlimit, 8); /* prevent buffer overrun */ diff --git a/src/backend/utils/mb/meson.build b/src/backend/utils/mb/meson.build index 700b705901743..3569b39f6265d 100644 --- a/src/backend/utils/mb/meson.build +++ b/src/backend/utils/mb/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'conv.c', diff --git a/src/backend/utils/mb/stringinfo_mb.c b/src/backend/utils/mb/stringinfo_mb.c index 241a6c2562cef..2f40cf745c413 100644 --- a/src/backend/utils/mb/stringinfo_mb.c +++ b/src/backend/utils/mb/stringinfo_mb.c @@ -8,7 +8,7 @@ * code. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/mb/win1251.c b/src/backend/utils/mb/win1251.c deleted file mode 100644 index 75129e6eff895..0000000000000 --- a/src/backend/utils/mb/win1251.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * make KOI8->CP1251(win-1251) and CP1251(win-1251)->KOI8 translation table - * from koi-win.tab. - * - * Tatsuo Ishii - * - * src/backend/utils/mb/win1251.c - */ - -#include - - -main() -{ - int i; - char koitab[128], - wintab[128]; - char buf[4096]; - int koi, - win; - - for (i = 0; i < 128; i++) - koitab[i] = wintab[i] = 0; - - while (fgets(buf, sizeof(buf), stdin) != NULL) - { - if (*buf == '#') - continue; - sscanf(buf, "%d %d", &koi, &win); - if (koi < 128 || koi > 255 || win < 128 || win > 255) - { - fprintf(stderr, "invalid value %d\n", koi); - exit(1); - } - koitab[koi - 128] = win; - wintab[win - 128] = koi; - } - - i = 0; - printf("static char koi2win[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", koitab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); - - i = 0; - printf("static char win2koi[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", wintab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); -} diff --git a/src/backend/utils/mb/win866.c b/src/backend/utils/mb/win866.c deleted file mode 100644 index f98c376450366..0000000000000 --- a/src/backend/utils/mb/win866.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * make KOI8->CP866(ALT) and CP866(ALT)->KOI8 translation table - * from koi-alt.tab. - * - * Tatsuo Ishii - * - * src/backend/utils/mb/win866.c - */ - -#include - - -main() -{ - int i; - char koitab[128], - alttab[128]; - char buf[4096]; - int koi, - alt; - - for (i = 0; i < 128; i++) - koitab[i] = alttab[i] = 0; - - while (fgets(buf, sizeof(buf), stdin) != NULL) - { - if (*buf == '#') - continue; - sscanf(buf, "%d %d", &koi, &alt); - if (koi < 128 || koi > 255 || alt < 128 || alt > 255) - { - fprintf(stderr, "invalid value %d\n", koi); - exit(1); - } - koitab[koi - 128] = alt; - alttab[alt - 128] = koi; - } - - i = 0; - printf("static char koi2alt[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", koitab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); - - i = 0; - printf("static char alt2koi[] = {\n"); - while (i < 128) - { - int j = 0; - - while (j < 8) - { - printf("0x%02x", alttab[i++]); - j++; - if (i >= 128) - break; - printf(", "); - } - printf("\n"); - } - printf("};\n"); -} diff --git a/src/backend/utils/meson.build b/src/backend/utils/meson.build index 98db199c8cdf0..6891195ecb45b 100644 --- a/src/backend/utils/meson.build +++ b/src/backend/utils/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group install_data('errcodes.txt', install_dir: dir_data, diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile index d9f59785b9824..b362ae437710d 100644 --- a/src/backend/utils/misc/Makefile +++ b/src/backend/utils/misc/Makefile @@ -29,6 +29,7 @@ OBJS = \ queryenvironment.o \ rls.o \ sampling.o \ + stack_depth.o \ superuser.o \ timeout.o \ tzparser.o diff --git a/src/backend/utils/misc/conffiles.c b/src/backend/utils/misc/conffiles.c index be38f938610c0..23ebad4749b59 100644 --- a/src/backend/utils/misc/conffiles.c +++ b/src/backend/utils/misc/conffiles.c @@ -7,7 +7,7 @@ * used by PostgreSQL, be they related to GUCs or authentication. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 73be80076da73..11a1e2a3f9f9a 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -2,7 +2,7 @@ /* * Scanner for the configuration file * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/backend/utils/misc/guc-file.l */ @@ -57,6 +57,7 @@ static int GUC_flex_fatal(const char *msg); %} +%option reentrant %option 8bit %option never-interactive %option nodefault @@ -301,7 +302,7 @@ record_config_file_error(const char *errmsg, /* * Flex fatal errors bring us here. Stash the error message and jump back to * ParseConfigFp(). Assume all msg arguments point to string constants; this - * holds for flex 2.5.35 (earliest we support). Otherwise, we would need to + * holds for all currently known flex versions. Otherwise, we would need to * copy the message. * * We return "int" since this takes the place of calls to fprintf(). @@ -353,6 +354,8 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, unsigned int save_ConfigFileLineno = ConfigFileLineno; sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp; sigjmp_buf flex_fatal_jmp; + yyscan_t scanner; + struct yyguts_t *yyg; /* needed for yytext macro */ volatile YY_BUFFER_STATE lex_buffer = NULL; int errorcount; int token; @@ -381,11 +384,15 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, ConfigFileLineno = 1; errorcount = 0; - lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE); - yy_switch_to_buffer(lex_buffer); + if (yylex_init(&scanner) != 0) + elog(elevel, "yylex_init() failed: %m"); + yyg = (struct yyguts_t *) scanner; + + lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE, scanner); + yy_switch_to_buffer(lex_buffer, scanner); /* This loop iterates once per logical line */ - while ((token = yylex())) + while ((token = yylex(scanner))) { char *opt_name = NULL; char *opt_value = NULL; @@ -400,9 +407,9 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, opt_name = pstrdup(yytext); /* next we have an optional equal sign; discard if present */ - token = yylex(); + token = yylex(scanner); if (token == GUC_EQUALS) - token = yylex(); + token = yylex(scanner); /* now we must have the option value */ if (token != GUC_ID && @@ -417,7 +424,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, opt_value = pstrdup(yytext); /* now we'd like an end of line, or possibly EOF */ - token = yylex(); + token = yylex(scanner); if (token != GUC_EOL) { if (token != 0) @@ -438,7 +445,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, depth + 1, elevel, head_p, tail_p)) OK = false; - yy_switch_to_buffer(lex_buffer); + yy_switch_to_buffer(lex_buffer, scanner); pfree(opt_name); pfree(opt_value); } @@ -453,7 +460,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, depth + 1, elevel, head_p, tail_p)) OK = false; - yy_switch_to_buffer(lex_buffer); + yy_switch_to_buffer(lex_buffer, scanner); pfree(opt_name); pfree(opt_value); } @@ -468,7 +475,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, depth + 1, elevel, head_p, tail_p)) OK = false; - yy_switch_to_buffer(lex_buffer); + yy_switch_to_buffer(lex_buffer, scanner); pfree(opt_name); pfree(opt_value); } @@ -508,8 +515,8 @@ parse_error: { ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error in file \"%s\" line %u, near end of line", - config_file, ConfigFileLineno - 1))); + errmsg("syntax error in file \"%s\" line %u, near end of line", + config_file, ConfigFileLineno - 1))); record_config_file_error("syntax error", config_file, ConfigFileLineno - 1, head_p, tail_p); @@ -518,8 +525,8 @@ parse_error: { ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", - config_file, ConfigFileLineno, yytext))); + errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", + config_file, ConfigFileLineno, yytext))); record_config_file_error("syntax error", config_file, ConfigFileLineno, head_p, tail_p); @@ -538,21 +545,22 @@ parse_error: { ereport(elevel, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("too many syntax errors found, abandoning file \"%s\"", - config_file))); + errmsg("too many syntax errors found, abandoning file \"%s\"", + config_file))); break; } /* resync to next end-of-line or EOF */ while (token != GUC_EOL && token != 0) - token = yylex(); + token = yylex(scanner); /* break out of loop on EOF */ if (token == 0) break; } cleanup: - yy_delete_buffer(lex_buffer); + yy_delete_buffer(lex_buffer, scanner); + yylex_destroy(scanner); /* Each recursion level must save and restore these static variables. */ ConfigFileLineno = save_ConfigFileLineno; GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp; @@ -581,7 +589,7 @@ ParseConfigDirectory(const char *includedir, int num_filenames; filenames = GetConfFilesInDir(includedir, calling_file, elevel, - &num_filenames, &err_msg); + &num_filenames, &err_msg); if (!filenames) { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 0c593b81b4e33..667df448732f2 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -14,7 +14,7 @@ * See src/backend/utils/misc/README for more information. * * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * Written by Peter Eisentraut . * * IDENTIFICATION @@ -190,6 +190,7 @@ static const unit_conversion time_unit_conversion_table[] = static const char *const map_old_guc_names[] = { "sort_mem", "work_mem", "vacuum_mem", "maintenance_work_mem", + "ssl_ecdh_curve", "ssl_groups", NULL }; @@ -1588,7 +1589,7 @@ static void InitializeGUCOptionsFromEnvironment(void) { char *env; - long stack_rlimit; + ssize_t stack_rlimit; env = getenv("PGPORT"); if (env != NULL) @@ -1612,7 +1613,7 @@ InitializeGUCOptionsFromEnvironment(void) stack_rlimit = get_stack_depth_rlimit(); if (stack_rlimit > 0) { - long new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L; + ssize_t new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024; if (new_limit > 100) { @@ -1626,7 +1627,7 @@ InitializeGUCOptionsFromEnvironment(void) new_limit = 2048; source = PGC_S_DYNAMIC_DEFAULT; } - snprintf(limbuf, sizeof(limbuf), "%ld", new_limit); + snprintf(limbuf, sizeof(limbuf), "%d", (int) new_limit); SetConfigOption("max_stack_depth", limbuf, PGC_POSTMASTER, source); } @@ -3115,7 +3116,6 @@ config_enum_get_options(struct config_enum *record, const char *prefix, * and also calls any check hook the parameter may have. * * record: GUC variable's info record - * name: variable name (should match the record of course) * value: proposed value, as a string * source: identifies source of value (check hooks may need this) * elevel: level to log any error reports at @@ -3127,7 +3127,7 @@ config_enum_get_options(struct config_enum *record, const char *prefix, */ static bool parse_and_validate_value(struct config_generic *record, - const char *name, const char *value, + const char *value, GucSource source, int elevel, union config_var_val *newval, void **newextra) { @@ -3142,7 +3142,7 @@ parse_and_validate_value(struct config_generic *record, ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("parameter \"%s\" requires a Boolean value", - name))); + conf->gen.name))); return false; } @@ -3162,7 +3162,7 @@ parse_and_validate_value(struct config_generic *record, ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - name, value), + conf->gen.name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); return false; } @@ -3181,7 +3181,7 @@ parse_and_validate_value(struct config_generic *record, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d%s%s .. %d%s%s)", newval->intval, unitspace, unit, - name, + conf->gen.name, conf->min, unitspace, unit, conf->max, unitspace, unit))); return false; @@ -3203,7 +3203,7 @@ parse_and_validate_value(struct config_generic *record, ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - name, value), + conf->gen.name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); return false; } @@ -3222,7 +3222,7 @@ parse_and_validate_value(struct config_generic *record, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g%s%s .. %g%s%s)", newval->realval, unitspace, unit, - name, + conf->gen.name, conf->min, unitspace, unit, conf->max, unitspace, unit))); return false; @@ -3278,7 +3278,7 @@ parse_and_validate_value(struct config_generic *record, ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for parameter \"%s\": \"%s\"", - name, value), + conf->gen.name, value), hintmsg ? errhint("%s", _(hintmsg)) : 0)); if (hintmsg) @@ -3324,10 +3324,12 @@ parse_and_validate_value(struct config_generic *record, * * Return value: * +1: the value is valid and was successfully applied. - * 0: the name or value is invalid (but see below). - * -1: the value was not applied because of context, priority, or changeVal. + * 0: the name or value is invalid, or it's invalid to try to set + * this GUC now; but elevel was less than ERROR (see below). + * -1: no error detected, but the value was not applied, either + * because changeVal is false or there is some overriding setting. * - * If there is an error (non-existing option, invalid value) then an + * If there is an error (non-existing option, invalid value, etc) then an * ereport(ERROR) is thrown *unless* this is called for a source for which * we don't want an ERROR (currently, those are defaults, the config file, * and per-database or per-user settings, as well as callers who specify @@ -3390,8 +3392,11 @@ set_config_option_ext(const char *name, const char *value, /* - * set_config_with_handle: takes an optional 'handle' argument, which can be - * obtained by the caller from get_config_handle(). + * set_config_with_handle: sets option `name' to given value. + * + * This API adds the ability to pass a 'handle' argument, which can be + * obtained by the caller from get_config_handle(). NULL has no effect, + * but a non-null value avoids the need to search the GUC tables. * * This should be used by callers which repeatedly set the same config * option(s), and want to avoid the overhead of a hash lookup each time. @@ -3428,6 +3433,16 @@ set_config_with_handle(const char *name, config_handle *handle, elevel = ERROR; } + /* if handle is specified, no need to look up option */ + if (!handle) + { + record = find_option(name, true, false, elevel); + if (record == NULL) + return 0; + } + else + record = handle; + /* * GUC_ACTION_SAVE changes are acceptable during a parallel operation, * because the current worker will also pop the change. We're probably @@ -3435,25 +3450,19 @@ set_config_with_handle(const char *name, config_handle *handle, * body should observe the change, and peer workers do not share in the * execution of a function call started by this worker. * + * Also allow normal setting if the GUC is marked GUC_ALLOW_IN_PARALLEL. + * * Other changes might need to affect other workers, so forbid them. */ - if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE) + if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE && + (record->flags & GUC_ALLOW_IN_PARALLEL) == 0) { ereport(elevel, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("cannot set parameters during a parallel operation"))); - return -1; - } - - /* if handle is specified, no need to look up option */ - if (!handle) - { - record = find_option(name, true, false, elevel); - if (record == NULL) - return 0; + errmsg("parameter \"%s\" cannot be set during a parallel operation", + record->name))); + return 0; } - else - record = handle; /* * Check if the option can be set at this time. See guc.h for the precise @@ -3467,7 +3476,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed", - name))); + record->name))); return 0; } break; @@ -3490,7 +3499,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + record->name))); return 0; } break; @@ -3500,7 +3509,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed now", - name))); + record->name))); return 0; } @@ -3520,14 +3529,14 @@ set_config_with_handle(const char *name, config_handle *handle, */ AclResult aclresult; - aclresult = pg_parameter_aclcheck(name, srole, ACL_SET); + aclresult = pg_parameter_aclcheck(record->name, srole, ACL_SET); if (aclresult != ACLCHECK_OK) { /* No granted privilege */ ereport(elevel, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to set parameter \"%s\"", - name))); + record->name))); return 0; } } @@ -3569,7 +3578,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be set after connection start", - name))); + record->name))); return 0; } break; @@ -3582,14 +3591,14 @@ set_config_with_handle(const char *name, config_handle *handle, */ AclResult aclresult; - aclresult = pg_parameter_aclcheck(name, srole, ACL_SET); + aclresult = pg_parameter_aclcheck(record->name, srole, ACL_SET); if (aclresult != ACLCHECK_OK) { /* No granted privilege */ ereport(elevel, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to set parameter \"%s\"", - name))); + record->name))); return 0; } } @@ -3628,7 +3637,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot set parameter \"%s\" within security-definer function", - name))); + record->name))); return 0; } if (InSecurityRestrictedOperation()) @@ -3636,7 +3645,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("cannot set parameter \"%s\" within security-restricted operation", - name))); + record->name))); return 0; } } @@ -3648,7 +3657,7 @@ set_config_with_handle(const char *name, config_handle *handle, { ereport(elevel, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("parameter \"%s\" cannot be reset", name))); + errmsg("parameter \"%s\" cannot be reset", record->name))); return 0; } if (action == GUC_ACTION_SAVE) @@ -3656,7 +3665,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("parameter \"%s\" cannot be set locally in functions", - name))); + record->name))); return 0; } } @@ -3682,7 +3691,7 @@ set_config_with_handle(const char *name, config_handle *handle, if (changeVal && !makeDefault) { elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority", - name); + record->name); return -1; } changeVal = false; @@ -3701,7 +3710,7 @@ set_config_with_handle(const char *name, config_handle *handle, if (value) { - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, source, elevel, &newval_union, &newextra)) return 0; @@ -3734,7 +3743,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + conf->gen.name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3799,7 +3808,7 @@ set_config_with_handle(const char *name, config_handle *handle, if (value) { - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, source, elevel, &newval_union, &newextra)) return 0; @@ -3832,7 +3841,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + conf->gen.name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3897,7 +3906,7 @@ set_config_with_handle(const char *name, config_handle *handle, if (value) { - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, source, elevel, &newval_union, &newextra)) return 0; @@ -3930,7 +3939,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + conf->gen.name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -3990,12 +3999,15 @@ set_config_with_handle(const char *name, config_handle *handle, case PGC_STRING: { struct config_string *conf = (struct config_string *) record; + GucContext orig_context = context; + GucSource orig_source = source; + Oid orig_srole = srole; #define newval (newval_union.stringval) if (value) { - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, source, elevel, &newval_union, &newextra)) return 0; @@ -4054,7 +4066,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + conf->gen.name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -4075,6 +4087,44 @@ set_config_with_handle(const char *name, config_handle *handle, set_guc_source(&conf->gen, source); conf->gen.scontext = context; conf->gen.srole = srole; + + /* + * Ugly hack: during SET session_authorization, forcibly + * do SET ROLE NONE with the same context/source/etc, so + * that the effects will have identical lifespan. This is + * required by the SQL spec, and it's not possible to do + * it within the variable's check hook or assign hook + * because our APIs for those don't pass enough info. + * However, don't do it if is_reload: in that case we + * expect that if "role" isn't supposed to be default, it + * has been or will be set by a separate reload action. + * + * Also, for the call from InitializeSessionUserId with + * source == PGC_S_OVERRIDE, use PGC_S_DYNAMIC_DEFAULT for + * "role"'s source, so that it's still possible to set + * "role" from pg_db_role_setting entries. (See notes in + * InitializeSessionUserId before changing this.) + * + * A fine point: for RESET session_authorization, we do + * "RESET role" not "SET ROLE NONE" (by passing down NULL + * rather than "none" for the value). This would have the + * same effects in typical cases, but if the reset value + * of "role" is not "none" it seems better to revert to + * that. + */ + if (!is_reload && + strcmp(conf->gen.name, "session_authorization") == 0) + (void) set_config_with_handle("role", NULL, + value ? "none" : NULL, + orig_context, + (orig_source == PGC_S_OVERRIDE) + ? PGC_S_DYNAMIC_DEFAULT + : orig_source, + orig_srole, + action, + true, + elevel, + false); } if (makeDefault) @@ -4124,7 +4174,7 @@ set_config_with_handle(const char *name, config_handle *handle, if (value) { - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, source, elevel, &newval_union, &newextra)) return 0; @@ -4157,7 +4207,7 @@ set_config_with_handle(const char *name, config_handle *handle, ereport(elevel, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed without restarting the server", - name))); + conf->gen.name))); return 0; } record->status &= ~GUC_PENDING_RESTART; @@ -4651,7 +4701,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) union config_var_val newval; void *newextra = NULL; - if (!parse_and_validate_value(record, name, value, + if (!parse_and_validate_value(record, value, PGC_S_FILE, ERROR, &newval, &newextra)) ereport(ERROR, @@ -4859,10 +4909,11 @@ init_custom_variable(const char *name, strcmp(name, "pljava.vmoptions") == 0)) context = PGC_SUSET; - gen = (struct config_generic *) guc_malloc(ERROR, sz); + /* As above, an OOM here is FATAL */ + gen = (struct config_generic *) guc_malloc(FATAL, sz); memset(gen, 0, sz); - gen->name = guc_strdup(ERROR, name); + gen->name = guc_strdup(FATAL, name); gen->context = context; gen->group = CUSTOM_OPTIONS; gen->short_desc = short_desc; @@ -5776,12 +5827,6 @@ can_skip_gucvar(struct config_generic *gconf) * mechanisms (if indeed they aren't compile-time constants). So we may * always skip these. * - * Role must be handled specially because its current value can be an - * invalid value (for instance, if someone dropped the role since we set - * it). So if we tried to serialize it normally, we might get a failure. - * We skip it here, and use another mechanism to ensure the worker has the - * right value. - * * For all other GUCs, we skip if the GUC has its compiled-in default * value (i.e., source == PGC_S_DEFAULT). On the leader side, this means * we don't send GUCs that have their default values, which typically @@ -5790,8 +5835,8 @@ can_skip_gucvar(struct config_generic *gconf) * comments in RestoreGUCState for more info. */ return gconf->context == PGC_POSTMASTER || - gconf->context == PGC_INTERNAL || gconf->source == PGC_S_DEFAULT || - strcmp(gconf->name, "role") == 0; + gconf->context == PGC_INTERNAL || + gconf->source == PGC_S_DEFAULT; } /* diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c index 9c9edd3d2f500..b9e26982abd90 100644 --- a/src/backend/utils/misc/guc_funcs.c +++ b/src/backend/utils/misc/guc_funcs.c @@ -5,7 +5,7 @@ * SQL commands and SQL-accessible functions related to GUC variables. * * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * Written by Peter Eisentraut . * * IDENTIFICATION diff --git a/src/backend/utils/misc/guc_internal.h b/src/backend/utils/misc/guc_internal.h index 9695dcd5b7dde..7e4c969989cc0 100644 --- a/src/backend/utils/misc/guc_internal.h +++ b/src/backend/utils/misc/guc_internal.h @@ -4,9 +4,9 @@ * Declarations shared between backend/utils/misc/guc.c and * backend/utils/misc/guc-file.l * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * - * src/include/utils/guc_internal.h + * src/backend/utils/misc/guc_internal.h *-------------------------------------------------------------------- */ #ifndef GUC_INTERNAL_H diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 6a623f5f3420f..f04bfedb2fd10 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -10,7 +10,7 @@ * their fields are intended to be constant, some fields change at runtime. * * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * Written by Peter Eisentraut . * * IDENTIFICATION @@ -20,6 +20,9 @@ */ #include "postgres.h" +#ifdef HAVE_COPYFILE_H +#include +#endif #include #include #ifdef HAVE_SYSLOG @@ -39,6 +42,7 @@ #include "catalog/namespace.h" #include "catalog/storage.h" #include "commands/async.h" +#include "commands/extension.h" #include "commands/event_trigger.h" #include "commands/tablespace.h" #include "commands/trigger.h" @@ -49,6 +53,7 @@ #include "jit/jit.h" #include "libpq/auth.h" #include "libpq/libpq.h" +#include "libpq/oauth.h" #include "libpq/scram.h" #include "nodes/queryjumble.h" #include "optimizer/cost.h" @@ -71,11 +76,15 @@ #include "replication/slot.h" #include "replication/slotsync.h" #include "replication/syncrep.h" +#include "storage/aio.h" #include "storage/bufmgr.h" #include "storage/bufpage.h" +#include "storage/copydir.h" +#include "storage/io_worker.h" #include "storage/large_object.h" #include "storage/pg_shmem.h" #include "storage/predicate.h" +#include "storage/procnumber.h" #include "storage/standby.h" #include "tcop/backend_startup.h" #include "tcop/tcopprot.h" @@ -474,6 +483,14 @@ static const struct config_enum_entry wal_compression_options[] = { {NULL, 0, false} }; +static const struct config_enum_entry file_copy_method_options[] = { + {"copy", FILE_COPY_METHOD_COPY, false}, +#if defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE) || defined(HAVE_COPY_FILE_RANGE) + {"clone", FILE_COPY_METHOD_CLONE, false}, +#endif + {NULL, 0, false} +}; + /* * Options for enum values stored in other modules */ @@ -493,6 +510,12 @@ bool Debug_print_parse = false; bool Debug_print_rewritten = false; bool Debug_pretty_print = true; +#ifdef DEBUG_NODE_TESTS_ENABLED +bool Debug_copy_parse_plan_trees; +bool Debug_write_read_parse_plan_trees; +bool Debug_raw_expression_coverage_test; +#endif + bool log_parser_stats = false; bool log_planner_stats = false; bool log_executor_stats = false; @@ -555,7 +578,7 @@ static int ssl_renegotiation_limit; */ int huge_pages = HUGE_PAGES_TRY; int huge_page_size; -static int huge_pages_status = HUGE_PAGES_UNKNOWN; +int huge_pages_status = HUGE_PAGES_UNKNOWN; /* * These variables are all dummies that don't do anything, except in some @@ -570,6 +593,7 @@ static char *server_encoding_string; static char *server_version_string; static int server_version_num; static char *debug_io_direct_string; +static char *restrict_nonsystem_relation_kind_string; #ifdef HAVE_SYSLOG #define DEFAULT_SYSLOG_FACILITY LOG_LOCAL0 @@ -674,9 +698,9 @@ const char *const config_group_names[] = [RESOURCES_MEM] = gettext_noop("Resource Usage / Memory"), [RESOURCES_DISK] = gettext_noop("Resource Usage / Disk"), [RESOURCES_KERNEL] = gettext_noop("Resource Usage / Kernel Resources"), - [RESOURCES_VACUUM_DELAY] = gettext_noop("Resource Usage / Cost-Based Vacuum Delay"), [RESOURCES_BGWRITER] = gettext_noop("Resource Usage / Background Writer"), - [RESOURCES_ASYNCHRONOUS] = gettext_noop("Resource Usage / Asynchronous Behavior"), + [RESOURCES_IO] = gettext_noop("Resource Usage / I/O"), + [RESOURCES_WORKER_PROCESSES] = gettext_noop("Resource Usage / Worker Processes"), [WAL_SETTINGS] = gettext_noop("Write-Ahead Log / Settings"), [WAL_CHECKPOINTS] = gettext_noop("Write-Ahead Log / Checkpoints"), [WAL_ARCHIVING] = gettext_noop("Write-Ahead Log / Archiving"), @@ -698,7 +722,10 @@ const char *const config_group_names[] = [PROCESS_TITLE] = gettext_noop("Reporting and Logging / Process Title"), [STATS_MONITORING] = gettext_noop("Statistics / Monitoring"), [STATS_CUMULATIVE] = gettext_noop("Statistics / Cumulative Query and Index Statistics"), - [AUTOVACUUM] = gettext_noop("Autovacuum"), + [VACUUM_AUTOVACUUM] = gettext_noop("Vacuuming / Automatic Vacuuming"), + [VACUUM_COST_DELAY] = gettext_noop("Vacuuming / Cost-Based Vacuum Delay"), + [VACUUM_DEFAULT] = gettext_noop("Vacuuming / Default Behavior"), + [VACUUM_FREEZING] = gettext_noop("Vacuuming / Freezing"), [CLIENT_CONN_STATEMENT] = gettext_noop("Client Connection Defaults / Statement Behavior"), [CLIENT_CONN_LOCALE] = gettext_noop("Client Connection Defaults / Locale and Formatting"), [CLIENT_CONN_PRELOAD] = gettext_noop("Client Connection Defaults / Shared Library Preloading"), @@ -979,6 +1006,16 @@ struct config_bool ConfigureNamesBool[] = true, NULL, NULL, NULL }, + { + {"enable_self_join_elimination", PGC_USERSET, QUERY_TUNING_METHOD, + gettext_noop("Enables removal of unique self-joins."), + NULL, + GUC_EXPLAIN + }, + &enable_self_join_elimination, + true, + NULL, NULL, NULL + }, { {"enable_group_by_reordering", PGC_USERSET, QUERY_TUNING_METHOD, gettext_noop("Enables reordering of GROUP BY keys."), @@ -989,6 +1026,16 @@ struct config_bool ConfigureNamesBool[] = true, NULL, NULL, NULL }, + { + {"enable_distinct_reordering", PGC_USERSET, QUERY_TUNING_METHOD, + gettext_noop("Enables reordering of DISTINCT pathkeys."), + NULL, + GUC_EXPLAIN + }, + &enable_distinct_reordering, + true, + NULL, NULL, NULL + }, { {"geqo", PGC_USERSET, QUERY_TUNING_GEQO, gettext_noop("Enables genetic query optimization."), @@ -1008,7 +1055,7 @@ struct config_bool ConfigureNamesBool[] = {"is_superuser", PGC_INTERNAL, UNGROUPED, gettext_noop("Shows whether the current user is a superuser."), NULL, - GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_ALLOW_IN_PARALLEL }, ¤t_role_is_superuser, false, @@ -1188,15 +1235,6 @@ struct config_bool ConfigureNamesBool[] = true, NULL, NULL, NULL }, - { - {"log_connections", PGC_SU_BACKEND, LOGGING_WHAT, - gettext_noop("Logs each successful connection."), - NULL - }, - &Log_connections, - false, - NULL, NULL, NULL - }, { {"trace_connection_negotiation", PGC_POSTMASTER, DEVELOPER_OPTIONS, gettext_noop("Logs details of pre-authentication connection handshake."), @@ -1294,6 +1332,59 @@ struct config_bool ConfigureNamesBool[] = false, NULL, NULL, NULL }, +#ifdef DEBUG_NODE_TESTS_ENABLED + { + {"debug_copy_parse_plan_trees", PGC_SUSET, DEVELOPER_OPTIONS, + gettext_noop("Set this to force all parse and plan trees to be passed through " + "copyObject(), to facilitate catching errors and omissions in " + "copyObject()."), + NULL, + GUC_NOT_IN_SAMPLE + }, + &Debug_copy_parse_plan_trees, +/* support for legacy compile-time setting */ +#ifdef COPY_PARSE_PLAN_TREES + true, +#else + false, +#endif + NULL, NULL, NULL + }, + { + {"debug_write_read_parse_plan_trees", PGC_SUSET, DEVELOPER_OPTIONS, + gettext_noop("Set this to force all parse and plan trees to be passed through " + "outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in " + "those modules."), + NULL, + GUC_NOT_IN_SAMPLE + }, + &Debug_write_read_parse_plan_trees, +/* support for legacy compile-time setting */ +#ifdef WRITE_READ_PARSE_PLAN_TREES + true, +#else + false, +#endif + NULL, NULL, NULL + }, + { + {"debug_raw_expression_coverage_test", PGC_SUSET, DEVELOPER_OPTIONS, + gettext_noop("Set this to force all raw parse trees for DML statements to be scanned " + "by raw_expression_tree_walker(), to facilitate catching errors and " + "omissions in that function."), + NULL, + GUC_NOT_IN_SAMPLE + }, + &Debug_raw_expression_coverage_test, +/* support for legacy compile-time setting */ +#ifdef RAW_EXPRESSION_COVERAGE_TEST + true, +#else + false, +#endif + NULL, NULL, NULL + }, +#endif /* DEBUG_NODE_TESTS_ENABLED */ { {"debug_print_parse", PGC_USERSET, LOGGING_WHAT, gettext_noop("Logs each query's parse tree."), @@ -1399,6 +1490,15 @@ struct config_bool ConfigureNamesBool[] = true, NULL, NULL, NULL }, + { + {"track_cost_delay_timing", PGC_SUSET, STATS_CUMULATIVE, + gettext_noop("Collects timing statistics for cost-based vacuum delay."), + NULL + }, + &track_cost_delay_timing, + false, + NULL, NULL, NULL + }, { {"track_io_timing", PGC_SUSET, STATS_CUMULATIVE, gettext_noop("Collects timing statistics for database I/O activity."), @@ -1429,7 +1529,7 @@ struct config_bool ConfigureNamesBool[] = }, { - {"autovacuum", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Starts the autovacuum subprocess."), NULL }, @@ -1501,6 +1601,15 @@ struct config_bool ConfigureNamesBool[] = false, NULL, NULL, NULL }, + { + {"log_lock_failures", PGC_SUSET, LOGGING_WHAT, + gettext_noop("Logs lock failures."), + NULL + }, + &log_lock_failures, + false, + NULL, NULL, NULL + }, { {"log_recovery_conflict_waits", PGC_SIGHUP, LOGGING_WHAT, gettext_noop("Logs standby recovery conflict waits."), @@ -1576,7 +1685,7 @@ struct config_bool ConfigureNamesBool[] = }, { {"row_security", PGC_USERSET, CLIENT_CONN_STATEMENT, - gettext_noop("Enable row security."), + gettext_noop("Enables row security."), gettext_noop("When enabled, row security will be applied to all users.") }, &row_security, @@ -1594,7 +1703,7 @@ struct config_bool ConfigureNamesBool[] = }, { {"array_nulls", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, - gettext_noop("Enable input of NULL elements in arrays."), + gettext_noop("Enables input of NULL elements in arrays."), gettext_noop("When turned on, unquoted NULL in an array input " "value means a null value; " "otherwise it is taken literally.") @@ -1621,7 +1730,7 @@ struct config_bool ConfigureNamesBool[] = }, { {"logging_collector", PGC_POSTMASTER, LOGGING_WHERE, - gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."), + gettext_noop("Start a subprocess to capture stderr, csvlog and/or jsonlog into log files."), NULL }, &Logging_collector, @@ -1638,7 +1747,6 @@ struct config_bool ConfigureNamesBool[] = NULL, NULL, NULL }, -#ifdef TRACE_SORT { {"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS, gettext_noop("Emit information about resource usage in sorting."), @@ -1649,7 +1757,6 @@ struct config_bool ConfigureNamesBool[] = false, NULL, NULL, NULL }, -#endif #ifdef TRACE_SYNCSCAN /* this is undocumented because not exposed in a standard build */ @@ -1670,7 +1777,7 @@ struct config_bool ConfigureNamesBool[] = { { "optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD, - gettext_noop("Enable bounded sorting using heap sort."), + gettext_noop("Enables bounded sorting using heap sort."), NULL, GUC_NOT_IN_SAMPLE | GUC_EXPLAIN }, @@ -1747,7 +1854,7 @@ struct config_bool ConfigureNamesBool[] = { {"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, - gettext_noop("Enable synchronized sequential scans."), + gettext_noop("Enables synchronized sequential scans."), NULL }, &synchronize_seqscans, @@ -1893,7 +2000,7 @@ struct config_bool ConfigureNamesBool[] = }, { - {"parallel_leader_participation", PGC_USERSET, RESOURCES_ASYNCHRONOUS, + {"parallel_leader_participation", PGC_USERSET, RESOURCES_WORKER_PROCESSES, gettext_noop("Controls whether Gather and Gather Merge also run subplans."), gettext_noop("Should gather nodes also run subplans or just gather tuples?"), GUC_EXPLAIN @@ -2011,13 +2118,31 @@ struct config_bool ConfigureNamesBool[] = { {"sync_replication_slots", PGC_SIGHUP, REPLICATION_STANDBY, - gettext_noop("Enables a physical standby to synchronize logical failover slots from the primary server."), + gettext_noop("Enables a physical standby to synchronize logical failover replication slots from the primary server."), }, &sync_replication_slots, false, NULL, NULL, NULL }, + { + {"md5_password_warnings", PGC_USERSET, CONN_AUTH_AUTH, + gettext_noop("Enables deprecation warnings for MD5 passwords."), + }, + &md5_password_warnings, + true, + NULL, NULL, NULL + }, + + { + {"vacuum_truncate", PGC_USERSET, VACUUM_DEFAULT, + gettext_noop("Enables vacuum to truncate empty pages at the end of the table."), + }, + &vacuum_truncate, + true, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL @@ -2031,7 +2156,7 @@ struct config_int ConfigureNamesInt[] = {"archive_timeout", PGC_SIGHUP, WAL_ARCHIVING, gettext_noop("Sets the amount of time to wait before forcing a " "switch to the next WAL file."), - NULL, + gettext_noop("0 disables the timeout."), GUC_UNIT_S }, &XLogArchiveTimeout, @@ -2108,7 +2233,7 @@ struct config_int ConfigureNamesInt[] = { {"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO, gettext_noop("GEQO: number of individuals in the population."), - gettext_noop("Zero selects a suitable default value."), + gettext_noop("0 means use a suitable default value."), GUC_EXPLAIN }, &Geqo_pool_size, @@ -2118,7 +2243,7 @@ struct config_int ConfigureNamesInt[] = { {"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO, gettext_noop("GEQO: number of iterations of the algorithm."), - gettext_noop("Zero selects a suitable default value."), + gettext_noop("0 means use a suitable default value."), GUC_EXPLAIN }, &Geqo_generations, @@ -2141,7 +2266,7 @@ struct config_int ConfigureNamesInt[] = { {"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY, gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."), - NULL, + gettext_noop("-1 means wait forever."), GUC_UNIT_MS }, &max_standby_archive_delay, @@ -2152,7 +2277,7 @@ struct config_int ConfigureNamesInt[] = { {"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY, gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."), - NULL, + gettext_noop("-1 means wait forever."), GUC_UNIT_MS }, &max_standby_streaming_delay, @@ -2185,7 +2310,7 @@ struct config_int ConfigureNamesInt[] = { {"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY, gettext_noop("Sets the maximum wait time to receive data from the sending server."), - NULL, + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &wal_receiver_timeout, @@ -2276,7 +2401,7 @@ struct config_int ConfigureNamesInt[] = { {"shared_memory_size_in_huge_pages", PGC_INTERNAL, PRESET_OPTIONS, gettext_noop("Shows the number of huge pages needed for the main shared memory area."), - gettext_noop("-1 indicates that the value could not be determined."), + gettext_noop("-1 means huge pages are not supported."), GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED }, &shared_memory_size_in_huge_pages, @@ -2298,7 +2423,7 @@ struct config_int ConfigureNamesInt[] = { {"commit_timestamp_buffers", PGC_POSTMASTER, RESOURCES_MEM, gettext_noop("Sets the size of the dedicated buffer pool used for the commit timestamp cache."), - gettext_noop("Specify 0 to have this value determined as a fraction of shared_buffers."), + gettext_noop("0 means use a fraction of \"shared_buffers\"."), GUC_UNIT_BLOCKS }, &commit_timestamp_buffers, @@ -2352,8 +2477,8 @@ struct config_int ConfigureNamesInt[] = { {"subtransaction_buffers", PGC_POSTMASTER, RESOURCES_MEM, - gettext_noop("Sets the size of the dedicated buffer pool used for the sub-transaction cache."), - gettext_noop("Specify 0 to have this value determined as a fraction of shared_buffers."), + gettext_noop("Sets the size of the dedicated buffer pool used for the subtransaction cache."), + gettext_noop("0 means use a fraction of \"shared_buffers\"."), GUC_UNIT_BLOCKS }, &subtransaction_buffers, @@ -2364,7 +2489,7 @@ struct config_int ConfigureNamesInt[] = { {"transaction_buffers", PGC_POSTMASTER, RESOURCES_MEM, gettext_noop("Sets the size of the dedicated buffer pool used for the transaction status cache."), - gettext_noop("Specify 0 to have this value determined as a fraction of shared_buffers."), + gettext_noop("0 means use a fraction of \"shared_buffers\"."), GUC_UNIT_BLOCKS }, &transaction_buffers, @@ -2450,6 +2575,11 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + /* + * Dynamic shared memory has a higher overhead than local memory contexts, + * so when testing low-memory scenarios that could use shared memory, the + * recommended minimum is 1MB. + */ { {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum memory to be used for maintenance operations."), @@ -2457,7 +2587,7 @@ struct config_int ConfigureNamesInt[] = GUC_UNIT_KB }, &maintenance_work_mem, - 65536, 1024, MAX_KILOBYTES, + 65536, 64, MAX_KILOBYTES, NULL, NULL, NULL }, @@ -2501,7 +2631,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY, + {"vacuum_cost_page_hit", PGC_USERSET, VACUUM_COST_DELAY, gettext_noop("Vacuum cost for a page found in the buffer cache."), NULL }, @@ -2511,7 +2641,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY, + {"vacuum_cost_page_miss", PGC_USERSET, VACUUM_COST_DELAY, gettext_noop("Vacuum cost for a page not found in the buffer cache."), NULL }, @@ -2521,7 +2651,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY, + {"vacuum_cost_page_dirty", PGC_USERSET, VACUUM_COST_DELAY, gettext_noop("Vacuum cost for a page dirtied by vacuum."), NULL }, @@ -2531,7 +2661,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY, + {"vacuum_cost_limit", PGC_USERSET, VACUUM_COST_DELAY, gettext_noop("Vacuum cost amount available before napping."), NULL }, @@ -2541,9 +2671,9 @@ struct config_int ConfigureNamesInt[] = }, { - {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_vacuum_cost_limit", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Vacuum cost amount available before napping, for autovacuum."), - NULL + gettext_noop("-1 means use \"vacuum_cost_limit\".") }, &autovacuum_vac_cost_limit, -1, -1, 10000, @@ -2552,7 +2682,7 @@ struct config_int ConfigureNamesInt[] = { {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL, - gettext_noop("Sets the maximum number of simultaneously open files for each server process."), + gettext_noop("Sets the maximum number of files each server process is allowed to open simultaneously."), NULL }, &max_files_per_process, @@ -2599,7 +2729,7 @@ struct config_int ConfigureNamesInt[] = { {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed duration of any statement."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &StatementTimeout, @@ -2610,7 +2740,7 @@ struct config_int ConfigureNamesInt[] = { {"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed duration of any wait for a lock."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &LockTimeout, @@ -2621,7 +2751,7 @@ struct config_int ConfigureNamesInt[] = { {"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed idle time between queries, when in a transaction."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &IdleInTransactionSessionTimeout, @@ -2632,7 +2762,7 @@ struct config_int ConfigureNamesInt[] = { {"transaction_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &TransactionTimeout, @@ -2643,7 +2773,7 @@ struct config_int ConfigureNamesInt[] = { {"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed idle time between queries, when not in a transaction."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("0 disables the timeout."), GUC_UNIT_MS }, &IdleSessionTimeout, @@ -2652,7 +2782,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_freeze_min_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Minimum age at which VACUUM should freeze a table row."), NULL }, @@ -2662,7 +2792,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_freeze_table_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."), NULL }, @@ -2672,7 +2802,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_multixact_freeze_min_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."), NULL }, @@ -2682,7 +2812,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_multixact_freeze_table_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."), NULL }, @@ -2692,7 +2822,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"vacuum_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_failsafe_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Age at which VACUUM should trigger failsafe to avoid a wraparound outage."), NULL }, @@ -2701,7 +2831,7 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, { - {"vacuum_multixact_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT, + {"vacuum_multixact_failsafe_age", PGC_USERSET, VACUUM_FREEZING, gettext_noop("Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage."), NULL }, @@ -2857,7 +2987,7 @@ struct config_int ConfigureNamesInt[] = gettext_noop("Write a message to the server log if checkpoints " "caused by the filling of WAL segment files happen more " "frequently than this amount of time. " - "Zero turns off the warning."), + "0 disables the warning."), GUC_UNIT_S }, &CheckPointWarning, @@ -2868,7 +2998,7 @@ struct config_int ConfigureNamesInt[] = { {"checkpoint_flush_after", PGC_SIGHUP, WAL_CHECKPOINTS, gettext_noop("Number of pages after which previously performed writes are flushed to disk."), - NULL, + gettext_noop("0 disables forced writeback."), GUC_UNIT_BLOCKS }, &checkpoint_flush_after, @@ -2879,7 +3009,7 @@ struct config_int ConfigureNamesInt[] = { {"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS, gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."), - gettext_noop("Specify -1 to have this value determined as a fraction of shared_buffers."), + gettext_noop("-1 means use a fraction of \"shared_buffers\"."), GUC_UNIT_XBLOCKS }, &XLOGbuffers, @@ -2945,8 +3075,8 @@ struct config_int ConfigureNamesInt[] = {"max_slot_wal_keep_size", PGC_SIGHUP, REPLICATION_SENDING, gettext_noop("Sets the maximum WAL size that can be reserved by replication slots."), gettext_noop("Replication slots will be marked as failed, and segments released " - "for deletion or recycling, if this much space is occupied by WAL " - "on disk."), + "for deletion or recycling, if this much space is occupied by WAL on disk. " + "-1 means no maximum."), GUC_UNIT_MB }, &max_slot_wal_keep_size_mb, @@ -2965,6 +3095,18 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"idle_replication_slot_timeout", PGC_SIGHUP, REPLICATION_SENDING, + gettext_noop("Sets the duration a replication slot can remain idle before " + "it is invalidated."), + NULL, + GUC_UNIT_MIN + }, + &idle_replication_slot_timeout_mins, + 0, 0, INT_MAX / SECS_PER_MINUTE, + check_idle_replication_slot_timeout, NULL, NULL + }, + { {"commit_delay", PGC_SUSET, WAL_SETTINGS, gettext_noop("Sets the delay in microseconds between transaction commit and " @@ -3005,8 +3147,8 @@ struct config_int ConfigureNamesInt[] = {"log_min_duration_sample", PGC_SUSET, LOGGING_WHEN, gettext_noop("Sets the minimum execution time above which " "a sample of statements will be logged." - " Sampling is determined by log_statement_sample_rate."), - gettext_noop("Zero logs a sample of all queries. -1 turns this feature off."), + " Sampling is determined by \"log_statement_sample_rate\"."), + gettext_noop("-1 disables sampling. 0 means sample all statements."), GUC_UNIT_MS }, &log_min_duration_sample, @@ -3018,7 +3160,7 @@ struct config_int ConfigureNamesInt[] = {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN, gettext_noop("Sets the minimum execution time above which " "all statements will be logged."), - gettext_noop("Zero prints all queries. -1 turns this feature off."), + gettext_noop("-1 disables logging statement durations. 0 means log all statement durations."), GUC_UNIT_MS }, &log_min_duration_statement, @@ -3030,7 +3172,7 @@ struct config_int ConfigureNamesInt[] = {"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT, gettext_noop("Sets the minimum execution time above which " "autovacuum actions will be logged."), - gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."), + gettext_noop("-1 disables logging autovacuum actions. 0 means log all autovacuum actions."), GUC_UNIT_MS }, &Log_autovacuum_min_duration, @@ -3042,7 +3184,7 @@ struct config_int ConfigureNamesInt[] = {"log_parameter_max_length", PGC_SUSET, LOGGING_WHAT, gettext_noop("Sets the maximum length in bytes of data logged for bind " "parameter values when logging statements."), - gettext_noop("-1 to print values in full."), + gettext_noop("-1 means log values in full."), GUC_UNIT_BYTE }, &log_parameter_max_length, @@ -3054,7 +3196,7 @@ struct config_int ConfigureNamesInt[] = {"log_parameter_max_length_on_error", PGC_USERSET, LOGGING_WHAT, gettext_noop("Sets the maximum length in bytes of data logged for bind " "parameter values when logging statements, on error."), - gettext_noop("-1 to print values in full."), + gettext_noop("-1 means log values in full."), GUC_UNIT_BYTE }, &log_parameter_max_length_on_error, @@ -3076,7 +3218,7 @@ struct config_int ConfigureNamesInt[] = { {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES_BGWRITER, gettext_noop("Background writer maximum number of LRU pages to flush per round."), - NULL + gettext_noop("0 disables background writing.") }, &bgwriter_lru_maxpages, 100, 0, INT_MAX / 2, /* Same upper limit as shared_buffers */ @@ -3086,7 +3228,7 @@ struct config_int ConfigureNamesInt[] = { {"bgwriter_flush_after", PGC_SIGHUP, RESOURCES_BGWRITER, gettext_noop("Number of pages after which previously performed writes are flushed to disk."), - NULL, + gettext_noop("0 disables forced writeback."), GUC_UNIT_BLOCKS }, &bgwriter_flush_after, @@ -3097,50 +3239,88 @@ struct config_int ConfigureNamesInt[] = { {"effective_io_concurrency", PGC_USERSET, - RESOURCES_ASYNCHRONOUS, + RESOURCES_IO, gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."), - NULL, + gettext_noop("0 disables simultaneous requests."), GUC_EXPLAIN }, &effective_io_concurrency, DEFAULT_EFFECTIVE_IO_CONCURRENCY, 0, MAX_IO_CONCURRENCY, - check_effective_io_concurrency, NULL, NULL + NULL, NULL, NULL }, { {"maintenance_io_concurrency", PGC_USERSET, - RESOURCES_ASYNCHRONOUS, + RESOURCES_IO, gettext_noop("A variant of \"effective_io_concurrency\" that is used for maintenance work."), - NULL, + gettext_noop("0 disables simultaneous requests."), GUC_EXPLAIN }, &maintenance_io_concurrency, DEFAULT_MAINTENANCE_IO_CONCURRENCY, 0, MAX_IO_CONCURRENCY, - check_maintenance_io_concurrency, assign_maintenance_io_concurrency, + NULL, assign_maintenance_io_concurrency, NULL }, + { + {"io_max_combine_limit", + PGC_POSTMASTER, + RESOURCES_IO, + gettext_noop("Server-wide limit that clamps io_combine_limit."), + NULL, + GUC_UNIT_BLOCKS + }, + &io_max_combine_limit, + DEFAULT_IO_COMBINE_LIMIT, + 1, MAX_IO_COMBINE_LIMIT, + NULL, assign_io_max_combine_limit, NULL + }, + { {"io_combine_limit", PGC_USERSET, - RESOURCES_ASYNCHRONOUS, + RESOURCES_IO, gettext_noop("Limit on the size of data reads and writes."), NULL, GUC_UNIT_BLOCKS }, - &io_combine_limit, + &io_combine_limit_guc, DEFAULT_IO_COMBINE_LIMIT, 1, MAX_IO_COMBINE_LIMIT, + NULL, assign_io_combine_limit, NULL + }, + + { + {"io_max_concurrency", + PGC_POSTMASTER, + RESOURCES_IO, + gettext_noop("Max number of IOs that one process can execute simultaneously."), + NULL, + }, + &io_max_concurrency, + -1, -1, 1024, + check_io_max_concurrency, NULL, NULL + }, + + { + {"io_workers", + PGC_SIGHUP, + RESOURCES_IO, + gettext_noop("Number of IO worker processes, for io_method=worker."), + NULL, + }, + &io_workers, + 3, 1, MAX_IO_WORKERS, NULL, NULL, NULL }, { - {"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS, + {"backend_flush_after", PGC_USERSET, RESOURCES_IO, gettext_noop("Number of pages after which previously performed writes are flushed to disk."), - NULL, + gettext_noop("0 disables forced writeback."), GUC_UNIT_BLOCKS }, &backend_flush_after, @@ -3151,7 +3331,7 @@ struct config_int ConfigureNamesInt[] = { {"max_worker_processes", PGC_POSTMASTER, - RESOURCES_ASYNCHRONOUS, + RESOURCES_WORKER_PROCESSES, gettext_noop("Maximum number of concurrent worker processes."), NULL, }, @@ -3196,11 +3376,23 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"max_active_replication_origins", + PGC_POSTMASTER, + REPLICATION_SUBSCRIBERS, + gettext_noop("Sets the maximum number of active replication origins."), + NULL + }, + &max_active_replication_origins, + 10, 0, MAX_BACKENDS, + NULL, NULL, NULL + }, + { {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Sets the amount of time to wait before forcing " "log file rotation."), - NULL, + gettext_noop("0 disables time-based creation of new log files."), GUC_UNIT_MIN }, &Log_RotationAge, @@ -3212,11 +3404,11 @@ struct config_int ConfigureNamesInt[] = {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Sets the maximum size a log file can reach before " "being rotated."), - NULL, + gettext_noop("0 disables size-based creation of new log files."), GUC_UNIT_KB }, &Log_RotationSize, - 10 * 1024, 0, INT_MAX / 1024, + 10 * 1024, 0, INT_MAX, NULL, NULL, NULL }, @@ -3314,7 +3506,7 @@ struct config_int ConfigureNamesInt[] = { {"wal_summary_keep_time", PGC_SIGHUP, WAL_SUMMARIZATION, gettext_noop("Time for which WAL summary files should be kept."), - NULL, + gettext_noop("0 disables automatic summary file deletion."), GUC_UNIT_MIN, }, &wal_summary_keep_time, @@ -3325,7 +3517,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_naptime", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Time to sleep between autovacuum runs."), NULL, GUC_UNIT_S @@ -3335,7 +3527,7 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, { - {"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_vacuum_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."), NULL }, @@ -3344,16 +3536,25 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, { - {"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, AUTOVACUUM, - gettext_noop("Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums."), - NULL + {"autovacuum_vacuum_max_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Maximum number of tuple updates or deletes prior to vacuum."), + gettext_noop("-1 disables the maximum threshold.") + }, + &autovacuum_vac_max_thresh, + 100000000, -1, INT_MAX, + NULL, NULL, NULL + }, + { + {"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, + gettext_noop("Minimum number of tuple inserts prior to vacuum."), + gettext_noop("-1 disables insert vacuums.") }, &autovacuum_vac_ins_thresh, 1000, -1, INT_MAX, NULL, NULL, NULL }, { - {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_analyze_threshold", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."), NULL }, @@ -3363,7 +3564,7 @@ struct config_int ConfigureNamesInt[] = }, { /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */ - {"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM, + {"autovacuum_freeze_max_age", PGC_POSTMASTER, VACUUM_AUTOVACUUM, gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."), NULL }, @@ -3375,7 +3576,7 @@ struct config_int ConfigureNamesInt[] = }, { /* see multixact.c for why this is PGC_POSTMASTER not PGC_SIGHUP */ - {"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM, + {"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, VACUUM_AUTOVACUUM, gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."), NULL }, @@ -3385,7 +3586,16 @@ struct config_int ConfigureNamesInt[] = }, { /* see max_connections */ - {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM, + {"autovacuum_worker_slots", PGC_POSTMASTER, VACUUM_AUTOVACUUM, + gettext_noop("Sets the number of backend slots to allocate for autovacuum workers."), + NULL + }, + &autovacuum_worker_slots, + 16, 1, MAX_BACKENDS, + NULL, NULL, NULL + }, + { + {"autovacuum_max_workers", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."), NULL }, @@ -3395,17 +3605,17 @@ struct config_int ConfigureNamesInt[] = }, { - {"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS, + {"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_WORKER_PROCESSES, gettext_noop("Sets the maximum number of parallel processes per maintenance operation."), NULL }, &max_parallel_maintenance_workers, - 2, 0, 1024, + 2, 0, MAX_PARALLEL_WORKER_LIMIT, NULL, NULL, NULL }, { - {"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_ASYNCHRONOUS, + {"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_WORKER_PROCESSES, gettext_noop("Sets the maximum number of parallel processes per executor node."), NULL, GUC_EXPLAIN @@ -3416,7 +3626,7 @@ struct config_int ConfigureNamesInt[] = }, { - {"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS, + {"max_parallel_workers", PGC_USERSET, RESOURCES_WORKER_PROCESSES, gettext_noop("Sets the maximum number of parallel workers that can be active at one time."), NULL, GUC_EXPLAIN @@ -3429,7 +3639,7 @@ struct config_int ConfigureNamesInt[] = { {"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM, gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."), - NULL, + gettext_noop("-1 means use \"maintenance_work_mem\"."), GUC_UNIT_KB }, &autovacuum_work_mem, @@ -3440,7 +3650,7 @@ struct config_int ConfigureNamesInt[] = { {"tcp_keepalives_idle", PGC_USERSET, CONN_AUTH_TCP, gettext_noop("Time between issuing TCP keepalives."), - gettext_noop("A value of 0 uses the system default."), + gettext_noop("0 means use the system default."), GUC_UNIT_S }, &tcp_keepalives_idle, @@ -3451,7 +3661,7 @@ struct config_int ConfigureNamesInt[] = { {"tcp_keepalives_interval", PGC_USERSET, CONN_AUTH_TCP, gettext_noop("Time between TCP keepalive retransmits."), - gettext_noop("A value of 0 uses the system default."), + gettext_noop("0 means use the system default."), GUC_UNIT_S }, &tcp_keepalives_interval, @@ -3474,8 +3684,8 @@ struct config_int ConfigureNamesInt[] = {"tcp_keepalives_count", PGC_USERSET, CONN_AUTH_TCP, gettext_noop("Maximum number of TCP keepalive retransmits."), gettext_noop("Number of consecutive keepalive retransmits that can be " - "lost before a connection is considered dead. A value of 0 uses the " - "system default."), + "lost before a connection is considered dead. " + "0 means use the system default."), }, &tcp_keepalives_count, 0, 0, INT_MAX, @@ -3485,8 +3695,7 @@ struct config_int ConfigureNamesInt[] = { {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER, gettext_noop("Sets the maximum allowed result for exact search by GIN."), - NULL, - 0 + gettext_noop("0 means no limit."), }, &GinFuzzySearchLimit, 0, 0, INT_MAX, @@ -3542,7 +3751,7 @@ struct config_int ConfigureNamesInt[] = { {"log_temp_files", PGC_SUSET, LOGGING_WHAT, gettext_noop("Log the use of temporary files larger than this number of kilobytes."), - gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."), + gettext_noop("-1 disables logging temporary files. 0 means log all temporary files."), GUC_UNIT_KB }, &log_temp_files, @@ -3575,7 +3784,7 @@ struct config_int ConfigureNamesInt[] = { {"tcp_user_timeout", PGC_USERSET, CONN_AUTH_TCP, gettext_noop("TCP user timeout."), - gettext_noop("A value of 0 uses the system default."), + gettext_noop("0 means use the system default."), GUC_UNIT_MS }, &tcp_user_timeout, @@ -3586,7 +3795,7 @@ struct config_int ConfigureNamesInt[] = { {"huge_page_size", PGC_POSTMASTER, RESOURCES_MEM, gettext_noop("The size of huge page that should be requested."), - NULL, + gettext_noop("0 means use the system default."), GUC_UNIT_KB }, &huge_page_size, @@ -3597,7 +3806,7 @@ struct config_int ConfigureNamesInt[] = { {"debug_discard_caches", PGC_SUSET, DEVELOPER_OPTIONS, gettext_noop("Aggressively flush system caches for debugging purposes."), - NULL, + gettext_noop("0 means use normal caching behavior."), GUC_NOT_IN_SAMPLE }, &debug_discard_caches, @@ -3620,7 +3829,7 @@ struct config_int ConfigureNamesInt[] = { {"client_connection_check_interval", PGC_USERSET, CONN_AUTH_TCP, gettext_noop("Sets the time interval between checks for disconnection while running queries."), - NULL, + gettext_noop("0 disables connection checks."), GUC_UNIT_MS }, &client_connection_check_interval, @@ -3632,7 +3841,7 @@ struct config_int ConfigureNamesInt[] = {"log_startup_progress_interval", PGC_SIGHUP, LOGGING_WHEN, gettext_noop("Time between progress updates for " "long-running startup operations."), - gettext_noop("0 turns this feature off."), + gettext_noop("0 disables progress updates."), GUC_UNIT_MS, }, &log_startup_progress_interval, @@ -3850,7 +4059,7 @@ struct config_real ConfigureNamesReal[] = }, { - {"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY, + {"vacuum_cost_delay", PGC_USERSET, VACUUM_COST_DELAY, gettext_noop("Vacuum cost delay in milliseconds."), NULL, GUC_UNIT_MS @@ -3861,9 +4070,9 @@ struct config_real ConfigureNamesReal[] = }, { - {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."), - NULL, + gettext_noop("-1 means use \"vacuum_cost_delay\"."), GUC_UNIT_MS }, &autovacuum_vac_cost_delay, @@ -3872,7 +4081,7 @@ struct config_real ConfigureNamesReal[] = }, { - {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_vacuum_scale_factor", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."), NULL }, @@ -3882,7 +4091,7 @@ struct config_real ConfigureNamesReal[] = }, { - {"autovacuum_vacuum_insert_scale_factor", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_vacuum_insert_scale_factor", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Number of tuple inserts prior to vacuum as a fraction of reltuples."), NULL }, @@ -3892,7 +4101,7 @@ struct config_real ConfigureNamesReal[] = }, { - {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM, + {"autovacuum_analyze_scale_factor", PGC_SIGHUP, VACUUM_AUTOVACUUM, gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."), NULL }, @@ -3932,6 +4141,16 @@ struct config_real ConfigureNamesReal[] = NULL, NULL, NULL }, + { + {"vacuum_max_eager_freeze_failure_rate", PGC_USERSET, VACUUM_FREEZING, + gettext_noop("Fraction of pages in a relation vacuum can scan and fail to freeze before disabling eager scanning."), + gettext_noop("A value of 0.0 disables eager scanning and a value of 1.0 will eagerly scan up to 100 percent of the all-visible pages in the relation. If vacuum successfully freezes these pages, the cap is lower than 100 percent, because the goal is to amortize page freezing across multiple vacuums.") + }, + &vacuum_max_eager_freeze_failure_rate, + 0.03, 0.0, 1.0, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, 0.0, 0.0, 0.0, NULL, NULL, NULL @@ -3944,7 +4163,7 @@ struct config_string ConfigureNamesString[] = { {"archive_command", PGC_SIGHUP, WAL_ARCHIVING, gettext_noop("Sets the shell command that will be called to archive a WAL file."), - gettext_noop("This is used only if \"archive_library\" is not set.") + gettext_noop("An empty string means use \"archive_library\".") }, &XLogArchiveCommand, "", @@ -3954,7 +4173,7 @@ struct config_string ConfigureNamesString[] = { {"archive_library", PGC_SIGHUP, WAL_ARCHIVING, gettext_noop("Sets the library that will be called to archive a WAL file."), - gettext_noop("An empty string indicates that \"archive_command\" should be used.") + gettext_noop("An empty string means use \"archive_command\".") }, &XLogArchiveLibrary, "", @@ -4082,7 +4301,7 @@ struct config_string ConfigureNamesString[] = { {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT, gettext_noop("Controls information prefixed to each log line."), - gettext_noop("If blank, no prefix is used.") + gettext_noop("An empty string means no prefix.") }, &Log_line_prefix, "%m [%p] ", @@ -4125,7 +4344,7 @@ struct config_string ConfigureNamesString[] = { {"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the default tablespace to create tables and indexes in."), - gettext_noop("An empty string selects the database's default tablespace."), + gettext_noop("An empty string means use the database's default tablespace."), GUC_IS_NAME }, &default_tablespace, @@ -4136,7 +4355,7 @@ struct config_string ConfigureNamesString[] = { {"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."), - NULL, + gettext_noop("An empty string means use the database's default tablespace."), GUC_LIST_INPUT | GUC_LIST_QUOTE }, &temp_tablespaces, @@ -4148,7 +4367,7 @@ struct config_string ConfigureNamesString[] = {"createrole_self_grant", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets whether a CREATEROLE user automatically grants " "the role to themselves, and with which options."), - NULL, + gettext_noop("An empty string disables automatic self grants."), GUC_LIST_INPUT }, &createrole_self_grant, @@ -4170,6 +4389,18 @@ struct config_string ConfigureNamesString[] = NULL, NULL, NULL }, + { + {"extension_control_path", PGC_SUSET, CLIENT_CONN_OTHER, + gettext_noop("Sets the path for extension control files."), + gettext_noop("The remaining extension script and secondary control files are then loaded " + "from the same directory where the primary control file was found."), + GUC_SUPERUSER_ONLY + }, + &Extension_control_path, + "$system", + NULL, NULL, NULL + }, + { {"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_AUTH, gettext_noop("Sets the location of the Kerberos server key file."), @@ -4184,7 +4415,7 @@ struct config_string ConfigureNamesString[] = { {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS, gettext_noop("Sets the Bonjour service name."), - NULL + gettext_noop("An empty string means use the computer name.") }, &bonjour_name, "", @@ -4194,7 +4425,7 @@ struct config_string ConfigureNamesString[] = { {"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE, gettext_noop("Sets the language in which messages are displayed."), - NULL + gettext_noop("An empty string means use the operating system setting.") }, &locale_messages, "", @@ -4204,7 +4435,7 @@ struct config_string ConfigureNamesString[] = { {"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE, gettext_noop("Sets the locale for formatting monetary amounts."), - NULL + gettext_noop("An empty string means use the operating system setting.") }, &locale_monetary, "C", @@ -4214,7 +4445,7 @@ struct config_string ConfigureNamesString[] = { {"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE, gettext_noop("Sets the locale for formatting numbers."), - NULL + gettext_noop("An empty string means use the operating system setting.") }, &locale_numeric, "C", @@ -4224,7 +4455,7 @@ struct config_string ConfigureNamesString[] = { {"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE, gettext_noop("Sets the locale for formatting date and time values."), - NULL + gettext_noop("An empty string means use the operating system setting.") }, &locale_time, "C", @@ -4268,7 +4499,7 @@ struct config_string ConfigureNamesString[] = {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the schema search order for names that are not schema-qualified."), NULL, - GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_EXPLAIN + GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_EXPLAIN | GUC_REPORT }, &namespace_search_path, "\"$user\", public", @@ -4402,8 +4633,8 @@ struct config_string ConfigureNamesString[] = { {"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS, gettext_noop("Sets the owning group of the Unix-domain socket."), - gettext_noop("The owning user of the socket is always the user " - "that starts the server.") + gettext_noop("The owning user of the socket is always the user that starts the server. " + "An empty string means use the user's default group.") }, &Unix_socket_group, "", @@ -4577,13 +4808,24 @@ struct config_string ConfigureNamesString[] = check_default_text_search_config, assign_default_text_search_config, NULL }, + { + {"ssl_tls13_ciphers", PGC_SIGHUP, CONN_AUTH_SSL, + gettext_noop("Sets the list of allowed TLSv1.3 cipher suites."), + gettext_noop("An empty string means use the default cipher suites."), + GUC_SUPERUSER_ONLY + }, + &SSLCipherSuites, + "", + NULL, NULL, NULL + }, + { {"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL, - gettext_noop("Sets the list of allowed SSL ciphers."), + gettext_noop("Sets the list of allowed TLSv1.2 (and lower) ciphers."), NULL, GUC_SUPERUSER_ONLY }, - &SSLCipherSuites, + &SSLCipherList, #ifdef USE_OPENSSL "HIGH:MEDIUM:+3DES:!aNULL", #else @@ -4593,14 +4835,14 @@ struct config_string ConfigureNamesString[] = }, { - {"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SSL, - gettext_noop("Sets the curve to use for ECDH."), - NULL, + {"ssl_groups", PGC_SIGHUP, CONN_AUTH_SSL, + gettext_noop("Sets the group(s) to use for Diffie-Hellman key exchange."), + gettext_noop("Multiple groups can be specified using colon-separated list."), GUC_SUPERUSER_ONLY }, &SSLECDHCurve, #ifdef USE_SSL - "prime256v1", + "X25519:prime256v1", #else "none", #endif @@ -4610,7 +4852,7 @@ struct config_string ConfigureNamesString[] = { {"ssl_dh_params_file", PGC_SIGHUP, CONN_AUTH_SSL, gettext_noop("Location of the SSL DH parameters file."), - NULL, + gettext_noop("An empty string means use compiled-in default parameters."), GUC_SUPERUSER_ONLY }, &ssl_dh_params_file, @@ -4621,7 +4863,7 @@ struct config_string ConfigureNamesString[] = { {"ssl_passphrase_command", PGC_SIGHUP, CONN_AUTH_SSL, gettext_noop("Command to obtain passphrases for SSL."), - NULL, + gettext_noop("An empty string means use the built-in prompting mechanism."), GUC_SUPERUSER_ONLY }, &ssl_passphrase_command, @@ -4687,7 +4929,7 @@ struct config_string ConfigureNamesString[] = { {"debug_io_direct", PGC_POSTMASTER, DEVELOPER_OPTIONS, gettext_noop("Use direct I/O for file access."), - NULL, + gettext_noop("An empty string disables direct I/O."), GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE }, &debug_io_direct_string, @@ -4697,11 +4939,11 @@ struct config_string ConfigureNamesString[] = { {"synchronized_standby_slots", PGC_SIGHUP, REPLICATION_PRIMARY, - gettext_noop("Lists streaming replication standby server slot " + gettext_noop("Lists streaming replication standby server replication slot " "names that logical WAL sender processes will wait for."), gettext_noop("Logical WAL sender processes will send decoded " - "changes to plugins only after the specified " - "replication slots confirm receiving WAL."), + "changes to output plugins only after the specified " + "replication slots have confirmed receiving WAL."), GUC_LIST_INPUT }, &synchronized_standby_slots, @@ -4709,6 +4951,40 @@ struct config_string ConfigureNamesString[] = check_synchronized_standby_slots, assign_synchronized_standby_slots, NULL }, + { + {"restrict_nonsystem_relation_kind", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Prohibits access to non-system relations of specified kinds."), + NULL, + GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE + }, + &restrict_nonsystem_relation_kind_string, + "", + check_restrict_nonsystem_relation_kind, assign_restrict_nonsystem_relation_kind, NULL + }, + + { + {"oauth_validator_libraries", PGC_SIGHUP, CONN_AUTH_AUTH, + gettext_noop("Lists libraries that may be called to validate OAuth v2 bearer tokens."), + NULL, + GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY + }, + &oauth_validator_libraries_string, + "", + NULL, NULL, NULL + }, + + { + {"log_connections", PGC_SU_BACKEND, LOGGING_WHAT, + gettext_noop("Logs specified aspects of connection establishment and setup."), + NULL, + GUC_LIST_INPUT + }, + &log_connections_string, + "", + check_log_connections, assign_log_connections, NULL + }, + + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL @@ -4978,6 +5254,16 @@ struct config_enum ConfigureNamesEnum[] = NULL, NULL, NULL }, + { + {"file_copy_method", PGC_USERSET, RESOURCES_DISK, + gettext_noop("Selects the file copy method."), + NULL + }, + &file_copy_method, + FILE_COPY_METHOD_COPY, file_copy_method_options, + NULL, NULL, NULL + }, + { {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS, gettext_noop("Selects the method used for forcing WAL updates to disk."), @@ -5122,6 +5408,16 @@ struct config_enum ConfigureNamesEnum[] = NULL, NULL, NULL }, + { + {"io_method", PGC_POSTMASTER, RESOURCES_IO, + gettext_noop("Selects the method for executing asynchronous I/O."), + NULL + }, + &io_method, + DEFAULT_IO_METHOD, io_method_options, + NULL, assign_io_method, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL diff --git a/src/backend/utils/misc/help_config.c b/src/backend/utils/misc/help_config.c index 4729a19a132f6..55c36ddf051d5 100644 --- a/src/backend/utils/misc/help_config.c +++ b/src/backend/utils/misc/help_config.c @@ -7,7 +7,7 @@ * or GUC_DISALLOW_IN_FILE are not displayed, unless the user specifically * requests that variable by name * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/misc/help_config.c diff --git a/src/backend/utils/misc/injection_point.c b/src/backend/utils/misc/injection_point.c index 80bc32b0e08ed..f58ebc8ee522d 100644 --- a/src/backend/utils/misc/injection_point.c +++ b/src/backend/utils/misc/injection_point.c @@ -6,7 +6,7 @@ * Injection points can be used to run arbitrary code by attaching callbacks * that would be executed in place of the named injection point. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -17,6 +17,10 @@ */ #include "postgres.h" +#include "utils/injection_point.h" + +#ifdef USE_INJECTION_POINTS + #include #include "fmgr.h" @@ -25,11 +29,8 @@ #include "storage/lwlock.h" #include "storage/shmem.h" #include "utils/hsearch.h" -#include "utils/injection_point.h" #include "utils/memutils.h" -#ifdef USE_INJECTION_POINTS - /* Field sizes */ #define INJ_NAME_MAXLEN 64 #define INJ_LIB_MAXLEN 128 @@ -59,7 +60,7 @@ typedef struct InjectionPointEntry */ pg_atomic_uint64 generation; - char name[INJ_NAME_MAXLEN]; /* hash key */ + char name[INJ_NAME_MAXLEN]; /* point name */ char library[INJ_LIB_MAXLEN]; /* library */ char function[INJ_FUNC_MAXLEN]; /* function */ @@ -315,8 +316,7 @@ InjectionPointAttach(const char *name, if (free_idx == -1) free_idx = idx; } - - if (strcmp(entry->name, name) == 0) + else if (strcmp(entry->name, name) == 0) elog(ERROR, "injection point \"%s\" already defined", name); } if (free_idx == -1) @@ -541,14 +541,14 @@ InjectionPointLoad(const char *name) * Execute an injection point, if defined. */ void -InjectionPointRun(const char *name) +InjectionPointRun(const char *name, void *arg) { #ifdef USE_INJECTION_POINTS InjectionPointCacheEntry *cache_entry; cache_entry = InjectionPointCacheRefresh(name); if (cache_entry) - cache_entry->callback(name, cache_entry->private_data); + cache_entry->callback(name, cache_entry->private_data, arg); #else elog(ERROR, "Injection points are not supported by this build"); #endif @@ -558,14 +558,14 @@ InjectionPointRun(const char *name) * Execute an injection point directly from the cache, if defined. */ void -InjectionPointCached(const char *name) +InjectionPointCached(const char *name, void *arg) { #ifdef USE_INJECTION_POINTS InjectionPointCacheEntry *cache_entry; cache_entry = injection_point_cache_get(name); if (cache_entry) - cache_entry->callback(name, cache_entry->private_data); + cache_entry->callback(name, cache_entry->private_data, arg); #else elog(ERROR, "Injection points are not supported by this build"); #endif diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build index 6669502205224..9e389a00d0576 100644 --- a/src/backend/utils/misc/meson.build +++ b/src/backend/utils/misc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'conffiles.c', @@ -14,6 +14,7 @@ backend_sources += files( 'queryenvironment.c', 'rls.c', 'sampling.c', + 'stack_depth.c', 'superuser.c', 'timeout.c', 'tzparser.c', diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c index 2af47e1244faa..e64e6758c9319 100644 --- a/src/backend/utils/misc/pg_config.c +++ b/src/backend/utils/misc/pg_config.c @@ -3,7 +3,7 @@ * pg_config.c * Expose same output as pg_config except as an SRF * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -17,7 +17,6 @@ #include "common/config_info.h" #include "funcapi.h" #include "miscadmin.h" -#include "port.h" #include "utils/builtins.h" Datum diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index 98c932dc7bd64..6d036e3bf3280 100644 --- a/src/backend/utils/misc/pg_controldata.c +++ b/src/backend/utils/misc/pg_controldata.c @@ -5,7 +5,7 @@ * Routines to expose the contents of the control data file via * a set of SQL functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -203,8 +203,8 @@ pg_control_recovery(PG_FUNCTION_ARGS) Datum pg_control_init(PG_FUNCTION_ARGS) { - Datum values[11]; - bool nulls[11]; + Datum values[12]; + bool nulls[12]; TupleDesc tupdesc; HeapTuple htup; ControlFileData *ControlFile; @@ -254,6 +254,9 @@ pg_control_init(PG_FUNCTION_ARGS) values[10] = Int32GetDatum(ControlFile->data_checksum_version); nulls[10] = false; + values[11] = BoolGetDatum(ControlFile->default_char_signedness); + nulls[11] = false; + htup = heap_form_tuple(tupdesc, values, nulls); PG_RETURN_DATUM(HeapTupleGetDatum(htup)); diff --git a/src/backend/utils/misc/pg_rusage.c b/src/backend/utils/misc/pg_rusage.c index d3810cce0694e..feac22b37a9ca 100644 --- a/src/backend/utils/misc/pg_rusage.c +++ b/src/backend/utils/misc/pg_rusage.c @@ -4,7 +4,7 @@ * Resource usage measurement support routines. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 9ec9f97e926dc..341f88adc87b2 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -21,7 +21,7 @@ # require a server shutdown and restart to take effect. # # Any parameter can also be given as a command-line option to the server, e.g., -# "postgres -c log_connections=on". Some parameters can be changed at run time +# "postgres -c log_connections=all". Some parameters can be changed at run time # with the "SET" SQL command. # # Memory units: B = bytes Time units: us = microseconds @@ -96,6 +96,8 @@ #authentication_timeout = 1min # 1s-600s #password_encryption = scram-sha-256 # scram-sha-256 or md5 #scram_iterations = 4096 +#md5_password_warnings = on +#oauth_validator_libraries = '' # comma-separated list of trusted validator modules # GSSAPI using Kerberos #krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab' @@ -110,9 +112,10 @@ #ssl_crl_file = '' #ssl_crl_dir = '' #ssl_key_file = 'server.key' -#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers +#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed TLSv1.2 ciphers +#ssl_tls13_ciphers = '' # allowed TLSv1.3 cipher suites, blank for default #ssl_prefer_server_ciphers = on -#ssl_ecdh_curve = 'prime256v1' +#ssl_groups = 'X25519:prime256v1' #ssl_min_protocol_version = 'TLSv1.2' #ssl_max_protocol_version = '' #ssl_dh_params_file = '' @@ -139,8 +142,8 @@ # you actively intend to use prepared transactions. #work_mem = 4MB # min 64kB #hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem -#maintenance_work_mem = 64MB # min 1MB -#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem +#maintenance_work_mem = 64MB # min 64kB +#autovacuum_work_mem = -1 # min 64kB, or -1 to use maintenance_work_mem #logical_decoding_work_mem = 64MB # min 64kB #max_stack_depth = 2MB # min 100kB #shared_memory_type = mmap # the default is the first option @@ -175,6 +178,8 @@ #temp_file_limit = -1 # limits per-process temp file space # in kilobytes, or -1 for no limit +#file_copy_method = copy # copy, clone (if supported by OS) + #max_notify_queue_pages = 1048576 # limits the number of SLRU pages allocated # for NOTIFY / LISTEN queue @@ -183,14 +188,6 @@ #max_files_per_process = 1000 # min 64 # (change requires restart) -# - Cost-Based Vacuum Delay - - -#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) -#vacuum_cost_page_hit = 1 # 0-10000 credits -#vacuum_cost_page_miss = 2 # 0-10000 credits -#vacuum_cost_page_dirty = 20 # 0-10000 credits -#vacuum_cost_limit = 200 # 1-10000 credits - # - Background Writer - #bgwriter_delay = 200ms # 10-10000ms between rounds @@ -198,12 +195,25 @@ #bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round #bgwriter_flush_after = 0 # measured in pages, 0 disables -# - Asynchronous Behavior - +# - I/O - #backend_flush_after = 0 # measured in pages, 0 disables -#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching -#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching -#io_combine_limit = 128kB # usually 1-32 blocks (depends on OS) +#effective_io_concurrency = 16 # 1-1000; 0 disables issuing multiple simultaneous IO requests +#maintenance_io_concurrency = 16 # 1-1000; same as effective_io_concurrency +#io_max_combine_limit = 128kB # usually 1-128 blocks (depends on OS) + # (change requires restart) +#io_combine_limit = 128kB # usually 1-128 blocks (depends on OS) + +#io_method = worker # worker, io_uring, sync + # (change requires restart) +#io_max_concurrency = -1 # Max number of IOs that one process + # can execute simultaneously + # -1 sets based on shared_buffers + # (change requires restart) +#io_workers = 3 # 1-32; + +# - Worker Processes - + #max_worker_processes = 8 # (change requires restart) #max_parallel_workers_per_gather = 2 # limited by max_parallel_workers #max_parallel_maintenance_workers = 2 # limited by max_parallel_workers @@ -332,6 +342,7 @@ # (change requires restart) #wal_keep_size = 0 # in megabytes; 0 disables #max_slot_wal_keep_size = -1 # in megabytes; -1 disables +#idle_replication_slot_timeout = 0 # in minutes; 0 disables #wal_sender_timeout = 60s # in milliseconds; 0 disables #track_commit_timestamp = off # collect timestamp of transaction commit # (change requires restart) @@ -379,6 +390,8 @@ # These settings are ignored on a publisher. +#max_active_replication_origins = 10 # max number of active replication origins + # (change requires restart) #max_logical_replication_workers = 4 # taken from max_worker_processes # (change requires restart) #max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers @@ -413,6 +426,8 @@ #enable_sort = on #enable_tidscan = on #enable_group_by_reordering = on +#enable_distinct_reordering = on +#enable_self_join_elimination = on # - Planner Cost Constants - @@ -576,9 +591,11 @@ # actions running at least this number # of milliseconds. #log_checkpoints = on -#log_connections = off +#log_connections = '' # log aspects of connection setup + # options include receipt, authentication, authorization, + # setup_durations, and all to log all of these aspects #log_disconnections = off -#log_duration = off +#log_duration = off # log statement duration #log_error_verbosity = default # terse, default, or verbose messages #log_hostname = off #log_line_prefix = '%m [%p] ' # special values: @@ -587,6 +604,7 @@ # %d = database name # %r = remote host and port # %h = remote host + # %L = local address # %b = backend type # %p = process ID # %P = process ID of parallel group leader @@ -606,6 +624,7 @@ # %% = '%' # e.g. '<%u%%%d> ' #log_lock_waits = off # log lock waits >= deadlock_timeout +#log_lock_failures = off # log lock failures #log_recovery_conflict_waits = off # log standby recovery conflict waits # >= deadlock_timeout #log_parameter_max_length = -1 # when logging statements, limit logged @@ -637,6 +656,7 @@ #track_activities = on #track_activity_query_size = 1024 # (change requires restart) #track_counts = on +#track_cost_delay_timing = off #track_io_timing = off #track_wal_io_timing = off #track_functions = none # none, pl, all @@ -653,13 +673,16 @@ #------------------------------------------------------------------------------ -# AUTOVACUUM +# VACUUMING #------------------------------------------------------------------------------ +# - Automatic Vacuuming - + #autovacuum = on # Enable autovacuum subprocess? 'on' # requires track_counts to also be on. -#autovacuum_max_workers = 3 # max number of autovacuum subprocesses +autovacuum_worker_slots = 16 # autovacuum worker slots to allocate # (change requires restart) +#autovacuum_max_workers = 3 # max number of autovacuum subprocesses #autovacuum_naptime = 1min # time between autovacuum runs #autovacuum_vacuum_threshold = 50 # min number of row updates before # vacuum @@ -669,9 +692,12 @@ #autovacuum_analyze_threshold = 50 # min number of row updates before # analyze #autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum -#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table - # size before insert vacuum +#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of unfrozen pages + # before insert vacuum #autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze +#autovacuum_vacuum_max_threshold = 100000000 # max number of row updates + # before vacuum; -1 disables max + # threshold #autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum # (change requires restart) #autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age @@ -684,6 +710,27 @@ # autovacuum, -1 means use # vacuum_cost_limit +# - Cost-Based Vacuum Delay - + +#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) +#vacuum_cost_page_hit = 1 # 0-10000 credits +#vacuum_cost_page_miss = 2 # 0-10000 credits +#vacuum_cost_page_dirty = 20 # 0-10000 credits +#vacuum_cost_limit = 200 # 1-10000 credits + +# - Default Behavior - + +#vacuum_truncate = on # enable truncation after vacuum + +# - Freezing - + +#vacuum_freeze_table_age = 150000000 +#vacuum_freeze_min_age = 50000000 +#vacuum_failsafe_age = 1600000000 +#vacuum_multixact_freeze_table_age = 150000000 +#vacuum_multixact_freeze_min_age = 5000000 +#vacuum_multixact_failsafe_age = 1600000000 +#vacuum_max_eager_freeze_failure_rate = 0.03 # 0 disables eager scanning #------------------------------------------------------------------------------ # CLIENT CONNECTION DEFAULTS @@ -718,12 +765,6 @@ #lock_timeout = 0 # in milliseconds, 0 is disabled #idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled #idle_session_timeout = 0 # in milliseconds, 0 is disabled -#vacuum_freeze_table_age = 150000000 -#vacuum_freeze_min_age = 50000000 -#vacuum_failsafe_age = 1600000000 -#vacuum_multixact_freeze_table_age = 150000000 -#vacuum_multixact_freeze_min_age = 5000000 -#vacuum_multixact_failsafe_age = 1600000000 #bytea_output = 'hex' # hex, escape #xmlbinary = 'base64' #xmloption = 'content' @@ -771,6 +812,7 @@ # - Other Defaults - #dynamic_library_path = '$libdir' +#extension_control_path = '$system' #gin_fuzzy_search_limit = 0 diff --git a/src/backend/utils/misc/ps_status.c b/src/backend/utils/misc/ps_status.c index 9da6377402024..e08b26e8c14f2 100644 --- a/src/backend/utils/misc/ps_status.c +++ b/src/backend/utils/misc/ps_status.c @@ -7,7 +7,7 @@ * * src/backend/utils/misc/ps_status.c * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * various details abducted from various places *-------------------------------------------------------------------- */ @@ -23,7 +23,9 @@ #include "utils/guc.h" #include "utils/ps_status.h" +#if !defined(WIN32) || defined(_MSC_VER) extern char **environ; +#endif /* GUC variable */ bool update_process_title = DEFAULT_UPDATE_PROCESS_TITLE; diff --git a/src/backend/utils/misc/queryenvironment.c b/src/backend/utils/misc/queryenvironment.c index 2b16e7a8c3c75..7bc72dabe6797 100644 --- a/src/backend/utils/misc/queryenvironment.c +++ b/src/backend/utils/misc/queryenvironment.c @@ -11,7 +11,7 @@ * on callers, since this is an opaque structure. This is the reason to * require a create function. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/rls.c b/src/backend/utils/misc/rls.c index 9947e3c2469ba..f5b4e45b84a96 100644 --- a/src/backend/utils/misc/rls.c +++ b/src/backend/utils/misc/rls.c @@ -3,7 +3,7 @@ * rls.c * RLS-related utility functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/sampling.c b/src/backend/utils/misc/sampling.c index 933db06702ccd..a26835ed20d6f 100644 --- a/src/backend/utils/misc/sampling.c +++ b/src/backend/utils/misc/sampling.c @@ -3,7 +3,7 @@ * sampling.c * Relation block sampling routines. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c new file mode 100644 index 0000000000000..8f7cf531fbc5f --- /dev/null +++ b/src/backend/utils/misc/stack_depth.c @@ -0,0 +1,201 @@ +/*------------------------------------------------------------------------- + * + * stack_depth.c + * Functions for monitoring and limiting process stack depth + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/utils/misc/stack_depth.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include + +#include "miscadmin.h" +#include "utils/guc_hooks.h" + + +/* GUC variable for maximum stack depth (measured in kilobytes) */ +int max_stack_depth = 100; + +/* max_stack_depth converted to bytes for speed of checking */ +static ssize_t max_stack_depth_bytes = 100 * (ssize_t) 1024; + +/* + * Stack base pointer -- initialized by set_stack_base(), which + * should be called from main(). + */ +static char *stack_base_ptr = NULL; + + +/* + * set_stack_base: set up reference point for stack depth checking + * + * Returns the old reference point, if any. + */ +pg_stack_base_t +set_stack_base(void) +{ +#ifndef HAVE__BUILTIN_FRAME_ADDRESS + char stack_base; +#endif + pg_stack_base_t old; + + old = stack_base_ptr; + + /* + * Set up reference point for stack depth checking. On recent gcc we use + * __builtin_frame_address() to avoid a warning about storing a local + * variable's address in a long-lived variable. + */ +#ifdef HAVE__BUILTIN_FRAME_ADDRESS + stack_base_ptr = __builtin_frame_address(0); +#else + stack_base_ptr = &stack_base; +#endif + + return old; +} + +/* + * restore_stack_base: restore reference point for stack depth checking + * + * This can be used after set_stack_base() to restore the old value. This + * is currently only used in PL/Java. When PL/Java calls a backend function + * from different thread, the thread's stack is at a different location than + * the main thread's stack, so it sets the base pointer before the call, and + * restores it afterwards. + */ +void +restore_stack_base(pg_stack_base_t base) +{ + stack_base_ptr = base; +} + + +/* + * check_stack_depth/stack_is_too_deep: check for excessively deep recursion + * + * This should be called someplace in any recursive routine that might possibly + * recurse deep enough to overflow the stack. Most Unixen treat stack + * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves + * before hitting the hardware limit. + * + * check_stack_depth() just throws an error summarily. stack_is_too_deep() + * can be used by code that wants to handle the error condition itself. + */ +void +check_stack_depth(void) +{ + if (stack_is_too_deep()) + { + ereport(ERROR, + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), + errmsg("stack depth limit exceeded"), + errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), " + "after ensuring the platform's stack depth limit is adequate.", + max_stack_depth))); + } +} + +bool +stack_is_too_deep(void) +{ + char stack_top_loc; + ssize_t stack_depth; + + /* + * Compute distance from reference point to my local variables + */ + stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc); + + /* + * Take abs value, since stacks grow up on some machines, down on others + */ + if (stack_depth < 0) + stack_depth = -stack_depth; + + /* + * Trouble? + * + * The test on stack_base_ptr prevents us from erroring out if called + * before that's been set. Logically it should be done first, but putting + * it last avoids wasting cycles during normal cases. + */ + if (stack_depth > max_stack_depth_bytes && + stack_base_ptr != NULL) + return true; + + return false; +} + + +/* GUC check hook for max_stack_depth */ +bool +check_max_stack_depth(int *newval, void **extra, GucSource source) +{ + ssize_t newval_bytes = *newval * (ssize_t) 1024; + ssize_t stack_rlimit = get_stack_depth_rlimit(); + + if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP) + { + GUC_check_errdetail("\"max_stack_depth\" must not exceed %zdkB.", + (stack_rlimit - STACK_DEPTH_SLOP) / 1024); + GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."); + return false; + } + return true; +} + +/* GUC assign hook for max_stack_depth */ +void +assign_max_stack_depth(int newval, void *extra) +{ + ssize_t newval_bytes = newval * (ssize_t) 1024; + + max_stack_depth_bytes = newval_bytes; +} + +/* + * Obtain platform stack depth limit (in bytes) + * + * Return -1 if unknown + * + * Note: we choose to use ssize_t not size_t as the result type because + * callers compute values that could theoretically go negative, + * such as "result - STACK_DEPTH_SLOP". + */ +ssize_t +get_stack_depth_rlimit(void) +{ +#if defined(HAVE_GETRLIMIT) + static ssize_t val = 0; + + /* This won't change after process launch, so check just once */ + if (val == 0) + { + struct rlimit rlim; + + if (getrlimit(RLIMIT_STACK, &rlim) < 0) + val = -1; + else if (rlim.rlim_cur == RLIM_INFINITY) + val = SSIZE_MAX; + /* rlim_cur is probably of an unsigned type, so check for overflow */ + else if (rlim.rlim_cur >= SSIZE_MAX) + val = SSIZE_MAX; + else + val = rlim.rlim_cur; + } + return val; +#else + /* On Windows we set the backend stack size in src/backend/Makefile */ + return WIN32_STACK_RLIMIT; +#endif +} diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c index 1490326a1580a..5858b0af64cdf 100644 --- a/src/backend/utils/misc/superuser.c +++ b/src/backend/utils/misc/superuser.c @@ -9,7 +9,7 @@ * the single-user case works. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/timeout.c b/src/backend/utils/misc/timeout.c index ec7e570920a5d..d92efa12550ae 100644 --- a/src/backend/utils/misc/timeout.c +++ b/src/backend/utils/misc/timeout.c @@ -3,7 +3,7 @@ * timeout.c * Routines to multiplex SIGALRM interrupts for multiple timeout reasons. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/backend/utils/misc/tzparser.c b/src/backend/utils/misc/tzparser.c index 96cc3912e56ad..6aaf7395ba852 100644 --- a/src/backend/utils/misc/tzparser.c +++ b/src/backend/utils/misc/tzparser.c @@ -11,7 +11,7 @@ * PG_TRY if necessary. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/mmgr/alignedalloc.c b/src/backend/utils/mmgr/alignedalloc.c index c266fb3dbb148..7eea695de62c5 100644 --- a/src/backend/utils/mmgr/alignedalloc.c +++ b/src/backend/utils/mmgr/alignedalloc.c @@ -8,7 +8,7 @@ * operations such as pfree() and repalloc() to work correctly on a memory * chunk that was allocated by palloc_aligned(). * - * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/mmgr/alignedalloc.c @@ -45,6 +45,7 @@ AlignedAllocFree(void *pointer) GetMemoryChunkContext(unaligned)->name, chunk); #endif + /* Recursively pfree the unaligned chunk */ pfree(unaligned); } @@ -96,18 +97,32 @@ AlignedAllocRealloc(void *pointer, Size size, int flags) Assert(old_size >= redirchunk->requested_size); #endif + /* + * To keep things simple, we always allocate a new aligned chunk and copy + * data into it. Because of the above inaccuracy, this may end in copying + * more data than was in the original allocation request size, but that + * should be OK. + */ ctx = GetMemoryChunkContext(unaligned); newptr = MemoryContextAllocAligned(ctx, size, alignto, flags); - /* - * We may memcpy beyond the end of the original allocation request size, - * so we must mark the entire allocation as defined. - */ - if (likely(newptr != NULL)) + /* Cope cleanly with OOM */ + if (unlikely(newptr == NULL)) { - VALGRIND_MAKE_MEM_DEFINED(pointer, old_size); - memcpy(newptr, pointer, Min(size, old_size)); + VALGRIND_MAKE_MEM_NOACCESS(redirchunk, sizeof(MemoryChunk)); + return MemoryContextAllocationFailure(ctx, size, flags); } + + /* + * We may memcpy more than the original allocation request size, which + * would result in trying to copy trailing bytes that the original + * MemoryContextAllocAligned call marked NOACCESS. So we must mark the + * entire old_size as defined. That's slightly annoying, but probably not + * worth improving. + */ + VALGRIND_MAKE_MEM_DEFINED(pointer, old_size); + memcpy(newptr, pointer, Min(size, old_size)); + pfree(unaligned); return newptr; diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index dede30dd86a94..666ecd8f78d0e 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -7,7 +7,7 @@ * type. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/mmgr/bump.c b/src/backend/utils/mmgr/bump.c index c60c9c131e395..f7a37d1b3e86c 100644 --- a/src/backend/utils/mmgr/bump.c +++ b/src/backend/utils/mmgr/bump.c @@ -12,7 +12,7 @@ * only way to release memory allocated by this context type is to reset or * delete the context. * - * Portions Copyright (c) 2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/mmgr/bump.c @@ -316,7 +316,7 @@ BumpAllocLarge(MemoryContext context, Size size, int flags) block = (BumpBlock *) malloc(blksize); if (block == NULL) - return NULL; + return MemoryContextAllocationFailure(context, size, flags); context->mem_allocated += blksize; diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c index 2d4639a63622f..17d4f7a7a06e1 100644 --- a/src/backend/utils/mmgr/dsa.c +++ b/src/backend/utils/mmgr/dsa.c @@ -39,7 +39,7 @@ * empty and be returned to the free page manager, and whole segments can * become empty and be returned to the operating system. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/mmgr/freepage.c b/src/backend/utils/mmgr/freepage.c index 294280256771f..52fa78dc58612 100644 --- a/src/backend/utils/mmgr/freepage.c +++ b/src/backend/utils/mmgr/freepage.c @@ -42,7 +42,7 @@ * where memory fragmentation is very severe, only a tiny fraction of * the pages under management are consumed by this btree. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c index 0238c111d2fa9..18679ad4f1e41 100644 --- a/src/backend/utils/mmgr/generation.c +++ b/src/backend/utils/mmgr/generation.c @@ -6,7 +6,7 @@ * Generation is a custom MemoryContext implementation designed for cases of * chunks with similar lifespan. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/mmgr/generation.c diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index bde54326c6604..15fa4d0a55eeb 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -9,7 +9,7 @@ * context's MemoryContextMethods struct. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -285,31 +285,31 @@ MemoryContextTraverseNext(MemoryContext curr, MemoryContext top) static void BogusFree(void *pointer) { - elog(ERROR, "pfree called with invalid pointer %p (header 0x%016llx)", - pointer, (unsigned long long) GetMemoryChunkHeader(pointer)); + elog(ERROR, "pfree called with invalid pointer %p (header 0x%016" PRIx64 ")", + pointer, GetMemoryChunkHeader(pointer)); } static void * BogusRealloc(void *pointer, Size size, int flags) { - elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016llx)", - pointer, (unsigned long long) GetMemoryChunkHeader(pointer)); + elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016" PRIx64 ")", + pointer, GetMemoryChunkHeader(pointer)); return NULL; /* keep compiler quiet */ } static MemoryContext BogusGetChunkContext(void *pointer) { - elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016llx)", - pointer, (unsigned long long) GetMemoryChunkHeader(pointer)); + elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016" PRIx64 ")", + pointer, GetMemoryChunkHeader(pointer)); return NULL; /* keep compiler quiet */ } static Size BogusGetChunkSpace(void *pointer) { - elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016llx)", - pointer, (unsigned long long) GetMemoryChunkHeader(pointer)); + elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016" PRIx64 ")", + pointer, GetMemoryChunkHeader(pointer)); return 0; /* keep compiler quiet */ } @@ -834,7 +834,7 @@ MemoryContextStatsDetail(MemoryContext context, memset(&grand_totals, 0, sizeof(grand_totals)); - MemoryContextStatsInternal(context, 0, max_level, max_children, + MemoryContextStatsInternal(context, 1, max_level, max_children, &grand_totals, print_to_stderr); if (print_to_stderr) @@ -886,7 +886,7 @@ MemoryContextStatsInternal(MemoryContext context, int level, /* Examine the context itself */ context->methods->stats(context, MemoryContextStatsPrint, - (void *) &level, + &level, totals, print_to_stderr); /* @@ -899,7 +899,7 @@ MemoryContextStatsInternal(MemoryContext context, int level, */ child = context->firstchild; ichild = 0; - if (level < max_level && !stack_is_too_deep()) + if (level <= max_level && !stack_is_too_deep()) { for (; child != NULL && ichild < max_children; child = child->nextchild, ichild++) @@ -928,7 +928,7 @@ MemoryContextStatsInternal(MemoryContext context, int level, if (print_to_stderr) { - for (int i = 0; i <= level; i++) + for (int i = 0; i < level; i++) fprintf(stderr, " "); fprintf(stderr, "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n", @@ -1029,7 +1029,7 @@ MemoryContextStatsPrint(MemoryContext context, void *passthru, if (print_to_stderr) { - for (i = 0; i < level; i++) + for (i = 1; i < level; i++) fprintf(stderr, " "); fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident); } @@ -1106,6 +1106,10 @@ MemoryContextCreate(MemoryContext node, /* Creating new memory contexts is not allowed in a critical section */ Assert(CritSectionCount == 0); + /* Validate parent, to help prevent crazy context linkages */ + Assert(parent == NULL || MemoryContextIsValid(parent)); + Assert(node != parent); + /* Initialize all standard fields of memory context header */ node->type = tag; node->isReset = true; @@ -1356,7 +1360,8 @@ palloc0(Size size) context->isReset = false; ret = context->methods->alloc(context, size, 0); - + /* We expect OOM to be handled by the alloc function */ + Assert(ret != NULL); VALGRIND_MEMPOOL_ALLOC(context, ret, size); MemSetAligned(ret, 0, size); @@ -1379,6 +1384,8 @@ palloc_extended(Size size, int flags) ret = context->methods->alloc(context, size, flags); if (unlikely(ret == NULL)) { + /* NULL can be returned only when using MCXT_ALLOC_NO_OOM */ + Assert(flags & MCXT_ALLOC_NO_OOM); return NULL; } diff --git a/src/backend/utils/mmgr/memdebug.c b/src/backend/utils/mmgr/memdebug.c index 1d30c01c7fb15..42f19aa8b21b9 100644 --- a/src/backend/utils/mmgr/memdebug.c +++ b/src/backend/utils/mmgr/memdebug.c @@ -5,7 +5,7 @@ * public API of the memory management subsystem. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/utils/mmgr/memdebug.c diff --git a/src/backend/utils/mmgr/meson.build b/src/backend/utils/mmgr/meson.build index dd43a6844c7c9..2addccf00def1 100644 --- a/src/backend/utils/mmgr/meson.build +++ b/src/backend/utils/mmgr/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'alignedalloc.c', diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 4a246135377a9..0be1c2b0fff85 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -8,7 +8,7 @@ * doesn't actually run the executor for them. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -1150,6 +1150,9 @@ pg_cursor(PG_FUNCTION_ARGS) /* report only "visible" entries */ if (!portal->visible) continue; + /* also ignore it if PortalDefineQuery hasn't been called yet */ + if (!portal->sourceText) + continue; values[0] = CStringGetTextDatum(portal->name); values[1] = CStringGetTextDatum(portal->sourceText); diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c index 3e15d59683f86..d32c0d318fbf4 100644 --- a/src/backend/utils/mmgr/slab.c +++ b/src/backend/utils/mmgr/slab.c @@ -8,7 +8,7 @@ * with minimal memory wastage and fragmentation. * * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/mmgr/slab.c @@ -601,8 +601,8 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags) * want to avoid that. */ pg_noinline +pg_noreturn static void -pg_attribute_noreturn() SlabAllocInvalidSize(MemoryContext context, Size size) { SlabContext *slab = (SlabContext *) context; diff --git a/src/backend/utils/postprocess_dtrace.sed b/src/backend/utils/postprocess_dtrace.sed index 193a10454a544..842eb17baad3d 100644 --- a/src/backend/utils/postprocess_dtrace.sed +++ b/src/backend/utils/postprocess_dtrace.sed @@ -1,7 +1,7 @@ #------------------------------------------------------------------------- # sed script to postprocess dtrace output # -# Copyright (c) 2008-2024, PostgreSQL Global Development Group +# Copyright (c) 2008-2025, PostgreSQL Global Development Group # # src/backend/utils/postprocess_dtrace.sed #------------------------------------------------------------------------- diff --git a/src/backend/utils/probes.d b/src/backend/utils/probes.d index d7725443774c1..e9e413477ba46 100644 --- a/src/backend/utils/probes.d +++ b/src/backend/utils/probes.d @@ -1,7 +1,7 @@ /* ---------- * DTrace probes for PostgreSQL backend * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/backend/utils/probes.d * ---------- diff --git a/src/backend/utils/resowner/meson.build b/src/backend/utils/resowner/meson.build index 6eda7044adc8a..3d7f914825f33 100644 --- a/src/backend/utils/resowner/meson.build +++ b/src/backend/utils/resowner/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'resowner.c' diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index 505534ee8d336..d39f3e1b655cd 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -34,7 +34,7 @@ * or reassigning locks from a resource owner to its parent. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -47,6 +47,8 @@ #include "common/hashfn.h" #include "common/int.h" +#include "lib/ilist.h" +#include "storage/aio.h" #include "storage/ipc.h" #include "storage/predicate.h" #include "storage/proc.h" @@ -155,6 +157,12 @@ struct ResourceOwnerData /* The local locks cache. */ LOCALLOCK *locks[MAX_RESOWNER_LOCKS]; /* list of owned locks */ + + /* + * AIO handles need be registered in critical sections and therefore + * cannot use the normal ResourceElem mechanism. + */ + dlist_head aio_handles; }; @@ -425,6 +433,8 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name) parent->firstchild = owner; } + dlist_init(&owner->aio_handles); + return owner; } @@ -725,6 +735,13 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, * so issue warnings. In the abort case, just clean up quietly. */ ResourceOwnerReleaseAll(owner, phase, isCommit); + + while (!dlist_is_empty(&owner->aio_handles)) + { + dlist_node *node = dlist_head_node(&owner->aio_handles); + + pgaio_io_release_resowner(node, !isCommit); + } } else if (phase == RESOURCE_RELEASE_LOCKS) { @@ -1082,3 +1099,15 @@ ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock) elog(ERROR, "lock reference %p is not owned by resource owner %s", locallock, owner->name); } + +void +ResourceOwnerRememberAioHandle(ResourceOwner owner, struct dlist_node *ioh_node) +{ + dlist_push_tail(&owner->aio_handles, ioh_node); +} + +void +ResourceOwnerForgetAioHandle(ResourceOwner owner, struct dlist_node *ioh_node) +{ + dlist_delete_from(&owner->aio_handles, ioh_node); +} diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c index 44b30e86adf47..e529ceb8260bb 100644 --- a/src/backend/utils/sort/logtape.c +++ b/src/backend/utils/sort/logtape.c @@ -66,7 +66,7 @@ * There will always be the same number of runs as input tapes, and the same * number of input tapes as participants (worker Tuplesortstates). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -263,8 +263,8 @@ ltsWriteBlock(LogicalTapeSet *lts, int64 blocknum, const void *buffer) if (BufFileSeekBlock(lts->pfile, blocknum) != 0) ereport(ERROR, (errcode_for_file_access(), - errmsg("could not seek to block %lld of temporary file", - (long long) blocknum))); + errmsg("could not seek to block %" PRId64 " of temporary file", + blocknum))); BufFileWrite(lts->pfile, buffer, BLCKSZ); /* Update nBlocksWritten, if we extended the file */ @@ -284,8 +284,8 @@ ltsReadBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer) if (BufFileSeekBlock(lts->pfile, blocknum) != 0) ereport(ERROR, (errcode_for_file_access(), - errmsg("could not seek to block %lld of temporary file", - (long long) blocknum))); + errmsg("could not seek to block %" PRId64 " of temporary file", + blocknum))); BufFileReadExact(lts->pfile, buffer, BLCKSZ); } @@ -1100,10 +1100,10 @@ LogicalTapeBackspace(LogicalTape *lt, size_t size) ltsReadBlock(lt->tapeSet, prev, lt->buffer); if (TapeBlockGetTrailer(lt->buffer)->next != lt->curBlockNumber) - elog(ERROR, "broken tape, next of block %lld is %lld, expected %lld", - (long long) prev, - (long long) (TapeBlockGetTrailer(lt->buffer)->next), - (long long) lt->curBlockNumber); + elog(ERROR, "broken tape, next of block %" PRId64 " is %" PRId64 ", expected %" PRId64, + prev, + TapeBlockGetTrailer(lt->buffer)->next, + lt->curBlockNumber); lt->nbytes = TapeBlockPayloadSize; lt->curBlockNumber = prev; diff --git a/src/backend/utils/sort/meson.build b/src/backend/utils/sort/meson.build index f1ae189693613..0743c56726252 100644 --- a/src/backend/utils/sort/meson.build +++ b/src/backend/utils/sort/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'logtape.c', diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c index 137476a7a7783..2f031c329094a 100644 --- a/src/backend/utils/sort/sharedtuplestore.c +++ b/src/backend/utils/sort/sharedtuplestore.c @@ -10,7 +10,7 @@ * scan where each backend reads an arbitrary subset of the tuples that were * written. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c index c8a75487a3a9f..e0f500b9aa29c 100644 --- a/src/backend/utils/sort/sortsupport.c +++ b/src/backend/utils/sort/sortsupport.c @@ -4,7 +4,7 @@ * Support routines for accelerated sorting. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -135,30 +135,30 @@ PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup) { Oid opfamily; Oid opcintype; - int16 strategy; + CompareType cmptype; Assert(ssup->comparator == NULL); /* Find the operator in pg_amop */ if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype, - &strategy)) + &cmptype)) elog(ERROR, "operator %u is not a valid ordering operator", orderingOp); - ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber); + ssup->ssup_reverse = (cmptype == COMPARE_GT); FinishSortSupportFunction(opfamily, opcintype, ssup); } /* - * Fill in SortSupport given an index relation, attribute, and strategy. + * Fill in SortSupport given an index relation and attribute. * * Caller must previously have zeroed the SortSupportData structure and then * filled in ssup_cxt, ssup_attno, ssup_collation, and ssup_nulls_first. This - * will fill in ssup_reverse (based on the supplied strategy), as well as the + * will fill in ssup_reverse (based on the supplied argument), as well as the * comparator function pointer. */ void -PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy, +PrepareSortSupportFromIndexRel(Relation indexRel, bool reverse, SortSupport ssup) { Oid opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1]; @@ -166,12 +166,9 @@ PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy, Assert(ssup->comparator == NULL); - if (indexRel->rd_rel->relam != BTREE_AM_OID) - elog(ERROR, "unexpected non-btree AM: %u", indexRel->rd_rel->relam); - if (strategy != BTGreaterStrategyNumber && - strategy != BTLessStrategyNumber) - elog(ERROR, "unexpected sort support strategy: %d", strategy); - ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber); + if (!indexRel->rd_indam->amcanorder) + elog(ERROR, "unexpected non-amcanorder AM: %u", indexRel->rd_rel->relam); + ssup->ssup_reverse = reverse; FinishSortSupportFunction(opfamily, opcintype, ssup); } diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index a3921373c5965..65ab83fff8b26 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -88,7 +88,7 @@ * produce exactly one output run from their partial input. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -121,9 +121,7 @@ ALLOCSET_SEPARATE_THRESHOLD / sizeof(SortTuple) + 1) /* GUC variables */ -#ifdef TRACE_SORT bool trace_sort = false; -#endif #ifdef DEBUG_BOUNDED_SORT bool optimize_bounded_sort = true; @@ -204,7 +202,7 @@ struct Tuplesortstate int64 maxSpace; /* maximum amount of space occupied among sort * of groups, either in-memory or on-disk */ bool isMaxSpaceDisk; /* true when maxSpace is value for on-disk - * space, false when it's value for in-memory + * space, false when its value for in-memory * space */ TupSortStatus maxSpaceStatus; /* sort status when maxSpace was reached */ LogicalTapeSet *tapeset; /* logtape.c object for tapes in a temp file */ @@ -335,9 +333,7 @@ struct Tuplesortstate /* * Resource snapshot for time of sort start. */ -#ifdef TRACE_SORT PGRUsage ru_start; -#endif }; /* @@ -683,10 +679,8 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt) state = (Tuplesortstate *) palloc0(sizeof(Tuplesortstate)); -#ifdef TRACE_SORT if (trace_sort) pg_rusage_init(&state->ru_start); -#endif state->base.sortopt = sortopt; state->base.tuples = true; @@ -904,22 +898,16 @@ tuplesort_free(Tuplesortstate *state) { /* context swap probably not needed, but let's be safe */ MemoryContext oldcontext = MemoryContextSwitchTo(state->base.sortcontext); - -#ifdef TRACE_SORT int64 spaceUsed; if (state->tapeset) spaceUsed = LogicalTapeSetBlocks(state->tapeset); else spaceUsed = (state->allowedMem - state->availMem + 1023) / 1024; -#endif /* * Delete temporary "tape" files, if any. * - * Note: want to include this in reported total cost of sort, hence need - * for two #ifdef TRACE_SORT sections. - * * We don't bother to destroy the individual tapes here. They will go away * with the sortcontext. (In TSS_FINALMERGE state, we have closed * finished tapes already.) @@ -927,28 +915,19 @@ tuplesort_free(Tuplesortstate *state) if (state->tapeset) LogicalTapeSetClose(state->tapeset); -#ifdef TRACE_SORT if (trace_sort) { if (state->tapeset) - elog(LOG, "%s of worker %d ended, %lld disk blocks used: %s", + elog(LOG, "%s of worker %d ended, %" PRId64 " disk blocks used: %s", SERIAL(state) ? "external sort" : "parallel external sort", - state->worker, (long long) spaceUsed, pg_rusage_show(&state->ru_start)); + state->worker, spaceUsed, pg_rusage_show(&state->ru_start)); else - elog(LOG, "%s of worker %d ended, %lld KB used: %s", + elog(LOG, "%s of worker %d ended, %" PRId64 " KB used: %s", SERIAL(state) ? "internal sort" : "unperformed parallel sort", - state->worker, (long long) spaceUsed, pg_rusage_show(&state->ru_start)); + state->worker, spaceUsed, pg_rusage_show(&state->ru_start)); } TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, spaceUsed); -#else - - /* - * If you disabled TRACE_SORT, you can still probe sort__done, but you - * ain't getting space-used stats. - */ - TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, 0L); -#endif FREESTATE(state); MemoryContextSwitchTo(oldcontext); @@ -1263,12 +1242,10 @@ tuplesort_puttuple_common(Tuplesortstate *state, SortTuple *tuple, (state->memtupcount > state->bound * 2 || (state->memtupcount > state->bound && LACKMEM(state)))) { -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "switching to bounded heapsort at %d tuples: %s", state->memtupcount, pg_rusage_show(&state->ru_start)); -#endif make_bounded_heap(state); MemoryContextSwitchTo(oldcontext); return; @@ -1387,11 +1364,9 @@ tuplesort_performsort(Tuplesortstate *state) { MemoryContext oldcontext = MemoryContextSwitchTo(state->base.sortcontext); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "performsort of worker %d starting: %s", state->worker, pg_rusage_show(&state->ru_start)); -#endif switch (state->status) { @@ -1470,7 +1445,6 @@ tuplesort_performsort(Tuplesortstate *state) break; } -#ifdef TRACE_SORT if (trace_sort) { if (state->status == TSS_FINALMERGE) @@ -1481,7 +1455,6 @@ tuplesort_performsort(Tuplesortstate *state) elog(LOG, "performsort of worker %d done: %s", state->worker, pg_rusage_show(&state->ru_start)); } -#endif MemoryContextSwitchTo(oldcontext); } @@ -1905,11 +1878,9 @@ inittapes(Tuplesortstate *state, bool mergeruns) state->maxTapes = MINORDER; } -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "worker %d switching to external sort with %d tapes: %s", state->worker, state->maxTapes, pg_rusage_show(&state->ru_start)); -#endif /* Create the tape set */ inittapestate(state, state->maxTapes); @@ -2118,11 +2089,9 @@ mergeruns(Tuplesortstate *state) */ state->tape_buffer_mem = state->availMem; USEMEM(state, state->tape_buffer_mem); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "worker %d using %zu KB of memory for tape buffers", state->worker, state->tape_buffer_mem / 1024); -#endif for (;;) { @@ -2167,12 +2136,10 @@ mergeruns(Tuplesortstate *state) state->nInputRuns, state->maxTapes); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "starting merge pass of %d input runs on %d tapes, " INT64_FORMAT " KB of memory for each input tape: %s", state->nInputRuns, state->nInputTapes, input_buffer_size / 1024, pg_rusage_show(&state->ru_start)); -#endif /* Prepare the new input tapes for merge pass. */ for (tapenum = 0; tapenum < state->nInputTapes; tapenum++) @@ -2378,12 +2345,10 @@ dumptuples(Tuplesortstate *state, bool alltuples) state->currentRun++; -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "worker %d starting quicksort of run %d: %s", state->worker, state->currentRun, pg_rusage_show(&state->ru_start)); -#endif /* * Sort all tuples accumulated within the allowed amount of memory for @@ -2391,12 +2356,10 @@ dumptuples(Tuplesortstate *state, bool alltuples) */ tuplesort_sort_memtuples(state); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "worker %d finished quicksort of run %d: %s", state->worker, state->currentRun, pg_rusage_show(&state->ru_start)); -#endif memtupwrite = state->memtupcount; for (i = 0; i < memtupwrite; i++) @@ -2426,12 +2389,10 @@ dumptuples(Tuplesortstate *state, bool alltuples) markrunend(state->destTape); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "worker %d finished writing run %d to tape %d: %s", state->worker, state->currentRun, (state->currentRun - 1) % state->nOutputTapes + 1, pg_rusage_show(&state->ru_start)); -#endif } /* diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c index 05a853caa3610..5f70e8dddac57 100644 --- a/src/backend/utils/sort/tuplesortvariants.c +++ b/src/backend/utils/sort/tuplesortvariants.c @@ -9,7 +9,7 @@ * could be easily added here, another module, or even an extension. * * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/utils/sort/tuplesortvariants.c @@ -20,10 +20,12 @@ #include "postgres.h" #include "access/brin_tuple.h" +#include "access/gin_tuple.h" #include "access/hash.h" #include "access/htup_details.h" #include "access/nbtree.h" #include "catalog/index.h" +#include "catalog/pg_collation.h" #include "executor/executor.h" #include "pg_trace.h" #include "utils/datum.h" @@ -46,6 +48,8 @@ static void removeabbrev_index(Tuplesortstate *state, SortTuple *stups, int count); static void removeabbrev_index_brin(Tuplesortstate *state, SortTuple *stups, int count); +static void removeabbrev_index_gin(Tuplesortstate *state, SortTuple *stups, + int count); static void removeabbrev_datum(Tuplesortstate *state, SortTuple *stups, int count); static int comparetup_heap(const SortTuple *a, const SortTuple *b, @@ -74,6 +78,8 @@ static int comparetup_index_hash_tiebreak(const SortTuple *a, const SortTuple *b Tuplesortstate *state); static int comparetup_index_brin(const SortTuple *a, const SortTuple *b, Tuplesortstate *state); +static int comparetup_index_gin(const SortTuple *a, const SortTuple *b, + Tuplesortstate *state); static void writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup); static void readtup_index(Tuplesortstate *state, SortTuple *stup, @@ -82,6 +88,10 @@ static void writetup_index_brin(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup); static void readtup_index_brin(Tuplesortstate *state, SortTuple *stup, LogicalTape *tape, unsigned int len); +static void writetup_index_gin(Tuplesortstate *state, LogicalTape *tape, + SortTuple *stup); +static void readtup_index_gin(Tuplesortstate *state, SortTuple *stup, + LogicalTape *tape, unsigned int len); static int comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state); static int comparetup_datum_tiebreak(const SortTuple *a, const SortTuple *b, @@ -181,12 +191,10 @@ tuplesort_begin_heap(TupleDesc tupDesc, Assert(nkeys > 0); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", nkeys, workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = nkeys; @@ -258,13 +266,11 @@ tuplesort_begin_cluster(TupleDesc tupDesc, oldcontext = MemoryContextSwitchTo(base->maincontext); arg = (TuplesortClusterArg *) palloc0(sizeof(TuplesortClusterArg)); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin tuple sort: nkeys = %d, workMem = %d, randomAccess = %c", RelationGetNumberOfAttributes(indexRel), workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); @@ -323,7 +329,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc, { SortSupport sortKey = base->sortKeys + i; ScanKey scanKey = indexScanKey->scankeys + i; - int16 strategy; + bool reverse; sortKey->ssup_cxt = CurrentMemoryContext; sortKey->ssup_collation = scanKey->sk_collation; @@ -335,10 +341,9 @@ tuplesort_begin_cluster(TupleDesc tupDesc, Assert(sortKey->ssup_attno != 0); - strategy = (scanKey->sk_flags & SK_BT_DESC) != 0 ? - BTGreaterStrategyNumber : BTLessStrategyNumber; + reverse = (scanKey->sk_flags & SK_BT_DESC) != 0; - PrepareSortSupportFromIndexRel(indexRel, strategy, sortKey); + PrepareSortSupportFromIndexRel(indexRel, reverse, sortKey); } pfree(indexScanKey); @@ -368,13 +373,11 @@ tuplesort_begin_index_btree(Relation heapRel, oldcontext = MemoryContextSwitchTo(base->maincontext); arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg)); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin index sort: unique = %c, workMem = %d, randomAccess = %c", enforceUnique ? 't' : 'f', workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); @@ -408,7 +411,7 @@ tuplesort_begin_index_btree(Relation heapRel, { SortSupport sortKey = base->sortKeys + i; ScanKey scanKey = indexScanKey->scankeys + i; - int16 strategy; + bool reverse; sortKey->ssup_cxt = CurrentMemoryContext; sortKey->ssup_collation = scanKey->sk_collation; @@ -420,10 +423,9 @@ tuplesort_begin_index_btree(Relation heapRel, Assert(sortKey->ssup_attno != 0); - strategy = (scanKey->sk_flags & SK_BT_DESC) != 0 ? - BTGreaterStrategyNumber : BTLessStrategyNumber; + reverse = (scanKey->sk_flags & SK_BT_DESC) != 0; - PrepareSortSupportFromIndexRel(indexRel, strategy, sortKey); + PrepareSortSupportFromIndexRel(indexRel, reverse, sortKey); } pfree(indexScanKey); @@ -452,7 +454,6 @@ tuplesort_begin_index_hash(Relation heapRel, oldcontext = MemoryContextSwitchTo(base->maincontext); arg = (TuplesortIndexHashArg *) palloc(sizeof(TuplesortIndexHashArg)); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin index sort: high_mask = 0x%x, low_mask = 0x%x, " @@ -462,7 +463,6 @@ tuplesort_begin_index_hash(Relation heapRel, max_buckets, workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = 1; /* Only one sort column, the hash code */ @@ -503,12 +503,10 @@ tuplesort_begin_index_gist(Relation heapRel, oldcontext = MemoryContextSwitchTo(base->maincontext); arg = (TuplesortIndexBTreeArg *) palloc(sizeof(TuplesortIndexBTreeArg)); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin index sort: workMem = %d, randomAccess = %c", workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); @@ -560,13 +558,11 @@ tuplesort_begin_index_brin(int workMem, sortopt); TuplesortPublic *base = TuplesortstateGetPublic(state); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin index sort: workMem = %d, randomAccess = %c", workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = 1; /* Only one sort column, the block number */ @@ -580,6 +576,77 @@ tuplesort_begin_index_brin(int workMem, return state; } +Tuplesortstate * +tuplesort_begin_index_gin(Relation heapRel, + Relation indexRel, + int workMem, SortCoordinate coordinate, + int sortopt) +{ + Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate, + sortopt); + TuplesortPublic *base = TuplesortstateGetPublic(state); + MemoryContext oldcontext; + int i; + TupleDesc desc = RelationGetDescr(indexRel); + + oldcontext = MemoryContextSwitchTo(base->maincontext); + +#ifdef TRACE_SORT + if (trace_sort) + elog(LOG, + "begin index sort: workMem = %d, randomAccess = %c", + workMem, + sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); +#endif + + /* + * Multi-column GIN indexes expand the row into a separate index entry for + * attribute, and that's what we write into the tuplesort. But we still + * need to initialize sortsupport for all the attributes. + */ + base->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel); + + /* Prepare SortSupport data for each column */ + base->sortKeys = (SortSupport) palloc0(base->nKeys * + sizeof(SortSupportData)); + + for (i = 0; i < base->nKeys; i++) + { + SortSupport sortKey = base->sortKeys + i; + Form_pg_attribute att = TupleDescAttr(desc, i); + TypeCacheEntry *typentry; + + sortKey->ssup_cxt = CurrentMemoryContext; + sortKey->ssup_collation = indexRel->rd_indcollation[i]; + sortKey->ssup_nulls_first = false; + sortKey->ssup_attno = i + 1; + sortKey->abbreviate = false; + + Assert(sortKey->ssup_attno != 0); + + if (!OidIsValid(sortKey->ssup_collation)) + sortKey->ssup_collation = DEFAULT_COLLATION_OID; + + /* + * Look for a ordering for the index key data type, and then the sort + * support function. + */ + typentry = lookup_type_cache(att->atttypid, TYPECACHE_LT_OPR); + PrepareSortSupportFromOrderingOp(typentry->lt_opr, sortKey); + } + + base->removeabbrev = removeabbrev_index_gin; + base->comparetup = comparetup_index_gin; + base->writetup = writetup_index_gin; + base->readtup = readtup_index_gin; + base->haveDatum1 = false; + base->arg = NULL; + + MemoryContextSwitchTo(oldcontext); + + return state; +} + Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, @@ -596,12 +663,10 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, oldcontext = MemoryContextSwitchTo(base->maincontext); arg = (TuplesortDatumArg *) palloc(sizeof(TuplesortDatumArg)); -#ifdef TRACE_SORT if (trace_sort) elog(LOG, "begin datum sort: workMem = %d, randomAccess = %c", workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f'); -#endif base->nKeys = 1; /* always a one-column sort */ @@ -678,7 +743,7 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot) /* copy the tuple into sort storage */ tuple = ExecCopySlotMinimalTuple(slot); - stup.tuple = (void *) tuple; + stup.tuple = tuple; /* set up first-column key value */ htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET; htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET); @@ -716,7 +781,7 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup) /* copy the tuple into sort storage */ tup = heap_copytuple(tup); - stup.tuple = (void *) tup; + stup.tuple = tup; /* * set up first-column key value, and potentially abbreviate, if it's a @@ -817,6 +882,37 @@ tuplesort_putbrintuple(Tuplesortstate *state, BrinTuple *tuple, Size size) MemoryContextSwitchTo(oldcontext); } +void +tuplesort_putgintuple(Tuplesortstate *state, GinTuple *tuple, Size size) +{ + SortTuple stup; + GinTuple *ctup; + TuplesortPublic *base = TuplesortstateGetPublic(state); + MemoryContext oldcontext = MemoryContextSwitchTo(base->tuplecontext); + Size tuplen; + + /* copy the GinTuple into the right memory context */ + ctup = palloc(size); + memcpy(ctup, tuple, size); + + stup.tuple = ctup; + stup.datum1 = (Datum) 0; + stup.isnull1 = false; + + /* GetMemoryChunkSpace is not supported for bump contexts */ + if (TupleSortUseBumpTupleCxt(base->sortopt)) + tuplen = MAXALIGN(size); + else + tuplen = GetMemoryChunkSpace(ctup); + + tuplesort_puttuple_common(state, &stup, + base->sortKeys && + base->sortKeys->abbrev_converter && + !stup.isnull1, tuplen); + + MemoryContextSwitchTo(oldcontext); +} + /* * Accept one Datum while collecting input data for sort. * @@ -906,7 +1002,7 @@ tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy, *abbrev = stup.datum1; if (copy) - stup.tuple = heap_copy_minimal_tuple((MinimalTuple) stup.tuple); + stup.tuple = heap_copy_minimal_tuple((MinimalTuple) stup.tuple, 0); ExecStoreMinimalTuple((MinimalTuple) stup.tuple, slot, copy); return true; @@ -989,6 +1085,29 @@ tuplesort_getbrintuple(Tuplesortstate *state, Size *len, bool forward) return &btup->tuple; } +GinTuple * +tuplesort_getgintuple(Tuplesortstate *state, Size *len, bool forward) +{ + TuplesortPublic *base = TuplesortstateGetPublic(state); + MemoryContext oldcontext = MemoryContextSwitchTo(base->sortcontext); + SortTuple stup; + GinTuple *tup; + + if (!tuplesort_gettuple_common(state, forward, &stup)) + stup.tuple = NULL; + + MemoryContextSwitchTo(oldcontext); + + if (!stup.tuple) + return NULL; + + tup = (GinTuple *) stup.tuple; + + *len = tup->tuplen; + + return tup; +} + /* * Fetch the next Datum in either forward or back direction. * Returns false if no more datums. @@ -1189,7 +1308,7 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup, LogicalTapeReadExact(tape, tupbody, tupbodylen); if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; + stup->tuple = tuple; /* set up first-column key value */ htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET; htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET); @@ -1386,7 +1505,7 @@ readtup_cluster(Tuplesortstate *state, SortTuple *stup, LogicalTapeReadExact(tape, tuple->t_data, tuple->t_len); if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; + stup->tuple = tuple; /* set up first-column key value, if it's a simple column */ if (base->haveDatum1) stup->datum1 = heap_getattr(tuple, @@ -1695,7 +1814,7 @@ readtup_index(Tuplesortstate *state, SortTuple *stup, LogicalTapeReadExact(tape, tuple, tuplen); if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; + stup->tuple = tuple; /* set up first-column key value */ stup->datum1 = index_getattr(tuple, 1, @@ -1771,12 +1890,75 @@ readtup_index_brin(Tuplesortstate *state, SortTuple *stup, LogicalTapeReadExact(tape, &tuple->tuple, tuplen); if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); - stup->tuple = (void *) tuple; + stup->tuple = tuple; /* set up first-column key value, which is block number */ stup->datum1 = tuple->tuple.bt_blkno; } +/* + * Routines specialized for GIN case + */ + +static void +removeabbrev_index_gin(Tuplesortstate *state, SortTuple *stups, int count) +{ + Assert(false); + elog(ERROR, "removeabbrev_index_gin not implemented"); +} + +static int +comparetup_index_gin(const SortTuple *a, const SortTuple *b, + Tuplesortstate *state) +{ + TuplesortPublic *base = TuplesortstateGetPublic(state); + + Assert(!TuplesortstateGetPublic(state)->haveDatum1); + + return _gin_compare_tuples((GinTuple *) a->tuple, + (GinTuple *) b->tuple, + base->sortKeys); +} + +static void +writetup_index_gin(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup) +{ + TuplesortPublic *base = TuplesortstateGetPublic(state); + GinTuple *tuple = (GinTuple *) stup->tuple; + unsigned int tuplen = tuple->tuplen; + + tuplen = tuplen + sizeof(tuplen); + LogicalTapeWrite(tape, &tuplen, sizeof(tuplen)); + LogicalTapeWrite(tape, tuple, tuple->tuplen); + if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ + LogicalTapeWrite(tape, &tuplen, sizeof(tuplen)); +} + +static void +readtup_index_gin(Tuplesortstate *state, SortTuple *stup, + LogicalTape *tape, unsigned int len) +{ + GinTuple *tuple; + TuplesortPublic *base = TuplesortstateGetPublic(state); + unsigned int tuplen = len - sizeof(unsigned int); + + /* + * Allocate space for the GIN sort tuple, which already has the proper + * length included in the header. + */ + tuple = (GinTuple *) tuplesort_readtup_alloc(state, tuplen); + + tuple->tuplen = tuplen; + + LogicalTapeReadExact(tape, tuple, tuplen); + if (base->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length word? */ + LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen)); + stup->tuple = (void *) tuple; + + /* no abbreviations (FIXME maybe use attrnum for this?) */ + stup->datum1 = (Datum) 0; +} + /* * Routines specialized for DatumTuple case */ diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index 444c8e25c21fc..c9aecab8d66cb 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -43,7 +43,7 @@ * before switching to the other state or activating a different read pointer. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -107,9 +107,10 @@ struct Tuplestorestate bool backward; /* store extra length words in file? */ bool interXact; /* keep open through transactions? */ bool truncated; /* tuplestore_trim has removed tuples? */ + bool usedDisk; /* used by tuplestore_get_stats() */ + int64 maxSpace; /* used by tuplestore_get_stats() */ int64 availMem; /* remaining memory available, in bytes */ int64 allowedMem; /* total memory allowed, in bytes */ - int64 maxSpace; /* maximum space used in memory */ int64 tuples; /* number of tuples added */ BufFile *myfile; /* underlying file, or NULL if none */ MemoryContext context; /* memory context for holding tuples */ @@ -262,9 +263,10 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes) state->eflags = eflags; state->interXact = interXact; state->truncated = false; - state->allowedMem = maxKBytes * 1024L; - state->availMem = state->allowedMem; + state->usedDisk = false; state->maxSpace = 0; + state->allowedMem = maxKBytes * (int64) 1024; + state->availMem = state->allowedMem; state->myfile = NULL; /* @@ -749,7 +751,7 @@ tuplestore_puttupleslot(Tuplestorestate *state, tuple = ExecCopySlotMinimalTuple(slot); USEMEM(state, GetMemoryChunkSpace(tuple)); - tuplestore_puttuple_common(state, (void *) tuple); + tuplestore_puttuple_common(state, tuple); MemoryContextSwitchTo(oldcxt); } @@ -769,7 +771,7 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple) */ tuple = COPYTUP(state, tuple); - tuplestore_puttuple_common(state, (void *) tuple); + tuplestore_puttuple_common(state, tuple); MemoryContextSwitchTo(oldcxt); } @@ -785,10 +787,10 @@ tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, MinimalTuple tuple; MemoryContext oldcxt = MemoryContextSwitchTo(state->context); - tuple = heap_form_minimal_tuple(tdesc, values, isnull); + tuple = heap_form_minimal_tuple(tdesc, values, isnull, 0); USEMEM(state, GetMemoryChunkSpace(tuple)); - tuplestore_puttuple_common(state, (void *) tuple); + tuplestore_puttuple_common(state, tuple); MemoryContextSwitchTo(oldcxt); } @@ -870,6 +872,14 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple) * though callers might drop the requirement. */ state->backward = (state->eflags & EXEC_FLAG_BACKWARD) != 0; + + /* + * Update the maximum space used before dumping the tuples. It's + * possible that more space will be used by the tuples in memory + * than the space that will be used on disk. + */ + tuplestore_updatemax(state); + state->status = TSS_WRITEFILE; dumptuples(state); break; @@ -1129,7 +1139,7 @@ tuplestore_gettupleslot(Tuplestorestate *state, bool forward, { if (copy && !should_free) { - tuple = heap_copy_minimal_tuple(tuple); + tuple = heap_copy_minimal_tuple(tuple, 0); should_free = true; } ExecStoreMinimalTuple(tuple, slot, should_free); @@ -1444,7 +1454,7 @@ tuplestore_trim(Tuplestorestate *state) Assert(nremove >= state->memtupdeleted); Assert(nremove <= state->memtupcount); - /* before freeing any memory, update maxSpace */ + /* before freeing any memory, update the statistics */ tuplestore_updatemax(state); /* Release no-longer-needed tuples */ @@ -1491,7 +1501,8 @@ tuplestore_trim(Tuplestorestate *state) /* * tuplestore_updatemax - * Update maxSpace field + * Update the maximum space used by this tuplestore and the method used + * for storage. */ static void tuplestore_updatemax(Tuplestorestate *state) @@ -1499,37 +1510,37 @@ tuplestore_updatemax(Tuplestorestate *state) if (state->status == TSS_INMEM) state->maxSpace = Max(state->maxSpace, state->allowedMem - state->availMem); -} - -/* - * tuplestore_storage_type_name - * Return a string description of the storage method used to store the - * tuples. - */ -const char * -tuplestore_storage_type_name(Tuplestorestate *state) -{ - if (state->status == TSS_INMEM) - return "Memory"; else - return "Disk"; + { + state->maxSpace = Max(state->maxSpace, + BufFileSize(state->myfile)); + + /* + * usedDisk never gets set to false again after spilling to disk, even + * if tuplestore_clear() is called and new tuples go to memory again. + */ + state->usedDisk = true; + } } /* - * tuplestore_space_used - * Return the maximum space used in memory unless the tuplestore has spilled - * to disk, in which case, return the disk space used. + * tuplestore_get_stats + * Obtain statistics about the maximum space used by the tuplestore. + * These statistics are the maximums and are not reset by calls to + * tuplestore_trim() or tuplestore_clear(). */ -int64 -tuplestore_space_used(Tuplestorestate *state) +void +tuplestore_get_stats(Tuplestorestate *state, char **max_storage_type, + int64 *max_space) { - /* First, update the maxSpace field */ tuplestore_updatemax(state); - if (state->status == TSS_INMEM) - return state->maxSpace; + if (state->usedDisk) + *max_storage_type = "Disk"; else - return BufFileSize(state->myfile); + *max_storage_type = "Memory"; + + *max_space = state->maxSpace; } /* @@ -1579,9 +1590,9 @@ copytup_heap(Tuplestorestate *state, void *tup) { MinimalTuple tuple; - tuple = minimal_tuple_from_heap_tuple((HeapTuple) tup); + tuple = minimal_tuple_from_heap_tuple((HeapTuple) tup, 0); USEMEM(state, GetMemoryChunkSpace(tuple)); - return (void *) tuple; + return tuple; } static void @@ -1601,7 +1612,6 @@ writetup_heap(Tuplestorestate *state, void *tup) if (state->backward) /* need trailing length word? */ BufFileWrite(state->myfile, &tuplen, sizeof(tuplen)); - /* no need to call tuplestore_updatemax() when not in TSS_INMEM */ FREEMEM(state, GetMemoryChunkSpace(tuple)); heap_free_minimal_tuple(tuple); } @@ -1619,5 +1629,5 @@ readtup_heap(Tuplestorestate *state, unsigned int len) BufFileReadExact(state->myfile, tupbody, tupbodylen); if (state->backward) /* need trailing length word? */ BufFileReadExact(state->myfile, &tuplen, sizeof(tuplen)); - return (void *) tuple; + return tuple; } diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c index f85510b74ff1c..1e81557157090 100644 --- a/src/backend/utils/time/combocid.c +++ b/src/backend/utils/time/combocid.c @@ -30,7 +30,7 @@ * destroyed at the end of each transaction. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -101,7 +101,7 @@ static CommandId GetRealCmax(CommandId combocid); */ CommandId -HeapTupleHeaderGetCmin(HeapTupleHeader tup) +HeapTupleHeaderGetCmin(const HeapTupleHeaderData *tup) { CommandId cid = HeapTupleHeaderGetRawCommandId(tup); @@ -115,7 +115,7 @@ HeapTupleHeaderGetCmin(HeapTupleHeader tup) } CommandId -HeapTupleHeaderGetCmax(HeapTupleHeader tup) +HeapTupleHeaderGetCmax(const HeapTupleHeaderData *tup) { CommandId cid = HeapTupleHeaderGetRawCommandId(tup); @@ -150,7 +150,7 @@ HeapTupleHeaderGetCmax(HeapTupleHeader tup) * changes the tuple in shared buffers. */ void -HeapTupleHeaderAdjustCmax(HeapTupleHeader tup, +HeapTupleHeaderAdjustCmax(const HeapTupleHeaderData *tup, CommandId *cmax, bool *iscombo) { diff --git a/src/backend/utils/time/meson.build b/src/backend/utils/time/meson.build index ea8943f70d4fa..be40f43ab9450 100644 --- a/src/backend/utils/time/meson.build +++ b/src/backend/utils/time/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group backend_sources += files( 'combocid.c', diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 7d2b34d4f20ea..ea35f30f49457 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -3,11 +3,70 @@ * snapmgr.c * PostgreSQL snapshot manager * + * The following functions return an MVCC snapshot that can be used in tuple + * visibility checks: + * + * - GetTransactionSnapshot + * - GetLatestSnapshot + * - GetCatalogSnapshot + * - GetNonHistoricCatalogSnapshot + * + * Each of these functions returns a reference to a statically allocated + * snapshot. The statically allocated snapshot is subject to change on any + * snapshot-related function call, and should not be used directly. Instead, + * call PushActiveSnapshot() or RegisterSnapshot() to create a longer-lived + * copy and use that. + * * We keep track of snapshots in two ways: those "registered" by resowner.c, * and the "active snapshot" stack. All snapshots in either of them live in * persistent memory. When a snapshot is no longer in any of these lists * (tracked by separate refcounts on each snapshot), its memory can be freed. * + * In addition to the above-mentioned MVCC snapshots, there are some special + * snapshots like SnapshotSelf, SnapshotAny, and "dirty" snapshots. They can + * only be used in limited contexts and cannot be registered or pushed to the + * active stack. + * + * ActiveSnapshot stack + * -------------------- + * + * Most visibility checks use the current "active snapshot" returned by + * GetActiveSnapshot(). When running normal queries, the active snapshot is + * set when query execution begins based on the transaction isolation level. + * + * The active snapshot is tracked in a stack so that the currently active one + * is at the top of the stack. It mirrors the process call stack: whenever we + * recurse or switch context to fetch rows from a different portal for + * example, the appropriate snapshot is pushed to become the active snapshot, + * and popped on return. Once upon a time, ActiveSnapshot was just a global + * variable that was saved and restored similar to CurrentMemoryContext, but + * nowadays it's managed as a separate data structure so that we can keep + * track of which snapshots are in use and reset MyProc->xmin when there is no + * active snapshot. + * + * However, there are a couple of exceptions where the active snapshot stack + * does not strictly mirror the call stack: + * + * - VACUUM and a few other utility commands manage their own transactions, + * which take their own snapshots. They are called with an active snapshot + * set, like most utility commands, but they pop the active snapshot that + * was pushed by the caller. PortalRunUtility knows about the possibility + * that the snapshot it pushed is no longer active on return. + * + * - When COMMIT or ROLLBACK is executed within a procedure or DO-block, the + * active snapshot stack is destroyed, and re-established later when + * subsequent statements in the procedure are executed. There are many + * limitations on when in-procedure COMMIT/ROLLBACK is allowed; one such + * limitation is that all the snapshots on the active snapshot stack are + * known to portals that are being executed, which makes it safe to reset + * the stack. See EnsurePortalSnapshotExists(). + * + * Registered snapshots + * -------------------- + * + * In addition to snapshots pushed to the active snapshot stack, a snapshot + * can be registered with a resource owner. + * * The FirstXactSnapshot, if any, is treated a bit specially: we increment its * regd_count and list it in RegisteredSnapshots, but this reference is not * tracked by a resource owner. We used to use the TopTransactionResourceOwner @@ -35,7 +94,7 @@ * stack is empty. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -80,9 +139,10 @@ */ static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC}; static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC}; -SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}; +static SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC}; SnapshotData SnapshotSelfData = {SNAPSHOT_SELF}; SnapshotData SnapshotAnyData = {SNAPSHOT_ANY}; +SnapshotData SnapshotToastData = {SNAPSHOT_TOAST}; /* Pointers to valid snapshots */ static Snapshot CurrentSnapshot = NULL; @@ -119,9 +179,6 @@ typedef struct ActiveSnapshotElt /* Top of the stack of active snapshots */ static ActiveSnapshotElt *ActiveSnapshot = NULL; -/* Bottom of the stack of active snapshots */ -static ActiveSnapshotElt *OldestActiveSnapshot = NULL; - /* * Currently registered Snapshots. Ordered in a heap by xmin, so that we can * quickly find the one with lowest xmin, to advance our MyProc->xmin. @@ -199,33 +256,27 @@ typedef struct SerializedSnapshotData bool suboverflowed; bool takenDuringRecovery; CommandId curcid; - TimestampTz whenTaken; - XLogRecPtr lsn; } SerializedSnapshotData; /* * GetTransactionSnapshot * Get the appropriate snapshot for a new query in a transaction. * - * Note that the return value may point at static storage that will be modified - * by future calls and by CommandCounterIncrement(). Callers should call - * RegisterSnapshot or PushActiveSnapshot on the returned snap if it is to be - * used very long. + * Note that the return value points at static storage that will be modified + * by future calls and by CommandCounterIncrement(). Callers must call + * RegisterSnapshot or PushActiveSnapshot on the returned snap before doing + * any other non-trivial work that could invalidate it. */ Snapshot GetTransactionSnapshot(void) { /* - * Return historic snapshot if doing logical decoding. We'll never need a - * non-historic transaction snapshot in this (sub-)transaction, so there's - * no need to be careful to set one up for later calls to - * GetTransactionSnapshot(). + * This should not be called while doing logical decoding. Historic + * snapshots are only usable for catalog access, not for general-purpose + * queries. */ if (HistoricSnapshotActive()) - { - Assert(!FirstSnapshotSet); - return HistoricSnapshot; - } + elog(ERROR, "cannot take query snapshot during logical decoding"); /* First call in transaction? */ if (!FirstSnapshotSet) @@ -313,36 +364,6 @@ GetLatestSnapshot(void) return SecondarySnapshot; } -/* - * GetOldestSnapshot - * - * Get the transaction's oldest known snapshot, as judged by the LSN. - * Will return NULL if there are no active or registered snapshots. - */ -Snapshot -GetOldestSnapshot(void) -{ - Snapshot OldestRegisteredSnapshot = NULL; - XLogRecPtr RegisteredLSN = InvalidXLogRecPtr; - - if (!pairingheap_is_empty(&RegisteredSnapshots)) - { - OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node, - pairingheap_first(&RegisteredSnapshots)); - RegisteredLSN = OldestRegisteredSnapshot->lsn; - } - - if (OldestActiveSnapshot != NULL) - { - XLogRecPtr ActiveLSN = OldestActiveSnapshot->as_snap->lsn; - - if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN) - return OldestActiveSnapshot->as_snap; - } - - return OldestRegisteredSnapshot; -} - /* * GetCatalogSnapshot * Get a snapshot that is sufficiently up-to-date for scan of the @@ -684,8 +705,6 @@ PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level) newactive->as_snap->active_count++; ActiveSnapshot = newactive; - if (OldestActiveSnapshot == NULL) - OldestActiveSnapshot = ActiveSnapshot; } /* @@ -756,8 +775,6 @@ PopActiveSnapshot(void) pfree(ActiveSnapshot); ActiveSnapshot = newstack; - if (ActiveSnapshot == NULL) - OldestActiveSnapshot = NULL; SnapshotResetXmin(); } @@ -902,13 +919,6 @@ xmin_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg) * dropped. For efficiency, we only consider recomputing PGPROC->xmin when * the active snapshot stack is empty; this allows us not to need to track * which active snapshot is oldest. - * - * Note: it's tempting to use GetOldestSnapshot() here so that we can include - * active snapshots in the calculation. However, that compares by LSN not - * xmin so it's not entirely clear that it's the same thing. Also, we'd be - * critically dependent on the assumption that the bottommost active snapshot - * stack entry has the oldest xmin. (Current uses of GetOldestSnapshot() are - * not actually critical, but this would be.) */ static void SnapshotResetXmin(void) @@ -920,7 +930,7 @@ SnapshotResetXmin(void) if (pairingheap_is_empty(&RegisteredSnapshots)) { - MyProc->xmin = InvalidTransactionId; + MyProc->xmin = TransactionXmin = InvalidTransactionId; return; } @@ -928,7 +938,7 @@ SnapshotResetXmin(void) pairingheap_first(&RegisteredSnapshots)); if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin)) - MyProc->xmin = minSnapshot->xmin; + MyProc->xmin = TransactionXmin = minSnapshot->xmin; } /* @@ -980,8 +990,6 @@ AtSubAbort_Snapshot(int level) pfree(ActiveSnapshot); ActiveSnapshot = next; - if (ActiveSnapshot == NULL) - OldestActiveSnapshot = NULL; } SnapshotResetXmin(); @@ -1065,7 +1073,6 @@ AtEOXact_Snapshot(bool isCommit, bool resetXmin) * it'll go away with TopTransactionContext. */ ActiveSnapshot = NULL; - OldestActiveSnapshot = NULL; pairingheap_reset(&RegisteredSnapshots); CurrentSnapshot = NULL; @@ -1727,8 +1734,6 @@ SerializeSnapshot(Snapshot snapshot, char *start_address) serialized_snapshot.suboverflowed = snapshot->suboverflowed; serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery; serialized_snapshot.curcid = snapshot->curcid; - serialized_snapshot.whenTaken = snapshot->whenTaken; - serialized_snapshot.lsn = snapshot->lsn; /* * Ignore the SubXID array if it has overflowed, unless the snapshot was @@ -1801,8 +1806,6 @@ RestoreSnapshot(char *start_address) snapshot->suboverflowed = serialized_snapshot.suboverflowed; snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery; snapshot->curcid = serialized_snapshot.curcid; - snapshot->whenTaken = serialized_snapshot.whenTaken; - snapshot->lsn = serialized_snapshot.lsn; snapshot->snapXactCompletionCount = 0; /* Copy XIDs, if present. */ diff --git a/src/bin/Makefile b/src/bin/Makefile index fc789da17bb5a..ac50cf93cb67e 100644 --- a/src/bin/Makefile +++ b/src/bin/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin (client programs) # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/Makefile diff --git a/src/bin/initdb/Makefile b/src/bin/initdb/Makefile index 031cc77c9d61b..997e0a013e956 100644 --- a/src/bin/initdb/Makefile +++ b/src/bin/initdb/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/initdb # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/initdb/Makefile diff --git a/src/bin/initdb/findtimezone.c b/src/bin/initdb/findtimezone.c index 95204e482be0a..2b2ae39adf34f 100644 --- a/src/bin/initdb/findtimezone.c +++ b/src/bin/initdb/findtimezone.c @@ -3,7 +3,7 @@ * findtimezone.c * Functions for determining the default timezone to use. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/initdb/findtimezone.c diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index f00718a0150c2..62bbd08d9f658 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -38,7 +38,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/initdb/initdb.c @@ -61,14 +61,14 @@ #include #ifdef HAVE_SHM_OPEN -#include "sys/mman.h" +#include #endif #include "access/xlog_internal.h" #include "catalog/pg_authid_d.h" -#include "catalog/pg_class_d.h" /* pgrminclude ignore */ +#include "catalog/pg_class_d.h" #include "catalog/pg_collation_d.h" -#include "catalog/pg_database_d.h" /* pgrminclude ignore */ +#include "catalog/pg_database_d.h" #include "common/file_perm.h" #include "common/file_utils.h" #include "common/logging.h" @@ -164,10 +164,11 @@ static bool noinstructions = false; static bool do_sync = true; static bool sync_only = false; static bool show_setting = false; -static bool data_checksums = false; +static bool data_checksums = true; static char *xlog_dir = NULL; static int wal_segment_size_mb = (DEFAULT_XLOG_SEG_SIZE) / (1024 * 1024); static DataDirSyncMethod sync_method = DATA_DIR_SYNC_METHOD_FSYNC; +static bool sync_data_files = true; /* internal vars */ @@ -196,6 +197,7 @@ static char *pgdata_native; /* defaults */ static int n_connections = 10; +static int n_av_slots = 16; static int n_buffers = 50; static const char *dynamic_shared_memory_type = NULL; static const char *default_timezone = NULL; @@ -273,7 +275,8 @@ static void check_input(char *path); static void write_version_file(const char *extrapath); static void set_null_conf(void); static void test_config_settings(void); -static bool test_specific_config_settings(int test_conns, int test_buffs); +static bool test_specific_config_settings(int test_conns, int test_av_slots, + int test_buffs); static void setup_config(void); static void bootstrap_template1(void); static void setup_auth(FILE *cmdfd); @@ -340,6 +343,61 @@ do { \ output_failed = true, output_errno = errno; \ } while (0) +#ifdef WIN32 +typedef wchar_t *save_locale_t; +#else +typedef char *save_locale_t; +#endif + +/* + * Save a copy of the current global locale's name, for the given category. + * The returned value must be passed to restore_global_locale(). + * + * Since names from the environment haven't been vetted for non-ASCII + * characters, we use the wchar_t variant of setlocale() on Windows. Otherwise + * they might not survive a save-restore round trip: when restoring, the name + * itself might be interpreted with a different encoding by plain setlocale(), + * after we switch to another locale in between. (This is a problem only in + * initdb, not in similar backend code where the global locale's name should + * already have been verified as ASCII-only.) + */ +static save_locale_t +save_global_locale(int category) +{ + save_locale_t save; + +#ifdef WIN32 + save = _wsetlocale(category, NULL); + if (!save) + pg_fatal("_wsetlocale() failed"); + save = wcsdup(save); + if (!save) + pg_fatal("out of memory"); +#else + save = setlocale(category, NULL); + if (!save) + pg_fatal("setlocale() failed"); + save = pg_strdup(save); +#endif + return save; +} + +/* + * Restore the global locale returned by save_global_locale(). + */ +static void +restore_global_locale(int category, save_locale_t save) +{ +#ifdef WIN32 + if (!_wsetlocale(category, save)) + pg_fatal("failed to restore old locale"); +#else + if (!setlocale(category, save)) + pg_fatal("failed to restore old locale \"%s\"", save); +#endif + free(save); +} + /* * Escape single quotes and backslashes, suitably for insertions into * configuration files or SQL E'' strings. @@ -826,6 +884,8 @@ static const struct tsearch_config_match tsearch_config_languages[] = {"english", "POSIX"}, {"english", "en"}, {"english", "English"}, + {"estonian", "et"}, + {"estonian", "Estonian"}, {"finnish", "fi"}, {"finnish", "Finnish"}, {"french", "fr"}, @@ -1063,6 +1123,17 @@ test_config_settings(void) */ #define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10) + /* + * This macro defines the default value of autovacuum_worker_slots we want + * for a given max_connections value. Note that it has been carefully + * crafted to provide specific values for the associated values in + * trial_conns. We want it to return autovacuum_worker_slots's initial + * default value (16) for the maximum value in trial_conns[] (100), while + * it mustn't return less than the default value of autovacuum_max_workers + * (3) for the minimum value in trial_conns[]. + */ +#define AV_SLOTS_FOR_CONNS(nconns) ((nconns) / 6) + static const int trial_conns[] = { 100, 50, 40, 30, 20 }; @@ -1090,7 +1161,8 @@ test_config_settings(void) /* * Probe for max_connections before shared_buffers, since it is subject to - * more constraints than shared_buffers. + * more constraints than shared_buffers. We also choose the default + * autovacuum_worker_slots here. */ printf(_("selecting default \"max_connections\" ... ")); fflush(stdout); @@ -1098,9 +1170,10 @@ test_config_settings(void) for (i = 0; i < connslen; i++) { test_conns = trial_conns[i]; + n_av_slots = AV_SLOTS_FOR_CONNS(test_conns); test_buffs = MIN_BUFS_FOR_CONNS(test_conns); - if (test_specific_config_settings(test_conns, test_buffs)) + if (test_specific_config_settings(test_conns, n_av_slots, test_buffs)) { ok_buffers = test_buffs; break; @@ -1125,7 +1198,7 @@ test_config_settings(void) break; } - if (test_specific_config_settings(n_connections, test_buffs)) + if (test_specific_config_settings(n_connections, n_av_slots, test_buffs)) break; } n_buffers = test_buffs; @@ -1145,7 +1218,7 @@ test_config_settings(void) * Test a specific combination of configuration settings. */ static bool -test_specific_config_settings(int test_conns, int test_buffs) +test_specific_config_settings(int test_conns, int test_av_slots, int test_buffs) { PQExpBufferData cmd; _stringlist *gnames, @@ -1158,10 +1231,11 @@ test_specific_config_settings(int test_conns, int test_buffs) printfPQExpBuffer(&cmd, "\"%s\" --check %s %s " "-c max_connections=%d " + "-c autovacuum_worker_slots=%d " "-c shared_buffers=%d " "-c dynamic_shared_memory_type=%s", backend_exec, boot_options, extra_options, - test_conns, test_buffs, + test_conns, test_av_slots, test_buffs, dynamic_shared_memory_type); /* Add any user-given setting overrides */ @@ -1225,6 +1299,10 @@ setup_config(void) conflines = replace_guc_value(conflines, "max_connections", repltok, false); + snprintf(repltok, sizeof(repltok), "%d", n_av_slots); + conflines = replace_guc_value(conflines, "autovacuum_worker_slots", + repltok, false); + if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0) snprintf(repltok, sizeof(repltok), "%dMB", (n_buffers * (BLCKSZ / 1024)) / 1024); @@ -1316,11 +1394,6 @@ setup_config(void) repltok, true); #endif -#ifndef USE_PREFETCH - conflines = replace_guc_value(conflines, "effective_io_concurrency", - "0", true); -#endif - #ifdef WIN32 conflines = replace_guc_value(conflines, "update_process_title", "off", true); @@ -1539,9 +1612,9 @@ bootstrap_template1(void) printfPQExpBuffer(&cmd, "\"%s\" --boot %s %s", backend_exec, boot_options, extra_options); appendPQExpBuffer(&cmd, " -X %d", wal_segment_size_mb * (1024 * 1024)); if (data_checksums) - appendPQExpBuffer(&cmd, " -k"); + appendPQExpBufferStr(&cmd, " -k"); if (debug) - appendPQExpBuffer(&cmd, " -d 5"); + appendPQExpBufferStr(&cmd, " -d 5"); PG_CMD_OPEN(cmd.data); @@ -2074,16 +2147,13 @@ locale_date_order(const char *locale) char *posD; char *posM; char *posY; - char *save; + save_locale_t save; size_t res; int result; result = DATEORDER_MDY; /* default */ - save = setlocale(LC_TIME, NULL); - if (!save) - return result; - save = pg_strdup(save); + save = save_global_locale(LC_TIME); setlocale(LC_TIME, locale); @@ -2094,8 +2164,7 @@ locale_date_order(const char *locale) res = my_strftime(buf, sizeof(buf), "%x", &testtime); - setlocale(LC_TIME, save); - free(save); + restore_global_locale(LC_TIME, save); if (res == 0) return result; @@ -2132,18 +2201,17 @@ locale_date_order(const char *locale) static void check_locale_name(int category, const char *locale, char **canonname) { - char *save; + save_locale_t save; char *res; + /* Don't let Windows' non-ASCII locale names in. */ + if (locale && !pg_is_ascii(locale)) + pg_fatal("locale name \"%s\" contains non-ASCII characters", locale); + if (canonname) *canonname = NULL; /* in case of failure */ - save = setlocale(category, NULL); - if (!save) - pg_fatal("setlocale() failed"); - - /* save may be pointing at a modifiable scratch variable, so copy it. */ - save = pg_strdup(save); + save = save_global_locale(category); /* for setlocale() call */ if (!locale) @@ -2157,9 +2225,7 @@ check_locale_name(int category, const char *locale, char **canonname) *canonname = pg_strdup(res); /* restore old value. */ - if (!setlocale(category, save)) - pg_fatal("failed to restore old locale \"%s\"", save); - free(save); + restore_global_locale(category, save); /* complain if locale wasn't valid */ if (res == NULL) @@ -2183,6 +2249,11 @@ check_locale_name(int category, const char *locale, char **canonname) pg_fatal("invalid locale settings; check LANG and LC_* environment variables"); } } + + /* Don't let Windows' non-ASCII locale names out. */ + if (canonname && !pg_is_ascii(*canonname)) + pg_fatal("locale name \"%s\" contains non-ASCII characters", + *canonname); } /* @@ -2408,6 +2479,8 @@ setlocales(void) else if (strcmp(datlocale, "C.UTF-8") == 0 || strcmp(datlocale, "C.UTF8") == 0) canonname = "C.UTF-8"; + else if (strcmp(datlocale, "PG_UNICODE_FAST") == 0) + canonname = "PG_UNICODE_FAST"; else pg_fatal("invalid locale name \"%s\" for builtin provider", datlocale); @@ -2466,6 +2539,7 @@ usage(const char *progname) " set builtin locale name for new databases\n")); printf(_(" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n")); + printf(_(" --no-data-checksums do not use data page checksums\n")); printf(_(" --pwfile=FILE read password for the new superuser from file\n")); printf(_(" -T, --text-search-config=CFG\n" " default text search configuration\n")); @@ -2480,6 +2554,7 @@ usage(const char *progname) printf(_(" -L DIRECTORY where to find the input files\n")); printf(_(" -n, --no-clean do not clean up after errors\n")); printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n")); + printf(_(" --no-sync-data-files do not sync files within database directories\n")); printf(_(" --no-instructions do not print instructions for next steps\n")); printf(_(" -s, --show show internal settings, then exit\n")); printf(_(" --sync-method=METHOD set method for syncing files to disk\n")); @@ -2700,7 +2775,9 @@ setup_locale_encoding(void) if (locale_provider == COLLPROVIDER_BUILTIN) { - if (strcmp(datlocale, "C.UTF-8") == 0 && encodingid != PG_UTF8) + if ((strcmp(datlocale, "C.UTF-8") == 0 || + strcmp(datlocale, "PG_UNICODE_FAST") == 0) && + encodingid != PG_UTF8) pg_fatal("builtin provider locale \"%s\" requires encoding \"%s\"", datlocale, "UTF-8"); } @@ -2792,27 +2869,18 @@ setup_text_search(void) void setup_signals(void) { - /* some of these are not valid on Windows */ -#ifdef SIGHUP - pqsignal(SIGHUP, trapsig); -#endif -#ifdef SIGINT pqsignal(SIGINT, trapsig); -#endif -#ifdef SIGQUIT - pqsignal(SIGQUIT, trapsig); -#endif -#ifdef SIGTERM pqsignal(SIGTERM, trapsig); -#endif + + /* the following are not valid on Windows */ +#ifndef WIN32 + pqsignal(SIGHUP, trapsig); + pqsignal(SIGQUIT, trapsig); /* Ignore SIGPIPE when writing to backend, so we can clean up */ -#ifdef SIGPIPE pqsignal(SIGPIPE, SIG_IGN); -#endif /* Prevent SIGSYS so we can probe for kernel calls that might not work */ -#ifdef SIGSYS pqsignal(SIGSYS, SIG_IGN); #endif } @@ -3128,6 +3196,8 @@ main(int argc, char *argv[]) {"icu-locale", required_argument, NULL, 17}, {"icu-rules", required_argument, NULL, 18}, {"sync-method", required_argument, NULL, 19}, + {"no-data-checksums", no_argument, NULL, 20}, + {"no-sync-data-files", no_argument, NULL, 21}, {NULL, 0, NULL, 0} }; @@ -3319,6 +3389,12 @@ main(int argc, char *argv[]) if (!parse_sync_method(optarg, &sync_method)) exit(1); break; + case 20: + data_checksums = false; + break; + case 21: + sync_data_files = false; + break; default: /* getopt_long already emitted a complaint */ pg_log_error_hint("Try \"%s --help\" for more information.", progname); @@ -3370,7 +3446,7 @@ main(int argc, char *argv[]) fputs(_("syncing data to disk ... "), stdout); fflush(stdout); - sync_pgdata(pg_data, PG_VERSION_NUM, sync_method); + sync_pgdata(pg_data, PG_VERSION_NUM, sync_method, sync_data_files); check_ok(); return 0; } @@ -3433,7 +3509,7 @@ main(int argc, char *argv[]) { fputs(_("syncing data to disk ... "), stdout); fflush(stdout); - sync_pgdata(pg_data, PG_VERSION_NUM, sync_method); + sync_pgdata(pg_data, PG_VERSION_NUM, sync_method, sync_data_files); check_ok(); } else diff --git a/src/bin/initdb/meson.build b/src/bin/initdb/meson.build index 7dc5ed6e77e4e..06958e370f320 100644 --- a/src/bin/initdb/meson.build +++ b/src/bin/initdb/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group initdb_sources = files( 'findtimezone.c', diff --git a/src/bin/initdb/po/de.po b/src/bin/initdb/po/de.po index 5d59324b55797..43ea62f18273a 100644 --- a/src/bin/initdb/po/de.po +++ b/src/bin/initdb/po/de.po @@ -1,14 +1,14 @@ # German message translation file for initdb. -# Peter Eisentraut , 2003 - 2024. +# Peter Eisentraut , 2003 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-19 21:51+0000\n" -"PO-Revision-Date: 2024-06-20 10:36+0200\n" +"POT-Creation-Date: 2025-04-03 12:22+0000\n" +"PO-Revision-Date: 2025-04-03 16:13+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,22 +16,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -56,28 +56,28 @@ msgstr "konnte kein »%s« zum Ausführen finden" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "konnte Pfad »%s« nicht in absolute Form auflösen: %m" -#: ../../common/exec.c:382 initdb.c:695 +#: ../../common/exec.c:363 initdb.c:753 #, c-format msgid "could not execute command \"%s\": %m" msgstr "konnte Befehl »%s« nicht ausführen: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "konnte nicht von Befehl »%s« lesen: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "Befehl »%s« gab keine Daten zurück" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s() fehlgeschlagen: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 -#: initdb.c:353 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 +#: initdb.c:375 initdb.c:411 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" @@ -93,46 +93,46 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -241,12 +241,12 @@ msgstr "%s muss im Bereich %d..%d sein" msgid "unrecognized sync method: %s" msgstr "unbekannte Sync-Methode: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" @@ -261,274 +261,294 @@ msgstr "konnte Junction für »%s« nicht erzeugen: %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "konnte Junction für »%s« nicht ermitteln: %s\n" -#: initdb.c:627 initdb.c:1619 +#: initdb.c:372 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale() fehlgeschlagen" + +#: initdb.c:379 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale() fehlgeschlagen" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale" +msgstr "konnte alte Locale nicht wiederherstellen" + +#: initdb.c:396 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "konnte alte Locale »%s« nicht wiederherstellen" + +#: initdb.c:685 initdb.c:1700 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m" -#: initdb.c:671 initdb.c:975 initdb.c:995 +#: initdb.c:729 initdb.c:1035 initdb.c:1055 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "konnte Datei »%s« nicht zum Schreiben öffnen: %m" -#: initdb.c:675 initdb.c:978 initdb.c:997 +#: initdb.c:733 initdb.c:1038 initdb.c:1057 #, c-format msgid "could not write file \"%s\": %m" msgstr "konnte Datei »%s« nicht schreiben: %m" -#: initdb.c:679 +#: initdb.c:737 #, c-format msgid "could not close file \"%s\": %m" msgstr "konnte Datei »%s« nicht schließen: %m" -#: initdb.c:713 +#: initdb.c:771 #, c-format msgid "removing data directory \"%s\"" msgstr "entferne Datenverzeichnis »%s«" -#: initdb.c:715 +#: initdb.c:773 #, c-format msgid "failed to remove data directory" msgstr "konnte Datenverzeichnis nicht entfernen" -#: initdb.c:719 +#: initdb.c:777 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "entferne Inhalt des Datenverzeichnisses »%s«" -#: initdb.c:722 +#: initdb.c:780 #, c-format msgid "failed to remove contents of data directory" msgstr "konnte Inhalt des Datenverzeichnisses nicht entfernen" -#: initdb.c:727 +#: initdb.c:785 #, c-format msgid "removing WAL directory \"%s\"" msgstr "entferne WAL-Verzeichnis »%s«" -#: initdb.c:729 +#: initdb.c:787 #, c-format msgid "failed to remove WAL directory" msgstr "konnte WAL-Verzeichnis nicht entfernen" -#: initdb.c:733 +#: initdb.c:791 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "entferne Inhalt des WAL-Verzeichnisses »%s«" -#: initdb.c:735 +#: initdb.c:793 #, c-format msgid "failed to remove contents of WAL directory" msgstr "konnte Inhalt des WAL-Verzeichnisses nicht entfernen" -#: initdb.c:742 +#: initdb.c:800 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "Datenverzeichnis »%s« wurde auf Anwenderwunsch nicht entfernt" -#: initdb.c:746 +#: initdb.c:804 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "WAL-Verzeichnis »%s« wurde auf Anwenderwunsch nicht entfernt" -#: initdb.c:764 +#: initdb.c:822 #, c-format msgid "cannot be run as root" msgstr "kann nicht als root ausgeführt werden" -#: initdb.c:765 +#: initdb.c:823 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "Bitte loggen Sie sich (z.B. mit »su«) als der (unprivilegierte) Benutzer ein, der Eigentümer des Serverprozesses sein soll." -#: initdb.c:797 +#: initdb.c:855 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "»%s« ist keine gültige Serverkodierung" -#: initdb.c:941 +#: initdb.c:1001 #, c-format msgid "file \"%s\" does not exist" msgstr "Datei »%s« existiert nicht" -#: initdb.c:942 initdb.c:947 initdb.c:954 +#: initdb.c:1002 initdb.c:1007 initdb.c:1014 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "Das könnte bedeuten, dass Ihre Installation fehlerhaft ist oder dass Sie das falsche Verzeichnis mit der Kommandozeilenoption -L angegeben haben." -#: initdb.c:946 +#: initdb.c:1006 #, c-format msgid "could not access file \"%s\": %m" msgstr "konnte nicht auf Datei »%s« zugreifen: %m" -#: initdb.c:953 +#: initdb.c:1013 #, c-format msgid "file \"%s\" is not a regular file" msgstr "Datei »%s« ist keine normale Datei" -#: initdb.c:1086 +#: initdb.c:1158 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "wähle Implementierung von dynamischem Shared Memory ... " -#: initdb.c:1095 +#: initdb.c:1168 #, c-format msgid "selecting default \"max_connections\" ... " msgstr "wähle Vorgabewert für »max_connections« ... " -#: initdb.c:1115 +#: initdb.c:1193 +#, c-format +msgid "selecting default \"autovacuum_worker_slots\" ... %d\n" +msgstr "wähle Vorgabewert für »autovacuum_worker_slots« ... %d\n" + +#: initdb.c:1196 #, c-format msgid "selecting default \"shared_buffers\" ... " msgstr "wähle Vorgabewert für »shared_buffers« ... " -#: initdb.c:1138 +#: initdb.c:1219 #, c-format msgid "selecting default time zone ... " msgstr "wähle Vorgabewert für Zeitzone ... " -#: initdb.c:1217 +#: initdb.c:1299 msgid "creating configuration files ... " msgstr "erzeuge Konfigurationsdateien ... " -#: initdb.c:1370 initdb.c:1384 initdb.c:1451 initdb.c:1462 +#: initdb.c:1451 initdb.c:1465 initdb.c:1532 initdb.c:1543 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "konnte Zugriffsrechte von »%s« nicht ändern: %m" -#: initdb.c:1481 +#: initdb.c:1562 #, c-format msgid "running bootstrap script ... " msgstr "führe Bootstrap-Skript aus ... " -#: initdb.c:1493 +#: initdb.c:1574 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "Eingabedatei »%s« gehört nicht zu PostgreSQL %s" -#: initdb.c:1495 +#: initdb.c:1576 #, c-format msgid "Specify the correct path using the option -L." msgstr "Geben Sie den korrekten Pfad mit der Option -L an." -#: initdb.c:1597 +#: initdb.c:1678 msgid "Enter new superuser password: " msgstr "Geben Sie das neue Superuser-Passwort ein: " -#: initdb.c:1598 +#: initdb.c:1679 msgid "Enter it again: " msgstr "Geben Sie es noch einmal ein: " -#: initdb.c:1601 +#: initdb.c:1682 #, c-format msgid "Passwords didn't match.\n" msgstr "Passwörter stimmten nicht überein.\n" -#: initdb.c:1625 +#: initdb.c:1706 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "konnte Passwort nicht aus Datei »%s« lesen: %m" -#: initdb.c:1628 +#: initdb.c:1709 #, c-format msgid "password file \"%s\" is empty" msgstr "Passwortdatei »%s« ist leer" -#: initdb.c:2040 +#: initdb.c:2121 #, c-format msgid "caught signal\n" msgstr "Signal abgefangen\n" -#: initdb.c:2046 +#: initdb.c:2127 #, c-format msgid "could not write to child process: %s\n" msgstr "konnte nicht an Kindprozess schreiben: %s\n" -#: initdb.c:2054 +#: initdb.c:2135 #, c-format msgid "ok\n" msgstr "ok\n" -#: initdb.c:2143 -#, c-format -msgid "setlocale() failed" -msgstr "setlocale() fehlgeschlagen" - -#: initdb.c:2161 +#: initdb.c:2217 initdb.c:2263 #, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "konnte alte Locale »%s« nicht wiederherstellen" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "Locale-Name »%s« enthält Nicht-ASCII-Zeichen" -#: initdb.c:2169 +#: initdb.c:2243 #, c-format msgid "invalid locale name \"%s\"" msgstr "ungültiger Locale-Name: »%s«" -#: initdb.c:2170 +#: initdb.c:2244 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "Wenn der Locale-Name nur für ICU gültig ist, verwenden Sie --icu-locale." -#: initdb.c:2183 +#: initdb.c:2257 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "ungültige Locale-Einstellungen; prüfen Sie die Umgebungsvariablen LANG und LC_*" -#: initdb.c:2209 initdb.c:2233 +#: initdb.c:2288 initdb.c:2312 #, c-format msgid "encoding mismatch" msgstr "unpassende Kodierungen" -#: initdb.c:2210 +#: initdb.c:2289 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "Die von Ihnen gewählte Kodierung (%s) und die von der gewählten Locale verwendete Kodierung (%s) passen nicht zu einander. Das würde in verschiedenen Zeichenkettenfunktionen zu Fehlverhalten führen." -#: initdb.c:2215 initdb.c:2236 +#: initdb.c:2294 initdb.c:2315 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "Starten Sie %s erneut und geben Sie entweder keine Kodierung explizit an oder wählen Sie eine passende Kombination." -#: initdb.c:2234 +#: initdb.c:2313 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "Die von Ihnen gewählte Kodierung (%s) wird vom ICU-Provider nicht unterstützt." -#: initdb.c:2285 +#: initdb.c:2364 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "konnte Locale-Namen »%s« nicht in Sprach-Tag umwandeln: %s" -#: initdb.c:2291 initdb.c:2343 initdb.c:2435 +#: initdb.c:2370 initdb.c:2422 initdb.c:2516 #, c-format msgid "ICU is not supported in this build" msgstr "ICU wird in dieser Installation nicht unterstützt" -#: initdb.c:2314 +#: initdb.c:2393 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "konnte Sprache nicht aus Locale »%s« ermitteln: %s" -#: initdb.c:2340 +#: initdb.c:2419 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "Locale »%s« hat unbekannte Sprache »%s«" -#: initdb.c:2401 +#: initdb.c:2480 #, c-format msgid "locale must be specified if provider is %s" msgstr "Locale muss angegeben werden, wenn der Provider %s ist" -#: initdb.c:2412 +#: initdb.c:2493 #, c-format msgid "invalid locale name \"%s\" for builtin provider" msgstr "ungültiger Locale-Name »%s« für Provider »builtin«" -#: initdb.c:2423 +#: initdb.c:2504 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "Verwende Sprach-Tag »%s« für ICU-Locale »%s«.\n" -#: initdb.c:2446 +#: initdb.c:2527 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -537,17 +557,17 @@ msgstr "" "%s initialisiert einen PostgreSQL-Datenbankcluster.\n" "\n" -#: initdb.c:2447 +#: initdb.c:2528 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: initdb.c:2448 +#: initdb.c:2529 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATENVERZEICHNIS]\n" -#: initdb.c:2449 +#: initdb.c:2530 #, c-format msgid "" "\n" @@ -556,65 +576,65 @@ msgstr "" "\n" "Optionen:\n" -#: initdb.c:2450 +#: initdb.c:2531 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, --auth=METHODE vorgegebene Authentifizierungsmethode für lokale Verbindungen\n" -#: initdb.c:2451 +#: initdb.c:2532 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr "" " --auth-host=METHODE vorgegebene Authentifizierungsmethode für lokale\n" " TCP/IP-Verbindungen\n" -#: initdb.c:2452 +#: initdb.c:2533 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr "" " --auth-local=METHODE vorgegebene Authentifizierungsmethode für Verbindungen\n" " auf lokalen Sockets\n" -#: initdb.c:2453 +#: initdb.c:2534 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATENVERZ Datenverzeichnis für diesen Datenbankcluster\n" -#: initdb.c:2454 +#: initdb.c:2535 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=KODIERUNG setze Standardkodierung für neue Datenbanken\n" -#: initdb.c:2455 +#: initdb.c:2536 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr "" " -g, --allow-group-access Lese- und Ausführungsrechte am Datenverzeichnis\n" " für Gruppe setzen\n" -#: initdb.c:2456 +#: initdb.c:2537 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOCALE setze ICU-Locale-ID für neue Datenbanken\n" -#: initdb.c:2457 +#: initdb.c:2538 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" msgstr "" " --icu-rules=REGELN setze zusätzliche ICU-Sortierfolgenregeln für neue\n" " Datenbanken\n" -#: initdb.c:2458 +#: initdb.c:2539 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums Datenseitenprüfsummen verwenden\n" -#: initdb.c:2459 +#: initdb.c:2540 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=LOCALE setze Standardlocale für neue Datenbanken\n" -#: initdb.c:2460 +#: initdb.c:2541 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -628,12 +648,12 @@ msgstr "" " für neue Datenbanken (Voreinstellung aus der\n" " Umgebung entnommen)\n" -#: initdb.c:2464 +#: initdb.c:2545 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale entspricht --locale=C\n" -#: initdb.c:2465 +#: initdb.c:2546 #, c-format msgid "" " --builtin-locale=LOCALE\n" @@ -642,7 +662,7 @@ msgstr "" " --builtin-locale=LOCALE\n" " setze Locale für Provider »builtin« für neue Datenbanken\n" -#: initdb.c:2467 +#: initdb.c:2548 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -651,12 +671,17 @@ msgstr "" " --locale-provider={builtin|libc|icu}\n" " setze Standard-Locale-Provider für neue Datenbanken\n" -#: initdb.c:2469 +#: initdb.c:2550 +#, c-format +msgid " --no-data-checksums do not use data page checksums\n" +msgstr " --no-data-checksums Datenseitenprüfsummen nicht verwenden\n" + +#: initdb.c:2551 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=DATEI lese Passwort des neuen Superusers aus Datei\n" -#: initdb.c:2470 +#: initdb.c:2552 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -665,27 +690,27 @@ msgstr "" " -T, --text-search-config=KFG\n" " Standardtextsuchekonfiguration\n" -#: initdb.c:2472 +#: initdb.c:2554 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NAME Datenbank-Superusername\n" -#: initdb.c:2473 +#: initdb.c:2555 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt frage nach Passwort für neuen Superuser\n" -#: initdb.c:2474 +#: initdb.c:2556 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALVERZ Verzeichnis für das Write-Ahead-Log\n" -#: initdb.c:2475 +#: initdb.c:2557 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=ZAHL Größe eines WAL-Segments, in Megabyte\n" -#: initdb.c:2476 +#: initdb.c:2558 #, c-format msgid "" "\n" @@ -694,63 +719,68 @@ msgstr "" "\n" "Weniger häufig verwendete Optionen:\n" -#: initdb.c:2477 +#: initdb.c:2559 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAME=WERT Voreinstellung für Serverparameter setzen\n" -#: initdb.c:2478 +#: initdb.c:2560 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug erzeuge eine Menge Debug-Ausgaben\n" -#: initdb.c:2479 +#: initdb.c:2561 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches debug_discard_caches=1 setzen\n" -#: initdb.c:2480 +#: initdb.c:2562 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L VERZEICHNIS wo sind die Eingabedateien zu finden\n" -#: initdb.c:2481 +#: initdb.c:2563 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean nach Fehlern nicht aufräumen\n" -#: initdb.c:2482 +#: initdb.c:2564 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n" " geschrieben sind\n" -#: initdb.c:2483 +#: initdb.c:2565 +#, c-format +msgid " --no-sync-data-files do not sync files within database directories\n" +msgstr " --no-sync-data-files Dateien in Datenbankverzeichnissen nicht synchronisieren\n" + +#: initdb.c:2566 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions Anleitung für nächste Schritte nicht ausgeben\n" -#: initdb.c:2484 +#: initdb.c:2567 #, c-format msgid " -s, --show show internal settings, then exit\n" msgstr " -s, --show interne Einstellungen zeigen, dann beenden\n" -#: initdb.c:2485 +#: initdb.c:2568 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHODE Methode zum Synchronisieren vond Dateien auf\n" " Festplatte setzen\n" -#: initdb.c:2486 +#: initdb.c:2569 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr "" " -S, --sync-only nur Datenbankdateien auf Festplatte synchronisieren,\n" " dann beenden\n" -#: initdb.c:2487 +#: initdb.c:2570 #, c-format msgid "" "\n" @@ -759,17 +789,17 @@ msgstr "" "\n" "Weitere Optionen:\n" -#: initdb.c:2488 +#: initdb.c:2571 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: initdb.c:2489 +#: initdb.c:2572 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: initdb.c:2490 +#: initdb.c:2573 #, c-format msgid "" "\n" @@ -780,7 +810,7 @@ msgstr "" "Wenn kein Datenverzeichnis angegeben ist, dann wird die Umgebungsvariable\n" "PGDATA verwendet.\n" -#: initdb.c:2492 +#: initdb.c:2575 #, c-format msgid "" "\n" @@ -789,72 +819,72 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: initdb.c:2493 +#: initdb.c:2576 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: initdb.c:2517 +#: initdb.c:2600 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "ungültige Authentifizierungsmethode »%s« für »%s«-Verbindungen" -#: initdb.c:2531 +#: initdb.c:2614 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "Superuser-Passwort muss angegeben werden um Passwortauthentifizierung einzuschalten" -#: initdb.c:2550 +#: initdb.c:2633 #, c-format msgid "no data directory specified" msgstr "kein Datenverzeichnis angegeben" -#: initdb.c:2551 +#: initdb.c:2634 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "Sie müssen das Verzeichnis angeben, wo dieses Datenbanksystem abgelegt werden soll. Machen Sie dies entweder mit der Kommandozeilenoption -D oder mit der Umgebungsvariable PGDATA." -#: initdb.c:2568 +#: initdb.c:2651 #, c-format msgid "could not set environment" msgstr "konnte Umgebung nicht setzen" -#: initdb.c:2586 +#: initdb.c:2669 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden" -#: initdb.c:2589 +#: initdb.c:2672 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s" -#: initdb.c:2604 +#: initdb.c:2687 #, c-format msgid "input file location must be an absolute path" msgstr "Eingabedatei muss absoluten Pfad haben" -#: initdb.c:2621 +#: initdb.c:2704 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "Der Datenbankcluster wird mit der Locale »%s« initialisiert werden.\n" -#: initdb.c:2624 +#: initdb.c:2707 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "Der Datenbankcluster wird mit dieser Locale-Konfiguration initialisiert werden:\n" -#: initdb.c:2625 +#: initdb.c:2708 #, c-format msgid " locale provider: %s\n" msgstr " Locale-Provider: %s\n" -#: initdb.c:2627 +#: initdb.c:2710 #, c-format msgid " default collation: %s\n" msgstr " Standardsortierfolge: %s\n" -#: initdb.c:2628 +#: initdb.c:2711 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -871,22 +901,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2658 +#: initdb.c:2741 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "konnte keine passende Kodierung für Locale »%s« finden" -#: initdb.c:2660 +#: initdb.c:2743 #, c-format msgid "Rerun %s with the -E option." msgstr "Führen Sie %s erneut mit der Option -E aus." -#: initdb.c:2661 initdb.c:3204 initdb.c:3324 initdb.c:3344 +#: initdb.c:2744 initdb.c:3282 initdb.c:3408 initdb.c:3428 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: initdb.c:2673 +#: initdb.c:2756 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -895,112 +925,112 @@ msgstr "" "Die von der Locale gesetzte Kodierung »%s« ist nicht als serverseitige Kodierung erlaubt.\n" "Die Standarddatenbankkodierung wird stattdessen auf »%s« gesetzt.\n" -#: initdb.c:2678 +#: initdb.c:2761 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "Locale »%s« benötigt nicht unterstützte Kodierung »%s«" -#: initdb.c:2680 +#: initdb.c:2763 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "Kodierung »%s« ist nicht als serverseitige Kodierung erlaubt." -#: initdb.c:2682 +#: initdb.c:2765 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Starten Sie %s erneut mit einer anderen Locale-Wahl." -#: initdb.c:2690 +#: initdb.c:2773 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "Die Standarddatenbankkodierung wurde entsprechend auf »%s« gesetzt.\n" -#: initdb.c:2704 +#: initdb.c:2789 #, c-format msgid "builtin provider locale \"%s\" requires encoding \"%s\"" msgstr "Locale »%s« vom Provider »builtin« benötigt Kodierung »%s«" -#: initdb.c:2766 +#: initdb.c:2851 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "konnte keine passende Textsuchekonfiguration für Locale »%s« finden" -#: initdb.c:2777 +#: initdb.c:2862 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "passende Textsuchekonfiguration für Locale »%s« ist unbekannt" -#: initdb.c:2782 +#: initdb.c:2867 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "angegebene Textsuchekonfiguration »%s« passt möglicherweise nicht zur Locale »%s«" -#: initdb.c:2787 +#: initdb.c:2872 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "Die Standardtextsuchekonfiguration wird auf »%s« gesetzt.\n" -#: initdb.c:2830 initdb.c:2901 +#: initdb.c:2906 initdb.c:2977 #, c-format msgid "creating directory %s ... " msgstr "erzeuge Verzeichnis %s ... " -#: initdb.c:2835 initdb.c:2906 initdb.c:2954 initdb.c:3011 +#: initdb.c:2911 initdb.c:2982 initdb.c:3030 initdb.c:3087 #, c-format msgid "could not create directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" -#: initdb.c:2844 initdb.c:2916 +#: initdb.c:2920 initdb.c:2992 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "berichtige Zugriffsrechte des bestehenden Verzeichnisses %s ... " -#: initdb.c:2849 initdb.c:2921 +#: initdb.c:2925 initdb.c:2997 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "konnte Rechte des Verzeichnisses »%s« nicht ändern: %m" -#: initdb.c:2861 initdb.c:2933 +#: initdb.c:2937 initdb.c:3009 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "Verzeichnis »%s« existiert aber ist nicht leer" -#: initdb.c:2865 +#: initdb.c:2941 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "Wenn Sie ein neues Datenbanksystem erzeugen wollen, entfernen oder leeren Sie das Verzeichnis »%s« or führen Sie %s mit einem anderen Argument als »%s« aus." -#: initdb.c:2873 initdb.c:2943 initdb.c:3369 +#: initdb.c:2949 initdb.c:3019 initdb.c:3453 #, c-format msgid "could not access directory \"%s\": %m" msgstr "konnte nicht auf Verzeichnis »%s« zugreifen: %m" -#: initdb.c:2894 +#: initdb.c:2970 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL-Verzeichnis muss absoluten Pfad haben" -#: initdb.c:2937 +#: initdb.c:3013 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "Wenn Sie dort den WAL ablegen wollen, entfernen oder leeren Sie das Verzeichnis »%s«." -#: initdb.c:2947 +#: initdb.c:3023 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "konnte symbolische Verknüpfung »%s« nicht erstellen: %m" -#: initdb.c:2966 +#: initdb.c:3042 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "Es enthält eine unsichtbare Datei (beginnt mit Punkt), vielleicht weil es ein Einhängepunkt ist." -#: initdb.c:2968 +#: initdb.c:3044 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Es enthält ein Verzeichnis »lost+found«, vielleicht weil es ein Einhängepunkt ist." -#: initdb.c:2970 +#: initdb.c:3046 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -1009,65 +1039,65 @@ msgstr "" "Einen Einhängepunkt direkt als Datenverzeichnis zu verwenden wird nicht empfohlen.\n" "Erzeugen Sie ein Unterverzeichnis unter dem Einhängepunkt." -#: initdb.c:2997 +#: initdb.c:3073 #, c-format msgid "creating subdirectories ... " msgstr "erzeuge Unterverzeichnisse ... " -#: initdb.c:3040 +#: initdb.c:3116 msgid "performing post-bootstrap initialization ... " msgstr "führe Post-Bootstrap-Initialisierung durch ... " -#: initdb.c:3203 +#: initdb.c:3281 #, c-format msgid "-c %s requires a value" msgstr "-c %s benötigt einen Wert" -#: initdb.c:3228 +#: initdb.c:3306 #, c-format msgid "Running in debug mode.\n" msgstr "Debug-Modus ist an.\n" -#: initdb.c:3232 +#: initdb.c:3310 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "No-Clean-Modus ist an. Bei Fehlern wird nicht aufgeräumt.\n" -#: initdb.c:3305 +#: initdb.c:3383 #, c-format msgid "unrecognized locale provider: %s" msgstr "unbekannter Locale-Provider: %s" -#: initdb.c:3342 +#: initdb.c:3426 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: initdb.c:3349 initdb.c:3353 initdb.c:3357 +#: initdb.c:3433 initdb.c:3437 initdb.c:3441 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s kann nur angegeben werden, wenn Locale-Provider »%s« gewählt ist" -#: initdb.c:3371 initdb.c:3434 +#: initdb.c:3455 initdb.c:3518 msgid "syncing data to disk ... " msgstr "synchronisiere Daten auf Festplatte ... " -#: initdb.c:3379 +#: initdb.c:3463 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "Passwortprompt und Passwortdatei können nicht zusammen angegeben werden" -#: initdb.c:3390 +#: initdb.c:3474 #, c-format msgid "argument of %s must be a power of two between 1 and 1024" msgstr "Argument von %s muss eine Zweierpotenz zwischen 1 und 1024 sein" -#: initdb.c:3403 +#: initdb.c:3487 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "Superuser-Name »%s« nicht erlaubt; Rollennamen können nicht mit »pg_« anfangen" -#: initdb.c:3405 +#: initdb.c:3489 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1078,17 +1108,17 @@ msgstr "" "»%s« gehören. Diesem Benutzer muss auch der Serverprozess gehören.\n" "\n" -#: initdb.c:3421 +#: initdb.c:3505 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Datenseitenprüfsummen sind eingeschaltet.\n" -#: initdb.c:3423 +#: initdb.c:3507 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Datenseitenprüfsummen sind ausgeschaltet.\n" -#: initdb.c:3440 +#: initdb.c:3524 #, c-format msgid "" "\n" @@ -1099,22 +1129,22 @@ msgstr "" "Synchronisation auf Festplatte übersprungen.\n" "Das Datenverzeichnis könnte verfälscht werden, falls das Betriebssystem abstürzt.\n" -#: initdb.c:3445 +#: initdb.c:3529 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "Authentifizierung für lokale Verbindungen auf »trust« gesetzt" -#: initdb.c:3446 +#: initdb.c:3530 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "Sie können dies ändern, indem Sie pg_hba.conf bearbeiten oder beim nächsten Aufruf von initdb die Option -A, oder --auth-local und --auth-host, verwenden." #. translator: This is a placeholder in a shell command. -#: initdb.c:3476 +#: initdb.c:3560 msgid "logfile" msgstr "logdatei" -#: initdb.c:3478 +#: initdb.c:3562 #, c-format msgid "" "\n" diff --git a/src/bin/initdb/po/es.po b/src/bin/initdb/po/es.po index 449d2020a6ecd..1c12d9c641771 100644 --- a/src/bin/initdb/po/es.po +++ b/src/bin/initdb/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: initdb (PostgreSQL) 16\n" +"Project-Id-Version: initdb (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-03 07:20+0000\n" -"PO-Revision-Date: 2023-10-04 11:47+0200\n" +"POT-Creation-Date: 2025-02-16 19:50+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -40,33 +40,48 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:750 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:372 initdb.c:408 #, c-format msgid "out of memory" msgstr "memoria agotada" @@ -82,35 +97,46 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "no se pudo hacer stat al archivo «%s»: %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "no se pudo leer el directorio «%s»: %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" @@ -150,12 +176,12 @@ msgstr "no se pudo re-ejecutar con el token restringido: código de error %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "no se pudo obtener el código de salida del subproceso: código de error %lu" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "no se pudo eliminar el archivo «%s»: %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "no se pudo eliminar el directorio «%s»: %m" @@ -204,6 +230,31 @@ msgstr "el proceso hijo fue terminado por una señal %d: %s" msgid "child process exited with unrecognized status %d" msgstr "el proceso hijo terminó con código no reconocido %d" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "el valor «%s» no es válido para la opción %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s debe estar en el rango %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + #: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" @@ -214,276 +265,291 @@ msgstr "no se pudo definir un junction para «%s»: %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "no se pudo obtener junction para «%s»: %s\n" -#: initdb.c:618 initdb.c:1613 +#: initdb.c:369 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale() falló" + +#: initdb.c:376 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale() falló" + +#: initdb.c:390 +#, c-format +msgid "failed to restore old locale" +msgstr "no se pudo restaurar la configuración regional anterior" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "no se pudo restaurar la configuración regional anterior «%s»" + +#: initdb.c:682 initdb.c:1674 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "no se pudo abrir archivo «%s» para lectura: %m" -#: initdb.c:662 initdb.c:966 initdb.c:986 +#: initdb.c:726 initdb.c:1030 initdb.c:1050 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "no se pudo abrir el archivo «%s» para escritura: %m" -#: initdb.c:666 initdb.c:969 initdb.c:988 +#: initdb.c:730 initdb.c:1033 initdb.c:1052 #, c-format msgid "could not write file \"%s\": %m" msgstr "no se pudo escribir el archivo «%s»: %m" -#: initdb.c:670 +#: initdb.c:734 #, c-format msgid "could not close file \"%s\": %m" msgstr "no se pudo cerrar el archivo «%s»: %m" -#: initdb.c:686 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "no se pudo ejecutar la orden «%s»: %m" - -#: initdb.c:704 +#: initdb.c:768 #, c-format msgid "removing data directory \"%s\"" msgstr "eliminando el directorio de datos «%s»" -#: initdb.c:706 +#: initdb.c:770 #, c-format msgid "failed to remove data directory" msgstr "no se pudo eliminar el directorio de datos" -#: initdb.c:710 +#: initdb.c:774 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "eliminando el contenido del directorio «%s»" -#: initdb.c:713 +#: initdb.c:777 #, c-format msgid "failed to remove contents of data directory" msgstr "no se pudo eliminar el contenido del directorio de datos" -#: initdb.c:718 +#: initdb.c:782 #, c-format msgid "removing WAL directory \"%s\"" msgstr "eliminando el directorio de WAL «%s»" -#: initdb.c:720 +#: initdb.c:784 #, c-format msgid "failed to remove WAL directory" msgstr "no se pudo eliminar el directorio de WAL" -#: initdb.c:724 +#: initdb.c:788 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "eliminando el contenido del directorio de WAL «%s»" -#: initdb.c:726 +#: initdb.c:790 #, c-format msgid "failed to remove contents of WAL directory" msgstr "no se pudo eliminar el contenido del directorio de WAL" -#: initdb.c:733 +#: initdb.c:797 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "directorio de datos «%s» no eliminado a petición del usuario" -#: initdb.c:737 +#: initdb.c:801 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "directorio de WAL «%s» no eliminado a petición del usuario" -#: initdb.c:755 +#: initdb.c:819 #, c-format msgid "cannot be run as root" msgstr "no se puede ejecutar como «root»" -#: initdb.c:756 +#: initdb.c:820 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "Por favor conéctese (usando, por ejemplo, «su») con un usuario no privilegiado, quien ejecutará el proceso servidor." -#: initdb.c:788 +#: initdb.c:852 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "«%s» no es un nombre válido de codificación" -#: initdb.c:932 +#: initdb.c:996 #, c-format msgid "file \"%s\" does not exist" msgstr "el archivo «%s» no existe" -#: initdb.c:933 initdb.c:938 initdb.c:945 +#: initdb.c:997 initdb.c:1002 initdb.c:1009 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "Esto puede significar que tiene una instalación corrupta o ha identificado el directorio equivocado con la opción -L." -#: initdb.c:937 +#: initdb.c:1001 #, c-format msgid "could not access file \"%s\": %m" msgstr "no se pudo acceder al archivo «%s»: %m" -#: initdb.c:944 +#: initdb.c:1008 #, c-format msgid "file \"%s\" is not a regular file" msgstr "el archivo «%s» no es un archivo regular" -#: initdb.c:1077 +#: initdb.c:1141 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "seleccionando implementación de memoria compartida dinámica ... " -#: initdb.c:1086 +#: initdb.c:1150 #, c-format -msgid "selecting default max_connections ... " -msgstr "seleccionando el valor para max_connections ... " +msgid "selecting default \"max_connections\" ... " +msgstr "seleccionando el valor para «max_connections» ... " -#: initdb.c:1106 +#: initdb.c:1170 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "seleccionando el valor para shared_buffers ... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "seleccionando el valor para «shared_buffers» ... " -#: initdb.c:1129 +#: initdb.c:1193 #, c-format msgid "selecting default time zone ... " msgstr "seleccionando el huso horario por omisión ... " -#: initdb.c:1206 +#: initdb.c:1272 msgid "creating configuration files ... " msgstr "creando archivos de configuración ... " -#: initdb.c:1367 initdb.c:1381 initdb.c:1448 initdb.c:1459 +#: initdb.c:1425 initdb.c:1439 initdb.c:1506 initdb.c:1517 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "no se pudo cambiar los permisos de «%s»: %m" -#: initdb.c:1477 +#: initdb.c:1536 #, c-format msgid "running bootstrap script ... " msgstr "ejecutando script de inicio (bootstrap) ... " -#: initdb.c:1489 +#: initdb.c:1548 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "el archivo de entrada «%s» no pertenece a PostgreSQL %s" -#: initdb.c:1491 +#: initdb.c:1550 #, c-format msgid "Specify the correct path using the option -L." msgstr "Especifique la ruta correcta usando la opción -L." -#: initdb.c:1591 +#: initdb.c:1652 msgid "Enter new superuser password: " msgstr "Ingrese la nueva contraseña del superusuario: " -#: initdb.c:1592 +#: initdb.c:1653 msgid "Enter it again: " msgstr "Ingrésela nuevamente: " -#: initdb.c:1595 +#: initdb.c:1656 #, c-format msgid "Passwords didn't match.\n" msgstr "Las contraseñas no coinciden.\n" -#: initdb.c:1619 +#: initdb.c:1680 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "no se pudo leer la contraseña desde el archivo «%s»: %m" -#: initdb.c:1622 +#: initdb.c:1683 #, c-format msgid "password file \"%s\" is empty" msgstr "el archivo de contraseña «%s» está vacío" -#: initdb.c:2034 +#: initdb.c:2095 #, c-format msgid "caught signal\n" msgstr "se ha capturado una señal\n" -#: initdb.c:2040 +#: initdb.c:2101 #, c-format msgid "could not write to child process: %s\n" msgstr "no se pudo escribir al proceso hijo: %s\n" -#: initdb.c:2048 +#: initdb.c:2109 #, c-format msgid "ok\n" msgstr "hecho\n" -#: initdb.c:2137 +#: initdb.c:2191 initdb.c:2237 #, c-format -msgid "setlocale() failed" -msgstr "setlocale() falló" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "el nombre de configuración regional «%s» contiene caracteres no ASCII" -#: initdb.c:2155 -#, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "no se pudo restaurar la configuración regional anterior «%s»" - -#: initdb.c:2163 +#: initdb.c:2217 #, c-format msgid "invalid locale name \"%s\"" msgstr "nombre de configuración regional «%s» no es válido" -#: initdb.c:2164 +#: initdb.c:2218 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." -msgstr "Si el nombre de configuración regional es específico de ICU, use --icu-locale." +msgstr "Si el nombre de configuración regional es específico a ICU, utilice --icu-locale." -#: initdb.c:2177 +#: initdb.c:2231 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "configuración regional inválida; revise las variables de entorno LANG y LC_*" -#: initdb.c:2203 initdb.c:2227 +#: initdb.c:2262 initdb.c:2286 #, c-format msgid "encoding mismatch" msgstr "codificaciones no coinciden" -#: initdb.c:2204 +#: initdb.c:2263 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "La codificación que seleccionó (%s) y la codificación de la configuración regional elegida (%s) no coinciden. Esto llevaría a comportamientos erráticos en ciertas funciones de procesamiento de cadenas de caracteres." -#: initdb.c:2209 initdb.c:2230 +#: initdb.c:2268 initdb.c:2289 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "" "Vuelva a ejecutar %s sin escoger explícitamente una codificación, o bien\n" "escoja una combinación coincidente." -#: initdb.c:2228 +#: initdb.c:2287 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "La codificación que seleccionó (%s) no está soportada con el proveedor ICU." -#: initdb.c:2279 +#: initdb.c:2338 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "no se pudo convertir el nombre de configuración regional «%s» a etiqueta de lenguaje: %s" -#: initdb.c:2285 initdb.c:2337 initdb.c:2416 +#: initdb.c:2344 initdb.c:2396 initdb.c:2488 #, c-format msgid "ICU is not supported in this build" msgstr "ICU no está soportado en este servidor" -#: initdb.c:2308 +#: initdb.c:2367 #, c-format msgid "could not get language from locale \"%s\": %s" -msgstr "no se pudo obtener el lenguaje de la configuración regional «%s»: %s" +msgstr "no se pudo el lenguaje de la configuración regional «%s»: %s" -#: initdb.c:2334 +#: initdb.c:2393 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" -msgstr "la configuración regional «%s» tiene lenguaje «%s» desconocido" +msgstr "la configuración regional «%s» no idioma desconocido «%s»" + +#: initdb.c:2454 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "la configuración regional debe especificarse si el proveedor es %s" -#: initdb.c:2400 +#: initdb.c:2465 #, c-format -msgid "ICU locale must be specified" -msgstr "el locale ICU debe ser especificado" +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "nombre de configuración regional «%s» no válido para el proveedor builtin" -#: initdb.c:2404 +#: initdb.c:2476 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" -msgstr "Usando la marca de lenguaje «%s» para la configuración regional ICU «%s».\n" +msgstr "Usando la etiqueta de idioma «%s» para la configuración regional ICU «%s».\n" -#: initdb.c:2427 +#: initdb.c:2499 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -492,17 +558,17 @@ msgstr "" "%s inicializa un cluster de base de datos PostgreSQL.\n" "\n" -#: initdb.c:2428 +#: initdb.c:2500 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: initdb.c:2429 +#: initdb.c:2501 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPCIÓN]... [DATADIR]\n" -#: initdb.c:2430 +#: initdb.c:2502 #, c-format msgid "" "\n" @@ -511,69 +577,69 @@ msgstr "" "\n" "Opciones:\n" -#: initdb.c:2431 +#: initdb.c:2503 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr "" " -A, --auth=MÉTODO método de autentificación por omisión para\n" " conexiones locales\n" -#: initdb.c:2432 +#: initdb.c:2504 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr "" " --auth-host=MÉTODO método de autentificación por omisión para\n" " conexiones locales TCP/IP\n" -#: initdb.c:2433 +#: initdb.c:2505 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr "" " --auth-local=MÉTODO método de autentificación por omisión para\n" " conexiones de socket local\n" -#: initdb.c:2434 +#: initdb.c:2506 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATADIR ubicación para este cluster de bases de datos\n" -#: initdb.c:2435 +#: initdb.c:2507 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=CODIF codificación por omisión para nuevas bases de datos\n" -#: initdb.c:2436 +#: initdb.c:2508 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr "" " -g, --allow-group-access dar al grupo permisos de lectura/ejecución sobre\n" " el directorio de datos\n" -#: initdb.c:2437 +#: initdb.c:2509 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr "" " --icu-locale=LOCALE definir el ID de configuración regional ICU para\n" " nuevas bases de datos\n" -#: initdb.c:2438 +#: initdb.c:2510 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" -msgstr " --icu-rules=REGLAS reglas adicionales ICU en nuevas bases de datos\n" +msgstr " --icu-rules=REGLAS reglas de ordenamiento ICU adicionales para nuevas bases de datos\n" -#: initdb.c:2439 +#: initdb.c:2511 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums activar sumas de verificación en páginas de datos\n" -#: initdb.c:2440 +#: initdb.c:2512 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr "" " --locale=LOCALE configuración regional por omisión para \n" " nuevas bases de datos\n" -#: initdb.c:2441 +#: initdb.c:2513 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -587,27 +653,37 @@ msgstr "" " en la categoría respectiva (el valor por omisión\n" " es tomado de variables de ambiente)\n" -#: initdb.c:2445 +#: initdb.c:2517 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale equivalente a --locale=C\n" -#: initdb.c:2446 +#: initdb.c:2518 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" --builtin-locale=LOCALE\n" +" define el nombre de configuración regional builtin\n" +" para nuevas bases de datos\n" + +#: initdb.c:2520 +#, c-format +msgid "" +" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " define el proveedor de configuración regional\n" " para nuevas bases de datos\n" -#: initdb.c:2448 +#: initdb.c:2522 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=ARCHIVO leer contraseña del nuevo superusuario del archivo\n" -#: initdb.c:2449 +#: initdb.c:2523 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -616,27 +692,27 @@ msgstr "" " -T, --text-search-config=CONF\n" " configuración de búsqueda en texto por omisión\n" -#: initdb.c:2451 +#: initdb.c:2525 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=USUARIO nombre del superusuario del cluster\n" -#: initdb.c:2452 +#: initdb.c:2526 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt pedir una contraseña para el nuevo superusuario\n" -#: initdb.c:2453 +#: initdb.c:2527 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR ubicación del directorio WAL\n" -#: initdb.c:2454 +#: initdb.c:2528 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=TAMAÑO tamaño de los segmentos de WAL, en megabytes\n" -#: initdb.c:2455 +#: initdb.c:2529 #, c-format msgid "" "\n" @@ -645,52 +721,57 @@ msgstr "" "\n" "Opciones menos usadas:\n" -#: initdb.c:2456 +#: initdb.c:2530 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" -msgstr " -c, --set NOMBRE=VALOR sobreescribe valor por omisión de parámetro de servidor\n" +msgstr " -c, --set VAR=VALOR sobreescribir el valor por omisión del parámetro\n" -#: initdb.c:2457 +#: initdb.c:2531 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug genera mucha salida de depuración\n" -#: initdb.c:2458 +#: initdb.c:2532 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches establece debug_discard_caches=1\n" -#: initdb.c:2459 +#: initdb.c:2533 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L DIRECTORIO donde encontrar los archivos de entrada\n" -#: initdb.c:2460 +#: initdb.c:2534 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean no limpiar después de errores\n" -#: initdb.c:2461 +#: initdb.c:2535 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" -#: initdb.c:2462 +#: initdb.c:2536 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions no mostrar instrucciones para los siguientes pasos\n" -#: initdb.c:2463 +#: initdb.c:2537 +#, c-format +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show muestra variables internas y salir\n" + +#: initdb.c:2538 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show muestra variables internas\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método para sincronizar archivos a disco\n" -#: initdb.c:2464 +#: initdb.c:2539 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only sólo sincronizar el directorio de datos y salir\n" -#: initdb.c:2465 +#: initdb.c:2540 #, c-format msgid "" "\n" @@ -699,17 +780,17 @@ msgstr "" "\n" "Otras opciones:\n" -#: initdb.c:2466 +#: initdb.c:2541 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de version y salir\n" -#: initdb.c:2467 +#: initdb.c:2542 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: initdb.c:2468 +#: initdb.c:2543 #, c-format msgid "" "\n" @@ -720,7 +801,7 @@ msgstr "" "Si el directorio de datos no es especificado, se usa la variable de\n" "ambiente PGDATA.\n" -#: initdb.c:2470 +#: initdb.c:2545 #, c-format msgid "" "\n" @@ -729,72 +810,72 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: initdb.c:2471 +#: initdb.c:2546 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: initdb.c:2499 +#: initdb.c:2570 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "método de autentificación «%s» no válido para conexiones «%s»" -#: initdb.c:2513 +#: initdb.c:2584 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "debe especificar una contraseña al superusuario para activar autentificación mediante contraseña" -#: initdb.c:2532 +#: initdb.c:2603 #, c-format msgid "no data directory specified" msgstr "no se especificó un directorio de datos" -#: initdb.c:2533 +#: initdb.c:2604 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "Debe especificar el directorio donde residirán los datos para este clúster. Hágalo usando la opción -D o la variable de ambiente PGDATA." -#: initdb.c:2550 +#: initdb.c:2621 #, c-format msgid "could not set environment" msgstr "no se pudo establecer el ambiente" -#: initdb.c:2568 +#: initdb.c:2639 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "el programa «%s» es requerido por %s pero se encontró en el mismo directorio que «%s»" -#: initdb.c:2571 +#: initdb.c:2642 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "El programa «%s» fue encontrado por «%s», pero no es de la misma versión que %s" -#: initdb.c:2586 +#: initdb.c:2657 #, c-format msgid "input file location must be an absolute path" msgstr "la ubicación de archivos de entrada debe ser una ruta absoluta" -#: initdb.c:2603 +#: initdb.c:2674 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "El cluster será inicializado con configuración regional «%s».\n" -#: initdb.c:2606 +#: initdb.c:2677 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "El cluster será inicializado con esta configuración regional:\n" -#: initdb.c:2607 +#: initdb.c:2678 #, c-format -msgid " provider: %s\n" -msgstr " proveedor: %s\n" +msgid " locale provider: %s\n" +msgstr " proveedor de configuración regional: %s\n" -#: initdb.c:2609 +#: initdb.c:2680 #, c-format -msgid " ICU locale: %s\n" -msgstr " Locale ICU: %s\n" +msgid " default collation: %s\n" +msgstr " ordenamiento por omisión: %s\n" -#: initdb.c:2610 +#: initdb.c:2681 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -811,22 +892,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2640 +#: initdb.c:2711 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "no se pudo encontrar una codificación apropiada para la configuración regional «%s»" -#: initdb.c:2642 +#: initdb.c:2713 #, c-format msgid "Rerun %s with the -E option." msgstr "Ejecute %s nuevamente con la opción -E." -#: initdb.c:2643 initdb.c:3176 initdb.c:3284 initdb.c:3304 +#: initdb.c:2714 initdb.c:3257 initdb.c:3377 initdb.c:3397 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: initdb.c:2655 +#: initdb.c:2726 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -836,109 +917,114 @@ msgstr "" "no puede ser usada como codificación del lado del servidor.\n" "La codificación por omisión será «%s».\n" -#: initdb.c:2660 +#: initdb.c:2731 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "la configuración regional «%s» requiere la codificación no soportada «%s»" -#: initdb.c:2662 +#: initdb.c:2733 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "La codificación «%s» no puede ser usada como codificación del lado del servidor." -#: initdb.c:2664 +#: initdb.c:2735 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Ejecute %s nuevamente con opciones de configuración regional diferente." -#: initdb.c:2672 +#: initdb.c:2743 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "La codificación por omisión ha sido por lo tanto definida a «%s».\n" -#: initdb.c:2741 +#: initdb.c:2757 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "la configuración regional «%s» del proveedor builtin requiere la codificación «%s»" + +#: initdb.c:2819 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "" "no se pudo encontrar una configuración para búsqueda en texto apropiada\n" "para la configuración regional «%s»" -#: initdb.c:2752 +#: initdb.c:2830 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "la configuración de búsqueda en texto apropiada para la configuración regional «%s» es desconocida" -#: initdb.c:2757 +#: initdb.c:2835 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "la configuración de búsqueda en texto «%s» especificada podría no coincidir con la configuración regional «%s»" -#: initdb.c:2762 +#: initdb.c:2840 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "La configuración de búsqueda en texto ha sido definida a «%s».\n" -#: initdb.c:2805 initdb.c:2876 +#: initdb.c:2883 initdb.c:2954 #, c-format msgid "creating directory %s ... " msgstr "creando el directorio %s ... " -#: initdb.c:2810 initdb.c:2881 initdb.c:2929 initdb.c:2985 +#: initdb.c:2888 initdb.c:2959 initdb.c:3007 initdb.c:3064 #, c-format msgid "could not create directory \"%s\": %m" msgstr "no se pudo crear el directorio «%s»: %m" -#: initdb.c:2819 initdb.c:2891 +#: initdb.c:2897 initdb.c:2969 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "corrigiendo permisos en el directorio existente %s ... " -#: initdb.c:2824 initdb.c:2896 +#: initdb.c:2902 initdb.c:2974 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "no se pudo cambiar los permisos del directorio «%s»: %m" -#: initdb.c:2836 initdb.c:2908 +#: initdb.c:2914 initdb.c:2986 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "el directorio «%s» existe pero no está vacío" -#: initdb.c:2840 +#: initdb.c:2918 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "Si quiere crear un nuevo cluster de bases de datos, elimine o vacíe el directorio «%s», o ejecute %s con un argumento distinto de «%s»." -#: initdb.c:2848 initdb.c:2918 initdb.c:3325 +#: initdb.c:2926 initdb.c:2996 initdb.c:3422 #, c-format msgid "could not access directory \"%s\": %m" msgstr "no se pudo acceder al directorio «%s»: %m" -#: initdb.c:2869 +#: initdb.c:2947 #, c-format msgid "WAL directory location must be an absolute path" msgstr "la ubicación del directorio de WAL debe ser una ruta absoluta" -#: initdb.c:2912 +#: initdb.c:2990 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "Si quiere almacenar el WAL ahí, elimine o vacíe el directorio «%s»." -#: initdb.c:2922 +#: initdb.c:3000 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "no se pudo crear el enlace simbólico «%s»: %m" -#: initdb.c:2941 +#: initdb.c:3019 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "Contiene un archivo invisible o que empieza con un punto (.), quizás por ser un punto de montaje." -#: initdb.c:2943 +#: initdb.c:3021 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Contiene un directorio lost+found, quizás por ser un punto de montaje." -#: initdb.c:2945 +#: initdb.c:3023 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -947,72 +1033,67 @@ msgstr "" "Usar un punto de montaje directamente como directorio de datos no es recomendado.\n" "Cree un subdirectorio bajo el punto de montaje." -#: initdb.c:2971 +#: initdb.c:3050 #, c-format msgid "creating subdirectories ... " msgstr "creando subdirectorios ... " -#: initdb.c:3014 +#: initdb.c:3093 msgid "performing post-bootstrap initialization ... " msgstr "realizando inicialización post-bootstrap ... " -#: initdb.c:3175 +#: initdb.c:3256 #, c-format msgid "-c %s requires a value" msgstr "-c %s requiere un valor" -#: initdb.c:3200 +#: initdb.c:3281 #, c-format msgid "Running in debug mode.\n" msgstr "Ejecutando en modo de depuración.\n" -#: initdb.c:3204 +#: initdb.c:3285 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "Ejecutando en modo no-clean. Los errores no serán limpiados.\n" -#: initdb.c:3274 +#: initdb.c:3358 #, c-format msgid "unrecognized locale provider: %s" msgstr "proveedor de ordenamiento no reconocido: %s" -#: initdb.c:3302 +#: initdb.c:3395 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: initdb.c:3309 initdb.c:3313 +#: initdb.c:3402 initdb.c:3406 initdb.c:3410 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s no puede especificarse a menos que el proveedor de locale «%s» sea escogido" -#: initdb.c:3327 initdb.c:3404 +#: initdb.c:3424 initdb.c:3487 msgid "syncing data to disk ... " msgstr "sincronizando los datos a disco ... " -#: initdb.c:3335 +#: initdb.c:3432 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "" "la petición de contraseña y el archivo de contraseña no pueden\n" "ser especificados simultáneamente" -#: initdb.c:3357 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "el argumento de --wal-segsize debe ser un número" - -#: initdb.c:3359 +#: initdb.c:3443 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "el argumento de --wal-segsize debe ser una potencia de dos entre 1 y 1024" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "el argumento de %s debe ser una potencia de dos entre 1 y 1024" -#: initdb.c:3373 +#: initdb.c:3456 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "nombre de superusuario «%s» no permitido; los nombres de rol no pueden comenzar con «pg_»" -#: initdb.c:3375 +#: initdb.c:3458 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1023,17 +1104,17 @@ msgstr "" "Este usuario también debe ser quien ejecute el proceso servidor.\n" "\n" -#: initdb.c:3391 +#: initdb.c:3474 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Las sumas de verificación en páginas de datos han sido activadas.\n" -#: initdb.c:3393 +#: initdb.c:3476 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Las sumas de verificación en páginas de datos han sido desactivadas.\n" -#: initdb.c:3410 +#: initdb.c:3493 #, c-format msgid "" "\n" @@ -1045,22 +1126,22 @@ msgstr "" "El directorio de datos podría corromperse si el sistema operativo sufre\n" "una caída.\n" -#: initdb.c:3415 +#: initdb.c:3498 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "activando el método de autentificación «trust» para conexiones locales" -#: initdb.c:3416 +#: initdb.c:3499 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "Puede cambiar esto editando pg_hba.conf o usando el parámetro -A, o --auth-local y --auth-host la próxima vez que ejecute initdb." #. translator: This is a placeholder in a shell command. -#: initdb.c:3446 +#: initdb.c:3529 msgid "logfile" msgstr "archivo_de_registro" -#: initdb.c:3448 +#: initdb.c:3531 #, c-format msgid "" "\n" diff --git a/src/bin/initdb/po/fr.po b/src/bin/initdb/po/fr.po index a175e105d711c..c8a155a62bbeb 100644 --- a/src/bin/initdb/po/fr.po +++ b/src/bin/initdb/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-05 17:20+0000\n" -"PO-Revision-Date: 2023-09-05 22:01+0200\n" +"POT-Creation-Date: 2024-10-29 18:21+0000\n" +"PO-Revision-Date: 2024-10-30 07:41+0100\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -43,33 +43,48 @@ msgstr "détail : " msgid "hint: " msgstr "astuce : " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binaire « %s » invalide : %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "n'a pas pu lire le binaire « %s » : %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "n'a pas pu trouver un « %s » à exécuter" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "n'a pas pu résoudre le chemin « %s » en sa forme absolue : %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:750 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "n'a pas pu exécuter la commande « %s » : %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "n'a pas pu lire à partir de la commande « %s » : %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "aucune donnée n'a été renvoyée par la commande « %s »" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:372 initdb.c:408 #, c-format msgid "out of memory" msgstr "mémoire épuisée" @@ -85,35 +100,46 @@ msgstr "mémoire épuisée\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "n'a pas pu tester le fichier « %s » : %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "n'a pas pu lire le répertoire « %s » : %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" @@ -153,12 +179,12 @@ msgstr "n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "n'a pas pu supprimer le fichier « %s » : %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "n'a pas pu supprimer le répertoire « %s » : %m" @@ -207,6 +233,31 @@ msgstr "le processus fils a été terminé par le signal %d : %s" msgid "child process exited with unrecognized status %d" msgstr "le processus fils a quitté avec un statut %d non reconnu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "valeur « %s » invalide pour l'option %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s doit être compris entre %d et %d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + #: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" @@ -217,274 +268,289 @@ msgstr "n'a pas pu configurer la jonction pour « %s » : %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "n'a pas pu obtenir la jonction pour « %s » : %s\n" -#: initdb.c:618 initdb.c:1613 +#: initdb.c:369 +#, c-format +msgid "_wsetlocale() failed" +msgstr "échec de _wsetlocale()" + +#: initdb.c:376 +#, c-format +msgid "setlocale() failed" +msgstr "échec de setlocale()" + +#: initdb.c:390 +#, c-format +msgid "failed to restore old locale" +msgstr "a échoué pour restaurer l'ancienne locale" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "a échoué pour restaurer l'ancienne locale « %s »" + +#: initdb.c:682 initdb.c:1674 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" -#: initdb.c:662 initdb.c:966 initdb.c:986 +#: initdb.c:726 initdb.c:1030 initdb.c:1050 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "n'a pas pu ouvrir le fichier « %s » en écriture : %m" -#: initdb.c:666 initdb.c:969 initdb.c:988 +#: initdb.c:730 initdb.c:1033 initdb.c:1052 #, c-format msgid "could not write file \"%s\": %m" msgstr "impossible d'écrire le fichier « %s » : %m" -#: initdb.c:670 +#: initdb.c:734 #, c-format msgid "could not close file \"%s\": %m" msgstr "n'a pas pu fermer le fichier « %s » : %m" -#: initdb.c:686 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "n'a pas pu exécuter la commande « %s » : %m" - -#: initdb.c:704 +#: initdb.c:768 #, c-format msgid "removing data directory \"%s\"" msgstr "suppression du répertoire des données « %s »" -#: initdb.c:706 +#: initdb.c:770 #, c-format msgid "failed to remove data directory" msgstr "échec de la suppression du répertoire des données" -#: initdb.c:710 +#: initdb.c:774 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "suppression du contenu du répertoire des données « %s »" -#: initdb.c:713 +#: initdb.c:777 #, c-format msgid "failed to remove contents of data directory" msgstr "échec de la suppression du contenu du répertoire des données" -#: initdb.c:718 +#: initdb.c:782 #, c-format msgid "removing WAL directory \"%s\"" msgstr "suppression du répertoire des journaux de transactions « %s »" -#: initdb.c:720 +#: initdb.c:784 #, c-format msgid "failed to remove WAL directory" msgstr "échec de la suppression du répertoire des journaux de transactions" -#: initdb.c:724 +#: initdb.c:788 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "suppression du contenu du répertoire des journaux de transactions « %s »" -#: initdb.c:726 +#: initdb.c:790 #, c-format msgid "failed to remove contents of WAL directory" msgstr "échec de la suppression du contenu du répertoire des journaux de transactions" -#: initdb.c:733 +#: initdb.c:797 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "répertoire des données « %s » non supprimé à la demande de l'utilisateur" -#: initdb.c:737 +#: initdb.c:801 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "répertoire des journaux de transactions « %s » non supprimé à la demande de l'utilisateur" -#: initdb.c:755 +#: initdb.c:819 #, c-format msgid "cannot be run as root" msgstr "ne peut pas être exécuté en tant que root" -#: initdb.c:756 +#: initdb.c:820 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "Connectez-vous (par exemple en utilisant « su ») sous l'utilisateur (non privilégié) qui sera propriétaire du processus serveur." -#: initdb.c:788 +#: initdb.c:852 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "« %s » n'est pas un nom d'encodage serveur valide" -#: initdb.c:932 +#: initdb.c:996 #, c-format msgid "file \"%s\" does not exist" msgstr "le rôle « %s » n'existe pas" -#: initdb.c:933 initdb.c:938 initdb.c:945 +#: initdb.c:997 initdb.c:1002 initdb.c:1009 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "Cela peut signifier que votre installation est corrompue ou que vous avez identifié le mauvais répertoire avec l'option -L." -#: initdb.c:937 +#: initdb.c:1001 #, c-format msgid "could not access file \"%s\": %m" msgstr "n'a pas pu accéder au fichier « %s » : %m" -#: initdb.c:944 +#: initdb.c:1008 #, c-format msgid "file \"%s\" is not a regular file" msgstr "le fichier « %s » n'est pas un fichier standard" -#: initdb.c:1077 +#: initdb.c:1141 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "sélection de l'implémentation de la mémoire partagée dynamique..." -#: initdb.c:1086 +#: initdb.c:1150 #, c-format -msgid "selecting default max_connections ... " -msgstr "sélection de la valeur par défaut pour max_connections... " +msgid "selecting default \"max_connections\" ... " +msgstr "sélection de la valeur par défaut pour « max_connections »... " -#: initdb.c:1106 +#: initdb.c:1170 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "sélection de la valeur par défaut pour shared_buffers... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "sélection de la valeur par défaut pour « shared_buffers »... " -#: initdb.c:1129 +#: initdb.c:1193 #, c-format msgid "selecting default time zone ... " msgstr "sélection du fuseau horaire par défaut... " -#: initdb.c:1206 +#: initdb.c:1272 msgid "creating configuration files ... " msgstr "création des fichiers de configuration... " -#: initdb.c:1367 initdb.c:1381 initdb.c:1448 initdb.c:1459 +#: initdb.c:1425 initdb.c:1439 initdb.c:1506 initdb.c:1517 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "n'a pas pu modifier les droits de « %s » : %m" -#: initdb.c:1477 +#: initdb.c:1536 #, c-format msgid "running bootstrap script ... " msgstr "lancement du script bootstrap..." -#: initdb.c:1489 +#: initdb.c:1548 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "le fichier en entrée « %s » n'appartient pas à PostgreSQL %s" -#: initdb.c:1491 +#: initdb.c:1550 #, c-format msgid "Specify the correct path using the option -L." msgstr "Indiquez le bon chemin avec l'option -L." -#: initdb.c:1591 +#: initdb.c:1652 msgid "Enter new superuser password: " msgstr "Saisir le nouveau mot de passe du super-utilisateur : " -#: initdb.c:1592 +#: initdb.c:1653 msgid "Enter it again: " msgstr "Saisir le mot de passe à nouveau : " -#: initdb.c:1595 +#: initdb.c:1656 #, c-format msgid "Passwords didn't match.\n" msgstr "Les mots de passe ne sont pas identiques.\n" -#: initdb.c:1619 +#: initdb.c:1680 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "n'a pas pu lire le mot de passe à partir du fichier « %s » : %m" -#: initdb.c:1622 +#: initdb.c:1683 #, c-format msgid "password file \"%s\" is empty" msgstr "le fichier de mots de passe « %s » est vide" -#: initdb.c:2034 +#: initdb.c:2095 #, c-format msgid "caught signal\n" msgstr "signal reçu\n" -#: initdb.c:2040 +#: initdb.c:2101 #, c-format msgid "could not write to child process: %s\n" msgstr "n'a pas pu écrire au processus fils : %s\n" -#: initdb.c:2048 +#: initdb.c:2109 #, c-format msgid "ok\n" msgstr "ok\n" -#: initdb.c:2137 +#: initdb.c:2191 initdb.c:2237 #, c-format -msgid "setlocale() failed" -msgstr "échec de setlocale()" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "le nom de la locale « %s » contient des caractères non ASCII" -#: initdb.c:2155 -#, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "a échoué pour restaurer l'ancienne locale « %s »" - -#: initdb.c:2163 +#: initdb.c:2217 #, c-format msgid "invalid locale name \"%s\"" msgstr "nom de locale « %s » invalide" -#: initdb.c:2164 +#: initdb.c:2218 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "Si le nom de la locale est spécifique à ICU, utilisez --icu-locale." -#: initdb.c:2177 +#: initdb.c:2231 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "configuration invalide de la locale ; vérifiez les variables d'environnement LANG et LC_*" -#: initdb.c:2203 initdb.c:2227 +#: initdb.c:2262 initdb.c:2286 #, c-format msgid "encoding mismatch" msgstr "différence d'encodage" -#: initdb.c:2204 +#: initdb.c:2263 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "L'encodage que vous avez sélectionné (%s) et celui que la locale sélectionnée utilise (%s) ne sont pas compatibles. Cela peut conduire à des erreurs dans les fonctions de manipulation de chaînes de caractères." -#: initdb.c:2209 initdb.c:2230 +#: initdb.c:2268 initdb.c:2289 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "Relancez %s et soit vous ne spécifiez pas explicitement d'encodage, soit vous choisissez une combinaison compatible." -#: initdb.c:2228 +#: initdb.c:2287 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "L'encodage que vous avez sélectionné (%s) n'est pas supporté avec le fournisseur ICU." -#: initdb.c:2279 +#: initdb.c:2338 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "n'a pas pu convertir le nom de locale « %s » en balise de langage : %s" -#: initdb.c:2285 initdb.c:2337 initdb.c:2416 +#: initdb.c:2344 initdb.c:2396 initdb.c:2488 #, c-format msgid "ICU is not supported in this build" msgstr "ICU n'est pas supporté dans cette installation" -#: initdb.c:2308 +#: initdb.c:2367 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "n'a pas pu obtenir la langue à partir de la locale « %s » : %s" -#: initdb.c:2334 +#: initdb.c:2393 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "la locale « %s » a le langage inconnu « %s »" -#: initdb.c:2400 +#: initdb.c:2454 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "la locale doit être spécifiée si le fournisseur est %s" + +#: initdb.c:2465 #, c-format -msgid "ICU locale must be specified" -msgstr "la locale ICU doit être précisée" +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "nom de locale « %s » invalide pour le fournisseur natif" -#: initdb.c:2404 +#: initdb.c:2476 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "Utilisation de la balise de langage « %s » pour la locale ICU « %s ».\n" -#: initdb.c:2427 +#: initdb.c:2499 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -493,17 +559,17 @@ msgstr "" "%s initialise une instance PostgreSQL.\n" "\n" -#: initdb.c:2428 +#: initdb.c:2500 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: initdb.c:2429 +#: initdb.c:2501 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [RÉP_DONNÉES]\n" -#: initdb.c:2430 +#: initdb.c:2502 #, c-format msgid "" "\n" @@ -512,71 +578,71 @@ msgstr "" "\n" "Options :\n" -#: initdb.c:2431 +#: initdb.c:2503 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr "" " -A, --auth=MÉTHODE méthode d'authentification par défaut pour les\n" " connexions locales\n" -#: initdb.c:2432 +#: initdb.c:2504 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr "" " --auth-host=MÉTHODE méthode d'authentification par défaut pour les\n" " connexions locales TCP/IP\n" -#: initdb.c:2433 +#: initdb.c:2505 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr "" " --auth-local=MÉTHODE méthode d'authentification par défaut pour les\n" " connexions locales socket\n" -#: initdb.c:2434 +#: initdb.c:2506 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]RÉP_DONNÉES emplacement du répertoire principal des données\n" -#: initdb.c:2435 +#: initdb.c:2507 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr "" " -E, --encoding=ENCODAGE initialise l'encodage par défaut des nouvelles\n" " bases de données\n" -#: initdb.c:2436 +#: initdb.c:2508 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr "" " -g, --allow-group-access autorise la lecture/écriture pour le groupe sur\n" " le répertoire des données\n" -#: initdb.c:2437 +#: initdb.c:2509 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOCALE initialise l'identifiant de locale ICU pour les nouvelles bases de données\n" -#: initdb.c:2438 +#: initdb.c:2510 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" -msgstr " --icu-rules=REGLES initialise les règles supplémentaires de la locale ICU pour les nouvelles bases de données\n" +msgstr " --icu-rules=REGLES initialise les règles supplémentaires de la locale ICU pour les nouvelles bases de données\n" -#: initdb.c:2439 +#: initdb.c:2511 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr "" " -k, --data-checksums active les sommes de contrôle pour les blocs des\n" " fichiers de données\n" -#: initdb.c:2440 +#: initdb.c:2512 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr "" " --locale=LOCALE initialise la locale par défaut pour les\n" " nouvelles bases de données\n" -#: initdb.c:2441 +#: initdb.c:2513 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -591,29 +657,39 @@ msgstr "" " (les valeurs par défaut sont prises dans\n" " l'environnement)\n" -#: initdb.c:2445 +#: initdb.c:2517 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale équivalent à --locale=C\n" -#: initdb.c:2446 +#: initdb.c:2518 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" --builtin-provider=LOCALE\n" +" initialise le fournisseur de locale natif pour\n" +" les nouvelles bases de données\n" + +#: initdb.c:2520 +#, c-format +msgid "" +" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " initialise le fournisseur de locale par défaut pour\n" " les nouvelles bases de données\n" -#: initdb.c:2448 +#: initdb.c:2522 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr "" " --pwfile=FICHIER lit le mot de passe du nouveau super-utilisateur\n" " à partir de ce fichier\n" -#: initdb.c:2449 +#: initdb.c:2523 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -622,31 +698,31 @@ msgstr "" " -T, --text-search-config=CFG configuration par défaut de la recherche plein\n" " texte\n" -#: initdb.c:2451 +#: initdb.c:2525 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NOM nom du super-utilisateur de la base de données\n" -#: initdb.c:2452 +#: initdb.c:2526 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr "" " -W, --pwprompt demande un mot de passe pour le nouveau\n" " super-utilisateur\n" -#: initdb.c:2453 +#: initdb.c:2527 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr "" " -X, --waldir=RÉP_WAL emplacement du répertoire des journaux de\n" " transactions\n" -#: initdb.c:2454 +#: initdb.c:2528 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=TAILLE configure la taille des segments WAL, en Mo\n" -#: initdb.c:2455 +#: initdb.c:2529 #, c-format msgid "" "\n" @@ -655,58 +731,63 @@ msgstr "" "\n" "Options moins utilisées :\n" -#: initdb.c:2456 +#: initdb.c:2530 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" -msgstr " -c NOM=VALEUR surcharge la configuration par défaut d'un paramètre serveur\n" +msgstr " -c NOM=VALEUR surcharge la configuration par défaut d'un paramètre serveur\n" -#: initdb.c:2457 +#: initdb.c:2531 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug engendre un grand nombre de traces de débogage\n" -#: initdb.c:2458 +#: initdb.c:2532 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches initialise debug_discard_caches à 1\n" -#: initdb.c:2459 +#: initdb.c:2533 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr "" " -L RÉPERTOIRE indique où trouver les fichiers servant à la\n" " création de l'instance\n" -#: initdb.c:2460 +#: initdb.c:2534 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --noclean ne nettoie pas après des erreurs\n" -#: initdb.c:2461 +#: initdb.c:2535 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --nosync n'attend pas que les modifications soient\n" " proprement écrites sur disque\n" -#: initdb.c:2462 +#: initdb.c:2536 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr "" " --no-instructions n'affiche pas les instructions des prochaines\n" " étapes\n" -#: initdb.c:2463 +#: initdb.c:2537 +#, c-format +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show affiche la configuration interne, puis quitte\n" + +#: initdb.c:2538 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show affiche la configuration interne\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" -#: initdb.c:2464 +#: initdb.c:2539 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only synchronise uniquement le répertoire des données, puis quitte\n" -#: initdb.c:2465 +#: initdb.c:2540 #, c-format msgid "" "\n" @@ -715,17 +796,17 @@ msgstr "" "\n" "Autres options :\n" -#: initdb.c:2466 +#: initdb.c:2541 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: initdb.c:2467 +#: initdb.c:2542 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: initdb.c:2468 +#: initdb.c:2543 #, c-format msgid "" "\n" @@ -736,7 +817,7 @@ msgstr "" "Si le répertoire des données n'est pas indiqué, la variable d'environnement\n" "PGDATA est utilisée.\n" -#: initdb.c:2470 +#: initdb.c:2545 #, c-format msgid "" "\n" @@ -745,72 +826,72 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: initdb.c:2471 +#: initdb.c:2546 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: initdb.c:2499 +#: initdb.c:2570 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "méthode d'authentification « %s » invalide pour « %s » connexions" -#: initdb.c:2513 +#: initdb.c:2584 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "doit indiquer un mot de passe pour le super-utilisateur afin d'activer l'authentification par mot de passe" -#: initdb.c:2532 +#: initdb.c:2603 #, c-format msgid "no data directory specified" msgstr "aucun répertoire de données indiqué" -#: initdb.c:2533 +#: initdb.c:2604 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "Vous devez identifier le répertoire où résideront les données pour ce système de bases de données. Faites-le soit avec l'option -D soit avec la variable d'environnement PGDATA." -#: initdb.c:2550 +#: initdb.c:2621 #, c-format msgid "could not set environment" msgstr "n'a pas pu configurer l'environnement" -#: initdb.c:2568 +#: initdb.c:2639 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé dans le même répertoire que « %s »" -#: initdb.c:2571 +#: initdb.c:2642 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "le programme « %s » a été trouvé par « %s » mais n'est pas de la même version que %s" -#: initdb.c:2586 +#: initdb.c:2657 #, c-format msgid "input file location must be an absolute path" msgstr "l'emplacement du fichier d'entrée doit être indiqué avec un chemin absolu" -#: initdb.c:2603 +#: initdb.c:2674 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "L'instance sera initialisée avec la locale « %s ».\n" -#: initdb.c:2606 +#: initdb.c:2677 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "L'instance sera initialisée avec cette configuration de locale :\n" -#: initdb.c:2607 +#: initdb.c:2678 #, c-format -msgid " provider: %s\n" -msgstr " fournisseur: %s\n" +msgid " locale provider: %s\n" +msgstr " fournisseur de locale : %s\n" -#: initdb.c:2609 +#: initdb.c:2680 #, c-format -msgid " ICU locale: %s\n" -msgstr " locale ICU : %s\n" +msgid " default collation: %s\n" +msgstr "collation par défaut : %s\n" -#: initdb.c:2610 +#: initdb.c:2681 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -827,22 +908,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2640 +#: initdb.c:2711 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "n'a pas pu trouver un encodage adéquat pour la locale « %s »" -#: initdb.c:2642 +#: initdb.c:2713 #, c-format msgid "Rerun %s with the -E option." msgstr "Relancez %s avec l'option -E." -#: initdb.c:2643 initdb.c:3176 initdb.c:3284 initdb.c:3304 +#: initdb.c:2714 initdb.c:3257 initdb.c:3377 initdb.c:3397 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: initdb.c:2655 +#: initdb.c:2726 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -851,109 +932,114 @@ msgstr "" "L'encodage « %s » a été déduit de la locale mais n'est pas autorisé en tant qu'encodage serveur.\n" "L'encodage par défaut des bases de données sera configuré à « %s ».\n" -#: initdb.c:2660 +#: initdb.c:2731 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "la locale « %s » nécessite l'encodage « %s » non supporté" -#: initdb.c:2662 +#: initdb.c:2733 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "L'encodage « %s » n'est pas autorisé en tant qu'encodage serveur." -#: initdb.c:2664 +#: initdb.c:2735 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Relancez %s avec une locale différente." -#: initdb.c:2672 +#: initdb.c:2743 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "" "L'encodage par défaut des bases de données a été configuré en conséquence\n" "avec « %s ».\n" -#: initdb.c:2741 +#: initdb.c:2757 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "la locale du fournisseur natif « %s » nécessite l'encodage « %s »" + +#: initdb.c:2819 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "n'a pas pu trouver la configuration de la recherche plein texte en adéquation avec la locale « %s »" -#: initdb.c:2752 +#: initdb.c:2830 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "la configuration de la recherche plein texte convenable pour la locale « %s » est inconnue" -#: initdb.c:2757 +#: initdb.c:2835 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "la configuration indiquée pour la recherche plein texte, « %s », pourrait ne pas correspondre à la locale « %s »" -#: initdb.c:2762 +#: initdb.c:2840 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "La configuration de la recherche plein texte a été initialisée à « %s ».\n" -#: initdb.c:2805 initdb.c:2876 +#: initdb.c:2883 initdb.c:2954 #, c-format msgid "creating directory %s ... " msgstr "création du répertoire %s... " -#: initdb.c:2810 initdb.c:2881 initdb.c:2929 initdb.c:2985 +#: initdb.c:2888 initdb.c:2959 initdb.c:3007 initdb.c:3064 #, c-format msgid "could not create directory \"%s\": %m" msgstr "n'a pas pu créer le répertoire « %s » : %m" -#: initdb.c:2819 initdb.c:2891 +#: initdb.c:2897 initdb.c:2969 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "correction des droits sur le répertoire existant %s... " -#: initdb.c:2824 initdb.c:2896 +#: initdb.c:2902 initdb.c:2974 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "n'a pas pu modifier les droits du répertoire « %s » : %m" -#: initdb.c:2836 initdb.c:2908 +#: initdb.c:2914 initdb.c:2986 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "le répertoire « %s » existe mais n'est pas vide" -#: initdb.c:2840 +#: initdb.c:2918 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "Si vous voulez créer un nouveau système de bases de données, supprimez ou videz le répertoire « %s ». Vous pouvez aussi exécuter %s avec un argument autre que « %s »." -#: initdb.c:2848 initdb.c:2918 initdb.c:3325 +#: initdb.c:2926 initdb.c:2996 initdb.c:3422 #, c-format msgid "could not access directory \"%s\": %m" msgstr "n'a pas pu accéder au répertoire « %s » : %m" -#: initdb.c:2869 +#: initdb.c:2947 #, c-format msgid "WAL directory location must be an absolute path" msgstr "l'emplacement du répertoire des journaux de transactions doit être indiqué avec un chemin absolu" -#: initdb.c:2912 +#: initdb.c:2990 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "Si vous voulez enregistrer ici les WAL, supprimez ou videz le répertoire « %s »." -#: initdb.c:2922 +#: initdb.c:3000 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "n'a pas pu créer le lien symbolique « %s » : %m" -#: initdb.c:2941 +#: initdb.c:3019 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "Il contient un fichier invisible, peut-être parce qu'il s'agit d'un point de montage." -#: initdb.c:2943 +#: initdb.c:3021 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Il contient un répertoire lost+found, peut-être parce qu'il s'agit d'un point de montage.\\" -#: initdb.c:2945 +#: initdb.c:3023 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -962,72 +1048,67 @@ msgstr "" "Utiliser un point de montage comme répertoire des données n'est pas recommandé.\n" "Créez un sous-répertoire sous le point de montage." -#: initdb.c:2971 +#: initdb.c:3050 #, c-format msgid "creating subdirectories ... " msgstr "création des sous-répertoires... " -#: initdb.c:3014 +#: initdb.c:3093 msgid "performing post-bootstrap initialization ... " msgstr "exécution de l'initialisation après bootstrap... " -#: initdb.c:3175 +#: initdb.c:3256 #, c-format msgid "-c %s requires a value" msgstr "-c %s requiert une valeur" -#: initdb.c:3200 +#: initdb.c:3281 #, c-format msgid "Running in debug mode.\n" msgstr "Lancé en mode débogage.\n" -#: initdb.c:3204 +#: initdb.c:3285 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "Lancé en mode « sans nettoyage ». Les erreurs ne seront pas nettoyées.\n" -#: initdb.c:3274 +#: initdb.c:3358 #, c-format msgid "unrecognized locale provider: %s" msgstr "fournisseur de locale non reconnu : %s" -#: initdb.c:3302 +#: initdb.c:3395 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: initdb.c:3309 initdb.c:3313 +#: initdb.c:3402 initdb.c:3406 initdb.c:3410 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s ne peut pas être spécifié sauf si le fournisseur de locale « %s » est choisi" -#: initdb.c:3327 initdb.c:3404 +#: initdb.c:3424 initdb.c:3487 msgid "syncing data to disk ... " msgstr "synchronisation des données sur disque... " -#: initdb.c:3335 +#: initdb.c:3432 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "" "les options d'invite du mot de passe et de fichier de mots de passe ne\n" "peuvent pas être indiquées simultanément" -#: initdb.c:3357 +#: initdb.c:3443 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "l'argument de --wal-segsize doit être un nombre" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "l'argument de %s doit être une puissance de 2 comprise entre 1 et 1024" -#: initdb.c:3359 -#, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "l'argument de --wal-segsize doit être une puissance de 2 comprise entre 1 et 1024" - -#: initdb.c:3373 +#: initdb.c:3456 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "le nom de superutilisateur « %s » n'est pas autorisé ; les noms de rôle ne peuvent pas commencer par « pg_ »" -#: initdb.c:3375 +#: initdb.c:3458 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1038,17 +1119,17 @@ msgstr "" "Le processus serveur doit également lui appartenir.\n" "\n" -#: initdb.c:3391 +#: initdb.c:3474 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Les sommes de contrôle des pages de données sont activées.\n" -#: initdb.c:3393 +#: initdb.c:3476 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Les sommes de contrôle des pages de données sont désactivées.\n" -#: initdb.c:3410 +#: initdb.c:3493 #, c-format msgid "" "\n" @@ -1059,22 +1140,22 @@ msgstr "" "Synchronisation sur disque ignorée.\n" "Le répertoire des données pourrait être corrompu si le système d'exploitation s'arrêtait brutalement.\n" -#: initdb.c:3415 +#: initdb.c:3498 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "activation de l'authentification « trust » pour les connexions locales" -#: initdb.c:3416 +#: initdb.c:3499 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "Vous pouvez changer cette configuration en éditant le fichier pg_hba.conf ou en utilisant l'option -A, ou --auth-local et --auth-host, à la prochaine exécution d'initdb." #. translator: This is a placeholder in a shell command. -#: initdb.c:3446 +#: initdb.c:3529 msgid "logfile" msgstr "fichier_de_trace" -#: initdb.c:3448 +#: initdb.c:3531 #, c-format msgid "" "\n" @@ -1088,265 +1169,3 @@ msgstr "" "\n" " %s\n" "\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid "%s: The password file was not generated. Please report this problem.\n" -#~ msgstr "" -#~ "%s : le fichier de mots de passe n'a pas été créé.\n" -#~ "Merci de rapporter ce problème.\n" - -#~ msgid "%s: could not access directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu accéder au répertoire « %s » : %s\n" - -#~ msgid "%s: could not access file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu accéder au fichier « %s » : %s\n" - -#~ msgid "%s: could not close directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu fermer le répertoire « %s » : %s\n" - -#~ msgid "%s: could not create directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le répertoire « %s » : %s\n" - -#~ msgid "%s: could not create symbolic link \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le lien symbolique « %s » : %s\n" - -#~ msgid "%s: could not determine valid short version string\n" -#~ msgstr "%s : n'a pas pu déterminer une chaîne de version courte valide\n" - -#~ msgid "%s: could not execute command \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu exécuter la commande « %s » : %s\n" - -#~ msgid "%s: could not fsync file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu synchroniser sur disque le fichier « %s » : %s\n" - -#~ msgid "%s: could not get current user name: %s\n" -#~ msgstr "%s : n'a pas pu obtenir le nom de l'utilisateur courant : %s\n" - -#~ msgid "%s: could not obtain information about current user: %s\n" -#~ msgstr "%s : n'a pas pu obtenir d'informations sur l'utilisateur courant : %s\n" - -#~ msgid "%s: could not open directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#~ msgid "%s: could not open file \"%s\" for reading: %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » en lecture : %s\n" - -#~ msgid "%s: could not open file \"%s\" for writing: %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » en écriture : %s\n" - -#~ msgid "%s: could not open file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n" - -#~ msgid "%s: could not read directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "%s: could not rename file \"%s\" to \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu renommer le fichier « %s » en « %s » : %s\n" - -#~ msgid "%s: could not stat file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu récupérer les informations sur le fichier « %s » : %s\n" - -#~ msgid "%s: could not to allocate SIDs: error code %lu\n" -#~ msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n" - -#~ msgid "%s: could not write file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu écrire le fichier « %s » : %s\n" - -#~ msgid "%s: failed to remove contents of transaction log directory\n" -#~ msgstr "%s : échec de la suppression du contenu du répertoire des journaux de transaction\n" - -#~ msgid "%s: failed to remove transaction log directory\n" -#~ msgstr "%s : échec de la suppression du répertoire des journaux de transaction\n" - -#~ msgid "%s: failed to restore old locale \"%s\"\n" -#~ msgstr "%s : n'a pas pu restaurer l'ancienne locale « %s »\n" - -#~ msgid "%s: file \"%s\" does not exist\n" -#~ msgstr "%s : le fichier « %s » n'existe pas\n" - -#~ msgid "%s: invalid locale name \"%s\"\n" -#~ msgstr "%s : nom de locale invalide (« %s »)\n" - -#~ msgid "%s: locale name has non-ASCII characters, skipped: \"%s\"\n" -#~ msgstr "%s : le nom de la locale contient des caractères non ASCII, ignoré : « %s »\n" - -#~ msgid "%s: locale name too long, skipped: \"%s\"\n" -#~ msgstr "%s : nom de locale trop long, ignoré : « %s »\n" - -#~ msgid "%s: out of memory\n" -#~ msgstr "%s : mémoire épuisée\n" - -#~ msgid "%s: removing contents of transaction log directory \"%s\"\n" -#~ msgstr "%s : suppression du contenu du répertoire des journaux de transaction « %s »\n" - -#~ msgid "%s: removing transaction log directory \"%s\"\n" -#~ msgstr "%s : suppression du répertoire des journaux de transaction « %s »\n" - -#~ msgid "%s: symlinks are not supported on this platform\n" -#~ msgstr "%s : les liens symboliques ne sont pas supportés sur cette plateforme\n" - -#~ msgid "%s: transaction log directory \"%s\" not removed at user's request\n" -#~ msgstr "" -#~ "%s : répertoire des journaux de transaction « %s » non supprimé à la demande\n" -#~ "de l'utilisateur\n" - -#~ msgid "%s: unrecognized authentication method \"%s\"\n" -#~ msgstr "%s : méthode d'authentification « %s » inconnue.\n" - -#~ msgid "No usable system locales were found.\n" -#~ msgstr "Aucune locale système utilisable n'a été trouvée.\n" - -#, c-format -#~ msgid "The default database encoding has been set to \"%s\".\n" -#~ msgstr "L'encodage par défaut des bases de données a été configuré à « %s ».\n" - -#~ msgid "" -#~ "The program \"postgres\" is needed by %s but was not found in the\n" -#~ "same directory as \"%s\".\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « postgres » est nécessaire à %s mais n'a pas été trouvé dans\n" -#~ "le même répertoire que « %s ».\n" -#~ "Vérifiez votre installation." - -#~ msgid "" -#~ "The program \"postgres\" was found by \"%s\"\n" -#~ "but was not the same version as %s.\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « postgres » a été trouvé par « %s » mais n'est pas de la même\n" -#~ "version que « %s ».\n" -#~ "Vérifiez votre installation." - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#~ msgid "Use the option \"--debug\" to see details.\n" -#~ msgstr "Utilisez l'option « --debug » pour voir le détail.\n" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "ne peut pas créer les jetons restreints sur cette plateforme : code d'erreur %lu" - -#~ msgid "child process was terminated by signal %s" -#~ msgstr "le processus fils a été terminé par le signal %s" - -#~ msgid "copying template1 to postgres ... " -#~ msgstr "copie de template1 vers postgres... " - -#~ msgid "copying template1 to template0 ... " -#~ msgstr "copie de template1 vers template0... " - -#~ msgid "could not change directory to \"%s\"" -#~ msgstr "n'a pas pu accéder au répertoire « %s »" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %m" - -#~ msgid "could not change directory to \"%s\": %s" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %s" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "n'a pas pu identifier le répertoire courant : %m" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "n'a pas pu charger la bibliothèque « %s » : code d'erreur %lu" - -#~ msgid "could not open directory \"%s\": %s\n" -#~ msgstr "n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "n'a pas pu lire le binaire « %s »" - -#~ msgid "could not read directory \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "could not read symbolic link \"%s\"" -#~ msgstr "n'a pas pu lire le lien symbolique « %s »" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" - -#, c-format -#~ msgid "could not remove file or directory \"%s\": %m" -#~ msgstr "n'a pas pu supprimer le fichier ou répertoire « %s » : %m" - -#, c-format -#~ msgid "could not stat file or directory \"%s\": %m" -#~ msgstr "" -#~ "n'a pas pu récupérer les informations sur le fichier ou répertoire\n" -#~ "« %s » : %m" - -#~ msgid "could not stat file or directory \"%s\": %s\n" -#~ msgstr "" -#~ "n'a pas pu récupérer les informations sur le fichier ou répertoire\n" -#~ "« %s » : %s\n" - -#~ msgid "creating collations ... " -#~ msgstr "création des collationnements... " - -#~ msgid "creating conversions ... " -#~ msgstr "création des conversions... " - -#~ msgid "creating dictionaries ... " -#~ msgstr "création des dictionnaires... " - -#~ msgid "creating information schema ... " -#~ msgstr "création du schéma d'informations... " - -#~ msgid "creating system views ... " -#~ msgstr "création des vues système... " - -#~ msgid "creating template1 database in %s/base/1 ... " -#~ msgstr "création de la base de données template1 dans %s/base/1... " - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "initializing dependencies ... " -#~ msgstr "initialisation des dépendances... " - -#~ msgid "initializing pg_authid ... " -#~ msgstr "initialisation de pg_authid... " - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "binaire « %s » invalide" - -#~ msgid "loading PL/pgSQL server-side language ... " -#~ msgstr "chargement du langage PL/pgSQL... " - -#~ msgid "loading system objects' descriptions ... " -#~ msgstr "chargement de la description des objets système... " - -#~ msgid "not supported on this platform\n" -#~ msgstr "non supporté sur cette plateforme\n" - -#~ msgid "pclose failed: %m" -#~ msgstr "échec de pclose : %m" - -#~ msgid "setting password ... " -#~ msgstr "initialisation du mot de passe... " - -#~ msgid "setting privileges on built-in objects ... " -#~ msgstr "initialisation des droits sur les objets internes... " - -#, c-format -#~ msgid "symlinks are not supported on this platform" -#~ msgstr "les liens symboliques ne sont pas supportés sur cette plateforme" - -#~ msgid "vacuuming database template1 ... " -#~ msgstr "lancement du vacuum sur la base de données template1... " diff --git a/src/bin/initdb/po/ja.po b/src/bin/initdb/po/ja.po index 404f2f6125b83..62098fe2bbab3 100644 --- a/src/bin/initdb/po/ja.po +++ b/src/bin/initdb/po/ja.po @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: initdb (PostgreSQL 17)\n" +"Project-Id-Version: initdb (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:23+0900\n" -"PO-Revision-Date: 2024-06-14 11:27+0900\n" +"POT-Creation-Date: 2025-03-26 11:21+0900\n" +"PO-Revision-Date: 2025-03-31 16:23+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -17,22 +17,22 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " @@ -57,28 +57,28 @@ msgstr "実行する\"%s\"がありませんでした" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "パス\"%s\"を絶対パス形式に変換できませんでした: %m" -#: ../../common/exec.c:382 initdb.c:695 +#: ../../common/exec.c:363 initdb.c:753 #, c-format msgid "could not execute command \"%s\": %m" msgstr "コマンド\"%s\"を実行できませんでした: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "コマンド\"%s\"から読み取れませんでした: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "コマンド\"%s\"がデータを返却しませんでした" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s() が失敗しました: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 -#: initdb.c:353 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 +#: initdb.c:375 initdb.c:411 #, c-format msgid "out of memory" msgstr "メモリ不足です" @@ -94,46 +94,46 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null ポインタを複製できません(内部エラー)。\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -242,12 +242,12 @@ msgstr "%sは%d..%dの範囲になければなりません" msgid "unrecognized sync method: %s" msgstr "認識できない同期方式: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" @@ -262,291 +262,311 @@ msgstr "\"%s\"のjunctionを設定できませんでした: %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "\"%s\"のjunctionを入手できませんでした: %s\n" -#: initdb.c:627 initdb.c:1619 +#: initdb.c:372 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale()が失敗しました" + +#: initdb.c:379 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale()が失敗しました" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale" +msgstr "古いロケールの復元に失敗しました" + +#: initdb.c:396 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "古いロケール\"%s\"を復元できませんでした" + +#: initdb.c:685 initdb.c:1705 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "ファイル\"%s\"を読み取り用にオープンできませんでした: %m" -#: initdb.c:671 initdb.c:975 initdb.c:995 +#: initdb.c:729 initdb.c:1035 initdb.c:1055 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "ファイル\"%s\"を書き込み用にオープンできませんでした: %m" -#: initdb.c:675 initdb.c:978 initdb.c:997 +#: initdb.c:733 initdb.c:1038 initdb.c:1057 #, c-format msgid "could not write file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: initdb.c:679 +#: initdb.c:737 #, c-format msgid "could not close file \"%s\": %m" msgstr "ファイル\"%s\"をクローズできませんでした: %m" -#: initdb.c:713 +#: initdb.c:771 #, c-format msgid "removing data directory \"%s\"" msgstr "データディレクトリ\"%s\"を削除しています" -#: initdb.c:715 +#: initdb.c:773 #, c-format msgid "failed to remove data directory" msgstr "データディレクトリの削除に失敗しました" -#: initdb.c:719 +#: initdb.c:777 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "データディレクトリ\"%s\"の内容を削除しています" -#: initdb.c:722 +#: initdb.c:780 #, c-format msgid "failed to remove contents of data directory" msgstr "データディレクトリの内容の削除に失敗しました" -#: initdb.c:727 +#: initdb.c:785 #, c-format msgid "removing WAL directory \"%s\"" msgstr "WAL ディレクトリ\"%s\"を削除しています" -#: initdb.c:729 +#: initdb.c:787 #, c-format msgid "failed to remove WAL directory" msgstr "WAL ディレクトリの削除に失敗しました" -#: initdb.c:733 +#: initdb.c:791 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "WAL ディレクトリ\"%s\"の中身を削除しています" -#: initdb.c:735 +#: initdb.c:793 #, c-format msgid "failed to remove contents of WAL directory" msgstr "WAL ディレクトリの中身の削除に失敗しました" -#: initdb.c:742 +#: initdb.c:800 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "ユーザーの要求によりデータディレクトリ\"%s\"を削除しませんでした" -#: initdb.c:746 +#: initdb.c:804 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "ユーザーの要求により WAL ディレクトリ\"%s\"を削除しませんでした" -#: initdb.c:764 +#: initdb.c:822 #, c-format msgid "cannot be run as root" msgstr "root では実行できません" -#: initdb.c:765 +#: initdb.c:823 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "サーバープロセスの所有者となる(非特権)ユーザーとして(例えば\"su\"を使用して)ログインしてください。" -#: initdb.c:797 +#: initdb.c:855 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\"は有効なサーバー符号化方式名ではありません" -#: initdb.c:941 +#: initdb.c:1001 #, c-format msgid "file \"%s\" does not exist" msgstr "ファイル\"%s\"は存在しません" -#: initdb.c:942 initdb.c:947 initdb.c:954 +#: initdb.c:1002 initdb.c:1007 initdb.c:1014 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "インストール先が破損しているか実行時オプション-Lで間違ったディレクトリを指定した可能性があります。" -#: initdb.c:946 +#: initdb.c:1006 #, c-format msgid "could not access file \"%s\": %m" msgstr "ファイル\"%s\"にアクセスできませんでした: %m" -#: initdb.c:953 +#: initdb.c:1013 #, c-format msgid "file \"%s\" is not a regular file" msgstr "ファイル\"%s\"は通常のファイルではありません" -#: initdb.c:1086 +#: initdb.c:1158 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "動的共有メモリの実装を選択しています ... " -#: initdb.c:1095 +#: initdb.c:1168 #, c-format msgid "selecting default \"max_connections\" ... " msgstr "デフォルトの\"max_connections\"を選択しています ... " -#: initdb.c:1115 +#: initdb.c:1193 +#, c-format +msgid "selecting default \"autovacuum_worker_slots\" ... %d\n" +msgstr "デフォルトの\"autovacuum_worker_slots\"を選択しています ... %d\n" + +#: initdb.c:1196 #, c-format msgid "selecting default \"shared_buffers\" ... " msgstr "デフォルトの\"shared_buffers\"を選択しています ... " -#: initdb.c:1138 +#: initdb.c:1219 #, c-format msgid "selecting default time zone ... " msgstr "デフォルトの時間帯を選択しています ... " -#: initdb.c:1217 +#: initdb.c:1299 msgid "creating configuration files ... " msgstr "設定ファイルを作成しています ... " -#: initdb.c:1370 initdb.c:1384 initdb.c:1451 initdb.c:1462 +#: initdb.c:1456 initdb.c:1470 initdb.c:1537 initdb.c:1548 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "\"%s\"の権限を変更できませんでした: %m" -#: initdb.c:1481 +#: initdb.c:1567 #, c-format msgid "running bootstrap script ... " msgstr "ブートストラップスクリプトを実行しています ... " -#: initdb.c:1493 +#: initdb.c:1579 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "入力ファイル\"%s\"は PostgreSQL %s のものではありません" -#: initdb.c:1495 +#: initdb.c:1581 #, c-format msgid "Specify the correct path using the option -L." msgstr "-Lオプションを使用して正しいパスを指定してください。" -#: initdb.c:1597 +#: initdb.c:1683 msgid "Enter new superuser password: " msgstr "新しいスーパーユーザーのパスワードを入力してください:" -#: initdb.c:1598 +#: initdb.c:1684 msgid "Enter it again: " msgstr "再入力してください:" -#: initdb.c:1601 +#: initdb.c:1687 #, c-format msgid "Passwords didn't match.\n" msgstr "パスワードが一致しません。\n" -#: initdb.c:1625 +#: initdb.c:1711 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "ファイル\"%s\"からパスワードを読み取ることができませんでした: %m" -#: initdb.c:1628 +#: initdb.c:1714 #, c-format msgid "password file \"%s\" is empty" msgstr "パスワードファイル\"%s\"が空です" -#: initdb.c:2040 +#: initdb.c:2126 #, c-format msgid "caught signal\n" msgstr "シグナルが発生しました\n" -#: initdb.c:2046 +#: initdb.c:2132 #, c-format msgid "could not write to child process: %s\n" msgstr "子プロセスへの書き込みができませんでした: %s\n" -#: initdb.c:2054 +#: initdb.c:2140 #, c-format msgid "ok\n" msgstr "ok\n" -#: initdb.c:2143 -#, c-format -msgid "setlocale() failed" -msgstr "setlocale()が失敗しました" - -#: initdb.c:2161 +#: initdb.c:2222 initdb.c:2268 #, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "古いロケール\"%s\"を復元できませんでした" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "ロケール名\"%s\"は不正な非ASCII文字を含んでいます" -#: initdb.c:2169 +#: initdb.c:2248 #, c-format msgid "invalid locale name \"%s\"" msgstr "ロケール名\"%s\"は不正です" -#: initdb.c:2170 +#: initdb.c:2249 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "ロケール名がICU特有のものである場合は、--icu-localeを使用してください。" -#: initdb.c:2183 +#: initdb.c:2262 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "不正なロケール設定; 環境変数LANGおよびLC_* を確認してください" -#: initdb.c:2209 initdb.c:2233 +#: initdb.c:2293 initdb.c:2317 #, c-format msgid "encoding mismatch" msgstr "符号化方式が合いません" -#: initdb.c:2210 +#: initdb.c:2294 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "選択した符号化方式(%s)と選択したロケールが使用する符号化方式(%s)が合っていません。これにより各種の文字列処理関数が間違った動作をすることになります。" -#: initdb.c:2215 initdb.c:2236 +#: initdb.c:2299 initdb.c:2320 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "%sを再度実行してください、その際にはエンコーディングを明示的に指定しないか、適合する組み合わせを選択してください。" -#: initdb.c:2234 +#: initdb.c:2318 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "指定された符号化方式(%s)はICUプロバイダではサポートされません。" -#: initdb.c:2285 +#: initdb.c:2369 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "ロケール名\"%s\"を、言語タグに変換できませんでした: %s" -#: initdb.c:2291 initdb.c:2343 initdb.c:2435 +#: initdb.c:2375 initdb.c:2427 initdb.c:2521 #, c-format msgid "ICU is not supported in this build" msgstr "このビルドではICUはサポートされていません" -#: initdb.c:2314 +#: initdb.c:2398 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "ロケール\"%s\"から言語を取得できませんでした: %s" -#: initdb.c:2340 +#: initdb.c:2424 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "ロケール\"%s\"は未知の言語\"%s\"を含んでいます" -#: initdb.c:2401 +#: initdb.c:2485 #, c-format msgid "locale must be specified if provider is %s" msgstr "ロケールプロバイダが%sの場合はロケールの指定が必須です" -#: initdb.c:2412 +#: initdb.c:2498 #, c-format msgid "invalid locale name \"%s\" for builtin provider" msgstr "ロケール名\"%s\"は組み込みプロバイダでは不正です" -#: initdb.c:2423 +#: initdb.c:2509 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "ICUロケール\"%s\"に対して言語タグ\"%s\"を使用します。\n" -#: initdb.c:2446 +#: initdb.c:2532 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" "\n" msgstr "%sはPostgreSQLデータベースクラスタを初期化します。\n" -#: initdb.c:2447 +#: initdb.c:2533 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: initdb.c:2448 +#: initdb.c:2534 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATADIR]\n" -#: initdb.c:2449 +#: initdb.c:2535 #, c-format msgid "" "\n" @@ -555,57 +575,57 @@ msgstr "" "\n" "オプション:\n" -#: initdb.c:2450 +#: initdb.c:2536 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, --auth=METHOD ローカル接続のデフォルト認証方式\n" -#: initdb.c:2451 +#: initdb.c:2537 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr " --auth-host=METHOD ローカルTCP/IP接続のデフォルト認証方式\n" -#: initdb.c:2452 +#: initdb.c:2538 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr " --auth-local=METHOD ローカルソケット接続のデフォルト認証方式\n" -#: initdb.c:2453 +#: initdb.c:2539 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATADIR データベースクラスタの場所\n" -#: initdb.c:2454 +#: initdb.c:2540 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=ENCODING 新規データベースのデフォルト符号化方式\n" -#: initdb.c:2455 +#: initdb.c:2541 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr " -g, --allow-group-access データディレクトリのグループ読み取り/実行を許可\n" -#: initdb.c:2456 +#: initdb.c:2542 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOCALE 新しいデータベースのICUロケールIDを設定\n" -#: initdb.c:2457 +#: initdb.c:2543 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" msgstr " --icu-rules=RULES 新しいデータベースに追加するICU照合順序ルール(群)\n" -#: initdb.c:2458 +#: initdb.c:2544 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums データページのチェックサムを使用\n" -#: initdb.c:2459 +#: initdb.c:2545 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=LOCALE 新しいデータベースのデフォルトロケールをセット\n" -#: initdb.c:2460 +#: initdb.c:2546 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -619,12 +639,12 @@ msgstr "" " デフォルトロケールを設定(デフォルト値は環境変数から\n" " 取得)\n" -#: initdb.c:2464 +#: initdb.c:2550 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale --locale=C と同じ\n" -#: initdb.c:2465 +#: initdb.c:2551 #, c-format msgid "" " --builtin-locale=LOCALE\n" @@ -633,7 +653,7 @@ msgstr "" " --builtin-locale=LOCALE\n" " 新しいデータベースの組み込みロケールを指定\n" -#: initdb.c:2467 +#: initdb.c:2553 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -643,14 +663,19 @@ msgstr "" " 新しいデータベースにおけるデフォルトのロケール\n" " プロバイダを設定\n" -#: initdb.c:2469 +#: initdb.c:2555 +#, c-format +msgid " --no-data-checksums do not use data page checksums\n" +msgstr " --no-data-checksums データページのチェックサムを使用しない\n" + +#: initdb.c:2556 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr "" " --pwfile=ファイル名 新しいスーパーユーザーのパスワードをファイルから\n" " 読み込む\n" -#: initdb.c:2470 +#: initdb.c:2557 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -659,27 +684,27 @@ msgstr "" " -T, --text-search-config=CFG\\\n" " デフォルトのテキスト検索設定\n" -#: initdb.c:2472 +#: initdb.c:2559 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NAME データベースのスーパーユーザーの名前\n" -#: initdb.c:2473 +#: initdb.c:2560 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt 新規スーパーユーザーに対してパスワード入力を促す\n" -#: initdb.c:2474 +#: initdb.c:2561 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR 先行書き込みログ用ディレクトリの位置\n" -#: initdb.c:2475 +#: initdb.c:2562 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE WALセグメントのサイズ、メガバイト単位\n" -#: initdb.c:2476 +#: initdb.c:2563 #, c-format msgid "" "\n" @@ -688,57 +713,62 @@ msgstr "" "\n" "使用頻度の低いオプション:\n" -#: initdb.c:2477 +#: initdb.c:2564 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAME=VALUE サーバーパラメータのデフォルト値を上書き設定\n" -#: initdb.c:2478 +#: initdb.c:2565 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug 多くのデバッグ用の出力を生成\n" -#: initdb.c:2479 +#: initdb.c:2566 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches debug_discard_cachesを1に設定する\n" -#: initdb.c:2480 +#: initdb.c:2567 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L DIRECTORY 入力ファイルの場所を指定\n" -#: initdb.c:2481 +#: initdb.c:2568 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean エラー発生後のクリーンアップを行わない\n" -#: initdb.c:2482 +#: initdb.c:2569 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync 変更の安全なディスクへの書き出しを待機しない\n" -#: initdb.c:2483 +#: initdb.c:2570 +#, c-format +msgid " --no-sync-data-files do not sync files within database directories\n" +msgstr " --no-sync-data-files データベースディレクトリ内のファイルを同期しない\n" + +#: initdb.c:2571 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions 次の手順の指示を表示しない\n" -#: initdb.c:2484 +#: initdb.c:2572 #, c-format msgid " -s, --show show internal settings, then exit\n" msgstr " -s, --show 内部設定を表示して終了\n" -#: initdb.c:2485 +#: initdb.c:2573 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=METHOD ファイルをディスクに同期させる方法を指定\n" -#: initdb.c:2486 +#: initdb.c:2574 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only データベースファイルのsyncのみを実行して終了\n" -#: initdb.c:2487 +#: initdb.c:2575 #, c-format msgid "" "\n" @@ -747,17 +777,17 @@ msgstr "" "\n" "その他のオプション:\n" -#: initdb.c:2488 +#: initdb.c:2576 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: initdb.c:2489 +#: initdb.c:2577 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: initdb.c:2490 +#: initdb.c:2578 #, c-format msgid "" "\n" @@ -767,7 +797,7 @@ msgstr "" "\n" "データディレクトリが指定されない場合、PGDATA環境変数が使用されます。\n" -#: initdb.c:2492 +#: initdb.c:2580 #, c-format msgid "" "\n" @@ -776,72 +806,72 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: initdb.c:2493 +#: initdb.c:2581 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: initdb.c:2517 +#: initdb.c:2605 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "\"%2$s\"接続では認証方式\"%1$s\"は無効です" -#: initdb.c:2531 +#: initdb.c:2619 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "パスワード認証を有効にするにはスーパーユーザーのパスワードを指定する必要があります" -#: initdb.c:2550 +#: initdb.c:2638 #, c-format msgid "no data directory specified" msgstr "データディレクトリが指定されていません" -#: initdb.c:2551 +#: initdb.c:2639 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "データベースシステムのデータを格納するディレクトリを指定する必要があります。実行時オプション -D、もしくは、PGDATA環境変数で指定してください。" -#: initdb.c:2568 +#: initdb.c:2656 #, c-format msgid "could not set environment" msgstr "環境を設定できません" -#: initdb.c:2586 +#: initdb.c:2674 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "%2$sにはプログラム\"%1$s\"が必要ですが、\"%3$s\"と同じディレクトリにはありませんでした。" -#: initdb.c:2589 +#: initdb.c:2677 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした。" -#: initdb.c:2604 +#: initdb.c:2692 #, c-format msgid "input file location must be an absolute path" msgstr "入力ファイルの場所は絶対パスでなければなりません" -#: initdb.c:2621 +#: initdb.c:2709 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "データベースクラスタはロケール\"%s\"で初期化されます。\n" -#: initdb.c:2624 +#: initdb.c:2712 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "データベースクラスタは以下のロケール構成で初期化されます。\n" -#: initdb.c:2625 +#: initdb.c:2713 #, c-format msgid " locale provider: %s\n" msgstr " ロケールプロバイダ:%s\n" -#: initdb.c:2627 +#: initdb.c:2715 #, c-format msgid " default collation: %s\n" msgstr " デフォルト照合順序:%s\n" -#: initdb.c:2628 +#: initdb.c:2716 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -858,22 +888,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2658 +#: initdb.c:2746 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "ロケール\"%s\"に対して適切な符号化方式がありませんでした" -#: initdb.c:2660 +#: initdb.c:2748 #, c-format msgid "Rerun %s with the -E option." msgstr "-Eオプションを付けて%sを再実行してください。" -#: initdb.c:2661 initdb.c:3204 initdb.c:3324 initdb.c:3344 +#: initdb.c:2749 initdb.c:3287 initdb.c:3413 initdb.c:3433 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: initdb.c:2673 +#: initdb.c:2761 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -883,112 +913,112 @@ msgstr "" "符号化方式として使用できません。\n" "デフォルトのデータベース符号化方式は代わりに\"%s\"に設定されます。\n" -#: initdb.c:2678 +#: initdb.c:2766 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "ロケール\"%s\"は非サポートの符号化方式\"%s\"を必要とします" -#: initdb.c:2680 +#: initdb.c:2768 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "符号化方式\"%s\"はサーバー側の符号化方式として使用できません。" -#: initdb.c:2682 +#: initdb.c:2770 #, c-format msgid "Rerun %s with a different locale selection." msgstr "別のローケルを選択して%sを再実行してください。" -#: initdb.c:2690 +#: initdb.c:2778 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "デフォルトのデータベース符号化方式はそれに対応して%sに設定されました。\n" -#: initdb.c:2704 +#: initdb.c:2794 #, c-format msgid "builtin provider locale \"%s\" requires encoding \"%s\"" msgstr "組み込みプロバイダロケール\"%s\"は符号化方式\"%s\"を必要とします" -#: initdb.c:2766 +#: initdb.c:2856 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "ロケール\"%s\"用の適切なテキスト検索設定が見つかりませんでした" -#: initdb.c:2777 +#: initdb.c:2867 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "ロケール\"%s\"に適したテキスト検索設定が不明です" -#: initdb.c:2782 +#: initdb.c:2872 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "指定したテキスト検索設定\"%s\"がロケール\"%s\"に合わない可能性があります" -#: initdb.c:2787 +#: initdb.c:2877 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "デフォルトのテキスト検索構成は %s に設定されます。\n" -#: initdb.c:2830 initdb.c:2901 +#: initdb.c:2911 initdb.c:2982 #, c-format msgid "creating directory %s ... " msgstr "ディレクトリ%sを作成しています ... " -#: initdb.c:2835 initdb.c:2906 initdb.c:2954 initdb.c:3011 +#: initdb.c:2916 initdb.c:2987 initdb.c:3035 initdb.c:3092 #, c-format msgid "could not create directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" -#: initdb.c:2844 initdb.c:2916 +#: initdb.c:2925 initdb.c:2997 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "ディレクトリ%sの権限を設定しています ... " -#: initdb.c:2849 initdb.c:2921 +#: initdb.c:2930 initdb.c:3002 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "ディレクトリ\"%s\"の権限を変更できませんでした: %m" -#: initdb.c:2861 initdb.c:2933 +#: initdb.c:2942 initdb.c:3014 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "ディレクトリ\"%s\"は存在しますが、空ではありません" -#: initdb.c:2865 +#: initdb.c:2946 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "新規にデータベースシステムを作成したいのであれば、ディレクトリ\"%s\"を削除あるいは空にする、または%sを\"%s\"以外の引数で実行してください。" -#: initdb.c:2873 initdb.c:2943 initdb.c:3369 +#: initdb.c:2954 initdb.c:3024 initdb.c:3458 #, c-format msgid "could not access directory \"%s\": %m" msgstr "ディレクトリ\"%s\"にアクセスできませんでした: %m" -#: initdb.c:2894 +#: initdb.c:2975 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL ディレクトリの位置は、絶対パスでなければなりません" -#: initdb.c:2937 +#: initdb.c:3018 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "そこにWALを格納したい場合は、ディレクトリ\"%s\"を削除するか空にしてください。" -#: initdb.c:2947 +#: initdb.c:3028 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "シンボリックリンク\"%s\"を作成できませんでした: %m" -#: initdb.c:2966 +#: initdb.c:3047 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "おそらくマウントポイントであることに起因した先頭がドットであるファイル、または不可視なファイルが含まれています。" -#: initdb.c:2968 +#: initdb.c:3049 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "おそらくマウントポイントであることに起因したlost+foundディレクトリが含まれています。" -#: initdb.c:2970 +#: initdb.c:3051 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -997,65 +1027,65 @@ msgstr "" "マウントポイントであるディレクトリをデータディレクトリとして使用することはお勧めしません。\n" "この下にサブディレクトリを作成してください。" -#: initdb.c:2997 +#: initdb.c:3078 #, c-format msgid "creating subdirectories ... " msgstr "サブディレクトリを作成しています ... " -#: initdb.c:3040 +#: initdb.c:3121 msgid "performing post-bootstrap initialization ... " msgstr "ブートストラップ後の初期化を実行しています ... " -#: initdb.c:3203 +#: initdb.c:3286 #, c-format msgid "-c %s requires a value" msgstr "-c %sは値が必要です" -#: initdb.c:3228 +#: initdb.c:3311 #, c-format msgid "Running in debug mode.\n" msgstr "デバッグモードで実行しています。\n" -#: initdb.c:3232 +#: initdb.c:3315 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "no-clean モードで実行しています。失敗した状況は削除されません。\n" -#: initdb.c:3305 +#: initdb.c:3388 #, c-format msgid "unrecognized locale provider: %s" msgstr "認識できない照合順序プロバイダ: %s" -#: initdb.c:3342 +#: initdb.c:3431 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: initdb.c:3349 initdb.c:3353 initdb.c:3357 +#: initdb.c:3438 initdb.c:3442 initdb.c:3446 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "ロケールプロバイダ\"%2$s\"が選択されていなければ%1$sは指定できません" -#: initdb.c:3371 initdb.c:3434 +#: initdb.c:3460 initdb.c:3523 msgid "syncing data to disk ... " msgstr "データをディスクに同期しています ... " -#: initdb.c:3379 +#: initdb.c:3468 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "パスワードプロンプトとパスワードファイルは同時に指定できません" -#: initdb.c:3390 +#: initdb.c:3479 #, c-format msgid "argument of %s must be a power of two between 1 and 1024" msgstr "%sの引数は1から1024までの間の2の累乗でなければなりません" -#: initdb.c:3403 +#: initdb.c:3492 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "スーパーユーザー名\"%s\"は許可されません; ロール名は\"pg_\"で始めることはできません" -#: initdb.c:3405 +#: initdb.c:3494 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1066,17 +1096,17 @@ msgstr "" "このユーザーをサーバープロセスの所有者とする必要があります。\n" "\n" -#: initdb.c:3421 +#: initdb.c:3510 #, c-format msgid "Data page checksums are enabled.\n" msgstr "データページのチェックサムは有効です。\n" -#: initdb.c:3423 +#: initdb.c:3512 #, c-format msgid "Data page checksums are disabled.\n" msgstr "データベージのチェックサムは無効です。\n" -#: initdb.c:3440 +#: initdb.c:3529 #, c-format msgid "" "\n" @@ -1087,22 +1117,22 @@ msgstr "" "ディスクへの同期がスキップされました。\n" "オペレーティングシステムがクラッシュした場合データディレクトリは破損されるかもしれません。\n" -#: initdb.c:3445 +#: initdb.c:3534 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "ローカル接続に対して\"trust\"認証を有効にします " -#: initdb.c:3446 +#: initdb.c:3535 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "pg_hba.confを編集する、もしくは、次回initdbを実行する時に -A オプション、あるいは --auth-local および --auth-host オプションを使用することで変更できます。" #. translator: This is a placeholder in a shell command. -#: initdb.c:3476 +#: initdb.c:3565 msgid "logfile" msgstr "ログファイル" -#: initdb.c:3478 +#: initdb.c:3567 #, c-format msgid "" "\n" diff --git a/src/bin/initdb/po/ka.po b/src/bin/initdb/po/ka.po index 898a421cb4c2a..fe27c8f866e00 100644 --- a/src/bin/initdb/po/ka.po +++ b/src/bin/initdb/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: initdb (PostgreSQL) 17\n" +"Project-Id-Version: initdb (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:21+0000\n" -"PO-Revision-Date: 2024-06-14 06:11+0200\n" +"POT-Creation-Date: 2025-03-27 22:52+0000\n" +"PO-Revision-Date: 2025-03-28 03:57+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,24 +16,24 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " @@ -58,28 +58,28 @@ msgstr "გასაშვებად ფაილის \"%s\" პოვნა msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "ბილიკის (\"%s\") აბსოლუტურ ფორმაში ამოხსნის შეცდომა: %m" -#: ../../common/exec.c:382 initdb.c:695 +#: ../../common/exec.c:363 initdb.c:753 #, c-format msgid "could not execute command \"%s\": %m" msgstr "ბრძანების (\"%s\") შესრულების შეცდომა: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "ბრძანებიდან \"%s\" წაკითხვის შეცდომა: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "ბრძანებამ \"%s\" მონაცემები არ დააბრუნა" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s()-ის შეცდომა: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 -#: initdb.c:353 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 +#: initdb.c:375 initdb.c:411 #, c-format msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" @@ -95,46 +95,46 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -243,12 +243,12 @@ msgstr "%s არაა საზღვრებში %d-დან %d-მდე msgid "unrecognized sync method: %s" msgstr "უცნობი სინქრონიზაციის მეთოდი: \"%s\"" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" @@ -263,274 +263,294 @@ msgstr "\"%s\"-ისთვის შეერთების დაყენე msgid "could not get junction for \"%s\": %s\n" msgstr "\"%s\"-ისთვის შეერთების მიღება ვერ მოხერხდა: %s\n" -#: initdb.c:627 initdb.c:1619 +#: initdb.c:372 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale() ჩავარდა" + +#: initdb.c:379 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale() ჩავარდა" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale" +msgstr "ძველი ლოკალის აღდგენა ჩავარდა" + +#: initdb.c:396 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "ძველი ენის (\"%s\") აღდგენის შეცდომა" + +#: initdb.c:685 initdb.c:1705 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: initdb.c:671 initdb.c:975 initdb.c:995 +#: initdb.c:729 initdb.c:1035 initdb.c:1055 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "ფაილის (\"%s\") ჩასაწერად გახსნა შეუძლებელია: %m" -#: initdb.c:675 initdb.c:978 initdb.c:997 +#: initdb.c:733 initdb.c:1038 initdb.c:1057 #, c-format msgid "could not write file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: initdb.c:679 +#: initdb.c:737 #, c-format msgid "could not close file \"%s\": %m" msgstr "ფაილის (%s) დახურვის შეცდომა: %m" -#: initdb.c:713 +#: initdb.c:771 #, c-format msgid "removing data directory \"%s\"" msgstr "მონაცემების საქაღალდის წაშლა \"%s\"" -#: initdb.c:715 +#: initdb.c:773 #, c-format msgid "failed to remove data directory" msgstr "მონაცემების საქაღალდის წაშლის შეცდომა" -#: initdb.c:719 +#: initdb.c:777 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "მონაცემების საქაღალდის შემცველობის წაშლა \"%s\"" -#: initdb.c:722 +#: initdb.c:780 #, c-format msgid "failed to remove contents of data directory" msgstr "მონაცემების საქაღალდის შემცველობის წაშლის შეცდომა" -#: initdb.c:727 +#: initdb.c:785 #, c-format msgid "removing WAL directory \"%s\"" msgstr "მიმდინარეობს WAL საქაღალდის წაშლა \"%s\"" -#: initdb.c:729 +#: initdb.c:787 #, c-format msgid "failed to remove WAL directory" msgstr "შეცდომა WAL საქაღალდის წაშლისას" -#: initdb.c:733 +#: initdb.c:791 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "მიმდინარეობს WAL საქაღალდის (\"%s\") შემცველობის წაშლა" -#: initdb.c:735 +#: initdb.c:793 #, c-format msgid "failed to remove contents of WAL directory" msgstr "შეცდომა WAL საქაღალდის შემცველობის წაშლისას" -#: initdb.c:742 +#: initdb.c:800 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "მონაცემების საქაღალდე \"%s\" მომხმარებლის მოთხოვნისას არ წაიშლება" -#: initdb.c:746 +#: initdb.c:804 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "WAL საქაღალდე \"%s\" მომხმარებლის მოთხოვნისას არ წაიშლება" -#: initdb.c:764 +#: initdb.c:822 #, c-format msgid "cannot be run as root" msgstr "root-ით ვერ გაეშვება" -#: initdb.c:765 +#: initdb.c:823 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "შედით (ან გამოიყენეთ \"su\") არაპრივილეგირებული მომხმარებლით, რომელიც სერვერს პროცესის მფლობელი იქნება." -#: initdb.c:797 +#: initdb.c:855 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\" კოდირების სწორ სახელს არ წარმოადგენს" -#: initdb.c:941 +#: initdb.c:1001 #, c-format msgid "file \"%s\" does not exist" msgstr "ფაილი %s არ არსებობს" -#: initdb.c:942 initdb.c:947 initdb.c:954 +#: initdb.c:1002 initdb.c:1007 initdb.c:1014 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "შეიძლება ნიშნავდეს, რომ თქვენი დაყენებული ვერსია გაფუჭებულია ან -L -ს არასწორი საქაღალდე მიუთითეთ." -#: initdb.c:946 +#: initdb.c:1006 #, c-format msgid "could not access file \"%s\": %m" msgstr "ფაილის (%s) წვდომის შეცდომა: %m" -#: initdb.c:953 +#: initdb.c:1013 #, c-format msgid "file \"%s\" is not a regular file" msgstr "ფაილ \"%s\" ჩვეულებრივი ფაილი არაა" -#: initdb.c:1086 +#: initdb.c:1158 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "დინამიკური გაზიარებული მეხსიერების იმპლემენტაციის არჩევა ... " -#: initdb.c:1095 +#: initdb.c:1168 #, c-format msgid "selecting default \"max_connections\" ... " msgstr "ნაგულისხმევი \"max_connections\"-ის არჩევა … " -#: initdb.c:1115 +#: initdb.c:1193 +#, c-format +msgid "selecting default \"autovacuum_worker_slots\" ... %d\n" +msgstr "მიმდინარეობს ნაგულისხმევი \"autovacuum_worker_slots\"-ის არჩევა ... %d\n" + +#: initdb.c:1196 #, c-format msgid "selecting default \"shared_buffers\" ... " msgstr "ნაგულისხმევი \"shared_buffers\"-ის არჩევა … " -#: initdb.c:1138 +#: initdb.c:1219 #, c-format msgid "selecting default time zone ... " msgstr "დროის ნაგულისხმევი სარტყლის არჩევა … " -#: initdb.c:1217 +#: initdb.c:1299 msgid "creating configuration files ... " msgstr "კონფიგურაციის ფაილების შექმნა … " -#: initdb.c:1370 initdb.c:1384 initdb.c:1451 initdb.c:1462 +#: initdb.c:1456 initdb.c:1470 initdb.c:1537 initdb.c:1548 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "\"%s\"-ის წვდომების შეცვლის შეცდომა: %m" -#: initdb.c:1481 +#: initdb.c:1567 #, c-format msgid "running bootstrap script ... " msgstr "მოსამზადებელი სკრიპტის გაშვება ... " -#: initdb.c:1493 +#: initdb.c:1579 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "შეყვანილი ფაილი \"%s\" PostgreSQL %s -ს არ ეკუთვნის" -#: initdb.c:1495 +#: initdb.c:1581 #, c-format msgid "Specify the correct path using the option -L." msgstr "მიუთითეთ სწორი ბილიკი -L პარამეტრით." -#: initdb.c:1597 +#: initdb.c:1683 msgid "Enter new superuser password: " msgstr "შეიყვანეთ ზემომხმარებლის ახალი პაროლი: " -#: initdb.c:1598 +#: initdb.c:1684 msgid "Enter it again: " msgstr "შეიყვანეთ კდევ ერთხელ: " -#: initdb.c:1601 +#: initdb.c:1687 #, c-format msgid "Passwords didn't match.\n" msgstr "პაროლები არ ემთხვევა.\n" -#: initdb.c:1625 +#: initdb.c:1711 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "პაროლის ფაილიდან (\"%s\") წაკითხვის შეცდომა: %m" -#: initdb.c:1628 +#: initdb.c:1714 #, c-format msgid "password file \"%s\" is empty" msgstr "პაროლის ფაილი (\"%s\") ცარიელია" -#: initdb.c:2040 +#: initdb.c:2126 #, c-format msgid "caught signal\n" msgstr "მიღებულია სიგნალი\n" -#: initdb.c:2046 +#: initdb.c:2132 #, c-format msgid "could not write to child process: %s\n" msgstr "შვილობილი პროცესისთვის ჩაწერის შეცდომა: %s\n" -#: initdb.c:2054 +#: initdb.c:2140 #, c-format msgid "ok\n" msgstr "დიახ\n" -#: initdb.c:2143 -#, c-format -msgid "setlocale() failed" -msgstr "setlocale()-ის შეცდომა" - -#: initdb.c:2161 +#: initdb.c:2222 initdb.c:2268 #, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "ძველი ენის (\"%s\") აღდგენის შეცდომა" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "ლოკალის სახელი \"%s\" არა-ASCII სიმბოლოებს შეიცავს" -#: initdb.c:2169 +#: initdb.c:2248 #, c-format msgid "invalid locale name \"%s\"" msgstr "ენის არასწორი სახელი: \"%s\"" -#: initdb.c:2170 +#: initdb.c:2249 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "თუ ლოკალის სახელი მხოლოდ მითითებული ICU-სთვისა ხელმისაწვდომი, გამოიყენეთ --icu-locale." -#: initdb.c:2183 +#: initdb.c:2262 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "ენის არასწორი პარამეტრები; გადაამოწმეთ გარემოს ცვლადები: LANG და LC_*" -#: initdb.c:2209 initdb.c:2233 +#: initdb.c:2293 initdb.c:2317 #, c-format msgid "encoding mismatch" msgstr "კოდირება არ ემთხვევა" -#: initdb.c:2210 +#: initdb.c:2294 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "თქვენ მიერ არჩეული კოდირება (%s) და კოდირება, რომელსაც არჩეული ენა იყენებს (%s) არ ემთხვევა. ეს სიმბოლოების სტრიქონების დამუშავების სხვადასხვა ფუნქციების არასწორ ქცევას გამოიწვევს." -#: initdb.c:2215 initdb.c:2236 +#: initdb.c:2299 initdb.c:2320 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "თავიდან გაუშვით %s და კოდირება ან არ მიუთითოთ, ან სწორად მიუთითეთ." -#: initdb.c:2234 +#: initdb.c:2318 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "თქვენს მიერ შერჩეული კოდირება (%s) ICU -ის მომწოდებელთან ერთად მხარდაუჭერელია." -#: initdb.c:2285 +#: initdb.c:2369 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "მდებარეობის კოდის \"%s\" ენის ჭდეში (%s) გადაყვანის შეცდომა" -#: initdb.c:2291 initdb.c:2343 initdb.c:2435 +#: initdb.c:2375 initdb.c:2427 initdb.c:2521 #, c-format msgid "ICU is not supported in this build" msgstr "ამ აგებაში ICU-ის მხარდაჭერა არ არსებბს" -#: initdb.c:2314 +#: initdb.c:2398 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "ლოკალიდან \"%s\" ენის მიღების შეცდომა: %s" -#: initdb.c:2340 +#: initdb.c:2424 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "ლოკალის \"%s\" ენა \"%s\" უცნობია" -#: initdb.c:2401 +#: initdb.c:2485 #, c-format msgid "locale must be specified if provider is %s" msgstr "ლოკალის მითითება აუცილებელია, თუ მომწოდებელია %s" -#: initdb.c:2412 +#: initdb.c:2498 #, c-format msgid "invalid locale name \"%s\" for builtin provider" msgstr "არასწორი ლოკალის სახელი \"%s\" ჩაშენებული მომწოდებლისთვის" -#: initdb.c:2423 +#: initdb.c:2509 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "ვიყენებ ენის ჭდეს \"%s\" ICU ლოკალისთვის \"%s\".\n" -#: initdb.c:2446 +#: initdb.c:2532 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -539,17 +559,17 @@ msgstr "" "%s PostgreSQL ბაზის კლასერის ინიციალიზაციას ახდენს.\n" "\n" -#: initdb.c:2447 +#: initdb.c:2533 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: initdb.c:2448 +#: initdb.c:2534 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [პარამეტრი]... [მონაცემებისსაქაღალდე]\n" -#: initdb.c:2449 +#: initdb.c:2535 #, c-format msgid "" "\n" @@ -558,57 +578,57 @@ msgstr "" "\n" "პარამეტრები:\n" -#: initdb.c:2450 +#: initdb.c:2536 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, --auth=მეთოდი ავთენტიკაციის ნაგულისხმევი მეთოდი ლოკალური შეერთებებისთვის\n" -#: initdb.c:2451 +#: initdb.c:2537 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr " --auth-host=მეთოდი ლოკალური TCP/IP შეერთების ავთენტიკაციის ნაგულისხმევი მეთოდი\n" -#: initdb.c:2452 +#: initdb.c:2538 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr " --auth-local=მეთოდი ლოკალური სოკეტის შეერთების ავთენტიკაციის ნაგულისხმევი მეთოდი\n" -#: initdb.c:2453 +#: initdb.c:2539 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATADIR ბაზის კლასტერის მდებარეობა\n" -#: initdb.c:2454 +#: initdb.c:2540 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=კოდირება ახალი ბაზების ნაგულისხმევი კოდირება\n" -#: initdb.c:2455 +#: initdb.c:2541 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr " -g, --allow-group-access მონაცემების საქაღალდეზე ჯგუფის კითხვა/გაშვების წვდომის დაყენება\n" -#: initdb.c:2456 +#: initdb.c:2542 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=კოდირება ICU ენის ID ახალი ბაზებისთვის\n" -#: initdb.c:2457 +#: initdb.c:2543 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" msgstr " --icu-rules=წესები ახალი ბაზებისთვის დამატებითი ICUკოლაციის წესების დაყენება\n" -#: initdb.c:2458 +#: initdb.c:2544 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums მონაცემების გვერდის საკონტროლო ჯამების გამოყენება\n" -#: initdb.c:2459 +#: initdb.c:2545 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=ენა ახალი ბაზების ნაგულისხმევი ენის დაყენება\n" -#: initdb.c:2460 +#: initdb.c:2546 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -621,12 +641,12 @@ msgstr "" " დააყენეთ ნაგულისხმევი ენა შესაბამის კატეგორიაში\n" " ახალი ბაზებისთვის (ნაგულისხმევი აღებულია გარემოდან)\n" -#: initdb.c:2464 +#: initdb.c:2550 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale იგივე, რაც --locale=C\n" -#: initdb.c:2465 +#: initdb.c:2551 #, c-format msgid "" " --builtin-locale=LOCALE\n" @@ -635,7 +655,7 @@ msgstr "" " --builtin-locale=ლოკალი\n" " ჩაშენებული ლოკალის სახელის დაყენება ახალი ბაზებისთვის\n" -#: initdb.c:2467 +#: initdb.c:2553 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -644,12 +664,17 @@ msgstr "" " --locale-provider={builtin|libc|icu}\n" " ახალი ბაზებისთვის ლოკალის ნაგულისხმევი მიმწოდებლის დაყენება\n" -#: initdb.c:2469 +#: initdb.c:2555 +#, c-format +msgid " --no-data-checksums do not use data page checksums\n" +msgstr " --no-data-checksums მონაცემების გვერდის საკონტროლო ჯამები გამოყენებული არ იქნება\n" + +#: initdb.c:2556 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=FILE ახალი ზემომხმარებლის პაროლის ფაილიდან წაკითხვა\n" -#: initdb.c:2470 +#: initdb.c:2557 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -658,27 +683,27 @@ msgstr "" " -T, --text-search-config=CFG\n" " ტექსტის ძებნის ნაგულისხმევი კონფიგურაცია\n" -#: initdb.c:2472 +#: initdb.c:2559 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=სახელი ბაზის ზემომხმარებლის სახელი\n" -#: initdb.c:2473 +#: initdb.c:2560 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt ზემომხმარებლის პაროლის კითხვა\n" -#: initdb.c:2474 +#: initdb.c:2561 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR წინასწარ ჩაწერადი ჟურნალის (WAL) საქაღალდის მდებარეობა\n" -#: initdb.c:2475 +#: initdb.c:2562 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=ზომა WAL სეგმენტების ზომა, მეგაბაიტებში\n" -#: initdb.c:2476 +#: initdb.c:2563 #, c-format msgid "" "\n" @@ -687,57 +712,63 @@ msgstr "" "\n" "იშვიათად გამოყენებული პარამეტრები:\n" -#: initdb.c:2477 +#: initdb.c:2564 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAME=VALUE სერვერის ნაგულისხმევი პარამეტრის გადაფარვა\n" -#: initdb.c:2478 +#: initdb.c:2565 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug გასამართი ინფორმაციის გენერაცია\n" -#: initdb.c:2479 +#: initdb.c:2566 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches debug_discard_caches=1 დაყენება\n" -#: initdb.c:2480 +#: initdb.c:2567 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L საქაღალდე შეყვანის ფაილების შემცველი საქაღალდე\n" -#: initdb.c:2481 +#: initdb.c:2568 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean შეცდომის შემთხვევაში არ გაასუფთავო\n" -#: initdb.c:2482 +#: initdb.c:2569 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: initdb.c:2483 +#: initdb.c:2570 +#, c-format +#| msgid " --no-data-checksums do not use data page checksums\n" +msgid " --no-sync-data-files do not sync files within database directories\n" +msgstr " --no-sync-data-files მონაცემთა საქაღალდეებს შორის ფაილების სინქრონიზაცია არ მოხდება\n" + +#: initdb.c:2571 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions შემდეგი ნაბიჯის ინსტრუქციები ნაჩვენები არ იქნება\n" -#: initdb.c:2484 +#: initdb.c:2572 #, c-format msgid " -s, --show show internal settings, then exit\n" msgstr " -s, --show შიდა პარამეტრების ჩვენება და გასვლა\n" -#: initdb.c:2485 +#: initdb.c:2573 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=მეთოდი ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: initdb.c:2486 +#: initdb.c:2574 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only ბაზის ფაილების დისკზე სინქრონიზაცია და გასვლა\n" -#: initdb.c:2487 +#: initdb.c:2575 #, c-format msgid "" "\n" @@ -746,17 +777,17 @@ msgstr "" "\n" "სხვა პარამეტრები:\n" -#: initdb.c:2488 +#: initdb.c:2576 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: initdb.c:2489 +#: initdb.c:2577 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: initdb.c:2490 +#: initdb.c:2578 #, c-format msgid "" "\n" @@ -767,7 +798,7 @@ msgstr "" "თუ მონაცემების საქაღალდე მითითებული არაა, გამოყენებული იქნება \n" "გარემოს ცვლადი PGDATA.\n" -#: initdb.c:2492 +#: initdb.c:2580 #, c-format msgid "" "\n" @@ -776,72 +807,72 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: initdb.c:2493 +#: initdb.c:2581 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: initdb.c:2517 +#: initdb.c:2605 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "ავთენტიკაციის მეთოდი (\"%s\") არასწორია \"%s\" შეერთებებისთვის" -#: initdb.c:2531 +#: initdb.c:2619 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "პაროლით ავთენტიკაციის ჩასართავად საჭიროა ზემომხმარებლის პაროლის მითითება" -#: initdb.c:2550 +#: initdb.c:2638 #, c-format msgid "no data directory specified" msgstr "მონაცემების საქაღალდე მითითებული არაა" -#: initdb.c:2551 +#: initdb.c:2639 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "უნდა დაადგინოთ საქაღლდე, სადაც ბაზის ამ სისტემის მონაცემები იქნება განთავსებული . გააკეთეთ ეს ან გამოძახების პარამეტრით -D ან გარემოს ცვლადით PGDATA." -#: initdb.c:2568 +#: initdb.c:2656 #, c-format msgid "could not set environment" msgstr "გარემოს დაყენების შეცდომა" -#: initdb.c:2586 +#: initdb.c:2674 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა" -#: initdb.c:2589 +#: initdb.c:2677 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s" -#: initdb.c:2604 +#: initdb.c:2692 #, c-format msgid "input file location must be an absolute path" msgstr "შეყვანის ფაილის მდებარეობა აბსტოლუტური ბილიკი უნდა იყოს" -#: initdb.c:2621 +#: initdb.c:2709 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "ბაზის კლასტერის ინიციალიზაცია ენით \"%s\".\n" -#: initdb.c:2624 +#: initdb.c:2712 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "ბაზის კლასტერის ინიციალიზაცია ენის ამ კონფიგურაციით მოხდება:\n" -#: initdb.c:2625 +#: initdb.c:2713 #, c-format msgid " locale provider: %s\n" msgstr " ლოკალის მომწოდებელი: %s\n" -#: initdb.c:2627 +#: initdb.c:2715 #, c-format msgid " default collation: %s\n" msgstr " ნაგულიხმევი კოლაცია: %s\n" -#: initdb.c:2628 +#: initdb.c:2716 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -858,22 +889,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2658 +#: initdb.c:2746 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "ენისთვის (\"%s\") შესაბამისი კოდირება ვერ ვიპოვე" -#: initdb.c:2660 +#: initdb.c:2748 #, c-format msgid "Rerun %s with the -E option." msgstr "გაუშვით %s თავიდან -E პარამეტრით." -#: initdb.c:2661 initdb.c:3204 initdb.c:3324 initdb.c:3344 +#: initdb.c:2749 initdb.c:3287 initdb.c:3413 initdb.c:3433 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: initdb.c:2673 +#: initdb.c:2761 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -882,112 +913,112 @@ msgstr "" "ენის ნაგულისხმევი „%s“ კოდირების დაყენება, სერვერის დასაშიფრად შეუძლებელია.\n" "სანაცვლოდ, ბაზის ნაგულისხმევი კოდირება დაყენდება „%s“.\n" -#: initdb.c:2678 +#: initdb.c:2766 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "ენას (\"%s\") მხარდაუჭერელი კოდირება (\"%s\") სჭირდება" -#: initdb.c:2680 +#: initdb.c:2768 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "%s სერვერის მხარეს კოდირება ვერ იქნება." -#: initdb.c:2682 +#: initdb.c:2770 #, c-format msgid "Rerun %s with a different locale selection." msgstr "%s-ის თავიდან გაშვება ენის სხვა არჩევანით." -#: initdb.c:2690 +#: initdb.c:2778 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "ბაზის ნაგულისხმევი კოდირება შესაბამისად დაყენებულია „%s“-ზე.\n" -#: initdb.c:2704 +#: initdb.c:2794 #, c-format msgid "builtin provider locale \"%s\" requires encoding \"%s\"" msgstr "ჩაშენებულ მომწოდებელს ლოკალისთვის \"%s\" ესაჭიროება კოდირება \"%s\"" -#: initdb.c:2766 +#: initdb.c:2856 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "ტექსტის ძებნის ენისთვის შესაფერისი კონფიგურაციის მოძებნა შეუძლებელია: \"%s\"" -#: initdb.c:2777 +#: initdb.c:2867 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "ტექსტის ძებნის ენისთვის შესაფერისი კონფიგურაცია არ არსებობს: \"%s\"" -#: initdb.c:2782 +#: initdb.c:2872 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "ტექსტის ძებნის მითითებული კონფიგურაცია \"%s\" ენას (\"%s\") არ ემთხვევა" -#: initdb.c:2787 +#: initdb.c:2877 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "ტექსტის ძებნის ნაგულისხმევი კონფიგურაცია \"%s\" იქნება.\n" -#: initdb.c:2830 initdb.c:2901 +#: initdb.c:2911 initdb.c:2982 #, c-format msgid "creating directory %s ... " msgstr "საქაღალდის (\"%s\") შექმნა .... " -#: initdb.c:2835 initdb.c:2906 initdb.c:2954 initdb.c:3011 +#: initdb.c:2916 initdb.c:2987 initdb.c:3035 initdb.c:3092 #, c-format msgid "could not create directory \"%s\": %m" msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" -#: initdb.c:2844 initdb.c:2916 +#: initdb.c:2925 initdb.c:2997 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "არსებულ საქაღალდეზე (\"%s\") წვდომების ჩასწორება ... " -#: initdb.c:2849 initdb.c:2921 +#: initdb.c:2930 initdb.c:3002 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "საქაღალდის წვდომების შეცვლა შეუძლებელია \"%s\": %m" -#: initdb.c:2861 initdb.c:2933 +#: initdb.c:2942 initdb.c:3014 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "საქაღალდე \"%s\" არსებობს, მაგრამ ცარიელი არაა" -#: initdb.c:2865 +#: initdb.c:2946 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "თუ გსურთ ბაზის ახალი სისტემის შექმნა, წაშალეთ ან დააცარიელეთ საქაღალდე, %s ან %s „%s“-ის გარდა არგუმენტით გაუშვით." -#: initdb.c:2873 initdb.c:2943 initdb.c:3369 +#: initdb.c:2954 initdb.c:3024 initdb.c:3458 #, c-format msgid "could not access directory \"%s\": %m" msgstr "საქაღალდის (%s) წვდომის შეცდომა: %m" -#: initdb.c:2894 +#: initdb.c:2975 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL საქაღალდის მდებარეობა აბსოლუტური ბილიკი უნდა იყოს" -#: initdb.c:2937 +#: initdb.c:3018 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "თუ გსურთ WAL-ის იქ შენახვა, წაშალეთ ან დააცარიელეთ საქაღალდე „%s“." -#: initdb.c:2947 +#: initdb.c:3028 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "სიმბმულის შექმნის შეცდომა %s: %m" -#: initdb.c:2966 +#: initdb.c:3047 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "ის შეიცავს წერტილით დაწყებულ/უხილავ ფაილს, შესაძლოა იმის გამო, რომ ის მიმაგრების წერტილია." -#: initdb.c:2968 +#: initdb.c:3049 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "ის შეიცავს lost+found საქაღალდეს. ალბათ იმის გამო, რომ ის მიმაგრების წერტილია." -#: initdb.c:2970 +#: initdb.c:3051 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -996,65 +1027,65 @@ msgstr "" "მიმაგრების წერტილის პირდაპირ მონაცემთა საქაღალდედ გამოყენება რეკომენდებული არაა.\n" "შექმენით ქვესაქაღალდე მიმაგრების წერტილის ქვეშ." -#: initdb.c:2997 +#: initdb.c:3078 #, c-format msgid "creating subdirectories ... " msgstr "ქვესაქაღალდეების შექმნა ... " -#: initdb.c:3040 +#: initdb.c:3121 msgid "performing post-bootstrap initialization ... " msgstr "პირველადი მომზადების შემდგომი ინიციალიზაციის შესრულება ... " -#: initdb.c:3203 +#: initdb.c:3286 #, c-format msgid "-c %s requires a value" msgstr "-c %s მნიშვნელობა სჭირდება" -#: initdb.c:3228 +#: initdb.c:3311 #, c-format msgid "Running in debug mode.\n" msgstr "გაშვებულია გამართვის რეჟიმში.\n" -#: initdb.c:3232 +#: initdb.c:3315 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "გაშვებულია მოუწმენდავ რეჟიმში. შეცდომები არ გაიწმინდება.\n" -#: initdb.c:3305 +#: initdb.c:3388 #, c-format msgid "unrecognized locale provider: %s" msgstr "ენის უცნობი მომწოდებელი: %s" -#: initdb.c:3342 +#: initdb.c:3431 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: initdb.c:3349 initdb.c:3353 initdb.c:3357 +#: initdb.c:3438 initdb.c:3442 initdb.c:3446 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s ვერ იქნება მითითებული, თუ ენის მომწოდებლად „%s“ არ არის არჩეული" -#: initdb.c:3371 initdb.c:3434 +#: initdb.c:3460 initdb.c:3523 msgid "syncing data to disk ... " msgstr "მონაცემების სინქრონიზაცია დისკზე ... " -#: initdb.c:3379 +#: initdb.c:3468 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "პაროლის მოთხოვნისა და პაროლის ფაილის ერთდროულად მითითება შეუძებელია" -#: initdb.c:3390 +#: initdb.c:3479 #, c-format msgid "argument of %s must be a power of two between 1 and 1024" msgstr "%s-ის არგუმენტი 2-ის ხარისხი უნდა იყოს 1-1024 შუალედიდან" -#: initdb.c:3403 +#: initdb.c:3492 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "ზემომხმარებლის სახელი \"%s\" უარყოფილია. როლის სახელებია \"pg_\"-ით ვერ დაიწყება" -#: initdb.c:3405 +#: initdb.c:3494 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1065,17 +1096,17 @@ msgstr "" "ეს მომხმარებელი სერვერის პროცესსაც უნდა ფლობდეს.\n" "\n" -#: initdb.c:3421 +#: initdb.c:3510 #, c-format msgid "Data page checksums are enabled.\n" msgstr "მონაცემების გვერდის საკონტროლო ჯამები ჩართულია.\n" -#: initdb.c:3423 +#: initdb.c:3512 #, c-format msgid "Data page checksums are disabled.\n" msgstr "მონაცემების გვერდის საკონტროლო ჯამები გამორთულია.\n" -#: initdb.c:3440 +#: initdb.c:3529 #, c-format msgid "" "\n" @@ -1086,22 +1117,22 @@ msgstr "" "დისკთან სინქრონიზაცია გამოტოვებულია.\n" "ოპერაციული სისტემის სიკვდილის შემთხვევაში მონაცემების საქაღალდე შეიძლება დაზიანდეს.\n" -#: initdb.c:3445 +#: initdb.c:3534 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "ლოკალური შეერთებებისთვის \"trust\" ავთენტიკაციის ჩართვა" -#: initdb.c:3446 +#: initdb.c:3535 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "შეცვლა შეგიძლიათ pg_hba.conf-ის რედაქტირებით ან როცა შემდეგ ჯერზე გაუშვებთ initdb-ს, -A, ან --auth-local და --auth-host-ის გამოყენებით." #. translator: This is a placeholder in a shell command. -#: initdb.c:3476 +#: initdb.c:3565 msgid "logfile" msgstr "ჟურნალის ფაილი" -#: initdb.c:3478 +#: initdb.c:3567 #, c-format msgid "" "\n" diff --git a/src/bin/initdb/po/ko.po b/src/bin/initdb/po/ko.po index 871c7ca7e6d9f..cc204fa046df1 100644 --- a/src/bin/initdb/po/ko.po +++ b/src/bin/initdb/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: initdb (PostgreSQL) 16\n" +"Project-Id-Version: initdb (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:50+0000\n" -"PO-Revision-Date: 2023-09-08 16:09+0900\n" +"POT-Creation-Date: 2025-01-17 04:51+0000\n" +"PO-Revision-Date: 2025-01-16 11:33+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -35,33 +35,48 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일임: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "\"%s\" 실행 파일을 찾을 수 없음" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 경로를 절대 경로로 바꿀 수 없음: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:750 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령에서 읽을 수 없음: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령이 아무 데이터도 반환하지 않음" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:372 initdb.c:408 #, c-format msgid "out of memory" msgstr "메모리 부족" @@ -77,35 +92,46 @@ msgstr "메모리 부족\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일 fsync 실패: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "\"%s\" 디렉터리 열 수 없음: %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "\"%s\" 파일 fsync 실패: %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" @@ -145,12 +171,12 @@ msgstr "제한된 토큰으로 재실행할 수 없음: 오류 코드 %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "\"%s\" 파일을 지울 수 없음: %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 지울 수 없음: %m" @@ -199,6 +225,31 @@ msgstr "하위 프로세스가 종료되었음, 시그널 %d: %s" msgid "child process exited with unrecognized status %d" msgstr "하위 프로세스가 종료되었음, 알수 없는 상태 %d" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값은 %s 옵션 값으로 쓸 수 없음" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 값은 %d..%d 범위여야 함" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령의 인자에 줄바꿈 문자가 포함되어 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + #: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" @@ -209,87 +260,106 @@ msgstr "\"%s\" 파일의 연결을 설정할 수 없음: %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "\"%s\" 파일의 정션을 구할 수 없음: %s\n" -#: initdb.c:618 initdb.c:1613 +# # search5 끝 +# # advance 부분 +#: initdb.c:369 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale() 실패" + +# # search5 끝 +# # advance 부분 +#: initdb.c:376 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale() 실패" + +#: initdb.c:390 +#, c-format +msgid "failed to restore old locale" +msgstr "옛 로케일을 복원할 수 없음" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "\"%s\" 옛 로케일을 복원할 수 없음" + +#: initdb.c:682 initdb.c:1674 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" -#: initdb.c:662 initdb.c:966 initdb.c:986 +#: initdb.c:726 initdb.c:1030 initdb.c:1050 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "\"%s\" 파일 열기 실패: %m" -#: initdb.c:666 initdb.c:969 initdb.c:988 +#: initdb.c:730 initdb.c:1033 initdb.c:1052 #, c-format msgid "could not write file \"%s\": %m" msgstr "\"%s\" 파일 쓰기 실패: %m" -#: initdb.c:670 +#: initdb.c:734 #, c-format msgid "could not close file \"%s\": %m" msgstr "\"%s\" 파일을 닫을 수 없음: %m" -#: initdb.c:686 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "\"%s\" 명령을 실행할 수 없음: %m" - -#: initdb.c:704 +#: initdb.c:768 #, c-format msgid "removing data directory \"%s\"" msgstr "\"%s\" 데이터 디렉터리를 지우는 중" -#: initdb.c:706 +#: initdb.c:770 #, c-format msgid "failed to remove data directory" msgstr "데이터 디렉터리를 지우는데 실패" -#: initdb.c:710 +#: initdb.c:774 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "\"%s\" 데이터 디렉터리 안의 내용을 지우는 중" -#: initdb.c:713 +#: initdb.c:777 #, c-format msgid "failed to remove contents of data directory" msgstr "데이터 디렉터리 내용을 지우는데 실패" -#: initdb.c:718 +#: initdb.c:782 #, c-format msgid "removing WAL directory \"%s\"" msgstr "\"%s\" WAL 디렉터리를 지우는 중" -#: initdb.c:720 +#: initdb.c:784 #, c-format msgid "failed to remove WAL directory" msgstr "WAL 디렉터리를 지우는데 실패" -#: initdb.c:724 +#: initdb.c:788 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "\"%s\" WAL 디렉터리 안의 내용을 지우는 중" -#: initdb.c:726 +#: initdb.c:790 #, c-format msgid "failed to remove contents of WAL directory" msgstr "WAL 디렉터리 내용을 지우는데 실패" -#: initdb.c:733 +#: initdb.c:797 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "\"%s\" 데이터 디렉터리가 사용자의 요청으로 삭제되지 않았음" -#: initdb.c:737 +#: initdb.c:801 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "\"%s\" WAL 디렉터리가 사용자의 요청으로 삭제되지 않았음" -#: initdb.c:755 +#: initdb.c:819 #, c-format msgid "cannot be run as root" msgstr "root 권한으로 실행할 수 없음" -#: initdb.c:756 +#: initdb.c:820 #, c-format msgid "" "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own " @@ -298,17 +368,17 @@ msgstr "" "시스템관리자 권한이 없는, 서버프로세스의 소유주가 될 일반 사용자로 로그인 해" "서(\"su\" 같은 명령 이용) 실행하십시오." -#: initdb.c:788 +#: initdb.c:852 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\" 인코딩은 서버 인코딩 이름을 사용할 수 없음" -#: initdb.c:932 +#: initdb.c:996 #, c-format msgid "file \"%s\" does not exist" msgstr "\"%s\" 파일 없음" -#: initdb.c:933 initdb.c:938 initdb.c:945 +#: initdb.c:997 initdb.c:1002 initdb.c:1009 #, c-format msgid "" "This might mean you have a corrupted installation or identified the wrong " @@ -317,131 +387,124 @@ msgstr "" "설치가 잘못되었거나 -L 호출 옵션으로 지정한 디렉터리가 잘못되었을 수 있습니" "다." -#: initdb.c:937 +#: initdb.c:1001 #, c-format msgid "could not access file \"%s\": %m" msgstr "\"%s\" 파일에 액세스할 수 없음: %m" -#: initdb.c:944 +#: initdb.c:1008 #, c-format msgid "file \"%s\" is not a regular file" msgstr "\"%s\" 파일은 일반 파일이 아님" -#: initdb.c:1077 +#: initdb.c:1141 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "사용할 동적 공유 메모리 관리방식을 선택하는 중 ... " -#: initdb.c:1086 +#: initdb.c:1150 #, c-format -msgid "selecting default max_connections ... " -msgstr "max_connections 초기값을 선택하는 중 ..." +msgid "selecting default \"max_connections\" ... " +msgstr "\"max_connections\" 초기값을 선택 중 ..." -#: initdb.c:1106 +#: initdb.c:1170 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "기본 shared_buffers를 선택하는 중... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "\"shared_buffers\" 초기값을 선택 중... " -#: initdb.c:1129 +#: initdb.c:1193 #, c-format msgid "selecting default time zone ... " msgstr "기본 지역 시간대를 선택 중 ... " -#: initdb.c:1206 +#: initdb.c:1272 msgid "creating configuration files ... " msgstr "환경설정 파일을 만드는 중 ..." -#: initdb.c:1367 initdb.c:1381 initdb.c:1448 initdb.c:1459 +#: initdb.c:1425 initdb.c:1439 initdb.c:1506 initdb.c:1517 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "\"%s\" 접근 권한을 바꿀 수 없음: %m" -#: initdb.c:1477 +#: initdb.c:1536 #, c-format msgid "running bootstrap script ... " msgstr "부트스트랩 스크립트 실행 중 ... " -#: initdb.c:1489 +#: initdb.c:1548 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "\"%s\" 입력 파일이 PostgreSQL %s 용이 아님" -#: initdb.c:1491 +#: initdb.c:1550 #, c-format msgid "Specify the correct path using the option -L." msgstr "-L 옵션으로 바른 경로를 지정하십시오." -#: initdb.c:1591 +#: initdb.c:1652 msgid "Enter new superuser password: " msgstr "새 superuser 암호를 입력하십시오:" -#: initdb.c:1592 +#: initdb.c:1653 msgid "Enter it again: " msgstr "암호 확인:" -#: initdb.c:1595 +#: initdb.c:1656 #, c-format msgid "Passwords didn't match.\n" msgstr "암호가 서로 틀립니다.\n" -#: initdb.c:1619 +#: initdb.c:1680 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "\"%s\" 파일에서 암호를 읽을 수 없음: %m" -#: initdb.c:1622 +#: initdb.c:1683 #, c-format msgid "password file \"%s\" is empty" msgstr "\"%s\" 패스워드 파일이 비어있음" -#: initdb.c:2034 +#: initdb.c:2095 #, c-format msgid "caught signal\n" msgstr "시스템의 간섭 신호(signal) 받았음\n" -#: initdb.c:2040 +#: initdb.c:2101 #, c-format msgid "could not write to child process: %s\n" msgstr "하위 프로세스에 쓸 수 없음: %s\n" -#: initdb.c:2048 +#: initdb.c:2109 #, c-format msgid "ok\n" msgstr "완료\n" -# # search5 끝 -# # advance 부분 -#: initdb.c:2137 +#: initdb.c:2191 initdb.c:2237 #, c-format -msgid "setlocale() failed" -msgstr "setlocale() 실패" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "\"%s\" 로케일 이름에 ASCII 문자가 아닌 것이 있음" -#: initdb.c:2155 -#, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "\"%s\" 옛 로케일을 복원할 수 없음" - -#: initdb.c:2163 +#: initdb.c:2217 #, c-format msgid "invalid locale name \"%s\"" msgstr "\"%s\" 로케일 이름이 잘못됨" -#: initdb.c:2164 +#: initdb.c:2218 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "ICU 로케일 이름을 사용하려면, --icu-locale 옵션을 사용하세요." -#: initdb.c:2177 +#: initdb.c:2231 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "잘못된 로케일 설정; LANG 또는 LC_* OS 환경 변수를 확인하세요" -#: initdb.c:2203 initdb.c:2227 +#: initdb.c:2262 initdb.c:2286 #, c-format msgid "encoding mismatch" msgstr "인코딩 불일치" -#: initdb.c:2204 +#: initdb.c:2263 #, c-format msgid "" "The encoding you selected (%s) and the encoding that the selected locale " @@ -451,7 +514,7 @@ msgstr "" "선택한 인코딩(%s)과 선택한 로케일에서 사용하는 인코딩(%s)이 일치하지 않습니" "다. 이로 인해 여러 문자열 처리 함수에 오작동이 발생할 수 있습니다." -#: initdb.c:2209 initdb.c:2230 +#: initdb.c:2268 initdb.c:2289 #, c-format msgid "" "Rerun %s and either do not specify an encoding explicitly, or choose a " @@ -460,42 +523,47 @@ msgstr "" "암묵적으로 지정된 인코딩이 마음에 들지 않으면 지정할 수 있는 인코딩을 지정해" "서 %s 작업을 다시 하세요." -#: initdb.c:2228 +#: initdb.c:2287 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "지정한 %s 인코딩을 ICU 제공자가 지원하지 않습니다." -#: initdb.c:2279 +#: initdb.c:2338 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "\"%s\" 로케일 이름을 로케일 태그로 바꿀 수 없음: %s" -#: initdb.c:2285 initdb.c:2337 initdb.c:2416 +#: initdb.c:2344 initdb.c:2396 initdb.c:2488 #, c-format msgid "ICU is not supported in this build" msgstr "ICU 지원 기능을 뺀 채로 서버가 만들어졌습니다." -#: initdb.c:2308 +#: initdb.c:2367 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "\"%s\" 로케일에서 언어를 찾을 수 없음: %s" -#: initdb.c:2334 +#: initdb.c:2393 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "\"%s\" 로케일은 \"%s\" 라는 알 수 없는 언어를 사용함" -#: initdb.c:2400 +#: initdb.c:2454 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "제공자가 %s 인경우 로케일을 지정해야 함" + +#: initdb.c:2465 #, c-format -msgid "ICU locale must be specified" -msgstr "ICU 로케일을 지정해야합니다." +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "내장 제공자용 \"%s\" 로케일 이름이 잘못됨" -#: initdb.c:2404 +#: initdb.c:2476 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "\"%s\" 로케일 태그를 사용함, 해당 ICU 로케일: \"%s\"\n" -#: initdb.c:2427 +#: initdb.c:2499 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -504,17 +572,17 @@ msgstr "" "%s PostgreSQL 데이터베이스 클러스터를 초기화 하는 프로그램.\n" "\n" -#: initdb.c:2428 +#: initdb.c:2500 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: initdb.c:2429 +#: initdb.c:2501 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [옵션]... [DATADIR]\n" -#: initdb.c:2430 +#: initdb.c:2502 #, c-format msgid "" "\n" @@ -523,50 +591,50 @@ msgstr "" "\n" "옵션들:\n" -#: initdb.c:2431 +#: initdb.c:2503 #, c-format msgid "" " -A, --auth=METHOD default authentication method for local " "connections\n" msgstr " -A, --auth=METHOD 로컬 연결의 기본 인증 방법\n" -#: initdb.c:2432 +#: initdb.c:2504 #, c-format msgid "" " --auth-host=METHOD default authentication method for local TCP/IP " "connections\n" msgstr " --auth-host=METHOD local TCP/IP 연결에 대한 기본 인증 방법\n" -#: initdb.c:2433 +#: initdb.c:2505 #, c-format msgid "" " --auth-local=METHOD default authentication method for local-socket " "connections\n" msgstr " --auth-local=METHOD local-socket 연결에 대한 기본 인증 방법\n" -#: initdb.c:2434 +#: initdb.c:2506 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATADIR 새 데이터베이스 클러스터를 만들 디렉터리\n" -#: initdb.c:2435 +#: initdb.c:2507 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=ENCODING 새 데이터베이스의 기본 인코딩\n" -#: initdb.c:2436 +#: initdb.c:2508 #, c-format msgid "" " -g, --allow-group-access allow group read/execute on data directory\n" msgstr "" " -g, --allow-group-access 데이터 디렉터리를 그룹이 읽고 접근할 있게 함\n" -#: initdb.c:2437 +#: initdb.c:2509 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOCALE 새 데이터베이스의 ICU 로케일 ID 지정\n" -#: initdb.c:2438 +#: initdb.c:2510 #, c-format msgid "" " --icu-rules=RULES set additional ICU collation rules for new " @@ -575,17 +643,17 @@ msgstr "" " --icu-rules=RULES 새 데이터베이스의 추가 ICU 문자열 정렬 규칙을 지" "정\n" -#: initdb.c:2439 +#: initdb.c:2511 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums 자료 페이지 체크섬 사용\n" -#: initdb.c:2440 +#: initdb.c:2512 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=LOCALE 새 데이터베이스의 기본 로케일 설정\n" -#: initdb.c:2441 +#: initdb.c:2513 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -599,27 +667,36 @@ msgstr "" " 새 데이터베이스의 각 범주에 기본 로케일 설정\n" " (환경에서 가져온 기본 값)\n" -#: initdb.c:2445 +#: initdb.c:2517 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale -locale=C와 같음\n" -#: initdb.c:2446 +#: initdb.c:2518 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" --builtin-locale=LOCALE\n" +" 새 데이터베이스용 내장 로케일 이름 지정\n" + +#: initdb.c:2520 +#, c-format +msgid "" +" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " 새 데이터베이스의 로케일 제공자 지정\n" -#: initdb.c:2448 +#: initdb.c:2522 #, c-format msgid "" " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=FILE 파일에서 새 superuser의 암호 읽기\n" -#: initdb.c:2449 +#: initdb.c:2523 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -628,29 +705,29 @@ msgstr "" " -T, --text-search-config=CFG\n" " 기본 텍스트 검색 구성\n" -#: initdb.c:2451 +#: initdb.c:2525 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NAME 데이터베이스 superuser 이름\n" -#: initdb.c:2452 +#: initdb.c:2526 #, c-format msgid "" " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt 새 superuser 암호를 입력 받음\n" -#: initdb.c:2453 +#: initdb.c:2527 #, c-format msgid "" " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR 트랜잭션 로그 디렉터리 위치\n" -#: initdb.c:2454 +#: initdb.c:2528 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE WAL 조각 파일 크기, MB단위\n" -#: initdb.c:2455 +#: initdb.c:2529 #, c-format msgid "" "\n" @@ -659,33 +736,33 @@ msgstr "" "\n" "덜 일반적으로 사용되는 옵션들:\n" -#: initdb.c:2456 +#: initdb.c:2530 #, c-format msgid "" " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAME=VALUE 서버 매개 변수 기본 설정을 바꿈\n" -#: initdb.c:2457 +#: initdb.c:2531 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug 디버깅에 필요한 정보들도 함께 출력함\n" -#: initdb.c:2458 +#: initdb.c:2532 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches debug_discard_caches=1 지정\n" -#: initdb.c:2459 +#: initdb.c:2533 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L DIRECTORY 입력파일들이 있는 디렉터리\n" -#: initdb.c:2460 +#: initdb.c:2534 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean 오류가 발생되었을 경우 그대로 둠\n" -#: initdb.c:2461 +#: initdb.c:2535 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " @@ -693,23 +770,28 @@ msgid "" msgstr "" " -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않음\n" -#: initdb.c:2462 +#: initdb.c:2536 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions 다음 작업을 위해 구성 정보를 출력 안함\n" -#: initdb.c:2463 +#: initdb.c:2537 +#, c-format +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show 내부 설정값들을 보여주고 마침\n" + +#: initdb.c:2538 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show 내부 설정값들을 보여줌\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD 파일을 디스크에 동기화 하는 방법 지정\n" -#: initdb.c:2464 +#: initdb.c:2539 #, c-format msgid "" " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only 데이터 디렉터리만 동기화하고 마침\n" -#: initdb.c:2465 +#: initdb.c:2540 #, c-format msgid "" "\n" @@ -718,17 +800,17 @@ msgstr "" "\n" "기타 옵션:\n" -#: initdb.c:2466 +#: initdb.c:2541 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: initdb.c:2467 +#: initdb.c:2542 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: initdb.c:2468 +#: initdb.c:2543 #, c-format msgid "" "\n" @@ -738,7 +820,7 @@ msgstr "" "\n" "데이터 디렉터리를 지정하지 않으면, PGDATA 환경 변수값을 사용합니다.\n" -#: initdb.c:2470 +#: initdb.c:2545 #, c-format msgid "" "\n" @@ -747,28 +829,28 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: initdb.c:2471 +#: initdb.c:2546 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: initdb.c:2499 +#: initdb.c:2570 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "\"%s\" 인증 방법은 \"%s\" 연결에서는 사용할 수 없음" -#: initdb.c:2513 +#: initdb.c:2584 #, c-format msgid "" "must specify a password for the superuser to enable password authentication" msgstr "비밀번호 인증방식을 사용하려면, 반드시 superuser의 암호를 지정해야함" -#: initdb.c:2532 +#: initdb.c:2603 #, c-format msgid "no data directory specified" msgstr "데이터 디렉터리를 지정하지 않았음" -#: initdb.c:2533 +#: initdb.c:2604 #, c-format msgid "" "You must identify the directory where the data for this database system will " @@ -778,12 +860,12 @@ msgstr "" "이 작업을 진행하려면, 반드시 이 데이터 디렉터리를 지정해 주어야합니다. 지정하" "는 방법은 -D 옵션의 값이나, PGDATA 환경 변수값으로 지정해 주면 됩니 다." -#: initdb.c:2550 +#: initdb.c:2621 #, c-format msgid "could not set environment" msgstr "환경 변수를 지정할 수 없음" -#: initdb.c:2568 +#: initdb.c:2639 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " @@ -792,40 +874,40 @@ msgstr "" "\"%s\" 프로그램이 %s 작업에서 필요합니다. 그런데, 이 파일이 \"%s\" 파일이 있" "는 디렉터리안에 없습니다." -#: initdb.c:2571 +#: initdb.c:2642 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "\"%s\" 프로그램을 \"%s\" 작업 때문에 찾았지만 이 파일은 %s 프로그램의 버전과 " "다릅니다." -#: initdb.c:2586 +#: initdb.c:2657 #, c-format msgid "input file location must be an absolute path" msgstr "입력 파일 위치는 반드시 절대경로여야함" -#: initdb.c:2603 +#: initdb.c:2674 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "데이터베이스 클러스터는 \"%s\" 로케일으로 초기화될 것입니다.\n" -#: initdb.c:2606 +#: initdb.c:2677 #, c-format msgid "" "The database cluster will be initialized with this locale configuration:\n" msgstr "데이터베이스 클러스터는 아래 로케일 환경으로 초기화될 것입니다:\n" -#: initdb.c:2607 +#: initdb.c:2678 #, c-format -msgid " provider: %s\n" -msgstr " 제공자: %s\n" +msgid " locale provider: %s\n" +msgstr " 로케일 제공자: %s\n" -#: initdb.c:2609 +#: initdb.c:2680 #, c-format -msgid " ICU locale: %s\n" -msgstr " ICU 로케일: %s\n" +msgid " default collation: %s\n" +msgstr " 기본 문자정렬: %s\n" -#: initdb.c:2610 +#: initdb.c:2681 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -842,22 +924,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2640 +#: initdb.c:2711 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "\"%s\" 로케일에 알맞은 인코딩을 찾을 수 없음" -#: initdb.c:2642 +#: initdb.c:2713 #, c-format msgid "Rerun %s with the -E option." msgstr "-E 옵션 지정해서 %s 작업을 다시 하세요." -#: initdb.c:2643 initdb.c:3176 initdb.c:3284 initdb.c:3304 +#: initdb.c:2714 initdb.c:3257 initdb.c:3377 initdb.c:3397 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: initdb.c:2655 +#: initdb.c:2726 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -866,73 +948,78 @@ msgstr "" "\"%s\" 인코딩을 서버측 인코딩으로 사용할 수 없습니다.\n" "기본 데이터베이스는 \"%s\" 인코딩으로 지정됩니다.\n" -#: initdb.c:2660 +#: initdb.c:2731 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "\"%s\" 로케일은 지원하지 않는 \"%s\" 인코딩을 필요로 함" -#: initdb.c:2662 +#: initdb.c:2733 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "\"%s\" 인코딩을 서버측 인코딩으로 사용할 수 없습니다." -#: initdb.c:2664 +#: initdb.c:2735 #, c-format msgid "Rerun %s with a different locale selection." msgstr "다른 로케일을 지정해서 %s 작업을 다시 하세요." -#: initdb.c:2672 +#: initdb.c:2743 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "기본 데이터베이스 인코딩은 \"%s\" 인코딩으로 설정되었습니다.\n" -#: initdb.c:2741 +#: initdb.c:2757 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "\"%s\" 내장 제공자 로케일은 \"%s\" 인코딩을 필요로 함" + +#: initdb.c:2819 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "\"%s\" 로케일에 알맞은 전문검색 설정을 찾을 수 없음" -#: initdb.c:2752 +#: initdb.c:2830 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "\"%s\" 로케일에 알맞은 전문검색 설정을 알 수 없음" -#: initdb.c:2757 +#: initdb.c:2835 #, c-format msgid "" "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "지정한 \"%s\" 전문검색 설정은 \"%s\" 로케일과 일치하지 않음" -#: initdb.c:2762 +#: initdb.c:2840 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "기본 텍스트 검색 구성이 \"%s\"(으)로 설정됩니다.\n" -#: initdb.c:2805 initdb.c:2876 +#: initdb.c:2883 initdb.c:2954 #, c-format msgid "creating directory %s ... " msgstr "%s 디렉터리 만드는 중 ..." -#: initdb.c:2810 initdb.c:2881 initdb.c:2929 initdb.c:2985 +#: initdb.c:2888 initdb.c:2959 initdb.c:3007 initdb.c:3064 #, c-format msgid "could not create directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" -#: initdb.c:2819 initdb.c:2891 +#: initdb.c:2897 initdb.c:2969 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "이미 있는 %s 디렉터리의 액세스 권한을 고치는 중 ..." -#: initdb.c:2824 initdb.c:2896 +#: initdb.c:2902 initdb.c:2974 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "\"%s\" 디렉터리의 액세스 권한을 바꿀 수 없습니다: %m" -#: initdb.c:2836 initdb.c:2908 +#: initdb.c:2914 initdb.c:2986 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "\"%s\" 디렉터리가 있지만 비어 있지 않음" -#: initdb.c:2840 +#: initdb.c:2918 #, c-format msgid "" "If you want to create a new database system, either remove or empty the " @@ -941,31 +1028,31 @@ msgstr "" "새로운 데이터베이스 시스템을 만들려면 \"%s\" 디렉터리를 제거하거나 비우십시" "오. 또는 %s 작업을 \"%s\" 디렉터리가 아닌 것으로 지정해서 하세요." -#: initdb.c:2848 initdb.c:2918 initdb.c:3325 +#: initdb.c:2926 initdb.c:2996 initdb.c:3422 #, c-format msgid "could not access directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" -#: initdb.c:2869 +#: initdb.c:2947 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL 디렉터리 위치는 절대 경로여야 함" -#: initdb.c:2912 +#: initdb.c:2990 #, c-format msgid "" -"If you want to store the WAL there, either remove or empty the directory \"%s" -"\"." +"If you want to store the WAL there, either remove or empty the directory " +"\"%s\"." msgstr "" "트랜잭션 로그를 해당 위치에 저장하려면 \"%s\" 디렉터리를 제거하거나 비우십시" "오." -#: initdb.c:2922 +#: initdb.c:3000 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "\"%s\" 심벌릭 링크를 만들 수 없음: %m" -#: initdb.c:2941 +#: initdb.c:3019 #, c-format msgid "" "It contains a dot-prefixed/invisible file, perhaps due to it being a mount " @@ -974,13 +1061,13 @@ msgstr "" "점(.)으로 시작하는 숨은 파일이 포함되어 있습니다. 마운트 최상위 디렉터리 같습" "니다." -#: initdb.c:2943 +#: initdb.c:3021 #, c-format msgid "" "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "lost-found 디렉터리가 있습니다. 마운트 최상위 디렉터리 같습니다." -#: initdb.c:2945 +#: initdb.c:3023 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -989,66 +1076,61 @@ msgstr "" "마운트 최상위 디렉터리를 데이터 디렉터리로 사용하는 것은 권장하지 않습니다.\n" "하위 디렉터리를 만들어서 그것을 데이터 디렉터리로 사용하세요." -#: initdb.c:2971 +#: initdb.c:3050 #, c-format msgid "creating subdirectories ... " msgstr "하위 디렉터리 만드는 중 ..." -#: initdb.c:3014 +#: initdb.c:3093 msgid "performing post-bootstrap initialization ... " msgstr "부트스트랩 다음 초기화 작업 중 ... " -#: initdb.c:3175 +#: initdb.c:3256 #, c-format msgid "-c %s requires a value" msgstr "-c %s 설정은 값을 필요로 합니다." -#: initdb.c:3200 +#: initdb.c:3281 #, c-format msgid "Running in debug mode.\n" msgstr "디버그 모드로 실행 중.\n" -#: initdb.c:3204 +#: initdb.c:3285 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "지저분 모드로 실행 중. 오류가 발생되어도 뒷정리를 안합니다.\n" -#: initdb.c:3274 +#: initdb.c:3358 #, c-format msgid "unrecognized locale provider: %s" msgstr "알 수 없는 로케일 제공자 이름: %s" -#: initdb.c:3302 +#: initdb.c:3395 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인자를 지정했습니다. (처음 \"%s\")" -#: initdb.c:3309 initdb.c:3313 +#: initdb.c:3402 initdb.c:3406 initdb.c:3410 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s 옵션은 \"%s\" 로케일 제공자를 사용할 때만 사용할 수 있습니다." -#: initdb.c:3327 initdb.c:3404 +#: initdb.c:3424 initdb.c:3487 msgid "syncing data to disk ... " msgstr "자료를 디스크에 동기화 하는 중 ... " -#: initdb.c:3335 +#: initdb.c:3432 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "" "암호를 입력받는 옵션과 암호를 파일에서 가져오는 옵션은 동시에 사용될 수 없음" -#: initdb.c:3357 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "--wal-segsize 옵션 값은 숫자여야 함" - -#: initdb.c:3359 +#: initdb.c:3443 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "--wal-segsize 옵션값은 1에서 1024사이 2^n 값이여야 함" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "%s 옵션값은 1에서 1024사이 2^n 값이여야 함" -#: initdb.c:3373 +#: initdb.c:3456 #, c-format msgid "" "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" @@ -1056,7 +1138,7 @@ msgstr "" "\"%s\" 사용자는 슈퍼유저 이름으로 쓸 수 없습니다. \"pg_\"로 시작하는롤 이름" "은 허용하지 않음" -#: initdb.c:3375 +#: initdb.c:3458 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1067,17 +1149,17 @@ msgstr "" "지정될 것입니다. 또한 이 사용자는 서버 프로세스의 소유주가 됩니다.\n" "\n" -#: initdb.c:3391 +#: initdb.c:3474 #, c-format msgid "Data page checksums are enabled.\n" msgstr "자료 페이지 체크섬 기능 사용함.\n" -#: initdb.c:3393 +#: initdb.c:3476 #, c-format msgid "Data page checksums are disabled.\n" msgstr "자료 페이지 체크섬 기능 사용 하지 않음\n" -#: initdb.c:3410 +#: initdb.c:3493 #, c-format msgid "" "\n" @@ -1089,12 +1171,12 @@ msgstr "" "이 상태에서 OS가 갑자기 중지 되면 데이터 디렉토리 안에 있는 자료가 깨질 수 있" "습니다.\n" -#: initdb.c:3415 +#: initdb.c:3498 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "로컬 접속용 \"trust\" 인증을 설정 함" -#: initdb.c:3416 +#: initdb.c:3499 #, c-format msgid "" "You can change this by editing pg_hba.conf or using the option -A, or --auth-" @@ -1105,11 +1187,11 @@ msgstr "" "요." #. translator: This is a placeholder in a shell command. -#: initdb.c:3446 +#: initdb.c:3529 msgid "logfile" msgstr "로그파일" -#: initdb.c:3448 +#: initdb.c:3531 #, c-format msgid "" "\n" @@ -1125,13 +1207,21 @@ msgstr "" "\n" #, c-format -#~ msgid "Using default ICU locale \"%s\".\n" -#~ msgstr "기본 ICU 로케일로 \"%s\" 사용함.\n" +#~ msgid " ICU locale: %s\n" +#~ msgstr " ICU 로케일: %s\n" #, c-format -#~ msgid "could not open collator for default locale: %s" -#~ msgstr "기본 로케일용 문자열 정렬 규칙을 열 수 없음: %s" +#~ msgid "argument of --wal-segsize must be a number" +#~ msgstr "--wal-segsize 옵션 값은 숫자여야 함" + +#, c-format +#~ msgid "Using default ICU locale \"%s\".\n" +#~ msgstr "기본 ICU 로케일로 \"%s\" 사용함.\n" #, c-format #~ msgid "could not determine default ICU locale" #~ msgstr "기본 ICU 로케일을 결정할 수 없음" + +#, c-format +#~ msgid "could not open collator for default locale: %s" +#~ msgstr "기본 로케일용 문자열 정렬 규칙을 열 수 없음: %s" diff --git a/src/bin/initdb/po/meson.build b/src/bin/initdb/po/meson.build index 23d43d64baf1e..0eeeaca8cc1eb 100644 --- a/src/bin/initdb/po/meson.build +++ b/src/bin/initdb/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('initdb-' + pg_version_major.to_string())] diff --git a/src/bin/initdb/po/pt_BR.po b/src/bin/initdb/po/pt_BR.po index fd7d406b73e30..8911b29572209 100644 --- a/src/bin/initdb/po/pt_BR.po +++ b/src/bin/initdb/po/pt_BR.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: PostgreSQL 16\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2024-01-02 12:54-0300\n" -"PO-Revision-Date: 2010-09-25 00:45-0300\n" +"PO-Revision-Date: 2024-07-02 00:07+0200\n" "Last-Translator: Euler Taveira \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" @@ -535,17 +535,17 @@ msgstr " -E, --encoding=CODIFICAÇÃO ajusta a codificação padrão para nov #: initdb.c:2436 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" -msgstr " -g, --allow-group-access permite leitura/execução do grupo no diretório de dados\n" +msgstr " -g, --allow-group-access permite leitura/execução do grupo no diretório de dados\n" #: initdb.c:2437 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" -msgstr " --icu-locale=LOCALE ajusta ID de configuração regional ICU para novos bancos de dados\n" +msgstr " --icu-locale=LOCALE ajusta ID de configuração regional ICU para novos bancos de dados\n" #: initdb.c:2438 #, fuzzy, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" -msgstr " --icu-rules=REGRAS ajusta regras adicionais de agregação ICU para novos bancos de dados\n" +msgstr " --icu-rules=REGRAS ajusta regras adicionais de agregação ICU para novos bancos de dados\n" #: initdb.c:2439 #, c-format @@ -582,7 +582,7 @@ msgid "" " set default locale provider for new databases\n" msgstr "" " --locale-provider={libc|icu}\n" -" ajusta provedor de configuração regional padrão para novos bancos de dados\n" +" ajusta provedor de configuração regional padrão para novos bancos de dados\n" #: initdb.c:2448 #, c-format @@ -611,12 +611,12 @@ msgstr " -W, --pwprompt pergunta senha do novo super-usuário\n" #: initdb.c:2453 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" -msgstr " -X, --waldir=DIRWAL local do diretório do log de transação\n" +msgstr " -X, --waldir=DIRWAL local do diretório do log de transação\n" #: initdb.c:2454 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" -msgstr " --wal-segsize=TAMANHO tamanho dos segmentos do WAL, em megabytes\n" +msgstr " --wal-segsize=TAMANHO tamanho dos segmentos do WAL, em megabytes\n" #: initdb.c:2455 #, c-format @@ -630,7 +630,7 @@ msgstr "" #: initdb.c:2456 #, fuzzy, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" -msgstr " -c, --set NOME=VALOR sobrescreve o valor padrão para parâmetro do servidor\n" +msgstr " -c, --set NOME=VALOR sobrescreve o valor padrão para parâmetro do servidor\n" #: initdb.c:2457 #, c-format @@ -660,7 +660,7 @@ msgstr " -N, --no-sync não espera mudanças serem escritas com #: initdb.c:2462 #, c-format msgid " --no-instructions do not print instructions for next steps\n" -msgstr " --no-instructions não mostra instruções para próximos passos\n" +msgstr " --no-instructions não mostra instruções para próximos passos\n" #: initdb.c:2463 #, c-format diff --git a/src/bin/initdb/po/ru.po b/src/bin/initdb/po/ru.po index f601e6220f033..c1fab13b8c488 100644 --- a/src/bin/initdb/po/ru.po +++ b/src/bin/initdb/po/ru.po @@ -6,13 +6,13 @@ # Sergey Burladyan , 2009. # Andrey Sudnik , 2010. # Dmitriy Olshevskiy , 2014. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: initdb (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2023-09-11 16:13+0300\n" +"POT-Creation-Date: 2024-11-02 08:21+0300\n" +"PO-Revision-Date: 2024-11-02 08:27+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -42,33 +42,48 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:750 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:372 initdb.c:408 #, c-format msgid "out of memory" msgstr "нехватка памяти" @@ -84,35 +99,46 @@ msgstr "нехватка памяти\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не удалось получить информацию о файле \"%s\": %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не удалось открыть каталог \"%s\": %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не удалось прочитать каталог \"%s\": %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" @@ -152,12 +178,12 @@ msgstr "не удалось перезапуститься с ограничен msgid "could not get exit code from subprocess: error code %lu" msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не удалось стереть файл \"%s\": %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "ошибка при удалении каталога \"%s\": %m" @@ -204,7 +230,35 @@ msgstr "дочерний процесс завершён по сигналу %d: #: ../../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" -msgstr "дочерний процесс завершился с нераспознанным состоянием %d" +msgstr "дочерний процесс завершился с нераспознанным кодом состояния %d" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неверное значение \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "значение %s должно быть в диапазоне %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" #: ../../port/dirmod.c:287 #, c-format @@ -216,87 +270,102 @@ msgstr "не удалось создать связь для каталога \" msgid "could not get junction for \"%s\": %s\n" msgstr "не удалось получить связь для каталога \"%s\": %s\n" -#: initdb.c:623 initdb.c:1610 +#: initdb.c:369 +#, c-format +msgid "_wsetlocale() failed" +msgstr "ошибка в _wsetlocale()" + +#: initdb.c:376 +#, c-format +msgid "setlocale() failed" +msgstr "ошибка в setlocale()" + +#: initdb.c:390 +#, c-format +msgid "failed to restore old locale" +msgstr "не удалось восстановить старую локаль" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "не удалось восстановить старую локаль \"%s\"" + +#: initdb.c:682 initdb.c:1674 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не удалось открыть файл \"%s\" для чтения: %m" -#: initdb.c:667 initdb.c:971 initdb.c:991 +#: initdb.c:726 initdb.c:1030 initdb.c:1050 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "не удалось открыть файл \"%s\" для записи: %m" -#: initdb.c:671 initdb.c:974 initdb.c:993 +#: initdb.c:730 initdb.c:1033 initdb.c:1052 #, c-format msgid "could not write file \"%s\": %m" msgstr "не удалось записать файл \"%s\": %m" -#: initdb.c:675 +#: initdb.c:734 #, c-format msgid "could not close file \"%s\": %m" msgstr "не удалось закрыть файл \"%s\": %m" -#: initdb.c:691 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не удалось выполнить команду \"%s\": %m" - -#: initdb.c:709 +#: initdb.c:768 #, c-format msgid "removing data directory \"%s\"" msgstr "удаление каталога данных \"%s\"" -#: initdb.c:711 +#: initdb.c:770 #, c-format msgid "failed to remove data directory" msgstr "ошибка при удалении каталога данных" -#: initdb.c:715 +#: initdb.c:774 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "удаление содержимого каталога данных \"%s\"" -#: initdb.c:718 +#: initdb.c:777 #, c-format msgid "failed to remove contents of data directory" msgstr "ошибка при удалении содержимого каталога данных" -#: initdb.c:723 +#: initdb.c:782 #, c-format msgid "removing WAL directory \"%s\"" msgstr "удаление каталога WAL \"%s\"" -#: initdb.c:725 +#: initdb.c:784 #, c-format msgid "failed to remove WAL directory" msgstr "ошибка при удалении каталога WAL" -#: initdb.c:729 +#: initdb.c:788 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "удаление содержимого каталога WAL \"%s\"" -#: initdb.c:731 +#: initdb.c:790 #, c-format msgid "failed to remove contents of WAL directory" msgstr "ошибка при удалении содержимого каталога WAL" -#: initdb.c:738 +#: initdb.c:797 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "каталог данных \"%s\" не был удалён по запросу пользователя" -#: initdb.c:742 +#: initdb.c:801 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "каталог WAL \"%s\" не был удалён по запросу пользователя" -#: initdb.c:760 +#: initdb.c:819 #, c-format msgid "cannot be run as root" msgstr "программу не должен запускать root" -#: initdb.c:761 +#: initdb.c:820 #, c-format msgid "" "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own " @@ -305,17 +374,17 @@ msgstr "" "Пожалуйста, переключитесь на обычного пользователя (например, используя " "\"su\"), которому будет принадлежать серверный процесс." -#: initdb.c:793 +#: initdb.c:852 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\" — некорректное имя серверной кодировки" -#: initdb.c:937 +#: initdb.c:996 #, c-format msgid "file \"%s\" does not exist" msgstr "файл \"%s\" не существует" -#: initdb.c:938 initdb.c:943 initdb.c:950 +#: initdb.c:997 initdb.c:1002 initdb.c:1009 #, c-format msgid "" "This might mean you have a corrupted installation or identified the wrong " @@ -324,129 +393,124 @@ msgstr "" "Это означает, что ваша установка PostgreSQL испорчена или в параметре -L " "задан неправильный каталог." -#: initdb.c:942 +#: initdb.c:1001 #, c-format msgid "could not access file \"%s\": %m" -msgstr "нет доступа к файлу \"%s\": %m" +msgstr "ошибка при обращении к файлу \"%s\": %m" -#: initdb.c:949 +#: initdb.c:1008 #, c-format msgid "file \"%s\" is not a regular file" msgstr "\"%s\" — не обычный файл" -#: initdb.c:1082 +#: initdb.c:1141 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "выбирается реализация динамической разделяемой памяти... " -#: initdb.c:1091 +#: initdb.c:1150 #, c-format -msgid "selecting default max_connections ... " -msgstr "выбирается значение max_connections по умолчанию... " +msgid "selecting default \"max_connections\" ... " +msgstr "выбирается значение \"max_connections\" по умолчанию... " -#: initdb.c:1111 +#: initdb.c:1170 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "выбирается значение shared_buffers по умолчанию... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "выбирается значение \"shared_buffers\" по умолчанию... " -#: initdb.c:1134 +#: initdb.c:1193 #, c-format msgid "selecting default time zone ... " msgstr "выбирается часовой пояс по умолчанию... " -#: initdb.c:1211 +#: initdb.c:1272 msgid "creating configuration files ... " msgstr "создание конфигурационных файлов... " -#: initdb.c:1364 initdb.c:1378 initdb.c:1445 initdb.c:1456 +#: initdb.c:1425 initdb.c:1439 initdb.c:1506 initdb.c:1517 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "не удалось поменять права для \"%s\": %m" -#: initdb.c:1474 +#: initdb.c:1536 #, c-format msgid "running bootstrap script ... " msgstr "выполняется подготовительный скрипт... " -#: initdb.c:1486 +#: initdb.c:1548 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "входной файл \"%s\" не принадлежит PostgreSQL %s" -#: initdb.c:1488 +#: initdb.c:1550 #, c-format msgid "Specify the correct path using the option -L." msgstr "Укажите корректный путь в параметре -L." -#: initdb.c:1588 +#: initdb.c:1652 msgid "Enter new superuser password: " msgstr "Введите новый пароль суперпользователя: " -#: initdb.c:1589 +#: initdb.c:1653 msgid "Enter it again: " msgstr "Повторите его: " -#: initdb.c:1592 +#: initdb.c:1656 #, c-format msgid "Passwords didn't match.\n" msgstr "Пароли не совпадают.\n" -#: initdb.c:1616 +#: initdb.c:1680 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "не удалось прочитать пароль из файла \"%s\": %m" -#: initdb.c:1619 +#: initdb.c:1683 #, c-format msgid "password file \"%s\" is empty" msgstr "файл пароля \"%s\" пуст" -#: initdb.c:2031 +#: initdb.c:2095 #, c-format msgid "caught signal\n" msgstr "получен сигнал\n" -#: initdb.c:2037 +#: initdb.c:2101 #, c-format msgid "could not write to child process: %s\n" msgstr "не удалось записать в поток дочернего процесса: %s\n" -#: initdb.c:2045 +#: initdb.c:2109 #, c-format msgid "ok\n" msgstr "ок\n" -#: initdb.c:2134 -#, c-format -msgid "setlocale() failed" -msgstr "ошибка в setlocale()" - -#: initdb.c:2152 +#: initdb.c:2191 initdb.c:2237 #, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "не удалось восстановить старую локаль \"%s\"" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "имя локали \"%s\" содержит не-ASCII символы" -#: initdb.c:2160 +#: initdb.c:2217 #, c-format msgid "invalid locale name \"%s\"" msgstr "ошибочное имя локали \"%s\"" -#: initdb.c:2161 +#: initdb.c:2218 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "Если эта локаль свойственна ICU, укажите --icu-locale." -#: initdb.c:2174 +#: initdb.c:2231 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "неверные установки локали; проверьте переменные окружения LANG и LC_*" -#: initdb.c:2200 initdb.c:2224 +#: initdb.c:2262 initdb.c:2286 #, c-format msgid "encoding mismatch" msgstr "несоответствие кодировки" -#: initdb.c:2201 +#: initdb.c:2263 #, c-format msgid "" "The encoding you selected (%s) and the encoding that the selected locale " @@ -457,7 +521,7 @@ msgstr "" "может привести к неправильной работе различных функций обработки текстовых " "строк." -#: initdb.c:2206 initdb.c:2227 +#: initdb.c:2268 initdb.c:2289 #, c-format msgid "" "Rerun %s and either do not specify an encoding explicitly, or choose a " @@ -466,42 +530,47 @@ msgstr "" "Для исправления перезапустите %s, не указывая кодировку явно, либо выберите " "подходящее сочетание параметров локализации." -#: initdb.c:2225 +#: initdb.c:2287 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "Выбранная вами кодировка (%s) не поддерживается провайдером ICU." -#: initdb.c:2276 +#: initdb.c:2338 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "не удалось получить из названия локали \"%s\" метку языка: %s" -#: initdb.c:2282 initdb.c:2334 initdb.c:2413 +#: initdb.c:2344 initdb.c:2396 initdb.c:2488 #, c-format msgid "ICU is not supported in this build" msgstr "ICU не поддерживается в данной сборке" -#: initdb.c:2305 +#: initdb.c:2367 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "не удалось определить язык для локали \"%s\": %s" -#: initdb.c:2331 +#: initdb.c:2393 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "для локали \"%s\" получен неизвестный язык \"%s\"" -#: initdb.c:2397 +#: initdb.c:2454 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "если выбран провайдер %s, необходимо задать локаль" + +#: initdb.c:2465 #, c-format -msgid "ICU locale must be specified" -msgstr "необходимо задать локаль ICU" +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "неверное имя локали \"%s\" для встроенного провайдера" -#: initdb.c:2401 +#: initdb.c:2476 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "Для локали ICU \"%s\" используется метка языка \"%s\".\n" -#: initdb.c:2424 +#: initdb.c:2499 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -510,17 +579,17 @@ msgstr "" "%s инициализирует кластер PostgreSQL.\n" "\n" -#: initdb.c:2425 +#: initdb.c:2500 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: initdb.c:2426 +#: initdb.c:2501 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [ПАРАМЕТР]... [КАТАЛОГ]\n" -#: initdb.c:2427 +#: initdb.c:2502 #, c-format msgid "" "\n" @@ -529,7 +598,7 @@ msgstr "" "\n" "Параметры:\n" -#: initdb.c:2428 +#: initdb.c:2503 #, c-format msgid "" " -A, --auth=METHOD default authentication method for local " @@ -538,7 +607,7 @@ msgstr "" " -A, --auth=МЕТОД метод проверки подлинности по умолчанию\n" " для локальных подключений\n" -#: initdb.c:2429 +#: initdb.c:2504 #, c-format msgid "" " --auth-host=METHOD default authentication method for local TCP/IP " @@ -547,7 +616,7 @@ msgstr "" " --auth-host=МЕТОД метод проверки подлинности по умолчанию\n" " для локальных TCP/IP-подключений\n" -#: initdb.c:2430 +#: initdb.c:2505 #, c-format msgid "" " --auth-local=METHOD default authentication method for local-socket " @@ -556,17 +625,17 @@ msgstr "" " --auth-local=МЕТОД метод проверки подлинности по умолчанию\n" " для локальных подключений через сокет\n" -#: initdb.c:2431 +#: initdb.c:2506 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]КАТАЛОГ расположение данных этого кластера БД\n" -#: initdb.c:2432 +#: initdb.c:2507 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=КОДИРОВКА кодировка по умолчанию для новых баз\n" -#: initdb.c:2433 +#: initdb.c:2508 #, c-format msgid "" " -g, --allow-group-access allow group read/execute on data directory\n" @@ -575,12 +644,12 @@ msgstr "" "для\n" " группы\n" -#: initdb.c:2434 +#: initdb.c:2509 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=ЛОКАЛЬ идентификатор локали ICU для новых баз\n" -#: initdb.c:2435 +#: initdb.c:2510 #, c-format msgid "" " --icu-rules=RULES set additional ICU collation rules for new " @@ -589,17 +658,17 @@ msgstr "" " --icu-rules=ПРАВИЛА дополнительные правила сортировки ICU для новых " "баз\n" -#: initdb.c:2436 +#: initdb.c:2511 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums включить контроль целостности страниц\n" -#: initdb.c:2437 +#: initdb.c:2512 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=ЛОКАЛЬ локаль по умолчанию для новых баз\n" -#: initdb.c:2438 +#: initdb.c:2513 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -613,28 +682,37 @@ msgstr "" " установить соответствующий параметр локали\n" " для новых баз (вместо значения из окружения)\n" -#: initdb.c:2442 +#: initdb.c:2517 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale эквивалентно --locale=C\n" -#: initdb.c:2443 +#: initdb.c:2518 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" --builtin-locale=ЛОКАЛЬ\n" +" имя встроенной локали для новых баз\n" + +#: initdb.c:2520 +#, c-format +msgid "" +" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " провайдер основной локали для новых баз\n" -#: initdb.c:2445 +#: initdb.c:2522 #, c-format msgid "" " --pwfile=FILE read password for the new superuser from file\n" msgstr "" " --pwfile=ФАЙЛ прочитать пароль суперпользователя из файла\n" -#: initdb.c:2446 +#: initdb.c:2523 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -643,29 +721,29 @@ msgstr "" " -T, --text-search-config=КОНФИГУРАЦИЯ\n" " конфигурация текстового поиска по умолчанию\n" -#: initdb.c:2448 +#: initdb.c:2525 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=ИМЯ имя суперпользователя БД\n" -#: initdb.c:2449 +#: initdb.c:2526 #, c-format msgid "" " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt запросить пароль суперпользователя\n" -#: initdb.c:2450 +#: initdb.c:2527 #, c-format msgid "" " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=КАТАЛОГ расположение журнала предзаписи\n" -#: initdb.c:2451 +#: initdb.c:2528 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=РАЗМЕР размер сегментов WAL (в мегабайтах)\n" -#: initdb.c:2452 +#: initdb.c:2529 #, c-format msgid "" "\n" @@ -674,7 +752,7 @@ msgstr "" "\n" "Редко используемые параметры:\n" -#: initdb.c:2453 +#: initdb.c:2530 #, c-format msgid "" " -c, --set NAME=VALUE override default setting for server parameter\n" @@ -682,27 +760,27 @@ msgstr "" " -c, --set ИМЯ=ЗНАЧЕНИЕ переопределить значение серверного параметра по\n" " умолчанию\n" -#: initdb.c:2454 +#: initdb.c:2531 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug выдавать много отладочных сообщений\n" -#: initdb.c:2455 +#: initdb.c:2532 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches установить debug_discard_caches=1\n" -#: initdb.c:2456 +#: initdb.c:2533 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L КАТАЛОГ расположение входных файлов\n" -#: initdb.c:2457 +#: initdb.c:2534 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean не очищать после ошибок\n" -#: initdb.c:2458 +#: initdb.c:2535 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " @@ -710,18 +788,23 @@ msgid "" msgstr "" " -N, --no-sync не ждать завершения сохранения данных на диске\n" -#: initdb.c:2459 +#: initdb.c:2536 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr "" " --no-instructions не выводить инструкции для дальнейших действий\n" -#: initdb.c:2460 +#: initdb.c:2537 +#, c-format +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show показать внутренние установки и выйти\n" + +#: initdb.c:2538 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show показать внутренние установки\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" -#: initdb.c:2461 +#: initdb.c:2539 #, c-format msgid "" " -S, --sync-only only sync database files to disk, then exit\n" @@ -729,7 +812,7 @@ msgstr "" " -S, --sync-only только синхронизировать с ФС файлы базы и " "завершиться\n" -#: initdb.c:2462 +#: initdb.c:2540 #, c-format msgid "" "\n" @@ -738,17 +821,17 @@ msgstr "" "\n" "Другие параметры:\n" -#: initdb.c:2463 +#: initdb.c:2541 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: initdb.c:2464 +#: initdb.c:2542 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: initdb.c:2465 +#: initdb.c:2543 #, c-format msgid "" "\n" @@ -758,7 +841,7 @@ msgstr "" "\n" "Если каталог данных не указан, используется переменная окружения PGDATA.\n" -#: initdb.c:2467 +#: initdb.c:2545 #, c-format msgid "" "\n" @@ -767,18 +850,18 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: initdb.c:2468 +#: initdb.c:2546 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: initdb.c:2496 +#: initdb.c:2570 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "" "нераспознанный метод проверки подлинности \"%s\" для подключений \"%s\"" -#: initdb.c:2510 +#: initdb.c:2584 #, c-format msgid "" "must specify a password for the superuser to enable password authentication" @@ -786,12 +869,12 @@ msgstr "" "для включения аутентификации по паролю необходимо указать пароль " "суперпользователя" -#: initdb.c:2529 +#: initdb.c:2603 #, c-format msgid "no data directory specified" msgstr "каталог данных не указан" -#: initdb.c:2530 +#: initdb.c:2604 #, c-format msgid "" "You must identify the directory where the data for this database system will " @@ -801,53 +884,55 @@ msgstr "" "Вы должны указать каталог, в котором будут располагаться данные этой СУБД. " "Это можно сделать, добавив ключ -D или установив переменную окружения PGDATA." -#: initdb.c:2547 +#: initdb.c:2621 #, c-format msgid "could not set environment" msgstr "не удалось задать переменную окружения" -#: initdb.c:2565 +#: initdb.c:2639 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " "\"%s\"" msgstr "программа \"%s\" нужна для %s, но она не найдена в каталоге \"%s\"" -#: initdb.c:2568 +#: initdb.c:2642 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "программа \"%s\" найдена программой \"%s\", но её версия отличается от " "версии %s" -#: initdb.c:2583 +#: initdb.c:2657 #, c-format msgid "input file location must be an absolute path" msgstr "расположение входных файлов должно задаваться абсолютным путём" -#: initdb.c:2600 +#: initdb.c:2674 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "Кластер баз данных будет инициализирован с локалью \"%s\".\n" -#: initdb.c:2603 +#: initdb.c:2677 #, c-format msgid "" "The database cluster will be initialized with this locale configuration:\n" msgstr "" "Кластер баз данных будет инициализирован со следующими параметрами локали:\n" -#: initdb.c:2604 +#: initdb.c:2678 #, c-format -msgid " provider: %s\n" -msgstr " провайдер: %s\n" +msgid " locale provider: %s\n" +msgstr " провайдер локалей: %s\n" -#: initdb.c:2606 +#: initdb.c:2680 #, c-format -msgid " ICU locale: %s\n" -msgstr " локаль ICU: %s\n" +msgid " default collation: %s\n" +msgstr "" +" правило сортировки\n" +" по умолчанию: %s\n" -#: initdb.c:2607 +#: initdb.c:2681 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -864,22 +949,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2637 +#: initdb.c:2711 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "не удалось найти подходящую кодировку для локали \"%s\"" -#: initdb.c:2639 +#: initdb.c:2713 #, c-format msgid "Rerun %s with the -E option." msgstr "Перезапустите %s с параметром -E." -#: initdb.c:2640 initdb.c:3173 initdb.c:3281 initdb.c:3301 +#: initdb.c:2714 initdb.c:3257 initdb.c:3377 initdb.c:3397 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: initdb.c:2652 +#: initdb.c:2726 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -888,40 +973,45 @@ msgstr "" "Кодировка \"%s\", подразумеваемая локалью, не годится для сервера.\n" "Вместо неё в качестве кодировки БД по умолчанию будет выбрана \"%s\".\n" -#: initdb.c:2657 +#: initdb.c:2731 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "для локали \"%s\" требуется неподдерживаемая кодировка \"%s\"" -#: initdb.c:2659 +#: initdb.c:2733 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "Кодировка \"%s\" недопустима в качестве серверной кодировки." -#: initdb.c:2661 +#: initdb.c:2735 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Перезапустите %s, выбрав другую локаль." -#: initdb.c:2669 +#: initdb.c:2743 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "" "Кодировка БД по умолчанию, выбранная в соответствии с настройками: \"%s\".\n" -#: initdb.c:2738 +#: initdb.c:2757 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "для локали \"%s\" встроенного провайдера требуется кодировка \"%s\"" + +#: initdb.c:2819 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "" "не удалось найти подходящую конфигурацию текстового поиска для локали \"%s\"" -#: initdb.c:2749 +#: initdb.c:2830 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "" "внимание: для локали \"%s\" нет известной конфигурации текстового поиска" -#: initdb.c:2754 +#: initdb.c:2835 #, c-format msgid "" "specified text search configuration \"%s\" might not match locale \"%s\"" @@ -929,37 +1019,37 @@ msgstr "" "указанная конфигурация текстового поиска \"%s\" может не соответствовать " "локали \"%s\"" -#: initdb.c:2759 +#: initdb.c:2840 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "Выбрана конфигурация текстового поиска по умолчанию \"%s\".\n" -#: initdb.c:2802 initdb.c:2873 +#: initdb.c:2883 initdb.c:2954 #, c-format msgid "creating directory %s ... " msgstr "создание каталога %s... " -#: initdb.c:2807 initdb.c:2878 initdb.c:2926 initdb.c:2982 +#: initdb.c:2888 initdb.c:2959 initdb.c:3007 initdb.c:3064 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не удалось создать каталог \"%s\": %m" -#: initdb.c:2816 initdb.c:2888 +#: initdb.c:2897 initdb.c:2969 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "исправление прав для существующего каталога %s... " -#: initdb.c:2821 initdb.c:2893 +#: initdb.c:2902 initdb.c:2974 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "не удалось поменять права для каталога \"%s\": %m" -#: initdb.c:2833 initdb.c:2905 +#: initdb.c:2914 initdb.c:2986 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" существует, но он не пуст" -#: initdb.c:2837 +#: initdb.c:2918 #, c-format msgid "" "If you want to create a new database system, either remove or empty the " @@ -968,29 +1058,29 @@ msgstr "" "Если вы хотите создать новую систему баз данных, удалите или очистите " "каталог \"%s\", либо при запуске %s в качестве пути укажите не \"%s\"." -#: initdb.c:2845 initdb.c:2915 initdb.c:3322 +#: initdb.c:2926 initdb.c:2996 initdb.c:3422 #, c-format msgid "could not access directory \"%s\": %m" -msgstr "ошибка доступа к каталогу \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" -#: initdb.c:2866 +#: initdb.c:2947 #, c-format msgid "WAL directory location must be an absolute path" msgstr "расположение каталога WAL должно определяться абсолютным путём" -#: initdb.c:2909 +#: initdb.c:2990 #, c-format msgid "" "If you want to store the WAL there, either remove or empty the directory " "\"%s\"." msgstr "Если вы хотите хранить WAL здесь, удалите или очистите каталог \"%s\"." -#: initdb.c:2919 +#: initdb.c:3000 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не удалось создать символическую ссылку \"%s\": %m" -#: initdb.c:2938 +#: initdb.c:3019 #, c-format msgid "" "It contains a dot-prefixed/invisible file, perhaps due to it being a mount " @@ -998,13 +1088,13 @@ msgid "" msgstr "" "Он содержит файл с точкой (невидимый), возможно, это точка монтирования." -#: initdb.c:2940 +#: initdb.c:3021 #, c-format msgid "" "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Он содержит подкаталог lost+found, возможно, это точка монтирования." -#: initdb.c:2942 +#: initdb.c:3023 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -1014,67 +1104,62 @@ msgstr "" "рекомендуется.\n" "Создайте в монтируемом ресурсе подкаталог и используйте его." -#: initdb.c:2968 +#: initdb.c:3050 #, c-format msgid "creating subdirectories ... " msgstr "создание подкаталогов... " -#: initdb.c:3011 +#: initdb.c:3093 msgid "performing post-bootstrap initialization ... " msgstr "выполняется заключительная инициализация... " -#: initdb.c:3172 +#: initdb.c:3256 #, c-format msgid "-c %s requires a value" msgstr "для -c %s требуется значение" -#: initdb.c:3197 +#: initdb.c:3281 #, c-format msgid "Running in debug mode.\n" msgstr "Программа запущена в режиме отладки.\n" -#: initdb.c:3201 +#: initdb.c:3285 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "" "Программа запущена в режиме 'no-clean' - очистки и исправления ошибок не " "будет.\n" -#: initdb.c:3271 +#: initdb.c:3358 #, c-format msgid "unrecognized locale provider: %s" msgstr "нераспознанный провайдер локали: %s" -#: initdb.c:3299 +#: initdb.c:3395 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: initdb.c:3306 initdb.c:3310 +#: initdb.c:3402 initdb.c:3406 initdb.c:3410 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s можно указать, только если выбран провайдер локали \"%s\"" -#: initdb.c:3324 initdb.c:3401 +#: initdb.c:3424 initdb.c:3487 msgid "syncing data to disk ... " msgstr "сохранение данных на диске... " -#: initdb.c:3332 +#: initdb.c:3432 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "нельзя одновременно запросить пароль и прочитать пароль из файла" -#: initdb.c:3354 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "аргументом --wal-segsize должно быть число" - -#: initdb.c:3356 +#: initdb.c:3443 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "аргументом --wal-segsize должна быть степень двух от 1 до 1024" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "аргументом %s должна быть степень двух от 1 до 1024" -#: initdb.c:3370 +#: initdb.c:3456 #, c-format msgid "" "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" @@ -1082,7 +1167,7 @@ msgstr "" "имя \"%s\" для суперпользователя не допускается; имена ролей не могут " "начинаться с \"pg_\"" -#: initdb.c:3372 +#: initdb.c:3458 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1093,17 +1178,17 @@ msgstr "" "От его имени также будет запускаться процесс сервера.\n" "\n" -#: initdb.c:3388 +#: initdb.c:3474 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Контроль целостности страниц данных включён.\n" -#: initdb.c:3390 +#: initdb.c:3476 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Контроль целостности страниц данных отключён.\n" -#: initdb.c:3407 +#: initdb.c:3493 #, c-format msgid "" "\n" @@ -1114,12 +1199,12 @@ msgstr "" "Сохранение данных на диск пропускается.\n" "Каталог данных может повредиться при сбое операционной системы.\n" -#: initdb.c:3412 +#: initdb.c:3498 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "включение метода аутентификации \"trust\" для локальных подключений" -#: initdb.c:3413 +#: initdb.c:3499 #, c-format msgid "" "You can change this by editing pg_hba.conf or using the option -A, or --auth-" @@ -1129,11 +1214,11 @@ msgstr "" "initdb с ключом -A, --auth-local или --auth-host." #. translator: This is a placeholder in a shell command. -#: initdb.c:3443 +#: initdb.c:3529 msgid "logfile" msgstr "файл_журнала" -#: initdb.c:3445 +#: initdb.c:3531 #, c-format msgid "" "\n" @@ -1148,6 +1233,14 @@ msgstr "" " %s\n" "\n" +#, c-format +#~ msgid " ICU locale: %s\n" +#~ msgstr " локаль ICU: %s\n" + +#, c-format +#~ msgid "argument of --wal-segsize must be a number" +#~ msgstr "аргументом --wal-segsize должно быть число" + #, c-format #~ msgid "could not identify current directory: %m" #~ msgstr "не удалось определить текущий каталог: %m" @@ -1172,10 +1265,6 @@ msgstr "" #~ msgid "could not stat file or directory \"%s\": %m" #~ msgstr "не удалось получить информацию о файле или каталоге \"%s\": %m" -#, c-format -#~ msgid "could not remove file or directory \"%s\": %m" -#~ msgstr "ошибка при удалении файла или каталога \"%s\": %m" - #, c-format #~ msgid "The default database encoding has been set to \"%s\".\n" #~ msgstr "В качестве кодировки БД по умолчанию установлена \"%s\".\n" @@ -1226,9 +1315,6 @@ msgstr "" #~ msgid "%s: locale name too long, skipped: \"%s\"\n" #~ msgstr "%s: слишком длинное имя локали, пропущено: \"%s\"\n" -#~ msgid "%s: locale name has non-ASCII characters, skipped: \"%s\"\n" -#~ msgstr "%s: имя локали содержит не ASCII-символы, пропущено: \"%s\"\n" - #~ msgid "No usable system locales were found.\n" #~ msgstr "Пригодные локали в системе не найдены.\n" diff --git a/src/bin/initdb/po/sv.po b/src/bin/initdb/po/sv.po index dc5e8fd525168..58183c91295e7 100644 --- a/src/bin/initdb/po/sv.po +++ b/src/bin/initdb/po/sv.po @@ -1,5 +1,5 @@ # Swedish message translation file for initdb -# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # Magnus Hagander , 2007. # Peter Eisentraut , 2009. # Mats Erik Andersson , 2014. @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-31 19:50+0000\n" -"PO-Revision-Date: 2023-08-31 21:59+0200\n" +"POT-Creation-Date: 2025-02-12 13:51+0000\n" +"PO-Revision-Date: 2025-02-12 20:46+0100\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -40,33 +40,48 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:750 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:372 initdb.c:408 #, c-format msgid "out of memory" msgstr "slut på minne" @@ -82,35 +97,46 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "kunde inte göra stat() på fil \"%s\": %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "kunde inte öppna katalog \"%s\": %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "kunde inte läsa katalog \"%s\": %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "kunde inte fsync:a fil \"%s\": %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" @@ -150,12 +176,12 @@ msgstr "kunde inte köra igen med token för begränsad åtkomst: felkod %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "kunde inte hämta statuskod för underprocess: felkod %lu" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "kunde inte ta bort fil \"%s\": %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "kunde inte ta bort katalog \"%s\": %m" @@ -204,6 +230,31 @@ msgstr "barnprocess terminerades av signal %d: %s" msgid "child process exited with unrecognized status %d" msgstr "barnprocess avslutade med okänd statuskod %d" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s måste vara i intervallet %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: ../../fe_utils/string_utils.c:608 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:781 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + #: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" @@ -214,151 +265,166 @@ msgstr "kunde inte sätta en knutpunkt (junction) för \"%s\": %s\n" msgid "could not get junction for \"%s\": %s\n" msgstr "kunde inte få en knutpunkt (junction) för \"%s\": %s\n" -#: initdb.c:618 initdb.c:1613 +#: initdb.c:369 +#, c-format +msgid "_wsetlocale() failed" +msgstr "_wsetlocale() misslyckades" + +#: initdb.c:376 +#, c-format +msgid "setlocale() failed" +msgstr "setlocale() misslyckades" + +#: initdb.c:390 +#, c-format +msgid "failed to restore old locale" +msgstr "misslyckades med att återställa gamla lokalen" + +#: initdb.c:393 +#, c-format +msgid "failed to restore old locale \"%s\"" +msgstr "misslyckades med att återställa gamla lokalen \"%s\"" + +#: initdb.c:682 initdb.c:1674 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "kunde inte öppna filen \"%s\" för läsning: %m" -#: initdb.c:662 initdb.c:966 initdb.c:986 +#: initdb.c:726 initdb.c:1030 initdb.c:1050 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "kunde inte öppna fil \"%s\" för skrivning: %m" -#: initdb.c:666 initdb.c:969 initdb.c:988 +#: initdb.c:730 initdb.c:1033 initdb.c:1052 #, c-format msgid "could not write file \"%s\": %m" msgstr "kunde inte skriva fil \"%s\": %m" -#: initdb.c:670 +#: initdb.c:734 #, c-format msgid "could not close file \"%s\": %m" msgstr "kunde inte stänga fil \"%s\": %m" -#: initdb.c:686 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "kunde inte köra kommandot \"%s\": %m" - -#: initdb.c:704 +#: initdb.c:768 #, c-format msgid "removing data directory \"%s\"" msgstr "tar bort datakatalog \"%s\"" -#: initdb.c:706 +#: initdb.c:770 #, c-format msgid "failed to remove data directory" msgstr "misslyckades med att ta bort datakatalog" -#: initdb.c:710 +#: initdb.c:774 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "tar bort innehållet i datakatalog \"%s\"" -#: initdb.c:713 +#: initdb.c:777 #, c-format msgid "failed to remove contents of data directory" msgstr "misslyckades med att ta bort innehållet i datakatalogen" -#: initdb.c:718 +#: initdb.c:782 #, c-format msgid "removing WAL directory \"%s\"" msgstr "tar bort WAL-katalog \"%s\"" -#: initdb.c:720 +#: initdb.c:784 #, c-format msgid "failed to remove WAL directory" msgstr "misslyckades med att ta bort WAL-katalog" -#: initdb.c:724 +#: initdb.c:788 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "tar bort innehållet i WAL-katalog \"%s\"" -#: initdb.c:726 +#: initdb.c:790 #, c-format msgid "failed to remove contents of WAL directory" msgstr "misslyckades med att ta bort innehållet i WAL-katalogen" -#: initdb.c:733 +#: initdb.c:797 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "datakatalog \"%s\" är ej borttagen på användares begäran" -#: initdb.c:737 +#: initdb.c:801 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "WAL-katalog \"%s\" är ej borttagen på användares begäran" -#: initdb.c:755 +#: initdb.c:819 #, c-format msgid "cannot be run as root" msgstr "kan inte köras som root" -#: initdb.c:756 +#: initdb.c:820 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "Logga in (t.ex. med \"su\") som den (opriviligerade) användare som skall äga serverprocessen." -#: initdb.c:788 +#: initdb.c:852 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\" är inte en giltig teckenkodning för servern" -#: initdb.c:932 +#: initdb.c:996 #, c-format msgid "file \"%s\" does not exist" msgstr "filen \"%s\" finns inte" -#: initdb.c:933 initdb.c:938 initdb.c:945 +#: initdb.c:997 initdb.c:1002 initdb.c:1009 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "Detta kan betyda att du har en korrupt installation eller att du har angivit felaktig katalog till flaggan -L." -#: initdb.c:937 +#: initdb.c:1001 #, c-format msgid "could not access file \"%s\": %m" msgstr "kunde inte komma åt filen \"%s\": %m" -#: initdb.c:944 +#: initdb.c:1008 #, c-format msgid "file \"%s\" is not a regular file" msgstr "filen \"%s\" är inte en normal fil" -#: initdb.c:1077 +#: initdb.c:1141 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "väljer mekanism för dynamiskt, delat minne ... " -#: initdb.c:1086 +#: initdb.c:1150 #, c-format -msgid "selecting default max_connections ... " -msgstr "sätter förvalt värde för max_connections ... " +msgid "selecting default \"max_connections\" ... " +msgstr "sätter förvalt värde för \"max_connections\" ... " -#: initdb.c:1106 +#: initdb.c:1170 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "sätter förvalt värde för shared_buffers ... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "sätter förvalt värde för \"shared_buffers\" ... " -#: initdb.c:1129 +#: initdb.c:1193 #, c-format msgid "selecting default time zone ... " msgstr "sätter förvalt värde för tidszon ... " -#: initdb.c:1206 +#: initdb.c:1272 msgid "creating configuration files ... " msgstr "skapar konfigurationsfiler ... " -#: initdb.c:1367 initdb.c:1381 initdb.c:1448 initdb.c:1459 +#: initdb.c:1425 initdb.c:1439 initdb.c:1506 initdb.c:1517 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "kunde inte ändra rättigheter på \"%s\": %m" -#: initdb.c:1477 +#: initdb.c:1536 #, c-format msgid "running bootstrap script ... " msgstr "kör uppsättningsskript..." -#: initdb.c:1489 +#: initdb.c:1548 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "indatafil \"%s\" tillhör inte PostgreSQL %s" @@ -367,125 +433,125 @@ msgstr "indatafil \"%s\" tillhör inte PostgreSQL %s" # with a standard directory "/usr/local/pgsql", is such that # the translated message string produces a reasonable output. # -#: initdb.c:1491 +#: initdb.c:1550 #, c-format msgid "Specify the correct path using the option -L." msgstr "Ange korrekt sökväg med flaggan -L." -#: initdb.c:1591 +#: initdb.c:1652 msgid "Enter new superuser password: " msgstr "Mata in ett nytt lösenord för superuser: " -#: initdb.c:1592 +#: initdb.c:1653 msgid "Enter it again: " msgstr "Mata in det igen: " -#: initdb.c:1595 +#: initdb.c:1656 #, c-format msgid "Passwords didn't match.\n" msgstr "Lösenorden stämde inte överens.\n" -#: initdb.c:1619 +#: initdb.c:1680 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "kunde inte läsa lösenord i filen \"%s\": %m" -#: initdb.c:1622 +#: initdb.c:1683 #, c-format msgid "password file \"%s\" is empty" msgstr "lösenordsfilen \"%s\" är tom" -#: initdb.c:2034 +#: initdb.c:2095 #, c-format msgid "caught signal\n" msgstr "mottog signal\n" -#: initdb.c:2040 +#: initdb.c:2101 #, c-format msgid "could not write to child process: %s\n" msgstr "kunde inte skriva till barnprocess: %s\n" -#: initdb.c:2048 +#: initdb.c:2109 #, c-format msgid "ok\n" msgstr "ok\n" -#: initdb.c:2137 -#, c-format -msgid "setlocale() failed" -msgstr "setlocale() misslyckades" - -#: initdb.c:2155 +#: initdb.c:2191 initdb.c:2237 #, c-format -msgid "failed to restore old locale \"%s\"" -msgstr "misslyckades med att återställa gamla lokalen \"%s\"" +msgid "locale name \"%s\" contains non-ASCII characters" +msgstr "lokalnamn \"%s\" innehåller tecken som ej är ASCII" -#: initdb.c:2163 +#: initdb.c:2217 #, c-format msgid "invalid locale name \"%s\"" msgstr "ogiltigt lokalnamn \"%s\"" -#: initdb.c:2164 +#: initdb.c:2218 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "Om lokalnamnet är specifikt för ICU, använd --icu-locale." -#: initdb.c:2177 +#: initdb.c:2231 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "ogiltig lokalinställning. Kontrollera miljövariablerna LANG och LC_*" -#: initdb.c:2203 initdb.c:2227 +#: initdb.c:2262 initdb.c:2286 #, c-format msgid "encoding mismatch" msgstr "teckenkodning matchar inte" -#: initdb.c:2204 +#: initdb.c:2263 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "Teckenkodningen du har valt (%s) och teckenkodningen som valda lokalen använder (%s) passar inte ihop. Detta kommer leda till problem för funktioner som arbetar med strängar." -#: initdb.c:2209 initdb.c:2230 +#: initdb.c:2268 initdb.c:2289 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "Kör %s igen och ange antingen ingen explicit kodning eller välj en matchande kombination." -#: initdb.c:2228 +#: initdb.c:2287 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "Den valda teckenkodningen (%s) stöds inte av ICU." -#: initdb.c:2279 +#: initdb.c:2338 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "kunde inte konvertera lokalnamn \"%s\" till språktagg: %s" -#: initdb.c:2285 initdb.c:2337 initdb.c:2416 +#: initdb.c:2344 initdb.c:2396 initdb.c:2488 #, c-format msgid "ICU is not supported in this build" msgstr "ICU stöds inte av detta bygge" -#: initdb.c:2308 +#: initdb.c:2367 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "kunde inte härleda språk från lokalen \"%s\": %s" -#: initdb.c:2334 +#: initdb.c:2393 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "lokalen \"%s\" har ett okänt språk \"%s\"" -#: initdb.c:2400 +#: initdb.c:2454 #, c-format -msgid "ICU locale must be specified" -msgstr "ICU-lokal måste anges" +msgid "locale must be specified if provider is %s" +msgstr "lokal måste anges när leverantören är %s" -#: initdb.c:2404 +#: initdb.c:2465 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "ogiltigt lokalnamn \"%s\" för inbyggd leverantör" + +#: initdb.c:2476 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "Använder språktagg \"%s\" för ICU-lokal \"%s\".\n" -#: initdb.c:2427 +#: initdb.c:2499 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" @@ -494,17 +560,17 @@ msgstr "" "%s initierar ett databaskluster för PostgreSQL.\n" "\n" -#: initdb.c:2428 +#: initdb.c:2500 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: initdb.c:2429 +#: initdb.c:2501 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [FLAGGA]... [DATAKATALOG]\n" -#: initdb.c:2430 +#: initdb.c:2502 #, c-format msgid "" "\n" @@ -513,57 +579,57 @@ msgstr "" "\n" "Flaggor:\n" -#: initdb.c:2431 +#: initdb.c:2503 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, --auth=METOD förvald autentiseringsmetod för alla anslutningar\n" -#: initdb.c:2432 +#: initdb.c:2504 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr " --auth-host=METOD autentiseringsmetod för TCP/IP-anslutningar\n" -#: initdb.c:2433 +#: initdb.c:2505 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr " --auth-local=METOD autentiseringsmetod för anslutningar via unix-uttag\n" -#: initdb.c:2434 +#: initdb.c:2506 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D, --pgdata=]DATAKATALOG läge för detta databaskluster\n" -#: initdb.c:2435 +#: initdb.c:2507 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=KODNING sätter teckenkodning för nya databaser\n" -#: initdb.c:2436 +#: initdb.c:2508 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr " -g, --allow-group-access tillåt läs/kör för grupp på datakatalogen\n" -#: initdb.c:2437 +#: initdb.c:2509 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOKAL sätt ID för ICU-lokal för nya databaser\n" -#: initdb.c:2438 +#: initdb.c:2510 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" msgstr " --icu-rules=REGLER sätt ytterligare ICU-jämförelseregler för nya databaser\n" -#: initdb.c:2439 +#: initdb.c:2511 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums använd checksummor på datablock\n" -#: initdb.c:2440 +#: initdb.c:2512 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=LOKAL sätt standardlokal för nya databaser\n" -#: initdb.c:2441 +#: initdb.c:2513 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -576,26 +642,35 @@ msgstr "" " sätter standardlokal i utvald kategori för\n" " nya databaser (förval hämtas ur omgivningen)\n" -#: initdb.c:2445 +#: initdb.c:2517 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale samma som --locale=C\n" -#: initdb.c:2446 +#: initdb.c:2518 +#, c-format +msgid "" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" --builtin-locale=LOKAL\n" +" sätt standard lokalnamn för nya databaser\n" + +#: initdb.c:2520 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " sätt standard lokalleverantör för nya databaser\n" -#: initdb.c:2448 +#: initdb.c:2522 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=FIL läser lösenord för superuser från fil\n" -#: initdb.c:2449 +#: initdb.c:2523 #, c-format msgid "" " -T, --text-search-config=CFG\n" @@ -604,27 +679,27 @@ msgstr "" " -T, --text-search-config=CFG\n" " standardkonfiguration för textsökning\n" -#: initdb.c:2451 +#: initdb.c:2525 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NAMN namn på databasens superuser\n" -#: initdb.c:2452 +#: initdb.c:2526 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt efterfråga lösenord för superuser\n" -#: initdb.c:2453 +#: initdb.c:2527 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR katalog för write-ahead-log (WAL)\n" -#: initdb.c:2454 +#: initdb.c:2528 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=STORLEK storlek på WAL-segment i megabyte\n" -#: initdb.c:2455 +#: initdb.c:2529 #, c-format msgid "" "\n" @@ -633,52 +708,57 @@ msgstr "" "\n" "Mindre vanliga flaggor:\n" -#: initdb.c:2456 +#: initdb.c:2530 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAMN=VÄRDE ersätt standardinställning för serverparameter\n" -#: initdb.c:2457 +#: initdb.c:2531 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug generera massor med debug-utskrifter\n" -#: initdb.c:2458 +#: initdb.c:2532 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches sätt debug_discard_caches=1\n" -#: initdb.c:2459 +#: initdb.c:2533 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L KATALOG katalog där indatafiler skall sökas\n" -#: initdb.c:2460 +#: initdb.c:2534 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean städa inte upp efter fel\n" -#: initdb.c:2461 +#: initdb.c:2535 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync vänta inte på att ändingar säkert skrivits till disk\n" -#: initdb.c:2462 +#: initdb.c:2536 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions skriv inte instruktioner för nästa steg\n" -#: initdb.c:2463 +#: initdb.c:2537 +#, c-format +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show visa interna inställningar, avsluta sedan\n" + +#: initdb.c:2538 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show visa interna inställningar\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" -#: initdb.c:2464 +#: initdb.c:2539 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only synka bara databasfiler till disk, avsluta seden\n" -#: initdb.c:2465 +#: initdb.c:2540 #, c-format msgid "" "\n" @@ -687,17 +767,17 @@ msgstr "" "\n" "Andra flaggor:\n" -#: initdb.c:2466 +#: initdb.c:2541 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: initdb.c:2467 +#: initdb.c:2542 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: initdb.c:2468 +#: initdb.c:2543 #, c-format msgid "" "\n" @@ -707,7 +787,7 @@ msgstr "" "\n" "Om datakatalogen inte anges så tas den från omgivningsvariabeln PGDATA.\n" -#: initdb.c:2470 +#: initdb.c:2545 #, c-format msgid "" "\n" @@ -716,72 +796,72 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: initdb.c:2471 +#: initdb.c:2546 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: initdb.c:2499 +#: initdb.c:2570 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "ogiltig autentiseringsmetod \"%s\" för anslutning av typen \"%s\"" -#: initdb.c:2513 +#: initdb.c:2584 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "du måste ange ett lösenord för superuser för att kunna slå på lösenordsautentisering" -#: initdb.c:2532 +#: initdb.c:2603 #, c-format msgid "no data directory specified" msgstr "ingen datakatalog angiven" -#: initdb.c:2533 +#: initdb.c:2604 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "Du måste uppge den katalog där data för detta databassystem skall lagras. Gör det antingen med flaggan -D eller genom att sätta omgivningsvariabeln PGDATA." -#: initdb.c:2550 +#: initdb.c:2621 #, c-format msgid "could not set environment" msgstr "kunde inte sätta omgivningen" -#: initdb.c:2568 +#: initdb.c:2639 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "programmet \"%s\" behövs av %s men hittades inte i samma katalog som \"%s\"" -#: initdb.c:2571 +#: initdb.c:2642 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "programmet \"%s\" hittades av \"%s\" men är inte av samma version som %s" -#: initdb.c:2586 +#: initdb.c:2657 #, c-format msgid "input file location must be an absolute path" msgstr "plats för indatafiler måste vara en absolut sökväg" -#: initdb.c:2603 +#: initdb.c:2674 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "Databasklustret kommer att skapas med lokalnamn \"%s\".\n" -#: initdb.c:2606 +#: initdb.c:2677 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "Databasklustret kommer att initieras med denna lokalkonfiguration:\n" -#: initdb.c:2607 +#: initdb.c:2678 #, c-format -msgid " provider: %s\n" -msgstr " leverantör: %s\n" +msgid " locale provider: %s\n" +msgstr " lokalleverantör: %s\n" -#: initdb.c:2609 +#: initdb.c:2680 #, c-format -msgid " ICU locale: %s\n" -msgstr " ICU-lokal: %s\n" +msgid " default collation: %s\n" +msgstr " standardjämförelse: %s\n" -#: initdb.c:2610 +#: initdb.c:2681 #, c-format msgid "" " LC_COLLATE: %s\n" @@ -798,22 +878,22 @@ msgstr "" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2640 +#: initdb.c:2711 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "kunde inte välja en lämplig kodning för lokal \"%s\"" -#: initdb.c:2642 +#: initdb.c:2713 #, c-format msgid "Rerun %s with the -E option." msgstr "Kör %s igen men med flaggan -E." -#: initdb.c:2643 initdb.c:3176 initdb.c:3284 initdb.c:3304 +#: initdb.c:2714 initdb.c:3257 initdb.c:3377 initdb.c:3397 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: initdb.c:2655 +#: initdb.c:2726 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -822,107 +902,112 @@ msgstr "" "Teckenkodning \"%s\", tagen ur lokalnamnet, är inte godtagbar för servern.\n" "I dess ställe sättes databasens förvalda teckenkodning till \"%s\".\n" -#: initdb.c:2660 +#: initdb.c:2731 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "lokalen \"%s\" kräver ej supportad teckenkodning \"%s\"" -#: initdb.c:2662 +#: initdb.c:2733 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "Teckenkodning \"%s\" tillåts inte som serverteckenkodning." -#: initdb.c:2664 +#: initdb.c:2735 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Kör %s igen men välj en annan lokal." -#: initdb.c:2672 +#: initdb.c:2743 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "Förvald teckenkodning för databaser är satt till \"%s\".\n" -#: initdb.c:2741 +#: initdb.c:2757 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "lokal \"%s\" för inbyggd leverantör kräver teckenkodning \"%s\"" + +#: initdb.c:2819 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "kunde inte hitta en lämplig textsökningskonfiguration för lokalnamn \"%s\"" -#: initdb.c:2752 +#: initdb.c:2830 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "ingen lämplig textsökningskonfiguration för lokalnamn \"%s\"" -#: initdb.c:2757 +#: initdb.c:2835 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "uppgiven textsökningskonfiguration \"%s\" passar kanske inte till lokalnamn \"%s\"" -#: initdb.c:2762 +#: initdb.c:2840 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "Förvald textsökningskonfiguration för databaser är satt till \"%s\".\n" -#: initdb.c:2805 initdb.c:2876 +#: initdb.c:2883 initdb.c:2954 #, c-format msgid "creating directory %s ... " msgstr "skapar katalog %s ... " -#: initdb.c:2810 initdb.c:2881 initdb.c:2929 initdb.c:2985 +#: initdb.c:2888 initdb.c:2959 initdb.c:3007 initdb.c:3064 #, c-format msgid "could not create directory \"%s\": %m" msgstr "kunde inte skapa katalog \"%s\": %m" -#: initdb.c:2819 initdb.c:2891 +#: initdb.c:2897 initdb.c:2969 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "sätter rättigheter på existerande katalog %s ... " -#: initdb.c:2824 initdb.c:2896 +#: initdb.c:2902 initdb.c:2974 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "kunde inte ändra rättigheter på katalogen \"%s\": %m" -#: initdb.c:2836 initdb.c:2908 +#: initdb.c:2914 initdb.c:2986 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "katalogen \"%s\" existerar men är inte tom" -#: initdb.c:2840 +#: initdb.c:2918 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "Om du vill skapa ett nytt databassystem, tag då antingen bort eller töm katalogen \"%s\" eller kör %s med annat argument än \"%s\"." -#: initdb.c:2848 initdb.c:2918 initdb.c:3325 +#: initdb.c:2926 initdb.c:2996 initdb.c:3422 #, c-format msgid "could not access directory \"%s\": %m" msgstr "kunde inte komma åt katalog \"%s\": %m" -#: initdb.c:2869 +#: initdb.c:2947 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL-katalogen måste vara en absolut sökväg" -#: initdb.c:2912 +#: initdb.c:2990 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "Om du vill spara WAL där, antingen radera eller töm katalogen \"%s\"." -#: initdb.c:2922 +#: initdb.c:3000 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "kan inte skapa symbolisk länk \"%s\": %m" -#: initdb.c:2941 +#: initdb.c:3019 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "Den innehåller en gömd fil, med inledande punkt i namnet; kanske är detta en monteringspunkt." -#: initdb.c:2943 +#: initdb.c:3021 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Den innehåller \"lost+found\"; kanske är detta en monteringspunkt." -#: initdb.c:2945 +#: initdb.c:3023 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" @@ -931,70 +1016,65 @@ msgstr "" "Att använda en monteringspunkt som datakatalog rekommenderas inte.\n" "Skapa först en underkatalog under monteringspunkten." -#: initdb.c:2971 +#: initdb.c:3050 #, c-format msgid "creating subdirectories ... " msgstr "Skapar underkataloger ... " -#: initdb.c:3014 +#: initdb.c:3093 msgid "performing post-bootstrap initialization ... " msgstr "utför initiering efter uppstättning..." -#: initdb.c:3175 +#: initdb.c:3256 #, c-format msgid "-c %s requires a value" msgstr "-c %s kräver ett värde" -#: initdb.c:3200 +#: initdb.c:3281 #, c-format msgid "Running in debug mode.\n" msgstr "Kör i debug-läge.\n" -#: initdb.c:3204 +#: initdb.c:3285 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "Kör i no-clean-läge. Misstag kommer inte städas bort.\n" -#: initdb.c:3274 +#: initdb.c:3358 #, c-format msgid "unrecognized locale provider: %s" msgstr "okänd lokalleverantör: %s" -#: initdb.c:3302 +#: initdb.c:3395 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: initdb.c:3309 initdb.c:3313 +#: initdb.c:3402 initdb.c:3406 initdb.c:3410 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s kan inte anges om inte lokalleverantör \"%s\" valts" -#: initdb.c:3327 initdb.c:3404 +#: initdb.c:3424 initdb.c:3487 msgid "syncing data to disk ... " msgstr "synkar data till disk ... " -#: initdb.c:3335 +#: initdb.c:3432 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "lösenordsfråga och lösenordsfil kan inte anges samtidigt" -#: initdb.c:3357 +#: initdb.c:3443 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "argumentet till --wal-segsize måste vara ett tal" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "argumentet till %s måste vara en tvåpotens mellan 1 och 1024" -#: initdb.c:3359 -#, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "argumentet till --wal-segsize måste vara en tvåpotens mellan 1 och 1024" - -#: initdb.c:3373 +#: initdb.c:3456 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "superuser-namn \"%s\" tillåts inte; rollnamn får inte börja på \"pg_\"" -#: initdb.c:3375 +#: initdb.c:3458 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -1005,17 +1085,17 @@ msgstr "" "Denna användare måste också vara ägare av server-processen.\n" "\n" -#: initdb.c:3391 +#: initdb.c:3474 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Checksummor för datablock är aktiva.\n" -#: initdb.c:3393 +#: initdb.c:3476 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Checksummor för datablock är avstängda.\n" -#: initdb.c:3410 +#: initdb.c:3493 #, c-format msgid "" "\n" @@ -1026,22 +1106,22 @@ msgstr "" "Avstod från synkning mot lagringsmedium.\n" "Datakatalogen kan komma att fördärvas om operativsystemet störtar.\n" -#: initdb.c:3415 +#: initdb.c:3498 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "slår på autentiseringsmetod \"trust\" för lokala anslutningar" -#: initdb.c:3416 +#: initdb.c:3499 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "Du kan ändra detta genom att redigera pg_hba.conf eller genom att sätta flaggor -A eller --auth-local och --auth-host nästa gång du kör initdb." #. translator: This is a placeholder in a shell command. -#: initdb.c:3446 +#: initdb.c:3529 msgid "logfile" msgstr "loggfil" -#: initdb.c:3448 +#: initdb.c:3531 #, c-format msgid "" "\n" @@ -1055,39 +1135,3 @@ msgstr "" "\n" " %s\n" "\n" - -#, c-format -#~ msgid "The default database encoding has been set to \"%s\".\n" -#~ msgstr "Förvald teckenkodning för databaser är satt till \"%s\".\n" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "kan inte skapa token för begränsad åtkomst på denna plattorm: felkod %lu" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "kunde inte byta katalog till \"%s\": %m" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "kunde inte ladda länkbibliotek \"%s\": felkod %lu" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "kan inte läsa symbolisk länk \"%s\": %m" - -#, c-format -#~ msgid "could not remove file or directory \"%s\": %m" -#~ msgstr "kunde inte ta bort fil eller katalog \"%s\": %m" - -#, c-format -#~ msgid "could not stat file or directory \"%s\": %m" -#~ msgstr "kunde inte ta status på fil eller katalog \"%s\": %m" - -#, c-format -#~ msgid "symlinks are not supported on this platform" -#~ msgstr "symboliska länkar stöds inte på denna plattform" diff --git a/src/bin/initdb/po/uk.po b/src/bin/initdb/po/uk.po index bcda4ce03cfcd..699f6e9680374 100644 --- a/src/bin/initdb/po/uk.po +++ b/src/bin/initdb/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:19+0000\n" -"PO-Revision-Date: 2023-12-19 16:43+0100\n" +"POT-Creation-Date: 2024-08-31 06:21+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,9 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/initdb.pot\n" -"X-Crowdin-File-ID: 943\n" -"X-Generator: Poedit 3.4.1\n" +"X-Crowdin-File: /REL_17_STABLE/initdb.pot\n" +"X-Crowdin-File-ID: 1034\n" #: ../../../src/common/logging.c:276 #, c-format @@ -38,33 +37,48 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 initdb.c:695 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: initdb.c:349 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:353 #, c-format msgid "out of memory" msgstr "недостатньо пам'яті" @@ -80,35 +94,46 @@ msgstr "недостатньо пам'яті\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" -#: ../../common/file_utils.c:162 ../../common/pgfnames.c:48 -#: ../../common/rmtree.c:63 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не вдалося відкрити каталог \"%s\": %m" -#: ../../common/file_utils.c:196 ../../common/pgfnames.c:69 -#: ../../common/rmtree.c:104 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не вдалося прочитати каталог \"%s\": %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" - -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не вдалося fsync файл \"%s\": %m" -#: ../../common/file_utils.c:379 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" @@ -148,12 +173,12 @@ msgstr "не вдалося перезапустити з обмеженим т msgid "could not get exit code from subprocess: error code %lu" msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu" -#: ../../common/rmtree.c:95 +#: ../../common/rmtree.c:97 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не можливо видалити файл \"%s\": %m" -#: ../../common/rmtree.c:122 +#: ../../common/rmtree.c:124 #, c-format msgid "could not remove directory \"%s\": %m" msgstr "не вдалося видалити каталог \"%s\": %m" @@ -202,6 +227,31 @@ msgstr "дочірній процес перервано через сигнал msgid "child process exited with unrecognized status %d" msgstr "дочірній процес завершився з невизнаним статусом %d" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неприпустиме значення \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s має бути в діапазоні %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + #: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" @@ -212,842 +262,816 @@ msgstr "не вдалося встановити сполучення для \"% msgid "could not get junction for \"%s\": %s\n" msgstr "не вдалося встановити сполучення для \"%s\": %s\n" -#: initdb.c:618 initdb.c:1613 +#: initdb.c:627 initdb.c:1619 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не вдалося відкрити файл \"%s\" для читання: %m" -#: initdb.c:662 initdb.c:966 initdb.c:986 +#: initdb.c:671 initdb.c:975 initdb.c:995 #, c-format msgid "could not open file \"%s\" for writing: %m" msgstr "не вдалося відкрити файл \"%s\" для запису: %m" -#: initdb.c:666 initdb.c:969 initdb.c:988 +#: initdb.c:675 initdb.c:978 initdb.c:997 #, c-format msgid "could not write file \"%s\": %m" msgstr "не вдалося записати файл \"%s\": %m" -#: initdb.c:670 +#: initdb.c:679 #, c-format msgid "could not close file \"%s\": %m" msgstr "неможливо закрити файл \"%s\": %m" -#: initdb.c:686 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не вдалося виконати команду \"%s\": %m" - -#: initdb.c:704 +#: initdb.c:713 #, c-format msgid "removing data directory \"%s\"" msgstr "видалення даних з директорії \"%s\"" -#: initdb.c:706 +#: initdb.c:715 #, c-format msgid "failed to remove data directory" msgstr "не вдалося видалити дані директорії" -#: initdb.c:710 +#: initdb.c:719 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "видалення даних з директорії \"%s\"" -#: initdb.c:713 +#: initdb.c:722 #, c-format msgid "failed to remove contents of data directory" msgstr "не вдалося видалити дані директорії" -#: initdb.c:718 +#: initdb.c:727 #, c-format msgid "removing WAL directory \"%s\"" msgstr "видалення WAL директорії \"%s\"" -#: initdb.c:720 +#: initdb.c:729 #, c-format msgid "failed to remove WAL directory" msgstr "не вдалося видалити директорію WAL" -#: initdb.c:724 +#: initdb.c:733 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "видалення даних з директорії WAL \"%s\"" -#: initdb.c:726 +#: initdb.c:735 #, c-format msgid "failed to remove contents of WAL directory" msgstr "не вдалося видалити дані директорії WAL" -#: initdb.c:733 +#: initdb.c:742 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "директорія даних \"%s\" не видалена за запитом користувача" -#: initdb.c:737 +#: initdb.c:746 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "директорія WAL \"%s\" не видалена за запитом користувача" -#: initdb.c:755 +#: initdb.c:764 #, c-format msgid "cannot be run as root" msgstr "не може виконуватись як root" -#: initdb.c:756 +#: initdb.c:765 #, c-format msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." msgstr "Будь ласка, увійдіть (за допомогою, наприклад, \"su\") як (непривілейований) користувач, від імені якого буде запущено серверний процес." -#: initdb.c:788 +#: initdb.c:797 #, c-format msgid "\"%s\" is not a valid server encoding name" msgstr "\"%s\" невірне ім'я серверного кодування" -#: initdb.c:932 +#: initdb.c:941 #, c-format msgid "file \"%s\" does not exist" msgstr "файл \"%s\" не існує" -#: initdb.c:933 initdb.c:938 initdb.c:945 +#: initdb.c:942 initdb.c:947 initdb.c:954 #, c-format msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." msgstr "Це означає, що ваша інсталяція пошкоджена або в параметрі -L задана неправильна директорія." -#: initdb.c:937 +#: initdb.c:946 #, c-format msgid "could not access file \"%s\": %m" msgstr "немає доступу до файлу \"%s\": %m" -#: initdb.c:944 +#: initdb.c:953 #, c-format msgid "file \"%s\" is not a regular file" msgstr "файл \"%s\" не є звичайним файлом" -#: initdb.c:1077 +#: initdb.c:1086 #, c-format msgid "selecting dynamic shared memory implementation ... " msgstr "обирається реалізація динамічної спільної пам'яті ... " -#: initdb.c:1086 +#: initdb.c:1095 #, c-format -msgid "selecting default max_connections ... " -msgstr "" -"обирається значення max_connections ... \n" +msgid "selecting default \"max_connections\" ... " +msgstr "обирається значення \"max_connections\" за замовчуванням... \n" " " -#: initdb.c:1106 +#: initdb.c:1115 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "обирається значення shared_buffers... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "обирається значення \"shared_buffers\" за замовчуванням... " -#: initdb.c:1129 +#: initdb.c:1138 #, c-format msgid "selecting default time zone ... " msgstr "обирається часовий пояс за замовчуванням ... " -#: initdb.c:1206 +#: initdb.c:1217 msgid "creating configuration files ... " msgstr "створення конфігураційних файлів... " -#: initdb.c:1367 initdb.c:1381 initdb.c:1448 initdb.c:1459 +#: initdb.c:1370 initdb.c:1384 initdb.c:1451 initdb.c:1462 #, c-format msgid "could not change permissions of \"%s\": %m" msgstr "неможливо змінити дозволи \"%s\": %m" -#: initdb.c:1477 +#: initdb.c:1481 #, c-format msgid "running bootstrap script ... " msgstr "виконуємо сценарій ініціалізації ... " -#: initdb.c:1489 +#: initdb.c:1493 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" msgstr "вхідний файл \"%s\" не належить PostgreSQL %s" -#: initdb.c:1491 +#: initdb.c:1495 #, c-format msgid "Specify the correct path using the option -L." msgstr "Вкажіть правильний шлях за допомогою параметру -L." -#: initdb.c:1591 +#: initdb.c:1597 msgid "Enter new superuser password: " msgstr "Введіть новий пароль для superuser: " -#: initdb.c:1592 +#: initdb.c:1598 msgid "Enter it again: " msgstr "Введіть знову: " -#: initdb.c:1595 +#: initdb.c:1601 #, c-format msgid "Passwords didn't match.\n" msgstr "Паролі не співпадають.\n" -#: initdb.c:1619 +#: initdb.c:1625 #, c-format msgid "could not read password from file \"%s\": %m" msgstr "не вдалося прочитати пароль з файлу \"%s\": %m" -#: initdb.c:1622 +#: initdb.c:1628 #, c-format msgid "password file \"%s\" is empty" msgstr "файл з паролями \"%s\" є порожнім" -#: initdb.c:2034 +#: initdb.c:2040 #, c-format msgid "caught signal\n" msgstr "отримано сигнал\n" -#: initdb.c:2040 +#: initdb.c:2046 #, c-format msgid "could not write to child process: %s\n" msgstr "не вдалося написати у дочірній процес: %s\n" -#: initdb.c:2048 +#: initdb.c:2054 #, c-format msgid "ok\n" msgstr "ok\n" -#: initdb.c:2137 +#: initdb.c:2143 #, c-format msgid "setlocale() failed" msgstr "setlocale() завершився невдало" -#: initdb.c:2155 +#: initdb.c:2161 #, c-format msgid "failed to restore old locale \"%s\"" msgstr "не вдалося відновити стару локаль \"%s\"" -#: initdb.c:2163 +#: initdb.c:2169 #, c-format msgid "invalid locale name \"%s\"" msgstr "не допустиме ім'я локалі \"%s\"" -#: initdb.c:2164 +#: initdb.c:2170 #, c-format msgid "If the locale name is specific to ICU, use --icu-locale." msgstr "Якщо ім'я локалі характерне для ICU, використовуйте --icu-locale." -#: initdb.c:2177 +#: initdb.c:2183 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" msgstr "неприпустимі параметри локалі; перевірте LANG та LC_* змінні середовища" -#: initdb.c:2203 initdb.c:2227 +#: initdb.c:2209 initdb.c:2233 #, c-format msgid "encoding mismatch" msgstr "невідповідність кодування" -#: initdb.c:2204 +#: initdb.c:2210 #, c-format msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." msgstr "Вибране вами кодування (%s) і кодування, яке використовує обрана локаль (%s) не збігаються. Це призведе до неправильної поведінки у різних функціях обробки символьних рядків." -#: initdb.c:2209 initdb.c:2230 +#: initdb.c:2215 initdb.c:2236 #, c-format msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." msgstr "Перезапустіть %s і або не вказуйте кодування прямо або виберіть відповідну комбінацію." -#: initdb.c:2228 +#: initdb.c:2234 #, c-format msgid "The encoding you selected (%s) is not supported with the ICU provider." msgstr "Обране вами кодування (%s) не підтримується провайдером ICU." -#: initdb.c:2279 +#: initdb.c:2285 #, c-format msgid "could not convert locale name \"%s\" to language tag: %s" msgstr "не вдалося перетворити локальну назву \"%s\" на мітку мови: %s" -#: initdb.c:2285 initdb.c:2337 initdb.c:2416 +#: initdb.c:2291 initdb.c:2343 initdb.c:2435 #, c-format msgid "ICU is not supported in this build" msgstr "ICU не підтримується в цій збірці" -#: initdb.c:2308 +#: initdb.c:2314 #, c-format msgid "could not get language from locale \"%s\": %s" msgstr "не вдалося отримати мову з локалі \"%s\": %s" -#: initdb.c:2334 +#: initdb.c:2340 #, c-format msgid "locale \"%s\" has unknown language \"%s\"" msgstr "locale \"%s\" має невідому мову \"%s\"" -#: initdb.c:2400 +#: initdb.c:2401 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "потрібно вказати локаль для провайдера %s" + +#: initdb.c:2412 #, c-format -msgid "ICU locale must be specified" -msgstr "Необхідно вказати локаль ICU" +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "неприпустиме ім'я локалі \"%s\" для вбудованого провайдера" -#: initdb.c:2404 +#: initdb.c:2423 #, c-format msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" msgstr "Використання мітки мови \"%s\" для локалі ICU \"%s\".\n" -#: initdb.c:2427 +#: initdb.c:2446 #, c-format -msgid "" -"%s initializes a PostgreSQL database cluster.\n" -"\n" -msgstr "" -"%s ініціалізує кластер баз даних PostgreSQL.\n" -"\n" +msgid "%s initializes a PostgreSQL database cluster.\n\n" +msgstr "%s ініціалізує кластер баз даних PostgreSQL.\n\n" -#: initdb.c:2428 +#: initdb.c:2447 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: initdb.c:2429 +#: initdb.c:2448 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATADIR]\n" -#: initdb.c:2430 +#: initdb.c:2449 #, c-format -msgid "" -"\n" +msgid "\n" "Options:\n" -msgstr "" -"\n" +msgstr "\n" "Параметри:\n" -#: initdb.c:2431 +#: initdb.c:2450 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, -- auth=METHOD метод аутентифікації за замовчуванням для локальних підключень\n" -#: initdb.c:2432 +#: initdb.c:2451 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" msgstr " --auth-host=METHOD метод аутентифікації за замовчуванням для локального TCP/IP підключення\n" -#: initdb.c:2433 +#: initdb.c:2452 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" msgstr " --auth-local=METHOD метод аутентифікації за замовчуванням для локального під'єднання через сокет\n" -#: initdb.c:2434 +#: initdb.c:2453 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" msgstr " [-D - pgdata =] DATADIR розташування кластеру цієї бази даних\n" -#: initdb.c:2435 +#: initdb.c:2454 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=ENCODING встановлення кодування за замовчуванням для нової бази даних\n" -#: initdb.c:2436 +#: initdb.c:2455 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr " -g, --allow-group-access дозволити читати/виконувати у каталозі даних для групи\n" -#: initdb.c:2437 +#: initdb.c:2456 #, c-format msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" msgstr " --icu-locale=LOCALE встановлює ідентифікатор мови ICU для нових баз даних\n" -#: initdb.c:2438 +#: initdb.c:2457 #, c-format msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" msgstr " --icu-rules=RULES встановити додаткові правила сортування в ICU для нових баз даних\n" -#: initdb.c:2439 +#: initdb.c:2458 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums використовувати контрольні суми сторінок\n" -#: initdb.c:2440 +#: initdb.c:2459 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" msgstr " --locale=LOCALE встановлює локаль за замовчуванням для нових баз даних\n" -#: initdb.c:2441 +#: initdb.c:2460 #, c-format -msgid "" -" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" +msgid " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" " --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n" " set default locale in the respective category for\n" " new databases (default taken from environment)\n" -msgstr "" -" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" +msgstr " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" " --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n" " встановлення локалі за замовчуванням для відповідної категорії в\n" " нових базах даних (замість значення з середовища)\n" -#: initdb.c:2445 +#: initdb.c:2464 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale еквівалентно --locale=C\n" -#: initdb.c:2446 +#: initdb.c:2465 #, c-format -msgid "" -" --locale-provider={libc|icu}\n" +msgid " --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr " --builtin-locale=LOCALE\n" +" встановити ім'я вбудованої локалі для нових баз даних\n" + +#: initdb.c:2467 +#, c-format +msgid " --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n" -msgstr "" -" --locale-provider={libc|icu}\n" +msgstr " --locale-provider={builtin|libc|icu}\n" " встановлює провайдер локалі за замовченням для нових баз даних\n" -#: initdb.c:2448 +#: initdb.c:2469 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" msgstr " --pwfile=FILE прочитати пароль для нового суперкористувача з файлу\n" -#: initdb.c:2449 +#: initdb.c:2470 #, c-format -msgid "" -" -T, --text-search-config=CFG\n" +msgid " -T, --text-search-config=CFG\n" " default text search configuration\n" msgstr " -T, --text-search-config=CFG конфігурація текстового пошуку за замовчуванням\n" -#: initdb.c:2451 +#: initdb.c:2472 #, c-format msgid " -U, --username=NAME database superuser name\n" msgstr " -U, --username=NAME ім'я суперкористувача бази даних\n" -#: initdb.c:2452 +#: initdb.c:2473 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" msgstr " -W, --pwprompt запитувати пароль нового суперкористувача\n" -#: initdb.c:2453 +#: initdb.c:2474 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR розташування журналу попереднього запису\n" -#: initdb.c:2454 +#: initdb.c:2475 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE розмір сегментів WAL у мегабайтах\n" -#: initdb.c:2455 +#: initdb.c:2476 #, c-format -msgid "" -"\n" +msgid "\n" "Less commonly used options:\n" -msgstr "" -"\n" +msgstr "\n" "Рідковживані параметри:\n" -#: initdb.c:2456 +#: initdb.c:2477 #, c-format msgid " -c, --set NAME=VALUE override default setting for server parameter\n" msgstr " -c, --set NAME=VALUE перевизначити параметр за замовчуванням для параметра сервера\n" -#: initdb.c:2457 +#: initdb.c:2478 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug генерувати багато налагоджувальних повідомлень\n" -#: initdb.c:2458 +#: initdb.c:2479 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" msgstr " --discard-caches встановити debug_discard_caches=1\n" -#: initdb.c:2459 +#: initdb.c:2480 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L DIRECTORY розташування вхідних файлів\n" -#: initdb.c:2460 +#: initdb.c:2481 #, c-format msgid " -n, --no-clean do not clean up after errors\n" -msgstr "" -" -n, --no-clean не очищувати після помилок\n" +msgstr " -n, --no-clean не очищувати після помилок\n" " \n" -#: initdb.c:2461 +#: initdb.c:2482 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync не чекати на безпечний запис змін на диск\n" -#: initdb.c:2462 +#: initdb.c:2483 #, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions не друкувати інструкції для наступних кроків\n" -#: initdb.c:2463 +#: initdb.c:2484 #, c-format -msgid " -s, --show show internal settings\n" -msgstr " -s, --show показати внутрішні налаштування\n" +msgid " -s, --show show internal settings, then exit\n" +msgstr " -s, --show показати внутрішні налаштування і вийти\n" -#: initdb.c:2464 +#: initdb.c:2485 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод синхронізації файлів на диск\n" + +#: initdb.c:2486 #, c-format msgid " -S, --sync-only only sync database files to disk, then exit\n" msgstr " -S, --sync-only лише синхронізувати файли бази даних на диск, потім вийти\n" -#: initdb.c:2465 +#: initdb.c:2487 #, c-format -msgid "" -"\n" +msgid "\n" "Other options:\n" -msgstr "" -"\n" +msgstr "\n" "Інші параметри:\n" -#: initdb.c:2466 +#: initdb.c:2488 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: initdb.c:2467 +#: initdb.c:2489 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: initdb.c:2468 +#: initdb.c:2490 #, c-format -msgid "" -"\n" +msgid "\n" "If the data directory is not specified, the environment variable PGDATA\n" "is used.\n" -msgstr "" -"\n" +msgstr "\n" "Якщо каталог даних не вказано, використовується змінна середовища PGDATA.\n" -#: initdb.c:2470 +#: initdb.c:2492 #, c-format -msgid "" -"\n" +msgid "\n" "Report bugs to <%s>.\n" -msgstr "" -"\n" +msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: initdb.c:2471 +#: initdb.c:2493 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: initdb.c:2499 +#: initdb.c:2517 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" msgstr "неприпустимий спосіб автентифікації \"%s\" для \"%s\" підключення" -#: initdb.c:2513 +#: initdb.c:2531 #, c-format msgid "must specify a password for the superuser to enable password authentication" msgstr "необхідно вказати пароль суперкористувача для активації автентифікації за допомогою пароля" -#: initdb.c:2532 +#: initdb.c:2550 #, c-format msgid "no data directory specified" msgstr "каталог даних не вказано" -#: initdb.c:2533 +#: initdb.c:2551 #, c-format msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." msgstr "Ви повинні зазначити каталог, де будуть зберігатися дані цієї системи баз даних. Зробіть це або параметром -D, або змінною середовища PGDATA." -#: initdb.c:2550 +#: initdb.c:2568 #, c-format msgid "could not set environment" msgstr "не вдалося встановити середовище" -#: initdb.c:2568 +#: initdb.c:2586 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\"" -#: initdb.c:2571 +#: initdb.c:2589 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "програма \"%s\" знайдена для \"%s\", але має відмінну версію від %s" -#: initdb.c:2586 +#: initdb.c:2604 #, c-format msgid "input file location must be an absolute path" msgstr "розташування вхідного файлу має бути абсолютним шляхом" -#: initdb.c:2603 +#: initdb.c:2621 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" msgstr "Кластер бази даних буде ініціалізовано з локалізацією \"%s\".\n" -#: initdb.c:2606 +#: initdb.c:2624 #, c-format msgid "The database cluster will be initialized with this locale configuration:\n" msgstr "Кластер бази даних буде ініціалізовано з локалізацією:\n" -#: initdb.c:2607 +#: initdb.c:2625 #, c-format -msgid " provider: %s\n" -msgstr " постачальник: %s\n" +msgid " locale provider: %s\n" +msgstr " провайдер локалі: %s\n" -#: initdb.c:2609 +#: initdb.c:2627 #, c-format -msgid " ICU locale: %s\n" -msgstr " Локаль ICU: %s\n" +msgid " default collation: %s\n" +msgstr " стандартне сортування: %s\n" -#: initdb.c:2610 +#: initdb.c:2628 #, c-format -msgid "" -" LC_COLLATE: %s\n" +msgid " LC_COLLATE: %s\n" " LC_CTYPE: %s\n" " LC_MESSAGES: %s\n" " LC_MONETARY: %s\n" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -msgstr "" -" LC_COLLATE: %s\n" +msgstr " LC_COLLATE: %s\n" " LC_CTYPE: %s\n" " LC_MESSAGES: %s\n" " LC_MONETARY: %s\n" " LC_NUMERIC: %s\n" " LC_TIME: %s\n" -#: initdb.c:2640 +#: initdb.c:2658 #, c-format msgid "could not find suitable encoding for locale \"%s\"" msgstr "не вдалося знайти відповідне кодування для локалі \"%s\"" -#: initdb.c:2642 +#: initdb.c:2660 #, c-format msgid "Rerun %s with the -E option." msgstr "Перезапустіть %s з параметром -E." -#: initdb.c:2643 initdb.c:3176 initdb.c:3284 initdb.c:3304 +#: initdb.c:2661 initdb.c:3204 initdb.c:3324 initdb.c:3344 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: initdb.c:2655 +#: initdb.c:2673 #, c-format -msgid "" -"Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" +msgid "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" "The default database encoding will be set to \"%s\" instead.\n" -msgstr "" -"Кодування \"%s\", що очікується локалізацією, не дозволено у якості кодування сервера.\n" +msgstr "Кодування \"%s\", що очікується локалізацією, не дозволено у якості кодування сервера.\n" "Замість нього буде встановлене кодування \"%s\" за замовчуванням.\n" -#: initdb.c:2660 +#: initdb.c:2678 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" msgstr "локалізація \"%s\" потребує кодування \"%s\", що не підтримується" -#: initdb.c:2662 +#: initdb.c:2680 #, c-format msgid "Encoding \"%s\" is not allowed as a server-side encoding." msgstr "Кодування \"%s\" не допускається як кодування сервера." -#: initdb.c:2664 +#: initdb.c:2682 #, c-format msgid "Rerun %s with a different locale selection." msgstr "Перезапустіть %s з іншим вибором локалі." -#: initdb.c:2672 +#: initdb.c:2690 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "Кодування бази даних за замовчуванням встановлено: \"%s\".\n" -#: initdb.c:2741 +#: initdb.c:2704 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "локаль вбудованого провайдера \"%s\" вимагає кодування \"%s\"" + +#: initdb.c:2766 #, c-format msgid "could not find suitable text search configuration for locale \"%s\"" msgstr "не вдалося знайти відповідну конфігурацію текстового пошуку для локалі\"%s\"" -#: initdb.c:2752 +#: initdb.c:2777 #, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" msgstr "відповідна конфігурація текстового пошуку для локалі \"%s\" невідома" -#: initdb.c:2757 +#: initdb.c:2782 #, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" msgstr "вказана конфігурація текстового пошуку \"%s\" може не підходити локалі \"%s\"" -#: initdb.c:2762 +#: initdb.c:2787 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" msgstr "Конфігурація текстового пошуку за замовчуванням буде встановлена в \"%s\".\n" -#: initdb.c:2805 initdb.c:2876 +#: initdb.c:2830 initdb.c:2901 #, c-format msgid "creating directory %s ... " msgstr "створення каталогу %s... " -#: initdb.c:2810 initdb.c:2881 initdb.c:2929 initdb.c:2985 +#: initdb.c:2835 initdb.c:2906 initdb.c:2954 initdb.c:3011 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не вдалося створити каталог \"%s\": %m" -#: initdb.c:2819 initdb.c:2891 +#: initdb.c:2844 initdb.c:2916 #, c-format msgid "fixing permissions on existing directory %s ... " msgstr "виправляю дозволи для створеного каталогу %s... " -#: initdb.c:2824 initdb.c:2896 +#: initdb.c:2849 initdb.c:2921 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "не вдалося змінити дозволи каталогу \"%s\": %m" -#: initdb.c:2836 initdb.c:2908 +#: initdb.c:2861 initdb.c:2933 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" існує, але він не порожній" -#: initdb.c:2840 +#: initdb.c:2865 #, c-format msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." msgstr "Якщо ви хочете створити нову систему бази даних, видаліть або очистіть каталог \"%s\", або запустіть %s з аргументом, відмінним від \"%s\"." -#: initdb.c:2848 initdb.c:2918 initdb.c:3325 +#: initdb.c:2873 initdb.c:2943 initdb.c:3369 #, c-format msgid "could not access directory \"%s\": %m" msgstr "немає доступу до каталогу \"%s\": %m" -#: initdb.c:2869 +#: initdb.c:2894 #, c-format msgid "WAL directory location must be an absolute path" msgstr "розташування WAL каталогу має бути абсолютним шляхом" -#: initdb.c:2912 +#: initdb.c:2937 #, c-format msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." msgstr "Якщо ви хочете зберігати дані з WAL там, потрібно видалити або очистити директорію \"%s\"." -#: initdb.c:2922 +#: initdb.c:2947 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не вдалося створити символічне послання \"%s\": %m" -#: initdb.c:2941 +#: initdb.c:2966 #, c-format msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." msgstr "Він містить файл з крапкою або невидимий файл, можливо це точка під'єднання." -#: initdb.c:2943 +#: initdb.c:2968 #, c-format msgid "It contains a lost+found directory, perhaps due to it being a mount point." msgstr "Він містить каталог lost+found, можливо це точка під'єднання." -#: initdb.c:2945 +#: initdb.c:2970 #, c-format -msgid "" -"Using a mount point directly as the data directory is not recommended.\n" +msgid "Using a mount point directly as the data directory is not recommended.\n" "Create a subdirectory under the mount point." -msgstr "" -"Не рекомендується використовувати точку під'єднання у якості каталогу даних.\n" +msgstr "Не рекомендується використовувати точку під'єднання у якості каталогу даних.\n" "Створіть підкаталог і використайте його." -#: initdb.c:2971 +#: initdb.c:2997 #, c-format msgid "creating subdirectories ... " msgstr "створення підкаталогів... " -#: initdb.c:3014 +#: initdb.c:3040 msgid "performing post-bootstrap initialization ... " msgstr "виконується кінцева фаза ініціалізації ... " -#: initdb.c:3175 +#: initdb.c:3203 #, c-format msgid "-c %s requires a value" msgstr "-c %s необхідне значення" -#: initdb.c:3200 +#: initdb.c:3228 #, c-format msgid "Running in debug mode.\n" msgstr "Виконується у режимі налагодження.\n" -#: initdb.c:3204 +#: initdb.c:3232 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" msgstr "Виконується у режимі 'no-clean'. Помилки не будуть виправлені.\n" -#: initdb.c:3274 +#: initdb.c:3305 #, c-format msgid "unrecognized locale provider: %s" msgstr "нерозпізнаний постачальник локалів: %s" -#: initdb.c:3302 +#: initdb.c:3342 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: initdb.c:3309 initdb.c:3313 +#: initdb.c:3349 initdb.c:3353 initdb.c:3357 #, c-format msgid "%s cannot be specified unless locale provider \"%s\" is chosen" msgstr "%s не може бути вказано, поки не буде обрано постачальник локалі \"%s\"" -#: initdb.c:3327 initdb.c:3404 +#: initdb.c:3371 initdb.c:3434 msgid "syncing data to disk ... " msgstr "синхронізація даних з диском ... " -#: initdb.c:3335 +#: initdb.c:3379 #, c-format msgid "password prompt and password file cannot be specified together" msgstr "неможливо вказати одночасно пароль і файл паролю" -#: initdb.c:3357 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "аргумент --wal-segsize повинен бути числом" - -#: initdb.c:3359 +#: initdb.c:3390 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "аргумент --wal-segsize повинен бути ступенем 2 між 1 і 1024" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "аргумент %s має бути ступенем двійки в діапазоні від 1 до 1024" -#: initdb.c:3373 +#: initdb.c:3403 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" msgstr "неприпустиме ім'я суперкористувача \"%s\"; імена ролей не можуть починатися на \"pg_\"" -#: initdb.c:3375 +#: initdb.c:3405 #, c-format -msgid "" -"The files belonging to this database system will be owned by user \"%s\".\n" -"This user must also own the server process.\n" -"\n" -msgstr "" -"Файли цієї бази даних будуть належати користувачеві \"%s\".\n" -"Від імені цього користувача повинен запускатися процес сервера.\n" -"\n" +msgid "The files belonging to this database system will be owned by user \"%s\".\n" +"This user must also own the server process.\n\n" +msgstr "Файли цієї бази даних будуть належати користувачеві \"%s\".\n" +"Від імені цього користувача повинен запускатися процес сервера.\n\n" -#: initdb.c:3391 +#: initdb.c:3421 #, c-format msgid "Data page checksums are enabled.\n" msgstr "Контроль цілісності сторінок даних увімкнено.\n" -#: initdb.c:3393 +#: initdb.c:3423 #, c-format msgid "Data page checksums are disabled.\n" msgstr "Контроль цілісності сторінок даних вимкнено.\n" -#: initdb.c:3410 +#: initdb.c:3440 #, c-format -msgid "" -"\n" +msgid "\n" "Sync to disk skipped.\n" "The data directory might become corrupt if the operating system crashes.\n" -msgstr "" -"\n" +msgstr "\n" "Синхронізація з диском пропущена.\n" "Каталог з даними може бути пошкоджено під час аварійного завершення роботи операційної системи.\n" -#: initdb.c:3415 +#: initdb.c:3445 #, c-format msgid "enabling \"trust\" authentication for local connections" msgstr "увімкнення автентифікації \"довіри\" для локальних підключень" -#: initdb.c:3416 +#: initdb.c:3446 #, c-format msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." msgstr "Ви можете змінити це, змінивши pg_hba.conf або скориставшись опцією -A, або --auth-local і --auth-host, наступного разу, коли ви запускаєте initdb." #. translator: This is a placeholder in a shell command. -#: initdb.c:3446 +#: initdb.c:3476 msgid "logfile" msgstr "logfile" -#: initdb.c:3448 +#: initdb.c:3478 #, c-format -msgid "" -"\n" -"Success. You can now start the database server using:\n" -"\n" -" %s\n" -"\n" -msgstr "" -"\n" -"Готово. Тепер ви можете запустити сервер бази даних командою:\n" -"\n" -" %s\n" -"\n" +msgid "\n" +"Success. You can now start the database server using:\n\n" +" %s\n\n" +msgstr "\n" +"Готово. Тепер ви можете запустити сервер бази даних командою:\n\n" +" %s\n\n" + diff --git a/src/bin/initdb/po/zh_CN.po b/src/bin/initdb/po/zh_CN.po index 9876679154c3c..5ffb5e045fe4c 100644 --- a/src/bin/initdb/po/zh_CN.po +++ b/src/bin/initdb/po/zh_CN.po @@ -4,111 +4,135 @@ # msgid "" msgstr "" -"Project-Id-Version: initdb (PostgreSQL) 14\n" +"Project-Id-Version: initdb (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 05:47+0000\n" -"PO-Revision-Date: 2021-08-15 18:00+0800\n" -"Last-Translator: Jie Zhang \n" +"POT-Creation-Date: 2024-05-24 03:30+0000\n" +"PO-Revision-Date: 2024-05-25 16:46+0800\n" +"Last-Translator: Dianjin Wang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.7\n" +"X-Generator: Poedit 3.4.4\n" -#: ../../../src/common/logging.c:259 -#, c-format -msgid "fatal: " -msgstr "致命的: " - -#: ../../../src/common/logging.c:266 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "错误: " -#: ../../../src/common/logging.c:273 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "警告: " -#: ../../common/exec.c:136 ../../common/exec.c:253 ../../common/exec.c:299 +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "详细信息: " + +#: ../../../src/common/logging.c:301 #, c-format -msgid "could not identify current directory: %m" -msgstr "无法确认当前目录: %m" +msgid "hint: " +msgstr "提示: " -#: ../../common/exec.c:155 +#: ../../common/exec.c:174 #, c-format -msgid "invalid binary \"%s\"" -msgstr "无效的二进制码 \"%s\"" +msgid "invalid binary \"%s\": %m" +msgstr "无效的二进制码 \"%s\": %m" -#: ../../common/exec.c:205 +#: ../../common/exec.c:217 #, c-format -msgid "could not read binary \"%s\"" -msgstr "无法读取二进制码 \"%s\"" +msgid "could not read binary \"%s\": %m" +msgstr "无法读取二进制码 \"%s\": %m" -#: ../../common/exec.c:213 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "未能找到一个 \"%s\" 来执行" -#: ../../common/exec.c:269 ../../common/exec.c:308 +#: ../../common/exec.c:252 #, c-format -msgid "could not change directory to \"%s\": %m" -msgstr "无法跳转到目录 \"%s\" 中: %m" +msgid "could not resolve path \"%s\" to absolute form: %m" +msgstr "无法将路径 \"%s\" 解析为绝对路径格式: %m" -#: ../../common/exec.c:286 +#: ../../common/exec.c:382 initdb.c:695 #, c-format -msgid "could not read symbolic link \"%s\": %m" -msgstr "无法读取符号链接 \"%s\": %m" +msgid "could not execute command \"%s\": %m" +msgstr "无法执行命令 \"%s\": %m" -#: ../../common/exec.c:409 +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "无法读取命令 \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "命令 \"%s\" 未返回数据" + +#: ../../common/exec.c:424 +#, c-format msgid "%s() failed: %m" -msgstr "%s()失败: %m" +msgstr "%s() 失败: %m" -#: ../../common/exec.c:522 ../../common/exec.c:567 ../../common/exec.c:659 -#: initdb.c:331 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: initdb.c:353 #, c-format msgid "out of memory" msgstr "内存不足" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 -#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format msgid "out of memory\n" msgstr "内存不足\n" -#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 #, c-format msgid "cannot duplicate null pointer (internal error)\n" msgstr "无法复制空指针 (内部错误)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:451 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "无法打开文件 \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "无法为文件 \"%s\" 同步文件系统: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 #, c-format msgid "could not stat file \"%s\": %m" -msgstr "无法取文件 \"%s\" 的状态: %m" +msgstr "无法获取文件 \"%s\" 的状态: %m" -#: ../../common/file_utils.c:166 ../../common/pgfnames.c:48 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "该版本不支持同步方法 \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/pgfnames.c:48 ../../common/rmtree.c:63 #, c-format msgid "could not open directory \"%s\": %m" msgstr "无法打开目录 \"%s\": %m" -#: ../../common/file_utils.c:200 ../../common/pgfnames.c:69 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/pgfnames.c:69 ../../common/rmtree.c:106 #, c-format msgid "could not read directory \"%s\": %m" msgstr "无法读取目录 \"%s\": %m" -#: ../../common/file_utils.c:232 ../../common/file_utils.c:291 -#: ../../common/file_utils.c:365 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "无法打开文件 \"%s\": %m" - -#: ../../common/file_utils.c:303 ../../common/file_utils.c:373 +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "无法 fsync 文件 \"%s\": %m" -#: ../../common/file_utils.c:383 +#: ../../common/file_utils.c:498 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "无法把文件 \"%s\" 重命名为 \"%s\": %m" @@ -118,60 +142,50 @@ msgstr "无法把文件 \"%s\" 重命名为 \"%s\": %m" msgid "could not close directory \"%s\": %m" msgstr "无法关闭目录 \"%s\": %m" -#: ../../common/restricted_token.c:64 -#, c-format -msgid "could not load library \"%s\": error code %lu" -msgstr "无法加载库 \"%s\": 错误码 %lu" - -#: ../../common/restricted_token.c:73 -#, c-format -msgid "cannot create restricted tokens on this platform: error code %lu" -msgstr "无法为该平台创建受限制的令牌:错误码 %lu" - -#: ../../common/restricted_token.c:82 +#: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" -msgstr "无法打开进程令牌 (token): 错误码 %lu" +msgstr "无法打开进程令牌: 错误码 %lu" -#: ../../common/restricted_token.c:97 +#: ../../common/restricted_token.c:74 #, c-format msgid "could not allocate SIDs: error code %lu" -msgstr "无法分配SID: 错误码 %lu" +msgstr "无法分配 SID: 错误码 %lu" -#: ../../common/restricted_token.c:119 +#: ../../common/restricted_token.c:94 #, c-format msgid "could not create restricted token: error code %lu" -msgstr "无法创建受限令牌: 错误码为 %lu" +msgstr "无法创建受限令牌: 错误码 %lu" -#: ../../common/restricted_token.c:140 +#: ../../common/restricted_token.c:115 #, c-format msgid "could not start process for command \"%s\": error code %lu" -msgstr "无法为命令 \"%s\"创建进程: 错误码 %lu" +msgstr "无法为命令 \"%s\" 创建进程: 错误码 %lu" -#: ../../common/restricted_token.c:178 +#: ../../common/restricted_token.c:153 #, c-format msgid "could not re-execute with restricted token: error code %lu" msgstr "无法使用受限令牌再次执行: 错误码 %lu" -#: ../../common/restricted_token.c:194 +#: ../../common/restricted_token.c:168 #, c-format msgid "could not get exit code from subprocess: error code %lu" -msgstr "无法从子进程得到退出码: 错误码 %lu" +msgstr "无法从子进程获取退出码: 错误码 %lu" -#: ../../common/rmtree.c:79 +#: ../../common/rmtree.c:97 #, c-format -msgid "could not stat file or directory \"%s\": %m" -msgstr "无法统计文件或目录\"%s\": %m" +msgid "could not remove file \"%s\": %m" +msgstr "无法删除文件 \"%s\": %m" -#: ../../common/rmtree.c:101 ../../common/rmtree.c:113 +#: ../../common/rmtree.c:124 #, c-format -msgid "could not remove file or directory \"%s\": %m" -msgstr "无法删除文件或目录 \"%s\": %m" +msgid "could not remove directory \"%s\": %m" +msgstr "无法删除目录 \"%s\": %m" #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" -msgstr "无法找到有效的用户ID %ld: %s" +msgstr "无法找到有效的用户 ID %ld: %s" #: ../../common/username.c:45 msgid "user does not exist" @@ -180,302 +194,350 @@ msgstr "用户不存在" #: ../../common/username.c:60 #, c-format msgid "user name lookup failure: error code %lu" -msgstr "用户名查找失败:错误代码%lu" +msgstr "用户名查找失败: 错误码 %lu" -#: ../../common/wait_error.c:45 +#: ../../common/wait_error.c:55 #, c-format msgid "command not executable" -msgstr "无法执行命令" +msgstr "命令无法执行" -#: ../../common/wait_error.c:49 +#: ../../common/wait_error.c:59 #, c-format msgid "command not found" msgstr "命令没有找到" -#: ../../common/wait_error.c:54 +#: ../../common/wait_error.c:64 #, c-format msgid "child process exited with exit code %d" msgstr "子进程已退出, 退出码为 %d" -#: ../../common/wait_error.c:62 +#: ../../common/wait_error.c:72 #, c-format msgid "child process was terminated by exception 0x%X" -msgstr "子进程被例外(exception) 0x%X 终止" +msgstr "子进程被异常 0x%X 终止" -#: ../../common/wait_error.c:66 +#: ../../common/wait_error.c:76 #, c-format msgid "child process was terminated by signal %d: %s" msgstr "子进程被信号 %d 终止: %s" -#: ../../common/wait_error.c:72 +#: ../../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" msgstr "子进程已退出, 未知状态 %d" -#: ../../port/dirmod.c:221 +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 是选项 %s 的无效值" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 必须位于 %d..%d 的范围内" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "无法识别同步方法: %s" + +#: ../../port/dirmod.c:287 #, c-format msgid "could not set junction for \"%s\": %s\n" -msgstr "无法为 \"%s\"设置连接: %s\n" +msgstr "无法为 \"%s\" 设置连接: %s\n" -#: ../../port/dirmod.c:298 +#: ../../port/dirmod.c:367 #, c-format msgid "could not get junction for \"%s\": %s\n" -msgstr "无法为\"%s\"得到连接: %s\n" +msgstr "无法为 \"%s\" 获取连接: %s\n" -#: initdb.c:464 initdb.c:1496 +#: initdb.c:627 initdb.c:1619 #, c-format msgid "could not open file \"%s\" for reading: %m" -msgstr "为了读取, 无法打开文件 \"%s\": %m" +msgstr "无法打开文件 \"%s\" 进行读取: %m" -#: initdb.c:508 initdb.c:830 initdb.c:856 +#: initdb.c:671 initdb.c:975 initdb.c:995 #, c-format msgid "could not open file \"%s\" for writing: %m" -msgstr "为了写入, 无法打开文件 \"%s\": %m" +msgstr "无法打开文件 \"%s\" 进行写入: %m" -#: initdb.c:515 initdb.c:522 initdb.c:836 initdb.c:861 +#: initdb.c:675 initdb.c:978 initdb.c:997 #, c-format msgid "could not write file \"%s\": %m" msgstr "无法写入文件 \"%s\": %m" -#: initdb.c:540 +#: initdb.c:679 #, c-format -msgid "could not execute command \"%s\": %m" -msgstr "无法执行命令 \"%s\": %m" +msgid "could not close file \"%s\": %m" +msgstr "无法关闭文件 \"%s\": %m" -#: initdb.c:558 +#: initdb.c:713 #, c-format msgid "removing data directory \"%s\"" -msgstr "删除数据目录 \"%s\"" +msgstr "正在删除数据目录 \"%s\"" -#: initdb.c:560 +#: initdb.c:715 #, c-format msgid "failed to remove data directory" msgstr "删除数据目录失败" -#: initdb.c:564 +#: initdb.c:719 #, c-format msgid "removing contents of data directory \"%s\"" -msgstr "删除数据目录 \"%s\" 的内容" +msgstr "正在删除数据目录 \"%s\" 的内容" -#: initdb.c:567 +#: initdb.c:722 #, c-format msgid "failed to remove contents of data directory" msgstr "删除数据目录内容失败" -#: initdb.c:572 +#: initdb.c:727 #, c-format msgid "removing WAL directory \"%s\"" -msgstr "正在删除WAL目录\"%s\"" +msgstr "正在删除 WAL 目录 \"%s\"" -#: initdb.c:574 +#: initdb.c:729 #, c-format msgid "failed to remove WAL directory" -msgstr "删除WAL目录失败" +msgstr "删除 WAL 目录失败" -#: initdb.c:578 +#: initdb.c:733 #, c-format msgid "removing contents of WAL directory \"%s\"" -msgstr "正在删除WAL目录 \"%s\" 的内容" +msgstr "正在删除 WAL 目录 \"%s\" 的内容" -#: initdb.c:580 +#: initdb.c:735 #, c-format msgid "failed to remove contents of WAL directory" -msgstr "删除WAL目录内容失败" +msgstr "删除 WAL 目录内容失败" -#: initdb.c:587 +#: initdb.c:742 #, c-format msgid "data directory \"%s\" not removed at user's request" -msgstr "在用户的要求下数据库目录 \"%s\" 不被删除" +msgstr "依照用户要求数据库目录 \"%s\" 不被删除" -#: initdb.c:591 +#: initdb.c:746 #, c-format msgid "WAL directory \"%s\" not removed at user's request" -msgstr "在用户的要求下WAL目录 \"%s\" 不被删除" +msgstr "依照用户要求 WAL 目录 \"%s\" 不被删除" -#: initdb.c:609 +#: initdb.c:764 #, c-format msgid "cannot be run as root" -msgstr "不能使用root用户运行" +msgstr "无法以 root 身份运行" -#: initdb.c:611 +#: initdb.c:765 #, c-format -msgid "" -"Please log in (using, e.g., \"su\") as the (unprivileged) user that will\n" -"own the server process.\n" -msgstr "" -"请以服务器进程所有者的用户 (无特权) 身份\n" -"登陆 (使用, e.g., \"su\").\n" +msgid "Please log in (using, e.g., \"su\") as the (unprivileged) user that will own the server process." +msgstr "请以拥有服务器进程的 (无特权) 用户身份登录 (例如使用 \"su\")." -#: initdb.c:644 +#: initdb.c:797 #, c-format msgid "\"%s\" is not a valid server encoding name" -msgstr "\"%s\" 不是一个有效的服务器编码名字" +msgstr "\"%s\" 不是一个有效的服务器编码名称" -#: initdb.c:789 +#: initdb.c:941 #, c-format msgid "file \"%s\" does not exist" msgstr "文件 \"%s\" 不存在" -#: initdb.c:791 initdb.c:798 initdb.c:807 +#: initdb.c:942 initdb.c:947 initdb.c:954 #, c-format -msgid "" -"This might mean you have a corrupted installation or identified\n" -"the wrong directory with the invocation option -L.\n" -msgstr "" -"这意味着您的安装发生了错误或\n" -"使用 -L 选项指定了错误的路径.\n" +msgid "This might mean you have a corrupted installation or identified the wrong directory with the invocation option -L." +msgstr "这意味着你的安装发生了错误或使用 -L 选项指定了错误的目录." -#: initdb.c:796 +#: initdb.c:946 #, c-format msgid "could not access file \"%s\": %m" msgstr "无法访问文件 \"%s\": %m" -#: initdb.c:805 +#: initdb.c:953 #, c-format msgid "file \"%s\" is not a regular file" msgstr "文件 \"%s\" 不是常规文件" -#: initdb.c:950 +#: initdb.c:1086 #, c-format msgid "selecting dynamic shared memory implementation ... " -msgstr "选择动态共享内存实现 ......" +msgstr "正在选择动态共享内存实现 ... " -#: initdb.c:959 +#: initdb.c:1095 #, c-format -msgid "selecting default max_connections ... " -msgstr "选择默认最大联接数 (max_connections) ... " +msgid "selecting default \"max_connections\" ... " +msgstr "正在选择默认最大连接数 (max_connections) ... " -#: initdb.c:990 +#: initdb.c:1115 #, c-format -msgid "selecting default shared_buffers ... " -msgstr "选择默认共享缓冲区大小 (shared_buffers) ... " +msgid "selecting default \"shared_buffers\" ... " +msgstr "正在选择默认共享缓冲区 (shared_buffers) ... " -#: initdb.c:1024 +#: initdb.c:1138 +#, c-format msgid "selecting default time zone ... " -msgstr "选择默认时区 ... " +msgstr "正在选择默认时区 ... " -#: initdb.c:1058 +#: initdb.c:1217 msgid "creating configuration files ... " -msgstr "创建配置文件 ... " +msgstr "正在创建配置文件 ... " -#: initdb.c:1217 initdb.c:1236 initdb.c:1322 initdb.c:1337 +#: initdb.c:1370 initdb.c:1384 initdb.c:1451 initdb.c:1462 #, c-format msgid "could not change permissions of \"%s\": %m" -msgstr "无法改变\"%s\"的权限: %m" +msgstr "无法改变 \"%s\" 的权限: %m" -#: initdb.c:1359 +#: initdb.c:1481 #, c-format msgid "running bootstrap script ... " -msgstr "正在运行自举脚本 ..." +msgstr "正在运行启动脚本 ... " -#: initdb.c:1371 +#: initdb.c:1493 #, c-format msgid "input file \"%s\" does not belong to PostgreSQL %s" -msgstr "输入文件 \"%s\" 不属于PostgreSQL %s" +msgstr "输入文件 \"%s\" 不属于 PostgreSQL %s" -#: initdb.c:1374 +#: initdb.c:1495 #, c-format -msgid "Check your installation or specify the correct path using the option -L.\n" -msgstr "检查你的安装或使用 -L 选项指定正确的路径.\n" +msgid "Specify the correct path using the option -L." +msgstr "使用 -L 选项指定正确的路径." -#: initdb.c:1473 +#: initdb.c:1597 msgid "Enter new superuser password: " -msgstr "输入新的超级用户口令: " +msgstr "输入新的超级用户密码: " -#: initdb.c:1474 +#: initdb.c:1598 msgid "Enter it again: " msgstr "再输入一遍: " -#: initdb.c:1477 +#: initdb.c:1601 #, c-format msgid "Passwords didn't match.\n" -msgstr "口令不匹配.\n" +msgstr "密码不匹配.\n" -#: initdb.c:1504 +#: initdb.c:1625 #, c-format msgid "could not read password from file \"%s\": %m" -msgstr "无法从文件 \"%s\" 读取口令: %m" +msgstr "无法从文件 \"%s\" 读取密码: %m" -#: initdb.c:1507 +#: initdb.c:1628 #, c-format msgid "password file \"%s\" is empty" -msgstr "口令文件\"%s\"为空" +msgstr "密码文件 \"%s\" 为空" -#: initdb.c:1998 +#: initdb.c:2040 #, c-format msgid "caught signal\n" msgstr "捕获信号\n" -#: initdb.c:2004 +#: initdb.c:2046 #, c-format msgid "could not write to child process: %s\n" -msgstr "无法写到子进程: %s\n" +msgstr "无法写入子进程: %s\n" -#: initdb.c:2012 +#: initdb.c:2054 #, c-format msgid "ok\n" msgstr "成功\n" -#: initdb.c:2102 +#: initdb.c:2143 #, c-format msgid "setlocale() failed" -msgstr "setlocale()调用失败" +msgstr "setlocale() 调用失败" -#: initdb.c:2123 +#: initdb.c:2161 #, c-format msgid "failed to restore old locale \"%s\"" -msgstr "还原旧区域\"%s\"失败" +msgstr "恢复旧区域设置 \"%s\" 失败" -#: initdb.c:2132 +#: initdb.c:2169 #, c-format msgid "invalid locale name \"%s\"" -msgstr "无效的语言环境名称 \"%s\"" +msgstr "无效的区域设置名称 \"%s\"" -#: initdb.c:2143 +#: initdb.c:2170 +#, c-format +msgid "If the locale name is specific to ICU, use --icu-locale." +msgstr "如果将区域设置名称指定为 ICU, 请使用 --icu-locale." + +#: initdb.c:2183 #, c-format msgid "invalid locale settings; check LANG and LC_* environment variables" -msgstr "无效的本地化设置; 请检查环境变量LANG和LC_*的值" +msgstr "无效的区域设置; 请检查环境变量 LANG 和 LC_* 的值" -#: initdb.c:2170 +#: initdb.c:2209 initdb.c:2233 #, c-format msgid "encoding mismatch" msgstr "编码不匹配" -#: initdb.c:2172 +#: initdb.c:2210 #, c-format -msgid "" -"The encoding you selected (%s) and the encoding that the\n" -"selected locale uses (%s) do not match. This would lead to\n" -"misbehavior in various character string processing functions.\n" -"Rerun %s and either do not specify an encoding explicitly,\n" -"or choose a matching combination.\n" -msgstr "" -"您选择的编码 (%s) 和所选择的语言环境使用的编码 (%s) 不匹配的.\n" -"这样将导致处理不同字符串的函数时产生错误.\n" -"要修复此问题, 重新运行 %s 并且不要明确指定编码, 或者先选择一个匹配\n" -"组合类型.\n" -"\n" +msgid "The encoding you selected (%s) and the encoding that the selected locale uses (%s) do not match. This would lead to misbehavior in various character string processing functions." +msgstr "你选择的编码 (%s) 和所选择的区域设置使用的编码 (%s) 不匹配. 这将导致不同字符串处理函数时产生错误." + +#: initdb.c:2215 initdb.c:2236 +#, c-format +msgid "Rerun %s and either do not specify an encoding explicitly, or choose a matching combination." +msgstr "请重新运行 %s, 且不要显示指定编码, 或选择一个匹配的组合." + +#: initdb.c:2234 +#, c-format +msgid "The encoding you selected (%s) is not supported with the ICU provider." +msgstr "你所选择的编码 (%s) 不受 ICU 支持程序支持." + +#: initdb.c:2285 +#, c-format +msgid "could not convert locale name \"%s\" to language tag: %s" +msgstr "无法将区域设置名称 \"%s\" 转换为语言标签: %s" + +#: initdb.c:2291 initdb.c:2343 initdb.c:2435 +#, c-format +msgid "ICU is not supported in this build" +msgstr "该版本不支持 ICU" + +#: initdb.c:2314 +#, c-format +msgid "could not get language from locale \"%s\": %s" +msgstr "无法从区域设置 \"%s\" 获取语言: %s" + +#: initdb.c:2340 +#, c-format +msgid "locale \"%s\" has unknown language \"%s\"" +msgstr "区域设置 \"%s\" 拥有未知的语言 \"%s\"" + +#: initdb.c:2401 +#, c-format +msgid "locale must be specified if provider is %s" +msgstr "如果支持程序为 %s 必须指定区域设置" + +#: initdb.c:2412 +#, c-format +msgid "invalid locale name \"%s\" for builtin provider" +msgstr "\"%s\" 是内置支持程序的无效区域设置名称" + +#: initdb.c:2423 +#, c-format +msgid "Using language tag \"%s\" for ICU locale \"%s\".\n" +msgstr "使用语言标签 \"%s\" 用于 ICU 区域设置 \"%s\".\n" -#: initdb.c:2244 +#: initdb.c:2446 #, c-format msgid "" "%s initializes a PostgreSQL database cluster.\n" "\n" msgstr "" -"%s 初始化一个 PostgreSQL 数据库簇.\n" +"%s 初始化一个 PostgreSQL 数据库集簇.\n" "\n" -#: initdb.c:2245 +#: initdb.c:2447 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: initdb.c:2246 +#: initdb.c:2448 #, c-format msgid " %s [OPTION]... [DATADIR]\n" -msgstr " %s [选项]... [DATADIR]\n" +msgstr " %s [选项]... [数据目录]\n" -#: initdb.c:2247 +#: initdb.c:2449 #, c-format msgid "" "\n" @@ -484,47 +546,57 @@ msgstr "" "\n" "选项:\n" -#: initdb.c:2248 +#: initdb.c:2450 #, c-format msgid " -A, --auth=METHOD default authentication method for local connections\n" msgstr " -A, --auth=METHOD 本地连接的默认认证方法\n" -#: initdb.c:2249 +#: initdb.c:2451 #, c-format msgid " --auth-host=METHOD default authentication method for local TCP/IP connections\n" -msgstr " --auth-host=METHOD 本地的TCP/IP连接的默认认证方法\n" +msgstr " --auth-host=METHOD 本地的 TCP/IP 连接的默认认证方法\n" -#: initdb.c:2250 +#: initdb.c:2452 #, c-format msgid " --auth-local=METHOD default authentication method for local-socket connections\n" -msgstr " --auth-local=METHOD 本地socket连接的默认认证方法\n" +msgstr " --auth-local=METHOD 本地 socket 连接的默认认证方法\n" -#: initdb.c:2251 +#: initdb.c:2453 #, c-format msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" -msgstr " -D, --pgdata=DATADIR 当前数据库簇的位置\n" +msgstr " [-D, --pgdata=]DATADIR 当前数据库集簇的位置\n" -#: initdb.c:2252 +#: initdb.c:2454 #, c-format msgid " -E, --encoding=ENCODING set default encoding for new databases\n" msgstr " -E, --encoding=ENCODING 为新数据库设置默认编码\n" -#: initdb.c:2253 +#: initdb.c:2455 #, c-format msgid " -g, --allow-group-access allow group read/execute on data directory\n" msgstr " -g, --allow-group-access 允许组对数据目录进行读/执行\n" -#: initdb.c:2254 +#: initdb.c:2456 +#, c-format +msgid " --icu-locale=LOCALE set ICU locale ID for new databases\n" +msgstr " --icu-locale=LOCALE 为新数据库设置 ICU 区域环境 ID\n" + +#: initdb.c:2457 +#, c-format +msgid " --icu-rules=RULES set additional ICU collation rules for new databases\n" +msgstr " --icu-rules=RULES 为新数据库设置额外的 ICU 排序规则\n" + +#: initdb.c:2458 #, c-format msgid " -k, --data-checksums use data page checksums\n" msgstr " -k, --data-checksums 使用数据页产生效验和\n" -#: initdb.c:2255 +#: initdb.c:2459 #, c-format msgid " --locale=LOCALE set default locale for new databases\n" -msgstr " --locale=LOCALE 为新数据库设置默认语言环境\n" +msgstr " --locale=LOCALE 为新数据库设置默认区域环境\n" -#: initdb.c:2256 +#: initdb.c:2460 #, c-format msgid "" " --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n" @@ -534,97 +606,126 @@ msgid "" msgstr "" " --lc-collate, --lc-ctype, --lc-messages=LOCALE\n" " --lc-monetary, --lc-numeric, --lc-time=LOCALE\n" -" 为新的数据库簇在各自的目录中分别\n" -" 设定缺省语言环境(默认使用环境变量)\n" +" 为新的数据库集簇在各自的目录中分别\n" +" 设置默认区域环境(默认使用环境变量)\n" -#: initdb.c:2260 +#: initdb.c:2464 #, c-format msgid " --no-locale equivalent to --locale=C\n" msgstr " --no-locale 等同于 --locale=C\n" -#: initdb.c:2261 +#: initdb.c:2465 +#, c-format +msgid "" +" --builtin-locale=LOCALE\n" +" set builtin locale name for new databases\n" +msgstr "" +" —builtin-locale=LOCALE\n" +" 为新数据库设置内置区域环境名称\n" + +#: initdb.c:2467 +#, c-format +msgid "" +" --locale-provider={builtin|libc|icu}\n" +" set default locale provider for new databases\n" +msgstr "" +" —locale-provider={builtin|libc|icu}\n" +" 为新数据库设置默认的区域环境支持程序\n" + +#: initdb.c:2469 #, c-format msgid " --pwfile=FILE read password for the new superuser from file\n" -msgstr " --pwfile=FILE 对于新的超级用户从文件读取口令\n" +msgstr " --pwfile=FILE 为新的超级用户从文件读取密码\n" -#: initdb.c:2262 +#: initdb.c:2470 #, c-format msgid "" " -T, --text-search-config=CFG\n" " default text search configuration\n" msgstr "" " -T, --text-search-config=CFG\n" -" 缺省的文本搜索配置\n" +" 默认的文本搜索配置\n" -#: initdb.c:2264 +#: initdb.c:2472 #, c-format msgid " -U, --username=NAME database superuser name\n" -msgstr " -U, --username=NAME 数据库超级用户名\n" +msgstr " -U, --username=NAME 数据库超级用户名称\n" -#: initdb.c:2265 +#: initdb.c:2473 #, c-format msgid " -W, --pwprompt prompt for a password for the new superuser\n" -msgstr " -W, --pwprompt 对于新的超级用户提示输入口令\n" +msgstr " -W, --pwprompt 对于新的超级用户提示输入密码\n" -#: initdb.c:2266 +#: initdb.c:2474 #, c-format msgid " -X, --waldir=WALDIR location for the write-ahead log directory\n" msgstr " -X, --waldir=WALDIR 预写日志目录的位置\n" -#: initdb.c:2267 +#: initdb.c:2475 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" -msgstr " --wal-segsize=SIZE WAL段的大小(兆字节)\n" +msgstr " --wal-segsize=SIZE WAL 段的大小(兆字节)\n" -#: initdb.c:2268 +#: initdb.c:2476 #, c-format msgid "" "\n" "Less commonly used options:\n" msgstr "" "\n" -"非普通使用选项:\n" +"不常用选项:\n" -#: initdb.c:2269 +#: initdb.c:2477 +#, c-format +msgid " -c, --set NAME=VALUE override default setting for server parameter\n" +msgstr " -c, --set NAME=VALUE 覆盖默认的服务器参数设置\n" + +#: initdb.c:2478 #, c-format msgid " -d, --debug generate lots of debugging output\n" -msgstr " -d, --debug 产生大量的除错信息\n" +msgstr " -d, --debug 产生大量的调试信息\n" -#: initdb.c:2270 +#: initdb.c:2479 #, c-format msgid " --discard-caches set debug_discard_caches=1\n" -msgstr " --discard-caches 设置debug_discard_caches=1\n" +msgstr " --discard-caches 设置 debug_discard_caches=1\n" -#: initdb.c:2271 +#: initdb.c:2480 #, c-format msgid " -L DIRECTORY where to find the input files\n" msgstr " -L DIRECTORY 输入文件的位置\n" -#: initdb.c:2272 +#: initdb.c:2481 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean 出错后不清理\n" -#: initdb.c:2273 +#: initdb.c:2482 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" -msgstr " -N, --no-sync 不用等待变化安全写入磁盘\n" +msgstr " -N, --no-sync 不用等待变更安全写入磁盘\n" -#: initdb.c:2274 +#: initdb.c:2483 +#, c-format msgid " --no-instructions do not print instructions for next steps\n" msgstr " --no-instructions 不要打印后续步骤的说明\n" -#: initdb.c:2275 +#: initdb.c:2484 #, c-format msgid " -s, --show show internal settings\n" msgstr " -s, --show 显示内部设置\n" -#: initdb.c:2276 +#: initdb.c:2485 #, c-format -msgid " -S, --sync-only only sync data directory\n" -msgstr " -S, --sync-only 只同步数据目录\n" +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD 设置同步文件到磁盘的方法\n" -#: initdb.c:2277 +#: initdb.c:2486 +#, c-format +msgid " -S, --sync-only only sync database files to disk, then exit\n" +msgstr " -S, --sync-only 只同步数据库文件到磁盘, 然后退出\n" + +#: initdb.c:2487 #, c-format msgid "" "\n" @@ -633,17 +734,17 @@ msgstr "" "\n" "其它选项:\n" -#: initdb.c:2278 +#: initdb.c:2488 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 输出版本信息, 然后退出\n" -#: initdb.c:2279 +#: initdb.c:2489 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 显示此帮助, 然后退出\n" -#: initdb.c:2280 +#: initdb.c:2490 #, c-format msgid "" "\n" @@ -652,117 +753,115 @@ msgid "" msgstr "" "\n" "如果没有指定数据目录, 将使用环境变量 PGDATA\n" +"\n" -#: initdb.c:2282 +#: initdb.c:2492 #, c-format msgid "" "\n" "Report bugs to <%s>.\n" msgstr "" "\n" -"臭虫报告至<%s>.\n" +"报告缺陷: <%s>.\n" -#: initdb.c:2283 +#: initdb.c:2493 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 主页: <%s>\n" -#: initdb.c:2311 +#: initdb.c:2517 #, c-format msgid "invalid authentication method \"%s\" for \"%s\" connections" -msgstr "无效认证方法 \"%s\" 用于 \"%s\" 连接" +msgstr "\"%s\" 是用于 \"%s\" 连接的无效认证方法" -#: initdb.c:2327 +#: initdb.c:2531 +#, c-format msgid "must specify a password for the superuser to enable password authentication" -msgstr "为了启动密码认证, 你需要为超级用户指定一个口令" +msgstr "为了启用密码认证, 必须为超级用户指定一个密码" -#: initdb.c:2348 +#: initdb.c:2550 #, c-format msgid "no data directory specified" msgstr "没有指定数据目录" -#: initdb.c:2350 +#: initdb.c:2551 #, c-format -msgid "" -"You must identify the directory where the data for this database system\n" -"will reside. Do this with either the invocation option -D or the\n" -"environment variable PGDATA.\n" -msgstr "" -"您必须确认此数据库系统的数据所在目录\n" -"存在. 使用 -D 选项或者\n" -"环境变量 PGDATA.\n" +msgid "You must identify the directory where the data for this database system will reside. Do this with either the invocation option -D or the environment variable PGDATA." +msgstr "你必须确认此数据库系统的数据所在目录存在. 可使用 -D 选项或者环境变量 PGDATA 操作." -#: initdb.c:2368 +#: initdb.c:2568 +#, c-format msgid "could not set environment" msgstr "无法设置环境" -#: initdb.c:2388 +#: initdb.c:2586 #, c-format -msgid "" -"The program \"%s\" is needed by %s but was not found in the\n" -"same directory as \"%s\".\n" -"Check your installation." -msgstr "" -"%2$s需要程序\"%1$s\"\n" -"但在与\"%3$s\"相同的目录中找不到该程序.\n" -"检查您的安装." +msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +msgstr "%2$s 需要程序 \"%1$s\", 但在与 \"%3$s\" 相同的目录中找不到该程序" -#: initdb.c:2393 +#: initdb.c:2589 #, c-format -msgid "" -"The program \"%s\" was found by \"%s\"\n" -"but was not the same version as %s.\n" -"Check your installation." -msgstr "" -"程序\"%s\"是由\"%s\"找到的\n" -"但与%s的版本不同.\n" -"检查您的安装." +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "程序 \"%s\" 已由 \"%s\" 找到, 但与 %s 版本不一致" -#: initdb.c:2412 +#: initdb.c:2604 #, c-format msgid "input file location must be an absolute path" msgstr "输入文件位置必须为绝对路径" -#: initdb.c:2429 +#: initdb.c:2621 #, c-format msgid "The database cluster will be initialized with locale \"%s\".\n" -msgstr "数据库簇将使用本地化语言 \"%s\"进行初始化.\n" +msgstr "数据库集簇将以区域环境设置 \"%s\" 进行初始化.\n" + +#: initdb.c:2624 +#, c-format +msgid "The database cluster will be initialized with this locale configuration:\n" +msgstr "数据库集簇将以该区域环境配置进行初始化:\n" + +#: initdb.c:2625 +#, c-format +msgid " locale provider: %s\n" +msgstr " 区域环境支持程序: %s\n" + +#: initdb.c:2627 +#, c-format +msgid " default collation: %s\n" +msgstr " 默认排序: %s\n" -#: initdb.c:2432 +#: initdb.c:2628 #, c-format msgid "" -"The database cluster will be initialized with locales\n" -" COLLATE: %s\n" -" CTYPE: %s\n" -" MESSAGES: %s\n" -" MONETARY: %s\n" -" NUMERIC: %s\n" -" TIME: %s\n" +" LC_COLLATE: %s\n" +" LC_CTYPE: %s\n" +" LC_MESSAGES: %s\n" +" LC_MONETARY: %s\n" +" LC_NUMERIC: %s\n" +" LC_TIME: %s\n" msgstr "" -"数据库簇将带有一下 locales 初始化\n" -" COLLATE: %s\n" -" CTYPE: %s\n" -" MESSAGES: %s\n" -" MONETARY: %s\n" -" NUMERIC: %s\n" -" TIME: %s\n" +" LC_COLLATE: %s\n" +" LC_CTYPE: %s\n" +" LC_MESSAGES: %s\n" +" LC_MONETARY: %s\n" +" LC_NUMERIC: %s\n" +" LC_TIME: %s\n" -#: initdb.c:2456 +#: initdb.c:2658 #, c-format msgid "could not find suitable encoding for locale \"%s\"" -msgstr "无法为locale(本地化语言)\"%s\"找到合适的编码" +msgstr "无法为区域环境 \"%s\" 找到合适的编码" -#: initdb.c:2458 +#: initdb.c:2660 #, c-format -msgid "Rerun %s with the -E option.\n" -msgstr "带 -E 选项重新运行 %s.\n" +msgid "Rerun %s with the -E option." +msgstr "请带 -E 选项重新运行 %s." -#: initdb.c:2459 initdb.c:3099 initdb.c:3120 +#: initdb.c:2661 initdb.c:3204 initdb.c:3324 initdb.c:3344 #, c-format -msgid "Try \"%s --help\" for more information.\n" -msgstr "请用 \"%s --help\" 获取更多的信息.\n" +msgid "Try \"%s --help\" for more information." +msgstr "请用 \"%s --help\" 获取更多信息." -#: initdb.c:2472 +#: initdb.c:2673 #, c-format msgid "" "Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n" @@ -771,173 +870,179 @@ msgstr "" "本地化隐含的编码 \"%s\" 不允许作为服务器端的编码.\n" "默认的数据库编码将采用 \"%s\" 作为代替.\n" -#: initdb.c:2477 +#: initdb.c:2678 #, c-format msgid "locale \"%s\" requires unsupported encoding \"%s\"" -msgstr "本地化语言环境 \"%s\"要求使用不支持的编码\"%s\"" +msgstr "区域环境 \"%s\" 要求使用不支持的编码 \"%s\"" -#: initdb.c:2480 +#: initdb.c:2680 #, c-format -msgid "" -"Encoding \"%s\" is not allowed as a server-side encoding.\n" -"Rerun %s with a different locale selection.\n" -msgstr "" -"不允许将编码\"%s\"作为服务器端编码.\n" -"使用一个不同的本地化语言环境重新运行%s.\n" +msgid "Encoding \"%s\" is not allowed as a server-side encoding." +msgstr "编码 \"%s\" 不允许作为服务器端编码." -#: initdb.c:2489 +#: initdb.c:2682 +#, c-format +msgid "Rerun %s with a different locale selection." +msgstr "请使用一个不同的区域环境选项重新运行 %s." + +#: initdb.c:2690 #, c-format msgid "The default database encoding has accordingly been set to \"%s\".\n" msgstr "默认的数据库编码已经相应的设置为 \"%s\".\n" -#: initdb.c:2555 +#: initdb.c:2704 +#, c-format +msgid "builtin provider locale \"%s\" requires encoding \"%s\"" +msgstr "内置的支持程序区域环境 \"%s\" 要求编码 \"%s\"" + +#: initdb.c:2766 +#, c-format msgid "could not find suitable text search configuration for locale \"%s\"" -msgstr "无法为本地化语言环境\"%s\"找到合适的文本搜索配置" +msgstr "无法为区域环境 \"%s\" 找到合适的文本搜索配置" -#: initdb.c:2566 +#: initdb.c:2777 +#, c-format msgid "suitable text search configuration for locale \"%s\" is unknown" -msgstr "对于本地化语言环境\"%s\"合适的文本搜索配置未知" +msgstr "区域环境 \"%s\" 的合适文本搜索配置未知" -#: initdb.c:2571 +#: initdb.c:2782 +#, c-format msgid "specified text search configuration \"%s\" might not match locale \"%s\"" -msgstr "所指定的文本搜索配置\"%s\"可能与本地语言环境\"%s\"不匹配" +msgstr "所指定的文本搜索配置 \"%s\" 可能与区域环境 \"%s\" 不匹配" -#: initdb.c:2576 +#: initdb.c:2787 #, c-format msgid "The default text search configuration will be set to \"%s\".\n" -msgstr "缺省的文本搜索配置将会被设置到\"%s\"\n" +msgstr "默认的文本搜索配置将被设为 \"%s\".\n" -#: initdb.c:2620 initdb.c:2702 +#: initdb.c:2830 initdb.c:2901 #, c-format msgid "creating directory %s ... " -msgstr "创建目录 %s ... " +msgstr "正在创建目录 %s ... " -#: initdb.c:2626 initdb.c:2708 initdb.c:2773 initdb.c:2835 +#: initdb.c:2835 initdb.c:2906 initdb.c:2954 initdb.c:3011 #, c-format msgid "could not create directory \"%s\": %m" msgstr "无法创建目录 \"%s\": %m" -#: initdb.c:2637 initdb.c:2720 +#: initdb.c:2844 initdb.c:2916 #, c-format msgid "fixing permissions on existing directory %s ... " -msgstr "修复已存在目录 %s 的权限 ... " +msgstr "正在修复已存在目录 %s 的权限 ... " -#: initdb.c:2643 initdb.c:2726 +#: initdb.c:2849 initdb.c:2921 #, c-format msgid "could not change permissions of directory \"%s\": %m" msgstr "无法改变目录 \"%s\" 的权限: %m" -#: initdb.c:2657 initdb.c:2740 +#: initdb.c:2861 initdb.c:2933 #, c-format msgid "directory \"%s\" exists but is not empty" -msgstr "目录\"%s\"已存在,但不是空的" +msgstr "目录 \"%s\" 已存在,但不为空" -#: initdb.c:2662 +#: initdb.c:2865 #, c-format -msgid "" -"If you want to create a new database system, either remove or empty\n" -"the directory \"%s\" or run %s\n" -"with an argument other than \"%s\".\n" -msgstr "" -"如果您想创建一个新的数据库系统, 请删除或清空\n" -"目录 \"%s\" 或者运行带参数的 %s\n" -"而不是 \"%s\".\n" +msgid "If you want to create a new database system, either remove or empty the directory \"%s\" or run %s with an argument other than \"%s\"." +msgstr "如果你想创建一个新的数据库系统, 请删除或清空目录 \"%s\" 或者运行带有参数的 %s 而不是 \"%s\"." -#: initdb.c:2670 initdb.c:2752 initdb.c:3135 +#: initdb.c:2873 initdb.c:2943 initdb.c:3369 #, c-format msgid "could not access directory \"%s\": %m" msgstr "无法访问目录 \"%s\": %m" -#: initdb.c:2693 +#: initdb.c:2894 #, c-format msgid "WAL directory location must be an absolute path" -msgstr "WAL目录的位置必须为绝对路径" +msgstr "WAL 目录位置必须为绝对路径" -#: initdb.c:2745 +#: initdb.c:2937 #, c-format -msgid "" -"If you want to store the WAL there, either remove or empty the directory\n" -"\"%s\".\n" -msgstr "如果您要存储WAL日志,需要删除或者清空目录\"%s\".\n" +msgid "If you want to store the WAL there, either remove or empty the directory \"%s\"." +msgstr "如果你要存储 WAL 日志,需要删除或者清空目录 \"%s\"." -#: initdb.c:2759 +#: initdb.c:2947 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "无法创建符号链接 \"%s\": %m" -#: initdb.c:2764 +#: initdb.c:2966 #, c-format -msgid "symlinks are not supported on this platform" -msgstr "在这个平台上不支持符号链接" +msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point." +msgstr "它包含一个以点号开头/不可见的文件,可能因为它是一个挂载点." -#: initdb.c:2788 +#: initdb.c:2968 #, c-format -msgid "It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n" -msgstr "它包含一个不可见的带固定点的文件,可能因为它是一个装载点。\n" +msgid "It contains a lost+found directory, perhaps due to it being a mount point." +msgstr "它包含名为 lost+found 的目录,可能因为它是一个挂载点." -#: initdb.c:2791 -#, c-format -msgid "It contains a lost+found directory, perhaps due to it being a mount point.\n" -msgstr "它包含名为lost+found的目录,可能因为它是一个加载点.\n" - -#: initdb.c:2794 +#: initdb.c:2970 #, c-format msgid "" "Using a mount point directly as the data directory is not recommended.\n" -"Create a subdirectory under the mount point.\n" +"Create a subdirectory under the mount point." msgstr "" -"不推荐将加载点作为数据目录.\n" -"通常在加载点下边创建一个子目录.\n" +"不推荐直接将挂载点用作数据目录.\n" +"通常在挂载点下边创建一个子目录." -#: initdb.c:2820 +#: initdb.c:2997 #, c-format msgid "creating subdirectories ... " msgstr "正在创建子目录 ... " -#: initdb.c:2866 +#: initdb.c:3040 msgid "performing post-bootstrap initialization ... " -msgstr "正在执行自举后初始化 ..." +msgstr "正在执行启动脚本后续初始化 ... " + +#: initdb.c:3203 +#, c-format +msgid "-c %s requires a value" +msgstr "-c %s 需要一个值" -#: initdb.c:3029 +#: initdb.c:3228 #, c-format msgid "Running in debug mode.\n" -msgstr "运行在除错模式中. \n" +msgstr "正在以调试模式运行. \n" -#: initdb.c:3033 +#: initdb.c:3232 #, c-format msgid "Running in no-clean mode. Mistakes will not be cleaned up.\n" -msgstr "运行在 no-clean 模式中. 错误将不被清理.\n" +msgstr "正在以 no-clean 模式运行. 错误将不被清理.\n" + +#: initdb.c:3305 +#, c-format +msgid "unrecognized locale provider: %s" +msgstr "无法识别的区域环境支持程序: %s" -#: initdb.c:3118 +#: initdb.c:3342 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "命令行参数太多 (第一个是 \"%s\")" -#: initdb.c:3139 initdb.c:3228 +#: initdb.c:3349 initdb.c:3353 initdb.c:3357 +#, c-format +msgid "%s cannot be specified unless locale provider \"%s\" is chosen" +msgstr "无法指定 %s, 除非选择区域环境支持程序 \"%s\"" + +#: initdb.c:3371 initdb.c:3434 msgid "syncing data to disk ... " -msgstr "同步数据到磁盘..." +msgstr "正在同步数据到磁盘 ... " -#: initdb.c:3148 +#: initdb.c:3379 #, c-format msgid "password prompt and password file cannot be specified together" -msgstr "口令提示和口令文件不能同时都指定" +msgstr "密码提示和密码文件不能同时都指定" -#: initdb.c:3173 +#: initdb.c:3390 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "--wal-segsize的参数必须是一个数字" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "%s 的参数必须是 2 的幂次方(在 1 - 1024 之间)" -#: initdb.c:3178 -#, c-format -msgid "argument of --wal-segsize must be a power of 2 between 1 and 1024" -msgstr "--wal-segsize的参数必须是2的幂次方(在1和1024之间)" - -#: initdb.c:3195 +#: initdb.c:3403 #, c-format msgid "superuser name \"%s\" is disallowed; role names cannot begin with \"pg_\"" -msgstr "超级用户名\"%s\"是不允许的;角色名称不能以\"pg_\"开始" +msgstr "超级用户名 \"%s\" 不被允许;角色名称不能以 \"pg_\" 开始" -#: initdb.c:3199 +#: initdb.c:3405 #, c-format msgid "" "The files belonging to this database system will be owned by user \"%s\".\n" @@ -946,18 +1051,19 @@ msgid "" msgstr "" "属于此数据库系统的文件宿主为用户 \"%s\".\n" "此用户也必须为服务器进程的宿主.\n" +"\n" -#: initdb.c:3215 +#: initdb.c:3421 #, c-format msgid "Data page checksums are enabled.\n" msgstr "允许生成数据页校验和.\n" -#: initdb.c:3217 +#: initdb.c:3423 #, c-format msgid "Data page checksums are disabled.\n" msgstr "禁止为数据页生成校验和.\n" -#: initdb.c:3234 +#: initdb.c:3440 #, c-format msgid "" "\n" @@ -968,26 +1074,22 @@ msgstr "" "跳过同步到磁盘操作.\n" "如果操作系统宕机,数据目录可能会毁坏.\n" -#: initdb.c:3239 +#: initdb.c:3445 #, c-format msgid "enabling \"trust\" authentication for local connections" -msgstr "为本地连接启用\"trust\"身份验证" +msgstr "为本地连接启用 \"trust\" 身份验证" -#: initdb.c:3240 +#: initdb.c:3446 #, c-format -msgid "" -"You can change this by editing pg_hba.conf or using the option -A, or\n" -"--auth-local and --auth-host, the next time you run initdb.\n" -msgstr "" -"你可以通过编辑 pg_hba.conf 更改或你下次\n" -"执行 initdb 时使用 -A或者--auth-local和--auth-host选项.\n" +msgid "You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb." +msgstr "你可以通过编辑 pg_hba.conf 或下次运行 initdb 时使用 -A 或者 --auth-local 和 --auth-host 选项进行更改." #. translator: This is a placeholder in a shell command. -#: initdb.c:3270 +#: initdb.c:3476 msgid "logfile" -msgstr "日志文件" +msgstr "logfile" -#: initdb.c:3272 +#: initdb.c:3478 #, c-format msgid "" "\n" @@ -997,8 +1099,79 @@ msgid "" "\n" msgstr "" "\n" -"成功。您现在可以用下面的命令开启数据库服务器:\n" +"成功。你现在可以用下面的命令开启数据库服务器:\n" "\n" " %s\n" "\n" +#, c-format +#~ msgid "" +#~ "The program \"%s\" is needed by %s but was not found in the\n" +#~ "same directory as \"%s\".\n" +#~ "Check your installation." +#~ msgstr "" +#~ "%2$s需要程序\"%1$s\"\n" +#~ "但在与\"%3$s\"相同的目录中找不到该程序.\n" +#~ "检查您的安装." + +#, c-format +#~ msgid "" +#~ "The program \"%s\" was found by \"%s\"\n" +#~ "but was not the same version as %s.\n" +#~ "Check your installation." +#~ msgstr "" +#~ "程序\"%s\"是由\"%s\"找到的\n" +#~ "但与%s的版本不同.\n" +#~ "检查您的安装." + +#, c-format +#~ msgid "Try \"%s --help\" for more information.\n" +#~ msgstr "请用 \"%s --help\" 获取更多的信息.\n" + +#, c-format +#~ msgid "argument of --wal-segsize must be a number" +#~ msgstr "--wal-segsize 的参数必须是一个数字" + +#, c-format +#~ msgid "cannot create restricted tokens on this platform: error code %lu" +#~ msgstr "无法为该平台创建受限令牌: 错误码 %lu" + +#, c-format +#~ msgid "could not change directory to \"%s\": %m" +#~ msgstr "无法跳转到目录 \"%s\" 中: %m" + +#, c-format +#~ msgid "could not identify current directory: %m" +#~ msgstr "无法确认当前目录: %m" + +#, c-format +#~ msgid "could not load library \"%s\": error code %lu" +#~ msgstr "无法加载库 \"%s\": 错误码 %lu" + +#, c-format +#~ msgid "could not read binary \"%s\"" +#~ msgstr "无法读取二进制码 \"%s\"" + +#, c-format +#~ msgid "could not read symbolic link \"%s\": %m" +#~ msgstr "无法读取符号链接 \"%s\": %m" + +#, c-format +#~ msgid "could not remove file or directory \"%s\": %m" +#~ msgstr "无法删除文件或目录 \"%s\": %m" + +#, c-format +#~ msgid "could not stat file or directory \"%s\": %m" +#~ msgstr "无法获取文件或目录 \"%s\" 状态: %m" + +#, c-format +#~ msgid "fatal: " +#~ msgstr "致命的: " + +#, c-format +#~ msgid "invalid binary \"%s\"" +#~ msgstr "无效的二进制码 \"%s\"" + +#, c-format +#~ msgid "symlinks are not supported on this platform" +#~ msgstr "在这个平台上不支持符号链接" diff --git a/src/bin/initdb/t/001_initdb.pl b/src/bin/initdb/t/001_initdb.pl index 06a35ac0b738e..15dd10ce40a31 100644 --- a/src/bin/initdb/t/001_initdb.pl +++ b/src/bin/initdb/t/001_initdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # To test successful data directory creation with an additional feature, first # try to elaborate the "successful creation" test instead of adding a test. @@ -22,21 +22,19 @@ program_version_ok('initdb'); program_options_handling_ok('initdb'); -command_fails([ 'initdb', '-S', "$tempdir/nonexistent" ], +command_fails([ 'initdb', '--sync-only', "$tempdir/nonexistent" ], 'sync missing data directory'); mkdir $xlogdir; mkdir "$xlogdir/lost+found"; -command_fails( - [ 'initdb', '-X', $xlogdir, $datadir ], +command_fails([ 'initdb', '--waldir' => $xlogdir, $datadir ], 'existing nonempty xlog directory'); rmdir "$xlogdir/lost+found"; command_fails( - [ 'initdb', '-X', 'pgxlog', $datadir ], + [ 'initdb', '--waldir' => 'pgxlog', $datadir ], 'relative xlog directory not allowed'); -command_fails( - [ 'initdb', '-U', 'pg_test', $datadir ], +command_fails([ 'initdb', '--username' => 'pg_test', $datadir ], 'role names cannot begin with "pg_"'); mkdir $datadir; @@ -49,12 +47,14 @@ local (%ENV) = %ENV; delete $ENV{TZ}; - # while we are here, also exercise -T and -c options + # while we are here, also exercise --text-search-config and --set options command_ok( [ - 'initdb', '-N', '-T', 'german', '-c', - 'default_text_search_config=german', - '-X', $xlogdir, $datadir + 'initdb', '--no-sync', + '--text-search-config' => 'german', + '--set' => 'default_text_search_config=german', + '--waldir' => $xlogdir, + $datadir ], 'successful creation'); @@ -69,28 +69,26 @@ } } -# Control file should tell that data checksums are disabled by default. +# Control file should tell that data checksums are enabled by default. command_like( [ 'pg_controldata', $datadir ], - qr/Data page checksum version:.*0/, - 'checksums are disabled in control file'); -# pg_checksums fails with checksums disabled by default. This is -# not part of the tests included in pg_checksums to save from -# the creation of an extra instance. -command_fails([ 'pg_checksums', '-D', $datadir ], - "pg_checksums fails with data checksum disabled"); + qr/Data page checksum version:.*1/, + 'checksums are enabled in control file'); -command_ok([ 'initdb', '-S', $datadir ], 'sync only'); +command_ok([ 'initdb', '--sync-only', $datadir ], 'sync only'); +command_ok([ 'initdb', '--sync-only', '--no-sync-data-files', $datadir ], '--no-sync-data-files'); command_fails([ 'initdb', $datadir ], 'existing data directory'); if ($supports_syncfs) { - command_ok([ 'initdb', '-S', $datadir, '--sync-method', 'syncfs' ], + command_ok( + [ 'initdb', '--sync-only', $datadir, '--sync-method' => 'syncfs' ], 'sync method syncfs'); } else { - command_fails([ 'initdb', '-S', $datadir, '--sync-method', 'syncfs' ], + command_fails( + [ 'initdb', '--sync-only', $datadir, '--sync-method' => 'syncfs' ], 'sync method syncfs'); } @@ -103,8 +101,7 @@ # Init a new db with group access my $datadir_group = "$tempdir/data_group"; - command_ok( - [ 'initdb', '-g', $datadir_group ], + command_ok([ 'initdb', '--allow-group-access', $datadir_group ], 'successful creation with group access'); ok(check_mode_recursive($datadir_group, 0750, 0640), @@ -116,14 +113,19 @@ if ($ENV{with_icu} eq 'yes') { command_fails_like( - [ 'initdb', '--no-sync', '--locale-provider=icu', "$tempdir/data2" ], + [ + 'initdb', '--no-sync', + '--locale-provider' => 'icu', + "$tempdir/data2" + ], qr/initdb: error: locale must be specified if provider is icu/, 'locale provider ICU requires --icu-locale'); command_ok( [ 'initdb', '--no-sync', - '--locale-provider=icu', '--icu-locale=en', + '--locale-provider' => 'icu', + '--icu-locale' => 'en', "$tempdir/data3" ], 'option --icu-locale'); @@ -131,11 +133,15 @@ command_like( [ 'initdb', '--no-sync', - '-A', 'trust', - '--locale-provider=icu', '--locale=und', - '--lc-collate=C', '--lc-ctype=C', - '--lc-messages=C', '--lc-numeric=C', - '--lc-monetary=C', '--lc-time=C', + '--auth' => 'trust', + '--locale-provider' => 'icu', + '--locale' => 'und', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + '--lc-messages' => 'C', + '--lc-numeric' => 'C', + '--lc-monetary' => 'C', + '--lc-time' => 'C', "$tempdir/data4" ], qr/^\s+default collation:\s+und\n/ms, @@ -144,7 +150,8 @@ command_fails_like( [ 'initdb', '--no-sync', - '--locale-provider=icu', '--icu-locale=@colNumeric=lower', + '--locale-provider' => 'icu', + '--icu-locale' => '@colNumeric=lower', "$tempdir/dataX" ], qr/could not open collator for locale/, @@ -153,8 +160,10 @@ command_fails_like( [ 'initdb', '--no-sync', - '--locale-provider=icu', '--encoding=SQL_ASCII', - '--icu-locale=en', "$tempdir/dataX" + '--locale-provider' => 'icu', + '--encoding' => 'SQL_ASCII', + '--icu-locale' => 'en', + "$tempdir/dataX" ], qr/error: encoding mismatch/, 'fails for encoding not supported by ICU'); @@ -162,7 +171,8 @@ command_fails_like( [ 'initdb', '--no-sync', - '--locale-provider=icu', '--icu-locale=nonsense-nowhere', + '--locale-provider' => 'icu', + '--icu-locale' => 'nonsense-nowhere', "$tempdir/dataX" ], qr/error: locale "nonsense-nowhere" has unknown language "nonsense"/, @@ -171,7 +181,8 @@ command_fails_like( [ 'initdb', '--no-sync', - '--locale-provider=icu', '--icu-locale=@colNumeric=lower', + '--locale-provider' => 'icu', + '--icu-locale' => '@colNumeric=lower', "$tempdir/dataX" ], qr/could not open collator for locale "und-u-kn-lower": U_ILLEGAL_ARGUMENT_ERROR/, @@ -180,18 +191,27 @@ else { command_fails( - [ 'initdb', '--no-sync', '--locale-provider=icu', "$tempdir/data2" ], + [ + 'initdb', '--no-sync', + '--locale-provider' => 'icu', + "$tempdir/data2" + ], 'locale provider ICU fails since no ICU support'); } command_fails( - [ 'initdb', '--no-sync', '--locale-provider=builtin', "$tempdir/data6" ], + [ + 'initdb', '--no-sync', + '--locale-provider' => 'builtin', + "$tempdir/data6" + ], 'locale provider builtin fails without --locale'); command_ok( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '--locale=C', + '--locale-provider' => 'builtin', + '--locale' => 'C', "$tempdir/data7" ], 'locale provider builtin with --locale'); @@ -199,18 +219,24 @@ command_ok( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '-E UTF-8', - '--lc-collate=C', '--lc-ctype=C', - '--builtin-locale=C.UTF-8', "$tempdir/data8" + '--locale-provider' => 'builtin', + '--encoding' => 'UTF-8', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + '--builtin-locale' => 'C.UTF-8', + "$tempdir/data8" ], - 'locale provider builtin with -E UTF-8 --builtin-locale=C.UTF-8'); + 'locale provider builtin with --encoding=UTF-8 --builtin-locale=C.UTF-8'); command_fails( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '-E SQL_ASCII', - '--lc-collate=C', '--lc-ctype=C', - '--builtin-locale=C.UTF-8', "$tempdir/data9" + '--locale-provider' => 'builtin', + '--encoding' => 'SQL_ASCII', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + '--builtin-locale' => 'C.UTF-8', + "$tempdir/data9" ], 'locale provider builtin with --builtin-locale=C.UTF-8 fails for SQL_ASCII' ); @@ -218,15 +244,18 @@ command_ok( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '--lc-ctype=C', - '--locale=C', "$tempdir/data10" + '--locale-provider' => 'builtin', + '--lc-ctype' => 'C', + '--locale' => 'C', + "$tempdir/data10" ], 'locale provider builtin with --lc-ctype'); command_fails( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '--icu-locale=en', + '--locale-provider' => 'builtin', + '--icu-locale' => 'en', "$tempdir/dataX" ], 'fails for locale provider builtin with ICU locale'); @@ -234,38 +263,71 @@ command_fails( [ 'initdb', '--no-sync', - '--locale-provider=builtin', '--icu-rules=""', + '--locale-provider' => 'builtin', + '--icu-rules' => '""', "$tempdir/dataX" ], 'fails for locale provider builtin with ICU rules'); command_fails( - [ 'initdb', '--no-sync', '--locale-provider=xyz', "$tempdir/dataX" ], + [ + 'initdb', '--no-sync', + '--locale-provider' => 'xyz', + "$tempdir/dataX" + ], 'fails for invalid locale provider'); command_fails( [ 'initdb', '--no-sync', - '--locale-provider=libc', '--icu-locale=en', + '--locale-provider' => 'libc', + '--icu-locale' => 'en', "$tempdir/dataX" ], 'fails for invalid option combination'); -command_fails([ 'initdb', '--no-sync', '--set', 'foo=bar', "$tempdir/dataX" ], +command_fails( + [ + 'initdb', '--no-sync', + '--set' => 'foo=bar', + "$tempdir/dataX" + ], 'fails for invalid --set option'); -# Make sure multiple invocations of -c parameters are added case insensitive +# Make sure multiple invocations of --set parameters are added case +# insensitive. command_ok( [ - 'initdb', '-cwork_mem=128', - '-cWork_Mem=256', '-cWORK_MEM=512', + 'initdb', '--no-sync', + '--set' => 'work_mem=128', + '--set' => 'Work_Mem=256', + '--set' => 'WORK_MEM=512', "$tempdir/dataY" ], - 'multiple -c options with different case'); + 'multiple --set options with different case'); my $conf = slurp_file("$tempdir/dataY/postgresql.conf"); ok($conf !~ qr/^WORK_MEM = /m, "WORK_MEM should not be configured"); ok($conf !~ qr/^Work_Mem = /m, "Work_Mem should not be configured"); ok($conf =~ qr/^work_mem = 512/m, "work_mem should be in config"); +# Test the no-data-checksums flag +my $datadir_nochecksums = "$tempdir/data_no_checksums"; + +command_ok([ 'initdb', '--no-data-checksums', $datadir_nochecksums ], + 'successful creation without data checksums'); + +# Control file should tell that data checksums are disabled. +command_like( + [ 'pg_controldata', $datadir_nochecksums ], + qr/Data page checksum version:.*0/, + 'checksums are disabled in control file'); + +# pg_checksums fails with checksums disabled. This is +# not part of the tests included in pg_checksums to save from +# the creation of an extra instance. +command_fails( + [ 'pg_checksums', '--pgdata' => $datadir_nochecksums ], + "pg_checksums fails with data checksum disabled"); + done_testing(); diff --git a/src/bin/meson.build b/src/bin/meson.build index aa60ebaa3026f..b33cb6c75bf88 100644 --- a/src/bin/meson.build +++ b/src/bin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('initdb') subdir('pg_amcheck') diff --git a/src/bin/pg_amcheck/Makefile b/src/bin/pg_amcheck/Makefile index f9488c447a887..fa6071f97c186 100644 --- a/src/bin/pg_amcheck/Makefile +++ b/src/bin/pg_amcheck/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_amcheck # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_amcheck/Makefile diff --git a/src/bin/pg_amcheck/meson.build b/src/bin/pg_amcheck/meson.build index 292b33eb09425..316ea0d40b8c2 100644 --- a/src/bin/pg_amcheck/meson.build +++ b/src/bin/pg_amcheck/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_amcheck_sources = files( 'pg_amcheck.c', diff --git a/src/bin/pg_amcheck/pg_amcheck.c b/src/bin/pg_amcheck/pg_amcheck.c index a1ad41e766471..2b1fd566c353f 100644 --- a/src/bin/pg_amcheck/pg_amcheck.c +++ b/src/bin/pg_amcheck/pg_amcheck.c @@ -3,7 +3,7 @@ * pg_amcheck.c * Detects corruption within database relations. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_amcheck/pg_amcheck.c @@ -16,6 +16,7 @@ #include #include "catalog/pg_am_d.h" +#include "catalog/pg_class_d.h" #include "catalog/pg_namespace_d.h" #include "common/logging.h" #include "common/username.h" @@ -25,7 +26,7 @@ #include "fe_utils/query_utils.h" #include "fe_utils/simple_list.h" #include "fe_utils/string_utils.h" -#include "getopt_long.h" /* pgrminclude ignore */ +#include "getopt_long.h" #include "pgtime.h" #include "storage/block.h" @@ -559,7 +560,7 @@ main(int argc, char *argv[]) executeCommand(conn, install_sql, opts.echo); pfree(install_sql); - pfree(schema); + PQfreemem(schema); } /* @@ -586,6 +587,7 @@ main(int argc, char *argv[]) /* Querying the catalog succeeded, but amcheck is missing. */ pg_log_warning("skipping database \"%s\": amcheck is not installed", PQdb(conn)); + PQclear(result); disconnectDatabase(conn); conn = NULL; continue; @@ -621,8 +623,8 @@ main(int argc, char *argv[]) */ if ((vmaj == 1 && vmin < 4) || vmaj == 0) { - pg_log_warning("--checkunique option is not supported by amcheck " - "version \"%s\"", amcheck_version); + pg_log_warning("option %s is not supported by amcheck version %s", + "--checkunique", amcheck_version); dat->is_checkunique = false; } else @@ -857,7 +859,7 @@ prepare_heap_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn) appendPQExpBuffer(sql, "\n) v WHERE c.oid = %u " - "AND c.relpersistence != 't'", + "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP), rel->reloid); } @@ -890,7 +892,7 @@ prepare_btree_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn) "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i " "WHERE c.oid = %u " "AND c.oid = i.indexrelid " - "AND c.relpersistence != 't' " + "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP) " " "AND i.indisready AND i.indisvalid AND i.indislive", rel->datinfo->amcheck_schema, (opts.heapallindexed ? "true" : "false"), @@ -905,7 +907,7 @@ prepare_btree_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn) "\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i " "WHERE c.oid = %u " "AND c.oid = i.indexrelid " - "AND c.relpersistence != 't' " + "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP) " " "AND i.indisready AND i.indisvalid AND i.indislive", rel->datinfo->amcheck_schema, (opts.heapallindexed ? "true" : "false"), @@ -1952,7 +1954,8 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, * until firing off the amcheck command, as the state of an index may * change by then. */ - appendPQExpBufferStr(&sql, "\nWHERE c.relpersistence != 't'"); + appendPQExpBufferStr(&sql, "\nWHERE c.relpersistence != " + CppAsString2(RELPERSISTENCE_TEMP)); if (opts.excludetbl || opts.excludeidx || opts.excludensp) appendPQExpBufferStr(&sql, "\nAND ep.pattern_id IS NULL"); @@ -1972,15 +1975,29 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, if (opts.allrel) appendPQExpBuffer(&sql, " AND c.relam = %u " - "AND c.relkind IN ('r', 'S', 'm', 't') " + "AND c.relkind IN (" + CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_SEQUENCE) ", " + CppAsString2(RELKIND_MATVIEW) ", " + CppAsString2(RELKIND_TOASTVALUE) ") " "AND c.relnamespace != %u", HEAP_TABLE_AM_OID, PG_TOAST_NAMESPACE); else appendPQExpBuffer(&sql, " AND c.relam IN (%u, %u)" - "AND c.relkind IN ('r', 'S', 'm', 't', 'i') " - "AND ((c.relam = %u AND c.relkind IN ('r', 'S', 'm', 't')) OR " - "(c.relam = %u AND c.relkind = 'i'))", + "AND c.relkind IN (" + CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_SEQUENCE) ", " + CppAsString2(RELKIND_MATVIEW) ", " + CppAsString2(RELKIND_TOASTVALUE) ", " + CppAsString2(RELKIND_INDEX) ") " + "AND ((c.relam = %u AND c.relkind IN (" + CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_SEQUENCE) ", " + CppAsString2(RELKIND_MATVIEW) ", " + CppAsString2(RELKIND_TOASTVALUE) ")) OR " + "(c.relam = %u AND c.relkind = " + CppAsString2(RELKIND_INDEX) "))", HEAP_TABLE_AM_OID, BTREE_AM_OID, HEAP_TABLE_AM_OID, BTREE_AM_OID); @@ -2007,7 +2024,7 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, "\nAND (t.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)" "\nAND ep.heap_only" "\nWHERE ep.pattern_id IS NULL" - "\nAND t.relpersistence != 't'"); + "\nAND t.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)); appendPQExpBufferStr(&sql, "\n)"); } @@ -2026,7 +2043,7 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, "ON r.oid = i.indrelid " "INNER JOIN pg_catalog.pg_class c " "ON i.indexrelid = c.oid " - "AND c.relpersistence != 't'"); + "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)); if (opts.excludeidx || opts.excludensp) appendPQExpBufferStr(&sql, "\nINNER JOIN pg_catalog.pg_namespace n " @@ -2041,7 +2058,7 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, "\nWHERE true"); appendPQExpBuffer(&sql, " AND c.relam = %u " - "AND c.relkind = 'i'", + "AND c.relkind = " CppAsString2(RELKIND_INDEX), BTREE_AM_OID); if (opts.no_toast_expansion) appendPQExpBuffer(&sql, @@ -2065,7 +2082,7 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, "ON t.oid = i.indrelid" "\nINNER JOIN pg_catalog.pg_class c " "ON i.indexrelid = c.oid " - "AND c.relpersistence != 't'"); + "AND c.relpersistence != " CppAsString2(RELPERSISTENCE_TEMP)); if (opts.excludeidx) appendPQExpBufferStr(&sql, "\nLEFT OUTER JOIN exclude_pat ep " @@ -2078,7 +2095,7 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations, "\nWHERE true"); appendPQExpBuffer(&sql, " AND c.relam = %u" - " AND c.relkind = 'i')", + " AND c.relkind = " CppAsString2(RELKIND_INDEX) ")", BTREE_AM_OID); } diff --git a/src/bin/pg_amcheck/po/de.po b/src/bin/pg_amcheck/po/de.po index 428a8b3262e0c..5dd5992747206 100644 --- a/src/bin/pg_amcheck/po/de.po +++ b/src/bin/pg_amcheck/po/de.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_amcheck (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 10:22+0000\n" -"PO-Revision-Date: 2024-06-16 19:05+0200\n" +"POT-Creation-Date: 2024-08-28 04:23+0000\n" +"PO-Revision-Date: 2024-08-28 07:51+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -249,8 +249,8 @@ msgstr "in Datenbank »%s«: verwende amcheck Version »%s« in Schema »%s«" #: pg_amcheck.c:624 #, c-format -msgid "--checkunique option is not supported by amcheck version \"%s\"" -msgstr "Option --checkunique wird von amcheck Version »%s« nicht unterstützt" +msgid "option %s is not supported by amcheck version %s" +msgstr "Option %s wird von amcheck Version %s nicht unterstützt" #: pg_amcheck.c:650 #, c-format diff --git a/src/bin/pg_amcheck/po/es.po b/src/bin/pg_amcheck/po/es.po index ed8cb6e5503c0..7dc5272b7b76d 100644 --- a/src/bin/pg_amcheck/po/es.po +++ b/src/bin/pg_amcheck/po/es.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_amcheck (PostgreSQL) 16\n" +"Project-Id-Version: pg_amcheck (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-09-24 23:20+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2024-11-16 05:22+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -39,11 +39,78 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "no se pudo buscar el ID de usuario efectivo %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "el usuario no existe" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "fallo en la búsqueda de nombre de usuario: código de error %lu" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Petición de cancelación enviada\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "No se pudo enviar la petición de cancelación: " @@ -52,7 +119,7 @@ msgstr "No se pudo enviar la petición de cancelación: " msgid "could not connect to database %s: out of memory" msgstr "no se pudo conectar a la base de datos %s: memoria agotada" -#: ../../fe_utils/connect_utils.c:117 +#: ../../fe_utils/connect_utils.c:116 #, c-format msgid "%s" msgstr "%s" @@ -67,174 +134,214 @@ msgstr "el valor «%s» no es válido para la opción %s" msgid "%s must be in range %d..%d" msgstr "%s debe estar en el rango %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método de sync no reconocido: %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "demasiados procesos para esta plataforma: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "descriptor de archivo para socket fuera de rango para select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Intente con menos trabajos." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "falló el procesamiento de la base de datos «%s»: %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1647 pg_amcheck.c:2092 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "la consulta falló: %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1102 pg_amcheck.c:1648 pg_amcheck.c:2093 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "La consulta era: %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "argumento no válido para la opción %s" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "bloque de inicio no válido" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "bloque de inicio fuera de rango" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "bloque final no válido" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "bloque final fuera de rango" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "bloque final precede al bloque de inicio" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "no se puede especificar un nombre de base de datos al usar --all" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "no se puede especificar al mismo tiempo un nombre de base de datos junto con patrones de bases de datos" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "no hay bases de datos para revisar" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "base de datos «%s»: %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "omitiendo la base de datos «%s»: amcheck no está instalado" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "en base de datos «%s»: usando amcheck versión «%s» en esquema «%s»" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "la opción %s no está soportada por la versión %s de amcheck" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "no hay tablas heap para revisar que coincidan con «%s»" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "no hay índices btree para revisar que coincidan con «%s»" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "no hay relaciones para revisar en esquemas que coincidan con «%s»" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "no hay relaciones para revisar que coincidan con «%s»" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "no hay relaciones para revisar" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "revisando tabla heap «%s.%s.%s»" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "revisando índice btree «%s.%s.%s»" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "error al enviar orden a la base de datos «%s»: %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "La orden era: % s" -#: pg_amcheck.c:1015 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "tabla heap «%s.%s.%s», bloque %s, posición %s, atributo %s:\n" -#: pg_amcheck.c:1022 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "tabla heap «%s.%s.%s», bloque %s, posición %s:\n" -#: pg_amcheck.c:1028 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "tabla heap «%s.%s.%s», bloque %s:\n" -#: pg_amcheck.c:1033 pg_amcheck.c:1044 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "tabla heap «%s.%s.%s»:\n" -#: pg_amcheck.c:1048 pg_amcheck.c:1117 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "la consulta era: %s\n" -#: pg_amcheck.c:1099 +#: pg_amcheck.c:1144 #, c-format msgid "btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d" msgstr "índice btree «%s.%s.%s»: la función de comprobación de btree devolvió un número inesperado de registros: %d" -#: pg_amcheck.c:1103 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "¿Son compatibles la versión de %s con la de amcheck?" -#: pg_amcheck.c:1113 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "índice btree «%s.%s.%s»:\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1183 #, c-format msgid "" "%s checks objects in a PostgreSQL database for corruption.\n" @@ -243,17 +350,17 @@ msgstr "" "%s busca corrupción en objetos de una base de datos PostgreSQL.\n" "\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPCIÓN]... [BASE-DE-DATOS]\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1186 #, c-format msgid "" "\n" @@ -262,77 +369,77 @@ msgstr "" "\n" "Opciones de objetivo:\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" msgstr " -a, --all revisar todas las bases de datos\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" msgstr " -d, --database=PATRÓN revisar la(s) base(s) de datos que coincida(n)\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr " -D, --exclude-database=PATRÓN NO revisar la(s) base(s) de datos que coincida(n)\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" msgstr " -i, --index=PATRÓN revisar el(los) índice(s) que coincida(n)\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" msgstr " -I, --exclude-index=PATRÓN NO revisar el(los) índice(s) que coincida(n)\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" msgstr " -r, --relation=PATRÓN revisar la(s) relación(es) que coincida(n)\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" msgstr " -R, --exclude-relation=PATRÓN NO revisar la(s) relación(es) que coincida(n)\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" msgstr " -s, --schema=PATRÓN revisar el(los) esquema(s) que coincida(n)\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" msgstr " -S, --exclude-schema=PATRÓN NO revisar el(los) esquema(s) que coincida(n)\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" msgstr " -t, --table=PATRÓN revisar la(s) tabla(s) que coincida(n)\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" msgstr " -T, --exclude-table=PATRÓN NO revisar la(s) tabla(s) que coincida(n)\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1198 #, c-format msgid " --no-dependent-indexes do NOT expand list of relations to include indexes\n" msgstr " --no-dependent-indexes NO expandir la lista de relaciones para incluir índices\n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1199 #, c-format msgid " --no-dependent-toast do NOT expand list of relations to include TOAST tables\n" msgstr " --no-dependent-toast NO expandir lista de relaciones para incluir tablas TOAST\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1200 #, c-format msgid " --no-strict-names do NOT require patterns to match objects\n" msgstr " --no-strict-names NO requerir que los patrones coincidan con los objetos\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1201 #, c-format msgid "" "\n" @@ -341,32 +448,32 @@ msgstr "" "\n" "Opciones para revisión de tabla:\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1202 #, c-format msgid " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" msgstr " --exclude-toast-pointers NO seguir punteros TOAST de la relación\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1203 #, c-format msgid " --on-error-stop stop checking at end of first corrupt page\n" msgstr " --on-error-stop detener la revisión al final de la primera página corrupta\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1204 #, c-format msgid " --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n" msgstr " --skip=OPTION NO revisar bloques «all-frozen» u «all-visible»\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1205 #, c-format msgid " --startblock=BLOCK begin checking table(s) at the given block number\n" msgstr " --startblock=BLOQUE empezar la revisión de la(s) tabla(s) en el número de bloque especificado\n" -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1206 #, c-format msgid " --endblock=BLOCK check table(s) only up to the given block number\n" msgstr " --endblock=BLOQUE solo revisar la(s) tabla(s) hasta el número de bloque especificado\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1207 #, c-format msgid "" "\n" @@ -375,22 +482,27 @@ msgstr "" "\n" "Opciones para revisión de índices B-tree:\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1208 +#, c-format +msgid " --checkunique check unique constraint if index is unique\n" +msgstr " --checkunique verificar si restricción de unicidad se cumple en índice\n" + +#: pg_amcheck.c:1209 #, c-format msgid " --heapallindexed check that all heap tuples are found within indexes\n" msgstr " --heapallindexed revisar que todas las tuplas heap se encuentren en los índices\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1210 #, c-format msgid " --parent-check check index parent/child relationships\n" msgstr " --parent-check revisar relaciones padre/hijo de índice\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1211 #, c-format msgid " --rootdescend search from root page to refind tuples\n" msgstr " --rootdescend buscar desde la página raíz para volver a encontrar tuplas\n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1212 #, c-format msgid "" "\n" @@ -399,37 +511,37 @@ msgstr "" "\n" "Opciones de conexión:\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1213 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=ANFITRIÓN nombre del servidor o directorio del socket\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PUERTO puerto del servidor de base de datos\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USUARIO nombre de usuario para la conexión\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir contraseña\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password forzar la petición de contraseña\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE base de datos de mantención alternativa\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1219 #, c-format msgid "" "\n" @@ -438,42 +550,42 @@ msgstr "" "\n" "Otras opciones:\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1220 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo mostrar las órdenes enviadas al servidor\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1221 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to the server\n" msgstr " -j, --jobs=NUM usar esta cantidad de conexiones concurrentes hacia el servidor\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress mostrar información de progreso\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose desplegar varios mensajes informativos\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1224 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: pg_amcheck.c:1179 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" msgstr " --install-missing instalar extensiones faltantes\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: pg_amcheck.c:1182 +#: pg_amcheck.c:1228 #, c-format msgid "" "\n" @@ -482,52 +594,52 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_amcheck.c:1183 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_amcheck.c:1236 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "%*s/%s relaciones (%d%%), %*s/%s páginas (%d%%) %*s" -#: pg_amcheck.c:1247 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "%*s/%s relaciones (%d%%), %*s/%s páginas (%d%%), (%s%-*.*s)" -#: pg_amcheck.c:1262 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "%*s/%s relaciones (%d%%), %*s/%s páginas (%d%%)" -#: pg_amcheck.c:1321 pg_amcheck.c:1354 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "el nombre no es válido (demasiados puntos): %s" -#: pg_amcheck.c:1399 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "el nombre de relación no es válido (demasiados puntos): %s" -#: pg_amcheck.c:1552 pg_amcheck.c:1691 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "incluyendo base de datos «%s»" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "error interno: se recibió pattern_id de base de datos inesperado (%d)" -#: pg_amcheck.c:1675 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "no hay bases de datos a las que se pueda conectar que coincidan con «%s»" -#: pg_amcheck.c:2133 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "error interno: se recibió pattern_id de relación inesperado (%d)" diff --git a/src/bin/pg_amcheck/po/fr.po b/src/bin/pg_amcheck/po/fr.po index 9fc553f23b70c..14157b066b0b5 100644 --- a/src/bin/pg_amcheck/po/fr.po +++ b/src/bin/pg_amcheck/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-14 10:19+0000\n" -"PO-Revision-Date: 2022-05-14 17:15+0200\n" +"POT-Creation-Date: 2024-08-29 17:53+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,33 +19,100 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "erreur : " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "attention : " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "détail : " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "astuce : " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation %s" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "n'a pas pu trouver l'identifiant réel %ld de l'utilisateur : %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "l'utilisateur n'existe pas" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Requête d'annulation envoyée\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "N'a pas pu envoyer la requête d'annulation : " @@ -54,7 +121,7 @@ msgstr "N'a pas pu envoyer la requête d'annulation : " msgid "could not connect to database %s: out of memory" msgstr "n'a pas pu se connecter à la base de données %s : plus de mémoire" -#: ../../fe_utils/connect_utils.c:117 +#: ../../fe_utils/connect_utils.c:116 #, c-format msgid "%s" msgstr "%s" @@ -69,174 +136,214 @@ msgstr "valeur « %s » invalide pour l'option %s" msgid "%s must be in range %d..%d" msgstr "%s doit être compris entre %d et %d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "trop de jobs pour cette plateforme : %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "descripteur de fichier socket hors d'échelle pour select() : %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Essayez moins de jobs." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "le traitement de la base de données « %s » a échoué : %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1645 pg_amcheck.c:2090 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "échec de la requête : %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1100 pg_amcheck.c:1646 pg_amcheck.c:2091 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "La requête était : %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "argument invalide pour l'option %s" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "bloc de début invalide" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "bloc de début hors des limites" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "bloc de fin invalide" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "bloc de fin hors des limites" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "le bloc de fin précède le bloc de début" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "ne peut pas spécifier un nom de base de données avec --all" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "ne peut pas spécifier à la fois le nom d'une base de données et des motifs de noms de base" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "aucune base de données à vérifier" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "base de données « %s » : %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "ignore la base « %s » : amcheck n'est pas installé" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "dans la base de données « %s » : utilisation de la version « %s » d'amcheck dans le schéma « %s »" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "l'option %s n'est pas acceptée par la version « %s » de amcheck" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "aucune table heap à vérifier correspondant à « %s »" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "aucun index btree à vérifier correspondant à « %s »" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "aucune relation à vérifier dans les schémas correspondant à « %s »" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "aucune relation à vérifier correspondant à « %s »" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "aucune relation à vérifier" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "vérification de la table heap « %s %s.%s »" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "vérification de l'index btree « %s %s.%s »" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "erreur de l'envoi d'une commande à la base de données « %s » : %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "La commande était : %s" -#: pg_amcheck.c:1013 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "table heap « %s.%s.%s », bloc %s, décalage %s, attribut %s :\n" -#: pg_amcheck.c:1020 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "table heap « %s.%s.%s », bloc %s, décalage %s :\n" -#: pg_amcheck.c:1026 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "table heap « %s %s.%s », bloc %s :\n" -#: pg_amcheck.c:1031 pg_amcheck.c:1042 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "table heap « %s %s.%s » :\n" -#: pg_amcheck.c:1046 pg_amcheck.c:1115 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "la requête était : %s\n" -#: pg_amcheck.c:1097 +#: pg_amcheck.c:1144 #, c-format msgid "btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d" msgstr "index btree « %s.%s.%s » : la fonction de vérification des index btree a renvoyé un nombre de lignes inattendu : %d" -#: pg_amcheck.c:1101 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "est-ce que les versions de %s et d'amcheck sont compatibles ?" -#: pg_amcheck.c:1111 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "vérification de l'index btree« %s %s.%s » :\n" -#: pg_amcheck.c:1136 +#: pg_amcheck.c:1183 #, c-format msgid "" "%s checks objects in a PostgreSQL database for corruption.\n" @@ -246,17 +353,17 @@ msgstr "" "PostgreSQL sont corrompus.\n" "\n" -#: pg_amcheck.c:1137 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [BASE]\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1186 #, c-format msgid "" "\n" @@ -265,83 +372,83 @@ msgstr "" "\n" "Options de la cible :\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" msgstr " -a, --all vérifie toutes les bases\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" msgstr " -d, --database=MOTIF vérifie les bases correspondantes\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr " -D, --exclude-database=MOTIF ne vérifie PAS les bases correspondantes\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" msgstr " -i, --index=MOTIF vérifie les index correspondants\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" msgstr " -I, --exclude-index=MOTIF ne vérifie PAS les index correspondants\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" msgstr " -r, --relation=MOTIF vérifie les relations correspondantes\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" msgstr " -R, --exclude-relation=MOTIF ne vérifie PAS les relations correspondantes\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" msgstr " -s, --schema=MOTIF vérifie les schémas correspondants\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" msgstr " -S, --exclude-schema=MOTIF ne vérifie PAS les schémas correspondants\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" msgstr " -t, --table=MOTIF vérifie les tables correspondantes\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" msgstr " -T, --exclude-table=MOTIF ne vérifie PAS les tables correspondantes\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1198 #, c-format msgid " --no-dependent-indexes do NOT expand list of relations to include indexes\n" msgstr "" " --no-dependent-indexes n'étend PAS la liste des relations pour inclure\n" " les index\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1199 #, c-format msgid " --no-dependent-toast do NOT expand list of relations to include TOAST tables\n" msgstr "" " --no-dependent-toast n'étend PAS la liste des relations pour inclure\n" " les TOAST\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1200 #, c-format msgid " --no-strict-names do NOT require patterns to match objects\n" msgstr "" " --no-strict-names ne requiert PAS que les motifs correspondent à\n" " des objets\n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1201 #, c-format msgid "" "\n" @@ -350,40 +457,40 @@ msgstr "" "\n" "Options de vérification des tables :\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1202 #, c-format msgid " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" msgstr " --exclude-toast-pointers ne suit PAS les pointeurs de TOAST\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1203 #, c-format msgid " --on-error-stop stop checking at end of first corrupt page\n" msgstr "" " --on-error-stop arrête la vérification à la fin du premier bloc\n" " corrompu\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1204 #, c-format msgid " --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n" msgstr "" " --skip=OPTION ne vérifie PAS les blocs « all-frozen » et\n" " « all-visible »\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1205 #, c-format msgid " --startblock=BLOCK begin checking table(s) at the given block number\n" msgstr "" " --startblock=BLOC commence la vérification des tables au numéro\n" " de bloc indiqué\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1206 #, c-format msgid " --endblock=BLOCK check table(s) only up to the given block number\n" msgstr "" " --endblock=BLOC vérifie les tables jusqu'au numéro de bloc\n" " indiqué\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1207 #, c-format msgid "" "\n" @@ -392,28 +499,33 @@ msgstr "" "\n" "Options de vérification des index Btree :\n" -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1208 +#, c-format +msgid " --checkunique check unique constraint if index is unique\n" +msgstr " --checkunique vérifie l'unicité de l'index pour la contrainte d'unicité\n" + +#: pg_amcheck.c:1209 #, c-format msgid " --heapallindexed check that all heap tuples are found within indexes\n" msgstr "" " --heapallindexed vérifie que tous les enregistrements de la\n" " table sont référencés dans les index\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1210 #, c-format msgid " --parent-check check index parent/child relationships\n" msgstr "" " --parent-check vérifie les relations parent/enfants dans les\n" " index\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1211 #, c-format msgid " --rootdescend search from root page to refind tuples\n" msgstr "" " --rootdescend recherche à partir de la racine pour trouver\n" " les lignes\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1212 #, c-format msgid "" "\n" @@ -422,37 +534,37 @@ msgstr "" "\n" "Options de connexion :\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1213 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HÔTE IP/alias du serveur ou répertoire du socket\n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT port du serveur de bases de données\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=UTILISATEUR nom d'utilisateur pour la connexion\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ne demande jamais un mot de passe\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password force la saisie d'un mot de passe\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE change la base de maintenance\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1219 #, c-format msgid "" "\n" @@ -461,44 +573,44 @@ msgstr "" "\n" "Autres options :\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1220 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo affiche les commandes envoyées au serveur\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1221 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to the server\n" msgstr "" " -j, --jobs=NOMBRE utilise ce nombre de connexions simultanées au\n" " serveur\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress affiche la progression\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose mode verbeux\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1224 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" msgstr " --install-missing installe les extensions manquantes\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1228 #, c-format msgid "" "\n" @@ -507,99 +619,52 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_amcheck.c:1181 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_amcheck.c:1234 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "relations %*s/%s (%d%%), blocs %*s/%s (%d%%) %*s" -#: pg_amcheck.c:1245 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "relations %*s/%s (%d%%), blocs %*s/%s (%d%%) (%s%-*.*s)" -#: pg_amcheck.c:1260 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "relations %*s/%s (%d%%), blocs %*s/%s (%d%%)" -#: pg_amcheck.c:1319 pg_amcheck.c:1352 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s" -#: pg_amcheck.c:1397 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "nom de relation incorrecte (trop de points entre les noms) : %s" -#: pg_amcheck.c:1550 pg_amcheck.c:1689 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "en incluant la base de données : « %s »" -#: pg_amcheck.c:1671 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "erreur interne : a reçu un pattern_id %d inattendu de la base" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "aucune base de données connectable à vérifier correspondant à « %s »" -#: pg_amcheck.c:2131 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "erreur interne : a reçu un pattern_id %d inattendu de la relation" - -#~ msgid "" -#~ "\n" -#~ "Other Options:\n" -#~ msgstr "" -#~ "\n" -#~ "Autres options:\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide, puis quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version, puis quitte\n" - -#~ msgid " -e, --echo show the commands being sent to the server\n" -#~ msgstr " -e, --echo affiche les commandes envoyées au serveur\n" - -#~ msgid " -q, --quiet don't write any messages\n" -#~ msgstr " -q, --quiet n'écrit aucun message\n" - -#~ msgid " -q, --quiet don't write any messages\n" -#~ msgstr " -q, --quiet n'écrit aucun message\n" - -#~ msgid " -v, --verbose write a lot of output\n" -#~ msgstr " -v, --verbose mode verbeux\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "command was: %s" -#~ msgstr "la commande était : %s" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "invalid skip option" -#~ msgstr "option skip invalide" - -#, c-format -#~ msgid "number of parallel jobs must be at least 1" -#~ msgstr "le nombre maximum de jobs en parallèle doit être au moins de 1" - -#~ msgid "number of parallel jobs must be at least 1\n" -#~ msgstr "le nombre de jobs parallèles doit être au moins de 1\n" diff --git a/src/bin/pg_amcheck/po/ja.po b/src/bin/pg_amcheck/po/ja.po index 170a2dc2a4ebd..a4f67dfd21182 100644 --- a/src/bin/pg_amcheck/po/ja.po +++ b/src/bin/pg_amcheck/po/ja.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_amcheck (PostgreSQL 17)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:23+0900\n" -"PO-Revision-Date: 2024-06-14 11:27+0900\n" +"POT-Creation-Date: 2024-08-28 10:42+0900\n" +"PO-Revision-Date: 2024-08-28 11:43+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: \n" "Language: ja\n" @@ -18,22 +18,22 @@ msgstr "" "X-Generator: Poedit 1.8.13\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:278 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:285 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:296 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:303 #, c-format msgid "hint: " msgstr "ヒント: " @@ -252,8 +252,8 @@ msgstr "データベース\"%1$s\"内: スキーマ\"%3$s\"内でamcheck バー #: pg_amcheck.c:624 #, c-format -msgid "--checkunique option is not supported by amcheck version \"%s\"" -msgstr "--checkuniqueオプションはamcheckバージョン\"%s\"ではサポートされていません" +msgid "option %s is not supported by amcheck version %s" +msgstr "%sオプションはamcheckバージョン\"%s\"ではサポートされていません" #: pg_amcheck.c:650 #, c-format diff --git a/src/bin/pg_amcheck/po/ka.po b/src/bin/pg_amcheck/po/ka.po index fb08fc2ae6549..8cf7f280e248b 100644 --- a/src/bin/pg_amcheck/po/ka.po +++ b/src/bin/pg_amcheck/po/ka.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_amcheck (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:22+0000\n" -"PO-Revision-Date: 2024-06-14 06:13+0200\n" +"POT-Creation-Date: 2024-08-27 16:52+0000\n" +"PO-Revision-Date: 2024-08-28 05:43+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -252,8 +252,8 @@ msgstr "ბაზაში \"%s\": გამოიყენება amcheck-ი #: pg_amcheck.c:624 #, c-format -msgid "--checkunique option is not supported by amcheck version \"%s\"" -msgstr "--checkunique პარამეტრის მხარდაჭერა amcheck-ის ვერსიას \"%s\" არ გააჩნია" +msgid "option %s is not supported by amcheck version %s" +msgstr "პარამეტრის '%s' მხარდაჭერა amcheck-ის ვერსიას \"%s\" არ გააჩნია" #: pg_amcheck.c:650 #, c-format diff --git a/src/bin/pg_amcheck/po/ko.po b/src/bin/pg_amcheck/po/ko.po index cef3583a4432e..d5e78e4f22c7f 100644 --- a/src/bin/pg_amcheck/po/ko.po +++ b/src/bin/pg_amcheck/po/ko.po @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_amcheck (PostgreSQL) 16\n" +"Project-Id-Version: pg_amcheck (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:51+0000\n" -"PO-Revision-Date: 2023-05-30 12:37+0900\n" +"POT-Creation-Date: 2025-01-17 04:52+0000\n" +"PO-Revision-Date: 2025-01-17 18:01+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -36,11 +36,78 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위한 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일 상태 정보를 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법은 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "사용자 ID(%ld)를 찾을 수 없음: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "사용자 없음" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "사용자 이름 찾기 실패: 오류 코드 %lu" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "취소 요청 보냄\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "취소 요청 보내기 실패: " @@ -64,195 +131,235 @@ msgstr "\"%s\" 값은 %s 옵션의 값으로 적당하지 않음" msgid "%s must be in range %d..%d" msgstr "%s 값은 %d부터 %d까지만 허용합니다" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "이 플랫폼에서는 너무 많은 job 입니다: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "select() 작업 범위를 벗어나는 소켓 파일 기술자: %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "job 수를 줄여주세요." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "\"%s\" 데이터베이스 처리 중 오류 발생: %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1647 pg_amcheck.c:2092 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "쿼리 실패: %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1102 pg_amcheck.c:1648 pg_amcheck.c:2093 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "사용한 쿼리: %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "%s 옵션의 잘못된 인자" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "시작 블록이 유효하지 않음" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "시작 블록이 범위를 벗어남" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "마지막 블록이 유효하지 않음" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "마지막 블록이 범위를 벗어남" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보십시오." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "마지막 블록이 시작 블록보다 앞에 존재함" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인자를 지정했습니다. (처음 \"%s\")" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "데이터베이스 이름을 —all 와 같이 지정할 수 없습니다" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "데이터베이스 이름과 형식을 지정할 수 없습니다" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "확인할 데이터베이스가 없습니다" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "데이터베이스 “%s”: %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "데이터베이스 생략 “%s”: amcheck 가 설치되지 않음" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "데이터베이스 “%s”: 사용하는 amcheck 버전 “%s” 스키마 “%s”" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "%s 옵션은 %s 버전 amcheck에서 지원하지 않음" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "“%s” 와 일치하는 heap 테이블을 찾을 수 없습니다" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "“%s” 와 일치하는 btree 인덱스를 찾을 수 없습니다" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "스키마에서 “%s” 와 일치하는 릴레이션을 찾을 수 없습니다" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "“%s” 와 일치하는 릴레이션을 찾을 수 없습니다" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "확인할 릴레이션이 없습니다" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "heap 테이블 확인 “%s.%s.%s”" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "btree 인덱스 확인 “%s.%s.%s”" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "데이터베이스에 명령을 보내는 중 오류 발생 “%s”: %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "사용한 명령: %s" -#: pg_amcheck.c:1015 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "heap 테이블 “%s.%s.%s”, 블록 %s, 오프셋 %s, 에트리뷰트 %s:\n" -#: pg_amcheck.c:1022 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "heap 테이블 “%s.%s.%s”, 블록 %s, 오프셋 %s:\n" -#: pg_amcheck.c:1028 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "heap 테이블 “%s.%s.%s”, 블록 %s:\n" -#: pg_amcheck.c:1033 pg_amcheck.c:1044 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "heap 테이블 “%s.%s.%s”:\n" -#: pg_amcheck.c:1048 pg_amcheck.c:1117 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "사용한 쿼리: %s\n" -#: pg_amcheck.c:1099 +#: pg_amcheck.c:1144 #, c-format msgid "" "btree index \"%s.%s.%s\": btree checking function returned unexpected number " "of rows: %d" msgstr "btree 인덱스 “%s.%s.%s”: btree 확인 중에 예기치 않은 행수를 반환함: %d" -#: pg_amcheck.c:1103 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "%s 버전과 amcheck의 버전이 호환 가능합니까?" -#: pg_amcheck.c:1113 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "btree 인덱스 “%s.%s.%s”:\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1183 #, c-format msgid "" "%s checks objects in a PostgreSQL database for corruption.\n" "\n" msgstr "" -"%s 가 PostgreSQL 데이터베이스 개체 손상 여부를 검사합니다.\n" +"%s는 PostgreSQL 데이터베이스 개체 손상 여부를 검사합니다.\n" "\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [옵션]... [DB이름]\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1186 #, c-format msgid "" "\n" @@ -261,85 +368,85 @@ msgstr "" "\n" "사용가능한 옵션들:\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" -msgstr " -a, —all 모든 데이터베이스를 검사\n" +msgstr " -a, -—all 모든 데이터베이스를 검사\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" -msgstr " -d, —database=PATTERN 일치하는 모든 데이터베이스를 검사\n" +msgstr " -d, -—database=PATTERN 일치하는 모든 데이터베이스를 검사\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr "" -" -D, —exclude-database=PATTERN 일치하는 데이터베이스를 제외 하고 검사\n" +" -D, -—exclude-database=PATTERN 일치하는 데이터베이스를 제외 하고 검사\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" -msgstr " -i, —index=PATTERN 일치하는 인덱스를 검사\n" +msgstr " -i, -—index=PATTERN 일치하는 인덱스를 검사\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" -msgstr " -I, —exclude-index=PATTERN 일치하는 인덱스를 제외하고 검사\n" +msgstr " -I, -—exclude-index=PATTERN 일치하는 인덱스를 제외하고 검사\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" -msgstr " -r, —relation=PATTERN 일치하는 릴레이션을 검사\n" +msgstr " -r, -—relation=PATTERN 일치하는 릴레이션을 검사\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" -msgstr " -R, —exclude-relation=PATTERN 일치하는 릴레이션을 제외하고 검사\n" +msgstr " -R, -—exclude-relation=PATTERN 일치하는 릴레이션을 제외하고 검사\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" -msgstr " -s, —schema=PATTERN 일치하는 스키마를 검사\n" +msgstr " -s, -—schema=PATTERN 일치하는 스키마를 검사\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" -msgstr " -S, —exclude-schema=PATTERN 일치하는 스키마를 제외하고 검사\n" +msgstr " -S, -—exclude-schema=PATTERN 일치하는 스키마를 제외하고 검사\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" -msgstr " -t, —table=PATTERN 일치하는 테이블을 검사\n" +msgstr " -t, -—table=PATTERN 일치하는 테이블을 검사\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" -msgstr " -T, —exclude-table=PATTERN 일치하는 테이블을 제외하고 검사\n" +msgstr " -T, -—exclude-table=PATTERN 일치하는 테이블을 제외하고 검사\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1198 #, c-format msgid "" " --no-dependent-indexes do NOT expand list of relations to include " "indexes\n" -msgstr " —no-dependent-indexes 릴레이션에 인덱스를 포함하지 않음 \n" +msgstr " -—no-dependent-indexes 릴레이션에 인덱스를 포함하지 않음 \n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1199 #, c-format msgid "" " --no-dependent-toast do NOT expand list of relations to include " "TOAST tables\n" msgstr "" -" —no-dependent-toast 릴레이션에 TOAST 테이블을 포함하지 않음\n" +" -—no-dependent-toast 릴레이션에 TOAST 테이블을 포함하지 않음\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1200 #, c-format msgid "" " --no-strict-names do NOT require patterns to match objects\n" msgstr "" -" —no-strict-names 개체가 패턴과 일치하지 않아도 허용함\n" +" -—no-strict-names 개체가 패턴과 일치하지 않아도 허용함\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1201 #, c-format msgid "" "\n" @@ -348,45 +455,45 @@ msgstr "" "\n" "테이블 검사 옵션들:\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1202 #, c-format msgid "" " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" -msgstr " —exclude-toast-pointers TOAST 포인터를 확인하지 않음\n" +msgstr " -—exclude-toast-pointers TOAST 포인터를 확인하지 않음\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1203 #, c-format msgid "" " --on-error-stop stop checking at end of first corrupt " "page\n" -msgstr " —on-error-stop 손상된 페이지 끝에서 검사를 멈춤\n" +msgstr " -—on-error-stop 손상된 페이지 끝에서 검사를 멈춤\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1204 #, c-format msgid "" " --skip=OPTION do NOT check \"all-frozen\" or \"all-" "visible\" blocks\n" msgstr "" -" —skip=OPTION “all-frozen” 또는 “all-visible” 블록을 검사" -"하지 않음\n" +" -—skip=OPTION \"all-frozen\" 또는 \"all-visible\" 블록을 " +"검사하지 않음\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1205 #, c-format msgid "" " --startblock=BLOCK begin checking table(s) at the given block " "number\n" msgstr "" -" —startblock=BLOCK 지정된 블록 번호부터 테이블 검사를 시작\n" +" -—startblock=BLOCK 지정된 블록 번호부터 테이블 검사를 시작\n" -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1206 #, c-format msgid "" " --endblock=BLOCK check table(s) only up to the given block " "number\n" msgstr "" -" —endblock=BLOCK 지정된 블록 번호까지 테이블 검사 마침 \n" +" -—endblock=BLOCK 지정된 블록 번호까지 테이블 검사 마침\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1207 #, c-format msgid "" "\n" @@ -395,27 +502,35 @@ msgstr "" "\n" "B-tree 인덱스 검사 옵션들:\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1208 +#, c-format +msgid "" +" --checkunique check unique constraint if index is " +"unique\n" +msgstr "" +" --checkunique 유니크 인덱스라면 유니크 제약조건 검사\n" + +#: pg_amcheck.c:1209 #, c-format msgid "" " --heapallindexed check that all heap tuples are found " "within indexes\n" msgstr "" -" —heapallindexed 모든 heap 튜플이 인덱스 내에 있는지 검사\n" +" -—heapallindexed 모든 heap 튜플이 인덱스 내에 있는지 검사\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1210 #, c-format msgid "" " --parent-check check index parent/child relationships\n" -msgstr " —parent-check 인덱스의 부모/자식 관계를 검사\n" +msgstr " -—parent-check 인덱스의 부모/자식 관계를 검사\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1211 #, c-format msgid "" " --rootdescend search from root page to refind tuples\n" -msgstr " —rootdescend 루트 페이지 부터 튜플을 다시 찾음 \n" +msgstr " —-rootdescend 루트 페이지 부터 튜플을 다시 찾음 \n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1212 #, c-format msgid "" "\n" @@ -424,40 +539,40 @@ msgstr "" "\n" "연결 옵션들:\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1213 #, c-format msgid "" " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, —host=HOSTNAME 데이터베이스 서버 호스트 또는 소켓의 디렉터" +" -h, -—host=HOSTNAME 데이터베이스 서버 호스트 또는 소켓의 디렉터" "리\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" -msgstr " -p, —port=PORT 데이터베이스 서버 포트\n" +msgstr " -p, -—port=PORT 데이터베이스 서버 포트\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" -msgstr " -U, —username=USERNAME 연결할 유저 이름\n" +msgstr " -U, -—username=USERNAME 연결할 유저 이름\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" -msgstr " -w, —no-password 암호 입력 프롬프트가 나타나지 않음\n" +msgstr " -w, -—no-password 암호 입력 프롬프트가 나타나지 않음\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" -msgstr " -W, —password 암호 입력 프롬프트가 나타남\n" +msgstr " -W, -—password 암호 입력 프롬프트가 나타남\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" -msgstr " —maintenance-db=DBNAME 대체 연결 데이터베이스\n" +msgstr " -—maintenance-db=DBNAME 대체 연결 데이터베이스\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1219 #, c-format msgid "" "\n" @@ -466,47 +581,47 @@ msgstr "" "\n" "기타 옵션:\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1220 #, c-format msgid "" " -e, --echo show the commands being sent to the " "server\n" msgstr " -e, --echo 서버로 보내는 명령들을 보여줌\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1221 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " "the server\n" -msgstr " -j, —jobs=NUM 서버에 동시 연결할 수를 지정\n" +msgstr " -j, -—jobs=NUM 서버에 동시 연결할 수를 지정\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" -msgstr " -P, —progress 진행 사항 정보를 보여줌\n" +msgstr " -P, -—progress 진행 사항 정보를 보여줌\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 작업내역의 자세한 출력\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1224 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_amcheck.c:1179 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" -msgstr " —install-missing 누락된 익스텐션을 설치\n" +msgstr " -—install-missing 누락된 익스텐션을 설치\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 도움말을 표시하고 종료\n" -#: pg_amcheck.c:1182 +#: pg_amcheck.c:1228 #, c-format msgid "" "\n" @@ -515,52 +630,52 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_amcheck.c:1183 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_amcheck.c:1236 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "%*s/%s 릴레이션 (%d%%), %*s/%s 페이지 (%d%%) %*s" -#: pg_amcheck.c:1247 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "%*s/%s 릴레이션 (%d%%), %*s/%s 페이지 (%d%%) (%s%-*.*s)" -#: pg_amcheck.c:1262 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "%*s/%s 릴레이션 (%d%%), %*s/%s 페이지 (%d%%)" -#: pg_amcheck.c:1321 pg_amcheck.c:1354 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "바르지 못한 규정 이름(점으로 구분된 이름이 너무 많음): %s" -#: pg_amcheck.c:1399 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "바르지 못한 릴레이션 이름(점으로 구분된 이름이 너무 많음): %s" -#: pg_amcheck.c:1552 pg_amcheck.c:1691 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "“%s” 데이터베이스를 포함합니다" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "내부 오류: 올바르지 않은 데이터베이스 패턴 아이디 %d" -#: pg_amcheck.c:1675 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "“%s” 와 일치하는 연결 가능한 데이터베이스를 찾을 수 없음" -#: pg_amcheck.c:2133 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "내부 오류: 올바르지 않은 릴레이션 패턴 아이디 %d" diff --git a/src/bin/pg_amcheck/po/meson.build b/src/bin/pg_amcheck/po/meson.build index 8ab3577dd29ed..d1bfa58cd795e 100644 --- a/src/bin/pg_amcheck/po/meson.build +++ b/src/bin/pg_amcheck/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_amcheck-' + pg_version_major.to_string())] diff --git a/src/bin/pg_amcheck/po/ru.po b/src/bin/pg_amcheck/po/ru.po index c6be3badc0d35..0889dfb2f8ebc 100644 --- a/src/bin/pg_amcheck/po/ru.po +++ b/src/bin/pg_amcheck/po/ru.po @@ -1,10 +1,10 @@ -# Alexander Lakhin , 2021, 2022. +# Alexander Lakhin , 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pg_amcheck (PostgreSQL) 14\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2022-09-05 13:33+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-05 08:23+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -32,11 +32,78 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "выяснить эффективный идентификатор пользователя (%ld) не удалось: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "пользователь не существует" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "распознать имя пользователя не удалось (код ошибки: %lu)" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Сигнал отмены отправлен\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Отправить сигнал отмены не удалось: " @@ -60,160 +127,203 @@ msgstr "неверное значение \"%s\" для параметра %s" msgid "%s must be in range %d..%d" msgstr "значение %s должно быть в диапазоне %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "слишком много заданий для этой платформы: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "дескриптор файла сокета вне диапазона, допустимого для select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Попробуйте уменьшить количество заданий." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "ошибка при обработке базы \"%s\": %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1647 pg_amcheck.c:2092 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "ошибка при выполнении запроса: %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1102 pg_amcheck.c:1648 pg_amcheck.c:2093 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "Выполнялся запрос: %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "недопустимый аргумент параметра %s" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "неверный начальный блок" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "начальный блок вне допустимых пределов" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "неверный конечный блок" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "конечный блок вне допустимых пределов" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "конечный блок предшествует начальному" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "имя базы данных нельзя задавать с --all" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "нельзя задавать одновременно имя базы данных и шаблоны имён" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "не указаны базы для проверки" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "база данных \"%s\": %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "база \"%s\" пропускается: расширение amcheck не установлено" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "база \"%s\": используется amcheck версии \"%s\" в схеме \"%s\"" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "параметр %s не поддерживается версией amcheck %s" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "не найдены подлежащие проверке базовые таблицы, соответствующие \"%s\"" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "не найдены подлежащие проверке индексы btree, соответствующие \"%s\"" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "" "не найдены подлежащие проверке отношения в схемах, соответствующих \"%s\"" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "не найдены подлежащие проверке отношения, соответствующие \"%s\"" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "не найдены отношения для проверки" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "проверка базовой таблицы \"%s.%s.%s\"" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "проверка индекса btree \"%s.%s.%s\"" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "ошибка передачи команды базе \"%s\": %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "Выполнялась команда: %s" -#: pg_amcheck.c:1015 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "базовая таблица \"%s.%s.%s\", блок %s, смещение %s, атрибут %s:\n" -#: pg_amcheck.c:1022 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "базовая таблица \"%s.%s.%s\", блок %s, смещение %s:\n" -#: pg_amcheck.c:1028 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "базовая таблица \"%s.%s.%s\", блок %s:\n" -#: pg_amcheck.c:1033 pg_amcheck.c:1044 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "базовая таблица \"%s.%s.%s\":\n" -#: pg_amcheck.c:1048 pg_amcheck.c:1117 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "запрос: %s\n" -#: pg_amcheck.c:1099 +#: pg_amcheck.c:1144 #, c-format msgid "" "btree index \"%s.%s.%s\": btree checking function returned unexpected number " @@ -222,17 +332,17 @@ msgstr "" "индекс btree \"%s.%s.%s\": функция проверки btree выдала неожиданное " "количество строк: %d" -#: pg_amcheck.c:1103 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "Совместимы ли версии %s и amcheck?" -#: pg_amcheck.c:1113 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "индекс btree \"%s.%s.%s\":\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1183 #, c-format msgid "" "%s checks objects in a PostgreSQL database for corruption.\n" @@ -241,17 +351,17 @@ msgstr "" "%s проверяет объекты в базе данных PostgreSQL на предмет повреждений.\n" "\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [ПАРАМЕТР]... [ИМЯ_БД]\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1186 #, c-format msgid "" "\n" @@ -260,77 +370,77 @@ msgstr "" "\n" "Параметры выбора объектов:\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" msgstr " -a, --all проверить все базы\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" msgstr "" " -d, --database=ШАБЛОН проверить соответствующие шаблону базы\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr "" " -D, --exclude-database=ШАБЛОН не проверять соответствующие шаблону базы\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" msgstr "" " -i, --index=ШАБЛОН проверить соответствующие шаблону индексы\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" msgstr "" " -I, --exclude-index=ШАБЛОН не проверять соответствующие шаблону " "индексы\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" msgstr "" " -r, --relation=ШАБЛОН проверить соответствующие шаблону " "отношения\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" msgstr "" " -R, --exclude-relation=ШАБЛОН не проверять соответствующие шаблону " "отношения\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" msgstr "" " -s, --schema=ШАБЛОН проверить соответствующие шаблону схемы\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" msgstr "" " -S, --exclude-schema=ШАБЛОН не проверять соответствующие шаблону " "схемы\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" msgstr "" " -t, --table=ШАБЛОН проверить соответствующие шаблону таблицы\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" msgstr "" " -T, --exclude-table=ШАБЛОН не проверять соответствующие шаблону " "таблицы\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1198 #, c-format msgid "" " --no-dependent-indexes do NOT expand list of relations to include " @@ -339,7 +449,7 @@ msgstr "" " --no-dependent-indexes не включать в список проверяемых отношений " "индексы\n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1199 #, c-format msgid "" " --no-dependent-toast do NOT expand list of relations to include " @@ -348,7 +458,7 @@ msgstr "" " --no-dependent-toast не включать в список проверяемых отношений " "TOAST-таблицы\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1200 #, c-format msgid "" " --no-strict-names do NOT require patterns to match objects\n" @@ -356,7 +466,7 @@ msgstr "" " --no-strict-names не требовать наличия объектов, " "соответствующих шаблонам\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1201 #, c-format msgid "" "\n" @@ -365,14 +475,14 @@ msgstr "" "\n" "Параметры проверки таблиц:\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1202 #, c-format msgid "" " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" msgstr "" " --exclude-toast-pointers не переходить по указателям в TOAST\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1203 #, c-format msgid "" " --on-error-stop stop checking at end of first corrupt " @@ -381,7 +491,7 @@ msgstr "" " --on-error-stop прекратить проверку по достижении конца " "первой повреждённой страницы\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1204 #, c-format msgid "" " --skip=OPTION do NOT check \"all-frozen\" or \"all-" @@ -390,7 +500,7 @@ msgstr "" " --skip=ТИП_БЛОКА не проверять блоки типа \"all-frozen\" или " "\"all-visible\"\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1205 #, c-format msgid "" " --startblock=BLOCK begin checking table(s) at the given block " @@ -400,7 +510,7 @@ msgstr "" "заданным номером\n" # skip-rule: no-space-before-parentheses -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1206 #, c-format msgid "" " --endblock=BLOCK check table(s) only up to the given block " @@ -409,7 +519,7 @@ msgstr "" " --endblock=БЛОК проверить таблицы(у) до блока с заданным " "номером\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1207 #, c-format msgid "" "\n" @@ -418,7 +528,16 @@ msgstr "" "\n" "Параметры проверки индексов-B-деревьев:\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1208 +#, c-format +msgid "" +" --checkunique check unique constraint if index is " +"unique\n" +msgstr "" +" --checkunique проверить ограничение уникальности для " +"уникальных индексов\n" + +#: pg_amcheck.c:1209 #, c-format msgid "" " --heapallindexed check that all heap tuples are found " @@ -427,7 +546,7 @@ msgstr "" " --heapallindexed проверить, что всем кортежам кучи " "находится соответствие в индексах\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1210 #, c-format msgid "" " --parent-check check index parent/child relationships\n" @@ -435,7 +554,7 @@ msgstr "" " --parent-check проверить связи родитель/потомок в " "индексах\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1211 #, c-format msgid "" " --rootdescend search from root page to refind tuples\n" @@ -443,7 +562,7 @@ msgstr "" " --rootdescend перепроверять поиск кортежей от корневой " "страницы\n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1212 #, c-format msgid "" "\n" @@ -452,42 +571,42 @@ msgstr "" "\n" "Параметры подключения:\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1213 #, c-format msgid "" " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог " -"сокетов\n" +" -h, --host=ИМЯ компьютер с сервером баз данных или " +"каталог сокетов\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=ПОРТ порт сервера баз данных\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr "" " -U, --username=ИМЯ имя пользователя для подключения к " "серверу\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password запросить пароль\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=ИМЯ_БД другая опорная база данных\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1219 #, c-format msgid "" "\n" @@ -496,7 +615,7 @@ msgstr "" "\n" "Другие параметры:\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1220 #, c-format msgid "" " -e, --echo show the commands being sent to the " @@ -504,7 +623,7 @@ msgid "" msgstr "" " -e, --echo отображать команды, отправляемые серверу\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1221 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " @@ -513,33 +632,33 @@ msgstr "" " -j, --jobs=ЧИСЛО устанавливать заданное число подключений к " "серверу\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress показывать прогресс операции\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose выводить исчерпывающие сообщения\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1224 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_amcheck.c:1179 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" msgstr " --install-missing установить недостающие расширения\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_amcheck.c:1182 +#: pg_amcheck.c:1228 #, c-format msgid "" "\n" @@ -548,53 +667,53 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_amcheck.c:1183 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_amcheck.c:1236 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "отношений: %*s/%s (%d%%), страниц: %*s/%s (%d%%) %*s" -#: pg_amcheck.c:1247 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "отношений: %*s/%s (%d%%), страниц: %*s/%s (%d%%) (%s%-*.*s)" -#: pg_amcheck.c:1262 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "отношений: %*s/%s (%d%%), страниц: %*s/%s (%d%%)" -#: pg_amcheck.c:1321 pg_amcheck.c:1354 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неверное полное имя (слишком много компонентов): %s" -#: pg_amcheck.c:1399 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неверное имя отношения (слишком много компонентов): %s" -#: pg_amcheck.c:1552 pg_amcheck.c:1691 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "выбирается база \"%s\"" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "внутренняя ошибка: получен неожиданный идентификатор шаблона базы %d" -#: pg_amcheck.c:1675 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "" "не найдены подлежащие проверке доступные базы, соответствующие шаблону \"%s\"" -#: pg_amcheck.c:2133 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "" diff --git a/src/bin/pg_amcheck/po/sv.po b/src/bin/pg_amcheck/po/sv.po index 2a9ee08207df0..6db26dc737657 100644 --- a/src/bin/pg_amcheck/po/sv.po +++ b/src/bin/pg_amcheck/po/sv.po @@ -1,14 +1,14 @@ # SWEDISH message translation file for pg_amcheck # Copyright (C) 2021 PostgreSQL Global Development Group # This file is distributed under the same license as the pg_amcheck (PostgreSQL) package. -# Dennis Björklund , 2021, 2022. +# Dennis Björklund , 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-09 18:50+0000\n" -"PO-Revision-Date: 2023-09-05 08:59+0200\n" +"POT-Creation-Date: 2024-08-27 15:52+0000\n" +"PO-Revision-Date: 2024-08-27 18:29+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -16,31 +16,98 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "fel: " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "varning: " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "detalj: " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "tips: " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "kunde inte slå upp effektivt användar-id %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "användaren finns inte" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "misslyckad sökning efter användarnamn: felkod %lu" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Förfrågan om avbrytning skickad\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Kunde inte skicka förfrågan om avbrytning: " @@ -49,7 +116,7 @@ msgstr "Kunde inte skicka förfrågan om avbrytning: " msgid "could not connect to database %s: out of memory" msgstr "kunde inte ansluta till databas %s: slut på minne" -#: ../../fe_utils/connect_utils.c:117 +#: ../../fe_utils/connect_utils.c:116 #, c-format msgid "%s" msgstr "%s" @@ -64,174 +131,214 @@ msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" msgid "%s must be in range %d..%d" msgstr "%s måste vara i intervallet %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "för många jobb för denna plattform: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "deskriptor-index utanför sitt intervall för select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Försök med färre job." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "processande av databas \"%s\" misslyckades: %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1645 pg_amcheck.c:2090 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "fråga misslyckades: %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1100 pg_amcheck.c:1646 pg_amcheck.c:2091 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "Frågan var: %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "ogiltigt argument för flaggan %s" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "ogiltigt startblock" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "startblocket utanför giltig gräns" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "ogiltigt slutblock" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "slutblocket utanför giltig gräns" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "slutblocket kommer före startblocket" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "kan inte ange databasnamn tillsammans med --all" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "kan inte ange både ett databasnamn och ett databasmönster" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "inga databaser att kontrollera" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "databas \"%s\": %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "hoppar över databas \"%s\": amcheck är inte installerad" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "i databas \"%s\": använder amcheck version \"%s\" i schema \"%s\"" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "flaggan %s stöds inte av amcheck version %s" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "finns inga heap-tabeller för att kontrollera matchning \"%s\"" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "finns inga btree-index för att kontrollera matching \"%s\"" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "finns inga relationer att kontrollera i schemamatchning \"%s\"" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "finns inga relations för att kontrollera matching \"%s\"" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "finns inga relationer att kontrollera" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "kontrollerar heap-tabell \"%s.%s.%s\"" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "kontrollerar btree-index \"%s.%s.%s\"" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "fel vid skickande av kommando till databas \"%s\": %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "Kommandot var: %s" -#: pg_amcheck.c:1013 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "heap-tabell \"%s.%s.%s\", block %s, offset %s, attribut %s:\n" -#: pg_amcheck.c:1020 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "heap-tabell \"%s.%s.%s\", block %s, offset %s:\n" -#: pg_amcheck.c:1026 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "heap-tabell \"%s.%s.%s\", block %s:\n" -#: pg_amcheck.c:1031 pg_amcheck.c:1042 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "heap-tabell \"%s.%s.%s\":\n" -#: pg_amcheck.c:1046 pg_amcheck.c:1115 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "frågan var: %s\n" -#: pg_amcheck.c:1097 +#: pg_amcheck.c:1144 #, c-format msgid "btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d" msgstr "btree-index \"%s.%s.%s\": kontrollfunktion för btree returnerade oväntat antal rader: %d" -#: pg_amcheck.c:1101 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "Är versionerna på %s och amcheck kompatibla?" -#: pg_amcheck.c:1111 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "btree-index \"%s.%s.%s\":\n" -#: pg_amcheck.c:1136 +#: pg_amcheck.c:1183 #, c-format msgid "" "%s checks objects in a PostgreSQL database for corruption.\n" @@ -240,17 +347,17 @@ msgstr "" "%s kontrollerar objekt i en PostgreSQL-database för att hitta korruption.\n" "\n" -#: pg_amcheck.c:1137 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [FLAGGA]... [DBNAMN]\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1186 #, c-format msgid "" "\n" @@ -259,77 +366,77 @@ msgstr "" "\n" "Flaggor för destinationen:\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" msgstr " -a, --all kontrollera alla databaser\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" msgstr " -d, --database=MALL kontrollera matchande databas(er)\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr " -D, --exclude-database=MALL kontrollera INTE matchande databas(er)\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" msgstr " -i, --index=MALL kontrollera matchande index\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" msgstr " -I, --exclude-index=MALL kontrollera INTE matchande index\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" msgstr " -r, --relation=MALL kontrollera matchande relation(er)\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" msgstr " -R, --exclude-relation=MALL kontrollera INTE matchande relation(er)\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" msgstr " -s, --schema=MALL kontrollera matchande schema(n)\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" msgstr " -S, --exclude-schema=MALL kontrollera INTE matchande schema(n)\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" msgstr " -t, --table=MALL kontollera matchande tabell(er)\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" msgstr " -T, --exclude-table=MALL kontollera INTE matchande tabell(er)\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1198 #, c-format msgid " --no-dependent-indexes do NOT expand list of relations to include indexes\n" msgstr " --no-dependent-indexes expandera INTE listan med relationer för att inkludera index\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1199 #, c-format msgid " --no-dependent-toast do NOT expand list of relations to include TOAST tables\n" msgstr " --no-dependent-toast expandera inte listan av relationer för att inkludera TOAST-tabeller\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1200 #, c-format msgid " --no-strict-names do NOT require patterns to match objects\n" msgstr " --no-strict-names kräv INTE mallar för matcha objekt\n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1201 #, c-format msgid "" "\n" @@ -338,32 +445,32 @@ msgstr "" "\n" "Flaggor för kontroll av tabeller:\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1202 #, c-format msgid " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" msgstr " --exclude-toast-pointers följ INTE relationers TOAST-pekare\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1203 #, c-format msgid " --on-error-stop stop checking at end of first corrupt page\n" msgstr " --on-error-stop sluta kontrollera efter första korrupta sidan\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1204 #, c-format msgid " --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n" msgstr " --skip=FLAGGA kontrollera INTE block som är \"all-frozen\" eller \"all-visible\"\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1205 #, c-format msgid " --startblock=BLOCK begin checking table(s) at the given block number\n" msgstr " --startblock=BLOCK börja kontollera tabell(er) vid angivet blocknummer\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1206 #, c-format msgid " --endblock=BLOCK check table(s) only up to the given block number\n" msgstr " --endblock=BLOCK kontrollera tabell(er) fram till angivet blocknummer\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1207 #, c-format msgid "" "\n" @@ -372,22 +479,27 @@ msgstr "" "\n" "Flaggor för kontroll av B-tree-index:\n" -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1208 +#, c-format +msgid " --checkunique check unique constraint if index is unique\n" +msgstr " --checkunique verifiera unik-villkor om indexet är unikt\n" + +#: pg_amcheck.c:1209 #, c-format msgid " --heapallindexed check that all heap tuples are found within indexes\n" msgstr " --heapallindexed kontrollera att alla heap-tupler hittas i index\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1210 #, c-format msgid " --parent-check check index parent/child relationships\n" msgstr " --parent-check kontrollera förhållandet mellan barn/förälder i index\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1211 #, c-format msgid " --rootdescend search from root page to refind tuples\n" msgstr " --rootdescend sök från root-sidan för att återfinna tupler\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1212 #, c-format msgid "" "\n" @@ -396,37 +508,37 @@ msgstr "" "\n" "Flaggor för anslutning:\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1213 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT databasserverns port\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ANVÄNDARE användarnamn att ansluta som\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga ej efter lösenord\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password tvinga fram lösenordsfråga\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAMN val av underhållsdatabas\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1219 #, c-format msgid "" "\n" @@ -435,42 +547,42 @@ msgstr "" "\n" "Andra flaggor:\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1220 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo visa kommandon som skickas till servern\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1221 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to the server\n" msgstr " -j, --jobs=NUM antal samtidiga anslutningar till servern\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress visa förloppsinformation\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose skriv massor med utdata\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1224 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" msgstr " --install-missing installera utökningar som saknas\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1228 #, c-format msgid "" "\n" @@ -479,68 +591,52 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_amcheck.c:1181 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_amcheck.c:1234 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "%*s/%s relationer (%d%%), %*s/%s sidor (%d%%) %*s" -#: pg_amcheck.c:1245 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "%*s/%s relationer (%d%%), %*s/%s sidor (%d%%) (%s%-*.*s)" -#: pg_amcheck.c:1260 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "%*s/%s relationer (%d%%), %*s/%s sidor (%d%%)" -#: pg_amcheck.c:1319 pg_amcheck.c:1352 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "ej korrekt kvalificerat namn (för många namn med punkt): %s" -#: pg_amcheck.c:1397 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "ej korrekt relationsnamn (för många namn med punkt): %s" -#: pg_amcheck.c:1550 pg_amcheck.c:1689 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "inkludera databas \"%s\"" -#: pg_amcheck.c:1671 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "internt fel: tog emot oväntat pattern_id %d för databas" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "finns inga anslutningsbara databaser att kontrollera som matchar \"%s\"" -#: pg_amcheck.c:2131 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "internt fel: tog emot oväntat pattern_id %d för relation" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Försök med \"%s --help\" för mer information.\n" - -#, c-format -#~ msgid "command was: %s" -#~ msgstr "kommandot var: %s" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatalt: " - -#, c-format -#~ msgid "number of parallel jobs must be at least 1" -#~ msgstr "antalet parallella jobb måste vara minst 1" diff --git a/src/bin/pg_amcheck/po/uk.po b/src/bin/pg_amcheck/po/uk.po index 601e0434da1e5..7ce979b0ea83b 100644 --- a/src/bin/pg_amcheck/po/uk.po +++ b/src/bin/pg_amcheck/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:50+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:23+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_amcheck.pot\n" -"X-Crowdin-File-ID: 892\n" +"X-Crowdin-File: /REL_17_STABLE/pg_amcheck.pot\n" +"X-Crowdin-File-ID: 1036\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,11 +37,78 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "не можу знайти користувача з ефективним ID %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "користувача не існує" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "невдала підстановка імені користувача: код помилки %lu" + +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Запит на скасування відправлений\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Не вдалося надіслати запит на скасування: " @@ -50,7 +117,7 @@ msgstr "Не вдалося надіслати запит на скасуван msgid "could not connect to database %s: out of memory" msgstr "не можливо під'єднатися до бази даних %s: не вистачає пам'яті" -#: ../../fe_utils/connect_utils.c:117 +#: ../../fe_utils/connect_utils.c:116 #, c-format msgid "%s" msgstr "%s" @@ -65,451 +132,496 @@ msgstr "неприпустиме значення \"%s\" для параметр msgid "%s must be in range %d..%d" msgstr "%s має бути в діапазоні %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "занадто багато завдань для цієї платформи: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "дескриптор файлу сокету поза діапазоном для select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Спробуйте менше робочих завдань." + +#: ../../fe_utils/parallel_slot.c:553 +#, c-format +msgid "processing of database \"%s\" failed: %s" +msgstr "обробка бази даних \"%s\" не вдалась: %s" + #: ../../fe_utils/query_utils.c:33 ../../fe_utils/query_utils.c:58 -#: pg_amcheck.c:1647 pg_amcheck.c:2092 +#: pg_amcheck.c:1693 pg_amcheck.c:2138 #, c-format msgid "query failed: %s" msgstr "запит не вдався: %s" #: ../../fe_utils/query_utils.c:34 ../../fe_utils/query_utils.c:59 -#: pg_amcheck.c:571 pg_amcheck.c:1102 pg_amcheck.c:1648 pg_amcheck.c:2093 +#: pg_amcheck.c:578 pg_amcheck.c:1147 pg_amcheck.c:1694 pg_amcheck.c:2139 #, c-format msgid "Query was: %s" msgstr "Запит був: %s" -#: pg_amcheck.c:399 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: pg_amcheck.c:403 #, c-format msgid "invalid argument for option %s" msgstr "неприпустимий аргумент для параметру %s" -#: pg_amcheck.c:405 +#: pg_amcheck.c:409 #, c-format msgid "invalid start block" msgstr "неприпустимий початковий блок" -#: pg_amcheck.c:407 +#: pg_amcheck.c:411 #, c-format msgid "start block out of bounds" msgstr "початковий блок поза межами" -#: pg_amcheck.c:414 +#: pg_amcheck.c:418 #, c-format msgid "invalid end block" msgstr "неприпустимий кінцевий блок" -#: pg_amcheck.c:416 +#: pg_amcheck.c:420 #, c-format msgid "end block out of bounds" msgstr "кінцевий блок поза межами" -#: pg_amcheck.c:439 pg_amcheck.c:461 +#: pg_amcheck.c:446 pg_amcheck.c:468 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_amcheck.c:445 +#: pg_amcheck.c:452 #, c-format msgid "end block precedes start block" msgstr "кінцевий блок передує початковому блоку" -#: pg_amcheck.c:459 +#: pg_amcheck.c:466 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_amcheck.c:479 +#: pg_amcheck.c:486 #, c-format msgid "cannot specify a database name with --all" msgstr "не можна вказати назву бази даних з --all" -#: pg_amcheck.c:485 +#: pg_amcheck.c:492 #, c-format msgid "cannot specify both a database name and database patterns" msgstr "не можна вказати одночасно ім'я бази даних і шаблони бази даних" -#: pg_amcheck.c:513 +#: pg_amcheck.c:520 #, c-format msgid "no databases to check" msgstr "немає баз даних для перевірки" -#: pg_amcheck.c:569 +#: pg_amcheck.c:576 #, c-format msgid "database \"%s\": %s" msgstr "база даних \"%s\": %s" -#: pg_amcheck.c:580 +#: pg_amcheck.c:587 #, c-format msgid "skipping database \"%s\": amcheck is not installed" msgstr "пропуск бази даних \"%s\": amcheck не встановлено" -#: pg_amcheck.c:588 +#: pg_amcheck.c:595 #, c-format msgid "in database \"%s\": using amcheck version \"%s\" in schema \"%s\"" msgstr "у базі даних \"%s\": використовується amcheck версії \"%s\" у схемі \"%s\"" -#: pg_amcheck.c:610 +#: pg_amcheck.c:624 +#, c-format +msgid "option %s is not supported by amcheck version %s" +msgstr "параметр %s не підтримується у версії amcheck %s" + +#: pg_amcheck.c:650 #, c-format msgid "no heap tables to check matching \"%s\"" msgstr "немає таблиць в динамічній пам'яті для перевірки відповідності \"%s\"" -#: pg_amcheck.c:613 +#: pg_amcheck.c:653 #, c-format msgid "no btree indexes to check matching \"%s\"" msgstr "немає індексів btree для перевірки відповідності \"%s\"" -#: pg_amcheck.c:616 +#: pg_amcheck.c:656 #, c-format msgid "no relations to check in schemas matching \"%s\"" msgstr "немає відношень для перевірки в схемах, відповідних \"%s\"" -#: pg_amcheck.c:619 +#: pg_amcheck.c:659 #, c-format msgid "no relations to check matching \"%s\"" msgstr "немає відношень для перевірки відповідності \"%s\"" -#: pg_amcheck.c:647 +#: pg_amcheck.c:687 #, c-format msgid "no relations to check" msgstr "немає зв'язків для перевірки" -#: pg_amcheck.c:730 +#: pg_amcheck.c:770 #, c-format msgid "checking heap table \"%s.%s.%s\"" msgstr "перевірка таблиць динамічної пам'яті \"%s.%s.%s\"" -#: pg_amcheck.c:746 +#: pg_amcheck.c:786 #, c-format msgid "checking btree index \"%s.%s.%s\"" msgstr "перевірка індексу btree \"%s.%s.%s\"" -#: pg_amcheck.c:893 +#: pg_amcheck.c:937 #, c-format msgid "error sending command to database \"%s\": %s" msgstr "помилка надсилання команди до бази даних \"%s: %s" -#: pg_amcheck.c:896 +#: pg_amcheck.c:940 #, c-format msgid "Command was: %s" msgstr "Команда була: %s" -#: pg_amcheck.c:1015 +#: pg_amcheck.c:1060 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s, attribute %s:\n" msgstr "таблиця динамічної пам'яті \"%s.%s.%s\", блок %s, зсув %s, атрибут %s:\n" -#: pg_amcheck.c:1022 +#: pg_amcheck.c:1067 #, c-format msgid "heap table \"%s.%s.%s\", block %s, offset %s:\n" msgstr "таблиця динамічної пам'яті \"%s.%s.%s\", блок %s, зсув %s:\n" -#: pg_amcheck.c:1028 +#: pg_amcheck.c:1073 #, c-format msgid "heap table \"%s.%s.%s\", block %s:\n" msgstr "таблиця динамічної пам'яті \"%s.%s.%s\", блок %s:\n" -#: pg_amcheck.c:1033 pg_amcheck.c:1044 +#: pg_amcheck.c:1078 pg_amcheck.c:1089 #, c-format msgid "heap table \"%s.%s.%s\":\n" msgstr "таблиця динамічної пам'яті \"%s.%s.%s\":\n" -#: pg_amcheck.c:1048 pg_amcheck.c:1117 +#: pg_amcheck.c:1093 pg_amcheck.c:1162 #, c-format msgid "query was: %s\n" msgstr "запит був: %s\n" -#: pg_amcheck.c:1099 +#: pg_amcheck.c:1144 #, c-format msgid "btree index \"%s.%s.%s\": btree checking function returned unexpected number of rows: %d" msgstr "індекс btree \"%s.%s.%s\": функція перевірки btree повернула неочікувану кількість рядків: %d" -#: pg_amcheck.c:1103 +#: pg_amcheck.c:1148 #, c-format msgid "Are %s's and amcheck's versions compatible?" msgstr "Чи сумісні версії %s і amcheck?" -#: pg_amcheck.c:1113 +#: pg_amcheck.c:1158 #, c-format msgid "btree index \"%s.%s.%s\":\n" msgstr "індекс btree \"%s.%s.%s\":\n" -#: pg_amcheck.c:1138 +#: pg_amcheck.c:1183 #, c-format msgid "%s checks objects in a PostgreSQL database for corruption.\n\n" msgstr "%s перевіряє об'єкти бази даних PostgreSQL на пошкодження.\n\n" -#: pg_amcheck.c:1139 +#: pg_amcheck.c:1184 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_amcheck.c:1140 +#: pg_amcheck.c:1185 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: pg_amcheck.c:1141 +#: pg_amcheck.c:1186 #, c-format msgid "\n" "Target options:\n" msgstr "\n" "Цільові параметри:\n" -#: pg_amcheck.c:1142 +#: pg_amcheck.c:1187 #, c-format msgid " -a, --all check all databases\n" msgstr " -a, --all перевірити всі бази даних\n" -#: pg_amcheck.c:1143 +#: pg_amcheck.c:1188 #, c-format msgid " -d, --database=PATTERN check matching database(s)\n" msgstr " -d, --database=PATTERN перевірити відповідні бази даних\n" -#: pg_amcheck.c:1144 +#: pg_amcheck.c:1189 #, c-format msgid " -D, --exclude-database=PATTERN do NOT check matching database(s)\n" msgstr " -D, --exclude-database=PATTERN НЕ перевіряти відповідні бази даних\n" -#: pg_amcheck.c:1145 +#: pg_amcheck.c:1190 #, c-format msgid " -i, --index=PATTERN check matching index(es)\n" msgstr " -i, --index=PATTERN перевірити відповідні індекси\n" -#: pg_amcheck.c:1146 +#: pg_amcheck.c:1191 #, c-format msgid " -I, --exclude-index=PATTERN do NOT check matching index(es)\n" msgstr " -I, --exclude-index=PATTERN НЕ перевіряти відповідні індекси\n" -#: pg_amcheck.c:1147 +#: pg_amcheck.c:1192 #, c-format msgid " -r, --relation=PATTERN check matching relation(s)\n" msgstr " -r, --relation=PATTERN перевірити відповідні відношення\n" -#: pg_amcheck.c:1148 +#: pg_amcheck.c:1193 #, c-format msgid " -R, --exclude-relation=PATTERN do NOT check matching relation(s)\n" msgstr " -R, --exclude-relation=PATTERN НЕ перевіряти відповідні відношення\n" -#: pg_amcheck.c:1149 +#: pg_amcheck.c:1194 #, c-format msgid " -s, --schema=PATTERN check matching schema(s)\n" msgstr " -s, --schema=PATTERN перевірити відповідні схеми\n" -#: pg_amcheck.c:1150 +#: pg_amcheck.c:1195 #, c-format msgid " -S, --exclude-schema=PATTERN do NOT check matching schema(s)\n" msgstr " -S, --exclude-schema=PATTERN НЕ перевіряти відповідні схеми\n" -#: pg_amcheck.c:1151 +#: pg_amcheck.c:1196 #, c-format msgid " -t, --table=PATTERN check matching table(s)\n" msgstr " -t, --table=PATTERN перевірити відповідні таблиці\n" -#: pg_amcheck.c:1152 +#: pg_amcheck.c:1197 #, c-format msgid " -T, --exclude-table=PATTERN do NOT check matching table(s)\n" msgstr " -T, --exclude-table=PATTERN НЕ перевіряти відповідні таблиці\n" -#: pg_amcheck.c:1153 +#: pg_amcheck.c:1198 #, c-format msgid " --no-dependent-indexes do NOT expand list of relations to include indexes\n" msgstr " --no-dependent-indexes НЕ розширювати список відносин, щоб включити індекси\n" -#: pg_amcheck.c:1154 +#: pg_amcheck.c:1199 #, c-format msgid " --no-dependent-toast do NOT expand list of relations to include TOAST tables\n" msgstr " --no-dependent-toast НЕ розширювати список відносин, щоб включити таблиці TOAST\n" -#: pg_amcheck.c:1155 +#: pg_amcheck.c:1200 #, c-format msgid " --no-strict-names do NOT require patterns to match objects\n" msgstr " --no-strict-names НЕ вимагати відповідності шаблонів об'єктам\n" -#: pg_amcheck.c:1156 +#: pg_amcheck.c:1201 #, c-format msgid "\n" "Table checking options:\n" msgstr "\n" "Параметри перевірки таблиць:\n" -#: pg_amcheck.c:1157 +#: pg_amcheck.c:1202 #, c-format msgid " --exclude-toast-pointers do NOT follow relation TOAST pointers\n" msgstr " --exclude-toast-pointers НЕ слідувати покажчикам відношень TOAST\n" -#: pg_amcheck.c:1158 +#: pg_amcheck.c:1203 #, c-format msgid " --on-error-stop stop checking at end of first corrupt page\n" msgstr " --on-error-stop зупинити перевірку наприкінці першої пошкодженої сторінки\n" -#: pg_amcheck.c:1159 +#: pg_amcheck.c:1204 #, c-format msgid " --skip=OPTION do NOT check \"all-frozen\" or \"all-visible\" blocks\n" msgstr " --skip=OPTION НЕ перевіряти \"всі заморожені\" або \"всі видимі\" блоки\n" -#: pg_amcheck.c:1160 +#: pg_amcheck.c:1205 #, c-format msgid " --startblock=BLOCK begin checking table(s) at the given block number\n" msgstr " --startblock=BLOCK почати перевірку таблиць за поданим номером блоку\n" -#: pg_amcheck.c:1161 +#: pg_amcheck.c:1206 #, c-format msgid " --endblock=BLOCK check table(s) only up to the given block number\n" msgstr " --endblock=BLOCK перевіряти таблиці лише до поданого номеру блоку\n" -#: pg_amcheck.c:1162 +#: pg_amcheck.c:1207 #, c-format msgid "\n" "B-tree index checking options:\n" msgstr "\n" "Параметри перевірки індексів B-tree:\n" -#: pg_amcheck.c:1163 +#: pg_amcheck.c:1208 +#, c-format +msgid " --checkunique check unique constraint if index is unique\n" +msgstr " --checkunique перевіряємо обмеження unique, якщо індекс унікальний\n" + +#: pg_amcheck.c:1209 #, c-format msgid " --heapallindexed check that all heap tuples are found within indexes\n" msgstr " --heapallindexed перевірити чи всі кортежі динамічної пам'яті містяться в індексах\n" -#: pg_amcheck.c:1164 +#: pg_amcheck.c:1210 #, c-format msgid " --parent-check check index parent/child relationships\n" msgstr " --parent-check перевірити індекс батьківських/дочірніх відносин\n" -#: pg_amcheck.c:1165 +#: pg_amcheck.c:1211 #, c-format msgid " --rootdescend search from root page to refind tuples\n" msgstr " --rootdescend шукати з кореневої сторінки, для повторного пошуку кортежів\n" -#: pg_amcheck.c:1166 +#: pg_amcheck.c:1212 #, c-format msgid "\n" "Connection options:\n" msgstr "\n" "Налаштування з'єднання:\n" -#: pg_amcheck.c:1167 +#: pg_amcheck.c:1213 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME хост сервера бази даних або каталог сокетів\n" -#: pg_amcheck.c:1168 +#: pg_amcheck.c:1214 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT порт серверу бази даних\n" -#: pg_amcheck.c:1169 +#: pg_amcheck.c:1215 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME ім'я користувача для з'єднання з сервером\n" -#: pg_amcheck.c:1170 +#: pg_amcheck.c:1216 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не запитувати пароль\n" -#: pg_amcheck.c:1171 +#: pg_amcheck.c:1217 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password примусовий запит пароля\n" -#: pg_amcheck.c:1172 +#: pg_amcheck.c:1218 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME база даних альтернативного обслуговування\n" -#: pg_amcheck.c:1173 +#: pg_amcheck.c:1219 #, c-format msgid "\n" "Other options:\n" msgstr "\n" "Інші параметри:\n" -#: pg_amcheck.c:1174 +#: pg_amcheck.c:1220 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo показати команди, надіслані серверу\n" -#: pg_amcheck.c:1175 +#: pg_amcheck.c:1221 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to the server\n" msgstr " -j, --jobs=NUM використати цю кількість одночасних з'єднань з сервером\n" -#: pg_amcheck.c:1176 +#: pg_amcheck.c:1222 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress показати інформацію про прогрес\n" -#: pg_amcheck.c:1177 +#: pg_amcheck.c:1223 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose виводити багато інформації\n" -#: pg_amcheck.c:1178 +#: pg_amcheck.c:1224 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: pg_amcheck.c:1179 +#: pg_amcheck.c:1225 #, c-format msgid " --install-missing install missing extensions\n" msgstr " --install-missing встановити відсутні розширення\n" -#: pg_amcheck.c:1180 +#: pg_amcheck.c:1226 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю справку, потім вийти\n" -#: pg_amcheck.c:1182 +#: pg_amcheck.c:1228 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_amcheck.c:1183 +#: pg_amcheck.c:1229 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_amcheck.c:1236 +#: pg_amcheck.c:1282 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) %*s" msgstr "%*s/%s відношень (%d%%), %*s/%s сторінок (%d%%) %*s" -#: pg_amcheck.c:1247 +#: pg_amcheck.c:1293 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%) (%s%-*.*s)" msgstr "%*s/%s відношень (%d%%), %*s/%s сторінок (%d%%) (%s%-*.*s)" -#: pg_amcheck.c:1262 +#: pg_amcheck.c:1308 #, c-format msgid "%*s/%s relations (%d%%), %*s/%s pages (%d%%)" msgstr "%*s/%s відношень (%d%%), %*s/%s сторінок (%d%%)" -#: pg_amcheck.c:1321 pg_amcheck.c:1354 +#: pg_amcheck.c:1367 pg_amcheck.c:1400 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неправильне повне ім'я (забагато компонентів): %s" -#: pg_amcheck.c:1399 +#: pg_amcheck.c:1445 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неправильне ім'я зв'язку (забагато компонентів): %s" -#: pg_amcheck.c:1552 pg_amcheck.c:1691 +#: pg_amcheck.c:1598 pg_amcheck.c:1737 #, c-format msgid "including database \"%s\"" msgstr "включаючи базу даних \"%s\"" -#: pg_amcheck.c:1673 +#: pg_amcheck.c:1719 #, c-format msgid "internal error: received unexpected database pattern_id %d" msgstr "внутрішня помилка: отримано неочікувану помилку шаблону бази даних %d" -#: pg_amcheck.c:1675 +#: pg_amcheck.c:1721 #, c-format msgid "no connectable databases to check matching \"%s\"" msgstr "немає бази даних для підключення, щоб перевірити відповідність\"%s\"" -#: pg_amcheck.c:2133 +#: pg_amcheck.c:2179 #, c-format msgid "internal error: received unexpected relation pattern_id %d" msgstr "внутрішня помилка: отримано неочікувану помилку шаблону відношення %d" diff --git a/src/bin/pg_amcheck/t/001_basic.pl b/src/bin/pg_amcheck/t/001_basic.pl index b7b5607728cef..462793977da80 100644 --- a/src/bin/pg_amcheck/t/001_basic.pl +++ b/src/bin/pg_amcheck/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_amcheck/t/002_nonesuch.pl b/src/bin/pg_amcheck/t/002_nonesuch.pl index 67d700ea07a90..f23368abeab3b 100644 --- a/src/bin/pg_amcheck/t/002_nonesuch.pl +++ b/src/bin/pg_amcheck/t/002_nonesuch.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -11,7 +11,7 @@ # Test set-up my ($node, $port); $node = PostgreSQL::Test::Cluster->new('test'); -$node->init; +$node->init(auth_extra => [ '--create-role' => 'no_such_user' ]); $node->start; $port = $node->port; @@ -30,7 +30,7 @@ # Failing to resolve a database pattern is an error by default. $node->command_checks_all( - [ 'pg_amcheck', '-d', 'qqq', '-d', 'postgres' ], + [ 'pg_amcheck', '--database' => 'qqq', '--database' => 'postgres' ], 1, [qr/^$/], [qr/pg_amcheck: error: no connectable databases to check matching "qqq"/], @@ -38,7 +38,12 @@ # But only a warning under --no-strict-names $node->command_checks_all( - [ 'pg_amcheck', '--no-strict-names', '-d', 'qqq', '-d', 'postgres' ], + [ + 'pg_amcheck', + '--no-strict-names', + '--database' => 'qqq', + '--database' => 'postgres' + ], 0, [qr/^$/], [ @@ -49,7 +54,7 @@ # Check that a substring of an existent database name does not get interpreted # as a matching pattern. $node->command_checks_all( - [ 'pg_amcheck', '-d', 'post', '-d', 'postgres' ], + [ 'pg_amcheck', '--database' => 'post', '--database' => 'postgres' ], 1, [qr/^$/], [ @@ -61,7 +66,11 @@ # Check that a superstring of an existent database name does not get interpreted # as a matching pattern. $node->command_checks_all( - [ 'pg_amcheck', '-d', 'postgresql', '-d', 'postgres' ], + [ + 'pg_amcheck', + '--database' => 'postgresql', + '--database' => 'postgres' + ], 1, [qr/^$/], [ @@ -74,8 +83,12 @@ # Test connecting with a non-existent user # Failing to connect to the initial database due to bad username is an error. -$node->command_checks_all([ 'pg_amcheck', '-U', 'no_such_user', 'postgres' ], - 1, [qr/^$/], [], 'checking with a non-existent user'); +$node->command_checks_all( + [ 'pg_amcheck', '--username' => 'no_such_user', 'postgres' ], + 1, + [qr/^$/], + [qr/role "no_such_user" does not exist/], + 'checking with a non-existent user'); ######################################### # Test checking databases without amcheck installed @@ -96,7 +109,7 @@ # Again, but this time with another database to check, so no error is raised. $node->command_checks_all( - [ 'pg_amcheck', '-d', 'template1', '-d', 'postgres' ], + [ 'pg_amcheck', '--database' => 'template1', '--database' => 'postgres' ], 0, [qr/^$/], [ @@ -121,7 +134,7 @@ # Check three-part unreasonable pattern that has zero-length names $node->command_checks_all( - [ 'pg_amcheck', '-d', 'postgres', '-t', '..' ], + [ 'pg_amcheck', '--database' => 'postgres', '--table' => '..' ], 1, [qr/^$/], [ @@ -131,7 +144,7 @@ # Again, but with non-trivial schema and relation parts $node->command_checks_all( - [ 'pg_amcheck', '-d', 'postgres', '-t', '.foo.bar' ], + [ 'pg_amcheck', '--database' => 'postgres', '--table' => '.foo.bar' ], 1, [qr/^$/], [ @@ -141,7 +154,7 @@ # Check two-part unreasonable pattern that has zero-length names $node->command_checks_all( - [ 'pg_amcheck', '-d', 'postgres', '-t', '.' ], + [ 'pg_amcheck', '--database' => 'postgres', '--table' => '.' ], 1, [qr/^$/], [qr/pg_amcheck: error: no heap tables to check matching "\."/], @@ -149,7 +162,7 @@ # Check that a multipart database name is rejected $node->command_checks_all( - [ 'pg_amcheck', '-d', 'localhost.postgres' ], + [ 'pg_amcheck', '--database' => 'localhost.postgres' ], 2, [qr/^$/], [ @@ -159,7 +172,7 @@ # Check that a three-part schema name is rejected $node->command_checks_all( - [ 'pg_amcheck', '-s', 'localhost.postgres.pg_catalog' ], + [ 'pg_amcheck', '--schema' => 'localhost.postgres.pg_catalog' ], 2, [qr/^$/], [ @@ -169,7 +182,7 @@ # Check that a four-part table name is rejected $node->command_checks_all( - [ 'pg_amcheck', '-t', 'localhost.postgres.pg_catalog.pg_class' ], + [ 'pg_amcheck', '--table' => 'localhost.postgres.pg_catalog.pg_class' ], 2, [qr/^$/], [ @@ -183,7 +196,7 @@ $node->command_checks_all( [ 'pg_amcheck', '--no-strict-names', - '-t', 'this.is.a.really.long.dotted.string' + '--table' => 'this.is.a.really.long.dotted.string' ], 2, [qr/^$/], @@ -193,8 +206,8 @@ 'ungrammatical table names still draw errors under --no-strict-names'); $node->command_checks_all( [ - 'pg_amcheck', '--no-strict-names', '-s', - 'postgres.long.dotted.string' + 'pg_amcheck', '--no-strict-names', + '--schema' => 'postgres.long.dotted.string' ], 2, [qr/^$/], @@ -204,8 +217,8 @@ 'ungrammatical schema names still draw errors under --no-strict-names'); $node->command_checks_all( [ - 'pg_amcheck', '--no-strict-names', '-d', - 'postgres.long.dotted.string' + 'pg_amcheck', '--no-strict-names', + '--database' => 'postgres.long.dotted.string' ], 2, [qr/^$/], @@ -216,7 +229,7 @@ # Likewise for exclusion patterns $node->command_checks_all( - [ 'pg_amcheck', '--no-strict-names', '-T', 'a.b.c.d' ], + [ 'pg_amcheck', '--no-strict-names', '--exclude-table' => 'a.b.c.d' ], 2, [qr/^$/], [ @@ -225,7 +238,7 @@ 'ungrammatical table exclusions still draw errors under --no-strict-names' ); $node->command_checks_all( - [ 'pg_amcheck', '--no-strict-names', '-S', 'a.b.c' ], + [ 'pg_amcheck', '--no-strict-names', '--exclude-schema' => 'a.b.c' ], 2, [qr/^$/], [ @@ -234,7 +247,7 @@ 'ungrammatical schema exclusions still draw errors under --no-strict-names' ); $node->command_checks_all( - [ 'pg_amcheck', '--no-strict-names', '-D', 'a.b' ], + [ 'pg_amcheck', '--no-strict-names', '--exclude-database' => 'a.b' ], 2, [qr/^$/], [ @@ -252,20 +265,20 @@ $node->command_checks_all( [ 'pg_amcheck', '--no-strict-names', - '-t', 'no_such_table', - '-t', 'no*such*table', - '-i', 'no_such_index', - '-i', 'no*such*index', - '-r', 'no_such_relation', - '-r', 'no*such*relation', - '-d', 'no_such_database', - '-d', 'no*such*database', - '-r', 'none.none', - '-r', 'none.none.none', - '-r', 'postgres.none.none', - '-r', 'postgres.pg_catalog.none', - '-r', 'postgres.none.pg_class', - '-t', 'postgres.pg_catalog.pg_class', # This exists + '--table' => 'no_such_table', + '--table' => 'no*such*table', + '--index' => 'no_such_index', + '--index' => 'no*such*index', + '--relation' => 'no_such_relation', + '--relation' => 'no*such*relation', + '--database' => 'no_such_database', + '--database' => 'no*such*database', + '--relation' => 'none.none', + '--relation' => 'none.none.none', + '--relation' => 'postgres.none.none', + '--relation' => 'postgres.pg_catalog.none', + '--relation' => 'postgres.none.pg_class', + '--table' => 'postgres.pg_catalog.pg_class', # This exists ], 0, [qr/^$/], @@ -302,7 +315,7 @@ )); $node->command_checks_all( - [ 'pg_amcheck', '-d', 'regression_invalid' ], + [ 'pg_amcheck', '--database' => 'regression_invalid' ], 1, [qr/^$/], [ @@ -312,7 +325,9 @@ $node->command_checks_all( [ - 'pg_amcheck', '-d', 'postgres', '-t', 'regression_invalid.public.foo', + 'pg_amcheck', + '--database' => 'postgres', + '--table' => 'regression_invalid.public.foo', ], 1, [qr/^$/], @@ -334,14 +349,15 @@ $node->command_checks_all( [ - 'pg_amcheck', '-d', - 'postgres', '--no-strict-names', - '-t', 'template1.public.foo', - '-t', 'another_db.public.foo', - '-t', 'no_such_database.public.foo', - '-i', 'template1.public.foo_idx', - '-i', 'another_db.public.foo_idx', - '-i', 'no_such_database.public.foo_idx', + 'pg_amcheck', + '--database' => 'postgres', + '--no-strict-names', + '--table' => 'template1.public.foo', + '--table' => 'another_db.public.foo', + '--table' => 'no_such_database.public.foo', + '--index' => 'template1.public.foo_idx', + '--index' => 'another_db.public.foo_idx', + '--index' => 'no_such_database.public.foo_idx', ], 1, [qr/^$/], @@ -364,9 +380,13 @@ # Check with only schema exclusion patterns $node->command_checks_all( [ - 'pg_amcheck', '--all', '--no-strict-names', '-S', - 'public', '-S', 'pg_catalog', '-S', - 'pg_toast', '-S', 'information_schema', + 'pg_amcheck', + '--all', + '--no-strict-names', + '--exclude-schema' => 'public', + '--exclude-schema' => 'pg_catalog', + '--exclude-schema' => 'pg_toast', + '--exclude-schema' => 'information_schema', ], 1, [qr/^$/], @@ -379,10 +399,15 @@ # Check with schema exclusion patterns overriding relation and schema inclusion patterns $node->command_checks_all( [ - 'pg_amcheck', '--all', '--no-strict-names', '-s', - 'public', '-s', 'pg_catalog', '-s', - 'pg_toast', '-s', 'information_schema', '-t', - 'pg_catalog.pg_class', '-S*' + 'pg_amcheck', + '--all', + '--no-strict-names', + '--schema' => 'public', + '--schema' => 'pg_catalog', + '--schema' => 'pg_toast', + '--schema' => 'information_schema', + '--table' => 'pg_catalog.pg_class', + '--exclude-schema' => '*' ], 1, [qr/^$/], diff --git a/src/bin/pg_amcheck/t/003_check.pl b/src/bin/pg_amcheck/t/003_check.pl index 4b16bda6a4865..881854da254b1 100644 --- a/src/bin/pg_amcheck/t/003_check.pl +++ b/src/bin/pg_amcheck/t/003_check.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -120,7 +120,7 @@ () # Test set-up $node = PostgreSQL::Test::Cluster->new('test'); -$node->init; +$node->init(no_data_checksums => 1); $node->append_conf('postgresql.conf', 'autovacuum=off'); $node->start; $port = $node->port; @@ -319,7 +319,7 @@ () # # Standard first arguments to PostgreSQL::Test::Utils functions -my @cmd = ('pg_amcheck', '-p', $port); +my @cmd = ('pg_amcheck', '--port' => $port); # Regular expressions to match various expected output my $no_output_re = qr/^$/; @@ -332,8 +332,17 @@ () # yet corrupted anything. As such, we expect no corruption and verify that # none is reported # -$node->command_checks_all([ @cmd, '-d', 'db1', '-d', 'db2', '-d', 'db3' ], - 0, [$no_output_re], [$no_output_re], 'pg_amcheck prior to corruption'); +$node->command_checks_all( + [ + @cmd, + '--database' => 'db1', + '--database' => 'db2', + '--database' => 'db3' + ], + 0, + [$no_output_re], + [$no_output_re], + 'pg_amcheck prior to corruption'); # Perform the corruptions we planned above using only a single database restart. # @@ -356,7 +365,12 @@ () 'pg_amcheck all schemas, tables and indexes in database db1'); $node->command_checks_all( - [ @cmd, '-d', 'db1', '-d', 'db2', '-d', 'db3' ], + [ + @cmd, + '--database' => 'db1', + '--database' => 'db2', + '--database' => 'db3' + ], 2, [ $index_missing_relation_fork_re, $line_pointer_corruption_re, @@ -376,7 +390,7 @@ () # complaint on stderr, but otherwise stderr should be quiet. # $node->command_checks_all( - [ @cmd, '--all', '-s', 's1', '-i', 't1_btree' ], + [ @cmd, '--all', '--schema' => 's1', '--index' => 't1_btree' ], 2, [$index_missing_relation_fork_re], [ @@ -385,7 +399,12 @@ () 'pg_amcheck index s1.t1_btree reports missing main relation fork'); $node->command_checks_all( - [ @cmd, '-d', 'db1', '-s', 's1', '-i', 't2_btree' ], + [ + @cmd, + '--database' => 'db1', + '--schema' => 's1', + '--index' => 't2_btree' + ], 2, [qr/.+/], # Any non-empty error message is acceptable [$no_output_re], @@ -396,22 +415,24 @@ () # are quiet. # $node->command_checks_all( - [ @cmd, '-t', 's1.*', '--no-dependent-indexes', 'db1' ], + [ @cmd, '--table' => 's1.*', '--no-dependent-indexes', 'db1' ], 0, [$no_output_re], [$no_output_re], 'pg_amcheck of db1.s1 excluding indexes'); # Checking db2.s1 should show table corruptions if indexes are excluded # $node->command_checks_all( - [ @cmd, '-t', 's1.*', '--no-dependent-indexes', 'db2' ], - 2, [$missing_file_re], [$no_output_re], + [ @cmd, '--table' => 's1.*', '--no-dependent-indexes', 'db2' ], + 2, + [$missing_file_re], + [$no_output_re], 'pg_amcheck of db2.s1 excluding indexes'); # In schema db1.s3, the tables and indexes are both corrupt. We should see # corruption messages on stdout, and nothing on stderr. # $node->command_checks_all( - [ @cmd, '-s', 's3', 'db1' ], + [ @cmd, '--schema' => 's3', 'db1' ], 2, [ $index_missing_relation_fork_re, $line_pointer_corruption_re, @@ -423,13 +444,16 @@ () # In schema db1.s4, only toast tables are corrupt. Check that under default # options the toast corruption is reported, but when excluding toast we get no # error reports. -$node->command_checks_all([ @cmd, '-s', 's4', 'db1' ], +$node->command_checks_all([ @cmd, '--schema' => 's4', 'db1' ], 2, [$missing_file_re], [$no_output_re], 'pg_amcheck in schema s4 reports toast corruption'); $node->command_checks_all( [ - @cmd, '--no-dependent-toast', '--exclude-toast-pointers', '-s', 's4', + @cmd, + '--no-dependent-toast', + '--exclude-toast-pointers', + '--schema' => 's4', 'db1' ], 0, @@ -438,7 +462,7 @@ () 'pg_amcheck in schema s4 excluding toast reports no corruption'); # Check that no corruption is reported in schema db1.s5 -$node->command_checks_all([ @cmd, '-s', 's5', 'db1' ], +$node->command_checks_all([ @cmd, '--schema' => 's5', 'db1' ], 0, [$no_output_re], [$no_output_re], 'pg_amcheck over schema s5 reports no corruption'); @@ -446,7 +470,13 @@ () # the indexes, no corruption is reported about the schema. # $node->command_checks_all( - [ @cmd, '-s', 's1', '-I', 't1_btree', '-I', 't2_btree', 'db1' ], + [ + @cmd, + '--schema' => 's1', + '--exclude-index' => 't1_btree', + '--exclude-index' => 't2_btree', + 'db1' + ], 0, [$no_output_re], [$no_output_re], @@ -458,7 +488,7 @@ () # about the schema. # $node->command_checks_all( - [ @cmd, '-t', 's1.*', '--no-dependent-indexes', 'db1' ], + [ @cmd, '--table' => 's1.*', '--no-dependent-indexes', 'db1' ], 0, [$no_output_re], [$no_output_re], @@ -469,7 +499,13 @@ () # tables that no corruption is reported. # $node->command_checks_all( - [ @cmd, '-s', 's2', '-T', 't1', '-T', 't2', 'db1' ], + [ + @cmd, + '--schema' => 's2', + '--exclude-table' => 't1', + '--exclude-table' => 't2', + 'db1' + ], 0, [$no_output_re], [$no_output_re], @@ -480,17 +516,23 @@ () # to avoid getting messages about corrupt tables or indexes. # command_fails_like( - [ @cmd, '-s', 's5', '--startblock', 'junk', 'db1' ], + [ @cmd, '--schema' => 's5', '--startblock' => 'junk', 'db1' ], qr/invalid start block/, 'pg_amcheck rejects garbage startblock'); command_fails_like( - [ @cmd, '-s', 's5', '--endblock', '1234junk', 'db1' ], + [ @cmd, '--schema' => 's5', '--endblock' => '1234junk', 'db1' ], qr/invalid end block/, 'pg_amcheck rejects garbage endblock'); command_fails_like( - [ @cmd, '-s', 's5', '--startblock', '5', '--endblock', '4', 'db1' ], + [ + @cmd, + '--schema' => 's5', + '--startblock' => '5', + '--endblock' => '4', + 'db1' + ], qr/end block precedes start block/, 'pg_amcheck rejects invalid block range'); @@ -499,7 +541,12 @@ () # arguments are handled sensibly. # $node->command_checks_all( - [ @cmd, '-s', 's1', '-i', 't1_btree', '--parent-check', 'db1' ], + [ + @cmd, + '--schema' => 's1', + '--index' => 't1_btree', + '--parent-check', 'db1' + ], 2, [$index_missing_relation_fork_re], [$no_output_re], @@ -507,7 +554,10 @@ () $node->command_checks_all( [ - @cmd, '-s', 's1', '-i', 't1_btree', '--heapallindexed', + @cmd, + '--schema' => 's1', + '--index' => 't1_btree', + '--heapallindexed', '--rootdescend', 'db1' ], 2, @@ -516,13 +566,24 @@ () 'pg_amcheck smoke test --heapallindexed --rootdescend'); $node->command_checks_all( - [ @cmd, '-d', 'db1', '-d', 'db2', '-d', 'db3', '-S', 's*' ], - 0, [$no_output_re], [$no_output_re], + [ + @cmd, + '--database' => 'db1', + '--database' => 'db2', + '--database' => 'db3', + '--exclude-schema' => 's*' + ], + 0, + [$no_output_re], + [$no_output_re], 'pg_amcheck excluding all corrupt schemas'); $node->command_checks_all( [ - @cmd, '-s', 's1', '-i', 't1_btree', '--parent-check', + @cmd, + '--schema' => 's1', + '--index' => 't1_btree', + '--parent-check', '--checkunique', 'db1' ], 2, @@ -532,7 +593,10 @@ () $node->command_checks_all( [ - @cmd, '-s', 's1', '-i', 't1_btree', '--heapallindexed', + @cmd, + '--schema' => 's1', + '--index' => 't1_btree', + '--heapallindexed', '--rootdescend', '--checkunique', 'db1' ], 2, @@ -542,8 +606,12 @@ () $node->command_checks_all( [ - @cmd, '--checkunique', '-d', 'db1', '-d', 'db2', - '-d', 'db3', '-S', 's*' + @cmd, + '--checkunique', + '--database' => 'db1', + '--database' => 'db2', + '--database' => 'db3', + '--exclude-schema' => 's*' ], 0, [$no_output_re], @@ -564,7 +632,7 @@ () 0, [$no_output_re], [ - qr/pg_amcheck: warning: --checkunique option is not supported by amcheck version "1.3"/ + qr/pg_amcheck: warning: option --checkunique is not supported by amcheck version 1.3/ ], 'pg_amcheck smoke test --checkunique'); done_testing(); diff --git a/src/bin/pg_amcheck/t/004_verify_heapam.pl b/src/bin/pg_amcheck/t/004_verify_heapam.pl index f6d2c5f7877d5..2a3af2666f52a 100644 --- a/src/bin/pg_amcheck/t/004_verify_heapam.pl +++ b/src/bin/pg_amcheck/t/004_verify_heapam.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -181,7 +181,7 @@ sub write_tuple # autovacuum workers visiting the table could crash the backend. # Disable autovacuum so that won't happen. my $node = PostgreSQL::Test::Cluster->new('test'); -$node->init; +$node->init(no_data_checksums => 1); $node->append_conf('postgresql.conf', 'autovacuum=off'); $node->append_conf('postgresql.conf', 'max_prepared_transactions=10'); @@ -386,11 +386,12 @@ sub write_tuple # Check that pg_amcheck runs against the uncorrupted table without error. $node->command_ok( - [ 'pg_amcheck', '-p', $port, 'postgres' ], + [ 'pg_amcheck', '--port' => $port, 'postgres' ], 'pg_amcheck test table, prior to corruption'); # Check that pg_amcheck runs against the uncorrupted table and index without error. -$node->command_ok([ 'pg_amcheck', '-p', $port, 'postgres' ], +$node->command_ok( + [ 'pg_amcheck', '--port' => $port, 'postgres' ], 'pg_amcheck test table and index, prior to corruption'); $node->stop; @@ -754,7 +755,7 @@ sub header # Run pg_amcheck against the corrupt table with epoch=0, comparing actual # corruption messages against the expected messages $node->command_checks_all( - [ 'pg_amcheck', '--no-dependent-indexes', '-p', $port, 'postgres' ], + [ 'pg_amcheck', '--no-dependent-indexes', '--port' => $port, 'postgres' ], 2, [@expected], [], 'Expected corruption message output'); $node->safe_psql( 'postgres', qq( diff --git a/src/bin/pg_amcheck/t/005_opclass_damage.pl b/src/bin/pg_amcheck/t/005_opclass_damage.pl index 1eea215227208..775014aabdc45 100644 --- a/src/bin/pg_amcheck/t/005_opclass_damage.pl +++ b/src/bin/pg_amcheck/t/005_opclass_damage.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This regression test checks the behavior of the btree validation in the # presence of breaking sort order changes. @@ -52,7 +52,7 @@ )); # We have not yet broken the index, so we should get no corruption -$node->command_like([ 'pg_amcheck', '-p', $node->port, 'postgres' ], +$node->command_like([ 'pg_amcheck', '--port' => $node->port, 'postgres' ], qr/^$/, 'pg_amcheck all schemas, tables and indexes reports no corruption'); @@ -69,7 +69,7 @@ # Index corruption should now be reported $node->command_checks_all( - [ 'pg_amcheck', '-p', $node->port, 'postgres' ], + [ 'pg_amcheck', '--port' => $node->port, 'postgres' ], 2, [qr/item order invariant violated for index "fickleidx"/], [], @@ -90,7 +90,7 @@ # We should get no corruptions $node->command_like( - [ 'pg_amcheck', '--checkunique', '-p', $node->port, 'postgres' ], + [ 'pg_amcheck', '--checkunique', '--port' => $node->port, 'postgres' ], qr/^$/, 'pg_amcheck all schemas, tables and indexes reports no corruption'); @@ -116,7 +116,7 @@ # Unique index corruption should now be reported $node->command_checks_all( - [ 'pg_amcheck', '--checkunique', '-p', $node->port, 'postgres' ], + [ 'pg_amcheck', '--checkunique', '--port' => $node->port, 'postgres' ], 2, [qr/index uniqueness is violated for index "bttest_unique_idx"/], [], diff --git a/src/bin/pg_archivecleanup/meson.build b/src/bin/pg_archivecleanup/meson.build index f5ae47eaf464f..7590cecee3442 100644 --- a/src/bin/pg_archivecleanup/meson.build +++ b/src/bin/pg_archivecleanup/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_archivecleanup_sources = files( 'pg_archivecleanup.c', diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c index 5a124385b7cd8..c25348bcb85dd 100644 --- a/src/bin/pg_archivecleanup/pg_archivecleanup.c +++ b/src/bin/pg_archivecleanup/pg_archivecleanup.c @@ -270,7 +270,7 @@ usage(void) " clean up\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\n" - "For use as archive_cleanup_command in postgresql.conf:\n" + "For use as \"archive_cleanup_command\" in postgresql.conf:\n" " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n" "e.g.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n")); diff --git a/src/bin/pg_archivecleanup/po/de.po b/src/bin/pg_archivecleanup/po/de.po index ff82851e552cd..78f867ca0fd64 100644 --- a/src/bin/pg_archivecleanup/po/de.po +++ b/src/bin/pg_archivecleanup/po/de.po @@ -1,14 +1,14 @@ # pg_archivecleanup message translation file for pg_archivecleanup -# Copyright (C) 2019-2024 PostgreSQL Global Development Group +# Copyright (C) 2019-2025 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Peter Eisentraut , 2019 - 2024. +# Peter Eisentraut , 2019 - 2025. # msgid "" msgstr "" -"Project-Id-Version: pg_archivecleanup (PostgreSQL) 17\n" +"Project-Id-Version: pg_archivecleanup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 07:53+0000\n" -"PO-Revision-Date: 2024-04-04 11:48+0200\n" +"POT-Creation-Date: 2025-03-06 09:23+0000\n" +"PO-Revision-Date: 2025-03-06 12:11+0100\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,22 +16,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -47,43 +47,43 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: pg_archivecleanup.c:68 +#: pg_archivecleanup.c:69 #, c-format msgid "archive location \"%s\" does not exist" msgstr "Archivverzeichnis »%s« existiert nicht" -#: pg_archivecleanup.c:100 +#: pg_archivecleanup.c:101 #, c-format msgid "could not open archive location \"%s\": %m" msgstr "konnte Archivverzeichnis »%s« nicht öffnen: %m" -#: pg_archivecleanup.c:164 +#: pg_archivecleanup.c:165 #, c-format msgid "could not remove file \"%s\": %m" msgstr "konnte Datei »%s« nicht löschen: %m" -#: pg_archivecleanup.c:169 +#: pg_archivecleanup.c:170 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "konnte Archivverzeichnis »%s« nicht lesen: %m" -#: pg_archivecleanup.c:172 +#: pg_archivecleanup.c:173 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "konnte Archivverzeichnis »%s« nicht schließen: %m" -#: pg_archivecleanup.c:245 +#: pg_archivecleanup.c:246 #, c-format msgid "invalid file name argument" msgstr "ungültiges Dateinamenargument" -#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 -#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 +#: pg_archivecleanup.c:247 pg_archivecleanup.c:335 pg_archivecleanup.c:355 +#: pg_archivecleanup.c:367 pg_archivecleanup.c:374 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:260 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -92,17 +92,17 @@ msgstr "" "%s entfernt alte WAL-Dateien aus PostgreSQL-Archiven.\n" "\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:261 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_archivecleanup.c:261 +#: pg_archivecleanup.c:262 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [OPTION]... ARCHIVVERZEICHNIS ÄLTESTE-ZU-BEHALTENE-WALDATEI\n" -#: pg_archivecleanup.c:262 +#: pg_archivecleanup.c:263 #, c-format msgid "" "\n" @@ -111,29 +111,29 @@ msgstr "" "\n" "Optionen:\n" -#: pg_archivecleanup.c:263 +#: pg_archivecleanup.c:264 #, c-format msgid " -b, --clean-backup-history clean up files including backup history files\n" msgstr " -b, --clean-backup-history Dateien einschließlich Backup-History-Dateien aufräumen\n" -#: pg_archivecleanup.c:264 +#: pg_archivecleanup.c:265 #, c-format msgid " -d, --debug generate debug output (verbose mode)\n" msgstr " -d, --debug Debug-Ausgaben erzeugen (Verbose-Modus)\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:266 #, c-format msgid "" " -n, --dry-run dry run, show the names of the files that would be\n" " removed\n" msgstr " -n, --dry-run Probelauf, Namen der Dateien anzeigen, die entfernt würden\n" -#: pg_archivecleanup.c:267 +#: pg_archivecleanup.c:268 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_archivecleanup.c:268 +#: pg_archivecleanup.c:269 #, c-format msgid "" " -x, --strip-extension=EXT strip this extension before identifying files for\n" @@ -142,27 +142,27 @@ msgstr "" " -x, --strip-extension=ERW diese Erweiterung entfernen, bevor aufzuräumende\n" " Dateien bestimmt werden\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:271 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_archivecleanup.c:271 +#: pg_archivecleanup.c:272 #, c-format msgid "" "\n" -"For use as archive_cleanup_command in postgresql.conf:\n" +"For use as \"archive_cleanup_command\" in postgresql.conf:\n" " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n" "e.g.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" msgstr "" "\n" -"Verwendung als archive_cleanup_command in postgresql.conf:\n" +"Verwendung als »archive_cleanup_command« in postgresql.conf:\n" " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVVERZ %%r'\n" "z.B.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiv %%r'\n" -#: pg_archivecleanup.c:276 +#: pg_archivecleanup.c:277 #, c-format msgid "" "\n" @@ -175,7 +175,7 @@ msgstr "" "z.B.\n" " pg_archivecleanup /mnt/server/archiv 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:280 +#: pg_archivecleanup.c:281 #, c-format msgid "" "\n" @@ -184,22 +184,22 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: pg_archivecleanup.c:281 +#: pg_archivecleanup.c:282 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: pg_archivecleanup.c:353 +#: pg_archivecleanup.c:354 #, c-format msgid "must specify archive location" msgstr "Archivverzeichnis muss angegeben werden" -#: pg_archivecleanup.c:365 +#: pg_archivecleanup.c:366 #, c-format msgid "must specify oldest kept WAL file" msgstr "älteste zu behaltene WAL-Datei muss angegeben werden" -#: pg_archivecleanup.c:372 +#: pg_archivecleanup.c:373 #, c-format msgid "too many command-line arguments" msgstr "zu viele Kommandozeilenargumente" diff --git a/src/bin/pg_archivecleanup/po/es.po b/src/bin/pg_archivecleanup/po/es.po index 902f4a849d7a1..bac039fa0539b 100644 --- a/src/bin/pg_archivecleanup/po/es.po +++ b/src/bin/pg_archivecleanup/po/es.po @@ -6,10 +6,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_archivecleanup (PostgreSQL) 16\n" +"Project-Id-Version: pg_archivecleanup (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:21+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:52+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -38,43 +38,54 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " -#: pg_archivecleanup.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "ubicación de archivador «%s» no existe" -#: pg_archivecleanup.c:151 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "no se pudo abrir la ubicación del archivador «%s»: %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "no se pudo eliminar el archivo «%s»: %m" -#: pg_archivecleanup.c:157 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "no se pudo leer la ubicación del archivador «%s»: %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "no se pudo cerrar la ubicación del archivador «%s»: %m" -#: pg_archivecleanup.c:164 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "no se pudo abrir la ubicación del archivador «%s»: %m" - -#: pg_archivecleanup.c:237 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "el nombre de archivo usado como argumento no es válido" -#: pg_archivecleanup.c:238 pg_archivecleanup.c:313 pg_archivecleanup.c:333 -#: pg_archivecleanup.c:345 pg_archivecleanup.c:352 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_archivecleanup.c:251 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -83,17 +94,17 @@ msgstr "" "%s elimina archivos de WAL antiguos del archivador de PostgreSQL.\n" "\n" -#: pg_archivecleanup.c:252 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_archivecleanup.c:253 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [OPCIÓN].... UBICACIÓNARCHIVADOR WALMÁSANTIGUOAMANTENER\n" -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -102,32 +113,43 @@ msgstr "" "\n" "Opciones:\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d genera salida de depuración (modo verboso)\n" +msgid " -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -, --clean-backup-history limpia archivos incluyendo archivos de historia de backup\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:264 #, c-format -msgid " -n dry run, show the names of the files that would be removed\n" -msgstr " -n simulacro, muestra el nombre de los archivos que se eliminarían\n" +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug genera salida de depuración (modo verboso)\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:265 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version muestra información de la versión, luego sale\n" +msgid "" +" -n, --dry-run dry run, show the names of the files that would be\n" +" removed\n" +msgstr " -n, --dry-run simulacro, muestra el nombre de los archivos que se eliminarían\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:267 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x EXT hace limpieza de archivos que tengan esta extensión\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar la información de la versión, luego salir\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:268 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help muestra esta ayuda, luego sale\n" +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files for\n" +" clean up\n" +msgstr "" +" -x, --strip-extension=EXT quitar esta extensión antes de identificar archivos\n" +" a limpiar\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:270 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help muestra esta ayuda, luego salir\n" + +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" @@ -142,7 +164,7 @@ msgstr "" "por ej.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/servidor/directorioarchivador %%r'\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" @@ -155,7 +177,7 @@ msgstr "" "por ej.\n" " pg_archivecleanup /mnt/servidor/directorioarchivador 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:269 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" @@ -164,22 +186,22 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_archivecleanup.c:332 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "debe especificar la ubicación del archivador" -#: pg_archivecleanup.c:344 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "debe especificar el fichero WAL más antiguo a mantener" -#: pg_archivecleanup.c:351 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "demasiados argumentos de línea de órdenes" diff --git a/src/bin/pg_archivecleanup/po/fr.po b/src/bin/pg_archivecleanup/po/fr.po index 0ac310cc7012a..392e6e64d5f60 100644 --- a/src/bin/pg_archivecleanup/po/fr.po +++ b/src/bin/pg_archivecleanup/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-07-20 21:23+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,65 +19,76 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:273 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "erreur : " -#: ../../../src/common/logging.c:280 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "attention : " -#: ../../../src/common/logging.c:291 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "détail : " -#: ../../../src/common/logging.c:298 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "astuce : " -#: pg_archivecleanup.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "l'emplacement d'archivage « %s » n'existe pas" -#: pg_archivecleanup.c:151 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "n'a pas pu ouvrir l'emplacement de l'archive « %s » : %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "n'a pas pu supprimer le fichier « %s » : %m" -#: pg_archivecleanup.c:157 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "n'a pas pu lire l'emplacement de l'archive « %s » : %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "n'a pas pu fermer l'emplacement de l'archive « %s » : %m" -#: pg_archivecleanup.c:164 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "n'a pas pu ouvrir l'emplacement de l'archive « %s » : %m" - -#: pg_archivecleanup.c:237 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "argument du nom de fichier invalide" -#: pg_archivecleanup.c:238 pg_archivecleanup.c:313 pg_archivecleanup.c:333 -#: pg_archivecleanup.c:345 pg_archivecleanup.c:352 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_archivecleanup.c:251 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -86,17 +97,17 @@ msgstr "" "%s supprime les anciens fichiers WAL des archives de PostgreSQL.\n" "\n" -#: pg_archivecleanup.c:252 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_archivecleanup.c:253 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [OPTION]... EMPLACEMENTARCHIVE PLUSANCIENFICHIERWALCONSERVÉ\n" -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -105,32 +116,41 @@ msgstr "" "\n" "Options :\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:263 +#, c-format +msgid " -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -b, --clean-backup-history nettoie les fichiers, y compris les historiques de sauvegarde\n" + +#: pg_archivecleanup.c:264 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d affiche des informations de débugage (mode verbeux)\n" +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug affiche des informations de débogage (mode verbeux)\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:265 #, c-format -msgid " -n dry run, show the names of the files that would be removed\n" -msgstr " -n test, affiche le nom des fichiers qui seraient supprimés\n" +msgid "" +" -n, --dry-run dry run, show the names of the files that would be\n" +" removed\n" +msgstr " -n, --dry-run test, affiche le nom des fichiers qui seraient supprimés\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:267 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version affiche la version et quitte\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version, puis quitte\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:268 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x EXT nettoie les fichiers s'ils ont cette extension\n" +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files for\n" +" clean up\n" +msgstr " -x, --strip-extension=EXT supprime cette extension avant d'identifier les fichiers pour nettoyage\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:270 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help affiche cette aide et quitte\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide, puis quitte\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" @@ -145,7 +165,7 @@ msgstr "" "Par exemple :\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/serveur/reparchives %%r'\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" @@ -158,7 +178,7 @@ msgstr "" "Par exemple :\n" " pg_archivecleanup /mnt/serveur/reparchives 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:269 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" @@ -167,52 +187,22 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_archivecleanup.c:332 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "doit spécifier l'emplacement de l'archive" -#: pg_archivecleanup.c:344 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "doit spécifier le plus ancien journal de transactions conservé" -#: pg_archivecleanup.c:351 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "trop d'arguments en ligne de commande" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid "%s: ERROR: could not remove file \"%s\": %s\n" -#~ msgstr "%s : ERREUR : n'a pas pu supprimer le fichier « %s » : %s\n" - -#~ msgid "%s: file \"%s\" would be removed\n" -#~ msgstr "%s : le fichier « %s » serait supprimé\n" - -#~ msgid "%s: keeping WAL file \"%s\" and later\n" -#~ msgstr "%s : conservation du fichier WAL « %s » et des suivants\n" - -#~ msgid "%s: removing file \"%s\"\n" -#~ msgstr "%s : suppression du fichier « %s »\n" - -#~ msgid "%s: too many parameters\n" -#~ msgstr "%s : trop de paramètres\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " diff --git a/src/bin/pg_archivecleanup/po/ja.po b/src/bin/pg_archivecleanup/po/ja.po index 57886bc8df0d9..f601cfc4376b3 100644 --- a/src/bin/pg_archivecleanup/po/ja.po +++ b/src/bin/pg_archivecleanup/po/ja.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_archivecleanup (PostgreSQL 17)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-01-09 10:22+0900\n" -"PO-Revision-Date: 2024-01-09 11:54+0900\n" +"POT-Creation-Date: 2024-09-05 09:59+0900\n" +"PO-Revision-Date: 2024-09-05 10:38+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -17,63 +17,74 @@ msgstr "" "X-Generator: Poedit 1.8.13\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:278 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:285 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:296 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:303 #, c-format msgid "hint: " msgstr "ヒント: " -#: pg_archivecleanup.c:68 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "メモリ不足です\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nullポインタは複製できません(内部エラー)\n" + +#: pg_archivecleanup.c:69 #, c-format msgid "archive location \"%s\" does not exist" msgstr "アーカイブの場所\"%s\"が存在しません" -#: pg_archivecleanup.c:100 +#: pg_archivecleanup.c:101 #, c-format msgid "could not open archive location \"%s\": %m" msgstr "アーカイブの場所\"%s\"をオープンできませんでした: %m" -#: pg_archivecleanup.c:164 +#: pg_archivecleanup.c:165 #, c-format msgid "could not remove file \"%s\": %m" msgstr "ファイル\"%s\"を削除できませんでした: %m" -#: pg_archivecleanup.c:169 +#: pg_archivecleanup.c:170 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "アーカイブの場所\"%s\"を読み込めませんでした: %m" -#: pg_archivecleanup.c:172 +#: pg_archivecleanup.c:173 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "アーカイブの場所\"%s\"をクローズできませんでした: %m" -#: pg_archivecleanup.c:245 +#: pg_archivecleanup.c:246 #, c-format msgid "invalid file name argument" msgstr "ファイル名引数が無効です" -#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 -#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 +#: pg_archivecleanup.c:247 pg_archivecleanup.c:335 pg_archivecleanup.c:355 +#: pg_archivecleanup.c:367 pg_archivecleanup.c:374 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:260 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -82,17 +93,17 @@ msgstr "" "%sはPostgreSQLのアーカイブから古いWALファイルを削除します。\n" "\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:261 #, c-format msgid "Usage:\n" msgstr "使用法:\n" -#: pg_archivecleanup.c:261 +#: pg_archivecleanup.c:262 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr "%s [オプション] ... {アーカイブの場所} {保存する最古の WAL ファイル名}\n" -#: pg_archivecleanup.c:262 +#: pg_archivecleanup.c:263 #, c-format msgid "" "\n" @@ -101,56 +112,56 @@ msgstr "" "\n" "オプション:\n" -#: pg_archivecleanup.c:263 +#: pg_archivecleanup.c:264 #, c-format msgid " -b, --clean-backup-history clean up files including backup history files\n" msgstr " -b, --clean-backup-history バックアップヒストリファイルを含めて削除する\n" -#: pg_archivecleanup.c:264 +#: pg_archivecleanup.c:265 #, c-format msgid " -d, --debug generate debug output (verbose mode)\n" msgstr " -d, --debug デバッグ情報を出力(冗長モード)\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:266 #, c-format msgid "" " -n, --dry-run dry run, show the names of the files that would be\n" " removed\n" msgstr " -n, --dry-run リハーサル、削除対象のファイル名を表示\n" -#: pg_archivecleanup.c:267 +#: pg_archivecleanup.c:268 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_archivecleanup.c:268 +#: pg_archivecleanup.c:269 #, c-format msgid "" " -x, --strip-extension=EXT strip this extension before identifying files for\n" " clean up\n" msgstr " -x, --strip-extension=EXT 削除対象のファイルの確認前にこの拡張子を削除する\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:271 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_archivecleanup.c:271 +#: pg_archivecleanup.c:272 #, c-format msgid "" "\n" -"For use as archive_cleanup_command in postgresql.conf:\n" +"For use as \"archive_cleanup_command\" in postgresql.conf:\n" " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n" "e.g.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" msgstr "" "\n" -"postgresql.confでarchive_cleanup_commandとして使用する場合は以下のようにします:\n" +"postgresql.confで\"archive_cleanup_command\"として使用する場合は以下のようにします:\n" " archive_cleanup_command = 'pg_archivecleanup [オプション]... アーカイブの場所 %%r'\n" "例としては:\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:276 +#: pg_archivecleanup.c:277 #, c-format msgid "" "\n" @@ -163,7 +174,7 @@ msgstr "" "使用例\n" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:280 +#: pg_archivecleanup.c:281 #, c-format msgid "" "\n" @@ -172,22 +183,22 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_archivecleanup.c:281 +#: pg_archivecleanup.c:282 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: pg_archivecleanup.c:353 +#: pg_archivecleanup.c:354 #, c-format msgid "must specify archive location" msgstr "アーカイブの場所を指定してください" -#: pg_archivecleanup.c:365 +#: pg_archivecleanup.c:366 #, c-format msgid "must specify oldest kept WAL file" msgstr "保存する最古のWALファイルを指定してください" -#: pg_archivecleanup.c:372 +#: pg_archivecleanup.c:373 #, c-format msgid "too many command-line arguments" msgstr "コマンドライン引数が多すぎます" diff --git a/src/bin/pg_archivecleanup/po/ka.po b/src/bin/pg_archivecleanup/po/ka.po index 4f4c9f74f0b1a..801657a4b3a3b 100644 --- a/src/bin/pg_archivecleanup/po/ka.po +++ b/src/bin/pg_archivecleanup/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_archivecleanup (PostgreSQL) 17\n" +"Project-Id-Version: pg_archivecleanup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-11 09:52+0000\n" -"PO-Revision-Date: 2024-02-11 14:42+0100\n" +"POT-Creation-Date: 2025-02-27 09:54+0000\n" +"PO-Revision-Date: 2025-02-27 12:57+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,65 +16,76 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "warning: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " -#: pg_archivecleanup.c:68 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + +#: pg_archivecleanup.c:69 #, c-format msgid "archive location \"%s\" does not exist" msgstr "არქივის მდებარეობა არ არსებობს: %s" -#: pg_archivecleanup.c:100 +#: pg_archivecleanup.c:101 #, c-format msgid "could not open archive location \"%s\": %m" msgstr "არქივის მდებარეობის გახსნის შეცდომა\"%s\": %m" -#: pg_archivecleanup.c:164 +#: pg_archivecleanup.c:165 #, c-format msgid "could not remove file \"%s\": %m" msgstr "ფაილის წაშლის შეცდომა \"%s\": %m" -#: pg_archivecleanup.c:169 +#: pg_archivecleanup.c:170 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "არქივის მდებარეობის წაკითხვის შეცდომა\"%s\": %m" -#: pg_archivecleanup.c:172 +#: pg_archivecleanup.c:173 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "არქივის მდებარეობის დაყენების შეცდომა\"%s\": %m" -#: pg_archivecleanup.c:245 +#: pg_archivecleanup.c:246 #, c-format msgid "invalid file name argument" msgstr "ფაილის სახელის არასწორი არგუმენტი" -#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 -#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 +#: pg_archivecleanup.c:247 pg_archivecleanup.c:335 pg_archivecleanup.c:355 +#: pg_archivecleanup.c:367 pg_archivecleanup.c:374 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:260 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -83,17 +94,17 @@ msgstr "" "%s PostgreSQL-ის არქივებიდან ძველი WAL ფაილების წაშლა.\n" "\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:261 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_archivecleanup.c:261 +#: pg_archivecleanup.c:262 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [პარამეტრი]... არქივისმდგომარეობა უძველესიშენახულიWALფაილი\n" -#: pg_archivecleanup.c:262 +#: pg_archivecleanup.c:263 #, c-format msgid "" "\n" @@ -102,17 +113,17 @@ msgstr "" "\n" "პარამეტრები\n" -#: pg_archivecleanup.c:263 +#: pg_archivecleanup.c:264 #, c-format msgid " -b, --clean-backup-history clean up files including backup history files\n" msgstr " -b, --clean-backup-history ფაილების მოსუფთავება მარქაფი ისტორიის ფაილების ჩათვლით\n" -#: pg_archivecleanup.c:264 +#: pg_archivecleanup.c:265 #, c-format msgid " -d, --debug generate debug output (verbose mode)\n" msgstr " -d, --debug გასამართი ინფორმაციის გამოტანა(დამატებითი შეტყობინებების რეჟიმი)\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:266 #, c-format msgid "" " -n, --dry-run dry run, show the names of the files that would be\n" @@ -121,16 +132,13 @@ msgstr "" " -n, --dry-run მშრალი გაშვება. ფაილების წაშლის მაგიერ მხოლოდ მათი \n" " სახელების ჩვენება\n" -#: pg_archivecleanup.c:267 +#: pg_archivecleanup.c:268 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_archivecleanup.c:268 +#: pg_archivecleanup.c:269 #, c-format -#| msgid "" -#| " -L, --use-list=FILENAME use table of contents from this file for\n" -#| " selecting/ordering output\n" msgid "" " -x, --strip-extension=EXT strip this extension before identifying files for\n" " clean up\n" @@ -138,27 +146,27 @@ msgstr "" " -x, --strip-extension=გაფ ამ გაფართოების მოცილებაფაილის მოსასუფთავებლების\n" " სიაში ჩასმამდე\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:271 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_archivecleanup.c:271 +#: pg_archivecleanup.c:272 #, c-format msgid "" "\n" -"For use as archive_cleanup_command in postgresql.conf:\n" +"For use as \"archive_cleanup_command\" in postgresql.conf:\n" " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n" "e.g.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" msgstr "" "\n" -"გამოსაყენებლად, როგორც archive_cleanup_command postgresql.conf-ში: \n" +"გამოსაყენებლად, როგორც \"archive_cleanup_command\" postgresql.conf-ში: \n" " archive_cleanup_command = 'pg_archivecleanup [პარამეტრი]... არქივისმდებარეობა %%r'\n" "მაგ: \n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:276 +#: pg_archivecleanup.c:277 #, c-format msgid "" "\n" @@ -171,7 +179,7 @@ msgstr "" "მაგ:\n" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:280 +#: pg_archivecleanup.c:281 #, c-format msgid "" "\n" @@ -180,22 +188,22 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_archivecleanup.c:281 +#: pg_archivecleanup.c:282 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: pg_archivecleanup.c:353 +#: pg_archivecleanup.c:354 #, c-format msgid "must specify archive location" msgstr "არქივის მდებარეობის მითითება აუცილებელია" -#: pg_archivecleanup.c:365 +#: pg_archivecleanup.c:366 #, c-format msgid "must specify oldest kept WAL file" msgstr "დატოვებული უძველესი WAL ფაილის მითითება აუცილებელია" -#: pg_archivecleanup.c:372 +#: pg_archivecleanup.c:373 #, c-format msgid "too many command-line arguments" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი" diff --git a/src/bin/pg_archivecleanup/po/ko.po b/src/bin/pg_archivecleanup/po/ko.po index 785839ab2fd4a..79fea6d7cf4cd 100644 --- a/src/bin/pg_archivecleanup/po/ko.po +++ b/src/bin/pg_archivecleanup/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_archivecleanup (PostgreSQL) 13\n" +"Project-Id-Version: pg_archivecleanup (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2020-10-05 01:16+0000\n" -"PO-Revision-Date: 2020-10-05 17:51+0900\n" +"POT-Creation-Date: 2025-01-17 04:52+0000\n" +"PO-Revision-Date: 2025-01-16 13:10+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -17,58 +17,74 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:236 -#, c-format -msgid "fatal: " -msgstr "심각: " - -#: ../../../src/common/logging.c:243 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "오류: " -#: ../../../src/common/logging.c:250 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "경고: " -#: pg_archivecleanup.c:66 +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "상세정보: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "힌트: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "\"%s\" 이름의 아카이브 위치가 없음" -#: pg_archivecleanup.c:152 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "\"%s\" 아카이브 위치를 열 수 없음: %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "\"%s\" 파일을 삭제할 수 없음: %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "\"%s\" 아카이브 위치를 읽을 수 없음: %m" -#: pg_archivecleanup.c:163 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "\"%s\" 아카이브 위치를 닫을 수 없음: %m" -#: pg_archivecleanup.c:167 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "\"%s\" 아카이브 위치를 열 수 없음: %m" - -#: pg_archivecleanup.c:240 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "잘못된 파일 이름 매개변수" -#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336 -#: pg_archivecleanup.c:348 pg_archivecleanup.c:355 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format -msgid "Try \"%s --help\" for more information.\n" -msgstr "보다 자세한 정보는 \"%s --help\" 명령을 참조하세요.\n" +msgid "Try \"%s --help\" for more information." +msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -78,17 +94,17 @@ msgstr "" "WAL 파일을 지웁니다.\n" "\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [옵션]... 아카이브위치 보관할제일오래된파일\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -97,33 +113,45 @@ msgstr "" "\n" "옵션들:\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d 보다 자세한 작업 내용 출력\n" +msgid "" +" -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -b, --clean-backup-history 백업 내역 파일을 포함해서 파일들 지움\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:264 +#, c-format +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug 보다 자세한 작업 내용 출력\n" + +#: pg_archivecleanup.c:265 #, c-format msgid "" -" -n dry run, show the names of the files that would be removed\n" -msgstr " -n 지울 대상만 확인하고 지우지는 않음\n" +" -n, --dry-run dry run, show the names of the files that " +"would be\n" +" removed\n" +msgstr " -n, --dry-run 지울 대상만 확인하고 지우지는 않음\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:267 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version 버전 정보를 보여주고 마침\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_archivecleanup.c:261 +#: pg_archivecleanup.c:268 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x EXT 해당 확장자 파일들을 작업 대상으로 함\n" +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files " +"for\n" +" clean up\n" +msgstr "" +" -x, --strip-extension=EXT 지울 파일을 식별하기 전에 해당 확장 모듈 지움\n" -#: pg_archivecleanup.c:262 +#: pg_archivecleanup.c:270 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help 도움말을 보여주고 마침\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_archivecleanup.c:263 +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" @@ -139,7 +167,7 @@ msgstr "" "사용예:\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:268 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" @@ -154,7 +182,7 @@ msgstr "" " pg_archivecleanup /mnt/server/archiverdir " "000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:272 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" @@ -163,22 +191,26 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_archivecleanup.c:273 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_archivecleanup.c:335 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "아카이브 위치는 지정해야 함" -#: pg_archivecleanup.c:347 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "남길 가장 오래된 WAL 파일은 지정해야 함" -#: pg_archivecleanup.c:354 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "너무 많은 명령행 인자를 지정했음" + +#, c-format +#~ msgid " -x EXT clean up files if they have this extension\n" +#~ msgstr " -x EXT 해당 확장자 파일들을 작업 대상으로 함\n" diff --git a/src/bin/pg_archivecleanup/po/meson.build b/src/bin/pg_archivecleanup/po/meson.build index 9c2d4ba82b5f4..0d65690246d44 100644 --- a/src/bin/pg_archivecleanup/po/meson.build +++ b/src/bin/pg_archivecleanup/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_archivecleanup-' + pg_version_major.to_string())] diff --git a/src/bin/pg_archivecleanup/po/ru.po b/src/bin/pg_archivecleanup/po/ru.po index 4b542ce16ce84..e04456d67d365 100644 --- a/src/bin/pg_archivecleanup/po/ru.po +++ b/src/bin/pg_archivecleanup/po/ru.po @@ -1,21 +1,21 @@ # Russian message translation file for pg_archivecleanup # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2017, 2019, 2020, 2022. +# Alexander Lakhin , 2017, 2019, 2020, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pg_archivecleanup (PostgreSQL) 10\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-27 14:52+0300\n" -"PO-Revision-Date: 2022-09-05 13:34+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-07 06:17+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,43 +37,54 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " -#: pg_archivecleanup.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "расположение архива \"%s\" не существует" -#: pg_archivecleanup.c:151 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "не удалось открыть расположение архива \"%s\": %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не удалось стереть файл \"%s\": %m" -#: pg_archivecleanup.c:157 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "не удалось прочитать расположение архива \"%s\": %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "не удалось закрыть расположение архива \"%s\": %m" -#: pg_archivecleanup.c:164 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "не удалось открыть расположение архива \"%s\": %m" - -#: pg_archivecleanup.c:237 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "неверный аргумент с именем файла" -#: pg_archivecleanup.c:238 pg_archivecleanup.c:313 pg_archivecleanup.c:333 -#: pg_archivecleanup.c:345 pg_archivecleanup.c:352 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_archivecleanup.c:251 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -82,18 +93,18 @@ msgstr "" "%s удаляет старые файлы WAL из архивов PostgreSQL.\n" "\n" -#: pg_archivecleanup.c:252 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_archivecleanup.c:253 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr "" " %s [ПАРАМЕТР]... РАСПОЛОЖЕНИЕ_АРХИВА СТАРЕЙШИЙ_СОХРАНЯЕМЫЙ_ФАЙЛ_WAL\n" -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -102,42 +113,60 @@ msgstr "" "\n" "Параметры:\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d генерировать подробные сообщения (отладочный режим)\n" +msgid "" +" -b, --clean-backup-history clean up files including backup history files\n" +msgstr "" +" -b, --clean-backup-history удалить также файлы истории копирования\n" + +#: pg_archivecleanup.c:264 +#, c-format +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr "" +" -d, --debug генерировать подробные сообщения (режим " +"отладки)\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:265 #, c-format msgid "" -" -n dry run, show the names of the files that would be removed\n" +" -n, --dry-run dry run, show the names of the files that " +"would be\n" +" removed\n" msgstr "" -" -n холостой запуск, только показать имена файлов, которые " -"будут удалены\n" +" -n, --dry-run холостой запуск, только показать имена " +"файлов,\n" +" которые будут удалены\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:267 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version показать версию и выйти\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" # well-spelled: РСШ -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:268 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x РСШ убрать файлы с заданным расширением\n" +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files " +"for\n" +" clean up\n" +msgstr "" +" -x, --strip-extension=РСШ убрать это расширение прежде чем определять " +"файлы,\n" +" подлежащие удалению\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:270 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help показать эту справку и выйти\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" "For use as archive_cleanup_command in postgresql.conf:\n" -" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %" -"%r'\n" +" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION " +"%%r'\n" "e.g.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" msgstr "" @@ -148,22 +177,22 @@ msgstr "" "например:\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" "Or for use as a standalone archive cleaner:\n" "e.g.\n" -" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010." -"00000020.backup\n" +" pg_archivecleanup /mnt/server/archiverdir " +"000000010000000000000010.00000020.backup\n" msgstr "" "\n" "Либо для использования в качестве отдельного средства очистки архива,\n" "например:\n" -" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010." -"00000020.backup\n" +" pg_archivecleanup /mnt/server/archiverdir " +"000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:269 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" @@ -172,26 +201,31 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_archivecleanup.c:332 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "необходимо задать расположение архива" -#: pg_archivecleanup.c:344 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "необходимо задать имя старейшего сохраняемого файла WAL" -#: pg_archivecleanup.c:351 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "слишком много аргументов командной строки" +# well-spelled: РСШ +#, c-format +#~ msgid " -x EXT clean up files if they have this extension\n" +#~ msgstr " -x РСШ убрать файлы с заданным расширением\n" + #~ msgid "fatal: " #~ msgstr "важно: " diff --git a/src/bin/pg_archivecleanup/po/sv.po b/src/bin/pg_archivecleanup/po/sv.po index 6cebbc1ad1b86..d91831a8ba751 100644 --- a/src/bin/pg_archivecleanup/po/sv.po +++ b/src/bin/pg_archivecleanup/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_archivecleanup # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 13:50+0000\n" -"PO-Revision-Date: 2022-04-11 16:06+0200\n" +"POT-Creation-Date: 2024-07-12 13:23+0000\n" +"PO-Revision-Date: 2024-07-12 15:46+0200\n" "Last-Translator: FDennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,63 +17,74 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:268 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "fel: " -#: ../../../src/common/logging.c:275 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "varning: " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "detalj: " -#: ../../../src/common/logging.c:287 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "tips: " -#: pg_archivecleanup.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "arkivplats \"%s\" finns inte" -#: pg_archivecleanup.c:151 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "kunde inte öppna arkivplats \"%s\": %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "kunde inte ta bort fil \"%s\": %m" -#: pg_archivecleanup.c:157 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "kunde inte läsa arkivplats \"%s\": %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "kunde inte stänga arkivplats \"%s\": %m" -#: pg_archivecleanup.c:164 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "kunde inte öppna arkivplats \"%s\": %m" - -#: pg_archivecleanup.c:237 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "ogiltigt filnamnsargument" -#: pg_archivecleanup.c:238 pg_archivecleanup.c:313 pg_archivecleanup.c:333 -#: pg_archivecleanup.c:345 pg_archivecleanup.c:352 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_archivecleanup.c:251 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" @@ -82,17 +93,17 @@ msgstr "" "%s tar bort gamla WAL-filer från PostgreSQLs arkiv.\n" "\n" -#: pg_archivecleanup.c:252 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_archivecleanup.c:253 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [FLAGGA]... ARKIVPLATS ÄLDSTASPARADEWALFIL\n" -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -101,32 +112,45 @@ msgstr "" "\n" "Flaggor:\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d generera debugutskrift (utförligt läge)\n" +msgid " -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -b, --clean-backup-history rensa upp filer, inklusive filer för backuphistorik\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:264 #, c-format -msgid " -n dry run, show the names of the files that would be removed\n" -msgstr " -n gör inga ändringar visa namn på de filer som skulle ha tagits bort\n" +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug generera debugutskrift (utförligt läge)\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:265 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version visa versionsinformation, avsluta sedan\n" +msgid "" +" -n, --dry-run dry run, show the names of the files that would be\n" +" removed\n" +msgstr "" +" -n, --dry-run gör inga ändringar, visa namn på de filer som skulle\n" +" ha tagits bort\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:267 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x SUF städa upp filer om de har detta suffix\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:268 +#, c-format +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files for\n" +" clean up\n" +msgstr "" +" -x, --strip-extension=EXT ta bort denna ändelse innan vi identifierar filer\n" +" som skall tas bort\n" + +#: pg_archivecleanup.c:270 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help visa denna hjälp, avsluta sedan\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" @@ -141,7 +165,7 @@ msgstr "" "t.ex.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" @@ -154,7 +178,7 @@ msgstr "" "t.ex.\n" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:269 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" @@ -163,22 +187,22 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_archivecleanup.c:332 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "måste ange en arkivplats" -#: pg_archivecleanup.c:344 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "måste ange äldsta sparade WAL-filen" -#: pg_archivecleanup.c:351 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "för många kommandoradsargument" diff --git a/src/bin/pg_archivecleanup/po/uk.po b/src/bin/pg_archivecleanup/po/uk.po index 120f799bc7014..767f51cc73f95 100644 --- a/src/bin/pg_archivecleanup/po/uk.po +++ b/src/bin/pg_archivecleanup/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:51+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:23+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_archivecleanup.pot\n" -"X-Crowdin-File-ID: 898\n" +"X-Crowdin-File: /REL_17_STABLE/pg_archivecleanup.pot\n" +"X-Crowdin-File-ID: 1032\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,90 +37,110 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " -#: pg_archivecleanup.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" msgstr "архівного розташування \"%s\" не існує" -#: pg_archivecleanup.c:151 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "не вдалося відкрити архівне розташування \"%s\":%m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "не можливо видалити файл \"%s\": %m" -#: pg_archivecleanup.c:157 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" msgstr "не вдалося прочитати архівне розташування \"%s\":%m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "не вдалося закрити архівне розташування \"%s\":%m" -#: pg_archivecleanup.c:164 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "не вдалося відкрити архівне розташування \"%s\":%m" - -#: pg_archivecleanup.c:237 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "недійсна назва файла з аргументом" -#: pg_archivecleanup.c:238 pg_archivecleanup.c:313 pg_archivecleanup.c:333 -#: pg_archivecleanup.c:345 pg_archivecleanup.c:352 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_archivecleanup.c:251 +#: pg_archivecleanup.c:259 #, c-format msgid "%s removes older WAL files from PostgreSQL archives.\n\n" msgstr "%s видаляє старі WAL-файли з архівів PostgreSQL.\n\n" -#: pg_archivecleanup.c:252 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_archivecleanup.c:253 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" msgstr " %s [OPTION]... РОЗТАШУВАННЯ_АРХІВА НАЙДАВНІШИЙ_ЗБЕРЕЖЕНИЙ_WAL_ФАЙЛ\n" -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:262 #, c-format msgid "\n" "Options:\n" msgstr "\n" "Параметри:\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d генерує налагоджувальні повідомлення (детальний режим)\n" +msgid " -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -b, --clean-backup-history очистити файли, включаючи файли історії резервного копіювання\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:264 #, c-format -msgid " -n dry run, show the names of the files that would be removed\n" -msgstr " -n сухий запуск, показує тільки ті файли, які будуть видалені\n" +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug генерувати налагоджувальний вивід (розгорнутий режим)\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:265 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version показати версію, потім вийти\n" +msgid " -n, --dry-run dry run, show the names of the files that would be\n" +" removed\n" +msgstr " -n, --dry-run сухий запуск, показати назви файлів, які будуть\n" +" вилучені\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:267 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x EXT прибрати файли з цим розширенням\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:268 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help показати цю довідку, потім вийти\n" +msgid " -x, --strip-extension=EXT strip this extension before identifying files for\n" +" clean up\n" +msgstr " -x, --strip-extension=EXT вилучати це розширення перед ідентифікацією файлів для\n" +" очищення\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:270 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку, потім вийти\n" + +#: pg_archivecleanup.c:271 #, c-format msgid "\n" "For use as archive_cleanup_command in postgresql.conf:\n" @@ -133,7 +153,7 @@ msgstr "\n" "напр.\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:265 +#: pg_archivecleanup.c:276 #, c-format msgid "\n" "Or for use as a standalone archive cleaner:\n" @@ -144,29 +164,29 @@ msgstr "\n" "наприклад:\n" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:269 +#: pg_archivecleanup.c:280 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_archivecleanup.c:270 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_archivecleanup.c:332 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "необхідно вказати розташування архіва" -#: pg_archivecleanup.c:344 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" msgstr "необхідно вказати найдавніший збережений WAL-файл" -#: pg_archivecleanup.c:351 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "занадто багато аргументів командного рядка" diff --git a/src/bin/pg_archivecleanup/po/zh_CN.po b/src/bin/pg_archivecleanup/po/zh_CN.po index e8c33482e1750..ae2cc68e75c68 100644 --- a/src/bin/pg_archivecleanup/po/zh_CN.po +++ b/src/bin/pg_archivecleanup/po/zh_CN.po @@ -1,92 +1,98 @@ # LANGUAGE message translation file for pg_archivecleanup # Copyright (C) 2019 PostgreSQL Global Development Group # This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package. -# FIRST AUTHOR , 2019. +# Dianjin Wang , 2024. # msgid "" msgstr "" -"Project-Id-Version: pg_archivecleanup (PostgreSQL) 14\n" +"Project-Id-Version: pg_archivecleanup (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 05:48+0000\n" -"PO-Revision-Date: 2021-08-14 19:40+0800\n" -"Last-Translator: Jie Zhang \n" +"POT-Creation-Date: 2024-06-06 01:23+0000\n" +"PO-Revision-Date: 2024-06-06 16:40+0800\n" +"Last-Translator: Dianjin Wang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.4.4\n" -#: ../../../src/common/logging.c:259 -#, c-format -msgid "fatal: " -msgstr "致命的: " - -#: ../../../src/common/logging.c:266 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "错误: " -#: ../../../src/common/logging.c:273 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "警告: " -#: pg_archivecleanup.c:66 +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "详细信息: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "提示: " + +#: pg_archivecleanup.c:68 #, c-format msgid "archive location \"%s\" does not exist" -msgstr "存档位置\"%s\"不存在" +msgstr "存档位置 \"%s\" 不存在" -#: pg_archivecleanup.c:152 +#: pg_archivecleanup.c:100 +#, c-format +msgid "could not open archive location \"%s\": %m" +msgstr "无法打开存档位置 \"%s\": %m" + +#: pg_archivecleanup.c:164 #, c-format msgid "could not remove file \"%s\": %m" msgstr "无法删除文件 \"%s\": %m" -#: pg_archivecleanup.c:160 +#: pg_archivecleanup.c:169 #, c-format msgid "could not read archive location \"%s\": %m" -msgstr "无法读取存档位置\"%s\": %m" +msgstr "无法读取存档位置 \"%s\": %m" -#: pg_archivecleanup.c:163 +#: pg_archivecleanup.c:172 #, c-format msgid "could not close archive location \"%s\": %m" msgstr "无法关闭存档位置 \"%s\": %m" -#: pg_archivecleanup.c:167 -#, c-format -msgid "could not open archive location \"%s\": %m" -msgstr "无法打开存档位置\"%s\": %m" - -#: pg_archivecleanup.c:240 +#: pg_archivecleanup.c:245 #, c-format msgid "invalid file name argument" msgstr "文件名参数无效" -#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336 -#: pg_archivecleanup.c:348 pg_archivecleanup.c:355 +#: pg_archivecleanup.c:246 pg_archivecleanup.c:334 pg_archivecleanup.c:354 +#: pg_archivecleanup.c:366 pg_archivecleanup.c:373 #, c-format -msgid "Try \"%s --help\" for more information.\n" -msgstr "请用 \"%s --help\" 获取更多的信息.\n" +msgid "Try \"%s --help\" for more information." +msgstr "请用 \"%s --help\" 获取更多的信息." -#: pg_archivecleanup.c:254 +#: pg_archivecleanup.c:259 #, c-format msgid "" "%s removes older WAL files from PostgreSQL archives.\n" "\n" msgstr "" -"%s 从PostgreSQL存档中删除旧的WAL文件.\n" +"%s 从 PostgreSQL 存档中删除旧的 WAL 文件.\n" "\n" -#: pg_archivecleanup.c:255 +#: pg_archivecleanup.c:260 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_archivecleanup.c:256 +#: pg_archivecleanup.c:261 #, c-format msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n" -msgstr " %s [OPTION]... 归档文件位置 最早保存的WAL文件\n" +msgstr " %s [选项]... 归档文件位置 最早保存的WAL文件\n" -#: pg_archivecleanup.c:257 +#: pg_archivecleanup.c:262 #, c-format msgid "" "\n" @@ -95,32 +101,45 @@ msgstr "" "\n" "选项:\n" -#: pg_archivecleanup.c:258 +#: pg_archivecleanup.c:263 #, c-format -msgid " -d generate debug output (verbose mode)\n" -msgstr " -d 生成调试输出(详细模式)\n" +msgid " -b, --clean-backup-history clean up files including backup history files\n" +msgstr " -b, --clean-backup-history 清理包括备份历史文件在内的文件\n" -#: pg_archivecleanup.c:259 +#: pg_archivecleanup.c:264 #, c-format -msgid " -n dry run, show the names of the files that would be removed\n" -msgstr " -n dry运行,显示要删除的文件的名称\n" +msgid " -d, --debug generate debug output (verbose mode)\n" +msgstr " -d, --debug 生成调试输出(详细模式)\n" -#: pg_archivecleanup.c:260 +#: pg_archivecleanup.c:265 #, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version 输出版本信息,然后退出\n" +msgid "" +" -n, --dry-run dry run, show the names of the files that would be\n" +" removed\n" +msgstr "" +" -n, --dry-run 模拟运行, 显示要被删除的文件名称\n" +" \n" -#: pg_archivecleanup.c:261 +#: pg_archivecleanup.c:267 #, c-format -msgid " -x EXT clean up files if they have this extension\n" -msgstr " -x EXT 如果文件具有此扩展名,则清除文件\n" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 输出版本信息,然后退出\n" -#: pg_archivecleanup.c:262 +#: pg_archivecleanup.c:268 +#, c-format +msgid "" +" -x, --strip-extension=EXT strip this extension before identifying files for\n" +" clean up\n" +msgstr "" +" -x, --strip-extension=EXT 在识别要清理的文件前移除该扩展\n" +" \n" + +#: pg_archivecleanup.c:270 #, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help 显示帮助信息,然后退出\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 显示此帮助,然后退出\n" -#: pg_archivecleanup.c:263 +#: pg_archivecleanup.c:271 #, c-format msgid "" "\n" @@ -130,12 +149,12 @@ msgid "" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" msgstr "" "\n" -"在postgresql.conf中,archive_cleanup_command的用法 \n" +"在 postgresql.conf 中,archive_cleanup_command 的用法为:\n" " archive_cleanup_command = 'pg_archivecleanup [选项]... 存档位置 %%r'\n" -"例.\n" +"例如:\n" " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n" -#: pg_archivecleanup.c:268 +#: pg_archivecleanup.c:276 #, c-format msgid "" "\n" @@ -144,36 +163,55 @@ msgid "" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" msgstr "" "\n" -"或者,用作独立存档清理程序:\n" -"例.\n" +"或者,将其用作独立存档清理程序:\n" +"例如:\n" " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n" -#: pg_archivecleanup.c:272 +#: pg_archivecleanup.c:280 #, c-format msgid "" "\n" "Report bugs to <%s>.\n" msgstr "" "\n" -"臭虫报告至<%s>.\n" +"报告缺陷: <%s>.\n" -#: pg_archivecleanup.c:273 +#: pg_archivecleanup.c:281 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 主页: <%s>\n" -#: pg_archivecleanup.c:335 +#: pg_archivecleanup.c:353 #, c-format msgid "must specify archive location" msgstr "必须指定存档位置" -#: pg_archivecleanup.c:347 +#: pg_archivecleanup.c:365 #, c-format msgid "must specify oldest kept WAL file" -msgstr "必须指定最早保存的WAL文件" +msgstr "必须指定最早保存的 WAL 文件" -#: pg_archivecleanup.c:354 +#: pg_archivecleanup.c:372 #, c-format msgid "too many command-line arguments" msgstr "命令行参数太多" +#, c-format +#~ msgid " -?, --help show this help, then exit\n" +#~ msgstr " -?, --help 显示帮助信息,然后退出\n" + +#, c-format +#~ msgid " -V, --version output version information, then exit\n" +#~ msgstr " -V, --version 输出版本信息,然后退出\n" + +#, c-format +#~ msgid " -x EXT clean up files if they have this extension\n" +#~ msgstr " -x EXT 如果文件具有此扩展名,则清除文件\n" + +#, c-format +#~ msgid "Try \"%s --help\" for more information.\n" +#~ msgstr "请用 \"%s --help\" 获取更多的信息.\n" + +#, c-format +#~ msgid "fatal: " +#~ msgstr "致命的: " diff --git a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl b/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl index 91a98c71e9974..c6148cda7fc2f 100644 --- a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl +++ b/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -85,10 +85,11 @@ sub remove_files my $stderr; my $oldestkeptwalfile = '00000001000000370000000E'; - my $result = - IPC::Run::run [ 'pg_archivecleanup', '-d', '-n', $tempdir, - $oldestkeptwalfile ], - '2>', \$stderr; + my $result = IPC::Run::run [ + 'pg_archivecleanup', '--debug', '--dry-run', $tempdir, + $oldestkeptwalfile + ], + '2>' => \$stderr; ok($result, "pg_archivecleanup dry run: exit code 0"); for my $walpair (@walfiles_verbose) diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile index 26c53e473f560..a9557c0789f6f 100644 --- a/src/bin/pg_basebackup/Makefile +++ b/src/bin/pg_basebackup/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_basebackup # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_basebackup/Makefile @@ -37,12 +37,7 @@ OBJS = \ BBOBJS = \ pg_basebackup.o \ - bbstreamer_file.o \ - bbstreamer_gzip.o \ - bbstreamer_inject.o \ - bbstreamer_lz4.o \ - bbstreamer_tar.o \ - bbstreamer_zstd.o + astreamer_inject.o all: pg_basebackup pg_createsubscriber pg_receivewal pg_recvlogical diff --git a/src/bin/pg_basebackup/bbstreamer_inject.c b/src/bin/pg_basebackup/astreamer_inject.c similarity index 53% rename from src/bin/pg_basebackup/bbstreamer_inject.c rename to src/bin/pg_basebackup/astreamer_inject.c index 194026b56e9cf..15334e458ad1e 100644 --- a/src/bin/pg_basebackup/bbstreamer_inject.c +++ b/src/bin/pg_basebackup/astreamer_inject.c @@ -1,51 +1,51 @@ /*------------------------------------------------------------------------- * - * bbstreamer_inject.c + * astreamer_inject.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_inject.c + * src/bin/pg_basebackup/astreamer_inject.c *------------------------------------------------------------------------- */ #include "postgres_fe.h" -#include "bbstreamer.h" +#include "astreamer_inject.h" #include "common/file_perm.h" #include "common/logging.h" -typedef struct bbstreamer_recovery_injector +typedef struct astreamer_recovery_injector { - bbstreamer base; + astreamer base; bool skip_file; bool is_recovery_guc_supported; bool is_postgresql_auto_conf; bool found_postgresql_auto_conf; PQExpBuffer recoveryconfcontents; - bbstreamer_member member; -} bbstreamer_recovery_injector; - -static void bbstreamer_recovery_injector_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_recovery_injector_finalize(bbstreamer *streamer); -static void bbstreamer_recovery_injector_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_recovery_injector_ops = { - .content = bbstreamer_recovery_injector_content, - .finalize = bbstreamer_recovery_injector_finalize, - .free = bbstreamer_recovery_injector_free + astreamer_member member; +} astreamer_recovery_injector; + +static void astreamer_recovery_injector_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_recovery_injector_finalize(astreamer *streamer); +static void astreamer_recovery_injector_free(astreamer *streamer); + +static const astreamer_ops astreamer_recovery_injector_ops = { + .content = astreamer_recovery_injector_content, + .finalize = astreamer_recovery_injector_finalize, + .free = astreamer_recovery_injector_free }; /* - * Create a bbstreamer that can edit recoverydata into an archive stream. + * Create a astreamer that can edit recoverydata into an archive stream. * - * The input should be a series of typed chunks (not BBSTREAMER_UNKNOWN) as - * per the conventions described in bbstreamer.h; the chunks forwarded to - * the next bbstreamer will be similarly typed, but the - * BBSTREAMER_MEMBER_HEADER chunks may be zero-length in cases where we've + * The input should be a series of typed chunks (not ASTREAMER_UNKNOWN) as + * per the conventions described in astreamer.h; the chunks forwarded to + * the next astreamer will be similarly typed, but the + * ASTREAMER_MEMBER_HEADER chunks may be zero-length in cases where we've * edited the archive stream. * * Our goal is to do one of the following three things with the content passed @@ -61,16 +61,16 @@ static const bbstreamer_ops bbstreamer_recovery_injector_ops = { * zero-length standby.signal file, dropping any file with that name from * the archive. */ -bbstreamer * -bbstreamer_recovery_injector_new(bbstreamer *next, - bool is_recovery_guc_supported, - PQExpBuffer recoveryconfcontents) +astreamer * +astreamer_recovery_injector_new(astreamer *next, + bool is_recovery_guc_supported, + PQExpBuffer recoveryconfcontents) { - bbstreamer_recovery_injector *streamer; + astreamer_recovery_injector *streamer; - streamer = palloc0(sizeof(bbstreamer_recovery_injector)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_recovery_injector_ops; + streamer = palloc0(sizeof(astreamer_recovery_injector)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_recovery_injector_ops; streamer->base.bbs_next = next; streamer->is_recovery_guc_supported = is_recovery_guc_supported; streamer->recoveryconfcontents = recoveryconfcontents; @@ -82,21 +82,21 @@ bbstreamer_recovery_injector_new(bbstreamer *next, * Handle each chunk of tar content while injecting recovery configuration. */ static void -bbstreamer_recovery_injector_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_recovery_injector_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_recovery_injector *mystreamer; + astreamer_recovery_injector *mystreamer; - mystreamer = (bbstreamer_recovery_injector *) streamer; - Assert(member != NULL || context == BBSTREAMER_ARCHIVE_TRAILER); + mystreamer = (astreamer_recovery_injector *) streamer; + Assert(member != NULL || context == ASTREAMER_ARCHIVE_TRAILER); switch (context) { - case BBSTREAMER_MEMBER_HEADER: + case ASTREAMER_MEMBER_HEADER: /* Must copy provided data so we have the option to modify it. */ - memcpy(&mystreamer->member, member, sizeof(bbstreamer_member)); + memcpy(&mystreamer->member, member, sizeof(astreamer_member)); /* * On v12+, skip standby.signal and edit postgresql.auto.conf; on @@ -119,8 +119,8 @@ bbstreamer_recovery_injector_content(bbstreamer *streamer, /* * Zap data and len because the archive header is no - * longer valid; some subsequent bbstreamer must - * regenerate it if it's necessary. + * longer valid; some subsequent astreamer must regenerate + * it if it's necessary. */ data = NULL; len = 0; @@ -135,26 +135,26 @@ bbstreamer_recovery_injector_content(bbstreamer *streamer, return; break; - case BBSTREAMER_MEMBER_CONTENTS: + case ASTREAMER_MEMBER_CONTENTS: /* Do not forward if the file is to be skipped. */ if (mystreamer->skip_file) return; break; - case BBSTREAMER_MEMBER_TRAILER: + case ASTREAMER_MEMBER_TRAILER: /* Do not forward it the file is to be skipped. */ if (mystreamer->skip_file) return; /* Append provided content to whatever we already sent. */ if (mystreamer->is_postgresql_auto_conf) - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->recoveryconfcontents->data, - mystreamer->recoveryconfcontents->len, - BBSTREAMER_MEMBER_CONTENTS); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->recoveryconfcontents->data, + mystreamer->recoveryconfcontents->len, + ASTREAMER_MEMBER_CONTENTS); break; - case BBSTREAMER_ARCHIVE_TRAILER: + case ASTREAMER_ARCHIVE_TRAILER: if (mystreamer->is_recovery_guc_supported) { /* @@ -163,22 +163,22 @@ bbstreamer_recovery_injector_content(bbstreamer *streamer, * member now. */ if (!mystreamer->found_postgresql_auto_conf) - bbstreamer_inject_file(mystreamer->base.bbs_next, - "postgresql.auto.conf", - mystreamer->recoveryconfcontents->data, - mystreamer->recoveryconfcontents->len); + astreamer_inject_file(mystreamer->base.bbs_next, + "postgresql.auto.conf", + mystreamer->recoveryconfcontents->data, + mystreamer->recoveryconfcontents->len); /* Inject empty standby.signal file. */ - bbstreamer_inject_file(mystreamer->base.bbs_next, - "standby.signal", "", 0); + astreamer_inject_file(mystreamer->base.bbs_next, + "standby.signal", "", 0); } else { /* Inject recovery.conf file with specified contents. */ - bbstreamer_inject_file(mystreamer->base.bbs_next, - "recovery.conf", - mystreamer->recoveryconfcontents->data, - mystreamer->recoveryconfcontents->len); + astreamer_inject_file(mystreamer->base.bbs_next, + "recovery.conf", + mystreamer->recoveryconfcontents->data, + mystreamer->recoveryconfcontents->len); } /* Nothing to do here. */ @@ -189,26 +189,26 @@ bbstreamer_recovery_injector_content(bbstreamer *streamer, pg_fatal("unexpected state while injecting recovery settings"); } - bbstreamer_content(mystreamer->base.bbs_next, &mystreamer->member, - data, len, context); + astreamer_content(mystreamer->base.bbs_next, &mystreamer->member, + data, len, context); } /* - * End-of-stream processing for this bbstreamer. + * End-of-stream processing for this astreamer. */ static void -bbstreamer_recovery_injector_finalize(bbstreamer *streamer) +astreamer_recovery_injector_finalize(astreamer *streamer) { - bbstreamer_finalize(streamer->bbs_next); + astreamer_finalize(streamer->bbs_next); } /* - * Free memory associated with this bbstreamer. + * Free memory associated with this astreamer. */ static void -bbstreamer_recovery_injector_free(bbstreamer *streamer) +astreamer_recovery_injector_free(astreamer *streamer) { - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); pfree(streamer); } @@ -216,10 +216,10 @@ bbstreamer_recovery_injector_free(bbstreamer *streamer) * Inject a member into the archive with specified contents. */ void -bbstreamer_inject_file(bbstreamer *streamer, char *pathname, char *data, - int len) +astreamer_inject_file(astreamer *streamer, char *pathname, char *data, + int len) { - bbstreamer_member member; + astreamer_member member; strlcpy(member.pathname, pathname, MAXPGPATH); member.size = len; @@ -238,12 +238,12 @@ bbstreamer_inject_file(bbstreamer *streamer, char *pathname, char *data, /* * We don't know here how to generate valid member headers and trailers * for the archiving format in use, so if those are needed, some successor - * bbstreamer will have to generate them using the data from 'member'. + * astreamer will have to generate them using the data from 'member'. */ - bbstreamer_content(streamer, &member, NULL, 0, - BBSTREAMER_MEMBER_HEADER); - bbstreamer_content(streamer, &member, data, len, - BBSTREAMER_MEMBER_CONTENTS); - bbstreamer_content(streamer, &member, NULL, 0, - BBSTREAMER_MEMBER_TRAILER); + astreamer_content(streamer, &member, NULL, 0, + ASTREAMER_MEMBER_HEADER); + astreamer_content(streamer, &member, data, len, + ASTREAMER_MEMBER_CONTENTS); + astreamer_content(streamer, &member, NULL, 0, + ASTREAMER_MEMBER_TRAILER); } diff --git a/src/bin/pg_basebackup/astreamer_inject.h b/src/bin/pg_basebackup/astreamer_inject.h new file mode 100644 index 0000000000000..cd11685588423 --- /dev/null +++ b/src/bin/pg_basebackup/astreamer_inject.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * astreamer_inject.h + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/bin/pg_basebackup/astreamer_inject.h + *------------------------------------------------------------------------- + */ + +#ifndef ASTREAMER_INJECT_H +#define ASTREAMER_INJECT_H + +#include "fe_utils/astreamer.h" +#include "pqexpbuffer.h" + +extern astreamer *astreamer_recovery_injector_new(astreamer *next, + bool is_recovery_guc_supported, + PQExpBuffer recoveryconfcontents); +extern void astreamer_inject_file(astreamer *streamer, char *pathname, + char *data, int len); + +#endif diff --git a/src/bin/pg_basebackup/bbstreamer.h b/src/bin/pg_basebackup/bbstreamer.h deleted file mode 100644 index 3b820f13b519a..0000000000000 --- a/src/bin/pg_basebackup/bbstreamer.h +++ /dev/null @@ -1,226 +0,0 @@ -/*------------------------------------------------------------------------- - * - * bbstreamer.h - * - * Each tar archive returned by the server is passed to one or more - * bbstreamer objects for further processing. The bbstreamer may do - * something simple, like write the archive to a file, perhaps after - * compressing it, but it can also do more complicated things, like - * annotating the byte stream to indicate which parts of the data - * correspond to tar headers or trailing padding, vs. which parts are - * payload data. A subsequent bbstreamer may use this information to - * make further decisions about how to process the data; for example, - * it might choose to modify the archive contents. - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer.h - *------------------------------------------------------------------------- - */ - -#ifndef BBSTREAMER_H -#define BBSTREAMER_H - -#include "common/compression.h" -#include "lib/stringinfo.h" -#include "pqexpbuffer.h" - -struct bbstreamer; -struct bbstreamer_ops; -typedef struct bbstreamer bbstreamer; -typedef struct bbstreamer_ops bbstreamer_ops; - -/* - * Each chunk of archive data passed to a bbstreamer is classified into one - * of these categories. When data is first received from the remote server, - * each chunk will be categorized as BBSTREAMER_UNKNOWN, and the chunks will - * be of whatever size the remote server chose to send. - * - * If the archive is parsed (e.g. see bbstreamer_tar_parser_new()), then all - * chunks should be labelled as one of the other types listed here. In - * addition, there should be exactly one BBSTREAMER_MEMBER_HEADER chunk and - * exactly one BBSTREAMER_MEMBER_TRAILER chunk per archive member, even if - * that means a zero-length call. There can be any number of - * BBSTREAMER_MEMBER_CONTENTS chunks in between those calls. There - * should exactly BBSTREAMER_ARCHIVE_TRAILER chunk, and it should follow the - * last BBSTREAMER_MEMBER_TRAILER chunk. - * - * In theory, we could need other classifications here, such as a way of - * indicating an archive header, but the "tar" format doesn't need anything - * else, so for the time being there's no point. - */ -typedef enum -{ - BBSTREAMER_UNKNOWN, - BBSTREAMER_MEMBER_HEADER, - BBSTREAMER_MEMBER_CONTENTS, - BBSTREAMER_MEMBER_TRAILER, - BBSTREAMER_ARCHIVE_TRAILER, -} bbstreamer_archive_context; - -/* - * Each chunk of data that is classified as BBSTREAMER_MEMBER_HEADER, - * BBSTREAMER_MEMBER_CONTENTS, or BBSTREAMER_MEMBER_TRAILER should also - * pass a pointer to an instance of this struct. The details are expected - * to be present in the archive header and used to fill the struct, after - * which all subsequent calls for the same archive member are expected to - * pass the same details. - */ -typedef struct -{ - char pathname[MAXPGPATH]; - pgoff_t size; - mode_t mode; - uid_t uid; - gid_t gid; - bool is_directory; - bool is_link; - char linktarget[MAXPGPATH]; -} bbstreamer_member; - -/* - * Generally, each type of bbstreamer will define its own struct, but the - * first element should be 'bbstreamer base'. A bbstreamer that does not - * require any additional private data could use this structure directly. - * - * bbs_ops is a pointer to the bbstreamer_ops object which contains the - * function pointers appropriate to this type of bbstreamer. - * - * bbs_next is a pointer to the successor bbstreamer, for those types of - * bbstreamer which forward data to a successor. It need not be used and - * should be set to NULL when not relevant. - * - * bbs_buffer is a buffer for accumulating data for temporary storage. Each - * type of bbstreamer makes its own decisions about whether and how to use - * this buffer. - */ -struct bbstreamer -{ - const bbstreamer_ops *bbs_ops; - bbstreamer *bbs_next; - StringInfoData bbs_buffer; -}; - -/* - * There are three callbacks for a bbstreamer. The 'content' callback is - * called repeatedly, as described in the bbstreamer_archive_context comments. - * Then, the 'finalize' callback is called once at the end, to give the - * bbstreamer a chance to perform cleanup such as closing files. Finally, - * because this code is running in a frontend environment where, as of this - * writing, there are no memory contexts, the 'free' callback is called to - * release memory. These callbacks should always be invoked using the static - * inline functions defined below. - */ -struct bbstreamer_ops -{ - void (*content) (bbstreamer *streamer, bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); - void (*finalize) (bbstreamer *streamer); - void (*free) (bbstreamer *streamer); -}; - -/* Send some content to a bbstreamer. */ -static inline void -bbstreamer_content(bbstreamer *streamer, bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) -{ - Assert(streamer != NULL); - streamer->bbs_ops->content(streamer, member, data, len, context); -} - -/* Finalize a bbstreamer. */ -static inline void -bbstreamer_finalize(bbstreamer *streamer) -{ - Assert(streamer != NULL); - streamer->bbs_ops->finalize(streamer); -} - -/* Free a bbstreamer. */ -static inline void -bbstreamer_free(bbstreamer *streamer) -{ - Assert(streamer != NULL); - streamer->bbs_ops->free(streamer); -} - -/* - * This is a convenience method for use when implementing a bbstreamer; it is - * not for use by outside callers. It adds the amount of data specified by - * 'nbytes' to the bbstreamer's buffer and adjusts '*len' and '*data' - * accordingly. - */ -static inline void -bbstreamer_buffer_bytes(bbstreamer *streamer, const char **data, int *len, - int nbytes) -{ - Assert(nbytes <= *len); - - appendBinaryStringInfo(&streamer->bbs_buffer, *data, nbytes); - *len -= nbytes; - *data += nbytes; -} - -/* - * This is a convenience method for use when implementing a bbstreamer; it is - * not for use by outsider callers. It attempts to add enough data to the - * bbstreamer's buffer to reach a length of target_bytes and adjusts '*len' - * and '*data' accordingly. It returns true if the target length has been - * reached and false otherwise. - */ -static inline bool -bbstreamer_buffer_until(bbstreamer *streamer, const char **data, int *len, - int target_bytes) -{ - int buflen = streamer->bbs_buffer.len; - - if (buflen >= target_bytes) - { - /* Target length already reached; nothing to do. */ - return true; - } - - if (buflen + *len < target_bytes) - { - /* Not enough data to reach target length; buffer all of it. */ - bbstreamer_buffer_bytes(streamer, data, len, *len); - return false; - } - - /* Buffer just enough to reach the target length. */ - bbstreamer_buffer_bytes(streamer, data, len, target_bytes - buflen); - return true; -} - -/* - * Functions for creating bbstreamer objects of various types. See the header - * comments for each of these functions for details. - */ -extern bbstreamer *bbstreamer_plain_writer_new(char *pathname, FILE *file); -extern bbstreamer *bbstreamer_gzip_writer_new(char *pathname, FILE *file, - pg_compress_specification *compress); -extern bbstreamer *bbstreamer_extractor_new(const char *basepath, - const char *(*link_map) (const char *), - void (*report_output_file) (const char *)); - -extern bbstreamer *bbstreamer_gzip_decompressor_new(bbstreamer *next); -extern bbstreamer *bbstreamer_lz4_compressor_new(bbstreamer *next, - pg_compress_specification *compress); -extern bbstreamer *bbstreamer_lz4_decompressor_new(bbstreamer *next); -extern bbstreamer *bbstreamer_zstd_compressor_new(bbstreamer *next, - pg_compress_specification *compress); -extern bbstreamer *bbstreamer_zstd_decompressor_new(bbstreamer *next); -extern bbstreamer *bbstreamer_tar_parser_new(bbstreamer *next); -extern bbstreamer *bbstreamer_tar_terminator_new(bbstreamer *next); -extern bbstreamer *bbstreamer_tar_archiver_new(bbstreamer *next); - -extern bbstreamer *bbstreamer_recovery_injector_new(bbstreamer *next, - bool is_recovery_guc_supported, - PQExpBuffer recoveryconfcontents); -extern void bbstreamer_inject_file(bbstreamer *streamer, char *pathname, - char *data, int len); - -#endif diff --git a/src/bin/pg_basebackup/meson.build b/src/bin/pg_basebackup/meson.build index c00acd5e11828..8a1c96b4f5c84 100644 --- a/src/bin/pg_basebackup/meson.build +++ b/src/bin/pg_basebackup/meson.build @@ -1,12 +1,7 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group common_sources = files( - 'bbstreamer_file.c', - 'bbstreamer_gzip.c', - 'bbstreamer_inject.c', - 'bbstreamer_lz4.c', - 'bbstreamer_tar.c', - 'bbstreamer_zstd.c', + 'astreamer_inject.c', 'receivelog.c', 'streamutil.c', 'walmethods.c', diff --git a/src/bin/pg_basebackup/nls.mk b/src/bin/pg_basebackup/nls.mk index 384dbb021e922..f75f44dbe643c 100644 --- a/src/bin/pg_basebackup/nls.mk +++ b/src/bin/pg_basebackup/nls.mk @@ -1,12 +1,7 @@ # src/bin/pg_basebackup/nls.mk CATALOG_NAME = pg_basebackup GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ - bbstreamer_file.c \ - bbstreamer_gzip.c \ - bbstreamer_inject.c \ - bbstreamer_lz4.c \ - bbstreamer_tar.c \ - bbstreamer_zstd.c \ + astreamer_inject.c \ pg_basebackup.c \ pg_createsubscriber.c \ pg_receivewal.c \ @@ -19,6 +14,11 @@ GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ ../../common/fe_memutils.c \ ../../common/file_utils.c \ ../../common/restricted_token.c \ + ../../fe_utils/astreamer_file.c \ + ../../fe_utils/astreamer_gzip.c \ + ../../fe_utils/astreamer_lz4.c \ + ../../fe_utils/astreamer_tar.c \ + ../../fe_utils/astreamer_zstd.c \ ../../fe_utils/option_utils.c \ ../../fe_utils/recovery_gen.c \ ../../fe_utils/string_utils.c diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 8f3dd04fd2226..eb7354200bcee 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -4,7 +4,7 @@ * * Author: Magnus Hagander * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/pg_basebackup.c @@ -26,8 +26,8 @@ #endif #include "access/xlog_internal.h" +#include "astreamer_inject.h" #include "backup/basebackup.h" -#include "bbstreamer.h" #include "common/compression.h" #include "common/file_perm.h" #include "common/file_utils.h" @@ -57,8 +57,8 @@ typedef struct ArchiveStreamState { int tablespacenum; pg_compress_specification *compress; - bbstreamer *streamer; - bbstreamer *manifest_inject_streamer; + astreamer *streamer; + astreamer *manifest_inject_streamer; PQExpBuffer manifest_buffer; char manifest_filename[MAXPGPATH]; FILE *manifest_file; @@ -67,7 +67,7 @@ typedef struct ArchiveStreamState typedef struct WriteTarState { int tablespacenum; - bbstreamer *streamer; + astreamer *streamer; } WriteTarState; typedef struct WriteManifestState @@ -199,11 +199,11 @@ static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *fo static void progress_update_filename(const char *filename); static void progress_report(int tablespacenum, bool force, bool finished); -static bbstreamer *CreateBackupStreamer(char *archive_name, char *spclocation, - bbstreamer **manifest_inject_streamer_p, - bool is_recovery_guc_supported, - bool expect_unterminated_tarfile, - pg_compress_specification *compress); +static astreamer *CreateBackupStreamer(char *archive_name, char *spclocation, + astreamer **manifest_inject_streamer_p, + bool is_recovery_guc_supported, + bool expect_unterminated_tarfile, + pg_compress_specification *compress); static void ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data); static char GetCopyDataByte(size_t r, char *copybuf, size_t *cursor); @@ -667,7 +667,8 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier, if (temp_replication_slot || create_slot) { if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL, - temp_replication_slot, true, true, false, false)) + temp_replication_slot, true, true, false, + false, false)) exit(1); if (verbose) @@ -1053,19 +1054,19 @@ ReceiveCopyData(PGconn *conn, WriteDataCallback callback, * the options selected by the user. We may just write the results directly * to a file, or we might compress first, or we might extract the tar file * and write each member separately. This function doesn't do any of that - * directly, but it works out what kind of bbstreamer we need to create so + * directly, but it works out what kind of astreamer we need to create so * that the right stuff happens when, down the road, we actually receive * the data. */ -static bbstreamer * +static astreamer * CreateBackupStreamer(char *archive_name, char *spclocation, - bbstreamer **manifest_inject_streamer_p, + astreamer **manifest_inject_streamer_p, bool is_recovery_guc_supported, bool expect_unterminated_tarfile, pg_compress_specification *compress) { - bbstreamer *streamer = NULL; - bbstreamer *manifest_inject_streamer = NULL; + astreamer *streamer = NULL; + astreamer *manifest_inject_streamer = NULL; bool inject_manifest; bool is_tar, is_tar_gz, @@ -1160,9 +1161,9 @@ CreateBackupStreamer(char *archive_name, char *spclocation, directory = psprintf("%s/%s", basedir, spclocation); else directory = get_tablespace_mapping(spclocation); - streamer = bbstreamer_extractor_new(directory, - get_tablespace_mapping, - progress_update_filename); + streamer = astreamer_extractor_new(directory, + get_tablespace_mapping, + progress_update_filename); } else { @@ -1188,27 +1189,27 @@ CreateBackupStreamer(char *archive_name, char *spclocation, } if (compress->algorithm == PG_COMPRESSION_NONE) - streamer = bbstreamer_plain_writer_new(archive_filename, - archive_file); + streamer = astreamer_plain_writer_new(archive_filename, + archive_file); else if (compress->algorithm == PG_COMPRESSION_GZIP) { strlcat(archive_filename, ".gz", sizeof(archive_filename)); - streamer = bbstreamer_gzip_writer_new(archive_filename, - archive_file, compress); + streamer = astreamer_gzip_writer_new(archive_filename, + archive_file, compress); } else if (compress->algorithm == PG_COMPRESSION_LZ4) { strlcat(archive_filename, ".lz4", sizeof(archive_filename)); - streamer = bbstreamer_plain_writer_new(archive_filename, - archive_file); - streamer = bbstreamer_lz4_compressor_new(streamer, compress); + streamer = astreamer_plain_writer_new(archive_filename, + archive_file); + streamer = astreamer_lz4_compressor_new(streamer, compress); } else if (compress->algorithm == PG_COMPRESSION_ZSTD) { strlcat(archive_filename, ".zst", sizeof(archive_filename)); - streamer = bbstreamer_plain_writer_new(archive_filename, - archive_file); - streamer = bbstreamer_zstd_compressor_new(streamer, compress); + streamer = astreamer_plain_writer_new(archive_filename, + archive_file); + streamer = astreamer_zstd_compressor_new(streamer, compress); } else { @@ -1222,7 +1223,7 @@ CreateBackupStreamer(char *archive_name, char *spclocation, * into it. */ if (must_parse_archive) - streamer = bbstreamer_tar_archiver_new(streamer); + streamer = astreamer_tar_archiver_new(streamer); progress_update_filename(archive_filename); } @@ -1241,9 +1242,9 @@ CreateBackupStreamer(char *archive_name, char *spclocation, if (spclocation == NULL && writerecoveryconf) { Assert(must_parse_archive); - streamer = bbstreamer_recovery_injector_new(streamer, - is_recovery_guc_supported, - recoveryconfcontents); + streamer = astreamer_recovery_injector_new(streamer, + is_recovery_guc_supported, + recoveryconfcontents); } /* @@ -1253,9 +1254,9 @@ CreateBackupStreamer(char *archive_name, char *spclocation, * we're talking to such a server we'll need to add the terminator here. */ if (must_parse_archive) - streamer = bbstreamer_tar_parser_new(streamer); + streamer = astreamer_tar_parser_new(streamer); else if (expect_unterminated_tarfile) - streamer = bbstreamer_tar_terminator_new(streamer); + streamer = astreamer_tar_terminator_new(streamer); /* * If the user has requested a server compressed archive along with @@ -1264,11 +1265,11 @@ CreateBackupStreamer(char *archive_name, char *spclocation, if (format == 'p') { if (is_tar_gz) - streamer = bbstreamer_gzip_decompressor_new(streamer); + streamer = astreamer_gzip_decompressor_new(streamer); else if (is_tar_lz4) - streamer = bbstreamer_lz4_decompressor_new(streamer); + streamer = astreamer_lz4_decompressor_new(streamer); else if (is_tar_zstd) - streamer = bbstreamer_zstd_decompressor_new(streamer); + streamer = astreamer_zstd_decompressor_new(streamer); } /* Return the results. */ @@ -1307,10 +1308,10 @@ ReceiveArchiveStream(PGconn *conn, pg_compress_specification *compress) if (state.manifest_inject_streamer != NULL && state.manifest_buffer != NULL) { - bbstreamer_inject_file(state.manifest_inject_streamer, - "backup_manifest", - state.manifest_buffer->data, - state.manifest_buffer->len); + astreamer_inject_file(state.manifest_inject_streamer, + "backup_manifest", + state.manifest_buffer->data, + state.manifest_buffer->len); destroyPQExpBuffer(state.manifest_buffer); state.manifest_buffer = NULL; } @@ -1318,8 +1319,8 @@ ReceiveArchiveStream(PGconn *conn, pg_compress_specification *compress) /* If there's still an archive in progress, end processing. */ if (state.streamer != NULL) { - bbstreamer_finalize(state.streamer); - bbstreamer_free(state.streamer); + astreamer_finalize(state.streamer); + astreamer_free(state.streamer); state.streamer = NULL; } } @@ -1383,8 +1384,8 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data) /* End processing of any prior archive. */ if (state->streamer != NULL) { - bbstreamer_finalize(state->streamer); - bbstreamer_free(state->streamer); + astreamer_finalize(state->streamer); + astreamer_free(state->streamer); state->streamer = NULL; } @@ -1437,8 +1438,8 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data) else if (state->streamer != NULL) { /* Archive data. */ - bbstreamer_content(state->streamer, NULL, copybuf + 1, - r - 1, BBSTREAMER_UNKNOWN); + astreamer_content(state->streamer, NULL, copybuf + 1, + r - 1, ASTREAMER_UNKNOWN); } else pg_fatal("unexpected payload data"); @@ -1600,7 +1601,7 @@ ReceiveTarFile(PGconn *conn, char *archive_name, char *spclocation, bool tablespacenum, pg_compress_specification *compress) { WriteTarState state; - bbstreamer *manifest_inject_streamer; + astreamer *manifest_inject_streamer; bool is_recovery_guc_supported; bool expect_unterminated_tarfile; @@ -1636,16 +1637,16 @@ ReceiveTarFile(PGconn *conn, char *archive_name, char *spclocation, pg_fatal("out of memory"); /* Inject it into the output tarfile. */ - bbstreamer_inject_file(manifest_inject_streamer, "backup_manifest", - buf.data, buf.len); + astreamer_inject_file(manifest_inject_streamer, "backup_manifest", + buf.data, buf.len); /* Free memory. */ termPQExpBuffer(&buf); } /* Cleanup. */ - bbstreamer_finalize(state.streamer); - bbstreamer_free(state.streamer); + astreamer_finalize(state.streamer); + astreamer_free(state.streamer); progress_report(tablespacenum, true, false); @@ -1663,7 +1664,7 @@ ReceiveTarCopyChunk(size_t r, char *copybuf, void *callback_data) { WriteTarState *state = callback_data; - bbstreamer_content(state->streamer, NULL, copybuf, r, BBSTREAMER_UNKNOWN); + astreamer_content(state->streamer, NULL, copybuf, r, ASTREAMER_UNKNOWN); totaldone += r; progress_report(state->tablespacenum, false, false); @@ -1818,7 +1819,7 @@ BaseBackup(char *compression_algorithm, char *compression_detail, if (writerecoveryconf) recoveryconfcontents = GenerateRecoveryConfig(conn, replication_slot, - GetDbnameFromConnectionOptions()); + GetDbnameFromConnectionOptions(connection_string)); /* * Run IDENTIFY_SYSTEM so we can get the timeline @@ -2056,7 +2057,7 @@ BaseBackup(char *compression_algorithm, char *compression_detail, tablespacecount = PQntuples(res); for (i = 0; i < PQntuples(res); i++) { - totalsize_kb += atol(PQgetvalue(res, i, 2)); + totalsize_kb += atoll(PQgetvalue(res, i, 2)); /* * Verify tablespace directories are empty. Don't bother with the @@ -2310,7 +2311,7 @@ BaseBackup(char *compression_algorithm, char *compression_detail, } else { - (void) sync_pgdata(basedir, serverVersion, sync_method); + (void) sync_pgdata(basedir, serverVersion, sync_method, true); } } diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c index b02318782a66d..c43c0cbbba5a6 100644 --- a/src/bin/pg_basebackup/pg_createsubscriber.c +++ b/src/bin/pg_basebackup/pg_createsubscriber.c @@ -3,7 +3,7 @@ * pg_createsubscriber.c * Create a new logical replica from a standby server * - * Copyright (C) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/pg_createsubscriber.c @@ -13,14 +13,13 @@ #include "postgres_fe.h" +#include #include #include #include -#include "catalog/pg_authid_d.h" #include "common/connect.h" #include "common/controldata_utils.h" -#include "common/file_perm.h" #include "common/logging.h" #include "common/pg_prng.h" #include "common/restricted_token.h" @@ -30,6 +29,7 @@ #include "getopt_long.h" #define DEFAULT_SUB_PORT "50432" +#define OBJECTTYPE_PUBLICATIONS 0x0001 /* Command-line options */ struct CreateSubscriberOptions @@ -39,13 +39,17 @@ struct CreateSubscriberOptions char *socket_dir; /* directory for Unix-domain socket, if any */ char *sub_port; /* subscriber port number */ const char *sub_username; /* subscriber username */ + bool two_phase; /* enable-two-phase option */ SimpleStringList database_names; /* list of database names */ SimpleStringList pub_names; /* list of publication names */ SimpleStringList sub_names; /* list of subscription names */ SimpleStringList replslot_names; /* list of replication slot names */ int recovery_timeout; /* stop recovery after this time */ + bool all_dbs; /* all option */ + SimpleStringList objecttypes_to_remove; /* list of object types to remove */ }; +/* per-database publication/subscription info */ struct LogicalRepInfo { char *dbname; /* database name */ @@ -59,6 +63,18 @@ struct LogicalRepInfo bool made_publication; /* publication was created */ }; +/* + * Information shared across all the databases (or publications and + * subscriptions). + */ +struct LogicalRepInfos +{ + struct LogicalRepInfo *dbinfo; + bool two_phase; /* enable-two-phase option */ + bits32 objecttypes_to_remove; /* flags indicating which object types + * to remove on subscriber */ +}; + static void cleanup_objects_atexit(void); static void usage(); static char *get_base_conninfo(const char *conninfo, char **dbname); @@ -98,7 +114,9 @@ static void stop_standby_server(const char *datadir); static void wait_for_end_recovery(const char *conninfo, const struct CreateSubscriberOptions *opt); static void create_publication(PGconn *conn, struct LogicalRepInfo *dbinfo); -static void drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo); +static void drop_publication(PGconn *conn, const char *pubname, + const char *dbname, bool *made_publication); +static void check_and_drop_publications(PGconn *conn, struct LogicalRepInfo *dbinfo); static void create_subscription(PGconn *conn, const struct LogicalRepInfo *dbinfo); static void set_replication_progress(PGconn *conn, const struct LogicalRepInfo *dbinfo, const char *lsn); @@ -107,6 +125,8 @@ static void check_and_drop_existing_subscriptions(PGconn *conn, const struct LogicalRepInfo *dbinfo); static void drop_existing_subscriptions(PGconn *conn, const char *subname, const char *dbname); +static void get_publisher_databases(struct CreateSubscriberOptions *opt, + bool dbnamespecified); #define USEC_PER_SEC 1000000 #define WAIT_INTERVAL 1 /* 1 second */ @@ -118,7 +138,7 @@ static bool dry_run = false; static bool success = false; -static struct LogicalRepInfo *dbinfo; +static struct LogicalRepInfos dbinfos; static int num_dbs = 0; /* number of specified databases */ static int num_pubs = 0; /* number of specified publications */ static int num_subs = 0; /* number of specified subscriptions */ @@ -173,17 +193,20 @@ cleanup_objects_atexit(void) for (int i = 0; i < num_dbs; i++) { - if (dbinfo[i].made_publication || dbinfo[i].made_replslot) + struct LogicalRepInfo *dbinfo = &dbinfos.dbinfo[i]; + + if (dbinfo->made_publication || dbinfo->made_replslot) { PGconn *conn; - conn = connect_database(dbinfo[i].pubconninfo, false); + conn = connect_database(dbinfo->pubconninfo, false); if (conn != NULL) { - if (dbinfo[i].made_publication) - drop_publication(conn, &dbinfo[i]); - if (dbinfo[i].made_replslot) - drop_replication_slot(conn, &dbinfo[i], dbinfo[i].replslotname); + if (dbinfo->made_publication) + drop_publication(conn, dbinfo->pubname, dbinfo->dbname, + &dbinfo->made_publication); + if (dbinfo->made_replslot) + drop_replication_slot(conn, dbinfo, dbinfo->replslotname); disconnect_database(conn, false); } else @@ -193,16 +216,18 @@ cleanup_objects_atexit(void) * that some objects were left on primary and should be * removed before trying again. */ - if (dbinfo[i].made_publication) + if (dbinfo->made_publication) { - pg_log_warning("publication \"%s\" in database \"%s\" on primary might be left behind", - dbinfo[i].pubname, dbinfo[i].dbname); - pg_log_warning_hint("Consider dropping this publication before trying again."); + pg_log_warning("publication \"%s\" created in database \"%s\" on primary was left behind", + dbinfo->pubname, + dbinfo->dbname); + pg_log_warning_hint("Drop this publication before trying again."); } - if (dbinfo[i].made_replslot) + if (dbinfo->made_replslot) { - pg_log_warning("replication slot \"%s\" in database \"%s\" on primary might be left behind", - dbinfo[i].replslotname, dbinfo[i].dbname); + pg_log_warning("replication slot \"%s\" created in database \"%s\" on primary was left behind", + dbinfo->replslotname, + dbinfo->dbname); pg_log_warning_hint("Drop this replication slot soon to avoid retention of WAL files."); } } @@ -221,14 +246,19 @@ usage(void) printf(_("Usage:\n")); printf(_(" %s [OPTION]...\n"), progname); printf(_("\nOptions:\n")); - printf(_(" -d, --database=DBNAME database to create a subscription\n")); + printf(_(" -a, --all create subscriptions for all databases except template\n" + " databases and databases that don't allow connections\n")); + printf(_(" -d, --database=DBNAME database in which to create a subscription\n")); printf(_(" -D, --pgdata=DATADIR location for the subscriber data directory\n")); printf(_(" -n, --dry-run dry run, just show what would be done\n")); printf(_(" -p, --subscriber-port=PORT subscriber port number (default %s)\n"), DEFAULT_SUB_PORT); printf(_(" -P, --publisher-server=CONNSTR publisher connection string\n")); - printf(_(" -s, --socket-directory=DIR socket directory to use (default current directory)\n")); + printf(_(" -R, --remove=OBJECTTYPE remove all objects of the specified type from specified\n" + " databases on the subscriber; accepts: \"%s\"\n"), "publications"); + printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n")); printf(_(" -t, --recovery-timeout=SECS seconds to wait for recovery to end\n")); - printf(_(" -U, --subscriber-username=NAME subscriber username\n")); + printf(_(" -T, --enable-two-phase enable two-phase commit for all subscriptions\n")); + printf(_(" -U, --subscriber-username=NAME user name for subscriber connection\n")); printf(_(" -v, --verbose output verbose messages\n")); printf(_(" --config-file=FILENAME use specified main server configuration\n" " file when running target cluster\n")); @@ -480,9 +510,10 @@ store_pub_sub_info(const struct CreateSubscriberOptions *opt, dbinfo[i].pubname ? dbinfo[i].pubname : "(auto)", dbinfo[i].replslotname ? dbinfo[i].replslotname : "(auto)", dbinfo[i].pubconninfo); - pg_log_debug("subscriber(%d): subscription: %s ; connection string: %s", i, + pg_log_debug("subscriber(%d): subscription: %s ; connection string: %s, two_phase: %s", i, dbinfo[i].subname ? dbinfo[i].subname : "(auto)", - dbinfo[i].subconninfo); + dbinfo[i].subconninfo, + dbinfos.two_phase ? "true" : "false"); if (num_pubs > 0) pubcell = pubcell->next; @@ -523,7 +554,7 @@ connect_database(const char *conninfo, bool exit_on_error) res = PQexec(conn, ALWAYS_SECURE_SEARCH_PATH_SQL); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - pg_log_error("could not clear search_path: %s", + pg_log_error("could not clear \"search_path\": %s", PQresultErrorMessage(res)); PQclear(res); PQfinish(conn); @@ -583,8 +614,7 @@ get_primary_sysid(const char *conninfo) sysid = strtou64(PQgetvalue(res, 0, 0), NULL, 10); - pg_log_info("system identifier is %llu on publisher", - (unsigned long long) sysid); + pg_log_info("system identifier is %" PRIu64 " on publisher", sysid); PQclear(res); disconnect_database(conn, false); @@ -612,8 +642,7 @@ get_standby_sysid(const char *datadir) sysid = cf->system_identifier; - pg_log_info("system identifier is %llu on subscriber", - (unsigned long long) sysid); + pg_log_info("system identifier is %" PRIu64 " on subscriber", sysid); pg_free(cf); @@ -653,8 +682,8 @@ modify_subscriber_sysid(const struct CreateSubscriberOptions *opt) if (!dry_run) update_controlfile(subscriber_dir, cf, true); - pg_log_info("system identifier is %llu on subscriber", - (unsigned long long) cf->system_identifier); + pg_log_info("system identifier is %" PRIu64 " on subscriber", + cf->system_identifier); pg_log_info("running pg_resetwal on the subscriber"); @@ -670,7 +699,7 @@ modify_subscriber_sysid(const struct CreateSubscriberOptions *opt) if (rc == 0) pg_log_info("subscriber successfully changed the system identifier"); else - pg_fatal("subscriber failed to change system identifier: exit code: %d", rc); + pg_fatal("could not change system identifier of subscriber: %s", wait_result_to_str(rc)); } pg_free(cf); @@ -778,6 +807,28 @@ setup_publisher(struct LogicalRepInfo *dbinfo) else exit(1); + /* + * Since we are using the LSN returned by the last replication slot as + * recovery_target_lsn, this LSN is ahead of the current WAL position + * and the recovery waits until the publisher writes a WAL record to + * reach the target and ends the recovery. On idle systems, this wait + * time is unpredictable and could lead to failure in promoting the + * subscriber. To avoid that, insert a harmless WAL record. + */ + if (i == num_dbs - 1 && !dry_run) + { + PGresult *res; + + res = PQexec(conn, "SELECT pg_log_standby_snapshot()"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("could not write an additional WAL record: %s", + PQresultErrorMessage(res)); + disconnect_database(conn, true); + } + PQclear(res); + } + disconnect_database(conn, false); } @@ -828,6 +879,7 @@ check_publisher(const struct LogicalRepInfo *dbinfo) int max_walsenders; int cur_walsenders; int max_prepared_transactions; + char *max_slot_wal_keep_size; pg_log_info("checking settings on publisher"); @@ -851,6 +903,7 @@ check_publisher(const struct LogicalRepInfo *dbinfo) * - wal_level = logical * - max_replication_slots >= current + number of dbs to be converted * - max_wal_senders >= current + number of dbs to be converted + * - max_slot_wal_keep_size = -1 (to prevent deletion of required WAL files) * ----------------------------------------------------------------------- */ res = PQexec(conn, @@ -859,7 +912,8 @@ check_publisher(const struct LogicalRepInfo *dbinfo) " (SELECT count(*) FROM pg_catalog.pg_replication_slots)," " pg_catalog.current_setting('max_wal_senders')," " (SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type = 'walsender')," - " pg_catalog.current_setting('max_prepared_transactions')"); + " pg_catalog.current_setting('max_prepared_transactions')," + " pg_catalog.current_setting('max_slot_wal_keep_size')"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { @@ -874,6 +928,7 @@ check_publisher(const struct LogicalRepInfo *dbinfo) max_walsenders = atoi(PQgetvalue(res, 0, 3)); cur_walsenders = atoi(PQgetvalue(res, 0, 4)); max_prepared_transactions = atoi(PQgetvalue(res, 0, 5)); + max_slot_wal_keep_size = pg_strdup(PQgetvalue(res, 0, 6)); PQclear(res); @@ -884,12 +939,14 @@ check_publisher(const struct LogicalRepInfo *dbinfo) pg_log_debug("publisher: current wal senders: %d", cur_walsenders); pg_log_debug("publisher: max_prepared_transactions: %d", max_prepared_transactions); + pg_log_debug("publisher: max_slot_wal_keep_size: %s", + max_slot_wal_keep_size); disconnect_database(conn, false); if (strcmp(wal_level, "logical") != 0) { - pg_log_error("publisher requires wal_level >= \"logical\""); + pg_log_error("publisher requires \"wal_level\" >= \"logical\""); failed = true; } @@ -904,18 +961,31 @@ check_publisher(const struct LogicalRepInfo *dbinfo) if (max_walsenders - cur_walsenders < num_dbs) { - pg_log_error("publisher requires %d wal sender processes, but only %d remain", + pg_log_error("publisher requires %d WAL sender processes, but only %d remain", num_dbs, max_walsenders - cur_walsenders); pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_wal_senders", cur_walsenders + num_dbs); failed = true; } - if (max_prepared_transactions != 0) + if (max_prepared_transactions != 0 && !dbinfos.two_phase) { - pg_log_warning("two_phase option will not be enabled for slots"); + pg_log_warning("two_phase option will not be enabled for replication slots"); pg_log_warning_detail("Subscriptions will be created with the two_phase option disabled. " "Prepared transactions will be replicated at COMMIT PREPARED."); + pg_log_warning_hint("You can use the command-line option --enable-two-phase to enable two_phase."); + } + + /* + * Validate 'max_slot_wal_keep_size'. If this parameter is set to a + * non-default value, it may cause replication failures due to required + * WAL files being prematurely removed. + */ + if (dry_run && (strcmp(max_slot_wal_keep_size, "-1") != 0)) + { + pg_log_warning("required WAL could be removed from the publisher"); + pg_log_warning_hint("Set the configuration parameter \"%s\" to -1 to ensure that required WAL files are not prematurely removed.", + "max_slot_wal_keep_size"); } pg_free(wal_level); @@ -943,7 +1013,7 @@ check_subscriber(const struct LogicalRepInfo *dbinfo) bool failed = false; int max_lrworkers; - int max_repslots; + int max_reporigins; int max_wprocs; pg_log_info("checking settings on subscriber"); @@ -962,7 +1032,7 @@ check_subscriber(const struct LogicalRepInfo *dbinfo) * Since these parameters are not a requirement for physical replication, * we should check it to make sure it won't fail. * - * - max_replication_slots >= number of dbs to be converted + * - max_active_replication_origins >= number of dbs to be converted * - max_logical_replication_workers >= number of dbs to be converted * - max_worker_processes >= 1 + number of dbs to be converted *------------------------------------------------------------------------ @@ -970,7 +1040,7 @@ check_subscriber(const struct LogicalRepInfo *dbinfo) res = PQexec(conn, "SELECT setting FROM pg_catalog.pg_settings WHERE name IN (" "'max_logical_replication_workers', " - "'max_replication_slots', " + "'max_active_replication_origins', " "'max_worker_processes', " "'primary_slot_name') " "ORDER BY name"); @@ -982,15 +1052,15 @@ check_subscriber(const struct LogicalRepInfo *dbinfo) disconnect_database(conn, true); } - max_lrworkers = atoi(PQgetvalue(res, 0, 0)); - max_repslots = atoi(PQgetvalue(res, 1, 0)); + max_reporigins = atoi(PQgetvalue(res, 0, 0)); + max_lrworkers = atoi(PQgetvalue(res, 1, 0)); max_wprocs = atoi(PQgetvalue(res, 2, 0)); if (strcmp(PQgetvalue(res, 3, 0), "") != 0) primary_slot_name = pg_strdup(PQgetvalue(res, 3, 0)); pg_log_debug("subscriber: max_logical_replication_workers: %d", max_lrworkers); - pg_log_debug("subscriber: max_replication_slots: %d", max_repslots); + pg_log_debug("subscriber: max_active_replication_origins: %d", max_reporigins); pg_log_debug("subscriber: max_worker_processes: %d", max_wprocs); if (primary_slot_name) pg_log_debug("subscriber: primary_slot_name: %s", primary_slot_name); @@ -999,12 +1069,12 @@ check_subscriber(const struct LogicalRepInfo *dbinfo) disconnect_database(conn, false); - if (max_repslots < num_dbs) + if (max_reporigins < num_dbs) { - pg_log_error("subscriber requires %d replication slots, but only %d remain", - num_dbs, max_repslots); + pg_log_error("subscriber requires %d active replication origins, but only %d remain", + num_dbs, max_reporigins); pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", - "max_replication_slots", num_dbs); + "max_active_replication_origins", num_dbs); failed = true; } @@ -1063,7 +1133,7 @@ drop_existing_subscriptions(PGconn *conn, const char *subname, const char *dbnam if (PQresultStatus(res) != PGRES_COMMAND_OK) { - pg_log_error("could not drop a subscription \"%s\" settings: %s", + pg_log_error("could not drop subscription \"%s\": %s", subname, PQresultErrorMessage(res)); disconnect_database(conn, true); } @@ -1109,6 +1179,7 @@ check_and_drop_existing_subscriptions(PGconn *conn, PQclear(res); destroyPQExpBuffer(query); + PQfreemem(dbname); } /* @@ -1134,12 +1205,8 @@ setup_subscriber(struct LogicalRepInfo *dbinfo, const char *consistent_lsn) */ check_and_drop_existing_subscriptions(conn, &dbinfo[i]); - /* - * Since the publication was created before the consistent LSN, it is - * available on the subscriber when the physical replica is promoted. - * Remove publications from the subscriber because it has no use. - */ - drop_publication(conn, &dbinfo[i]); + /* Check and drop the required publications in the given database. */ + check_and_drop_publications(conn, &dbinfo[i]); create_subscription(conn, &dbinfo[i]); @@ -1180,20 +1247,20 @@ setup_recovery(const struct LogicalRepInfo *dbinfo, const char *datadir, const c * targets (name, time, xid, LSN). */ recoveryconfcontents = GenerateRecoveryConfig(conn, NULL, NULL); - appendPQExpBuffer(recoveryconfcontents, "recovery_target = ''\n"); - appendPQExpBuffer(recoveryconfcontents, - "recovery_target_timeline = 'latest'\n"); - appendPQExpBuffer(recoveryconfcontents, - "recovery_target_inclusive = true\n"); - appendPQExpBuffer(recoveryconfcontents, - "recovery_target_action = promote\n"); - appendPQExpBuffer(recoveryconfcontents, "recovery_target_name = ''\n"); - appendPQExpBuffer(recoveryconfcontents, "recovery_target_time = ''\n"); - appendPQExpBuffer(recoveryconfcontents, "recovery_target_xid = ''\n"); + appendPQExpBufferStr(recoveryconfcontents, "recovery_target = ''\n"); + appendPQExpBufferStr(recoveryconfcontents, + "recovery_target_timeline = 'latest'\n"); + appendPQExpBufferStr(recoveryconfcontents, + "recovery_target_inclusive = true\n"); + appendPQExpBufferStr(recoveryconfcontents, + "recovery_target_action = promote\n"); + appendPQExpBufferStr(recoveryconfcontents, "recovery_target_name = ''\n"); + appendPQExpBufferStr(recoveryconfcontents, "recovery_target_time = ''\n"); + appendPQExpBufferStr(recoveryconfcontents, "recovery_target_xid = ''\n"); if (dry_run) { - appendPQExpBuffer(recoveryconfcontents, "# dry run mode"); + appendPQExpBufferStr(recoveryconfcontents, "# dry run mode"); appendPQExpBuffer(recoveryconfcontents, "recovery_target_lsn = '%X/%X'\n", LSN_FORMAT_ARGS((XLogRecPtr) InvalidXLogRecPtr)); @@ -1305,10 +1372,11 @@ create_logical_replication_slot(PGconn *conn, struct LogicalRepInfo *dbinfo) slot_name_esc = PQescapeLiteral(conn, slot_name, strlen(slot_name)); appendPQExpBuffer(str, - "SELECT lsn FROM pg_catalog.pg_create_logical_replication_slot(%s, 'pgoutput', false, false, false)", - slot_name_esc); + "SELECT lsn FROM pg_catalog.pg_create_logical_replication_slot(%s, 'pgoutput', false, %s, false)", + slot_name_esc, + dbinfos.two_phase ? "true" : "false"); - pg_free(slot_name_esc); + PQfreemem(slot_name_esc); pg_log_debug("command is: %s", str->data); @@ -1354,7 +1422,7 @@ drop_replication_slot(PGconn *conn, struct LogicalRepInfo *dbinfo, appendPQExpBuffer(str, "SELECT pg_catalog.pg_drop_replication_slot(%s)", slot_name_esc); - pg_free(slot_name_esc); + PQfreemem(slot_name_esc); pg_log_debug("command is: %s", str->data); @@ -1416,7 +1484,11 @@ start_standby_server(const struct CreateSubscriberOptions *opt, bool restricted_ appendPQExpBuffer(pg_ctl_cmd, "\"%s\" start -D ", pg_ctl_path); appendShellString(pg_ctl_cmd, subscriber_dir); - appendPQExpBuffer(pg_ctl_cmd, " -s -o \"-c sync_replication_slots=off\""); + appendPQExpBufferStr(pg_ctl_cmd, " -s -o \"-c sync_replication_slots=off\""); + + /* Prevent unintended slot invalidation */ + appendPQExpBufferStr(pg_ctl_cmd, " -o \"-c idle_replication_slot_timeout=0\""); + if (restricted_access) { appendPQExpBuffer(pg_ctl_cmd, " -o \"-p %s\"", opt->sub_port); @@ -1441,7 +1513,7 @@ start_standby_server(const struct CreateSubscriberOptions *opt, bool restricted_ /* Suppress to start logical replication if requested */ if (restrict_logical_worker) - appendPQExpBuffer(pg_ctl_cmd, " -o \"-c max_logical_replication_workers=0\""); + appendPQExpBufferStr(pg_ctl_cmd, " -o \"-c max_logical_replication_workers=0\""); pg_log_debug("pg_ctl command is: %s", pg_ctl_cmd->data); rc = system(pg_ctl_cmd->data); @@ -1593,16 +1665,17 @@ create_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) /* For cleanup purposes */ dbinfo->made_publication = true; - pg_free(ipubname_esc); - pg_free(spubname_esc); + PQfreemem(ipubname_esc); + PQfreemem(spubname_esc); destroyPQExpBuffer(str); } /* - * Remove publication if it couldn't finish all steps. + * Drop the specified publication in the given database. */ static void -drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) +drop_publication(PGconn *conn, const char *pubname, const char *dbname, + bool *made_publication) { PQExpBuffer str = createPQExpBuffer(); PGresult *res; @@ -1610,14 +1683,14 @@ drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) Assert(conn != NULL); - pubname_esc = PQescapeIdentifier(conn, dbinfo->pubname, strlen(dbinfo->pubname)); + pubname_esc = PQescapeIdentifier(conn, pubname, strlen(pubname)); pg_log_info("dropping publication \"%s\" in database \"%s\"", - dbinfo->pubname, dbinfo->dbname); + pubname, dbname); appendPQExpBuffer(str, "DROP PUBLICATION %s", pubname_esc); - pg_free(pubname_esc); + PQfreemem(pubname_esc); pg_log_debug("command is: %s", str->data); @@ -1627,8 +1700,8 @@ drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) if (PQresultStatus(res) != PGRES_COMMAND_OK) { pg_log_error("could not drop publication \"%s\" in database \"%s\": %s", - dbinfo->pubname, dbinfo->dbname, PQresultErrorMessage(res)); - dbinfo->made_publication = false; /* don't try again. */ + pubname, dbname, PQresultErrorMessage(res)); + *made_publication = false; /* don't try again. */ /* * Don't disconnect and exit here. This routine is used by primary @@ -1644,6 +1717,55 @@ drop_publication(PGconn *conn, struct LogicalRepInfo *dbinfo) destroyPQExpBuffer(str); } +/* + * Retrieve and drop the publications. + * + * Since the publications were created before the consistent LSN, they + * remain on the subscriber even after the physical replica is + * promoted. Remove these publications from the subscriber because + * they have no use. Additionally, if requested, drop all pre-existing + * publications. + */ +static void +check_and_drop_publications(PGconn *conn, struct LogicalRepInfo *dbinfo) +{ + PGresult *res; + bool drop_all_pubs = dbinfos.objecttypes_to_remove & OBJECTTYPE_PUBLICATIONS; + + Assert(conn != NULL); + + if (drop_all_pubs) + { + pg_log_info("dropping all existing publications in database \"%s\"", + dbinfo->dbname); + + /* Fetch all publication names */ + res = PQexec(conn, "SELECT pubname FROM pg_catalog.pg_publication;"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("could not obtain publication information: %s", + PQresultErrorMessage(res)); + PQclear(res); + disconnect_database(conn, true); + } + + /* Drop each publication */ + for (int i = 0; i < PQntuples(res); i++) + drop_publication(conn, PQgetvalue(res, i, 0), dbinfo->dbname, + &dbinfo->made_publication); + + PQclear(res); + } + + /* + * In dry-run mode, we don't create publications, but we still try to drop + * those to provide necessary information to the user. + */ + if (!drop_all_pubs || dry_run) + drop_publication(conn, dbinfo->pubname, dbinfo->dbname, + &dbinfo->made_publication); +} + /* * Create a subscription with some predefined options. * @@ -1678,13 +1800,14 @@ create_subscription(PGconn *conn, const struct LogicalRepInfo *dbinfo) appendPQExpBuffer(str, "CREATE SUBSCRIPTION %s CONNECTION %s PUBLICATION %s " "WITH (create_slot = false, enabled = false, " - "slot_name = %s, copy_data = false)", - subname_esc, pubconninfo_esc, pubname_esc, replslotname_esc); + "slot_name = %s, copy_data = false, two_phase = %s)", + subname_esc, pubconninfo_esc, pubname_esc, replslotname_esc, + dbinfos.two_phase ? "true" : "false"); - pg_free(pubname_esc); - pg_free(subname_esc); - pg_free(pubconninfo_esc); - pg_free(replslotname_esc); + PQfreemem(pubname_esc); + PQfreemem(subname_esc); + PQfreemem(pubconninfo_esc); + PQfreemem(replslotname_esc); pg_log_debug("command is: %s", str->data); @@ -1769,7 +1892,7 @@ set_replication_progress(PGconn *conn, const struct LogicalRepInfo *dbinfo, cons */ originname = psprintf("pg_%u", suboid); - pg_log_info("setting the replication progress (node name \"%s\" ; LSN %s) in database \"%s\"", + pg_log_info("setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"", originname, lsnstr, dbinfo->dbname); resetPQExpBuffer(str); @@ -1784,15 +1907,15 @@ set_replication_progress(PGconn *conn, const struct LogicalRepInfo *dbinfo, cons res = PQexec(conn, str->data); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - pg_log_error("could not set replication progress for the subscription \"%s\": %s", + pg_log_error("could not set replication progress for subscription \"%s\": %s", dbinfo->subname, PQresultErrorMessage(res)); disconnect_database(conn, true); } PQclear(res); } - pg_free(subname); - pg_free(dbname); + PQfreemem(subname); + PQfreemem(dbname); pg_free(originname); pg_free(lsnstr); destroyPQExpBuffer(str); @@ -1835,22 +1958,78 @@ enable_subscription(PGconn *conn, const struct LogicalRepInfo *dbinfo) PQclear(res); } - pg_free(subname); + PQfreemem(subname); destroyPQExpBuffer(str); } +/* + * Fetch a list of all connectable non-template databases from the source server + * and form a list such that they appear as if the user has specified multiple + * --database options, one for each source database. + */ +static void +get_publisher_databases(struct CreateSubscriberOptions *opt, + bool dbnamespecified) +{ + PGconn *conn; + PGresult *res; + + /* If a database name was specified, just connect to it. */ + if (dbnamespecified) + conn = connect_database(opt->pub_conninfo_str, true); + else + { + /* Otherwise, try postgres first and then template1. */ + char *conninfo; + + conninfo = concat_conninfo_dbname(opt->pub_conninfo_str, "postgres"); + conn = connect_database(conninfo, false); + pg_free(conninfo); + if (!conn) + { + conninfo = concat_conninfo_dbname(opt->pub_conninfo_str, "template1"); + conn = connect_database(conninfo, true); + pg_free(conninfo); + } + } + + res = PQexec(conn, "SELECT datname FROM pg_database WHERE datistemplate = false AND datallowconn AND datconnlimit <> -2 ORDER BY 1"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("could not obtain a list of databases: %s", PQresultErrorMessage(res)); + PQclear(res); + disconnect_database(conn, true); + } + + for (int i = 0; i < PQntuples(res); i++) + { + const char *dbname = PQgetvalue(res, i, 0); + + simple_string_list_append(&opt->database_names, dbname); + + /* Increment num_dbs to reflect multiple --database options */ + num_dbs++; + } + + PQclear(res); + disconnect_database(conn, false); +} + int main(int argc, char **argv) { static struct option long_options[] = { + {"all", no_argument, NULL, 'a'}, {"database", required_argument, NULL, 'd'}, {"pgdata", required_argument, NULL, 'D'}, {"dry-run", no_argument, NULL, 'n'}, {"subscriber-port", required_argument, NULL, 'p'}, {"publisher-server", required_argument, NULL, 'P'}, - {"socket-directory", required_argument, NULL, 's'}, + {"remove", required_argument, NULL, 'R'}, + {"socketdir", required_argument, NULL, 's'}, {"recovery-timeout", required_argument, NULL, 't'}, + {"enable-two-phase", no_argument, NULL, 'T'}, {"subscriber-username", required_argument, NULL, 'U'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, @@ -1882,7 +2061,7 @@ main(int argc, char **argv) pg_logging_init(argv[0]); pg_logging_set_level(PG_LOG_WARNING); progname = get_progname(argv[0]); - set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_createsubscriber")); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup")); if (argc > 1) { @@ -1906,11 +2085,13 @@ main(int argc, char **argv) opt.socket_dir = NULL; opt.sub_port = DEFAULT_SUB_PORT; opt.sub_username = NULL; + opt.two_phase = false; opt.database_names = (SimpleStringList) { 0 }; opt.recovery_timeout = 0; + opt.all_dbs = false; /* * Don't allow it to be run as root. It uses pg_ctl which does not allow @@ -1928,11 +2109,14 @@ main(int argc, char **argv) get_restricted_token(); - while ((c = getopt_long(argc, argv, "d:D:np:P:s:t:U:v", + while ((c = getopt_long(argc, argv, "ad:D:np:P:R:s:t:TU:v", long_options, &option_index)) != -1) { switch (c) { + case 'a': + opt.all_dbs = true; + break; case 'd': if (!simple_string_list_member(&opt.database_names, optarg)) { @@ -1940,10 +2124,7 @@ main(int argc, char **argv) num_dbs++; } else - { - pg_log_error("duplicate database \"%s\"", optarg); - exit(1); - } + pg_fatal("database \"%s\" specified more than once for -d/--database", optarg); break; case 'D': subscriber_dir = pg_strdup(optarg); @@ -1958,6 +2139,12 @@ main(int argc, char **argv) case 'P': opt.pub_conninfo_str = pg_strdup(optarg); break; + case 'R': + if (!simple_string_list_member(&opt.objecttypes_to_remove, optarg)) + simple_string_list_append(&opt.objecttypes_to_remove, optarg); + else + pg_fatal("object type \"%s\" specified more than once for -R/--remove", optarg); + break; case 's': opt.socket_dir = pg_strdup(optarg); canonicalize_path(opt.socket_dir); @@ -1965,6 +2152,9 @@ main(int argc, char **argv) case 't': opt.recovery_timeout = atoi(optarg); break; + case 'T': + opt.two_phase = true; + break; case 'U': opt.sub_username = pg_strdup(optarg); break; @@ -1981,10 +2171,7 @@ main(int argc, char **argv) num_pubs++; } else - { - pg_log_error("duplicate publication \"%s\"", optarg); - exit(1); - } + pg_fatal("publication \"%s\" specified more than once for --publication", optarg); break; case 3: if (!simple_string_list_member(&opt.replslot_names, optarg)) @@ -1993,10 +2180,7 @@ main(int argc, char **argv) num_replslots++; } else - { - pg_log_error("duplicate replication slot \"%s\"", optarg); - exit(1); - } + pg_fatal("replication slot \"%s\" specified more than once for --replication-slot", optarg); break; case 4: if (!simple_string_list_member(&opt.sub_names, optarg)) @@ -2005,10 +2189,7 @@ main(int argc, char **argv) num_subs++; } else - { - pg_log_error("duplicate subscription \"%s\"", optarg); - exit(1); - } + pg_fatal("subscription \"%s\" specified more than once for --subscription", optarg); break; default: /* getopt_long already emitted a complaint */ @@ -2017,6 +2198,28 @@ main(int argc, char **argv) } } + /* Validate that --all is not used with incompatible options */ + if (opt.all_dbs) + { + char *bad_switch = NULL; + + if (num_dbs > 0) + bad_switch = "--database"; + else if (num_pubs > 0) + bad_switch = "--publication"; + else if (num_replslots > 0) + bad_switch = "--replication-slot"; + else if (num_subs > 0) + bad_switch = "--subscription"; + + if (bad_switch) + { + pg_log_error("options %s and -a/--all cannot be used together", bad_switch); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } + } + /* Any non-option arguments? */ if (optind < argc) { @@ -2061,30 +2264,41 @@ main(int argc, char **argv) pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1); } - pg_log_info("validating connection string on publisher"); + pg_log_info("validating publisher connection string"); pub_base_conninfo = get_base_conninfo(opt.pub_conninfo_str, &dbname_conninfo); if (pub_base_conninfo == NULL) exit(1); - pg_log_info("validating connection string on subscriber"); + pg_log_info("validating subscriber connection string"); sub_base_conninfo = get_sub_conninfo(&opt); + /* + * Fetch all databases from the source (publisher) and treat them as if + * the user specified has multiple --database options, one for each source + * database. + */ + if (opt.all_dbs) + { + bool dbnamespecified = (dbname_conninfo != NULL); + + get_publisher_databases(&opt, dbnamespecified); + } + if (opt.database_names.head == NULL) { pg_log_info("no database was specified"); /* - * If --database option is not provided, try to obtain the dbname from - * the publisher conninfo. If dbname parameter is not available, error - * out. + * Try to obtain the dbname from the publisher conninfo. If dbname + * parameter is not available, error out. */ if (dbname_conninfo) { simple_string_list_append(&opt.database_names, dbname_conninfo); num_dbs++; - pg_log_info("database \"%s\" was extracted from the publisher connection string", + pg_log_info("database name \"%s\" was extracted from the publisher connection string", dbname_conninfo); } else @@ -2099,26 +2313,39 @@ main(int argc, char **argv) /* Number of object names must match number of databases */ if (num_pubs > 0 && num_pubs != num_dbs) { - pg_log_error("wrong number of publication names"); - pg_log_error_hint("Number of publication names (%d) must match number of database names (%d).", - num_pubs, num_dbs); + pg_log_error("wrong number of publication names specified"); + pg_log_error_detail("The number of specified publication names (%d) must match the number of specified database names (%d).", + num_pubs, num_dbs); exit(1); } if (num_subs > 0 && num_subs != num_dbs) { - pg_log_error("wrong number of subscription names"); - pg_log_error_hint("Number of subscription names (%d) must match number of database names (%d).", - num_subs, num_dbs); + pg_log_error("wrong number of subscription names specified"); + pg_log_error_detail("The number of specified subscription names (%d) must match the number of specified database names (%d).", + num_subs, num_dbs); exit(1); } if (num_replslots > 0 && num_replslots != num_dbs) { - pg_log_error("wrong number of replication slot names"); - pg_log_error_hint("Number of replication slot names (%d) must match number of database names (%d).", - num_replslots, num_dbs); + pg_log_error("wrong number of replication slot names specified"); + pg_log_error_detail("The number of specified replication slot names (%d) must match the number of specified database names (%d).", + num_replslots, num_dbs); exit(1); } + /* Verify the object types specified for removal from the subscriber */ + for (SimpleStringListCell *cell = opt.objecttypes_to_remove.head; cell; cell = cell->next) + { + if (pg_strcasecmp(cell->val, "publications") == 0) + dbinfos.objecttypes_to_remove |= OBJECTTYPE_PUBLICATIONS; + else + { + pg_log_error("invalid object type \"%s\" specified for -R/--remove", cell->val); + pg_log_error_hint("The valid value is: \"%s\"", "publications"); + exit(1); + } + } + /* Get the absolute path of pg_ctl and pg_resetwal on the subscriber */ pg_ctl_path = get_exec_path(argv[0], "pg_ctl"); pg_resetwal_path = get_exec_path(argv[0], "pg_resetwal"); @@ -2126,12 +2353,14 @@ main(int argc, char **argv) /* Rudimentary check for a data directory */ check_data_directory(subscriber_dir); + dbinfos.two_phase = opt.two_phase; + /* * Store database information for publisher and subscriber. It should be * called before atexit() because its return is used in the * cleanup_objects_atexit(). */ - dbinfo = store_pub_sub_info(&opt, pub_base_conninfo, sub_base_conninfo); + dbinfos.dbinfo = store_pub_sub_info(&opt, pub_base_conninfo, sub_base_conninfo); /* Register a function to clean up objects in case of failure */ atexit(cleanup_objects_atexit); @@ -2140,7 +2369,7 @@ main(int argc, char **argv) * Check if the subscriber data directory has the same system identifier * than the publisher data directory. */ - pub_sysid = get_primary_sysid(dbinfo[0].pubconninfo); + pub_sysid = get_primary_sysid(dbinfos.dbinfo[0].pubconninfo); sub_sysid = get_standby_sysid(subscriber_dir); if (pub_sysid != sub_sysid) pg_fatal("subscriber data directory is not a copy of the source database cluster"); @@ -2156,8 +2385,8 @@ main(int argc, char **argv) */ if (stat(pidfile, &statbuf) == 0) { - pg_log_error("standby is up and running"); - pg_log_error_hint("Stop the standby and try again."); + pg_log_error("standby server is running"); + pg_log_error_hint("Stop the standby server and try again."); exit(1); } @@ -2166,14 +2395,14 @@ main(int argc, char **argv) * by command-line options). The goal is to avoid connections during the * transformation steps. */ - pg_log_info("starting the standby with command-line options"); + pg_log_info("starting the standby server with command-line options"); start_standby_server(&opt, true, false); /* Check if the standby server is ready for logical replication */ - check_subscriber(dbinfo); + check_subscriber(dbinfos.dbinfo); /* Check if the primary server is ready for logical replication */ - check_publisher(dbinfo); + check_publisher(dbinfos.dbinfo); /* * Stop the target server. The recovery process requires that the server @@ -2185,16 +2414,11 @@ main(int argc, char **argv) pg_log_info("stopping the subscriber"); stop_standby_server(subscriber_dir); - /* - * Create the required objects for each database on publisher. This step - * is here mainly because if we stop the standby we cannot verify if the - * primary slot is in use. We could use an extra connection for it but it - * doesn't seem worth. - */ - consistent_lsn = setup_publisher(dbinfo); + /* Create the required objects for each database on publisher */ + consistent_lsn = setup_publisher(dbinfos.dbinfo); /* Write the required recovery parameters */ - setup_recovery(dbinfo, subscriber_dir, consistent_lsn); + setup_recovery(dbinfos.dbinfo, subscriber_dir, consistent_lsn); /* * Start subscriber so the recovery parameters will take effect. Wait @@ -2205,7 +2429,7 @@ main(int argc, char **argv) start_standby_server(&opt, true, true); /* Waiting the subscriber to be promoted */ - wait_for_end_recovery(dbinfo[0].subconninfo, &opt); + wait_for_end_recovery(dbinfos.dbinfo[0].subconninfo, &opt); /* * Create the subscription for each database on subscriber. It does not @@ -2213,13 +2437,13 @@ main(int argc, char **argv) * point to the LSN reported by setup_publisher(). It also cleans up * publications created by this tool and replication to the standby. */ - setup_subscriber(dbinfo, consistent_lsn); + setup_subscriber(dbinfos.dbinfo, consistent_lsn); /* Remove primary_slot_name if it exists on primary */ - drop_primary_replication_slot(dbinfo, primary_slot_name); + drop_primary_replication_slot(dbinfos.dbinfo, primary_slot_name); /* Remove failover replication slots if they exist on subscriber */ - drop_failover_replication_slots(dbinfo); + drop_failover_replication_slots(dbinfos.dbinfo); /* Stop the subscriber */ pg_log_info("stopping the subscriber"); diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c index 555f0175f0e82..e816cf58101fb 100644 --- a/src/bin/pg_basebackup/pg_receivewal.c +++ b/src/bin/pg_basebackup/pg_receivewal.c @@ -5,7 +5,7 @@ * * Author: Magnus Hagander * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/pg_receivewal.c @@ -342,7 +342,7 @@ FindStreamingStart(uint32 *tli) if (lseek(fd, (off_t) (-4), SEEK_END) < 0) pg_fatal("could not seek in compressed file \"%s\": %m", fullpath); - r = read(fd, (char *) buf, sizeof(buf)); + r = read(fd, buf, sizeof(buf)); if (r != sizeof(buf)) { if (r < 0) @@ -889,7 +889,7 @@ main(int argc, char **argv) pg_log_info("creating replication slot \"%s\"", replication_slot); if (!CreateReplicationSlot(conn, replication_slot, NULL, false, true, false, - slot_exists_ok, false)) + slot_exists_ok, false, false)) exit(1); exit(0); } diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c index 3db520ed38b65..4b4b545917d7d 100644 --- a/src/bin/pg_basebackup/pg_recvlogical.c +++ b/src/bin/pg_basebackup/pg_recvlogical.c @@ -3,7 +3,7 @@ * pg_recvlogical.c - receive data from a logical decoding slot in a streaming * fashion and write it to a local file. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/pg_recvlogical.c @@ -18,8 +18,6 @@ #include #include -#include "access/xlog_internal.h" -#include "common/fe_memutils.h" #include "common/file_perm.h" #include "common/logging.h" #include "fe_utils/option_utils.h" @@ -44,6 +42,7 @@ typedef enum static char *outfile = NULL; static int verbose = 0; static bool two_phase = false; +static bool failover = false; static int noloop = 0; static int standby_message_timeout = 10 * 1000; /* 10 sec = default */ static int fsync_interval = 10 * 1000; /* 10 sec = default */ @@ -91,6 +90,8 @@ usage(void) printf(_(" --start start streaming in a replication slot (for the slot's name see --slot)\n")); printf(_("\nOptions:\n")); printf(_(" -E, --endpos=LSN exit after receiving the specified LSN\n")); + printf(_(" --failover enable replication slot synchronization to standby servers when\n" + " creating a replication slot\n")); printf(_(" -f, --file=FILE receive log into this file, - for stdout\n")); printf(_(" -F --fsync-interval=SECS\n" " time between fsyncs to the output file (default: %d)\n"), (fsync_interval / 1000)); @@ -635,6 +636,7 @@ StreamLogicalLog(void) { pg_log_error("unexpected termination of replication stream: %s", PQresultErrorMessage(res)); + PQclear(res); goto error; } PQclear(res); @@ -696,6 +698,7 @@ main(int argc, char **argv) {"file", required_argument, NULL, 'f'}, {"fsync-interval", required_argument, NULL, 'F'}, {"no-loop", no_argument, NULL, 'n'}, + {"failover", no_argument, NULL, 5}, {"verbose", no_argument, NULL, 'v'}, {"two-phase", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'V'}, @@ -771,6 +774,9 @@ main(int argc, char **argv) case 'v': verbose++; break; + case 5: + failover = true; + break; /* connection options */ case 'd': dbname = pg_strdup(optarg); @@ -918,11 +924,21 @@ main(int argc, char **argv) exit(1); } - if (two_phase && !do_create_slot) + if (!do_create_slot) { - pg_log_error("--two-phase may only be specified with --create-slot"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit(1); + if (two_phase) + { + pg_log_error("--two-phase may only be specified with --create-slot"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } + + if (failover) + { + pg_log_error("--failover may only be specified with --create-slot"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } } /* @@ -946,13 +962,16 @@ main(int argc, char **argv) #endif /* - * Run IDENTIFY_SYSTEM to make sure we connected using a database specific - * replication connection. + * Run IDENTIFY_SYSTEM to check the connection type for each action. + * --create-slot and --start actions require a database-specific + * replication connection because they handle logical replication slots. + * --drop-slot can remove replication slots from any replication + * connection without this restriction. */ if (!RunIdentifySystem(conn, NULL, NULL, NULL, &db_name)) exit(1); - if (db_name == NULL) + if (!do_drop_slot && db_name == NULL) pg_fatal("could not establish database-specific replication connection"); /* @@ -982,7 +1001,8 @@ main(int argc, char **argv) pg_log_info("creating replication slot \"%s\"", replication_slot); if (!CreateReplicationSlot(conn, replication_slot, plugin, false, - false, false, slot_exists_ok, two_phase)) + false, false, slot_exists_ok, two_phase, + failover)) exit(1); startpos = InvalidXLogRecPtr; } diff --git a/src/bin/pg_basebackup/po/de.po b/src/bin/pg_basebackup/po/de.po index f501eaddef02b..0afd145285c35 100644 --- a/src/bin/pg_basebackup/po/de.po +++ b/src/bin/pg_basebackup/po/de.po @@ -1,15 +1,15 @@ # German message translation file for pg_basebackup -# Copyright (C) 2011 - 2024 PostgreSQL Global Development Group +# Copyright (C) 2011 - 2025 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 16:50+0000\n" -"PO-Revision-Date: 2024-06-22 10:55+0200\n" +"POT-Creation-Date: 2025-04-14 00:20+0000\n" +"PO-Revision-Date: 2025-04-14 09:52+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -18,30 +18,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " #: ../../common/compression.c:132 ../../common/compression.c:141 -#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 -#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 -#: bbstreamer_zstd.c:284 +#: ../../common/compression.c:150 ../../fe_utils/astreamer_gzip.c:140 +#: ../../fe_utils/astreamer_gzip.c:273 ../../fe_utils/astreamer_lz4.c:102 +#: ../../fe_utils/astreamer_lz4.c:300 ../../fe_utils/astreamer_zstd.c:133 +#: ../../fe_utils/astreamer_zstd.c:288 #, c-format msgid "this build does not support compression with %s" msgstr "diese Installation unterstützt keine Komprimierung mit %s" @@ -95,7 +96,7 @@ msgstr "Komprimierungsalgorithmus »%s« unterstützt keinen Long-Distance-Modus msgid "could not open file \"%s\" for reading: %m" msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m" -#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1874 #: pg_receivewal.c:402 #, c-format msgid "could not read file \"%s\": %m" @@ -107,7 +108,7 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#: ../../fe_utils/astreamer_file.c:141 pg_recvlogical.c:652 #, c-format msgid "could not close file \"%s\": %m" msgstr "konnte Datei »%s« nicht schließen: %m" @@ -130,10 +131,10 @@ msgstr "" "diesem Fall wären die Ergebnisse unten falsch und die PostgreSQL-Installation\n" "wäre inkompatibel mit diesem Datenverzeichnis." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: pg_basebackup.c:1846 pg_receivewal.c:386 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: pg_basebackup.c:1847 pg_receivewal.c:386 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" @@ -143,8 +144,8 @@ msgstr "konnte Datei »%s« nicht öffnen: %m" msgid "could not write file \"%s\": %m" msgstr "konnte Datei »%s« nicht schreiben: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 pg_recvlogical.c:205 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" @@ -160,36 +161,36 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: pg_receivewal.c:319 pg_recvlogical.c:352 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: pg_receivewal.c:319 pg_recvlogical.c:353 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 +#: ../../common/file_utils.c:520 pg_basebackup.c:2345 walmethods.c:462 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -224,191 +225,200 @@ msgstr "konnte Prozess nicht mit beschränktem Token neu starten: Fehlercode %lu msgid "could not get exit code from subprocess: error code %lu" msgstr "konnte Statuscode des Subprozesses nicht ermitteln: Fehlercode %lu" -#: ../../fe_utils/option_utils.c:69 -#, c-format -msgid "invalid value \"%s\" for option %s" -msgstr "ungültiger Wert »%s« für Option %s" - -#: ../../fe_utils/option_utils.c:76 -#, c-format -msgid "%s must be in range %d..%d" -msgstr "%s muss im Bereich %d..%d sein" - -#: ../../fe_utils/option_utils.c:106 -#, c-format -msgid "unrecognized sync method: %s" -msgstr "unbekannte Sync-Methode: %s" - -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 -#, c-format -msgid "out of memory" -msgstr "Speicher aufgebraucht" - -#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 -#, c-format -msgid "could not write to file \"%s\": %m" -msgstr "konnte nicht in Datei »%s« schreiben: %m" - -#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 -#: pg_basebackup.c:1497 pg_basebackup.c:1706 +#: ../../fe_utils/astreamer_file.c:96 ../../fe_utils/astreamer_file.c:364 +#: ../../fe_utils/recovery_gen.c:153 pg_basebackup.c:1498 pg_basebackup.c:1707 #, c-format msgid "could not create file \"%s\": %m" msgstr "konnte Datei »%s« nicht erstellen: %m" -#: ../../fe_utils/string_utils.c:434 -#, c-format -msgid "shell command argument contains a newline or carriage return: \"%s\"\n" -msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" - -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/astreamer_file.c:124 ../../fe_utils/astreamer_file.c:261 +#: ../../fe_utils/recovery_gen.c:144 pg_basebackup.c:1434 pg_basebackup.c:1728 #, c-format -msgid "database name contains a newline or carriage return: \"%s\"\n" -msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" +msgid "could not write to file \"%s\": %m" +msgstr "konnte nicht in Datei »%s« schreiben: %m" -#: bbstreamer_file.c:275 +#: ../../fe_utils/astreamer_file.c:278 #, c-format msgid "unexpected state while extracting archive" msgstr "unerwarteter Zustand beim Extrahieren des Archivs" -#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 -#: pg_basebackup.c:757 +#: ../../fe_utils/astreamer_file.c:324 pg_basebackup.c:699 pg_basebackup.c:713 +#: pg_basebackup.c:758 #, c-format msgid "could not create directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" -#: bbstreamer_file.c:326 +#: ../../fe_utils/astreamer_file.c:329 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "konnte Zugriffsrechte für Verzeichnis »%s« nicht setzen: %m" -#: bbstreamer_file.c:345 +#: ../../fe_utils/astreamer_file.c:348 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "konnte symbolische Verknüpfung von »%s« nach »%s« nicht erzeugen: %m" -#: bbstreamer_file.c:365 +#: ../../fe_utils/astreamer_file.c:368 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "konnte Zugriffsrechte von Datei »%s« nicht setzen: %m" -#: bbstreamer_gzip.c:95 +#: ../../fe_utils/astreamer_gzip.c:115 #, c-format msgid "could not create compressed file \"%s\": %m" msgstr "konnte komprimierte Datei »%s« nicht erzeugen: %m" -#: bbstreamer_gzip.c:103 +#: ../../fe_utils/astreamer_gzip.c:127 #, c-format msgid "could not duplicate stdout: %m" msgstr "konnte Standardausgabe nicht duplizieren: %m" -#: bbstreamer_gzip.c:107 +#: ../../fe_utils/astreamer_gzip.c:131 #, c-format msgid "could not open output file: %m" msgstr "konnte Ausgabedatei nicht öffnen: %m" -#: bbstreamer_gzip.c:111 +#: ../../fe_utils/astreamer_gzip.c:135 #, c-format msgid "could not set compression level %d: %s" msgstr "konnte Komprimierungsniveau %d nicht setzen: %s" -#: bbstreamer_gzip.c:143 +#: ../../fe_utils/astreamer_gzip.c:167 #, c-format msgid "could not write to compressed file \"%s\": %s" msgstr "konnte nicht in komprimierte Datei »%s« schreiben: %s" -#: bbstreamer_gzip.c:167 +#: ../../fe_utils/astreamer_gzip.c:191 #, c-format msgid "could not close compressed file \"%s\": %m" msgstr "konnte komprimierte Datei »%s« nicht schließen: %m" -#: bbstreamer_gzip.c:245 walmethods.c:880 +#: ../../fe_utils/astreamer_gzip.c:269 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "konnte Komprimierungsbibliothek nicht initialisieren" -#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 +#: ../../fe_utils/astreamer_gzip.c:320 ../../fe_utils/astreamer_lz4.c:356 +#: ../../fe_utils/astreamer_zstd.c:333 #, c-format msgid "could not decompress data: %s" msgstr "konnte Daten nicht dekomprimieren: %s" -#: bbstreamer_inject.c:189 -#, c-format -msgid "unexpected state while injecting recovery settings" -msgstr "unerwarteter Zustand beim Einfügen der Recovery-Einstellungen" - -#: bbstreamer_lz4.c:95 +#: ../../fe_utils/astreamer_lz4.c:97 #, c-format msgid "could not create lz4 compression context: %s" msgstr "konnte lz4-Komprimierungskontext nicht erzeugen: %s" -#: bbstreamer_lz4.c:140 +#: ../../fe_utils/astreamer_lz4.c:142 #, c-format msgid "could not write lz4 header: %s" msgstr "konnte lz4-Header nicht schreiben: %s" -#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 +#: ../../fe_utils/astreamer_lz4.c:191 ../../fe_utils/astreamer_zstd.c:185 +#: ../../fe_utils/astreamer_zstd.c:227 #, c-format msgid "could not compress data: %s" msgstr "konnte Daten nicht komprimieren: %s" -#: bbstreamer_lz4.c:241 +#: ../../fe_utils/astreamer_lz4.c:243 #, c-format msgid "could not end lz4 compression: %s" msgstr "konnte lz4-Komprimierung nicht beenden: %s" -#: bbstreamer_lz4.c:293 +#: ../../fe_utils/astreamer_lz4.c:295 #, c-format msgid "could not initialize compression library: %s" msgstr "konnte Komprimierungsbibliothek nicht initialisieren: %s" -#: bbstreamer_tar.c:244 +#: ../../fe_utils/astreamer_tar.c:244 #, c-format msgid "tar file trailer exceeds 2 blocks" msgstr "Tar-Datei-Trailer überschreitet 2 Blöcke" -#: bbstreamer_tar.c:249 +#: ../../fe_utils/astreamer_tar.c:249 #, c-format msgid "unexpected state while parsing tar archive" msgstr "unerwarteter Zustand beim Parsen des Tar-Archivs" -#: bbstreamer_tar.c:292 +#: ../../fe_utils/astreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "Tar-Mitglied hat leeren Namen" -#: bbstreamer_tar.c:326 +#: ../../fe_utils/astreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "COPY-Strom endete vor dem Ende der letzten Datei" -#: bbstreamer_zstd.c:85 +#: ../../fe_utils/astreamer_zstd.c:89 #, c-format msgid "could not create zstd compression context" msgstr "konnte zstd-Komprimierungskontext nicht erzeugen" -#: bbstreamer_zstd.c:91 +#: ../../fe_utils/astreamer_zstd.c:95 #, c-format msgid "could not set zstd compression level to %d: %s" msgstr "konnte zstd-Komprimierungsniveau nicht auf %d setzen: %s" -#: bbstreamer_zstd.c:105 +#: ../../fe_utils/astreamer_zstd.c:109 #, c-format msgid "could not set compression worker count to %d: %s" msgstr "konnte Komprimierungs-Worker-Anzahl nicht auf %d setzen: %s" -#: bbstreamer_zstd.c:116 +#: ../../fe_utils/astreamer_zstd.c:120 #, c-format msgid "could not enable long-distance mode: %s" msgstr "konnte Long-Distance-Modus nicht einschalten: %s" -#: bbstreamer_zstd.c:275 +#: ../../fe_utils/astreamer_zstd.c:279 #, c-format msgid "could not create zstd decompression context" msgstr "konnte zstd-Dekomprimierungskontext nicht erzeugen" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "ungültiger Wert »%s« für Option %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s muss im Bereich %d..%d sein" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "unbekannte Sync-Methode: %s" + +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 +#: pg_basebackup.c:1637 +#, c-format +msgid "out of memory" +msgstr "Speicher aufgebraucht" + +#: ../../fe_utils/recovery_gen.c:215 pg_basebackup.c:2249 streamutil.c:89 +#: streamutil.c:204 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" + +#: astreamer_inject.c:189 +#, c-format +msgid "unexpected state while injecting recovery settings" +msgstr "unerwarteter Zustand beim Einfügen der Recovery-Einstellungen" + #: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" @@ -498,14 +508,14 @@ msgstr "" "%s erzeugt eine Basissicherung eines laufenden PostgreSQL-Servers.\n" "\n" -#: pg_basebackup.c:394 pg_createsubscriber.c:216 pg_receivewal.c:79 -#: pg_recvlogical.c:86 +#: pg_basebackup.c:394 pg_createsubscriber.c:246 pg_receivewal.c:79 +#: pg_recvlogical.c:85 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_basebackup.c:395 pg_createsubscriber.c:217 pg_receivewal.c:80 -#: pg_recvlogical.c:87 +#: pg_basebackup.c:395 pg_createsubscriber.c:247 pg_receivewal.c:80 +#: pg_recvlogical.c:86 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPTION]...\n" @@ -658,12 +668,12 @@ msgstr " -P, --progress Fortschrittsinformationen zeigen\n" msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=SLOTNAME zu verwendender Replikations-Slot\n" -#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:109 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose »Verbose«-Modus\n" -#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:110 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" @@ -720,12 +730,12 @@ msgstr "" " Methode zum Synchronisieren von Dateien auf Festplatte\n" " setzen\n" -#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:111 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:112 #, c-format msgid "" "\n" @@ -739,12 +749,12 @@ msgstr "" msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=VERBDG Verbindungsparameter\n" -#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:114 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" -#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:115 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT Portnummer des Datenbankservers\n" @@ -758,23 +768,23 @@ msgstr "" " -s, --status-interval=INTERVALL\n" " Zeit zwischen an Server gesendeten Statuspaketen (in Sekunden)\n" -#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:116 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME Datenbankbenutzername\n" -#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:117 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password niemals nach Passwort fragen\n" -#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:118 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password nach Passwort fragen (sollte automatisch geschehen)\n" -#: pg_basebackup.c:448 pg_createsubscriber.c:235 pg_receivewal.c:106 -#: pg_recvlogical.c:118 +#: pg_basebackup.c:448 pg_createsubscriber.c:270 pg_receivewal.c:106 +#: pg_recvlogical.c:119 #, c-format msgid "" "\n" @@ -783,8 +793,8 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: pg_basebackup.c:449 pg_createsubscriber.c:236 pg_receivewal.c:107 -#: pg_recvlogical.c:119 +#: pg_basebackup.c:449 pg_createsubscriber.c:271 pg_receivewal.c:107 +#: pg_recvlogical.c:120 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" @@ -794,8 +804,8 @@ msgstr "%s Homepage: <%s>\n" msgid "could not read from ready pipe: %m" msgstr "konnte nicht aus bereiter Pipe lesen: %m" -#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 -#: streamutil.c:518 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2259 +#: streamutil.c:450 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "konnte Write-Ahead-Log-Position »%s« nicht interpretieren" @@ -810,521 +820,517 @@ msgstr "konnte WAL-Dateien nicht zu Ende schreiben: %m" msgid "could not create pipe for background process: %m" msgstr "konnte Pipe für Hintergrundprozess nicht erzeugen: %m" -#: pg_basebackup.c:676 +#: pg_basebackup.c:677 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "temporärer Replikations-Slot »%s« wurde erzeugt" -#: pg_basebackup.c:679 +#: pg_basebackup.c:680 #, c-format msgid "created replication slot \"%s\"" msgstr "Replikations-Slot »%s« wurde erzeugt" -#: pg_basebackup.c:728 +#: pg_basebackup.c:729 #, c-format msgid "could not create background process: %m" msgstr "konnte Hintergrundprozess nicht erzeugen: %m" -#: pg_basebackup.c:737 +#: pg_basebackup.c:738 #, c-format msgid "could not create background thread: %m" msgstr "konnte Hintergrund-Thread nicht erzeugen: %m" -#: pg_basebackup.c:776 +#: pg_basebackup.c:777 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "Verzeichnis »%s« existiert aber ist nicht leer" -#: pg_basebackup.c:782 pg_createsubscriber.c:378 +#: pg_basebackup.c:783 pg_createsubscriber.c:420 #, c-format msgid "could not access directory \"%s\": %m" msgstr "konnte nicht auf Verzeichnis »%s« zugreifen: %m" -#: pg_basebackup.c:858 +#: pg_basebackup.c:859 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s kB (100%%), %d/%d Tablespace %*s" msgstr[1] "%*s/%s kB (100%%), %d/%d Tablespaces %*s" -#: pg_basebackup.c:870 +#: pg_basebackup.c:871 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s kB (%d%%), %d/%d Tablespace (%s%-*.*s)" msgstr[1] "%*s/%s kB (%d%%), %d/%d Tablespaces (%s%-*.*s)" -#: pg_basebackup.c:886 +#: pg_basebackup.c:887 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s kB (%d%%), %d/%d Tablespace" msgstr[1] "%*s/%s kB (%d%%), %d/%d Tablespaces" -#: pg_basebackup.c:910 +#: pg_basebackup.c:911 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "Transferrate »%s« ist kein gültiger Wert" -#: pg_basebackup.c:912 +#: pg_basebackup.c:913 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "ungültige Transferrate »%s«: %m" -#: pg_basebackup.c:919 +#: pg_basebackup.c:920 #, c-format msgid "transfer rate must be greater than zero" msgstr "Transferrate muss größer als null sein" -#: pg_basebackup.c:949 +#: pg_basebackup.c:950 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "ungültige Einheit für --max-rate: »%s«" -#: pg_basebackup.c:953 +#: pg_basebackup.c:954 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "Transferrate »%s« überschreitet Bereich für ganze Zahlen" -#: pg_basebackup.c:960 +#: pg_basebackup.c:961 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "Transferrate »%s« ist außerhalb des gültigen Bereichs" -#: pg_basebackup.c:1022 +#: pg_basebackup.c:1023 #, c-format msgid "could not get COPY data stream: %s" msgstr "konnte COPY-Datenstrom nicht empfangen: %s" -#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 -#: receivelog.c:973 +#: pg_basebackup.c:1040 pg_recvlogical.c:450 pg_recvlogical.c:626 +#: receivelog.c:980 #, c-format msgid "could not read COPY data: %s" msgstr "konnte COPY-Daten nicht lesen: %s" -#: pg_basebackup.c:1043 +#: pg_basebackup.c:1044 #, c-format msgid "background process terminated unexpectedly" msgstr "Hintergrundprozess beendete unerwartet" -#: pg_basebackup.c:1114 +#: pg_basebackup.c:1115 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "Manifest kann nicht in eine komprimierte Tar-Datei eingefügt werden" -#: pg_basebackup.c:1115 +#: pg_basebackup.c:1116 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "Verwenden Sie clientseitige Komprimierung, senden Sie die Ausgabe in ein Verzeichnis statt auf die Standardausgabe, oder verwenden Sie %s." -#: pg_basebackup.c:1131 +#: pg_basebackup.c:1132 #, c-format msgid "cannot parse archive \"%s\"" msgstr "kann Archiv »%s« nicht parsen" -#: pg_basebackup.c:1132 +#: pg_basebackup.c:1133 #, c-format msgid "Only tar archives can be parsed." msgstr "Nur Tar-Archive können geparst werden." -#: pg_basebackup.c:1134 +#: pg_basebackup.c:1135 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Format »plain« benötigt pg_basebackup, um das Archiv zu parsen." -#: pg_basebackup.c:1136 +#: pg_basebackup.c:1137 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "Wenn - als Ausgabeverzeichnis verwendet wird, wird pg_basebackup benötigt, um das Archiv zu parsen." -#: pg_basebackup.c:1138 +#: pg_basebackup.c:1139 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "Die Option -R benötigt pg_basebackup, um das Archiv zu parsen." -#: pg_basebackup.c:1357 +#: pg_basebackup.c:1358 #, c-format msgid "archives must precede manifest" msgstr "Archive müssen vor dem Manifest kommen" -#: pg_basebackup.c:1372 +#: pg_basebackup.c:1373 #, c-format msgid "invalid archive name: \"%s\"" msgstr "ungültiger Archivname: »%s«" -#: pg_basebackup.c:1444 +#: pg_basebackup.c:1445 #, c-format msgid "unexpected payload data" msgstr "unerwartete Payload-Daten" -#: pg_basebackup.c:1587 +#: pg_basebackup.c:1588 #, c-format msgid "empty COPY message" msgstr "leere COPY-Nachricht" -#: pg_basebackup.c:1589 +#: pg_basebackup.c:1590 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "fehlerhafte COPY-Nachricht vom Typ %d, Länge %zu" -#: pg_basebackup.c:1789 +#: pg_basebackup.c:1790 #, c-format msgid "incompatible server version %s" msgstr "inkompatible Serverversion %s" -#: pg_basebackup.c:1805 +#: pg_basebackup.c:1806 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "Verwenden Sie -X none oder -X fetch, um Log-Streaming abzuschalten." -#: pg_basebackup.c:1841 +#: pg_basebackup.c:1842 #, c-format msgid "server does not support incremental backup" msgstr "Server unterstützt kein inkrementelles Backup" -#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 -#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 -#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#: pg_basebackup.c:1851 pg_basebackup.c:2009 pg_recvlogical.c:273 +#: receivelog.c:542 receivelog.c:581 streamutil.c:296 streamutil.c:370 +#: streamutil.c:422 streamutil.c:510 streamutil.c:667 streamutil.c:712 #, c-format msgid "could not send replication command \"%s\": %s" msgstr "konnte Replikationsbefehl »%s« nicht senden: %s" -#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#: pg_basebackup.c:1857 pg_basebackup.c:1884 #, c-format msgid "could not upload manifest: %s" msgstr "konnte Manifest nicht hochladen: %s" -#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#: pg_basebackup.c:1860 pg_basebackup.c:1887 #, c-format msgid "could not upload manifest: unexpected status %s" msgstr "konnte Manifest nicht hochladen: unerwarteter Status %s" -#: pg_basebackup.c:1867 +#: pg_basebackup.c:1868 #, c-format msgid "could not send COPY data: %s" msgstr "konnte COPY-Daten nicht senden: %s" -#: pg_basebackup.c:1877 +#: pg_basebackup.c:1878 #, c-format msgid "could not send end-of-COPY: %s" msgstr "konnte End-of-COPY nicht senden: %s" -#: pg_basebackup.c:1892 +#: pg_basebackup.c:1893 #, c-format msgid "unexpected extra result while sending manifest" msgstr "unerwartetes zusätzliches Ergebnis beim Senden des Manifests" -#: pg_basebackup.c:1950 +#: pg_basebackup.c:1951 #, c-format msgid "backup targets are not supported by this server version" msgstr "Backup-Ziele werden von dieser Serverversion nicht unterstützt" -#: pg_basebackup.c:1953 +#: pg_basebackup.c:1954 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "Recovery-Konfiguration kann nicht geschrieben werden, wenn ein Backup-Ziel verwendet wird" -#: pg_basebackup.c:1980 +#: pg_basebackup.c:1981 #, c-format msgid "server does not support server-side compression" msgstr "Server unterstützt keine serverseitige Komprimierung" -#: pg_basebackup.c:1990 +#: pg_basebackup.c:1991 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "Basissicherung eingeleitet, warte auf Abschluss des Checkpoints" -#: pg_basebackup.c:1994 +#: pg_basebackup.c:1995 #, c-format msgid "waiting for checkpoint" msgstr "Warten auf Checkpoint" -#: pg_basebackup.c:2016 +#: pg_basebackup.c:2017 #, c-format msgid "could not initiate base backup: %s" msgstr "konnte Basissicherung nicht starten: %s" -#: pg_basebackup.c:2019 +#: pg_basebackup.c:2020 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "unerwartete Antwort auf Befehl BASE_BACKUP: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" -#: pg_basebackup.c:2025 +#: pg_basebackup.c:2026 #, c-format msgid "checkpoint completed" msgstr "Checkpoint abgeschlossen" -#: pg_basebackup.c:2039 +#: pg_basebackup.c:2040 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "Write-Ahead-Log-Startpunkt: %s auf Zeitleiste %u" -#: pg_basebackup.c:2047 +#: pg_basebackup.c:2048 #, c-format msgid "could not get backup header: %s" msgstr "konnte Kopf der Sicherung nicht empfangen: %s" -#: pg_basebackup.c:2050 +#: pg_basebackup.c:2051 #, c-format msgid "no data returned from server" msgstr "keine Daten vom Server zurückgegeben" -#: pg_basebackup.c:2093 +#: pg_basebackup.c:2094 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "kann nur einen einzelnen Tablespace auf die Standardausgabe schreiben, Datenbank hat %d" -#: pg_basebackup.c:2106 +#: pg_basebackup.c:2107 #, c-format msgid "starting background WAL receiver" msgstr "Hintergrund-WAL-Receiver wird gestartet" -#: pg_basebackup.c:2189 +#: pg_basebackup.c:2190 #, c-format msgid "backup failed: %s" msgstr "Backup fehlgeschlagen: %s" -#: pg_basebackup.c:2192 +#: pg_basebackup.c:2193 #, c-format msgid "no write-ahead log end position returned from server" msgstr "keine Write-Ahead-Log-Endposition vom Server zurückgegeben" -#: pg_basebackup.c:2195 +#: pg_basebackup.c:2196 #, c-format msgid "write-ahead log end point: %s" msgstr "Write-Ahead-Log-Endposition: %s" -#: pg_basebackup.c:2206 +#: pg_basebackup.c:2207 #, c-format msgid "checksum error occurred" msgstr "ein Prüfsummenfehler ist aufgetreten" -#: pg_basebackup.c:2211 +#: pg_basebackup.c:2212 #, c-format msgid "final receive failed: %s" msgstr "letztes Empfangen fehlgeschlagen: %s" -#: pg_basebackup.c:2235 +#: pg_basebackup.c:2236 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "warte bis Hintergrundprozess Streaming beendet hat ..." -#: pg_basebackup.c:2239 +#: pg_basebackup.c:2240 #, c-format msgid "could not send command to background pipe: %m" msgstr "konnte Befehl nicht an Hintergrund-Pipe senden: %m" -#: pg_basebackup.c:2244 +#: pg_basebackup.c:2245 #, c-format msgid "could not wait for child process: %m" msgstr "konnte nicht auf Kindprozess warten: %m" -#: pg_basebackup.c:2246 +#: pg_basebackup.c:2247 #, c-format msgid "child %d died, expected %d" msgstr "Kindprozess %d endete, aber %d wurde erwartet" -#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 -#, c-format -msgid "%s" -msgstr "%s" - -#: pg_basebackup.c:2268 +#: pg_basebackup.c:2269 #, c-format msgid "could not wait for child thread: %m" msgstr "konnte nicht auf Kind-Thread warten: %m" -#: pg_basebackup.c:2273 +#: pg_basebackup.c:2274 #, c-format msgid "could not get child thread exit status: %m" msgstr "konnte Statuscode des Kind-Threads nicht ermitteln: %m" -#: pg_basebackup.c:2276 +#: pg_basebackup.c:2277 #, c-format msgid "child thread exited with error %u" msgstr "Kind-Thread hat mit Fehler %u beendet" -#: pg_basebackup.c:2305 +#: pg_basebackup.c:2306 #, c-format msgid "syncing data to disk ..." msgstr "synchronisiere Daten auf Festplatte ..." -#: pg_basebackup.c:2330 +#: pg_basebackup.c:2331 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "umbenennen von backup_manifest.tmp nach backup_manifest" -#: pg_basebackup.c:2350 +#: pg_basebackup.c:2351 #, c-format msgid "base backup completed" msgstr "Basissicherung abgeschlossen" -#: pg_basebackup.c:2436 +#: pg_basebackup.c:2437 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "ungültiges Checkpoint-Argument »%s«, muss »fast« oder »spread« sein" -#: pg_basebackup.c:2454 +#: pg_basebackup.c:2455 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "ungültiges Ausgabeformat »%s«, muss »plain« oder »tar« sein" -#: pg_basebackup.c:2535 +#: pg_basebackup.c:2536 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "ungültige Option »%s« für --wal-method, muss »fetch«, »stream« oder »none« sein" -#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 -#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 -#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 -#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 -#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 -#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 -#: pg_basebackup.c:2803 pg_createsubscriber.c:1907 pg_createsubscriber.c:1917 -#: pg_createsubscriber.c:1925 pg_createsubscriber.c:1953 -#: pg_createsubscriber.c:1985 pg_receivewal.c:748 pg_receivewal.c:760 -#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 -#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 -#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 -#: pg_recvlogical.c:917 pg_recvlogical.c:924 +#: pg_basebackup.c:2575 pg_basebackup.c:2587 pg_basebackup.c:2609 +#: pg_basebackup.c:2621 pg_basebackup.c:2627 pg_basebackup.c:2679 +#: pg_basebackup.c:2690 pg_basebackup.c:2700 pg_basebackup.c:2706 +#: pg_basebackup.c:2713 pg_basebackup.c:2725 pg_basebackup.c:2737 +#: pg_basebackup.c:2745 pg_basebackup.c:2758 pg_basebackup.c:2764 +#: pg_basebackup.c:2773 pg_basebackup.c:2785 pg_basebackup.c:2796 +#: pg_basebackup.c:2804 pg_createsubscriber.c:2196 pg_createsubscriber.c:2218 +#: pg_createsubscriber.c:2228 pg_createsubscriber.c:2236 +#: pg_createsubscriber.c:2264 pg_createsubscriber.c:2307 pg_receivewal.c:748 +#: pg_receivewal.c:760 pg_receivewal.c:767 pg_receivewal.c:776 +#: pg_receivewal.c:783 pg_receivewal.c:793 pg_recvlogical.c:859 +#: pg_recvlogical.c:871 pg_recvlogical.c:881 pg_recvlogical.c:888 +#: pg_recvlogical.c:895 pg_recvlogical.c:902 pg_recvlogical.c:909 +#: pg_recvlogical.c:916 pg_recvlogical.c:923 pg_recvlogical.c:932 +#: pg_recvlogical.c:939 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_basebackup.c:2584 pg_createsubscriber.c:1915 pg_receivewal.c:758 -#: pg_recvlogical.c:863 +#: pg_basebackup.c:2585 pg_createsubscriber.c:2226 pg_receivewal.c:758 +#: pg_recvlogical.c:869 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: pg_basebackup.c:2607 +#: pg_basebackup.c:2608 #, c-format msgid "cannot specify both format and backup target" msgstr "Format und Backup-Ziel können nicht beide angegeben werden" -#: pg_basebackup.c:2619 +#: pg_basebackup.c:2620 #, c-format msgid "must specify output directory or backup target" msgstr "Ausgabeverzeichnis oder Backup-Ziel muss angegeben werden" -#: pg_basebackup.c:2625 +#: pg_basebackup.c:2626 #, c-format msgid "cannot specify both output directory and backup target" msgstr "Ausgabeverzeichnis und Backup-Ziel können nicht beide angegeben werden" -#: pg_basebackup.c:2655 pg_receivewal.c:802 +#: pg_basebackup.c:2656 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "unbekannter Komprimierungsalgorithmus: »%s«" -#: pg_basebackup.c:2661 pg_receivewal.c:809 +#: pg_basebackup.c:2662 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "ungültige Komprimierungsangabe: %s" -#: pg_basebackup.c:2677 +#: pg_basebackup.c:2678 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "clientseitige Komprimierung ist nicht möglich, wenn ein Backup-Ziel angegeben ist" -#: pg_basebackup.c:2688 +#: pg_basebackup.c:2689 #, c-format msgid "only tar mode backups can be compressed" msgstr "nur Sicherungen im Tar-Modus können komprimiert werden" -#: pg_basebackup.c:2698 +#: pg_basebackup.c:2699 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "WAL-Streaming ist nicht möglich, wenn ein Backup-Ziel angegeben ist" -#: pg_basebackup.c:2704 +#: pg_basebackup.c:2705 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "im Tar-Modus können Write-Ahead-Logs nicht auf Standardausgabe geschrieben werden" -#: pg_basebackup.c:2711 +#: pg_basebackup.c:2712 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "Replikations-Slots können nur mit WAL-Streaming verwendet werden" -#: pg_basebackup.c:2723 +#: pg_basebackup.c:2724 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot kann nicht zusammen mit einem Slot-Namen verwendet werden" #. translator: second %s is an option name -#: pg_basebackup.c:2734 pg_receivewal.c:774 +#: pg_basebackup.c:2735 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "für %s muss ein Slot mit --slot angegeben werden" -#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 -#: pg_basebackup.c:2801 +#: pg_basebackup.c:2743 pg_basebackup.c:2783 pg_basebackup.c:2794 +#: pg_basebackup.c:2802 #, c-format msgid "%s and %s are incompatible options" msgstr "%s und %s sind inkompatible Optionen" -#: pg_basebackup.c:2756 +#: pg_basebackup.c:2757 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "WAL-Verzeichnis kann nicht zusammen mit einem Backup-Ziel angegeben werden" -#: pg_basebackup.c:2762 +#: pg_basebackup.c:2763 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "WAL-Verzeichnis kann nur im »plain«-Modus angegeben werden" -#: pg_basebackup.c:2771 +#: pg_basebackup.c:2772 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL-Verzeichnis muss absoluten Pfad haben" -#: pg_basebackup.c:2871 +#: pg_basebackup.c:2872 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "konnte symbolische Verknüpfung »%s« nicht erstellen: %m" -#: pg_createsubscriber.c:164 -#, fuzzy, c-format -#| msgid "pausing at the end of recovery" +#: pg_createsubscriber.c:189 +#, c-format msgid "failed after the end of recovery" -msgstr "pausiere am Ende der Wiederherstellung" +msgstr "fehlgeschlagen am Ende der Wiederherstellung" -#: pg_createsubscriber.c:165 +#: pg_createsubscriber.c:190 #, c-format msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." -msgstr "" +msgstr "Der Zielserver kann nicht mehr als physischer Standby verwendet werden. Sie müssen den physischen Standby neu erzeugen bevor fortgesetzt werden kann." -#: pg_createsubscriber.c:193 +#: pg_createsubscriber.c:221 #, c-format -msgid "publication \"%s\" in database \"%s\" on primary might be left behind" -msgstr "" +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "Publikation »%s« erzeugt in Datenbank »%s« auf dem Primärserver wurde zurückgelassen" -#: pg_createsubscriber.c:195 +#: pg_createsubscriber.c:224 #, c-format -msgid "Consider dropping this publication before trying again." -msgstr "" +msgid "Drop this publication before trying again." +msgstr "Löschen Sie diese Publikation, bevor Sie erneut versuchen." -#: pg_createsubscriber.c:199 +#: pg_createsubscriber.c:228 #, c-format -msgid "replication slot \"%s\" in database \"%s\" on primary might be left behind" -msgstr "" +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "Replikations-Slot »%s« erzeugt in Datenbank »%s« auf dem Primärserver wurde zurückgelassen" -#: pg_createsubscriber.c:201 pg_createsubscriber.c:1137 +#: pg_createsubscriber.c:231 pg_createsubscriber.c:1305 #, c-format msgid "Drop this replication slot soon to avoid retention of WAL files." -msgstr "" +msgstr "Löschen Sie diesen Replikations-Slot bald, um Zurückhalten von WAL-Datein zu vermeiden." -#: pg_createsubscriber.c:214 -#, fuzzy, c-format -#| msgid "cannot copy a replication slot that doesn't reserve WAL" +#: pg_createsubscriber.c:244 +#, c-format msgid "" "%s creates a new logical replica from a standby server.\n" "\n" -msgstr "ein Replikations-Slot, der kein WAL reserviert, kann nicht kopiert werden" +msgstr "" +"%s erzeugt eine neue logische Replik aus einem Standby-Server.\n" +"\n" -#: pg_createsubscriber.c:218 pg_receivewal.c:81 pg_recvlogical.c:92 +#: pg_createsubscriber.c:248 pg_receivewal.c:81 pg_recvlogical.c:91 #, c-format msgid "" "\n" @@ -1333,60 +1339,71 @@ msgstr "" "\n" "Optionen:\n" -#: pg_createsubscriber.c:219 -#, fuzzy, c-format -#| msgid " -d, --dbname=DBNAME database to vacuum\n" -msgid " -d, --database=DBNAME database to create a subscription\n" -msgstr " -d, --dbname=DBNAME führe Vacuum in dieser Datenbank aus\n" +#: pg_createsubscriber.c:249 +#, c-format +msgid "" +" -a, --all create subscriptions for all databases except template\n" +" databases or databases that don't allow connections\n" +msgstr "" -#: pg_createsubscriber.c:220 -#, fuzzy, c-format -#| msgid " [-D, --pgdata=]DATADIR location for this database cluster\n" +#: pg_createsubscriber.c:251 +#, c-format +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --database=DBNAME Datenbank, in der eine Subskription erzeugt werden soll\n" + +#: pg_createsubscriber.c:252 +#, c-format msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" -msgstr " [-D, --pgdata=]DATENVERZ Datenverzeichnis für diesen Datenbankcluster\n" +msgstr " -D, --pgdata=DATENVERZ Datenverzeichnis für den Subskriptionsserver\n" -#: pg_createsubscriber.c:221 -#, fuzzy, c-format -#| msgid " -n, --dry-run no update, just show what would be done\n" +#: pg_createsubscriber.c:253 +#, c-format msgid " -n, --dry-run dry run, just show what would be done\n" -msgstr " -n, --dry-run keine Änderungen; nur zeigen, was gemacht werden würde\n" +msgstr " -n, --dry-run Probelauf; nur zeigen, was gemacht werden würde\n" -#: pg_createsubscriber.c:222 -#, fuzzy, c-format -#| msgid " -p, --old-port=PORT old cluster port number (default %d)\n" +#: pg_createsubscriber.c:254 +#, c-format msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" -msgstr " -p, --old-port=PORT Portnummer für den alten Cluster (Standard: %d)\n" +msgstr " -p, --subscriber-port=PORT Portnummer für den Subskriptionsserver (Standard %s)\n" -#: pg_createsubscriber.c:223 -#, fuzzy, c-format -#| msgid " -d, --dbname=CONNSTR connect using connection string\n" +#: pg_createsubscriber.c:255 +#, c-format msgid " -P, --publisher-server=CONNSTR publisher connection string\n" -msgstr " -d, --dbname=VERBDG mit angegebenen Verbindungsparametern verbinden\n" +msgstr " -P, --publisher-server=VERBDG Verbindungsparameter des Publikationsservers\n" -#: pg_createsubscriber.c:224 -#, fuzzy, c-format -#| msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" -msgid " -s, --socket-directory=DIR socket directory to use (default current directory)\n" -msgstr " -s, --socketdir=VERZ Verzeichnis für Socket (Standard: aktuelles Verz.)\n" +#: pg_createsubscriber.c:256 +#, c-format +msgid "" +" -R, --remove=OBJECTTYPE remove all objects of the specified type from specified\n" +" databases on the subscriber; accepts: publications\n" +msgstr "" -#: pg_createsubscriber.c:225 -#, fuzzy, c-format -#| msgid " -t, --timeout=SECS seconds to wait when using -w option\n" +#: pg_createsubscriber.c:258 +#, c-format +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=VERZ Verzeichnis für Socket (Standard: aktuelles Verz.)\n" + +#: pg_createsubscriber.c:259 +#, c-format msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" -msgstr " -t, --timeout=SEK Sekunden zu warten bei Option -w\n" +msgstr " -t, --recovery-timeout=SEK Sekunden zu warten auf Ende der Wiederherstellung\n" -#: pg_createsubscriber.c:226 -#, fuzzy, c-format -#| msgid " -U, --username=NAME database superuser name\n" -msgid " -U, --subscriber-username=NAME subscriber username\n" -msgstr " -U, --username=NAME Datenbank-Superusername\n" +#: pg_createsubscriber.c:260 +#, c-format +msgid " -T, --enable-two-phase enable two-phase commit for all subscriptions\n" +msgstr " -T, --enable-two-phase Zwei-Phasen-Commit für alle Subskriptionen einschalten\n" -#: pg_createsubscriber.c:227 +#: pg_createsubscriber.c:261 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NAME Benutzername für Subskriptionsserver-Verbindung\n" + +#: pg_createsubscriber.c:262 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose »Verbose«-Modus\n" -#: pg_createsubscriber.c:228 +#: pg_createsubscriber.c:263 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -1395,606 +1412,611 @@ msgstr "" " --config-file=DATEINAME angegebene Serverkonfigurationsdatei zum\n" " Starten des Ziel-Clusters verwenden\n" -#: pg_createsubscriber.c:230 +#: pg_createsubscriber.c:265 #, c-format msgid " --publication=NAME publication name\n" msgstr " --publication=NAME Publikationsname\n" -#: pg_createsubscriber.c:231 -#, fuzzy, c-format -#| msgid " -C, --create-slot create replication slot\n" +#: pg_createsubscriber.c:266 +#, c-format msgid " --replication-slot=NAME replication slot name\n" -msgstr " -C, --create-slot Replikations-Slot erzeugen\n" +msgstr " --replication-slot=NAME Replikations-Slot-Name\n" -#: pg_createsubscriber.c:232 +#: pg_createsubscriber.c:267 #, c-format msgid " --subscription=NAME subscription name\n" msgstr " --subscription=NAME Subskriptionsname\n" -#: pg_createsubscriber.c:233 +#: pg_createsubscriber.c:268 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_createsubscriber.c:234 +#: pg_createsubscriber.c:269 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_createsubscriber.c:265 +#: pg_createsubscriber.c:312 #, c-format msgid "could not parse connection string: %s" msgstr "konnte Verbindungsparameter nicht interpretieren: %s" -#: pg_createsubscriber.c:347 +#: pg_createsubscriber.c:389 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden" -#: pg_createsubscriber.c:350 +#: pg_createsubscriber.c:392 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s" -#: pg_createsubscriber.c:370 -#, fuzzy, c-format -#| msgid "specified data directory \"%s\" is not a directory" +#: pg_createsubscriber.c:412 +#, c-format msgid "checking if directory \"%s\" is a cluster data directory" -msgstr "angegebenes Datenverzeichnis »%s« ist kein Verzeichnis" +msgstr "prüfe ob Verzeichnis »%s« ein Cluster-Datenverzeichnis ist" -#: pg_createsubscriber.c:376 +#: pg_createsubscriber.c:418 #, c-format msgid "data directory \"%s\" does not exist" msgstr "Datenverzeichnis »%s« existiert nicht" -#: pg_createsubscriber.c:384 +#: pg_createsubscriber.c:426 #, c-format msgid "directory \"%s\" is not a database cluster directory" msgstr "Verzeichnis »%s« ist kein Datenbankclusterverzeichnis" -#: pg_createsubscriber.c:501 +#: pg_createsubscriber.c:544 #, c-format msgid "connection to database failed: %s" msgstr "Verbindung zur Datenbank fehlgeschlagen: %s" -#: pg_createsubscriber.c:514 +#: pg_createsubscriber.c:557 streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "konnte search_path nicht auf leer setzen: %s" +msgid "could not clear \"search_path\": %s" +msgstr "konnte »search_path« nicht auf leer setzen: %s" -#: pg_createsubscriber.c:554 +#: pg_createsubscriber.c:597 #, c-format msgid "getting system identifier from publisher" msgstr "hole Systemidentifikator vom Publikationsserver" -#: pg_createsubscriber.c:561 +#: pg_createsubscriber.c:604 #, c-format msgid "could not get system identifier: %s" msgstr "konnte Systemidentifikator nicht ermitteln: %s" -#: pg_createsubscriber.c:567 -#, fuzzy, c-format -#| msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" +#: pg_createsubscriber.c:610 +#, c-format msgid "could not get system identifier: got %d rows, expected %d row" -msgstr "Konnte System nicht identifizieren: %d Zeilen und %d Felder erhalten, %d Zeilen und %d oder mehr Felder erwartet" +msgstr "konnte Systemidentifikator nicht ermitteln: %d Zeilen erhalten, %d Zeile erwartet" -#: pg_createsubscriber.c:574 -#, fuzzy, c-format -#| msgid "%s: expected system identifier %llu, but found %llu" -msgid "system identifier is %llu on publisher" -msgstr "%s: Systemidentifikator %llu erwartet, aber %llu gefunden" +#: pg_createsubscriber.c:617 +#, c-format +msgid "system identifier is % on publisher" +msgstr "Systemidentifikator ist % auf dem Publikationsserver" -#: pg_createsubscriber.c:595 +#: pg_createsubscriber.c:637 #, c-format msgid "getting system identifier from subscriber" msgstr "hole Systemidentifikator vom Subskriptionsserver" -#: pg_createsubscriber.c:599 pg_createsubscriber.c:629 +#: pg_createsubscriber.c:641 pg_createsubscriber.c:670 #, c-format msgid "control file appears to be corrupt" msgstr "Kontrolldatei scheint kaputt zu sein" -#: pg_createsubscriber.c:603 pg_createsubscriber.c:644 +#: pg_createsubscriber.c:645 pg_createsubscriber.c:685 #, c-format -msgid "system identifier is %llu on subscriber" -msgstr "Systemidentifikator ist %llu auf dem Subskriptionsserver" +msgid "system identifier is % on subscriber" +msgstr "Systemidentifikator ist % auf dem Subskriptionsserver" -#: pg_createsubscriber.c:625 +#: pg_createsubscriber.c:666 #, c-format msgid "modifying system identifier of subscriber" msgstr "ändere Systemidentifikator auf dem Subskriptionsserver" -#: pg_createsubscriber.c:647 +#: pg_createsubscriber.c:688 #, c-format msgid "running pg_resetwal on the subscriber" msgstr "führe pg_resetwal auf dem Subskriptionsserver aus" -#: pg_createsubscriber.c:659 +#: pg_createsubscriber.c:700 #, c-format msgid "subscriber successfully changed the system identifier" msgstr "Subskriptionsserver hat Systemidentifikator erfolgreich geändert" -#: pg_createsubscriber.c:661 +#: pg_createsubscriber.c:702 #, c-format -msgid "subscriber failed to change system identifier: exit code: %d" -msgstr "" +msgid "could not change system identifier of subscriber: %s" +msgstr "konnte Systemidentifikator des Subskriptionsservers nicht ändern: %s" -#: pg_createsubscriber.c:685 +#: pg_createsubscriber.c:726 #, c-format msgid "could not obtain database OID: %s" msgstr "konnte Datenbank-OID nicht ermitteln: %s" -#: pg_createsubscriber.c:692 -#, fuzzy, c-format -#| msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" +#: pg_createsubscriber.c:733 +#, c-format msgid "could not obtain database OID: got %d rows, expected %d row" -msgstr "konnte Replikations-Slot »%s« nicht löschen: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" +msgstr "konnte Datenbank-OID nicht ermitteln: %d Zeilen erhalten, %d Zeile erwartet" -#: pg_createsubscriber.c:764 -#, fuzzy, c-format -#| msgid "created replication slot \"%s\" on publisher" +#: pg_createsubscriber.c:805 +#, c-format msgid "create replication slot \"%s\" on publisher" -msgstr "Replikations-Slot »%s« wurde auf dem Publikationsserver erzeugt" +msgstr "erzeuge Replikations-Slot »%s« auf dem Publikationsserver" + +#: pg_createsubscriber.c:825 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "konnte zusätzlichen WAL-Datensatz nicht schreiben: %s" -#: pg_createsubscriber.c:788 +#: pg_createsubscriber.c:851 #, c-format msgid "could not obtain recovery progress: %s" msgstr "konnte Recovery-Fortschritt nicht ermitteln: %s" -#: pg_createsubscriber.c:819 -#, fuzzy, c-format -#| msgid "created replication slot \"%s\" on publisher" +#: pg_createsubscriber.c:884 +#, c-format msgid "checking settings on publisher" -msgstr "Replikations-Slot »%s« wurde auf dem Publikationsserver erzeugt" +msgstr "prüfe Einstellungen auf dem Publikationsserver" -#: pg_createsubscriber.c:829 -#, fuzzy, c-format -#| msgid "primary keys cannot be expressions" +#: pg_createsubscriber.c:894 +#, c-format msgid "primary server cannot be in recovery" -msgstr "Primärschlüssel können keine Ausdrücke sein" +msgstr "Primärserver kann nicht im Wiederherstellungsmodus sein" -#: pg_createsubscriber.c:864 -#, fuzzy, c-format -#| msgid "could not connect to the publisher: %s" +#: pg_createsubscriber.c:920 +#, c-format msgid "could not obtain publisher settings: %s" -msgstr "konnte nicht mit dem Publikationsserver verbinden: %s" +msgstr "konnte Einstellungen des Publikationsservers nicht ermitteln: %s" -#: pg_createsubscriber.c:887 +#: pg_createsubscriber.c:949 #, c-format -msgid "publisher requires wal_level >= \"logical\"" -msgstr "Publikationsserver benötigt wal_level >= »logical«" +msgid "publisher requires \"wal_level\" >= \"logical\"" +msgstr "Publikationsserver benötigt »wal_level« >= »logical«" -#: pg_createsubscriber.c:893 -#, fuzzy, c-format -#| msgid "Field requires %d characters, but only %d remain." +#: pg_createsubscriber.c:955 +#, c-format msgid "publisher requires %d replication slots, but only %d remain" -msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben." +msgstr "Publikationsserver benötigt %d Replikations-Slots, aber nur %d verbleiben" -#: pg_createsubscriber.c:895 pg_createsubscriber.c:994 -#, fuzzy, c-format -#| msgid "Free one or increase max_replication_slots." -msgid "Consider increasing max_replication_slots to at least %d." -msgstr "Geben Sie einen frei oder erhöhen Sie max_replication_slots." +#: pg_createsubscriber.c:957 pg_createsubscriber.c:966 +#: pg_createsubscriber.c:1076 pg_createsubscriber.c:1085 +#: pg_createsubscriber.c:1094 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Erhöhen Sie den Konfigurationsparameter »%s« auf mindestens %d." -#: pg_createsubscriber.c:902 -#, fuzzy, c-format -#| msgid "Field requires %d characters, but only %d remain." -msgid "publisher requires %d wal sender processes, but only %d remain" -msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben." +#: pg_createsubscriber.c:964 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "Publikationsserver benötigt %d WAL-Sender-Prozesse, aber nur %d verbleiben" + +#: pg_createsubscriber.c:973 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "Option »two_phase« wird für Replikations-Slots nicht aktiviert" -#: pg_createsubscriber.c:904 +#: pg_createsubscriber.c:974 #, c-format -msgid "Consider increasing max_wal_senders to at least %d." +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "Subskriptionen werden mit der Option »two_phase« ausgeschaltet erzeugt. Vorbereitete Transaktionen werden bei COMMIT PREPARED repliziert werden." + +#: pg_createsubscriber.c:976 +#, c-format +msgid "You can use --enable-two-phase switch to enable two_phase." msgstr "" -#: pg_createsubscriber.c:937 +#: pg_createsubscriber.c:986 +#, c-format +msgid "required WAL could be removed from the publisher" +msgstr "" + +#: pg_createsubscriber.c:987 +#, fuzzy, c-format +#| msgid "Make sure the configuration parameter \"%s\" is set on the primary server." +msgid "Set the configuration parameter \"%s\" to -1 to ensure that required WAL files are not prematurely removed." +msgstr "Stellen Sie sicher, dass der Konfigurationsparameter »%s« auf dem Primärserver gesetzt ist." + +#: pg_createsubscriber.c:1019 #, c-format msgid "checking settings on subscriber" msgstr "prüfe Einstellungen auf Subskriptionsserver" -#: pg_createsubscriber.c:944 -#, fuzzy, c-format -#| msgid "target server must be shut down cleanly" +#: pg_createsubscriber.c:1026 +#, c-format msgid "target server must be a standby" -msgstr "Zielserver muss sauber heruntergefahren worden sein" +msgstr "Zielserver muss ein Standby sein" -#: pg_createsubscriber.c:968 +#: pg_createsubscriber.c:1050 #, c-format msgid "could not obtain subscriber settings: %s" msgstr "konnte Einstellungen des Subskriptionsservers nicht ermitteln: %s" -#: pg_createsubscriber.c:992 +#: pg_createsubscriber.c:1074 #, fuzzy, c-format -#| msgid "Field requires %d characters, but only %d remain." -msgid "subscriber requires %d replication slots, but only %d remain" -msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben." +#| msgid "subscriber requires %d replication slots, but only %d remain" +msgid "subscriber requires %d active replication origins, but only %d remain" +msgstr "Subskriptionsserver benötigt %d Replikations-Slots, aber nur %d verbleiben" -#: pg_createsubscriber.c:1001 -#, fuzzy, c-format -#| msgid "Field requires %d characters, but only %d remain." +#: pg_createsubscriber.c:1083 +#, c-format msgid "subscriber requires %d logical replication workers, but only %d remain" -msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben." +msgstr "Subskriptionsserver benötigt %d Arbeitsprozesse für logische Replikation, aber nur %d verbleiben" -#: pg_createsubscriber.c:1003 -#, fuzzy, c-format -#| msgid "terminating logical replication worker due to timeout" -msgid "Consider increasing max_logical_replication_workers to at least %d." -msgstr "Arbeitsprozess für logische Replikation wird abgebrochen wegen Zeitüberschreitung" - -#: pg_createsubscriber.c:1010 -#, fuzzy, c-format -#| msgid "Field requires %d characters, but only %d remain." +#: pg_createsubscriber.c:1092 +#, c-format msgid "subscriber requires %d worker processes, but only %d remain" -msgstr "Feld benötigt %d Zeichen, aber nur %d verbleiben." +msgstr "Subskriptionsserver benötigt %d Arbeitsprozesse, aber nur %d verbleiben" -#: pg_createsubscriber.c:1012 -#, fuzzy, c-format -#| msgid "Consider increasing the configuration parameter \"max_worker_processes\"." -msgid "Consider increasing max_worker_processes to at least %d." -msgstr "Erhöhen Sie eventuell den Konfigurationsparameter »max_worker_processes«." +#: pg_createsubscriber.c:1127 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "lösche Subskription »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1135 -#, fuzzy, c-format -#| msgid "could not drop replication slot \"%s\" on publisher: %s" +#: pg_createsubscriber.c:1136 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "konnte Subskription »%s« nicht löschen: %s" + +#: pg_createsubscriber.c:1171 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "konnte bereits existierende Subskriptionen nicht ermitteln: %s" + +#: pg_createsubscriber.c:1303 +#, c-format msgid "could not drop replication slot \"%s\" on primary" -msgstr "konnte Replikations-Slot »%s« auf dem Publikationsserver nicht löschen: %s" +msgstr "konnte Replikations-Slot »%s« auf dem Primärserver nicht löschen" -#: pg_createsubscriber.c:1169 -#, fuzzy, c-format -#| msgid "could not obtain replication slot information: %s" +#: pg_createsubscriber.c:1337 +#, c-format msgid "could not obtain failover replication slot information: %s" -msgstr "konnte Replikations-Slot-Informationen nicht ermitteln: %s" +msgstr "konnte Failover-Replikations-Slot-Informationen nicht ermitteln: %s" -#: pg_createsubscriber.c:1171 pg_createsubscriber.c:1180 +#: pg_createsubscriber.c:1339 pg_createsubscriber.c:1348 #, c-format msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." -msgstr "" +msgstr "Löschen Sie die Failover-Replikations-Slots auf dem Subskriptionsserver bald, um Zurückhalten von WAL-Dateien zu vermeiden." -#: pg_createsubscriber.c:1179 -#, fuzzy, c-format -#| msgid "could not alter replication slot \"%s\": %s" +#: pg_createsubscriber.c:1347 +#, c-format msgid "could not drop failover replication slot" -msgstr "konnte Replikations-Slot »%s« nicht ändern: %s" +msgstr "konnte Failover-Replikations-Slot nicht löschen" -#: pg_createsubscriber.c:1201 -#, fuzzy, c-format -#| msgid "created replication slot \"%s\" on publisher" -msgid "creating the replication slot \"%s\" on database \"%s\"" -msgstr "Replikations-Slot »%s« wurde auf dem Publikationsserver erzeugt" +#: pg_createsubscriber.c:1369 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "erzeuge Replikations-Slot »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1219 -#, fuzzy, c-format -#| msgid "could not create replication slot \"%s\": %s" -msgid "could not create replication slot \"%s\" on database \"%s\": %s" -msgstr "konnte Replikations-Slot »%s« nicht erzeugen: %s" +#: pg_createsubscriber.c:1388 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "konnte Replikations-Slot »%s« in Datenbank »%s« nicht erzeugen: %s" -#: pg_createsubscriber.c:1249 -#, fuzzy, c-format -#| msgid "dropped replication slot \"%s\" on publisher" -msgid "dropping the replication slot \"%s\" on database \"%s\"" -msgstr "Replikations-Slot »%s« auf dem Publikationsserver wurde gelöscht" +#: pg_createsubscriber.c:1418 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "lösche Replikations-Slot »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1265 -#, fuzzy, c-format -#| msgid "could not drop replication slot \"%s\" on publisher: %s" -msgid "could not drop replication slot \"%s\" on database \"%s\": %s" -msgstr "konnte Replikations-Slot »%s« auf dem Publikationsserver nicht löschen: %s" +#: pg_createsubscriber.c:1434 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "konnte Replikations-Slot »%s« in Datenbank »%s« nicht löschen: %s" -#: pg_createsubscriber.c:1286 -#, fuzzy, c-format -#| msgid "archive command failed with exit code %d" +#: pg_createsubscriber.c:1455 +#, c-format msgid "pg_ctl failed with exit code %d" -msgstr "Archivbefehl ist fehlgeschlagen mit Statuscode %d" +msgstr "pg_ctl ist fehlgeschlagen mit Statuscode %d" -#: pg_createsubscriber.c:1291 -#, fuzzy, c-format -#| msgid "child process was terminated by exception 0x%X" +#: pg_createsubscriber.c:1460 +#, c-format msgid "pg_ctl was terminated by exception 0x%X" -msgstr "Kindprozess wurde durch Ausnahme 0x%X beendet" +msgstr "pg_ctl wurde durch Ausnahme 0x%X beendet" -#: pg_createsubscriber.c:1293 +#: pg_createsubscriber.c:1462 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "Sehen Sie die Beschreibung des Hexadezimalwerts in der C-Include-Datei »ntstatus.h« nach." -#: pg_createsubscriber.c:1295 -#, fuzzy, c-format -#| msgid "child process was terminated by signal %d: %s" +#: pg_createsubscriber.c:1464 +#, c-format msgid "pg_ctl was terminated by signal %d: %s" -msgstr "Kindprozess wurde von Signal %d beendet: %s" +msgstr "pg_ctl wurde durch Signal %d beendet: %s" -#: pg_createsubscriber.c:1301 -#, fuzzy, c-format -#| msgid "child process exited with unrecognized status %d" +#: pg_createsubscriber.c:1470 +#, c-format msgid "pg_ctl exited with unrecognized status %d" -msgstr "Kindprozess hat mit unbekanntem Status %d beendet" +msgstr "pg_ctl hat mit unbekanntem Status %d beendet" -#: pg_createsubscriber.c:1304 +#: pg_createsubscriber.c:1473 #, c-format msgid "The failed command was: %s" msgstr "Der fehlgeschlagene Befehl war: %s" -#: pg_createsubscriber.c:1343 +#: pg_createsubscriber.c:1523 #, c-format msgid "server was started" msgstr "Server wurde gestartet" -#: pg_createsubscriber.c:1358 +#: pg_createsubscriber.c:1538 #, c-format msgid "server was stopped" msgstr "Server wurde angehalten" -#: pg_createsubscriber.c:1377 +#: pg_createsubscriber.c:1557 #, c-format msgid "waiting for the target server to reach the consistent state" -msgstr "" +msgstr "warte, dass der Zielserver einen konsistenten Zustand erreicht" -#: pg_createsubscriber.c:1400 +#: pg_createsubscriber.c:1580 #, c-format msgid "recovery timed out" -msgstr "" +msgstr "Zeitüberschreitung bei der Wiederherstellung" -#: pg_createsubscriber.c:1413 -#, fuzzy, c-format -#| msgid "server did not promote within %d second" -#| msgid_plural "server did not promote within %d seconds" +#: pg_createsubscriber.c:1593 +#, c-format msgid "server did not end recovery" -msgstr "Befördern des Servers wurde nicht innerhalb von %d Sekunde abgeschlossen" +msgstr "Server hat Recovery-Zustand nicht beendet" -#: pg_createsubscriber.c:1415 +#: pg_createsubscriber.c:1595 #, c-format msgid "target server reached the consistent state" -msgstr "" +msgstr "Zielserver hat einen konsistenten Zustand erreicht" -#: pg_createsubscriber.c:1416 -#, fuzzy, c-format -#| msgid "" -#| "\n" -#| "If pg_upgrade fails after this point, you must re-initdb the\n" -#| "new cluster before continuing." +#: pg_createsubscriber.c:1596 +#, c-format msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." -msgstr "" -"\n" -"Wenn pg_upgrade ab diesem Punkt fehlschlägt, dann müssen Sie den\n" -"neuen Cluster neu mit initdb initialisieren, bevor fortgesetzt\n" -"werden kann." +msgstr "Wenn pg_createsubscriber ab diesem Punkt fehlschlägt, dann müssen Sie die physikalische Replik neu erzeugen, bevor fortgesetzt werden kann." -#: pg_createsubscriber.c:1443 -#, fuzzy, c-format -#| msgid "could not obtain lock on relation \"%s\"" +#: pg_createsubscriber.c:1623 pg_createsubscriber.c:1746 +#, c-format msgid "could not obtain publication information: %s" -msgstr "konnte Sperre für Relation »%s« nicht setzen" +msgstr "konnte Publikationsinformationen nicht ermitteln: %s" -#: pg_createsubscriber.c:1457 +#: pg_createsubscriber.c:1637 #, c-format msgid "publication \"%s\" already exists" msgstr "Publikation »%s« existiert bereits" -#: pg_createsubscriber.c:1458 +#: pg_createsubscriber.c:1638 #, c-format msgid "Consider renaming this publication before continuing." -msgstr "" +msgstr "Nennen Sie diese Publikation eventuell um bevor Sie fortsetzen." -#: pg_createsubscriber.c:1465 -#, fuzzy, c-format -#| msgid "creating replication slot \"%s\"" -msgid "creating publication \"%s\" on database \"%s\"" -msgstr "erzeuge Replikations-Slot »%s«" +#: pg_createsubscriber.c:1645 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "erzeuge Publikation »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1478 -#, fuzzy, c-format -#| msgid "could not create replication slot \"%s\": %s" -msgid "could not create publication \"%s\" on database \"%s\": %s" -msgstr "konnte Replikations-Slot »%s« nicht erzeugen: %s" +#: pg_createsubscriber.c:1658 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "konnte Publikation »%s« in Datenbank »%s« nicht erzeugen: %s" -#: pg_createsubscriber.c:1507 -#, fuzzy, c-format -#| msgid "dropping replication slot \"%s\"" -msgid "dropping publication \"%s\" on database \"%s\"" -msgstr "lösche Replikations-Slot »%s«" +#: pg_createsubscriber.c:1688 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "lösche Publikation »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1521 -#, fuzzy, c-format -#| msgid "could not drop replication slot \"%s\" on publisher: %s" -msgid "could not drop publication \"%s\" on database \"%s\": %s" -msgstr "konnte Replikations-Slot »%s« auf dem Publikationsserver nicht löschen: %s" +#: pg_createsubscriber.c:1702 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "konnte Publikation »%s« in Datenbank »%s« nicht löschen: %s" -#: pg_createsubscriber.c:1567 +#: pg_createsubscriber.c:1739 #, fuzzy, c-format -#| msgid "remote transaction %u of subscription %u of database %u" -msgid "creating subscription \"%s\" on database \"%s\"" -msgstr "Remote-Transaktion %u von Subskription %u in Datenbank %u" +#| msgid "dropping publication \"%s\" in database \"%s\"" +msgid "dropping all existing publications in database \"%s\"" +msgstr "lösche Publikation »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1588 -#, fuzzy, c-format -#| msgid "could not create replication slot \"%s\": %s" -msgid "could not create subscription \"%s\" on database \"%s\": %s" -msgstr "konnte Replikations-Slot »%s« nicht erzeugen: %s" +#: pg_createsubscriber.c:1797 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "erzeuge Subskription »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1633 -#, fuzzy, c-format -#| msgid "could not obtain lock on relation \"%s\"" +#: pg_createsubscriber.c:1819 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "konnte Subskription »%s« in Datenbank »%s« nicht erzeugen: %s" + +#: pg_createsubscriber.c:1864 +#, c-format msgid "could not obtain subscription OID: %s" -msgstr "konnte Sperre für Relation »%s« nicht setzen" +msgstr "konnte Subskriptions-OID nicht ermitteln: %s" -#: pg_createsubscriber.c:1640 -#, fuzzy, c-format -#| msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" +#: pg_createsubscriber.c:1871 +#, c-format msgid "could not obtain subscription OID: got %d rows, expected %d row" -msgstr "konnte Replikations-Slot »%s« nicht lesen: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" +msgstr "konnte Subskriptions-OID nicht ermitteln: %d Zeilen erhalten, %d Zeile erwartet" -#: pg_createsubscriber.c:1664 +#: pg_createsubscriber.c:1895 #, c-format -msgid "setting the replication progress (node name \"%s\" ; LSN %s) on database \"%s\"" -msgstr "" +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "setze Replikationsfortschritt (Knotenname »%s«, LSN %s) in Datenbank »%s«" -#: pg_createsubscriber.c:1679 -#, fuzzy, c-format -#| msgid "could not drop relation mapping for subscription \"%s\"" -msgid "could not set replication progress for the subscription \"%s\": %s" -msgstr "konnte Relation-Mapping für Subskription »%s« nicht löschen" +#: pg_createsubscriber.c:1910 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "konnte Replikationsfortschritt für Subskription »%s« nicht setzen: %s" -#: pg_createsubscriber.c:1710 -#, fuzzy, c-format -#| msgid "remote transaction %u of subscription %u of database %u" -msgid "enabling subscription \"%s\" on database \"%s\"" -msgstr "Remote-Transaktion %u von Subskription %u in Datenbank %u" +#: pg_createsubscriber.c:1941 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "aktiviere Subskription »%s« in Datenbank »%s«" -#: pg_createsubscriber.c:1722 -#, fuzzy, c-format -#| msgid "could not enable user right \"%s\"" +#: pg_createsubscriber.c:1953 +#, c-format msgid "could not enable subscription \"%s\": %s" -msgstr "konnte Benutzerrecht »%s« nicht aktivieren" +msgstr "konnte Subskription »%s« nicht aktivieren: %s" + +#: pg_createsubscriber.c:1999 +#, fuzzy, c-format +#| msgid "could not obtain database OID: %s" +msgid "could not obtain a list of databases: %s" +msgstr "konnte Datenbank-OID nicht ermitteln: %s" -#: pg_createsubscriber.c:1814 +#: pg_createsubscriber.c:2103 #, c-format msgid "cannot be executed by \"root\"" msgstr "kann nicht von »root« ausgeführt werden" -#: pg_createsubscriber.c:1815 +#: pg_createsubscriber.c:2104 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Sie müssen %s als PostgreSQL-Superuser ausführen." -#: pg_createsubscriber.c:1836 +#: pg_createsubscriber.c:2127 #, fuzzy, c-format -#| msgid "dumping database \"%s\"" -msgid "duplicate database \"%s\"" -msgstr "Ausgabe der Datenbank »%s«" +#| msgid "database \"%s\" specified more than once" +msgid "database \"%s\" specified more than once for -d/--database" +msgstr "Datenbank »%s« mehrmals angegeben" -#: pg_createsubscriber.c:1877 +#: pg_createsubscriber.c:2146 #, fuzzy, c-format -#| msgid "duplicate option \"%s\"" -msgid "duplicate publication \"%s\"" -msgstr "doppelte Option »%s«" +#| msgid "table name \"%s\" specified more than once" +msgid "object type \"%s\" is specified more than once for -R/--remove" +msgstr "Tabellenname »%s« mehrmals angegeben" -#: pg_createsubscriber.c:1889 +#: pg_createsubscriber.c:2174 #, fuzzy, c-format -#| msgid "created replication slot \"%s\"" -msgid "duplicate replication slot \"%s\"" -msgstr "Replikations-Slot »%s« wurde erzeugt" +#| msgid "publication \"%s\" specified more than once" +msgid "publication \"%s\" specified more than once for --publication" +msgstr "Publikation »%s« mehrmals angegeben" -#: pg_createsubscriber.c:1901 +#: pg_createsubscriber.c:2183 #, fuzzy, c-format -#| msgid "duplicate option \"%s\"" -msgid "duplicate subscription \"%s\"" -msgstr "doppelte Option »%s«" +#| msgid "replication slot \"%s\" specified more than once" +msgid "replication slot \"%s\" specified more than once for --replication-slot" +msgstr "Replikations-Slot »%s« mehrmals angegeben" -#: pg_createsubscriber.c:1924 +#: pg_createsubscriber.c:2192 #, fuzzy, c-format -#| msgid "no data directory specified" +#| msgid "subscription \"%s\" specified more than once" +msgid "subscription \"%s\" specified more than once for --subscription" +msgstr "Subskription »%s« mehrmals angegeben" + +#: pg_createsubscriber.c:2217 +#, fuzzy, c-format +#| msgid "COPY %s cannot be used with %s" +msgid "%s cannot be used with -a/--all" +msgstr "COPY %s kann nicht mit %s verwendet werden" + +#: pg_createsubscriber.c:2235 +#, c-format msgid "no subscriber data directory specified" -msgstr "kein Datenverzeichnis angegeben" +msgstr "kein Datenverzeichnis für Subskriptionsserver angegeben" -#: pg_createsubscriber.c:1935 +#: pg_createsubscriber.c:2246 #, c-format msgid "could not determine current directory" msgstr "konnte aktuelles Verzeichnis nicht ermitteln" -#: pg_createsubscriber.c:1952 -#, fuzzy, c-format -#| msgid "could not parse connection string: %s" +#: pg_createsubscriber.c:2263 +#, c-format msgid "no publisher connection string specified" -msgstr "konnte Verbindungsparameter nicht interpretieren: %s" +msgstr "keine Verbindungsparameter für Publikationsserver angegeben" -#: pg_createsubscriber.c:1956 -#, fuzzy, c-format -#| msgid "invalid connection string syntax: %s" -msgid "validating connection string on publisher" -msgstr "ungültige Syntax für Verbindungszeichenkette: %s" +#: pg_createsubscriber.c:2267 +#, c-format +msgid "validating publisher connection string" +msgstr "validiere Verbindungsparameter für Publikationsserver" -#: pg_createsubscriber.c:1962 -#, fuzzy, c-format -#| msgid "invalid connection string syntax: %s" -msgid "validating connection string on subscriber" -msgstr "ungültige Syntax für Verbindungszeichenkette: %s" +#: pg_createsubscriber.c:2273 +#, c-format +msgid "validating subscriber connection string" +msgstr "validiere Verbindungsparameter für Subskriptionsserver" -#: pg_createsubscriber.c:1967 -#, fuzzy, c-format -#| msgid "no database specified" +#: pg_createsubscriber.c:2290 +#, c-format msgid "no database was specified" -msgstr "keine Datenbank angegeben" +msgstr "keine Datenbank wurde angegeben" -#: pg_createsubscriber.c:1979 -#, fuzzy, c-format -#| msgid "database \"%s\" is not currently accepting connections" -msgid "database \"%s\" was extracted from the publisher connection string" -msgstr "Datenbank »%s« akzeptiert gegenwärtig keine Verbindungen" +#: pg_createsubscriber.c:2301 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "Datenbankname »%s« wurde aus der Verbindungszeichenkette des Publikationsservers extrahiert" -#: pg_createsubscriber.c:1984 -#, fuzzy, c-format -#| msgid "no database specified" +#: pg_createsubscriber.c:2306 +#, c-format msgid "no database name specified" -msgstr "keine Datenbank angegeben" +msgstr "kein Datenbankname angegeben" -#: pg_createsubscriber.c:1994 -#, fuzzy, c-format -#| msgid "must be owner of publication %s" -msgid "wrong number of publication names" -msgstr "Berechtigung nur für Eigentümer der Publikation %s" +#: pg_createsubscriber.c:2316 +#, c-format +msgid "wrong number of publication names specified" +msgstr "falsche Anzahl Publikationsnamen angegeben" -#: pg_createsubscriber.c:1995 -#, fuzzy, c-format -#| msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" -msgid "Number of publication names (%d) must match number of database names (%d)." -msgstr "Anzahl der Partitionierungsspalten (%d) stimmt nicht mit der Anzahl der angegebenen Partitionierungsschlüssel (%d) überein" +#: pg_createsubscriber.c:2317 +#, c-format +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "Die Anzahl der angegebenen Publikationsnamen (%d) muss mit der Anzahl der angegebenen Datenbanknamen (%d) übereinstimmen." -#: pg_createsubscriber.c:2001 -#, fuzzy, c-format -#| msgid "wrong number of array subscripts" -msgid "wrong number of subscription names" -msgstr "falsche Anzahl Arrayindizes" +#: pg_createsubscriber.c:2323 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "falsche Anzahl Subskriptionsnamen angegeben" -#: pg_createsubscriber.c:2002 -#, fuzzy, c-format -#| msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" -msgid "Number of subscription names (%d) must match number of database names (%d)." -msgstr "Anzahl der Partitionierungsspalten (%d) stimmt nicht mit der Anzahl der angegebenen Partitionierungsschlüssel (%d) überein" +#: pg_createsubscriber.c:2324 +#, c-format +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "Die Anzahl der angegebenen Subskriptionsnamen (%d) muss mit der Anzahl der angegebenen Datenbanknamen (%d) übereinstimmen." -#: pg_createsubscriber.c:2008 -#, fuzzy, c-format -#| msgid "dropping replication slot \"%s\"" -msgid "wrong number of replication slot names" -msgstr "lösche Replikations-Slot »%s«" +#: pg_createsubscriber.c:2330 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "falsche Anzahl Replikations-Slot-Namen angegeben" + +#: pg_createsubscriber.c:2331 +#, c-format +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "Die Anzahl der angegebenen Replikations-Slot-Namen (%d) muss mit der Anzahl der angegebenen Datenbanknamen (%d) übereinstimmen." -#: pg_createsubscriber.c:2009 +#: pg_createsubscriber.c:2343 #, fuzzy, c-format -#| msgid "number of partitioning columns (%d) does not match number of partition keys provided (%d)" -msgid "Number of replication slot names (%d) must match number of database names (%d)." -msgstr "Anzahl der Partitionierungsspalten (%d) stimmt nicht mit der Anzahl der angegebenen Partitionierungsschlüssel (%d) überein" +#| msgid "invalid output format \"%s\" specified" +msgid "invalid object type \"%s\" specified for -R/--remove" +msgstr "ungültiges Ausgabeformat »%s« angegeben" -#: pg_createsubscriber.c:2038 +#: pg_createsubscriber.c:2344 #, fuzzy, c-format -#| msgid "Finding the real data directory for the source cluster" +#| msgid "reading publications" +msgid "The valid option is: \"publications\"" +msgstr "lese Publikationen" + +#: pg_createsubscriber.c:2375 +#, c-format msgid "subscriber data directory is not a copy of the source database cluster" -msgstr "Suche das tatsächliche Datenverzeichnis des alten Clusters" +msgstr "Datenverzeichnis des Subskriptionsservers ist keine Kopie des Quelldatenbankclusters" -#: pg_createsubscriber.c:2051 +#: pg_createsubscriber.c:2388 #, c-format -msgid "standby is up and running" -msgstr "" +msgid "standby server is running" +msgstr "Standby-Server läuft" -#: pg_createsubscriber.c:2052 +#: pg_createsubscriber.c:2389 #, c-format -msgid "Stop the standby and try again." -msgstr "" +msgid "Stop the standby server and try again." +msgstr "Halten Sie den Standby-Server an und versuchen Sie erneut." -#: pg_createsubscriber.c:2061 +#: pg_createsubscriber.c:2398 #, c-format -msgid "starting the standby with command-line options" -msgstr "" +msgid "starting the standby server with command-line options" +msgstr "starte den Standby-Server mit Kommandozeilenoptionen" -#: pg_createsubscriber.c:2077 pg_createsubscriber.c:2116 +#: pg_createsubscriber.c:2414 pg_createsubscriber.c:2449 #, c-format msgid "stopping the subscriber" -msgstr "" +msgstr "stoppe den Subskriptionsserver" -#: pg_createsubscriber.c:2095 +#: pg_createsubscriber.c:2428 #, c-format msgid "starting the subscriber" msgstr "starte den Subskriptionsserver" -#: pg_createsubscriber.c:2124 +#: pg_createsubscriber.c:2457 #, c-format msgid "Done!" msgstr "Fertig!" @@ -2013,17 +2035,17 @@ msgstr "" msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=VERZ Write-Ahead-Log-Dateien in dieses Verzeichnis empfangen\n" -#: pg_receivewal.c:83 pg_recvlogical.c:93 +#: pg_receivewal.c:83 pg_recvlogical.c:92 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN nach Empfang der angegebenen LSN beenden\n" -#: pg_receivewal.c:84 pg_recvlogical.c:97 +#: pg_receivewal.c:84 pg_recvlogical.c:98 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr " --if-not-exists keinen Fehler ausgeben, wenn Slot beim Erzeugen schon existiert\n" -#: pg_receivewal.c:85 pg_recvlogical.c:99 +#: pg_receivewal.c:85 pg_recvlogical.c:100 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop bei Verbindungsverlust nicht erneut probieren\n" @@ -2035,7 +2057,7 @@ msgstr "" " --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n" " geschrieben sind\n" -#: pg_receivewal.c:87 pg_recvlogical.c:104 +#: pg_receivewal.c:87 pg_recvlogical.c:105 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -2067,12 +2089,12 @@ msgstr "" "\n" "Optionale Aktionen:\n" -#: pg_receivewal.c:104 pg_recvlogical.c:89 +#: pg_receivewal.c:104 pg_recvlogical.c:88 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr " --create-slot neuen Replikations-Slot erzeugen (Slot-Name siehe --slot)\n" -#: pg_receivewal.c:105 pg_recvlogical.c:90 +#: pg_receivewal.c:105 pg_recvlogical.c:89 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr " --drop-slot Replikations-Slot löschen (Slot-Name siehe --slot)\n" @@ -2092,7 +2114,7 @@ msgstr "Log-Streaming gestoppt bei %X/%X (Zeitleiste %u)" msgid "switched to timeline %u at %X/%X" msgstr "auf Zeitleiste %u umgeschaltet bei %X/%X" -#: pg_receivewal.c:224 pg_recvlogical.c:1053 +#: pg_receivewal.c:224 pg_recvlogical.c:1073 #, c-format msgid "received interrupt signal, exiting" msgstr "Interrupt-Signal erhalten, beende" @@ -2162,7 +2184,7 @@ msgstr "kann Datei »%s« nicht prüfen: Komprimierung mit %s wird von dieser In msgid "starting log streaming at %X/%X (timeline %u)" msgstr "starte Log-Streaming bei %X/%X (Zeitleiste %u)" -#: pg_receivewal.c:693 pg_recvlogical.c:801 +#: pg_receivewal.c:693 pg_recvlogical.c:807 #, c-format msgid "could not parse end position \"%s\"" msgstr "konnte Endposition »%s« nicht parsen" @@ -2192,28 +2214,28 @@ msgstr "Komprimierung mit %s wird noch nicht unterstützt" msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "Replikationsverbindung, die Slot »%s« verwendet, ist unerwarteterweise datenbankspezifisch" -#: pg_receivewal.c:878 pg_recvlogical.c:972 +#: pg_receivewal.c:878 pg_recvlogical.c:991 #, c-format msgid "dropping replication slot \"%s\"" msgstr "lösche Replikations-Slot »%s«" -#: pg_receivewal.c:889 pg_recvlogical.c:982 +#: pg_receivewal.c:889 pg_recvlogical.c:1001 #, c-format msgid "creating replication slot \"%s\"" msgstr "erzeuge Replikations-Slot »%s«" -#: pg_receivewal.c:918 pg_recvlogical.c:1006 +#: pg_receivewal.c:918 pg_recvlogical.c:1026 #, c-format msgid "disconnected" msgstr "Verbindung beendet" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:1010 +#: pg_receivewal.c:922 pg_recvlogical.c:1030 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "Verbindung beendet; erneuter Versuch in %d Sekunden" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:83 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -2222,7 +2244,7 @@ msgstr "" "%s kontrolliert logische Dekodierungsströme von PostgreSQL.\n" "\n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:87 #, c-format msgid "" "\n" @@ -2231,17 +2253,29 @@ msgstr "" "\n" "Auszuführende Aktion:\n" -#: pg_recvlogical.c:91 +#: pg_recvlogical.c:90 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr " --start Streaming in einem Replikations-Slot starten (Slot-Name siehe --slot)\n" -#: pg_recvlogical.c:94 +#: pg_recvlogical.c:93 +#, fuzzy, c-format +#| msgid "" +#| " --includedir show location of C header files of the client\n" +#| " interfaces\n" +msgid "" +" --failover enable replication slot synchronization to standby servers when\n" +" creating a slot\n" +msgstr "" +" --includedir zeige Installationsverzeichnis der Headerdateien der\n" +" Client-Schnittstellen\n" + +#: pg_recvlogical.c:95 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=DATEI Log in diese Datei empfangen, - für Standardausgabe\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:96 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -2250,12 +2284,12 @@ msgstr "" " -F --fsync-interval=SEK\n" " Zeit zwischen Fsyncs der Ausgabedatei (Standard: %d)\n" -#: pg_recvlogical.c:98 +#: pg_recvlogical.c:99 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN wo in einem bestehenden Slot das Streaming starten soll\n" -#: pg_recvlogical.c:100 +#: pg_recvlogical.c:101 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -2266,282 +2300,287 @@ msgstr "" " Option NAME mit optionalem Wert WERT an den\n" " Ausgabe-Plugin übergeben\n" -#: pg_recvlogical.c:103 +#: pg_recvlogical.c:104 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN Ausgabe-Plugin PLUGIN verwenden (Standard: %s)\n" -#: pg_recvlogical.c:106 +#: pg_recvlogical.c:107 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOTNAME Name des logischen Replikations-Slots\n" -#: pg_recvlogical.c:107 +#: pg_recvlogical.c:108 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr "" " -t, --two-phase Dekodieren von vorbereiteten Transaktionen beim Erzeugen\n" " eines Slots einschalten\n" -#: pg_recvlogical.c:112 +#: pg_recvlogical.c:113 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=DBNAME Datenbank, mit der verbunden werden soll\n" -#: pg_recvlogical.c:145 +#: pg_recvlogical.c:146 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "bestätige Schreiben bis %X/%X, Flush bis %X/%X (Slot %s)" -#: pg_recvlogical.c:169 receivelog.c:360 +#: pg_recvlogical.c:170 receivelog.c:359 #, c-format msgid "could not send feedback packet: %s" msgstr "konnte Rückmeldungspaket nicht senden: %s" -#: pg_recvlogical.c:239 +#: pg_recvlogical.c:240 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "starte Log-Streaming bei %X/%X (Slot %s)" -#: pg_recvlogical.c:281 +#: pg_recvlogical.c:282 #, c-format msgid "streaming initiated" msgstr "Streaming eingeleitet" -#: pg_recvlogical.c:346 +#: pg_recvlogical.c:347 #, c-format msgid "could not open log file \"%s\": %m" msgstr "konnte Logdatei »%s« nicht öffnen: %m" -#: pg_recvlogical.c:375 receivelog.c:882 +#: pg_recvlogical.c:376 receivelog.c:889 #, c-format msgid "invalid socket: %s" msgstr "ungültiges Socket: %s" -#: pg_recvlogical.c:428 receivelog.c:910 +#: pg_recvlogical.c:429 receivelog.c:917 #, c-format msgid "%s() failed: %m" msgstr "%s() fehlgeschlagen: %m" -#: pg_recvlogical.c:435 receivelog.c:959 +#: pg_recvlogical.c:436 receivelog.c:966 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "konnte keine Daten vom WAL-Stream empfangen: %s" -#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 -#: receivelog.c:1066 +#: pg_recvlogical.c:478 pg_recvlogical.c:529 receivelog.c:1010 +#: receivelog.c:1073 #, c-format msgid "streaming header too small: %d" msgstr "Streaming-Header zu klein: %d" -#: pg_recvlogical.c:512 receivelog.c:843 +#: pg_recvlogical.c:513 receivelog.c:846 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "unbekannter Streaming-Header: »%c«" -#: pg_recvlogical.c:566 pg_recvlogical.c:578 +#: pg_recvlogical.c:567 pg_recvlogical.c:579 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "konnte %d Bytes nicht in Logdatei »%s« schreiben: %m" -#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:637 receivelog.c:641 receivelog.c:678 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "unerwarteter Abbruch des Replikations-Streams: %s" -#: pg_recvlogical.c:796 +#: pg_recvlogical.c:802 #, c-format msgid "could not parse start position \"%s\"" msgstr "konnte Startposition »%s« nicht parsen" -#: pg_recvlogical.c:874 +#: pg_recvlogical.c:880 #, c-format msgid "no slot specified" msgstr "kein Slot angegeben" -#: pg_recvlogical.c:881 +#: pg_recvlogical.c:887 #, c-format msgid "no target file specified" msgstr "keine Zieldatei angegeben" -#: pg_recvlogical.c:888 +#: pg_recvlogical.c:894 #, c-format msgid "no database specified" msgstr "keine Datenbank angegeben" -#: pg_recvlogical.c:895 +#: pg_recvlogical.c:901 #, c-format msgid "at least one action needs to be specified" msgstr "mindestens eine Aktion muss angegeben werden" -#: pg_recvlogical.c:902 +#: pg_recvlogical.c:908 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "--create-slot oder --start kann nicht zusammen mit --drop-slot verwendet werden" -#: pg_recvlogical.c:909 +#: pg_recvlogical.c:915 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "--create-slot oder --drop-slot kann nicht zusammen mit --startpos verwendet werden" -#: pg_recvlogical.c:916 +#: pg_recvlogical.c:922 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos kann nur zusammen mit --start angegeben werden" -#: pg_recvlogical.c:923 +#: pg_recvlogical.c:931 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase kann nur zusammen mit --create-slot angegeben werden" -#: pg_recvlogical.c:956 +#: pg_recvlogical.c:938 +#, c-format +msgid "--failover may only be specified with --create-slot" +msgstr "--failover kann nur zusammen mit --create-slot angegeben werden" + +#: pg_recvlogical.c:975 #, c-format msgid "could not establish database-specific replication connection" msgstr "konnte keine datenbankspezifische Replikationsverbindung herstellen" -#: pg_recvlogical.c:1056 +#: pg_recvlogical.c:1076 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "Endposition %X/%X durch Keepalive erreicht" -#: pg_recvlogical.c:1061 +#: pg_recvlogical.c:1081 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "Endposition %X/%X erreicht durch WAL-Eintrag bei %X/%X" -#: receivelog.c:66 +#: receivelog.c:65 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "konnte Archivstatusdatei »%s« nicht erstellen: %s" -#: receivelog.c:73 +#: receivelog.c:72 #, c-format msgid "could not close archive status file \"%s\": %s" msgstr "konnte Archivstatusdatei »%s« nicht schließen: %s" -#: receivelog.c:122 +#: receivelog.c:121 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "konnte Größe der Write-Ahead-Log-Datei »%s« nicht ermittlen: %s" -#: receivelog.c:133 +#: receivelog.c:132 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "konnte bestehende Write-Ahead-Log-Datei »%s« nicht öffnen: %s" -#: receivelog.c:142 +#: receivelog.c:141 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "konnte bestehende Write-Ahead-Log-Datei »%s« nicht fsyncen: %s" -#: receivelog.c:157 +#: receivelog.c:156 #, c-format msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" msgstr[0] "Write-Ahead-Log-Datei »%s« hat %zd Byte, sollte 0 oder %d sein" msgstr[1] "Write-Ahead-Log-Datei »%s« hat %zd Bytes, sollte 0 oder %d sein" -#: receivelog.c:175 +#: receivelog.c:174 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "konnte Write-Ahead-Log-Datei »%s« nicht öffnen: %s" -#: receivelog.c:216 +#: receivelog.c:215 #, c-format msgid "not renaming \"%s\", segment is not complete" msgstr "»%s« wird nicht umbenannt, Segment ist noch nicht vollständig" -#: receivelog.c:227 receivelog.c:317 receivelog.c:688 +#: receivelog.c:226 receivelog.c:316 receivelog.c:687 #, c-format msgid "could not close file \"%s\": %s" msgstr "konnte Datei »%s« nicht schließen: %s" -#: receivelog.c:288 +#: receivelog.c:287 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "Server berichtete unerwarteten History-Dateinamen für Zeitleiste %u: %s" -#: receivelog.c:297 +#: receivelog.c:296 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "konnte Zeitleisten-History-Datei »%s« nicht erzeugen: %s" -#: receivelog.c:304 +#: receivelog.c:303 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "konnte Zeitleisten-History-Datei »%s« nicht schreiben: %s" -#: receivelog.c:394 +#: receivelog.c:393 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions older than %s" msgstr "inkompatible Serverversion %s; Client unterstützt Streaming nicht mit Serverversionen älter als %s" -#: receivelog.c:403 +#: receivelog.c:402 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions newer than %s" msgstr "inkompatible Serverversion %s; Client unterstützt Streaming nicht mit Serverversionen neuer als %s" -#: receivelog.c:508 +#: receivelog.c:507 #, c-format msgid "system identifier does not match between base backup and streaming connection" msgstr "Systemidentifikator stimmt nicht zwischen Basissicherung und Streaming-Verbindung überein" -#: receivelog.c:516 +#: receivelog.c:515 #, c-format msgid "starting timeline %u is not present in the server" msgstr "Startzeitleiste %u ist auf dem Server nicht vorhanden" -#: receivelog.c:555 +#: receivelog.c:554 #, c-format msgid "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, expected %d rows and %d fields" msgstr "unerwartete Antwort auf Befehl TIMELINE_HISTORY: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" -#: receivelog.c:626 +#: receivelog.c:625 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "Server berichtete unerwartete nächste Zeitleiste %u, folgend auf Zeitleiste %u" -#: receivelog.c:632 +#: receivelog.c:631 #, c-format msgid "server stopped streaming timeline %u at %X/%X, but reported next timeline %u to begin at %X/%X" msgstr "Server beendete Streaming von Zeitleiste %u bei %X/%X, aber gab an, dass nächste Zeitleiste %u bei %X/%X beginnt" -#: receivelog.c:672 +#: receivelog.c:671 #, c-format msgid "replication stream was terminated before stop point" msgstr "Replikationsstrom wurde vor Stopppunkt abgebrochen" -#: receivelog.c:718 +#: receivelog.c:717 #, c-format msgid "unexpected result set after end-of-timeline: got %d rows and %d fields, expected %d rows and %d fields" msgstr "unerwartete Ergebnismenge nach Ende der Zeitleiste: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" -#: receivelog.c:727 +#: receivelog.c:726 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "konnte Startpunkt der nächsten Zeitleiste (»%s«) nicht interpretieren" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 +#: receivelog.c:774 receivelog.c:1029 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "konnte Datei »%s« nicht fsyncen: %s" -#: receivelog.c:1083 +#: receivelog.c:1090 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "Write-Ahead-Log-Eintrag für Offset %u erhalten ohne offene Datei" -#: receivelog.c:1093 +#: receivelog.c:1100 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "WAL-Daten-Offset %08x erhalten, %08x erwartet" -#: receivelog.c:1128 +#: receivelog.c:1135 #, c-format msgid "could not write %d bytes to WAL file \"%s\": %s" msgstr "konnte %d Bytes nicht in WAL-Datei »%s« schreiben: %s" -#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 +#: receivelog.c:1160 receivelog.c:1200 receivelog.c:1228 #, c-format msgid "could not send copy-end packet: %s" msgstr "konnte COPY-Ende-Paket nicht senden: %s" @@ -2555,11 +2594,6 @@ msgstr "Passwort: " msgid "could not connect to server" msgstr "konnte nicht mit Server verbinden" -#: streamutil.c:230 -#, c-format -msgid "could not clear \"search_path\": %s" -msgstr "konnte »search_path« nicht auf leer setzen: %s" - #: streamutil.c:246 #, c-format msgid "could not determine server setting for \"integer_datetimes\"" @@ -2570,69 +2604,69 @@ msgstr "konnte Servereinstellung für »integer_datetimes« nicht ermitteln" msgid "\"integer_datetimes\" compile flag does not match server" msgstr "Kompilieroption »integer_datetimes« stimmt nicht mit Server überein" -#: streamutil.c:372 +#: streamutil.c:304 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "konnte WAL-Segmentgröße nicht ermitteln: %d Zeilen und %d Felder erhalten, %d Zeilen und %d oder mehr Felder erwartet" -#: streamutil.c:382 +#: streamutil.c:314 #, c-format msgid "WAL segment size could not be parsed" msgstr "WAL-Segmentgröße konnte nicht interpretiert werden" -#: streamutil.c:400 +#: streamutil.c:332 #, c-format msgid "remote server reported invalid WAL segment size (%d byte)" msgid_plural "remote server reported invalid WAL segment size (%d bytes)" msgstr[0] "Server meldete ungültige WAL-Segmentgröße (%d Byte)" msgstr[1] "Server meldete ungültige WAL-Segmentgröße (%d Bytes)" -#: streamutil.c:404 +#: streamutil.c:336 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "Die WAL-Segmentgröße muss eine Zweierpotenz zwischen 1 MB und 1 GB sein." -#: streamutil.c:446 +#: streamutil.c:378 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "konnte Gruppenzugriffseinstellung nicht ermitteln: %d Zeilen und %d Felder erhalten, %d Zeilen und %d oder mehr Felder erwartet" -#: streamutil.c:455 +#: streamutil.c:387 #, c-format msgid "group access flag could not be parsed: %s" msgstr "Gruppenzugriffseinstellung konnte nicht interpretiert werden: %s" -#: streamutil.c:498 streamutil.c:535 +#: streamutil.c:430 streamutil.c:467 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "Konnte System nicht identifizieren: %d Zeilen und %d Felder erhalten, %d Zeilen und %d oder mehr Felder erwartet" -#: streamutil.c:587 +#: streamutil.c:519 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "konnte Replikations-Slot »%s« nicht lesen: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" -#: streamutil.c:599 +#: streamutil.c:531 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "Replikations-Slot »%s« existiert nicht" -#: streamutil.c:610 +#: streamutil.c:542 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "physischer Replikations-Slot wurde erwartet, stattdessen wurde Typ »%s« erhalten" -#: streamutil.c:624 +#: streamutil.c:556 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "konnte restart_lsn »%s« für Replikations-Slot »%s« nicht parsen" -#: streamutil.c:741 +#: streamutil.c:678 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "konnte Replikations-Slot »%s« nicht erzeugen: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" -#: streamutil.c:785 +#: streamutil.c:722 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "konnte Replikations-Slot »%s« nicht löschen: %d Zeilen und %d Felder erhalten, %d Zeilen und %d Felder erwartet" diff --git a/src/bin/pg_basebackup/po/es.po b/src/bin/pg_basebackup/po/es.po index 1148c0b46b9dc..b637026541f0e 100644 --- a/src/bin/pg_basebackup/po/es.po +++ b/src/bin/pg_basebackup/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_basebackup (PostgreSQL) 16\n" +"Project-Id-Version: pg_basebackup (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:19+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:49+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -70,9 +70,8 @@ msgstr "el valor para la opción de compresión «%s» debe ser un entero" #: ../../common/compression.c:331 #, c-format -#| msgid "value for compression option \"%s\" must be a boolean" msgid "value for compression option \"%s\" must be a Boolean value" -msgstr "el valor para la opción de compresión «%s» debe ser booleano" +msgstr "el valor para la opción de compresión «%s» debe ser un booleano" #: ../../common/compression.c:379 #, c-format @@ -94,6 +93,65 @@ msgstr "el algoritmo de compresión «%s» no acepta una cantidad de procesos ay msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "el algoritmo de compresión «%s» no acepta modo de larga distancia" +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "no se pudo cerrar el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"posible discordancia en orden de bytes\n" +"El ordenamiento de bytes usado para almacenar el archivo pg_control puede no\n" +"coincidir con el usado por este programa. En tal caso los resultados de abajo\n" +"serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" +"directorio de datos." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "no se pudo escribir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -105,39 +163,69 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 -#: pg_receivewal.c:319 pg_recvlogical.c:339 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "no se pudo hacer stat al archivo «%s»: %m" -#: ../../common/file_utils.c:162 pg_receivewal.c:242 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: ../../common/file_utils.c:196 pg_receivewal.c:471 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "no se pudo leer el directorio «%s»: %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 ../../fe_utils/recovery_gen.c:121 -#: pg_receivewal.c:386 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 -#: pg_recvlogical.c:194 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" +msgid "could not open process token: error code %lu" +msgstr "no se pudo abrir el token de proceso: código de error %lu" -#: ../../common/file_utils.c:379 pg_basebackup.c:2237 walmethods.c:462 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "no se pudo emplazar los SIDs: código de error %lu" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "no se pudo crear el token restringido: código de error %lu" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "no se pudo iniciar el proceso para la orden «%s»: código de error %lu" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "no se pudo re-ejecutar con el token restringido: código de error %lu" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "no se pudo obtener el código de salida del subproceso: código de error %lu" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -149,51 +237,62 @@ msgstr "el valor «%s» no es válido para la opción «%s»" msgid "%s must be in range %d..%d" msgstr "%s debe estar en el rango %d..%d" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 pg_basebackup.c:1609 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método de sync no reconocido: «%s»" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:334 #, c-format msgid "out of memory" msgstr "memoria agotada" -#: ../../fe_utils/recovery_gen.c:124 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1406 pg_basebackup.c:1700 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "no se pudo escribir a archivo «%s»: %m" -#: ../../fe_utils/recovery_gen.c:133 bbstreamer_file.c:93 bbstreamer_file.c:360 -#: pg_basebackup.c:1470 pg_basebackup.c:1679 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "no se pudo crear archivo «%s»: %m" -#: bbstreamer_file.c:138 pg_recvlogical.c:633 +#: ../../fe_utils/string_utils.c:587 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "no se pudo cerrar el archivo «%s»: %m" +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" #: bbstreamer_file.c:275 #, c-format msgid "unexpected state while extracting archive" msgstr "estado inesperado mientras se extraía el archivo" -#: bbstreamer_file.c:320 pg_basebackup.c:686 pg_basebackup.c:730 +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 #, c-format msgid "could not create directory \"%s\": %m" msgstr "no se pudo crear el directorio «%s»: %m" -#: bbstreamer_file.c:325 +#: bbstreamer_file.c:326 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "no se pudo definir los permisos del directorio «%s»: %m" -#: bbstreamer_file.c:344 +#: bbstreamer_file.c:345 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "no se pudo crear un enlace simbólico desde «%s» a «%s»: %m" -#: bbstreamer_file.c:364 +#: bbstreamer_file.c:365 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "no se pudo definir los permisos al archivo «%s»: %m" @@ -228,7 +327,7 @@ msgstr "no se pudo escribir al archivo comprimido «%s»: %s" msgid "could not close compressed file \"%s\": %m" msgstr "no se pudo cerrar el archivo comprimido «%s»: %m" -#: bbstreamer_gzip.c:245 walmethods.c:876 +#: bbstreamer_gzip.c:245 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "no se pudo inicializar la biblioteca de compresión" @@ -278,12 +377,12 @@ msgstr "la terminación del archivo tar excede de 2 bloques" msgid "unexpected state while parsing tar archive" msgstr "se encontró un estado inesperado mientras se interpretaba el archivo tar" -#: bbstreamer_tar.c:296 +#: bbstreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "miembro de tar tiene nombre vacío" -#: bbstreamer_tar.c:328 +#: bbstreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "el flujo COPY terminó antes que el último archivo estuviera completo" @@ -305,115 +404,117 @@ msgstr "no se pudo definir la cantidad de procesos ayudantes de compresión a %d #: bbstreamer_zstd.c:116 #, c-format -#| msgid "could not enable user right \"%s\"" msgid "could not enable long-distance mode: %s" -msgstr "no se pudo habilitar el modo “long-distance”: %s" +msgstr "no se pudo habilitar el modo de larga distancia: %s" #: bbstreamer_zstd.c:275 #, c-format msgid "could not create zstd decompression context" msgstr "no se pudo crear el contexto de descompresión zstd" -#: pg_basebackup.c:238 +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "eliminando el directorio de datos «%s»" -#: pg_basebackup.c:240 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "no se pudo eliminar el directorio de datos" -#: pg_basebackup.c:244 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "eliminando el contenido del directorio «%s»" -#: pg_basebackup.c:246 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "no se pudo eliminar el contenido del directorio de datos" -#: pg_basebackup.c:251 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "eliminando el directorio de WAL «%s»" -#: pg_basebackup.c:253 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "no se pudo eliminar el directorio de WAL" -#: pg_basebackup.c:257 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "eliminando el contenido del directorio de WAL «%s»" -#: pg_basebackup.c:259 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "no se pudo eliminar el contenido del directorio de WAL" -#: pg_basebackup.c:265 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "directorio de datos «%s» no eliminado a petición del usuario" -#: pg_basebackup.c:268 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "directorio de WAL «%s» no eliminado a petición del usuario" -#: pg_basebackup.c:272 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "los cambios a los directorios de tablespaces no se desharán" -#: pg_basebackup.c:324 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "nombre de directorio demasiado largo" -#: pg_basebackup.c:331 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "múltiples signos «=» en mapeo de tablespace" -#: pg_basebackup.c:340 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "formato de mapeo de tablespace «%s» no válido, debe ser «ANTIGUO=NUEVO»" -#: pg_basebackup.c:359 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "directorio antiguo no es una ruta absoluta en mapeo de tablespace: %s" -#: pg_basebackup.c:363 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "directorio nuevo no es una ruta absoluta en mapeo de tablespace: %s" -#: pg_basebackup.c:385 +#: pg_basebackup.c:392 #, c-format msgid "" "%s takes a base backup of a running PostgreSQL server.\n" "\n" msgstr "" -"%s obtiene un respaldo base a partir de un servidor PostgreSQL en ejecución.\n" +"%s obtiene un respaldo base a partir de un servidor PostgreSQL\n" +"en ejecución.\n" "\n" -#: pg_basebackup.c:387 pg_receivewal.c:79 pg_recvlogical.c:76 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_basebackup.c:388 pg_receivewal.c:80 pg_recvlogical.c:77 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPCIÓN]...\n" -#: pg_basebackup.c:389 +#: pg_basebackup.c:396 #, c-format msgid "" "\n" @@ -422,17 +523,26 @@ msgstr "" "\n" "Opciones que controlan la salida:\n" -#: pg_basebackup.c:390 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" msgstr " -D, --pgdata=DIR directorio en el cual recibir el respaldo base\n" -#: pg_basebackup.c:391 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr " -F, --format=p|t formato de salida (plano (por omisión), tar)\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:399 +#, c-format +msgid "" +" -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr "" +" -i, --incremental=MANIFIESTOANTIGUO\n" +" tomar respaldo base incremental\n" + +#: pg_basebackup.c:401 #, c-format msgid "" " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" @@ -441,7 +551,7 @@ msgstr "" " -r, --max-rate=TASA máxima tasa a la que transferir el directorio de datos\n" " (en kB/s, o use sufijos «k» o «M»)\n" -#: pg_basebackup.c:394 +#: pg_basebackup.c:403 #, c-format msgid "" " -R, --write-recovery-conf\n" @@ -450,7 +560,7 @@ msgstr "" " -R, --write-recovery-conf\n" " escribe configuración para replicación\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:405 #, c-format msgid "" " -t, --target=TARGET[:DETAIL]\n" @@ -459,7 +569,7 @@ msgstr "" " -t, --target=DESTINO:[DETALLE]\n" " destino del respaldo base (si no es el cliente)\n" -#: pg_basebackup.c:398 +#: pg_basebackup.c:407 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -468,12 +578,12 @@ msgstr "" " -T, --tablespace-mapping=ANTIGUO=NUEVO\n" " reubicar el directorio de tablespace de ANTIGUO a NUEVO\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr " --waldir=DIRWAL ubicación para el directorio WAL\n" -#: pg_basebackup.c:401 +#: pg_basebackup.c:410 #, c-format msgid "" " -X, --wal-method=none|fetch|stream\n" @@ -481,14 +591,14 @@ msgid "" msgstr "" " -X, --wal-method=none|fetch|stream\n" " incluye los archivos WAL necesarios,\n" -" en el modo especificado\n" +" usando el método especificado\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip comprimir la salida de tar\n" -#: pg_basebackup.c:404 +#: pg_basebackup.c:413 #, c-format msgid "" " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" @@ -497,12 +607,12 @@ msgstr "" " -Z, --compress=[{client|server}-]MÉTODO[:DETALLE]\n" " comprimir en cliente o servidor como se especifica\n" -#: pg_basebackup.c:406 +#: pg_basebackup.c:415 #, c-format msgid " -Z, --compress=none do not compress tar output\n" msgstr " -Z, --compress=none no comprimir la salida tar\n" -#: pg_basebackup.c:407 +#: pg_basebackup.c:416 #, c-format msgid "" "\n" @@ -511,89 +621,93 @@ msgstr "" "\n" "Opciones generales:\n" -#: pg_basebackup.c:408 +#: pg_basebackup.c:417 #, c-format msgid "" " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" +" set fast or spread (default) checkpointing\n" msgstr "" -" -c, --checkpoint=fast|spread\n" -" utilizar checkpoint rápido o extendido\n" +" -c, --checkpoint=spread|fast\n" +" utilizar checkpoint extendido (por omisión) o rápido\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " -C, --create-slot crear un slot de replicación\n" -#: pg_basebackup.c:411 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=ETIQUETA establecer etiqueta del respaldo\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean no hacer limpieza tras errores\n" -#: pg_basebackup.c:413 +#: pg_basebackup.c:422 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress mostrar información de progreso\n" -#: pg_basebackup.c:415 pg_receivewal.c:89 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=NOMBRE slot de replicación a usar\n" -#: pg_basebackup.c:416 pg_receivewal.c:91 pg_recvlogical.c:98 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose desplegar mensajes verbosos\n" -#: pg_basebackup.c:417 pg_receivewal.c:92 pg_recvlogical.c:99 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión, luego salir\n" -#: pg_basebackup.c:418 +#: pg_basebackup.c:427 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " use algorithm for manifest checksums\n" msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" -" usar algoritmo para sumas de comprobación del manifiesto\n" +" algoritmo a usar para \"checksums\" del manifiesto\n" -#: pg_basebackup.c:420 +#: pg_basebackup.c:429 #, c-format msgid "" " --manifest-force-encode\n" " hex encode all file names in manifest\n" msgstr "" -" --manifest-force-encode\n" -" codifica a hexadecimal todos los nombres de archivo en el manifiesto\n" +" --manifest-force-encode codifica a hexadecimal todos los nombres\n" +" de archivo en el manifiesto\n" -#: pg_basebackup.c:422 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" -msgstr " --no-estimate-size no estimar el tamaño del la copia de seguridad en el lado del servidor\n" +msgstr "" +" --no-estimate-size no estimar el tamaño de la copia de seguridad en\n" +" el lado del servidor\n" -#: pg_basebackup.c:423 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" -msgstr " --no-manifest suprimir la generación del manifiesto de la copia de seguridad\n" +msgstr "" +" --no-manifest suprimir la generación del manifiesto\n" +" de la copia de seguridad\n" -#: pg_basebackup.c:424 +#: pg_basebackup.c:433 #, c-format msgid " --no-slot prevent creation of temporary replication slot\n" msgstr " --no-slot evitar la creación de un slot de replicación temporal\n" -#: pg_basebackup.c:425 +#: pg_basebackup.c:434 #, c-format msgid "" " --no-verify-checksums\n" @@ -602,12 +716,19 @@ msgstr "" " --no-verify-checksums\n" " no verificar checksums\n" -#: pg_basebackup.c:427 pg_receivewal.c:95 pg_recvlogical.c:100 +#: pg_basebackup.c:436 +#, c-format +msgid "" +" --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método para sincronizar archivos a disco\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda, luego salir\n" -#: pg_basebackup.c:428 pg_receivewal.c:96 pg_recvlogical.c:101 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "" "\n" @@ -616,22 +737,22 @@ msgstr "" "\n" "Opciones de conexión:\n" -#: pg_basebackup.c:429 pg_receivewal.c:97 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CONSTR cadena de conexión\n" -#: pg_basebackup.c:430 pg_receivewal.c:98 pg_recvlogical.c:103 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=ANFITRIÓN dirección del servidor o directorio del socket\n" -#: pg_basebackup.c:431 pg_receivewal.c:99 pg_recvlogical.c:104 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT número de port del servidor\n" -#: pg_basebackup.c:432 +#: pg_basebackup.c:443 #, c-format msgid "" " -s, --status-interval=INTERVAL\n" @@ -640,24 +761,25 @@ msgstr "" " -s, --status-interval=INTERVALO (segundos)\n" " tiempo entre envíos de paquetes de estado al servidor\n" -#: pg_basebackup.c:434 pg_receivewal.c:100 pg_recvlogical.c:105 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NOMBRE conectarse con el usuario especificado\n" -#: pg_basebackup.c:435 pg_receivewal.c:101 pg_recvlogical.c:106 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir contraseña\n" -#: pg_basebackup.c:436 pg_receivewal.c:102 pg_recvlogical.c:107 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password forzar un prompt para la contraseña\n" " (debería ser automático)\n" -#: pg_basebackup.c:437 pg_receivewal.c:106 pg_recvlogical.c:108 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "" "\n" @@ -666,484 +788,549 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_basebackup.c:438 pg_receivewal.c:107 pg_recvlogical.c:109 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_basebackup.c:477 +#: pg_basebackup.c:488 #, c-format msgid "could not read from ready pipe: %m" msgstr "no se pudo leer desde la tubería: %m" -#: pg_basebackup.c:480 pg_basebackup.c:622 pg_basebackup.c:2151 -#: streamutil.c:441 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:521 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "no se pudo interpretar la ubicación del WAL «%s»" -#: pg_basebackup.c:585 pg_receivewal.c:600 +#: pg_basebackup.c:596 pg_receivewal.c:600 #, c-format msgid "could not finish writing WAL files: %m" msgstr "no se pudo completar la escritura de archivos WAL: %m" -#: pg_basebackup.c:631 +#: pg_basebackup.c:642 #, c-format msgid "could not create pipe for background process: %m" msgstr "no se pudo crear la tubería para el proceso en segundo plano: %m" -#: pg_basebackup.c:664 +#: pg_basebackup.c:676 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "se creó slot temporal de replicación «%s»" -#: pg_basebackup.c:667 +#: pg_basebackup.c:679 #, c-format msgid "created replication slot \"%s\"" msgstr "se creó el slot de replicación «%s»" -#: pg_basebackup.c:701 +#: pg_basebackup.c:728 #, c-format msgid "could not create background process: %m" msgstr "no se pudo lanzar el proceso en segundo plano: %m" -#: pg_basebackup.c:710 +#: pg_basebackup.c:737 #, c-format msgid "could not create background thread: %m" msgstr "no se pudo lanzar el hilo en segundo plano: %m" -#: pg_basebackup.c:749 +#: pg_basebackup.c:776 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "el directorio «%s» existe pero no está vacío" -#: pg_basebackup.c:755 +#: pg_basebackup.c:782 pg_createsubscriber.c:390 #, c-format msgid "could not access directory \"%s\": %m" msgstr "no se pudo acceder al directorio «%s»: %m" -#: pg_basebackup.c:831 +#: pg_basebackup.c:858 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s kB (100%%), %d/%d tablespace %*s" msgstr[1] "%*s/%s kB (100%%), %d/%d tablespaces %*s" -#: pg_basebackup.c:843 +#: pg_basebackup.c:870 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgstr[1] "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" -#: pg_basebackup.c:859 +#: pg_basebackup.c:886 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s kB (%d%%), %d/%d tablespace" msgstr[1] "%*s/%s kB (%d%%), %d/%d tablespaces" -#: pg_basebackup.c:883 +#: pg_basebackup.c:910 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "tasa de transferencia «%s» no es un valor válido" -#: pg_basebackup.c:885 +#: pg_basebackup.c:912 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "tasa de transferencia «%s» no válida: %m" -#: pg_basebackup.c:892 +#: pg_basebackup.c:919 #, c-format msgid "transfer rate must be greater than zero" msgstr "tasa de transferencia debe ser mayor que cero" -#: pg_basebackup.c:922 +#: pg_basebackup.c:949 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "unidad de --max-rato no válida: «%s»" -#: pg_basebackup.c:926 +#: pg_basebackup.c:953 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "la tasa de transferencia «%s» excede el rango de enteros" -#: pg_basebackup.c:933 +#: pg_basebackup.c:960 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "la tasa de transferencia «%s» está fuera de rango" -#: pg_basebackup.c:995 +#: pg_basebackup.c:1022 #, c-format msgid "could not get COPY data stream: %s" msgstr "no se pudo obtener un flujo de datos COPY: %s" -#: pg_basebackup.c:1012 pg_recvlogical.c:436 pg_recvlogical.c:608 +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 #: receivelog.c:973 #, c-format msgid "could not read COPY data: %s" msgstr "no fue posible leer datos COPY: %s" -#: pg_basebackup.c:1016 +#: pg_basebackup.c:1043 #, c-format msgid "background process terminated unexpectedly" msgstr "un proceso en segundo plano terminó inesperadamente" -#: pg_basebackup.c:1087 +#: pg_basebackup.c:1114 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "no se pueden inyectar un manifiesto en un archivo tar comprimido" -#: pg_basebackup.c:1088 +#: pg_basebackup.c:1115 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "Use compresión del lado del cliente, envíe la salida a un directorio en lugar de a salida estándar, o use %s." -#: pg_basebackup.c:1104 +#: pg_basebackup.c:1131 #, c-format msgid "cannot parse archive \"%s\"" msgstr "no se pudo interpretar el archivo «%s»" -#: pg_basebackup.c:1105 +#: pg_basebackup.c:1132 #, c-format msgid "Only tar archives can be parsed." msgstr "Sólo los archivos tar pueden ser interpretados." -#: pg_basebackup.c:1107 +#: pg_basebackup.c:1134 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "El formato plano requiere que pg_basebackup interprete el archivo." -#: pg_basebackup.c:1109 +#: pg_basebackup.c:1136 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "Usar - como directorio de salida requiere que pg_basebackup interprete el archivo." -#: pg_basebackup.c:1111 +#: pg_basebackup.c:1138 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "La opción -R requiere que pg_basebackup interprete el archivo." -#: pg_basebackup.c:1330 +#: pg_basebackup.c:1357 #, c-format msgid "archives must precede manifest" msgstr "los archivos deben preceder al manifiesto" -#: pg_basebackup.c:1345 +#: pg_basebackup.c:1372 #, c-format msgid "invalid archive name: \"%s\"" msgstr "nombre de archivo no válido: «%s»" -#: pg_basebackup.c:1417 +#: pg_basebackup.c:1444 #, c-format msgid "unexpected payload data" msgstr "datos inesperados" -#: pg_basebackup.c:1560 +#: pg_basebackup.c:1587 #, c-format msgid "empty COPY message" msgstr "mensaje COPY vacío" -#: pg_basebackup.c:1562 +#: pg_basebackup.c:1589 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "mensaje COPY mal formado de tipo %d, largo %zu" -#: pg_basebackup.c:1760 +#: pg_basebackup.c:1789 #, c-format msgid "incompatible server version %s" msgstr "versión del servidor %s incompatible" -#: pg_basebackup.c:1776 +#: pg_basebackup.c:1805 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "Use -X none o -X fetch para deshabilitar el flujo de log." -#: pg_basebackup.c:1844 +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "el servidor no soporta backup incremental" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:367 streamutil.c:441 +#: streamutil.c:493 streamutil.c:581 streamutil.c:733 streamutil.c:778 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "no se pudo ejecutar la orden de replicación «%s»: %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "no se pudo cargar el manifiesto: %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#, c-format +msgid "could not upload manifest: unexpected status %s" +msgstr "no se pudo cargar el manifiesto: estado inesperado %s" + +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "no fue posible enviar datos COPY: %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "no se pudo enviar fin-de-COPY: %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "conjunto de resultados inesperado mientras se enviaba el manifiesto" + +#: pg_basebackup.c:1950 #, c-format msgid "backup targets are not supported by this server version" msgstr "los destinos de respaldo no están soportados por esta versión de servidor" -#: pg_basebackup.c:1847 +#: pg_basebackup.c:1953 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "la configuración de recuperación no puede ser escrita cuando se usa un destino de respaldo base" -#: pg_basebackup.c:1874 +#: pg_basebackup.c:1980 #, c-format msgid "server does not support server-side compression" msgstr "el servidor no soporta compresión del lado del servidor" -#: pg_basebackup.c:1884 +#: pg_basebackup.c:1990 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "iniciando el respaldo base, esperando que el checkpoint se complete" -#: pg_basebackup.c:1888 +#: pg_basebackup.c:1994 #, c-format msgid "waiting for checkpoint" msgstr "esperando al checkpoint" -#: pg_basebackup.c:1901 pg_recvlogical.c:260 receivelog.c:543 receivelog.c:582 -#: streamutil.c:288 streamutil.c:361 streamutil.c:413 streamutil.c:501 -#: streamutil.c:653 streamutil.c:698 -#, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "no se pudo ejecutar la orden de replicación «%s»: %s" - -#: pg_basebackup.c:1909 +#: pg_basebackup.c:2016 #, c-format msgid "could not initiate base backup: %s" msgstr "no se pudo iniciar el respaldo base: %s" -#: pg_basebackup.c:1912 +#: pg_basebackup.c:2019 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "el servidor envió una respuesta inesperada a la orden BASE_BACKUP; se obtuvieron %d filas y %d campos, se esperaban %d filas y %d campos" -#: pg_basebackup.c:1918 +#: pg_basebackup.c:2025 #, c-format msgid "checkpoint completed" msgstr "el checkpoint se ha completado" -#: pg_basebackup.c:1932 +#: pg_basebackup.c:2039 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "punto de inicio del WAL: %s en el timeline %u" -#: pg_basebackup.c:1940 +#: pg_basebackup.c:2047 #, c-format msgid "could not get backup header: %s" msgstr "no se pudo obtener la cabecera de respaldo: %s" -#: pg_basebackup.c:1943 +#: pg_basebackup.c:2050 #, c-format msgid "no data returned from server" msgstr "el servidor no retornó datos" -#: pg_basebackup.c:1986 +#: pg_basebackup.c:2093 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "sólo se puede escribir un tablespace a stdout, la base de datos tiene %d" -#: pg_basebackup.c:1999 +#: pg_basebackup.c:2106 #, c-format msgid "starting background WAL receiver" msgstr "iniciando el receptor de WAL en segundo plano" -#: pg_basebackup.c:2082 +#: pg_basebackup.c:2189 #, c-format msgid "backup failed: %s" msgstr "el respaldo falló: %s" -#: pg_basebackup.c:2085 +#: pg_basebackup.c:2192 #, c-format msgid "no write-ahead log end position returned from server" msgstr "el servidor no retornó la posición final del WAL" -#: pg_basebackup.c:2088 +#: pg_basebackup.c:2195 #, c-format msgid "write-ahead log end point: %s" msgstr "posición final del WAL: %s" -#: pg_basebackup.c:2099 +#: pg_basebackup.c:2206 #, c-format msgid "checksum error occurred" msgstr "ocurrió un error de checksums" -#: pg_basebackup.c:2104 +#: pg_basebackup.c:2211 #, c-format msgid "final receive failed: %s" msgstr "la recepción final falló: %s" -#: pg_basebackup.c:2128 +#: pg_basebackup.c:2235 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "esperando que el proceso en segundo plano complete el flujo..." -#: pg_basebackup.c:2132 +#: pg_basebackup.c:2239 #, c-format msgid "could not send command to background pipe: %m" msgstr "no se pudo enviar una orden a la tubería de segundo plano: %m" -#: pg_basebackup.c:2137 +#: pg_basebackup.c:2244 #, c-format msgid "could not wait for child process: %m" msgstr "no se pudo esperar al proceso hijo: %m" -#: pg_basebackup.c:2139 +#: pg_basebackup.c:2246 #, c-format msgid "child %d died, expected %d" msgstr "el hijo %d murió, pero se esperaba al %d" -#: pg_basebackup.c:2141 streamutil.c:91 streamutil.c:196 +#: pg_basebackup.c:2248 streamutil.c:92 streamutil.c:207 streamutil.c:319 #, c-format msgid "%s" msgstr "%s" -#: pg_basebackup.c:2161 +#: pg_basebackup.c:2268 #, c-format msgid "could not wait for child thread: %m" msgstr "no se pudo esperar el hilo hijo: %m" -#: pg_basebackup.c:2166 +#: pg_basebackup.c:2273 #, c-format msgid "could not get child thread exit status: %m" msgstr "no se pudo obtener la cabecera de respaldo: %m" -#: pg_basebackup.c:2169 +#: pg_basebackup.c:2276 #, c-format msgid "child thread exited with error %u" msgstr "el hilo hijo terminó con error %u" -#: pg_basebackup.c:2198 +#: pg_basebackup.c:2305 #, c-format msgid "syncing data to disk ..." msgstr "sincronizando datos a disco ..." -#: pg_basebackup.c:2223 +#: pg_basebackup.c:2330 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "renombrando backup_manifest.tmp a backup_manifest" -#: pg_basebackup.c:2243 +#: pg_basebackup.c:2350 #, c-format msgid "base backup completed" msgstr "el respaldo base se ha completado" -#: pg_basebackup.c:2326 +#: pg_basebackup.c:2436 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "argumento de checkpoint «%s» no válido, debe ser «fast» o «spread»" -#: pg_basebackup.c:2344 +#: pg_basebackup.c:2454 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "formato de salida «%s» no válido, debe ser «plain» o «tar»" -#: pg_basebackup.c:2422 +#: pg_basebackup.c:2535 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "opción de wal-method «%s» no válida, debe ser «fetch», «stream» o «none»" -#: pg_basebackup.c:2457 pg_basebackup.c:2469 pg_basebackup.c:2491 -#: pg_basebackup.c:2503 pg_basebackup.c:2509 pg_basebackup.c:2561 -#: pg_basebackup.c:2572 pg_basebackup.c:2582 pg_basebackup.c:2588 -#: pg_basebackup.c:2595 pg_basebackup.c:2607 pg_basebackup.c:2619 -#: pg_basebackup.c:2627 pg_basebackup.c:2640 pg_basebackup.c:2646 -#: pg_basebackup.c:2655 pg_basebackup.c:2667 pg_basebackup.c:2678 -#: pg_basebackup.c:2686 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2038 pg_createsubscriber.c:2048 +#: pg_createsubscriber.c:2056 pg_createsubscriber.c:2084 +#: pg_createsubscriber.c:2116 pg_receivewal.c:748 pg_receivewal.c:760 #: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:835 pg_recvlogical.c:847 -#: pg_recvlogical.c:857 pg_recvlogical.c:864 pg_recvlogical.c:871 -#: pg_recvlogical.c:878 pg_recvlogical.c:885 pg_recvlogical.c:892 -#: pg_recvlogical.c:899 pg_recvlogical.c:906 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_basebackup.c:2467 pg_receivewal.c:758 pg_recvlogical.c:845 +#: pg_basebackup.c:2584 pg_createsubscriber.c:2046 pg_receivewal.c:758 +#: pg_recvlogical.c:863 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_basebackup.c:2490 +#: pg_basebackup.c:2607 #, c-format msgid "cannot specify both format and backup target" msgstr "no se puede especificar un formato junto con un destino de respaldo" -#: pg_basebackup.c:2502 +#: pg_basebackup.c:2619 #, c-format msgid "must specify output directory or backup target" msgstr "debe especificar un directorio de salida o destino de respaldo base" -#: pg_basebackup.c:2508 +#: pg_basebackup.c:2625 #, c-format msgid "cannot specify both output directory and backup target" msgstr "no se puede especificar un directorio de salida junto con un destino de respaldo" -#: pg_basebackup.c:2538 pg_receivewal.c:802 +#: pg_basebackup.c:2655 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "algoritmo de compresión no reconocido: «%s»" -#: pg_basebackup.c:2544 pg_receivewal.c:809 +#: pg_basebackup.c:2661 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "especificación de compresión no válida: %s" -#: pg_basebackup.c:2560 +#: pg_basebackup.c:2677 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "la compresión del lado del cliente no es posible cuando se especifica un destino del respaldo base" -#: pg_basebackup.c:2571 +#: pg_basebackup.c:2688 #, c-format msgid "only tar mode backups can be compressed" msgstr "sólo los respaldos de modo tar pueden ser comprimidos" -#: pg_basebackup.c:2581 +#: pg_basebackup.c:2698 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "no se puede enviar WAL cuando se especifica un destino del respaldo base" -#: pg_basebackup.c:2587 +#: pg_basebackup.c:2704 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "no se puede enviar WALs en modo tar a stdout" -#: pg_basebackup.c:2594 +#: pg_basebackup.c:2711 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "los slots de replicación sólo pueden usarse con flujo de WAL" -#: pg_basebackup.c:2606 +#: pg_basebackup.c:2723 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "no se puede usar --no-slot junto con nombre de slot" #. translator: second %s is an option name -#: pg_basebackup.c:2617 pg_receivewal.c:774 +#: pg_basebackup.c:2734 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "la opcón %s necesita que se especifique un slot con --slot" -#: pg_basebackup.c:2625 pg_basebackup.c:2665 pg_basebackup.c:2676 -#: pg_basebackup.c:2684 +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 #, c-format msgid "%s and %s are incompatible options" msgstr "%s y %s son opciones incompatibles" -#: pg_basebackup.c:2639 +#: pg_basebackup.c:2756 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "la ubicación del directorio de WAL no puede especificarse junto con un destino de respaldo" -#: pg_basebackup.c:2645 +#: pg_basebackup.c:2762 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "la ubicación del directorio de WAL sólo puede especificarse en modo «plain»" -#: pg_basebackup.c:2654 +#: pg_basebackup.c:2771 #, c-format msgid "WAL directory location must be an absolute path" msgstr "la ubicación del directorio de WAL debe ser una ruta absoluta" -#: pg_basebackup.c:2754 +#: pg_basebackup.c:2871 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "no se pudo crear el enlace simbólico «%s»: %m" -#: pg_receivewal.c:77 +#: pg_createsubscriber.c:169 +#, c-format +msgid "failed after the end of recovery" +msgstr "falló al final de la recuperación" + +#: pg_createsubscriber.c:170 +#, c-format +msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." +msgstr "El servidor de destino no puede ser usado más como réplica física. Debe volver a crear la réplica física antes de continuar." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "la publicación «%s» en la base de datos «%s» en el primaro fue abandonada" + +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "Borre esta publicación antes de volver a intentar." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "el slot de replicación «%s» en la base de datos «%s» en el primario fue abandonada" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1261 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "Elimine este slot de replicación pronto para evitar la retención de archivos WAL." + +#: pg_createsubscriber.c:219 #, c-format msgid "" -"%s receives PostgreSQL streaming write-ahead logs.\n" +"%s creates a new logical replica from a standby server.\n" "\n" msgstr "" -"%s recibe flujos del WAL de PostgreSQL.\n" +"%s crea una nueva réplica lógica a partir de un\n" +"servidor standby.\n" "\n" -#: pg_receivewal.c:81 pg_recvlogical.c:82 +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 #, c-format msgid "" "\n" @@ -1152,22 +1339,638 @@ msgstr "" "\n" "Opciones:\n" +#: pg_createsubscriber.c:224 +#, c-format +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --dbname=BASE-DATOS base de datos en la cual crear una suscripción\n" + +#: pg_createsubscriber.c:225 +#, c-format +msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" +msgstr " -D, --pgdata=DATADIR ubicación del directorio de datos del suscriptor\n" + +#: pg_createsubscriber.c:226 +#, c-format +msgid " -n, --dry-run dry run, just show what would be done\n" +msgstr " -n, --dry-run no actualiza, sólo muestra lo que se haría\n" + +#: pg_createsubscriber.c:227 +#, c-format +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr " -p, --subscriber-port=PUERTO número de puerto del suscriptor (def. %s)\n" + +#: pg_createsubscriber.c:228 +#, c-format +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CONSTR cadena de conexión del publicador\n" + +#: pg_createsubscriber.c:229 +#, c-format +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=DIR directorio de sockets a usar (omisión: dir. actual)\n" + +#: pg_createsubscriber.c:230 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=SEGS segundos a esperar a que la recuperación termine\n" + +#: pg_createsubscriber.c:231 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=USUARIO nombre de usuario para conexión del suscriptor\n" + +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose desplegar mensajes verbosos\n" + +#: pg_createsubscriber.c:233 +#, c-format +msgid "" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" +msgstr "" +" --config-file=ARCHIVO utilizar el archivo de configuración del servidor\n" +" principal especificado al ejecutar el clúster de destino\n" + +#: pg_createsubscriber.c:235 +#, c-format +msgid " --publication=NAME publication name\n" +msgstr " --publication=NOMBRE nombre de publicación\n" + +#: pg_createsubscriber.c:236 +#, c-format +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=NOMBRE nombre de slot de replicación\n" + +#: pg_createsubscriber.c:237 +#, c-format +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NOMBRE nombre de suscripción\n" + +#: pg_createsubscriber.c:238 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de versión y salir\n" + +#: pg_createsubscriber.c:239 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda y salir\n" + +#: pg_createsubscriber.c:282 +#, c-format +msgid "could not parse connection string: %s" +msgstr "no se pudo interpretar la cadena de conexión: %s" + +#: pg_createsubscriber.c:359 +#, c-format +msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +msgstr "el programa «%s» es requerido por %s pero se encontró en el mismo directorio que «%s»" + +#: pg_createsubscriber.c:362 +#, c-format +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "El programa «%s» fue encontrado por «%s», pero no es de la misma versión que %s" + +#: pg_createsubscriber.c:382 +#, c-format +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "verificando si el directorio «%s» es un directorio de datos de base de datos" + +#: pg_createsubscriber.c:388 +#, c-format +msgid "data directory \"%s\" does not exist" +msgstr "no existe el directorio de datos «%s»" + +#: pg_createsubscriber.c:396 +#, c-format +msgid "directory \"%s\" is not a database cluster directory" +msgstr "el directorio «%s» no es un directorio de base de datos" + +#: pg_createsubscriber.c:513 +#, c-format +msgid "connection to database failed: %s" +msgstr "falló la conexión a la base de datos: %s" + +#: pg_createsubscriber.c:526 +#, c-format +msgid "could not clear search_path: %s" +msgstr "no se pudo limpiar search_path: %s" + +#: pg_createsubscriber.c:566 +#, c-format +msgid "getting system identifier from publisher" +msgstr "obteniendo el identificador de sistema del publicador" + +#: pg_createsubscriber.c:573 +#, c-format +msgid "could not get system identifier: %s" +msgstr "no se pudo obtener el identificador de sistema: %s" + +#: pg_createsubscriber.c:579 +#, c-format +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "no se pudo obtener el identificador de sistema: se obtuvieron %d filas, se esperaban %d filas" + +#: pg_createsubscriber.c:586 +#, c-format +msgid "system identifier is %llu on publisher" +msgstr "identificador de sistema es %llu en el publicador" + +#: pg_createsubscriber.c:607 +#, c-format +msgid "getting system identifier from subscriber" +msgstr "obteniendo identificador de sistema del suscriptor" + +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 +#, c-format +msgid "control file appears to be corrupt" +msgstr "el archivo de control parece estar corrupto" + +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 +#, c-format +msgid "system identifier is %llu on subscriber" +msgstr "el identificador de sistema es %llu en suscriptor" + +#: pg_createsubscriber.c:637 +#, c-format +msgid "modifying system identifier of subscriber" +msgstr "modificando el identificador de sistema del suscriptor" + +#: pg_createsubscriber.c:659 +#, c-format +msgid "running pg_resetwal on the subscriber" +msgstr "ejecutando pg_resetwal en el suscriptor" + +#: pg_createsubscriber.c:671 +#, c-format +msgid "subscriber successfully changed the system identifier" +msgstr "el suscriptor cambió exitosamente el identificador de sistema" + +#: pg_createsubscriber.c:673 +#, c-format +msgid "could not change system identifier of subscriber: %s" +msgstr "no se pudo cambiar el identificador de sistema del suscriptor: %s" + +#: pg_createsubscriber.c:697 +#, c-format +msgid "could not obtain database OID: %s" +msgstr "no se pudo obtener el OID de base de datos: %s" + +#: pg_createsubscriber.c:704 +#, c-format +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "no se pudo obtener el OID de base de datos: se obtuvieron %d filas, se esperaban %d filas" + +#: pg_createsubscriber.c:776 +#, c-format +msgid "create replication slot \"%s\" on publisher" +msgstr "crear el slot de replicación «%s» en el publicador" + +#: pg_createsubscriber.c:796 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "no se pudo escribir un registro WAL adicional: %s" + +#: pg_createsubscriber.c:822 +#, c-format +msgid "could not obtain recovery progress: %s" +msgstr "no se pudo obtener el progreso de la recuperación: %s" + +#: pg_createsubscriber.c:854 +#, c-format +msgid "checking settings on publisher" +msgstr "verificando configuración en el publicador" + +#: pg_createsubscriber.c:864 +#, c-format +msgid "primary server cannot be in recovery" +msgstr "el servidor primario no puede estar en recuperación" + +#: pg_createsubscriber.c:888 +#, c-format +msgid "could not obtain publisher settings: %s" +msgstr "no se pudo obtener configuraciones del publicador: %s" + +# FIXME see slot.c:779. See also postmaster.c:835 +#: pg_createsubscriber.c:914 +#, c-format +msgid "publisher requires wal_level >= \"logical\"" +msgstr "el publicador requiere wal_level >= «logical»" + +#: pg_createsubscriber.c:920 +#, c-format +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "el publicador requiere %d slots de replicación, pero solo quedan %d" + +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Aumente el parámetro de configuración «%s» a al menos %d." + +#: pg_createsubscriber.c:929 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "el publicador requiere %d procesos WAL sender, pero sólo quedan %d" + +#: pg_createsubscriber.c:938 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "la opción two_phase no será activada en los slots de replicación" + +#: pg_createsubscriber.c:939 +#, c-format +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "Las suscripciones serán creadas con la opción two_phase desactivada. Las transacciones preparadas serán replicadas durante COMMIT PREPARED." + +#: pg_createsubscriber.c:971 +#, c-format +msgid "checking settings on subscriber" +msgstr "verificando configuraciones en el suscriptor" + +#: pg_createsubscriber.c:978 +#, c-format +msgid "target server must be a standby" +msgstr "el servidor de destino debe ser un standby" + +#: pg_createsubscriber.c:1002 +#, c-format +msgid "could not obtain subscriber settings: %s" +msgstr "no se pudo obtener la configuración del suscriptor: %s" + +#: pg_createsubscriber.c:1026 +#, c-format +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "el suscriptor requiere %d slots de replicación, pero sólo quedan %d" + +#: pg_createsubscriber.c:1035 +#, c-format +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "el suscriptor requiere %d procesos de replicación lógica, pero sólo quedan %d" + +#: pg_createsubscriber.c:1044 +#, c-format +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "el suscriptor requiere %d procesos ayudantes, pero solo quedan %d" + +#: pg_createsubscriber.c:1079 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "eliminando suscripción «%s» en base de datos «%s»" + +#: pg_createsubscriber.c:1088 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "no se pudo eliminar la suscripción «%s»: %s" + +#: pg_createsubscriber.c:1123 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "no se pudo obtener suscripciones pre-existentes: %s" + +#: pg_createsubscriber.c:1259 +#, c-format +msgid "could not drop replication slot \"%s\" on primary" +msgstr "no se pudo eliminar el slot de replicación «%s» en el primario" + +#: pg_createsubscriber.c:1293 +#, c-format +msgid "could not obtain failover replication slot information: %s" +msgstr "no se pudo obtener información de slots de replicación \"failover\": %s" + +#: pg_createsubscriber.c:1295 pg_createsubscriber.c:1304 +#, c-format +msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." +msgstr "Elimine los slots de replicación de failover en el suscriptor pronto para evitar retención de archivos WAL." + +#: pg_createsubscriber.c:1303 +#, c-format +msgid "could not drop failover replication slot" +msgstr "no se pudo eliminar el slot de replicación \"failover\"" + +#: pg_createsubscriber.c:1325 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "creando el slot de replicación «%s» en base de datos «%s»" + +#: pg_createsubscriber.c:1343 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "no se pudo crear el slot de replicación «%s» en base de datos «%s»: %s" + +#: pg_createsubscriber.c:1373 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "eliminando el slot de replicación «%s» en base de datos «%s»" + +#: pg_createsubscriber.c:1389 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "no se pudo eliminar el slot de replicación «%s» en base de datos «%s»: %s" + +#: pg_createsubscriber.c:1410 +#, c-format +msgid "pg_ctl failed with exit code %d" +msgstr "pg_ctl falló con código de retorno %d" + +#: pg_createsubscriber.c:1415 +#, c-format +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "pg_ctl fue terminado por una excepción 0x%X" + +#: pg_createsubscriber.c:1417 +#, c-format +msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "Vea el archivo «ntstatus.h» para una descripción del valor hexadecimal." + +#: pg_createsubscriber.c:1419 +#, c-format +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "pg_ctl fue terminado por una señal %d: %s" + +#: pg_createsubscriber.c:1425 +#, c-format +msgid "pg_ctl exited with unrecognized status %d" +msgstr "pg_ctl terminó con código no reconocido %d" + +#: pg_createsubscriber.c:1428 +#, c-format +msgid "The failed command was: %s" +msgstr "La orden fallida era: %s" + +#: pg_createsubscriber.c:1474 +#, c-format +msgid "server was started" +msgstr "el servidor fue iniciado" + +#: pg_createsubscriber.c:1489 +#, c-format +msgid "server was stopped" +msgstr "el servidor fue detenido" + +#: pg_createsubscriber.c:1508 +#, c-format +msgid "waiting for the target server to reach the consistent state" +msgstr "esperando que el servidor de destino alcance el estado consistente" + +#: pg_createsubscriber.c:1531 +#, c-format +msgid "recovery timed out" +msgstr "la recuperación tomó demasiado tiempo" + +#: pg_createsubscriber.c:1544 +#, c-format +msgid "server did not end recovery" +msgstr "el servidor no terminó la recuperación" + +#: pg_createsubscriber.c:1546 +#, c-format +msgid "target server reached the consistent state" +msgstr "el servidor de destino alcanzó el estado consistente" + +#: pg_createsubscriber.c:1547 +#, c-format +msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." +msgstr "Si pg_createsubscriber falla a partir de este punto, deberá re-crear la réplica física antes de continuar." + +#: pg_createsubscriber.c:1574 +#, c-format +msgid "could not obtain publication information: %s" +msgstr "no se pudo obtener la información de publicación: %s" + +#: pg_createsubscriber.c:1588 +#, c-format +msgid "publication \"%s\" already exists" +msgstr "la publicación «%s» ya existe" + +#: pg_createsubscriber.c:1589 +#, c-format +msgid "Consider renaming this publication before continuing." +msgstr "Considere cambiar el nombre de esta publicación antes de continuar." + +#: pg_createsubscriber.c:1596 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "creando la publicación «%s» en la base de datos «%s»" + +#: pg_createsubscriber.c:1609 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "no se pudo crear la publicación «%s» en la base de datos «%s»: %s" + +#: pg_createsubscriber.c:1638 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "eliminando la publicación «%s» en la base de datos «%s»" + +#: pg_createsubscriber.c:1652 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "no se pudo eliminar la publicación «%s» en la base de datos «%s»: %s" + +#: pg_createsubscriber.c:1698 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "creando la suscripción «%s» en la base de datos «%s»" + +#: pg_createsubscriber.c:1719 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "no se pudo create la suscripción «%s» en la base de datos «%s»: %s" + +#: pg_createsubscriber.c:1764 +#, c-format +msgid "could not obtain subscription OID: %s" +msgstr "no se pudo obtener el OID de suscripción: %s" + +#: pg_createsubscriber.c:1771 +#, c-format +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "no se pudo obtener el OID de suscripción: se obtuvieron %d filas, se esperaban %d filas" + +#: pg_createsubscriber.c:1795 +#, c-format +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "definiendo progreso de replicación (nombre de nodo «%s», LSN %s) en base de datos «%s»" + +#: pg_createsubscriber.c:1810 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "no se pudo establecer el progreso de replicación para la suscripción «%s»: %s" + +#: pg_createsubscriber.c:1841 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "activando la suscripción «%s» en la base de datos «%s»" + +#: pg_createsubscriber.c:1853 +#, c-format +msgid "could not enable subscription \"%s\": %s" +msgstr "no se pudo habilitar la suscripción «%s»: %s" + +#: pg_createsubscriber.c:1945 +#, c-format +msgid "cannot be executed by \"root\"" +msgstr "no puede ser ejecutado con el usuario «root»" + +#: pg_createsubscriber.c:1946 +#, c-format +msgid "You must run %s as the PostgreSQL superuser." +msgstr "Debe ejecutar %s con el superusuario de PostgreSQL." + +#: pg_createsubscriber.c:1967 +#, c-format +msgid "database \"%s\" specified more than once" +msgstr "la base de datos «%s» fue especificado más de una vez" + +#: pg_createsubscriber.c:2008 +#, c-format +msgid "publication \"%s\" specified more than once" +msgstr "la publicación «%s» fue especificada más de una vez" + +#: pg_createsubscriber.c:2020 +#, c-format +msgid "replication slot \"%s\" specified more than once" +msgstr "el slot de replicación «%s» fue especificado más de una vez" + +#: pg_createsubscriber.c:2032 +#, c-format +msgid "subscription \"%s\" specified more than once" +msgstr "la suscripción «%s» fue especificada más de una vez" + +#: pg_createsubscriber.c:2055 +#, c-format +msgid "no subscriber data directory specified" +msgstr "no se especificó un directorio de datos de suscripción" + +#: pg_createsubscriber.c:2066 +#, c-format +msgid "could not determine current directory" +msgstr "no se pudo determinar el directorio actual" + +#: pg_createsubscriber.c:2083 +#, c-format +msgid "no publisher connection string specified" +msgstr "no se especificó un string de conexión de publicador" + +#: pg_createsubscriber.c:2087 +#, c-format +msgid "validating publisher connection string" +msgstr "validando string de conexión del publicador" + +#: pg_createsubscriber.c:2093 +#, c-format +msgid "validating subscriber connection string" +msgstr "validando string de conexión del suscriptor" + +#: pg_createsubscriber.c:2098 +#, c-format +msgid "no database was specified" +msgstr "no se especificó una base de datos" + +#: pg_createsubscriber.c:2110 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "el nombr de base de datos «%s» fue extraído del string de conexión del publicador" + +#: pg_createsubscriber.c:2115 +#, c-format +msgid "no database name specified" +msgstr "no se especificó un nombre de base de datos" + +#: pg_createsubscriber.c:2125 +#, c-format +msgid "wrong number of publication names specified" +msgstr "una cantidad incorrecta de nombres de publicación fue especificada" + +#: pg_createsubscriber.c:2126 +#, c-format +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "La cantidad de nombres de publicación especificados (%d) debe coincidir con el número de nombres de bases de datos (%d)." + +#: pg_createsubscriber.c:2132 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "una cantidad incorrecta de nombres de suscripción fue especificada" + +#: pg_createsubscriber.c:2133 +#, c-format +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "La cantidad de nombres de suscripción especificados (%d) debe coincidir con el número de nombres de bases de datos (%d)." + +#: pg_createsubscriber.c:2139 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "una cantidad incorrecta de nombres de slots de replicación fue especificada" + +#: pg_createsubscriber.c:2140 +#, c-format +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "La cantidad de nombres de slots de replicación especificados (%d) debe coincidir con el número de nombres de bases de datos (%d)." + +#: pg_createsubscriber.c:2169 +#, c-format +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "el directorio de datos del suscriptor no es una copia del clúster de origen" + +#: pg_createsubscriber.c:2182 +#, c-format +msgid "standby server is running" +msgstr "el servidor standby está en ejecución" + +#: pg_createsubscriber.c:2183 +#, c-format +msgid "Stop the standby server and try again." +msgstr "Detenga el servidor standby y pruebe otra vez." + +#: pg_createsubscriber.c:2192 +#, c-format +msgid "starting the standby server with command-line options" +msgstr "iniciando el standby con opciones de línea de órdenes" + +#: pg_createsubscriber.c:2208 pg_createsubscriber.c:2243 +#, c-format +msgid "stopping the subscriber" +msgstr "deteniendo el suscriptor" + +#: pg_createsubscriber.c:2222 +#, c-format +msgid "starting the subscriber" +msgstr "iniciando el suscriptor" + +#: pg_createsubscriber.c:2251 +#, c-format +msgid "Done!" +msgstr "¡Listo!" + +#: pg_receivewal.c:77 +#, c-format +msgid "" +"%s receives PostgreSQL streaming write-ahead logs.\n" +"\n" +msgstr "" +"%s recibe flujos del WAL de PostgreSQL.\n" +"\n" + #: pg_receivewal.c:82 #, c-format msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=DIR recibir los archivos de WAL en este directorio\n" -#: pg_receivewal.c:83 pg_recvlogical.c:83 +#: pg_receivewal.c:83 pg_recvlogical.c:93 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN salir luego de recibir el LSN especificado\n" -#: pg_receivewal.c:84 pg_recvlogical.c:87 +#: pg_receivewal.c:84 pg_recvlogical.c:97 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr " --if-not-exists no abandonar si el slot ya existe al crear un slot\n" -#: pg_receivewal.c:85 pg_recvlogical.c:89 +#: pg_receivewal.c:85 pg_recvlogical.c:99 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop no entrar en bucle al perder la conexión\n" @@ -1177,7 +1980,7 @@ msgstr " -n, --no-loop no entrar en bucle al perder la conexión\n" msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync no esperar que los cambios se sincronicen a disco\n" -#: pg_receivewal.c:87 pg_recvlogical.c:94 +#: pg_receivewal.c:87 pg_recvlogical.c:104 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -1210,12 +2013,12 @@ msgstr "" "\n" "Acciones optativas:\n" -#: pg_receivewal.c:104 pg_recvlogical.c:79 +#: pg_receivewal.c:104 pg_recvlogical.c:89 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr " --create-slot crear un nuevo slot de replicación (para el nombre, vea --slot)\n" -#: pg_receivewal.c:105 pg_recvlogical.c:80 +#: pg_receivewal.c:105 pg_recvlogical.c:90 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr " --drop-slot eliminar un slot de replicación (para el nombre, vea --slot)\n" @@ -1235,7 +2038,7 @@ msgstr "detenido el flujo de log en %X/%X (timeline %u)" msgid "switched to timeline %u at %X/%X" msgstr "cambiado al timeline %u en %X/%X" -#: pg_receivewal.c:224 +#: pg_receivewal.c:224 pg_recvlogical.c:1053 #, c-format msgid "received interrupt signal, exiting" msgstr "se recibió una señal de interrupción, saliendo" @@ -1280,11 +2083,6 @@ msgstr "el archivo de segmento «%s» tiene tamaño incorrecto %d al descomprimi msgid "could not create LZ4 decompression context: %s" msgstr "no se pudo crear un contexto de descompresión LZ4: %s" -#: pg_receivewal.c:402 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "no se pudo leer el archivo «%s»: %m" - #: pg_receivewal.c:420 #, c-format msgid "could not decompress file \"%s\": %s" @@ -1310,7 +2108,7 @@ msgstr "no se puede verificar el archivo «%s»: la compresión con %s no está msgid "starting log streaming at %X/%X (timeline %u)" msgstr "iniciando el flujo de log en %X/%X (timeline %u)" -#: pg_receivewal.c:693 pg_recvlogical.c:783 +#: pg_receivewal.c:693 pg_recvlogical.c:801 #, c-format msgid "could not parse end position \"%s\"" msgstr "no se pudo interpretar la posición final «%s»" @@ -1340,28 +2138,28 @@ msgstr "el método de compresión %s no está soportado aún" msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "la conexión de replicación usando el slot «%s» es inesperadamente específica a una base de datos" -#: pg_receivewal.c:878 pg_recvlogical.c:954 +#: pg_receivewal.c:878 pg_recvlogical.c:972 #, c-format msgid "dropping replication slot \"%s\"" msgstr "eliminando el slot de replicación «%s»" -#: pg_receivewal.c:889 pg_recvlogical.c:964 +#: pg_receivewal.c:889 pg_recvlogical.c:982 #, c-format msgid "creating replication slot \"%s\"" msgstr "creando el slot de replicación «%s»" -#: pg_receivewal.c:918 pg_recvlogical.c:988 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "desconectado" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:992 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "desconectado; esperando %d segundos para intentar nuevamente" -#: pg_recvlogical.c:74 +#: pg_recvlogical.c:84 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -1370,7 +2168,7 @@ msgstr "" "%s controla flujos de decodificación lógica de PostgreSQL.\n" "\n" -#: pg_recvlogical.c:78 +#: pg_recvlogical.c:88 #, c-format msgid "" "\n" @@ -1379,17 +2177,17 @@ msgstr "" "\n" "Acciones a ejecutar:\n" -#: pg_recvlogical.c:81 +#: pg_recvlogical.c:91 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr " --start iniciar flujo en un slot de replicación (para el nombre, vea --slot)\n" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=ARCHIVO recibir el log en este archivo, - para stdout\n" -#: pg_recvlogical.c:85 +#: pg_recvlogical.c:95 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -1398,12 +2196,12 @@ msgstr "" " -F, --fsync-interval=SEGS\n" " tiempo entre fsyncs del archivo de salida (omisión: %d)\n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:98 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN dónde en un slot existente debe empezar el flujo\n" -#: pg_recvlogical.c:90 +#: pg_recvlogical.c:100 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -1414,143 +2212,143 @@ msgstr "" " pasar opción NOMBRE con valor opcional VALOR al\n" " plugin de salida\n" -#: pg_recvlogical.c:93 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN usar plug-in de salida PLUGIN (omisión: %s)\n" -#: pg_recvlogical.c:96 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=NOMBRE-SLOT nombre del slot de replicación lógica\n" -#: pg_recvlogical.c:97 +#: pg_recvlogical.c:107 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr " -t, --two-phase activa decodificación de transacciones preparadas al crear un slot\n" -#: pg_recvlogical.c:102 +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=BASE base de datos a la cual conectarse\n" -#: pg_recvlogical.c:135 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "confirmando escritura hasta %X/%X, fsync hasta %X/%X (slot %s)" -#: pg_recvlogical.c:159 receivelog.c:360 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "no se pudo enviar el paquete de retroalimentación: %s" -#: pg_recvlogical.c:227 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "iniciando el flujo de log en %X/%X (slot %s)" -#: pg_recvlogical.c:269 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "flujo iniciado" -#: pg_recvlogical.c:333 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "no se pudo abrir el archivo de registro «%s»: %m" -#: pg_recvlogical.c:362 receivelog.c:882 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "el socket no es válido: %s" -#: pg_recvlogical.c:415 receivelog.c:910 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: pg_recvlogical.c:422 receivelog.c:959 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "no se pudo recibir datos desde el flujo de WAL: %s" -#: pg_recvlogical.c:464 pg_recvlogical.c:515 receivelog.c:1003 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 #: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "cabecera de flujo demasiado pequeña: %d" -#: pg_recvlogical.c:499 receivelog.c:843 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "cabecera de flujo no reconocida: «%c»" -#: pg_recvlogical.c:553 pg_recvlogical.c:565 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "no se pudo escribir %d bytes al archivo de registro «%s»: %m" -#: pg_recvlogical.c:619 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "término inesperado del flujo de replicación: %s" -#: pg_recvlogical.c:778 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "no se pudo interpretar la posición de inicio «%s»" -#: pg_recvlogical.c:856 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "no se especificó slot" -#: pg_recvlogical.c:863 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "no se especificó un archivo de destino" -#: pg_recvlogical.c:870 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "no se especificó una base de datos" -#: pg_recvlogical.c:877 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "debe especificarse al menos una operación" -#: pg_recvlogical.c:884 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "no puede usarse --create-slot o --start junto con --drop-slot" -#: pg_recvlogical.c:891 +#: pg_recvlogical.c:909 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "no puede usarse --create-slot o --drop-slot junto con --startpos" -#: pg_recvlogical.c:898 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos sólo se puede utilizar con --start" -#: pg_recvlogical.c:905 +#: pg_recvlogical.c:923 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase sólo se puede utilizar con --create-slot" -#: pg_recvlogical.c:938 +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "no se pudo establecer una conexión de replicación específica a una base de datos" -#: pg_recvlogical.c:1032 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "ubicación de término %X/%X alcanzado por «keep-alive»" -#: pg_recvlogical.c:1035 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "ubicación de término %X/%X alcanzado por registro WAL en %X/%X" @@ -1667,7 +2465,7 @@ msgstr "respuesta inesperada después del fin-de-timeline: se obtuvieron %d fila msgid "could not parse next timeline's starting point \"%s\"" msgstr "no se pudo interpretar el punto de inicio del siguiente timeline «%s»" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1201 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "no se pudo sincronizar (fsync) archivo «%s»: %s" @@ -1692,120 +2490,121 @@ msgstr "no se pudo escribir %d bytes al archivo WAL «%s»: %s" msgid "could not send copy-end packet: %s" msgstr "no se pudo enviar el paquete copy-end: %s" -#: streamutil.c:158 +#: streamutil.c:165 msgid "Password: " msgstr "Contraseña: " -#: streamutil.c:181 +#: streamutil.c:192 #, c-format msgid "could not connect to server" msgstr "no se pudo conectar al servidor" -#: streamutil.c:222 +#: streamutil.c:233 #, c-format -msgid "could not clear search_path: %s" -msgstr "no se pudo limpiar search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "no se pudo limpiar «search_path»: %s" -#: streamutil.c:238 +#: streamutil.c:249 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "no se pudo determinar la opción integer_datetimes del servidor" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "no se pudo determinar la opción «integer_datetimes» del servidor" -#: streamutil.c:245 +#: streamutil.c:256 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "la opción de compilación integer_datetimes no coincide con el servidor" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "la opción de compilación «integer_datetimes» no coincide con el servidor" -#: streamutil.c:296 +#: streamutil.c:375 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "no se pudo obtener el tamaño del segmento de WAL: se obtuvo %d filas y %d campos, se esperaban %d filas y %d o más campos" -#: streamutil.c:306 +#: streamutil.c:385 #, c-format msgid "WAL segment size could not be parsed" msgstr "el tamaño de segmento de WAL no pudo ser analizado" -#: streamutil.c:324 +#: streamutil.c:403 +#, c-format +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "el servidor remoto reportó un tamaño de segmento de WAL no válido (%d byte)" +msgstr[1] "el servidor remoto reportó un tamaño de segmento de WAL no válido (%d bytes)" + +#: streamutil.c:407 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d bytes" -msgstr[0] "el tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el servidor remoto reportó un valor de %d byte" -msgstr[1] "el tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el servidor remoto reportó un valor de %d bytes" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "El tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB." -#: streamutil.c:369 +#: streamutil.c:449 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "no se pudo obtener el indicador de acceso de grupo: se obtuvo %d filas y %d campos, se esperaban %d filas y %d o más campos" -#: streamutil.c:378 +#: streamutil.c:458 #, c-format msgid "group access flag could not be parsed: %s" msgstr "el indicador de acceso de grupo no pudo ser analizado: %s" -#: streamutil.c:421 streamutil.c:458 +#: streamutil.c:501 streamutil.c:538 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "no se pudo identificar al sistema: se obtuvieron %d filas y %d campos, se esperaban %d filas y %d o más campos" -#: streamutil.c:510 +#: streamutil.c:590 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "no se pudo leer el slot de replicación «%s»: se obtuvieron %d filas y %d campos, se esperaban %d filas y %d campos" -#: streamutil.c:522 +#: streamutil.c:602 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "no existe el slot de replicación «%s»" -#: streamutil.c:533 +#: streamutil.c:613 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "se esperaba un slot de replicación físico, en cambio se obtuvo tipo «%s»" -#: streamutil.c:547 +#: streamutil.c:627 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "no se pudo interpretar restart_lsn de WAL «%s» para el slot de replicación «%s»" -#: streamutil.c:664 +#: streamutil.c:744 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "no se pudo create el slot de replicación «%s»: se obtuvieron %d filas y %d campos, se esperaban %d filas y %d campos" -#: streamutil.c:708 +#: streamutil.c:788 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "no se pudo eliminar el slot de replicación «%s»: se obtuvieron %d filas y %d campos, se esperaban %d filas y %d campos" -#: walmethods.c:721 walmethods.c:1264 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "no se pudo comprimir datos" -#: walmethods.c:750 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "no se pudo restablecer el flujo comprimido" -#: walmethods.c:888 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "error de implementación: los archivos tar no pueden tener abierto más de un fichero" -#: walmethods.c:903 +#: walmethods.c:907 msgid "could not create tar header" msgstr "no se pudo crear la cabecera del archivo tar" -#: walmethods.c:920 walmethods.c:961 walmethods.c:1166 walmethods.c:1179 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "no se pudo cambiar los parámetros de compresión" -#: walmethods.c:1052 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "unlink no soportado con compresión" -#: walmethods.c:1288 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "no se pudo cerrar el flujo comprimido" - -#, c-format -#~ msgid "could not set compression flag for %s: %s" -#~ msgstr "no se pudo definir una opción de compresión para %s: %s" diff --git a/src/bin/pg_basebackup/po/fr.po b/src/bin/pg_basebackup/po/fr.po index 54a388acf9d1d..ae370d26a6cae 100644 --- a/src/bin/pg_basebackup/po/fr.po +++ b/src/bin/pg_basebackup/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:18+0000\n" -"PO-Revision-Date: 2023-07-29 22:45+0200\n" +"POT-Creation-Date: 2024-08-26 19:50+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -93,6 +93,65 @@ msgstr "l'algorithme de compression « %s » n'accepte pas un nombre de workers" msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "l'algorithme de compression « %s » n'accepte pas un mode distance longue" +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"possible incohérence dans l'ordre des octets\n" +"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n" +"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n" +"résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" +"est incompatible avec ce répertoire des données." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "impossible d'écrire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -104,39 +163,69 @@ msgstr "mémoire épuisée\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 -#: pg_receivewal.c:319 pg_recvlogical.c:339 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "n'a pas pu tester le fichier « %s » : %m" -#: ../../common/file_utils.c:162 pg_receivewal.c:242 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" -#: ../../common/file_utils.c:196 pg_receivewal.c:471 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "n'a pas pu lire le répertoire « %s » : %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 ../../fe_utils/recovery_gen.c:121 -#: pg_receivewal.c:386 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 -#: pg_recvlogical.c:194 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" +msgid "could not open process token: error code %lu" +msgstr "n'a pas pu ouvrir le jeton du processus : code d'erreur %lu" -#: ../../common/file_utils.c:379 pg_basebackup.c:2237 walmethods.c:462 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "n'a pas pu allouer les SID : code d'erreur %lu" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "n'a pas pu créer le jeton restreint : code d'erreur %lu" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -148,51 +237,62 @@ msgstr "valeur « %s » invalide pour l'option %s" msgid "%s must be in range %d..%d" msgstr "%s doit être compris entre %d et %d" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 pg_basebackup.c:1609 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 #, c-format msgid "out of memory" msgstr "mémoire épuisée" -#: ../../fe_utils/recovery_gen.c:124 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1406 pg_basebackup.c:1700 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "n'a pas pu écrire dans le fichier « %s » : %m" -#: ../../fe_utils/recovery_gen.c:133 bbstreamer_file.c:93 bbstreamer_file.c:360 -#: pg_basebackup.c:1470 pg_basebackup.c:1679 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "n'a pas pu créer le fichier « %s » : %m" -#: bbstreamer_file.c:138 pg_recvlogical.c:633 +#: ../../fe_utils/string_utils.c:434 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "n'a pas pu fermer le fichier « %s » : %m" +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" #: bbstreamer_file.c:275 #, c-format msgid "unexpected state while extracting archive" msgstr "état inattendu lors de l'extraction de l'archive" -#: bbstreamer_file.c:320 pg_basebackup.c:686 pg_basebackup.c:730 +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 #, c-format msgid "could not create directory \"%s\": %m" msgstr "n'a pas pu créer le répertoire « %s » : %m" -#: bbstreamer_file.c:325 +#: bbstreamer_file.c:326 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "n'a pas pu configurer les droits du répertoire « %s » : %m" -#: bbstreamer_file.c:344 +#: bbstreamer_file.c:345 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "n'a pas pu créer le lien symbolique de « %s » vers « %s » : %m" -#: bbstreamer_file.c:364 +#: bbstreamer_file.c:365 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "n'a pas pu initialiser les droits du fichier « %s » : %m" @@ -227,7 +327,7 @@ msgstr "n'a pas pu écrire dans le fichier compressé « %s » : %s" msgid "could not close compressed file \"%s\": %m" msgstr "n'a pas pu fermer le fichier compressé « %s » : %m" -#: bbstreamer_gzip.c:245 walmethods.c:876 +#: bbstreamer_gzip.c:245 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "n'a pas pu initialiser la bibliothèque de compression" @@ -277,12 +377,12 @@ msgstr "la fin du fichier tar fait plus de 2 blocs" msgid "unexpected state while parsing tar archive" msgstr "état inattendu lors de l'analyse de l'archive tar" -#: bbstreamer_tar.c:296 +#: bbstreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "le membre de tar a un nom vide" -#: bbstreamer_tar.c:328 +#: bbstreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "le flux COPY s'est terminé avant que le dernier fichier soit terminé" @@ -312,87 +412,87 @@ msgstr "n'a pas pu activer le mode distance longue : %s" msgid "could not create zstd decompression context" msgstr "n'a pas pu créer le contexte de décompression zstd" -#: pg_basebackup.c:238 +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "suppression du répertoire des données « %s »" -#: pg_basebackup.c:240 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "échec de la suppression du répertoire des données" -#: pg_basebackup.c:244 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "suppression du contenu du répertoire des données « %s »" -#: pg_basebackup.c:246 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "échec de la suppression du contenu du répertoire des données" -#: pg_basebackup.c:251 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "suppression du répertoire des journaux de transactions « %s »" -#: pg_basebackup.c:253 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "échec de la suppression du répertoire des journaux de transactions" -#: pg_basebackup.c:257 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "suppression du contenu du répertoire des journaux de transactions « %s »" -#: pg_basebackup.c:259 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "échec de la suppression du contenu du répertoire des journaux de transactions" -#: pg_basebackup.c:265 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "répertoire des données « %s » non supprimé à la demande de l'utilisateur" -#: pg_basebackup.c:268 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "répertoire des journaux de transactions « %s » non supprimé à la demande de l'utilisateur" -#: pg_basebackup.c:272 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "les modifications des répertoires des tablespaces ne seront pas annulées" -#: pg_basebackup.c:324 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "nom du répertoire trop long" -#: pg_basebackup.c:331 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "multiple signes « = » dans la correspondance de tablespace" -#: pg_basebackup.c:340 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "format de correspondance de tablespace « %s » invalide, doit être « ANCIENREPERTOIRE=NOUVEAUREPERTOIRE »" -#: pg_basebackup.c:359 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "l'ancien répertoire n'est pas un chemin absolu dans la correspondance de tablespace : %s" -#: pg_basebackup.c:363 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "le nouveau répertoire n'est pas un chemin absolu dans la correspondance de tablespace : %s" -#: pg_basebackup.c:385 +#: pg_basebackup.c:392 #, c-format msgid "" "%s takes a base backup of a running PostgreSQL server.\n" @@ -402,17 +502,19 @@ msgstr "" "d'exécution.\n" "\n" -#: pg_basebackup.c:387 pg_receivewal.c:79 pg_recvlogical.c:76 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_basebackup.c:388 pg_receivewal.c:80 pg_recvlogical.c:77 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPTION]...\n" -#: pg_basebackup.c:389 +#: pg_basebackup.c:396 #, c-format msgid "" "\n" @@ -421,17 +523,26 @@ msgstr "" "\n" "Options contrôlant la sortie :\n" -#: pg_basebackup.c:390 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" msgstr " -D, --pgdata=RÉPERTOIRE reçoit la sauvegarde de base dans ce répertoire\n" -#: pg_basebackup.c:391 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr " -F, --format=p|t format en sortie (plain (par défaut), tar)\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:399 +#, c-format +msgid "" +" -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr "" +" -i, --incremental=ANCIENMANIFESTE\n" +" réalise une sauvegarde incrémentale\n" + +#: pg_basebackup.c:401 #, c-format msgid "" " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" @@ -441,21 +552,21 @@ msgstr "" " données (en Ko/s, ou utiliser le suffixe « k »\n" " ou « M »)\n" -#: pg_basebackup.c:394 +#: pg_basebackup.c:403 #, c-format msgid "" " -R, --write-recovery-conf\n" " write configuration for replication\n" msgstr " -R, --write-recovery-conf écrit la configuration pour la réplication\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:405 #, c-format msgid "" " -t, --target=TARGET[:DETAIL]\n" " backup target (if other than client)\n" msgstr " -t, --target=CIBLE[:DETAIL] cible de sauvegarde (si autre que client)\n" -#: pg_basebackup.c:398 +#: pg_basebackup.c:407 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -464,14 +575,14 @@ msgstr "" " -T, --tablespace-mapping=ANCIENREP=NOUVEAUREP\n" " déplace le répertoire ANCIENREP en NOUVEAUREP\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr "" " --waldir=RÉP_WAL emplacement du répertoire des journaux de\n" " transactions\n" -#: pg_basebackup.c:401 +#: pg_basebackup.c:410 #, c-format msgid "" " -X, --wal-method=none|fetch|stream\n" @@ -481,12 +592,12 @@ msgstr "" " inclut les journaux de transactions requis avec\n" " la méthode spécifiée\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip compresse la sortie tar\n" -#: pg_basebackup.c:404 +#: pg_basebackup.c:413 #, c-format msgid "" " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" @@ -495,12 +606,12 @@ msgstr "" " -Z, --compress=[{client|server}-]METHODE[:DETAIL]\n" " compresse sur le client ou le serveur comme indiqué\n" -#: pg_basebackup.c:406 +#: pg_basebackup.c:415 #, c-format msgid " -Z, --compress=none do not compress tar output\n" msgstr " -Z, --compress=none ne compresse pas la sortie tar\n" -#: pg_basebackup.c:407 +#: pg_basebackup.c:416 #, c-format msgid "" "\n" @@ -509,56 +620,56 @@ msgstr "" "\n" "Options générales :\n" -#: pg_basebackup.c:408 +#: pg_basebackup.c:417 #, c-format msgid "" " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" -msgstr " -c, --checkpoint=fast|spread exécute un CHECKPOINT rapide ou réparti\n" +" set fast or spread (default) checkpointing\n" +msgstr " -c, --checkpoint=fast|spread exécute un CHECKPOINT rapide ou réparti (par défaut)\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " --create-slot crée un slot de réplication\n" -#: pg_basebackup.c:411 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=LABEL configure le label de sauvegarde\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean ne nettoie pas en cas d'erreur\n" -#: pg_basebackup.c:413 +#: pg_basebackup.c:422 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync n'attend pas que les modifications soient\n" " proprement écrites sur disque\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress affiche la progression de la sauvegarde\n" -#: pg_basebackup.c:415 pg_receivewal.c:89 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=NOMREP slot de réplication à utiliser\n" -#: pg_basebackup.c:416 pg_receivewal.c:91 pg_recvlogical.c:98 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose affiche des messages verbeux\n" -#: pg_basebackup.c:417 pg_receivewal.c:92 pg_recvlogical.c:99 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_basebackup.c:418 +#: pg_basebackup.c:427 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -568,7 +679,7 @@ msgstr "" " utilise cet algorithme pour les sommes de\n" " contrôle du manifeste\n" -#: pg_basebackup.c:420 +#: pg_basebackup.c:429 #, c-format msgid "" " --manifest-force-encode\n" @@ -577,40 +688,47 @@ msgstr "" " --manifest-force-encode encode tous les noms de fichier dans le\n" " manifeste en hexadécimal\n" -#: pg_basebackup.c:422 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" msgstr "" " --no-estimate-size ne réalise pas d'estimation sur la taille de la\n" " sauvegarde côté serveur\n" -#: pg_basebackup.c:423 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr "" " --no-manifest supprime la génération de manifeste de\n" " sauvegarde\n" -#: pg_basebackup.c:424 +#: pg_basebackup.c:433 #, c-format msgid " --no-slot prevent creation of temporary replication slot\n" msgstr "" " --no-slot empêche la création de slots de réplication\n" " temporaires\n" -#: pg_basebackup.c:425 +#: pg_basebackup.c:434 #, c-format msgid "" " --no-verify-checksums\n" " do not verify checksums\n" msgstr " --no-verify-checksums ne vérifie pas les sommes de contrôle\n" -#: pg_basebackup.c:427 pg_receivewal.c:95 pg_recvlogical.c:100 +#: pg_basebackup.c:436 +#, c-format +msgid "" +" --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_basebackup.c:428 pg_receivewal.c:96 pg_recvlogical.c:101 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "" "\n" @@ -619,24 +737,24 @@ msgstr "" "\n" "Options de connexion :\n" -#: pg_basebackup.c:429 pg_receivewal.c:97 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CHAÎNE_CONNEX chaîne de connexion\n" -#: pg_basebackup.c:430 pg_receivewal.c:98 pg_recvlogical.c:103 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HÔTE hôte du serveur de bases de données ou\n" " répertoire des sockets\n" -#: pg_basebackup.c:431 pg_receivewal.c:99 pg_recvlogical.c:104 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT numéro de port du serveur de bases de données\n" -#: pg_basebackup.c:432 +#: pg_basebackup.c:443 #, c-format msgid "" " -s, --status-interval=INTERVAL\n" @@ -645,24 +763,25 @@ msgstr "" " -s, --status-interval=INTERVAL durée entre l'envoi de paquets de statut au\n" " serveur (en secondes)\n" -#: pg_basebackup.c:434 pg_receivewal.c:100 pg_recvlogical.c:105 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=UTILISATEUR se connecte avec cet utilisateur\n" -#: pg_basebackup.c:435 pg_receivewal.c:101 pg_recvlogical.c:106 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ne demande jamais le mot de passe\n" -#: pg_basebackup.c:436 pg_receivewal.c:102 pg_recvlogical.c:107 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password force la demande du mot de passe (devrait\n" " survenir automatiquement)\n" -#: pg_basebackup.c:437 pg_receivewal.c:106 pg_recvlogical.c:108 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "" "\n" @@ -671,484 +790,548 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_basebackup.c:438 pg_receivewal.c:107 pg_recvlogical.c:109 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_basebackup.c:477 +#: pg_basebackup.c:488 #, c-format msgid "could not read from ready pipe: %m" msgstr "n'a pas pu lire à partir du tube : %m" -#: pg_basebackup.c:480 pg_basebackup.c:622 pg_basebackup.c:2151 -#: streamutil.c:441 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:518 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "n'a pas pu analyser l'emplacement du journal des transactions « %s »" -#: pg_basebackup.c:585 pg_receivewal.c:600 +#: pg_basebackup.c:596 pg_receivewal.c:600 #, c-format msgid "could not finish writing WAL files: %m" msgstr "n'a pas pu finir l'écriture dans les fichiers de transactions : %m" -#: pg_basebackup.c:631 +#: pg_basebackup.c:642 #, c-format msgid "could not create pipe for background process: %m" msgstr "n'a pas pu créer un tube pour le processus en tâche de fond : %m" -#: pg_basebackup.c:664 +#: pg_basebackup.c:676 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "a créé le slot de réplication temporaire « %s »" -#: pg_basebackup.c:667 +#: pg_basebackup.c:679 #, c-format msgid "created replication slot \"%s\"" msgstr "a créé le slot de réplication « %s »" -#: pg_basebackup.c:701 +#: pg_basebackup.c:728 #, c-format msgid "could not create background process: %m" msgstr "n'a pas pu créer un processus en tâche de fond : %m" -#: pg_basebackup.c:710 +#: pg_basebackup.c:737 #, c-format msgid "could not create background thread: %m" msgstr "n'a pas pu créer un thread en tâche de fond : %m" -#: pg_basebackup.c:749 +#: pg_basebackup.c:776 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "le répertoire « %s » existe mais n'est pas vide" -#: pg_basebackup.c:755 +#: pg_basebackup.c:782 pg_createsubscriber.c:390 #, c-format msgid "could not access directory \"%s\": %m" msgstr "n'a pas pu accéder au répertoire « %s » : %m" -#: pg_basebackup.c:831 +#: pg_basebackup.c:858 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s Ko (100%%), %d/%d tablespace %*s" msgstr[1] "%*s/%s Ko (100%%), %d/%d tablespaces %*s" -#: pg_basebackup.c:843 +#: pg_basebackup.c:870 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s Ko (%d%%), %d/%d tablespace (%s%-*.*s)" msgstr[1] "%*s/%s Ko (%d%%), %d/%d tablespaces (%s%-*.*s)" -#: pg_basebackup.c:859 +#: pg_basebackup.c:886 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s Ko (%d%%), %d/%d tablespace" msgstr[1] "%*s/%s Ko (%d%%), %d/%d tablespaces" -#: pg_basebackup.c:883 +#: pg_basebackup.c:910 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "le taux de transfert « %s » ne correspond pas à une valeur valide" -#: pg_basebackup.c:885 +#: pg_basebackup.c:912 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "taux de transfert invalide (« %s ») : %m" -#: pg_basebackup.c:892 +#: pg_basebackup.c:919 #, c-format msgid "transfer rate must be greater than zero" msgstr "le taux de transfert doit être supérieur à zéro" -#: pg_basebackup.c:922 +#: pg_basebackup.c:949 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "unité invalide pour --max-rate : « %s »" -#: pg_basebackup.c:926 +#: pg_basebackup.c:953 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "le taux de transfert « %s » dépasse l'échelle des entiers" -#: pg_basebackup.c:933 +#: pg_basebackup.c:960 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "le taux de transfert « %s » est en dehors des limites" -#: pg_basebackup.c:995 +#: pg_basebackup.c:1022 #, c-format msgid "could not get COPY data stream: %s" msgstr "n'a pas pu obtenir le flux de données de COPY : %s" -#: pg_basebackup.c:1012 pg_recvlogical.c:436 pg_recvlogical.c:608 +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 #: receivelog.c:973 #, c-format msgid "could not read COPY data: %s" msgstr "n'a pas pu lire les données du COPY : %s" -#: pg_basebackup.c:1016 +#: pg_basebackup.c:1043 #, c-format msgid "background process terminated unexpectedly" msgstr "un processus worker s'est arrêté de façon inattendue" -#: pg_basebackup.c:1087 +#: pg_basebackup.c:1114 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "ne peut pas injecter le manifeste dans un fichier tar compressé" -#: pg_basebackup.c:1088 +#: pg_basebackup.c:1115 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "Utilisez la compression côté client, envoyez la sortie dans un répertoire plutôt que sur la sortie standard, ou utilisez %s." -#: pg_basebackup.c:1104 +#: pg_basebackup.c:1131 #, c-format msgid "cannot parse archive \"%s\"" msgstr "n'a pas pu analyser l'archive « %s »" -#: pg_basebackup.c:1105 +#: pg_basebackup.c:1132 #, c-format msgid "Only tar archives can be parsed." msgstr "Seules les archives tar peuvent être analysées" -#: pg_basebackup.c:1107 +#: pg_basebackup.c:1134 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Le format plain requiert que pg_basebackup analyse l'archive." -#: pg_basebackup.c:1109 +#: pg_basebackup.c:1136 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "Utiliser - comme répertoire de sortie requiert que pg_basebackup analyse l'archive." -#: pg_basebackup.c:1111 +#: pg_basebackup.c:1138 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "L'option -R requiert que pg_basebackup analyse l'archive." -#: pg_basebackup.c:1330 +#: pg_basebackup.c:1357 #, c-format msgid "archives must precede manifest" msgstr "les archives doivent précéder le manifeste" -#: pg_basebackup.c:1345 +#: pg_basebackup.c:1372 #, c-format msgid "invalid archive name: \"%s\"" msgstr "nom d'archive invalide : « %s »" -#: pg_basebackup.c:1417 +#: pg_basebackup.c:1444 #, c-format msgid "unexpected payload data" msgstr "donnée de charge inattendue" -#: pg_basebackup.c:1560 +#: pg_basebackup.c:1587 #, c-format msgid "empty COPY message" msgstr "message COPY vide" -#: pg_basebackup.c:1562 +#: pg_basebackup.c:1589 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "message COPY malformé de type %d, longueur %zu" -#: pg_basebackup.c:1760 +#: pg_basebackup.c:1789 #, c-format msgid "incompatible server version %s" msgstr "version « %s » du serveur incompatible" -#: pg_basebackup.c:1776 +#: pg_basebackup.c:1805 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "Utilisez -X none ou -X fetch pour désactiver la réplication en flux." -#: pg_basebackup.c:1844 +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "le serveur n'accepte pas les sauvegardes incrémentales" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 +#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "n'a pas pu envoyer la commande de réplication « %s » : %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "n'a pas pu charger le manifeste : %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#, c-format +msgid "could not upload manifest: unexpected status %s" +msgstr "n'a pas pu charger le manifeste : statut %s inattendu" + +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "n'a pas pu envoyer les données COPY : %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "n'a pas pu envoyer end-of-COPY : %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "résultat supplémentaire inattendu lors de l'envoi du manifeste" + +#: pg_basebackup.c:1950 #, c-format msgid "backup targets are not supported by this server version" msgstr "les cibles de sauvegarde ne sont pas supportées par cette version du serveur" -#: pg_basebackup.c:1847 +#: pg_basebackup.c:1953 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "la configuration de la restauration ne peut pas être écrite quand une cible de restauration est utilisée" -#: pg_basebackup.c:1874 +#: pg_basebackup.c:1980 #, c-format msgid "server does not support server-side compression" msgstr "le serveur ne supporte pas la compression côté serveur" -#: pg_basebackup.c:1884 +#: pg_basebackup.c:1990 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "début de la sauvegarde de base, en attente de la fin du checkpoint" -#: pg_basebackup.c:1888 +#: pg_basebackup.c:1994 #, c-format msgid "waiting for checkpoint" msgstr "en attente du checkpoint" -#: pg_basebackup.c:1901 pg_recvlogical.c:260 receivelog.c:543 receivelog.c:582 -#: streamutil.c:288 streamutil.c:361 streamutil.c:413 streamutil.c:501 -#: streamutil.c:653 streamutil.c:698 -#, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "n'a pas pu envoyer la commande de réplication « %s » : %s" - -#: pg_basebackup.c:1909 +#: pg_basebackup.c:2016 #, c-format msgid "could not initiate base backup: %s" msgstr "n'a pas pu initier la sauvegarde de base : %s" -#: pg_basebackup.c:1912 +#: pg_basebackup.c:2019 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "le serveur a renvoyé une réponse inattendue à la commande BASE_BACKUP ; a récupéré %d lignes et %d champs, alors qu'il attendait %d lignes et %d champs" -#: pg_basebackup.c:1918 +#: pg_basebackup.c:2025 #, c-format msgid "checkpoint completed" msgstr "checkpoint terminé" -#: pg_basebackup.c:1932 +#: pg_basebackup.c:2039 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "point de départ du journal de transactions : %s sur la timeline %u" -#: pg_basebackup.c:1940 +#: pg_basebackup.c:2047 #, c-format msgid "could not get backup header: %s" msgstr "n'a pas pu obtenir l'en-tête du serveur : %s" -#: pg_basebackup.c:1943 +#: pg_basebackup.c:2050 #, c-format msgid "no data returned from server" msgstr "aucune donnée renvoyée du serveur" -#: pg_basebackup.c:1986 +#: pg_basebackup.c:2093 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "peut seulement écrire un tablespace sur la sortie standard, la base en a %d" -#: pg_basebackup.c:1999 +#: pg_basebackup.c:2106 #, c-format msgid "starting background WAL receiver" msgstr "lance le récepteur de journaux de transactions en tâche de fond" -#: pg_basebackup.c:2082 +#: pg_basebackup.c:2189 #, c-format msgid "backup failed: %s" msgstr "échec de la sauvegarde : %s" -#: pg_basebackup.c:2085 +#: pg_basebackup.c:2192 #, c-format msgid "no write-ahead log end position returned from server" msgstr "aucune position de fin du journal de transactions renvoyée par le serveur" -#: pg_basebackup.c:2088 +#: pg_basebackup.c:2195 #, c-format msgid "write-ahead log end point: %s" msgstr "point final du journal de transactions : %s" -#: pg_basebackup.c:2099 +#: pg_basebackup.c:2206 #, c-format msgid "checksum error occurred" msgstr "erreur de somme de contrôle" -#: pg_basebackup.c:2104 +#: pg_basebackup.c:2211 #, c-format msgid "final receive failed: %s" msgstr "échec lors de la réception finale : %s" -#: pg_basebackup.c:2128 +#: pg_basebackup.c:2235 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "en attente que le processus en tâche de fond termine le flux..." -#: pg_basebackup.c:2132 +#: pg_basebackup.c:2239 #, c-format msgid "could not send command to background pipe: %m" msgstr "n'a pas pu envoyer la commande au tube du processus : %m" -#: pg_basebackup.c:2137 +#: pg_basebackup.c:2244 #, c-format msgid "could not wait for child process: %m" msgstr "n'a pas pu attendre le processus fils : %m" -#: pg_basebackup.c:2139 +#: pg_basebackup.c:2246 #, c-format msgid "child %d died, expected %d" msgstr "le fils %d est mort, %d attendu" -#: pg_basebackup.c:2141 streamutil.c:91 streamutil.c:196 +#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 #, c-format msgid "%s" msgstr "%s" -#: pg_basebackup.c:2161 +#: pg_basebackup.c:2268 #, c-format msgid "could not wait for child thread: %m" msgstr "n'a pas pu attendre le thread : %m" -#: pg_basebackup.c:2166 +#: pg_basebackup.c:2273 #, c-format msgid "could not get child thread exit status: %m" msgstr "n'a pas pu obtenir le code de sortie du thread : %m" -#: pg_basebackup.c:2169 +#: pg_basebackup.c:2276 #, c-format msgid "child thread exited with error %u" msgstr "le thread a quitté avec le code d'erreur %u" -#: pg_basebackup.c:2198 +#: pg_basebackup.c:2305 #, c-format msgid "syncing data to disk ..." msgstr "synchronisation des données sur disque..." -#: pg_basebackup.c:2223 +#: pg_basebackup.c:2330 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "renommage de backup_manifest.tmp en backup_manifest" -#: pg_basebackup.c:2243 +#: pg_basebackup.c:2350 #, c-format msgid "base backup completed" msgstr "sauvegarde de base terminée" -#: pg_basebackup.c:2326 +#: pg_basebackup.c:2436 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "argument « %s » invalide pour le CHECKPOINT, doit être soit « fast » soit « spread »" -#: pg_basebackup.c:2344 +#: pg_basebackup.c:2454 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "format de sortie « %s » invalide, doit être soit « plain » soit « tar »" -#: pg_basebackup.c:2422 +#: pg_basebackup.c:2535 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "option wal-method « %s » invalide, doit être soit « fetch » soit « stream » soit « none »" -#: pg_basebackup.c:2457 pg_basebackup.c:2469 pg_basebackup.c:2491 -#: pg_basebackup.c:2503 pg_basebackup.c:2509 pg_basebackup.c:2561 -#: pg_basebackup.c:2572 pg_basebackup.c:2582 pg_basebackup.c:2588 -#: pg_basebackup.c:2595 pg_basebackup.c:2607 pg_basebackup.c:2619 -#: pg_basebackup.c:2627 pg_basebackup.c:2640 pg_basebackup.c:2646 -#: pg_basebackup.c:2655 pg_basebackup.c:2667 pg_basebackup.c:2678 -#: pg_basebackup.c:2686 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2037 pg_createsubscriber.c:2047 +#: pg_createsubscriber.c:2055 pg_createsubscriber.c:2083 +#: pg_createsubscriber.c:2115 pg_receivewal.c:748 pg_receivewal.c:760 #: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:835 pg_recvlogical.c:847 -#: pg_recvlogical.c:857 pg_recvlogical.c:864 pg_recvlogical.c:871 -#: pg_recvlogical.c:878 pg_recvlogical.c:885 pg_recvlogical.c:892 -#: pg_recvlogical.c:899 pg_recvlogical.c:906 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_basebackup.c:2467 pg_receivewal.c:758 pg_recvlogical.c:845 +#: pg_basebackup.c:2584 pg_createsubscriber.c:2045 pg_receivewal.c:758 +#: pg_recvlogical.c:863 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_basebackup.c:2490 +#: pg_basebackup.c:2607 #, c-format msgid "cannot specify both format and backup target" msgstr "ne peut pas spécifier à la fois le format et la cible de sauvegarde" -#: pg_basebackup.c:2502 +#: pg_basebackup.c:2619 #, c-format msgid "must specify output directory or backup target" msgstr "doit spécifier un répertoire de sortie ou une cible de sauvegarde" -#: pg_basebackup.c:2508 +#: pg_basebackup.c:2625 #, c-format msgid "cannot specify both output directory and backup target" msgstr "ne peut pas spécifier à la fois le répertoire en sortie et la cible de sauvegarde" -#: pg_basebackup.c:2538 pg_receivewal.c:802 +#: pg_basebackup.c:2655 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "algorithme de compression inconnu : « %s »" -#: pg_basebackup.c:2544 pg_receivewal.c:809 +#: pg_basebackup.c:2661 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "spécification de compression invalide : %s" -#: pg_basebackup.c:2560 +#: pg_basebackup.c:2677 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "la compression client n'est pas possible quand une cible de restauration est indiquée." -#: pg_basebackup.c:2571 +#: pg_basebackup.c:2688 #, c-format msgid "only tar mode backups can be compressed" msgstr "seules les sauvegardes en mode tar peuvent être compressées" -#: pg_basebackup.c:2581 +#: pg_basebackup.c:2698 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "Les journaux de transactions ne peuvent pas être envoyés en flux quand une cible de sauvegarde est indiquée." -#: pg_basebackup.c:2587 +#: pg_basebackup.c:2704 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "ne peut pas envoyer les journaux de transactions vers stdout en mode tar" -#: pg_basebackup.c:2594 +#: pg_basebackup.c:2711 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "les slots de réplications peuvent seulement être utilisés avec la réplication en flux des WAL" -#: pg_basebackup.c:2606 +#: pg_basebackup.c:2723 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot ne peut pas être utilisé avec un nom de slot" #. translator: second %s is an option name -#: pg_basebackup.c:2617 pg_receivewal.c:774 +#: pg_basebackup.c:2734 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "%s a besoin du slot avec l'option --slot" -#: pg_basebackup.c:2625 pg_basebackup.c:2665 pg_basebackup.c:2676 -#: pg_basebackup.c:2684 +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 #, c-format msgid "%s and %s are incompatible options" msgstr "%s et %s sont des options incompatibles" -#: pg_basebackup.c:2639 +#: pg_basebackup.c:2756 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "l'emplacement du répertoire des journaux de transactions ne peut pas être indiqué avec une cible de sauvegarde" -#: pg_basebackup.c:2645 +#: pg_basebackup.c:2762 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "l'emplacement du répertoire des journaux de transactions doit être indiqué uniquement dans le mode plain" -#: pg_basebackup.c:2654 +#: pg_basebackup.c:2771 #, c-format msgid "WAL directory location must be an absolute path" msgstr "l'emplacement du répertoire des journaux de transactions doit être indiqué avec un chemin absolu" -#: pg_basebackup.c:2754 +#: pg_basebackup.c:2871 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "n'a pas pu créer le lien symbolique « %s » : %m" -#: pg_receivewal.c:77 +#: pg_createsubscriber.c:169 +#, c-format +msgid "failed after the end of recovery" +msgstr "échec après la fin de la restauration" + +#: pg_createsubscriber.c:170 +#, c-format +msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." +msgstr "Le serveur cible ne peut plus être utilisé comme un réplicat physique. Vous devez recréer le réplicat physique avant de continuer." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "la publication « %s » dans la base « %s » sur le primaire pourrait être laissé derrière" + +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "Supprimez cette publication avant de tenter de nouveau." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "le slot de réplication « %s » dans la base « %s » sur le primaire pourrait être laissé derrière" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1260 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "Supprimez rapidement ce slot de réplication pour éviter la rétention des fichiers WAL." + +#: pg_createsubscriber.c:219 #, c-format msgid "" -"%s receives PostgreSQL streaming write-ahead logs.\n" +"%s creates a new logical replica from a standby server.\n" "\n" msgstr "" -"%s reçoit le flux des journaux de transactions PostgreSQL.\n" +"%s crée un nouveau réplicat logique à partir d'un serveur secondaire.\n" "\n" -#: pg_receivewal.c:81 pg_recvlogical.c:82 +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 #, c-format msgid "" "\n" @@ -1157,227 +1340,842 @@ msgstr "" "\n" "Options :\n" -#: pg_receivewal.c:82 +#: pg_createsubscriber.c:224 #, c-format -msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" -msgstr "" -" -D, --directory=RÉPERTOIRE reçoit les journaux de transactions dans ce\n" -" répertoire\n" +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --dbname=BASE base de données où créer la souscription\n" -#: pg_receivewal.c:83 pg_recvlogical.c:83 +#: pg_createsubscriber.c:225 #, c-format -msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" -msgstr " -E, --endpos=LSN quitte après avoir reçu le LSN spécifié\n" +msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" +msgstr " [-D, --pgdata=]RÉP_DONNEES emplacement du répertoire de données de l'abonné\n" -#: pg_receivewal.c:84 pg_recvlogical.c:87 +#: pg_createsubscriber.c:226 #, c-format -msgid " --if-not-exists do not error if slot already exists when creating a slot\n" +msgid " -n, --dry-run dry run, just show what would be done\n" msgstr "" -" --if-not-exists ne pas renvoyer une erreur si le slot existe\n" -" déjà lors de sa création\n" +" -n, --dry-run pas d'exécution, affiche\n" +" simplement ce qui sera fait\n" -#: pg_receivewal.c:85 pg_recvlogical.c:89 +#: pg_createsubscriber.c:227 #, c-format -msgid " -n, --no-loop do not loop on connection lost\n" -msgstr " -n, --no-loop ne boucle pas en cas de perte de la connexion\n" +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr " -p, --subscriber-port=PORT numéro de port de l'abonné (par défaut %s)\n" -#: pg_receivewal.c:86 +#: pg_createsubscriber.c:228 #, c-format -msgid " --no-sync do not wait for changes to be written safely to disk\n" -msgstr "" -" --no-sync n'attend pas que les modifications soient\n" -" proprement écrites sur disque\n" +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CHAÎNE_CONNEX chaîne de connexion du publieur\n" -#: pg_receivewal.c:87 pg_recvlogical.c:94 +#: pg_createsubscriber.c:229 #, c-format -msgid "" -" -s, --status-interval=SECS\n" -" time between status packets sent to server (default: %d)\n" -msgstr "" -" -s, --status-interval=SECS durée entre l'envoi de paquets de statut au\n" -" (par défaut %d)\n" +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=RÉP répertoire de la socket à utiliser (par défaut, le répertoire courant)\n" -#: pg_receivewal.c:90 +#: pg_createsubscriber.c:230 #, c-format -msgid " --synchronous flush write-ahead log immediately after writing\n" -msgstr "" -" --synchronous vide le journal de transactions immédiatement\n" -" après son écriture\n" +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=SECS durée en secondes à attendre pour la fin de la restauration\n" -#: pg_receivewal.c:93 +#: pg_createsubscriber.c:231 #, c-format -msgid "" -" -Z, --compress=METHOD[:DETAIL]\n" -" compress as specified\n" -msgstr "" -" -Z, --compress=METHOD[:DETAIL]\n" -" compresse comme indiqué\n" +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NOM nom d'utilisateur pour la connexion de l'abonné\n" -#: pg_receivewal.c:103 +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose affiche des messages verbeux\n" + +#: pg_createsubscriber.c:233 #, c-format msgid "" -"\n" -"Optional actions:\n" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" msgstr "" -"\n" -"Actions optionnelles :\n" +" --config-file=NOMFICHIER utilise le fichier de configuration indiqué\n" +" du serveur principal lors de l'exécution de\n" +" l'instance cible\n" -#: pg_receivewal.c:104 pg_recvlogical.c:79 +#: pg_createsubscriber.c:235 #, c-format -msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" -msgstr "" -" --create-slot crée un nouveau slot de réplication\n" -" (pour le nom du slot, voir --slot)\n" +msgid " --publication=NAME publication name\n" +msgstr " --publication=NOM nom de la publication\n" -#: pg_receivewal.c:105 pg_recvlogical.c:80 +#: pg_createsubscriber.c:236 #, c-format -msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" -msgstr "" -" --drop-slot supprime un nouveau slot de réplication\n" -" (pour le nom du slot, voir --slot)\n" +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=NOM nom du slot de réplication\n" -#: pg_receivewal.c:191 +#: pg_createsubscriber.c:237 #, c-format -msgid "finished segment at %X/%X (timeline %u)" -msgstr "segment terminé à %X/%X (timeline %u)" +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NOM nom de la souscription\n" -#: pg_receivewal.c:198 +#: pg_createsubscriber.c:238 #, c-format -msgid "stopped log streaming at %X/%X (timeline %u)" -msgstr "arrêt du flux streaming à %X/%X (timeline %u)" +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" -#: pg_receivewal.c:214 +#: pg_createsubscriber.c:239 #, c-format -msgid "switched to timeline %u at %X/%X" -msgstr "a basculé sur la timeline %u à %X/%X" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_receivewal.c:224 +#: pg_createsubscriber.c:282 #, c-format -msgid "received interrupt signal, exiting" -msgstr "a reçu un signal d'interruption, quitte" +msgid "could not parse connection string: %s" +msgstr "n'a pas pu analyser la chaîne de connexion : %s" -#: pg_receivewal.c:256 +#: pg_createsubscriber.c:359 #, c-format -msgid "could not close directory \"%s\": %m" -msgstr "n'a pas pu fermer le répertoire « %s » : %m" +msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +msgstr "le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé dans le même répertoire que « %s »" -#: pg_receivewal.c:323 +#: pg_createsubscriber.c:362 #, c-format -msgid "segment file \"%s\" has incorrect size %lld, skipping" -msgstr "le segment « %s » a une taille incorrecte (%lld), ignoré" +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "le programme « %s » a été trouvé par « %s » mais n'est pas de la même version que %s" -#: pg_receivewal.c:340 +#: pg_createsubscriber.c:382 #, c-format -msgid "could not open compressed file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier compressé « %s » : %m" +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "vérification si le répertoire « %s » est le répertoire d'une instance" -#: pg_receivewal.c:343 +#: pg_createsubscriber.c:388 #, c-format -msgid "could not seek in compressed file \"%s\": %m" -msgstr "n'a pas pu chercher dans le fichier compressé « %s » : %m" +msgid "data directory \"%s\" does not exist" +msgstr "le répertoire des données « %s » n'existe pas" -#: pg_receivewal.c:349 +#: pg_createsubscriber.c:396 #, c-format -msgid "could not read compressed file \"%s\": %m" -msgstr "n'a pas pu lire le fichier compressé « %s » : %m" +msgid "directory \"%s\" is not a database cluster directory" +msgstr "le répertoire « %s » n'est pas un répertoire d'instance" -#: pg_receivewal.c:352 +#: pg_createsubscriber.c:513 #, c-format -msgid "could not read compressed file \"%s\": read %d of %zu" -msgstr "n'a pas pu lire le fichier compressé « %s » : a lu %d sur %zu" +msgid "connection to database failed: %s" +msgstr "échec de la connexion à la base de données : %s" -#: pg_receivewal.c:362 +#: pg_createsubscriber.c:526 #, c-format -msgid "compressed segment file \"%s\" has incorrect uncompressed size %d, skipping" -msgstr "le segment compressé « %s » a une taille %d non compressé incorrecte, ignoré" +msgid "could not clear search_path: %s" +msgstr "n'a pas pu effacer search_path : %s" -#: pg_receivewal.c:390 +#: pg_createsubscriber.c:566 #, c-format -msgid "could not create LZ4 decompression context: %s" -msgstr "n'a pas pu créer le contexte de décompression LZ4 : %s" +msgid "getting system identifier from publisher" +msgstr "recherche de l'identifieur système sur le publieur" -#: pg_receivewal.c:402 +#: pg_createsubscriber.c:573 #, c-format -msgid "could not read file \"%s\": %m" -msgstr "n'a pas pu lire le fichier « %s » : %m" +msgid "could not get system identifier: %s" +msgstr "n'a pas pu obtenir l'identifiant du système : %s" -#: pg_receivewal.c:420 +#: pg_createsubscriber.c:579 #, c-format -msgid "could not decompress file \"%s\": %s" -msgstr "n'a pas pu décompresser le fichier « %s » : %s" +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "n'a pas pu obtenir l'identifiant du système : lu %d octets, %d attendus" -#: pg_receivewal.c:443 +#: pg_createsubscriber.c:586 #, c-format -msgid "could not free LZ4 decompression context: %s" -msgstr "n'a pas pu libérer le contexte de décompression LZ4 : %s" +msgid "system identifier is %llu on publisher" +msgstr "l'identifieur système est %llu sur le publieur" -#: pg_receivewal.c:448 +#: pg_createsubscriber.c:607 #, c-format -msgid "compressed segment file \"%s\" has incorrect uncompressed size %zu, skipping" -msgstr "le fichier segment compressé « %s » a une taille %zu décompressée incorrecte, ignoré" +msgid "getting system identifier from subscriber" +msgstr "recherche l'identifieur système sur l'abonné" -#: pg_receivewal.c:453 +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 #, c-format -msgid "cannot check file \"%s\": compression with %s not supported by this build" -msgstr "ne peut pas vérifier le fichier « %s » : la compression avec %s n'a pas été intégrée lors de la compilation" +msgid "control file appears to be corrupt" +msgstr "le fichier de contrôle semble corrompu" -#: pg_receivewal.c:578 +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 #, c-format -msgid "starting log streaming at %X/%X (timeline %u)" -msgstr "commence le flux des journaux à %X/%X (timeline %u)" +msgid "system identifier is %llu on subscriber" +msgstr "l'identifieur système est %llu sur l'abonné" -#: pg_receivewal.c:693 pg_recvlogical.c:783 +#: pg_createsubscriber.c:637 #, c-format -msgid "could not parse end position \"%s\"" -msgstr "n'a pas pu analyser la position finale « %s »" +msgid "modifying system identifier of subscriber" +msgstr "modification de l'identifieur système sur l'abonné" -#: pg_receivewal.c:766 +#: pg_createsubscriber.c:659 #, c-format -msgid "cannot use --create-slot together with --drop-slot" -msgstr "ne peut pas utiliser --create-slot avec --drop-slot" +msgid "running pg_resetwal on the subscriber" +msgstr "exécution de pg_resetwal sur l'abonné" -#: pg_receivewal.c:782 +#: pg_createsubscriber.c:671 #, c-format -msgid "cannot use --synchronous together with --no-sync" -msgstr "ne peut pas utiliser --synchronous avec --no-sync" +msgid "subscriber successfully changed the system identifier" +msgstr "l'abonné a modifié avec succès l'identifieur système" -#: pg_receivewal.c:792 +#: pg_createsubscriber.c:673 #, c-format -msgid "no target directory specified" -msgstr "aucun répertoire cible indiqué" +msgid "could not change system identifier of subscriber: %s" +msgstr "n'a pas pu modifier l'identifiant du système abonné : %s" -#: pg_receivewal.c:816 +#: pg_createsubscriber.c:697 #, c-format -msgid "compression with %s is not yet supported" -msgstr "la méthode de compression %s n'est pas encore supportée" +msgid "could not obtain database OID: %s" +msgstr "n'a pas pu obtenir l'OID de la base : %s" -#: pg_receivewal.c:859 +#: pg_createsubscriber.c:704 #, c-format -msgid "replication connection using slot \"%s\" is unexpectedly database specific" -msgstr "la connexion de réplication utilisant le slot « %s » est spécifique à une base, ce qui est inattendu" +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "n'a pas pu obtenir l'OID de la base de données : %d lignes attendues, %d ligne reçue" -#: pg_receivewal.c:878 pg_recvlogical.c:954 +#: pg_createsubscriber.c:776 #, c-format -msgid "dropping replication slot \"%s\"" -msgstr "suppression du slot de réplication « %s »" +msgid "create replication slot \"%s\" on publisher" +msgstr "création du slot de réplication « %s » sur le publieur" -#: pg_receivewal.c:889 pg_recvlogical.c:964 +#: pg_createsubscriber.c:796 #, c-format -msgid "creating replication slot \"%s\"" +msgid "could not write an additional WAL record: %s" +msgstr "n'a pas pu écrire un enregistrement WAL supplémentaire : %s" + +#: pg_createsubscriber.c:822 +#, c-format +msgid "could not obtain recovery progress: %s" +msgstr "n'a pas pu obtenir la progression de la restauration : %s" + +#: pg_createsubscriber.c:854 +#, c-format +msgid "checking settings on publisher" +msgstr "vérification de la configuration du publieur" + +#: pg_createsubscriber.c:864 +#, c-format +msgid "primary server cannot be in recovery" +msgstr "le serveur primaire ne peut pas être en restauration" + +#: pg_createsubscriber.c:888 +#, c-format +msgid "could not obtain publisher settings: %s" +msgstr "n'a pas pu obtenir la configuration du publieur : %s" + +#: pg_createsubscriber.c:914 +#, c-format +msgid "publisher requires wal_level >= \"logical\"" +msgstr "le publieur requiert wal_level >= « logical »" + +#: pg_createsubscriber.c:920 +#, c-format +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "le publieur requiert %d slots de réplication, mais seuls %d restent" + +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Augmentez le paramètre de configuration « %s » à au moins %d." + +#: pg_createsubscriber.c:929 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "le publieur requiert %d processus wal sender, mais seuls %d restent" + +#: pg_createsubscriber.c:938 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "l'option two_phase ne sera pas activée pour les slots de réplication" + +#: pg_createsubscriber.c:939 +#, c-format +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "Les souscriptions seront créées avec l'option two_phase désactivé. Les transactions préparées seront répliquées au COMMIT PREPARED." + +#: pg_createsubscriber.c:971 +#, c-format +msgid "checking settings on subscriber" +msgstr "vérification de la configuration sur l'abonné" + +#: pg_createsubscriber.c:978 +#, c-format +msgid "target server must be a standby" +msgstr "le serveur cible doit être un secondaire" + +#: pg_createsubscriber.c:1002 +#, c-format +msgid "could not obtain subscriber settings: %s" +msgstr "n'a pas pu obtenir la configuration de l'abonné : %s" + +#: pg_createsubscriber.c:1026 +#, c-format +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "l'abonné requiert %d slots de réplication, mais seuls %d restent" + +#: pg_createsubscriber.c:1035 +#, c-format +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "l'abonné requiert %d processus worker de réplication logique, mais seuls %d restent" + +#: pg_createsubscriber.c:1044 +#, c-format +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "l'abonné requiert %d processus worker, mais seuls %d restent" + +#: pg_createsubscriber.c:1079 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "suppression de la souscription « %s » dans la base de données « %s »" + +#: pg_createsubscriber.c:1088 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "n'a pas pu supprimer la souscription « %s » : %s" + +#: pg_createsubscriber.c:1123 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "n'a pas pu obtenir les souscriptions pré-existantes : %s" + +#: pg_createsubscriber.c:1258 +#, c-format +msgid "could not drop replication slot \"%s\" on primary" +msgstr "n'a pas pu supprimer le slot de réplication « %s » sur le primaire" + +#: pg_createsubscriber.c:1292 +#, c-format +msgid "could not obtain failover replication slot information: %s" +msgstr "n'a pas pu obtenir l'information de slot de réplication failover : %s" + +#: pg_createsubscriber.c:1294 pg_createsubscriber.c:1303 +#, c-format +msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." +msgstr "Supprimez rapidement les slots de réplication failover sur l'abonnée pour éviter la rétention des fichiers WAL." + +#: pg_createsubscriber.c:1302 +#, c-format +msgid "could not drop failover replication slot" +msgstr "n'a pas pu supprimer le slot de réplication failover" + +#: pg_createsubscriber.c:1324 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "création du slot de réplication « %s » dans la base « %s »" + +#: pg_createsubscriber.c:1342 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "n'a pas pu créer le slot de réplication « %s » dans la base « %s » : %s" + +#: pg_createsubscriber.c:1372 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "suppression du slot de réplication « %s » dans la base « %s »" + +#: pg_createsubscriber.c:1388 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "n'a pas pu supprimer le slot de réplication « %s » dans la base « %s » : %s" + +#: pg_createsubscriber.c:1409 +#, c-format +msgid "pg_ctl failed with exit code %d" +msgstr "échec de pg_ctl avec un code de retour %d" + +#: pg_createsubscriber.c:1414 +#, c-format +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "pg_ctl a été terminé par l'exception 0x%X" + +#: pg_createsubscriber.c:1416 +#, c-format +msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "" +"Voir le fichier d'en-tête C « ntstatus.h » pour une description de la valeur\n" +"hexadécimale." + +#: pg_createsubscriber.c:1418 +#, c-format +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "pg_ctl a été terminé par le signal %d : %s" + +#: pg_createsubscriber.c:1424 +#, c-format +msgid "pg_ctl exited with unrecognized status %d" +msgstr "pg_ctl a quitté avec un statut %d non reconnu" + +#: pg_createsubscriber.c:1427 +#, c-format +msgid "The failed command was: %s" +msgstr "La commande échouée était : %s" + +#: pg_createsubscriber.c:1473 +#, c-format +msgid "server was started" +msgstr "le serveur a été démarré" + +#: pg_createsubscriber.c:1488 +#, c-format +msgid "server was stopped" +msgstr "le serveur a été arrêté" + +#: pg_createsubscriber.c:1507 +#, c-format +msgid "waiting for the target server to reach the consistent state" +msgstr "en attente de l'atteinte de l'état de cohérence sur le serveur cible" + +#: pg_createsubscriber.c:1530 +#, c-format +msgid "recovery timed out" +msgstr "délai de restauration atteint" + +#: pg_createsubscriber.c:1543 +#, c-format +msgid "server did not end recovery" +msgstr "le serveur n'a pas terminé la restauration" + +#: pg_createsubscriber.c:1545 +#, c-format +msgid "target server reached the consistent state" +msgstr "le serveur cible a atteint l'état de cohérence" + +#: pg_createsubscriber.c:1546 +#, c-format +msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." +msgstr "Si pg_createsubscriber échoue après cela, vous devez recréer le réplicat physique avant de continuer." + +#: pg_createsubscriber.c:1573 +#, c-format +msgid "could not obtain publication information: %s" +msgstr "n'a pas pu obtenir une information sur la publication : %s" + +#: pg_createsubscriber.c:1587 +#, c-format +msgid "publication \"%s\" already exists" +msgstr "la publication « %s » existe déjà" + +#: pg_createsubscriber.c:1588 +#, c-format +msgid "Consider renaming this publication before continuing." +msgstr "Pensez à renommer cette publication avant de continuer." + +#: pg_createsubscriber.c:1595 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "création de la publication « %s » dans la base de données « %s »" + +#: pg_createsubscriber.c:1608 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "n'a pas pu créer la publication « %s » dans la base de données « %s » : %s" + +#: pg_createsubscriber.c:1637 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "suppression de la publication « %s » dans la base de données « %s »" + +#: pg_createsubscriber.c:1651 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "n'a pas pu supprimer la publication « %s » dans la base de données « %s » : %s" + +#: pg_createsubscriber.c:1697 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "création de la souscription « %s » dans la base de données « %s »" + +#: pg_createsubscriber.c:1718 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "n'a pas pu créer la souscription « %s » dans la base « %s » : %s" + +#: pg_createsubscriber.c:1763 +#, c-format +msgid "could not obtain subscription OID: %s" +msgstr "n'a pas pu obtenir l'OID de la souscription : %s" + +#: pg_createsubscriber.c:1770 +#, c-format +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "n'a pas pu obtenir l'OID de la souscription : attendait %d lignes, a reçu %d ligne" + +#: pg_createsubscriber.c:1794 +#, c-format +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "configuration de la progression de la réplication (nom du noeud « %s » , LSN %s) dans la base de données « %s »" + +#: pg_createsubscriber.c:1809 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "n'a pas pu configurer la progression de la réplication pour la souscription « %s » : %s" + +#: pg_createsubscriber.c:1840 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "activation de la souscription « %s » dans la base de données « %s »" + +#: pg_createsubscriber.c:1852 +#, c-format +msgid "could not enable subscription \"%s\": %s" +msgstr "n'a pas pu activer la souscription « %s » : %s" + +#: pg_createsubscriber.c:1944 +#, c-format +msgid "cannot be executed by \"root\"" +msgstr "ne peut pas être exécuté par « root »" + +#: pg_createsubscriber.c:1945 +#, c-format +msgid "You must run %s as the PostgreSQL superuser." +msgstr "Vous devez exécuter %s en tant que super-utilisateur PostgreSQL." + +#: pg_createsubscriber.c:1966 +#, c-format +msgid "database \"%s\" specified more than once" +msgstr "la base de données « %s » est spécifiée plus d'une fois" + +#: pg_createsubscriber.c:2007 +#, c-format +msgid "publication \"%s\" specified more than once" +msgstr "la publication « %s » est spécifiée plus d'une fois" + +#: pg_createsubscriber.c:2019 +#, c-format +msgid "replication slot \"%s\" specified more than once" +msgstr "le slot de réplication « %s » est spécifié plus d'une fois" + +#: pg_createsubscriber.c:2031 +#, c-format +msgid "subscription \"%s\" specified more than once" +msgstr "la souscription « %s » est spécifiée plus d'une fois" + +#: pg_createsubscriber.c:2054 +#, c-format +msgid "no subscriber data directory specified" +msgstr "aucune chaîne de connexion de l'abonné indiquée" + +#: pg_createsubscriber.c:2065 +#, c-format +msgid "could not determine current directory" +msgstr "n'a pas pu déterminer le répertoire courant" + +#: pg_createsubscriber.c:2082 +#, c-format +msgid "no publisher connection string specified" +msgstr "aucune chaîne de connexion du publieur indiquée" + +#: pg_createsubscriber.c:2086 +#, c-format +msgid "validating publisher connection string" +msgstr "validation de la chaîne de connexion du publieur" + +#: pg_createsubscriber.c:2092 +#, c-format +msgid "validating subscriber connection string" +msgstr "validation de la chaîne de connexion de l'abonné" + +#: pg_createsubscriber.c:2097 +#, c-format +msgid "no database was specified" +msgstr "aucune base de données n'a été indiquée" + +#: pg_createsubscriber.c:2109 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "le nom de la base de données « %s » a été extrait de la chaîne de connexion du publieur" + +#: pg_createsubscriber.c:2114 +#, c-format +msgid "no database name specified" +msgstr "aucun nom de base de données indiqué" + +#: pg_createsubscriber.c:2124 +#, c-format +msgid "wrong number of publication names specified" +msgstr "mauvais nombre de noms de publication indiqués" + +#: pg_createsubscriber.c:2125 +#, c-format +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "Le nombre de noms de publication indiqués (%d) doit correspondre au nombre de noms de bases de données indiqués (%d)" + +#: pg_createsubscriber.c:2131 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "mauvais nombre de noms de souscription indiqués" + +#: pg_createsubscriber.c:2132 +#, c-format +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "Le nombre de noms de souscriptions indiqués (%d) doit correspondre au nombre de noms de bases de données indiqués (%d)" + +#: pg_createsubscriber.c:2138 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "mauvais nombre de noms de slots de réplication indiqués" + +#: pg_createsubscriber.c:2139 +#, c-format +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "Le nombre de noms de slots de réplication indiqués (%d) doit correspondre au nombre de noms de bases de données indiqués (%d)" + +#: pg_createsubscriber.c:2168 +#, c-format +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "le répertoire de données de l'abonné n'est pas une copie de l'instance source" + +#: pg_createsubscriber.c:2181 +#, c-format +msgid "standby server is running" +msgstr "le serveur secondaire est en cours d'exécution" + +#: pg_createsubscriber.c:2182 +#, c-format +msgid "Stop the standby server and try again." +msgstr "Arrêtez le secondaire et tentez de nouveau." + +#: pg_createsubscriber.c:2191 +#, c-format +msgid "starting the standby server with command-line options" +msgstr "lancement du serveur secondaire avec les options en ligne de commande" + +#: pg_createsubscriber.c:2207 pg_createsubscriber.c:2242 +#, c-format +msgid "stopping the subscriber" +msgstr "arrêt de l'abonné" + +#: pg_createsubscriber.c:2221 +#, c-format +msgid "starting the subscriber" +msgstr "lancement de l'abonné" + +#: pg_createsubscriber.c:2250 +#, c-format +msgid "Done!" +msgstr "Terminé !" + +#: pg_receivewal.c:77 +#, c-format +msgid "" +"%s receives PostgreSQL streaming write-ahead logs.\n" +"\n" +msgstr "" +"%s reçoit le flux des journaux de transactions PostgreSQL.\n" +"\n" + +#: pg_receivewal.c:82 +#, c-format +msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" +msgstr "" +" -D, --directory=RÉPERTOIRE reçoit les journaux de transactions dans ce\n" +" répertoire\n" + +#: pg_receivewal.c:83 pg_recvlogical.c:93 +#, c-format +msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" +msgstr " -E, --endpos=LSN quitte après avoir reçu le LSN spécifié\n" + +#: pg_receivewal.c:84 pg_recvlogical.c:97 +#, c-format +msgid " --if-not-exists do not error if slot already exists when creating a slot\n" +msgstr "" +" --if-not-exists ne pas renvoyer une erreur si le slot existe\n" +" déjà lors de sa création\n" + +#: pg_receivewal.c:85 pg_recvlogical.c:99 +#, c-format +msgid " -n, --no-loop do not loop on connection lost\n" +msgstr " -n, --no-loop ne boucle pas en cas de perte de la connexion\n" + +#: pg_receivewal.c:86 +#, c-format +msgid " --no-sync do not wait for changes to be written safely to disk\n" +msgstr "" +" --no-sync n'attend pas que les modifications soient\n" +" proprement écrites sur disque\n" + +#: pg_receivewal.c:87 pg_recvlogical.c:104 +#, c-format +msgid "" +" -s, --status-interval=SECS\n" +" time between status packets sent to server (default: %d)\n" +msgstr "" +" -s, --status-interval=SECS durée entre l'envoi de paquets de statut au\n" +" serveur (par défaut %d)\n" + +#: pg_receivewal.c:90 +#, c-format +msgid " --synchronous flush write-ahead log immediately after writing\n" +msgstr "" +" --synchronous vide le journal de transactions immédiatement\n" +" après son écriture\n" + +#: pg_receivewal.c:93 +#, c-format +msgid "" +" -Z, --compress=METHOD[:DETAIL]\n" +" compress as specified\n" +msgstr "" +" -Z, --compress=METHOD[:DETAIL]\n" +" compresse comme indiqué\n" + +#: pg_receivewal.c:103 +#, c-format +msgid "" +"\n" +"Optional actions:\n" +msgstr "" +"\n" +"Actions optionnelles :\n" + +#: pg_receivewal.c:104 pg_recvlogical.c:89 +#, c-format +msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" +msgstr "" +" --create-slot crée un nouveau slot de réplication\n" +" (pour le nom du slot, voir --slot)\n" + +#: pg_receivewal.c:105 pg_recvlogical.c:90 +#, c-format +msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" +msgstr "" +" --drop-slot supprime un nouveau slot de réplication\n" +" (pour le nom du slot, voir --slot)\n" + +#: pg_receivewal.c:191 +#, c-format +msgid "finished segment at %X/%X (timeline %u)" +msgstr "segment terminé à %X/%X (timeline %u)" + +#: pg_receivewal.c:198 +#, c-format +msgid "stopped log streaming at %X/%X (timeline %u)" +msgstr "arrêt du flux streaming à %X/%X (timeline %u)" + +#: pg_receivewal.c:214 +#, c-format +msgid "switched to timeline %u at %X/%X" +msgstr "a basculé sur la timeline %u à %X/%X" + +#: pg_receivewal.c:224 pg_recvlogical.c:1053 +#, c-format +msgid "received interrupt signal, exiting" +msgstr "a reçu un signal d'interruption, quitte" + +#: pg_receivewal.c:256 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "n'a pas pu fermer le répertoire « %s » : %m" + +#: pg_receivewal.c:323 +#, c-format +msgid "segment file \"%s\" has incorrect size %lld, skipping" +msgstr "le segment « %s » a une taille incorrecte (%lld), ignoré" + +#: pg_receivewal.c:340 +#, c-format +msgid "could not open compressed file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier compressé « %s » : %m" + +#: pg_receivewal.c:343 +#, c-format +msgid "could not seek in compressed file \"%s\": %m" +msgstr "n'a pas pu chercher dans le fichier compressé « %s » : %m" + +#: pg_receivewal.c:349 +#, c-format +msgid "could not read compressed file \"%s\": %m" +msgstr "n'a pas pu lire le fichier compressé « %s » : %m" + +#: pg_receivewal.c:352 +#, c-format +msgid "could not read compressed file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier compressé « %s » : a lu %d sur %zu" + +#: pg_receivewal.c:362 +#, c-format +msgid "compressed segment file \"%s\" has incorrect uncompressed size %d, skipping" +msgstr "le segment compressé « %s » a une taille %d non compressé incorrecte, ignoré" + +#: pg_receivewal.c:390 +#, c-format +msgid "could not create LZ4 decompression context: %s" +msgstr "n'a pas pu créer le contexte de décompression LZ4 : %s" + +#: pg_receivewal.c:420 +#, c-format +msgid "could not decompress file \"%s\": %s" +msgstr "n'a pas pu décompresser le fichier « %s » : %s" + +#: pg_receivewal.c:443 +#, c-format +msgid "could not free LZ4 decompression context: %s" +msgstr "n'a pas pu libérer le contexte de décompression LZ4 : %s" + +#: pg_receivewal.c:448 +#, c-format +msgid "compressed segment file \"%s\" has incorrect uncompressed size %zu, skipping" +msgstr "le fichier segment compressé « %s » a une taille %zu décompressée incorrecte, ignoré" + +#: pg_receivewal.c:453 +#, c-format +msgid "cannot check file \"%s\": compression with %s not supported by this build" +msgstr "ne peut pas vérifier le fichier « %s » : la compression avec %s n'a pas été intégrée lors de la compilation" + +#: pg_receivewal.c:578 +#, c-format +msgid "starting log streaming at %X/%X (timeline %u)" +msgstr "commence le flux des journaux à %X/%X (timeline %u)" + +#: pg_receivewal.c:693 pg_recvlogical.c:801 +#, c-format +msgid "could not parse end position \"%s\"" +msgstr "n'a pas pu analyser la position finale « %s »" + +#: pg_receivewal.c:766 +#, c-format +msgid "cannot use --create-slot together with --drop-slot" +msgstr "ne peut pas utiliser --create-slot avec --drop-slot" + +#: pg_receivewal.c:782 +#, c-format +msgid "cannot use --synchronous together with --no-sync" +msgstr "ne peut pas utiliser --synchronous avec --no-sync" + +#: pg_receivewal.c:792 +#, c-format +msgid "no target directory specified" +msgstr "aucun répertoire cible indiqué" + +#: pg_receivewal.c:816 +#, c-format +msgid "compression with %s is not yet supported" +msgstr "la méthode de compression %s n'est pas encore supportée" + +#: pg_receivewal.c:859 +#, c-format +msgid "replication connection using slot \"%s\" is unexpectedly database specific" +msgstr "la connexion de réplication utilisant le slot « %s » est spécifique à une base, ce qui est inattendu" + +#: pg_receivewal.c:878 pg_recvlogical.c:972 +#, c-format +msgid "dropping replication slot \"%s\"" +msgstr "suppression du slot de réplication « %s »" + +#: pg_receivewal.c:889 pg_recvlogical.c:982 +#, c-format +msgid "creating replication slot \"%s\"" msgstr "création du slot de réplication « %s »" -#: pg_receivewal.c:918 pg_recvlogical.c:988 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "déconnecté" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:992 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "déconnecté, attente de %d secondes avant une nouvelle tentative" -#: pg_recvlogical.c:74 +#: pg_recvlogical.c:84 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -1386,7 +2184,7 @@ msgstr "" "%s contrôle le flux des modifications logiques de PostgreSQL.\n" "\n" -#: pg_recvlogical.c:78 +#: pg_recvlogical.c:88 #, c-format msgid "" "\n" @@ -1395,21 +2193,21 @@ msgstr "" "\n" "Action à réaliser :\n" -#: pg_recvlogical.c:81 +#: pg_recvlogical.c:91 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr "" " --start lance le flux dans un slot de réplication (pour\n" " le nom du slot, voir --slot)\n" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr "" " -f, --file=FICHIER trace la réception dans ce fichier, - pour\n" " stdout\n" -#: pg_recvlogical.c:85 +#: pg_recvlogical.c:95 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -1418,14 +2216,14 @@ msgstr "" " -F --fsync-interval=SECS durée entre les fsyncs vers le fichier de sortie\n" " (par défaut %d)\n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:98 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr "" " -I, --startpos=LSN position de début du streaming dans le slot\n" " existant\n" -#: pg_recvlogical.c:90 +#: pg_recvlogical.c:100 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -1435,145 +2233,145 @@ msgstr "" " -o, --option=NOM[=VALEUR] passe l'option NOM avec la valeur optionnelle\n" " VALEUR au plugin en sortie\n" -#: pg_recvlogical.c:93 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr "" " -P, --plugin=PLUGIN utilise le plugin PLUGIN en sortie (par défaut\n" " %s)\n" -#: pg_recvlogical.c:96 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOT nom du slot de réplication logique\n" -#: pg_recvlogical.c:97 +#: pg_recvlogical.c:107 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr " -t, --two-phase active le décodage des transactions préparées lors de la création d'un slot\n" -#: pg_recvlogical.c:102 +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=BASE base de données de connexion\n" -#: pg_recvlogical.c:135 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "confirmation d'écriture jusqu'à %X/%X et de synchronisation jusqu'à %X/%X (slot %s)" -#: pg_recvlogical.c:159 receivelog.c:360 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "n'a pas pu envoyer le paquet d'informations en retour : %s" -#: pg_recvlogical.c:227 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "commence le flux des journaux à %X/%X (slot %s)" -#: pg_recvlogical.c:269 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "flux lancé" -#: pg_recvlogical.c:333 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "n'a pas pu ouvrir le journal applicatif « %s » : %m" -#: pg_recvlogical.c:362 receivelog.c:882 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "socket invalide : %s" -#: pg_recvlogical.c:415 receivelog.c:910 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: pg_recvlogical.c:422 receivelog.c:959 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "n'a pas pu recevoir des données du flux de WAL : %s" -#: pg_recvlogical.c:464 pg_recvlogical.c:515 receivelog.c:1003 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 #: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "en-tête de flux trop petit : %d" -#: pg_recvlogical.c:499 receivelog.c:843 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "entête non reconnu du flux : « %c »" -#: pg_recvlogical.c:553 pg_recvlogical.c:565 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "n'a pas pu écrire %d octets dans le journal de transactions « %s » : %m" -#: pg_recvlogical.c:619 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "fin inattendue du flux de réplication : %s" -#: pg_recvlogical.c:778 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "n'a pas pu analyser la position de départ « %s »" -#: pg_recvlogical.c:856 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "aucun slot de réplication indiqué" -#: pg_recvlogical.c:863 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "aucun fichier cible indiqué" -#: pg_recvlogical.c:870 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "aucune base de données indiquée" -#: pg_recvlogical.c:877 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "au moins une action doit être indiquée" -#: pg_recvlogical.c:884 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "ne peut pas utiliser --create-slot ou --start avec --drop-slot" -#: pg_recvlogical.c:891 +#: pg_recvlogical.c:909 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "ne peut pas utiliser --create-slot ou --drop-slot avec --startpos" -#: pg_recvlogical.c:898 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos peut seulement être spécifié avec --start" -#: pg_recvlogical.c:905 +#: pg_recvlogical.c:923 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase peut seulement être spécifié avec --create-slot" -#: pg_recvlogical.c:938 +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "n'a pas pu établir une connexion de réplication spécifique à la base" -#: pg_recvlogical.c:1032 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "position finale %X/%X atteinte par keepalive" -#: pg_recvlogical.c:1035 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "position finale %X/%X atteinte à l'enregistrement WAL %X/%X" @@ -1690,7 +2488,7 @@ msgstr "ensemble de résultats inattendu après la fin de la timeline : a récup msgid "could not parse next timeline's starting point \"%s\"" msgstr "n'a pas pu analyser la position de départ de la prochaine timeline « %s »" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1201 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %s" @@ -1715,495 +2513,121 @@ msgstr "n'a pas pu écrire %d octets dans le journal de transactions « %s » : msgid "could not send copy-end packet: %s" msgstr "n'a pas pu envoyer le paquet de fin de copie : %s" -#: streamutil.c:158 +#: streamutil.c:162 msgid "Password: " msgstr "Mot de passe : " -#: streamutil.c:181 +#: streamutil.c:189 #, c-format msgid "could not connect to server" msgstr "n'a pas pu se connecter au serveur" -#: streamutil.c:222 +#: streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "n'a pas pu effacer search_path : %s" +msgid "could not clear \"search_path\": %s" +msgstr "n'a pas pu effacer « search_path » : %s" -#: streamutil.c:238 +#: streamutil.c:246 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "n'a pas pu déterminer la configuration serveur de integer_datetimes" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "n'a pas pu déterminer la configuration serveur de « integer_datetimes »" -#: streamutil.c:245 +#: streamutil.c:253 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "l'option de compilation integer_datetimes ne correspond pas au serveur" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "l'option de compilation « integer_datetimes » ne correspond pas au serveur" -#: streamutil.c:296 +#: streamutil.c:372 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "n'a pas pu récupéré la taille d'un segment WAL : a obtenu %d lignes et %d champs, attendait %d lignes et %d champs (ou plus)" -#: streamutil.c:306 +#: streamutil.c:382 #, c-format msgid "WAL segment size could not be parsed" msgstr "la taille du segment WAL n'a pas pu être analysée" -#: streamutil.c:324 +#: streamutil.c:400 +#, c-format +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "le serveur distant a rapporté une taille invalide du segment WAL (%d octet)" +msgstr[1] "le serveur distant a rapporté une taille invalide du segment WAL (%d octets)" + +#: streamutil.c:404 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d bytes" -msgstr[0] "la taille d'un WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go mais le serveur distant a rapporté une valeur de %d octet" -msgstr[1] "la taille d'un WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go mais le serveur distant a rapporté une valeur de %d octets" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go." -#: streamutil.c:369 +#: streamutil.c:446 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "n'a pas pu récupérer les options d'accès du groupe : a obtenu %d lignes et %d champs, attendait %d lignes et %d champs (ou plus)" -#: streamutil.c:378 +#: streamutil.c:455 #, c-format msgid "group access flag could not be parsed: %s" msgstr "l'option d'accès du groupe n'a pas pu être analysé : %s" -#: streamutil.c:421 streamutil.c:458 +#: streamutil.c:498 streamutil.c:535 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "n'a pas pu identifier le système : a récupéré %d lignes et %d champs, attendait %d lignes et %d champs (ou plus)." -#: streamutil.c:510 +#: streamutil.c:587 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "n'a pas pu lire le slot de réplication « %s » : a récupéré %d lignes et %d champs, attendait %d lignes et %d champs" -#: streamutil.c:522 +#: streamutil.c:599 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "le slot de réplication « %s » n'existe pas" -#: streamutil.c:533 +#: streamutil.c:610 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "attendait un slot de réplication physique, a obtenu le type « %s » à la place" -#: streamutil.c:547 +#: streamutil.c:624 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "n'a pas pu analyser le champ restart_lsn « %s » pour le slot de réplication « %s »" -#: streamutil.c:664 +#: streamutil.c:741 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "n'a pas pu créer le slot de réplication « %s » : a récupéré %d lignes et %d champs, attendait %d lignes et %d champs" -#: streamutil.c:708 +#: streamutil.c:785 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "n'a pas pu supprimer le slot de réplication « %s » : a récupéré %d lignes et %d champs, attendait %d lignes et %d champs" -#: walmethods.c:721 walmethods.c:1264 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "n'a pas pu compresser les données" -#: walmethods.c:750 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "n'a pas pu réinitialiser le flux de compression" -#: walmethods.c:888 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "erreur d'implémentation : les fichiers tar ne peuvent pas avoir plus d'un fichier ouvert" -#: walmethods.c:903 +#: walmethods.c:907 msgid "could not create tar header" msgstr "n'a pas pu créer l'en-tête du fichier tar" -#: walmethods.c:920 walmethods.c:961 walmethods.c:1166 walmethods.c:1179 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "n'a pas pu modifier les paramètres de compression" -#: walmethods.c:1052 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "suppression non supportée avec la compression" -#: walmethods.c:1288 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "n'a pas pu fermer le flux de compression" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#, c-format -#~ msgid "" -#~ " --compression-method=METHOD\n" -#~ " method to compress logs\n" -#~ msgstr "" -#~ " --compression-method=METHODE\n" -#~ " méthode pour compresser les journaux\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide puis quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version puis quitte\n" - -#, c-format -#~ msgid " -Z, --compress=0-9 compress tar output with given compression level\n" -#~ msgstr "" -#~ " -Z, --compress=0-9 compresse la sortie tar avec le niveau de\n" -#~ " compression indiqué\n" - -#, c-format -#~ msgid " -Z, --compress=1-9 compress logs with given compression level\n" -#~ msgstr "" -#~ " -Z, --compress=0-9 compresse les journaux avec le niveau de\n" -#~ " compression indiqué\n" - -#~ msgid " -x, --xlog include required WAL files in backup (fetch mode)\n" -#~ msgstr "" -#~ " -x, --xlog inclut les journaux de transactions nécessaires\n" -#~ " dans la sauvegarde (mode fetch)\n" - -#~ msgid "%s: WAL directory \"%s\" not removed at user's request\n" -#~ msgstr "%s : répertoire des journaux de transactions « %s » non supprimé à la demande de l'utilisateur\n" - -#~ msgid "%s: WAL directory location must be an absolute path\n" -#~ msgstr "" -#~ "%s : l'emplacement du répertoire des journaux de transactions doit être\n" -#~ "indiqué avec un chemin absolu\n" - -#~ msgid "%s: WAL streaming can only be used in plain mode\n" -#~ msgstr "%s : le flux de journaux de transactions peut seulement être utilisé en mode plain\n" - -#~ msgid "%s: cannot specify both --xlog and --xlog-method\n" -#~ msgstr "%s : ne peut pas spécifier à la fois --xlog et --xlog-method\n" - -#~ msgid "%s: child process did not exit normally\n" -#~ msgstr "%s : le processus fils n'a pas quitté normalement\n" - -#~ msgid "%s: child process exited with error %d\n" -#~ msgstr "%s : le processus fils a quitté avec le code erreur %d\n" - -#~ msgid "%s: could not access directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu accéder au répertoire « %s » : %s\n" - -#~ msgid "%s: could not clear search_path: %s" -#~ msgstr "%s : n'a pas pu effacer search_path : %s" - -#~ msgid "%s: could not close directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu fermer le répertoire « %s » : %s\n" - -#~ msgid "%s: could not close file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu fermer le fichier « %s » : %s\n" - -#~ msgid "%s: could not close file %s: %s\n" -#~ msgstr "%s : n'a pas pu fermer le fichier %s : %s\n" - -#~ msgid "%s: could not connect to server\n" -#~ msgstr "%s : n'a pas pu se connecter au serveur\n" - -#~ msgid "%s: could not connect to server: %s" -#~ msgstr "%s : n'a pas pu se connecter au serveur : %s" - -#~ msgid "%s: could not create archive status file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le fichier de statut d'archivage « %s » : %s\n" - -#~ msgid "%s: could not create directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le répertoire « %s » : %s\n" - -#~ msgid "%s: could not create file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le fichier « %s » : %s\n" - -#~ msgid "%s: could not create symbolic link \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le lien symbolique « %s » : %s\n" - -#~ msgid "%s: could not fsync file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu synchroniser sur disque le fichier « %s » : %s\n" - -#~ msgid "%s: could not fsync log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu synchroniser sur disque le fichier « %s » : %s\n" - -#~ msgid "%s: could not get current position in file %s: %s\n" -#~ msgstr "%s : n'a pas pu obtenir la position courant dans le fichier %s : %s\n" - -#~ msgid "%s: could not identify system: %s" -#~ msgstr "%s : n'a pas pu identifier le système : %s" - -#~ msgid "%s: could not identify system: %s\n" -#~ msgstr "%s : n'a pas pu identifier le système : %s\n" - -#~ msgid "%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n" -#~ msgstr "" -#~ "%s : n'a pas pu identifier le système, a récupéré %d lignes et %d champs,\n" -#~ "attendait %d lignes et %d champs (ou plus)\n" - -#~ msgid "%s: could not open WAL segment %s: %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le segment WAL %s : %s\n" - -#~ msgid "%s: could not open directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#~ msgid "%s: could not open file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n" - -#~ msgid "%s: could not open log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le journal applicatif « %s » : %s\n" - -#~ msgid "%s: could not open timeline history file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le journal historique de la timeline « %s » : %s\n" - -#~ msgid "%s: could not open write-ahead log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le journal de transactions « %s » : %s\n" - -#~ msgid "%s: could not pad WAL segment %s: %s\n" -#~ msgstr "%s : n'a pas pu terminer le segment WAL %s : %s\n" - -#~ msgid "%s: could not pad transaction log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu remplir de zéros le journal de transactions « %s » : %s\n" - -#~ msgid "%s: could not parse file mode\n" -#~ msgstr "%s : n'a pas pu analyser le mode du fichier\n" - -#~ msgid "%s: could not parse file size\n" -#~ msgstr "%s : n'a pas pu analyser la taille du fichier\n" - -#~ msgid "%s: could not parse log start position from value \"%s\"\n" -#~ msgstr "%s : n'a pas pu analyser la position de départ des WAL à partir de la valeur « %s »\n" - -#~ msgid "%s: could not parse transaction log file name \"%s\"\n" -#~ msgstr "%s : n'a pas pu analyser le nom du journal de transactions « %s »\n" - -#~ msgid "%s: could not read copy data: %s\n" -#~ msgstr "%s : n'a pas pu lire les données du COPY : %s\n" - -#~ msgid "%s: could not read directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "%s: could not receive data from WAL stream: %s" -#~ msgstr "%s : n'a pas pu recevoir des données du flux de WAL : %s" - -#~ msgid "%s: could not rename file \"%s\" to \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu renommer le fichier « %s » en « %s » : %s\n" - -#~ msgid "%s: could not rename file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu renommer le fichier « %s » : %s\n" - -#~ msgid "%s: could not seek back to beginning of WAL segment %s: %s\n" -#~ msgstr "%s : n'a pas pu se déplacer au début du segment WAL %s : %s\n" - -#~ msgid "%s: could not seek to beginning of transaction log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu rechercher le début du journal de transaction « %s » : %s\n" - -#~ msgid "%s: could not send base backup command: %s" -#~ msgstr "%s : n'a pas pu envoyer la commande de sauvegarde de base : %s" - -#~ msgid "%s: could not set permissions on directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas configurer les droits sur le répertoire « %s » : %s\n" - -#~ msgid "%s: could not set permissions on file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu configurer les droits sur le fichier « %s » : %s\n" - -#~ msgid "%s: could not stat WAL segment %s: %s\n" -#~ msgstr "%s : n'a pas pu récupérer les informations sur le segment WAL %s : %s\n" - -#~ msgid "%s: could not stat file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu récupérer les informations sur le fichier « %s » : %s\n" - -#~ msgid "%s: could not stat transaction log file \"%s\": %s\n" -#~ msgstr "" -#~ "%s : n'a pas pu récupérer les informations sur le journal de transactions\n" -#~ "« %s » : %s\n" - -#~ msgid "%s: could not write to file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu écrire dans le fichier « %s » : %s\n" - -#~ msgid "%s: data directory \"%s\" not removed at user's request\n" -#~ msgstr "%s : répertoire des données « %s » non supprimé à la demande de l'utilisateur\n" - -#~ msgid "%s: directory \"%s\" exists but is not empty\n" -#~ msgstr "%s : le répertoire « %s » existe mais n'est pas vide\n" - -#~ msgid "%s: failed to remove WAL directory\n" -#~ msgstr "%s : échec de la suppression du répertoire des journaux de transactions\n" - -#~ msgid "%s: failed to remove contents of WAL directory\n" -#~ msgstr "%s : échec de la suppression du contenu du répertoire des journaux de transactions\n" - -#~ msgid "%s: failed to remove contents of data directory\n" -#~ msgstr "%s : échec de la suppression du contenu du répertoire des données\n" - -#~ msgid "%s: failed to remove data directory\n" -#~ msgstr "%s : échec de la suppression du répertoire des données\n" - -#~ msgid "%s: invalid format of xlog location: %s\n" -#~ msgstr "%s : format invalide de l'emplacement du journal de transactions : %s\n" - -#~ msgid "%s: invalid port number \"%s\"\n" -#~ msgstr "%s : numéro de port invalide : « %s »\n" - -#~ msgid "%s: invalid socket: %s" -#~ msgstr "%s : socket invalide : %s" - -#~ msgid "%s: keepalive message has incorrect size %d\n" -#~ msgstr "%s : le message keepalive a une taille %d incorrecte\n" - -#~ msgid "%s: no start point returned from server\n" -#~ msgstr "%s : aucun point de redémarrage renvoyé du serveur\n" - -#~ msgid "%s: out of memory\n" -#~ msgstr "%s : mémoire épuisée\n" - -#~ msgid "%s: removing WAL directory \"%s\"\n" -#~ msgstr "%s : suppression du répertoire des journaux de transactions « %s »\n" - -#~ msgid "%s: removing contents of WAL directory \"%s\"\n" -#~ msgstr "%s : suppression du contenu du répertoire des journaux de transactions « %s »\n" - -#~ msgid "%s: removing contents of data directory \"%s\"\n" -#~ msgstr "%s : suppression du contenu du répertoire des données « %s »\n" - -#~ msgid "%s: removing data directory \"%s\"\n" -#~ msgstr "%s : suppression du répertoire des données « %s »\n" - -#~ msgid "%s: select() failed: %s\n" -#~ msgstr "%s : échec de select() : %s\n" - -#~ msgid "%s: socket not open" -#~ msgstr "%s : socket non ouvert" - -#~ msgid "%s: symlinks are not supported on this platform\n" -#~ msgstr "%s : les liens symboliques ne sont pas supportés sur cette plateforme\n" - -#~ msgid "%s: timeline does not match between base backup and streaming connection\n" -#~ msgstr "" -#~ "%s : la timeline ne correspond pas entre la sauvegarde des fichiers et la\n" -#~ "connexion de réplication\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "--create-slot and --no-slot are incompatible options" -#~ msgstr "--create-slot et --no-slot sont des options incompatibles" - -#~ msgid "--no-manifest and --manifest-checksums are incompatible options" -#~ msgstr "--no-manifest et --manifest-checksums sont des options incompatibles" - -#~ msgid "--no-manifest and --manifest-force-encode are incompatible options" -#~ msgstr "--no-manifest et --manifest-force-encode sont des options incompatibles" - -#~ msgid "--progress and --no-estimate-size are incompatible options" -#~ msgstr "--progress et --no-estimate-size sont des options incompatibles" - -#, c-format -#~ msgid "This build does not support compression with %s." -#~ msgstr "Cette construction ne supporte pas la compression avec %s." - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "cannot use --compress with --compression-method=%s" -#~ msgstr "ne peut pas utiliser --compress avec --compression-method=%s" - -#, c-format -#~ msgid "could not check file \"%s\"" -#~ msgstr "n'a pas pu vérifier le fichier « %s »" - -#~ msgid "could not connect to server: %s" -#~ msgstr "n'a pas pu se connecter au serveur : %s" - -#, c-format -#~ msgid "could not determine seek position in file \"%s\": %s" -#~ msgstr "n'a pas pu déterminer la position de recherche dans le fichier d'archive « %s » : %s" - -#, c-format -#~ msgid "could not find replication slot \"%s\"" -#~ msgstr "n'a pas pu trouver le slot de réplication « %s »" - -#, c-format -#~ msgid "could not get write-ahead log end position from server: %s" -#~ msgstr "n'a pas pu obtenir la position finale des journaux de transactions à partir du serveur : %s" - -#~ msgid "deflate failed" -#~ msgstr "échec en décompression" - -#~ msgid "deflateEnd failed" -#~ msgstr "échec de deflateEnd" - -#~ msgid "deflateInit2 failed" -#~ msgstr "échec de deflateInit2" - -#~ msgid "deflateParams failed" -#~ msgstr "échec de deflateParams" - -#~ msgid "deflateReset failed" -#~ msgstr "échec de deflateReset" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#, c-format -#~ msgid "invalid compression level \"%s\"" -#~ msgstr "niveau de compression « %s » invalide" - -#, c-format -#~ msgid "invalid fsync interval \"%s\"" -#~ msgstr "intervalle fsync « %s » invalide" - -#, c-format -#~ msgid "invalid port number \"%s\"" -#~ msgstr "numéro de port invalide : « %s »" - -#, c-format -#~ msgid "invalid status interval \"%s\"" -#~ msgstr "intervalle « %s » invalide du statut" - -#, c-format -#~ msgid "invalid tar block header size: %zu" -#~ msgstr "taille invalide de l'en-tête de bloc du fichier tar : %zu" - -#, c-format -#~ msgid "log streamer with pid %d exiting" -#~ msgstr "le processus d'envoi des journaux de PID %d quitte" - -#, c-format -#~ msgid "no value specified for --compress, switching to default" -#~ msgstr "aucune valeur indiquée pour --compression, utilise la valeur par défaut" - -#~ msgid "select() failed: %m" -#~ msgstr "échec de select() : %m" - -#, c-format -#~ msgid "symlinks are not supported on this platform" -#~ msgstr "les liens symboliques ne sont pas supportés sur cette plateforme" - -#, c-format -#~ msgid "this build does not support gzip compression" -#~ msgstr "cette construction ne supporte pas la compression gzip" - -#, c-format -#~ msgid "this build does not support lz4 compression" -#~ msgstr "cette construction ne supporte pas la compression lz4" - -#, c-format -#~ msgid "this build does not support zstd compression" -#~ msgstr "cette construction ne supporte pas la compression zstd" - -#, c-format -#~ msgid "unknown compression option \"%s\"" -#~ msgstr "option de compression « %s » inconnue" - -#, c-format -#~ msgid "unrecognized link indicator \"%c\"" -#~ msgstr "indicateur de lien « %c » non reconnu" diff --git a/src/bin/pg_basebackup/po/ja.po b/src/bin/pg_basebackup/po/ja.po index e1926adeaab62..d85ecc42ae0b2 100644 --- a/src/bin/pg_basebackup/po/ja.po +++ b/src/bin/pg_basebackup/po/ja.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_basebackup (PostgreSQL 17)\n" +"Project-Id-Version: pg_basebackup (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 09:57+0900\n" -"PO-Revision-Date: 2024-06-21 10:16+0900\n" +"POT-Creation-Date: 2025-04-07 09:45+0900\n" +"PO-Revision-Date: 2025-04-07 15:32+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -22,30 +22,31 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " #: ../../common/compression.c:132 ../../common/compression.c:141 -#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 -#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 -#: bbstreamer_zstd.c:284 +#: ../../common/compression.c:150 ../../fe_utils/astreamer_gzip.c:140 +#: ../../fe_utils/astreamer_gzip.c:273 ../../fe_utils/astreamer_lz4.c:102 +#: ../../fe_utils/astreamer_lz4.c:300 ../../fe_utils/astreamer_zstd.c:133 +#: ../../fe_utils/astreamer_zstd.c:288 #, c-format msgid "this build does not support compression with %s" msgstr "このビルドでは%sによる圧縮をサポートしていません" @@ -99,7 +100,7 @@ msgstr "圧縮アルゴリズム\"%s\"は長距離モードをサポートしま msgid "could not open file \"%s\" for reading: %m" msgstr "ファイル\"%s\"を読み込み用にオープンできませんでした: %m" -#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1874 #: pg_receivewal.c:402 #, c-format msgid "could not read file \"%s\": %m" @@ -111,7 +112,7 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#: ../../fe_utils/astreamer_file.c:141 pg_recvlogical.c:652 #, c-format msgid "could not close file \"%s\": %m" msgstr "ファイル\"%s\"をクローズできませんでした: %m" @@ -133,10 +134,10 @@ msgstr "" "されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" "PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: pg_basebackup.c:1846 pg_receivewal.c:386 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: pg_basebackup.c:1847 pg_receivewal.c:386 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" @@ -146,8 +147,8 @@ msgstr "ファイル\"%s\"をオープンできませんでした: %m" msgid "could not write file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 pg_recvlogical.c:205 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" @@ -163,36 +164,36 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null ポインタを複製できません (内部エラー)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: pg_receivewal.c:319 pg_recvlogical.c:352 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: pg_receivewal.c:319 pg_recvlogical.c:353 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 +#: ../../common/file_utils.c:520 pg_basebackup.c:2345 walmethods.c:462 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -227,191 +228,200 @@ msgstr "制限付きトークンで再実行できませんでした: %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "サブプロセスの終了コードを取得できませんでした: エラーコード %lu" -#: ../../fe_utils/option_utils.c:69 -#, c-format -msgid "invalid value \"%s\" for option %s" -msgstr "オプション\"%2$s\"に対する不正な値\"%1$s\"" - -#: ../../fe_utils/option_utils.c:76 -#, c-format -msgid "%s must be in range %d..%d" -msgstr "%sは%d..%dの範囲でなければなりません" - -#: ../../fe_utils/option_utils.c:106 -#, c-format -msgid "unrecognized sync method: %s" -msgstr "認識できない同期方式: %s" - -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 -#, c-format -msgid "out of memory" -msgstr "メモリ不足です" - -#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 -#, c-format -msgid "could not write to file \"%s\": %m" -msgstr "ファイル\"%s\"を書き込めませんでした: %m" - -#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 -#: pg_basebackup.c:1497 pg_basebackup.c:1706 +#: ../../fe_utils/astreamer_file.c:96 ../../fe_utils/astreamer_file.c:364 +#: ../../fe_utils/recovery_gen.c:153 pg_basebackup.c:1498 pg_basebackup.c:1707 #, c-format msgid "could not create file \"%s\": %m" msgstr "ファイル\"%s\"を作成できませんでした: %m" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/astreamer_file.c:124 ../../fe_utils/astreamer_file.c:261 +#: ../../fe_utils/recovery_gen.c:144 pg_basebackup.c:1434 pg_basebackup.c:1728 #, c-format -msgid "shell command argument contains a newline or carriage return: \"%s\"\n" -msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" - -#: ../../fe_utils/string_utils.c:607 -#, c-format -msgid "database name contains a newline or carriage return: \"%s\"\n" -msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" +msgid "could not write to file \"%s\": %m" +msgstr "ファイル\"%s\"を書き込めませんでした: %m" -#: bbstreamer_file.c:275 +#: ../../fe_utils/astreamer_file.c:278 #, c-format msgid "unexpected state while extracting archive" msgstr "アーカイブの抽出中に想定外の状態" -#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 -#: pg_basebackup.c:757 +#: ../../fe_utils/astreamer_file.c:324 pg_basebackup.c:699 pg_basebackup.c:713 +#: pg_basebackup.c:758 #, c-format msgid "could not create directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" -#: bbstreamer_file.c:326 +#: ../../fe_utils/astreamer_file.c:329 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "ディレクトリ\"%s\"に権限を設定できませんでした: %m" -#: bbstreamer_file.c:345 +#: ../../fe_utils/astreamer_file.c:348 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "\"%s\"から\"%s\"へのシンボリックリンクを作成できませんでした: %m" -#: bbstreamer_file.c:365 +#: ../../fe_utils/astreamer_file.c:368 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "ファイル\"%s\"の権限を設定できませんでした: %m" -#: bbstreamer_gzip.c:95 +#: ../../fe_utils/astreamer_gzip.c:115 #, c-format msgid "could not create compressed file \"%s\": %m" msgstr "圧縮ファイル\"%s\"を作成できませんでした: %m" -#: bbstreamer_gzip.c:103 +#: ../../fe_utils/astreamer_gzip.c:127 #, c-format msgid "could not duplicate stdout: %m" msgstr "標準出力の複製に失敗しました: %m" -#: bbstreamer_gzip.c:107 +#: ../../fe_utils/astreamer_gzip.c:131 #, c-format msgid "could not open output file: %m" msgstr "出力ファイルをオープンできませんでした: %m" -#: bbstreamer_gzip.c:111 +#: ../../fe_utils/astreamer_gzip.c:135 #, c-format msgid "could not set compression level %d: %s" msgstr "圧縮レベルを%dに設定できませんでした: %s" -#: bbstreamer_gzip.c:143 +#: ../../fe_utils/astreamer_gzip.c:167 #, c-format msgid "could not write to compressed file \"%s\": %s" msgstr "圧縮ファイル\"%s\"に書き込めませんでした: %s" -#: bbstreamer_gzip.c:167 +#: ../../fe_utils/astreamer_gzip.c:191 #, c-format msgid "could not close compressed file \"%s\": %m" msgstr "圧縮ファイル\"%s\"をクローズすることができませんでした: %m" -#: bbstreamer_gzip.c:245 walmethods.c:880 +#: ../../fe_utils/astreamer_gzip.c:269 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "圧縮ライブラリを初期化できませんでした" -#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 +#: ../../fe_utils/astreamer_gzip.c:320 ../../fe_utils/astreamer_lz4.c:356 +#: ../../fe_utils/astreamer_zstd.c:333 #, c-format msgid "could not decompress data: %s" msgstr "データを伸張できませんでした: %s" -#: bbstreamer_inject.c:189 -#, c-format -msgid "unexpected state while injecting recovery settings" -msgstr "リカバリ設定の出力中に想定外の状態" - -#: bbstreamer_lz4.c:95 +#: ../../fe_utils/astreamer_lz4.c:97 #, c-format msgid "could not create lz4 compression context: %s" msgstr "lz4圧縮コンテクストを生成できませんでした: %s" -#: bbstreamer_lz4.c:140 +#: ../../fe_utils/astreamer_lz4.c:142 #, c-format msgid "could not write lz4 header: %s" msgstr "lz4ヘッダを出力できませんでした: %s" -#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 +#: ../../fe_utils/astreamer_lz4.c:191 ../../fe_utils/astreamer_zstd.c:185 +#: ../../fe_utils/astreamer_zstd.c:227 #, c-format msgid "could not compress data: %s" msgstr "データを圧縮できませんでした: %s" -#: bbstreamer_lz4.c:241 +#: ../../fe_utils/astreamer_lz4.c:243 #, c-format msgid "could not end lz4 compression: %s" msgstr "lz4圧縮を終了できませんでした: %s" -#: bbstreamer_lz4.c:293 +#: ../../fe_utils/astreamer_lz4.c:295 #, c-format msgid "could not initialize compression library: %s" msgstr "圧縮ライブラリを初期化できませんでした: %s" -#: bbstreamer_tar.c:244 +#: ../../fe_utils/astreamer_tar.c:244 #, c-format msgid "tar file trailer exceeds 2 blocks" msgstr "tarファイル後続ブロックが2ブロックを超えています" -#: bbstreamer_tar.c:249 +#: ../../fe_utils/astreamer_tar.c:249 #, c-format msgid "unexpected state while parsing tar archive" msgstr "tarアーカイブのパース中に想定外の状態" -#: bbstreamer_tar.c:292 +#: ../../fe_utils/astreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "tarメンバーの名前が空です" -#: bbstreamer_tar.c:326 +#: ../../fe_utils/astreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "最後のファイルが終わる前にCOPYストリームが終了しました" -#: bbstreamer_zstd.c:85 +#: ../../fe_utils/astreamer_zstd.c:89 #, c-format msgid "could not create zstd compression context" msgstr "zstd圧縮コンテクストを生成できませんでした" -#: bbstreamer_zstd.c:91 +#: ../../fe_utils/astreamer_zstd.c:95 #, c-format msgid "could not set zstd compression level to %d: %s" msgstr "zstd圧縮レベルを%dに設定できませんでした: %s" -#: bbstreamer_zstd.c:105 +#: ../../fe_utils/astreamer_zstd.c:109 #, c-format msgid "could not set compression worker count to %d: %s" msgstr "圧縮ワーカー数を%dに設定できませんでした: %s" -#: bbstreamer_zstd.c:116 +#: ../../fe_utils/astreamer_zstd.c:120 #, c-format msgid "could not enable long-distance mode: %s" msgstr "長距離モードを有効化できませんでした: %s" -#: bbstreamer_zstd.c:275 +#: ../../fe_utils/astreamer_zstd.c:279 #, c-format msgid "could not create zstd decompression context" msgstr "zstd伸張コンテクストを生成できませんでした" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "オプション\"%2$s\"に対する不正な値\"%1$s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%sは%d..%dの範囲でなければなりません" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "認識できない同期方式: %s" + +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 +#: pg_basebackup.c:1637 +#, c-format +msgid "out of memory" +msgstr "メモリ不足です" + +#: ../../fe_utils/recovery_gen.c:215 pg_basebackup.c:2249 streamutil.c:89 +#: streamutil.c:204 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" + +#: astreamer_inject.c:189 +#, c-format +msgid "unexpected state while injecting recovery settings" +msgstr "リカバリ設定の出力中に想定外の状態" + #: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" @@ -501,14 +511,14 @@ msgstr "" "%sは実行中のPostgreSQLサーバーのベースバックアップを取得します。\n" "\n" -#: pg_basebackup.c:394 pg_createsubscriber.c:216 pg_receivewal.c:79 -#: pg_recvlogical.c:86 +#: pg_basebackup.c:394 pg_createsubscriber.c:246 pg_receivewal.c:79 +#: pg_recvlogical.c:85 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_basebackup.c:395 pg_createsubscriber.c:217 pg_receivewal.c:80 -#: pg_recvlogical.c:87 +#: pg_basebackup.c:395 pg_createsubscriber.c:247 pg_receivewal.c:80 +#: pg_recvlogical.c:86 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [オプション]...\n" @@ -659,12 +669,12 @@ msgstr " -P, --progress 進行状況の表示\n" msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=スロット名 使用するレプリケーションスロット\n" -#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:109 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose 冗長メッセージの出力\n" -#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:110 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" @@ -720,12 +730,12 @@ msgstr "" " --sync-method=METHOD\n" " ファイルをディスクに同期させる方法を指定\n" -#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:111 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:112 #, c-format msgid "" "\n" @@ -739,12 +749,12 @@ msgstr "" msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CONNSTR 接続文字列\n" -#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:114 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME データベースサーバーホストまたはソケットディレクトリ\n" -#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:115 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT データベースサーバーのポート番号\n" @@ -758,23 +768,23 @@ msgstr "" " -s, --status-interval=INTERVAL\n" " サーバーへ送出するステータスパケットの間隔(秒単位)\n" -#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:116 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME 指定したデータベースユーザーで接続\n" -#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:117 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password パスワードの入力を要求しない\n" -#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:118 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password パスワード入力要求を強制(自動的に行われるはず)\n" -#: pg_basebackup.c:448 pg_createsubscriber.c:235 pg_receivewal.c:106 -#: pg_recvlogical.c:118 +#: pg_basebackup.c:448 pg_createsubscriber.c:270 pg_receivewal.c:106 +#: pg_recvlogical.c:119 #, c-format msgid "" "\n" @@ -783,8 +793,8 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_basebackup.c:449 pg_createsubscriber.c:236 pg_receivewal.c:107 -#: pg_recvlogical.c:119 +#: pg_basebackup.c:449 pg_createsubscriber.c:271 pg_receivewal.c:107 +#: pg_recvlogical.c:120 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" @@ -794,8 +804,8 @@ msgstr "%s ホームページ: <%s>\n" msgid "could not read from ready pipe: %m" msgstr "準備ができたパイプからの読み込みが失敗しました: %m" -#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 -#: streamutil.c:518 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2259 +#: streamutil.c:450 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "先行書き込みログの位置\"%s\"をパースできませんでした" @@ -810,509 +820,505 @@ msgstr "WALファイルの書き込みを終了できませんでした: %m" msgid "could not create pipe for background process: %m" msgstr "バックグランドプロセス用のパイプを作成できませんでした: \"%m" -#: pg_basebackup.c:676 +#: pg_basebackup.c:677 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "一時レプリケーションスロット\"%s\"を作成しました" -#: pg_basebackup.c:679 +#: pg_basebackup.c:680 #, c-format msgid "created replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"を作成していました" -#: pg_basebackup.c:728 +#: pg_basebackup.c:729 #, c-format msgid "could not create background process: %m" msgstr "バックグラウンドプロセスを生成できませんでした: %m" -#: pg_basebackup.c:737 +#: pg_basebackup.c:738 #, c-format msgid "could not create background thread: %m" msgstr "バックグラウンドスレッドを生成できませんでした: %m" -#: pg_basebackup.c:776 +#: pg_basebackup.c:777 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "ディレクトリ\"%s\"は存在しますが空ではありません" -#: pg_basebackup.c:782 pg_createsubscriber.c:378 +#: pg_basebackup.c:783 pg_createsubscriber.c:420 #, c-format msgid "could not access directory \"%s\": %m" msgstr "ディレクトリ\"%s\"にアクセスできませんでした: %m" -#: pg_basebackup.c:858 +#: pg_basebackup.c:859 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s kB (100%%), %d/%d テーブル空間 %*s" -#: pg_basebackup.c:870 +#: pg_basebackup.c:871 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s kB (%d%%), %d/%d テーブル空間 (%s%-*.*s)" -#: pg_basebackup.c:886 +#: pg_basebackup.c:887 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s kB (%d%%), %d/%d テーブル空間" -#: pg_basebackup.c:910 +#: pg_basebackup.c:911 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "転送速度\"%s\"は無効な値です" -#: pg_basebackup.c:912 +#: pg_basebackup.c:913 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "転送速度\"%s\"は無効です: %m" -#: pg_basebackup.c:919 +#: pg_basebackup.c:920 #, c-format msgid "transfer rate must be greater than zero" msgstr "転送速度は0より大きな値でなければなりません" -#: pg_basebackup.c:949 +#: pg_basebackup.c:950 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "--max-rate の単位が不正です: \"%s\"" -#: pg_basebackup.c:953 +#: pg_basebackup.c:954 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "転送速度\"%s\"がintegerの範囲を超えています" -#: pg_basebackup.c:960 +#: pg_basebackup.c:961 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "転送速度\"%s\"が範囲外です" -#: pg_basebackup.c:1022 +#: pg_basebackup.c:1023 #, c-format msgid "could not get COPY data stream: %s" msgstr "COPYデータストリームを取得できませんでした: %s" -#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 -#: receivelog.c:973 +#: pg_basebackup.c:1040 pg_recvlogical.c:450 pg_recvlogical.c:626 +#: receivelog.c:980 #, c-format msgid "could not read COPY data: %s" msgstr "COPYデータを読み取ることができませんでした: %s" -#: pg_basebackup.c:1043 +#: pg_basebackup.c:1044 #, c-format msgid "background process terminated unexpectedly" msgstr "バックグラウンドプロセスが突然終了しました" -#: pg_basebackup.c:1114 +#: pg_basebackup.c:1115 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "圧縮tarファイルには目録は出力できません" -#: pg_basebackup.c:1115 +#: pg_basebackup.c:1116 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "クライアントサイド圧縮を使用して標準出力ではなくディレクトリに出力する、または %s を使用してください。" -#: pg_basebackup.c:1131 +#: pg_basebackup.c:1132 #, c-format msgid "cannot parse archive \"%s\"" msgstr "アーカイブ\"%s\"のパースができませんでした" -#: pg_basebackup.c:1132 +#: pg_basebackup.c:1133 #, c-format msgid "Only tar archives can be parsed." msgstr "tarアーカイブのみパース可能です。" -#: pg_basebackup.c:1134 +#: pg_basebackup.c:1135 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Plainフォーマットではpg_basebackupがアーカイブをパースする必要があります。" -#: pg_basebackup.c:1136 +#: pg_basebackup.c:1137 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "出力ディレクトリに - を指定する際にはpg_basebackupがアーカイブをパースする必要があります。" -#: pg_basebackup.c:1138 +#: pg_basebackup.c:1139 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "-Rオプションを指定する場合はpg_basebackupがアーカイブをパースする必要があります。" -#: pg_basebackup.c:1357 +#: pg_basebackup.c:1358 #, c-format msgid "archives must precede manifest" msgstr "アーカイブは目録より先にあるはずです" -#: pg_basebackup.c:1372 +#: pg_basebackup.c:1373 #, c-format msgid "invalid archive name: \"%s\"" msgstr "不正なアーカイブ名: \"%s\"" -#: pg_basebackup.c:1444 +#: pg_basebackup.c:1445 #, c-format msgid "unexpected payload data" msgstr "予期しないペイロードのデータ" -#: pg_basebackup.c:1587 +#: pg_basebackup.c:1588 #, c-format msgid "empty COPY message" msgstr "空のCOPYメッセージ" -#: pg_basebackup.c:1589 +#: pg_basebackup.c:1590 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "タイプ%d、長さ%zuのCOPYメッセージのフォーマット異常" -#: pg_basebackup.c:1789 +#: pg_basebackup.c:1790 #, c-format msgid "incompatible server version %s" msgstr "非互換のサーバーバージョン \"%s\"" -#: pg_basebackup.c:1805 +#: pg_basebackup.c:1806 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "-X none または -X fetch でログストリーミングを無効にできます。" -#: pg_basebackup.c:1841 +#: pg_basebackup.c:1842 #, c-format msgid "server does not support incremental backup" msgstr "サーバーは差分バックアップをサポートしていません" -#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 -#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 -#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#: pg_basebackup.c:1851 pg_basebackup.c:2009 pg_recvlogical.c:273 +#: receivelog.c:542 receivelog.c:581 streamutil.c:296 streamutil.c:370 +#: streamutil.c:422 streamutil.c:510 streamutil.c:667 streamutil.c:712 #, c-format msgid "could not send replication command \"%s\": %s" msgstr "レプリケーションコマンド\"%s\"を送信できませんでした: %s" -#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#: pg_basebackup.c:1857 pg_basebackup.c:1884 #, c-format msgid "could not upload manifest: %s" msgstr "バックアップ目録をアップロードできませんでした: %s" -#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#: pg_basebackup.c:1860 pg_basebackup.c:1887 #, c-format msgid "could not upload manifest: unexpected status %s" msgstr "バックアップ目録をアップロードできませんでした: 予期しないステータス %s" -#: pg_basebackup.c:1867 +#: pg_basebackup.c:1868 #, c-format msgid "could not send COPY data: %s" msgstr "COPYデータを創出することができませんでした: %s" -#: pg_basebackup.c:1877 +#: pg_basebackup.c:1878 #, c-format msgid "could not send end-of-COPY: %s" msgstr "COPY終端マーカーを送信できませんでした: %s" -#: pg_basebackup.c:1892 +#: pg_basebackup.c:1893 #, c-format msgid "unexpected extra result while sending manifest" msgstr "バックアップ目録送出中の想定外の余分な結果" -#: pg_basebackup.c:1950 +#: pg_basebackup.c:1951 #, c-format msgid "backup targets are not supported by this server version" msgstr "バックアップターゲットはこのサーバーバージョンではサポートされません" -#: pg_basebackup.c:1953 +#: pg_basebackup.c:1954 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "バックアップターゲットが使用されている場合にはリカバリ設定は出力できません" -#: pg_basebackup.c:1980 +#: pg_basebackup.c:1981 #, c-format msgid "server does not support server-side compression" msgstr "サーバーはサーバーサイド圧縮をサポートしていません" -#: pg_basebackup.c:1990 +#: pg_basebackup.c:1991 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "ベースバックアップを開始しています - チェックポイントの完了を待機中" -#: pg_basebackup.c:1994 +#: pg_basebackup.c:1995 #, c-format msgid "waiting for checkpoint" msgstr "チェックポイントを待っています" -#: pg_basebackup.c:2016 +#: pg_basebackup.c:2017 #, c-format msgid "could not initiate base backup: %s" msgstr "ベースバックアップを開始できませんでした: %s" -#: pg_basebackup.c:2019 +#: pg_basebackup.c:2020 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "サーバーが BASE_BACKUP コマンドに期待していない応答を返しました; %d行 %d列を受信しましたが期待は %d列 %d行でした" -#: pg_basebackup.c:2025 +#: pg_basebackup.c:2026 #, c-format msgid "checkpoint completed" msgstr "チェックポイントが完了しました" -#: pg_basebackup.c:2039 +#: pg_basebackup.c:2040 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "先行書き込みログの開始ポイント: タイムライン %2$u 上の %1$s" -#: pg_basebackup.c:2047 +#: pg_basebackup.c:2048 #, c-format msgid "could not get backup header: %s" msgstr "バックアップヘッダを取得できませんでした: %s" -#: pg_basebackup.c:2050 +#: pg_basebackup.c:2051 #, c-format msgid "no data returned from server" msgstr "サーバーからデータが返されませんでした" -#: pg_basebackup.c:2093 +#: pg_basebackup.c:2094 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "標準出力に書き出せるテーブル空間は1つだけですが、データベースには%d個あります" -#: pg_basebackup.c:2106 +#: pg_basebackup.c:2107 #, c-format msgid "starting background WAL receiver" msgstr "バックグランドWAL受信処理を起動します" -#: pg_basebackup.c:2189 +#: pg_basebackup.c:2190 #, c-format msgid "backup failed: %s" msgstr "バックアップが失敗しました: %s" -#: pg_basebackup.c:2192 +#: pg_basebackup.c:2193 #, c-format msgid "no write-ahead log end position returned from server" msgstr "サーバーから先行書き込みログの終了位置が返されませんでした" -#: pg_basebackup.c:2195 +#: pg_basebackup.c:2196 #, c-format msgid "write-ahead log end point: %s" msgstr "先行書き込みログの終了ポイント: %s" -#: pg_basebackup.c:2206 +#: pg_basebackup.c:2207 #, c-format msgid "checksum error occurred" msgstr "チェックサムエラーが発生しました" -#: pg_basebackup.c:2211 +#: pg_basebackup.c:2212 #, c-format msgid "final receive failed: %s" msgstr "終端の受信に失敗しました: %s" -#: pg_basebackup.c:2235 +#: pg_basebackup.c:2236 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "バックグランドプロセスがストリーミング処理が終わるまで待機します ..." -#: pg_basebackup.c:2239 +#: pg_basebackup.c:2240 #, c-format msgid "could not send command to background pipe: %m" msgstr "バックグランドへのパイプにコマンドを送信できませんでした: %m" -#: pg_basebackup.c:2244 +#: pg_basebackup.c:2245 #, c-format msgid "could not wait for child process: %m" msgstr "子プロセスの待機ができませんでした: %m" -#: pg_basebackup.c:2246 +#: pg_basebackup.c:2247 #, c-format msgid "child %d died, expected %d" msgstr "子プロセス %d が終了しましたが、期待していたのは %d でした" -#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 -#, c-format -msgid "%s" -msgstr "%s" - -#: pg_basebackup.c:2268 +#: pg_basebackup.c:2269 #, c-format msgid "could not wait for child thread: %m" msgstr "子スレッドの待機ができませんでした: %m" -#: pg_basebackup.c:2273 +#: pg_basebackup.c:2274 #, c-format msgid "could not get child thread exit status: %m" msgstr "子スレッドの終了ステータスを取得できませんでした: %m" -#: pg_basebackup.c:2276 +#: pg_basebackup.c:2277 #, c-format msgid "child thread exited with error %u" msgstr "子スレッドがエラー%uで終了しました" -#: pg_basebackup.c:2305 +#: pg_basebackup.c:2306 #, c-format msgid "syncing data to disk ..." msgstr "データをディスクに同期しています..." -#: pg_basebackup.c:2330 +#: pg_basebackup.c:2331 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" -msgstr "backup_manifest.tmp の名前を backup_manifest に変更してください" +msgstr "backup_manifest.tmp の名前を backup_manifest に変更しています" -#: pg_basebackup.c:2350 +#: pg_basebackup.c:2351 #, c-format msgid "base backup completed" msgstr "ベースバックアップが完了しました" -#: pg_basebackup.c:2436 +#: pg_basebackup.c:2437 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "不正な checkpoint の引数\"%s\"、\"fast\" または \"spreadでなければなりません" -#: pg_basebackup.c:2454 +#: pg_basebackup.c:2455 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "不正な出力フォーマット\"%s\"、\"plain\"か\"tar\"でなければなりません" -#: pg_basebackup.c:2535 +#: pg_basebackup.c:2536 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "不正な wal-method オプション\"%s\"、\"fetch\"、\"stream\" または \"none\" のいずれかでなければなりません" -#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 -#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 -#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 -#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 -#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 -#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 -#: pg_basebackup.c:2803 pg_createsubscriber.c:1907 pg_createsubscriber.c:1917 -#: pg_createsubscriber.c:1925 pg_createsubscriber.c:1953 -#: pg_createsubscriber.c:1985 pg_receivewal.c:748 pg_receivewal.c:760 -#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 -#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 -#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 -#: pg_recvlogical.c:917 pg_recvlogical.c:924 +#: pg_basebackup.c:2575 pg_basebackup.c:2587 pg_basebackup.c:2609 +#: pg_basebackup.c:2621 pg_basebackup.c:2627 pg_basebackup.c:2679 +#: pg_basebackup.c:2690 pg_basebackup.c:2700 pg_basebackup.c:2706 +#: pg_basebackup.c:2713 pg_basebackup.c:2725 pg_basebackup.c:2737 +#: pg_basebackup.c:2745 pg_basebackup.c:2758 pg_basebackup.c:2764 +#: pg_basebackup.c:2773 pg_basebackup.c:2785 pg_basebackup.c:2796 +#: pg_basebackup.c:2804 pg_createsubscriber.c:2196 pg_createsubscriber.c:2218 +#: pg_createsubscriber.c:2228 pg_createsubscriber.c:2236 +#: pg_createsubscriber.c:2264 pg_createsubscriber.c:2307 pg_receivewal.c:748 +#: pg_receivewal.c:760 pg_receivewal.c:767 pg_receivewal.c:776 +#: pg_receivewal.c:783 pg_receivewal.c:793 pg_recvlogical.c:859 +#: pg_recvlogical.c:871 pg_recvlogical.c:881 pg_recvlogical.c:888 +#: pg_recvlogical.c:895 pg_recvlogical.c:902 pg_recvlogical.c:909 +#: pg_recvlogical.c:916 pg_recvlogical.c:923 pg_recvlogical.c:932 +#: pg_recvlogical.c:939 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_basebackup.c:2584 pg_createsubscriber.c:1915 pg_receivewal.c:758 -#: pg_recvlogical.c:863 +#: pg_basebackup.c:2585 pg_createsubscriber.c:2226 pg_receivewal.c:758 +#: pg_recvlogical.c:869 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多過ぎます(先頭は\"%s\"です)" -#: pg_basebackup.c:2607 +#: pg_basebackup.c:2608 #, c-format msgid "cannot specify both format and backup target" msgstr "フォーマットとバックアップターゲットの両方を同時には指定できません" -#: pg_basebackup.c:2619 +#: pg_basebackup.c:2620 #, c-format msgid "must specify output directory or backup target" msgstr "出力ディレクトリかバックアップターゲットを指定する必要があります" -#: pg_basebackup.c:2625 +#: pg_basebackup.c:2626 #, c-format msgid "cannot specify both output directory and backup target" msgstr "出力先ディレクトリとバックアップターゲットの両方を同時には指定できません" -#: pg_basebackup.c:2655 pg_receivewal.c:802 +#: pg_basebackup.c:2656 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "認識できない圧縮アルゴリズム\"%s\"" -#: pg_basebackup.c:2661 pg_receivewal.c:809 +#: pg_basebackup.c:2662 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "不正な圧縮指定: %s" -#: pg_basebackup.c:2677 +#: pg_basebackup.c:2678 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "バックアップターゲットが指定されているとクライアントサイド圧縮はできません" -#: pg_basebackup.c:2688 +#: pg_basebackup.c:2689 #, c-format msgid "only tar mode backups can be compressed" msgstr "tarモードでのバックアップのみが圧縮可能です" -#: pg_basebackup.c:2698 +#: pg_basebackup.c:2699 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "バックアップターゲット指定されているとWALはストリーム出力できません" -#: pg_basebackup.c:2704 +#: pg_basebackup.c:2705 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "標準出力への tar モードでは書き込み先行ログをストリーム出力できません" -#: pg_basebackup.c:2711 +#: pg_basebackup.c:2712 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "レプリケーションスロットはWALストリーミングでのみ使用可能です" -#: pg_basebackup.c:2723 +#: pg_basebackup.c:2724 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot はスロット名と同時には指定できません" #. translator: second %s is an option name -#: pg_basebackup.c:2734 pg_receivewal.c:774 +#: pg_basebackup.c:2735 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "%s は --slot でスロットを指定する必要があります" -#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 -#: pg_basebackup.c:2801 +#: pg_basebackup.c:2743 pg_basebackup.c:2783 pg_basebackup.c:2794 +#: pg_basebackup.c:2802 #, c-format msgid "%s and %s are incompatible options" msgstr "%s と %s は非互換なオプションです" -#: pg_basebackup.c:2756 +#: pg_basebackup.c:2757 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "WALディレクトリの位置はバックアップターゲットと同時には指定できません" -#: pg_basebackup.c:2762 +#: pg_basebackup.c:2763 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "WALディレクトリの位置は plainモードでのみ指定可能です" -#: pg_basebackup.c:2771 +#: pg_basebackup.c:2772 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WALディレクトリの位置は、絶対パスでなければなりません" -#: pg_basebackup.c:2871 +#: pg_basebackup.c:2872 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "シンボリックリンク\"%s\"を作成できませんでした: %m" -#: pg_createsubscriber.c:164 +#: pg_createsubscriber.c:189 #, c-format msgid "failed after the end of recovery" msgstr "リカバリ完了後に失敗しました" -#: pg_createsubscriber.c:165 +#: pg_createsubscriber.c:190 #, c-format msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." msgstr "以降この対象サーバーは物理複製としては使用できません。作業を継続する前に物理複製を再作成する必要があります。" -#: pg_createsubscriber.c:193 +#: pg_createsubscriber.c:221 #, c-format -msgid "publication \"%s\" in database \"%s\" on primary might be left behind" -msgstr "プライマリ上のデータベース\"%2$s\"にパブリケーション\"%1$s\"が残される可能性があります" +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "プライマリ上のデータベース\"%2$s\"で作成されたパブリケーション\"%1$s\"が残されています" -#: pg_createsubscriber.c:195 +#: pg_createsubscriber.c:224 #, c-format -msgid "Consider dropping this publication before trying again." -msgstr "再試行の前にこのパブリケーションを削除することを検討してください。" +msgid "Drop this publication before trying again." +msgstr "再試行の前にこのパブリケーションを削除してください。" -#: pg_createsubscriber.c:199 +#: pg_createsubscriber.c:228 #, c-format -msgid "replication slot \"%s\" in database \"%s\" on primary might be left behind" -msgstr "プライマリ上のデータベース\"%2$s\"にレプリケーションスロット\"%1$s\"が残される可能性があります" +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "プライマリ上のデータベース\"%2$s\"で作成されたレプリケーションスロット\"%1$s\"が残されています" -#: pg_createsubscriber.c:201 pg_createsubscriber.c:1137 +#: pg_createsubscriber.c:231 pg_createsubscriber.c:1305 #, c-format msgid "Drop this replication slot soon to avoid retention of WAL files." msgstr "WALファイルの増加を避けるためにこのレプリケーションスロットを直ちに削除してください。" -#: pg_createsubscriber.c:214 +#: pg_createsubscriber.c:244 #, c-format msgid "" "%s creates a new logical replica from a standby server.\n" @@ -1321,7 +1327,7 @@ msgstr "" "%s スタンバイサーバーから新たな論理複製を作成します。\n" "\n" -#: pg_createsubscriber.c:218 pg_receivewal.c:81 pg_recvlogical.c:92 +#: pg_createsubscriber.c:248 pg_receivewal.c:81 pg_recvlogical.c:91 #, c-format msgid "" "\n" @@ -1330,593 +1336,682 @@ msgstr "" "\n" "オプション:\n" -#: pg_createsubscriber.c:219 +#: pg_createsubscriber.c:249 #, c-format -msgid " -d, --database=DBNAME database to create a subscription\n" +msgid "" +" -a, --all create subscriptions for all databases except template\n" +" databases or databases that don't allow connections\n" +msgstr "" +" -a, --all テンプレートデータベースまたは接続を許可\n" +" しないデーバーベースを除くすべてのデータ\n" +" ベースでサブスクリプションを作成する\n" + +#: pg_createsubscriber.c:251 +#, c-format +msgid " -d, --database=DBNAME database in which to create a subscription\n" msgstr " -d, --database=DBNAME サブスクリプションを作成するデータベース名\n" -#: pg_createsubscriber.c:220 +#: pg_createsubscriber.c:252 #, c-format msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" msgstr " -D, --pgdata=DATADIR サブスクライバのデータディレクトリの場所\n" -#: pg_createsubscriber.c:221 +#: pg_createsubscriber.c:253 #, c-format msgid " -n, --dry-run dry run, just show what would be done\n" msgstr " -n, --dry-run 更新をせず、単に何が行なわれるかを表示\n" -#: pg_createsubscriber.c:222 +#: pg_createsubscriber.c:254 #, c-format msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" msgstr " -p, --subscriber-port=PORT サブスクライバのポート番号 (デフォルト %s)\n" -#: pg_createsubscriber.c:223 +#: pg_createsubscriber.c:255 #, c-format msgid " -P, --publisher-server=CONNSTR publisher connection string\n" msgstr " -P, --publisher-server=CONNSTR パブリッシャの接続文字列\n" -#: pg_createsubscriber.c:224 +#: pg_createsubscriber.c:256 #, c-format -msgid " -s, --socket-directory=DIR socket directory to use (default current directory)\n" +msgid "" +" -R, --remove=OBJECTTYPE remove all objects of the specified type from specified\n" +" databases on the subscriber; accepts: publications\n" msgstr "" -" -s, --socket-directory=DIR 使用するソケットディレクトリ(デフォルトは\n" +" -R, --remove=OBJECTTYPE サブスクライバ側の指定したデータベースから、\n" +" 指定された種類のオブジェクトをすべて削除する;\n" +" 指定可能なオブジェクト種別: publications\n" + +#: pg_createsubscriber.c:258 +#, c-format +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr "" +" -s, --socketdir=DIR 使用するソケットディレクトリ(デフォルトは\n" " カレントディレクトリ)\n" -#: pg_createsubscriber.c:225 +#: pg_createsubscriber.c:259 #, c-format msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" msgstr " -t, --recovery-timeout=SECS リカバリ完了を待機する秒数\n" -#: pg_createsubscriber.c:226 +#: pg_createsubscriber.c:260 #, c-format -msgid " -U, --subscriber-username=NAME subscriber username\n" -msgstr " -U, --subscriber-username=NAME サブスクライバのユーザー名\n" +msgid " -T, --enable-two-phase enable two-phase commit for all subscriptions\n" +msgstr "" +" -T, --enable-two-phase 2相コミットをすべてのサブスクリプションに\n" +" 対して有効化\n" -#: pg_createsubscriber.c:227 +#: pg_createsubscriber.c:261 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NAME サブスクライバ接続のユーザー名\n" + +#: pg_createsubscriber.c:262 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose 冗長メッセージを出力\n" -#: pg_createsubscriber.c:228 +#: pg_createsubscriber.c:263 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" " file when running target cluster\n" msgstr "" -" --config-file=FILENAME ターゲットのクラスタの実行時に指定した\n" -" 主サーバー設定ファイルを使用する\n" +" --config-file=FILENAME ターゲットクラスタの実行時に、指定した\n" +" メインのサーバー設定ファイルを使用する\n" -#: pg_createsubscriber.c:230 +#: pg_createsubscriber.c:265 #, c-format msgid " --publication=NAME publication name\n" msgstr " --publication=NAME パブリケーション名\n" -#: pg_createsubscriber.c:231 +#: pg_createsubscriber.c:266 #, c-format msgid " --replication-slot=NAME replication slot name\n" msgstr " --replication-slot=NAME レプリケーションスロット名\n" -#: pg_createsubscriber.c:232 +#: pg_createsubscriber.c:267 #, c-format msgid " --subscription=NAME subscription name\n" msgstr " --subscription=NAME サブスクリプション名\n" -#: pg_createsubscriber.c:233 +#: pg_createsubscriber.c:268 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_createsubscriber.c:234 +#: pg_createsubscriber.c:269 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_createsubscriber.c:265 +#: pg_createsubscriber.c:312 #, c-format msgid "could not parse connection string: %s" msgstr "接続文字列をパースできませんでした: %s" -#: pg_createsubscriber.c:347 +#: pg_createsubscriber.c:389 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "%2$sにはプログラム\"%1$s\"が必要ですが、\"%3$s\"と同じディレクトリにはありませんでした。" -#: pg_createsubscriber.c:350 +#: pg_createsubscriber.c:392 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした。" -#: pg_createsubscriber.c:370 +#: pg_createsubscriber.c:412 #, c-format msgid "checking if directory \"%s\" is a cluster data directory" msgstr "ディレクトリ\"%s\"がクラスタデータディレクトリであることを確認中" -#: pg_createsubscriber.c:376 +#: pg_createsubscriber.c:418 #, c-format msgid "data directory \"%s\" does not exist" msgstr "データディレクトリ\"%s\"は存在しません" -#: pg_createsubscriber.c:384 +#: pg_createsubscriber.c:426 #, c-format msgid "directory \"%s\" is not a database cluster directory" msgstr "ディレクトリ\"%s\"はデータベースクラスタディレクトリではありません" -#: pg_createsubscriber.c:501 +#: pg_createsubscriber.c:544 #, c-format msgid "connection to database failed: %s" msgstr "データベース接続に失敗しました: %s" -#: pg_createsubscriber.c:514 +#: pg_createsubscriber.c:557 streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "search_pathを消去できませんでした: %s" +msgid "could not clear \"search_path\": %s" +msgstr "\"search_path\"を消去できませんでした: %s" -#: pg_createsubscriber.c:554 +#: pg_createsubscriber.c:597 #, c-format msgid "getting system identifier from publisher" msgstr "パブリッシャからシステム識別子を取得しています" -#: pg_createsubscriber.c:561 +#: pg_createsubscriber.c:604 #, c-format msgid "could not get system identifier: %s" msgstr "システム識別子を取得できませんでした: %s" -#: pg_createsubscriber.c:567 +#: pg_createsubscriber.c:610 #, c-format msgid "could not get system identifier: got %d rows, expected %d row" msgstr "システム識別子を取得できませんでした: 受信したのは%d行、想定は%d行" -#: pg_createsubscriber.c:574 +#: pg_createsubscriber.c:617 #, c-format -msgid "system identifier is %llu on publisher" -msgstr "パブリッシャのシステム識別子は%lluです" +msgid "system identifier is % on publisher" +msgstr "パブリッシャのシステム識別子は%です" -#: pg_createsubscriber.c:595 +#: pg_createsubscriber.c:637 #, c-format msgid "getting system identifier from subscriber" msgstr "サブスクライバからシステム識別子を取得しています" -#: pg_createsubscriber.c:599 pg_createsubscriber.c:629 +#: pg_createsubscriber.c:641 pg_createsubscriber.c:670 #, c-format msgid "control file appears to be corrupt" msgstr "制御ファイルが破損しているようです" -#: pg_createsubscriber.c:603 pg_createsubscriber.c:644 +#: pg_createsubscriber.c:645 pg_createsubscriber.c:685 #, c-format -msgid "system identifier is %llu on subscriber" -msgstr "サブスクライバのシステム識別子は%lluです" +msgid "system identifier is % on subscriber" +msgstr "サブスクライバのシステム識別子は%です" -#: pg_createsubscriber.c:625 +#: pg_createsubscriber.c:666 #, c-format msgid "modifying system identifier of subscriber" msgstr "サブスクライバのシステム識別子を変更しています" -#: pg_createsubscriber.c:647 +#: pg_createsubscriber.c:688 #, c-format msgid "running pg_resetwal on the subscriber" msgstr "サブスクライバ上でpg_resetwalを実行します" -#: pg_createsubscriber.c:659 +#: pg_createsubscriber.c:700 #, c-format msgid "subscriber successfully changed the system identifier" msgstr "サブスクライバはシステム識別子の変更に成功しました" -#: pg_createsubscriber.c:661 +#: pg_createsubscriber.c:702 #, c-format -msgid "subscriber failed to change system identifier: exit code: %d" -msgstr "サブスクライバはシステム識別子の変更に失敗しました: 終了コード: %d" +msgid "could not change system identifier of subscriber: %s" +msgstr "サブスクライバーのシステム識別子を変更できませんでした: %s" -#: pg_createsubscriber.c:685 +#: pg_createsubscriber.c:726 #, c-format msgid "could not obtain database OID: %s" msgstr "データベースOIDを取得できませんでした: %s" -#: pg_createsubscriber.c:692 +#: pg_createsubscriber.c:733 #, c-format msgid "could not obtain database OID: got %d rows, expected %d row" msgstr "データベースOIDを取得できませんでした: 受信したのは%d行、想定は%d行" -#: pg_createsubscriber.c:764 +#: pg_createsubscriber.c:805 #, c-format msgid "create replication slot \"%s\" on publisher" msgstr "パブリッシャでレプリケーションスロット\"%s\"を作成します" -#: pg_createsubscriber.c:788 +#: pg_createsubscriber.c:825 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "追加のWALレコードを書き込めませんでした: %s" + +#: pg_createsubscriber.c:851 #, c-format msgid "could not obtain recovery progress: %s" msgstr "リカバリ進捗を取得できませんでした: %s" -#: pg_createsubscriber.c:819 +#: pg_createsubscriber.c:884 #, c-format msgid "checking settings on publisher" msgstr "パブリッシャ上の設定を確認しています" -#: pg_createsubscriber.c:829 +#: pg_createsubscriber.c:894 #, c-format msgid "primary server cannot be in recovery" msgstr "プライマリサーバーがリカバリ中であってはなりません" -#: pg_createsubscriber.c:864 +#: pg_createsubscriber.c:920 #, c-format msgid "could not obtain publisher settings: %s" msgstr "パブリッシャの設定が取得できませんでした: %s" -#: pg_createsubscriber.c:887 +#: pg_createsubscriber.c:949 #, c-format -msgid "publisher requires wal_level >= \"logical\"" -msgstr "パブリッシャは wal_level >= \"logical\" である必要があります" +msgid "publisher requires \"wal_level\" >= \"logical\"" +msgstr "パブリッシャでは \"wal_level\" >= \"logical\" である必要があります" -#: pg_createsubscriber.c:893 +#: pg_createsubscriber.c:955 #, c-format msgid "publisher requires %d replication slots, but only %d remain" msgstr "パブリッシャは%d個のレプリケーションスロットを必要としますが、%d個しか残っていません" -#: pg_createsubscriber.c:895 pg_createsubscriber.c:994 +#: pg_createsubscriber.c:957 pg_createsubscriber.c:966 +#: pg_createsubscriber.c:1076 pg_createsubscriber.c:1085 +#: pg_createsubscriber.c:1094 #, c-format -msgid "Consider increasing max_replication_slots to at least %d." -msgstr "max_replication_slots を最低でも%dまで増やすことを検討してください。" +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "設定パラメータ\"%s\"を少なくとも%dに増やしてください。" -#: pg_createsubscriber.c:902 +#: pg_createsubscriber.c:964 #, c-format -msgid "publisher requires %d wal sender processes, but only %d remain" -msgstr "パブリッシャは%d個のwal senderプロセスを必要としますが、%d個しか残っていません" +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "パブリッシャは%d個のWAL senderプロセスを必要としますが、%d個しか残っていません" -#: pg_createsubscriber.c:904 +#: pg_createsubscriber.c:973 #, c-format -msgid "Consider increasing max_wal_senders to at least %d." -msgstr "max_wal_sendersを最低でも%dに上げることを検討してください。" +msgid "two_phase option will not be enabled for replication slots" +msgstr "レプリケーションスロットに対してtwo_phaseオプションは有効化されません" -#: pg_createsubscriber.c:937 +#: pg_createsubscriber.c:974 +#, c-format +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "サブスクリプションはtwo_phaseオプションが無効な状態で作成されます。準備済みトランザクションはCOMMIT PREPAREDでレプリケートされます。" + +#: pg_createsubscriber.c:976 +#, c-format +msgid "You can use --enable-two-phase switch to enable two_phase." +msgstr "--enable-two-phase オプションで two_phase を有効にできます。" + +#: pg_createsubscriber.c:986 +#, c-format +msgid "required WAL could be removed from the publisher" +msgstr "必要なWALがパブリッシャから削除される可能性があります" + +#: pg_createsubscriber.c:987 +#, c-format +msgid "Set the configuration parameter \"%s\" to -1 to ensure that required WAL files are not prematurely removed." +msgstr "設定パラメータ\"%s\"を -1 に設定して、必要となるWALファイルが使用される前に削除されないようにしてください。" + +#: pg_createsubscriber.c:1019 #, c-format msgid "checking settings on subscriber" msgstr "サブスクライバ上で設定を確認します" -#: pg_createsubscriber.c:944 +#: pg_createsubscriber.c:1026 #, c-format msgid "target server must be a standby" msgstr "ターゲットサーバーはスタンバイである必要があります" -#: pg_createsubscriber.c:968 +#: pg_createsubscriber.c:1050 #, c-format msgid "could not obtain subscriber settings: %s" msgstr "サブスクライバの設定を取得できませんでした: %s" -#: pg_createsubscriber.c:992 +#: pg_createsubscriber.c:1074 #, c-format -msgid "subscriber requires %d replication slots, but only %d remain" -msgstr "サブスクライバは%d個のレプリケーションスロットを必要としますが、%d個しか残ってません" +msgid "subscriber requires %d active replication origins, but only %d remain" +msgstr "サブスクライバは%d個の有効なレプリケーション起源を必要としますが、%d個しか残ってません" -#: pg_createsubscriber.c:1001 +#: pg_createsubscriber.c:1083 #, c-format msgid "subscriber requires %d logical replication workers, but only %d remain" msgstr "サブスクライバは%d個の論理レプリケーションワーカーを必要としますが、%d個しか残っていません" -#: pg_createsubscriber.c:1003 -#, c-format -msgid "Consider increasing max_logical_replication_workers to at least %d." -msgstr "max_logical_replication_workersを最低でも%dに増やすことを検討してください。" - -#: pg_createsubscriber.c:1010 +#: pg_createsubscriber.c:1092 #, c-format msgid "subscriber requires %d worker processes, but only %d remain" msgstr "サブスクライバは%d個のワーカープロセスを必要としますが、%d個しか残っていません" -#: pg_createsubscriber.c:1012 +#: pg_createsubscriber.c:1127 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"のサブスクリプション\"%1$s\"の削除中" + +#: pg_createsubscriber.c:1136 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "サブスクリプション\"%s\"を削除できませんでした: %s" + +#: pg_createsubscriber.c:1171 #, c-format -msgid "Consider increasing max_worker_processes to at least %d." -msgstr "max_worker_processesを最低でも%dに増やすことを検討してください。" +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "既存のサブスクリプションを取得できませんでした: %s" -#: pg_createsubscriber.c:1135 +#: pg_createsubscriber.c:1303 #, c-format msgid "could not drop replication slot \"%s\" on primary" msgstr "プライマリ上のレプリケーションスロット\"%s\"を削除できませんでした" -#: pg_createsubscriber.c:1169 +#: pg_createsubscriber.c:1337 #, c-format msgid "could not obtain failover replication slot information: %s" msgstr "フェイルオーバーレプリケーションスロットの情報を取得できませんでした: %s" -#: pg_createsubscriber.c:1171 pg_createsubscriber.c:1180 +#: pg_createsubscriber.c:1339 pg_createsubscriber.c:1348 #, c-format msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." msgstr "WALファイルの増加を避けるためにこのフェイルオーバーレプリケーションスロットを直ちに削除してください。" -#: pg_createsubscriber.c:1179 +#: pg_createsubscriber.c:1347 #, c-format msgid "could not drop failover replication slot" msgstr "フェイルオーバーレプリケーションスロットを削除できませんでした" -#: pg_createsubscriber.c:1201 +#: pg_createsubscriber.c:1369 #, c-format -msgid "creating the replication slot \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でレプリケーションスロット\"%1$s:を作成します" +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"でレプリケーションスロット\"%1$s:を作成します" -#: pg_createsubscriber.c:1219 +#: pg_createsubscriber.c:1388 #, c-format -msgid "could not create replication slot \"%s\" on database \"%s\": %s" -msgstr "データベース\"%2$s\"上でレプリケーションスロット\"%1$s\"を作成できませんでした: %3$s" +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "データベース\"%2$s\"でレプリケーションスロット\"%1$s\"を作成できませんでした: %3$s" -#: pg_createsubscriber.c:1249 +#: pg_createsubscriber.c:1418 #, c-format -msgid "dropping the replication slot \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でレプリケーションスロット\"%1$s:を削除します" +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"のレプリケーションスロット\"%1$s:を削除します" -#: pg_createsubscriber.c:1265 +#: pg_createsubscriber.c:1434 #, c-format -msgid "could not drop replication slot \"%s\" on database \"%s\": %s" -msgstr "データベース\"%2$s\"上でレプリケーションスロット\"%1$s\"を削除できませんでした: %3$s" +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "データベース\"%2$s\"のレプリケーションスロット\"%1$s\"を削除できませんでした: %3$s" -#: pg_createsubscriber.c:1286 +#: pg_createsubscriber.c:1455 #, c-format msgid "pg_ctl failed with exit code %d" msgstr "pg_ctlが終了コード%dで失敗しました" -#: pg_createsubscriber.c:1291 +#: pg_createsubscriber.c:1460 #, c-format msgid "pg_ctl was terminated by exception 0x%X" msgstr "pg_ctlが例外0x%Xによって終了させられました" -#: pg_createsubscriber.c:1293 +#: pg_createsubscriber.c:1462 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "16進値の説明についてはC インクルードファイル\"ntstatus.h\"を参照してください。" -#: pg_createsubscriber.c:1295 +#: pg_createsubscriber.c:1464 #, c-format msgid "pg_ctl was terminated by signal %d: %s" msgstr "pg_ctlがシグナル%dによって終了させられました %s" -#: pg_createsubscriber.c:1301 +#: pg_createsubscriber.c:1470 #, c-format msgid "pg_ctl exited with unrecognized status %d" msgstr "pg_ctlが認識できない状態%dで終了しました" -#: pg_createsubscriber.c:1304 +#: pg_createsubscriber.c:1473 #, c-format msgid "The failed command was: %s" msgstr "失敗したコマンドは以下のとおりです: %s" -#: pg_createsubscriber.c:1343 +#: pg_createsubscriber.c:1523 #, c-format msgid "server was started" msgstr "サーバー起動完了" -#: pg_createsubscriber.c:1358 +#: pg_createsubscriber.c:1538 #, c-format msgid "server was stopped" msgstr "サーバーは停止しました" -#: pg_createsubscriber.c:1377 +#: pg_createsubscriber.c:1557 #, c-format msgid "waiting for the target server to reach the consistent state" msgstr "対象サーバーが一貫性のある状態に到達するのを待っています" -#: pg_createsubscriber.c:1400 +#: pg_createsubscriber.c:1580 #, c-format msgid "recovery timed out" msgstr "リカバリーがタイムアウトしました" -#: pg_createsubscriber.c:1413 +#: pg_createsubscriber.c:1593 #, c-format msgid "server did not end recovery" msgstr "サーバーはリカバリを完了しませんでした" -#: pg_createsubscriber.c:1415 +#: pg_createsubscriber.c:1595 #, c-format msgid "target server reached the consistent state" msgstr "対象サーバーが一貫性のある状態に到達しました" -#: pg_createsubscriber.c:1416 +#: pg_createsubscriber.c:1596 #, c-format msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." msgstr "もしpg_createsubscriberが今時点より後で失敗した場合は、作業を継続する前に物理レプリカを再作成する必要があります。" -#: pg_createsubscriber.c:1443 +#: pg_createsubscriber.c:1623 pg_createsubscriber.c:1746 #, c-format msgid "could not obtain publication information: %s" msgstr "パブリケーション情報を取得できませんでした: %s" -#: pg_createsubscriber.c:1457 +#: pg_createsubscriber.c:1637 #, c-format msgid "publication \"%s\" already exists" msgstr "パブリケーション\"%s\"はすでに存在します" -#: pg_createsubscriber.c:1458 +#: pg_createsubscriber.c:1638 #, c-format msgid "Consider renaming this publication before continuing." msgstr "作業を継続する前にこのパブリケーションの名前を変更することを検討してください。" -#: pg_createsubscriber.c:1465 +#: pg_createsubscriber.c:1645 #, c-format -msgid "creating publication \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でパブリケーション\"%1$s\"を作成します" +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"でパブリケーション\"%1$s\"を作成します" -#: pg_createsubscriber.c:1478 +#: pg_createsubscriber.c:1658 #, c-format -msgid "could not create publication \"%s\" on database \"%s\": %s" -msgstr "データベース\"%2$s\"上でパブリケーション\"%1$s\"を作成できませんでした: %3$s" +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "データベース\"%2$s\"でパブリケーション\"%1$s\"を作成できませんでした: %3$s" -#: pg_createsubscriber.c:1507 +#: pg_createsubscriber.c:1688 #, c-format -msgid "dropping publication \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でパブリケーション\"%1$s\"を削除します" +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"のパブリケーション\"%1$s\"を削除します" -#: pg_createsubscriber.c:1521 +#: pg_createsubscriber.c:1702 #, c-format -msgid "could not drop publication \"%s\" on database \"%s\": %s" -msgstr "データベース\"%2$s\"上でパブリケーション\"%1$s\"が削除できませんでした: %3$s" +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "データベース\"%2$s\"のパブリケーション\"%1$s\"が削除できませんでした: %3$s" -#: pg_createsubscriber.c:1567 +#: pg_createsubscriber.c:1739 #, c-format -msgid "creating subscription \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でサブスクリプション\"%1$s\"を作成します" +msgid "dropping all existing publications in database \"%s\"" +msgstr "データベース\"%s\"のすべてのパブリケーションを削除します" -#: pg_createsubscriber.c:1588 +#: pg_createsubscriber.c:1797 #, c-format -msgid "could not create subscription \"%s\" on database \"%s\": %s" -msgstr "データベース\"%2$s\"上でサブスクリプション\"%1$s\"を作成できませんでした: %3$s" +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"でサブスクリプション\"%1$s\"を作成します" -#: pg_createsubscriber.c:1633 +#: pg_createsubscriber.c:1819 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "データベース\"%2$s\"でサブスクリプション\"%1$s\"を作成できませんでした: %3$s" + +#: pg_createsubscriber.c:1864 #, c-format msgid "could not obtain subscription OID: %s" msgstr "サブスクリプションOIDが取得できませんでした: %s" -#: pg_createsubscriber.c:1640 +#: pg_createsubscriber.c:1871 #, c-format msgid "could not obtain subscription OID: got %d rows, expected %d row" msgstr "サブスクリプションOIDが取得できませんでした: 受信したのは%d行、想定は%d行" -#: pg_createsubscriber.c:1664 +#: pg_createsubscriber.c:1895 #, c-format -msgid "setting the replication progress (node name \"%s\" ; LSN %s) on database \"%s\"" -msgstr "データベース\"%3$s\"上でレプリケーションの進捗を設定しています(ノード名\"%1$s\", LSN %2$s)" +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "データベース\"%3$s\"でのレプリケーションの進捗を設定しています(ノード名\"%1$s\", LSN %2$s)" -#: pg_createsubscriber.c:1679 +#: pg_createsubscriber.c:1910 #, c-format -msgid "could not set replication progress for the subscription \"%s\": %s" +msgid "could not set replication progress for subscription \"%s\": %s" msgstr "サブスクリプション\"%s\"にレプリケーション進捗を設定できませんでした: %s" -#: pg_createsubscriber.c:1710 +#: pg_createsubscriber.c:1941 #, c-format -msgid "enabling subscription \"%s\" on database \"%s\"" -msgstr "データベース\"%2$s\"上でサブスクリプション\"%1$s\"を有効にします" +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "データベース\"%2$s\"のサブスクリプション\"%1$s\"を有効にします" -#: pg_createsubscriber.c:1722 +#: pg_createsubscriber.c:1953 #, c-format msgid "could not enable subscription \"%s\": %s" msgstr "サブスクリプション\"%s\"を有効化できませんでした: %s" -#: pg_createsubscriber.c:1814 +#: pg_createsubscriber.c:1999 +#, c-format +msgid "could not obtain a list of databases: %s" +msgstr "データベースの一覧を取得できませんでした: %s" + +#: pg_createsubscriber.c:2103 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\"では実行できません" -#: pg_createsubscriber.c:1815 +#: pg_createsubscriber.c:2104 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "PostgreSQLのスーパーユーザーで%sを実行しなければなりません" -#: pg_createsubscriber.c:1836 +#: pg_createsubscriber.c:2127 #, c-format -msgid "duplicate database \"%s\"" -msgstr "データベース\"%s\"が重複しています" +msgid "database \"%s\" specified more than once for -d/--database" +msgstr "-d/--database に対してデータベース\"%s\"が複数回指定されました" -#: pg_createsubscriber.c:1877 +#: pg_createsubscriber.c:2146 #, c-format -msgid "duplicate publication \"%s\"" -msgstr "パブリケーション\"%s\"が重複しています" +msgid "object type \"%s\" is specified more than once for -R/--remove" +msgstr "-R/--remove に対してオブジェクト種別%s\"が複数回指定されました" -#: pg_createsubscriber.c:1889 +#: pg_createsubscriber.c:2174 #, c-format -msgid "duplicate replication slot \"%s\"" -msgstr "レプリケーションスロット\"%s\"が重複しています" +msgid "publication \"%s\" specified more than once for --publication" +msgstr "--publication に対してパブリケーション\"%s\"が複数回指定されました" -#: pg_createsubscriber.c:1901 +#: pg_createsubscriber.c:2183 #, c-format -msgid "duplicate subscription \"%s\"" -msgstr "サブスクリプション\"%s\"が重複しています" +msgid "replication slot \"%s\" specified more than once for --replication-slot" +msgstr "--replication-slot に対してレプリケーションスロット\"%s\"が複数回指定されました" -#: pg_createsubscriber.c:1924 +#: pg_createsubscriber.c:2192 +#, c-format +msgid "subscription \"%s\" specified more than once for --subscription" +msgstr "--subscription に対してブスクリプション\"%s\"が複数回指定されました" + +#: pg_createsubscriber.c:2217 +#, c-format +msgid "%s cannot be used with -a/--all" +msgstr "%s は -a/--all と同時には使えません" + +#: pg_createsubscriber.c:2235 #, c-format msgid "no subscriber data directory specified" msgstr "サブスクライバのデータディレクトリが指定されていません" -#: pg_createsubscriber.c:1935 +#: pg_createsubscriber.c:2246 #, c-format msgid "could not determine current directory" msgstr "カレントディレクトリを特定できませんでした" -#: pg_createsubscriber.c:1952 +#: pg_createsubscriber.c:2263 #, c-format msgid "no publisher connection string specified" msgstr "パブリッシャの接続文字列が指定されていません" -#: pg_createsubscriber.c:1956 +#: pg_createsubscriber.c:2267 #, c-format -msgid "validating connection string on publisher" -msgstr "パブリッシャ上の接続文字列を検証しています" +msgid "validating publisher connection string" +msgstr "パブリッシャの接続文字列の検証中" -#: pg_createsubscriber.c:1962 +#: pg_createsubscriber.c:2273 #, c-format -msgid "validating connection string on subscriber" -msgstr "サブスクライバ上の接続文字列を検証しています" +msgid "validating subscriber connection string" +msgstr "サブスクライバの接続文字列の検証中" -#: pg_createsubscriber.c:1967 +#: pg_createsubscriber.c:2290 #, c-format msgid "no database was specified" msgstr "データベースが指定されていません" -#: pg_createsubscriber.c:1979 +#: pg_createsubscriber.c:2301 #, c-format -msgid "database \"%s\" was extracted from the publisher connection string" -msgstr "データベース\"%s\"がパブリッシャの接続文字列から抽出されました" +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "データベース名\"%s\"がパブリッシャの接続文字列から抽出されました" -#: pg_createsubscriber.c:1984 +#: pg_createsubscriber.c:2306 #, c-format msgid "no database name specified" msgstr "データベース名が指定されていません" -#: pg_createsubscriber.c:1994 +#: pg_createsubscriber.c:2316 #, c-format -msgid "wrong number of publication names" -msgstr "パブリケーション名の数が間違っています" +msgid "wrong number of publication names specified" +msgstr "指定されたパブリケーション名の数が間違っています" -#: pg_createsubscriber.c:1995 +#: pg_createsubscriber.c:2317 #, c-format -msgid "Number of publication names (%d) must match number of database names (%d)." +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." msgstr "パブリケーション名の数(%d)はデータベース名の数(%d)と一致している必要があります。" -#: pg_createsubscriber.c:2001 +#: pg_createsubscriber.c:2323 #, c-format -msgid "wrong number of subscription names" -msgstr "サブスクリプション名の数が間違っています" +msgid "wrong number of subscription names specified" +msgstr "指定されたサブスクリプション名の数が間違っています" -#: pg_createsubscriber.c:2002 +#: pg_createsubscriber.c:2324 #, c-format -msgid "Number of subscription names (%d) must match number of database names (%d)." +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." msgstr "サブスクリプション名の数(%d)はデータベース名の数(%d)と一致している必要があります。" -#: pg_createsubscriber.c:2008 +#: pg_createsubscriber.c:2330 #, c-format -msgid "wrong number of replication slot names" -msgstr "レプリケーションスロット名の数が間違っています" +msgid "wrong number of replication slot names specified" +msgstr "指定されたレプリケーションスロット名の数が間違っています" -#: pg_createsubscriber.c:2009 +#: pg_createsubscriber.c:2331 #, c-format -msgid "Number of replication slot names (%d) must match number of database names (%d)." +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." msgstr "レプリケーションスロット名の数(%d)はデータベース名の数(%d)と一致している必要があります。" -#: pg_createsubscriber.c:2038 +#: pg_createsubscriber.c:2343 +#, c-format +msgid "invalid object type \"%s\" specified for -R/--remove" +msgstr "-R/--remove に対して指定された不正なオブジェクト種別\"%s\"" + +#: pg_createsubscriber.c:2344 +#, c-format +msgid "The valid option is: \"publications\"" +msgstr "有効なオプション: \"publications\"" + +#: pg_createsubscriber.c:2375 #, c-format msgid "subscriber data directory is not a copy of the source database cluster" msgstr "サブスクライバのデータディレクトリは元データベースクラスタのコピーではありません" -#: pg_createsubscriber.c:2051 +#: pg_createsubscriber.c:2388 #, c-format -msgid "standby is up and running" -msgstr "スタンバイは起動して実行中です" +msgid "standby server is running" +msgstr "スタンバイサーバーが稼働中です" -#: pg_createsubscriber.c:2052 +#: pg_createsubscriber.c:2389 #, c-format -msgid "Stop the standby and try again." -msgstr "このスタンバイを停止して再試行してください。" +msgid "Stop the standby server and try again." +msgstr "このスタンバイサーバーを停止してから再試行してください。" -#: pg_createsubscriber.c:2061 +#: pg_createsubscriber.c:2398 #, c-format -msgid "starting the standby with command-line options" -msgstr "コマンドラインオプションを指定してスタンバイを起動しています" +msgid "starting the standby server with command-line options" +msgstr "コマンドラインオプションを指定してスタンバイサーバーを起動しています" -#: pg_createsubscriber.c:2077 pg_createsubscriber.c:2116 +#: pg_createsubscriber.c:2414 pg_createsubscriber.c:2449 #, c-format msgid "stopping the subscriber" msgstr "サブスクライバを起動しています" -#: pg_createsubscriber.c:2095 +#: pg_createsubscriber.c:2428 #, c-format msgid "starting the subscriber" msgstr "サブスクライバを起動しています" -#: pg_createsubscriber.c:2124 +#: pg_createsubscriber.c:2457 #, c-format msgid "Done!" msgstr "完了!" @@ -1935,17 +2030,17 @@ msgstr "" msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=DIR 受信した先行書き込みログの格納ディレクトリ\n" -#: pg_receivewal.c:83 pg_recvlogical.c:93 +#: pg_receivewal.c:83 pg_recvlogical.c:92 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN 指定したLSNの受信後に終了\n" -#: pg_receivewal.c:84 pg_recvlogical.c:97 +#: pg_receivewal.c:84 pg_recvlogical.c:98 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr "   --if-not-exists スロットの作成時に既に存在していてもエラーとしない\n" -#: pg_receivewal.c:85 pg_recvlogical.c:99 +#: pg_receivewal.c:85 pg_recvlogical.c:100 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop 接続断の際にループしない\n" @@ -1955,7 +2050,7 @@ msgstr " -n, --no-loop 接続断の際にループしない\n" msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync ディスクへの安全な書き込みの待機を行わない\n" -#: pg_receivewal.c:87 pg_recvlogical.c:104 +#: pg_receivewal.c:87 pg_recvlogical.c:105 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -1988,14 +2083,14 @@ msgstr "" "\n" "追加の動作:\n" -#: pg_receivewal.c:104 pg_recvlogical.c:89 +#: pg_receivewal.c:104 pg_recvlogical.c:88 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr "" " --create-slot 新しいレプリケーションスロットを作成する\n" " (スロット名については --slot を参照)\n" -#: pg_receivewal.c:105 pg_recvlogical.c:90 +#: pg_receivewal.c:105 pg_recvlogical.c:89 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr "" @@ -2017,7 +2112,7 @@ msgstr "%X/%X (タイムライン %u)でログのストリーミングを停止 msgid "switched to timeline %u at %X/%X" msgstr "%3$X/%2$Xで タイムライン%1$uに切り替えました" -#: pg_receivewal.c:224 pg_recvlogical.c:1053 +#: pg_receivewal.c:224 pg_recvlogical.c:1073 #, c-format msgid "received interrupt signal, exiting" msgstr "割り込みシグナルを受信、終了します" @@ -2087,7 +2182,7 @@ msgstr "ファイル\"%s\"の確認ができません: %sによる圧縮はこ msgid "starting log streaming at %X/%X (timeline %u)" msgstr "%X/%X (タイムライン %u)からログのストリーミングを開始" -#: pg_receivewal.c:693 pg_recvlogical.c:801 +#: pg_receivewal.c:693 pg_recvlogical.c:807 #, c-format msgid "could not parse end position \"%s\"" msgstr "終了位置\"%s\"をパースできませんでした" @@ -2117,28 +2212,28 @@ msgstr "%sによる圧縮`まだサポートされていません" msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "スロット\"%s\"を使用するレプリケーション接続で、想定に反してデータベースが指定されています" -#: pg_receivewal.c:878 pg_recvlogical.c:972 +#: pg_receivewal.c:878 pg_recvlogical.c:991 #, c-format msgid "dropping replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"を削除しています" -#: pg_receivewal.c:889 pg_recvlogical.c:982 +#: pg_receivewal.c:889 pg_recvlogical.c:1001 #, c-format msgid "creating replication slot \"%s\"" msgstr "レプリケーションスロット\"%s\"を作成しています" -#: pg_receivewal.c:918 pg_recvlogical.c:1006 +#: pg_receivewal.c:918 pg_recvlogical.c:1026 #, c-format msgid "disconnected" msgstr "切断しました" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:1010 +#: pg_receivewal.c:922 pg_recvlogical.c:1030 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "切断しました; %d秒待機して再試行します" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:83 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -2147,7 +2242,7 @@ msgstr "" "%s はPostgreSQLの論理デコードストリームを制御します。\n" "\n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:87 #, c-format msgid "" "\n" @@ -2156,19 +2251,28 @@ msgstr "" "\n" "実行する動作:\n" -#: pg_recvlogical.c:91 +#: pg_recvlogical.c:90 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr "" " --start レプリケーションスロットでストリーミングを開始する\n" " (スロット名については --slot を参照)\n" -#: pg_recvlogical.c:94 +#: pg_recvlogical.c:93 +#, c-format +msgid "" +" --failover enable replication slot synchronization to standby servers when\n" +" creating a slot\n" +msgstr "" +" --failover スロット作成時にスタンバイサーバーへのスロット同期を\n" +" 有効にする\n" + +#: pg_recvlogical.c:95 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=FILE このファイルにログを受け取る、 - で標準出力\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:96 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -2177,12 +2281,12 @@ msgstr "" " -F --fsync-interval=SECS\n" " 出力ファイルへのfsync時間間隔(デフォルト: %d)\n" -#: pg_recvlogical.c:98 +#: pg_recvlogical.c:99 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN 既存スロット内のストリーミング開始位置\n" -#: pg_recvlogical.c:100 +#: pg_recvlogical.c:101 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -2193,279 +2297,284 @@ msgstr "" " 出力プラグインにオプションNAMEをオプション値VALUEと\n" " ともに渡す\n" -#: pg_recvlogical.c:103 +#: pg_recvlogical.c:104 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN 出力プラグインPLUGINを使う(デフォルト: %s)\n" -#: pg_recvlogical.c:106 +#: pg_recvlogical.c:107 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOTNAME 論理レプリケーションスロットの名前\n" -#: pg_recvlogical.c:107 +#: pg_recvlogical.c:108 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr " -t, --two-phase スロット作成時にプリペアドトランザクションのデコードを有効にする\n" -#: pg_recvlogical.c:112 +#: pg_recvlogical.c:113 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=DBNAME 接続先データベース\n" -#: pg_recvlogical.c:145 +#: pg_recvlogical.c:146 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "PrecPpg%X/%Xまでの書き込みと、%X/%X (スロット %s)までのフラッシュを確認しています" -#: pg_recvlogical.c:169 receivelog.c:360 +#: pg_recvlogical.c:170 receivelog.c:359 #, c-format msgid "could not send feedback packet: %s" msgstr "フィードバックパケットを送信できませんでした: %s" -#: pg_recvlogical.c:239 +#: pg_recvlogical.c:240 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "%X/%X (スロット %s)からログのストリーミングを開始します" -#: pg_recvlogical.c:281 +#: pg_recvlogical.c:282 #, c-format msgid "streaming initiated" msgstr "ストリーミングを開始しました" -#: pg_recvlogical.c:346 +#: pg_recvlogical.c:347 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ロックファイル\"%s\"をオープンできませんでした: %m" -#: pg_recvlogical.c:375 receivelog.c:882 +#: pg_recvlogical.c:376 receivelog.c:889 #, c-format msgid "invalid socket: %s" msgstr "無効なソケット: %s" -#: pg_recvlogical.c:428 receivelog.c:910 +#: pg_recvlogical.c:429 receivelog.c:917 #, c-format msgid "%s() failed: %m" msgstr "%s() が失敗しました: %m" -#: pg_recvlogical.c:435 receivelog.c:959 +#: pg_recvlogical.c:436 receivelog.c:966 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "WAL ストリームからデータを受信できませんでした: %s" -#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 -#: receivelog.c:1066 +#: pg_recvlogical.c:478 pg_recvlogical.c:529 receivelog.c:1010 +#: receivelog.c:1073 #, c-format msgid "streaming header too small: %d" msgstr "ストリーミングヘッダが小さ過ぎます: %d" -#: pg_recvlogical.c:512 receivelog.c:843 +#: pg_recvlogical.c:513 receivelog.c:846 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "ストリーミングヘッダを認識できませんでした: \"%c\"" -#: pg_recvlogical.c:566 pg_recvlogical.c:578 +#: pg_recvlogical.c:567 pg_recvlogical.c:579 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "%dバイトをログファイル\"%s\"に書き込めませんでした: %m" -#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:637 receivelog.c:641 receivelog.c:678 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "レプリケーションストリームが突然終了しました: %s" -#: pg_recvlogical.c:796 +#: pg_recvlogical.c:802 #, c-format msgid "could not parse start position \"%s\"" msgstr "開始位置\"%s\"をパースできませんでした" -#: pg_recvlogical.c:874 +#: pg_recvlogical.c:880 #, c-format msgid "no slot specified" msgstr "スロットが指定されていません" -#: pg_recvlogical.c:881 +#: pg_recvlogical.c:887 #, c-format msgid "no target file specified" msgstr "ターゲットファイルが指定されていません" -#: pg_recvlogical.c:888 +#: pg_recvlogical.c:894 #, c-format msgid "no database specified" msgstr "データベースが指定されていません" -#: pg_recvlogical.c:895 +#: pg_recvlogical.c:901 #, c-format msgid "at least one action needs to be specified" msgstr "少なくとも一つのアクションを指定する必要があります" -#: pg_recvlogical.c:902 +#: pg_recvlogical.c:908 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "--create-slot や --start は --drop-slot と同時には指定できません" -#: pg_recvlogical.c:909 +#: pg_recvlogical.c:915 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "--create-slot や --drop-slot は --startpos と同時には指定できません" -#: pg_recvlogical.c:916 +#: pg_recvlogical.c:922 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos は --start が指定されているときにのみ指定可能です" -#: pg_recvlogical.c:923 +#: pg_recvlogical.c:931 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phaseは--create-slotが指定されているときにのみ指定可能です" -#: pg_recvlogical.c:956 +#: pg_recvlogical.c:938 +#, c-format +msgid "--failover may only be specified with --create-slot" +msgstr "--failover は --create-slot が指定されているときにのみ指定可能です" + +#: pg_recvlogical.c:975 #, c-format msgid "could not establish database-specific replication connection" msgstr "データベース指定のレプリケーション接続が確立できませんでした" -#: pg_recvlogical.c:1056 +#: pg_recvlogical.c:1076 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "キープアライブで終了位置 %X/%X に到達しました " -#: pg_recvlogical.c:1061 +#: pg_recvlogical.c:1081 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "%X/%X のWALレコードで終了位置 %X/%X に到達しました" -#: receivelog.c:66 +#: receivelog.c:65 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "アーカイブステータスファイル\"%s\"を作成できませんでした: %s" -#: receivelog.c:73 +#: receivelog.c:72 #, c-format msgid "could not close archive status file \"%s\": %s" msgstr "アーカイブステータスファイル\"%s\"をクローズできませんでした: %s" -#: receivelog.c:122 +#: receivelog.c:121 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "先行書き込みログファイル\"%s\"のサイズを取得できませんでした: %s" -#: receivelog.c:133 +#: receivelog.c:132 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "既存の先行書き込みログファイル\"%s\"をオープンできませんでした: %s" -#: receivelog.c:142 +#: receivelog.c:141 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "既存の先行書き込みログファイル\"%s\"をfsyncできませんでした: %s" -#: receivelog.c:157 +#: receivelog.c:156 #, c-format msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" msgstr[0] "先行書き込みログファイル\"%s\"は%zdバイトですが、0または%dであるはずです" -#: receivelog.c:175 +#: receivelog.c:174 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "先行書き込みログファイル\"%s\"をオープンできませんでした: %s" -#: receivelog.c:216 +#: receivelog.c:215 #, c-format msgid "not renaming \"%s\", segment is not complete" msgstr "\"%s\"の名前を変更しません、セグメントが完成していません" -#: receivelog.c:227 receivelog.c:317 receivelog.c:688 +#: receivelog.c:226 receivelog.c:316 receivelog.c:687 #, c-format msgid "could not close file \"%s\": %s" msgstr "ファイル\"%s\"をクローズできませんでした: %s" -#: receivelog.c:288 +#: receivelog.c:287 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "サーバーがタイムライン%uに対する想定外の履歴ファイル名を通知してきました: %s" -#: receivelog.c:297 +#: receivelog.c:296 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "タイムライン履歴ファイル\"%s\"を作成できませんでした: %s" -#: receivelog.c:304 +#: receivelog.c:303 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "タイムライン履歴ファイル\"%s\"に書き込めませんでした: %s" -#: receivelog.c:394 +#: receivelog.c:393 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions older than %s" msgstr "非互換のサーバーバージョン%s、クライアントは%sより古いサーバーバージョンからのストリーミングをサポートしていません" -#: receivelog.c:403 +#: receivelog.c:402 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions newer than %s" msgstr "非互換のサーバーバージョン%s、クライアントは%sより新しいサーバーバージョンからのストリーミングをサポートしていません" -#: receivelog.c:508 +#: receivelog.c:507 #, c-format msgid "system identifier does not match between base backup and streaming connection" msgstr "システム識別子がベースバックアップとストリーミング接続の間で一致しません" -#: receivelog.c:516 +#: receivelog.c:515 #, c-format msgid "starting timeline %u is not present in the server" msgstr "開始タイムライン%uがサーバーに存在しません" -#: receivelog.c:555 +#: receivelog.c:554 #, c-format msgid "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, expected %d rows and %d fields" msgstr "TIMELINE_HISTORYコマンドへの想定外の応答: 受信したのは%d行%d列、想定は%d行%d列" -#: receivelog.c:626 +#: receivelog.c:625 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "サーバーがタイムライン%2$uに続いて想定外のタイムライン%1$uを通知してきました" -#: receivelog.c:632 +#: receivelog.c:631 #, c-format msgid "server stopped streaming timeline %u at %X/%X, but reported next timeline %u to begin at %X/%X" msgstr "サーバーはタイムライン%uのストリーミングを%X/%Xで停止しました、しかし次のタイムライン%uが%X/%Xから開始すると通知してきています" -#: receivelog.c:672 +#: receivelog.c:671 #, c-format msgid "replication stream was terminated before stop point" msgstr "レプリケーションストリームが停止ポイントより前で終了しました" -#: receivelog.c:718 +#: receivelog.c:717 #, c-format msgid "unexpected result set after end-of-timeline: got %d rows and %d fields, expected %d rows and %d fields" msgstr "タイムライン終了後に想定外の結果セット: 受信したのは%d行%d列、想定は%d行%d列" -#: receivelog.c:727 +#: receivelog.c:726 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "次のタイムラインの開始ポイント\"%s\"をパースできませんでした" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 +#: receivelog.c:774 receivelog.c:1029 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "ファイル\"%s\"をfsyncできませんでした: %s" -#: receivelog.c:1083 +#: receivelog.c:1090 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "ファイルがオープンされていない状態で、オフセット%uに対する先行書き込みログレコードを受信しました" -#: receivelog.c:1093 +#: receivelog.c:1100 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "WALデータオフセット%08xを受信、想定は%08x" -#: receivelog.c:1128 +#: receivelog.c:1135 #, c-format msgid "could not write %d bytes to WAL file \"%s\": %s" msgstr "WALファイル\"%2$s\"に%1$dバイト書き込めませんでした: %3$s" -#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 +#: receivelog.c:1160 receivelog.c:1200 receivelog.c:1228 #, c-format msgid "could not send copy-end packet: %s" msgstr "コピー終端パケットを送信できませんでした: %s" @@ -2479,11 +2588,6 @@ msgstr "パスワード: " msgid "could not connect to server" msgstr "サーバーに接続できませんでした" -#: streamutil.c:230 -#, c-format -msgid "could not clear \"search_path\": %s" -msgstr "\"search_path\"を消去できませんでした: %s" - #: streamutil.c:246 #, c-format msgid "could not determine server setting for \"integer_datetimes\"" @@ -2494,68 +2598,68 @@ msgstr "\"integer_datetimes\"のサーバー設定を取得できませんでし msgid "\"integer_datetimes\" compile flag does not match server" msgstr "コンパイル時フラグ\"integer_datetimes\"がサーバーと異なっています" -#: streamutil.c:372 +#: streamutil.c:304 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "WALセグメントサイズを取得できませんでした: 受信したのは%d行で%d列、想定は%d行で%d列以上" -#: streamutil.c:382 +#: streamutil.c:314 #, c-format msgid "WAL segment size could not be parsed" msgstr "WALセグメントサイズがパースできませんでした" -#: streamutil.c:400 +#: streamutil.c:332 #, c-format msgid "remote server reported invalid WAL segment size (%d byte)" msgid_plural "remote server reported invalid WAL segment size (%d bytes)" msgstr[0] "リモートサーバーが不正なWALセグメントサイズを報告してきました (%dバイト)" -#: streamutil.c:404 +#: streamutil.c:336 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WALセグメントサイズは1MBから1GBまでの間の2の累乗でなければなりません。" -#: streamutil.c:446 +#: streamutil.c:378 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "グループアクセスフラグを取得できませんでした: 受信したのは%d行で%d列、想定は%d行で%d列以上" -#: streamutil.c:455 +#: streamutil.c:387 #, c-format msgid "group access flag could not be parsed: %s" msgstr "グループアクセスフラグがパースできませんでした: %s" -#: streamutil.c:498 streamutil.c:535 +#: streamutil.c:430 streamutil.c:467 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "システムを識別できませんでした: 受信したのは%d行%d列、想定は%d行%d列以上" -#: streamutil.c:587 +#: streamutil.c:519 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "レプリケーションスロット\"%s\"を読み取れませんでした: 受信したのは%d行%d列、想定は%d行%d列" -#: streamutil.c:599 +#: streamutil.c:531 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "レプリケーションスロット\"%s\"は存在しません" -#: streamutil.c:610 +#: streamutil.c:542 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "物理レプリケーションスロットが必要ですが、タイプは\"%s\"でした" -#: streamutil.c:624 +#: streamutil.c:556 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "レプリケーションスロット\"%2$s\"のrestart_lsn\"%1$s\"をパースできませんでした" -#: streamutil.c:741 +#: streamutil.c:678 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "レプリケーションスロット\"%s\"を作成できませんでした: 受信したのは%d行%d列、想定は%d行%d列" -#: streamutil.c:785 +#: streamutil.c:722 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "レプリケーションスロット\"%s\"を削除できませんでした: 受信したのは%d行%d列、想定は%d行%d列" diff --git a/src/bin/pg_basebackup/po/ka.po b/src/bin/pg_basebackup/po/ka.po index 559531710eeeb..b42019dcab678 100644 --- a/src/bin/pg_basebackup/po/ka.po +++ b/src/bin/pg_basebackup/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_basebackup (PostgreSQL) 17\n" +"Project-Id-Version: pg_basebackup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-18 04:20+0000\n" -"PO-Revision-Date: 2024-06-18 06:28+0200\n" +"POT-Creation-Date: 2025-04-05 02:20+0000\n" +"PO-Revision-Date: 2025-04-05 05:14+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,32 +16,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " #: ../../common/compression.c:132 ../../common/compression.c:141 -#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 -#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 -#: bbstreamer_zstd.c:284 +#: ../../common/compression.c:150 ../../fe_utils/astreamer_gzip.c:140 +#: ../../fe_utils/astreamer_gzip.c:273 ../../fe_utils/astreamer_lz4.c:102 +#: ../../fe_utils/astreamer_lz4.c:300 ../../fe_utils/astreamer_zstd.c:133 +#: ../../fe_utils/astreamer_zstd.c:288 #, c-format msgid "this build does not support compression with %s" msgstr "ამ აგებაში %s-ით შეკუმშვის მხარდაჭრა არ არსებობს" @@ -78,7 +79,7 @@ msgstr "შეკუმშვის ალგორითმს \"%s\" შეკ #: ../../common/compression.c:386 #, c-format msgid "compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)" -msgstr "შეკუმშვის ალგორითმის \"%s\" შეკუმშვის დონე %d-სა და %d-ს შორის უნდა იყოს (ნაგულისხმები %d)" +msgstr "შეკუმშვის ალგორითმის \"%s\" შეკუმშვის დონე %d-სა და %d-ს შორის უნდა იყოს (ნაგულისხმევი %d)" #: ../../common/compression.c:397 #, c-format @@ -95,7 +96,7 @@ msgstr "შეკუმშვის ალგორითმს \"%s\" long-dist msgid "could not open file \"%s\" for reading: %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1874 #: pg_receivewal.c:402 #, c-format msgid "could not read file \"%s\": %m" @@ -107,7 +108,7 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#: ../../fe_utils/astreamer_file.c:141 pg_recvlogical.c:652 #, c-format msgid "could not close file \"%s\": %m" msgstr "ფაილის (%s) დახურვის შეცდომა: %m" @@ -128,10 +129,10 @@ msgstr "" "ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" "მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: pg_basebackup.c:1846 pg_receivewal.c:386 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: pg_basebackup.c:1847 pg_receivewal.c:386 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" @@ -141,8 +142,8 @@ msgstr "ფაილის (%s) გახსნის შეცდომა: %m" msgid "could not write file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 pg_recvlogical.c:205 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" @@ -158,36 +159,36 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: pg_receivewal.c:319 pg_recvlogical.c:352 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: pg_receivewal.c:319 pg_recvlogical.c:353 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 +#: ../../common/file_utils.c:520 pg_basebackup.c:2345 walmethods.c:462 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -222,191 +223,200 @@ msgstr "შეზღუდულ კოდის ხელახლა შეს msgid "could not get exit code from subprocess: error code %lu" msgstr "ქვეპროცესიდან გასასვლელი კოდი ვერ მივიღე: შეცდომის კოდი %lu" -#: ../../fe_utils/option_utils.c:69 -#, c-format -msgid "invalid value \"%s\" for option %s" -msgstr "არასწორი მნიშვნელობა \"%s\" პარამეტრისთვის %s" - -#: ../../fe_utils/option_utils.c:76 -#, c-format -msgid "%s must be in range %d..%d" -msgstr "%s არაა საზღვრებში %d-დან %d-მდე" - -#: ../../fe_utils/option_utils.c:106 -#, c-format -msgid "unrecognized sync method: %s" -msgstr "უცნობი სინქრონიზაციის მეთოდი: %s" - -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 -#, c-format -msgid "out of memory" -msgstr "არასაკმარისი მეხსიერება" - -#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 -#, c-format -msgid "could not write to file \"%s\": %m" -msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" - -#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 -#: pg_basebackup.c:1497 pg_basebackup.c:1706 +#: ../../fe_utils/astreamer_file.c:96 ../../fe_utils/astreamer_file.c:364 +#: ../../fe_utils/recovery_gen.c:153 pg_basebackup.c:1498 pg_basebackup.c:1707 #, c-format msgid "could not create file \"%s\": %m" msgstr "ფაილის (%s) შექმნის შეცდომა: %m" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/astreamer_file.c:124 ../../fe_utils/astreamer_file.c:261 +#: ../../fe_utils/recovery_gen.c:144 pg_basebackup.c:1434 pg_basebackup.c:1728 #, c-format -msgid "shell command argument contains a newline or carriage return: \"%s\"\n" -msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" - -#: ../../fe_utils/string_utils.c:607 -#, c-format -msgid "database name contains a newline or carriage return: \"%s\"\n" -msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" +msgid "could not write to file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: bbstreamer_file.c:275 +#: ../../fe_utils/astreamer_file.c:278 #, c-format msgid "unexpected state while extracting archive" msgstr "არქივის გაშლის მოულოდნელი მდგომარეობა" -#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 -#: pg_basebackup.c:757 +#: ../../fe_utils/astreamer_file.c:324 pg_basebackup.c:699 pg_basebackup.c:713 +#: pg_basebackup.c:758 #, c-format msgid "could not create directory \"%s\": %m" msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" -#: bbstreamer_file.c:326 +#: ../../fe_utils/astreamer_file.c:329 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "საქაღალდეზე \"%s\" წვდომების დაყენების შეცდომა: %m" -#: bbstreamer_file.c:345 +#: ../../fe_utils/astreamer_file.c:348 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "%s-დან %s-მდე სიმბმულის შექმნა შეუძლებელია: %m" -#: bbstreamer_file.c:365 +#: ../../fe_utils/astreamer_file.c:368 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "ფაილზე \"%s\" წვდომების დაყენების შეცდომა: %m" -#: bbstreamer_gzip.c:95 +#: ../../fe_utils/astreamer_gzip.c:115 #, c-format msgid "could not create compressed file \"%s\": %m" msgstr "ვერ შექმნა შეკუმშული ფაილი \"%s\": %m" -#: bbstreamer_gzip.c:103 +#: ../../fe_utils/astreamer_gzip.c:127 #, c-format msgid "could not duplicate stdout: %m" msgstr "stdout-ის დუბლირების შეცდომა: %m" -#: bbstreamer_gzip.c:107 +#: ../../fe_utils/astreamer_gzip.c:131 #, c-format msgid "could not open output file: %m" msgstr "გამოტანის ფაილის გახსნის შეცდომა: %m" -#: bbstreamer_gzip.c:111 +#: ../../fe_utils/astreamer_gzip.c:135 #, c-format msgid "could not set compression level %d: %s" msgstr "შეკუმშვის დონის დაყენების შეცდომა %d: %s" -#: bbstreamer_gzip.c:143 +#: ../../fe_utils/astreamer_gzip.c:167 #, c-format msgid "could not write to compressed file \"%s\": %s" msgstr "შეკუმშული ფაილში (\"%s\") ჩაწერის შეცდომა: %s" -#: bbstreamer_gzip.c:167 +#: ../../fe_utils/astreamer_gzip.c:191 #, c-format msgid "could not close compressed file \"%s\": %m" msgstr "შეკუმშული ფაილის (\"%s\") დახურვის შეცდომა: %m" -#: bbstreamer_gzip.c:245 walmethods.c:880 +#: ../../fe_utils/astreamer_gzip.c:269 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზაციის შეცდომა" -#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 +#: ../../fe_utils/astreamer_gzip.c:320 ../../fe_utils/astreamer_lz4.c:356 +#: ../../fe_utils/astreamer_zstd.c:333 #, c-format msgid "could not decompress data: %s" msgstr "მონაცემების გაშლის შეცდომა: %s" -#: bbstreamer_inject.c:189 -#, c-format -msgid "unexpected state while injecting recovery settings" -msgstr "უცნობი მდგომარეობა აღდგენის ინფორმაციის ჩასმისას" - -#: bbstreamer_lz4.c:95 +#: ../../fe_utils/astreamer_lz4.c:97 #, c-format msgid "could not create lz4 compression context: %s" msgstr "lz4 შეკუმშვის კონტექსტის შექმნის შეცდომა: %s" -#: bbstreamer_lz4.c:140 +#: ../../fe_utils/astreamer_lz4.c:142 #, c-format msgid "could not write lz4 header: %s" msgstr "lz4 თავსართის ჩაწერის შეცდოა: %s" -#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 +#: ../../fe_utils/astreamer_lz4.c:191 ../../fe_utils/astreamer_zstd.c:185 +#: ../../fe_utils/astreamer_zstd.c:227 #, c-format msgid "could not compress data: %s" msgstr "მონაცემების შეკუმშვა შეუძლებელია: %s" -#: bbstreamer_lz4.c:241 +#: ../../fe_utils/astreamer_lz4.c:243 #, c-format msgid "could not end lz4 compression: %s" msgstr "lz4 შეკუმშვის დასრულების შეცდომა: %s" -#: bbstreamer_lz4.c:293 +#: ../../fe_utils/astreamer_lz4.c:295 #, c-format msgid "could not initialize compression library: %s" msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზება ვერ მოხერხდა: %s" -#: bbstreamer_tar.c:244 +#: ../../fe_utils/astreamer_tar.c:244 #, c-format msgid "tar file trailer exceeds 2 blocks" msgstr "tar ფაილის ბოლოსართი 2 ბლოკს სცდება" -#: bbstreamer_tar.c:249 +#: ../../fe_utils/astreamer_tar.c:249 #, c-format msgid "unexpected state while parsing tar archive" msgstr "მოულოდნელი მდგომარეობა tar არქივის დამუშავებისას" -#: bbstreamer_tar.c:292 +#: ../../fe_utils/astreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "tar-ის წევრს ცარიელი სახელი აქვს" -#: bbstreamer_tar.c:326 +#: ../../fe_utils/astreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "COPY-ის ნაკადი ბოლო ფაილის დასრულებამდე დასრულდა" -#: bbstreamer_zstd.c:85 +#: ../../fe_utils/astreamer_zstd.c:89 #, c-format msgid "could not create zstd compression context" msgstr "zstd შეკუმშვის კონტექსტის შექმნის შეცდომა" -#: bbstreamer_zstd.c:91 +#: ../../fe_utils/astreamer_zstd.c:95 #, c-format msgid "could not set zstd compression level to %d: %s" msgstr "zstd შეკუმშვის დონის %d-ზე დაყენების შეცდომა: %s" -#: bbstreamer_zstd.c:105 +#: ../../fe_utils/astreamer_zstd.c:109 #, c-format msgid "could not set compression worker count to %d: %s" msgstr "შეკუმშვის დამხმარე პროცესების რიცხვის %d-ზე დაყენების შეცდომა: %s" -#: bbstreamer_zstd.c:116 +#: ../../fe_utils/astreamer_zstd.c:120 #, c-format msgid "could not enable long-distance mode: %s" msgstr "long-distance რეჟიმი ვერ ჩავრთე: %s" -#: bbstreamer_zstd.c:275 +#: ../../fe_utils/astreamer_zstd.c:279 #, c-format msgid "could not create zstd decompression context" msgstr "zstd გაშლის კონტექსტის შექმნის შეცდომა" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "არასწორი მნიშვნელობა \"%s\" პარამეტრისთვის %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s არაა საზღვრებში %d-დან %d-მდე" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "უცნობი სინქრონიზაციის მეთოდი: %s" + +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 +#: pg_basebackup.c:1637 +#, c-format +msgid "out of memory" +msgstr "არასაკმარისი მეხსიერება" + +#: ../../fe_utils/recovery_gen.c:215 pg_basebackup.c:2249 streamutil.c:89 +#: streamutil.c:204 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" + +#: astreamer_inject.c:189 +#, c-format +msgid "unexpected state while injecting recovery settings" +msgstr "უცნობი მდგომარეობა აღდგენის ინფორმაციის ჩასმისას" + #: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" @@ -496,14 +506,14 @@ msgstr "" "%s გაშვებული PostgreSQL სერვერის მარქაფს იღებს.\n" "\n" -#: pg_basebackup.c:394 pg_createsubscriber.c:216 pg_receivewal.c:79 -#: pg_recvlogical.c:86 +#: pg_basebackup.c:394 pg_createsubscriber.c:246 pg_receivewal.c:79 +#: pg_recvlogical.c:85 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_basebackup.c:395 pg_createsubscriber.c:217 pg_receivewal.c:80 -#: pg_recvlogical.c:87 +#: pg_basebackup.c:395 pg_createsubscriber.c:247 pg_receivewal.c:80 +#: pg_recvlogical.c:86 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [პარამეტრი]...\n" @@ -525,7 +535,7 @@ msgstr " -D, --pgdata=საქაღლდე იღებს ბაზის #: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" -msgstr " -F, --format=p|t გამოტანის ფორმატი (plain (ნაგულისხმები), tar)\n" +msgstr " -F, --format=p|t გამოტანის ფორმატი (plain (ნაგულისხმევი), tar)\n" #: pg_basebackup.c:399 #, c-format @@ -653,12 +663,12 @@ msgstr " -P, --progress მიმდინარეობი msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=SLOTNAME გამოსაყენებელი სლოტი\n" -#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:109 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:110 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" @@ -714,12 +724,12 @@ msgstr "" " --sync-method=მეთოდი\n" " ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:111 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:112 #, c-format msgid "" "\n" @@ -733,12 +743,12 @@ msgstr "" msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CONNSTR კავშირის სტრიქონი\n" -#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:114 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME მონაცემთა ბაზის სერვერის ჰოსტის ან სოკეტის საქაღალდე\n" -#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:115 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT მონაცემთა ბაზის სერვერის პორტი\n" @@ -752,23 +762,23 @@ msgstr "" " -s, --status-interval=INTERVAL=INTERVAL\n" " სერვერზე გაგზავნილ სტატუსის პაკეტებს შორის დაყოვნება(წამებში)\n" -#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:116 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=მომხმარებელი ბაზის მომხმარებლის სახელი\n" -#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:117 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password არასოდეს მკითხო პაროლი\n" -#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:118 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password პაროლის ყოველთვის კითხვა (ავტომატურად უნდა ხდებოდეს)\n" -#: pg_basebackup.c:448 pg_createsubscriber.c:235 pg_receivewal.c:106 -#: pg_recvlogical.c:118 +#: pg_basebackup.c:448 pg_createsubscriber.c:270 pg_receivewal.c:106 +#: pg_recvlogical.c:119 #, c-format msgid "" "\n" @@ -777,8 +787,8 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_basebackup.c:449 pg_createsubscriber.c:236 pg_receivewal.c:107 -#: pg_recvlogical.c:119 +#: pg_basebackup.c:449 pg_createsubscriber.c:271 pg_receivewal.c:107 +#: pg_recvlogical.c:120 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" @@ -788,8 +798,8 @@ msgstr "%s-ის საწყისი გვერდია: <%s>\n" msgid "could not read from ready pipe: %m" msgstr "მზა ფაიფიდან წაკითხვის შეცდომა: %m" -#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 -#: streamutil.c:518 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2259 +#: streamutil.c:450 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "წინასწარ-ჩაწერადი ჟურნალის მდებარეობის დამუშავების შეცდომა: %s" @@ -804,512 +814,508 @@ msgstr "\"WAL\" ფაილების ჩაწერის დასრუ msgid "could not create pipe for background process: %m" msgstr "ფონური პროცესისთვის ფაიფის შექმნის შეცდომა: %m" -#: pg_basebackup.c:676 +#: pg_basebackup.c:677 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "შექმნილია რეპლიკაციის დროებითი სლოტი %s" -#: pg_basebackup.c:679 +#: pg_basebackup.c:680 #, c-format msgid "created replication slot \"%s\"" msgstr "შექმნილია რეპლიკაციის სლოტი %s" -#: pg_basebackup.c:728 +#: pg_basebackup.c:729 #, c-format msgid "could not create background process: %m" msgstr "ფონური პროცესის შექმნის შეცდომა: %m" -#: pg_basebackup.c:737 +#: pg_basebackup.c:738 #, c-format msgid "could not create background thread: %m" msgstr "ფონური ნაკადის შექმნის შეცდომა: %m" -#: pg_basebackup.c:776 +#: pg_basebackup.c:777 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "საქაღალდე \"%s\" არსებობს, მაგრამ ცარიელი არაა" -#: pg_basebackup.c:782 pg_createsubscriber.c:378 +#: pg_basebackup.c:783 pg_createsubscriber.c:420 #, c-format msgid "could not access directory \"%s\": %m" msgstr "საქაღალდის (%s) წვდომის შეცდომა: %m" -#: pg_basebackup.c:858 +#: pg_basebackup.c:859 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s კბ (100%%), %d/%d ცხრილების სივრცე %*s" msgstr[1] "%*s/%s კბ (100%%), %d/%d ცხრილების სივრცე %*s" -#: pg_basebackup.c:870 +#: pg_basebackup.c:871 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s კბ (%d%%), %d/%d ცხრილების სივრცე (%s%-*.*s)" msgstr[1] "%*s/%s კბ (%d%%), %d/%d ცხრილების სივრცე (%s%-*.*s)" -#: pg_basebackup.c:886 +#: pg_basebackup.c:887 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s კბ (%d%%), %d/%d ცხრილების სივრცე" msgstr[1] "%*s/%s კბ (%d%%), %d/%d ცხრილების სივრცე" -#: pg_basebackup.c:910 +#: pg_basebackup.c:911 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "გადაცემის სიჩქარის არასწორი მნიშვნელობა: %s" -#: pg_basebackup.c:912 +#: pg_basebackup.c:913 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "გადაცემის არასწორი სიჩქარე \"%s\": %m" -#: pg_basebackup.c:919 +#: pg_basebackup.c:920 #, c-format msgid "transfer rate must be greater than zero" msgstr "გადაცემის სიჩქარე ნულზე მეტი უნდა იყოს" -#: pg_basebackup.c:949 +#: pg_basebackup.c:950 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "--max-rate -ის არასწორი ერთეული: \"%s\"" -#: pg_basebackup.c:953 +#: pg_basebackup.c:954 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "გადაცემის სიჩქარე მთელი რიცხვის დიაპაზონს აღემატება: %s" -#: pg_basebackup.c:960 +#: pg_basebackup.c:961 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "გადაცემის სიჩქარის მნიშვნელობა დიაპაზონს გარეთაა: %s" -#: pg_basebackup.c:1022 +#: pg_basebackup.c:1023 #, c-format msgid "could not get COPY data stream: %s" msgstr "\"COPY\"-ის მონაცემების ნაკადის მიღების შეცდომა: %s" -#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 -#: receivelog.c:973 +#: pg_basebackup.c:1040 pg_recvlogical.c:450 pg_recvlogical.c:626 +#: receivelog.c:980 #, c-format msgid "could not read COPY data: %s" msgstr "\"COPY\"-ის მონაცემების წაკითხვის შეცდომა: %s" -#: pg_basebackup.c:1043 +#: pg_basebackup.c:1044 #, c-format msgid "background process terminated unexpectedly" msgstr "ფონური პროცესი მოულოდნელად დასრულდა" -#: pg_basebackup.c:1114 +#: pg_basebackup.c:1115 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "შეკუმშულ tar ფაილში მანიფესტის შეჩურთვა შეუძლებელია" -#: pg_basebackup.c:1115 +#: pg_basebackup.c:1116 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "გამოიყენეთ კლიენტის მხარეს შეკუმშვა და გააგზავნეთ გამონატანი საქაღალდეში stdout-ის მაგიერ, ან გამოიყენეთ %s." -#: pg_basebackup.c:1131 +#: pg_basebackup.c:1132 #, c-format msgid "cannot parse archive \"%s\"" msgstr "არქივის დამუშავების შეცდომა: %s" -#: pg_basebackup.c:1132 +#: pg_basebackup.c:1133 #, c-format msgid "Only tar archives can be parsed." msgstr "შესაძლებელია მხოლოდ tar არქივების დამუშავება." -#: pg_basebackup.c:1134 +#: pg_basebackup.c:1135 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Plain-ის ფორმატი არქივის დასამუშავებლად pg_basebackup-ს მოითხოვს." -#: pg_basebackup.c:1136 +#: pg_basebackup.c:1137 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "გამოსატან საქაღალდედ - -ის მითითება არქივის დასამუშავებლად pg_basebackup-ს მოითხოვს." -#: pg_basebackup.c:1138 +#: pg_basebackup.c:1139 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "-R პარამეტრს არქივის დასამუშავებლად pg_basebackup-ს მოითხოვს." -#: pg_basebackup.c:1357 +#: pg_basebackup.c:1358 #, c-format msgid "archives must precede manifest" msgstr "არქივები წინ უნდა უსწრებდეს მანიფესტს" -#: pg_basebackup.c:1372 +#: pg_basebackup.c:1373 #, c-format msgid "invalid archive name: \"%s\"" msgstr "არქივის არასწორი სახელი: \"%s\"" -#: pg_basebackup.c:1444 +#: pg_basebackup.c:1445 #, c-format msgid "unexpected payload data" msgstr "მოულოდნელი შიგთავსი" -#: pg_basebackup.c:1587 +#: pg_basebackup.c:1588 #, c-format msgid "empty COPY message" msgstr "შეტყობინება COPY ცარიელია" -#: pg_basebackup.c:1589 +#: pg_basebackup.c:1590 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "არასწორი COPY შეტყობინება ტიპით %d, სიგრძე %zu" -#: pg_basebackup.c:1789 +#: pg_basebackup.c:1790 #, c-format msgid "incompatible server version %s" msgstr "სერვერის შეუთავსებელი ვერსია %s" -#: pg_basebackup.c:1805 +#: pg_basebackup.c:1806 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "ჟურნალის ნაკადის გასათიშად -X none ან -X fetch გამოიყენეთ." -#: pg_basebackup.c:1841 +#: pg_basebackup.c:1842 #, c-format msgid "server does not support incremental backup" msgstr "სერვერს ინკრემენტული მარქაფის მხარდაჭერა არ გააჩნია" -#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 -#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 -#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#: pg_basebackup.c:1851 pg_basebackup.c:2009 pg_recvlogical.c:273 +#: receivelog.c:542 receivelog.c:581 streamutil.c:296 streamutil.c:370 +#: streamutil.c:422 streamutil.c:510 streamutil.c:667 streamutil.c:712 #, c-format msgid "could not send replication command \"%s\": %s" msgstr "რეპლიკაციის ბრძანების (\"%s\") გაგზავნის შეცდომა: %s" -#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#: pg_basebackup.c:1857 pg_basebackup.c:1884 #, c-format msgid "could not upload manifest: %s" msgstr "ვერ ავტვირთე მანიფესტი: %s" -#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#: pg_basebackup.c:1860 pg_basebackup.c:1887 #, c-format msgid "could not upload manifest: unexpected status %s" msgstr "ვერ ავტვირთე მანიფესტი: მოულოდნელი სტატუსი %s" -#: pg_basebackup.c:1867 +#: pg_basebackup.c:1868 #, c-format msgid "could not send COPY data: %s" msgstr "ვერ გავაგზავნე COPY-ის მონაცემები: %s" -#: pg_basebackup.c:1877 +#: pg_basebackup.c:1878 #, c-format msgid "could not send end-of-COPY: %s" msgstr "ვერ გავაგზავნე end-of-COPY: %s" -#: pg_basebackup.c:1892 +#: pg_basebackup.c:1893 #, c-format msgid "unexpected extra result while sending manifest" msgstr "მოულოდნელი დამატებითი პასუხი მანიფესტის გაგზავნისას" -#: pg_basebackup.c:1950 +#: pg_basebackup.c:1951 #, c-format msgid "backup targets are not supported by this server version" msgstr "სერვერის ამ ვერსიას მარქაფის სამიზნის მხარდაჭერა არ გააჩნია" -#: pg_basebackup.c:1953 +#: pg_basebackup.c:1954 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "აღდგენის კონფიგურაციის ჩაწერა მაშინ, როცა მარქაფის სამიზნე გამოიყენება, შეუძლებელია" -#: pg_basebackup.c:1980 +#: pg_basebackup.c:1981 #, c-format msgid "server does not support server-side compression" msgstr "სერვერს თავის მხარეს შეკუმშვის მხარდაჭერა არ გააჩნია" -#: pg_basebackup.c:1990 +#: pg_basebackup.c:1991 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "ბაზის მარქაფის პროფესი დაიწყო. ველოდები საკონტროლო წერტილის დასასრულს" -#: pg_basebackup.c:1994 +#: pg_basebackup.c:1995 #, c-format msgid "waiting for checkpoint" msgstr "საკონტროლო წერტილის მოლოდინი" -#: pg_basebackup.c:2016 +#: pg_basebackup.c:2017 #, c-format msgid "could not initiate base backup: %s" msgstr "ბაზის მარქაფის ინიციალიზაციის შეცდომა: %s" -#: pg_basebackup.c:2019 +#: pg_basebackup.c:2020 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "სერვერმა BASE_BACKUP ბრძანებაზე მოულოდნელი პასუხი დააბრუნა; მივიღე %d მწკრივი და %d ველი, მოველოდი %d მწკრივს და %d ველს" -#: pg_basebackup.c:2025 +#: pg_basebackup.c:2026 #, c-format msgid "checkpoint completed" msgstr "საკონტროლო წერტილი დასრულებულია" -#: pg_basebackup.c:2039 +#: pg_basebackup.c:2040 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "წინასწარ-ჩაწერადი ჟურნალის საწყისი წერტილი: %s დროს ხაზზე %u" -#: pg_basebackup.c:2047 +#: pg_basebackup.c:2048 #, c-format msgid "could not get backup header: %s" msgstr "მარქაფის თავსართის მიღების შეცდომა: %s" -#: pg_basebackup.c:2050 +#: pg_basebackup.c:2051 #, c-format msgid "no data returned from server" msgstr "სერვერიდან მონაცემები არ დაბრუნებულა" -#: pg_basebackup.c:2093 +#: pg_basebackup.c:2094 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "stdout-ში მხოლოდ ერთი ცხრილების სივრცის ჩაწერა შეუძლია. ბაზას კი %d აქვს" -#: pg_basebackup.c:2106 +#: pg_basebackup.c:2107 #, c-format msgid "starting background WAL receiver" msgstr "ფონური WAL მიმღების გაშვება" -#: pg_basebackup.c:2189 +#: pg_basebackup.c:2190 #, c-format msgid "backup failed: %s" msgstr "მარქაფის შეცდომა: %s" -#: pg_basebackup.c:2192 +#: pg_basebackup.c:2193 #, c-format msgid "no write-ahead log end position returned from server" msgstr "სერვერიდან წინასწარ-ჩაწერადი ჟურნალის ბოლო პოზიცია არ დაბრუნებულა" -#: pg_basebackup.c:2195 +#: pg_basebackup.c:2196 #, c-format msgid "write-ahead log end point: %s" msgstr "წინასწარ-ჩაწერადი ჟურნალის ბოლო წერტილი: %s" -#: pg_basebackup.c:2206 +#: pg_basebackup.c:2207 #, c-format msgid "checksum error occurred" msgstr "საკონტროლო ჯამის შეცდომა" -#: pg_basebackup.c:2211 +#: pg_basebackup.c:2212 #, c-format msgid "final receive failed: %s" msgstr "მიღების დასრულების შეცდომა: %s" -#: pg_basebackup.c:2235 +#: pg_basebackup.c:2236 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "ფონური პროცესის მიერ ნაკადის დასრულების მოლოდინი ..." -#: pg_basebackup.c:2239 +#: pg_basebackup.c:2240 #, c-format msgid "could not send command to background pipe: %m" msgstr "ფონური ფაიფისთვის ბრძანების გაგზავნის შეცდომა: %m" -#: pg_basebackup.c:2244 +#: pg_basebackup.c:2245 #, c-format msgid "could not wait for child process: %m" msgstr "შვულეულ პროცესს ვერ დაველოდები: %m" -#: pg_basebackup.c:2246 +#: pg_basebackup.c:2247 #, c-format msgid "child %d died, expected %d" msgstr "%d შვილი მოკვდა, მოველოდი %d" -#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 -#, c-format -msgid "%s" -msgstr "%s" - -#: pg_basebackup.c:2268 +#: pg_basebackup.c:2269 #, c-format msgid "could not wait for child thread: %m" msgstr "შვილეულ ნაკადს ვერ დაველოდები %m" -#: pg_basebackup.c:2273 +#: pg_basebackup.c:2274 #, c-format msgid "could not get child thread exit status: %m" msgstr "შვილეული ნაკადის გამოსვლის სტატუსის მიღების შეცდომა: %m" -#: pg_basebackup.c:2276 +#: pg_basebackup.c:2277 #, c-format msgid "child thread exited with error %u" msgstr "შვილეული ნაკადის შეცდომა: %u" -#: pg_basebackup.c:2305 +#: pg_basebackup.c:2306 #, c-format msgid "syncing data to disk ..." msgstr "მონაცემების სინქრონიზაცია დისკზე ..." -#: pg_basebackup.c:2330 +#: pg_basebackup.c:2331 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "backup_manifest.tmp -ის სახელის გადარქმევა backup_manifest" -#: pg_basebackup.c:2350 +#: pg_basebackup.c:2351 #, c-format msgid "base backup completed" msgstr "ბაზის მარქაფი დასრულდა" -#: pg_basebackup.c:2436 +#: pg_basebackup.c:2437 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "საკონტროლო წერტილის არასწორი არგუმენტი %s: უნდა იყოს \"fast\" an \"spread\"" -#: pg_basebackup.c:2454 +#: pg_basebackup.c:2455 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "\"%s\"-ის არასწორი გამოტანის ფორმატი. უნდა იყოს: \"plain\" ან \"tar\"" -#: pg_basebackup.c:2535 +#: pg_basebackup.c:2536 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "wal-method-ის არასწორი მნიშვნელობა: %s. უნდა იყოს \"fetch\", \"stream\" ან \"none\"" -#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 -#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 -#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 -#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 -#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 -#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 -#: pg_basebackup.c:2803 pg_createsubscriber.c:1907 pg_createsubscriber.c:1917 -#: pg_createsubscriber.c:1925 pg_createsubscriber.c:1953 -#: pg_createsubscriber.c:1985 pg_receivewal.c:748 pg_receivewal.c:760 -#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 -#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 -#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 -#: pg_recvlogical.c:917 pg_recvlogical.c:924 +#: pg_basebackup.c:2575 pg_basebackup.c:2587 pg_basebackup.c:2609 +#: pg_basebackup.c:2621 pg_basebackup.c:2627 pg_basebackup.c:2679 +#: pg_basebackup.c:2690 pg_basebackup.c:2700 pg_basebackup.c:2706 +#: pg_basebackup.c:2713 pg_basebackup.c:2725 pg_basebackup.c:2737 +#: pg_basebackup.c:2745 pg_basebackup.c:2758 pg_basebackup.c:2764 +#: pg_basebackup.c:2773 pg_basebackup.c:2785 pg_basebackup.c:2796 +#: pg_basebackup.c:2804 pg_createsubscriber.c:2196 pg_createsubscriber.c:2218 +#: pg_createsubscriber.c:2228 pg_createsubscriber.c:2236 +#: pg_createsubscriber.c:2264 pg_createsubscriber.c:2307 pg_receivewal.c:748 +#: pg_receivewal.c:760 pg_receivewal.c:767 pg_receivewal.c:776 +#: pg_receivewal.c:783 pg_receivewal.c:793 pg_recvlogical.c:859 +#: pg_recvlogical.c:871 pg_recvlogical.c:881 pg_recvlogical.c:888 +#: pg_recvlogical.c:895 pg_recvlogical.c:902 pg_recvlogical.c:909 +#: pg_recvlogical.c:916 pg_recvlogical.c:923 pg_recvlogical.c:932 +#: pg_recvlogical.c:939 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_basebackup.c:2584 pg_createsubscriber.c:1915 pg_receivewal.c:758 -#: pg_recvlogical.c:863 +#: pg_basebackup.c:2585 pg_createsubscriber.c:2226 pg_receivewal.c:758 +#: pg_recvlogical.c:869 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_basebackup.c:2607 +#: pg_basebackup.c:2608 #, c-format msgid "cannot specify both format and backup target" msgstr "ერთდროულად შეუძლებელია ორივე, ფორმატის და მარქაფის სამიზნის მითითება" -#: pg_basebackup.c:2619 +#: pg_basebackup.c:2620 #, c-format msgid "must specify output directory or backup target" msgstr "გამოტანის საქაღალდის ან მარქაფის სამიზნის მითითება აუცილებელია" -#: pg_basebackup.c:2625 +#: pg_basebackup.c:2626 #, c-format msgid "cannot specify both output directory and backup target" msgstr "ორივე, გამოტანის საქაღალდის და მარქაფის სამიზნის მითითება ერთდროულად შეუძლებელია" -#: pg_basebackup.c:2655 pg_receivewal.c:802 +#: pg_basebackup.c:2656 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "შეკუმშვის უცხო ალგორითმი: \"%s\"" -#: pg_basebackup.c:2661 pg_receivewal.c:809 +#: pg_basebackup.c:2662 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "შეკუმშვის არასწორი სპეციფიკაცია: %s" -#: pg_basebackup.c:2677 +#: pg_basebackup.c:2678 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "როცა მარქაფის სამიზნე მითითებულია, კლიენტის-მხრის შეკუმშვის მითითება შეუძლებელია" -#: pg_basebackup.c:2688 +#: pg_basebackup.c:2689 #, c-format msgid "only tar mode backups can be compressed" msgstr "შესაძლებელია მხოლოდ tar რეჟიმის მარქაფების შეკუმშვა" -#: pg_basebackup.c:2698 +#: pg_basebackup.c:2699 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "WAL-ის ნაკადი მაშინ, როცა მარქაფის სამიზნე მითითებულია, შეუძლებელია" -#: pg_basebackup.c:2704 +#: pg_basebackup.c:2705 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "წინასწარ-ჩაწერადი ჟურნალის ნაკადის tar-ის რეჟიმში stdout-ზე გამოტანა შეუძლებელია" -#: pg_basebackup.c:2711 +#: pg_basebackup.c:2712 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "რეპლიკაციის სლოტების გამოყენება მხოლოდ WAL ნაკადთან ერთადაა შესაძლებელი" -#: pg_basebackup.c:2723 +#: pg_basebackup.c:2724 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot სლოტის სახელთან ერთად არ გამოიყენება" #. translator: second %s is an option name -#: pg_basebackup.c:2734 pg_receivewal.c:774 +#: pg_basebackup.c:2735 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "%s-სთვის საჭიროა სლოტის მითითება --slot პარამეტრის საშუალებით" -#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 -#: pg_basebackup.c:2801 +#: pg_basebackup.c:2743 pg_basebackup.c:2783 pg_basebackup.c:2794 +#: pg_basebackup.c:2802 #, c-format msgid "%s and %s are incompatible options" msgstr "პარამეტრები %s და %s შეუთავსებელია" -#: pg_basebackup.c:2756 +#: pg_basebackup.c:2757 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "WAL საქაღალდის მდებარეობა მარქაფის სამიზნესთან ერთად მითითებული არ შეიძლება იყოს" -#: pg_basebackup.c:2762 +#: pg_basebackup.c:2763 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "WAL-ის საქაღალდის მდებარეობის მითითება მხოლოდ უბრალო რეჟიმშია შესაძლებელი" -#: pg_basebackup.c:2771 +#: pg_basebackup.c:2772 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL საქაღალდის მდებარეობა აბსოლუტური ბილიკი უნდა იყოს" -#: pg_basebackup.c:2871 +#: pg_basebackup.c:2872 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "სიმბმულის შექმნის შეცდომა %s: %m" -#: pg_createsubscriber.c:164 +#: pg_createsubscriber.c:189 #, c-format msgid "failed after the end of recovery" msgstr "ჩავარდა აღდგენის დასრულების შემდეგ" -#: pg_createsubscriber.c:165 +#: pg_createsubscriber.c:190 #, c-format msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." msgstr "სამიზნე სერვერს ფიზიკურ რეპლიკად ვეღარ გამოიყენებთ. გაგრძელებამდე ფიზიკური რეპლიკა თავიდან უნდა შექმნათ." -#: pg_createsubscriber.c:193 +#: pg_createsubscriber.c:221 #, c-format -msgid "publication \"%s\" in database \"%s\" on primary might be left behind" -msgstr "გამოცემა \"%s\" მონაცემთა ბაზაში \"%s\" ძირითადზე შეიძლება გამოტოვებულია" +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "გამოცემა \"%s\", შექმნილი მონაცემთა ბაზაში \"%s\" ძირითადზე, გამოტოვებულია" -#: pg_createsubscriber.c:195 +#: pg_createsubscriber.c:224 #, c-format -msgid "Consider dropping this publication before trying again." -msgstr "განიხილეთ ამ პუბლიკაციის გაუქმება ხელახლა ცდამდე." +msgid "Drop this publication before trying again." +msgstr "მოაცილეთ ეს გამოცემა, სანამ თავიდან სცდით." -#: pg_createsubscriber.c:199 +#: pg_createsubscriber.c:228 #, c-format -msgid "replication slot \"%s\" in database \"%s\" on primary might be left behind" -msgstr "რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაში \"%s\" ძირითადზე შეიძლება გამოტოვებულია" +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "რეპლიკაციის სლოტი \"%s\" შეიქმნა მონაცემთა ბაზაში \"%s\" ძირითადზე, შეიძლება, გამოტოვებულია" -#: pg_createsubscriber.c:201 pg_createsubscriber.c:1137 +#: pg_createsubscriber.c:231 pg_createsubscriber.c:1305 #, c-format msgid "Drop this replication slot soon to avoid retention of WAL files." msgstr "ამ რეპლიკაციის სლოტის მალე წაშლა WAL ფაილების მორჩენის თავიდან ასაცილებლად." -#: pg_createsubscriber.c:214 +#: pg_createsubscriber.c:244 #, c-format msgid "" "%s creates a new logical replica from a standby server.\n" @@ -1318,7 +1324,7 @@ msgstr "" "%s შექმნის ახალ ლოგიკური რეპლიკას უქმე სერვერიდან.\n" "\n" -#: pg_createsubscriber.c:218 pg_receivewal.c:81 pg_recvlogical.c:92 +#: pg_createsubscriber.c:248 pg_receivewal.c:81 pg_recvlogical.c:91 #, c-format msgid "" "\n" @@ -1327,599 +1333,676 @@ msgstr "" "\n" "პარამეტრები:\n" -#: pg_createsubscriber.c:219 +#: pg_createsubscriber.c:249 #, c-format -msgid " -d, --database=DBNAME database to create a subscription\n" +msgid "" +" -a, --all create subscriptions for all databases except template\n" +" databases or databases that don't allow connections\n" msgstr "" -" -d, --database=ბაზისსახელი გამოწერის შესაქმნელი ბაზის სახელი\n" -"\n" +" -a, --all გამოწერების შექმნა ყველა მონაცემთა ბაზისთვის გარდა შაბლონი\n" +" მონაცემთა ბაზების და მონაცემთა ბაზებისთვის, რომლებთანაც დაკავშირება აკრძალულია\n" -#: pg_createsubscriber.c:220 +#: pg_createsubscriber.c:251 #, c-format -msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" -msgstr "" -" -D, --pgdata=DATADIR გამომწერის მონაცემების საქაღალდის მდებარეობა\n" -"\n" +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --database=ბაზისსახელი მონაცემთა ბაზა, რომელშიც გნებავთ, გამოწერა შექმნათ\n" -#: pg_createsubscriber.c:221 +#: pg_createsubscriber.c:252 #, c-format -msgid " -n, --dry-run dry run, just show what would be done\n" -msgstr " -n, --dry-run განახლების გარეშე. უბრალოდ ნაჩვენები იქნება, რა მოხდებოდა\n" +msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" +msgstr " -D, --pgdata=DATADIR გამომწერის მონაცემების საქაღალდის მდებარეობა\n" -#: pg_createsubscriber.c:222 +#: pg_createsubscriber.c:253 #, c-format -msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" -msgstr " -p, --subscriber-port=პორტი გამომწერის პორტის ნომერი (ნაგულისხმევი %s)\n" +msgid " -n, --dry-run dry run, just show what would be done\n" +msgstr " -n, --dry-run განახლების გარეშე. უბრალოდ ნაჩვენები იქნება, რა მოხდებოდა\n" -#: pg_createsubscriber.c:223 +#: pg_createsubscriber.c:254 #, c-format -msgid " -P, --publisher-server=CONNSTR publisher connection string\n" -msgstr " -P, --publisher-server=CONNSTR გამომცემელთან მიერთების სტრიქონი\n" +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr " -p, --subscriber-port=პორტი გამომწერის პორტის ნომერი (ნაგულისხმევი %s)\n" -#: pg_createsubscriber.c:224 +#: pg_createsubscriber.c:255 #, c-format -msgid " -s, --socket-directory=DIR socket directory to use (default current directory)\n" -msgstr " -s, --socketdir=DIR სოკეტის საქაღალდე (ნაგულისხმევია მიმდინარე.)\n" +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CONNSTR გამომცემელთან მიერთების სტრიქონი\n" -#: pg_createsubscriber.c:225 +#: pg_createsubscriber.c:256 #, c-format -msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgid "" +" -R, --remove=OBJECTTYPE remove all objects of the specified type from specified\n" +" databases on the subscriber; accepts: publications\n" msgstr "" -" -t, --recovery-timeout=წამები რამდენი წამი დაველოდო აღდგენის დასრულებას\n" -"\n" +" -R, --remove=ობიექტისტიპი წაშლის მითითებული ტიპის ყველა ობიექტს მითითებული\n" +" მონაცემთა ბაზებიდან გამომწერზე. იღებს: გამოცემებს\n" -#: pg_createsubscriber.c:226 +#: pg_createsubscriber.c:258 #, c-format -msgid " -U, --subscriber-username=NAME subscriber username\n" -msgstr "" -" -U, --subscriber-username=სახელი გამომწერის მომხმარებლის სახელი\n" -"\n" +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=DIR სოკეტის საქაღალდე (ნაგულისხმევია მიმდინარე.)\n" + +#: pg_createsubscriber.c:259 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=წამები რამდენი წამი დაველოდო აღდგენის დასრულებას\n" + +#: pg_createsubscriber.c:260 +#, c-format +msgid " -T, --enable-two-phase enable two-phase commit for all subscriptions\n" +msgstr " -T, --enable-two-phase ორფაზიანი კომიტების ჩართვა ყველა გამოწერისთვის\n" + +#: pg_createsubscriber.c:261 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=სახელი მომხმარებლის სახელი გამომწერის კავშირისთვის\n" -#: pg_createsubscriber.c:227 +#: pg_createsubscriber.c:262 #, c-format -msgid " -v, --verbose output verbose messages\n" +msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: pg_createsubscriber.c:228 +#: pg_createsubscriber.c:263 #, c-format msgid "" -" --config-file=FILENAME use specified main server configuration\n" -" file when running target cluster\n" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" msgstr "" " --config-file=FILENAME სამიზნე კლასტერის გაშვებისას მთავარი \n" -" სერვერის მითითებული კონფიგურაციის ფაილში გამოყენება\n" +" სერვერის მითითებული კონფიგურაციის ფაილის გამოყენება\n" -#: pg_createsubscriber.c:230 +#: pg_createsubscriber.c:265 #, c-format -msgid " --publication=NAME publication name\n" +msgid " --publication=NAME publication name\n" msgstr " --publication=NAME პუბლიკაციის სახელი\n" -#: pg_createsubscriber.c:231 +#: pg_createsubscriber.c:266 #, c-format -msgid " --replication-slot=NAME replication slot name\n" -msgstr " --replication-slot=სახელი რეპლიკაციის სლოტის სახელი\n" +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=სახელი რეპლიკაციის სლოტის სახელი\n" -#: pg_createsubscriber.c:232 +#: pg_createsubscriber.c:267 #, c-format -msgid " --subscription=NAME subscription name\n" -msgstr " --subscription=NAME გამოწერის სახელი\n" +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NAME გამოწერის სახელი\n" -#: pg_createsubscriber.c:233 +#: pg_createsubscriber.c:268 #, c-format -msgid " -V, --version output version information, then exit\n" +msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_createsubscriber.c:234 +#: pg_createsubscriber.c:269 #, c-format -msgid " -?, --help show this help, then exit\n" +msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_createsubscriber.c:265 +#: pg_createsubscriber.c:312 #, c-format msgid "could not parse connection string: %s" msgstr "შეერთების სტრიქონის დამუშავების შეცდომა: %s" -#: pg_createsubscriber.c:347 +#: pg_createsubscriber.c:389 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა" -#: pg_createsubscriber.c:350 +#: pg_createsubscriber.c:392 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s" -#: pg_createsubscriber.c:370 +#: pg_createsubscriber.c:412 #, c-format msgid "checking if directory \"%s\" is a cluster data directory" msgstr "შემოწმება, არის თუ არა საქაღალდე \"%s\" კლასტერის მონაცემების საქაღალდე" -#: pg_createsubscriber.c:376 +#: pg_createsubscriber.c:418 #, c-format msgid "data directory \"%s\" does not exist" msgstr "მონაცემების საქაღალდე არ არსებობს: \"%s\"" -#: pg_createsubscriber.c:384 +#: pg_createsubscriber.c:426 #, c-format msgid "directory \"%s\" is not a database cluster directory" msgstr "საქაღალდე \"%s\" ბაზის კლასტერის საქაღალდეს არ წარმოადგენს" -#: pg_createsubscriber.c:501 +#: pg_createsubscriber.c:544 #, c-format msgid "connection to database failed: %s" msgstr "მონაცემთა ბაზასთან მიერთება ჩავარდა: %s" -#: pg_createsubscriber.c:514 +#: pg_createsubscriber.c:557 streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "search_path-ის გასუფთავების პრობლემა: %s" +msgid "could not clear \"search_path\": %s" +msgstr "\"search_path\"-ის გასუფთავების პრობლემა: %s" -#: pg_createsubscriber.c:554 +#: pg_createsubscriber.c:597 #, c-format msgid "getting system identifier from publisher" msgstr "სისტემური იდენტიფიკატორის მიღება გამომცემლისგან" -#: pg_createsubscriber.c:561 +#: pg_createsubscriber.c:604 #, c-format msgid "could not get system identifier: %s" msgstr "ვერ მივიღე სისტემის იდენტიფიკატორი: %s" -#: pg_createsubscriber.c:567 +#: pg_createsubscriber.c:610 #, c-format msgid "could not get system identifier: got %d rows, expected %d row" msgstr "სისტემური იდენტიფიკატორის მიღება შეუძლებელია: მივიღე %d მწკრივი. მოველოდი %d მწკრივს" -#: pg_createsubscriber.c:574 +#: pg_createsubscriber.c:617 #, c-format -msgid "system identifier is %llu on publisher" -msgstr "სისტემური იდენტიფიკატორი გამომცემელზე %llu-ია" +msgid "system identifier is % on publisher" +msgstr "სისტემური იდენტიფიკატორი % გამომცემელზეა" -#: pg_createsubscriber.c:595 +#: pg_createsubscriber.c:637 #, c-format msgid "getting system identifier from subscriber" msgstr "სისტემური იდენტიფიკატორის მიღება გამომწერისგან" -#: pg_createsubscriber.c:599 pg_createsubscriber.c:629 +#: pg_createsubscriber.c:641 pg_createsubscriber.c:670 #, c-format msgid "control file appears to be corrupt" msgstr "როგორც ჩანს, საკონტროლო ფაილი დაზიანებულია" -#: pg_createsubscriber.c:603 pg_createsubscriber.c:644 +#: pg_createsubscriber.c:645 pg_createsubscriber.c:685 #, c-format -msgid "system identifier is %llu on subscriber" -msgstr "სისტემური იდენტიფიკატორი %llu გამომწერზეა" +msgid "system identifier is % on subscriber" +msgstr "სისტემური იდენტიფიკატორი % გამომწერზეა" -#: pg_createsubscriber.c:625 +#: pg_createsubscriber.c:666 #, c-format msgid "modifying system identifier of subscriber" msgstr "გამომწერის სისტემური იდენტიფიკატორის შეცვლა" -#: pg_createsubscriber.c:647 +#: pg_createsubscriber.c:688 #, c-format msgid "running pg_resetwal on the subscriber" msgstr "pg_resetwal-ის გაშვება გამომწერზე" -#: pg_createsubscriber.c:659 +#: pg_createsubscriber.c:700 #, c-format msgid "subscriber successfully changed the system identifier" msgstr "გამომწერმა სისტემური იდენტიფიკატორი წარმატებით შეცვალა" -#: pg_createsubscriber.c:661 +#: pg_createsubscriber.c:702 #, c-format -msgid "subscriber failed to change system identifier: exit code: %d" -msgstr "გამომწერის სისტემური იდენტიფიკატორის შეცვლა ჩავარდა: გამოსვლის კოდი: %d" +msgid "could not change system identifier of subscriber: %s" +msgstr "ვერ შევცვალე სისტემურ იდენტიფიკატორი გამომწერისთვის: %s" -#: pg_createsubscriber.c:685 +#: pg_createsubscriber.c:726 #, c-format msgid "could not obtain database OID: %s" msgstr "ვერ მივიღე მონაცემთა ბაზის OID: %s" -#: pg_createsubscriber.c:692 +#: pg_createsubscriber.c:733 #, c-format msgid "could not obtain database OID: got %d rows, expected %d row" msgstr "ვერ მივიღე მონაცემთა ბაზის OID: მივიღე %d მწკრივი, მოველოდი %d მწკრივს" -#: pg_createsubscriber.c:764 +#: pg_createsubscriber.c:805 #, c-format msgid "create replication slot \"%s\" on publisher" msgstr "რეპლიკაციის სლოტის \"%s\" შექმნა გამომცემელზე" -#: pg_createsubscriber.c:788 +#: pg_createsubscriber.c:825 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "ვერ ჩავწერე დამატებითი WAL ჩანაწერი: %s" + +#: pg_createsubscriber.c:851 #, c-format msgid "could not obtain recovery progress: %s" msgstr "აღდგენის მიმდინარეობის მდგომარეობის მიღება შეუძლებელია: %s" -#: pg_createsubscriber.c:819 +#: pg_createsubscriber.c:884 #, c-format msgid "checking settings on publisher" msgstr "პარამეტრების შექმნა გამომცემელზე" -#: pg_createsubscriber.c:829 +#: pg_createsubscriber.c:894 #, c-format msgid "primary server cannot be in recovery" msgstr "ძირითადი სერვერი აღდგენის რეჟიმში ვერ იქნება" -#: pg_createsubscriber.c:864 +#: pg_createsubscriber.c:920 #, c-format msgid "could not obtain publisher settings: %s" msgstr "გამომცემლის პარამეტრების მიღება შეუძლებელია: %s" -#: pg_createsubscriber.c:887 +#: pg_createsubscriber.c:949 #, c-format -msgid "publisher requires wal_level >= \"logical\"" -msgstr "გამომცემელს wal_level >= \"logical\" ესაჭიროება" +msgid "publisher requires \"wal_level\" >= \"logical\"" +msgstr "გამომცემელს \"wal_level\" >= \"logical\" ესაჭიროება" -#: pg_createsubscriber.c:893 +#: pg_createsubscriber.c:955 #, c-format msgid "publisher requires %d replication slots, but only %d remain" msgstr "გამომცემელს %d რეპლიკაციის სლოტი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" -#: pg_createsubscriber.c:895 pg_createsubscriber.c:994 +#: pg_createsubscriber.c:957 pg_createsubscriber.c:966 +#: pg_createsubscriber.c:1076 pg_createsubscriber.c:1085 +#: pg_createsubscriber.c:1094 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "გაზარდეთ კონფიგურაციის პარამეტრი \"%s\" %d-მდე მაინც." + +#: pg_createsubscriber.c:964 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "გამომცემელს %d WAL-ის გამგზავნი პროცესი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" + +#: pg_createsubscriber.c:973 #, c-format -msgid "Consider increasing max_replication_slots to at least %d." -msgstr "განიხილეთ max_replication_slots-ის გაზრდა მინიმუმ %d-მდე." +msgid "two_phase option will not be enabled for replication slots" +msgstr "პარამეტრი two_phase რეპლიკაციის სლოტებისთვის არ ჩაირთვება" -#: pg_createsubscriber.c:902 +#: pg_createsubscriber.c:974 #, c-format -msgid "publisher requires %d wal sender processes, but only %d remain" -msgstr "გამომცემელს %d wal გამგზავნი პროცესი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "გამოწერები two_phase პარამეტრით გათიშული შეიქმნება. მომზადებული ტრანზაქციების რეპლიკაცია მოხდება COMMIT PREPARED-თან." -#: pg_createsubscriber.c:904 +#: pg_createsubscriber.c:976 #, c-format -msgid "Consider increasing max_wal_senders to at least %d." -msgstr "განიხილეთ max_wal_senders-ის გაზრდა მინიმუმ %d-მდე." +msgid "You can use --enable-two-phase switch to enable two_phase." +msgstr "'two_phase'-ის ჩასართავად, შეგიძლიათ, გამოიყენოთ პარამეტრი --enable-two-phase." -#: pg_createsubscriber.c:937 +#: pg_createsubscriber.c:986 +#, c-format +msgid "required WAL could be removed from the publisher" +msgstr "აუცილებელი WAL-ის წაშლა შესაძლებელია გამომცემლიდან" + +#: pg_createsubscriber.c:987 +#, c-format +msgid "Set the configuration parameter \"%s\" to -1 to ensure that required WAL files are not prematurely removed." +msgstr "დააყენეთ კონფიგურაციის პარამეტრი \"%s\" მნიშვნელობაზე -1, რომ დარწმუნდეთ, რომ WAL ფაილები საჭიროზე ადრე არ წაიშლება." + +#: pg_createsubscriber.c:1019 #, c-format msgid "checking settings on subscriber" msgstr "პარამეტრების შემოწმება გამომწერზე" -#: pg_createsubscriber.c:944 +#: pg_createsubscriber.c:1026 #, c-format msgid "target server must be a standby" msgstr "სამიზნე სერვერი უქმე უნდა იყოს" -#: pg_createsubscriber.c:968 +#: pg_createsubscriber.c:1050 #, c-format msgid "could not obtain subscriber settings: %s" msgstr "გამომწერის პარამეტრების მიღება შეუძლებელია: %s" -#: pg_createsubscriber.c:992 +#: pg_createsubscriber.c:1074 #, c-format -msgid "subscriber requires %d replication slots, but only %d remain" -msgstr "გამომწერს %d რეპლიკაციის სლოტი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" +msgid "subscriber requires %d active replication origins, but only %d remain" +msgstr "გამომწერს %d აქტიური რეპლიკაციის წყარო სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" -#: pg_createsubscriber.c:1001 +#: pg_createsubscriber.c:1083 #, c-format msgid "subscriber requires %d logical replication workers, but only %d remain" msgstr "გამომწერს %d ლოგიკური რეპლიკაციის დამხმარე პროცესი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" -#: pg_createsubscriber.c:1003 -#, c-format -msgid "Consider increasing max_logical_replication_workers to at least %d." -msgstr "განიხილეთ max_logical_replication_workers-ის გაზრდა მინიმუმ %d-მდე." - -#: pg_createsubscriber.c:1010 +#: pg_createsubscriber.c:1092 #, c-format msgid "subscriber requires %d worker processes, but only %d remain" msgstr "გამომწერს %d დამხმარე პროცესი სჭირდება, მაგრამ დარჩენილია, მხოლოდ, %d" -#: pg_createsubscriber.c:1012 +#: pg_createsubscriber.c:1127 #, c-format -msgid "Consider increasing max_worker_processes to at least %d." -msgstr "განიხილეთ max_worker_processes-ის გაზრდა მინიმუმ %d-მდე." +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "მოხდება მოცილება გამოწერისა \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1135 +#: pg_createsubscriber.c:1136 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "ვერ მოვაცილე გამოწერა \"%s\": %s" + +#: pg_createsubscriber.c:1171 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "ვერ მივიღე უკვე არსებული გამოწერები: %s" + +#: pg_createsubscriber.c:1303 #, c-format msgid "could not drop replication slot \"%s\" on primary" msgstr "ვერ წავშალე რეპლიკაციის სლოტი \"%s\" ძირითადზე" -#: pg_createsubscriber.c:1169 +#: pg_createsubscriber.c:1337 #, c-format msgid "could not obtain failover replication slot information: %s" msgstr "გადასართველი რეპლიკაციის სლოტის ინფორმაციის მიღება შეუძლებელია: %s" -#: pg_createsubscriber.c:1171 pg_createsubscriber.c:1180 +#: pg_createsubscriber.c:1339 pg_createsubscriber.c:1348 #, c-format msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." msgstr "გამომწერზე გადასართველი რეპლიკაციის სლოტების მალე წაშლა WAL ფაილების მორჩენის თავიდან ასაცილებლად." -#: pg_createsubscriber.c:1179 +#: pg_createsubscriber.c:1347 #, c-format msgid "could not drop failover replication slot" msgstr "გადასართველი რეპლიკაციის სლოტი წაშლა შეუძლებელია" -#: pg_createsubscriber.c:1201 +#: pg_createsubscriber.c:1369 #, c-format -msgid "creating the replication slot \"%s\" on database \"%s\"" -msgstr "იქმნება რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "იქმნება რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1219 +#: pg_createsubscriber.c:1388 #, c-format -msgid "could not create replication slot \"%s\" on database \"%s\": %s" -msgstr "ვერ შევქმენი რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაზე \"%s\": %s" +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "ვერ შევქმენი რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაში \"%s\": %s" -#: pg_createsubscriber.c:1249 +#: pg_createsubscriber.c:1418 #, c-format -msgid "dropping the replication slot \"%s\" on database \"%s\"" -msgstr "იშლება რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "იშლება რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1265 +#: pg_createsubscriber.c:1434 #, c-format -msgid "could not drop replication slot \"%s\" on database \"%s\": %s" -msgstr "ვერ წავშალე რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაზე \"%s\": %s" +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "ვერ წავშალე რეპლიკაციის სლოტი \"%s\" მონაცემთა ბაზაში \"%s\": %s" -#: pg_createsubscriber.c:1286 +#: pg_createsubscriber.c:1455 #, c-format msgid "pg_ctl failed with exit code %d" msgstr "pg_ctl ჩავარდა გამოსვლის კოდით %d" -#: pg_createsubscriber.c:1291 +#: pg_createsubscriber.c:1460 #, c-format msgid "pg_ctl was terminated by exception 0x%X" msgstr "pg_ctl შეწყდა გამონაკლისით 0x%X" -#: pg_createsubscriber.c:1293 +#: pg_createsubscriber.c:1462 #, c-format msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." msgstr "თექვსმეტობითი მნიშვნელობის აღწერისთვის იხილეთ C-ის ჩასასმელი ფაილი \"ntstatus.h\"." -#: pg_createsubscriber.c:1295 +#: pg_createsubscriber.c:1464 #, c-format msgid "pg_ctl was terminated by signal %d: %s" msgstr "pg_ctl შეწყვეტილია სიგნალით %d: %s" -#: pg_createsubscriber.c:1301 +#: pg_createsubscriber.c:1470 #, c-format msgid "pg_ctl exited with unrecognized status %d" msgstr "pg_ctl დასრულდა უცნობი სტატუსით %d" -#: pg_createsubscriber.c:1304 +#: pg_createsubscriber.c:1473 #, c-format msgid "The failed command was: %s" msgstr "ჩავარდნილი ბრძანება იყო: %s" -#: pg_createsubscriber.c:1343 +#: pg_createsubscriber.c:1523 #, c-format msgid "server was started" msgstr "სერვერი გაეშვა" -#: pg_createsubscriber.c:1358 +#: pg_createsubscriber.c:1538 #, c-format msgid "server was stopped" msgstr "სერვერი გამოირთო" -#: pg_createsubscriber.c:1377 +#: pg_createsubscriber.c:1557 #, c-format msgid "waiting for the target server to reach the consistent state" msgstr "სამიზნე სერვერის მდგრად მდგომარეობაში გადასვლის მოლოდინი" -#: pg_createsubscriber.c:1400 +#: pg_createsubscriber.c:1580 #, c-format msgid "recovery timed out" msgstr "აღდგენის მოლოდინის ვადა ამოიწურა" -#: pg_createsubscriber.c:1413 +#: pg_createsubscriber.c:1593 #, c-format msgid "server did not end recovery" msgstr "სერვერმა აღდგენა არ დაამთავრა" -#: pg_createsubscriber.c:1415 +#: pg_createsubscriber.c:1595 #, c-format msgid "target server reached the consistent state" msgstr "სამიზნე სერვერმა მიაღწია მდგრად მდგომარეობას" -#: pg_createsubscriber.c:1416 +#: pg_createsubscriber.c:1596 #, c-format msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." msgstr "თუ ამ წერტილის შემდეგ pg_createsubscriber ჩავარდება, გაგრძელებამდე ფიზიკური რეპლიკა თავიდან უნდა შექმნათ." -#: pg_createsubscriber.c:1443 +#: pg_createsubscriber.c:1623 pg_createsubscriber.c:1746 #, c-format msgid "could not obtain publication information: %s" msgstr "გამოცემის ინფორმაციის მიღება შეუძლებელია: %s" -#: pg_createsubscriber.c:1457 +#: pg_createsubscriber.c:1637 #, c-format msgid "publication \"%s\" already exists" msgstr "პუბლიკაცია \"%s\" უკვე არსებობს" -#: pg_createsubscriber.c:1458 +#: pg_createsubscriber.c:1638 #, c-format msgid "Consider renaming this publication before continuing." msgstr "განიხილეთ ამ პუბლიკაციის სახელის გადარქმევა ხელახლა ცდამდე." -#: pg_createsubscriber.c:1465 +#: pg_createsubscriber.c:1645 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "იქმნება გამოცემა \"%s\" მონაცემთა ბაზაში \"%s\"" + +#: pg_createsubscriber.c:1658 #, c-format -msgid "creating publication \"%s\" on database \"%s\"" -msgstr "იქმნება გამოცემა \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "ვერ შევქმენი გამოცემა \"%s\" მონაცემთა ბაზაში \"%s\": %s" -#: pg_createsubscriber.c:1478 +#: pg_createsubscriber.c:1688 #, c-format -msgid "could not create publication \"%s\" on database \"%s\": %s" -msgstr "ვერ შევქმენი გამოცემა \"%s\" მონაცემთა ბაზაზე \"%s\": %s" +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "ვშლი გამოცემას \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1507 +#: pg_createsubscriber.c:1702 #, c-format -msgid "dropping publication \"%s\" on database \"%s\"" -msgstr "ვშლი გამოცემას \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "ვერ წავშალე გამოცემა \"%s\" მონაცემთა ბაზაში \"%s\": %s" -#: pg_createsubscriber.c:1521 +#: pg_createsubscriber.c:1739 #, c-format -msgid "could not drop publication \"%s\" on database \"%s\": %s" -msgstr "ვერ წავშალე გამოცემა \"%s\" მონაცემთა ბაზაზე \"%s\": %s" +msgid "dropping all existing publications in database \"%s\"" +msgstr "ვშლი ყველა არსებულ გამოცემას მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1567 +#: pg_createsubscriber.c:1797 #, c-format -msgid "creating subscription \"%s\" on database \"%s\"" -msgstr "იქმნება გამოწერა \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "იქმნება გამოწერა \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1588 +#: pg_createsubscriber.c:1819 #, c-format -msgid "could not create subscription \"%s\" on database \"%s\": %s" -msgstr "ვერ შევქმენი გამოწერა \"%s\" მონაცემთა ბაზაზე \"%s\": %s" +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "ვერ შევქმენი გამოწერა \"%s\" მონაცემთა ბაზაში \"%s\": %s" -#: pg_createsubscriber.c:1633 +#: pg_createsubscriber.c:1864 #, c-format msgid "could not obtain subscription OID: %s" msgstr "ვერ მივიღე გამოწერის OID: %s" -#: pg_createsubscriber.c:1640 +#: pg_createsubscriber.c:1871 #, c-format msgid "could not obtain subscription OID: got %d rows, expected %d row" msgstr "ვერ მივიღე გამოწერის OID: მივიღე %d მწკრივი, მოველოდი %d მწკრივს" -#: pg_createsubscriber.c:1664 +#: pg_createsubscriber.c:1895 #, c-format -msgid "setting the replication progress (node name \"%s\" ; LSN %s) on database \"%s\"" +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" msgstr "რეპლიკაციის მიმდინარეობის (კვანძის სახელი \"%s\", LSN %s) დაყენება მონაცემთა ბაზაზე \"%s\"" -#: pg_createsubscriber.c:1679 +#: pg_createsubscriber.c:1910 #, c-format -msgid "could not set replication progress for the subscription \"%s\": %s" +msgid "could not set replication progress for subscription \"%s\": %s" msgstr "შეუძლებელია რეპლიკაციის მიმდინარეობის დაყენება გამოწერისთვის \"%s\": %s" -#: pg_createsubscriber.c:1710 +#: pg_createsubscriber.c:1941 #, c-format -msgid "enabling subscription \"%s\" on database \"%s\"" -msgstr "ჩაირთვება გამოწერა \"%s\" მონაცემთა ბაზაზე \"%s\"" +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "ჩაირთვება გამოწერა \"%s\" მონაცემთა ბაზაში \"%s\"" -#: pg_createsubscriber.c:1722 +#: pg_createsubscriber.c:1953 #, c-format msgid "could not enable subscription \"%s\": %s" msgstr "ვერ ჩავრთე გამოწერა \"%s\": %s" -#: pg_createsubscriber.c:1814 +#: pg_createsubscriber.c:1999 +#, c-format +msgid "could not obtain a list of databases: %s" +msgstr "ვერ მივიღე მონაცემთა ბაზების სია: %s" + +#: pg_createsubscriber.c:2103 #, c-format msgid "cannot be executed by \"root\"" msgstr "root-ით ვერ გაეშვება" -#: pg_createsubscriber.c:1815 +#: pg_createsubscriber.c:2104 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "%s PostgreSQL-ის ზემომხმარებლით უნდა გაუშვათ." -#: pg_createsubscriber.c:1836 +#: pg_createsubscriber.c:2127 +#, c-format +msgid "database \"%s\" specified more than once for -d/--database" +msgstr "მონაცემთა ბაზა \"%s\" ერთზე მეტჯერაა მითითებული პარამეტრისთვის -d/--database" + +#: pg_createsubscriber.c:2146 +#, c-format +msgid "object type \"%s\" is specified more than once for -R/--remove" +msgstr "პარამეტრისთვის -R/--remove ობიექტის ტიპი \"%s\" ერთზე მეტჯერაა მითითებული" + +#: pg_createsubscriber.c:2174 #, c-format -msgid "duplicate database \"%s\"" -msgstr "განმეორებადი ბაზა \"%s\"" +msgid "publication \"%s\" specified more than once for --publication" +msgstr "პუბლიკაცია \"%s\" მითითებულია ერთზე მეტჯერ პარამეტრისთვის --publication" -#: pg_createsubscriber.c:1877 +#: pg_createsubscriber.c:2183 #, c-format -msgid "duplicate publication \"%s\"" -msgstr "განმეორებადი გამოცემა \"%s\"" +msgid "replication slot \"%s\" specified more than once for --replication-slot" +msgstr "რეპლიკაციის სლოტი \"%s\" მითითებულია ერთზე მეტჯერ პარამეტრისთვის --repilication-slot" -#: pg_createsubscriber.c:1889 +#: pg_createsubscriber.c:2192 #, c-format -msgid "duplicate replication slot \"%s\"" -msgstr "განმეორებადი რეპლიკაციის სლოტი \"%s\"" +msgid "subscription \"%s\" specified more than once for --subscription" +msgstr "გამოწერა \"%s\" მითითებულია ერთზე მეტჯერ პარამეტრისთვის --subscription" -#: pg_createsubscriber.c:1901 +#: pg_createsubscriber.c:2217 #, c-format -msgid "duplicate subscription \"%s\"" -msgstr "განმეორებადი გამოწერა \"%s\"" +msgid "%s cannot be used with -a/--all" +msgstr "%s-ს ვერ გამოიყენებთ -a/--all -თან ერთად" -#: pg_createsubscriber.c:1924 +#: pg_createsubscriber.c:2235 #, c-format msgid "no subscriber data directory specified" msgstr "გამომწერის მონაცემების საქაღალდე მითითებული არაა" -#: pg_createsubscriber.c:1935 +#: pg_createsubscriber.c:2246 #, c-format msgid "could not determine current directory" msgstr "მიმდინარე საქაღალდის იდენტიფიკაციის პრობლემა" -#: pg_createsubscriber.c:1952 +#: pg_createsubscriber.c:2263 #, c-format msgid "no publisher connection string specified" msgstr "გამომცემლის მიერთების სტრიქონი მითითებული არაა" -#: pg_createsubscriber.c:1956 +#: pg_createsubscriber.c:2267 #, c-format -msgid "validating connection string on publisher" -msgstr "შეერთების სტრიქონის დადასტურება გამომცემელზე" +msgid "validating publisher connection string" +msgstr "გამომცემლის მიერთების სტრიქონის გადამოწმება" -#: pg_createsubscriber.c:1962 +#: pg_createsubscriber.c:2273 #, c-format -msgid "validating connection string on subscriber" -msgstr "შეერთების სტრიქონის დადასტურება გამომწერზე" +msgid "validating subscriber connection string" +msgstr "მიმდინარეობს გამომწერის დაკავშირების სტრიქონის გადამოწმება" -#: pg_createsubscriber.c:1967 +#: pg_createsubscriber.c:2290 #, c-format msgid "no database was specified" msgstr "ბაზა მითითებული არაა" -#: pg_createsubscriber.c:1979 +#: pg_createsubscriber.c:2301 #, c-format -msgid "database \"%s\" was extracted from the publisher connection string" -msgstr "ბაზა \"%s\" ამოღებულია გამომცემლის მიერთების სტრიქონიიდან" +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "ბაზა \"%s\" გამოღებულია გამომცემლის მიერთების სტრიქონიდან" -#: pg_createsubscriber.c:1984 +#: pg_createsubscriber.c:2306 #, c-format msgid "no database name specified" msgstr "ბაზის სახელი მითითებული არაა" -#: pg_createsubscriber.c:1994 +#: pg_createsubscriber.c:2316 #, c-format -msgid "wrong number of publication names" -msgstr "გამოცემის სახელების არასწორი რაოდენობა" +msgid "wrong number of publication names specified" +msgstr "მითითებულია გამოცემის სახელების არასწორი რაოდენობა" -#: pg_createsubscriber.c:1995 +#: pg_createsubscriber.c:2317 #, c-format -msgid "Number of publication names (%d) must match number of database names (%d)." -msgstr "გამოცემის სახელების რაოდენობა (%d) ბაზის სახელების რაოდენობას (%d) უნდა ემთხვეოდეს." +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "გამოცემის სახელების რაოდენობა (%d) ბაზის სახელების მითითებულ რაოდენობას (%d) უნდა ემთხვეოდეს." -#: pg_createsubscriber.c:2001 +#: pg_createsubscriber.c:2323 #, c-format -msgid "wrong number of subscription names" -msgstr "გამოწერის სახელების არასწორი რაოდენობა" +msgid "wrong number of subscription names specified" +msgstr "მითითებულია გამოწერის სახელების არასწორი რაოდენობა" -#: pg_createsubscriber.c:2002 +#: pg_createsubscriber.c:2324 #, c-format -msgid "Number of subscription names (%d) must match number of database names (%d)." -msgstr "გამოწერის სახელების რაოდენობა (%d) ბაზის სახელების რაოდენობას (%d) უნდა ემთხვეოდეს." +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "მითითებული გამოწერის სახელების რაოდენობა (%d) მითითებული ბაზის სახელების რაოდენობას (%d) უნდა ემთხვეოდეს." -#: pg_createsubscriber.c:2008 +#: pg_createsubscriber.c:2330 #, c-format -msgid "wrong number of replication slot names" -msgstr "რეპლიკაციის სლოტის სახელების არასწორი რაოდენობა" +msgid "wrong number of replication slot names specified" +msgstr "მითითებულია რეპლიკაციის სლოტის სახელების არასწორი რაოდენობა" -#: pg_createsubscriber.c:2009 +#: pg_createsubscriber.c:2331 #, c-format -msgid "Number of replication slot names (%d) must match number of database names (%d)." -msgstr "რეპლიკაციის სლოტების სახელების რაოდენობა (%d) ბაზის სახელების რაოდენობას (%d) უნდა ემთხვეოდეს." +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "რეპლიკაციის სლოტების მითითებული სახელების რაოდენობა (%d) ბაზის სახელების მითითებულ რაოდენობას (%d) უნდა ემთხვეოდეს." -#: pg_createsubscriber.c:2038 +#: pg_createsubscriber.c:2343 +#, c-format +msgid "invalid object type \"%s\" specified for -R/--remove" +msgstr "პარამეტრისთვის -R/--remove მითითებული ობიექტის ტიპი '%s' არასწორია" + +#: pg_createsubscriber.c:2344 +#, c-format +msgid "The valid option is: \"publications\"" +msgstr "სწორი პარამეტრია \"publications\"" + +#: pg_createsubscriber.c:2375 #, c-format msgid "subscriber data directory is not a copy of the source database cluster" msgstr "გამომწერის მონაცემების საქაღალდე წყარო ბაზის კლასტერის ასლი არაა" -#: pg_createsubscriber.c:2051 +#: pg_createsubscriber.c:2388 #, c-format -msgid "standby is up and running" -msgstr "უქმე ჩართულია და მუშაობს" +msgid "standby server is running" +msgstr "უქმე სერვერი გაშვებულია" -#: pg_createsubscriber.c:2052 +#: pg_createsubscriber.c:2389 #, c-format -msgid "Stop the standby and try again." -msgstr "გააჩერეთ უქმე და თავიდან სცადეთ." +msgid "Stop the standby server and try again." +msgstr "გააჩერეთ უქმე სერვერი და თავიდან სცადეთ." -#: pg_createsubscriber.c:2061 +#: pg_createsubscriber.c:2398 #, c-format -msgid "starting the standby with command-line options" -msgstr "უქმეს გაშვება ბრძანების სტრიქონის პარამეტრებით" +msgid "starting the standby server with command-line options" +msgstr "მიმდინარეობს უქმე სერვერის გაშვება ბრძანების სტრიქონის პარამეტრებით" -#: pg_createsubscriber.c:2077 pg_createsubscriber.c:2116 +#: pg_createsubscriber.c:2414 pg_createsubscriber.c:2449 #, c-format msgid "stopping the subscriber" msgstr "გამომწერის გაჩერება" -#: pg_createsubscriber.c:2095 +#: pg_createsubscriber.c:2428 #, c-format msgid "starting the subscriber" msgstr "გამომწერის გაშვება" -#: pg_createsubscriber.c:2124 +#: pg_createsubscriber.c:2457 #, c-format msgid "Done!" msgstr "შესრულებულია!" @@ -1938,17 +2021,17 @@ msgstr "" msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=DIR წინასწარ-ჩაწერადი ჟურნალის ფაილების მითითებულ საქაღალდეში ჩაწერა\n" -#: pg_receivewal.c:83 pg_recvlogical.c:93 +#: pg_receivewal.c:83 pg_recvlogical.c:92 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN გამოსვლა მითითებული LSN-ის მიღების შემდეგ\n" -#: pg_receivewal.c:84 pg_recvlogical.c:97 +#: pg_receivewal.c:84 pg_recvlogical.c:98 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr " --if-not-exists სლოტის შექმნისას მისი არსებობის შემთხვევაში ფაქტი შეცდომად არ ჩაითვლება\n" -#: pg_receivewal.c:85 pg_recvlogical.c:99 +#: pg_receivewal.c:85 pg_recvlogical.c:100 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop შეერთების დაკარგვისას თავიდან არ ცდა\n" @@ -1958,14 +2041,14 @@ msgstr " -n, --no-loop შეერთების დაკარგ msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: pg_receivewal.c:87 pg_recvlogical.c:104 +#: pg_receivewal.c:87 pg_recvlogical.c:105 #, c-format msgid "" " -s, --status-interval=SECS\n" " time between status packets sent to server (default: %d)\n" msgstr "" " -s, --status-interval=SECS\n" -" შუალედი სერვერზე სტატუსის პაკეტების გაგზავნებს შორის (ნაგულისხმები: %d)\n" +" შუალედი სერვერზე სტატუსის პაკეტების გაგზავნებს შორის (ნაგულისხმევი: %d)\n" #: pg_receivewal.c:90 #, c-format @@ -1990,12 +2073,12 @@ msgstr "" "\n" "არასავალდებულო ქმედებები:\n" -#: pg_receivewal.c:104 pg_recvlogical.c:89 +#: pg_receivewal.c:104 pg_recvlogical.c:88 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr " --create-slot ახალი რეპლიკაციის სლოტის შექმნა (სლოტის სახელისთვის იხილეთ --slot)\n" -#: pg_receivewal.c:105 pg_recvlogical.c:90 +#: pg_receivewal.c:105 pg_recvlogical.c:89 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr " --drop-slot რეპლიკაციის სლოტის გადაგდება (რეპლიკაციის სახელისთვის იხილეთ --slot)\n" @@ -2015,7 +2098,7 @@ msgstr "ჟურნალის ნაკადი შეჩერდა მი msgid "switched to timeline %u at %X/%X" msgstr "გადავერთე %u-ე დროის ხაზზე მისამართით %X/%X" -#: pg_receivewal.c:224 pg_recvlogical.c:1053 +#: pg_receivewal.c:224 pg_recvlogical.c:1073 #, c-format msgid "received interrupt signal, exiting" msgstr "მიღებულია შეწყვეტის სიგნალი. გამოსვლა" @@ -2085,7 +2168,7 @@ msgstr "ფაილის (%s) შემოწმება შეუძლე msgid "starting log streaming at %X/%X (timeline %u)" msgstr "ჟურნალის ნაკადი დაიწყო მისამართზე %X/%X (დროის ხაზი %u)" -#: pg_receivewal.c:693 pg_recvlogical.c:801 +#: pg_receivewal.c:693 pg_recvlogical.c:807 #, c-format msgid "could not parse end position \"%s\"" msgstr "ბოლო პოზიციის დამუშავების შეცდომა: %s" @@ -2115,28 +2198,28 @@ msgstr "%s-სთან დაკავშირების მხარდა msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "რეპლიკაციის შეერთება სლოტით \"%s\" მოულოდნელად ბაზაზეა დამოკიდებული" -#: pg_receivewal.c:878 pg_recvlogical.c:972 +#: pg_receivewal.c:878 pg_recvlogical.c:991 #, c-format msgid "dropping replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის წაშლა: %s" -#: pg_receivewal.c:889 pg_recvlogical.c:982 +#: pg_receivewal.c:889 pg_recvlogical.c:1001 #, c-format msgid "creating replication slot \"%s\"" msgstr "რეპლიკაციის სლოტის შექმნა \"%s\"" -#: pg_receivewal.c:918 pg_recvlogical.c:1006 +#: pg_receivewal.c:918 pg_recvlogical.c:1026 #, c-format msgid "disconnected" msgstr "გათიშულია" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:1010 +#: pg_receivewal.c:922 pg_recvlogical.c:1030 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "გათიშულია; თავიდან ცდამდე დაყოვნება %d წამია" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:83 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -2146,7 +2229,7 @@ msgstr "" "\n" " \n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:87 #, c-format msgid "" "\n" @@ -2155,31 +2238,43 @@ msgstr "" "\n" "შესასრულებელი ქმედებები:\n" -#: pg_recvlogical.c:91 +#: pg_recvlogical.c:90 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr " --start რეპლიკაციის სლოტში ნაკადის გაშვება (სლოტის სახელისთვის იხილეთ --slot)\n" -#: pg_recvlogical.c:94 +#: pg_recvlogical.c:93 +#, c-format +#| msgid "" +#| " --includedir show location of C header files of the client\n" +#| " interfaces\n" +msgid "" +" --failover enable replication slot synchronization to standby servers when\n" +" creating a slot\n" +msgstr "" +" --failover ჩართავს რეპლიკაციის სლოტის სინქრონიზაციას უქმე სერვერებთან\n" +" სლოტის შექმნისას\n" + +#: pg_recvlogical.c:95 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=FILE ჟურნალის მითითებულ ფაილში მიღება. stdout-ისთვის -\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:96 #, c-format msgid "" " -F --fsync-interval=SECS\n" " time between fsyncs to the output file (default: %d)\n" msgstr "" " -F --fsync-interval=SECS\n" -" შუალედი გამოსატანი ფაილის fsync-ებს შორის (ნაგულისხმები: %d)\n" +" შუალედი გამოსატანი ფაილის fsync-ებს შორის (ნაგულისხმევი: %d)\n" -#: pg_recvlogical.c:98 +#: pg_recvlogical.c:99 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN ნაკადის დასაწყისი არსებული სლოტისთვის\n" -#: pg_recvlogical.c:100 +#: pg_recvlogical.c:101 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -2190,280 +2285,286 @@ msgstr "" " გამოტანის დამატებისთვის მითითებული სახელის, არასავალდებულო მნიშვნელობით,\n" " გადაცემა\n" -#: pg_recvlogical.c:103 +#: pg_recvlogical.c:104 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" -msgstr " -P, --plugin=PLUGIN გამოტანის მითითებული დამატების გამოყენება (ნაგულისხმები: %s)\n" +msgstr " -P, --plugin=PLUGIN გამოტანის მითითებული დამატების გამოყენება (ნაგულისხმევი: %s)\n" -#: pg_recvlogical.c:106 +#: pg_recvlogical.c:107 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOTNAME ლოგიკური რეპლიკაციის სლოტის სახელი\n" -#: pg_recvlogical.c:107 +#: pg_recvlogical.c:108 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr " -t, --two-phase სლოტის შექმნისას მომზადებული ტრანზაქციების დეკოდერის ჩართვა\n" -#: pg_recvlogical.c:112 +#: pg_recvlogical.c:113 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=DBNAME მისაერთებელი ბაზის სახელი\n" -#: pg_recvlogical.c:145 +#: pg_recvlogical.c:146 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "ჩაწერის დადასტურება %X/%X-მდე, %X/%X-მდე მოცილება (სლოტი %s)" -#: pg_recvlogical.c:169 receivelog.c:360 +#: pg_recvlogical.c:170 receivelog.c:359 #, c-format msgid "could not send feedback packet: %s" msgstr "უკუკავშირის პაკეტის გაგზავნის შეცდომა: %s" -#: pg_recvlogical.c:239 +#: pg_recvlogical.c:240 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "ჟურნალის ნაკადის დაწყება მისამართზე %X/%X (სლოტი %s)" -#: pg_recvlogical.c:281 +#: pg_recvlogical.c:282 #, c-format msgid "streaming initiated" msgstr "ნაკადი ინიცირებულია" -#: pg_recvlogical.c:346 +#: pg_recvlogical.c:347 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ჟურნალის ფაილის გახსნის შეცდომა \"%s\": %m" -#: pg_recvlogical.c:375 receivelog.c:882 +#: pg_recvlogical.c:376 receivelog.c:889 #, c-format msgid "invalid socket: %s" msgstr "არასწორი სოკეტი: %s" -#: pg_recvlogical.c:428 receivelog.c:910 +#: pg_recvlogical.c:429 receivelog.c:917 #, c-format msgid "%s() failed: %m" msgstr "%s()-ის შეცდომა: %m" -#: pg_recvlogical.c:435 receivelog.c:959 +#: pg_recvlogical.c:436 receivelog.c:966 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "\"WAL\" ნაკადიდან მონაცემების მიღების შეცდომა: %s" -#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 -#: receivelog.c:1066 +#: pg_recvlogical.c:478 pg_recvlogical.c:529 receivelog.c:1010 +#: receivelog.c:1073 #, c-format msgid "streaming header too small: %d" msgstr "ნაკადის თავსართი ძალიან პატარაა: %d" -#: pg_recvlogical.c:512 receivelog.c:843 +#: pg_recvlogical.c:513 receivelog.c:846 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "ნაკადის უცნობი თავსართი: \"%c\"" -#: pg_recvlogical.c:566 pg_recvlogical.c:578 +#: pg_recvlogical.c:567 pg_recvlogical.c:579 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "%d ბაიტის ჩაწერის შეცდომა ჟურნალის ფაილში \"%s\": %m" -#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:637 receivelog.c:641 receivelog.c:678 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "რეპლიკაციის ნაკადის მოულოდნელი დასასრული: %s" -#: pg_recvlogical.c:796 +#: pg_recvlogical.c:802 #, c-format msgid "could not parse start position \"%s\"" msgstr "საწყისი მდებარეობის დამუშავების შეცდომა: %s" -#: pg_recvlogical.c:874 +#: pg_recvlogical.c:880 #, c-format msgid "no slot specified" msgstr "სლოტი მითითებული არაა" -#: pg_recvlogical.c:881 +#: pg_recvlogical.c:887 #, c-format msgid "no target file specified" msgstr "სამიზნე ფაილი მითითებული არაა" -#: pg_recvlogical.c:888 +#: pg_recvlogical.c:894 #, c-format msgid "no database specified" msgstr "ბაზა მითითებული არაა" -#: pg_recvlogical.c:895 +#: pg_recvlogical.c:901 #, c-format msgid "at least one action needs to be specified" msgstr "საჭიროა, სულ ცოტა, ერთი ქმედების მითითება" -#: pg_recvlogical.c:902 +#: pg_recvlogical.c:908 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "--create-slot -ს და ---start-ს -drop-slot -თან ერთად ვერ გამოიყენებთ" -#: pg_recvlogical.c:909 +#: pg_recvlogical.c:915 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "--create-slot -ს და --drop-slot-ს --startpos -თან ერთად ვერ გამოიყენებთ" -#: pg_recvlogical.c:916 +#: pg_recvlogical.c:922 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos -ის მითითება მხოლოდ --start -თან ერთად შეიძლება" -#: pg_recvlogical.c:923 +#: pg_recvlogical.c:931 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase -ის მითითება მხოლოდ --create-slot -თან ერთად შეიძლება" -#: pg_recvlogical.c:956 +#: pg_recvlogical.c:938 +#, c-format +#| msgid "--two-phase may only be specified with --create-slot" +msgid "--failover may only be specified with --create-slot" +msgstr "--failover პარამეტრის მითითება, მხოლოდ, --create-slot პარამეტრთან ერთად შეგიძლიათ" + +#: pg_recvlogical.c:975 #, c-format msgid "could not establish database-specific replication connection" msgstr "ბაზაზე-დამოკიდებული რეპლიკაციის შეერთების დამყარების შეცდომა" -#: pg_recvlogical.c:1056 +#: pg_recvlogical.c:1076 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "ბოლო მდებარეობა %X/%X keepalive-ის მიერ მიღწეული" -#: pg_recvlogical.c:1061 +#: pg_recvlogical.c:1081 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "ბოლო მდებარეობა %X/%X WAL ჩანაწერის მიერ მიღწეულია მისამართზე %X/%X" -#: receivelog.c:66 +#: receivelog.c:65 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "არქივის სტატუსის ფაილის \"%s\" შექმნის შეცდომა: %s" -#: receivelog.c:73 +#: receivelog.c:72 #, c-format msgid "could not close archive status file \"%s\": %s" msgstr "არქივის სტატუსის ფაილის \"%s\" დახურვის შეცდომა: %s" -#: receivelog.c:122 +#: receivelog.c:121 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "წინასწარ-ჩაწერადი ჟურნალის ფაილის \"%s\" ზომის მიღების შეცდომა: %s" -#: receivelog.c:133 +#: receivelog.c:132 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "წინასწარ-ჩაწერადი ჟურნალის არსებული ფაილის \"%s\" გახსნის შეცდომა: %s" -#: receivelog.c:142 +#: receivelog.c:141 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "წინასწარ-ჩაწერადი ჟურნალის არსებული ფაილის \"%s\" fsync()-ის შეცდომა: %s" -#: receivelog.c:157 +#: receivelog.c:156 #, c-format msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" msgstr[0] "წინასწარ-ჩაწერადი ჟურნალის ფაილს \"%s\" აქვს %zd ბაიტი. უნდა იყოს 0 ან %d" msgstr[1] "წინასწარ-ჩაწერადი ჟურნალის ფაილს \"%s\" აქვს %zd ბაიტი. უნდა იყოს 0 ან %d" -#: receivelog.c:175 +#: receivelog.c:174 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "წინასწარ-ჩაწერადი ჟურნალის არსებული ფაილის \"%s\" გახსნის შეცდომა: %s" -#: receivelog.c:216 +#: receivelog.c:215 #, c-format msgid "not renaming \"%s\", segment is not complete" msgstr "\"%s\"-ის სახელი არ შეიცვლება. სეგმენტი დაუსრულებელია" -#: receivelog.c:227 receivelog.c:317 receivelog.c:688 +#: receivelog.c:226 receivelog.c:316 receivelog.c:687 #, c-format msgid "could not close file \"%s\": %s" msgstr "ფაილის (\"%s\") დახურვის შეცდომა: %s" -#: receivelog.c:288 +#: receivelog.c:287 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "სერვერის პასუხში მოულოდნელი ისტორიის ფაილის სახელია, დროის ხაზისთვის %u: %s" -#: receivelog.c:297 +#: receivelog.c:296 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "დროის ხაზის ისტორიის ფაილის (%s) შექმნის შეცდომა: %s" -#: receivelog.c:304 +#: receivelog.c:303 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "დროის ხაზის ისტორიის ფაილის (%s) ჩაწერის შეცდომა: %s" -#: receivelog.c:394 +#: receivelog.c:393 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions older than %s" msgstr "სერვერის შეუთავსებელი ვერსია %s: კლიენტს ნაკადის მხარდაჭერა სერვერებიდან, რომლის ვერსიაც დაბალია %s-ზე, არ გააჩნია" -#: receivelog.c:403 +#: receivelog.c:402 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions newer than %s" msgstr "სერვერის შეუთავსებელი ვერსია %s: კლიენტს ნაკადის მხარდაჭერა სერვერებიდან, რომლის ვერსიაც მაღალია %s-ზე, არ გააჩნია" -#: receivelog.c:508 +#: receivelog.c:507 #, c-format msgid "system identifier does not match between base backup and streaming connection" msgstr "სისტემის იდენტიფიკატორი ბაზს მარქაფსა და ნაკადურ შეერთებას შორის არ ემთხვევა" -#: receivelog.c:516 +#: receivelog.c:515 #, c-format msgid "starting timeline %u is not present in the server" msgstr "დაწყების დროის ხაზი %u სერვერზე არ არსებობს" -#: receivelog.c:555 +#: receivelog.c:554 #, c-format msgid "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, expected %d rows and %d fields" msgstr "მოულოდნელი პასუხი TIMELINE_HISTORY ბრძანებაზე: მივიღე %d მწკრივი და %d ველი, ველოდებოდი %d მწკრივს და %d ველს" -#: receivelog.c:626 +#: receivelog.c:625 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "სერვერის პასუხში მოულოდნელი შემდეგი დროის ხაზია (%u), დროის ხაზის შემდეგ: %u" -#: receivelog.c:632 +#: receivelog.c:631 #, c-format msgid "server stopped streaming timeline %u at %X/%X, but reported next timeline %u to begin at %X/%X" msgstr "სერვერმა შეწყვიტა დროის ხაზის %u ნაკადი მისამართზე %X/%X, მაგრამ მოიწერა, რომ შემდეგი დროის ხაზი %u მისამართზე %X/%X იწყება" -#: receivelog.c:672 +#: receivelog.c:671 #, c-format msgid "replication stream was terminated before stop point" msgstr "რეპლიკაციის ნაკადი გაჩერების წერტილამდე შეწყდა" -#: receivelog.c:718 +#: receivelog.c:717 #, c-format msgid "unexpected result set after end-of-timeline: got %d rows and %d fields, expected %d rows and %d fields" msgstr "მოულოდნელი შედეგების ნაკრები დროის-ხაზის-დამთავრების შემდეგ: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ველს" -#: receivelog.c:727 +#: receivelog.c:726 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "შემდეგი დროის ხაზის დაწყების წერტილის (%s) დამუშავების შეცდომა" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 +#: receivelog.c:774 receivelog.c:1029 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "ფაილის (\"%s\") fsync-ის შეცდომა: %s" -#: receivelog.c:1083 +#: receivelog.c:1090 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "მიღებულია წინასწარ-ჩაწერადი ჟურნალის ჩანაწერი წანაცვლებისთვის %u მაშინ, როცა ფაილები ღია არაა" -#: receivelog.c:1093 +#: receivelog.c:1100 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "მიღებული WAL მონაცემის წანაცვლება %08x, მოველოდი %08x" -#: receivelog.c:1128 +#: receivelog.c:1135 #, c-format msgid "could not write %d bytes to WAL file \"%s\": %s" msgstr "%d ბაიტის WAL ფაილში (\"%s\") ჩაწერის შეცდომა: %s" -#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 +#: receivelog.c:1160 receivelog.c:1200 receivelog.c:1228 #, c-format msgid "could not send copy-end packet: %s" msgstr "copy-end პაკეტის გაგზავნის შეცდომა: %s" @@ -2477,11 +2578,6 @@ msgstr "პაროლი: " msgid "could not connect to server" msgstr "სერვერთან მიერთების პრობლემა" -#: streamutil.c:230 -#, c-format -msgid "could not clear \"search_path\": %s" -msgstr "\"search_path\"-ის გასუფთავების პრობლემა: %s" - #: streamutil.c:246 #, c-format msgid "could not determine server setting for \"integer_datetimes\"" @@ -2492,69 +2588,69 @@ msgstr "სერვერის პარამეტრის \"integer_dateti msgid "\"integer_datetimes\" compile flag does not match server" msgstr "აგებისას მითითებული ალამი \"integer_datetimes\" სერვერისას არ ემთხვვევა" -#: streamutil.c:372 +#: streamutil.c:304 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "შეცდომა WAL-ის სეგმენტის ზომის მიღებისას: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ან მეტ ველს" -#: streamutil.c:382 +#: streamutil.c:314 #, c-format msgid "WAL segment size could not be parsed" msgstr "WAL სეგმენტის ზომის დამუშავების შეცდომა" -#: streamutil.c:400 +#: streamutil.c:332 #, c-format msgid "remote server reported invalid WAL segment size (%d byte)" msgid_plural "remote server reported invalid WAL segment size (%d bytes)" msgstr[0] "დაშორებულმა სერვერმა არასწორი WAL სეგმენტის ზომის (%d ბაიტი) შესახებ შეგვატყობინა" msgstr[1] "დაშორებულმა სერვერმა არასწორი WAL სეგმენტის ზომის (%d ბაიტი) შესახებ შეგვატყობინა" -#: streamutil.c:404 +#: streamutil.c:336 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WAL სეგმენტის ზომა ორის ხარისხი უნდა იყოს, შუალედიდან 1მბ-1გბ." -#: streamutil.c:446 +#: streamutil.c:378 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "ჯგუფის წვდომის ალმის გამოთხოვის შეცდომა: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ან მეტ ველს" -#: streamutil.c:455 +#: streamutil.c:387 #, c-format msgid "group access flag could not be parsed: %s" msgstr "ჯგუფის წვდომის ალმის დამუშავების შეცდომა: %s" -#: streamutil.c:498 streamutil.c:535 +#: streamutil.c:430 streamutil.c:467 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "სისტემის ამოცნობის შეცდომა: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ან მეტ ველს" -#: streamutil.c:587 +#: streamutil.c:519 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "რეპლიკაციის სლოტის (\"%s\") წაკითხვის შეცდომა: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ველს" -#: streamutil.c:599 +#: streamutil.c:531 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "რეპლიკაციის სლოტი \"%s\"არ არსებობს" -#: streamutil.c:610 +#: streamutil.c:542 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "მოველოდი ფიზიკური რეპლიკაციის სლოტს. მივიღე: %s" -#: streamutil.c:624 +#: streamutil.c:556 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "restart_lsn \"%s\"-ის დამუშავების შეცდომა რეპლიკაციის სლოტისთვის \"%s\"" -#: streamutil.c:741 +#: streamutil.c:678 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "რეპლიკაციის სლოტის (\"%s\") შექმნის შეცდომა: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ველს" -#: streamutil.c:785 +#: streamutil.c:722 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "რეპლიკაციის სლოტის (\"%s\") გადაგდების შეცდომა: მივიღე %d მწკრივი და %d ველი. მოველოდი %d მწკრივს და %d ველს" @@ -2587,6 +2683,42 @@ msgstr "წაშლა შეკუმშვით მხარდაუჭე msgid "could not close compression stream" msgstr "შეკუმშვის ნაკადის დახურვის შეცდომა" +#, c-format +#~ msgid "" +#~ " --config-file=FILENAME use specified main server configuration\n" +#~ " file when running target cluster\n" +#~ msgstr "" +#~ " --config-file=FILENAME სამიზნე კლასტერის გაშვებისას მთავარი \n" +#~ " სერვერის მითითებული კონფიგურაციის ფაილში გამოყენება\n" + +#, c-format +#~ msgid " -s, --socket-directory=DIR socket directory to use (default current directory)\n" +#~ msgstr " -s, --socket-directory=DIR სოკეტის საქაღალდე (ნაგულისხმევია მიმდინარე.)\n" + +#, c-format +#~ msgid " -?, --help show this help, then exit\n" +#~ msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" + +#, c-format +#~ msgid " -V, --version output version information, then exit\n" +#~ msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" + +#, c-format +#~ msgid "Consider increasing max_logical_replication_workers to at least %d." +#~ msgstr "განიხილეთ max_logical_replication_workers-ის გაზრდა მინიმუმ %d-მდე." + +#, c-format +#~ msgid "Consider increasing max_replication_slots to at least %d." +#~ msgstr "განიხილეთ max_replication_slots-ის გაზრდა მინიმუმ %d-მდე." + +#, c-format +#~ msgid "Consider increasing max_wal_senders to at least %d." +#~ msgstr "განიხილეთ max_wal_senders-ის გაზრდა მინიმუმ %d-მდე." + +#, c-format +#~ msgid "Consider increasing max_worker_processes to at least %d." +#~ msgstr "განიხილეთ max_worker_processes-ის გაზრდა მინიმუმ %d-მდე." + #, c-format #~ msgid "This build does not support compression with %s." #~ msgstr "ამ აგებაში %s-ით შეკუმშვის მხარდაჭრა არ არსებობს." @@ -2601,6 +2733,10 @@ msgstr "შეკუმშვის ნაკადის დახურვი #~ msgid "could not check file \"%s\"" #~ msgstr "ფაილის შემოწმება შეუძლებელია: %s" +#, c-format +#~ msgid "could not clear search_path: %s" +#~ msgstr "search_path-ის გასუფთავების პრობლემა: %s" + #, c-format #~ msgid "could not determine seek position in file \"%s\": %s" #~ msgstr "ფაილში %s გადახვევის მდებარეობის დადგენა შეუძლებელია: %s" @@ -2613,6 +2749,22 @@ msgstr "შეკუმშვის ნაკადის დახურვი #~ msgid "could not set compression flag for %s: %s" #~ msgstr "%s-სთვის შეკუმშვის დონის დაყენების შეცდომა: %s" +#, c-format +#~ msgid "duplicate database \"%s\"" +#~ msgstr "განმეორებადი ბაზა \"%s\"" + +#, c-format +#~ msgid "duplicate publication \"%s\"" +#~ msgstr "განმეორებადი გამოცემა \"%s\"" + +#, c-format +#~ msgid "duplicate replication slot \"%s\"" +#~ msgstr "განმეორებადი რეპლიკაციის სლოტი \"%s\"" + +#, c-format +#~ msgid "duplicate subscription \"%s\"" +#~ msgstr "განმეორებადი გამოწერა \"%s\"" + #, c-format #~ msgid "log streamer with pid %d exiting" #~ msgstr "ჟურნალის ნაკადის პროცესი pid-ით %d ასრულებს მუშაობას" @@ -2625,10 +2777,18 @@ msgstr "შეკუმშვის ნაკადის დახურვი #~ msgid "primary has replication slot \"%s\"" #~ msgstr "ძირითადს აქვს რეპლიკაციის სლოტი \"%s\"" +#, c-format +#~ msgid "standby is up and running" +#~ msgstr "უქმე ჩართულია და მუშაობს" + #, c-format #~ msgid "standby server disconnected from the primary" #~ msgstr "უქმე სერვერ გაითიშა ძირითადისგან" +#, c-format +#~ msgid "subscriber failed to change system identifier: exit code: %d" +#~ msgstr "გამომწერის სისტემური იდენტიფიკატორის შეცვლა ჩავარდა: გამოსვლის კოდი: %d" + #, c-format #~ msgid "symlinks are not supported on this platform" #~ msgstr "სიმბმულები ამ პლატფორმაზე მხარდაჭერილი არაა" @@ -2648,3 +2808,7 @@ msgstr "შეკუმშვის ნაკადის დახურვი #, c-format #~ msgid "unknown compression option \"%s\"" #~ msgstr "შეკუმშვის უცნობი პარამეტრი: \"%s\"" + +#, c-format +#~ msgid "validating connection string on subscriber" +#~ msgstr "შეერთების სტრიქონის დადასტურება გამომწერზე" diff --git a/src/bin/pg_basebackup/po/ko.po b/src/bin/pg_basebackup/po/ko.po index bbd19de74311b..08861d1022c3e 100644 --- a/src/bin/pg_basebackup/po/ko.po +++ b/src/bin/pg_basebackup/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_basebackup (PostgreSQL) 13\n" +"Project-Id-Version: pg_basebackup (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2020-10-05 01:15+0000\n" -"PO-Revision-Date: 2020-10-06 11:02+0900\n" +"POT-Creation-Date: 2025-01-17 04:49+0000\n" +"PO-Revision-Date: 2025-01-18 02:23+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -17,167 +17,484 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:236 -#, c-format -msgid "fatal: " -msgstr "심각: " - -#: ../../../src/common/logging.c:243 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "오류: " -#: ../../../src/common/logging.c:250 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "경고: " +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "상세정보: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "힌트: " + +#: ../../common/compression.c:132 ../../common/compression.c:141 +#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 +#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 +#: bbstreamer_zstd.c:284 +#, c-format +msgid "this build does not support compression with %s" +msgstr "이 버전은 %s 압축 기능을 포함 하지 않고 빌드 되었습니다." + +#: ../../common/compression.c:205 +msgid "found empty string where a compression option was expected" +msgstr "압축 옵션을 지정하는 자리에 빈 문자열이 있습니다." + +#: ../../common/compression.c:244 +#, c-format +msgid "unrecognized compression option: \"%s\"" +msgstr "인식할 수 없는 압축 옵션: \"%s\"" + +#: ../../common/compression.c:283 +#, c-format +msgid "compression option \"%s\" requires a value" +msgstr "\"%s\" 압축 옵션에는 그 지정값이 필요합니다." + +#: ../../common/compression.c:292 +#, c-format +msgid "value for compression option \"%s\" must be an integer" +msgstr "\"%s\" 압축 옵션 값은 정수여야 합니다." + +#: ../../common/compression.c:331 +#, c-format +msgid "value for compression option \"%s\" must be a Boolean value" +msgstr "\"%s\" 압축 옵션 값은 부울린형여야 합니다." + +#: ../../common/compression.c:379 +#, c-format +msgid "compression algorithm \"%s\" does not accept a compression level" +msgstr "\"%s\" 압축 알고리즘은 압축 수준을 지정할 수 없습니다." + +#: ../../common/compression.c:386 +#, c-format +msgid "" +"compression algorithm \"%s\" expects a compression level between %d and %d " +"(default at %d)" +msgstr "" +"\"%s\" 압축 알고리즘은 압축 수준값으로 %d에서 %d까지만 허용함 (기본값 %d)" + +#: ../../common/compression.c:397 +#, c-format +msgid "compression algorithm \"%s\" does not accept a worker count" +msgstr "\"%s\" 압축 알고리즘은 병렬 작업 수를 지정할 수 없습니다." + +#: ../../common/compression.c:408 +#, c-format +msgid "compression algorithm \"%s\" does not support long-distance mode" +msgstr "\"%s\" 압축 알고리즘은 원거리 모드를 지원하지 않습니다." + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "읽기 용 \"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "\"%s\" 파일을 닫을 수 없음: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 불일치" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"바이트 순서 일치하지 않는 문제\n" +"바이트 순서 정보는 pg_control 파일을 저장할 때 사용되는데,\n" +"이 파일의 바이트 순서 정보와 이 프로그램에서 사용하는 순서 정보가 다릅니다.\n" +"이럴 경우, 출력 결과가 바르지 않을 수 있고,\n" +"설치된 PostgreSQL 프로그램과 데이터 디렉터리가 호환되지 않을 수 있습니다." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "\"%s\" 파일 쓰기 실패: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일 fsync 실패: %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 -#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format msgid "out of memory\n" msgstr "메모리 부족\n" -#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 #, c-format msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 복제할 수 없음(내부 오류)\n" -#: ../../common/file_utils.c:79 ../../common/file_utils.c:181 -#: pg_receivewal.c:266 pg_recvlogical.c:340 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위해 파일 시스템 동기화 실패: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" -#: ../../common/file_utils.c:158 pg_receivewal.c:169 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "\"%s\" 디렉터리 열 수 없음: %m" -#: ../../common/file_utils.c:192 pg_receivewal.c:337 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" -#: ../../common/file_utils.c:224 ../../common/file_utils.c:283 -#: ../../common/file_utils.c:357 ../../fe_utils/recovery_gen.c:134 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" -#: ../../common/file_utils.c:295 ../../common/file_utils.c:365 -#: pg_recvlogical.c:193 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "\"%s\" 파일 fsync 실패: %m" +msgid "could not open process token: error code %lu" +msgstr "프로세스 토큰을 열 수 없음: 오류 코드 %lu" -#: ../../common/file_utils.c:375 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "SID를 할당할 수 없음: 오류 코드 %lu" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "제한된 토큰을 생성할 수 없습니다: %lu" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "\"%s\" 명령용 프로세스를 시작할 수 없음: 오류 코드 %lu" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "제한된 토큰으로 다시 실행할 수 없음: 오류 코드 %lu" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값은 \"%s\" 옵션값으로 유효하지 않음" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 값은 %d부터 %d까지 지정할 수 있습니다." + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" -#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49 -#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100 -#: ../../fe_utils/recovery_gen.c:171 pg_basebackup.c:1248 +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:334 #, c-format msgid "out of memory" msgstr "메모리 부족" -#: ../../fe_utils/recovery_gen.c:140 pg_basebackup.c:1021 pg_basebackup.c:1714 -#: pg_basebackup.c:1770 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "\"%s\" 파일 쓰기 실패: %m" -#: ../../fe_utils/recovery_gen.c:152 pg_basebackup.c:1166 pg_basebackup.c:1671 -#: pg_basebackup.c:1747 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "\"%s\" 파일을 만들 수 없음: %m" -#: pg_basebackup.c:224 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + +#: bbstreamer_file.c:275 +#, c-format +msgid "unexpected state while extracting archive" +msgstr "아카이브 추출 중 예상치 못한 상태값 발견" + +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" + +#: bbstreamer_file.c:326 +#, c-format +msgid "could not set permissions on directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 액세스 권한을 지정할 수 없음: %m" + +#: bbstreamer_file.c:345 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 심볼릭 링크로 만들 수 없음: %m" + +#: bbstreamer_file.c:365 +#, c-format +msgid "could not set permissions on file \"%s\": %m" +msgstr "파일 \"%s\" 의 접근권한을 지정할 수 없음: %m" + +#: bbstreamer_gzip.c:95 +#, c-format +msgid "could not create compressed file \"%s\": %m" +msgstr "\"%s\" 압축 파일 만들기 실패: %m" + +#: bbstreamer_gzip.c:103 +#, c-format +msgid "could not duplicate stdout: %m" +msgstr "stdout을 중복할 수 없음: %m" + +#: bbstreamer_gzip.c:107 +#, c-format +msgid "could not open output file: %m" +msgstr "출력파일을 열 수 없음: %m" + +#: bbstreamer_gzip.c:111 +#, c-format +msgid "could not set compression level %d: %s" +msgstr "잘못된 압축 수위 %d: %s" + +#: bbstreamer_gzip.c:143 +#, c-format +msgid "could not write to compressed file \"%s\": %s" +msgstr "\"%s\" 압축 파일 쓰기 실패: %s" + +#: bbstreamer_gzip.c:167 +#, c-format +msgid "could not close compressed file \"%s\": %m" +msgstr "\"%s\" 압축 파일 닫기 실패: %m" + +#: bbstreamer_gzip.c:245 walmethods.c:880 +#, c-format +msgid "could not initialize compression library" +msgstr "압축 라이브러리를 초기화할 수 없음" + +#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 +#, c-format +msgid "could not decompress data: %s" +msgstr "압축 풀기 실패: %s" + +#: bbstreamer_inject.c:189 +#, c-format +msgid "unexpected state while injecting recovery settings" +msgstr "복구 관련 설정을 추가 하는 도중 예상치 못한 상태 발견" + +#: bbstreamer_lz4.c:95 +#, c-format +msgid "could not create lz4 compression context: %s" +msgstr "lz4 압축 컨텍스트 정보를 생성할 수 없습니다: %s" + +#: bbstreamer_lz4.c:140 +#, c-format +msgid "could not write lz4 header: %s" +msgstr "lz4 헤더를 쓸 수 없음: %s" + +#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 +#, c-format +msgid "could not compress data: %s" +msgstr "자료를 압축할 수 없음: %s" + +#: bbstreamer_lz4.c:241 +#, c-format +msgid "could not end lz4 compression: %s" +msgstr "lz4 압축을 끝낼 수 없음: %s" + +#: bbstreamer_lz4.c:293 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "압축 라이브러리를 초기화 할 수 없음: %s" + +#: bbstreamer_tar.c:244 +#, c-format +msgid "tar file trailer exceeds 2 blocks" +msgstr "tar 파일 끝부분에서 2 블록이 초과됨" + +#: bbstreamer_tar.c:249 +#, c-format +msgid "unexpected state while parsing tar archive" +msgstr "tar 아카이브 분석 중 예상치 못한 상태 발견" + +#: bbstreamer_tar.c:292 +#, c-format +msgid "tar member has empty name" +msgstr "tar 맴버에 이름이 없음" + +#: bbstreamer_tar.c:326 +#, c-format +msgid "COPY stream ended before last file was finished" +msgstr "마지막 파일을 끝내기 전에 COPY 스트림이 끝났음" + +#: bbstreamer_zstd.c:85 +#, c-format +msgid "could not create zstd compression context" +msgstr "zstd 압축 컨텍스트를 만들 수 없음" + +#: bbstreamer_zstd.c:91 +#, c-format +msgid "could not set zstd compression level to %d: %s" +msgstr "zstd 압축 수준을 %d 값으로 지정할 수 없음: %s" + +#: bbstreamer_zstd.c:105 +#, c-format +msgid "could not set compression worker count to %d: %s" +msgstr "압축용 병렬 작업자 수를 %d 값으로 지정할 수 없음: %s" + +#: bbstreamer_zstd.c:116 +#, c-format +msgid "could not enable long-distance mode: %s" +msgstr "원거리 모드를 활성화 할 수 없음: %s" + +#: bbstreamer_zstd.c:275 +#, c-format +msgid "could not create zstd decompression context" +msgstr "zstd 압축 컨텍스트를 만들 수 없음" + +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "\"%s\" 디렉터리를 지우는 중" -#: pg_basebackup.c:226 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "데이터 디렉터리 삭제 실패" -#: pg_basebackup.c:230 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "\"%s\" 데이터 디렉터리의 내용을 지우는 중" -#: pg_basebackup.c:232 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "데이터 디렉터리의 내용을 지울 수 없음" -#: pg_basebackup.c:237 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "\"%s\" WAL 디렉터리를 지우는 중" -#: pg_basebackup.c:239 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "WAL 디렉터리 삭제 실패" -#: pg_basebackup.c:243 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "\"%s\" WAL 디렉터리 내용을 지우는 중" -#: pg_basebackup.c:245 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "WAL 디렉터리의 내용을 지울 수 없음" -#: pg_basebackup.c:251 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "사용자 요청으로 \"%s\" 데이터 디렉터리를 지우지 않았음" -#: pg_basebackup.c:254 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "사용자 요청으로 \"%s\" WAL 디렉터리를 지우지 않았음" -#: pg_basebackup.c:258 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "아직 마무리 되지 않은 테이블스페이스 디렉터리 변경함" -#: pg_basebackup.c:299 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "디렉터리 이름이 너무 김" -#: pg_basebackup.c:309 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "테이블스페이스 맵핑 하는 곳에서 \"=\" 문자가 중복 되어 있음" -#: pg_basebackup.c:321 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "" "\"%s\" 형식의 테이블스페이스 맵핑이 잘못 되었음, \"OLDDIR=NEWDIR\" 형식이어" "야 함" -#: pg_basebackup.c:333 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "테이블스페이스 맵핑용 옛 디렉터리가 절대 경로가 아님: %s" -#: pg_basebackup.c:340 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "테이블스페이스 맵핑용 새 디렉터리가 절대 경로가 아님: %s" -#: pg_basebackup.c:379 +#: pg_basebackup.c:392 #, c-format msgid "" "%s takes a base backup of a running PostgreSQL server.\n" @@ -187,17 +504,19 @@ msgstr "" "다.\n" "\n" -#: pg_basebackup.c:381 pg_receivewal.c:79 pg_recvlogical.c:75 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_basebackup.c:382 pg_receivewal.c:80 pg_recvlogical.c:76 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [옵션]...\n" -#: pg_basebackup.c:383 +#: pg_basebackup.c:396 #, c-format msgid "" "\n" @@ -206,17 +525,26 @@ msgstr "" "\n" "출력물을 제어야하는 옵션들:\n" -#: pg_basebackup.c:384 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" msgstr " -D, --pgdata=디렉터리 베이스 백업 결과물이 저장될 디렉터리\n" -#: pg_basebackup.c:385 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr " -F, --format=p|t 출력 형식 (plain (초기값), tar)\n" -#: pg_basebackup.c:386 +#: pg_basebackup.c:399 +#, c-format +msgid "" +" -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr "" +" -i, --incremental=이전매니페이스\n" +" 증분 백업\n" + +#: pg_basebackup.c:401 #, c-format msgid "" " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" @@ -226,7 +554,7 @@ msgstr "" " (단위는 kB/s, 또는 숫자 뒤에 \"k\" 또는 \"M\" 단위 " "문자 지정 가능)\n" -#: pg_basebackup.c:388 +#: pg_basebackup.c:403 #, c-format msgid "" " -R, --write-recovery-conf\n" @@ -235,7 +563,16 @@ msgstr "" " -R, --write-recovery-conf\n" " 복제를 위한 환경 설정 함\n" -#: pg_basebackup.c:390 +#: pg_basebackup.c:405 +#, c-format +msgid "" +" -t, --target=TARGET[:DETAIL]\n" +" backup target (if other than client)\n" +msgstr "" +" -t, --target=TARGET[:DETAIL]\n" +" 백업 타겟 지정 (이곳 또는 다른 곳)\n" + +#: pg_basebackup.c:407 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -244,12 +581,12 @@ msgstr "" " -T, --tablespace-mapping=옛DIR=새DIR\n" " 테이블스페이스 디렉터리 새 맵핑\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr " --waldir=WALDIR 트랜잭션 로그 디렉터리 지정\n" -#: pg_basebackup.c:393 +#: pg_basebackup.c:410 #, c-format msgid "" " -X, --wal-method=none|fetch|stream\n" @@ -258,18 +595,26 @@ msgstr "" " -X, --wal-method=none|fetch|stream\n" " 필요한 WAL 파일을 백업하는 방법\n" -#: pg_basebackup.c:395 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip tar 출력물을 압축\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:413 #, c-format msgid "" -" -Z, --compress=0-9 compress tar output with given compression level\n" -msgstr " -Z, --compress=0-9 압축된 tar 파일의 압축 수위 지정\n" +" -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" +" compress on client or server as specified\n" +msgstr "" +" -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" +" 압축 관련 설정\n" -#: pg_basebackup.c:397 +#: pg_basebackup.c:415 +#, c-format +msgid " -Z, --compress=none do not compress tar output\n" +msgstr " -Z, --compress=none tar 출력에서 압축 안함\n" + +#: pg_basebackup.c:416 #, c-format msgid "" "\n" @@ -278,58 +623,58 @@ msgstr "" "\n" "일반 옵션들:\n" -#: pg_basebackup.c:398 +#: pg_basebackup.c:417 #, c-format msgid "" " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" +" set fast or spread (default) checkpointing\n" msgstr "" " -c, --checkpoint=fast|spread\n" -" 체크포인트 방법\n" +" 체크포인트 방법, fast 또는 spread (기본값)\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " -C, --create-slot 새 복제 슬롯을 만듬\n" -#: pg_basebackup.c:401 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=라벨 백업 라벨 지정\n" -#: pg_basebackup.c:402 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean 오류 발생 시 정리하지 않음\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:422 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " "disk\n" msgstr " -N, --no-sync 디스크 쓰기 뒤 sync 작업 생략\n" -#: pg_basebackup.c:404 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress 진행 과정 보여줌\n" -#: pg_basebackup.c:405 pg_receivewal.c:89 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=슬롯이름 지정한 복제 슬롯을 사용함\n" -#: pg_basebackup.c:406 pg_receivewal.c:91 pg_recvlogical.c:96 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose 자세한 작업 메시지 보여줌\n" -#: pg_basebackup.c:407 pg_receivewal.c:92 pg_recvlogical.c:97 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보 보여주고 마침\n" -#: pg_basebackup.c:408 +#: pg_basebackup.c:427 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -338,7 +683,7 @@ msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " 사용할 manifest 체크섬 알고리즘\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:429 #, c-format msgid "" " --manifest-force-encode\n" @@ -347,23 +692,23 @@ msgstr "" " --manifest-force-encode\n" " manifest 내 모든 파일 이름을 16진수 인코딩함\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" msgstr " --no-estimate-size 서버측 백업 크기를 예상하지 않음\n" -#: pg_basebackup.c:413 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest 백업 매니페스트 만들지 않음\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:433 #, c-format msgid "" " --no-slot prevent creation of temporary replication slot\n" msgstr " --no-slot 임시 복제 슬롯 만들지 않음\n" -#: pg_basebackup.c:415 +#: pg_basebackup.c:434 #, c-format msgid "" " --no-verify-checksums\n" @@ -372,12 +717,21 @@ msgstr "" " --no-verify-checksums\n" " 체크섬 검사 안함\n" -#: pg_basebackup.c:417 pg_receivewal.c:94 pg_recvlogical.c:98 +#: pg_basebackup.c:436 +#, c-format +msgid "" +" --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr "" +" --sync-method=METHOD\n" +" 파일을 디스크에 동기화 하는 방법 지정\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_basebackup.c:418 pg_receivewal.c:95 pg_recvlogical.c:99 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "" "\n" @@ -386,22 +740,22 @@ msgstr "" "\n" "연결 옵션들:\n" -#: pg_basebackup.c:419 pg_receivewal.c:96 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=접속문자열 서버 접속 문자열\n" -#: pg_basebackup.c:420 pg_receivewal.c:97 pg_recvlogical.c:101 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=호스트이름 접속할 데이터베이스 서버나 소켓 디렉터리\n" -#: pg_basebackup.c:421 pg_receivewal.c:98 pg_recvlogical.c:102 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=포트 데이터베이스 서버 포트 번호\n" -#: pg_basebackup.c:422 +#: pg_basebackup.c:443 #, c-format msgid "" " -s, --status-interval=INTERVAL\n" @@ -411,17 +765,17 @@ msgstr "" " -s, --status-interval=초\n" " 초 단위 매번 서버로 상태 패킷을 보냄\n" -#: pg_basebackup.c:424 pg_receivewal.c:99 pg_recvlogical.c:103 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=사용자 접속할 특정 데이터베이스 사용자\n" -#: pg_basebackup.c:425 pg_receivewal.c:100 pg_recvlogical.c:104 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password 비밀번호 물어 보지 않음\n" -#: pg_basebackup.c:426 pg_receivewal.c:101 pg_recvlogical.c:105 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid "" " -W, --password force password prompt (should happen " @@ -429,7 +783,8 @@ msgid "" msgstr "" " -W, --password 항상 비밀번호 프롬프트 보임 (자동으로 판단 함)\n" -#: pg_basebackup.c:427 pg_receivewal.c:105 pg_recvlogical.c:106 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "" "\n" @@ -438,464 +793,1218 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_basebackup.c:428 pg_receivewal.c:106 pg_recvlogical.c:107 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_basebackup.c:471 +#: pg_basebackup.c:488 +#, c-format +msgid "could not read from ready pipe: %m" +msgstr "준비된 파이프로부터 읽기 실패: %m" + +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:521 +#, c-format +msgid "could not parse write-ahead log location \"%s\"" +msgstr "트랜잭션 로그 위치 \"%s\" 분석 실패" + +#: pg_basebackup.c:596 pg_receivewal.c:600 +#, c-format +msgid "could not finish writing WAL files: %m" +msgstr "WAL 파일 쓰기 마무리 실패: %m" + +#: pg_basebackup.c:642 +#, c-format +msgid "could not create pipe for background process: %m" +msgstr "백그라운드 프로세스를 위한 파이프 만들기 실패: %m" + +#: pg_basebackup.c:676 +#, c-format +msgid "created temporary replication slot \"%s\"" +msgstr "\"%s\" 임시 복제 슬롯을 만듦" + +#: pg_basebackup.c:679 +#, c-format +msgid "created replication slot \"%s\"" +msgstr "\"%s\" 이름의 복제 슬롯을 만듦" + +#: pg_basebackup.c:728 +#, c-format +msgid "could not create background process: %m" +msgstr "백그라운드 프로세스 만들기 실패: %m" + +#: pg_basebackup.c:737 +#, c-format +msgid "could not create background thread: %m" +msgstr "백그라운드 스래드 만들기 실패: %m" + +#: pg_basebackup.c:776 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "\"%s\" 디렉터리가 있지만 비어 있지 않음" + +#: pg_basebackup.c:782 pg_createsubscriber.c:390 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" + +#: pg_basebackup.c:858 +#, c-format +msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" +msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" +msgstr[0] "%*s/%s kB (100%%), %d/%d 테이블스페이스 %*s" + +#: pg_basebackup.c:870 +#, c-format +msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" +msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" +msgstr[0] "%*s/%s kB (%d%%), %d/%d 테이블스페이스 (%s%-*.*s)" + +#: pg_basebackup.c:886 +#, c-format +msgid "%*s/%s kB (%d%%), %d/%d tablespace" +msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" +msgstr[0] "%*s/%s kB (%d%%), %d/%d 테이블스페이스" + +#: pg_basebackup.c:910 +#, c-format +msgid "transfer rate \"%s\" is not a valid value" +msgstr "\"%s\" 전송 속도는 잘못된 값임" + +#: pg_basebackup.c:912 +#, c-format +msgid "invalid transfer rate \"%s\": %m" +msgstr "잘못된 전송 속도 \"%s\": %m" + +#: pg_basebackup.c:919 +#, c-format +msgid "transfer rate must be greater than zero" +msgstr "전송 속도는 0보다 커야 함" + +#: pg_basebackup.c:949 +#, c-format +msgid "invalid --max-rate unit: \"%s\"" +msgstr "잘못된 --max-rate 단위: \"%s\"" + +#: pg_basebackup.c:953 +#, c-format +msgid "transfer rate \"%s\" exceeds integer range" +msgstr "\"%s\" 전송 속도는 정수형 범위가 아님" + +#: pg_basebackup.c:960 +#, c-format +msgid "transfer rate \"%s\" is out of range" +msgstr "\"%s\" 전송 속도는 범위 초과" + +#: pg_basebackup.c:1022 +#, c-format +msgid "could not get COPY data stream: %s" +msgstr "COPY 데이터 스트림을 사용할 수 없음: %s" + +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 +#: receivelog.c:973 +#, c-format +msgid "could not read COPY data: %s" +msgstr "COPY 자료를 읽을 수 없음: %s" + +#: pg_basebackup.c:1043 +#, c-format +msgid "background process terminated unexpectedly" +msgstr "백그라운드 프로세스가 예상치 않게 종료됨" + +#: pg_basebackup.c:1114 +#, c-format +msgid "cannot inject manifest into a compressed tar file" +msgstr "압축된 tar 파일에는 manifest를 넣을 수 없습니다." + +#: pg_basebackup.c:1115 +#, c-format +msgid "" +"Use client-side compression, send the output to a directory rather than " +"standard output, or use %s." +msgstr "" +"결과물을 표준 출력으로 보내지 말고, 디렉터리로 보낸 뒤 클라이언트 측에서 압" +"축 하거나, %s 옵션을 사용하세요." + +#: pg_basebackup.c:1131 +#, c-format +msgid "cannot parse archive \"%s\"" +msgstr "\"%s\" 아카이브를 구문분석할 수 없음" + +#: pg_basebackup.c:1132 +#, c-format +msgid "Only tar archives can be parsed." +msgstr "tar 형식만 구문분석할 수 있음" + +#: pg_basebackup.c:1134 +#, c-format +msgid "Plain format requires pg_basebackup to parse the archive." +msgstr "아카이브를 분석하기 위해서는 일반 양식이어야 합니다." + +#: pg_basebackup.c:1136 +#, c-format +msgid "" +"Using - as the output directory requires pg_basebackup to parse the archive." +msgstr "아카이브를 분석하기 위해 출력 디렉터리 이름으로 - 문자를 사용하세요." + +#: pg_basebackup.c:1138 +#, c-format +msgid "The -R option requires pg_basebackup to parse the archive." +msgstr "아카이브를 분석하기 위해 -R 옵션을 사용하세요." + +#: pg_basebackup.c:1357 +#, c-format +msgid "archives must precede manifest" +msgstr "아카이브 작업은 매니페스트보다 앞서야합니다" + +#: pg_basebackup.c:1372 +#, c-format +msgid "invalid archive name: \"%s\"" +msgstr "잘못된 아카이브 이름: \"%s\"" + +#: pg_basebackup.c:1444 +#, c-format +msgid "unexpected payload data" +msgstr "비정상 payload 자료" + +#: pg_basebackup.c:1587 +#, c-format +msgid "empty COPY message" +msgstr "빈 COPY 메시지" + +#: pg_basebackup.c:1589 +#, c-format +msgid "malformed COPY message of type %d, length %zu" +msgstr "타입 %d의 잘못된 COPY 메시지, 길이: %zu" + +#: pg_basebackup.c:1789 +#, c-format +msgid "incompatible server version %s" +msgstr "호환하지 않는 서버 버전 %s" + +#: pg_basebackup.c:1805 +#, c-format +msgid "Use -X none or -X fetch to disable log streaming." +msgstr "" +"트랜잭션 로그 스트리밍을 사용하지 않으려면 -X none 또는 -X fetch 옵션을 사용" +"하세요." + +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "서버가 증분 백업을 지원하지 않음" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:367 streamutil.c:441 +#: streamutil.c:493 streamutil.c:581 streamutil.c:733 streamutil.c:778 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "\"%s\" 복제 명령을 보낼 수 없음: %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "매니페이스 파일을 업로드 할 수 없음: %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#, c-format +msgid "could not upload manifest: unexpected status %s" +msgstr "매니페이스 파일을 업로드 할 수 없음: 예상치 않은 상태 %s" + +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "COPY 자료를 보낼 수 없음: %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "COPY 종료 정보를 보낼 수 없음: %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "매니페이스를 보내는 중 예상치 못한 부가 결과 발견" + +#: pg_basebackup.c:1950 +#, c-format +msgid "backup targets are not supported by this server version" +msgstr "이 서버는 백업 타켓을 지원하지 않음." + +#: pg_basebackup.c:1953 +#, c-format +msgid "recovery configuration cannot be written when a backup target is used" +msgstr "백업 타겟을 사용할 때는 원 환경 설정을 기록할 수 없습니다." + +#: pg_basebackup.c:1980 +#, c-format +msgid "server does not support server-side compression" +msgstr "이 서버는 서버 측 압축을 지원하지 않습니다" + +#: pg_basebackup.c:1990 +#, c-format +msgid "initiating base backup, waiting for checkpoint to complete" +msgstr "베이스 백업을 초기화 중, 체크포인트 완료를 기다리는 중" + +#: pg_basebackup.c:1994 +#, c-format +msgid "waiting for checkpoint" +msgstr "체크포인트가 끝나길 기다리는 중" + +#: pg_basebackup.c:2016 +#, c-format +msgid "could not initiate base backup: %s" +msgstr "베이스 백업을 초기화 할 수 없음: %s" + +#: pg_basebackup.c:2019 +#, c-format +msgid "" +"server returned unexpected response to BASE_BACKUP command; got %d rows and " +"%d fields, expected %d rows and %d fields" +msgstr "" +"서버가 BASE_BACKUP 명령에 대해서 잘못된 응답을 했습니다; 응답값: %d 로우, %d " +"필드, (기대값: %d 로우, %d 필드)" + +#: pg_basebackup.c:2025 +#, c-format +msgid "checkpoint completed" +msgstr "체크포인트 완료" + +#: pg_basebackup.c:2039 +#, c-format +msgid "write-ahead log start point: %s on timeline %u" +msgstr "트랙잭션 로그 시작 위치: %s, 타임라인: %u" + +#: pg_basebackup.c:2047 +#, c-format +msgid "could not get backup header: %s" +msgstr "백업 헤더를 구할 수 없음: %s" + +#: pg_basebackup.c:2050 +#, c-format +msgid "no data returned from server" +msgstr "서버가 아무런 자료도 주지 않았음" + +#: pg_basebackup.c:2093 +#, c-format +msgid "can only write single tablespace to stdout, database has %d" +msgstr "" +"표준 출력으로는 하나의 테이블스페이스만 쓸 수 있음, 데이터베이스는 %d 개의 테" +"이블 스페이스가 있음" + +#: pg_basebackup.c:2106 +#, c-format +msgid "starting background WAL receiver" +msgstr "백그라운드 WAL 수신자 시작 중" + +#: pg_basebackup.c:2189 +#, c-format +msgid "backup failed: %s" +msgstr "백업 실패: %s" + +#: pg_basebackup.c:2192 +#, c-format +msgid "no write-ahead log end position returned from server" +msgstr "서버에서 트랜잭션 로그 마지막 위치가 수신 되지 않았음" + +#: pg_basebackup.c:2195 +#, c-format +msgid "write-ahead log end point: %s" +msgstr "트랜잭션 로그 마지막 위치: %s" + +#: pg_basebackup.c:2206 +#, c-format +msgid "checksum error occurred" +msgstr "체크섬 오류 발생" + +#: pg_basebackup.c:2211 +#, c-format +msgid "final receive failed: %s" +msgstr "수신 작업 마무리 실패: %s" + +#: pg_basebackup.c:2235 +#, c-format +msgid "waiting for background process to finish streaming ..." +msgstr "스트리밍을 끝내기 위해서 백그라운드 프로세스를 기다리는 중 ..." + +#: pg_basebackup.c:2239 +#, c-format +msgid "could not send command to background pipe: %m" +msgstr "백그라운드 파이프로 명령을 보낼 수 없음: %m" + +#: pg_basebackup.c:2244 +#, c-format +msgid "could not wait for child process: %m" +msgstr "하위 프로세스를 기다릴 수 없음: %m" + +#: pg_basebackup.c:2246 +#, c-format +msgid "child %d died, expected %d" +msgstr "%d 개의 하위 프로세스가 종료됨, 기대값 %d" + +#: pg_basebackup.c:2248 streamutil.c:92 streamutil.c:207 streamutil.c:319 +#, c-format +msgid "%s" +msgstr "%s" + +#: pg_basebackup.c:2268 +#, c-format +msgid "could not wait for child thread: %m" +msgstr "하위 스레드를 기다릴 수 없음: %m" + +#: pg_basebackup.c:2273 +#, c-format +msgid "could not get child thread exit status: %m" +msgstr "하위 스레드 종료 상태가 정상적이지 않음: %m" + +#: pg_basebackup.c:2276 +#, c-format +msgid "child thread exited with error %u" +msgstr "하위 스레드가 비정상 종료됨: 오류 코드 %u" + +#: pg_basebackup.c:2305 +#, c-format +msgid "syncing data to disk ..." +msgstr "자료를 디스크에 동기화 하는 중 ... " + +#: pg_basebackup.c:2330 +#, c-format +msgid "renaming backup_manifest.tmp to backup_manifest" +msgstr "backup_manifest.tmp 파일을 backup_manifest로 바꾸는 중" + +#: pg_basebackup.c:2350 +#, c-format +msgid "base backup completed" +msgstr "베이스 백업 완료" + +#: pg_basebackup.c:2436 +#, c-format +msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" +msgstr "잘못된 체크포인트 옵션값 \"%s\", \"fast\" 또는 \"spread\"만 사용 가능" + +#: pg_basebackup.c:2454 +#, c-format +msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" +msgstr "\"%s\" 값은 잘못된 출력 형식, \"plain\" 또는 \"tar\" 만 사용 가능" + +#: pg_basebackup.c:2535 +#, c-format +msgid "" +"invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" +msgstr "" +"\"%s\" 값은 잘못된 wal-method 옵션값, \"fetch\", \"stream\" 또는 \"none\"만 " +"사용 가능" + +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2037 pg_createsubscriber.c:2047 +#: pg_createsubscriber.c:2055 pg_createsubscriber.c:2083 +#: pg_createsubscriber.c:2115 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." + +#: pg_basebackup.c:2584 pg_createsubscriber.c:2045 pg_receivewal.c:758 +#: pg_recvlogical.c:863 +#, c-format +msgid "too many command-line arguments (first is \"%s\")" +msgstr "너무 많은 명령행 인자를 지정했습니다. (처음 \"%s\")" + +#: pg_basebackup.c:2607 +#, c-format +msgid "cannot specify both format and backup target" +msgstr "백업 양식과 백업 타겟을 함께 사용할 수 없음" + +#: pg_basebackup.c:2619 +#, c-format +msgid "must specify output directory or backup target" +msgstr "출력 디렉터리를 지정하거나, 백업 타겟을 지정하세요." + +#: pg_basebackup.c:2625 +#, c-format +msgid "cannot specify both output directory and backup target" +msgstr "출력 디렉터리와 백업 타겟은 함께 지정할 수 없음" + +#: pg_basebackup.c:2655 pg_receivewal.c:802 +#, c-format +msgid "unrecognized compression algorithm: \"%s\"" +msgstr "알 수 없는 압축 알고리즘: \"%s\"" + +#: pg_basebackup.c:2661 pg_receivewal.c:809 +#, c-format +msgid "invalid compression specification: %s" +msgstr "잘못된 압축 정보: %s" + +#: pg_basebackup.c:2677 +#, c-format +msgid "" +"client-side compression is not possible when a backup target is specified" +msgstr "백업 타켓을 사용할 때는 클라이언트 측 압축을 사용할 수 없습니다." + +#: pg_basebackup.c:2688 +#, c-format +msgid "only tar mode backups can be compressed" +msgstr "tar 형식만 압축을 사용할 수 있음" + +#: pg_basebackup.c:2698 +#, c-format +msgid "WAL cannot be streamed when a backup target is specified" +msgstr "백업 타겟을 지정할 때는 WAL 스트리밍을 사용할 수 없습니다." + +#: pg_basebackup.c:2704 +#, c-format +msgid "cannot stream write-ahead logs in tar mode to stdout" +msgstr "tar 방식에서 stdout으로 트랜잭션 로그 스트리밍 불가" + +#: pg_basebackup.c:2711 +#, c-format +msgid "replication slots can only be used with WAL streaming" +msgstr "복제 슬롯은 WAL 스트리밍 방식에서만 사용할 수 있음" + +#: pg_basebackup.c:2723 +#, c-format +msgid "--no-slot cannot be used with slot name" +msgstr "슬롯 이름을 지정한 경우 --no-slot 옵션을 사용할 수 없음" + +#. translator: second %s is an option name +#: pg_basebackup.c:2734 pg_receivewal.c:774 +#, c-format +msgid "%s needs a slot to be specified using --slot" +msgstr "%s 옵션은 --slot 옵션을 함께 사용해야 함" + +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 +#, c-format +msgid "%s and %s are incompatible options" +msgstr "%s 옵션과 %s 옵션은 함께 사용할 수 없음" + +#: pg_basebackup.c:2756 +#, c-format +msgid "WAL directory location cannot be specified along with a backup target" +msgstr "트랜잭션 로그 디렉터리 위치는 백업 타켓과 함께 지정할 수 없음" + +#: pg_basebackup.c:2762 +#, c-format +msgid "WAL directory location can only be specified in plain mode" +msgstr "트랜잭션 로그 디렉터리 위치는 plain 모드에서만 사용할 수 있음" + +#: pg_basebackup.c:2771 +#, c-format +msgid "WAL directory location must be an absolute path" +msgstr "트랜잭션 로그 디렉터리 위치는 절대 경로여야 함" + +#: pg_basebackup.c:2871 +#, c-format +msgid "could not create symbolic link \"%s\": %m" +msgstr "\"%s\" 심벌릭 링크를 만들 수 없음: %m" + +#: pg_createsubscriber.c:169 +#, c-format +msgid "failed after the end of recovery" +msgstr "복구 뒤 실패" + +#: pg_createsubscriber.c:170 +#, c-format +msgid "" +"The target server cannot be used as a physical replica anymore. You must " +"recreate the physical replica before continuing." +msgstr "" +"대상 서버는 더 이상 물리 복제 대기 서버로 사용할 수 없습니다. 물리 복제 대기 " +"서버가 필요하다면, 다시 만들어야 합니다." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "" +"publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "다음 발행이 남아 있음: 발행 이름=\"%s\", 대상 데이터베이스=\"%s\"" + +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "재시도 전에 이 발행을 삭제하세요." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "" +"replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "" +"다음 복제 슬롯이 남아 있음: 복제 슬롯 이름=\"%s\", 대상 데이터베이스=\"%s\"" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1260 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "WAL 파일이 늘어나는 것을 막기위해 해당 복제 슬롯을 삭제하세요." + +#: pg_createsubscriber.c:219 +#, c-format +msgid "" +"%s creates a new logical replica from a standby server.\n" +"\n" +msgstr "" +"%s 프로그램은 물리 복제 대기 서버를 새로운 논리 복제 서버로 만듭니다.\n" +"\n" + +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"옵션들:\n" + +#: pg_createsubscriber.c:224 +#, c-format +msgid "" +" -d, --database=DBNAME database in which to create a " +"subscription\n" +msgstr " -d, --database=DBNAME 구독을 만들 데이터베이스 지정\n" + +#: pg_createsubscriber.c:225 +#, c-format +msgid "" +" -D, --pgdata=DATADIR location for the subscriber data " +"directory\n" +msgstr " -D, --pgdata=DATADIR 구독용 인스턴스 데이터 디렉터리\n" + +#: pg_createsubscriber.c:226 +#, c-format +msgid "" +" -n, --dry-run dry run, just show what would be done\n" +msgstr "" +" -n, --dry-run 실작업은 안하고, 뭘 할 것인지만 보여줌\n" + +#: pg_createsubscriber.c:227 +#, c-format +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr "" +" -p, --subscriber-port=PORT 구독용 인스턴스 포트 번호 (초기값 %s)\n" + +#: pg_createsubscriber.c:228 +#, c-format +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CONNSTR 구독용 인스턴스 연결 문자열\n" + +#: pg_createsubscriber.c:229 +#, c-format +msgid "" +" -s, --socketdir=DIR socket directory to use (default current " +"dir.)\n" +msgstr "" +" -s, --socketdir=DIR 사용할 소켓 디렉터리 (초기값 current " +"dir.)\n" + +#: pg_createsubscriber.c:230 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=SECS 복구가 끝날 때까지 기다리는 초\n" + +#: pg_createsubscriber.c:231 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NAME 구독용 인스턴스 연결을 위한 사용자\n" + +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose 자세한 작업 메시지 보여줌\n" + +#: pg_createsubscriber.c:233 +#, c-format +msgid "" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" +msgstr "" +" --config-file=FILENAME 대상 클러스터가 실행될 때 사용할\n" +" 주 서버용 환경 설정 파일\n" + +#: pg_createsubscriber.c:235 +#, c-format +msgid " --publication=NAME publication name\n" +msgstr " --publication=NAME 발행 이름\n" + +#: pg_createsubscriber.c:236 +#, c-format +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=NAME 복제 슬롯 이름\n" + +#: pg_createsubscriber.c:237 +#, c-format +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NAME 구독 이름\n" + +#: pg_createsubscriber.c:238 +#, c-format +msgid "" +" -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보 보여주고 마침\n" + +#: pg_createsubscriber.c:239 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" + +#: pg_createsubscriber.c:282 +#, c-format +msgid "could not parse connection string: %s" +msgstr "연결 문자열 구문이 잘못됨: %s" + +#: pg_createsubscriber.c:359 +#, c-format +msgid "" +"program \"%s\" is needed by %s but was not found in the same directory as " +"\"%s\"" +msgstr "\"%s\" 프로그램이 %s에서 필요하지만, \"%s\" 디렉터리 안에 없음" + +#: pg_createsubscriber.c:362 +#, c-format +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "\"%s\" 프로그램이 \"%s\" 프로그램에서 사용하는 %s 버전과 같지 않음" + +#: pg_createsubscriber.c:382 +#, c-format +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "\"%s\" 디렉터리가 클러스터 데이터 디렉터리인지 확인해보세요." + +#: pg_createsubscriber.c:388 +#, c-format +msgid "data directory \"%s\" does not exist" +msgstr "\"%s\" 데이터 디렉터리가 없음" + +#: pg_createsubscriber.c:396 +#, c-format +msgid "directory \"%s\" is not a database cluster directory" +msgstr "\"%s\" 디렉터리는 데이베이스 클러스터 디렉터리가 아님" + +#: pg_createsubscriber.c:513 +#, c-format +msgid "connection to database failed: %s" +msgstr "데이터베이스 연결 실패: %s" + +#: pg_createsubscriber.c:526 +#, c-format +msgid "could not clear search_path: %s" +msgstr "search_path를 지울 수 없음: %s" + +#: pg_createsubscriber.c:566 +#, c-format +msgid "getting system identifier from publisher" +msgstr "발행에서 system identifier 가져오는 중" + +#: pg_createsubscriber.c:573 +#, c-format +msgid "could not get system identifier: %s" +msgstr "system identifier 가져오기 실패: %s" + +#: pg_createsubscriber.c:579 +#, c-format +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "system identifier 가져오기 실패: 취득=%d개 로우, 예상=%d개 로우" + +#: pg_createsubscriber.c:586 +#, c-format +msgid "system identifier is %llu on publisher" +msgstr "발행 서버의 system identifier: %llu" + +#: pg_createsubscriber.c:607 +#, c-format +msgid "getting system identifier from subscriber" +msgstr "구독에서 system identifier 가져오는 중" + +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 +#, c-format +msgid "control file appears to be corrupt" +msgstr "컨트롤 파일 깨짐" + +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 +#, c-format +msgid "system identifier is %llu on subscriber" +msgstr "구독 서버의 system identifier: %llu" + +#: pg_createsubscriber.c:637 +#, c-format +msgid "modifying system identifier of subscriber" +msgstr "구독 서버의 system identifier 바꾸는 중" + +#: pg_createsubscriber.c:659 +#, c-format +msgid "running pg_resetwal on the subscriber" +msgstr "구독 서버에서 pg_resetwal 실행 중" + +#: pg_createsubscriber.c:671 +#, c-format +msgid "subscriber successfully changed the system identifier" +msgstr "구독 서버의 system identifier 바꾸기 끝" + +#: pg_createsubscriber.c:673 +#, c-format +msgid "could not change system identifier of subscriber: %s" +msgstr "구독 서버의 system identifier 바꾸기 실패: %s" + +#: pg_createsubscriber.c:697 +#, c-format +msgid "could not obtain database OID: %s" +msgstr "베이스베이스 OID 확인 불가: %s" + +#: pg_createsubscriber.c:704 #, c-format -msgid "could not read from ready pipe: %m" -msgstr "준비된 파이프로부터 읽기 실패: %m" +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "베이스베이스 OID 확인 불가: %d개 로우 발견, %d개 로우 예상" -#: pg_basebackup.c:477 pg_basebackup.c:608 pg_basebackup.c:2133 -#: streamutil.c:450 +#: pg_createsubscriber.c:776 #, c-format -msgid "could not parse write-ahead log location \"%s\"" -msgstr "트랜잭션 로그 위치 \"%s\" 분석 실패" +msgid "create replication slot \"%s\" on publisher" +msgstr "발행 서버에서 \"%s\" 이름의 복제 슬롯을 만듦" -#: pg_basebackup.c:573 pg_receivewal.c:441 +#: pg_createsubscriber.c:796 #, c-format -msgid "could not finish writing WAL files: %m" -msgstr "WAL 파일 쓰기 마무리 실패: %m" +msgid "could not write an additional WAL record: %s" +msgstr "추가 WAL 레코드를 쓸 수 없음: %s" -#: pg_basebackup.c:620 +#: pg_createsubscriber.c:822 #, c-format -msgid "could not create pipe for background process: %m" -msgstr "백그라운드 프로세스를 위한 파이프 만들기 실패: %m" +msgid "could not obtain recovery progress: %s" +msgstr "복구 작업 과정 확인 불가: %s" -#: pg_basebackup.c:655 +#: pg_createsubscriber.c:854 #, c-format -msgid "created temporary replication slot \"%s\"" -msgstr "\"%s\" 임시 복제 슬롯을 만들 수 없음" +msgid "checking settings on publisher" +msgstr "발행 서버 설정 검사 중" -#: pg_basebackup.c:658 +#: pg_createsubscriber.c:864 #, c-format -msgid "created replication slot \"%s\"" -msgstr "\"%s\" 이름의 복제 슬롯을 만듦" +msgid "primary server cannot be in recovery" +msgstr "주 서버는 복구 작업을 할 수 없음" -#: pg_basebackup.c:678 pg_basebackup.c:731 pg_basebackup.c:1620 +#: pg_createsubscriber.c:888 #, c-format -msgid "could not create directory \"%s\": %m" -msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" +msgid "could not obtain publisher settings: %s" +msgstr "발행 서버 설정 확인 불가: %s" -#: pg_basebackup.c:696 +#: pg_createsubscriber.c:914 #, c-format -msgid "could not create background process: %m" -msgstr "백그라운드 프로세스 만들기 실패: %m" +msgid "publisher requires wal_level >= \"logical\"" +msgstr "발행 서버의 wal_level >= \"logical\" 설정 필요" -#: pg_basebackup.c:708 +#: pg_createsubscriber.c:920 #, c-format -msgid "could not create background thread: %m" -msgstr "백그라운드 스래드 만들기 실패: %m" +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "발행서버는 %d개의 복제 슬롯이 필요하지만, %d개만 남았음" -#: pg_basebackup.c:752 +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 #, c-format -msgid "directory \"%s\" exists but is not empty" -msgstr "\"%s\" 디렉터리가 있지만 비어 있지 않음" +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "\"%s\" 환경설정 매개변수 값을 %d 이상으로 늘려주세요." -#: pg_basebackup.c:759 +#: pg_createsubscriber.c:929 #, c-format -msgid "could not access directory \"%s\": %m" -msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "발행서버는 %d개의 WAL 발송 프로세스가 필요하지만, %d개만 남았음" -#: pg_basebackup.c:824 +#: pg_createsubscriber.c:938 #, c-format -msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" -msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" -msgstr[0] "%*s/%s kB (100%%), %d/%d 테이블스페이스 %*s" +msgid "two_phase option will not be enabled for replication slots" +msgstr "two_phase 옵션은 복제 슬롯을 위해 비활성화 될 예정" -#: pg_basebackup.c:836 +#: pg_createsubscriber.c:939 #, c-format -msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" -msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" -msgstr[0] "%*s/%s kB (%d%%), %d/%d 테이블스페이스 (%s%-*.*s)" +msgid "" +"Subscriptions will be created with the two_phase option disabled. Prepared " +"transactions will be replicated at COMMIT PREPARED." +msgstr "" +"구독은 two_phase 옵션이 비활성 되어 만들어집니다. 미리 준비된 트랜잭션은 " +"COMMIT PREPARED 때 복제될 것입니다." -#: pg_basebackup.c:852 +#: pg_createsubscriber.c:971 #, c-format -msgid "%*s/%s kB (%d%%), %d/%d tablespace" -msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" -msgstr[0] "%*s/%s kB (%d%%), %d/%d 테이블스페이스" +msgid "checking settings on subscriber" +msgstr "구독 서버 설정 검사 중" -#: pg_basebackup.c:877 +#: pg_createsubscriber.c:978 #, c-format -msgid "transfer rate \"%s\" is not a valid value" -msgstr "\"%s\" 전송 속도는 잘못된 값임" +msgid "target server must be a standby" +msgstr "대상 서버는 대기 서버여야 함" -#: pg_basebackup.c:882 +#: pg_createsubscriber.c:1002 #, c-format -msgid "invalid transfer rate \"%s\": %m" -msgstr "잘못된 전송 속도 \"%s\": %m" +msgid "could not obtain subscriber settings: %s" +msgstr "구독 서버 설정 확인 불가: %s" -#: pg_basebackup.c:891 +#: pg_createsubscriber.c:1026 #, c-format -msgid "transfer rate must be greater than zero" -msgstr "전송 속도는 0보다 커야 함" +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "구독 서버는 %d개의 복제 슬롯이 필요하지만, %d개만 남았음" -#: pg_basebackup.c:923 +#: pg_createsubscriber.c:1035 #, c-format -msgid "invalid --max-rate unit: \"%s\"" -msgstr "잘못된 --max-rate 단위: \"%s\"" +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "구독 서버는 %d개의 논리 복제 작업자가 필요하지만, %d개만 남았음" -#: pg_basebackup.c:930 +#: pg_createsubscriber.c:1044 #, c-format -msgid "transfer rate \"%s\" exceeds integer range" -msgstr "\"%s\" 전송 속도는 정수형 범위가 아님" +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "구독 서버는 %d개의 작업자가 필요하지만, %d개만 남았음" -#: pg_basebackup.c:940 +#: pg_createsubscriber.c:1079 #, c-format -msgid "transfer rate \"%s\" is out of range" -msgstr "\"%s\" 전송 속도는 범위 초과" +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 구독을 \"%s\" 데이터베이스에서 삭제 중" -#: pg_basebackup.c:961 +#: pg_createsubscriber.c:1088 #, c-format -msgid "could not get COPY data stream: %s" -msgstr "COPY 데이터 스트림을 사용할 수 없음: %s" +msgid "could not drop subscription \"%s\": %s" +msgstr "\"%s\" 구독 삭제 실패: %s" -#: pg_basebackup.c:981 pg_recvlogical.c:435 pg_recvlogical.c:607 -#: receivelog.c:965 +#: pg_createsubscriber.c:1123 #, c-format -msgid "could not read COPY data: %s" -msgstr "COPY 자료를 읽을 수 없음: %s" +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "이미 있는 구독 정보를 알 수 없음: %s" -#: pg_basebackup.c:1007 +#: pg_createsubscriber.c:1258 #, c-format -msgid "could not write to compressed file \"%s\": %s" -msgstr "\"%s\" 압축 파일 쓰기 실패: %s" +msgid "could not drop replication slot \"%s\" on primary" +msgstr "주 서버의 \"%s\" 복제 슬롯을 삭제 수 없음" -#: pg_basebackup.c:1071 +#: pg_createsubscriber.c:1292 #, c-format -msgid "could not duplicate stdout: %m" -msgstr "stdout을 중복할 수 없음: %m" +msgid "could not obtain failover replication slot information: %s" +msgstr "failover 복제 슬롯 정보를 찾을 수 없음: %s" -#: pg_basebackup.c:1078 +#: pg_createsubscriber.c:1294 pg_createsubscriber.c:1303 #, c-format -msgid "could not open output file: %m" -msgstr "출력파일을 열 수 없음: %m" +msgid "" +"Drop the failover replication slots on subscriber soon to avoid retention of " +"WAL files." +msgstr "" +"WAL 파일이 비정상적으로 증가는 문제를 막기 위해, 구독 서버에서 failover 복제 " +"슬롯을 바로 지우세요." -#: pg_basebackup.c:1085 pg_basebackup.c:1106 pg_basebackup.c:1135 +#: pg_createsubscriber.c:1302 #, c-format -msgid "could not set compression level %d: %s" -msgstr "잘못된 압축 수위 %d: %s" +msgid "could not drop failover replication slot" +msgstr "failover 복제 슬롯을 삭제할 수 없음" -#: pg_basebackup.c:1155 +#: pg_createsubscriber.c:1324 #, c-format -msgid "could not create compressed file \"%s\": %s" -msgstr "\"%s\" 압축 파일 만들기 실패: %s" +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 복제 슬롯을 \"%s\" 데이터베이스에 만드는 중" -#: pg_basebackup.c:1267 +#: pg_createsubscriber.c:1342 #, c-format -msgid "could not close compressed file \"%s\": %s" -msgstr "\"%s\" 압축 파일 닫기 실패: %s" +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "\"%s\" 이름의 복제 슬롯을 \"%s\" 데이터베이스에 만들기 실패: %s" -#: pg_basebackup.c:1279 pg_recvlogical.c:632 +#: pg_createsubscriber.c:1372 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "\"%s\" 파일을 닫을 수 없음: %m" +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 복제 슬롯을 \"%s\" 데이터베이스에서 삭제 중" -#: pg_basebackup.c:1541 +#: pg_createsubscriber.c:1388 #, c-format -msgid "COPY stream ended before last file was finished" -msgstr "마지막 파일을 끝내기 전에 COPY 스트림이 끝났음" +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "\"%s\" 이름의 복제 슬롯을 \"%s\" 데이터베이스에서 삭제 실패: %s" -#: pg_basebackup.c:1570 +#: pg_createsubscriber.c:1409 #, c-format -msgid "invalid tar block header size: %zu" -msgstr "잘못된 tar 블럭 헤더 크기: %zu" +msgid "pg_ctl failed with exit code %d" +msgstr "pg_ctl 작업 실패: 오류 코드 %d" -#: pg_basebackup.c:1627 +#: pg_createsubscriber.c:1414 #, c-format -msgid "could not set permissions on directory \"%s\": %m" -msgstr "\"%s\" 디렉터리 액세스 권한을 지정할 수 없음: %m" +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "pg_ctl 종료됨: 예외 처리 0x%X" -#: pg_basebackup.c:1651 +#: pg_createsubscriber.c:1416 #, c-format -msgid "could not create symbolic link from \"%s\" to \"%s\": %m" -msgstr "\"%s\" 파일을 \"%s\" 심볼릭 링크로 만들 수 없음: %m" +msgid "" +"See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "윗 16진수 값은 \"ntstatus.h\" 파일을 참조하세요." -#: pg_basebackup.c:1658 +#: pg_createsubscriber.c:1418 #, c-format -msgid "unrecognized link indicator \"%c\"" -msgstr "알 수 없는 링크 지시자 \"%c\"" +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "pg_ctl 종료됨: 수신 시그널=%d: %s" -#: pg_basebackup.c:1677 +#: pg_createsubscriber.c:1424 #, c-format -msgid "could not set permissions on file \"%s\": %m" -msgstr "파일 \"%s\" 의 접근권한을 지정할 수 없음: %m" +msgid "pg_ctl exited with unrecognized status %d" +msgstr "pg_ctl 종료됨: 알 수 없은 상태 %d" -#: pg_basebackup.c:1831 +#: pg_createsubscriber.c:1427 #, c-format -msgid "incompatible server version %s" -msgstr "호환하지 않는 서버 버전 %s" +msgid "The failed command was: %s" +msgstr "실패한 명령: %s" -#: pg_basebackup.c:1846 +#: pg_createsubscriber.c:1473 #, c-format -msgid "HINT: use -X none or -X fetch to disable log streaming" -msgstr "" -"힌트: 트랜잭션 로그 스트리밍을 사용하지 않으려면 -X none 또는 -X fetch 옵션" -"을 사용하세요." +msgid "server was started" +msgstr "서버 시작됨" -#: pg_basebackup.c:1882 +#: pg_createsubscriber.c:1488 #, c-format -msgid "initiating base backup, waiting for checkpoint to complete" -msgstr "베이스 백업을 초기화 중, 체크포인트 완료를 기다리는 중" +msgid "server was stopped" +msgstr "서버 멈춤" -#: pg_basebackup.c:1908 pg_recvlogical.c:262 receivelog.c:481 receivelog.c:530 -#: receivelog.c:569 streamutil.c:297 streamutil.c:370 streamutil.c:422 -#: streamutil.c:533 streamutil.c:578 +#: pg_createsubscriber.c:1507 #, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "\"%s\" 복제 명령을 보낼 수 없음: %s" +msgid "waiting for the target server to reach the consistent state" +msgstr "일관성 맞추기 위해 대상 서버 기다리는 중" -#: pg_basebackup.c:1919 +#: pg_createsubscriber.c:1530 #, c-format -msgid "could not initiate base backup: %s" -msgstr "베이스 백업을 초기화 할 수 없음: %s" +msgid "recovery timed out" +msgstr "복구 시간 초과" -#: pg_basebackup.c:1925 +#: pg_createsubscriber.c:1543 #, c-format -msgid "" -"server returned unexpected response to BASE_BACKUP command; got %d rows and " -"%d fields, expected %d rows and %d fields" -msgstr "" -"서버가 BASE_BACKUP 명령에 대해서 잘못된 응답을 했습니다; 응답값: %d 로우, %d " -"필드, (기대값: %d 로우, %d 필드)" +msgid "server did not end recovery" +msgstr "서버 복구 실패" -#: pg_basebackup.c:1933 +#: pg_createsubscriber.c:1545 #, c-format -msgid "checkpoint completed" -msgstr "체크포인트 완료" +msgid "target server reached the consistent state" +msgstr "대상 서버 일관성 맞추기 완료" -#: pg_basebackup.c:1948 +#: pg_createsubscriber.c:1546 #, c-format -msgid "write-ahead log start point: %s on timeline %u" -msgstr "트랙잭션 로그 시작 위치: %s, 타임라인: %u" +msgid "" +"If pg_createsubscriber fails after this point, you must recreate the " +"physical replica before continuing." +msgstr "" +"이 시점에서 pg_createsubscriber 작업을 실패하면, 물리 복제 대기 서버는 다시 " +"만들어야 합니다." -#: pg_basebackup.c:1957 +#: pg_createsubscriber.c:1573 #, c-format -msgid "could not get backup header: %s" -msgstr "백업 헤더를 구할 수 없음: %s" +msgid "could not obtain publication information: %s" +msgstr "발행 정보를 찾을 수 없음: %s" -#: pg_basebackup.c:1963 +#: pg_createsubscriber.c:1587 #, c-format -msgid "no data returned from server" -msgstr "서버가 아무런 자료도 주지 않았음" +msgid "publication \"%s\" already exists" +msgstr "\"%s\" 이름의 발행이 이미 있음" -#: pg_basebackup.c:1995 +#: pg_createsubscriber.c:1588 #, c-format -msgid "can only write single tablespace to stdout, database has %d" -msgstr "" -"표준 출력으로는 하나의 테이블스페이스만 쓸 수 있음, 데이터베이스는 %d 개의 테" -"이블 스페이스가 있음" +msgid "Consider renaming this publication before continuing." +msgstr "계속 진행을 위해서는 이 발행 이름을 바꿔보세요." -#: pg_basebackup.c:2007 +#: pg_createsubscriber.c:1595 #, c-format -msgid "starting background WAL receiver" -msgstr "백그라운드 WAL 수신자 시작 중" +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 발행을 \"%s\" 데이터베이스에 만드는 중" -#: pg_basebackup.c:2046 +#: pg_createsubscriber.c:1608 #, c-format -msgid "could not get write-ahead log end position from server: %s" -msgstr "서버에서 트랜잭션 로그 마지막 위치를 구할 수 없음: %s" +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "\"%s\" 이름의 발행을 \"%s\" 데이터베이스에 만들 수 없음: %s" -#: pg_basebackup.c:2052 +#: pg_createsubscriber.c:1637 #, c-format -msgid "no write-ahead log end position returned from server" -msgstr "서버에서 트랜잭션 로그 마지막 위치가 수신 되지 않았음" +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 발행을 \"%s\" 데이터베이스에서 삭제 중" -#: pg_basebackup.c:2057 +#: pg_createsubscriber.c:1651 #, c-format -msgid "write-ahead log end point: %s" -msgstr "트랜잭션 로그 마지막 위치: %s" +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "\"%s\" 이름의 발행을 \"%s\" 데이터베이스에 지울 수 없음: %s" -#: pg_basebackup.c:2068 +#: pg_createsubscriber.c:1697 #, c-format -msgid "checksum error occurred" -msgstr "체크섬 오류 발생" +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "\"%s\" 이름의 구독을 \"%s\" 데이터베이스에 만드는 중" -#: pg_basebackup.c:2073 +#: pg_createsubscriber.c:1718 #, c-format -msgid "final receive failed: %s" -msgstr "수신 작업 마무리 실패: %s" +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "\"%s\" 이름의 구독을 \"%s\" 데이터베이스에 만들 수 없음: %s" -#: pg_basebackup.c:2097 +#: pg_createsubscriber.c:1763 #, c-format -msgid "waiting for background process to finish streaming ..." -msgstr "스트리밍을 끝내기 위해서 백그라운드 프로세스를 기다리는 중 ..." +msgid "could not obtain subscription OID: %s" +msgstr "구독 OID 찾지 못함: %s" -#: pg_basebackup.c:2102 +#: pg_createsubscriber.c:1770 #, c-format -msgid "could not send command to background pipe: %m" -msgstr "백그라운드 파이프로 명령을 보낼 수 없음: %m" +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "구독 OID 확인 불가: %d개 로우 발견, %d개 로우 예상" -#: pg_basebackup.c:2110 +#: pg_createsubscriber.c:1794 #, c-format -msgid "could not wait for child process: %m" -msgstr "하위 프로세스를 기다릴 수 없음: %m" +msgid "" +"setting the replication progress (node name \"%s\", LSN %s) in database " +"\"%s\"" +msgstr "복제 설정 중(노드이름 \"%s\", LSN %s, 데이터베이스 \"%s\")" -#: pg_basebackup.c:2115 +#: pg_createsubscriber.c:1809 #, c-format -msgid "child %d died, expected %d" -msgstr "%d 개의 하위 프로세스가 종료됨, 기대값 %d" +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "\"%s\" 구독을 위한 복제 설정 실패: %s" -#: pg_basebackup.c:2120 streamutil.c:92 +#: pg_createsubscriber.c:1840 #, c-format -msgid "%s" -msgstr "%s" +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "\"%s\" 구독을 \"%s\" 데이터베이스에서 활성화 시도 중" -#: pg_basebackup.c:2145 +#: pg_createsubscriber.c:1852 #, c-format -msgid "could not wait for child thread: %m" -msgstr "하위 스레드를 기다릴 수 없음: %m" +msgid "could not enable subscription \"%s\": %s" +msgstr "\"%s\" 구독을 활성화 할 수 없음: %s" -#: pg_basebackup.c:2151 +#: pg_createsubscriber.c:1944 #, c-format -msgid "could not get child thread exit status: %m" -msgstr "하위 스레드 종료 상태가 정상적이지 않음: %m" +msgid "cannot be executed by \"root\"" +msgstr "\"root\" 권한으로 실행할 수 없음" -#: pg_basebackup.c:2156 +#: pg_createsubscriber.c:1945 #, c-format -msgid "child thread exited with error %u" -msgstr "하위 스레드가 비정상 종료됨: 오류 코드 %u" +msgid "You must run %s as the PostgreSQL superuser." +msgstr "PostgreSQL 슈퍼유저 계정으로 %s 프로그램을 실행하세요." -#: pg_basebackup.c:2184 +#: pg_createsubscriber.c:1966 #, c-format -msgid "syncing data to disk ..." -msgstr "자료를 디스크에 동기화 하는 중 ... " +msgid "database \"%s\" specified more than once" +msgstr "\"%s\" 데이터베이스가 중복 지정 되었음" -#: pg_basebackup.c:2209 +#: pg_createsubscriber.c:2007 #, c-format -msgid "renaming backup_manifest.tmp to backup_manifest" -msgstr "backup_manifest.tmp 파일을 backup_manifest로 바꾸는 중" +msgid "publication \"%s\" specified more than once" +msgstr "\"%s\" 발행이 중복 지정 되었음" -#: pg_basebackup.c:2220 +#: pg_createsubscriber.c:2019 #, c-format -msgid "base backup completed" -msgstr "베이스 백업 완료" +msgid "replication slot \"%s\" specified more than once" +msgstr "\"%s\" 복제 슬롯이 중복 지정 되었음" -#: pg_basebackup.c:2305 +#: pg_createsubscriber.c:2031 #, c-format -msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" -msgstr "\"%s\" 값은 잘못된 출력 형식, \"plain\" 또는 \"tar\" 만 사용 가능" +msgid "subscription \"%s\" specified more than once" +msgstr "\"%s\" 구독이 중복 지정 되었음" -#: pg_basebackup.c:2349 +#: pg_createsubscriber.c:2054 #, c-format -msgid "" -"invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" -msgstr "" -"\"%s\" 값은 잘못된 wal-method 옵션값, \"fetch\", \"stream\" 또는 \"none\"만 " -"사용 가능" +msgid "no subscriber data directory specified" +msgstr "구독 서버용 데이터 디렉터리를 지정하지 않았음" -#: pg_basebackup.c:2377 pg_receivewal.c:580 +#: pg_createsubscriber.c:2065 #, c-format -msgid "invalid compression level \"%s\"" -msgstr "잘못된 압축 수위 \"%s\"" +msgid "could not determine current directory" +msgstr "현재 디렉터리를 확인할 수 없음" -#: pg_basebackup.c:2388 +#: pg_createsubscriber.c:2082 #, c-format -msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" -msgstr "잘못된 체크포인트 옵션값 \"%s\", \"fast\" 또는 \"spread\"만 사용 가능" +msgid "no publisher connection string specified" +msgstr "발행 서버 연결 문자열을 지정하지 않았음" -#: pg_basebackup.c:2415 pg_receivewal.c:555 pg_recvlogical.c:820 +#: pg_createsubscriber.c:2086 #, c-format -msgid "invalid status interval \"%s\"" -msgstr "잘못된 상태값 간격: \"%s\"" +msgid "validating publisher connection string" +msgstr "발행 서버 연결 문자열 검사 중" -#: pg_basebackup.c:2445 pg_basebackup.c:2458 pg_basebackup.c:2469 -#: pg_basebackup.c:2480 pg_basebackup.c:2488 pg_basebackup.c:2496 -#: pg_basebackup.c:2506 pg_basebackup.c:2519 pg_basebackup.c:2527 -#: pg_basebackup.c:2538 pg_basebackup.c:2548 pg_basebackup.c:2565 -#: pg_basebackup.c:2573 pg_basebackup.c:2581 pg_receivewal.c:605 -#: pg_receivewal.c:618 pg_receivewal.c:626 pg_receivewal.c:636 -#: pg_receivewal.c:644 pg_receivewal.c:655 pg_recvlogical.c:846 -#: pg_recvlogical.c:859 pg_recvlogical.c:870 pg_recvlogical.c:878 -#: pg_recvlogical.c:886 pg_recvlogical.c:894 pg_recvlogical.c:902 -#: pg_recvlogical.c:910 pg_recvlogical.c:918 +#: pg_createsubscriber.c:2092 #, c-format -msgid "Try \"%s --help\" for more information.\n" -msgstr "자제한 사항은 \"%s --help\" 명령으로 살펴보십시오.\n" +msgid "validating subscriber connection string" +msgstr "구독 서버 연결 문자열 검사 중" -#: pg_basebackup.c:2456 pg_receivewal.c:616 pg_recvlogical.c:857 +#: pg_createsubscriber.c:2097 #, c-format -msgid "too many command-line arguments (first is \"%s\")" -msgstr "너무 많은 명령행 인자를 지정했습니다. (처음 \"%s\")" +msgid "no database was specified" +msgstr "데이터베이스를 지정하지 않았음" -#: pg_basebackup.c:2468 pg_receivewal.c:654 +#: pg_createsubscriber.c:2109 #, c-format -msgid "no target directory specified" -msgstr "대상 디렉터리를 지정하지 않음" +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "발행 서버 연결 문자열에서 데이터베이스 이름 확인: \"%s\"" -#: pg_basebackup.c:2479 +#: pg_createsubscriber.c:2114 #, c-format -msgid "only tar mode backups can be compressed" -msgstr "tar 형식만 압축을 사용할 수 있음" +msgid "no database name specified" +msgstr "데이터베이스 이름을 지정하지 않았음" -#: pg_basebackup.c:2487 +#: pg_createsubscriber.c:2124 #, c-format -msgid "cannot stream write-ahead logs in tar mode to stdout" -msgstr "tar 방식에서 stdout으로 트랜잭션 로그 스트리밍 불가" +msgid "wrong number of publication names specified" +msgstr "발행 이름들의 개수가 잘못됨" -#: pg_basebackup.c:2495 +#: pg_createsubscriber.c:2125 #, c-format -msgid "replication slots can only be used with WAL streaming" -msgstr "복제 슬롯은 WAL 스트리밍 방식에서만 사용할 수 있음" +msgid "" +"The number of specified publication names (%d) must match the number of " +"specified database names (%d)." +msgstr "지정한 발행 이름의 수(%d)와 데이터베이스 이름의 수(%d)가 같지 않음" -#: pg_basebackup.c:2505 +#: pg_createsubscriber.c:2131 #, c-format -msgid "--no-slot cannot be used with slot name" -msgstr "슬롯 이름을 지정한 경우 --no-slot 옵션을 사용할 수 없음" +msgid "wrong number of subscription names specified" +msgstr "구독 이름들의 개수가 잘못됨" -#. translator: second %s is an option name -#: pg_basebackup.c:2517 pg_receivewal.c:634 +#: pg_createsubscriber.c:2132 #, c-format -msgid "%s needs a slot to be specified using --slot" -msgstr "%s 옵션은 --slot 옵션을 함께 사용해야 함" +msgid "" +"The number of specified subscription names (%d) must match the number of " +"specified database names (%d)." +msgstr "지정한 구독 이름의 수(%d)와 데이터베이스 이름의 수(%d)가 같지 않음" -#: pg_basebackup.c:2526 +#: pg_createsubscriber.c:2138 #, c-format -msgid "--create-slot and --no-slot are incompatible options" -msgstr "--create-slot 옵션과 -no-slot 옵션은 함께 사용할 수 없음" +msgid "wrong number of replication slot names specified" +msgstr "복제 슬롯 이름들의 개수가 잘못됨" -#: pg_basebackup.c:2537 +#: pg_createsubscriber.c:2139 #, c-format -msgid "WAL directory location can only be specified in plain mode" -msgstr "트랜잭션 로그 디렉터리 위치는 plain 모드에서만 사용할 수 있음" +msgid "" +"The number of specified replication slot names (%d) must match the number of " +"specified database names (%d)." +msgstr "" +"지정한 복제 슬롯 이름의 수(%d)와 데이터베이스 이름의 수(%d)가 같지 않음" -#: pg_basebackup.c:2547 +#: pg_createsubscriber.c:2168 #, c-format -msgid "WAL directory location must be an absolute path" -msgstr "트랜잭션 로그 디렉터리 위치는 절대 경로여야 함" +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "구독 서버의 데이터 디렉터리는 원본 데이터베이스 클러스터의 것이 아님" -#: pg_basebackup.c:2557 pg_receivewal.c:663 +#: pg_createsubscriber.c:2181 #, c-format -msgid "this build does not support compression" -msgstr "이 버전은 압축 하는 기능을 포함 하지 않고 빌드 되었습니다." +msgid "standby server is running" +msgstr "대기 서버가 실행 중입니다." -#: pg_basebackup.c:2564 +#: pg_createsubscriber.c:2182 #, c-format -msgid "--progress and --no-estimate-size are incompatible options" -msgstr "--progress 옵션과 --no-estimate-size 옵션은 함께 사용할 수 없음" +msgid "Stop the standby server and try again." +msgstr "대기 서버를 중지 하고, 다시 하세요." -#: pg_basebackup.c:2572 +#: pg_createsubscriber.c:2191 #, c-format -msgid "--no-manifest and --manifest-checksums are incompatible options" -msgstr "--no-manifest 옵션과 --manifest-checksums 옵션은 함께 사용할 수 없음" +msgid "starting the standby server with command-line options" +msgstr "명령행 옵션을 포함해서 대기 서버를 시작 중" -#: pg_basebackup.c:2580 +#: pg_createsubscriber.c:2207 pg_createsubscriber.c:2242 #, c-format -msgid "--no-manifest and --manifest-force-encode are incompatible options" -msgstr "" -"--no-manifest 옵션과 --manifest-force-encode 옵션은 함께 사용할 수 없음" +msgid "stopping the subscriber" +msgstr "구독 서버 중지 중" -#: pg_basebackup.c:2639 +#: pg_createsubscriber.c:2221 #, c-format -msgid "could not create symbolic link \"%s\": %m" -msgstr "\"%s\" 심벌릭 링크를 만들 수 없음: %m" +msgid "starting the subscriber" +msgstr "구독 서버 실행 중" -#: pg_basebackup.c:2643 +#: pg_createsubscriber.c:2250 #, c-format -msgid "symlinks are not supported on this platform" -msgstr "이 플랫폼에서는 심볼 링크가 지원되지 않음" +msgid "Done!" +msgstr "완료!" #: pg_receivewal.c:77 #, c-format @@ -906,15 +2015,6 @@ msgstr "" "%s 프로그램은 PostgreSQL 스트리밍 트랜잭션 로그를 수신하는 도구입니다.\n" "\n" -#: pg_receivewal.c:81 pg_recvlogical.c:81 -#, c-format -msgid "" -"\n" -"Options:\n" -msgstr "" -"\n" -"옵션들:\n" - #: pg_receivewal.c:82 #, c-format msgid "" @@ -922,12 +2022,12 @@ msgid "" msgstr "" " -D, --directory=DIR 지정한 디렉터리로 트랜잭션 로그 파일을 백업함\n" -#: pg_receivewal.c:83 pg_recvlogical.c:82 +#: pg_receivewal.c:83 pg_recvlogical.c:93 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN 지정한 LSN까지 받고 종료함\n" -#: pg_receivewal.c:84 pg_recvlogical.c:86 +#: pg_receivewal.c:84 pg_recvlogical.c:97 #, c-format msgid "" " --if-not-exists do not error if slot already exists when creating a " @@ -935,7 +2035,7 @@ msgid "" msgstr "" " --if-not-exists 슬롯을 새로 만들 때 이미 있어도 오류 내지 않음\n" -#: pg_receivewal.c:85 pg_recvlogical.c:88 +#: pg_receivewal.c:85 pg_recvlogical.c:99 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop 접속이 끊겼을 때 재연결 하지 않음\n" @@ -947,7 +2047,7 @@ msgid "" "disk\n" msgstr " --no-sync 디스크 쓰기 뒤 sync 작업 생략\n" -#: pg_receivewal.c:87 pg_recvlogical.c:93 +#: pg_receivewal.c:87 pg_recvlogical.c:104 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -966,10 +2066,14 @@ msgstr " --synchronous 쓰기 작업 후 즉시 트랜잭션 로그를 #: pg_receivewal.c:93 #, c-format -msgid " -Z, --compress=0-9 compress logs with given compression level\n" -msgstr " -Z, --compress=0-9 압축된 로그 파일의 압축 수위 지정\n" +msgid "" +" -Z, --compress=METHOD[:DETAIL]\n" +" compress as specified\n" +msgstr "" +" -Z, --compress=METHOD[:DETAIL]\n" +" 압축 관련 속성 지정\n" -#: pg_receivewal.c:102 +#: pg_receivewal.c:103 #, c-format msgid "" "\n" @@ -978,7 +2082,7 @@ msgstr "" "\n" "추가 기능:\n" -#: pg_receivewal.c:103 pg_recvlogical.c:78 +#: pg_receivewal.c:104 pg_recvlogical.c:89 #, c-format msgid "" " --create-slot create a new replication slot (for the slot's name " @@ -987,7 +2091,7 @@ msgstr "" " --create-slot 새 복제 슬롯을 만듬 (--slot 옵션에서 슬롯 이름 지" "정)\n" -#: pg_receivewal.c:104 pg_recvlogical.c:79 +#: pg_receivewal.c:105 pg_recvlogical.c:90 #, c-format msgid "" " --drop-slot drop the replication slot (for the slot's name see " @@ -995,115 +2099,147 @@ msgid "" msgstr "" " --drop-slot 복제 슬롯 삭제 (--slot 옵션에서 슬롯 이름 지정)\n" -#: pg_receivewal.c:117 +#: pg_receivewal.c:191 #, c-format msgid "finished segment at %X/%X (timeline %u)" msgstr "마무리된 세그먼트 위치: %X/%X (타임라인 %u)" -#: pg_receivewal.c:124 +#: pg_receivewal.c:198 #, c-format msgid "stopped log streaming at %X/%X (timeline %u)" msgstr "로그 스트리밍 중지된 위치: %X/%X (타임라인 %u)" -#: pg_receivewal.c:140 +#: pg_receivewal.c:214 #, c-format msgid "switched to timeline %u at %X/%X" msgstr "전환됨: 타임라인 %u, 위치 %X/%X" -#: pg_receivewal.c:150 +#: pg_receivewal.c:224 pg_recvlogical.c:1053 #, c-format msgid "received interrupt signal, exiting" msgstr "인터럽터 시그널을 받음, 종료함" -#: pg_receivewal.c:186 +#: pg_receivewal.c:256 #, c-format msgid "could not close directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" -#: pg_receivewal.c:272 +#: pg_receivewal.c:323 #, c-format -msgid "segment file \"%s\" has incorrect size %d, skipping" -msgstr "\"%s\" 조각 파일은 잘못된 크기임: %d, 무시함" +msgid "segment file \"%s\" has incorrect size %lld, skipping" +msgstr "\"%s\" 조각 파일은 잘못된 크기임: %lld, 무시함" -#: pg_receivewal.c:290 +#: pg_receivewal.c:340 #, c-format msgid "could not open compressed file \"%s\": %m" msgstr "\"%s\" 압축 파일 열기 실패: %m" -#: pg_receivewal.c:296 +#: pg_receivewal.c:343 #, c-format msgid "could not seek in compressed file \"%s\": %m" msgstr "\"%s\" 압축 파일 작업 위치 찾기 실패: %m" -#: pg_receivewal.c:304 +#: pg_receivewal.c:349 #, c-format msgid "could not read compressed file \"%s\": %m" msgstr "\"%s\" 압축 파일 읽기 실패: %m" -#: pg_receivewal.c:307 +#: pg_receivewal.c:352 #, c-format msgid "could not read compressed file \"%s\": read %d of %zu" msgstr "\"%s\" 압축 파일을 읽을 수 없음: %d 읽음, 전체 %zu" -#: pg_receivewal.c:318 +#: pg_receivewal.c:362 #, c-format msgid "" "compressed segment file \"%s\" has incorrect uncompressed size %d, skipping" msgstr "\"%s\" 압축 파일은 압축 풀었을 때 잘못된 크기임: %d, 무시함" -#: pg_receivewal.c:422 +#: pg_receivewal.c:390 #, c-format -msgid "starting log streaming at %X/%X (timeline %u)" -msgstr "로그 스트리밍 시작 위치: %X/%X (타임라인 %u)" +msgid "could not create LZ4 decompression context: %s" +msgstr "LZ4 압축 컨텍스트 정보를 생성할 수 없습니다: %s" + +#: pg_receivewal.c:420 +#, c-format +msgid "could not decompress file \"%s\": %s" +msgstr "\"%s\" 파일 압축 풀기 실패: %s" + +#: pg_receivewal.c:443 +#, c-format +msgid "could not free LZ4 decompression context: %s" +msgstr "LZ4 압축 해제 컨텍스트 반환 실패: %s" -#: pg_receivewal.c:537 pg_recvlogical.c:762 +#: pg_receivewal.c:448 #, c-format -msgid "invalid port number \"%s\"" -msgstr "잘못된 포트 번호: \"%s\"" +msgid "" +"compressed segment file \"%s\" has incorrect uncompressed size %zu, skipping" +msgstr "\"%s\" 압축된 조각 파일은 압축 풀었을 때 잘못된 크기임: %zu, 무시함" + +#: pg_receivewal.c:453 +#, c-format +msgid "" +"cannot check file \"%s\": compression with %s not supported by this build" +msgstr "\"%s\" 파일 검사 실패: %s 압축을 지원 안하게 빌드되었음" + +#: pg_receivewal.c:578 +#, c-format +msgid "starting log streaming at %X/%X (timeline %u)" +msgstr "로그 스트리밍 시작 위치: %X/%X (타임라인 %u)" -#: pg_receivewal.c:565 pg_recvlogical.c:788 +#: pg_receivewal.c:693 pg_recvlogical.c:801 #, c-format msgid "could not parse end position \"%s\"" msgstr "시작 위치 구문이 잘못됨 \"%s\"" -#: pg_receivewal.c:625 +#: pg_receivewal.c:766 #, c-format msgid "cannot use --create-slot together with --drop-slot" msgstr "--create-slot 옵션과 --drop-slot 옵션을 함께 사용할 수 없음" -#: pg_receivewal.c:643 +#: pg_receivewal.c:782 #, c-format msgid "cannot use --synchronous together with --no-sync" msgstr "--synchronous 옵션과 --no-sync 옵션을 함께 사용할 수 없음" -#: pg_receivewal.c:719 +#: pg_receivewal.c:792 +#, c-format +msgid "no target directory specified" +msgstr "대상 디렉터리를 지정하지 않음" + +#: pg_receivewal.c:816 +#, c-format +msgid "compression with %s is not yet supported" +msgstr "%s 압축을 아직 지원하지 않음" + +#: pg_receivewal.c:859 #, c-format msgid "" "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "\"%s\" 슬롯을 이용한 복제 연결은 이 데이터베이스에서 사용할 수 없음" -#: pg_receivewal.c:730 pg_recvlogical.c:966 +#: pg_receivewal.c:878 pg_recvlogical.c:972 #, c-format msgid "dropping replication slot \"%s\"" msgstr "\"%s\" 이름의 복제 슬롯을 삭제 중" -#: pg_receivewal.c:741 pg_recvlogical.c:976 +#: pg_receivewal.c:889 pg_recvlogical.c:982 #, c-format msgid "creating replication slot \"%s\"" msgstr "\"%s\" 이름의 복제 슬롯을 만드는 중" -#: pg_receivewal.c:767 pg_recvlogical.c:1001 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "연결 끊김" #. translator: check source for value for %d -#: pg_receivewal.c:773 pg_recvlogical.c:1007 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "연결 끊김; 다시 연결 하기 위해 %d 초를 기다리는 중" -#: pg_recvlogical.c:73 +#: pg_recvlogical.c:84 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -1112,7 +2248,7 @@ msgstr "" "%s 프로그램은 논리 디코딩 스트림을 제어하는 도구입니다.\n" "\n" -#: pg_recvlogical.c:77 +#: pg_recvlogical.c:88 #, c-format msgid "" "\n" @@ -1121,7 +2257,7 @@ msgstr "" "\n" "성능에 관계된 기능들:\n" -#: pg_recvlogical.c:80 +#: pg_recvlogical.c:91 #, c-format msgid "" " --start start streaming in a replication slot (for the " @@ -1130,12 +2266,12 @@ msgstr "" " --start 복제 슬롯을 이용한 스트리밍 시작 (--slot 옵션에서 슬" "롯 이름 지정)\n" -#: pg_recvlogical.c:83 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=파일 작업 로그를 해당 파일에 기록, 표준 출력은 -\n" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:95 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -1146,14 +2282,14 @@ msgstr "" " 지정한 초 간격으로 파일 fsync 작업을 함 (초기값: " "%d)\n" -#: pg_recvlogical.c:87 +#: pg_recvlogical.c:98 #, c-format msgid "" " -I, --startpos=LSN where in an existing slot should the streaming " "start\n" msgstr " -I, --startpos=LSN 스트리밍을 시작할 기존 슬롯 위치\n" -#: pg_recvlogical.c:89 +#: pg_recvlogical.c:100 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -1164,112 +2300,116 @@ msgstr "" " 출력 플러그인에서 사용할 옵션들의 옵션 이름과 그 " "값\n" -#: pg_recvlogical.c:92 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN 사용할 출력 플러그인 (초기값: %s)\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=슬롯이름 논리 복제 슬롯 이름\n" -#: pg_recvlogical.c:100 +#: pg_recvlogical.c:107 +#, c-format +msgid "" +" -t, --two-phase enable decoding of prepared transactions when " +"creating a slot\n" +msgstr "" +" -t, --two-phase 슬롯을 만들 때 미리 준비된 트랜잭션 디코딩 활성화\n" + +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=디비이름 접속할 데이터베이스\n" -#: pg_recvlogical.c:133 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "쓰기 확인 위치: %X/%X, 플러시 위치 %X/%X (슬롯 %s)" -#: pg_recvlogical.c:157 receivelog.c:343 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "피드백 패킷을 보낼 수 없음: %s" -#: pg_recvlogical.c:230 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "로그 스트리밍 시작 함, 위치: %X/%X (슬롯 %s)" -#: pg_recvlogical.c:271 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "스트리밍 초기화 됨" -#: pg_recvlogical.c:335 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "\"%s\" 잠금파일을 열 수 없음: %m" -#: pg_recvlogical.c:361 receivelog.c:873 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "잘못된 소켓: %s" -#: pg_recvlogical.c:414 receivelog.c:901 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format -msgid "select() failed: %m" -msgstr "select() 실패: %m" +msgid "%s() failed: %m" +msgstr "%s() 실패: %m" -#: pg_recvlogical.c:421 receivelog.c:951 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "WAL 스트림에서 자료 받기 실패: %s" -#: pg_recvlogical.c:463 pg_recvlogical.c:514 receivelog.c:995 receivelog.c:1061 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 +#: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "스트리밍 헤더 크기가 너무 작음: %d" -#: pg_recvlogical.c:498 receivelog.c:833 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "알 수 없는 스트리밍 헤더: \"%c\"" -#: pg_recvlogical.c:552 pg_recvlogical.c:564 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format -msgid "could not write %u bytes to log file \"%s\": %m" -msgstr "%u 바이트 쓰기 실패, 로그파일 \"%s\": %m" +msgid "could not write %d bytes to log file \"%s\": %m" +msgstr "%d 바이트 쓰기 실패, 대상 로그파일 \"%s\": %m" -#: pg_recvlogical.c:618 receivelog.c:629 receivelog.c:666 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "복제 스트림의 예상치 못한 종료: %s" -#: pg_recvlogical.c:742 -#, c-format -msgid "invalid fsync interval \"%s\"" -msgstr "\"%s\" 값은 잘못된 fsync 반복주기 임" - -#: pg_recvlogical.c:780 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "시작 위치 구문이 잘못됨 \"%s\"" -#: pg_recvlogical.c:869 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "슬롯을 지정하지 않았음" -#: pg_recvlogical.c:877 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "대상 파일을 지정하지 않았음" -#: pg_recvlogical.c:885 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "데이터베이스 지정하지 않았음" -#: pg_recvlogical.c:893 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "적어도 하나 이상의 작업 방법을 지정해야 함" -#: pg_recvlogical.c:901 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "" @@ -1281,89 +2421,94 @@ msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "" " --create-slot 옵션이나 --drop-slot 옵션은 --startpos 옵션과 함께 쓸 수 없음" -#: pg_recvlogical.c:917 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos 옵션은 --start 옵션과 함께 사용해야 함" -#: pg_recvlogical.c:948 +#: pg_recvlogical.c:923 +#, c-format +msgid "--two-phase may only be specified with --create-slot" +msgstr "--two-phase 옵션은 --create-slot 옵션을 쓸 때만 사용 가능함" + +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "데이터베이스 의존적인 복제 연결을 할 수 없음" -#: pg_recvlogical.c:1047 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "keepalive에 의해서 %X/%X 마지막 위치에 도달했음" -#: pg_recvlogical.c:1050 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "%X/%X 마지막 위치가 WAL 레코드 %X/%X 위치에서 도달했음" -#: receivelog.c:69 +#: receivelog.c:66 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "\"%s\" archive status 파일을 만들 수 없습니다: %s" -#: receivelog.c:116 +#: receivelog.c:73 +#, c-format +msgid "could not close archive status file \"%s\": %s" +msgstr "\"%s\" archive status 파일을 닫을 수 없습니다: %s" + +#: receivelog.c:122 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "\"%s\" WAL 파일 크기를 알 수 없음: %s" -#: receivelog.c:126 +#: receivelog.c:133 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "이미 있는 \"%s\" 트랜잭션 로그 파일을 열 수 없음: %s" -#: receivelog.c:134 +#: receivelog.c:142 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "이미 있는 \"%s\" WAL 파일 fsync 실패: %s" -#: receivelog.c:148 +#: receivelog.c:157 #, c-format -msgid "write-ahead log file \"%s\" has %d byte, should be 0 or %d" -msgid_plural "write-ahead log file \"%s\" has %d bytes, should be 0 or %d" +msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" +msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" msgstr[0] "" -"\"%s\" 트랜잭션 로그파일의 크기가 %d 바이트임, 0 또는 %d 바이트여야 함" +"\"%s\" 트랜잭션 로그파일의 크기가 %zd 바이트임, 0 또는 %d 바이트여야 함" -#: receivelog.c:163 +#: receivelog.c:175 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "\"%s\" WAL 파일을 열 수 없음: %s" -#: receivelog.c:189 -#, c-format -msgid "could not determine seek position in file \"%s\": %s" -msgstr "\"%s\" 파일의 시작 위치를 결정할 수 없음: %s" - -#: receivelog.c:203 +#: receivelog.c:216 #, c-format -msgid "not renaming \"%s%s\", segment is not complete" -msgstr "\"%s%s\" 이름 변경 실패, 세그먼트가 완료되지 않았음" +msgid "not renaming \"%s\", segment is not complete" +msgstr "\"%s\" 이름 변경 실패, 세그먼트가 완료되지 않았음" -#: receivelog.c:215 receivelog.c:300 receivelog.c:675 +#: receivelog.c:227 receivelog.c:317 receivelog.c:688 #, c-format msgid "could not close file \"%s\": %s" msgstr "\"%s\" 파일을 닫을 수 없음: %s" -#: receivelog.c:272 +#: receivelog.c:288 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "타임라인 %u 번을 위한 내역 파일 이름이 잘못 되었음: %s" -#: receivelog.c:280 +#: receivelog.c:297 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "\"%s\" 타임라인 내역 파일을 만들 수 없음: %s" -#: receivelog.c:287 +#: receivelog.c:304 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "\"%s\" 타임라인 내역 파일에 쓸 수 없음: %s" -#: receivelog.c:377 +#: receivelog.c:394 #, c-format msgid "" "incompatible server version %s; client does not support streaming from " @@ -1372,7 +2517,7 @@ msgstr "" "%s 서버 버전은 호환되지 않음; 클라이언트는 %s 버전 보다 오래된 서버의 스트리" "밍은 지원하지 않음" -#: receivelog.c:386 +#: receivelog.c:403 #, c-format msgid "" "incompatible server version %s; client does not support streaming from " @@ -1381,27 +2526,18 @@ msgstr "" "%s 서버 버전은 호환되지 않음; 클라이언트는 %s 버전 보다 새로운 서버의 스트리" "밍은 지원하지 않음" -#: receivelog.c:488 streamutil.c:430 streamutil.c:467 -#, c-format -msgid "" -"could not identify system: got %d rows and %d fields, expected %d rows and " -"%d or more fields" -msgstr "" -"시스템을 식별할 수 없음: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, 필드수 %d " -"이상" - -#: receivelog.c:495 +#: receivelog.c:508 #, c-format msgid "" "system identifier does not match between base backup and streaming connection" msgstr "시스템 식별자가 베이스 백업과 스트리밍 연결에서 서로 다름" -#: receivelog.c:501 +#: receivelog.c:516 #, c-format msgid "starting timeline %u is not present in the server" msgstr "%u 타임라인으로 시작하는 것을 서버에서 제공 하지 않음" -#: receivelog.c:542 +#: receivelog.c:555 #, c-format msgid "" "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, " @@ -1410,12 +2546,12 @@ msgstr "" "TIMELINE_HISTORY 명령 결과가 잘못됨: 받은 값: 로우수 %d, 필드수 %d, 예상값: " "로우수 %d, 필드수 %d" -#: receivelog.c:613 +#: receivelog.c:626 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "서버가 잘못된 다음 타임라인 번호 %u 보고함, 이전 타임라인 번호 %u" -#: receivelog.c:619 +#: receivelog.c:632 #, c-format msgid "" "server stopped streaming timeline %u at %X/%X, but reported next timeline %u " @@ -1424,12 +2560,12 @@ msgstr "" "서버의 중지 위치: 타임라인 %u, 위치 %X/%X, 하지만 보고 받은 위치: 타임라인 " "%u 위치 %X/%X" -#: receivelog.c:659 +#: receivelog.c:672 #, c-format msgid "replication stream was terminated before stop point" msgstr "복제 스트림이 중지 위치 전에 종료 되었음" -#: receivelog.c:705 +#: receivelog.c:718 #, c-format msgid "" "unexpected result set after end-of-timeline: got %d rows and %d fields, " @@ -1438,66 +2574,61 @@ msgstr "" "타임라인 끝에 잘못된 결과가 발견 됨: 로우수 %d, 필드수 %d / 예상값: 로우수 " "%d, 필드수 %d" -#: receivelog.c:714 +#: receivelog.c:727 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "다음 타임라인 시작 위치 분석 실패 \"%s\"" -#: receivelog.c:763 receivelog.c:1015 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "\"%s\" 파일 fsync 실패: %s" -#: receivelog.c:1078 +#: receivelog.c:1083 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "%u 위치의 수신된 트랜잭션 로그 레코드에 파일을 열 수 없음" -#: receivelog.c:1088 +#: receivelog.c:1093 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "잘못된 WAL 자료 위치 %08x, 기대값 %08x" -#: receivelog.c:1122 +#: receivelog.c:1128 #, c-format -msgid "could not write %u bytes to WAL file \"%s\": %s" -msgstr "%u 바이트를 \"%s\" WAL 파일에 쓸 수 없음: %s" +msgid "could not write %d bytes to WAL file \"%s\": %s" +msgstr "%d 바이트를 \"%s\" WAL 파일에 쓸 수 없음: %s" -#: receivelog.c:1147 receivelog.c:1187 receivelog.c:1218 +#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 #, c-format msgid "could not send copy-end packet: %s" msgstr "copy-end 패킷을 보낼 수 없음: %s" -#: streamutil.c:160 +#: streamutil.c:165 msgid "Password: " msgstr "암호: " -#: streamutil.c:185 +#: streamutil.c:192 #, c-format msgid "could not connect to server" msgstr "서버 접속 실패" -#: streamutil.c:202 -#, c-format -msgid "could not connect to server: %s" -msgstr "서버 접속 실패: %s" - -#: streamutil.c:231 +#: streamutil.c:233 #, c-format -msgid "could not clear search_path: %s" -msgstr "search_path를 지울 수 없음: %s" +msgid "could not clear \"search_path\": %s" +msgstr "\"search_path\"를 지울 수 없음: %s" -#: streamutil.c:247 +#: streamutil.c:249 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "integer_datetimes 서버 설정을 알 수 없음" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "\"integer_datetimes\" 서버 설정을 알 수 없음" -#: streamutil.c:254 +#: streamutil.c:256 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "integer_datetimes 컴파일 플래그가 서버와 일치하지 않음" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "\"integer_datetimes\" 컴파일 플래그가 서버와 일치하지 않음" -#: streamutil.c:305 +#: streamutil.c:375 #, c-format msgid "" "could not fetch WAL segment size: got %d rows and %d fields, expected %d " @@ -1506,24 +2637,23 @@ msgstr "" "WAL 조각 크기 계산 실패: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, 필드수 %d " "이상" -#: streamutil.c:315 +#: streamutil.c:385 #, c-format msgid "WAL segment size could not be parsed" msgstr "WAL 조각 크기 분석 못함" -#: streamutil.c:333 +#: streamutil.c:403 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"remote server reported a value of %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"remote server reported a value of %d bytes" -msgstr[0] "" -"WAL 조각 파일 크기는 1MB에서 1GB사이 2의 제곱 크기여야 하는데, " -"원격 서버는 %d 바이트입니다." +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "원격 서버가 잘못 WAL 조각 크기를 보고했음 (%d 바이트)" + +#: streamutil.c:407 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL 조각 파일 크기는 1MB에서 1GB사이 2의 제곱 크기여야 합니다." -#: streamutil.c:378 +#: streamutil.c:449 #, c-format msgid "" "could not fetch group access flag: got %d rows and %d fields, expected %d " @@ -1532,12 +2662,45 @@ msgstr "" "그룹 접근 플래그를 가져올 수 없음: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, " "필드수 %d 이상" -#: streamutil.c:387 +#: streamutil.c:458 #, c-format msgid "group access flag could not be parsed: %s" msgstr "그룹 접근 플래그를 분석 못함: %s" -#: streamutil.c:544 +#: streamutil.c:501 streamutil.c:538 +#, c-format +msgid "" +"could not identify system: got %d rows and %d fields, expected %d rows and " +"%d or more fields" +msgstr "" +"시스템을 식별할 수 없음: 로우수 %d, 필드수 %d, 예상값: 로우수 %d, 필드수 %d " +"이상" + +#: streamutil.c:590 +#, c-format +msgid "" +"could not read replication slot \"%s\": got %d rows and %d fields, expected " +"%d rows and %d fields" +msgstr "" +"\"%s\" 복제 슬롯을 읽을 수 없음: 로우수 %d, 필드수 %d, 기대값 로우수 %d, 필드" +"수 %d" + +#: streamutil.c:602 +#, c-format +msgid "replication slot \"%s\" does not exist" +msgstr "\"%s\" 이름의 복제 슬롯이 없습니다" + +#: streamutil.c:613 +#, c-format +msgid "expected a physical replication slot, got type \"%s\" instead" +msgstr "물리 복제 슬롯을 사용해야 함, \"%s\" 복제 슬롯임" + +#: streamutil.c:627 +#, c-format +msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" +msgstr "\"%s\" restart_lsn 위치를 해석할 수 없음, 해당 슬롯: \"%s\"" + +#: streamutil.c:744 #, c-format msgid "" "could not create replication slot \"%s\": got %d rows and %d fields, " @@ -1546,7 +2709,7 @@ msgstr "" "\"%s\" 복제 슬롯을 만들 수 없음: 로우수 %d, 필드수 %d, 기대값 로우수 %d, 필드" "수 %d" -#: streamutil.c:588 +#: streamutil.c:788 #, c-format msgid "" "could not drop replication slot \"%s\": got %d rows and %d fields, expected " @@ -1555,34 +2718,30 @@ msgstr "" "\"%s\" 복제 슬롯을 삭제할 수 없음: 로우수 %d, 필드수 %d, 기대값 로우수 %d, 필" "드수 %d" -#: walmethods.c:438 walmethods.c:927 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "자료를 압축할 수 없음" -#: walmethods.c:470 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "압축 스트림을 리셋할 수 없음" -#: walmethods.c:568 -msgid "could not initialize compression library" -msgstr "압축 라이브러리를 초기화할 수 없음" - -#: walmethods.c:580 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "구현 오류: tar 파일은 하나 이상 열 수 없음" -#: walmethods.c:594 +#: walmethods.c:907 msgid "could not create tar header" msgstr "tar 해더를 만들 수 없음" -#: walmethods.c:608 walmethods.c:648 walmethods.c:843 walmethods.c:854 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "압축 매개 변수를 바꿀 수 없음" -#: walmethods.c:730 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "압축 상태에서 파일 삭제는 지원하지 않음" -#: walmethods.c:952 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "압축 스트림을 닫을 수 없음" diff --git a/src/bin/pg_basebackup/po/meson.build b/src/bin/pg_basebackup/po/meson.build index aee79603634ba..bab2cd32646fd 100644 --- a/src/bin/pg_basebackup/po/meson.build +++ b/src/bin/pg_basebackup/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_basebackup-' + pg_version_major.to_string())] diff --git a/src/bin/pg_basebackup/po/ru.po b/src/bin/pg_basebackup/po/ru.po index 743d7c935e40d..94912f27c90b4 100644 --- a/src/bin/pg_basebackup/po/ru.po +++ b/src/bin/pg_basebackup/po/ru.po @@ -1,21 +1,21 @@ # Russian message translation file for pg_basebackup # Copyright (C) 2012-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_basebackup (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-11-01 14:40+0300\n" -"PO-Revision-Date: 2022-09-29 12:01+0300\n" +"POT-Creation-Date: 2024-11-09 07:47+0300\n" +"PO-Revision-Date: 2024-09-07 11:12+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,37 +37,44 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " -#: ../../common/compression.c:130 ../../common/compression.c:139 -#: ../../common/compression.c:148 +#: ../../common/compression.c:132 ../../common/compression.c:141 +#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 +#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 +#: bbstreamer_zstd.c:284 #, c-format msgid "this build does not support compression with %s" msgstr "эта сборка программы не поддерживает сжатие %s" -#: ../../common/compression.c:203 +#: ../../common/compression.c:205 msgid "found empty string where a compression option was expected" msgstr "вместо указания параметра сжатия получена пустая строка" -#: ../../common/compression.c:237 +#: ../../common/compression.c:244 #, c-format msgid "unrecognized compression option: \"%s\"" msgstr "нераспознанный параметр сжатия: \"%s\"" -#: ../../common/compression.c:276 +#: ../../common/compression.c:283 #, c-format msgid "compression option \"%s\" requires a value" msgstr "для параметра сжатия \"%s\" требуется значение" -#: ../../common/compression.c:285 +#: ../../common/compression.c:292 #, c-format msgid "value for compression option \"%s\" must be an integer" msgstr "значение параметра сжатия \"%s\" должно быть целочисленным" -#: ../../common/compression.c:335 +#: ../../common/compression.c:331 +#, c-format +msgid "value for compression option \"%s\" must be a Boolean value" +msgstr "значение параметра сжатия \"%s\" должно быть булевским" + +#: ../../common/compression.c:379 #, c-format msgid "compression algorithm \"%s\" does not accept a compression level" msgstr "для алгоритма сжатия \"%s\" нельзя задать уровень сжатия" -#: ../../common/compression.c:342 +#: ../../common/compression.c:386 #, c-format msgid "" "compression algorithm \"%s\" expects a compression level between %d and %d " @@ -76,55 +83,149 @@ msgstr "" "для алгоритма сжатия \"%s\" ожидается уровень сжатия от %d до %d (по " "умолчанию %d)" -#: ../../common/compression.c:353 +#: ../../common/compression.c:397 #, c-format msgid "compression algorithm \"%s\" does not accept a worker count" msgstr "для алгоритма сжатия \"%s\" нельзя задать число потоков" +#: ../../common/compression.c:408 +#, c-format +msgid "compression algorithm \"%s\" does not support long-distance mode" +msgstr "алгоритм сжатия \"%s\" не поддерживает режим большой дистанции" + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "не удалось закрыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"возможно несоответствие порядка байт\n" +"Порядок байт в файле pg_control может не соответствовать используемому\n" +"этой программой. В этом случае результаты будут неверными и\n" +"установленный PostgreSQL будет несовместим с этим каталогом данных." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не удалось записать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 -#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format msgid "out of memory\n" msgstr "нехватка памяти\n" -#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 #, c-format msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:451 -#: pg_receivewal.c:380 pg_recvlogical.c:341 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не удалось получить информацию о файле \"%s\": %m" -#: ../../common/file_utils.c:166 pg_receivewal.c:303 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не удалось открыть каталог \"%s\": %m" -#: ../../common/file_utils.c:200 pg_receivewal.c:532 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не удалось прочитать каталог \"%s\": %m" -#: ../../common/file_utils.c:232 ../../common/file_utils.c:291 -#: ../../common/file_utils.c:365 ../../fe_utils/recovery_gen.c:121 -#: pg_receivewal.c:447 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" -#: ../../common/file_utils.c:303 ../../common/file_utils.c:373 -#: pg_recvlogical.c:196 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" +msgid "could not open process token: error code %lu" +msgstr "не удалось открыть маркер процесса (код ошибки: %lu)" -#: ../../common/file_utils.c:383 pg_basebackup.c:2266 walmethods.c:459 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "не удалось подготовить структуры SID (код ошибки: %lu)" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "не удалось создать ограниченный маркер (код ошибки: %lu)" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "не удалось запустить процесс для команды \"%s\" (код ошибки: %lu)" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "не удалось перезапуститься с ограниченным маркером (код ошибки: %lu)" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -136,51 +237,65 @@ msgstr "неверное значение \"%s\" для параметра %s" msgid "%s must be in range %d..%d" msgstr "значение %s должно быть в диапазоне %d..%d" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 pg_basebackup.c:1646 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:334 #, c-format msgid "out of memory" msgstr "нехватка памяти" -#: ../../fe_utils/recovery_gen.c:124 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1443 pg_basebackup.c:1737 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "не удалось записать в файл \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 bbstreamer_file.c:93 bbstreamer_file.c:339 -#: pg_basebackup.c:1507 pg_basebackup.c:1716 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "не удалось создать файл \"%s\": %m" -#: bbstreamer_file.c:138 pg_recvlogical.c:635 +#: ../../fe_utils/string_utils.c:434 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "не удалось закрыть файл \"%s\": %m" +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" #: bbstreamer_file.c:275 #, c-format msgid "unexpected state while extracting archive" msgstr "неожиданное состояние при извлечении архива" -#: bbstreamer_file.c:298 pg_basebackup.c:696 pg_basebackup.c:740 +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не удалось создать каталог \"%s\": %m" -#: bbstreamer_file.c:304 +#: bbstreamer_file.c:326 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "не удалось установить права для каталога \"%s\": %m" -#: bbstreamer_file.c:323 +#: bbstreamer_file.c:345 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "не удалось создать символическую ссылку \"%s\" в \"%s\": %m" -#: bbstreamer_file.c:343 +#: bbstreamer_file.c:365 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "не удалось установить права доступа для файла \"%s\": %m" @@ -205,11 +320,6 @@ msgstr "не удалось открыть выходной файл: %m" msgid "could not set compression level %d: %s" msgstr "не удалось установить уровень сжатия %d: %s" -#: bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 -#, c-format -msgid "this build does not support gzip compression" -msgstr "эта сборка программы не поддерживает сжатие gzip" - #: bbstreamer_gzip.c:143 #, c-format msgid "could not write to compressed file \"%s\": %s" @@ -220,12 +330,12 @@ msgstr "не удалось записать сжатый файл \"%s\": %s" msgid "could not close compressed file \"%s\": %m" msgstr "не удалось закрыть сжатый файл \"%s\": %m" -#: bbstreamer_gzip.c:245 walmethods.c:869 +#: bbstreamer_gzip.c:245 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "не удалось инициализировать библиотеку сжатия" -#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:316 +#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 #, c-format msgid "could not decompress data: %s" msgstr "не удалось распаковать данные: %s" @@ -240,17 +350,12 @@ msgstr "неожиданное состояние при внедрении па msgid "could not create lz4 compression context: %s" msgstr "не удалось создать контекст сжатия lz4: %s" -#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 -#, c-format -msgid "this build does not support lz4 compression" -msgstr "эта сборка программы не поддерживает сжатие lz4" - #: bbstreamer_lz4.c:140 #, c-format msgid "could not write lz4 header: %s" msgstr "не удалось записать заголовок lz4: %s" -#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:168 bbstreamer_zstd.c:210 +#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 #, c-format msgid "could not compress data: %s" msgstr "не удалось сжать данные: %s" @@ -275,12 +380,12 @@ msgstr "окончание файла tar занимает больше 2 бло msgid "unexpected state while parsing tar archive" msgstr "неожиданное состояние при разборе архива tar" -#: bbstreamer_tar.c:296 +#: bbstreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "пустое имя у компонента tar" -#: bbstreamer_tar.c:328 +#: bbstreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "поток COPY закончился до завершения последнего файла" @@ -300,103 +405,103 @@ msgstr "не удалось установить для zstd уровень сж msgid "could not set compression worker count to %d: %s" msgstr "не удалось установить для zstd число потоков %d: %s" -#: bbstreamer_zstd.c:116 bbstreamer_zstd.c:271 +#: bbstreamer_zstd.c:116 #, c-format -msgid "this build does not support zstd compression" -msgstr "эта сборка программы не поддерживает сжатие zstd" +msgid "could not enable long-distance mode: %s" +msgstr "не удалось включить режим большой дистанции: %s" -#: bbstreamer_zstd.c:262 +#: bbstreamer_zstd.c:275 #, c-format msgid "could not create zstd decompression context" msgstr "не удалось создать контекст распаковки zstd" -#: pg_basebackup.c:240 +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "удаление каталога данных \"%s\"" -#: pg_basebackup.c:242 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "ошибка при удалении каталога данных" -#: pg_basebackup.c:246 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "удаление содержимого каталога данных \"%s\"" -#: pg_basebackup.c:248 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "ошибка при удалении содержимого каталога данных" -#: pg_basebackup.c:253 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "удаление каталога WAL \"%s\"" -#: pg_basebackup.c:255 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "ошибка при удалении каталога WAL" -#: pg_basebackup.c:259 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "удаление содержимого каталога WAL \"%s\"" -#: pg_basebackup.c:261 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "ошибка при удалении содержимого каталога WAL" -#: pg_basebackup.c:267 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "каталог данных \"%s\" не был удалён по запросу пользователя" -#: pg_basebackup.c:270 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "каталог WAL \"%s\" не был удалён по запросу пользователя" -#: pg_basebackup.c:274 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "изменения в каталогах табличных пространств не будут отменены" -#: pg_basebackup.c:326 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "слишком длинное имя каталога" -#: pg_basebackup.c:333 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "несколько знаков \"=\" в сопоставлении табличного пространства" -#: pg_basebackup.c:342 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "" "сопоставление табл. пространства записано неверно: \"%s\"; должно быть " "\"СТАРЫЙ_КАТАЛОГ=НОВЫЙ_КАТАЛОГ\"" -#: pg_basebackup.c:361 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "" "старый каталог в сопоставлении табл. пространства задан не абсолютным путём: " "%s" -#: pg_basebackup.c:365 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "" "новый каталог в сопоставлении табл. пространства задан не абсолютным путём: " "%s" -#: pg_basebackup.c:387 +#: pg_basebackup.c:392 #, c-format msgid "" "%s takes a base backup of a running PostgreSQL server.\n" @@ -405,17 +510,19 @@ msgstr "" "%s делает базовую резервную копию работающего сервера PostgreSQL.\n" "\n" -#: pg_basebackup.c:389 pg_receivewal.c:81 pg_recvlogical.c:78 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_basebackup.c:390 pg_receivewal.c:82 pg_recvlogical.c:79 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [ПАРАМЕТР]...\n" -#: pg_basebackup.c:391 +#: pg_basebackup.c:396 #, c-format msgid "" "\n" @@ -424,19 +531,28 @@ msgstr "" "\n" "Параметры, управляющие выводом:\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" msgstr " -D, --pgdata=КАТАЛОГ сохранить базовую копию в указанный каталог\n" -#: pg_basebackup.c:393 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr "" " -F, --format=p|t формат вывода (p (по умолчанию) - простой, t - " "tar)\n" -#: pg_basebackup.c:394 +#: pg_basebackup.c:399 +#, c-format +msgid "" +" -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr "" +" -i, --incremental=СТАРЫЙ_МАНИФЕСТ\n" +" создать инкрементальную копию\n" + +#: pg_basebackup.c:401 #, c-format msgid "" " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" @@ -445,7 +561,7 @@ msgstr "" " -r, --max-rate=СКОРОСТЬ макс. скорость передачи данных в целевой каталог\n" " (в КБ/с, либо добавьте суффикс \"k\" или \"M\")\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:403 #, c-format msgid "" " -R, --write-recovery-conf\n" @@ -455,7 +571,7 @@ msgstr "" " записать конфигурацию для репликации\n" # well-spelled: ИНФО -#: pg_basebackup.c:398 +#: pg_basebackup.c:405 #, c-format msgid "" " -t, --target=TARGET[:DETAIL]\n" @@ -464,7 +580,7 @@ msgstr "" " -t, --target=ПОЛУЧАТЕЛЬ[:ДОП_ИНФО]\n" " получатель копии (если отличается от client)\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:407 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -475,14 +591,14 @@ msgstr "" "каталога\n" " в новый\n" -#: pg_basebackup.c:402 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr "" " --waldir=КАТАЛОГ_WAL\n" " расположение каталога с журналом предзаписи\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:410 #, c-format msgid "" " -X, --wal-method=none|fetch|stream\n" @@ -492,13 +608,13 @@ msgstr "" " включить в копию требуемые файлы WAL, используя\n" " заданный метод\n" -#: pg_basebackup.c:405 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip сжать выходной tar\n" # well-spelled: ИНФО -#: pg_basebackup.c:406 +#: pg_basebackup.c:413 #, c-format msgid "" " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" @@ -508,12 +624,12 @@ msgstr "" " выполнять сжатие на клиенте или сервере как " "указано\n" -#: pg_basebackup.c:408 +#: pg_basebackup.c:415 #, c-format msgid " -Z, --compress=none do not compress tar output\n" msgstr " -Z, --compress=none не сжимать вывод tar\n" -#: pg_basebackup.c:409 +#: pg_basebackup.c:416 #, c-format msgid "" "\n" @@ -522,31 +638,32 @@ msgstr "" "\n" "Общие параметры:\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:417 #, c-format msgid "" " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" +" set fast or spread (default) checkpointing\n" msgstr "" " -c, --checkpoint=fast|spread\n" -" режим быстрых или распределённых контрольных точек\n" +" режим быстрых или распределённых (по умолчанию)\n" +" контрольных точек\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " -C, --create-slot создать слот репликации\n" -#: pg_basebackup.c:413 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=МЕТКА установить метку резервной копии\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean не очищать после ошибок\n" -#: pg_basebackup.c:415 +#: pg_basebackup.c:422 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " @@ -554,27 +671,27 @@ msgid "" msgstr "" " -N, --no-sync не ждать завершения сохранения данных на диске\n" -#: pg_basebackup.c:416 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress показывать прогресс операции\n" -#: pg_basebackup.c:417 pg_receivewal.c:91 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=ИМЯ_СЛОТА использовать заданный слот репликации\n" -#: pg_basebackup.c:418 pg_receivewal.c:93 pg_recvlogical.c:100 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose выводить подробные сообщения\n" -#: pg_basebackup.c:419 pg_receivewal.c:94 pg_recvlogical.c:101 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_basebackup.c:420 +#: pg_basebackup.c:427 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -585,7 +702,7 @@ msgstr "" # skip-rule: capital-letter-first # well-spelled: шестнадц -#: pg_basebackup.c:422 +#: pg_basebackup.c:429 #, c-format msgid "" " --manifest-force-encode\n" @@ -595,25 +712,25 @@ msgstr "" " записывать все имена файлов в манифесте в шестнадц. " "виде\n" -#: pg_basebackup.c:424 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" msgstr "" " --no-estimate-size не рассчитывать размер копии на стороне сервера\n" -#: pg_basebackup.c:425 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest отключить создание манифеста копии\n" -#: pg_basebackup.c:426 +#: pg_basebackup.c:433 #, c-format msgid "" " --no-slot prevent creation of temporary replication slot\n" msgstr "" " --no-slot предотвратить создание временного слота репликации\n" -#: pg_basebackup.c:427 +#: pg_basebackup.c:434 #, c-format msgid "" " --no-verify-checksums\n" @@ -622,12 +739,22 @@ msgstr "" " --no-verify-checksums\n" " не проверять контрольные суммы\n" -#: pg_basebackup.c:429 pg_receivewal.c:97 pg_recvlogical.c:102 +# well-spelled: ИНФО +#: pg_basebackup.c:436 +#, c-format +msgid "" +" --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr "" +" --sync-method=МЕТОД\n" +" метод синхронизации файлов с ФС\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_basebackup.c:430 pg_receivewal.c:98 pg_recvlogical.c:103 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "" "\n" @@ -636,22 +763,24 @@ msgstr "" "\n" "Параметры подключения:\n" -#: pg_basebackup.c:431 pg_receivewal.c:99 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=СТРОКА строка подключения\n" -#: pg_basebackup.c:432 pg_receivewal.c:100 pg_recvlogical.c:105 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" -msgstr " -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" +msgstr "" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" -#: pg_basebackup.c:433 pg_receivewal.c:101 pg_recvlogical.c:106 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=ПОРТ номер порта сервера БД\n" -#: pg_basebackup.c:434 +#: pg_basebackup.c:443 #, c-format msgid "" " -s, --status-interval=INTERVAL\n" @@ -662,19 +791,19 @@ msgstr "" " интервал между передаваемыми серверу\n" " пакетами состояния (в секундах)\n" -#: pg_basebackup.c:436 pg_receivewal.c:102 pg_recvlogical.c:107 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr "" " -U, --username=NAME connect as specified database user\n" " -U, --username=ИМЯ имя пользователя баз данных\n" -#: pg_basebackup.c:437 pg_receivewal.c:103 pg_recvlogical.c:108 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: pg_basebackup.c:438 pg_receivewal.c:104 pg_recvlogical.c:109 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid "" " -W, --password force password prompt (should happen " @@ -682,7 +811,8 @@ msgid "" msgstr "" " -W, --password запрашивать пароль всегда (обычно не требуется)\n" -#: pg_basebackup.c:439 pg_receivewal.c:108 pg_recvlogical.c:110 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "" "\n" @@ -691,63 +821,64 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_basebackup.c:440 pg_receivewal.c:109 pg_recvlogical.c:111 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_basebackup.c:482 +#: pg_basebackup.c:488 #, c-format msgid "could not read from ready pipe: %m" msgstr "не удалось прочитать из готового канала: %m" -#: pg_basebackup.c:485 pg_basebackup.c:632 pg_basebackup.c:2180 -#: streamutil.c:444 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:521 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "не удалось разобрать положение в журнале предзаписи \"%s\"" -#: pg_basebackup.c:591 pg_receivewal.c:663 +#: pg_basebackup.c:596 pg_receivewal.c:600 #, c-format msgid "could not finish writing WAL files: %m" msgstr "не удалось завершить запись файлов WAL: %m" -#: pg_basebackup.c:641 +#: pg_basebackup.c:642 #, c-format msgid "could not create pipe for background process: %m" msgstr "не удалось создать канал для фонового процесса: %m" -#: pg_basebackup.c:674 +#: pg_basebackup.c:676 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "создан временный слот репликации \"%s\"" -#: pg_basebackup.c:677 +#: pg_basebackup.c:679 #, c-format msgid "created replication slot \"%s\"" msgstr "создан слот репликации \"%s\"" -#: pg_basebackup.c:711 +#: pg_basebackup.c:728 #, c-format msgid "could not create background process: %m" msgstr "не удалось создать фоновый процесс: %m" -#: pg_basebackup.c:720 +#: pg_basebackup.c:737 #, c-format msgid "could not create background thread: %m" msgstr "не удалось создать фоновый поток выполнения: %m" -#: pg_basebackup.c:759 +#: pg_basebackup.c:776 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" существует, но он не пуст" -#: pg_basebackup.c:765 +#: pg_basebackup.c:782 pg_createsubscriber.c:390 #, c-format msgid "could not access directory \"%s\": %m" -msgstr "ошибка доступа к каталогу \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" -#: pg_basebackup.c:842 +#: pg_basebackup.c:858 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" @@ -755,7 +886,7 @@ msgstr[0] "%*s/%s КБ (100%%), табличное пространство %d/% msgstr[1] "%*s/%s КБ (100%%), табличное пространство %d/%d %*s" msgstr[2] "%*s/%s КБ (100%%), табличное пространство %d/%d %*s" -#: pg_basebackup.c:854 +#: pg_basebackup.c:870 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" @@ -763,7 +894,7 @@ msgstr[0] "%*s/%s КБ (%d%%), табличное пространство %d/%d msgstr[1] "%*s/%s КБ (%d%%), табличное пространство %d/%d (%s%-*.*s)" msgstr[2] "%*s/%s КБ (%d%%), табличное пространство %d/%d (%s%-*.*s)" -#: pg_basebackup.c:870 +#: pg_basebackup.c:886 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" @@ -771,58 +902,58 @@ msgstr[0] "%*s/%s КБ (%d%%), табличное пространство %d/%d msgstr[1] "%*s/%s КБ (%d%%), табличное пространство %d/%d" msgstr[2] "%*s/%s КБ (%d%%), табличное пространство %d/%d" -#: pg_basebackup.c:894 +#: pg_basebackup.c:910 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "неверное значение (\"%s\") для скорости передачи данных" -#: pg_basebackup.c:896 +#: pg_basebackup.c:912 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "неверная скорость передачи данных \"%s\": %m" -#: pg_basebackup.c:903 +#: pg_basebackup.c:919 #, c-format msgid "transfer rate must be greater than zero" msgstr "скорость передачи должна быть больше 0" -#: pg_basebackup.c:933 +#: pg_basebackup.c:949 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "неверная единица измерения в --max-rate: \"%s\"" -#: pg_basebackup.c:937 +#: pg_basebackup.c:953 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "скорость передачи \"%s\" вне целочисленного диапазона" -#: pg_basebackup.c:944 +#: pg_basebackup.c:960 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "скорость передачи \"%s\" вне диапазона" -#: pg_basebackup.c:1040 +#: pg_basebackup.c:1022 #, c-format msgid "could not get COPY data stream: %s" msgstr "не удалось получить поток данных COPY: %s" -#: pg_basebackup.c:1057 pg_recvlogical.c:438 pg_recvlogical.c:610 -#: receivelog.c:981 +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 +#: receivelog.c:973 #, c-format msgid "could not read COPY data: %s" msgstr "не удалось прочитать данные COPY: %s" -#: pg_basebackup.c:1061 +#: pg_basebackup.c:1043 #, c-format msgid "background process terminated unexpectedly" msgstr "фоновый процесс завершился неожиданно" -#: pg_basebackup.c:1132 +#: pg_basebackup.c:1114 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "манифест нельзя внедрить в сжатый архив tar" -#: pg_basebackup.c:1133 +#: pg_basebackup.c:1115 #, c-format msgid "" "Use client-side compression, send the output to a directory rather than " @@ -831,24 +962,24 @@ msgstr "" "Примените сжатие на стороне клиента, передайте вывод в каталог, а не в " "стандартный вывод, или используйте %s." -#: pg_basebackup.c:1149 +#: pg_basebackup.c:1131 #, c-format msgid "cannot parse archive \"%s\"" msgstr "обработать архив \"%s\" невозможно" -#: pg_basebackup.c:1150 +#: pg_basebackup.c:1132 #, c-format msgid "Only tar archives can be parsed." msgstr "Возможна обработка только архивов tar." -#: pg_basebackup.c:1152 +#: pg_basebackup.c:1134 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "" "Когда используется простой формат, программа pg_basebackup должна обработать " "архив." -#: pg_basebackup.c:1154 +#: pg_basebackup.c:1136 #, c-format msgid "" "Using - as the output directory requires pg_basebackup to parse the archive." @@ -856,89 +987,119 @@ msgstr "" "Когда в качестве выходного каталога используется \"-\", программа " "pg_basebackup должна обработать архив." -#: pg_basebackup.c:1156 +#: pg_basebackup.c:1138 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "" "Когда используется ключ -R, программа pg_basebackup должна обработать архив." -#: pg_basebackup.c:1367 +#: pg_basebackup.c:1357 #, c-format msgid "archives must precede manifest" msgstr "архивы должны предшествовать манифесту" -#: pg_basebackup.c:1382 +#: pg_basebackup.c:1372 #, c-format msgid "invalid archive name: \"%s\"" msgstr "неверное имя архива: \"%s\"" -#: pg_basebackup.c:1454 +#: pg_basebackup.c:1444 #, c-format msgid "unexpected payload data" msgstr "неожиданно получены данные" -#: pg_basebackup.c:1597 +#: pg_basebackup.c:1587 #, c-format msgid "empty COPY message" msgstr "пустое сообщение COPY" -#: pg_basebackup.c:1599 +#: pg_basebackup.c:1589 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "неправильное сообщение COPY типа %d, длины %zu" -#: pg_basebackup.c:1797 +#: pg_basebackup.c:1789 #, c-format msgid "incompatible server version %s" msgstr "несовместимая версия сервера %s" -#: pg_basebackup.c:1813 +#: pg_basebackup.c:1805 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "Укажите -X none или -X fetch для отключения трансляции журнала." -#: pg_basebackup.c:1881 +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "сервер не поддерживает инкрементальное копирование" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:367 streamutil.c:441 +#: streamutil.c:493 streamutil.c:581 streamutil.c:733 streamutil.c:778 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "не удалось передать команду репликации \"%s\": %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "не удалось загрузить манифест на сервер: %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#, c-format +msgid "could not upload manifest: unexpected status %s" +msgstr "не удалось загрузить манифест на сервер: неожиданное состояние %s" + +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "не удалось отправить данные COPY: %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "не удалось отправить сообщение \"конец COPY\": %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "неожиданный лишний результат при передаче манифеста" + +#: pg_basebackup.c:1950 #, c-format msgid "backup targets are not supported by this server version" msgstr "получатели копий не поддерживаются данной версией сервера" -#: pg_basebackup.c:1884 +#: pg_basebackup.c:1953 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "" "при использовании получателя копии записать конфигурацию восстановления " "нельзя" -#: pg_basebackup.c:1911 +#: pg_basebackup.c:1980 #, c-format msgid "server does not support server-side compression" msgstr "сервер не поддерживает сжатие на стороне сервера" -#: pg_basebackup.c:1921 +#: pg_basebackup.c:1990 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "" "начинается базовое резервное копирование, ожидается завершение контрольной " "точки" -#: pg_basebackup.c:1925 +#: pg_basebackup.c:1994 #, c-format msgid "waiting for checkpoint" msgstr "ожидание контрольной точки" -#: pg_basebackup.c:1938 pg_recvlogical.c:262 receivelog.c:549 receivelog.c:588 -#: streamutil.c:291 streamutil.c:364 streamutil.c:416 streamutil.c:504 -#: streamutil.c:656 streamutil.c:701 -#, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "не удалось передать команду репликации \"%s\": %s" - -#: pg_basebackup.c:1946 +#: pg_basebackup.c:2016 #, c-format msgid "could not initiate base backup: %s" msgstr "не удалось инициализировать базовое резервное копирование: %s" -#: pg_basebackup.c:1949 +#: pg_basebackup.c:2019 #, c-format msgid "" "server returned unexpected response to BASE_BACKUP command; got %d rows and " @@ -947,123 +1108,130 @@ msgstr "" "сервер вернул неожиданный ответ на команду BASE_BACKUP; получено строк: %d, " "полей: %d, а ожидалось строк: %d, полей: %d" -#: pg_basebackup.c:1955 +#: pg_basebackup.c:2025 #, c-format msgid "checkpoint completed" msgstr "контрольная точка завершена" -#: pg_basebackup.c:1970 +#: pg_basebackup.c:2039 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "стартовая точка в журнале предзаписи: %s на линии времени %u" -#: pg_basebackup.c:1978 +#: pg_basebackup.c:2047 #, c-format msgid "could not get backup header: %s" msgstr "не удалось получить заголовок резервной копии: %s" -#: pg_basebackup.c:1981 +#: pg_basebackup.c:2050 #, c-format msgid "no data returned from server" msgstr "сервер не вернул данные" -#: pg_basebackup.c:2016 +#: pg_basebackup.c:2093 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "" "в stdout можно вывести только одно табличное пространство, всего в СУБД их %d" -#: pg_basebackup.c:2029 +#: pg_basebackup.c:2106 #, c-format msgid "starting background WAL receiver" msgstr "запуск фонового процесса считывания WAL" -#: pg_basebackup.c:2111 +#: pg_basebackup.c:2189 #, c-format msgid "backup failed: %s" msgstr "ошибка при создании копии: %s" -#: pg_basebackup.c:2114 +#: pg_basebackup.c:2192 #, c-format msgid "no write-ahead log end position returned from server" msgstr "сервер не передал конечную позицию в журнале предзаписи" -#: pg_basebackup.c:2117 +#: pg_basebackup.c:2195 #, c-format msgid "write-ahead log end point: %s" msgstr "конечная точка в журнале предзаписи: %s" -#: pg_basebackup.c:2128 +#: pg_basebackup.c:2206 #, c-format msgid "checksum error occurred" msgstr "выявлена ошибка контрольной суммы" -#: pg_basebackup.c:2133 +#: pg_basebackup.c:2211 #, c-format msgid "final receive failed: %s" msgstr "ошибка в конце передачи: %s" -#: pg_basebackup.c:2157 +#: pg_basebackup.c:2235 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "ожидание завершения потоковой передачи фоновым процессом..." -#: pg_basebackup.c:2161 +#: pg_basebackup.c:2239 #, c-format msgid "could not send command to background pipe: %m" msgstr "не удалось отправить команду в канал фонового процесса: %m" -#: pg_basebackup.c:2166 +#: pg_basebackup.c:2244 #, c-format msgid "could not wait for child process: %m" msgstr "сбой при ожидании дочернего процесса: %m" -#: pg_basebackup.c:2168 +#: pg_basebackup.c:2246 #, c-format msgid "child %d died, expected %d" msgstr "завершился дочерний процесс %d вместо ожидаемого %d" -#: pg_basebackup.c:2170 streamutil.c:91 streamutil.c:197 +#: pg_basebackup.c:2248 streamutil.c:92 streamutil.c:207 streamutil.c:319 #, c-format msgid "%s" msgstr "%s" -#: pg_basebackup.c:2190 +#: pg_basebackup.c:2268 #, c-format msgid "could not wait for child thread: %m" msgstr "сбой при ожидании дочернего потока: %m" -#: pg_basebackup.c:2195 +#: pg_basebackup.c:2273 #, c-format msgid "could not get child thread exit status: %m" msgstr "не удалось получить состояние завершения дочернего потока: %m" -#: pg_basebackup.c:2198 +#: pg_basebackup.c:2276 #, c-format msgid "child thread exited with error %u" msgstr "дочерний поток завершился с ошибкой %u" -#: pg_basebackup.c:2227 +#: pg_basebackup.c:2305 #, c-format msgid "syncing data to disk ..." msgstr "сохранение данных на диске..." -#: pg_basebackup.c:2252 +#: pg_basebackup.c:2330 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "переименование backup_manifest.tmp в backup_manifest" -#: pg_basebackup.c:2272 +#: pg_basebackup.c:2350 #, c-format msgid "base backup completed" msgstr "базовое резервное копирование завершено" -#: pg_basebackup.c:2361 +#: pg_basebackup.c:2436 +#, c-format +msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" +msgstr "" +"неверный аргумент режима контрольных точек \"%s\"; должен быть \"fast\" или " +"\"spread\"" + +#: pg_basebackup.c:2454 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "неверный формат вывода \"%s\", должен быть \"plain\" или \"tar\"" -#: pg_basebackup.c:2405 +#: pg_basebackup.c:2535 #, c-format msgid "" "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" @@ -1071,137 +1239,167 @@ msgstr "" "неверный аргумент для wal-method — \"%s\", допускается только \"fetch\", " "\"stream\" или \"none\"" -#: pg_basebackup.c:2435 -#, c-format -msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" -msgstr "" -"неверный аргумент режима контрольных точек \"%s\"; должен быть \"fast\" или " -"\"spread\"" - -#: pg_basebackup.c:2486 pg_basebackup.c:2498 pg_basebackup.c:2520 -#: pg_basebackup.c:2532 pg_basebackup.c:2538 pg_basebackup.c:2590 -#: pg_basebackup.c:2601 pg_basebackup.c:2611 pg_basebackup.c:2617 -#: pg_basebackup.c:2624 pg_basebackup.c:2636 pg_basebackup.c:2648 -#: pg_basebackup.c:2656 pg_basebackup.c:2669 pg_basebackup.c:2675 -#: pg_basebackup.c:2684 pg_basebackup.c:2696 pg_basebackup.c:2707 -#: pg_basebackup.c:2715 pg_receivewal.c:814 pg_receivewal.c:826 -#: pg_receivewal.c:833 pg_receivewal.c:842 pg_receivewal.c:849 -#: pg_receivewal.c:859 pg_recvlogical.c:837 pg_recvlogical.c:849 -#: pg_recvlogical.c:859 pg_recvlogical.c:866 pg_recvlogical.c:873 -#: pg_recvlogical.c:880 pg_recvlogical.c:887 pg_recvlogical.c:894 -#: pg_recvlogical.c:901 pg_recvlogical.c:908 +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2037 pg_createsubscriber.c:2047 +#: pg_createsubscriber.c:2055 pg_createsubscriber.c:2083 +#: pg_createsubscriber.c:2115 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_basebackup.c:2496 pg_receivewal.c:824 pg_recvlogical.c:847 +#: pg_basebackup.c:2584 pg_createsubscriber.c:2045 pg_receivewal.c:758 +#: pg_recvlogical.c:863 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_basebackup.c:2519 +#: pg_basebackup.c:2607 #, c-format msgid "cannot specify both format and backup target" msgstr "указать и формат, и получателя копии одновременно нельзя" -#: pg_basebackup.c:2531 +#: pg_basebackup.c:2619 #, c-format msgid "must specify output directory or backup target" msgstr "необходимо указать выходной каталог или получателя копии" -#: pg_basebackup.c:2537 +#: pg_basebackup.c:2625 #, c-format msgid "cannot specify both output directory and backup target" msgstr "указать и выходной каталог, и получателя копии одновременно нельзя" -#: pg_basebackup.c:2567 pg_receivewal.c:868 +#: pg_basebackup.c:2655 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "нераспознанный алгоритм сжатия: \"%s\"" -#: pg_basebackup.c:2573 pg_receivewal.c:875 +#: pg_basebackup.c:2661 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "неправильное указание сжатия: %s" -#: pg_basebackup.c:2589 +#: pg_basebackup.c:2677 #, c-format msgid "" "client-side compression is not possible when a backup target is specified" msgstr "сжатие на стороне клиента невозможно при указании получателя копии" -#: pg_basebackup.c:2600 +#: pg_basebackup.c:2688 #, c-format msgid "only tar mode backups can be compressed" msgstr "сжиматься могут только резервные копии в архиве tar" -#: pg_basebackup.c:2610 +#: pg_basebackup.c:2698 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "потоковая передача WAL невозможна при указании получателя копии" -#: pg_basebackup.c:2616 +#: pg_basebackup.c:2704 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "транслировать журналы предзаписи в режиме tar в поток stdout нельзя" -#: pg_basebackup.c:2623 +#: pg_basebackup.c:2711 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "слоты репликации можно использовать только при потоковой передаче WAL" -#: pg_basebackup.c:2635 +#: pg_basebackup.c:2723 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot нельзя использовать с именем слота" #. translator: second %s is an option name -#: pg_basebackup.c:2646 pg_receivewal.c:840 +#: pg_basebackup.c:2734 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "для %s необходимо задать слот с помощью параметра --slot" -#: pg_basebackup.c:2654 pg_basebackup.c:2694 pg_basebackup.c:2705 -#: pg_basebackup.c:2713 +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 #, c-format msgid "%s and %s are incompatible options" msgstr "параметры %s и %s несовместимы" -#: pg_basebackup.c:2668 +#: pg_basebackup.c:2756 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "расположение каталога WAL нельзя указать вместе с получателем копии" -#: pg_basebackup.c:2674 +#: pg_basebackup.c:2762 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "расположение каталога WAL можно указать только в режиме plain" -#: pg_basebackup.c:2683 +#: pg_basebackup.c:2771 #, c-format msgid "WAL directory location must be an absolute path" msgstr "расположение каталога WAL должно определяться абсолютным путём" -#: pg_basebackup.c:2784 +#: pg_basebackup.c:2871 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не удалось создать символическую ссылку \"%s\": %m" -#: pg_basebackup.c:2786 +#: pg_createsubscriber.c:169 #, c-format -msgid "symlinks are not supported on this platform" -msgstr "символические ссылки не поддерживаются в этой ОС" +msgid "failed after the end of recovery" +msgstr "ошибка после окончания восстановления" -#: pg_receivewal.c:79 +#: pg_createsubscriber.c:170 #, c-format msgid "" -"%s receives PostgreSQL streaming write-ahead logs.\n" +"The target server cannot be used as a physical replica anymore. You must " +"recreate the physical replica before continuing." +msgstr "" +"Целевой сервер больше не может использоваться как физическая реплика. Чтобы " +"продолжить, физическую реплику необходимо пересоздать." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "" +"publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "на главном сервере осталась публикация \"%s\", созданная в базе \"%s\"" + +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "Удалите эту публикацию и попробуйте повторить операцию." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "" +"replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "" +"на главном сервере остался слот репликации \"%s\", созданный в базе \"%s\"" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1260 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "" +"Удалите этот слот репликации незамедлительно во избежание накопления файлов " +"WAL." + +#: pg_createsubscriber.c:219 +#, c-format +msgid "" +"%s creates a new logical replica from a standby server.\n" "\n" msgstr "" -"%s получает транслируемые журналы предзаписи PostgreSQL.\n" +"%s превращает резервный сервер в логическую реплику.\n" "\n" -#: pg_receivewal.c:83 pg_recvlogical.c:84 +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 #, c-format msgid "" "\n" @@ -1210,7 +1408,681 @@ msgstr "" "\n" "Параметры:\n" -#: pg_receivewal.c:84 +#: pg_createsubscriber.c:224 +#, c-format +msgid "" +" -d, --database=DBNAME database in which to create a " +"subscription\n" +msgstr "" +" -d, --database=ИМЯ_БД база, в которой будет создана подписка\n" + +#: pg_createsubscriber.c:225 +#, c-format +msgid "" +" -D, --pgdata=DATADIR location for the subscriber data " +"directory\n" +msgstr "" +" -D, --pgdata=КАТ_ДАННЫХ расположение каталога данных подписчика\n" + +#: pg_createsubscriber.c:226 +#, c-format +msgid "" +" -n, --dry-run dry run, just show what would be done\n" +msgstr "" +" -n, --dry-run показать, какие действия будут выполнены,\n" +" но не выполнять их\n" + +#: pg_createsubscriber.c:227 +#, c-format +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr "" +" -p, --subscriber-port=ПОРТ номер порта подписчика (по умолчанию: %s)\n" + +#: pg_createsubscriber.c:228 +#, c-format +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr "" +" -P, --publisher-server=СТРОКА строка подключения к серверу публикации\n" + +#: pg_createsubscriber.c:229 +#, c-format +msgid "" +" -s, --socketdir=DIR socket directory to use (default current " +"dir.)\n" +msgstr "" +" -s, --socketdir=КАТАЛОГ каталог сокетов (по умолчанию текущий)\n" + +#: pg_createsubscriber.c:230 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr "" +" -t, --recovery-timeout=СЕК время ожидания окончания восстановления\n" + +#: pg_createsubscriber.c:231 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr "" +" -U, --subscriber-username=ИМЯ имя пользователя для подключения " +"подписчика\n" + +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose выводить подробные сообщения\n" + +#: pg_createsubscriber.c:233 +#, c-format +msgid "" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" +msgstr "" +" --config-file=ИМЯ_ФАЙЛА использовать указанный основной файл\n" +" конфигурации сервера при запуске целевого\n" +" кластера\n" + +#: pg_createsubscriber.c:235 +#, c-format +msgid " --publication=NAME publication name\n" +msgstr " --publication=ИМЯ имя публикации\n" + +#: pg_createsubscriber.c:236 +#, c-format +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=ИМЯ имя слота репликации\n" + +#: pg_createsubscriber.c:237 +#, c-format +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=ИМЯ имя подписки\n" + +#: pg_createsubscriber.c:238 +#, c-format +msgid "" +" -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_createsubscriber.c:239 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_createsubscriber.c:282 +#, c-format +msgid "could not parse connection string: %s" +msgstr "не удалось разобрать строку подключения: %s" + +#: pg_createsubscriber.c:359 +#, c-format +msgid "" +"program \"%s\" is needed by %s but was not found in the same directory as " +"\"%s\"" +msgstr "программа \"%s\" нужна для %s, но она не найдена в каталоге \"%s\"" + +#: pg_createsubscriber.c:362 +#, c-format +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "" +"программа \"%s\" найдена программой \"%s\", но её версия отличается от " +"версии %s" + +#: pg_createsubscriber.c:382 +#, c-format +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "проверяется, является ли каталог \"%s\" каталогом данных кластера" + +#: pg_createsubscriber.c:388 +#, c-format +msgid "data directory \"%s\" does not exist" +msgstr "каталог данных \"%s\" не существует" + +#: pg_createsubscriber.c:396 +#, c-format +msgid "directory \"%s\" is not a database cluster directory" +msgstr "каталог \"%s\" не является каталогом кластера баз данных" + +#: pg_createsubscriber.c:513 +#, c-format +msgid "connection to database failed: %s" +msgstr "не удалось подключиться к базе: %s" + +#: pg_createsubscriber.c:526 +#, c-format +msgid "could not clear search_path: %s" +msgstr "не удалось очистить search_path: %s" + +#: pg_createsubscriber.c:566 +#, c-format +msgid "getting system identifier from publisher" +msgstr "получение идентификатора системы с сервера публикации" + +#: pg_createsubscriber.c:573 +#, c-format +msgid "could not get system identifier: %s" +msgstr "не удалось получить идентификатор системы: %s" + +#: pg_createsubscriber.c:579 +#, c-format +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "" +"не удалось получить идентификатор системы; получено строк: %d, ожидалось: %d" + +#: pg_createsubscriber.c:586 +#, c-format +msgid "system identifier is %llu on publisher" +msgstr "идентификатор системы на стороне публикации: %llu" + +#: pg_createsubscriber.c:607 +#, c-format +msgid "getting system identifier from subscriber" +msgstr "получение идентификатора системы с подписчика" + +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 +#, c-format +msgid "control file appears to be corrupt" +msgstr "управляющий файл, по-видимому, испорчен" + +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 +#, c-format +msgid "system identifier is %llu on subscriber" +msgstr "идентификатор системы на подписчике: %llu" + +#: pg_createsubscriber.c:637 +#, c-format +msgid "modifying system identifier of subscriber" +msgstr "изменение идентификатора системы на подписчике" + +#: pg_createsubscriber.c:659 +#, c-format +msgid "running pg_resetwal on the subscriber" +msgstr "запуск pg_resetwal на подписчике" + +#: pg_createsubscriber.c:671 +#, c-format +msgid "subscriber successfully changed the system identifier" +msgstr "идентификатор системы на подписчике успешно изменён" + +#: pg_createsubscriber.c:673 +#, c-format +msgid "could not change system identifier of subscriber: %s" +msgstr "изменить идентификатор системы на подписчике не удалось: %s" + +#: pg_createsubscriber.c:697 +#, c-format +msgid "could not obtain database OID: %s" +msgstr "получить OID базы данных не удалось: %s" + +#: pg_createsubscriber.c:704 +#, c-format +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "получить OID базы данных не удалось; получено строк: %d, ожидалось: %d" + +#: pg_createsubscriber.c:776 +#, c-format +msgid "create replication slot \"%s\" on publisher" +msgstr "создаётся слот репликации \"%s\" на подписчике" + +#: pg_createsubscriber.c:796 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "не удалось записать дополнительную запись WAL: %s" + +#: pg_createsubscriber.c:822 +#, c-format +msgid "could not obtain recovery progress: %s" +msgstr "не удалось получить состояние восстановления: %s" + +#: pg_createsubscriber.c:854 +#, c-format +msgid "checking settings on publisher" +msgstr "проверка параметров на стороне публикации" + +#: pg_createsubscriber.c:864 +#, c-format +msgid "primary server cannot be in recovery" +msgstr "главный сервер не должен быть в состоянии восстановления" + +#: pg_createsubscriber.c:888 +#, c-format +msgid "could not obtain publisher settings: %s" +msgstr "не удалось получить параметры с сервера публикации: %s" + +#: pg_createsubscriber.c:914 +#, c-format +msgid "publisher requires wal_level >= \"logical\"" +msgstr "на стороне публикации требуется значение wal_level >= \"logical\"" + +#: pg_createsubscriber.c:920 +#, c-format +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "" +"на стороне публикации требуется слотов репликации: %d, но доступно всего %d" + +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Увеличьте значение параметра конфигурации \"%s\" как минимум до %d." + +#: pg_createsubscriber.c:929 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "" +"на стороне публикации требуется процессов-передатчиков WAL: %d, но доступно " +"всего %d" + +#: pg_createsubscriber.c:938 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "параметр two_phase для слотов репликации не будет включён" + +#: pg_createsubscriber.c:939 +#, c-format +msgid "" +"Subscriptions will be created with the two_phase option disabled. Prepared " +"transactions will be replicated at COMMIT PREPARED." +msgstr "" +"Подписки будут созданы с отключённым параметром two_phase. Подготовленные " +"транзакции будут реплицироваться в момент выполнения COMMIT PREPARED." + +#: pg_createsubscriber.c:971 +#, c-format +msgid "checking settings on subscriber" +msgstr "проверка параметров на подписчике" + +#: pg_createsubscriber.c:978 +#, c-format +msgid "target server must be a standby" +msgstr "целевой сервер должен быть резервным" + +#: pg_createsubscriber.c:1002 +#, c-format +msgid "could not obtain subscriber settings: %s" +msgstr "получить параметры подписчика не удалось: %s" + +#: pg_createsubscriber.c:1026 +#, c-format +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "подписчику требуется слотов репликации: %d, но доступно всего %d" + +#: pg_createsubscriber.c:1035 +#, c-format +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "" +"подписчику требуется процессов логической репликации: %d, но доступно всего " +"%d" + +#: pg_createsubscriber.c:1044 +#, c-format +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "подписчику требуется рабочих процессов: %d, но доступно всего %d" + +#: pg_createsubscriber.c:1079 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "удаление подписки \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1088 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "удалить подписку \"%s\" не получилось: %s" + +#: pg_createsubscriber.c:1123 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "получить уже существующие подписки не удалось: %s" + +#: pg_createsubscriber.c:1258 +#, c-format +msgid "could not drop replication slot \"%s\" on primary" +msgstr "удалить слот репликации \"%s\" на главном сервере не получилось" + +#: pg_createsubscriber.c:1292 +#, c-format +msgid "could not obtain failover replication slot information: %s" +msgstr "получить информацию о переносимом слоте репликации не удалось: %s" + +#: pg_createsubscriber.c:1294 pg_createsubscriber.c:1303 +#, c-format +msgid "" +"Drop the failover replication slots on subscriber soon to avoid retention of " +"WAL files." +msgstr "" +"Удалите переносимые слоты репликации на подписчике незамедлительно во " +"избежание накопления файлов WAL." + +#: pg_createsubscriber.c:1302 +#, c-format +msgid "could not drop failover replication slot" +msgstr "удалить переносимый слот репликации не получилось" + +#: pg_createsubscriber.c:1324 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "создание слота репликации \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1342 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "создать слот репликации \"%s\" в базе \"%s\" не удалось: %s" + +#: pg_createsubscriber.c:1372 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "удаление слота репликации \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1388 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "удалить слот репликации \"%s\" в базе \"%s\" не получилось: %s" + +#: pg_createsubscriber.c:1409 +#, c-format +msgid "pg_ctl failed with exit code %d" +msgstr "команда pg_ctl завершилась с кодом ошибки %d" + +#: pg_createsubscriber.c:1414 +#, c-format +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "команда pg_ctl была прервана исключением 0x%X" + +#: pg_createsubscriber.c:1416 +#, c-format +msgid "" +"See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "" +"Описание этого шестнадцатеричного значения ищите во включаемом C-файле " +"\"ntstatus.h\"" + +#: pg_createsubscriber.c:1418 +#, c-format +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "команда pg_ctl была завершена сигналом %d: %s" + +#: pg_createsubscriber.c:1424 +#, c-format +msgid "pg_ctl exited with unrecognized status %d" +msgstr "команда pg_ctl завершилась с нераспознанным кодом состояния %d" + +#: pg_createsubscriber.c:1427 +#, c-format +msgid "The failed command was: %s" +msgstr "Ошибку вызвала команда: %s" + +#: pg_createsubscriber.c:1473 +#, c-format +msgid "server was started" +msgstr "сервер был запущен" + +#: pg_createsubscriber.c:1488 +#, c-format +msgid "server was stopped" +msgstr "сервер был остановлен" + +#: pg_createsubscriber.c:1507 +#, c-format +msgid "waiting for the target server to reach the consistent state" +msgstr "ожидание достижения целевым сервером согласованного состояния" + +#: pg_createsubscriber.c:1530 +#, c-format +msgid "recovery timed out" +msgstr "тайм-аут при восстановлении" + +#: pg_createsubscriber.c:1543 +#, c-format +msgid "server did not end recovery" +msgstr "сервер не завершил восстановление" + +#: pg_createsubscriber.c:1545 +#, c-format +msgid "target server reached the consistent state" +msgstr "целевой сервер достиг согласованного состояния" + +#: pg_createsubscriber.c:1546 +#, c-format +msgid "" +"If pg_createsubscriber fails after this point, you must recreate the " +"physical replica before continuing." +msgstr "" +"Если в работе pg_createsubscriber произойдёт сбой после этого момента, " +"продолжение возможно только после пересоздания физической реплики." + +#: pg_createsubscriber.c:1573 +#, c-format +msgid "could not obtain publication information: %s" +msgstr "получить информацию о публикации не удалось: %s" + +#: pg_createsubscriber.c:1587 +#, c-format +msgid "publication \"%s\" already exists" +msgstr "публикация \"%s\" уже существует" + +#: pg_createsubscriber.c:1588 +#, c-format +msgid "Consider renaming this publication before continuing." +msgstr "Чтобы продолжить, её можно переименовать." + +#: pg_createsubscriber.c:1595 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "создаётся публикация \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1608 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "создать публикацию \"%s\" в базе \"%s\" не удалось: %s" + +#: pg_createsubscriber.c:1637 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "удаляется публикация \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1651 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "удалить публикацию \"%s\" в базе \"%s\" не получилось: %s" + +#: pg_createsubscriber.c:1697 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "создаётся подписка \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1718 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "создать подписку \"%s\" в базе \"%s\" не удалось: %s" + +#: pg_createsubscriber.c:1763 +#, c-format +msgid "could not obtain subscription OID: %s" +msgstr "получить OID подписки не удалось: %s" + +#: pg_createsubscriber.c:1770 +#, c-format +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "получить OID подписки не удалось; получено строк: %d, ожидалось: %d" + +#: pg_createsubscriber.c:1794 +#, c-format +msgid "" +"setting the replication progress (node name \"%s\", LSN %s) in database " +"\"%s\"" +msgstr "отражение состояния репликации (имя узла \"%s\", LSN %s) в базе \"%s\"" + +#: pg_createsubscriber.c:1809 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "не удалось передать состояние репликации для подписки \"%s\": %s" + +#: pg_createsubscriber.c:1840 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "включение подписки \"%s\" в базе \"%s\"" + +#: pg_createsubscriber.c:1852 +#, c-format +msgid "could not enable subscription \"%s\": %s" +msgstr "включить подписку \"%s\" не удалось: %s" + +#: pg_createsubscriber.c:1944 +#, c-format +msgid "cannot be executed by \"root\"" +msgstr "программу не должен запускать root" + +#: pg_createsubscriber.c:1945 +#, c-format +msgid "You must run %s as the PostgreSQL superuser." +msgstr "Запускать %s нужно от имени суперпользователя PostgreSQL." + +#: pg_createsubscriber.c:1966 +#, c-format +msgid "database \"%s\" specified more than once" +msgstr "база \"%s\" указана неоднократно" + +#: pg_createsubscriber.c:2007 +#, c-format +msgid "publication \"%s\" specified more than once" +msgstr "публикация \"%s\" указана неоднократно" + +#: pg_createsubscriber.c:2019 +#, c-format +msgid "replication slot \"%s\" specified more than once" +msgstr "слот репликации \"%s\" указан неоднократно" + +#: pg_createsubscriber.c:2031 +#, c-format +msgid "subscription \"%s\" specified more than once" +msgstr "подписка \"%s\" указана неоднократно" + +#: pg_createsubscriber.c:2054 +#, c-format +msgid "no subscriber data directory specified" +msgstr "каталог данных подписчика не указан" + +#: pg_createsubscriber.c:2065 +#, c-format +msgid "could not determine current directory" +msgstr "не удалось определить текущий каталог" + +#: pg_createsubscriber.c:2082 +#, c-format +msgid "no publisher connection string specified" +msgstr "строка подключения к серверу публикации не указана" + +#: pg_createsubscriber.c:2086 +#, c-format +msgid "validating publisher connection string" +msgstr "проверяется строка подключения к серверу публикации" + +#: pg_createsubscriber.c:2092 +#, c-format +msgid "validating subscriber connection string" +msgstr "проверяется строка подключения к подписчику" + +#: pg_createsubscriber.c:2097 +#, c-format +msgid "no database was specified" +msgstr "база данных не указана" + +#: pg_createsubscriber.c:2109 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "имя базы \"%s\" извлечено из строки подключения к серверу публикации" + +#: pg_createsubscriber.c:2114 +#, c-format +msgid "no database name specified" +msgstr "имя базы данных не указано" + +#: pg_createsubscriber.c:2124 +#, c-format +msgid "wrong number of publication names specified" +msgstr "указано неверное количество имён публикаций" + +#: pg_createsubscriber.c:2125 +#, c-format +msgid "" +"The number of specified publication names (%d) must match the number of " +"specified database names (%d)." +msgstr "" +"Количество указанных имён публикаций (%d) должно совпадать с количеством " +"указанных имён баз (%d)." + +#: pg_createsubscriber.c:2131 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "указано неверное количество имён подписок" + +#: pg_createsubscriber.c:2132 +#, c-format +msgid "" +"The number of specified subscription names (%d) must match the number of " +"specified database names (%d)." +msgstr "" +"Количество указанных имён подписок (%d) должно совпадать с количеством " +"указанных имён баз (%d)." + +#: pg_createsubscriber.c:2138 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "указано неверное количество имён слотов репликации" + +#: pg_createsubscriber.c:2139 +#, c-format +msgid "" +"The number of specified replication slot names (%d) must match the number of " +"specified database names (%d)." +msgstr "" +"Количество указанных имён слотов репликации (%d) должно совпадать с " +"количеством указанных имён баз (%d)." + +#: pg_createsubscriber.c:2168 +#, c-format +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "" +"каталог данных подписчика не является копией исходного кластера баз данных" + +#: pg_createsubscriber.c:2181 +#, c-format +msgid "standby server is running" +msgstr "резервный сервер запущен" + +#: pg_createsubscriber.c:2182 +#, c-format +msgid "Stop the standby server and try again." +msgstr "Остановите резервный сервер и повторите попытку." + +#: pg_createsubscriber.c:2191 +#, c-format +msgid "starting the standby server with command-line options" +msgstr "резервный сервер запускается с параметрами командной строки" + +#: pg_createsubscriber.c:2207 pg_createsubscriber.c:2242 +#, c-format +msgid "stopping the subscriber" +msgstr "подписчик останавливается" + +#: pg_createsubscriber.c:2221 +#, c-format +msgid "starting the subscriber" +msgstr "подписчик запускается" + +#: pg_createsubscriber.c:2250 +#, c-format +msgid "Done!" +msgstr "Готово!" + +#: pg_receivewal.c:77 +#, c-format +msgid "" +"%s receives PostgreSQL streaming write-ahead logs.\n" +"\n" +msgstr "" +"%s получает транслируемые журналы предзаписи PostgreSQL.\n" +"\n" + +#: pg_receivewal.c:82 #, c-format msgid "" " -D, --directory=DIR receive write-ahead log files into this directory\n" @@ -1218,14 +2090,14 @@ msgstr "" " -D, --directory=ПУТЬ сохранять файлы журнала предзаписи в данный " "каталог\n" -#: pg_receivewal.c:85 pg_recvlogical.c:85 +#: pg_receivewal.c:83 pg_recvlogical.c:93 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr "" " -E, --endpos=LSN определяет позицию, после которой нужно " "остановиться\n" -#: pg_receivewal.c:86 pg_recvlogical.c:89 +#: pg_receivewal.c:84 pg_recvlogical.c:97 #, c-format msgid "" " --if-not-exists do not error if slot already exists when creating a " @@ -1234,12 +2106,12 @@ msgstr "" " --if-not-exists не выдавать ошибку при попытке создать уже " "существующий слот\n" -#: pg_receivewal.c:87 pg_recvlogical.c:91 +#: pg_receivewal.c:85 pg_recvlogical.c:99 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop прерывать работу при потере соединения\n" -#: pg_receivewal.c:88 +#: pg_receivewal.c:86 #, c-format msgid "" " --no-sync do not wait for changes to be written safely to " @@ -1247,7 +2119,7 @@ msgid "" msgstr "" " --no-sync не ждать надёжного сохранения изменений на диске\n" -#: pg_receivewal.c:89 pg_recvlogical.c:96 +#: pg_receivewal.c:87 pg_recvlogical.c:104 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -1258,7 +2130,7 @@ msgstr "" " интервал между отправкой статусных пакетов серверу " "(по умолчанию: %d)\n" -#: pg_receivewal.c:92 +#: pg_receivewal.c:90 #, c-format msgid "" " --synchronous flush write-ahead log immediately after writing\n" @@ -1266,7 +2138,7 @@ msgstr "" " --synchronous сбрасывать журнал предзаписи сразу после записи\n" # well-spelled: ИНФО -#: pg_receivewal.c:95 +#: pg_receivewal.c:93 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1275,7 +2147,7 @@ msgstr "" " -Z, --compress=МЕТОД[:ДОП_ИНФО]\n" " выполнять сжатие как указано\n" -#: pg_receivewal.c:105 +#: pg_receivewal.c:103 #, c-format msgid "" "\n" @@ -1284,7 +2156,7 @@ msgstr "" "\n" "Дополнительные действия:\n" -#: pg_receivewal.c:106 pg_recvlogical.c:81 +#: pg_receivewal.c:104 pg_recvlogical.c:89 #, c-format msgid "" " --create-slot create a new replication slot (for the slot's name " @@ -1293,7 +2165,7 @@ msgstr "" " --create-slot создать новый слот репликации (имя слота задаёт " "параметр --slot)\n" -#: pg_receivewal.c:107 pg_recvlogical.c:82 +#: pg_receivewal.c:105 pg_recvlogical.c:90 #, c-format msgid "" " --drop-slot drop the replication slot (for the slot's name see " @@ -1302,57 +2174,57 @@ msgstr "" " --drop-slot удалить слот репликации (имя слота задаёт параметр " "--slot)\n" -#: pg_receivewal.c:252 +#: pg_receivewal.c:191 #, c-format msgid "finished segment at %X/%X (timeline %u)" msgstr "завершён сегмент %X/%X (линия времени %u)" -#: pg_receivewal.c:259 +#: pg_receivewal.c:198 #, c-format msgid "stopped log streaming at %X/%X (timeline %u)" msgstr "завершена передача журнала с позиции %X/%X (линия времени %u)" -#: pg_receivewal.c:275 +#: pg_receivewal.c:214 #, c-format msgid "switched to timeline %u at %X/%X" msgstr "переключение на линию времени %u (позиция %X/%X)" -#: pg_receivewal.c:285 +#: pg_receivewal.c:224 pg_recvlogical.c:1053 #, c-format msgid "received interrupt signal, exiting" msgstr "получен сигнал прерывания, работа завершается" -#: pg_receivewal.c:317 +#: pg_receivewal.c:256 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не удалось закрыть каталог \"%s\": %m" -#: pg_receivewal.c:384 +#: pg_receivewal.c:323 #, c-format msgid "segment file \"%s\" has incorrect size %lld, skipping" msgstr "файл сегмента \"%s\" имеет неправильный размер %lld, файл пропускается" -#: pg_receivewal.c:401 +#: pg_receivewal.c:340 #, c-format msgid "could not open compressed file \"%s\": %m" msgstr "не удалось открыть сжатый файл \"%s\": %m" -#: pg_receivewal.c:404 +#: pg_receivewal.c:343 #, c-format msgid "could not seek in compressed file \"%s\": %m" msgstr "ошибка позиционирования в сжатом файле \"%s\": %m" -#: pg_receivewal.c:410 +#: pg_receivewal.c:349 #, c-format msgid "could not read compressed file \"%s\": %m" msgstr "не удалось прочитать сжатый файл \"%s\": %m" -#: pg_receivewal.c:413 +#: pg_receivewal.c:352 #, c-format msgid "could not read compressed file \"%s\": read %d of %zu" msgstr "не удалось прочитать сжатый файл \"%s\" (прочитано байт: %d из %zu)" -#: pg_receivewal.c:423 +#: pg_receivewal.c:362 #, c-format msgid "" "compressed segment file \"%s\" has incorrect uncompressed size %d, skipping" @@ -1360,27 +2232,22 @@ msgstr "" "файл сжатого сегмента \"%s\" имеет неправильный исходный размер %d, файл " "пропускается" -#: pg_receivewal.c:451 +#: pg_receivewal.c:390 #, c-format msgid "could not create LZ4 decompression context: %s" msgstr "не удалось создать контекст распаковки LZ4: %s" -#: pg_receivewal.c:463 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не удалось прочитать файл \"%s\": %m" - -#: pg_receivewal.c:481 +#: pg_receivewal.c:420 #, c-format msgid "could not decompress file \"%s\": %s" msgstr "не удалось распаковать файл \"%s\": %s" -#: pg_receivewal.c:504 +#: pg_receivewal.c:443 #, c-format msgid "could not free LZ4 decompression context: %s" msgstr "не удалось освободить контекст распаковки LZ4: %s" -#: pg_receivewal.c:509 +#: pg_receivewal.c:448 #, c-format msgid "" "compressed segment file \"%s\" has incorrect uncompressed size %zu, skipping" @@ -1388,7 +2255,7 @@ msgstr "" "файл сжатого сегмента \"%s\" имеет неправильный исходный размер %zu, файл " "пропускается" -#: pg_receivewal.c:514 +#: pg_receivewal.c:453 #, c-format msgid "" "cannot check file \"%s\": compression with %s not supported by this build" @@ -1396,37 +2263,37 @@ msgstr "" "не удалось проверить файл \"%s\": сжатие методом %s не поддерживается данной " "сборкой" -#: pg_receivewal.c:641 +#: pg_receivewal.c:578 #, c-format msgid "starting log streaming at %X/%X (timeline %u)" msgstr "начало передачи журнала с позиции %X/%X (линия времени %u)" -#: pg_receivewal.c:783 pg_recvlogical.c:785 +#: pg_receivewal.c:693 pg_recvlogical.c:801 #, c-format msgid "could not parse end position \"%s\"" msgstr "не удалось разобрать конечную позицию \"%s\"" -#: pg_receivewal.c:832 +#: pg_receivewal.c:766 #, c-format msgid "cannot use --create-slot together with --drop-slot" msgstr "--create-slot нельзя применять вместе с --drop-slot" -#: pg_receivewal.c:848 +#: pg_receivewal.c:782 #, c-format msgid "cannot use --synchronous together with --no-sync" msgstr "--synchronous нельзя применять вместе с --no-sync" -#: pg_receivewal.c:858 +#: pg_receivewal.c:792 #, c-format msgid "no target directory specified" msgstr "целевой каталог не указан" -#: pg_receivewal.c:882 +#: pg_receivewal.c:816 #, c-format msgid "compression with %s is not yet supported" msgstr "метод сжатия %s ещё не поддерживается" -#: pg_receivewal.c:924 +#: pg_receivewal.c:859 #, c-format msgid "" "replication connection using slot \"%s\" is unexpectedly database specific" @@ -1434,28 +2301,28 @@ msgstr "" "подключение для репликации через слот \"%s\" оказалось привязано к базе " "данных" -#: pg_receivewal.c:943 pg_recvlogical.c:955 +#: pg_receivewal.c:878 pg_recvlogical.c:972 #, c-format msgid "dropping replication slot \"%s\"" msgstr "удаление слота репликации \"%s\"" -#: pg_receivewal.c:954 pg_recvlogical.c:965 +#: pg_receivewal.c:889 pg_recvlogical.c:982 #, c-format msgid "creating replication slot \"%s\"" msgstr "создание слота репликации \"%s\"" -#: pg_receivewal.c:983 pg_recvlogical.c:989 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "отключение" #. translator: check source for value for %d -#: pg_receivewal.c:987 pg_recvlogical.c:993 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "отключение; через %d сек. последует повторное подключение" -#: pg_recvlogical.c:76 +#: pg_recvlogical.c:84 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -1464,7 +2331,7 @@ msgstr "" "%s управляет потоками логического декодирования PostgreSQL.\n" "\n" -#: pg_recvlogical.c:80 +#: pg_recvlogical.c:88 #, c-format msgid "" "\n" @@ -1473,7 +2340,7 @@ msgstr "" "\n" "Действие, которое будет выполнено:\n" -#: pg_recvlogical.c:83 +#: pg_recvlogical.c:91 #, c-format msgid "" " --start start streaming in a replication slot (for the " @@ -1482,13 +2349,13 @@ msgstr "" " --start начать передачу в слоте репликации (имя слота " "задаёт параметр --slot)\n" -#: pg_recvlogical.c:86 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr "" " -f, --file=ФАЙЛ сохранять журнал в этот файл, - обозначает stdout\n" -#: pg_recvlogical.c:87 +#: pg_recvlogical.c:95 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -1499,7 +2366,7 @@ msgstr "" " периодичность сброса на диск выходного файла (по " "умолчанию: %d)\n" -#: pg_recvlogical.c:90 +#: pg_recvlogical.c:98 #, c-format msgid "" " -I, --startpos=LSN where in an existing slot should the streaming " @@ -1508,7 +2375,7 @@ msgstr "" " -I, --startpos=LSN определяет, с какой позиции в существующем слоте " "начнётся передача\n" -#: pg_recvlogical.c:92 +#: pg_recvlogical.c:100 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -1520,19 +2387,19 @@ msgstr "" "необязательным\n" " значением модулю вывода\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr "" " -P, --plugin=МОДУЛЬ использовать заданный модуль вывода (по умолчанию: " "%s)\n" -#: pg_recvlogical.c:98 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=ИМЯ_СЛОТА имя слота логической репликации\n" -#: pg_recvlogical.c:99 +#: pg_recvlogical.c:107 #, c-format msgid "" " -t, --two-phase enable decoding of prepared transactions when " @@ -1541,160 +2408,160 @@ msgstr "" " -t, --two-phase включить декодирование подготовленных транзакций " "при создании слота\n" -#: pg_recvlogical.c:104 +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=ИМЯ_БД целевая база данных\n" -#: pg_recvlogical.c:137 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "подтверждается запись до %X/%X, синхронизация с ФС до %X/%X (слот %s)" -#: pg_recvlogical.c:161 receivelog.c:366 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "не удалось отправить пакет ответа: %s" -#: pg_recvlogical.c:229 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "начало передачи журнала с позиции %X/%X (слот %s)" -#: pg_recvlogical.c:271 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "передача запущена" -#: pg_recvlogical.c:335 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "не удалось открыть файл протокола \"%s\": %m" -#: pg_recvlogical.c:364 receivelog.c:889 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "неверный сокет: %s" -#: pg_recvlogical.c:417 receivelog.c:917 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: pg_recvlogical.c:424 receivelog.c:967 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "не удалось получить данные из потока WAL: %s" -#: pg_recvlogical.c:466 pg_recvlogical.c:517 receivelog.c:1011 -#: receivelog.c:1074 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 +#: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "заголовок потока слишком мал: %d" -#: pg_recvlogical.c:501 receivelog.c:849 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "нераспознанный заголовок потока: \"%c\"" -#: pg_recvlogical.c:555 pg_recvlogical.c:567 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "не удалось записать %d Б в файл журнала \"%s\": %m" -#: pg_recvlogical.c:621 receivelog.c:648 receivelog.c:685 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "неожиданный конец потока репликации: %s" -#: pg_recvlogical.c:780 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "не удалось разобрать начальную позицию \"%s\"" -#: pg_recvlogical.c:858 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "слот не указан" -#: pg_recvlogical.c:865 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "целевой файл не задан" -#: pg_recvlogical.c:872 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "база данных не задана" -#: pg_recvlogical.c:879 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "необходимо задать минимум одно действие" -#: pg_recvlogical.c:886 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "--create-slot или --start нельзя применять вместе с --drop-slot" -#: pg_recvlogical.c:893 +#: pg_recvlogical.c:909 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "--create-slot или --drop-slot нельзя применять вместе с --startpos" -#: pg_recvlogical.c:900 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos можно задать только вместе с --start" -#: pg_recvlogical.c:907 +#: pg_recvlogical.c:923 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase можно задать только вместе с --create-slot" -#: pg_recvlogical.c:939 +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "" "не удалось установить подключение для репликации к определённой базе данных" -#: pg_recvlogical.c:1033 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "конечная позиция %X/%X достигнута при обработке keepalive" -#: pg_recvlogical.c:1036 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "конечная позиция %X/%X достигнута при обработке записи WAL %X/%X" -#: receivelog.c:68 +#: receivelog.c:66 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "не удалось создать файл статуса архива \"%s\": %s" -#: receivelog.c:75 +#: receivelog.c:73 #, c-format msgid "could not close archive status file \"%s\": %s" msgstr "не удалось закрыть файл статуса архива \"%s\": %s" -#: receivelog.c:123 +#: receivelog.c:122 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "не удалось получить размер файла журнала предзаписи \"%s\": %s" -#: receivelog.c:134 +#: receivelog.c:133 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "не удалось открыть существующий файл журнала предзаписи \"%s\": %s" -#: receivelog.c:143 +#: receivelog.c:142 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "" "не удалось сбросить на диск существующий файл журнала предзаписи \"%s\": %s" -#: receivelog.c:158 +#: receivelog.c:157 #, c-format msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" @@ -1705,42 +2572,37 @@ msgstr[1] "" msgstr[2] "" "файл журнала предзаписи \"%s\" имеет размер %zd Б, а должен — 0 или %d" -#: receivelog.c:174 +#: receivelog.c:175 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "не удалось открыть файл журнала предзаписи \"%s\": %s" -#: receivelog.c:208 -#, c-format -msgid "could not determine seek position in file \"%s\": %s" -msgstr "не удалось определить текущую позицию в файле \"%s\": %s" - -#: receivelog.c:223 +#: receivelog.c:216 #, c-format msgid "not renaming \"%s\", segment is not complete" msgstr "файл сегмента \"%s\" не переименовывается, так как он неполный" -#: receivelog.c:234 receivelog.c:323 receivelog.c:694 +#: receivelog.c:227 receivelog.c:317 receivelog.c:688 #, c-format msgid "could not close file \"%s\": %s" msgstr "не удалось закрыть файл \"%s\": %s" -#: receivelog.c:295 +#: receivelog.c:288 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "сервер сообщил неожиданное имя файла истории для линии времени %u: %s" -#: receivelog.c:303 +#: receivelog.c:297 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "не удалось создать файл истории линии времени \"%s\": %s" -#: receivelog.c:310 +#: receivelog.c:304 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "не удалось записать файл истории линии времени \"%s\": %s" -#: receivelog.c:400 +#: receivelog.c:394 #, c-format msgid "" "incompatible server version %s; client does not support streaming from " @@ -1749,7 +2611,7 @@ msgstr "" "несовместимая версия сервера %s; клиент не поддерживает репликацию с " "серверов версии ниже %s" -#: receivelog.c:409 +#: receivelog.c:403 #, c-format msgid "" "incompatible server version %s; client does not support streaming from " @@ -1758,7 +2620,7 @@ msgstr "" "несовместимая версия сервера %s; клиент не поддерживает репликацию с " "серверов версии выше %s" -#: receivelog.c:514 +#: receivelog.c:508 #, c-format msgid "" "system identifier does not match between base backup and streaming connection" @@ -1766,12 +2628,12 @@ msgstr "" "системный идентификатор базовой резервной копии отличается от идентификатора " "потоковой передачи" -#: receivelog.c:522 +#: receivelog.c:516 #, c-format msgid "starting timeline %u is not present in the server" msgstr "на сервере нет начальной линии времени %u" -#: receivelog.c:561 +#: receivelog.c:555 #, c-format msgid "" "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, " @@ -1780,12 +2642,12 @@ msgstr "" "сервер вернул неожиданный ответ на команду TIMELINE_HISTORY; получено строк: " "%d, полей: %d, а ожидалось строк: %d, полей: %d" -#: receivelog.c:632 +#: receivelog.c:626 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "сервер неожиданно сообщил линию времени %u после линии времени %u" -#: receivelog.c:638 +#: receivelog.c:632 #, c-format msgid "" "server stopped streaming timeline %u at %X/%X, but reported next timeline %u " @@ -1794,12 +2656,12 @@ msgstr "" "сервер прекратил передачу линии времени %u в %X/%X, но сообщил, что " "следующая линии времени %u начнётся в %X/%X" -#: receivelog.c:678 +#: receivelog.c:672 #, c-format msgid "replication stream was terminated before stop point" msgstr "поток репликации закончился до точки остановки" -#: receivelog.c:724 +#: receivelog.c:718 #, c-format msgid "" "unexpected result set after end-of-timeline: got %d rows and %d fields, " @@ -1808,61 +2670,62 @@ msgstr "" "сервер вернул неожиданный набор данных после конца линии времени; получено " "строк: %d, полей: %d, а ожидалось строк: %d, полей: %d" -#: receivelog.c:733 +#: receivelog.c:727 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "не удалось разобрать начальную точку следующей линии времени \"%s\"" -#: receivelog.c:781 receivelog.c:1030 walmethods.c:1205 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "не удалось синхронизировать с ФС файл \"%s\": %s" -#: receivelog.c:1091 +#: receivelog.c:1083 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "получена запись журнала предзаписи по смещению %u, но файл не открыт" -#: receivelog.c:1101 +#: receivelog.c:1093 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "получено смещение данных WAL %08x, но ожидалось %08x" -#: receivelog.c:1135 +#: receivelog.c:1128 #, c-format msgid "could not write %d bytes to WAL file \"%s\": %s" msgstr "не удалось записать %d Б в файл WAL \"%s\": %s" -#: receivelog.c:1160 receivelog.c:1200 receivelog.c:1230 +#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 #, c-format msgid "could not send copy-end packet: %s" msgstr "не удалось отправить пакет \"конец COPY\": %s" -#: streamutil.c:159 +#: streamutil.c:165 msgid "Password: " msgstr "Пароль: " -#: streamutil.c:182 +#: streamutil.c:192 #, c-format msgid "could not connect to server" msgstr "не удалось подключиться к серверу" -#: streamutil.c:225 +#: streamutil.c:233 #, c-format -msgid "could not clear search_path: %s" -msgstr "не удалось очистить search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "не удалось очистить \"search_path\": %s" -#: streamutil.c:241 +#: streamutil.c:249 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "не удалось получить настройку сервера integer_datetimes" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "не удалось получить параметр сервера \"integer_datetimes\"" -#: streamutil.c:248 +#: streamutil.c:256 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "флаг компиляции integer_datetimes не соответствует настройке сервера" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "" +"флаг компиляции \"integer_datetimes\" не соответствует настройке сервера" -#: streamutil.c:299 +#: streamutil.c:375 #, c-format msgid "" "could not fetch WAL segment size: got %d rows and %d fields, expected %d " @@ -1871,30 +2734,26 @@ msgstr "" "не удалось извлечь размер сегмента WAL; получено строк: %d, полей: %d " "(ожидалось: %d и %d (или более))" -#: streamutil.c:309 +#: streamutil.c:385 #, c-format msgid "WAL segment size could not be parsed" msgstr "разобрать размер сегмента WAL не удалось" -#: streamutil.c:327 +#: streamutil.c:403 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"remote server reported a value of %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"remote server reported a value of %d bytes" -msgstr[0] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но удалённый сервер сообщил значение: %d" -msgstr[1] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но удалённый сервер сообщил значение: %d" -msgstr[2] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но удалённый сервер сообщил значение: %d" +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "удалённый сервер выдал неверный размер сегмента WAL: %d Б" +msgstr[1] "удалённый сервер выдал неверный размер сегмента WAL: %d Б" +msgstr[2] "удалённый сервер выдал неверный размер сегмента WAL: %d Б" -#: streamutil.c:372 +#: streamutil.c:407 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "" +"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 ГБ." + +#: streamutil.c:449 #, c-format msgid "" "could not fetch group access flag: got %d rows and %d fields, expected %d " @@ -1903,12 +2762,12 @@ msgstr "" "не удалось извлечь флаг доступа группы; получено строк: %d, полей: %d " "(ожидалось: %d и %d (или более))" -#: streamutil.c:381 +#: streamutil.c:458 #, c-format msgid "group access flag could not be parsed: %s" msgstr "не удалось разобрать флаг доступа группы: %s" -#: streamutil.c:424 streamutil.c:461 +#: streamutil.c:501 streamutil.c:538 #, c-format msgid "" "could not identify system: got %d rows and %d fields, expected %d rows and " @@ -1917,7 +2776,7 @@ msgstr "" "не удалось идентифицировать систему; получено строк: %d, полей: %d " "(ожидалось: %d и %d (или более))" -#: streamutil.c:513 +#: streamutil.c:590 #, c-format msgid "" "could not read replication slot \"%s\": got %d rows and %d fields, expected " @@ -1926,23 +2785,23 @@ msgstr "" "прочитать из слота репликации \"%s\" не удалось; получено строк: %d, полей: " "%d (ожидалось: %d и %d)" -#: streamutil.c:525 +#: streamutil.c:602 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "слот репликации \"%s\" не существует" -#: streamutil.c:536 +#: streamutil.c:613 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "ожидался слот физической репликации, вместо этого получен тип \"%s\"" -#: streamutil.c:550 +#: streamutil.c:627 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "" "не удалось разобрать позицию restart_lsn \"%s\" для слота репликации \"%s\"" -#: streamutil.c:667 +#: streamutil.c:744 #, c-format msgid "" "could not create replication slot \"%s\": got %d rows and %d fields, " @@ -1951,7 +2810,7 @@ msgstr "" "создать слот репликации \"%s\" не удалось; получено строк: %d, полей: %d " "(ожидалось: %d и %d)" -#: streamutil.c:711 +#: streamutil.c:788 #, c-format msgid "" "could not drop replication slot \"%s\": got %d rows and %d fields, expected " @@ -1960,35 +2819,55 @@ msgstr "" "удалить слот репликации \"%s\" не получилось; получено строк: %d, полей: %d " "(ожидалось: %d и %d)" -#: walmethods.c:720 walmethods.c:1267 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "не удалось сжать данные" -#: walmethods.c:749 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "не удалось сбросить поток сжатых данных" -#: walmethods.c:880 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "" "ошибка реализации: в файлах tar не может быть больше одно открытого файла" -#: walmethods.c:894 +#: walmethods.c:907 msgid "could not create tar header" msgstr "не удалось создать заголовок tar" -#: walmethods.c:910 walmethods.c:951 walmethods.c:1170 walmethods.c:1183 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "не удалось изменить параметры сжатия" -#: walmethods.c:1055 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "со сжатием закрытие файла с удалением не поддерживается" -#: walmethods.c:1291 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "не удалось закрыть поток сжатых данных" +#, c-format +#~ msgid "this build does not support gzip compression" +#~ msgstr "эта сборка программы не поддерживает сжатие gzip" + +#, c-format +#~ msgid "this build does not support lz4 compression" +#~ msgstr "эта сборка программы не поддерживает сжатие lz4" + +#, c-format +#~ msgid "this build does not support zstd compression" +#~ msgstr "эта сборка программы не поддерживает сжатие zstd" + +#, c-format +#~ msgid "symlinks are not supported on this platform" +#~ msgstr "символические ссылки не поддерживаются в этой ОС" + +#, c-format +#~ msgid "could not determine seek position in file \"%s\": %s" +#~ msgstr "не удалось определить текущую позицию в файле \"%s\": %s" + #~ msgid "unknown compression option \"%s\"" #~ msgstr "неизвестный параметр сжатия \"%s\"" @@ -2003,9 +2882,6 @@ msgstr "не удалось закрыть поток сжатых данных" #~ "для параметра --compress не задано значение, используется значение по " #~ "умолчанию" -#~ msgid "could not find replication slot \"%s\"" -#~ msgstr "не удалось найти слот репликации \"%s\"" - #~ msgid "fatal: " #~ msgstr "важно: " @@ -2044,9 +2920,6 @@ msgstr "не удалось закрыть поток сжатых данных" #~ msgid "--no-manifest and --manifest-force-encode are incompatible options" #~ msgstr "параметры --no-manifest и --manifest-force-encode несовместимы" -#~ msgid "could not connect to server: %s" -#~ msgstr "не удалось подключиться к серверу: %s" - #~ msgid "" #~ "\n" #~ "Report bugs to .\n" @@ -2130,13 +3003,6 @@ msgstr "не удалось закрыть поток сжатых данных" #~ msgid "%s: initializing replication slot \"%s\"\n" #~ msgstr "%s: инициализируется слот репликации \"%s\"\n" -#~ msgid "" -#~ "%s: could not init logical replication: got %d rows and %d fields, " -#~ "expected %d rows and %d fields\n" -#~ msgstr "" -#~ "%s: не удалось инициализировать логическую репликацию; получено строк: " -#~ "%d, полей: %d (ожидалось: %d и %d)\n" - #~ msgid "%s: no start point returned from server\n" #~ msgstr "%s: сервер не вернул стартовую точку\n" @@ -2155,9 +3021,6 @@ msgstr "не удалось закрыть поток сжатых данных" #~ msgid "%s: invalid format of xlog location: %s\n" #~ msgstr "%s: неверный формат позиции в xlog: %s\n" -#~ msgid "%s: could not identify system: %s" -#~ msgstr "%s: не удалось идентифицировать систему: %s" - #~ msgid "%s: could not send base backup command: %s" #~ msgstr "" #~ "%s: не удалось отправить команду базового резервного копирования: %s" diff --git a/src/bin/pg_basebackup/po/sv.po b/src/bin/pg_basebackup/po/sv.po index e3cb887029169..e93dab66b4ca8 100644 --- a/src/bin/pg_basebackup/po/sv.po +++ b/src/bin/pg_basebackup/po/sv.po @@ -1,14 +1,14 @@ # SWEDISH message translation file for pg_basebackup # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-01 14:19+0000\n" -"PO-Revision-Date: 2023-08-01 22:11+0200\n" +"POT-Creation-Date: 2024-08-26 18:20+0000\n" +"PO-Revision-Date: 2024-08-26 20:56+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -52,7 +52,7 @@ msgstr "hittade en tom sträng där en komprimeringsinställning förväntades" #: ../../common/compression.c:244 #, c-format msgid "unrecognized compression option: \"%s\"" -msgstr "okänd komprimeringsflagga \"%s\"" +msgstr "okänd komprimeringsflagga: \"%s\"" #: ../../common/compression.c:283 #, c-format @@ -89,6 +89,64 @@ msgstr "komprimeringsalgoritmen \"%s\" stöder inte inställning av antal arbeta msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "komprimeringsalgoritmen \"%s\" stöder inte långdistansläge" +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "kunde inte stänga fil \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"möjligt fel i byteordning\n" +"Den byteordning som filen från pg_control lagrats med passar kanske\n" +"inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" +"och PostgreSQL-installationen vara inkompatibel med databaskatalogen." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "kunde inte skriva fil \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -100,39 +158,69 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:447 -#: pg_receivewal.c:319 pg_recvlogical.c:339 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "kunde inte göra stat() på fil \"%s\": %m" -#: ../../common/file_utils.c:162 pg_receivewal.c:242 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "kunde inte öppna katalog \"%s\": %m" -#: ../../common/file_utils.c:196 pg_receivewal.c:471 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "kunde inte läsa katalog \"%s\": %m" -#: ../../common/file_utils.c:228 ../../common/file_utils.c:287 -#: ../../common/file_utils.c:361 ../../fe_utils/recovery_gen.c:121 -#: pg_receivewal.c:386 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" -#: ../../common/file_utils.c:299 ../../common/file_utils.c:369 -#: pg_recvlogical.c:194 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "kunde inte fsync:a fil \"%s\": %m" +msgid "could not open process token: error code %lu" +msgstr "kunde inte öppna process-token: felkod %lu" -#: ../../common/file_utils.c:379 pg_basebackup.c:2237 walmethods.c:462 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "kunde inte allokera SID: felkod %lu" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "kunde inte skapa token för begränsad åtkomst: felkod %lu" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "kunde inte starta process för kommando \"%s\": felkod %lu" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "kunde inte köra igen med token för begränsad åtkomst: felkod %lu" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "kunde inte hämta statuskod för underprocess: felkod %lu" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -144,51 +232,62 @@ msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" msgid "%s must be in range %d..%d" msgstr "%s måste vara i intervallet %d..%d" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 pg_basebackup.c:1609 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 #, c-format msgid "out of memory" msgstr "slut på minne" -#: ../../fe_utils/recovery_gen.c:124 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1406 pg_basebackup.c:1700 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "kunde inte skriva till fil \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 bbstreamer_file.c:93 bbstreamer_file.c:360 -#: pg_basebackup.c:1470 pg_basebackup.c:1679 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "kunde inte skapa fil \"%s\": %m" -#: bbstreamer_file.c:138 pg_recvlogical.c:633 +#: ../../fe_utils/string_utils.c:434 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "kunde inte stänga fil \"%s\": %m" +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" #: bbstreamer_file.c:275 #, c-format msgid "unexpected state while extracting archive" msgstr "oväntat tillstånd vid uppackning av arkiv" -#: bbstreamer_file.c:320 pg_basebackup.c:686 pg_basebackup.c:730 +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 #, c-format msgid "could not create directory \"%s\": %m" msgstr "kunde inte skapa katalog \"%s\": %m" -#: bbstreamer_file.c:325 +#: bbstreamer_file.c:326 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "kunde inte sätta rättigheter på katalogen \"%s\": %m" -#: bbstreamer_file.c:344 +#: bbstreamer_file.c:345 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "kunde inte skapa symbolisk länk från \"%s\" till \"%s\": %m" -#: bbstreamer_file.c:364 +#: bbstreamer_file.c:365 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "kunde inte sätta rättigheter på filen \"%s\": %m" @@ -223,7 +322,7 @@ msgstr "kunde inte skriva till komprimerad fil \"%s\": %s" msgid "could not close compressed file \"%s\": %m" msgstr "kunde inte stänga komprimerad fil \"%s\": %m" -#: bbstreamer_gzip.c:245 walmethods.c:876 +#: bbstreamer_gzip.c:245 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "kunde inte initierar komprimeringsbibliotek" @@ -273,12 +372,12 @@ msgstr "tarfilens slutdel överskred 2 block" msgid "unexpected state while parsing tar archive" msgstr "oväntat tillstånd vid parsning av tar-arkiv" -#: bbstreamer_tar.c:296 +#: bbstreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "tar-medlem har tomt namn" -#: bbstreamer_tar.c:328 +#: bbstreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "COPY-ström avslutade innan sista filen var klar" @@ -308,87 +407,87 @@ msgstr "kunde inte aktivera långdistansläge: %s" msgid "could not create zstd decompression context" msgstr "kunde inte skapa kontext för zstd-dekomprimering" -#: pg_basebackup.c:238 +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "tar bort datakatalog \"%s\"" -#: pg_basebackup.c:240 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "misslyckades med att ta bort datakatalog" -#: pg_basebackup.c:244 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "tar bort innehållet i datakatalog \"%s\"" -#: pg_basebackup.c:246 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "misslyckades med att ta bort innehållet i datakatalogen" -#: pg_basebackup.c:251 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "tar bort WAL-katalog \"%s\"" -#: pg_basebackup.c:253 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "misslyckades med att ta bort WAL-katalog" -#: pg_basebackup.c:257 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "tar bort innehållet i WAL-katalog \"%s\"" -#: pg_basebackup.c:259 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "misslyckades med att ta bort innehållet i WAL-katalogen" -#: pg_basebackup.c:265 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "datakatalog \"%s\" är ej borttagen på användares begäran" -#: pg_basebackup.c:268 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "WAL-katalog \"%s\" är ej borttagen på användares begäran" -#: pg_basebackup.c:272 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "ändringar av tablespace-kataloger kan inte backas" -#: pg_basebackup.c:324 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "katalognamn för långt" -#: pg_basebackup.c:331 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "multipla \"=\"-tecken i tablespace-mappning" -#: pg_basebackup.c:340 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "ogiltigt tablespace-mappningsformat \"%s\", måste vara \"OLDDIR=NEWDIR\"" -#: pg_basebackup.c:359 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "gammal katalog är inte en absolut sökväg i tablespace-mappning: %s" -#: pg_basebackup.c:363 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "ny katalog är inte en absolut sökväg i tablespace-mappning: %s" -#: pg_basebackup.c:385 +#: pg_basebackup.c:392 #, c-format msgid "" "%s takes a base backup of a running PostgreSQL server.\n" @@ -397,17 +496,19 @@ msgstr "" "%s tar en basbackup av en körande PostgreSQL-server.\n" "\n" -#: pg_basebackup.c:387 pg_receivewal.c:79 pg_recvlogical.c:76 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_basebackup.c:388 pg_receivewal.c:80 pg_recvlogical.c:77 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [FLAGGA]...\n" -#: pg_basebackup.c:389 +#: pg_basebackup.c:396 #, c-format msgid "" "\n" @@ -416,17 +517,26 @@ msgstr "" "\n" "Flaggor som styr utmatning:\n" -#: pg_basebackup.c:390 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" -msgstr " -D, --pgdata=KATALOG ta emot basbackup till katalog\n" +msgstr " -D, --pgdata=KATALOG ta emot basbackup till katalog\n" -#: pg_basebackup.c:391 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr " -F, --format=p|t utdataformat (plain (standard), tar)\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:399 +#, c-format +msgid "" +" -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr "" +" -i, --incremental=GAMMALTMANIFEST\n" +" ta inkrementell backup\n" + +#: pg_basebackup.c:401 #, c-format msgid "" " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" @@ -435,7 +545,7 @@ msgstr "" " -r, --max-rate=RATE maximal överföringshastighet för att överföra datakatalog\n" " (i kB/s, eller använd suffix \"k\" resp. \"M\")\n" -#: pg_basebackup.c:394 +#: pg_basebackup.c:403 #, c-format msgid "" " -R, --write-recovery-conf\n" @@ -444,7 +554,7 @@ msgstr "" " -R, --write-recovery-conf\n" " skriv konfiguration för replikering\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:405 #, c-format msgid "" " -t, --target=TARGET[:DETAIL]\n" @@ -453,7 +563,7 @@ msgstr "" " -t, --target=MÅL[:DETALJ]\n" " backupmål (om annat än klienten)\n" -#: pg_basebackup.c:398 +#: pg_basebackup.c:407 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -462,12 +572,12 @@ msgstr "" " -T, --tablespace-mapping=GAMMALKAT=NYKAT\n" " flytta tablespace i GAMMALKAT till NYKAT\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr " --waldir=WALKAT plats för write-ahead-logg-katalog\n" -#: pg_basebackup.c:401 +#: pg_basebackup.c:410 #, c-format msgid "" " -X, --wal-method=none|fetch|stream\n" @@ -476,12 +586,12 @@ msgstr "" " -X, --wal-method=none|fetch|stream\n" " inkludera behövda WAL-filer med angiven metod\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip komprimera tar-utdata\n" -#: pg_basebackup.c:404 +#: pg_basebackup.c:413 #, c-format msgid "" " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" @@ -490,12 +600,12 @@ msgstr "" " -Z, --compress=[{client|server}-]METOD[:DETALJ]\n" " komprimera på klient- eller serversida\n" -#: pg_basebackup.c:406 +#: pg_basebackup.c:415 #, c-format msgid " -Z, --compress=none do not compress tar output\n" msgstr " -Z, --compress=none komprimera inte tar-utdata\n" -#: pg_basebackup.c:407 +#: pg_basebackup.c:416 #, c-format msgid "" "\n" @@ -504,56 +614,56 @@ msgstr "" "\n" "Allmänna flaggor:\n" -#: pg_basebackup.c:408 +#: pg_basebackup.c:417 #, c-format msgid "" " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" +" set fast or spread (default) checkpointing\n" msgstr "" " -c, --checkpoint=fast|spread\n" -" ställ in \"fast\" eller \"spread\" checkpoint-metod\n" +" ställ in checkpoint-metod \"fast\" eller \"spread\" (standard)\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " --create-slot skapa en replikeringsslot\n" -#: pg_basebackup.c:411 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=ETIKETT sätt backup-etikett\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean städa inte upp efter fel\n" -#: pg_basebackup.c:413 +#: pg_basebackup.c:422 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync vänta inte på att ändringar skall skrivas säkert till disk\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress visa förloppsinformation\n" -#: pg_basebackup.c:415 pg_receivewal.c:89 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=SLOTNAMN replikerings-slot att använda\n" -#: pg_basebackup.c:416 pg_receivewal.c:91 pg_recvlogical.c:98 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose mata ut utförliga meddelanden\n" -#: pg_basebackup.c:417 pg_receivewal.c:92 pg_recvlogical.c:99 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_basebackup.c:418 +#: pg_basebackup.c:427 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -562,7 +672,7 @@ msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " använd algoritm för manifestchecksummor\n" -#: pg_basebackup.c:420 +#: pg_basebackup.c:429 #, c-format msgid "" " --manifest-force-encode\n" @@ -571,22 +681,22 @@ msgstr "" " --manifest-force-encode\n" " hex-koda alla filnamn i manifestet\n" -#: pg_basebackup.c:422 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" msgstr " --no-estimate-size estimerar inte backupstorlek på serversidan\n" -#: pg_basebackup.c:423 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest förhindra att backupmanifest genereras\n" -#: pg_basebackup.c:424 +#: pg_basebackup.c:433 #, c-format msgid " --no-slot prevent creation of temporary replication slot\n" msgstr " --no-slot förhindra skapande av temporär replikerings-slot\n" -#: pg_basebackup.c:425 +#: pg_basebackup.c:434 #, c-format msgid "" " --no-verify-checksums\n" @@ -595,12 +705,21 @@ msgstr "" " --no-verify-checksums\n" " verifiera inte checksummor\n" -#: pg_basebackup.c:427 pg_receivewal.c:95 pg_recvlogical.c:100 +#: pg_basebackup.c:436 +#, c-format +msgid "" +" --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr "" +" --sync-method=METOD\n" +" sätt synkmetod för att synka filer till disk\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa den här hjälpen, avsluta sedan\n" -#: pg_basebackup.c:428 pg_receivewal.c:96 pg_recvlogical.c:101 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "" "\n" @@ -609,22 +728,22 @@ msgstr "" "\n" "Flaggor för anslutning:\n" -#: pg_basebackup.c:429 pg_receivewal.c:97 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CONNSTR anslutningssträng\n" -#: pg_basebackup.c:430 pg_receivewal.c:98 pg_recvlogical.c:103 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAMN databasserverns värdnamn eller socket-katalog\n" -#: pg_basebackup.c:431 pg_receivewal.c:99 pg_recvlogical.c:104 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT databasserverns postnummer\n" -#: pg_basebackup.c:432 +#: pg_basebackup.c:443 #, c-format msgid "" " -s, --status-interval=INTERVAL\n" @@ -633,22 +752,23 @@ msgstr "" " -s, --status-interval=INTERVAL\n" " tid mellan att statuspaket skickas till servern (i sekunder)\n" -#: pg_basebackup.c:434 pg_receivewal.c:100 pg_recvlogical.c:105 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAMN ansluta som angiven databasanvändare\n" -#: pg_basebackup.c:435 pg_receivewal.c:101 pg_recvlogical.c:106 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga aldrig efter lösenord\n" -#: pg_basebackup.c:436 pg_receivewal.c:102 pg_recvlogical.c:107 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password tvinga fram lösenordsfråga (skall ske automatiskt)\n" -#: pg_basebackup.c:437 pg_receivewal.c:106 pg_recvlogical.c:108 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "" "\n" @@ -657,484 +777,546 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_basebackup.c:438 pg_receivewal.c:107 pg_recvlogical.c:109 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_basebackup.c:477 +#: pg_basebackup.c:488 #, c-format msgid "could not read from ready pipe: %m" msgstr "kunde inte läsa från rör (pipe) som har data: %m" -#: pg_basebackup.c:480 pg_basebackup.c:622 pg_basebackup.c:2151 -#: streamutil.c:441 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:518 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "kunde inte parsa write-ahead-logg-plats \"%s\"" -#: pg_basebackup.c:585 pg_receivewal.c:600 +#: pg_basebackup.c:596 pg_receivewal.c:600 #, c-format msgid "could not finish writing WAL files: %m" msgstr "kunde inte slutföra skrivning av WAL-filer: %m" -#: pg_basebackup.c:631 +#: pg_basebackup.c:642 #, c-format msgid "could not create pipe for background process: %m" msgstr "kunde inte skapa rör (pipe) för bakgrundsprocess: %m" -#: pg_basebackup.c:664 +#: pg_basebackup.c:676 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "skapade en temporär replikeringsslot \"%s\"" -#: pg_basebackup.c:667 +#: pg_basebackup.c:679 #, c-format msgid "created replication slot \"%s\"" msgstr "skapade en replikeringsslot \"%s\"" -#: pg_basebackup.c:701 +#: pg_basebackup.c:728 #, c-format msgid "could not create background process: %m" msgstr "kunde inte skapa bakgrundsprocess: %m" -#: pg_basebackup.c:710 +#: pg_basebackup.c:737 #, c-format msgid "could not create background thread: %m" msgstr "kunde inte skapa bakgrundstråd: %m" -#: pg_basebackup.c:749 +#: pg_basebackup.c:776 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "katalogen \"%s\" existerar men är inte tom" -#: pg_basebackup.c:755 +#: pg_basebackup.c:782 pg_createsubscriber.c:390 #, c-format msgid "could not access directory \"%s\": %m" msgstr "kunde inte komma åt katalog \"%s\": %m" -#: pg_basebackup.c:831 +#: pg_basebackup.c:858 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" msgstr[0] "%*s/%s kB (100%%), %d/%d tablespace %*s" msgstr[1] "%*s/%s kB (100%%), %d/%d tablespace %*s" -#: pg_basebackup.c:843 +#: pg_basebackup.c:870 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" msgstr[0] "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgstr[1] "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" -#: pg_basebackup.c:859 +#: pg_basebackup.c:886 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" msgstr[0] "%*s/%s kB (%d%%), %d/%d tablespace" msgstr[1] "%*s/%s kB (%d%%), %d/%d tablespace" -#: pg_basebackup.c:883 +#: pg_basebackup.c:910 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "överföringshastighet \"%s\" är inte ett giltigt värde" -#: pg_basebackup.c:885 +#: pg_basebackup.c:912 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "ogiltig överföringshastighet \"%s\": %m" -#: pg_basebackup.c:892 +#: pg_basebackup.c:919 #, c-format msgid "transfer rate must be greater than zero" msgstr "överföringshastigheten måste vara större än noll" -#: pg_basebackup.c:922 +#: pg_basebackup.c:949 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "ogiltig enhet för --max-rate: \"%s\"" -#: pg_basebackup.c:926 +#: pg_basebackup.c:953 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "överföringshastighet \"%s\" överskrider heltalsintervall" -#: pg_basebackup.c:933 +#: pg_basebackup.c:960 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "överföringshastighet \"%s\" är utanför sitt intervall" -#: pg_basebackup.c:995 +#: pg_basebackup.c:1022 #, c-format msgid "could not get COPY data stream: %s" msgstr "kunde inte hämta COPY-data-ström: %s" -#: pg_basebackup.c:1012 pg_recvlogical.c:436 pg_recvlogical.c:608 +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 #: receivelog.c:973 #, c-format msgid "could not read COPY data: %s" msgstr "kunde inte läsa COPY-data: %s" -#: pg_basebackup.c:1016 +#: pg_basebackup.c:1043 #, c-format msgid "background process terminated unexpectedly" msgstr "en bakgrundsprocess avslutade oväntat" -#: pg_basebackup.c:1087 +#: pg_basebackup.c:1114 #, c-format msgid "cannot inject manifest into a compressed tar file" msgstr "kan inte injicera manifest in i en komprimerad tarfil" -#: pg_basebackup.c:1088 +#: pg_basebackup.c:1115 #, c-format msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." msgstr "använd komprimering på klientsidan, skicka utdatan till en katalog istället för till standard ut eller använd %s." -#: pg_basebackup.c:1104 +#: pg_basebackup.c:1131 #, c-format msgid "cannot parse archive \"%s\"" msgstr "kunde inte parsa arkiv \"%s\"" -#: pg_basebackup.c:1105 +#: pg_basebackup.c:1132 #, c-format msgid "Only tar archives can be parsed." msgstr "Bara tar-arkiv kan parsas." -#: pg_basebackup.c:1107 +#: pg_basebackup.c:1134 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Enkelt format kräver pg_basebackup för att parsa arkivet." -#: pg_basebackup.c:1109 +#: pg_basebackup.c:1136 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "Att använda - som utkatalog kräver att pg_basebackup parsar arkivet." -#: pg_basebackup.c:1111 +#: pg_basebackup.c:1138 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "Flaggan -R kräver att pg_basebackup parsar arkivet." -#: pg_basebackup.c:1330 +#: pg_basebackup.c:1357 #, c-format msgid "archives must precede manifest" msgstr "arkiv skall komma före manifest" -#: pg_basebackup.c:1345 +#: pg_basebackup.c:1372 #, c-format msgid "invalid archive name: \"%s\"" msgstr "ogiltigt arkivnamn: \"%s\"" -#: pg_basebackup.c:1417 +#: pg_basebackup.c:1444 #, c-format msgid "unexpected payload data" msgstr "oväntat datainnehåll" -#: pg_basebackup.c:1560 +#: pg_basebackup.c:1587 #, c-format msgid "empty COPY message" msgstr "tomt COPY-meddelande" -#: pg_basebackup.c:1562 +#: pg_basebackup.c:1589 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "felaktigt COPY-meddelande av typ %d, längd %zu" -#: pg_basebackup.c:1760 +#: pg_basebackup.c:1789 #, c-format msgid "incompatible server version %s" msgstr "inkompatibel serverversion %s" -#: pg_basebackup.c:1776 +#: pg_basebackup.c:1805 #, c-format msgid "Use -X none or -X fetch to disable log streaming." msgstr "Använd -X none eller -X fetch för att stänga av logg-strömning" -#: pg_basebackup.c:1844 +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "servern stöder inte inkrementella backup:er" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 +#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "kunde inte skicka replikeringskommando \"%s\": %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "kunde inte ladda upp manifest: %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 +#, c-format +msgid "could not upload manifest: unexpected status %s" +msgstr "kunde inte ladda upp manifest: oväntad status %s" + +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "kunde inte skicka COPY-data: %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "kunde inte skicka slut-på-COPY: %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "oväntat extra resultat vid skickande av manifest" + +#: pg_basebackup.c:1950 #, c-format msgid "backup targets are not supported by this server version" msgstr "backupmål stöds inte av denna serverversion" -#: pg_basebackup.c:1847 +#: pg_basebackup.c:1953 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "återställningskonfiguration kan inte skrivas när backupmål används" -#: pg_basebackup.c:1874 +#: pg_basebackup.c:1980 #, c-format msgid "server does not support server-side compression" msgstr "servern stöder inte komprimering på serversidan" -#: pg_basebackup.c:1884 +#: pg_basebackup.c:1990 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "initierar basbackup, väntar på att checkpoint skall gå klart" -#: pg_basebackup.c:1888 +#: pg_basebackup.c:1994 #, c-format msgid "waiting for checkpoint" msgstr "väntar på checkpoint" -#: pg_basebackup.c:1901 pg_recvlogical.c:260 receivelog.c:543 receivelog.c:582 -#: streamutil.c:288 streamutil.c:361 streamutil.c:413 streamutil.c:501 -#: streamutil.c:653 streamutil.c:698 -#, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "kunde inte skicka replikeringskommando \"%s\": %s" - -#: pg_basebackup.c:1909 +#: pg_basebackup.c:2016 #, c-format msgid "could not initiate base backup: %s" msgstr "kunde inte initiera basbackup: %s" -#: pg_basebackup.c:1912 +#: pg_basebackup.c:2019 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "servern retunerade ett oväntat svar på BASE_BACKUP-kommandot; fick %d rader och %d fält, förväntade %d rader och %d fält" -#: pg_basebackup.c:1918 +#: pg_basebackup.c:2025 #, c-format msgid "checkpoint completed" msgstr "checkpoint klar" -#: pg_basebackup.c:1932 +#: pg_basebackup.c:2039 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "write-ahead-loggens startposition: %s på tidslinje %u" -#: pg_basebackup.c:1940 +#: pg_basebackup.c:2047 #, c-format msgid "could not get backup header: %s" msgstr "kunde inte hämta backup-header: %s" -#: pg_basebackup.c:1943 +#: pg_basebackup.c:2050 #, c-format msgid "no data returned from server" msgstr "ingen data returnerades från servern" -#: pg_basebackup.c:1986 +#: pg_basebackup.c:2093 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "kunde bara skriva en endaste tablespace till stdout, databasen har %d" -#: pg_basebackup.c:1999 +#: pg_basebackup.c:2106 #, c-format msgid "starting background WAL receiver" msgstr "startar bakgrunds-WAL-mottagare" -#: pg_basebackup.c:2082 +#: pg_basebackup.c:2189 #, c-format msgid "backup failed: %s" msgstr "backup misslyckades: %s" -#: pg_basebackup.c:2085 +#: pg_basebackup.c:2192 #, c-format msgid "no write-ahead log end position returned from server" msgstr "ingen write-ahead-logg-slutposition returnerad från servern" -#: pg_basebackup.c:2088 +#: pg_basebackup.c:2195 #, c-format msgid "write-ahead log end point: %s" msgstr "write-ahead-logg-slutposition: %s" -#: pg_basebackup.c:2099 +#: pg_basebackup.c:2206 #, c-format msgid "checksum error occurred" msgstr "felaktig kontrollsumma upptäcktes" -#: pg_basebackup.c:2104 +#: pg_basebackup.c:2211 #, c-format msgid "final receive failed: %s" msgstr "sista mottagning misslyckades: %s" -#: pg_basebackup.c:2128 +#: pg_basebackup.c:2235 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "väntat på att bakgrundsprocess skall avsluta strömmande ..." -#: pg_basebackup.c:2132 +#: pg_basebackup.c:2239 #, c-format msgid "could not send command to background pipe: %m" msgstr "kunde inte skicka kommando till bakgrundsrör (pipe): %m" -#: pg_basebackup.c:2137 +#: pg_basebackup.c:2244 #, c-format msgid "could not wait for child process: %m" msgstr "kunde inte vänta på barnprocess: %m" -#: pg_basebackup.c:2139 +#: pg_basebackup.c:2246 #, c-format msgid "child %d died, expected %d" msgstr "barn %d dog, förväntade %d" -#: pg_basebackup.c:2141 streamutil.c:91 streamutil.c:196 +#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 #, c-format msgid "%s" msgstr "%s" -#: pg_basebackup.c:2161 +#: pg_basebackup.c:2268 #, c-format msgid "could not wait for child thread: %m" msgstr "kunde inte vänta på barntråd: %m" -#: pg_basebackup.c:2166 +#: pg_basebackup.c:2273 #, c-format msgid "could not get child thread exit status: %m" msgstr "kunde inte hämta barntrådens slutstatus: %m" -#: pg_basebackup.c:2169 +#: pg_basebackup.c:2276 #, c-format msgid "child thread exited with error %u" msgstr "barntråd avslutade med fel %u" -#: pg_basebackup.c:2198 +#: pg_basebackup.c:2305 #, c-format msgid "syncing data to disk ..." msgstr "synkar data till disk ..." -#: pg_basebackup.c:2223 +#: pg_basebackup.c:2330 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "byter namn på backup_manifest.tmp till backup_manifest" -#: pg_basebackup.c:2243 +#: pg_basebackup.c:2350 #, c-format msgid "base backup completed" msgstr "basbackup klar" -#: pg_basebackup.c:2326 +#: pg_basebackup.c:2436 #, c-format msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" msgstr "ogiltigt checkpoint-argument \"%s\", måste vara \"fast\" eller \"spread\"" -#: pg_basebackup.c:2344 +#: pg_basebackup.c:2454 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "ogiltigt utdataformat \"%s\", måste vara \"plain\" eller \"tar\"" -#: pg_basebackup.c:2422 +#: pg_basebackup.c:2535 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "ogiltig wal-metod-flagga \"%s\", måste vara \"fetch\", \"stream\" eller \"none\"" -#: pg_basebackup.c:2457 pg_basebackup.c:2469 pg_basebackup.c:2491 -#: pg_basebackup.c:2503 pg_basebackup.c:2509 pg_basebackup.c:2561 -#: pg_basebackup.c:2572 pg_basebackup.c:2582 pg_basebackup.c:2588 -#: pg_basebackup.c:2595 pg_basebackup.c:2607 pg_basebackup.c:2619 -#: pg_basebackup.c:2627 pg_basebackup.c:2640 pg_basebackup.c:2646 -#: pg_basebackup.c:2655 pg_basebackup.c:2667 pg_basebackup.c:2678 -#: pg_basebackup.c:2686 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2037 pg_createsubscriber.c:2047 +#: pg_createsubscriber.c:2055 pg_createsubscriber.c:2083 +#: pg_createsubscriber.c:2115 pg_receivewal.c:748 pg_receivewal.c:760 #: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 -#: pg_receivewal.c:793 pg_recvlogical.c:835 pg_recvlogical.c:847 -#: pg_recvlogical.c:857 pg_recvlogical.c:864 pg_recvlogical.c:871 -#: pg_recvlogical.c:878 pg_recvlogical.c:885 pg_recvlogical.c:892 -#: pg_recvlogical.c:899 pg_recvlogical.c:906 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_basebackup.c:2467 pg_receivewal.c:758 pg_recvlogical.c:845 +#: pg_basebackup.c:2584 pg_createsubscriber.c:2045 pg_receivewal.c:758 +#: pg_recvlogical.c:863 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_basebackup.c:2490 +#: pg_basebackup.c:2607 #, c-format msgid "cannot specify both format and backup target" msgstr "kan inte ange både format och backupmål" -#: pg_basebackup.c:2502 +#: pg_basebackup.c:2619 #, c-format msgid "must specify output directory or backup target" msgstr "måste ange utkatalog eller backupmål" -#: pg_basebackup.c:2508 +#: pg_basebackup.c:2625 #, c-format msgid "cannot specify both output directory and backup target" msgstr "kan inte ange både utdatakatalog och backupmål" -#: pg_basebackup.c:2538 pg_receivewal.c:802 +#: pg_basebackup.c:2655 pg_receivewal.c:802 #, c-format msgid "unrecognized compression algorithm: \"%s\"" -msgstr "okänd komprimeringsalgoritm \"%s\"" +msgstr "okänd komprimeringsalgoritm: \"%s\"" -#: pg_basebackup.c:2544 pg_receivewal.c:809 +#: pg_basebackup.c:2661 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "ogiltig komprimeringsangivelse: %s" -#: pg_basebackup.c:2560 +#: pg_basebackup.c:2677 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "komprimering på klientsidan är inte möjlig när backupmål angivits" -#: pg_basebackup.c:2571 +#: pg_basebackup.c:2688 #, c-format msgid "only tar mode backups can be compressed" msgstr "bara backupper i tar-läge kan komprimeras" -#: pg_basebackup.c:2581 +#: pg_basebackup.c:2698 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "WAL kan inte strömmas när ett backupmål angivits" -#: pg_basebackup.c:2587 +#: pg_basebackup.c:2704 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "kan inte strömma write-ahead-logg i tar-läge till stdout" -#: pg_basebackup.c:2594 +#: pg_basebackup.c:2711 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "replikerings-slot kan bara användas med WAL-strömning" -#: pg_basebackup.c:2606 +#: pg_basebackup.c:2723 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot kan inte användas tillsammans med slot-namn" #. translator: second %s is an option name -#: pg_basebackup.c:2617 pg_receivewal.c:774 +#: pg_basebackup.c:2734 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "%s kräver att en slot anges med --slot" -#: pg_basebackup.c:2625 pg_basebackup.c:2665 pg_basebackup.c:2676 -#: pg_basebackup.c:2684 +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 #, c-format msgid "%s and %s are incompatible options" msgstr "%s och %s är inkompatibla flaggor" -#: pg_basebackup.c:2639 +#: pg_basebackup.c:2756 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "WAL-katalogplats kan inte anges tillsammans med backupmål" -#: pg_basebackup.c:2645 +#: pg_basebackup.c:2762 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "WAL-katalogplats kan bara anges i läget \"plain\"" -#: pg_basebackup.c:2654 +#: pg_basebackup.c:2771 #, c-format msgid "WAL directory location must be an absolute path" msgstr "WAL-katalogen måste vara en absolut sökväg" -#: pg_basebackup.c:2754 +#: pg_basebackup.c:2871 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "kan inte skapa symbolisk länk \"%s\": %m" -#: pg_receivewal.c:77 +#: pg_createsubscriber.c:169 +#, c-format +msgid "failed after the end of recovery" +msgstr "misslyckades vid slutet av återställning" + +#: pg_createsubscriber.c:170 +#, c-format +msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." +msgstr "Målservern kan inte längre användas som en fysisk replika. Du måste återskapa den fysiska replikan innan det går att fortsätta." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "publiceringen \"%s\" som skapades i databasen \"%s\" på primären har lämnats kvar" + +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "Släng denna publiceringen innan du försöker igen." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "replikeringsslotten \"%s\" som skapades i databasen \"%s\" på primären har lämnats kvar" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1260 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "Släng denna replikeringsslot inom kort för att undvika att WAL-filer köas upp." + +#: pg_createsubscriber.c:219 #, c-format msgid "" -"%s receives PostgreSQL streaming write-ahead logs.\n" -"\n" -msgstr "" -"%s tar emot PostgreSQL-strömning-write-ahead-logg.\n" +"%s creates a new logical replica from a standby server.\n" "\n" +msgstr "%s skapar en ny logisk replikering från en standby-server.\n" -#: pg_receivewal.c:81 pg_recvlogical.c:82 +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 #, c-format msgid "" "\n" @@ -1143,22 +1325,639 @@ msgstr "" "\n" "Flaggor:\n" +#: pg_createsubscriber.c:224 +#, c-format +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --database=DBNAME databas att skapa prenumeration i\n" + +#: pg_createsubscriber.c:225 +#, c-format +msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" +msgstr " -D, --pgdata=DATADIR plats för prenumerantens datakatalog\n" + +#: pg_createsubscriber.c:226 +#, c-format +msgid " -n, --dry-run dry run, just show what would be done\n" +msgstr " -n, --dry-run ingen updatering, visa bara planerade åtgärder\n" + +#: pg_createsubscriber.c:227 +#, c-format +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr " -p, --subscriber-port=PORT prenumerantens portnummer (standard %s)\n" + +#: pg_createsubscriber.c:228 +#, c-format +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CONNSTR publicerarens anslutningssträng\n" + +#: pg_createsubscriber.c:229 +#, c-format +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=KAT uttagskatalog (standard är aktuell katalog.)\n" + +#: pg_createsubscriber.c:230 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=SECS antal sekunder att vänta på att återställning skall avslutas\n" + +#: pg_createsubscriber.c:231 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NAME användarnamn för prenumerantens anslutning\n" + +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose visa utförliga meddelanden\n" + +#: pg_createsubscriber.c:233 +#, c-format +msgid "" +" --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" +msgstr "" +" --config-file=FILNAMN använd angiven fil med serverkonfiguration\n" +" när målklustret körs\n" + +#: pg_createsubscriber.c:235 +#, c-format +msgid " --publication=NAME publication name\n" +msgstr " --publication=NAME publiceringsnamn\n" + +#: pg_createsubscriber.c:236 +#, c-format +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=NAME namn på replikeringsslot\n" + +#: pg_createsubscriber.c:237 +#, c-format +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NAME namn på prenumeration\n" + +#: pg_createsubscriber.c:238 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" + +#: pg_createsubscriber.c:239 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" + +#: pg_createsubscriber.c:282 +#, c-format +msgid "could not parse connection string: %s" +msgstr "kunde inte parsa anslutningssträng: %s" + +#: pg_createsubscriber.c:359 +#, c-format +msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +msgstr "programmet \"%s\" behövs av %s men hittades inte i samma katalog som \"%s\"" + +#: pg_createsubscriber.c:362 +#, c-format +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "programmet \"%s\" hittades av \"%s\" men är inte av samma version som %s" + +#: pg_createsubscriber.c:382 +#, c-format +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "undersöker om katalogen \"%s\" är en klusterkatalog" + +#: pg_createsubscriber.c:388 +#, c-format +msgid "data directory \"%s\" does not exist" +msgstr "databaskatalogen \"%s\" existerar inte" + +#: pg_createsubscriber.c:396 +#, c-format +msgid "directory \"%s\" is not a database cluster directory" +msgstr "katalogen \"%s\" innehåller inte ett databaskluster." + +#: pg_createsubscriber.c:513 +#, c-format +msgid "connection to database failed: %s" +msgstr "anslutning till databasen misslyckades: %s" + +#: pg_createsubscriber.c:526 +#, c-format +msgid "could not clear search_path: %s" +msgstr "kunde inte nollställa search_path: %s" + +#: pg_createsubscriber.c:566 +#, c-format +msgid "getting system identifier from publisher" +msgstr "hämtar systemidentifierare från publicerare" + +#: pg_createsubscriber.c:573 +#, c-format +msgid "could not get system identifier: %s" +msgstr "kunde inte hämta systemidentifierare: %s" + +#: pg_createsubscriber.c:579 +#, c-format +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "kunde inte hämta systemidentifierare: fick %d rader, förväntade %d rad" + +#: pg_createsubscriber.c:586 +#, c-format +msgid "system identifier is %llu on publisher" +msgstr "systemidentifieraren är %llu på publiceraren" + +#: pg_createsubscriber.c:607 +#, c-format +msgid "getting system identifier from subscriber" +msgstr "hämtar systemidentifierare från prenumeranten" + +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 +#, c-format +msgid "control file appears to be corrupt" +msgstr "kontrollfilen verkar vara trasig" + +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 +#, c-format +msgid "system identifier is %llu on subscriber" +msgstr "systemidentifieraren är %llu hos prenumeranten" + +#: pg_createsubscriber.c:637 +#, c-format +msgid "modifying system identifier of subscriber" +msgstr "uppdaterar systemidentifieraren för prenumeranten" + +#: pg_createsubscriber.c:659 +#, c-format +msgid "running pg_resetwal on the subscriber" +msgstr "kör pg_resetwal på prenumeranten" + +#: pg_createsubscriber.c:671 +#, c-format +msgid "subscriber successfully changed the system identifier" +msgstr "prenumeranten lyckades ändra systemidentifieraren" + +#: pg_createsubscriber.c:673 +#, c-format +msgid "could not change system identifier of subscriber: %s" +msgstr "kunde inte ändra systemidentifierare för prenumerant: %s" + +#: pg_createsubscriber.c:697 +#, c-format +msgid "could not obtain database OID: %s" +msgstr "kunde inte hämta databas-OID: %s" + +#: pg_createsubscriber.c:704 +#, c-format +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "kunde inte hämta databas-OID: fick %d rader, förväntade %d rad" + +#: pg_createsubscriber.c:776 +#, c-format +msgid "create replication slot \"%s\" on publisher" +msgstr "skapa replikerings-slot \"%s\" på publicerare" + +#: pg_createsubscriber.c:796 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "kunde inte läsa ytterligare en WAL-post: %s" + +#: pg_createsubscriber.c:822 +#, c-format +msgid "could not obtain recovery progress: %s" +msgstr "kunde inte hämta progress för återställning: %s" + +#: pg_createsubscriber.c:854 +#, c-format +msgid "checking settings on publisher" +msgstr "kontrollerar inställningar på publicerare" + +#: pg_createsubscriber.c:864 +#, c-format +msgid "primary server cannot be in recovery" +msgstr "primära servern kan inte vara i återställningsläge" + +#: pg_createsubscriber.c:888 +#, c-format +msgid "could not obtain publisher settings: %s" +msgstr "kunde inte hämta inställningar för publicerare: %s" + +#: pg_createsubscriber.c:914 +#, c-format +msgid "publisher requires wal_level >= \"logical\"" +msgstr "publiceraren kräver wal_level >= \"logical\"" + +#: pg_createsubscriber.c:920 +#, c-format +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "publicerare kräver %d replikeringssslottar men bara %d återstår" + +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Öka konfigurationsparametern \"%s\" till minst %d." + +#: pg_createsubscriber.c:929 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "publicerare kräver %d WAL-skickar-processer men bara %d återstår" + +#: pg_createsubscriber.c:938 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "flaggan two_phase kommer inte aktiveras för replikeringsslottar" + +#: pg_createsubscriber.c:939 +#, c-format +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "Prenumerationer kommer skapas med flaggan two_phase avaktiverad. Förberedda transaktioner kommer replikeras vid COMMIT PREPARED." + +#: pg_createsubscriber.c:971 +#, c-format +msgid "checking settings on subscriber" +msgstr "kontrollerar inställningar på prenumeranten" + +#: pg_createsubscriber.c:978 +#, c-format +msgid "target server must be a standby" +msgstr "målserver måste vara en standby" + +#: pg_createsubscriber.c:1002 +#, c-format +msgid "could not obtain subscriber settings: %s" +msgstr "kunde inte hämta inställningar för prenumerant: %s" + +#: pg_createsubscriber.c:1026 +#, c-format +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "prenumerant kräver %d replikeringsslottar men bara %d återstår" + +#: pg_createsubscriber.c:1035 +#, c-format +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "prenumerant kräver %d logiska replikeringsprocesser men bara %d återstår" + +#: pg_createsubscriber.c:1044 +#, c-format +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "prenumerant kräver %d arbetsprocesser men bara %d återstår" + +#: pg_createsubscriber.c:1079 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "slänger prenumeration \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1088 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "kunde inte slänga prenumeration \"%s\": %s" + +#: pg_createsubscriber.c:1123 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "kunde inte hämta redan existerande prenumerationer: %s" + +#: pg_createsubscriber.c:1258 +#, c-format +msgid "could not drop replication slot \"%s\" on primary" +msgstr "kunde inte slänga replikeringsslotten \"%s\" på primären" + +#: pg_createsubscriber.c:1292 +#, c-format +msgid "could not obtain failover replication slot information: %s" +msgstr "kunde inte hämta replikeringsslottens information för failover: %s" + +#: pg_createsubscriber.c:1294 pg_createsubscriber.c:1303 +#, c-format +msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." +msgstr "Släng replikeringsslottar för failover på prenumeranten inom kort för att undvika att köa upp WAL-filer." + +#: pg_createsubscriber.c:1302 +#, c-format +msgid "could not drop failover replication slot" +msgstr "kunde inte slänga replikeringsslot för failover" + +#: pg_createsubscriber.c:1324 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "skapar replikeringsslot \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1342 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "kunde inte skapa replikeringsslot \"%s\" i databasen \"%s\": %s" + +#: pg_createsubscriber.c:1372 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "slänger replikeringsslot \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1388 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "kunde inte slänga replikeringsslot \"%s\" i databasen \"%s\": %s" + +#: pg_createsubscriber.c:1409 +#, c-format +msgid "pg_ctl failed with exit code %d" +msgstr "pg_ctl avslutade med felkod %d" + +#: pg_createsubscriber.c:1414 +#, c-format +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "pg_ctl avslutades med avbrott 0x%X" + +#: pg_createsubscriber.c:1416 +#, c-format +msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "Se C-include-fil \"ntstatus.h\" för en beskrivning av det hexdecimala värdet." + +#: pg_createsubscriber.c:1418 +#, c-format +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "pg_ctl terminerades av signal %d: %s" + +#: pg_createsubscriber.c:1424 +#, c-format +msgid "pg_ctl exited with unrecognized status %d" +msgstr "pg_ctl avslutade med okänd statuskod %d" + +#: pg_createsubscriber.c:1427 +#, c-format +msgid "The failed command was: %s" +msgstr "Det misslyckade kommandot var: %s" + +#: pg_createsubscriber.c:1473 +#, c-format +msgid "server was started" +msgstr "servern startad" + +#: pg_createsubscriber.c:1488 +#, c-format +msgid "server was stopped" +msgstr "servern är stoppad" + +#: pg_createsubscriber.c:1507 +#, c-format +msgid "waiting for the target server to reach the consistent state" +msgstr "väntar på att målservern skall komma till ett konsistent läge" + +#: pg_createsubscriber.c:1530 +#, c-format +msgid "recovery timed out" +msgstr "timeout vid återställning" + +#: pg_createsubscriber.c:1543 +#, c-format +msgid "server did not end recovery" +msgstr "servern avslutade inte återställning" + +#: pg_createsubscriber.c:1545 +#, c-format +msgid "target server reached the consistent state" +msgstr "målservern har nått ett konsistent läge" + +#: pg_createsubscriber.c:1546 +#, c-format +msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." +msgstr "" +"Om pg_createsubscriber misslyckas efter denna punkt så måste du\n" +"återskapa den fysiska replikan innan du fortsätter." + +#: pg_createsubscriber.c:1573 +#, c-format +msgid "could not obtain publication information: %s" +msgstr "kunde inte hämta publiceringsinformation: %s" + +#: pg_createsubscriber.c:1587 +#, c-format +msgid "publication \"%s\" already exists" +msgstr "publicering \"%s\" finns redan" + +#: pg_createsubscriber.c:1588 +#, c-format +msgid "Consider renaming this publication before continuing." +msgstr "Överväg att byta namn på denna publicering innan fortsättning." + +#: pg_createsubscriber.c:1595 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "skapar puiblicering \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1608 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "kunde inte skapa publicering \"%s\" i databasen \"%s\": %s" + +#: pg_createsubscriber.c:1637 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "slänger publiceringen \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1651 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "kunde inte slänga publiceringen \"%s\" i databasen \"%s\": %s" + +#: pg_createsubscriber.c:1697 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "skapar prenumeration \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1718 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "kunde inte skapa prenumeration \"%s\" i databasen \"%s\": %s" + +#: pg_createsubscriber.c:1763 +#, c-format +msgid "could not obtain subscription OID: %s" +msgstr "kunde inte hämta prenumerations-OID: %s" + +#: pg_createsubscriber.c:1770 +#, c-format +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "kunde inte hämta prenumerations-OID: fick %d rader, förväntade %d rad" + +#: pg_createsubscriber.c:1794 +#, c-format +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "sätter progress för replikering (nod-namn \"%s\", LSN %s) i databasen \"%s\"" + +#: pg_createsubscriber.c:1809 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "kunde inte sätta progress för replikering till prenumeration \"%s\": %s" + +#: pg_createsubscriber.c:1840 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "aktiverar prenumeration \"%s\" i databasen \"%s\"" + +#: pg_createsubscriber.c:1852 +#, c-format +msgid "could not enable subscription \"%s\": %s" +msgstr "kunde inte aktivera prenumerationen \"%s\": %s" + +#: pg_createsubscriber.c:1944 +#, c-format +msgid "cannot be executed by \"root\"" +msgstr "kan inte köras av \"root\"" + +#: pg_createsubscriber.c:1945 +#, c-format +msgid "You must run %s as the PostgreSQL superuser." +msgstr "Du måste köra %s som PostgreSQL:s superuser." + +#: pg_createsubscriber.c:1966 +#, c-format +msgid "database \"%s\" specified more than once" +msgstr "database \"%s\" angiven mer än en gång" + +#: pg_createsubscriber.c:2007 +#, c-format +msgid "publication \"%s\" specified more than once" +msgstr "publicering \"%s\" angiven mer än en gång" + +#: pg_createsubscriber.c:2019 +#, c-format +msgid "replication slot \"%s\" specified more than once" +msgstr "replikeringsslott \"%s\" angiven mer än en gång" + +#: pg_createsubscriber.c:2031 +#, c-format +msgid "subscription \"%s\" specified more than once" +msgstr "prenumeration \"%s\" angiven mer än en gång" + +#: pg_createsubscriber.c:2054 +#, c-format +msgid "no subscriber data directory specified" +msgstr "ingen datakatalog för prenumeration angiven" + +#: pg_createsubscriber.c:2065 +#, c-format +msgid "could not determine current directory" +msgstr "kunde inte bestämma aktuell katalog" + +#: pg_createsubscriber.c:2082 +#, c-format +msgid "no publisher connection string specified" +msgstr "ingen anslutningssträng angiven för publicerare" + +#: pg_createsubscriber.c:2086 +#, c-format +msgid "validating publisher connection string" +msgstr "validerar publicerares anslutningssträng" + +#: pg_createsubscriber.c:2092 +#, c-format +msgid "validating subscriber connection string" +msgstr "validerar prenumerants anslutningssträng" + +#: pg_createsubscriber.c:2097 +#, c-format +msgid "no database was specified" +msgstr "ingen databas angavs" + +#: pg_createsubscriber.c:2109 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "databasnamn \"%s\" extraherades från publicistens anslutningssträng" + +#: pg_createsubscriber.c:2114 +#, c-format +msgid "no database name specified" +msgstr "inget databasnamn angavs" + +#: pg_createsubscriber.c:2124 +#, c-format +msgid "wrong number of publication names specified" +msgstr "fel antal namn på publicister angavs" + +#: pg_createsubscriber.c:2125 +#, c-format +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "Antalet angivna namn på publicister (%d) måste matcha antalet angivna namn på databaser (%d)." + +#: pg_createsubscriber.c:2131 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "fel antal namn på prenumeranter angivna" + +#: pg_createsubscriber.c:2132 +#, c-format +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "Antalet angivna namn på prenumeranter (%d) måste matcha antalet angivna namn på databaser (%d)." + +#: pg_createsubscriber.c:2138 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "fel antal namn på replikeringsslottar angivet" + +#: pg_createsubscriber.c:2139 +#, c-format +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "Antalet angivna namn på replikeringsslottar (%d) måste matcha antalet angivna namn på databaser (%d)." + +#: pg_createsubscriber.c:2168 +#, c-format +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "prenumerantens datakatalog är inte en kopia på källdatabasens kluster" + +#: pg_createsubscriber.c:2181 +#, c-format +msgid "standby server is running" +msgstr "standby-servern kör" + +#: pg_createsubscriber.c:2182 +#, c-format +msgid "Stop the standby server and try again." +msgstr "Stoppa standby-servern och försök igen." + +#: pg_createsubscriber.c:2191 +#, c-format +msgid "starting the standby server with command-line options" +msgstr "startar standby-server med kommandoradsflaggor" + +#: pg_createsubscriber.c:2207 pg_createsubscriber.c:2242 +#, c-format +msgid "stopping the subscriber" +msgstr "stoppar prenumeranten" + +#: pg_createsubscriber.c:2221 +#, c-format +msgid "starting the subscriber" +msgstr "startar prenumeranten" + +#: pg_createsubscriber.c:2250 +#, c-format +msgid "Done!" +msgstr "Klar!" + +#: pg_receivewal.c:77 +#, c-format +msgid "" +"%s receives PostgreSQL streaming write-ahead logs.\n" +"\n" +msgstr "" +"%s tar emot PostgreSQL-strömning-write-ahead-logg.\n" +"\n" + #: pg_receivewal.c:82 #, c-format msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=KAT ta emot write-ahead-logg-filer till denna katalog\n" -#: pg_receivewal.c:83 pg_recvlogical.c:83 +#: pg_receivewal.c:83 pg_recvlogical.c:93 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN avsluta efter att ha taget emot den angivna LSN\n" -#: pg_receivewal.c:84 pg_recvlogical.c:87 +#: pg_receivewal.c:84 pg_recvlogical.c:97 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr " --if-not-exists inget fel om slot:en redan finns när vi skapar slot:en\n" -#: pg_receivewal.c:85 pg_recvlogical.c:89 +#: pg_receivewal.c:85 pg_recvlogical.c:99 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop loopa inte om anslutning tappas\n" @@ -1168,7 +1967,7 @@ msgstr " -n, --no-loop loopa inte om anslutning tappas\n" msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync vänta inte på att ändringar skall skrivas säkert till disk\n" -#: pg_receivewal.c:87 pg_recvlogical.c:94 +#: pg_receivewal.c:87 pg_recvlogical.c:104 #, c-format msgid "" " -s, --status-interval=SECS\n" @@ -1200,12 +1999,12 @@ msgstr "" "\n" "Valfria handlingar:\n" -#: pg_receivewal.c:104 pg_recvlogical.c:79 +#: pg_receivewal.c:104 pg_recvlogical.c:89 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr " --create-slot skapa en ny replikeringsslot (angående slot:ens namn, se --slot)\n" -#: pg_receivewal.c:105 pg_recvlogical.c:80 +#: pg_receivewal.c:105 pg_recvlogical.c:90 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr " --drop-slot släng replikeringsslot (angående slot:ens namn, se --slot)\n" @@ -1225,7 +2024,7 @@ msgstr "stoppade logg-strömning vid %X/%X (tidslinje %u)" msgid "switched to timeline %u at %X/%X" msgstr "bytte till tidslinje %u vid %X/%X" -#: pg_receivewal.c:224 +#: pg_receivewal.c:224 pg_recvlogical.c:1053 #, c-format msgid "received interrupt signal, exiting" msgstr "mottog avbrottsignal, avslutar" @@ -1270,11 +2069,6 @@ msgstr "komprimerad segmentfil \"%s\" har inkorrekt okomprimerad storlek %d, hop msgid "could not create LZ4 decompression context: %s" msgstr "kunde inte skapa kontext för LZ4-dekomprimering: %s" -#: pg_receivewal.c:402 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "kunde inte läsa fil \"%s\": %m" - #: pg_receivewal.c:420 #, c-format msgid "could not decompress file \"%s\": %s" @@ -1300,7 +2094,7 @@ msgstr "kan inte kontrollera filen \"%s\": komprimering med %s stöds inte av de msgid "starting log streaming at %X/%X (timeline %u)" msgstr "startar logg-strömning vid %X/%X (tidslinje %u)" -#: pg_receivewal.c:693 pg_recvlogical.c:783 +#: pg_receivewal.c:693 pg_recvlogical.c:801 #, c-format msgid "could not parse end position \"%s\"" msgstr "kunde inte parsa slutposition \"%s\"" @@ -1330,28 +2124,28 @@ msgstr "komprimering med %s stöds inte än" msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "replikeringsanslutning som använder slot \"%s\" är oväntat databasspecifik" -#: pg_receivewal.c:878 pg_recvlogical.c:954 +#: pg_receivewal.c:878 pg_recvlogical.c:972 #, c-format msgid "dropping replication slot \"%s\"" msgstr "slänger replikeringsslot \"%s\"" -#: pg_receivewal.c:889 pg_recvlogical.c:964 +#: pg_receivewal.c:889 pg_recvlogical.c:982 #, c-format msgid "creating replication slot \"%s\"" msgstr "skapar replikeringsslot \"%s\"" -#: pg_receivewal.c:918 pg_recvlogical.c:988 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "nerkopplad" #. translator: check source for value for %d -#: pg_receivewal.c:922 pg_recvlogical.c:992 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "nerkopplad; väntar %d sekunder för att försöka igen" -#: pg_recvlogical.c:74 +#: pg_recvlogical.c:84 #, c-format msgid "" "%s controls PostgreSQL logical decoding streams.\n" @@ -1360,7 +2154,7 @@ msgstr "" "%s styr PostgreSQL:s logiskt avkodade strömmar.\n" "\n" -#: pg_recvlogical.c:78 +#: pg_recvlogical.c:88 #, c-format msgid "" "\n" @@ -1369,17 +2163,17 @@ msgstr "" "\n" "Handling att utföra:\n" -#: pg_recvlogical.c:81 +#: pg_recvlogical.c:91 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr " --start starta strömning i en replikeringsslot (angående slot:ens namn, se --slot)\n" -#: pg_recvlogical.c:84 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=FIL ta emot logg till denna fil, - för stdout\n" -#: pg_recvlogical.c:85 +#: pg_recvlogical.c:95 #, c-format msgid "" " -F --fsync-interval=SECS\n" @@ -1388,12 +2182,12 @@ msgstr "" " -F --fsync-interval=SEK\n" " tid mellan fsync av utdatafil (standard: %d)\n" -#: pg_recvlogical.c:88 +#: pg_recvlogical.c:98 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN var i en existerande slot skall strömningen starta\n" -#: pg_recvlogical.c:90 +#: pg_recvlogical.c:100 #, c-format msgid "" " -o, --option=NAME[=VALUE]\n" @@ -1404,143 +2198,143 @@ msgstr "" " skicka vidare flaggan NAMN med ev. värde VÄRDE till\n" " utmatnings-plugin:en\n" -#: pg_recvlogical.c:93 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN använd utmatnings-plugin:en PLUGIN (standard: %s)\n" -#: pg_recvlogical.c:96 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOTNAMN namn på den logiska replikerings-slotten\n" -#: pg_recvlogical.c:97 +#: pg_recvlogical.c:107 #, c-format msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" msgstr " -t, --two-phase slå på avkodning av förberedda transaktioner när en slot skapas\n" -#: pg_recvlogical.c:102 +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=DBNAMN databas att ansluta till\n" -#: pg_recvlogical.c:135 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "bekräftar skrivning fram till %X/%X, flush till %X/%X (slot %s)" -#: pg_recvlogical.c:159 receivelog.c:360 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "kunde inte skicka feedback-paket: %s" -#: pg_recvlogical.c:227 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "startar logg-strömning vid %X/%X (slot %s)" -#: pg_recvlogical.c:269 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "strömning initierad" -#: pg_recvlogical.c:333 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "kunde inte öppna loggfil \"%s\": %m" -#: pg_recvlogical.c:362 receivelog.c:882 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "ogiltigt uttag: %s" -#: pg_recvlogical.c:415 receivelog.c:910 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: pg_recvlogical.c:422 receivelog.c:959 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "kunde inte ta emot data från WAL-ström: %s" -#: pg_recvlogical.c:464 pg_recvlogical.c:515 receivelog.c:1003 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 #: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "strömningsheader för liten: %d" -#: pg_recvlogical.c:499 receivelog.c:843 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "okänd strömningsheader: \"%c\"" -#: pg_recvlogical.c:553 pg_recvlogical.c:565 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "kunde inte skriva %d byte till loggfil \"%s\": %m" -#: pg_recvlogical.c:619 receivelog.c:642 receivelog.c:679 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "oväntad terminering av replikeringsström: %s" -#: pg_recvlogical.c:778 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "kunde inte parsa startposition \"%s\"" -#: pg_recvlogical.c:856 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "ingen slot angiven" -#: pg_recvlogical.c:863 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "ingen målfil angiven" -#: pg_recvlogical.c:870 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "ingen databas angiven" -#: pg_recvlogical.c:877 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "minst en handling måste anges" -#: pg_recvlogical.c:884 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "kan inte använda --create-slot eller --start tillsammans med --drop-slot" -#: pg_recvlogical.c:891 +#: pg_recvlogical.c:909 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "kan inte använda --create-slot eller --drop-slot tillsammans med --startpos" -#: pg_recvlogical.c:898 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos får bara anges tillsammans med --start" -#: pg_recvlogical.c:905 +#: pg_recvlogical.c:923 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase får bara anges tillsammans med --create-slot" -#: pg_recvlogical.c:938 +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "kunde inte upprätta databasspecifik replikeringsanslutning" -#: pg_recvlogical.c:1032 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "slutposition %X/%X nådd av keepalive" -#: pg_recvlogical.c:1035 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "slutposition %X/%X nådd av WAL-post vid %X/%X" @@ -1657,7 +2451,7 @@ msgstr "oväntad resultatmängd efter slut-på-tidslinje: fick %d rader och %d f msgid "could not parse next timeline's starting point \"%s\"" msgstr "kunde inte parsa nästa tidslinjens startpunkt \"%s\"" -#: receivelog.c:775 receivelog.c:1022 walmethods.c:1201 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "kunde inte fsync:a fil \"%s\": %s" @@ -1682,136 +2476,121 @@ msgstr "kunde inte skriva %d byte till WAL-fil \"%s\": %s" msgid "could not send copy-end packet: %s" msgstr "kunde inte skicka \"copy-end\"-paket: %s" -#: streamutil.c:158 +#: streamutil.c:162 msgid "Password: " msgstr "Lösenord: " -#: streamutil.c:181 +#: streamutil.c:189 #, c-format msgid "could not connect to server" msgstr "kunde inte ansluta till server" -#: streamutil.c:222 +#: streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "kunde inte nollställa search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "kunde inte nollställa \"search_path\": %s" -#: streamutil.c:238 +#: streamutil.c:246 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "kunde inte lista ut serverns inställning för integer_datetimes" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "kunde inte lista ut serverns inställning för \"integer_datetimes\"" -#: streamutil.c:245 +#: streamutil.c:253 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "kompileringsflaggan integer_datetimes matchar inte servern" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "kompileringsflaggan \"integer_datetimes\" matchar inte servern" -#: streamutil.c:296 +#: streamutil.c:372 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "kunde inte hämta WAL-segmentstorlek: fick %d rader och %d fält, förväntade %d rader och %d eller fler fält" -#: streamutil.c:306 +#: streamutil.c:382 #, c-format msgid "WAL segment size could not be parsed" msgstr "WAL-segment-storlek kunde inte parsas" -#: streamutil.c:324 +#: streamutil.c:400 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d bytes" -msgstr[0] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men fjärrservern rapporterade värdet %d byte" -msgstr[1] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men fjärrservern rapporterade värdet %d byte" +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "fjärrservern rapporterade ogiltig WAL-segmentstorlek (%d byte)" +msgstr[1] "fjärrservern rapporterade ogiltig WAL-segmentstorlek (%d byte)" -#: streamutil.c:369 +#: streamutil.c:404 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Storleken på WAL-segment måste vara en tvåpotens mellan 1 MB och 1 GB." + +#: streamutil.c:446 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "kunde inte hämta gruppaccessflagga: fick %d rader och %d fält, förväntade %d rader och %d eller fler fält" -#: streamutil.c:378 +#: streamutil.c:455 #, c-format msgid "group access flag could not be parsed: %s" msgstr "gruppaccessflagga kunde inte parsas: %s" -#: streamutil.c:421 streamutil.c:458 +#: streamutil.c:498 streamutil.c:535 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "kunde inte identifiera system: fick %d rader och %d fält, förväntade %d rader och %d eller fler fält" -#: streamutil.c:510 +#: streamutil.c:587 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "kunde inte läsa replikeringsslot \"%s\": fick %d rader och %d fält, förväntade %d rader och %d fält" -#: streamutil.c:522 +#: streamutil.c:599 #, c-format msgid "replication slot \"%s\" does not exist" msgstr "replikeringsslot \"%s\" existerar inte" -#: streamutil.c:533 +#: streamutil.c:610 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "förväntade en fysisk replikeringsslot men fick av typen \"%s\" istället" -#: streamutil.c:547 +#: streamutil.c:624 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "kunde inte parsa restart_lsn \"%s\" för replikeringsslot \"%s\"" -#: streamutil.c:664 +#: streamutil.c:741 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "kunde inte skapa replikeringsslot \"%s\": fick %d rader och %d fält, förväntade %d rader och %d fält" -#: streamutil.c:708 +#: streamutil.c:785 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "kunde inte slänga replikeringsslot \"%s\": fick %d rader och %d fält, förväntade %d rader och %d fält" -#: walmethods.c:721 walmethods.c:1264 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "kunde inte komprimera data" -#: walmethods.c:750 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "kunde inte nollställa komprimeringsström" -#: walmethods.c:888 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "implementationsfel: tar-filer kan inte ha mer än en öppen fil" -#: walmethods.c:903 +#: walmethods.c:907 msgid "could not create tar header" msgstr "kunde inte skapa tar-header" -#: walmethods.c:920 walmethods.c:961 walmethods.c:1166 walmethods.c:1179 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "kunde inte ändra komprimeringsparametrar" -#: walmethods.c:1052 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "unlink stöds inte med komprimering" -#: walmethods.c:1288 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "kunde inte stänga komprimeringsström" - -#, c-format -#~ msgid "could not determine seek position in file \"%s\": %s" -#~ msgstr "kunde inte fastställa sökposition i fil \"%s\": %s" - -#, c-format -#~ msgid "symlinks are not supported on this platform" -#~ msgstr "symboliska länkar stöds inte på denna plattform" - -#, c-format -#~ msgid "this build does not support gzip compression" -#~ msgstr "detta bygge stöder inte gzip-komprimering" - -#, c-format -#~ msgid "this build does not support lz4 compression" -#~ msgstr "detta bygge stöder inte lz4-komprimering" - -#, c-format -#~ msgid "this build does not support zstd compression" -#~ msgstr "detta bygge stöder inte zstd-komprimering" diff --git a/src/bin/pg_basebackup/po/uk.po b/src/bin/pg_basebackup/po/uk.po index 695c62a9fd948..09cd1a552dde9 100644 --- a/src/bin/pg_basebackup/po/uk.po +++ b/src/bin/pg_basebackup/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:48+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:20+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_basebackup.pot\n" -"X-Crowdin-File-ID: 910\n" +"X-Crowdin-File: /REL_17_STABLE/pg_basebackup.pot\n" +"X-Crowdin-File-ID: 1006\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,84 +37,186 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " -#: ../../common/compression.c:157 +#: ../../common/compression.c:132 ../../common/compression.c:141 +#: ../../common/compression.c:150 bbstreamer_gzip.c:116 bbstreamer_gzip.c:249 +#: bbstreamer_lz4.c:100 bbstreamer_lz4.c:298 bbstreamer_zstd.c:129 +#: bbstreamer_zstd.c:284 +#, c-format +msgid "this build does not support compression with %s" +msgstr "ця збірка не підтримує стиснення з %s" + +#: ../../common/compression.c:205 msgid "found empty string where a compression option was expected" msgstr "знайдено порожній рядок, де очікувався параметр стискання" -#: ../../common/compression.c:187 +#: ../../common/compression.c:244 #, c-format -msgid "unknown compression option \"%s\"" -msgstr "невідомий параметр стискання \"%s\"" +msgid "unrecognized compression option: \"%s\"" +msgstr "нерозпізнаний алгоритм стискання: \"%s\"" -#: ../../common/compression.c:226 +#: ../../common/compression.c:283 #, c-format msgid "compression option \"%s\" requires a value" msgstr "параметр стискання \"%s\" потребує значення" -#: ../../common/compression.c:235 +#: ../../common/compression.c:292 #, c-format msgid "value for compression option \"%s\" must be an integer" msgstr "значення параметру стискання \"%s\" має бути цілим числом" -#: ../../common/compression.c:273 +#: ../../common/compression.c:331 +#, c-format +msgid "value for compression option \"%s\" must be a Boolean value" +msgstr "значення параметра стискання \"%s\" має бути логічним значенням" + +#: ../../common/compression.c:379 #, c-format msgid "compression algorithm \"%s\" does not accept a compression level" msgstr "алгоритм стискання \"%s\" не приймає рівень стискання" -#: ../../common/compression.c:277 +#: ../../common/compression.c:386 #, c-format -msgid "compression algorithm \"%s\" expects a compression level between %d and %d" -msgstr "алгоритм стискання \"%s\" очікує рівень стискання між %d і %d" +msgid "compression algorithm \"%s\" expects a compression level between %d and %d (default at %d)" +msgstr "алгоритм стискання \"%s\" очікує рівень стискання між %d і %d (за замовчуванням %d)" -#: ../../common/compression.c:289 +#: ../../common/compression.c:397 #, c-format msgid "compression algorithm \"%s\" does not accept a worker count" msgstr "алгоритм стиснення \"%s\" не приймає кількість працівників" +#: ../../common/compression.c:408 +#, c-format +msgid "compression algorithm \"%s\" does not support long-distance mode" +msgstr "алгоритм стиснення \"%s\" не підтримує режим довгої відстані" + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" + +#: ../../common/controldata_utils.c:110 pg_basebackup.c:1873 +#: pg_receivewal.c:402 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: bbstreamer_file.c:138 pg_recvlogical.c:650 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "неможливо закрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "можлива помилка у послідовності байтів.\n" +"Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: pg_basebackup.c:1846 pg_receivewal.c:386 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не вдалося записати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 pg_recvlogical.c:204 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 -#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format msgid "out of memory\n" msgstr "недостатньо пам'яті\n" -#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154 +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 #, c-format msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" -#: ../../common/file_utils.c:87 ../../common/file_utils.c:451 -#: pg_receivewal.c:380 pg_recvlogical.c:341 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_receivewal.c:319 pg_recvlogical.c:352 #, c-format msgid "could not stat file \"%s\": %m" msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" -#: ../../common/file_utils.c:166 pg_receivewal.c:303 +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_receivewal.c:242 #, c-format msgid "could not open directory \"%s\": %m" msgstr "не вдалося відкрити каталог \"%s\": %m" -#: ../../common/file_utils.c:200 pg_receivewal.c:534 +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_receivewal.c:471 #, c-format msgid "could not read directory \"%s\": %m" msgstr "не вдалося прочитати каталог \"%s\": %m" -#: ../../common/file_utils.c:232 ../../common/file_utils.c:291 -#: ../../common/file_utils.c:365 ../../fe_utils/recovery_gen.c:121 -#: pg_receivewal.c:447 +#: ../../common/file_utils.c:498 pg_basebackup.c:2344 walmethods.c:462 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" -#: ../../common/file_utils.c:303 ../../common/file_utils.c:373 -#: pg_recvlogical.c:196 +#: ../../common/restricted_token.c:60 #, c-format -msgid "could not fsync file \"%s\": %m" -msgstr "не вдалося fsync файл \"%s\": %m" +msgid "could not open process token: error code %lu" +msgstr "не вдалося відкрити токен процесу: код помилки %lu" -#: ../../common/file_utils.c:383 pg_basebackup.c:2256 walmethods.c:459 +#: ../../common/restricted_token.c:74 #, c-format -msgid "could not rename file \"%s\" to \"%s\": %m" -msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" +msgid "could not allocate SIDs: error code %lu" +msgstr "не вдалося виділити SID: код помилки %lu" + +#: ../../common/restricted_token.c:94 +#, c-format +msgid "could not create restricted token: error code %lu" +msgstr "не вдалося створити обмежений токен: код помилки %lu" + +#: ../../common/restricted_token.c:115 +#, c-format +msgid "could not start process for command \"%s\": error code %lu" +msgstr "не вдалося запустити процес для команди \"%s\": код помилки %lu" + +#: ../../common/restricted_token.c:153 +#, c-format +msgid "could not re-execute with restricted token: error code %lu" +msgstr "не вдалося перезапустити з обмеженим токеном: код помилки %lu" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -126,51 +228,62 @@ msgstr "неприпустиме значення \"%s\" для параметр msgid "%s must be in range %d..%d" msgstr "%s має бути в діапазоні %d..%d" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 pg_basebackup.c:1635 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 pg_basebackup.c:1636 streamutil.c:331 #, c-format msgid "out of memory" msgstr "недостатньо пам'яті" -#: ../../fe_utils/recovery_gen.c:124 bbstreamer_file.c:121 -#: bbstreamer_file.c:258 pg_basebackup.c:1432 pg_basebackup.c:1726 +#: ../../fe_utils/recovery_gen.c:143 bbstreamer_file.c:121 +#: bbstreamer_file.c:258 pg_basebackup.c:1433 pg_basebackup.c:1727 #, c-format msgid "could not write to file \"%s\": %m" msgstr "неможливо записати до файлу \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 bbstreamer_file.c:93 bbstreamer_file.c:339 -#: pg_basebackup.c:1496 pg_basebackup.c:1705 +#: ../../fe_utils/recovery_gen.c:152 bbstreamer_file.c:93 bbstreamer_file.c:361 +#: pg_basebackup.c:1497 pg_basebackup.c:1706 #, c-format msgid "could not create file \"%s\": %m" msgstr "неможливо створити файл \"%s\": %m" -#: bbstreamer_file.c:138 pg_recvlogical.c:635 +#: ../../fe_utils/string_utils.c:434 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "неможливо закрити файл \"%s\": %m" +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" #: bbstreamer_file.c:275 #, c-format msgid "unexpected state while extracting archive" msgstr "неочікуваний стан під час розпакування архіву" -#: bbstreamer_file.c:298 pg_basebackup.c:686 pg_basebackup.c:730 +#: bbstreamer_file.c:321 pg_basebackup.c:698 pg_basebackup.c:712 +#: pg_basebackup.c:757 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не вдалося створити каталог \"%s\": %m" -#: bbstreamer_file.c:304 +#: bbstreamer_file.c:326 #, c-format msgid "could not set permissions on directory \"%s\": %m" msgstr "не вдалося встановити права для каталогу \"%s\": %m" -#: bbstreamer_file.c:323 +#: bbstreamer_file.c:345 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "не вдалося створити символічне послання з \"%s\" на \"%s\": %m" -#: bbstreamer_file.c:343 +#: bbstreamer_file.c:365 #, c-format msgid "could not set permissions on file \"%s\": %m" msgstr "не вдалося встановити права на файл \"%s\": %m" @@ -190,32 +303,27 @@ msgstr "не вдалося дублювати stdout: %m" msgid "could not open output file: %m" msgstr "не вдалося відкрити вихідний файл: %m" -#: bbstreamer_gzip.c:113 +#: bbstreamer_gzip.c:111 #, c-format msgid "could not set compression level %d: %s" msgstr "не вдалося встановити рівень стискання %d: %s" -#: bbstreamer_gzip.c:118 bbstreamer_gzip.c:251 -#, c-format -msgid "this build does not support gzip compression" -msgstr "ця збірка не підтримує стиснення gzip" - -#: bbstreamer_gzip.c:145 +#: bbstreamer_gzip.c:143 #, c-format msgid "could not write to compressed file \"%s\": %s" msgstr "не вдалося записати до стиснутого файлу \"%s\": %s" -#: bbstreamer_gzip.c:169 +#: bbstreamer_gzip.c:167 #, c-format msgid "could not close compressed file \"%s\": %m" msgstr "не вдалося закрити стиснутий файл \"%s\": %m" -#: bbstreamer_gzip.c:247 walmethods.c:869 +#: bbstreamer_gzip.c:245 walmethods.c:880 #, c-format msgid "could not initialize compression library" msgstr "не вдалося ініціалізувати бібліотеку стискання" -#: bbstreamer_gzip.c:298 bbstreamer_lz4.c:355 bbstreamer_zstd.c:319 +#: bbstreamer_gzip.c:296 bbstreamer_lz4.c:354 bbstreamer_zstd.c:329 #, c-format msgid "could not decompress data: %s" msgstr "не вдалося розпакувати дані: %s" @@ -225,32 +333,27 @@ msgstr "не вдалося розпакувати дані: %s" msgid "unexpected state while injecting recovery settings" msgstr "неочікуваний стан під час введення налаштувань відновлення" -#: bbstreamer_lz4.c:96 +#: bbstreamer_lz4.c:95 #, c-format msgid "could not create lz4 compression context: %s" msgstr "не вдалося створити контекст стиснення lz4: %s" -#: bbstreamer_lz4.c:101 bbstreamer_lz4.c:299 -#, c-format -msgid "this build does not support lz4 compression" -msgstr "ця збірка не підтримує стиснення lz4" - -#: bbstreamer_lz4.c:141 +#: bbstreamer_lz4.c:140 #, c-format msgid "could not write lz4 header: %s" msgstr "не вдалося записати заголовок lz4: %s" -#: bbstreamer_lz4.c:190 bbstreamer_zstd.c:171 bbstreamer_zstd.c:213 +#: bbstreamer_lz4.c:189 bbstreamer_zstd.c:181 bbstreamer_zstd.c:223 #, c-format msgid "could not compress data: %s" msgstr "не вдалося стиснути дані: %s" -#: bbstreamer_lz4.c:242 +#: bbstreamer_lz4.c:241 #, c-format msgid "could not end lz4 compression: %s" msgstr "не вдалося закінчити стискання lz4: %s" -#: bbstreamer_lz4.c:294 +#: bbstreamer_lz4.c:293 #, c-format msgid "could not initialize compression library: %s" msgstr "не вдалося ініціалізувати бібліотеку стиснення: %s" @@ -265,12 +368,12 @@ msgstr "причіп файлу tar перевищує 2 блоки" msgid "unexpected state while parsing tar archive" msgstr "неочікуваний стан під час розбору архіву tar" -#: bbstreamer_tar.c:296 +#: bbstreamer_tar.c:292 #, c-format msgid "tar member has empty name" msgstr "частина tar містить порожню назву" -#: bbstreamer_tar.c:328 +#: bbstreamer_tar.c:326 #, c-format msgid "COPY stream ended before last file was finished" msgstr "потік COPY завершився до завершення останнього файлу" @@ -280,397 +383,415 @@ msgstr "потік COPY завершився до завершення оста msgid "could not create zstd compression context" msgstr "не вдалося створити контекст стиснення zstd" -#: bbstreamer_zstd.c:93 +#: bbstreamer_zstd.c:91 #, c-format msgid "could not set zstd compression level to %d: %s" msgstr "не вдалося встановити рівень стискання zstd на %d: %s" -#: bbstreamer_zstd.c:108 +#: bbstreamer_zstd.c:105 #, c-format msgid "could not set compression worker count to %d: %s" msgstr "не вдалося встановити кількість процесів стискання на %d: %s" -#: bbstreamer_zstd.c:119 bbstreamer_zstd.c:274 +#: bbstreamer_zstd.c:116 #, c-format -msgid "this build does not support zstd compression" -msgstr "ця збірка не підтримує стиснення zstd" +msgid "could not enable long-distance mode: %s" +msgstr "не вдалося включити режим довгої відстані: %s" -#: bbstreamer_zstd.c:265 +#: bbstreamer_zstd.c:275 #, c-format msgid "could not create zstd decompression context" msgstr "не вдалося створити контекст zstd декомпресії" -#: pg_basebackup.c:240 +#: pg_basebackup.c:245 #, c-format msgid "removing data directory \"%s\"" msgstr "видалення даних з директорії \"%s\"" -#: pg_basebackup.c:242 +#: pg_basebackup.c:247 #, c-format msgid "failed to remove data directory" msgstr "не вдалося видалити дані директорії" -#: pg_basebackup.c:246 +#: pg_basebackup.c:251 #, c-format msgid "removing contents of data directory \"%s\"" msgstr "видалення даних з директорії \"%s\"" -#: pg_basebackup.c:248 +#: pg_basebackup.c:253 #, c-format msgid "failed to remove contents of data directory" msgstr "не вдалося видалити дані директорії" -#: pg_basebackup.c:253 +#: pg_basebackup.c:258 #, c-format msgid "removing WAL directory \"%s\"" msgstr "видалення WAL директорії \"%s\"" -#: pg_basebackup.c:255 +#: pg_basebackup.c:260 #, c-format msgid "failed to remove WAL directory" msgstr "не вдалося видалити директорію WAL" -#: pg_basebackup.c:259 +#: pg_basebackup.c:264 #, c-format msgid "removing contents of WAL directory \"%s\"" msgstr "видалення даних з директорії WAL \"%s\"" -#: pg_basebackup.c:261 +#: pg_basebackup.c:266 #, c-format msgid "failed to remove contents of WAL directory" msgstr "не вдалося видалити дані директорії WAL" -#: pg_basebackup.c:267 +#: pg_basebackup.c:272 #, c-format msgid "data directory \"%s\" not removed at user's request" msgstr "директорія даних \"%s\" не видалена за запитом користувача" -#: pg_basebackup.c:270 +#: pg_basebackup.c:275 #, c-format msgid "WAL directory \"%s\" not removed at user's request" msgstr "директорія WAL \"%s\" не видалена за запитом користувача" -#: pg_basebackup.c:274 +#: pg_basebackup.c:279 #, c-format msgid "changes to tablespace directories will not be undone" msgstr "зміни в каталогах табличних просторів незворотні" -#: pg_basebackup.c:326 +#: pg_basebackup.c:331 #, c-format msgid "directory name too long" msgstr "ім'я директорії задовге" -#: pg_basebackup.c:333 +#: pg_basebackup.c:338 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "кілька знаків \"=\" зіставленні табличних просторів" -#: pg_basebackup.c:342 +#: pg_basebackup.c:347 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "неприпустимий табличний простір зіставлення формату \"%s\", має бути \"OLDDIR = NEWDIR\"" -#: pg_basebackup.c:351 +#: pg_basebackup.c:366 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "старий каталог не є абсолютним шляхом у зіставлення табличного простору: %s" -#: pg_basebackup.c:355 +#: pg_basebackup.c:370 #, c-format msgid "new directory is not an absolute path in tablespace mapping: %s" msgstr "новий каталог не є абсолютним шляхом у зіставлення табличного простору: %s" -#: pg_basebackup.c:377 +#: pg_basebackup.c:392 #, c-format msgid "%s takes a base backup of a running PostgreSQL server.\n\n" msgstr "%s робить базову резервну копію працюючого сервера PostgreSQL.\n\n" -#: pg_basebackup.c:379 pg_receivewal.c:81 pg_recvlogical.c:78 +#: pg_basebackup.c:394 pg_createsubscriber.c:221 pg_receivewal.c:79 +#: pg_recvlogical.c:86 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_basebackup.c:380 pg_receivewal.c:82 pg_recvlogical.c:79 +#: pg_basebackup.c:395 pg_createsubscriber.c:222 pg_receivewal.c:80 +#: pg_recvlogical.c:87 #, c-format msgid " %s [OPTION]...\n" msgstr " %s: [OPTION]...\n" -#: pg_basebackup.c:381 +#: pg_basebackup.c:396 #, c-format msgid "\n" "Options controlling the output:\n" msgstr "\n" "Параметри, що контролюють вивід:\n" -#: pg_basebackup.c:382 +#: pg_basebackup.c:397 #, c-format msgid " -D, --pgdata=DIRECTORY receive base backup into directory\n" msgstr " -D, -- pgdata=DIRECTORY директорія, в яку зберегти резервну копію бази\n" -#: pg_basebackup.c:383 +#: pg_basebackup.c:398 #, c-format msgid " -F, --format=p|t output format (plain (default), tar)\n" msgstr " -F, --format=p|т формат виводу (звичайний за замовчуванням, tar)\n" -#: pg_basebackup.c:384 +#: pg_basebackup.c:399 +#, c-format +msgid " -i, --incremental=OLDMANIFEST\n" +" take incremental backup\n" +msgstr " -i, --incremental=OLDMANIFEST\n" +" створювати інкрементні резервні копії\n" + +#: pg_basebackup.c:401 #, c-format msgid " -r, --max-rate=RATE maximum transfer rate to transfer data directory\n" " (in kB/s, or use suffix \"k\" or \"M\")\n" msgstr " -r, --max-rate=RATE максимальна швидкість передавання даних до директорії\n" " (у кБ/с або з використанням суфіксів \"k\" або \"М\")\n" -#: pg_basebackup.c:386 +#: pg_basebackup.c:403 #, c-format msgid " -R, --write-recovery-conf\n" " write configuration for replication\n" msgstr " -R, --write-recovery-conf\n" " записати конфігурацію для реплікації\n" -#: pg_basebackup.c:388 +#: pg_basebackup.c:405 #, c-format msgid " -t, --target=TARGET[:DETAIL]\n" " backup target (if other than client)\n" msgstr " -t, --target=TARGET[:DETAIL]\n" " ціль резервного копіювання (якщо не клієнт)\n" -#: pg_basebackup.c:390 +#: pg_basebackup.c:407 #, c-format msgid " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" " relocate tablespace in OLDDIR to NEWDIR\n" msgstr " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" " перенестb табличний простір з OLDDIR до NEWDIR\n" -#: pg_basebackup.c:392 +#: pg_basebackup.c:409 #, c-format msgid " --waldir=WALDIR location for the write-ahead log directory\n" msgstr "--waldir=WALDIR розташування журналу попереднього запису\n" -#: pg_basebackup.c:393 +#: pg_basebackup.c:410 #, c-format msgid " -X, --wal-method=none|fetch|stream\n" " include required WAL files with specified method\n" msgstr " -X, --wal-method=none|fetch|stream\n" " додати необхідні WAL файли за допомогою вказаного методу\n" -#: pg_basebackup.c:395 +#: pg_basebackup.c:412 #, c-format msgid " -z, --gzip compress tar output\n" msgstr " -z, --gzip стиснути вихідний tar\n" -#: pg_basebackup.c:396 +#: pg_basebackup.c:413 #, c-format msgid " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" " compress on client or server as specified\n" msgstr " -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n" " стискати на клієнті або сервері, як зазначено\n" -#: pg_basebackup.c:398 +#: pg_basebackup.c:415 #, c-format msgid " -Z, --compress=none do not compress tar output\n" msgstr " -Z, --compress=none не стискати вивід tar\n" -#: pg_basebackup.c:399 +#: pg_basebackup.c:416 #, c-format msgid "\n" "General options:\n" msgstr "\n" "Основні налаштування:\n" -#: pg_basebackup.c:400 +#: pg_basebackup.c:417 #, c-format msgid " -c, --checkpoint=fast|spread\n" -" set fast or spread checkpointing\n" +" set fast or spread (default) checkpointing\n" msgstr " -c, --checkpoint=fast|spread\n" -" режим швидких або розділених контрольних точок\n" +" встановлювати швидкі або розподілені (за замовчуванням) контрольні точки\n" -#: pg_basebackup.c:402 +#: pg_basebackup.c:419 #, c-format msgid " -C, --create-slot create replication slot\n" msgstr " -C, --create-slot створити слот для реплікації\n" -#: pg_basebackup.c:403 +#: pg_basebackup.c:420 #, c-format msgid " -l, --label=LABEL set backup label\n" msgstr " -l, --label=LABEL встановити мітку резервної копії\n" -#: pg_basebackup.c:404 +#: pg_basebackup.c:421 #, c-format msgid " -n, --no-clean do not clean up after errors\n" msgstr " -n, --no-clean не очищати після помилок\n" -#: pg_basebackup.c:405 +#: pg_basebackup.c:422 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync не чекати завершення збереження даних на диску\n" -#: pg_basebackup.c:406 +#: pg_basebackup.c:423 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress відображати інформацію про прогрес\n" -#: pg_basebackup.c:407 pg_receivewal.c:91 +#: pg_basebackup.c:424 pg_receivewal.c:89 #, c-format msgid " -S, --slot=SLOTNAME replication slot to use\n" msgstr " -S, --slot=ИМ'Я_СЛОТА використовувати вказаний слот реплікації\n" -#: pg_basebackup.c:408 pg_receivewal.c:93 pg_recvlogical.c:100 +#: pg_basebackup.c:425 pg_receivewal.c:91 pg_recvlogical.c:108 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose виводити детальні повідомлення\n" -#: pg_basebackup.c:409 pg_receivewal.c:94 pg_recvlogical.c:101 +#: pg_basebackup.c:426 pg_receivewal.c:92 pg_recvlogical.c:109 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: pg_basebackup.c:410 +#: pg_basebackup.c:427 #, c-format msgid " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " use algorithm for manifest checksums\n" msgstr " --manifest-checksums=SHA{224,256,384,512}|CRC32C|НЕ\n" " використовувати алгоритм для контрольних сум маніфесту\n" -#: pg_basebackup.c:412 +#: pg_basebackup.c:429 #, c-format msgid " --manifest-force-encode\n" " hex encode all file names in manifest\n" msgstr " --manifest-force-encode\n" " кодувати у hex всі імена файлів у маніфесті\n" -#: pg_basebackup.c:414 +#: pg_basebackup.c:431 #, c-format msgid " --no-estimate-size do not estimate backup size in server side\n" msgstr " --no-estimate-size не оцінювати розмір резервної копії на стороні сервера\n" -#: pg_basebackup.c:415 +#: pg_basebackup.c:432 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest пропустити створення маніфесту резервного копіювання\n" -#: pg_basebackup.c:416 +#: pg_basebackup.c:433 #, c-format msgid " --no-slot prevent creation of temporary replication slot\n" msgstr " --no-slot не створювати тимчасового слоту реплікації\n" -#: pg_basebackup.c:417 +#: pg_basebackup.c:434 #, c-format msgid " --no-verify-checksums\n" " do not verify checksums\n" msgstr " --no-verify-checksums\n" " не перевіряти контрольні суми\n" -#: pg_basebackup.c:419 pg_receivewal.c:97 pg_recvlogical.c:102 +#: pg_basebackup.c:436 +#, c-format +msgid " --sync-method=METHOD\n" +" set method for syncing files to disk\n" +msgstr " --sync-method=METHOD\n" +" встановити метод синхронізації файлів на диск\n" + +#: pg_basebackup.c:438 pg_receivewal.c:95 pg_recvlogical.c:110 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку потім вийти\n" -#: pg_basebackup.c:420 pg_receivewal.c:98 pg_recvlogical.c:103 +#: pg_basebackup.c:439 pg_receivewal.c:96 pg_recvlogical.c:111 #, c-format msgid "\n" "Connection options:\n" msgstr "\n" "Налаштування з'єднання:\n" -#: pg_basebackup.c:421 pg_receivewal.c:99 +#: pg_basebackup.c:440 pg_receivewal.c:97 #, c-format msgid " -d, --dbname=CONNSTR connection string\n" msgstr " -d, --dbname=CONNSTR рядок з'єднання\n" -#: pg_basebackup.c:422 pg_receivewal.c:100 pg_recvlogical.c:105 +#: pg_basebackup.c:441 pg_receivewal.c:98 pg_recvlogical.c:113 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME хост сервера бази даних або каталог сокетів\n" -#: pg_basebackup.c:423 pg_receivewal.c:101 pg_recvlogical.c:106 +#: pg_basebackup.c:442 pg_receivewal.c:99 pg_recvlogical.c:114 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT порт сервера бази даних\n" -#: pg_basebackup.c:424 +#: pg_basebackup.c:443 #, c-format msgid " -s, --status-interval=INTERVAL\n" " time between status packets sent to server (in seconds)\n" msgstr " -s, --status-interval=INTERVAL часу між пакетами статусу до сервера (у секундах)\n" -#: pg_basebackup.c:426 pg_receivewal.c:102 pg_recvlogical.c:107 +#: pg_basebackup.c:445 pg_receivewal.c:100 pg_recvlogical.c:115 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME підключатись як вказаний користувач бази даних\n" -#: pg_basebackup.c:427 pg_receivewal.c:103 pg_recvlogical.c:108 +#: pg_basebackup.c:446 pg_receivewal.c:101 pg_recvlogical.c:116 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не питати пароль\n" -#: pg_basebackup.c:428 pg_receivewal.c:104 pg_recvlogical.c:109 +#: pg_basebackup.c:447 pg_receivewal.c:102 pg_recvlogical.c:117 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password обов'язково питати пароль (повинно відбуватися автоматично)\n" -#: pg_basebackup.c:429 pg_receivewal.c:108 pg_recvlogical.c:110 +#: pg_basebackup.c:448 pg_createsubscriber.c:240 pg_receivewal.c:106 +#: pg_recvlogical.c:118 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_basebackup.c:430 pg_receivewal.c:109 pg_recvlogical.c:111 +#: pg_basebackup.c:449 pg_createsubscriber.c:241 pg_receivewal.c:107 +#: pg_recvlogical.c:119 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_basebackup.c:472 +#: pg_basebackup.c:488 #, c-format msgid "could not read from ready pipe: %m" msgstr "не можливо прочитати з готових каналів: %m" -#: pg_basebackup.c:475 pg_basebackup.c:622 pg_basebackup.c:2170 -#: streamutil.c:444 +#: pg_basebackup.c:491 pg_basebackup.c:633 pg_basebackup.c:2258 +#: streamutil.c:518 #, c-format msgid "could not parse write-ahead log location \"%s\"" msgstr "не вдалося проаналізувати наперед журнал локації \"%s\"" -#: pg_basebackup.c:581 pg_receivewal.c:665 +#: pg_basebackup.c:596 pg_receivewal.c:600 #, c-format msgid "could not finish writing WAL files: %m" msgstr "не можливо закінчити написання файлів WAL: %m" -#: pg_basebackup.c:631 +#: pg_basebackup.c:642 #, c-format msgid "could not create pipe for background process: %m" msgstr "не можливо створити канал для фонового процесу: %m" -#: pg_basebackup.c:664 +#: pg_basebackup.c:676 #, c-format msgid "created temporary replication slot \"%s\"" msgstr "створено слот тимчасових реплікацій \"%s\"" -#: pg_basebackup.c:667 +#: pg_basebackup.c:679 #, c-format msgid "created replication slot \"%s\"" msgstr "створено слот реплікацій \"%s\"" -#: pg_basebackup.c:701 +#: pg_basebackup.c:728 #, c-format msgid "could not create background process: %m" msgstr "не можливо створити фоновий процес: %m" -#: pg_basebackup.c:710 +#: pg_basebackup.c:737 #, c-format msgid "could not create background thread: %m" msgstr "не можливо створити фоновий потік: %m" -#: pg_basebackup.c:749 +#: pg_basebackup.c:776 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "каталог \"%s\" існує, але він не порожній" -#: pg_basebackup.c:755 +#: pg_basebackup.c:782 pg_createsubscriber.c:390 #, c-format msgid "could not access directory \"%s\": %m" msgstr "немає доступу до каталогу \"%s\": %m" -#: pg_basebackup.c:832 +#: pg_basebackup.c:858 #, c-format msgid "%*s/%s kB (100%%), %d/%d tablespace %*s" msgid_plural "%*s/%s kB (100%%), %d/%d tablespaces %*s" @@ -679,7 +800,7 @@ msgstr[1] "%*s/%s kB (100%%), %d/%d табличних простори %*s" msgstr[2] "%*s/%s kB (100%%), %d/%d табличних просторів %*s" msgstr[3] "%*s/%s kB (100%%), %d/%d табличних просторів %*s" -#: pg_basebackup.c:844 +#: pg_basebackup.c:870 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)" @@ -688,7 +809,7 @@ msgstr[1] "%*s/%s kB (%d%%), %d/%d табличних простори (%s%-*.*s msgstr[2] "%*s/%s kB (%d%%), %d/%d табличних просторів (%s%-*.*s)" msgstr[3] "%*s/%s kB (%d%%), %d/%d табличних просторів (%s%-*.*s)" -#: pg_basebackup.c:860 +#: pg_basebackup.c:886 #, c-format msgid "%*s/%s kB (%d%%), %d/%d tablespace" msgid_plural "%*s/%s kB (%d%%), %d/%d tablespaces" @@ -697,661 +818,1313 @@ msgstr[1] "%*s/%s kB (%d%%), %d/%d табличних простори" msgstr[2] "%*s/%s kB (%d%%), %d/%d табличних просторів" msgstr[3] "%*s/%s kB (%d%%), %d/%d табличних просторів" -#: pg_basebackup.c:884 +#: pg_basebackup.c:910 #, c-format msgid "transfer rate \"%s\" is not a valid value" msgstr "частота передач \"%s\" не є припустимим значенням" -#: pg_basebackup.c:886 +#: pg_basebackup.c:912 #, c-format msgid "invalid transfer rate \"%s\": %m" msgstr "неприпустима частота передач \"%s\": %m" -#: pg_basebackup.c:893 +#: pg_basebackup.c:919 #, c-format msgid "transfer rate must be greater than zero" msgstr "частота передач повинна бути більша за нуль" -#: pg_basebackup.c:923 +#: pg_basebackup.c:949 #, c-format msgid "invalid --max-rate unit: \"%s\"" msgstr "неприпустима одиниця виміру в --max-rate: \"%s\"" -#: pg_basebackup.c:927 +#: pg_basebackup.c:953 #, c-format msgid "transfer rate \"%s\" exceeds integer range" msgstr "швидкість передачі \"%s\" перевищує діапазон цілого числа" -#: pg_basebackup.c:934 +#: pg_basebackup.c:960 #, c-format msgid "transfer rate \"%s\" is out of range" msgstr "швидкість передавання \"%s\" поза діапазоном" -#: pg_basebackup.c:1030 +#: pg_basebackup.c:1022 #, c-format msgid "could not get COPY data stream: %s" msgstr "не вдалося отримати потік даних COPY: %s" -#: pg_basebackup.c:1047 pg_recvlogical.c:438 pg_recvlogical.c:610 -#: receivelog.c:981 +#: pg_basebackup.c:1039 pg_recvlogical.c:449 pg_recvlogical.c:625 +#: receivelog.c:973 #, c-format msgid "could not read COPY data: %s" msgstr "не вдалося прочитати дані COPY: %s" -#: pg_basebackup.c:1051 +#: pg_basebackup.c:1043 #, c-format msgid "background process terminated unexpectedly" msgstr "фоновий процес несподівано перервано" -#: pg_basebackup.c:1122 +#: pg_basebackup.c:1114 #, c-format -msgid "cannot inject manifest into a compressed tarfile" +msgid "cannot inject manifest into a compressed tar file" msgstr "неможливо підставити маніфест в стиснений tar-файл" -#: pg_basebackup.c:1123 +#: pg_basebackup.c:1115 #, c-format -msgid "use client-side compression, send the output to a directory rather than standard output, or use --no-manifest" -msgstr "використйте стиснення на клієнті та відправлення даних в каталог замість стандартного виводу, або використайте параметр --no-manifest" +msgid "Use client-side compression, send the output to a directory rather than standard output, or use %s." +msgstr "Використайте стиснення на клієнті та відправлення даних в каталог замість стандартного виводу, або використайте %s." -#: pg_basebackup.c:1138 +#: pg_basebackup.c:1131 #, c-format -msgid "unable to parse archive: %s" -msgstr "не вдалося розібрати архів: %s" +msgid "cannot parse archive \"%s\"" +msgstr "неможливо розібрати архів \"%s\"" -#: pg_basebackup.c:1139 +#: pg_basebackup.c:1132 #, c-format msgid "Only tar archives can be parsed." msgstr "Тільки архів tar може бути проаналізований." -#: pg_basebackup.c:1141 +#: pg_basebackup.c:1134 #, c-format msgid "Plain format requires pg_basebackup to parse the archive." msgstr "Простий формат потребує обробки архіву в pg_basebackup для обробки." -#: pg_basebackup.c:1143 +#: pg_basebackup.c:1136 #, c-format msgid "Using - as the output directory requires pg_basebackup to parse the archive." msgstr "Використання - в якості вихідного каталогу потребує pg_basebackup для аналізу архіву." -#: pg_basebackup.c:1145 +#: pg_basebackup.c:1138 #, c-format msgid "The -R option requires pg_basebackup to parse the archive." msgstr "Параметр -R потребує використання pg_basebackup для аналізу архіву." -#: pg_basebackup.c:1356 +#: pg_basebackup.c:1357 #, c-format -msgid "archives should precede manifest" +msgid "archives must precede manifest" msgstr "архіви повинні передувати маніфесту" -#: pg_basebackup.c:1371 +#: pg_basebackup.c:1372 #, c-format msgid "invalid archive name: \"%s\"" msgstr "неприпустиме ім'я архіву: \"%s\"" -#: pg_basebackup.c:1443 +#: pg_basebackup.c:1444 #, c-format msgid "unexpected payload data" msgstr "неочікувані дані корисного навантаження" -#: pg_basebackup.c:1586 +#: pg_basebackup.c:1587 #, c-format msgid "empty COPY message" msgstr "порожнє повідомлення COPY" -#: pg_basebackup.c:1588 +#: pg_basebackup.c:1589 #, c-format msgid "malformed COPY message of type %d, length %zu" msgstr "неправильне повідомлення COPY з типом %d, довжина %zu" -#: pg_basebackup.c:1786 +#: pg_basebackup.c:1789 #, c-format msgid "incompatible server version %s" msgstr "несумісна версія серверу %s" -#: pg_basebackup.c:1802 +#: pg_basebackup.c:1805 +#, c-format +msgid "Use -X none or -X fetch to disable log streaming." +msgstr "Використайте -X none або -X fetch, щоб вимкнути потокову передачу журналу." + +#: pg_basebackup.c:1841 +#, c-format +msgid "server does not support incremental backup" +msgstr "сервер не підтримує інкрементне резервне копіювання" + +#: pg_basebackup.c:1850 pg_basebackup.c:2008 pg_recvlogical.c:272 +#: receivelog.c:543 receivelog.c:582 streamutil.c:364 streamutil.c:438 +#: streamutil.c:490 streamutil.c:578 streamutil.c:730 streamutil.c:775 +#, c-format +msgid "could not send replication command \"%s\": %s" +msgstr "не вдалося відправити реплікаційну команду \"%s\": %s" + +#: pg_basebackup.c:1856 pg_basebackup.c:1883 +#, c-format +msgid "could not upload manifest: %s" +msgstr "не вдалося завантажити маніфест: %s" + +#: pg_basebackup.c:1859 pg_basebackup.c:1886 #, c-format -msgid "HINT: use -X none or -X fetch to disable log streaming" -msgstr "ПІДКАЗКА: використайте -X none або -X fetch, щоб вимкнути потокову передачу журналу" +msgid "could not upload manifest: unexpected status %s" +msgstr "не вдалося завантажити маніфест: неочікуваний статус %s" -#: pg_basebackup.c:1870 +#: pg_basebackup.c:1867 +#, c-format +msgid "could not send COPY data: %s" +msgstr "не вдалося надіслати дані COPY: %s" + +#: pg_basebackup.c:1877 +#, c-format +msgid "could not send end-of-COPY: %s" +msgstr "не вдалося надіслати сповіщення про закінчення копіювання: %s" + +#: pg_basebackup.c:1892 +#, c-format +msgid "unexpected extra result while sending manifest" +msgstr "несподіваний додатковий результат під час надсилання маніфесту" + +#: pg_basebackup.c:1950 #, c-format msgid "backup targets are not supported by this server version" msgstr "цілі резервного копіювання не підтримуються цією версією сервера" -#: pg_basebackup.c:1873 +#: pg_basebackup.c:1953 #, c-format msgid "recovery configuration cannot be written when a backup target is used" msgstr "конфігурація відновлення не може бути записана під час використання цілі резервного копіювання" -#: pg_basebackup.c:1900 +#: pg_basebackup.c:1980 #, c-format msgid "server does not support server-side compression" msgstr "сервер не підтримує стиснення на сервері" -#: pg_basebackup.c:1910 +#: pg_basebackup.c:1990 #, c-format msgid "initiating base backup, waiting for checkpoint to complete" msgstr "початок базового резервного копіювання, очікується завершення контрольної точки" -#: pg_basebackup.c:1927 pg_recvlogical.c:262 receivelog.c:549 receivelog.c:588 -#: streamutil.c:291 streamutil.c:364 streamutil.c:416 streamutil.c:504 -#: streamutil.c:656 streamutil.c:701 +#: pg_basebackup.c:1994 #, c-format -msgid "could not send replication command \"%s\": %s" -msgstr "не вдалося відправити реплікаційну команду \"%s\": %s" +msgid "waiting for checkpoint" +msgstr "очікування контрольної точки" -#: pg_basebackup.c:1935 +#: pg_basebackup.c:2016 #, c-format msgid "could not initiate base backup: %s" msgstr "не вдалося почати базове резервне копіювання: %s" -#: pg_basebackup.c:1938 +#: pg_basebackup.c:2019 #, c-format msgid "server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields" msgstr "сервер повернув неочікувану відповідь на команду BASE_BACKUP; отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: pg_basebackup.c:1944 +#: pg_basebackup.c:2025 #, c-format msgid "checkpoint completed" msgstr "контрольна точка завершена" -#: pg_basebackup.c:1959 +#: pg_basebackup.c:2039 #, c-format msgid "write-ahead log start point: %s on timeline %u" msgstr "стартова точка у випереджувальному журналюванні: %s на часовій шкалі %u" -#: pg_basebackup.c:1967 +#: pg_basebackup.c:2047 #, c-format msgid "could not get backup header: %s" msgstr "не вдалося отримати заголовок резервної копії: %s" -#: pg_basebackup.c:1970 +#: pg_basebackup.c:2050 #, c-format msgid "no data returned from server" msgstr "сервер не повернув дані" -#: pg_basebackup.c:2005 +#: pg_basebackup.c:2093 #, c-format msgid "can only write single tablespace to stdout, database has %d" msgstr "можна записати лише один табличний простір в stdout, всього їх в базі даних %d" -#: pg_basebackup.c:2018 +#: pg_basebackup.c:2106 #, c-format msgid "starting background WAL receiver" msgstr "запуск фонового процесу зчитування WAL" -#: pg_basebackup.c:2101 +#: pg_basebackup.c:2189 #, c-format msgid "backup failed: %s" msgstr "помилка резервного копіювання: %s" -#: pg_basebackup.c:2104 +#: pg_basebackup.c:2192 #, c-format msgid "no write-ahead log end position returned from server" msgstr "сервер не повернув кінцеву позицію у випереджувальному журналюванні" -#: pg_basebackup.c:2107 +#: pg_basebackup.c:2195 #, c-format msgid "write-ahead log end point: %s" msgstr "кінцева точка у випереджувальному журналюванні: %s" -#: pg_basebackup.c:2118 +#: pg_basebackup.c:2206 #, c-format msgid "checksum error occurred" msgstr "сталася помилка контрольної суми" -#: pg_basebackup.c:2123 +#: pg_basebackup.c:2211 #, c-format msgid "final receive failed: %s" msgstr "помилка в кінці передачі: %s" -#: pg_basebackup.c:2147 +#: pg_basebackup.c:2235 #, c-format msgid "waiting for background process to finish streaming ..." msgstr "очікування завершення потокового передавання фоновим процесом ..." -#: pg_basebackup.c:2151 +#: pg_basebackup.c:2239 #, c-format msgid "could not send command to background pipe: %m" msgstr "не вдалося надіслати команду до канала фонового процесу: %m" -#: pg_basebackup.c:2156 +#: pg_basebackup.c:2244 #, c-format msgid "could not wait for child process: %m" msgstr "збій при очікуванні дочірнього процесу: %m" -#: pg_basebackup.c:2158 +#: pg_basebackup.c:2246 #, c-format msgid "child %d died, expected %d" msgstr "завершився дочірній процес %d, очікувалося %d" -#: pg_basebackup.c:2160 streamutil.c:91 streamutil.c:197 +#: pg_basebackup.c:2248 streamutil.c:89 streamutil.c:204 streamutil.c:316 #, c-format msgid "%s" msgstr "%s" -#: pg_basebackup.c:2180 +#: pg_basebackup.c:2268 #, c-format msgid "could not wait for child thread: %m" msgstr "неможливо дочекатися дочірнього потоку: %m" -#: pg_basebackup.c:2185 +#: pg_basebackup.c:2273 #, c-format msgid "could not get child thread exit status: %m" msgstr "не можливо отримати статус завершення дочірнього потоку: %m" -#: pg_basebackup.c:2188 +#: pg_basebackup.c:2276 #, c-format msgid "child thread exited with error %u" msgstr "дочірній потік завершився з помилкою %u" -#: pg_basebackup.c:2217 +#: pg_basebackup.c:2305 #, c-format msgid "syncing data to disk ..." msgstr "синхронізація даних з диском ..." -#: pg_basebackup.c:2242 +#: pg_basebackup.c:2330 #, c-format msgid "renaming backup_manifest.tmp to backup_manifest" msgstr "перейменування backup_manifest.tmp в backup_manifest" -#: pg_basebackup.c:2262 +#: pg_basebackup.c:2350 #, c-format msgid "base backup completed" msgstr "базове резервне копіювання завершено" -#: pg_basebackup.c:2351 +#: pg_basebackup.c:2436 +#, c-format +msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" +msgstr "неприпустимий аргумент контрольної точки \"%s\", повинен бути \"fast\" або \"spread\"" + +#: pg_basebackup.c:2454 #, c-format msgid "invalid output format \"%s\", must be \"plain\" or \"tar\"" msgstr "неприпустимий формат виводу \"%s\", повинен бути \"plain\" або \"tar\"" -#: pg_basebackup.c:2395 +#: pg_basebackup.c:2535 #, c-format msgid "invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"" msgstr "неприпустимий параметр wal-method \"%s\", повинен бути \"fetch\", \"stream\" або \"none\"" -#: pg_basebackup.c:2425 -#, c-format -msgid "invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"" -msgstr "неприпустимий аргумент контрольної точки \"%s\", повинен бути \"fast\" або \"spread\"" - -#: pg_basebackup.c:2476 pg_basebackup.c:2488 pg_basebackup.c:2510 -#: pg_basebackup.c:2522 pg_basebackup.c:2528 pg_basebackup.c:2580 -#: pg_basebackup.c:2591 pg_basebackup.c:2601 pg_basebackup.c:2607 -#: pg_basebackup.c:2614 pg_basebackup.c:2626 pg_basebackup.c:2638 -#: pg_basebackup.c:2646 pg_basebackup.c:2659 pg_basebackup.c:2665 -#: pg_basebackup.c:2674 pg_basebackup.c:2686 pg_basebackup.c:2697 -#: pg_basebackup.c:2705 pg_receivewal.c:816 pg_receivewal.c:828 -#: pg_receivewal.c:835 pg_receivewal.c:844 pg_receivewal.c:851 -#: pg_receivewal.c:861 pg_recvlogical.c:837 pg_recvlogical.c:849 -#: pg_recvlogical.c:859 pg_recvlogical.c:866 pg_recvlogical.c:873 -#: pg_recvlogical.c:880 pg_recvlogical.c:887 pg_recvlogical.c:894 -#: pg_recvlogical.c:901 pg_recvlogical.c:908 +#: pg_basebackup.c:2574 pg_basebackup.c:2586 pg_basebackup.c:2608 +#: pg_basebackup.c:2620 pg_basebackup.c:2626 pg_basebackup.c:2678 +#: pg_basebackup.c:2689 pg_basebackup.c:2699 pg_basebackup.c:2705 +#: pg_basebackup.c:2712 pg_basebackup.c:2724 pg_basebackup.c:2736 +#: pg_basebackup.c:2744 pg_basebackup.c:2757 pg_basebackup.c:2763 +#: pg_basebackup.c:2772 pg_basebackup.c:2784 pg_basebackup.c:2795 +#: pg_basebackup.c:2803 pg_createsubscriber.c:2037 pg_createsubscriber.c:2047 +#: pg_createsubscriber.c:2055 pg_createsubscriber.c:2083 +#: pg_createsubscriber.c:2115 pg_receivewal.c:748 pg_receivewal.c:760 +#: pg_receivewal.c:767 pg_receivewal.c:776 pg_receivewal.c:783 +#: pg_receivewal.c:793 pg_recvlogical.c:853 pg_recvlogical.c:865 +#: pg_recvlogical.c:875 pg_recvlogical.c:882 pg_recvlogical.c:889 +#: pg_recvlogical.c:896 pg_recvlogical.c:903 pg_recvlogical.c:910 +#: pg_recvlogical.c:917 pg_recvlogical.c:924 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_basebackup.c:2486 pg_receivewal.c:826 pg_recvlogical.c:847 +#: pg_basebackup.c:2584 pg_createsubscriber.c:2045 pg_receivewal.c:758 +#: pg_recvlogical.c:863 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_basebackup.c:2509 +#: pg_basebackup.c:2607 #, c-format msgid "cannot specify both format and backup target" msgstr "неможливо одночасно вказати формат і ціль резервного копіювання" -#: pg_basebackup.c:2521 +#: pg_basebackup.c:2619 #, c-format msgid "must specify output directory or backup target" msgstr "потрібно вказати вихідний каталог або ціль резервного копіювання" -#: pg_basebackup.c:2527 +#: pg_basebackup.c:2625 #, c-format msgid "cannot specify both output directory and backup target" msgstr "неможливо одночасно вказати вихідну директорію і ціль резервного копіювання" -#: pg_basebackup.c:2557 pg_receivewal.c:870 +#: pg_basebackup.c:2655 pg_receivewal.c:802 #, c-format -msgid "unrecognized compression algorithm \"%s\"" -msgstr "нерозпізнаний алгоритм стискання \"%s\"" +msgid "unrecognized compression algorithm: \"%s\"" +msgstr "нерозпізнаний алгоритм стискання: \"%s\"" -#: pg_basebackup.c:2563 pg_receivewal.c:877 +#: pg_basebackup.c:2661 pg_receivewal.c:809 #, c-format msgid "invalid compression specification: %s" msgstr "неприпустима специфікація стискання: %s" -#: pg_basebackup.c:2579 +#: pg_basebackup.c:2677 #, c-format msgid "client-side compression is not possible when a backup target is specified" msgstr "стиснення на стороні клієнта неможливе, коли вказана ціль резервного копіювання" -#: pg_basebackup.c:2590 +#: pg_basebackup.c:2688 #, c-format msgid "only tar mode backups can be compressed" msgstr "лише резервні копії в архіві tar можуть стискатись" -#: pg_basebackup.c:2600 +#: pg_basebackup.c:2698 #, c-format msgid "WAL cannot be streamed when a backup target is specified" msgstr "неможливо передавати WAL, коли вказана ціль резервного копіювання" -#: pg_basebackup.c:2606 +#: pg_basebackup.c:2704 #, c-format msgid "cannot stream write-ahead logs in tar mode to stdout" msgstr "транслювати випереджувальні журналювання в режимі tar в потік stdout не можна" -#: pg_basebackup.c:2613 +#: pg_basebackup.c:2711 #, c-format msgid "replication slots can only be used with WAL streaming" msgstr "слоти реплікації можуть використовуватись тільки з потоковим передаванням WAL" -#: pg_basebackup.c:2625 +#: pg_basebackup.c:2723 #, c-format msgid "--no-slot cannot be used with slot name" msgstr "--no-slot не можна використовувати з іменем слота" #. translator: second %s is an option name -#: pg_basebackup.c:2636 pg_receivewal.c:842 +#: pg_basebackup.c:2734 pg_receivewal.c:774 #, c-format msgid "%s needs a slot to be specified using --slot" msgstr "для %s потрібно вказати слот за допомогою --slot" -#: pg_basebackup.c:2644 pg_basebackup.c:2684 pg_basebackup.c:2695 -#: pg_basebackup.c:2703 +#: pg_basebackup.c:2742 pg_basebackup.c:2782 pg_basebackup.c:2793 +#: pg_basebackup.c:2801 #, c-format msgid "%s and %s are incompatible options" msgstr "параметри %s і %s несумісні" -#: pg_basebackup.c:2658 +#: pg_basebackup.c:2756 #, c-format msgid "WAL directory location cannot be specified along with a backup target" msgstr "Не можна вказати розташування директорії WAL разом з ціллю резервного копіювання" -#: pg_basebackup.c:2664 +#: pg_basebackup.c:2762 #, c-format msgid "WAL directory location can only be specified in plain mode" msgstr "розташування каталога WAL можна вказати лише в режимі plain" -#: pg_basebackup.c:2673 +#: pg_basebackup.c:2771 #, c-format msgid "WAL directory location must be an absolute path" msgstr "розташування WAL каталогу має бути абсолютним шляхом" -#: pg_basebackup.c:2774 +#: pg_basebackup.c:2871 #, c-format msgid "could not create symbolic link \"%s\": %m" msgstr "не вдалося створити символічне послання \"%s\": %m" -#: pg_basebackup.c:2776 +#: pg_createsubscriber.c:169 #, c-format -msgid "symlinks are not supported on this platform" -msgstr "символічні посилання не підтримуються цією платформою" +msgid "failed after the end of recovery" +msgstr "помилка після закінчення відновлення" -#: pg_receivewal.c:79 +#: pg_createsubscriber.c:170 #, c-format -msgid "%s receives PostgreSQL streaming write-ahead logs.\n\n" -msgstr "%s отримує передачу випереджувальних журналів PostgreSQL.\n\n" +msgid "The target server cannot be used as a physical replica anymore. You must recreate the physical replica before continuing." +msgstr "Цільовий сервер не можна більше використовувати як фізичну репліку. Перед продовженням вам слід відтворити фізичну репліку." + +#: pg_createsubscriber.c:198 +#, c-format +msgid "publication \"%s\" created in database \"%s\" on primary was left behind" +msgstr "публікація \"%s\" створена в базі даних \"%s\" на основному кластері залишилася позаду" -#: pg_receivewal.c:83 pg_recvlogical.c:84 +#: pg_createsubscriber.c:200 +#, c-format +msgid "Drop this publication before trying again." +msgstr "Видаліть цю публікацію перед тим, як спробувати знову." + +#: pg_createsubscriber.c:204 +#, c-format +msgid "replication slot \"%s\" created in database \"%s\" on primary was left behind" +msgstr "слот реплікації \"%s\" створений в базі даних \"%s\" на основному кластері залишився позаду" + +#: pg_createsubscriber.c:206 pg_createsubscriber.c:1260 +#, c-format +msgid "Drop this replication slot soon to avoid retention of WAL files." +msgstr "Видаліть цей слот реплікації найближчим часом, щоб уникнути збереження файлів WAL." + +#: pg_createsubscriber.c:219 +#, c-format +msgid "%s creates a new logical replica from a standby server.\n\n" +msgstr "%s створює нову логічну репліку з резервного сервера.\n\n" + +#: pg_createsubscriber.c:223 pg_receivewal.c:81 pg_recvlogical.c:92 #, c-format msgid "\n" "Options:\n" msgstr "\n" "Параметри:\n" -#: pg_receivewal.c:84 +#: pg_createsubscriber.c:224 +#, c-format +msgid " -d, --database=DBNAME database in which to create a subscription\n" +msgstr " -d, --database=DBNAME база даних для створення підписки\n" + +#: pg_createsubscriber.c:225 +#, c-format +msgid " -D, --pgdata=DATADIR location for the subscriber data directory\n" +msgstr " -D, --pgdata=DATADIR розташування каталогу даних підписника\n" + +#: pg_createsubscriber.c:226 +#, c-format +msgid " -n, --dry-run dry run, just show what would be done\n" +msgstr " -n, --dry-run сухий запуск, просто показати, що буде зроблено\n" + +#: pg_createsubscriber.c:227 +#, c-format +msgid " -p, --subscriber-port=PORT subscriber port number (default %s)\n" +msgstr " -p, --subscriber-port=PORT номер порту підписника (за замовчуванням %s)\n" + +#: pg_createsubscriber.c:228 +#, c-format +msgid " -P, --publisher-server=CONNSTR publisher connection string\n" +msgstr " -P, --publisher-server=CONNSTR рядок підключення видавця\n" + +#: pg_createsubscriber.c:229 +#, c-format +msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" +msgstr " -s, --socketdir=DIR директорія сокету для використання (за замовчування поточна директорія)\n" + +#: pg_createsubscriber.c:230 +#, c-format +msgid " -t, --recovery-timeout=SECS seconds to wait for recovery to end\n" +msgstr " -t, --recovery-timeout=SECS секунд для очікування кінця відновлення\n" + +#: pg_createsubscriber.c:231 +#, c-format +msgid " -U, --subscriber-username=NAME user name for subscriber connection\n" +msgstr " -U, --subscriber-username=NAME користувач для під'єднання підписника\n" + +#: pg_createsubscriber.c:232 +#, c-format +msgid " -v, --verbose output verbose messages\n" +msgstr " -v, --verbose виводити детальні повідомлення\n" + +#: pg_createsubscriber.c:233 +#, c-format +msgid " --config-file=FILENAME use specified main server configuration\n" +" file when running target cluster\n" +msgstr " --config-file=FILENAME використовувати заданий основний файл конфігурації сервера\n" +" при запуску цільового кластера\n" + +#: pg_createsubscriber.c:235 +#, c-format +msgid " --publication=NAME publication name\n" +msgstr " --publication=NAME назва публікації\n" + +#: pg_createsubscriber.c:236 +#, c-format +msgid " --replication-slot=NAME replication slot name\n" +msgstr " --replication-slot=NAME назва слота реплікації\n" + +#: pg_createsubscriber.c:237 +#, c-format +msgid " --subscription=NAME subscription name\n" +msgstr " --subscription=NAME назва підписки\n" + +#: pg_createsubscriber.c:238 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію і вийти\n" + +#: pg_createsubscriber.c:239 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю справку, потім вийти\n" + +#: pg_createsubscriber.c:282 +#, c-format +msgid "could not parse connection string: %s" +msgstr "не вдалося аналізувати рядок підключення: %s" + +#: pg_createsubscriber.c:359 +#, c-format +msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" +msgstr "програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\"" + +#: pg_createsubscriber.c:362 +#, c-format +msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" +msgstr "програма \"%s\" знайдена для \"%s\", але має відмінну версію від %s" + +#: pg_createsubscriber.c:382 +#, c-format +msgid "checking if directory \"%s\" is a cluster data directory" +msgstr "перевірка чи каталог \"%s\" є каталогом даних кластера" + +#: pg_createsubscriber.c:388 +#, c-format +msgid "data directory \"%s\" does not exist" +msgstr "каталог даних \"%s\" не існує" + +#: pg_createsubscriber.c:396 +#, c-format +msgid "directory \"%s\" is not a database cluster directory" +msgstr "каталог \"%s\" не є каталогом кластера бази даних" + +#: pg_createsubscriber.c:513 +#, c-format +msgid "connection to database failed: %s" +msgstr "помилка підключення до бази даних: %s" + +#: pg_createsubscriber.c:526 +#, c-format +msgid "could not clear search_path: %s" +msgstr "не вдалося очистити search_path: %s" + +#: pg_createsubscriber.c:566 +#, c-format +msgid "getting system identifier from publisher" +msgstr "отримання системного ідентифікатора з публікації" + +#: pg_createsubscriber.c:573 +#, c-format +msgid "could not get system identifier: %s" +msgstr "не вдалося отримати системний ідентифікатор: %s" + +#: pg_createsubscriber.c:579 +#, c-format +msgid "could not get system identifier: got %d rows, expected %d row" +msgstr "не вдалося отримати системний ідентифікатор: отримано рядки %d, очікувалось %d рядок" + +#: pg_createsubscriber.c:586 +#, c-format +msgid "system identifier is %llu on publisher" +msgstr "системний ідентифікатор %llu на сервері публікації" + +#: pg_createsubscriber.c:607 +#, c-format +msgid "getting system identifier from subscriber" +msgstr "отримання системного ідентифікатора від підписника" + +#: pg_createsubscriber.c:611 pg_createsubscriber.c:641 +#, c-format +msgid "control file appears to be corrupt" +msgstr "контрольний файл здається пошкодженим" + +#: pg_createsubscriber.c:615 pg_createsubscriber.c:656 +#, c-format +msgid "system identifier is %llu on subscriber" +msgstr "системний ідентифікатор %llu на підписнику" + +#: pg_createsubscriber.c:637 +#, c-format +msgid "modifying system identifier of subscriber" +msgstr "змінюю системний ідентифікатор підписника" + +#: pg_createsubscriber.c:659 +#, c-format +msgid "running pg_resetwal on the subscriber" +msgstr "запускаю pg_resetwal на підписнику" + +#: pg_createsubscriber.c:671 +#, c-format +msgid "subscriber successfully changed the system identifier" +msgstr "підписник успішно змінив системний ідентифікатор" + +#: pg_createsubscriber.c:673 +#, c-format +msgid "could not change system identifier of subscriber: %s" +msgstr "не вдалося змінити системний ідентифікатор підписника: %s" + +#: pg_createsubscriber.c:697 +#, c-format +msgid "could not obtain database OID: %s" +msgstr "не вдалося отримати OID бази даних: %s" + +#: pg_createsubscriber.c:704 +#, c-format +msgid "could not obtain database OID: got %d rows, expected %d row" +msgstr "не вдалося отримати OID бази даних: отримано %d рядків, очікувалось %d рядок" + +#: pg_createsubscriber.c:776 +#, c-format +msgid "create replication slot \"%s\" on publisher" +msgstr "створіть слот реплікації \"%s\" на сервері публікації" + +#: pg_createsubscriber.c:796 +#, c-format +msgid "could not write an additional WAL record: %s" +msgstr "не вдалося написати додатковий запис WAL: %s" + +#: pg_createsubscriber.c:822 +#, c-format +msgid "could not obtain recovery progress: %s" +msgstr "не вдалося отримати прогрес відновлення: %s" + +#: pg_createsubscriber.c:854 +#, c-format +msgid "checking settings on publisher" +msgstr "перевірка налаштувань на сервері публікації" + +#: pg_createsubscriber.c:864 +#, c-format +msgid "primary server cannot be in recovery" +msgstr "основний сервер не може бути у процесі відновлення" + +#: pg_createsubscriber.c:888 +#, c-format +msgid "could not obtain publisher settings: %s" +msgstr "не вдалось отримати налаштування сервера публікацій: %s" + +#: pg_createsubscriber.c:914 +#, c-format +msgid "publisher requires wal_level >= \"logical\"" +msgstr "сервер публікації вимагає wal_level >= \"logical\"" + +#: pg_createsubscriber.c:920 +#, c-format +msgid "publisher requires %d replication slots, but only %d remain" +msgstr "сервер публікацій вимагає %d слотів реплікації, але залишається тільки %d" + +#: pg_createsubscriber.c:922 pg_createsubscriber.c:931 +#: pg_createsubscriber.c:1028 pg_createsubscriber.c:1037 +#: pg_createsubscriber.c:1046 +#, c-format +msgid "Increase the configuration parameter \"%s\" to at least %d." +msgstr "Збільшіть параметр налаштування \"%s\" принаймні до %d." + +#: pg_createsubscriber.c:929 +#, c-format +msgid "publisher requires %d WAL sender processes, but only %d remain" +msgstr "сервер публікацій вимагає %d процесів відправника WAL, але залишається тільки %d" + +#: pg_createsubscriber.c:938 +#, c-format +msgid "two_phase option will not be enabled for replication slots" +msgstr "опція two_phase для слотів реплікації не буде увімкнена" + +#: pg_createsubscriber.c:939 +#, c-format +msgid "Subscriptions will be created with the two_phase option disabled. Prepared transactions will be replicated at COMMIT PREPARED." +msgstr "Підписки будуть створені з відключенем параметром two_phase. Підготовлені транзакції будуть скопійовані в COMMIT PREPARED." + +#: pg_createsubscriber.c:971 +#, c-format +msgid "checking settings on subscriber" +msgstr "перевірка налаштувань підписника" + +#: pg_createsubscriber.c:978 +#, c-format +msgid "target server must be a standby" +msgstr "цільовий сервер повинен бути в режимі очікування" + +#: pg_createsubscriber.c:1002 +#, c-format +msgid "could not obtain subscriber settings: %s" +msgstr "не вдалося отримати налаштування підписника: %s" + +#: pg_createsubscriber.c:1026 +#, c-format +msgid "subscriber requires %d replication slots, but only %d remain" +msgstr "підписник вимагає %d слотів реплікації, але залишається тільки %d" + +#: pg_createsubscriber.c:1035 +#, c-format +msgid "subscriber requires %d logical replication workers, but only %d remain" +msgstr "підписник вимагає %d процесів логічної реплікації, але залишається тільки %d" + +#: pg_createsubscriber.c:1044 +#, c-format +msgid "subscriber requires %d worker processes, but only %d remain" +msgstr "підписник вимагає %d робочих процесів, але залишається тільки %d" + +#: pg_createsubscriber.c:1079 +#, c-format +msgid "dropping subscription \"%s\" in database \"%s\"" +msgstr "видалення підписки \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1088 +#, c-format +msgid "could not drop subscription \"%s\": %s" +msgstr "не вдалося видалити підписку \"%s\": %s" + +#: pg_createsubscriber.c:1123 +#, c-format +msgid "could not obtain pre-existing subscriptions: %s" +msgstr "не вдалося отримати раніше наявні підписки: %s" + +#: pg_createsubscriber.c:1258 +#, c-format +msgid "could not drop replication slot \"%s\" on primary" +msgstr "не вдалося видалити слот реплікації \"%s\" на головному сервері" + +#: pg_createsubscriber.c:1292 +#, c-format +msgid "could not obtain failover replication slot information: %s" +msgstr "не вдалося отримати інформацію про запасний слот реплікації: %s" + +#: pg_createsubscriber.c:1294 pg_createsubscriber.c:1303 +#, c-format +msgid "Drop the failover replication slots on subscriber soon to avoid retention of WAL files." +msgstr "Видаліть запасний слот реплікації найближчим часом, щоб уникнути збереження файлів WAL." + +#: pg_createsubscriber.c:1302 +#, c-format +msgid "could not drop failover replication slot" +msgstr "не вдалося видалити запасний слот реплікації" + +#: pg_createsubscriber.c:1324 +#, c-format +msgid "creating the replication slot \"%s\" in database \"%s\"" +msgstr "створюю слот реплікації \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1342 +#, c-format +msgid "could not create replication slot \"%s\" in database \"%s\": %s" +msgstr "не вдалося створити слот реплікації \"%s\" в базі даних \"%s\": %s" + +#: pg_createsubscriber.c:1372 +#, c-format +msgid "dropping the replication slot \"%s\" in database \"%s\"" +msgstr "видалення слоту реплікації \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1388 +#, c-format +msgid "could not drop replication slot \"%s\" in database \"%s\": %s" +msgstr "не вдалося видалити слот реплікації \"%s\" в базі даних \"%s\": %s" + +#: pg_createsubscriber.c:1409 +#, c-format +msgid "pg_ctl failed with exit code %d" +msgstr "помилка pg_ctl з кодом %d" + +#: pg_createsubscriber.c:1414 +#, c-format +msgid "pg_ctl was terminated by exception 0x%X" +msgstr "pg_ctl був перерваний винятком 0x%X" + +#: pg_createsubscriber.c:1416 +#, c-format +msgid "See C include file \"ntstatus.h\" for a description of the hexadecimal value." +msgstr "Опис цього Шістнадцяткового значення дивіться у включаємому C-файлі \"ntstatus.h\"." + +#: pg_createsubscriber.c:1418 +#, c-format +msgid "pg_ctl was terminated by signal %d: %s" +msgstr "pg_ctl було припинено сигналом %d: %s" + +#: pg_createsubscriber.c:1424 +#, c-format +msgid "pg_ctl exited with unrecognized status %d" +msgstr "pg_ctl завершився з невідомим статусом %d" + +#: pg_createsubscriber.c:1427 +#, c-format +msgid "The failed command was: %s" +msgstr "Команда з помилкою: %s" + +#: pg_createsubscriber.c:1473 +#, c-format +msgid "server was started" +msgstr "сервер був запущений" + +#: pg_createsubscriber.c:1488 +#, c-format +msgid "server was stopped" +msgstr "сервер було зупинено" + +#: pg_createsubscriber.c:1507 +#, c-format +msgid "waiting for the target server to reach the consistent state" +msgstr "чекаю на досягнення узгодженого стану цільовим сервером" + +#: pg_createsubscriber.c:1530 +#, c-format +msgid "recovery timed out" +msgstr "час відновлення вичерпався" + +#: pg_createsubscriber.c:1543 +#, c-format +msgid "server did not end recovery" +msgstr "сервер не завершив відновлення" + +#: pg_createsubscriber.c:1545 +#, c-format +msgid "target server reached the consistent state" +msgstr "цільовий сервер досяг узгодженого стану" + +#: pg_createsubscriber.c:1546 +#, c-format +msgid "If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing." +msgstr "Якщо pg_createsubscriber поверне помилку після цієї точки, вам потрібно буде перестворити фізичну репліку перед продовженням." + +#: pg_createsubscriber.c:1573 +#, c-format +msgid "could not obtain publication information: %s" +msgstr "не вдалося отримати інформацію про публікацію: %s" + +#: pg_createsubscriber.c:1587 +#, c-format +msgid "publication \"%s\" already exists" +msgstr "публікація \"%s\" вже існує" + +#: pg_createsubscriber.c:1588 +#, c-format +msgid "Consider renaming this publication before continuing." +msgstr "Подумайте про перейменування цієї публікації, перш ніж продовжити." + +#: pg_createsubscriber.c:1595 +#, c-format +msgid "creating publication \"%s\" in database \"%s\"" +msgstr "створення публікації \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1608 +#, c-format +msgid "could not create publication \"%s\" in database \"%s\": %s" +msgstr "не вдалося створити публікацію \"%s\" в базі даних \"%s\": %s" + +#: pg_createsubscriber.c:1637 +#, c-format +msgid "dropping publication \"%s\" in database \"%s\"" +msgstr "видалення публікації \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1651 +#, c-format +msgid "could not drop publication \"%s\" in database \"%s\": %s" +msgstr "не вдалося видалити публікацію \"%s\" в базі даних \"%s\": %s" + +#: pg_createsubscriber.c:1697 +#, c-format +msgid "creating subscription \"%s\" in database \"%s\"" +msgstr "створення підписки \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1718 +#, c-format +msgid "could not create subscription \"%s\" in database \"%s\": %s" +msgstr "не вдалося створити підписку \"%s\" в базі даних \"%s\": %s" + +#: pg_createsubscriber.c:1763 +#, c-format +msgid "could not obtain subscription OID: %s" +msgstr "не вдалося отримати OID підписки: %s" + +#: pg_createsubscriber.c:1770 +#, c-format +msgid "could not obtain subscription OID: got %d rows, expected %d row" +msgstr "не вдалося отримати OID підписки: отримано %d рядків, очікувалось %d рядок" + +#: pg_createsubscriber.c:1794 +#, c-format +msgid "setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"" +msgstr "налаштування прогресу реплікації (назва вузла \"%s, LSN %s) в базі даних \"%s\"" + +#: pg_createsubscriber.c:1809 +#, c-format +msgid "could not set replication progress for subscription \"%s\": %s" +msgstr "не вдалося виставити прогрес реплікації для підписки \"%s\": %s" + +#: pg_createsubscriber.c:1840 +#, c-format +msgid "enabling subscription \"%s\" in database \"%s\"" +msgstr "активація підписки \"%s\" в базі даних \"%s\"" + +#: pg_createsubscriber.c:1852 +#, c-format +msgid "could not enable subscription \"%s\": %s" +msgstr "не вдалося активувати підписку \"%s\": %s" + +#: pg_createsubscriber.c:1944 +#, c-format +msgid "cannot be executed by \"root\"" +msgstr "\"root\" не може це виконувати" + +#: pg_createsubscriber.c:1945 +#, c-format +msgid "You must run %s as the PostgreSQL superuser." +msgstr "Запускати %s треба від суперкористувача PostgreSQL." + +#: pg_createsubscriber.c:1966 +#, c-format +msgid "database \"%s\" specified more than once" +msgstr "база даних \"%s\" вказана неодноразово" + +#: pg_createsubscriber.c:2007 +#, c-format +msgid "publication \"%s\" specified more than once" +msgstr "публікація \"%s\" вказана неодноразово" + +#: pg_createsubscriber.c:2019 +#, c-format +msgid "replication slot \"%s\" specified more than once" +msgstr "слот реплікації \"%s\" вказаний неодноразово" + +#: pg_createsubscriber.c:2031 +#, c-format +msgid "subscription \"%s\" specified more than once" +msgstr "підписка \"%s\" вказана неодноразово" + +#: pg_createsubscriber.c:2054 +#, c-format +msgid "no subscriber data directory specified" +msgstr "не вказано каталог з даними підписника" + +#: pg_createsubscriber.c:2065 +#, c-format +msgid "could not determine current directory" +msgstr "не вдалося визначити поточний каталог" + +#: pg_createsubscriber.c:2082 +#, c-format +msgid "no publisher connection string specified" +msgstr "немає рядка підключення до видавця" + +#: pg_createsubscriber.c:2086 +#, c-format +msgid "validating publisher connection string" +msgstr "перевірка рядка підключення видавця" + +#: pg_createsubscriber.c:2092 +#, c-format +msgid "validating subscriber connection string" +msgstr "перевірка рядка з'єднання з підписником" + +#: pg_createsubscriber.c:2097 +#, c-format +msgid "no database was specified" +msgstr "база даних не вказана" + +#: pg_createsubscriber.c:2109 +#, c-format +msgid "database name \"%s\" was extracted from the publisher connection string" +msgstr "ім'я бази даних \"%s\" було отримано з рядка підключення видавця" + +#: pg_createsubscriber.c:2114 +#, c-format +msgid "no database name specified" +msgstr "не вказано ім'я бази даних" + +#: pg_createsubscriber.c:2124 +#, c-format +msgid "wrong number of publication names specified" +msgstr "вказана невірна кількість імен публікації" + +#: pg_createsubscriber.c:2125 +#, c-format +msgid "The number of specified publication names (%d) must match the number of specified database names (%d)." +msgstr "Кількість вказаних назв публікації (%d) мусить співпадати з кількістю вказаних баз даних (%d)." + +#: pg_createsubscriber.c:2131 +#, c-format +msgid "wrong number of subscription names specified" +msgstr "вказано неправильну кількість імен підписки" + +#: pg_createsubscriber.c:2132 +#, c-format +msgid "The number of specified subscription names (%d) must match the number of specified database names (%d)." +msgstr "Кількість зазначених назв підписки (%d) повинна співпадати з кількістю зазначених назв бази даних (%d)." + +#: pg_createsubscriber.c:2138 +#, c-format +msgid "wrong number of replication slot names specified" +msgstr "вказано неправильну кількість назв слотів реплікації" + +#: pg_createsubscriber.c:2139 +#, c-format +msgid "The number of specified replication slot names (%d) must match the number of specified database names (%d)." +msgstr "Кількість вказаних назв слотів реплікації (%d) повинна збігатися з кількістю вказаних назв бази даних (%d)." + +#: pg_createsubscriber.c:2168 +#, c-format +msgid "subscriber data directory is not a copy of the source database cluster" +msgstr "каталог даних підписника не є копією кластера вихідної бази даних" + +#: pg_createsubscriber.c:2181 +#, c-format +msgid "standby server is running" +msgstr "резервний сервер працює" + +#: pg_createsubscriber.c:2182 +#, c-format +msgid "Stop the standby server and try again." +msgstr "Зупиніть резервний сервер та повторіть спробу." + +#: pg_createsubscriber.c:2191 +#, c-format +msgid "starting the standby server with command-line options" +msgstr "запуск резервного серверу з параметрами командного рядка" + +#: pg_createsubscriber.c:2207 pg_createsubscriber.c:2242 +#, c-format +msgid "stopping the subscriber" +msgstr "зупинка підписника" + +#: pg_createsubscriber.c:2221 +#, c-format +msgid "starting the subscriber" +msgstr "запуск підписника" + +#: pg_createsubscriber.c:2250 +#, c-format +msgid "Done!" +msgstr "Готово!" + +#: pg_receivewal.c:77 +#, c-format +msgid "%s receives PostgreSQL streaming write-ahead logs.\n\n" +msgstr "%s отримує передачу випереджувальних журналів PostgreSQL.\n\n" + +#: pg_receivewal.c:82 #, c-format msgid " -D, --directory=DIR receive write-ahead log files into this directory\n" msgstr " -D, --directory=DIR зберігати файли випереджувального журналювання до цього каталогу\n" -#: pg_receivewal.c:85 pg_recvlogical.c:85 +#: pg_receivewal.c:83 pg_recvlogical.c:93 #, c-format msgid " -E, --endpos=LSN exit after receiving the specified LSN\n" msgstr " -E, --endpos=LSN вийти після отримання вказаного LSN\n" -#: pg_receivewal.c:86 pg_recvlogical.c:89 +#: pg_receivewal.c:84 pg_recvlogical.c:97 #, c-format msgid " --if-not-exists do not error if slot already exists when creating a slot\n" msgstr " --if-not-exists не видавати помилку, при створенні слота, якщо слот вже існує\n" -#: pg_receivewal.c:87 pg_recvlogical.c:91 +#: pg_receivewal.c:85 pg_recvlogical.c:99 #, c-format msgid " -n, --no-loop do not loop on connection lost\n" msgstr " -n, --no-loop переривати роботу при втраті підключення\n" -#: pg_receivewal.c:88 +#: pg_receivewal.c:86 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync не чекати безпечного збереження змін на диск\n" -#: pg_receivewal.c:89 pg_recvlogical.c:96 +#: pg_receivewal.c:87 pg_recvlogical.c:104 #, c-format msgid " -s, --status-interval=SECS\n" " time between status packets sent to server (default: %d)\n" msgstr " -s, --status-interval=SECS\n" " інтервал між відправкою статусних пакетів серверу (за замовчуванням: %d)\n" -#: pg_receivewal.c:92 +#: pg_receivewal.c:90 #, c-format msgid " --synchronous flush write-ahead log immediately after writing\n" msgstr " --synchronous очистити випереджувальне журналювання відразу після запису\n" -#: pg_receivewal.c:95 +#: pg_receivewal.c:93 #, c-format msgid " -Z, --compress=METHOD[:DETAIL]\n" " compress as specified\n" msgstr " -Z, --compress=METHOD[:DETAIL]\n" " стискати як вказано\n" -#: pg_receivewal.c:105 +#: pg_receivewal.c:103 #, c-format msgid "\n" "Optional actions:\n" msgstr "\n" "Додаткові дії:\n" -#: pg_receivewal.c:106 pg_recvlogical.c:81 +#: pg_receivewal.c:104 pg_recvlogical.c:89 #, c-format msgid " --create-slot create a new replication slot (for the slot's name see --slot)\n" msgstr " --create-slot створити новий слот реплікації (ім'я слота задає параметр --slot)\n" -#: pg_receivewal.c:107 pg_recvlogical.c:82 +#: pg_receivewal.c:105 pg_recvlogical.c:90 #, c-format msgid " --drop-slot drop the replication slot (for the slot's name see --slot)\n" msgstr " --drop-slot видалити слот реплікації (ім'я слота задає параметр --slot)\n" -#: pg_receivewal.c:252 +#: pg_receivewal.c:191 #, c-format msgid "finished segment at %X/%X (timeline %u)" msgstr "завершено сегмент в позиції %X/%X (часова шкала %u)" -#: pg_receivewal.c:259 +#: pg_receivewal.c:198 #, c-format msgid "stopped log streaming at %X/%X (timeline %u)" msgstr "зупинено потокове передавання журналу в позиції %X/%X (часова шкала %u)" -#: pg_receivewal.c:275 +#: pg_receivewal.c:214 #, c-format msgid "switched to timeline %u at %X/%X" msgstr "переключено на часову шкалу %u в позиції %X/%X" -#: pg_receivewal.c:285 +#: pg_receivewal.c:224 pg_recvlogical.c:1053 #, c-format msgid "received interrupt signal, exiting" msgstr "отримано сигнал переривання, завершення роботи" -#: pg_receivewal.c:317 +#: pg_receivewal.c:256 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не вдалося закрити каталог \"%s\": %m" -#: pg_receivewal.c:384 +#: pg_receivewal.c:323 #, c-format msgid "segment file \"%s\" has incorrect size %lld, skipping" msgstr "файл сегменту \"%s\" має неправильний розмір %lld, пропускається" -#: pg_receivewal.c:401 +#: pg_receivewal.c:340 #, c-format msgid "could not open compressed file \"%s\": %m" msgstr "не вдалося відкрити стиснутий файл \"%s\": %m" -#: pg_receivewal.c:404 +#: pg_receivewal.c:343 #, c-format msgid "could not seek in compressed file \"%s\": %m" msgstr "не вдалося знайти в стиснутому файлі \"%s\": %m" -#: pg_receivewal.c:410 +#: pg_receivewal.c:349 #, c-format msgid "could not read compressed file \"%s\": %m" msgstr "не вдалося прочитати стиснутий файл \"%s\": %m" -#: pg_receivewal.c:413 +#: pg_receivewal.c:352 #, c-format msgid "could not read compressed file \"%s\": read %d of %zu" msgstr "не вдалося прочитати стиснутий файл \"%s\": прочитано %d з %zu" -#: pg_receivewal.c:423 +#: pg_receivewal.c:362 #, c-format msgid "compressed segment file \"%s\" has incorrect uncompressed size %d, skipping" msgstr "файл стиснутого сегменту \"%s\" має неправильний розмір без стискання %d, пропускається" -#: pg_receivewal.c:451 +#: pg_receivewal.c:390 #, c-format msgid "could not create LZ4 decompression context: %s" msgstr "не вдалося створити контекст декомпресії LZ4: %s" -#: pg_receivewal.c:463 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не вдалося прочитати файл \"%s\": %m" - -#: pg_receivewal.c:481 +#: pg_receivewal.c:420 #, c-format msgid "could not decompress file \"%s\": %s" msgstr "не вдалося розпакувати файл \"%s\": %s" -#: pg_receivewal.c:504 +#: pg_receivewal.c:443 #, c-format msgid "could not free LZ4 decompression context: %s" msgstr "не вдалося звільнити контекст декомпресії LZ4: %s" -#: pg_receivewal.c:509 +#: pg_receivewal.c:448 #, c-format msgid "compressed segment file \"%s\" has incorrect uncompressed size %zu, skipping" msgstr "файл стиснутого сегменту \"%s\" має неправильний розмір не стиснутого розміру %zu, пропускається" -#: pg_receivewal.c:514 -#, c-format -msgid "could not check file \"%s\"" -msgstr "не вдалося перевірити файл \"%s\"" - -#: pg_receivewal.c:516 +#: pg_receivewal.c:453 #, c-format -msgid "This build does not support compression with %s." -msgstr "Ця збірка не підтримує стиснення з %s." +msgid "cannot check file \"%s\": compression with %s not supported by this build" +msgstr "неможливо перевірити файл \"%s\": стиснення %s не підтримується даною збіркою" -#: pg_receivewal.c:643 +#: pg_receivewal.c:578 #, c-format msgid "starting log streaming at %X/%X (timeline %u)" msgstr "початок потокового передавання журналу в позиції %X/%X (часова шкала %u)" -#: pg_receivewal.c:785 pg_recvlogical.c:785 +#: pg_receivewal.c:693 pg_recvlogical.c:801 #, c-format msgid "could not parse end position \"%s\"" msgstr "не вдалося проаналізувати кінцеву позицію \"%s\"" -#: pg_receivewal.c:834 +#: pg_receivewal.c:766 #, c-format msgid "cannot use --create-slot together with --drop-slot" msgstr "використовувати --create-slot разом з --drop-slot не можна" -#: pg_receivewal.c:850 +#: pg_receivewal.c:782 #, c-format msgid "cannot use --synchronous together with --no-sync" msgstr "використовувати --synchronous разом з --no-sync не можна" -#: pg_receivewal.c:860 +#: pg_receivewal.c:792 #, c-format msgid "no target directory specified" msgstr "цільовий каталог не вказано" -#: pg_receivewal.c:893 -#, c-format -msgid "no value specified for --compress, switching to default" -msgstr "не вказано значення для --compress, використовується значення за замовчуванням" - -#: pg_receivewal.c:897 pg_receivewal.c:903 -#, c-format -msgid "this build does not support compression with %s" -msgstr "ця збірка не підтримує стиснення з %s" - -#: pg_receivewal.c:908 +#: pg_receivewal.c:816 #, c-format msgid "compression with %s is not yet supported" msgstr "стиснення з %s ще не підтримується" -#: pg_receivewal.c:953 +#: pg_receivewal.c:859 #, c-format msgid "replication connection using slot \"%s\" is unexpectedly database specific" msgstr "підключення для реплікації з використанням слоту \"%s\" неочікувано виявилось прив'язаним до бази даних" -#: pg_receivewal.c:972 pg_recvlogical.c:955 +#: pg_receivewal.c:878 pg_recvlogical.c:972 #, c-format msgid "dropping replication slot \"%s\"" msgstr "видалення слоту реплікації \"%s\"" -#: pg_receivewal.c:983 pg_recvlogical.c:965 +#: pg_receivewal.c:889 pg_recvlogical.c:982 #, c-format msgid "creating replication slot \"%s\"" msgstr "створення слоту реплікації \"%s\"" -#: pg_receivewal.c:1012 pg_recvlogical.c:989 +#: pg_receivewal.c:918 pg_recvlogical.c:1006 #, c-format msgid "disconnected" msgstr "роз’єднано" #. translator: check source for value for %d -#: pg_receivewal.c:1016 pg_recvlogical.c:993 +#: pg_receivewal.c:922 pg_recvlogical.c:1010 #, c-format msgid "disconnected; waiting %d seconds to try again" msgstr "роз’єднано; через %d секунд буде повторна спроба" -#: pg_recvlogical.c:76 +#: pg_recvlogical.c:84 #, c-format msgid "%s controls PostgreSQL logical decoding streams.\n\n" msgstr "%s керує потоковими передаваннями логічного декодування PostgreSQL.\n\n" -#: pg_recvlogical.c:80 +#: pg_recvlogical.c:88 #, c-format msgid "\n" "Action to be performed:\n" msgstr "\n" "Дія до виконання:\n" -#: pg_recvlogical.c:83 +#: pg_recvlogical.c:91 #, c-format msgid " --start start streaming in a replication slot (for the slot's name see --slot)\n" msgstr " --start почати потокове передавання в слоті реплікації (ім'я слоту задає параметр --slot)\n" -#: pg_recvlogical.c:86 +#: pg_recvlogical.c:94 #, c-format msgid " -f, --file=FILE receive log into this file, - for stdout\n" msgstr " -f, --file=FILE зберігати журнал до цього файлу, - позначає stdout\n" -#: pg_recvlogical.c:87 +#: pg_recvlogical.c:95 #, c-format msgid " -F --fsync-interval=SECS\n" " time between fsyncs to the output file (default: %d)\n" msgstr " -F --fsync-interval=SECS\n" " час між fsyncs до файлу виводу (за замовчуванням: %d)\n" -#: pg_recvlogical.c:90 +#: pg_recvlogical.c:98 #, c-format msgid " -I, --startpos=LSN where in an existing slot should the streaming start\n" msgstr " -I, --startpos=LSN де в існуючому слоті слід почати потокове передавання\n" -#: pg_recvlogical.c:92 +#: pg_recvlogical.c:100 #, c-format msgid " -o, --option=NAME[=VALUE]\n" " pass option NAME with optional value VALUE to the\n" @@ -1360,173 +2133,173 @@ msgstr " -o, --option=NAME[=VALUE]\n" " передати параметр NAME з додатковим значенням VALUE до\n" " плагіну виводу\n" -#: pg_recvlogical.c:95 +#: pg_recvlogical.c:103 #, c-format msgid " -P, --plugin=PLUGIN use output plugin PLUGIN (default: %s)\n" msgstr " -P, --plugin=PLUGIN використовувати плагін виводу PLUGIN (за замовчуванням: %s)\n" -#: pg_recvlogical.c:98 +#: pg_recvlogical.c:106 #, c-format msgid " -S, --slot=SLOTNAME name of the logical replication slot\n" msgstr " -S, --slot=SLOTNAME ім'я слоту логічної реплікації\n" -#: pg_recvlogical.c:99 +#: pg_recvlogical.c:107 #, c-format -msgid " -t, --two-phase enable two-phase decoding when creating a slot\n" -msgstr " -t, --2-фазове декодування під час створення слота\n" +msgid " -t, --two-phase enable decoding of prepared transactions when creating a slot\n" +msgstr " -t, --two-phase активувати декодування підготовлених транзакцій під час створення слоту\n" -#: pg_recvlogical.c:104 +#: pg_recvlogical.c:112 #, c-format msgid " -d, --dbname=DBNAME database to connect to\n" msgstr " -d, --dbname=DBNAME бази даних для підключення\n" -#: pg_recvlogical.c:137 +#: pg_recvlogical.c:145 #, c-format msgid "confirming write up to %X/%X, flush to %X/%X (slot %s)" msgstr "підтвердження запису до %X/%X, очищення до %X/%X (слот %s)" -#: pg_recvlogical.c:161 receivelog.c:366 +#: pg_recvlogical.c:169 receivelog.c:360 #, c-format msgid "could not send feedback packet: %s" msgstr "не вдалося відправити пакет зворотнього зв'язку: %s" -#: pg_recvlogical.c:229 +#: pg_recvlogical.c:239 #, c-format msgid "starting log streaming at %X/%X (slot %s)" msgstr "початок потокового передавання журналу в позиції %X/%X (слот %s)" -#: pg_recvlogical.c:271 +#: pg_recvlogical.c:281 #, c-format msgid "streaming initiated" msgstr "потокове передавання ініційовано" -#: pg_recvlogical.c:335 +#: pg_recvlogical.c:346 #, c-format msgid "could not open log file \"%s\": %m" msgstr "не вдалося відкрити файл журналу \"%s\": %m" -#: pg_recvlogical.c:364 receivelog.c:889 +#: pg_recvlogical.c:375 receivelog.c:882 #, c-format msgid "invalid socket: %s" msgstr "неприпустимий сокет: %s" -#: pg_recvlogical.c:417 receivelog.c:917 +#: pg_recvlogical.c:428 receivelog.c:910 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: pg_recvlogical.c:424 receivelog.c:967 +#: pg_recvlogical.c:435 receivelog.c:959 #, c-format msgid "could not receive data from WAL stream: %s" msgstr "не вдалося отримати дані з WAL потоку: %s" -#: pg_recvlogical.c:466 pg_recvlogical.c:517 receivelog.c:1011 -#: receivelog.c:1074 +#: pg_recvlogical.c:477 pg_recvlogical.c:528 receivelog.c:1003 +#: receivelog.c:1066 #, c-format msgid "streaming header too small: %d" msgstr "заголовок потокового передавання занадто малий: %d" -#: pg_recvlogical.c:501 receivelog.c:849 +#: pg_recvlogical.c:512 receivelog.c:843 #, c-format msgid "unrecognized streaming header: \"%c\"" msgstr "нерозпізнаний заголовок потокового передавання: \"%c\"" -#: pg_recvlogical.c:555 pg_recvlogical.c:567 +#: pg_recvlogical.c:566 pg_recvlogical.c:578 #, c-format msgid "could not write %d bytes to log file \"%s\": %m" msgstr "не вдалося записати %d байт до файлу журналу \"%s\": %m" -#: pg_recvlogical.c:621 receivelog.c:648 receivelog.c:685 +#: pg_recvlogical.c:636 receivelog.c:642 receivelog.c:679 #, c-format msgid "unexpected termination of replication stream: %s" msgstr "неочікуване завершення роботи потоку реплікації: %s" -#: pg_recvlogical.c:780 +#: pg_recvlogical.c:796 #, c-format msgid "could not parse start position \"%s\"" msgstr "не вдалося аналізувати початкову позицію \"%s\"" -#: pg_recvlogical.c:858 +#: pg_recvlogical.c:874 #, c-format msgid "no slot specified" msgstr "слот не вказано" -#: pg_recvlogical.c:865 +#: pg_recvlogical.c:881 #, c-format msgid "no target file specified" msgstr "цільовий файл не вказано" -#: pg_recvlogical.c:872 +#: pg_recvlogical.c:888 #, c-format msgid "no database specified" msgstr "база даних не вказана" -#: pg_recvlogical.c:879 +#: pg_recvlogical.c:895 #, c-format msgid "at least one action needs to be specified" msgstr "необхідно вказати щонайменше одну дію" -#: pg_recvlogical.c:886 +#: pg_recvlogical.c:902 #, c-format msgid "cannot use --create-slot or --start together with --drop-slot" msgstr "використовувати --create-slot або --start разом з --drop-slot не можна" -#: pg_recvlogical.c:893 +#: pg_recvlogical.c:909 #, c-format msgid "cannot use --create-slot or --drop-slot together with --startpos" msgstr "використовувати --create-slot або --drop-slot разом з --startpos не можна" -#: pg_recvlogical.c:900 +#: pg_recvlogical.c:916 #, c-format msgid "--endpos may only be specified with --start" msgstr "--endpos можна вказати лише з --start" -#: pg_recvlogical.c:907 +#: pg_recvlogical.c:923 #, c-format msgid "--two-phase may only be specified with --create-slot" msgstr "--two-phase може бути вказано тільки з --create-slot" -#: pg_recvlogical.c:939 +#: pg_recvlogical.c:956 #, c-format msgid "could not establish database-specific replication connection" msgstr "не вдалося встановити підключення для реплікації до вказаної бази даних" -#: pg_recvlogical.c:1033 +#: pg_recvlogical.c:1056 #, c-format msgid "end position %X/%X reached by keepalive" msgstr "кінцева позиція %X/%X досягнута наживо" -#: pg_recvlogical.c:1036 +#: pg_recvlogical.c:1061 #, c-format msgid "end position %X/%X reached by WAL record at %X/%X" msgstr "кінцева позиція %X/%X досягнута WAL записом %X/%X" -#: receivelog.c:68 +#: receivelog.c:66 #, c-format msgid "could not create archive status file \"%s\": %s" msgstr "не вдалося створити файл статусу архіву \"%s\": %s" -#: receivelog.c:75 +#: receivelog.c:73 #, c-format msgid "could not close archive status file \"%s\": %s" msgstr "не вдалося закрити файл статусу архіву \"%s\": %s" -#: receivelog.c:123 +#: receivelog.c:122 #, c-format msgid "could not get size of write-ahead log file \"%s\": %s" msgstr "не вдалося отримати розмір файлу випереджувального журналювання \"%s\": %s" -#: receivelog.c:134 +#: receivelog.c:133 #, c-format msgid "could not open existing write-ahead log file \"%s\": %s" msgstr "не вдалося відкрити існуючий файл випереджувального журналювання \"%s\": %s" -#: receivelog.c:143 +#: receivelog.c:142 #, c-format msgid "could not fsync existing write-ahead log file \"%s\": %s" msgstr "не вдалося fsync існуючий файл випереджувального журналювання \"%s\": %s" -#: receivelog.c:158 +#: receivelog.c:157 #, c-format msgid "write-ahead log file \"%s\" has %zd byte, should be 0 or %d" msgid_plural "write-ahead log file \"%s\" has %zd bytes, should be 0 or %d" @@ -1535,229 +2308,229 @@ msgstr[1] "файл випереджувального журналювання msgstr[2] "файл випереджувального журналювання \"%s\" має %zd байтів, а повинен мати 0 або %d" msgstr[3] "файл випереджувального журналювання \"%s\" має %zd байтів, а повинен мати 0 або %d" -#: receivelog.c:174 +#: receivelog.c:175 #, c-format msgid "could not open write-ahead log file \"%s\": %s" msgstr "не вдалося відкрити файл випереджувального журналювання \"%s\": %s" -#: receivelog.c:208 -#, c-format -msgid "could not determine seek position in file \"%s\": %s" -msgstr "не вдалося визначити позицію у файлі \"%s\": %s" - -#: receivelog.c:223 +#: receivelog.c:216 #, c-format msgid "not renaming \"%s\", segment is not complete" msgstr "не перейменовується \"%s\", сегмент не завершений" -#: receivelog.c:234 receivelog.c:323 receivelog.c:694 +#: receivelog.c:227 receivelog.c:317 receivelog.c:688 #, c-format msgid "could not close file \"%s\": %s" msgstr "не вдалося закрити файл \"%s\": %s" -#: receivelog.c:295 +#: receivelog.c:288 #, c-format msgid "server reported unexpected history file name for timeline %u: %s" msgstr "сервер повідомив неочікуване ім'я файлу історії часової шкали %u: %s" -#: receivelog.c:303 +#: receivelog.c:297 #, c-format msgid "could not create timeline history file \"%s\": %s" msgstr "не вдалося створити файл історії часової шкали \"%s\": %s" -#: receivelog.c:310 +#: receivelog.c:304 #, c-format msgid "could not write timeline history file \"%s\": %s" msgstr "не вдалося записати файл історії часової шкали \"%s\": %s" -#: receivelog.c:400 +#: receivelog.c:394 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions older than %s" msgstr "несумісна версія серверу %s; клієнт не підтримує потокове передавання з версій серверу старіших, ніж %s" -#: receivelog.c:409 +#: receivelog.c:403 #, c-format msgid "incompatible server version %s; client does not support streaming from server versions newer than %s" msgstr "несумісна версія серверу %s; клієнт не підтримує потокове передавання з версій серверу новіших, ніж %s" -#: receivelog.c:514 +#: receivelog.c:508 #, c-format msgid "system identifier does not match between base backup and streaming connection" msgstr "системний ідентифікатор базової резервної копії не відповідає ідентифікатору потокового передавання підключення" -#: receivelog.c:522 +#: receivelog.c:516 #, c-format msgid "starting timeline %u is not present in the server" msgstr "початкова часова шкала %u не існує на сервері" -#: receivelog.c:561 +#: receivelog.c:555 #, c-format msgid "unexpected response to TIMELINE_HISTORY command: got %d rows and %d fields, expected %d rows and %d fields" msgstr "неочікувана відповідь на команду TIMELINE_HISTORY: отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: receivelog.c:632 +#: receivelog.c:626 #, c-format msgid "server reported unexpected next timeline %u, following timeline %u" msgstr "сервер неочікувано повідомив наступну часову шкалу %u після часової шкали %u" -#: receivelog.c:638 +#: receivelog.c:632 #, c-format msgid "server stopped streaming timeline %u at %X/%X, but reported next timeline %u to begin at %X/%X" msgstr "сервер зупинив потокове передавання часової шкали %u в позиції %X/%X, але повідомив, що наступна часова шкала %u почнеться в позиції %X/%X" -#: receivelog.c:678 +#: receivelog.c:672 #, c-format msgid "replication stream was terminated before stop point" msgstr "потік реплікації перервано до точки зупинки" -#: receivelog.c:724 +#: receivelog.c:718 #, c-format msgid "unexpected result set after end-of-timeline: got %d rows and %d fields, expected %d rows and %d fields" msgstr "неочікуваний набір результатів після кінця часової шкали: отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: receivelog.c:733 +#: receivelog.c:727 #, c-format msgid "could not parse next timeline's starting point \"%s\"" msgstr "не вдалося аналізувати початкову точку наступної часової шкали \"%s\"" -#: receivelog.c:781 receivelog.c:1030 walmethods.c:1203 +#: receivelog.c:775 receivelog.c:1022 walmethods.c:1206 #, c-format msgid "could not fsync file \"%s\": %s" msgstr "не вдалося fsync файл \"%s\": %s" -#: receivelog.c:1091 +#: receivelog.c:1083 #, c-format msgid "received write-ahead log record for offset %u with no file open" msgstr "отримано запис випереджувального журналювання для зсуву %u з закритим файлом" -#: receivelog.c:1101 +#: receivelog.c:1093 #, c-format msgid "got WAL data offset %08x, expected %08x" msgstr "отримано дані зсуву WAL %08x, очікувалось %08x" -#: receivelog.c:1135 +#: receivelog.c:1128 #, c-format msgid "could not write %d bytes to WAL file \"%s\": %s" msgstr "не вдалося записати %d байт до файлу WAL \"%s\": %s" -#: receivelog.c:1160 receivelog.c:1200 receivelog.c:1230 +#: receivelog.c:1153 receivelog.c:1193 receivelog.c:1222 #, c-format msgid "could not send copy-end packet: %s" msgstr "не вдалося відправити пакет кінця копіювання \"copy-end\": %s" -#: streamutil.c:159 +#: streamutil.c:162 msgid "Password: " msgstr "Пароль: " -#: streamutil.c:182 +#: streamutil.c:189 #, c-format msgid "could not connect to server" msgstr "не вдалося підключитись до серверу" -#: streamutil.c:225 +#: streamutil.c:230 #, c-format -msgid "could not clear search_path: %s" -msgstr "не вдалося очистити search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "не вдалося очистити \"search_path\": %s" -#: streamutil.c:241 +#: streamutil.c:246 #, c-format -msgid "could not determine server setting for integer_datetimes" -msgstr "не вдалося визначити настроювання серверу для integer_datetimes" +msgid "could not determine server setting for \"integer_datetimes\"" +msgstr "не вдалося визначити налаштування сервера для \"integer_datetimes\"" -#: streamutil.c:248 +#: streamutil.c:253 #, c-format -msgid "integer_datetimes compile flag does not match server" -msgstr "параметри компіляції integer_datetimes не відповідають серверу" +msgid "\"integer_datetimes\" compile flag does not match server" +msgstr "флаг компіляції \"integer_datetimes\" не відповідає серверу" -#: streamutil.c:299 +#: streamutil.c:372 #, c-format msgid "could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "не вдалося отримати розмір сегменту WAL: отримано %d рядків і %d полів, очікувалось %d рядків і %d або більше полів" -#: streamutil.c:309 +#: streamutil.c:382 #, c-format msgid "WAL segment size could not be parsed" msgstr "не вдалося аналізувати розмір сегмента WAL" -#: streamutil.c:327 +#: streamutil.c:400 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the remote server reported a value of %d bytes" -msgstr[0] "Розмір сегменту WAL повинен бути двійкою, піднесеною до степеня в інтервалі між 1 МБ і 1 ГБ, але віддалений сервер повідомив значення %d байт" -msgstr[1] "Розмір сегменту WAL повинен бути двійкою, піднесеною до степеня в інтервалі між 1 МБ і 1 ГБ, але віддалений сервер повідомив значення %d байти" -msgstr[2] "Розмір сегменту WAL повинен бути двійкою, піднесеною до степеня в інтервалі між 1 МБ і 1 ГБ, але віддалений сервер повідомив значення %d байтів" -msgstr[3] "Розмір сегменту WAL повинен бути двійкою, піднесеною до степеня в інтервалі між 1 МБ і 1 ГБ, але віддалений сервер повідомив значення %d байтів" +msgid "remote server reported invalid WAL segment size (%d byte)" +msgid_plural "remote server reported invalid WAL segment size (%d bytes)" +msgstr[0] "віддалений сервер повідомив про неправильний розмір сегмента WAL (%d байт)" +msgstr[1] "віддалений сервер повідомив про неправильний розмір сегмента WAL (%d байтів)" +msgstr[2] "віддалений сервер повідомив про неправильний розмір сегмента WAL (%d байтів)" +msgstr[3] "віддалений сервер повідомив про неправильний розмір сегмента WAL (%d байтів)" -#: streamutil.c:372 +#: streamutil.c:404 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Розмір сегмента WAL повинен бути степенем двійки від 1 МБ до 1 ГБ." + +#: streamutil.c:446 #, c-format msgid "could not fetch group access flag: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "не вдалося вилучити позначку доступа групи: отримано %d рядків і %d полів, очікувалось %d рядків і %d або більше полів" -#: streamutil.c:381 +#: streamutil.c:455 #, c-format msgid "group access flag could not be parsed: %s" msgstr "не вдалося аналізувати позначку доступа групи: %s" -#: streamutil.c:424 streamutil.c:461 +#: streamutil.c:498 streamutil.c:535 #, c-format msgid "could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields" msgstr "не вдалося ідентифікувати систему: отримано %d рядків і %d полів, очікувалось %d рядків і %d або більше полів" -#: streamutil.c:513 +#: streamutil.c:587 #, c-format msgid "could not read replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "не вдалося прочитати слот реплікації \"%s\": отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: streamutil.c:525 +#: streamutil.c:599 #, c-format -msgid "could not find replication slot \"%s\"" -msgstr "не вдалося знайти слот реплікації \"%s\"" +msgid "replication slot \"%s\" does not exist" +msgstr "слот реплікації \"%s\" не існує" -#: streamutil.c:536 +#: streamutil.c:610 #, c-format msgid "expected a physical replication slot, got type \"%s\" instead" msgstr "очікувався слот фізичної реплікації, а натомість знайдено \"%s\"" -#: streamutil.c:550 +#: streamutil.c:624 #, c-format msgid "could not parse restart_lsn \"%s\" for replication slot \"%s\"" msgstr "не вдалося аналізувати restart_lsn \"%s\" для слоту реплікації \"%s\"" -#: streamutil.c:667 +#: streamutil.c:741 #, c-format msgid "could not create replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "не вдалося створити слот реплікації \"%s\": отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: streamutil.c:711 +#: streamutil.c:785 #, c-format msgid "could not drop replication slot \"%s\": got %d rows and %d fields, expected %d rows and %d fields" msgstr "не вдалося видалити слот реплікації \"%s\": отримано %d рядків і %d полів, очікувалось %d рядків і %d полів" -#: walmethods.c:720 walmethods.c:1265 +#: walmethods.c:726 walmethods.c:1269 msgid "could not compress data" msgstr "не вдалося стиснути дані" -#: walmethods.c:749 +#: walmethods.c:755 msgid "could not reset compression stream" msgstr "не вдалося скинути потік стискання" -#: walmethods.c:880 +#: walmethods.c:892 msgid "implementation error: tar files can't have more than one open file" msgstr "помилка реалізації: файли tar не можуть мати більше одного відкритого файлу" -#: walmethods.c:894 +#: walmethods.c:907 msgid "could not create tar header" msgstr "не вдалося створити заголовок tar" -#: walmethods.c:910 walmethods.c:950 walmethods.c:1169 walmethods.c:1181 +#: walmethods.c:924 walmethods.c:965 walmethods.c:1171 walmethods.c:1184 msgid "could not change compression parameters" msgstr "не вдалося змінити параметри стискання" -#: walmethods.c:1054 +#: walmethods.c:1056 msgid "unlink not supported with compression" msgstr "unink не підтримується зі стисканням" -#: walmethods.c:1289 +#: walmethods.c:1293 msgid "could not close compression stream" msgstr "не вдалося закрити потік стискання" diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c index 70f4246764950..6b6e32dfbdf56 100644 --- a/src/bin/pg_basebackup/receivelog.c +++ b/src/bin/pg_basebackup/receivelog.c @@ -5,7 +5,7 @@ * * Author: Magnus Hagander * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/receivelog.c @@ -19,7 +19,6 @@ #include #include "access/xlog_internal.h" -#include "common/file_utils.h" #include "common/logging.h" #include "libpq-fe.h" #include "receivelog.h" @@ -192,7 +191,7 @@ static bool close_walfile(StreamCtl *stream, XLogRecPtr pos) { char *fn; - off_t currpos; + pgoff_t currpos; int r; char walfile_name[MAXPGPATH]; @@ -804,6 +803,10 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream, sleeptime = CalculateCopyStreamSleeptime(now, stream->standby_message_timeout, last_status); + /* Done with any prior message */ + PQfreemem(copybuf); + copybuf = NULL; + r = CopyStreamReceive(conn, sleeptime, stream->stop_socket, ©buf); while (r != 0) { @@ -815,8 +818,8 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream, if (res == NULL) goto error; - else - return res; + PQfreemem(copybuf); + return res; } /* Check the message type. */ @@ -845,6 +848,10 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream, goto error; } + /* Done with that message */ + PQfreemem(copybuf); + copybuf = NULL; + /* * Process the received data, and any subsequent data we can read * without blocking. @@ -921,8 +928,8 @@ CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket) * maximum of 'timeout' ms. * * If data was received, returns the length of the data. *buffer is set to - * point to a buffer holding the received message. The buffer is only valid - * until the next CopyStreamReceive call. + * point to a buffer holding the received message. The caller must eventually + * free the buffer with PQfreemem(). * * Returns 0 if no data was available within timeout, or if wait was * interrupted by signal or stop_socket input. @@ -935,8 +942,8 @@ CopyStreamReceive(PGconn *conn, long timeout, pgsocket stop_socket, char *copybuf = NULL; int rawlen; - PQfreemem(*buffer); - *buffer = NULL; + /* Caller should have cleared any prior buffer */ + Assert(*buffer == NULL); /* Try to receive a CopyData message */ rawlen = PQgetCopyData(conn, ©buf, 1); @@ -1199,7 +1206,6 @@ HandleEndOfCopyStream(PGconn *conn, StreamCtl *stream, char *copybuf, } still_sending = false; } - PQfreemem(copybuf); *stoppos = blockpos; return res; } diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h index 0a18f897964f6..36beddcea459f 100644 --- a/src/bin/pg_basebackup/receivelog.h +++ b/src/bin/pg_basebackup/receivelog.h @@ -2,7 +2,7 @@ * * receivelog.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/receivelog.h diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c index feee451d5951e..c7b8a4c3a4b6a 100644 --- a/src/bin/pg_basebackup/streamutil.c +++ b/src/bin/pg_basebackup/streamutil.c @@ -5,7 +5,7 @@ * * Author: Magnus Hagander * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/streamutil.c @@ -19,14 +19,12 @@ #include "access/xlog_internal.h" #include "common/connect.h" -#include "common/fe_memutils.h" #include "common/file_perm.h" #include "common/logging.h" #include "common/string.h" #include "datatype/timestamp.h" #include "port/pg_bswap.h" #include "pqexpbuffer.h" -#include "receivelog.h" #include "streamutil.h" #define ERRCODE_DUPLICATE_OBJECT "42710" @@ -34,7 +32,6 @@ int WalSegSz; static bool RetrieveDataDirCreatePerm(PGconn *conn); -static char *FindDbnameInConnParams(PQconninfoOption *conn_opts); /* SHOW command for replication connection was introduced in version 10 */ #define MINIMUM_VERSION_FOR_SHOW_CMD 100000 @@ -74,7 +71,10 @@ GetConnection(void) PQconninfoOption *conn_opt; char *err_msg = NULL; - /* pg_recvlogical uses dbname only; others use connection_string only. */ + /* + * pg_recvlogical uses dbname only; others use connection_string only. + * (Note: both variables will be NULL if there's no command line options.) + */ Assert(dbname == NULL || connection_string == NULL); /* @@ -120,12 +120,12 @@ GetConnection(void) keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); values = pg_malloc0((argcount + 1) * sizeof(*values)); keywords[i] = "dbname"; - values[i] = dbname; + values[i] = (dbname == NULL) ? "replication" : dbname; i++; } keywords[i] = "replication"; - values[i] = dbname == NULL ? "true" : "database"; + values[i] = (dbname == NULL) ? "true" : "database"; i++; keywords[i] = "fallback_application_name"; values[i] = progname; @@ -268,74 +268,6 @@ GetConnection(void) return tmpconn; } -/* - * FindDbnameInConnParams - * - * This is a helper function for GetDbnameFromConnectionOptions(). Extract - * the value of dbname from PQconninfoOption parameters, if it's present. - * Returns a strdup'd result or NULL. - */ -static char * -FindDbnameInConnParams(PQconninfoOption *conn_opts) -{ - PQconninfoOption *conn_opt; - - for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) - { - if (strcmp(conn_opt->keyword, "dbname") == 0 && - conn_opt->val != NULL && conn_opt->val[0] != '\0') - return pg_strdup(conn_opt->val); - } - return NULL; -} - -/* - * GetDbnameFromConnectionOptions - * - * This is a special purpose function to retrieve the dbname from either the - * connection_string specified by the user or from the environment variables. - * - * We follow GetConnection() to fetch the dbname from various connection - * options. - * - * Returns NULL, if dbname is not specified by the user in the above - * mentioned connection options. - */ -char * -GetDbnameFromConnectionOptions(void) -{ - PQconninfoOption *conn_opts; - char *err_msg = NULL; - char *dbname; - - /* First try to get the dbname from connection string. */ - if (connection_string) - { - conn_opts = PQconninfoParse(connection_string, &err_msg); - if (conn_opts == NULL) - pg_fatal("%s", err_msg); - - dbname = FindDbnameInConnParams(conn_opts); - - PQconninfoFree(conn_opts); - if (dbname) - return dbname; - } - - /* - * Next try to get the dbname from default values that are available from - * the environment. - */ - conn_opts = PQconndefaults(); - if (conn_opts == NULL) - pg_fatal("out of memory"); - - dbname = FindDbnameInConnParams(conn_opts); - - PQconninfoFree(conn_opts); - return dbname; -} - /* * From version 10, explicitly set wal segment size using SHOW wal_segment_size * since ControlFile is not accessible here. @@ -631,7 +563,7 @@ GetSlotInformation(PGconn *conn, const char *slot_name, /* current TLI */ if (!PQgetisnull(res, 0, 2)) - tli_loc = (TimeLineID) atol(PQgetvalue(res, 0, 2)); + tli_loc = (TimeLineID) atoll(PQgetvalue(res, 0, 2)); PQclear(res); @@ -651,7 +583,7 @@ GetSlotInformation(PGconn *conn, const char *slot_name, bool CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin, bool is_temporary, bool is_physical, bool reserve_wal, - bool slot_exists_ok, bool two_phase) + bool slot_exists_ok, bool two_phase, bool failover) { PQExpBuffer query; PGresult *res; @@ -662,6 +594,7 @@ CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin, Assert((is_physical && plugin == NULL) || (!is_physical && plugin != NULL)); Assert(!(two_phase && is_physical)); + Assert(!(failover && is_physical)); Assert(slot_name != NULL); /* Build base portion of query */ @@ -684,6 +617,10 @@ CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin, } else { + if (failover && PQserverVersion(conn) >= 170000) + AppendPlainCommandOption(query, use_new_option_syntax, + "FAILOVER"); + if (two_phase && PQserverVersion(conn) >= 150000) AppendPlainCommandOption(query, use_new_option_syntax, "TWO_PHASE"); diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h index 9b38e8c0f38f9..017b227303c83 100644 --- a/src/bin/pg_basebackup/streamutil.h +++ b/src/bin/pg_basebackup/streamutil.h @@ -2,7 +2,7 @@ * * streamutil.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/streamutil.h @@ -31,13 +31,12 @@ extern PGconn *conn; extern PGconn *GetConnection(void); -extern char *GetDbnameFromConnectionOptions(void); - /* Replication commands */ extern bool CreateReplicationSlot(PGconn *conn, const char *slot_name, const char *plugin, bool is_temporary, bool is_physical, bool reserve_wal, - bool slot_exists_ok, bool two_phase); + bool slot_exists_ok, bool two_phase, + bool failover); extern bool DropReplicationSlot(PGconn *conn, const char *slot_name); extern bool RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli, diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl index eebe3307d2cba..7cdd444275524 100644 --- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl +++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -31,7 +31,7 @@ # Initialize node without replication settings $node->init( extra => ['--data-checksums'], - auth_extra => [ '--create-role', 'backupuser' ]); + auth_extra => [ '--create-role' => 'backupuser' ]); $node->start; my $pgdata = $node->data_dir; @@ -40,11 +40,19 @@ # Sanity checks for options $node->command_fails_like( - [ 'pg_basebackup', '-D', "$tempdir/backup", '--compress', 'none:1' ], + [ + 'pg_basebackup', + '--pgdata' => "$tempdir/backup", + '--compress' => 'none:1' + ], qr/\Qcompression algorithm "none" does not accept a compression level/, 'failure if method "none" specified with compression level'); $node->command_fails_like( - [ 'pg_basebackup', '-D', "$tempdir/backup", '--compress', 'none+' ], + [ + 'pg_basebackup', + '--pgdata' => "$tempdir/backup", + '--compress' => 'none+' + ], qr/\Qunrecognized compression algorithm: "none+"/, 'failure on incorrect separator to define compression level'); @@ -60,7 +68,7 @@ $node->reload; $node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup" ], + [ @pg_basebackup_defs, '--pgdata' => "$tempdir/backup" ], 'pg_basebackup fails because of WAL configuration'); ok(!-d "$tempdir/backup", 'backup directory was cleaned up'); @@ -71,7 +79,8 @@ or BAIL_OUT("unable to create $tempdir/backup"); append_to_file("$tempdir/backup/dir-not-empty.txt", "Some data"); -$node->command_fails([ @pg_basebackup_defs, '-D', "$tempdir/backup", '-n' ], +$node->command_fails( + [ @pg_basebackup_defs, '--pgdata' => "$tempdir/backup", '-n' ], 'failing run with no-clean option'); ok(-d "$tempdir/backup", 'backup directory was created and left behind'); @@ -153,17 +162,17 @@ my $sfail = quotemeta($server_fails . $cft->[1]); $node->command_fails_like( [ - 'pg_basebackup', '-D', - "$tempdir/backup", '--compress', - $cft->[0] + 'pg_basebackup', + '--pgdata' => "$tempdir/backup", + '--compress' => $cft->[0], ], qr/$cfail/, 'client ' . $cft->[2]); $node->command_fails_like( [ - 'pg_basebackup', '-D', - "$tempdir/backup", '--compress', - 'server-' . $cft->[0] + 'pg_basebackup', + '--pgdata' => "$tempdir/backup", + '--compress' => 'server-' . $cft->[0], ], qr/$sfail/, 'server ' . $cft->[2]); @@ -219,7 +228,11 @@ # Run base backup. $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backup", '-X', 'none' ], + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup", + '--wal-method' => 'none' + ], 'pg_basebackup runs'); ok(-f "$tempdir/backup/PG_VERSION", 'backup was created'); ok(-f "$tempdir/backup/backup_manifest", 'backup manifest included'); @@ -289,9 +302,10 @@ $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup2", '--no-manifest', - '--waldir', "$tempdir/xlog2" + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup2", + '--no-manifest', + '--waldir' => "$tempdir/xlog2" ], 'separate xlog directory'); ok(-f "$tempdir/backup2/PG_VERSION", 'backup was created'); @@ -300,32 +314,70 @@ rmtree("$tempdir/backup2"); rmtree("$tempdir/xlog2"); -$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/tarbackup", '-Ft' ], +$node->command_ok( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/tarbackup", + '--format' => 'tar' + ], 'tar format'); ok(-f "$tempdir/tarbackup/base.tar", 'backup tar was created'); rmtree("$tempdir/tarbackup"); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', "-T=/foo" ], - '-T with empty old directory fails'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', "-T/foo=" ], - '-T with empty new directory fails'); -$node->command_fails( +$node->command_fails_like( [ - @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', - "-T/foo=/bar=/baz" + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => '=/foo' ], - '-T with multiple = fails'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', "-Tfoo=/bar" ], - '-T with old directory not absolute fails'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', "-T/foo=bar" ], - '-T with new directory not absolute fails'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_foo", '-Fp', "-Tfoo" ], - '-T with invalid format fails'); + qr/invalid tablespace mapping format/, + '--tablespace-mapping with empty old directory fails'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => '/foo=' + ], + qr/invalid tablespace mapping format/, + '--tablespace-mapping with empty new directory fails'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => '/foo=/bar=/baz' + ], + qr/multiple "=" signs in tablespace mapping/, + '--tablespace-mapping with multiple = fails'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => 'foo=/bar' + ], + qr/old directory is not an absolute path in tablespace mapping/, + '--tablespace-mapping with old directory not absolute fails'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => '/foo=bar' + ], + qr/new directory is not an absolute path in tablespace mapping/, + '--tablespace-mapping with new directory not absolute fails'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_foo", + '--format' => 'plain', + '--tablespace-mapping' => 'foo' + ], + qr/invalid tablespace mapping format/, + '--tablespace-mapping with invalid format fails'); my $superlongname = "superlongname_" . ("x" x 100); # Tar format doesn't support filenames longer than 100 bytes. @@ -340,7 +392,11 @@ or die "unable to create file $superlongpath"; close $file; $node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/tarbackup_l1", '-Ft' ], + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/tarbackup_l1", + '--format' => 'tar' + ], 'pg_basebackup tar with long name fails'); unlink "$superlongpath"; } @@ -364,7 +420,7 @@ # drives. rmdir("$pgdata/pg_replslot") or BAIL_OUT "could not remove $pgdata/pg_replslot"; -mkdir("$sys_tempdir/pg_replslot"); # if this fails the symlink will fail +mkdir("$sys_tempdir/pg_replslot"); # if this fails the symlink will fail dir_symlink("$sys_tempdir/pg_replslot", "$pgdata/pg_replslot") or BAIL_OUT "could not symlink to $pgdata/pg_replslot"; @@ -384,7 +440,7 @@ $node->safe_psql('postgres', "CREATE TABLE test1 (a int) TABLESPACE tblspc1;" . "INSERT INTO test1 VALUES (1234);"); -$node->backup('tarbackup2', backup_options => ['-Ft']); +$node->backup('tarbackup2', backup_options => [ '--format' => 'tar' ]); # empty test1, just so that it's different from the to-be-restored data $node->safe_psql('postgres', "TRUNCATE TABLE test1;"); @@ -414,7 +470,7 @@ $node2->init_from_backup( $node, 'tarbackup2', tar_program => $tar, - 'tablespace_map' => { $tblspcoid => $realRepTsDir }); + tablespace_map => { $tblspcoid => $realRepTsDir }); $node2->start; my $result = $node2->safe_psql('postgres', 'SELECT * FROM test1'); @@ -451,14 +507,19 @@ } $node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backup1", '-Fp' ], + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup1", + '--format' => 'plain' + ], 'plain format with tablespaces fails without tablespace mapping'); $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup1", '-Fp', - "-T$realTsDir=$tempdir/tbackup/tblspc1", + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup1", + '--format' => 'plain', + '--tablespace-mapping' => "$realTsDir=$tempdir/tbackup/tblspc1", ], 'plain format with tablespaces succeeds with tablespace mapping'); ok(-d "$tempdir/tbackup/tblspc1", 'tablespace was relocated'); @@ -526,9 +587,10 @@ $realTsDir =~ s/=/\\=/; $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup3", '-Fp', - "-T$realTsDir=$tempdir/tbackup/tbl\\=spc2", + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup3", + '--format' => 'plain', + '--tablespace-mapping' => "$realTsDir=$tempdir/tbackup/tbl\\=spc2", ], 'mapping tablespace with = sign in path'); ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated'); @@ -540,13 +602,22 @@ $node->safe_psql('postgres', "CREATE TABLESPACE tblspc3 LOCATION '$realTsDir';"); $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/tarbackup_l3", '-Ft' ], + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/tarbackup_l3", + '--format' => 'tar' + ], 'pg_basebackup tar with long symlink target'); $node->safe_psql('postgres', "DROP TABLESPACE tblspc3;"); rmtree("$tempdir/tarbackup_l3"); -$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/backupR", '-R' ], - 'pg_basebackup -R runs'); +$node->command_ok( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupR", + '--write-recovery-conf' + ], + 'pg_basebackup --write-recovery-conf runs'); ok(-f "$tempdir/backupR/postgresql.auto.conf", 'postgresql.auto.conf exists'); ok(-f "$tempdir/backupR/standby.signal", 'standby.signal was created'); my $recovery_conf = slurp_file "$tempdir/backupR/postgresql.auto.conf"; @@ -558,76 +629,105 @@ qr/^primary_conninfo = '.*port=$port.*'\n/m, 'postgresql.auto.conf sets primary_conninfo'); -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxd" ], +$node->command_ok([ @pg_basebackup_defs, '--pgdata' => "$tempdir/backupxd" ], 'pg_basebackup runs in default xlog mode'); ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxd/pg_wal")), 'WAL files copied'); rmtree("$tempdir/backupxd"); $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxf", '-X', 'fetch' ], - 'pg_basebackup -X fetch runs'); + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxf", + '--wal-method' => 'fetch' + ], + 'pg_basebackup --wal-method fetch runs'); ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxf/pg_wal")), 'WAL files copied'); rmtree("$tempdir/backupxf"); $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs", '-X', 'stream' ], - 'pg_basebackup -X stream runs'); + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs", + '--wal-method' => 'stream' + ], + 'pg_basebackup --wal-method stream runs'); ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxs/pg_wal")), 'WAL files copied'); rmtree("$tempdir/backupxs"); $node->command_ok( [ - @pg_basebackup_defs, '-D', "$tempdir/backupxst", '-X', 'stream', - '-Ft' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxst", + '--wal-method' => 'stream', + '--format' => 'tar' ], - 'pg_basebackup -X stream runs in tar mode'); + 'pg_basebackup --wal-method stream runs in tar mode'); ok(-f "$tempdir/backupxst/pg_wal.tar", "tar file was created"); rmtree("$tempdir/backupxst"); $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupnoslot", '-X', - 'stream', '--no-slot' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupnoslot", + '--wal-method' => 'stream', + '--no-slot' ], - 'pg_basebackup -X stream runs with --no-slot'); + 'pg_basebackup --wal-method stream runs with --no-slot'); rmtree("$tempdir/backupnoslot"); $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxf", '-X', 'fetch' ], - 'pg_basebackup -X fetch runs'); + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxf", + '--wal-method' => 'fetch' + ], + 'pg_basebackup --wal-method fetch runs'); $node->command_fails_like( - [ @pg_basebackup_defs, '--target', 'blackhole' ], + [ @pg_basebackup_defs, '--target' => 'blackhole' ], qr/WAL cannot be streamed when a backup target is specified/, - 'backup target requires -X'); + 'backup target requires --wal-method'); $node->command_fails_like( - [ @pg_basebackup_defs, '--target', 'blackhole', '-X', 'stream' ], + [ + @pg_basebackup_defs, + '--target' => 'blackhole', + '--wal-method' => 'stream' + ], qr/WAL cannot be streamed when a backup target is specified/, - 'backup target requires -X other than -X stream'); + 'backup target requires --wal-method other than --wal-method stream'); $node->command_fails_like( - [ @pg_basebackup_defs, '--target', 'bogus', '-X', 'none' ], + [ @pg_basebackup_defs, '--target' => 'bogus', '--wal-method' => 'none' ], qr/unrecognized target/, 'backup target unrecognized'); $node->command_fails_like( [ - @pg_basebackup_defs, '--target', 'blackhole', '-X', - 'none', '-D', "$tempdir/blackhole" + @pg_basebackup_defs, + '--target' => 'blackhole', + '--wal-method' => 'none', + '--pgdata' => "$tempdir/blackhole" ], qr/cannot specify both output directory and backup target/, 'backup target and output directory'); $node->command_fails_like( - [ @pg_basebackup_defs, '--target', 'blackhole', '-X', 'none', '-Ft' ], + [ + @pg_basebackup_defs, + '--target' => 'blackhole', + '--wal-method' => 'none', + '--format' => 'tar' + ], qr/cannot specify both format and backup target/, - 'backup target and output directory'); + 'backup target and format'); $node->command_ok( - [ @pg_basebackup_defs, '--target', 'blackhole', '-X', 'none' ], + [ + @pg_basebackup_defs, + '--target' => 'blackhole', + '--wal-method' => 'none' + ], 'backup target blackhole'); $node->command_ok( [ - @pg_basebackup_defs, '--target', - "server:$tempdir/backuponserver", '-X', - 'none' + @pg_basebackup_defs, + '--target' => "server:$tempdir/backuponserver", + '--wal-method' => 'none' ], 'backup target server'); ok(-f "$tempdir/backuponserver/base.tar", 'backup tar was created'); @@ -638,77 +738,70 @@ 'create backup user'); $node->command_ok( [ - @pg_basebackup_defs, '-U', 'backupuser', '--target', - "server:$tempdir/backuponserver", - '-X', 'none' + @pg_basebackup_defs, + '--username' => 'backupuser', + '--target' => "server:$tempdir/backuponserver", + '--wal-method' => 'none' ], 'backup target server'); ok( -f "$tempdir/backuponserver/base.tar", 'backup tar was created as non-superuser'); rmtree("$tempdir/backuponserver"); -$node->command_fails( +$node->command_fails_like( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_sl_fail", '-X', - 'stream', '-S', - 'slot0' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_sl_fail", + '--wal-method' => 'stream', + '--slot' => 'slot0' ], + qr/replication slot "slot0" does not exist/, 'pg_basebackup fails with nonexistent replication slot'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C' ], - 'pg_basebackup -C fails without slot name'); +$node->command_fails_like( + [ + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_slot", + '--create-slot' + ], + qr/--create-slot needs a slot to be specified using --slot/, + 'pg_basebackup --create-slot fails without slot name'); -$node->command_fails( +$node->command_fails_like( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_slot", '-C', - '-S', 'slot0', + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_slot", + '--create-slot', + '--slot' => 'slot0', '--no-slot' ], - 'pg_basebackup fails with -C -S --no-slot'); + qr/--no-slot cannot be used with slot name/, + 'pg_basebackup fails with --create-slot --slot --no-slot'); $node->command_fails_like( [ - @pg_basebackup_defs, '--target', 'blackhole', '-D', - "$tempdir/blackhole" + @pg_basebackup_defs, + '--target' => 'blackhole', + '--pgdata' => "$tempdir/blackhole" ], qr/cannot specify both output directory and backup target/, 'backup target and output directory'); $node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backuptr/co", '-X', 'none' ], - 'pg_basebackup -X fetch runs'); - -$node->command_fails( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_sl_fail", '-X', - 'stream', '-S', - 'slot0' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backuptr/co", + '--wal-method' => 'none' ], - 'pg_basebackup fails with nonexistent replication slot'); - -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C' ], - 'pg_basebackup -C fails without slot name'); - -$node->command_fails( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_slot", '-C', - '-S', 'slot0', - '--no-slot' - ], - 'pg_basebackup fails with -C -S --no-slot'); + 'pg_basebackup --wal-method fetch runs'); $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_slot", '-C', - '-S', 'slot0' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_slot", + '--create-slot', + '--slot' => 'slot0' ], - 'pg_basebackup -C runs'); + 'pg_basebackup --create-slot runs'); rmtree("$tempdir/backupxs_slot"); is( $node->safe_psql( @@ -725,13 +818,16 @@ '', 'restart LSN of new slot is not null'); -$node->command_fails( +$node->command_fails_like( [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_slot1", '-C', - '-S', 'slot0' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_slot1", + '--create-slot', + '--slot' => 'slot0' ], - 'pg_basebackup fails with -C -S and a previously existing slot'); + qr/replication slot "slot0" already exists/, + 'pg_basebackup fails with --create-slot --slot and a previously existing slot' +); $node->safe_psql('postgres', q{SELECT * FROM pg_create_physical_replication_slot('slot1')}); @@ -741,16 +837,20 @@ is($lsn, '', 'restart LSN of new slot is null'); $node->command_fails( [ - @pg_basebackup_defs, '-D', "$tempdir/fail", '-S', - 'slot1', '-X', 'none' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/fail", + '--slot' => 'slot1', + '--wal-method' => 'none' ], 'pg_basebackup with replication slot fails without WAL streaming'); $node->command_ok( [ - @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl", '-X', - 'stream', '-S', 'slot1' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_sl", + '--wal-method' => 'stream', + '--slot' => 'slot1' ], - 'pg_basebackup -X stream with replication slot runs'); + 'pg_basebackup --wal-method stream with replication slot runs'); $lsn = $node->safe_psql('postgres', q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'} ); @@ -759,10 +859,13 @@ $node->command_ok( [ - @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl_R", '-X', - 'stream', '-S', 'slot1', '-R', + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backupxs_sl_R", + '--wal-method' => 'stream', + '--slot' => 'slot1', + '--write-recovery-conf', ], - 'pg_basebackup with replication slot and -R runs'); + 'pg_basebackup with replication slot and --write-recovery-conf runs'); like( slurp_file("$tempdir/backupxs_sl_R/postgresql.auto.conf"), qr/^primary_slot_name = 'slot1'\n/m, @@ -774,10 +877,13 @@ $node->command_ok( [ - @pg_basebackup_defs, '-D', "$tempdir/backup_dbname_R", '-X', - 'stream', '-d', "dbname=db1", '-R', + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_dbname_R", + '--wal-method' => 'stream', + '--dbname' => "dbname=db1", + '--write-recovery-conf', ], - 'pg_basebackup with dbname and -R runs'); + 'pg_basebackup with dbname and --write-recovery-conf runs'); like(slurp_file("$tempdir/backup_dbname_R/postgresql.auto.conf"), qr/dbname=db1/m, 'recovery conf file sets dbname'); @@ -800,7 +906,7 @@ $node->start; $node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt" ], + [ @pg_basebackup_defs, '--pgdata' => "$tempdir/backup_corrupt" ], 1, [qr{^$}], [qr/^WARNING.*checksum verification failed/s], @@ -816,7 +922,7 @@ $node->start; $node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt2" ], + [ @pg_basebackup_defs, '--pgdata' => "$tempdir/backup_corrupt2" ], 1, [qr{^$}], [qr/^WARNING.*further.*failures.*will.not.be.reported/s], @@ -829,7 +935,7 @@ $node->start; $node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt3" ], + [ @pg_basebackup_defs, '--pgdata' => "$tempdir/backup_corrupt3" ], 1, [qr{^$}], [qr/^WARNING.*7 total checksum verification failures/s], @@ -839,8 +945,9 @@ # do not verify checksums, should return ok $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_corrupt4", '--no-verify-checksums', + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_corrupt4", + '--no-verify-checksums', ], 'pg_basebackup with -k does not report checksum mismatch'); rmtree("$tempdir/backup_corrupt4"); @@ -858,25 +965,26 @@ $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_gzip", '--compress', - '1', '--format', - 't' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_gzip", + '--compress' => '1', + '--format' => 't' ], 'pg_basebackup with --compress'); $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_gzip2", '--gzip', - '--format', 't' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_gzip2", + '--gzip', + '--format' => 't' ], 'pg_basebackup with --gzip'); $node->command_ok( [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_gzip3", '--compress', - 'gzip:1', '--format', - 't' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/backup_gzip3", + '--compress' => 'gzip:1', + '--format' => 't' ], 'pg_basebackup with --compress=gzip:1'); @@ -921,16 +1029,13 @@ my $sigchld_bb = IPC::Run::start( [ @pg_basebackup_defs, '--wal-method=stream', - '-D', "$tempdir/sigchld", - '--max-rate=32', '-d', - $node->connstr('postgres') - ], - '<', - \$sigchld_bb_stdin, - '>', - \$sigchld_bb_stdout, - '2>', - \$sigchld_bb_stderr, + '--pgdata' => "$tempdir/sigchld", + '--max-rate' => '32', + '--dbname' => $node->connstr('postgres') + ], + '<' => \$sigchld_bb_stdin, + '>' => \$sigchld_bb_stdout, + '2>' => \$sigchld_bb_stderr, $sigchld_bb_timeout); is( $node->poll_query_until( @@ -977,11 +1082,11 @@ $node2->command_fails_like( [ - @pg_basebackup_defs, '-D', - "$tempdir" . '/diff_sysid', '--incremental', - "$backupdir" . '/backup_manifest' + @pg_basebackup_defs, + '--pgdata' => "$tempdir/diff_sysid", + '--incremental' => "$backupdir/backup_manifest", ], - qr/manifest system identifier is .*, but database system identifier is/, + qr/system identifier in backup manifest is .*, but database system identifier is/, "pg_basebackup fails with different database system manifest"); done_testing(); diff --git a/src/bin/pg_basebackup/t/011_in_place_tablespace.pl b/src/bin/pg_basebackup/t/011_in_place_tablespace.pl index 439171c0ef969..ec942e54eee87 100644 --- a/src/bin/pg_basebackup/t/011_in_place_tablespace.pl +++ b/src/bin/pg_basebackup/t/011_in_place_tablespace.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -12,11 +12,12 @@ # to keep test times reasonable. Using @pg_basebackup_defs as the first # element of the array passed to IPC::Run interpolate the array (as it is # not a reference to an array)... -my @pg_basebackup_defs = ('pg_basebackup', '--no-sync', '-cfast'); +my @pg_basebackup_defs = + ('pg_basebackup', '--no-sync', '--checkpoint' => 'fast'); # Set up an instance. my $node = PostgreSQL::Test::Cluster->new('main'); -$node->init('allows_streaming' => 1); +$node->init(allows_streaming => 1); $node->start(); # Create an in-place tablespace. @@ -28,7 +29,12 @@ # Back it up. my $backupdir = $tempdir . '/backup'; $node->command_ok( - [ @pg_basebackup_defs, '-D', $backupdir, '-Ft', '-X', 'none' ], + [ + @pg_basebackup_defs, + '--pgdata' => $backupdir, + '--format' => 'tar', + '--wal-method' => 'none' + ], 'pg_basebackup runs'); # Make sure we got base.tar and one tablespace. diff --git a/src/bin/pg_basebackup/t/020_pg_receivewal.pl b/src/bin/pg_basebackup/t/020_pg_receivewal.pl index e4a0377331bf4..4be96affd7b7a 100644 --- a/src/bin/pg_basebackup/t/020_pg_receivewal.pl +++ b/src/bin/pg_basebackup/t/020_pg_receivewal.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -25,28 +25,43 @@ $primary->command_fails(['pg_receivewal'], 'pg_receivewal needs target directory specified'); $primary->command_fails( - [ 'pg_receivewal', '-D', $stream_dir, '--create-slot', '--drop-slot' ], + [ + 'pg_receivewal', + '--directory' => $stream_dir, + '--create-slot', + '--drop-slot', + ], 'failure if both --create-slot and --drop-slot specified'); $primary->command_fails( - [ 'pg_receivewal', '-D', $stream_dir, '--create-slot' ], + [ 'pg_receivewal', '--directory' => $stream_dir, '--create-slot' ], 'failure if --create-slot specified without --slot'); $primary->command_fails( - [ 'pg_receivewal', '-D', $stream_dir, '--synchronous', '--no-sync' ], + [ + 'pg_receivewal', + '--directory' => $stream_dir, + '--synchronous', + '--no-sync', + ], 'failure if --synchronous specified with --no-sync'); $primary->command_fails_like( - [ 'pg_receivewal', '-D', $stream_dir, '--compress', 'none:1', ], + [ + 'pg_receivewal', + '--directory' => $stream_dir, + '--compress' => 'none:1', + ], qr/\Qpg_receivewal: error: invalid compression specification: compression algorithm "none" does not accept a compression level/, 'failure if --compress none:N (where N > 0)'); # Slot creation and drop my $slot_name = 'test'; $primary->command_ok( - [ 'pg_receivewal', '--slot', $slot_name, '--create-slot' ], + [ 'pg_receivewal', '--slot' => $slot_name, '--create-slot' ], 'creating a replication slot'); my $slot = $primary->slot($slot_name); is($slot->{'slot_type'}, 'physical', 'physical replication slot was created'); is($slot->{'restart_lsn'}, '', 'restart LSN of new slot is null'); -$primary->command_ok([ 'pg_receivewal', '--slot', $slot_name, '--drop-slot' ], +$primary->command_ok( + [ 'pg_receivewal', '--slot' => $slot_name, '--drop-slot' ], 'dropping a replication slot'); is($primary->slot($slot_name)->{'slot_type'}, '', 'replication slot was removed'); @@ -66,8 +81,12 @@ # compression involved. $primary->command_ok( [ - 'pg_receivewal', '-D', $stream_dir, '--verbose', - '--endpos', $nextlsn, '--synchronous', '--no-loop' + 'pg_receivewal', + '--directory' => $stream_dir, + '--verbose', + '--endpos' => $nextlsn, + '--synchronous', + '--no-loop', ], 'streaming some WAL with --synchronous'); @@ -92,8 +111,11 @@ $primary->command_ok( [ - 'pg_receivewal', '-D', $stream_dir, '--verbose', - '--endpos', $nextlsn, '--compress', 'gzip:1', + 'pg_receivewal', + '--directory' => $stream_dir, + '--verbose', + '--endpos' => $nextlsn, + '--compress' => 'gzip:1', '--no-loop' ], "streaming some WAL using ZLIB compression"); @@ -145,9 +167,12 @@ # Stream up to the given position. $primary->command_ok( [ - 'pg_receivewal', '-D', $stream_dir, '--verbose', - '--endpos', $nextlsn, '--no-loop', '--compress', - 'lz4' + 'pg_receivewal', + '--directory' => $stream_dir, + '--verbose', + '--endpos' => $nextlsn, + '--no-loop', + '--compress' => 'lz4' ], 'streaming some WAL using --compress=lz4'); @@ -191,8 +216,11 @@ $primary->psql('postgres', 'INSERT INTO test_table VALUES (4);'); $primary->command_ok( [ - 'pg_receivewal', '-D', $stream_dir, '--verbose', - '--endpos', $nextlsn, '--no-loop' + 'pg_receivewal', + '--directory' => $stream_dir, + '--verbose', + '--endpos' => $nextlsn, + '--no-loop' ], "streaming some WAL"); @@ -247,17 +275,25 @@ # Check case where the slot does not exist. $primary->command_fails_like( [ - 'pg_receivewal', '-D', $slot_dir, '--slot', - 'nonexistentslot', '-n', '--no-sync', '--verbose', - '--endpos', $nextlsn + 'pg_receivewal', + '--directory' => $slot_dir, + '--slot' => 'nonexistentslot', + '--no-loop', + '--no-sync', + '--verbose', + '--endpos' => $nextlsn ], qr/pg_receivewal: error: replication slot "nonexistentslot" does not exist/, 'pg_receivewal fails with non-existing slot'); $primary->command_ok( [ - 'pg_receivewal', '-D', $slot_dir, '--slot', - $slot_name, '-n', '--no-sync', '--verbose', - '--endpos', $nextlsn + 'pg_receivewal', + '--directory' => $slot_dir, + '--slot' => $slot_name, + '--no-loop', + '--no-sync', + '--verbose', + '--endpos' => $nextlsn ], "WAL streamed from the slot's restart_lsn"); ok(-e "$slot_dir/$walfile_streamed", @@ -311,9 +347,13 @@ $standby->command_ok( [ - 'pg_receivewal', '-D', $timeline_dir, '--verbose', - '--endpos', $nextlsn, '--slot', $archive_slot, - '--no-sync', '-n' + 'pg_receivewal', + '--directory' => $timeline_dir, + '--verbose', + '--endpos' => $nextlsn, + '--slot' => $archive_slot, + '--no-sync', + '--no-loop' ], "Stream some wal after promoting, resuming from the slot's position"); ok(-e "$timeline_dir/$walfile_before_promotion", diff --git a/src/bin/pg_basebackup/t/030_pg_recvlogical.pl b/src/bin/pg_basebackup/t/030_pg_recvlogical.pl index 8432e5660d63f..c82e78847b382 100644 --- a/src/bin/pg_basebackup/t/030_pg_recvlogical.pl +++ b/src/bin/pg_basebackup/t/030_pg_recvlogical.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -28,23 +28,27 @@ $node->start; $node->command_fails(['pg_recvlogical'], 'pg_recvlogical needs a slot name'); -$node->command_fails([ 'pg_recvlogical', '-S', 'test' ], +$node->command_fails( + [ 'pg_recvlogical', '--slot' => 'test' ], 'pg_recvlogical needs a database'); -$node->command_fails([ 'pg_recvlogical', '-S', 'test', '-d', 'postgres' ], +$node->command_fails( + [ 'pg_recvlogical', '--slot' => 'test', '--dbname' => 'postgres' ], 'pg_recvlogical needs an action'); $node->command_fails( [ - 'pg_recvlogical', '-S', - 'test', '-d', - $node->connstr('postgres'), '--start' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--start', ], 'no destination file'); $node->command_ok( [ - 'pg_recvlogical', '-S', - 'test', '-d', - $node->connstr('postgres'), '--create-slot' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--create-slot', ], 'slot created'); @@ -60,26 +64,33 @@ $node->command_ok( [ - 'pg_recvlogical', '-S', 'test', '-d', $node->connstr('postgres'), - '--start', '--endpos', "$nextlsn", '--no-loop', '-f', '-' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--start', + '--endpos' => $nextlsn, + '--no-loop', + '--file' => '-', ], 'replayed a transaction'); $node->command_ok( [ - 'pg_recvlogical', '-S', - 'test', '-d', - $node->connstr('postgres'), '--drop-slot' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--drop-slot' ], 'slot dropped'); #test with two-phase option enabled $node->command_ok( [ - 'pg_recvlogical', '-S', - 'test', '-d', - $node->connstr('postgres'), '--create-slot', - '--two-phase' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--create-slot', + '--two-phase', ], 'slot with two-phase created'); @@ -94,20 +105,49 @@ $node->command_fails( [ - 'pg_recvlogical', '-S', - 'test', '-d', - $node->connstr('postgres'), '--start', - '--endpos', "$nextlsn", + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--start', + '--endpos' => $nextlsn, '--two-phase', '--no-loop', - '-f', '-' + '--file' => '-', ], 'incorrect usage'); $node->command_ok( [ - 'pg_recvlogical', '-S', 'test', '-d', $node->connstr('postgres'), - '--start', '--endpos', "$nextlsn", '--no-loop', '-f', '-' + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--start', + '--endpos' => $nextlsn, + '--no-loop', + '--file' => '-', ], 'replayed a two-phase transaction'); +$node->command_ok( + [ + 'pg_recvlogical', + '--slot' => 'test', + '--drop-slot' + ], + 'drop could work without dbname'); + +# test with failover option enabled +$node->command_ok( + [ + 'pg_recvlogical', + '--slot' => 'test', + '--dbname' => $node->connstr('postgres'), + '--create-slot', + '--failover', + ], + 'slot with failover created'); + +my $result = $node->safe_psql('postgres', + "SELECT failover FROM pg_catalog.pg_replication_slots WHERE slot_name = 'test'"); +is($result, 't', "failover is enabled for the new slot"); + done_testing(); diff --git a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl index 546f784a31115..df4924023fdf2 100644 --- a/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl +++ b/src/bin/pg_basebackup/t/040_pg_createsubscriber.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # # Test using a standby server as the subscriber. @@ -46,69 +46,75 @@ sub generate_db command_fails(['pg_createsubscriber'], 'no subscriber data directory specified'); command_fails( - [ 'pg_createsubscriber', '--pgdata', $datadir ], + [ 'pg_createsubscriber', '--pgdata' => $datadir ], 'no publisher connection string specified'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', ], 'no database name specified'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432', - '--database', 'pg1', - '--database', 'pg1' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--database' => 'pg1', + '--database' => 'pg1', ], 'duplicate database name'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432', - '--publication', 'foo1', - '--publication', 'foo1', - '--database', 'pg1', - '--database', 'pg2' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--publication' => 'foo1', + '--publication' => 'foo1', + '--database' => 'pg1', + '--database' => 'pg2', ], 'duplicate publication name'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432', - '--publication', 'foo1', - '--database', 'pg1', - '--database', 'pg2' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--publication' => 'foo1', + '--database' => 'pg1', + '--database' => 'pg2', ], 'wrong number of publication names'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432', - '--publication', 'foo1', - '--publication', 'foo2', - '--subscription', 'bar1', - '--database', 'pg1', - '--database', 'pg2' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--publication' => 'foo1', + '--publication' => 'foo2', + '--subscription' => 'bar1', + '--database' => 'pg1', + '--database' => 'pg2', ], 'wrong number of subscription names'); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $datadir, - '--publisher-server', 'port=5432', - '--publication', 'foo1', - '--publication', 'foo2', - '--subscription', 'bar1', - '--subscription', 'bar2', - '--replication-slot', 'baz1', - '--database', 'pg1', - '--database', 'pg2' + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $datadir, + '--publisher-server' => 'port=5432', + '--publication' => 'foo1', + '--publication' => 'foo2', + '--subscription' => 'bar1', + '--subscription' => 'bar2', + '--replication-slot' => 'baz1', + '--database' => 'pg1', + '--database' => 'pg2', ], 'wrong number of replication slot names'); @@ -168,41 +174,44 @@ sub generate_db # Run pg_createsubscriber on a promoted server command_fails( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_t->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_t->host, '--subscriber-port', - $node_t->port, '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_t->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_t->host, + '--subscriber-port' => $node_t->port, + '--database' => $db1, + '--database' => $db2, ], 'target server is not in recovery'); # Run pg_createsubscriber when standby is running command_fails( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--database' => $db1, + '--database' => $db2, ], 'standby is up and running'); # Run pg_createsubscriber on about-to-fail node F command_fails( [ - 'pg_createsubscriber', '--verbose', - '--pgdata', $node_f->data_dir, - '--publisher-server', $node_p->connstr($db1), - '--socket-directory', $node_f->host, - '--subscriber-port', $node_f->port, - '--database', $db1, - '--database', $db2 + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $node_f->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_f->host, + '--subscriber-port' => $node_f->port, + '--database' => $db1, + '--database' => $db2 ], 'subscriber data directory is not a copy of the source database cluster'); @@ -216,14 +225,15 @@ sub generate_db # Run pg_createsubscriber on node C (P -> S -> C) command_fails( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_c->data_dir, '--publisher-server', - $node_s->connstr($db1), '--socket-directory', - $node_c->host, '--subscriber-port', - $node_c->port, '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_c->data_dir, + '--publisher-server' => $node_s->connstr($db1), + '--socketdir' => $node_c->host, + '--subscriber-port' => $node_c->port, + '--database' => $db1, + '--database' => $db2, ], 'primary server is in recovery'); @@ -239,14 +249,16 @@ sub generate_db $node_s->stop; command_fails( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--database' => $db1, + '--database' => $db2, + ], 'primary contains unmet conditions on node P'); # Restore default settings here but only apply it after testing standby. Some @@ -262,25 +274,26 @@ sub generate_db # Check some unmet conditions on node S $node_s->append_conf( 'postgresql.conf', q{ -max_replication_slots = 1 +max_active_replication_origins = 1 max_logical_replication_workers = 1 max_worker_processes = 2 }); command_fails( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--database' => $db1, + '--database' => $db2, ], 'standby contains unmet conditions on node S'); $node_s->append_conf( 'postgresql.conf', q{ -max_replication_slots = 10 +max_active_replication_origins = 10 max_logical_replication_workers = 4 max_worker_processes = 8 }); @@ -316,24 +329,40 @@ sub generate_db "CREATE SUBSCRIPTION $dummy_sub CONNECTION 'dbname=dummy' PUBLICATION pub_dummy WITH (connect=false)" ); $node_p->wait_for_replay_catchup($node_s); + +# Create user-defined publications, wait for streaming replication to sync them +# to the standby, then verify that '--remove' +# removes them. +$node_p->safe_psql( + $db1, qq( + CREATE PUBLICATION test_pub1 FOR ALL TABLES; + CREATE PUBLICATION test_pub2 FOR ALL TABLES; +)); + +$node_p->wait_for_replay_catchup($node_s); + +ok($node_s->safe_psql($db1, "SELECT COUNT(*) = 2 FROM pg_publication"), + 'two pre-existing publications on subscriber'); + $node_s->stop; # dry run mode on node S command_ok( [ - 'pg_createsubscriber', '--verbose', - '--recovery-timeout', "$PostgreSQL::Test::Utils::timeout_default", - '--dry-run', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--publication', - 'pub1', '--publication', - 'pub2', '--subscription', - 'sub1', '--subscription', - 'sub2', '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--recovery-timeout' => $PostgreSQL::Test::Utils::timeout_default, + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--publication' => 'pub1', + '--publication' => 'pub2', + '--subscription' => 'sub1', + '--subscription' => 'sub2', + '--database' => $db1, + '--database' => $db2, ], 'run pg_createsubscriber --dry-run on node S'); @@ -346,32 +375,95 @@ sub generate_db # pg_createsubscriber can run without --databases option command_ok( [ - 'pg_createsubscriber', '--verbose', - '--dry-run', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--replication-slot', - 'replslot1' + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--replication-slot' => 'replslot1', ], 'run pg_createsubscriber without --databases'); -# Run pg_createsubscriber on node S +# run pg_createsubscriber with '--database' and '--all' without '--dry-run' +# and verify the failure +command_fails_like( + [ + 'pg_createsubscriber', + '--verbose', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--database' => $db1, + '--all', + ], + qr/options --database and -a\/--all cannot be used together/, + 'fail if --database is used with --all'); + +# run pg_createsubscriber with '--publication' and '--all' and verify +# the failure +command_fails_like( + [ + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--all', + '--publication' => 'pub1', + ], + qr/options --publication and -a\/--all cannot be used together/, + 'fail if --publication is used with --all'); + +# run pg_createsubscriber with '--all' option +my ($stdout, $stderr) = run_command( + [ + 'pg_createsubscriber', + '--verbose', + '--dry-run', + '--recovery-timeout' => $PostgreSQL::Test::Utils::timeout_default, + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr, + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--all', + ], + 'run pg_createsubscriber with --all'); + +# Verify that the required logical replication objects are output. +# The expected count 3 refers to postgres, $db1 and $db2 databases. +is(scalar(() = $stderr =~ /creating publication/g), + 3, "verify publications are created for all databases"); +is(scalar(() = $stderr =~ /creating the replication slot/g), + 3, "verify replication slots are created for all databases"); +is(scalar(() = $stderr =~ /creating subscription/g), + 3, "verify subscriptions are created for all databases"); + +# Run pg_createsubscriber on node S. --verbose is used twice +# to show more information. +# In passing, also test the --enable-two-phase option and +# --remove option command_ok( [ - 'pg_createsubscriber', '--verbose', - '--recovery-timeout', "$PostgreSQL::Test::Utils::timeout_default", - '--verbose', '--pgdata', - $node_s->data_dir, '--publisher-server', - $node_p->connstr($db1), '--socket-directory', - $node_s->host, '--subscriber-port', - $node_s->port, '--publication', - 'pub1', '--publication', - 'Pub2', '--replication-slot', - 'replslot1', '--replication-slot', - 'replslot2', '--database', - $db1, '--database', - $db2 + 'pg_createsubscriber', + '--verbose', '--verbose', + '--recovery-timeout' => $PostgreSQL::Test::Utils::timeout_default, + '--pgdata' => $node_s->data_dir, + '--publisher-server' => $node_p->connstr($db1), + '--socketdir' => $node_s->host, + '--subscriber-port' => $node_s->port, + '--publication' => 'pub1', + '--publication' => 'pub2', + '--replication-slot' => 'replslot1', + '--replication-slot' => 'replslot2', + '--database' => $db1, + '--database' => $db2, + '--enable-two-phase', + '--remove' => 'publications', ], 'run pg_createsubscriber on node S'); @@ -390,6 +482,19 @@ sub generate_db # Start subscriber $node_s->start; +# Confirm publications are removed from the subscriber node +is($node_s->safe_psql($db1, "SELECT COUNT(*) FROM pg_publication;"), + '0', 'all publications on subscriber have been removed'); + +# Verify that all subtwophase states are pending or enabled, +# e.g. there are no subscriptions where subtwophase is disabled ('d') +is( $node_s->safe_psql( + 'postgres', + "SELECT count(1) = 0 FROM pg_subscription WHERE subtwophasestate = 'd'" + ), + 't', + 'subscriptions are created with the two-phase option enabled'); + # Confirm the pre-existing subscription has been removed $result = $node_s->safe_psql( 'postgres', qq( diff --git a/src/bin/pg_basebackup/walmethods.c b/src/bin/pg_basebackup/walmethods.c index 832aafd29737a..eaaabc5f3745a 100644 --- a/src/bin/pg_basebackup/walmethods.c +++ b/src/bin/pg_basebackup/walmethods.c @@ -2,7 +2,7 @@ * * walmethods.c - implementations of different ways to write received wal * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/walmethods.c @@ -11,6 +11,7 @@ #include "postgres_fe.h" +#include #include #include #include @@ -26,8 +27,7 @@ #include "common/file_utils.h" #include "common/logging.h" #include "pgtar.h" -#include "receivelog.h" -#include "streamutil.h" +#include "walmethods.h" /* Size of zlib buffer for .tar.gz */ #define ZLIB_OUT_SIZE 4096 @@ -691,7 +691,7 @@ static const WalWriteMethodOps WalTarMethodOps = { typedef struct TarMethodFile { Walfile base; - off_t ofs_start; /* Where does the *header* for this file start */ + pgoff_t ofs_start; /* Where does the *header* for this file start */ char header[TAR_BLOCK_SIZE]; size_t pad_to_size; } TarMethodFile; diff --git a/src/bin/pg_basebackup/walmethods.h b/src/bin/pg_basebackup/walmethods.h index c9042600f950c..f7a6dc18439ff 100644 --- a/src/bin/pg_basebackup/walmethods.h +++ b/src/bin/pg_basebackup/walmethods.h @@ -2,7 +2,7 @@ * * walmethods.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_basebackup/walmethods.h @@ -17,7 +17,7 @@ typedef struct WalWriteMethod WalWriteMethod; typedef struct { WalWriteMethod *wwmethod; - off_t currpos; + pgoff_t currpos; char *pathname; /* diff --git a/src/bin/pg_checksums/Makefile b/src/bin/pg_checksums/Makefile index 31de5fb467344..a7f6d9c7c5cc9 100644 --- a/src/bin/pg_checksums/Makefile +++ b/src/bin/pg_checksums/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_checksums # -# Copyright (c) 1998-2024, PostgreSQL Global Development Group +# Copyright (c) 1998-2025, PostgreSQL Global Development Group # # src/bin/pg_checksums/Makefile # diff --git a/src/bin/pg_checksums/meson.build b/src/bin/pg_checksums/meson.build index e5153a47a97ce..52b5cafa441fd 100644 --- a/src/bin/pg_checksums/meson.build +++ b/src/bin/pg_checksums/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_checksums_sources = files( 'pg_checksums.c', diff --git a/src/bin/pg_checksums/pg_checksums.c b/src/bin/pg_checksums/pg_checksums.c index b5bb0e78875ae..f20be82862a2b 100644 --- a/src/bin/pg_checksums/pg_checksums.c +++ b/src/bin/pg_checksums/pg_checksums.c @@ -4,7 +4,7 @@ * Checks, enables or disables page level checksums for an offline * cluster * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_checksums/pg_checksums.c @@ -16,12 +16,11 @@ #include #include -#include #include +#include #include #include "common/controldata_utils.h" -#include "common/file_perm.h" #include "common/file_utils.h" #include "common/logging.h" #include "common/relpath.h" @@ -142,9 +141,9 @@ progress_report(bool finished) /* Calculate current percentage of size done */ percent = total_size ? (int) ((current_size) * 100 / total_size) : 0; - fprintf(stderr, _("%lld/%lld MB (%d%%) computed"), - (long long) (current_size / (1024 * 1024)), - (long long) (total_size / (1024 * 1024)), + fprintf(stderr, _("%" PRId64 "/%" PRId64 " MB (%d%%) computed"), + (current_size / (1024 * 1024)), + (total_size / (1024 * 1024)), percent); /* @@ -388,7 +387,7 @@ scan_directory(const char *basedir, const char *subdir, bool sizeonly) * is valid, resolving the linked locations and dive into them * directly. */ - if (strncmp("pg_tblspc", subdir, strlen("pg_tblspc")) == 0) + if (strncmp(PG_TBLSPC_DIR, subdir, strlen(PG_TBLSPC_DIR)) == 0) { char tblspc_path[MAXPGPATH]; struct stat tblspc_st; @@ -593,22 +592,22 @@ main(int argc, char *argv[]) { total_size = scan_directory(DataDir, "global", true); total_size += scan_directory(DataDir, "base", true); - total_size += scan_directory(DataDir, "pg_tblspc", true); + total_size += scan_directory(DataDir, PG_TBLSPC_DIR, true); } (void) scan_directory(DataDir, "global", false); (void) scan_directory(DataDir, "base", false); - (void) scan_directory(DataDir, "pg_tblspc", false); + (void) scan_directory(DataDir, PG_TBLSPC_DIR, false); if (showprogress) progress_report(true); printf(_("Checksum operation completed\n")); - printf(_("Files scanned: %lld\n"), (long long) files_scanned); - printf(_("Blocks scanned: %lld\n"), (long long) blocks_scanned); + printf(_("Files scanned: %" PRId64 "\n"), files_scanned); + printf(_("Blocks scanned: %" PRId64 "\n"), blocks_scanned); if (mode == PG_MODE_CHECK) { - printf(_("Bad checksums: %lld\n"), (long long) badblocks); + printf(_("Bad checksums: %" PRId64 "\n"), badblocks); printf(_("Data checksum version: %u\n"), ControlFile->data_checksum_version); if (badblocks > 0) @@ -616,8 +615,8 @@ main(int argc, char *argv[]) } else if (mode == PG_MODE_ENABLE) { - printf(_("Files written: %lld\n"), (long long) files_written); - printf(_("Blocks written: %lld\n"), (long long) blocks_written); + printf(_("Files written: %" PRId64 "\n"), files_written); + printf(_("Blocks written: %" PRId64 "\n"), blocks_written); } } @@ -634,7 +633,7 @@ main(int argc, char *argv[]) if (do_sync) { pg_log_info("syncing data directory"); - sync_pgdata(DataDir, PG_VERSION_NUM, sync_method); + sync_pgdata(DataDir, PG_VERSION_NUM, sync_method, true); } pg_log_info("updating control file"); diff --git a/src/bin/pg_checksums/po/de.po b/src/bin/pg_checksums/po/de.po index 8b74011f53b17..dc8eab7e76424 100644 --- a/src/bin/pg_checksums/po/de.po +++ b/src/bin/pg_checksums/po/de.po @@ -1,14 +1,14 @@ # German message translation file for pg_checksums # Copyright (C) 2024 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Peter Eisentraut , 2018 - 2024. +# Peter Eisentraut , 2018 - 2025. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 07:54+0000\n" -"PO-Revision-Date: 2024-03-19 21:17+0100\n" +"POT-Creation-Date: 2025-03-02 13:25+0000\n" +"PO-Revision-Date: 2025-03-02 15:48+0100\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,22 +16,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -74,9 +74,9 @@ msgstr "" "diesem Fall wären die Ergebnisse unten falsch und die PostgreSQL-Installation\n" "wäre inkompatibel mit diesem Datenverzeichnis." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 pg_checksums.c:192 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:71 +#: ../../common/file_utils.c:348 ../../common/file_utils.c:407 +#: ../../common/file_utils.c:481 pg_checksums.c:191 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" @@ -86,8 +86,8 @@ msgstr "konnte Datei »%s« nicht öffnen: %m" msgid "could not write file \"%s\": %m" msgstr "konnte Datei »%s« nicht schreiben: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:419 +#: ../../common/file_utils.c:489 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" @@ -103,35 +103,35 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:77 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: pg_checksums.c:338 pg_checksums.c:407 +#: ../../common/file_utils.c:121 ../../common/file_utils.c:567 +#: pg_checksums.c:337 pg_checksums.c:406 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:131 ../../common/file_utils.c:228 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 -#: pg_checksums.c:310 +#: ../../common/file_utils.c:152 ../../common/file_utils.c:282 +#: pg_checksums.c:309 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:170 ../../common/file_utils.c:316 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:499 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -151,7 +151,7 @@ msgstr "%s muss im Bereich %d..%d sein" msgid "unrecognized sync method: %s" msgstr "unbekannte Sync-Methode: %s" -#: pg_checksums.c:70 +#: pg_checksums.c:69 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" @@ -160,17 +160,17 @@ msgstr "" "%s überprüft die Datenprüfsummen in einem PostgreSQL-Datenbankcluster oder schaltet sie ein oder aus.\n" "\n" -#: pg_checksums.c:71 +#: pg_checksums.c:70 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_checksums.c:72 +#: pg_checksums.c:71 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATENVERZEICHNIS]\n" -#: pg_checksums.c:73 +#: pg_checksums.c:72 #, c-format msgid "" "\n" @@ -179,44 +179,44 @@ msgstr "" "\n" "Optionen:\n" -#: pg_checksums.c:74 +#: pg_checksums.c:73 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]VERZ Datenbankverzeichnis\n" -#: pg_checksums.c:75 +#: pg_checksums.c:74 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check Datenprüfsummen prüfen (Voreinstellung)\n" -#: pg_checksums.c:76 +#: pg_checksums.c:75 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable Datenprüfsummen ausschalten\n" -#: pg_checksums.c:77 +#: pg_checksums.c:76 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable Datenprüfsummen einschalten\n" -#: pg_checksums.c:78 +#: pg_checksums.c:77 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=FILENODE nur Relation mit angegebenem Filenode prüfen\n" -#: pg_checksums.c:79 +#: pg_checksums.c:78 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n" " geschrieben sind\n" -#: pg_checksums.c:80 +#: pg_checksums.c:79 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress Fortschrittsinformationen zeigen\n" -#: pg_checksums.c:81 +#: pg_checksums.c:80 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" @@ -224,22 +224,22 @@ msgstr "" " Methode zum Synchronisieren von Dateien auf Festplatte\n" " setzen\n" -#: pg_checksums.c:82 +#: pg_checksums.c:81 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose »Verbose«-Modus\n" -#: pg_checksums.c:83 +#: pg_checksums.c:82 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_checksums.c:84 +#: pg_checksums.c:83 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_checksums.c:85 +#: pg_checksums.c:84 #, c-format msgid "" "\n" @@ -252,177 +252,177 @@ msgstr "" "PGDATA verwendet.\n" "\n" -#: pg_checksums.c:87 +#: pg_checksums.c:86 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Berichten Sie Fehler an <%s>.\n" -#: pg_checksums.c:88 +#: pg_checksums.c:87 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: pg_checksums.c:145 +#: pg_checksums.c:144 #, c-format -msgid "%lld/%lld MB (%d%%) computed" -msgstr "%lld/%lld MB (%d%%) berechnet" +msgid "%/% MB (%d%%) computed" +msgstr "%/% MB (%d%%) berechnet" -#: pg_checksums.c:206 +#: pg_checksums.c:205 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "konnte Block %u in Datei »%s« nicht lesen: %m" -#: pg_checksums.c:209 +#: pg_checksums.c:208 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "konnte Block %u in Datei »%s« nicht lesen: %d von %d gelesen" -#: pg_checksums.c:232 +#: pg_checksums.c:231 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "Prüfsummenprüfung fehlgeschlagen in Datei »%s«, Block %u: berechnete Prüfsumme ist %X, aber der Block enthält %X" -#: pg_checksums.c:255 +#: pg_checksums.c:254 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "seek fehlgeschlagen für Block %u in Datei »%s«: %m" -#: pg_checksums.c:262 +#: pg_checksums.c:261 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "konnte Block %u in Datei »%s« nicht schreiben: %m" -#: pg_checksums.c:265 +#: pg_checksums.c:264 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "konnte Block %u in Datei »%s« nicht schreiben: %d von %d geschrieben" -#: pg_checksums.c:277 +#: pg_checksums.c:276 #, c-format msgid "checksums verified in file \"%s\"" msgstr "Prüfsummen wurden überprüft in Datei »%s«" -#: pg_checksums.c:279 +#: pg_checksums.c:278 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "Prüfsummen wurden eingeschaltet in Datei »%s«" -#: pg_checksums.c:362 +#: pg_checksums.c:361 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "ungültige Segmentnummer %d in Dateiname »%s«" -#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 +#: pg_checksums.c:508 pg_checksums.c:524 pg_checksums.c:534 pg_checksums.c:542 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_checksums.c:524 +#: pg_checksums.c:523 #, c-format msgid "no data directory specified" msgstr "kein Datenverzeichnis angegeben" -#: pg_checksums.c:533 +#: pg_checksums.c:532 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: pg_checksums.c:542 +#: pg_checksums.c:541 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "Option -f/--filenode kann nur mit --check verwendet werden" -#: pg_checksums.c:550 +#: pg_checksums.c:549 #, c-format msgid "pg_control CRC value is incorrect" msgstr "CRC-Wert in pg_control ist falsch" -#: pg_checksums.c:553 +#: pg_checksums.c:552 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "die Cluster sind nicht mit dieser Version von pg_checksums kompatibel" -#: pg_checksums.c:557 +#: pg_checksums.c:556 #, c-format msgid "database cluster is not compatible" msgstr "Datenbank-Cluster ist nicht kompatibel" -#: pg_checksums.c:558 +#: pg_checksums.c:557 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "Der Datenbank-Cluster wurde mit Blockgröße %u initialisiert, aber pg_checksums wurde mit Blockgröße %u kompiliert." -#: pg_checksums.c:570 +#: pg_checksums.c:569 #, c-format msgid "cluster must be shut down" msgstr "Cluster muss heruntergefahren sein" -#: pg_checksums.c:574 +#: pg_checksums.c:573 #, c-format msgid "data checksums are not enabled in cluster" msgstr "Datenprüfsummen sind im Cluster nicht eingeschaltet" -#: pg_checksums.c:578 +#: pg_checksums.c:577 #, c-format msgid "data checksums are already disabled in cluster" msgstr "Datenprüfsummen sind im Cluster bereits ausgeschaltet" -#: pg_checksums.c:582 +#: pg_checksums.c:581 #, c-format msgid "data checksums are already enabled in cluster" msgstr "Datenprüfsummen sind im Cluster bereits eingeschaltet" -#: pg_checksums.c:606 +#: pg_checksums.c:605 #, c-format msgid "Checksum operation completed\n" msgstr "Prüfsummenoperation abgeschlossen\n" -#: pg_checksums.c:607 +#: pg_checksums.c:606 #, c-format -msgid "Files scanned: %lld\n" -msgstr "Überprüfte Dateien: %lld\n" +msgid "Files scanned: %\n" +msgstr "Überprüfte Dateien: %\n" -#: pg_checksums.c:608 +#: pg_checksums.c:607 #, c-format -msgid "Blocks scanned: %lld\n" -msgstr "Überprüfte Blöcke: %lld\n" +msgid "Blocks scanned: %\n" +msgstr "Überprüfte Blöcke: %\n" -#: pg_checksums.c:611 +#: pg_checksums.c:610 #, c-format -msgid "Bad checksums: %lld\n" -msgstr "Falsche Prüfsummen: %lld\n" +msgid "Bad checksums: %\n" +msgstr "Falsche Prüfsummen: %\n" -#: pg_checksums.c:612 pg_checksums.c:644 +#: pg_checksums.c:611 pg_checksums.c:643 #, c-format msgid "Data checksum version: %u\n" msgstr "Datenprüfsummenversion: %u\n" -#: pg_checksums.c:619 +#: pg_checksums.c:618 #, c-format -msgid "Files written: %lld\n" -msgstr "Geschriebene Dateien: %lld\n" +msgid "Files written: %\n" +msgstr "Geschriebene Dateien: %\n" -#: pg_checksums.c:620 +#: pg_checksums.c:619 #, c-format -msgid "Blocks written: %lld\n" -msgstr "Geschriebene Blöcke: %lld\n" +msgid "Blocks written: %\n" +msgstr "Geschriebene Blöcke: %\n" -#: pg_checksums.c:636 +#: pg_checksums.c:635 #, c-format msgid "syncing data directory" msgstr "synchronisiere Datenverzeichnis" -#: pg_checksums.c:640 +#: pg_checksums.c:639 #, c-format msgid "updating control file" msgstr "aktualisiere Kontrolldatei" -#: pg_checksums.c:646 +#: pg_checksums.c:645 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Prüfsummen wurden im Cluster eingeschaltet\n" -#: pg_checksums.c:648 +#: pg_checksums.c:647 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Prüfsummen wurden im Cluster ausgeschaltet\n" diff --git a/src/bin/pg_checksums/po/es.po b/src/bin/pg_checksums/po/es.po index 475406d903720..4a45c85987bbe 100644 --- a/src/bin/pg_checksums/po/es.po +++ b/src/bin/pg_checksums/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_checksums (PostgreSQL) 16\n" +"Project-Id-Version: pg_checksums (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:23+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:53+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: pgsql-es-ayuda \n" "Language: es\n" @@ -40,6 +40,106 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "no se pudo cerrar el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"posible discordancia en orden de bytes\n" +"El ordenamiento de bytes usado para almacenar el archivo pg_control puede no\n" +"coincidir con el usado por este programa. En tal caso los resultados de abajo\n" +"serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" +"directorio de datos." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "no se pudo escribir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -50,26 +150,32 @@ msgstr "el valor «%s» no es válido para la opción %s" msgid "%s must be in range %d..%d" msgstr "%s debe estar en el rango %d..%d" -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" + +#: pg_checksums.c:70 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" "\n" msgstr "" -"%s activa, desactiva o verifica checksums de datos en un clúster PostgreSQL.\n" +"%s activa, desactiva o verifica checksums de datos en un\n" +"clúster PostgreSQL.\n" "\n" -#: pg_checksums.c:80 +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPCIÓN]... [DATADIR]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format msgid "" "\n" @@ -78,57 +184,62 @@ msgstr "" "\n" "Opciones:\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR directorio de datos\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check verificar checksums (por omisión)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable desactivar checksums\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable activar checksums\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=FILENODE verificar sólo la relación con el filenode dado\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress mostrar información de progreso\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método para sincr. archivos a disco\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose desplegar mensajes verbosos\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format msgid "" "\n" @@ -141,192 +252,177 @@ msgstr "" "la variable de entorno PGDATA.\n" "\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Reporte errores a <%s>.\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld MB (%d%%) calculado" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "no se pudo leer el bloque %u del archivo «%s»: %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "no se pudo leer bloque %u en archivo «%s»: leídos %d de %d" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "verificación de checksums falló en archivo «%s», bloque %u: checksum calculado %X pero bloque contiene %X" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "posicionamiento (seek) falló para el bloque %u en archivo «%s»: %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "no se pudo escribir el bloque %u en el archivo «%s»: %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "no se pudo escribir el bloque %u en el archivo «%s»: se escribieron %d de %d" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "checksums verificados en archivo «%s»" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "checksums activados en archivo «%s»" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "no se pudo abrir el directorio «%s»: %m" - -#: pg_checksums.c:342 pg_checksums.c:411 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "no se pudo hacer stat al archivo «%s»: %m" - -#: pg_checksums.c:366 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "número de segmento %d no válido en nombre de archivo «%s»" -#: pg_checksums.c:508 pg_checksums.c:524 pg_checksums.c:534 pg_checksums.c:542 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_checksums.c:523 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "no se especificó el directorio de datos" -#: pg_checksums.c:532 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_checksums.c:541 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "la opción -f/--filenode sólo puede usarse con --check" -#: pg_checksums.c:549 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "el valor de CRC de pg_control es incorrecto" -#: pg_checksums.c:552 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "el clúster no es compatible con esta versión de pg_checksums" -#: pg_checksums.c:556 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "el clúster de bases de datos no es compatible" -#: pg_checksums.c:557 +#: pg_checksums.c:558 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "El clúster fue inicializado con tamaño de bloque %u, pero pg_checksums fue compilado con tamaño de bloques %u." -#: pg_checksums.c:569 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "el clúster debe estar apagado" -#: pg_checksums.c:573 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "los checksums de datos no están activados en el clúster" -#: pg_checksums.c:577 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "los checksums de datos ya están desactivados en el clúster" -#: pg_checksums.c:581 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "los checksums de datos ya están activados en el clúster" -#: pg_checksums.c:605 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "Operación de checksums completa\n" -#: pg_checksums.c:606 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "Archivos recorridos: %lld\n" -#: pg_checksums.c:607 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "Bloques recorridos: %lld\n" -#: pg_checksums.c:610 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "Checksums incorrectos: %lld\n" -#: pg_checksums.c:611 pg_checksums.c:643 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "Versión de checksums de datos: %u\n" -#: pg_checksums.c:618 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "Archivos escritos: %lld\n" -#: pg_checksums.c:619 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "Bloques escritos: %lld\n" -#: pg_checksums.c:635 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "sincronizando directorio de datos" -#: pg_checksums.c:639 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "actualizando archivo de control" -#: pg_checksums.c:645 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Checksums activos en el clúster\n" -#: pg_checksums.c:647 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Checksums inactivos en el clúster\n" diff --git a/src/bin/pg_checksums/po/fr.po b/src/bin/pg_checksums/po/fr.po index dcdb4c74f1512..dcd82587d4ff4 100644 --- a/src/bin/pg_checksums/po/fr.po +++ b/src/bin/pg_checksums/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-14 10:21+0000\n" -"PO-Revision-Date: 2022-05-14 17:15+0200\n" +"POT-Creation-Date: 2024-07-20 21:25+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,28 +19,128 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "erreur : " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "attention : " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "détail : " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "astuce : " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"possible incohérence dans l'ordre des octets\n" +"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n" +"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n" +"résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" +"est incompatible avec ce répertoire des données." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "impossible d'écrire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -51,7 +151,12 @@ msgstr "valeur « %s » invalide pour l'option %s" msgid "%s must be in range %d..%d" msgstr "%s doit être compris entre %d et %d" -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: pg_checksums.c:70 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" @@ -61,17 +166,17 @@ msgstr "" "une instance PostgreSQL.\n" "\n" -#: pg_checksums.c:80 +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [RÉP_DONNÉES]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format msgid "" "\n" @@ -80,61 +185,66 @@ msgstr "" "\n" "Options :\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]REP_DONNEES répertoire des données\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check vérifie les sommes de contrôle (par défaut)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable désactive les sommes de contrôle\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable active les sommes de contrôle\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr "" " -f, --filenode=FILENODE vérifie seulement la relation dont l'identifiant\n" " relfilenode est indiqué\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync n'attend pas que les modifications soient\n" " proprement écrites sur disque\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress affiche la progression de l'opération\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose affiche des messages verbeux\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format msgid "" "\n" @@ -147,228 +257,177 @@ msgstr "" "PGDATA est utilisée.\n" "\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapporter les bogues à <%s>.\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld Mo (%d%%) traités" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "n'a pas pu lire le bloc %u dans le fichier « %s » : %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "n'a pas pu lire le bloc %u dans le fichier « %s » : %d lus sur %d" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "échec de la vérification de la somme de contrôle dans le fichier « %s », bloc %u : somme de contrôle calculée %X, alors que le bloc contient %X" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "n'a pas pu rechercher le bloc %u dans le fichier « %s » : %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "n'a pas pu écrire le bloc %u dans le fichier « %s » : %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "n'a pas pu écrire le bloc %u du fichier « %s » : a écrit %d octets sur %d" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "sommes de contrôle vérifiées dans le fichier « %s »" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "sommes de contrôle activées dans le fichier « %s »" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" - -#: pg_checksums.c:342 pg_checksums.c:415 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "n'a pas pu tester le fichier « %s » : %m" - -#: pg_checksums.c:366 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "numéro de segment %d invalide dans le nom de fichier « %s »" -#: pg_checksums.c:512 pg_checksums.c:528 pg_checksums.c:538 pg_checksums.c:546 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_checksums.c:527 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "aucun répertoire de données indiqué" -#: pg_checksums.c:536 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_checksums.c:545 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "l'option « -f/--filenode » peut seulement être utilisée avec --check" -#: pg_checksums.c:553 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "la valeur CRC de pg_control n'est pas correcte" -#: pg_checksums.c:556 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "l'instance n'est pas compatible avec cette version de pg_checksums" -#: pg_checksums.c:560 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "l'instance n'est pas compatible" -#: pg_checksums.c:561 +#: pg_checksums.c:558 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "L'instance a été initialisée avec une taille de bloc à %u alors que pg_checksums a été compilé avec une taille de bloc à %u." -#: pg_checksums.c:573 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "l'instance doit être arrêtée" -#: pg_checksums.c:577 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "les sommes de contrôle sur les données ne sont pas activées sur cette instance" -#: pg_checksums.c:581 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "les sommes de contrôle sur les données sont déjà désactivées sur cette instance" -#: pg_checksums.c:585 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "les sommes de contrôle sur les données sont déjà activées sur cette instance" -#: pg_checksums.c:609 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "Opération sur les sommes de contrôle terminée\n" -#: pg_checksums.c:610 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "Fichiers parcourus : %lld\n" -#: pg_checksums.c:611 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "Blocs parcourus : %lld\n" -#: pg_checksums.c:614 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "Mauvaises sommes de contrôle : %lld\n" -#: pg_checksums.c:615 pg_checksums.c:647 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "Version des sommes de contrôle sur les données : %u\n" -#: pg_checksums.c:622 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "Fichiers écrits : %lld\n" -#: pg_checksums.c:623 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "Blocs écrits : %lld\n" -#: pg_checksums.c:639 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "synchronisation du répertoire des données" -#: pg_checksums.c:643 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "mise à jour du fichier de contrôle" -#: pg_checksums.c:649 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Sommes de contrôle sur les données activées sur cette instance\n" -#: pg_checksums.c:651 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Sommes de contrôle sur les données désactivées sur cette instance\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide puis quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version puis quitte\n" - -#~ msgid "%s: could not open directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#~ msgid "%s: could not open file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n" - -#~ msgid "%s: could not stat file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu récupérer les informations sur le fichier « %s » : %s\n" - -#~ msgid "%s: no data directory specified\n" -#~ msgstr "%s : aucun répertoire de données indiqué\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#, c-format -#~ msgid "invalid filenode specification, must be numeric: %s" -#~ msgstr "spécification invalide du relfilnode, doit être numérique : %s" diff --git a/src/bin/pg_checksums/po/ja.po b/src/bin/pg_checksums/po/ja.po index f4d3da0256ed6..9241f4704a66a 100644 --- a/src/bin/pg_checksums/po/ja.po +++ b/src/bin/pg_checksums/po/ja.po @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_checksums (PostgreSQL 17)\n" +"Project-Id-Version: pg_checksums (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 09:23+0900\n" -"PO-Revision-Date: 2023-09-07 10:23+0900\n" +"POT-Creation-Date: 2025-03-03 16:14+0900\n" +"PO-Revision-Date: 2025-03-31 16:24+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -17,26 +17,125 @@ msgstr "" "X-Generator: Poedit 1.8.13\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ファイル\"%s\"を読み込み用にオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ファイル\"%s\"の読み込みに失敗しました: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ファイル\"%s\"をクローズできませんでした: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "バイトオーダが合っていません" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"バイトオーダが異なる可能性があります。\n" +"pg_controlファイルを格納するために使用するバイトオーダが本プログラムで使用\n" +"されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" +"PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:71 +#: ../../common/file_utils.c:348 ../../common/file_utils.c:407 +#: ../../common/file_utils.c:481 pg_checksums.c:191 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ファイル\"%s\"をオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ファイル\"%s\"を書き出せませんでした: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:419 +#: ../../common/file_utils.c:489 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ファイル\"%s\"をfsyncできませんでした: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "メモリ不足です\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nullポインタは複製できません(内部エラー)\n" + +#: ../../common/file_utils.c:77 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" + +#: ../../common/file_utils.c:121 ../../common/file_utils.c:567 +#: pg_checksums.c:337 pg_checksums.c:406 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ファイル\"%s\"のstatに失敗しました: %m" + +#: ../../common/file_utils.c:131 ../../common/file_utils.c:228 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "このビルドでは同期方式\"%s\"をサポートしていません" + +#: ../../common/file_utils.c:152 ../../common/file_utils.c:282 +#: pg_checksums.c:309 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" + +#: ../../common/file_utils.c:170 ../../common/file_utils.c:316 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" + +#: ../../common/file_utils.c:499 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -47,17 +146,12 @@ msgstr "オプション%sの不正な値\"%s\"" msgid "%s must be in range %d..%d" msgstr "%sは%d..%dの範囲でなければなりません" -#: ../../fe_utils/option_utils.c:99 -#, c-format -msgid "this build does not support sync method \"%s\"" -msgstr "このビルドでは同期方式\"%s\"をサポートしていません" - #: ../../fe_utils/option_utils.c:106 #, c-format msgid "unrecognized sync method: %s" msgstr "認識できない同期方式: %s" -#: pg_checksums.c:70 +#: pg_checksums.c:69 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" @@ -66,17 +160,17 @@ msgstr "" "%sはPostgreSQLデータベースクラスタにおけるデータチェックサムの有効化、無効化および検証を行います。\n" "\n" -#: pg_checksums.c:71 +#: pg_checksums.c:70 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_checksums.c:72 +#: pg_checksums.c:71 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATADIR]\n" -#: pg_checksums.c:73 +#: pg_checksums.c:72 #, c-format msgid "" "\n" @@ -85,62 +179,62 @@ msgstr "" "\n" "オプション:\n" -#: pg_checksums.c:74 +#: pg_checksums.c:73 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR データディレクトリ\n" -#: pg_checksums.c:75 +#: pg_checksums.c:74 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check データチェックサムを検証(デフォルト)\n" -#: pg_checksums.c:76 +#: pg_checksums.c:75 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable データチェックサムを無効化\n" -#: pg_checksums.c:77 +#: pg_checksums.c:76 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable データチェックサムを有効化\n" -#: pg_checksums.c:78 +#: pg_checksums.c:77 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=FILENODE 指定したファイルノードのリレーションのみ検証\n" -#: pg_checksums.c:79 +#: pg_checksums.c:78 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync ディスクへの安全な書き込みを待機しない\n" -#: pg_checksums.c:80 +#: pg_checksums.c:79 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress 進行状況を表示\n" -#: pg_checksums.c:81 +#: pg_checksums.c:80 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=METHOD ファイルをディスクに同期させる方法を指定\n" -#: pg_checksums.c:82 +#: pg_checksums.c:81 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose 冗長メッセージを出力\n" -#: pg_checksums.c:83 +#: pg_checksums.c:82 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_checksums.c:84 +#: pg_checksums.c:83 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_checksums.c:85 +#: pg_checksums.c:84 #, c-format msgid "" "\n" @@ -152,192 +246,177 @@ msgstr "" "データディレクトリ(DATADIR)が指定されない場合、PGDATA環境変数が使用されます。\n" "\n" -#: pg_checksums.c:87 +#: pg_checksums.c:86 #, c-format msgid "Report bugs to <%s>.\n" msgstr "バグは<%s>に報告してください。\n" -#: pg_checksums.c:88 +#: pg_checksums.c:87 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: pg_checksums.c:145 -#, c-format -msgid "%lld/%lld MB (%d%%) computed" -msgstr "%lld/%lld MB (%d%%) 完了" - -#: pg_checksums.c:192 +#: pg_checksums.c:144 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "ファイル\"%s\"をオープンできませんでした: %m" +msgid "%/% MB (%d%%) computed" +msgstr "%/% MB (%d%%) 完了" -#: pg_checksums.c:206 +#: pg_checksums.c:205 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "ファイル\"%2$s\"で%1$uブロックを読み取れませんでした: %3$m" -#: pg_checksums.c:209 +#: pg_checksums.c:208 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr " ファイル\"%2$s\"のブロック%1$uが読み込めませんでした: %4$d中%3$d読み込み済み" -#: pg_checksums.c:232 +#: pg_checksums.c:231 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "ファイル\"%s\" ブロック%uでチェックサム検証が失敗: 算出したチェックサムは%X 、しかしブロック上の値は%X" -#: pg_checksums.c:255 +#: pg_checksums.c:254 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "ファイル\"%2$s\" ブロック%1$uへのシーク失敗: %3$m" -#: pg_checksums.c:262 +#: pg_checksums.c:261 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "ファイル\"%2$s\"で%1$uブロックが書き出せませんでした: %3$m" -#: pg_checksums.c:265 +#: pg_checksums.c:264 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "ファイル\"%2$s\"のブロック%1$uの書き込みに失敗しました: %4$dバイト中%3$dバイトのみ書き込みました" -#: pg_checksums.c:277 +#: pg_checksums.c:276 #, c-format msgid "checksums verified in file \"%s\"" msgstr "ファイル\"%s\"のチェックサムは検証されました" -#: pg_checksums.c:279 +#: pg_checksums.c:278 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "ファイル\"%s\"のチェックサムは有効化されました" -#: pg_checksums.c:310 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" - -#: pg_checksums.c:334 pg_checksums.c:403 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "ファイル\"%s\"のstatに失敗しました: %m" - -#: pg_checksums.c:358 +#: pg_checksums.c:361 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "ファイル名\"%2$s\"の不正なセグメント番号%1$d" -#: pg_checksums.c:505 pg_checksums.c:521 pg_checksums.c:531 pg_checksums.c:539 +#: pg_checksums.c:508 pg_checksums.c:524 pg_checksums.c:534 pg_checksums.c:542 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細については\"%s --help\"を実行してください。" -#: pg_checksums.c:520 +#: pg_checksums.c:523 #, c-format msgid "no data directory specified" msgstr "データディレクトリが指定されていません" -#: pg_checksums.c:529 +#: pg_checksums.c:532 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます (最初は\"%s\")" -#: pg_checksums.c:538 +#: pg_checksums.c:541 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "オプション-f/--filenodeは--checkを指定したときのみ指定可能" -#: pg_checksums.c:546 +#: pg_checksums.c:549 #, c-format msgid "pg_control CRC value is incorrect" msgstr "pg_controlのCRC値が正しくありません" -#: pg_checksums.c:549 +#: pg_checksums.c:552 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "クラスタはこのバージョンのpg_checksumsと互換性がありません" -#: pg_checksums.c:553 +#: pg_checksums.c:556 #, c-format msgid "database cluster is not compatible" msgstr "データベースクラスタが非互換です" -#: pg_checksums.c:554 +#: pg_checksums.c:557 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "データベースクラスタはブロックサイズ%uで初期化されています、しかしpg_checksumsはブロックサイズ%uでコンパイルされています。" -#: pg_checksums.c:566 +#: pg_checksums.c:569 #, c-format msgid "cluster must be shut down" msgstr "クラスタはシャットダウンされていなければなりません" -#: pg_checksums.c:570 +#: pg_checksums.c:573 #, c-format msgid "data checksums are not enabled in cluster" msgstr "クラスタのデータチェックサムは有効になっていません" -#: pg_checksums.c:574 +#: pg_checksums.c:577 #, c-format msgid "data checksums are already disabled in cluster" msgstr "クラスタのデータチェックサムはすでに無効になっています" -#: pg_checksums.c:578 +#: pg_checksums.c:581 #, c-format msgid "data checksums are already enabled in cluster" msgstr "クラスタのデータチェックサムはすでに有効になっています" -#: pg_checksums.c:602 +#: pg_checksums.c:605 #, c-format msgid "Checksum operation completed\n" msgstr "チェックサム操作が完了しました\n" -#: pg_checksums.c:603 +#: pg_checksums.c:606 #, c-format -msgid "Files scanned: %lld\n" -msgstr "スキャンしたファイル数: %lld\n" +msgid "Files scanned: %\n" +msgstr "スキャンしたファイル数: %\n" -#: pg_checksums.c:604 +#: pg_checksums.c:607 #, c-format -msgid "Blocks scanned: %lld\n" -msgstr "スキャンしたブロック数: %lld\n" +msgid "Blocks scanned: %\n" +msgstr "スキャンしたブロック数: %\n" -#: pg_checksums.c:607 +#: pg_checksums.c:610 #, c-format -msgid "Bad checksums: %lld\n" -msgstr "不正なチェックサム数: %lld\n" +msgid "Bad checksums: %\n" +msgstr "不正なチェックサム数: %\n" -#: pg_checksums.c:608 pg_checksums.c:640 +#: pg_checksums.c:611 pg_checksums.c:643 #, c-format msgid "Data checksum version: %u\n" msgstr "データチェックサムバージョン: %u\n" -#: pg_checksums.c:615 +#: pg_checksums.c:618 #, c-format -msgid "Files written: %lld\n" -msgstr "スキャンしたファイル数: %lld\n" +msgid "Files written: %\n" +msgstr "スキャンしたファイル数: %\n" -#: pg_checksums.c:616 +#: pg_checksums.c:619 #, c-format -msgid "Blocks written: %lld\n" -msgstr "スキャンしたブロック数: %lld\n" +msgid "Blocks written: %\n" +msgstr "スキャンしたブロック数: %\n" -#: pg_checksums.c:632 +#: pg_checksums.c:635 #, c-format msgid "syncing data directory" msgstr "データディレクトリを同期しています" -#: pg_checksums.c:636 +#: pg_checksums.c:639 #, c-format msgid "updating control file" msgstr "コントロールファイルを更新しています" -#: pg_checksums.c:642 +#: pg_checksums.c:645 #, c-format msgid "Checksums enabled in cluster\n" msgstr "クラスタのチェックサムが有効化されました\n" -#: pg_checksums.c:644 +#: pg_checksums.c:647 #, c-format msgid "Checksums disabled in cluster\n" msgstr "クラスタのチェックサムが無効化されました\n" diff --git a/src/bin/pg_checksums/po/ka.po b/src/bin/pg_checksums/po/ka.po index 71e6f8a8c8cf4..ac8f90bc7cfae 100644 --- a/src/bin/pg_checksums/po/ka.po +++ b/src/bin/pg_checksums/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_checksums (PostgreSQL) 17\n" +"Project-Id-Version: pg_checksums (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-11 09:53+0000\n" -"PO-Revision-Date: 2024-02-11 14:43+0100\n" +"POT-Creation-Date: 2025-03-02 16:24+0000\n" +"PO-Revision-Date: 2025-03-02 18:36+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,28 +16,126 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ფაილის (%s) დახურვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "ბაიტების მიმდევრობა არ ემთხვევა" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"ბაიტების მიმდევრობის შესაძლო შეუსაბამობა pg_control ფაილის შესანახად გამოყენებული \n" +"ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" +"მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:71 +#: ../../common/file_utils.c:348 ../../common/file_utils.c:407 +#: ../../common/file_utils.c:481 pg_checksums.c:191 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:419 +#: ../../common/file_utils.c:489 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + +#: ../../common/file_utils.c:77 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" + +#: ../../common/file_utils.c:121 ../../common/file_utils.c:567 +#: pg_checksums.c:337 pg_checksums.c:406 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: ../../common/file_utils.c:131 ../../common/file_utils.c:228 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" + +#: ../../common/file_utils.c:152 ../../common/file_utils.c:282 +#: pg_checksums.c:309 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:170 ../../common/file_utils.c:316 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/file_utils.c:499 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "გადარქმევის შეცდომა %s - %s: %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -48,17 +146,12 @@ msgstr "არასწორი მნიშვნელობა \"%s\" პა msgid "%s must be in range %d..%d" msgstr "%s არაა საზღვრებში %d-დან %d-მდე" -#: ../../fe_utils/option_utils.c:99 -#, c-format -msgid "this build does not support sync method \"%s\"" -msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" - #: ../../fe_utils/option_utils.c:106 #, c-format msgid "unrecognized sync method: %s" msgstr "უცნობი სინქრონიზაციის მეთოდი: %s" -#: pg_checksums.c:70 +#: pg_checksums.c:69 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" @@ -67,17 +160,17 @@ msgstr "" "%s ჩართავს, გამორთავს და შეამოწმებს მონაცემების საკონტროლო ჯამებს PostgreSQL მონაცემთა ბაზის კლასტერში.\n" "\n" -#: pg_checksums.c:71 +#: pg_checksums.c:70 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_checksums.c:72 +#: pg_checksums.c:71 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [პარამეტრი]... [მონაცემებისსაქაღალდე]\n" -#: pg_checksums.c:73 +#: pg_checksums.c:72 #, c-format msgid "" "\n" @@ -86,62 +179,62 @@ msgstr "" "\n" "პარამეტრები:\n" -#: pg_checksums.c:74 +#: pg_checksums.c:73 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR მონაცემების საქაღალდე\n" -#: pg_checksums.c:75 +#: pg_checksums.c:74 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check მონაცემების საკნტროლო ჯამის შემოწმება(ნაგულისხმები)\n" -#: pg_checksums.c:76 +#: pg_checksums.c:75 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable მონაცემების საკონტროლო ჯამების გამორთვა\n" -#: pg_checksums.c:77 +#: pg_checksums.c:76 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable მონაცემების საკონტროლო ჯამების ჩართვა\n" -#: pg_checksums.c:78 +#: pg_checksums.c:77 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=ფაილისკვანძი მხოლოდ მითითებულ ფაილის კვანძთან ურთიერთობის შემოწმება\n" -#: pg_checksums.c:79 +#: pg_checksums.c:78 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: pg_checksums.c:80 +#: pg_checksums.c:79 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress მიმდინარეობის ინფორმაციის ჩვენება\n" -#: pg_checksums.c:81 +#: pg_checksums.c:80 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=მეთოდი ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: pg_checksums.c:82 +#: pg_checksums.c:81 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: pg_checksums.c:83 +#: pg_checksums.c:82 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_checksums.c:84 +#: pg_checksums.c:83 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_checksums.c:85 +#: pg_checksums.c:84 #, c-format msgid "" "\n" @@ -153,192 +246,179 @@ msgstr "" "თუ მონაცემების საქაღალდე მითითებული არაა, გამოყენებული იქნება \n" "გარემოს ცვლადი PGDATA.\n" -#: pg_checksums.c:87 +#: pg_checksums.c:86 #, c-format msgid "Report bugs to <%s>.\n" msgstr "შეცდომების შესახებ მიწერეთ: <%s>\n" -#: pg_checksums.c:88 +#: pg_checksums.c:87 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: pg_checksums.c:145 -#, c-format -msgid "%lld/%lld MB (%d%%) computed" -msgstr "%lld/%lld მბ (%d%%) გამოთვლილია" - -#: pg_checksums.c:192 +#: pg_checksums.c:144 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" +#| msgid "%lld/%lld MB (%d%%) computed" +msgid "%/% MB (%d%%) computed" +msgstr "%/% მბ (%d%%) გამოთვლილია" -#: pg_checksums.c:206 +#: pg_checksums.c:205 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "ბლოკის %u წაკითხვის შეცდომა ფაილში \"%s\": %m" -#: pg_checksums.c:209 +#: pg_checksums.c:208 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "ბლოკის %u წაკითხვის შეცდომა ფაილში \"%s\": წაკითხულია %d %d-დან" -#: pg_checksums.c:232 +#: pg_checksums.c:231 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "საკონტროლო ჯამის გამოთვლის შეცდომა ფაილში \"%s\", ბლოკი \"%u\": გამოთვლილი საკონტროლო კამია %X, მაგრამ ბლოკი შეიცავს: %X" -#: pg_checksums.c:255 +#: pg_checksums.c:254 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "გადახვევის შეცდომა ბლოკისთვის %u ფაილში \"%s\": %m" -#: pg_checksums.c:262 +#: pg_checksums.c:261 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "ბლოკის %u ჩაწერის შეცდომა ფაილში \"%s\": %m" -#: pg_checksums.c:265 +#: pg_checksums.c:264 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "ბლოკის %u ჩაწერის შეცდომა ფაილში \"%s\": ჩაწერილია %d %d-დან" -#: pg_checksums.c:277 +#: pg_checksums.c:276 #, c-format msgid "checksums verified in file \"%s\"" msgstr "ფაილის საკონტროლო ჯამები შემოწმებულია ფაილში: \"%s\"" -#: pg_checksums.c:279 +#: pg_checksums.c:278 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "ფაილის საკონტროლო ჯამები ჩართულია ფაილიდან: \"%s\"" -#: pg_checksums.c:310 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" - -#: pg_checksums.c:334 pg_checksums.c:403 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "ფაილი \"%s\" არ არსებობს: %m" - -#: pg_checksums.c:358 +#: pg_checksums.c:361 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "სეგმენტის არასწორი ნომერი %d ფაილის სახელში \"%s\"" -#: pg_checksums.c:505 pg_checksums.c:521 pg_checksums.c:531 pg_checksums.c:539 +#: pg_checksums.c:508 pg_checksums.c:524 pg_checksums.c:534 pg_checksums.c:542 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_checksums.c:520 +#: pg_checksums.c:523 #, c-format msgid "no data directory specified" msgstr "მონაცემების საქაღალდე მითითებული არაა" -#: pg_checksums.c:529 +#: pg_checksums.c:532 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_checksums.c:538 +#: pg_checksums.c:541 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "პარამეტრი -f/--filenode მხოლოდ --check -თან ერთად შეიძლება იქნას გამოყენებული" -#: pg_checksums.c:546 +#: pg_checksums.c:549 #, c-format msgid "pg_control CRC value is incorrect" msgstr "pg_control CRC მნიშვნელობა არასწორია" -#: pg_checksums.c:549 +#: pg_checksums.c:552 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "კლასტერი შეუთავსებელია pg_checksums-ის ამ ვერსიასთან" -#: pg_checksums.c:553 +#: pg_checksums.c:556 #, c-format msgid "database cluster is not compatible" msgstr "ბაზის კლასტერი შეუთავსებელია" -#: pg_checksums.c:554 +#: pg_checksums.c:557 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "ბაზის კლასტერის ინიციალიზაცია მოხდა ბლოკის ზომით %u მაშინ, როცა pg_checksums აგებულია ბლოკის ზომით: %u." -#: pg_checksums.c:566 +#: pg_checksums.c:569 #, c-format msgid "cluster must be shut down" msgstr "კლასტერი უნდა გამოირთოს" -#: pg_checksums.c:570 +#: pg_checksums.c:573 #, c-format msgid "data checksums are not enabled in cluster" msgstr "კლასტერში მონაცემების საკონტროლო ჯამები ჩართული არაა" -#: pg_checksums.c:574 +#: pg_checksums.c:577 #, c-format msgid "data checksums are already disabled in cluster" msgstr "კლასტერში მონაცემების საკონტროლო ჯამები უკვე გამორთულია" -#: pg_checksums.c:578 +#: pg_checksums.c:581 #, c-format msgid "data checksums are already enabled in cluster" msgstr "კლასტერში მონაცემების საკონტროლო ჯამები უკვე ჩართულია" -#: pg_checksums.c:602 +#: pg_checksums.c:605 #, c-format msgid "Checksum operation completed\n" msgstr "საკონტროლო ჯამების ოპერაცია დასრულდა\n" -#: pg_checksums.c:603 +#: pg_checksums.c:606 #, c-format -msgid "Files scanned: %lld\n" -msgstr "დასკანერებულია ფაილები: %lld\n" +#| msgid "Files scanned: %lld\n" +msgid "Files scanned: %\n" +msgstr "დასკანირებულია ფაილები: %\n" -#: pg_checksums.c:604 +#: pg_checksums.c:607 #, c-format -msgid "Blocks scanned: %lld\n" -msgstr "დასკარერებული ბლოკები: %lld\n" +msgid "Blocks scanned: %\n" +msgstr "დასკანირებულია ბლოკები: %\n" -#: pg_checksums.c:607 +#: pg_checksums.c:610 #, c-format -msgid "Bad checksums: %lld\n" -msgstr "ცუდი საკონტროლო ჯამები: %lld\n" +msgid "Bad checksums: %\n" +msgstr "ცუდი საკონტროლო ჯამები: %\n" -#: pg_checksums.c:608 pg_checksums.c:640 +#: pg_checksums.c:611 pg_checksums.c:643 #, c-format msgid "Data checksum version: %u\n" msgstr "მონაცემების საკონტროლო ჯამის ვერსია: %u\n" -#: pg_checksums.c:615 +#: pg_checksums.c:618 #, c-format -msgid "Files written: %lld\n" -msgstr "ჩაწერილი ფაილები: %lld\n" +msgid "Files written: %\n" +msgstr "ჩაწერილი ფაილები: %\n" -#: pg_checksums.c:616 +#: pg_checksums.c:619 #, c-format -msgid "Blocks written: %lld\n" -msgstr "ჩაწერილი ბლოკები: %lld\n" +msgid "Blocks written: %\n" +msgstr "ჩაწერილი ბლოკები: %\n" -#: pg_checksums.c:632 +#: pg_checksums.c:635 #, c-format msgid "syncing data directory" msgstr "მონაცემების საქაღალდის სინქრონიზაცია" -#: pg_checksums.c:636 +#: pg_checksums.c:639 #, c-format msgid "updating control file" msgstr "საკონტროლო ფაილის ატვირთვა" -#: pg_checksums.c:642 +#: pg_checksums.c:645 #, c-format msgid "Checksums enabled in cluster\n" msgstr "კლასტერში მონაცემების საკონტროლო ჯამები ჩართულია\n" -#: pg_checksums.c:644 +#: pg_checksums.c:647 #, c-format msgid "Checksums disabled in cluster\n" msgstr "კლასტერში საკონტროლო ჯამები გამორთულია\n" diff --git a/src/bin/pg_checksums/po/ko.po b/src/bin/pg_checksums/po/ko.po index 3c9a6027c02f6..f8c71ae2ead3a 100644 --- a/src/bin/pg_checksums/po/ko.po +++ b/src/bin/pg_checksums/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_checksums (PostgreSQL) 16\n" +"Project-Id-Version: pg_checksums (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:53+0000\n" -"PO-Revision-Date: 2023-05-30 12:38+0900\n" +"POT-Creation-Date: 2025-01-17 04:54+0000\n" +"PO-Revision-Date: 2025-01-16 15:23+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: PostgreSQL Korea \n" "Language: ko\n" @@ -36,6 +36,107 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "읽기용 \"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %d / %zu 바이트만 읽음" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "\"%s\" 파일을 닫을 수 없음: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 일치하지 않음" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"바이트 순서 일치하지 않는 문제\n" +"바이트 순서 정보는 pg_control 파일을 저장할 때 사용되는데,\n" +"이 파일의 바이트 순서 정보와 이 프로그램에서 사용하는 순서 정보가 다릅니다.\n" +"이럴 경우, 출력 결과가 바르지 않을 수 있고,\n" +"설치된 PostgreSQL 프로그램과 데이터 디렉터리가 호환되지 않을 수 있습니다." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "\"%s\" 파일을 쓸 수 없음: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위해 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -46,7 +147,12 @@ msgstr "\"%s\" 값은 \"%s\" 옵션값으로 유효하지 않음" msgid "%s must be in range %d..%d" msgstr "%s 값은 %d부터 %d까지 지정할 수 있습니다." -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: pg_checksums.c:70 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database " @@ -57,17 +163,17 @@ msgstr "" "비활성화 또는 유효성 검사를 합니다.\n" "\n" -#: pg_checksums.c:80 +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [옵션]... [DATADIR]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format msgid "" "\n" @@ -76,33 +182,33 @@ msgstr "" "\n" "옵션들:\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR 데이터 디렉터리\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check 실 작업 없이, 그냥 검사만 (기본값)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable 자료 페이지 체크섬 비활성화\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable 자료 페이지 체크섬 활성화\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid "" " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=FILENODE 지정한 파일노드만 검사\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " @@ -110,27 +216,32 @@ msgid "" msgstr "" " -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않음\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress 진행 과정 보여줌\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD 파일을 디스크에 동기화 하는 방법 지정\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose 자세한 작업 메시지 보여줌\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format msgid "" "\n" @@ -144,37 +255,32 @@ msgstr "" "사용합니다.\n" "\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "문제점 보고 주소: <%s>\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld MB (%d%%) 계산됨" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "%u 블럭을 \"%s\" 파일에서 읽을 수 없음: %d / %d 바이트만 읽음" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "" "checksum verification failed in file \"%s\", block %u: calculated checksum " @@ -183,82 +289,72 @@ msgstr "" "\"%s\" 파일, %u 블럭의 체크섬 검사 실패: 계산된 체크섬은 %X 값이지만, 블럭에" "는 %X 값이 있음" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "%u 블럭을 \"%s\" 파일에서 찾을 수 없음: %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "%u 블럭을 \"%s\" 파일에 쓸 수 없음: %d / %d 바이트만 씀" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "\"%s\" 파일 체크섬 검사 마침" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "\"%s\" 파일 체크섬 활성화 함" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "\"%s\" 디렉터리 열 수 없음: %m" - -#: pg_checksums.c:342 pg_checksums.c:411 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" - -#: pg_checksums.c:366 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "잘못된 조각 번호 %d, 해당 파일: \"%s\"" -#: pg_checksums.c:508 pg_checksums.c:524 pg_checksums.c:534 pg_checksums.c:542 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: pg_checksums.c:523 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "데이터 디렉터리를 지정하지 않았음" -#: pg_checksums.c:532 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인수를 지정했음 (처음 \"%s\")" -#: pg_checksums.c:541 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "-f/--filenode 옵션은 --check 옵션만 사용할 수 있음" -#: pg_checksums.c:549 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "pg_control CRC 값이 잘못되었음" -#: pg_checksums.c:552 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "해당 클러스터는 이 버전 pg_checksum과 호환되지 않음" -#: pg_checksums.c:556 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "데이터베이스 클러스터는 호환되지 않음" -#: pg_checksums.c:557 +#: pg_checksums.c:558 #, c-format msgid "" "The database cluster was initialized with block size %u, but pg_checksums " @@ -267,77 +363,77 @@ msgstr "" "이 데이터베이스 클러스터는 %u 블록 크기로 초기화 되었지만, pg_checksum은 %u " "블록 크기로 컴파일 되어있습니다." -#: pg_checksums.c:569 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "먼저 서버가 중지되어야 함" -#: pg_checksums.c:573 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "이 클러스터는 자료 체크섬이 비활성화 상태임" -#: pg_checksums.c:577 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "이 클러스터는 이미 자료 체크섬이 비활성화 상태임" -#: pg_checksums.c:581 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "이 클러스터는 이미 자료 체크섬이 활성화 상태임" -#: pg_checksums.c:605 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "체크섬 작업 완료\n" -#: pg_checksums.c:606 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "조사한 파일수: %lld\n" -#: pg_checksums.c:607 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "조사한 블럭수: %lld\n" -#: pg_checksums.c:610 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "잘못된 체크섬: %lld\n" -#: pg_checksums.c:611 pg_checksums.c:643 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "자료 체크섬 버전: %u\n" -#: pg_checksums.c:618 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "기록한 파일수: %lld\n" -#: pg_checksums.c:619 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "기록한 블럭수: %lld\n" -#: pg_checksums.c:635 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "데이터 디렉터리 fsync 중" -#: pg_checksums.c:639 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "컨트롤 파일 바꾸는 중" -#: pg_checksums.c:645 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "이 클러스터는 자료 체크섬 옵션이 활성화 되었음\n" -#: pg_checksums.c:647 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "이 클러스터는 자료 체크섬 옵션이 비활성화 되었음\n" diff --git a/src/bin/pg_checksums/po/meson.build b/src/bin/pg_checksums/po/meson.build index b91cef0828f6f..f654700f91ee8 100644 --- a/src/bin/pg_checksums/po/meson.build +++ b/src/bin/pg_checksums/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_checksums-' + pg_version_major.to_string())] diff --git a/src/bin/pg_checksums/po/ru.po b/src/bin/pg_checksums/po/ru.po index ebe4636657321..30f9791b0460a 100644 --- a/src/bin/pg_checksums/po/ru.po +++ b/src/bin/pg_checksums/po/ru.po @@ -1,10 +1,10 @@ -# Alexander Lakhin , 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2019, 2020, 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pg_verify_checksums (PostgreSQL) 11\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2022-09-05 13:34+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 13:35+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -32,6 +32,106 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "не удалось закрыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"возможно несоответствие порядка байт\n" +"Порядок байт в файле pg_control может не соответствовать используемому\n" +"этой программой. В этом случае результаты будут неверными и\n" +"установленный PostgreSQL будет несовместим с этим каталогом данных." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не удалось записать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -42,7 +142,12 @@ msgstr "неверное значение \"%s\" для параметра %s" msgid "%s must be in range %d..%d" msgstr "значение %s должно быть в диапазоне %d..%d" -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: pg_checksums.c:70 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database " @@ -53,17 +158,17 @@ msgstr "" "PostgreSQL.\n" "\n" -#: pg_checksums.c:80 +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [ПАРАМЕТР]... [КАТАЛОГ]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format msgid "" "\n" @@ -72,29 +177,29 @@ msgstr "" "\n" "Параметры:\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]КАТ_ДАННЫХ каталог данных\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr "" " -c, --check проверить контрольные суммы данных (по " "умолчанию)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable отключить контрольные суммы\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable включить контрольные суммы\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid "" " -f, --filenode=FILENODE check only relation with specified filenode\n" @@ -102,7 +207,7 @@ msgstr "" " -f, --filenode=ФАЙЛ_УЗЕЛ проверить только отношение с заданным файловым " "узлом\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written safely to " @@ -110,27 +215,32 @@ msgid "" msgstr "" " -N, --no-sync не ждать завершения сохранения данных на диске\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress показывать прогресс операции\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose выводить подробные сообщения\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format msgid "" "\n" @@ -144,37 +254,32 @@ msgstr "" "переменной окружения PGDATA.\n" "\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld МБ (%d%%) обработано" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "не удалось прочитать блок %u в файле \"%s\": %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "не удалось прочитать блок %u в файле \"%s\" (прочитано байт: %d из %d)" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "" "checksum verification failed in file \"%s\", block %u: calculated checksum " @@ -183,82 +288,72 @@ msgstr "" "ошибка контрольных сумм в файле \"%s\", блоке %u: вычислена контрольная " "сумма %X, но блок содержит %X" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "ошибка при переходе к блоку %u в файле \"%s\": %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "не удалось записать блок %u в файл \"%s\": %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "не удалось записать блок %u в файле \"%s\" (записано байт: %d из %d)" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "контрольные суммы в файле \"%s\" проверены" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "контрольные суммы в файле \"%s\" включены" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не удалось открыть каталог \"%s\": %m" - -#: pg_checksums.c:346 pg_checksums.c:415 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "не удалось получить информацию о файле \"%s\": %m" - -#: pg_checksums.c:370 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "неверный номер сегмента %d в имени файла \"%s\"" -#: pg_checksums.c:512 pg_checksums.c:528 pg_checksums.c:538 pg_checksums.c:546 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_checksums.c:527 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "каталог данных не указан" -#: pg_checksums.c:536 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_checksums.c:545 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "параметр -f/--filenode можно использовать только с --check" -#: pg_checksums.c:553 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "ошибка контрольного значения в pg_control" -#: pg_checksums.c:556 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "кластер несовместим с этой версией pg_checksums" -#: pg_checksums.c:560 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "несовместимый кластер баз данных" -#: pg_checksums.c:561 +#: pg_checksums.c:558 #, c-format msgid "" "The database cluster was initialized with block size %u, but pg_checksums " @@ -267,77 +362,77 @@ msgstr "" "Кластер баз данных был инициализирован с размером блока %u, а утилита " "pg_checksums скомпилирована для размера блока %u." -#: pg_checksums.c:573 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "кластер должен быть отключён" -#: pg_checksums.c:577 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "контрольные суммы в кластере не включены" -#: pg_checksums.c:581 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "контрольные суммы в кластере уже отключены" -#: pg_checksums.c:585 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "контрольные суммы в кластере уже включены" -#: pg_checksums.c:609 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "Обработка контрольных сумм завершена\n" -#: pg_checksums.c:610 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "Просканировано файлов: %lld\n" -#: pg_checksums.c:611 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "Просканировано блоков: %lld\n" -#: pg_checksums.c:614 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "Неверные контрольные суммы: %lld\n" -#: pg_checksums.c:615 pg_checksums.c:647 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "Версия контрольных сумм данных: %u\n" -#: pg_checksums.c:622 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "Записано файлов: %lld\n" -#: pg_checksums.c:623 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "Записано блоков: %lld\n" -#: pg_checksums.c:639 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "синхронизация каталога данных" -#: pg_checksums.c:643 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "модификация управляющего файла" -#: pg_checksums.c:649 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Контрольные суммы в кластере включены\n" -#: pg_checksums.c:651 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Контрольные суммы в кластере отключены\n" diff --git a/src/bin/pg_checksums/po/sv.po b/src/bin/pg_checksums/po/sv.po index 8e92a9e5443b1..245aa1722ae29 100644 --- a/src/bin/pg_checksums/po/sv.po +++ b/src/bin/pg_checksums/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_checksums # Copyright (C) 2019 PostgreSQL Global Development Group # This file is distributed under the same license as the pg_checksums (PostgreSQL) package. -# Dennis Björklund , 2019, 2020, 2021, 2022. +# Dennis Björklund , 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-09 18:52+0000\n" -"PO-Revision-Date: 2022-05-09 21:46+0200\n" +"POT-Creation-Date: 2024-07-12 14:25+0000\n" +"PO-Revision-Date: 2024-07-12 18:57+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,26 +17,125 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "fel: " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "varning: " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "detalj: " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "tips: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "kunde inte stänga fil \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"möjligt fel i byteordning\n" +"Den byteordning som filen från pg_control lagrats med passar kanske\n" +"inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" +"och PostgreSQL-installationen vara inkompatibel med databaskatalogen." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "kunde inte skriva fil \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -47,7 +146,12 @@ msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" msgid "%s must be in range %d..%d" msgstr "%s måste vara i intervallet %d..%d" -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: pg_checksums.c:70 #, c-format msgid "" "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" @@ -56,17 +160,17 @@ msgstr "" "%s slår på, slår av eller verifierar datakontrollsummor i ett PostgreSQL databaskluster.\n" "\n" -#: pg_checksums.c:80 +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [FLAGGA]... [DATAKATALOG]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format msgid "" "\n" @@ -75,57 +179,62 @@ msgstr "" "\n" "Flaggor:\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATAKAT datakatalog\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check kontrollera datakontrollsummor (standard)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable slå av datakontrollsummor\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable slå på datakontrollsummor\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" msgstr " -f, --filenode=FILNOD kontrollera bara relation med angiven filnod\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync vänta inte på att ändingar säkert skrivits till disk\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress visa förloppsinformation\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" msgstr " -v, --verbose visa utförliga meddelanden\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format msgid "" "\n" @@ -138,192 +247,177 @@ msgstr "" "PGDATA för detta syfte.\n" "\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapportera fel till <%s>.\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld MB (%d%%) beräknad" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "kunde inte läsa block %u i fil \"%s\": %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "kunde inte läsa block %u i fil \"%s\": läste %d av %d" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "verifiering av kontrollsumma misslyckades i fil \"%s\", block %u: beräknad kontrollsumma är %X men blocket innehåller %X" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "seek misslyckades för block %u i fil \"%s\": %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "kunde inte skriva block %u i fil \"%s\": %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "kunde inte skriva block %u i fil \"%s\": skrev %d av %d" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "kontrollsummor verifierade i fil \"%s\"" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "kontrollsummor påslagen i fil \"%s\"" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "kunde inte öppna katalog \"%s\": %m" - -#: pg_checksums.c:342 pg_checksums.c:415 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "kunde inte göra stat() på fil \"%s\": %m" - -#: pg_checksums.c:366 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "ogiltigt segmentnummer %d i filnamn \"%s\"" -#: pg_checksums.c:512 pg_checksums.c:528 pg_checksums.c:538 pg_checksums.c:546 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_checksums.c:527 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "ingen datakatalog angiven" -#: pg_checksums.c:536 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_checksums.c:545 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "inställningen -f/--filenode tillåts bara med --check" -#: pg_checksums.c:553 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "pg_control CRC-värde är inkorrekt" -#: pg_checksums.c:556 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "klustret är inte kompatibelt med denna version av pg_checksums" -#: pg_checksums.c:560 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "databasklustret är inte kompatibelt" -#: pg_checksums.c:561 +#: pg_checksums.c:558 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "Databasklustret initierades med blockstorlek %u men pg_checksums kompilerades med blockstorlek %u." -#: pg_checksums.c:573 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "klustret måste stängas ner" -#: pg_checksums.c:577 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "datakontrollsummor är inte påslaget i klustret" -#: pg_checksums.c:581 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "datakontrollsummor är redan avslaget i klustret" -#: pg_checksums.c:585 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "datakontrollsummor är redan påslagna i klustret" -#: pg_checksums.c:609 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "Kontrollsummeoperation avslutad\n" -#: pg_checksums.c:610 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "Skannade filer: %lld\n" -#: pg_checksums.c:611 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "Skannade block: %lld\n" -#: pg_checksums.c:614 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "Felaktiga kontrollsummor: %lld\n" -#: pg_checksums.c:615 pg_checksums.c:647 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "Datakontrollsummeversion: %u\n" -#: pg_checksums.c:622 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "Skrivna filer: %lld\n" -#: pg_checksums.c:623 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "Skrivna block: %lld\n" -#: pg_checksums.c:639 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "synkar datakatalogen" -#: pg_checksums.c:643 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "uppdaterar kontrollfil" -#: pg_checksums.c:649 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Kontrollsummor påslaget i klustret\n" -#: pg_checksums.c:651 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Kontrollsummor avslaget i klustret\n" diff --git a/src/bin/pg_checksums/po/uk.po b/src/bin/pg_checksums/po/uk.po index f27bd1ec3e9a2..747d6867562a4 100644 --- a/src/bin/pg_checksums/po/uk.po +++ b/src/bin/pg_checksums/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:52+0000\n" -"PO-Revision-Date: 2023-09-05 10:04+0200\n" +"POT-Creation-Date: 2024-08-31 06:25+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_checksums.pot\n" -"X-Crowdin-File-ID: 888\n" +"X-Crowdin-File: /REL_17_STABLE/pg_checksums.pot\n" +"X-Crowdin-File-ID: 1000\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,6 +37,101 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" + +#: ../../common/controldata_utils.c:110 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "неможливо закрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "можлива помилка у послідовності байтів.\n" +"Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_checksums.c:192 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не вдалося записати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: pg_checksums.c:338 pg_checksums.c:407 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_checksums.c:310 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: ../../fe_utils/option_utils.c:69 #, c-format msgid "invalid value \"%s\" for option %s" @@ -47,282 +142,268 @@ msgstr "неприпустиме значення \"%s\" для параметр msgid "%s must be in range %d..%d" msgstr "%s має бути в діапазоні %d..%d" -#: pg_checksums.c:79 +#: ../../fe_utils/option_utils.c:106 #, c-format -msgid "" -"%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n" -"\n" -msgstr "" -"%s активує, деактивує або перевіряє контрольні суми даних в кластері бази даних PostgreSQL.\n" -"\n" +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" -#: pg_checksums.c:80 +#: pg_checksums.c:70 +#, c-format +msgid "%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n\n" +msgstr "%s активує, деактивує або перевіряє контрольні суми даних в кластері бази даних PostgreSQL.\n\n" + +#: pg_checksums.c:71 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_checksums.c:81 +#: pg_checksums.c:72 #, c-format msgid " %s [OPTION]... [DATADIR]\n" msgstr " %s [OPTION]... [DATADIR]\n" -#: pg_checksums.c:82 +#: pg_checksums.c:73 #, c-format -msgid "" -"\n" +msgid "\n" "Options:\n" -msgstr "" -"\n" +msgstr "\n" "Параметри:\n" -#: pg_checksums.c:83 +#: pg_checksums.c:74 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]DATADIR каталог даних\n" +msgstr " [-D, --pgdata=]DATADIR каталог даних\n" -#: pg_checksums.c:84 +#: pg_checksums.c:75 #, c-format msgid " -c, --check check data checksums (default)\n" msgstr " -c, --check перевірити контрольні суми даних (за замовчуванням)\n" -#: pg_checksums.c:85 +#: pg_checksums.c:76 #, c-format msgid " -d, --disable disable data checksums\n" msgstr " -d, --disable вимкнути контрольні суми даних\n" -#: pg_checksums.c:86 +#: pg_checksums.c:77 #, c-format msgid " -e, --enable enable data checksums\n" msgstr " -e, --enable активувати контрольні суми даних\n" -#: pg_checksums.c:87 +#: pg_checksums.c:78 #, c-format msgid " -f, --filenode=FILENODE check only relation with specified filenode\n" -msgstr " -f, --filenode=FILENODE перевіряти відношення лише із вказаним файлом\n" +msgstr " -f, --filenode=FILENODE перевіряти відношення лише із вказаним файлом\n" -#: pg_checksums.c:88 +#: pg_checksums.c:79 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" -msgstr " -N, --no-sync не чекати на безпечний запис змін на диск\n" +msgstr " -N, --no-sync не чекати на безпечний запис змін на диск\n" -#: pg_checksums.c:89 +#: pg_checksums.c:80 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress показати інформацію про прогрес\n" -#: pg_checksums.c:90 +#: pg_checksums.c:81 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод синхронізації файлів на диск\n" + +#: pg_checksums.c:82 #, c-format msgid " -v, --verbose output verbose messages\n" -msgstr " -v, --verbose виводити детальні повідомлення\n" +msgstr " -v, --verbose виводити детальні повідомлення\n" -#: pg_checksums.c:91 +#: pg_checksums.c:83 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: pg_checksums.c:92 +#: pg_checksums.c:84 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: pg_checksums.c:93 +#: pg_checksums.c:85 #, c-format -msgid "" -"\n" +msgid "\n" "If no data directory (DATADIR) is specified, the environment variable PGDATA\n" -"is used.\n" -"\n" -msgstr "" -"\n" -"Якщо каталог даних не вказано (DATADIR), використовується змінна середовища PGDATA.\n" -"\n" +"is used.\n\n" +msgstr "\n" +"Якщо каталог даних не вказано (DATADIR), використовується змінна середовища PGDATA.\n\n" -#: pg_checksums.c:95 +#: pg_checksums.c:87 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Повідомляти про помилки на <%s>.\n" -#: pg_checksums.c:96 +#: pg_checksums.c:88 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_checksums.c:153 +#: pg_checksums.c:145 #, c-format msgid "%lld/%lld MB (%d%%) computed" msgstr "%lld/%lld MB (%d%%) обчислено" -#: pg_checksums.c:200 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" - -#: pg_checksums.c:214 +#: pg_checksums.c:206 #, c-format msgid "could not read block %u in file \"%s\": %m" msgstr "не вдалося прочитати блок %u в файлі \"%s\": %m" -#: pg_checksums.c:217 +#: pg_checksums.c:209 #, c-format msgid "could not read block %u in file \"%s\": read %d of %d" msgstr "не вдалося прочитати блок %u у файлі \"%s\": прочитано %d з %d" -#: pg_checksums.c:240 +#: pg_checksums.c:232 #, c-format msgid "checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X" msgstr "помилка перевірки контрольних сум у файлі \"%s\", блок %u: обчислена контрольна сума %X, але блок містить %X" -#: pg_checksums.c:263 +#: pg_checksums.c:255 #, c-format msgid "seek failed for block %u in file \"%s\": %m" msgstr "помилка пошуку для блоку %u у файлі \"%s\": %m" -#: pg_checksums.c:270 +#: pg_checksums.c:262 #, c-format msgid "could not write block %u in file \"%s\": %m" msgstr "не вдалося записати блок %u у файл \"%s\": %m" -#: pg_checksums.c:273 +#: pg_checksums.c:265 #, c-format msgid "could not write block %u in file \"%s\": wrote %d of %d" msgstr "не вдалося записати блок %u у файлі \"%s\": записано %d з %d" -#: pg_checksums.c:285 +#: pg_checksums.c:277 #, c-format msgid "checksums verified in file \"%s\"" msgstr "контрольні суми у файлі \"%s\" перевірені" -#: pg_checksums.c:287 +#: pg_checksums.c:279 #, c-format msgid "checksums enabled in file \"%s\"" msgstr "контрольні суми у файлі \"%s\" активовані" -#: pg_checksums.c:318 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не вдалося відкрити каталог \"%s\": %m" - -#: pg_checksums.c:342 pg_checksums.c:415 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" - -#: pg_checksums.c:366 +#: pg_checksums.c:362 #, c-format msgid "invalid segment number %d in file name \"%s\"" msgstr "неприпустимий номер сегменту %d в імені файлу \"%s\"" -#: pg_checksums.c:512 pg_checksums.c:528 pg_checksums.c:538 pg_checksums.c:546 +#: pg_checksums.c:509 pg_checksums.c:525 pg_checksums.c:535 pg_checksums.c:543 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_checksums.c:527 +#: pg_checksums.c:524 #, c-format msgid "no data directory specified" msgstr "каталог даних не вказано" -#: pg_checksums.c:536 +#: pg_checksums.c:533 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_checksums.c:545 +#: pg_checksums.c:542 #, c-format msgid "option -f/--filenode can only be used with --check" msgstr "параметр -f/--filenode може бути використаний тільки з --check" -#: pg_checksums.c:553 +#: pg_checksums.c:550 #, c-format msgid "pg_control CRC value is incorrect" msgstr "значення CRC pg_control неправильне" -#: pg_checksums.c:556 +#: pg_checksums.c:553 #, c-format msgid "cluster is not compatible with this version of pg_checksums" msgstr "кластер не сумісний з цією версією pg_checksum" -#: pg_checksums.c:560 +#: pg_checksums.c:557 #, c-format msgid "database cluster is not compatible" msgstr "кластер бази даних не сумісний" -#: pg_checksums.c:561 +#: pg_checksums.c:558 #, c-format msgid "The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u." msgstr "Кластер бази даних було ініціалізовано з розміром блоку %u, але pg_checksums було скомпільовано з розміром блоку %u." -#: pg_checksums.c:573 +#: pg_checksums.c:570 #, c-format msgid "cluster must be shut down" msgstr "кластер повинен бути закритий" -#: pg_checksums.c:577 +#: pg_checksums.c:574 #, c-format msgid "data checksums are not enabled in cluster" msgstr "контрольні суми в кластері неактивовані" -#: pg_checksums.c:581 +#: pg_checksums.c:578 #, c-format msgid "data checksums are already disabled in cluster" msgstr "контрольні суми вже неактивовані в кластері" -#: pg_checksums.c:585 +#: pg_checksums.c:582 #, c-format msgid "data checksums are already enabled in cluster" msgstr "контрольні суми вже активовані в кластері" -#: pg_checksums.c:609 +#: pg_checksums.c:606 #, c-format msgid "Checksum operation completed\n" msgstr "Операція контрольної суми завершена\n" -#: pg_checksums.c:610 +#: pg_checksums.c:607 #, c-format msgid "Files scanned: %lld\n" msgstr "Файлів проскановано: %lld\n" -#: pg_checksums.c:611 +#: pg_checksums.c:608 #, c-format msgid "Blocks scanned: %lld\n" msgstr "Блоків відскановано: %lld\n" -#: pg_checksums.c:614 +#: pg_checksums.c:611 #, c-format msgid "Bad checksums: %lld\n" msgstr "Помилкові контрольні суми: %lld\n" -#: pg_checksums.c:615 pg_checksums.c:647 +#: pg_checksums.c:612 pg_checksums.c:644 #, c-format msgid "Data checksum version: %u\n" msgstr "Версія контрольних сум даних: %u\n" -#: pg_checksums.c:622 +#: pg_checksums.c:619 #, c-format msgid "Files written: %lld\n" msgstr "Файлів записано: %lld\n" -#: pg_checksums.c:623 +#: pg_checksums.c:620 #, c-format msgid "Blocks written: %lld\n" msgstr "Блоків записано: %lld\n" -#: pg_checksums.c:639 +#: pg_checksums.c:636 #, c-format msgid "syncing data directory" msgstr "синхронізація даних каталогу" -#: pg_checksums.c:643 +#: pg_checksums.c:640 #, c-format msgid "updating control file" msgstr "оновлення контрольного файлу" -#: pg_checksums.c:649 +#: pg_checksums.c:646 #, c-format msgid "Checksums enabled in cluster\n" msgstr "Контрольні суми активовані в кластері\n" -#: pg_checksums.c:651 +#: pg_checksums.c:648 #, c-format msgid "Checksums disabled in cluster\n" msgstr "Контрольні суми вимкнені у кластері\n" + diff --git a/src/bin/pg_checksums/t/001_basic.pl b/src/bin/pg_checksums/t/001_basic.pl index c11abe142e4c6..23730b1833ea3 100644 --- a/src/bin/pg_checksums/t/001_basic.pl +++ b/src/bin/pg_checksums/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_checksums/t/002_actions.pl b/src/bin/pg_checksums/t/002_actions.pl index 33e7fb53c5e16..339c1537a4606 100644 --- a/src/bin/pg_checksums/t/002_actions.pl +++ b/src/bin/pg_checksums/t/002_actions.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Do basic sanity checks supported by pg_checksums using # an initialized cluster. @@ -44,9 +44,10 @@ sub check_relation_corruption # corrupted yet. command_ok( [ - 'pg_checksums', '--check', - '-D', $pgdata, - '--filenode', $relfilenode_corrupted + 'pg_checksums', + '--check', + '--pgdata' => $pgdata, + '--filenode' => $relfilenode_corrupted, ], "succeeds for single relfilenode on tablespace $tablespace with offline cluster" ); @@ -57,9 +58,10 @@ sub check_relation_corruption # Checksum checks on single relfilenode fail $node->command_checks_all( [ - 'pg_checksums', '--check', - '-D', $pgdata, - '--filenode', $relfilenode_corrupted + 'pg_checksums', + '--check', + '--pgdata' => $pgdata, + '--filenode' => $relfilenode_corrupted, ], 1, [qr/Bad checksums:.*1/], @@ -69,7 +71,7 @@ sub check_relation_corruption # Global checksum checks fail as well $node->command_checks_all( - [ 'pg_checksums', '--check', '-D', $pgdata ], + [ 'pg_checksums', '--check', '--pgdata' => $pgdata ], 1, [qr/Bad checksums:.*1/], [qr/checksum verification failed/], @@ -79,7 +81,8 @@ sub check_relation_corruption $node->start; $node->safe_psql('postgres', "DROP TABLE $table;"); $node->stop; - $node->command_ok([ 'pg_checksums', '--check', '-D', $pgdata ], + $node->command_ok( + [ 'pg_checksums', '--check', '--pgdata' => $pgdata ], "succeeds again after table drop on tablespace $tablespace"); $node->start; @@ -88,7 +91,7 @@ sub check_relation_corruption # Initialize node with checksums disabled. my $node = PostgreSQL::Test::Cluster->new('node_checksum'); -$node->init(); +$node->init(no_data_checksums => 1); my $pgdata = $node->data_dir; # Control file should know that checksums are disabled. @@ -122,11 +125,12 @@ sub check_relation_corruption unless ($Config{osname} eq 'darwin'); # Enable checksums. -command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ], +command_ok([ 'pg_checksums', '--enable', '--no-sync', '--pgdata' => $pgdata ], "checksums successfully enabled in cluster"); # Successive attempt to enable checksums fails. -command_fails([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ], +command_fails( + [ 'pg_checksums', '--enable', '--no-sync', '--pgdata' => $pgdata ], "enabling checksums fails if already enabled"); # Control file should know that checksums are enabled. @@ -137,12 +141,12 @@ sub check_relation_corruption # Disable checksums again. Flush result here as that should be cheap. command_ok( - [ 'pg_checksums', '--disable', '-D', $pgdata ], + [ 'pg_checksums', '--disable', '--pgdata' => $pgdata ], "checksums successfully disabled in cluster"); # Successive attempt to disable checksums fails. command_fails( - [ 'pg_checksums', '--disable', '--no-sync', '-D', $pgdata ], + [ 'pg_checksums', '--disable', '--no-sync', '--pgdata' => $pgdata ], "disabling checksums fails if already disabled"); # Control file should know that checksums are disabled. @@ -152,7 +156,7 @@ sub check_relation_corruption 'checksums disabled in control file'); # Enable checksums again for follow-up tests. -command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ], +command_ok([ 'pg_checksums', '--enable', '--no-sync', '--pgdata' => $pgdata ], "checksums successfully enabled in cluster"); # Control file should know that checksums are enabled. @@ -162,21 +166,31 @@ sub check_relation_corruption 'checksums enabled in control file'); # Checksums pass on a newly-created cluster -command_ok([ 'pg_checksums', '--check', '-D', $pgdata ], +command_ok([ 'pg_checksums', '--check', '--pgdata' => $pgdata ], "succeeds with offline cluster"); # Checksums are verified if no other arguments are specified command_ok( - [ 'pg_checksums', '-D', $pgdata ], + [ 'pg_checksums', '--pgdata' => $pgdata ], "verifies checksums as default action"); # Specific relation files cannot be requested when action is --disable # or --enable. command_fails( - [ 'pg_checksums', '--disable', '--filenode', '1234', '-D', $pgdata ], + [ + 'pg_checksums', + '--disable', + '--filenode' => '1234', + '--pgdata' => $pgdata + ], "fails when relfilenodes are requested and action is --disable"); command_fails( - [ 'pg_checksums', '--enable', '--filenode', '1234', '-D', $pgdata ], + [ + 'pg_checksums', + '--enable', + '--filenode' => '1234', + '--pgdata' => $pgdata + ], "fails when relfilenodes are requested and action is --enable"); # Test postgres -C for an offline cluster. @@ -187,8 +201,10 @@ sub check_relation_corruption # account on Windows. command_checks_all( [ - 'pg_ctl', 'start', '-D', $pgdata, '-s', '-o', - '-C data_checksums -c log_min_messages=fatal' + 'pg_ctl', 'start', + '--silent', + '--pgdata' => $pgdata, + '-o' => '-C data_checksums -c log_min_messages=fatal', ], 1, [qr/^on$/], @@ -197,7 +213,7 @@ sub check_relation_corruption # Checks cannot happen with an online cluster $node->start; -command_fails([ 'pg_checksums', '--check', '-D', $pgdata ], +command_fails([ 'pg_checksums', '--check', '--pgdata' => $pgdata ], "fails with online cluster"); # Check corruption of table on default tablespace. @@ -224,7 +240,7 @@ sub fail_corrupt append_to_file $file_name, "foo"; $node->command_checks_all( - [ 'pg_checksums', '--check', '-D', $pgdata ], + [ 'pg_checksums', '--check', '--pgdata' => $pgdata ], 1, [qr/^$/], [qr/could not read block 0 in file.*$file\":/], @@ -242,7 +258,7 @@ sub fail_corrupt # when verifying checksums. mkdir "$tablespace_dir/PG_99_999999991/"; append_to_file "$tablespace_dir/PG_99_999999991/foo", "123"; -command_ok([ 'pg_checksums', '--check', '-D', $pgdata ], +command_ok([ 'pg_checksums', '--check', '--pgdata' => $pgdata ], "succeeds with foreign tablespace"); # Authorized relation files filled with corrupted data cause the diff --git a/src/bin/pg_combinebackup/Makefile b/src/bin/pg_combinebackup/Makefile index c3729755ba4ba..33a1f4483bfbd 100644 --- a/src/bin/pg_combinebackup/Makefile +++ b/src/bin/pg_combinebackup/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_combinebackup # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_combinebackup/Makefile diff --git a/src/bin/pg_combinebackup/backup_label.c b/src/bin/pg_combinebackup/backup_label.c index e676249247d47..e89d4603f09dc 100644 --- a/src/bin/pg_combinebackup/backup_label.c +++ b/src/bin/pg_combinebackup/backup_label.c @@ -2,7 +2,7 @@ * * Read and manipulate backup label files * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/backup_label.c diff --git a/src/bin/pg_combinebackup/backup_label.h b/src/bin/pg_combinebackup/backup_label.h index e2fc8dd4ce1fe..cbb56dc557b97 100644 --- a/src/bin/pg_combinebackup/backup_label.h +++ b/src/bin/pg_combinebackup/backup_label.h @@ -2,7 +2,7 @@ * * Read and manipulate backup label files * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/backup_label.h diff --git a/src/bin/pg_combinebackup/copy_file.c b/src/bin/pg_combinebackup/copy_file.c index 57a7c3a202c39..db6c86223bbda 100644 --- a/src/bin/pg_combinebackup/copy_file.c +++ b/src/bin/pg_combinebackup/copy_file.c @@ -1,7 +1,7 @@ /* * Copy entire files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/copy_file.h @@ -40,6 +40,9 @@ static void copy_file_copyfile(const char *src, const char *dst, pg_checksum_context *checksum_ctx); #endif +static void copy_file_link(const char *src, const char *dest, + pg_checksum_context *checksum_ctx); + /* * Copy a regular file, optionally computing a checksum, and emitting * appropriate debug messages. But if we're in dry-run mode, then just emit @@ -69,7 +72,14 @@ copy_file(const char *src, const char *dst, } #ifdef WIN32 - copy_method = COPY_METHOD_COPYFILE; + + /* + * We have no specific switch to enable CopyFile on Windows, because it's + * supported (as far as we know) on all Windows machines. So, + * automatically enable it unless some other strategy was selected. + */ + if (copy_method == COPY_METHOD_COPY) + copy_method = COPY_METHOD_COPYFILE; #endif /* Determine the name of the copy strategy for use in log messages. */ @@ -93,6 +103,10 @@ copy_file(const char *src, const char *dst, strategy_implementation = copy_file_copyfile; break; #endif + case COPY_METHOD_LINK: + strategy_name = "link"; + strategy_implementation = copy_file_link; + break; } if (dry_run) @@ -304,3 +318,21 @@ copy_file_copyfile(const char *src, const char *dst, checksum_file(src, checksum_ctx); } #endif /* WIN32 */ + +/* + * copy_file_link + * Hard-links a file from src to dest. + * + * If needed, also reads the file and calculates the checksum. + */ +static void +copy_file_link(const char *src, const char *dest, + pg_checksum_context *checksum_ctx) +{ + if (link(src, dest) < 0) + pg_fatal("could not create link from \"%s\" to \"%s\": %m", + src, dest); + + /* if needed, calculate checksum of the file */ + checksum_file(src, checksum_ctx); +} diff --git a/src/bin/pg_combinebackup/copy_file.h b/src/bin/pg_combinebackup/copy_file.h index cedb760738561..3779edd567793 100644 --- a/src/bin/pg_combinebackup/copy_file.h +++ b/src/bin/pg_combinebackup/copy_file.h @@ -1,7 +1,7 @@ /* * Copy entire files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/copy_file.h @@ -11,9 +11,7 @@ #ifndef COPY_FILE_H #define COPY_FILE_H -#include "c.h" #include "common/checksum_helper.h" -#include "common/file_utils.h" /* * Enumeration to denote copy modes. @@ -26,6 +24,7 @@ typedef enum CopyMethod #ifdef WIN32 COPY_METHOD_COPYFILE, #endif + COPY_METHOD_LINK, } CopyMethod; extern void copy_file(const char *src, const char *dst, diff --git a/src/bin/pg_combinebackup/load_manifest.c b/src/bin/pg_combinebackup/load_manifest.c index be8e6273fcb3b..8e0d04a26a6a7 100644 --- a/src/bin/pg_combinebackup/load_manifest.c +++ b/src/bin/pg_combinebackup/load_manifest.c @@ -2,7 +2,7 @@ * * Load data from a backup manifest into memory. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/load_manifest.c @@ -60,7 +60,7 @@ static void combinebackup_version_cb(JsonManifestParseContext *context, static void combinebackup_system_identifier_cb(JsonManifestParseContext *context, uint64 manifest_system_identifier); static void combinebackup_per_file_cb(JsonManifestParseContext *context, - const char *pathname, size_t size, + const char *pathname, uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload); @@ -68,9 +68,9 @@ static void combinebackup_per_wal_range_cb(JsonManifestParseContext *context, TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn); -static void report_manifest_error(JsonManifestParseContext *context, - const char *fmt,...) - pg_attribute_printf(2, 3) pg_attribute_noreturn(); +pg_noreturn static void report_manifest_error(JsonManifestParseContext *context, + const char *fmt,...) + pg_attribute_printf(2, 3); /* * Load backup_manifest files from an array of backups and produces an array @@ -204,8 +204,7 @@ load_backup_manifest(char *backup_directory) (long long int) statbuf.st_size); } bytes_left -= rc; - json_parse_manifest_incremental_chunk( - inc_state, buffer, rc, bytes_left == 0); + json_parse_manifest_incremental_chunk(inc_state, buffer, rc, bytes_left == 0); } /* Release the incremental state memory */ @@ -267,7 +266,7 @@ combinebackup_system_identifier_cb(JsonManifestParseContext *context, */ static void combinebackup_per_file_cb(JsonManifestParseContext *context, - const char *pathname, size_t size, + const char *pathname, uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload) { diff --git a/src/bin/pg_combinebackup/load_manifest.h b/src/bin/pg_combinebackup/load_manifest.h index a96ae12eb8ed4..9bd3c694b34aa 100644 --- a/src/bin/pg_combinebackup/load_manifest.h +++ b/src/bin/pg_combinebackup/load_manifest.h @@ -2,7 +2,7 @@ * * Load data from a backup manifest into memory. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/load_manifest.h @@ -23,7 +23,7 @@ typedef struct manifest_file { uint32 status; /* hash status */ const char *pathname; - size_t size; + uint64 size; pg_checksum_type checksum_type; int checksum_length; uint8 *checksum_payload; diff --git a/src/bin/pg_combinebackup/meson.build b/src/bin/pg_combinebackup/meson.build index d142608e94915..e80a4756a7f4f 100644 --- a/src/bin/pg_combinebackup/meson.build +++ b/src/bin/pg_combinebackup/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_combinebackup_sources = files( 'pg_combinebackup.c', @@ -36,6 +36,8 @@ tests += { 't/006_db_file_copy.pl', 't/007_wal_level_minimal.pl', 't/008_promote.pl', + 't/009_no_full_file.pl', + 't/010_hardlink.pl', ], } } diff --git a/src/bin/pg_combinebackup/pg_combinebackup.c b/src/bin/pg_combinebackup/pg_combinebackup.c index 9ded5a2140e90..28e58cd8ef458 100644 --- a/src/bin/pg_combinebackup/pg_combinebackup.c +++ b/src/bin/pg_combinebackup/pg_combinebackup.c @@ -3,7 +3,7 @@ * pg_combinebackup.c * Combine incremental backups with prior backups. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_combinebackup/pg_combinebackup.c @@ -24,13 +24,14 @@ #include #endif +#include "access/xlog_internal.h" #include "backup_label.h" -#include "common/blkreftable.h" #include "common/checksum_helper.h" #include "common/controldata_utils.h" #include "common/file_perm.h" #include "common/file_utils.h" #include "common/logging.h" +#include "common/relpath.h" #include "copy_file.h" #include "fe_utils/option_utils.h" #include "getopt_long.h" @@ -135,6 +136,7 @@ main(int argc, char *argv[]) {"no-sync", no_argument, NULL, 'N'}, {"output", required_argument, NULL, 'o'}, {"tablespace-mapping", required_argument, NULL, 'T'}, + {"link", no_argument, NULL, 'k'}, {"manifest-checksums", required_argument, NULL, 1}, {"no-manifest", no_argument, NULL, 2}, {"sync-method", required_argument, NULL, 3}, @@ -172,7 +174,7 @@ main(int argc, char *argv[]) opt.copy_method = COPY_METHOD_COPY; /* process command-line options */ - while ((c = getopt_long(argc, argv, "dnNo:T:", + while ((c = getopt_long(argc, argv, "dknNo:T:", long_options, &optindex)) != -1) { switch (c) @@ -181,6 +183,9 @@ main(int argc, char *argv[]) opt.debug = true; pg_logging_increase_verbosity(); break; + case 'k': + opt.copy_method = COPY_METHOD_LINK; + break; case 'n': opt.dry_run = true; break; @@ -296,12 +301,12 @@ main(int argc, char *argv[]) { char *controlpath; - controlpath = psprintf("%s/%s", prior_backup_dirs[i], "global/pg_control"); + controlpath = psprintf("%s/%s", prior_backup_dirs[i], XLOG_CONTROL_FILE); - pg_fatal("%s: manifest system identifier is %llu, but control file has %llu", + pg_fatal("%s: manifest system identifier is %" PRIu64 ", but control file has %" PRIu64, controlpath, - (unsigned long long) manifests[i]->system_identifier, - (unsigned long long) system_identifier); + manifests[i]->system_identifier, + system_identifier); } } @@ -337,7 +342,7 @@ main(int argc, char *argv[]) * won't have the WAL ranges for the resulting manifest. */ if (manifests[n_prior_backups] == NULL) - pg_fatal("can't generate a manifest because no manifest is available for the final input backup"); + pg_fatal("cannot generate a manifest because no manifest is available for the final input backup"); } else mwriter = NULL; @@ -373,7 +378,7 @@ main(int argc, char *argv[]) { char linkpath[MAXPGPATH]; - snprintf(linkpath, MAXPGPATH, "%s/pg_tblspc/%u", opt.output, + snprintf(linkpath, MAXPGPATH, "%s/%s/%u", opt.output, PG_TBLSPC_DIR, ts->oid); if (opt.dry_run) @@ -420,10 +425,15 @@ main(int argc, char *argv[]) else { pg_log_debug("recursively fsyncing \"%s\"", opt.output); - sync_pgdata(opt.output, version * 10000, opt.sync_method); + sync_pgdata(opt.output, version * 10000, opt.sync_method, true); } } + /* Warn about the possibility of compromising the backups, when link mode */ + if (opt.copy_method == COPY_METHOD_LINK) + pg_log_warning("--link mode was used; any modifications to the output " + "directory might destructively modify input directories"); + /* It's a success, so don't remove the output directories. */ reset_directory_cleanup_list(); exit(0); @@ -605,7 +615,7 @@ check_control_files(int n_backups, char **backup_dirs) bool crc_ok; char *controlpath; - controlpath = psprintf("%s/%s", backup_dirs[i], "global/pg_control"); + controlpath = psprintf("%s/%s", backup_dirs[i], XLOG_CONTROL_FILE); pg_log_debug("reading \"%s\"", controlpath); control_file = get_controlfile_by_exact_path(controlpath, &crc_ok); @@ -622,9 +632,9 @@ check_control_files(int n_backups, char **backup_dirs) if (i == n_backups - 1) system_identifier = control_file->system_identifier; else if (system_identifier != control_file->system_identifier) - pg_fatal("%s: expected system identifier %llu, but found %llu", - controlpath, (unsigned long long) system_identifier, - (unsigned long long) control_file->system_identifier); + pg_fatal("%s: expected system identifier %" PRIu64 ", but found %" PRIu64, + controlpath, system_identifier, + control_file->system_identifier); /* * Detect checksum mismatches, but only if the last backup in the @@ -645,8 +655,7 @@ check_control_files(int n_backups, char **backup_dirs) * If debug output is enabled, make a note of the system identifier that * we found in all of the relevant control files. */ - pg_log_debug("system identifier is %llu", - (unsigned long long) system_identifier); + pg_log_debug("system identifier is %" PRIu64, system_identifier); /* * Warn the user if not all backups are in the same state with regards to @@ -655,7 +664,7 @@ check_control_files(int n_backups, char **backup_dirs) if (data_checksum_mismatch) { pg_log_warning("only some backups have checksums enabled"); - pg_log_warning_hint("disable, and optionally reenable, checksums on the output directory to avoid failures"); + pg_log_warning_hint("Disable, and optionally reenable, checksums on the output directory to avoid failures."); } return system_identifier; @@ -761,14 +770,15 @@ help(const char *progname) printf(_(" %s [OPTION]... DIRECTORY...\n"), progname); printf(_("\nOptions:\n")); printf(_(" -d, --debug generate lots of debugging output\n")); + printf(_(" -k, --link link files instead of copying\n")); printf(_(" -n, --dry-run do not actually do anything\n")); printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n")); printf(_(" -o, --output=DIRECTORY output directory\n")); printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" " relocate tablespace in OLDDIR to NEWDIR\n")); - printf(_(" --clone clone (reflink) instead of copying files\n")); + printf(_(" --clone clone (reflink) files instead of copying\n")); printf(_(" --copy copy files (default)\n")); - printf(_(" --copy-file-range copy using copy_file_range() syscall\n")); + printf(_(" --copy-file-range copy using copy_file_range() system call\n")); printf(_(" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " use algorithm for manifest checksums\n")); printf(_(" --no-manifest suppress generation of backup manifest\n")); @@ -804,7 +814,7 @@ parse_oid(char *s, Oid *result) * Copy files from the input directory to the output directory, reconstructing * full files from incremental files as required. * - * If processing is a user-defined tablespace, the tsoid should be the OID + * If processing a user-defined tablespace, the tsoid should be the OID * of that tablespace and input_directory and output_directory should be the * toplevel input and output directories for that tablespace. Otherwise, * tsoid should be InvalidOid and input_directory and output_directory should @@ -816,7 +826,7 @@ parse_oid(char *s, Oid *result) * * n_prior_backups is the number of prior backups that we have available. * This doesn't count the very last backup, which is referenced by - * output_directory, just the older ones. prior_backup_dirs is an array of + * input_directory, just the older ones. prior_backup_dirs is an array of * the locations of those previous backups. */ static void @@ -849,7 +859,7 @@ process_directory_recursively(Oid tsoid, * * We set is_pg_wal for the toplevel WAL directory and all of its * subdirectories, because those files are not included in the backup - * manifest and hence need special treatement. (Since incremental backup + * manifest and hence need special treatment. (Since incremental backup * does not exist in pre-v10 versions, we don't have to worry about the * old pg_xlog naming.) * @@ -867,12 +877,12 @@ process_directory_recursively(Oid tsoid, is_incremental_dir = true; else if (relative_path != NULL) { - is_pg_tblspc = strcmp(relative_path, "pg_tblspc") == 0; + is_pg_tblspc = strcmp(relative_path, PG_TBLSPC_DIR) == 0; is_pg_wal = (strcmp(relative_path, "pg_wal") == 0 || strncmp(relative_path, "pg_wal/", 7) == 0); is_incremental_dir = strncmp(relative_path, "base/", 5) == 0 || strcmp(relative_path, "global") == 0 || - strncmp(relative_path, "pg_tblspc/", 10) == 0; + strncmp(relative_path, PG_TBLSPC_DIR_SLASH, 10) == 0; } /* @@ -895,7 +905,7 @@ process_directory_recursively(Oid tsoid, strlcpy(ifulldir, input_directory, MAXPGPATH); strlcpy(ofulldir, output_directory, MAXPGPATH); if (OidIsValid(tsoid)) - snprintf(manifest_prefix, MAXPGPATH, "pg_tblspc/%u/", tsoid); + snprintf(manifest_prefix, MAXPGPATH, "%s/%u/", PG_TBLSPC_DIR, tsoid); else manifest_prefix[0] = '\0'; } @@ -906,8 +916,8 @@ process_directory_recursively(Oid tsoid, snprintf(ofulldir, MAXPGPATH, "%s/%s", output_directory, relative_path); if (OidIsValid(tsoid)) - snprintf(manifest_prefix, MAXPGPATH, "pg_tblspc/%u/%s/", - tsoid, relative_path); + snprintf(manifest_prefix, MAXPGPATH, "%s/%u/%s/", + PG_TBLSPC_DIR, tsoid, relative_path); else snprintf(manifest_prefix, MAXPGPATH, "%s/", relative_path); } @@ -1070,7 +1080,7 @@ process_directory_recursively(Oid tsoid, */ bmpath = psprintf("%s/%s", input_directory, "backup_manifest"); - pg_log_warning("\"%s\" contains no entry for \"%s\"", + pg_log_warning("manifest file \"%s\" contains no entry for file \"%s\"", bmpath, manifest_path); pfree(bmpath); } @@ -1249,7 +1259,7 @@ scan_for_existing_tablespaces(char *pathname, cb_options *opt) struct dirent *de; cb_tablespace *tslist = NULL; - snprintf(pg_tblspc, MAXPGPATH, "%s/pg_tblspc", pathname); + snprintf(pg_tblspc, MAXPGPATH, "%s/%s", pathname, PG_TBLSPC_DIR); pg_log_debug("scanning \"%s\"", pg_tblspc); if ((dir = opendir(pg_tblspc)) == NULL) @@ -1344,8 +1354,8 @@ scan_for_existing_tablespaces(char *pathname, cb_options *opt) * we just record the paths within the data directories. */ snprintf(ts->old_dir, MAXPGPATH, "%s/%s", pg_tblspc, de->d_name); - snprintf(ts->new_dir, MAXPGPATH, "%s/pg_tblspc/%s", opt->output, - de->d_name); + snprintf(ts->new_dir, MAXPGPATH, "%s/%s/%s", opt->output, + PG_TBLSPC_DIR, de->d_name); ts->in_place = true; } diff --git a/src/bin/pg_combinebackup/po/LINGUAS b/src/bin/pg_combinebackup/po/LINGUAS index c675cfe1c72a6..a6af4f7c83594 100644 --- a/src/bin/pg_combinebackup/po/LINGUAS +++ b/src/bin/pg_combinebackup/po/LINGUAS @@ -1 +1 @@ -de ja ka +de es fr ja ka ko ru sv uk diff --git a/src/bin/pg_combinebackup/po/de.po b/src/bin/pg_combinebackup/po/de.po index 8a6b57b9db42d..7b7966539b9fd 100644 --- a/src/bin/pg_combinebackup/po/de.po +++ b/src/bin/pg_combinebackup/po/de.po @@ -1,13 +1,13 @@ # German message translation file for pg_combinebackup -# Copyright (C) 2024 PostgreSQL Global Development Group +# Copyright (C) 2025 PostgreSQL Global Development Group # This file is distributed under the same license as the pg_combinebackup (PostgreSQL) package. # msgid "" msgstr "" -"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Project-Id-Version: pg_combinebackup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 16:52+0000\n" -"PO-Revision-Date: 2024-06-22 09:58+0200\n" +"POT-Creation-Date: 2025-04-29 04:22+0000\n" +"PO-Revision-Date: 2025-04-29 08:34+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -15,22 +15,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -40,8 +40,8 @@ msgstr "Tipp: " msgid "could not open file \"%s\" for reading: %m" msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m" -#: ../../common/controldata_utils.c:110 copy_file.c:146 load_manifest.c:161 -#: load_manifest.c:199 pg_combinebackup.c:1387 reconstruct.c:527 +#: ../../common/controldata_utils.c:110 copy_file.c:164 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1410 reconstruct.c:540 #, c-format msgid "could not read file \"%s\": %m" msgstr "konnte Datei »%s« nicht lesen: %m" @@ -52,8 +52,8 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: backup_label.c:174 copy_file.c:64 pg_combinebackup.c:526 -#: pg_combinebackup.c:1162 reconstruct.c:356 reconstruct.c:727 +#: backup_label.c:174 copy_file.c:71 pg_combinebackup.c:548 +#: pg_combinebackup.c:1185 reconstruct.c:369 reconstruct.c:740 #: write_manifest.c:187 #, c-format msgid "could not close file \"%s\": %m" @@ -77,31 +77,32 @@ msgstr "" "diesem Fall wären die Ergebnisse unten falsch und die PostgreSQL-Installation\n" "wäre inkompatibel mit diesem Datenverzeichnis." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:62 -#: copy_file.c:135 copy_file.c:167 copy_file.c:171 copy_file.c:218 -#: copy_file.c:258 load_manifest.c:128 pg_combinebackup.c:511 -#: pg_combinebackup.c:1154 reconstruct.c:510 reconstruct.c:625 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 backup_label.c:143 copy_file.c:69 +#: copy_file.c:153 copy_file.c:185 copy_file.c:189 copy_file.c:239 +#: copy_file.c:282 load_manifest.c:128 pg_combinebackup.c:533 +#: pg_combinebackup.c:1177 reconstruct.c:523 reconstruct.c:638 #: write_manifest.c:250 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:746 +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 #: write_manifest.c:260 #, c-format msgid "could not write file \"%s\": %m" msgstr "konnte Datei »%s« nicht schreiben: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" #: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" @@ -130,290 +131,294 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:664 -#: pg_combinebackup.c:1118 pg_combinebackup.c:1370 reconstruct.c:199 -#: reconstruct.c:408 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:685 +#: pg_combinebackup.c:1141 pg_combinebackup.c:1393 reconstruct.c:204 +#: reconstruct.c:421 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 -#: pg_combinebackup.c:920 pg_combinebackup.c:1243 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_combinebackup.c:943 pg_combinebackup.c:1266 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" -#: ../../common/jsonapi.c:2121 +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "Parser mit rekursivem Abstieg kann inkrementellen Lexer nicht benutzen." -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "Inkrementeller Parser benötigt inkrementellen Lexer." -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSON zu tief geschachtelt, maximale erlaubte Tiefe ist 6400." -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "Escape-Sequenz »\\%.*s« ist nicht gültig." -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Zeichen mit Wert 0x%02x muss escapt werden." -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "Ende der Eingabe erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "Array-Element oder »]« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "»,« oder »]« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "»:« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "JSON-Wert erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "Die Eingabezeichenkette endete unerwartet." -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "Zeichenkette oder »}« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "»,« oder »}« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "Zeichenkette erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "Token »%.*s« ist ungültig." -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 kann nicht in »text« umgewandelt werden." -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "Nach »\\u« müssen vier Hexadezimalziffern folgen." -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "Unicode-Escape-Werte können nicht für Code-Punkt-Werte über 007F verwendet werden, wenn die Kodierung nicht UTF8 ist." -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Unicode-Escape-Wert konnte nicht in die Serverkodierung %s umgewandelt werden." -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicode-High-Surrogate darf nicht auf ein High-Surrogate folgen." -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicode-Low-Surrogate muss auf ein High-Surrogate folgen." -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "Speicher aufgebraucht beim Konstruieren der Fehlerbeschreibung" + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht initialisieren" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "Manifest endete unerwartet" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht aktualisieren" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "unerwarteter Objektstart" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "unerwartetes Objektende" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "unerwarteter Array-Start" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "unerwartetes Array-Ende" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "unerwartete Versionskennzeichnung" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "unbekanntes Feld auf oberster Ebene" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "unerwartetes Feld für Datei" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "unerwartetes Feld für WAL-Bereich" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "unbekanntes Feld für Objekt" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "unerwarteter Skalar" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "Manifestversion ist keine ganze Zahl" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "unerwartete Manifestversion" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" msgstr "Systemidentifikator im Manifest ist keine ganze Zahl" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "fehlender Pfadname" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "sowohl Pfadname als auch kodierter Pfadname angegeben" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "Größenangabe fehlt" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "Prüfsumme ohne Algorithmus" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "konnte Dateinamen nicht dekodieren" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "Dateigröße ist keine ganze Zahl" -#: ../../common/parse_manifest.c:700 pg_combinebackup.c:190 +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:204 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "unbekannter Prüfsummenalgorithmus: »%s«" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "ungültige Prüfsumme für Datei »%s«: »%s«" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "Zeitleiste fehlt" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "Start-LSN fehlt" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "End-LSN fehlt" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "Zeitleiste ist keine ganze Zahl" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "konnte Start-LSN nicht parsen" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "konnte End-LSN nicht parsen" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "mindestens 2 Zeilen erwartet" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "letzte Zeile nicht durch Newline abgeschlossen" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht abschließen" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "Manifest hat keine Prüfsumme" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "ungültige Manifestprüfsumme: »%s«" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "Manifestprüfsumme stimmt nicht überein" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "konnte Backup-Manifest nicht parsen: %s" @@ -463,67 +468,72 @@ msgstr "%s: konnte %s nicht finden" msgid "%s: %s requires %s" msgstr "%s: %s benötigt %s" -#: backup_label.c:162 reconstruct.c:748 write_manifest.c:262 +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 #, c-format msgid "could not write file \"%s\": wrote %d of %d" msgstr "konnte Datei »%s« nicht schreiben: %d von %d geschrieben" -#: backup_label.c:166 copy_file.c:142 copy_file.c:189 reconstruct.c:708 -#: reconstruct.c:754 write_manifest.c:270 +#: backup_label.c:166 copy_file.c:160 copy_file.c:207 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 #, c-format msgid "could not update checksum of file \"%s\"" msgstr "konnte Prüfsumme der Datei »%s« nicht aktualisieren" -#: copy_file.c:182 +#: copy_file.c:200 #, c-format msgid "could not write to file \"%s\": %m" msgstr "konnte nicht in Datei »%s« schreiben: %m" -#: copy_file.c:184 +#: copy_file.c:202 #, c-format msgid "could not write to file \"%s\", offset %u: wrote %d of %d" msgstr "konnte nicht in Datei »%s«, Position %u schreiben: %d von %d geschrieben" -#: copy_file.c:195 reconstruct.c:771 +#: copy_file.c:213 reconstruct.c:784 #, c-format msgid "could not read from file \"%s\": %m" msgstr "konnte nicht aus Datei »%s« lesen: %m" -#: copy_file.c:214 +#: copy_file.c:232 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %m" msgstr "Fehler beim Klonen von Datei »%s« nach »%s«: %m" -#: copy_file.c:222 copy_file.c:262 +#: copy_file.c:243 copy_file.c:286 #, c-format msgid "could not create file \"%s\": %m" msgstr "konnte Datei »%s« nicht erstellen: %m" -#: copy_file.c:230 +#: copy_file.c:251 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %s" msgstr "Fehler beim Klonen von Datei »%s« nach »%s«: %s" -#: copy_file.c:235 pg_combinebackup.c:239 +#: copy_file.c:259 pg_combinebackup.c:256 #, c-format msgid "file cloning not supported on this platform" msgstr "Klonen von Dateien wird auf dieser Plattform nicht unterstützt" -#: copy_file.c:268 reconstruct.c:691 +#: copy_file.c:292 reconstruct.c:704 #, c-format msgid "error while copying file range from \"%s\" to \"%s\": %m" msgstr "Fehler beim Kopieren von Dateibereich von »%s« nach »%s«: %m" -#: copy_file.c:275 pg_combinebackup.c:252 reconstruct.c:711 +#: copy_file.c:299 pg_combinebackup.c:269 reconstruct.c:724 #, c-format msgid "copy_file_range not supported on this platform" msgstr "copy_file_range wird auf dieser Plattform nicht unterstützt" -#: copy_file.c:290 +#: copy_file.c:314 #, c-format msgid "could not copy file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht nach »%s« kopieren: %m" +#: copy_file.c:333 +#, c-format +msgid "could not create link from \"%s\" to \"%s\": %m" +msgstr "konnte Verknüpfung von »%s« nach »%s« nicht erzeugen: %m" + #: load_manifest.c:125 #, c-format msgid "file \"%s\" does not exist" @@ -539,147 +549,152 @@ msgstr "konnte Datei »%s« nicht lesen: %d von %lld gelesen" msgid "could not read file \"%s\": read %lld of %lld" msgstr "konnte Datei »%s« nicht lesen: %lld von %lld gelesen" -#: load_manifest.c:249 +#: load_manifest.c:248 #, c-format msgid "backup manifest version 1 does not support incremental backup" msgstr "Backup-Manifest Version 1 unterstützt kein inkrementelles Backup" -#: load_manifest.c:281 +#: load_manifest.c:280 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "doppelter Pfadname im Backup-Manifest: »%s«" -#: pg_combinebackup.c:208 pg_combinebackup.c:216 +#: pg_combinebackup.c:225 pg_combinebackup.c:233 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_combinebackup.c:215 +#: pg_combinebackup.c:232 #, c-format msgid "no input directories specified" msgstr "keine Eingabeverzeichnisse angegeben" -#: pg_combinebackup.c:221 +#: pg_combinebackup.c:238 #, c-format msgid "no output directory specified" msgstr "kein Ausgabeverzeichnis angegeben" -#: pg_combinebackup.c:289 +#: pg_combinebackup.c:306 #, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: Systemidentifikator im Manifest ist %llu, aber Kontrolldatei hat %llu" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: Systemidentifikator im Manifest ist %, aber Kontrolldatei hat %" -#: pg_combinebackup.c:328 +#: pg_combinebackup.c:345 #, c-format -msgid "can't generate a manifest because no manifest is available for the final input backup" +msgid "cannot generate a manifest because no manifest is available for the final input backup" msgstr "kann kein Manifest erzeugen, weil kein Manifest für das letzte Eingabe-Backup verfügbar ist" -#: pg_combinebackup.c:375 +#: pg_combinebackup.c:392 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "konnte symbolische Verknüpfung von »%s« nach »%s« nicht erzeugen: %m" -#: pg_combinebackup.c:387 pg_combinebackup.c:718 pg_combinebackup.c:914 +#: pg_combinebackup.c:404 pg_combinebackup.c:739 pg_combinebackup.c:937 #, c-format msgid "could not create directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" -#: pg_combinebackup.c:442 +#: pg_combinebackup.c:434 +#, c-format +msgid "--link mode was used; any modifications to the output directory might destructively modify input directories" +msgstr "Modus --link wurde verwendet; Änderungen am Ausgabeverzeichnis könnten die Eingabeverzeichnisse destruktiv verändern" + +#: pg_combinebackup.c:464 #, c-format msgid "directory name too long" msgstr "Verzeichnisname zu lang" -#: pg_combinebackup.c:449 +#: pg_combinebackup.c:471 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "mehrere »=«-Zeichen im Tablespace-Mapping" -#: pg_combinebackup.c:457 +#: pg_combinebackup.c:479 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "ungültiges Tablespace-Mapping-Format »%s«, muss »ALTES_VERZ=NEUES_VERZ« sein" -#: pg_combinebackup.c:468 pg_combinebackup.c:472 +#: pg_combinebackup.c:490 pg_combinebackup.c:494 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "altes Verzeichnis im Tablespace-Mapping ist kein absoluter Pfad: %s" -#: pg_combinebackup.c:541 +#: pg_combinebackup.c:563 #, c-format msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" msgstr "Backup in »%s« ist ein volles Backup, aber nur das erste Backup sollte ein volles Backup sein" -#: pg_combinebackup.c:544 +#: pg_combinebackup.c:566 #, c-format msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" msgstr "Backup in »%s« ist ein inkrementelles Backup, aber das erste Backup sollte ein volles Backup sein" -#: pg_combinebackup.c:547 +#: pg_combinebackup.c:569 #, c-format msgid "backup at \"%s\" starts on timeline %u, but expected %u" msgstr "Backup in »%s« startet auf Zeitleiste %u, aber %u wurde erwartet" -#: pg_combinebackup.c:550 +#: pg_combinebackup.c:572 #, c-format msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" msgstr "Backup in »%s« startet bei LSN %X/%X, aber %X/%X wurde erwartet" -#: pg_combinebackup.c:602 +#: pg_combinebackup.c:624 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRC ist falsch" -#: pg_combinebackup.c:606 +#: pg_combinebackup.c:628 #, c-format msgid "%s: unexpected control file version" msgstr "%s: unerwartete Kontrolldateiversion" -#: pg_combinebackup.c:613 +#: pg_combinebackup.c:635 #, c-format -msgid "%s: expected system identifier %llu, but found %llu" -msgstr "%s: Systemidentifikator %llu erwartet, aber %llu gefunden" +msgid "%s: expected system identifier %, but found %" +msgstr "%s: Systemidentifikator % erwartet, aber % gefunden" -#: pg_combinebackup.c:645 +#: pg_combinebackup.c:666 #, c-format msgid "only some backups have checksums enabled" msgstr "nur einige Sicherungen haben Prüfsummen aktiviert" -#: pg_combinebackup.c:646 +#: pg_combinebackup.c:667 #, c-format -msgid "disable, and optionally reenable, checksums on the output directory to avoid failures" -msgstr "schalten Sie für das Ausgabeverzeichnis Prüfsummen aus, und optional wieder an, um Fehler zu vermeiden" +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "Schalten Sie für das Ausgabeverzeichnis Prüfsummen aus, und optional wieder an, um Fehler zu vermeiden." -#: pg_combinebackup.c:681 +#: pg_combinebackup.c:702 #, c-format msgid "removing output directory \"%s\"" msgstr "Ausgabeverzeichnis »%s« wird entfernt" -#: pg_combinebackup.c:683 +#: pg_combinebackup.c:704 #, c-format msgid "failed to remove output directory" msgstr "konnte Ausgabeverzeichnis nicht entfernen" -#: pg_combinebackup.c:687 +#: pg_combinebackup.c:708 #, c-format msgid "removing contents of output directory \"%s\"" msgstr "entferne Inhalt des Ausgabeverzeichnisses »%s«" -#: pg_combinebackup.c:690 +#: pg_combinebackup.c:711 #, c-format msgid "failed to remove contents of output directory" msgstr "konnte Inhalt des Ausgabeverzeichnisses nicht entfernen" -#: pg_combinebackup.c:730 +#: pg_combinebackup.c:751 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "Verzeichnis »%s« existiert aber ist nicht leer" -#: pg_combinebackup.c:733 +#: pg_combinebackup.c:754 #, c-format msgid "could not access directory \"%s\": %m" msgstr "konnte nicht auf Verzeichnis »%s« zugreifen: %m" -#: pg_combinebackup.c:747 +#: pg_combinebackup.c:768 #, c-format msgid "" "%s reconstructs full backups from incrementals.\n" @@ -688,17 +703,17 @@ msgstr "" "%s rekonstruiert volle Backups aus inkrementellen.\n" "\n" -#: pg_combinebackup.c:748 +#: pg_combinebackup.c:769 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_combinebackup.c:749 +#: pg_combinebackup.c:770 #, c-format msgid " %s [OPTION]... DIRECTORY...\n" msgstr " %s [OPTION]... VERZEICHNIS...\n" -#: pg_combinebackup.c:750 +#: pg_combinebackup.c:771 #, c-format msgid "" "\n" @@ -707,29 +722,34 @@ msgstr "" "\n" "Optionen:\n" -#: pg_combinebackup.c:751 +#: pg_combinebackup.c:772 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug erzeuge eine Menge Debug-Ausgaben\n" -#: pg_combinebackup.c:752 +#: pg_combinebackup.c:773 +#, c-format +msgid " -k, --link link files instead of copying\n" +msgstr " -k, --link Dateien verknüpfen statt kopieren\n" + +#: pg_combinebackup.c:774 #, c-format msgid " -n, --dry-run do not actually do anything\n" msgstr " -n, --dry-run nichts wirklich ausführen\n" -#: pg_combinebackup.c:753 +#: pg_combinebackup.c:775 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n" " geschrieben sind\n" -#: pg_combinebackup.c:754 +#: pg_combinebackup.c:776 #, c-format msgid " -o, --output=DIRECTORY output directory\n" msgstr " -o, --output=VERZEICHNIS Ausgabeverzeichnis\n" -#: pg_combinebackup.c:755 +#: pg_combinebackup.c:777 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -738,17 +758,22 @@ msgstr "" " -T, --tablespace-mapping=ALTES_VERZ=NEUES_VERZ\n" " Tablespace in ALTES_VERZ nach NEUES_VERZ verlagern\n" -#: pg_combinebackup.c:757 +#: pg_combinebackup.c:779 #, c-format -msgid " --clone clone (reflink) instead of copying files\n" +msgid " --clone clone (reflink) files instead of copying\n" msgstr " --clone Dateien klonen (reflink) statt kopieren\n" -#: pg_combinebackup.c:758 +#: pg_combinebackup.c:780 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy Dateien kopieren (Voreinstellung)\n" + +#: pg_combinebackup.c:781 #, c-format -msgid " --copy-file-range copy using copy_file_range() syscall\n" +msgid " --copy-file-range copy using copy_file_range() system call\n" msgstr " --copy-file-range mit Systemaufruf copy_file_range() kopieren\n" -#: pg_combinebackup.c:759 +#: pg_combinebackup.c:782 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -757,29 +782,29 @@ msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " Algorithmus für Manifest-Prüfsummen\n" -#: pg_combinebackup.c:761 +#: pg_combinebackup.c:784 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest Erzeugen des Backup-Manifests unterbinden\n" -#: pg_combinebackup.c:762 +#: pg_combinebackup.c:785 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHODE Methode zum Synchronisieren vond Dateien auf\n" " Festplatte setzen\n" -#: pg_combinebackup.c:763 +#: pg_combinebackup.c:786 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_combinebackup.c:764 +#: pg_combinebackup.c:787 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_combinebackup.c:766 +#: pg_combinebackup.c:789 #, c-format msgid "" "\n" @@ -788,107 +813,107 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: pg_combinebackup.c:767 +#: pg_combinebackup.c:790 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: pg_combinebackup.c:982 +#: pg_combinebackup.c:1005 #, c-format msgid "skipping symbolic link \"%s\"" msgstr "überspringe symbolische Verknüpfung »%s«" -#: pg_combinebackup.c:984 +#: pg_combinebackup.c:1007 #, c-format msgid "skipping special file \"%s\"" msgstr "überspringe besondere Datei »%s«" -#: pg_combinebackup.c:1060 +#: pg_combinebackup.c:1083 reconstruct.c:305 #, c-format -msgid "\"%s\" contains no entry for \"%s\"" -msgstr "»%s« enthält keinen Eintrag für »%s«" +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "Manifestdatei »%s« enthält keinen Eintrag für Datei »%s«" -#: pg_combinebackup.c:1176 +#: pg_combinebackup.c:1199 #, c-format msgid "%s: server version too old" msgstr "%s: Serverversion zu alt" -#: pg_combinebackup.c:1177 +#: pg_combinebackup.c:1200 #, c-format msgid "%s: could not parse version number" msgstr "%s: konnte Versionsnummer nicht parsen" -#: pg_combinebackup.c:1296 +#: pg_combinebackup.c:1319 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "konnte symbolische Verknüpfung »%s« nicht lesen: %m" -#: pg_combinebackup.c:1299 +#: pg_combinebackup.c:1322 #, c-format msgid "target of symbolic link \"%s\" is too long" msgstr "Ziel der symbolischen Verknüpfung »%s« ist zu lang" -#: pg_combinebackup.c:1302 +#: pg_combinebackup.c:1325 #, c-format msgid "target of symbolic link \"%s\" is relative" msgstr "Ziel der symbolischen Verknüpfung »%s« ist relativ" -#: pg_combinebackup.c:1324 +#: pg_combinebackup.c:1347 #, c-format msgid "tablespace at \"%s\" has no tablespace mapping" msgstr "Tablespace in »%s« hat kein Tablespace-Mapping" -#: pg_combinebackup.c:1342 +#: pg_combinebackup.c:1365 #, c-format msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" msgstr "die Tablespaces mit OIDs %u und %u zeigen beide auf Verzeichnis »%s«" -#: pg_combinebackup.c:1351 +#: pg_combinebackup.c:1374 #, c-format msgid "could not close directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht schließen: %m" -#: pg_combinebackup.c:1372 +#: pg_combinebackup.c:1395 #, c-format msgid "file \"%s\" is too large" msgstr "Datei »%s« ist zu groß" -#: pg_combinebackup.c:1389 +#: pg_combinebackup.c:1412 #, c-format msgid "could not read file \"%s\": read %zd of %lld" msgstr "konnte Datei »%s« nicht lesen: %zd von %lld gelesen" -#: reconstruct.c:300 +#: reconstruct.c:339 #, c-format -msgid "manifest file \"%s\" contains no entry for file \"%s\"" -msgstr "Manifestdatei »%s« enthält keinen Eintrag für Datei »%s«" +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "volles Backup enthält unerwartete inkrementelle Datei »%s«" -#: reconstruct.c:410 +#: reconstruct.c:423 #, c-format msgid "file \"%s\" is too short: expected %llu, found %llu" msgstr "Datei »%s« ist zu kurz: %llu erwartet, %llu gefunden" -#: reconstruct.c:452 +#: reconstruct.c:465 #, c-format -msgid "file \"%s\" has bad incremental magic number (0x%x not 0x%x)" -msgstr "Datei »%s« hat falsche magische Zahl für inkrementelles Backup (0x%x, nicht 0x%x)" +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "Datei »%s« hat falsche inkrementelle magische Zahl (0x%x, erwartet 0x%x)" -#: reconstruct.c:458 +#: reconstruct.c:471 #, c-format msgid "file \"%s\" has block count %u in excess of segment size %u" msgstr "Datei »%s« hat Blockzahl %u, was die Segmentgröße %u überschreitet" -#: reconstruct.c:465 +#: reconstruct.c:478 #, c-format msgid "file \"%s\" has truncation block length %u in excess of segment size %u" msgstr "Datei »%s« hat Truncation-Blocklänge %u, was die Segmentgröße %u überschreitet" -#: reconstruct.c:529 +#: reconstruct.c:542 #, c-format msgid "could not read file \"%s\": read %d of %u" msgstr "konnte Datei »%s« nicht lesen: %d von %u gelesen" -#: reconstruct.c:773 +#: reconstruct.c:786 #, c-format msgid "could not read from file \"%s\", offset %llu: read %d of %d" msgstr "konnte nicht aus Datei »%s«, Position %llu lesen: %d von %d gelesen" diff --git a/src/bin/pg_combinebackup/po/es.po b/src/bin/pg_combinebackup/po/es.po new file mode 100644 index 0000000000000..850ef3dde2a0e --- /dev/null +++ b/src/bin/pg_combinebackup/po/es.po @@ -0,0 +1,900 @@ +# Spanish translation file for pg_combinebackup +# +# Copyright (c) 2024, PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# +# Alvaro Herrera , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-11-16 05:22+0000\n" +"PO-Revision-Date: 2024-11-16 09:07+0100\n" +"Last-Translator: Álvaro Herrera \n" +"Language-Team: PgSQL-es-Ayuda \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: BlackCAT 1.1\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "error: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "precaución: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "detalle: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "consejo: " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "no se pudo cerrar el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"posible discordancia en orden de bytes\n" +"El ordenamiento de bytes usado para almacenar el archivo pg_control puede no\n" +"coincidir con el usado por este programa. En tal caso los resultados de abajo\n" +"serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" +"directorio de datos." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "no se pudo escribir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#, c-format +msgid "out of memory" +msgstr "memoria agotada" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "éxito" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "el búfer de destino es demasiado pequeño" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "falla de openSSL" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "El parser recursivo descendiente no puede usar el lexer incremental." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "El parser incremental requiere el lexer incremental." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON anidado demasiado profundamente, profundidad máxima es 6400." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "La secuencia de escape «\\%.*s» no es válida." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "Los caracteres con valor 0x%02x deben ser escapados." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Se esperaba el fin de la entrada, se encontró «%.*s»." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Se esperaba un elemento de array o «]», se encontró «%.*s»." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Se esperaba «,» o «]», se encontró «%.*s»." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Se esperaba «:», se encontró «%.*s»." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Se esperaba un valor JSON, se encontró «%.*s»." + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "La cadena de entrada terminó inesperadamente." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Se esperaba una cadena o «}», se encontró «%.*s»." + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Se esperaba «,» o «}», se encontró «%.*s»." + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "Se esperaba una cadena, se encontró «%.*s»." + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "El elemento «%.*s» no es válido." + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 no puede ser convertido a text." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "«\\u» debe ser seguido por cuatro dígitos hexadecimales." + +#: ../../common/jsonapi.c:2169 +msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." +msgstr "Los valores de escape Unicode no se pueden utilizar para valores de código superiores a 007F cuando la codificación no es UTF8." + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "Unicode escape value could not be translated to the server's encoding %s." +msgstr "El valor de escape Unicode no pudo ser traducido a la codificación del servidor %s." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "Un «high-surrogate» Unicode no puede venir después de un «high-surrogate»." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "Un «low-surrogate» Unicode debe seguir a un «high-surrogate»." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "no se pudo inicializar la suma de verificación del manifiesto" + +#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +msgid "manifest ended unexpectedly" +msgstr "el manifiesto terminó inesperadamente" + +#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#, c-format +msgid "could not update checksum of manifest" +msgstr "no se pudo actualizar la suma de verificación del manifiesto" + +#: ../../common/parse_manifest.c:302 +msgid "unexpected object start" +msgstr "inicio de objeto inesperado" + +#: ../../common/parse_manifest.c:337 +msgid "unexpected object end" +msgstr "fin de objeto inesperado" + +#: ../../common/parse_manifest.c:366 +msgid "unexpected array start" +msgstr "inicio de array inesperado" + +#: ../../common/parse_manifest.c:391 +msgid "unexpected array end" +msgstr "fin de array inesperado" + +#: ../../common/parse_manifest.c:418 +msgid "expected version indicator" +msgstr "se esperaba indicador de versión" + +#: ../../common/parse_manifest.c:454 +msgid "unrecognized top-level field" +msgstr "campo de nivel superior no reconocido" + +#: ../../common/parse_manifest.c:473 +msgid "unexpected file field" +msgstr "campo de archivo inesperado" + +#: ../../common/parse_manifest.c:487 +msgid "unexpected WAL range field" +msgstr "campo de rango de WAL inesperado" + +#: ../../common/parse_manifest.c:493 +msgid "unexpected object field" +msgstr "campo de objeto inesperado" + +#: ../../common/parse_manifest.c:583 +msgid "unexpected scalar" +msgstr "escalar inesperado" + +#: ../../common/parse_manifest.c:609 +msgid "manifest version not an integer" +msgstr "la versión de manifiesto no es un número entero" + +#: ../../common/parse_manifest.c:613 +msgid "unexpected manifest version" +msgstr "versión de manifiesto inesperada" + +#: ../../common/parse_manifest.c:637 +msgid "system identifier in manifest not an integer" +msgstr "el identificador de sistema en el manifiesto no es un número entero" + +#: ../../common/parse_manifest.c:662 +msgid "missing path name" +msgstr "ruta de archivo faltante" + +#: ../../common/parse_manifest.c:665 +msgid "both path name and encoded path name" +msgstr "hay ambos ruta de archivo (path name) y ruta codificada (encoded path name)" + +#: ../../common/parse_manifest.c:667 +msgid "missing size" +msgstr "tamaño faltante" + +#: ../../common/parse_manifest.c:670 +msgid "checksum without algorithm" +msgstr "suma de comprobación sin algoritmo" + +#: ../../common/parse_manifest.c:684 +msgid "could not decode file name" +msgstr "no se pudo decodificar el nombre del archivo" + +#: ../../common/parse_manifest.c:694 +msgid "file size is not an integer" +msgstr "el tamaño del archivo no es un número entero" + +#: ../../common/parse_manifest.c:700 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "algoritmo de suma de comprobación no reconocido: \"%s\"" + +#: ../../common/parse_manifest.c:719 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "suma de comprobación no válida para el archivo \"%s\": \"%s\"" + +#: ../../common/parse_manifest.c:762 +msgid "missing timeline" +msgstr "falta el timeline" + +#: ../../common/parse_manifest.c:764 +msgid "missing start LSN" +msgstr "falta el LSN de inicio" + +#: ../../common/parse_manifest.c:766 +msgid "missing end LSN" +msgstr "falta el LSN de término" + +#: ../../common/parse_manifest.c:772 +msgid "timeline is not an integer" +msgstr "el timeline no es un número entero" + +#: ../../common/parse_manifest.c:775 +msgid "could not parse start LSN" +msgstr "no se pudo interpretar el LSN de inicio" + +#: ../../common/parse_manifest.c:778 +msgid "could not parse end LSN" +msgstr "no se pudo interpretar el LSN de término" + +#: ../../common/parse_manifest.c:843 +msgid "expected at least 2 lines" +msgstr "esperado al menos 2 líneas" + +#: ../../common/parse_manifest.c:846 +msgid "last line not newline-terminated" +msgstr "última línea no termina en nueva línea" + +#: ../../common/parse_manifest.c:865 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "no se pudo finalizar la suma de verificación del manifiesto" + +#: ../../common/parse_manifest.c:869 +#, c-format +msgid "manifest has no checksum" +msgstr "el manifiesto no tiene suma de comprobación" + +#: ../../common/parse_manifest.c:873 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "suma de comprobación de manifiesto no válida: \"%s\"" + +#: ../../common/parse_manifest.c:877 +#, c-format +msgid "manifest checksum mismatch" +msgstr "discordancia en la suma de comprobación del manifiesto" + +#: ../../common/parse_manifest.c:892 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "no se pudo analizar el manifiesto de la copia de seguridad: %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "el valor «%s» no es válido para la opción %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s debe estar en el rango %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método de sync no reconocido: %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s: no se pudo interpretar %s" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s: terminador inapropiado para %s" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s: no se pudo interpretar el TLI para %s" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s: TLI no válido" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s: no se pudo encontrar %s" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s: %s requiere %s" + +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "no se pudo escribir al archivo «%s»: se escribió %d de %d" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "no se pudo actualizar la suma de verificación para el archivo «%s»" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "no se pudo escribir a archivo «%s»: %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "no se pudo escribir al archivo «%s», posición %u: se escribió %d de %d" + +#: copy_file.c:199 reconstruct.c:784 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "error mientras se clonaba el archivo «%s» a «%s»: %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "no se pudo crear archivo «%s»: %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "error mientras se clonaba la relación «%s» a «%s»: %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "el clonado de archivos no está soportado en esta plataforma" + +#: copy_file.c:278 reconstruct.c:704 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "error mientras se copiaba un rango de archivo de «%s» a «%s»: %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:724 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range no está soportado en esta plataforma" + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "no se pudo copiar el archivo de «%s» a «%s»: %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "el archivo «%s» no existe" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %lld" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "no se pudo leer el archivo «%s»: leídos %lld de %lld" + +#: load_manifest.c:249 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "el manifiesto de backup versión 1 no soporta backups incrementales" + +#: load_manifest.c:281 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "nombre de ruta duplicado en el manifiesto de la copia de seguridad: \"%s\"" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Pruebe «%s --help» para mayor información." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "no se especificó un directorio de entrada" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "no se especificó un directorio de salida" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: el identificador de sistema del manifiesto es %llu, pero el archivo de control tiene %llu" + +#: pg_combinebackup.c:340 +#, c-format +msgid "cannot generate a manifest because no manifest is available for the final input backup" +msgstr "no se puede generar un manifiesto porque no hay un manifiesto disponible para el backup final de entrada" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "no se pudo crear un enlace simbólico desde «%s» a «%s»: %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "no se pudo crear el directorio «%s»: %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "nombre de directorio demasiado largo" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "múltiples signos «=» en mapeo de tablespace" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "formato de mapeo de tablespace «%s» no válido, debe ser «ANTIGUO=NUEVO»" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "directorio antiguo no es una ruta absoluta en mapeo de tablespace: %s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" +msgstr "el backup en «%s» es un backup full, pero sólo el primer backup puede ser full" + +#: pg_combinebackup.c:556 +#, c-format +msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" +msgstr "el backup en «%s» es incremental, pero el primer backup debería ser full" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "el backup en «%s» empieza en el timeline %u, pero se esperaba %u" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "el backup en «%s» empieza en el LSN %X/%X, pero se esperaba %X/%X" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s: el valor de CRC es incorrecto" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s: versión de archivo de control inesperado" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s: se esperaba identificador de sistema %llu, pero se encontró %llu" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "sólo algunos backups tienen checksums activados" + +#: pg_combinebackup.c:658 +#, c-format +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "Desactive (y opcionalmente reactive) los checksums en el directorio de salida para evitar fallos." + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "eliminando el directorio de salida «%s»" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "no se pudo eliminar el directorio de salida" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "eliminando el contenido del directorio de salida «%s»" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "no se pudo eliminar el contenido del directorio de salida" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "el directorio «%s» existe pero no está vacío" + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "no se pudo acceder al directorio «%s»: %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "" +"%s reconstructs full backups from incrementals.\n" +"\n" +msgstr "" +"%s reconstruye backups full desde incrementales.\n" +"\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "Empleo:\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [OPCIÓN]... DIRECTOTIO...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Opciones:\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug genera mucha salida de depuración\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr " -n, --dry-run no hacer realmente nada\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" +msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=DIR directorio de salida\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr "" +" -T, --tablespace-mapping=ANTIGUO=NUEVO\n" +" reubicar el tablespace de ANTIGUO a NUEVO\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr " --clone clonar (reflink) archivos en vez de copiarlos\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy copiar archivos (por omisión)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr " --copy-file-range copiar usando la llamada copy_file_range()\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" usar algoritmo para checksums del manifiesto\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest suprimir generación del manifiesto\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método para sincronizar archivos a disco\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de version y salir\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda y salir\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Reporte errores a <%s>.\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Sitio web de %s: <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "omitiendo el link simbólico «%s»" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "omitiendo el archivo especial «%s»" + +#: pg_combinebackup.c:1073 reconstruct.c:305 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "el archivo de manifiesto «%s» no contiene una entrada para el archivo «%s»" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s: versión de servidor demasiado antigua" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s: no se pudo interpretar el número de versión" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "no se pudo leer el enlace simbólico «%s»: %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "el destino del enlace simbólico «%s» es demasiado largo" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "el destino del enlace simbólico «%s» es relativo" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "el tablespace en «%s» no tiene mapeo de tablespace" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "los tablespaces con OIDs %u y %u ambos apuntan al directorio «%s»" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "el archivo «%s» es demasiado grande" + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "no se pudo leer el archivo «%s»: leídos %zd de %lld" + +#: reconstruct.c:339 +#, c-format +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "backup «full» contiene archivo incremental «%s» inesperado" + +#: reconstruct.c:423 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "el archivo «%s» es demasiado corto: se esperaban %llu, se encontraron %llu" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "el archivo «%s» tiene número mágico incremental erróneo (0x%x, se esperaba 0x%x)" + +#: reconstruct.c:471 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "el archivo «%s» tiene una cantidad de bloques %u más allá del tamaño de bloque %u" + +#: reconstruct.c:478 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "el archivo «%s» tiene una longitud de truncado de bloque %u en exceso del tamaño de segmento %u" + +#: reconstruct.c:542 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %u" + +#: reconstruct.c:786 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "no se pudo leer del archivo \"%s\", posición %llu: leídos %d de %d" diff --git a/src/bin/pg_combinebackup/po/fr.po b/src/bin/pg_combinebackup/po/fr.po new file mode 100644 index 0000000000000..aa8b0f4ea61f8 --- /dev/null +++ b/src/bin/pg_combinebackup/po/fr.po @@ -0,0 +1,900 @@ +# LANGUAGE message translation file for pg_combinebackup +# Copyright (C) 2024 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_combinebackup (PostgreSQL) package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-11-11 01:52+0000\n" +"PO-Revision-Date: 2024-11-11 09:55+0100\n" +"Last-Translator: Guillaume Lelarge \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.5\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "erreur : " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "attention : " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "détail : " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "astuce : " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"possible incohérence dans l'ordre des octets\n" +"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n" +"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n" +"résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" +"est incompatible avec ce répertoire des données." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "impossible d'écrire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#, c-format +msgid "out of memory" +msgstr "mémoire épuisée" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "succès" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "tampon de destination trop petit" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "échec OpenSSL" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "L'analyseur (parser) en descente récursive ne peut pas utiliser l'analyseur (lexer) incrémental." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "L'analyser (parser) incrémental nécessite l'analyseur (lexer) incrémental." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON trop profondément imbriqué, profondeur maximum permise est 6400." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "La séquence d'échappement « \\%.*s » est invalide." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "Le caractère de valeur 0x%02x doit être échappé." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Fin de l'entrée attendue, mais trouvé « %.*s »." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Élément de tableau ou « ] » attendu, mais trouvé « %.*s »." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "« , » ou « ] » attendu, mais trouvé « %.*s »." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "« : » attendu, mais trouvé « %.*s »." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Valeur JSON attendue, mais « %.*s » trouvé." + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "La chaîne en entrée se ferme de manière inattendue." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Chaîne ou « } » attendu, mais « %.*s » trouvé." + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "« , » ou « } » attendu, mais trouvé « %.*s »." + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "Chaîne attendue, mais « %.*s » trouvé." + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "Le jeton « %.*s » n'est pas valide." + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 ne peut pas être converti en texte." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "« \\u » doit être suivi par quatre chiffres hexadécimaux." + +#: ../../common/jsonapi.c:2169 +msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." +msgstr "Les valeurs d'échappement Unicode ne peuvent pas être utilisées pour des valeurs de point code au-dessus de 007F quand l'encodage n'est pas UTF8." + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "Unicode escape value could not be translated to the server's encoding %s." +msgstr "La valeur d'échappement unicode ne peut pas être traduite dans l'encodage du serveur %s." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "Une substitution unicode haute ne doit pas suivre une substitution haute." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "Une substitution unicode basse ne doit pas suivre une substitution haute." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "n'a pas pu initialiser la somme de contrôle du manifeste" + +#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +msgid "manifest ended unexpectedly" +msgstr "le manifeste se termine de façon inattendue" + +#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#, c-format +msgid "could not update checksum of manifest" +msgstr "n'a pas pu mettre à jour la somme de contrôle du manifeste" + +#: ../../common/parse_manifest.c:302 +msgid "unexpected object start" +msgstr "début d'objet inattendu" + +#: ../../common/parse_manifest.c:337 +msgid "unexpected object end" +msgstr "fin d'objet inattendue" + +#: ../../common/parse_manifest.c:366 +msgid "unexpected array start" +msgstr "début de tableau inattendu" + +#: ../../common/parse_manifest.c:391 +msgid "unexpected array end" +msgstr "fin de tableau inattendue" + +#: ../../common/parse_manifest.c:418 +msgid "expected version indicator" +msgstr "indicateur de version inattendu" + +#: ../../common/parse_manifest.c:454 +msgid "unrecognized top-level field" +msgstr "champ haut niveau inconnu" + +#: ../../common/parse_manifest.c:473 +msgid "unexpected file field" +msgstr "champ de fichier inattendu" + +#: ../../common/parse_manifest.c:487 +msgid "unexpected WAL range field" +msgstr "champ d'intervalle de WAL inattendu" + +#: ../../common/parse_manifest.c:493 +msgid "unexpected object field" +msgstr "champ d'objet inattendu" + +#: ../../common/parse_manifest.c:583 +msgid "unexpected scalar" +msgstr "scalaire inattendu" + +#: ../../common/parse_manifest.c:609 +msgid "manifest version not an integer" +msgstr "la version du manifeste n'est pas un entier" + +#: ../../common/parse_manifest.c:613 +msgid "unexpected manifest version" +msgstr "version du manifeste inattendue" + +#: ../../common/parse_manifest.c:637 +msgid "system identifier in manifest not an integer" +msgstr "l'identifieur système dans le manifeste n'est pas un entier" + +#: ../../common/parse_manifest.c:662 +msgid "missing path name" +msgstr "nom de chemin manquant" + +#: ../../common/parse_manifest.c:665 +msgid "both path name and encoded path name" +msgstr "le nom du chemin et le nom du chemin encodé" + +#: ../../common/parse_manifest.c:667 +msgid "missing size" +msgstr "taille manquante" + +#: ../../common/parse_manifest.c:670 +msgid "checksum without algorithm" +msgstr "somme de contrôle sans algorithme" + +#: ../../common/parse_manifest.c:684 +msgid "could not decode file name" +msgstr "n'a pas pu décoder le nom du fichier" + +#: ../../common/parse_manifest.c:694 +msgid "file size is not an integer" +msgstr "la taille du fichier n'est pas un entier" + +#: ../../common/parse_manifest.c:700 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "algorithme de somme de contrôle inconnu : « %s »" + +#: ../../common/parse_manifest.c:719 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "somme de contrôle invalide pour le fichier « %s » : « %s »" + +#: ../../common/parse_manifest.c:762 +msgid "missing timeline" +msgstr "timeline manquante" + +#: ../../common/parse_manifest.c:764 +msgid "missing start LSN" +msgstr "LSN de début manquante" + +#: ../../common/parse_manifest.c:766 +msgid "missing end LSN" +msgstr "LSN de fin manquante" + +#: ../../common/parse_manifest.c:772 +msgid "timeline is not an integer" +msgstr "la timeline n'est pas un entier" + +#: ../../common/parse_manifest.c:775 +msgid "could not parse start LSN" +msgstr "n'a pas pu analyser le LSN de début" + +#: ../../common/parse_manifest.c:778 +msgid "could not parse end LSN" +msgstr "n'a pas pu analyser le LSN de fin" + +#: ../../common/parse_manifest.c:843 +msgid "expected at least 2 lines" +msgstr "attendait au moins deux lignes" + +#: ../../common/parse_manifest.c:846 +msgid "last line not newline-terminated" +msgstr "dernière ligne non terminée avec un caractère newline" + +#: ../../common/parse_manifest.c:865 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "n'a pas pu finaliser la somme de contrôle du manifeste" + +#: ../../common/parse_manifest.c:869 +#, c-format +msgid "manifest has no checksum" +msgstr "le manifeste n'a pas de somme de contrôle" + +#: ../../common/parse_manifest.c:873 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "somme de contrôle du manifeste invalide : « %s »" + +#: ../../common/parse_manifest.c:877 +#, c-format +msgid "manifest checksum mismatch" +msgstr "différence de somme de contrôle pour le manifeste" + +#: ../../common/parse_manifest.c:892 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "n'a pas pu analyser le manifeste de sauvegarde : %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "valeur « %s » invalide pour l'option %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s doit être compris entre %d et %d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s : n'a pas pu analyser %s" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s : mauvais terminateur pour %s" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s : n'a pas pu analyser le TLI pour %s" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s : TLI invalide" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s : n'a pas pu trouver %s" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s : %s requiert %s" + +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "n'a pas pu écrire le fichier « %s » : a écrit %d sur %d" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "n'a pas pu mettre à jour la somme de contrôle du fichier « %s »" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "n'a pas pu écrire dans le fichier « %s » : %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "n'a pas pu écrire dans le fichier « %s », à la position %u : a écrit %d sur %d" + +#: copy_file.c:199 reconstruct.c:784 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "n'a pas pu lire à partir du fichier « %s » : %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "erreur lors du clonage du fichier « %s » en «%s » : %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "n'a pas pu créer le fichier « %s » : %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "erreur lors du clonage du fichier « %s » en «%s » : %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "clonage de fichiers non supporté sur cette plateforme" + +#: copy_file.c:278 reconstruct.c:704 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "erreur lors de l'opération copy_file_range de « %s » à « %s » : %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:724 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range non supporté sur cette plateforme" + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu copier le fichier « %s » en « %s » : %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "le rôle « %s » n'existe pas" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %lld" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "n'a pas pu lire le fichier « %s » : a lu %lld sur %lld" + +#: load_manifest.c:249 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "la version du manifeste de sauvegarde ne permet pas les sauvegardes incrémentales" + +#: load_manifest.c:281 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "nom de chemin dupliqué dans le manifeste de sauvegarde : « %s »" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Essayez « %s --help » pour plus d'informations." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "aucun répertoire en entrée indiqué" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "aucun répertoire cible indiqué" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: l'identifieur système du manifeste est %llu, mais le fichier de contrôle a %llu" + +#: pg_combinebackup.c:340 +#, c-format +msgid "cannot generate a manifest because no manifest is available for the final input backup" +msgstr "ne peut pas générer un manifeste parce qu'aucun manifeste n'est disponible pour la sauvegarde finale en entrée" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "n'a pas pu créer le lien symbolique de « %s » vers « %s » : %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "n'a pas pu créer le répertoire « %s » : %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "nom du répertoire trop long" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "multiple signes « = » dans la correspondance de tablespace" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "format de correspondance de tablespace « %s » invalide, doit être « ANCIENREPERTOIRE=NOUVEAUREPERTOIRE »" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "l'ancien répertoire n'est pas un chemin absolu dans la correspondance de tablespace : %s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" +msgstr "la sauvegarde à « %s » est une sauvegarde complète, mais seule la première sauvegarde devrait être une sauvegarde complète" + +#: pg_combinebackup.c:556 +#, c-format +msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" +msgstr "la sauvegarde à « %s » est une sauvegarde incrémentale, mais la première sauvegarde devrait être une sauvegarde complète" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "la sauvegarde à « %s » commence à la timeline %u, mais attendait %u" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "la sauvegarde à « %s » commence au LSN %X/%X, mais s'attendait à %X/%X" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s : la valeur CRC n'est pas correcte" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s : version inattendue pour le fichier de contrôle" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s : identifieur système attendu %llu, mais %llu trouvé" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "seules certaines sauvegardes ont les sommes de contrôle activées" + +#: pg_combinebackup.c:658 +#, c-format +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "Désactivez, puis activez si vous le souhaitez, les sommes de contrôle sur le répertoire en sortie pour éviter les échecs" + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "suppression du répertoire en sortie « %s »" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "échec lors de la suppression du répertoire en sortie" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "suppression du contenu du répertoire en sortie « %s »" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "échec lors de la suppression du contenu du répertoire en sortie" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "le répertoire « %s » existe mais n'est pas vide" + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "n'a pas pu accéder au répertoire « %s » : %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "" +"%s reconstructs full backups from incrementals.\n" +"\n" +msgstr "" +"%s reconstruit des sauvegardes complètes à partir de sauvegardes incrémentales.\n" +"\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "Usage :\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [OPTION]... RÉPERTOIRE...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Options :\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug engendre un grand nombre de traces de débogage\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr " -n, --dry-run ne fait rien\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" +msgstr "" +" -N, --nosync n'attend pas que les modifications soient\n" +" proprement écrites sur disque\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=RÉPERTOIRE répertoire en sortie\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr "" +" -T, --tablespace-mapping=ANCIENREP=NOUVEAUREP\n" +" déplace le tablespace de ANCIENREP vers NOUVEAUREP\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr " --clone clone (reflink) les fichiers au lieu de les copier\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy copie les fichiers (par défaut)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr " --copy-file-range copie les fichiers en utilisant la fonction système copy_file_range()\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" utilise l'algorithme pour les sommes de contrôle du manifeste\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest ne génère pas de manifeste de sauvegarde\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Rapporter les bogues à <%s>.\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Page d'accueil de %s : <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "ignore le lien symbolique « %s »" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "ignore le fichier spécial « %s »" + +#: pg_combinebackup.c:1073 reconstruct.c:305 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "le fichier manifeste « %s » ne contient aucune entrée pour le fichier « %s »" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s : version trop ancienne du serveur" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s : n'a pas pu analyser le numéro de version" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "n'a pas pu lire le lien symbolique « %s » : %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "la cible « %s » du lien symbolique est trop longue" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "la cible « %s » du lien symbolique est relative" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "le tablespace sur \"%s\" n'a pas de correspondance de tablespace" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "les tablespaces d'OID %u et %u pointent tous les deux au répertoire « %s »" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "n'a pas pu fermer le répertoire « %s » : %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "le fichier « %s » est trop gros" + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "n'a pas pu lire le fichier « %s » : a lu %zd sur %lld" + +#: reconstruct.c:339 +#, c-format +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "la sauvegarde complète contient un fichier incrémental inattendu « %s »" + +#: reconstruct.c:423 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "le fichier « %s » est trop court : attendait %llu, a trouvé %llu" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "le fichier « %s » a un mauvaise numéro magique incrémental (0x%x et non pas 0x%x)" + +#: reconstruct.c:471 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "le fichier « %s » a %u blocs en plus de la taille de segment %u" + +#: reconstruct.c:478 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "le fichier « %s » a une longueur de bloc %u pour la troncation en excès de la taille de segment %u" + +#: reconstruct.c:542 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %u" + +#: reconstruct.c:786 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "n'a pas pu lire le fichier « %s » à la position %llu : a lu %d sur %d" diff --git a/src/bin/pg_combinebackup/po/ja.po b/src/bin/pg_combinebackup/po/ja.po index 3ae33d2f69045..627c4213b2467 100644 --- a/src/bin/pg_combinebackup/po/ja.po +++ b/src/bin/pg_combinebackup/po/ja.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Project-Id-Version: pg_combinebackup (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 17:48+0900\n" -"PO-Revision-Date: 2024-06-24 10:03+0900\n" +"POT-Creation-Date: 2025-03-31 09:53+0900\n" +"PO-Revision-Date: 2025-03-31 16:40+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: \n" "Language: ja\n" @@ -17,22 +17,22 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " @@ -42,8 +42,8 @@ msgstr "ヒント: " msgid "could not open file \"%s\" for reading: %m" msgstr "ファイル\"%s\"を読み込み用にオープンできませんでした: %m" -#: ../../common/controldata_utils.c:110 copy_file.c:146 load_manifest.c:161 -#: load_manifest.c:199 pg_combinebackup.c:1387 reconstruct.c:527 +#: ../../common/controldata_utils.c:110 copy_file.c:164 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1409 reconstruct.c:540 #, c-format msgid "could not read file \"%s\": %m" msgstr "ファイル\"%s\"の読み込みに失敗しました: %m" @@ -54,8 +54,8 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: backup_label.c:174 copy_file.c:64 pg_combinebackup.c:526 -#: pg_combinebackup.c:1162 reconstruct.c:356 reconstruct.c:727 +#: backup_label.c:174 copy_file.c:71 pg_combinebackup.c:547 +#: pg_combinebackup.c:1184 reconstruct.c:369 reconstruct.c:740 #: write_manifest.c:187 #, c-format msgid "could not close file \"%s\": %m" @@ -78,31 +78,32 @@ msgstr "" "されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" "PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:62 -#: copy_file.c:135 copy_file.c:167 copy_file.c:171 copy_file.c:218 -#: copy_file.c:258 load_manifest.c:128 pg_combinebackup.c:511 -#: pg_combinebackup.c:1154 reconstruct.c:510 reconstruct.c:625 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 backup_label.c:143 copy_file.c:69 +#: copy_file.c:153 copy_file.c:185 copy_file.c:189 copy_file.c:239 +#: copy_file.c:282 load_manifest.c:128 pg_combinebackup.c:532 +#: pg_combinebackup.c:1176 reconstruct.c:523 reconstruct.c:638 #: write_manifest.c:250 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:746 +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 #: write_manifest.c:260 #, c-format msgid "could not write file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" #: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 #, c-format msgid "out of memory" msgstr "メモリ不足です" @@ -131,290 +132,294 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "nullポインタは複製できません(内部エラー)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 -#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:664 -#: pg_combinebackup.c:1118 pg_combinebackup.c:1370 reconstruct.c:199 -#: reconstruct.c:408 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:684 +#: pg_combinebackup.c:1140 pg_combinebackup.c:1392 reconstruct.c:204 +#: reconstruct.c:421 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 -#: pg_combinebackup.c:920 pg_combinebackup.c:1243 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_combinebackup.c:942 pg_combinebackup.c:1265 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" -#: ../../common/jsonapi.c:2121 +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "再帰降下パーサーは差分字句解析器を使用できません。" -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "差分パーサーは差分字句解析器を必要とします。" -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSONのネストが深すぎます、可能な最大の深さは6400です。" -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "エスケープシーケンス\"\\%.*s\"は不正です。" -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "0x%02x値を持つ文字はエスケープしなければなりません" -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "入力の終端を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "配列要素または\"]\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "\",\"または\"]\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "\":\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "JSON値を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "入力文字列が予期せず終了しました。" -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "文字列または\"}\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "\",\"または\"}\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "文字列を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "トークン\"\\%.*s\"は不正です。" -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 はテキストに変換できません。" -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\"の後には16進数の4桁が続かなければなりません。" -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "エンコーディングがUTF-8ではない場合、コードポイントの値が 007F 以上についてはUnicodeエスケープの値は使用できません。" -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Unicodeエスケープの値がサーバーエンコーディング%sに変換できませんでした。" -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicodeのハイサロゲートはハイサロゲートに続いてはいけません。" -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicodeのローサロゲートはハイサロゲートに続かなければなりません。" -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "エラー記述の構築中にメモリ不足" + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "目録のチェックサムの初期化ができませんでした" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "目録が予期せず終了しました。" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "目録のチェックサムの更新ができませんでした" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "予期しないオブジェクトの開始" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "予期しないオブジェクトの終わり" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "予期しない配列の開始" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "予期しない配列の終わり" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "バージョン指示子を想定していました" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "認識できないトップレベルフィールド" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "予期しないファイルフィールド" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "予期しないWAL範囲フィールド" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "予期しないオブジェクトフィールド" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "予期しないスカラー" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "目録バージョンが整数ではありません" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "予期しない目録バージョン" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" -msgstr "目録のシステム識別子が整数ではありません" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "目録中のシステム識別子が整数ではありません" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "パス名がありません" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "パス名とエンコードされたパス名の両方" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "サイズがありません" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "アルゴリズムなしのチェックサム" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ファイル名をデコードできませんでした" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ファイルサイズが整数ではありません" -#: ../../common/parse_manifest.c:700 pg_combinebackup.c:190 +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:203 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "認識できないチェックサムアルゴリズム: \"%s\"" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "\"%s\" ファイルのチェックサムが無効: \"%s\"" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "タイムラインがありません" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "開始LSNがありません" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "終了LSNがありません" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "タイムラインが整数ではありません" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "開始LSNをパースできませんでした" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "終了LSNをパースできませんでした" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "少なくとも2行が必要です" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "最後の行が改行で終わっていません" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "目録のチェックサムの完了ができませんでした" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "目録にチェックサムがありません" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "無効な目録チェックサム: \"%s\"" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "目録チェックサムの不一致" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "バックアップ目録をパースできませんでした: %s" @@ -464,67 +469,72 @@ msgstr "%s: %sが見つかりませんでした" msgid "%s: %s requires %s" msgstr "%s: %sは%sを必要とします" -#: backup_label.c:162 reconstruct.c:748 write_manifest.c:262 +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 #, c-format msgid "could not write file \"%s\": wrote %d of %d" msgstr "ファイル\"%1$s\"の書き込みができませんでした: %3$dバイト中%2$dバイト書き込みました" -#: backup_label.c:166 copy_file.c:142 copy_file.c:189 reconstruct.c:708 -#: reconstruct.c:754 write_manifest.c:270 +#: backup_label.c:166 copy_file.c:160 copy_file.c:207 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 #, c-format msgid "could not update checksum of file \"%s\"" msgstr "ファイル\"%s\"のチェックサムの更新ができませんでした" -#: copy_file.c:182 +#: copy_file.c:200 #, c-format msgid "could not write to file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: copy_file.c:184 +#: copy_file.c:202 #, c-format msgid "could not write to file \"%s\", offset %u: wrote %d of %d" msgstr "ファイル \"%1$s\"、オフセット%2$uで書き込みができませんでした: %4$dバイト中%3$dバイト書き込みました" -#: copy_file.c:195 reconstruct.c:771 +#: copy_file.c:213 reconstruct.c:784 #, c-format msgid "could not read from file \"%s\": %m" msgstr "ファイル\"%s\"から読み取れませんでした: %m" -#: copy_file.c:214 +#: copy_file.c:232 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の\"%s\"へのクローニング中のエラー: %m" -#: copy_file.c:222 copy_file.c:262 +#: copy_file.c:243 copy_file.c:286 #, c-format msgid "could not create file \"%s\": %m" msgstr "ファイル\"%s\"を作成できませんでした: %m" -#: copy_file.c:230 +#: copy_file.c:251 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %s" msgstr "ファイル\"%s\"の\"%s\"へのクローニング中のエラー: %s" -#: copy_file.c:235 pg_combinebackup.c:239 +#: copy_file.c:259 pg_combinebackup.c:255 #, c-format msgid "file cloning not supported on this platform" msgstr "このプラットフォームではファイルのクローンはサポートされません" -#: copy_file.c:268 reconstruct.c:691 +#: copy_file.c:292 reconstruct.c:704 #, c-format msgid "error while copying file range from \"%s\" to \"%s\": %m" msgstr "\"%s\"の\"%s\"へのファイル範囲のコピー中のエラー: %m" -#: copy_file.c:275 pg_combinebackup.c:252 reconstruct.c:711 +#: copy_file.c:299 pg_combinebackup.c:268 reconstruct.c:724 #, c-format msgid "copy_file_range not supported on this platform" msgstr "このプラットフォームではcopy_file_rangeはサポートされません" -#: copy_file.c:290 +#: copy_file.c:314 #, c-format msgid "could not copy file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"を\"%s\"にコピーできませんでした: %m" +#: copy_file.c:333 +#, c-format +msgid "error while linking file from \"%s\" to \"%s\": %m" +msgstr "\"%s\"から\"%s\"へのリンク作成中にエラーが発生しました: %m" + #: load_manifest.c:125 #, c-format msgid "file \"%s\" does not exist" @@ -540,147 +550,152 @@ msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイト msgid "could not read file \"%s\": read %lld of %lld" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイトのうち%2$lldバイトを読み込みました" -#: load_manifest.c:249 +#: load_manifest.c:248 #, c-format msgid "backup manifest version 1 does not support incremental backup" msgstr "バックアップ目録のバージョン1は差分バックアップをサポートしていません" -#: load_manifest.c:281 +#: load_manifest.c:280 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "バックアップ目録内の重複パス名: \"%s\"" -#: pg_combinebackup.c:208 pg_combinebackup.c:216 +#: pg_combinebackup.c:224 pg_combinebackup.c:232 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_combinebackup.c:215 +#: pg_combinebackup.c:231 #, c-format msgid "no input directories specified" msgstr "入力ディレクトリが指定されていません" -#: pg_combinebackup.c:221 +#: pg_combinebackup.c:237 #, c-format msgid "no output directory specified" msgstr "出力ディレクトリが指定されていません" -#: pg_combinebackup.c:289 +#: pg_combinebackup.c:305 #, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: 目録のシステム識別子が%lluですが、制御ファイルでは%lluです" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: 目録のシステム識別子が%ですが、制御ファイルでは%です" -#: pg_combinebackup.c:328 +#: pg_combinebackup.c:344 #, c-format -msgid "can't generate a manifest because no manifest is available for the final input backup" +msgid "cannot generate a manifest because no manifest is available for the final input backup" msgstr "最後の入力バックアップに目録がないため目録を生成できません" -#: pg_combinebackup.c:375 +#: pg_combinebackup.c:391 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "\"%s\"から\"%s\"へのシンボリックリンクを作成できませんでした: %m" -#: pg_combinebackup.c:387 pg_combinebackup.c:718 pg_combinebackup.c:914 +#: pg_combinebackup.c:403 pg_combinebackup.c:738 pg_combinebackup.c:936 #, c-format msgid "could not create directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" -#: pg_combinebackup.c:442 +#: pg_combinebackup.c:433 +#, c-format +msgid "--link mode was used; any modifications to the output directory may destructively modify input directories" +msgstr "--link モードが使用されています。出力ディレクトリに変更を加えると、入力ディレクトリが破壊的に変更される可能性があります。" + +#: pg_combinebackup.c:463 #, c-format msgid "directory name too long" msgstr "ディレクトリ名が長すぎます" -#: pg_combinebackup.c:449 +#: pg_combinebackup.c:470 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "テーブル空間のマッピングに複数の\"=\"記号があります" -#: pg_combinebackup.c:457 +#: pg_combinebackup.c:478 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "テーブル空間のマッピング形式\"%s\"が不正です。\"旧DIR=新DIR\"でなければなりません" -#: pg_combinebackup.c:468 pg_combinebackup.c:472 +#: pg_combinebackup.c:489 pg_combinebackup.c:493 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "テーブル空間のマッピングにおいて、旧ディレクトリが絶対パスではありません: %s" -#: pg_combinebackup.c:541 +#: pg_combinebackup.c:562 #, c-format msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" msgstr "\"%s\"のバックアップはフルバックアップですが、最初のバックアップのみがフルバックアップである必要があります" -#: pg_combinebackup.c:544 +#: pg_combinebackup.c:565 #, c-format msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" msgstr "\"%s\"のバックアップは差分バックアップですが、最初のバックアップはフルバックアップである必要があります" -#: pg_combinebackup.c:547 +#: pg_combinebackup.c:568 #, c-format msgid "backup at \"%s\" starts on timeline %u, but expected %u" msgstr "\"%s\"のバックアップはタイムライン%uで始まっていますが、%uを期待していました" -#: pg_combinebackup.c:550 +#: pg_combinebackup.c:571 #, c-format msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" msgstr "\"%s\"のバックアップはLSN %X/%Xで始まっていますが、%X/%Xを期待していました" -#: pg_combinebackup.c:602 +#: pg_combinebackup.c:623 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRCが正しくありません" -#: pg_combinebackup.c:606 +#: pg_combinebackup.c:627 #, c-format msgid "%s: unexpected control file version" msgstr "%s: 予期しない制御ファイルバージョン" -#: pg_combinebackup.c:613 +#: pg_combinebackup.c:634 #, c-format -msgid "%s: expected system identifier %llu, but found %llu" -msgstr "%s: システム識別子 %llu を予期していましたが、%llu でした" +msgid "%s: expected system identifier %, but found %" +msgstr "%s: システム識別子 % を予期していましたが、% でした" -#: pg_combinebackup.c:645 +#: pg_combinebackup.c:665 #, c-format msgid "only some backups have checksums enabled" msgstr "一部のバックアップのみチェックサムが有効化されています" -#: pg_combinebackup.c:646 +#: pg_combinebackup.c:666 #, c-format -msgid "disable, and optionally reenable, checksums on the output directory to avoid failures" -msgstr "失敗を防止するためには出力先ディレクトリでのチェックサムを無効にして、必要に応じて再度有効にしてください" +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "失敗を防止するためには出力先ディレクトリでのチェックサムを無効にして、必要に応じて再度有効にしてください。" -#: pg_combinebackup.c:681 +#: pg_combinebackup.c:701 #, c-format msgid "removing output directory \"%s\"" msgstr "出力ディレクトリ\"%s\"を削除しています" -#: pg_combinebackup.c:683 +#: pg_combinebackup.c:703 #, c-format msgid "failed to remove output directory" msgstr "出力ディレクトリの削除に失敗しました" -#: pg_combinebackup.c:687 +#: pg_combinebackup.c:707 #, c-format msgid "removing contents of output directory \"%s\"" msgstr "出力ディレクトリ\"%s\"の内容の削除中" -#: pg_combinebackup.c:690 +#: pg_combinebackup.c:710 #, c-format msgid "failed to remove contents of output directory" msgstr "出力ディレクトリの内容の削除に失敗しました" -#: pg_combinebackup.c:730 +#: pg_combinebackup.c:750 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "ディレクトリ\"%s\"は存在しますが、空ではありません" -#: pg_combinebackup.c:733 +#: pg_combinebackup.c:753 #, c-format msgid "could not access directory \"%s\": %m" msgstr "ディレクトリ\"%s\"にアクセスできませんでした: %m" -#: pg_combinebackup.c:747 +#: pg_combinebackup.c:767 #, c-format msgid "" "%s reconstructs full backups from incrementals.\n" @@ -689,17 +704,17 @@ msgstr "" "%s 差分からフルバックアップを再構築する。\n" "\n" -#: pg_combinebackup.c:748 +#: pg_combinebackup.c:768 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_combinebackup.c:749 +#: pg_combinebackup.c:769 #, c-format msgid " %s [OPTION]... DIRECTORY...\n" msgstr " %s [オプション]... ディレクトリ...\n" -#: pg_combinebackup.c:750 +#: pg_combinebackup.c:770 #, c-format msgid "" "\n" @@ -708,27 +723,32 @@ msgstr "" "\n" "オプション:\n" -#: pg_combinebackup.c:751 +#: pg_combinebackup.c:771 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug 多くのデバッグ用の出力を生成\n" -#: pg_combinebackup.c:752 +#: pg_combinebackup.c:772 +#, c-format +msgid " -k, --link link files instead of copying\n" +msgstr " -k, --link コピーする代わりにリンクを作成する\n" + +#: pg_combinebackup.c:773 #, c-format msgid " -n, --dry-run do not actually do anything\n" msgstr " -n, --dry-run 実際には何もしない\n" -#: pg_combinebackup.c:753 +#: pg_combinebackup.c:774 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync 変更の安全なディスクへの書き出しを待機しない\n" -#: pg_combinebackup.c:754 +#: pg_combinebackup.c:775 #, c-format msgid " -o, --output=DIRECTORY output directory\n" msgstr " -o, --output=DIRECTORY 出力ディレクトリ\n" -#: pg_combinebackup.c:755 +#: pg_combinebackup.c:776 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -737,19 +757,24 @@ msgstr "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" " OLDDIRにあるテーブルスペースをNEWDIRへ移動\n" -#: pg_combinebackup.c:757 +#: pg_combinebackup.c:778 #, c-format -msgid " --clone clone (reflink) instead of copying files\n" +msgid " --clone clone (reflink) files instead of copying\n" msgstr "" -" --clone ファイルコピーではなくクローニング(またはreflink)を\n" -" 行う\n" +" --clone ファイルをコピーする代わりにクローニング(reflink)\n" +" を行う\n" -#: pg_combinebackup.c:758 +#: pg_combinebackup.c:779 #, c-format -msgid " --copy-file-range copy using copy_file_range() syscall\n" +msgid " --copy copy files (default)\n" +msgstr " --copy ファイルをコピーする(デフォルト)\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" msgstr " --copy-file-range copy_file_range()システムコールでコピーする\n" -#: pg_combinebackup.c:759 +#: pg_combinebackup.c:781 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -758,27 +783,27 @@ msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " 目録チェックサムのアルゴリズムを指定\n" -#: pg_combinebackup.c:761 +#: pg_combinebackup.c:783 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest バックアップマニフェストの生成を抑止\n" -#: pg_combinebackup.c:762 +#: pg_combinebackup.c:784 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=METHOD ファイルをディスクに同期させる方法を指定\n" -#: pg_combinebackup.c:763 +#: pg_combinebackup.c:785 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_combinebackup.c:764 +#: pg_combinebackup.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_combinebackup.c:766 +#: pg_combinebackup.c:788 #, c-format msgid "" "\n" @@ -787,107 +812,107 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_combinebackup.c:767 +#: pg_combinebackup.c:789 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: pg_combinebackup.c:982 +#: pg_combinebackup.c:1004 #, c-format msgid "skipping symbolic link \"%s\"" msgstr "シンボリックリンク\"%s\"をスキップします" -#: pg_combinebackup.c:984 +#: pg_combinebackup.c:1006 #, c-format msgid "skipping special file \"%s\"" msgstr "スペシャルファイル\"%s\"をスキップしています" -#: pg_combinebackup.c:1060 +#: pg_combinebackup.c:1082 reconstruct.c:305 #, c-format -msgid "\"%s\" contains no entry for \"%s\"" -msgstr "\"%s\" には\"%s\"のエントリがありません" +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "目録ファイル\"%s\" にはファイル\"%s\"のエントリがありません" -#: pg_combinebackup.c:1176 +#: pg_combinebackup.c:1198 #, c-format msgid "%s: server version too old" msgstr "%s: サーバーバージョンが古すぎます" -#: pg_combinebackup.c:1177 +#: pg_combinebackup.c:1199 #, c-format msgid "%s: could not parse version number" msgstr "%s: バージョン番号をパースできませんでした" -#: pg_combinebackup.c:1296 +#: pg_combinebackup.c:1318 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "シンボリックリンク\"%s\"を読めませんでした: %m" -#: pg_combinebackup.c:1299 +#: pg_combinebackup.c:1321 #, c-format msgid "target of symbolic link \"%s\" is too long" msgstr "シンボリックリンク\"%s\"のターゲットが長すぎます" -#: pg_combinebackup.c:1302 +#: pg_combinebackup.c:1324 #, c-format msgid "target of symbolic link \"%s\" is relative" msgstr "シンボリックリンク\"%s\"のターゲットが相対的です" -#: pg_combinebackup.c:1324 +#: pg_combinebackup.c:1346 #, c-format msgid "tablespace at \"%s\" has no tablespace mapping" msgstr "\"%s\"にあるテーブルスペースに対応するテーブルスペースマッピングがありません" -#: pg_combinebackup.c:1342 +#: pg_combinebackup.c:1364 #, c-format msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" msgstr "OID %uと%uのテーブルスペースがどちらもディレクトリ\"%s\"を指しています" -#: pg_combinebackup.c:1351 +#: pg_combinebackup.c:1373 #, c-format msgid "could not close directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" -#: pg_combinebackup.c:1372 +#: pg_combinebackup.c:1394 #, c-format msgid "file \"%s\" is too large" msgstr "ファイル\"%s\"は大きすぎます" -#: pg_combinebackup.c:1389 +#: pg_combinebackup.c:1411 #, c-format msgid "could not read file \"%s\": read %zd of %lld" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイトのうち%2$zdバイトを読み込みました" -#: reconstruct.c:300 +#: reconstruct.c:339 #, c-format -msgid "manifest file \"%s\" contains no entry for file \"%s\"" -msgstr "目録ファイル\"%s\" にはファイル\"%s\"のエントリがありません" +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "フルバックアップに予期しない差分ファイル\"%s\"が含まれています" -#: reconstruct.c:410 +#: reconstruct.c:423 #, c-format msgid "file \"%s\" is too short: expected %llu, found %llu" msgstr "ファイル\"%s\"が短すぎます: %lluを期待していましたが%lluでした" -#: reconstruct.c:452 +#: reconstruct.c:465 #, c-format -msgid "file \"%s\" has bad incremental magic number (0x%x not 0x%x)" -msgstr "ファイル\"%1$s\"の差分マジックナンバーが正しくありません (0x%3$xではなく0x%2$xでした)" +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "ファイル\"%1$s\"の差分マジックナンバーが正しくありません (0x%3$xを期待していましたが0x%2$xでした)" -#: reconstruct.c:458 +#: reconstruct.c:471 #, c-format msgid "file \"%s\" has block count %u in excess of segment size %u" msgstr "ファイル\"%s\"のブロック数%uがセグメントサイズ%uを超えています" -#: reconstruct.c:465 +#: reconstruct.c:478 #, c-format msgid "file \"%s\" has truncation block length %u in excess of segment size %u" msgstr "ファイル\"%s\"の切り詰めブロック長%uがセグメントサイズ%uを超えています" -#: reconstruct.c:529 +#: reconstruct.c:542 #, c-format msgid "could not read file \"%s\": read %d of %u" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$uバイトのうち%2$dバイトを読み込みました" -#: reconstruct.c:773 +#: reconstruct.c:786 #, c-format msgid "could not read from file \"%s\", offset %llu: read %d of %d" msgstr "ファイル \"%1$s\"、オフセット%2$lluから読み取れませんでした: %4$d中%3$d" diff --git a/src/bin/pg_combinebackup/po/ka.po b/src/bin/pg_combinebackup/po/ka.po index 294257800ba65..9aa8952078c75 100644 --- a/src/bin/pg_combinebackup/po/ka.po +++ b/src/bin/pg_combinebackup/po/ka.po @@ -5,38 +5,121 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Project-Id-Version: pg_combinebackup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-04 22:22+0000\n" -"PO-Revision-Date: 2024-06-05 01:39+0200\n" +"POT-Creation-Date: 2025-05-02 22:22+0000\n" +"PO-Revision-Date: 2025-05-03 01:27+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: \n" "Language: ka\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:164 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1410 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:71 pg_combinebackup.c:548 +#: pg_combinebackup.c:1185 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ფაილის (%s) დახურვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "ბაიტების მიმდევრობა არ ემთხვევა" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"ბაიტების მიმდევრობის შესაძლო შეუსაბამობა pg_control ფაილის შესანახად გამოყენებული \n" +"ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" +"მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 backup_label.c:143 copy_file.c:69 +#: copy_file.c:153 copy_file.c:185 copy_file.c:189 copy_file.c:239 +#: copy_file.c:282 load_manifest.c:128 pg_combinebackup.c:533 +#: pg_combinebackup.c:1177 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "არასაკმარისი მეხსიერება" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "წარმატება" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "სამიზნე ბუფერი ძალიან პატარაა" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "OpenSSL -ის სეცდომა" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,264 +131,313 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/jsonapi.c:2121 +#: ../../common/file_utils.c:75 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" + +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:685 +#: pg_combinebackup.c:1141 pg_combinebackup.c:1393 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" + +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_combinebackup.c:943 pg_combinebackup.c:1266 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/file_utils.c:520 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "გადარქმევის შეცდომა %s - %s: %m" + +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "რეკურსიულ დაღმავალ დამმუშავებელს ინკრემენტული lexer-ის გამოყენება არ შეუძლია." -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "ინკრემენტულ დამმუშავებელს ინკრემენტული lexer სჭირდება." -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSON მეტისმეტად ღრმადაა ერთმანეთში ჩალაგებული. მაქსიმალური დასაშვები სიღრმეა 6400." -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "სპეციალური მიმდევრობა \"\\%.*s\" არასწორია." -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "სიმბოლო კოდით 0x%02x აუცილებლად ეკრანირებული უნდა იყოს." -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "მოველოდი შეყვანის დასასრულს, მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "მოველოდი მასივის ელემენტს ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "მოველოდი \",\" ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "მოველოდი \":\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "მოველოდი JSON მნიშვნელობას. მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "შეყვანის სტრიქონი მოულოდნელად დასრულდა." -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "მოველოდი სტრიქონს ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "მოველოდი \",\", ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "მოველოდი სტრიქონს, მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "კოდი \"%.*s\" არასწორია." -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 ტექსტად ვერ გარდაიქმნება." -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\" ს თექვსმეტობითი ციფრები უნდა მოჰყვებოდეს." -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "უნიკოდის სპეციალური კოდების გამოყენება კოდის წერტილის მნიშვნელობებად 007F-ის ზემოთ შეუძლებელია, თუ კოდირება UTF-8 არაა." -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "უნიკოდის სპეციალური კოდების სერვერის კოდირებაში (%s) თარგმნა შეუძლებელია." -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "უნიკოდის მაღალ სუროგატს მაღალი სუროგატი არ უნდა მოსდევდეს." -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "უნიკოდის დაბალი სუროგატი მაღალ სუროგატს უნდა მისდევდეს." -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 -#, c-format -msgid "out of memory" -msgstr "არასაკმარისი მეხსიერება" +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "არასაკმარისი მეხსიერება შეცდომის აღწერის აგებისას" -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის ინიციალიზაციის შეცდომა" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "მანიფესტი მოულოდნელად დასრულდა" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის განახლების შეცდომა" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "ობიექტის მოულოდნელი დასაწყისი" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "ობიექტის მოულოდნელი დასასრული" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "მასივის მოულოდნელი დასაწყისი" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "მასივის მოულოდნელი დასასრული" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "მოსალოდნელი ვერსიის მაჩვენებელი" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "უცნობი ველი ზედა დონეზე" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "მოულოდნელი ველი ფაილისთვის" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "მოულოდნელი ველი WAL-ის დიაპაზონისთვის" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "ობიექტის მოულოდნელი ველი" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "მოულოდნელი სკალარი" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "მანიფესტის ვერსია მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "მანიფესტის მოულოდნელი ვერსია" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" msgstr "მანიფესტის სისტემის იდენფიტიკატორი მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "აკლია ბილიკის სახელი" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "ორივე, ბილიკის სახელი და ბილიკის კოდირებული სახელი" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "ზომა აკლია" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "საკონტროლო ჯამი ალგორითმის გარეშე" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ფაილის სახელის გაშიფვრის შეცდომა" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ფაილის ზომა მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:700 pg_combinebackup.c:190 +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:204 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "საკონტროლო ჯამის უცნობი ალგორითმი: \"%s\"" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "არასწორი საკონტროლო ჯამი ფაილისთვის \"%s\": \"%s\"" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "აკლია დროის ხაზი" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "აკლია საწყისი LSN" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "აკლია დასასრულის LSN" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "დროის ხაზი მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "საწყისი LSN-ის დამუშავების შეცდომა" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "საბოლოო LSN-ის დამუშავების შეცდომა" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "ველოდებოდი სულ ცოტა 2 ხაზს" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "ბოლო ხაზი ხაზის გადატანით არ სრულდება" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის დასრულების შეცდომა" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "მანიფესტის საკონტროლო ჯამი არ გააჩნია" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "მანიფესტის საკონტროლო ჯამის არასწორია: %s" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "მანიფესტის საკონტროლო ჯამი არ ემთხვევა" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "მარქაფის მანიფესტის დამუშავების შეცრომა: %s" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "არასწორი მნიშვნელობა \"%s\" პარამეტრისთვის %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s არაა საზღვრებში %d-დან %d-მდე" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "უცნობი სინქრონიზაციის მეთოდი: \"%s\"" + #: backup_label.c:66 backup_label.c:85 backup_label.c:95 #, c-format msgid "%s: could not parse %s" @@ -336,97 +468,76 @@ msgstr "%s: %s ვერ ვიპოვე" msgid "%s: %s requires %s" msgstr "%s: %s-ს %s სჭირდება" -#: backup_label.c:143 copy_file.c:135 copy_file.c:167 copy_file.c:171 -#: copy_file.c:218 copy_file.c:258 load_manifest.c:128 pg_combinebackup.c:511 -#: pg_combinebackup.c:1154 reconstruct.c:511 reconstruct.c:626 -#: write_manifest.c:250 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" - -#: backup_label.c:160 copy_file.c:182 reconstruct.c:747 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" - -#: backup_label.c:162 reconstruct.c:749 write_manifest.c:262 +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 #, c-format -msgid "could not write file \"%s\": wrote only %d of %d bytes" -msgstr "ვერ ჩავწერე ფაილი \"%s\": ჩავწერე, მხოლოდ, %d ბაიტი %d-დან" +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "ფაილში \"%s\" ჩაწერა შეუძლებელია. ჩაწერილია %d %d-დან" -#: backup_label.c:166 copy_file.c:142 copy_file.c:189 reconstruct.c:709 -#: reconstruct.c:755 write_manifest.c:270 +#: backup_label.c:166 copy_file.c:160 copy_file.c:207 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 #, c-format msgid "could not update checksum of file \"%s\"" msgstr "ფაილის (\"%s\") საკონტროლო ჯამის განახლების შეცდომა" -#: backup_label.c:174 copy_file.c:64 pg_combinebackup.c:526 -#: pg_combinebackup.c:1162 reconstruct.c:357 reconstruct.c:728 -#: write_manifest.c:187 -#, c-format -msgid "could not close \"%s\": %m" -msgstr "\"%s\" ვერ დავხურე: %m" - -#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:1118 +#: copy_file.c:200 #, c-format -msgid "could not stat file \"%s\": %m" -msgstr "ფაილი \"%s\" არ არსებობს: %m" +msgid "could not write to file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: copy_file.c:62 +#: copy_file.c:202 #, c-format -msgid "could not open \"%s\": %m" -msgstr "\"%s\" ვერ გავხსენი: %m" +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "ფაილში \"%s\" ჩაწერის შეცდომა. წანაცვლება %u: ჩავწერე %d ბაიტი %d-დან" -#: copy_file.c:146 copy_file.c:195 load_manifest.c:161 load_manifest.c:199 -#: pg_combinebackup.c:1387 reconstruct.c:528 reconstruct.c:772 +#: copy_file.c:213 reconstruct.c:784 #, c-format -msgid "could not read file \"%s\": %m" -msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" +msgid "could not read from file \"%s\": %m" +msgstr "ფაილიდან (\"%s\") წაკითხვის შეცდომა: %m" -#: copy_file.c:184 -#, c-format -msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" -msgstr "ფაილში \"%s\" ჩაწერის შეცდომა: ჩავწერე მხოლოდ %d ბაიტი %d-დან , წანაცვლებაზე %u" - -#: copy_file.c:214 +#: copy_file.c:232 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %m" msgstr "შეცდომა ფაილის დაკლონვისას \"%s\"-დან \"%s\"-მდე: %m" -#: copy_file.c:222 copy_file.c:262 +#: copy_file.c:243 copy_file.c:286 #, c-format msgid "could not create file \"%s\": %m" msgstr "ფაილის (%s) შექმნის შეცდომა: %m" -#: copy_file.c:230 +#: copy_file.c:251 #, c-format msgid "error while cloning file \"%s\" to \"%s\": %s" msgstr "შეცდომა ფაილის დაკლონვისას \"%s\"-დან \"%s\"-მდე: %s" -#: copy_file.c:235 pg_combinebackup.c:239 +#: copy_file.c:259 pg_combinebackup.c:256 #, c-format msgid "file cloning not supported on this platform" msgstr "ამ პლატფორმაზე კლონირება მხარდაჭერილი არაა" -#: copy_file.c:268 reconstruct.c:692 +#: copy_file.c:292 reconstruct.c:704 #, c-format msgid "error while copying file range from \"%s\" to \"%s\": %m" msgstr "შეცდომა ფაილბის შუალედის კოპირებისას \"%s\"-დან \"%s\"-მდე: %m" -#: copy_file.c:275 pg_combinebackup.c:252 reconstruct.c:712 +#: copy_file.c:299 pg_combinebackup.c:269 reconstruct.c:724 #, c-format msgid "copy_file_range not supported on this platform" msgstr "ამ პლატფორმაზე copy_file_range მხარდაჭერილი არაა" -#: copy_file.c:290 +#: copy_file.c:314 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "ფაილის \"%s\"-დან \"%s\"-ში კოპირება შეუძლებელია: %m" + +#: copy_file.c:333 #, c-format -msgid "could not copy \"%s\" to \"%s\": %m" -msgstr "\"%s\"-დან \"%s\"-ში კოპირება შეუძლებელია: %m" +msgid "could not create link from \"%s\" to \"%s\": %m" +msgstr "\"%s\"-დან \"%s\"-მდე ბმულის შექმნა შეუძლებელია: %m" #: load_manifest.c:125 #, c-format -msgid "\"%s\" does not exist" -msgstr "\"%s\" არ არსებობს" +msgid "file \"%s\" does not exist" +msgstr "ფაილი %s არ არსებობს" #: load_manifest.c:163 #, c-format @@ -438,153 +549,152 @@ msgstr "ფაილის \"%s\" წაკითხვა შეუძლებ msgid "could not read file \"%s\": read %lld of %lld" msgstr "ფაილის \"%s\" წაკითხვა შეუძლებელია: წაკითხულია %lld %lld-დან" -#: load_manifest.c:249 +#: load_manifest.c:248 #, c-format msgid "backup manifest version 1 does not support incremental backup" msgstr "მარქაფის მანიფესტის ვერსიას 1 ინკრემენტული მარქაფების მხარდაჭერა არ გააჩნია" -#: load_manifest.c:281 +#: load_manifest.c:280 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "მარქაფს მანიფესტში მითითებული ბილიკის სახელი დუბლირებულია: %s" -#: pg_combinebackup.c:208 pg_combinebackup.c:216 +#: pg_combinebackup.c:225 pg_combinebackup.c:233 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_combinebackup.c:215 +#: pg_combinebackup.c:232 #, c-format -msgid "%s: no input directories specified" -msgstr "%s: შეყვანის საქაღალდეები მითითებული არაა" +msgid "no input directories specified" +msgstr "შეყვანის საქაღალდეები მითითებული არაა" -#: pg_combinebackup.c:221 +#: pg_combinebackup.c:238 #, c-format msgid "no output directory specified" msgstr "გამოტანის საქაღალდე მითითებული არაა" -#: pg_combinebackup.c:289 +#: pg_combinebackup.c:306 #, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: მანიფესტის სისტემის იდენტიფიკატორია %llu, მაგრამ კონტროლის ფაილი შეიცავს %llu" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: მანიფესტის სისტემის იდენტიფიკატორია %, მაგრამ კონტროლის ფაილი შეიცავს %-ს" -#: pg_combinebackup.c:328 +#: pg_combinebackup.c:345 #, c-format -msgid "can't generate a manifest because no manifest is available for the final input backup" +msgid "cannot generate a manifest because no manifest is available for the final input backup" msgstr "მანიფესტის გენერაცია შეუძლებელია, რადგან საბოლოო შეყვანის მარქაფისთვის მანიფესტი ხელმისაწვდომი არაა" -#: pg_combinebackup.c:375 +#: pg_combinebackup.c:392 #, c-format msgid "could not create symbolic link from \"%s\" to \"%s\": %m" msgstr "%s-დან %s-მდე სიმბმულის შექმნა შეუძლებელია: %m" -#: pg_combinebackup.c:387 pg_combinebackup.c:718 pg_combinebackup.c:914 +#: pg_combinebackup.c:404 pg_combinebackup.c:739 pg_combinebackup.c:937 #, c-format msgid "could not create directory \"%s\": %m" msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" -#: pg_combinebackup.c:442 +#: pg_combinebackup.c:434 +#, c-format +msgid "--link mode was used; any modifications to the output directory might destructively modify input directories" +msgstr "გამოყენებული იყო რეჟიმი --link. გამოტანის საქაღალდის ნებისმიერმა ცვლილებამ, შეიძლება, შეყვანის საქაღალდეები დამანგრევლად შეცვალოს" + +#: pg_combinebackup.c:464 #, c-format msgid "directory name too long" msgstr "საქაღალდის სახელი ძალიან გრძელია" -#: pg_combinebackup.c:449 +#: pg_combinebackup.c:471 #, c-format msgid "multiple \"=\" signs in tablespace mapping" msgstr "ცხრილების სივრცის მიბმაში ერთზე მეტი \"=\" ნიშანია" -#: pg_combinebackup.c:457 +#: pg_combinebackup.c:479 #, c-format msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" msgstr "ცხრილების მიბმის არასწორი ფორმატი \"%s\", უნდა იყოს \"OLDDIR=NEWDIR\"" -#: pg_combinebackup.c:468 pg_combinebackup.c:472 +#: pg_combinebackup.c:490 pg_combinebackup.c:494 #, c-format msgid "old directory is not an absolute path in tablespace mapping: %s" msgstr "ძველი საქაღალდის ბილიკი ცხრილის სივრცის მიბმაში აბსოლუტური არაა: %s" -#: pg_combinebackup.c:541 +#: pg_combinebackup.c:563 #, c-format msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" msgstr "მარქაფი მისამართზე \"%s\" სრული მარქაფია, მაგრამ, მხოლოდ, პირველი მარქაფი უნდა იყოს სრული" -#: pg_combinebackup.c:544 +#: pg_combinebackup.c:566 #, c-format msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" msgstr "მარქაფი მისამართზე \"%s\" ინკრემენტული მარქაფია, მაგრამ პირველი მარქაფი სრული უნდა იყოს" -#: pg_combinebackup.c:547 +#: pg_combinebackup.c:569 #, c-format msgid "backup at \"%s\" starts on timeline %u, but expected %u" msgstr "მარქაფი მისამართზე \"%s\" იწყება დროის ხაზზე %u, მაგრამ მოველოდი მნიშვნელობას %u" -#: pg_combinebackup.c:550 +#: pg_combinebackup.c:572 #, c-format msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" msgstr "მარქაფი მისამართზე \"%s\" იწყება LSN-თან %X/%X, მაგრამ მოველოდი მნიშვნელობას %X/%X" -#: pg_combinebackup.c:602 +#: pg_combinebackup.c:624 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRC არასწორია" -#: pg_combinebackup.c:606 +#: pg_combinebackup.c:628 #, c-format msgid "%s: unexpected control file version" msgstr "%s: მოულოდნელი საკონტროლო ფაილის ვერსია" -#: pg_combinebackup.c:613 +#: pg_combinebackup.c:635 #, c-format -msgid "%s: expected system identifier %llu, but found %llu" -msgstr "%s: მოველოდი სისტემის იდენტიფიკატორს %llu, ნაპოვნი მნიშვნელობაა %llu" +msgid "%s: expected system identifier %, but found %" +msgstr "%s: მოველოდი სისტემის იდენტიფიკატორს %, ნაპოვნი მნიშვნელობაა %" -#: pg_combinebackup.c:645 +#: pg_combinebackup.c:666 #, c-format msgid "only some backups have checksums enabled" msgstr "საკონტროლო ჯამები, მხოლოდ, ზოგიერთ მარქაფს ჰქონდა" -#: pg_combinebackup.c:646 -#, c-format -msgid "disable, and optionally reenable, checksums on the output directory to avoid failures" -msgstr "გამორთვა და არასავალდებულოდ თავიდან ჩართვა საკონტროლო ჯამებისა გამოტანის საქაღალდეზე, ჩავარდნების თავიდან ასაცილებლად" - -#: pg_combinebackup.c:664 pg_combinebackup.c:1370 reconstruct.c:199 -#: reconstruct.c:409 +#: pg_combinebackup.c:667 #, c-format -msgid "could not stat \"%s\": %m" -msgstr "\"%s\" ვერ აღმოვაჩინე: %m" +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "გამორთვა და არასავალდებულოდ თავიდან ჩართვა საკონტროლო ჯამებისა გამოტანის საქაღალდეზე, ჩავარდნების თავიდან ასაცილებლად." -#: pg_combinebackup.c:681 +#: pg_combinebackup.c:702 #, c-format msgid "removing output directory \"%s\"" msgstr "წაიშლება გამოტანის საქაღალდე \"%s\"" -#: pg_combinebackup.c:683 +#: pg_combinebackup.c:704 #, c-format msgid "failed to remove output directory" msgstr "გამოტანის საქაღალდის წაშლა ჩავარდა" -#: pg_combinebackup.c:687 +#: pg_combinebackup.c:708 #, c-format msgid "removing contents of output directory \"%s\"" msgstr "წაიშლება შემცველობა გამოტანის საქაღალდისთვის \"%s\"" -#: pg_combinebackup.c:690 +#: pg_combinebackup.c:711 #, c-format msgid "failed to remove contents of output directory" msgstr "გამოტანის საქაღალდის შემცველობის წაშლა ჩავარდა" -#: pg_combinebackup.c:730 +#: pg_combinebackup.c:751 #, c-format msgid "directory \"%s\" exists but is not empty" msgstr "საქაღალდე \"%s\" არსებობს, მაგრამ ცარიელი არაა" -#: pg_combinebackup.c:733 +#: pg_combinebackup.c:754 #, c-format msgid "could not access directory \"%s\": %m" msgstr "საქაღალდის (%s) წვდომის შეცდომა: %m" -#: pg_combinebackup.c:747 +#: pg_combinebackup.c:768 #, c-format msgid "" "%s reconstructs full backups from incrementals.\n" @@ -593,17 +703,17 @@ msgstr "" "%s სრული მარქაფების აგება ინკრემენტულებისგან.\n" "\n" -#: pg_combinebackup.c:748 +#: pg_combinebackup.c:769 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_combinebackup.c:749 +#: pg_combinebackup.c:770 #, c-format msgid " %s [OPTION]... DIRECTORY...\n" msgstr " %s [პარამეტრი]... საქაღალდე...\n" -#: pg_combinebackup.c:750 +#: pg_combinebackup.c:771 #, c-format msgid "" "\n" @@ -612,27 +722,32 @@ msgstr "" "\n" "პარამეტრები:\n" -#: pg_combinebackup.c:751 +#: pg_combinebackup.c:772 #, c-format msgid " -d, --debug generate lots of debugging output\n" msgstr " -d, --debug გასამართი ინფორმაციის გენერაცია\n" -#: pg_combinebackup.c:752 +#: pg_combinebackup.c:773 +#, c-format +msgid " -k, --link link files instead of copying\n" +msgstr " -k, --link ფაილებზე ბმულების შექმნა მათი კოპირების ნაცვლად\n" + +#: pg_combinebackup.c:774 #, c-format msgid " -n, --dry-run do not actually do anything\n" msgstr " -n, --dry-run არაფერი სინამდვილეში არ ქნა\n" -#: pg_combinebackup.c:753 +#: pg_combinebackup.c:775 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: pg_combinebackup.c:754 +#: pg_combinebackup.c:776 #, c-format -msgid " -o, --output output directory\n" -msgstr " -o, --output გამოტანის საქაღალდე\n" +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=საქაღალდე გამოტანის საქაღალდე\n" -#: pg_combinebackup.c:755 +#: pg_combinebackup.c:777 #, c-format msgid "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" @@ -641,17 +756,22 @@ msgstr "" " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" " ცხრილების სივრცის OLDDIR-დან NEWDIR-ში გადატანა\n" -#: pg_combinebackup.c:757 +#: pg_combinebackup.c:779 #, c-format -msgid " --clone clone (reflink) instead of copying files\n" +msgid " --clone clone (reflink) files instead of copying\n" msgstr " --clone ფაილების დაკლონვა (reflink) კოპირების ნაცვლად\n" -#: pg_combinebackup.c:758 +#: pg_combinebackup.c:780 #, c-format -msgid " --copy-file-range copy using copy_file_range() syscall\n" +msgid " --copy copy files (default)\n" +msgstr " --copy ფაილების კოპირება (ნაგულისხმევი)\n" + +#: pg_combinebackup.c:781 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" msgstr " --copy-file-range კოპირება სისტემური ფუნქციით copy_file_range()\n" -#: pg_combinebackup.c:759 +#: pg_combinebackup.c:782 #, c-format msgid "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" @@ -660,27 +780,27 @@ msgstr "" " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" " მანიფესტების საკონტროლო ჯამის გამოსათვლელი ალფორითმი\n" -#: pg_combinebackup.c:761 +#: pg_combinebackup.c:784 #, c-format msgid " --no-manifest suppress generation of backup manifest\n" msgstr " --no-manifest მარქაფის მანიფესტი არ შეიქმნება\n" -#: pg_combinebackup.c:762 +#: pg_combinebackup.c:785 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=მეთოდი ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: pg_combinebackup.c:763 +#: pg_combinebackup.c:786 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_combinebackup.c:764 +#: pg_combinebackup.c:787 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_combinebackup.c:766 +#: pg_combinebackup.c:789 #, c-format msgid "" "\n" @@ -689,116 +809,158 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_combinebackup.c:767 +#: pg_combinebackup.c:790 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: pg_combinebackup.c:920 pg_combinebackup.c:1243 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" - -#: pg_combinebackup.c:982 +#: pg_combinebackup.c:1005 #, c-format msgid "skipping symbolic link \"%s\"" msgstr "%s: სიმბმულია. გამოტოვება" -#: pg_combinebackup.c:984 +#: pg_combinebackup.c:1007 #, c-format msgid "skipping special file \"%s\"" msgstr "სპეციალური ფაილის გამოტოვება \"%s\"" -#. translator: the first %s is a backup manifest file, the second is a file absent therein -#: pg_combinebackup.c:1060 reconstruct.c:301 +#: pg_combinebackup.c:1083 reconstruct.c:305 #, c-format -msgid "\"%s\" contains no entry for \"%s\"" -msgstr "\"%s\" არ შეიცავს ჩანაწერს \"%s\"-სთვის" +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "მანიფესტის ფაილი \"%s\" ფაილისთვის \"%s\" ჩანაწერებს არ შეიცავს" -#: pg_combinebackup.c:1176 +#: pg_combinebackup.c:1199 #, c-format -msgid "%s: server version too old\n" -msgstr "%s: სერვერის ვერსია ძალიან ძველია\n" +msgid "%s: server version too old" +msgstr "%s: სერვერის ვერსია ძალიან ძველია" -#: pg_combinebackup.c:1177 +#: pg_combinebackup.c:1200 #, c-format -msgid "%s: could not parse version number\n" -msgstr "%s: ვერსის ნომრის დამუშავების შეცდომა\n" +msgid "%s: could not parse version number" +msgstr "%s: ვერსის ნომრის დამუშავების შეცდომა" -#: pg_combinebackup.c:1296 +#: pg_combinebackup.c:1319 #, c-format msgid "could not read symbolic link \"%s\": %m" msgstr "სიმბოლური ბმის \"%s\" წაკითხვის შეცდომა: %m" -#: pg_combinebackup.c:1299 +#: pg_combinebackup.c:1322 #, c-format -msgid "symbolic link \"%s\" is too long" -msgstr "სიმბოლური ბმული \"%s\" მეტისმეტად გრძელია" +msgid "target of symbolic link \"%s\" is too long" +msgstr "სიმბოლური ბმულის \"%s\" სამიზნე მეტისმეტად გრძელია" -#: pg_combinebackup.c:1302 +#: pg_combinebackup.c:1325 #, c-format -msgid "symbolic link \"%s\" is relative" -msgstr "სიმბმული \"%s\" ფარდობითია" +msgid "target of symbolic link \"%s\" is relative" +msgstr "სიმბმულის \"%s\" სამიზნე ფარდობითია" -#: pg_combinebackup.c:1324 +#: pg_combinebackup.c:1347 #, c-format msgid "tablespace at \"%s\" has no tablespace mapping" msgstr "ცხრილები სივრცეს მისამართზე \"%s\" ცხრილების სივრცის ასახვები არ გააჩნია" -#: pg_combinebackup.c:1342 +#: pg_combinebackup.c:1365 #, c-format -msgid "tablespaces with OIDs %u and %u both point at \"%s\"" -msgstr "ცხრილის სივრცეები OID-ებით %u და %u, ორივე, \"%s\"-ზე მიუთითებს" +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "ცხრილის სივრცეები OID-ებით %u და %u, ორივე მიუთითებს საქაღალდეზე \"%s\"-ზე" -#: pg_combinebackup.c:1351 +#: pg_combinebackup.c:1374 #, c-format msgid "could not close directory \"%s\": %m" msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" -#: pg_combinebackup.c:1372 +#: pg_combinebackup.c:1395 #, c-format msgid "file \"%s\" is too large" msgstr "%s: ფაილი ძალიან დიდია" -#: pg_combinebackup.c:1389 +#: pg_combinebackup.c:1412 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "ფაილის \"%s\" წაკითხვა შეუძლებელია: წაკითხულია %zd %lld-დან" + +#: reconstruct.c:339 #, c-format -msgid "could not read file \"%s\": read only %zd of %lld bytes" -msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ, %zd ბაიტი %lld-დან" +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "სრული მარქაფი შეიცავს მოულოდნელ ინკრემენტულ ფაილს \"%s\"" -#: reconstruct.c:411 +#: reconstruct.c:423 #, c-format msgid "file \"%s\" is too short: expected %llu, found %llu" msgstr "ფაილი \"%s\" მეტისმეტად მოკლეა. მოველოდი %llu, მივიღე %llu" -#: reconstruct.c:453 +#: reconstruct.c:465 #, c-format -msgid "file \"%s\" has bad incremental magic number (0x%x not 0x%x)" +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" msgstr "ფაილს \"%s\" არასწორი ინკრემენტული ჯადოსნური რიცხვი (0x%x not 0x%x) გააჩნია" -#: reconstruct.c:459 +#: reconstruct.c:471 #, c-format msgid "file \"%s\" has block count %u in excess of segment size %u" msgstr "ფაილს \"%s\" აქვს ბლოკების რაოდენობა %u, რომელიც სეგმენტის ზომას %u აჭარბებს" -#: reconstruct.c:466 +#: reconstruct.c:478 #, c-format msgid "file \"%s\" has truncation block length %u in excess of segment size %u" msgstr "ფაილს \"%s\" აქვს წაკვეთის ბლოკის სიგრძე %u, რომელიც სეგმენტის ზომას %u აჭარბებს" -#: reconstruct.c:530 +#: reconstruct.c:542 #, c-format -msgid "could not read file \"%s\": read only %d of %u bytes" -msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ, %d ბაიტი %u-დან" +msgid "could not read file \"%s\": read %d of %u" +msgstr "ფაილის \"%s\" წაკითხვის შეცდომა: წაკითხულია %d %u-დან" -#: reconstruct.c:774 +#: reconstruct.c:786 #, c-format -msgid "could not read file \"%s\": read only %d of %d bytes at offset %llu" -msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ %d ბაიტი %d-დან წანაცვლებაზე %llu" +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "ფაილიდან \"%s\" წაკითხვის შეცდომა. წანაცვლება %llu: წაკითხულია %d %d-დან" + +#, c-format +#~ msgid "\"%s\" contains no entry for \"%s\"" +#~ msgstr "\"%s\" არ შეიცავს ჩანაწერს \"%s\"-სთვის" + +#, c-format +#~ msgid "\"%s\" does not exist" +#~ msgstr "\"%s\" არ არსებობს" + +#, c-format +#~ msgid "could not close \"%s\": %m" +#~ msgstr "\"%s\" ვერ დავხურე: %m" + +#, c-format +#~ msgid "could not open \"%s\": %m" +#~ msgstr "\"%s\" ვერ გავხსენი: %m" + +#, c-format +#~ msgid "could not read file \"%s\": read only %d of %d bytes at offset %llu" +#~ msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ %d ბაიტი %d-დან წანაცვლებაზე %llu" + +#, c-format +#~ msgid "could not read file \"%s\": read only %d of %u bytes" +#~ msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ, %d ბაიტი %u-დან" + +#, c-format +#~ msgid "could not read file \"%s\": read only %zd of %lld bytes" +#~ msgstr "ვერ წავიკითხე ფაილი \"%s\": წავიკითხე, მხოლოდ, %zd ბაიტი %lld-დან" + +#, c-format +#~ msgid "could not stat \"%s\": %m" +#~ msgstr "\"%s\" ვერ აღმოვაჩინე: %m" + +#, c-format +#~ msgid "could not write \"%s\": %m" +#~ msgstr "\"%s\"-ში ჩაწერის შეცდომა: %m" + +#, c-format +#~ msgid "could not write file \"%s\": wrote only %d of %d bytes" +#~ msgstr "ვერ ჩავწერე ფაილი \"%s\": ჩავწერე, მხოლოდ, %d ბაიტი %d-დან" + +#, c-format +#~ msgid "could not write file \"%s\": wrote only %d of %d bytes at offset %u" +#~ msgstr "ფაილში \"%s\" ჩაწერის შეცდომა: ჩავწერე მხოლოდ %d ბაიტი %d-დან , წანაცვლებაზე %u" -#: write_manifest.c:260 #, c-format -msgid "could not write \"%s\": %m" -msgstr "\"%s\"-ში ჩაწერის შეცდომა: %m" +#~ msgid "error while linking file from \"%s\" to \"%s\": %m" +#~ msgstr "შეცდომა ფაილის ბმულის შექმნისას \"%s\"-დან \"%s\"-მდე: %m" #, c-format #~ msgid "unexpected json parse error type: %d" diff --git a/src/bin/pg_combinebackup/po/ko.po b/src/bin/pg_combinebackup/po/ko.po new file mode 100644 index 0000000000000..e6d9629b170ff --- /dev/null +++ b/src/bin/pg_combinebackup/po/ko.po @@ -0,0 +1,918 @@ +# Korean message translation file for pg_combinebackup +# Copyright (C) 2025 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_combinebackup (PostgreSQL) package. +# Ioseph Kim , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2025-01-17 04:52+0000\n" +"PO-Revision-Date: 2025-01-18 00:54+0900\n" +"Last-Translator: Ioseph Kim \n" +"Language-Team: Korean team \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "오류: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "경고: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "상세정보: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "힌트: " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "\"%s\" 파일을 닫을 수 없음: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 불일치" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"바이트 순서가 일치하지 않습니다.\n" +"pg_control 파일을 저장하는 데 사용된 바이트 순서는 \n" +"이 프로그램에서 사용하는 순서와 일치해야 합니다. 이 경우 아래 결과는 올바르" +"지 않으며\n" +"현재 PostgreSQL 설치본과 이 데이터 디렉터리가 호환하지 않습니다." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "\"%s\" 파일 쓰기 실패: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일 fsync 실패: %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "메모리 부족" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "성공" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "대상 버퍼가 너무 작습니다." + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "OpenSSL 실패" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일 대상으로 파일 시스템 동기화를 할 수 없습니다: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "재귀적 하향 구문분석기는 증분 토큰분석기을 사용할 수 없습니다." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "증분 구문분석기는 증분 토큰분석기를 필요로 합니다." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON 계층이 너무 깊음, 허용하는 최대 깊이는 6400입니다." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "\"\\%.*s\" 이스케이프 표기가 바르지 않습니다." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "0x%02x 값의 문자는 이스케이프 처리를 해야함." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "입력이 끝나야하는데, \"%.*s\" 발견했습니다." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "배열 요소나 \"]\" 문자를 기대했는데, \"%.*s\" 발견했습니다." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "\",\" 또는 \"]\" 문자를 기대했는데, \"%.*s\" 발견했습니다." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "\":\" 문자를 기대했는데, \"%.*s\" 발견했습니다." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "JSON 값을 기대했는데, \"%.*s\" 값임" + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "입력 문자열이 예상치 않게 끝났음." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "문자열이나, \"}\"가 필요한데 \"%.*s\"이(가) 있음" + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "\",\" 또는 \"}\"가 필요한데 \"%.*s\"이(가) 있음" + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "문자열 값을 기대했는데, \"%.*s\" 값임" + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "잘못된 토큰: \"%.*s\"" + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 값은 text 형으로 변환할 수 없음." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "\"\\u\" 표기법은 뒤에 4개의 16진수가 와야 합니다." + +#: ../../common/jsonapi.c:2169 +msgid "" +"Unicode escape values cannot be used for code point values above 007F when " +"the encoding is not UTF8." +msgstr "" +"서버 인코딩이 UTF8이 아닌 경우 007F보다 큰 코드 지점 값에는 유니코드 이스케이" +"프 값을 사용할 수 없음" + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "" +"Unicode escape value could not be translated to the server's encoding %s." +msgstr "유니코드 이스케이프 값을 %s 서버 인코딩으로 변환할 수 없음." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "유니코드 상위 surrogate(딸림 코드)는 상위 딸림 코드 뒤에 오면 안됨." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "유니코드 상위 surrogate(딸림 코드) 뒤에는 하위 딸림 코드가 있어야 함." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "메니페스트 체크섬 초기화를 할 수 없음" + +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "메니페스트가 비정상적으로 끝났음" + +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "메니페스트 체크섬 갱신 할 수 없음" + +#: ../../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "비정상적인 개체 시작" + +#: ../../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "비정상적인 개체 끝" + +#: ../../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "비정상적인 배열 시작" + +#: ../../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "비정상적인 배열 끝" + +#: ../../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "버전 지시자가 있어야 함" + +#: ../../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "최상위 필드를 알 수 없음" + +#: ../../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "예상치 못한 파일 필드" + +#: ../../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "예상치 못한 WAL 범위 필드" + +#: ../../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "예상치 못한 개체 필드" + +#: ../../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "예상치 못한 스칼라" + +#: ../../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "매니페이스 버전이 정수가 아님" + +#: ../../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "예상치 못한 메니페스트 버전" + +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "매니페이스 안 system identifier가 정수가 아님" + +#: ../../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "패스 이름 빠짐" + +#: ../../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "패스 이름과 인코딩 된 패스 이름이 함께 있음" + +#: ../../common/parse_manifest.c:666 +msgid "missing size" +msgstr "크기 빠짐" + +#: ../../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "알고리즘 없는 체크섬" + +#: ../../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "파일 이름을 디코딩할 수 없음" + +#: ../../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "파일 크기가 정수가 아님" + +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "알 수 없는 체크섬 알고리즘: \"%s\"" + +#: ../../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "\"%s\" 파일의 체크섬이 잘못됨: \"%s\"" + +#: ../../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "타임라인 빠짐" + +#: ../../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "시작 LSN 빠짐" + +#: ../../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "끝 LSN 빠짐" + +#: ../../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "타임라인이 정수가 아님" + +#: ../../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "시작 LSN 값을 분석할 수 없음" + +#: ../../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "끝 LSN 값을 분석할 수 없음" + +#: ../../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "적어도 2줄이 더 있어야 함" + +#: ../../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "마지막 줄에 줄바꿈 문자가 없음" + +#: ../../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "메니페스트 체크섬 마무리 작업 할 수 없음" + +#: ../../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "메니페스트에 체크섬 없음" + +#: ../../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "잘못된 메니페스트 체크섬: \"%s\"" + +#: ../../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "메니페스트 체크섬 불일치" + +#: ../../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "백업 메니페스트 구문 분석 실패: %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값은 %s 옵션의 값으로 적당하지 않음" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 값은 %d부터 %d까지만 허용합니다" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s: %s 구문분석 실패" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s: %s 값의 끝이 이상함" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s: %s 값의 TLI 구문분석 실패" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s: 바르지 않은 TLI" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s: %s 찾지 못함" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s: %s은(는) %s을(를) 필요로 함" + +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "\"%s\" 파일 쓰기 실패: %d/%d 만큼 씀" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "\"%s\" 파일 체크섬을 갱신할 수 없음" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "\"%s\" 파일 쓰기 실패: %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "\"%s\"파일 쓰기 실패: 시작위치=%u, %d/%d 만큼 씀" + +#: copy_file.c:199 reconstruct.c:784 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 클론하는 동안 오류 발생: %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "\"%s\" 파일을 만들 수 없음: %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "\"%s\" 파일을 \"%s\" 파일로 클론하는 동안 오류 발생: %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "이 운영체제는 파일 클론 기능을 제공하지 않습니다." + +#: copy_file.c:278 reconstruct.c:704 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 copy_file_range 기능으로 복사 중 오류: %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:724 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "이 운영체제는 copy_file_range 기능을 지원하지 않습니다." + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 복사할 수 없음: %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "\"%s\" 파일 없음" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "\"%s\" 파일 읽기 실패: %d/%lld 읽음" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "\"%s\" 파일 읽기 실패: %lld/%lld 읽음" + +#: load_manifest.c:248 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "백업 매니페이스 파일 버전이 1인 경우는 증분 백업을 지원하지 않음" + +#: load_manifest.c:280 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "백업 메니페스트 안에 경로 이름이 중복됨: \"%s\"" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "입력 디렉터리를 지정하지 않았음" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "자료가 저장될 디렉터리를 지정하지 않았음" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: 매니페이스 시스템 식별번호는 %llu인데, 컨트롤 파일은 %llu임" + +#: pg_combinebackup.c:340 +#, c-format +msgid "" +"cannot generate a manifest because no manifest is available for the final " +"input backup" +msgstr "마지막 입력 백업용 매니페이스가 없어 매니페이스를 만들 수 없음" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 심볼릭 링크로 만들 수 없음: %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "디렉터리 이름이 너무 김" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "테이블스페이스 맵핑 하는 곳에서 \"=\" 문자가 중복 되어 있음" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "" +"\"%s\" 형식의 테이블스페이스 맵핑이 잘못 되었음, \"OLDDIR=NEWDIR\" 형식이어" +"야 함" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "테이블스페이스 맵핑용 옛 디렉터리가 절대 경로가 아님: %s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "" +"backup at \"%s\" is a full backup, but only the first backup should be a " +"full backup" +msgstr "\"%s\"의 백업은 전체 백업이지만, 첫 백업 단 하나만 전체 백업이어야 함" + +#: pg_combinebackup.c:556 +#, c-format +msgid "" +"backup at \"%s\" is an incremental backup, but the first backup should be a " +"full backup" +msgstr "\"%s\"의 백업은 증분 백업이지만, 첫 백업은 전체 백업이어야 함" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "\"%s\"의 백업은 타임라인 %u번으로 시작하지만, 기대번호는 %u임" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "\"%s\"의 백업은 시작 LSN이 %X/%X이지만, 기대 LSN은 %X/%X임" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s: CRC 잘못됨" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s: 예상치 못한 컨트롤 파일 버전" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s: 예상 시스템 식별번호는 %llu이지만, %llu임" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "일부 백업만 체크섬 기능이 활성화 되었음" + +#: pg_combinebackup.c:658 +#, c-format +msgid "" +"Disable, and optionally reenable, checksums on the output directory to avoid " +"failures." +msgstr "" +"실패를 피하기 위해 출력 디렉터리의 체크섬 기능을 비활성하고, 다 합치고 나서 " +"활성화하는 방법이 있음." + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "\"%s\" 출력 디렉터리 삭제 중" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "출력 디렉터리 삭제 실패" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "\"%s\" 출력 디렉터리 안 파일들을 삭제 중" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "출력 디렉터리 안 파일 삭제 실패" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "\"%s\" 디렉터리가 비어있지 않습니다." + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "" +"%s reconstructs full backups from incrementals.\n" +"\n" +msgstr "" +"%s은 증분 백업들을 합쳐 전체 백업을 재생성 합니다.\n" +"\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "사용법:\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [옵션]... 디렉터리...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"옵션들:\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug 디버깅에 필요한 정보들도 함께 출력함\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr " -n, --dry-run 실 작업은 진행하지 않음\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid "" +" -N, --no-sync do not wait for changes to be written safely to " +"disk\n" +msgstr "" +" -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않음\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=DIRECTORY 출력 디렉터리\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" OLDDIR을 NEWDIR로 테이블스페이스 재조정\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr " --clone 파일을 복사 대신에 클론 (reflink)\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy 파일 복사 (기본값)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr "" +" --copy-file-range 복사 할 때 copy using copy_file_range() 사용\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" 매니페스트 체크섬 알고리즘 지정\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest 백업 매니페이스 파일 만들지 않음\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD 파일을 디스크에 동기화 하는 방법 지정\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"문제점 보고 주소: <%s>\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s 홈페이지: <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "\"%s\" 심볼릭 링크 건너뜀" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "\"%s\" 특수 파일을 건너뜀" + +#: pg_combinebackup.c:1073 reconstruct.c:305 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "\"%s\" 매니페스트 파일에 \"%s\" 파일에 대한 정보가 없음" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s: 서버 버전이 너무 낮음" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s: 버전 번호를 해석할 수 없음" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "\"%s\" 심볼릭 링크의 대상이 너무 긺" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "\"%s\" 심볼릭 링크 대상이 상대 경로임" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "\"%s\"의 테이블스페이스는 테이블스페이스 맵핑 정보가 없음" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "OIDs %u, %u 두 테이블스페이스는 같은 \"%s\" 디렉터리를 사용함" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "\"%s\" 파일이 너무 큽니다." + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "\"%s\" 파일을 읽을 수 없음: %zd/%lld 만 읽었음" + +#: reconstruct.c:339 +#, c-format +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "전체 백업에 예상치 못한 증분 파일이 있음: \"%s\"" + +#: reconstruct.c:423 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "\"%s\" 파일 크기가 너무 적음: 기대값=%llu, 실재값=%llu" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "\"%s\" 파일에 잘못된 증분 매직 번호(0x%x)가 있음 (기대값 0x%x)" + +#: reconstruct.c:471 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "\"%s\" 파일의 블록 수(%u)가 조각 크기(%u)보다 큼" + +#: reconstruct.c:478 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "\"%s\" 파일의 삭제 블럭 길이(%u)가 조각 크기(%u)보다 큼" + +#: reconstruct.c:542 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "\"%s\" 파일 읽을 수 없음: %d/%u만 읽음" + +#: reconstruct.c:786 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "\"%s\" 파일 읽을 수 없음: 시작위치 %llu, %d/%d만 읽음" diff --git a/src/bin/pg_combinebackup/po/meson.build b/src/bin/pg_combinebackup/po/meson.build index 48568425f68d4..29f7049ab0861 100644 --- a/src/bin/pg_combinebackup/po/meson.build +++ b/src/bin/pg_combinebackup/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_combinebackup-' + pg_version_major.to_string())] diff --git a/src/bin/pg_combinebackup/po/ru.po b/src/bin/pg_combinebackup/po/ru.po new file mode 100644 index 0000000000000..5c2af7387c385 --- /dev/null +++ b/src/bin/pg_combinebackup/po/ru.po @@ -0,0 +1,944 @@ +# Alexander Lakhin , 2024. +msgid "" +msgstr "" +"Project-Id-Version: pg_combinebackup (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-11-09 08:04+0300\n" +"Last-Translator: Alexander Lakhin \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Lokalize 21.12.3\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "ошибка: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "предупреждение: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "подробности: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "подсказка: " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "не удалось закрыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"возможно несоответствие порядка байт\n" +"Порядок байт в файле pg_control может не соответствовать используемому\n" +"этой программой. В этом случае результаты будут неверными и\n" +"установленный PostgreSQL будет несовместим с этим каталогом данных." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не удалось записать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "нехватка памяти" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "успех" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "буфер назначения слишком мал" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "ошибка OpenSSL" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "" +"Инкрементальный лексический анализатор не подходит для нисходящего " +"рекурсивного разбора." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "" +"Для инкрементального разбора требуется инкрементальный лексический " +"анализатор." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "" +"Слишком большая вложенность JSON, максимальная допустимая глубина: 6400." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Неверная спецпоследовательность: \"\\%.*s\"." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "Символ с кодом 0x%02x необходимо экранировать." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Ожидался конец текста, но обнаружено продолжение \"%.*s\"." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Ожидался элемент массива или \"]\", но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Ожидалась \",\" или \"]\", но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Ожидалось \":\", но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Ожидалось значение JSON, но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "Неожиданный конец входной строки." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Ожидалась строка или \"}\", но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Ожидалась \",\" или \"}\", но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "Ожидалась строка, но обнаружено \"%.*s\"." + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "Ошибочный элемент \"%.*s\"." + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 нельзя преобразовать в текст." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "За \"\\u\" должны следовать четыре шестнадцатеричные цифры." + +#: ../../common/jsonapi.c:2169 +msgid "" +"Unicode escape values cannot be used for code point values above 007F when " +"the encoding is not UTF8." +msgstr "" +"Спецкоды Unicode для значений выше 007F можно использовать только с " +"кодировкой UTF8." + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "" +"Unicode escape value could not be translated to the server's encoding %s." +msgstr "Спецкод Unicode нельзя преобразовать в серверную кодировку %s." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "" +"Старшее слово суррогата Unicode не может следовать за другим старшим словом." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "Младшее слово суррогата Unicode должно следовать за старшим словом." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "не удалось подготовить контекст контрольной суммы манифеста" + +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "неожиданный конец манифеста" + +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "не удалось изменить контекст контрольной суммы манифеста" + +#: ../../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "неожиданное начало объекта" + +#: ../../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "неожиданный конец объекта" + +#: ../../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "неожиданное начало массива" + +#: ../../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "неожиданный конец массива" + +#: ../../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "ожидалось указание версии" + +#: ../../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "нераспознанное поле на верхнем уровне" + +#: ../../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "неизвестное поле для файла" + +#: ../../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "неизвестное поле в указании диапазона WAL" + +#: ../../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "неожиданное поле объекта" + +#: ../../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "неожиданное скалярное значение" + +#: ../../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "версия манифеста не является целым числом" + +#: ../../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "неожиданная версия манифеста" + +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "идентификатор системы в манифесте не является целым числом" + +#: ../../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "отсутствует указание пути" + +#: ../../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "путь задан в обычном виде и в закодированном" + +#: ../../common/parse_manifest.c:666 +msgid "missing size" +msgstr "отсутствует указание размера" + +#: ../../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "не задан алгоритм расчёта контрольной суммы" + +#: ../../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "не удалось декодировать имя файла" + +#: ../../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "размер файла не является целочисленным" + +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "нераспознанный алгоритм расчёта контрольных сумм: \"%s\"" + +#: ../../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "неверная контрольная сумма для файла \"%s\": \"%s\"" + +#: ../../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "отсутствует линия времени" + +#: ../../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "отсутствует начальный LSN" + +#: ../../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "отсутствует конечный LSN" + +#: ../../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "линия времени задана не целым числом" + +#: ../../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "не удалось разобрать начальный LSN" + +#: ../../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "не удалось разобрать конечный LSN" + +#: ../../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "ожидалось как минимум 2 строки" + +#: ../../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "последняя строка не оканчивается символом новой строки" + +#: ../../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "не удалось завершить расчёт контрольной суммы манифеста" + +#: ../../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "в манифесте нет контрольной суммы" + +#: ../../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "неверная контрольная сумма в манифесте: \"%s\"" + +#: ../../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "ошибка контрольной суммы манифеста" + +#: ../../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "не удалось разобрать манифест копии: %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неверное значение \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "значение %s должно быть в диапазоне %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s: не удалось разобрать %s" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s: неподходящее окончание для %s" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s: не удалось разобрать TLI для %s" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s: неверное значение TLI" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s: не удалось найти %s" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s: %s требует %s" + +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "не удалось записать файл \"%s\" (записано байт: %d из %d)" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "не удалось изменить контекст контрольной суммы файла \"%s\"" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "не удалось записать в файл \"%s\": %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "" +"не удалось записать в файл \"%s\" (смещение %u, записано байт: %d из %d)" + +#: copy_file.c:199 reconstruct.c:784 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "ошибка при клонировании файла \"%s\" в \"%s\": %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "не удалось создать файл \"%s\": %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "ошибка при клонировании файла \"%s\" в \"%s\": %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "клонирование файлов не поддерживается в этой ОС" + +#: copy_file.c:278 reconstruct.c:704 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "ошибка при копировании фрагмента файла \"%s\" в \"%s\": %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:724 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range не поддерживается в этой ОС" + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "не удалось скопировать файл \"%s\" в \"%s\": %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "файл \"%s\" не существует" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %lld)" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %lld из %lld)" + +#: load_manifest.c:248 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "" +"с версией 1 манифеста копии инкрементальное копирование не поддерживается" + +#: load_manifest.c:280 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "дублирующийся путь в манифесте копии: \"%s\"" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Для дополнительной информации попробуйте \"%s --help\"." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "входные каталоги не указаны" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "выходной каталог не указан" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: идентификатор системы в манифесте %llu, а в управляющем файле %llu" + +#: pg_combinebackup.c:340 +#, c-format +msgid "" +"cannot generate a manifest because no manifest is available for the final " +"input backup" +msgstr "" +"сгенерировать манифест нельзя по причине отсутствия манифеста в последней " +"указанной копии" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "не удалось создать символическую ссылку \"%s\" в \"%s\": %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не удалось создать каталог \"%s\": %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "слишком длинное имя каталога" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "несколько знаков \"=\" в сопоставлении табличного пространства" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "" +"сопоставление табл. пространства записано неверно: \"%s\"; должно быть " +"\"СТАРЫЙ_КАТАЛОГ=НОВЫЙ_КАТАЛОГ\"" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "" +"старый каталог в сопоставлении табл. пространства задан не абсолютным путём: " +"%s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "" +"backup at \"%s\" is a full backup, but only the first backup should be a " +"full backup" +msgstr "" +"копия в \"%s\" является полной копией, но полную копию можно передать только " +"первой в списке" + +#: pg_combinebackup.c:556 +#, c-format +msgid "" +"backup at \"%s\" is an incremental backup, but the first backup should be a " +"full backup" +msgstr "" +"копия в \"%s\" является инкрементальной, но первой в списке должна " +"передаваться полная копия" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "копия в \"%s\" начинается с линии времени %u, а ожидалась %u" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "копия в \"%s\" начинается с LSN %X/%X, а ожидался %X/%X" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s: ошибка CRC" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s: неожиданная версия управляющего файла" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s: ожидался идентификатор системы %llu, но обнаружен %llu" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "контрольные суммы включены только в некоторых копиях" + +#: pg_combinebackup.c:658 +#, c-format +msgid "" +"Disable, and optionally reenable, checksums on the output directory to avoid " +"failures." +msgstr "" +"Отключите (и при необходимости вновь включите) контрольные суммы в выходном " +"каталоге во избежание сбоев." + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "удаление выходного каталога \"%s\"" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "ошибка при удалении выходного каталога" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "удаление содержимого выходного каталога \"%s\"" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "ошибка при удалении содержимого выходного каталога" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "каталог \"%s\" существует, но он не пуст" + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "" +"%s reconstructs full backups from incrementals.\n" +"\n" +msgstr "" +"%s реконструирует полные копии из инкрементальных.\n" +"\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "Использование:\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [ПАРАМЕТР]... КАТАЛОГ...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Параметры:\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug выдавать много отладочных сообщений\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr "" +" -n, --dry-run не выполнять никаких практических действий\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid "" +" -N, --no-sync do not wait for changes to be written safely to " +"disk\n" +msgstr "" +" -N, --no-sync не ждать завершения сохранения данных на диске\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=КАТАЛОГ выходной каталог\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr "" +" -T, --tablespace-mapping=СТАРЫЙ_КАТАЛОГ=НОВЫЙ_КАТАЛОГ\n" +" перенести табличное пространство из старого " +"каталога\n" +" в новый\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr "" +" --clone клонировать (используя reflink), а не " +"копировать\n" +" файлы\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy копировать файлы (по умолчанию)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr "" +" --copy-file-range использовать для копирования системную функцию\n" +" copy_file_range()\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" алгоритм подсчёта контрольных сумм в манифесте\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest отключить создание манифеста копии\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Об ошибках сообщайте по адресу <%s>.\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашняя страница %s: <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "символическая ссылка \"%s\" пропускается" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "специальный файл \"%s\" пропускается" + +#: pg_combinebackup.c:1073 reconstruct.c:305 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "файл манифеста \"%s\" не содержит записи о файле \"%s\"" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s: версия сервера слишком старая" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s: не удалось разобрать номер версии" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "не удалось прочитать символическую ссылку \"%s\": %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "целевой путь символической ссылки \"%s\" слишком длинный" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "целевой путь символической ссылки \"%s\" является относительным" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "для табличного пространства в \"%s\" не задано сопоставление" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "" +"два табличных пространства с OIDs %u и %u указывают на один каталог \"%s\"" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "не удалось закрыть каталог \"%s\": %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "файл \"%s\" слишком большой" + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %zd из %lld)" + +#: reconstruct.c:339 +#, c-format +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "полная копия содержит неожиданный инкрементальный файл \"%s\"" + +#: reconstruct.c:423 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "файл \"%s\" слишком мал (ожидалось байт: %llu, фактически: %llu)" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "" +"в файла \"%s\" неверное контрольное число инкрементальной копии (0x%x, " +"ожидалось: 0x%x)" + +#: reconstruct.c:471 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "в файле \"%s\" количество блоков %u превышает размер сегмента %u" + +#: reconstruct.c:478 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "" +"в файле \"%s\" длина отсечения в блоках (%u) превышает размер сегмента %u" + +#: reconstruct.c:542 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %u)" + +#: reconstruct.c:786 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "" +"не удалось прочитать файл \"%s\" по смещению %llu (прочитано байт: %d из %d)" diff --git a/src/bin/pg_combinebackup/po/sv.po b/src/bin/pg_combinebackup/po/sv.po new file mode 100644 index 0000000000000..06327f49fe97d --- /dev/null +++ b/src/bin/pg_combinebackup/po/sv.po @@ -0,0 +1,896 @@ +# Swedish message translation file for pg_combinebackup +# Copyright (C) 2024 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_combinebackup (PostgreSQL) package. +# Dennis Björklund , 2024, 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2025-02-12 13:52+0000\n" +"PO-Revision-Date: 2025-02-12 20:37+0100\n" +"Last-Translator: Dennis Björklund \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "fel: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "varning: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "detalj: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "tips: " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:540 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:369 reconstruct.c:740 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "kunde inte stänga fil \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"möjligt fel i byteordning\n" +"Den byteordning som filen från pg_control lagrats med passar kanske\n" +"inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" +"och PostgreSQL-installationen vara inkompatibel med databaskatalogen." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:523 reconstruct.c:638 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:759 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "kunde inte skriva fil \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "slut på minne" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "lyckades" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "destinationsbuffer för liten" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "OpenSSL-fel" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:204 +#: reconstruct.c:421 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "Recursive-descent-parser kan inte använda inkrementell lexer." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "Inkrementell parser kräver en inkrementell lexer." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON nästlad för djupt, maximal tillåtet djup är 6400." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Escape-sekvens \"\\%.*s\" är ogiltig." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "Tecken med värde 0x%02x måste escape:as." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Förväntade slut på indata, men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Färväntade array-element eller \"]\", men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Förväntade \",\" eller \"]\", men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Förväntade sig \":\" men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Förväntade JSON-värde, men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "Indatasträngen avslutades oväntat." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Färväntade sträng eller \"}\", men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Förväntade sig \",\" eller \"}\" men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "Förväntade sträng, men hittade \"%.*s\"." + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "Token \"%.*s\" är ogiltig." + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 kan inte konverteras till text." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "\"\\u\" måste följas av fyra hexdecimala siffror." + +#: ../../common/jsonapi.c:2169 +msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." +msgstr "Escape-värden för unicode kan inte användas för kodpunkter med värde över 007F när kodningen inte är UTF8." + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "Unicode escape value could not be translated to the server's encoding %s." +msgstr "Escape-värde för unicode kan inte översättas till serverns kodning %s." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "Unicodes övre surrogathalva får inte komma efter en övre surrogathalva." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "Unicodes lägre surrogathalva måste följa en övre surrogathalva." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "kunde inte initiera kontrollsumma för backup-manifest" + +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 +msgid "manifest ended unexpectedly" +msgstr "manifestet avslutades oväntat" + +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 +#, c-format +msgid "could not update checksum of manifest" +msgstr "kunde inte uppdatera kontrollsumma för backup-manifest" + +#: ../../common/parse_manifest.c:301 +msgid "unexpected object start" +msgstr "oväntad objektstart" + +#: ../../common/parse_manifest.c:336 +msgid "unexpected object end" +msgstr "oväntat objektslut" + +#: ../../common/parse_manifest.c:365 +msgid "unexpected array start" +msgstr "oväntad array-start" + +#: ../../common/parse_manifest.c:390 +msgid "unexpected array end" +msgstr "oväntat array-slut" + +#: ../../common/parse_manifest.c:417 +msgid "expected version indicator" +msgstr "förväntade en versionsindikator" + +#: ../../common/parse_manifest.c:453 +msgid "unrecognized top-level field" +msgstr "okänt toppnivåfält" + +#: ../../common/parse_manifest.c:472 +msgid "unexpected file field" +msgstr "oväntat filfält" + +#: ../../common/parse_manifest.c:486 +msgid "unexpected WAL range field" +msgstr "oväntat WAL-intervall-fält" + +#: ../../common/parse_manifest.c:492 +msgid "unexpected object field" +msgstr "oväntat objektfält" + +#: ../../common/parse_manifest.c:582 +msgid "unexpected scalar" +msgstr "oväntad skalar" + +#: ../../common/parse_manifest.c:608 +msgid "manifest version not an integer" +msgstr "manifestversion är inte ett heltal" + +#: ../../common/parse_manifest.c:612 +msgid "unexpected manifest version" +msgstr "oväntad manifestversion" + +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "manifestets systemidentifierare är inte ett heltal" + +#: ../../common/parse_manifest.c:661 +msgid "missing path name" +msgstr "saknas sökväg" + +#: ../../common/parse_manifest.c:664 +msgid "both path name and encoded path name" +msgstr "både sökväg och kodad sökväg" + +#: ../../common/parse_manifest.c:666 +msgid "missing size" +msgstr "saknar storlek" + +#: ../../common/parse_manifest.c:669 +msgid "checksum without algorithm" +msgstr "kontrollsumma utan algoritm" + +#: ../../common/parse_manifest.c:683 +msgid "could not decode file name" +msgstr "kunde inte avkoda filnamn" + +#: ../../common/parse_manifest.c:693 +msgid "file size is not an integer" +msgstr "filstorlek är inte ett haltal" + +#: ../../common/parse_manifest.c:699 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "okänd algoritm för kontrollsumma: \"%s\"" + +#: ../../common/parse_manifest.c:718 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "ogiltig kontrollsumma för fil \"%s\": \"%s\"" + +#: ../../common/parse_manifest.c:761 +msgid "missing timeline" +msgstr "saknar tidslinje" + +#: ../../common/parse_manifest.c:763 +msgid "missing start LSN" +msgstr "saknar start-LSN" + +#: ../../common/parse_manifest.c:765 +msgid "missing end LSN" +msgstr "saknar slut-LSN" + +#: ../../common/parse_manifest.c:771 +msgid "timeline is not an integer" +msgstr "tidslinje är inte ett heltal" + +#: ../../common/parse_manifest.c:774 +msgid "could not parse start LSN" +msgstr "kunde inte parsa start-LSN" + +#: ../../common/parse_manifest.c:777 +msgid "could not parse end LSN" +msgstr "kunde inte parsa slut-LSN" + +#: ../../common/parse_manifest.c:842 +msgid "expected at least 2 lines" +msgstr "förväntade minst två rader" + +#: ../../common/parse_manifest.c:845 +msgid "last line not newline-terminated" +msgstr "sista raden är inte nyradsterminerad" + +#: ../../common/parse_manifest.c:864 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "kunde inte göra klart kontrollsumma för backup-manifest" + +#: ../../common/parse_manifest.c:868 +#, c-format +msgid "manifest has no checksum" +msgstr "manifestet har ingen kontrollsumma" + +#: ../../common/parse_manifest.c:872 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "ogiltig kontrollsumma för manifest: \"%s\"" + +#: ../../common/parse_manifest.c:876 +#, c-format +msgid "manifest checksum mismatch" +msgstr "kontrollsumma för manifest matchar inte" + +#: ../../common/parse_manifest.c:891 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "kunde inte parsa backup-manifest: %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s måste vara i intervallet %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s: kunde inte parsa %s" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s: felaktig avslutare för %s" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s: kunde inte parsa TLI för %s" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s: ogitlig TLI" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s: kunde inte hitta %s" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s: %s kräver %s" + +#: backup_label.c:162 reconstruct.c:761 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "kunde inte skriva fil \"%s\": skrev %d av %d" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:721 +#: reconstruct.c:767 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "kunde inte uppdatera kontrollsumma för filen \"%s\"" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "kunde inte skriva till fil \"%s\": %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "kunde inte skriva till fil \"%s\", offset %u: skrev %d av %d" + +#: copy_file.c:199 reconstruct.c:784 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "kunde inte läsa från fil \"%s\": %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "fel vid kloning av fil \"%s\" till \"%s\": %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "kunde inte skapa fil \"%s\": %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "fel vid kloning av fil \"%s\" till \"%s\": %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "filkloning stöds inte på denna plattform" + +#: copy_file.c:278 reconstruct.c:704 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "fel vid kopiering av filintervall från \"%s\" till \"%s\": %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:724 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range stöds inte på denna plattform" + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "kunde inte kopiera fil \"%s\" till \"%s\": %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "filen \"%s\" finns inte" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "kunde inte läsa fil \"%s\": läste %d av %lld" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "kunde inte läsa fil \"%s\": läste %lld av %lld" + +#: load_manifest.c:248 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "version 1 av backup-manifest stöder inte inkrementell backup" + +#: load_manifest.c:280 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "duplicerad sökväg i backup-manifest: \"%s\"" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Försök med \"%s --help\" för mer information." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "inga indatakataloger har angivits" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "ingen utdatakatalog angiven" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: manifestets systemidentifierare är %llu men kontrollfilern har %llu" + +#: pg_combinebackup.c:340 +#, c-format +msgid "cannot generate a manifest because no manifest is available for the final input backup" +msgstr "kan inte skapa manifest då inget manifest är tillgängligt för den avslutande indatabackup:en" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "kunde inte skapa symbolisk länk från \"%s\" till \"%s\": %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "kunde inte skapa katalog \"%s\": %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "katalognamn för långt" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "multipla \"=\"-tecken i tablespace-mappning" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "ogiltigt tablespace-mappningsformat \"%s\", måste vara \"OLDDIR=NEWDIR\"" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "gammal katalog är inte en absolut sökväg i tablespace-mappning: %s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" +msgstr "backup:en vid \"%s\" är en full backup men det är bara den första backup:en som skall vara en full backup" + +#: pg_combinebackup.c:556 +#, c-format +msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" +msgstr "backup:en vid \"%s\" är en inkrementell backup men den första backupen skall vara en full backup" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "backup:en vid \"%s\" startar på tidslinjen %u men det förväntades vara %u" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "backup:eb vid \"%s\" startar vid LSN %X/%X men förväntades vare %X/%X" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s: CRC är inkorrekt" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s: oväntad version på kontrollfil" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s: förväntade systemidentifierare %llu men hittade %llu" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "bara några backup:er har checksummor aktiverade" + +#: pg_combinebackup.c:658 +#, c-format +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "Avaktivera och möjligen återaktivera checksummor på utdatakatalogen för att undvika fel" + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "tar bort katalog för utdata \"%s\"" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "misslyckades att ta bort katalog för utdata" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "tar bort innehåll i katalog för utdata \"%s\"" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "misslyckades att ta bort innehåll i katalog för utdata" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "katalogen \"%s\" existerar men är inte tom" + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "kunde inte komma åt katalog \"%s\": %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "" +"%s reconstructs full backups from incrementals.\n" +"\n" +msgstr "" +"%s återskapar fulla backup:er från inkrementella.\n" +"\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "Användning:\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [FLAGGA]... KATALOG...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Flaggor:\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug generera massor med debug-utskrifter\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr " -n, --dry-run gör inga operationer\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" +msgstr " -N, --no-sync vänta inte på att ändingar säkert skrivits till disk\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=KATALOG katalog för utdata\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid "" +" -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr "" +" -T, --tablespace-mapping=FRÅNKAT=NYKAT\n" +" flytta tabellutrymme i FRÅNKAT till NYKAT\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr " --clone klona (reflink) filer istället för att kopiera\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy kopiera filer (standard)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr " --copy-file-range kopiera med systemaropet copy_file_range()\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr "" +" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" algoritm att anvvända för checksummor i manifest\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest skapa inget backup-manifest\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Rapportera fel till <%s>.\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "hemsida för %s: <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "hoppar över symbolisk länk \"%s\"" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "hoppar över specialfil \"%s\"" + +#: pg_combinebackup.c:1073 reconstruct.c:305 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "manifestfil \"%s\" innehåller ingen post för fil \"%s\"" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s: serverns version är för gammal" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s: kunde inte parsa versionnummer" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "kan inte läsa symbolisk länk \"%s\": %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "destinationen för symbolisk länk \"%s\" är för lång" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "destination för symbolisk länk \"%s\" är relativ" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "tabellutrymme vid \"%s\" har ingen mapping" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "tabellutrymme med OID:er %u och %u pekar på samma katalog \"%s\"" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "kunde inte stänga katalog \"%s\": %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "filen \"%s\" är för stor" + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "kunde inte läsa fil \"%s\": läste %zd av %lld" + +#: reconstruct.c:339 +#, c-format +msgid "full backup contains unexpected incremental file \"%s\"" +msgstr "full backup innehåller in oväntad inkrementell fil \"%s\"" + +#: reconstruct.c:423 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "filen \"%s\" är för kort: förväntade %llu, hittade %llu" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "filen \"%s\" har ett felaktigt inkrementellt magiskt nummer (0x%x, förväntade 0x%x)" + +#: reconstruct.c:471 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "filen \"%s\" har ett blockantal %u som är större än segmentstorleken %u" + +#: reconstruct.c:478 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "filen \"%s\" trunkeringsblocklängd %u som är större än segmentstorleken %u" + +#: reconstruct.c:542 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "kunde inte läsa filen \"%s\": läste %d av %u" + +#: reconstruct.c:786 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "kunde inte läsa från filen \"%s\", offset %llu: läste %d av %d" diff --git a/src/bin/pg_combinebackup/po/uk.po b/src/bin/pg_combinebackup/po/uk.po new file mode 100644 index 0000000000000..51e19b6220614 --- /dev/null +++ b/src/bin/pg_combinebackup/po/uk.po @@ -0,0 +1,876 @@ +msgid "" +msgstr "" +"Project-Id-Version: postgresql\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-08-31 06:22+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" +"Last-Translator: \n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n" +"X-Crowdin-Project: postgresql\n" +"X-Crowdin-Project-ID: 324573\n" +"X-Crowdin-Language: uk\n" +"X-Crowdin-File: /REL_17_STABLE/pg_combinebackup.pot\n" +"X-Crowdin-File-ID: 1008\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "помилка: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "попередження: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "деталі: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "підказка: " + +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" + +#: ../../common/controldata_utils.c:110 copy_file.c:150 load_manifest.c:161 +#: load_manifest.c:199 pg_combinebackup.c:1400 reconstruct.c:527 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: backup_label.c:174 copy_file.c:68 pg_combinebackup.c:538 +#: pg_combinebackup.c:1175 reconstruct.c:356 reconstruct.c:727 +#: write_manifest.c:187 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "неможливо закрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "можлива помилка у послідовності байтів.\n" +"Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 backup_label.c:143 copy_file.c:66 +#: copy_file.c:139 copy_file.c:171 copy_file.c:175 copy_file.c:225 +#: copy_file.c:268 load_manifest.c:128 pg_combinebackup.c:523 +#: pg_combinebackup.c:1167 reconstruct.c:510 reconstruct.c:625 +#: write_manifest.c:250 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 backup_label.c:160 reconstruct.c:746 +#: write_manifest.c:260 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не вдалося записати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#, c-format +msgid "out of memory" +msgstr "недостатньо пам'яті" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "успіх" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "буфер призначення занадто малий" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "Помилка OpenSSL" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: backup_label.c:187 load_manifest.c:133 pg_combinebackup.c:676 +#: pg_combinebackup.c:1131 pg_combinebackup.c:1383 reconstruct.c:199 +#: reconstruct.c:408 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_combinebackup.c:933 pg_combinebackup.c:1256 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + +#: ../../common/jsonapi.c:2121 +msgid "Recursive descent parser cannot use incremental lexer." +msgstr "Рекурсивний спуск не може використовувати інкрементний лексичний аналізатор." + +#: ../../common/jsonapi.c:2123 +msgid "Incremental parser requires incremental lexer." +msgstr "Інкрементний аналізатор потребує Інкрементний лексичний аналізатор." + +#: ../../common/jsonapi.c:2125 +msgid "JSON nested too deep, maximum permitted depth is 6400." +msgstr "JSON вкладений занадто глибокий, максимально дозволена глибина - 6400." + +#: ../../common/jsonapi.c:2127 +#, c-format +msgid "Escape sequence \"\\%.*s\" is invalid." +msgstr "Неприпустима спеціальна послідовність \"\\%.*s\"." + +#: ../../common/jsonapi.c:2131 +#, c-format +msgid "Character with value 0x%02x must be escaped." +msgstr "Символ зі значенням 0x%02x повинен бути пропущений." + +#: ../../common/jsonapi.c:2135 +#, c-format +msgid "Expected end of input, but found \"%.*s\"." +msgstr "Очікувався кінець введення, але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2138 +#, c-format +msgid "Expected array element or \"]\", but found \"%.*s\"." +msgstr "Очікувався елемент масиву або \"]\", але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2141 +#, c-format +msgid "Expected \",\" or \"]\", but found \"%.*s\"." +msgstr "Очікувалось \",\" або \"]\", але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2144 +#, c-format +msgid "Expected \":\", but found \"%.*s\"." +msgstr "Очікувалось \":\", але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2147 +#, c-format +msgid "Expected JSON value, but found \"%.*s\"." +msgstr "Очікувалось значення JSON, але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2150 +msgid "The input string ended unexpectedly." +msgstr "Несподіваний кінець вхідного рядка." + +#: ../../common/jsonapi.c:2152 +#, c-format +msgid "Expected string or \"}\", but found \"%.*s\"." +msgstr "Очікувався рядок або \"}\", але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2155 +#, c-format +msgid "Expected \",\" or \"}\", but found \"%.*s\"." +msgstr "Очікувалось \",\" або \"}\", але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2158 +#, c-format +msgid "Expected string, but found \"%.*s\"." +msgstr "Очікувався рядок, але знайдено \"%.*s\"." + +#: ../../common/jsonapi.c:2161 +#, c-format +msgid "Token \"%.*s\" is invalid." +msgstr "Неприпустимий маркер \"%.*s\"." + +#: ../../common/jsonapi.c:2164 +msgid "\\u0000 cannot be converted to text." +msgstr "\\u0000 не можна перетворити в текст." + +#: ../../common/jsonapi.c:2166 +msgid "\"\\u\" must be followed by four hexadecimal digits." +msgstr "За \"\\u\" повинні прямувати чотири шістнадцяткових числа." + +#: ../../common/jsonapi.c:2169 +msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." +msgstr "Значення виходу Unicode не можна використовувати для значень кодових точок більше 007F, якщо кодування не UTF8." + +#: ../../common/jsonapi.c:2178 +#, c-format +msgid "Unicode escape value could not be translated to the server's encoding %s." +msgstr "Значення символу Unicode не вдалося перекласти в кодування сервера %s." + +#: ../../common/jsonapi.c:2185 +msgid "Unicode high surrogate must not follow a high surrogate." +msgstr "Старший сурогат Unicode не повинен прямувати за іншим старшим сурогатом." + +#: ../../common/jsonapi.c:2187 +msgid "Unicode low surrogate must follow a high surrogate." +msgstr "Молодший сурогат Unicode не повинен прямувати за іншим молодшим сурогатом." + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#, c-format +msgid "could not initialize checksum of manifest" +msgstr "не вдалося ініціалізувати контрольну суму маніфесту" + +#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +msgid "manifest ended unexpectedly" +msgstr "маніфест закінчився несподівано" + +#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#, c-format +msgid "could not update checksum of manifest" +msgstr "не вдалося оновити контрольну суму маніфесту" + +#: ../../common/parse_manifest.c:302 +msgid "unexpected object start" +msgstr "неочікуваний початок об'єкта" + +#: ../../common/parse_manifest.c:337 +msgid "unexpected object end" +msgstr "неочікуваний кінець об'єкта" + +#: ../../common/parse_manifest.c:366 +msgid "unexpected array start" +msgstr "неочікуваний початок масиву" + +#: ../../common/parse_manifest.c:391 +msgid "unexpected array end" +msgstr "неочікуваний кінець масиву" + +#: ../../common/parse_manifest.c:418 +msgid "expected version indicator" +msgstr "індикатор очікуваної версії" + +#: ../../common/parse_manifest.c:454 +msgid "unrecognized top-level field" +msgstr "нерозпізнане поле верхнього рівня" + +#: ../../common/parse_manifest.c:473 +msgid "unexpected file field" +msgstr "неочікуване поле файлу" + +#: ../../common/parse_manifest.c:487 +msgid "unexpected WAL range field" +msgstr "неочікуване поле діапазону WAL" + +#: ../../common/parse_manifest.c:493 +msgid "unexpected object field" +msgstr "неочікуване поле об'єкта" + +#: ../../common/parse_manifest.c:583 +msgid "unexpected scalar" +msgstr "неочікуваний скаляр" + +#: ../../common/parse_manifest.c:609 +msgid "manifest version not an integer" +msgstr "версія маніфесту не ціле число" + +#: ../../common/parse_manifest.c:613 +msgid "unexpected manifest version" +msgstr "неочікувана версія маніфесту" + +#: ../../common/parse_manifest.c:637 +msgid "system identifier in manifest not an integer" +msgstr "системний ідентифікатор в маніфесті не ціле число" + +#: ../../common/parse_manifest.c:662 +msgid "missing path name" +msgstr "пропущено шлях" + +#: ../../common/parse_manifest.c:665 +msgid "both path name and encoded path name" +msgstr "і ім'я шляху, і закодований шлях" + +#: ../../common/parse_manifest.c:667 +msgid "missing size" +msgstr "відсутній розмір" + +#: ../../common/parse_manifest.c:670 +msgid "checksum without algorithm" +msgstr "контрольна сума без алгоритму" + +#: ../../common/parse_manifest.c:684 +msgid "could not decode file name" +msgstr "не вдалося декодувати ім'я файлу" + +#: ../../common/parse_manifest.c:694 +msgid "file size is not an integer" +msgstr "розмір файлу не є цілим числом" + +#: ../../common/parse_manifest.c:700 pg_combinebackup.c:199 +#, c-format +msgid "unrecognized checksum algorithm: \"%s\"" +msgstr "нерозпізнаний алгоритм контрольної суми: \"%s\"" + +#: ../../common/parse_manifest.c:719 +#, c-format +msgid "invalid checksum for file \"%s\": \"%s\"" +msgstr "неприпустима контрольна сума для файлу \"%s\": \"%s\"" + +#: ../../common/parse_manifest.c:762 +msgid "missing timeline" +msgstr "відсутня часова шкала" + +#: ../../common/parse_manifest.c:764 +msgid "missing start LSN" +msgstr "відсутній LSN початку" + +#: ../../common/parse_manifest.c:766 +msgid "missing end LSN" +msgstr "відсутній LSN кінця" + +#: ../../common/parse_manifest.c:772 +msgid "timeline is not an integer" +msgstr "часова лінія не є цілим числом" + +#: ../../common/parse_manifest.c:775 +msgid "could not parse start LSN" +msgstr "не вдалося проаналізувати початковий LSN" + +#: ../../common/parse_manifest.c:778 +msgid "could not parse end LSN" +msgstr "не вдалося проаналізувати кінцевий LSN" + +#: ../../common/parse_manifest.c:843 +msgid "expected at least 2 lines" +msgstr "очікувалося принаймні 2 рядки" + +#: ../../common/parse_manifest.c:846 +msgid "last line not newline-terminated" +msgstr "останній рядок не завершений новим рядком" + +#: ../../common/parse_manifest.c:865 +#, c-format +msgid "could not finalize checksum of manifest" +msgstr "не вдалося остаточно завершити контрольну суму маніфесту" + +#: ../../common/parse_manifest.c:869 +#, c-format +msgid "manifest has no checksum" +msgstr "у маніфесті немає контрольної суми" + +#: ../../common/parse_manifest.c:873 +#, c-format +msgid "invalid manifest checksum: \"%s\"" +msgstr "неприпустима контрольна сума маніфесту: \"%s\"" + +#: ../../common/parse_manifest.c:877 +#, c-format +msgid "manifest checksum mismatch" +msgstr "невідповідність контрольної суми маніфесту" + +#: ../../common/parse_manifest.c:892 +#, c-format +msgid "could not parse backup manifest: %s" +msgstr "не вдалося проаналізувати маніфест резервної копії: %s" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неприпустиме значення \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s має бути в діапазоні %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: backup_label.c:66 backup_label.c:85 backup_label.c:95 +#, c-format +msgid "%s: could not parse %s" +msgstr "%s: не вдалося розібрати %s" + +#: backup_label.c:69 backup_label.c:88 +#, c-format +msgid "%s: improper terminator for %s" +msgstr "%s: неправильний термінатор для %s" + +#: backup_label.c:76 +#, c-format +msgid "%s: could not parse TLI for %s" +msgstr "%s: не вдалося розібрати TLI для %s" + +#: backup_label.c:79 backup_label.c:98 +#, c-format +msgid "%s: invalid TLI" +msgstr "%s: невірний TLI" + +#: backup_label.c:106 backup_label.c:108 +#, c-format +msgid "%s: could not find %s" +msgstr "%s: не вдалося знайти %s" + +#: backup_label.c:110 backup_label.c:113 +#, c-format +msgid "%s: %s requires %s" +msgstr "%s: %s вимагає %s" + +#: backup_label.c:162 reconstruct.c:748 write_manifest.c:262 +#, c-format +msgid "could not write file \"%s\": wrote %d of %d" +msgstr "не вдалося записати файл \"%s\": записано %d з %d" + +#: backup_label.c:166 copy_file.c:146 copy_file.c:193 reconstruct.c:708 +#: reconstruct.c:754 write_manifest.c:270 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "не вдалося оновити контрольну суму файлу \"%s\"" + +#: copy_file.c:186 +#, c-format +msgid "could not write to file \"%s\": %m" +msgstr "неможливо записати до файлу \"%s\": %m" + +#: copy_file.c:188 +#, c-format +msgid "could not write to file \"%s\", offset %u: wrote %d of %d" +msgstr "не вдалося записати до файлу \"%s\", зсув %u: записано %d з %d" + +#: copy_file.c:199 reconstruct.c:771 +#, c-format +msgid "could not read from file \"%s\": %m" +msgstr "не вдалося прочитати з файлу \"%s\": %m" + +#: copy_file.c:218 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %m" +msgstr "помилка при клонуванні файлу \"%s\" в \"%s\": %m" + +#: copy_file.c:229 copy_file.c:272 +#, c-format +msgid "could not create file \"%s\": %m" +msgstr "неможливо створити файл \"%s\": %m" + +#: copy_file.c:237 +#, c-format +msgid "error while cloning file \"%s\" to \"%s\": %s" +msgstr "помилка при клонуванні файлу \"%s\" в \"%s\": %s" + +#: copy_file.c:245 pg_combinebackup.c:251 +#, c-format +msgid "file cloning not supported on this platform" +msgstr "клонування файлів не підтримується на цій платформі" + +#: copy_file.c:278 reconstruct.c:691 +#, c-format +msgid "error while copying file range from \"%s\" to \"%s\": %m" +msgstr "помилка при копіюванні діапазону файлу від \"%s\" до \"%s\": %m" + +#: copy_file.c:285 pg_combinebackup.c:264 reconstruct.c:711 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range не підтримується на цій платформі" + +#: copy_file.c:300 +#, c-format +msgid "could not copy file \"%s\" to \"%s\": %m" +msgstr "не вдалося скопіювати файл \"%s\" в \"%s\": %m" + +#: load_manifest.c:125 +#, c-format +msgid "file \"%s\" does not exist" +msgstr "файл \"%s\" не існує" + +#: load_manifest.c:163 +#, c-format +msgid "could not read file \"%s\": read %d of %lld" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %lld" + +#: load_manifest.c:201 +#, c-format +msgid "could not read file \"%s\": read %lld of %lld" +msgstr "не вдалося прочитати файл \"%s\": прочитано %lld з %lld" + +#: load_manifest.c:249 +#, c-format +msgid "backup manifest version 1 does not support incremental backup" +msgstr "маніфест резервного копіювання версії 1 не підтримує інкреметного резервного копіювання" + +#: load_manifest.c:281 +#, c-format +msgid "duplicate path name in backup manifest: \"%s\"" +msgstr "дубльований шлях у маніфесті резервного копіювання: \"%s\"" + +#: pg_combinebackup.c:220 pg_combinebackup.c:228 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Спробуйте \"%s --help\" для додаткової інформації." + +#: pg_combinebackup.c:227 +#, c-format +msgid "no input directories specified" +msgstr "вхідні каталоги не вказано" + +#: pg_combinebackup.c:233 +#, c-format +msgid "no output directory specified" +msgstr "вихідний каталог не вказано" + +#: pg_combinebackup.c:301 +#, c-format +msgid "%s: manifest system identifier is %llu, but control file has %llu" +msgstr "%s: маніфестовий ідентифікатор системи - %llu, але контрольний файл має %llu" + +#: pg_combinebackup.c:340 +#, c-format +msgid "cannot generate a manifest because no manifest is available for the final input backup" +msgstr "не вдається згенерувати маніфест, оскільки для остаточної резервної копії вхідних даних немає маніфесту" + +#: pg_combinebackup.c:387 +#, c-format +msgid "could not create symbolic link from \"%s\" to \"%s\": %m" +msgstr "не вдалося створити символічне послання з \"%s\" на \"%s\": %m" + +#: pg_combinebackup.c:399 pg_combinebackup.c:730 pg_combinebackup.c:927 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не вдалося створити каталог \"%s\": %m" + +#: pg_combinebackup.c:454 +#, c-format +msgid "directory name too long" +msgstr "ім'я директорії задовге" + +#: pg_combinebackup.c:461 +#, c-format +msgid "multiple \"=\" signs in tablespace mapping" +msgstr "кілька знаків \"=\" зіставленні табличних просторів" + +#: pg_combinebackup.c:469 +#, c-format +msgid "invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"" +msgstr "неприпустимий табличний простір зіставлення формату \"%s\", має бути \"OLDDIR = NEWDIR\"" + +#: pg_combinebackup.c:480 pg_combinebackup.c:484 +#, c-format +msgid "old directory is not an absolute path in tablespace mapping: %s" +msgstr "старий каталог не є абсолютним шляхом у зіставлення табличного простору: %s" + +#: pg_combinebackup.c:553 +#, c-format +msgid "backup at \"%s\" is a full backup, but only the first backup should be a full backup" +msgstr "резервна копія за адресою \"%s\" є повною резервною копією, але тільки перша резервна копія має бути повною резервною копією" + +#: pg_combinebackup.c:556 +#, c-format +msgid "backup at \"%s\" is an incremental backup, but the first backup should be a full backup" +msgstr "резервна копія за адресою \"%s\" є інкрементною резервною копією, але перша резервна копія має бути повною" + +#: pg_combinebackup.c:559 +#, c-format +msgid "backup at \"%s\" starts on timeline %u, but expected %u" +msgstr "резервне копіювання на \"%s\" починається на лінії часу %u, але очікується %u" + +#: pg_combinebackup.c:562 +#, c-format +msgid "backup at \"%s\" starts at LSN %X/%X, but expected %X/%X" +msgstr "резервне копіювання на \"%s\" починається з LSN %X/%X, але очікується %X/%X" + +#: pg_combinebackup.c:614 +#, c-format +msgid "%s: CRC is incorrect" +msgstr "%s: CRC невірний" + +#: pg_combinebackup.c:618 +#, c-format +msgid "%s: unexpected control file version" +msgstr "%s: неочікувана версія контрольного файлу" + +#: pg_combinebackup.c:625 +#, c-format +msgid "%s: expected system identifier %llu, but found %llu" +msgstr "%s: очікуваний ідентифікатор системи %llu, але знайдено %llu" + +#: pg_combinebackup.c:657 +#, c-format +msgid "only some backups have checksums enabled" +msgstr "лише деякі резервні копії мають включені контрольні суми" + +#: pg_combinebackup.c:658 +#, c-format +msgid "Disable, and optionally reenable, checksums on the output directory to avoid failures." +msgstr "Вимкніть, та за бажанням увімкніть, контрольні суми для вихідного каталога, щоб уникнути помилок." + +#: pg_combinebackup.c:693 +#, c-format +msgid "removing output directory \"%s\"" +msgstr "видалення вихідного каталогу \"%s\"" + +#: pg_combinebackup.c:695 +#, c-format +msgid "failed to remove output directory" +msgstr "не вдалося вилучити вихідний каталог" + +#: pg_combinebackup.c:699 +#, c-format +msgid "removing contents of output directory \"%s\"" +msgstr "видалення вмісту вихідного каталогу \"%s\"" + +#: pg_combinebackup.c:702 +#, c-format +msgid "failed to remove contents of output directory" +msgstr "не вдалося вилучити вміст з вихідного каталогу" + +#: pg_combinebackup.c:742 +#, c-format +msgid "directory \"%s\" exists but is not empty" +msgstr "каталог \"%s\" існує, але він не порожній" + +#: pg_combinebackup.c:745 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "немає доступу до каталогу \"%s\": %m" + +#: pg_combinebackup.c:759 +#, c-format +msgid "%s reconstructs full backups from incrementals.\n\n" +msgstr "%s відновлює повні резервні копії з інкрементів.\n\n" + +#: pg_combinebackup.c:760 +#, c-format +msgid "Usage:\n" +msgstr "Використання:\n" + +#: pg_combinebackup.c:761 +#, c-format +msgid " %s [OPTION]... DIRECTORY...\n" +msgstr " %s [ПАРАМЕТР]... КАТАЛОГ...\n" + +#: pg_combinebackup.c:762 +#, c-format +msgid "\n" +"Options:\n" +msgstr "\n" +"Параметри:\n" + +#: pg_combinebackup.c:763 +#, c-format +msgid " -d, --debug generate lots of debugging output\n" +msgstr " -d, --debug генерувати багато налагоджувальних повідомлень\n" + +#: pg_combinebackup.c:764 +#, c-format +msgid " -n, --dry-run do not actually do anything\n" +msgstr " -n, --dry-run насправді ніякої дії\n" + +#: pg_combinebackup.c:765 +#, c-format +msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" +msgstr " -N, --no-sync не чекати на безпечний запис змін на диск\n" + +#: pg_combinebackup.c:766 +#, c-format +msgid " -o, --output=DIRECTORY output directory\n" +msgstr " -o, --output=DIRECTORY вихідний каталог\n" + +#: pg_combinebackup.c:767 +#, c-format +msgid " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" relocate tablespace in OLDDIR to NEWDIR\n" +msgstr " -T, --tablespace-mapping=OLDDIR=NEWDIR\n" +" перемістити табличний простір з OLDDIR в NEWDIR\n" + +#: pg_combinebackup.c:769 +#, c-format +msgid " --clone clone (reflink) files instead of copying\n" +msgstr " --clone клонувати (reflink) файли замість копіювання\n" + +#: pg_combinebackup.c:770 +#, c-format +msgid " --copy copy files (default)\n" +msgstr " --copy копіювати файли (за замовчуванням)\n" + +#: pg_combinebackup.c:771 +#, c-format +msgid " --copy-file-range copy using copy_file_range() system call\n" +msgstr " --copy-file-range копіювати за допомогою системного виклику copy_file_range()\n" + +#: pg_combinebackup.c:772 +#, c-format +msgid " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" use algorithm for manifest checksums\n" +msgstr " --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n" +" алгоритм використання контрольних сум маніфесту\n" + +#: pg_combinebackup.c:774 +#, c-format +msgid " --no-manifest suppress generation of backup manifest\n" +msgstr " --no-manifest заборонити створення маніфесту резервної копії\n" + +#: pg_combinebackup.c:775 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод синхронізації файлів на диск\n" + +#: pg_combinebackup.c:776 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію і вийти\n" + +#: pg_combinebackup.c:777 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку, потім вийти\n" + +#: pg_combinebackup.c:779 +#, c-format +msgid "\n" +"Report bugs to <%s>.\n" +msgstr "\n" +"Повідомляти про помилки на <%s>.\n" + +#: pg_combinebackup.c:780 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашня сторінка %s: <%s>\n" + +#: pg_combinebackup.c:995 +#, c-format +msgid "skipping symbolic link \"%s\"" +msgstr "пропускання символічного посилання \"%s\"" + +#: pg_combinebackup.c:997 +#, c-format +msgid "skipping special file \"%s\"" +msgstr "спеціальний файл \"%s\" пропускається" + +#: pg_combinebackup.c:1073 reconstruct.c:300 +#, c-format +msgid "manifest file \"%s\" contains no entry for file \"%s\"" +msgstr "файл маніфеста \"%s\" не містить запису для файлу \"%s\"" + +#: pg_combinebackup.c:1189 +#, c-format +msgid "%s: server version too old" +msgstr "%s: версія серверу застаріла" + +#: pg_combinebackup.c:1190 +#, c-format +msgid "%s: could not parse version number" +msgstr "%s: не вдалося розібрати номер версії" + +#: pg_combinebackup.c:1309 +#, c-format +msgid "could not read symbolic link \"%s\": %m" +msgstr "не можливо прочитати символічне послання \"%s\": %m" + +#: pg_combinebackup.c:1312 +#, c-format +msgid "target of symbolic link \"%s\" is too long" +msgstr "ціль символічного посилання \"%s\" занадто довга" + +#: pg_combinebackup.c:1315 +#, c-format +msgid "target of symbolic link \"%s\" is relative" +msgstr "ціль символічного посилання \"%s\" є відносною" + +#: pg_combinebackup.c:1337 +#, c-format +msgid "tablespace at \"%s\" has no tablespace mapping" +msgstr "табличний простір за адресою \"%s\" не має зіставлення табличного простору" + +#: pg_combinebackup.c:1355 +#, c-format +msgid "tablespaces with OIDs %u and %u both point at directory \"%s\"" +msgstr "табличні простори з OID %u та %u обидва вказують на каталог \"%s\"" + +#: pg_combinebackup.c:1364 +#, c-format +msgid "could not close directory \"%s\": %m" +msgstr "не вдалося закрити каталог \"%s\": %m" + +#: pg_combinebackup.c:1385 +#, c-format +msgid "file \"%s\" is too large" +msgstr "файл \"%s\" занадто великий" + +#: pg_combinebackup.c:1402 +#, c-format +msgid "could not read file \"%s\": read %zd of %lld" +msgstr "не вдалося прочитати файл \"%s\": прочитано %zd з %lld" + +#: reconstruct.c:410 +#, c-format +msgid "file \"%s\" is too short: expected %llu, found %llu" +msgstr "файл \"%s\" занадто короткий: очікується %llu, знайдено %llu" + +#: reconstruct.c:452 +#, c-format +msgid "file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)" +msgstr "файл \"%s\" має неправильне інкрементне магічне число (0x%x, очікувалось 0x%x)" + +#: reconstruct.c:458 +#, c-format +msgid "file \"%s\" has block count %u in excess of segment size %u" +msgstr "файл \"%s\" має кількість блоків %u, що перевищує розмір сегмента %u" + +#: reconstruct.c:465 +#, c-format +msgid "file \"%s\" has truncation block length %u in excess of segment size %u" +msgstr "файл \"%s\" має довжину блоку усікання %u, що перевищує розмір сегмента %u" + +#: reconstruct.c:529 +#, c-format +msgid "could not read file \"%s\": read %d of %u" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %u" + +#: reconstruct.c:773 +#, c-format +msgid "could not read from file \"%s\", offset %llu: read %d of %d" +msgstr "не вдалося прочитати з файлу \"%s\", зміщення %llu: прочитано %d з %d" + diff --git a/src/bin/pg_combinebackup/reconstruct.c b/src/bin/pg_combinebackup/reconstruct.c index a08ca221457cf..8acaa54ff38b4 100644 --- a/src/bin/pg_combinebackup/reconstruct.c +++ b/src/bin/pg_combinebackup/reconstruct.c @@ -3,7 +3,7 @@ * reconstruct.c * Reconstruct full file from incremental file and backup chain. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_combinebackup/reconstruct.c @@ -77,8 +77,9 @@ static void read_block(rfile *s, off_t off, uint8 *buffer); * * relative_path should be the path to the directory containing this file, * relative to the root of the backup (NOT relative to the root of the - * tablespace). bare_file_name should be the name of the file within that - * directory, without "INCREMENTAL.". + * tablespace). It must always end with a trailing slash. bare_file_name + * should be the name of the file within that directory, without + * "INCREMENTAL.". * * n_prior_backups is the number of prior backups, and prior_backup_dirs is * an array of pathnames where those backups can be found. @@ -111,6 +112,10 @@ reconstruct_from_incremental_file(char *input_filename, rfile *copy_source = NULL; pg_checksum_context checksum_ctx; + /* Sanity check the relative_path. */ + Assert(relative_path[0] != '\0'); + Assert(relative_path[strlen(relative_path) - 1] == '/'); + /* * Every block must come either from the latest version of the file or * from one of the prior backups. @@ -174,11 +179,11 @@ reconstruct_from_incremental_file(char *input_filename, * Look for the full file in the previous backup. If not found, then * look for an incremental file instead. */ - snprintf(source_filename, MAXPGPATH, "%s/%s/%s", + snprintf(source_filename, MAXPGPATH, "%s/%s%s", prior_backup_dirs[sidx], relative_path, bare_file_name); if ((s = make_rfile(source_filename, true)) == NULL) { - snprintf(source_filename, MAXPGPATH, "%s/%s/INCREMENTAL.%s", + snprintf(source_filename, MAXPGPATH, "%s/%sINCREMENTAL.%s", prior_backup_dirs[sidx], relative_path, bare_file_name); s = make_incremental_rfile(source_filename); } @@ -209,7 +214,7 @@ reconstruct_from_incremental_file(char *input_filename, * taking no action on those blocks that generated any WAL. * * Sadly, we have no way of validating that this is really what - * happened, and neither does the server. From it's perspective, + * happened, and neither does the server. From its perspective, * an unmodified block that contains data looks exactly the same * as a zero-filled block that never had any data: either way, * it's not mentioned in any WAL summary and the server has no @@ -321,11 +326,19 @@ reconstruct_from_incremental_file(char *input_filename, * result, then forget about performing reconstruction and just copy that * file in its entirety. * + * If we have only incremental files, and there's no full file at any + * point in the backup chain, something has gone wrong. Emit an error. + * * Otherwise, reconstruct. */ if (copy_source != NULL) copy_file(copy_source->filename, output_filename, &checksum_ctx, copy_method, dry_run); + else if (sidx == 0 && source[0]->header_length != 0) + { + pg_fatal("full backup contains unexpected incremental file \"%s\"", + source[0]->filename); + } else { write_reconstructed_file(input_filename, output_filename, @@ -449,7 +462,7 @@ make_incremental_rfile(char *filename) /* Read and validate magic number. */ read_bytes(rf, &magic, sizeof(magic)); if (magic != INCREMENTAL_MAGIC) - pg_fatal("file \"%s\" has bad incremental magic number (0x%x not 0x%x)", + pg_fatal("file \"%s\" has bad incremental magic number (0x%x, expected 0x%x)", filename, magic, INCREMENTAL_MAGIC); /* Read block count. */ diff --git a/src/bin/pg_combinebackup/reconstruct.h b/src/bin/pg_combinebackup/reconstruct.h index c878febbb3862..c605fd7efdde0 100644 --- a/src/bin/pg_combinebackup/reconstruct.h +++ b/src/bin/pg_combinebackup/reconstruct.h @@ -3,7 +3,7 @@ * reconstruct.h * Reconstruct full file from incremental file and backup chain. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_combinebackup/reconstruct.h diff --git a/src/bin/pg_combinebackup/t/001_basic.pl b/src/bin/pg_combinebackup/t/001_basic.pl index a2b7f30d59e55..123bf4a21fb28 100644 --- a/src/bin/pg_combinebackup/t/001_basic.pl +++ b/src/bin/pg_combinebackup/t/001_basic.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_combinebackup/t/002_compare_backups.pl b/src/bin/pg_combinebackup/t/002_compare_backups.pl index 63a0255de1522..2c7ca89b92f7f 100644 --- a/src/bin/pg_combinebackup/t/002_compare_backups.pl +++ b/src/bin/pg_combinebackup/t/002_compare_backups.pl @@ -1,8 +1,8 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; -use File::Compare; +use File::Compare qw(compare_text); use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; use Test::More; @@ -58,9 +58,11 @@ mkdir($tsbackup1path) || die "mkdir $tsbackup1path: $!"; $primary->command_ok( [ - 'pg_basebackup', '-D', - $backup1path, '--no-sync', - '-cfast', "-T${tsprimary}=${tsbackup1path}" + 'pg_basebackup', + '--no-sync', + '--pgdata' => $backup1path, + '--checkpoint' => 'fast', + '--tablespace-mapping' => "${tsprimary}=${tsbackup1path}" ], "full backup"); @@ -89,10 +91,12 @@ mkdir($tsbackup2path) || die "mkdir $tsbackup2path: $!"; $primary->command_ok( [ - 'pg_basebackup', '-D', - $backup2path, '--no-sync', - '-cfast', "-T${tsprimary}=${tsbackup2path}", - '--incremental', $backup1path . '/backup_manifest' + 'pg_basebackup', + '--no-sync', + '--pgdata' => $backup2path, + '--checkpoint' => 'fast', + '--tablespace-mapping' => "${tsprimary}=${tsbackup2path}", + '--incremental' => $backup1path . '/backup_manifest' ], "incremental backup"); @@ -169,38 +173,31 @@ my $dump2 = $backupdir . '/pitr2.dump'; $pitr1->command_ok( [ - 'pg_dumpall', '-f', - $dump1, '--no-sync', - '--no-unlogged-table-data', '-d', - $pitr1->connstr('postgres'), + 'pg_dumpall', + '--no-sync', + '--no-unlogged-table-data', + '--file' => $dump1, + '--dbname' => $pitr1->connstr('postgres'), ], 'dump from PITR 1'); -$pitr1->command_ok( +$pitr2->command_ok( [ - 'pg_dumpall', '-f', - $dump2, '--no-sync', - '--no-unlogged-table-data', '-d', - $pitr1->connstr('postgres'), + 'pg_dumpall', + '--no-sync', + '--no-unlogged-table-data', + '--file' => $dump2, + '--dbname' => $pitr2->connstr('postgres'), ], 'dump from PITR 2'); -# Compare the two dumps, there should be no differences. -my $compare_res = compare($dump1, $dump2); -note($dump1); -note($dump2); -is($compare_res, 0, "dumps are identical"); - -# Provide more context if the dumps do not match. -if ($compare_res != 0) -{ - my ($stdout, $stderr) = - run_command([ 'diff', '-u', $dump1, $dump2 ]); - print "=== diff of $dump1 and $dump2\n"; - print "=== stdout ===\n"; - print $stdout; - print "=== stderr ===\n"; - print $stderr; - print "=== EOF ===\n"; -} +# Compare the two dumps, there should be no differences other than +# the tablespace paths. +compare_files( + $dump1, $dump2, + "contents of dumps match for both PITRs", + sub { + s{create tablespace .* location .*\btspitr\K[12]}{N}i for @_; + return $_[0] ne $_[1]; + }); done_testing(); diff --git a/src/bin/pg_combinebackup/t/003_timeline.pl b/src/bin/pg_combinebackup/t/003_timeline.pl index b9c67341ad83a..0205a59f927ef 100644 --- a/src/bin/pg_combinebackup/t/003_timeline.pl +++ b/src/bin/pg_combinebackup/t/003_timeline.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # This test aims to validate that restoring an incremental backup works # properly even when the reference backup is on a different timeline. @@ -30,7 +30,12 @@ # Take a full backup. my $backup1path = $node1->backup_dir . '/backup1'; $node1->command_ok( - [ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast' + ], "full backup from node1"); # Insert a second row on the original node. @@ -42,8 +47,11 @@ my $backup2path = $node1->backup_dir . '/backup2'; $node1->command_ok( [ - 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast', - '--incremental', $backup1path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest' ], "incremental backup from node1"); @@ -65,8 +73,11 @@ my $backup3path = $node1->backup_dir . '/backup3'; $node2->command_ok( [ - 'pg_basebackup', '-D', $backup3path, '--no-sync', '-cfast', - '--incremental', $backup2path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup3path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup2path . '/backup_manifest' ], "incremental backup from node2"); diff --git a/src/bin/pg_combinebackup/t/004_manifest.pl b/src/bin/pg_combinebackup/t/004_manifest.pl index 9b09ae2641d0d..2a69d4d9b9ca0 100644 --- a/src/bin/pg_combinebackup/t/004_manifest.pl +++ b/src/bin/pg_combinebackup/t/004_manifest.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # This test aims to validate that pg_combinebackup works in the degenerate # case where it is invoked on a single full backup and that it can produce @@ -25,7 +25,12 @@ # Take a full backup. my $original_backup_path = $node->backup_dir . '/original'; $node->command_ok( - [ 'pg_basebackup', '-D', $original_backup_path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $original_backup_path, + '--no-sync', + '--checkpoint' => 'fast', + ], "full backup"); # Verify the full backup. @@ -39,9 +44,11 @@ sub combine_and_test_one_backup my $revised_backup_path = $node->backup_dir . '/' . $backup_name; $node->command_ok( [ - 'pg_combinebackup', $original_backup_path, - '-o', $revised_backup_path, - '--no-sync', @extra_options + 'pg_combinebackup', + $original_backup_path, + '--output' => $revised_backup_path, + '--no-sync', + @extra_options, ], "pg_combinebackup with @extra_options"); if (defined $failure_pattern) diff --git a/src/bin/pg_combinebackup/t/005_integrity.pl b/src/bin/pg_combinebackup/t/005_integrity.pl index 25ebb8c04068d..cfacf5ad7a001 100644 --- a/src/bin/pg_combinebackup/t/005_integrity.pl +++ b/src/bin/pg_combinebackup/t/005_integrity.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # This test aims to validate that an incremental backup can be combined # with a valid prior backup and that it cannot be combined with an invalid @@ -43,15 +43,23 @@ # Take a full backup from node1. my $backup1path = $node1->backup_dir . '/backup1'; $node1->command_ok( - [ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast', + ], "full backup from node1"); # Now take an incremental backup. my $backup2path = $node1->backup_dir . '/backup2'; $node1->command_ok( [ - 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast', - '--incremental', $backup1path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest', ], "incremental backup from node1"); @@ -59,23 +67,34 @@ my $backup3path = $node1->backup_dir . '/backup3'; $node1->command_ok( [ - 'pg_basebackup', '-D', $backup3path, '--no-sync', '-cfast', - '--incremental', $backup2path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup3path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup2path . '/backup_manifest', ], "another incremental backup from node1"); # Take a full backup from node2. my $backupother1path = $node1->backup_dir . '/backupother1'; $node2->command_ok( - [ 'pg_basebackup', '-D', $backupother1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backupother1path, + '--no-sync', + '--checkpoint' => 'fast', + ], "full backup from node2"); # Take an incremental backup from node2. my $backupother2path = $node1->backup_dir . '/backupother2'; $node2->command_ok( [ - 'pg_basebackup', '-D', $backupother2path, '--no-sync', '-cfast', - '--incremental', $backupother1path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backupother2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backupother1path . '/backup_manifest', ], "incremental backup from node2"); @@ -85,8 +104,9 @@ # Can't combine 2 full backups. $node1->command_fails_like( [ - 'pg_combinebackup', $backup1path, $backup1path, '-o', - $resultpath, $mode + 'pg_combinebackup', $backup1path, $backup1path, + '--output' => $resultpath, + $mode, ], qr/is a full backup, but only the first backup should be a full backup/, "can't combine full backups"); @@ -94,8 +114,9 @@ # Can't combine 2 incremental backups. $node1->command_fails_like( [ - 'pg_combinebackup', $backup2path, $backup2path, '-o', - $resultpath, $mode + 'pg_combinebackup', $backup2path, $backup2path, + '--output' => $resultpath, + $mode, ], qr/is an incremental backup, but the first backup should be a full backup/, "can't combine full backups"); @@ -103,8 +124,9 @@ # Can't combine full backup with an incremental backup from a different system. $node1->command_fails_like( [ - 'pg_combinebackup', $backup1path, $backupother2path, '-o', - $resultpath, $mode + 'pg_combinebackup', $backup1path, $backupother2path, + '--output' => $resultpath, + $mode, ], qr/expected system identifier.*but found/, "can't combine backups from different nodes"); @@ -117,7 +139,8 @@ $node1->command_fails_like( [ 'pg_combinebackup', $backup1path, $backup2path, $backup3path, - '-o', $resultpath, $mode + '--output' => $resultpath, + $mode, ], qr/ manifest system identifier is .*, but control file has /, "can't combine backups with different manifest system identifier "); @@ -128,8 +151,9 @@ # Can't omit a required backup. $node1->command_fails_like( [ - 'pg_combinebackup', $backup1path, $backup3path, '-o', - $resultpath, $mode + 'pg_combinebackup', $backup1path, $backup3path, + '--output' => $resultpath, + $mode, ], qr/starts at LSN.*but expected/, "can't omit a required backup"); @@ -138,7 +162,8 @@ $node1->command_fails_like( [ 'pg_combinebackup', $backup1path, $backup3path, $backup2path, - '-o', $resultpath, $mode + '--output' => $resultpath, + $mode, ], qr/starts at LSN.*but expected/, "can't combine backups in the wrong order"); @@ -147,7 +172,8 @@ $node1->command_ok( [ 'pg_combinebackup', $backup1path, $backup2path, $backup3path, - '-o', $resultpath, $mode + '--output' => $resultpath, + $mode, ], "can combine 3 matching backups"); rmtree($resultpath); @@ -156,17 +182,18 @@ my $synthetic12path = $node1->backup_dir . '/synthetic12'; $node1->command_ok( [ - 'pg_combinebackup', $backup1path, $backup2path, '-o', - $synthetic12path, $mode + 'pg_combinebackup', $backup1path, $backup2path, + '--output' => $synthetic12path, + $mode, ], "can combine 2 matching backups"); # Can combine result of previous step with second incremental. $node1->command_ok( [ - 'pg_combinebackup', $synthetic12path, - $backup3path, '-o', - $resultpath, $mode + 'pg_combinebackup', $synthetic12path, $backup3path, + '--output' => $resultpath, + $mode, ], "can combine synthetic backup with later incremental"); rmtree($resultpath); @@ -174,9 +201,9 @@ # Can't combine result of 1+2 with 2. $node1->command_fails_like( [ - 'pg_combinebackup', $synthetic12path, - $backup2path, '-o', - $resultpath, $mode + 'pg_combinebackup', $synthetic12path, $backup2path, + '--output' => $resultpath, + $mode, ], qr/starts at LSN.*but expected/, "can't combine synthetic backup with included incremental"); diff --git a/src/bin/pg_combinebackup/t/006_db_file_copy.pl b/src/bin/pg_combinebackup/t/006_db_file_copy.pl index 60bdc8d00f79a..65dd4e2d46074 100644 --- a/src/bin/pg_combinebackup/t/006_db_file_copy.pl +++ b/src/bin/pg_combinebackup/t/006_db_file_copy.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -29,7 +29,12 @@ # Take a full backup. my $backup1path = $primary->backup_dir . '/backup1'; $primary->command_ok( - [ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast' + ], "full backup"); # Now make some database changes. @@ -42,8 +47,11 @@ my $backup2path = $primary->backup_dir . '/backup2'; $primary->command_ok( [ - 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast', - '--incremental', $backup1path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest' ], "incremental backup"); diff --git a/src/bin/pg_combinebackup/t/007_wal_level_minimal.pl b/src/bin/pg_combinebackup/t/007_wal_level_minimal.pl index 900df6b2864a7..be24e0558922a 100644 --- a/src/bin/pg_combinebackup/t/007_wal_level_minimal.pl +++ b/src/bin/pg_combinebackup/t/007_wal_level_minimal.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # This test aims to validate that taking an incremental backup fails when # wal_level has been changed to minimal between the full backup and the @@ -34,7 +34,12 @@ # Take a full backup. my $backup1path = $node1->backup_dir . '/backup1'; $node1->command_ok( - [ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast' + ], "full backup"); # Switch to wal_level=minimal, which also requires max_wal_senders=0 and @@ -63,8 +68,11 @@ my $backup2path = $node1->backup_dir . '/backup2'; $node1->command_fails_like( [ - 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast', - '--incremental', $backup1path . '/backup_manifest' + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest' ], qr/WAL summaries are required on timeline 1 from.*are incomplete/, "incremental backup fails"); diff --git a/src/bin/pg_combinebackup/t/008_promote.pl b/src/bin/pg_combinebackup/t/008_promote.pl index 1154a5d8b2241..3a15983f4a131 100644 --- a/src/bin/pg_combinebackup/t/008_promote.pl +++ b/src/bin/pg_combinebackup/t/008_promote.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test whether WAL summaries are complete such that incremental backup # can be performed after promoting a standby at an arbitrary LSN. @@ -31,7 +31,12 @@ # Take a full backup. my $backup1path = $node1->backup_dir . '/backup1'; $node1->command_ok( - [ 'pg_basebackup', '-D', $backup1path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast', + ], "full backup from node1"); # Checkpoint and record LSN after. @@ -47,15 +52,16 @@ # then stop recovery at some arbitrary LSN, not just when it hits the end of # WAL, so use a recovery target. my $node2 = PostgreSQL::Test::Cluster->new('node2'); -$node2->init_from_backup($node1, 'backup1', 'has_streaming' => 1); +$node2->init_from_backup($node1, 'backup1', has_streaming => 1); $node2->append_conf('postgresql.conf', <start(); -# Wait until recoveery pauses, then promote. -$node2->poll_query_until('postgres', "SELECT pg_get_wal_replay_pause_state() = 'paused';"); +# Wait until recovery pauses, then promote. +$node2->poll_query_until('postgres', + "SELECT pg_get_wal_replay_pause_state() = 'paused';"); $node2->safe_psql('postgres', "SELECT pg_promote()"); # Once promotion occurs, insert a second row on the new node. @@ -65,17 +71,22 @@ EOM # Now take an incremental backup. If WAL summarization didn't follow the -# timeline cange correctly, something should break at this point. +# timeline change correctly, something should break at this point. my $backup2path = $node1->backup_dir . '/backup2'; $node2->command_ok( - [ 'pg_basebackup', '-D', $backup2path, '--no-sync', '-cfast', - '--incremental', $backup1path . '/backup_manifest' ], + [ + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest', + ], "incremental backup from node2"); # Restore the incremental backup and use it to create a new node. my $node3 = PostgreSQL::Test::Cluster->new('node3'); $node3->init_from_backup($node1, 'backup2', - combine_with_prior => [ 'backup1' ]); + combine_with_prior => ['backup1']); $node3->start(); done_testing(); diff --git a/src/bin/pg_combinebackup/t/009_no_full_file.pl b/src/bin/pg_combinebackup/t/009_no_full_file.pl new file mode 100644 index 0000000000000..abe9e9a6a8113 --- /dev/null +++ b/src/bin/pg_combinebackup/t/009_no_full_file.pl @@ -0,0 +1,75 @@ +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; +use File::Copy; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Can be changed to test the other modes. +my $mode = $ENV{PG_TEST_PG_COMBINEBACKUP_MODE} || '--copy'; + +note "testing using mode $mode"; + +# Set up a new database instance. +my $primary = PostgreSQL::Test::Cluster->new('primary'); +$primary->init(has_archiving => 1, allows_streaming => 1); +$primary->append_conf('postgresql.conf', 'summarize_wal = on'); +$primary->start; + +# Take a full backup. +my $backup1path = $primary->backup_dir . '/backup1'; +$primary->command_ok( + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast' + ], + "full backup"); + +# Take an incremental backup. +my $backup2path = $primary->backup_dir . '/backup2'; +$primary->command_ok( + [ + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--incremental' => $backup1path . '/backup_manifest' + ], + "incremental backup"); + +# Find an incremental file in the incremental backup for which there is a full +# file in the full backup. When we find one, replace the full file with an +# incremental file. +my @filelist = grep { /^INCREMENTAL\./ } slurp_dir("$backup2path/base/1"); +my $success = 0; +for my $iname (@filelist) +{ + my $name = $iname; + $name =~ s/^INCREMENTAL.//; + + if (-f "$backup1path/base/1/$name") + { + copy("$backup2path/base/1/$iname", "$backup1path/base/1/$iname") + || die "copy $backup2path/base/1/$iname: $!"; + unlink("$backup1path/base/1/$name") + || die "unlink $backup1path/base/1/$name: $!"; + $success = 1; + last; + } +} + +# pg_combinebackup should fail. +my $outpath = $primary->backup_dir . '/out'; +$primary->command_fails_like( + [ + 'pg_combinebackup', $backup1path, + $backup2path, '--output' => $outpath, + ], + qr/full backup contains unexpected incremental file/, + "pg_combinebackup fails"); + +done_testing(); diff --git a/src/bin/pg_combinebackup/t/010_hardlink.pl b/src/bin/pg_combinebackup/t/010_hardlink.pl new file mode 100644 index 0000000000000..a0ee419090cf6 --- /dev/null +++ b/src/bin/pg_combinebackup/t/010_hardlink.pl @@ -0,0 +1,169 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group +# +# This test aims to validate that hard links are created as expected in the +# output directory, when running pg_combinebackup with --link mode. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Set up a new database instance. +my $primary = PostgreSQL::Test::Cluster->new('primary'); +$primary->init(has_archiving => 1, allows_streaming => 1); +$primary->append_conf('postgresql.conf', 'summarize_wal = on'); +# We disable autovacuum to prevent "something else" to modify our test tables. +$primary->append_conf('postgresql.conf', 'autovacuum = off'); +$primary->start; + +# Create a couple of tables (~264KB each). +# Note: Cirrus CI runs some tests with a very small segment size, so, in that +# environment, a single table of 264KB would have both a segment with a link +# count of 1 and also one with a link count of 2. But in a normal installation, +# segment size is 1GB. Therefore, we use 2 different tables here: for test_1, +# all segments (or the only one) will have two hard links; for test_2, the +# last segment (or the only one) will have 1 hard link, and any others will +# have 2. +my $query = <<'EOM'; +CREATE TABLE test_%s AS + SELECT x.id::bigint, + repeat('a', 1600) AS value + FROM generate_series(1, 100) AS x(id); +EOM + +$primary->safe_psql('postgres', sprintf($query, '1')); +$primary->safe_psql('postgres', sprintf($query, '2')); + +# Fetch information about the data files. +$query = <<'EOM'; +SELECT pg_relation_filepath(oid) +FROM pg_class +WHERE relname = 'test_%s'; +EOM + +my $test_1_path = $primary->safe_psql('postgres', sprintf($query, '1')); +note "test_1 path is $test_1_path"; + +my $test_2_path = $primary->safe_psql('postgres', sprintf($query, '2')); +note "test_2 path is $test_2_path"; + +# Take a full backup. +my $backup1path = $primary->backup_dir . '/backup1'; +$primary->command_ok( + [ + 'pg_basebackup', + '--pgdata' => $backup1path, + '--no-sync', + '--checkpoint' => 'fast', + '--wal-method' => 'none' + ], + "full backup"); + +# Perform an insert that touches a page of the last segment of the data file of +# table test_2. +$primary->safe_psql('postgres', <backup_dir . '/backup2'; +$primary->command_ok( + [ + 'pg_basebackup', + '--pgdata' => $backup2path, + '--no-sync', + '--checkpoint' => 'fast', + '--wal-method' => 'none', + '--incremental' => $backup1path . '/backup_manifest' + ], + "incremental backup"); + +# Restore the incremental backup and use it to create a new node. +my $restore = PostgreSQL::Test::Cluster->new('restore'); +$restore->init_from_backup( + $primary, 'backup2', + combine_with_prior => ['backup1'], + combine_mode => '--link'); + +# Ensure files have the expected count of hard links. We expect all data files +# from test_1 to contain 2 hard links, because they were not touched between the +# full and incremental backups, and the last data file of table test_2 to +# contain a single hard link because of changes in its last page. +my $test_1_full_path = join('/', $restore->data_dir, $test_1_path); +check_data_file($test_1_full_path, 2); + +my $test_2_full_path = join('/', $restore->data_dir, $test_2_path); +check_data_file($test_2_full_path, 1); + +# OK, that's all. +done_testing(); + + +# Given the path to the first segment of a data file, inspect its parent +# directory to find all the segments of that data file, and make sure all the +# segments contain 2 hard links. The last one must have the given number of hard +# links. +# +# Parameters: +# * data_file: path to the first segment of a data file, as per the output of +# pg_relation_filepath. +# * last_segment_nlinks: the number of hard links expected in the last segment +# of the given data file. +sub check_data_file +{ + my ($data_file, $last_segment_nlinks) = @_; + + my @data_file_segments = ($data_file); + + # Start checking for additional segments + my $segment_number = 1; + + while (1) + { + my $next_segment = $data_file . '.' . $segment_number; + + # If the file exists and is a regular file, add it to the list + if (-f $next_segment) + { + push @data_file_segments, $next_segment; + $segment_number++; + } + # Stop the loop if the file doesn't exist + else + { + last; + } + } + + # All segments of the given data file should contain 2 hard links, except + # for the last one, which should match the given number of links. + my $last_segment = pop @data_file_segments; + + for my $segment (@data_file_segments) + { + # Get the file's stat information of each segment + my $nlink_count = get_hard_link_count($segment); + ok($nlink_count == 2, "File '$segment' has 2 hard links"); + } + + # Get the file's stat information of the last segment + my $nlink_count = get_hard_link_count($last_segment); + ok($nlink_count == $last_segment_nlinks, + "File '$last_segment' has $last_segment_nlinks hard link(s)"); +} + + +# Subroutine to get hard link count of a given file. +# Receives the path to a file, and returns the number of hard links of +# that file. +sub get_hard_link_count +{ + my ($file) = @_; + + # Get file stats + my @stats = stat($file); + my $nlink = $stats[3]; # Number of hard links + + return $nlink; +} diff --git a/src/bin/pg_combinebackup/write_manifest.c b/src/bin/pg_combinebackup/write_manifest.c index 369d6d2071c75..313f8929df509 100644 --- a/src/bin/pg_combinebackup/write_manifest.c +++ b/src/bin/pg_combinebackup/write_manifest.c @@ -2,7 +2,7 @@ * * Write a new backup manifest. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/write_manifest.c @@ -74,7 +74,7 @@ create_manifest_writer(char *directory, uint64 system_identifier) */ void add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path, - size_t size, time_t mtime, + uint64 size, time_t mtime, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload) @@ -104,7 +104,7 @@ add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path, appendStringInfoString(&mwriter->buf, "\", "); } - appendStringInfo(&mwriter->buf, "\"Size\": %zu, ", size); + appendStringInfo(&mwriter->buf, "\"Size\": %" PRIu64 ", ", size); appendStringInfoString(&mwriter->buf, "\"Last-Modified\": \""); enlargeStringInfo(&mwriter->buf, 128); diff --git a/src/bin/pg_combinebackup/write_manifest.h b/src/bin/pg_combinebackup/write_manifest.h index ebc4f9441ada5..3bb9c04ec299f 100644 --- a/src/bin/pg_combinebackup/write_manifest.h +++ b/src/bin/pg_combinebackup/write_manifest.h @@ -2,7 +2,7 @@ * * Write a new backup manifest. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_combinebackup/write_manifest.h @@ -23,7 +23,7 @@ extern manifest_writer *create_manifest_writer(char *directory, uint64 system_identifier); extern void add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path, - size_t size, time_t mtime, + uint64 size, time_t mtime, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload); diff --git a/src/bin/pg_config/Makefile b/src/bin/pg_config/Makefile index c54f68c9daddd..38169b0ded5b0 100644 --- a/src/bin/pg_config/Makefile +++ b/src/bin/pg_config/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_config # -# Copyright (c) 1998-2024, PostgreSQL Global Development Group +# Copyright (c) 1998-2025, PostgreSQL Global Development Group # # src/bin/pg_config/Makefile # diff --git a/src/bin/pg_config/meson.build b/src/bin/pg_config/meson.build index b4fddd297abfa..a245e752cbd99 100644 --- a/src/bin/pg_config/meson.build +++ b/src/bin/pg_config/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_config_sources = files( 'pg_config.c', diff --git a/src/bin/pg_config/pg_config.c b/src/bin/pg_config/pg_config.c index 77d09ccfc47ca..28db024263dbd 100644 --- a/src/bin/pg_config/pg_config.c +++ b/src/bin/pg_config/pg_config.c @@ -15,7 +15,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/bin/pg_config/pg_config.c * @@ -25,7 +25,6 @@ #include "postgres_fe.h" #include "common/config_info.h" -#include "port.h" static const char *progname; diff --git a/src/bin/pg_config/po/es.po b/src/bin/pg_config/po/es.po index 4ea583846477a..2ebb19f2a50c9 100644 --- a/src/bin/pg_config/po/es.po +++ b/src/bin/pg_config/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_config (PostgreSQL) 16\n" +"Project-Id-Version: pg_config (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:18+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:48+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -27,35 +27,61 @@ msgstr "" msgid "not recorded" msgstr "no registrado" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "memoria agotada" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + #: pg_config.c:74 #, c-format msgid "" diff --git a/src/bin/pg_config/po/fr.po b/src/bin/pg_config/po/fr.po index 3517868aa2bdb..3433a07cc2ef8 100644 --- a/src/bin/pg_config/po/fr.po +++ b/src/bin/pg_config/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:18+0000\n" -"PO-Revision-Date: 2023-07-30 08:09+0200\n" +"POT-Creation-Date: 2024-07-20 21:19+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../common/config_info.c:134 ../../common/config_info.c:142 #: ../../common/config_info.c:150 ../../common/config_info.c:158 @@ -30,35 +30,61 @@ msgstr "" msgid "not recorded" msgstr "non enregistré" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binaire « %s » invalide : %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "n'a pas pu lire le binaire « %s » : %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "n'a pas pu trouver un « %s » à exécuter" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "n'a pas pu résoudre le chemin « %s » en sa forme absolue : %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "n'a pas pu exécuter la commande « %s » : %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "n'a pas pu lire à partir de la commande « %s » : %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "aucune donnée n'a été renvoyée par la commande « %s »" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "mémoire épuisée" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + #: pg_config.c:74 #, c-format msgid "" @@ -278,56 +304,3 @@ msgstr "%s : n'a pas pu trouver l'exécutable du programme\n" #, c-format msgid "%s: invalid argument: %s\n" msgstr "%s : argument invalide : %s\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide puis quitte\n" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#~ msgid "child process exited with exit code %d" -#~ msgstr "le processus fils a quitté avec le code de sortie %d" - -#~ msgid "child process exited with unrecognized status %d" -#~ msgstr "le processus fils a quitté avec un statut %d non reconnu" - -#~ msgid "child process was terminated by exception 0x%X" -#~ msgstr "le processus fils a été terminé par l'exception 0x%X" - -#~ msgid "child process was terminated by signal %d" -#~ msgstr "le processus fils a été terminé par le signal %d" - -#~ msgid "child process was terminated by signal %s" -#~ msgstr "le processus fils a été terminé par le signal %s" - -#~ msgid "could not change directory to \"%s\"" -#~ msgstr "n'a pas pu accéder au répertoire « %s »" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %m" - -#~ msgid "could not change directory to \"%s\": %s" -#~ msgstr "n'a pas pu changer le répertoire par « %s » : %s" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "n'a pas pu identifier le répertoire courant : %m" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "n'a pas pu lire le binaire « %s »" - -#~ msgid "could not read symbolic link \"%s\"" -#~ msgstr "n'a pas pu lire le lien symbolique « %s »" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "binaire « %s » invalide" - -#~ msgid "pclose failed: %m" -#~ msgstr "échec de pclose : %m" diff --git a/src/bin/pg_config/po/ka.po b/src/bin/pg_config/po/ka.po index 6537557bead61..f0014e3c1fde7 100644 --- a/src/bin/pg_config/po/ka.po +++ b/src/bin/pg_config/po/ka.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pg_config (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-10 07:18+0000\n" +"POT-Creation-Date: 2024-07-01 03:49+0000\n" "PO-Revision-Date: 2024-03-10 20:43+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" @@ -69,6 +69,17 @@ msgstr "%s()-ის შეცდომა: %m" msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + #: pg_config.c:74 #, c-format msgid "" diff --git a/src/bin/pg_config/po/ko.po b/src/bin/pg_config/po/ko.po index de9084760585e..e735330275b57 100644 --- a/src/bin/pg_config/po/ko.po +++ b/src/bin/pg_config/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_config (PostgreSQL) 16\n" +"Project-Id-Version: pg_config (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:48+0000\n" -"PO-Revision-Date: 2023-05-26 13:20+0900\n" +"POT-Creation-Date: 2025-01-17 04:48+0000\n" +"PO-Revision-Date: 2025-01-16 12:53+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean team \n" "Language: ko\n" @@ -22,35 +22,61 @@ msgstr "" msgid "not recorded" msgstr "기록되어 있지 않음" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일임: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "실행할 \"%s\" 파일 찾을 수 없음" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 경로를 절대경로로 바꿀 수 없음: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령으로부터 읽을 수 없음: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령이 아무런 데이터를 반환하지 않음" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "메모리 부족" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + #: pg_config.c:74 #, c-format msgid "" diff --git a/src/bin/pg_config/po/meson.build b/src/bin/pg_config/po/meson.build index 4db4bda6356c8..b407175884072 100644 --- a/src/bin/pg_config/po/meson.build +++ b/src/bin/pg_config/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_config-' + pg_version_major.to_string())] diff --git a/src/bin/pg_config/po/ru.po b/src/bin/pg_config/po/ru.po index 34e80c83c632d..0a86bbb455c6d 100644 --- a/src/bin/pg_config/po/ru.po +++ b/src/bin/pg_config/po/ru.po @@ -5,13 +5,13 @@ # Serguei A. Mokhov , 2004-2005. # Sergey Burladyan , 2009, 2012. # Andrey Sudnik , 2010. -# Alexander Lakhin , 2012-2016, 2017, 2019, 2020, 2021, 2023. +# Alexander Lakhin , 2012-2016, 2017, 2019, 2020, 2021, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_config (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2023-08-29 10:19+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 13:45+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -28,35 +28,61 @@ msgstr "" msgid "not recorded" msgstr "не записано" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "нехватка памяти" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + #: pg_config.c:74 #, c-format msgid "" @@ -295,10 +321,6 @@ msgstr "%s: неверный аргумент: %s\n" #~ msgid "could not identify current directory: %m" #~ msgstr "не удалось определить текущий каталог: %m" -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "не удалось перейти в каталог \"%s\": %m" - #, c-format #~ msgid "could not read symbolic link \"%s\": %m" #~ msgstr "не удалось прочитать символическую ссылку \"%s\": %m" diff --git a/src/bin/pg_config/po/sv.po b/src/bin/pg_config/po/sv.po index 2b5468ec93ac0..d729e3053217d 100644 --- a/src/bin/pg_config/po/sv.po +++ b/src/bin/pg_config/po/sv.po @@ -1,13 +1,13 @@ # Swedish message translation file for pg_config. -# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Mats Erik Andersson , 2014. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-01 14:18+0000\n" -"PO-Revision-Date: 2023-08-30 09:01+0200\n" +"POT-Creation-Date: 2024-07-12 14:19+0000\n" +"PO-Revision-Date: 2024-07-12 18:58+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -23,35 +23,61 @@ msgstr "" msgid "not recorded" msgstr "ej sparad" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "slut på minne" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + #: pg_config.c:74 #, c-format msgid "" @@ -245,15 +271,3 @@ msgstr "%s: kunde inte hitta det egna programmets körbara fil\n" #, c-format msgid "%s: invalid argument: %s\n" msgstr "%s: ogiltigt argument: %s\n" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "kunde inte byta katalog till \"%s\": %m" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "kan inte läsa symbolisk länk \"%s\": %m" diff --git a/src/bin/pg_config/po/uk.po b/src/bin/pg_config/po/uk.po index d64a71c7a55d4..ad38f026516c6 100644 --- a/src/bin/pg_config/po/uk.po +++ b/src/bin/pg_config/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-04-19 11:17+0000\n" -"PO-Revision-Date: 2023-12-20 11:53\n" +"POT-Creation-Date: 2024-08-31 06:19+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_config.pot\n" -"X-Crowdin-File-ID: 973\n" +"X-Crowdin-File: /REL_17_STABLE/pg_config.pot\n" +"X-Crowdin-File-ID: 1024\n" #: ../../common/config_info.c:134 ../../common/config_info.c:142 #: ../../common/config_info.c:150 ../../common/config_info.c:158 @@ -24,35 +24,61 @@ msgstr "" msgid "not recorded" msgstr "не записано" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "недостатньо пам'яті" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + #: pg_config.c:74 #, c-format msgid "\n" diff --git a/src/bin/pg_config/po/zh_CN.po b/src/bin/pg_config/po/zh_CN.po index 8c32e10321f30..b12c1e2da620b 100644 --- a/src/bin/pg_config/po/zh_CN.po +++ b/src/bin/pg_config/po/zh_CN.po @@ -1,20 +1,20 @@ # SOME DESCRIPTIVE TITLE. # This file is put in the public domain. -# FIRST AUTHOR , YEAR. +# Dianjin Wang , 2024 # msgid "" msgstr "" -"Project-Id-Version: pg_config (PostgreSQL) 14\n" +"Project-Id-Version: pg_config (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 05:46+0000\n" -"PO-Revision-Date: 2021-08-15 17:25+0800\n" -"Last-Translator: Jie Zhang \n" +"POT-Creation-Date: 2024-09-13 22:51+0000\n" +"PO-Revision-Date: 2024-09-14 12:07+0800\n" +"Last-Translator: Dianjin Wang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.4\n" +"X-Generator: Poedit 3.4.4\n" #: ../../common/config_info.c:134 ../../common/config_info.c:142 #: ../../common/config_info.c:150 ../../common/config_info.c:158 @@ -23,44 +23,61 @@ msgstr "" msgid "not recorded" msgstr "没有被记录" -#: ../../common/exec.c:136 ../../common/exec.c:253 ../../common/exec.c:299 +#: ../../common/exec.c:174 #, c-format -msgid "could not identify current directory: %m" -msgstr "无法确认当前目录: %m" +msgid "invalid binary \"%s\": %m" +msgstr "无效的二进制 \"%s\": %m" -#: ../../common/exec.c:155 +#: ../../common/exec.c:217 #, c-format -msgid "invalid binary \"%s\"" -msgstr "无效的二进制码 \"%s\"" +msgid "could not read binary \"%s\": %m" +msgstr "无法读取二进制 \"%s\": %m" -#: ../../common/exec.c:205 +#: ../../common/exec.c:225 #, c-format -msgid "could not read binary \"%s\"" -msgstr "无法读取二进制码 \"%s\"" +msgid "could not find a \"%s\" to execute" +msgstr "未能找到一个 \"%s\" 予以执行" -#: ../../common/exec.c:213 +#: ../../common/exec.c:252 #, c-format -msgid "could not find a \"%s\" to execute" -msgstr "未能找到一个 \"%s\" 来执行" +msgid "could not resolve path \"%s\" to absolute form: %m" +msgstr "无法将路径 \"%s\" 解析为绝对路径格式: %m" -#: ../../common/exec.c:269 ../../common/exec.c:308 +#: ../../common/exec.c:382 #, c-format -msgid "could not change directory to \"%s\": %m" -msgstr "无法跳转到目录 \"%s\" 中: %m" +msgid "could not execute command \"%s\": %m" +msgstr "无法执行命令 \"%s\": %m" -#: ../../common/exec.c:286 +#: ../../common/exec.c:394 #, c-format -msgid "could not read symbolic link \"%s\": %m" -msgstr "无法读取符号链接 \"%s\": %m" +msgid "could not read from command \"%s\": %m" +msgstr "无法读取命令 \"%s\": %m" -#: ../../common/exec.c:409 +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "命令 \"%s\" 未返回数据" + +#: ../../common/exec.c:424 +#, c-format msgid "%s() failed: %m" -msgstr "%s()失败: %m" +msgstr "%s() 失败: %m" -#: ../../common/exec.c:522 ../../common/exec.c:567 ../../common/exec.c:659 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "内存不足" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "内存不足\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "无法复制空指针 (内部错误)\n" + #: pg_config.c:74 #, c-format msgid "" @@ -69,7 +86,7 @@ msgid "" "\n" msgstr "" "\n" -"%s 提供 PostgreSQL 的安装信息.\n" +"%s 提供所安装 PostgreSQL 版本的信息.\n" "\n" #: pg_config.c:75 @@ -82,7 +99,9 @@ msgstr "使用方法:\n" msgid "" " %s [OPTION]...\n" "\n" -msgstr " %s [选项]...\n" +msgstr "" +" %s [选项]...\n" +"\n" #: pg_config.c:77 #, c-format @@ -92,17 +111,17 @@ msgstr "选项:\n" #: pg_config.c:78 #, c-format msgid " --bindir show location of user executables\n" -msgstr " --bindir 显示执行文件所在位置\n" +msgstr " --bindir 显示用户执行文件所在位置\n" #: pg_config.c:79 #, c-format msgid " --docdir show location of documentation files\n" -msgstr " --docdir 显示文档所在位置\n" +msgstr " --docdir 显示文档文件所在位置\n" #: pg_config.c:80 #, c-format msgid " --htmldir show location of HTML documentation files\n" -msgstr " --htmldir 显示HTML文档文件所在位置\n" +msgstr " --htmldir 显示 HTML 文档文件所在位置\n" #: pg_config.c:81 #, c-format @@ -110,18 +129,18 @@ msgid "" " --includedir show location of C header files of the client\n" " interfaces\n" msgstr "" -" --includedir 显示客户端接口 C 头文件所在\n" +" --includedir 显示客户端接口 C 语言头文件所在\n" " 位置\n" #: pg_config.c:83 #, c-format msgid " --pkgincludedir show location of other C header files\n" -msgstr " --pkgincludedir 显示其它C语言头文件所在的位置\n" +msgstr " --pkgincludedir 显示其它 C 语言头文件所在位置\n" #: pg_config.c:84 #, c-format msgid " --includedir-server show location of C header files for the server\n" -msgstr " --includedir-server 显示服务端 C 头文件所在位置\n" +msgstr " --includedir-server 显示服务器端 C 语言头文件所在位置\n" #: pg_config.c:85 #, c-format @@ -151,7 +170,7 @@ msgstr " --sharedir 显示独立架构支持文件所在位置\n" #: pg_config.c:90 #, c-format msgid " --sysconfdir show location of system-wide configuration files\n" -msgstr " --sysconfdir 显示系统范围的配置文件的所在位置\n" +msgstr " --sysconfdir 显示系统范围的配置文件所在位置\n" #: pg_config.c:91 #, c-format @@ -164,53 +183,53 @@ msgid "" " --configure show options given to \"configure\" script when\n" " PostgreSQL was built\n" msgstr "" -" --configure 显示编译 PostgreSQL 时 \"configure\"\n" -" 的选项\n" +" --configure 显示在编译 PostgreSQL 时 \"configure\" 脚本\n" +" 的所用选项\n" #: pg_config.c:94 #, c-format msgid " --cc show CC value used when PostgreSQL was built\n" -msgstr " --cc 显示在创建PostgreSQL时所使用的CC值\n" +msgstr " --cc 显示在编译 PostgreSQL 时所使用的 CC 值\n" #: pg_config.c:95 #, c-format msgid " --cppflags show CPPFLAGS value used when PostgreSQL was built\n" -msgstr " --cppflags 当创建PostgreSQL时显示CPPFLAGS的值\n" +msgstr " --cppflags 显示在编译 PostgreSQL 时所使用的 CPPFLAGS 值\n" #: pg_config.c:96 #, c-format msgid " --cflags show CFLAGS value used when PostgreSQL was built\n" -msgstr " --cflags 显示在创建PostgreSQL时所使用的CFLAG值\n" +msgstr " --cflags 显示在编译 PostgreSQL 时所使用的 CFLAGS 值\n" #: pg_config.c:97 #, c-format msgid " --cflags_sl show CFLAGS_SL value used when PostgreSQL was built\n" -msgstr " --cflags_sl 当创建PostgreSQL时显示CFLAGS_SL的值\n" +msgstr " --cflags_sl 显示在编译 PostgreSQL 时所使用的 CFLAGS_SL 值\n" #: pg_config.c:98 #, c-format msgid " --ldflags show LDFLAGS value used when PostgreSQL was built\n" -msgstr " --ldflags 显示在创建PostgreSQL时所使用的LDFLAG值\n" +msgstr " --ldflags 显示在编译 PostgreSQL 时所使用的 LDFLAGS 值\n" #: pg_config.c:99 #, c-format msgid " --ldflags_ex show LDFLAGS_EX value used when PostgreSQL was built\n" -msgstr " --ldflags_ex 当创建PostgreSQL时显示LDFLAGS_EX的值\n" +msgstr " --ldflags_ex 显示在编译 PostgreSQL 时所使用的 LDFLAGS_EX 值\n" #: pg_config.c:100 #, c-format msgid " --ldflags_sl show LDFLAGS_SL value used when PostgreSQL was built\n" -msgstr " --ldflags_sl 当创建PostgreSQL时显示LDFLAGS_SL的值\n" +msgstr " --ldflags_sl 显示在编译 PostgreSQL 时所使用的 LDFLAGS_SL 值\n" #: pg_config.c:101 #, c-format msgid " --libs show LIBS value used when PostgreSQL was built\n" -msgstr " --libs 显示在创建PostgreSQL时所使用的LIBS值\n" +msgstr " --libs 显示在编译 PostgreSQL 时所使用的 LIBS 值\n" #: pg_config.c:102 #, c-format msgid " --version show the PostgreSQL version\n" -msgstr " --version 显示PostgreSQL的版本信息\n" +msgstr " --version 显示 PostgreSQL 的版本信息\n" #: pg_config.c:103 #, c-format @@ -225,13 +244,13 @@ msgid "" "\n" msgstr "" "\n" -"没有参数,将显示所有已知的成员.\n" +"没有参数, 将显示所有已知条目.\n" "\n" #: pg_config.c:105 #, c-format msgid "Report bugs to <%s>.\n" -msgstr "臭虫报告至<%s>.\n" +msgstr "报告缺陷: <%s>.\n" #: pg_config.c:106 #, c-format @@ -246,10 +265,29 @@ msgstr "请用 \"%s --help\" 获取更多的信息.\n" #: pg_config.c:154 #, c-format msgid "%s: could not find own program executable\n" -msgstr "%s: 无法找到执行文件\n" +msgstr "%s: 无法找到所属执行程序\n" #: pg_config.c:181 #, c-format msgid "%s: invalid argument: %s\n" msgstr "%s: 无效参数: %s\n" +#, c-format +#~ msgid "could not change directory to \"%s\": %m" +#~ msgstr "无法跳转到目录 \"%s\" 中: %m" + +#, c-format +#~ msgid "could not identify current directory: %m" +#~ msgstr "无法确认当前目录: %m" + +#, c-format +#~ msgid "could not read binary \"%s\"" +#~ msgstr "无法读取二进制码 \"%s\"" + +#, c-format +#~ msgid "could not read symbolic link \"%s\": %m" +#~ msgstr "无法读取符号链接 \"%s\": %m" + +#, c-format +#~ msgid "invalid binary \"%s\"" +#~ msgstr "无效的二进制码 \"%s\"" diff --git a/src/bin/pg_config/t/001_pg_config.pl b/src/bin/pg_config/t/001_pg_config.pl index 94c3eb377c7c5..1dfc4c3f87633 100644 --- a/src/bin/pg_config/t/001_pg_config.pl +++ b/src/bin/pg_config/t/001_pg_config.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_controldata/Makefile b/src/bin/pg_controldata/Makefile index c3f64e189690a..029370afb13d5 100644 --- a/src/bin/pg_controldata/Makefile +++ b/src/bin/pg_controldata/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_controldata # -# Copyright (c) 1998-2024, PostgreSQL Global Development Group +# Copyright (c) 1998-2025, PostgreSQL Global Development Group # # src/bin/pg_controldata/Makefile # diff --git a/src/bin/pg_controldata/meson.build b/src/bin/pg_controldata/meson.build index 8009bd8c9a7af..a7701ff675431 100644 --- a/src/bin/pg_controldata/meson.build +++ b/src/bin/pg_controldata/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_controldata_sources = files( 'pg_controldata.c', diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c index 93a05d80ca7b6..7bb801bb88612 100644 --- a/src/bin/pg_controldata/pg_controldata.c +++ b/src/bin/pg_controldata/pg_controldata.c @@ -1,7 +1,7 @@ /* * pg_controldata * - * reads the data from $PGDATA/global/pg_control + * reads the data from the control file located at $PGDATA/XLOG_CONTROL_FILE. * * copyright (c) Oliver Elphick , 2001; * license: BSD @@ -97,6 +97,7 @@ main(int argc, char *argv[]) bool crc_ok; char *DataDir = NULL; time_t time_tmp; + struct tm *tm_tmp; char pgctime_str[128]; char ckpttime_str[128]; char mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1]; @@ -196,20 +197,30 @@ main(int argc, char *argv[]) * about %c */ time_tmp = (time_t) ControlFile->time; - strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, - localtime(&time_tmp)); + tm_tmp = localtime(&time_tmp); + + if (tm_tmp != NULL) + strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, tm_tmp); + else + snprintf(pgctime_str, sizeof(pgctime_str), _("???")); + time_tmp = (time_t) ControlFile->checkPointCopy.time; - strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, - localtime(&time_tmp)); + tm_tmp = localtime(&time_tmp); + + if (tm_tmp != NULL) + strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, tm_tmp); + else + snprintf(ckpttime_str, sizeof(ckpttime_str), _("???")); /* * Calculate name of the WAL file containing the latest checkpoint's REDO * start point. * - * A corrupted control file could report a WAL segment size of 0, and to - * guard against division by zero, we need to treat that specially. + * A corrupted control file could report a WAL segment size of 0 or + * negative value, and to guard against division by zero, we need to treat + * that specially. */ - if (WalSegSz != 0) + if (WalSegSz > 0) { XLogSegNo segno; @@ -228,8 +239,8 @@ main(int argc, char *argv[]) ControlFile->pg_control_version); printf(_("Catalog version number: %u\n"), ControlFile->catalog_version_no); - printf(_("Database system identifier: %llu\n"), - (unsigned long long) ControlFile->system_identifier); + printf(_("Database system identifier: %" PRIu64 "\n"), + ControlFile->system_identifier); printf(_("Database cluster state: %s\n"), dbState(ControlFile->state)); printf(_("pg_control last modified: %s\n"), @@ -325,6 +336,8 @@ main(int argc, char *argv[]) (ControlFile->float8ByVal ? _("by value") : _("by reference"))); printf(_("Data page checksum version: %u\n"), ControlFile->data_checksum_version); + printf(_("Default char data signedness: %s\n"), + (ControlFile->default_char_signedness ? _("signed") : _("unsigned"))); printf(_("Mock authentication nonce: %s\n"), mock_auth_nonce_str); return 0; diff --git a/src/bin/pg_controldata/po/es.po b/src/bin/pg_controldata/po/es.po index 58127cba51d81..79a931a21b2d1 100644 --- a/src/bin/pg_controldata/po/es.po +++ b/src/bin/pg_controldata/po/es.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_controldata (PostgreSQL) 16\n" +"Project-Id-Version: pg_controldata (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:22+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:53+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -22,31 +22,31 @@ msgstr "" "X-Generator: Poedit 2.0.2\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../../common/controldata_utils.c:73 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "no se pudo abrir archivo «%s» para lectura: %m" -#: ../../common/controldata_utils.c:86 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "no se pudo leer el archivo «%s»: %m" -#: ../../common/controldata_utils.c:95 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" -#: ../../common/controldata_utils.c:108 ../../common/controldata_utils.c:236 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "no se pudo cerrar el archivo «%s»: %m" -#: ../../common/controldata_utils.c:124 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "discordancia en orden de bytes" -#: ../../common/controldata_utils.c:126 +#: ../../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -60,21 +60,32 @@ msgstr "" "serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" "directorio de datos." -#: ../../common/controldata_utils.c:186 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "no se pudo abrir el archivo «%s»: %m" -#: ../../common/controldata_utils.c:205 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "no se pudo escribir el archivo «%s»: %m" -#: ../../common/controldata_utils.c:224 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -174,342 +185,330 @@ msgid "unrecognized status code" msgstr "código de estado no reconocido" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "wal_level no reconocido" +msgid "unrecognized \"wal_level\"" +msgstr "«wal_level» no reconocido" -#: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 +#: pg_controldata.c:139 pg_controldata.c:157 pg_controldata.c:164 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_controldata.c:154 +#: pg_controldata.c:155 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_controldata.c:162 +#: pg_controldata.c:163 #, c-format msgid "no data directory specified" msgstr "no se especificó el directorio de datos" -#: pg_controldata.c:170 +#: pg_controldata.c:172 #, c-format -msgid "" -"WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n" -"\n" -msgstr "" -"ATENCIÓN: La suma de verificación calculada no coincide con el valor\n" -"almacenado en el archivo. Puede ser que el archivo esté corrupto, o\n" -"bien tiene una estructura diferente de la que este programa está\n" -"esperando. Los resultados presentados a continuación no son confiables.\n" -"\n" +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "el \"checksum\" calculado no coincide con el valor almacenado en el archivo de control" -#: pg_controldata.c:179 +#: pg_controldata.c:173 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "PRECAUCIÓN: tamaño de segmento de WAL no válido\n" +msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." +msgstr "O bien el archivo está corrupto, o tiene una estructura diferente de la que este programa está esperando. Los resultados presentados a continuación no son confiables." -#: pg_controldata.c:180 +#: pg_controldata.c:182 +#, c-format +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "tamaño de segmento de WAL no válido (%d byte) en archivo de control" +msgstr[1] "tamaño de segmento de WAL no válido (%d bytes) en archivo de control" + +#: pg_controldata.c:186 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "El tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB." + +#: pg_controldata.c:187 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "El archivo está corrupto y los resultados a continuación no son confiables." + +#: pg_controldata.c:205 pg_controldata.c:213 pg_controldata.c:232 #, c-format -msgid "" -"The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgid_plural "" -"The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgstr[0] "" -"El tamaño de segmento de WAL almacenado en el archivo, %d byte,\n" -"no es una potencia de dos entre 1 MB y 1 GB. El archivo está corrupto y los\n" -"resultados de abajo no son confiables.\n" -msgstr[1] "" -"El tamaño de segmento de WAL almacenado en el archivo, %d bytes,\n" -"no es una potencia de dos entre 1 MB y 1 GB. El archivo está corrupto y los\n" -"resultados de abajo no son confiables.\n" - -#: pg_controldata.c:222 msgid "???" msgstr "???" -#: pg_controldata.c:228 +#: pg_controldata.c:238 #, c-format msgid "pg_control version number: %u\n" msgstr "Número de versión de pg_control: %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:240 #, c-format msgid "Catalog version number: %u\n" msgstr "Número de versión del catálogo: %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:242 #, c-format msgid "Database system identifier: %llu\n" msgstr "Identificador de sistema: %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:244 #, c-format msgid "Database cluster state: %s\n" msgstr "Estado del sistema de base de datos: %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:246 #, c-format msgid "pg_control last modified: %s\n" msgstr "Última modificación de pg_control: %s\n" -#: pg_controldata.c:238 +#: pg_controldata.c:248 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "Ubicación del último checkpoint: %X/%X\n" -#: pg_controldata.c:240 +#: pg_controldata.c:250 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "Ubicación de REDO de último checkpoint: %X/%X\n" -#: pg_controldata.c:242 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "Ubicación de REDO de último checkpoint: %s\n" -#: pg_controldata.c:244 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "TimeLineID del último checkpoint: %u\n" -#: pg_controldata.c:246 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "PrevTimeLineID del último checkpoint: %u\n" -#: pg_controldata.c:248 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "full_page_writes del último checkpoint: %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "off" msgstr "desactivado" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "on" msgstr "activado" -#: pg_controldata.c:250 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID de último checkpoint: %u/%u\n" -#: pg_controldata.c:253 +#: pg_controldata.c:263 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID de último checkpoint: %u\n" -#: pg_controldata.c:255 +#: pg_controldata.c:265 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId de último checkpoint: %u\n" -#: pg_controldata.c:257 +#: pg_controldata.c:267 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset de último checkpoint: %u\n" -#: pg_controldata.c:259 +#: pg_controldata.c:269 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID del último checkpoint: %u\n" -#: pg_controldata.c:261 +#: pg_controldata.c:271 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "DB del oldestXID del último checkpoint: %u\n" -#: pg_controldata.c:263 +#: pg_controldata.c:273 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID del último checkpoint: %u\n" -#: pg_controldata.c:265 +#: pg_controldata.c:275 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid del último checkpoint: %u\n" -#: pg_controldata.c:267 +#: pg_controldata.c:277 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "DB del oldestMultiXid del últ. checkpoint: %u\n" -#: pg_controldata.c:269 +#: pg_controldata.c:279 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid del último checkpoint: %u\n" -#: pg_controldata.c:271 +#: pg_controldata.c:281 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid del último checkpoint: %u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:283 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "Instante de último checkpoint: %s\n" -#: pg_controldata.c:275 +#: pg_controldata.c:285 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "Contador de LSN falsas para rels. unlogged: %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:287 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "Punto final mínimo de recuperación: %X/%X\n" -#: pg_controldata.c:279 +#: pg_controldata.c:289 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "Timeline de dicho punto final mínimo: %u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:291 #, c-format msgid "Backup start location: %X/%X\n" msgstr "Ubicación del inicio de backup: %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:293 #, c-format msgid "Backup end location: %X/%X\n" msgstr "Ubicación del fin de backup: %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:295 #, c-format msgid "End-of-backup record required: %s\n" msgstr "Registro fin-de-backup requerido: %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:296 msgid "no" msgstr "no" -#: pg_controldata.c:286 +#: pg_controldata.c:296 msgid "yes" msgstr "sí" -#: pg_controldata.c:287 +#: pg_controldata.c:297 #, c-format msgid "wal_level setting: %s\n" msgstr "Parámetro wal_level: %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:299 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "Parámetro wal_log_hings: %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:301 #, c-format msgid "max_connections setting: %d\n" msgstr "Parámetro max_connections: %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:303 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "Parámetro max_worker_processes: %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:305 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "Parámetro max_wal_senders: %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:307 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "Parámetro max_prepared_xacts: %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:309 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "Parámetro max_locks_per_xact: %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:311 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "Parámetro track_commit_timestamp: %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:313 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Alineamiento máximo de datos: %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:316 #, c-format msgid "Database block size: %u\n" msgstr "Tamaño de bloque de la base de datos: %u\n" -#: pg_controldata.c:308 +#: pg_controldata.c:318 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Bloques por segmento en relación grande: %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:320 #, c-format msgid "WAL block size: %u\n" msgstr "Tamaño del bloque de WAL: %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:322 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Bytes por segmento WAL: %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:324 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Máxima longitud de identificadores: %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:326 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Máximo número de columnas de un índice: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:328 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Longitud máxima de un trozo TOAST: %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:330 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Longitud máx. de un trozo de objeto grande: %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:333 #, c-format msgid "Date/time type storage: %s\n" msgstr "Tipo de almacenamiento de horas y fechas: %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:334 msgid "64-bit integers" msgstr "enteros de 64 bits" -#: pg_controldata.c:325 +#: pg_controldata.c:335 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Paso de parámetros float8: %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:336 msgid "by reference" msgstr "por referencia" -#: pg_controldata.c:326 +#: pg_controldata.c:336 msgid "by value" msgstr "por valor" -#: pg_controldata.c:327 +#: pg_controldata.c:337 #, c-format msgid "Data page checksum version: %u\n" msgstr "Versión de sumas de verificación de datos: %u\n" -#: pg_controldata.c:329 +#: pg_controldata.c:339 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "Nonce para autentificación simulada: %s\n" diff --git a/src/bin/pg_controldata/po/fr.po b/src/bin/pg_controldata/po/fr.po index a22d809a9478c..1c94ff051b777 100644 --- a/src/bin/pg_controldata/po/fr.po +++ b/src/bin/pg_controldata/po/fr.po @@ -11,10 +11,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-07-20 21:24+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -22,33 +22,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: ../../common/controldata_utils.c:73 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" -#: ../../common/controldata_utils.c:86 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "n'a pas pu lire le fichier « %s » : %m" -#: ../../common/controldata_utils.c:95 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" -#: ../../common/controldata_utils.c:108 ../../common/controldata_utils.c:244 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "n'a pas pu fermer le fichier « %s » : %m" -#: ../../common/controldata_utils.c:124 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "différence de l'ordre des octets" -#: ../../common/controldata_utils.c:126 +#: ../../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -62,21 +62,32 @@ msgstr "" "résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" "est incompatible avec ce répertoire des données." -#: ../../common/controldata_utils.c:194 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "n'a pas pu ouvrir le fichier « %s » : %m" -#: ../../common/controldata_utils.c:213 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "impossible d'écrire le fichier « %s » : %m" -#: ../../common/controldata_utils.c:232 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -176,8 +187,8 @@ msgid "unrecognized status code" msgstr "code de statut inconnu" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "wal_level non reconnu" +msgid "unrecognized \"wal_level\"" +msgstr "« wal_level » non reconnu" #: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 #, c-format @@ -194,376 +205,311 @@ msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" msgid "no data directory specified" msgstr "aucun répertoire de données indiqué" -#: pg_controldata.c:170 +#: pg_controldata.c:171 #, c-format -msgid "" -"WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n" -"\n" -msgstr "" -"ATTENTION : Les sommes de contrôle (CRC) calculées ne correspondent pas aux\n" -"valeurs stockées dans le fichier.\n" -"Soit le fichier est corrompu, soit son organisation diffère de celle\n" -"attendue par le programme.\n" -"Les résultats ci-dessous ne sont pas dignes de confiance.\n" -"\n" +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "la somme de contrôle CRC calculée ne correspond par à la valeur enregistrée dans le fichier de contrôle" -#: pg_controldata.c:179 +#: pg_controldata.c:172 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "ATTENTION : taille invalide du segment WAL\n" +msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." +msgstr "Soit le fichier de contrôle est corrompu, soit son organisation diffère de celle attendue par le programme. Les résultats ci-dessous ne sont pas dignes de confiance." -#: pg_controldata.c:180 +#: pg_controldata.c:181 #, c-format -msgid "" -"The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgid_plural "" -"The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgstr[0] "" -"La taille d'un segment WAL enregistré dans le fichier, %d octet, n'est pas une puissance de deux " -"entre 1 Mo et 1 Go. Le fichier est corrompu et les résultats ci-dessous ne proviennent pas d'une " -"source fiable.\n" -"\n" -msgstr[1] "" -"La taille d'un segment WAL enregistré dans le fichier, %d octets, n'est pas une puissance de deux " -"entre 1 Mo et 1 Go. Le fichier est corrompu et les résultats ci-dessous ne proviennent pas d'une " -"source fiable.\n" -"\n" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "taille invalide du segment WAL dans le fichier de contrôle (%d octet)" +msgstr[1] "taille invalide du segment WAL dans le fichier de contrôle (%d octets)" + +#: pg_controldata.c:185 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go." -#: pg_controldata.c:222 +#: pg_controldata.c:186 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "Le fichier est corrompu et il ne faut pas faire confiance aux résultats ci-dessous." + +#: pg_controldata.c:221 msgid "???" msgstr "???" -#: pg_controldata.c:228 +#: pg_controldata.c:227 #, c-format msgid "pg_control version number: %u\n" msgstr "Numéro de version de pg_control : %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:229 #, c-format msgid "Catalog version number: %u\n" msgstr "Numéro de version du catalogue : %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:231 #, c-format msgid "Database system identifier: %llu\n" msgstr "Identifiant du système de base de données : %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:233 #, c-format msgid "Database cluster state: %s\n" msgstr "État du cluster de base de données : %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:235 #, c-format msgid "pg_control last modified: %s\n" msgstr "Dernière modification de pg_control : %s\n" -#: pg_controldata.c:238 +#: pg_controldata.c:237 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "Dernier point de contrôle : %X/%X\n" -#: pg_controldata.c:240 +#: pg_controldata.c:239 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "Dernier REDO (reprise) du point de contrôle : %X/%X\n" -#: pg_controldata.c:242 +#: pg_controldata.c:241 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "Dernier fichier WAL du rejeu du point de contrôle : %s\n" -#: pg_controldata.c:244 +#: pg_controldata.c:243 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Dernier TimeLineID du point de contrôle : %u\n" -#: pg_controldata.c:246 +#: pg_controldata.c:245 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "Dernier PrevTimeLineID du point de contrôle : %u\n" -#: pg_controldata.c:248 +#: pg_controldata.c:247 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Dernier full_page_writes du point de contrôle : %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "off" msgstr "désactivé" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "on" msgstr "activé" -#: pg_controldata.c:250 +#: pg_controldata.c:249 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "Dernier NextXID du point de contrôle : %u:%u\n" -#: pg_controldata.c:253 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "Dernier NextOID du point de contrôle : %u\n" -#: pg_controldata.c:255 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "Dernier NextMultiXactId du point de contrôle : %u\n" -#: pg_controldata.c:257 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "Dernier NextMultiOffset du point de contrôle : %u\n" -#: pg_controldata.c:259 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "Dernier oldestXID du point de contrôle : %u\n" -#: pg_controldata.c:261 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "Dernier oldestXID du point de contrôle de la base : %u\n" -#: pg_controldata.c:263 +#: pg_controldata.c:262 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "Dernier oldestActiveXID du point de contrôle : %u\n" -#: pg_controldata.c:265 +#: pg_controldata.c:264 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "Dernier oldestMultiXid du point de contrôle : %u\n" -#: pg_controldata.c:267 +#: pg_controldata.c:266 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "Dernier oldestMulti du point de contrôle de la base : %u\n" -#: pg_controldata.c:269 +#: pg_controldata.c:268 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "Dernier oldestCommitTsXid du point de contrôle : %u\n" -#: pg_controldata.c:271 +#: pg_controldata.c:270 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "Dernier newestCommitTsXid du point de contrôle : %u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:272 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "Heure du dernier point de contrôle : %s\n" -#: pg_controldata.c:275 +#: pg_controldata.c:274 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "Faux compteur LSN pour les relations non journalisés : %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:276 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "Emplacement de fin de la récupération minimale : %X/%X\n" -#: pg_controldata.c:279 +#: pg_controldata.c:278 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "Timeline de l'emplacement de fin de restauration : %u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:280 #, c-format msgid "Backup start location: %X/%X\n" msgstr "Début de la sauvegarde : %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:282 #, c-format msgid "Backup end location: %X/%X\n" msgstr "Fin de la sauvegarde : %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:284 #, c-format msgid "End-of-backup record required: %s\n" msgstr "Enregistrement de fin de sauvegarde requis : %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "no" msgstr "non" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "yes" msgstr "oui" -#: pg_controldata.c:287 +#: pg_controldata.c:286 #, c-format msgid "wal_level setting: %s\n" -msgstr "Paramètrage actuel de wal_level : %s\n" +msgstr "Paramétrage actuel de wal_level : %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:288 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "Paramétrage actuel de wal_log_hints : %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:290 #, c-format msgid "max_connections setting: %d\n" -msgstr "Paramètrage actuel de max_connections : %d\n" +msgstr "Paramétrage actuel de max_connections : %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:292 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "Paramétrage actuel de max_worker_processes : %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:294 #, c-format msgid "max_wal_senders setting: %d\n" -msgstr "Paramètrage actuel de max_wal_senders : %d\n" +msgstr "Paramétrage actuel de max_wal_senders : %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:296 #, c-format msgid "max_prepared_xacts setting: %d\n" -msgstr "Paramètrage actuel de max_prepared_xacts : %d\n" +msgstr "Paramétrage actuel de max_prepared_xacts : %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:298 #, c-format msgid "max_locks_per_xact setting: %d\n" -msgstr "Paramètrage actuel de max_locks_per_xact : %d\n" +msgstr "Paramétrage actuel de max_locks_per_xact : %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:300 #, c-format msgid "track_commit_timestamp setting: %s\n" -msgstr "Paramètrage actuel de track_commit_timestamp : %s\n" +msgstr "Paramétrage actuel de track_commit_timestamp : %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:302 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Alignement maximal des données : %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:305 #, c-format msgid "Database block size: %u\n" msgstr "Taille du bloc de la base de données : %u\n" -#: pg_controldata.c:308 +#: pg_controldata.c:307 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Blocs par segment des relations volumineuses : %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:309 #, c-format msgid "WAL block size: %u\n" msgstr "Taille de bloc du journal de transaction : %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:311 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Octets par segment du journal de transaction : %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:313 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Longueur maximale des identifiants : %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:315 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Nombre maximum de colonnes d'un index: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:317 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Longueur maximale d'un morceau TOAST : %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:319 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Taille d'un morceau de Large Object : %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:322 #, c-format msgid "Date/time type storage: %s\n" msgstr "Stockage du type date/heure : %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:323 msgid "64-bit integers" msgstr "entiers 64-bits" -#: pg_controldata.c:325 +#: pg_controldata.c:324 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Passage d'argument float8 : %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by reference" msgstr "par référence" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by value" msgstr "par valeur" -#: pg_controldata.c:327 +#: pg_controldata.c:326 #, c-format msgid "Data page checksum version: %u\n" msgstr "Version des sommes de contrôle des pages de données : %u\n" -#: pg_controldata.c:329 +#: pg_controldata.c:328 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "Nonce pour simuler une identité: %s\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide et quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version et quitte\n" - -#~ msgid "%s: could not open file \"%s\" for reading: %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » en lecture : %s\n" - -#~ msgid "%s: could not read file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le fichier « %s » : %s\n" - -#~ msgid "%s: could not read file \"%s\": read %d of %d\n" -#~ msgstr "%s : n'a pas pu lire le fichier « %s » : a lu %d sur %d\n" - -#~ msgid "Float4 argument passing: %s\n" -#~ msgstr "Passage d'argument float4 : %s\n" - -#~ msgid "Prior checkpoint location: %X/%X\n" -#~ msgstr "Point de contrôle précédent : %X/%X\n" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#~ msgid "" -#~ "Usage:\n" -#~ " %s [OPTION] [DATADIR]\n" -#~ "\n" -#~ "Options:\n" -#~ " --help show this help, then exit\n" -#~ " --version output version information, then exit\n" -#~ msgstr "" -#~ "Usage :\n" -#~ " %s [OPTION] [RÉP_DONNÉES]\n" -#~ "\n" -#~ "Options :\n" -#~ " --help affiche cette aide et quitte\n" -#~ " --version affiche les informations de version et quitte\n" - -#~ msgid "calculated CRC checksum does not match value stored in file" -#~ msgstr "la somme de contrôle CRC calculée ne correspond par à la valeur enregistrée dans le fichier" - -#~ msgid "floating-point numbers" -#~ msgstr "nombres à virgule flottante" diff --git a/src/bin/pg_controldata/po/ja.po b/src/bin/pg_controldata/po/ja.po index 8da59bf47503a..6b9c5d7128af4 100644 --- a/src/bin/pg_controldata/po/ja.po +++ b/src/bin/pg_controldata/po/ja.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_controldata (PostgreSQL 17)\n" +"Project-Id-Version: pg_controldata (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-20 14:21+0900\n" -"PO-Revision-Date: 2024-05-20 16:33+0900\n" +"POT-Creation-Date: 2025-03-31 09:53+0900\n" +"PO-Revision-Date: 2025-03-31 16:28+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -70,6 +70,17 @@ msgstr "ファイル\"%s\"を書き出せませんでした: %m" msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "メモリ不足です\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nullポインタは複製できません(内部エラー)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -171,325 +182,339 @@ msgstr "未知のステータスコード" msgid "unrecognized \"wal_level\"" msgstr "\"wal_level\"を認識できません" -#: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 +#: pg_controldata.c:139 pg_controldata.c:157 pg_controldata.c:164 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_controldata.c:154 +#: pg_controldata.c:155 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: pg_controldata.c:162 +#: pg_controldata.c:163 #, c-format msgid "no data directory specified" msgstr "データディレクトリが指定されていません" -#: pg_controldata.c:171 +#: pg_controldata.c:172 #, c-format msgid "calculated CRC checksum does not match value stored in control file" msgstr "算出されたCRCチェックサムが制御ファイルに格納されている値と一致しません" -#: pg_controldata.c:172 +#: pg_controldata.c:173 #, c-format msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." msgstr "制御ファイルが破損しているか、このプログラムが期待していない配置になっています。以下の結果は信頼できません。" -#: pg_controldata.c:181 +#: pg_controldata.c:182 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "制御ファイル中の不正なWALセグメントサイズ (%dバイト)" -#: pg_controldata.c:185 +#: pg_controldata.c:186 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WALセグメントサイズは1MBから1GBまでの間の2の累乗でなければなりません。" -#: pg_controldata.c:186 +#: pg_controldata.c:187 #, c-format msgid "The file is corrupt and the results below are untrustworthy." msgstr "このファイルは破損しており、以下の結果は信頼できません。" -#: pg_controldata.c:221 +#: pg_controldata.c:205 pg_controldata.c:213 pg_controldata.c:232 +#, c-format msgid "???" msgstr "???" -#: pg_controldata.c:227 +#: pg_controldata.c:238 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_controlバージョン番号: %u\n" -#: pg_controldata.c:229 +#: pg_controldata.c:240 #, c-format msgid "Catalog version number: %u\n" msgstr "カタログバージョン番号: %u\n" -#: pg_controldata.c:231 +#: pg_controldata.c:242 #, c-format -msgid "Database system identifier: %llu\n" -msgstr "データベースシステム識別子: %llu\n" +msgid "Database system identifier: %\n" +msgstr "データベースシステム識別子: %\n" -#: pg_controldata.c:233 +#: pg_controldata.c:244 #, c-format msgid "Database cluster state: %s\n" msgstr "データベースクラスタの状態: %s\n" -#: pg_controldata.c:235 +#: pg_controldata.c:246 #, c-format msgid "pg_control last modified: %s\n" msgstr "pg_control最終更新: %s\n" -#: pg_controldata.c:237 +#: pg_controldata.c:248 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "最終チェックポイント位置: %X/%X\n" -#: pg_controldata.c:239 +#: pg_controldata.c:250 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "最終チェックポイントのREDO位置: %X/%X\n" -#: pg_controldata.c:241 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "最終チェックポイントのREDO WALファイル: %s\n" -#: pg_controldata.c:243 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "最終チェックポイントの時系列ID: %u\n" -#: pg_controldata.c:245 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "最終チェックポイントのPrevTimeLineID: %u\n" -#: pg_controldata.c:247 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "最終チェックポイントのfull_page_writes: %s\n" -#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "off" msgstr "オフ" -#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "on" msgstr "オン" -#: pg_controldata.c:249 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "最終チェックポイントのNextXID: %u:%u\n" -#: pg_controldata.c:252 +#: pg_controldata.c:263 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "最終チェックポイントのNextOID: %u\n" -#: pg_controldata.c:254 +#: pg_controldata.c:265 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "最終チェックポイントのNextMultiXactId: %u\n" -#: pg_controldata.c:256 +#: pg_controldata.c:267 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "最終チェックポイントのNextMultiOffset: %u\n" -#: pg_controldata.c:258 +#: pg_controldata.c:269 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "最終チェックポイントのoldestXID: %u\n" -#: pg_controldata.c:260 +#: pg_controldata.c:271 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "最終チェックポイントのoldestXIDのDB: %u\n" -#: pg_controldata.c:262 +#: pg_controldata.c:273 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "最終チェックポイントのoldestActiveXID: %u\n" -#: pg_controldata.c:264 +#: pg_controldata.c:275 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "最終チェックポイントのoldestMultiXid: %u\n" -#: pg_controldata.c:266 +#: pg_controldata.c:277 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "最終チェックポイントのoldestMultiのDB: %u\n" -#: pg_controldata.c:268 +#: pg_controldata.c:279 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "最終チェックポイントのoldestCommitTsXid: %u\n" -#: pg_controldata.c:270 +#: pg_controldata.c:281 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "最終チェックポイントのnewestCommitTsXid: %u\n" -#: pg_controldata.c:272 +#: pg_controldata.c:283 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "最終チェックポイント時刻: %s\n" -#: pg_controldata.c:274 +#: pg_controldata.c:285 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "UNLOGGEDリレーションの偽のLSNカウンタ: %X/%X\n" -#: pg_controldata.c:276 +#: pg_controldata.c:287 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "最小リカバリ終了位置: %X/%X\n" -#: pg_controldata.c:278 +#: pg_controldata.c:289 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "最小リカバリ終了位置のタイムライン: %u\n" -#: pg_controldata.c:280 +#: pg_controldata.c:291 #, c-format msgid "Backup start location: %X/%X\n" msgstr "バックアップ開始位置: %X/%X\n" -#: pg_controldata.c:282 +#: pg_controldata.c:293 #, c-format msgid "Backup end location: %X/%X\n" msgstr "バックアップ終了位置: %X/%X\n" -#: pg_controldata.c:284 +#: pg_controldata.c:295 #, c-format msgid "End-of-backup record required: %s\n" msgstr "必要なバックアップ最終レコード: %s\n" -#: pg_controldata.c:285 +#: pg_controldata.c:296 msgid "no" msgstr "いいえ" -#: pg_controldata.c:285 +#: pg_controldata.c:296 msgid "yes" msgstr "はい" -#: pg_controldata.c:286 +#: pg_controldata.c:297 #, c-format msgid "wal_level setting: %s\n" msgstr "wal_levelの設定: %s\n" -#: pg_controldata.c:288 +#: pg_controldata.c:299 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "wal_log_hintsの設定: %s\n" -#: pg_controldata.c:290 +#: pg_controldata.c:301 #, c-format msgid "max_connections setting: %d\n" msgstr "max_connectionsの設定: %d\n" -#: pg_controldata.c:292 +#: pg_controldata.c:303 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "max_worker_processesの設定: %d\n" -#: pg_controldata.c:294 +#: pg_controldata.c:305 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "max_wal_sendersの設定: %d\n" -#: pg_controldata.c:296 +#: pg_controldata.c:307 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "max_prepared_xactsの設定: %d\n" -#: pg_controldata.c:298 +#: pg_controldata.c:309 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "max_locks_per_xactの設定: %d\n" -#: pg_controldata.c:300 +#: pg_controldata.c:311 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "track_commit_timestampの設定: %s\n" -#: pg_controldata.c:302 +#: pg_controldata.c:313 #, c-format msgid "Maximum data alignment: %u\n" msgstr "最大データアラインメント: %u\n" -#: pg_controldata.c:305 +#: pg_controldata.c:316 #, c-format msgid "Database block size: %u\n" msgstr "データベースのブロックサイズ: %u\n" -#: pg_controldata.c:307 +#: pg_controldata.c:318 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "大きなリレーションのセグメント毎のブロック数:%u\n" -#: pg_controldata.c:309 +#: pg_controldata.c:320 #, c-format msgid "WAL block size: %u\n" msgstr "WALのブロックサイズ: %u\n" -#: pg_controldata.c:311 +#: pg_controldata.c:322 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "WALセグメント当たりのバイト数: %u\n" -#: pg_controldata.c:313 +#: pg_controldata.c:324 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "識別子の最大長: %u\n" -#: pg_controldata.c:315 +#: pg_controldata.c:326 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "インデックス内の最大列数: %u\n" -#: pg_controldata.c:317 +#: pg_controldata.c:328 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOASTチャンクの最大サイズ: %u\n" -#: pg_controldata.c:319 +#: pg_controldata.c:330 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "ラージオブジェクトチャンクのサイズ: %u\n" -#: pg_controldata.c:322 +#: pg_controldata.c:333 #, c-format msgid "Date/time type storage: %s\n" msgstr "日付/時刻型の格納方式: %s\n" -#: pg_controldata.c:323 +#: pg_controldata.c:334 msgid "64-bit integers" msgstr "64ビット整数" -#: pg_controldata.c:324 +#: pg_controldata.c:335 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8引数の渡し方: %s\n" -#: pg_controldata.c:325 +#: pg_controldata.c:336 msgid "by reference" msgstr "参照渡し" -#: pg_controldata.c:325 +#: pg_controldata.c:336 msgid "by value" msgstr "値渡し" -#: pg_controldata.c:326 +#: pg_controldata.c:337 #, c-format msgid "Data page checksum version: %u\n" msgstr "データベージチェックサムのバージョン: %u\n" -#: pg_controldata.c:328 +#: pg_controldata.c:339 +#, c-format +msgid "Default char data signedness: %s\n" +msgstr "デフォルトのchar型の符号あり/なし: %s\n" + +#: pg_controldata.c:340 +msgid "signed" +msgstr "signed" + +#: pg_controldata.c:340 +msgid "unsigned" +msgstr "unsigned" + +#: pg_controldata.c:341 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "認証用の疑似nonce: %s\n" diff --git a/src/bin/pg_controldata/po/ka.po b/src/bin/pg_controldata/po/ka.po index 94bb60ceebc99..fe23c53667b11 100644 --- a/src/bin/pg_controldata/po/ka.po +++ b/src/bin/pg_controldata/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_controldata (PostgreSQL) 17\n" +"Project-Id-Version: pg_controldata (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-18 22:23+0000\n" -"PO-Revision-Date: 2024-05-19 07:11+0200\n" +"POT-Creation-Date: 2025-03-29 21:24+0000\n" +"PO-Revision-Date: 2025-03-30 01:29+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../common/controldata_utils.c:97 #, c-format @@ -69,6 +69,17 @@ msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -170,326 +181,340 @@ msgstr "სტატუსის უცნობი კოდი" msgid "unrecognized \"wal_level\"" msgstr "უცნობი \"wal_level\"" -#: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 +#: pg_controldata.c:139 pg_controldata.c:157 pg_controldata.c:164 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_controldata.c:154 +#: pg_controldata.c:155 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_controldata.c:162 +#: pg_controldata.c:163 #, c-format msgid "no data directory specified" msgstr "მონაცემების საქაღალდე მითითებული არაა" -#: pg_controldata.c:171 +#: pg_controldata.c:172 #, c-format msgid "calculated CRC checksum does not match value stored in control file" msgstr "გამოთვლილი CRC საკონტროლო ჯამი კონტროლის ფაილში დამახსოვრებულ მნიშვნელობას არ ემთხვევა" -#: pg_controldata.c:172 +#: pg_controldata.c:173 #, c-format msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." msgstr "ან კონტროლი ფაილი დაზიანებულია, ან გააჩნია იმისგან განსხვავებული განლაგება, ვიდრე ამას პროგრამა მოელოდა. ქვემო შედეგები სანდო არაა." -#: pg_controldata.c:181 +#: pg_controldata.c:182 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" msgstr[1] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" -#: pg_controldata.c:185 +#: pg_controldata.c:186 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WAL სეგმენტის ზომა ორის ხარისხი უნდა იყოს, შუალედიდან 1მბ-1გბ." -#: pg_controldata.c:186 +#: pg_controldata.c:187 #, c-format msgid "The file is corrupt and the results below are untrustworthy." msgstr "ფაილი დაზიანებულია და ქვემო შედეგები სანდო არაა." -#: pg_controldata.c:221 +#: pg_controldata.c:205 pg_controldata.c:213 pg_controldata.c:232 +#, c-format msgid "???" msgstr "???" -#: pg_controldata.c:227 +#: pg_controldata.c:238 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control ვერსიის ნომერი: %u\n" -#: pg_controldata.c:229 +#: pg_controldata.c:240 #, c-format msgid "Catalog version number: %u\n" msgstr "კატალოგის ვერსიის ნომერი: %u\n" -#: pg_controldata.c:231 +#: pg_controldata.c:242 #, c-format -msgid "Database system identifier: %llu\n" -msgstr "ბაზის სისტემური იდენტიფიკატორი: %llu\n" +msgid "Database system identifier: %\n" +msgstr "ბაზის სისტემური იდენტიფიკატორი: %\n" -#: pg_controldata.c:233 +#: pg_controldata.c:244 #, c-format msgid "Database cluster state: %s\n" msgstr "ბაზის კლასტერის მდგომარეობა: %s\n" -#: pg_controldata.c:235 +#: pg_controldata.c:246 #, c-format msgid "pg_control last modified: %s\n" msgstr "pg_control-ის ბოლო ცვლილების დრო: %s\n" -#: pg_controldata.c:237 +#: pg_controldata.c:248 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "საკონტროლო წერტილის უკანასკნელი მდებარეობა: %X/%X\n" -#: pg_controldata.c:239 +#: pg_controldata.c:250 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "საკონტროლო წერტილის REDO-ის უკანასკნელი მდებარეობა: %X/%X\n" -#: pg_controldata.c:241 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "უკანასკნელი საკონტროლო წერტილის REDO WAL ფაილი: %s\n" -#: pg_controldata.c:243 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "უახლესი საკონტროლო წერტილისTimeLineID: %u\n" -#: pg_controldata.c:245 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "უახლესი საკონტროლო წერტილის PrevTimeLineID: %u\n" -#: pg_controldata.c:247 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "უახლესი უკანასკნელი საკონტროლო წერტილის full_page_writes: %s\n" -#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "off" msgstr "გამორთული" -#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "on" msgstr "ჩართ" -#: pg_controldata.c:249 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "უახლესი საკონტროლო წერტილის NextXID: %u:%u\n" -#: pg_controldata.c:252 +#: pg_controldata.c:263 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextOID: %u\n" -#: pg_controldata.c:254 +#: pg_controldata.c:265 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextMultiXactId: %u\n" -#: pg_controldata.c:256 +#: pg_controldata.c:267 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextMultiOffset: %u\n" -#: pg_controldata.c:258 +#: pg_controldata.c:269 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestXID: %u\n" -#: pg_controldata.c:260 +#: pg_controldata.c:271 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestXID's DB: %u\n" -#: pg_controldata.c:262 +#: pg_controldata.c:273 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestActiveXID: %u\n" -#: pg_controldata.c:264 +#: pg_controldata.c:275 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestMultiXid: %u\n" -#: pg_controldata.c:266 +#: pg_controldata.c:277 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestMulti's DB: %u\n" -#: pg_controldata.c:268 +#: pg_controldata.c:279 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "უახლესი საკონტროლო წერტილის oldestCommitTsXid:%u\n" -#: pg_controldata.c:270 +#: pg_controldata.c:281 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "უახლესი საკონტროლო წერტილის newestCommitTsXid:%u\n" -#: pg_controldata.c:272 +#: pg_controldata.c:283 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "უახლესი საკონტოლო წერტილის დრო: %s\n" -#: pg_controldata.c:274 +#: pg_controldata.c:285 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "LSN-ის ყალბი მთვლელი არაჟურნალიზებადი ურთ-თვის: %X/%X\n" -#: pg_controldata.c:276 +#: pg_controldata.c:287 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "მინიმალური აღდგენის დასასრულის მდებარეობა %X/%X\n" -#: pg_controldata.c:278 +#: pg_controldata.c:289 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "მინ. აღდგ დასასრ მდებარ დროის ხაზი: %u\n" -#: pg_controldata.c:280 +#: pg_controldata.c:291 #, c-format msgid "Backup start location: %X/%X\n" msgstr "მარქაფის დაწყების მდებარეობა: %X/%X\n" -#: pg_controldata.c:282 +#: pg_controldata.c:293 #, c-format msgid "Backup end location: %X/%X\n" msgstr "მარქაფს დასასრულის მდებარეობა: %X/%X\n" -#: pg_controldata.c:284 +#: pg_controldata.c:295 #, c-format msgid "End-of-backup record required: %s\n" msgstr "მარქაფის-ბოლო ჩანაწერი აუცილებელია: %s\n" -#: pg_controldata.c:285 +#: pg_controldata.c:296 msgid "no" msgstr "არა" -#: pg_controldata.c:285 +#: pg_controldata.c:296 msgid "yes" msgstr "დიახ" -#: pg_controldata.c:286 +#: pg_controldata.c:297 #, c-format msgid "wal_level setting: %s\n" msgstr "wal_level პარამეტრი: %s\n" -#: pg_controldata.c:288 +#: pg_controldata.c:299 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "wal_log_hints პარამეტრი: %s\n" -#: pg_controldata.c:290 +#: pg_controldata.c:301 #, c-format msgid "max_connections setting: %d\n" msgstr "max_connections პარამეტრი: %d\n" -#: pg_controldata.c:292 +#: pg_controldata.c:303 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "max_worker_processes პარამეტრი: %d\n" -#: pg_controldata.c:294 +#: pg_controldata.c:305 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "max_wal_senders პარამეტრი: %d\n" -#: pg_controldata.c:296 +#: pg_controldata.c:307 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "max_prepared_xacts პარამეტრი: %d\n" -#: pg_controldata.c:298 +#: pg_controldata.c:309 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "max_locks_per_xact პარამეტრი: %d\n" -#: pg_controldata.c:300 +#: pg_controldata.c:311 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "track_commit_timestamp პარამეტრი: %s\n" -#: pg_controldata.c:302 +#: pg_controldata.c:313 #, c-format msgid "Maximum data alignment: %u\n" msgstr "მონაცემების სწორების მაქსიმუმი: %u\n" -#: pg_controldata.c:305 +#: pg_controldata.c:316 #, c-format msgid "Database block size: %u\n" msgstr "ბაზის ბლოკის ზომა: %u\n" -#: pg_controldata.c:307 +#: pg_controldata.c:318 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "დიდი ურთიერთობის სეგმენტები თითოეულ ბლოკში: %u\n" -#: pg_controldata.c:309 +#: pg_controldata.c:320 #, c-format msgid "WAL block size: %u\n" msgstr "WAL ბლოკის ზომა: %u\n" -#: pg_controldata.c:311 +#: pg_controldata.c:322 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "ბაიტები თითოეულ WAL სეგმენტში: %u\n" -#: pg_controldata.c:313 +#: pg_controldata.c:324 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "იდენტიფიკატორების მაქსიმალური სიგრძე: %u\n" -#: pg_controldata.c:315 +#: pg_controldata.c:326 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "ინდექსში სვეტების მაქსიმალური რაოდენობა: %u\n" -#: pg_controldata.c:317 +#: pg_controldata.c:328 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOAST ნაგლეჯის მაქსიმალური ზომა: %u\n" -#: pg_controldata.c:319 +#: pg_controldata.c:330 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "დიდი ობიექტის ნაგლეჯის ზომა: %u\n" -#: pg_controldata.c:322 +#: pg_controldata.c:333 #, c-format msgid "Date/time type storage: %s\n" msgstr "თარიღის ტიპის საცავი: %s\n" -#: pg_controldata.c:323 +#: pg_controldata.c:334 msgid "64-bit integers" msgstr "64-ბიტიანი მთელ რიცხვები" -#: pg_controldata.c:324 +#: pg_controldata.c:335 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8 არგუმენტის გადაცემა: %s\n" -#: pg_controldata.c:325 +#: pg_controldata.c:336 msgid "by reference" msgstr "ბმით" -#: pg_controldata.c:325 +#: pg_controldata.c:336 msgid "by value" msgstr "მნიშვნელობით" -#: pg_controldata.c:326 +#: pg_controldata.c:337 #, c-format msgid "Data page checksum version: %u\n" msgstr "მონაცემების გვერდის საკონტროლო ჯამის ვერსია: %u\n" -#: pg_controldata.c:328 +#: pg_controldata.c:339 +#, c-format +msgid "Default char data signedness: %s\n" +msgstr "ნაგულისხმევი სტრიქონის მონაცემების ნიშნიანობა: %s\n" + +#: pg_controldata.c:340 +msgid "signed" +msgstr "ნიშნიანი" + +#: pg_controldata.c:340 +msgid "unsigned" +msgstr "უნიშნო" + +#: pg_controldata.c:341 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "ფსევდოავთენტიკაციის შემთხვევითი რიცხვი: %s\n" diff --git a/src/bin/pg_controldata/po/ko.po b/src/bin/pg_controldata/po/ko.po index 4b40dca65e0dc..b753d7e93c13c 100644 --- a/src/bin/pg_controldata/po/ko.po +++ b/src/bin/pg_controldata/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_controldata (PostgreSQL) 16\n" +"Project-Id-Version: pg_controldata (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:52+0000\n" -"PO-Revision-Date: 2023-05-30 12:38+0900\n" +"POT-Creation-Date: 2025-01-17 04:53+0000\n" +"PO-Revision-Date: 2025-01-16 15:43+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -15,31 +15,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../common/controldata_utils.c:73 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "\"%s\" 파일을 읽기 모드로 열 수 없습니다: %m" -#: ../../common/controldata_utils.c:86 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "\"%s\" 파일을 읽을 수 없습니다: %m" -#: ../../common/controldata_utils.c:95 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" -#: ../../common/controldata_utils.c:108 ../../common/controldata_utils.c:236 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "\"%s\" 파일을 닫을 수 없습니다: %m" -#: ../../common/controldata_utils.c:124 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "바이트 순서 불일치" -#: ../../common/controldata_utils.c:126 +#: ../../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -48,26 +48,38 @@ msgid "" "and\n" "the PostgreSQL installation would be incompatible with this data directory." msgstr "" -"바이트 순서가 일치하지 않습니다.\n" -"pg_control 파일을 저장하는 데 사용된 바이트 순서는 \n" -"이 프로그램에서 사용하는 순서와 일치해야 합니다. 이 경우 아래 결과는\n" -"올바르지 않으며 이 데이터 디렉터리에 PostgreSQL을 설치할 수 없습니다." +"바이트 순서 일치하지 않는 문제\n" +"바이트 순서 정보는 pg_control 파일을 저장할 때 사용되는데,\n" +"이 파일의 바이트 순서 정보와 이 프로그램에서 사용하는 순서 정보가 다릅니다.\n" +"이럴 경우, 출력 결과가 바르지 않을 수 있고,\n" +"설치된 PostgreSQL 프로그램과 데이터 디렉터리가 호환되지 않을 수 있습니다." -#: ../../common/controldata_utils.c:186 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "\"%s\" 파일을 읽을 수 없습니다: %m" -#: ../../common/controldata_utils.c:205 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "\"%s\" 파일을 쓸 수 없습니다: %m" -#: ../../common/controldata_utils.c:224 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "\"%s\" 파일을 fsync 할 수 없습니다: %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -168,8 +180,8 @@ msgid "unrecognized status code" msgstr "알수 없는 상태 코드" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "알 수 없는 wal_level" +msgid "unrecognized \"wal_level\"" +msgstr "알 수 없는 \"wal_level\"" #: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 #, c-format @@ -186,319 +198,334 @@ msgstr "너무 많은 명령행 인수를 지정했습니다. (처음 \"%s\")" msgid "no data directory specified" msgstr "데이터 디렉터리를 지정하지 않았습니다" -#: pg_controldata.c:170 +#: pg_controldata.c:171 +#, c-format +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "계산된 CRC 체크섬 값과 컨트롤 파일에 저장된 값이 다름" + +#: pg_controldata.c:172 #, c-format msgid "" -"WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n" -"\n" +"Either the control file is corrupt, or it has a different layout than this " +"program is expecting. The results below are untrustworthy." msgstr "" -"경고: 계산된 CRC 체크섬값이 파일에 있는 값과 틀립니다.\n" -"이 경우는 파일이 손상되었거나, 이 프로그램과 컨트롤 파일의 버전이 틀린\n" -"경우입니다. 결과값들은 믿지 못할 값들이 출력될 수 있습니다.\n" -"\n" +"이 경우는 컨트롤 파일이 손상되었거나, 이 프로그램과 컨트롤 파일의 버전이 틀" +"린 경우입니다. 결과값들은 믿지 못할 값들이 출력될 수 있습니다." -#: pg_controldata.c:179 +#: pg_controldata.c:181 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "경고: 잘못된 WAL 조각 크기\n" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "컨트롤 파일의 WAL 조각 파일 크기가 올바르지 않음 (%d 바이트)" -#: pg_controldata.c:180 +#: pg_controldata.c:185 #, c-format -msgid "" -"The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgid_plural "" -"The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgstr[0] "" -"저장된 WAL 조각 파일의 크기는 %d 바이트입니다. 이 값은 1MB부터 1GB사이\n" -"2^n 값이 아닙니다. 파일이 손상되었으며, 결과 또한 믿을 수 없습니다.\n" -"\n" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL 조각 파일 크기는 1MB에서 1GB사이 2의 제곱값이어야 합니다." -#: pg_controldata.c:222 +#: pg_controldata.c:186 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "이 파일이 깨져서 신뢰할 수 없는 결과값이 출력됩니다." + +#: pg_controldata.c:221 msgid "???" msgstr "???" -#: pg_controldata.c:228 +#: pg_controldata.c:227 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control 버전 번호: %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:229 #, c-format msgid "Catalog version number: %u\n" msgstr "카탈로그 버전 번호: %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:231 #, c-format msgid "Database system identifier: %llu\n" msgstr "데이터베이스 시스템 식별자: %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:233 #, c-format msgid "Database cluster state: %s\n" msgstr "데이터베이스 클러스터 상태: %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:235 #, c-format msgid "pg_control last modified: %s\n" msgstr "pg_control 마지막 변경시간: %s\n" -#: pg_controldata.c:238 +#: pg_controldata.c:237 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "마지막 체크포인트 위치: %X/%X\n" -#: pg_controldata.c:240 +#: pg_controldata.c:239 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "마지막 체크포인트 REDO 위치: %X/%X\n" -#: pg_controldata.c:242 +#: pg_controldata.c:241 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "마지막 체크포인트 REDO WAL 파일: %s\n" -#: pg_controldata.c:244 +#: pg_controldata.c:243 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "마지막 체크포인트 TimeLineID: %u\n" -#: pg_controldata.c:246 +#: pg_controldata.c:245 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "마지막 체크포인트 PrevTimeLineID: %u\n" -#: pg_controldata.c:248 +#: pg_controldata.c:247 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "마지막 체크포인트 full_page_writes: %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "off" msgstr "off" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "on" msgstr "on" -#: pg_controldata.c:250 +#: pg_controldata.c:249 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "마지막 체크포인트 NextXID: %u:%u\n" -#: pg_controldata.c:253 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "마지막 체크포인트 NextOID: %u\n" -#: pg_controldata.c:255 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "마지막 체크포인트 NextMultiXactId: %u\n" -#: pg_controldata.c:257 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "마지막 체크포인트 NextMultiOffset: %u\n" -#: pg_controldata.c:259 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "마지막 체크포인트 제일오래된XID: %u\n" -#: pg_controldata.c:261 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "마지막 체크포인트 제일오래된XID의 DB: %u\n" -#: pg_controldata.c:263 +#: pg_controldata.c:262 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "마지막 체크포인트 제일오래된ActiveXID:%u\n" -#: pg_controldata.c:265 +#: pg_controldata.c:264 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "마지막 체크포인트 제일오래된MultiXid: %u\n" -#: pg_controldata.c:267 +#: pg_controldata.c:266 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "마지막 체크포인트 제일오래된멀티Xid DB:%u\n" -#: pg_controldata.c:269 +#: pg_controldata.c:268 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "마지막 체크포인트 제일오래된CommitTsXid:%u\n" -#: pg_controldata.c:271 +#: pg_controldata.c:270 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "마지막 체크포인트 최신CommitTsXid: %u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:272 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "마지막 체크포인트 시간: %s\n" -#: pg_controldata.c:275 +#: pg_controldata.c:274 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "언로그 릴레이션의 가짜 LSN 카운터: %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:276 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "최소 복구 마지막 위치: %X/%X\n" -#: pg_controldata.c:279 +#: pg_controldata.c:278 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "최소 복구 종료 위치의 타임라인: %u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:280 #, c-format msgid "Backup start location: %X/%X\n" msgstr "백업 시작 위치: %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:282 #, c-format msgid "Backup end location: %X/%X\n" msgstr "백업 종료 위치: %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:284 #, c-format msgid "End-of-backup record required: %s\n" msgstr "백업 종료 레코드 필요 여부: %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "no" msgstr "아니오" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "yes" msgstr "예" -#: pg_controldata.c:287 +#: pg_controldata.c:286 #, c-format msgid "wal_level setting: %s\n" msgstr "wal_level 설정값: %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:288 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "wal_log_hints 설정값: %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:290 #, c-format msgid "max_connections setting: %d\n" msgstr "max_connections 설정값: %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:292 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "max_worker_processes 설정값: %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:294 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "max_wal_senders 설정값: %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:296 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "max_prepared_xacts 설정값: %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:298 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "max_locks_per_xact 설정값: %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:300 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "track_commit_timestamp 설정값: %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:302 #, c-format msgid "Maximum data alignment: %u\n" msgstr "최대 자료 정렬: %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:305 #, c-format msgid "Database block size: %u\n" msgstr "데이터베이스 블록 크기: %u\n" -#: pg_controldata.c:308 +#: pg_controldata.c:307 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "대형 릴레이션의 세그먼트당 블럭 개수: %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:309 #, c-format msgid "WAL block size: %u\n" msgstr "WAL 블록 크기: %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:311 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "WAL 세그먼트의 크기(byte): %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:313 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "식별자 최대 길이: %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:315 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "인덱스에서 사용하는 최대 열 수: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:317 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOAST 청크 최대 크기: %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:319 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "대형 객체 청크 크기: %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:322 #, c-format msgid "Date/time type storage: %s\n" msgstr "날짜/시간형 자료의 저장방식: %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:323 msgid "64-bit integers" msgstr "64-비트 정수" -#: pg_controldata.c:325 +#: pg_controldata.c:324 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8 인수 전달: %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by reference" msgstr "참조별" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by value" msgstr "값별" -#: pg_controldata.c:327 +#: pg_controldata.c:326 #, c-format msgid "Data page checksum version: %u\n" msgstr "데이터 페이지 체크섬 버전: %u\n" -#: pg_controldata.c:329 +#: pg_controldata.c:328 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "임시 모의 인증: %s\n" + +#, c-format +#~ msgid "WARNING: invalid WAL segment size\n" +#~ msgstr "경고: 잘못된 WAL 조각 크기\n" + +#, c-format +#~ msgid "" +#~ "The WAL segment size stored in the file, %d byte, is not a power of two\n" +#~ "between 1 MB and 1 GB. The file is corrupt and the results below are\n" +#~ "untrustworthy.\n" +#~ "\n" +#~ msgid_plural "" +#~ "The WAL segment size stored in the file, %d bytes, is not a power of two\n" +#~ "between 1 MB and 1 GB. The file is corrupt and the results below are\n" +#~ "untrustworthy.\n" +#~ "\n" +#~ msgstr[0] "" +#~ "저장된 WAL 조각 파일의 크기는 %d 바이트입니다. 이 값은 1MB부터 1GB사이\n" +#~ "2^n 값이 아닙니다. 파일이 손상되었으며, 결과 또한 믿을 수 없습니다.\n" +#~ "\n" diff --git a/src/bin/pg_controldata/po/meson.build b/src/bin/pg_controldata/po/meson.build index 465bb3c2572ba..608ad5d6257db 100644 --- a/src/bin/pg_controldata/po/meson.build +++ b/src/bin/pg_controldata/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_controldata-' + pg_version_major.to_string())] diff --git a/src/bin/pg_controldata/po/ru.po b/src/bin/pg_controldata/po/ru.po index 430ec929eed2c..5197e06cc71d3 100644 --- a/src/bin/pg_controldata/po/ru.po +++ b/src/bin/pg_controldata/po/ru.po @@ -4,13 +4,13 @@ # Serguei A. Mokhov , 2002-2004. # Oleg Bartunov , 2004. # Andrey Sudnik , 2011. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pg_controldata (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-11-03 09:08+0300\n" -"PO-Revision-Date: 2022-09-05 13:34+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-04 17:08+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -20,31 +20,31 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../../common/controldata_utils.c:83 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не удалось открыть файл \"%s\" для чтения: %m" -#: ../../common/controldata_utils.c:96 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "не удалось прочитать файл \"%s\": %m" -#: ../../common/controldata_utils.c:105 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" -#: ../../common/controldata_utils.c:118 ../../common/controldata_utils.c:266 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "не удалось закрыть файл \"%s\": %m" -#: ../../common/controldata_utils.c:154 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "несоответствие порядка байт" -#: ../../common/controldata_utils.c:156 +#: ../../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -58,21 +58,32 @@ msgstr "" "этой программой. В этом случае результаты будут неверными и\n" "установленный PostgreSQL будет несовместим с этим каталогом данных." -#: ../../common/controldata_utils.c:216 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "не удалось открыть файл \"%s\": %m" -#: ../../common/controldata_utils.c:235 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "не удалось записать файл \"%s\": %m" -#: ../../common/controldata_utils.c:254 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -173,378 +184,398 @@ msgid "unrecognized status code" msgstr "нераспознанный код состояния" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "нераспознанный уровень WAL" +msgid "unrecognized \"wal_level\"" +msgstr "нераспознанное значение \"wal_level\"" -#: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 +#: pg_controldata.c:139 pg_controldata.c:157 pg_controldata.c:164 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_controldata.c:154 +#: pg_controldata.c:155 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_controldata.c:162 +#: pg_controldata.c:163 #, c-format msgid "no data directory specified" msgstr "каталог данных не указан" -#: pg_controldata.c:170 +#: pg_controldata.c:172 +#, c-format +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "" +"вычисленная контрольная сумма (CRC) не соответствует значению, сохранённому " +"в управляющем файле" + +#: pg_controldata.c:173 #, c-format msgid "" -"WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n" -"\n" +"Either the control file is corrupt, or it has a different layout than this " +"program is expecting. The results below are untrustworthy." msgstr "" -"ПРЕДУПРЕЖДЕНИЕ: Вычисленная контрольная сумма не совпадает со значением в " -"файле.\n" -"Либо файл повреждён, либо его формат отличается от ожидаемого.\n" -"Следующая информация может быть недостоверной.\n" -"\n" +"Либо управляющий файл повреждён, либо его структура отличается от ожидаемой. " +"Следующая информация может быть недостоверной." -#: pg_controldata.c:179 +#: pg_controldata.c:182 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "ПРЕДУПРЕЖДЕНИЕ: неверный размер сегмента WAL\n" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[1] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[2] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" -#: pg_controldata.c:180 +#: pg_controldata.c:186 #, c-format -msgid "" -"The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgid_plural "" -"The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgstr[0] "" -"Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " -"степенью\n" -"двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" -"подлежит сомнению.\n" -"\n" -msgstr[1] "" -"Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " -"степенью\n" -"двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" -"подлежит сомнению.\n" -"\n" -msgstr[2] "" -"Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " -"степенью\n" -"двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" -"подлежит сомнению.\n" -"\n" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "" +"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 ГБ." -#: pg_controldata.c:222 +#: pg_controldata.c:187 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "Файл испорчен, поэтому следующая информация не является достоверной." + +#: pg_controldata.c:205 pg_controldata.c:213 pg_controldata.c:232 +#, c-format msgid "???" msgstr "???" -#: pg_controldata.c:228 +#: pg_controldata.c:238 #, c-format msgid "pg_control version number: %u\n" msgstr "Номер версии pg_control: %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:240 #, c-format msgid "Catalog version number: %u\n" msgstr "Номер версии каталога: %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:242 #, c-format msgid "Database system identifier: %llu\n" msgstr "Идентификатор системы баз данных: %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:244 #, c-format msgid "Database cluster state: %s\n" msgstr "Состояние кластера БД: %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:246 #, c-format msgid "pg_control last modified: %s\n" msgstr "Последнее обновление pg_control: %s\n" # skip-rule: capital-letter-first -#: pg_controldata.c:238 +#: pg_controldata.c:248 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "Положение последней конт. точки: %X/%X\n" # skip-rule: capital-letter-first -#: pg_controldata.c:240 +#: pg_controldata.c:250 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "Положение REDO последней конт. точки: %X/%X\n" # skip-rule: capital-letter-first -#: pg_controldata.c:242 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "Файл WAL c REDO последней к. т.: %s\n" # skip-rule: capital-letter-first -#: pg_controldata.c:244 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Линия времени последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:246 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "Пред. линия времени последней к. т.: %u\n" # skip-rule: no-space-after-period -#: pg_controldata.c:248 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Режим full_page_writes последней к.т: %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "off" msgstr "выкл." -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:259 pg_controldata.c:300 pg_controldata.c:312 msgid "on" msgstr "вкл." # skip-rule: capital-letter-first -#: pg_controldata.c:250 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID последней конт. точки: %u:%u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:253 +#: pg_controldata.c:263 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:255 +#: pg_controldata.c:265 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId послед. конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:257 +#: pg_controldata.c:267 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset послед. конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:259 +#: pg_controldata.c:269 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:261 +#: pg_controldata.c:271 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "БД с oldestXID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:263 +#: pg_controldata.c:273 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID последней к. т.: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:265 +#: pg_controldata.c:275 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid последней конт. точки: %u\n" # skip-rule: double-space, capital-letter-first -#: pg_controldata.c:267 +#: pg_controldata.c:277 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "БД с oldestMulti последней к. т.: %u\n" # skip-rule: double-space, capital-letter-first -#: pg_controldata.c:269 +#: pg_controldata.c:279 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid последней к. т.: %u\n" # skip-rule: capital-letter-first, double-space -#: pg_controldata.c:271 +#: pg_controldata.c:281 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid последней к. т.: %u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:283 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "Время последней контрольной точки: %s\n" # skip-rule: capital-letter-first # well-spelled: нежурналир -#: pg_controldata.c:275 +#: pg_controldata.c:285 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "Фиктивный LSN для нежурналир. таблиц: %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:287 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "Мин. положение конца восстановления: %X/%X\n" # skip-rule: capital-letter-first -#: pg_controldata.c:279 +#: pg_controldata.c:289 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "Линия времени мин. положения к. в.: %u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:291 #, c-format msgid "Backup start location: %X/%X\n" msgstr "Положение начала копии: %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:293 #, c-format msgid "Backup end location: %X/%X\n" msgstr "Положение конца копии: %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:295 #, c-format msgid "End-of-backup record required: %s\n" msgstr "Требуется запись конец-копии: %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:296 msgid "no" msgstr "нет" -#: pg_controldata.c:286 +#: pg_controldata.c:296 msgid "yes" msgstr "да" -#: pg_controldata.c:287 +#: pg_controldata.c:297 #, c-format msgid "wal_level setting: %s\n" msgstr "Значение wal_level: %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:299 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "Значение wal_log_hints: %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:301 #, c-format msgid "max_connections setting: %d\n" msgstr "Значение max_connections: %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:303 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "Значение max_worker_processes: %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:305 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "Значение max_wal_senders: %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:307 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "Значение max_prepared_xacts: %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:309 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "Значение max_locks_per_xact: %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:311 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "Значение track_commit_timestamp: %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:313 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Макс. предел выравнивания данных: %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:316 #, c-format msgid "Database block size: %u\n" msgstr "Размер блока БД: %u\n" # skip-rule: double-space -#: pg_controldata.c:308 +#: pg_controldata.c:318 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Блоков в макс. сегменте отношений: %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:320 #, c-format msgid "WAL block size: %u\n" msgstr "Размер блока WAL: %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:322 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Байт в сегменте WAL: %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:324 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Максимальная длина идентификаторов: %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:326 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Макс. число столбцов в индексе: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:328 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Максимальный размер порции TOAST: %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:330 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Размер порции большого объекта: %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:333 #, c-format msgid "Date/time type storage: %s\n" msgstr "Формат хранения даты/времени: %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:334 msgid "64-bit integers" msgstr "64-битные целые" -#: pg_controldata.c:325 +#: pg_controldata.c:335 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Передача аргумента float8: %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:336 msgid "by reference" msgstr "по ссылке" -#: pg_controldata.c:326 +#: pg_controldata.c:336 msgid "by value" msgstr "по значению" -#: pg_controldata.c:327 +#: pg_controldata.c:337 #, c-format msgid "Data page checksum version: %u\n" msgstr "Версия контрольных сумм страниц: %u\n" # skip-rule: capital-letter-first -#: pg_controldata.c:329 +#: pg_controldata.c:339 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "Случ. число для псевдоаутентификации: %s\n" +#, c-format +#~ msgid "WARNING: invalid WAL segment size\n" +#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: неверный размер сегмента WAL\n" + +#, c-format +#~ msgid "" +#~ "The WAL segment size stored in the file, %d byte, is not a power of two\n" +#~ "between 1 MB and 1 GB. The file is corrupt and the results below are\n" +#~ "untrustworthy.\n" +#~ "\n" +#~ msgid_plural "" +#~ "The WAL segment size stored in the file, %d bytes, is not a power of two\n" +#~ "between 1 MB and 1 GB. The file is corrupt and the results below are\n" +#~ "untrustworthy.\n" +#~ "\n" +#~ msgstr[0] "" +#~ "Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " +#~ "степенью\n" +#~ "двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" +#~ "подлежит сомнению.\n" +#~ "\n" +#~ msgstr[1] "" +#~ "Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " +#~ "степенью\n" +#~ "двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" +#~ "подлежит сомнению.\n" +#~ "\n" +#~ msgstr[2] "" +#~ "Сохранённый в этом файле размер сегмента WAL (байт: %d) не является " +#~ "степенью\n" +#~ "двух между 1 МБ и 1 ГБ. Файл испорчен, выводимая ниже информация\n" +#~ "подлежит сомнению.\n" +#~ "\n" + #~ msgid "Report bugs to .\n" #~ msgstr "Об ошибках сообщайте по адресу .\n" @@ -555,11 +586,6 @@ msgstr "Случ. число для псевдоаутентификации: %s #~ msgid "Prior checkpoint location: %X/%X\n" #~ msgstr "Положение предыдущей конт. точки: %X/%X\n" -#~ msgid "calculated CRC checksum does not match value stored in file" -#~ msgstr "" -#~ "вычисленная контрольная сумма (CRC) не соответствует значению, " -#~ "сохранённому в файле" - #~ msgid "floating-point numbers" #~ msgstr "числа с плавающей точкой" diff --git a/src/bin/pg_controldata/po/sv.po b/src/bin/pg_controldata/po/sv.po index 9836890199473..07b46343b13f3 100644 --- a/src/bin/pg_controldata/po/sv.po +++ b/src/bin/pg_controldata/po/sv.po @@ -1,16 +1,16 @@ # Swedish message translation file for pg_controldata # This file is put in the public domain. -# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Mats Erik Andersson , 2014. # # Use these quotes: "%s" # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 09:21+0000\n" -"PO-Revision-Date: 2023-08-17 16:56+0200\n" +"POT-Creation-Date: 2024-07-12 14:24+0000\n" +"PO-Revision-Date: 2024-07-12 19:01+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -19,31 +19,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../common/controldata_utils.c:73 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "kunde inte öppna filen \"%s\" för läsning: %m" -#: ../../common/controldata_utils.c:86 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "kunde inte läsa fil \"%s\": %m" -#: ../../common/controldata_utils.c:95 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" -#: ../../common/controldata_utils.c:108 ../../common/controldata_utils.c:244 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "kunde inte stänga fil \"%s\": %m" -#: ../../common/controldata_utils.c:124 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "byte-ordning stämmer inte" -#: ../../common/controldata_utils.c:126 +#: ../../common/controldata_utils.c:170 #, c-format msgid "" "possible byte ordering mismatch\n" @@ -56,21 +56,32 @@ msgstr "" "inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" "och PostgreSQL-installationen vara inkompatibel med databaskatalogen." -#: ../../common/controldata_utils.c:194 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "kunde inte öppna fil \"%s\": %m" -#: ../../common/controldata_utils.c:213 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "kunde inte skriva fil \"%s\": %m" -#: ../../common/controldata_utils.c:232 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "kunde inte fsync:a fil \"%s\": %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + #: pg_controldata.c:35 #, c-format msgid "" @@ -170,8 +181,8 @@ msgid "unrecognized status code" msgstr "okänd statuskod" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "okänd wal_level" +msgid "unrecognized \"wal_level\"" +msgstr "okänd \"wal_level\"" #: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 #, c-format @@ -188,48 +199,34 @@ msgstr "för många kommandoradsargument (första är \"%s\")" msgid "no data directory specified" msgstr "ingen datakatalog angiven" -#: pg_controldata.c:170 +#: pg_controldata.c:171 #, c-format -msgid "" -"WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n" -"\n" -msgstr "" -"VARNING: Beräknad CRC-kontrollsumma matchar inte det värde som har sparats i filen.\n" -"Antingen är filen trasig, eller så har den en annan uppbyggnad än vad detta\n" -"program förväntade sig. Resultatet nedan är inte helt tillförlitligt.\n" -"\n" +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "uträknad CRC-checksumma matchar inte värdet som är lagrat i kontrollfil" -#: pg_controldata.c:179 +#: pg_controldata.c:172 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "VARNING: ogiltig WAL-segmentstorlek\n" +msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." +msgstr "Antingen är filen trasig, eller så har den en annan uppbyggnad än vad detta program förväntade sig. Resultatet nedan är inte helt tillförlitligt." -#: pg_controldata.c:180 +#: pg_controldata.c:181 #, c-format -msgid "" -"The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgid_plural "" -"The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n" -"\n" -msgstr[0] "" -"WAL-segmentstorleken sparad i filen, %d byte, är inte en tvåpotens\n" -"mellan 1 MB och 1 GB. Filen är trasig och resultatet nedan går\n" -"ej att lita på.\n" -"\n" -msgstr[1] "" -"WAL-segmentstorleken sparad i filen, %d byte, är inte en tvåpotens\n" -"mellan 1 MB och 1 GB. Filen är trasig och resultatet nedan går\n" -"ej att lita på.\n" -"\n" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" +msgstr[1] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" + +#: pg_controldata.c:185 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL-segmentstorleken måste vara en tvåpotens mellan 1 MB och 1 GB." + +#: pg_controldata.c:186 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "Filen är trasig och resultatet nedan är inte helt tillförlitligt." -#: pg_controldata.c:222 +#: pg_controldata.c:221 msgid "???" msgstr "???" @@ -239,280 +236,280 @@ msgstr "???" # used for English is insufficient for Swedish. New indenting # is consistent for all reporting statements: six additional # space characters. -#: pg_controldata.c:228 +#: pg_controldata.c:227 #, c-format msgid "pg_control version number: %u\n" msgstr "Versionsnummer för pg_control: %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:229 #, c-format msgid "Catalog version number: %u\n" msgstr "Katalogversion: %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:231 #, c-format msgid "Database system identifier: %llu\n" msgstr "Databasens systemidentifierare: %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:233 #, c-format msgid "Database cluster state: %s\n" msgstr "Databasklustrets tillstånd: %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:235 #, c-format msgid "pg_control last modified: %s\n" msgstr "pg_control ändrades senast: %s\n" -#: pg_controldata.c:238 +#: pg_controldata.c:237 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "Läge för senaste kontrollpunkt: %X/%X\n" -#: pg_controldata.c:240 +#: pg_controldata.c:239 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "REDO-läge för senaste kontrollpunkt: %X/%X\n" -#: pg_controldata.c:242 +#: pg_controldata.c:241 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "REDO-WAL-fil vid senaste kontrollpunkt: %s\n" -#: pg_controldata.c:244 +#: pg_controldata.c:243 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "TimeLineID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:246 +#: pg_controldata.c:245 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "PrevTimeLineID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:248 +#: pg_controldata.c:247 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Senaste kontrollpunktens full_page_writes: %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "off" msgstr "av" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "on" msgstr "på" -#: pg_controldata.c:250 +#: pg_controldata.c:249 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID vid senaste kontrollpunkt: %u:%u\n" -#: pg_controldata.c:253 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:255 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:257 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:259 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:261 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "DB för oldestXID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:263 +#: pg_controldata.c:262 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:265 +#: pg_controldata.c:264 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid vid senaste kontrollpunkt: %u\n" -#: pg_controldata.c:267 +#: pg_controldata.c:266 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "DB för oldestMulti vid senaste kontrollpkt: %u\n" -#: pg_controldata.c:269 +#: pg_controldata.c:268 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid vid senaste kontrollpunkt:%u\n" -#: pg_controldata.c:271 +#: pg_controldata.c:270 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid vid senaste kontrollpunkt:%u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:272 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "Tidpunkt för senaste kontrollpunkt: %s\n" -#: pg_controldata.c:275 +#: pg_controldata.c:274 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "Beräknat LSN-tal av ologgade relationer: %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:276 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "Minsta slutposition vid återställning: %X/%X\n" -#: pg_controldata.c:279 +#: pg_controldata.c:278 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "Tidslinje för min slutpos vid återställning:%u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:280 #, c-format msgid "Backup start location: %X/%X\n" msgstr "Startpunkt för backup: %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:282 #, c-format msgid "Backup end location: %X/%X\n" msgstr "Slutpunkt för backup: %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:284 #, c-format msgid "End-of-backup record required: %s\n" msgstr "Tvingande markering av backupslut: %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "no" msgstr "nej" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "yes" msgstr "ja" -#: pg_controldata.c:287 +#: pg_controldata.c:286 #, c-format msgid "wal_level setting: %s\n" msgstr "Värde på wal_level: %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:288 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "Värde på wal_log_hints: %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:290 #, c-format msgid "max_connections setting: %d\n" msgstr "Värde på max_connections: %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:292 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "Värde på max_worker_processes: %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:294 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "Värde på max_wal_senders setting %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:296 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "Värde på max_prepared_xacts: %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:298 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "Nuvarande max_locks_per_xact: %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:300 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "Värde på track_commit_timestamp: %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:302 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Maximal jämkning av data (alignment): %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:305 #, c-format msgid "Database block size: %u\n" msgstr "Databasens blockstorlek: %u\n" -#: pg_controldata.c:308 +#: pg_controldata.c:307 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Block per segment i en stor relation: %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:309 #, c-format msgid "WAL block size: %u\n" msgstr "Blockstorlek i transaktionsloggen: %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:311 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Segmentstorlek i transaktionsloggen: %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:313 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Maximal längd för identifierare: %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:315 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Maximalt antal kolonner i ett index: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:317 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Maximal storlek för en TOAST-enhet: %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:319 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Storlek för large-object-enheter: %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:322 #, c-format msgid "Date/time type storage: %s\n" msgstr "Representation av dag och tid: %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:323 msgid "64-bit integers" msgstr "64-bitars heltal" -#: pg_controldata.c:325 +#: pg_controldata.c:324 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Överföring av float8-argument: %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by reference" msgstr "med referens" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by value" msgstr "med värde" -#: pg_controldata.c:327 +#: pg_controldata.c:326 #, c-format msgid "Data page checksum version: %u\n" msgstr "Checksummaversion för datasidor: %u\n" -#: pg_controldata.c:329 +#: pg_controldata.c:328 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "Fejkat authentiseringsvärde: %s\n" diff --git a/src/bin/pg_controldata/po/uk.po b/src/bin/pg_controldata/po/uk.po index 758c4c1245eb9..c2b2e3217f1bb 100644 --- a/src/bin/pg_controldata/po/uk.po +++ b/src/bin/pg_controldata/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:51+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:24+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,34 +14,34 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_controldata.pot\n" -"X-Crowdin-File-ID: 924\n" +"X-Crowdin-File: /REL_17_STABLE/pg_controldata.pot\n" +"X-Crowdin-File-ID: 1018\n" -#: ../../common/controldata_utils.c:73 +#: ../../common/controldata_utils.c:97 #, c-format msgid "could not open file \"%s\" for reading: %m" msgstr "не вдалося відкрити файл \"%s\" для читання: %m" -#: ../../common/controldata_utils.c:86 +#: ../../common/controldata_utils.c:110 #, c-format msgid "could not read file \"%s\": %m" msgstr "не вдалося прочитати файл \"%s\": %m" -#: ../../common/controldata_utils.c:95 +#: ../../common/controldata_utils.c:119 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" -#: ../../common/controldata_utils.c:108 ../../common/controldata_utils.c:244 +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 #, c-format msgid "could not close file \"%s\": %m" msgstr "неможливо закрити файл \"%s\": %m" -#: ../../common/controldata_utils.c:124 +#: ../../common/controldata_utils.c:168 msgid "byte ordering mismatch" msgstr "неправильний порядок байтів" -#: ../../common/controldata_utils.c:126 +#: ../../common/controldata_utils.c:170 #, c-format msgid "possible byte ordering mismatch\n" "The byte ordering used to store the pg_control file might not match the one\n" @@ -50,21 +50,32 @@ msgid "possible byte ordering mismatch\n" msgstr "можлива помилка у послідовності байтів.\n" "Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." -#: ../../common/controldata_utils.c:194 +#: ../../common/controldata_utils.c:230 #, c-format msgid "could not open file \"%s\": %m" msgstr "не можливо відкрити файл \"%s\": %m" -#: ../../common/controldata_utils.c:213 +#: ../../common/controldata_utils.c:249 #, c-format msgid "could not write file \"%s\": %m" msgstr "не вдалося записати файл \"%s\": %m" -#: ../../common/controldata_utils.c:232 +#: ../../common/controldata_utils.c:268 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "не вдалося fsync файл \"%s\": %m" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + #: pg_controldata.c:35 #, c-format msgid "%s displays control information of a PostgreSQL database cluster.\n\n" @@ -153,8 +164,8 @@ msgid "unrecognized status code" msgstr "невизнаний код статусу" #: pg_controldata.c:84 -msgid "unrecognized wal_level" -msgstr "невизнаний wal_рівень" +msgid "unrecognized \"wal_level\"" +msgstr "нерозпізнано \"wal_level\"" #: pg_controldata.c:138 pg_controldata.c:156 pg_controldata.c:163 #, c-format @@ -171,309 +182,313 @@ msgstr "забагато аргументів у командному рядку msgid "no data directory specified" msgstr "каталог даних не вказано" -#: pg_controldata.c:170 +#: pg_controldata.c:171 +#, c-format +msgid "calculated CRC checksum does not match value stored in control file" +msgstr "обчислена контрольна сума CRC не збігається зі значенням, що зберігається в контрольному файлі" + +#: pg_controldata.c:172 #, c-format -msgid "WARNING: Calculated CRC checksum does not match value stored in file.\n" -"Either the file is corrupt, or it has a different layout than this program\n" -"is expecting. The results below are untrustworthy.\n\n" -msgstr "ПОПЕРЕДЖЕННЯ: Контрольна сума CRC не відповідає збереженому значенню у файлі. Або файл пошкоджено, або він містить іншу структуру, ніж очікує ця програма. Результати нижче є недостовірними.\n\n" +msgid "Either the control file is corrupt, or it has a different layout than this program is expecting. The results below are untrustworthy." +msgstr "Або контрольний файл пошкоджено, або він має іншу структуру, ніж очікує ця програма. Наведені нижче результати не заслуговують на довіру." -#: pg_controldata.c:179 +#: pg_controldata.c:181 #, c-format -msgid "WARNING: invalid WAL segment size\n" -msgstr "ПОПЕРЕДЖЕННЯ: неправильний розмір WAL сегменту \n" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "невірний розмір сегменту WAL у файлі керування (%d байт)" +msgstr[1] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[2] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[3] "невірний розмір сегмента WAL у файлі керування (%d байтів)" -#: pg_controldata.c:180 +#: pg_controldata.c:185 #, c-format -msgid "The WAL segment size stored in the file, %d byte, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n\n" -msgid_plural "The WAL segment size stored in the file, %d bytes, is not a power of two\n" -"between 1 MB and 1 GB. The file is corrupt and the results below are\n" -"untrustworthy.\n\n" -msgstr[0] "Розмір WAL сегменту збережений у файлі, %d байт, не є степенем двійки між 1 MB та 1 GB. Файл пошкоджено та результати нижче є недостовірними.\n\n" -msgstr[1] "Розмір WAL сегменту збережений у файлі, %d байтів, не є степенем двійки між 1 MB та 1 GB. Файл пошкоджено та результати нижче є недостовірними.\n\n" -msgstr[2] "Розмір WAL сегменту збережений у файлі, %d байтів, не є степенем двійки між 1 MB та 1 GB. Файл пошкоджено та результати нижче є недостовірними.\n\n" -msgstr[3] "Розмір WAL сегменту збережений у файлі, %d байта, не є степенем двійки між 1 MB та 1 GB. Файл пошкоджено та результати нижче є недостовірними.\n\n" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Розмір сегмента WAL повинен бути степенем двійки від 1 МБ до 1 ГБ." -#: pg_controldata.c:222 +#: pg_controldata.c:186 +#, c-format +msgid "The file is corrupt and the results below are untrustworthy." +msgstr "Файл пошкоджено, і наведені нижче результати не заслуговують на довіру." + +#: pg_controldata.c:221 msgid "???" msgstr "???" -#: pg_controldata.c:228 +#: pg_controldata.c:227 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control номер версії: %u\n" -#: pg_controldata.c:230 +#: pg_controldata.c:229 #, c-format msgid "Catalog version number: %u\n" msgstr "Номер версії каталогу: %u\n" -#: pg_controldata.c:232 +#: pg_controldata.c:231 #, c-format msgid "Database system identifier: %llu\n" msgstr "Системний ідентифікатор бази даних: %llu\n" -#: pg_controldata.c:234 +#: pg_controldata.c:233 #, c-format msgid "Database cluster state: %s\n" msgstr "Стан кластеру бази даних: %s\n" -#: pg_controldata.c:236 +#: pg_controldata.c:235 #, c-format msgid "pg_control last modified: %s\n" msgstr "pg_control був модифікований востаннє: %s\n" -#: pg_controldata.c:238 +#: pg_controldata.c:237 #, c-format msgid "Latest checkpoint location: %X/%X\n" msgstr "Останнє місце знаходження контрольної точки: %X/%X\n" -#: pg_controldata.c:240 +#: pg_controldata.c:239 #, c-format msgid "Latest checkpoint's REDO location: %X/%X\n" msgstr "Розташування останньої контрольної точки: %X%X\n" -#: pg_controldata.c:242 +#: pg_controldata.c:241 #, c-format msgid "Latest checkpoint's REDO WAL file: %s\n" msgstr "Останній файл контрольної точки REDO WAL: %s\n" -#: pg_controldata.c:244 +#: pg_controldata.c:243 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Останній TimeLineID контрольної точки: %u\n" -#: pg_controldata.c:246 +#: pg_controldata.c:245 #, c-format msgid "Latest checkpoint's PrevTimeLineID: %u\n" msgstr "Останній PrevTimeLineID контрольної точки: %u\n" -#: pg_controldata.c:248 +#: pg_controldata.c:247 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Останній full_page_writes контрольної точки: %s\n" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "off" msgstr "вимк" -#: pg_controldata.c:249 pg_controldata.c:290 pg_controldata.c:302 +#: pg_controldata.c:248 pg_controldata.c:289 pg_controldata.c:301 msgid "on" msgstr "увімк" -#: pg_controldata.c:250 +#: pg_controldata.c:249 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "Останній NextXID контрольної точки: %u%u\n" -#: pg_controldata.c:253 +#: pg_controldata.c:252 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "Останній NextOID контрольної точки: %u\n" -#: pg_controldata.c:255 +#: pg_controldata.c:254 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "Останній NextMultiXactId контрольної точки: %u\n" -#: pg_controldata.c:257 +#: pg_controldata.c:256 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "Останній NextMultiOffset контрольної точки: %u\n" -#: pg_controldata.c:259 +#: pg_controldata.c:258 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "Останній oldestXID контрольної точки: %u\n" -#: pg_controldata.c:261 +#: pg_controldata.c:260 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "Остання DB останнього oldestXID контрольної точки: %u\n" -#: pg_controldata.c:263 +#: pg_controldata.c:262 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "Останній oldestActiveXID контрольної точки: %u\n" -#: pg_controldata.c:265 +#: pg_controldata.c:264 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "Останній oldestMultiXid контрольної точки: %u \n" -#: pg_controldata.c:267 +#: pg_controldata.c:266 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "Остання DB останньої oldestMulti контрольної точки: %u\n" -#: pg_controldata.c:269 +#: pg_controldata.c:268 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "Останній oldestCommitTsXid контрольної точки:%u\n" -#: pg_controldata.c:271 +#: pg_controldata.c:270 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "Останній newestCommitTsXid контрольної точки: %u\n" -#: pg_controldata.c:273 +#: pg_controldata.c:272 #, c-format msgid "Time of latest checkpoint: %s\n" msgstr "Час останньої контрольної точки: %s\n" -#: pg_controldata.c:275 +#: pg_controldata.c:274 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" msgstr "Фіктивний LSN для таблиць без журналювання: %X/%X\n" -#: pg_controldata.c:277 +#: pg_controldata.c:276 #, c-format msgid "Minimum recovery ending location: %X/%X\n" msgstr "Мінімальне розташування кінця відновлення: %X/%X\n" -#: pg_controldata.c:279 +#: pg_controldata.c:278 #, c-format msgid "Min recovery ending loc's timeline: %u\n" msgstr "Мінімальна позиція історії часу завершення відновлення: %u\n" -#: pg_controldata.c:281 +#: pg_controldata.c:280 #, c-format msgid "Backup start location: %X/%X\n" msgstr "Початкове розташування резервного копіювання: %X/%X\n" -#: pg_controldata.c:283 +#: pg_controldata.c:282 #, c-format msgid "Backup end location: %X/%X\n" msgstr "Кінцеве розташування резервного копіювання: %X/%X\n" -#: pg_controldata.c:285 +#: pg_controldata.c:284 #, c-format msgid "End-of-backup record required: %s\n" msgstr "Вимагається запис кінця резервного копіювання: %s\n" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "no" msgstr "ні" -#: pg_controldata.c:286 +#: pg_controldata.c:285 msgid "yes" msgstr "так" -#: pg_controldata.c:287 +#: pg_controldata.c:286 #, c-format msgid "wal_level setting: %s\n" msgstr "налаштування wal_рівня: %s\n" -#: pg_controldata.c:289 +#: pg_controldata.c:288 #, c-format msgid "wal_log_hints setting: %s\n" msgstr "налаштування wal_log_hints: %s\n" -#: pg_controldata.c:291 +#: pg_controldata.c:290 #, c-format msgid "max_connections setting: %d\n" msgstr "налаштування max_connections: %d\n" -#: pg_controldata.c:293 +#: pg_controldata.c:292 #, c-format msgid "max_worker_processes setting: %d\n" msgstr "налаштування max_worker_processes: %d\n" -#: pg_controldata.c:295 +#: pg_controldata.c:294 #, c-format msgid "max_wal_senders setting: %d\n" msgstr "налаштування max_wal_senders: %d\n" -#: pg_controldata.c:297 +#: pg_controldata.c:296 #, c-format msgid "max_prepared_xacts setting: %d\n" msgstr "налаштування max_prepared_xacts: %d\n" -#: pg_controldata.c:299 +#: pg_controldata.c:298 #, c-format msgid "max_locks_per_xact setting: %d\n" msgstr "налаштування max_locks_per_xact: %d\n" -#: pg_controldata.c:301 +#: pg_controldata.c:300 #, c-format msgid "track_commit_timestamp setting: %s\n" msgstr "налаштування track_commit_timestamp: %s\n" -#: pg_controldata.c:303 +#: pg_controldata.c:302 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Максимальне вирівнювання даних: %u\n" -#: pg_controldata.c:306 +#: pg_controldata.c:305 #, c-format msgid "Database block size: %u\n" msgstr "Розмір блоку бази даних: %u\n" -#: pg_controldata.c:308 +#: pg_controldata.c:307 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Блоків на сегмент великого відношення: %u\n" -#: pg_controldata.c:310 +#: pg_controldata.c:309 #, c-format msgid "WAL block size: %u\n" msgstr "Pозмір блоку WAL: %u\n" -#: pg_controldata.c:312 +#: pg_controldata.c:311 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Байтів на сегмент WAL: %u\n" -#: pg_controldata.c:314 +#: pg_controldata.c:313 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Максимальна довжина ідентифікаторів: %u\n" -#: pg_controldata.c:316 +#: pg_controldata.c:315 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Максимальна кількість стовпців в індексі: %u\n" -#: pg_controldata.c:318 +#: pg_controldata.c:317 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Максимальний розмір сегменту TOAST: %u\n" -#: pg_controldata.c:320 +#: pg_controldata.c:319 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Розмір сегменту великих обїєктів: %u\n" -#: pg_controldata.c:323 +#: pg_controldata.c:322 #, c-format msgid "Date/time type storage: %s\n" msgstr "Дата/час типу сховища: %s\n" -#: pg_controldata.c:324 +#: pg_controldata.c:323 msgid "64-bit integers" msgstr "64-бітні цілі" -#: pg_controldata.c:325 +#: pg_controldata.c:324 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Передача аргументу Float8: %s\n" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by reference" msgstr "за посиланням" -#: pg_controldata.c:326 +#: pg_controldata.c:325 msgid "by value" msgstr "за значенням" -#: pg_controldata.c:327 +#: pg_controldata.c:326 #, c-format msgid "Data page checksum version: %u\n" msgstr "Версія контрольних сум сторінок даних: %u\n" -#: pg_controldata.c:329 +#: pg_controldata.c:328 #, c-format msgid "Mock authentication nonce: %s\n" msgstr "Імітувати нонс для аутентифікації: %s\n" diff --git a/src/bin/pg_controldata/po/zh_TW.po b/src/bin/pg_controldata/po/zh_TW.po index 450aec76ce0eb..b9ffb5669ac06 100644 --- a/src/bin/pg_controldata/po/zh_TW.po +++ b/src/bin/pg_controldata/po/zh_TW.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: pg_controldata (PostgreSQL) 16\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2023-09-08 21:52+0000\n" -"PO-Revision-Date: 2023-11-06 08:49+0800\n" +"PO-Revision-Date: 2024-06-26 08:37+0200\n" "Last-Translator: Zhenbang Wei \n" "Language-Team: \n" "Language: zh_TW\n" @@ -382,7 +382,7 @@ msgstr "最新檢查點的時間: %s\n" #: pg_controldata.c:275 #, c-format msgid "Fake LSN counter for unlogged rels: %X/%X\n" -msgstr "無日誌關聯的虛擬 LSN 計數: %X/%X\n" +msgstr "無日誌關聯的虛擬 LSN 計數: %X/%X\n" #: pg_controldata.c:277 #, c-format @@ -484,7 +484,7 @@ msgstr "資料庫區塊大小: %u\n" #: pg_controldata.c:308 #, c-format msgid "Blocks per segment of large relation: %u\n" -msgstr "大型關聯每個片段的區塊數: %u\n" +msgstr "大型關聯每個片段的區塊數: %u\n" #: pg_controldata.c:310 #, c-format diff --git a/src/bin/pg_controldata/t/001_pg_controldata.pl b/src/bin/pg_controldata/t/001_pg_controldata.pl index b0e938da6bcbe..4aea00d6d5af4 100644 --- a/src/bin/pg_controldata/t/001_pg_controldata.pl +++ b/src/bin/pg_controldata/t/001_pg_controldata.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_ctl/Makefile b/src/bin/pg_ctl/Makefile index a3fbad7a3a5a5..1c4bb324714dd 100644 --- a/src/bin/pg_ctl/Makefile +++ b/src/bin/pg_ctl/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_ctl # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_ctl/Makefile diff --git a/src/bin/pg_ctl/meson.build b/src/bin/pg_ctl/meson.build index da05bd8a8d476..e92ba50f8a3e6 100644 --- a/src/bin/pg_ctl/meson.build +++ b/src/bin/pg_ctl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_ctl_sources = files( 'pg_ctl.c', diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index e7e878c22f04c..8a405ff122c71 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -2,7 +2,7 @@ * * pg_ctl --- start/stops/restarts the PostgreSQL server * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/bin/pg_ctl/pg_ctl.c * @@ -618,7 +618,7 @@ wait_for_postmaster_start(pid_t pm_pid, bool do_checkpoint) * Allow 2 seconds slop for possible cross-process clock skew. */ pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]); - pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]); + pmstart = atoll(optlines[LOCK_FILE_LINE_START_TIME - 1]); if (pmstart >= start_time - 2 && #ifndef WIN32 pmpid == pm_pid diff --git a/src/bin/pg_ctl/po/de.po b/src/bin/pg_ctl/po/de.po index b61e43eefb205..3cfd780365e4b 100644 --- a/src/bin/pg_ctl/po/de.po +++ b/src/bin/pg_ctl/po/de.po @@ -1,14 +1,14 @@ # German message translation file for pg_ctl -# Peter Eisentraut , 2004 - 2024. +# Peter Eisentraut , 2004 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 07:49+0000\n" -"PO-Revision-Date: 2024-03-26 10:59+0100\n" +"POT-Creation-Date: 2025-03-19 06:50+0000\n" +"PO-Revision-Date: 2025-03-19 11:06+0100\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -40,33 +40,33 @@ msgstr "konnte kein »%s« zum Ausführen finden" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "konnte Pfad »%s« nicht in absolute Form auflösen: %m" -#: ../../common/exec.c:382 +#: ../../common/exec.c:363 #, c-format msgid "could not execute command \"%s\": %m" msgstr "konnte Befehl »%s« nicht ausführen: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "konnte nicht von Befehl »%s« lesen: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "Befehl »%s« gab keine Daten zurück" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s() fehlgeschlagen: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 msgid "out of memory" msgstr "Speicher aufgebraucht" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 +#: ../../port/path.c:831 ../../port/path.c:868 ../../port/path.c:885 #, c-format msgid "out of memory\n" msgstr "Speicher aufgebraucht\n" @@ -106,123 +106,127 @@ msgstr "Kindprozess wurde von Signal %d beendet: %s" msgid "child process exited with unrecognized status %d" msgstr "Kindprozess hat mit unbekanntem Status %d beendet" -#: ../../port/path.c:775 +#: ../../port/path.c:853 #, c-format msgid "could not get current working directory: %m\n" msgstr "konnte aktuelles Arbeitsverzeichnis nicht ermitteln: %m\n" -#: pg_ctl.c:254 +#: pg_ctl.c:255 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: Verzeichnis »%s« existiert nicht\n" -#: pg_ctl.c:257 +#: pg_ctl.c:258 #, c-format msgid "%s: could not access directory \"%s\": %m\n" msgstr "%s: konnte nicht auf Verzeichnis »%s« zugreifen: %m\n" -#: pg_ctl.c:270 +#: pg_ctl.c:271 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: Verzeichnis »%s« ist kein Datenbankclusterverzeichnis\n" -#: pg_ctl.c:283 +#: pg_ctl.c:284 #, c-format msgid "%s: could not open PID file \"%s\": %m\n" msgstr "%s: konnte PID-Datei »%s« nicht öffnen: %m\n" -#: pg_ctl.c:292 +#: pg_ctl.c:293 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: die PID-Datei »%s« ist leer\n" -#: pg_ctl.c:295 +#: pg_ctl.c:296 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: ungültige Daten in PID-Datei »%s«\n" -#: pg_ctl.c:457 pg_ctl.c:499 +#: pg_ctl.c:458 pg_ctl.c:500 #, c-format msgid "%s: could not start server: %m\n" msgstr "%s: konnte Server nicht starten: %m\n" -#: pg_ctl.c:477 +#: pg_ctl.c:478 #, c-format msgid "%s: could not start server due to setsid() failure: %m\n" msgstr "%s: konnte Server wegen setsid()-Fehler nicht starten: %m\n" -#: pg_ctl.c:547 +#: pg_ctl.c:548 #, c-format msgid "%s: could not open log file \"%s\": %m\n" msgstr "%s: konnte Logdatei »%s« nicht öffnen: %m\n" -#: pg_ctl.c:564 +#: pg_ctl.c:565 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: konnte Server nicht starten: Fehlercode %lu\n" -#: pg_ctl.c:781 +#: pg_ctl.c:789 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "%s: kann Grenzwert für Core-Datei-Größe nicht setzen; durch harten Grenzwert verboten\n" -#: pg_ctl.c:807 +#: pg_ctl.c:815 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: konnte Datei »%s« nicht lesen\n" -#: pg_ctl.c:812 +#: pg_ctl.c:820 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: Optionsdatei »%s« muss genau eine Zeile haben\n" -#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 +#: pg_ctl.c:862 pg_ctl.c:1050 pg_ctl.c:1117 #, c-format msgid "%s: could not send stop signal (PID: %d): %m\n" msgstr "%s: konnte Stopp-Signal nicht senden (PID: %d): %m\n" -#: pg_ctl.c:882 +#: pg_ctl.c:890 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden\n" -#: pg_ctl.c:885 +#: pg_ctl.c:893 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s\n" -#: pg_ctl.c:917 +#: pg_ctl.c:925 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: Initialisierung des Datenbanksystems fehlgeschlagen\n" -#: pg_ctl.c:932 +#: pg_ctl.c:940 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: ein anderer Server läuft möglicherweise; versuche trotzdem zu starten\n" -#: pg_ctl.c:980 +#: pg_ctl.c:988 msgid "waiting for server to start..." msgstr "warte auf Start des Servers..." -#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 +#: pg_ctl.c:993 pg_ctl.c:1003 pg_ctl.c:1073 pg_ctl.c:1135 pg_ctl.c:1247 msgid " done\n" msgstr " fertig\n" -#: pg_ctl.c:986 +#: pg_ctl.c:994 msgid "server started\n" msgstr "Server gestartet\n" -#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 +#: pg_ctl.c:997 pg_ctl.c:1007 pg_ctl.c:1252 msgid " stopped waiting\n" msgstr " Warten beendet\n" -#: pg_ctl.c:990 +#: pg_ctl.c:998 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: Starten des Servers hat nicht rechtzeitig abgeschlossen\n" -#: pg_ctl.c:996 +#: pg_ctl.c:1004 +msgid "server shut down because of recovery target settings\n" +msgstr "Server fuhr aufgrund der Einstellungen für das Wiederherstellungsziel herunter\n" + +#: pg_ctl.c:1008 #, c-format msgid "" "%s: could not start server\n" @@ -231,42 +235,42 @@ msgstr "" "%s: konnte Server nicht starten\n" "Prüfen Sie die Logausgabe.\n" -#: pg_ctl.c:1004 +#: pg_ctl.c:1016 msgid "server starting\n" msgstr "Server startet\n" -#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 +#: pg_ctl.c:1035 pg_ctl.c:1093 pg_ctl.c:1156 pg_ctl.c:1195 pg_ctl.c:1276 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: PID-Datei »%s« existiert nicht\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 +#: pg_ctl.c:1036 pg_ctl.c:1095 pg_ctl.c:1157 pg_ctl.c:1196 pg_ctl.c:1277 msgid "Is server running?\n" msgstr "Läuft der Server?\n" -#: pg_ctl.c:1030 +#: pg_ctl.c:1042 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: kann Server nicht anhalten; Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1044 +#: pg_ctl.c:1056 msgid "server shutting down\n" msgstr "Server fährt herunter\n" -#: pg_ctl.c:1049 pg_ctl.c:1109 +#: pg_ctl.c:1061 pg_ctl.c:1121 msgid "waiting for server to shut down..." msgstr "warte auf Herunterfahren des Servers..." -#: pg_ctl.c:1053 pg_ctl.c:1114 +#: pg_ctl.c:1065 pg_ctl.c:1126 msgid " failed\n" msgstr " Fehler\n" -#: pg_ctl.c:1055 pg_ctl.c:1116 +#: pg_ctl.c:1067 pg_ctl.c:1128 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: Server fährt nicht herunter\n" -#: pg_ctl.c:1057 pg_ctl.c:1118 +#: pg_ctl.c:1069 pg_ctl.c:1130 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -274,235 +278,235 @@ msgstr "" "TIPP: Die Option »-m fast« beendet Sitzungen sofort, statt auf das Beenden\n" "durch die Sitzungen selbst zu warten.\n" -#: pg_ctl.c:1063 pg_ctl.c:1124 +#: pg_ctl.c:1075 pg_ctl.c:1136 msgid "server stopped\n" msgstr "Server angehalten\n" -#: pg_ctl.c:1084 +#: pg_ctl.c:1096 msgid "trying to start server anyway\n" msgstr "versuche Server trotzdem zu starten\n" -#: pg_ctl.c:1093 +#: pg_ctl.c:1105 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "%s: kann Server nicht neu starten; Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1096 pg_ctl.c:1154 +#: pg_ctl.c:1108 pg_ctl.c:1166 msgid "Please terminate the single-user server and try again.\n" msgstr "Bitte beenden Sie den Einzelbenutzerserver und versuchen Sie es noch einmal.\n" -#: pg_ctl.c:1128 +#: pg_ctl.c:1140 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: alter Serverprozess (PID: %d) scheint verschwunden zu sein\n" -#: pg_ctl.c:1130 +#: pg_ctl.c:1142 msgid "starting server anyway\n" msgstr "starte Server trotzdem\n" -#: pg_ctl.c:1151 +#: pg_ctl.c:1163 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "%s: kann Server nicht neu laden; Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1160 +#: pg_ctl.c:1172 #, c-format msgid "%s: could not send reload signal (PID: %d): %m\n" msgstr "%s: konnte Signal zum Neuladen nicht senden (PID: %d): %m\n" -#: pg_ctl.c:1165 +#: pg_ctl.c:1177 msgid "server signaled\n" msgstr "Signal an Server gesendet\n" -#: pg_ctl.c:1190 +#: pg_ctl.c:1202 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: kann Server nicht befördern; Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1198 +#: pg_ctl.c:1210 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: kann Server nicht befördern; Server ist nicht im Standby-Modus\n" -#: pg_ctl.c:1208 +#: pg_ctl.c:1220 #, c-format msgid "%s: could not create promote signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Befördern »%s« nicht erzeugen: %m\n" -#: pg_ctl.c:1214 +#: pg_ctl.c:1226 #, c-format msgid "%s: could not write promote signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Befördern »%s« nicht schreiben: %m\n" -#: pg_ctl.c:1222 +#: pg_ctl.c:1234 #, c-format msgid "%s: could not send promote signal (PID: %d): %m\n" msgstr "%s: konnte Signal zum Befördern nicht senden (PID: %d): %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1237 #, c-format msgid "%s: could not remove promote signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Befördern »%s« nicht entfernen: %m\n" -#: pg_ctl.c:1232 +#: pg_ctl.c:1244 msgid "waiting for server to promote..." msgstr "warte auf Befördern des Servers..." -#: pg_ctl.c:1236 +#: pg_ctl.c:1248 msgid "server promoted\n" msgstr "Server wurde befördert\n" -#: pg_ctl.c:1241 +#: pg_ctl.c:1253 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: Befördern des Servers hat nicht rechtzeitig abgeschlossen\n" -#: pg_ctl.c:1247 +#: pg_ctl.c:1259 msgid "server promoting\n" msgstr "Server wird befördert\n" -#: pg_ctl.c:1271 +#: pg_ctl.c:1283 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: kann Logdatei nicht rotieren; Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1281 +#: pg_ctl.c:1293 #, c-format msgid "%s: could not create log rotation signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Logrotieren »%s« nicht erzeugen: %m\n" -#: pg_ctl.c:1287 +#: pg_ctl.c:1299 #, c-format msgid "%s: could not write log rotation signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Logrotieren »%s« nicht schreiben: %m\n" -#: pg_ctl.c:1295 +#: pg_ctl.c:1307 #, c-format msgid "%s: could not send log rotation signal (PID: %d): %m\n" msgstr "%s: konnte Signal zum Logrotieren nicht senden (PID: %d): %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1310 #, c-format msgid "%s: could not remove log rotation signal file \"%s\": %m\n" msgstr "%s: konnte Signaldatei zum Logrotieren »%s« nicht entfernen: %m\n" -#: pg_ctl.c:1303 +#: pg_ctl.c:1315 msgid "server signaled to rotate log file\n" msgstr "Signal zum Logrotieren an Server gesendet\n" -#: pg_ctl.c:1350 +#: pg_ctl.c:1362 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: Einzelbenutzerserver läuft (PID: %d)\n" -#: pg_ctl.c:1364 +#: pg_ctl.c:1376 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: Server läuft (PID: %d)\n" -#: pg_ctl.c:1380 +#: pg_ctl.c:1392 #, c-format msgid "%s: no server running\n" msgstr "%s: kein Server läuft\n" -#: pg_ctl.c:1397 +#: pg_ctl.c:1409 #, c-format msgid "%s: could not send signal %d (PID: %d): %m\n" msgstr "%s: konnte Signal %d nicht senden (PID: %d): %m\n" -#: pg_ctl.c:1428 +#: pg_ctl.c:1440 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: konnte eigene Programmdatei nicht finden\n" -#: pg_ctl.c:1438 +#: pg_ctl.c:1450 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: konnte »postgres« Programmdatei nicht finden\n" -#: pg_ctl.c:1508 pg_ctl.c:1542 +#: pg_ctl.c:1520 pg_ctl.c:1554 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: konnte Servicemanager nicht öffnen\n" -#: pg_ctl.c:1514 +#: pg_ctl.c:1526 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: Systemdienst »%s« ist bereits registriert\n" -#: pg_ctl.c:1525 +#: pg_ctl.c:1537 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: konnte Systemdienst »%s« nicht registrieren: Fehlercode %lu\n" -#: pg_ctl.c:1548 +#: pg_ctl.c:1560 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: Systemdienst »%s« ist nicht registriert\n" -#: pg_ctl.c:1555 +#: pg_ctl.c:1567 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: konnte Systemdienst »%s« nicht öffnen: Fehlercode %lu\n" -#: pg_ctl.c:1564 +#: pg_ctl.c:1576 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: konnte Systemdienst »%s« nicht deregistrieren: Fehlercode %lu\n" -#: pg_ctl.c:1651 +#: pg_ctl.c:1663 msgid "Waiting for server startup...\n" msgstr "Warte auf Start des Servers...\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1666 msgid "Timed out waiting for server startup\n" msgstr "Zeitüberschreitung beim Warten auf Start des Servers\n" -#: pg_ctl.c:1658 +#: pg_ctl.c:1670 msgid "Server started and accepting connections\n" msgstr "Server wurde gestartet und nimmt Verbindungen an\n" -#: pg_ctl.c:1713 +#: pg_ctl.c:1725 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: konnte Systemdienst »%s« nicht starten: Fehlercode %lu\n" -#: pg_ctl.c:1786 +#: pg_ctl.c:1798 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: konnte Prozess-Token nicht öffnen: Fehlercode %lu\n" -#: pg_ctl.c:1800 +#: pg_ctl.c:1812 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: konnte SIDs nicht erzeugen: Fehlercode %lu\n" -#: pg_ctl.c:1826 +#: pg_ctl.c:1838 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: konnte beschränktes Token nicht erzeugen: Fehlercode %lu\n" -#: pg_ctl.c:1908 +#: pg_ctl.c:1920 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: konnte LUIDs für Privilegien nicht ermitteln: Fehlercode %lu\n" -#: pg_ctl.c:1916 pg_ctl.c:1931 +#: pg_ctl.c:1928 pg_ctl.c:1943 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: konnte Token-Informationen nicht ermitteln: Fehlercode %lu\n" -#: pg_ctl.c:1925 +#: pg_ctl.c:1937 #, c-format msgid "%s: out of memory\n" msgstr "%s: Speicher aufgebraucht\n" -#: pg_ctl.c:1955 +#: pg_ctl.c:1967 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n" -#: pg_ctl.c:1963 +#: pg_ctl.c:1975 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -512,17 +516,17 @@ msgstr "" "starten, anzuhalten oder zu steuern.\n" "\n" -#: pg_ctl.c:1964 +#: pg_ctl.c:1976 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_ctl.c:1965 +#: pg_ctl.c:1977 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D DATENVERZ] [-s] [-o OPTIONEN]\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1978 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -531,12 +535,12 @@ msgstr "" " %s start [-D DATENVERZ] [-l DATEINAME] [-W] [-t SEK] [-s]\n" " [-o OPTIONEN] [-p PFAD] [-c]\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1980 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D DATENVERZ] [-m SHUTDOWN-MODUS] [-W] [-t SEK] [-s]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1981 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -545,32 +549,32 @@ msgstr "" " %s restart [-D DATENVERZ] [-m SHUTDOWN-MODUS] [-W] [-t SEK] [-s]\n" " [-o OPTIONEN] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1983 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D DATENVERZ] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1984 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D DATENVERZ]\n" -#: pg_ctl.c:1973 +#: pg_ctl.c:1985 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D DATENVERZ] [-W] [-t SEK] [-s]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1986 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D DATENVERZ] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1987 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill SIGNALNAME PID\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1989 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -579,12 +583,12 @@ msgstr "" " %s register [-D DATENVERZ] [-N DIENSTNAME] [-U BENUTZERNAME] [-P PASSWORT]\n" " [-S STARTTYP] [-e QUELLE] [-W] [-t SEK] [-s] [-o OPTIONEN]\n" -#: pg_ctl.c:1979 +#: pg_ctl.c:1991 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N DIENSTNAME]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1994 #, c-format msgid "" "\n" @@ -593,56 +597,56 @@ msgstr "" "\n" "Optionen für alle Modi:\n" -#: pg_ctl.c:1983 +#: pg_ctl.c:1995 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=DATENVERZ Datenbankverzeichnis\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1997 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr "" " -e QUELLE Ereignisquelle fürs Loggen, wenn als Systemdienst\n" " gestartet\n" -#: pg_ctl.c:1987 +#: pg_ctl.c:1999 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent nur Fehler zeigen, keine Informationsmeldungen\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:2000 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=SEK Sekunden zu warten bei Option -w\n" -#: pg_ctl.c:1989 +#: pg_ctl.c:2001 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:2002 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait warten bis Operation abgeschlossen ist (Voreinstellung)\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:2003 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait nicht warten bis Operation abgeschlossen ist\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:2004 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:2005 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "" "Wenn die Option -D weggelassen wird, dann wird die Umgebungsvariable\n" "PGDATA verwendet.\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:2007 #, c-format msgid "" "\n" @@ -651,24 +655,24 @@ msgstr "" "\n" "Optionen für Start oder Neustart:\n" -#: pg_ctl.c:1997 +#: pg_ctl.c:2009 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files erlaubt postgres Core-Dateien zu erzeugen\n" -#: pg_ctl.c:1999 +#: pg_ctl.c:2011 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files betrifft diese Plattform nicht\n" -#: pg_ctl.c:2001 +#: pg_ctl.c:2013 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr "" " -l, --log=DATEINAME Serverlog in DATEINAME schreiben (wird an bestehende\n" " Datei angehängt)\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:2014 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -677,12 +681,12 @@ msgstr "" " -o, --options=OPTIONEN Kommandozeilenoptionen für postgres (PostgreSQL-\n" " Serverprogramm) oder initdb\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2016 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p PFAD-ZU-POSTGRES normalerweise nicht notwendig\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -691,12 +695,12 @@ msgstr "" "\n" "Optionen für Anhalten oder Neustart:\n" -#: pg_ctl.c:2006 +#: pg_ctl.c:2018 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=MODUS MODUS kann »smart«, »fast« oder »immediate« sein\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2020 #, c-format msgid "" "\n" @@ -705,24 +709,24 @@ msgstr "" "\n" "Shutdown-Modi sind:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2021 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart beenden nachdem alle Clientverbindungen geschlossen sind\n" -#: pg_ctl.c:2010 +#: pg_ctl.c:2022 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast sofort beenden, mit richtigem Shutdown (Voreinstellung)\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2023 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr "" " immediate beenden ohne vollständigen Shutdown; führt zu Recovery-Lauf\n" " beim Neustart\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2025 #, c-format msgid "" "\n" @@ -731,7 +735,7 @@ msgstr "" "\n" "Erlaubte Signalnamen für »kill«:\n" -#: pg_ctl.c:2017 +#: pg_ctl.c:2029 #, c-format msgid "" "\n" @@ -740,27 +744,27 @@ msgstr "" "\n" "Optionen für »register« und »unregister«:\n" -#: pg_ctl.c:2018 +#: pg_ctl.c:2030 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N DIENSTNAME Systemdienstname für Registrierung des PostgreSQL-Servers\n" -#: pg_ctl.c:2019 +#: pg_ctl.c:2031 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P PASSWORD Passwort des Benutzers für Registrierung des PostgreSQL-Servers\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2032 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U USERNAME Benutzername für Registrierung des PostgreSQL-Servers\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2033 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S STARTTYP Systemdienst-Starttyp für PostgreSQL-Server\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2035 #, c-format msgid "" "\n" @@ -769,19 +773,19 @@ msgstr "" "\n" "Starttypen sind:\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2036 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr "" " auto Dienst automatisch starten beim Start des Betriebssystems\n" " (Voreinstellung)\n" -#: pg_ctl.c:2025 +#: pg_ctl.c:2037 #, c-format msgid " demand start service on demand\n" msgstr " demand Dienst bei Bedarf starten\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2040 #, c-format msgid "" "\n" @@ -790,37 +794,37 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: pg_ctl.c:2029 +#: pg_ctl.c:2041 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: pg_ctl.c:2054 +#: pg_ctl.c:2066 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: unbekannter Shutdown-Modus »%s«\n" -#: pg_ctl.c:2083 +#: pg_ctl.c:2095 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: unbekannter Signalname »%s«\n" -#: pg_ctl.c:2100 +#: pg_ctl.c:2112 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: unbekannter Starttyp »%s«\n" -#: pg_ctl.c:2156 +#: pg_ctl.c:2168 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: konnte das Datenverzeichnis mit Befehl »%s« nicht ermitteln\n" -#: pg_ctl.c:2179 +#: pg_ctl.c:2191 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: Kontrolldatei scheint kaputt zu sein\n" -#: pg_ctl.c:2247 +#: pg_ctl.c:2259 #, c-format msgid "" "%s: cannot be run as root\n" @@ -831,32 +835,32 @@ msgstr "" "Bitte loggen Sie sich (z.B. mit »su«) als der (unprivilegierte) Benutzer\n" "ein, der Eigentümer des Serverprozesses sein soll.\n" -#: pg_ctl.c:2319 +#: pg_ctl.c:2331 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: Option -S wird auf dieser Plattform nicht unterstützt\n" -#: pg_ctl.c:2375 +#: pg_ctl.c:2387 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: fehlende Argumente für »kill«-Modus\n" -#: pg_ctl.c:2393 +#: pg_ctl.c:2405 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: unbekannter Operationsmodus »%s«\n" -#: pg_ctl.c:2402 +#: pg_ctl.c:2414 #, c-format msgid "%s: too many command-line arguments (first is \"%s\")\n" msgstr "%s: zu viele Kommandozeilenargumente (das erste ist »%s«)\n" -#: pg_ctl.c:2409 +#: pg_ctl.c:2421 #, c-format msgid "%s: no operation specified\n" msgstr "%s: keine Operation angegeben\n" -#: pg_ctl.c:2430 +#: pg_ctl.c:2442 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: kein Datenbankverzeichnis angegeben und Umgebungsvariable PGDATA nicht gesetzt\n" diff --git a/src/bin/pg_ctl/po/es.po b/src/bin/pg_ctl/po/es.po index ea82807aee75f..f57f1217e9586 100644 --- a/src/bin/pg_ctl/po/es.po +++ b/src/bin/pg_ctl/po/es.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_ctl (PostgreSQL) 16\n" +"Project-Id-Version: pg_ctl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:18+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:49+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -21,38 +21,57 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.2\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "memoria agotada" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:830 ../../port/path.c:867 ../../port/path.c:884 #, c-format msgid "out of memory\n" msgstr "memoria agotada\n" @@ -92,125 +111,125 @@ msgstr "el proceso hijo fue terminado por una señal %d: %s" msgid "child process exited with unrecognized status %d" msgstr "el proceso hijo terminó con código no reconocido %d" -#: ../../port/path.c:775 +#: ../../port/path.c:852 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "no se pudo obtener el directorio de trabajo actual: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "no se pudo obtener el directorio de trabajo actual: %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: el directorio «%s» no existe\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: no se pudo acceder al directorio «%s»: %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: no se pudo acceder al directorio «%s»: %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: el directorio «%s» no es un directorio de base de datos\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s: no se pudo abrir el archivo de PID «%s»: %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s: no se pudo abrir el archivo de PID «%s»: %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: el archivo de PID «%s» está vacío\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: datos no válidos en archivo de PID «%s»\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s: no se pudo iniciar el servidor: %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s: no se pudo iniciar el servidor: %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s: no se pudo iniciar el servidor debido a falla en setsid(): %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s: no se pudo iniciar el servidor debido a falla en setsid(): %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s: no se pudo abrir el archivo de log «%s»: %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s: no se pudo abrir el archivo de log «%s»: %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: no se pudo iniciar el servidor: código de error %lu\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "" "%s: no se puede establecer el límite de archivos de volcado;\n" "impedido por un límite duro\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: no se pudo leer el archivo «%s»\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: archivo de opciones «%s» debe tener exactamente una línea\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s: falló la señal de detención (PID: %d): %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s: falló la señal de detención (PID: %d): %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "el programa «%s» es requerido por %s, pero no fue encontrado en el mismo directorio que «%s»\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "El programa «%s» fue encontrado por «%s», pero no es de la misma versión que %s\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: falló la creación de la base de datos\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: otro servidor puede estar en ejecución; tratando de iniciarlo de todas formas.\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "esperando que el servidor se inicie..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " listo\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "servidor iniciado\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " abandonando la espera\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: el servidor no inició a tiempo\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "" "%s: could not start server\n" @@ -219,44 +238,42 @@ msgstr "" "%s: no se pudo iniciar el servidor.\n" "Examine el registro del servidor.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "servidor iniciándose\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: el archivo de PID «%s» no existe\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "¿Está el servidor en ejecución?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" -msgstr "" -"%s: no se puede detener el servidor;\n" -"un servidor en modo mono-usuario está en ejecución (PID: %d)\n" +msgstr "%s: no se puede detener el servidor; un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "servidor deteniéndose\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "esperando que el servidor se detenga..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " falló\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: el servidor no se detiene\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -264,243 +281,237 @@ msgstr "" "SUGERENCIA: La opción «-m fast» desconecta las sesiones inmediatamente\n" "en lugar de esperar que cada sesión finalice por sí misma.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "servidor detenido\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "intentando iniciae el servidor de todas maneras\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" -msgstr "" -"%s: no se puede reiniciar el servidor;\n" -"un servidor en modo mono-usuario está en ejecución (PID: %d)\n" +msgstr "%s: no se puede reiniciar el servidor; un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "Por favor termine el servidor mono-usuario e intente nuevamente.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: el proceso servidor antiguo (PID: %d) parece no estar\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "iniciando el servidor de todas maneras\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" -msgstr "" -"%s: no se puede recargar el servidor;\n" -"un servidor en modo mono-usuario está en ejecución (PID: %d)\n" +msgstr "%s: no se puede recargar el servidor; un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s: la señal de recarga falló (PID: %d): %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s: no se pudo enviar señal de recarga (PID: %d): %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "se ha enviado una señal al servidor\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" -msgstr "" -"%s: no se puede promover el servidor;\n" -"un servidor en modo mono-usuario está en ejecución (PID: %d)\n" +msgstr "%s: no se puede promover el servidor; un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "" "%s: no se puede promover el servidor;\n" "el servidor no está en modo «standby»\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s: no se pudo crear el archivo de señal de promoción «%s»: %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s: no se pudo crear el archivo de señal de promoción «%s»: %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s: no se pudo escribir al archivo de señal de promoción «%s»: %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s: no se pudo escribir al archivo de señal de promoción «%s»: %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s: no se pudo enviar la señal de promoción (PID: %d): %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s: no se pudo enviar la señal de promoción (PID: %d): %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s: no se pudo eliminar el archivo de señal de promoción «%s»: %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s: no se pudo eliminar el archivo de señal de promoción «%s»: %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "esperando que el servidor se promueva..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "servidor promovido\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: el servidor no se promovió a tiempo\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "servidor promoviendo\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: no se puede rotar el archivo de log; un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" -msgstr "%s: no se pudo crear el archivo de señal de rotación de log «%s»: %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" +msgstr "%s: no se pudo crear el archivo de señal de rotación de log «%s»: %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" -msgstr "%s: no se pudo escribir al archivo de señal de rotación de log «%s»: %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" +msgstr "%s: no se pudo escribir al archivo de señal de rotación de log «%s»: %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s: no se pudo enviar la señal de rotación de log (PID: %d): %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s: no se pudo enviar la señal de rotación de log (PID: %d): %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" -msgstr "%s: no se pudo eliminar el archivo de señal de rotación de log «%s»: %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" +msgstr "%s: no se pudo eliminar el archivo de señal de rotación de log «%s»: %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "se ha enviado una señal de rotación de log al servidor\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: un servidor en modo mono-usuario está en ejecución (PID: %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: el servidor está en ejecución (PID: %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s: no hay servidor en ejecución\n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s: no se pudo enviar la señal %d (PID: %d): %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s: no se pudo enviar la señal %d (PID: %d): %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: no se pudo encontrar el ejecutable propio\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: no se pudo encontrar el ejecutable postgres\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: no se pudo abrir el gestor de servicios\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: el servicio «%s» ya está registrado\n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: no se pudo registrar el servicio «%s»: código de error %lu\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: el servicio «%s» no ha sido registrado\n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: no se pudo abrir el servicio «%s»: código de error %lu\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: no se pudo dar de baja el servicio «%s»: código de error %lu\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "Esperando que el servidor se inicie...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "Se agotó el tiempo de espera al inicio del servidor\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "Servidor iniciado y aceptando conexiones\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: no se pudo iniciar el servicio «%s»: código de error %lu\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: no se pudo abrir el token de proceso: código de error %lu\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: no se pudo emplazar los SIDs: código de error %lu\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: no se pudo crear el token restringido: código de error %lu\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: no se pudo obtener LUIDs para privilegios: código de error %lu\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: no se pudo obtener información de token: código de error %lu\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s: memoria agotada\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Use «%s --help» para obtener más información.\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -510,17 +521,17 @@ msgstr "" "un servidor PostgreSQL.\n" "\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D DATADIR] [-s] [-o OPCIONES]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -529,12 +540,12 @@ msgstr "" " %s start [-D DATADIR] [-l ARCHIVO] [-W] [-t SEGS] [-s]\n" " [-o OPCIONES] [-p RUTA] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D DATADIR] [-m MODO-DETENCIÓN] [-W] [-t SEGS] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -543,32 +554,32 @@ msgstr "" " %s restart [-D DATADIR] [-m MODO-DETENCIÓN] [-W] [-t SEGS] [-s]\n" " [-o OPCIONES]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D DATADIR] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D DATADIR]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D DATADIR] [-W] [-t SEGS] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D DATADIR] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill NOMBRE-SEÑAL ID-DE-PROCESO\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -577,12 +588,12 @@ msgstr "" " %s register [-D DATADIR] [-N SERVICIO] [-U USUARIO] [-P PASSWORD]\n" " [-S TIPO-INICIO] [-e ORIGEN] [-W] [-t SEGS] [-o OPCIONES]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N SERVICIO]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "" "\n" @@ -591,52 +602,52 @@ msgstr "" "\n" "Opciones comunes:\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata DATADIR ubicación del área de almacenamiento de datos\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr " -e ORIGEN origen para el log de eventos cuando se ejecuta como servicio\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent mostrar sólo errores, no mensajes de información\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=SEGS segundos a esperar cuando se use la opción -w\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión, luego salir\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait esperar hasta que la operación se haya completado (por omisión)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait no esperar hasta que la operación se haya completado\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda, luego salir\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "Si la opción -D es omitida, se usa la variable de ambiente PGDATA.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "" "\n" @@ -645,24 +656,24 @@ msgstr "" "\n" "Opciones para inicio y reinicio:\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr "" " -c, --core-files permite que postgres produzca archivos\n" " de volcado (core)\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files no aplicable en esta plataforma\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l --log=ARCHIVO guardar el registro del servidor en ARCHIVO.\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -671,12 +682,12 @@ msgstr "" " -o, --options=OPCIONES parámetros de línea de órdenes a pasar a postgres\n" " (ejecutable del servidor de PostgreSQL) o initdb\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p RUTA-A-POSTGRES normalmente no es necesario\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "" "\n" @@ -685,12 +696,12 @@ msgstr "" "\n" "Opciones para detener o reiniciar:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=MODO puede ser «smart», «fast» o «immediate»\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "" "\n" @@ -699,24 +710,24 @@ msgstr "" "\n" "Modos de detención son:\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart salir después que todos los clientes se hayan desconectado\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast salir directamente, con apagado apropiado (por omisión)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr "" " immediate salir sin apagado completo; se ejecutará recuperación\n" " en el próximo inicio\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "" "\n" @@ -725,7 +736,7 @@ msgstr "" "\n" "Nombres de señales permitidos para kill:\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -734,35 +745,35 @@ msgstr "" "\n" "Opciones para registrar y dar de baja:\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr "" " -N SERVICIO nombre de servicio con el cual registrar\n" " el servidor PostgreSQL\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr "" " -P CONTRASEÑA contraseña de la cuenta con la cual registrar\n" " el servidor PostgreSQL\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr "" " -U USUARIO nombre de usuario de la cuenta con la cual\n" " registrar el servidor PostgreSQL\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr "" " -S TIPO-INICIO tipo de inicio de servicio con que registrar\n" " el servidor PostgreSQL\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "" "\n" @@ -771,17 +782,17 @@ msgstr "" "\n" "Tipos de inicio del servicio son:\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr " auto iniciar automáticamente al inicio del sistema (por omisión)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand iniciar el servicio en demanda\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "" "\n" @@ -790,37 +801,37 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: modo de apagado «%s» no reconocido\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: nombre de señal «%s» no reconocido\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: tipo de inicio «%s» no reconocido\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: no se pudo determinar el directorio de datos usando la orden «%s»\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: el archivo de control parece estar corrupto\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "" "%s: cannot be run as root\n" @@ -831,32 +842,32 @@ msgstr "" "Por favor conéctese (usando, por ejemplo, «su») con un usuario no privilegiado,\n" "quien ejecutará el proceso servidor.\n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: la opción -S no está soportada en esta plataforma\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s: demasiados argumentos de línea de órdenes (el primero es «%s»)\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: argumentos faltantes para envío de señal\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: modo de operación «%s» no reconocido\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: demasiados argumentos de línea de órdenes (el primero es «%s»)\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s: no se especificó operación\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: no se especificó directorio de datos y la variable PGDATA no está definida\n" diff --git a/src/bin/pg_ctl/po/fr.po b/src/bin/pg_ctl/po/fr.po index f5d95cd84a619..ea31cdbc395f9 100644 --- a/src/bin/pg_ctl/po/fr.po +++ b/src/bin/pg_ctl/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:18+0000\n" -"PO-Revision-Date: 2023-07-29 22:45+0200\n" +"POT-Creation-Date: 2024-08-22 10:19+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,40 +21,59 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binaire « %s » invalide : %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "n'a pas pu lire le binaire « %s » : %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "n'a pas pu trouver un « %s » à exécuter" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "n'a pas pu résoudre le chemin « %s » en sa forme absolue : %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "n'a pas pu exécuter la commande « %s » : %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "n'a pas pu lire à partir de la commande « %s » : %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "aucune donnée n'a été renvoyée par la commande « %s »" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "mémoire épuisée" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 #, c-format msgid "out of memory\n" msgstr "mémoire épuisée\n" @@ -96,125 +115,125 @@ msgstr "le processus fils a quitté avec un statut %d non reconnu" #: ../../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "n'a pas pu obtenir le répertoire de travail : %s\n" +msgid "could not get current working directory: %m\n" +msgstr "n'a pas pu obtenir le répertoire de travail : %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s : le répertoire « %s » n'existe pas\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s : n'a pas pu accéder au répertoire « %s » : %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s : n'a pas pu accéder au répertoire « %s » : %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s : le répertoire « %s » n'est pas un répertoire d'instance\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s : n'a pas pu ouvrir le fichier de PID « %s » : %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s : n'a pas pu ouvrir le fichier de PID « %s » : %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s : le fichier PID « %s » est vide\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s : données invalides dans le fichier de PID « %s »\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s : n'a pas pu démarrer le serveur : %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s : n'a pas pu démarrer le serveur : %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s : n'a pas pu démarrer le serveur à cause d'un échec de setsid() : %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s : n'a pas pu démarrer le serveur à cause d'un échec de setsid() : %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s : n'a pas pu ouvrir le journal applicatif « %s » : %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s : n'a pas pu ouvrir le journal applicatif « %s » : %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s : n'a pas pu démarrer le serveur : code d'erreur %lu\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "" "%s : n'a pas pu initialiser la taille des fichiers core, ceci est interdit\n" "par une limite dure\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s : n'a pas pu lire le fichier « %s »\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s : le fichier d'options « %s » ne doit comporter qu'une seule ligne\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s : n'a pas pu envoyer le signal d'arrêt (PID : %d) : %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s : n'a pas pu envoyer le signal d'arrêt (PID : %d) : %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé dans le même répertoire que « %s »\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "le programme « %s » a été trouvé par « %s » mais n'est pas de la même version que %s\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s : l'initialisation du système a échoué\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "" "%s : un autre serveur semble en cours d'exécution ; le démarrage du serveur\n" "va toutefois être tenté\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "en attente du démarrage du serveur..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " effectué\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "serveur démarré\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " attente arrêtée\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s : le serveur ne s'est pas lancé à temps\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "" "%s: could not start server\n" @@ -223,44 +242,44 @@ msgstr "" "%s : n'a pas pu démarrer le serveur\n" "Examinez le journal applicatif.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "serveur en cours de démarrage\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s : le fichier de PID « %s » n'existe pas\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "Le serveur est-il en cours d'exécution ?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "" "%s : ne peut pas arrêter le serveur ; le serveur mono-utilisateur est en\n" "cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "serveur en cours d'arrêt\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "en attente de l'arrêt du serveur..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " a échoué\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s : le serveur ne s'est pas arrêté\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -268,243 +287,243 @@ msgstr "" "ASTUCE : l'option « -m fast » déconnecte immédiatement les sessions plutôt que\n" "d'attendre la déconnexion des sessions déjà présentes.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "serveur arrêté\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "tentative de lancement du serveur malgré tout\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "" "%s : ne peut pas relancer le serveur ; le serveur mono-utilisateur est en\n" "cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "Merci d'arrêter le serveur mono-utilisateur et de réessayer.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s : l'ancien processus serveur (PID : %d) semble être parti\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "lancement du serveur malgré tout\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "" "%s : ne peut pas recharger le serveur ; le serveur mono-utilisateur est en\n" "cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s : n'a pas pu envoyer le signal de rechargement (PID : %d) : %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s : n'a pas pu envoyer le signal de rechargement (PID : %d) : %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "envoi d'un signal au serveur\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "" "%s : ne peut pas promouvoir le serveur ; le serveur mono-utilisateur est en\n" "cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s : ne peut pas promouvoir le serveur ; le serveur n'est pas en standby\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu créer le fichier « %s » signalant la promotion : %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu créer le fichier « %s » signalant la promotion : %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu écrire le fichier « %s » signalant la promotion : %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu écrire le fichier « %s » signalant la promotion : %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s : n'a pas pu envoyer le signal de promotion (PID : %d) : %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s : n'a pas pu envoyer le signal de promotion (PID : %d) : %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu supprimer le fichier « %s » signalant la promotion : %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu supprimer le fichier « %s » signalant la promotion : %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "en attente du serveur à promouvoir..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "serveur promu\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s : le serveur ne s'est pas promu à temps\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "serveur en cours de promotion\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "" "%s : ne peut pas faire une rotation de fichier de traces ; le serveur mono-utilisateur est en\n" "cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu créer le fichier « %s » de demande de rotation des fichiers de trace : %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu créer le fichier « %s » de demande de rotation des fichiers de trace : %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu écrire le fichier « %s » de demande de rotation des fichiers de trace : %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu écrire le fichier « %s » de demande de rotation des fichiers de trace : %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s : n'a pas pu envoyer le signal de rotation des fichiers de trace (PID : %d) : %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s : n'a pas pu envoyer le signal de rotation des fichiers de trace (PID : %d) : %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" -msgstr "%s : n'a pas pu supprimer le fichier « %s » signalant la demande de rotation des fichiers de trace : %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" +msgstr "%s : n'a pas pu supprimer le fichier « %s » signalant la demande de rotation des fichiers de trace : %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "envoi d'un signal au serveur pour faire une rotation des traces\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s : le serveur mono-utilisateur est en cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s : le serveur est en cours d'exécution (PID : %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s : aucun serveur en cours d'exécution\n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s : n'a pas pu envoyer le signal %d (PID : %d) : %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s : n'a pas pu envoyer le signal %d (PID : %d) : %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s : n'a pas pu trouver l'exécutable du programme\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s : n'a pas pu trouver l'exécutable postgres\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s : n'a pas pu ouvrir le gestionnaire de services\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s : le service « %s » est déjà enregistré\n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s : n'a pas pu enregistrer le service « %s » : code d'erreur %lu\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s : le service « %s » n'est pas enregistré\n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s : n'a pas pu ouvrir le service « %s » : code d'erreur %lu\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s : n'a pas pu supprimer le service « %s » : code d'erreur %lu\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "En attente du démarrage du serveur...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "Dépassement du délai pour le démarrage du serveur\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "Serveur lancé et acceptant les connexions\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s : n'a pas pu démarrer le service « %s » : code d'erreur %lu\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s : n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s : n'a pas pu créer le jeton restreint : code d'erreur %lu\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s : n'a pas pu obtenir les LUID pour les droits : code d'erreur %lu\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s : n'a pas pu obtenir l'information sur le jeton : code d'erreur %lu\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s : mémoire épuisée\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Essayer « %s --help » pour plus d'informations.\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -514,17 +533,17 @@ msgstr "" "PostgreSQL.\n" "\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D RÉP_DONNÉES] [-s] [-o OPTIONS]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -533,12 +552,12 @@ msgstr "" " %s start [-D RÉP_DONNÉES] [-l FICHIER] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-p CHEMIN] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D RÉP_DONNÉES] [-m MODE_ARRÊT] [-W] [-t SECS] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -547,32 +566,32 @@ msgstr "" " %s restart [-D RÉP_DONNÉES] [-m MODE_ARRÊT] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-c]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D RÉP_DONNÉES] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D RÉP_DONNÉES]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D RÉP_DONNÉES] [-W] [-t SECS] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D RÉP_DONNÉES] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill NOM_SIGNAL PID\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -581,12 +600,12 @@ msgstr "" " %s register [-D RÉP_DONNÉES] [-N NOM_SERVICE] [-U NOM_UTILISATEUR] [-P MOT_DE_PASSE]\n" " [-S TYPE_DÉMARRAGE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N NOM_SERVICE]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "" "\n" @@ -595,58 +614,58 @@ msgstr "" "\n" "Options générales :\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=RÉP_DONNÉES emplacement du répertoire des données de l'instance\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr "" " -e SOURCE source de l'événement pour la trace lors de\n" " l'exécution en tant que service\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr "" " -s, --silent affiche uniquement les erreurs, aucun message\n" " d'informations\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr "" " -t, --timeout=SECS durée en secondes à attendre lors de l'utilisation\n" " de l'option -w\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait attend la fin de l'opération (par défaut)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait n'attend pas la fin de l'opération\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "Si l'option -D est omise, la variable d'environnement PGDATA est utilisée.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "" "\n" @@ -655,22 +674,22 @@ msgstr "" "\n" "Options pour le démarrage ou le redémarrage :\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files autorise postgres à produire des fichiers core\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files non applicable à cette plateforme\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log=FICHIER écrit (ou ajoute) le journal du serveur dans FICHIER\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -680,12 +699,12 @@ msgstr "" " postgres (exécutable du serveur PostgreSQL)\n" " ou à initdb\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p CHEMIN_POSTGRES normalement pas nécessaire\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "" "\n" @@ -694,14 +713,14 @@ msgstr "" "\n" "Options pour l'arrêt ou le redémarrage :\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr "" " -m, --mode=MODE MODE peut valoir « smart », « fast » ou\n" " « immediate »\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "" "\n" @@ -710,24 +729,24 @@ msgstr "" "\n" "Les modes d'arrêt sont :\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart quitte après déconnexion de tous les clients\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast quitte directement, et arrête correctement (par défaut)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr "" " immediate quitte sans arrêt complet ; entraîne une restauration au démarrage\n" " suivant\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "" "\n" @@ -736,7 +755,7 @@ msgstr "" "\n" "Signaux autorisés pour kill :\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -745,35 +764,35 @@ msgstr "" "\n" "Options d'enregistrement ou de dés-enregistrement :\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr "" " -N NOM_SERVICE nom du service utilisé pour l'enregistrement du\n" " serveur PostgreSQL\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr "" " -P MOT_DE_PASSE mot de passe du compte utilisé pour\n" " l'enregistrement du serveur PostgreSQL\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr "" " -U NOM_UTILISATEUR nom de l'utilisateur du compte utilisé pour\n" " l'enregistrement du serveur PostgreSQL\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr "" " -S TYPE_DÉMARRAGE type de démarrage du service pour enregistrer le\n" " serveur PostgreSQL\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "" "\n" @@ -782,19 +801,19 @@ msgstr "" "\n" "Les types de démarrage sont :\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr "" " auto démarre le service automatiquement lors du démarrage du système\n" " (par défaut)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand démarre le service à la demande\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "" "\n" @@ -803,37 +822,37 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s : mode d'arrêt non reconnu « %s »\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s : signal non reconnu « %s »\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s : type de redémarrage « %s » non reconnu\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s : n'a pas déterminer le répertoire des données en utilisant la commande « %s »\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s : le fichier de contrôle semble corrompu\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "" "%s: cannot be run as root\n" @@ -844,170 +863,34 @@ msgstr "" "Connectez-vous (par exemple en utilisant « su ») sous l'utilisateur (non\n" " privilégié) qui sera propriétaire du processus serveur.\n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s : option -S non supportée sur cette plateforme\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s : arguments manquant pour le mode kill\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s : mode d'opération « %s » non reconnu\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s : aucune opération indiquée\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "" "%s : aucun répertoire de bases de données indiqué et variable\n" "d'environnement PGDATA non initialisée\n" - -#~ msgid "" -#~ "\n" -#~ "%s: -w option cannot use a relative socket directory specification\n" -#~ msgstr "" -#~ "\n" -#~ "%s : l'option -w ne peut pas utiliser un chemin relatif vers le répertoire de\n" -#~ "la socket\n" - -#~ msgid "" -#~ "\n" -#~ "%s: -w option is not supported when starting a pre-9.1 server\n" -#~ msgstr "" -#~ "\n" -#~ "%s : l'option -w n'est pas supportée lors du démarrage d'un serveur pré-9.1\n" - -#~ msgid "" -#~ "\n" -#~ "%s: this data directory appears to be running a pre-existing postmaster\n" -#~ msgstr "" -#~ "\n" -#~ "%s : ce répertoire des données semble être utilisé par un postmaster déjà existant\n" - -#~ msgid "" -#~ "\n" -#~ "Options for stop, restart, or promote:\n" -#~ msgstr "" -#~ "\n" -#~ "Options pour l'arrêt, le redémarrage ou la promotion :\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid " %s start [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n" -#~ msgstr "" -#~ " %s start [-w] [-t SECS] [-D RÉP_DONNÉES] [-s] [-l NOM_FICHIER]\n" -#~ " [-o \"OPTIONS\"]\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid "" -#~ "%s is a utility to start, stop, restart, reload configuration files,\n" -#~ "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n" -#~ "\n" -#~ msgstr "" -#~ "%s est un outil qui permet de démarrer, arrêter, redémarrer, recharger les\n" -#~ "les fichiers de configuration, rapporter le statut d'un serveur PostgreSQL\n" -#~ "ou d'envoyer un signal à un processus PostgreSQL\n" -#~ "\n" - -#~ msgid "%s: could not create log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu créer le fichier de traces « %s » : %s\n" - -#~ msgid "%s: could not open process token: %lu\n" -#~ msgstr "%s : n'a pas pu ouvrir le jeton du processus : %lu\n" - -#~ msgid "%s: could not start server: exit code was %d\n" -#~ msgstr "%s : n'a pas pu démarrer le serveur : le code de sortie est %d\n" - -#~ msgid "%s: could not wait for server because of misconfiguration\n" -#~ msgstr "%s : n'a pas pu attendre le serveur à cause d'une mauvaise configuration\n" - -#~ msgid "" -#~ "(The default is to wait for shutdown, but not for start or restart.)\n" -#~ "\n" -#~ msgstr "" -#~ "(Le comportement par défaut attend l'arrêt, pas le démarrage ou le\n" -#~ "redémarrage.)\n" -#~ "\n" - -#, c-format -#~ msgid "" -#~ "The program \"%s\" is needed by %s but was not found in the\n" -#~ "same directory as \"%s\".\n" -#~ "Check your installation.\n" -#~ msgstr "" -#~ "Le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé\n" -#~ "dans le même répertoire que « %s ».\n" -#~ "Vérifiez votre installation.\n" - -#, c-format -#~ msgid "" -#~ "The program \"%s\" was found by \"%s\"\n" -#~ "but was not the same version as %s.\n" -#~ "Check your installation.\n" -#~ msgstr "" -#~ "Le programme « %s » a été trouvé par « %s »\n" -#~ "mais n'est pas de la même version que %s.\n" -#~ "Vérifiez votre installation.\n" - -#~ msgid "" -#~ "WARNING: online backup mode is active\n" -#~ "Shutdown will not complete until pg_stop_backup() is called.\n" -#~ "\n" -#~ msgstr "" -#~ "ATTENTION : le mode de sauvegarde en ligne est activé.\n" -#~ "L'arrêt ne surviendra qu'au moment où pg_stop_backup() sera appelé.\n" -#~ "\n" - -#~ msgid "child process was terminated by signal %s" -#~ msgstr "le processus fils a été terminé par le signal %s" - -#~ msgid "could not change directory to \"%s\"" -#~ msgstr "n'a pas pu accéder au répertoire « %s »" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %m" - -#~ msgid "could not change directory to \"%s\": %s" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %s" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "n'a pas pu identifier le répertoire courant : %m" - -#~ msgid "could not read symbolic link \"%s\"" -#~ msgstr "n'a pas pu lire le lien symbolique « %s »" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" - -#~ msgid "pclose failed: %m" -#~ msgstr "échec de pclose : %m" - -#~ msgid "server is still starting up\n" -#~ msgstr "le serveur est toujours en cours de démarrage\n" diff --git a/src/bin/pg_ctl/po/ja.po b/src/bin/pg_ctl/po/ja.po index 892da976cada2..77c2d6ba2f16c 100644 --- a/src/bin/pg_ctl/po/ja.po +++ b/src/bin/pg_ctl/po/ja.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_ctl (PostgreSQL 17)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-13 10:06+0900\n" -"PO-Revision-Date: 2024-03-13 10:29+0900\n" +"POT-Creation-Date: 2024-07-19 09:21+0900\n" +"PO-Revision-Date: 2024-07-19 09:52+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -22,6 +22,10 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "バイトオーダが合っていません" + #: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" @@ -113,118 +117,122 @@ msgstr "子プロセスが未知のステータス%dで終了しました" msgid "could not get current working directory: %m\n" msgstr "現在の作業ディレクトリを取得できませんでした: %m\n" -#: pg_ctl.c:254 +#: pg_ctl.c:255 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: ディレクトリ \"%s\" は存在しません\n" -#: pg_ctl.c:257 +#: pg_ctl.c:258 #, c-format msgid "%s: could not access directory \"%s\": %m\n" msgstr "%s: ディレクトリ\"%s\"にアクセスできませんでした: %m\n" -#: pg_ctl.c:270 +#: pg_ctl.c:271 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: ディレクトリ\"%s\"はデータベースクラスタディレクトリではありません\n" -#: pg_ctl.c:283 +#: pg_ctl.c:284 #, c-format msgid "%s: could not open PID file \"%s\": %m\n" msgstr "%s: PIDファイル\"%s\"をオープンできませんでした: %m\n" -#: pg_ctl.c:292 +#: pg_ctl.c:293 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: PIDファイル\"%s\"が空です\n" -#: pg_ctl.c:295 +#: pg_ctl.c:296 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: PIDファイル\"%s\"内に無効なデータがあります\n" -#: pg_ctl.c:457 pg_ctl.c:499 +#: pg_ctl.c:458 pg_ctl.c:500 #, c-format msgid "%s: could not start server: %m\n" msgstr "%s: サーバーを起動できませんでした: %m\n" -#: pg_ctl.c:477 +#: pg_ctl.c:478 #, c-format msgid "%s: could not start server due to setsid() failure: %m\n" msgstr "%s: setsid()に失敗したためサーバーを起動できませんでした: %m\n" -#: pg_ctl.c:547 +#: pg_ctl.c:548 #, c-format msgid "%s: could not open log file \"%s\": %m\n" msgstr "%s: ログファイル \"%s\" をオープンできませんでした: %m\n" -#: pg_ctl.c:564 +#: pg_ctl.c:565 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: サーバーの起動に失敗しました: エラーコード %lu\n" -#: pg_ctl.c:781 +#: pg_ctl.c:789 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "%s: コアファイルのサイズ制限を設定できません:固定の制限により許されていません\n" -#: pg_ctl.c:807 +#: pg_ctl.c:815 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: ファイル\"%s\"を読み取ることに失敗しました\n" -#: pg_ctl.c:812 +#: pg_ctl.c:820 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: オプションファイル\"%s\"は1行のみでなければなりません\n" -#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 +#: pg_ctl.c:862 pg_ctl.c:1050 pg_ctl.c:1117 #, c-format msgid "%s: could not send stop signal (PID: %d): %m\n" msgstr "%s: 停止シグナルを送信できませんでした。(PID: %d): %m\n" -#: pg_ctl.c:882 +#: pg_ctl.c:890 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "%2$sにはプログラム\"%1$s\"が必要ですが、\"%3$s\"と同じディレクトリにありませんでした\n" -#: pg_ctl.c:885 +#: pg_ctl.c:893 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした\n" -#: pg_ctl.c:917 +#: pg_ctl.c:925 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: データベースシステムが初期化に失敗しました\n" -#: pg_ctl.c:932 +#: pg_ctl.c:940 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: 他のサーバーが動作中の可能性がありますが、とにかくpostmasterの起動を試みます。\n" -#: pg_ctl.c:980 +#: pg_ctl.c:988 msgid "waiting for server to start..." msgstr "サーバーの起動完了を待っています..." -#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 +#: pg_ctl.c:993 pg_ctl.c:1003 pg_ctl.c:1073 pg_ctl.c:1135 pg_ctl.c:1247 msgid " done\n" msgstr "完了\n" -#: pg_ctl.c:986 +#: pg_ctl.c:994 msgid "server started\n" msgstr "サーバー起動完了\n" -#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 +#: pg_ctl.c:997 pg_ctl.c:1007 pg_ctl.c:1252 msgid " stopped waiting\n" msgstr " 待機処理が停止されました\n" -#: pg_ctl.c:990 +#: pg_ctl.c:998 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: サーバーは時間内に起動しませんでした\n" -#: pg_ctl.c:996 +#: pg_ctl.c:1004 +msgid "server shut down because of recovery target settings\n" +msgstr "リカバリ目標設定によりシャットダウンしました\n" + +#: pg_ctl.c:1008 #, c-format msgid "" "%s: could not start server\n" @@ -233,42 +241,42 @@ msgstr "" "%s: サーバーを起動できませんでした。\n" "ログ出力を確認してください。\n" -#: pg_ctl.c:1004 +#: pg_ctl.c:1016 msgid "server starting\n" msgstr "サーバーは起動中です。\n" -#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 +#: pg_ctl.c:1035 pg_ctl.c:1093 pg_ctl.c:1156 pg_ctl.c:1195 pg_ctl.c:1276 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: PIDファイル\"%s\"がありません\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 +#: pg_ctl.c:1036 pg_ctl.c:1095 pg_ctl.c:1157 pg_ctl.c:1196 pg_ctl.c:1277 msgid "Is server running?\n" msgstr "サーバーが動作していますか?\n" -#: pg_ctl.c:1030 +#: pg_ctl.c:1042 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: サーバーを停止できません。シングルユーザーサーバー(PID: %d)が動作しています。\n" -#: pg_ctl.c:1044 +#: pg_ctl.c:1056 msgid "server shutting down\n" msgstr "サーバーの停止中です\n" -#: pg_ctl.c:1049 pg_ctl.c:1109 +#: pg_ctl.c:1061 pg_ctl.c:1121 msgid "waiting for server to shut down..." msgstr "サーバー停止処理の完了を待っています..." -#: pg_ctl.c:1053 pg_ctl.c:1114 +#: pg_ctl.c:1065 pg_ctl.c:1126 msgid " failed\n" msgstr "失敗しました\n" -#: pg_ctl.c:1055 pg_ctl.c:1116 +#: pg_ctl.c:1067 pg_ctl.c:1128 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: サーバーは停止していません\n" -#: pg_ctl.c:1057 pg_ctl.c:1118 +#: pg_ctl.c:1069 pg_ctl.c:1130 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -276,252 +284,252 @@ msgstr "" "ヒント: \"-m fast\"オプションは、セッション切断が始まるまで待機するのではなく\n" "即座にセッションを切断します。\n" -#: pg_ctl.c:1063 pg_ctl.c:1124 +#: pg_ctl.c:1075 pg_ctl.c:1136 msgid "server stopped\n" msgstr "サーバーは停止しました\n" -#: pg_ctl.c:1084 +#: pg_ctl.c:1096 msgid "trying to start server anyway\n" msgstr "とにかくサーバーの起動を試みます\n" -#: pg_ctl.c:1093 +#: pg_ctl.c:1105 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "%s: サーバーを再起動できません。シングルユーザーサーバー(PID: %d)が動作中です。\n" -#: pg_ctl.c:1096 pg_ctl.c:1154 +#: pg_ctl.c:1108 pg_ctl.c:1166 msgid "Please terminate the single-user server and try again.\n" msgstr "シングルユーザーサーバーを終了させてから、再度実行してください\n" -#: pg_ctl.c:1128 +#: pg_ctl.c:1140 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: 古いサーバープロセス(PID: %d)が動作していないようです\n" -#: pg_ctl.c:1130 +#: pg_ctl.c:1142 msgid "starting server anyway\n" msgstr "とにかくサーバーを起動しています\n" -#: pg_ctl.c:1151 +#: pg_ctl.c:1163 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "%s: サーバーをリロードできません。シングルユーザーサーバー(PID: %d)が動作中です\n" -#: pg_ctl.c:1160 +#: pg_ctl.c:1172 #, c-format msgid "%s: could not send reload signal (PID: %d): %m\n" msgstr "%s: リロードシグナルを送信できませんでした。(PID: %d): %m\n" -#: pg_ctl.c:1165 +#: pg_ctl.c:1177 msgid "server signaled\n" msgstr "サーバーにシグナルを送信しました\n" -#: pg_ctl.c:1190 +#: pg_ctl.c:1202 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: サーバーを昇格できません; シングルユーザーサーバー(PID: %d)が動作中です\n" -#: pg_ctl.c:1198 +#: pg_ctl.c:1210 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: サーバーを昇格できません; サーバーはスタンバイモードではありません\n" -#: pg_ctl.c:1208 +#: pg_ctl.c:1220 #, c-format msgid "%s: could not create promote signal file \"%s\": %m\n" msgstr "%s: 昇格指示ファイル\"%s\"を作成できませんでした: %m\n" -#: pg_ctl.c:1214 +#: pg_ctl.c:1226 #, c-format msgid "%s: could not write promote signal file \"%s\": %m\n" msgstr "%s: 昇格指示ファイル\"%s\"に書き込めませんでした: %m\n" -#: pg_ctl.c:1222 +#: pg_ctl.c:1234 #, c-format msgid "%s: could not send promote signal (PID: %d): %m\n" msgstr "%s: 昇格シグナルを送信できませんでした (PID: %d): %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1237 #, c-format msgid "%s: could not remove promote signal file \"%s\": %m\n" msgstr "%s: 昇格指示ファイル\"%s\"の削除に失敗しました: %m\n" -#: pg_ctl.c:1232 +#: pg_ctl.c:1244 msgid "waiting for server to promote..." msgstr "サーバーの昇格を待っています..." -#: pg_ctl.c:1236 +#: pg_ctl.c:1248 msgid "server promoted\n" msgstr "サーバーは昇格しました\n" -#: pg_ctl.c:1241 +#: pg_ctl.c:1253 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: サーバーは時間内に昇格しませんでした\n" -#: pg_ctl.c:1247 +#: pg_ctl.c:1259 msgid "server promoting\n" msgstr "サーバーを昇格中です\n" -#: pg_ctl.c:1271 +#: pg_ctl.c:1283 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: ログをローテートできません; シングルユーザーサーバーが動作中です (PID: %d)\n" -#: pg_ctl.c:1281 +#: pg_ctl.c:1293 #, c-format msgid "%s: could not create log rotation signal file \"%s\": %m\n" msgstr "%s: ログローテート指示ファイル\"%s\"を作成できませんでした: %m\n" -#: pg_ctl.c:1287 +#: pg_ctl.c:1299 #, c-format msgid "%s: could not write log rotation signal file \"%s\": %m\n" msgstr "%s: ログローテート指示ファイル\"%s\"に書き込めきませんでした: %m\n" -#: pg_ctl.c:1295 +#: pg_ctl.c:1307 #, c-format msgid "%s: could not send log rotation signal (PID: %d): %m\n" msgstr "%s: ログローテートシグナルを送信できませんでした (PID: %d): %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1310 #, c-format msgid "%s: could not remove log rotation signal file \"%s\": %m\n" msgstr "%s: ログローテート指示ファイル\"%s\"の削除に失敗しました: %m\n" -#: pg_ctl.c:1303 +#: pg_ctl.c:1315 msgid "server signaled to rotate log file\n" msgstr "サーバーがログローテートをシグナルされました\n" -#: pg_ctl.c:1350 +#: pg_ctl.c:1362 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: シングルユーザーサーバーが動作中です(PID: %d)\n" -#: pg_ctl.c:1364 +#: pg_ctl.c:1376 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: サーバーが動作中です(PID: %d)\n" -#: pg_ctl.c:1380 +#: pg_ctl.c:1392 #, c-format msgid "%s: no server running\n" msgstr "%s: サーバーが動作していません\n" -#: pg_ctl.c:1397 +#: pg_ctl.c:1409 #, c-format msgid "%s: could not send signal %d (PID: %d): %m\n" msgstr "%s: シグナル%dを送信できませんでした(PID: %d): %m\n" -#: pg_ctl.c:1428 +#: pg_ctl.c:1440 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: 本プログラムの実行ファイルの検索に失敗しました\n" -#: pg_ctl.c:1438 +#: pg_ctl.c:1450 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: postgres の実行ファイルが見つかりません\n" -#: pg_ctl.c:1508 pg_ctl.c:1542 +#: pg_ctl.c:1520 pg_ctl.c:1554 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: サービスマネージャのオープンに失敗しました\n" -#: pg_ctl.c:1514 +#: pg_ctl.c:1526 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: サービス\\\"%s\\\"は登録済みです\n" -#: pg_ctl.c:1525 +#: pg_ctl.c:1537 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: サービス\"%s\"の登録に失敗しました: エラーコード %lu\n" -#: pg_ctl.c:1548 +#: pg_ctl.c:1560 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: サービス\"%s\"は登録されていません\n" -#: pg_ctl.c:1555 +#: pg_ctl.c:1567 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: サービス\"%s\"のオープンに失敗しました: エラーコード %lu\n" -#: pg_ctl.c:1564 +#: pg_ctl.c:1576 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: サービス\"%s\"の登録削除に失敗しました: エラーコード %lu\n" -#: pg_ctl.c:1651 +#: pg_ctl.c:1663 msgid "Waiting for server startup...\n" msgstr "サーバーの起動完了を待っています...\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1666 msgid "Timed out waiting for server startup\n" msgstr "サーバーの起動待機がタイムアウトしました\n" -#: pg_ctl.c:1658 +#: pg_ctl.c:1670 msgid "Server started and accepting connections\n" msgstr "サーバーは起動し、接続を受け付けています\n" -#: pg_ctl.c:1713 +#: pg_ctl.c:1725 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: サービス\"%s\"の起動に失敗しました: エラーコード %lu\n" -#: pg_ctl.c:1786 +#: pg_ctl.c:1798 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: プロセストークンをオープンできませんでした: エラーコード %lu\n" -#: pg_ctl.c:1800 +#: pg_ctl.c:1812 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: SIDを割り当てられませんでした: エラーコード %lu\n" -#: pg_ctl.c:1826 +#: pg_ctl.c:1838 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: 制限付きトークンを作成できませんでした: エラーコード %lu\n" -#: pg_ctl.c:1908 +#: pg_ctl.c:1920 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: 権限の LUID を取得できません: エラーコード %lu\n" -#: pg_ctl.c:1916 pg_ctl.c:1931 +#: pg_ctl.c:1928 pg_ctl.c:1943 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: トークン情報を取得できませんでした: エラーコード %lu\n" -#: pg_ctl.c:1925 +#: pg_ctl.c:1937 #, c-format msgid "%s: out of memory\n" msgstr "%s: メモリ不足です\n" -#: pg_ctl.c:1955 +#: pg_ctl.c:1967 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "詳細は\"%s --help\"を実行してください。\n" -#: pg_ctl.c:1963 +#: pg_ctl.c:1975 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" "\n" msgstr "%sはPostgreSQLサーバーの初期化、起動、停止、制御を行うユーティリティです。\n" -#: pg_ctl.c:1964 +#: pg_ctl.c:1976 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_ctl.c:1965 +#: pg_ctl.c:1977 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1978 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -530,12 +538,12 @@ msgstr "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-p PATH] [-c]\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1980 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1981 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -544,32 +552,32 @@ msgstr "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1983 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D DATADIR] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1984 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D DATADIR]\n" -#: pg_ctl.c:1973 +#: pg_ctl.c:1985 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1986 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D DATADIR] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1987 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill SIGNALNAME PID\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1989 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -578,12 +586,12 @@ msgstr "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" " [-S START-TYPE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n" -#: pg_ctl.c:1979 +#: pg_ctl.c:1991 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N SERVICENAME]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1994 #, c-format msgid "" "\n" @@ -592,52 +600,52 @@ msgstr "" "\n" "共通のオプション:\n" -#: pg_ctl.c:1983 +#: pg_ctl.c:1995 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=DATADIR データベース格納領域の場所\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1997 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr " -e SOURCE サービスとして起動させたときのログのイベントソース\n" -#: pg_ctl.c:1987 +#: pg_ctl.c:1999 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent エラーメッセージのみを表示、情報メッセージは表示しない\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:2000 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=SECS -wオプションを使用する時に待機する秒数\n" -#: pg_ctl.c:1989 +#: pg_ctl.c:2001 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:2002 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait 操作が完了するまで待機 (デフォルト)\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:2003 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait 作業の完了を待たない\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:2004 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:2005 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "-Dオプションの省略時はPGDATA環境変数が使用されます。\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:2007 #, c-format msgid "" "\n" @@ -646,22 +654,22 @@ msgstr "" "\n" "起動、再起動のオプション\n" -#: pg_ctl.c:1997 +#: pg_ctl.c:2009 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files postgresのコアファイル生成を許可\n" -#: pg_ctl.c:1999 +#: pg_ctl.c:2011 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files このプラットフォームでは適用されない\n" -#: pg_ctl.c:2001 +#: pg_ctl.c:2013 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log FILENAME サーバーログをFILENAMEへ書き込む(または追加する)\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:2014 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -670,12 +678,12 @@ msgstr "" " -o, --options=OPTIONS postgres(PostgreSQLサーバー実行ファイル)または\n" " initdb に渡すコマンドラインオプション\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2016 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p PATH-TO-POSTGRES 通常は不要\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -684,12 +692,12 @@ msgstr "" "\n" "停止、再起動のオプション\n" -#: pg_ctl.c:2006 +#: pg_ctl.c:2018 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=MODE MODEは\"smart\"、\"fast\"、\"immediate\"のいずれか\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2020 #, c-format msgid "" "\n" @@ -698,22 +706,22 @@ msgstr "" "\n" "シャットダウンモードは以下の通り:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2021 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart 全クライアントの接続切断後に停止\n" -#: pg_ctl.c:2010 +#: pg_ctl.c:2022 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast 適切な手続きで直ちに停止(デフォルト)\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2023 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr " immediate 適切な手続き抜きで停止; 再起動時にはリカバリが実行される\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2025 #, c-format msgid "" "\n" @@ -722,7 +730,7 @@ msgstr "" "\n" "killモードで利用できるシグナル名:\n" -#: pg_ctl.c:2017 +#: pg_ctl.c:2029 #, c-format msgid "" "\n" @@ -731,27 +739,27 @@ msgstr "" "\n" "登録、登録解除のオプション:\n" -#: pg_ctl.c:2018 +#: pg_ctl.c:2030 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N SERVICENAME PostgreSQLサーバーを登録する際のサービス名\n" -#: pg_ctl.c:2019 +#: pg_ctl.c:2031 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P PASSWORD PostgreSQLサーバーを登録するためのアカウントのパスワード\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2032 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U USERNAME PostgreSQLサーバーを登録するためのアカウント名\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2033 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S START-TYPE PostgreSQLサーバーを登録する際のサービス起動タイプ\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2035 #, c-format msgid "" "\n" @@ -760,17 +768,17 @@ msgstr "" "\n" "起動タイプは以下の通り:\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2036 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr " auto システムの起動時にサービスを自動的に開始(デフォルト)\n" -#: pg_ctl.c:2025 +#: pg_ctl.c:2037 #, c-format msgid " demand start service on demand\n" msgstr " demand 要求に応じてサービスを開始\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2040 #, c-format msgid "" "\n" @@ -779,37 +787,37 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_ctl.c:2029 +#: pg_ctl.c:2041 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: pg_ctl.c:2054 +#: pg_ctl.c:2066 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: 不正なシャットダウンモード\"%s\"\n" -#: pg_ctl.c:2083 +#: pg_ctl.c:2095 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: 不正なシグナル名\"%s\"\n" -#: pg_ctl.c:2100 +#: pg_ctl.c:2112 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: 不正な起動タイプ\"%s\"\n" -#: pg_ctl.c:2156 +#: pg_ctl.c:2168 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: コマンド\"%s\"を使用するデータディレクトリを決定できませんでした\n" -#: pg_ctl.c:2179 +#: pg_ctl.c:2191 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: 制御ファイルが壊れているようです\n" -#: pg_ctl.c:2247 +#: pg_ctl.c:2259 #, c-format msgid "" "%s: cannot be run as root\n" @@ -820,32 +828,32 @@ msgstr "" "サーバープロセスの所有者となる(非特権)ユーザーとして(\"su\"などを使用して)\n" "ログインしてください。\n" -#: pg_ctl.c:2319 +#: pg_ctl.c:2331 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: -Sオプションはこのプラットフォームでサポートされていません\n" -#: pg_ctl.c:2375 +#: pg_ctl.c:2387 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: killモード用の引数がありません\n" -#: pg_ctl.c:2393 +#: pg_ctl.c:2405 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: 操作モード\"%s\"は不明です\n" -#: pg_ctl.c:2402 +#: pg_ctl.c:2414 #, c-format msgid "%s: too many command-line arguments (first is \"%s\")\n" msgstr "%s: コマンドライン引数が多すぎます(先頭は\"%s\")\n" -#: pg_ctl.c:2409 +#: pg_ctl.c:2421 #, c-format msgid "%s: no operation specified\n" msgstr "%s: 操作モードが指定されていません\n" -#: pg_ctl.c:2430 +#: pg_ctl.c:2442 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: データベースの指定も、PGDATA環境変数の設定もありません\n" diff --git a/src/bin/pg_ctl/po/ka.po b/src/bin/pg_ctl/po/ka.po index fe7004788ae2d..5500c71f6d9b1 100644 --- a/src/bin/pg_ctl/po/ka.po +++ b/src/bin/pg_ctl/po/ka.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_ctl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-13 00:49+0000\n" -"PO-Revision-Date: 2024-03-13 02:04+0100\n" +"POT-Creation-Date: 2025-02-27 09:50+0000\n" +"PO-Revision-Date: 2025-02-27 12:52+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,7 +16,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "ბაიტების მიმდევრობა არ ემთხვევა" #: ../../common/exec.c:174 #, c-format @@ -38,33 +42,33 @@ msgstr "გასაშვებად ფაილის \"%s\" პოვნა msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "ბილიკის (\"%s\") აბსოლუტურ ფორმაში ამოხსნის შეცდომა: %m" -#: ../../common/exec.c:382 +#: ../../common/exec.c:363 #, c-format msgid "could not execute command \"%s\": %m" msgstr "ბრძანების (\"%s\") შესრულების შეცდომა: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "ბრძანებიდან \"%s\" წაკითხვის შეცდომა: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "ბრძანებამ \"%s\" მონაცემები არ დააბრუნა" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s()-ის შეცდომა: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 +#: ../../port/path.c:831 ../../port/path.c:868 ../../port/path.c:885 #, c-format msgid "out of memory\n" msgstr "არასაკმარისი მეხსიერება\n" @@ -104,123 +108,127 @@ msgstr "პროცესი გაჩერდა სიგნალით: %d msgid "child process exited with unrecognized status %d" msgstr "შვილეული პროცესი დასრულდა უცნობი სტატუსით %d" -#: ../../port/path.c:775 +#: ../../port/path.c:853 #, c-format msgid "could not get current working directory: %m\n" msgstr "მიმდინარე სამუშაო საქაღალდის მიღების შეცდომა: %m\n" -#: pg_ctl.c:254 +#: pg_ctl.c:255 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: საქაღალდე %s არ არსებობს\n" -#: pg_ctl.c:257 +#: pg_ctl.c:258 #, c-format msgid "%s: could not access directory \"%s\": %m\n" msgstr "%s საქაღალდესთან %s წვდომის უფლება არ გაქვთ: %m\n" -#: pg_ctl.c:270 +#: pg_ctl.c:271 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: საქაღალდე \"%s\" ბაზის კლასტერის საქაღალდეს არ წარმოადგენს\n" -#: pg_ctl.c:283 +#: pg_ctl.c:284 #, c-format msgid "%s: could not open PID file \"%s\": %m\n" msgstr "%s: PID ფაილის (\"%s\") გახსნის შეცდომა: %m\n" -#: pg_ctl.c:292 +#: pg_ctl.c:293 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: PID ფაილი \"%s\" ცარიელია\n" -#: pg_ctl.c:295 +#: pg_ctl.c:296 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: PID ფაილის (\"%s\") არასწორი შიგთავსი\n" -#: pg_ctl.c:457 pg_ctl.c:499 +#: pg_ctl.c:458 pg_ctl.c:500 #, c-format msgid "%s: could not start server: %m\n" msgstr "%s: სერვერის გაშვების შეცდომა: %m\n" -#: pg_ctl.c:477 +#: pg_ctl.c:478 #, c-format msgid "%s: could not start server due to setsid() failure: %m\n" msgstr "%s: სერვერის გაშვება შეუძლებელია setsid()-ის ჩავარდნის გამო: %m\n" -#: pg_ctl.c:547 +#: pg_ctl.c:548 #, c-format msgid "%s: could not open log file \"%s\": %m\n" msgstr "%s: ჟურნალის ფაილის გახსნის შეცდომა \"%s\": %m\n" -#: pg_ctl.c:564 +#: pg_ctl.c:565 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: სერვერის გაშვება შეუძლებელია: შეცდომის კოდი %lu\n" -#: pg_ctl.c:781 +#: pg_ctl.c:789 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "%s ბირთვის ფაილის ზომის ლიმიტის დაყენება აკრძალულია hardlimit-ის მიერ\n" -#: pg_ctl.c:807 +#: pg_ctl.c:815 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "ფაილის (%s) წაკითხვის შეცდომა: %s\n" -#: pg_ctl.c:812 +#: pg_ctl.c:820 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: პარამეტრების ფაილში \"%s\" ზუსტად ერთი ხაზი უნდა იყოს\n" -#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 +#: pg_ctl.c:862 pg_ctl.c:1050 pg_ctl.c:1117 #, c-format msgid "%s: could not send stop signal (PID: %d): %m\n" msgstr "%s: გაჩერების სიგნალის გაგზავნა შეუძლებელია (PID: %d): %m\n" -#: pg_ctl.c:882 +#: pg_ctl.c:890 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა\n" -#: pg_ctl.c:885 +#: pg_ctl.c:893 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s\n" -#: pg_ctl.c:917 +#: pg_ctl.c:925 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: მონაცემთა ბაზის ინიციალიზაციის შეცდომა\n" -#: pg_ctl.c:932 +#: pg_ctl.c:940 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: შეიძლება გაშვებულია სხვა სერვერი; გაშვებას მაინც ვეცდები\n" -#: pg_ctl.c:980 +#: pg_ctl.c:988 msgid "waiting for server to start..." msgstr "სერვერის გაშვების მოლოდინი..." -#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 +#: pg_ctl.c:993 pg_ctl.c:1003 pg_ctl.c:1073 pg_ctl.c:1135 pg_ctl.c:1247 msgid " done\n" msgstr " დასრულდა\n" -#: pg_ctl.c:986 +#: pg_ctl.c:994 msgid "server started\n" msgstr "სერვერი გაეშვა\n" -#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 +#: pg_ctl.c:997 pg_ctl.c:1007 pg_ctl.c:1252 msgid " stopped waiting\n" msgstr " ლოდინი შეწყვეტილია\n" -#: pg_ctl.c:990 +#: pg_ctl.c:998 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: სერვერი დროზე არ გაეშვა\n" -#: pg_ctl.c:996 +#: pg_ctl.c:1004 +msgid "server shut down because of recovery target settings\n" +msgstr "სერვერი გამოირთო აღდგენის სამიზნის პარამეტრების გამო\n" + +#: pg_ctl.c:1008 #, c-format msgid "" "%s: could not start server\n" @@ -229,42 +237,42 @@ msgstr "" "%s: სერვერის გაშვების შეცდომა\n" "შეამოწმეთ ჟურნალის ფაილი.\n" -#: pg_ctl.c:1004 +#: pg_ctl.c:1016 msgid "server starting\n" msgstr "სერვერი ეშვება\n" -#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 +#: pg_ctl.c:1035 pg_ctl.c:1093 pg_ctl.c:1156 pg_ctl.c:1195 pg_ctl.c:1276 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: PID-ის ფაილი \"%s\" არ არსებობს\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 +#: pg_ctl.c:1036 pg_ctl.c:1095 pg_ctl.c:1157 pg_ctl.c:1196 pg_ctl.c:1277 msgid "Is server running?\n" msgstr "სერვერი გაშვებიულია?\n" -#: pg_ctl.c:1030 +#: pg_ctl.c:1042 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: სერვერის გაჩერების შეცდომა; გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1044 +#: pg_ctl.c:1056 msgid "server shutting down\n" msgstr "მიმდინარეობს სერვერის გამორთვა\n" -#: pg_ctl.c:1049 pg_ctl.c:1109 +#: pg_ctl.c:1061 pg_ctl.c:1121 msgid "waiting for server to shut down..." msgstr "სერვერის გამორთვის მოლოდინი..." -#: pg_ctl.c:1053 pg_ctl.c:1114 +#: pg_ctl.c:1065 pg_ctl.c:1126 msgid " failed\n" msgstr " წარუმატებელი.\n" -#: pg_ctl.c:1055 pg_ctl.c:1116 +#: pg_ctl.c:1067 pg_ctl.c:1128 #, c-format msgid "%s: server does not shut down\n" msgstr "%s სერვერი არ გამორთულა\n" -#: pg_ctl.c:1057 pg_ctl.c:1118 +#: pg_ctl.c:1069 pg_ctl.c:1130 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -272,235 +280,235 @@ msgstr "" "მინიშნება: \"-m fast\" პარამეტრი სესიებს მაშინვე წყვეტს,\n" "სესიის-ინიცირებული გათიშვის მოლოდინის გარეშე.\n" -#: pg_ctl.c:1063 pg_ctl.c:1124 +#: pg_ctl.c:1075 pg_ctl.c:1136 msgid "server stopped\n" msgstr "სერვერი გამოირთო\n" -#: pg_ctl.c:1084 +#: pg_ctl.c:1096 msgid "trying to start server anyway\n" msgstr "სერვერის მაინც გაშვების მცდელობა\n" -#: pg_ctl.c:1093 +#: pg_ctl.c:1105 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "%s: სერვერის რესტარტი შეუძლებელია; გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1096 pg_ctl.c:1154 +#: pg_ctl.c:1108 pg_ctl.c:1166 msgid "Please terminate the single-user server and try again.\n" msgstr "შეაჩერეთ ერთმომხმარებლიანი სერვერი და თავიდან სცადეთ.\n" -#: pg_ctl.c:1128 +#: pg_ctl.c:1140 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: სერვერის ძველი პროცესი (PID: %d) როგორც ჩანს, მოკვდა\n" -#: pg_ctl.c:1130 +#: pg_ctl.c:1142 msgid "starting server anyway\n" msgstr "სერვერის მაინც გაშვება\n" -#: pg_ctl.c:1151 +#: pg_ctl.c:1163 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "%s: სერვერის გადატვირთვის შეცდომა; გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1160 +#: pg_ctl.c:1172 #, c-format msgid "%s: could not send reload signal (PID: %d): %m\n" msgstr "%s: გადატვირთვის სიგნალის გაგზავნის შეცდომა (PID: %d): %m\n" -#: pg_ctl.c:1165 +#: pg_ctl.c:1177 msgid "server signaled\n" msgstr "სერვერს სიგნალი გაეგზავნა\n" -#: pg_ctl.c:1190 +#: pg_ctl.c:1202 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: სერვერის წახალისების შეცდომა; გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1198 +#: pg_ctl.c:1210 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s:სერვერის წახალისება შეუძლებელია; სერვერი უქმე რეჟიმში არაა\n" -#: pg_ctl.c:1208 +#: pg_ctl.c:1220 #, c-format msgid "%s: could not create promote signal file \"%s\": %m\n" msgstr "%s: წახალისების სიგნალის ფაილის (\"%s\") შექმნა შეუძლებელია: %m\n" -#: pg_ctl.c:1214 +#: pg_ctl.c:1226 #, c-format msgid "%s: could not write promote signal file \"%s\": %m\n" msgstr "%s: წახალისების სიგნალის ფაილში (\"%s\") ჩაწერა შეუძლებელია: %m\n" -#: pg_ctl.c:1222 +#: pg_ctl.c:1234 #, c-format msgid "%s: could not send promote signal (PID: %d): %m\n" msgstr "%s: წახალისების სიგნალის გაგზავნა შეუძლებელია(PID: %d): %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1237 #, c-format msgid "%s: could not remove promote signal file \"%s\": %m\n" msgstr "%s: წახალისების სიგნალის ფაილის (\"%s\") წაშლის შეცდომა: %m\n" -#: pg_ctl.c:1232 +#: pg_ctl.c:1244 msgid "waiting for server to promote..." msgstr "სერვერის დაწინაურების მოლოდინი..." -#: pg_ctl.c:1236 +#: pg_ctl.c:1248 msgid "server promoted\n" msgstr "სერვერი დაწინაურდა\n" -#: pg_ctl.c:1241 +#: pg_ctl.c:1253 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s სერვერი დროზე არ დაწინაურდა\n" -#: pg_ctl.c:1247 +#: pg_ctl.c:1259 msgid "server promoting\n" msgstr "სერვერის დაწინაურება\n" -#: pg_ctl.c:1271 +#: pg_ctl.c:1283 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: ჟურნალის ფაილების როტაცია შეუძლებელია; გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1281 +#: pg_ctl.c:1293 #, c-format msgid "%s: could not create log rotation signal file \"%s\": %m\n" msgstr "%s: ჟურნალის როტაციის სიგნალის ფაილის (\"%s\") შექმნა შეუძლებელია: %m\n" -#: pg_ctl.c:1287 +#: pg_ctl.c:1299 #, c-format msgid "%s: could not write log rotation signal file \"%s\": %m\n" msgstr "%s: ჟურნალის როტაციის სიგნალის ფაილში (\"%s\") ჩაწერა შეუძლებელია: %m\n" -#: pg_ctl.c:1295 +#: pg_ctl.c:1307 #, c-format msgid "%s: could not send log rotation signal (PID: %d): %m\n" msgstr "%s: ჟურნალის როტაციის სიგნალის გაგზავნის შეცდომა (PID: %d): %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1310 #, c-format msgid "%s: could not remove log rotation signal file \"%s\": %m\n" msgstr "%s: ჟურნალის როტაციის სიგნალის ფაილის (\"%s\") წაშლის შეცდომა : %m\n" -#: pg_ctl.c:1303 +#: pg_ctl.c:1315 msgid "server signaled to rotate log file\n" msgstr "სერვერმა გვანიშნა რომ ჟურნალის ფაილი დასატრიალებელია\n" -#: pg_ctl.c:1350 +#: pg_ctl.c:1362 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: გაშვებულია ერთმომხმარებლიანი სერვერი (PID: %d)\n" -#: pg_ctl.c:1364 +#: pg_ctl.c:1376 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: სერვერი გაშვებულია (PID: %d)\n" -#: pg_ctl.c:1380 +#: pg_ctl.c:1392 #, c-format msgid "%s: no server running\n" msgstr "%s: სერვერი გაშვებული არა\n" -#: pg_ctl.c:1397 +#: pg_ctl.c:1409 #, c-format msgid "%s: could not send signal %d (PID: %d): %m\n" msgstr "%s: სიგნალის (%d) გაგზავნის შეცდომა (PID: %d): %m\n" -#: pg_ctl.c:1428 +#: pg_ctl.c:1440 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: საკუთარი პროგრამის გამშვები ფაილის პოვნა შეუძლებელია\n" -#: pg_ctl.c:1438 +#: pg_ctl.c:1450 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: გამშვები ფაილი postgres არ არსებობს\n" -#: pg_ctl.c:1508 pg_ctl.c:1542 +#: pg_ctl.c:1520 pg_ctl.c:1554 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: სერვისის მმართველის გახსნის შეცდომა\n" -#: pg_ctl.c:1514 +#: pg_ctl.c:1526 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: სერვისი %s უკვე რეგისტრირებულია\n" -#: pg_ctl.c:1525 +#: pg_ctl.c:1537 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: სერვისის (\"%s\") რეგისტრაციის შეცდომა: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1548 +#: pg_ctl.c:1560 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: სერვისი %s უკვე რეგისტრირებულია\n" -#: pg_ctl.c:1555 +#: pg_ctl.c:1567 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: სერვისის (%s) გახსნა შეუძლებელია: შეცდომის კოდი: %lu\n" -#: pg_ctl.c:1564 +#: pg_ctl.c:1576 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: სერვისის (\"%s\") რეგისტრაციის მოხსნა შეუძლებელია: შეცდომის კოდი: %lu\n" -#: pg_ctl.c:1651 +#: pg_ctl.c:1663 msgid "Waiting for server startup...\n" msgstr "სერვერის გაშვების მოლოდინი...\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1666 msgid "Timed out waiting for server startup\n" msgstr "სერვერის გაშვების მოლოდინის ვადა გავიდა\n" -#: pg_ctl.c:1658 +#: pg_ctl.c:1670 msgid "Server started and accepting connections\n" msgstr "სერვერი გაეშვა და მზადაა შეერთებისთვის\n" -#: pg_ctl.c:1713 +#: pg_ctl.c:1725 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: სერვისის (%s) გაშვება შეუძლებელია: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1786 +#: pg_ctl.c:1798 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: პროცესის კოდის გახსნა შეუძლებელია: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1800 +#: pg_ctl.c:1812 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: შეცდომა SSID-ების გამოყოფისას: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1826 +#: pg_ctl.c:1838 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: შეზღუდული კოდის შექმნა ვერ მოხერხდა: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1908 +#: pg_ctl.c:1920 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: პრივილეგიებისთვის LUID-ების მიღება შეუძლებელია: შეცდომის კოდი: %lu\n" -#: pg_ctl.c:1916 pg_ctl.c:1931 +#: pg_ctl.c:1928 pg_ctl.c:1943 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: შეზღუდული კოდის ინფორმაციის მიღება ვერ მოხერხდა: შეცდომის კოდი %lu\n" -#: pg_ctl.c:1925 +#: pg_ctl.c:1937 #, c-format msgid "%s: out of memory\n" msgstr "%s: არასაკმარისი მეხსიერება\n" -#: pg_ctl.c:1955 +#: pg_ctl.c:1967 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'.\n" -#: pg_ctl.c:1963 +#: pg_ctl.c:1975 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -509,17 +517,17 @@ msgstr "" "%s წარმოადგენს პროგრამას PostgreSQL სერვერის ინიციალიზაციის, გაშვების, გაჩერების და კონტროლისთვის.\n" "\n" -#: pg_ctl.c:1964 +#: pg_ctl.c:1976 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_ctl.c:1965 +#: pg_ctl.c:1977 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D მონაცემებისსაქაღალდე] [-s] [-o პარამეტრები]\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1978 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -528,12 +536,12 @@ msgstr "" " %s start [-D მონაცემებსსაქაღალდე] [-l ფაილისსახელი] [-W] [-t წამი] [-s]\n" " [-o პარამეტრი] [-p ბილიკი] [-c]\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1980 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D მონაცემებსსაქაღალდე] [-m გამორთვის-რეჟიმი] [-W] [-t წამი] [-s]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1981 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -542,32 +550,32 @@ msgstr "" " %s restart [-D მონაცემებსსაქაღალდე] [-m გამორთვის-რეჟიმი] [-W] [-t წამი] [-s]\n" " [-o პარამეტრები] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1983 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D მონაცემებსსაქაღალდე] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1984 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D მონაცემებსსაქაღალდე]\n" -#: pg_ctl.c:1973 +#: pg_ctl.c:1985 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D მონაცემებისსაქაღალდე] [-W] [-t წამი] [-s]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1986 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D მონაცემებისსაქაღალდე] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1987 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill სიგნალისსახელი PID\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1989 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -576,12 +584,12 @@ msgstr "" " %s register [-D მონაცემებსსაქაღალდე] [-N სერვისისსახელი] [-U მომხმარებელი] [-P პაროლი]\n" " [-S გაშვების-ტიპი] [-e წყარო] [-W] [-t წამი] [-s] [-o პარამეტრები]\n" -#: pg_ctl.c:1979 +#: pg_ctl.c:1991 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N სერვისისსახელი]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1994 #, c-format msgid "" "\n" @@ -590,52 +598,52 @@ msgstr "" "\n" "ზოგადი პარამეტრები:\n" -#: pg_ctl.c:1983 +#: pg_ctl.c:1995 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " [-D, --pgdata=]DATADIR ბაზის საცავის მდებარეობა\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1997 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr " -e SOURCE მოვლენების წყარო სერვისად გაშვებულობის დროს ჟურნალის ჩასაწერად\n" -#: pg_ctl.c:1987 +#: pg_ctl.c:1999 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent მხოლოდ შეცდომების გამოტანა. საინფორმაციო შეტყობინებები არ გამოჩნდება\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:2000 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=წამი -w პარამეტრის გამოყენებისას მითითებული ლოდინის დრო\n" -#: pg_ctl.c:1989 +#: pg_ctl.c:2001 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:2002 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait დალოდება ოპერაციის დასრულებამდე(ნაგულისხმები)\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:2003 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait არ დაელოდება ოპერაციის დასასრულს\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:2004 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:2005 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "თუ -D პარამეტრი მითითებული არაა, გამოყენებული იქნება გარემოს ცვლადი PGDATA.\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:2007 #, c-format msgid "" "\n" @@ -644,22 +652,22 @@ msgstr "" "\n" "გაშვების ან თავიდან გაშვების პარამეტრები:\n" -#: pg_ctl.c:1997 +#: pg_ctl.c:2009 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files postgres-ისთვის ბირთვის ფაილების ჩაწერის უფლების მიცემა\n" -#: pg_ctl.c:1999 +#: pg_ctl.c:2011 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files ამ პლატფორმაზე არ მუშაობს\n" -#: pg_ctl.c:2001 +#: pg_ctl.c:2013 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log=ფაილისსახელი სერვერის ჟურნალის ფაილში ჩაწერა (ან არსებული ფაილის ბოლოში მიწერა)\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:2014 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -668,12 +676,12 @@ msgstr "" " -o, --options=OPTIONS postgres-ისთვის (PostgreSQL სერვერი) ან initdb-სთვის გადასაცემი \n" " ბრძანების სტრიქონის პარამეტრები \n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2016 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p ბილიკი-POSTGRES-მდე ჩვეულებრივ საჭირო არაა\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -682,12 +690,12 @@ msgstr "" "\n" "გაჩერებისა და გადატვირთვის პარამეტრები:\n" -#: pg_ctl.c:2006 +#: pg_ctl.c:2018 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=რეჟიმი რეჟიმი შეიძლება იყოს: (ჭკვიანი)\"smart\", (ჩქარი)\"fast\", ან (ახლავე)\"immediate\"\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2020 #, c-format msgid "" "\n" @@ -696,22 +704,22 @@ msgstr "" "\n" "გამორთვის რეჟიმებია:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2021 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart გასვლა, როცა ყველა კლიენტი გაითიშება\n" -#: pg_ctl.c:2010 +#: pg_ctl.c:2022 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast პირდაპირ გასვლა, სწორად გამორთვით (ნაგულისხმები)\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2023 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr " immediate სრული გათიშვის გარეშე გასვლა; დიდი ალბათობით შემდეგ გაშვებაზე მონაცემების აღდგენა მოგიწევთ\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2025 #, c-format msgid "" "\n" @@ -720,7 +728,7 @@ msgstr "" "\n" "მოსაკლავად დაშვებული სიგნალის სახელები:\n" -#: pg_ctl.c:2017 +#: pg_ctl.c:2029 #, c-format msgid "" "\n" @@ -729,27 +737,27 @@ msgstr "" "\n" "რეგისტრაციისა და მისი მოხსნის პარამეტრები:\n" -#: pg_ctl.c:2018 +#: pg_ctl.c:2030 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N სერვისისსახელი სერვისის სახელი, რომელიც PostgreSQL სერვერი დარეგისტრირდება\n" -#: pg_ctl.c:2019 +#: pg_ctl.c:2031 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P პაროლი PostgreSQL სერვერის დასარეგისტრირებელი მომხმარებლის პაროლი\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2032 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U მომხმარებელი PostgreSQL სერვერის დასარეგისტრირებელი მომხმარებლის სახელი\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2033 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S გაშვების ტიპი PostgreSQL სერვერის გაშვების ტიპი\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2035 #, c-format msgid "" "\n" @@ -758,17 +766,17 @@ msgstr "" "\n" "გაშვების ტიპები:\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2036 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr " auto სერვისი ავტომატურად გაეშვება სისტემის ჩატვირთვისას (ნაგულისხმები)\n" -#: pg_ctl.c:2025 +#: pg_ctl.c:2037 #, c-format msgid " demand start service on demand\n" msgstr " demand საჭიროების მიხედვით\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2040 #, c-format msgid "" "\n" @@ -777,37 +785,37 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_ctl.c:2029 +#: pg_ctl.c:2041 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: pg_ctl.c:2054 +#: pg_ctl.c:2066 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: მუშაობის დასრულების უცნობი რეჟიმი: \"%s\"\n" -#: pg_ctl.c:2083 +#: pg_ctl.c:2095 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: სიგნალის უცნობი სახელი: \"%s\"\n" -#: pg_ctl.c:2100 +#: pg_ctl.c:2112 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: გაშვების უცნობი ტიპი \"%s\"\n" -#: pg_ctl.c:2156 +#: pg_ctl.c:2168 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: შეუძლებელია მონაცემების საქაღალდის პოვნა ბრძანებით \"%s\"\n" -#: pg_ctl.c:2179 +#: pg_ctl.c:2191 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: როგორც ჩანს, საკონტროლო ფაილი დაზიანებულია\n" -#: pg_ctl.c:2247 +#: pg_ctl.c:2259 #, c-format msgid "" "%s: cannot be run as root\n" @@ -818,32 +826,32 @@ msgstr "" "გთხოვთ შეხვიდეთ (მაგ. \"su\"-ის გამოყენებით) როგორც (არაპრივილეგირებული)\n" "მომხმარებელი, რომელიც ფლობს სერვერის პროცესს.\n" -#: pg_ctl.c:2319 +#: pg_ctl.c:2331 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: პარამეტრი -S ამ პლატფორმაზე მხარდაუჭერელია\n" -#: pg_ctl.c:2375 +#: pg_ctl.c:2387 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: ნაკლული არგუმენტები მოკვლის რეჟიმისთვის\n" -#: pg_ctl.c:2393 +#: pg_ctl.c:2405 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: ოპერაციის უცნობი რეჟიმი \"%s\"\n" -#: pg_ctl.c:2402 +#: pg_ctl.c:2414 #, c-format msgid "%s: too many command-line arguments (first is \"%s\")\n" msgstr "%s: მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")\n" -#: pg_ctl.c:2409 +#: pg_ctl.c:2421 #, c-format msgid "%s: no operation specified\n" msgstr "%s: ოპერაცია მითითებული არაა\n" -#: pg_ctl.c:2430 +#: pg_ctl.c:2442 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: ბაზის საქაღალდე და გარემოს ცვლადი PGDATA მითითებული არაა\n" diff --git a/src/bin/pg_ctl/po/ko.po b/src/bin/pg_ctl/po/ko.po index 03d2ac8190162..e6f6e8ccb5691 100644 --- a/src/bin/pg_ctl/po/ko.po +++ b/src/bin/pg_ctl/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_ctl (PostgreSQL) 16\n" +"Project-Id-Version: pg_ctl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:49+0000\n" -"PO-Revision-Date: 2023-05-26 13:21+0900\n" +"POT-Creation-Date: 2025-01-17 04:49+0000\n" +"PO-Revision-Date: 2025-01-16 14:12+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -15,38 +15,57 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 정보 불일치" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일임: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "실행할 \"%s\" 파일을 찾을 수 없음" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 경로를 절대경로로 바꿀 수 없음: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령에서 읽을 수 없음: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령이 아무런 데이터도 반환하지 않음" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "메모리 부족" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 #, c-format msgid "out of memory\n" msgstr "메모리 부족\n" @@ -88,82 +107,82 @@ msgstr "하위 프로세스가 종료되었음, 알수 없는 상태 %d" #: ../../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "현재 작업 디렉터리를 알 수 없음: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "현재 작업 디렉터리를 알 수 없음: %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: \"%s\" 디렉터리 없음\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: \"%s\" 디렉터리에 액세스할 수 없음: %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: \"%s\" 디렉터리에 액세스할 수 없음: %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: 지정한 \"%s\" 디렉터리는 데이터베이스 클러스트 디렉터리가 아님\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s: \"%s\" PID 파일을 열 수 없음: %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s: \"%s\" PID 파일을 열 수 없음: %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: \"%s\" PID 파일에 내용이 없습니다\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: \"%s\" PID 파일이 비었음\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s: 서버를 시작 할 수 없음: %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s: 서버를 시작 할 수 없음: %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s: setsid() 실패로 서버를 시작 할 수 없음: %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s: setsid() 실패로 서버를 시작 할 수 없음: %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s: \"%s\" 로그 파일을 열 수 없음: %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s: \"%s\" 로그 파일을 열 수 없음: %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: 서버를 시작할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "" "%s: 코어 파일 크기 한도를 설정할 수 없음, 하드 디스크 용량 초과로 허용되지 않" "음\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: \"%s\" 파일을 읽을 수 없음\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: \"%s\" 환경설정파일은 반드시 한 줄을 가져야한다?\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s: stop 시그널을 보낼 수 없음 (PID: %d): %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s: stop 시그널을 보낼 수 없음 (PID: %d): %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " @@ -172,45 +191,45 @@ msgstr "" "\"%s\" 프로그램이 %s 작업에서 필요합니다. 그런데, 이 파일이\n" "\"%s\" 파일이 있는 디렉터리안에 없습니다.\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "" "\"%s\" 프로그램을 \"%s\" 작업 때문에 찾았지만 이 파일은\n" "%s 프로그램의 버전과 다릅니다.\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: 데이터베이스 초기화 실패\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: 다른 서버가 가동 중인 것 같음; 어째든 서버 가동을 시도함\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "서버를 시작하기 위해 기다리는 중..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " 완료\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "서버 시작됨\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " 중지 기다리는 중\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: 서버가 제 시간에 시작되지 못했음\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "" "%s: could not start server\n" @@ -219,42 +238,42 @@ msgstr "" "%s: 서버를 시작 할 수 없음\n" "로그 출력을 살펴보십시오.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "서버를 시작합니다\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: \"%s\" PID 파일이 없습니다\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "서버가 실행 중입니까?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: 서버 중지 실패; 단일 사용자 서버가 실행 중 (PID: %d)\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "서버를 멈춥니다\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "서버를 멈추기 위해 기다리는 중..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " 실패\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: 서버를 멈추지 못했음\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -262,239 +281,239 @@ msgstr "" "힌트: \"-m fast\" 옵션을 사용하면 접속한 세션들을 즉시 정리합니다.\n" "이 옵션을 사용하지 않으면 접속한 세션들 스스로 끊을 때까지 기다립니다.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "서버 멈추었음\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "어째든 서버를 시작해 봅니다\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "" "%s: 서버를 다시 시작 할 수 없음; 단일사용자 서버가 실행 중임 (PID: %d)\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "단일 사용자 서버를 멈추고 다시 시도하십시오.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: 이전 서버 프로세스(PID: %d)가 없어졌습니다\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "어째든 서버를 시작합니다\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "" "%s: 서버 환경설정을 다시 불러올 수 없음; 단일 사용자 서버가 실행 중임 (PID: " "%d)\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s: reload 시그널을 보낼 수 없음 (PID: %d): %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s: reload 시그널을 보낼 수 없음 (PID: %d): %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "서버가 시스템 시그널을 받았음\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: 운영서버 전환 실패; 단일사용자 서버가 실행 중(PID: %d)\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: 운영서버 전환 실패; 서버가 대기 모드로 상태가 아님\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일을 만들 수 없음: %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일을 만들 수 없음: %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일에 쓰기 실패: %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일에 쓰기 실패: %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s: 운영전환 시그널을 서버(PID: %d)로 보낼 수 없음: %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s: 운영전환 시그널을 서버(PID: %d)로 보낼 수 없음: %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일을 지울 수 없음: %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s: 운영전환 시그널 파일인 \"%s\" 파일을 지울 수 없음: %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "서버를 운영 모드로 전환하는 중 ..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "운영 모드 전환 완료\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: 서버를 제 시간에 운영 모드로 전환하지 못했음\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "서버를 운영 모드로 전환합니다\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "" "%s: 서버 로그 파일을 바꿀 수 없음; 단일 사용자 서버가 실행 중임 (PID: %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" -msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일을 만들 수 없음: %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" +msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일을 만들 수 없음: %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" -msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일에 쓰기 실패: %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" +msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일에 쓰기 실패: %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s: 로그 전환 시그널을 보낼 수 없음 (PID: %d): %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s: 로그 전환 시그널을 보낼 수 없음 (PID: %d): %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" -msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일을 지울 수 없음: %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" +msgstr "%s: 로그 전환 시그널 파일인 \"%s\" 파일을 지울 수 없음: %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "서버가 로그 전환 시그널을 받았음\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: 단일사용자 서버가 실행 중임 (PID: %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: 서버가 실행 중임 (PID: %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s: 가동 중인 서버가 없음\n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s: %d 시그널을 보낼 수 없음 (PID: %d): %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s: %d 시그널을 보낼 수 없음 (PID: %d): %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: 실행 가능한 프로그램을 찾을 수 없습니다\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: 실행 가능한 postgres 프로그램을 찾을 수 없음\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: 서비스 관리자를 열 수 없음\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: \"%s\" 서비스가 이미 등록 되어 있음\n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: \"%s\" 서비스를 등록할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: \"%s\" 서비스가 등록되어 있지 않음\n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: \"%s\" 서비스를 열 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: \"%s\" 서비스를 서비스 목록에서 뺄 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "서버를 시작하기 위해 기다리는 중...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "서버 시작을 기다리는 동안 시간 초과됨\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "서버가 시작되었으며 연결을 허용함\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: \"%s\" 서비스를 시작할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: 프로세스 토큰을 열 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: SID를 할당할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: restricted token을 만들 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: 접근 권한용 LUID를 구할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: 토큰 정보를 구할 수 없음: 오류 코드 %lu\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s: 메모리 부족\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "보다 자세한 사용법은 \"%s --help\"\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -503,17 +522,17 @@ msgstr "" "%s 프로그램은 PostgreSQL 서버를 초기화, 시작, 중지, 제어하는 도구입니다.\n" "\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D 데이터디렉터리] [-s] [-o 옵션]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -522,12 +541,12 @@ msgstr "" " %s start [-D 데이터디렉터리] [-l 파일이름] [-W] [-t 초] [-s]\n" " [-o 옵션] [-p 경로] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D 데이터디렉터리] [-m 중지방법] [-W] [-t 초] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -536,32 +555,32 @@ msgstr "" " %s restart [-D 데이터디렉터리] [-m 중지방법] [-W] [-t 초] [-s]\n" " [-o 옵션] [-c]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D 데이터디렉터리] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D 데이터디렉터리]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D 데이터디렉터리] [-W] [-t 초] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D 데이터디렉터리] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill 시그널이름 PID\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -572,12 +591,12 @@ msgstr "" "호]\n" " [-S 시작형태] [-e SOURCE] [-w] [-t 초] [-o 옵션]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N 서비스이름]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "" "\n" @@ -586,56 +605,56 @@ msgstr "" "\n" "일반 옵션들:\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr "" " -D, --pgdata=데이터디렉터리 데이터베이스 자료가 저장되어있는 디렉터리\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid "" " -e SOURCE event source for logging when running as a service\n" msgstr "" " -e SOURCE 서비스가 실행 중일때 쌓을 로그를 위한 이벤트 소스\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr "" " -s, --silent 일반적인 메시지는 보이지 않고, 오류만 보여줌\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=초 -w 옵션 사용 시 대기 시간(초)\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait 작업이 끝날 때까지 기다림 (기본값)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait 작업이 끝날 때까지 기다리지 않음\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "-D 옵션을 사용하지 않으면, PGDATA 환경변수값을 사용함.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "" "\n" @@ -644,22 +663,22 @@ msgstr "" "\n" "start, restart 때 사용할 수 있는 옵션들:\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files 코어 덤프 파일을 만듬\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files 이 플랫폼에서는 사용할 수 없음\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log=로그파일 서버 로그를 이 로그파일에 기록함\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -668,12 +687,12 @@ msgstr "" " -o, --options=옵션들 PostgreSQL 서버프로그램인 postgres나 initdb\n" " 명령에서 사용할 명령행 옵션들\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p PATH-TO-POSTGRES 보통은 필요치 않음\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "" "\n" @@ -682,14 +701,14 @@ msgstr "" "\n" "stop, restart 때 사용 할 수 있는 옵션들:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid "" " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr "" " -m, --mode=모드 모드는 \"smart\", \"fast\", \"immediate\" 중 하나\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "" "\n" @@ -698,18 +717,18 @@ msgstr "" "\n" "중지방법 설명:\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart 모든 클라이언트의 연결이 끊기게 되면 중지 됨\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr "" " fast 클라이언트의 연결을 강제로 끊고 정상적으로 중지 됨 (기본값)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid "" " immediate quit without complete shutdown; will lead to recovery on " @@ -717,7 +736,7 @@ msgid "" msgstr "" " immediate 그냥 무조건 중지함; 다시 시작할 때 복구 작업을 할 수도 있음\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "" "\n" @@ -726,7 +745,7 @@ msgstr "" "\n" "사용할 수 있는 중지용(for kill) 시그널 이름:\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -735,28 +754,28 @@ msgstr "" "\n" "서비스 등록/제거용 옵션들:\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid "" " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N SERVICENAME 서비스 목록에 등록될 PostgreSQL 서비스 이름\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P PASSWORD 이 서비스를 실행할 사용자의 암호\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U USERNAME 이 서비스를 실행할 사용자 이름\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S 시작형태 서비스로 등록된 PostgreSQL 서버 시작 방법\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "" "\n" @@ -765,18 +784,18 @@ msgstr "" "\n" "시작형태 설명:\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid "" " auto start service automatically during system startup (default)\n" msgstr " auto 시스템이 시작되면 자동으로 서비스가 시작됨 (초기값)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand 수동 시작\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "" "\n" @@ -785,37 +804,37 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: 잘못된 중지 방법 \"%s\"\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: 잘못된 시그널 이름 \"%s\"\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: 알 수 없는 시작형태 \"%s\"\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: \"%s\" 명령에서 사용할 데이터 디렉터리를 알 수 없음\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: 컨트롤 파일이 깨졌음\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "" "%s: cannot be run as root\n" @@ -826,32 +845,32 @@ msgstr "" "시스템관리자 권한이 없는, 서버프로세스의 소유주가 될 일반 사용자로\n" "로그인 해서(\"su\", \"runas\" 같은 명령 이용) 실행하십시오.\n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: -S 옵션은 이 운영체제에서는 지원하지 않음\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s: 너무 많은 명령행 인수들 (시작 \"%s\")\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: kill 작업에 필요한 인수가 빠졌습니다\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: 알 수 없는 작업 모드 \"%s\"\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: 너무 많은 명령행 인수들 (시작 \"%s\")\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s: 수행할 작업을 지정하지 않았습니다\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "" "%s: no database directory specified and environment variable PGDATA unset\n" diff --git a/src/bin/pg_ctl/po/meson.build b/src/bin/pg_ctl/po/meson.build index 03a259a61d617..dedb45b480840 100644 --- a/src/bin/pg_ctl/po/meson.build +++ b/src/bin/pg_ctl/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_ctl-' + pg_version_major.to_string())] diff --git a/src/bin/pg_ctl/po/ru.po b/src/bin/pg_ctl/po/ru.po index a5d7ee2b74815..8f9a0a24aef49 100644 --- a/src/bin/pg_ctl/po/ru.po +++ b/src/bin/pg_ctl/po/ru.po @@ -6,13 +6,13 @@ # Sergey Burladyan , 2009, 2012. # Andrey Sudnik , 2010. # Dmitriy Olshevskiy , 2014. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_ctl (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2023-08-29 10:20+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-07 06:47+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -22,38 +22,57 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "нехватка памяти" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:830 ../../port/path.c:867 ../../port/path.c:884 #, c-format msgid "out of memory\n" msgstr "нехватка памяти\n" @@ -91,133 +110,133 @@ msgstr "дочерний процесс завершён по сигналу %d: #: ../../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" -msgstr "дочерний процесс завершился с нераспознанным состоянием %d" +msgstr "дочерний процесс завершился с нераспознанным кодом состояния %d" -#: ../../port/path.c:775 +#: ../../port/path.c:852 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "не удалось определить текущий рабочий каталог: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "не удалось определить текущий рабочий каталог: %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: каталог \"%s\" не существует\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: ошибка доступа к каталогу \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: ошибка при обращении к каталогу \"%s\": %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: каталог \"%s\" не содержит структуры кластера баз данных\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s: не удалось открыть файл PID \"%s\": %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s: не удалось открыть файл PID \"%s\": %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: файл PID \"%s\" пуст\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: неверные данные в файле PID \"%s\"\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s: не удалось запустить сервер: %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s: не удалось запустить сервер: %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s: не удалось запустить сервер из-за ошибки в setsid(): %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s: не удалось запустить сервер из-за ошибки в setsid(): %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s: не удалось открыть файл протокола \"%s\": %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s: не удалось открыть файл протокола \"%s\": %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: не удалось запустить сервер (код ошибки: %lu)\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "" "%s: не удалось ограничить размер дампа памяти; запрещено жёстким " "ограничением\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: не удалось прочитать файл \"%s\"\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: в файле параметров \"%s\" должна быть ровно одна строка\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s: не удалось отправить сигнал остановки (PID: %d): %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s: не удалось отправить сигнал остановки (PID: %d): %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " "\"%s\"\n" msgstr "программа \"%s\" нужна для %s, но она не найдена в каталоге \"%s\"\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "" "программа \"%s\" найдена программой \"%s\", но её версия отличается от " "версии %s\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: сбой при инициализации системы баз данных\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "" "%s: возможно, уже работает другой сервер; всё же пробуем запустить этот " "сервер\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "ожидание запуска сервера..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " готово\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "сервер запущен\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " прекращение ожидания\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: сервер не запустился за отведённое время\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "" "%s: could not start server\n" @@ -226,43 +245,43 @@ msgstr "" "%s: не удалось запустить сервер\n" "Изучите протокол выполнения.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "сервер запускается\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: файл PID \"%s\" не существует\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "Запущен ли сервер?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "" "%s: остановить сервер с PID %d нельзя - он запущен в монопольном режиме\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "сервер останавливается\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "ожидание завершения работы сервера..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " ошибка\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: сервер не останавливается\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -270,243 +289,243 @@ msgstr "" "ПОДСКАЗКА: Параметр \"-m fast\" может сбросить сеансы принудительно,\n" "не дожидаясь, пока они завершатся сами.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "сервер остановлен\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "производится попытка запуска сервера в любом случае\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "" "%s: перезапустить сервер с PID %d нельзя - он запущен в монопольном режиме\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "Пожалуйста, остановите его и повторите попытку.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: похоже, что старый серверный процесс (PID: %d) исчез\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "сервер запускается, несмотря на это\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "" "%s: перезагрузить сервер с PID %d нельзя - он запущен в монопольном режиме\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s: не удалось отправить сигнал перезагрузки (PID: %d): %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s: не удалось отправить сигнал перезагрузки (PID: %d): %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "сигнал отправлен серверу\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "" "%s: повысить сервер с PID %d нельзя - он выполняется в монопольном режиме\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: повысить сервер нельзя - он работает не в режиме резерва\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s: не удалось создать файл \"%s\" с сигналом к повышению: %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s: не удалось создать файл \"%s\" с сигналом к повышению: %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s: не удалось записать файл \"%s\" с сигналом к повышению: %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s: не удалось записать файл \"%s\" с сигналом к повышению: %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s: не удалось отправить сигнал к повышению (PID: %d): %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s: не удалось отправить сигнал к повышению (PID: %d): %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s: ошибка при удалении файла \"%s\" с сигналом к повышению: %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s: ошибка при удалении файла \"%s\" с сигналом к повышению: %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "ожидание повышения сервера..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "сервер повышен\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: повышение сервера не завершилось за отведённое время\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "сервер повышается\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "" "%s: не удалось прокрутить файл журнала; сервер работает в монопольном режиме " "(PID: %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" msgstr "" -"%s: не удалось создать файл \"%s\" с сигналом к прокрутке журнала: %s\n" +"%s: не удалось создать файл \"%s\" с сигналом к прокрутке журнала: %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" msgstr "" -"%s: не удалось записать файл \"%s\" с сигналом к прокрутке журнала: %s\n" +"%s: не удалось записать файл \"%s\" с сигналом к прокрутке журнала: %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s: не удалось отправить сигнал к прокрутке журнала (PID: %d): %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s: не удалось отправить сигнал к прокрутке журнала (PID: %d): %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" msgstr "" -"%s: ошибка при удалении файла \"%s\" с сигналом к прокрутке журнала: %s\n" +"%s: ошибка при удалении файла \"%s\" с сигналом к прокрутке журнала: %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "сигнал для прокрутки файла журнала отправлен серверу\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: сервер работает в монопольном режиме (PID: %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: сервер работает (PID: %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s: сервер не работает\n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s: не удалось отправить сигнал %d (PID: %d): %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s: не удалось отправить сигнал %d (PID: %d): %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: не удалось найти свой исполняемый файл\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: не удалось найти исполняемый файл postgres\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: не удалось открыть менеджер служб\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: служба \"%s\" уже зарегистрирована\n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: не удалось зарегистрировать службу \"%s\" (код ошибки: %lu)\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: служба \"%s\" не зарегистрирована\n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: не удалось открыть службу \"%s\" (код ошибки: %lu)\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: ошибка при удалении службы \"%s\" (код ошибки: %lu)\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "Ожидание запуска сервера...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "Превышено время ожидания запуска сервера\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "Сервер запущен и принимает подключения\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: не удалось запустить службу \"%s\" (код ошибки: %lu)\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: не удалось открыть маркер процесса (код ошибки: %lu)\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: не удалось подготовить структуры SID (код ошибки: %lu)\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: не удалось создать ограниченный маркер (код ошибки: %lu)\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: не удалось получить LUID для привилегий (код ошибки: %lu)\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: не удалось получить информацию о маркере (код ошибки: %lu)\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s: нехватка памяти\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Для дополнительной информации попробуйте \"%s --help\".\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -516,17 +535,17 @@ msgstr "" "PostgreSQL.\n" "\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D КАТАЛОГ-ДАННЫХ] [-s] [-o ПАРАМЕТРЫ]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -535,13 +554,13 @@ msgstr "" " %s start [-D КАТАЛОГ-ДАННЫХ] [-l ИМЯ-ФАЙЛА] [-W] [-t СЕК] [-s]\n" " [-o ПАРАМЕТРЫ] [-p ПУТЬ] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr "" " %s stop [-D КАТАЛОГ-ДАННЫХ] [-m РЕЖИМ-ОСТАНОВКИ] [-W] [-t СЕК] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -550,32 +569,32 @@ msgstr "" " %s restart [-D КАТАЛОГ-ДАННЫХ] [-m РЕЖИМ-ОСТАНОВКИ] [-W] [-t СЕК] [-s]\n" " [-o ПАРАМЕТРЫ] [-c]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D КАТАЛОГ-ДАННЫХ] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D КАТАЛОГ-ДАННЫХ]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D КАТАЛОГ-ДАННЫХ] [-W] [-t СЕК] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D КАТАЛОГ-ДАННЫХ] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill СИГНАЛ PID\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -587,12 +606,12 @@ msgstr "" " [-S ТИП-ЗАПУСКА] [-e ИСТОЧНИК] [-W] [-t СЕК] [-s] [-o " "ПАРАМЕТРЫ]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N ИМЯ-СЛУЖБЫ]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "" "\n" @@ -601,12 +620,12 @@ msgstr "" "\n" "Общие параметры:\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=КАТАЛОГ расположение хранилища баз данных\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid "" " -e SOURCE event source for logging when running as a service\n" @@ -615,45 +634,45 @@ msgstr "" "журнал,\n" " когда сервер работает в виде службы\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr "" " -s, --silent выводить только ошибки, без информационных " "сообщений\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr "" " -t, --timeout=СЕК время ожидания при использовании параметра -w\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait ждать завершения операции (по умолчанию)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait не ждать завершения операции\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "Если параметр -D опущен, используется переменная окружения PGDATA.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "" "\n" @@ -662,24 +681,24 @@ msgstr "" "\n" "Параметры запуска и перезапуска:\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files указать postgres создавать дампы памяти\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files неприменимо на этой платформе\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr "" " -l, --log=ФАЙЛ записывать (или добавлять) протокол сервера в " "ФАЙЛ.\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -689,12 +708,12 @@ msgstr "" "PostgreSQL)\n" " или initdb параметры командной строки\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p ПУТЬ-К-POSTGRES обычно не требуется\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "" "\n" @@ -703,14 +722,14 @@ msgstr "" "\n" "Параметры остановки и перезапуска:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid "" " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr "" " -m, --mode=РЕЖИМ может быть \"smart\", \"fast\" или \"immediate\"\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "" "\n" @@ -719,17 +738,17 @@ msgstr "" "\n" "Режимы остановки:\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart закончить работу после отключения всех клиентов\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast закончить сразу, в штатном режиме (по умолчанию)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid "" " immediate quit without complete shutdown; will lead to recovery on " @@ -738,7 +757,7 @@ msgstr "" " immediate закончить немедленно, в экстренном режиме; влечёт за собой\n" " восстановление при перезапуске\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "" "\n" @@ -747,7 +766,7 @@ msgstr "" "\n" "Разрешённые сигналы для команды kill:\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -756,30 +775,30 @@ msgstr "" "\n" "Параметры для регистрации и удаления:\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid "" " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N ИМЯ-СЛУЖБЫ имя службы для регистрации сервера PostgreSQL\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr "" " -P ПАРОЛЬ пароль учётной записи для регистрации сервера PostgreSQL\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr "" " -U ПОЛЬЗОВАТЕЛЬ имя пользователя для регистрации сервера PostgreSQL\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S ТИП-ЗАПУСКА тип запуска службы сервера PostgreSQL\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "" "\n" @@ -788,7 +807,7 @@ msgstr "" "\n" "Типы запуска:\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid "" " auto start service automatically during system startup (default)\n" @@ -796,12 +815,12 @@ msgstr "" " auto запускать службу автоматически при старте системы (по " "умолчанию)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand запускать службу по требованию\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "" "\n" @@ -810,37 +829,37 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: неизвестный режим остановки \"%s\"\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: нераспознанное имя сигнала \"%s\"\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: нераспознанный тип запуска \"%s\"\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: не удалось определить каталог данных с помощью команды \"%s\"\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: управляющий файл, по-видимому, испорчен\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "" "%s: cannot be run as root\n" @@ -851,32 +870,32 @@ msgstr "" "Пожалуйста, переключитесь на обычного пользователя (например,\n" "используя \"su\"), который будет запускать серверный процесс.\n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: параметр -S не поддерживается в этой ОС\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s: слишком много аргументов командной строки (первый: \"%s\")\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: отсутствуют аргументы для режима kill\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: нераспознанный режим работы \"%s\"\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: слишком много аргументов командной строки (первый: \"%s\")\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s: команда не указана\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "" "%s: no database directory specified and environment variable PGDATA unset\n" @@ -1009,10 +1028,6 @@ msgstr "" #~ msgid "child process was terminated by signal %s" #~ msgstr "дочерний процесс завершён по сигналу %s" -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "не удалось перейти в каталог \"%s\": %m" - #, c-format #~ msgid "could not identify current directory: %m" #~ msgstr "не удалось определить текущий каталог: %m" diff --git a/src/bin/pg_ctl/po/sv.po b/src/bin/pg_ctl/po/sv.po index 3ab0f950e7026..ff52b8cb20915 100644 --- a/src/bin/pg_ctl/po/sv.po +++ b/src/bin/pg_ctl/po/sv.po @@ -1,5 +1,5 @@ # Swedish message translation file for pg_ctl -# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Magnus Hagander , 2010. # Mats Erik Andersson , 2013, 2014. # @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-01 14:18+0000\n" -"PO-Revision-Date: 2023-08-30 09:01+0200\n" +"POT-Creation-Date: 2024-07-12 14:20+0000\n" +"PO-Revision-Date: 2024-07-12 19:04+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -19,38 +19,57 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "slut på minne" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 #, c-format msgid "out of memory\n" msgstr "slut på minne\n" @@ -92,121 +111,121 @@ msgstr "barnprocess avslutade med okänd statuskod %d" #: ../../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "kunde inte fastställa nuvarande arbetskatalog: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "kunde inte fastställa nuvarande arbetskatalog: %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: katalogen \"%s\" existerar inte\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: kunde inte komma åt katalogen \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: kunde inte komma åt katalogen \"%s\": %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: katalogen \"%s\" innehåller inte något databaskluster.\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s: kunde inte öppna PID-fil \"%s\": %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s: kunde inte öppna PID-fil \"%s\": %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: PID-filen \"%s\" är tom\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: ogiltig data i PID-fil \"%s\"\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s: kunde inte starta servern: %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s: kunde inte starta servern: %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s: kunde inte starta servern då setsid() misslyckades: %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s: kunde inte starta servern då setsid() misslyckades: %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s: kunde inte öppna logg-fil \"%s\": %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s: kunde inte öppna logg-fil \"%s\": %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: kunde inte starta servern: felkod %lu\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "%s: kan inte sätta storleksgränsning på core-fil; tillåts inte av hård gräns\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: kunde inte läsa filen \"%s\"\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: inställningsfilen \"%s\" måste bestå av en enda rad.\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s: kunde inte skicka stopp-signal (PID: %d): %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s: kunde inte skicka stopp-signal (PID: %d): %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "programmet \"%s\" behövs av %s men hittades inte i samma katalog som \"%s\"\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "programmet \"%s\" hittades av \"%s\" men är inte av samma version som %s\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: skapande av databaskluster misslyckades\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: en annan server verkar köra; försöker starta servern ändå.\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "väntar på att servern skall starta..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " klar\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "servern startad\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " avslutade väntan\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: servern startade inte i tid\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "" "%s: could not start server\n" @@ -215,42 +234,42 @@ msgstr "" "%s: kunde inte starta servern\n" "Undersök logg-utskriften.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "servern startar\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: PID-filen \"%s\" finns inte\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "Kör servern?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: Kan inte stanna servern. En-användar-server i drift (PID: %d).\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "servern stänger ner\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "väntar på att servern skall stänga ner..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " misslyckades\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: servern stänger inte ner\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "" "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" @@ -258,235 +277,235 @@ msgstr "" "TIPS: Flaggan \"-m fast\" avslutar sessioner omedelbart, i stället för att\n" "vänta på deras självvalda avslut.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "servern är stoppad\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "försöker starta servern ändå\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "%s: kan inte starta om servern. En-användar-server kör (PID: %d).\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "Var vänlig att stanna en-användar-servern och försök sedan igen.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: gamla serverprocessen (PID: %d) verkar vara borta\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "startar servern ändå\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "%s: kan inte ladda om servern; en-användar-server kör (PID: %d)\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s: kunde inte skicka signalen \"reload\" (PID: %d): %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s: kunde inte skicka signalen \"reload\" (PID: %d): %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "servern är signalerad\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: kan inte befordra servern; en-användar-server kör (PID: %d)\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: kan inte befordra servern; servern är inte i beredskapsläge.\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s: kunde inte skapa befordringssignalfil \"%s\": %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s: kunde inte skapa befordringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s: kunde inte skriva befordringssignalfil \"%s\": %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s: kunde inte skriva befordringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s: kunde inte skicka befordringssignal (PID: %d): %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s: kunde inte skicka befordringssignal (PID: %d): %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s: kunde inte ta bort befordringssignalfil \"%s\": %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s: kunde inte ta bort befordringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "väntar på att servern skall befordras..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "servern befordrad\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: servern befordrades inte i tid\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "servern befordras\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: kan inte rotera loggfil; en-användar-server kör (PID: %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" -msgstr "%s: kunde inte skapa loggroteringssignalfil \"%s\": %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" +msgstr "%s: kunde inte skapa loggroteringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" -msgstr "%s: kunde inte skriva loggroteringssignalfil \"%s\": %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" +msgstr "%s: kunde inte skriva loggroteringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s: kunde inte skicka signalen för loggrotering (PID: %d): %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s: kunde inte skicka signalen för loggrotering (PID: %d): %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" -msgstr "%s: kunde inte ta bort loggroteringssignalfil \"%s\": %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" +msgstr "%s: kunde inte ta bort loggroteringssignalfil \"%s\": %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "servern är signalerad att rotera loggfil\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: en-användar-server kör. (PID: %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: servern kör (PID: %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s: ingen server kör\n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s: kunde inte skicka signal %d (PID: %d): %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s: kunde inte skicka signal %d (PID: %d): %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: kunde inte hitta det egna programmets körbara fil\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: kunde inte hitta körbar postgres.\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: kunde inte öppna tjänstehanteraren\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: tjänsten \"%s\" är redan registrerad\n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: kunde inte registrera tjänsten \"%s\": felkod %lu\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: tjänsten \"%s\" är inte registrerad\n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: kunde inte öppna tjänsten \"%s\": felkod %lu\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: kunde inte avregistrera tjänsten \"%s\": felkod %lu\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "Väntar på serverstart...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "Tidsfristen ute vid väntan på serverstart\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "Server startad och accepterar nu anslutningar\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: kunde inte starta tjänsten \"%s\": felkod %lu\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: kunde inte öppna process-token: felkod %lu\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: kunde inte tilldela SID: felkod %lu\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: kunde inte skapa restriktivt styrmärke (token): felkod %lu\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: kunde inte hämta LUID:er för rättigheter: felkod %lu\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: kunde inte hämta token-information: felkod %lu\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s: slut på minne\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Försök med \"%s --help\" för mer information.\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "" "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n" @@ -496,17 +515,17 @@ msgstr "" "PostgreSQL-tjänsten.\n" "\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D DATAKAT] [-s] [-o FLAGGOR]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid "" " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" @@ -515,12 +534,12 @@ msgstr "" " %s start [-D DATAKAT] [-l FILNAMN] [-W] [-t SEK] [-s]\n" " [-o FLAGGOR] [-p SOKVÄG] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D DATAKAT] [-m STÄNGNINGSMETOD] [-W] [-t SEK] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid "" " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" @@ -529,32 +548,32 @@ msgstr "" " %s restart [-D DATAKAT] [-m STÄNGNINGSMETOD] [-W] [-t SEK] [-s]\n" " [-o FLAGGOR] [-c]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D DATAKAT] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D DATAKAT]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D DATAKAT] [-W] [-t SEK] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D DATAKAT] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill SIGNALNAMN PID\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid "" " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" @@ -563,12 +582,12 @@ msgstr "" " %s register [-D DATAKAT] [-N TJÄNSTENAMN] [-U ANVÄNDARNAMN] [-P LÖSENORD]\n" " [-S STARTTYPE] [-e KÄLLA] [-W] [-t SEK] [-s] [-o FLAGGOR]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N TJÄNSTNAMN]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "" "\n" @@ -577,52 +596,52 @@ msgstr "" "\n" "Gemensamma flaggor:\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=DATAKAT plats för databasens lagringsarea\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr " -e KÄLLA händelsekälla för loggning när vi kör som en tjänst\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent skriv bara ut fel, inga informationsmeddelanden\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=SEK antal sekunder att vänta när växeln -w används\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait vänta på att operationen slutförs (standard)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait vänta inte på att operationen slutförs\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa den här hjälpen, avsluta sedan\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "Om flaggan -D inte har angivits så används omgivningsvariabeln PGDATA.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "" "\n" @@ -631,22 +650,22 @@ msgstr "" "\n" "Flaggor för start eller omstart:\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files tillåt postgres att skapa core-filer\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files inte giltig för denna plattform\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log=FILNAMN skriv, eller tillfoga, server-loggen till FILNAMN\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid "" " -o, --options=OPTIONS command line options to pass to postgres\n" @@ -655,14 +674,14 @@ msgstr "" " -o, --options=OPTIONS kommandoradsflaggor som skickas vidare till postgres\n" " (PostgreSQL-serverns körbara fil) eller till initdb\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr "" " -p SÖKVÄG-TILL-POSTGRES\n" " behövs normalt inte\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "" "\n" @@ -671,12 +690,12 @@ msgstr "" "\n" "Flaggor för stopp eller omstart:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=METOD METOD kan vara \"smart\", \"fast\" eller \"immediate\"\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "" "\n" @@ -685,22 +704,22 @@ msgstr "" "\n" "Stängningsmetoder är:\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart stäng när alla klienter har avslutat\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast stäng omedelbart, med en kontrollerad nedstängning (standard)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr " immediate stäng utan kontroller; kommer leda till återställning vid omstart\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "" "\n" @@ -709,7 +728,7 @@ msgstr "" "\n" "Tillåtna signalnamn för kommando \"kill\":\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "" "\n" @@ -718,27 +737,27 @@ msgstr "" "\n" "Flaggor för registrering och avregistrering:\n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N TJÄNSTENAMN tjänstenamn att registrera PostgreSQL-servern med\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P LÖSENORD lösenord för konto vid registrering av PostgreSQL-servern\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U NAMN användarnamn för konto vid registrering av PostgreSQL-servern\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S STARTSÄTT sätt att registrera PostgreSQL-servern vid tjänstestart\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "" "\n" @@ -747,17 +766,17 @@ msgstr "" "\n" "Startmetoder är:\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr " auto starta tjänsten automatiskt vid systemstart (förval)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand starta tjänsten vid behov\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "" "\n" @@ -766,37 +785,37 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: ogiltig stängningsmetod \"%s\"\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: ogiltigt signalnamn \"%s\"\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: ogiltigt startvillkor \"%s\"\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: kunde inte bestämma databaskatalogen från kommandot \"%s\"\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: kontrollfilen verkar vara trasig\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "" "%s: cannot be run as root\n" @@ -807,52 +826,32 @@ msgstr "" "Logga in (t.ex. med \"su\") som den (opriviligerade) användare\n" "vilken skall äga serverprocessen.\n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: flaggan -S stöds inte på denna plattform.\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s: för många kommandoradsargument (första är \"%s\")\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: saknar argument för \"kill\"-kommando.\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: okänd operationsmetod \"%s\"\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: för många kommandoradsargument (första är \"%s\")\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s: ingen operation angiven\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: ingen databaskatalog angiven och omgivningsvariabeln PGDATA är inte satt\n" - -#, c-format -#~ msgid "%s: WARNING: cannot create restricted tokens on this platform\n" -#~ msgstr "%s: VARNING: \"Restricted Token\" stöds inte av plattformen.\n" - -#, c-format -#~ msgid "%s: WARNING: could not locate all job object functions in system API\n" -#~ msgstr "%s: VARNING: kunde inte hitta alla jobb-funktioner system-API:et.\n" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "kunde inte byta katalog till \"%s\": %m" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "kan inte läsa symbolisk länk \"%s\": %m" diff --git a/src/bin/pg_ctl/po/uk.po b/src/bin/pg_ctl/po/uk.po index c1fcbe971331d..b517535543aac 100644 --- a/src/bin/pg_ctl/po/uk.po +++ b/src/bin/pg_ctl/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-04-19 11:18+0000\n" -"PO-Revision-Date: 2023-12-19 15:37\n" +"POT-Creation-Date: 2024-08-31 06:20+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,41 +14,60 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_ctl.pot\n" -"X-Crowdin-File-ID: 937\n" +"X-Crowdin-File: /REL_17_STABLE/pg_ctl.pot\n" +"X-Crowdin-File-ID: 994\n" -#: ../../common/exec.c:172 +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "недостатньо пам'яті" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 -#: ../../port/path.c:753 ../../port/path.c:791 ../../port/path.c:808 +#: ../../port/path.c:753 ../../port/path.c:790 ../../port/path.c:807 #, c-format msgid "out of memory\n" msgstr "недостатньо пам'яті\n" @@ -90,674 +109,674 @@ msgstr "дочірній процес завершився з невизнани #: ../../port/path.c:775 #, c-format -msgid "could not get current working directory: %s\n" -msgstr "не вдалося отримати поточний робочий каталог: %s\n" +msgid "could not get current working directory: %m\n" +msgstr "не вдалося отримати поточний робочий каталог: %m\n" -#: pg_ctl.c:255 +#: pg_ctl.c:254 #, c-format msgid "%s: directory \"%s\" does not exist\n" msgstr "%s: директорія \"%s\" не існує\n" -#: pg_ctl.c:258 +#: pg_ctl.c:257 #, c-format -msgid "%s: could not access directory \"%s\": %s\n" -msgstr "%s: немає доступу до каталогу \"%s\": %s\n" +msgid "%s: could not access directory \"%s\": %m\n" +msgstr "%s: не вдалося отримати доступ до каталогу \"%s\": %m\n" -#: pg_ctl.c:271 +#: pg_ctl.c:270 #, c-format msgid "%s: directory \"%s\" is not a database cluster directory\n" msgstr "%s: каталог \"%s\" не є каталогом кластера бази даних\n" -#: pg_ctl.c:284 +#: pg_ctl.c:283 #, c-format -msgid "%s: could not open PID file \"%s\": %s\n" -msgstr "%s: не вдалося відкрити файл PID \"%s\": %s\n" +msgid "%s: could not open PID file \"%s\": %m\n" +msgstr "%s: не вдалося відкрити файл PID \"%s\": %m\n" -#: pg_ctl.c:293 +#: pg_ctl.c:292 #, c-format msgid "%s: the PID file \"%s\" is empty\n" msgstr "%s: файл PID \"%s\" пустий\n" -#: pg_ctl.c:296 +#: pg_ctl.c:295 #, c-format msgid "%s: invalid data in PID file \"%s\"\n" msgstr "%s: невірні дані у файлі PID \"%s\"\n" -#: pg_ctl.c:458 pg_ctl.c:500 +#: pg_ctl.c:457 pg_ctl.c:499 #, c-format -msgid "%s: could not start server: %s\n" -msgstr "%s: не вдалося запустити сервер: %s\n" +msgid "%s: could not start server: %m\n" +msgstr "%s: не вдалося запустити сервер: %m\n" -#: pg_ctl.c:478 +#: pg_ctl.c:477 #, c-format -msgid "%s: could not start server due to setsid() failure: %s\n" -msgstr "%s: не вдалося запустити сервер через помилку setsid(): %s\n" +msgid "%s: could not start server due to setsid() failure: %m\n" +msgstr "%s: не вдалося запустити сервер через помилку setsid(): %m\n" -#: pg_ctl.c:548 +#: pg_ctl.c:547 #, c-format -msgid "%s: could not open log file \"%s\": %s\n" -msgstr "%s: не вдалося відкрити файл журналу \"%s\": %s\n" +msgid "%s: could not open log file \"%s\": %m\n" +msgstr "%s: не вдалося відкрити файл журналу \"%s\": %m\n" -#: pg_ctl.c:565 +#: pg_ctl.c:564 #, c-format msgid "%s: could not start server: error code %lu\n" msgstr "%s: не вдалося запустити сервер: код помилки %lu\n" -#: pg_ctl.c:782 +#: pg_ctl.c:781 #, c-format msgid "%s: cannot set core file size limit; disallowed by hard limit\n" msgstr "%s: не вдалося встановити обмеження на розмір файлу; заборонено жорстким лімітом\n" -#: pg_ctl.c:808 +#: pg_ctl.c:807 #, c-format msgid "%s: could not read file \"%s\"\n" msgstr "%s: не вдалося прочитати файл \"%s\"\n" -#: pg_ctl.c:813 +#: pg_ctl.c:812 #, c-format msgid "%s: option file \"%s\" must have exactly one line\n" msgstr "%s: файл параметрів \"%s\" повинен містити рівно один рядок\n" -#: pg_ctl.c:855 pg_ctl.c:1039 pg_ctl.c:1107 +#: pg_ctl.c:854 pg_ctl.c:1038 pg_ctl.c:1105 #, c-format -msgid "%s: could not send stop signal (PID: %d): %s\n" -msgstr "%s: не вдалося надіслати стоп-сигнал (PID: %d): %s\n" +msgid "%s: could not send stop signal (PID: %d): %m\n" +msgstr "%s: не вдалося надіслати стоп-сигнал (PID: %d): %m\n" -#: pg_ctl.c:883 +#: pg_ctl.c:882 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"\n" msgstr "програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\"\n" -#: pg_ctl.c:886 +#: pg_ctl.c:885 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s\n" msgstr "програма \"%s\" знайдена для \"%s\", але має відмінну версію від %s\n" -#: pg_ctl.c:918 +#: pg_ctl.c:917 #, c-format msgid "%s: database system initialization failed\n" msgstr "%s: не вдалося виконати ініціалізацію системи бази даних\n" -#: pg_ctl.c:933 +#: pg_ctl.c:932 #, c-format msgid "%s: another server might be running; trying to start server anyway\n" msgstr "%s: мабуть, інший сервер вже працює; у будь-якому разі спробуємо запустити сервер\n" -#: pg_ctl.c:981 +#: pg_ctl.c:980 msgid "waiting for server to start..." msgstr "очікується запуск серверу..." -#: pg_ctl.c:986 pg_ctl.c:1063 pg_ctl.c:1126 pg_ctl.c:1238 +#: pg_ctl.c:985 pg_ctl.c:1061 pg_ctl.c:1123 pg_ctl.c:1235 msgid " done\n" msgstr " готово\n" -#: pg_ctl.c:987 +#: pg_ctl.c:986 msgid "server started\n" msgstr "сервер запущено\n" -#: pg_ctl.c:990 pg_ctl.c:996 pg_ctl.c:1243 +#: pg_ctl.c:989 pg_ctl.c:995 pg_ctl.c:1240 msgid " stopped waiting\n" msgstr " очікування припинено\n" -#: pg_ctl.c:991 +#: pg_ctl.c:990 #, c-format msgid "%s: server did not start in time\n" msgstr "%s: сервер не було запущено вчасно\n" -#: pg_ctl.c:997 +#: pg_ctl.c:996 #, c-format msgid "%s: could not start server\n" "Examine the log output.\n" msgstr "%s: неможливо запустити сервер\n" "Передивіться протокол виконання.\n" -#: pg_ctl.c:1005 +#: pg_ctl.c:1004 msgid "server starting\n" msgstr "запуск серверу\n" -#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1147 pg_ctl.c:1186 pg_ctl.c:1267 +#: pg_ctl.c:1023 pg_ctl.c:1081 pg_ctl.c:1144 pg_ctl.c:1183 pg_ctl.c:1264 #, c-format msgid "%s: PID file \"%s\" does not exist\n" msgstr "%s: файл PID \"%s\" не існує\n" -#: pg_ctl.c:1025 pg_ctl.c:1085 pg_ctl.c:1148 pg_ctl.c:1187 pg_ctl.c:1268 +#: pg_ctl.c:1024 pg_ctl.c:1083 pg_ctl.c:1145 pg_ctl.c:1184 pg_ctl.c:1265 msgid "Is server running?\n" msgstr "Сервер працює?\n" -#: pg_ctl.c:1031 +#: pg_ctl.c:1030 #, c-format msgid "%s: cannot stop server; single-user server is running (PID: %d)\n" msgstr "%s: не можливо зупинити сервер; сервер запущений в режимі single-user (PID: %d)\n" -#: pg_ctl.c:1046 +#: pg_ctl.c:1044 msgid "server shutting down\n" msgstr "сервер зупиняється\n" -#: pg_ctl.c:1051 pg_ctl.c:1112 +#: pg_ctl.c:1049 pg_ctl.c:1109 msgid "waiting for server to shut down..." msgstr "очікується зупинка серверу..." -#: pg_ctl.c:1055 pg_ctl.c:1117 +#: pg_ctl.c:1053 pg_ctl.c:1114 msgid " failed\n" msgstr " помилка\n" -#: pg_ctl.c:1057 pg_ctl.c:1119 +#: pg_ctl.c:1055 pg_ctl.c:1116 #, c-format msgid "%s: server does not shut down\n" msgstr "%s: сервер не зупинено\n" -#: pg_ctl.c:1059 pg_ctl.c:1121 +#: pg_ctl.c:1057 pg_ctl.c:1118 msgid "HINT: The \"-m fast\" option immediately disconnects sessions rather than\n" "waiting for session-initiated disconnection.\n" msgstr "ПІДКАЗКА: Режим \"-m fast\" закриває сесії відразу, не чекаючи на відключення ініційовані сесіями.\n" -#: pg_ctl.c:1065 pg_ctl.c:1127 +#: pg_ctl.c:1063 pg_ctl.c:1124 msgid "server stopped\n" msgstr "сервер зупинено\n" -#: pg_ctl.c:1086 +#: pg_ctl.c:1084 msgid "trying to start server anyway\n" msgstr "спроба запуску серверу в будь-якому разі\n" -#: pg_ctl.c:1095 +#: pg_ctl.c:1093 #, c-format msgid "%s: cannot restart server; single-user server is running (PID: %d)\n" msgstr "%s: не можливо перезапустити сервер; сервер запущений в режимі single-user (PID: %d)\n" -#: pg_ctl.c:1098 pg_ctl.c:1157 +#: pg_ctl.c:1096 pg_ctl.c:1154 msgid "Please terminate the single-user server and try again.\n" msgstr "Будь ласка, припиніть однокористувацький сервер та спробуйте ще раз.\n" -#: pg_ctl.c:1131 +#: pg_ctl.c:1128 #, c-format msgid "%s: old server process (PID: %d) seems to be gone\n" msgstr "%s: старий серверний процес (PID: %d), здається, зник\n" -#: pg_ctl.c:1133 +#: pg_ctl.c:1130 msgid "starting server anyway\n" msgstr "запуск серверу в будь-якому разі\n" -#: pg_ctl.c:1154 +#: pg_ctl.c:1151 #, c-format msgid "%s: cannot reload server; single-user server is running (PID: %d)\n" msgstr "%s: не можливо перезапустити сервер; сервер запущений в режимі single-user (PID: %d)\n" -#: pg_ctl.c:1163 +#: pg_ctl.c:1160 #, c-format -msgid "%s: could not send reload signal (PID: %d): %s\n" -msgstr "%s: не можливо надіслати сигнал перезавантаження (PID: %d): %s\n" +msgid "%s: could not send reload signal (PID: %d): %m\n" +msgstr "%s: не можливо надіслати сигнал перезавантаження (PID: %d): %m\n" -#: pg_ctl.c:1168 +#: pg_ctl.c:1165 msgid "server signaled\n" msgstr "серверу надіслано сигнал\n" -#: pg_ctl.c:1193 +#: pg_ctl.c:1190 #, c-format msgid "%s: cannot promote server; single-user server is running (PID: %d)\n" msgstr "%s: неможливо підвищити сервер; сервер запущено в режимі single-user (PID: %d)\n" -#: pg_ctl.c:1201 +#: pg_ctl.c:1198 #, c-format msgid "%s: cannot promote server; server is not in standby mode\n" msgstr "%s: неможливо підвищити сервер; сервер запущено не в режимі резерву\n" -#: pg_ctl.c:1211 +#: pg_ctl.c:1208 #, c-format -msgid "%s: could not create promote signal file \"%s\": %s\n" -msgstr "%s: неможливо створити файл \"%s\" із сигналом для підвищення: %s\n" +msgid "%s: could not create promote signal file \"%s\": %m\n" +msgstr "%s: неможливо створити файл \"%s\" із сигналом для підвищення: %m\n" -#: pg_ctl.c:1217 +#: pg_ctl.c:1214 #, c-format -msgid "%s: could not write promote signal file \"%s\": %s\n" -msgstr "%s: неможливо записати файл \"%s\" із сигналом для підвищення: %s\n" +msgid "%s: could not write promote signal file \"%s\": %m\n" +msgstr "%s: неможливо записати файл \"%s\" із сигналом для підвищення: %m\n" -#: pg_ctl.c:1225 +#: pg_ctl.c:1222 #, c-format -msgid "%s: could not send promote signal (PID: %d): %s\n" -msgstr "%s: неможливо надіслати сигнал підвищення (PID: %d): %s\n" +msgid "%s: could not send promote signal (PID: %d): %m\n" +msgstr "%s: неможливо надіслати сигнал підвищення (PID: %d): %m\n" -#: pg_ctl.c:1228 +#: pg_ctl.c:1225 #, c-format -msgid "%s: could not remove promote signal file \"%s\": %s\n" -msgstr "%s: неможливо видалити файл \"%s\" із сигналом для підвищення: %s\n" +msgid "%s: could not remove promote signal file \"%s\": %m\n" +msgstr "%s: неможливо видалити файл \"%s\" із сигналом для підвищення: %m\n" -#: pg_ctl.c:1235 +#: pg_ctl.c:1232 msgid "waiting for server to promote..." msgstr "очікується підвищення серверу..." -#: pg_ctl.c:1239 +#: pg_ctl.c:1236 msgid "server promoted\n" msgstr "сервер підвищено\n" -#: pg_ctl.c:1244 +#: pg_ctl.c:1241 #, c-format msgid "%s: server did not promote in time\n" msgstr "%s: сервер не було підвищено вчасно\n" -#: pg_ctl.c:1250 +#: pg_ctl.c:1247 msgid "server promoting\n" msgstr "сервер підвищується\n" -#: pg_ctl.c:1274 +#: pg_ctl.c:1271 #, c-format msgid "%s: cannot rotate log file; single-user server is running (PID: %d)\n" msgstr "%s: не можливо розвернути файл журналу; сервер працює в режимі одного користувача (PID: %d)\n" -#: pg_ctl.c:1284 +#: pg_ctl.c:1281 #, c-format -msgid "%s: could not create log rotation signal file \"%s\": %s\n" -msgstr "%s: не вдалося створити файл сигналу розвороту журналу \"%s\": %s\n" +msgid "%s: could not create log rotation signal file \"%s\": %m\n" +msgstr "%s: не вдалося створити файл сигналу розвороту журналу \"%s\": %m\n" -#: pg_ctl.c:1290 +#: pg_ctl.c:1287 #, c-format -msgid "%s: could not write log rotation signal file \"%s\": %s\n" -msgstr "%s: не вдалося записати у файл сигналу розвороту журналу \"%s\": %s\n" +msgid "%s: could not write log rotation signal file \"%s\": %m\n" +msgstr "%s: не вдалося записати у файл сигналу розвороту журналу \"%s\": %m\n" -#: pg_ctl.c:1298 +#: pg_ctl.c:1295 #, c-format -msgid "%s: could not send log rotation signal (PID: %d): %s\n" -msgstr "%s: не вдалося надіслати сигнал розвороту журналу (PID: %d): %s\n" +msgid "%s: could not send log rotation signal (PID: %d): %m\n" +msgstr "%s: не вдалося надіслати сигнал розвороту журналу (PID: %d): %m\n" -#: pg_ctl.c:1301 +#: pg_ctl.c:1298 #, c-format -msgid "%s: could not remove log rotation signal file \"%s\": %s\n" -msgstr "%s: не вдалося видалити файл сигналу розвороту журналу \"%s\": %s\n" +msgid "%s: could not remove log rotation signal file \"%s\": %m\n" +msgstr "%s: не вдалося видалити файл сигналу розвороту журналу \"%s\": %m\n" -#: pg_ctl.c:1306 +#: pg_ctl.c:1303 msgid "server signaled to rotate log file\n" msgstr "серверу надіслано сигнал для розворот файлу журналу\n" -#: pg_ctl.c:1353 +#: pg_ctl.c:1350 #, c-format msgid "%s: single-user server is running (PID: %d)\n" msgstr "%s: однокористувацький сервер працює (PID: %d)\n" -#: pg_ctl.c:1367 +#: pg_ctl.c:1364 #, c-format msgid "%s: server is running (PID: %d)\n" msgstr "%s: сервер працює (PID: %d)\n" -#: pg_ctl.c:1383 +#: pg_ctl.c:1380 #, c-format msgid "%s: no server running\n" msgstr "%s: сервер не працює \n" -#: pg_ctl.c:1400 +#: pg_ctl.c:1397 #, c-format -msgid "%s: could not send signal %d (PID: %d): %s\n" -msgstr "%s: не вдалося надіслати сигнал %d (PID: %d): %s\n" +msgid "%s: could not send signal %d (PID: %d): %m\n" +msgstr "%s: не вдалося надіслати сигнал %d (PID: %d): %m\n" -#: pg_ctl.c:1431 +#: pg_ctl.c:1428 #, c-format msgid "%s: could not find own program executable\n" msgstr "%s: не вдалося знайти ехе файл власної програми\n" -#: pg_ctl.c:1441 +#: pg_ctl.c:1438 #, c-format msgid "%s: could not find postgres program executable\n" msgstr "%s: не вдалося знайти виконану програму postgres\n" -#: pg_ctl.c:1511 pg_ctl.c:1545 +#: pg_ctl.c:1508 pg_ctl.c:1542 #, c-format msgid "%s: could not open service manager\n" msgstr "%s: не вдалося відкрити менеджер служб\n" -#: pg_ctl.c:1517 +#: pg_ctl.c:1514 #, c-format msgid "%s: service \"%s\" already registered\n" msgstr "%s: служба \"%s\" вже зареєстрована \n" -#: pg_ctl.c:1528 +#: pg_ctl.c:1525 #, c-format msgid "%s: could not register service \"%s\": error code %lu\n" msgstr "%s: не вдалося зареєструвати службу \"%s\": код помилки %lu\n" -#: pg_ctl.c:1551 +#: pg_ctl.c:1548 #, c-format msgid "%s: service \"%s\" not registered\n" msgstr "%s: служба \"%s\" не зареєстрована \n" -#: pg_ctl.c:1558 +#: pg_ctl.c:1555 #, c-format msgid "%s: could not open service \"%s\": error code %lu\n" msgstr "%s: не вдалося відкрити службу \"%s\": код помилки %lu\n" -#: pg_ctl.c:1567 +#: pg_ctl.c:1564 #, c-format msgid "%s: could not unregister service \"%s\": error code %lu\n" msgstr "%s: не вдалося видалити службу \"%s\": код помилки %lu\n" -#: pg_ctl.c:1654 +#: pg_ctl.c:1651 msgid "Waiting for server startup...\n" msgstr "Очікування запуску сервера...\n" -#: pg_ctl.c:1657 +#: pg_ctl.c:1654 msgid "Timed out waiting for server startup\n" msgstr "Перевищено час очікування запуску сервера\n" -#: pg_ctl.c:1661 +#: pg_ctl.c:1658 msgid "Server started and accepting connections\n" msgstr "Сервер запущений і приймає з'єднання\n" -#: pg_ctl.c:1716 +#: pg_ctl.c:1713 #, c-format msgid "%s: could not start service \"%s\": error code %lu\n" msgstr "%s: не вдалося почати службу \"%s\": код помилки %lu\n" -#: pg_ctl.c:1789 +#: pg_ctl.c:1786 #, c-format msgid "%s: could not open process token: error code %lu\n" msgstr "%s: не вдалося відкрити токен процесу: код помилки %lu\n" -#: pg_ctl.c:1803 +#: pg_ctl.c:1800 #, c-format msgid "%s: could not allocate SIDs: error code %lu\n" msgstr "%s: не вдалося виділити SID: код помилки %lu\n" -#: pg_ctl.c:1829 +#: pg_ctl.c:1826 #, c-format msgid "%s: could not create restricted token: error code %lu\n" msgstr "%s: не вдалося створити обмежений токен: код помилки %lu\n" -#: pg_ctl.c:1911 +#: pg_ctl.c:1908 #, c-format msgid "%s: could not get LUIDs for privileges: error code %lu\n" msgstr "%s: не вдалося отримати LUIDs для прав: код помилки %lu\n" -#: pg_ctl.c:1919 pg_ctl.c:1934 +#: pg_ctl.c:1916 pg_ctl.c:1931 #, c-format msgid "%s: could not get token information: error code %lu\n" msgstr "%s: не вдалося отримати інформацію токену: код помилки %lu\n" -#: pg_ctl.c:1928 +#: pg_ctl.c:1925 #, c-format msgid "%s: out of memory\n" msgstr "%s: бракує пам'яті\n" -#: pg_ctl.c:1958 +#: pg_ctl.c:1955 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Спробуйте \"%s --help\" для додаткової інформації.\n" -#: pg_ctl.c:1966 +#: pg_ctl.c:1963 #, c-format msgid "%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n\n" msgstr "%s - це утиліта для ініціалізації, запуску, зупинки і контролю серверу PostgreSQL.\n\n" -#: pg_ctl.c:1967 +#: pg_ctl.c:1964 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_ctl.c:1968 +#: pg_ctl.c:1965 #, c-format msgid " %s init[db] [-D DATADIR] [-s] [-o OPTIONS]\n" msgstr " %s init[db] [-D КАТАЛОГ-ДАНИХ] [-s] [-o ПАРАМЕТРИ]\n" -#: pg_ctl.c:1969 +#: pg_ctl.c:1966 #, c-format msgid " %s start [-D DATADIR] [-l FILENAME] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-p PATH] [-c]\n" msgstr " %s start [-D КАТАЛОГ-ДАНИХ] [-l ІМ'Я-ФАЙЛ] [-W] [-t СЕК] [-s]\n" " [-o ПАРАМЕТРИ] [-p ШЛЯХ] [-c]\n" -#: pg_ctl.c:1971 +#: pg_ctl.c:1968 #, c-format msgid " %s stop [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" msgstr " %s stop [-D КАТАЛОГ-ДАНИХ] [-m РЕЖИМ-ЗУПИНКИ] [-W] [-t СЕК] [-s]\n" -#: pg_ctl.c:1972 +#: pg_ctl.c:1969 #, c-format msgid " %s restart [-D DATADIR] [-m SHUTDOWN-MODE] [-W] [-t SECS] [-s]\n" " [-o OPTIONS] [-c]\n" msgstr " %s restart [-D КАТАЛОГ-ДАНИХ] [-m РЕЖИМ-ЗУПИНКИ] [-W] [-t СЕК] [-s]\n" " [-o ПАРАМЕТРИ] [-c]\n" -#: pg_ctl.c:1974 +#: pg_ctl.c:1971 #, c-format msgid " %s reload [-D DATADIR] [-s]\n" msgstr " %s reload [-D КАТАЛОГ-ДАНИХ] [-s]\n" -#: pg_ctl.c:1975 +#: pg_ctl.c:1972 #, c-format msgid " %s status [-D DATADIR]\n" msgstr " %s status [-D DATADIR]\n" -#: pg_ctl.c:1976 +#: pg_ctl.c:1973 #, c-format msgid " %s promote [-D DATADIR] [-W] [-t SECS] [-s]\n" msgstr " %s promote [-D КАТАЛОГ-ДАНИХ] [-W] [-t СЕК] [-s]\n" -#: pg_ctl.c:1977 +#: pg_ctl.c:1974 #, c-format msgid " %s logrotate [-D DATADIR] [-s]\n" msgstr " %s logrotate [-D DATADIR] [-s]\n" -#: pg_ctl.c:1978 +#: pg_ctl.c:1975 #, c-format msgid " %s kill SIGNALNAME PID\n" msgstr " %s kill ІМ'Я-СИГНАЛУ PID\n" -#: pg_ctl.c:1980 +#: pg_ctl.c:1977 #, c-format msgid " %s register [-D DATADIR] [-N SERVICENAME] [-U USERNAME] [-P PASSWORD]\n" " [-S START-TYPE] [-e SOURCE] [-W] [-t SECS] [-s] [-o OPTIONS]\n" msgstr " %s register [-D КАТАЛОГ-ДАНИХ] [-N ІМ'Я-СЛУЖБИ] [-U ІМ'Я-КОРИСТУВАЧА] [-P ПАРОЛЬ]\n" " [-S ТИП-ЗАПУСКУ] [-e ДЖЕРЕЛО] [-W] [-t СЕК] [-s] [-o ПАРАМЕТРИ]\n" -#: pg_ctl.c:1982 +#: pg_ctl.c:1979 #, c-format msgid " %s unregister [-N SERVICENAME]\n" msgstr " %s unregister [-N ІМ'Я-СЛУЖБИ]\n" -#: pg_ctl.c:1985 +#: pg_ctl.c:1982 #, c-format msgid "\n" "Common options:\n" msgstr "\n" "Загальні параметри:\n" -#: pg_ctl.c:1986 +#: pg_ctl.c:1983 #, c-format msgid " -D, --pgdata=DATADIR location of the database storage area\n" msgstr " -D, --pgdata=КАТАЛОГ-ДАНИХ розташування простору зберігання бази даних\n" -#: pg_ctl.c:1988 +#: pg_ctl.c:1985 #, c-format msgid " -e SOURCE event source for logging when running as a service\n" msgstr " -e ДЖЕРЕЛО джерело подій для протоколу при запуску в якості послуги\n" -#: pg_ctl.c:1990 +#: pg_ctl.c:1987 #, c-format msgid " -s, --silent only print errors, no informational messages\n" msgstr " -s, --silent виводити лише помилки, без інформаційних повідомлень\n" -#: pg_ctl.c:1991 +#: pg_ctl.c:1988 #, c-format msgid " -t, --timeout=SECS seconds to wait when using -w option\n" msgstr " -t, --timeout=СЕК час очікування при використанні -w параметра\n" -#: pg_ctl.c:1992 +#: pg_ctl.c:1989 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: pg_ctl.c:1993 +#: pg_ctl.c:1990 #, c-format msgid " -w, --wait wait until operation completes (default)\n" msgstr " -w, --wait чекати завершення операції (за замовчуванням)\n" -#: pg_ctl.c:1994 +#: pg_ctl.c:1991 #, c-format msgid " -W, --no-wait do not wait until operation completes\n" msgstr " -W, --no-wait не чекати завершення операції\n" -#: pg_ctl.c:1995 +#: pg_ctl.c:1992 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку потім вийти\n" -#: pg_ctl.c:1996 +#: pg_ctl.c:1993 #, c-format msgid "If the -D option is omitted, the environment variable PGDATA is used.\n" msgstr "Якщо -D параметр пропущено, використовувати змінну середовища PGDATA.\n" -#: pg_ctl.c:1998 +#: pg_ctl.c:1995 #, c-format msgid "\n" "Options for start or restart:\n" msgstr "\n" "Параметри запуску або перезапуску:\n" -#: pg_ctl.c:2000 +#: pg_ctl.c:1997 #, c-format msgid " -c, --core-files allow postgres to produce core files\n" msgstr " -c, --core-files дозволяти postgres створювати дампи пам'яті\n" -#: pg_ctl.c:2002 +#: pg_ctl.c:1999 #, c-format msgid " -c, --core-files not applicable on this platform\n" msgstr " -c, --core-files недопустимо цією платформою\n" -#: pg_ctl.c:2004 +#: pg_ctl.c:2001 #, c-format msgid " -l, --log=FILENAME write (or append) server log to FILENAME\n" msgstr " -l, --log=ФАЙЛ записувати (або додавати) протокол служби до ФАЙЛ\n" -#: pg_ctl.c:2005 +#: pg_ctl.c:2002 #, c-format msgid " -o, --options=OPTIONS command line options to pass to postgres\n" " (PostgreSQL server executable) or initdb\n" msgstr " -o, --options=ПАРАМЕТРИ параметри командного рядку для PostgreSQL або initdb\n" -#: pg_ctl.c:2007 +#: pg_ctl.c:2004 #, c-format msgid " -p PATH-TO-POSTGRES normally not necessary\n" msgstr " -p ШЛЯХ-ДО-СЕРВЕРУ зазвичай зайвий\n" -#: pg_ctl.c:2008 +#: pg_ctl.c:2005 #, c-format msgid "\n" "Options for stop or restart:\n" msgstr "\n" "Параметри припинення або перезапуску:\n" -#: pg_ctl.c:2009 +#: pg_ctl.c:2006 #, c-format msgid " -m, --mode=MODE MODE can be \"smart\", \"fast\", or \"immediate\"\n" msgstr " -m, --mode=РЕЖИМ РЕЖИМ може бути \"smart\", \"fast\", або \"immediate\"\n" -#: pg_ctl.c:2011 +#: pg_ctl.c:2008 #, c-format msgid "\n" "Shutdown modes are:\n" msgstr "\n" "Режими зупинки:\n" -#: pg_ctl.c:2012 +#: pg_ctl.c:2009 #, c-format msgid " smart quit after all clients have disconnected\n" msgstr " smart вийти після від'єднання усіх клієнтів\n" -#: pg_ctl.c:2013 +#: pg_ctl.c:2010 #, c-format msgid " fast quit directly, with proper shutdown (default)\n" msgstr " fast вийти негайно з коректним вимкненням (за замовченням)\n" -#: pg_ctl.c:2014 +#: pg_ctl.c:2011 #, c-format msgid " immediate quit without complete shutdown; will lead to recovery on restart\n" msgstr " immediate вийти негайно без повної процедури. Приведе до відновлення під час перезапуску\n" -#: pg_ctl.c:2016 +#: pg_ctl.c:2013 #, c-format msgid "\n" "Allowed signal names for kill:\n" msgstr "\n" "Дозволенні сигнали для команди kill:\n" -#: pg_ctl.c:2020 +#: pg_ctl.c:2017 #, c-format msgid "\n" "Options for register and unregister:\n" msgstr "\n" "Параметри для реєстрації і видалення: \n" -#: pg_ctl.c:2021 +#: pg_ctl.c:2018 #, c-format msgid " -N SERVICENAME service name with which to register PostgreSQL server\n" msgstr " -N ІМ'Я-СЛУЖБИ ім'я служби під яким зареєструвати сервер PostgreSQL\n" -#: pg_ctl.c:2022 +#: pg_ctl.c:2019 #, c-format msgid " -P PASSWORD password of account to register PostgreSQL server\n" msgstr " -P ПАРОЛЬ пароль облікового запису для реєстрації серверу PostgreSQL\n" -#: pg_ctl.c:2023 +#: pg_ctl.c:2020 #, c-format msgid " -U USERNAME user name of account to register PostgreSQL server\n" msgstr " -U КОРИСТУВАЧ ім'я користувача під яким зареєструвати сервер PostgreSQL\n" -#: pg_ctl.c:2024 +#: pg_ctl.c:2021 #, c-format msgid " -S START-TYPE service start type to register PostgreSQL server\n" msgstr " -S ТИП-ЗАПУСКУ тип запуску служби для реєстрації серверу PostgreSQL\n" -#: pg_ctl.c:2026 +#: pg_ctl.c:2023 #, c-format msgid "\n" "Start types are:\n" msgstr "\n" "Типи запуску:\n" -#: pg_ctl.c:2027 +#: pg_ctl.c:2024 #, c-format msgid " auto start service automatically during system startup (default)\n" msgstr " auto запускати сервер автоматично під час запуску системи (за замовчуванням)\n" -#: pg_ctl.c:2028 +#: pg_ctl.c:2025 #, c-format msgid " demand start service on demand\n" msgstr " demand запускати сервер за потреби\n" -#: pg_ctl.c:2031 +#: pg_ctl.c:2028 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_ctl.c:2032 +#: pg_ctl.c:2029 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_ctl.c:2057 +#: pg_ctl.c:2054 #, c-format msgid "%s: unrecognized shutdown mode \"%s\"\n" msgstr "%s: невідомий режим завершення \"%s\"\n" -#: pg_ctl.c:2086 +#: pg_ctl.c:2083 #, c-format msgid "%s: unrecognized signal name \"%s\"\n" msgstr "%s: невідомий сигнал \"%s\"\n" -#: pg_ctl.c:2103 +#: pg_ctl.c:2100 #, c-format msgid "%s: unrecognized start type \"%s\"\n" msgstr "%s: невідомий тип запуску \"%s\"\n" -#: pg_ctl.c:2159 +#: pg_ctl.c:2156 #, c-format msgid "%s: could not determine the data directory using command \"%s\"\n" msgstr "%s: неможливо визначити каталог даних за допомогою команди \"%s\"\n" -#: pg_ctl.c:2182 +#: pg_ctl.c:2179 #, c-format msgid "%s: control file appears to be corrupt\n" msgstr "%s: контрольний файл видається пошкодженим\n" -#: pg_ctl.c:2250 +#: pg_ctl.c:2247 #, c-format msgid "%s: cannot be run as root\n" "Please log in (using, e.g., \"su\") as the (unprivileged) user that will\n" @@ -766,32 +785,32 @@ msgstr "%s: не може бути запущеним від ім'я супер- " Будь ласка увійдіть (використовуючи наприклад, \"su\") як (непривілейований) користувач який буде мати\n" "свій серверний процес. \n" -#: pg_ctl.c:2333 +#: pg_ctl.c:2319 #, c-format msgid "%s: -S option not supported on this platform\n" msgstr "%s: параметр -S не підтримується цією платформою\n" -#: pg_ctl.c:2370 -#, c-format -msgid "%s: too many command-line arguments (first is \"%s\")\n" -msgstr "%s: забагато аргументів у командному рядку (перший \"%s\")\n" - -#: pg_ctl.c:2396 +#: pg_ctl.c:2375 #, c-format msgid "%s: missing arguments for kill mode\n" msgstr "%s: відсутні аргументи для режиму kill\n" -#: pg_ctl.c:2414 +#: pg_ctl.c:2393 #, c-format msgid "%s: unrecognized operation mode \"%s\"\n" msgstr "%s: невідомий режим роботи \"%s\"\n" -#: pg_ctl.c:2424 +#: pg_ctl.c:2402 +#, c-format +msgid "%s: too many command-line arguments (first is \"%s\")\n" +msgstr "%s: забагато аргументів у командному рядку (перший \"%s\")\n" + +#: pg_ctl.c:2409 #, c-format msgid "%s: no operation specified\n" msgstr "%s: команда не вказана\n" -#: pg_ctl.c:2445 +#: pg_ctl.c:2430 #, c-format msgid "%s: no database directory specified and environment variable PGDATA unset\n" msgstr "%s: не вказано каталог даних і змінна середовища PGDATA не встановлена\n" diff --git a/src/bin/pg_ctl/t/001_start_stop.pl b/src/bin/pg_ctl/t/001_start_stop.pl index 6a5ef0074335d..8c86faf3ad5f1 100644 --- a/src/bin/pg_ctl/t/001_start_stop.pl +++ b/src/bin/pg_ctl/t/001_start_stop.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -15,10 +15,15 @@ program_version_ok('pg_ctl'); program_options_handling_ok('pg_ctl'); -command_exit_is([ 'pg_ctl', 'start', '-D', "$tempdir/nonexistent" ], +command_exit_is([ 'pg_ctl', 'start', '--pgdata' => "$tempdir/nonexistent" ], 1, 'pg_ctl start with nonexistent directory'); -command_ok([ 'pg_ctl', 'initdb', '-D', "$tempdir/data", '-o', '-N' ], +command_ok( + [ + 'pg_ctl', 'initdb', + '--pgdata' => "$tempdir/data", + '--options' => '--no-sync' + ], 'pg_ctl initdb'); command_ok([ $ENV{PG_REGRESS}, '--config-auth', "$tempdir/data" ], 'configure authentication'); @@ -41,8 +46,9 @@ } close $conf; my $ctlcmd = [ - 'pg_ctl', 'start', '-D', "$tempdir/data", '-l', - "$PostgreSQL::Test::Utils::log_path/001_start_stop_server.log" + 'pg_ctl', 'start', + '--pgdata' => "$tempdir/data", + '--log' => "$PostgreSQL::Test::Utils::log_path/001_start_stop_server.log" ]; command_like($ctlcmd, qr/done.*server started/s, 'pg_ctl start'); @@ -51,17 +57,23 @@ # postmaster they start. Waiting more than the 2 seconds slop time allowed # by wait_for_postmaster() prevents that mistake. sleep 3 if ($windows_os); -command_fails([ 'pg_ctl', 'start', '-D', "$tempdir/data" ], +command_fails([ 'pg_ctl', 'start', '--pgdata' => "$tempdir/data" ], 'second pg_ctl start fails'); -command_ok([ 'pg_ctl', 'stop', '-D', "$tempdir/data" ], 'pg_ctl stop'); -command_fails([ 'pg_ctl', 'stop', '-D', "$tempdir/data" ], +command_ok([ 'pg_ctl', 'stop', '--pgdata' => "$tempdir/data" ], + 'pg_ctl stop'); +command_fails([ 'pg_ctl', 'stop', '--pgdata' => "$tempdir/data" ], 'second pg_ctl stop fails'); # Log file for default permission test. The permissions won't be checked on # Windows but we still want to do the restart test. my $logFileName = "$tempdir/data/perm-test-600.log"; -command_ok([ 'pg_ctl', 'restart', '-D', "$tempdir/data", '-l', $logFileName ], +command_ok( + [ + 'pg_ctl', 'restart', + '--pgdata' => "$tempdir/data", + '--log' => $logFileName + ], 'pg_ctl restart with server not running'); # Permissions on log file should be default @@ -82,23 +94,27 @@ skip "group access not supported on Windows", 3 if ($windows_os || $Config::Config{osname} eq 'cygwin'); - system_or_bail 'pg_ctl', 'stop', '-D', "$tempdir/data"; + system_or_bail 'pg_ctl', 'stop', '--pgdata' => "$tempdir/data"; # Change the data dir mode so log file will be created with group read # privileges on the next start chmod_recursive("$tempdir/data", 0750, 0640); command_ok( - [ 'pg_ctl', 'start', '-D', "$tempdir/data", '-l', $logFileName ], + [ + 'pg_ctl', 'start', + '--pgdata' => "$tempdir/data", + '--log' => $logFileName + ], 'start server to check group permissions'); ok(-f $logFileName); ok(check_mode_recursive("$tempdir/data", 0750, 0640)); } -command_ok([ 'pg_ctl', 'restart', '-D', "$tempdir/data" ], +command_ok([ 'pg_ctl', 'restart', '--pgdata' => "$tempdir/data" ], 'pg_ctl restart with server running'); -system_or_bail 'pg_ctl', 'stop', '-D', "$tempdir/data"; +system_or_bail 'pg_ctl', 'stop', '--pgdata' => "$tempdir/data"; done_testing(); diff --git a/src/bin/pg_ctl/t/002_status.pl b/src/bin/pg_ctl/t/002_status.pl index 1931abc99cb99..346f6919ac69c 100644 --- a/src/bin/pg_ctl/t/002_status.pl +++ b/src/bin/pg_ctl/t/002_status.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -10,20 +10,23 @@ my $tempdir = PostgreSQL::Test::Utils::tempdir; -command_exit_is([ 'pg_ctl', 'status', '-D', "$tempdir/nonexistent" ], +command_exit_is([ 'pg_ctl', 'status', '--pgdata' => "$tempdir/nonexistent" ], 4, 'pg_ctl status with nonexistent directory'); my $node = PostgreSQL::Test::Cluster->new('main'); $node->init; -command_exit_is([ 'pg_ctl', 'status', '-D', $node->data_dir ], +command_exit_is([ 'pg_ctl', 'status', '--pgdata' => $node->data_dir ], 3, 'pg_ctl status with server not running'); -system_or_bail 'pg_ctl', '-l', "$tempdir/logfile", '-D', - $node->data_dir, '-w', 'start'; -command_exit_is([ 'pg_ctl', 'status', '-D', $node->data_dir ], +system_or_bail( + 'pg_ctl', + '--log' => "$tempdir/logfile", + '--pgdata' => $node->data_dir, + '--wait', 'start'); +command_exit_is([ 'pg_ctl', 'status', '--pgdata' => $node->data_dir ], 0, 'pg_ctl status with server running'); -system_or_bail 'pg_ctl', 'stop', '-D', $node->data_dir; +system_or_bail 'pg_ctl', 'stop', '--pgdata' => $node->data_dir; done_testing(); diff --git a/src/bin/pg_ctl/t/003_promote.pl b/src/bin/pg_ctl/t/003_promote.pl index df01742ccb536..43a9bbac2ac59 100644 --- a/src/bin/pg_ctl/t/003_promote.pl +++ b/src/bin/pg_ctl/t/003_promote.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -11,7 +11,7 @@ my $tempdir = PostgreSQL::Test::Utils::tempdir; command_fails_like( - [ 'pg_ctl', '-D', "$tempdir/nonexistent", 'promote' ], + [ 'pg_ctl', '--pgdata' => "$tempdir/nonexistent", 'promote' ], qr/directory .* does not exist/, 'pg_ctl promote with nonexistent directory'); @@ -19,14 +19,14 @@ $node_primary->init(allows_streaming => 1); command_fails_like( - [ 'pg_ctl', '-D', $node_primary->data_dir, 'promote' ], + [ 'pg_ctl', '--pgdata' => $node_primary->data_dir, 'promote' ], qr/PID file .* does not exist/, 'pg_ctl promote of not running instance fails'); $node_primary->start; command_fails_like( - [ 'pg_ctl', '-D', $node_primary->data_dir, 'promote' ], + [ 'pg_ctl', '--pgdata' => $node_primary->data_dir, 'promote' ], qr/not in standby mode/, 'pg_ctl promote of primary instance fails'); @@ -39,8 +39,13 @@ is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'), 't', 'standby is in recovery'); -command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, '-W', 'promote' ], - 'pg_ctl -W promote of standby runs'); +command_ok( + [ + 'pg_ctl', + '--pgdata' => $node_standby->data_dir, + '--no-wait', 'promote' + ], + 'pg_ctl --no-wait promote of standby runs'); ok( $node_standby->poll_query_until( 'postgres', 'SELECT NOT pg_is_in_recovery()'), @@ -55,7 +60,7 @@ is($node_standby->safe_psql('postgres', 'SELECT pg_is_in_recovery()'), 't', 'standby is in recovery'); -command_ok([ 'pg_ctl', '-D', $node_standby->data_dir, 'promote' ], +command_ok([ 'pg_ctl', '--pgdata' => $node_standby->data_dir, 'promote' ], 'pg_ctl promote of standby runs'); # no wait here diff --git a/src/bin/pg_ctl/t/004_logrotate.pl b/src/bin/pg_ctl/t/004_logrotate.pl index eacca1a652394..d78360e6d1ae1 100644 --- a/src/bin/pg_ctl/t/004_logrotate.pl +++ b/src/bin/pg_ctl/t/004_logrotate.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile index 930c741c95d85..fa795883e9f30 100644 --- a/src/bin/pg_dump/Makefile +++ b/src/bin/pg_dump/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_dump # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_dump/Makefile @@ -31,6 +31,7 @@ OBJS = \ compress_lz4.o \ compress_none.o \ compress_zstd.o \ + connectdb.o \ dumputils.o \ filter.o \ parallel.o \ @@ -50,8 +51,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) | submake-libpq submake-libpg pg_restore: pg_restore.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils $(CC) $(CFLAGS) pg_restore.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) -pg_dumpall: pg_dumpall.o dumputils.o filter.o $(WIN32RES) | submake-libpq submake-libpgport submake-libpgfeutils - $(CC) $(CFLAGS) pg_dumpall.o dumputils.o filter.o $(WIN32RES) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) +pg_dumpall: pg_dumpall.o $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils + $(CC) $(CFLAGS) pg_dumpall.o $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) install: all installdirs $(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X) diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index c323b5bd3d952..aa1589e3331d2 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -4,7 +4,7 @@ * Catalog routines used by pg_dump; long ago these were shared * by another dump tool, but not anymore. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -27,8 +27,6 @@ #include "catalog/pg_subscription_d.h" #include "catalog/pg_type_d.h" #include "common/hashfn.h" -#include "fe_utils/string_utils.h" -#include "pg_backup_archiver.h" #include "pg_backup_utils.h" #include "pg_dump.h" @@ -85,7 +83,8 @@ static catalogid_hash *catalogIdHash = NULL; static void flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables, InhInfo *inhinfo, int numInherits); static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables); -static void flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables); +static void flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, + int numTables); static int strInArray(const char *pattern, char **arr, int arr_size); static IndxInfo *findIndexByOid(Oid oid); @@ -206,7 +205,7 @@ getSchemaData(Archive *fout, int *numTablesPtr) getTableAttrs(fout, tblinfo, numTables); pg_log_info("flagging inherited columns in subtables"); - flagInhAttrs(fout, tblinfo, numTables); + flagInhAttrs(fout, fout->dopt, tblinfo, numTables); pg_log_info("reading partitioning data"); getPartitioningInfo(fout); @@ -454,7 +453,8 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) * What we need to do here is: * * - Detect child columns that inherit NOT NULL bits from their parents, so - * that we needn't specify that again for the child. + * that we needn't specify that again for the child. For versions 18 and + * up, this is needed when the parent is NOT VALID and the child isn't. * * - Detect child columns that have DEFAULT NULL when their parents had some * non-null default. In this case, we make up a dummy AttrDefInfo object so @@ -474,9 +474,8 @@ flagInhIndexes(Archive *fout, TableInfo tblinfo[], int numTables) * modifies tblinfo */ static void -flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables) +flagInhAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, int numTables) { - DumpOptions *dopt = fout->dopt; int i, j, k; @@ -517,6 +516,8 @@ flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables) bool foundDefault; /* Found a default in a parent */ bool foundSameGenerated; /* Found matching GENERATED */ bool foundDiffGenerated; /* Found non-matching GENERATED */ + bool allNotNullsInvalid = true; /* is NOT NULL NOT VALID + * on all parents? */ /* no point in examining dropped columns */ if (tbinfo->attisdropped[j]) @@ -538,7 +539,27 @@ flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables) { AttrDefInfo *parentDef = parent->attrdefs[inhAttrInd]; - foundNotNull |= parent->notnull[inhAttrInd]; + /* + * Account for each parent having a not-null constraint. + * In versions 18 and later, we don't need this (and those + * didn't have NO INHERIT.) + */ + if (fout->remoteVersion < 180000 && + parent->notnull_constrs[inhAttrInd] != NULL) + foundNotNull = true; + + /* + * Keep track of whether all the parents that have a + * not-null constraint on this column have it as NOT + * VALID; if they all are, arrange to have it printed for + * this column. If at least one parent has it as valid, + * there's no need. + */ + if (fout->remoteVersion >= 180000 && + parent->notnull_constrs[inhAttrInd] && + !parent->notnull_invalid[inhAttrInd]) + allNotNullsInvalid = false; + foundDefault |= (parentDef != NULL && strcmp(parentDef->adef_expr, "NULL") != 0 && !parent->attgenerated[inhAttrInd]); @@ -556,8 +577,21 @@ flagInhAttrs(Archive *fout, TableInfo *tblinfo, int numTables) } } - /* Remember if we found inherited NOT NULL */ - tbinfo->inhNotNull[j] = foundNotNull; + /* + * In versions < 18, for lack of a better system, we arbitrarily + * decide that a not-null constraint is not locally defined if at + * least one of the parents has it. + */ + if (fout->remoteVersion < 180000 && foundNotNull) + tbinfo->notnull_islocal[j] = false; + + /* + * For versions >18, we must print the not-null constraint locally + * for this table even if it isn't really locally defined, but is + * valid for the child and no parent has it as valid. + */ + if (fout->remoteVersion >= 180000 && allNotNullsInvalid) + tbinfo->notnull_islocal[j] = true; /* * Manufacture a DEFAULT NULL clause if necessary. This breaks diff --git a/src/bin/pg_dump/compress_gzip.c b/src/bin/pg_dump/compress_gzip.c index 9e1b7c157ea76..5a30ebf9bf5b5 100644 --- a/src/bin/pg_dump/compress_gzip.c +++ b/src/bin/pg_dump/compress_gzip.c @@ -3,7 +3,7 @@ * compress_gzip.c * Routines for archivers to read or write a gzip compressed data stream. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,7 +18,7 @@ #include "pg_backup_utils.h" #ifdef HAVE_LIBZ -#include "zlib.h" +#include /*---------------------- * Compressor API @@ -129,7 +129,7 @@ DeflateCompressorCommon(ArchiveHandle *AH, CompressorState *cs, bool flush) */ size_t len = gzipcs->outsize - zp->avail_out; - cs->writeF(AH, (char *) out, len); + cs->writeF(AH, out, len); } zp->next_out = out; zp->avail_out = gzipcs->outsize; diff --git a/src/bin/pg_dump/compress_gzip.h b/src/bin/pg_dump/compress_gzip.h index 072a30df14c36..3bef0d5b1b802 100644 --- a/src/bin/pg_dump/compress_gzip.h +++ b/src/bin/pg_dump/compress_gzip.h @@ -3,7 +3,7 @@ * compress_gzip.h * GZIP interface to compress_io.c routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index e2edf8bf4f612..8c3d9c911c47b 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -4,7 +4,7 @@ * Routines for archivers to write an uncompressed or compressed data * stream. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * This file includes two APIs for dealing with compressed data. The first @@ -70,7 +70,6 @@ #include "compress_lz4.h" #include "compress_none.h" #include "compress_zstd.h" -#include "pg_backup_utils.h" /*---------------------- * Generic functions diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h index bbbf1582abc5e..db9b38744c8e2 100644 --- a/src/bin/pg_dump/compress_io.h +++ b/src/bin/pg_dump/compress_io.h @@ -3,7 +3,7 @@ * compress_io.h * Interface to compress_io.c routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_lz4.c b/src/bin/pg_dump/compress_lz4.c index 7f72492beaf80..e99f0cad71fcb 100644 --- a/src/bin/pg_dump/compress_lz4.c +++ b/src/bin/pg_dump/compress_lz4.c @@ -3,7 +3,7 @@ * compress_lz4.c * Routines for archivers to write a LZ4 compressed data stream. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_lz4.h b/src/bin/pg_dump/compress_lz4.h index 36f1a01b4e6d2..7f7216cc6489f 100644 --- a/src/bin/pg_dump/compress_lz4.h +++ b/src/bin/pg_dump/compress_lz4.h @@ -3,7 +3,7 @@ * compress_lz4.h * LZ4 interface to compress_io.c routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_none.c b/src/bin/pg_dump/compress_none.c index f3a524d8a4969..3fc89c9985461 100644 --- a/src/bin/pg_dump/compress_none.c +++ b/src/bin/pg_dump/compress_none.c @@ -3,7 +3,7 @@ * compress_none.c * Routines for archivers to read or write an uncompressed stream. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_none.h b/src/bin/pg_dump/compress_none.h index c8e6c2089a664..f927f196c36ae 100644 --- a/src/bin/pg_dump/compress_none.h +++ b/src/bin/pg_dump/compress_none.h @@ -3,7 +3,7 @@ * compress_none.h * Uncompressed interface to compress_io.c routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/compress_zstd.c b/src/bin/pg_dump/compress_zstd.c index aa5aff2fee32d..cb595b10c2d32 100644 --- a/src/bin/pg_dump/compress_zstd.c +++ b/src/bin/pg_dump/compress_zstd.c @@ -3,7 +3,7 @@ * compress_zstd.c * Routines for archivers to write a Zstd compressed data stream. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -137,10 +137,12 @@ EndCompressorZstd(ArchiveHandle *AH, CompressorState *cs) Assert(zstdcs->dstream == NULL); _ZstdWriteCommon(AH, cs, true); ZSTD_freeCStream(zstdcs->cstream); - pg_free(zstdcs->output.dst); } + /* output buffer may be allocated in either mode */ + pg_free(zstdcs->output.dst); pg_free(zstdcs); + cs->private_data = NULL; } static void diff --git a/src/bin/pg_dump/compress_zstd.h b/src/bin/pg_dump/compress_zstd.h index 5acdc12bf1567..af21db48ded34 100644 --- a/src/bin/pg_dump/compress_zstd.h +++ b/src/bin/pg_dump/compress_zstd.h @@ -3,7 +3,7 @@ * compress_zstd.h * Zstd interface to compress_io.c routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/connectdb.c b/src/bin/pg_dump/connectdb.c new file mode 100644 index 0000000000000..d55d53dbeeab9 --- /dev/null +++ b/src/bin/pg_dump/connectdb.c @@ -0,0 +1,295 @@ +/*------------------------------------------------------------------------- + * + * connectdb.c + * This is a common file connection to the database. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/pg_dump/connectdb.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "common/connect.h" +#include "common/logging.h" +#include "common/string.h" +#include "connectdb.h" +#include "dumputils.h" +#include "fe_utils/string_utils.h" + +static char *constructConnStr(const char **keywords, const char **values); + +/* + * ConnectDatabase + * + * Make a database connection with the given parameters. An + * interactive password prompt is automatically issued if required. + * + * If fail_on_error is false, we return NULL without printing any message + * on failure, but preserve any prompted password for the next try. + * + * On success, the 'connstr' is set to a connection string containing + * the options used and 'server_version' is set to version so that caller + * can use them. + */ +PGconn * +ConnectDatabase(const char *dbname, const char *connection_string, + const char *pghost, const char *pgport, const char *pguser, + trivalue prompt_password, bool fail_on_error, const char *progname, + const char **connstr, int *server_version, char *password, + char *override_dbname) +{ + PGconn *conn; + bool new_pass; + const char *remoteversion_str; + int my_version; + const char **keywords = NULL; + const char **values = NULL; + PQconninfoOption *conn_opts = NULL; + int server_version_temp; + + if (prompt_password == TRI_YES && !password) + password = simple_prompt("Password: ", false); + + /* + * Start the connection. Loop until we have a password if requested by + * backend. + */ + do + { + int argcount = 8; + PQconninfoOption *conn_opt; + char *err_msg = NULL; + int i = 0; + + free(keywords); + free(values); + PQconninfoFree(conn_opts); + + /* + * Merge the connection info inputs given in form of connection string + * and other options. Explicitly discard any dbname value in the + * connection string; otherwise, PQconnectdbParams() would interpret + * that value as being itself a connection string. + */ + if (connection_string) + { + conn_opts = PQconninfoParse(connection_string, &err_msg); + if (conn_opts == NULL) + pg_fatal("%s", err_msg); + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && + strcmp(conn_opt->keyword, "dbname") != 0) + argcount++; + } + + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && + strcmp(conn_opt->keyword, "dbname") != 0) + { + keywords[i] = conn_opt->keyword; + values[i] = conn_opt->val; + i++; + } + } + } + else + { + keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); + values = pg_malloc0((argcount + 1) * sizeof(*values)); + } + + if (pghost) + { + keywords[i] = "host"; + values[i] = pghost; + i++; + } + if (pgport) + { + keywords[i] = "port"; + values[i] = pgport; + i++; + } + if (pguser) + { + keywords[i] = "user"; + values[i] = pguser; + i++; + } + if (password) + { + keywords[i] = "password"; + values[i] = password; + i++; + } + if (dbname) + { + keywords[i] = "dbname"; + values[i] = dbname; + i++; + } + if (override_dbname) + { + keywords[i] = "dbname"; + values[i] = override_dbname; + i++; + } + + keywords[i] = "fallback_application_name"; + values[i] = progname; + i++; + + new_pass = false; + conn = PQconnectdbParams(keywords, values, true); + + if (!conn) + pg_fatal("could not connect to database \"%s\"", dbname); + + if (PQstatus(conn) == CONNECTION_BAD && + PQconnectionNeedsPassword(conn) && + !password && + prompt_password != TRI_NO) + { + PQfinish(conn); + password = simple_prompt("Password: ", false); + new_pass = true; + } + } while (new_pass); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) + { + if (fail_on_error) + pg_fatal("%s", PQerrorMessage(conn)); + else + { + PQfinish(conn); + + free(keywords); + free(values); + PQconninfoFree(conn_opts); + + return NULL; + } + } + + /* + * Ok, connected successfully. If requested, remember the options used, in + * the form of a connection string. + */ + if (connstr) + *connstr = constructConnStr(keywords, values); + + free(keywords); + free(values); + PQconninfoFree(conn_opts); + + /* Check version */ + remoteversion_str = PQparameterStatus(conn, "server_version"); + if (!remoteversion_str) + pg_fatal("could not get server version"); + + server_version_temp = PQserverVersion(conn); + if (server_version_temp == 0) + pg_fatal("could not parse server version \"%s\"", + remoteversion_str); + + /* If requested, then copy server version to out variable. */ + if (server_version) + *server_version = server_version_temp; + + my_version = PG_VERSION_NUM; + + /* + * We allow the server to be back to 9.2, and up to any minor release of + * our own major version. (See also version check in pg_dump.c.) + */ + if (my_version != server_version_temp + && (server_version_temp < 90200 || + (server_version_temp / 100) > (my_version / 100))) + { + pg_log_error("aborting because of server version mismatch"); + pg_log_error_detail("server version: %s; %s version: %s", + remoteversion_str, progname, PG_VERSION); + exit_nicely(1); + } + + PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL)); + + return conn; +} + +/* + * constructConnStr + * + * Construct a connection string from the given keyword/value pairs. It is + * used to pass the connection options to the pg_dump subprocess. + * + * The following parameters are excluded: + * dbname - varies in each pg_dump invocation + * password - it's not secure to pass a password on the command line + * fallback_application_name - we'll let pg_dump set it + */ +static char * +constructConnStr(const char **keywords, const char **values) +{ + PQExpBuffer buf = createPQExpBuffer(); + char *connstr; + int i; + bool firstkeyword = true; + + /* Construct a new connection string in key='value' format. */ + for (i = 0; keywords[i] != NULL; i++) + { + if (strcmp(keywords[i], "dbname") == 0 || + strcmp(keywords[i], "password") == 0 || + strcmp(keywords[i], "fallback_application_name") == 0) + continue; + + if (!firstkeyword) + appendPQExpBufferChar(buf, ' '); + firstkeyword = false; + appendPQExpBuffer(buf, "%s=", keywords[i]); + appendConnStrVal(buf, values[i]); + } + + connstr = pg_strdup(buf->data); + destroyPQExpBuffer(buf); + return connstr; +} + +/* + * executeQuery + * + * Run a query, return the results, exit program on failure. + */ +PGresult * +executeQuery(PGconn *conn, const char *query) +{ + PGresult *res; + + pg_log_info("executing %s", query); + + res = PQexec(conn, query); + if (!res || + PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("query failed: %s", PQerrorMessage(conn)); + pg_log_error_detail("Query was: %s", query); + PQfinish(conn); + exit_nicely(1); + } + + return res; +} diff --git a/src/bin/pg_dump/connectdb.h b/src/bin/pg_dump/connectdb.h new file mode 100644 index 0000000000000..6c1e1954769ff --- /dev/null +++ b/src/bin/pg_dump/connectdb.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * connectdb.h + * Common header file for connection to the database. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/pg_dump/connectdb.h + * + *------------------------------------------------------------------------- + */ +#ifndef CONNECTDB_H +#define CONNECTDB_H + +#include "pg_backup.h" +#include "pg_backup_utils.h" + +extern PGconn *ConnectDatabase(const char *dbname, const char *connection_string, const char *pghost, + const char *pgport, const char *pguser, + trivalue prompt_password, bool fail_on_error, + const char *progname, const char **connstr, int *server_version, + char *password, char *override_dbname); +extern PGresult *executeQuery(PGconn *conn, const char *query); +#endif /* CONNECTDB_H */ diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 5649859aa1e2d..73ce34346b278 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -5,7 +5,7 @@ * Basically this is stuff that is useful in both pg_dump and pg_dumpall. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_dump/dumputils.c @@ -16,6 +16,8 @@ #include +#include "common/file_perm.h" +#include "common/logging.h" #include "dumputils.h" #include "fe_utils/string_utils.h" @@ -506,7 +508,8 @@ do { \ CONVERT_PRIV('s', "SET"); CONVERT_PRIV('A', "ALTER SYSTEM"); } - else if (strcmp(type, "LARGE OBJECT") == 0) + else if (strcmp(type, "LARGE OBJECT") == 0 || + strcmp(type, "LARGE OBJECTS") == 0) { CONVERT_PRIV('r', "SELECT"); CONVERT_PRIV('w', "UPDATE"); @@ -883,3 +886,37 @@ makeAlterConfigCommand(PGconn *conn, const char *configitem, pg_free(mine); } + +/* + * create_or_open_dir + * + * This will create a new directory with the given dirname. If there is + * already an empty directory with that name, then use it. + */ +void +create_or_open_dir(const char *dirname) +{ + int ret; + + switch ((ret = pg_check_dir(dirname))) + { + case -1: + /* opendir failed but not with ENOENT */ + pg_fatal("could not open directory \"%s\": %m", dirname); + break; + case 0: + /* directory does not exist */ + if (mkdir(dirname, pg_dir_create_mode) < 0) + pg_fatal("could not create directory \"%s\": %m", dirname); + break; + case 1: + /* exists and is empty, fix perms */ + if (chmod(dirname, pg_dir_create_mode) != 0) + pg_fatal("could not change permissions of directory \"%s\": %m", + dirname); + break; + default: + /* exists and is not empty */ + pg_fatal("directory \"%s\" is not empty", dirname); + } +} diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index 98c71c6bf9473..91c6e612e282e 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -5,7 +5,7 @@ * Basically this is stuff that is useful in both pg_dump and pg_dumpall. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_dump/dumputils.h @@ -62,5 +62,6 @@ extern void makeAlterConfigCommand(PGconn *conn, const char *configitem, const char *type, const char *name, const char *type2, const char *name2, PQExpBuffer buf); +extern void create_or_open_dir(const char *dirname); #endif /* DUMPUTILS_H */ diff --git a/src/bin/pg_dump/filter.c b/src/bin/pg_dump/filter.c index 5815cd237483f..7214d51413771 100644 --- a/src/bin/pg_dump/filter.c +++ b/src/bin/pg_dump/filter.c @@ -3,7 +3,7 @@ * filter.c * Implementation of simple filter file parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -13,7 +13,6 @@ */ #include "postgres_fe.h" -#include "common/fe_memutils.h" #include "common/logging.h" #include "common/string.h" #include "filter.h" diff --git a/src/bin/pg_dump/filter.h b/src/bin/pg_dump/filter.h index d9b9b3eebcb81..f35b7b8d0c1c4 100644 --- a/src/bin/pg_dump/filter.h +++ b/src/bin/pg_dump/filter.h @@ -3,7 +3,7 @@ * filter.h * Common header file for the parser of filter file * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/meson.build b/src/bin/pg_dump/meson.build index ecd0a0a0e12db..d8e9e101254b1 100644 --- a/src/bin/pg_dump/meson.build +++ b/src/bin/pg_dump/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_dump_common_sources = files( 'compress_gzip.c', @@ -6,6 +6,7 @@ pg_dump_common_sources = files( 'compress_lz4.c', 'compress_none.c', 'compress_zstd.c', + 'connectdb.c', 'dumputils.c', 'filter.c', 'parallel.c', @@ -101,6 +102,7 @@ tests += { 't/003_pg_dump_with_server.pl', 't/004_pg_dump_parallel.pl', 't/005_pg_dump_filterfile.pl', + 't/006_pg_dumpall.pl', 't/010_dump_connstr.pl', ], }, diff --git a/src/bin/pg_dump/nls.mk b/src/bin/pg_dump/nls.mk index b7b77394f0fa6..9700f7cbe6c28 100644 --- a/src/bin/pg_dump/nls.mk +++ b/src/bin/pg_dump/nls.mk @@ -13,6 +13,7 @@ GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ compress_lz4.c \ compress_none.c \ compress_zstd.c \ + connectdb.c \ pg_dump.c \ common.c \ pg_dump_sort.c \ diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c index a09247fae47e3..5974d6706fd57 100644 --- a/src/bin/pg_dump/parallel.c +++ b/src/bin/pg_dump/parallel.c @@ -4,7 +4,7 @@ * * Parallel support for pg_dump and pg_restore * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -63,7 +63,9 @@ #include "fe_utils/string_utils.h" #include "parallel.h" #include "pg_backup_utils.h" +#ifdef WIN32 #include "port/pg_bswap.h" +#endif /* Mnemonic macros for indexing the fd array returned by pipe(2) */ #define PIPE_READ 0 @@ -331,6 +333,16 @@ on_exit_close_archive(Archive *AHX) on_exit_nicely(archive_close_connection, &shutdown_info); } +/* + * When pg_restore restores multiple databases, then update already added entry + * into array for cleanup. + */ +void +replace_on_exit_close_archive(Archive *AHX) +{ + shutdown_info.AHX = AHX; +} + /* * on_exit_nicely handler for shutting down database connections and * worker processes cleanly. diff --git a/src/bin/pg_dump/parallel.h b/src/bin/pg_dump/parallel.h index 5efc02c77c557..beddfaa6d3192 100644 --- a/src/bin/pg_dump/parallel.h +++ b/src/bin/pg_dump/parallel.h @@ -4,7 +4,7 @@ * * Parallel support for pg_dump and pg_restore * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index fbf5f1c515e5e..af0007fb6d2f1 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -72,11 +72,13 @@ enum _dumpPreparedQueries PREPQUERY_DUMPOPR, PREPQUERY_DUMPRANGETYPE, PREPQUERY_DUMPTABLEATTACH, + PREPQUERY_GETATTRIBUTESTATS, PREPQUERY_GETCOLUMNACLS, PREPQUERY_GETDOMAINCONSTRAINTS, - NUM_PREP_QUERIES /* must be last */ }; +#define NUM_PREP_QUERIES (PREPQUERY_GETDOMAINCONSTRAINTS + 1) + /* Parameters needed by ConnectDatabase; same for dump and restore */ typedef struct _connParams { @@ -109,14 +111,13 @@ typedef struct _restoreOptions int column_inserts; int if_exists; int no_comments; /* Skip comments */ + int no_policies; /* Skip row security policies */ int no_publications; /* Skip publication entries */ int no_security_labels; /* Skip security label entries */ int no_subscriptions; /* Skip subscription entries */ int strict_names; const char *filename; - int dataOnly; - int schemaOnly; int dumpSections; int verbose; int aclsSkip; @@ -157,6 +158,11 @@ typedef struct _restoreOptions int enable_row_security; int sequence_data; /* dump sequence data even in schema-only mode */ int binary_upgrade; + + /* flags derived from the user-settable flags */ + bool dumpSchema; + bool dumpData; + bool dumpStatistics; } RestoreOptions; typedef struct _dumpOptions @@ -166,8 +172,6 @@ typedef struct _dumpOptions int binary_upgrade; /* various user-settable parameters */ - bool schemaOnly; - bool dataOnly; int dumpSections; /* bitmask of chosen sections */ bool aclsSkip; const char *lockWaitTimeout; @@ -178,8 +182,9 @@ typedef struct _dumpOptions int column_inserts; int if_exists; int no_comments; - int no_security_labels; + int no_policies; /* Skip row security policies */ int no_publications; + int no_security_labels; int no_subscriptions; int no_toast_compression; int no_unlogged_table_data; @@ -203,6 +208,11 @@ typedef struct _dumpOptions int sequence_data; /* dump sequence data even in schema-only mode */ int do_nothing; + + /* flags derived from the user-settable flags */ + bool dumpSchema; + bool dumpData; + bool dumpStatistics; } DumpOptions; /* @@ -274,18 +284,15 @@ typedef int DumpId; /* * Function pointer prototypes for assorted callback methods. */ - -typedef int (*DataDumperPtr) (Archive *AH, const void *userArg); - typedef void (*SetupWorkerPtrType) (Archive *AH); /* * Main archiver interface. */ -extern void ConnectDatabase(Archive *AHX, - const ConnParams *cparams, - bool isReconnect); +extern void ConnectDatabaseAhx(Archive *AHX, + const ConnParams *cparams, + bool isReconnect); extern void DisconnectDatabase(Archive *AHX); extern PGconn *GetConnection(Archive *AHX); @@ -301,7 +308,7 @@ extern void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ro extern void ProcessArchiveRestoreOptions(Archive *AHX); -extern void RestoreArchive(Archive *AHX); +extern void RestoreArchive(Archive *AHX, bool append_data); /* Open an existing archive */ extern Archive *OpenArchive(const char *FileSpec, const ArchiveFormat fmt); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 68e321212d922..197c1295d93fd 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -46,6 +46,9 @@ #define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n" #define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n" +#define TOC_PREFIX_NONE "" +#define TOC_PREFIX_DATA "Data for " +#define TOC_PREFIX_STATS "Statistics for " static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, @@ -53,7 +56,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, SetupWorkerPtrType setupWorkerPtr, DataDirSyncMethod sync_method); static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te); -static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData); +static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx); static char *sanitize_line(const char *str, bool want_hyphen); static void _doSetFixedOutputState(ArchiveHandle *AH); static void _doSetSessionAuth(ArchiveHandle *AH, const char *user); @@ -82,7 +85,7 @@ static int RestoringToDB(ArchiveHandle *AH); static void dump_lo_buf(ArchiveHandle *AH); static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim); static void SetOutput(ArchiveHandle *AH, const char *filename, - const pg_compress_specification compression_spec); + const pg_compress_specification compression_spec, bool append_data); static CompressFileHandle *SaveOutput(ArchiveHandle *AH); static void RestoreOutput(ArchiveHandle *AH, CompressFileHandle *savedOutput); @@ -147,6 +150,9 @@ InitDumpOptions(DumpOptions *opts) opts->include_everything = true; opts->cparams.promptPassword = TRI_DEFAULT; opts->dumpSections = DUMP_UNSECTIONED; + opts->dumpSchema = true; + opts->dumpData = true; + opts->dumpStatistics = false; } /* @@ -165,11 +171,12 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt) dopt->cparams.username = ropt->cparams.username ? pg_strdup(ropt->cparams.username) : NULL; dopt->cparams.promptPassword = ropt->cparams.promptPassword; dopt->outputClean = ropt->dropSchema; - dopt->dataOnly = ropt->dataOnly; - dopt->schemaOnly = ropt->schemaOnly; + dopt->dumpData = ropt->dumpData; + dopt->dumpSchema = ropt->dumpSchema; + dopt->dumpSections = ropt->dumpSections; + dopt->dumpStatistics = ropt->dumpStatistics; dopt->if_exists = ropt->if_exists; dopt->column_inserts = ropt->column_inserts; - dopt->dumpSections = ropt->dumpSections; dopt->aclsSkip = ropt->aclsSkip; dopt->outputSuperuser = ropt->superuser; dopt->outputCreateDB = ropt->createDB; @@ -181,6 +188,7 @@ dumpOptionsFromRestoreOptions(RestoreOptions *ropt) dopt->disable_dollar_quoting = ropt->disable_dollar_quoting; dopt->dump_inserts = ropt->dump_inserts; dopt->no_comments = ropt->no_comments; + dopt->no_policies = ropt->no_policies; dopt->no_publications = ropt->no_publications; dopt->no_security_labels = ropt->no_security_labels; dopt->no_subscriptions = ropt->no_subscriptions; @@ -329,9 +337,14 @@ ProcessArchiveRestoreOptions(Archive *AHX) StrictNamesCheck(ropt); } -/* Public */ +/* + * RestoreArchive + * + * If append_data is set, then append data into file as we are restoring dump + * of multiple databases which was taken by pg_dumpall. + */ void -RestoreArchive(Archive *AHX) +RestoreArchive(Archive *AHX, bool append_data) { ArchiveHandle *AH = (ArchiveHandle *) AHX; RestoreOptions *ropt = AH->public.ropt; @@ -406,7 +419,7 @@ RestoreArchive(Archive *AHX) AHX->minRemoteVersion = 0; AHX->maxRemoteVersion = 9999999; - ConnectDatabase(AHX, &ropt->cparams, false); + ConnectDatabaseAhx(AHX, &ropt->cparams, false); /* * If we're talking to the DB directly, don't send comments since they @@ -416,30 +429,30 @@ RestoreArchive(Archive *AHX) } /* - * Work out if we have an implied data-only restore. This can happen if - * the dump was data only or if the user has used a toc list to exclude + * Work out if we have an implied schema-less restore. This can happen if + * the dump excluded the schema or the user has used a toc list to exclude * all of the schema data. All we do is look for schema entries - if none - * are found then we set the dataOnly flag. + * are found then we unset the dumpSchema flag. * * We could scan for wanted TABLE entries, but that is not the same as - * dataOnly. At this stage, it seems unnecessary (6-Mar-2001). + * data-only. At this stage, it seems unnecessary (6-Mar-2001). */ - if (!ropt->dataOnly) + if (ropt->dumpSchema) { - int impliedDataOnly = 1; + bool no_schema_found = true; for (te = AH->toc->next; te != AH->toc; te = te->next) { if ((te->reqs & REQ_SCHEMA) != 0) - { /* It's schema, and it's wanted */ - impliedDataOnly = 0; + { + no_schema_found = false; break; } } - if (impliedDataOnly) + if (no_schema_found) { - ropt->dataOnly = impliedDataOnly; - pg_log_info("implied data-only restore"); + ropt->dumpSchema = false; + pg_log_info("implied no-schema restore"); } } @@ -448,7 +461,7 @@ RestoreArchive(Archive *AHX) */ sav = SaveOutput(AH); if (ropt->filename || ropt->compression_spec.algorithm != PG_COMPRESSION_NONE) - SetOutput(AH, ropt->filename, ropt->compression_spec); + SetOutput(AH, ropt->filename, ropt->compression_spec, append_data); ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n"); @@ -737,7 +750,7 @@ RestoreArchive(Archive *AHX) for (te = AH->toc->next; te != AH->toc; te = te->next) { - if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) == 0) + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0) continue; /* ignore if not to be dumped at all */ switch (_tocEntryRestorePass(te)) @@ -758,7 +771,7 @@ RestoreArchive(Archive *AHX) { for (te = AH->toc->next; te != AH->toc; te = te->next) { - if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && _tocEntryRestorePass(te) == RESTORE_PASS_ACL) (void) restore_toc_entry(AH, te, false); } @@ -768,7 +781,7 @@ RestoreArchive(Archive *AHX) { for (te = AH->toc->next; te != AH->toc; te = te->next) { - if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && _tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL) (void) restore_toc_entry(AH, te, false); } @@ -824,7 +837,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) /* Dump any relevant dump warnings to stderr */ if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0) { - if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0) + if (ropt->dumpSchema && te->defn != NULL && strlen(te->defn) != 0) pg_log_warning("warning from original dump file: %s", te->defn); else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0) pg_log_warning("warning from original dump file: %s", te->copyStmt); @@ -867,7 +880,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) pg_log_info("creating %s \"%s\"", te->desc, te->tag); - _printTocEntry(AH, te, false); + _printTocEntry(AH, te, TOC_PREFIX_NONE); defnDumped = true; if (strcmp(te->desc, "TABLE") == 0) @@ -936,7 +949,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) */ if (AH->PrintTocDataPtr != NULL) { - _printTocEntry(AH, te, true); + _printTocEntry(AH, te, TOC_PREFIX_DATA); if (strcmp(te->desc, "BLOBS") == 0 || strcmp(te->desc, "BLOB COMMENTS") == 0) @@ -1034,15 +1047,21 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) { /* If we haven't already dumped the defn part, do so now */ pg_log_info("executing %s %s", te->desc, te->tag); - _printTocEntry(AH, te, false); + _printTocEntry(AH, te, TOC_PREFIX_NONE); } } + /* + * If it has a statistics component that we want, then process that + */ + if ((reqs & REQ_STATS) != 0) + _printTocEntry(AH, te, TOC_PREFIX_STATS); + /* * If we emitted anything for this TOC entry, that counts as one action * against the transaction-size limit. Commit if it's time to. */ - if ((reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && ropt->txn_size > 0) + if ((reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && ropt->txn_size > 0) { if (++AH->txnCount >= ropt->txn_size) { @@ -1080,6 +1099,9 @@ NewRestoreOptions(void) opts->dumpSections = DUMP_UNSECTIONED; opts->compression_spec.algorithm = PG_COMPRESSION_NONE; opts->compression_spec.level = 0; + opts->dumpSchema = true; + opts->dumpData = true; + opts->dumpStatistics = true; return opts; } @@ -1090,7 +1112,7 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te) RestoreOptions *ropt = AH->public.ropt; /* This hack is only needed in a data-only restore */ - if (!ropt->dataOnly || !ropt->disable_triggers) + if (ropt->dumpSchema || !ropt->disable_triggers) return; pg_log_info("disabling triggers for %s", te->tag); @@ -1116,7 +1138,7 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te) RestoreOptions *ropt = AH->public.ropt; /* This hack is only needed in a data-only restore */ - if (!ropt->dataOnly || !ropt->disable_triggers) + if (ropt->dumpSchema || !ropt->disable_triggers) return; pg_log_info("enabling triggers for %s", te->tag); @@ -1248,6 +1270,9 @@ ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId, newToc->dataDumperArg = opts->dumpArg; newToc->hadDumper = opts->dumpFn ? true : false; + newToc->defnDumper = opts->defnFn; + newToc->defnDumperArg = opts->defnArg; + newToc->formatData = NULL; newToc->dataLength = 0; @@ -1275,7 +1300,7 @@ PrintTOCSummary(Archive *AHX) sav = SaveOutput(AH); if (ropt->filename) - SetOutput(AH, ropt->filename, out_compression_spec); + SetOutput(AH, ropt->filename, out_compression_spec, false); if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT, localtime(&AH->createDate)) == 0) @@ -1325,7 +1350,7 @@ PrintTOCSummary(Archive *AHX) te->reqs = _tocEntryRequired(te, curSection, AH); /* Now, should we print it? */ if (ropt->verbose || - (te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) + (te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0) { char *sanitized_name; char *sanitized_schema; @@ -1462,7 +1487,7 @@ StartRestoreLO(ArchiveHandle *AH, Oid oid, bool drop) { /* First time through (in this process) so allocate the buffer */ AH->lo_buf_size = LOBBUFSIZE; - AH->lo_buf = (void *) pg_malloc(LOBBUFSIZE); + AH->lo_buf = pg_malloc(LOBBUFSIZE); } AH->lo_buf_used = 0; @@ -1654,7 +1679,8 @@ archprintf(Archive *AH, const char *fmt,...) static void SetOutput(ArchiveHandle *AH, const char *filename, - const pg_compress_specification compression_spec) + const pg_compress_specification compression_spec, + bool append_data) { CompressFileHandle *CFH; const char *mode; @@ -1674,7 +1700,7 @@ SetOutput(ArchiveHandle *AH, const char *filename, else fn = fileno(stdout); - if (AH->mode == archModeAppend) + if (append_data || AH->mode == archModeAppend) mode = PG_BINARY_A; else mode = PG_BINARY_W; @@ -1818,7 +1844,7 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH) size_t avail = AH->lo_buf_size - AH->lo_buf_used; memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail); - ptr = (const void *) ((const char *) ptr + avail); + ptr = (const char *) ptr + avail; remaining -= avail; AH->lo_buf_used += avail; dump_lo_buf(AH); @@ -2178,7 +2204,7 @@ ReadStr(ArchiveHandle *AH) else { buf = (char *) pg_malloc(l + 1); - AH->ReadBufPtr(AH, (void *) buf, l); + AH->ReadBufPtr(AH, buf, l); buf[l] = '\0'; } @@ -2443,7 +2469,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt, break; default: - pg_fatal("unrecognized file format \"%d\"", fmt); + pg_fatal("unrecognized file format \"%d\"", AH->format); } return AH; @@ -2578,7 +2604,7 @@ WriteToc(ArchiveHandle *AH) tocCount = 0; for (te = AH->toc->next; te != AH->toc; te = te->next) { - if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0) + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) != 0) tocCount++; } @@ -2588,7 +2614,7 @@ WriteToc(ArchiveHandle *AH) for (te = AH->toc->next; te != AH->toc; te = te->next) { - if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0) + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) == 0) continue; WriteInt(AH, te->dumpId); @@ -2603,7 +2629,45 @@ WriteToc(ArchiveHandle *AH) WriteStr(AH, te->tag); WriteStr(AH, te->desc); WriteInt(AH, te->section); - WriteStr(AH, te->defn); + + if (te->defnLen) + { + /* + * defnLen should only be set for custom format's second call to + * WriteToc(), which rewrites the TOC in place to update data + * offsets. Instead of calling the defnDumper a second time + * (which could involve re-executing queries), just skip writing + * the entry. While regenerating the definition should + * theoretically produce the same result as before, it's expensive + * and feels risky. + * + * The custom format only calls WriteToc() a second time if + * fseeko() is usable (see _CloseArchive() in pg_backup_custom.c), + * so we can safely use it without checking. For other formats, + * we fail because one of our assumptions must no longer hold + * true. + * + * XXX This is a layering violation, but the alternative is an + * awkward and complicated callback infrastructure for this + * special case. This might be worth revisiting in the future. + */ + if (AH->format != archCustom) + pg_fatal("unexpected TOC entry in WriteToc(): %d %s %s", + te->dumpId, te->desc, te->tag); + + if (fseeko(AH->FH, te->defnLen, SEEK_CUR) != 0) + pg_fatal("error during file seek: %m"); + } + else if (te->defnDumper) + { + char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te); + + te->defnLen = WriteStr(AH, defn); + pg_free(defn); + } + else + WriteStr(AH, te->defn); + WriteStr(AH, te->dropStmt); WriteStr(AH, te->copyStmt); WriteStr(AH, te->namespace); @@ -2818,6 +2882,7 @@ processEncodingEntry(ArchiveHandle *AH, TocEntry *te) pg_fatal("unrecognized encoding \"%s\"", ptr1); AH->public.encoding = encoding; + setFmtEncoding(encoding); } else pg_fatal("invalid ENCODING item: %s", @@ -2899,8 +2964,9 @@ StrictNamesCheck(RestoreOptions *ropt) * Determine whether we want to restore this TOC entry. * * Returns 0 if entry should be skipped, or some combination of the - * REQ_SCHEMA and REQ_DATA bits if we want to restore schema and/or data - * portions of this TOC entry, or REQ_SPECIAL if it's a special entry. + * REQ_SCHEMA, REQ_DATA, and REQ_STATS bits if we want to restore schema, data + * and/or statistics portions of this TOC entry, or REQ_SPECIAL if it's a + * special entry. */ static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) @@ -2914,6 +2980,14 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) strcmp(te->desc, "SEARCHPATH") == 0) return REQ_SPECIAL; + if (strcmp(te->desc, "STATISTICS DATA") == 0) + { + if (!ropt->dumpStatistics) + return 0; + + res = REQ_STATS; + } + /* * DATABASE and DATABASE PROPERTIES also have a special rule: they are * restored in createDB mode, and not restored otherwise, independently of @@ -2940,6 +3014,12 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0) return 0; + /* If it's a policy, maybe ignore it */ + if (ropt->no_policies && + (strcmp(te->desc, "POLICY") == 0 || + strcmp(te->desc, "ROW SECURITY") == 0)) + return 0; + /* * If it's a publication or a table part of a publication, maybe ignore * it. @@ -2987,6 +3067,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) */ if (strcmp(te->desc, "ACL") == 0 || strcmp(te->desc, "COMMENT") == 0 || + strcmp(te->desc, "STATISTICS DATA") == 0 || strcmp(te->desc, "SECURITY LABEL") == 0) { /* Database properties react to createDB, not selectivity options. */ @@ -3103,6 +3184,7 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) } } + /* * Determine whether the TOC entry contains schema and/or data components, * and mask off inapplicable REQ bits. If it had a dataDumper, assume @@ -3147,13 +3229,13 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) if ((strcmp(te->desc, "") == 0) && (strcmp(te->tag, "Max OID") == 0)) return 0; - /* Mask it if we only want schema */ - if (ropt->schemaOnly) + /* Mask it if we don't want data */ + if (!ropt->dumpData) { /* - * The sequence_data option overrides schemaOnly for SEQUENCE SET. + * The sequence_data option overrides dumpData for SEQUENCE SET. * - * In binary-upgrade mode, even with schemaOnly set, we do not mask + * In binary-upgrade mode, even with dumpData unset, we do not mask * out large objects. (Only large object definitions, comments and * other metadata should be generated in binary-upgrade mode, not the * actual data, but that need not concern us here.) @@ -3168,12 +3250,12 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) strncmp(te->tag, "LARGE OBJECT", 12) == 0) || (strcmp(te->desc, "SECURITY LABEL") == 0 && strncmp(te->tag, "LARGE OBJECT", 12) == 0)))) - res = res & REQ_SCHEMA; + res = res & (REQ_SCHEMA | REQ_STATS); } - /* Mask it if we only want data */ - if (ropt->dataOnly) - res = res & REQ_DATA; + /* Mask it if we don't want schema */ + if (!ropt->dumpSchema) + res = res & (REQ_DATA | REQ_STATS); return res; } @@ -3205,6 +3287,19 @@ _tocEntryRestorePass(TocEntry *te) strncmp(te->tag, "EVENT TRIGGER ", 14) == 0) return RESTORE_PASS_POST_ACL; + /* + * If statistics data is dependent on materialized view data, it must be + * deferred to RESTORE_PASS_POST_ACL. Those entries are already marked as + * SECTION_POST_DATA, and some other stats entries (e.g., index stats) + * will also be marked as SECTION_POST_DATA. Additionally, our lookahead + * code in fetchAttributeStats() assumes that we dump all statistics data + * entries in TOC order. To ensure this assumption holds, we move all + * statistics data entries in SECTION_POST_DATA to RESTORE_PASS_POST_ACL. + */ + if (strcmp(te->desc, "STATISTICS DATA") == 0 && + te->section == SECTION_POST_DATA) + return RESTORE_PASS_POST_ACL; + /* All else can be handled in the main pass. */ return RESTORE_PASS_MAIN; } @@ -3725,7 +3820,7 @@ _getObjectDescription(PQExpBuffer buf, const TocEntry *te) * will remain at default, until the matching ACL TOC entry is restored. */ static void -_printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) +_printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx) { RestoreOptions *ropt = AH->public.ropt; @@ -3744,16 +3839,10 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) /* Emit header comment for item */ if (!AH->noTocComments) { - const char *pfx; char *sanitized_name; char *sanitized_schema; char *sanitized_owner; - if (isData) - pfx = "Data for "; - else - pfx = ""; - ahprintf(AH, "--\n"); if (AH->public.verbose) { @@ -3799,7 +3888,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) /* * Actually print the definition. Normally we can just print the defn - * string if any, but we have three special cases: + * string if any, but we have four special cases: * * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump * versions put into CREATE SCHEMA. Don't mutate the variant for schema @@ -3812,6 +3901,11 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) * 3. ACL LARGE OBJECTS entries need special processing because they * contain only one copy of the ACL GRANT/REVOKE commands, which we must * apply to each large object listed in the associated BLOB METADATA. + * + * 4. Entries with a defnDumper need to call it to generate the + * definition. This is primarily intended to provide a way to save memory + * for objects that would otherwise need a lot of it (e.g., statistics + * data). */ if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0) @@ -3827,10 +3921,65 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData) { IssueACLPerBlob(AH, te); } - else + else if (te->defnLen && AH->format != archTar) + { + /* + * If defnLen is set, the defnDumper has already been called for this + * TOC entry. We don't normally expect a defnDumper to be called for + * a TOC entry a second time in _printTocEntry(), but there's an + * exception. The tar format first calls WriteToc(), which scans the + * entire TOC, and then it later calls RestoreArchive() to generate + * restore.sql, which scans the TOC again. There doesn't appear to be + * a good way to prevent a second defnDumper call in this case without + * storing the definition in memory, which defeats the purpose. This + * second defnDumper invocation should generate the same output as the + * first, but even if it doesn't, the worst-case scenario is that + * restore.sql might have different statistics data than the archive. + * + * In all other cases, encountering a TOC entry a second time in + * _printTocEntry() is unexpected, so we fail because one of our + * assumptions must no longer hold true. + * + * XXX This is a layering violation, but the alternative is an awkward + * and complicated callback infrastructure for this special case. This + * might be worth revisiting in the future. + */ + pg_fatal("unexpected TOC entry in _printTocEntry(): %d %s %s", + te->dumpId, te->desc, te->tag); + } + else if (te->defnDumper) { - if (te->defn && strlen(te->defn) > 0) - ahprintf(AH, "%s\n\n", te->defn); + char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te); + + te->defnLen = ahprintf(AH, "%s\n\n", defn); + pg_free(defn); + } + else if (te->defn && strlen(te->defn) > 0) + { + ahprintf(AH, "%s\n\n", te->defn); + + /* + * If the defn string contains multiple SQL commands, txn_size mode + * should count it as N actions not one. But rather than build a full + * SQL parser, approximate this by counting semicolons. One case + * where that tends to be badly fooled is function definitions, so + * ignore them. (restore_toc_entry will count one action anyway.) + */ + if (ropt->txn_size > 0 && + strcmp(te->desc, "FUNCTION") != 0 && + strcmp(te->desc, "PROCEDURE") != 0) + { + const char *p = te->defn; + int nsemis = 0; + + while ((p = strchr(p, ';')) != NULL) + { + nsemis++; + p++; + } + if (nsemis > 1) + AH->txnCount += nsemis - 1; + } } /* @@ -4298,7 +4447,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, if (next_work_item != NULL) { /* If not to be restored, don't waste time launching a worker */ - if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0) + if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0) { pg_log_info("skipping item %d %s %s", next_work_item->dumpId, @@ -4386,7 +4535,7 @@ restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list) /* * Now reconnect the single parent connection. */ - ConnectDatabase((Archive *) AH, &ropt->cparams, true); + ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true); /* re-establish fixed state */ _doSetFixedOutputState(AH); @@ -5003,7 +5152,7 @@ CloneArchive(ArchiveHandle *AH) * Connect our new clone object to the database, using the same connection * parameters used for the original connection. */ - ConnectDatabase((Archive *) clone, &clone->public.ropt->cparams, true); + ConnectDatabaseAhx((Archive *) clone, &clone->public.ropt->cparams, true); /* re-establish fixed state */ if (AH->mode == archModeRead) diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index ce5ed1dd395d6..365073b3eae45 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -209,7 +209,8 @@ typedef enum #define REQ_SCHEMA 0x01 /* want schema */ #define REQ_DATA 0x02 /* want data */ -#define REQ_SPECIAL 0x04 /* for special TOC entries */ +#define REQ_STATS 0x04 +#define REQ_SPECIAL 0x08 /* for special TOC entries */ struct _archiveHandle { @@ -340,6 +341,10 @@ struct _archiveHandle struct _tocEntry *lastErrorTE; }; + +typedef char *(*DefnDumperPtr) (Archive *AH, const void *userArg, const TocEntry *te); +typedef int (*DataDumperPtr) (Archive *AH, const void *userArg); + struct _tocEntry { struct _tocEntry *prev; @@ -367,6 +372,10 @@ struct _tocEntry const void *dataDumperArg; /* Arg for above routine */ void *formatData; /* TOC Entry data specific to file format */ + DefnDumperPtr defnDumper; /* routine to dump definition statement */ + const void *defnDumperArg; /* arg for above routine */ + size_t defnLen; /* length of dumped definition */ + /* working state while dumping/restoring */ pgoff_t dataLength; /* item's data size; 0 if none or unknown */ int reqs; /* do we need schema and/or data of object @@ -385,6 +394,7 @@ struct _tocEntry extern int parallel_restore(ArchiveHandle *AH, TocEntry *te); extern void on_exit_close_archive(Archive *AHX); +extern void replace_on_exit_close_archive(Archive *AHX); extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...) pg_attribute_printf(2, 3); @@ -406,6 +416,8 @@ typedef struct _archiveOpts int nDeps; DataDumperPtr dumpFn; const void *dumpArg; + DefnDumperPtr defnFn; + const void *defnArg; } ArchiveOpts; #define ARCHIVE_OPTS(...) &(ArchiveOpts){__VA_ARGS__} /* Called to add a TOC entry */ diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c index 55107b200581b..f7c3af56304ce 100644 --- a/src/bin/pg_dump/pg_backup_custom.c +++ b/src/bin/pg_dump/pg_backup_custom.c @@ -27,7 +27,6 @@ #include "common/file_utils.h" #include "compress_io.h" -#include "parallel.h" #include "pg_backup_utils.h" /*-------- @@ -138,7 +137,7 @@ InitArchiveFmt_Custom(ArchiveHandle *AH) /* Set up a private area. */ ctx = (lclContext *) pg_malloc0(sizeof(lclContext)); - AH->formatData = (void *) ctx; + AH->formatData = ctx; /* * Now open the file @@ -206,7 +205,7 @@ _ArchiveEntry(ArchiveHandle *AH, TocEntry *te) else ctx->dataState = K_OFFSET_NO_DATA; - te->formatData = (void *) ctx; + te->formatData = ctx; } /* @@ -242,7 +241,7 @@ _ReadExtraToc(ArchiveHandle *AH, TocEntry *te) if (ctx == NULL) { ctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); - te->formatData = (void *) ctx; + te->formatData = ctx; } ctx->dataState = ReadOffset(AH, &(ctx->dataPos)); @@ -756,9 +755,11 @@ _CloseArchive(ArchiveHandle *AH) * If possible, re-write the TOC in order to update the data offset * information. This is not essential, as pg_restore can cope in most * cases without it; but it can make pg_restore significantly faster - * in some situations (especially parallel restore). + * in some situations (especially parallel restore). We can skip this + * step if we're not dumping any data; there are no offsets to update + * in that case. */ - if (ctx->hasSeek && + if (ctx->hasSeek && AH->public.dopt->dumpData && fseeko(AH->FH, tpos, SEEK_SET) == 0) WriteToc(AH); } diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index a02841c405026..5c349279beb56 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -19,8 +19,7 @@ #include "common/connect.h" #include "common/string.h" -#include "dumputils.h" -#include "fe_utils/string_utils.h" +#include "connectdb.h" #include "parallel.h" #include "pg_backup_archiver.h" #include "pg_backup_db.h" @@ -39,7 +38,7 @@ _check_database_version(ArchiveHandle *AH) remoteversion_str = PQparameterStatus(AH->connection, "server_version"); remoteversion = PQserverVersion(AH->connection); if (remoteversion == 0 || !remoteversion_str) - pg_fatal("could not get server_version from libpq"); + pg_fatal("could not get \"server_version\" from libpq"); AH->public.remoteVersionStr = pg_strdup(remoteversion_str); AH->public.remoteVersion = remoteversion; @@ -88,9 +87,9 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname) * ArchiveHandle's connCancel, before closing old connection. Otherwise * an ill-timed SIGINT could try to access a dead connection. */ - AH->connection = NULL; /* dodge error check in ConnectDatabase */ + AH->connection = NULL; /* dodge error check in ConnectDatabaseAhx */ - ConnectDatabase((Archive *) AH, &ropt->cparams, true); + ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true); PQfinish(oldConn); } @@ -107,14 +106,13 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname) * username never does change, so one savedPassword is sufficient. */ void -ConnectDatabase(Archive *AHX, - const ConnParams *cparams, - bool isReconnect) +ConnectDatabaseAhx(Archive *AHX, + const ConnParams *cparams, + bool isReconnect) { ArchiveHandle *AH = (ArchiveHandle *) AHX; trivalue prompt_password; char *password; - bool new_pass; if (AH->connection) pg_fatal("already connected to a database"); @@ -127,69 +125,10 @@ ConnectDatabase(Archive *AHX, if (prompt_password == TRI_YES && password == NULL) password = simple_prompt("Password: ", false); - /* - * Start the connection. Loop until we have a password if requested by - * backend. - */ - do - { - const char *keywords[8]; - const char *values[8]; - int i = 0; - - /* - * If dbname is a connstring, its entries can override the other - * values obtained from cparams; but in turn, override_dbname can - * override the dbname component of it. - */ - keywords[i] = "host"; - values[i++] = cparams->pghost; - keywords[i] = "port"; - values[i++] = cparams->pgport; - keywords[i] = "user"; - values[i++] = cparams->username; - keywords[i] = "password"; - values[i++] = password; - keywords[i] = "dbname"; - values[i++] = cparams->dbname; - if (cparams->override_dbname) - { - keywords[i] = "dbname"; - values[i++] = cparams->override_dbname; - } - keywords[i] = "fallback_application_name"; - values[i++] = progname; - keywords[i] = NULL; - values[i++] = NULL; - Assert(i <= lengthof(keywords)); - - new_pass = false; - AH->connection = PQconnectdbParams(keywords, values, true); - - if (!AH->connection) - pg_fatal("could not connect to database"); - - if (PQstatus(AH->connection) == CONNECTION_BAD && - PQconnectionNeedsPassword(AH->connection) && - password == NULL && - prompt_password != TRI_NO) - { - PQfinish(AH->connection); - password = simple_prompt("Password: ", false); - new_pass = true; - } - } while (new_pass); - - /* check to see that the backend connection was successfully made */ - if (PQstatus(AH->connection) == CONNECTION_BAD) - { - if (isReconnect) - pg_fatal("reconnection failed: %s", - PQerrorMessage(AH->connection)); - else - pg_fatal("%s", - PQerrorMessage(AH->connection)); - } + AH->connection = ConnectDatabase(cparams->dbname, NULL, cparams->pghost, + cparams->pgport, cparams->username, + prompt_password, true, + progname, NULL, NULL, password, cparams->override_dbname); /* Start strict; later phases may override this. */ PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH, diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c index 7be8d5487d4b2..bc2a2fb479741 100644 --- a/src/bin/pg_dump/pg_backup_directory.c +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -19,7 +19,7 @@ * sync. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 2000, Philip Warner * @@ -41,6 +41,7 @@ #include "common/file_utils.h" #include "compress_io.h" +#include "dumputils.h" #include "parallel.h" #include "pg_backup_utils.h" @@ -140,7 +141,7 @@ InitArchiveFmt_Directory(ArchiveHandle *AH) /* Set up our private context */ ctx = (lclContext *) pg_malloc0(sizeof(lclContext)); - AH->formatData = (void *) ctx; + AH->formatData = ctx; ctx->dataFH = NULL; ctx->LOsTocFH = NULL; @@ -156,41 +157,8 @@ InitArchiveFmt_Directory(ArchiveHandle *AH) if (AH->mode == archModeWrite) { - struct stat st; - bool is_empty = false; - /* we accept an empty existing directory */ - if (stat(ctx->directory, &st) == 0 && S_ISDIR(st.st_mode)) - { - DIR *dir = opendir(ctx->directory); - - if (dir) - { - struct dirent *d; - - is_empty = true; - while (errno = 0, (d = readdir(dir))) - { - if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) - { - is_empty = false; - break; - } - } - - if (errno) - pg_fatal("could not read directory \"%s\": %m", - ctx->directory); - - if (closedir(dir)) - pg_fatal("could not close directory \"%s\": %m", - ctx->directory); - } - } - - if (!is_empty && mkdir(ctx->directory, 0700) < 0) - pg_fatal("could not create directory \"%s\": %m", - ctx->directory); + create_or_open_dir(ctx->directory); } else { /* Read Mode */ @@ -246,7 +214,7 @@ _ArchiveEntry(ArchiveHandle *AH, TocEntry *te) else tctx->filename = NULL; - te->formatData = (void *) tctx; + te->formatData = tctx; } /* @@ -285,7 +253,7 @@ _ReadExtraToc(ArchiveHandle *AH, TocEntry *te) if (tctx == NULL) { tctx = (lclTocEntry *) pg_malloc0(sizeof(lclTocEntry)); - te->formatData = (void *) tctx; + te->formatData = tctx; } tctx->filename = ReadStr(AH); @@ -444,10 +412,15 @@ _LoadLOs(ArchiveHandle *AH, TocEntry *te) /* * Note: before archive v16, there was always only one BLOBS TOC entry, - * now there can be multiple. We don't need to worry what version we are - * reading though, because tctx->filename should be correct either way. + * now there can be multiple. Furthermore, although the actual filename + * was always "blobs.toc" before v16, the value of tctx->filename did not + * match that before commit 548e50976 fixed it. For simplicity we assume + * it must be "blobs.toc" in all archives before v16. */ - setFilePath(AH, tocfname, tctx->filename); + if (AH->version < K_VERS_1_16) + setFilePath(AH, tocfname, "blobs.toc"); + else + setFilePath(AH, tocfname, tctx->filename); CFH = ctx->LOsTocFH = InitDiscoverCompressFileHandle(tocfname, PG_BINARY_R); @@ -780,7 +753,7 @@ _PrepParallelRestore(ArchiveHandle *AH) continue; /* We may ignore items not due to be restored */ - if ((te->reqs & REQ_DATA) == 0) + if ((te->reqs & (REQ_DATA | REQ_STATS)) == 0) continue; /* diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 41ee52b1d69cc..d94d0de2a5d17 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -152,7 +152,7 @@ InitArchiveFmt_Tar(ArchiveHandle *AH) * Set up some special context used in compressing data. */ ctx = pg_malloc0_object(lclContext); - AH->formatData = (void *) ctx; + AH->formatData = ctx; ctx->filePos = 0; ctx->isSpecialScript = 0; @@ -219,7 +219,7 @@ InitArchiveFmt_Tar(ArchiveHandle *AH) ctx->hasSeek = checkSeek(ctx->tarFH); - ctx->FH = (void *) tarOpen(AH, "toc.dat", 'r'); + ctx->FH = tarOpen(AH, "toc.dat", 'r'); ReadHead(AH); ReadToc(AH); tarClose(AH, ctx->FH); /* Nothing else in the file... */ @@ -247,7 +247,7 @@ _ArchiveEntry(ArchiveHandle *AH, TocEntry *te) ctx->filename = NULL; ctx->TH = NULL; } - te->formatData = (void *) ctx; + te->formatData = ctx; } static void @@ -269,7 +269,7 @@ _ReadExtraToc(ArchiveHandle *AH, TocEntry *te) if (ctx == NULL) { ctx = pg_malloc0_object(lclTocEntry); - te->formatData = (void *) ctx; + te->formatData = ctx; } ctx->filename = ReadStr(AH); @@ -826,7 +826,7 @@ _CloseArchive(ArchiveHandle *AH) savVerbose = AH->public.verbose; AH->public.verbose = 0; - RestoreArchive((Archive *) AH); + RestoreArchive((Archive *) AH, false); SetArchiveOptions((Archive *) AH, savDopt, savRopt); diff --git a/src/bin/pg_dump/pg_backup_utils.c b/src/bin/pg_dump/pg_backup_utils.c index a0045cf5e5885..79aec5f515825 100644 --- a/src/bin/pg_dump/pg_backup_utils.c +++ b/src/bin/pg_dump/pg_backup_utils.c @@ -4,7 +4,7 @@ * Utility routines shared by pg_dump and pg_restore * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_dump/pg_backup_utils.c @@ -13,7 +13,9 @@ */ #include "postgres_fe.h" +#ifdef WIN32 #include "parallel.h" +#endif #include "pg_backup_utils.h" /* Globals exported by this file */ diff --git a/src/bin/pg_dump/pg_backup_utils.h b/src/bin/pg_dump/pg_backup_utils.h index f2677839e3086..ba042016879d4 100644 --- a/src/bin/pg_dump/pg_backup_utils.h +++ b/src/bin/pg_dump/pg_backup_utils.h @@ -4,7 +4,7 @@ * Utility routines shared by pg_dump and pg_restore. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_dump/pg_backup_utils.h @@ -29,7 +29,7 @@ extern const char *progname; extern void set_dump_section(const char *arg, int *dumpSections); extern void on_exit_nicely(on_exit_nicely_callback function, void *arg); -extern void exit_nicely(int code) pg_attribute_noreturn(); +pg_noreturn extern void exit_nicely(int code); /* In pg_dump, we modify pg_fatal to call exit_nicely instead of exit */ #undef pg_fatal diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index b8b1888bd3387..a8f0309e8fc1e 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -4,7 +4,7 @@ * pg_dump is a utility for dumping out a postgres database * into a script file. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * pg_dump will read the system catalogs in a database and dump out a @@ -49,14 +49,14 @@ #include "catalog/pg_class_d.h" #include "catalog/pg_default_acl_d.h" #include "catalog/pg_largeobject_d.h" -#include "catalog/pg_largeobject_metadata_d.h" #include "catalog/pg_proc_d.h" -#include "catalog/pg_subscription.h" -#include "catalog/pg_trigger_d.h" +#include "catalog/pg_publication_d.h" +#include "catalog/pg_subscription_d.h" #include "catalog/pg_type_d.h" #include "common/connect.h" #include "common/int.h" #include "common/relpath.h" +#include "common/shortest_dec.h" #include "compress_io.h" #include "dumputils.h" #include "fe_utils/option_utils.h" @@ -104,6 +104,38 @@ typedef struct RelFileNumber toast_index_relfilenumber; /* toast table index filenode */ } BinaryUpgradeClassOidItem; +/* sequence types */ +typedef enum SeqType +{ + SEQTYPE_SMALLINT, + SEQTYPE_INTEGER, + SEQTYPE_BIGINT, +} SeqType; + +static const char *const SeqTypeNames[] = +{ + [SEQTYPE_SMALLINT] = "smallint", + [SEQTYPE_INTEGER] = "integer", + [SEQTYPE_BIGINT] = "bigint", +}; + +StaticAssertDecl(lengthof(SeqTypeNames) == (SEQTYPE_BIGINT + 1), + "array length mismatch"); + +typedef struct +{ + Oid oid; /* sequence OID */ + SeqType seqtype; /* data type of sequence */ + bool cycled; /* whether sequence cycles */ + int64 minv; /* minimum value */ + int64 maxv; /* maximum value */ + int64 startv; /* start value */ + int64 incby; /* increment value */ + int64 cache; /* cache size */ + int64 last_value; /* last value of sequence */ + bool is_called; /* whether nextval advances before returning */ +} SequenceItem; + typedef enum OidOptions { zeroIsError = 1, @@ -173,6 +205,13 @@ static int nseclabels = 0; static BinaryUpgradeClassOidItem *binaryUpgradeClassOids = NULL; static int nbinaryUpgradeClassOids = 0; +/* sorted table of sequences */ +static SequenceItem *sequences = NULL; +static int nsequences = 0; + +/* Maximum number of relations to fetch in a fetchAttributeStats() call. */ +#define MAX_ATTR_STATS_RELS 64 + /* * The default number of rows per INSERT when * --inserts is specified without --rows-per-insert @@ -270,6 +309,7 @@ static void dumpTable(Archive *fout, const TableInfo *tbinfo); static void dumpTableSchema(Archive *fout, const TableInfo *tbinfo); static void dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo); static void dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo); +static void collectSequences(Archive *fout); static void dumpSequence(Archive *fout, const TableInfo *tbinfo); static void dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo); static void dumpIndex(Archive *fout, const IndxInfo *indxinfo); @@ -308,6 +348,12 @@ static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, c static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo); static void buildMatViewRefreshDependencies(Archive *fout); static void getTableDataFKConstraints(void); +static void determineNotNullFlags(Archive *fout, PGresult *res, int r, + TableInfo *tbinfo, int j, + int i_notnull_name, int i_notnull_invalidoid, + int i_notnull_noinherit, + int i_notnull_islocal, + PQExpBuffer *invalidnotnulloids); static char *format_function_arguments(const FuncInfo *finfo, const char *funcargs, bool is_agg); static char *format_function_signature(Archive *fout, @@ -353,6 +399,7 @@ static bool nonemptyReloptions(const char *reloptions); static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions, const char *prefix, Archive *fout); static char *get_synchronized_snapshot(Archive *fout); +static void set_restrict_relation_kind(Archive *AH, const char *value); static void setupDumpWorker(Archive *AH); static TableInfo *getRootTableInfo(const TableInfo *tbinfo); static bool forcePartitionRootLoad(const TableInfo *tbinfo); @@ -388,6 +435,15 @@ main(int argc, char **argv) char *error_detail = NULL; bool user_compression_defined = false; DataDirSyncMethod sync_method = DATA_DIR_SYNC_METHOD_FSYNC; + bool data_only = false; + bool schema_only = false; + bool statistics_only = false; + bool with_data = false; + bool with_schema = false; + bool with_statistics = false; + bool no_data = false; + bool no_schema = false; + bool no_statistics = false; static DumpOptions dopt; @@ -447,15 +503,23 @@ main(int argc, char **argv) {"section", required_argument, NULL, 5}, {"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1}, {"snapshot", required_argument, NULL, 6}, + {"statistics-only", no_argument, NULL, 18}, {"strict-names", no_argument, &strict_names, 1}, {"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1}, {"no-comments", no_argument, &dopt.no_comments, 1}, + {"no-data", no_argument, NULL, 19}, + {"no-policies", no_argument, &dopt.no_policies, 1}, {"no-publications", no_argument, &dopt.no_publications, 1}, + {"no-schema", no_argument, NULL, 20}, {"no-security-labels", no_argument, &dopt.no_security_labels, 1}, + {"no-statistics", no_argument, NULL, 21}, {"no-subscriptions", no_argument, &dopt.no_subscriptions, 1}, {"no-toast-compression", no_argument, &dopt.no_toast_compression, 1}, {"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1}, {"no-sync", no_argument, NULL, 7}, + {"with-data", no_argument, NULL, 22}, + {"with-schema", no_argument, NULL, 23}, + {"with-statistics", no_argument, NULL, 24}, {"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1}, {"rows-per-insert", required_argument, NULL, 10}, {"include-foreign-data", required_argument, NULL, 11}, @@ -465,6 +529,7 @@ main(int argc, char **argv) {"sync-method", required_argument, NULL, 15}, {"filter", required_argument, NULL, 16}, {"exclude-extension", required_argument, NULL, 17}, + {"sequence-data", no_argument, &dopt.sequence_data, 1}, {NULL, 0, NULL, 0} }; @@ -497,13 +562,13 @@ main(int argc, char **argv) InitDumpOptions(&dopt); - while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:", + while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxXZ:", long_options, &optindex)) != -1) { switch (c) { case 'a': /* Dump data only */ - dopt.dataOnly = true; + data_only = true; break; case 'b': /* Dump LOs */ @@ -576,7 +641,7 @@ main(int argc, char **argv) break; case 's': /* dump schema only */ - dopt.schemaOnly = true; + schema_only = true; break; case 'S': /* Username for superuser in plain text output */ @@ -705,6 +770,34 @@ main(int argc, char **argv) optarg); break; + case 18: + statistics_only = true; + break; + + case 19: + no_data = true; + break; + + case 20: + no_schema = true; + break; + + case 21: + no_statistics = true; + break; + + case 22: + with_data = true; + break; + + case 23: + with_schema = true; + break; + + case 24: + with_statistics = true; + break; + default: /* getopt_long already emitted a complaint */ pg_log_error_hint("Try \"%s --help\" for more information.", progname); @@ -732,29 +825,57 @@ main(int argc, char **argv) if (dopt.column_inserts && dopt.dump_inserts == 0) dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT; - /* - * Binary upgrade mode implies dumping sequence data even in schema-only - * mode. This is not exposed as a separate option, but kept separate - * internally for clarity. - */ - if (dopt.binary_upgrade) - dopt.sequence_data = 1; - - if (dopt.dataOnly && dopt.schemaOnly) + /* reject conflicting "-only" options */ + if (data_only && schema_only) pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together"); - - if (dopt.schemaOnly && foreign_servers_include_patterns.head != NULL) + if (schema_only && statistics_only) + pg_fatal("options -s/--schema-only and --statistics-only cannot be used together"); + if (data_only && statistics_only) + pg_fatal("options -a/--data-only and --statistics-only cannot be used together"); + + /* reject conflicting "-only" and "no-" options */ + if (data_only && no_data) + pg_fatal("options -a/--data-only and --no-data cannot be used together"); + if (schema_only && no_schema) + pg_fatal("options -s/--schema-only and --no-schema cannot be used together"); + if (statistics_only && no_statistics) + pg_fatal("options --statistics-only and --no-statistics cannot be used together"); + + /* reject conflicting "with-" and "no-" options */ + if (with_data && no_data) + pg_fatal("options --with-data and --no-data cannot be used together"); + if (with_schema && no_schema) + pg_fatal("options --with-schema and --no-schema cannot be used together"); + if (with_statistics && no_statistics) + pg_fatal("options --with-statistics and --no-statistics cannot be used together"); + + if (schema_only && foreign_servers_include_patterns.head != NULL) pg_fatal("options -s/--schema-only and --include-foreign-data cannot be used together"); if (numWorkers > 1 && foreign_servers_include_patterns.head != NULL) pg_fatal("option --include-foreign-data is not supported with parallel backup"); - if (dopt.dataOnly && dopt.outputClean) + if (data_only && dopt.outputClean) pg_fatal("options -c/--clean and -a/--data-only cannot be used together"); if (dopt.if_exists && !dopt.outputClean) pg_fatal("option --if-exists requires option -c/--clean"); + /* + * Set derivative flags. An "-only" option may be overridden by an + * explicit "with-" option; e.g. "--schema-only --with-statistics" will + * include schema and statistics. Other ambiguous or nonsensical + * combinations, e.g. "--schema-only --no-schema", will have already + * caused an error in one of the checks above. + */ + dopt.dumpData = ((dopt.dumpData && !schema_only && !statistics_only) || + (data_only || with_data)) && !no_data; + dopt.dumpSchema = ((dopt.dumpSchema && !data_only && !statistics_only) || + (schema_only || with_schema)) && !no_schema; + dopt.dumpStatistics = ((dopt.dumpStatistics && !schema_only && !data_only) || + (statistics_only || with_statistics)) && !no_statistics; + + /* * --inserts are already implied above if --column-inserts or * --rows-per-insert were specified. @@ -850,7 +971,7 @@ main(int argc, char **argv) * Open the database using the Archiver, so it knows about it. Errors mean * death. */ - ConnectDatabase(fout, &dopt.cparams, false); + ConnectDatabaseAhx(fout, &dopt.cparams, false); setup_connection(fout, dumpencoding, dumpsnapshot, use_role); /* @@ -937,7 +1058,7 @@ main(int argc, char **argv) * -s means "schema only" and LOs are data, not schema, so we never * include LOs when -s is used. */ - if (dopt.include_everything && !dopt.schemaOnly && !dopt.dontOutputLOs) + if (dopt.include_everything && dopt.dumpData && !dopt.dontOutputLOs) dopt.outputLOs = true; /* @@ -951,15 +1072,15 @@ main(int argc, char **argv) */ tblinfo = getSchemaData(fout, &numTables); - if (!dopt.schemaOnly) + if (dopt.dumpData) { getTableData(&dopt, tblinfo, numTables, 0); buildMatViewRefreshDependencies(fout); - if (dopt.dataOnly) + if (!dopt.dumpSchema) getTableDataFKConstraints(); } - if (dopt.schemaOnly && dopt.sequence_data) + if (!dopt.dumpData && dopt.sequence_data) getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE); /* @@ -992,6 +1113,9 @@ main(int argc, char **argv) if (dopt.binary_upgrade) collectBinaryUpgradeClassOids(fout); + /* Collect sequence information. */ + collectSequences(fout); + /* Lastly, create dummy objects to represent the section boundaries */ boundaryObjs = createBoundaryObjects(); @@ -1048,8 +1172,9 @@ main(int argc, char **argv) ropt->cparams.username = dopt.cparams.username ? pg_strdup(dopt.cparams.username) : NULL; ropt->cparams.promptPassword = dopt.cparams.promptPassword; ropt->dropSchema = dopt.outputClean; - ropt->dataOnly = dopt.dataOnly; - ropt->schemaOnly = dopt.schemaOnly; + ropt->dumpData = dopt.dumpData; + ropt->dumpSchema = dopt.dumpSchema; + ropt->dumpStatistics = dopt.dumpStatistics; ropt->if_exists = dopt.if_exists; ropt->column_inserts = dopt.column_inserts; ropt->dumpSections = dopt.dumpSections; @@ -1064,6 +1189,7 @@ main(int argc, char **argv) ropt->disable_dollar_quoting = dopt.disable_dollar_quoting; ropt->dump_inserts = dopt.dump_inserts; ropt->no_comments = dopt.no_comments; + ropt->no_policies = dopt.no_policies; ropt->no_publications = dopt.no_publications; ropt->no_security_labels = dopt.no_security_labels; ropt->no_subscriptions = dopt.no_subscriptions; @@ -1098,7 +1224,7 @@ main(int argc, char **argv) * right now. */ if (plainText) - RestoreArchive(fout); + RestoreArchive(fout, false); CloseArchive(fout); @@ -1128,7 +1254,7 @@ help(const char *progname) printf(_(" -?, --help show this help, then exit\n")); printf(_("\nOptions controlling the output content:\n")); - printf(_(" -a, --data-only dump only the data, not the schema\n")); + printf(_(" -a, --data-only dump only the data, not the schema or statistics\n")); printf(_(" -b, --large-objects include large objects in dump\n")); printf(_(" --blobs (same as --large-objects, deprecated)\n")); printf(_(" -B, --no-large-objects exclude large objects in dump\n")); @@ -1141,7 +1267,7 @@ help(const char *progname) printf(_(" -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n")); printf(_(" -O, --no-owner skip restoration of object ownership in\n" " plain-text format\n")); - printf(_(" -s, --schema-only dump only the schema, no data\n")); + printf(_(" -s, --schema-only dump only the schema, no data or statistics\n")); printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n")); printf(_(" -t, --table=PATTERN dump only the specified table(s)\n")); printf(_(" -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n")); @@ -1169,9 +1295,13 @@ help(const char *progname) " servers matching PATTERN\n")); printf(_(" --inserts dump data as INSERT commands, rather than COPY\n")); printf(_(" --load-via-partition-root load partitions via the root table\n")); - printf(_(" --no-comments do not dump comments\n")); + printf(_(" --no-comments do not dump comment commands\n")); + printf(_(" --no-data do not dump data\n")); + printf(_(" --no-policies do not dump row security policies\n")); printf(_(" --no-publications do not dump publications\n")); + printf(_(" --no-schema do not dump schema\n")); printf(_(" --no-security-labels do not dump security label assignments\n")); + printf(_(" --no-statistics do not dump statistics\n")); printf(_(" --no-subscriptions do not dump subscriptions\n")); printf(_(" --no-table-access-method do not dump table access methods\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n")); @@ -1181,8 +1311,10 @@ help(const char *progname) printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n")); printf(_(" --section=SECTION dump named section (pre-data, data, or post-data)\n")); + printf(_(" --sequence-data include sequence data in dump\n")); printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n")); printf(_(" --snapshot=SNAPSHOT use given snapshot for the dump\n")); + printf(_(" --statistics-only dump only the statistics, not schema or data\n")); printf(_(" --strict-names require table and/or schema include patterns to\n" " match at least one entity each\n")); printf(_(" --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1190,6 +1322,9 @@ help(const char *progname) printf(_(" --use-set-session-authorization\n" " use SET SESSION AUTHORIZATION commands instead of\n" " ALTER OWNER commands to set ownership\n")); + printf(_(" --with-data dump the data\n")); + printf(_(" --with-schema dump the schema\n")); + printf(_(" --with-statistics dump the statistics\n")); printf(_("\nConnection options:\n")); printf(_(" -d, --dbname=DBNAME database to dump\n")); @@ -1231,6 +1366,7 @@ setup_connection(Archive *AH, const char *dumpencoding, * we know how to escape strings. */ AH->encoding = PQclientEncoding(conn); + setFmtEncoding(AH->encoding); std_strings = PQparameterStatus(conn, "standard_conforming_strings"); AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0); @@ -1314,6 +1450,13 @@ setup_connection(Archive *AH, const char *dumpencoding, ExecuteSqlStatement(AH, "SET row_security = off"); } + /* + * For security reasons, we restrict the expansion of non-system views and + * access to foreign tables during the pg_dump process. This restriction + * is adjusted when dumping foreign table data. + */ + set_restrict_relation_kind(AH, "view, foreign-table"); + /* * Initialize prepared-query state to "nothing prepared". We do this here * so that a parallel dump worker will have its own state. @@ -1634,7 +1777,7 @@ expand_table_name_patterns(Archive *fout, */ if (with_child_tables) { - appendPQExpBuffer(query, "WITH RECURSIVE partition_tree (relid) AS (\n"); + appendPQExpBufferStr(query, "WITH RECURSIVE partition_tree (relid) AS (\n"); } appendPQExpBuffer(query, @@ -1661,13 +1804,13 @@ expand_table_name_patterns(Archive *fout, if (with_child_tables) { - appendPQExpBuffer(query, "UNION" - "\nSELECT i.inhrelid" - "\nFROM partition_tree p" - "\n JOIN pg_catalog.pg_inherits i" - "\n ON p.relid OPERATOR(pg_catalog.=) i.inhparent" - "\n)" - "\nSELECT relid FROM partition_tree"); + appendPQExpBufferStr(query, "UNION" + "\nSELECT i.inhrelid" + "\nFROM partition_tree p" + "\n JOIN pg_catalog.pg_inherits i" + "\n ON p.relid OPERATOR(pg_catalog.=) i.inhparent" + "\n)" + "\nSELECT relid FROM partition_tree"); } ExecuteSqlStatement(fout, "RESET search_path"); @@ -1937,7 +2080,7 @@ selectDumpableType(TypeInfo *tyinfo, Archive *fout) * Mark a default ACL as to be dumped or not * * For per-schema default ACLs, dump if the schema is to be dumped. - * Otherwise dump if we are dumping "everything". Note that dataOnly + * Otherwise dump if we are dumping "everything". Note that dumpSchema * and aclsSkip are checked separately. */ static void @@ -2182,6 +2325,10 @@ dumpTableData_copy(Archive *fout, const void *dcontext) */ if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE) { + /* Temporary allows to access to foreign tables to dump data */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE) + set_restrict_relation_kind(fout, "view"); + appendPQExpBufferStr(q, "COPY (SELECT "); /* klugery to get rid of parens in column list */ if (strlen(column_list) > 2) @@ -2293,6 +2440,11 @@ dumpTableData_copy(Archive *fout, const void *dcontext) classname); destroyPQExpBuffer(q); + + /* Revert back the setting */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE) + set_restrict_relation_kind(fout, "view, foreign-table"); + return 1; } @@ -2319,6 +2471,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext) int rows_per_statement = dopt->dump_inserts; int rows_this_statement = 0; + /* Temporary allows to access to foreign tables to dump data */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE) + set_restrict_relation_kind(fout, "view"); + /* * If we're going to emit INSERTs with column names, the most efficient * way to deal with generated columns is to exclude them entirely. For @@ -2558,6 +2714,10 @@ dumpTableData_insert(Archive *fout, const void *dcontext) destroyPQExpBuffer(insertStmt); free(attgenerated); + /* Revert back the setting */ + if (tbinfo->relkind == RELKIND_FOREIGN_TABLE) + set_restrict_relation_kind(fout, "view, foreign-table"); + return 1; } @@ -2847,6 +3007,19 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo) tbinfo->dataObj = tdinfo; + /* + * Materialized view statistics must be restored after the data, because + * REFRESH MATERIALIZED VIEW replaces the storage and resets the stats. + * + * The dependency is added here because the statistics objects are created + * first. + */ + if (tbinfo->relkind == RELKIND_MATVIEW && tbinfo->stats != NULL) + { + tbinfo->stats->section = SECTION_POST_DATA; + addObjectDependency(&tbinfo->stats->dobj, tdinfo->dobj.dumpId); + } + /* Make sure that we'll collect per-column info for this table. */ tbinfo->interesting = true; } @@ -3918,6 +4091,7 @@ dumpLOs(Archive *fout, const void *arg) void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables) { + DumpOptions *dopt = fout->dopt; PQExpBuffer query; PQExpBuffer tbloids; PGresult *res; @@ -3939,6 +4113,10 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables) if (fout->remoteVersion < 90500) return; + /* Skip if --no-policies was specified */ + if (dopt->no_policies) + return; + query = createPQExpBuffer(); tbloids = createPQExpBuffer(); @@ -4094,8 +4272,8 @@ dumpPolicy(Archive *fout, const PolicyInfo *polinfo) const char *cmd; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* @@ -4217,6 +4395,7 @@ getPublications(Archive *fout) int i_pubdelete; int i_pubtruncate; int i_pubviaroot; + int i_pubgencols; int i, ntups; @@ -4225,32 +4404,35 @@ getPublications(Archive *fout) query = createPQExpBuffer(); - resetPQExpBuffer(query); - /* Get the publications. */ + appendPQExpBufferStr(query, "SELECT p.tableoid, p.oid, p.pubname, " + "p.pubowner, p.puballtables, p.pubinsert, " + "p.pubupdate, p.pubdelete, "); + + if (fout->remoteVersion >= 110000) + appendPQExpBufferStr(query, "p.pubtruncate, "); + else + appendPQExpBufferStr(query, "false AS pubtruncate, "); + if (fout->remoteVersion >= 130000) - appendPQExpBufferStr(query, - "SELECT p.tableoid, p.oid, p.pubname, " - "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot " - "FROM pg_publication p"); - else if (fout->remoteVersion >= 110000) - appendPQExpBufferStr(query, - "SELECT p.tableoid, p.oid, p.pubname, " - "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot " - "FROM pg_publication p"); + appendPQExpBufferStr(query, "p.pubviaroot, "); else - appendPQExpBufferStr(query, - "SELECT p.tableoid, p.oid, p.pubname, " - "p.pubowner, " - "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot " - "FROM pg_publication p"); + appendPQExpBufferStr(query, "false AS pubviaroot, "); + + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(query, "p.pubgencols "); + else + appendPQExpBuffer(query, "'%c' AS pubgencols ", PUBLISH_GENCOLS_NONE); + + appendPQExpBufferStr(query, "FROM pg_publication p"); res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); ntups = PQntuples(res); + if (ntups == 0) + goto cleanup; + i_tableoid = PQfnumber(res, "tableoid"); i_oid = PQfnumber(res, "oid"); i_pubname = PQfnumber(res, "pubname"); @@ -4261,6 +4443,7 @@ getPublications(Archive *fout) i_pubdelete = PQfnumber(res, "pubdelete"); i_pubtruncate = PQfnumber(res, "pubtruncate"); i_pubviaroot = PQfnumber(res, "pubviaroot"); + i_pubgencols = PQfnumber(res, "pubgencols"); pubinfo = pg_malloc(ntups * sizeof(PublicationInfo)); @@ -4285,10 +4468,14 @@ getPublications(Archive *fout) (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0); pubinfo[i].pubviaroot = (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0); + pubinfo[i].pubgencols_type = + *(PQgetvalue(res, i, i_pubgencols)); /* Decide whether we want to dump it */ selectDumpableObject(&(pubinfo[i].dobj), fout); } + +cleanup: PQclear(res); destroyPQExpBuffer(query); @@ -4307,8 +4494,8 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo) char *qpubname; bool first = true; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; delq = createPQExpBuffer(); @@ -4364,6 +4551,9 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo) if (pubinfo->pubviaroot) appendPQExpBufferStr(query, ", publish_via_partition_root = true"); + if (pubinfo->pubgencols_type == PUBLISH_GENCOLS_STORED) + appendPQExpBufferStr(query, ", publish_generated_columns = stored"); + appendPQExpBufferStr(query, ");\n"); if (pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) @@ -4449,13 +4639,6 @@ getPublicationNamespaces(Archive *fout) if (nspinfo == NULL) continue; - /* - * We always dump publication namespaces unless the corresponding - * namespace is excluded from the dump. - */ - if (nspinfo->dobj.dump == DUMP_COMPONENT_NONE) - continue; - /* OK, make a DumpableObject for this relationship */ pubsinfo[j].dobj.objType = DO_PUBLICATION_TABLE_IN_SCHEMA; pubsinfo[j].dobj.catId.tableoid = @@ -4555,13 +4738,6 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) if (tbinfo == NULL) continue; - /* - * Ignore publication membership of tables whose definitions are not - * to be dumped. - */ - if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) - continue; - /* OK, make a DumpableObject for this relationship */ pubrinfo[j].dobj.objType = DO_PUBLICATION_REL; pubrinfo[j].dobj.catId.tableoid = @@ -4595,6 +4771,8 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables) appendPQExpBufferStr(attribs, fmtId(attnames[k])); } pubrinfo[j].pubrattrs = attribs->data; + free(attribs); /* but not attribs->data */ + free(attnames); } else pubrinfo[j].pubrattrs = NULL; @@ -4622,8 +4800,8 @@ dumpPublicationNamespace(Archive *fout, const PublicationSchemaInfo *pubsinfo) PQExpBuffer query; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; tag = psprintf("%s %s", pubinfo->dobj.name, schemainfo->dobj.name); @@ -4665,8 +4843,8 @@ dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo) PQExpBuffer query; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name); @@ -4731,6 +4909,28 @@ is_superuser(Archive *fout) return false; } +/* + * Set the given value to restrict_nonsystem_relation_kind value. Since + * restrict_nonsystem_relation_kind is introduced in minor version releases, + * the setting query is effective only where available. + */ +static void +set_restrict_relation_kind(Archive *AH, const char *value) +{ + PQExpBuffer query = createPQExpBuffer(); + PGresult *res; + + appendPQExpBuffer(query, + "SELECT set_config(name, '%s', false) " + "FROM pg_settings " + "WHERE name = 'restrict_nonsystem_relation_kind'", + value); + res = ExecuteSqlQuery(AH, query->data, PGRES_TUPLES_OK); + + PQclear(res); + destroyPQExpBuffer(query); +} + /* * getSubscriptions * get information about subscriptions @@ -4834,8 +5034,8 @@ getSubscriptions(Archive *fout) appendPQExpBufferStr(query, " s.subfailover\n"); else - appendPQExpBuffer(query, - " false AS subfailover\n"); + appendPQExpBufferStr(query, + " false AS subfailover\n"); appendPQExpBufferStr(query, "FROM pg_subscription s\n"); @@ -4861,20 +5061,20 @@ getSubscriptions(Archive *fout) i_oid = PQfnumber(res, "oid"); i_subname = PQfnumber(res, "subname"); i_subowner = PQfnumber(res, "subowner"); + i_subenabled = PQfnumber(res, "subenabled"); i_subbinary = PQfnumber(res, "subbinary"); i_substream = PQfnumber(res, "substream"); i_subtwophasestate = PQfnumber(res, "subtwophasestate"); i_subdisableonerr = PQfnumber(res, "subdisableonerr"); i_subpasswordrequired = PQfnumber(res, "subpasswordrequired"); i_subrunasowner = PQfnumber(res, "subrunasowner"); + i_subfailover = PQfnumber(res, "subfailover"); i_subconninfo = PQfnumber(res, "subconninfo"); i_subslotname = PQfnumber(res, "subslotname"); i_subsynccommit = PQfnumber(res, "subsynccommit"); i_subpublications = PQfnumber(res, "subpublications"); i_suborigin = PQfnumber(res, "suborigin"); i_suboriginremotelsn = PQfnumber(res, "suboriginremotelsn"); - i_subenabled = PQfnumber(res, "subenabled"); - i_subfailover = PQfnumber(res, "subfailover"); subinfo = pg_malloc(ntups * sizeof(SubscriptionInfo)); @@ -4888,18 +5088,20 @@ getSubscriptions(Archive *fout) subinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_subname)); subinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_subowner)); + subinfo[i].subenabled = + (strcmp(PQgetvalue(res, i, i_subenabled), "t") == 0); subinfo[i].subbinary = - pg_strdup(PQgetvalue(res, i, i_subbinary)); - subinfo[i].substream = - pg_strdup(PQgetvalue(res, i, i_substream)); - subinfo[i].subtwophasestate = - pg_strdup(PQgetvalue(res, i, i_subtwophasestate)); + (strcmp(PQgetvalue(res, i, i_subbinary), "t") == 0); + subinfo[i].substream = *(PQgetvalue(res, i, i_substream)); + subinfo[i].subtwophasestate = *(PQgetvalue(res, i, i_subtwophasestate)); subinfo[i].subdisableonerr = - pg_strdup(PQgetvalue(res, i, i_subdisableonerr)); + (strcmp(PQgetvalue(res, i, i_subdisableonerr), "t") == 0); subinfo[i].subpasswordrequired = - pg_strdup(PQgetvalue(res, i, i_subpasswordrequired)); + (strcmp(PQgetvalue(res, i, i_subpasswordrequired), "t") == 0); subinfo[i].subrunasowner = - pg_strdup(PQgetvalue(res, i, i_subrunasowner)); + (strcmp(PQgetvalue(res, i, i_subrunasowner), "t") == 0); + subinfo[i].subfailover = + (strcmp(PQgetvalue(res, i, i_subfailover), "t") == 0); subinfo[i].subconninfo = pg_strdup(PQgetvalue(res, i, i_subconninfo)); if (PQgetisnull(res, i, i_subslotname)) @@ -4917,10 +5119,6 @@ getSubscriptions(Archive *fout) else subinfo[i].suboriginremotelsn = pg_strdup(PQgetvalue(res, i, i_suboriginremotelsn)); - subinfo[i].subenabled = - pg_strdup(PQgetvalue(res, i, i_subenabled)); - subinfo[i].subfailover = - pg_strdup(PQgetvalue(res, i, i_subfailover)); /* Decide whether we want to dump it */ selectDumpableObject(&(subinfo[i].dobj), fout); @@ -5029,8 +5227,8 @@ dumpSubscriptionTable(Archive *fout, const SubRelInfo *subrinfo) PQExpBuffer query; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; Assert(fout->dopt->binary_upgrade && fout->remoteVersion >= 170000); @@ -5059,7 +5257,7 @@ dumpSubscriptionTable(Archive *fout, const SubRelInfo *subrinfo) if (subrinfo->srsublsn && subrinfo->srsublsn[0] != '\0') appendPQExpBuffer(query, ", '%s'", subrinfo->srsublsn); else - appendPQExpBuffer(query, ", NULL"); + appendPQExpBufferStr(query, ", NULL"); appendPQExpBufferStr(query, ");\n"); } @@ -5101,10 +5299,9 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) char **pubnames = NULL; int npubnames = 0; int i; - char two_phase_disabled[] = {LOGICALREP_TWOPHASE_STATE_DISABLED, '\0'}; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; delq = createPQExpBuffer(); @@ -5138,27 +5335,29 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) else appendPQExpBufferStr(query, "NONE"); - if (strcmp(subinfo->subbinary, "t") == 0) + if (subinfo->subbinary) appendPQExpBufferStr(query, ", binary = true"); - if (strcmp(subinfo->substream, "t") == 0) + if (subinfo->substream == LOGICALREP_STREAM_ON) appendPQExpBufferStr(query, ", streaming = on"); - else if (strcmp(subinfo->substream, "p") == 0) + else if (subinfo->substream == LOGICALREP_STREAM_PARALLEL) appendPQExpBufferStr(query, ", streaming = parallel"); + else + appendPQExpBufferStr(query, ", streaming = off"); - if (strcmp(subinfo->subtwophasestate, two_phase_disabled) != 0) + if (subinfo->subtwophasestate != LOGICALREP_TWOPHASE_STATE_DISABLED) appendPQExpBufferStr(query, ", two_phase = on"); - if (strcmp(subinfo->subdisableonerr, "t") == 0) + if (subinfo->subdisableonerr) appendPQExpBufferStr(query, ", disable_on_error = true"); - if (strcmp(subinfo->subpasswordrequired, "t") != 0) - appendPQExpBuffer(query, ", password_required = false"); + if (!subinfo->subpasswordrequired) + appendPQExpBufferStr(query, ", password_required = false"); - if (strcmp(subinfo->subrunasowner, "t") == 0) + if (subinfo->subrunasowner) appendPQExpBufferStr(query, ", run_as_owner = true"); - if (strcmp(subinfo->subfailover, "t") == 0) + if (subinfo->subfailover) appendPQExpBufferStr(query, ", failover = true"); if (strcmp(subinfo->subsynccommit, "off") != 0) @@ -5194,7 +5393,7 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) appendPQExpBuffer(query, ", '%s');\n", subinfo->suboriginremotelsn); } - if (strcmp(subinfo->subenabled, "t") == 0) + if (subinfo->subenabled) { /* * Enable the subscription to allow the replication to continue @@ -5325,23 +5524,18 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout, Oid pg_type_array_oid; Oid pg_type_multirange_oid; Oid pg_type_multirange_array_oid; + TypeInfo *tinfo; appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n"); appendPQExpBuffer(upgrade_buffer, "SELECT pg_catalog.binary_upgrade_set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n", pg_type_oid); - appendPQExpBuffer(upgrade_query, - "SELECT typarray " - "FROM pg_catalog.pg_type " - "WHERE oid = '%u'::pg_catalog.oid;", - pg_type_oid); - - res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); - - pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray"))); - - PQclear(res); + tinfo = findTypeByOid(pg_type_oid); + if (tinfo) + pg_type_array_oid = tinfo->typarray; + else + pg_type_array_oid = InvalidOid; if (!OidIsValid(pg_type_array_oid) && force_array_type) pg_type_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query); @@ -5737,7 +5931,7 @@ getExtensions(Archive *fout, int *numExtensions) int ntups; int i; PQExpBuffer query; - ExtensionInfo *extinfo; + ExtensionInfo *extinfo = NULL; int i_tableoid; int i_oid; int i_extname; @@ -5757,6 +5951,8 @@ getExtensions(Archive *fout, int *numExtensions) res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); ntups = PQntuples(res); + if (ntups == 0) + goto cleanup; extinfo = (ExtensionInfo *) pg_malloc(ntups * sizeof(ExtensionInfo)); @@ -5786,6 +5982,7 @@ getExtensions(Archive *fout, int *numExtensions) selectDumpableExtension(&(extinfo[i]), dopt); } +cleanup: PQclear(res); destroyPQExpBuffer(query); @@ -5823,6 +6020,7 @@ getTypes(Archive *fout) int i_typtype; int i_typisdefined; int i_isarray; + int i_typarray; /* * we include even the built-in types because those may be used as array @@ -5843,7 +6041,7 @@ getTypes(Archive *fout) "typnamespace, typacl, " "acldefault('T', typowner) AS acldefault, " "typowner, " - "typelem, typrelid, " + "typelem, typrelid, typarray, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" " "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, " "typtype, typisdefined, " @@ -5870,6 +6068,7 @@ getTypes(Archive *fout) i_typtype = PQfnumber(res, "typtype"); i_typisdefined = PQfnumber(res, "typisdefined"); i_isarray = PQfnumber(res, "isarray"); + i_typarray = PQfnumber(res, "typarray"); for (i = 0; i < ntups; i++) { @@ -5902,6 +6101,8 @@ getTypes(Archive *fout) else tyinfo[i].isArray = false; + tyinfo[i].typarray = atooid(PQgetvalue(res, i, i_typarray)); + if (tyinfo[i].typtype == TYPTYPE_MULTIRANGE) tyinfo[i].isMultirange = true; else @@ -6669,6 +6870,83 @@ getFuncs(Archive *fout) destroyPQExpBuffer(query); } +/* + * getRelationStatistics + * register the statistics object as a dependent of the relation. + * + * reltuples is passed as a string to avoid complexities in converting from/to + * floating point. + */ +static RelStatsInfo * +getRelationStatistics(Archive *fout, DumpableObject *rel, int32 relpages, + char *reltuples, int32 relallvisible, + int32 relallfrozen, char relkind, + char **indAttNames, int nindAttNames) +{ + if (!fout->dopt->dumpStatistics) + return NULL; + + if ((relkind == RELKIND_RELATION) || + (relkind == RELKIND_PARTITIONED_TABLE) || + (relkind == RELKIND_INDEX) || + (relkind == RELKIND_PARTITIONED_INDEX) || + (relkind == RELKIND_MATVIEW || + relkind == RELKIND_FOREIGN_TABLE)) + { + RelStatsInfo *info = pg_malloc0(sizeof(RelStatsInfo)); + DumpableObject *dobj = &info->dobj; + + dobj->objType = DO_REL_STATS; + dobj->catId.tableoid = 0; + dobj->catId.oid = 0; + AssignDumpId(dobj); + dobj->dependencies = (DumpId *) pg_malloc(sizeof(DumpId)); + dobj->dependencies[0] = rel->dumpId; + dobj->nDeps = 1; + dobj->allocDeps = 1; + dobj->components |= DUMP_COMPONENT_STATISTICS; + dobj->name = pg_strdup(rel->name); + dobj->namespace = rel->namespace; + info->relpages = relpages; + info->reltuples = pstrdup(reltuples); + info->relallvisible = relallvisible; + info->relallfrozen = relallfrozen; + info->relkind = relkind; + info->indAttNames = indAttNames; + info->nindAttNames = nindAttNames; + + /* + * Ordinarily, stats go in SECTION_DATA for tables and + * SECTION_POST_DATA for indexes. + * + * However, the section may be updated later for materialized view + * stats. REFRESH MATERIALIZED VIEW replaces the storage and resets + * the stats, so the stats must be restored after the data. Also, the + * materialized view definition may be postponed to SECTION_POST_DATA + * (see repairMatViewBoundaryMultiLoop()). + */ + switch (info->relkind) + { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: + case RELKIND_MATVIEW: + case RELKIND_FOREIGN_TABLE: + info->section = SECTION_DATA; + break; + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + info->section = SECTION_POST_DATA; + break; + default: + pg_fatal("cannot dump statistics for relation kind \"%c\"", + info->relkind); + } + + return info; + } + return NULL; +} + /* * getTables * read all the tables (no indexes) in the system catalogs, @@ -6696,6 +6974,9 @@ getTables(Archive *fout, int *numTables) int i_relhasindex; int i_relhasrules; int i_relpages; + int i_reltuples; + int i_relallvisible; + int i_relallfrozen; int i_toastpages; int i_owning_tab; int i_owning_col; @@ -6746,8 +7027,15 @@ getTables(Archive *fout, int *numTables) "c.relowner, " "c.relchecks, " "c.relhasindex, c.relhasrules, c.relpages, " - "c.relhastriggers, " - "c.relpersistence, " + "c.reltuples, c.relallvisible, "); + + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(query, "c.relallfrozen, "); + else + appendPQExpBufferStr(query, "0 AS relallfrozen, "); + + appendPQExpBufferStr(query, + "c.relhastriggers, c.relpersistence, " "c.reloftype, " "c.relacl, " "acldefault(CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE) @@ -6910,6 +7198,9 @@ getTables(Archive *fout, int *numTables) i_relhasindex = PQfnumber(res, "relhasindex"); i_relhasrules = PQfnumber(res, "relhasrules"); i_relpages = PQfnumber(res, "relpages"); + i_reltuples = PQfnumber(res, "reltuples"); + i_relallvisible = PQfnumber(res, "relallvisible"); + i_relallfrozen = PQfnumber(res, "relallfrozen"); i_toastpages = PQfnumber(res, "toastpages"); i_owning_tab = PQfnumber(res, "owning_tab"); i_owning_col = PQfnumber(res, "owning_col"); @@ -6956,6 +7247,9 @@ getTables(Archive *fout, int *numTables) for (i = 0; i < ntups; i++) { + int32 relallvisible = atoi(PQgetvalue(res, i, i_relallvisible)); + int32 relallfrozen = atoi(PQgetvalue(res, i, i_relallfrozen)); + tblinfo[i].dobj.objType = DO_TABLE; tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid)); tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid)); @@ -7028,8 +7322,8 @@ getTables(Archive *fout, int *numTables) /* * Now, consider the table "interesting" if we need to dump its - * definition or its data. Later on, we'll skip a lot of data - * collection for uninteresting tables. + * definition, data or its statistics. Later on, we'll skip a lot of + * data collection for uninteresting tables. * * Note: the "interesting" flag will also be set by flagInhTables for * parents of interesting tables, so that we collect necessary @@ -7039,7 +7333,8 @@ getTables(Archive *fout, int *numTables) */ tblinfo[i].interesting = (tblinfo[i].dobj.dump & (DUMP_COMPONENT_DEFINITION | - DUMP_COMPONENT_DATA)) != 0; + DUMP_COMPONENT_DATA | + DUMP_COMPONENT_STATISTICS)) != 0; tblinfo[i].dummy_view = false; /* might get set during sort */ tblinfo[i].postponed_def = false; /* might get set during sort */ @@ -7052,6 +7347,20 @@ getTables(Archive *fout, int *numTables) tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL; tblinfo[i].hascolumnACLs = false; /* may get set later */ + /* Add statistics */ + if (tblinfo[i].interesting) + { + RelStatsInfo *stats; + + stats = getRelationStatistics(fout, &tblinfo[i].dobj, + tblinfo[i].relpages, + PQgetvalue(res, i, i_reltuples), + relallvisible, relallfrozen, + tblinfo[i].relkind, NULL, 0); + if (tblinfo[i].relkind == RELKIND_MATVIEW) + tblinfo[i].stats = stats; + } + /* * Read-lock target tables to make sure they aren't DROPPED or altered * in schema before we get around to dumping them. @@ -7145,20 +7454,15 @@ getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables) seqinfo->owning_tab, seqinfo->dobj.catId.oid); /* - * Only dump identity sequences if we're going to dump the table that - * it belongs to. - */ - if (owning_tab->dobj.dump == DUMP_COMPONENT_NONE && - seqinfo->is_identity_sequence) - { - seqinfo->dobj.dump = DUMP_COMPONENT_NONE; - continue; - } - - /* - * Otherwise we need to dump the components that are being dumped for - * the table and any components which the sequence is explicitly - * marked with. + * For an identity sequence, dump exactly the same components for the + * sequence as for the owning table. This is important because we + * treat the identity sequence as an integral part of the table. For + * example, there is not any DDL command that allows creation of such + * a sequence independently of the table. + * + * For other owned sequences such as serial sequences, we need to dump + * the components that are being dumped for the table and any + * components that the sequence is explicitly marked with. * * We can't simply use the set of components which are being dumped * for the table as the table might be in an extension (and only the @@ -7171,10 +7475,17 @@ getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables) * marked by checkExtensionMembership() and this will be a no-op as * the table will be equivalently marked. */ - seqinfo->dobj.dump = seqinfo->dobj.dump | owning_tab->dobj.dump; + if (seqinfo->is_identity_sequence) + seqinfo->dobj.dump = owning_tab->dobj.dump; + else + seqinfo->dobj.dump |= owning_tab->dobj.dump; + /* Make sure that necessary data is available if we're dumping it */ if (seqinfo->dobj.dump != DUMP_COMPONENT_NONE) + { seqinfo->interesting = true; + owning_tab->interesting = true; + } } } @@ -7251,8 +7562,8 @@ getPartitioningInfo(Archive *fout) /* hash partitioning didn't exist before v11 */ if (fout->remoteVersion < 110000) return; - /* needn't bother if schema-only dump */ - if (fout->dopt->schemaOnly) + /* needn't bother if not dumping data */ + if (!fout->dopt->dumpData) return; query = createPQExpBuffer(); @@ -7314,6 +7625,10 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) i_oid, i_indrelid, i_indexname, + i_relpages, + i_reltuples, + i_relallvisible, + i_relallfrozen, i_parentidx, i_indexdef, i_indnkeyatts, @@ -7326,9 +7641,11 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) i_conname, i_condeferrable, i_condeferred, + i_conperiod, i_contableoid, i_conoid, i_condef, + i_indattnames, i_tablespace, i_indreloptions, i_indstatcols, @@ -7366,6 +7683,14 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) appendPQExpBufferStr(query, "SELECT t.tableoid, t.oid, i.indrelid, " "t.relname AS indexname, " + "t.relpages, t.reltuples, t.relallvisible, "); + + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(query, "t.relallfrozen, "); + else + appendPQExpBufferStr(query, "0 AS relallfrozen, "); + + appendPQExpBufferStr(query, "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, " "i.indkey, i.indisclustered, " "c.contype, c.conname, " @@ -7373,6 +7698,11 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) "c.tableoid AS contableoid, " "c.oid AS conoid, " "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, " + "CASE WHEN i.indexprs IS NOT NULL THEN " + "(SELECT pg_catalog.array_agg(attname ORDER BY attnum)" + " FROM pg_catalog.pg_attribute " + " WHERE attrelid = i.indexrelid) " + "ELSE NULL END AS indattnames, " "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, " "t.reloptions AS indreloptions, "); @@ -7407,10 +7737,17 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) if (fout->remoteVersion >= 150000) appendPQExpBufferStr(query, - "i.indnullsnotdistinct "); + "i.indnullsnotdistinct, "); + else + appendPQExpBufferStr(query, + "false AS indnullsnotdistinct, "); + + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(query, + "c.conperiod "); else appendPQExpBufferStr(query, - "false AS indnullsnotdistinct "); + "NULL AS conperiod "); /* * The point of the messy-looking outer join is to find a constraint that @@ -7466,6 +7803,10 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) i_oid = PQfnumber(res, "oid"); i_indrelid = PQfnumber(res, "indrelid"); i_indexname = PQfnumber(res, "indexname"); + i_relpages = PQfnumber(res, "relpages"); + i_reltuples = PQfnumber(res, "reltuples"); + i_relallvisible = PQfnumber(res, "relallvisible"); + i_relallfrozen = PQfnumber(res, "relallfrozen"); i_parentidx = PQfnumber(res, "parentidx"); i_indexdef = PQfnumber(res, "indexdef"); i_indnkeyatts = PQfnumber(res, "indnkeyatts"); @@ -7478,9 +7819,11 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) i_conname = PQfnumber(res, "conname"); i_condeferrable = PQfnumber(res, "condeferrable"); i_condeferred = PQfnumber(res, "condeferred"); + i_conperiod = PQfnumber(res, "conperiod"); i_contableoid = PQfnumber(res, "contableoid"); i_conoid = PQfnumber(res, "conoid"); i_condef = PQfnumber(res, "condef"); + i_indattnames = PQfnumber(res, "indattnames"); i_tablespace = PQfnumber(res, "tablespace"); i_indreloptions = PQfnumber(res, "indreloptions"); i_indstatcols = PQfnumber(res, "indstatcols"); @@ -7497,6 +7840,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) { Oid indrelid = atooid(PQgetvalue(res, j, i_indrelid)); TableInfo *tbinfo = NULL; + char **indAttNames = NULL; + int nindAttNames = 0; int numinds; /* Count rows for this table */ @@ -7529,6 +7874,11 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) for (int c = 0; c < numinds; c++, j++) { char contype; + char indexkind; + RelStatsInfo *relstats; + int32 relpages = atoi(PQgetvalue(res, j, i_relpages)); + int32 relallvisible = atoi(PQgetvalue(res, j, i_relallvisible)); + int32 relallfrozen = atoi(PQgetvalue(res, j, i_relallfrozen)); indxinfo[j].dobj.objType = DO_INDEX; indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid)); @@ -7556,8 +7906,25 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) { NULL, NULL }; - contype = *(PQgetvalue(res, j, i_contype)); + if (indxinfo[j].parentidx == 0) + indexkind = RELKIND_INDEX; + else + indexkind = RELKIND_PARTITIONED_INDEX; + + if (!PQgetisnull(res, j, i_indattnames)) + { + if (!parsePGArray(PQgetvalue(res, j, i_indattnames), + &indAttNames, &nindAttNames)) + pg_fatal("could not parse %s array", "indattnames"); + } + + relstats = getRelationStatistics(fout, &indxinfo[j].dobj, relpages, + PQgetvalue(res, j, i_reltuples), + relallvisible, relallfrozen, indexkind, + indAttNames, nindAttNames); + + contype = *(PQgetvalue(res, j, i_contype)); if (contype == 'p' || contype == 'u' || contype == 'x') { /* @@ -7585,10 +7952,13 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables) constrinfo->conindex = indxinfo[j].dobj.dumpId; constrinfo->condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't'; constrinfo->condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't'; + constrinfo->conperiod = *(PQgetvalue(res, j, i_conperiod)) == 't'; constrinfo->conislocal = true; constrinfo->separate = true; indxinfo[j].indexconstraint = constrinfo->dobj.dumpId; + if (relstats != NULL) + addObjectDependency(&relstats->dobj, constrinfo->dobj.dumpId); } else { @@ -7721,13 +8091,7 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables) { TableInfo *tinfo = &tblinfo[i]; - /* - * For partitioned tables, foreign keys have no triggers so they must - * be included anyway in case some foreign keys are defined. - */ - if ((!tinfo->hastriggers && - tinfo->relkind != RELKIND_PARTITIONED_TABLE) || - !(tinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) + if (!(tinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)) continue; /* OK, we need info for this table */ @@ -8624,6 +8988,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) PQExpBuffer q = createPQExpBuffer(); PQExpBuffer tbloids = createPQExpBuffer(); PQExpBuffer checkoids = createPQExpBuffer(); + PQExpBuffer invalidnotnulloids = NULL; PGresult *res; int ntups; int curtblindx; @@ -8640,7 +9005,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) int i_attlen; int i_attalign; int i_attislocal; - int i_attnotnull; + int i_notnull_name; + int i_notnull_noinherit; + int i_notnull_islocal; + int i_notnull_invalidoid; int i_attoptions; int i_attcollation; int i_attcompression; @@ -8650,13 +9018,13 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) /* * We want to perform just one query against pg_attribute, and then just - * one against pg_attrdef (for DEFAULTs) and one against pg_constraint - * (for CHECK constraints). However, we mustn't try to select every row - * of those catalogs and then sort it out on the client side, because some - * of the server-side functions we need would be unsafe to apply to tables - * we don't have lock on. Hence, we build an array of the OIDs of tables - * we care about (and now have lock on!), and use a WHERE clause to - * constrain which rows are selected. + * one against pg_attrdef (for DEFAULTs) and two against pg_constraint + * (for CHECK constraints and for NOT NULL constraints). However, we + * mustn't try to select every row of those catalogs and then sort it out + * on the client side, because some of the server-side functions we need + * would be unsafe to apply to tables we don't have lock on. Hence, we + * build an array of the OIDs of tables we care about (and now have lock + * on!), and use a WHERE clause to constrain which rows are selected. */ appendPQExpBufferChar(tbloids, '{'); appendPQExpBufferChar(checkoids, '{'); @@ -8703,7 +9071,6 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) "a.attstattarget,\n" "a.attstorage,\n" "t.typstorage,\n" - "a.attnotnull,\n" "a.atthasdef,\n" "a.attisdropped,\n" "a.attlen,\n" @@ -8720,6 +9087,37 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) "ORDER BY option_name" "), E',\n ') AS attfdwoptions,\n"); + /* + * Find out any NOT NULL markings for each column. In 18 and up we read + * pg_constraint to obtain the constraint name. notnull_noinherit is set + * according to the NO INHERIT property. For versions prior to 18, we + * store an empty string as the name when a constraint is marked as + * attnotnull (this cues dumpTableSchema to print the NOT NULL clause + * without a name); also, such cases are never NO INHERIT. + * + * For invalid constraints, we need to store their OIDs for processing + * elsewhere, so we bring the pg_constraint.oid value when the constraint + * is invalid, and NULL otherwise. + * + * We track in notnull_islocal whether the constraint was defined directly + * in this table or via an ancestor, for binary upgrade. flagInhAttrs + * might modify this later; that routine is also in charge of determining + * the correct inhcount. + */ + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(q, + "co.conname AS notnull_name,\n" + "CASE WHEN NOT co.convalidated THEN co.oid " + "ELSE NULL END AS notnull_invalidoid,\n" + "co.connoinherit AS notnull_noinherit,\n" + "co.conislocal AS notnull_islocal,\n"); + else + appendPQExpBufferStr(q, + "CASE WHEN a.attnotnull THEN '' ELSE NULL END AS notnull_name,\n" + "NULL AS notnull_invalidoid,\n" + "false AS notnull_noinherit,\n" + "a.attislocal AS notnull_islocal,\n"); + if (fout->remoteVersion >= 140000) appendPQExpBufferStr(q, "a.attcompression AS attcompression,\n"); @@ -8754,11 +9152,25 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n" "JOIN pg_catalog.pg_attribute a ON (src.tbloid = a.attrelid) " "LEFT JOIN pg_catalog.pg_type t " - "ON (a.atttypid = t.oid)\n" - "WHERE a.attnum > 0::pg_catalog.int2\n" - "ORDER BY a.attrelid, a.attnum", + "ON (a.atttypid = t.oid)\n", tbloids->data); + /* + * In versions 18 and up, we need pg_constraint for explicit NOT NULL + * entries. Also, we need to know if the NOT NULL for each column is + * backing a primary key. + */ + if (fout->remoteVersion >= 180000) + appendPQExpBufferStr(q, + " LEFT JOIN pg_catalog.pg_constraint co ON " + "(a.attrelid = co.conrelid\n" + " AND co.contype = 'n' AND " + "co.conkey = array[a.attnum])\n"); + + appendPQExpBufferStr(q, + "WHERE a.attnum > 0::pg_catalog.int2\n" + "ORDER BY a.attrelid, a.attnum"); + res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); ntups = PQntuples(res); @@ -8776,7 +9188,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) i_attlen = PQfnumber(res, "attlen"); i_attalign = PQfnumber(res, "attalign"); i_attislocal = PQfnumber(res, "attislocal"); - i_attnotnull = PQfnumber(res, "attnotnull"); + i_notnull_name = PQfnumber(res, "notnull_name"); + i_notnull_invalidoid = PQfnumber(res, "notnull_invalidoid"); + i_notnull_noinherit = PQfnumber(res, "notnull_noinherit"); + i_notnull_islocal = PQfnumber(res, "notnull_islocal"); i_attoptions = PQfnumber(res, "attoptions"); i_attcollation = PQfnumber(res, "attcollation"); i_attcompression = PQfnumber(res, "attcompression"); @@ -8841,8 +9256,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) tbinfo->attcompression = (char *) pg_malloc(numatts * sizeof(char)); tbinfo->attfdwoptions = (char **) pg_malloc(numatts * sizeof(char *)); tbinfo->attmissingval = (char **) pg_malloc(numatts * sizeof(char *)); - tbinfo->notnull = (bool *) pg_malloc(numatts * sizeof(bool)); - tbinfo->inhNotNull = (bool *) pg_malloc(numatts * sizeof(bool)); + tbinfo->notnull_constrs = (char **) pg_malloc(numatts * sizeof(char *)); + tbinfo->notnull_invalid = (bool *) pg_malloc(numatts * sizeof(bool)); + tbinfo->notnull_noinh = (bool *) pg_malloc(numatts * sizeof(bool)); + tbinfo->notnull_islocal = (bool *) pg_malloc(numatts * sizeof(bool)); tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(numatts * sizeof(AttrDefInfo *)); hasdefaults = false; @@ -8866,7 +9283,16 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) tbinfo->attlen[j] = atoi(PQgetvalue(res, r, i_attlen)); tbinfo->attalign[j] = *(PQgetvalue(res, r, i_attalign)); tbinfo->attislocal[j] = (PQgetvalue(res, r, i_attislocal)[0] == 't'); - tbinfo->notnull[j] = (PQgetvalue(res, r, i_attnotnull)[0] == 't'); + + /* Handle not-null constraint name and flags */ + determineNotNullFlags(fout, res, r, + tbinfo, j, + i_notnull_name, + i_notnull_invalidoid, + i_notnull_noinherit, + i_notnull_islocal, + &invalidnotnulloids); + tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, r, i_attoptions)); tbinfo->attcollation[j] = atooid(PQgetvalue(res, r, i_attcollation)); tbinfo->attcompression[j] = *(PQgetvalue(res, r, i_attcompression)); @@ -8875,8 +9301,6 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) tbinfo->attrdefs[j] = NULL; /* fix below */ if (PQgetvalue(res, r, i_atthasdef)[0] == 't') hasdefaults = true; - /* these flags will be set in flagInhAttrs() */ - tbinfo->inhNotNull[j] = false; } if (hasdefaults) @@ -8888,13 +9312,17 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) } } + /* If invalidnotnulloids has any data, finalize it */ + if (invalidnotnulloids != NULL) + appendPQExpBufferChar(invalidnotnulloids, '}'); + PQclear(res); /* * Now get info about column defaults. This is skipped for a data-only * dump, as it is only needed for table schemas. */ - if (!dopt->dataOnly && tbloids->len > 1) + if (dopt->dumpSchema && tbloids->len > 1) { AttrDefInfo *attrdefs; int numDefaults; @@ -9021,10 +9449,10 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) } /* - * Get info about table CHECK constraints. This is skipped for a + * Get info about NOT NULL NOT VALID constraints. This is skipped for a * data-only dump, as it is only needed for table schemas. */ - if (!dopt->dataOnly && checkoids->len > 2) + if (dopt->dumpSchema && invalidnotnulloids) { ConstraintInfo *constrs; int numConstrs; @@ -9034,20 +9462,18 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) int i_conname; int i_consrc; int i_conislocal; - int i_convalidated; - pg_log_info("finding table check constraints"); + pg_log_info("finding invalid not-null constraints"); resetPQExpBuffer(q); appendPQExpBuffer(q, "SELECT c.tableoid, c.oid, conrelid, conname, " "pg_catalog.pg_get_constraintdef(c.oid) AS consrc, " "conislocal, convalidated " - "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n" - "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n" - "WHERE contype = 'c' " + "FROM unnest('%s'::pg_catalog.oid[]) AS src(conoid)\n" + "JOIN pg_catalog.pg_constraint c ON (src.conoid = c.oid)\n" "ORDER BY c.conrelid, c.conname", - checkoids->data); + invalidnotnulloids->data); res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); @@ -9060,7 +9486,6 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) i_conname = PQfnumber(res, "conname"); i_consrc = PQfnumber(res, "consrc"); i_conislocal = PQfnumber(res, "conislocal"); - i_convalidated = PQfnumber(res, "convalidated"); /* As above, this loop iterates once per table, not once per row */ curtblindx = -1; @@ -9088,22 +9513,8 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) if (curtblindx >= numTables) pg_fatal("unrecognized table OID %u", conrelid); - if (numcons != tbinfo->ncheck) - { - pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d", - "expected %d check constraints on table \"%s\" but found %d", - tbinfo->ncheck), - tbinfo->ncheck, tbinfo->dobj.name, numcons); - pg_log_error_hint("The system catalogs might be corrupted."); - exit_nicely(1); - } - - tbinfo->checkexprs = constrs + j; - for (int c = 0; c < numcons; c++, j++) { - bool validated = PQgetvalue(res, j, i_convalidated)[0] == 't'; - constrs[j].dobj.objType = DO_CONSTRAINT; constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid)); constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); @@ -9112,7 +9523,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) constrs[j].dobj.namespace = tbinfo->dobj.namespace; constrs[j].contable = tbinfo; constrs[j].condomain = NULL; - constrs[j].contype = 'c'; + constrs[j].contype = 'n'; constrs[j].condef = pg_strdup(PQgetvalue(res, j, i_consrc)); constrs[j].confrelid = InvalidOid; constrs[j].conindex = 0; @@ -9121,43 +9532,310 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables) constrs[j].conislocal = (PQgetvalue(res, j, i_conislocal)[0] == 't'); /* - * An unvalidated constraint needs to be dumped separately, so - * that potentially-violating existing data is loaded before - * the constraint. + * All invalid not-null constraints must be dumped separately, + * because CREATE TABLE would not create them as invalid, and + * also because they must be created after potentially + * violating data has been loaded. */ - constrs[j].separate = !validated; + constrs[j].separate = true; constrs[j].dobj.dump = tbinfo->dobj.dump; - - /* - * Mark the constraint as needing to appear before the table - * --- this is so that any other dependencies of the - * constraint will be emitted before we try to create the - * table. If the constraint is to be dumped separately, it - * will be dumped after data is loaded anyway, so don't do it. - * (There's an automatic dependency in the opposite direction - * anyway, so don't need to add one manually here.) - */ - if (!constrs[j].separate) - addObjectDependency(&tbinfo->dobj, - constrs[j].dobj.dumpId); - - /* - * We will detect later whether the constraint must be split - * out from the table definition. - */ } } - PQclear(res); } - destroyPQExpBuffer(q); - destroyPQExpBuffer(tbloids); - destroyPQExpBuffer(checkoids); -} + /* + * Get info about table CHECK constraints. This is skipped for a + * data-only dump, as it is only needed for table schemas. + */ + if (dopt->dumpSchema && checkoids->len > 2) + { + ConstraintInfo *constrs; + int numConstrs; + int i_tableoid; + int i_oid; + int i_conrelid; + int i_conname; + int i_consrc; + int i_conislocal; + int i_convalidated; -/* + pg_log_info("finding table check constraints"); + + resetPQExpBuffer(q); + appendPQExpBuffer(q, + "SELECT c.tableoid, c.oid, conrelid, conname, " + "pg_catalog.pg_get_constraintdef(c.oid) AS consrc, " + "conislocal, convalidated " + "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n" + "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n" + "WHERE contype = 'c' " + "ORDER BY c.conrelid, c.conname", + checkoids->data); + + res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK); + + numConstrs = PQntuples(res); + constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_conrelid = PQfnumber(res, "conrelid"); + i_conname = PQfnumber(res, "conname"); + i_consrc = PQfnumber(res, "consrc"); + i_conislocal = PQfnumber(res, "conislocal"); + i_convalidated = PQfnumber(res, "convalidated"); + + /* As above, this loop iterates once per table, not once per row */ + curtblindx = -1; + for (int j = 0; j < numConstrs;) + { + Oid conrelid = atooid(PQgetvalue(res, j, i_conrelid)); + TableInfo *tbinfo = NULL; + int numcons; + + /* Count rows for this table */ + for (numcons = 1; numcons < numConstrs - j; numcons++) + if (atooid(PQgetvalue(res, j + numcons, i_conrelid)) != conrelid) + break; + + /* + * Locate the associated TableInfo; we rely on tblinfo[] being in + * OID order. + */ + while (++curtblindx < numTables) + { + tbinfo = &tblinfo[curtblindx]; + if (tbinfo->dobj.catId.oid == conrelid) + break; + } + if (curtblindx >= numTables) + pg_fatal("unrecognized table OID %u", conrelid); + + if (numcons != tbinfo->ncheck) + { + pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d", + "expected %d check constraints on table \"%s\" but found %d", + tbinfo->ncheck), + tbinfo->ncheck, tbinfo->dobj.name, numcons); + pg_log_error_hint("The system catalogs might be corrupted."); + exit_nicely(1); + } + + tbinfo->checkexprs = constrs + j; + + for (int c = 0; c < numcons; c++, j++) + { + bool validated = PQgetvalue(res, j, i_convalidated)[0] == 't'; + + constrs[j].dobj.objType = DO_CONSTRAINT; + constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid)); + constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid)); + AssignDumpId(&constrs[j].dobj); + constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname)); + constrs[j].dobj.namespace = tbinfo->dobj.namespace; + constrs[j].contable = tbinfo; + constrs[j].condomain = NULL; + constrs[j].contype = 'c'; + constrs[j].condef = pg_strdup(PQgetvalue(res, j, i_consrc)); + constrs[j].confrelid = InvalidOid; + constrs[j].conindex = 0; + constrs[j].condeferrable = false; + constrs[j].condeferred = false; + constrs[j].conislocal = (PQgetvalue(res, j, i_conislocal)[0] == 't'); + + /* + * An unvalidated constraint needs to be dumped separately, so + * that potentially-violating existing data is loaded before + * the constraint. + */ + constrs[j].separate = !validated; + + constrs[j].dobj.dump = tbinfo->dobj.dump; + + /* + * Mark the constraint as needing to appear before the table + * --- this is so that any other dependencies of the + * constraint will be emitted before we try to create the + * table. If the constraint is to be dumped separately, it + * will be dumped after data is loaded anyway, so don't do it. + * (There's an automatic dependency in the opposite direction + * anyway, so don't need to add one manually here.) + */ + if (!constrs[j].separate) + addObjectDependency(&tbinfo->dobj, + constrs[j].dobj.dumpId); + + /* + * We will detect later whether the constraint must be split + * out from the table definition. + */ + } + } + + PQclear(res); + } + + destroyPQExpBuffer(q); + destroyPQExpBuffer(tbloids); + destroyPQExpBuffer(checkoids); +} + +/* + * Based on the getTableAttrs query's row corresponding to one column, set + * the name and flags to handle a not-null constraint for that column in + * the tbinfo struct. + * + * Result row 'r' is for tbinfo's attribute 'j'. + * + * There are four possibilities: + * 1) the column has no not-null constraints. In that case, ->notnull_constrs + * (the constraint name) remains NULL. + * 2) The column has a constraint with no name (this is the case when + * constraints come from pre-18 servers). In this case, ->notnull_constrs + * is set to the empty string; dumpTableSchema will print just "NOT NULL". + * 3) The column has an invalid not-null constraint. This must be treated + * as a separate object (because it must be created after the table data + * is loaded). So we add its OID to invalidnotnulloids for processing + * elsewhere and do nothing further with it here. We distinguish this + * case because the "notnull_invalidoid" column has been set to a non-NULL + * value, which is the constraint OID. Valid constraints have a null OID. + * 4) The column has a constraint with a known name; in that case + * notnull_constrs carries that name and dumpTableSchema will print + * "CONSTRAINT the_name NOT NULL". However, if the name is the default + * (table_column_not_null), there's no need to print that name in the dump, + * so notnull_constrs is set to the empty string and it behaves as case 2. + * + * In a child table that inherits from a parent already containing NOT NULL + * constraints and the columns in the child don't have their own NOT NULL + * declarations, we suppress printing constraints in the child: the + * constraints are acquired at the point where the child is attached to the + * parent. This is tracked in ->notnull_islocal; for servers pre-18 this is + * set not here but in flagInhAttrs. That flag is also used when the + * constraint was validated in a child but all its parent have it as NOT + * VALID. + * + * Any of these constraints might have the NO INHERIT bit. If so we set + * ->notnull_noinh and NO INHERIT will be printed by dumpTableSchema. + * + * In case 4 above, the name comparison is a bit of a hack; it actually fails + * to do the right thing in all but the trivial case. However, the downside + * of getting it wrong is simply that the name is printed rather than + * suppressed, so it's not a big deal. + * + * invalidnotnulloids is expected to be given as NULL; if any invalid not-null + * constraints are found, it is initialized and filled with the array of + * OIDs of such constraints, for later processing. + */ +static void +determineNotNullFlags(Archive *fout, PGresult *res, int r, + TableInfo *tbinfo, int j, + int i_notnull_name, + int i_notnull_invalidoid, + int i_notnull_noinherit, + int i_notnull_islocal, + PQExpBuffer *invalidnotnulloids) +{ + DumpOptions *dopt = fout->dopt; + + /* + * If this not-null constraint is not valid, list its OID in + * invalidnotnulloids and do nothing further. It'll be processed + * elsewhere later. + * + * Because invalid not-null constraints are rare, we don't want to malloc + * invalidnotnulloids until we're sure we're going it need it, which + * happens here. + */ + if (!PQgetisnull(res, r, i_notnull_invalidoid)) + { + char *constroid = PQgetvalue(res, r, i_notnull_invalidoid); + + if (*invalidnotnulloids == NULL) + { + *invalidnotnulloids = createPQExpBuffer(); + appendPQExpBufferChar(*invalidnotnulloids, '{'); + appendPQExpBufferStr(*invalidnotnulloids, constroid); + } + else + appendPQExpBuffer(*invalidnotnulloids, ",%s", constroid); + + /* + * Track when a parent constraint is invalid for the cases where a + * child constraint has been validated independenly. + */ + tbinfo->notnull_invalid[j] = true; + + /* nothing else to do */ + tbinfo->notnull_constrs[j] = NULL; + return; + } + + /* + * notnull_noinh is straight from the query result. notnull_islocal also, + * though flagInhAttrs may change that one later. + */ + tbinfo->notnull_noinh[j] = PQgetvalue(res, r, i_notnull_noinherit)[0] == 't'; + tbinfo->notnull_islocal[j] = PQgetvalue(res, r, i_notnull_islocal)[0] == 't'; + tbinfo->notnull_invalid[j] = false; + + /* + * Determine a constraint name to use. If the column is not marked not- + * null, we set NULL which cues ... to do nothing. An empty string says + * to print an unnamed NOT NULL, and anything else is a constraint name to + * use. + */ + if (fout->remoteVersion < 180000) + { + /* + * < 18 doesn't have not-null names, so an unnamed constraint is + * sufficient. + */ + if (PQgetisnull(res, r, i_notnull_name)) + tbinfo->notnull_constrs[j] = NULL; + else + tbinfo->notnull_constrs[j] = ""; + } + else + { + if (PQgetisnull(res, r, i_notnull_name)) + tbinfo->notnull_constrs[j] = NULL; + else + { + /* + * In binary upgrade of inheritance child tables, must have a + * constraint name that we can UPDATE later. + */ + if (dopt->binary_upgrade && + !tbinfo->ispartition && + !tbinfo->notnull_islocal) + { + tbinfo->notnull_constrs[j] = + pstrdup(PQgetvalue(res, r, i_notnull_name)); + } + else + { + char *default_name; + + /* XXX should match ChooseConstraintName better */ + default_name = psprintf("%s_%s_not_null", tbinfo->dobj.name, + tbinfo->attnames[j]); + if (strcmp(default_name, + PQgetvalue(res, r, i_notnull_name)) == 0) + tbinfo->notnull_constrs[j] = ""; + else + { + tbinfo->notnull_constrs[j] = + pstrdup(PQgetvalue(res, r, i_notnull_name)); + } + free(default_name); + } + } + } +} + +/* * Test whether a column should be printed as part of table's CREATE TABLE. * Column number is zero-based. * @@ -9934,13 +10612,13 @@ dumpCommentExtended(Archive *fout, const char *type, /* Comments are schema not data ... except LO comments are data */ if (strcmp(type, "LARGE OBJECT") != 0) { - if (dopt->dataOnly) + if (!dopt->dumpSchema) return; } else { /* We do dump LO comments in binary-upgrade mode */ - if (dopt->schemaOnly && !dopt->binary_upgrade) + if (!dopt->dumpData && !dopt->binary_upgrade) return; } @@ -10026,6 +10704,411 @@ dumpComment(Archive *fout, const char *type, catalogId, subid, dumpId, NULL); } +/* + * appendNamedArgument -- + * + * Convenience routine for constructing parameters of the form: + * 'paraname', 'value'::type + */ +static void +appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname, + const char *argtype, const char *argval) +{ + appendPQExpBufferStr(out, ",\n\t"); + + appendStringLiteralAH(out, argname, fout); + appendPQExpBufferStr(out, ", "); + + appendStringLiteralAH(out, argval, fout); + appendPQExpBuffer(out, "::%s", argtype); +} + +/* + * fetchAttributeStats -- + * + * Fetch next batch of attribute statistics for dumpRelationStats_dumper(). + */ +static PGresult * +fetchAttributeStats(Archive *fout) +{ + ArchiveHandle *AH = (ArchiveHandle *) fout; + PQExpBuffer nspnames = createPQExpBuffer(); + PQExpBuffer relnames = createPQExpBuffer(); + int count = 0; + PGresult *res = NULL; + static TocEntry *te; + static bool restarted; + int max_rels = MAX_ATTR_STATS_RELS; + + /* + * Our query for retrieving statistics for multiple relations uses WITH + * ORDINALITY and multi-argument UNNEST(), both of which were introduced + * in v9.4. For older versions, we resort to gathering statistics for a + * single relation at a time. + */ + if (fout->remoteVersion < 90400) + max_rels = 1; + + /* If we're just starting, set our TOC pointer. */ + if (!te) + te = AH->toc->next; + + /* + * We can't easily avoid a second TOC scan for the tar format because it + * writes restore.sql separately, which means we must execute the queries + * twice. This feels risky, but there is no known reason it should + * generate different output than the first pass. Even if it does, the + * worst-case scenario is that restore.sql might have different statistics + * data than the archive. + */ + if (!restarted && te == AH->toc && AH->format == archTar) + { + te = AH->toc->next; + restarted = true; + } + + appendPQExpBufferChar(nspnames, '{'); + appendPQExpBufferChar(relnames, '{'); + + /* + * Scan the TOC for the next set of relevant stats entries. We assume + * that statistics are dumped in the order they are listed in the TOC. + * This is perhaps not the sturdiest assumption, so we verify it matches + * reality in dumpRelationStats_dumper(). + */ + for (; te != AH->toc && count < max_rels; te = te->next) + { + if ((te->reqs & REQ_STATS) != 0 && + strcmp(te->desc, "STATISTICS DATA") == 0) + { + appendPGArray(nspnames, te->namespace); + appendPGArray(relnames, te->tag); + count++; + } + } + + appendPQExpBufferChar(nspnames, '}'); + appendPQExpBufferChar(relnames, '}'); + + /* Execute the query for the next batch of relations. */ + if (count > 0) + { + PQExpBuffer query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "EXECUTE getAttributeStats("); + appendStringLiteralAH(query, nspnames->data, fout); + appendPQExpBufferStr(query, "::pg_catalog.name[],"); + appendStringLiteralAH(query, relnames->data, fout); + appendPQExpBufferStr(query, "::pg_catalog.name[])"); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + destroyPQExpBuffer(query); + } + + destroyPQExpBuffer(nspnames); + destroyPQExpBuffer(relnames); + return res; +} + +/* + * dumpRelationStats_dumper -- + * + * Generate command to import stats into the relation on the new database. + * This routine is called by the Archiver when it wants the statistics to be + * dumped. + */ +static char * +dumpRelationStats_dumper(Archive *fout, const void *userArg, const TocEntry *te) +{ + const RelStatsInfo *rsinfo = (RelStatsInfo *) userArg; + static PGresult *res; + static int rownum; + PQExpBuffer query; + PQExpBufferData out_data; + PQExpBuffer out = &out_data; + int i_schemaname; + int i_tablename; + int i_attname; + int i_inherited; + int i_null_frac; + int i_avg_width; + int i_n_distinct; + int i_most_common_vals; + int i_most_common_freqs; + int i_histogram_bounds; + int i_correlation; + int i_most_common_elems; + int i_most_common_elem_freqs; + int i_elem_count_histogram; + int i_range_length_histogram; + int i_range_empty_frac; + int i_range_bounds_histogram; + static TocEntry *expected_te; + + /* + * fetchAttributeStats() assumes that the statistics are dumped in the + * order they are listed in the TOC. We verify that here for safety. + */ + if (!expected_te) + expected_te = ((ArchiveHandle *) fout)->toc; + + expected_te = expected_te->next; + while ((expected_te->reqs & REQ_STATS) == 0 || + strcmp(expected_te->desc, "STATISTICS DATA") != 0) + expected_te = expected_te->next; + + if (te != expected_te) + pg_fatal("statistics dumped out of order (current: %d %s %s, expected: %d %s %s)", + te->dumpId, te->desc, te->tag, + expected_te->dumpId, expected_te->desc, expected_te->tag); + + query = createPQExpBuffer(); + if (!fout->is_prepared[PREPQUERY_GETATTRIBUTESTATS]) + { + appendPQExpBufferStr(query, + "PREPARE getAttributeStats(pg_catalog.name[], pg_catalog.name[]) AS\n" + "SELECT s.schemaname, s.tablename, s.attname, s.inherited, " + "s.null_frac, s.avg_width, s.n_distinct, " + "s.most_common_vals, s.most_common_freqs, " + "s.histogram_bounds, s.correlation, " + "s.most_common_elems, s.most_common_elem_freqs, " + "s.elem_count_histogram, "); + + if (fout->remoteVersion >= 170000) + appendPQExpBufferStr(query, + "s.range_length_histogram, " + "s.range_empty_frac, " + "s.range_bounds_histogram "); + else + appendPQExpBufferStr(query, + "NULL AS range_length_histogram," + "NULL AS range_empty_frac," + "NULL AS range_bounds_histogram "); + + /* + * The results must be in the order of the relations supplied in the + * parameters to ensure we remain in sync as we walk through the TOC. + * The redundant filter clause on s.tablename = ANY(...) seems + * sufficient to convince the planner to use + * pg_class_relname_nsp_index, which avoids a full scan of pg_stats. + * This may not work for all versions. + * + * Our query for retrieving statistics for multiple relations uses + * WITH ORDINALITY and multi-argument UNNEST(), both of which were + * introduced in v9.4. For older versions, we resort to gathering + * statistics for a single relation at a time. + */ + if (fout->remoteVersion >= 90400) + appendPQExpBufferStr(query, + "FROM pg_catalog.pg_stats s " + "JOIN unnest($1, $2) WITH ORDINALITY AS u (schemaname, tablename, ord) " + "ON s.schemaname = u.schemaname " + "AND s.tablename = u.tablename " + "WHERE s.tablename = ANY($2) " + "ORDER BY u.ord, s.attname, s.inherited"); + else + appendPQExpBufferStr(query, + "FROM pg_catalog.pg_stats s " + "WHERE s.schemaname = $1[1] " + "AND s.tablename = $2[1] " + "ORDER BY s.attname, s.inherited"); + + ExecuteSqlStatement(fout, query->data); + + fout->is_prepared[PREPQUERY_GETATTRIBUTESTATS] = true; + resetPQExpBuffer(query); + } + + initPQExpBuffer(out); + + /* restore relation stats */ + appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n"); + appendPQExpBuffer(out, "\t'version', '%d'::integer,\n", + fout->remoteVersion); + appendPQExpBufferStr(out, "\t'schemaname', "); + appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout); + appendPQExpBufferStr(out, ",\n"); + appendPQExpBufferStr(out, "\t'relname', "); + appendStringLiteralAH(out, rsinfo->dobj.name, fout); + appendPQExpBufferStr(out, ",\n"); + appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages); + + /* + * Before v14, a reltuples value of 0 was ambiguous: it could either mean + * the relation is empty, or it could mean that it hadn't yet been + * vacuumed or analyzed. (Newer versions use -1 for the latter case.) + * This ambiguity allegedly can cause the planner to choose inefficient + * plans after restoring to v18 or newer. To deal with this, let's just + * set reltuples to -1 in that case. + */ + if (fout->remoteVersion < 140000 && strcmp("0", rsinfo->reltuples) == 0) + appendPQExpBufferStr(out, "\t'reltuples', '-1'::real,\n"); + else + appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", rsinfo->reltuples); + + appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer", + rsinfo->relallvisible); + + if (fout->remoteVersion >= 180000) + appendPQExpBuffer(out, ",\n\t'relallfrozen', '%d'::integer", rsinfo->relallfrozen); + + appendPQExpBufferStr(out, "\n);\n"); + + /* Fetch the next batch of attribute statistics if needed. */ + if (rownum >= PQntuples(res)) + { + PQclear(res); + res = fetchAttributeStats(fout); + rownum = 0; + } + + i_schemaname = PQfnumber(res, "schemaname"); + i_tablename = PQfnumber(res, "tablename"); + i_attname = PQfnumber(res, "attname"); + i_inherited = PQfnumber(res, "inherited"); + i_null_frac = PQfnumber(res, "null_frac"); + i_avg_width = PQfnumber(res, "avg_width"); + i_n_distinct = PQfnumber(res, "n_distinct"); + i_most_common_vals = PQfnumber(res, "most_common_vals"); + i_most_common_freqs = PQfnumber(res, "most_common_freqs"); + i_histogram_bounds = PQfnumber(res, "histogram_bounds"); + i_correlation = PQfnumber(res, "correlation"); + i_most_common_elems = PQfnumber(res, "most_common_elems"); + i_most_common_elem_freqs = PQfnumber(res, "most_common_elem_freqs"); + i_elem_count_histogram = PQfnumber(res, "elem_count_histogram"); + i_range_length_histogram = PQfnumber(res, "range_length_histogram"); + i_range_empty_frac = PQfnumber(res, "range_empty_frac"); + i_range_bounds_histogram = PQfnumber(res, "range_bounds_histogram"); + + /* restore attribute stats */ + for (; rownum < PQntuples(res); rownum++) + { + const char *attname; + + /* Stop if the next stat row in our cache isn't for this relation. */ + if (strcmp(te->tag, PQgetvalue(res, rownum, i_tablename)) != 0 || + strcmp(te->namespace, PQgetvalue(res, rownum, i_schemaname)) != 0) + break; + + appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n"); + appendPQExpBuffer(out, "\t'version', '%d'::integer,\n", + fout->remoteVersion); + appendPQExpBufferStr(out, "\t'schemaname', "); + appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout); + appendPQExpBufferStr(out, ",\n\t'relname', "); + appendStringLiteralAH(out, rsinfo->dobj.name, fout); + + if (PQgetisnull(res, rownum, i_attname)) + pg_fatal("unexpected null attname"); + attname = PQgetvalue(res, rownum, i_attname); + + /* + * Indexes look up attname in indAttNames to derive attnum, all others + * use attname directly. We must specify attnum for indexes, since + * their attnames are not necessarily stable across dump/reload. + */ + if (rsinfo->nindAttNames == 0) + { + appendPQExpBufferStr(out, ",\n\t'attname', "); + appendStringLiteralAH(out, attname, fout); + } + else + { + bool found = false; + + for (int i = 0; i < rsinfo->nindAttNames; i++) + { + if (strcmp(attname, rsinfo->indAttNames[i]) == 0) + { + appendPQExpBuffer(out, ",\n\t'attnum', '%d'::smallint", + i + 1); + found = true; + break; + } + } + + if (!found) + pg_fatal("could not find index attname \"%s\"", attname); + } + + if (!PQgetisnull(res, rownum, i_inherited)) + appendNamedArgument(out, fout, "inherited", "boolean", + PQgetvalue(res, rownum, i_inherited)); + if (!PQgetisnull(res, rownum, i_null_frac)) + appendNamedArgument(out, fout, "null_frac", "real", + PQgetvalue(res, rownum, i_null_frac)); + if (!PQgetisnull(res, rownum, i_avg_width)) + appendNamedArgument(out, fout, "avg_width", "integer", + PQgetvalue(res, rownum, i_avg_width)); + if (!PQgetisnull(res, rownum, i_n_distinct)) + appendNamedArgument(out, fout, "n_distinct", "real", + PQgetvalue(res, rownum, i_n_distinct)); + if (!PQgetisnull(res, rownum, i_most_common_vals)) + appendNamedArgument(out, fout, "most_common_vals", "text", + PQgetvalue(res, rownum, i_most_common_vals)); + if (!PQgetisnull(res, rownum, i_most_common_freqs)) + appendNamedArgument(out, fout, "most_common_freqs", "real[]", + PQgetvalue(res, rownum, i_most_common_freqs)); + if (!PQgetisnull(res, rownum, i_histogram_bounds)) + appendNamedArgument(out, fout, "histogram_bounds", "text", + PQgetvalue(res, rownum, i_histogram_bounds)); + if (!PQgetisnull(res, rownum, i_correlation)) + appendNamedArgument(out, fout, "correlation", "real", + PQgetvalue(res, rownum, i_correlation)); + if (!PQgetisnull(res, rownum, i_most_common_elems)) + appendNamedArgument(out, fout, "most_common_elems", "text", + PQgetvalue(res, rownum, i_most_common_elems)); + if (!PQgetisnull(res, rownum, i_most_common_elem_freqs)) + appendNamedArgument(out, fout, "most_common_elem_freqs", "real[]", + PQgetvalue(res, rownum, i_most_common_elem_freqs)); + if (!PQgetisnull(res, rownum, i_elem_count_histogram)) + appendNamedArgument(out, fout, "elem_count_histogram", "real[]", + PQgetvalue(res, rownum, i_elem_count_histogram)); + if (fout->remoteVersion >= 170000) + { + if (!PQgetisnull(res, rownum, i_range_length_histogram)) + appendNamedArgument(out, fout, "range_length_histogram", "text", + PQgetvalue(res, rownum, i_range_length_histogram)); + if (!PQgetisnull(res, rownum, i_range_empty_frac)) + appendNamedArgument(out, fout, "range_empty_frac", "real", + PQgetvalue(res, rownum, i_range_empty_frac)); + if (!PQgetisnull(res, rownum, i_range_bounds_histogram)) + appendNamedArgument(out, fout, "range_bounds_histogram", "text", + PQgetvalue(res, rownum, i_range_bounds_histogram)); + } + appendPQExpBufferStr(out, "\n);\n"); + } + + destroyPQExpBuffer(query); + return out->data; +} + +/* + * dumpRelationStats -- + * + * Make an ArchiveEntry for the relation statistics. The Archiver will take + * care of gathering the statistics and generating the restore commands when + * they are needed. + */ +static void +dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo) +{ + const DumpableObject *dobj = &rsinfo->dobj; + + /* nothing to do if we are not dumping statistics */ + if (!fout->dopt->dumpStatistics) + return; + + ArchiveEntry(fout, nilCatalogId, createDumpId(), + ARCHIVE_OPTS(.tag = dobj->name, + .namespace = dobj->namespace->dobj.name, + .description = "STATISTICS DATA", + .section = rsinfo->section, + .defnFn = dumpRelationStats_dumper, + .defnArg = rsinfo, + .deps = dobj->dependencies, + .nDeps = dobj->nDeps)); +} + /* * dumpTableComment -- * @@ -10047,7 +11130,7 @@ dumpTableComment(Archive *fout, const TableInfo *tbinfo, return; /* Comments are SCHEMA not data */ - if (dopt->dataOnly) + if (!dopt->dumpSchema) return; /* Search for comments associated with relation, using table */ @@ -10474,6 +11557,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj) case DO_SUBSCRIPTION_REL: dumpSubscriptionTable(fout, (const SubRelInfo *) dobj); break; + case DO_REL_STATS: + dumpRelationStats(fout, (const RelStatsInfo *) dobj); + break; case DO_PRE_DATA_BOUNDARY: case DO_POST_DATA_BOUNDARY: /* never dumped, nothing to do */ @@ -10493,8 +11579,8 @@ dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo) PQExpBuffer delq; char *qnspname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -10570,8 +11656,8 @@ dumpExtension(Archive *fout, const ExtensionInfo *extinfo) PQExpBuffer delq; char *qextname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -10695,8 +11781,8 @@ dumpType(Archive *fout, const TypeInfo *tyinfo) { DumpOptions *dopt = fout->dopt; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* Dump out in proper style */ @@ -11806,8 +12892,8 @@ dumpShellType(Archive *fout, const ShellTypeInfo *stinfo) DumpOptions *dopt = fout->dopt; PQExpBuffer q; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -11858,8 +12944,8 @@ dumpProcLang(Archive *fout, const ProcLangInfo *plang) FuncInfo *inlineInfo = NULL; FuncInfo *validatorInfo = NULL; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* @@ -12066,8 +13152,8 @@ dumpFunc(Archive *fout, const FuncInfo *finfo) int nconfigitems = 0; const char *keyword; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -12263,7 +13349,7 @@ dumpFunc(Archive *fout, const FuncInfo *finfo) if (*protrftypes) { - Oid *typeids = palloc(FUNC_MAX_ARGS * sizeof(Oid)); + Oid *typeids = pg_malloc(FUNC_MAX_ARGS * sizeof(Oid)); int i; appendPQExpBufferStr(q, " TRANSFORM "); @@ -12275,6 +13361,8 @@ dumpFunc(Archive *fout, const FuncInfo *finfo) appendPQExpBuffer(q, "FOR TYPE %s", getFormattedTypeName(fout, typeids[i], zeroAsNone)); } + + free(typeids); } if (prokind[0] == PROKIND_WINDOW) @@ -12458,8 +13546,8 @@ dumpCast(Archive *fout, const CastInfo *cast) const char *sourceType; const char *targetType; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* Cannot dump if we don't have the cast function's info */ @@ -12564,8 +13652,8 @@ dumpTransform(Archive *fout, const TransformInfo *transform) char *lanname; const char *transformType; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* Cannot dump if we don't have the transform functions' info */ @@ -12713,8 +13801,8 @@ dumpOpr(Archive *fout, const OprInfo *oprinfo) char *oprregproc; char *oprref; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* @@ -13000,8 +14088,8 @@ dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo) PQExpBuffer delq; char *qamname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -13103,8 +14191,8 @@ dumpOpclass(Archive *fout, const OpclassInfo *opcinfo) bool needComma; int i; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -13374,8 +14462,8 @@ dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo) bool needComma; int i; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -13581,8 +14669,8 @@ dumpCollation(Archive *fout, const CollInfo *collinfo) const char *colllocale; const char *collicurules; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -13835,8 +14923,8 @@ dumpConversion(Archive *fout, const ConvInfo *convinfo) const char *conproc; bool condefault; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -13983,8 +15071,8 @@ dumpAgg(Archive *fout, const AggInfo *agginfo) const char *proparallel; char defaultfinalmodify; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -14313,8 +15401,8 @@ dumpTSParser(Archive *fout, const TSParserInfo *prsinfo) PQExpBuffer delq; char *qprsname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14381,8 +15469,8 @@ dumpTSDictionary(Archive *fout, const TSDictInfo *dictinfo) char *nspname; char *tmplname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14457,8 +15545,8 @@ dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo) PQExpBuffer delq; char *qtmplname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14523,8 +15611,8 @@ dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo) int i_tokenname; int i_dictname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14635,8 +15723,8 @@ dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo) PQExpBuffer delq; char *qfdwname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14708,8 +15796,8 @@ dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo) char *qsrvname; char *fdwname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -14899,8 +15987,8 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo) PQExpBuffer tag; const char *type; - /* Do nothing in data-only dump, or if we're skipping ACLs */ - if (dopt->dataOnly || dopt->aclsSkip) + /* Do nothing if not dumping schema, or if we're skipping ACLs */ + if (!dopt->dumpSchema || dopt->aclsSkip) return; q = createPQExpBuffer(); @@ -14923,6 +16011,9 @@ dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo) case DEFACLOBJ_NAMESPACE: type = "SCHEMAS"; break; + case DEFACLOBJ_LARGEOBJECT: + type = "LARGE OBJECTS"; + break; default: /* shouldn't get here */ pg_fatal("unrecognized object type in default privileges: %d", @@ -15000,7 +16091,7 @@ dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId, return InvalidDumpId; /* --data-only skips ACLs *except* large object ACLs */ - if (dopt->dataOnly && strcmp(type, "LARGE OBJECT") != 0) + if (!dopt->dumpSchema && strcmp(type, "LARGE OBJECT") != 0) return InvalidDumpId; sql = createPQExpBuffer(); @@ -15129,13 +16220,13 @@ dumpSecLabel(Archive *fout, const char *type, const char *name, */ if (strcmp(type, "LARGE OBJECT") != 0) { - if (dopt->dataOnly) + if (!dopt->dumpSchema) return; } else { /* We do dump large object security labels in binary-upgrade mode */ - if (dopt->schemaOnly && !dopt->binary_upgrade) + if (!dopt->dumpData && !dopt->binary_upgrade) return; } @@ -15203,7 +16294,7 @@ dumpTableSecLabel(Archive *fout, const TableInfo *tbinfo, const char *reltypenam return; /* SecLabel are SCHEMA not data */ - if (dopt->dataOnly) + if (!dopt->dumpSchema) return; /* Search for comments associated with relation, using table */ @@ -15442,8 +16533,8 @@ dumpTable(Archive *fout, const TableInfo *tbinfo) DumpId tableAclDumpId = InvalidDumpId; char *namecopy; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) @@ -15670,6 +16761,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) DumpOptions *dopt = fout->dopt; PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); + PQExpBuffer extra = createPQExpBuffer(); char *qrelname; char *qualrelname; int numParents; @@ -15736,7 +16828,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) char *partkeydef = NULL; char *ftoptions = NULL; char *srvname = NULL; - char *foreign = ""; + const char *foreign = ""; /* * Set reltypename, and collect any relkind-specific data that we @@ -15812,8 +16904,13 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) binary_upgrade_set_pg_class_oids(fout, q, tbinfo->dobj.catId.oid); + /* + * PostgreSQL 18 has disabled UNLOGGED for partitioned tables, so + * ignore it when dumping if it was set in this case. + */ appendPQExpBuffer(q, "CREATE %s%s %s", - tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? + (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED && + tbinfo->relkind != RELKIND_PARTITIONED_TABLE) ? "UNLOGGED " : "", reltypename, qualrelname); @@ -15853,13 +16950,14 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) !tbinfo->attrdefs[j]->separate); /* - * Not Null constraint --- suppress if inherited, except - * if partition, or in binary-upgrade case where that - * won't work. + * Not Null constraint --- print it if it is locally + * defined, or if binary upgrade. (In the latter case, we + * reset conislocal below.) */ - print_notnull = (tbinfo->notnull[j] && - (!tbinfo->inhNotNull[j] || - tbinfo->ispartition || dopt->binary_upgrade)); + print_notnull = (tbinfo->notnull_constrs[j] != NULL && + (tbinfo->notnull_islocal[j] || + dopt->binary_upgrade || + tbinfo->ispartition)); /* * Skip column if fully defined by reloftype, except in @@ -15910,14 +17008,25 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_STORED) appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s) STORED", tbinfo->attrdefs[j]->adef_expr); + else if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_VIRTUAL) + appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s)", + tbinfo->attrdefs[j]->adef_expr); else appendPQExpBuffer(q, " DEFAULT %s", tbinfo->attrdefs[j]->adef_expr); } - if (print_notnull) - appendPQExpBufferStr(q, " NOT NULL"); + { + if (tbinfo->notnull_constrs[j][0] == '\0') + appendPQExpBufferStr(q, " NOT NULL"); + else + appendPQExpBuffer(q, " CONSTRAINT %s NOT NULL", + fmtId(tbinfo->notnull_constrs[j])); + + if (tbinfo->notnull_noinh[j]) + appendPQExpBufferStr(q, " NO INHERIT"); + } /* Add collation if not default for the type */ if (OidIsValid(tbinfo->attcollation[j])) @@ -15930,6 +17039,38 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) fmtQualifiedDumpable(coll)); } } + + /* + * On the other hand, if we choose not to print a column + * (likely because it is created by inheritance), but the + * column has a locally-defined not-null constraint, we need + * to dump the constraint as a standalone object. + * + * This syntax isn't SQL-conforming, but if you wanted + * standard output you wouldn't be creating non-standard + * objects to begin with. + */ + if (!shouldPrintColumn(dopt, tbinfo, j) && + !tbinfo->attisdropped[j] && + tbinfo->notnull_constrs[j] != NULL && + tbinfo->notnull_islocal[j]) + { + /* Format properly if not first attr */ + if (actual_atts == 0) + appendPQExpBufferStr(q, " ("); + else + appendPQExpBufferChar(q, ','); + appendPQExpBufferStr(q, "\n "); + actual_atts++; + + if (tbinfo->notnull_constrs[j][0] == '\0') + appendPQExpBuffer(q, "NOT NULL %s", + fmtId(tbinfo->attnames[j])); + else + appendPQExpBuffer(q, "CONSTRAINT %s NOT NULL %s", + tbinfo->notnull_constrs[j], + fmtId(tbinfo->attnames[j])); + } } /* @@ -16094,51 +17235,164 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) tbinfo->relkind == RELKIND_FOREIGN_TABLE || tbinfo->relkind == RELKIND_PARTITIONED_TABLE)) { + bool firstitem; + bool firstitem_extra; + + /* + * Drop any dropped columns. Merge the pg_attribute manipulations + * into a single SQL command, so that we don't cause repeated + * relcache flushes on the target table. Otherwise we risk O(N^2) + * relcache bloat while dropping N columns. + */ + resetPQExpBuffer(extra); + firstitem = true; for (j = 0; j < tbinfo->numatts; j++) { if (tbinfo->attisdropped[j]) { - appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate dropped column.\n"); - appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n" - "SET attlen = %d, " - "attalign = '%c', attbyval = false\n" - "WHERE attname = ", + if (firstitem) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate dropped columns.\n" + "UPDATE pg_catalog.pg_attribute\n" + "SET attlen = v.dlen, " + "attalign = v.dalign, " + "attbyval = false\n" + "FROM (VALUES "); + firstitem = false; + } + else + appendPQExpBufferStr(q, ",\n "); + appendPQExpBufferChar(q, '('); + appendStringLiteralAH(q, tbinfo->attnames[j], fout); + appendPQExpBuffer(q, ", %d, '%c')", tbinfo->attlen[j], tbinfo->attalign[j]); - appendStringLiteralAH(q, tbinfo->attnames[j], fout); - appendPQExpBufferStr(q, "\n AND attrelid = "); - appendStringLiteralAH(q, qualrelname, fout); - appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); - - if (tbinfo->relkind == RELKIND_RELATION || - tbinfo->relkind == RELKIND_PARTITIONED_TABLE) - appendPQExpBuffer(q, "ALTER TABLE ONLY %s ", - qualrelname); - else - appendPQExpBuffer(q, "ALTER FOREIGN TABLE ONLY %s ", - qualrelname); - appendPQExpBuffer(q, "DROP COLUMN %s;\n", + /* The ALTER ... DROP COLUMN commands must come after */ + appendPQExpBuffer(extra, "ALTER %sTABLE ONLY %s ", + foreign, qualrelname); + appendPQExpBuffer(extra, "DROP COLUMN %s;\n", fmtId(tbinfo->attnames[j])); } - else if (!tbinfo->attislocal[j]) + } + if (!firstitem) + { + appendPQExpBufferStr(q, ") v(dname, dlen, dalign)\n" + "WHERE attrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass\n" + " AND attname = v.dname;\n"); + /* Now we can issue the actual DROP COLUMN commands */ + appendBinaryPQExpBuffer(q, extra->data, extra->len); + } + + /* + * Fix up inherited columns. As above, do the pg_attribute + * manipulations in a single SQL command. + */ + firstitem = true; + for (j = 0; j < tbinfo->numatts; j++) + { + if (!tbinfo->attisdropped[j] && + !tbinfo->attislocal[j]) { - appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate inherited column.\n"); - appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_attribute\n" - "SET attislocal = false\n" - "WHERE attname = "); + if (firstitem) + { + appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate inherited columns.\n"); + appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_attribute\n" + "SET attislocal = false\n" + "WHERE attrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass\n" + " AND attname IN ("); + firstitem = false; + } + else + appendPQExpBufferStr(q, ", "); appendStringLiteralAH(q, tbinfo->attnames[j], fout); - appendPQExpBufferStr(q, "\n AND attrelid = "); - appendStringLiteralAH(q, qualrelname, fout); - appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); } } + if (!firstitem) + appendPQExpBufferStr(q, ");\n"); + + /* + * Fix up not-null constraints that come from inheritance. As + * above, do the pg_constraint manipulations in a single SQL + * command. (Actually, two in special cases, if we're doing an + * upgrade from < 18). + */ + firstitem = true; + firstitem_extra = true; + resetPQExpBuffer(extra); + for (j = 0; j < tbinfo->numatts; j++) + { + /* + * If a not-null constraint comes from inheritance, reset + * conislocal. The inhcount is fixed by ALTER TABLE INHERIT, + * below. Special hack: in versions < 18, columns with no + * local definition need their constraint to be matched by + * column number in conkeys instead of by constraint name, + * because the latter is not available. (We distinguish the + * case because the constraint name is the empty string.) + */ + if (tbinfo->notnull_constrs[j] != NULL && + !tbinfo->notnull_islocal[j]) + { + if (tbinfo->notnull_constrs[j][0] != '\0') + { + if (firstitem) + { + appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_constraint\n" + "SET conislocal = false\n" + "WHERE contype = 'n' AND conrelid = "); + appendStringLiteralAH(q, qualrelname, fout); + appendPQExpBufferStr(q, "::pg_catalog.regclass AND\n" + "conname IN ("); + firstitem = false; + } + else + appendPQExpBufferStr(q, ", "); + appendStringLiteralAH(q, tbinfo->notnull_constrs[j], fout); + } + else + { + if (firstitem_extra) + { + appendPQExpBufferStr(extra, "UPDATE pg_catalog.pg_constraint\n" + "SET conislocal = false\n" + "WHERE contype = 'n' AND conrelid = "); + appendStringLiteralAH(extra, qualrelname, fout); + appendPQExpBufferStr(extra, "::pg_catalog.regclass AND\n" + "conkey IN ("); + firstitem_extra = false; + } + else + appendPQExpBufferStr(extra, ", "); + appendPQExpBuffer(extra, "'{%d}'", j + 1); + } + } + } + if (!firstitem) + appendPQExpBufferStr(q, ");\n"); + if (!firstitem_extra) + appendPQExpBufferStr(extra, ");\n"); + + if (extra->len > 0) + appendBinaryPQExpBuffer(q, extra->data, extra->len); /* * Add inherited CHECK constraints, if any. * * For partitions, they were already dumped, and conislocal * doesn't need fixing. + * + * As above, issue only one direct manipulation of pg_constraint. + * Although it is tempting to merge the ALTER ADD CONSTRAINT + * commands into one as well, refrain for now due to concern about + * possible backend memory bloat if there are many such + * constraints. */ + resetPQExpBuffer(extra); + firstitem = true; for (k = 0; k < tbinfo->ncheck; k++) { ConstraintInfo *constr = &(tbinfo->checkexprs[k]); @@ -16146,18 +17400,31 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) if (constr->separate || constr->conislocal || tbinfo->ispartition) continue; - appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n"); + if (firstitem) + appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraints.\n"); appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ADD CONSTRAINT %s %s;\n", foreign, qualrelname, fmtId(constr->dobj.name), constr->condef); - appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_constraint\n" - "SET conislocal = false\n" - "WHERE contype = 'c' AND conname = "); - appendStringLiteralAH(q, constr->dobj.name, fout); - appendPQExpBufferStr(q, "\n AND conrelid = "); - appendStringLiteralAH(q, qualrelname, fout); - appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); + /* Update pg_constraint after all the ALTER TABLEs */ + if (firstitem) + { + appendPQExpBufferStr(extra, "UPDATE pg_catalog.pg_constraint\n" + "SET conislocal = false\n" + "WHERE contype = 'c' AND conrelid = "); + appendStringLiteralAH(extra, qualrelname, fout); + appendPQExpBufferStr(extra, "::pg_catalog.regclass\n"); + appendPQExpBufferStr(extra, " AND conname IN ("); + firstitem = false; + } + else + appendPQExpBufferStr(extra, ", "); + appendStringLiteralAH(extra, constr->dobj.name, fout); + } + if (!firstitem) + { + appendPQExpBufferStr(extra, ");\n"); + appendBinaryPQExpBuffer(q, extra->data, extra->len); } if (numParents > 0 && !tbinfo->ispartition) @@ -16245,18 +17512,6 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) if (tbinfo->attisdropped[j]) continue; - /* - * If we didn't dump the column definition explicitly above, and - * it is not-null and did not inherit that property from a parent, - * we have to mark it separately. - */ - if (!shouldPrintColumn(dopt, tbinfo, j) && - tbinfo->notnull[j] && !tbinfo->inhNotNull[j]) - appendPQExpBuffer(q, - "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET NOT NULL;\n", - foreign, qualrelname, - fmtId(tbinfo->attnames[j])); - /* * Dump per-column statistics information. We only issue an ALTER * TABLE statement if the attstattarget entry for this column is @@ -16344,7 +17599,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && tbinfo->attfdwoptions[j][0] != '\0') appendPQExpBuffer(q, - "ALTER FOREIGN TABLE %s ALTER COLUMN %s OPTIONS (\n" + "ALTER FOREIGN TABLE ONLY %s ALTER COLUMN %s OPTIONS (\n" " %s\n" ");\n", qualrelname, @@ -16445,6 +17700,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) destroyPQExpBuffer(q); destroyPQExpBuffer(delq); + destroyPQExpBuffer(extra); free(qrelname); free(qualrelname); } @@ -16472,8 +17728,8 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo) PGresult *res; char *partbound; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -16544,8 +17800,8 @@ dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo) char *tag; char *foreign; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* Skip if not "separate"; it was dumped in the table's definition */ @@ -16633,8 +17889,8 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo) char *qindxname; char *qqindxname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -16727,7 +17983,17 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo) qindxname); } - appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); + /* + * If this index is a member of a partitioned index, the backend will + * not allow us to drop it separately, so don't try. It will go away + * automatically when we drop either the index's table or the + * partitioned index. (If, in a selective restore with --clean, we + * drop neither of those, then this index will not be dropped either. + * But that's fine, and even if you think it's not, the backend won't + * let us do differently.) + */ + if (indxinfo->parentidx == 0) + appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname); if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION) ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId, @@ -16766,8 +18032,8 @@ dumpIndex(Archive *fout, const IndxInfo *indxinfo) static void dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo) { - /* Do nothing in data-only dump */ - if (fout->dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!fout->dopt->dumpSchema) return; if (attachinfo->partitionIdx->dobj.dump & DUMP_COMPONENT_DEFINITION) @@ -16780,11 +18046,15 @@ dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo) fmtQualifiedDumpable(attachinfo->partitionIdx)); /* - * There is no point in creating a drop query as the drop is done by - * index drop. (If you think to change this, see also - * _printTocEntry().) Although this object doesn't really have - * ownership as such, set the owner field anyway to ensure that the - * command is run by the correct role at restore time. + * There is no need for a dropStmt since the drop is done implicitly + * when we drop either the index's table or the partitioned index. + * Moreover, since there's no ALTER INDEX DETACH PARTITION command, + * there's no way to do it anyway. (If you think to change this, + * consider also what to do with --if-exists.) + * + * Although this object doesn't really have ownership as such, set the + * owner field anyway to ensure that the command is run by the correct + * role at restore time. */ ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId, ARCHIVE_OPTS(.tag = attachinfo->dobj.name, @@ -16813,8 +18083,8 @@ dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo) PGresult *res; char *stxdef; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -16889,8 +18159,8 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) char *tag = NULL; char *foreign; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; q = createPQExpBuffer(); @@ -16954,6 +18224,8 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) (k == 0) ? "" : ", ", fmtId(attname)); } + if (coninfo->conperiod) + appendPQExpBufferStr(q, " WITHOUT OVERLAPS"); if (indxinfo->indnkeyattrs < indxinfo->indnattrs) appendPQExpBufferStr(q, ") INCLUDE ("); @@ -17079,13 +18351,20 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) .createStmt = q->data, .dropStmt = delq->data)); } - else if (coninfo->contype == 'c' && tbinfo) + else if ((coninfo->contype == 'c' || coninfo->contype == 'n') && tbinfo) { - /* CHECK constraint on a table */ + /* CHECK or invalid not-null constraint on a table */ /* Ignore if not to be dumped separately, or if it was inherited */ if (coninfo->separate && coninfo->conislocal) { + const char *keyword; + + if (coninfo->contype == 'c') + keyword = "CHECK CONSTRAINT"; + else + keyword = "CONSTRAINT"; + /* not ONLY since we want it to propagate to children */ appendPQExpBuffer(q, "ALTER %sTABLE %s\n", foreign, fmtQualifiedDumpable(tbinfo)); @@ -17105,7 +18384,7 @@ dumpConstraint(Archive *fout, const ConstraintInfo *coninfo) ARCHIVE_OPTS(.tag = tag, .namespace = tbinfo->dobj.namespace->dobj.name, .owner = tbinfo->rolname, - .description = "CHECK CONSTRAINT", + .description = keyword, .section = SECTION_POST_DATA, .createStmt = q->data, .dropStmt = delq->data)); @@ -17189,6 +18468,94 @@ dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo) free(qtabname); } +static inline SeqType +parse_sequence_type(const char *name) +{ + for (int i = 0; i < lengthof(SeqTypeNames); i++) + { + if (strcmp(SeqTypeNames[i], name) == 0) + return (SeqType) i; + } + + pg_fatal("unrecognized sequence type: %s", name); + return (SeqType) 0; /* keep compiler quiet */ +} + +/* + * bsearch() comparator for SequenceItem + */ +static int +SequenceItemCmp(const void *p1, const void *p2) +{ + SequenceItem v1 = *((const SequenceItem *) p1); + SequenceItem v2 = *((const SequenceItem *) p2); + + return pg_cmp_u32(v1.oid, v2.oid); +} + +/* + * collectSequences + * + * Construct a table of sequence information. This table is sorted by OID for + * speed in lookup. + */ +static void +collectSequences(Archive *fout) +{ + PGresult *res; + const char *query; + + /* + * Before Postgres 10, sequence metadata is in the sequence itself. With + * some extra effort, we might be able to use the sorted table for those + * versions, but for now it seems unlikely to be worth it. + * + * Since version 18, we can gather the sequence data in this query with + * pg_get_sequence_data(), but we only do so for non-schema-only dumps. + */ + if (fout->remoteVersion < 100000) + return; + else if (fout->remoteVersion < 180000 || + (!fout->dopt->dumpData && !fout->dopt->sequence_data)) + query = "SELECT seqrelid, format_type(seqtypid, NULL), " + "seqstart, seqincrement, " + "seqmax, seqmin, " + "seqcache, seqcycle, " + "NULL, 'f' " + "FROM pg_catalog.pg_sequence " + "ORDER BY seqrelid"; + else + query = "SELECT seqrelid, format_type(seqtypid, NULL), " + "seqstart, seqincrement, " + "seqmax, seqmin, " + "seqcache, seqcycle, " + "last_value, is_called " + "FROM pg_catalog.pg_sequence, " + "pg_get_sequence_data(seqrelid) " + "ORDER BY seqrelid;"; + + res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK); + + nsequences = PQntuples(res); + sequences = (SequenceItem *) pg_malloc(nsequences * sizeof(SequenceItem)); + + for (int i = 0; i < nsequences; i++) + { + sequences[i].oid = atooid(PQgetvalue(res, i, 0)); + sequences[i].seqtype = parse_sequence_type(PQgetvalue(res, i, 1)); + sequences[i].startv = strtoi64(PQgetvalue(res, i, 2), NULL, 10); + sequences[i].incby = strtoi64(PQgetvalue(res, i, 3), NULL, 10); + sequences[i].maxv = strtoi64(PQgetvalue(res, i, 4), NULL, 10); + sequences[i].minv = strtoi64(PQgetvalue(res, i, 5), NULL, 10); + sequences[i].cache = strtoi64(PQgetvalue(res, i, 6), NULL, 10); + sequences[i].cycled = (strcmp(PQgetvalue(res, i, 7), "t") == 0); + sequences[i].last_value = strtoi64(PQgetvalue(res, i, 8), NULL, 10); + sequences[i].is_called = (strcmp(PQgetvalue(res, i, 9), "t") == 0); + } + + PQclear(res); +} + /* * dumpSequence * write the declaration (not data) of one user-defined sequence @@ -17197,19 +18564,10 @@ static void dumpSequence(Archive *fout, const TableInfo *tbinfo) { DumpOptions *dopt = fout->dopt; - PGresult *res; - char *startv, - *incby, - *maxv, - *minv, - *cache, - *seqtype; - bool cycled; + SequenceItem *seq; bool is_ascending; int64 default_minv, default_maxv; - char bufm[32], - bufx[32]; PQExpBuffer query = createPQExpBuffer(); PQExpBuffer delqry = createPQExpBuffer(); char *qseqname; @@ -17217,19 +18575,25 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) qseqname = pg_strdup(fmtId(tbinfo->dobj.name)); + /* + * For versions >= 10, the sequence information is gathered in a sorted + * table before any calls to dumpSequence(). See collectSequences() for + * more information. + */ if (fout->remoteVersion >= 100000) { - appendPQExpBuffer(query, - "SELECT format_type(seqtypid, NULL), " - "seqstart, seqincrement, " - "seqmax, seqmin, " - "seqcache, seqcycle " - "FROM pg_catalog.pg_sequence " - "WHERE seqrelid = '%u'::oid", - tbinfo->dobj.catId.oid); + SequenceItem key = {0}; + + Assert(sequences); + + key.oid = tbinfo->dobj.catId.oid; + seq = bsearch(&key, sequences, nsequences, + sizeof(SequenceItem), SequenceItemCmp); } else { + PGresult *res; + /* * Before PostgreSQL 10, sequence metadata is in the sequence itself. * @@ -17241,60 +18605,50 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) "start_value, increment_by, max_value, min_value, " "cache_value, is_cycled FROM %s", fmtQualifiedDumpable(tbinfo)); - } - res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); - if (PQntuples(res) != 1) - pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", - "query to get data of sequence \"%s\" returned %d rows (expected 1)", - PQntuples(res)), - tbinfo->dobj.name, PQntuples(res)); - - seqtype = PQgetvalue(res, 0, 0); - startv = PQgetvalue(res, 0, 1); - incby = PQgetvalue(res, 0, 2); - maxv = PQgetvalue(res, 0, 3); - minv = PQgetvalue(res, 0, 4); - cache = PQgetvalue(res, 0, 5); - cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0); + if (PQntuples(res) != 1) + pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", + "query to get data of sequence \"%s\" returned %d rows (expected 1)", + PQntuples(res)), + tbinfo->dobj.name, PQntuples(res)); + + seq = pg_malloc0(sizeof(SequenceItem)); + seq->seqtype = parse_sequence_type(PQgetvalue(res, 0, 0)); + seq->startv = strtoi64(PQgetvalue(res, 0, 1), NULL, 10); + seq->incby = strtoi64(PQgetvalue(res, 0, 2), NULL, 10); + seq->maxv = strtoi64(PQgetvalue(res, 0, 3), NULL, 10); + seq->minv = strtoi64(PQgetvalue(res, 0, 4), NULL, 10); + seq->cache = strtoi64(PQgetvalue(res, 0, 5), NULL, 10); + seq->cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0); + + PQclear(res); + } /* Calculate default limits for a sequence of this type */ - is_ascending = (incby[0] != '-'); - if (strcmp(seqtype, "smallint") == 0) + is_ascending = (seq->incby >= 0); + if (seq->seqtype == SEQTYPE_SMALLINT) { default_minv = is_ascending ? 1 : PG_INT16_MIN; default_maxv = is_ascending ? PG_INT16_MAX : -1; } - else if (strcmp(seqtype, "integer") == 0) + else if (seq->seqtype == SEQTYPE_INTEGER) { default_minv = is_ascending ? 1 : PG_INT32_MIN; default_maxv = is_ascending ? PG_INT32_MAX : -1; } - else if (strcmp(seqtype, "bigint") == 0) + else if (seq->seqtype == SEQTYPE_BIGINT) { default_minv = is_ascending ? 1 : PG_INT64_MIN; default_maxv = is_ascending ? PG_INT64_MAX : -1; } else { - pg_fatal("unrecognized sequence type: %s", seqtype); + pg_fatal("unrecognized sequence type: %d", seq->seqtype); default_minv = default_maxv = 0; /* keep compiler quiet */ } - /* - * 64-bit strtol() isn't very portable, so convert the limits to strings - * and compare that way. - */ - snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv); - snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv); - - /* Don't print minv/maxv if they match the respective default limit */ - if (strcmp(minv, bufm) == 0) - minv = NULL; - if (strcmp(maxv, bufx) == 0) - maxv = NULL; - /* * Identity sequences are not to be dropped separately. */ @@ -17333,6 +18687,15 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) appendPQExpBufferStr(query, "BY DEFAULT"); appendPQExpBuffer(query, " AS IDENTITY (\n SEQUENCE NAME %s\n", fmtQualifiedDumpable(tbinfo)); + + /* + * Emit persistence option only if it's different from the owning + * table's. This avoids using this new syntax unnecessarily. + */ + if (tbinfo->relpersistence != owning_tab->relpersistence) + appendPQExpBuffer(query, " %s\n", + tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? + "UNLOGGED" : "LOGGED"); } else { @@ -17342,38 +18705,30 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) "UNLOGGED " : "", fmtQualifiedDumpable(tbinfo)); - if (strcmp(seqtype, "bigint") != 0) - appendPQExpBuffer(query, " AS %s\n", seqtype); + if (seq->seqtype != SEQTYPE_BIGINT) + appendPQExpBuffer(query, " AS %s\n", SeqTypeNames[seq->seqtype]); } - appendPQExpBuffer(query, " START WITH %s\n", startv); + appendPQExpBuffer(query, " START WITH " INT64_FORMAT "\n", seq->startv); - appendPQExpBuffer(query, " INCREMENT BY %s\n", incby); + appendPQExpBuffer(query, " INCREMENT BY " INT64_FORMAT "\n", seq->incby); - if (minv) - appendPQExpBuffer(query, " MINVALUE %s\n", minv); + if (seq->minv != default_minv) + appendPQExpBuffer(query, " MINVALUE " INT64_FORMAT "\n", seq->minv); else appendPQExpBufferStr(query, " NO MINVALUE\n"); - if (maxv) - appendPQExpBuffer(query, " MAXVALUE %s\n", maxv); + if (seq->maxv != default_maxv) + appendPQExpBuffer(query, " MAXVALUE " INT64_FORMAT "\n", seq->maxv); else appendPQExpBufferStr(query, " NO MAXVALUE\n"); appendPQExpBuffer(query, - " CACHE %s%s", - cache, (cycled ? "\n CYCLE" : "")); + " CACHE " INT64_FORMAT "%s", + seq->cache, (seq->cycled ? "\n CYCLE" : "")); if (tbinfo->is_identity_sequence) - { appendPQExpBufferStr(query, "\n);\n"); - if (tbinfo->relpersistence != owning_tab->relpersistence) - appendPQExpBuffer(query, - "ALTER SEQUENCE %s SET %s;\n", - fmtQualifiedDumpable(tbinfo), - tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ? - "UNLOGGED" : "LOGGED"); - } else appendPQExpBufferStr(query, ";\n"); @@ -17448,8 +18803,8 @@ dumpSequence(Archive *fout, const TableInfo *tbinfo) tbinfo->dobj.namespace->dobj.name, tbinfo->rolname, tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId); - PQclear(res); - + if (fout->remoteVersion < 100000) + pg_free(seq); destroyPQExpBuffer(query); destroyPQExpBuffer(delqry); free(qseqname); @@ -17463,30 +18818,59 @@ static void dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo) { TableInfo *tbinfo = tdinfo->tdtable; - PGresult *res; - char *last; + int64 last; bool called; PQExpBuffer query = createPQExpBuffer(); - appendPQExpBuffer(query, - "SELECT last_value, is_called FROM %s", - fmtQualifiedDumpable(tbinfo)); + /* + * For versions >= 18, the sequence information is gathered in the sorted + * array before any calls to dumpSequenceData(). See collectSequences() + * for more information. + * + * For older versions, we have to query the sequence relations + * individually. + */ + if (fout->remoteVersion < 180000) + { + PGresult *res; - res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + appendPQExpBuffer(query, + "SELECT last_value, is_called FROM %s", + fmtQualifiedDumpable(tbinfo)); - if (PQntuples(res) != 1) - pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", - "query to get data of sequence \"%s\" returned %d rows (expected 1)", - PQntuples(res)), - tbinfo->dobj.name, PQntuples(res)); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + if (PQntuples(res) != 1) + pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)", + "query to get data of sequence \"%s\" returned %d rows (expected 1)", + PQntuples(res)), + tbinfo->dobj.name, PQntuples(res)); - last = PQgetvalue(res, 0, 0); - called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0); + last = strtoi64(PQgetvalue(res, 0, 0), NULL, 10); + called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0); + + PQclear(res); + } + else + { + SequenceItem key = {0}; + SequenceItem *entry; + + Assert(sequences); + Assert(tbinfo->dobj.catId.oid); + + key.oid = tbinfo->dobj.catId.oid; + entry = bsearch(&key, sequences, nsequences, + sizeof(SequenceItem), SequenceItemCmp); + + last = entry->last_value; + called = entry->is_called; + } resetPQExpBuffer(query); appendPQExpBufferStr(query, "SELECT pg_catalog.setval("); appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout); - appendPQExpBuffer(query, ", %s, %s);\n", + appendPQExpBuffer(query, ", " INT64_FORMAT ", %s);\n", last, (called ? "true" : "false")); if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA) @@ -17500,8 +18884,6 @@ dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo) .deps = &(tbinfo->dobj.dumpId), .nDeps = 1)); - PQclear(res); - destroyPQExpBuffer(query); } @@ -17521,8 +18903,8 @@ dumpTrigger(Archive *fout, const TriggerInfo *tginfo) char *qtabname; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -17643,8 +19025,8 @@ dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo) PQExpBuffer delqry; char *qevtname; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; query = createPQExpBuffer(); @@ -17734,8 +19116,8 @@ dumpRule(Archive *fout, const RuleInfo *rinfo) PGresult *res; char *tag; - /* Do nothing in data-only dump */ - if (dopt->dataOnly) + /* Do nothing if not dumping schema */ + if (!dopt->dumpSchema) return; /* @@ -18001,7 +19383,7 @@ processExtensionTables(Archive *fout, ExtensionInfo extinfo[], * objects for them, ensuring their data will be dumped even though the * tables themselves won't be. * - * Note that we create TableDataInfo objects even in schemaOnly mode, ie, + * Note that we create TableDataInfo objects even in schema-only mode, ie, * user data in a configuration table is treated like schema data. This * seems appropriate since system data in a config table would get * reloaded by CREATE EXTENSION. If the extension is not listed in the @@ -18426,6 +19808,16 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs, /* must come after the pre-data boundary */ addObjectDependency(dobj, preDataBound->dumpId); break; + case DO_REL_STATS: + /* stats section varies by parent object type, DATA or POST */ + if (((RelStatsInfo *) dobj)->section == SECTION_DATA) + { + addObjectDependency(dobj, preDataBound->dumpId); + addObjectDependency(postDataBound, dobj->dumpId); + } + else + addObjectDependency(dobj, postDataBound->dumpId); + break; } } } diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 4b2e5870a9cef..7417eab6aefa6 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -3,7 +3,7 @@ * pg_dump.h * Common header file for the pg_dump utility * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_dump/pg_dump.h @@ -15,6 +15,7 @@ #define PG_DUMP_H #include "pg_backup.h" +#include "catalog/pg_publication_d.h" #define oidcmp(x,y) ( ((x) < (y) ? -1 : ((x) > (y)) ? 1 : 0) ) @@ -82,15 +83,26 @@ typedef enum DO_PUBLICATION, DO_PUBLICATION_REL, DO_PUBLICATION_TABLE_IN_SCHEMA, + DO_REL_STATS, DO_SUBSCRIPTION, DO_SUBSCRIPTION_REL, /* see note for SubRelInfo */ } DumpableObjectType; +#define NUM_DUMPABLE_OBJECT_TYPES (DO_SUBSCRIPTION_REL + 1) + /* * DumpComponents is a bitmask of the potentially dumpable components of * a database object: its core definition, plus optional attributes such - * as ACL, comments, etc. The NONE and ALL symbols are convenient - * shorthands. + * as ACL, comments, etc. + * + * The NONE and ALL symbols are convenient shorthands for assigning values, + * but be careful about using them in tests. For example, a test like + * "if (dobj->dump == DUMP_COMPONENT_NONE)" is probably wrong; you likely want + * "if (!(dobj->dump & DUMP_COMPONENT_DEFINITION))" instead. This is because + * we aren't too careful about the values of irrelevant bits, as indeed can be + * seen in the definition of DUMP_COMPONENT_ALL. It's also possible that an + * object has only subsidiary bits such as DUMP_COMPONENT_ACL set, leading to + * unexpected behavior of a test against NONE. */ typedef uint32 DumpComponents; #define DUMP_COMPONENT_NONE (0) @@ -101,6 +113,7 @@ typedef uint32 DumpComponents; #define DUMP_COMPONENT_ACL (1 << 4) #define DUMP_COMPONENT_POLICY (1 << 5) #define DUMP_COMPONENT_USERMAP (1 << 6) +#define DUMP_COMPONENT_STATISTICS (1 << 7) #define DUMP_COMPONENT_ALL (0xFFFF) /* @@ -128,6 +141,7 @@ typedef uint32 DumpComponents; #define DUMP_COMPONENTS_REQUIRING_LOCK (\ DUMP_COMPONENT_DEFINITION |\ DUMP_COMPONENT_DATA |\ + DUMP_COMPONENT_STATISTICS |\ DUMP_COMPONENT_POLICY) typedef struct _dumpableObject @@ -200,6 +214,7 @@ typedef struct _typeInfo const char *rolname; Oid typelem; Oid typrelid; + Oid typarray; char typrelkind; /* 'r', 'v', 'c', etc */ char typtype; /* 'b', 'c', etc */ bool isArray; /* true if auto-generated array type */ @@ -313,7 +328,7 @@ typedef struct _tableInfo Oid owning_tab; /* OID of table owning sequence */ int owning_col; /* attr # of column owning sequence */ bool is_identity_sequence; - int relpages; /* table's size in pages (from pg_class) */ + int32 relpages; /* table's size in pages (from pg_class) */ int toastpages; /* toast table's size in pages, if any */ bool interesting; /* true if need to collect more data */ @@ -346,10 +361,16 @@ typedef struct _tableInfo char *attcompression; /* per-attribute compression method */ char **attfdwoptions; /* per-attribute fdw options */ char **attmissingval; /* per attribute missing value */ - bool *notnull; /* not-null constraints on attributes */ - bool *inhNotNull; /* true if NOT NULL is inherited */ + char **notnull_constrs; /* NOT NULL constraint names. If null, + * there isn't one on this column. If + * empty string, unnamed constraint + * (pre-v17) */ + bool *notnull_invalid; /* true for NOT NULL NOT VALID */ + bool *notnull_noinh; /* NOT NULL is NO INHERIT */ + bool *notnull_islocal; /* true if NOT NULL has local definition */ struct _attrDefInfo **attrdefs; /* DEFAULT expressions */ struct _constraintInfo *checkexprs; /* CHECK constraints */ + struct _relStatsInfo *stats; /* only set for matviews */ bool needs_override; /* has GENERATED ALWAYS AS IDENTITY */ char *amname; /* relation access method */ @@ -416,6 +437,24 @@ typedef struct _indexAttachInfo IndxInfo *partitionIdx; /* link to index on partition */ } IndexAttachInfo; +typedef struct _relStatsInfo +{ + DumpableObject dobj; + int32 relpages; + char *reltuples; + int32 relallvisible; + int32 relallfrozen; + char relkind; /* 'r', 'm', 'i', etc */ + + /* + * indAttNames/nindAttNames are populated only if the relation is an index + * with at least one expression column; we don't need them otherwise. + */ + char **indAttNames; /* attnames of the index, in order */ + int32 nindAttNames; /* number of attnames stored (can be 0) */ + teSection section; /* stats may appear in data or post-data */ +} RelStatsInfo; + typedef struct _statsExtInfo { DumpableObject dobj; @@ -460,6 +499,8 @@ typedef struct _evttriggerInfo * use a different objType for foreign key constraints, to make it easier * to sort them the way we want. * + * Not-null constraints don't need this, unless they are NOT VALID. + * * Note: condeferrable and condeferred are currently only valid for * unique/primary-key constraints. Otherwise that info is in condef. */ @@ -474,6 +515,7 @@ typedef struct _constraintInfo DumpId conindex; /* identifies associated index if any */ bool condeferrable; /* true if constraint is DEFERRABLE */ bool condeferred; /* true if constraint is INITIALLY DEFERRED */ + bool conperiod; /* true if the constraint is WITHOUT OVERLAPS */ bool conislocal; /* true if constraint has local definition */ bool separate; /* true if must dump as separate item */ } ConstraintInfo; @@ -624,6 +666,7 @@ typedef struct _PublicationInfo bool pubdelete; bool pubtruncate; bool pubviaroot; + PublishGencolsType pubgencols_type; } PublicationInfo; /* @@ -657,20 +700,20 @@ typedef struct _SubscriptionInfo { DumpableObject dobj; const char *rolname; - char *subenabled; - char *subbinary; - char *substream; - char *subtwophasestate; - char *subdisableonerr; - char *subpasswordrequired; - char *subrunasowner; + bool subenabled; + bool subbinary; + char substream; + char subtwophasestate; + bool subdisableonerr; + bool subpasswordrequired; + bool subrunasowner; + bool subfailover; char *subconninfo; char *subslotname; char *subsynccommit; char *subpublications; char *suborigin; char *suboriginremotelsn; - char *subfailover; } SubscriptionInfo; /* diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index 4cb754caa55fd..0b0977788f13d 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -4,7 +4,7 @@ * Sort the items of a dump into a safe order for dumping * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -18,7 +18,6 @@ #include "catalog/pg_class_d.h" #include "common/int.h" #include "lib/binaryheap.h" -#include "pg_backup_archiver.h" #include "pg_backup_utils.h" #include "pg_dump.h" @@ -82,6 +81,7 @@ enum dbObjectTypePriorities PRIO_TABLE_DATA, PRIO_SEQUENCE_SET, PRIO_LARGE_OBJECT_DATA, + PRIO_STATISTICS_DATA_DATA, PRIO_POST_DATA_BOUNDARY, /* boundary! */ PRIO_CONSTRAINT, PRIO_INDEX, @@ -149,11 +149,12 @@ static const int dbObjectTypePriority[] = [DO_PUBLICATION] = PRIO_PUBLICATION, [DO_PUBLICATION_REL] = PRIO_PUBLICATION_REL, [DO_PUBLICATION_TABLE_IN_SCHEMA] = PRIO_PUBLICATION_TABLE_IN_SCHEMA, + [DO_REL_STATS] = PRIO_STATISTICS_DATA_DATA, [DO_SUBSCRIPTION] = PRIO_SUBSCRIPTION, [DO_SUBSCRIPTION_REL] = PRIO_SUBSCRIPTION_REL, }; -StaticAssertDecl(lengthof(dbObjectTypePriority) == (DO_SUBSCRIPTION_REL + 1), +StaticAssertDecl(lengthof(dbObjectTypePriority) == NUM_DUMPABLE_OBJECT_TYPES, "array length mismatch"); static DumpId preDataBoundId; @@ -294,6 +295,17 @@ DOTypeNameCompare(const void *p1, const void *p2) if (cmpval != 0) return cmpval; } + else if (obj1->objType == DO_RULE) + { + RuleInfo *robj1 = *(RuleInfo *const *) p1; + RuleInfo *robj2 = *(RuleInfo *const *) p2; + + /* Sort by table name (table namespace was considered already) */ + cmpval = strcmp(robj1->ruletable->dobj.name, + robj2->ruletable->dobj.name); + if (cmpval != 0) + return cmpval; + } else if (obj1->objType == DO_TRIGGER) { TriggerInfo *tobj1 = *(TriggerInfo *const *) p1; @@ -791,7 +803,11 @@ repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj, { /* remove boundary's dependency on object after it in loop */ removeObjectDependency(boundaryobj, nextobj->dumpId); - /* if that object is a matview, mark it as postponed into post-data */ + + /* + * If that object is a matview or matview stats, mark it as postponed into + * post-data. + */ if (nextobj->objType == DO_TABLE) { TableInfo *nextinfo = (TableInfo *) nextobj; @@ -799,6 +815,13 @@ repairMatViewBoundaryMultiLoop(DumpableObject *boundaryobj, if (nextinfo->relkind == RELKIND_MATVIEW) nextinfo->postponed_def = true; } + else if (nextobj->objType == DO_REL_STATS) + { + RelStatsInfo *nextinfo = (RelStatsInfo *) nextobj; + + if (nextinfo->relkind == RELKIND_MATVIEW) + nextinfo->section = SECTION_POST_DATA; + } } /* @@ -1008,6 +1031,21 @@ repairDependencyLoop(DumpableObject **loop, { DumpableObject *nextobj; + nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0]; + repairMatViewBoundaryMultiLoop(loop[j], nextobj); + return; + } + } + } + else if (loop[i]->objType == DO_REL_STATS && + ((RelStatsInfo *) loop[i])->relkind == RELKIND_MATVIEW) + { + for (j = 0; j < nLoop; j++) + { + if (loop[j]->objType == DO_POST_DATA_BOUNDARY) + { + DumpableObject *nextobj; + nextobj = (j < nLoop - 1) ? loop[j + 1] : loop[0]; repairMatViewBoundaryMultiLoop(loop[j], nextobj); return; @@ -1490,6 +1528,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize) "POST-DATA BOUNDARY (ID %d)", obj->dumpId); return; + case DO_REL_STATS: + snprintf(buf, bufsize, + "RELATION STATISTICS FOR %s (ID %d OID %u)", + obj->name, obj->dumpId, obj->catId.oid); + return; } /* shouldn't get here */ snprintf(buf, bufsize, diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 882dbf8e8657a..b1f388cb39160 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -2,7 +2,7 @@ * * pg_dumpall.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * pg_dumpall forces all pg_dump output to be text, since it also outputs @@ -20,15 +20,16 @@ #include "catalog/pg_authid_d.h" #include "common/connect.h" +#include "common/file_perm.h" #include "common/file_utils.h" #include "common/hashfn_unstable.h" #include "common/logging.h" #include "common/string.h" +#include "connectdb.h" #include "dumputils.h" #include "fe_utils/string_utils.h" #include "filter.h" #include "getopt_long.h" -#include "pg_backup.h" /* version string we expect back from pg_dump */ #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n" @@ -64,28 +65,23 @@ static void dropTablespaces(PGconn *conn); static void dumpTablespaces(PGconn *conn); static void dropDBs(PGconn *conn); static void dumpUserConfig(PGconn *conn, const char *username); -static void dumpDatabases(PGconn *conn); +static void dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat); static void dumpTimestamp(const char *msg); -static int runPgDump(const char *dbname, const char *create_opts); +static int runPgDump(const char *dbname, const char *create_opts, + char *dbfile, ArchiveFormat archDumpFormat); static void buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, const char *objtype, const char *objname, PQExpBuffer buffer); -static PGconn *connectDatabase(const char *dbname, - const char *connection_string, const char *pghost, - const char *pgport, const char *pguser, - trivalue prompt_password, bool fail_on_error); -static char *constructConnStr(const char **keywords, const char **values); -static PGresult *executeQuery(PGconn *conn, const char *query); static void executeCommand(PGconn *conn, const char *query); static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, SimpleStringList *names); static void read_dumpall_filters(const char *filename, SimpleStringList *pattern); +static ArchiveFormat parseDumpFormat(const char *format); static char pg_dump_bin[MAXPGPATH]; -static const char *progname; static PQExpBuffer pgdumpopts; -static char *connstr = ""; +static const char *connstr = ""; static bool output_clean = false; static bool skip_acls = false; static bool verbose = false; @@ -101,15 +97,24 @@ static int no_table_access_method = 0; static int no_tablespaces = 0; static int use_setsessauth = 0; static int no_comments = 0; +static int no_policies = 0; static int no_publications = 0; static int no_security_labels = 0; +static int no_data = 0; +static int no_schema = 0; +static int no_statistics = 0; static int no_subscriptions = 0; static int no_toast_compression = 0; static int no_unlogged_table_data = 0; static int no_role_passwords = 0; +static int with_data = 0; +static int with_schema = 0; +static int with_statistics = 0; static int server_version; static int load_via_partition_root = 0; static int on_conflict_do_nothing = 0; +static int statistics_only = 0; +static int sequence_data = 0; static char role_catalog[10]; #define PG_AUTHID "pg_authid" @@ -121,8 +126,6 @@ static char *filename = NULL; static SimpleStringList database_exclude_patterns = {NULL, NULL}; static SimpleStringList database_exclude_names = {NULL, NULL}; -#define exit_nicely(code) exit(code) - int main(int argc, char *argv[]) { @@ -147,6 +150,7 @@ main(int argc, char *argv[]) {"password", no_argument, NULL, 'W'}, {"no-privileges", no_argument, NULL, 'x'}, {"no-acl", no_argument, NULL, 'x'}, + {"format", required_argument, NULL, 'F'}, /* * the following options don't have an equivalent short option letter @@ -168,16 +172,25 @@ main(int argc, char *argv[]) {"role", required_argument, NULL, 3}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"no-comments", no_argument, &no_comments, 1}, + {"no-data", no_argument, &no_data, 1}, + {"no-policies", no_argument, &no_policies, 1}, {"no-publications", no_argument, &no_publications, 1}, {"no-role-passwords", no_argument, &no_role_passwords, 1}, + {"no-schema", no_argument, &no_schema, 1}, {"no-security-labels", no_argument, &no_security_labels, 1}, {"no-subscriptions", no_argument, &no_subscriptions, 1}, + {"no-statistics", no_argument, &no_statistics, 1}, {"no-sync", no_argument, NULL, 4}, {"no-toast-compression", no_argument, &no_toast_compression, 1}, {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1}, + {"with-data", no_argument, &with_data, 1}, + {"with-schema", no_argument, &with_schema, 1}, + {"with-statistics", no_argument, &with_statistics, 1}, {"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1}, {"rows-per-insert", required_argument, NULL, 7}, + {"statistics-only", no_argument, &statistics_only, 1}, {"filter", required_argument, NULL, 8}, + {"sequence-data", no_argument, &sequence_data, 1}, {NULL, 0, NULL, 0} }; @@ -188,6 +201,8 @@ main(int argc, char *argv[]) char *pgdb = NULL; char *use_role = NULL; const char *dumpencoding = NULL; + ArchiveFormat archDumpFormat = archNull; + const char *formatName = "p"; trivalue prompt_password = TRI_DEFAULT; bool data_only = false; bool globals_only = false; @@ -237,7 +252,7 @@ main(int argc, char *argv[]) pgdumpopts = createPQExpBuffer(); - while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "acd:E:f:F:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1) { switch (c) { @@ -265,7 +280,9 @@ main(int argc, char *argv[]) appendPQExpBufferStr(pgdumpopts, " -f "); appendShellString(pgdumpopts, filename); break; - + case 'F': + formatName = pg_strdup(optarg); + break; case 'g': globals_only = true; break; @@ -414,6 +431,21 @@ main(int argc, char *argv[]) exit_nicely(1); } + /* Get format for dump. */ + archDumpFormat = parseDumpFormat(formatName); + + /* + * If a non-plain format is specified, a file name is also required as the + * path to the main directory. + */ + if (archDumpFormat != archNull && + (!filename || strcmp(filename, "") == 0)) + { + pg_log_error("option -F/--format=d|c|t requires option -f/--file"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit_nicely(1); + } + /* * If password values are not required in the dump, switch to using * pg_roles which is equally useful, just more likely to have unrestricted @@ -447,18 +479,63 @@ main(int argc, char *argv[]) appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization"); if (no_comments) appendPQExpBufferStr(pgdumpopts, " --no-comments"); + if (no_data) + appendPQExpBufferStr(pgdumpopts, " --no-data"); + if (no_policies) + appendPQExpBufferStr(pgdumpopts, " --no-policies"); if (no_publications) appendPQExpBufferStr(pgdumpopts, " --no-publications"); if (no_security_labels) appendPQExpBufferStr(pgdumpopts, " --no-security-labels"); + if (no_schema) + appendPQExpBufferStr(pgdumpopts, " --no-schema"); + if (no_statistics) + appendPQExpBufferStr(pgdumpopts, " --no-statistics"); if (no_subscriptions) appendPQExpBufferStr(pgdumpopts, " --no-subscriptions"); if (no_toast_compression) appendPQExpBufferStr(pgdumpopts, " --no-toast-compression"); if (no_unlogged_table_data) appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data"); + if (with_data) + appendPQExpBufferStr(pgdumpopts, " --with-data"); + if (with_schema) + appendPQExpBufferStr(pgdumpopts, " --with-schema"); + if (with_statistics) + appendPQExpBufferStr(pgdumpopts, " --with-statistics"); if (on_conflict_do_nothing) appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing"); + if (statistics_only) + appendPQExpBufferStr(pgdumpopts, " --statistics-only"); + if (sequence_data) + appendPQExpBufferStr(pgdumpopts, " --sequence-data"); + + /* + * Open the output file if required, otherwise use stdout. If required, + * then create new directory and global.dat file. + */ + if (archDumpFormat != archNull) + { + char global_path[MAXPGPATH]; + + /* Create new directory or accept the empty existing directory. */ + create_or_open_dir(filename); + + snprintf(global_path, MAXPGPATH, "%s/global.dat", filename); + + OPF = fopen(global_path, PG_BINARY_W); + if (!OPF) + pg_fatal("could not open file \"%s\": %m", global_path); + } + else if (filename) + { + OPF = fopen(filename, PG_BINARY_W); + if (!OPF) + pg_fatal("could not open output file \"%s\": %m", + filename); + } + else + OPF = stdout; /* * If there was a database specified on the command line, use that, @@ -467,19 +544,22 @@ main(int argc, char *argv[]) */ if (pgdb) { - conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser, - prompt_password, false); + conn = ConnectDatabase(pgdb, connstr, pghost, pgport, pguser, + prompt_password, false, + progname, &connstr, &server_version, NULL, NULL); if (!conn) pg_fatal("could not connect to database \"%s\"", pgdb); } else { - conn = connectDatabase("postgres", connstr, pghost, pgport, pguser, - prompt_password, false); + conn = ConnectDatabase("postgres", connstr, pghost, pgport, pguser, + prompt_password, false, + progname, &connstr, &server_version, NULL, NULL); if (!conn) - conn = connectDatabase("template1", connstr, pghost, pgport, pguser, - prompt_password, true); + conn = ConnectDatabase("template1", connstr, pghost, pgport, pguser, + prompt_password, true, + progname, &connstr, &server_version, NULL, NULL); if (!conn) { @@ -496,19 +576,6 @@ main(int argc, char *argv[]) expand_dbname_patterns(conn, &database_exclude_patterns, &database_exclude_names); - /* - * Open the output file if required, otherwise use stdout - */ - if (filename) - { - OPF = fopen(filename, PG_BINARY_W); - if (!OPF) - pg_fatal("could not open output file \"%s\": %m", - filename); - } - else - OPF = stdout; - /* * Set the client encoding if requested. */ @@ -524,6 +591,7 @@ main(int argc, char *argv[]) * we know how to escape strings. */ encoding = PQclientEncoding(conn); + setFmtEncoding(encoding); std_strings = PQparameterStatus(conn, "standard_conforming_strings"); if (!std_strings) std_strings = "off"; @@ -607,7 +675,7 @@ main(int argc, char *argv[]) } if (!globals_only && !roles_only && !tablespaces_only) - dumpDatabases(conn); + dumpDatabases(conn, archDumpFormat); PQfinish(conn); @@ -620,7 +688,7 @@ main(int argc, char *argv[]) fclose(OPF); /* sync the resulting file, errors are not fatal */ - if (dosync) + if (dosync && (archDumpFormat == archNull)) (void) fsync_fname(filename, false); } @@ -631,24 +699,26 @@ main(int argc, char *argv[]) static void help(void) { - printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname); + printf(_("%s extracts a PostgreSQL database cluster based on specified dump format.\n\n"), progname); printf(_("Usage:\n")); printf(_(" %s [OPTION]...\n"), progname); printf(_("\nGeneral options:\n")); printf(_(" -f, --file=FILENAME output file name\n")); + printf(_(" -F, --format=c|d|t|p output file format (custom, directory, tar,\n" + " plain text (default))\n")); printf(_(" -v, --verbose verbose mode\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\nOptions controlling the output content:\n")); - printf(_(" -a, --data-only dump only the data, not the schema\n")); + printf(_(" -a, --data-only dump only the data, not the schema or statistics\n")); printf(_(" -c, --clean clean (drop) databases before recreating\n")); printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n")); printf(_(" -g, --globals-only dump only global objects, no databases\n")); printf(_(" -O, --no-owner skip restoration of object ownership\n")); printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n")); - printf(_(" -s, --schema-only dump only the schema, no data\n")); + printf(_(" -s, --schema-only dump only the schema, no data or statistics\n")); printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n")); printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n")); printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n")); @@ -658,14 +728,18 @@ help(void) printf(_(" --disable-triggers disable triggers during data-only restore\n")); printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n")); printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n")); - printf(_(" --filter=FILENAME exclude databases specified in FILENAME\n")); + printf(_(" --filter=FILENAME exclude databases based on expressions in FILENAME\n")); printf(_(" --if-exists use IF EXISTS when dropping objects\n")); printf(_(" --inserts dump data as INSERT commands, rather than COPY\n")); printf(_(" --load-via-partition-root load partitions via the root table\n")); - printf(_(" --no-comments do not dump comments\n")); + printf(_(" --no-comments do not dump comment commands\n")); + printf(_(" --no-data do not dump data\n")); + printf(_(" --no-policies do not dump row security policies\n")); printf(_(" --no-publications do not dump publications\n")); printf(_(" --no-role-passwords do not dump passwords for roles\n")); + printf(_(" --no-schema do not dump schema\n")); printf(_(" --no-security-labels do not dump security label assignments\n")); + printf(_(" --no-statistics do not dump statistics\n")); printf(_(" --no-subscriptions do not dump subscriptions\n")); printf(_(" --no-sync do not wait for changes to be written safely to disk\n")); printf(_(" --no-table-access-method do not dump table access methods\n")); @@ -675,9 +749,14 @@ help(void) printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n")); printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n")); + printf(_(" --sequence-data include sequence data in dump\n")); + printf(_(" --statistics-only dump only the statistics, not schema or data\n")); printf(_(" --use-set-session-authorization\n" " use SET SESSION AUTHORIZATION commands instead of\n" " ALTER OWNER commands to set ownership\n")); + printf(_(" --with-data dump the data\n")); + printf(_(" --with-schema dump the schema\n")); + printf(_(" --with-statistics dump the statistics\n")); printf(_("\nConnection options:\n")); printf(_(" -d, --dbname=CONNSTR connect using connection string\n")); @@ -934,9 +1013,6 @@ dumpRoles(PGconn *conn) * We do it this way because config settings for roles could mention the * names of other roles. */ - if (PQntuples(res) > 0) - fprintf(OPF, "\n--\n-- User Configurations\n--\n"); - for (i = 0; i < PQntuples(res); i++) dumpUserConfig(conn, PQgetvalue(res, i, i_rolname)); @@ -965,6 +1041,13 @@ dumpRoleMembership(PGconn *conn) total; bool dump_grantors; bool dump_grant_options; + int i_role; + int i_member; + int i_grantor; + int i_roleid; + int i_memberid; + int i_grantorid; + int i_admin_option; int i_inherit_option; int i_set_option; @@ -974,6 +1057,10 @@ dumpRoleMembership(PGconn *conn) * they didn't have ADMIN OPTION on the role, or a user that no longer * existed. To avoid dump and restore failures, don't dump the grantor * when talking to an old server version. + * + * Also, in older versions the roleid and/or member could be role OIDs + * that no longer exist. If we find such cases, print a warning and skip + * the entry. */ dump_grantors = (PQserverVersion(conn) >= 160000); @@ -985,8 +1072,10 @@ dumpRoleMembership(PGconn *conn) /* Generate and execute query. */ printfPQExpBuffer(buf, "SELECT ur.rolname AS role, " "um.rolname AS member, " - "ug.oid AS grantorid, " "ug.rolname AS grantor, " + "a.roleid AS roleid, " + "a.member AS memberid, " + "a.grantor AS grantorid, " "a.admin_option"); if (dump_grant_options) appendPQExpBufferStr(buf, ", a.inherit_option, a.set_option"); @@ -995,8 +1084,15 @@ dumpRoleMembership(PGconn *conn) "LEFT JOIN %s um on um.oid = a.member " "LEFT JOIN %s ug on ug.oid = a.grantor " "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')" - "ORDER BY 1,2,4", role_catalog, role_catalog, role_catalog); + "ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog); res = executeQuery(conn, buf->data); + i_role = PQfnumber(res, "role"); + i_member = PQfnumber(res, "member"); + i_grantor = PQfnumber(res, "grantor"); + i_roleid = PQfnumber(res, "roleid"); + i_memberid = PQfnumber(res, "memberid"); + i_grantorid = PQfnumber(res, "grantorid"); + i_admin_option = PQfnumber(res, "admin_option"); i_inherit_option = PQfnumber(res, "inherit_option"); i_set_option = PQfnumber(res, "set_option"); @@ -1020,24 +1116,32 @@ dumpRoleMembership(PGconn *conn) total = PQntuples(res); while (start < total) { - char *role = PQgetvalue(res, start, 0); + char *role = PQgetvalue(res, start, i_role); int i; bool *done; int remaining; int prev_remaining = 0; rolename_hash *ht; + /* If we hit a null roleid, we're done (nulls sort to the end). */ + if (PQgetisnull(res, start, i_role)) + { + /* translator: %s represents a numeric role OID */ + pg_log_warning("found orphaned pg_auth_members entry for role %s", + PQgetvalue(res, start, i_roleid)); + break; + } + /* All memberships for a single role should be adjacent. */ for (end = start; end < total; ++end) { char *otherrole; - otherrole = PQgetvalue(res, end, 0); + otherrole = PQgetvalue(res, end, i_role); if (strcmp(role, otherrole) != 0) break; } - role = PQgetvalue(res, start, 0); remaining = end - start; done = pg_malloc0(remaining * sizeof(bool)); ht = rolename_create(remaining, NULL); @@ -1077,10 +1181,30 @@ dumpRoleMembership(PGconn *conn) if (done[i - start]) continue; - member = PQgetvalue(res, i, 1); - grantorid = PQgetvalue(res, i, 2); - grantor = PQgetvalue(res, i, 3); - admin_option = PQgetvalue(res, i, 4); + /* Complain about, then ignore, entries with orphaned OIDs. */ + if (PQgetisnull(res, i, i_member)) + { + /* translator: %s represents a numeric role OID */ + pg_log_warning("found orphaned pg_auth_members entry for role %s", + PQgetvalue(res, i, i_memberid)); + done[i - start] = true; + --remaining; + continue; + } + if (PQgetisnull(res, i, i_grantor)) + { + /* translator: %s represents a numeric role OID */ + pg_log_warning("found orphaned pg_auth_members entry for role %s", + PQgetvalue(res, i, i_grantorid)); + done[i - start] = true; + --remaining; + continue; + } + + member = PQgetvalue(res, i, i_member); + grantor = PQgetvalue(res, i, i_grantor); + grantorid = PQgetvalue(res, i, i_grantorid); + admin_option = PQgetvalue(res, i, i_admin_option); if (dump_grant_options) set_option = PQgetvalue(res, i, i_set_option); @@ -1127,7 +1251,7 @@ dumpRoleMembership(PGconn *conn) { if (optbuf->data[0] != '\0') appendPQExpBufferStr(optbuf, ", "); - appendPQExpBuffer(optbuf, "SET FALSE"); + appendPQExpBufferStr(optbuf, "SET FALSE"); } if (optbuf->data[0] != '\0') fprintf(OPF, " WITH %s", optbuf->data); @@ -1402,6 +1526,7 @@ dumpUserConfig(PGconn *conn, const char *username) { PQExpBuffer buf = createPQExpBuffer(); PGresult *res; + static bool header_done = false; printfPQExpBuffer(buf, "SELECT unnest(setconfig) FROM pg_db_role_setting " "WHERE setdatabase = 0 AND setrole = " @@ -1413,7 +1538,13 @@ dumpUserConfig(PGconn *conn, const char *username) res = executeQuery(conn, buf->data); if (PQntuples(res) > 0) + { + if (!header_done) + fprintf(OPF, "\n--\n-- User Configurations\n--\n"); + header_done = true; + fprintf(OPF, "\n--\n-- User Config \"%s\"\n--\n\n", username); + } for (int i = 0; i < PQntuples(res); i++) { @@ -1487,10 +1618,13 @@ expand_dbname_patterns(PGconn *conn, * Dump contents of databases. */ static void -dumpDatabases(PGconn *conn) +dumpDatabases(PGconn *conn, ArchiveFormat archDumpFormat) { PGresult *res; int i; + char db_subdir[MAXPGPATH]; + char dbfilepath[MAXPGPATH]; + FILE *map_file = NULL; /* * Skip databases marked not datallowconn, since we'd be unable to connect @@ -1504,18 +1638,42 @@ dumpDatabases(PGconn *conn) * doesn't have some failure mode with --clean. */ res = executeQuery(conn, - "SELECT datname " + "SELECT datname, oid " "FROM pg_database d " "WHERE datallowconn AND datconnlimit != -2 " "ORDER BY (datname <> 'template1'), datname"); - if (PQntuples(res) > 0) + if (archDumpFormat == archNull && PQntuples(res) > 0) fprintf(OPF, "--\n-- Databases\n--\n\n"); + /* + * If directory/tar/custom format is specified, create a subdirectory + * under the main directory and each database dump file or subdirectory + * will be created in that subdirectory by pg_dump. + */ + if (archDumpFormat != archNull) + { + char map_file_path[MAXPGPATH]; + + snprintf(db_subdir, MAXPGPATH, "%s/databases", filename); + + /* Create a subdirectory with 'databases' name under main directory. */ + if (mkdir(db_subdir, pg_dir_create_mode) != 0) + pg_fatal("could not create directory \"%s\": %m", db_subdir); + + snprintf(map_file_path, MAXPGPATH, "%s/map.dat", filename); + + /* Create a map file (to store dboid and dbname) */ + map_file = fopen(map_file_path, PG_BINARY_W); + if (!map_file) + pg_fatal("could not open file \"%s\": %m", map_file_path); + } + for (i = 0; i < PQntuples(res); i++) { char *dbname = PQgetvalue(res, i, 0); - const char *create_opts; + char *oid = PQgetvalue(res, i, 1); + const char *create_opts = ""; int ret; /* Skip template0, even if it's not marked !datallowconn. */ @@ -1529,9 +1687,27 @@ dumpDatabases(PGconn *conn) continue; } + /* + * If this is not a plain format dump, then append dboid and dbname to + * the map.dat file. + */ + if (archDumpFormat != archNull) + { + if (archDumpFormat == archCustom) + snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".dmp", db_subdir, oid); + else if (archDumpFormat == archTar) + snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\".tar", db_subdir, oid); + else + snprintf(dbfilepath, MAXPGPATH, "\"%s\"/\"%s\"", db_subdir, oid); + + /* Put one line entry for dboid and dbname in map file. */ + fprintf(map_file, "%s %s\n", oid, dbname); + } + pg_log_info("dumping database \"%s\"", dbname); - fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", dbname); + if (archDumpFormat == archNull) + fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", dbname); /* * We assume that "template1" and "postgres" already exist in the @@ -1545,12 +1721,9 @@ dumpDatabases(PGconn *conn) { if (output_clean) create_opts = "--clean --create"; - else - { - create_opts = ""; - /* Since pg_dump won't emit a \connect command, we must */ + /* Since pg_dump won't emit a \connect command, we must */ + else if (archDumpFormat == archNull) fprintf(OPF, "\\connect %s\n\n", dbname); - } } else create_opts = "--create"; @@ -1558,19 +1731,30 @@ dumpDatabases(PGconn *conn) if (filename) fclose(OPF); - ret = runPgDump(dbname, create_opts); + ret = runPgDump(dbname, create_opts, dbfilepath, archDumpFormat); if (ret != 0) pg_fatal("pg_dump failed on database \"%s\", exiting", dbname); if (filename) { - OPF = fopen(filename, PG_BINARY_A); + char global_path[MAXPGPATH]; + + if (archDumpFormat != archNull) + snprintf(global_path, MAXPGPATH, "%s/global.dat", filename); + else + snprintf(global_path, MAXPGPATH, "%s", filename); + + OPF = fopen(global_path, PG_BINARY_A); if (!OPF) pg_fatal("could not re-open the output file \"%s\": %m", - filename); + global_path); } } + /* Close map file */ + if (archDumpFormat != archNull) + fclose(map_file); + PQclear(res); } @@ -1580,7 +1764,8 @@ dumpDatabases(PGconn *conn) * Run pg_dump on dbname, with specified options. */ static int -runPgDump(const char *dbname, const char *create_opts) +runPgDump(const char *dbname, const char *create_opts, char *dbfile, + ArchiveFormat archDumpFormat) { PQExpBufferData connstrbuf; PQExpBufferData cmd; @@ -1589,17 +1774,36 @@ runPgDump(const char *dbname, const char *create_opts) initPQExpBuffer(&connstrbuf); initPQExpBuffer(&cmd); - printfPQExpBuffer(&cmd, "\"%s\" %s %s", pg_dump_bin, - pgdumpopts->data, create_opts); - /* - * If we have a filename, use the undocumented plain-append pg_dump - * format. + * If this is not a plain format dump, then append file name and dump + * format to the pg_dump command to get archive dump. */ - if (filename) - appendPQExpBufferStr(&cmd, " -Fa "); + if (archDumpFormat != archNull) + { + printfPQExpBuffer(&cmd, "\"%s\" -f %s %s", pg_dump_bin, + dbfile, create_opts); + + if (archDumpFormat == archDirectory) + appendPQExpBufferStr(&cmd, " --format=directory "); + else if (archDumpFormat == archCustom) + appendPQExpBufferStr(&cmd, " --format=custom "); + else if (archDumpFormat == archTar) + appendPQExpBufferStr(&cmd, " --format=tar "); + } else - appendPQExpBufferStr(&cmd, " -Fp "); + { + printfPQExpBuffer(&cmd, "\"%s\" %s %s", pg_dump_bin, + pgdumpopts->data, create_opts); + + /* + * If we have a filename, use the undocumented plain-append pg_dump + * format. + */ + if (filename) + appendPQExpBufferStr(&cmd, " -Fa "); + else + appendPQExpBufferStr(&cmd, " -Fp "); + } /* * Append the database name to the already-constructed stem of connection @@ -1649,256 +1853,6 @@ buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, destroyPQExpBuffer(sql); } -/* - * Make a database connection with the given parameters. An - * interactive password prompt is automatically issued if required. - * - * If fail_on_error is false, we return NULL without printing any message - * on failure, but preserve any prompted password for the next try. - * - * On success, the global variable 'connstr' is set to a connection string - * containing the options used. - */ -static PGconn * -connectDatabase(const char *dbname, const char *connection_string, - const char *pghost, const char *pgport, const char *pguser, - trivalue prompt_password, bool fail_on_error) -{ - PGconn *conn; - bool new_pass; - const char *remoteversion_str; - int my_version; - const char **keywords = NULL; - const char **values = NULL; - PQconninfoOption *conn_opts = NULL; - static char *password = NULL; - - if (prompt_password == TRI_YES && !password) - password = simple_prompt("Password: ", false); - - /* - * Start the connection. Loop until we have a password if requested by - * backend. - */ - do - { - int argcount = 6; - PQconninfoOption *conn_opt; - char *err_msg = NULL; - int i = 0; - - free(keywords); - free(values); - PQconninfoFree(conn_opts); - - /* - * Merge the connection info inputs given in form of connection string - * and other options. Explicitly discard any dbname value in the - * connection string; otherwise, PQconnectdbParams() would interpret - * that value as being itself a connection string. - */ - if (connection_string) - { - conn_opts = PQconninfoParse(connection_string, &err_msg); - if (conn_opts == NULL) - pg_fatal("%s", err_msg); - - for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) - { - if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && - strcmp(conn_opt->keyword, "dbname") != 0) - argcount++; - } - - keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); - values = pg_malloc0((argcount + 1) * sizeof(*values)); - - for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) - { - if (conn_opt->val != NULL && conn_opt->val[0] != '\0' && - strcmp(conn_opt->keyword, "dbname") != 0) - { - keywords[i] = conn_opt->keyword; - values[i] = conn_opt->val; - i++; - } - } - } - else - { - keywords = pg_malloc0((argcount + 1) * sizeof(*keywords)); - values = pg_malloc0((argcount + 1) * sizeof(*values)); - } - - if (pghost) - { - keywords[i] = "host"; - values[i] = pghost; - i++; - } - if (pgport) - { - keywords[i] = "port"; - values[i] = pgport; - i++; - } - if (pguser) - { - keywords[i] = "user"; - values[i] = pguser; - i++; - } - if (password) - { - keywords[i] = "password"; - values[i] = password; - i++; - } - if (dbname) - { - keywords[i] = "dbname"; - values[i] = dbname; - i++; - } - keywords[i] = "fallback_application_name"; - values[i] = progname; - i++; - - new_pass = false; - conn = PQconnectdbParams(keywords, values, true); - - if (!conn) - pg_fatal("could not connect to database \"%s\"", dbname); - - if (PQstatus(conn) == CONNECTION_BAD && - PQconnectionNeedsPassword(conn) && - !password && - prompt_password != TRI_NO) - { - PQfinish(conn); - password = simple_prompt("Password: ", false); - new_pass = true; - } - } while (new_pass); - - /* check to see that the backend connection was successfully made */ - if (PQstatus(conn) == CONNECTION_BAD) - { - if (fail_on_error) - pg_fatal("%s", PQerrorMessage(conn)); - else - { - PQfinish(conn); - - free(keywords); - free(values); - PQconninfoFree(conn_opts); - - return NULL; - } - } - - /* - * Ok, connected successfully. Remember the options used, in the form of a - * connection string. - */ - connstr = constructConnStr(keywords, values); - - free(keywords); - free(values); - PQconninfoFree(conn_opts); - - /* Check version */ - remoteversion_str = PQparameterStatus(conn, "server_version"); - if (!remoteversion_str) - pg_fatal("could not get server version"); - server_version = PQserverVersion(conn); - if (server_version == 0) - pg_fatal("could not parse server version \"%s\"", - remoteversion_str); - - my_version = PG_VERSION_NUM; - - /* - * We allow the server to be back to 9.2, and up to any minor release of - * our own major version. (See also version check in pg_dump.c.) - */ - if (my_version != server_version - && (server_version < 90200 || - (server_version / 100) > (my_version / 100))) - { - pg_log_error("aborting because of server version mismatch"); - pg_log_error_detail("server version: %s; %s version: %s", - remoteversion_str, progname, PG_VERSION); - exit_nicely(1); - } - - PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL)); - - return conn; -} - -/* ---------- - * Construct a connection string from the given keyword/value pairs. It is - * used to pass the connection options to the pg_dump subprocess. - * - * The following parameters are excluded: - * dbname - varies in each pg_dump invocation - * password - it's not secure to pass a password on the command line - * fallback_application_name - we'll let pg_dump set it - * ---------- - */ -static char * -constructConnStr(const char **keywords, const char **values) -{ - PQExpBuffer buf = createPQExpBuffer(); - char *connstr; - int i; - bool firstkeyword = true; - - /* Construct a new connection string in key='value' format. */ - for (i = 0; keywords[i] != NULL; i++) - { - if (strcmp(keywords[i], "dbname") == 0 || - strcmp(keywords[i], "password") == 0 || - strcmp(keywords[i], "fallback_application_name") == 0) - continue; - - if (!firstkeyword) - appendPQExpBufferChar(buf, ' '); - firstkeyword = false; - appendPQExpBuffer(buf, "%s=", keywords[i]); - appendConnStrVal(buf, values[i]); - } - - connstr = pg_strdup(buf->data); - destroyPQExpBuffer(buf); - return connstr; -} - -/* - * Run a query, return the results, exit program on failure. - */ -static PGresult * -executeQuery(PGconn *conn, const char *query) -{ - PGresult *res; - - pg_log_info("executing %s", query); - - res = PQexec(conn, query); - if (!res || - PQresultStatus(res) != PGRES_TUPLES_OK) - { - pg_log_error("query failed: %s", PQerrorMessage(conn)); - pg_log_error_detail("Query was: %s", query); - PQfinish(conn); - exit_nicely(1); - } - - return res; -} - /* * As above for a SQL command (which returns nothing). */ @@ -1994,3 +1948,36 @@ read_dumpall_filters(const char *filename, SimpleStringList *pattern) filter_free(&fstate); } + +/* + * parseDumpFormat + * + * This will validate dump formats. + */ +static ArchiveFormat +parseDumpFormat(const char *format) +{ + ArchiveFormat archDumpFormat; + + if (pg_strcasecmp(format, "c") == 0) + archDumpFormat = archCustom; + else if (pg_strcasecmp(format, "custom") == 0) + archDumpFormat = archCustom; + else if (pg_strcasecmp(format, "d") == 0) + archDumpFormat = archDirectory; + else if (pg_strcasecmp(format, "directory") == 0) + archDumpFormat = archDirectory; + else if (pg_strcasecmp(format, "p") == 0) + archDumpFormat = archNull; + else if (pg_strcasecmp(format, "plain") == 0) + archDumpFormat = archNull; + else if (pg_strcasecmp(format, "t") == 0) + archDumpFormat = archTar; + else if (pg_strcasecmp(format, "tar") == 0) + archDumpFormat = archTar; + else + pg_fatal("unrecognized output format \"%s\"; please specify \"c\", \"d\", \"p\", or \"t\"", + format); + + return archDumpFormat; +} diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index df119591ccaa0..6ef789cb06d63 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -2,7 +2,7 @@ * * pg_restore.c * pg_restore is an utility extracting postgres database definitions - * from a backup archive created by pg_dump using the archiver + * from a backup archive created by pg_dump/pg_dumpall using the archiver * interface. * * pg_restore will read the backup archive and @@ -41,12 +41,15 @@ #include "postgres_fe.h" #include +#include #ifdef HAVE_TERMIOS_H #include #endif -#include "dumputils.h" +#include "common/string.h" +#include "connectdb.h" #include "fe_utils/option_utils.h" +#include "fe_utils/string_utils.h" #include "filter.h" #include "getopt_long.h" #include "parallel.h" @@ -54,16 +57,43 @@ static void usage(const char *progname); static void read_restore_filters(const char *filename, RestoreOptions *opts); +static bool file_exists_in_directory(const char *dir, const char *filename); +static int restore_one_database(const char *inputFileSpec, RestoreOptions *opts, + int numWorkers, bool append_data, int num); +static int read_one_statement(StringInfo inBuf, FILE *pfile); +static int restore_all_databases(PGconn *conn, const char *dumpdirpath, + SimpleStringList db_exclude_patterns, RestoreOptions *opts, int numWorkers); +static int process_global_sql_commands(PGconn *conn, const char *dumpdirpath, + const char *outfile); +static void copy_or_print_global_file(const char *outfile, FILE *pfile); +static int get_dbnames_list_to_restore(PGconn *conn, + SimplePtrList *dbname_oid_list, + SimpleStringList db_exclude_patterns); +static int get_dbname_oid_list_from_mfile(const char *dumpdirpath, + SimplePtrList *dbname_oid_list); + +/* + * Stores a database OID and the corresponding name. + */ +typedef struct DbOidName +{ + Oid oid; + char str[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string here */ +} DbOidName; + int main(int argc, char **argv) { RestoreOptions *opts; int c; - int exit_code; int numWorkers = 1; - Archive *AH; char *inputFileSpec; + bool data_only = false; + bool schema_only = false; + int n_errors = 0; + bool globals_only = false; + SimpleStringList db_exclude_patterns = {NULL, NULL}; static int disable_triggers = 0; static int enable_row_security = 0; static int if_exists = 0; @@ -72,15 +102,24 @@ main(int argc, char **argv) static int outputNoTablespaces = 0; static int use_setsessauth = 0; static int no_comments = 0; + static int no_data = 0; + static int no_policies = 0; static int no_publications = 0; + static int no_schema = 0; static int no_security_labels = 0; + static int no_statistics = 0; static int no_subscriptions = 0; static int strict_names = 0; + static int statistics_only = 0; + static int with_data = 0; + static int with_schema = 0; + static int with_statistics = 0; struct option cmdopts[] = { {"clean", 0, NULL, 'c'}, {"create", 0, NULL, 'C'}, {"data-only", 0, NULL, 'a'}, + {"globals-only", 0, NULL, 'g'}, {"dbname", 1, NULL, 'd'}, {"exit-on-error", 0, NULL, 'e'}, {"exclude-schema", 1, NULL, 'N'}, @@ -123,10 +162,19 @@ main(int argc, char **argv) {"transaction-size", required_argument, NULL, 5}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"no-comments", no_argument, &no_comments, 1}, + {"no-data", no_argument, &no_data, 1}, + {"no-policies", no_argument, &no_policies, 1}, {"no-publications", no_argument, &no_publications, 1}, + {"no-schema", no_argument, &no_schema, 1}, {"no-security-labels", no_argument, &no_security_labels, 1}, {"no-subscriptions", no_argument, &no_subscriptions, 1}, + {"no-statistics", no_argument, &no_statistics, 1}, + {"with-data", no_argument, &with_data, 1}, + {"with-schema", no_argument, &with_schema, 1}, + {"with-statistics", no_argument, &with_statistics, 1}, + {"statistics-only", no_argument, &statistics_only, 1}, {"filter", required_argument, NULL, 4}, + {"exclude-database", required_argument, NULL, 6}, {NULL, 0, NULL, 0} }; @@ -155,13 +203,13 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "acCd:ef:F:h:I:j:lL:n:N:Op:P:RsS:t:T:U:vwWx1", + while ((c = getopt_long(argc, argv, "acCd:ef:F:gh:I:j:lL:n:N:Op:P:RsS:t:T:U:vwWx1", cmdopts, NULL)) != -1) { switch (c) { case 'a': /* Dump data only */ - opts->dataOnly = 1; + data_only = true; break; case 'c': /* clean (i.e., drop) schema prior to create */ opts->dropSchema = 1; @@ -182,11 +230,14 @@ main(int argc, char **argv) if (strlen(optarg) != 0) opts->formatName = pg_strdup(optarg); break; + case 'g': + /* restore only global.dat file from directory */ + globals_only = true; + break; case 'h': if (strlen(optarg) != 0) opts->cparams.pghost = pg_strdup(optarg); break; - case 'j': /* number of restore jobs */ if (!option_parse_int(optarg, "-j/--jobs", 1, PG_MAX_JOBS, @@ -237,7 +288,7 @@ main(int argc, char **argv) simple_string_list_append(&opts->triggerNames, optarg); break; case 's': /* dump schema only */ - opts->schemaOnly = 1; + schema_only = true; break; case 'S': /* Superuser username */ if (strlen(optarg) != 0) @@ -301,6 +352,9 @@ main(int argc, char **argv) exit(1); opts->exit_on_error = true; break; + case 6: /* database patterns to skip */ + simple_string_list_append(&db_exclude_patterns, optarg); + break; default: /* getopt_long already emitted a complaint */ @@ -328,6 +382,13 @@ main(int argc, char **argv) if (!opts->cparams.dbname && !opts->filename && !opts->tocSummary) pg_fatal("one of -d/--dbname and -f/--file must be specified"); + if (db_exclude_patterns.head != NULL && globals_only) + { + pg_log_error("option --exclude-database cannot be used together with -g/--globals-only"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit_nicely(1); + } + /* Should get at most one of -d and -f, else user is confused */ if (opts->cparams.dbname) { @@ -340,10 +401,31 @@ main(int argc, char **argv) opts->useDB = 1; } - if (opts->dataOnly && opts->schemaOnly) + /* reject conflicting "-only" options */ + if (data_only && schema_only) pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together"); - - if (opts->dataOnly && opts->dropSchema) + if (schema_only && statistics_only) + pg_fatal("options -s/--schema-only and --statistics-only cannot be used together"); + if (data_only && statistics_only) + pg_fatal("options -a/--data-only and --statistics-only cannot be used together"); + + /* reject conflicting "-only" and "no-" options */ + if (data_only && no_data) + pg_fatal("options -a/--data-only and --no-data cannot be used together"); + if (schema_only && no_schema) + pg_fatal("options -s/--schema-only and --no-schema cannot be used together"); + if (statistics_only && no_statistics) + pg_fatal("options --statistics-only and --no-statistics cannot be used together"); + + /* reject conflicting "with-" and "no-" options */ + if (with_data && no_data) + pg_fatal("options --with-data and --no-data cannot be used together"); + if (with_schema && no_schema) + pg_fatal("options --with-schema and --no-schema cannot be used together"); + if (with_statistics && no_statistics) + pg_fatal("options --with-statistics and --no-statistics cannot be used together"); + + if (data_only && opts->dropSchema) pg_fatal("options -c/--clean and -a/--data-only cannot be used together"); if (opts->single_txn && opts->txn_size > 0) @@ -360,6 +442,20 @@ main(int argc, char **argv) if (opts->single_txn && numWorkers > 1) pg_fatal("cannot specify both --single-transaction and multiple jobs"); + /* + * Set derivative flags. An "-only" option may be overridden by an + * explicit "with-" option; e.g. "--schema-only --with-statistics" will + * include schema and statistics. Other ambiguous or nonsensical + * combinations, e.g. "--schema-only --no-schema", will have already + * caused an error in one of the checks above. + */ + opts->dumpData = ((opts->dumpData && !schema_only && !statistics_only) || + (data_only || with_data)) && !no_data; + opts->dumpSchema = ((opts->dumpSchema && !data_only && !statistics_only) || + (schema_only || with_schema)) && !no_schema; + opts->dumpStatistics = ((opts->dumpStatistics && !schema_only && !data_only) || + (statistics_only || with_statistics)) && !no_statistics; + opts->disable_triggers = disable_triggers; opts->enable_row_security = enable_row_security; opts->noDataForFailedTables = no_data_for_failed_tables; @@ -367,6 +463,7 @@ main(int argc, char **argv) opts->noTablespace = outputNoTablespaces; opts->use_setsessauth = use_setsessauth; opts->no_comments = no_comments; + opts->no_policies = no_policies; opts->no_publications = no_publications; opts->no_security_labels = no_security_labels; opts->no_subscriptions = no_subscriptions; @@ -378,29 +475,135 @@ main(int argc, char **argv) if (opts->formatName) { - switch (opts->formatName[0]) + if (pg_strcasecmp(opts->formatName, "c") == 0 || + pg_strcasecmp(opts->formatName, "custom") == 0) + opts->format = archCustom; + else if (pg_strcasecmp(opts->formatName, "d") == 0 || + pg_strcasecmp(opts->formatName, "directory") == 0) + opts->format = archDirectory; + else if (pg_strcasecmp(opts->formatName, "t") == 0 || + pg_strcasecmp(opts->formatName, "tar") == 0) + opts->format = archTar; + else if (pg_strcasecmp(opts->formatName, "p") == 0 || + pg_strcasecmp(opts->formatName, "plain") == 0) { - case 'c': - case 'C': - opts->format = archCustom; - break; + /* recognize this for consistency with pg_dump */ + pg_fatal("archive format \"%s\" is not supported; please use psql", + opts->formatName); + } + else + pg_fatal("unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"", + opts->formatName); + } - case 'd': - case 'D': - opts->format = archDirectory; - break; + /* + * If toc.dat file is not present in the current path, then check for + * global.dat. If global.dat file is present, then restore all the + * databases from map.dat (if it exists), but skip restoring those + * matching --exclude-database patterns. + */ + if (inputFileSpec != NULL && !file_exists_in_directory(inputFileSpec, "toc.dat") && + file_exists_in_directory(inputFileSpec, "global.dat")) + { + PGconn *conn = NULL; /* Connection to restore global sql + * commands. */ - case 't': - case 'T': - opts->format = archTar; - break; + /* + * Can only use --list or --use-list options with a single database + * dump. + */ + if (opts->tocSummary) + pg_fatal("option -l/--list cannot be used when restoring an archive created by pg_dumpall"); + else if (opts->tocFile) + pg_fatal("option -L/--use-list cannot be used when restoring an archive created by pg_dumpall"); - default: - pg_fatal("unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"", - opts->formatName); + /* + * To restore from a pg_dumpall archive, -C (create database) option + * must be specified unless we are only restoring globals. + */ + if (!globals_only && opts->createDB != 1) + { + pg_log_error("option -C/--create must be specified when restoring an archive created by pg_dumpall"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + pg_log_error_hint("Individual databases can be restored using their specific archives."); + exit_nicely(1); } + + /* + * Connect to the database to execute global sql commands from + * global.dat file. + */ + if (opts->cparams.dbname) + { + conn = ConnectDatabase(opts->cparams.dbname, NULL, opts->cparams.pghost, + opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT, + false, progname, NULL, NULL, NULL, NULL); + + + if (!conn) + pg_fatal("could not connect to database \"%s\"", opts->cparams.dbname); + } + + /* If globals-only, then return from here. */ + if (globals_only) + { + /* + * Open global.dat file and execute/append all the global sql + * commands. + */ + n_errors = process_global_sql_commands(conn, inputFileSpec, + opts->filename); + + if (conn) + PQfinish(conn); + + pg_log_info("database restoring skipped because option -g/--globals-only was specified"); + } + else + { + /* Now restore all the databases from map.dat */ + n_errors = restore_all_databases(conn, inputFileSpec, db_exclude_patterns, + opts, numWorkers); + } + + /* Free db pattern list. */ + simple_string_list_destroy(&db_exclude_patterns); + } + else /* process if global.dat file does not exist. */ + { + if (db_exclude_patterns.head != NULL) + pg_fatal("option --exclude-database can be used only when restoring an archive created by pg_dumpall"); + + if (globals_only) + pg_fatal("option -g/--globals-only can be used only when restoring an archive created by pg_dumpall"); + + n_errors = restore_one_database(inputFileSpec, opts, numWorkers, false, 0); } + /* Done, print a summary of ignored errors during restore. */ + if (n_errors) + { + pg_log_warning("errors ignored on restore: %d", n_errors); + return 1; + } + + return 0; +} + +/* + * restore_one_database + * + * This will restore one database using toc.dat file. + * + * returns the number of errors while doing restore. + */ +static int +restore_one_database(const char *inputFileSpec, RestoreOptions *opts, + int numWorkers, bool append_data, int num) +{ + Archive *AH; + int n_errors; + AH = OpenArchive(inputFileSpec, opts->format); SetArchiveOptions(AH, NULL, opts); @@ -408,9 +611,15 @@ main(int argc, char **argv) /* * We don't have a connection yet but that doesn't matter. The connection * is initialized to NULL and if we terminate through exit_nicely() while - * it's still NULL, the cleanup function will just be a no-op. + * it's still NULL, the cleanup function will just be a no-op. If we are + * restoring multiple databases, then only update AX handle for cleanup as + * the previous entry was already in the array and we had closed previous + * connection, so we can use the same array slot. */ - on_exit_close_archive(AH); + if (!append_data || num == 0) + on_exit_close_archive(AH); + else + replace_on_exit_close_archive(AH); /* Let the archiver know how noisy to be */ AH->verbose = opts->verbose; @@ -430,25 +639,21 @@ main(int argc, char **argv) else { ProcessArchiveRestoreOptions(AH); - RestoreArchive(AH); + RestoreArchive(AH, append_data); } - /* done, print a summary of ignored errors */ - if (AH->n_errors) - pg_log_warning("errors ignored on restore: %d", AH->n_errors); + n_errors = AH->n_errors; /* AH may be freed in CloseArchive? */ - exit_code = AH->n_errors ? 1 : 0; - CloseArchive(AH); - return exit_code; + return n_errors; } static void usage(const char *progname) { - printf(_("%s restores a PostgreSQL database from an archive created by pg_dump.\n\n"), progname); + printf(_("%s restores PostgreSQL databases from archives created by pg_dump or pg_dumpall.\n\n"), progname); printf(_("Usage:\n")); printf(_(" %s [OPTION]... [FILE]\n"), progname); @@ -466,6 +671,7 @@ usage(const char *progname) printf(_(" -c, --clean clean (drop) database objects before recreating\n")); printf(_(" -C, --create create the target database\n")); printf(_(" -e, --exit-on-error exit on error, default is to continue\n")); + printf(_(" -g, --globals-only restore only global objects, no databases\n")); printf(_(" -I, --index=NAME restore named index\n")); printf(_(" -j, --jobs=NUM use this many parallel jobs to restore\n")); printf(_(" -L, --use-list=FILENAME use table of contents from this file for\n" @@ -482,24 +688,33 @@ usage(const char *progname) printf(_(" -1, --single-transaction restore as a single transaction\n")); printf(_(" --disable-triggers disable triggers during data-only restore\n")); printf(_(" --enable-row-security enable row security\n")); + printf(_(" --exclude-database=PATTERN do not restore the specified database(s)\n")); printf(_(" --filter=FILENAME restore or skip objects based on expressions\n" " in FILENAME\n")); printf(_(" --if-exists use IF EXISTS when dropping objects\n")); - printf(_(" --no-comments do not restore comments\n")); + printf(_(" --no-comments do not restore comment commands\n")); + printf(_(" --no-data do not restore data\n")); printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n" " created\n")); + printf(_(" --no-policies do not restore row security policies\n")); printf(_(" --no-publications do not restore publications\n")); + printf(_(" --no-schema do not restore schema\n")); printf(_(" --no-security-labels do not restore security labels\n")); + printf(_(" --no-statistics do not restore statistics\n")); printf(_(" --no-subscriptions do not restore subscriptions\n")); printf(_(" --no-table-access-method do not restore table access methods\n")); printf(_(" --no-tablespaces do not restore tablespace assignments\n")); printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n")); + printf(_(" --statistics-only restore only the statistics, not schema or data\n")); printf(_(" --strict-names require table and/or schema include patterns to\n" " match at least one entity each\n")); printf(_(" --transaction-size=N commit after every N objects\n")); printf(_(" --use-set-session-authorization\n" " use SET SESSION AUTHORIZATION commands instead of\n" " ALTER OWNER commands to set ownership\n")); + printf(_(" --with-data restore the data\n")); + printf(_(" --with-schema restore the schema\n")); + printf(_(" --with-statistics restore the statistics\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); @@ -510,8 +725,8 @@ usage(const char *progname) printf(_(" --role=ROLENAME do SET ROLE before restore\n")); printf(_("\n" - "The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" - "multiple times to select multiple objects.\n")); + "The options -I, -n, -N, -P, -t, -T, --section, and --exclude-database can be\n" + "combined and specified multiple times to select multiple objects.\n")); printf(_("\nIf no input file name is supplied, then standard input is used.\n\n")); printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL); @@ -616,3 +831,585 @@ read_restore_filters(const char *filename, RestoreOptions *opts) filter_free(&fstate); } + +/* + * file_exists_in_directory + * + * Returns true if the file exists in the given directory. + */ +static bool +file_exists_in_directory(const char *dir, const char *filename) +{ + struct stat st; + char buf[MAXPGPATH]; + + if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH) + pg_fatal("directory name too long: \"%s\"", dir); + + return (stat(buf, &st) == 0 && S_ISREG(st.st_mode)); +} + +/* + * read_one_statement + * + * This will start reading from passed file pointer using fgetc and read till + * semicolon(sql statement terminator for global.dat file) + * + * EOF is returned if end-of-file input is seen; time to shut down. + */ + +static int +read_one_statement(StringInfo inBuf, FILE *pfile) +{ + int c; /* character read from getc() */ + int m; + + StringInfoData q; + + initStringInfo(&q); + + resetStringInfo(inBuf); + + /* + * Read characters until EOF or the appropriate delimiter is seen. + */ + while ((c = fgetc(pfile)) != EOF) + { + if (c != '\'' && c != '"' && c != '\n' && c != ';') + { + appendStringInfoChar(inBuf, (char) c); + while ((c = fgetc(pfile)) != EOF) + { + if (c != '\'' && c != '"' && c != ';' && c != '\n') + appendStringInfoChar(inBuf, (char) c); + else + break; + } + } + + if (c == '\'' || c == '"') + { + appendStringInfoChar(&q, (char) c); + m = c; + + while ((c = fgetc(pfile)) != EOF) + { + appendStringInfoChar(&q, (char) c); + + if (c == m) + { + appendStringInfoString(inBuf, q.data); + resetStringInfo(&q); + break; + } + } + } + + if (c == ';') + { + appendStringInfoChar(inBuf, (char) ';'); + break; + } + + if (c == '\n') + appendStringInfoChar(inBuf, (char) '\n'); + } + + pg_free(q.data); + + /* No input before EOF signal means time to quit. */ + if (c == EOF && inBuf->len == 0) + return EOF; + + /* return something that's not EOF */ + return 'Q'; +} + +/* + * get_dbnames_list_to_restore + * + * This will mark for skipping any entries from dbname_oid_list that pattern match an + * entry in the db_exclude_patterns list. + * + * Returns the number of database to be restored. + * + */ +static int +get_dbnames_list_to_restore(PGconn *conn, + SimplePtrList *dbname_oid_list, + SimpleStringList db_exclude_patterns) +{ + int count_db = 0; + PQExpBuffer query; + PGresult *res; + + query = createPQExpBuffer(); + + if (!conn) + pg_log_info("considering PATTERN as NAME for --exclude-database option as no database connection while doing pg_restore"); + + /* + * Process one by one all dbnames and if specified to skip restoring, then + * remove dbname from list. + */ + for (SimplePtrListCell *db_cell = dbname_oid_list->head; + db_cell; db_cell = db_cell->next) + { + DbOidName *dbidname = (DbOidName *) db_cell->ptr; + bool skip_db_restore = false; + PQExpBuffer db_lit = createPQExpBuffer(); + + appendStringLiteralConn(db_lit, dbidname->str, conn); + + for (SimpleStringListCell *pat_cell = db_exclude_patterns.head; pat_cell; pat_cell = pat_cell->next) + { + /* + * If there is an exact match then we don't need to try a pattern + * match + */ + if (pg_strcasecmp(dbidname->str, pat_cell->val) == 0) + skip_db_restore = true; + /* Otherwise, try a pattern match if there is a connection */ + else if (conn) + { + int dotcnt; + + appendPQExpBufferStr(query, "SELECT 1 "); + processSQLNamePattern(conn, query, pat_cell->val, false, + false, NULL, db_lit->data, + NULL, NULL, NULL, &dotcnt); + + if (dotcnt > 0) + { + pg_log_error("improper qualified name (too many dotted names): %s", + dbidname->str); + PQfinish(conn); + exit_nicely(1); + } + + res = executeQuery(conn, query->data); + + if ((PQresultStatus(res) == PGRES_TUPLES_OK) && PQntuples(res)) + { + skip_db_restore = true; + pg_log_info("database name \"%s\" matches exclude pattern \"%s\"", dbidname->str, pat_cell->val); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + if (skip_db_restore) + break; + } + + destroyPQExpBuffer(db_lit); + + /* + * Mark db to be skipped or increment the counter of dbs to be + * restored + */ + if (skip_db_restore) + { + pg_log_info("excluding database \"%s\"", dbidname->str); + dbidname->oid = InvalidOid; + } + else + { + count_db++; + } + } + + destroyPQExpBuffer(query); + + return count_db; +} + +/* + * get_dbname_oid_list_from_mfile + * + * Open map.dat file and read line by line and then prepare a list of database + * names and corresponding db_oid. + * + * Returns, total number of database names in map.dat file. + */ +static int +get_dbname_oid_list_from_mfile(const char *dumpdirpath, SimplePtrList *dbname_oid_list) +{ + StringInfoData linebuf; + FILE *pfile; + char map_file_path[MAXPGPATH]; + int count = 0; + + + /* + * If there is only global.dat file in dump, then return from here as + * there is no database to restore. + */ + if (!file_exists_in_directory(dumpdirpath, "map.dat")) + { + pg_log_info("database restoring is skipped because file \"%s\" does not exist in directory \"%s\"", "map.dat", dumpdirpath); + return 0; + } + + snprintf(map_file_path, MAXPGPATH, "%s/map.dat", dumpdirpath); + + /* Open map.dat file. */ + pfile = fopen(map_file_path, PG_BINARY_R); + + if (pfile == NULL) + pg_fatal("could not open file \"%s\": %m", map_file_path); + + initStringInfo(&linebuf); + + /* Append all the dbname/db_oid combinations to the list. */ + while (pg_get_line_buf(pfile, &linebuf)) + { + Oid db_oid = InvalidOid; + char *dbname; + DbOidName *dbidname; + int namelen; + char *p = linebuf.data; + + /* Extract dboid. */ + while (isdigit((unsigned char) *p)) + p++; + if (p > linebuf.data && *p == ' ') + { + sscanf(linebuf.data, "%u", &db_oid); + p++; + } + + /* dbname is the rest of the line */ + dbname = p; + namelen = strlen(dbname); + + /* Report error and exit if the file has any corrupted data. */ + if (!OidIsValid(db_oid) || namelen <= 1) + pg_fatal("invalid entry in file \"%s\" on line %d", map_file_path, + count + 1); + + pg_log_info("found database \"%s\" (OID: %u) in file \"%s\"", + dbname, db_oid, map_file_path); + + dbidname = pg_malloc(offsetof(DbOidName, str) + namelen + 1); + dbidname->oid = db_oid; + strlcpy(dbidname->str, dbname, namelen); + + simple_ptr_list_append(dbname_oid_list, dbidname); + count++; + } + + /* Close map.dat file. */ + fclose(pfile); + + return count; +} + +/* + * restore_all_databases + * + * This will restore databases those dumps are present in + * directory based on map.dat file mapping. + * + * This will skip restoring for databases that are specified with + * exclude-database option. + * + * returns, number of errors while doing restore. + */ +static int +restore_all_databases(PGconn *conn, const char *dumpdirpath, + SimpleStringList db_exclude_patterns, RestoreOptions *opts, + int numWorkers) +{ + SimplePtrList dbname_oid_list = {NULL, NULL}; + int num_db_restore = 0; + int num_total_db; + int n_errors_total; + int count = 0; + char *connected_db = NULL; + bool dumpData = opts->dumpData; + bool dumpSchema = opts->dumpSchema; + bool dumpStatistics = opts->dumpSchema; + + /* Save db name to reuse it for all the database. */ + if (opts->cparams.dbname) + connected_db = opts->cparams.dbname; + + num_total_db = get_dbname_oid_list_from_mfile(dumpdirpath, &dbname_oid_list); + + /* If map.dat has no entries, return after processing global.dat */ + if (dbname_oid_list.head == NULL) + return process_global_sql_commands(conn, dumpdirpath, opts->filename); + + pg_log_info(ngettext("found %d database name in \"%s\"", + "found %d database names in \"%s\"", + num_total_db), + num_total_db, "map.dat"); + + if (!conn) + { + pg_log_info("trying to connect to database \"%s\"", "postgres"); + + conn = ConnectDatabase("postgres", NULL, opts->cparams.pghost, + opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT, + false, progname, NULL, NULL, NULL, NULL); + + /* Try with template1. */ + if (!conn) + { + pg_log_info("trying to connect to database \"%s\"", "template1"); + + conn = ConnectDatabase("template1", NULL, opts->cparams.pghost, + opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT, + false, progname, NULL, NULL, NULL, NULL); + } + } + + /* + * filter the db list according to the exclude patterns + */ + num_db_restore = get_dbnames_list_to_restore(conn, &dbname_oid_list, + db_exclude_patterns); + + /* Open global.dat file and execute/append all the global sql commands. */ + n_errors_total = process_global_sql_commands(conn, dumpdirpath, opts->filename); + + /* Close the db connection as we are done with globals and patterns. */ + if (conn) + PQfinish(conn); + + /* Exit if no db needs to be restored. */ + if (dbname_oid_list.head == NULL || num_db_restore == 0) + { + pg_log_info(ngettext("no database needs restoring out of %d database", + "no database needs restoring out of %d databases", num_total_db), + num_total_db); + return n_errors_total; + } + + pg_log_info("need to restore %d databases out of %d databases", num_db_restore, num_total_db); + + /* + * We have a list of databases to restore after processing the + * exclude-database switch(es). Now we can restore them one by one. + */ + for (SimplePtrListCell *db_cell = dbname_oid_list.head; + db_cell; db_cell = db_cell->next) + { + DbOidName *dbidname = (DbOidName *) db_cell->ptr; + char subdirpath[MAXPGPATH]; + char subdirdbpath[MAXPGPATH]; + char dbfilename[MAXPGPATH]; + int n_errors; + + /* ignore dbs marked for skipping */ + if (dbidname->oid == InvalidOid) + continue; + + /* + * We need to reset override_dbname so that objects can be restored + * into an already created database. (used with -d/--dbname option) + */ + if (opts->cparams.override_dbname) + { + pfree(opts->cparams.override_dbname); + opts->cparams.override_dbname = NULL; + } + + snprintf(subdirdbpath, MAXPGPATH, "%s/databases", dumpdirpath); + + /* + * Look for the database dump file/dir. If there is an {oid}.tar or + * {oid}.dmp file, use it. Otherwise try to use a directory called + * {oid} + */ + snprintf(dbfilename, MAXPGPATH, "%u.tar", dbidname->oid); + if (file_exists_in_directory(subdirdbpath, dbfilename)) + snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.tar", dumpdirpath, dbidname->oid); + else + { + snprintf(dbfilename, MAXPGPATH, "%u.dmp", dbidname->oid); + + if (file_exists_in_directory(subdirdbpath, dbfilename)) + snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.dmp", dumpdirpath, dbidname->oid); + else + snprintf(subdirpath, MAXPGPATH, "%s/databases/%u", dumpdirpath, dbidname->oid); + } + + pg_log_info("restoring database \"%s\"", dbidname->str); + + /* If database is already created, then don't set createDB flag. */ + if (opts->cparams.dbname) + { + PGconn *test_conn; + + test_conn = ConnectDatabase(dbidname->str, NULL, opts->cparams.pghost, + opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT, + false, progname, NULL, NULL, NULL, NULL); + if (test_conn) + { + PQfinish(test_conn); + + /* Use already created database for connection. */ + opts->createDB = 0; + opts->cparams.dbname = dbidname->str; + } + else + { + /* we'll have to create it */ + opts->createDB = 1; + opts->cparams.dbname = connected_db; + } + } + + /* + * Reset flags - might have been reset in pg_backup_archiver.c by the + * previous restore. + */ + opts->dumpData = dumpData; + opts->dumpSchema = dumpSchema; + opts->dumpStatistics = dumpStatistics; + + /* Restore the single database. */ + n_errors = restore_one_database(subdirpath, opts, numWorkers, true, count); + + /* Print a summary of ignored errors during single database restore. */ + if (n_errors) + { + n_errors_total += n_errors; + pg_log_warning("errors ignored on database \"%s\" restore: %d", dbidname->str, n_errors); + } + + count++; + } + + /* Log number of processed databases. */ + pg_log_info("number of restored databases is %d", num_db_restore); + + /* Free dbname and dboid list. */ + simple_ptr_list_destroy(&dbname_oid_list); + + return n_errors_total; +} + +/* + * process_global_sql_commands + * + * Open global.dat and execute or copy the sql commands one by one. + * + * If outfile is not NULL, copy all sql commands into outfile rather than + * executing them. + * + * Returns the number of errors while processing global.dat + */ +static int +process_global_sql_commands(PGconn *conn, const char *dumpdirpath, const char *outfile) +{ + char global_file_path[MAXPGPATH]; + PGresult *result; + StringInfoData sqlstatement, + user_create; + FILE *pfile; + int n_errors = 0; + + snprintf(global_file_path, MAXPGPATH, "%s/global.dat", dumpdirpath); + + /* Open global.dat file. */ + pfile = fopen(global_file_path, PG_BINARY_R); + + if (pfile == NULL) + pg_fatal("could not open file \"%s\": %m", global_file_path); + + /* + * If outfile is given, then just copy all global.dat file data into + * outfile. + */ + if (outfile) + { + copy_or_print_global_file(outfile, pfile); + return 0; + } + + /* Init sqlstatement to append commands. */ + initStringInfo(&sqlstatement); + + /* creation statement for our current role */ + initStringInfo(&user_create); + appendStringInfoString(&user_create, "CREATE ROLE "); + /* should use fmtId here, but we don't know the encoding */ + appendStringInfoString(&user_create, PQuser(conn)); + appendStringInfoChar(&user_create, ';'); + + /* Process file till EOF and execute sql statements. */ + while (read_one_statement(&sqlstatement, pfile) != EOF) + { + /* don't try to create the role we are connected as */ + if (strstr(sqlstatement.data, user_create.data)) + continue; + + pg_log_info("executing query: %s", sqlstatement.data); + result = PQexec(conn, sqlstatement.data); + + switch (PQresultStatus(result)) + { + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + case PGRES_EMPTY_QUERY: + break; + default: + n_errors++; + pg_log_error("could not execute query: %s", PQerrorMessage(conn)); + pg_log_error_detail("Command was: %s", sqlstatement.data); + } + PQclear(result); + } + + /* Print a summary of ignored errors during global.dat. */ + if (n_errors) + pg_log_warning(ngettext("ignored %d error in file \"%s\"", + "ignored %d errors in file \"%s\"", n_errors), + n_errors, global_file_path); + fclose(pfile); + + return n_errors; +} + +/* + * copy_or_print_global_file + * + * Copy global.dat into the output file. If "-" is used as outfile, + * then print commands to stdout. + */ +static void +copy_or_print_global_file(const char *outfile, FILE *pfile) +{ + char out_file_path[MAXPGPATH]; + FILE *OPF; + int c; + + /* "-" is used for stdout. */ + if (strcmp(outfile, "-") == 0) + OPF = stdout; + else + { + snprintf(out_file_path, MAXPGPATH, "%s", outfile); + OPF = fopen(out_file_path, PG_BINARY_W); + + if (OPF == NULL) + { + fclose(pfile); + pg_fatal("could not open file: \"%s\"", outfile); + } + } + + /* Append global.dat into output file or print to stdout. */ + while ((c = fgetc(pfile)) != EOF) + fputc(c, OPF); + + fclose(pfile); + + /* Close output file. */ + if (strcmp(outfile, "-") != 0) + fclose(OPF); +} diff --git a/src/bin/pg_dump/po/de.po b/src/bin/pg_dump/po/de.po index fa22292c6a733..ecf78101184f4 100644 --- a/src/bin/pg_dump/po/de.po +++ b/src/bin/pg_dump/po/de.po @@ -1,14 +1,14 @@ # German message translation file for pg_dump and friends -# Peter Eisentraut , 2001 - 2024. +# Peter Eisentraut , 2001 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 16:52+0000\n" -"PO-Revision-Date: 2024-06-22 07:36+0200\n" +"POT-Creation-Date: 2025-04-04 11:22+0000\n" +"PO-Revision-Date: 2025-04-04 15:49+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -17,29 +17,29 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " #: ../../common/compression.c:132 ../../common/compression.c:141 #: ../../common/compression.c:150 compress_gzip.c:413 compress_gzip.c:420 -#: compress_io.c:109 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 +#: compress_io.c:108 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 #: compress_zstd.c:31 #, c-format msgid "this build does not support compression with %s" @@ -109,27 +109,27 @@ msgstr "konnte kein »%s« zum Ausführen finden" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "konnte Pfad »%s« nicht in absolute Form auflösen: %m" -#: ../../common/exec.c:382 +#: ../../common/exec.c:363 #, c-format msgid "could not execute command \"%s\": %m" msgstr "konnte Befehl »%s« nicht ausführen: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "konnte nicht von Befehl »%s« lesen: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "Befehl »%s« gab keine Daten zurück" -#: ../../common/exec.c:424 parallel.c:1609 +#: ../../common/exec.c:405 parallel.c:1611 #, c-format msgid "%s() failed: %m" msgstr "%s() fehlgeschlagen: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 msgid "out of memory" msgstr "Speicher aufgebraucht" @@ -144,45 +144,45 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #: pg_backup_directory.c:182 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -232,242 +232,242 @@ msgstr "%s muss im Bereich %d..%d sein" msgid "unrecognized sync method: %s" msgstr "unbekannte Sync-Methode: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" -#: common.c:135 +#: common.c:111 #, c-format msgid "reading extensions" msgstr "lese Erweiterungen" -#: common.c:138 +#: common.c:114 #, c-format msgid "identifying extension members" msgstr "identifiziere Erweiterungselemente" -#: common.c:141 +#: common.c:117 #, c-format msgid "reading schemas" msgstr "lese Schemas" -#: common.c:150 +#: common.c:126 #, c-format msgid "reading user-defined tables" msgstr "lese benutzerdefinierte Tabellen" -#: common.c:155 +#: common.c:131 #, c-format msgid "reading user-defined functions" msgstr "lese benutzerdefinierte Funktionen" -#: common.c:159 +#: common.c:135 #, c-format msgid "reading user-defined types" msgstr "lese benutzerdefinierte Typen" -#: common.c:163 +#: common.c:139 #, c-format msgid "reading procedural languages" msgstr "lese prozedurale Sprachen" -#: common.c:166 +#: common.c:142 #, c-format msgid "reading user-defined aggregate functions" msgstr "lese benutzerdefinierte Aggregatfunktionen" -#: common.c:169 +#: common.c:145 #, c-format msgid "reading user-defined operators" msgstr "lese benutzerdefinierte Operatoren" -#: common.c:172 +#: common.c:148 #, c-format msgid "reading user-defined access methods" msgstr "lese benutzerdefinierte Zugriffsmethoden" -#: common.c:175 +#: common.c:151 #, c-format msgid "reading user-defined operator classes" msgstr "lese benutzerdefinierte Operatorklassen" -#: common.c:178 +#: common.c:154 #, c-format msgid "reading user-defined operator families" msgstr "lese benutzerdefinierte Operatorfamilien" -#: common.c:181 +#: common.c:157 #, c-format msgid "reading user-defined text search parsers" msgstr "lese benutzerdefinierte Textsuche-Parser" -#: common.c:184 +#: common.c:160 #, c-format msgid "reading user-defined text search templates" msgstr "lese benutzerdefinierte Textsuche-Templates" -#: common.c:187 +#: common.c:163 #, c-format msgid "reading user-defined text search dictionaries" msgstr "lese benutzerdefinierte Textsuchewörterbücher" -#: common.c:190 +#: common.c:166 #, c-format msgid "reading user-defined text search configurations" msgstr "lese benutzerdefinierte Textsuchekonfigurationen" -#: common.c:193 +#: common.c:169 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "lese benutzerdefinierte Fremddaten-Wrapper" -#: common.c:196 +#: common.c:172 #, c-format msgid "reading user-defined foreign servers" msgstr "lese benutzerdefinierte Fremdserver" -#: common.c:199 +#: common.c:175 #, c-format msgid "reading default privileges" msgstr "lese Vorgabeprivilegien" -#: common.c:202 +#: common.c:178 #, c-format msgid "reading user-defined collations" msgstr "lese benutzerdefinierte Sortierfolgen" -#: common.c:205 +#: common.c:181 #, c-format msgid "reading user-defined conversions" msgstr "lese benutzerdefinierte Konversionen" -#: common.c:208 +#: common.c:184 #, c-format msgid "reading type casts" msgstr "lese Typumwandlungen" -#: common.c:211 +#: common.c:187 #, c-format msgid "reading transforms" msgstr "lese Transformationen" -#: common.c:214 +#: common.c:190 #, c-format msgid "reading table inheritance information" msgstr "lese Tabellenvererbungsinformationen" -#: common.c:217 +#: common.c:193 #, c-format msgid "reading event triggers" msgstr "lese Ereignistrigger" -#: common.c:221 +#: common.c:197 #, c-format msgid "finding extension tables" msgstr "finde Erweiterungstabellen" -#: common.c:225 +#: common.c:201 #, c-format msgid "finding inheritance relationships" msgstr "finde Vererbungsbeziehungen" -#: common.c:228 +#: common.c:204 #, c-format msgid "reading column info for interesting tables" msgstr "lese Spalteninfo für interessante Tabellen" -#: common.c:231 +#: common.c:207 #, c-format msgid "flagging inherited columns in subtables" msgstr "markiere vererbte Spalten in abgeleiteten Tabellen" -#: common.c:234 +#: common.c:210 #, c-format msgid "reading partitioning data" msgstr "lese Partitionierungsdaten" -#: common.c:237 +#: common.c:213 #, c-format msgid "reading indexes" msgstr "lese Indexe" -#: common.c:240 +#: common.c:216 #, c-format msgid "flagging indexes in partitioned tables" msgstr "markiere Indexe in partitionierten Tabellen" -#: common.c:243 +#: common.c:219 #, c-format msgid "reading extended statistics" msgstr "lese erweiterte Statistiken" -#: common.c:246 +#: common.c:222 #, c-format msgid "reading constraints" msgstr "lese Constraints" -#: common.c:249 +#: common.c:225 #, c-format msgid "reading triggers" msgstr "lese Trigger" -#: common.c:252 +#: common.c:228 #, c-format msgid "reading rewrite rules" msgstr "lese Umschreiberegeln" -#: common.c:255 +#: common.c:231 #, c-format msgid "reading policies" -msgstr "lese Policies" +msgstr "lese Policys" -#: common.c:258 +#: common.c:234 #, c-format msgid "reading publications" msgstr "lese Publikationen" -#: common.c:261 +#: common.c:237 #, c-format msgid "reading publication membership of tables" msgstr "lese Publikationsmitgliedschaft von Tabellen" -#: common.c:264 +#: common.c:240 #, c-format msgid "reading publication membership of schemas" msgstr "lese Publikationsmitgliedschaft von Schemas" -#: common.c:267 +#: common.c:243 #, c-format msgid "reading subscriptions" msgstr "lese Subskriptionen" -#: common.c:270 +#: common.c:246 #, c-format msgid "reading subscription membership of tables" msgstr "lese Subskriptionsmitgliedschaft von Tabellen" -#: common.c:333 +#: common.c:309 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "Sanity-Check fehlgeschlagen, Eltern-OID %u von Tabelle »%s« (OID %u) nicht gefunden" -#: common.c:375 +#: common.c:351 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "ungültige Anzahl Eltern %d für Tabelle »%s«" -#: common.c:1098 +#: common.c:1087 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "konnte numerisches Array »%s« nicht parsen: zu viele Zahlen" -#: common.c:1110 +#: common.c:1099 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "konnte numerisches Array »%s« nicht parsen: ungültiges Zeichen in Zahl" @@ -503,13 +503,13 @@ msgid "could not read from input file: %s" msgstr "konnte nicht aus Eingabedatei lesen: %s" #: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 -#: compress_zstd.c:373 pg_backup_custom.c:651 +#: compress_zstd.c:374 pg_backup_custom.c:650 #, c-format msgid "could not read from input file: %m" msgstr "konnte nicht aus Eingabedatei lesen: %m" #: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 -#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: compress_zstd.c:372 pg_backup_custom.c:648 pg_backup_directory.c:565 #: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" @@ -550,98 +550,98 @@ msgstr "konnte Dekomprimierung nicht beenden: %s" msgid "could not set compression parameter \"%s\": %s" msgstr "konnte Komprimierungsparameter »%s« nicht setzen: %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:232 compress_zstd.c:491 +#: compress_zstd.c:499 #, c-format msgid "could not initialize compression library" msgstr "konnte Komprimierungsbibliothek nicht initialisieren" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:195 compress_zstd.c:309 #, c-format msgid "could not decompress data: %s" msgstr "konnte Daten nicht dekomprimieren: %s" -#: compress_zstd.c:501 +#: compress_zstd.c:502 #, c-format msgid "unhandled mode \"%s\"" msgstr "unbehandelter Modus »%s«" -#: filter.c:49 +#: filter.c:48 #, c-format msgid "could not open filter file \"%s\": %m" msgstr "konnte Filterdatei »%s« nicht öffnen: %m" -#: filter.c:72 +#: filter.c:71 #, c-format msgid "could not close filter file \"%s\": %m" msgstr "konnte Filterdatei »%s« nicht schließen: %m" -#: filter.c:165 +#: filter.c:164 #, c-format msgid "invalid format in filter read from standard input on line %d: %s" msgstr "ungültiges Format in Filter gelesen von Standardeingabe auf Zeile %d: %s" -#: filter.c:168 +#: filter.c:167 #, c-format msgid "invalid format in filter read from file \"%s\" on line %d: %s" msgstr "ungültiges Format in Filter gelesen aus Datei »%s« auf Zeile %d: %s" -#: filter.c:241 filter.c:468 +#: filter.c:240 filter.c:467 #, c-format msgid "could not read from filter file \"%s\": %m" msgstr "konnte nicht aus Filterdatei »%s« lesen: %m" -#: filter.c:244 +#: filter.c:243 msgid "unexpected end of file" msgstr "unerwartetes Dateiende" -#: filter.c:311 +#: filter.c:310 msgid "missing object name pattern" msgstr "Objektnamenmuster fehlt" -#: filter.c:422 +#: filter.c:421 msgid "no filter command found (expected \"include\" or \"exclude\")" msgstr "kein Filterbefehl gefunden (»include« oder »exclude« erwartet)" -#: filter.c:433 +#: filter.c:432 msgid "invalid filter command (expected \"include\" or \"exclude\")" msgstr "ungültiger Filterbefehl (»include« oder »exclude« erwartet)" -#: filter.c:440 +#: filter.c:439 msgid "missing filter object type" msgstr "Filterobjekttyp fehlt" -#: filter.c:447 +#: filter.c:446 #, c-format msgid "unsupported filter object type: \"%.*s\"" msgstr "nicht unterstützter Filterobjekttyp: »%.*s«" -#: parallel.c:251 +#: parallel.c:253 #, c-format msgid "%s() failed: error code %d" msgstr "%s() fehlgeschlagen: Fehlercode %d" -#: parallel.c:959 +#: parallel.c:961 #, c-format msgid "could not create communication channels: %m" msgstr "konnte Kommunikationskanäle nicht erzeugen: %m" -#: parallel.c:1016 +#: parallel.c:1018 #, c-format msgid "could not create worker process: %m" msgstr "konnte Arbeitsprozess nicht erzeugen: %m" -#: parallel.c:1146 +#: parallel.c:1148 #, c-format msgid "unrecognized command received from leader: \"%s\"" msgstr "unbekannter Befehl vom Leader-Prozess empfangen: »%s«" -#: parallel.c:1189 parallel.c:1427 +#: parallel.c:1191 parallel.c:1429 #, c-format msgid "invalid message received from worker: \"%s\"" msgstr "ungültige Nachricht vom Arbeitsprozess empfangen: »%s«" -#: parallel.c:1321 +#: parallel.c:1323 #, c-format msgid "" "could not obtain lock on relation \"%s\"\n" @@ -650,657 +650,657 @@ msgstr "" "konnte Sperre für Relation »%s« nicht setzen\n" "Das bedeutet meistens, dass jemand eine ACCESS-EXCLUSIVE-Sperre auf die Tabelle gesetzt hat, nachdem der pg-dump-Elternprozess die anfängliche ACCESS-SHARE-Sperre gesetzt hatte." -#: parallel.c:1410 +#: parallel.c:1412 #, c-format msgid "a worker process died unexpectedly" msgstr "ein Arbeitsprozess endete unerwartet" -#: parallel.c:1532 parallel.c:1650 +#: parallel.c:1534 parallel.c:1652 #, c-format msgid "could not write to the communication channel: %m" msgstr "konnte nicht in den Kommunikationskanal schreiben: %m" -#: parallel.c:1734 +#: parallel.c:1736 #, c-format msgid "pgpipe: could not create socket: error code %d" msgstr "pgpipe: konnte Socket nicht erzeugen: Fehlercode %d" -#: parallel.c:1745 +#: parallel.c:1747 #, c-format msgid "pgpipe: could not bind: error code %d" msgstr "pgpipe: konnte nicht binden: Fehlercode %d" -#: parallel.c:1752 +#: parallel.c:1754 #, c-format msgid "pgpipe: could not listen: error code %d" msgstr "pgpipe: konnte nicht auf Socket hören: Fehlercode %d" -#: parallel.c:1759 +#: parallel.c:1761 #, c-format msgid "pgpipe: %s() failed: error code %d" msgstr "pgpipe: %s() fehlgeschlagen: Fehlercode %d" -#: parallel.c:1770 +#: parallel.c:1772 #, c-format msgid "pgpipe: could not create second socket: error code %d" msgstr "pgpipe: konnte zweites Socket nicht erzeugen: Fehlercode %d" -#: parallel.c:1779 +#: parallel.c:1781 #, c-format msgid "pgpipe: could not connect socket: error code %d" msgstr "pgpipe: konnte Socket nicht verbinden: Fehlercode %d" -#: parallel.c:1788 +#: parallel.c:1790 #, c-format msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: konnte Verbindung nicht annehmen: Fehlercode %d" -#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 +#: pg_backup_archiver.c:270 pg_backup_archiver.c:1724 #, c-format msgid "could not close output file: %m" msgstr "konnte Ausgabedatei nicht schließen: %m" -#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 +#: pg_backup_archiver.c:314 pg_backup_archiver.c:318 #, c-format msgid "archive items not in correct section order" msgstr "Archivelemente nicht in richtiger Abschnittsreihenfolge" -#: pg_backup_archiver.c:315 +#: pg_backup_archiver.c:324 #, c-format msgid "unexpected section code %d" msgstr "unerwarteter Abschnittscode %d" -#: pg_backup_archiver.c:352 +#: pg_backup_archiver.c:361 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "parallele Wiederherstellung wird von diesem Archivdateiformat nicht unterstützt" -#: pg_backup_archiver.c:356 +#: pg_backup_archiver.c:365 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "parallele Wiederherstellung wird mit Archiven, die mit pg_dump vor 8.0 erstellt worden sind, nicht unterstützt" -#: pg_backup_archiver.c:377 +#: pg_backup_archiver.c:386 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "kann komprimiertes Archiv nicht wiederherstellen (%s)" -#: pg_backup_archiver.c:397 +#: pg_backup_archiver.c:406 #, c-format msgid "connecting to database for restore" msgstr "verbinde mit der Datenbank zur Wiederherstellung" -#: pg_backup_archiver.c:399 +#: pg_backup_archiver.c:408 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "direkte Datenbankverbindungen sind in Archiven vor Version 1.3 nicht unterstützt" -#: pg_backup_archiver.c:442 +#: pg_backup_archiver.c:451 #, c-format -msgid "implied data-only restore" -msgstr "implizit werden nur Daten wiederhergestellt" +msgid "implied no-schema restore" +msgstr "implizit wird das Schema nicht wiederhergestellt" -#: pg_backup_archiver.c:510 +#: pg_backup_archiver.c:519 #, c-format msgid "dropping %s %s" msgstr "entferne %s %s" -#: pg_backup_archiver.c:642 +#: pg_backup_archiver.c:651 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "konnte nicht bestimmen, wo IF EXISTS in die Anweisung »%s« eingefügt werden soll" -#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 +#: pg_backup_archiver.c:837 pg_backup_archiver.c:839 #, c-format msgid "warning from original dump file: %s" msgstr "Warnung aus der ursprünglichen Ausgabedatei: %s" -#: pg_backup_archiver.c:864 +#: pg_backup_archiver.c:873 #, c-format msgid "creating %s \"%s.%s\"" msgstr "erstelle %s »%s.%s«" -#: pg_backup_archiver.c:867 +#: pg_backup_archiver.c:876 #, c-format msgid "creating %s \"%s\"" msgstr "erstelle %s »%s«" -#: pg_backup_archiver.c:917 +#: pg_backup_archiver.c:926 #, c-format msgid "connecting to new database \"%s\"" msgstr "verbinde mit neuer Datenbank »%s«" -#: pg_backup_archiver.c:944 +#: pg_backup_archiver.c:953 #, c-format msgid "processing %s" msgstr "verarbeite %s" -#: pg_backup_archiver.c:966 +#: pg_backup_archiver.c:975 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "verarbeite Daten für Tabelle »%s.%s«" -#: pg_backup_archiver.c:1036 +#: pg_backup_archiver.c:1045 #, c-format msgid "executing %s %s" msgstr "führe %s %s aus" -#: pg_backup_archiver.c:1096 +#: pg_backup_archiver.c:1114 #, c-format msgid "disabling triggers for %s" msgstr "schalte Trigger für %s aus" -#: pg_backup_archiver.c:1122 +#: pg_backup_archiver.c:1140 #, c-format msgid "enabling triggers for %s" msgstr "schalte Trigger für %s ein" -#: pg_backup_archiver.c:1187 +#: pg_backup_archiver.c:1205 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "interner Fehler -- WriteData kann nicht außerhalb des Kontexts einer DataDumper-Routine aufgerufen werden" -#: pg_backup_archiver.c:1379 +#: pg_backup_archiver.c:1397 #, c-format msgid "large-object output not supported in chosen format" msgstr "Large-Object-Ausgabe im gewählten Format nicht unterstützt" -#: pg_backup_archiver.c:1442 +#: pg_backup_archiver.c:1460 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "%d Large Object wiederhergestellt" msgstr[1] "%d Large Objects wiederhergestellt" -#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 +#: pg_backup_archiver.c:1487 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "Wiederherstellung von Large Object mit OID %u" -#: pg_backup_archiver.c:1481 +#: pg_backup_archiver.c:1499 #, c-format msgid "could not create large object %u: %s" msgstr "konnte Large Object %u nicht erstellen: %s" -#: pg_backup_archiver.c:1486 pg_dump.c:3863 +#: pg_backup_archiver.c:1504 pg_dump.c:4058 #, c-format msgid "could not open large object %u: %s" msgstr "konnte Large Object %u nicht öffnen: %s" -#: pg_backup_archiver.c:1542 +#: pg_backup_archiver.c:1560 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "konnte Inhaltsverzeichnisdatei »%s« nicht öffnen: %m" -#: pg_backup_archiver.c:1570 +#: pg_backup_archiver.c:1588 #, c-format msgid "line ignored: %s" msgstr "Zeile ignoriert: %s" -#: pg_backup_archiver.c:1577 pg_backup_db.c:609 +#: pg_backup_archiver.c:1595 pg_backup_db.c:607 #, c-format msgid "could not find entry for ID %d" msgstr "konnte Eintrag für ID %d nicht finden" -#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_archiver.c:1618 pg_backup_directory.c:219 #: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "konnte Inhaltsverzeichnisdatei nicht schließen: %m" -#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_archiver.c:1705 pg_backup_custom.c:151 pg_backup_directory.c:333 #: pg_backup_directory.c:600 pg_backup_directory.c:666 -#: pg_backup_directory.c:684 pg_dumpall.c:506 +#: pg_backup_directory.c:684 pg_dumpall.c:538 #, c-format msgid "could not open output file \"%s\": %m" msgstr "konnte Ausgabedatei »%s« nicht öffnen: %m" -#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 +#: pg_backup_archiver.c:1707 pg_backup_custom.c:157 #, c-format msgid "could not open output file: %m" msgstr "konnte Ausgabedatei nicht öffnen: %m" -#: pg_backup_archiver.c:1772 +#: pg_backup_archiver.c:1790 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "%zu Byte Large-Object-Daten geschrieben (Ergebnis = %d)" msgstr[1] "%zu Bytes Large-Object-Daten geschrieben (Ergebnis = %d)" -#: pg_backup_archiver.c:1778 +#: pg_backup_archiver.c:1796 #, c-format msgid "could not write to large object: %s" msgstr "konnte Large Object nicht schreiben: %s" -#: pg_backup_archiver.c:1868 +#: pg_backup_archiver.c:1886 #, c-format msgid "while INITIALIZING:" msgstr "in Phase INITIALIZING:" -#: pg_backup_archiver.c:1873 +#: pg_backup_archiver.c:1891 #, c-format msgid "while PROCESSING TOC:" msgstr "in Phase PROCESSING TOC:" -#: pg_backup_archiver.c:1878 +#: pg_backup_archiver.c:1896 #, c-format msgid "while FINALIZING:" msgstr "in Phase FINALIZING:" -#: pg_backup_archiver.c:1883 +#: pg_backup_archiver.c:1901 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "in Inhaltsverzeichniseintrag %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1959 +#: pg_backup_archiver.c:1977 #, c-format msgid "bad dumpId" msgstr "ungültige DumpId" -#: pg_backup_archiver.c:1980 +#: pg_backup_archiver.c:1998 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "ungültige Tabellen-DumpId für »TABLE DATA«-Eintrag" -#: pg_backup_archiver.c:2072 +#: pg_backup_archiver.c:2090 #, c-format msgid "unexpected data offset flag %d" msgstr "unerwartete Datenoffsetmarkierung %d" -#: pg_backup_archiver.c:2085 +#: pg_backup_archiver.c:2103 #, c-format msgid "file offset in dump file is too large" msgstr "Dateioffset in Dumpdatei ist zu groß" -#: pg_backup_archiver.c:2196 +#: pg_backup_archiver.c:2214 #, c-format msgid "directory name too long: \"%s\"" msgstr "Verzeichnisname zu lang: »%s«" -#: pg_backup_archiver.c:2246 +#: pg_backup_archiver.c:2264 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "Verzeichnis »%s« scheint kein gültiges Archiv zu sein (»toc.dat« existiert nicht)" -#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_archiver.c:2272 pg_backup_custom.c:168 pg_backup_custom.c:811 #: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "konnte Eingabedatei »%s« nicht öffnen: %m" -#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 +#: pg_backup_archiver.c:2279 pg_backup_custom.c:174 #, c-format msgid "could not open input file: %m" msgstr "konnte Eingabedatei nicht öffnen: %m" -#: pg_backup_archiver.c:2267 +#: pg_backup_archiver.c:2285 #, c-format msgid "could not read input file: %m" msgstr "konnte Eingabedatei nicht lesen: %m" -#: pg_backup_archiver.c:2269 +#: pg_backup_archiver.c:2287 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "Eingabedatei ist zu kurz (gelesen: %lu, erwartet: 5)" -#: pg_backup_archiver.c:2301 +#: pg_backup_archiver.c:2319 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "Eingabedatei ist anscheinend ein Dump im Textformat. Bitte verwenden Sie psql." -#: pg_backup_archiver.c:2307 +#: pg_backup_archiver.c:2325 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "Eingabedatei scheint kein gültiges Archiv zu sein (zu kurz?)" -#: pg_backup_archiver.c:2313 +#: pg_backup_archiver.c:2331 #, c-format msgid "input file does not appear to be a valid archive" msgstr "Eingabedatei scheint kein gültiges Archiv zu sein" -#: pg_backup_archiver.c:2322 +#: pg_backup_archiver.c:2340 #, c-format msgid "could not close input file: %m" msgstr "konnte Eingabedatei nicht schließen: %m" -#: pg_backup_archiver.c:2401 +#: pg_backup_archiver.c:2419 #, c-format msgid "could not open stdout for appending: %m" msgstr "konnte Standardausgabe nicht zum Anhängen öffnen: %m" -#: pg_backup_archiver.c:2446 +#: pg_backup_archiver.c:2464 #, c-format msgid "unrecognized file format \"%d\"" msgstr "nicht erkanntes Dateiformat »%d«" -#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4625 +#: pg_backup_archiver.c:2545 pg_backup_archiver.c:4698 #, c-format msgid "finished item %d %s %s" msgstr "Element %d %s %s abgeschlossen" -#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4638 +#: pg_backup_archiver.c:2549 pg_backup_archiver.c:4711 #, c-format msgid "worker process failed: exit code %d" msgstr "Arbeitsprozess fehlgeschlagen: Code %d" -#: pg_backup_archiver.c:2653 +#: pg_backup_archiver.c:2671 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "ID %d des Eintrags außerhalb des gültigen Bereichs -- vielleicht ein verfälschtes Inhaltsverzeichnis" -#: pg_backup_archiver.c:2736 +#: pg_backup_archiver.c:2754 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "Wiederherstellung von Tabellen mit WITH OIDS wird nicht mehr unterstützt" -#: pg_backup_archiver.c:2818 +#: pg_backup_archiver.c:2836 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "nicht erkannte Kodierung »%s«" -#: pg_backup_archiver.c:2823 +#: pg_backup_archiver.c:2842 #, c-format msgid "invalid ENCODING item: %s" msgstr "ungültiger ENCODING-Eintrag: %s" -#: pg_backup_archiver.c:2841 +#: pg_backup_archiver.c:2860 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "ungültiger STDSTRINGS-Eintrag: %s" -#: pg_backup_archiver.c:2866 +#: pg_backup_archiver.c:2885 #, c-format msgid "schema \"%s\" not found" msgstr "Schema »%s« nicht gefunden" -#: pg_backup_archiver.c:2873 +#: pg_backup_archiver.c:2892 #, c-format msgid "table \"%s\" not found" msgstr "Tabelle »%s« nicht gefunden" -#: pg_backup_archiver.c:2880 +#: pg_backup_archiver.c:2899 #, c-format msgid "index \"%s\" not found" msgstr "Index »%s« nicht gefunden" -#: pg_backup_archiver.c:2887 +#: pg_backup_archiver.c:2906 #, c-format msgid "function \"%s\" not found" msgstr "Funktion »%s« nicht gefunden" -#: pg_backup_archiver.c:2894 +#: pg_backup_archiver.c:2913 #, c-format msgid "trigger \"%s\" not found" msgstr "Trigger »%s« nicht gefunden" -#: pg_backup_archiver.c:3325 +#: pg_backup_archiver.c:3381 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "konnte Sitzungsbenutzer nicht auf »%s« setzen: %s" -#: pg_backup_archiver.c:3457 +#: pg_backup_archiver.c:3513 #, c-format msgid "could not set \"search_path\" to \"%s\": %s" msgstr "konnte »search_path« nicht auf »%s« setzen: %s" -#: pg_backup_archiver.c:3518 +#: pg_backup_archiver.c:3574 #, c-format msgid "could not set \"default_tablespace\" to %s: %s" msgstr "konnte »default_tablespace« nicht auf »%s« setzen: %s" -#: pg_backup_archiver.c:3567 +#: pg_backup_archiver.c:3623 #, c-format msgid "could not set \"default_table_access_method\": %s" msgstr "konnte »default_table_access_method« nicht setzen: %s" -#: pg_backup_archiver.c:3616 +#: pg_backup_archiver.c:3672 #, c-format msgid "could not alter table access method: %s" msgstr "konnte Tabellenzugriffsmethode nicht ändern: %s" -#: pg_backup_archiver.c:3717 +#: pg_backup_archiver.c:3773 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "kann Eigentümer für Objekttyp »%s« nicht setzen" -#: pg_backup_archiver.c:3982 +#: pg_backup_archiver.c:4054 #, c-format msgid "did not find magic string in file header" msgstr "magische Zeichenkette im Dateikopf nicht gefunden" -#: pg_backup_archiver.c:3996 +#: pg_backup_archiver.c:4068 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "nicht unterstützte Version (%d.%d) im Dateikopf" -#: pg_backup_archiver.c:4001 +#: pg_backup_archiver.c:4073 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "Prüfung der Integer-Größe (%lu) fehlgeschlagen" -#: pg_backup_archiver.c:4005 +#: pg_backup_archiver.c:4077 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "Archiv wurde auf einer Maschine mit größeren Integers erstellt; einige Operationen könnten fehlschlagen" -#: pg_backup_archiver.c:4015 +#: pg_backup_archiver.c:4087 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "erwartetes Format (%d) ist nicht das gleiche wie das in der Datei gefundene (%d)" -#: pg_backup_archiver.c:4037 +#: pg_backup_archiver.c:4109 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "Archiv ist komprimiert, aber diese Installation unterstützt keine Komprimierung (%s) -- keine Daten verfügbar" -#: pg_backup_archiver.c:4073 +#: pg_backup_archiver.c:4145 #, c-format msgid "invalid creation date in header" msgstr "ungültiges Erstellungsdatum im Kopf" -#: pg_backup_archiver.c:4207 +#: pg_backup_archiver.c:4279 #, c-format msgid "processing item %d %s %s" msgstr "verarbeite Element %d %s %s" -#: pg_backup_archiver.c:4292 +#: pg_backup_archiver.c:4364 #, c-format msgid "entering main parallel loop" msgstr "Eintritt in Hauptparallelschleife" -#: pg_backup_archiver.c:4303 +#: pg_backup_archiver.c:4375 #, c-format msgid "skipping item %d %s %s" msgstr "Element %d %s %s wird übersprungen" -#: pg_backup_archiver.c:4312 +#: pg_backup_archiver.c:4384 #, c-format msgid "launching item %d %s %s" msgstr "starte Element %d %s %s" -#: pg_backup_archiver.c:4366 +#: pg_backup_archiver.c:4438 #, c-format msgid "finished main parallel loop" msgstr "Hauptparallelschleife beendet" -#: pg_backup_archiver.c:4402 +#: pg_backup_archiver.c:4474 #, c-format msgid "processing missed item %d %s %s" msgstr "verarbeite verpasstes Element %d %s %s" -#: pg_backup_archiver.c:4944 +#: pg_backup_archiver.c:5017 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "Tabelle »%s« konnte nicht erzeugt werden, ihre Daten werden nicht wiederhergestellt werden" -#: pg_backup_custom.c:376 pg_backup_null.c:143 +#: pg_backup_custom.c:375 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "ungültige OID für Large Object" -#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 -#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 +#: pg_backup_custom.c:440 pg_backup_custom.c:506 pg_backup_custom.c:635 +#: pg_backup_custom.c:869 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "Fehler beim Suchen in Datei: %m" -#: pg_backup_custom.c:480 +#: pg_backup_custom.c:479 #, c-format msgid "data block %d has wrong seek position" msgstr "Datenblock %d hat falsche Seek-Position" -#: pg_backup_custom.c:497 +#: pg_backup_custom.c:496 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "unerkannter Datenblocktyp (%d) beim Suchen im Archiv gefunden" -#: pg_backup_custom.c:519 +#: pg_backup_custom.c:518 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "konnte Block-ID %d nicht im Archiv finden -- möglicherweise wegen Wiederherstellung außer der Reihe, was nicht möglich ist, weil die Eingabedatei kein Suchen unterstützt" -#: pg_backup_custom.c:524 +#: pg_backup_custom.c:523 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "konnte Block-ID %d nicht im Archiv finden -- möglicherweise beschädigtes Archiv" -#: pg_backup_custom.c:531 +#: pg_backup_custom.c:530 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "unerwartete Block-ID (%d) beim Lesen der Daten gefunden -- erwartet wurde %d" -#: pg_backup_custom.c:545 +#: pg_backup_custom.c:544 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "unerkannter Datenblocktyp %d beim Wiederherstellen des Archivs gefunden" -#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_custom.c:750 pg_backup_custom.c:802 pg_backup_custom.c:944 #: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "konnte Positionszeiger in Archivdatei nicht ermitteln: %m" -#: pg_backup_custom.c:767 pg_backup_custom.c:807 +#: pg_backup_custom.c:766 pg_backup_custom.c:806 #, c-format msgid "could not close archive file: %m" msgstr "konnte Archivdatei nicht schließen: %m" -#: pg_backup_custom.c:790 +#: pg_backup_custom.c:789 #, c-format msgid "can only reopen input archives" msgstr "nur Eingabearchive können neu geöffnet werden" -#: pg_backup_custom.c:797 +#: pg_backup_custom.c:796 #, c-format msgid "parallel restore from standard input is not supported" msgstr "parallele Wiederherstellung aus der Standardeingabe wird nicht unterstützt" -#: pg_backup_custom.c:799 +#: pg_backup_custom.c:798 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "parallele Wiederherstellung aus einer Datei, die kein Suchen ermöglicht, wird nicht unterstützt" -#: pg_backup_custom.c:815 +#: pg_backup_custom.c:814 #, c-format msgid "could not set seek position in archive file: %m" msgstr "konnte Positionszeiger in Archivdatei nicht setzen: %m" -#: pg_backup_custom.c:894 +#: pg_backup_custom.c:893 #, c-format msgid "compressor active" msgstr "Kompressor ist aktiv" -#: pg_backup_db.c:42 +#: pg_backup_db.c:40 #, c-format -msgid "could not get server_version from libpq" -msgstr "konnte server_version nicht von libpq ermitteln" +msgid "could not get \"server_version\" from libpq" +msgstr "konnte »server_version« nicht von libpq ermitteln" -#: pg_backup_db.c:53 pg_dumpall.c:1830 +#: pg_backup_db.c:51 pg_dumpall.c:1919 #, c-format msgid "aborting because of server version mismatch" msgstr "Abbruch wegen unpassender Serverversion" -#: pg_backup_db.c:54 pg_dumpall.c:1831 +#: pg_backup_db.c:52 pg_dumpall.c:1920 #, c-format msgid "server version: %s; %s version: %s" msgstr "Version des Servers: %s; Version von %s: %s" -#: pg_backup_db.c:120 +#: pg_backup_db.c:118 #, c-format msgid "already connected to a database" msgstr "bereits mit einer Datenbank verbunden" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 +#: pg_backup_db.c:126 pg_backup_db.c:176 pg_dumpall.c:1766 pg_dumpall.c:1868 msgid "Password: " msgstr "Passwort: " -#: pg_backup_db.c:170 +#: pg_backup_db.c:168 #, c-format msgid "could not connect to database" msgstr "konnte nicht mit der Datenbank verbinden" -#: pg_backup_db.c:187 +#: pg_backup_db.c:185 #, c-format msgid "reconnection failed: %s" msgstr "Wiederverbindung fehlgeschlagen: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:787 pg_dump_sort.c:1213 -#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 +#: pg_backup_db.c:188 pg_backup_db.c:262 pg_dump.c:920 pg_dump_sort.c:1251 +#: pg_dump_sort.c:1271 pg_dumpall.c:1793 pg_dumpall.c:1877 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 +#: pg_backup_db.c:269 pg_dumpall.c:1982 pg_dumpall.c:2005 #, c-format msgid "query failed: %s" msgstr "Anfrage fehlgeschlagen: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 +#: pg_backup_db.c:271 pg_dumpall.c:1983 pg_dumpall.c:2006 #, c-format msgid "Query was: %s" msgstr "Anfrage war: %s" -#: pg_backup_db.c:315 +#: pg_backup_db.c:313 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" msgstr[0] "Anfrage ergab %d Zeile anstatt einer: %s" msgstr[1] "Anfrage ergab %d Zeilen anstatt einer: %s" -#: pg_backup_db.c:351 +#: pg_backup_db.c:349 #, c-format msgid "%s: %sCommand was: %s" msgstr "%s: %sDie Anweisung war: %s" -#: pg_backup_db.c:407 pg_backup_db.c:481 pg_backup_db.c:488 +#: pg_backup_db.c:405 pg_backup_db.c:479 pg_backup_db.c:486 msgid "could not execute query" msgstr "konnte Anfrage nicht ausführen" -#: pg_backup_db.c:460 +#: pg_backup_db.c:458 #, c-format msgid "error returned by PQputCopyData: %s" msgstr "Fehler in PQputCopyData: %s" -#: pg_backup_db.c:509 +#: pg_backup_db.c:507 #, c-format msgid "error returned by PQputCopyEnd: %s" msgstr "Fehler in PQputCopyEnd: %s" -#: pg_backup_db.c:515 +#: pg_backup_db.c:513 #, c-format msgid "COPY failed for table \"%s\": %s" msgstr "COPY fehlgeschlagen für Tabelle »%s«: %s" -#: pg_backup_db.c:521 pg_dump.c:2271 +#: pg_backup_db.c:519 pg_dump.c:2434 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "unerwartete zusätzliche Ergebnisse während COPY von Tabelle »%s«" -#: pg_backup_db.c:533 +#: pg_backup_db.c:531 msgid "could not start database transaction" msgstr "konnte Datenbanktransaktion nicht starten" -#: pg_backup_db.c:541 +#: pg_backup_db.c:539 msgid "could not commit database transaction" msgstr "konnte Datenbanktransaktion nicht beenden" @@ -1458,100 +1458,140 @@ msgstr[1] "unvollständiger Tar-Dateikopf gefunden (%lu Bytes)" msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "beschädigter Tar-Kopf in %s gefunden (%d erwartet, %d berechnet), Dateiposition %llu" -#: pg_backup_utils.c:54 +#: pg_backup_utils.c:56 #, c-format msgid "unrecognized section name: \"%s\"" msgstr "unbekannter Abschnittsname: »%s«" -#: pg_backup_utils.c:55 pg_dump.c:693 pg_dump.c:710 pg_dumpall.c:370 -#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 -#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 -#: pg_restore.c:337 +#: pg_backup_utils.c:57 pg_dump.c:798 pg_dump.c:815 pg_dumpall.c:386 +#: pg_dumpall.c:396 pg_dumpall.c:404 pg_dumpall.c:412 pg_dumpall.c:419 +#: pg_dumpall.c:429 pg_dumpall.c:520 pg_restore.c:324 pg_restore.c:340 +#: pg_restore.c:354 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_backup_utils.c:66 +#: pg_backup_utils.c:68 #, c-format msgid "out of on_exit_nicely slots" msgstr "on_exit_nicely-Slots aufgebraucht" -#: pg_dump.c:708 pg_dumpall.c:378 pg_restore.c:321 +#: pg_dump.c:813 pg_dumpall.c:394 pg_restore.c:338 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: pg_dump.c:727 pg_restore.c:344 +#: pg_dump.c:825 pg_restore.c:362 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "Optionen -s/--schema-only und -a/--data-only können nicht zusammen verwendet werden" -#: pg_dump.c:730 +#: pg_dump.c:827 pg_restore.c:364 +#, c-format +msgid "options -s/--schema-only and --statistics-only cannot be used together" +msgstr "Optionen -s/--schema-only und --statistics-only können nicht zusammen verwendet werden" + +#: pg_dump.c:829 pg_restore.c:366 +#, c-format +msgid "options -a/--data-only and --statistics-only cannot be used together" +msgstr "Optionen -a/--data-only und --statistic-only können nicht zusammen verwendet werden" + +#: pg_dump.c:833 pg_restore.c:370 +#, c-format +msgid "options -a/--data-only and --no-data cannot be used together" +msgstr "Optionen -a/--data-only und --no-data können nicht zusammen verwendet werden" + +#: pg_dump.c:835 pg_restore.c:372 +#, c-format +msgid "options -s/--schema-only and --no-schema cannot be used together" +msgstr "Optionen -s/--schema-only und --no-schema können nicht zusammen verwendet werden" + +#: pg_dump.c:837 pg_restore.c:374 +#, c-format +msgid "options --statistics-only and --no-statistics cannot be used together" +msgstr "Optionen --statistics-only und --no-statistics können nicht zusammen verwendet werden" + +#: pg_dump.c:841 pg_restore.c:378 +#, c-format +msgid "options --with-data and --no-data cannot be used together" +msgstr "Optionen --with-data und --no-data können nicht zusammen verwendet werden" + +#: pg_dump.c:843 pg_restore.c:380 +#, c-format +msgid "options --with-schema and --no-schema cannot be used together" +msgstr "Optionen --with-schema und --no-schema können nicht zusammen verwendet werden" + +#: pg_dump.c:845 pg_restore.c:382 +#, c-format +msgid "options --with-statistics and --no-statistics cannot be used together" +msgstr "Optionen --with-statistics und --no-statistics können nicht zusammen verwendet werden" + +#: pg_dump.c:848 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "Optionen -s/--schema-only und --include-foreign-data können nicht zusammen verwendet werden" -#: pg_dump.c:733 +#: pg_dump.c:851 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "Option --include-foreign-data wird nicht mit paralleler Sicherung unterstützt" -#: pg_dump.c:736 pg_restore.c:347 +#: pg_dump.c:854 pg_restore.c:385 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "Optionen -c/--clean und -a/--data-only können nicht zusammen verwendet werden" -#: pg_dump.c:739 pg_dumpall.c:408 pg_restore.c:375 +#: pg_dump.c:857 pg_dumpall.c:424 pg_restore.c:428 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "Option --if-exists benötigt Option -c/--clean" -#: pg_dump.c:746 +#: pg_dump.c:879 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "Option --on-conflict-do-nothing benötigt Option --inserts, --rows-per-insert oder --column-inserts" -#: pg_dump.c:775 +#: pg_dump.c:908 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "unbekannter Komprimierungsalgorithmus: »%s«" -#: pg_dump.c:782 +#: pg_dump.c:915 #, c-format msgid "invalid compression specification: %s" msgstr "ungültige Komprimierungsangabe: %s" -#: pg_dump.c:795 +#: pg_dump.c:928 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "Komprimierungsoption »%s« wird aktuell von pg_dump nicht unterstützt" -#: pg_dump.c:807 +#: pg_dump.c:940 #, c-format msgid "parallel backup only supported by the directory format" msgstr "parallele Sicherung wird nur vom Ausgabeformat »Verzeichnis« unterstützt" -#: pg_dump.c:853 +#: pg_dump.c:986 #, c-format msgid "last built-in OID is %u" msgstr "letzte eingebaute OID ist %u" -#: pg_dump.c:862 +#: pg_dump.c:995 #, c-format msgid "no matching schemas were found" msgstr "keine passenden Schemas gefunden" -#: pg_dump.c:879 +#: pg_dump.c:1012 #, c-format msgid "no matching tables were found" msgstr "keine passenden Tabellen gefunden" -#: pg_dump.c:907 +#: pg_dump.c:1040 #, c-format msgid "no matching extensions were found" msgstr "keine passenden Erweiterungen gefunden" -#: pg_dump.c:1091 +#: pg_dump.c:1233 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1560,17 +1600,17 @@ msgstr "" "%s gibt eine Datenbank als Textdatei oder in anderen Formaten aus.\n" "\n" -#: pg_dump.c:1092 pg_dumpall.c:635 pg_restore.c:452 +#: pg_dump.c:1234 pg_dumpall.c:668 pg_restore.c:503 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: pg_dump.c:1093 +#: pg_dump.c:1235 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: pg_dump.c:1095 pg_dumpall.c:638 pg_restore.c:455 +#: pg_dump.c:1237 pg_dumpall.c:671 pg_restore.c:506 #, c-format msgid "" "\n" @@ -1579,12 +1619,12 @@ msgstr "" "\n" "Allgemeine Optionen:\n" -#: pg_dump.c:1096 +#: pg_dump.c:1238 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=DATEINAME Name der Ausgabedatei oder des -verzeichnisses\n" -#: pg_dump.c:1097 +#: pg_dump.c:1239 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1593,22 +1633,22 @@ msgstr "" " -F, --format=c|d|t|p Ausgabeformat (custom, d=Verzeichnis, tar,\n" " plain text)\n" -#: pg_dump.c:1099 +#: pg_dump.c:1241 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM so viele parallele Jobs zur Sicherung verwenden\n" -#: pg_dump.c:1100 pg_dumpall.c:640 +#: pg_dump.c:1242 pg_dumpall.c:673 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose »Verbose«-Modus\n" -#: pg_dump.c:1101 pg_dumpall.c:641 +#: pg_dump.c:1243 pg_dumpall.c:674 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_dump.c:1102 +#: pg_dump.c:1244 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1617,31 +1657,31 @@ msgstr "" " -Z, --compress=METHODE[:DETAIL]\n" " wie angegeben komprimieren\n" -#: pg_dump.c:1104 pg_dumpall.c:642 +#: pg_dump.c:1246 pg_dumpall.c:675 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=ZEIT Abbruch nach ZEIT Warten auf Tabellensperre\n" -#: pg_dump.c:1105 pg_dumpall.c:670 +#: pg_dump.c:1247 pg_dumpall.c:707 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " --no-sync nicht warten, bis Änderungen sicher auf\n" " Festplatte geschrieben sind\n" -#: pg_dump.c:1106 +#: pg_dump.c:1248 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHODE Methode zum Synchronisieren von Dateien auf\n" " Festplatte setzen\n" -#: pg_dump.c:1107 pg_dumpall.c:643 +#: pg_dump.c:1249 pg_dumpall.c:676 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_dump.c:1109 pg_dumpall.c:644 +#: pg_dump.c:1251 pg_dumpall.c:677 #, c-format msgid "" "\n" @@ -1650,64 +1690,64 @@ msgstr "" "\n" "Optionen die den Inhalt der Ausgabe kontrollieren:\n" -#: pg_dump.c:1110 pg_dumpall.c:645 +#: pg_dump.c:1252 pg_dumpall.c:678 #, c-format -msgid " -a, --data-only dump only the data, not the schema\n" -msgstr " -a, --data-only nur Daten ausgeben, nicht das Schema\n" +msgid " -a, --data-only dump only the data, not the schema or statistics\n" +msgstr " -a, --data-only nur die Daten ausgeben, nicht das Schema oder Statistiken\n" -#: pg_dump.c:1111 +#: pg_dump.c:1253 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects Large Objects mit ausgeben\n" -#: pg_dump.c:1112 +#: pg_dump.c:1254 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (gleich --large-objects, veraltet)\n" -#: pg_dump.c:1113 +#: pg_dump.c:1255 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects Large Objects nicht mit ausgeben\n" -#: pg_dump.c:1114 +#: pg_dump.c:1256 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (gleich --no-large-objects, veraltet)\n" -#: pg_dump.c:1115 pg_restore.c:466 +#: pg_dump.c:1257 pg_restore.c:517 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean Datenbankobjekte vor der Wiedererstellung löschen\n" -#: pg_dump.c:1116 +#: pg_dump.c:1258 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr "" " -C, --create Anweisungen zum Erstellen der Datenbank in\n" " Ausgabe einfügen\n" -#: pg_dump.c:1117 +#: pg_dump.c:1259 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=MUSTER nur die angegebene(n) Erweiterung(en) ausgeben\n" -#: pg_dump.c:1118 pg_dumpall.c:647 +#: pg_dump.c:1260 pg_dumpall.c:680 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=KODIERUNG Daten in Kodierung KODIERUNG ausgeben\n" -#: pg_dump.c:1119 +#: pg_dump.c:1261 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=MUSTER nur das/die angegebene(n) Schema(s) ausgeben\n" -#: pg_dump.c:1120 +#: pg_dump.c:1262 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=MUSTER das/die angegebene(n) Schema(s) NICHT ausgeben\n" -#: pg_dump.c:1121 +#: pg_dump.c:1263 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1716,58 +1756,58 @@ msgstr "" " -O, --no-owner Wiederherstellung der Objekteigentümerschaft im\n" " »plain text«-Format auslassen\n" -#: pg_dump.c:1123 pg_dumpall.c:651 +#: pg_dump.c:1265 pg_dumpall.c:684 #, c-format -msgid " -s, --schema-only dump only the schema, no data\n" -msgstr " -s, --schema-only nur das Schema, nicht die Daten, ausgeben\n" +msgid " -s, --schema-only dump only the schema, no data or statistics\n" +msgstr " -s, --schema-only nur das Schema ausgeben, nicht Daten oder Statistiken\n" -#: pg_dump.c:1124 +#: pg_dump.c:1266 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr " -S, --superuser=NAME Superusername für »plain text«-Format\n" -#: pg_dump.c:1125 +#: pg_dump.c:1267 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=MUSTER nur die angegebene(n) Tabelle(n) ausgeben\n" -#: pg_dump.c:1126 +#: pg_dump.c:1268 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=MUSTER die angegebene(n) Tabelle(n) NICHT ausgeben\n" -#: pg_dump.c:1127 pg_dumpall.c:654 +#: pg_dump.c:1269 pg_dumpall.c:687 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges Zugriffsprivilegien (grant/revoke) nicht ausgeben\n" -#: pg_dump.c:1128 pg_dumpall.c:655 +#: pg_dump.c:1270 pg_dumpall.c:688 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade wird nur von Upgrade-Programmen verwendet\n" -#: pg_dump.c:1129 pg_dumpall.c:656 +#: pg_dump.c:1271 pg_dumpall.c:689 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr "" " --column-inserts Daten als INSERT-Anweisungen mit Spaltennamen\n" " ausgeben\n" -#: pg_dump.c:1130 pg_dumpall.c:657 +#: pg_dump.c:1272 pg_dumpall.c:690 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr "" " --disable-dollar-quoting Dollar-Quoting abschalten, normales SQL-Quoting\n" " verwenden\n" -#: pg_dump.c:1131 pg_dumpall.c:658 pg_restore.c:483 +#: pg_dump.c:1273 pg_dumpall.c:691 pg_restore.c:534 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr "" " --disable-triggers Trigger während der Datenwiederherstellung\n" " abschalten\n" -#: pg_dump.c:1132 +#: pg_dump.c:1274 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1776,12 +1816,12 @@ msgstr "" " --enable-row-security Sicherheit auf Zeilenebene einschalten (nur Daten\n" " ausgeben, auf die der Benutzer Zugriff hat)\n" -#: pg_dump.c:1134 +#: pg_dump.c:1276 #, c-format msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" msgstr " --exclude-extension=MUSTER die angegebene(n) Erweiterung(en) NICHT ausgeben\n" -#: pg_dump.c:1135 +#: pg_dump.c:1277 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1792,12 +1832,12 @@ msgstr "" " die angegebene(n) Tabelle(n) NICHT ausgeben,\n" " einschließlich abgeleiteter und Partitionstabellen\n" -#: pg_dump.c:1138 +#: pg_dump.c:1280 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=MUSTER Daten der angegebenen Tabelle(n) NICHT ausgeben\n" -#: pg_dump.c:1139 +#: pg_dump.c:1281 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1808,12 +1848,12 @@ msgstr "" " Daten der angegebenen Tabelle(n) NICHT ausgeben,\n" " einschließlich abgeleiteter und Partitionstabellen\n" -#: pg_dump.c:1142 pg_dumpall.c:660 +#: pg_dump.c:1284 pg_dumpall.c:693 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=ZAHL Einstellung für extra_float_digits\n" -#: pg_dump.c:1143 +#: pg_dump.c:1285 #, c-format msgid "" " --filter=FILENAME include or exclude objects and data from dump\n" @@ -1822,12 +1862,12 @@ msgstr "" " --filter=DATEINAME Objekte und Daten basierend auf Ausdrücken in DATEINAME\n" " mit sichern oder überspringen\n" -#: pg_dump.c:1145 pg_dumpall.c:662 pg_restore.c:487 +#: pg_dump.c:1287 pg_dumpall.c:695 pg_restore.c:538 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists IF EXISTS verwenden, wenn Objekte gelöscht werden\n" -#: pg_dump.c:1146 +#: pg_dump.c:1288 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1838,91 +1878,121 @@ msgstr "" " Daten von Fremdtabellen auf Fremdservern, die\n" " mit MUSTER übereinstimmen, mit sichern\n" -#: pg_dump.c:1149 pg_dumpall.c:663 +#: pg_dump.c:1291 pg_dumpall.c:696 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts Daten als INSERT-Anweisungen statt COPY ausgeben\n" -#: pg_dump.c:1150 pg_dumpall.c:664 +#: pg_dump.c:1292 pg_dumpall.c:697 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root Partitionen über die Wurzeltabelle laden\n" -#: pg_dump.c:1151 pg_dumpall.c:665 +#: pg_dump.c:1293 pg_dumpall.c:698 #, c-format -msgid " --no-comments do not dump comments\n" -msgstr " --no-comments Kommentare nicht ausgeben\n" +msgid " --no-comments do not dump comment commands\n" +msgstr " --no-comments Kommentar-Befehle nicht ausgeben\n" -#: pg_dump.c:1152 pg_dumpall.c:666 +#: pg_dump.c:1294 pg_dumpall.c:699 +#, c-format +msgid " --no-data do not dump data\n" +msgstr " --no-data Daten nicht ausgeben\n" + +#: pg_dump.c:1295 pg_dumpall.c:700 +#, c-format +msgid " --no-policies do not dump row security policies\n" +msgstr " --no-policies Policys für Sicherheit auf Zeilenebene nicht ausgeben\n" + +#: pg_dump.c:1296 pg_dumpall.c:701 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications Publikationen nicht ausgeben\n" -#: pg_dump.c:1153 pg_dumpall.c:668 +#: pg_dump.c:1297 pg_dumpall.c:703 +#, c-format +msgid " --no-schema do not dump schema\n" +msgstr " --no-schema Schema nicht ausgeben\n" + +#: pg_dump.c:1298 pg_dumpall.c:704 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels Security-Label-Zuweisungen nicht ausgeben\n" -#: pg_dump.c:1154 pg_dumpall.c:669 +#: pg_dump.c:1299 pg_dumpall.c:705 +#, c-format +msgid " --no-statistics do not dump statistics\n" +msgstr " --no-statistics Statistiken nicht ausgeben\n" + +#: pg_dump.c:1300 pg_dumpall.c:706 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions Subskriptionen nicht ausgeben\n" -#: pg_dump.c:1155 pg_dumpall.c:671 +#: pg_dump.c:1301 pg_dumpall.c:708 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method Tabellenzugriffsmethoden nicht ausgeben\n" -#: pg_dump.c:1156 pg_dumpall.c:672 +#: pg_dump.c:1302 pg_dumpall.c:709 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces Tablespace-Zuordnungen nicht ausgeben\n" -#: pg_dump.c:1157 pg_dumpall.c:673 +#: pg_dump.c:1303 pg_dumpall.c:710 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression TOAST-Komprimierungsmethoden nicht ausgeben\n" -#: pg_dump.c:1158 pg_dumpall.c:674 +#: pg_dump.c:1304 pg_dumpall.c:711 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data Daten in ungeloggten Tabellen nicht ausgeben\n" -#: pg_dump.c:1159 pg_dumpall.c:675 +#: pg_dump.c:1305 pg_dumpall.c:712 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing INSERT-Befehle mit ON CONFLICT DO NOTHING ausgeben\n" -#: pg_dump.c:1160 pg_dumpall.c:676 +#: pg_dump.c:1306 pg_dumpall.c:713 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr "" " --quote-all-identifiers alle Bezeichner in Anführungszeichen, selbst wenn\n" " kein Schlüsselwort\n" -#: pg_dump.c:1161 pg_dumpall.c:677 +#: pg_dump.c:1307 pg_dumpall.c:714 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=ANZAHL Anzahl Zeilen pro INSERT; impliziert --inserts\n" -#: pg_dump.c:1162 +#: pg_dump.c:1308 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr "" " --section=ABSCHNITT angegebenen Abschnitt ausgeben (pre-data, data\n" " oder post-data)\n" -#: pg_dump.c:1163 +#: pg_dump.c:1309 +#, c-format +msgid " --sequence-data include sequence data in dump\n" +msgstr " --sequence-data Sequenzdaten in Ausgabe einfügen\n" + +#: pg_dump.c:1310 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr " --serializable-deferrable warten bis der Dump ohne Anomalien laufen kann\n" -#: pg_dump.c:1164 +#: pg_dump.c:1311 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT angegebenen Snapshot für den Dump verwenden\n" -#: pg_dump.c:1165 pg_restore.c:497 +#: pg_dump.c:1312 pg_dumpall.c:715 +#, c-format +msgid " --statistics-only dump only the statistics, not schema or data\n" +msgstr " --statistics-only nur die Statistiken ausgeben, nicht Schema oder Daten\n" + +#: pg_dump.c:1313 pg_restore.c:553 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1931,7 +2001,7 @@ msgstr "" " --strict-names Tabellen- oder Schemamuster müssen auf mindestens\n" " je ein Objekt passen\n" -#: pg_dump.c:1167 +#: pg_dump.c:1315 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1940,7 +2010,7 @@ msgstr "" " --table-and-children=MUSTER nur die angegebene(n) Tabelle(n) ausgeben,\n" " einschließlich abgeleiteter und Partitionstabellen\n" -#: pg_dump.c:1169 pg_dumpall.c:678 pg_restore.c:500 +#: pg_dump.c:1317 pg_dumpall.c:716 pg_restore.c:556 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1952,7 +2022,22 @@ msgstr "" " OWNER Befehle verwenden, um Eigentümerschaft zu\n" " setzen\n" -#: pg_dump.c:1173 pg_dumpall.c:682 pg_restore.c:504 +#: pg_dump.c:1320 pg_dumpall.c:719 pg_restore.c:559 +#, c-format +msgid " --with-data dump the data\n" +msgstr " --with-data die Daten ausgeben\n" + +#: pg_dump.c:1321 pg_dumpall.c:720 pg_restore.c:560 +#, c-format +msgid " --with-schema dump the schema\n" +msgstr " --with-schema das Schema ausgeben\n" + +#: pg_dump.c:1322 pg_dumpall.c:721 pg_restore.c:561 +#, c-format +msgid " --with-statistics dump the statistics\n" +msgstr " --with-statistics die Statistiken ausgeben\n" + +#: pg_dump.c:1324 pg_dumpall.c:723 pg_restore.c:563 #, c-format msgid "" "\n" @@ -1961,42 +2046,42 @@ msgstr "" "\n" "Verbindungsoptionen:\n" -#: pg_dump.c:1174 +#: pg_dump.c:1325 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=DBNAME auszugebende Datenbank\n" -#: pg_dump.c:1175 pg_dumpall.c:684 pg_restore.c:505 +#: pg_dump.c:1326 pg_dumpall.c:725 pg_restore.c:564 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" -#: pg_dump.c:1176 pg_dumpall.c:686 pg_restore.c:506 +#: pg_dump.c:1327 pg_dumpall.c:727 pg_restore.c:565 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT Portnummer des Datenbankservers\n" -#: pg_dump.c:1177 pg_dumpall.c:687 pg_restore.c:507 +#: pg_dump.c:1328 pg_dumpall.c:728 pg_restore.c:566 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME Datenbankbenutzername\n" -#: pg_dump.c:1178 pg_dumpall.c:688 pg_restore.c:508 +#: pg_dump.c:1329 pg_dumpall.c:729 pg_restore.c:567 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password niemals nach Passwort fragen\n" -#: pg_dump.c:1179 pg_dumpall.c:689 pg_restore.c:509 +#: pg_dump.c:1330 pg_dumpall.c:730 pg_restore.c:568 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password nach Passwort fragen (sollte automatisch geschehen)\n" -#: pg_dump.c:1180 pg_dumpall.c:690 +#: pg_dump.c:1331 pg_dumpall.c:731 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLLENNAME vor der Ausgabe SET ROLE ausführen\n" -#: pg_dump.c:1182 +#: pg_dump.c:1333 #, c-format msgid "" "\n" @@ -2009,537 +2094,560 @@ msgstr "" "PGDATABASE verwendet.\n" "\n" -#: pg_dump.c:1184 pg_dumpall.c:694 pg_restore.c:516 +#: pg_dump.c:1335 pg_dumpall.c:735 pg_restore.c:575 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Berichten Sie Fehler an <%s>.\n" -#: pg_dump.c:1185 pg_dumpall.c:695 pg_restore.c:517 +#: pg_dump.c:1336 pg_dumpall.c:736 pg_restore.c:576 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: pg_dump.c:1204 pg_dumpall.c:518 +#: pg_dump.c:1355 pg_dumpall.c:550 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "ungültige Clientkodierung »%s« angegeben" -#: pg_dump.c:1344 +#: pg_dump.c:1503 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "parallele Dumps von Standby-Servern werden von dieser Serverversion nicht unterstützt" -#: pg_dump.c:1409 +#: pg_dump.c:1568 #, c-format msgid "invalid output format \"%s\" specified" msgstr "ungültiges Ausgabeformat »%s« angegeben" -#: pg_dump.c:1450 pg_dump.c:1506 pg_dump.c:1559 pg_dumpall.c:1467 +#: pg_dump.c:1609 pg_dump.c:1665 pg_dump.c:1718 pg_dumpall.c:1556 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "falscher qualifizierter Name (zu viele Namensteile): %s" -#: pg_dump.c:1458 +#: pg_dump.c:1617 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "keine passenden Schemas für Muster »%s« gefunden" -#: pg_dump.c:1511 +#: pg_dump.c:1670 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "keine passenden Erweiterungen für Muster »%s« gefunden" -#: pg_dump.c:1564 +#: pg_dump.c:1723 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "keine passenden Fremdserver für Muster »%s« gefunden" -#: pg_dump.c:1635 +#: pg_dump.c:1794 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "falscher Relationsname (zu viele Namensteile): %s" -#: pg_dump.c:1657 +#: pg_dump.c:1816 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "keine passenden Tabellen für Muster »%s« gefunden" -#: pg_dump.c:1684 +#: pg_dump.c:1843 #, c-format msgid "You are currently not connected to a database." msgstr "Sie sind gegenwärtig nicht mit einer Datenbank verbunden." -#: pg_dump.c:1687 +#: pg_dump.c:1846 #, c-format msgid "cross-database references are not implemented: %s" msgstr "Verweise auf andere Datenbanken sind nicht implementiert: %s" -#: pg_dump.c:2146 +#: pg_dump.c:2305 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "gebe Inhalt der Tabelle »%s.%s« aus" -#: pg_dump.c:2252 +#: pg_dump.c:2415 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Ausgabe des Inhalts der Tabelle »%s« fehlgeschlagen: PQgetCopyData() fehlgeschlagen." -#: pg_dump.c:2253 pg_dump.c:2263 +#: pg_dump.c:2416 pg_dump.c:2426 #, c-format msgid "Error message from server: %s" msgstr "Fehlermeldung vom Server: %s" -#: pg_dump.c:2254 pg_dump.c:2264 +#: pg_dump.c:2417 pg_dump.c:2427 #, c-format msgid "Command was: %s" msgstr "Die Anweisung war: %s" -#: pg_dump.c:2262 +#: pg_dump.c:2425 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Ausgabe des Inhalts der Tabelle »%s« fehlgeschlagen: PQgetResult() fehlgeschlagen." -#: pg_dump.c:2344 +#: pg_dump.c:2516 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "falsche Anzahl Felder von Tabelle »%s« erhalten" -#: pg_dump.c:3042 +#: pg_dump.c:3231 #, c-format msgid "saving database definition" msgstr "sichere Datenbankdefinition" -#: pg_dump.c:3151 +#: pg_dump.c:3346 #, c-format msgid "unrecognized locale provider: %s" msgstr "unbekannter Locale-Provider: %s" -#: pg_dump.c:3512 +#: pg_dump.c:3707 #, c-format msgid "saving encoding = %s" msgstr "sichere Kodierung = %s" -#: pg_dump.c:3537 +#: pg_dump.c:3732 #, c-format msgid "saving \"standard_conforming_strings = %s\"" msgstr "sichere »standard_conforming_strings = %s«" -#: pg_dump.c:3576 +#: pg_dump.c:3771 #, c-format msgid "could not parse result of current_schemas()" msgstr "konnte Ergebnis von current_schemas() nicht interpretieren" -#: pg_dump.c:3595 +#: pg_dump.c:3790 #, c-format msgid "saving \"search_path = %s\"" msgstr "sichere »search_path = %s«" -#: pg_dump.c:3631 +#: pg_dump.c:3826 #, c-format msgid "reading large objects" msgstr "lese Large Objects" -#: pg_dump.c:3852 +#: pg_dump.c:4047 #, c-format msgid "saving large objects \"%s\"" msgstr "sichere Large Objects »%s«" -#: pg_dump.c:3873 +#: pg_dump.c:4068 #, c-format msgid "error reading large object %u: %s" msgstr "Fehler beim Lesen von Large Object %u: %s" -#: pg_dump.c:3976 +#: pg_dump.c:4176 #, c-format msgid "reading row-level security policies" msgstr "lese Policys für Sicherheit auf Zeilenebene" -#: pg_dump.c:4117 +#: pg_dump.c:4317 #, c-format msgid "unexpected policy command type: %c" msgstr "unerwarteter Policy-Befehlstyp: %c" -#: pg_dump.c:4567 pg_dump.c:5103 pg_dump.c:12315 pg_dump.c:18137 -#: pg_dump.c:18139 pg_dump.c:18761 +#: pg_dump.c:4759 pg_dump.c:5316 pg_dump.c:7912 pg_dump.c:12975 pg_dump.c:19072 +#: pg_dump.c:19074 pg_dump.c:19706 #, c-format msgid "could not parse %s array" msgstr "konnte %s-Array nicht interpretieren" -#: pg_dump.c:4759 +#: pg_dump.c:4975 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "Subskriptionen werden nicht ausgegeben, weil der aktuelle Benutzer kein Superuser ist" -#: pg_dump.c:4965 +#: pg_dump.c:5179 #, c-format msgid "subscription with OID %u does not exist" msgstr "Subskription mit OID %u existiert nicht" -#: pg_dump.c:4972 +#: pg_dump.c:5186 #, c-format msgid "failed sanity check, table with OID %u not found" msgstr "Sanity-Check fehlgeschlagen, Tabelle mit OID %u nicht gefunden" -#: pg_dump.c:5535 +#: pg_dump.c:5772 #, c-format msgid "could not find parent extension for %s %s" msgstr "konnte Erweiterung, zu der %s %s gehört, nicht finden" -#: pg_dump.c:5680 +#: pg_dump.c:5910 #, c-format msgid "schema with OID %u does not exist" msgstr "Schema mit OID %u existiert nicht" -#: pg_dump.c:7162 pg_dump.c:17508 +#: pg_dump.c:6934 +#, fuzzy, c-format +#| msgid "cannot define statistics for relation \"%s\"" +msgid "cannot dump statistics for relation kind '%c'" +msgstr "für Relation »%s« können keine Statistiken definiert werden" + +#: pg_dump.c:7446 pg_dump.c:18416 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "Sanity-Check fehlgeschlagen, Elterntabelle mit OID %u von Sequenz mit OID %u nicht gefunden" -#: pg_dump.c:7305 +#: pg_dump.c:7591 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "Sanity-Check fehlgeschlagen, Tabellen-OID %u, die in pg_partitioned_table erscheint, nicht gefunden" -#: pg_dump.c:7536 pg_dump.c:7810 pg_dump.c:8257 pg_dump.c:8871 pg_dump.c:8993 -#: pg_dump.c:9141 +#: pg_dump.c:7856 pg_dump.c:8149 pg_dump.c:8590 pg_dump.c:9217 pg_dump.c:9344 +#: pg_dump.c:9492 #, c-format msgid "unrecognized table OID %u" msgstr "unbekannte Tabellen-OID %u" -#: pg_dump.c:7540 +#: pg_dump.c:7860 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "unerwartete Indexdaten für Tabelle »%s«" -#: pg_dump.c:8042 +#: pg_dump.c:8377 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "Sanity-Check fehlgeschlagen, Elterntabelle mit OID %u von pg_rewrite-Eintrag mit OID %u nicht gefunden" -#: pg_dump.c:8875 +#: pg_dump.c:9221 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "unerwartete Spaltendaten für Tabelle »%s«" -#: pg_dump.c:8904 +#: pg_dump.c:9251 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "ungültige Spaltennummerierung in Tabelle »%s«" -#: pg_dump.c:8955 +#: pg_dump.c:9306 #, c-format msgid "finding table default expressions" msgstr "finde Tabellenvorgabeausdrücke" -#: pg_dump.c:8997 +#: pg_dump.c:9348 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "ungültiger adnum-Wert %d für Tabelle »%s«" -#: pg_dump.c:9091 +#: pg_dump.c:9442 #, c-format msgid "finding table check constraints" msgstr "finde Tabellen-Check-Constraints" -#: pg_dump.c:9145 +#: pg_dump.c:9496 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "%d Check-Constraint für Tabelle %s erwartet, aber %d gefunden" msgstr[1] "%d Check-Constraints für Tabelle %s erwartet, aber %d gefunden" -#: pg_dump.c:9149 +#: pg_dump.c:9500 #, c-format msgid "The system catalogs might be corrupted." msgstr "Die Systemkataloge sind wahrscheinlich verfälscht." -#: pg_dump.c:9839 +#: pg_dump.c:10253 #, c-format msgid "role with OID %u does not exist" msgstr "Rolle mit OID %u existiert nicht" -#: pg_dump.c:9951 pg_dump.c:9980 +#: pg_dump.c:10365 pg_dump.c:10394 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "nicht unterstützter pg_init_privs-Eintrag: %u %u %d" -#: pg_dump.c:10527 +#: pg_dump.c:10685 +#, fuzzy, c-format +#| msgid "timestamp cannot be NaN" +msgid "attname cannot be NULL" +msgstr "timestamp kann nicht NaN sein" + +#: pg_dump.c:10714 +#, fuzzy, c-format +#| msgid "could not find an aggregate named \"%s\"" +msgid "could not find index attname \"%s\"" +msgstr "konnte keine Aggregatfunktion namens »%s« finden" + +#: pg_dump.c:11184 #, c-format msgid "missing metadata for large objects \"%s\"" msgstr "fehlende Metadaten für Large Objects »%s«" -#: pg_dump.c:10810 +#: pg_dump.c:11470 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "typtype des Datentypen »%s« scheint ungültig zu sein" -#: pg_dump.c:12384 +#: pg_dump.c:13046 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "ungültiger provolatile-Wert für Funktion »%s«" -#: pg_dump.c:12434 pg_dump.c:14330 +#: pg_dump.c:13096 pg_dump.c:14992 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "ungültiger proparallel-Wert für Funktion »%s«" -#: pg_dump.c:12564 pg_dump.c:12670 pg_dump.c:12677 +#: pg_dump.c:13226 pg_dump.c:13332 pg_dump.c:13339 #, c-format msgid "could not find function definition for function with OID %u" msgstr "konnte Funktionsdefinition für Funktion mit OID %u nicht finden" -#: pg_dump.c:12603 +#: pg_dump.c:13265 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "unsinniger Wert in Feld pg_cast.castfunc oder pg_cast.castmethod" -#: pg_dump.c:12606 +#: pg_dump.c:13268 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "unsinniger Wert in Feld pg_cast.castmethod" -#: pg_dump.c:12696 +#: pg_dump.c:13358 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "unsinnige Transformationsdefinition, mindestens eins von trffromsql und trftosql sollte nicht null sein" -#: pg_dump.c:12713 +#: pg_dump.c:13375 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "unsinniger Wert in Feld pg_transform.trffromsql" -#: pg_dump.c:12734 +#: pg_dump.c:13396 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "unsinniger Wert in Feld pg_transform.trftosql" -#: pg_dump.c:12879 +#: pg_dump.c:13541 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "Postfix-Operatoren werden nicht mehr unterstützt (Operator »%s«)" -#: pg_dump.c:13049 +#: pg_dump.c:13711 #, c-format msgid "could not find operator with OID %s" msgstr "konnte Operator mit OID %s nicht finden" -#: pg_dump.c:13117 +#: pg_dump.c:13779 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "ungültiger Typ »%c« für Zugriffsmethode »%s«" -#: pg_dump.c:13791 pg_dump.c:13859 +#: pg_dump.c:14453 pg_dump.c:14521 #, c-format msgid "unrecognized collation provider: %s" msgstr "unbekannter Sortierfolgen-Provider: %s" -#: pg_dump.c:13800 pg_dump.c:13807 pg_dump.c:13818 pg_dump.c:13828 -#: pg_dump.c:13843 +#: pg_dump.c:14462 pg_dump.c:14469 pg_dump.c:14480 pg_dump.c:14490 +#: pg_dump.c:14505 #, c-format msgid "invalid collation \"%s\"" msgstr "ungültige Sortierfolge »%s«" -#: pg_dump.c:14249 +#: pg_dump.c:14911 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "unbekannter aggfinalmodify-Wert für Aggregat »%s«" -#: pg_dump.c:14305 +#: pg_dump.c:14967 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "unbekannter aggmfinalmodify-Wert für Aggregat »%s«" -#: pg_dump.c:15022 +#: pg_dump.c:15687 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "unbekannter Objekttyp in den Vorgabeprivilegien: %d" -#: pg_dump.c:15038 +#: pg_dump.c:15703 #, c-format msgid "could not parse default ACL list (%s)" msgstr "konnte Vorgabe-ACL-Liste (%s) nicht interpretieren" -#: pg_dump.c:15122 +#: pg_dump.c:15787 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "konnte initiale ACL-Liste (%s) oder Default (%s) für Objekt »%s« (%s) nicht interpretieren" -#: pg_dump.c:15147 +#: pg_dump.c:15812 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "konnte ACL-Liste (%s) oder Default (%s) für Objekt »%s« (%s) nicht interpretieren" -#: pg_dump.c:15690 +#: pg_dump.c:16355 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "Anfrage um die Definition der Sicht »%s« zu ermitteln lieferte keine Daten" -#: pg_dump.c:15693 +#: pg_dump.c:16358 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "Anfrage um die Definition der Sicht »%s« zu ermitteln lieferte mehr als eine Definition" -#: pg_dump.c:15700 +#: pg_dump.c:16365 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "Definition der Sicht »%s« scheint leer zu sein (Länge null)" -#: pg_dump.c:15784 +#: pg_dump.c:16450 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS wird nicht mehr unterstützt (Tabelle »%s«)" -#: pg_dump.c:16710 +#: pg_dump.c:17540 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "ungültige Spaltennummer %d in Tabelle »%s«" -#: pg_dump.c:16788 +#: pg_dump.c:17618 #, c-format msgid "could not parse index statistic columns" msgstr "konnte Indexstatistikspalten nicht interpretieren" -#: pg_dump.c:16790 +#: pg_dump.c:17620 #, c-format msgid "could not parse index statistic values" msgstr "konnte Indexstatistikwerte nicht interpretieren" -#: pg_dump.c:16792 +#: pg_dump.c:17622 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "Anzahl Spalten und Werte für Indexstatistiken stimmt nicht überein" -#: pg_dump.c:17007 +#: pg_dump.c:17837 #, c-format msgid "missing index for constraint \"%s\"" msgstr "fehlender Index für Constraint »%s«" -#: pg_dump.c:17242 +#: pg_dump.c:18074 #, c-format msgid "unrecognized constraint type: %c" msgstr "unbekannter Constraint-Typ: %c" -#: pg_dump.c:17343 pg_dump.c:17572 +#: pg_dump.c:18127 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "unbekannter Sequenztyp: %s" + +#: pg_dump.c:18259 pg_dump.c:18491 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "Anfrage nach Daten der Sequenz %s ergab %d Zeile (erwartete 1)" msgstr[1] "Anfrage nach Daten der Sequenz %s ergab %d Zeilen (erwartete 1)" -#: pg_dump.c:17375 +#: pg_dump.c:18295 #, c-format -msgid "unrecognized sequence type: %s" -msgstr "unbekannter Sequenztyp: %s" +msgid "unrecognized sequence type: %d" +msgstr "unbekannter Sequenztyp: %d" -#: pg_dump.c:17889 +#: pg_dump.c:18824 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "Anfrage nach Regel »%s« der Tabelle »%s« fehlgeschlagen: falsche Anzahl Zeilen zurückgegeben" -#: pg_dump.c:18042 +#: pg_dump.c:18977 #, c-format msgid "could not find referenced extension %u" msgstr "konnte referenzierte Erweiterung %u nicht finden" -#: pg_dump.c:18141 +#: pg_dump.c:19076 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "Anzahl Konfigurationen und Bedingungen für Erweiterung stimmt nicht überein" -#: pg_dump.c:18273 +#: pg_dump.c:19208 #, c-format msgid "reading dependency data" msgstr "lese Abhängigkeitsdaten" -#: pg_dump.c:18359 +#: pg_dump.c:19294 #, c-format msgid "no referencing object %u %u" msgstr "kein referenzierendes Objekt %u %u" -#: pg_dump.c:18370 +#: pg_dump.c:19305 #, c-format msgid "no referenced object %u %u" msgstr "kein referenziertes Objekt %u %u" -#: pg_dump.c:18795 pg_dump.c:18833 pg_dumpall.c:1962 pg_restore.c:551 -#: pg_restore.c:597 +#: pg_dump.c:19740 pg_dump.c:19778 pg_dumpall.c:2051 pg_restore.c:610 +#: pg_restore.c:656 #, c-format msgid "%s filter for \"%s\" is not allowed" msgstr "%s-Filter für »%s« ist nicht erlaubt" -#: pg_dump_sort.c:424 +#: pg_dump_sort.c:436 #, c-format msgid "invalid dumpId %d" msgstr "ungültige dumpId %d" -#: pg_dump_sort.c:430 +#: pg_dump_sort.c:442 #, c-format msgid "invalid dependency %d" msgstr "ungültige Abhängigkeit %d" -#: pg_dump_sort.c:594 +#: pg_dump_sort.c:606 #, c-format msgid "could not identify dependency loop" msgstr "konnte Abhängigkeitsschleife nicht bestimmen" -#: pg_dump_sort.c:1209 +#: pg_dump_sort.c:1247 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "Es gibt zirkuläre Fremdschlüssel-Constraints für diese Tabelle:" msgstr[1] "Es gibt zirkuläre Fremdschlüssel-Constraints zwischen diesen Tabellen:" -#: pg_dump_sort.c:1214 +#: pg_dump_sort.c:1252 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "Möglicherweise kann der Dump nur wiederhergestellt werden, wenn --disable-triggers verwendet wird oder die Constraints vorübergehend entfernt werden." -#: pg_dump_sort.c:1215 +#: pg_dump_sort.c:1253 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "Führen Sie einen vollen Dump statt eines Dumps mit --data-only durch, um dieses Problem zu vermeiden." -#: pg_dump_sort.c:1227 +#: pg_dump_sort.c:1265 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "konnte Abhängigkeitsschleife zwischen diesen Elementen nicht auflösen:" -#: pg_dumpall.c:231 +#: pg_dumpall.c:247 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden" -#: pg_dumpall.c:234 +#: pg_dumpall.c:250 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s" -#: pg_dumpall.c:387 +#: pg_dumpall.c:403 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "Option --exclude-database kann nicht zusammen mit -g/--globals-only, -r/--roles-only oder -t/--tablesspaces-only verwendet werden" -#: pg_dumpall.c:395 +#: pg_dumpall.c:411 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "Optionen -g/--globals-only und -r/--roles-only können nicht zusammen verwendet werden" -#: pg_dumpall.c:402 +#: pg_dumpall.c:418 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "Optionen -g/--globals-only und -t/--tablespaces-only können nicht zusammen verwendet werden" -#: pg_dumpall.c:412 +#: pg_dumpall.c:428 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "Optionen -r/--roles-only und -t/--tablespaces-only können nicht zusammen verwendet werden" -#: pg_dumpall.c:474 pg_dumpall.c:1771 +#: pg_dumpall.c:506 pg_dumpall.c:1860 #, c-format msgid "could not connect to database \"%s\"" msgstr "konnte nicht mit der Datenbank »%s« verbinden" -#: pg_dumpall.c:486 +#: pg_dumpall.c:518 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2548,7 +2656,7 @@ msgstr "" "konnte nicht mit Datenbank »postgres« oder »template1« verbinden\n" "Bitte geben Sie eine alternative Datenbank an." -#: pg_dumpall.c:634 +#: pg_dumpall.c:667 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2557,80 +2665,82 @@ msgstr "" "%s gibt einen PostgreSQL-Datenbankcluster in eine SQL-Skriptdatei aus.\n" "\n" -#: pg_dumpall.c:636 +#: pg_dumpall.c:669 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPTION]...\n" -#: pg_dumpall.c:639 +#: pg_dumpall.c:672 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=DATEINAME Name der Ausgabedatei\n" -#: pg_dumpall.c:646 +#: pg_dumpall.c:679 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean Datenbanken vor der Wiedererstellung löschen\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:681 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr " -g, --globals-only nur globale Objekte ausgeben, keine Datenbanken\n" -#: pg_dumpall.c:649 pg_restore.c:475 +#: pg_dumpall.c:682 pg_restore.c:526 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr "" " -O, --no-owner Wiederherstellung der Objekteigentümerschaft\n" " auslassen\n" -#: pg_dumpall.c:650 +#: pg_dumpall.c:683 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr "" " -r, --roles-only nur Rollen ausgeben, keine Datenbanken oder\n" " Tablespaces\n" -#: pg_dumpall.c:652 +#: pg_dumpall.c:685 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr " -S, --superuser=NAME Superusername für den Dump\n" -#: pg_dumpall.c:653 +#: pg_dumpall.c:686 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr "" " -t, --tablespaces-only nur Tablespaces ausgeben, keine Datenbanken oder\n" " Rollen\n" -#: pg_dumpall.c:659 +#: pg_dumpall.c:692 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr "" " --exclude-database=MUSTER Datenbanken deren Name mit MUSTER übereinstimmt\n" " überspringen\n" -#: pg_dumpall.c:661 +#: pg_dumpall.c:694 #, c-format -msgid " --filter=FILENAME exclude databases specified in FILENAME\n" -msgstr " --filter=DATEINAME in DATEINAME angegebene Datenbanken überspringen\n" +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr "" +" --filter=DATEINAME Datenbanken basierend auf Ausdrücken in DATEINAME\n" +" überspringen\n" -#: pg_dumpall.c:667 +#: pg_dumpall.c:702 #, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords Rollenpasswörter nicht mit ausgeben\n" -#: pg_dumpall.c:683 +#: pg_dumpall.c:724 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=VERBDG mit angegebenen Verbindungsparametern verbinden\n" -#: pg_dumpall.c:685 +#: pg_dumpall.c:726 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=DBNAME alternative Standarddatenbank\n" -#: pg_dumpall.c:692 +#: pg_dumpall.c:733 #, c-format msgid "" "\n" @@ -2643,106 +2753,117 @@ msgstr "" "Standardausgabe geschrieben.\n" "\n" -#: pg_dumpall.c:837 +#: pg_dumpall.c:878 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "mit »pg_« anfangender Rollenname übersprungen (%s)" -#: pg_dumpall.c:1059 +#. translator: %s represents a numeric role OID +#: pg_dumpall.c:1095 pg_dumpall.c:1153 pg_dumpall.c:1162 +#, c-format +msgid "found orphaned pg_auth_members entry for role %s" +msgstr "verwaister pg_auth_members-Eintrag für Rolle %s gefunden" + +#: pg_dumpall.c:1128 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "konnte keine legale Dump-Reihenfolge für Mitgliedschaften in Rolle »%s« finden" -#: pg_dumpall.c:1194 +#: pg_dumpall.c:1283 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "konnte ACL-Zeichenkette (%s) für Parameter »%s« nicht interpretieren" -#: pg_dumpall.c:1321 +#: pg_dumpall.c:1410 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "konnte ACL-Zeichenkette (%s) für Tablespace »%s« nicht interpretieren" -#: pg_dumpall.c:1528 +#: pg_dumpall.c:1617 #, c-format msgid "excluding database \"%s\"" msgstr "Datenbank »%s« übersprungen" -#: pg_dumpall.c:1532 +#: pg_dumpall.c:1621 #, c-format msgid "dumping database \"%s\"" msgstr "Ausgabe der Datenbank »%s«" -#: pg_dumpall.c:1563 +#: pg_dumpall.c:1652 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "pg_dump für Datenbank »%s« fehlgeschlagen; beende" -#: pg_dumpall.c:1569 +#: pg_dumpall.c:1658 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "konnte die Ausgabedatei »%s« nicht neu öffnen: %m" -#: pg_dumpall.c:1613 +#: pg_dumpall.c:1702 #, c-format msgid "running \"%s\"" msgstr "führe »%s« aus" -#: pg_dumpall.c:1814 +#: pg_dumpall.c:1903 #, c-format msgid "could not get server version" msgstr "konnte Version des Servers nicht ermitteln" -#: pg_dumpall.c:1817 +#: pg_dumpall.c:1906 #, c-format msgid "could not parse server version \"%s\"" msgstr "konnte Versionszeichenkette »%s« nicht entziffern" -#: pg_dumpall.c:1887 pg_dumpall.c:1910 +#: pg_dumpall.c:1976 pg_dumpall.c:1999 #, c-format msgid "executing %s" msgstr "führe %s aus" -#: pg_dumpall.c:1982 +#: pg_dumpall.c:2071 msgid "unsupported filter object" msgstr "nicht unterstütztes Filterobjekt" -#: pg_restore.c:329 +#: pg_restore.c:346 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "entweder -d/--dbname oder -f/--file muss angegeben werden" -#: pg_restore.c:336 +#: pg_restore.c:353 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "Optionen -d/--dbname und -f/--file können nicht zusammen verwendet werden" -#: pg_restore.c:350 +#: pg_restore.c:388 #, c-format msgid "options -1/--single-transaction and --transaction-size cannot be used together" msgstr "Optionen -1/--single-transaction und --transaction-size können nicht zusammen verwendet werden" -#: pg_restore.c:357 +#: pg_restore.c:395 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "Optionen -C/--create und -1/--single-transaction können nicht zusammen verwendet werden" -#: pg_restore.c:361 +#: pg_restore.c:399 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "--single-transaction und mehrere Jobs können nicht zusammen verwendet werden" -#: pg_restore.c:399 +#: pg_restore.c:447 +#, c-format +msgid "archive format \"%s\" is not supported; please use psql" +msgstr "Archivformat »%s« wird nicht unterstützt; bitte psql verwenden" + +#: pg_restore.c:451 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "unbekanntes Archivformat »%s«; bitte »c«, »d« oder »t« angeben" -#: pg_restore.c:438 +#: pg_restore.c:489 #, c-format msgid "errors ignored on restore: %d" msgstr "bei Wiederherstellung ignorierte Fehler: %d" -#: pg_restore.c:451 +#: pg_restore.c:502 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2752,47 +2873,47 @@ msgstr "" "gesichert wurde.\n" "\n" -#: pg_restore.c:453 +#: pg_restore.c:504 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [OPTION]... [DATEI]\n" -#: pg_restore.c:456 +#: pg_restore.c:507 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NAME mit angegebener Datenbank verbinden\n" -#: pg_restore.c:457 +#: pg_restore.c:508 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=DATEINAME Name der Ausgabedatei (- für stdout)\n" -#: pg_restore.c:458 +#: pg_restore.c:509 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t Format der Backup-Datei (sollte automatisch gehen)\n" -#: pg_restore.c:459 +#: pg_restore.c:510 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list Inhaltsverzeichnis für dieses Archiv anzeigen\n" -#: pg_restore.c:460 +#: pg_restore.c:511 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose »Verbose«-Modus\n" -#: pg_restore.c:461 +#: pg_restore.c:512 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_restore.c:462 +#: pg_restore.c:513 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_restore.c:464 +#: pg_restore.c:515 #, c-format msgid "" "\n" @@ -2801,34 +2922,34 @@ msgstr "" "\n" "Optionen die die Wiederherstellung kontrollieren:\n" -#: pg_restore.c:465 +#: pg_restore.c:516 #, c-format msgid " -a, --data-only restore only the data, no schema\n" -msgstr " -a, --data-only nur Daten, nicht das Schema, wiederherstellen\n" +msgstr " -a, --data-only nur die Daten wiederherstellen, nicht das Schema\n" -#: pg_restore.c:467 +#: pg_restore.c:518 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create Zieldatenbank erzeugen\n" -#: pg_restore.c:468 +#: pg_restore.c:519 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error bei Fehler beenden, Voreinstellung ist fortsetzen\n" -#: pg_restore.c:469 +#: pg_restore.c:520 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAME benannten Index wiederherstellen\n" -#: pg_restore.c:470 +#: pg_restore.c:521 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr "" " -j, --jobs=NUM so viele parallele Jobs zur Wiederherstellung\n" " verwenden\n" -#: pg_restore.c:471 +#: pg_restore.c:522 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2837,59 +2958,59 @@ msgstr "" " -L, --use-list=DATEINAME Inhaltsverzeichnis aus dieser Datei zur Auswahl oder\n" " Sortierung der Ausgabe verwenden\n" -#: pg_restore.c:473 +#: pg_restore.c:524 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME nur Objekte in diesem Schema wiederherstellen\n" -#: pg_restore.c:474 +#: pg_restore.c:525 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, ---exclude-schema=NAME Objekte in diesem Schema nicht wiederherstellen\n" -#: pg_restore.c:476 +#: pg_restore.c:527 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NAME(args) benannte Funktion wiederherstellen\n" -#: pg_restore.c:477 +#: pg_restore.c:528 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" -msgstr " -s, --schema-only nur das Schema, nicht die Daten, wiederherstellen\n" +msgstr " -s, --schema-only nur das Schema wiederherstellen, nicht die Daten\n" -#: pg_restore.c:478 +#: pg_restore.c:529 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr " -S, --superuser=NAME Name des Superusers, um Trigger auszuschalten\n" -#: pg_restore.c:479 +#: pg_restore.c:530 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr "" " -t, --table=NAME benannte Relation (Tabelle, Sicht, usw.)\n" " wiederherstellen\n" -#: pg_restore.c:480 +#: pg_restore.c:531 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAME benannten Trigger wiederherstellen\n" -#: pg_restore.c:481 +#: pg_restore.c:532 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges Wiederherstellung der Zugriffsprivilegien auslassen\n" -#: pg_restore.c:482 +#: pg_restore.c:533 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction Wiederherstellung als eine einzige Transaktion\n" -#: pg_restore.c:484 +#: pg_restore.c:535 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security Sicherheit auf Zeilenebene einschalten\n" -#: pg_restore.c:485 +#: pg_restore.c:536 #, c-format msgid "" " --filter=FILENAME restore or skip objects based on expressions\n" @@ -2898,12 +3019,17 @@ msgstr "" " --filter=DATEINAME Objekte basierend auf Ausdrücken in DATEINAME\n" " wiederherstellen oder überspringen\n" -#: pg_restore.c:488 +#: pg_restore.c:539 #, c-format -msgid " --no-comments do not restore comments\n" -msgstr " --no-comments Kommentare nicht wiederherstellen\n" +msgid " --no-comments do not restore comment commands\n" +msgstr " --no-comments Kommentar-Befehle nicht wiederherstellen\n" -#: pg_restore.c:489 +#: pg_restore.c:540 +#, c-format +msgid " --no-data do not restore data\n" +msgstr " --no-data Daten nicht wiederherstellen\n" + +#: pg_restore.c:541 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" @@ -2912,49 +3038,71 @@ msgstr "" " --no-data-for-failed-tables Daten für Tabellen, die nicht erzeugt werden\n" " konnten, nicht wiederherstellen\n" -#: pg_restore.c:491 +#: pg_restore.c:543 +#, c-format +msgid " --no-policies do not restore row security policies\n" +msgstr "" +" --no-policies Policys für Sicherheit auf Zeilenebene nicht\n" +" wiederherstellen\n" + +#: pg_restore.c:544 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications Publikationen nicht wiederherstellen\n" -#: pg_restore.c:492 +#: pg_restore.c:545 +#, c-format +msgid " --no-schema do not restore schema\n" +msgstr " --no-schema Schema nicht wiederherstellen\n" + +#: pg_restore.c:546 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels Security-Labels nicht wiederherstellen\n" -#: pg_restore.c:493 +#: pg_restore.c:547 +#, c-format +msgid " --no-statistics do not restore statistics\n" +msgstr " --no-statistics Statistiken nicht wiederherstellen\n" + +#: pg_restore.c:548 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions Subskriptionen nicht wiederherstellen\n" -#: pg_restore.c:494 +#: pg_restore.c:549 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method Tabellenzugriffsmethoden nicht wiederherstellen\n" -#: pg_restore.c:495 +#: pg_restore.c:550 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces Tablespace-Zuordnungen nicht wiederherstellen\n" -#: pg_restore.c:496 +#: pg_restore.c:551 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr "" " --section=ABSCHNITT angegebenen Abschnitt wiederherstellen (pre-data,\n" " data oder post-data)\n" -#: pg_restore.c:499 +#: pg_restore.c:552 +#, c-format +msgid " --statistics-only restore only the statistics, not schema or data\n" +msgstr " --statistics-only nur die Statistiken wiederherstellen, nicht Schema oder Daten\n" + +#: pg_restore.c:555 #, c-format msgid " --transaction-size=N commit after every N objects\n" msgstr " --transaction-size=N jeweils nach N Objekten committen\n" -#: pg_restore.c:510 +#: pg_restore.c:569 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLLENNAME vor der Wiederherstellung SET ROLE ausführen\n" -#: pg_restore.c:512 +#: pg_restore.c:571 #, c-format msgid "" "\n" @@ -2965,7 +3113,7 @@ msgstr "" "Die Optionen -I, -n, -N, -P, -t, -T und --section können kombiniert und mehrfach\n" "angegeben werden, um mehrere Objekte auszuwählen.\n" -#: pg_restore.c:515 +#: pg_restore.c:574 #, c-format msgid "" "\n" diff --git a/src/bin/pg_dump/po/es.po b/src/bin/pg_dump/po/es.po index ac8e807dbd441..b40afd89881bb 100644 --- a/src/bin/pg_dump/po/es.po +++ b/src/bin/pg_dump/po/es.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_dump (PostgreSQL) 16\n" +"Project-Id-Version: pg_dump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-03 07:20+0000\n" -"PO-Revision-Date: 2023-10-03 16:15+0200\n" +"POT-Creation-Date: 2025-02-16 19:51+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -94,32 +94,47 @@ msgstr "el algoritmo de compresión «%s» no acepta una cantidad de procesos ay msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "el algoritmo de compresión «%s» no acepta modo de larga distancia" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "memoria agotada" @@ -134,6 +149,49 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -174,227 +232,247 @@ msgstr "el valor «%s» no es válido para la opción %s" msgid "%s must be in range %d..%d" msgstr "%s debe estar en el rango %d..%d" -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "leyendo las extensiones" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "identificando miembros de extensión" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "leyendo esquemas" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "leyendo las tablas definidas por el usuario" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "leyendo las funciones definidas por el usuario" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "leyendo los tipos definidos por el usuario" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "leyendo los lenguajes procedurales" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "leyendo las funciones de agregación definidas por el usuario" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "leyendo los operadores definidos por el usuario" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "leyendo los métodos de acceso definidos por el usuario" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "leyendo las clases de operadores definidos por el usuario" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "leyendo las familias de operadores definidas por el usuario" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "leyendo los procesadores (parsers) de búsqueda en texto definidos por el usuario" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "leyendo las plantillas de búsqueda en texto definidas por el usuario" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "leyendo los diccionarios de búsqueda en texto definidos por el usuario" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "leyendo las configuraciones de búsqueda en texto definidas por el usuario" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "leyendo los conectores de datos externos definidos por el usuario" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "leyendo los servidores foráneos definidas por el usuario" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "leyendo los privilegios por omisión" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "leyendo los ordenamientos definidos por el usuario" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "leyendo las conversiones definidas por el usuario" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "leyendo conversiones de tipo" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "leyendo las transformaciones" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "leyendo la información de herencia de las tablas" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "leyendo los disparadores por eventos" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "buscando tablas de extensión" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "buscando relaciones de herencia" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "leyendo la información de columnas para las tablas interesantes" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "marcando las columnas heredadas en las subtablas" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "leyendo datos de particionamiento" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "leyendo los índices" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "marcando índices en las tablas particionadas" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "leyendo estadísticas extendidas" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "leyendo las restricciones" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "leyendo los disparadores (triggers)" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "leyendo las reglas de reescritura" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "leyendo políticas" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "leyendo publicaciones" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "leyendo membresía de tablas en publicaciones" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "leyendo membresía de esquemas en publicaciones" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "leyendo las suscripciones" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "leyendo membresía de tablas en suscripciones" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "falló la revisión de integridad, el OID %u del padre de la tabla «%s» (OID %u) no se encontró" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "número de padres %d para la tabla «%s» no es válido" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "no se pudo interpretar el arreglo numérico «%s»: demasiados números" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "no se pudo interpretar el arreglo numérico «%s»: carácter no válido en número" @@ -424,15 +502,20 @@ msgstr "no se pudo descomprimir datos: %s" msgid "could not close compression library: %s" msgstr "no se pudo cerrar la biblioteca de compresión: %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "no se pudo leer el archivo de entrada: %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:374 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "no se pudo leer el archivo de entrada: %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:372 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "no se pudo leer desde el archivo de entrada: fin de archivo" @@ -472,27 +555,72 @@ msgstr "no se pudo terminar la descompresión: %s" msgid "could not set compression parameter \"%s\": %s" msgstr "no se pudo definir el parámetro de compresión «%s»: %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:232 compress_zstd.c:491 +#: compress_zstd.c:499 #, c-format msgid "could not initialize compression library" msgstr "no se pudo inicializar la biblioteca de compresión" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:195 compress_zstd.c:309 #, c-format msgid "could not decompress data: %s" msgstr "no se pudo descomprimir datos: %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "no se pudo leer el archivo de entrada: %m" - -#: compress_zstd.c:501 +#: compress_zstd.c:502 #, c-format msgid "unhandled mode \"%s\"" msgstr "modo «%s» sin manejar" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "no se pudo abrir el archivo de filtro «%s»: %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "no se pudo cerrar el archivo de filtro «%s»: %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "formato inválido en filtro leído desde entrada estándar en línea %d: %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "sintaxis no válida en filtro leído desde archivo «%s», línea %d: %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "no se pudo leer el archivo de filtro «%s»: %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "fin de archivo inesperado" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "falta el parámetro de nombre de objeto" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "no se encontró orden de filtro (se esperaba «include» o «include»)" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "orden de filtro no válida (se esperaba «include» o «exclude»)" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "falta el parámetro de tipo de objeto" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "tipo de objeto de filtro «%.*s» no soportado" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -572,512 +700,517 @@ msgstr "pgpipe: no se pudo conectar el socket: código de error %d" msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: no se pudo aceptar la conexión: código de error %d" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "no se pudo cerrar el archivo de salida: %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "elementos del archivo no están en el orden correcto de secciones" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "código de sección %d inesperado" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "la restauración en paralelo no está soportada con este formato de archivo" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "la restauración en paralelo no está soportada con archivos construidos con pg_dump anterior a 8.0" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" -msgstr "no se pudo restaurar desde archivo comprimido (%s)" +msgstr "no se puede restaurar del archivo comprimido (%s)" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "conectando a la base de datos para reestablecimiento" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "las conexiones directas a la base de datos no están soportadas en archivadores pre-1.3" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "asumiendo reestablecimiento de sólo datos" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "eliminando %s %s" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "no se pudo encontrar dónde insertar IF EXISTS en la sentencia «%s»" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "precaución desde el archivo original: %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "creando %s «%s.%s»" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "creando %s «%s»" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "conectando a nueva base de datos «%s»" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "procesando %s" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "procesando datos de la tabla «%s.%s»" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "ejecutando %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "deshabilitando disparadores (triggers) para %s" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "habilitando disparadores (triggers) para %s" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "error interno -- WriteData no puede ser llamada fuera del contexto de una rutina DataDumper" -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "la extracción de objetos grandes no está soportada en el formato seleccionado" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "se reestableció %d objeto grande" msgstr[1] "se reestablecieron %d objetos grandes" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "reestableciendo objeto grande con OID %u" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "no se pudo crear el objeto grande %u: %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3718 +#: pg_backup_archiver.c:1486 pg_dump.c:3889 #, c-format msgid "could not open large object %u: %s" msgstr "no se pudo abrir el objeto grande %u: %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "no se pudo abrir el archivo TOC «%s»: %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "línea ignorada: %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "no se pudo encontrar una entrada para el ID %d" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "no se pudo cerrar el archivo TOC: %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "no se pudo abrir el archivo de salida «%s»: %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "no se pudo abrir el archivo de salida: %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "se escribió %zu byte de los datos del objeto grande (resultado = %d)" msgstr[1] "se escribieron %zu bytes de los datos del objeto grande (resultado = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "no se pudo escribir en objeto grande: %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "durante INICIALIZACIÓN:" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "durante PROCESAMIENTO DE TABLA DE CONTENIDOS:" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "durante FINALIZACIÓN:" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "en entrada de la tabla de contenidos %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "dumpId incorrecto" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "dumpId de tabla incorrecto para elemento TABLE DATA" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "bandera de posición inesperada %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "el posición en el archivo es demasiado grande" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "nombre de directorio demasiado largo: «%s»" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "el directorio «%s» no parece ser un archivador válido (no existe «toc.dat»)" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "no se pudo abrir el archivo de entrada «%s»: %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "no se pudo abrir el archivo de entrada: %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "no se pudo leer el archivo de entrada: %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "el archivo de entrada es demasiado corto (leidos %lu, esperados 5)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "el archivo de entrada parece ser un volcado de texto. Por favor use psql." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "el archivo de entrada no parece ser un archivador válido (¿demasiado corto?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "el archivo de entrada no parece ser un archivador válido" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "no se pudo cerrar el archivo de entrada: %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "no se pudo abrir stdout para agregar datos: %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "formato de archivo no reconocido «%d»" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4466 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4648 #, c-format msgid "finished item %d %s %s" msgstr "terminó el elemento %d %s %s" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4479 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4661 #, c-format msgid "worker process failed: exit code %d" msgstr "el proceso hijo falló: código de salida %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "la entrada con ID %d está fuera de rango -- tal vez la tabla de contenido está corrupta" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "restaurar tablas WITH OIDS ya no está soportado" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "no se reconoce la codificación: «%s»" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2824 #, c-format msgid "invalid ENCODING item: %s" msgstr "elemento ENCODING no válido: %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2842 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "elemento STDSTRINGS no válido: %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2867 #, c-format msgid "schema \"%s\" not found" msgstr "esquema «%s» no encontrado" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2874 #, c-format msgid "table \"%s\" not found" msgstr "tabla «%s» no encontrada" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2881 #, c-format msgid "index \"%s\" not found" msgstr "índice «%s» no encontrado" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2888 #, c-format msgid "function \"%s\" not found" msgstr "función «%s» no encontrada" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2895 #, c-format msgid "trigger \"%s\" not found" msgstr "disparador «%s» no encontrado" -#: pg_backup_archiver.c:3201 +#: pg_backup_archiver.c:3326 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "no se pudo establecer el usuario de sesión a «%s»: %s" -#: pg_backup_archiver.c:3333 +#: pg_backup_archiver.c:3458 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "no se pudo definir search_path a «%s»: %s" +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "no se pudo definir «search_path» a «%s»: %s" -#: pg_backup_archiver.c:3394 +#: pg_backup_archiver.c:3519 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "no se pudo definir default_tablespace a %s: %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "no se pudo definir «default_tablespace» a %s: %s" -#: pg_backup_archiver.c:3443 +#: pg_backup_archiver.c:3568 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "no se pudo definir default_table_access_method: %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "no se pudo definir «default_table_access_method»: %s" -#: pg_backup_archiver.c:3548 +#: pg_backup_archiver.c:3617 +#, c-format +msgid "could not alter table access method: %s" +msgstr "no se pudo alterar el método de acceso a tabla: %s" + +#: pg_backup_archiver.c:3718 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "no se sabe cómo establecer el dueño para el objeto de tipo «%s»" -#: pg_backup_archiver.c:3770 +#: pg_backup_archiver.c:4005 #, c-format msgid "did not find magic string in file header" msgstr "no se encontró la cadena mágica en el encabezado del archivo" -#: pg_backup_archiver.c:3784 +#: pg_backup_archiver.c:4019 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "versión no soportada (%d.%d) en el encabezado del archivo" -#: pg_backup_archiver.c:3789 +#: pg_backup_archiver.c:4024 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "revisión de integridad en el tamaño del entero (%lu) falló" -#: pg_backup_archiver.c:3793 +#: pg_backup_archiver.c:4028 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "el archivador fue hecho en una máquina con enteros más grandes, algunas operaciones podrían fallar" -#: pg_backup_archiver.c:3803 +#: pg_backup_archiver.c:4038 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "el formato esperado (%d) difiere del formato encontrado en el archivo (%d)" -#: pg_backup_archiver.c:3825 +#: pg_backup_archiver.c:4060 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "el archivo está comprimido, pero esta instalación no soporta compresión (%s) -- los datos no estarán disponibles" -#: pg_backup_archiver.c:3861 +#: pg_backup_archiver.c:4096 #, c-format msgid "invalid creation date in header" msgstr "la fecha de creación en el encabezado no es válida" -#: pg_backup_archiver.c:3995 +#: pg_backup_archiver.c:4230 #, c-format msgid "processing item %d %s %s" msgstr "procesando el elemento %d %s %s" -#: pg_backup_archiver.c:4070 +#: pg_backup_archiver.c:4315 #, c-format msgid "entering main parallel loop" msgstr "ingresando al bucle paralelo principal" -#: pg_backup_archiver.c:4081 +#: pg_backup_archiver.c:4326 #, c-format msgid "skipping item %d %s %s" msgstr "saltando el elemento %d %s %s" -#: pg_backup_archiver.c:4090 +#: pg_backup_archiver.c:4335 #, c-format msgid "launching item %d %s %s" msgstr "lanzando el elemento %d %s %s" -#: pg_backup_archiver.c:4144 +#: pg_backup_archiver.c:4389 #, c-format msgid "finished main parallel loop" msgstr "terminó el bucle paralelo principal" -#: pg_backup_archiver.c:4180 +#: pg_backup_archiver.c:4425 #, c-format msgid "processing missed item %d %s %s" msgstr "procesando el elemento saltado %d %s %s" -#: pg_backup_archiver.c:4785 +#: pg_backup_archiver.c:4967 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "la tabla «%s» no pudo ser creada, no se recuperarán sus datos" -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "OID no válido para objeto grande" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "error durante el posicionamiento (seek) en el archivo: %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "el bloque de datos %d tiene una posición de búsqueda incorrecta" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "tipo de bloque de datos (%d) no conocido al buscar en el archivador" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "no se pudo encontrar el bloque con ID %d en archivo -- posiblemente debido a una petición de restauración fuera de orden, la que no puede ser completada debido a que en el archivo de entrada no es reposicionable (seekable)" -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "no se pudo encontrar el bloque con ID %d en archivo -- posiblemente el archivo está corrupto" -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "se encontró un bloque no esperado ID (%d) mientras se leían los datos -- se esperaba %d" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "se encontró un bloque tipo %d no reconocido al restablecer el archivador" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "no se pudo determinar la posición (seek) en el archivo del archivador: %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "no se pudo cerrar el archivo del archivador: %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "sólo se pueden reabrir archivos de entrada" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "la restauración en paralelo desde entrada estándar (stdin) no está soportada" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "la restauración en paralelo desde un archivo no posicionable no está soportada" -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "no se pudo posicionar (seek) en el archivo del archivador: %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "compresor activo" @@ -1087,12 +1220,12 @@ msgstr "compresor activo" msgid "could not get server_version from libpq" msgstr "no se pudo obtener server_version desde libpq" -#: pg_backup_db.c:53 pg_dumpall.c:1809 +#: pg_backup_db.c:53 pg_dumpall.c:1831 #, c-format msgid "aborting because of server version mismatch" msgstr "abortando debido a que no coincide la versión del servidor" -#: pg_backup_db.c:54 pg_dumpall.c:1810 +#: pg_backup_db.c:54 pg_dumpall.c:1832 #, c-format msgid "server version: %s; %s version: %s" msgstr "versión del servidor: %s; versión de %s: %s" @@ -1102,7 +1235,7 @@ msgstr "versión del servidor: %s; versión de %s: %s" msgid "already connected to a database" msgstr "ya está conectado a una base de datos" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1656 pg_dumpall.c:1758 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1678 pg_dumpall.c:1780 msgid "Password: " msgstr "Contraseña: " @@ -1116,18 +1249,18 @@ msgstr "no se pudo hacer la conexión a la base de datos" msgid "reconnection failed: %s" msgstr "falló la reconexión: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1683 pg_dumpall.c:1767 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1705 pg_dumpall.c:1789 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1872 pg_dumpall.c:1895 +#: pg_backup_db.c:271 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "query failed: %s" msgstr "la consulta falló: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1873 pg_dumpall.c:1896 +#: pg_backup_db.c:273 pg_dumpall.c:1895 pg_dumpall.c:1918 #, c-format msgid "Query was: %s" msgstr "La consulta era: %s" @@ -1163,7 +1296,7 @@ msgstr "PQputCopyEnd regresó un error: %s" msgid "COPY failed for table \"%s\": %s" msgstr "COPY falló para la tabla «%s»: %s" -#: pg_backup_db.c:521 pg_dump.c:2202 +#: pg_backup_db.c:521 pg_dump.c:2284 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "resultados extra inesperados durante el COPY de la tabla «%s»" @@ -1176,161 +1309,156 @@ msgstr "no se pudo iniciar la transacción en la base de datos" msgid "could not commit database transaction" msgstr "no se pudo terminar la transacción a la base de datos" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "no se especificó un directorio de salida" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "no se pudo leer el directorio «%s»: %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "no se pudo crear el directorio «%s»: %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "no se pudo escribir al archivo de salida: %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "no se pudo cerrar el archivo de datos: %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "no se pudo cerrar el archivo de datos «%s»: %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "no se pudo abrir el archivo de la tabla de contenidos de objetos grandes «%s» para su lectura: %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "línea no válida en el archivo de la tabla de contenido de objetos grandes «%s»: «%s»" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "error al leer el archivo de la tabla de contenidos de objetos grandes «%s»" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "no se pudo cerrar el archivo de la tabla de contenido de los objetos grandes «%s»: %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "no se pudo cerrar el archivo de datos LO: %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "no se pudo escribir archivo TOC de LOs: %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" -msgstr "no se pudo cerrar el archivo TOC de LOs: %m" +msgstr "no se pudo cerrar el archivo TOC: %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "nombre de archivo demasiado largo: «%s»" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "no se puede leer este formato" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "no se pudo abrir el archivo de tabla de contenido «%s» para escribir: %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "no se pudo abrir la tabla de contenido para escribir: %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "la compresión no está soportada por el formato de salida tar" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "no se pudo abrir el archivo de tabla de contenido «%s» para leer: %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "no se pudo abrir la tabla de contenido para leer: %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "no se pudo encontrar el archivo «%s» en el archivador" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "no se pudo generar el nombre de archivo temporal: %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "sintaxis de sentencia COPY inesperada: «%s»" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "el OID del objeto grande no es válido (%u)" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "no se pudo abrir archivo temporal: %m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "el tamaño real del archivo (%lld) no coincide con el esperado (%lld)" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "no se pudo encontrar el encabezado para el archivo «%s» en el archivo tar" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." msgstr "la extracción de datos fuera de orden no está soportada en este formato: se requiere «%s», pero viene antes de «%s» en el archivador." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" msgstr[0] "se encontró un encabezado incompleto (%lu byte)" msgstr[1] "se encontró un encabezado incompleto (%lu bytes)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "se encontró un encabezado corrupto en %s (esperado %d, calculado %d) en la posición %llu" @@ -1340,10 +1468,10 @@ msgstr "se encontró un encabezado corrupto en %s (esperado %d, calculado %d) en msgid "unrecognized section name: \"%s\"" msgstr "nombre de sección «%s» no reconocido" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." @@ -1353,82 +1481,82 @@ msgstr "Pruebe «%s --help» para mayor información." msgid "out of on_exit_nicely slots" msgstr "elementos on_exit_nicely agotados" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "las opciones -s/--schema-only y -a/--data-only no pueden usarse juntas" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "las opciones -s/--schema-only y --include-foreign-data no pueden usarse juntas" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "la opción --include-foreign-data no está soportado con respaldo en paralelo" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "las opciones -c/--clean y -a/--data-only no pueden usarse juntas" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "la opción --if-exists requiere la opción -c/--clean" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "la opción --on-conflict-do-nothing requiere la opción --inserts, --rows-per-insert o --column-inserts" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "algoritmo de compresión no reconocido: «%s»" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "especificación de compresión no válida: %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "la opción de compresión «%s» no está soportada por pg_dump actualmente" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "el volcado en paralelo sólo está soportado por el formato «directory»" -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "el último OID interno es %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "no se encontraron esquemas coincidentes" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "no se encontraron tablas coincidentes" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "no se encontraron extensiones coincidentes" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1437,17 +1565,17 @@ msgstr "" "%s extrae una base de datos en formato de texto o en otros formatos.\n" "\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:636 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPCIÓN]... [NOMBREDB]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:639 pg_restore.c:455 #, c-format msgid "" "\n" @@ -1456,12 +1584,12 @@ msgstr "" "\n" "Opciones generales:\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=ARCHIVO nombre del archivo o directorio de salida\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1470,22 +1598,22 @@ msgstr "" " -F, --format=c|d|t|p Formato del archivo de salida (c=personalizado, \n" " d=directorio, t=tar, p=texto (por omisión))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM máximo de procesos paralelos para volcar\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:641 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose modo verboso\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:642 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de version y salir\n" -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1494,22 +1622,27 @@ msgstr "" " -Z, --compress=MÉTODO[:DETALLE]\n" " comprimir como se indica\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:643 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=SEGS espera a lo más SEGS segundos obtener un lock\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:671 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync no esperar que los cambios se sincronicen a disco\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método para sincr. archivos a disco\n" + +#: pg_dump.c:1108 pg_dumpall.c:644 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:645 #, c-format msgid "" "\n" @@ -1518,64 +1651,64 @@ msgstr "" "\n" "Opciones que controlan el contenido de la salida:\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:646 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only extrae sólo los datos, no el esquema\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects incluir “large objects” en la extracción\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (igual que --large-objects, deprecado)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects excluir “large objects” en la extracción\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (igual que --no-large-objects, deprecado)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean tira (drop) la base de datos antes de crearla\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr "" " -C, --create incluye órdenes para crear la base de datos\n" " en la extracción\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=PATRÓN extrae sólo la o las extensiones nombradas\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:648 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=CODIF extrae los datos con la codificación CODIF\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=PATRÓN extrae sólo el o los esquemas nombrados\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=PATRÓN NO extrae el o los esquemas nombrados\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1584,58 +1717,58 @@ msgstr "" " -O, --no-owner en formato de sólo texto, no reestablece\n" " los dueños de los objetos\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:652 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr " -s, --schema-only extrae sólo el esquema, no los datos\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr " -S, --superuser=NAME superusuario a utilizar en el volcado de texto\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=PATRÓN extrae sólo la o las tablas nombradas\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=PATRÓN NO extrae la o las tablas nombradas\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:655 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges no extrae los privilegios (grant/revoke)\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:656 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade sólo para uso de utilidades de upgrade\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:657 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr "" " --column-inserts extrae los datos usando INSERT con nombres\n" " de columnas\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:658 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr "" " --disable-dollar-quoting deshabilita el uso de «delimitadores de dólar»,\n" " usa delimitadores de cadena estándares\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:659 pg_restore.c:483 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr "" " --disable-triggers deshabilita los disparadores (triggers) durante el\n" " restablecimiento de la extracción de sólo-datos\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1644,7 +1777,12 @@ msgstr "" " --enable-row-security activa seguridad de filas (volcar sólo el\n" " contenido al que el usuario tiene acceso)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=PATRÓN NO volcar la o las extensiones indicadas\n" + +#: pg_dump.c:1136 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1655,12 +1793,12 @@ msgstr "" " NO extrae la o las tablas especificadas,\n" " incluyendo tablas hijas y particiones\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=PATRÓN NO extrae los datos de la(s) tablas nombradas\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1671,17 +1809,26 @@ msgstr "" " NO extrae datos para la o las tablas\n" " especificadas, incluyendo hijas y particiones\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:661 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=NUM usa este valor para extra_float_digits\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid "" +" --filter=FILENAME include or exclude objects and data from dump\n" +" based on expressions in FILENAME\n" +msgstr "" +" --filter=ARCHIVO incluir o excluir objetos y datos basado en\n" +" expresiones en ARCHIVO\n" + +#: pg_dump.c:1146 pg_dumpall.c:663 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists usa IF EXISTS al eliminar objetos\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1692,93 +1839,93 @@ msgstr "" " incluye datos de tablas foráneas en servidores\n" " que coinciden con PATRÓN\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:664 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts extrae los datos usando INSERT, en vez de COPY\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:665 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root cargar particiones a través de tabla raíz\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:666 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments no volcar los comentarios\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:667 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications no volcar las publicaciones\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:669 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels no volcar asignaciones de etiquetas de seguridad\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:670 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions no volcar las suscripciones\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:672 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method no volcar métodos de acceso de tablas\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:673 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces no volcar asignaciones de tablespace\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:674 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression no volcar métodos de compresión TOAST\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:675 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data no volcar datos de tablas unlogged\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:676 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing agregar ON CONFLICT DO NOTHING a órdenes INSERT\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:677 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr "" " --quote-all-identifiers entrecomilla todos los identificadores, incluso\n" " si no son palabras clave\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:678 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NUMFILAS número de filas por INSERT; implica --inserts\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr "" " --section=SECCIÓN volcar la sección nombrada (pre-data, data,\n" " post-data)\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr "" " --serializable-deferrable espera hasta que el respaldo pueda completarse\n" " sin anomalías\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT use el snapshot dado para la extracción\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1787,7 +1934,7 @@ msgstr "" " --strict-names requerir al menos una coincidencia para cada patrón\n" " de nombre de tablas y esquemas\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1796,7 +1943,7 @@ msgstr "" " --table-and-children=PATRÓN volcar sólo la o las tablas especificadas,\n" " incluyendo tablas hijas y particiones\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:679 pg_restore.c:500 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1807,7 +1954,7 @@ msgstr "" " usa órdenes SESSION AUTHORIZATION en lugar de\n" " ALTER OWNER para cambiar los dueño de los objetos\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:683 pg_restore.c:504 #, c-format msgid "" "\n" @@ -1816,46 +1963,46 @@ msgstr "" "\n" "Opciones de conexión:\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=NOMBRE nombre de la base de datos que volcar\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:685 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=ANFITRIÓN anfitrión de la base de datos o\n" " directorio del enchufe (socket)\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:687 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PUERTO número del puerto de la base de datos\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:688 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=USUARIO nombre de usuario con el cual conectarse\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:689 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir una contraseña\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:690 pg_restore.c:509 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password fuerza un prompt para la contraseña\n" " (debería ser automático)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:691 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROL ejecuta SET ROLE antes del volcado\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "" "\n" @@ -1868,530 +2015,537 @@ msgstr "" "de la variable de ambiente PGDATABASE.\n" "\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:695 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Reporte errores a <%s>.\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:696 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "la codificación de cliente especificada «%s» no es válida" -#: pg_dump.c:1303 +#: pg_dump.c:1353 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "Los volcados en paralelo desde servidores standby no están soportados por esta versión de servidor." -#: pg_dump.c:1368 +#: pg_dump.c:1418 #, c-format msgid "invalid output format \"%s\" specified" msgstr "el formato de salida especificado «%s» no es válido" -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1449 +#: pg_dump.c:1459 pg_dump.c:1515 pg_dump.c:1568 pg_dumpall.c:1468 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "el nombre no es válido (demasiados puntos): %s" -#: pg_dump.c:1417 +#: pg_dump.c:1467 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "no se encontraron esquemas coincidentes para el patrón «%s»" -#: pg_dump.c:1470 +#: pg_dump.c:1520 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "no se encontraron extensiones coincidentes para el patrón «%s»" -#: pg_dump.c:1523 +#: pg_dump.c:1573 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "no se encontraron servidores foráneos coincidentes para el patrón «%s»" -#: pg_dump.c:1594 +#: pg_dump.c:1644 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "el nombre de relación no es válido (demasiados puntos): %s" -#: pg_dump.c:1616 +#: pg_dump.c:1666 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "no se encontraron tablas coincidentes para el patrón «%s»" -#: pg_dump.c:1643 +#: pg_dump.c:1693 #, c-format msgid "You are currently not connected to a database." msgstr "No está conectado a una base de datos." -#: pg_dump.c:1646 +#: pg_dump.c:1696 #, c-format msgid "cross-database references are not implemented: %s" msgstr "no están implementadas las referencias entre bases de datos: %s" -#: pg_dump.c:2077 +#: pg_dump.c:2155 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "extrayendo el contenido de la tabla «%s.%s»" -#: pg_dump.c:2183 +#: pg_dump.c:2265 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Falló la extracción del contenido de la tabla «%s»: PQgetCopyData() falló." -#: pg_dump.c:2184 pg_dump.c:2194 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Error message from server: %s" msgstr "Mensaje de error del servidor: %s" -#: pg_dump.c:2185 pg_dump.c:2195 +#: pg_dump.c:2267 pg_dump.c:2277 #, c-format msgid "Command was: %s" msgstr "La orden era: % s" -#: pg_dump.c:2193 +#: pg_dump.c:2275 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Falló la extracción del contenido de la tabla «%s»: PQgetResult() falló." -#: pg_dump.c:2275 +#: pg_dump.c:2366 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "se obtuvo un número incorrecto de campos de la tabla «%s»" -#: pg_dump.c:2973 +#: pg_dump.c:3068 #, c-format msgid "saving database definition" msgstr "salvando las definiciones de la base de datos" -#: pg_dump.c:3078 +#: pg_dump.c:3177 #, c-format msgid "unrecognized locale provider: %s" msgstr "proveedor de configuración regional no reconocido: %s" -#: pg_dump.c:3429 +#: pg_dump.c:3538 #, c-format msgid "saving encoding = %s" msgstr "salvando codificaciones = %s" -#: pg_dump.c:3454 +#: pg_dump.c:3563 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "salvando standard_conforming_strings = %s" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "salvando «standard_conforming_strings = %s»" -#: pg_dump.c:3493 +#: pg_dump.c:3602 #, c-format msgid "could not parse result of current_schemas()" msgstr "no se pudo interpretar la salida de current_schemas()" -#: pg_dump.c:3512 +#: pg_dump.c:3621 #, c-format -msgid "saving search_path = %s" -msgstr "salvando search_path = %s" +msgid "saving \"search_path = %s\"" +msgstr "salvando «search_path = %s»" -#: pg_dump.c:3549 +#: pg_dump.c:3657 #, c-format msgid "reading large objects" msgstr "leyendo objetos grandes" -#: pg_dump.c:3687 +#: pg_dump.c:3878 #, c-format -msgid "saving large objects" -msgstr "salvando objetos grandes" +msgid "saving large objects \"%s\"" +msgstr "salvando objetos grandes «%s»" -#: pg_dump.c:3728 +#: pg_dump.c:3899 #, c-format msgid "error reading large object %u: %s" msgstr "error al leer el objeto grande %u: %s" -#: pg_dump.c:3834 +#: pg_dump.c:4002 #, c-format msgid "reading row-level security policies" msgstr "leyendo políticas de seguridad a nivel de registros" -#: pg_dump.c:3975 +#: pg_dump.c:4143 #, c-format msgid "unexpected policy command type: %c" msgstr "tipo de orden inesperada en política: %c" -#: pg_dump.c:4425 pg_dump.c:4760 pg_dump.c:11984 pg_dump.c:17894 -#: pg_dump.c:17896 pg_dump.c:18517 +#: pg_dump.c:4593 pg_dump.c:5151 pg_dump.c:12365 pg_dump.c:18250 +#: pg_dump.c:18252 pg_dump.c:18874 #, c-format msgid "could not parse %s array" msgstr "no se pudo interpretar el arreglo %s" -#: pg_dump.c:4613 +#: pg_dump.c:4807 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "no se volcaron las suscripciones porque el usuario actual no es un superusuario" -#: pg_dump.c:5149 +#: pg_dump.c:5013 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "no existe la suscripción con OID %u" + +#: pg_dump.c:5020 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "falló la revisión de integridad, tabla con OID %u no se encontró" + +#: pg_dump.c:5583 #, c-format msgid "could not find parent extension for %s %s" msgstr "no se pudo encontrar la extensión padre para %s %s" -#: pg_dump.c:5294 +#: pg_dump.c:5728 #, c-format msgid "schema with OID %u does not exist" msgstr "no existe el esquema con OID %u" -#: pg_dump.c:6776 pg_dump.c:17158 +#: pg_dump.c:7210 pg_dump.c:17621 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "falló la revisión de integridad, no se encontró la tabla padre con OID %u de la secuencia con OID %u" -#: pg_dump.c:6919 +#: pg_dump.c:7355 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "falló la revisión de integridad, el OID %u que aparece en pg_partitioned_table no se encontró" -#: pg_dump.c:7150 pg_dump.c:7417 pg_dump.c:7888 pg_dump.c:8552 pg_dump.c:8671 -#: pg_dump.c:8819 +#: pg_dump.c:7586 pg_dump.c:7860 pg_dump.c:8307 pg_dump.c:8921 pg_dump.c:9043 +#: pg_dump.c:9191 #, c-format msgid "unrecognized table OID %u" msgstr "OID de tabla %u no reconocido" -#: pg_dump.c:7154 +#: pg_dump.c:7590 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "datos de índice inesperados para la tabla «%s»" -#: pg_dump.c:7649 +#: pg_dump.c:8092 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "falló la revisión de integridad, no se encontró la tabla padre con OID %u del elemento con OID %u de pg_rewrite" -#: pg_dump.c:7940 -#, c-format -msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" -msgstr "la consulta produjo un nombre de tabla nulo para la llave foránea del disparador \"%s\" en la tabla «%s» (OID de la tabla: %u)" - -#: pg_dump.c:8556 +#: pg_dump.c:8925 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "información de columnas para la tabla «%s» inesperada" -#: pg_dump.c:8585 +#: pg_dump.c:8954 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "numeración de columnas no válida en la tabla «%s»" -#: pg_dump.c:8633 +#: pg_dump.c:9005 #, c-format msgid "finding table default expressions" msgstr "encontrando expresiones default de tablas" -#: pg_dump.c:8675 +#: pg_dump.c:9047 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "el valor de adnum %d para la tabla «%s» no es válido" -#: pg_dump.c:8769 +#: pg_dump.c:9141 #, c-format msgid "finding table check constraints" msgstr "encontrando restricciones CHECK de tablas" -#: pg_dump.c:8823 +#: pg_dump.c:9195 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "se esperaban %d restricciones CHECK en la tabla «%s» pero se encontraron %d" msgstr[1] "se esperaban %d restricciones CHECK en la tabla «%s» pero se encontraron %d" -#: pg_dump.c:8827 +#: pg_dump.c:9199 #, c-format msgid "The system catalogs might be corrupted." msgstr "Los catálogos del sistema podrían estar corruptos." -#: pg_dump.c:9517 +#: pg_dump.c:9889 #, c-format msgid "role with OID %u does not exist" msgstr "no existe el rol con OID %u" -#: pg_dump.c:9629 pg_dump.c:9658 +#: pg_dump.c:10001 pg_dump.c:10030 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "entrada en pg_init_privs no soportada: %u %u %d" -#: pg_dump.c:10479 +#: pg_dump.c:10577 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "metadata faltante para los objetos grandes «%s»" + +#: pg_dump.c:10860 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "el typtype del tipo «%s» parece no ser válido" -#: pg_dump.c:12053 +#: pg_dump.c:12434 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "el valor del atributo «provolatile» para la función «%s» es desconocido" -#: pg_dump.c:12103 pg_dump.c:13985 +#: pg_dump.c:12484 pg_dump.c:14380 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "el valor del atributo «proparallel» para la función «%s» es desconocido" -#: pg_dump.c:12233 pg_dump.c:12339 pg_dump.c:12346 +#: pg_dump.c:12614 pg_dump.c:12720 pg_dump.c:12727 #, c-format msgid "could not find function definition for function with OID %u" msgstr "no se encontró la definición de la función con OID %u" -#: pg_dump.c:12272 +#: pg_dump.c:12653 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "valor no válido en los campos pg_cast.castfunc o pg_cast.castmethod" -#: pg_dump.c:12275 +#: pg_dump.c:12656 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "valor no válido en el campo pg_cast.castmethod" -#: pg_dump.c:12365 +#: pg_dump.c:12746 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "definición errónea de transformación; al menos uno de trffromsql y trftosql debe ser distinto de cero" -#: pg_dump.c:12382 +#: pg_dump.c:12763 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "valor erróneo en el campo pg_transform.trffromsql" -#: pg_dump.c:12403 +#: pg_dump.c:12784 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "valor erróneo en el campo pg_transform.trftosql" -#: pg_dump.c:12548 +#: pg_dump.c:12929 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "los operadores postfix ya no están soportados (operador «%s»)" -#: pg_dump.c:12718 +#: pg_dump.c:13099 #, c-format msgid "could not find operator with OID %s" msgstr "no se pudo encontrar el operador con OID %s" -#: pg_dump.c:12786 +#: pg_dump.c:13167 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "el tipo «%c» para el método de acceso «%s» no es válido" -#: pg_dump.c:13455 pg_dump.c:13514 +#: pg_dump.c:13841 pg_dump.c:13909 #, c-format msgid "unrecognized collation provider: %s" msgstr "proveedor de ordenamiento no reconocido: %s" -#: pg_dump.c:13464 pg_dump.c:13473 pg_dump.c:13483 pg_dump.c:13498 +#: pg_dump.c:13850 pg_dump.c:13857 pg_dump.c:13868 pg_dump.c:13878 +#: pg_dump.c:13893 #, c-format msgid "invalid collation \"%s\"" msgstr "ordenamiento \"%s\" no válido" -#: pg_dump.c:13904 +#: pg_dump.c:14299 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "valor de aggfinalmodify no reconocido para la agregación «%s»" -#: pg_dump.c:13960 +#: pg_dump.c:14355 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "valor de aggmfinalmodify no reconocido para la agregación «%s»" -#: pg_dump.c:14677 +#: pg_dump.c:15072 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "tipo de objeto desconocido en privilegios por omisión: %d" -#: pg_dump.c:14693 +#: pg_dump.c:15088 #, c-format msgid "could not parse default ACL list (%s)" msgstr "no se pudo interpretar la lista de ACL (%s)" -#: pg_dump.c:14775 +#: pg_dump.c:15172 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "no se pudo interpretar la lista ACL inicial (%s) o por defecto (%s) para el objeto «%s» (%s)" -#: pg_dump.c:14800 +#: pg_dump.c:15197 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "no se pudo interpretar la lista de ACL (%s) o por defecto (%s) para el objeto «%s» (%s)" -#: pg_dump.c:15341 +#: pg_dump.c:15740 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "la consulta para obtener la definición de la vista «%s» no regresó datos" -#: pg_dump.c:15344 +#: pg_dump.c:15743 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "la consulta para obtener la definición de la vista «%s» regresó más de una definición" -#: pg_dump.c:15351 +#: pg_dump.c:15750 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "la definición de la vista «%s» parece estar vacía (tamaño cero)" -#: pg_dump.c:15435 +#: pg_dump.c:15835 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS ya no está soportado (tabla «%s»)" -#: pg_dump.c:16359 +#: pg_dump.c:16822 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "el número de columna %d no es válido para la tabla «%s»" -#: pg_dump.c:16437 +#: pg_dump.c:16900 #, c-format msgid "could not parse index statistic columns" msgstr "no se pudieron interpretar columnas de estadísticas de índices" -#: pg_dump.c:16439 +#: pg_dump.c:16902 #, c-format msgid "could not parse index statistic values" msgstr "no se pudieron interpretar valores de estadísticas de índices" -#: pg_dump.c:16441 +#: pg_dump.c:16904 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "no coincide el número de columnas con el de valores para estadísticas de índices" -#: pg_dump.c:16657 +#: pg_dump.c:17119 #, c-format msgid "missing index for constraint \"%s\"" msgstr "falta un índice para restricción «%s»" -#: pg_dump.c:16892 +#: pg_dump.c:17354 #, c-format msgid "unrecognized constraint type: %c" msgstr "tipo de restricción inesperado: %c" -#: pg_dump.c:16993 pg_dump.c:17222 +#: pg_dump.c:17455 pg_dump.c:17685 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "la consulta para obtener los datos de la secuencia «%s» regresó %d entrada, pero se esperaba 1" msgstr[1] "la consulta para obtener los datos de la secuencia «%s» regresó %d entradas, pero se esperaba 1" -#: pg_dump.c:17025 +#: pg_dump.c:17487 #, c-format msgid "unrecognized sequence type: %s" msgstr "tipo no reconocido de secuencia: %s" -#: pg_dump.c:17314 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "tgtype no esperado: %d" - -#: pg_dump.c:17386 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "argumento de cadena (%s) no válido para el disparador (trigger) «%s» en la tabla «%s»" - -#: pg_dump.c:17655 +#: pg_dump.c:18002 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "la consulta para obtener la regla «%s» asociada con la tabla «%s» falló: retornó un número incorrecto de renglones" -#: pg_dump.c:17808 +#: pg_dump.c:18155 #, c-format msgid "could not find referenced extension %u" msgstr "no se pudo encontrar la extensión referenciada %u" -#: pg_dump.c:17898 +#: pg_dump.c:18254 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "no coincide el número de configuraciones con el de condiciones para extensión" -#: pg_dump.c:18030 +#: pg_dump.c:18386 #, c-format msgid "reading dependency data" msgstr "obteniendo datos de dependencias" -#: pg_dump.c:18116 +#: pg_dump.c:18472 #, c-format msgid "no referencing object %u %u" msgstr "no existe el objeto referenciante %u %u" -#: pg_dump.c:18127 +#: pg_dump.c:18483 #, c-format msgid "no referenced object %u %u" msgstr "no existe el objeto referenciado %u %u" -#: pg_dump_sort.c:422 +#: pg_dump.c:18908 pg_dump.c:18946 pg_dumpall.c:1963 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "el filtro %s para «%s» no está permitido" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "dumpId %d no válido" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "dependencia %d no válida" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "no se pudo identificar bucle de dependencia" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "hay restricciones de llave foránea circulares en la siguiente tabla:" msgstr[1] "hay restricciones de llave foránea circulares entre las siguientes tablas:" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "Puede no ser capaz de restaurar el respaldo sin usar --disable-triggers o temporalmente eliminar las restricciones." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "Considere usar un volcado completo en lugar de --data-only para evitar este problema." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "no se pudo resolver el bucle de dependencias entre los siguientes elementos:" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "el programa «%s» es requerido por %s, pero no fue encontrado en el mismo directorio que «%s»" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "el programa «%s» fue encontrado por «%s», pero no es de la misma versión que %s" -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "la opción --exclude-database no puede ser usada junto con -g/--globals-only, -r/--roles-only o -t/--tablespaces-only" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "las opciones -g/--globals-only y -r/--roles-only no pueden usarse juntas" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "las opciones -g/--globals-only y -t/--tablespaces-only no pueden usarse juntas" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "las opciones -r/--roles-only y -t/--tablespaces-only no pueden usarse juntas" -#: pg_dumpall.c:469 pg_dumpall.c:1750 +#: pg_dumpall.c:474 pg_dumpall.c:1772 #, c-format msgid "could not connect to database \"%s\"" msgstr "no se pudo establecer la conexión a la base de datos «%s»" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2400,7 +2554,7 @@ msgstr "" "no se pudo establecer la conexión a las bases de datos «postgres» o\n" "«template1». Por favor especifique una base de datos para conectarse." -#: pg_dumpall.c:629 +#: pg_dumpall.c:635 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2410,73 +2564,78 @@ msgstr "" "guión (script) SQL.\n" "\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:637 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPCIÓN]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:640 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=ARCHIVO nombre del archivo de salida\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:647 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean tira (drop) la base de datos antes de crearla\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:649 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr " -g, --globals-only extrae sólo los objetos globales, no bases de datos\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:650 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner no reestablece los dueños de los objetos\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:651 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr "" " -r, --roles-only extrae sólo los roles, no bases de datos\n" " ni tablespaces\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:653 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr "" " -S, --superuser=NAME especifica el nombre del superusuario a usar en\n" " el volcado\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:654 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr "" " -t, --tablespaces-only extrae sólo los tablespaces, no bases de datos\n" " ni roles\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:660 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr " --exclude-database=PATRÓN excluir bases de datos cuyos nombres coinciden con el patrón\n" -#: pg_dumpall.c:661 +#: pg_dumpall.c:662 +#, c-format +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr " --filter=ARCHIVO excluir bases de datos basado en expresiones en ARCHIVO\n" + +#: pg_dumpall.c:668 #, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords no extraer contraseñas para roles\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:684 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=CONNSTR conectar usando la cadena de conexión\n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:686 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=NOMBRE especifica la base de datos a la cual conectarse\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:693 #, c-format msgid "" "\n" @@ -2488,97 +2647,106 @@ msgstr "" "Si no se usa -f/--file, el volcado de SQL será escrito a la salida estándar.\n" "\n" -#: pg_dumpall.c:828 +#: pg_dumpall.c:838 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "omitido nombre de rol que empieza con «pg_» (%s)" -#: pg_dumpall.c:1050 +#: pg_dumpall.c:1060 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "no se pudo encontrar un orden legal para membresías del rol «%s»" -#: pg_dumpall.c:1185 +#: pg_dumpall.c:1195 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "no se pudo interpretar la lista de control de acceso (%s) del parámetro «%s»" -#: pg_dumpall.c:1303 +#: pg_dumpall.c:1322 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "no se pudo interpretar la lista de control de acceso (%s) del tablespace «%s»" -#: pg_dumpall.c:1510 +#: pg_dumpall.c:1529 #, c-format msgid "excluding database \"%s\"" msgstr "excluyendo base de datos «%s»" -#: pg_dumpall.c:1514 +#: pg_dumpall.c:1533 #, c-format msgid "dumping database \"%s\"" msgstr "extrayendo base de datos «%s»" -#: pg_dumpall.c:1545 +#: pg_dumpall.c:1564 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "pg_dump falló en la base de datos «%s», saliendo" -#: pg_dumpall.c:1551 +#: pg_dumpall.c:1570 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "no se pudo reabrir el archivo de salida «%s»: %m" -#: pg_dumpall.c:1592 +#: pg_dumpall.c:1614 #, c-format msgid "running \"%s\"" msgstr "ejecutando «%s»" -#: pg_dumpall.c:1793 +#: pg_dumpall.c:1815 #, c-format msgid "could not get server version" msgstr "no se pudo obtener la versión del servidor" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1818 #, c-format msgid "could not parse server version \"%s\"" msgstr "no se pudo interpretar la versión del servidor «%s»" -#: pg_dumpall.c:1866 pg_dumpall.c:1889 +#: pg_dumpall.c:1888 pg_dumpall.c:1911 #, c-format msgid "executing %s" msgstr "ejecutando %s" -#: pg_restore.c:313 +#: pg_dumpall.c:1983 +msgid "unsupported filter object" +msgstr "objeto de filtro no soportado" + +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "una de las opciones -d/--dbname y -f/--file debe especificarse" -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "las opciones -d/--dbname y -f/--file no pueden usarse juntas" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "options -1/--single-transaction and --transaction-size cannot be used together" +msgstr "las opciones -1/--single-transaction y --transaction-size no pueden usarse juntas" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "las opciones -c/--clean y -1/--single-transaction no pueden usarse juntas" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "no se puede especificar --single-transaction junto con múltiples tareas" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "formato de archivo «%s» no reconocido; por favor especifique «c», «d» o «t»" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "errores ignorados durante la recuperación: %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2588,49 +2756,49 @@ msgstr "" "creado por pg_dump.\n" "\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [OPCIÓN]... [ARCHIVO]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NOMBRE nombre de la base de datos a la que conectarse\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=ARCHIVO nombre del archivo de salida (- para stdout)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t formato del volcado (debería ser automático)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr "" " -l, --list imprime una tabla resumida de contenidos\n" " del archivador\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose modo verboso\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "" "\n" @@ -2639,34 +2807,34 @@ msgstr "" "\n" "Opciones que controlan la recuperación:\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only reestablece sólo los datos, no el esquema\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create crea la base de datos de destino\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr "" " -e, --exit-on-error abandonar al encontrar un error\n" " por omisión, se continúa la restauración\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NOMBRE reestablece el índice nombrado\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM máximo de procesos paralelos para restaurar\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2675,64 +2843,73 @@ msgstr "" " -L, --use-list=ARCHIVO usa la tabla de contenido especificada para ordenar\n" " la salida de este archivo\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME reestablece sólo los objetos en este esquema\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NAME no reestablecer los objetos en este esquema\n" -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NOMBRE(args) reestablece la función nombrada\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only reestablece el esquema únicamente, no los datos\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr "" " -S, --superuser=NOMBRE especifica el nombre del superusuario que se usa\n" " para deshabilitar los disparadores (triggers)\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NOMBRE reestablece la relación (tabla, vista, etc.) nombrada\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NOMBRE reestablece el disparador (trigger) nombrado\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges no reestablece los privilegios (grant/revoke)\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction reestablece en una única transacción\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security activa seguridad de filas\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid "" +" --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr "" +" --filter=ARCHIVO restaurar o ignorar objetos basados en\n" +" expresiones en ARCHIVO\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments no restaurar comentarios\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" @@ -2741,44 +2918,49 @@ msgstr "" " --no-data-for-failed-tables no reestablece datos de tablas que no pudieron\n" " ser creadas\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications no restaurar publicaciones\n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels no restaura etiquetas de seguridad\n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions no restaurar suscripciones\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method no restaura métodos de acceso de tablas\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces no restaura asignaciones de tablespace\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr "" " --section=SECCIÓN reestablece la sección nombrada (pre-data, data\n" " post-data)\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr " --transaction-size=N comprometer transacción cada N objetos\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME hace SET ROLE antes de restaurar\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "" "\n" @@ -2789,7 +2971,7 @@ msgstr "" "Las opciones -I, -n, -N, -P, -t, -T, y --section pueden ser combinadas y especificadas\n" "varias veces para seleccionar varios objetos.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "" "\n" diff --git a/src/bin/pg_dump/po/fr.po b/src/bin/pg_dump/po/fr.po index 808499207e662..7e965dff10330 100644 --- a/src/bin/pg_dump/po/fr.po +++ b/src/bin/pg_dump/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-05 17:21+0000\n" -"PO-Revision-Date: 2023-09-05 22:02+0200\n" +"POT-Creation-Date: 2024-08-29 17:52+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -95,32 +95,47 @@ msgstr "l'algorithme de compression « %s » n'accepte pas un nombre de workers" msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "l'algorithme de compression « %s » n'accepte pas un mode distance longue" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binaire « %s » invalide : %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "n'a pas pu lire le binaire « %s » : %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "n'a pas pu trouver un « %s » à exécuter" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "n'a pas pu résoudre le chemin « %s » en sa forme absolue : %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "n'a pas pu exécuter la commande « %s » : %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "n'a pas pu lire à partir de la commande « %s » : %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "aucune donnée n'a été renvoyée par la commande « %s »" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "mémoire épuisée" @@ -135,6 +150,49 @@ msgstr "mémoire épuisée\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -175,227 +233,247 @@ msgstr "valeur « %s » invalide pour l'option %s" msgid "%s must be in range %d..%d" msgstr "%s doit être compris entre %d et %d" -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "lecture des extensions" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "identification des membres d'extension" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "lecture des schémas" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "lecture des tables utilisateur" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "lecture des fonctions utilisateur" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "lecture des types utilisateur" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "lecture des langages procéduraux" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "lecture des fonctions d'agrégats utilisateur" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "lecture des opérateurs utilisateur" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "lecture des méthodes d'accès définis par les utilisateurs" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "lecture des classes d'opérateurs utilisateur" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "lecture des familles d'opérateurs utilisateur" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "lecture des analyseurs utilisateur pour la recherche plein texte" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "lecture des modèles utilisateur pour la recherche plein texte" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "lecture des dictionnaires utilisateur pour la recherche plein texte" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "lecture des configurations utilisateur pour la recherche plein texte" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "lecture des wrappers de données distantes utilisateur" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "lecture des serveurs distants utilisateur" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "lecture des droits par défaut" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "lecture des collationnements utilisateurs" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "lecture des conversions utilisateur" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "lecture des conversions de type" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "lecture des transformations" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "lecture des informations d'héritage des tables" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "lecture des triggers sur évènement" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "recherche des tables d'extension" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "recherche des relations d'héritage" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "lecture des informations de colonnes des tables intéressantes" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "marquage des colonnes héritées dans les sous-tables" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "lecture des données de partitionnement" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "lecture des index" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "décrit les index des tables partitionnées" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "lecture des statistiques étendues" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "lecture des contraintes" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "lecture des triggers" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "lecture des règles de réécriture" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "lecture des politiques" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "lecture des publications" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "lecture des appartenances aux publications des tables" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "lecture des appartenances aux publications des schémas" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "lecture des souscriptions" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "lecture des appartenances aux souscriptions des tables" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "vérification échouée, OID %u parent de la table « %s » (OID %u) introuvable" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "nombre de parents invalide (%d) pour la table « %s »" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "n'a pas pu analyser le tableau numérique « %s » : trop de nombres" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "n'a pas pu analyser le tableau numérique « %s » : caractère invalide dans le nombre" @@ -425,15 +503,20 @@ msgstr "n'a pas pu décompresser les données : %s" msgid "could not close compression library: %s" msgstr "n'a pas pu fermer la bibliothèque de compression : %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "n'a pas pu lire à partir du fichier en entrée : %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:373 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "n'a pas pu lire à partir du fichier en entrée : %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "n'a pas pu lire à partir du fichier en entrée : fin du fichier" @@ -484,16 +567,61 @@ msgstr "n'a pas pu initialiser la bibliothèque de compression" msgid "could not decompress data: %s" msgstr "n'a pas pu décompresser les données : %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "n'a pas pu lire à partir du fichier en entrée : %m" - #: compress_zstd.c:501 #, c-format msgid "unhandled mode \"%s\"" msgstr "mode « %s » non géré" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier filtre « %s » : %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier filtre « %s » : %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "format invalide dans la lecture du filtre à partir de l'entrée standard sur la ligne %d : %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "format invalide dans le filtre lu du fichier « %s » sur la ligne %d : %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "n'a pas pu lire à partir du fichier filtre « %s » : %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "fin de fichier inattendu" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "motif de nom d'objet manquant" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "aucune commande de filtre (attendait « include » ou « exclude »)" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "commande de filtre invalide (attendait « include » ou « exclude »)" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "type d'objet filtre manquant" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "type d'objet filtre non supporté : « %.*s »" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -573,461 +701,466 @@ msgstr "pgpipe: n'a pas pu se connecter au socket: code d'erreur %d" msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: n'a pas pu accepter de connexion: code d'erreur %d" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "n'a pas pu fermer le fichier en sortie : %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "les éléments de l'archive ne sont pas dans l'ordre correct de la section" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "code de section inattendu %d" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "la restauration parallélisée n'est pas supportée avec ce format de fichier d'archive" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "la restauration parallélisée n'est pas supportée avec les archives réalisées par un pg_dump antérieur à la 8.0" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "ne peut pas restaurer l'archive compressée (%s)" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "connexion à la base de données pour la restauration" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "les connexions directes à la base de données ne sont pas supportées dans les archives pre-1.3" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "a impliqué une restauration des données uniquement" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "suppression de %s %s" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "n'a pas pu trouver où insérer IF EXISTS dans l'instruction « %s »" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "message d'avertissement du fichier de sauvegarde original : %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "création de %s « %s.%s »" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "création de %s « %s »" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "connexion à la nouvelle base de données « %s »" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "traitement de %s" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "traitement des données de la table « %s.%s »" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "exécution de %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "désactivation des triggers pour %s" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "activation des triggers pour %s" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "erreur interne -- WriteData ne peut pas être appelé en dehors du contexte de la routine DataDumper" -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "la sauvegarde des « Large Objects » n'est pas supportée dans le format choisi" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "restauration de %d « Large Object »" msgstr[1] "restauration de %d « Large Objects »" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "restauration du « Large Object » d'OID %u" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "n'a pas pu créer le « Large Object » %u : %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3718 +#: pg_backup_archiver.c:1486 pg_dump.c:3888 #, c-format msgid "could not open large object %u: %s" msgstr "n'a pas pu ouvrir le « Large Object » %u : %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "n'a pas pu ouvrir le fichier TOC « %s » : %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "ligne ignorée : %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "n'a pas pu trouver l'entrée pour l'ID %d" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "n'a pas pu fermer le fichier TOC : %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "n'a pas pu ouvrir le fichier de sauvegarde « %s » : %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "n'a pas pu ouvrir le fichier de sauvegarde : %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "a écrit %zu octet de données d'un « Large Object » (résultat = %d)" msgstr[1] "a écrit %zu octets de données d'un « Large Object » (résultat = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "n'a pas pu écrire dans le « Large Object » : %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "pendant l'initialisation (« INITIALIZING ») :" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "pendant le traitement de la TOC (« PROCESSING TOC ») :" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "pendant la finalisation (« FINALIZING ») :" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "de l'entrée TOC %d ; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "mauvais dumpId" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "mauvais dumpId de table pour l'élément TABLE DATA" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "drapeau de décalage de données inattendu %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "le décalage dans le fichier de sauvegarde est trop important" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "nom du répertoire trop long : « %s »" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "le répertoire « %s » ne semble pas être une archive valide (« toc.dat » n'existe pas)" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "n'a pas pu ouvrir le fichier en entrée « %s » : %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "n'a pas pu ouvrir le fichier en entrée : %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "n'a pas pu lire le fichier en entrée : %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "le fichier en entrée est trop petit (%lu lus, 5 attendus)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "Le fichier en entrée semble être une sauvegarde au format texte. Merci d'utiliser psql." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "le fichier en entrée ne semble pas être une archive valide (trop petit ?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "le fichier en entrée ne semble pas être une archive valide" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "n'a pas pu fermer le fichier en entrée : %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "n'a pas pu ouvrir stdout pour l'ajout : %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "format de fichier « %d » non reconnu" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4448 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4647 #, c-format msgid "finished item %d %s %s" msgstr "élément terminé %d %s %s" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4461 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4660 #, c-format msgid "worker process failed: exit code %d" msgstr "échec du processus worker : code de sortie %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "ID %d de l'entrée en dehors de la plage -- peut-être un TOC corrompu" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "la restauration des tables avec WITH OIDS n'est plus supportée" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "encodage « %s » non reconnu" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2823 #, c-format msgid "invalid ENCODING item: %s" msgstr "élément ENCODING invalide : %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2841 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "élément STDSTRINGS invalide : %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2866 #, c-format msgid "schema \"%s\" not found" msgstr "schéma « %s » non trouvé" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2873 #, c-format msgid "table \"%s\" not found" msgstr "table « %s » non trouvée" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2880 #, c-format msgid "index \"%s\" not found" msgstr "index « %s » non trouvé" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2887 #, c-format msgid "function \"%s\" not found" msgstr "fonction « %s » non trouvée" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2894 #, c-format msgid "trigger \"%s\" not found" msgstr "trigger « %s » non trouvé" -#: pg_backup_archiver.c:3183 +#: pg_backup_archiver.c:3325 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "n'a pas pu initialiser la session utilisateur à « %s »: %s" -#: pg_backup_archiver.c:3315 +#: pg_backup_archiver.c:3457 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "n'a pas pu configurer search_path à « %s » : %s" +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "n'a pas pu configurer « search_path » à « %s » : %s" -#: pg_backup_archiver.c:3376 +#: pg_backup_archiver.c:3518 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "n'a pas pu configurer default_tablespace à %s : %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "n'a pas pu configurer « default_tablespace » à %s : %s" -#: pg_backup_archiver.c:3425 +#: pg_backup_archiver.c:3567 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "n'a pas pu configurer la méthode default_table_access_method à %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "n'a pas pu configurer la méthode « default_table_access_method » : %s" -#: pg_backup_archiver.c:3530 +#: pg_backup_archiver.c:3616 +#, c-format +msgid "could not alter table access method: %s" +msgstr "n'a pas pu modifier la méthode d'accès aux tables : %s" + +#: pg_backup_archiver.c:3717 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "ne sait pas comment initialiser le propriétaire du type d'objet « %s »" -#: pg_backup_archiver.c:3752 +#: pg_backup_archiver.c:4004 #, c-format msgid "did not find magic string in file header" msgstr "n'a pas trouver la chaîne magique dans le fichier d'en-tête" -#: pg_backup_archiver.c:3766 +#: pg_backup_archiver.c:4018 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "version non supportée (%d.%d) dans le fichier d'en-tête" -#: pg_backup_archiver.c:3771 +#: pg_backup_archiver.c:4023 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "échec de la vérification sur la taille de l'entier (%lu)" -#: pg_backup_archiver.c:3775 +#: pg_backup_archiver.c:4027 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "l'archive a été créée sur une machine disposant d'entiers plus larges, certaines opérations peuvent échouer" -#: pg_backup_archiver.c:3785 +#: pg_backup_archiver.c:4037 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "le format attendu (%d) diffère du format du fichier (%d)" -#: pg_backup_archiver.c:3807 +#: pg_backup_archiver.c:4059 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "l'archive est compressée mais cette installation ne supporte pas la compression (%s) -- aucune donnée ne sera disponible" -#: pg_backup_archiver.c:3843 +#: pg_backup_archiver.c:4095 #, c-format msgid "invalid creation date in header" msgstr "date de création invalide dans l'en-tête" -#: pg_backup_archiver.c:3977 +#: pg_backup_archiver.c:4229 #, c-format msgid "processing item %d %s %s" msgstr "traitement de l'élément %d %s %s" -#: pg_backup_archiver.c:4052 +#: pg_backup_archiver.c:4314 #, c-format msgid "entering main parallel loop" msgstr "entrée dans la boucle parallèle principale" -#: pg_backup_archiver.c:4063 +#: pg_backup_archiver.c:4325 #, c-format msgid "skipping item %d %s %s" msgstr "omission de l'élément %d %s %s" -#: pg_backup_archiver.c:4072 +#: pg_backup_archiver.c:4334 #, c-format msgid "launching item %d %s %s" msgstr "lancement de l'élément %d %s %s" -#: pg_backup_archiver.c:4126 +#: pg_backup_archiver.c:4388 #, c-format msgid "finished main parallel loop" msgstr "fin de la boucle parallèle principale" -#: pg_backup_archiver.c:4162 +#: pg_backup_archiver.c:4424 #, c-format msgid "processing missed item %d %s %s" msgstr "traitement de l'élément manquant %d %s %s" -#: pg_backup_archiver.c:4767 +#: pg_backup_archiver.c:4966 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "la table « %s » n'a pas pu être créée, ses données ne seront pas restaurées" -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "OID invalide pour le « Large Object »" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "erreur lors de la recherche dans le fichier : %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "le bloc de données %d a une mauvaise position de recherche" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "type de bloc de données non reconnu (%d) lors de la recherche dans l'archive" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "" @@ -1036,53 +1169,53 @@ msgstr "" "différent, ce qui ne peut pas être géré à cause d'un fichier non gérable en\n" "recherche" -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "n'a pas pu trouver l'identifiant de bloc %d dans l'archive -- possible corruption de l'archive" -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "ID de bloc inattendu (%d) lors de la lecture des données -- %d attendu" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "type de bloc de données %d non reconnu lors de la restauration de l'archive" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "n'a pas pu déterminer la position de recherche dans le fichier d'archive : %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "n'a pas pu fermer le fichier d'archive : %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "peut seulement rouvrir l'archive en entrée" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "la restauration parallélisée n'est pas supportée à partir de stdin" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "la restauration parallélisée n'est pas supportée à partir de fichiers sans table de matière" -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "n'a pas pu initialiser la recherche de position dans le fichier d'archive : %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "compression activée" @@ -1092,12 +1225,12 @@ msgstr "compression activée" msgid "could not get server_version from libpq" msgstr "n'a pas pu obtenir server_version de libpq" -#: pg_backup_db.c:53 pg_dumpall.c:1809 +#: pg_backup_db.c:53 pg_dumpall.c:1830 #, c-format msgid "aborting because of server version mismatch" msgstr "annulation à cause de la différence des versions" -#: pg_backup_db.c:54 pg_dumpall.c:1810 +#: pg_backup_db.c:54 pg_dumpall.c:1831 #, c-format msgid "server version: %s; %s version: %s" msgstr "version du serveur : %s ; %s version : %s" @@ -1107,7 +1240,7 @@ msgstr "version du serveur : %s ; %s version : %s" msgid "already connected to a database" msgstr "déjà connecté à une base de données" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1656 pg_dumpall.c:1758 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 msgid "Password: " msgstr "Mot de passe : " @@ -1121,18 +1254,18 @@ msgstr "n'a pas pu se connecter à la base de données" msgid "reconnection failed: %s" msgstr "échec de la reconnexion : %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1683 pg_dumpall.c:1767 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1872 pg_dumpall.c:1895 +#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 #, c-format msgid "query failed: %s" msgstr "échec de la requête : %s" -#: pg_backup_db.c:273 pg_dumpall.c:1873 pg_dumpall.c:1896 +#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "Query was: %s" msgstr "La requête était : %s" @@ -1168,7 +1301,7 @@ msgstr "erreur renvoyée par PQputCopyEnd : %s" msgid "COPY failed for table \"%s\": %s" msgstr "COPY échoué pour la table « %s » : %s" -#: pg_backup_db.c:521 pg_dump.c:2202 +#: pg_backup_db.c:521 pg_dump.c:2283 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "résultats supplémentaires non attendus durant l'exécution de COPY sur la table « %s »" @@ -1181,161 +1314,156 @@ msgstr "n'a pas pu démarrer la transaction de la base de données" msgid "could not commit database transaction" msgstr "n'a pas pu valider la transaction de la base de données" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "aucun répertoire cible indiqué" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "n'a pas pu lire le répertoire « %s » : %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "n'a pas pu fermer le répertoire « %s » : %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "n'a pas pu créer le répertoire « %s » : %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "n'a pas pu écrire dans le fichier en sortie : %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "n'a pas pu fermer le fichier de données : %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "n'a pas pu fermer le fichier de données « %s » : %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "n'a pas pu ouvrir le fichier TOC « %s » du Large Object en entrée : %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "ligne invalide dans le fichier TOC du Large Object « %s » : « %s »" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "erreur lors de la lecture du TOC du fichier Large Object « %s »" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "n'a pas pu fermer le TOC du Large Object « %s » : %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "n'a pas pu fermer le fichier de données LO : %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "n'a pas pu écrire dans le fichier TOC des Large Objects : %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" msgstr "n'a pas pu fermer le fichier TOC des Large Objects : %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "nom du fichier trop long : « %s »" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "ce format ne peut pas être lu" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "n'a pas pu ouvrir le fichier TOC « %s » en sortie : %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "n'a pas pu ouvrir le fichier TOC en sortie : %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "compression non supportée par le format des archives tar" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "n'a pas pu ouvrir le fichier TOC « %s » en entrée : %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "n'a pas pu ouvrir le fichier TOC en entrée : %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "n'a pas pu trouver le fichier « %s » dans l'archive" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "impossible de créer le nom du fichier temporaire : %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "syntaxe inattendue de l'instruction COPY : « %s »" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "OID invalide pour le « Large Object » (%u)" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "n'a pas pu fermer le fichier temporaire : m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "la longueur réelle du fichier (%lld) ne correspond pas à ce qui était attendu (%lld)" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "n'a pas pu trouver l'en-tête du fichier « %s » dans l'archive tar" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." msgstr "la restauration désordonnée de données n'est pas supportée avec ce format d'archive : « %s » est requis mais vient avant « %s » dans le fichier d'archive." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" msgstr[0] "en-tête incomplet du fichier tar (%lu octet)" msgstr[1] "en-tête incomplet du fichier tar (%lu octets)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "en-tête tar corrompu trouvé dans %s (%d attendu, %d calculé ) à la position %llu du fichier" @@ -1345,10 +1473,10 @@ msgstr "en-tête tar corrompu trouvé dans %s (%d attendu, %d calculé ) à la p msgid "unrecognized section name: \"%s\"" msgstr "nom de section non reconnu : « %s »" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." @@ -1358,82 +1486,82 @@ msgstr "Essayez « %s --help » pour plus d'informations." msgid "out of on_exit_nicely slots" msgstr "plus d'emplacements on_exit_nicely" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "les options « -s/--schema-only » et « -a/--data-only » ne peuvent pas être utilisées ensemble" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "les options « -s/--schema-only » et « --include-foreign-data » ne peuvent pas être utilisées ensemble" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "l'option --include-foreign-data n'est pas supportée avec une sauvegarde parallélisée" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "les options « -c/--clean » et « -a/--data-only » ne peuvent pas être utilisées ensemble" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "l'option --if-exists nécessite l'option -c/--clean" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "l'option --on-conflict-do-nothing requiert l'option --inserts, --rows-per-insert, ou --column-inserts" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "algorithme de compression inconnu : « %s »" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "spécification de compression invalide : %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "l'option de compression « %s » n'est pas actuellement supportée par pg_dump" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "la sauvegarde parallélisée n'est supportée qu'avec le format directory" -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "le dernier OID interne est %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "aucun schéma correspondant n'a été trouvé" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "aucune table correspondante n'a été trouvée" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "aucune extension correspondante n'a été trouvée" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1443,17 +1571,17 @@ msgstr "" "formats.\n" "\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:635 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [BASE]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:638 pg_restore.c:455 #, c-format msgid "" "\n" @@ -1462,12 +1590,12 @@ msgstr "" "\n" "Options générales :\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=FICHIER nom du fichier ou du répertoire en sortie\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1476,24 +1604,24 @@ msgstr "" " -F, --format=c|d|t|p format du fichier de sortie (personnalisé,\n" " répertoire, tar, texte (par défaut))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr "" " -j, --jobs=NOMBRE utilise ce nombre de jobs en parallèle pour la\n" " sauvegarde\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:640 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose mode verbeux\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:641 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1502,26 +1630,31 @@ msgstr "" " -Z, --compress=METHODE[:DETAIL]\n" " compresse comme indiqué\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:642 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr "" " --lock-wait-timeout=DÉLAI échec après l'attente du DÉLAI pour un verrou de\n" " table\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:670 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " --no-sync n'attend pas que les modifications soient\n" " proprement écrites sur disque\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: pg_dump.c:1108 pg_dumpall.c:643 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:644 #, c-format msgid "" "\n" @@ -1530,66 +1663,66 @@ msgstr "" "\n" "Options contrôlant le contenu en sortie :\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:645 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only sauvegarde uniquement les données, pas le schéma\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects inclut les « Large Objects » dans la sauvegarde\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (comme --large-objects, obsolète)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects exclut les « Large Objects » de la sauvegarde\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (comme --no-large-objects, obsolète)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr "" " -c, --clean nettoie/supprime les objets de la base de données\n" " avant de les créer\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr "" " -C, --create inclut les commandes de création de la base\n" " dans la sauvegarde\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=MOTIF sauvegarde uniquement les extensions indiquées\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:647 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=ENCODAGE sauvegarde les données dans l'encodage ENCODAGE\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=MOTIF sauvegarde uniquement les schémas indiqués\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=MOTIF ne sauvegarde pas les schémas indiqués\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1598,50 +1731,50 @@ msgstr "" " -O, --no-owner ne sauvegarde pas les propriétaires des objets\n" " lors de l'utilisation du format texte\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:651 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr "" " -s, --schema-only sauvegarde uniquement la structure, pas les\n" " données\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr "" " -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" " avec le format texte\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=MOTIF sauvegarde uniquement les tables indiquées\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=MOTIF ne sauvegarde pas les tables indiquées\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:654 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges ne sauvegarde pas les droits sur les objets\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:655 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr "" " --binary-upgrade à n'utiliser que par les outils de mise à jour\n" " seulement\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:656 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr "" " --column-inserts sauvegarde les données avec des commandes INSERT\n" " en précisant les noms des colonnes\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:657 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr "" @@ -1649,14 +1782,14 @@ msgstr "" " dans le but de respecter le standard SQL en\n" " matière de guillemets\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:658 pg_restore.c:483 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr "" " --disable-triggers désactive les triggers en mode de restauration\n" " des données seules\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1666,7 +1799,12 @@ msgstr "" " sauvegarde uniquement le contenu visible par cet\n" " utilisateur)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=MOTIF ne sauvegarde PAS les extensions indiquées\n" + +#: pg_dump.c:1136 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1676,12 +1814,12 @@ msgstr "" " --exclude-table-and-children=MOTIF\n" " ne sauvegarde PAS les tables indiquées, ceci incluant les tables filles et les partitions\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=MOTIF ne sauvegarde pas les tables indiquées\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1691,21 +1829,30 @@ msgstr "" " --exclude-table-data-and-children=MOTIF\n" " ne sauvegarde PAS les données des tables indiquées, ceci incluant les tables filles et les partitions\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:660 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr "" " --extra-float-digits=NUM surcharge la configuration par défaut de\n" " extra_float_digits\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid "" +" --filter=FILENAME include or exclude objects and data from dump\n" +" based on expressions in FILENAME\n" +msgstr "" +" --filter=NOMFICHIER inclut ou exclut des objets et des données à partir de la sauvegarde\n" +" basée sur les expressions dans NOMFICHIER\n" + +#: pg_dump.c:1146 pg_dumpall.c:662 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr "" " --if-exists utilise IF EXISTS lors de la suppression des\n" " objets\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1715,103 +1862,103 @@ msgstr "" " --include-foreign-data=MOTIF inclut les données des tables externes pour les\n" " serveurs distants correspondant au motif MOTIF\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:663 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr "" " --inserts sauvegarde les données avec des instructions\n" " INSERT plutôt que COPY\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:664 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root charger les partitions via la table racine\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:665 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments ne sauvegarde pas les commentaires\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:666 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications ne sauvegarde pas les publications\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:668 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr "" " --no-security-labels ne sauvegarde pas les affectations de labels de\n" " sécurité\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:669 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions ne sauvegarde pas les souscriptions\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:671 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method ne sauvegarde pas les méthodes d'accès aux tables\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:672 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces ne sauvegarde pas les affectations de tablespaces\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:673 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr "" " --no-toast-compression ne sauvegarde pas les méthodes de compression de\n" " TOAST\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:674 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr "" " --no-unlogged-table-data ne sauvegarde pas les données des tables non\n" " journalisées\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:675 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr "" " --on-conflict-do-nothing ajoute ON CONFLICT DO NOTHING aux commandes\n" " INSERT\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:676 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr "" " --quote-all-identifiers met entre guillemets tous les identifiants même\n" " s'il ne s'agit pas de mots clés\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:677 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NROWS nombre de lignes par INSERT ; implique --inserts\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr "" " --section=SECTION sauvegarde la section indiquée (pre-data, data\n" " ou post-data)\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr "" " --serializable-deferrable attend jusqu'à ce que la sauvegarde puisse\n" " s'exécuter sans anomalies\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT utilise l'image donnée pour la sauvegarde\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1820,14 +1967,14 @@ msgstr "" " --strict-names requiert que les motifs des tables et/ou schémas\n" " correspondent à au moins une entité de chaque\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" " child and partition tables\n" msgstr " --table-and-children=MODÈLE sauvegarde uniquement les tables indiquées, en incluant les tables filles et les partitions\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:678 pg_restore.c:500 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1839,7 +1986,7 @@ msgstr "" " au lieu des commandes ALTER OWNER pour modifier\n" " les propriétaires\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:682 pg_restore.c:504 #, c-format msgid "" "\n" @@ -1848,46 +1995,46 @@ msgstr "" "\n" "Options de connexion :\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=BASE base de données à sauvegarder\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:684 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HÔTE hôte du serveur de bases de données ou\n" " répertoire des sockets\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:686 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT numéro de port du serveur de bases de données\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:687 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NOM se connecter avec cet utilisateur\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:688 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ne demande jamais un mot de passe\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:689 pg_restore.c:509 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password force la demande du mot de passe (devrait\n" " survenir automatiquement)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:690 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=NOMROLE exécute SET ROLE avant la sauvegarde\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "" "\n" @@ -1900,530 +2047,537 @@ msgstr "" "d'environnement PGDATABASE est alors utilisée.\n" "\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:694 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapporter les bogues à <%s>.\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:695 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "encodage client indiqué (« %s ») invalide" -#: pg_dump.c:1303 +#: pg_dump.c:1352 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "les sauvegardes parallélisées sur un serveur standby ne sont pas supportées par cette version du serveur" -#: pg_dump.c:1368 +#: pg_dump.c:1417 #, c-format msgid "invalid output format \"%s\" specified" msgstr "format de sortie « %s » invalide" -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1449 +#: pg_dump.c:1458 pg_dump.c:1514 pg_dump.c:1567 pg_dumpall.c:1467 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s" -#: pg_dump.c:1417 +#: pg_dump.c:1466 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "aucun schéma correspondant n'a été trouvé avec le motif « %s »" -#: pg_dump.c:1470 +#: pg_dump.c:1519 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "aucune extension correspondante n'a été trouvée avec le motif « %s »" -#: pg_dump.c:1523 +#: pg_dump.c:1572 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "aucun serveur distant correspondant n'a été trouvé avec le motif « %s »" -#: pg_dump.c:1594 +#: pg_dump.c:1643 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "nom de relation incorrecte (trop de points entre les noms) : %s" -#: pg_dump.c:1616 +#: pg_dump.c:1665 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "aucune table correspondante n'a été trouvée avec le motif « %s »" -#: pg_dump.c:1643 +#: pg_dump.c:1692 #, c-format msgid "You are currently not connected to a database." msgstr "Vous n'êtes pas connecté à une base de données." -#: pg_dump.c:1646 +#: pg_dump.c:1695 #, c-format msgid "cross-database references are not implemented: %s" msgstr "les références entre bases de données ne sont pas implémentées : %s" -#: pg_dump.c:2077 +#: pg_dump.c:2154 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "sauvegarde du contenu de la table « %s.%s »" -#: pg_dump.c:2183 +#: pg_dump.c:2264 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Sauvegarde du contenu de la table « %s » échouée : échec de PQgetCopyData()." -#: pg_dump.c:2184 pg_dump.c:2194 +#: pg_dump.c:2265 pg_dump.c:2275 #, c-format msgid "Error message from server: %s" msgstr "Message d'erreur du serveur : %s" -#: pg_dump.c:2185 pg_dump.c:2195 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Command was: %s" msgstr "La commande était : %s" -#: pg_dump.c:2193 +#: pg_dump.c:2274 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Sauvegarde du contenu de la table « %s » échouée : échec de PQgetResult()." -#: pg_dump.c:2275 +#: pg_dump.c:2365 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "mauvais nombre de champs récupérés à partir de la table « %s »" -#: pg_dump.c:2973 +#: pg_dump.c:3067 #, c-format msgid "saving database definition" msgstr "sauvegarde de la définition de la base de données" -#: pg_dump.c:3078 +#: pg_dump.c:3176 #, c-format msgid "unrecognized locale provider: %s" msgstr "fournisseur de locale non reconnu : %s" -#: pg_dump.c:3429 +#: pg_dump.c:3537 #, c-format msgid "saving encoding = %s" msgstr "encodage de la sauvegarde = %s" -#: pg_dump.c:3454 +#: pg_dump.c:3562 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "sauvegarde de standard_conforming_strings = %s" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "sauvegarde de « standard_conforming_strings = %s »" -#: pg_dump.c:3493 +#: pg_dump.c:3601 #, c-format msgid "could not parse result of current_schemas()" msgstr "n'a pas pu analyser le résultat de current_schema()" -#: pg_dump.c:3512 +#: pg_dump.c:3620 #, c-format -msgid "saving search_path = %s" -msgstr "sauvegarde de search_path = %s" +msgid "saving \"search_path = %s\"" +msgstr "sauvegarde de « search_path = %s »" -#: pg_dump.c:3549 +#: pg_dump.c:3656 #, c-format msgid "reading large objects" msgstr "lecture des « Large Objects »" -#: pg_dump.c:3687 +#: pg_dump.c:3877 #, c-format -msgid "saving large objects" -msgstr "sauvegarde des « Large Objects »" +msgid "saving large objects \"%s\"" +msgstr "sauvegarde des « Large Objects » « %s »" -#: pg_dump.c:3728 +#: pg_dump.c:3898 #, c-format msgid "error reading large object %u: %s" msgstr "erreur lors de la lecture du « Large Object » %u : %s" -#: pg_dump.c:3834 +#: pg_dump.c:4001 #, c-format msgid "reading row-level security policies" msgstr "lecture des politiques de sécurité au niveau ligne" -#: pg_dump.c:3975 +#: pg_dump.c:4142 #, c-format msgid "unexpected policy command type: %c" msgstr "type de commande inattendu pour la politique : %c" -#: pg_dump.c:4425 pg_dump.c:4760 pg_dump.c:11984 pg_dump.c:17894 -#: pg_dump.c:17896 pg_dump.c:18517 +#: pg_dump.c:4592 pg_dump.c:5150 pg_dump.c:12362 pg_dump.c:18246 +#: pg_dump.c:18248 pg_dump.c:18870 #, c-format msgid "could not parse %s array" msgstr "n'a pas pu analyser le tableau %s" -#: pg_dump.c:4613 +#: pg_dump.c:4806 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "les souscriptions ne sont pas sauvegardées parce que l'utilisateur courant n'est pas un superutilisateur" -#: pg_dump.c:5149 +#: pg_dump.c:5012 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "la souscription d'OID %u n'existe pas" + +#: pg_dump.c:5019 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "vérification de santé échouée, table d'OID %u introuvable" + +#: pg_dump.c:5582 #, c-format msgid "could not find parent extension for %s %s" msgstr "n'a pas pu trouver l'extension parent pour %s %s" -#: pg_dump.c:5294 +#: pg_dump.c:5727 #, c-format msgid "schema with OID %u does not exist" msgstr "le schéma d'OID %u n'existe pas" -#: pg_dump.c:6776 pg_dump.c:17158 +#: pg_dump.c:7209 pg_dump.c:17617 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "vérification échouée, OID %u de la table parent de l'OID %u de la séquence introuvable" -#: pg_dump.c:6919 +#: pg_dump.c:7352 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "vérification échouée, OID de table %u apparaissant dans partitioned introuvable" -#: pg_dump.c:7150 pg_dump.c:7417 pg_dump.c:7888 pg_dump.c:8552 pg_dump.c:8671 -#: pg_dump.c:8819 +#: pg_dump.c:7583 pg_dump.c:7857 pg_dump.c:8304 pg_dump.c:8918 pg_dump.c:9040 +#: pg_dump.c:9188 #, c-format msgid "unrecognized table OID %u" msgstr "OID de table %u non reconnu" -#: pg_dump.c:7154 +#: pg_dump.c:7587 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "données d'index inattendu pour la table « %s »" -#: pg_dump.c:7649 +#: pg_dump.c:8089 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "vérification échouée, OID %u de la table parent de l'OID %u de l'entrée de pg_rewrite introuvable" -#: pg_dump.c:7940 -#, c-format -msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" -msgstr "la requête a produit une réference de nom de table null pour le trigger de la clé étrangère « %s » sur la table « %s » (OID de la table : %u)" - -#: pg_dump.c:8556 +#: pg_dump.c:8922 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "données de colonne inattendues pour la table « %s »" -#: pg_dump.c:8585 +#: pg_dump.c:8951 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "numérotation des colonnes invalide pour la table « %s »" -#: pg_dump.c:8633 +#: pg_dump.c:9002 #, c-format msgid "finding table default expressions" msgstr "recherche des expressions par défaut de la table" -#: pg_dump.c:8675 +#: pg_dump.c:9044 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "valeur adnum %d invalide pour la table « %s »" -#: pg_dump.c:8769 +#: pg_dump.c:9138 #, c-format msgid "finding table check constraints" msgstr "recherche des contraintes CHECK de la table" -#: pg_dump.c:8823 +#: pg_dump.c:9192 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "%d contrainte de vérification attendue pour la table « %s » mais %d trouvée" msgstr[1] "%d contraintes de vérification attendues pour la table « %s » mais %d trouvée" -#: pg_dump.c:8827 +#: pg_dump.c:9196 #, c-format msgid "The system catalogs might be corrupted." msgstr "Les catalogues système pourraient être corrompus." -#: pg_dump.c:9517 +#: pg_dump.c:9886 #, c-format msgid "role with OID %u does not exist" msgstr "le rôle d'OID %u n'existe pas" -#: pg_dump.c:9629 pg_dump.c:9658 +#: pg_dump.c:9998 pg_dump.c:10027 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "entrée pg_init_privs non supportée : %u %u %d" -#: pg_dump.c:10479 +#: pg_dump.c:10574 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "métadonnée manquante pour les Large Object « %s »" + +#: pg_dump.c:10857 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "la colonne typtype du type de données « %s » semble être invalide" -#: pg_dump.c:12053 +#: pg_dump.c:12431 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "valeur provolatile non reconnue pour la fonction « %s »" -#: pg_dump.c:12103 pg_dump.c:13985 +#: pg_dump.c:12481 pg_dump.c:14377 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "valeur proparallel non reconnue pour la fonction « %s »" -#: pg_dump.c:12233 pg_dump.c:12339 pg_dump.c:12346 +#: pg_dump.c:12611 pg_dump.c:12717 pg_dump.c:12724 #, c-format msgid "could not find function definition for function with OID %u" msgstr "n'a pas pu trouver la définition de la fonction d'OID %u" -#: pg_dump.c:12272 +#: pg_dump.c:12650 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "valeur erronée dans le champ pg_cast.castfunc ou pg_cast.castmethod" -#: pg_dump.c:12275 +#: pg_dump.c:12653 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "valeur erronée dans pg_cast.castmethod" -#: pg_dump.c:12365 +#: pg_dump.c:12743 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "définition de transformation invalide, au moins un de trffromsql et trftosql ne doit pas valoir 0" -#: pg_dump.c:12382 +#: pg_dump.c:12760 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "valeur erronée dans pg_transform.trffromsql" -#: pg_dump.c:12403 +#: pg_dump.c:12781 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "valeur erronée dans pg_transform.trftosql" -#: pg_dump.c:12548 +#: pg_dump.c:12926 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "les opérateurs postfixes ne sont plus supportés (opérateur « %s »)" -#: pg_dump.c:12718 +#: pg_dump.c:13096 #, c-format msgid "could not find operator with OID %s" msgstr "n'a pas pu trouver l'opérateur d'OID %s" -#: pg_dump.c:12786 +#: pg_dump.c:13164 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "type « %c » invalide de la méthode d'accès « %s »" -#: pg_dump.c:13455 pg_dump.c:13514 +#: pg_dump.c:13838 pg_dump.c:13906 #, c-format msgid "unrecognized collation provider: %s" msgstr "fournisseur de collationnement non reconnu : %s" -#: pg_dump.c:13464 pg_dump.c:13473 pg_dump.c:13483 pg_dump.c:13498 +#: pg_dump.c:13847 pg_dump.c:13854 pg_dump.c:13865 pg_dump.c:13875 +#: pg_dump.c:13890 #, c-format msgid "invalid collation \"%s\"" msgstr "collation « %s » invalide" -#: pg_dump.c:13904 +#: pg_dump.c:14296 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "valeur non reconnue de aggfinalmodify pour l'agrégat « %s »" -#: pg_dump.c:13960 +#: pg_dump.c:14352 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "valeur non reconnue de aggmfinalmodify pour l'agrégat « %s »" -#: pg_dump.c:14677 +#: pg_dump.c:15069 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "type d'objet inconnu dans les droits par défaut : %d" -#: pg_dump.c:14693 +#: pg_dump.c:15085 #, c-format msgid "could not parse default ACL list (%s)" msgstr "n'a pas pu analyser la liste ACL par défaut (%s)" -#: pg_dump.c:14775 +#: pg_dump.c:15169 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "n'a pas pu analyser la liste ACL initiale (%s) ou par défaut (%s) pour l'objet « %s » (%s)" -#: pg_dump.c:14800 +#: pg_dump.c:15194 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "n'a pas pu analyser la liste ACL (%s) ou par défaut (%s) pour l'objet « %s » (%s)" -#: pg_dump.c:15341 +#: pg_dump.c:15737 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "la requête permettant d'obtenir la définition de la vue « %s » n'a renvoyé aucune donnée" -#: pg_dump.c:15344 +#: pg_dump.c:15740 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "la requête permettant d'obtenir la définition de la vue « %s » a renvoyé plusieurs définitions" -#: pg_dump.c:15351 +#: pg_dump.c:15747 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "la définition de la vue « %s » semble être vide (longueur nulle)" -#: pg_dump.c:15435 +#: pg_dump.c:15832 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS n'est plus supporté (table « %s »)" -#: pg_dump.c:16359 +#: pg_dump.c:16819 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "numéro de colonne %d invalide pour la table « %s »" -#: pg_dump.c:16437 +#: pg_dump.c:16897 #, c-format msgid "could not parse index statistic columns" msgstr "n'a pas pu analyser les colonnes statistiques de l'index" -#: pg_dump.c:16439 +#: pg_dump.c:16899 #, c-format msgid "could not parse index statistic values" msgstr "n'a pas pu analyser les valeurs statistiques de l'index" -#: pg_dump.c:16441 +#: pg_dump.c:16901 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "nombre de colonnes et de valeurs différentes pour les statistiques des index" -#: pg_dump.c:16657 +#: pg_dump.c:17116 #, c-format msgid "missing index for constraint \"%s\"" msgstr "index manquant pour la contrainte « %s »" -#: pg_dump.c:16892 +#: pg_dump.c:17351 #, c-format msgid "unrecognized constraint type: %c" msgstr "type de contrainte inconnu : %c" -#: pg_dump.c:16993 pg_dump.c:17222 +#: pg_dump.c:17452 pg_dump.c:17681 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé %d ligne (une seule attendue)" msgstr[1] "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé %d ligne (une seule attendue)" -#: pg_dump.c:17025 +#: pg_dump.c:17484 #, c-format msgid "unrecognized sequence type: %s" msgstr "type de séquence non reconnu : « %s »" -#: pg_dump.c:17314 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "valeur tgtype inattendue : %d" - -#: pg_dump.c:17386 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "chaîne argument invalide (%s) pour le trigger « %s » sur la table « %s »" - -#: pg_dump.c:17655 +#: pg_dump.c:17998 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "la requête permettant d'obtenir la règle « %s » associée à la table « %s » a échoué : mauvais nombre de lignes renvoyées" -#: pg_dump.c:17808 +#: pg_dump.c:18151 #, c-format msgid "could not find referenced extension %u" msgstr "n'a pas pu trouver l'extension référencée %u" -#: pg_dump.c:17898 +#: pg_dump.c:18250 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "nombre différent de configurations et de conditions pour l'extension" -#: pg_dump.c:18030 +#: pg_dump.c:18382 #, c-format msgid "reading dependency data" msgstr "lecture des données de dépendance" -#: pg_dump.c:18116 +#: pg_dump.c:18468 #, c-format msgid "no referencing object %u %u" msgstr "pas d'objet référant %u %u" -#: pg_dump.c:18127 +#: pg_dump.c:18479 #, c-format msgid "no referenced object %u %u" msgstr "pas d'objet référencé %u %u" -#: pg_dump_sort.c:422 +#: pg_dump.c:18904 pg_dump.c:18942 pg_dumpall.c:1962 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "filtre %s pour « %s » n'est pas autorisé" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "dumpId %d invalide" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "dépendance invalide %d" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "n'a pas pu identifier la boucle de dépendance" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" -msgstr[0] "NOTE : il existe des constraintes de clés étrangères circulaires sur cette table :" -msgstr[1] "NOTE : il existe des constraintes de clés étrangères circulaires sur ces tables :" +msgstr[0] "NOTE : il existe des contraintes de clés étrangères circulaires sur cette table :" +msgstr[1] "NOTE : il existe des contraintes de clés étrangères circulaires sur ces tables :" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." -msgstr "Il est possible de restaurer la sauvegarde sans utiliser --disable-triggers ou sans supprimer temporairement les constraintes." +msgstr "Il est possible de restaurer la sauvegarde sans utiliser --disable-triggers ou sans supprimer temporairement les contraintes." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "Considérez l'utilisation d'une sauvegarde complète au lieu d'une sauvegarde des données seulement pour éviter ce problème." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "n'a pas pu résoudre la boucle de dépendances parmi ces éléments :" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé dans le même répertoire que « %s »" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "le programme « %s » a été trouvé par « %s » mais n'est pas de la même version que %s" -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "l'option --exclude-database ne peut pas être utilisée avec -g/--globals-only, -r/--roles-only ou -t/--tablespaces-only" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "les options « -g/--globals-only » et « -r/--roles-only » ne peuvent pas être utilisées ensemble" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "les options « -g/--globals-only » et « -t/--tablespaces-only » ne peuvent pas être utilisées ensemble" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "les options « -r/--roles-only » et « -t/--tablespaces-only » ne peuvent pas être utilisées ensemble" -#: pg_dumpall.c:469 pg_dumpall.c:1750 +#: pg_dumpall.c:474 pg_dumpall.c:1771 #, c-format msgid "could not connect to database \"%s\"" msgstr "n'a pas pu se connecter à la base de données « %s »" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2432,7 +2586,7 @@ msgstr "" "n'a pas pu se connecter aux bases « postgres » et « template1 ».\n" "Merci de préciser une autre base de données." -#: pg_dumpall.c:629 +#: pg_dumpall.c:634 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2442,57 +2596,57 @@ msgstr "" "commandes SQL.\n" "\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:636 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPTION]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:639 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=FICHIER nom du fichier de sortie\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:646 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr "" " -c, --clean nettoie (supprime) les bases de données avant de\n" " les créer\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:648 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr "" " -g, --globals-only sauvegarde uniquement les objets système, pas\n" " le contenu des bases de données\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:649 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner omet la restauration des propriétaires des objets\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:650 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr "" " -r, --roles-only sauvegarde uniquement les rôles, pas les bases\n" " de données ni les tablespaces\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:652 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr "" " -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" " avec le format texte\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:653 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr "" " -t, --tablespaces-only sauvegarde uniquement les tablespaces, pas les\n" " bases de données ni les rôles\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:659 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr "" @@ -2501,20 +2655,25 @@ msgstr "" #: pg_dumpall.c:661 #, c-format +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr " -f, --file=FICHIER exclut les bases indiquées sous forme d'expressions dans FICHIER\n" + +#: pg_dumpall.c:667 +#, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords ne sauvegarde pas les mots de passe des rôles\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:683 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=CHAINE_CONNEX connexion à l'aide de la chaîne de connexion\n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:685 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=BASE indique une autre base par défaut\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:692 #, c-format msgid "" "\n" @@ -2527,97 +2686,106 @@ msgstr "" "standard.\n" "\n" -#: pg_dumpall.c:828 +#: pg_dumpall.c:837 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "nom de rôle commençant par « pg_ » ignoré (« %s »)" -#: pg_dumpall.c:1050 +#: pg_dumpall.c:1059 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "n'a pas pu trouver un ordre de sauvegarde correct pour les appartenances au rôle « %s »" -#: pg_dumpall.c:1185 +#: pg_dumpall.c:1194 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "n'a pas pu analyser la liste d'ACL (%s) pour le paramètre « %s »" -#: pg_dumpall.c:1303 +#: pg_dumpall.c:1321 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "n'a pas pu analyser la liste d'ACL (%s) pour le tablespace « %s »" -#: pg_dumpall.c:1510 +#: pg_dumpall.c:1528 #, c-format msgid "excluding database \"%s\"" msgstr "exclusion de la base de données « %s »" -#: pg_dumpall.c:1514 +#: pg_dumpall.c:1532 #, c-format msgid "dumping database \"%s\"" msgstr "sauvegarde de la base de données « %s »" -#: pg_dumpall.c:1545 +#: pg_dumpall.c:1563 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "échec de pg_dump sur la base de données « %s », quitte" -#: pg_dumpall.c:1551 +#: pg_dumpall.c:1569 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "n'a pas pu ré-ouvrir le fichier de sortie « %s » : %m" -#: pg_dumpall.c:1592 +#: pg_dumpall.c:1613 #, c-format msgid "running \"%s\"" msgstr "exécute « %s »" -#: pg_dumpall.c:1793 +#: pg_dumpall.c:1814 #, c-format msgid "could not get server version" msgstr "n'a pas pu obtenir la version du serveur" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1817 #, c-format msgid "could not parse server version \"%s\"" msgstr "n'a pas pu analyser la version du serveur « %s »" -#: pg_dumpall.c:1866 pg_dumpall.c:1889 +#: pg_dumpall.c:1887 pg_dumpall.c:1910 #, c-format msgid "executing %s" msgstr "exécution %s" -#: pg_restore.c:313 +#: pg_dumpall.c:1982 +msgid "unsupported filter object" +msgstr "objet de filtre non supporté" + +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "une seule des options -d/--dbname and -f/--file peut être indiquée" -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "les options « -d/--dbname » et « -f/--file » ne peuvent pas être utilisées ensemble" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "options -1/--single-transaction and --transaction-size cannot be used together" +msgstr "les options -1/--single-transaction » et --transaction-size ne peuvent pas être utilisées ensemble" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "les options « -C/--create » et « -1/--single-transaction » ne peuvent pas être utilisées ensemble" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "ne peut pas spécifier à la fois l'option --single-transaction et demander plusieurs jobs" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "format d'archive « %s » non reconnu ; merci d'indiquer « c », « d » ou « t »" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "erreurs ignorées lors de la restauration : %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2627,51 +2795,51 @@ msgstr "" "par pg_dump.\n" "\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [OPTION]... [FICHIER]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr "" " -d, --dbname=NOM nom de la base de données utilisée pour la\n" " connexion\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FICHIER nom du fichier de sortie (- pour stdout)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr "" " -F, --format=c|d|t format du fichier de sauvegarde (devrait être\n" " automatique)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list affiche la table des matières de l'archive (TOC)\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose mode verbeux\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "" "\n" @@ -2680,34 +2848,34 @@ msgstr "" "\n" "Options contrôlant la restauration :\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only restaure uniquement les données, pas la structure\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create crée la base de données cible\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error quitte en cas d'erreur, continue par défaut\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NOM restaure l'index indiqué\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr "" " -j, --jobs=NOMBRE utilise ce nombre de jobs en parallèle pour la\n" " restauration\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2716,66 +2884,75 @@ msgstr "" " -L, --use-list=FICHIER utilise la table des matières à partir de ce\n" " fichier pour sélectionner/trier la sortie\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NOM restaure uniquement les objets de ce schéma\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NOM ne restaure pas les objets de ce schéma\n" -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NOM(args) restaure la fonction indiquée\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only restaure uniquement la structure, pas les données\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr "" " -S, --superuser=NOM indique le nom du super-utilisateur à utiliser\n" " pour désactiver les triggers\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NOM restaure la relation indiquée (table, vue, etc)\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NOM restaure le trigger indiqué\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr "" " -x, --no-privileges omet la restauration des droits sur les objets\n" " (grant/revoke)\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction restaure dans une seule transaction\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security active la sécurité niveau ligne\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid "" +" --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr "" +" --filter=NOMFICHIER restaure ou ignore les objets suivant des expressions\n" +" dans NOMFICHIER\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments ne restaure pas les commentaires\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" @@ -2784,44 +2961,49 @@ msgstr "" " --no-data-for-failed-tables ne restaure pas les données des tables qui n'ont\n" " pas pu être créées\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications ne restaure pas les publications\n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels ne restaure pas les labels de sécurité\n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions ne restaure pas les souscriptions\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method ne restaure pas les méthodes d'accès aux tables\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces ne restaure pas les affectations de tablespaces\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr "" " --section=SECTION restaure la section indiquée (pre-data, data ou\n" " post-data)\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr " --transaction-size=N valide après N objets\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=RÔLE exécute SET ROLE avant la restauration\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "" "\n" @@ -2832,7 +3014,7 @@ msgstr "" "Les options -I, -n, -N, -P, -t, -T et --section peuvent être combinées et\n" "indiquées plusieurs fois pour sélectionner plusieurs objets.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "" "\n" @@ -2843,755 +3025,3 @@ msgstr "" "Si aucun nom de fichier n'est fourni en entrée, alors l'entrée standard est\n" "utilisée.\n" "\n" - -#, c-format -#~ msgid " %s" -#~ msgstr " %s" - -#~ msgid " --disable-triggers disable triggers during data-only restore\n" -#~ msgstr "" -#~ " --disable-triggers désactiver les déclencheurs lors de la\n" -#~ " restauration des données seules\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide puis quitte\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#, c-format -#~ msgid " --no-synchronized-snapshots do not use synchronized snapshots in parallel jobs\n" -#~ msgstr "" -#~ " --no-synchronized-snapshots n'utilise pas de snapshots synchronisés pour les\n" -#~ " jobs en parallèle\n" - -#~ msgid "" -#~ " --use-set-session-authorization\n" -#~ " use SET SESSION AUTHORIZATION commands instead of\n" -#~ " ALTER OWNER commands to set ownership\n" -#~ msgstr "" -#~ " --use-set-session-authorization\n" -#~ " utilise les commandes SET SESSION AUTHORIZATION\n" -#~ " au lieu des commandes ALTER OWNER pour les\n" -#~ " modifier les propriétaires\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version puis quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid " -O, --no-owner skip restoration of object ownership\n" -#~ msgstr "" -#~ " -O, --no-owner omettre la restauration des possessions des\n" -#~ " objets\n" - -#, c-format -#~ msgid " -Z, --compress=0-9 compression level for compressed formats\n" -#~ msgstr "" -#~ " -Z, --compress=0-9 niveau de compression pour les formats\n" -#~ " compressés\n" - -#~ msgid " -c, --clean clean (drop) database objects before recreating\n" -#~ msgstr "" -#~ " -c, --clean nettoie/supprime les bases de données avant de\n" -#~ " les créer\n" - -#~ msgid " -o, --oids include OIDs in dump\n" -#~ msgstr " -o, --oids inclut les OID dans la sauvegarde\n" - -#~ msgid "%s: could not connect to database \"%s\": %s" -#~ msgstr "%s : n'a pas pu se connecter à la base de données « %s » : %s" - -#~ msgid "%s: could not open the output file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier de sauvegarde « %s » : %s\n" - -#~ msgid "%s: could not parse ACL list (%s) for database \"%s\"\n" -#~ msgstr "%s : n'a pas pu analyser la liste d'ACL (%s) pour la base de données « %s »\n" - -#~ msgid "%s: could not parse version \"%s\"\n" -#~ msgstr "%s : n'a pas pu analyser la version « %s »\n" - -#~ msgid "%s: executing %s\n" -#~ msgstr "%s : exécute %s\n" - -#~ msgid "%s: invalid -X option -- %s\n" -#~ msgstr "%s : option -X invalide -- %s\n" - -#~ msgid "%s: invalid client encoding \"%s\" specified\n" -#~ msgstr "%s : encodage client indiqué (« %s ») invalide\n" - -#~ msgid "%s: invalid number of parallel jobs\n" -#~ msgstr "%s : nombre de jobs en parallèle invalide\n" - -#~ msgid "%s: option --if-exists requires option -c/--clean\n" -#~ msgstr "%s : l'option --if-exists nécessite l'option -c/--clean\n" - -#~ msgid "%s: options -c/--clean and -a/--data-only cannot be used together\n" -#~ msgstr "" -#~ "%s : les options « -c/--clean » et « -a/--data-only » ne peuvent pas être\n" -#~ "utilisées conjointement\n" - -#~ msgid "%s: options -s/--schema-only and -a/--data-only cannot be used together\n" -#~ msgstr "" -#~ "%s : les options « -s/--schema-only » et « -a/--data-only » ne peuvent pas être\n" -#~ "utilisées conjointement\n" - -#~ msgid "%s: out of memory\n" -#~ msgstr "%s : mémoire épuisée\n" - -#~ msgid "%s: query failed: %s" -#~ msgstr "%s : échec de la requête : %s" - -#~ msgid "%s: query was: %s\n" -#~ msgstr "%s : la requête était : %s\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "(The INSERT command cannot set OIDs.)\n" -#~ msgstr "(La commande INSERT ne peut pas positionner les OID.)\n" - -#~ msgid "*** aborted because of error\n" -#~ msgstr "*** interrompu du fait d'erreurs\n" - -#~ msgid "-C and -1 are incompatible options\n" -#~ msgstr "-C et -1 sont des options incompatibles\n" - -#~ msgid "-C and -c are incompatible options\n" -#~ msgstr "-C et -c sont des options incompatibles\n" - -#~ msgid "LOCK TABLE failed for \"%s\": %s" -#~ msgstr "LOCK TABLE échoué pour la table « %s » : %s" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#~ msgid "SQL command failed\n" -#~ msgstr "la commande SQL a échoué\n" - -#, c-format -#~ msgid "" -#~ "Synchronized snapshots are not supported by this server version.\n" -#~ "Run with --no-synchronized-snapshots instead if you do not need\n" -#~ "synchronized snapshots." -#~ msgstr "" -#~ "Les snapshots synchronisés ne sont pas supportés par cette version serveur.\n" -#~ "Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" -#~ "de snapshots synchronisés." - -#~ msgid "" -#~ "Synchronized snapshots are not supported on standby servers.\n" -#~ "Run with --no-synchronized-snapshots instead if you do not need\n" -#~ "synchronized snapshots.\n" -#~ msgstr "" -#~ "Les snapshots synchronisés ne sont pas supportés sur les serveurs de stadby.\n" -#~ "Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" -#~ "de snapshots synchronisés.\n" - -#, c-format -#~ msgid "" -#~ "Synchronized snapshots on standby servers are not supported by this server version.\n" -#~ "Run with --no-synchronized-snapshots instead if you do not need\n" -#~ "synchronized snapshots." -#~ msgstr "" -#~ "Les snapshots synchronisés sur les serveurs standbys ne sont pas supportés par cette version serveur.\n" -#~ "Lancez avec --no-synchronized-snapshots à la place si vous n'avez pas besoin\n" -#~ "de snapshots synchronisés." - -#~ msgid "TOC Entry %s at %s (length %s, checksum %d)\n" -#~ msgstr "entrée TOC %s à %s (longueur %s, somme de contrôle %d)\n" - -#, c-format -#~ msgid "The command was: %s" -#~ msgstr "La commande était : %s" - -#~ msgid "" -#~ "The program \"pg_dump\" is needed by %s but was not found in the\n" -#~ "same directory as \"%s\".\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « pg_dump » est nécessaire à %s mais n'a pas été trouvé dans le\n" -#~ "même répertoire que « %s ».\n" -#~ "Vérifiez votre installation." - -#~ msgid "" -#~ "The program \"pg_dump\" was found by \"%s\"\n" -#~ "but was not the same version as %s.\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « pg_dump » a été trouvé par « %s »\n" -#~ "mais n'a pas la même version que %s.\n" -#~ "Vérifiez votre installation." - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#~ msgid "" -#~ "WARNING:\n" -#~ " This format is for demonstration purposes; it is not intended for\n" -#~ " normal use. Files will be written in the current working directory.\n" -#~ msgstr "" -#~ "ATTENTION :\n" -#~ " Ce format est présent dans un but de démonstration ; il n'est pas prévu\n" -#~ " pour une utilisation normale. Les fichiers seront écrits dans le\n" -#~ " répertoire actuel.\n" - -#~ msgid "WARNING: could not parse reloptions array\n" -#~ msgstr "ATTENTION : n'a pas pu analyser le tableau reloptions\n" - -#~ msgid "WSAStartup failed: %d" -#~ msgstr "WSAStartup a échoué : %d" - -#~ msgid "aggregate function %s could not be dumped correctly for this database version; ignored" -#~ msgstr "la fonction d'aggrégat %s n'a pas pu être sauvegardée correctement avec cette version de la base de données ; ignorée" - -#~ msgid "allocating AH for %s, format %d\n" -#~ msgstr "allocation d'AH pour %s, format %d\n" - -#~ msgid "archive member too large for tar format\n" -#~ msgstr "membre de l'archive trop volumineux pour le format tar\n" - -#~ msgid "archiver" -#~ msgstr "archiveur" - -#~ msgid "archiver (db)" -#~ msgstr "programme d'archivage (db)" - -#~ msgid "attempting to ascertain archive format\n" -#~ msgstr "tentative d'identification du format de l'archive\n" - -#, c-format -#~ msgid "bogus value in proargmodes array" -#~ msgstr "valeur erronée dans le tableau proargmodes" - -#~ msgid "cannot duplicate null pointer\n" -#~ msgstr "ne peut pas dupliquer un pointeur nul\n" - -#~ msgid "cannot reopen non-seekable file\n" -#~ msgstr "ne peut pas rouvrir le fichier non cherchable\n" - -#~ msgid "cannot reopen stdin\n" -#~ msgstr "ne peut pas rouvrir stdin\n" - -#, c-format -#~ msgid "cannot restore from compressed archive (compression not supported in this installation)" -#~ msgstr "ne peut pas restaurer à partir de l'archive compressée (compression indisponible dans cette installation)" - -#~ msgid "child process was terminated by signal %d" -#~ msgstr "le processus fils a été terminé par le signal %d" - -#~ msgid "child process was terminated by signal %s" -#~ msgstr "le processus fils a été terminé par le signal %s" - -#~ msgid "compress_io" -#~ msgstr "compression_io" - -#, c-format -#~ msgid "compression level must be in range 0..9" -#~ msgstr "le niveau de compression doit être compris entre 0 et 9" - -#~ msgid "compression support is disabled in this format\n" -#~ msgstr "le support de la compression est désactivé avec ce format\n" - -#~ msgid "connecting to database \"%s\" as user \"%s\"" -#~ msgstr "connexion à la base de données « %s » en tant qu'utilisateur « %s »" - -#~ msgid "connection needs password" -#~ msgstr "la connexion nécessite un mot de passe" - -#~ msgid "connection to database \"%s\" failed: %s" -#~ msgstr "la connexion à la base de données « %s » a échoué : %s" - -#~ msgid "could not change directory to \"%s\"" -#~ msgstr "n'a pas pu accéder au répertoire « %s »" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %m" - -#~ msgid "could not change directory to \"%s\": %s" -#~ msgstr "n'a pas pu changer le répertoire par « %s » : %s" - -#, c-format -#~ msgid "could not close blob data file: %m" -#~ msgstr "n'a pas pu fermer le fichier de données blob : %m" - -#, c-format -#~ msgid "could not close blobs TOC file: %m" -#~ msgstr "n'a pas pu fermer le fichier TOC des blobs : %m" - -#~ msgid "could not close data file after reading\n" -#~ msgstr "n'a pas pu fermer le fichier de données après lecture\n" - -#~ msgid "could not close directory \"%s\": %s\n" -#~ msgstr "n'a pas pu fermer le répertoire « %s » : %s\n" - -#~ msgid "could not close large object file\n" -#~ msgstr "n'a pas pu fermer le fichier du « Large Object »\n" - -#, c-format -#~ msgid "could not close tar member: %m" -#~ msgstr "n'a pas pu fermer le membre de tar : %m" - -#~ msgid "could not connect to database \"%s\": %s" -#~ msgstr "n'a pas pu se connecter à la base de données « %s » : %s" - -#~ msgid "could not create directory \"%s\": %s\n" -#~ msgstr "n'a pas pu créer le répertoire « %s » : %s\n" - -#~ msgid "could not create worker thread: %s\n" -#~ msgstr "n'a pas pu créer le fil de travail: %s\n" - -#~ msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to lack of data offsets in archive" -#~ msgstr "" -#~ "n'a pas pu trouver l'identifiant de bloc %d dans l'archive --\n" -#~ "il est possible que cela soit dû à une demande de restauration dans un ordre\n" -#~ "différent, qui n'a pas pu être géré à cause d'un manque d'information de\n" -#~ "position dans l'archive" - -#~ msgid "could not find entry for pg_indexes in pg_class\n" -#~ msgstr "n'a pas pu trouver l'entrée de pg_indexes dans pg_class\n" - -#~ msgid "could not find slot of finished worker\n" -#~ msgstr "n'a pas pu trouver l'emplacement du worker qui vient de terminer\n" - -#~ msgid "could not get relation name for OID %u: %s\n" -#~ msgstr "n'a pas pu obtenir le nom de la relation pour l'OID %u: %s\n" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "n'a pas pu identifier le répertoire courant : %m" - -#~ msgid "could not identify current directory: %s" -#~ msgstr "n'a pas pu identifier le répertoire courant : %s" - -#~ msgid "could not open large object TOC for input: %s\n" -#~ msgstr "n'a pas pu ouvrir la TOC du « Large Object » en entrée : %s\n" - -#~ msgid "could not open large object TOC for output: %s\n" -#~ msgstr "n'a pas pu ouvrir la TOC du « Large Object » en sortie : %s\n" - -#~ msgid "could not open output file \"%s\" for writing\n" -#~ msgstr "n'a pas pu ouvrir le fichier de sauvegarde « %s » en écriture\n" - -#, c-format -#~ msgid "could not open temporary file" -#~ msgstr "n'a pas pu ouvrir le fichier temporaire" - -#~ msgid "could not output padding at end of tar member\n" -#~ msgstr "n'a pas pu remplir la fin du membre de tar\n" - -#~ msgid "could not parse ACL (%s) for large object %u" -#~ msgstr "n'a pas pu analyser la liste ACL (%s) du « Large Object » %u" - -#, c-format -#~ msgid "could not parse extension condition array" -#~ msgstr "n'a pas pu analyser le tableau de condition de l'extension" - -#, c-format -#~ msgid "could not parse extension configuration array" -#~ msgstr "n'a pas pu analyser le tableau de configuration des extensions" - -#~ msgid "could not parse index collation name array" -#~ msgstr "n'a pas pu analyser le tableau des noms de collation de l'index" - -#~ msgid "could not parse index collation version array" -#~ msgstr "n'a pas pu analyser le tableau des versions de collation de l'index" - -#, c-format -#~ msgid "could not parse proallargtypes array" -#~ msgstr "n'a pas pu analyser le tableau proallargtypes" - -#, c-format -#~ msgid "could not parse proargmodes array" -#~ msgstr "n'a pas pu analyser le tableau proargmodes" - -#, c-format -#~ msgid "could not parse proargnames array" -#~ msgstr "n'a pas pu analyser le tableau proargnames" - -#, c-format -#~ msgid "could not parse proconfig array" -#~ msgstr "n'a pas pu analyser le tableau proconfig" - -#, c-format -#~ msgid "could not parse subpublications array" -#~ msgstr "n'a pas pu analyser le tableau de sous-publications" - -#~ msgid "could not parse version string \"%s\"\n" -#~ msgstr "n'a pas pu analyser la chaîne de version « %s »\n" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "n'a pas pu lire le binaire « %s »" - -#~ msgid "could not read directory \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "could not read symbolic link \"%s\"" -#~ msgstr "n'a pas pu lire le lien symbolique « %s »" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" - -#~ msgid "could not reconnect to database" -#~ msgstr "n'a pas pu se reconnecter à la base de données" - -#~ msgid "could not reconnect to database: %s" -#~ msgstr "n'a pas pu se reconnecter à la base de données : %s" - -#~ msgid "could not set default_with_oids: %s" -#~ msgstr "n'a pas pu configurer default_with_oids : %s" - -#~ msgid "could not write byte\n" -#~ msgstr "n'a pas pu écrire l'octet\n" - -#~ msgid "could not write byte: %s\n" -#~ msgstr "n'a pas pu écrire un octet : %s\n" - -#~ msgid "could not write null block at end of tar archive\n" -#~ msgstr "n'a pas pu écrire le bloc nul à la fin de l'archive tar\n" - -#~ msgid "could not write to custom output routine\n" -#~ msgstr "n'a pas pu écrire vers la routine de sauvegarde personnalisée\n" - -#~ msgid "could not write to large object (result: %lu, expected: %lu)" -#~ msgstr "n'a pas pu écrire le « Large Object » (résultat : %lu, attendu : %lu)" - -#~ msgid "custom archiver" -#~ msgstr "programme d'archivage personnalisé" - -#~ msgid "directory archiver" -#~ msgstr "archiveur répertoire" - -#~ msgid "dumpBlobs(): could not open large object %u: %s" -#~ msgstr "dumpBlobs() : n'a pas pu ouvrir le « Large Object » %u : %s" - -#~ msgid "dumpDatabase(): could not find pg_largeobject.relfrozenxid\n" -#~ msgstr "dumpDatabase() : n'a pas pu trouver pg_largeobject.relfrozenxid\n" - -#~ msgid "dumpDatabase(): could not find pg_largeobject_metadata.relfrozenxid\n" -#~ msgstr "dumpDatabase() : n'a pas pu trouver pg_largeobject_metadata.relfrozenxid\n" - -#~ msgid "dumping a specific TOC data block out of order is not supported without ID on this input stream (fseek required)\n" -#~ msgstr "" -#~ "la sauvegarde d'un bloc de données spécifique du TOC dans le désordre n'est\n" -#~ "pas supporté sans identifiant sur ce flux d'entrée (fseek requis)\n" - -#~ msgid "entering restore_toc_entries_parallel\n" -#~ msgstr "entrée dans restore_toc_entries_parallel\n" - -#~ msgid "entering restore_toc_entries_postfork\n" -#~ msgstr "entrée dans restore_toc_entries_prefork\n" - -#~ msgid "entering restore_toc_entries_prefork\n" -#~ msgstr "entrée dans restore_toc_entries_prefork\n" - -#~ msgid "error during backup\n" -#~ msgstr "erreur lors de la sauvegarde\n" - -#~ msgid "error in ListenToWorkers(): %s\n" -#~ msgstr "erreur dans ListenToWorkers(): %s\n" - -#~ msgid "error processing a parallel work item\n" -#~ msgstr "erreur durant le traitement en parallèle d'un item\n" - -#, c-format -#~ msgid "extra_float_digits must be in range -15..3" -#~ msgstr "extra_float_digits doit être dans l'intervalle -15 à 3" - -#~ msgid "failed to connect to database\n" -#~ msgstr "n'a pas pu se connecter à la base de données\n" - -#~ msgid "failed to reconnect to database\n" -#~ msgstr "la reconnexion à la base de données a échoué\n" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "file archiver" -#~ msgstr "programme d'archivage de fichiers" - -#, c-format -#~ msgid "finding check constraints for table \"%s.%s\"" -#~ msgstr "recherche des contraintes de vérification pour la table « %s.%s »" - -#, c-format -#~ msgid "finding default expressions of table \"%s.%s\"" -#~ msgstr "recherche des expressions par défaut de la table « %s.%s »" - -#, c-format -#~ msgid "finding the columns and types of table \"%s.%s\"" -#~ msgstr "recherche des colonnes et types de la table « %s.%s »" - -#~ msgid "found more than one entry for pg_indexes in pg_class\n" -#~ msgstr "a trouvé plusieurs entrées pour pg_indexes dans la table pg_class\n" - -#~ msgid "found more than one pg_database entry for this database\n" -#~ msgstr "a trouvé plusieurs entrées dans pg_database pour cette base de données\n" - -#~ msgid "ftell mismatch with expected position -- ftell used" -#~ msgstr "ftell ne correspond pas à la position attendue -- ftell utilisé" - -#~ msgid "internal error -- neither th nor fh specified in _tarReadRaw()" -#~ msgstr "erreur interne -- ni th ni fh ne sont précisés dans _tarReadRaw()" - -#~ msgid "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n" -#~ msgstr "instruction COPY invalide -- n'a pas pu trouver « copy » dans la chaîne « %s »\n" - -#~ msgid "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n" -#~ msgstr "" -#~ "instruction COPY invalide -- n'a pas pu trouver « from stdin » dans la\n" -#~ "chaîne « %s » à partir de la position %lu\n" - -#~ msgid "invalid TOASTCOMPRESSION item: %s" -#~ msgstr "élément TOASTCOMPRESSION invalide : %s" - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "binaire « %s » invalide" - -#, c-format -#~ msgid "invalid compression code: %d" -#~ msgstr "code de compression invalide : %d" - -#, c-format -#~ msgid "invalid number of parallel jobs" -#~ msgstr "nombre de jobs parallèles invalide" - -#, c-format -#~ msgid "maximum number of parallel jobs is %d" -#~ msgstr "le nombre maximum de jobs en parallèle est %d" - -#~ msgid "mismatch in actual vs. predicted file position (%s vs. %s)\n" -#~ msgstr "" -#~ "pas de correspondance entre la position réelle et celle prévue du fichier\n" -#~ "(%s vs. %s)\n" - -#~ msgid "mismatched number of collation names and versions for index" -#~ msgstr "nombre différent de noms et versions de collation pour l'index" - -#~ msgid "missing pg_database entry for database \"%s\"\n" -#~ msgstr "entrée manquante dans pg_database pour la base de données « %s »\n" - -#~ msgid "missing pg_database entry for this database\n" -#~ msgstr "entrée pg_database manquante pour cette base de données\n" - -#~ msgid "moving from position %s to next member at file position %s\n" -#~ msgstr "déplacement de la position %s vers le prochain membre à la position %s du fichier\n" - -#~ msgid "no item ready\n" -#~ msgstr "aucun élément prêt\n" - -#~ msgid "no label definitions found for enum ID %u\n" -#~ msgstr "aucune définition de label trouvée pour l'ID enum %u\n" - -#, c-format -#~ msgid "not built with zlib support" -#~ msgstr "pas construit avec le support de zlib" - -#~ msgid "now at file position %s\n" -#~ msgstr "maintenant en position %s du fichier\n" - -#~ msgid "option --index-collation-versions-unknown only works in binary upgrade mode" -#~ msgstr "l'option --index-collation-versions-unknown fonctionne seulement dans le mode de mise à jour binaire" - -#~ msgid "options --inserts/--column-inserts and -o/--oids cannot be used together\n" -#~ msgstr "" -#~ "les options « --inserts/--column-inserts » et « -o/--oids » ne\n" -#~ "peuvent pas être utilisées conjointement\n" - -#, c-format -#~ msgid "owner of aggregate function \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la fonction d'agrégat « %s » semble être invalide" - -#, c-format -#~ msgid "owner of data type \"%s\" appears to be invalid" -#~ msgstr "le propriétaire du type de données « %s » semble être invalide" - -#, c-format -#~ msgid "owner of function \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la fonction « %s » semble être invalide" - -#, c-format -#~ msgid "owner of operator \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de l'opérateur « %s » semble être invalide" - -#, c-format -#~ msgid "owner of operator class \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la classe d'opérateur « %s » semble être invalide" - -#, c-format -#~ msgid "owner of operator family \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la famille d'opérateur « %s » semble être invalide" - -#, c-format -#~ msgid "owner of publication \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la publication « %s » semble être invalide" - -#, c-format -#~ msgid "owner of schema \"%s\" appears to be invalid" -#~ msgstr "le propriétaire du schéma « %s » semble être invalide" - -#, c-format -#~ msgid "owner of subscription \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la souscription « %s » semble être invalide" - -#, c-format -#~ msgid "owner of table \"%s\" appears to be invalid" -#~ msgstr "le propriétaire de la table « %s » semble être invalide" - -#~ msgid "parallel archiver" -#~ msgstr "archiveur en parallèle" - -#~ msgid "parallel_restore should not return\n" -#~ msgstr "parallel_restore ne devrait pas retourner\n" - -#~ msgid "pclose failed: %m" -#~ msgstr "échec de pclose : %m" - -#~ msgid "pclose failed: %s" -#~ msgstr "échec de pclose : %s" - -#~ msgid "query returned %d foreign server entry for foreign table \"%s\"\n" -#~ msgid_plural "query returned %d foreign server entries for foreign table \"%s\"\n" -#~ msgstr[0] "la requête a renvoyé %d entrée de serveur distant pour la table distante « %s »\n" -#~ msgstr[1] "la requête a renvoyé %d entrées de serveurs distants pour la table distante « %s »\n" - -#~ msgid "query returned %d row instead of one: %s\n" -#~ msgid_plural "query returned %d rows instead of one: %s\n" -#~ msgstr[0] "la requête a renvoyé %d ligne au lieu d'une seule : %s\n" -#~ msgstr[1] "la requête a renvoyé %d lignes au lieu d'une seule : %s\n" - -#~ msgid "query returned %d rows instead of one: %s\n" -#~ msgstr "la requête a renvoyé %d lignes au lieu d'une seule : %s\n" - -#~ msgid "query returned more than one (%d) pg_database entry for database \"%s\"\n" -#~ msgstr "" -#~ "la requête a renvoyé plusieurs (%d) entrées pg_database pour la base de\n" -#~ "données « %s »\n" - -#~ msgid "query returned no rows: %s\n" -#~ msgstr "la requête n'a renvoyé aucune ligne : %s\n" - -#~ msgid "query to get data of sequence \"%s\" returned name \"%s\"\n" -#~ msgstr "" -#~ "la requête permettant d'obtenir les données de la séquence « %s » a renvoyé\n" -#~ "le nom « %s »\n" - -#~ msgid "query was: %s\n" -#~ msgstr "la requête était : %s\n" - -#~ msgid "read %lu byte into lookahead buffer\n" -#~ msgid_plural "read %lu bytes into lookahead buffer\n" -#~ msgstr[0] "lecture de %lu octet dans le tampon prévisionnel\n" -#~ msgstr[1] "lecture de %lu octets dans le tampon prévisionnel\n" - -#~ msgid "read TOC entry %d (ID %d) for %s %s\n" -#~ msgstr "lecture de l'entrée %d de la TOC (ID %d) pour %s %s\n" - -#~ msgid "reading extended statistics for table \"%s.%s\"\n" -#~ msgstr "lecture des statistiques étendues pour la table « %s.%s »\n" - -#, c-format -#~ msgid "reading foreign key constraints for table \"%s.%s\"" -#~ msgstr "lecture des contraintes de clés étrangères pour la table « %s.%s »" - -#, c-format -#~ msgid "reading indexes for table \"%s.%s\"" -#~ msgstr "lecture des index de la table « %s.%s »" - -#~ msgid "reading policies for table \"%s.%s\"" -#~ msgstr "lecture des politiques pour la table « %s.%s »" - -#~ msgid "reading row security enabled for table \"%s.%s\"" -#~ msgstr "lecture de l'activation de la sécurité niveau ligne pour la table « %s.%s »" - -#, c-format -#~ msgid "reading triggers for table \"%s.%s\"" -#~ msgstr "lecture des triggers pour la table « %s.%s »" - -#~ msgid "reconnection to database \"%s\" failed: %s" -#~ msgstr "reconnexion à la base de données « %s » échouée : %s" - -#~ msgid "reducing dependencies for %d\n" -#~ msgstr "réduction des dépendances pour %d\n" - -#~ msgid "requested %d byte, got %d from lookahead and %d from file\n" -#~ msgid_plural "requested %d bytes, got %d from lookahead and %d from file\n" -#~ msgstr[0] "%d octet requis, %d obtenu de « lookahead » et %d du fichier\n" -#~ msgstr[1] "%d octets requis, %d obtenus de « lookahead » et %d du fichier\n" - -#, c-format -#~ msgid "requested compression not available in this installation -- archive will be uncompressed" -#~ msgstr "la compression requise n'est pas disponible avec cette installation -- l'archive ne sera pas compressée" - -#~ msgid "restoring large object OID %u\n" -#~ msgstr "restauration du « Large Object » d'OID %u\n" - -#, c-format -#~ msgid "rows-per-insert must be in range %d..%d" -#~ msgstr "le nombre de lignes par insertion doit être compris entre %d et %d" - -#~ msgid "saving default_toast_compression = %s" -#~ msgstr "sauvegarde de default_toast_compression = %s" - -#~ msgid "saving large object properties\n" -#~ msgstr "sauvegarde des propriétés des « Large Objects »\n" - -#~ msgid "schema with OID %u does not exist\n" -#~ msgstr "le schéma d'OID %u n'existe pas\n" - -#~ msgid "select() failed: %m" -#~ msgstr "échec de select() : %m" - -#~ msgid "select() failed: %s\n" -#~ msgstr "échec de select() : %s\n" - -#~ msgid "server version must be at least 7.3 to use schema selection switches\n" -#~ msgstr "" -#~ "le serveur doit être de version 7.3 ou supérieure pour utiliser les options\n" -#~ "de sélection du schéma\n" - -#~ msgid "setting owner and privileges for %s \"%s\"\n" -#~ msgstr "réglage du propriétaire et des droits pour %s « %s »\n" - -#~ msgid "setting owner and privileges for %s \"%s.%s\"\n" -#~ msgstr "réglage du propriétaire et des droits pour %s « %s.%s»\n" - -#~ msgid "skipping tar member %s\n" -#~ msgstr "omission du membre %s du tar\n" - -#~ msgid "sorter" -#~ msgstr "tri" - -#~ msgid "tar archiver" -#~ msgstr "archiveur tar" - -#~ msgid "terminated by user\n" -#~ msgstr "terminé par l'utilisateur\n" - -#~ msgid "transferring dependency %d -> %d to %d\n" -#~ msgstr "transfert de la dépendance %d -> %d vers %d\n" - -#~ msgid "unexpected end of file\n" -#~ msgstr "fin de fichier inattendu\n" - -#~ msgid "unrecognized collation provider: %s\n" -#~ msgstr "fournisseur de collationnement non reconnu : %s\n" - -#~ msgid "unrecognized command on communication channel: %s\n" -#~ msgstr "commande inconnue sur le canal de communucation: %s\n" - -#~ msgid "worker is terminating\n" -#~ msgstr "le worker est en cours d'arrêt\n" - -#~ msgid "worker process crashed: status %d\n" -#~ msgstr "crash du processus worker : statut %d\n" diff --git a/src/bin/pg_dump/po/ja.po b/src/bin/pg_dump/po/ja.po index 5cb951737212d..0b0dbacaffa92 100644 --- a/src/bin/pg_dump/po/ja.po +++ b/src/bin/pg_dump/po/ja.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_dump (PostgreSQL 17)\n" +"Project-Id-Version: pg_dump (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-21 09:58+0900\n" -"PO-Revision-Date: 2024-06-21 10:18+0900\n" +"POT-Creation-Date: 2025-04-14 09:41+0900\n" +"PO-Revision-Date: 2025-04-14 10:24+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -22,29 +22,29 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " #: ../../common/compression.c:132 ../../common/compression.c:141 #: ../../common/compression.c:150 compress_gzip.c:413 compress_gzip.c:420 -#: compress_io.c:109 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 +#: compress_io.c:108 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 #: compress_zstd.c:31 #, c-format msgid "this build does not support compression with %s" @@ -114,27 +114,27 @@ msgstr "実行する\"%s\"がありませんでした" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "パス\"%s\"を絶対パス形式に変換できませんでした: %m" -#: ../../common/exec.c:382 +#: ../../common/exec.c:363 #, c-format msgid "could not execute command \"%s\": %m" msgstr "コマンド\"%s\"を実行できませんでした: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "コマンド\"%s\"から読み取れませんでした: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "コマンド\"%s\"がデータを返却しませんでした" -#: ../../common/exec.c:424 parallel.c:1609 +#: ../../common/exec.c:405 parallel.c:1621 #, c-format msgid "%s() failed: %m" msgstr "%s() が失敗しました: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 msgid "out of memory" msgstr "メモリ不足です" @@ -149,45 +149,44 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null ポインタを複製できません(内部エラー)。\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 dumputils.c:905 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 -#: pg_backup_directory.c:182 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -237,242 +236,242 @@ msgstr "%sは%d..%dの範囲でなければなりません" msgid "unrecognized sync method: %s" msgstr "認識できない同期方式: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: common.c:135 +#: common.c:111 #, c-format msgid "reading extensions" msgstr "機能拡張を読み込んでいます" -#: common.c:138 +#: common.c:114 #, c-format msgid "identifying extension members" msgstr "機能拡張の構成要素を特定しています" -#: common.c:141 +#: common.c:117 #, c-format msgid "reading schemas" msgstr "スキーマを読み込んでいます" -#: common.c:150 +#: common.c:126 #, c-format msgid "reading user-defined tables" msgstr "ユーザー定義テーブルを読み込んでいます" -#: common.c:155 +#: common.c:131 #, c-format msgid "reading user-defined functions" msgstr "ユーザー定義関数を読み込んでいます" -#: common.c:159 +#: common.c:135 #, c-format msgid "reading user-defined types" msgstr "ユーザー定義型を読み込んでいます" -#: common.c:163 +#: common.c:139 #, c-format msgid "reading procedural languages" msgstr "手続き言語を読み込んでいます" -#: common.c:166 +#: common.c:142 #, c-format msgid "reading user-defined aggregate functions" msgstr "ユーザー定義集約関数を読み込んでいます" -#: common.c:169 +#: common.c:145 #, c-format msgid "reading user-defined operators" msgstr "ユーザー定義演算子を読み込んでいます" -#: common.c:172 +#: common.c:148 #, c-format msgid "reading user-defined access methods" msgstr "ユーザー定義アクセスメソッドを読み込んでいます" -#: common.c:175 +#: common.c:151 #, c-format msgid "reading user-defined operator classes" msgstr "ユーザー定義演算子クラスを読み込んでいます" -#: common.c:178 +#: common.c:154 #, c-format msgid "reading user-defined operator families" msgstr "ユーザー定義演算子族を読み込んでいます" -#: common.c:181 +#: common.c:157 #, c-format msgid "reading user-defined text search parsers" msgstr "ユーザー定義のテキスト検索パーサを読み込んでいます" -#: common.c:184 +#: common.c:160 #, c-format msgid "reading user-defined text search templates" msgstr "ユーザー定義のテキスト検索テンプレートを読み込んでいます" -#: common.c:187 +#: common.c:163 #, c-format msgid "reading user-defined text search dictionaries" msgstr "ユーザー定義のテキスト検索辞書を読み込んでいます" -#: common.c:190 +#: common.c:166 #, c-format msgid "reading user-defined text search configurations" msgstr "ユーザー定義のテキスト検索設定を読み込んでいます" -#: common.c:193 +#: common.c:169 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "ユーザー定義の外部データラッパーを読み込んでいます" -#: common.c:196 +#: common.c:172 #, c-format msgid "reading user-defined foreign servers" msgstr "ユーザー定義の外部サーバーを読み込んでいます" -#: common.c:199 +#: common.c:175 #, c-format msgid "reading default privileges" msgstr "デフォルト権限設定を読み込んでいます" -#: common.c:202 +#: common.c:178 #, c-format msgid "reading user-defined collations" msgstr "ユーザー定義の照合順序を読み込んでいます" -#: common.c:205 +#: common.c:181 #, c-format msgid "reading user-defined conversions" msgstr "ユーザー定義の変換を読み込んでいます" -#: common.c:208 +#: common.c:184 #, c-format msgid "reading type casts" msgstr "型キャストを読み込んでいます" -#: common.c:211 +#: common.c:187 #, c-format msgid "reading transforms" msgstr "変換を読み込んでいます" -#: common.c:214 +#: common.c:190 #, c-format msgid "reading table inheritance information" msgstr "テーブル継承情報を読み込んでいます" -#: common.c:217 +#: common.c:193 #, c-format msgid "reading event triggers" msgstr "イベントトリガを読み込んでいます" -#: common.c:221 +#: common.c:197 #, c-format msgid "finding extension tables" msgstr "機能拡張構成テーブルを探しています" -#: common.c:225 +#: common.c:201 #, c-format msgid "finding inheritance relationships" msgstr "継承関係を検索しています" -#: common.c:228 +#: common.c:204 #, c-format msgid "reading column info for interesting tables" msgstr "対象テーブルの列情報を読み込んでいます" -#: common.c:231 +#: common.c:207 #, c-format msgid "flagging inherited columns in subtables" msgstr "子テーブルの継承列にフラグを設定しています" -#: common.c:234 +#: common.c:210 #, c-format msgid "reading partitioning data" msgstr "パーティション情報を読み込んでいます" -#: common.c:237 +#: common.c:213 #, c-format msgid "reading indexes" msgstr "インデックスを読み込んでいます" -#: common.c:240 +#: common.c:216 #, c-format msgid "flagging indexes in partitioned tables" msgstr "パーティション親テーブルのインデックスにフラグを設定しています" -#: common.c:243 +#: common.c:219 #, c-format msgid "reading extended statistics" msgstr "拡張統計情報を読み込んでいます" -#: common.c:246 +#: common.c:222 #, c-format msgid "reading constraints" msgstr "制約を読み込んでいます" -#: common.c:249 +#: common.c:225 #, c-format msgid "reading triggers" msgstr "トリガを読み込んでいます" -#: common.c:252 +#: common.c:228 #, c-format msgid "reading rewrite rules" msgstr "書き換えルールを読み込んでいます" -#: common.c:255 +#: common.c:231 #, c-format msgid "reading policies" msgstr "ポリシを読み込んでいます" -#: common.c:258 +#: common.c:234 #, c-format msgid "reading publications" msgstr "パブリケーションを読み込んでいます" -#: common.c:261 +#: common.c:237 #, c-format msgid "reading publication membership of tables" msgstr "テーブルのパブリケーションへの所属を読み取っています" -#: common.c:264 +#: common.c:240 #, c-format msgid "reading publication membership of schemas" msgstr "スキーマのパブリケーションへの所属を読み取っています" -#: common.c:267 +#: common.c:243 #, c-format msgid "reading subscriptions" msgstr "サブスクリプションを読み込んでいます" -#: common.c:270 +#: common.c:246 #, c-format msgid "reading subscription membership of tables" msgstr "テーブルのサブスクリプションへの所属を読み取っています" -#: common.c:333 +#: common.c:309 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "健全性検査に失敗しました、テーブル\"%2$s\"(OID %3$u)の親のOID %1$uがありません" -#: common.c:375 +#: common.c:351 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "テーブル\"%2$s\"用の親テーブルの数%1$dが不正です" -#: common.c:1098 +#: common.c:1087 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "数値配列\"%s\"のパースに失敗しました: 要素が多すぎます" -#: common.c:1110 +#: common.c:1099 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "数値配列\"%s\"のパースに失敗しました: 数値に不正な文字が含まれています" @@ -508,13 +507,13 @@ msgid "could not read from input file: %s" msgstr "入力ファイルから読み込めませんでした: %s" #: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 -#: compress_zstd.c:373 pg_backup_custom.c:651 +#: compress_zstd.c:374 pg_backup_custom.c:650 #, c-format msgid "could not read from input file: %m" msgstr "入力ファイルから読み込めませんでした: %m" #: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 -#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: compress_zstd.c:372 pg_backup_custom.c:648 pg_backup_directory.c:533 #: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" @@ -555,98 +554,163 @@ msgstr "展開を終了できませんでした: %s" msgid "could not set compression parameter \"%s\": %s" msgstr "圧縮パラメータ\"%s\"を設定できませんでした: %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:232 compress_zstd.c:491 +#: compress_zstd.c:499 #, c-format msgid "could not initialize compression library" msgstr "圧縮ライブラリを初期化できませんでした" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:195 compress_zstd.c:309 #, c-format msgid "could not decompress data: %s" msgstr "データを伸張できませんでした: %s" -#: compress_zstd.c:501 +#: compress_zstd.c:502 #, c-format msgid "unhandled mode \"%s\"" msgstr "処理されないモード \"%s\"" -#: filter.c:49 +#: connectdb.c:56 connectdb.c:164 pg_backup_db.c:126 +msgid "Password: " +msgstr "パスワード: " + +#: connectdb.c:83 connectdb.c:173 pg_backup_db.c:203 pg_dump.c:925 +#: pg_dump_sort.c:1251 pg_dump_sort.c:1271 +#, c-format +msgid "%s" +msgstr "%s" + +#: connectdb.c:156 pg_dumpall.c:548 pg_restore.c:534 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "データベース\"%s\"へ接続できませんでした" + +#: connectdb.c:200 +#, c-format +msgid "could not get server version" +msgstr "サーバーバージョンを取得できませんでした" + +#: connectdb.c:204 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "サーバーバージョン\"%s\"をパースできませんでした" + +#: connectdb.c:221 pg_backup_db.c:52 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "サーバーバージョンの不一致のため処理を中断します" + +#: connectdb.c:222 pg_backup_db.c:53 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "サーバーバージョン: %s、%s バージョン: %s" + +#: connectdb.c:281 pg_dumpall.c:1859 +#, c-format +msgid "executing %s" +msgstr "%s を実行しています" + +#: connectdb.c:287 pg_backup_db.c:210 pg_dumpall.c:1865 +#, c-format +msgid "query failed: %s" +msgstr "問い合わせが失敗しました: %s" + +#: connectdb.c:288 pg_backup_db.c:212 pg_dumpall.c:1866 +#, c-format +msgid "Query was: %s" +msgstr "問い合わせ: %s" + +#: dumputils.c:910 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" + +#: dumputils.c:915 +#, c-format +msgid "could not change permissions of directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"の権限を変更できませんでした: %m" + +#: dumputils.c:920 +#, c-format +msgid "directory \"%s\" is not empty" +msgstr "ディレクトリ\"%s\"は空です" + +#: filter.c:48 #, c-format msgid "could not open filter file \"%s\": %m" msgstr "フィルターファイル\"%s\"をオープンできませんでした: %m" -#: filter.c:72 +#: filter.c:71 #, c-format msgid "could not close filter file \"%s\": %m" msgstr "フィルターファイル\"%s\"をクローズできませんでした: %m" -#: filter.c:165 +#: filter.c:164 #, c-format msgid "invalid format in filter read from standard input on line %d: %s" msgstr "標準入力からのフィルターの読み取り中%d行目に無効なフォーマット: %s" -#: filter.c:168 +#: filter.c:167 #, c-format msgid "invalid format in filter read from file \"%s\" on line %d: %s" msgstr "ファイル\"%s\"からのフィルターの読み取り中%d行目に無効なフォーマット: %s" -#: filter.c:241 filter.c:468 +#: filter.c:240 filter.c:467 #, c-format msgid "could not read from filter file \"%s\": %m" msgstr "フィルターファイル\"%s\"から読み取れませんでした: %m" -#: filter.c:244 +#: filter.c:243 msgid "unexpected end of file" msgstr "想定外のファイル終端です" -#: filter.c:311 +#: filter.c:310 msgid "missing object name pattern" msgstr "オブジェクト名のパターンが指定されていません" -#: filter.c:422 +#: filter.c:421 msgid "no filter command found (expected \"include\" or \"exclude\")" msgstr "フィルタコマンドが見つかりません (\"include\" または\"exclude\"が指定可能です)" -#: filter.c:433 +#: filter.c:432 msgid "invalid filter command (expected \"include\" or \"exclude\")" msgstr "不正なフィルターコマンド (\"include\"または\"exclude\"が指定可能です)" -#: filter.c:440 +#: filter.c:439 msgid "missing filter object type" msgstr "フィルターオブジェクトのタイプが指定されてません" -#: filter.c:447 +#: filter.c:446 #, c-format msgid "unsupported filter object type: \"%.*s\"" msgstr "サポートされないフィルターオブジェクトタイプ: \"%.*s\"" -#: parallel.c:251 +#: parallel.c:253 #, c-format msgid "%s() failed: error code %d" msgstr "%s()が失敗しました: エラーコード %d" -#: parallel.c:959 +#: parallel.c:971 #, c-format msgid "could not create communication channels: %m" msgstr "通信チャンネルを作成できませんでした: %m" -#: parallel.c:1016 +#: parallel.c:1028 #, c-format msgid "could not create worker process: %m" msgstr "ワーカープロセスを作成できませんでした: %m" -#: parallel.c:1146 +#: parallel.c:1158 #, c-format msgid "unrecognized command received from leader: \"%s\"" msgstr "リーダーから認識不能のコマンドを受信しました: \"%s\"" -#: parallel.c:1189 parallel.c:1427 +#: parallel.c:1201 parallel.c:1439 #, c-format msgid "invalid message received from worker: \"%s\"" msgstr "ワーカーから不正なメッセージを受信しました: \"%s\"" -#: parallel.c:1321 +#: parallel.c:1333 #, c-format msgid "" "could not obtain lock on relation \"%s\"\n" @@ -655,724 +719,685 @@ msgstr "" "リレーション\"%s\"のロックを獲得できませんでした。\n" "通常これは、pg_dumpの親プロセスが初期のACCESS SHAREロックを獲得した後にだれかがテーブルに対してACCESS EXCLUSIVEロックを要求したことを意味しています。" -#: parallel.c:1410 +#: parallel.c:1422 #, c-format msgid "a worker process died unexpectedly" msgstr "ワーカープロセスが突然終了しました" -#: parallel.c:1532 parallel.c:1650 +#: parallel.c:1544 parallel.c:1662 #, c-format msgid "could not write to the communication channel: %m" msgstr "通信チャンネルに書き込めませんでした: %m" -#: parallel.c:1734 +#: parallel.c:1746 #, c-format msgid "pgpipe: could not create socket: error code %d" msgstr "pgpipe: ソケットを作成できませんでした: エラーコード %d" -#: parallel.c:1745 +#: parallel.c:1757 #, c-format msgid "pgpipe: could not bind: error code %d" msgstr "pgpipe: バインドできませんでした: エラーコード %d" -#: parallel.c:1752 +#: parallel.c:1764 #, c-format msgid "pgpipe: could not listen: error code %d" msgstr "pgpipe: リッスンできませんでした: エラーコード %d" -#: parallel.c:1759 +#: parallel.c:1771 #, c-format msgid "pgpipe: %s() failed: error code %d" msgstr "pgpipe: %s()が失敗しました: エラーコード %d" -#: parallel.c:1770 +#: parallel.c:1782 #, c-format msgid "pgpipe: could not create second socket: error code %d" msgstr "pgpipe: 第二ソケットを作成できませんでした: エラーコード %d" -#: parallel.c:1779 +#: parallel.c:1791 #, c-format msgid "pgpipe: could not connect socket: error code %d" msgstr "pgpipe: ソケットを接続できませんでした: エラーコード %d" -#: parallel.c:1788 +#: parallel.c:1800 #, c-format msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: 接続を受け付けられませんでした: エラーコード %d" -#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 +#: pg_backup_archiver.c:269 pg_backup_archiver.c:1732 #, c-format msgid "could not close output file: %m" msgstr "出力ファイルをクローズできませんでした: %m" -#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 +#: pg_backup_archiver.c:313 pg_backup_archiver.c:317 #, c-format msgid "archive items not in correct section order" msgstr "アーカイブ項目が正しいセクション順ではありません" -#: pg_backup_archiver.c:315 +#: pg_backup_archiver.c:323 #, c-format msgid "unexpected section code %d" msgstr "想定外のセクションコード %d" -#: pg_backup_archiver.c:352 +#: pg_backup_archiver.c:365 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "このアーカイブファイル形式での並列リストアはサポートしていません" -#: pg_backup_archiver.c:356 +#: pg_backup_archiver.c:369 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "8.0 より古い pg_dump で作られたアーカイブでの並列リストアはサポートしていません" -#: pg_backup_archiver.c:377 +#: pg_backup_archiver.c:390 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "圧縮アーカイブから復元できませんでした(%s)" -#: pg_backup_archiver.c:397 +#: pg_backup_archiver.c:410 #, c-format msgid "connecting to database for restore" msgstr "リストアのためデータベースに接続しています" -#: pg_backup_archiver.c:399 +#: pg_backup_archiver.c:412 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "1.3より古いアーカイブではデータベースへの直接接続はサポートされていません" -#: pg_backup_archiver.c:442 +#: pg_backup_archiver.c:455 #, c-format -msgid "implied data-only restore" -msgstr "暗黙的にデータのみのリストアを行います" +msgid "implied no-schema restore" +msgstr "暗黙的にスキーマなしのリストアを行います" -#: pg_backup_archiver.c:510 +#: pg_backup_archiver.c:523 #, c-format msgid "dropping %s %s" msgstr "%s %sを削除しています" -#: pg_backup_archiver.c:642 +#: pg_backup_archiver.c:655 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "文\"%s\"中に IF EXISTS を挿入すべき場所が見つかりませでした" -#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 +#: pg_backup_archiver.c:841 pg_backup_archiver.c:843 #, c-format msgid "warning from original dump file: %s" msgstr "オリジナルのダンプファイルからの警告: %s" -#: pg_backup_archiver.c:864 +#: pg_backup_archiver.c:877 #, c-format msgid "creating %s \"%s.%s\"" msgstr "%s \"%s.%s\"を作成しています" -#: pg_backup_archiver.c:867 +#: pg_backup_archiver.c:880 #, c-format msgid "creating %s \"%s\"" msgstr "%s \"%s\"を作成しています" -#: pg_backup_archiver.c:917 +#: pg_backup_archiver.c:930 #, c-format msgid "connecting to new database \"%s\"" msgstr "新しいデータベース\"%s\"に接続しています" -#: pg_backup_archiver.c:944 +#: pg_backup_archiver.c:957 #, c-format msgid "processing %s" msgstr "%sを処理しています" -#: pg_backup_archiver.c:966 +#: pg_backup_archiver.c:979 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "テーブル\"%s.%s\"のデータを処理しています" -#: pg_backup_archiver.c:1036 +#: pg_backup_archiver.c:1049 #, c-format msgid "executing %s %s" msgstr "%s %sを実行しています" -#: pg_backup_archiver.c:1096 +#: pg_backup_archiver.c:1118 #, c-format msgid "disabling triggers for %s" msgstr "%sのトリガを無効にしています" -#: pg_backup_archiver.c:1122 +#: pg_backup_archiver.c:1144 #, c-format msgid "enabling triggers for %s" msgstr "%sのトリガを有効にしています" -#: pg_backup_archiver.c:1187 +#: pg_backup_archiver.c:1209 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "内部エラー -- WriteDataはDataDumperルーチンのコンテクスト外では呼び出せません" -#: pg_backup_archiver.c:1379 +#: pg_backup_archiver.c:1404 #, c-format msgid "large-object output not supported in chosen format" msgstr "選択した形式ではラージオブジェクト出力をサポートしていません" -#: pg_backup_archiver.c:1442 +#: pg_backup_archiver.c:1467 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "%d個のラージオブジェクトをリストアしました" -#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 +#: pg_backup_archiver.c:1494 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "OID %uのラージオブジェクトをリストアしています" -#: pg_backup_archiver.c:1481 +#: pg_backup_archiver.c:1506 #, c-format msgid "could not create large object %u: %s" msgstr "ラージオブジェクト %u を作成できませんでした: %s" -#: pg_backup_archiver.c:1486 pg_dump.c:3863 +#: pg_backup_archiver.c:1511 pg_dump.c:4063 #, c-format msgid "could not open large object %u: %s" msgstr "ラージオブジェクト %u をオープンできませんでした: %s" -#: pg_backup_archiver.c:1542 +#: pg_backup_archiver.c:1567 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "TOCファイル\"%s\"をオープンできませんでした: %m" -#: pg_backup_archiver.c:1570 +#: pg_backup_archiver.c:1595 #, c-format msgid "line ignored: %s" msgstr "行を無視しました: %s" -#: pg_backup_archiver.c:1577 pg_backup_db.c:609 +#: pg_backup_archiver.c:1602 pg_backup_db.c:548 #, c-format msgid "could not find entry for ID %d" msgstr "ID %dのエントリがありませんでした" -#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 -#: pg_backup_directory.c:613 +#: pg_backup_archiver.c:1625 pg_backup_directory.c:187 +#: pg_backup_directory.c:581 #, c-format msgid "could not close TOC file: %m" msgstr "TOCファイルをクローズできませんでした: %m" -#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 -#: pg_backup_directory.c:600 pg_backup_directory.c:666 -#: pg_backup_directory.c:684 pg_dumpall.c:506 +#: pg_backup_archiver.c:1713 pg_backup_custom.c:151 pg_backup_directory.c:301 +#: pg_backup_directory.c:568 pg_backup_directory.c:634 +#: pg_backup_directory.c:652 pg_dumpall.c:530 #, c-format msgid "could not open output file \"%s\": %m" msgstr "出力ファイル\"%s\"をオープンできませんでした: %m" -#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 +#: pg_backup_archiver.c:1715 pg_backup_custom.c:157 #, c-format msgid "could not open output file: %m" msgstr "出力ファイルをオープンできませんでした: %m" -#: pg_backup_archiver.c:1772 +#: pg_backup_archiver.c:1798 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "ラージオブジェクトデータを%zuバイト書き出しました(結果は%d)" -#: pg_backup_archiver.c:1778 +#: pg_backup_archiver.c:1804 #, c-format msgid "could not write to large object: %s" msgstr "ラージオブジェクトに書き込めませんでした: %s" -#: pg_backup_archiver.c:1868 +#: pg_backup_archiver.c:1894 #, c-format msgid "while INITIALIZING:" msgstr "初期化中:" -#: pg_backup_archiver.c:1873 +#: pg_backup_archiver.c:1899 #, c-format msgid "while PROCESSING TOC:" msgstr "TOC処理中:" -#: pg_backup_archiver.c:1878 +#: pg_backup_archiver.c:1904 #, c-format msgid "while FINALIZING:" msgstr "終了処理中:" -#: pg_backup_archiver.c:1883 +#: pg_backup_archiver.c:1909 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "TOCエントリ%d; %u %u %s %s %s から" -#: pg_backup_archiver.c:1959 +#: pg_backup_archiver.c:1985 #, c-format msgid "bad dumpId" msgstr "不正なdumpId" -#: pg_backup_archiver.c:1980 +#: pg_backup_archiver.c:2006 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "TABLE DATA項目に対する不正なテーブルdumpId" -#: pg_backup_archiver.c:2072 +#: pg_backup_archiver.c:2098 #, c-format msgid "unexpected data offset flag %d" msgstr "想定外のデータオフセットフラグ %d" -#: pg_backup_archiver.c:2085 +#: pg_backup_archiver.c:2111 #, c-format msgid "file offset in dump file is too large" msgstr "ダンプファイルのファイルオフセットが大きすぎます" -#: pg_backup_archiver.c:2196 +#: pg_backup_archiver.c:2222 pg_restore.c:838 #, c-format msgid "directory name too long: \"%s\"" msgstr "ディレクトリ名が長すぎます: \"%s\"" -#: pg_backup_archiver.c:2246 +#: pg_backup_archiver.c:2272 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "ディレクトリ\"%s\"は有効なアーカイブではないようです(\"toc.dat\"がありません)" -#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 -#: pg_backup_directory.c:204 pg_backup_directory.c:396 +#: pg_backup_archiver.c:2280 pg_backup_custom.c:168 pg_backup_custom.c:813 +#: pg_backup_directory.c:172 pg_backup_directory.c:364 #, c-format msgid "could not open input file \"%s\": %m" msgstr "入力ファイル\"%s\"をオープンできませんでした: %m" -#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 +#: pg_backup_archiver.c:2287 pg_backup_custom.c:174 #, c-format msgid "could not open input file: %m" msgstr "入力ファイルをオープンできませんでした: %m" -#: pg_backup_archiver.c:2267 +#: pg_backup_archiver.c:2293 #, c-format msgid "could not read input file: %m" msgstr "入力ファイルを読み込めませんでした: %m" -#: pg_backup_archiver.c:2269 +#: pg_backup_archiver.c:2295 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "入力ファイルが小さすぎます(読み取り%lu、想定は 5)" -#: pg_backup_archiver.c:2301 +#: pg_backup_archiver.c:2327 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "入力ファイルがテキスト形式のダンプのようです。psqlを使用してください。" -#: pg_backup_archiver.c:2307 +#: pg_backup_archiver.c:2333 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "入力ファイルが有効なアーカイブではないようです(小さすぎる?)" -#: pg_backup_archiver.c:2313 +#: pg_backup_archiver.c:2339 #, c-format msgid "input file does not appear to be a valid archive" msgstr "入力ファイルが有効なアーカイブではないようです" -#: pg_backup_archiver.c:2322 +#: pg_backup_archiver.c:2348 #, c-format msgid "could not close input file: %m" msgstr "入力ファイルをクローズできませんでした: %m" -#: pg_backup_archiver.c:2401 +#: pg_backup_archiver.c:2427 #, c-format msgid "could not open stdout for appending: %m" msgstr "標準出力を追記用にオープンできませんでした: %m" -#: pg_backup_archiver.c:2446 +#: pg_backup_archiver.c:2472 #, c-format msgid "unrecognized file format \"%d\"" msgstr "認識不能のファイル形式\"%d\"" -#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4625 +#: pg_backup_archiver.c:2553 pg_backup_archiver.c:4774 #, c-format msgid "finished item %d %s %s" msgstr "項目 %d %s %s の処理が完了" -#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4638 +#: pg_backup_archiver.c:2557 pg_backup_archiver.c:4787 #, c-format msgid "worker process failed: exit code %d" msgstr "ワーカープロセスの処理失敗: 終了コード %d" -#: pg_backup_archiver.c:2653 +#: pg_backup_archiver.c:2655 +#, c-format +msgid "unexpected TOC entry in WriteToc(): %d %s %s" +msgstr "WriteToc()で想定外のTOCエントリ: %d %s %s" + +#: pg_backup_archiver.c:2659 pg_backup_custom.c:440 pg_backup_custom.c:506 +#: pg_backup_custom.c:635 pg_backup_custom.c:871 pg_backup_tar.c:1029 +#: pg_backup_tar.c:1034 +#, c-format +msgid "error during file seek: %m" +msgstr "ファイルシーク中にエラーがありました: %m" + +#: pg_backup_archiver.c:2717 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "エントリID%dは範囲外です -- おそらくTOCの破損です" -#: pg_backup_archiver.c:2736 +#: pg_backup_archiver.c:2800 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "WITH OIDSと定義されたテーブルのリストアは今後サポートされません" -#: pg_backup_archiver.c:2818 +#: pg_backup_archiver.c:2882 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "認識不能のエンコーディング\"%s\"" -#: pg_backup_archiver.c:2823 +#: pg_backup_archiver.c:2888 #, c-format msgid "invalid ENCODING item: %s" msgstr "不正なENCODING項目: %s" -#: pg_backup_archiver.c:2841 +#: pg_backup_archiver.c:2906 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "不正なSTDSTRINGS項目: %s" -#: pg_backup_archiver.c:2866 +#: pg_backup_archiver.c:2931 #, c-format msgid "schema \"%s\" not found" msgstr "スキーマ \"%s\"が見つかりません" -#: pg_backup_archiver.c:2873 +#: pg_backup_archiver.c:2938 #, c-format msgid "table \"%s\" not found" msgstr "テーブル\"%s\"が見つかりません" -#: pg_backup_archiver.c:2880 +#: pg_backup_archiver.c:2945 #, c-format msgid "index \"%s\" not found" msgstr "インデックス\"%s\"が見つかりません" -#: pg_backup_archiver.c:2887 +#: pg_backup_archiver.c:2952 #, c-format msgid "function \"%s\" not found" msgstr "関数\"%s\"が見つかりません" -#: pg_backup_archiver.c:2894 +#: pg_backup_archiver.c:2959 #, c-format msgid "trigger \"%s\" not found" msgstr "トリガ\"%s\"が見つかりません" -#: pg_backup_archiver.c:3325 +#: pg_backup_archiver.c:3420 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "セッションユーザーを\"%s\"に設定できませんでした: %s" -#: pg_backup_archiver.c:3457 +#: pg_backup_archiver.c:3552 #, c-format msgid "could not set \"search_path\" to \"%s\": %s" msgstr "\"search_path\"を\"%s\"に設定できませんでした: %s" -#: pg_backup_archiver.c:3518 +#: pg_backup_archiver.c:3613 #, c-format msgid "could not set \"default_tablespace\" to %s: %s" msgstr "\"default_tablespace\"を\"%s\"に設定できませんでした: %s" -#: pg_backup_archiver.c:3567 +#: pg_backup_archiver.c:3662 #, c-format msgid "could not set \"default_table_access_method\": %s" msgstr "\"default_table_access_method\"を設定できませんでした: %s" -#: pg_backup_archiver.c:3616 +#: pg_backup_archiver.c:3711 #, c-format msgid "could not alter table access method: %s" msgstr "テーブルアクセスメソッドを変更できませんでした: %s" -#: pg_backup_archiver.c:3717 +#: pg_backup_archiver.c:3812 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "オブジェクトタイプ%sに対する所有者の設定方法がわかりません" -#: pg_backup_archiver.c:3982 +#: pg_backup_archiver.c:3947 +#, c-format +msgid "unexpected TOC entry in _printTocEntry(): %d %s %s" +msgstr "_printTocEntry()で想定外のTOCエントリ: %d %s %s" + +#: pg_backup_archiver.c:4131 #, c-format msgid "did not find magic string in file header" msgstr "ファイルヘッダにマジック文字列がありませんでした" -#: pg_backup_archiver.c:3996 +#: pg_backup_archiver.c:4145 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "ファイルヘッダ内のバージョン(%d.%d)はサポートされていません" -#: pg_backup_archiver.c:4001 +#: pg_backup_archiver.c:4150 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "整数のサイズ(%lu)に関する健全性検査が失敗しました" -#: pg_backup_archiver.c:4005 +#: pg_backup_archiver.c:4154 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "アーカイブはより大きなサイズの整数を持つマシンで作成されました、一部の操作が失敗する可能性があります" -#: pg_backup_archiver.c:4015 +#: pg_backup_archiver.c:4164 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "想定した形式(%d)はファイル内にある形式(%d)と異なります" -#: pg_backup_archiver.c:4037 +#: pg_backup_archiver.c:4186 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "アーカイブは圧縮されていますが、このインストールでは圧縮をサポートしていません (%s)-- データは利用できません" -#: pg_backup_archiver.c:4073 +#: pg_backup_archiver.c:4222 #, c-format msgid "invalid creation date in header" msgstr "ヘッダ内の作成日付が不正です" -#: pg_backup_archiver.c:4207 +#: pg_backup_archiver.c:4356 #, c-format msgid "processing item %d %s %s" msgstr "項目 %d %s %s を処理しています" -#: pg_backup_archiver.c:4292 +#: pg_backup_archiver.c:4441 #, c-format msgid "entering main parallel loop" msgstr "メインの並列ループに入ります" -#: pg_backup_archiver.c:4303 +#: pg_backup_archiver.c:4452 #, c-format msgid "skipping item %d %s %s" msgstr "項目 %d %s %s をスキップしています" -#: pg_backup_archiver.c:4312 +#: pg_backup_archiver.c:4461 #, c-format msgid "launching item %d %s %s" msgstr "項目 %d %s %s に着手します" -#: pg_backup_archiver.c:4366 +#: pg_backup_archiver.c:4515 #, c-format msgid "finished main parallel loop" msgstr "メインの並列ループが終了しました" -#: pg_backup_archiver.c:4402 +#: pg_backup_archiver.c:4551 #, c-format msgid "processing missed item %d %s %s" msgstr "やり残し項目 %d %s %s を処理しています" -#: pg_backup_archiver.c:4944 +#: pg_backup_archiver.c:5093 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "テーブル\"%s\"を作成できませんでした、このテーブルのデータは復元されません" -#: pg_backup_custom.c:376 pg_backup_null.c:143 +#: pg_backup_custom.c:375 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "ラージオブジェクトのOIDが不正です" -#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 -#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 -#, c-format -msgid "error during file seek: %m" -msgstr "ファイルシーク中にエラーがありました: %m" - -#: pg_backup_custom.c:480 +#: pg_backup_custom.c:479 #, c-format msgid "data block %d has wrong seek position" msgstr "データブロック%dのシーク位置が間違っています" -#: pg_backup_custom.c:497 +#: pg_backup_custom.c:496 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "アーカイブの探索中に認識不能のデータブロックタイプ(%d)がありました" -#: pg_backup_custom.c:519 +#: pg_backup_custom.c:518 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "アーカイブ中にブロックID %d がありません -- おそらくリストア要求が順不同だったためですが、入力ファイルがシーク不可なため処理できません" -#: pg_backup_custom.c:524 +#: pg_backup_custom.c:523 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "アーカイブ内にブロック ID %d がありませんでした -- おそらくアーカイブが壊れています" -#: pg_backup_custom.c:531 +#: pg_backup_custom.c:530 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "データ読み込み時に想定外のブロックID(%d)がありました --想定は%d" -#: pg_backup_custom.c:545 +#: pg_backup_custom.c:544 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "アーカイブのりストア中に認識不可のデータブロックタイプ%dがありました" -#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_custom.c:750 pg_backup_custom.c:804 pg_backup_custom.c:946 #: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "アーカイブファイルのシーク位置を決定できませんでした: %m" -#: pg_backup_custom.c:767 pg_backup_custom.c:807 +#: pg_backup_custom.c:768 pg_backup_custom.c:808 #, c-format msgid "could not close archive file: %m" msgstr "アーカイブファイルをクローズできませんでした: %m" -#: pg_backup_custom.c:790 +#: pg_backup_custom.c:791 #, c-format msgid "can only reopen input archives" msgstr "入力アーカイブだけが再オープン可能です" -#: pg_backup_custom.c:797 +#: pg_backup_custom.c:798 #, c-format msgid "parallel restore from standard input is not supported" msgstr "標準入力からの並列リストアはサポートされていません" -#: pg_backup_custom.c:799 +#: pg_backup_custom.c:800 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "シーク不可のファイルからの並列リストアはサポートされていません" -#: pg_backup_custom.c:815 +#: pg_backup_custom.c:816 #, c-format msgid "could not set seek position in archive file: %m" msgstr "アーカイブファイルのシークができませんでした: %m" -#: pg_backup_custom.c:894 +#: pg_backup_custom.c:895 #, c-format msgid "compressor active" msgstr "圧縮処理が有効です" -#: pg_backup_db.c:42 -#, c-format -msgid "could not get server_version from libpq" -msgstr "libpqからserver_versionを取得できませんでした" - -#: pg_backup_db.c:53 pg_dumpall.c:1830 +#: pg_backup_db.c:41 #, c-format -msgid "aborting because of server version mismatch" -msgstr "サーバーバージョンの不一致のため処理を中断します" +msgid "could not get \"server_version\" from libpq" +msgstr "libpqから\"server_version\"を取得できませんでした" -#: pg_backup_db.c:54 pg_dumpall.c:1831 -#, c-format -msgid "server version: %s; %s version: %s" -msgstr "サーバーバージョン: %s、%s バージョン: %s" - -#: pg_backup_db.c:120 +#: pg_backup_db.c:118 #, c-format msgid "already connected to a database" msgstr "データベースはすでに接続済みです" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 -msgid "Password: " -msgstr "パスワード: " - -#: pg_backup_db.c:170 -#, c-format -msgid "could not connect to database" -msgstr "データベースへの接続ができませんでした" - -#: pg_backup_db.c:187 -#, c-format -msgid "reconnection failed: %s" -msgstr "再接続に失敗しました: %s" - -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:787 pg_dump_sort.c:1213 -#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 -#, c-format -msgid "%s" -msgstr "%s" - -#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 -#, c-format -msgid "query failed: %s" -msgstr "問い合わせが失敗しました: %s" - -#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 -#, c-format -msgid "Query was: %s" -msgstr "問い合わせ: %s" - -#: pg_backup_db.c:315 +#: pg_backup_db.c:254 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" msgstr[0] "問い合わせが1行ではなく%d行返しました: %s" -#: pg_backup_db.c:351 +#: pg_backup_db.c:290 #, c-format msgid "%s: %sCommand was: %s" msgstr "%s: %sコマンド: %s" -#: pg_backup_db.c:407 pg_backup_db.c:481 pg_backup_db.c:488 +#: pg_backup_db.c:346 pg_backup_db.c:420 pg_backup_db.c:427 msgid "could not execute query" msgstr "問い合わせを実行できませんでした" -#: pg_backup_db.c:460 +#: pg_backup_db.c:399 #, c-format msgid "error returned by PQputCopyData: %s" msgstr "PQputCopyData からエラーが返されました: %s" -#: pg_backup_db.c:509 +#: pg_backup_db.c:448 #, c-format msgid "error returned by PQputCopyEnd: %s" msgstr "PQputCopyEnd からエラーが返されました: %s" -#: pg_backup_db.c:515 +#: pg_backup_db.c:454 #, c-format msgid "COPY failed for table \"%s\": %s" msgstr "テーブル\"%s\"へのコピーに失敗しました: %s" -#: pg_backup_db.c:521 pg_dump.c:2271 +#: pg_backup_db.c:460 pg_dump.c:2439 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "ファイル\"%s\"をCOPY中に想定していない余分な結果がありました" -#: pg_backup_db.c:533 +#: pg_backup_db.c:472 msgid "could not start database transaction" msgstr "データベーストランザクションを開始できませんでした" -#: pg_backup_db.c:541 +#: pg_backup_db.c:480 msgid "could not commit database transaction" msgstr "データベーストランザクションをコミットできませんでした" -#: pg_backup_directory.c:153 +#: pg_backup_directory.c:154 #, c-format msgid "no output directory specified" msgstr "出力ディレクトリが指定されていません" -#: pg_backup_directory.c:186 -#, c-format -msgid "could not close directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" - -#: pg_backup_directory.c:192 -#, c-format -msgid "could not create directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" - -#: pg_backup_directory.c:357 pg_backup_directory.c:506 -#: pg_backup_directory.c:544 +#: pg_backup_directory.c:325 pg_backup_directory.c:474 +#: pg_backup_directory.c:512 #, c-format msgid "could not write to output file: %s" msgstr "出力ファイルに書き込めませんでした: %s" -#: pg_backup_directory.c:375 +#: pg_backup_directory.c:343 #, c-format msgid "could not close data file: %m" msgstr "データファイルをクローズできませんでした: %m" -#: pg_backup_directory.c:408 +#: pg_backup_directory.c:376 #, c-format msgid "could not close data file \"%s\": %m" msgstr "データファイル\"%s\"をクローズできませんでした: %m" -#: pg_backup_directory.c:455 +#: pg_backup_directory.c:423 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "ラージオブジェクトTOCファイル\"%s\"を入力用としてオープンできませんでした: %m" -#: pg_backup_directory.c:466 +#: pg_backup_directory.c:434 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "ラージオブジェクトTOCファイル\"%s\"の中に不正な行がありました: \"%s\"" -#: pg_backup_directory.c:475 +#: pg_backup_directory.c:443 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "ラージオブジェクトTOCファイル\"%s\"の読み取り中にエラーがありました" -#: pg_backup_directory.c:479 +#: pg_backup_directory.c:447 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "ラージオブジェクトTOCファイル\"%s\"をクローズできませんでした: %m" -#: pg_backup_directory.c:702 +#: pg_backup_directory.c:670 #, c-format msgid "could not close LO data file: %m" msgstr "ラージオブジェクトのデータファイルをクローズできませんでした: %m" -#: pg_backup_directory.c:712 +#: pg_backup_directory.c:680 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "ラージオブジェクトのTOCファイルに書き出せませんでした: %s" -#: pg_backup_directory.c:728 +#: pg_backup_directory.c:696 #, c-format msgid "could not close LOs TOC file: %m" msgstr "ラージオブジェクトのTOCファイルをクローズできませんでした: %m" -#: pg_backup_directory.c:747 +#: pg_backup_directory.c:715 #, c-format msgid "file name too long: \"%s\"" msgstr "ファイル名が長すぎます: \"%s\"" @@ -1459,100 +1484,140 @@ msgstr[0] "不完全なtarヘッダがありました(%luバイト)" msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "破損したtarヘッダが%sにありました(想定 %d、算出結果 %d) ファイル位置 %llu" -#: pg_backup_utils.c:54 +#: pg_backup_utils.c:56 #, c-format msgid "unrecognized section name: \"%s\"" msgstr "認識不可のセクション名: \"%s\"" -#: pg_backup_utils.c:55 pg_dump.c:693 pg_dump.c:710 pg_dumpall.c:370 -#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 -#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 -#: pg_restore.c:337 +#: pg_backup_utils.c:57 pg_dump.c:803 pg_dump.c:820 pg_dumpall.c:385 +#: pg_dumpall.c:395 pg_dumpall.c:403 pg_dumpall.c:411 pg_dumpall.c:418 +#: pg_dumpall.c:428 pg_dumpall.c:443 pg_dumpall.c:564 pg_restore.c:351 +#: pg_restore.c:367 pg_restore.c:378 pg_restore.c:388 pg_restore.c:517 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_backup_utils.c:66 +#: pg_backup_utils.c:68 #, c-format msgid "out of on_exit_nicely slots" msgstr "on_exit_nicelyスロットが足りません" -#: pg_dump.c:708 pg_dumpall.c:378 pg_restore.c:321 +#: pg_dump.c:818 pg_dumpall.c:393 pg_restore.c:365 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます(先頭は\"%s\")" -#: pg_dump.c:727 pg_restore.c:344 +#: pg_dump.c:830 pg_restore.c:396 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "-s/--schema-only と -a/--data-only オプションは同時には使用できません" -#: pg_dump.c:730 +#: pg_dump.c:832 pg_restore.c:398 +#, c-format +msgid "options -s/--schema-only and --statistics-only cannot be used together" +msgstr "-s/--schema-only と--statistics-only オプションは同時には使用できません" + +#: pg_dump.c:834 pg_restore.c:400 +#, c-format +msgid "options -a/--data-only and --statistics-only cannot be used together" +msgstr "-a/--data-only と --statistics-only オプションは同時には使用できません" + +#: pg_dump.c:838 pg_restore.c:404 +#, c-format +msgid "options -a/--data-only and --no-data cannot be used together" +msgstr "-a/--data-only と --no-data オプションは同時には使用できません" + +#: pg_dump.c:840 pg_restore.c:406 +#, c-format +msgid "options -s/--schema-only and --no-schema cannot be used together" +msgstr "-s/--schema-only と --no-schema オプションは同時には使用できません" + +#: pg_dump.c:842 pg_restore.c:408 +#, c-format +msgid "options --statistics-only and --no-statistics cannot be used together" +msgstr "オプション --statistics-only と --no-statistics とは同時には使用できません" + +#: pg_dump.c:846 pg_restore.c:412 +#, c-format +msgid "options --with-data and --no-data cannot be used together" +msgstr "--with-data と --no-data オプションは同時には使用できません" + +#: pg_dump.c:848 pg_restore.c:414 +#, c-format +msgid "options --with-schema and --no-schema cannot be used together" +msgstr "--with-schema と --no-schema オプションは同時には使用できません" + +#: pg_dump.c:850 pg_restore.c:416 +#, c-format +msgid "options --with-statistics and --no-statistics cannot be used together" +msgstr "オプション --with-statistics と --no-statistics とは同時には使用できません" + +#: pg_dump.c:853 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "-s/--schema-only と --include-foreign-data オプションは同時には使用できません" -#: pg_dump.c:733 +#: pg_dump.c:856 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "オプション --include-foreign-data はパラレルバックアップではサポートされません" -#: pg_dump.c:736 pg_restore.c:347 +#: pg_dump.c:859 pg_restore.c:419 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "-c/--clean と -a/--data-only オプションは同時には使用できません" -#: pg_dump.c:739 pg_dumpall.c:408 pg_restore.c:375 +#: pg_dump.c:862 pg_dumpall.c:423 pg_restore.c:462 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "--if-existsは -c/--clean の指定が必要です" -#: pg_dump.c:746 +#: pg_dump.c:884 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "--on-conflict-do-nothingオプションは--inserts、--rows-per-insert または --column-insertsを必要とします" -#: pg_dump.c:775 +#: pg_dump.c:913 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "認識できない圧縮アルゴリズム: \"%s\"" -#: pg_dump.c:782 +#: pg_dump.c:920 #, c-format msgid "invalid compression specification: %s" msgstr "不正な圧縮指定: %s" -#: pg_dump.c:795 +#: pg_dump.c:933 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "圧縮オプション\"%s\"は現時点ではpg_dumpではサポートされていません" -#: pg_dump.c:807 +#: pg_dump.c:945 #, c-format msgid "parallel backup only supported by the directory format" msgstr "並列バックアップはディレクトリ形式でのみサポートされます" -#: pg_dump.c:853 +#: pg_dump.c:991 #, c-format msgid "last built-in OID is %u" msgstr "最後の組み込みOIDは%u" -#: pg_dump.c:862 +#: pg_dump.c:1000 #, c-format msgid "no matching schemas were found" msgstr "マッチするスキーマが見つかりません" -#: pg_dump.c:879 +#: pg_dump.c:1017 #, c-format msgid "no matching tables were found" msgstr "マッチするテーブルが見つかりません" -#: pg_dump.c:907 +#: pg_dump.c:1045 #, c-format msgid "no matching extensions were found" msgstr "合致する機能拡張が見つかりません" -#: pg_dump.c:1091 +#: pg_dump.c:1238 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1561,17 +1626,17 @@ msgstr "" "%sはデータベースをテキストファイルまたはその他の形式でダンプします。\n" "\n" -#: pg_dump.c:1092 pg_dumpall.c:635 pg_restore.c:452 +#: pg_dump.c:1239 pg_dumpall.c:699 pg_restore.c:648 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_dump.c:1093 +#: pg_dump.c:1240 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: pg_dump.c:1095 pg_dumpall.c:638 pg_restore.c:455 +#: pg_dump.c:1242 pg_dumpall.c:702 pg_restore.c:651 #, c-format msgid "" "\n" @@ -1580,12 +1645,12 @@ msgstr "" "\n" "一般的なオプション;\n" -#: pg_dump.c:1096 +#: pg_dump.c:1243 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=ファイル名 出力ファイルまたはディレクトリの名前\n" -#: pg_dump.c:1097 +#: pg_dump.c:1244 pg_dumpall.c:704 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1594,22 +1659,22 @@ msgstr "" " -F, --format=c|d|t|p 出力ファイルの形式(custom, directory, tar, \n" " plain text(デフォルト))\n" -#: pg_dump.c:1099 +#: pg_dump.c:1246 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM ダンプ時に指定した数の並列ジョブを使用\n" -#: pg_dump.c:1100 pg_dumpall.c:640 +#: pg_dump.c:1247 pg_dumpall.c:706 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose 冗長モード\n" -#: pg_dump.c:1101 pg_dumpall.c:641 +#: pg_dump.c:1248 pg_dumpall.c:707 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_dump.c:1102 +#: pg_dump.c:1249 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1618,29 +1683,29 @@ msgstr "" " -Z, --compress=方式[:詳細]\n" " 指定のとおり圧縮\n" -#: pg_dump.c:1104 pg_dumpall.c:642 +#: pg_dump.c:1251 pg_dumpall.c:708 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=TIMEOUT テーブルロックをTIMEOUT待ってから失敗\n" -#: pg_dump.c:1105 pg_dumpall.c:670 +#: pg_dump.c:1252 pg_dumpall.c:740 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync 変更のディスクへの安全な書き出しを待機しない\n" -#: pg_dump.c:1106 +#: pg_dump.c:1253 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHOD ファイルをディスクに同期させる方法を指定\n" "\n" -#: pg_dump.c:1107 pg_dumpall.c:643 +#: pg_dump.c:1254 pg_dumpall.c:709 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_dump.c:1109 pg_dumpall.c:644 +#: pg_dump.c:1256 pg_dumpall.c:710 #, c-format msgid "" "\n" @@ -1649,66 +1714,66 @@ msgstr "" "\n" "出力内容を制御するためのオプション:\n" -#: pg_dump.c:1110 pg_dumpall.c:645 +#: pg_dump.c:1257 pg_dumpall.c:711 #, c-format -msgid " -a, --data-only dump only the data, not the schema\n" -msgstr " -a, --data-only データのみをダンプし、スキーマをダンプしない\n" +msgid " -a, --data-only dump only the data, not the schema or statistics\n" +msgstr " -a, --data-only データのみをダンプし、スキーマまたは統計情報をダンプしない\n" -#: pg_dump.c:1111 +#: pg_dump.c:1258 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr "" " -b, --large-objects ダンプにラージオブジェクトを含める\n" "\n" -#: pg_dump.c:1112 +#: pg_dump.c:1259 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (--large-objectsに同じ、非推奨)\n" -#: pg_dump.c:1113 +#: pg_dump.c:1260 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects ダンプにラージオブジェクトを含めない\n" -#: pg_dump.c:1114 +#: pg_dump.c:1261 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr "" " --no-blobs (--no-large-objectsに同じ、非推奨)\n" "\n" -#: pg_dump.c:1115 pg_restore.c:466 +#: pg_dump.c:1262 pg_restore.c:662 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean 再作成前にデータベースオブジェクトを整理(削除)\n" -#: pg_dump.c:1116 +#: pg_dump.c:1263 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr " -C, --create ダンプにデータベース生成用コマンドを含める\n" -#: pg_dump.c:1117 +#: pg_dump.c:1264 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=PATTERN 指定した機能拡張のみをダンプ\n" -#: pg_dump.c:1118 pg_dumpall.c:647 +#: pg_dump.c:1265 pg_dumpall.c:713 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=ENCODING 指定した符号化方式でデータをダンプ\n" -#: pg_dump.c:1119 +#: pg_dump.c:1266 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=SCHEMA 指定したスキーマのみをダンプ\n" -#: pg_dump.c:1120 +#: pg_dump.c:1267 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=SCHEMA 指定したスキーマをダンプしない\n" -#: pg_dump.c:1121 +#: pg_dump.c:1268 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1717,56 +1782,58 @@ msgstr "" " -O, --no-owner プレインテキスト形式で、オブジェクト所有権の\n" " 復元を行わない\n" -#: pg_dump.c:1123 pg_dumpall.c:651 +#: pg_dump.c:1270 pg_dumpall.c:717 #, c-format -msgid " -s, --schema-only dump only the schema, no data\n" -msgstr " -s, --schema-only スキーマのみをダンプし、データはダンプしない\n" +msgid " -s, --schema-only dump only the schema, no data or statistics\n" +msgstr "" +" -s, --schema-only スキーマのみをダンプし、データまたは統計情報を\n" +" ダンプしない\n" -#: pg_dump.c:1124 +#: pg_dump.c:1271 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr "" " -S, --superuser=NAME プレインテキスト形式で使用するスーパーユーザーの\n" " 名前\n" -#: pg_dump.c:1125 +#: pg_dump.c:1272 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=PATTERN 指定したテーブル(群)のみをダンプ\n" -#: pg_dump.c:1126 +#: pg_dump.c:1273 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=PATTERN 指定したテーブルをダンプしない\n" -#: pg_dump.c:1127 pg_dumpall.c:654 +#: pg_dump.c:1274 pg_dumpall.c:720 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges 権限(grant/revoke)をダンプしない\n" -#: pg_dump.c:1128 pg_dumpall.c:655 +#: pg_dump.c:1275 pg_dumpall.c:721 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade アップグレードユーティリティ専用\n" -#: pg_dump.c:1129 pg_dumpall.c:656 +#: pg_dump.c:1276 pg_dumpall.c:722 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr " --column-inserts 列名指定のINSERTコマンドでデータをダンプ\n" -#: pg_dump.c:1130 pg_dumpall.c:657 +#: pg_dump.c:1277 pg_dumpall.c:723 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr "" " --disable-dollar-quoting ドル記号による引用符付けを禁止、SQL標準の引用符\n" " 付けを使用\n" -#: pg_dump.c:1131 pg_dumpall.c:658 pg_restore.c:483 +#: pg_dump.c:1278 pg_dumpall.c:724 pg_restore.c:681 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr " --disable-triggers データのみのリストアの際にトリガを無効化\n" -#: pg_dump.c:1132 +#: pg_dump.c:1279 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1775,12 +1842,12 @@ msgstr "" " --enable-row-security 行セキュリティを有効化(ユーザーがアクセス可能な\n" " 内容のみをダンプ)\n" -#: pg_dump.c:1134 +#: pg_dump.c:1281 #, c-format msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" msgstr " --exclude-extension=PATTERN 指定した機能拡張をダンプしない\n" -#: pg_dump.c:1135 +#: pg_dump.c:1282 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1791,12 +1858,12 @@ msgstr "" " 指定したテーブル(群)を子テーブルを含めて\n" " ダンプしない\n" -#: pg_dump.c:1138 +#: pg_dump.c:1285 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=PATTERN 指定したテーブルのデータをダンプしない\n" -#: pg_dump.c:1139 +#: pg_dump.c:1286 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1807,12 +1874,12 @@ msgstr "" " 指定したテーブル(群)のデータを子テーブルを含めて\n" " ダンプしない\n" -#: pg_dump.c:1142 pg_dumpall.c:660 +#: pg_dump.c:1289 pg_dumpall.c:726 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=NUM extra_float_digitsの設定を上書きする\n" -#: pg_dump.c:1143 +#: pg_dump.c:1290 #, c-format msgid "" " --filter=FILENAME include or exclude objects and data from dump\n" @@ -1821,12 +1888,12 @@ msgstr "" " --filter=FILENAME オブジェクトやデータの指定や除外を\n" " FILENAMEに記述された式をもとに行う\n" -#: pg_dump.c:1145 pg_dumpall.c:662 pg_restore.c:487 +#: pg_dump.c:1292 pg_dumpall.c:728 pg_restore.c:685 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists オブジェクト削除の際に IF EXISTS を使用\n" -#: pg_dump.c:1146 +#: pg_dump.c:1293 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1837,91 +1904,123 @@ msgstr "" " PATTERNに合致する外部サーバー上の外部テーブルの\n" " データを含める\n" -#: pg_dump.c:1149 pg_dumpall.c:663 +#: pg_dump.c:1296 pg_dumpall.c:729 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts COPYではなくINSERTコマンドでデータをダンプ\n" -#: pg_dump.c:1150 pg_dumpall.c:664 +#: pg_dump.c:1297 pg_dumpall.c:730 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root 子テーブルをルートテーブル経由でロードする\n" -#: pg_dump.c:1151 pg_dumpall.c:665 +#: pg_dump.c:1298 pg_dumpall.c:731 #, c-format -msgid " --no-comments do not dump comments\n" -msgstr " --no-comments コメントをダンプしない\n" +msgid " --no-comments do not dump comment commands\n" +msgstr " --no-comments コメントコマンドをダンプしない\n" -#: pg_dump.c:1152 pg_dumpall.c:666 +#: pg_dump.c:1299 pg_dumpall.c:732 +#, c-format +msgid " --no-data do not dump data\n" +msgstr " --no-data データをダンプしない\n" + +#: pg_dump.c:1300 pg_dumpall.c:733 +#, c-format +msgid " --no-policies do not dump row security policies\n" +msgstr " --no-policies 行セキュリティポリシーをダンプしない\n" + +#: pg_dump.c:1301 pg_dumpall.c:734 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications パブリケーションをダンプしない\n" -#: pg_dump.c:1153 pg_dumpall.c:668 +#: pg_dump.c:1302 pg_dumpall.c:736 +#, c-format +msgid " --no-schema do not dump schema\n" +msgstr " --no-schema スキーマをダンプしない\n" + +#: pg_dump.c:1303 pg_dumpall.c:737 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels セキュリティラベルの割り当てをダンプしない\n" -#: pg_dump.c:1154 pg_dumpall.c:669 +#: pg_dump.c:1304 pg_dumpall.c:738 +#, c-format +msgid " --no-statistics do not dump statistics\n" +msgstr " --no-statistics 統計情報をダンプしない\n" + +#: pg_dump.c:1305 pg_dumpall.c:739 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions サブスクリプションをダンプしない\n" -#: pg_dump.c:1155 pg_dumpall.c:671 +#: pg_dump.c:1306 pg_dumpall.c:741 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method テーブルアクセスメソッドをダンプしない\n" -#: pg_dump.c:1156 pg_dumpall.c:672 +#: pg_dump.c:1307 pg_dumpall.c:742 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces テーブルスペースの割り当てをダンプしない\n" -#: pg_dump.c:1157 pg_dumpall.c:673 +#: pg_dump.c:1308 pg_dumpall.c:743 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression TOAST圧縮方式をダンプしない\n" -#: pg_dump.c:1158 pg_dumpall.c:674 +#: pg_dump.c:1309 pg_dumpall.c:744 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data 非ログテーブルのデータをダンプしない\n" -#: pg_dump.c:1159 pg_dumpall.c:675 +#: pg_dump.c:1310 pg_dumpall.c:745 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing INSERTコマンドにON CONFLICT DO NOTHINGを付加する\n" -#: pg_dump.c:1160 pg_dumpall.c:676 +#: pg_dump.c:1311 pg_dumpall.c:746 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr "" " --quote-all-identifiers すべての識別子をキーワードでなかったとしても\n" " 引用符で囲む\n" -#: pg_dump.c:1161 pg_dumpall.c:677 +#: pg_dump.c:1312 pg_dumpall.c:747 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NROWS INSERT毎の行数; --insertsを暗黙的に指定する\n" -#: pg_dump.c:1162 +#: pg_dump.c:1313 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr "" " --section=SECTION 指定したセクション(pre-data、data または\n" " post-data)をダンプする\n" -#: pg_dump.c:1163 +#: pg_dump.c:1314 +#, c-format +msgid " --sequence-data include sequence data in dump\n" +msgstr " --sequence-data ダンプにシーケンスデータを含める\n" + +#: pg_dump.c:1315 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr " --serializable-deferrable ダンプを異常なく実行できるようになるまで待機\n" -#: pg_dump.c:1164 +#: pg_dump.c:1316 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT ダンプに指定のスナップショットを使用する\n" -#: pg_dump.c:1165 pg_restore.c:497 +#: pg_dump.c:1317 pg_dumpall.c:748 +#, c-format +msgid " --statistics-only dump only the statistics, not schema or data\n" +msgstr "" +" --statistics-only 統計情報のみをダンプし、スキーマまたはデータを\n" +" ダンプしない\n" + +#: pg_dump.c:1318 pg_restore.c:700 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1930,7 +2029,7 @@ msgstr "" " --strict-names テーブル/スキーマの対象パターンが最低でも\n" " 一つの実体にマッチすることを必須とする\n" -#: pg_dump.c:1167 +#: pg_dump.c:1320 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1939,7 +2038,7 @@ msgstr "" " --table-and-children=PATTERN 指定したテーブル(群)のみを子テーブル\n" " を含めてダンプ\n" -#: pg_dump.c:1169 pg_dumpall.c:678 pg_restore.c:500 +#: pg_dump.c:1322 pg_dumpall.c:749 pg_restore.c:703 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1950,7 +2049,22 @@ msgstr "" " 所有者をセットする際、ALTER OWNERコマンドの代わり\n" " にSET SESSION AUTHORIZATIONコマンドを使用する\n" -#: pg_dump.c:1173 pg_dumpall.c:682 pg_restore.c:504 +#: pg_dump.c:1325 pg_dumpall.c:752 pg_restore.c:706 +#, c-format +msgid " --with-data dump the data\n" +msgstr " --with-data データをダンプする\n" + +#: pg_dump.c:1326 pg_dumpall.c:753 pg_restore.c:707 +#, c-format +msgid " --with-schema dump the schema\n" +msgstr " --with-schema スキーマをダンプする\n" + +#: pg_dump.c:1327 pg_dumpall.c:754 pg_restore.c:708 +#, c-format +msgid " --with-statistics dump the statistics\n" +msgstr " --with-statistics 統計情報をダンプする\n" + +#: pg_dump.c:1329 pg_dumpall.c:756 pg_restore.c:710 #, c-format msgid "" "\n" @@ -1959,46 +2073,46 @@ msgstr "" "\n" "接続オプション:\n" -#: pg_dump.c:1174 +#: pg_dump.c:1330 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=DBNAME ダンプするデータベース\n" -#: pg_dump.c:1175 pg_dumpall.c:684 pg_restore.c:505 +#: pg_dump.c:1331 pg_dumpall.c:758 pg_restore.c:711 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME データベースサーバーのホストまたはソケット\n" " ディレクトリ\n" -#: pg_dump.c:1176 pg_dumpall.c:686 pg_restore.c:506 +#: pg_dump.c:1332 pg_dumpall.c:760 pg_restore.c:712 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT データベースサーバーのポート番号\n" -#: pg_dump.c:1177 pg_dumpall.c:687 pg_restore.c:507 +#: pg_dump.c:1333 pg_dumpall.c:761 pg_restore.c:713 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME 指定したデータベースユーザーで接続\n" -#: pg_dump.c:1178 pg_dumpall.c:688 pg_restore.c:508 +#: pg_dump.c:1334 pg_dumpall.c:762 pg_restore.c:714 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password パスワード入力を要求しない\n" -#: pg_dump.c:1179 pg_dumpall.c:689 pg_restore.c:509 +#: pg_dump.c:1335 pg_dumpall.c:763 pg_restore.c:715 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password パスワードプロンプトを強制表示\n" " (自動的に表示されるはず)\n" -#: pg_dump.c:1180 pg_dumpall.c:690 +#: pg_dump.c:1336 pg_dumpall.c:764 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLENAME ダンプの前に SET ROLE を行う\n" -#: pg_dump.c:1182 +#: pg_dump.c:1338 #, c-format msgid "" "\n" @@ -2010,534 +2124,570 @@ msgstr "" "データベース名が指定されなかった場合、環境変数PGDATABASEが使用されます\n" "\n" -#: pg_dump.c:1184 pg_dumpall.c:694 pg_restore.c:516 +#: pg_dump.c:1340 pg_dumpall.c:768 pg_restore.c:722 #, c-format msgid "Report bugs to <%s>.\n" msgstr "バグは<%s>に報告してください。\n" -#: pg_dump.c:1185 pg_dumpall.c:695 pg_restore.c:517 +#: pg_dump.c:1341 pg_dumpall.c:769 pg_restore.c:723 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: pg_dump.c:1204 pg_dumpall.c:518 +#: pg_dump.c:1360 pg_dumpall.c:581 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "不正なクライアントエンコーディング\"%s\"が指定されました" -#: pg_dump.c:1344 +#: pg_dump.c:1508 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "スタンバイサーバーからの並列ダンプはこのサーバーバージョンではサポートされません" -#: pg_dump.c:1409 +#: pg_dump.c:1573 #, c-format msgid "invalid output format \"%s\" specified" msgstr "不正な出力形式\"%s\"が指定されました" -#: pg_dump.c:1450 pg_dump.c:1506 pg_dump.c:1559 pg_dumpall.c:1467 +#: pg_dump.c:1614 pg_dump.c:1670 pg_dump.c:1723 pg_dumpall.c:1593 +#: pg_restore.c:974 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "修飾名が不適切です(ドット区切りの名前が多すぎます): %s" -#: pg_dump.c:1458 +#: pg_dump.c:1622 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "パターン\"%s\"にマッチするスキーマが見つかりません" -#: pg_dump.c:1511 +#: pg_dump.c:1675 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "パターン\"%s\"に合致する機能拡張が見つかりません" -#: pg_dump.c:1564 +#: pg_dump.c:1728 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "パターン\"%s\"にマッチする外部サーバーが見つかりません" -#: pg_dump.c:1635 +#: pg_dump.c:1799 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "リレーション名が不適切です(ドット区切りの名前が多すぎます): %s" -#: pg_dump.c:1657 +#: pg_dump.c:1821 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "パターン \"%s\"にマッチするテーブルが見つかりません" -#: pg_dump.c:1684 +#: pg_dump.c:1848 #, c-format msgid "You are currently not connected to a database." msgstr "現在データベースに接続していません。" -#: pg_dump.c:1687 +#: pg_dump.c:1851 #, c-format msgid "cross-database references are not implemented: %s" msgstr "データベース間の参照は実装されていません: %s" -#: pg_dump.c:2146 +#: pg_dump.c:2310 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "テーブル \"%s.%s\"の内容をダンプしています" -#: pg_dump.c:2252 +#: pg_dump.c:2420 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "テーブル\"%s\"の内容のダンプに失敗: PQgetCopyData()が失敗しました。" -#: pg_dump.c:2253 pg_dump.c:2263 +#: pg_dump.c:2421 pg_dump.c:2431 #, c-format msgid "Error message from server: %s" msgstr "サーバーのエラーメッセージ: %s" -#: pg_dump.c:2254 pg_dump.c:2264 +#: pg_dump.c:2422 pg_dump.c:2432 #, c-format msgid "Command was: %s" msgstr "コマンド: %s" -#: pg_dump.c:2262 +#: pg_dump.c:2430 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "テーブル\"%s\"の内容のダンプに失敗: PQgetResult()が失敗しました。" -#: pg_dump.c:2344 +#: pg_dump.c:2521 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "テーブル\"%s\"から取得したフィールドの数が間違っています" -#: pg_dump.c:3042 +#: pg_dump.c:3236 #, c-format msgid "saving database definition" msgstr "データベース定義を保存しています" -#: pg_dump.c:3151 +#: pg_dump.c:3351 #, c-format msgid "unrecognized locale provider: %s" msgstr "認識できない照合順序プロバイダ: %s" -#: pg_dump.c:3512 +#: pg_dump.c:3712 #, c-format msgid "saving encoding = %s" msgstr "encoding = %s を保存しています" -#: pg_dump.c:3537 +#: pg_dump.c:3737 #, c-format msgid "saving \"standard_conforming_strings = %s\"" msgstr "\"standard_conforming_strings = %s\" を保存しています" -#: pg_dump.c:3576 +#: pg_dump.c:3776 #, c-format msgid "could not parse result of current_schemas()" msgstr "current_schemas()の結果をパースできませんでした" -#: pg_dump.c:3595 +#: pg_dump.c:3795 #, c-format msgid "saving \"search_path = %s\"" msgstr "\"search_path = %s\" を保存しています" -#: pg_dump.c:3631 +#: pg_dump.c:3831 #, c-format msgid "reading large objects" msgstr "ラージオブジェクトを読み込んでいます" -#: pg_dump.c:3852 +#: pg_dump.c:4052 #, c-format msgid "saving large objects \"%s\"" msgstr "ラージオブジェクト\"%s\"を保存しています" -#: pg_dump.c:3873 +#: pg_dump.c:4073 #, c-format msgid "error reading large object %u: %s" msgstr "ラージオブジェクト %u を読み取り中にエラーがありました: %s" -#: pg_dump.c:3976 +#: pg_dump.c:4181 #, c-format msgid "reading row-level security policies" msgstr "行レベルセキュリティポリシーを読み取ります" -#: pg_dump.c:4117 +#: pg_dump.c:4322 #, c-format msgid "unexpected policy command type: %c" msgstr "想定外のポリシコマンドタイプ: \"%c\"" -#: pg_dump.c:4567 pg_dump.c:5103 pg_dump.c:12315 pg_dump.c:18137 -#: pg_dump.c:18139 pg_dump.c:18761 +#: pg_dump.c:4764 pg_dump.c:5321 pg_dump.c:7917 pg_dump.c:13277 pg_dump.c:19381 +#: pg_dump.c:19383 pg_dump.c:20015 #, c-format msgid "could not parse %s array" msgstr "%s配列をパースできませんでした" -#: pg_dump.c:4759 +#: pg_dump.c:4980 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "現在のユーザーがスーパーユーザーではないため、サブスクリプションはダンプされません" -#: pg_dump.c:4965 +#: pg_dump.c:5184 #, c-format msgid "subscription with OID %u does not exist" msgstr "OID %uのサブスクリプションは存在しません" -#: pg_dump.c:4972 +#: pg_dump.c:5191 #, c-format msgid "failed sanity check, table with OID %u not found" msgstr "健全性検査に失敗しました、OID %uのテーブルがありません" -#: pg_dump.c:5535 +#: pg_dump.c:5777 #, c-format msgid "could not find parent extension for %s %s" msgstr "%s %sの親となる機能拡張がありませんでした" -#: pg_dump.c:5680 +#: pg_dump.c:5915 #, c-format msgid "schema with OID %u does not exist" msgstr "OID %uのスキーマは存在しません" -#: pg_dump.c:7162 pg_dump.c:17508 +#: pg_dump.c:6939 +#, c-format +msgid "cannot dump statistics for relation kind '%c'" +msgstr "リレーション種別\"%c\"の統計情報はダンプできません" + +#: pg_dump.c:7451 pg_dump.c:18725 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "健全性検査に失敗しました、OID %2$u であるシーケンスの OID %1$u である親テーブルがありません" -#: pg_dump.c:7305 +#: pg_dump.c:7596 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "健全性検査に失敗しました、pg_partitioned_tableにあるテーブルOID %u が見つかりません" -#: pg_dump.c:7536 pg_dump.c:7810 pg_dump.c:8257 pg_dump.c:8871 pg_dump.c:8993 -#: pg_dump.c:9141 +#: pg_dump.c:7861 pg_dump.c:8154 pg_dump.c:8595 pg_dump.c:9232 pg_dump.c:9366 +#: pg_dump.c:9511 pg_dump.c:9611 #, c-format msgid "unrecognized table OID %u" msgstr "認識できないテーブルOID %u" -#: pg_dump.c:7540 +#: pg_dump.c:7865 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "テーブル\"%s\"に対する想定外のインデックスデータ" -#: pg_dump.c:8042 +#: pg_dump.c:8382 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "健全性検査に失敗しました、OID %2$u であるpg_rewriteエントリのOID %1$u である親テーブルが見つかりません" -#: pg_dump.c:8875 +#: pg_dump.c:9236 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "テーブル\"%s\"に対する想定外の列データ" -#: pg_dump.c:8904 +#: pg_dump.c:9266 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "テーブル\"%s\"の列番号が不正です" -#: pg_dump.c:8955 +#: pg_dump.c:9328 #, c-format msgid "finding table default expressions" msgstr "テーブルのデフォルト式を探しています" -#: pg_dump.c:8997 +#: pg_dump.c:9370 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "テーブル\"%2$s\"用のadnumの値%1$dが不正です" -#: pg_dump.c:9091 +#: pg_dump.c:9463 +#, c-format +msgid "finding invalid not null constraints" +msgstr "未検証の非NULL制約を探しています" + +#: pg_dump.c:9561 #, c-format msgid "finding table check constraints" msgstr "テーブルのチェック制約を探しています" -#: pg_dump.c:9145 +#: pg_dump.c:9615 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "テーブル\"%2$s\"で想定する検査制約は%1$d個でしたが、%3$dありました" -#: pg_dump.c:9149 +#: pg_dump.c:9619 #, c-format msgid "The system catalogs might be corrupted." msgstr "システムカタログが破損している可能性があります。" -#: pg_dump.c:9839 +#: pg_dump.c:10411 #, c-format msgid "role with OID %u does not exist" msgstr "OID が %u であるロールは存在しません" -#: pg_dump.c:9951 pg_dump.c:9980 +#: pg_dump.c:10523 pg_dump.c:10552 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "非サポートのpg_init_privsエントリ: %u %u %d" -#: pg_dump.c:10527 +#: pg_dump.c:10843 +#, c-format +msgid "stats dumped out of order (current: %d %s %s) (expected: %d %s %s)" +msgstr "統計情報が異常な順序でダンプされています (現在: %d %s %s) (想定: %d %s %s)" + +#: pg_dump.c:10971 +#, c-format +msgid "attname cannot be NULL" +msgstr "attname はNULLにはできません" + +#: pg_dump.c:11000 +#, c-format +msgid "could not find index attname \"%s\"" +msgstr "\"%s\" というインデックスのattnameは見つかりませんでした" + +#: pg_dump.c:11486 #, c-format msgid "missing metadata for large objects \"%s\"" msgstr "ラージオブジェクト\"%s\"のメタデータがありません" -#: pg_dump.c:10810 +#: pg_dump.c:11772 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "データ型\"%s\"のtyptypeが不正なようです" -#: pg_dump.c:12384 +#: pg_dump.c:13348 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "関数\"%s\"のprovolatileの値が認識できません" -#: pg_dump.c:12434 pg_dump.c:14330 +#: pg_dump.c:13398 pg_dump.c:15294 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "関数\"%s\"のproparallel値が認識できません" -#: pg_dump.c:12564 pg_dump.c:12670 pg_dump.c:12677 +#: pg_dump.c:13528 pg_dump.c:13634 pg_dump.c:13641 #, c-format msgid "could not find function definition for function with OID %u" msgstr "OID %uの関数の関数定義が見つかりませんでした" -#: pg_dump.c:12603 +#: pg_dump.c:13567 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "pg_cast.castfuncまたはpg_cast.castmethodフィールドの値がおかしいです" -#: pg_dump.c:12606 +#: pg_dump.c:13570 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "pg_cast.castmethod フィールドの値がおかしいです" -#: pg_dump.c:12696 +#: pg_dump.c:13660 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "おかしな変換定義、trffromsql か trftosql の少なくとも一方は非ゼロであるはずです" -#: pg_dump.c:12713 +#: pg_dump.c:13677 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "pg_cast.castmethod フィールドの値がおかしいです" -#: pg_dump.c:12734 +#: pg_dump.c:13698 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "pg_cast.castmethod フィールドの値がおかしいです" -#: pg_dump.c:12879 +#: pg_dump.c:13843 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "後置演算子は今後サポートされません(演算子\"%s\")" -#: pg_dump.c:13049 +#: pg_dump.c:14013 #, c-format msgid "could not find operator with OID %s" msgstr "OID %sの演算子がありませんでした" -#: pg_dump.c:13117 +#: pg_dump.c:14081 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "アクセスメソッド\"%2$s\"の不正なタイプ\"%1$c\"" -#: pg_dump.c:13791 pg_dump.c:13859 +#: pg_dump.c:14755 pg_dump.c:14823 #, c-format msgid "unrecognized collation provider: %s" msgstr "認識できないの照合順序プロバイダ: %s" -#: pg_dump.c:13800 pg_dump.c:13807 pg_dump.c:13818 pg_dump.c:13828 -#: pg_dump.c:13843 +#: pg_dump.c:14764 pg_dump.c:14771 pg_dump.c:14782 pg_dump.c:14792 +#: pg_dump.c:14807 #, c-format msgid "invalid collation \"%s\"" msgstr "不正な照合順序\"%s\"" -#: pg_dump.c:14249 +#: pg_dump.c:15213 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "集約\"%s\"のaggfinalmodifyの値が識別できません" -#: pg_dump.c:14305 +#: pg_dump.c:15269 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "集約\"%s\"のaggmfinalmodifyの値が識別できません" -#: pg_dump.c:15022 +#: pg_dump.c:15989 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "デフォルト権限設定中の認識できないオブジェクト型: %d" -#: pg_dump.c:15038 +#: pg_dump.c:16005 #, c-format msgid "could not parse default ACL list (%s)" msgstr "デフォルトの ACL リスト(%s)をパースできませんでした" -#: pg_dump.c:15122 +#: pg_dump.c:16089 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "オブジェクト\"%3$s\"(%4$s)の初期ACLリスト(%1$s)またはデフォルト値(%2$s)をパースできませんでした" -#: pg_dump.c:15147 +#: pg_dump.c:16114 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "オブジェクト\"%3$s\"(%4$s)のACLリスト(%1$s)またはデフォルト値(%2$s)をパースできませんでした" -#: pg_dump.c:15690 +#: pg_dump.c:16657 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "ビュー\"%s\"の定義を取り出すための問い合わせがデータを返却しませんでした" -#: pg_dump.c:15693 +#: pg_dump.c:16660 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "ビュー\"%s\"の定義を取り出すための問い合わせが2つ以上の定義を返却しました" -#: pg_dump.c:15700 +#: pg_dump.c:16667 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "ビュー\"%s\"の定義が空のようです(長さが0)" -#: pg_dump.c:15784 +#: pg_dump.c:16752 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDSは今後サポートされません(テーブル\"%s\")" -#: pg_dump.c:16710 +#: pg_dump.c:17842 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "テーブル\"%2$s\"の列番号%1$dは不正です" -#: pg_dump.c:16788 +#: pg_dump.c:17920 #, c-format msgid "could not parse index statistic columns" msgstr "インデックス統計列をパースできませんでした" -#: pg_dump.c:16790 +#: pg_dump.c:17922 #, c-format msgid "could not parse index statistic values" msgstr "インデックス統計値をパースできませんでした" -#: pg_dump.c:16792 +#: pg_dump.c:17924 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "インデックス統計に対して列と値の数が合致しません" -#: pg_dump.c:17007 +#: pg_dump.c:18139 #, c-format msgid "missing index for constraint \"%s\"" msgstr "制約\"%s\"のインデックスが見つかりません" -#: pg_dump.c:17242 +#: pg_dump.c:18383 #, c-format msgid "unrecognized constraint type: %c" msgstr "制約のタイプが識別できません: %c" -#: pg_dump.c:17343 pg_dump.c:17572 +#: pg_dump.c:18436 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "認識されないシーケンスの型\"%s\"" + +#: pg_dump.c:18568 pg_dump.c:18800 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "シーケンス\"%s\"のデータを得るための問い合わせが%d行返却しました(想定は1)" -#: pg_dump.c:17375 +#: pg_dump.c:18604 #, c-format -msgid "unrecognized sequence type: %s" -msgstr "認識されないシーケンスの型\"%s\"" +msgid "unrecognized sequence type: %d" +msgstr "認識されないシーケンスの型: %d" -#: pg_dump.c:17889 +#: pg_dump.c:19133 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "テーブル\"%2$s\"のルール\"%1$s\"を得るための問い合わせが失敗しました: 間違った行数が返却されました" -#: pg_dump.c:18042 +#: pg_dump.c:19286 #, c-format msgid "could not find referenced extension %u" msgstr "親の機能拡張%uが見つかりません" -#: pg_dump.c:18141 +#: pg_dump.c:19385 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "機能拡張に対して設定と条件の数が一致しません" -#: pg_dump.c:18273 +#: pg_dump.c:19517 #, c-format msgid "reading dependency data" msgstr "データの依存データを読み込んでいます" -#: pg_dump.c:18359 +#: pg_dump.c:19603 #, c-format msgid "no referencing object %u %u" msgstr "参照元オブジェクト%u %uがありません" -#: pg_dump.c:18370 +#: pg_dump.c:19614 #, c-format msgid "no referenced object %u %u" msgstr "参照先オブジェクト%u %uがありません" -#: pg_dump.c:18795 pg_dump.c:18833 pg_dumpall.c:1962 pg_restore.c:551 -#: pg_restore.c:597 +#: pg_dump.c:20049 pg_dump.c:20087 pg_dumpall.c:1911 pg_restore.c:757 +#: pg_restore.c:803 #, c-format msgid "%s filter for \"%s\" is not allowed" msgstr "\"%2$s\"に対しては%1$sフィルターを指定できません" -#: pg_dump_sort.c:424 +#: pg_dump_sort.c:436 #, c-format msgid "invalid dumpId %d" msgstr "不正なdumpId %d" -#: pg_dump_sort.c:430 +#: pg_dump_sort.c:442 #, c-format msgid "invalid dependency %d" msgstr "不正な依存関係 %d" -#: pg_dump_sort.c:594 +#: pg_dump_sort.c:606 #, c-format msgid "could not identify dependency loop" msgstr "依存関係のループが見つかりませんでした" -#: pg_dump_sort.c:1209 +#: pg_dump_sort.c:1247 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "次のテーブルの中で外部キー制約の循環があります: " -#: pg_dump_sort.c:1214 +#: pg_dump_sort.c:1252 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "--disable-triggersの使用または一時的な制約の削除を行わずにこのダンプをリストアすることはできないかもしれません。" -#: pg_dump_sort.c:1215 +#: pg_dump_sort.c:1253 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "この問題を回避するために--data-onlyダンプの代わりに完全なダンプを使用することを検討してください。" -#: pg_dump_sort.c:1227 +#: pg_dump_sort.c:1265 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "以下の項目の間の依存関係のループを解決できませんでした:" -#: pg_dumpall.c:231 +#: pg_dumpall.c:244 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "%2$sには\"%1$s\"プログラムが必要ですが、\"%3$s\"と同じディレクトリにありませんでした。" -#: pg_dumpall.c:234 +#: pg_dumpall.c:247 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした。" -#: pg_dumpall.c:387 +#: pg_dumpall.c:402 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "--exclude-database オプションは -g/--globals-only、-r/--roles-only もしくは -t/--tablespaces-only と一緒には使用できません" -#: pg_dumpall.c:395 +#: pg_dumpall.c:410 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "-g/--globals-onlyと-r/--roles-onlyオプションは同時に使用できません" -#: pg_dumpall.c:402 +#: pg_dumpall.c:417 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "-g/--globals-onlyと-t/--tablespaces-onlyオプションは同時に使用できません" -#: pg_dumpall.c:412 +#: pg_dumpall.c:427 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "-r/--roles-onlyと-t/--tablespaces-onlyオプションは同時に使用できません" -#: pg_dumpall.c:474 pg_dumpall.c:1771 +#: pg_dumpall.c:442 #, c-format -msgid "could not connect to database \"%s\"" -msgstr "データベース\"%s\"へ接続できませんでした" +msgid "option -F/--format=d|c|t requires option -f/--file" +msgstr "オプション -F/--format=d|c|t はオプション -f/--file の指定が必要です" + +#: pg_dumpall.c:524 pg_restore.c:1050 pg_restore.c:1295 +#, c-format +msgid "could not open \"%s\": %m" +msgstr "\"%s\"をオープンできませんでした: %m" -#: pg_dumpall.c:486 +#: pg_dumpall.c:562 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2546,89 +2696,89 @@ msgstr "" "\"postgres\"または\"template1\"データベースに接続できませんでした\n" "代わりのデータベースを指定してください。" -#: pg_dumpall.c:634 +#: pg_dumpall.c:698 #, c-format msgid "" -"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"%s extracts a PostgreSQL database cluster based on specified dump format.\n" "\n" msgstr "" -"%sはPostgreSQLデータベースクラスタをSQLスクリプトファイルに展開します。\n" +"%sはPostgreSQLデータベースクラスタを指定されたダンプ形式で抽出します。\n" "\n" -#: pg_dumpall.c:636 +#: pg_dumpall.c:700 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [OPTION]...\n" -#: pg_dumpall.c:639 +#: pg_dumpall.c:703 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=ファイル名 出力ファイル名\n" -#: pg_dumpall.c:646 +#: pg_dumpall.c:712 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean 再作成前にデータベースを整理(削除)\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:714 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr "" " -g, --globals-only グローバルオブジェクトのみをダンプし、\n" " データベースをダンプしない\n" -#: pg_dumpall.c:649 pg_restore.c:475 +#: pg_dumpall.c:715 pg_restore.c:672 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner オブジェクトの所有権の復元を省略\n" -#: pg_dumpall.c:650 +#: pg_dumpall.c:716 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr "" " -r, --roles-only ロールのみをダンプ。\n" " データベースとテーブル空間をダンプしない\n" -#: pg_dumpall.c:652 +#: pg_dumpall.c:718 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr "" " -S, --superuser=NAME ダンプで使用するスーパーユーザーのユーザー名を\n" " 指定\n" -#: pg_dumpall.c:653 +#: pg_dumpall.c:719 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr "" " -t, --tablespaces-only テーブル空間のみをダンプ。データベースとロールを\n" " ダンプしない\n" -#: pg_dumpall.c:659 +#: pg_dumpall.c:725 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr " --exclude-database=PATTERN PATTERNに合致する名前のデータベースを除外\n" -#: pg_dumpall.c:661 +#: pg_dumpall.c:727 #, c-format -msgid " --filter=FILENAME exclude databases specified in FILENAME\n" -msgstr " --filter=FILENAME FILENAMEで指定されているデータベースを除外する\n" +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr " --filter=FILENAME FILENAMEで指定された式に基づいてデータベースを除外する\n" -#: pg_dumpall.c:667 +#: pg_dumpall.c:735 #, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords ロールのパスワードをダンプしない\n" -#: pg_dumpall.c:683 +#: pg_dumpall.c:757 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=CONSTR 接続文字列を用いた接続\n" -#: pg_dumpall.c:685 +#: pg_dumpall.c:759 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=DBNAME 代替のデフォルトデータベースを指定\n" -#: pg_dumpall.c:692 +#: pg_dumpall.c:766 #, c-format msgid "" "\n" @@ -2640,157 +2790,210 @@ msgstr "" "-f/--file が指定されない場合、SQLスクリプトは標準出力に書き出されます。\n" "\n" -#: pg_dumpall.c:837 +#: pg_dumpall.c:911 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "\"pg_\"で始まるロール名はスキップされました(%s)" -#: pg_dumpall.c:1059 +#. translator: %s represents a numeric role OID +#: pg_dumpall.c:1125 pg_dumpall.c:1183 pg_dumpall.c:1192 +#, c-format +msgid "found orphaned pg_auth_members entry for role %s" +msgstr "ロール %s に対する pg_auth_members エントリがありましたが、このロールは存在しません" + +#: pg_dumpall.c:1158 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "ロール\"%s\"のメンバーシップに対して正当なダンプ順序が見つかりませんでした" -#: pg_dumpall.c:1194 +#: pg_dumpall.c:1313 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "パラメータ\"%2$s\"のACLリスト(%1$s)をパースできませんでした" -#: pg_dumpall.c:1321 +#: pg_dumpall.c:1440 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "テーブル空間\"%2$s\"のACLリスト(%1$s)をパースできませんでした" -#: pg_dumpall.c:1528 +#: pg_dumpall.c:1657 +#, c-format +msgid "could not create subdirectory \"%s\": %m" +msgstr "サブディレクトリ\"%s\"を作成できませんでした: %m" + +#: pg_dumpall.c:1664 +#, c-format +msgid "could not open map file: %s" +msgstr "マップファイルを開くことができませんでした: %s" + +#: pg_dumpall.c:1681 pg_restore.c:1004 #, c-format msgid "excluding database \"%s\"" msgstr "データベース\"%s\"を除外します" -#: pg_dumpall.c:1532 +#: pg_dumpall.c:1702 #, c-format msgid "dumping database \"%s\"" msgstr "データベース\"%s\"をダンプしています" -#: pg_dumpall.c:1563 +#: pg_dumpall.c:1731 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "データベース\"%s\"のダンプが失敗しました、終了します" -#: pg_dumpall.c:1569 +#: pg_dumpall.c:1744 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "出力ファイル\"%s\"を再オープンできませんでした: %m" -#: pg_dumpall.c:1613 +#: pg_dumpall.c:1812 #, c-format msgid "running \"%s\"" msgstr "\"%s\"を実行しています" -#: pg_dumpall.c:1814 -#, c-format -msgid "could not get server version" -msgstr "サーバーバージョンを取得できませんでした" - -#: pg_dumpall.c:1817 -#, c-format -msgid "could not parse server version \"%s\"" -msgstr "サーバーバージョン\"%s\"をパースできませんでした" - -#: pg_dumpall.c:1887 pg_dumpall.c:1910 -#, c-format -msgid "executing %s" -msgstr "%s を実行しています" - -#: pg_dumpall.c:1982 +#: pg_dumpall.c:1931 msgid "unsupported filter object" msgstr "サポートされていないフィルターオブジェクト" -#: pg_restore.c:329 +#: pg_dumpall.c:1974 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", \"p\", or \"t\"" +msgstr "アーカイブ形式\"%s\"が認識できません; \"c\"、\"d\"、\"p\" または\"t\"を指定してください" + +#: pg_restore.c:373 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "-d/--dbnameと-f/--fileのどちらか一方が指定されていなければなりません" -#: pg_restore.c:336 +#: pg_restore.c:377 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only" +msgstr "オプション --exclude-database は -g/--globals-only と一緒には使用できません" + +#: pg_restore.c:387 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "オプション-d/--dbnameと-f/--fileは同時に使用できません" -#: pg_restore.c:350 +#: pg_restore.c:422 #, c-format msgid "options -1/--single-transaction and --transaction-size cannot be used together" msgstr "オプション -1/--single-transaction と --transaction-size とは同時には使用できません" -#: pg_restore.c:357 +#: pg_restore.c:429 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "オプション-C/--createと-1/--single-transactionとは同時には使用できません" -#: pg_restore.c:361 +#: pg_restore.c:433 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "--single-transaction と複数ジョブは同時には指定できません" -#: pg_restore.c:399 +#: pg_restore.c:481 +#, c-format +msgid "archive format \"%s\" is not supported; please use psql" +msgstr "アーカイブ形式\"%s\"はサポートされていません、psqlを使ってください" + +#: pg_restore.c:485 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "アーカイブ形式\"%s\"が認識できません; \"c\"、\"d\"または\"t\"を指定してください" -#: pg_restore.c:438 +#: pg_restore.c:506 +#, c-format +msgid "option -l/--list cannot be used when restoring an archive created by pg_dumpall" +msgstr "オプション -l/--list はpg_dumpallで作成されたアーカイブの復元では使用できません" + +#: pg_restore.c:508 +#, c-format +msgid "option -L/--use-list cannot be used when restoring an archive created by pg_dumpall" +msgstr "オプション-L/--use-list はpg_dumpallで作成されたアーカイブの復元では使用できません" + +#: pg_restore.c:516 +#, c-format +msgid "-C/--create option should be specified when restoring an archive created by pg_dumpall" +msgstr "pg_dumpallで作成されたアーカイブを復元する際には、-C/--create オプションの指定が必要です" + +#: pg_restore.c:518 +#, c-format +msgid "Individual databases can be restored using their specific archives." +msgstr "各々のデータベースは対応するアーカイブを使って復元できます。" + +#: pg_restore.c:550 +#, c-format +msgid "database restoring skipped as -g/--globals-only option was specified" +msgstr "-g/--globals-only オプションが指定されているため、データベースの復元はスキップされました" + +#: pg_restore.c:565 +#, c-format +msgid "option --exclude-database can be used only when restoring an archive created by pg_dumpall" +msgstr "オプション --exclude-database はpg_dumpallで作成したアーカイブの復元時のみ使用できます" + +#: pg_restore.c:568 +#, c-format +msgid "option -g/--globals-only can be used only when restoring an archive created by pg_dumpall" +msgstr "オプション -g/--globals-only はpg_dumpallで作成したアーカイブの復元時のみ使用できます" + +#: pg_restore.c:576 #, c-format msgid "errors ignored on restore: %d" msgstr "リストア中に無視されたエラー数: %d" -#: pg_restore.c:451 +#: pg_restore.c:646 #, c-format msgid "" -"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"%s restores a PostgreSQL database from an archive created by pg_dump or pg_dumpall.\n" +"If the archive is created by pg_dumpall, then restores multiple databases also.\n" "\n" msgstr "" -"%sはpg_dumpで作成したアーカイブからPostgreSQLデータベースをリストアします。\n" +"%sはpg_dumpまたはpg_dumpallで作成したアーカイブからPostgreSQLデータベースを復元します。\n" +"pg_dumpallで作成されたものの場合は、複数のデータベースを復元します。\n" "\n" -#: pg_restore.c:453 +#: pg_restore.c:649 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [OPTION]... [FILE]\n" -#: pg_restore.c:456 +#: pg_restore.c:652 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NAME 接続するデータベース名\n" -#: pg_restore.c:457 +#: pg_restore.c:653 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FILENAME 出力ファイル名(- で標準出力)\n" -#: pg_restore.c:458 +#: pg_restore.c:654 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr "" " -F, --format=c|d|t バックアップファイルの形式\n" " (自動的に設定されるはずです)\n" -#: pg_restore.c:459 +#: pg_restore.c:655 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list アーカイブのTOCの要約を表示\n" -#: pg_restore.c:460 +#: pg_restore.c:656 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose 冗長モード\n" -#: pg_restore.c:461 +#: pg_restore.c:657 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示し、終了します\n" -#: pg_restore.c:462 +#: pg_restore.c:658 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示し、終了します\n" -#: pg_restore.c:464 +#: pg_restore.c:660 #, c-format msgid "" "\n" @@ -2799,32 +3002,39 @@ msgstr "" "\n" "リストア制御用のオプション:\n" -#: pg_restore.c:465 +#: pg_restore.c:661 #, c-format msgid " -a, --data-only restore only the data, no schema\n" -msgstr " -a, --data-only データのみをリストア。スキーマをリストアしません\n" +msgstr " -a, --data-only データのみをリストア。スキーマをリストアしない\n" -#: pg_restore.c:467 +#: pg_restore.c:663 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create 対象のデータベースを作成\n" -#: pg_restore.c:468 +#: pg_restore.c:664 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error エラー時に終了。デフォルトは継続\n" -#: pg_restore.c:469 +#: pg_restore.c:665 +#, c-format +msgid " -g, --globals-only restore only global objects, no databases\n" +msgstr "" +" -g, --globals-only グローバルオブジェクトのみを復元し、\n" +" データベースを復元しない\n" + +#: pg_restore.c:666 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAME 指名したインデックスをリストア\n" -#: pg_restore.c:470 +#: pg_restore.c:667 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM リストア時に指定した数の並列ジョブを使用\n" -#: pg_restore.c:471 +#: pg_restore.c:668 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2833,57 +3043,62 @@ msgstr "" " -L, --use-list=FILENAME このファイルの内容に従って SELECT や\n" " 出力のソートを行います\n" -#: pg_restore.c:473 +#: pg_restore.c:670 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME 指定したスキーマのオブジェクトのみをリストア\n" -#: pg_restore.c:474 +#: pg_restore.c:671 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NAME 指定したスキーマのオブジェクトはリストアしない\n" -#: pg_restore.c:476 +#: pg_restore.c:673 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NAME(args) 指名された関数をリストア\n" -#: pg_restore.c:477 +#: pg_restore.c:674 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" -msgstr " -s, --schema-only スキーマのみをリストア。データをリストアしません\n" +msgstr " -s, --schema-only スキーマのみをリストア。データをリストアしない\n" -#: pg_restore.c:478 +#: pg_restore.c:675 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr " -S, --superuser=NAME トリガを無効にするためのスーパーユーザーの名前\n" -#: pg_restore.c:479 +#: pg_restore.c:676 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NAME 指名したリレーション(テーブル、ビューなど)をリストア\n" -#: pg_restore.c:480 +#: pg_restore.c:677 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAME 指名したトリガをリストア\n" -#: pg_restore.c:481 +#: pg_restore.c:678 +#, c-format +msgid " --exclude-database=PATTERN exclude databases whose name matches with pattern\n" +msgstr " --exclude-database=<パターン> <パターン>に合致する名前のデータベースを除外\n" + +#: pg_restore.c:679 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges アクセス権限(grant/revoke)の復元を省略\n" -#: pg_restore.c:482 +#: pg_restore.c:680 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction 単一のトランザクションとしてリストア\n" -#: pg_restore.c:484 +#: pg_restore.c:682 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security 行セキュリティを有効にします\n" -#: pg_restore.c:485 +#: pg_restore.c:683 #, c-format msgid "" " --filter=FILENAME restore or skip objects based on expressions\n" @@ -2892,72 +3107,97 @@ msgstr "" " --filter=FILENAME オブジェクトの復元またはスキップをFILENAMEに\n" " 記述されている式を元に行う\n" -#: pg_restore.c:488 +#: pg_restore.c:686 +#, c-format +msgid " --no-comments do not restore comment commands\n" +msgstr " --no-comments コメントコマンドをリストアしない\n" + +#: pg_restore.c:687 #, c-format -msgid " --no-comments do not restore comments\n" -msgstr " --no-comments コメントをリストアしない\n" +msgid " --no-data do not restore data\n" +msgstr " --no-data データをリストアしない\n" -#: pg_restore.c:489 +#: pg_restore.c:688 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" " created\n" msgstr "" " --no-data-for-failed-tables 作成できなかったテーッブルのデータはリストア\n" -" しません\n" +" しない\n" -#: pg_restore.c:491 +#: pg_restore.c:690 +#, c-format +msgid " --no-policies do not restore row security policies\n" +msgstr " --no-policies 行セキュリティポリシーをリストアしない\n" + +#: pg_restore.c:691 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications パブリケーションをリストアしない\n" -#: pg_restore.c:492 +#: pg_restore.c:692 +#, c-format +msgid " --no-schema do not restore schema\n" +msgstr " --no-schema スキーマをリストアしない\n" + +#: pg_restore.c:693 #, c-format msgid " --no-security-labels do not restore security labels\n" -msgstr " --no-security-labels セキュリティラベルをリストアしません\n" +msgstr " --no-security-labels セキュリティラベルをリストアしない\n" -#: pg_restore.c:493 +#: pg_restore.c:694 +#, c-format +msgid " --no-statistics do not restore statistics\n" +msgstr " --no-statistics 統計情報をリストアしない\n" + +#: pg_restore.c:695 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions サブスクリプションをリストアしない\n" -#: pg_restore.c:494 +#: pg_restore.c:696 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method テーブルアクセスメソッドをリストアしない\n" -#: pg_restore.c:495 +#: pg_restore.c:697 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" -msgstr " --no-tablespaces テーブル空間の割り当てをリストアしません\n" +msgstr " --no-tablespaces テーブル空間の割り当てをリストアしない\n" -#: pg_restore.c:496 +#: pg_restore.c:698 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr " --section=SECTION 指定されたセクション(データ前部、データ、データ後部)をリストア\n" -#: pg_restore.c:499 +#: pg_restore.c:699 +#, c-format +msgid " --statistics-only restore only the statistics, not schema or data\n" +msgstr " --statistics-only 統計情報のみをリストア、スキーマまたはデータをリストアしない\n" + +#: pg_restore.c:702 #, c-format msgid " --transaction-size=N commit after every N objects\n" msgstr " --transaction-size=N Nオブジェクトごとにコミットします\n" -#: pg_restore.c:510 +#: pg_restore.c:716 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME リストアに先立って SET ROLE します\n" -#: pg_restore.c:512 +#: pg_restore.c:718 #, c-format msgid "" "\n" -"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" -"multiple times to select multiple objects.\n" +"The options -I, -n, -N, -P, -t, -T, --section, and --exclude-database can be combined\n" +"and specified multiple times to select multiple objects.\n" msgstr "" "\n" -" -I, -n, -N, -P, -t, -T および --section オプションは組み合わせて複数回\n" -"指定することで複数のオブジェクトを指定できます。\n" +"オプション -I、-n、-N、-P、-t、-T、--section および --exclude-databaseを組み\n" +"合わせて複数回指定することで複数のオブジェクトを指定できます。\n" -#: pg_restore.c:515 +#: pg_restore.c:721 #, c-format msgid "" "\n" @@ -2967,3 +3207,95 @@ msgstr "" "\n" "入力ファイル名が指定されない場合、標準入力が使用されます。\n" "\n" + +#: pg_restore.c:940 +#, c-format +msgid "considering PATTERN as NAME for --exclude-database option as no db connection while doing pg_restore." +msgstr "pg_restoreの実行中にDB接続がないため、--exclude-database オプションの<パターン>は<名前>とみなします。" + +#: pg_restore.c:985 +#, c-format +msgid "database \"%s\" matches exclude pattern: \"%s\"" +msgstr "データベース\"%s\"は除外パターンに合致します: \"%s\"" + +#: pg_restore.c:1040 +#, c-format +msgid "database restoring is skipped as \"map.dat\" is not present in \"%s\"" +msgstr "\"%s\"に \"map.dat\" がないため、データベースの復元をスキップします" + +#: pg_restore.c:1069 +#, c-format +msgid "found database \"%s\" (OID: %u) in \"%s\"" +msgstr "\"%3$s\" 内でデータベース \"%1$s\" (OID: %2$u) を検出しました。" + +#: pg_restore.c:1074 +#, c-format +msgid "invalid entry in \"%s\" at line : %d" +msgstr "\"%s\" 内に不正なエントリ: 行 %d" + +#: pg_restore.c:1123 +#, c-format +msgid "found %d database names in \"map.dat\"" +msgstr "\"map.dat\" 内に %d 個のデータベースを検出しました" + +#: pg_restore.c:1127 +#, c-format +msgid "trying to connect database \"postgres\"" +msgstr "データベース\"postgres\"に接続を試みています" + +#: pg_restore.c:1136 +#, c-format +msgid "trying to connect database \"template1\"" +msgstr "データベース\"template1\"に接続を試みています" + +#: pg_restore.c:1160 +#, c-format +msgid "no database needs to restore out of %d databases" +msgstr "%d 個のデータベースの中で復元が必要なものはありません" + +#: pg_restore.c:1164 +#, c-format +msgid "need to restore %d databases out of %d databases" +msgstr "%2$d 個のうち %1$d 個のデータベースの復元が必要です" + +#: pg_restore.c:1213 +#, c-format +msgid "restoring database \"%s\"" +msgstr "データベース\"%s\"の復元中" + +#: pg_restore.c:1254 +#, c-format +msgid "errors ignored on database \"%s\" restore: %d" +msgstr "データベース\"%s\"の復元中に無視されたエラー数: %d" + +#: pg_restore.c:1261 +#, c-format +msgid "number of restored databases is %d" +msgstr "復元されたデータベースの数は %d です" + +#: pg_restore.c:1324 +#, c-format +msgid "executing query: %s" +msgstr "実行クエリ: %s" + +#: pg_restore.c:1335 +#, c-format +msgid "" +"could not execute query: \"%s\" \n" +"Command was: \"%s\"" +msgstr "" +"クエリを実行できませんでした: \"%s\"\n" +"コマンドは: \"%s\"" + +#: pg_restore.c:1342 +#, c-format +msgid "ignored %d errors in \"%s\"" +msgstr "\"%2$s\" 内のエラー%1$d件を無視しました" + +#: pg_restore.c:1373 +#, c-format +msgid "could not open file: \"%s\"" +msgstr "ファイルを開くことができませんでした: \"%s\"" + +#~ msgid "could not close directory \"%s\": %m" +#~ msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" diff --git a/src/bin/pg_dump/po/ka.po b/src/bin/pg_dump/po/ka.po index 7b08ff6f9a27f..c045ae7574845 100644 --- a/src/bin/pg_dump/po/ka.po +++ b/src/bin/pg_dump/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_dump (PostgreSQL) 17\n" +"Project-Id-Version: pg_dump (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:22+0000\n" -"PO-Revision-Date: 2024-06-14 06:14+0200\n" +"POT-Creation-Date: 2025-05-02 22:21+0000\n" +"PO-Revision-Date: 2025-05-03 01:26+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,31 +16,31 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "warning: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " #: ../../common/compression.c:132 ../../common/compression.c:141 #: ../../common/compression.c:150 compress_gzip.c:413 compress_gzip.c:420 -#: compress_io.c:109 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 +#: compress_io.c:108 compress_lz4.c:780 compress_lz4.c:787 compress_zstd.c:25 #: compress_zstd.c:31 #, c-format msgid "this build does not support compression with %s" @@ -110,27 +110,27 @@ msgstr "გასაშვებად ფაილის \"%s\" პოვნა msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "ბილიკის (\"%s\") აბსოლუტურ ფორმაში ამოხსნის შეცდომა: %m" -#: ../../common/exec.c:382 +#: ../../common/exec.c:363 #, c-format msgid "could not execute command \"%s\": %m" msgstr "ბრძანების (\"%s\") შესრულების შეცდომა: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "ბრძანებიდან \"%s\" წაკითხვის შეცდომა: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "ბრძანებამ \"%s\" მონაცემები არ დააბრუნა" -#: ../../common/exec.c:424 parallel.c:1609 +#: ../../common/exec.c:405 parallel.c:1621 #, c-format msgid "%s() failed: %m" msgstr "%s()-ის შეცდომა: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" @@ -145,45 +145,44 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 dumputils.c:905 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 -#: pg_backup_directory.c:182 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -233,242 +232,242 @@ msgstr "%s არაა საზღვრებში %d-დან %d-მდე msgid "unrecognized sync method: %s" msgstr "უცნობი სინქრონიზაციის მეთოდი: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: common.c:135 +#: common.c:111 #, c-format msgid "reading extensions" msgstr "გაფართოებების წაკითხვა" -#: common.c:138 +#: common.c:114 #, c-format msgid "identifying extension members" msgstr "გაფართოების ნომრების იდენტიფიკაცია" -#: common.c:141 +#: common.c:117 #, c-format msgid "reading schemas" msgstr "სქემების კითხვა" -#: common.c:150 +#: common.c:126 #, c-format msgid "reading user-defined tables" msgstr "მომხმარებლის მიერ განსაზღვრული ცხრილების კითხვა" -#: common.c:155 +#: common.c:131 #, c-format msgid "reading user-defined functions" msgstr "მომხმარებლის მიერ განსაზღვრული ფუნქციების კითხვა" -#: common.c:159 +#: common.c:135 #, c-format msgid "reading user-defined types" msgstr "მომხმარებლის მიერ განსაზღვრული ტიპების კითხვა" -#: common.c:163 +#: common.c:139 #, c-format msgid "reading procedural languages" msgstr "პროცედურული ენების კითხვა" -#: common.c:166 +#: common.c:142 #, c-format msgid "reading user-defined aggregate functions" msgstr "მომხმარებლის მიერ განსაზღვრული აგრეგატული ფუნქციების კითხვა" -#: common.c:169 +#: common.c:145 #, c-format msgid "reading user-defined operators" msgstr "მომხმარებლის მიერ განსაზღვრული ოპერატორების კითხვა" -#: common.c:172 +#: common.c:148 #, c-format msgid "reading user-defined access methods" msgstr "მომხმარებლის მიერ განსაზღვრული წვდომის მეთოდების კითხვა" -#: common.c:175 +#: common.c:151 #, c-format msgid "reading user-defined operator classes" msgstr "მომხმარებლის მიერ განსაზღვრული ოპერატორის კლასების კითხვა" -#: common.c:178 +#: common.c:154 #, c-format msgid "reading user-defined operator families" msgstr "მომხმარებლის მიერ განსაზღვრული ოპერატორის ოჯახების კითხვა" -#: common.c:181 +#: common.c:157 #, c-format msgid "reading user-defined text search parsers" msgstr "მომხმარებლის მიერ განსაზღვრული ტექსტის ძებნის დამმუშავებლების კითხვა" -#: common.c:184 +#: common.c:160 #, c-format msgid "reading user-defined text search templates" msgstr "მომხმარებლის მიერ განსაზღვრული ტექსტის ძებნის შაბლონების კითხვა" -#: common.c:187 +#: common.c:163 #, c-format msgid "reading user-defined text search dictionaries" msgstr "მომხმარებლის მიერ განსაზღვრული ტექსტის ძებნის ლექსიკონების კითხვა" -#: common.c:190 +#: common.c:166 #, c-format msgid "reading user-defined text search configurations" msgstr "მომხმარებლის მიერ განსაზღვრული ტექსტის ძებნის კონფიგურაციების კითხვა" -#: common.c:193 +#: common.c:169 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "მომხმარებლის მიერ განსაზღვრული გარე მონაცემების გადამტანების კითხვა" -#: common.c:196 +#: common.c:172 #, c-format msgid "reading user-defined foreign servers" msgstr "მომხმარებლის მიერ განსაზღვრული გარე სერვერების კითხვა" -#: common.c:199 +#: common.c:175 #, c-format msgid "reading default privileges" msgstr "ნაგულისხმევი წვდომების კითხვა" -#: common.c:202 +#: common.c:178 #, c-format msgid "reading user-defined collations" msgstr "მომხმარებლის მიერ განსაზღვრული კოლაციების კითხვა" -#: common.c:205 +#: common.c:181 #, c-format msgid "reading user-defined conversions" msgstr "მომხმარებლის მიერ განსაზღვრული გადაყვანების კითხვა" -#: common.c:208 +#: common.c:184 #, c-format msgid "reading type casts" msgstr "ტიპის კასტების კითხვა" -#: common.c:211 +#: common.c:187 #, c-format msgid "reading transforms" msgstr "გარდაქმნების კითხვა" -#: common.c:214 +#: common.c:190 #, c-format msgid "reading table inheritance information" msgstr "ცხრილების მეკვიდრეობითობის ინფორმაციის კითხვა" -#: common.c:217 +#: common.c:193 #, c-format msgid "reading event triggers" msgstr "მოვლენების ტრიგერების კითხვა" -#: common.c:221 +#: common.c:197 #, c-format msgid "finding extension tables" msgstr "გაფართოების ცხრილების მოძებნა" -#: common.c:225 +#: common.c:201 #, c-format msgid "finding inheritance relationships" msgstr "მემკვიდრეობითი ურთიერთობების მოძებნა" -#: common.c:228 +#: common.c:204 #, c-format msgid "reading column info for interesting tables" msgstr "საინტერესო ცხრილების სვეტების ინფორმაციის კითხვა" -#: common.c:231 +#: common.c:207 #, c-format msgid "flagging inherited columns in subtables" msgstr "ქვეცხრილებში მემკვიდრეობით სვეტებზე ალმის დასმა" -#: common.c:234 +#: common.c:210 #, c-format msgid "reading partitioning data" msgstr "დანაყოფების მონაცემების კითხვა" -#: common.c:237 +#: common.c:213 #, c-format msgid "reading indexes" msgstr "ინდექსების კითხვა" -#: common.c:240 +#: common.c:216 #, c-format msgid "flagging indexes in partitioned tables" msgstr "დაყოფილ ცხრილებში ინდექსებზე ალმის დასმა" -#: common.c:243 +#: common.c:219 #, c-format msgid "reading extended statistics" msgstr "გაფართოებული სტატისტიკის კითხვა" -#: common.c:246 +#: common.c:222 #, c-format msgid "reading constraints" msgstr "შეზღუდვების კითხვა" -#: common.c:249 +#: common.c:225 #, c-format msgid "reading triggers" msgstr "ტრიგერების კითხვა" -#: common.c:252 +#: common.c:228 #, c-format msgid "reading rewrite rules" msgstr "გადაწერის წესების კითხვა" -#: common.c:255 +#: common.c:231 #, c-format msgid "reading policies" msgstr "წესების კითხვა" -#: common.c:258 +#: common.c:234 #, c-format msgid "reading publications" msgstr "გამოცემების კითხვა" -#: common.c:261 +#: common.c:237 #, c-format msgid "reading publication membership of tables" msgstr "ცხრილების გამოცემის წევრობის კითხვა" -#: common.c:264 +#: common.c:240 #, c-format msgid "reading publication membership of schemas" msgstr "სქემების გამოცემის წევრობის კითხვა" -#: common.c:267 +#: common.c:243 #, c-format msgid "reading subscriptions" msgstr "გამოწერების კითხვა" -#: common.c:270 +#: common.c:246 #, c-format msgid "reading subscription membership of tables" msgstr "ცხრილების გამოწერის წევრობის კითხვა" -#: common.c:333 +#: common.c:309 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "სისწორის შემოწმების შეცდომა. ცხრილის (\"%2$s\", OID %3$u) მშობელი OID (%1$u) არ არსებობს" -#: common.c:375 +#: common.c:351 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "მშობლების არასწორი რაოდენობა %d ცხრილისთვის \"%s\"" -#: common.c:1098 +#: common.c:1109 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "რიცხვითი მასივის \"%s\" დამუშავების შეცდომა: მეტისმეტად ბევრი რიცხვი" -#: common.c:1110 +#: common.c:1121 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "რიცხვითი მასივის \"%s\" დამუშავების შეცდომა: რიცხვში არასწორის სიმბოლოებია" @@ -504,13 +503,13 @@ msgid "could not read from input file: %s" msgstr "შეყვანის ფაილების წაკითხვის შეცდომა: %s" #: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 -#: compress_zstd.c:373 pg_backup_custom.c:651 +#: compress_zstd.c:375 pg_backup_custom.c:650 #, c-format msgid "could not read from input file: %m" msgstr "შემოსატანი ფაილის წაკითხვის შეცდომა: %m" #: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 -#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: compress_zstd.c:373 pg_backup_custom.c:648 pg_backup_directory.c:533 #: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" @@ -551,93 +550,163 @@ msgstr "დეკომპრესიის დასრულების შ msgid "could not set compression parameter \"%s\": %s" msgstr "შეკუმშვის პარამეტრის (%s) დაყენების შეცდომა: %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:233 compress_zstd.c:492 +#: compress_zstd.c:500 #, c-format msgid "could not initialize compression library" msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზაციის შეცდომა" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:196 compress_zstd.c:310 #, c-format msgid "could not decompress data: %s" msgstr "მონაცემების გაშლის შეცდომა: %s" -#: compress_zstd.c:501 +#: compress_zstd.c:503 #, c-format msgid "unhandled mode \"%s\"" msgstr "დაუმუშავებელი რეჟიმი \"%s\"" -#: filter.c:49 +#: connectdb.c:56 connectdb.c:165 pg_backup_db.c:126 +msgid "Password: " +msgstr "პაროლი: " + +#: connectdb.c:83 connectdb.c:174 pg_backup_db.c:203 pg_dump.c:925 +#: pg_dump_sort.c:1251 pg_dump_sort.c:1271 +#, c-format +msgid "%s" +msgstr "%s" + +#: connectdb.c:157 pg_dumpall.c:548 pg_restore.c:544 +#, c-format +msgid "could not connect to database \"%s\"" +msgstr "მონაცემთა ბაზასთან დაკავშირება ვერ მოხერხდა \"%s\"" + +#: connectdb.c:201 +#, c-format +msgid "could not get server version" +msgstr "სერვერის ვერსიის მღების შეცდომა" + +#: connectdb.c:205 +#, c-format +msgid "could not parse server version \"%s\"" +msgstr "შერვერის ვერსიის დამუშავების შეცდომა: %s" + +#: connectdb.c:222 pg_backup_db.c:52 +#, c-format +msgid "aborting because of server version mismatch" +msgstr "ოპერაცია გაუქმდა სერვერის ვერსიის შეუთავსებლობის გამო" + +#: connectdb.c:223 pg_backup_db.c:53 +#, c-format +msgid "server version: %s; %s version: %s" +msgstr "სერვერის ვერსია: %s; %s ვერსია: %s" + +#: connectdb.c:282 pg_dumpall.c:1859 +#, c-format +msgid "executing %s" +msgstr "%s -ის შესრულება" + +#: connectdb.c:288 pg_backup_db.c:210 pg_dumpall.c:1865 +#, c-format +msgid "query failed: %s" +msgstr "მოთხოვნის შეცდომა: %s" + +#: connectdb.c:289 pg_backup_db.c:212 pg_dumpall.c:1866 +#, c-format +msgid "Query was: %s" +msgstr "მოთხოვნის შინაარსი: %s" + +#: dumputils.c:910 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" + +#: dumputils.c:915 +#, c-format +msgid "could not change permissions of directory \"%s\": %m" +msgstr "საქაღალდის წვდომების შეცვლა შეუძლებელია \"%s\": %m" + +#: dumputils.c:920 +#, c-format +msgid "directory \"%s\" is not empty" +msgstr "საქაღალდე \"%s\" მაგრამ ცარიელი არაა" + +#: filter.c:48 #, c-format msgid "could not open filter file \"%s\": %m" msgstr "ფილტრის ფაილის \"%s\" გახსნის შეცდომა: %m" -#: filter.c:72 +#: filter.c:71 #, c-format msgid "could not close filter file \"%s\": %m" msgstr "ფილტრის ფაილის \"%s\" დახურვის შეცდომა: %m" #: filter.c:164 #, c-format -msgid "invalid format in filter read from \"%s\" on line %d: %s" -msgstr "არასწორი ფორმატი ფილტრში, რომელიც წავიკითხე \"%s\"-დან, ხაზზე %d: %s" +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "არასწორი ფორმატი ფილტრში, რომელიც წავიკითხე სტანდარტული შეყვანიდან, ხაზზე %d: %s" -#: filter.c:239 filter.c:466 +#: filter.c:167 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "არასწორი ფორმატი ფილტრში, რომელიც წავიკითხე ფაილიდან \"%s\", ხაზზე %d: %s" + +#: filter.c:240 filter.c:467 #, c-format msgid "could not read from filter file \"%s\": %m" msgstr "ფილტრის ფაილიდან \"%s\" წაკითხვა შეუძლებელია: %m" -#: filter.c:242 +#: filter.c:243 msgid "unexpected end of file" msgstr "ფაილის მოულოდნელი დასასრული" -#: filter.c:309 +#: filter.c:310 msgid "missing object name pattern" msgstr "აკლია ობიექტის სახელის ნიმუში" -#: filter.c:420 +#: filter.c:421 msgid "no filter command found (expected \"include\" or \"exclude\")" msgstr "ფილტრის ბრძანება ვერ ვიპოვე (მოველოდი \"include\" ან \"exclude\")" -#: filter.c:431 +#: filter.c:432 msgid "invalid filter command (expected \"include\" or \"exclude\")" msgstr "არასწორი ფილტრის ბრძანება (მოველოდი \"include\" ან \"exclude\")" -#: filter.c:438 +#: filter.c:439 msgid "missing filter object type" msgstr "აკლია ფილტრის ობიექტის ტიპი" -#: filter.c:445 +#: filter.c:446 #, c-format msgid "unsupported filter object type: \"%.*s\"" msgstr "მხარდაუჭერელი ფილტრის ობიექტის ტიპი: \"%.*s\"" -#: parallel.c:251 +#: parallel.c:253 #, c-format msgid "%s() failed: error code %d" msgstr "%s() -ის შეცდომა: შეცდომის კოდი: %d" -#: parallel.c:959 +#: parallel.c:971 #, c-format msgid "could not create communication channels: %m" msgstr "საკომუნიკაციო არხების შექმნა ვერ მოხერხდა: %m" -#: parallel.c:1016 +#: parallel.c:1028 #, c-format msgid "could not create worker process: %m" msgstr "დამხმარე პროცესის შექმნა შეუძლებელია: %m" -#: parallel.c:1146 +#: parallel.c:1158 #, c-format msgid "unrecognized command received from leader: \"%s\"" msgstr "თავსართიდან მიღებული ბრძანება უცნობია: %s" -#: parallel.c:1189 parallel.c:1427 +#: parallel.c:1201 parallel.c:1439 #, c-format msgid "invalid message received from worker: \"%s\"" msgstr "დამხმარე პროცესისგან მიღებულია არასწორი შეტყობინება: %s" -#: parallel.c:1321 +#: parallel.c:1333 #, c-format msgid "" "could not obtain lock on relation \"%s\"\n" @@ -646,727 +715,688 @@ msgstr "" "ურთიერთობის (\"%s\") დაბლოკვის შეცდომა\n" "ეს ჩვეულებრივ ნიშნავს, რომ ვინმემ მოითხოვა ACCESS EXCLUSIVE ბლოკი ცხრილზე მას შემდეგ, რაც pg_dump-ის მშობელმა პროცესმა საწყისი ACCESS SHARE ბლოკი ცხრილზე უკვე მიიღო." -#: parallel.c:1410 +#: parallel.c:1422 #, c-format msgid "a worker process died unexpectedly" msgstr "დამხმარე პროტოკოლის პროცესი მოულოდნელად მოკვდა" -#: parallel.c:1532 parallel.c:1650 +#: parallel.c:1544 parallel.c:1662 #, c-format msgid "could not write to the communication channel: %m" msgstr "საკომუნიკაციო არხში ჩაწერის შეცდომა: %m" -#: parallel.c:1734 +#: parallel.c:1746 #, c-format msgid "pgpipe: could not create socket: error code %d" msgstr "pgpipe: სოკეტის შექმნის შეცდომა. შეცდომის კოდი: %d" -#: parallel.c:1745 +#: parallel.c:1757 #, c-format msgid "pgpipe: could not bind: error code %d" msgstr "pgpipe: მიბმის შეცდომა: შეცდომის კოდი: %d" -#: parallel.c:1752 +#: parallel.c:1764 #, c-format msgid "pgpipe: could not listen: error code %d" msgstr "pgpipe: მოსმენის შეცდომა: შეცდომის კოდი: %d" -#: parallel.c:1759 +#: parallel.c:1771 #, c-format msgid "pgpipe: %s() failed: error code %d" msgstr "pgpipe: %s() -ის შეცდომა: შეცდომის კოდი %d" -#: parallel.c:1770 +#: parallel.c:1782 #, c-format msgid "pgpipe: could not create second socket: error code %d" msgstr "pgpipe: მეორე სოკეტის შექნა შეუძლებელია: შეცდომის კოდი: %d" -#: parallel.c:1779 +#: parallel.c:1791 #, c-format msgid "pgpipe: could not connect socket: error code %d" msgstr "pgpipe: სოკეტთან მიერთების შეცდომა: შეცდომის კოდი %d" -#: parallel.c:1788 +#: parallel.c:1800 #, c-format msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: შეერთების დადასტურება შეუძლებელია: შეცდომის კოდი %d" -#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 +#: pg_backup_archiver.c:269 pg_backup_archiver.c:1732 #, c-format msgid "could not close output file: %m" msgstr "გამოტანის ფაილის დახურვის შეცდომა: %m" -#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 +#: pg_backup_archiver.c:313 pg_backup_archiver.c:317 #, c-format msgid "archive items not in correct section order" msgstr "არქივის ჩანაწერების მიმდევრობა არასწორია" -#: pg_backup_archiver.c:315 +#: pg_backup_archiver.c:323 #, c-format msgid "unexpected section code %d" msgstr "სექციის მოულოდნელი კოდი %d" -#: pg_backup_archiver.c:352 +#: pg_backup_archiver.c:365 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "არქივის ფაილის ამ ფორმატზე პარალელური აღდგენა მხარდაჭერილი არაა" -#: pg_backup_archiver.c:356 +#: pg_backup_archiver.c:369 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "არქივის ფაილზე, რომელიც 8.0 pg_dump-ით ან უფრო ძველით შეიქმნა, პარალელური აღდგენა მხარდაჭერილი არაა" -#: pg_backup_archiver.c:377 +#: pg_backup_archiver.c:390 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "შეკუმშული არქივიდან (%s) აღდგენა შეუძლებელია" -#: pg_backup_archiver.c:397 +#: pg_backup_archiver.c:410 #, c-format msgid "connecting to database for restore" msgstr "მონაცემთა ბაზასთან დაკავშირება აღდგენისთვის" -#: pg_backup_archiver.c:399 +#: pg_backup_archiver.c:412 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "ბაზასთან პირდაპირი შეერთება 1.3 ან უფრო ძველ არქივებში მხარდაჭერილი არაა" -#: pg_backup_archiver.c:442 +#: pg_backup_archiver.c:455 #, c-format -msgid "implied data-only restore" -msgstr "მხოლოდ მონაცემთა აღდგენა" +msgid "implied no-schema restore" +msgstr "სავარაუდო no-schema აღდგენა" -#: pg_backup_archiver.c:510 +#: pg_backup_archiver.c:523 #, c-format msgid "dropping %s %s" msgstr "მოცილება %s %s" -#: pg_backup_archiver.c:642 +#: pg_backup_archiver.c:655 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "ვერ ვიპოვე, ოპერაციაში \"%s\" IF EXISTS სად უნდა ჩავსვა" -#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 +#: pg_backup_archiver.c:841 pg_backup_archiver.c:843 #, c-format msgid "warning from original dump file: %s" msgstr "გაფრთხილება საწყისი გამოტანილი ფაილიდან: %s" -#: pg_backup_archiver.c:864 +#: pg_backup_archiver.c:877 #, c-format msgid "creating %s \"%s.%s\"" msgstr "იქმნება %s \"%s.%s\"" -#: pg_backup_archiver.c:867 +#: pg_backup_archiver.c:880 #, c-format msgid "creating %s \"%s\"" msgstr "იქმნება %s \"%s\"" -#: pg_backup_archiver.c:917 +#: pg_backup_archiver.c:930 #, c-format msgid "connecting to new database \"%s\"" msgstr "ახალ ბაზასთან მიერთება \"%s\"" -#: pg_backup_archiver.c:944 +#: pg_backup_archiver.c:957 #, c-format msgid "processing %s" msgstr "დამუშავება %s" -#: pg_backup_archiver.c:966 +#: pg_backup_archiver.c:979 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "მონაცემების დამუშავება ცხრილისთვის \"%s.%s\"" -#: pg_backup_archiver.c:1036 +#: pg_backup_archiver.c:1049 #, c-format msgid "executing %s %s" msgstr "შესრულება %s %s" -#: pg_backup_archiver.c:1096 +#: pg_backup_archiver.c:1118 #, c-format msgid "disabling triggers for %s" msgstr "%s-სთვის ტრიგერების გამორთვა" -#: pg_backup_archiver.c:1122 +#: pg_backup_archiver.c:1144 #, c-format msgid "enabling triggers for %s" msgstr "%s-სთვის ტრიგერების ჩართვა" -#: pg_backup_archiver.c:1187 +#: pg_backup_archiver.c:1209 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "შიდა შეცდომა -- WriteData-ს DataDumper-ის ქვეპროგრამის კონტექსტის გარეთ ვერ გამოიძახებთ" -#: pg_backup_archiver.c:1379 +#: pg_backup_archiver.c:1404 #, c-format msgid "large-object output not supported in chosen format" msgstr "არჩეულ ფორმატს დიდი ობიექტების გამოტანის საშუალება არ გააჩნია" -#: pg_backup_archiver.c:1442 +#: pg_backup_archiver.c:1467 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "აღდგენილია %d დიდი ობიექტი" msgstr[1] "აღდგენილია %d დიდი ობიექტი" -#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 +#: pg_backup_archiver.c:1494 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "მიმდინარეობს დიდი ობიექტის აღდგენა OID-ით: %u" -#: pg_backup_archiver.c:1481 +#: pg_backup_archiver.c:1506 #, c-format msgid "could not create large object %u: %s" msgstr "დიდი ობიექტის (%u) შექმნის შეცდომა: %s" -#: pg_backup_archiver.c:1486 pg_dump.c:3863 +#: pg_backup_archiver.c:1511 pg_dump.c:4063 #, c-format msgid "could not open large object %u: %s" msgstr "დიდი ობიექტის (%u) გახსნის შეცდომა: %s" -#: pg_backup_archiver.c:1542 +#: pg_backup_archiver.c:1567 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "\"TOC\" ფაილის (%s) გახსნის შეცდომა: %m" -#: pg_backup_archiver.c:1570 +#: pg_backup_archiver.c:1595 #, c-format msgid "line ignored: %s" msgstr "ხაზი გამოტოვებულია: %s" -#: pg_backup_archiver.c:1577 pg_backup_db.c:609 +#: pg_backup_archiver.c:1602 pg_backup_db.c:548 #, c-format msgid "could not find entry for ID %d" msgstr "ჩანაწერი ID-ით %d არ არსებობს" -#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 -#: pg_backup_directory.c:613 +#: pg_backup_archiver.c:1625 pg_backup_directory.c:187 +#: pg_backup_directory.c:581 #, c-format msgid "could not close TOC file: %m" msgstr "\"TOC\" ფაილის დახურვის შეცდომა: %m" -#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 -#: pg_backup_directory.c:600 pg_backup_directory.c:666 -#: pg_backup_directory.c:684 pg_dumpall.c:506 +#: pg_backup_archiver.c:1713 pg_backup_custom.c:151 pg_backup_directory.c:301 +#: pg_backup_directory.c:568 pg_backup_directory.c:634 +#: pg_backup_directory.c:652 pg_dumpall.c:530 #, c-format msgid "could not open output file \"%s\": %m" msgstr "გამოტანის ფაილის (\"%s\") გახსნის შეცდომა: %m" -#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 +#: pg_backup_archiver.c:1715 pg_backup_custom.c:157 #, c-format msgid "could not open output file: %m" msgstr "გამოტანის ფაილის გახსნის შეცდომა: %m" -#: pg_backup_archiver.c:1772 +#: pg_backup_archiver.c:1798 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "ჩაწერილია დიდი ობიექტის მონაცემების %zu ბაიტი (შედეგი = %d)" msgstr[1] "ჩაწერილია დიდი ობიექტის მონაცემების %zu ბაიტი (შედეგი = %d)" -#: pg_backup_archiver.c:1778 +#: pg_backup_archiver.c:1804 #, c-format msgid "could not write to large object: %s" msgstr "დიდი ობიექტის ჩაწერის შეცდომა: %s" -#: pg_backup_archiver.c:1868 +#: pg_backup_archiver.c:1894 #, c-format msgid "while INITIALIZING:" msgstr "\"INITIALIZING\"-ის დროს:" -#: pg_backup_archiver.c:1873 +#: pg_backup_archiver.c:1899 #, c-format msgid "while PROCESSING TOC:" msgstr "\"PROCESSING TOC\"-ის დროს:" -#: pg_backup_archiver.c:1878 +#: pg_backup_archiver.c:1904 #, c-format msgid "while FINALIZING:" msgstr "\"FINALIZING\"-ის დროს:" -#: pg_backup_archiver.c:1883 +#: pg_backup_archiver.c:1909 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "შინაარსის ჩანაწერიდან %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1959 +#: pg_backup_archiver.c:1985 #, c-format msgid "bad dumpId" msgstr "არასწორი dumpId" -#: pg_backup_archiver.c:1980 +#: pg_backup_archiver.c:2006 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "ცხრილის არასწორი dumpId-ი TABLE DATA ელემენტისთვის" -#: pg_backup_archiver.c:2072 +#: pg_backup_archiver.c:2098 #, c-format msgid "unexpected data offset flag %d" msgstr "მონაცემების წანაცვლების მოულოდნელი ალამი: %d" -#: pg_backup_archiver.c:2085 +#: pg_backup_archiver.c:2111 #, c-format msgid "file offset in dump file is too large" msgstr "გამოტანილ ფაილში ფაილის წანაცვლება ძალიან დიდია" -#: pg_backup_archiver.c:2196 +#: pg_backup_archiver.c:2222 pg_restore.c:847 #, c-format msgid "directory name too long: \"%s\"" msgstr "საქაღალდის სახელი ძალიან გრძელია : \"%s\"" -#: pg_backup_archiver.c:2246 +#: pg_backup_archiver.c:2272 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "საქაღალდე \"%s\" სწორ არქივს არ ჰგავს (\"toc.dat\" არ არსებობს)" -#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 -#: pg_backup_directory.c:204 pg_backup_directory.c:396 +#: pg_backup_archiver.c:2280 pg_backup_custom.c:168 pg_backup_custom.c:813 +#: pg_backup_directory.c:172 pg_backup_directory.c:364 #, c-format msgid "could not open input file \"%s\": %m" msgstr "შეყვანის ფაილის (\"%s\") გახსნის შეცდომა: %m" -#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 +#: pg_backup_archiver.c:2287 pg_backup_custom.c:174 #, c-format msgid "could not open input file: %m" msgstr "შეყვანის ფაილის გახსნის შეცდომა: %m" -#: pg_backup_archiver.c:2267 +#: pg_backup_archiver.c:2293 #, c-format msgid "could not read input file: %m" msgstr "შემოსატანი ფაილის წაკითხვის შეცდომა: %m" -#: pg_backup_archiver.c:2269 +#: pg_backup_archiver.c:2295 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "შეყვანის ფაილი ძალიან მოკლეა (წავიკითხე %lu, მოსალოდნელია 5)" -#: pg_backup_archiver.c:2301 +#: pg_backup_archiver.c:2327 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "შეყვანის ფაილი, როგორც ჩანს, არის ტექსტის ფორმატის დამპია. გთხოვთ გამოიყენოთ psql." -#: pg_backup_archiver.c:2307 +#: pg_backup_archiver.c:2333 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "შეყვანილი ფაილი სწორ არქივს არ ჰგავს (ძალიან მოკლეა)" -#: pg_backup_archiver.c:2313 +#: pg_backup_archiver.c:2339 #, c-format msgid "input file does not appear to be a valid archive" msgstr "შეყვანის ფაილი სწორ არქივს არ ჰგავს" -#: pg_backup_archiver.c:2322 +#: pg_backup_archiver.c:2348 #, c-format msgid "could not close input file: %m" msgstr "შეყვანის ფაილის დახურვის შეცდომა: %m" -#: pg_backup_archiver.c:2401 +#: pg_backup_archiver.c:2427 #, c-format msgid "could not open stdout for appending: %m" msgstr "stdout-ის ბოლოში მისაწერად გახსნა შეუძლებელია: %m" -#: pg_backup_archiver.c:2446 +#: pg_backup_archiver.c:2472 #, c-format msgid "unrecognized file format \"%d\"" msgstr "ფაილის უცნობი ფორმატი \"%d\"" -#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4625 +#: pg_backup_archiver.c:2553 pg_backup_archiver.c:4774 #, c-format msgid "finished item %d %s %s" msgstr "დასრულებული ელემენტი %d %s %s" -#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4638 +#: pg_backup_archiver.c:2557 pg_backup_archiver.c:4787 #, c-format msgid "worker process failed: exit code %d" msgstr "დამხმარე პროცესის შეცდომა: გამოსვლის კოდი %d" -#: pg_backup_archiver.c:2653 +#: pg_backup_archiver.c:2655 +#, c-format +msgid "unexpected TOC entry in WriteToc(): %d %s %s" +msgstr "მოულოდნელი TOC-ის ჩანაწერი ფუნქციაში WriteToc(): %d %s %s" + +#: pg_backup_archiver.c:2659 pg_backup_custom.c:440 pg_backup_custom.c:506 +#: pg_backup_custom.c:635 pg_backup_custom.c:871 pg_backup_tar.c:1029 +#: pg_backup_tar.c:1034 +#, c-format +msgid "error during file seek: %m" +msgstr "ფაილში გადახვევის პრობლემა: %m" + +#: pg_backup_archiver.c:2717 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "ელემენტის ID %d დიაპაზონს გარეთაა -- შეიძლება სარჩევი დაზიანებულია" -#: pg_backup_archiver.c:2736 +#: pg_backup_archiver.c:2800 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "ცხრილების, აღწერილი WITH OIDS -ით, აღდგენა მხარდაჭერილი აღარაა" -#: pg_backup_archiver.c:2818 +#: pg_backup_archiver.c:2882 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "უცნობი კოდირება \"%s\"" -#: pg_backup_archiver.c:2823 +#: pg_backup_archiver.c:2888 #, c-format msgid "invalid ENCODING item: %s" msgstr "არასწორი ჩანაწერი \"ENCODING\": %s" -#: pg_backup_archiver.c:2841 +#: pg_backup_archiver.c:2906 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "არასწორი ჩანაწერი \"STDSTRINGS\": %s" -#: pg_backup_archiver.c:2866 +#: pg_backup_archiver.c:2931 #, c-format msgid "schema \"%s\" not found" msgstr "სქემა \"%s\" არ არსებობს" -#: pg_backup_archiver.c:2873 +#: pg_backup_archiver.c:2938 #, c-format msgid "table \"%s\" not found" msgstr "ცხრილი %s არ არსებობს" -#: pg_backup_archiver.c:2880 +#: pg_backup_archiver.c:2945 #, c-format msgid "index \"%s\" not found" msgstr "ინდექსი %s არ არსებობს" -#: pg_backup_archiver.c:2887 +#: pg_backup_archiver.c:2952 #, c-format msgid "function \"%s\" not found" msgstr "ფუნქცია %s არ არსებობს" -#: pg_backup_archiver.c:2894 +#: pg_backup_archiver.c:2959 #, c-format msgid "trigger \"%s\" not found" msgstr "ტრიგერი %s არ არსებობს" -#: pg_backup_archiver.c:3325 +#: pg_backup_archiver.c:3420 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "სესიის მომხმარებლის %s-ზე დაყენების შეცდომა: %s" -#: pg_backup_archiver.c:3457 +#: pg_backup_archiver.c:3552 #, c-format msgid "could not set \"search_path\" to \"%s\": %s" msgstr "\"session_path\"-ის %s-ზე დაყენების შეცდომა: %s" -#: pg_backup_archiver.c:3518 +#: pg_backup_archiver.c:3613 #, c-format msgid "could not set \"default_tablespace\" to %s: %s" msgstr "\"default_tablespace\"-ის %s-ზე დაყენების შეცდომა: %s" -#: pg_backup_archiver.c:3567 +#: pg_backup_archiver.c:3662 #, c-format msgid "could not set \"default_table_access_method\": %s" msgstr "\"default_table_access_method\"-ის დაყენების შეცდომა: %s" -#: pg_backup_archiver.c:3616 +#: pg_backup_archiver.c:3711 #, c-format msgid "could not alter table access method: %s" msgstr "ცხრილის წვდომის მეთოდის შეცვლა შეუძლებელია: %s" -#: pg_backup_archiver.c:3717 +#: pg_backup_archiver.c:3812 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "არ ვიცი, როგორ დავაყენო ობიექტის მოცემული ტიპის (%s) მფლობელი" -#: pg_backup_archiver.c:3982 +#: pg_backup_archiver.c:3947 +#, c-format +msgid "unexpected TOC entry in _printTocEntry(): %d %s %s" +msgstr "მოულოდნელი TOC ჩანაწერი ფუნქციაში _printTocEntry(): %d %s %s" + +#: pg_backup_archiver.c:4131 #, c-format msgid "did not find magic string in file header" msgstr "ფაილის თავსართში მაგიური სტრიქონი ნაპოვნი არაა" -#: pg_backup_archiver.c:3996 +#: pg_backup_archiver.c:4145 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "ფაილის თავსართში არსებული ვერსია (%d.%d) მხარდაუჭერელია" -#: pg_backup_archiver.c:4001 +#: pg_backup_archiver.c:4150 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "მთელი რიცხვის ზომის (%lu) სისწორის შემოწმების შეცდომა" -#: pg_backup_archiver.c:4005 +#: pg_backup_archiver.c:4154 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "არქივი შეიქმნა მანქანაზე, სადაც მთელი რიცხვი უფრო დიდია. ზოგიერთი ოპერაცია შეიძლება შეცდომით დასრულდეს" -#: pg_backup_archiver.c:4015 +#: pg_backup_archiver.c:4164 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "მოსალოდნელი ფორმატი (%d) განსხვავდება ფაილის ფორმატისგან (%d)" -#: pg_backup_archiver.c:4037 +#: pg_backup_archiver.c:4186 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "არქივი შეკუმშულია, მაგრამ ამ ვერსიას შეკუმშვის(%s) მხარდაჭერა არ გააჩნია -- მონაცემები მიუწვდომელი იქნება" -#: pg_backup_archiver.c:4073 +#: pg_backup_archiver.c:4222 #, c-format msgid "invalid creation date in header" msgstr "თავსართში არსებული შექმნის დრო არასწორია" -#: pg_backup_archiver.c:4207 +#: pg_backup_archiver.c:4356 #, c-format msgid "processing item %d %s %s" msgstr "მუშავდება ელემენტი %d %s %s" -#: pg_backup_archiver.c:4292 +#: pg_backup_archiver.c:4441 #, c-format msgid "entering main parallel loop" msgstr "მთავარი პარალელური მარყუჟის დასაწყისი" -#: pg_backup_archiver.c:4303 +#: pg_backup_archiver.c:4452 #, c-format msgid "skipping item %d %s %s" msgstr "ელემენტის გამოტოვება %d %s %s" -#: pg_backup_archiver.c:4312 +#: pg_backup_archiver.c:4461 #, c-format msgid "launching item %d %s %s" msgstr "ელემენტის გაშვება %d %s %s" -#: pg_backup_archiver.c:4366 +#: pg_backup_archiver.c:4515 #, c-format msgid "finished main parallel loop" msgstr "მთავარი პარალელური მარყუჟის დასასრული" -#: pg_backup_archiver.c:4402 +#: pg_backup_archiver.c:4551 #, c-format msgid "processing missed item %d %s %s" msgstr "გამორჩენილი ჩანაწერის დამუშავება %d %s %s" -#: pg_backup_archiver.c:4944 +#: pg_backup_archiver.c:5093 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "ცხრილის (%s) შექმნა შეუძლებელია. მონაცემების აღდგენა არ მოხდება" -#: pg_backup_custom.c:376 pg_backup_null.c:143 +#: pg_backup_custom.c:375 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "დიდი ობიექტის არასწორი OID" -#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 -#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 -#, c-format -msgid "error during file seek: %m" -msgstr "ფაილში გადახვევის პრობლემა: %m" - -#: pg_backup_custom.c:480 +#: pg_backup_custom.c:479 #, c-format msgid "data block %d has wrong seek position" msgstr "მონაცემების ბლოკს (%d) არასწორი გადახვევის მდებარეობა გააჩნია" -#: pg_backup_custom.c:497 +#: pg_backup_custom.c:496 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "არქივის ძებნისას მონაცემების ბლოკის ტიპი (%d) არასწორია" -#: pg_backup_custom.c:519 +#: pg_backup_custom.c:518 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "არქივში ბლოკის ID-ის (%d) პოვნა შეუძლებელია -- შეიძლება დაულაგებელი აღდგენის მოთხოვნის გამო, რომელიც არ შეიძლება დამუშავდეს გადაუხვევადი შეტანის ფაილის გამო" -#: pg_backup_custom.c:524 +#: pg_backup_custom.c:523 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "არქივში ბლოკის ID -ის (%d) პოვნის შეცდომა -- შეიძლება არქივი დაზიანებულია" -#: pg_backup_custom.c:531 +#: pg_backup_custom.c:530 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "მონაცემების კითხვისას ვიპოვე მოულოდნელი ბლოკის ID (%d) -- მოველოდი: %d" -#: pg_backup_custom.c:545 +#: pg_backup_custom.c:544 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "უცნობი მონაცემის ბლოკის ტიპი %d არქივის აღდგენისას" -#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_custom.c:750 pg_backup_custom.c:804 pg_backup_custom.c:946 #: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "არქივის ფაილში გადახვევის მდებარეობის დადგენის შეცდომა: %m" -#: pg_backup_custom.c:767 pg_backup_custom.c:807 +#: pg_backup_custom.c:768 pg_backup_custom.c:808 #, c-format msgid "could not close archive file: %m" msgstr "არქივის ფაილის დახურვის შეცდომა: %m" -#: pg_backup_custom.c:790 +#: pg_backup_custom.c:791 #, c-format msgid "can only reopen input archives" msgstr "შეყვანილი არქივების თავიდან გახსნის შეცდომა" -#: pg_backup_custom.c:797 +#: pg_backup_custom.c:798 #, c-format msgid "parallel restore from standard input is not supported" msgstr "სტანდარტული შეტანიდან პარალელური აღდგენის მხარდაჭერა არ არსებობს" -#: pg_backup_custom.c:799 +#: pg_backup_custom.c:800 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "გადაუხვევადი ფაილიდან პარალელური აღდგენის მხარდაჭერა არ არსებობს" -#: pg_backup_custom.c:815 +#: pg_backup_custom.c:816 #, c-format msgid "could not set seek position in archive file: %m" msgstr "არქივის ფაილში გადახვევის შეცდომა:%m" -#: pg_backup_custom.c:894 +#: pg_backup_custom.c:895 #, c-format msgid "compressor active" msgstr "შემკუმშველი აქტიურია" -#: pg_backup_db.c:42 -#, c-format -msgid "could not get server_version from libpq" -msgstr "libpq-დან server_version-ის მიღების შეცდომა" - -#: pg_backup_db.c:53 pg_dumpall.c:1830 +#: pg_backup_db.c:41 #, c-format -msgid "aborting because of server version mismatch" -msgstr "ოპერაცია გაუქმდა სერვერის ვერსიის შეუთავსებლობის გამო" +msgid "could not get \"server_version\" from libpq" +msgstr "libpq-დან \"server_version\"-ის მიღება შეუძლებელია" -#: pg_backup_db.c:54 pg_dumpall.c:1831 -#, c-format -msgid "server version: %s; %s version: %s" -msgstr "სერვერის ვერსია: %s; %s ვერსია: %s" - -#: pg_backup_db.c:120 +#: pg_backup_db.c:118 #, c-format msgid "already connected to a database" msgstr "ბაზასთან მიერთება უკვე არსებობს" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 -msgid "Password: " -msgstr "პაროლი: " - -#: pg_backup_db.c:170 -#, c-format -msgid "could not connect to database" -msgstr "ბაზასთან მიერთების შეცდომა" - -#: pg_backup_db.c:187 -#, c-format -msgid "reconnection failed: %s" -msgstr "თავიდან მიერთების შეცდომა: %s" - -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:787 pg_dump_sort.c:1213 -#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 -#, c-format -msgid "%s" -msgstr "%s" - -#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 -#, c-format -msgid "query failed: %s" -msgstr "მოთხოვნის შეცდომა: %s" - -#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 -#, c-format -msgid "Query was: %s" -msgstr "მოთხოვნის შინაარსი: %s" - -#: pg_backup_db.c:315 +#: pg_backup_db.c:254 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" msgstr[0] "მოთხოვნამ %d მწკრივი დააბრუნა, ერთის მაგიერ: %s" msgstr[1] "მოთხოვნამ %d მწკრივი დააბრუნა, ერთის მაგიერ: %s" -#: pg_backup_db.c:351 +#: pg_backup_db.c:290 #, c-format msgid "%s: %sCommand was: %s" msgstr "%s: %sბრძანება იყო: %s" -#: pg_backup_db.c:407 pg_backup_db.c:481 pg_backup_db.c:488 +#: pg_backup_db.c:346 pg_backup_db.c:420 pg_backup_db.c:427 msgid "could not execute query" msgstr "მოთხოვნის შესრულების შეცდომა" -#: pg_backup_db.c:460 +#: pg_backup_db.c:399 #, c-format msgid "error returned by PQputCopyData: %s" msgstr "\"PQputCopyData\"-ის მიერ დაბრუნებული შეცდომა: %s" -#: pg_backup_db.c:509 +#: pg_backup_db.c:448 #, c-format msgid "error returned by PQputCopyEnd: %s" msgstr "\"PQputCopyEnd\"-ის მიერ დაბრუნებული შეცდომა: %s" -#: pg_backup_db.c:515 +#: pg_backup_db.c:454 #, c-format msgid "COPY failed for table \"%s\": %s" msgstr "COPY-ის შეცდომა ცხრილისთვის \"%s\": %s" -#: pg_backup_db.c:521 pg_dump.c:2271 +#: pg_backup_db.c:460 pg_dump.c:2439 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "მოულოდნელი დამატებითი შედეგები COPY-ის დროს ცხრილისთვის \"%s\"" -#: pg_backup_db.c:533 +#: pg_backup_db.c:472 msgid "could not start database transaction" msgstr "ბაზის ტრანზაქციის დაწყების შეცდომა" -#: pg_backup_db.c:541 +#: pg_backup_db.c:480 msgid "could not commit database transaction" msgstr "ბაზის ტრანზაქციის გადაცემის შეცდომა" -#: pg_backup_directory.c:153 +#: pg_backup_directory.c:154 #, c-format msgid "no output directory specified" msgstr "გამოტანის საქაღალდე მითითებული არაა" -#: pg_backup_directory.c:186 -#, c-format -msgid "could not close directory \"%s\": %m" -msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" - -#: pg_backup_directory.c:192 -#, c-format -msgid "could not create directory \"%s\": %m" -msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" - -#: pg_backup_directory.c:357 pg_backup_directory.c:506 -#: pg_backup_directory.c:544 +#: pg_backup_directory.c:325 pg_backup_directory.c:474 +#: pg_backup_directory.c:512 #, c-format msgid "could not write to output file: %s" msgstr "გამოსატან ფაილში ჩაწერის შეცდომა: %s" -#: pg_backup_directory.c:375 +#: pg_backup_directory.c:343 #, c-format msgid "could not close data file: %m" msgstr "მონაცემების ფაილის დახურვის შეცდომა: %m" -#: pg_backup_directory.c:408 +#: pg_backup_directory.c:376 #, c-format msgid "could not close data file \"%s\": %m" msgstr "მონაცემების ფაილის (%s) დახურვის შეცდომა: %m" -#: pg_backup_directory.c:455 +#: pg_backup_directory.c:423 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "დიდი ობიექტის სარჩევის ფაილის %s წასაკითხად გახსნის შეცდომა: %m" -#: pg_backup_directory.c:466 +#: pg_backup_directory.c:434 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "არასწორი ხაზი დიდი ობიექტის ცხრილის ფაილში \"%s\": %s" -#: pg_backup_directory.c:475 +#: pg_backup_directory.c:443 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "დიდი ობიექტის სარჩევის ფაილის წაკითხვის შეცდომა: %s" -#: pg_backup_directory.c:479 +#: pg_backup_directory.c:447 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "დიდი ობიექტის სარჩევის ფაილის (%s) დახურვის შეცდომა: %m" -#: pg_backup_directory.c:702 +#: pg_backup_directory.c:670 #, c-format msgid "could not close LO data file: %m" msgstr "'LO' მონაცემების ფაილის დახურვის შეცდომა: %m" -#: pg_backup_directory.c:712 +#: pg_backup_directory.c:680 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "'LO'-ების სარჩევის ფაილში ჩაწერა შეუძლებელია: %s" -#: pg_backup_directory.c:728 +#: pg_backup_directory.c:696 #, c-format msgid "could not close LOs TOC file: %m" msgstr "'LO'-ის სარჩევის ფაილის დახურვის შეცდომა: %m" -#: pg_backup_directory.c:747 +#: pg_backup_directory.c:715 #, c-format msgid "file name too long: \"%s\"" msgstr "%s: ფაილის სახელი ძალიან გრძელია" @@ -1454,100 +1484,140 @@ msgstr[1] "tar ფაილის თავსართი არასრულ msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "%s-ში ნაპოვნია დაზიანებული თავსართი (მოველოდი %d, გამოთვლილია %d) ფაილის პოზიციაზე %llu" -#: pg_backup_utils.c:54 +#: pg_backup_utils.c:56 #, c-format msgid "unrecognized section name: \"%s\"" msgstr "სექციის უცნობი სახელი: %s" -#: pg_backup_utils.c:55 pg_dump.c:693 pg_dump.c:710 pg_dumpall.c:370 -#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 -#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 -#: pg_restore.c:337 +#: pg_backup_utils.c:57 pg_dump.c:803 pg_dump.c:820 pg_dumpall.c:385 +#: pg_dumpall.c:395 pg_dumpall.c:403 pg_dumpall.c:411 pg_dumpall.c:418 +#: pg_dumpall.c:428 pg_dumpall.c:443 pg_dumpall.c:564 pg_restore.c:361 +#: pg_restore.c:377 pg_restore.c:388 pg_restore.c:398 pg_restore.c:527 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_backup_utils.c:66 +#: pg_backup_utils.c:68 #, c-format msgid "out of on_exit_nicely slots" msgstr "on_exit_nicely ტიპის სლოტები აღარ დარჩა" -#: pg_dump.c:708 pg_dumpall.c:378 pg_restore.c:321 +#: pg_dump.c:818 pg_dumpall.c:393 pg_restore.c:375 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_dump.c:727 pg_restore.c:344 +#: pg_dump.c:830 pg_restore.c:406 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" -msgstr "პარამეტრები -s/--schema-only და -a/--data-only ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -s/--schema-only და -a/--data-only ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:832 pg_restore.c:408 +#, c-format +msgid "options -s/--schema-only and --statistics-only cannot be used together" +msgstr "პარამეტრებს -s/--schema-only და --statistics-only ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:834 pg_restore.c:410 +#, c-format +msgid "options -a/--data-only and --statistics-only cannot be used together" +msgstr "პარამეტრებს -a/--data-only და --statistics-only ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:838 pg_restore.c:414 +#, c-format +msgid "options -a/--data-only and --no-data cannot be used together" +msgstr "პარამეტრებს -a/--data-only და --no-data ერთად ვერ გამოიყენებთ" -#: pg_dump.c:730 +#: pg_dump.c:840 pg_restore.c:416 +#, c-format +msgid "options -s/--schema-only and --no-schema cannot be used together" +msgstr "პარამეტრებს -s/--schema-only და --no-schema ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:842 pg_restore.c:418 +#, c-format +msgid "options --statistics-only and --no-statistics cannot be used together" +msgstr "პარამეტრებს --statistics-only და --no-statistics ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:846 pg_restore.c:422 +#, c-format +msgid "options --with-data and --no-data cannot be used together" +msgstr "პარამეტრებს --with-data და --no-data ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:848 pg_restore.c:424 +#, c-format +msgid "options --with-schema and --no-schema cannot be used together" +msgstr "პარამეტრებს --with-schema და --no-schema ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:850 pg_restore.c:426 +#, c-format +msgid "options --with-statistics and --no-statistics cannot be used together" +msgstr "პარამეტრებს --with-statistics და --no-statistics ერთად ვერ გამოიყენებთ" + +#: pg_dump.c:853 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" -msgstr "პარამეტრები -s/--schema-only და --include-foreign-data ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -s/--schema-only და --include-foreign-data ერთად ვერ გამოიყენებთ" -#: pg_dump.c:733 +#: pg_dump.c:856 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "პარამეტრი --include-foreign-data მხარდაუჭერელია პარალელური მარქაფისას" -#: pg_dump.c:736 pg_restore.c:347 +#: pg_dump.c:859 pg_restore.c:429 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" -msgstr "პარამეტრები -c/--clean და -a/--data-only ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -c/--clean და -a/--data-only ერთად ვერ გამოიყენებთ" -#: pg_dump.c:739 pg_dumpall.c:408 pg_restore.c:375 +#: pg_dump.c:862 pg_dumpall.c:423 pg_restore.c:472 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "--if-exists -ს -c/--clean პარამეტრი ესაჭიროება" -#: pg_dump.c:746 +#: pg_dump.c:884 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "--on-conflict-do-nothing -ს --inserts, --rows-per-insert ან --column-inserts ესაჭიროება" -#: pg_dump.c:775 +#: pg_dump.c:913 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "შეკუმშვის უცხო ალგორითმი: \"%s\"" -#: pg_dump.c:782 +#: pg_dump.c:920 #, c-format msgid "invalid compression specification: %s" msgstr "შეკუმშვის არასწორი სპეციფიკაცია: %s" -#: pg_dump.c:795 +#: pg_dump.c:933 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "შეკუმშვის პარამეტრი \"%s\"-ი pg_dump-ის მიერ ამჟამად მხარდაჭერილი არაა" -#: pg_dump.c:807 +#: pg_dump.c:945 #, c-format msgid "parallel backup only supported by the directory format" msgstr "პარალელური მარქაფი მხოლოდ საქაღალდის რეჟიმშია მხარდაჭერილი" -#: pg_dump.c:853 +#: pg_dump.c:991 #, c-format msgid "last built-in OID is %u" msgstr "ბოლო ჩაშენებული OID %u" -#: pg_dump.c:862 +#: pg_dump.c:1000 #, c-format msgid "no matching schemas were found" msgstr "შესაბამისი სქემები ნაპოვნი არაა" -#: pg_dump.c:879 +#: pg_dump.c:1017 #, c-format msgid "no matching tables were found" msgstr "შესაბამისი ცხრილები ნაპოვნი არაა" -#: pg_dump.c:907 +#: pg_dump.c:1045 #, c-format msgid "no matching extensions were found" msgstr "შესაბამისი გაფართოებები ნაპოვნი არაა" -#: pg_dump.c:1091 +#: pg_dump.c:1238 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1556,17 +1626,17 @@ msgstr "" "%s მონაცემთა ბაზას გამოიტანს, როგორც ტექსტურ ფაილს ან სხვა ფორმატებს.\n" "\n" -#: pg_dump.c:1092 pg_dumpall.c:635 pg_restore.c:452 +#: pg_dump.c:1239 pg_dumpall.c:699 pg_restore.c:657 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_dump.c:1093 +#: pg_dump.c:1240 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [პარამეტრი]... [ბაზისსახელი]\n" -#: pg_dump.c:1095 pg_dumpall.c:638 pg_restore.c:455 +#: pg_dump.c:1242 pg_dumpall.c:702 pg_restore.c:660 #, c-format msgid "" "\n" @@ -1575,12 +1645,12 @@ msgstr "" "\n" "ზოგადი პარამეტრები:\n" -#: pg_dump.c:1096 +#: pg_dump.c:1243 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=FILENAME გამოტანის ფაილის სახელი\n" -#: pg_dump.c:1097 +#: pg_dump.c:1244 pg_dumpall.c:704 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1589,22 +1659,22 @@ msgstr "" " -F, --format=c|d|t|p გამოტანის ფაილის ფორმატი (custom, directory, tar\n" " უბრალო ტექსტი (ნაგულისხმევი))\n" -#: pg_dump.c:1099 +#: pg_dump.c:1246 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM მითითებული რაოდენობის პარალელური დავალების გაშვება\n" -#: pg_dump.c:1100 pg_dumpall.c:640 +#: pg_dump.c:1247 pg_dumpall.c:706 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: pg_dump.c:1101 pg_dumpall.c:641 +#: pg_dump.c:1248 pg_dumpall.c:707 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_dump.c:1102 +#: pg_dump.c:1249 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1613,27 +1683,27 @@ msgstr "" " -Z, --compress=მეთოდი[:წვრილმანი]\n" " შეკუმშვის მითითება\n" -#: pg_dump.c:1104 pg_dumpall.c:642 +#: pg_dump.c:1251 pg_dumpall.c:708 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=TIMEOUT ცხრილის დაბლოკვისას TIMEOUT ის შემდეგ შეცდომის გამოგდება\n" -#: pg_dump.c:1105 pg_dumpall.c:670 +#: pg_dump.c:1252 pg_dumpall.c:740 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: pg_dump.c:1106 +#: pg_dump.c:1253 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=მეთოდი ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: pg_dump.c:1107 pg_dumpall.c:643 +#: pg_dump.c:1254 pg_dumpall.c:709 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_dump.c:1109 pg_dumpall.c:644 +#: pg_dump.c:1256 pg_dumpall.c:710 #, c-format msgid "" "\n" @@ -1642,62 +1712,62 @@ msgstr "" "\n" "პარამეტრები, რომლებიც აკონტროლებენ გამოტანას:\n" -#: pg_dump.c:1110 pg_dumpall.c:645 +#: pg_dump.c:1257 pg_dumpall.c:711 #, c-format -msgid " -a, --data-only dump only the data, not the schema\n" -msgstr " -a, --data-only გამოტანილი იქნება მხოლოდ მონაცემები, სქემის გარეშე\n" +msgid " -a, --data-only dump only the data, not the schema or statistics\n" +msgstr " -a, --data-only მოხდება, მხოლოდ, მონაცემების დამპი, მაგრამ არა სქემის ან სტატისტიკის\n" -#: pg_dump.c:1111 +#: pg_dump.c:1258 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects გამოტანილი იქნება დიდი ობიექტებიც\n" -#: pg_dump.c:1112 +#: pg_dump.c:1259 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (იგივე, რაც--large-objects, რომელიც მოძველებულია)\n" -#: pg_dump.c:1113 +#: pg_dump.c:1260 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects დიდი ობიექტები გამოტანილი არ იქნება\n" -#: pg_dump.c:1114 +#: pg_dump.c:1261 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (იგივე, რაც --no-large-objects, რომელიც მოძველებულია)\n" -#: pg_dump.c:1115 pg_restore.c:466 +#: pg_dump.c:1262 pg_restore.c:671 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean ბაზის ობიექტების წაშლა თავიდან შექმნამდე\n" -#: pg_dump.c:1116 +#: pg_dump.c:1263 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr " -C, --create გამოტანილში ბაზის შექმნის ბრძანებების მიყოლება\n" -#: pg_dump.c:1117 +#: pg_dump.c:1264 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=PATTERN მხოლოდ მითითებული გაფართოებების გამოტანა\n" -#: pg_dump.c:1118 pg_dumpall.c:647 +#: pg_dump.c:1265 pg_dumpall.c:713 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=ENCODING მხოლოდ მითითებული კოდირების მქონე მონაცემების გამოტანა\n" -#: pg_dump.c:1119 +#: pg_dump.c:1266 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=PATTERN მხოლოდ მითითებული სქემების გამოტანა\n" -#: pg_dump.c:1120 +#: pg_dump.c:1267 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=PATTERN მითითებული სქემები გამოტანილი არ იქნება\n" -#: pg_dump.c:1121 +#: pg_dump.c:1268 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1706,52 +1776,52 @@ msgstr "" " -O, --no-owner უბრალო ტექსტურ ფორმატში ობიექტების მფლობელობის \n" " აღდგენის გამოტოვება\n" -#: pg_dump.c:1123 pg_dumpall.c:651 +#: pg_dump.c:1270 pg_dumpall.c:717 #, c-format -msgid " -s, --schema-only dump only the schema, no data\n" -msgstr " -s, --schema-only აღდგება მხოლოდ სქემები, მონაცემები კი არა\n" +msgid " -s, --schema-only dump only the schema, no data or statistics\n" +msgstr " -s, --schema-only მოხდება, მხოლოდ, სქემის დამპი, მაგრამ არა მონაცემების ან სტატისტიკის\n" -#: pg_dump.c:1124 +#: pg_dump.c:1271 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr " -S, --superuser=NAME უბრალო ტექსტურ ფაილში გამოტანისას გამოყენებული ზემომხმარებლის სახელი\n" -#: pg_dump.c:1125 +#: pg_dump.c:1272 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=შაბლონი მხოლოდ მითითებული ცხრილების დამპი\n" -#: pg_dump.c:1126 +#: pg_dump.c:1273 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=PATTERN მითითებული ცხრილები გამოტანილი არ იქნება\n" -#: pg_dump.c:1127 pg_dumpall.c:654 +#: pg_dump.c:1274 pg_dumpall.c:720 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges პრივილეგიები (dump/revoke) გამოტანილი არ იქნება\n" -#: pg_dump.c:1128 pg_dumpall.c:655 +#: pg_dump.c:1275 pg_dumpall.c:721 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade გამოიყენება მხოლოდ განახლების პროგრამების მიერ\n" -#: pg_dump.c:1129 pg_dumpall.c:656 +#: pg_dump.c:1276 pg_dumpall.c:722 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr " --column-inserts მონაცემების დამპი ისე, როგორც ბრძანება INSERT, სვეტების სახელებით\n" -#: pg_dump.c:1130 pg_dumpall.c:657 +#: pg_dump.c:1277 pg_dumpall.c:723 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr " --disable-dollar-quoting დოლარით ციტირების გამორთვა. სტანდარტული SQL ციტირების გამოყენება\n" -#: pg_dump.c:1131 pg_dumpall.c:658 pg_restore.c:483 +#: pg_dump.c:1278 pg_dumpall.c:724 pg_restore.c:689 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr " --disable-triggers მხოლოდ მონაცემების აღდგენისას ტრიგერების გამორთვა\n" -#: pg_dump.c:1132 +#: pg_dump.c:1279 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1760,12 +1830,12 @@ msgstr "" " --enable-row-security მწკრივების უსაფრთხოების ჩართვა (მხოლოდ იმ მონაცემების დამპი, \n" " რაზეც მომხმარებელს წვდომა გააჩნია)\n" -#: pg_dump.c:1134 +#: pg_dump.c:1281 #, c-format msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" msgstr " --exclude-extension=PATTERN მითითებული გაფართოებ(ებ)-ი გამოტანილი *არ* იქნება\n" -#: pg_dump.c:1135 +#: pg_dump.c:1282 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1776,12 +1846,12 @@ msgstr "" " მითითებული ცხრილები დამპში არ იქნება,\n" " შვილი და დაყოფილი ცხრილების ჩათვლით\n" -#: pg_dump.c:1138 +#: pg_dump.c:1285 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " -T, --exclude-table=შაბლონი შაბლონით მითითებული ცხრილები\n" -#: pg_dump.c:1139 +#: pg_dump.c:1286 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1792,12 +1862,12 @@ msgstr "" " მითითებული ცხრილების მონაცემები დამპში არ იქნება,\n" " შვილი და დაყოფილი ცხრილების ჩათვლით\n" -#: pg_dump.c:1142 pg_dumpall.c:660 +#: pg_dump.c:1289 pg_dumpall.c:726 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=NUM extra_float_digits-ის ნაგულისხმევი პარამეტრის გადაფარვა\n" -#: pg_dump.c:1143 +#: pg_dump.c:1290 #, c-format msgid "" " --filter=FILENAME include or exclude objects and data from dump\n" @@ -1806,12 +1876,12 @@ msgstr "" " --filter=ფაილისსახელი დამპიდან ობიექტების და მონაცემების, რომლებიც ემთხვევა მითითებულ\n" " ფაილისსახელში მყოფ გამოსახულებას, ამოღება ან ჩასმა\n" -#: pg_dump.c:1145 pg_dumpall.c:662 pg_restore.c:487 +#: pg_dump.c:1292 pg_dumpall.c:728 pg_restore.c:694 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists ობიექტების გადაყრისას IF EXISTS -ის გამოყენება\n" -#: pg_dump.c:1146 +#: pg_dump.c:1293 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1822,87 +1892,117 @@ msgstr "" " მონაცემების ჩასმა უცხო სერვერებზე მდებარე , უცხო ცხრილებიდან, რომლებიც\n" " შაბლონს ემთხვევა\n" -#: pg_dump.c:1149 pg_dumpall.c:663 +#: pg_dump.c:1296 pg_dumpall.c:729 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts მონაცემების დამპი INSERT ბრძანებების მსგავსად, COPY-ის მაგიერ\n" -#: pg_dump.c:1150 pg_dumpall.c:664 +#: pg_dump.c:1297 pg_dumpall.c:730 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root დანაყოფების root ცხრილს გავლით ჩატვირთვა\n" -#: pg_dump.c:1151 pg_dumpall.c:665 +#: pg_dump.c:1298 pg_dumpall.c:731 #, c-format -msgid " --no-comments do not dump comments\n" -msgstr " --no-comments კომენტარების გარეშე\n" +msgid " --no-comments do not dump comment commands\n" +msgstr " --no-comments კომენტარის ბრძანებების დამპი არ მოხდება\n" -#: pg_dump.c:1152 pg_dumpall.c:666 +#: pg_dump.c:1299 pg_dumpall.c:732 +#, c-format +msgid " --no-data do not dump data\n" +msgstr " --no-data მონაცემების დამპი არ მოხდება\n" + +#: pg_dump.c:1300 pg_dumpall.c:733 +#, c-format +msgid " --no-policies do not dump row security policies\n" +msgstr " --no-policies მწკრივის უსაფრთხოების პოლიტიკების დამპი არ მოხდება\n" + +#: pg_dump.c:1301 pg_dumpall.c:734 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications გამოცემების გარეშე\n" -#: pg_dump.c:1153 pg_dumpall.c:668 +#: pg_dump.c:1302 pg_dumpall.c:736 +#, c-format +msgid " --no-schema do not dump schema\n" +msgstr " --no-schema სქემების დამპი არ მოხდება\n" + +#: pg_dump.c:1303 pg_dumpall.c:737 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels უსაფრთხოების ჭდეების მინიჭებების გარეშე\n" -#: pg_dump.c:1154 pg_dumpall.c:669 +#: pg_dump.c:1304 pg_dumpall.c:738 +#, c-format +msgid " --no-statistics do not dump statistics\n" +msgstr " --no-statistics სტატისტიკის დამპი არ მოხდება\n" + +#: pg_dump.c:1305 pg_dumpall.c:739 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions გამოწერების გარეშე\n" -#: pg_dump.c:1155 pg_dumpall.c:671 +#: pg_dump.c:1306 pg_dumpall.c:741 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method ცხრილის წვდომის მეთოდები\n" -#: pg_dump.c:1156 pg_dumpall.c:672 +#: pg_dump.c:1307 pg_dumpall.c:742 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces ცხრილის სივრცის მინიჭებები\n" -#: pg_dump.c:1157 pg_dumpall.c:673 +#: pg_dump.c:1308 pg_dumpall.c:743 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression TOAST-ის შეკუმშვის მეთოდები დამპში არ ჩაიწერება\n" -#: pg_dump.c:1158 pg_dumpall.c:674 +#: pg_dump.c:1309 pg_dumpall.c:744 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data ის ცხრილები, რომლებსაც ჟურნალი არ აქვთ, დამპში არ ჩაიწერება\n" -#: pg_dump.c:1159 pg_dumpall.c:675 +#: pg_dump.c:1310 pg_dumpall.c:745 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing INSERT ბრძანებებისთვის ON CONFLICT DO NOTHING -ის დამატება\n" -#: pg_dump.c:1160 pg_dumpall.c:676 +#: pg_dump.c:1311 pg_dumpall.c:746 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr " --quote-all-identifiers ყველა იდენტიფიკატორის ციტირება. მაშინაც კი, თუ ისინი საკვანძო სიტყვები არაა\n" -#: pg_dump.c:1161 pg_dumpall.c:677 +#: pg_dump.c:1312 pg_dumpall.c:747 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NROWS მწკრივების რიცხვი თითოეული INSERT-ისთვის ; ასევე მიუთითებს --inserts\n" -#: pg_dump.c:1162 +#: pg_dump.c:1313 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr " --section=სექცია მითითებული სექცია (pre-data, data, ან post-data)\n" -#: pg_dump.c:1163 +#: pg_dump.c:1314 +#, c-format +msgid " --sequence-data include sequence data in dump\n" +msgstr " --sequence-data მიმდევრობის მონაცემების ჩასმა დამპში\n" + +#: pg_dump.c:1315 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr " --serializable-deferrable მოცდა, სანამ დამპის გაშვება ანომალიების გარეშე იქნება შესაძლებელი\n" -#: pg_dump.c:1164 +#: pg_dump.c:1316 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT დამპისთვის მითითებული სწრაფი ასლის გამოყენება\n" -#: pg_dump.c:1165 pg_restore.c:497 +#: pg_dump.c:1317 pg_dumpall.c:748 +#, c-format +msgid " --statistics-only dump only the statistics, not schema or data\n" +msgstr " --statistics-only მოხდება, მხოლოდ, სტატისტიკის დამპი, მაგრამ არ სქემის ან მონაცემების\n" + +#: pg_dump.c:1318 pg_restore.c:709 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1911,7 +2011,7 @@ msgstr "" " --strict-names მოთხოვნა, რომ ცხრილი ან/და სქემა შეიცავდეს შაბლონებს, რომლებიც\n" " ერთ ელემენტს მაინც ემთხვევა\n" -#: pg_dump.c:1167 +#: pg_dump.c:1320 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1920,7 +2020,7 @@ msgstr "" " --table-and-children=შაბლონი მხოლოდ მითითებული ცხრილების დამპი,\n" " შვილი და დაყოფილი ცხრილების ჩათვლით\n" -#: pg_dump.c:1169 pg_dumpall.c:678 pg_restore.c:500 +#: pg_dump.c:1322 pg_dumpall.c:749 pg_restore.c:712 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1931,7 +2031,22 @@ msgstr "" " მფლობელობის დასაყენებლად ALTER OWNER ბრძანებების მაგიერ\n" " SET SESSION AUTHORIZATION -ის გამოყენება\n" -#: pg_dump.c:1173 pg_dumpall.c:682 pg_restore.c:504 +#: pg_dump.c:1325 pg_dumpall.c:752 pg_restore.c:715 +#, c-format +msgid " --with-data dump the data\n" +msgstr " --with-data მონაცემების დამპი\n" + +#: pg_dump.c:1326 pg_dumpall.c:753 pg_restore.c:716 +#, c-format +msgid " --with-schema dump the schema\n" +msgstr " --with-schema სქემების დამპი\n" + +#: pg_dump.c:1327 pg_dumpall.c:754 pg_restore.c:717 +#, c-format +msgid " --with-statistics dump the statistics\n" +msgstr " --with-statistics სტატისტიკის დამპი\n" + +#: pg_dump.c:1329 pg_dumpall.c:756 pg_restore.c:719 #, c-format msgid "" "\n" @@ -1940,42 +2055,42 @@ msgstr "" "\n" "შეერთების პარამეტრები:\n" -#: pg_dump.c:1174 +#: pg_dump.c:1330 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=ბაზისსახელი მონაცემთა ბაზის სახელი\n" -#: pg_dump.c:1175 pg_dumpall.c:684 pg_restore.c:505 +#: pg_dump.c:1331 pg_dumpall.c:758 pg_restore.c:720 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME მონაცემთა ბაზის სერვერის ჰოსტის ან სოკეტის საქაღალდე\n" -#: pg_dump.c:1176 pg_dumpall.c:686 pg_restore.c:506 +#: pg_dump.c:1332 pg_dumpall.c:760 pg_restore.c:721 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT მონაცემთა ბაზის სერვერის პორტი\n" -#: pg_dump.c:1177 pg_dumpall.c:687 pg_restore.c:507 +#: pg_dump.c:1333 pg_dumpall.c:761 pg_restore.c:722 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=მომხმარებელი ბაზის მომხმარებლის სახელი\n" -#: pg_dump.c:1178 pg_dumpall.c:688 pg_restore.c:508 +#: pg_dump.c:1334 pg_dumpall.c:762 pg_restore.c:723 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password არასოდეს მკითხო პაროლი\n" -#: pg_dump.c:1179 pg_dumpall.c:689 pg_restore.c:509 +#: pg_dump.c:1335 pg_dumpall.c:763 pg_restore.c:724 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password პაროლის ყოველთვის კითხვა (ავტომატურად უნდა ხდებოდეს)\n" -#: pg_dump.c:1180 pg_dumpall.c:690 +#: pg_dump.c:1336 pg_dumpall.c:764 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLENAME აღდგენამდე SET ROLE -ის გაშვება\n" -#: pg_dump.c:1182 +#: pg_dump.c:1338 #, c-format msgid "" "\n" @@ -1988,537 +2103,573 @@ msgstr "" "ცვლადი გამოიყენება.\n" "\n" -#: pg_dump.c:1184 pg_dumpall.c:694 pg_restore.c:516 +#: pg_dump.c:1340 pg_dumpall.c:768 pg_restore.c:731 #, c-format msgid "Report bugs to <%s>.\n" msgstr "შეცდომების შესახებ მიწერეთ: <%s>\n" -#: pg_dump.c:1185 pg_dumpall.c:695 pg_restore.c:517 +#: pg_dump.c:1341 pg_dumpall.c:769 pg_restore.c:732 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: pg_dump.c:1204 pg_dumpall.c:518 +#: pg_dump.c:1360 pg_dumpall.c:581 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "კლიენტის მითითებული კოდირება არასწორია: %s" -#: pg_dump.c:1344 +#: pg_dump.c:1508 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "სერვერის ამ ვერსიაში უქმე სერვერებიდან პარალელური დამპი მხარდაჭერილი არაა" -#: pg_dump.c:1409 +#: pg_dump.c:1573 #, c-format msgid "invalid output format \"%s\" specified" msgstr "გამოტანის მითითებული ფორმატი არასწორია: %s" -#: pg_dump.c:1450 pg_dump.c:1506 pg_dump.c:1559 pg_dumpall.c:1467 +#: pg_dump.c:1614 pg_dump.c:1670 pg_dump.c:1723 pg_dumpall.c:1593 +#: pg_restore.c:984 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "არასწორი სრული სახელი (ძალიან ბევრი წერტილიანი სახელი): %s" -#: pg_dump.c:1458 +#: pg_dump.c:1622 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "შესაბამისი სქემა შაბლონისთვის \"%s\" ვერ ვიპოვე" -#: pg_dump.c:1511 +#: pg_dump.c:1675 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "შესაბამისი გაფართოება შაბლონისთვის \"%s\" ვერ ვიპოვე" -#: pg_dump.c:1564 +#: pg_dump.c:1728 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "შესაბამისი უცხო სერვერი შაბლონისთვის \"%s\" ვერ ვიპოვე" -#: pg_dump.c:1635 +#: pg_dump.c:1799 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "ურთიერთობის არასწორი სახელი (ძალიან ბევრი წერტილიანი სახელი): %s" -#: pg_dump.c:1657 +#: pg_dump.c:1821 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "შესაბამისი ცხრილი შაბლონისთვის \"%s\" ვერ ვიპოვე" -#: pg_dump.c:1684 +#: pg_dump.c:1848 #, c-format msgid "You are currently not connected to a database." msgstr "ამჟამად მონაცემთა ბაზასთან მიერთებული არ ბრძანდებით." -#: pg_dump.c:1687 +#: pg_dump.c:1851 #, c-format msgid "cross-database references are not implemented: %s" msgstr "ბაზებს შორის ბმულები განხორციელებული არაა: %s" -#: pg_dump.c:2146 +#: pg_dump.c:2310 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "ცხრილის შემცველობის გამოტანა: \"%s.%s\"" -#: pg_dump.c:2252 +#: pg_dump.c:2420 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "ცხრილის (\"%s\") დამპის შეცდომა: PQgetCopyData() failed." -#: pg_dump.c:2253 pg_dump.c:2263 +#: pg_dump.c:2421 pg_dump.c:2431 #, c-format msgid "Error message from server: %s" msgstr "შეცდომა სერვერიდან: %s" -#: pg_dump.c:2254 pg_dump.c:2264 +#: pg_dump.c:2422 pg_dump.c:2432 #, c-format msgid "Command was: %s" msgstr "ბრძანება იყო: %s" -#: pg_dump.c:2262 +#: pg_dump.c:2430 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "ცხრილის (\"%s\") დამპის შეცდომა: PQgetResult() failed." -#: pg_dump.c:2344 +#: pg_dump.c:2521 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "ცხრილიდან \"%s\" მიღებულია ველების არასწორი რაოდენობა" -#: pg_dump.c:3042 +#: pg_dump.c:3236 #, c-format msgid "saving database definition" msgstr "ბაზის აღწერის შენახვა" -#: pg_dump.c:3151 +#: pg_dump.c:3351 #, c-format msgid "unrecognized locale provider: %s" msgstr "ენის უცნობი მომწოდებელი: %s" -#: pg_dump.c:3512 +#: pg_dump.c:3712 #, c-format msgid "saving encoding = %s" msgstr "კოდირების შენახვა = %s" -#: pg_dump.c:3537 +#: pg_dump.c:3737 #, c-format msgid "saving \"standard_conforming_strings = %s\"" msgstr "შენახვა: \"standard_conforming_strings = %s\"" -#: pg_dump.c:3576 +#: pg_dump.c:3776 #, c-format msgid "could not parse result of current_schemas()" msgstr "current_schemas() -ის შედეგის დამუშავების შეცდომა" -#: pg_dump.c:3595 +#: pg_dump.c:3795 #, c-format msgid "saving \"search_path = %s\"" msgstr "შენახვა: \"search_path = %s\"" -#: pg_dump.c:3631 +#: pg_dump.c:3831 #, c-format msgid "reading large objects" msgstr "დიდი ობიექტების კითხვა" -#: pg_dump.c:3852 +#: pg_dump.c:4052 #, c-format msgid "saving large objects \"%s\"" msgstr "მიმდინარეობს შენახვა დიდი ობიექტებისთვის \"%s\"" -#: pg_dump.c:3873 +#: pg_dump.c:4073 #, c-format msgid "error reading large object %u: %s" msgstr "დიდი ობიექტის (%u) წაკითხვის შეცდომა: %s" -#: pg_dump.c:3976 +#: pg_dump.c:4181 #, c-format msgid "reading row-level security policies" msgstr "მწკრივის დონის უსაფრთხოების წესების წაკითხვა" -#: pg_dump.c:4117 +#: pg_dump.c:4322 #, c-format msgid "unexpected policy command type: %c" msgstr "წესების ბრძანების მოულოდნელი ტიპი: %c" -#: pg_dump.c:4567 pg_dump.c:5103 pg_dump.c:12315 pg_dump.c:18137 -#: pg_dump.c:18139 pg_dump.c:18761 +#: pg_dump.c:4764 pg_dump.c:5321 pg_dump.c:7917 pg_dump.c:13287 pg_dump.c:19405 +#: pg_dump.c:19407 pg_dump.c:20039 #, c-format msgid "could not parse %s array" msgstr "მასივის დამუშავების შეცდომა: %s" -#: pg_dump.c:4759 +#: pg_dump.c:4980 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "გამოწერები დამპში არ ჩაწერილა. მიმდინარე მომხმარებელი ზემომხმარებელი არაა" -#: pg_dump.c:4965 +#: pg_dump.c:5184 #, c-format msgid "subscription with OID %u does not exist" msgstr "გამოწერა OID-ით %u არ არსებობს" -#: pg_dump.c:4972 +#: pg_dump.c:5191 #, c-format msgid "failed sanity check, table with OID %u not found" msgstr "სისწორის შემოწმების შეცდომა. ცხრილი OID-ით %u აღმოჩენილი არაა" -#: pg_dump.c:5535 +#: pg_dump.c:5777 #, c-format msgid "could not find parent extension for %s %s" msgstr "%s-სთვის მშობელი გაფართოება ვერ ვიპოვე %s" -#: pg_dump.c:5680 +#: pg_dump.c:5915 #, c-format msgid "schema with OID %u does not exist" msgstr "სქემა OID-ით %u არ არსებობს" -#: pg_dump.c:7162 pg_dump.c:17508 +#: pg_dump.c:6939 +#, c-format +msgid "cannot dump statistics for relation kind '%c'" +msgstr "სტატისტიკის დამპი ურთიერთობის ტიპისთვის '%c' შეუძლებელია" + +#: pg_dump.c:7451 pg_dump.c:18749 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "სისწორის შემოწმების შეცდომა. მშობელი ცხრილი OID-ით %u მიმდევრობიდან OID-ით %u არ არსებობს" -#: pg_dump.c:7305 +#: pg_dump.c:7596 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "სისწორის შემოწმების შეცდომა. pg_parttioned_table-ში მოხსენიებული ცხრილი OID-ით %u ვერ ვიპოვე" -#: pg_dump.c:7536 pg_dump.c:7810 pg_dump.c:8257 pg_dump.c:8871 pg_dump.c:8993 -#: pg_dump.c:9141 +#: pg_dump.c:7861 pg_dump.c:8154 pg_dump.c:8595 pg_dump.c:9232 pg_dump.c:9367 +#: pg_dump.c:9512 pg_dump.c:9612 #, c-format msgid "unrecognized table OID %u" msgstr "ცხრილის უცნობი OID: %u" -#: pg_dump.c:7540 +#: pg_dump.c:7865 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "მოულოდნელი ინდექსის მონაცემები ცხრილისთვის \"%s\"" -#: pg_dump.c:8042 +#: pg_dump.c:8382 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "სისწორის შემოწმების შეცდომა. მშობელი ცხრილი OID-ით %u pg_rewrite-ის ელემენტიდან OID-ით %u ვერ ვიპოვე" -#: pg_dump.c:8875 +#: pg_dump.c:9236 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "სვეტის მოულოდნელი მონაცემები ცხრილისთვის %s" -#: pg_dump.c:8904 +#: pg_dump.c:9267 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "ცხრილში \"%s\" სვეტები არასწორადაა დანომრილი" -#: pg_dump.c:8955 +#: pg_dump.c:9329 #, c-format msgid "finding table default expressions" msgstr "ვეძებ ცხრილის ნაგულისხმევ გამოსახულებებს" -#: pg_dump.c:8997 +#: pg_dump.c:9371 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "adnum -ის არასწორი მნიშვნელობა %d ცხრილისთვის \"%s\"" -#: pg_dump.c:9091 +#: pg_dump.c:9464 +#, c-format +msgid "finding invalid not null constraints" +msgstr "ვეძებ არასწორ არანულოვან შეზღუდვებს" + +#: pg_dump.c:9562 #, c-format msgid "finding table check constraints" msgstr "ვეძებ ცხრილის შემოწმების შეზღუდვებს" -#: pg_dump.c:9145 +#: pg_dump.c:9616 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "მოველოდი %d შემოწმების შეზღუდვას ცხრილზე \"%s\", მაგრამ %d" msgstr[1] "მოველოდი %d შემოწმების შეზღუდვას ცხრილზე \"%s\", მაგრამ %d" -#: pg_dump.c:9149 +#: pg_dump.c:9620 #, c-format msgid "The system catalogs might be corrupted." msgstr "სისტემის კატალოგი შეიძლება დაზიანებულია." -#: pg_dump.c:9839 +#: pg_dump.c:10421 #, c-format msgid "role with OID %u does not exist" msgstr "როლი OID-ით %u არ არსებობს" -#: pg_dump.c:9951 pg_dump.c:9980 +#: pg_dump.c:10533 pg_dump.c:10562 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "pg_init_privs -ის არასწორი ჩანაწერი: %u %u %d" -#: pg_dump.c:10527 +#: pg_dump.c:10853 +#, c-format +msgid "stats dumped out of order (current: %d %s %s) (expected: %d %s %s)" +msgstr "სტატისტიკის დამპი დალაგებული არაა (მიმდინარე: %d %s %s) (მოველოდი: %d %s %s)" + +#: pg_dump.c:10981 +#, c-format +msgid "attname cannot be NULL" +msgstr "attname NULL ვერ იქნება" + +#: pg_dump.c:11010 +#, c-format +msgid "could not find index attname \"%s\"" +msgstr "ინდექსის attname \"%s\" აღმოჩენილი არაა" + +#: pg_dump.c:11496 #, c-format msgid "missing metadata for large objects \"%s\"" msgstr "აკლია მეტამონაცემები დიდი ობიექტებისთვის \"%s\"" -#: pg_dump.c:10810 +#: pg_dump.c:11782 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "მონაცემის ტიპი %s-ის typetype თურმე არასორია" -#: pg_dump.c:12384 +#: pg_dump.c:13358 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "უცნობი provolatile მნიშვნელობა ფუნქციისთვის \"%s\"" -#: pg_dump.c:12434 pg_dump.c:14330 +#: pg_dump.c:13408 pg_dump.c:15304 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "უცნობი proparallel მნიშვნელობა ფუნქციისთვის \"%s\"" -#: pg_dump.c:12564 pg_dump.c:12670 pg_dump.c:12677 +#: pg_dump.c:13538 pg_dump.c:13644 pg_dump.c:13651 #, c-format msgid "could not find function definition for function with OID %u" msgstr "ფუნქციის აღწერა ფუნქციისთვის OID-ით %u ვერ ვიპოვე" -#: pg_dump.c:12603 +#: pg_dump.c:13577 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "pg_cast.castfunc ან pg_cast.castmethod ველების არასწორი მნიშვნელობა" -#: pg_dump.c:12606 +#: pg_dump.c:13580 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "pg_cast.castmethod ველის არასწორი მნიშვნელობა" -#: pg_dump.c:12696 +#: pg_dump.c:13670 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "არასწორი გარდაქმნის აღწერა. ერთ-ერთი, trffromsql ან trftosql ნულს არ უნდა უდრიდეს" -#: pg_dump.c:12713 +#: pg_dump.c:13687 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "pg_transform.trffromsql ველის არასწორი მნიშვნელობა" -#: pg_dump.c:12734 +#: pg_dump.c:13708 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "pg_transform.trftosql ველის არასწორი მნიშვნელობა" -#: pg_dump.c:12879 +#: pg_dump.c:13853 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "postfix ოპერატორები მხარდაჭერილი აღარაა (ოპერატორი \"%s\")" -#: pg_dump.c:13049 +#: pg_dump.c:14023 #, c-format msgid "could not find operator with OID %s" msgstr "ოპერატორი OID-ით %s არ არსებობს" -#: pg_dump.c:13117 +#: pg_dump.c:14091 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "წვდომის მეთოდის (%2$s) არასწორი ტიპი: %1$c" -#: pg_dump.c:13791 pg_dump.c:13859 +#: pg_dump.c:14765 pg_dump.c:14833 #, c-format msgid "unrecognized collation provider: %s" msgstr "კოლაციის უცნობი მომწოდებელი: %s" -#: pg_dump.c:13800 pg_dump.c:13807 pg_dump.c:13818 pg_dump.c:13828 -#: pg_dump.c:13843 +#: pg_dump.c:14774 pg_dump.c:14781 pg_dump.c:14792 pg_dump.c:14802 +#: pg_dump.c:14817 #, c-format msgid "invalid collation \"%s\"" msgstr "არასწორი კოლაცია \"%s\"" -#: pg_dump.c:14249 +#: pg_dump.c:15223 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "აგრეგატის (%s) aggfinalmodify -ის უცნობი ტიპი" -#: pg_dump.c:14305 +#: pg_dump.c:15279 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "აგრეგატის (%s) aggmfinalmodify -ის უცნობი ტიპი" -#: pg_dump.c:15022 +#: pg_dump.c:15999 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "ნაგულისხმევ პრივილეგიებში არსებული ობიექტის უცნობი ტიპი: %d" -#: pg_dump.c:15038 +#: pg_dump.c:16015 #, c-format msgid "could not parse default ACL list (%s)" msgstr "ნაგულიხმები ACL სიის ანალიზი შეუძლებელია: %s" -#: pg_dump.c:15122 +#: pg_dump.c:16099 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "საწყისი ACL სიის (%s) დამუშავების შეცდომა ან ნაგულისხმევი (%s) ობიექტისთვის \"%s\" (%s)" -#: pg_dump.c:15147 +#: pg_dump.c:16124 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "შეცდომა ACL სიის (%s) დამუშავებისას ან ნაგულისხმევი (%s) ობიექტისთვის \"%s\" (%s)" -#: pg_dump.c:15690 +#: pg_dump.c:16667 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "ხედის (%s) აღწერის გამოთხოვამ მონაცემები არ დააბრუნა" -#: pg_dump.c:15693 +#: pg_dump.c:16670 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "ხედის (%s) აღწერის გამოთხოვამ ერთზე მეტი აღწერა დააბრუნა" -#: pg_dump.c:15700 +#: pg_dump.c:16677 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "ხედის (%s) აღწერა, როგორც ჩანს, ცარიელია (ნულოვანი სიგრძე)" -#: pg_dump.c:15784 +#: pg_dump.c:16762 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS-ები უკვე მხარდაუჭერელია (ცხრილი \"%s\")" -#: pg_dump.c:16710 +#: pg_dump.c:17852 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "სვეტების არასწორი რიცხვი %d ცხრილისთვის %s" -#: pg_dump.c:16788 +#: pg_dump.c:17930 #, c-format msgid "could not parse index statistic columns" msgstr "ინდექსის სტატისტიკის სვეტების დამუშავების შეცდომა" -#: pg_dump.c:16790 +#: pg_dump.c:17932 #, c-format msgid "could not parse index statistic values" msgstr "ინდექსის სტატისტიკის მნიშვნელობების დამუშავების შეცდომა" -#: pg_dump.c:16792 +#: pg_dump.c:17934 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "ინდექსის სტატისტიკისთვის სვეტებისა და მნიშვნელობების რაოდენობა არ ემთხვევა" -#: pg_dump.c:17007 +#: pg_dump.c:18163 #, c-format msgid "missing index for constraint \"%s\"" msgstr "შეზღუდვას ინდექსი აკლია: \"%s\"" -#: pg_dump.c:17242 +#: pg_dump.c:18407 #, c-format msgid "unrecognized constraint type: %c" msgstr "შეზღუდვის უცნობი ტიპი: %c" -#: pg_dump.c:17343 pg_dump.c:17572 +#: pg_dump.c:18460 +#, c-format +msgid "unrecognized sequence type: %s" +msgstr "მიმდევრობის უცნობი ტიპი: %s" + +#: pg_dump.c:18592 pg_dump.c:18824 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "მოთხოვნამ, რომელსაც მონაცემები მიმდევრობიდან (%s) უნდა მიეღო, %d მწკრივი დააბრუნა. (მოველოდი: 1)" msgstr[1] "მოთხოვნამ, რომელსაც მონაცემები მიმდევრობიდან (%s) უნდა მიეღო, %d მწკრივი დააბრუნა. (მოველოდი: 1)" -#: pg_dump.c:17375 +#: pg_dump.c:18628 #, c-format -msgid "unrecognized sequence type: %s" -msgstr "მიმდევრობის უცნობი ტიპი: %s" +msgid "unrecognized sequence type: %d" +msgstr "მიმდევრობის უცნობი ტიპი: %d" -#: pg_dump.c:17889 +#: pg_dump.c:19157 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "მოთხოვნის შეცდომა, რომელსაც ცხრილისთვის \"%2$s\" წესი \"%1$s\" უნდა მიეღო: დაბრუნებულია მწკრივების არასწორი რაოდენობა" -#: pg_dump.c:18042 +#: pg_dump.c:19310 #, c-format msgid "could not find referenced extension %u" msgstr "მიბმული გაფართოება (%u) ვერ ვიპოვე" -#: pg_dump.c:18141 +#: pg_dump.c:19409 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "კონფიგურაციებისა და პირობების რაოდენობა გაფართოებისთვის არ ემთხვევა" -#: pg_dump.c:18273 +#: pg_dump.c:19541 #, c-format msgid "reading dependency data" msgstr "დამოკიდებულების მონაცემების კითხვა" -#: pg_dump.c:18359 +#: pg_dump.c:19627 #, c-format msgid "no referencing object %u %u" msgstr "მიბმადი ობიექტის გარეშე %u %u" -#: pg_dump.c:18370 +#: pg_dump.c:19638 #, c-format msgid "no referenced object %u %u" msgstr "მიბმული ობიექტის გარეშე %u %u" -#: pg_dump.c:18795 pg_dump.c:18833 pg_dumpall.c:1962 pg_restore.c:551 -#: pg_restore.c:597 +#: pg_dump.c:20073 pg_dump.c:20111 pg_dumpall.c:1911 pg_restore.c:766 +#: pg_restore.c:812 #, c-format msgid "%s filter for \"%s\" is not allowed" msgstr "ფილტრი %s \"%s\"-სთვის დაშვებული არაა" -#: pg_dump_sort.c:424 +#: pg_dump_sort.c:436 #, c-format msgid "invalid dumpId %d" msgstr "არასწორი dumpId %d" -#: pg_dump_sort.c:430 +#: pg_dump_sort.c:442 #, c-format msgid "invalid dependency %d" msgstr "არასწორი დამოკიდებულება %d" -#: pg_dump_sort.c:594 +#: pg_dump_sort.c:606 #, c-format msgid "could not identify dependency loop" msgstr "დამოკიდებულებების მარყუჟები ნაპოვნი არაა" -#: pg_dump_sort.c:1209 +#: pg_dump_sort.c:1247 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "ცხრილები, რომლებშიც აღმოჩენილია წრიული გარე-გასაღების შეზღუდვები:" msgstr[1] "ცხრილები, რომლებშიც აღმოჩენილია წრიული გარე-გასაღების შეზღუდვები:" -#: pg_dump_sort.c:1214 +#: pg_dump_sort.c:1252 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "შეიძლება დამპის აღდგენა --disable-trigger-ების გამორთვის ან დროებით შეზღუდვების გადაყრის გარეშე ვერ შეძლოთ." -#: pg_dump_sort.c:1215 +#: pg_dump_sort.c:1253 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "ამ პრობლემის ასარიდებლად უმჯობესია --data-only -ის მაგიერ სრული დამპი აიღოთ." -#: pg_dump_sort.c:1227 +#: pg_dump_sort.c:1265 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "ამ ელემენტებს შორის დამოკიდებულებების მარყუჟის ამოხსნა შეუძლებელია:" -#: pg_dumpall.c:231 +#: pg_dumpall.c:244 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა" -#: pg_dumpall.c:234 +#: pg_dumpall.c:247 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s" -#: pg_dumpall.c:387 +#: pg_dumpall.c:402 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" -msgstr "პარამეტრი --exclude-database არ შეიძლება -g/--globals-only, -r/--roles-only, და -t/--tablespaces-only -სთან ერთად იყოს გამოყენებული" +msgstr "პარამეტრი --exclude-database არ შეიძლება, -g/--globals-only, -r/--roles-only, და -t/--tablespaces-only -სთან ერთად იყოს გამოყენებული" -#: pg_dumpall.c:395 +#: pg_dumpall.c:410 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" -msgstr "პარამეტრები -g/--globals-only და -r/--roles-only ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -g/--globals-only და -r/--roles-only ერთად ვერ გამოიყენებთ" -#: pg_dumpall.c:402 +#: pg_dumpall.c:417 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" -msgstr "პარამეტრები -g/--globals-only და -t/--tablespaces-only ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -g/--globals-only და -t/--tablespaces-only ერთად ვერ გამოიყენებთ" -#: pg_dumpall.c:412 +#: pg_dumpall.c:427 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" -msgstr "პარამეტრები -r/--roles-only და -t/--tablespaces-only ერთად ვერ გამოიყენება" +msgstr "პარამეტრებს -r/--roles-only და -t/--tablespaces-only ერთად ვერ გამოიყენებთ" -#: pg_dumpall.c:474 pg_dumpall.c:1771 +#: pg_dumpall.c:442 #, c-format -msgid "could not connect to database \"%s\"" -msgstr "მონაცემთა ბაზასთან დაკავშირება ვერ მოხერხდა \"%s\"" +msgid "option -F/--format=d|c|t requires option -f/--file" +msgstr "პარამეტრს -F/--format=d|c|t სჭირდება პარამეტრი -f/--file" + +#: pg_dumpall.c:524 pg_restore.c:1061 pg_restore.c:1317 +#, c-format +msgid "could not open \"%s\": %m" +msgstr "\"%s\" ვერ გავხსენი: %m" -#: pg_dumpall.c:486 +#: pg_dumpall.c:562 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2527,81 +2678,81 @@ msgstr "" "ვერ დაუკავშირდა მონაცემთა ბაზებს \"postgres\" ან \"template1\"\n" "გთხოვთ მიუთითოთ ალტერნატიული მონაცემთა ბაზა." -#: pg_dumpall.c:634 +#: pg_dumpall.c:698 #, c-format msgid "" -"%s extracts a PostgreSQL database cluster into an SQL script file.\n" +"%s extracts a PostgreSQL database cluster based on specified dump format.\n" "\n" msgstr "" -"%s-ი PostgreSQL-ის ბაზის კლასტერს SQL სკრიპტის ფაილში გამოიტანს.\n" +"%s გაშლის PostgreSQL-ის მონაცემთა ბაზაის კლასტერს მითითებული დამპის ფორმატის მიხედვით.\n" "\n" -#: pg_dumpall.c:636 +#: pg_dumpall.c:700 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [პარამეტრი]...\n" -#: pg_dumpall.c:639 +#: pg_dumpall.c:703 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=FILENAME გამოტანის ფაილის სახელი\n" -#: pg_dumpall.c:646 +#: pg_dumpall.c:712 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean ბაზის წაშლა თავიდან შექმნამდე\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:714 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" -msgstr " -g, --globals-only წაიშლება მხოლოდ გლობალური ობიექტები და არა ბაზები\n" +msgstr " -g, --globals-only მოხდება, მხოლოდ, გლობალური ობიექტების დამპი და არა ბაზები\n" -#: pg_dumpall.c:649 pg_restore.c:475 +#: pg_dumpall.c:715 pg_restore.c:681 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner ობიექტების მფლობელობის აღდგენის გამოტოვება\n" -#: pg_dumpall.c:650 +#: pg_dumpall.c:716 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr " -r, --roles-only გამოიტანს მხოლოდ როლებს და არც ბაზებს და არც ცხრილების სივრცეებს\n" -#: pg_dumpall.c:652 +#: pg_dumpall.c:718 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr " -S, --superuser=NAME გამოსაყენებელი ზემომხმარებლის სახელი\n" -#: pg_dumpall.c:653 +#: pg_dumpall.c:719 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr " -t, --tablespaces-only გამოიტანს მხლოდ ცხრილების სივრცეებს და არც ბაზებს და არც როლებს\n" -#: pg_dumpall.c:659 +#: pg_dumpall.c:725 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr " --exclude-database=PATTERN გამორიცხავს ბაზებს, რომლებიც PATTERN-ს ემთხვევა\n" -#: pg_dumpall.c:661 +#: pg_dumpall.c:727 #, c-format -msgid " --filter=FILENAME exclude databases specified in FILENAME\n" +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" msgstr " --filter=FILENAME ფაილში მითითებული მონაცემთა ბაზების ამოღება\n" -#: pg_dumpall.c:667 +#: pg_dumpall.c:735 #, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords როლების პაროლები გამოტანილ არ იქნება\n" -#: pg_dumpall.c:683 +#: pg_dumpall.c:757 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=CONNSTR კავშირის სტრიქონი\n" -#: pg_dumpall.c:685 +#: pg_dumpall.c:759 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=ბაზისსახელი ალტერნატიული ბაზის სახელი)\n" -#: pg_dumpall.c:692 +#: pg_dumpall.c:766 #, c-format msgid "" "\n" @@ -2614,155 +2765,206 @@ msgstr "" "სტანდარტულ გამოტანაზე იქნება გამოტანილი.\n" "\n" -#: pg_dumpall.c:837 +#: pg_dumpall.c:911 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "როლის სახელი, რომელიც \"pg_\"-ით იწყება, გამოტოვებულია (%s)" -#: pg_dumpall.c:1059 +#. translator: %s represents a numeric role OID +#: pg_dumpall.c:1125 pg_dumpall.c:1183 pg_dumpall.c:1192 +#, c-format +msgid "found orphaned pg_auth_members entry for role %s" +msgstr "აღმოჩენილია მიტოვებული pg_auth-ის წევრის ჩანაწერი როლისთვის %s" + +#: pg_dumpall.c:1158 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "სწორი დამპის მიმდევრობა წევრობისთვის როლში \"%s\" აღმოჩენილი არაა" -#: pg_dumpall.c:1194 +#: pg_dumpall.c:1313 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "ვერ გაანალიზდა ACL სია (%s) პარამეტრისთვის \"%s\"" -#: pg_dumpall.c:1321 +#: pg_dumpall.c:1440 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "შეცდომა ACL-ის სიის (%s) დამუშავებისთვის ცხრილის სივრცისთვის \"%s\"" -#: pg_dumpall.c:1528 +#: pg_dumpall.c:1657 +#, c-format +msgid "could not create subdirectory \"%s\": %m" +msgstr "ქვესაქაღალდის (%s) შექმნის შეცდომა: %m" + +#: pg_dumpall.c:1664 +#, c-format +msgid "could not open map file: %s" +msgstr "შეუძლებელია რუკის ფაილის გახსნა: %s" + +#: pg_dumpall.c:1681 pg_restore.c:1014 #, c-format msgid "excluding database \"%s\"" msgstr "გამოირიცხა ბაზა \"%s\"" -#: pg_dumpall.c:1532 +#: pg_dumpall.c:1702 #, c-format msgid "dumping database \"%s\"" msgstr "დამპის გამოტანა ბაზისთვის \"%s\"" -#: pg_dumpall.c:1563 +#: pg_dumpall.c:1731 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "pg_dump -ის შეცდომა ბაზაზე \"%s\". დასასრული" -#: pg_dumpall.c:1569 +#: pg_dumpall.c:1744 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "გამოსატანი ფაილის თავიდან გახსნის შეცდომა \"%s\": %m" -#: pg_dumpall.c:1613 +#: pg_dumpall.c:1812 #, c-format msgid "running \"%s\"" msgstr "%s -ის გაშვება" -#: pg_dumpall.c:1814 -#, c-format -msgid "could not get server version" -msgstr "სერვერის ვერსიის მღების შეცდომა" - -#: pg_dumpall.c:1817 -#, c-format -msgid "could not parse server version \"%s\"" -msgstr "შერვერის ვერსიის დამუშავების შეცდომა: %s" - -#: pg_dumpall.c:1887 pg_dumpall.c:1910 -#, c-format -msgid "executing %s" -msgstr "%s -ის შესრულება" - -#: pg_dumpall.c:1982 +#: pg_dumpall.c:1931 msgid "unsupported filter object" msgstr "მხარდაუჭერელი ფილტრის ობიექტი" -#: pg_restore.c:329 +#: pg_dumpall.c:1974 +#, c-format +msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", \"p\", or \"t\"" +msgstr "არქივის უცნობი ფორმატი \"%s\"; გთხოვთ მიუთითოთ \"c\", \"d\" \"p\", ან \"t\"" + +#: pg_restore.c:383 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "-d/--dbname და-f/--file -დან მხოლოდ ერთ-ერთის მითითება შეგიძლიათ" -#: pg_restore.c:336 +#: pg_restore.c:387 +#, c-format +msgid "option --exclude-database cannot be used together with -g/--globals-only" +msgstr "პარამეტრი --exclude-database არ შეიძლება, გამოიყენოთ პარამეტრთან -g/--globals-only ერთად" + +#: pg_restore.c:397 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "-d/--dbname და-f/--file ერთად არ გამოიყენება" -#: pg_restore.c:350 +#: pg_restore.c:432 #, c-format msgid "options -1/--single-transaction and --transaction-size cannot be used together" msgstr "პარამეტრებს -1/--single-transaction და --transaction-size ერთად ვერ გამოიყენებთ" -#: pg_restore.c:357 +#: pg_restore.c:439 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "-C/--create და -1/--single-transaction ერთად არ გამოიყენება" -#: pg_restore.c:361 +#: pg_restore.c:443 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "--single-transaction -ის მითითება ბევრ დავალებასთან ერთად შეუძლებელია" -#: pg_restore.c:399 +#: pg_restore.c:491 +#, c-format +msgid "archive format \"%s\" is not supported; please use psql" +msgstr "არქივის ფორმატი \"%s\" მხარდაჭერილი არაა. გამოიყენეთ psql" + +#: pg_restore.c:495 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "არქივის უცნობი ფორმატი \"%s\"; გთხოვთ მიუთითოთ \"გ\", \"დ\", ან \"t\"" -#: pg_restore.c:438 +#: pg_restore.c:516 +#, c-format +msgid "option -l/--list cannot be used when restoring an archive created by pg_dumpall" +msgstr "პარამეტრს -l/--list ვერ გამოიყენებთ pg_dumpall-ის მიერ შექმნილი არქივის აღდგენისას" + +#: pg_restore.c:518 +#, c-format +msgid "option -L/--use-list cannot be used when restoring an archive created by pg_dumpall" +msgstr "პარამეტრს -L/--use-list ვერ გამოიყენებთ pg_dumpall-ის მიერ შექმნილი არქივის აღდგენისას" + +#: pg_restore.c:526 +#, c-format +msgid "-C/--create option should be specified when restoring an archive created by pg_dumpall" +msgstr "პარამეტრი -C/--create, მხოლოდ, მაშინ უნდა მიუტითოთ, როცა ხდება pg_dumpall-ის მიერ შექმნილი არქივის აღდგენა" + +#: pg_restore.c:528 +#, c-format +msgid "Individual databases can be restored using their specific archives." +msgstr "ინდივიდუალური მონაცემთა ბაზის აღდგენა მათი სპეციფიკური არქივების გამოყენებითაა შესაძლებელი." + +#: pg_restore.c:560 +#, c-format +msgid "database restoring skipped as -g/--globals-only option was specified" +msgstr "მონაცემთა ბაზის აღდგენა გამოტოვებულია, რადგან მითითებულია პარამეტრი -g/--globals-only" + +#: pg_restore.c:575 +#, c-format +msgid "option --exclude-database can be used only when restoring an archive created by pg_dumpall" +msgstr "პარამეტრის --exclude-database გამოყენება, მხოლოდ, pg_dumpall-ით შექმნილი არქივის აღდგენისას შეგიძლიათ" + +#: pg_restore.c:578 +#, c-format +msgid "option -g/--globals-only can be used only when restoring an archive created by pg_dumpall" +msgstr "პარამეტრის -g/--globals-only გამოყენება, მხოლოდ, pg_dumpall-ით შექმნილი არქივის აღდგენისას შეგიძლიათ" + +#: pg_restore.c:586 #, c-format msgid "errors ignored on restore: %d" msgstr "აღდგენისას იგნორირებული შეცდომების რაოდენობა: %d" -#: pg_restore.c:451 +#: pg_restore.c:656 #, c-format msgid "" -"%s restores a PostgreSQL database from an archive created by pg_dump.\n" +"%s restores PostgreSQL databases from archives created by pg_dump or pg_dumpall.\n" "\n" msgstr "" -"%s აღადგენს PostgreSQL მონაცემთა ბაზას pg_dump მიერ შექმნილი არქივიდან.\n" +"%s აღადგენს PostgreSQL-ის მონაცემთა ბაზებს არქივებიდან, რომლებიც pg_dump-ის, ან pg_dumpall-ის მიერაა შექმნილი.\n" "\n" -#: pg_restore.c:453 +#: pg_restore.c:658 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [პარამეტრი]... [ფაილი]\n" -#: pg_restore.c:456 +#: pg_restore.c:661 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=ბაზისსახელი მონაცემთა ბაზის სახელი\n" -#: pg_restore.c:457 +#: pg_restore.c:662 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FILENAME გამოტანის ფაილის სახელი(stdout-ზე გამოსატანად გამოიყენეთ \"-\")\n" -#: pg_restore.c:458 +#: pg_restore.c:663 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t მარქაფის ფაილის ფორმატი (ავტომატური უნდა იყოს)\n" -#: pg_restore.c:459 +#: pg_restore.c:664 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list არქივის სარჩევის მიმოხილვის გამოტანა\n" -#: pg_restore.c:460 +#: pg_restore.c:665 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: pg_restore.c:461 +#: pg_restore.c:666 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_restore.c:462 +#: pg_restore.c:667 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_restore.c:464 +#: pg_restore.c:669 #, c-format msgid "" "\n" @@ -2771,32 +2973,37 @@ msgstr "" "\n" "პარამეტრები, რომლებიც აკონტროლებენ გამოტანას:\n" -#: pg_restore.c:465 +#: pg_restore.c:670 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only აღდგება მხოლოდ მონაცემები, სქემის გარეშე\n" -#: pg_restore.c:467 +#: pg_restore.c:672 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create სამიზნე ბაზის შექმნა\n" -#: pg_restore.c:468 +#: pg_restore.c:673 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error დაუყოვნებლივი გამოსვლა შეცდომის შემთხვევაში\n" -#: pg_restore.c:469 +#: pg_restore.c:674 +#, c-format +msgid " -g, --globals-only restore only global objects, no databases\n" +msgstr " -g, --globals-only აღდგება, მხოლოდ, გლობალური ობიექტები და არა ბაზები\n" + +#: pg_restore.c:675 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAME მითითებული სახელის მქონე ინდექსის აღდგენა\n" -#: pg_restore.c:470 +#: pg_restore.c:676 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM აღდგენისას მითითებული რაოდენობის პარალელური დავალების გაშვება\n" -#: pg_restore.c:471 +#: pg_restore.c:677 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2805,57 +3012,62 @@ msgstr "" " -L, --use-list=FILENAME გამოტანის ასარჩევად/დასალაგებლად მითითებული\n" " ფაილის შემცველობის გამოყენება\n" -#: pg_restore.c:473 +#: pg_restore.c:679 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME მხოლოდ მითითებული სქემის ობიექტების აღდგენა\n" -#: pg_restore.c:474 +#: pg_restore.c:680 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=სახელი მითითებული სახელის მქონე სქემაში ობიექტები არ აღდგება\n" -#: pg_restore.c:476 +#: pg_restore.c:682 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=სახელი(არგები) მითითებული სახელის მქონე ფუნქციის აღდგენა\n" -#: pg_restore.c:477 +#: pg_restore.c:683 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only აღდგება მხოლოდ სქემები, მონაცემები კი არა\n" -#: pg_restore.c:478 +#: pg_restore.c:684 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr " -S, --superuser=NAME ტრიგერების გამოსართავად გამოყენებული ზემომხმარებლის სახელი\n" -#: pg_restore.c:479 +#: pg_restore.c:685 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NAME მითითებული ურთიერთობის აღდგენა (ცხრილი, ხედი, და ა.შ.)\n" -#: pg_restore.c:480 +#: pg_restore.c:686 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAME მითითებული ტრიგერის აღდგენა \n" -#: pg_restore.c:481 +#: pg_restore.c:687 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges წვდომის პრივილეგიების აღდგენის გამოტოვება (grant/revoke)\n" -#: pg_restore.c:482 +#: pg_restore.c:688 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction აღდგენის ერთ ტრანზაქციად გაშვება\n" -#: pg_restore.c:484 +#: pg_restore.c:690 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security მწკრივების უსაფრთხოების ჩართვა\n" -#: pg_restore.c:485 +#: pg_restore.c:691 +#, c-format +msgid " --exclude-database=PATTERN do not restore the specified database(s)\n" +msgstr " --exclude-database=PATTERN მითითებული მონაცემთა ბაზ(ებ)-ის აღდგენა არ მოხდება\n" + +#: pg_restore.c:692 #, c-format msgid "" " --filter=FILENAME restore or skip objects based on expressions\n" @@ -2864,12 +3076,17 @@ msgstr "" " --filter=FILENAME ობიექტების აღდგენა ან გამოტოვება ფაილში\n" " მითითებული გამოსახულებების მიხედვით\n" -#: pg_restore.c:488 +#: pg_restore.c:695 +#, c-format +msgid " --no-comments do not restore comment commands\n" +msgstr " --no-comments კომენტარის ბრძანებები არ აღდგება\n" + +#: pg_restore.c:696 #, c-format -msgid " --no-comments do not restore comments\n" -msgstr " --no-comments კომენტარები არ აღდგება\n" +msgid " --no-data do not restore data\n" +msgstr " --no-data მონაცემები არ აღდგება\n" -#: pg_restore.c:489 +#: pg_restore.c:697 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" @@ -2878,58 +3095,78 @@ msgstr "" " --no-data-for-failed-tables ცხრილების, რომლის შექმნა შეუძლებელია,\n" " მონაცემები არ აღდგება\n" -#: pg_restore.c:491 +#: pg_restore.c:699 +#, c-format +msgid " --no-policies do not restore row security policies\n" +msgstr " --no-policies მწკრივის უსაფრთხოების პოლიტიკები არ აღდგება\n" + +#: pg_restore.c:700 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications გამოცემები არ აღდგება\n" -#: pg_restore.c:492 +#: pg_restore.c:701 +#, c-format +msgid " --no-schema do not restore schema\n" +msgstr " --no-schema სქემები არ აღდგება\n" + +#: pg_restore.c:702 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels უსაფრთხოების ჭდეები არ აღდგება\n" -#: pg_restore.c:493 +#: pg_restore.c:703 +#, c-format +msgid " --no-statistics do not restore statistics\n" +msgstr " --no-statistics სტატისტიკის აღდგენა არ მოხდება\n" + +#: pg_restore.c:704 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions გამოწერები არ აღდგება\n" -#: pg_restore.c:494 +#: pg_restore.c:705 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method ცხრილის წვდომის მეთოდები არ აღდგება\n" -#: pg_restore.c:495 +#: pg_restore.c:706 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces ცხრილის სივრცის მინიჭებები არ აღდგება\n" -#: pg_restore.c:496 +#: pg_restore.c:707 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr " --section=სექცია მითითებული სექციის აღდგენა (pre-data, data, ან post-data)\n" -#: pg_restore.c:499 +#: pg_restore.c:708 +#, c-format +msgid " --statistics-only restore only the statistics, not schema or data\n" +msgstr " --statistics-only აღდგება, მხოლოდ, სტატისტიკა, სქემა, ან მონაცემები კი - არა\n" + +#: pg_restore.c:711 #, c-format msgid " --transaction-size=N commit after every N objects\n" msgstr " --transaction-size=N გადაცემა ყოველი N ობიექტის შემდეგ\n" -#: pg_restore.c:510 +#: pg_restore.c:725 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME აღდგენამდე SET ROLE -ის გაშვება\n" -#: pg_restore.c:512 +#: pg_restore.c:727 #, c-format msgid "" "\n" -"The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" -"multiple times to select multiple objects.\n" +"The options -I, -n, -N, -P, -t, -T, --section, and --exclude-database can be combined\n" +"and specified multiple times to select multiple objects.\n" msgstr "" "\n" "შესაძლებელია პარამეტრების -I, -n, -N, -P, -t, -T, და --section ერთად და მრავალჯერ მითითება, მრავალი\n" "ობიექტის ამოსაღებად.\n" -#: pg_restore.c:515 +#: pg_restore.c:730 #, c-format msgid "" "\n" @@ -2940,10 +3177,103 @@ msgstr "" "თუ ფაილის სახელი მითითებული არაა, გამოყენებული იქნება სტანდარტული შეტანა.\n" "\n" +#: pg_restore.c:949 +#, c-format +msgid "considering PATTERN as NAME for --exclude-database option as no db connection while doing pg_restore." +msgstr "ნიმუში ჩაითვლება სახელად პარამეტრისთვის --exclude-database, რადგან pg_restore-ის გაშვების დროს ბაზასთან კავშირი არ დამყარებულა." + +#: pg_restore.c:995 +#, c-format +msgid "database \"%s\" matches exclude pattern: \"%s\"" +msgstr "მონაცემთა ბაზა \"%s\" ემთხვევა გამოტოვების ნიმუშს: \"%s\"" + +#: pg_restore.c:1051 +#, c-format +msgid "database restoring is skipped as \"map.dat\" is not present in \"%s\"" +msgstr "მონაცემთა ბაზის აღდგენა გამოტოვებულია, რადგან \"%s\"-ში ფაილი map.dat აღმოჩენილი არაა" + +#: pg_restore.c:1089 +#, c-format +msgid "invalid entry in \"%s\" at line: %d" +msgstr "არასწორი ჩანაწერი ფაილში \"%s\" ხაზზე: %d" + +#: pg_restore.c:1092 +#, c-format +msgid "found database \"%s\" (OID: %u) in \"%s\"" +msgstr "აღდგენისას ფაილში \"%3$s\" აღმოჩენილია მონაცემთა ბაზა \"%1$s\" (OID: %2$u)." + +#: pg_restore.c:1145 +#, c-format +msgid "found %d database names in \"map.dat\"" +msgstr "ფაილში map.dat აღმოჩენილია სულ %d მონაცემთა ბაზის სახელი" + +#: pg_restore.c:1149 +#, c-format +msgid "trying to connect database \"postgres\"" +msgstr "ვცდილობ, მივუერთდე მონაცემთა ბაზას \"postgres\"" + +#: pg_restore.c:1158 +#, c-format +msgid "trying to connect database \"template1\"" +msgstr "ვცდილობ, მივუერთდე მონაცემთა ბაზას \"postgres\"" + +#: pg_restore.c:1182 +#, c-format +msgid "no database needs to restore out of %d databases" +msgstr "%d მონაცემთა ბაზიდან აღსადგენი არცერთია" + +#: pg_restore.c:1186 +#, c-format +msgid "need to restore %d databases out of %d databases" +msgstr "საჭიროა %d მონაცემთა ბაზის აღდგენა %d-დან" + +#: pg_restore.c:1235 +#, c-format +msgid "restoring database \"%s\"" +msgstr "მიმდინარეობს აღდგენა მონაცემთა ბაზისთვის \"%s\"" + +#: pg_restore.c:1276 +#, c-format +msgid "errors ignored on database \"%s\" restore: %d" +msgstr "მონაცემთა ბაზის \"%s\" აღდგენისას გამოტოვებული შეცდომები: %d" + +#: pg_restore.c:1283 +#, c-format +msgid "number of restored databases is %d" +msgstr "აღდგენილი მონაცემთა ბაზების რაოდენობა: %d" + +#: pg_restore.c:1346 +#, c-format +msgid "executing query: %s" +msgstr "მიმდინარეობს შესრულება მოთხოვნის: %s" + +#: pg_restore.c:1357 +#, c-format +msgid "" +"could not execute query: \"%s\" \n" +"Command was: \"%s\"" +msgstr "" +"ვერ შევასრულე მოთხოვნა: \"%s\"\n" +"ბრძანება: \"%s\"" + +#: pg_restore.c:1364 +#, c-format +msgid "ignored %d errors in \"%s\"" +msgstr "გამოტოვებულია %d შეცდომა \"%s\"-ში" + +#: pg_restore.c:1395 +#, c-format +msgid "could not open file: \"%s\"" +msgstr "შეუძლებელია ფაილის გახსნა: \"%s\"" + #, c-format #~ msgid " %s" #~ msgstr " %s" +#, c-format +#~ msgid " --exclude-database=PATTERN exclude databases whose name matches with pattern\n" +#~ msgstr " --exclude-database=ნიმუში გამორიცხავს ბაზებს, რომლებიც ნიმუშს ემთხვევა\n" + #, c-format #~ msgid " -Z, --compress=0-9 compression level for compressed formats\n" #~ msgstr " -Z, --compress=0-9 შეკუმშვის დონე\n" @@ -2956,6 +3286,10 @@ msgstr "" #~ " -Z, --compress=მეთოდი[:დონე]\n" #~ " შეკუმშვის მითითება\n" +#, c-format +#~ msgid "Either remove the directory \"%s\" or its contents." +#~ msgstr "ან წაშალეთ საქაღალდე \"%s\", ან მისი შემცველობა." + #, c-format #~ msgid "cannot restore from compressed archive (compression not supported in this installation)" #~ msgstr "შეკუმშული არქივიდან აღდგენა შეუძლებელია (ამ აგებაში შეკუმშვა მხარდაჭერილი არაა)" @@ -2964,22 +3298,42 @@ msgstr "" #~ msgid "could not change directory to \"%s\": %m" #~ msgstr "საქაღალდის %s-ზე შეცვლის შეცდომა: %m" -#, c-format -#~ msgid "could not close blob data file: %m" -#~ msgstr "ბლობის ფაილის დახურვის შეცდომა: %m" - #, c-format #~ msgid "could not close blobs TOC file: %m" #~ msgstr "ბლობების შინაარსის ფაილის დახურვის შეცდომა: %m" +#, c-format +#~ msgid "could not close directory \"%s\": %m" +#~ msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" + +#, c-format +#~ msgid "could not connect to database" +#~ msgstr "ბაზასთან მიერთების შეცდომა" + #, c-format #~ msgid "could not identify current directory: %m" #~ msgstr "მიმდინარე საქაღალდის იდენტიფიკაციის პრობლემა: %m" +#, c-format +#~ msgid "could not open global.dat file: \"%s\"" +#~ msgstr "ვერ გავხსენი ფაილი global.dat: \"%s\"" + +#, c-format +#~ msgid "could not open global.dat file: %s" +#~ msgstr "ვერ გავხსენი ფაილი global.dat: %s" + +#, c-format +#~ msgid "could not open map.dat file: \"%s\"" +#~ msgstr "შეუძლებელია map.dat ფაილის გახსნა: \"%s\"" + #, c-format #~ msgid "could not read symbolic link \"%s\": %m" #~ msgstr "სიმბოლური ბმის \"%s\" წაკითხვის შეცდომა: %m" +#, c-format +#~ msgid "errors ignored on global.dat file restore: %d" +#~ msgstr "ფაილის global.dat აღდგენისას გამოტოვებული შეცდომები: %d" + #, c-format #~ msgid "failed to LZ4 compress data: %s" #~ msgstr "'LZ4'-ით მონაცემების შეკუმშვა შეუძლებელია: %s" @@ -3008,10 +3362,18 @@ msgstr "" #~ msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" #~ msgstr "მოთხოვნის შედეგია ნულოვანი ბმის ცხრილის სახელის უცხო გასაღების ტრიგერი \"%s\" ცხრილზე \"%s\" (ცხრილის OID: %u)" +#, c-format +#~ msgid "reconnection failed: %s" +#~ msgstr "თავიდან მიერთების შეცდომა: %s" + #, c-format #~ msgid "requested compression not available in this installation -- archive will be uncompressed" #~ msgstr "მოთხოვნილი შეკუმშვა ამ აგებაში მხარდაუჭერელია. -- არქივი შეუკუმშავი იქნება" +#, c-format +#~ msgid "trying to connect database \"template1\" as failed to connect to database \"postgres\" to dump into out file" +#~ msgstr "ვცდილობ, მივუერთდე მონაცემთა ბაზას \"template1\", რადგან მცდელობა, მივერთებოდი მონაცემთა ბაზას \"postgres\" გამოსატან ფაილში დამპისთვის, ჩავარდა" + #, c-format #~ msgid "unexpected tgtype value: %d" #~ msgstr "tgtype -ის არასწორი მნიშვნელობა: %d" diff --git a/src/bin/pg_dump/po/ko.po b/src/bin/pg_dump/po/ko.po index f38254e8dfb1a..296f7e5ff487f 100644 --- a/src/bin/pg_dump/po/ko.po +++ b/src/bin/pg_dump/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_dump (PostgreSQL) 16\n" +"Project-Id-Version: pg_dump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:51+0000\n" -"PO-Revision-Date: 2023-09-08 16:10+0900\n" +"POT-Creation-Date: 2025-01-17 04:51+0000\n" +"PO-Revision-Date: 2025-01-16 14:55+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -90,32 +90,47 @@ msgstr "\"%s\" 압축 알고리즘을 사용할 때는 작업자 수를 지정 msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "\"%s\" 압축 알고리즘은 원거리 모드를 지원하지 않습니다" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일임: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "실행 할 \"%s\" 파일을 찾을 수 없음" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 경로를 절대경로로 바꿀 수 없음: %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령에서 읽을 수 없음: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령이 아무런 데이터도 반환하지 않음" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "메모리 부족" @@ -130,6 +145,49 @@ msgstr "메모리 부족\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위해 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일 상태 정보를 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 일 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -170,227 +228,247 @@ msgstr "\"%s\" 값은 %s 옵션 값으로 유효하지 않음" msgid "%s must be in range %d..%d" msgstr "%s 값은 %d부터 %d까지 지정할 수 있습니다." -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 있습니다: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있습니다: \"%s\"\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "확장 기능 읽는 중" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "확장 멤버를 식별 중" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "스키마들을 읽는 중" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "사용자 정의 테이블들을 읽는 중" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "사용자 정의 함수들 읽는 중" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "사용자 정의 자료형을 읽는 중" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "프로시쥬얼 언어를 읽는 중" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "사용자 정의 집계 함수를 읽는 중" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "사용자 정의 연산자를 읽는 중" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "사용자 정의 접근 방법을 읽는 중" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "사용자 정의 연산자 클래스를 읽는 중" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "사용자 정의 연산자 부류들 읽는 중" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "사용자 정의 텍스트 검색 파서를 읽는 중" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "사용자 정의 텍스트 검색 템플릿을 읽는 중" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "사용자 정의 텍스트 검색 사전을 읽는 중" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "사용자 정의 텍스트 검색 구성을 읽는 중" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "사용자 정의 외부 데이터 래퍼를 읽는 중" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "사용자 정의 외부 서버를 읽는 중" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "기본 접근 권한 읽는 중" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "사용자 정의 글자 정렬(collation) 읽는 중" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "사용자 정의 인코딩 변환규칙을 읽는 중" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "형변환자(type cast)들을 읽는 중" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "변환자(transform) 읽는 중" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "테이블 상속 정보를 읽는 중" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "이벤트 트리거들을 읽는 중" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "확장 테이블을 찾는 중" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "상속 관계를 조사중" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "재미난 테이블들(interesting tables)을 위해 열 정보를 읽는 중" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "하위 테이블에서 상속된 열 구분중" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "파티션 자료 읽는 중" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "인덱스들을 읽는 중" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "하위 파티션 테이블에서 인덱스를 플래그 처리하는 중" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "확장 통계들을 읽는 중" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "제약 조건들을 읽는 중" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "트리거들을 읽는 중" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "룰(rule) 읽는 중" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "정책 읽는 중" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "발행 정보를 읽는 중" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "테이블의 발행 맵버쉽을 읽는 중" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "스키마의 발행 맵버쉽을 읽을 중" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "구독정보를 읽는 중" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "테이블의 구독 맵버쉽을 읽는 중" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "안전 검사 실패, OID %u인 부모 개체가 없음. 해당 테이블 \"%s\" (OID %u)" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "잘못된 부모 수: %d, 해당 테이블 \"%s\"" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "\"%s\" 숫자 배열을 분석할 수 없음: 너무 많은 숫자들이 있음" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "\"%s\" 숫자 배열을 분석할 수 없음: 숫자안에 이상한 글자가 있음" @@ -420,15 +498,20 @@ msgstr "자료 압축을 풀 수 없습니다: %s" msgid "could not close compression library: %s" msgstr "압축 라이브러리를 닫을 수 없음: %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "입력 파일을 읽을 수 없음: %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:374 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "입력 파일을 읽을 수 없음: %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:372 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "입력 파일을 읽을 수 없음: 파일 끝" @@ -468,27 +551,72 @@ msgstr "압축 풀기 작업 끝내기 실패: %s" msgid "could not set compression parameter \"%s\": %s" msgstr "\"%s\" 압축 매개 변수를 지정할 수 없음: %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:232 compress_zstd.c:491 +#: compress_zstd.c:499 #, c-format msgid "could not initialize compression library" msgstr "압축 라이브러리를 초기화 할 수 없음" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:195 compress_zstd.c:309 #, c-format msgid "could not decompress data: %s" msgstr "자료를 압축 해제 할 수 없음: %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "입력 파일을 읽을 수 없음: %m" - -#: compress_zstd.c:501 +#: compress_zstd.c:502 #, c-format msgid "unhandled mode \"%s\"" msgstr "\"%s\" 모드는 처리할 수 없음" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "\"%s\" 필터 파일을 열 수 없음: %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "\"%s\" 필터 파일을 닫을 수 없음: %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "표준 입력의 %d 번째 줄을 읽는데 잘못된 필터 포멧: %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "\"%s\" 파일의 %d 번째 줄에 잘못된 필터 포멧: %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "\"%s\" 필터 파일을 읽을 수 없음: %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "예상치 못한 파일 끝" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "객체 이름 패턴이 빠졌음" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "필터 명령이 없음 (\"include\" 또는 \"exclude\" 사용할 수 있음)" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "잘못된 필터 명령 (\"include\" 또는 \"exclude\" 사용할 수 있음)" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "필터 객체형이 빠졌음" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "지원하지 않는 필터 객체형: \"%.*s\"" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -571,387 +699,392 @@ msgstr "pgpipe: 소켓 접속 실패: 오류 코드 %d" msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: 접속을 승인할 수 없음: 오류 코드 %d" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "출력 파일을 닫을 수 없음: %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "아카이브 아이템의 순서가 섹션에서 비정상적임" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "예상치 못한 섹션 코드 %d" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "이 아카이브 파일 형식에서는 병렬 복원이 지원되지 않음" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "8.0 이전 pg_dump로 만든 아카이브에서는 병렬 복원이 지원되지 않음" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "압축된 아카이브 (%s) 에서 복원할 수 없음" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "복원 작업을 위해 데이터베이스에 접속 중" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "pre-1.3 archive에서 직통 데이터베이스 접속은 지원되지 않음" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "암묵적으로 자료만 복원" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "%s %s 삭제 중" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "\"%s\" 구문에서 insert IF EXISTS 부분을 찾을 수 없음" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "원본 덤프 파일에서 발생한 경고: %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "%s \"%s.%s\" 만드는 중" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "%s \"%s\" 만드는 중" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "\"%s\" 새 데이터베이스에 접속중" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "%s 처리 중" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "\"%s.%s\" 테이블의 자료를 처리 중" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "실행중: %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "%s 트리거 작동을 비활성화 하는 중" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "%s 트리거 작동을 활성화 하는 중" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "" "internal error -- WriteData cannot be called outside the context of a " "DataDumper routine" msgstr "내부 오류 -- WriteData는 DataDumper 루틴 영역 밖에서 호출 될 수 없음" -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "선택한 파일 양식으로는 large-object를 덤프할 수 없음" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "%d개의 큰 개체가 복원됨" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "%u OID large object를 복원중" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "%u large object를 만들 수 없음: %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3718 +#: pg_backup_archiver.c:1486 pg_dump.c:3888 #, c-format msgid "could not open large object %u: %s" msgstr "%u large object를 열 수 없음: %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "TOC 파일 \"%s\"을(를) 열 수 없음: %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "줄 무시됨: %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "%d ID에 대한 항목을 찾지 못했음" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "TOC 파일을 닫을 수 없음: %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "\"%s\" 출력 파일을 열 수 없음: %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "출력 파일을 열 수 없음: %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "%zu 바이트의 큰 객체 데이터를 씀(결과 = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "큰 객체를 쓸 수 없음: %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "초기화 작업 중:" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "TOC 처리하는 중:" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "뒷 마무리 작업 중:" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "%d TOC 항목에서; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "잘못된 dumpID" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "TABLE DATA 아이템에 대한 잘못된 테이블 dumpId" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "예상치 못한 자료 옵셋 플래그 %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "덤프 파일에서 파일 옵셋 값이 너무 큽니다" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "디렉터리 이름이 너무 긺: \"%s\"" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "" "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not " "exist)" msgstr "\"%s\" 디렉터리가 알맞은 아카이브용이 아님 (\"toc.dat\" 파일이 없음)" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "\"%s\" 입력 파일을 열 수 없음: %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "입력 파일을 열 수 없음: %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "입력 파일을 읽을 수 없음: %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "입력 파일이 너무 짧습니다 (%lu 읽었음, 예상치 5)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "입력 파일은 일반 텍스트 덤프 파일입니다. psql 명령을 사용하세요." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "입력 파일에서 타당한 아카이브를 찾을 수 없습니다(너무 짧은지?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "입력 파일에서 타당한 아카이브를 찾을 수 없음" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "입력 파일을 닫을 수 없음: %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "추가용 표준출력 파일을 열 수 없음: %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "알 수 없는 파일 포멧: \"%d\"" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4448 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4647 #, c-format msgid "finished item %d %s %s" msgstr "%d %s %s 항목 마침" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4461 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4660 #, c-format msgid "worker process failed: exit code %d" msgstr "작업자 프로세스 실패: 종료 코드 %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "%d ID 항목은 범위를 벗어났음 -- TOC 정보가 손상된 듯 합니다" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "WITH OIDS 옵션이 있는 테이블의 복원은 이제 지원하지 않습니다" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "알 수 없는 인코딩: \"%s\"" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2823 #, c-format msgid "invalid ENCODING item: %s" msgstr "잘못된 ENCODING 항목: %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2841 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "잘못된 STDSTRINGS 항목: %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2866 #, c-format msgid "schema \"%s\" not found" msgstr "\"%s\" 스키마를 찾을 수 없음" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2873 #, c-format msgid "table \"%s\" not found" msgstr "\"%s\" 테이블을 찾을 수 없음" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2880 #, c-format msgid "index \"%s\" not found" msgstr "\"%s\" 인덱스를 찾을 수 없음" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2887 #, c-format msgid "function \"%s\" not found" msgstr "\"%s\" 함수를 찾을 수 없음" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2894 #, c-format msgid "trigger \"%s\" not found" msgstr "\"%s\" 트리거를 찾을 수 없음" -#: pg_backup_archiver.c:3183 +#: pg_backup_archiver.c:3325 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "\"%s\" 사용자로 세션 사용자를 지정할 수 없음: %s" -#: pg_backup_archiver.c:3315 +#: pg_backup_archiver.c:3457 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "search_path를 \"%s\"(으)로 지정할 수 없음: %s" +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "\"search_path\"를 \"%s\"(으)로 지정할 수 없음: %s" -#: pg_backup_archiver.c:3376 +#: pg_backup_archiver.c:3518 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "default_tablespace로 %s(으)로 지정할 수 없음: %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "\"default_tablespace\"로 %s(으)로 지정할 수 없음: %s" -#: pg_backup_archiver.c:3425 +#: pg_backup_archiver.c:3567 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "default_table_access_method를 지정할 수 없음: %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "\"default_table_access_method\"를 지정할 수 없음: %s" -#: pg_backup_archiver.c:3530 +#: pg_backup_archiver.c:3616 +#, c-format +msgid "could not alter table access method: %s" +msgstr "alter table access method 실행 할 수 없음: %s" + +#: pg_backup_archiver.c:3717 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "\"%s\" 개체의 소유주를 지정할 수 없습니다" -#: pg_backup_archiver.c:3752 +#: pg_backup_archiver.c:4004 #, c-format msgid "did not find magic string in file header" msgstr "파일 헤더에서 매직 문자열을 찾지 못했습니다" -#: pg_backup_archiver.c:3766 +#: pg_backup_archiver.c:4018 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "파일 헤더에 있는 %d.%d 버전은 지원되지 않습니다" -#: pg_backup_archiver.c:3771 +#: pg_backup_archiver.c:4023 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "정수 크기 (%lu) 안전성 검사 실패" -#: pg_backup_archiver.c:3775 +#: pg_backup_archiver.c:4027 #, c-format msgid "" "archive was made on a machine with larger integers, some operations might " @@ -960,12 +1093,12 @@ msgstr "" "이 아카이브는 큰 정수를 지원하는 시스템에서 만들어졌습니다. 그래서 몇 동작이 " "실패할 수도 있습니다." -#: pg_backup_archiver.c:3785 +#: pg_backup_archiver.c:4037 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "예상되는 포멧 (%d)와 발견된 파일 포멧 (%d)이 서로 다름" -#: pg_backup_archiver.c:3807 +#: pg_backup_archiver.c:4059 #, c-format msgid "" "archive is compressed, but this installation does not support compression " @@ -974,68 +1107,68 @@ msgstr "" "아카이브는 압축되어있지만, 이 프로그램에서는 (%s) 압축기능을 지원하지 못합니" "다 -- 이 안에 있는 자료를 모두 사용할 수 없습니다." -#: pg_backup_archiver.c:3843 +#: pg_backup_archiver.c:4095 #, c-format msgid "invalid creation date in header" msgstr "헤더에 잘못된 생성 날짜가 있음" -#: pg_backup_archiver.c:3977 +#: pg_backup_archiver.c:4229 #, c-format msgid "processing item %d %s %s" msgstr "%d %s %s 항목을 처리하는 중" -#: pg_backup_archiver.c:4052 +#: pg_backup_archiver.c:4314 #, c-format msgid "entering main parallel loop" msgstr "기본 병렬 루프로 시작 중" -#: pg_backup_archiver.c:4063 +#: pg_backup_archiver.c:4325 #, c-format msgid "skipping item %d %s %s" msgstr "%d %s %s 항목을 건너뛰는 중" -#: pg_backup_archiver.c:4072 +#: pg_backup_archiver.c:4334 #, c-format msgid "launching item %d %s %s" msgstr "%d %s %s 항목을 시작하는 중" -#: pg_backup_archiver.c:4126 +#: pg_backup_archiver.c:4388 #, c-format msgid "finished main parallel loop" msgstr "기본 병렬 루프 마침" -#: pg_backup_archiver.c:4162 +#: pg_backup_archiver.c:4424 #, c-format msgid "processing missed item %d %s %s" msgstr "누락된 %d %s %s 항목 처리 중" -#: pg_backup_archiver.c:4767 +#: pg_backup_archiver.c:4966 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "\"%s\" 테이블을 만들 수 없어, 해당 자료는 복원되지 않을 것입니다." -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "잘못된 large object용 OID" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "파일 seek 작업하는 도중 오류가 발생했습니다: %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "%d 자료 블록에 잘못된 접근 위치가 있음" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "아카이브 검색하는 동안 알 수 없는 자료 블럭 형태(%d)를 발견함" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "" "could not find block ID %d in archive -- possibly due to out-of-order " @@ -1044,56 +1177,56 @@ msgstr "" "아카이브에서 블록 ID %d을(를) 찾지 못했습니다. 복원 요청이 잘못된 것 같습니" "다. 입력 파일을 검색할 수 없으므로 요청을 처리할 수 없습니다." -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "" "아카이브에서 블록 ID %d을(를) 찾을 수 없습니다. 아카이브가 손상된 것 같습니" "다." -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "자료를 읽는 동안 예상치 못한 ID (%d) 발견됨 -- 예상값 %d" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "아카이브 복원하는 중에, 알 수 없는 자료 블럭 형태 %d 를 발견함" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "아카이브 파일에서 검색 위치를 확인할 수 없음: %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "자료 파일을 닫을 수 없음: %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "입력 아카이브만 다시 열 수 있음" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "표준 입력을 이용한 병렬 복원 작업은 지원하지 않습니다" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "" "시작 위치를 임의로 지정할 수 없는 파일로는 병렬 복원 작업을 할 수 없습니다." -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "아카이브 파일에서 검색 위치를 설정할 수 없음: %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "압축기 사용" @@ -1103,12 +1236,12 @@ msgstr "압축기 사용" msgid "could not get server_version from libpq" msgstr "libpq에서 server_verion 값을 구할 수 없음" -#: pg_backup_db.c:53 pg_dumpall.c:1809 +#: pg_backup_db.c:53 pg_dumpall.c:1830 #, c-format msgid "aborting because of server version mismatch" msgstr "서버 버전이 일치하지 않아 중단하는 중" -#: pg_backup_db.c:54 pg_dumpall.c:1810 +#: pg_backup_db.c:54 pg_dumpall.c:1831 #, c-format msgid "server version: %s; %s version: %s" msgstr "서버 버전: %s; %s 버전: %s" @@ -1118,7 +1251,7 @@ msgstr "서버 버전: %s; %s 버전: %s" msgid "already connected to a database" msgstr "데이터베이스에 이미 접속해 있음" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1656 pg_dumpall.c:1758 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 msgid "Password: " msgstr "암호: " @@ -1132,18 +1265,18 @@ msgstr "데이터베이스 접속을 할 수 없음" msgid "reconnection failed: %s" msgstr "재연결 실패: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1683 pg_dumpall.c:1767 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1872 pg_dumpall.c:1895 +#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 #, c-format msgid "query failed: %s" msgstr "쿼리 실패: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1873 pg_dumpall.c:1896 +#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "Query was: %s" msgstr "사용한 쿼리: %s" @@ -1178,7 +1311,7 @@ msgstr "PQputCopyEnd에 의해서 오류가 반환되었음: %s" msgid "COPY failed for table \"%s\": %s" msgstr "\"%s\" 테이블을 위한 COPY 실패: %s" -#: pg_backup_db.c:521 pg_dump.c:2202 +#: pg_backup_db.c:521 pg_dump.c:2283 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "\"%s\" 테이블 COPY 작업 중 잘못된 부가 결과가 있음" @@ -1191,149 +1324,144 @@ msgstr "데이터베이스 트랜잭션을 시작할 수 없음" msgid "could not commit database transaction" msgstr "데이터베이스 트랜잭션을 commit 할 수 없음" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "자료가 저장될 디렉터리를 지정하지 않았음" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "출력 파일을 쓸 수 없음: %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "자료 파일을 닫을 수 없음: %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "\"%s\" 자료 파일을 닫을 수 없음: %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "입력용 large object TOC 파일(\"%s\")을 열 수 없음: %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음: \"%s\"" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "large object TOC 파일(\"%s\")을 닫을 수 없음: %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "LO 자료 파일을 닫을 수 없음: %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "LO TOC 파일에 쓸 수 없음: %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" msgstr "LO TOC 파일을 닫을 수 없음: %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "파일 이름이 너무 긺: \"%s\"" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "이 파일 형태는 읽을 수 없음" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "출력용 TOC 파일 \"%s\"을(를) 열 수 없음: %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "출력용 TOC 파일을 열 수 없음: %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "tar 출력 포멧에서 압축 기능을 지원하지 않음" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "입력용 TOC 파일(\"%s\")을 열 수 없음: %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "입력용 TOC 파일을 열 수 없음: %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "아카이브에서 \"%s\" 파일을 찾을 수 없음" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "임시 파일 이름을 짓지 못했습니다: %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "COPY 구문 오류: \"%s\"" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "잘못된 large object OID: %u" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "임시 파일을 열 수 없음: %m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "실재 파일 길이(%lld)와 예상되는 값(%lld)이 다릅니다" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "tar 아카이브에서 \"%s\" 파일을 위한 헤더를 찾을 수 없음" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "" "restoring data out of order is not supported in this archive format: \"%s\" " @@ -1342,13 +1470,13 @@ msgstr "" "순서를 넘어서는 자료 덤프 작업은 이 아카이브 포멧에서는 지원하지 않습니다: " "\"%s\" 요구되었지만, 이 아카이브 파일에서는 \"%s\" 전에 옵니다." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" msgstr[0] "불완전한 tar 헤더가 있음(%lu 바이트)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "" "corrupt tar header found in %s (expected %d, computed %d) file position %llu" @@ -1359,10 +1487,10 @@ msgstr "%s 안에 손상된 tar 헤더 발견 (예상치 %d, 계산된 값 %d), msgid "unrecognized section name: \"%s\"" msgstr "알 수 없는 섹션 이름: \"%s\"" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." @@ -1372,39 +1500,39 @@ msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." msgid "out of on_exit_nicely slots" msgstr "on_exit_nicely 슬롯 범위 벗어남" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인자를 지정했음 (시작: \"%s\")" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "-s/--schema-only 옵션과 -a/--data-only 옵션은 함께 사용할 수 없음" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "" "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "" "-s/--schema-only 옵션과 --include-foreign-data 옵션은 함께 사용할 수 없음" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "--include-foreign-data 옵션은 병렬 백업 작업에서 지원하지 않음" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "-c/--clean 옵션과 -a/--data-only 옵션은 함께 사용할 수 없음" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "--if-exists 옵션은 -c/--clean 옵션과 함께 사용해야 함" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "" "option --on-conflict-do-nothing requires option --inserts, --rows-per-" @@ -1413,47 +1541,47 @@ msgstr "" "--on-conflict-do-nothing 옵션은 --inserts, --rows-per-insert 또는 --column-" "inserts 옵션과 함께 사용해야 함" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "알 수 없는 압축 알고리즘: \"%s\"" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "잘못된 압축 명세: %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "\"%s\" 압축 옵션은 pg_dump에서 현재 지원하지 않음" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "병렬 백업은 디렉터리 기반 출력일 때만 사용할 수 있습니다." -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "마지막 내장 OID는 %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "조건에 맞는 스키마가 없습니다" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "조건에 맞는 테이블이 없습니다" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "조건에 맞는 확장 모듈이 없습니다" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1463,17 +1591,17 @@ msgstr "" "다른 형태의 파일로 덤프합니다.\n" "\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:635 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [옵션]... [DB이름]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:638 pg_restore.c:455 #, c-format msgid "" "\n" @@ -1482,12 +1610,12 @@ msgstr "" "\n" "일반 옵션들:\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=파일이름 출력 파일 또는 디렉터리 이름\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1496,22 +1624,22 @@ msgstr "" " -F, --format=c|d|t|p 출력 파일 형식(사용자 지정, 디렉터리, tar,\n" " 일반 텍스트(초기값))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=개수 덤프 작업을 병렬 처리 함\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:640 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose 작업 내역을 자세히 봄\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:641 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1520,26 +1648,31 @@ msgstr "" " -Z, --compress=METHOD[:DETAIL]\n" " 압축 지정\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:642 #, c-format msgid "" " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr "" " --lock-wait-timeout=초 테이블 잠금 시 지정한 초만큼 기다린 후 실패\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:670 #, c-format msgid "" " --no-sync do not wait for changes to be written safely " "to disk\n" msgstr " --no-sync fsync 작업 생략\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD 파일을 디스크에 동기화할 방법 지정\n" + +#: pg_dump.c:1108 pg_dumpall.c:643 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:644 #, c-format msgid "" "\n" @@ -1548,34 +1681,34 @@ msgstr "" "\n" "출력 내용을 다루는 옵션들:\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:645 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only 스키마 빼고 자료만 덤프\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects 큰 객체를 덤프에 포함\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (--large-objects 와 같음, 옛날 옵션)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects 큰 객체 빼고 덤프\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid "" " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr "" " --no-blobs (--no-large-objects와 같음, 옛날 옵션)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid "" " -c, --clean clean (drop) database objects before " @@ -1584,34 +1717,34 @@ msgstr "" " -c, --clean 다시 만들기 전에 데이터베이스 개체 지우기(삭" "제)\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid "" " -C, --create include commands to create database in dump\n" msgstr "" " -C, --create 데이터베이스 만드는 명령구문도 포함시킴\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=PATTERN 지정한 확장 모듈들만 덤프 함\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:647 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=인코딩 지정한 인코딩으로 자료를 덤프 함\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=PATTERN 지정한 SCHEMA들 자료만 덤프\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=PATTERN 지정한 SCHEMA들만 빼고 모두 덤프\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1620,12 +1753,12 @@ msgstr "" " -O, --no-owner 일반 텍스트 형식에서\n" " 개체 소유권 복원 건너뛰기\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:651 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr " -s, --schema-only 자료구조(스키마)만 덤프\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid "" " -S, --superuser=NAME superuser user name to use in plain-text " @@ -1634,28 +1767,28 @@ msgstr "" " -S, --superuser=NAME 일반 텍스트 형식에서 사용할 슈퍼유저 사용자 이" "름\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=PATTERN 지정한 이름의 테이블들만 덤프\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=PATTERN 지정한 테이블들만 빼고 덤프\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:654 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr "" " -x, --no-privileges 접근 권한 (grant/revoke) 정보는 덤프 안 함\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:655 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade 업그레이드 유틸리티 전용\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:656 #, c-format msgid "" " --column-inserts dump data as INSERT commands with column " @@ -1663,7 +1796,7 @@ msgid "" msgstr "" " --column-inserts 칼럼 이름과 함께 INSERT 명령으로 자료 덤프\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:657 #, c-format msgid "" " --disable-dollar-quoting disable dollar quoting, use SQL standard " @@ -1671,13 +1804,13 @@ msgid "" msgstr "" " --disable-dollar-quoting $ 인용 구문 사용안함, SQL 표준 따옴표 사용\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:658 pg_restore.c:483 #, c-format msgid "" " --disable-triggers disable triggers during data-only restore\n" msgstr " --disable-triggers 자료만 복원할 때 트리거 사용을 안함\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid "" " --enable-row-security enable row security (dump only content user " @@ -1687,7 +1820,12 @@ msgstr "" " --enable-row-security 로우 보안 활성화 (현재 작업자가 접근할 수\n" " 있는 자료만 덤프 함)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=PATTERN 지정한 확장 모듈은 덤프하지 않음\n" + +#: pg_dump.c:1136 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1699,13 +1837,13 @@ msgstr "" " 상속 하위, 파티션 하위 테이블을 포함하는\n" " 패턴의 테이블들은 빼고 덤프\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid "" " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=PATTERN 해당 테이블 자료는 덤프 안함\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1716,19 +1854,29 @@ msgstr "" " 상속 하위, 파티션 하위 테이블을 포함하는\n" " 패턴의 테이블들의 자료는 빼고 덤프\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:660 #, c-format msgid "" " --extra-float-digits=NUM override default setting for " "extra_float_digits\n" msgstr " --extra-float-digits=NUM 기본 extra_float_digits 값 바꿈\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid "" +" --filter=FILENAME include or exclude objects and data from " +"dump\n" +" based on expressions in FILENAME\n" +msgstr "" +" --filter=FILENAME 지정한 파일의 규칙대로 포함하거나 제외할\n" +" 객체를 반영하여 덤프\n" + +#: pg_dump.c:1146 pg_dumpall.c:662 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists 객체 삭제 시 IF EXISTS 구문 사용\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1739,60 +1887,60 @@ msgstr "" " 지정한 패턴과 일치하는 외부 서버의 외부\n" " 테이블 자료를 포함\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:663 #, c-format msgid "" " --inserts dump data as INSERT commands, rather than " "COPY\n" msgstr " --inserts COPY 대신 INSERT 명령으로 자료 덤프\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:664 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr "" " --load-via-partition-root 상위 테이블을 통해 하위 테이블을 로드함\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:665 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments 코멘트는 덤프 안함\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:666 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications 발행 정보는 덤프하지 않음\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:668 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels 보안 라벨 할당을 덤프 하지 않음\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:669 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions 구독 정보는 덤프하지 않음\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:671 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method 테이블 접근 방법은 덤프하지 않음\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:672 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces 테이블스페이스 할당을 덤프하지 않음\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:673 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression TOAST 압축 방법은 덤프하지 않음\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:674 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data 언로그드 테이블 자료는 덤프하지 않음\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:675 #, c-format msgid "" " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT " @@ -1801,14 +1949,14 @@ msgstr "" " --on-conflict-do-nothing INSERT 구문에 ON CONFLICT DO NOTHING 옵션 추" "가\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:676 #, c-format msgid "" " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr "" " --quote-all-identifiers 예약어가 아니여도 모든 식별자는 따옴표를 씀\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:677 #, c-format msgid "" " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" @@ -1816,7 +1964,7 @@ msgstr "" " --rows-per-insert=NROWS 한 INSERT 명령으로 입력할 로우 수; --inserts\n" " 옵션을 사용한 것으로 가정 함\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid "" " --section=SECTION dump named section (pre-data, data, or post-" @@ -1824,7 +1972,7 @@ msgid "" msgstr "" " --section=SECTION 해당 섹션(pre-data, data, post-data)만 덤프\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid "" " --serializable-deferrable wait until the dump can run without " @@ -1833,12 +1981,12 @@ msgstr "" " --serializable-deferrable 자료 정합성을 보장하기 위해 덤프 작업을\n" " 직렬화 가능한 트랜잭션으로 처리 함\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT 지정한 스냅샷을 덤프 함\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid "" " --strict-names require table and/or schema include patterns " @@ -1849,7 +1997,7 @@ msgstr "" "는\n" " 객체가 적어도 하나 이상 있어야 함\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1858,7 +2006,7 @@ msgstr "" " --table-and-children=PATTERN 해당 패턴의 상속 하위, 파티션 하위 테이블만\n" " 덤프\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:678 pg_restore.c:500 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1871,7 +2019,7 @@ msgstr "" "명령\n" " 대신 사용하여 소유권 설정\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:682 pg_restore.c:504 #, c-format msgid "" "\n" @@ -1880,45 +2028,45 @@ msgstr "" "\n" "연결 옵션들:\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=DBNAME 덤프할 데이터베이스\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:684 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME 접속할 데이터베이스 서버 또는 소켓 디렉터리\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:686 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT 데이터베이스 서버의 포트 번호\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:687 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME 연결할 데이터베이스 사용자\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:688 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password 암호 프롬프트 표시 안 함\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:689 pg_restore.c:509 #, c-format msgid "" " -W, --password force password prompt (should happen " "automatically)\n" msgstr " -W, --password 암호 입력 프롬프트 보임(자동으로 처리함)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:690 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLENAME 덤프 전에 SET ROLE 수행\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "" "\n" @@ -1931,423 +2079,430 @@ msgstr "" "사용합니다.\n" "\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:694 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "문제점 보고 주소 <%s>\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:695 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "클라이언트 인코딩 값이 잘못되었습니다: \"%s\"" -#: pg_dump.c:1303 +#: pg_dump.c:1352 #, c-format msgid "" "parallel dumps from standby servers are not supported by this server version" msgstr "대기 서버에서 병렬 덤프는 이 서버 버전에서 지원하지 않음" -#: pg_dump.c:1368 +#: pg_dump.c:1417 #, c-format msgid "invalid output format \"%s\" specified" msgstr "\"%s\" 값은 잘못된 출력 파일 형태입니다." -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1449 +#: pg_dump.c:1458 pg_dump.c:1514 pg_dump.c:1567 pg_dumpall.c:1467 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "적당하지 않은 qualified 이름 입니다 (너무 많은 점이 있네요): %s" -#: pg_dump.c:1417 +#: pg_dump.c:1466 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "\"%s\" 검색 조건에 만족하는 스키마가 없습니다" -#: pg_dump.c:1470 +#: pg_dump.c:1519 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "\"%s\" 검색 조건에 만족하는 확장 모듈이 없습니다" -#: pg_dump.c:1523 +#: pg_dump.c:1572 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "\"%s\" 검색 조건에 만족하는 외부 서버가 없습니다" -#: pg_dump.c:1594 +#: pg_dump.c:1643 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "" "적당하지 않은 릴레이션(relation) 이름 입니다 (너무 많은 점이 있네요): %s" -#: pg_dump.c:1616 +#: pg_dump.c:1665 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "\"%s\" 검색 조건에 만족하는 테이블이 없습니다" -#: pg_dump.c:1643 +#: pg_dump.c:1692 #, c-format msgid "You are currently not connected to a database." msgstr "현재 데이터베이스에 연결되어있지 않습니다." -#: pg_dump.c:1646 +#: pg_dump.c:1695 #, c-format msgid "cross-database references are not implemented: %s" msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: %s" -#: pg_dump.c:2077 +#: pg_dump.c:2154 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "\"%s.%s\" 테이블의 내용 덤프 중" -#: pg_dump.c:2183 +#: pg_dump.c:2264 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "\"%s\" 테이블 내용을 덤프하면서 오류 발생: PQgetCopyData() 실패." -#: pg_dump.c:2184 pg_dump.c:2194 +#: pg_dump.c:2265 pg_dump.c:2275 #, c-format msgid "Error message from server: %s" msgstr "서버에서 보낸 오류 메시지: %s" -#: pg_dump.c:2185 pg_dump.c:2195 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Command was: %s" msgstr "사용된 명령: %s" -#: pg_dump.c:2193 +#: pg_dump.c:2274 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "\"%s\" 테이블 내용을 덤프하면서 오류 발생: PQgetResult() 실패." -#: pg_dump.c:2275 +#: pg_dump.c:2365 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "\"%s\" 테이블에서 잘못된 필드 수" -#: pg_dump.c:2973 +#: pg_dump.c:3067 #, c-format msgid "saving database definition" msgstr "데이터베이스 구성정보를 저장 중" -#: pg_dump.c:3078 +#: pg_dump.c:3176 #, c-format msgid "unrecognized locale provider: %s" msgstr "알 수 없는 로케일 제공자 이름: %s" -#: pg_dump.c:3429 +#: pg_dump.c:3537 #, c-format msgid "saving encoding = %s" msgstr "인코딩 = %s 저장 중" -#: pg_dump.c:3454 +#: pg_dump.c:3562 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "standard_conforming_strings = %s 저장 중" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "\"standard_conforming_strings = %s\" 저장 중" -#: pg_dump.c:3493 +#: pg_dump.c:3601 #, c-format msgid "could not parse result of current_schemas()" msgstr "current_schemas() 결과를 분석할 수 없음" -#: pg_dump.c:3512 +#: pg_dump.c:3620 #, c-format -msgid "saving search_path = %s" -msgstr "search_path = %s 저장 중" +msgid "saving \"search_path = %s\"" +msgstr "\"search_path = %s\" 저장 중" -#: pg_dump.c:3549 +#: pg_dump.c:3656 #, c-format msgid "reading large objects" msgstr "large object 읽는 중" -#: pg_dump.c:3687 +#: pg_dump.c:3877 #, c-format -msgid "saving large objects" -msgstr "large object들을 저장 중" +msgid "saving large objects \"%s\"" +msgstr "\"%s\" large object들을 저장 중" -#: pg_dump.c:3728 +#: pg_dump.c:3898 #, c-format msgid "error reading large object %u: %s" msgstr "%u large object 읽는 중 오류: %s" -#: pg_dump.c:3834 +#: pg_dump.c:4001 #, c-format msgid "reading row-level security policies" msgstr "로우 단위 보안 정책 읽는 중" -#: pg_dump.c:3975 +#: pg_dump.c:4142 #, c-format msgid "unexpected policy command type: %c" msgstr "예상치 못한 정책 명령 형태: %c" -#: pg_dump.c:4425 pg_dump.c:4760 pg_dump.c:11984 pg_dump.c:17894 -#: pg_dump.c:17896 pg_dump.c:18517 +#: pg_dump.c:4592 pg_dump.c:5150 pg_dump.c:12364 pg_dump.c:18249 +#: pg_dump.c:18251 pg_dump.c:18873 #, c-format msgid "could not parse %s array" msgstr "%s 배열을 분석할 수 없음" -#: pg_dump.c:4613 +#: pg_dump.c:4806 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "" "현재 사용자가 슈퍼유저가 아니기 때문에 서브스크립션들은 덤프하지 못했음" -#: pg_dump.c:5149 +#: pg_dump.c:5012 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "%u OID 구독이 없음" + +#: pg_dump.c:5019 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "안전 검사 실패, OID %u인 테이블 없음" + +#: pg_dump.c:5582 #, c-format msgid "could not find parent extension for %s %s" msgstr "%s %s 객체와 관련된 상위 확장 기능을 찾을 수 없음" -#: pg_dump.c:5294 +#: pg_dump.c:5727 #, c-format msgid "schema with OID %u does not exist" msgstr "OID %u 스키마 없음" -#: pg_dump.c:6776 pg_dump.c:17158 +#: pg_dump.c:7209 pg_dump.c:17620 #, c-format msgid "" "failed sanity check, parent table with OID %u of sequence with OID %u not " "found" msgstr "의존성 검사 실패, 부모 테이블 OID %u 없음. 해당 시퀀스 개체 OID %u" -#: pg_dump.c:6919 +#: pg_dump.c:7354 #, c-format msgid "" "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "완전성 검사 실패, OID %u인 객체가 pg_partitioned_table에 없음" -#: pg_dump.c:7150 pg_dump.c:7417 pg_dump.c:7888 pg_dump.c:8552 pg_dump.c:8671 -#: pg_dump.c:8819 +#: pg_dump.c:7585 pg_dump.c:7859 pg_dump.c:8306 pg_dump.c:8920 pg_dump.c:9042 +#: pg_dump.c:9190 #, c-format msgid "unrecognized table OID %u" msgstr "알 수 없는 테이블 OID %u" -#: pg_dump.c:7154 +#: pg_dump.c:7589 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "\"%s\" 테이블의 인덱스 자료를 알 수 없음" -#: pg_dump.c:7649 +#: pg_dump.c:8091 #, c-format msgid "" "failed sanity check, parent table with OID %u of pg_rewrite entry with OID " "%u not found" msgstr "의존성 검사 실패, 부모 테이블 OID %u 없음. 해당 pg_rewrite 개체 OID %u" -#: pg_dump.c:7940 -#, c-format -msgid "" -"query produced null referenced table name for foreign key trigger \"%s\" on " -"table \"%s\" (OID of table: %u)" -msgstr "" -"쿼리가 참조테이블 정보가 없는 \"%s\" 참조키 트리거를 \"%s\" (해당 OID: %u) 테" -"이블에서 만들었습니다." - -#: pg_dump.c:8556 +#: pg_dump.c:8924 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "\"%s\" 테이블의 알 수 없는 칼럼 자료" -#: pg_dump.c:8585 +#: pg_dump.c:8953 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "\"%s\" 테이블에 매겨져 있는 열 번호가 잘못되었습니다" -#: pg_dump.c:8633 +#: pg_dump.c:9004 #, c-format msgid "finding table default expressions" msgstr "default 표현식 찾는 중" -#: pg_dump.c:8675 +#: pg_dump.c:9046 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "적당하지 않는 adnum 값: %d, 해당 테이블 \"%s\"" -#: pg_dump.c:8769 +#: pg_dump.c:9140 #, c-format msgid "finding table check constraints" msgstr "테이블 체크 제약조건 찾는 중" -#: pg_dump.c:8823 +#: pg_dump.c:9194 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "" "%d개의 제약 조건이 \"%s\" 테이블에 있을 것으로 예상했으나 %d개를 찾음" -#: pg_dump.c:8827 +#: pg_dump.c:9198 #, c-format msgid "The system catalogs might be corrupted." msgstr "시스템 카탈로그가 손상되었는 것 같습니다." -#: pg_dump.c:9517 +#: pg_dump.c:9888 #, c-format msgid "role with OID %u does not exist" msgstr "%u OID 롤이 없음" -#: pg_dump.c:9629 pg_dump.c:9658 +#: pg_dump.c:10000 pg_dump.c:10029 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "지원하지 않는 pg_init_privs 항목: %u %u %d" -#: pg_dump.c:10479 +#: pg_dump.c:10576 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "\"%s\"large object의 메타정보가 없음" + +#: pg_dump.c:10859 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "\"%s\" 자료형의 typtype가 잘못 되어 있음" -#: pg_dump.c:12053 +#: pg_dump.c:12433 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "\"%s\" 함수의 provolatile 값이 잘못 되었습니다" -#: pg_dump.c:12103 pg_dump.c:13985 +#: pg_dump.c:12483 pg_dump.c:14379 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "\"%s\" 함수의 proparallel 값이 잘못 되었습니다" -#: pg_dump.c:12233 pg_dump.c:12339 pg_dump.c:12346 +#: pg_dump.c:12613 pg_dump.c:12719 pg_dump.c:12726 #, c-format msgid "could not find function definition for function with OID %u" msgstr "%u OID 함수에 대한 함수 정의를 찾을 수 없음" -#: pg_dump.c:12272 +#: pg_dump.c:12652 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "pg_cast.castfunc 또는 pg_cast.castmethod 필드에 잘못된 값이 있음" -#: pg_dump.c:12275 +#: pg_dump.c:12655 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "pg_cast.castmethod 필드에 잘못된 값이 있음" -#: pg_dump.c:12365 +#: pg_dump.c:12745 #, c-format msgid "" "bogus transform definition, at least one of trffromsql and trftosql should " "be nonzero" msgstr "잘못된 전송 정의, trffromsql 또는 trftosql 중 하나는 비어 있으면 안됨" -#: pg_dump.c:12382 +#: pg_dump.c:12762 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "pg_transform.trffromsql 필드에 잘못된 값이 있음" -#: pg_dump.c:12403 +#: pg_dump.c:12783 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "pg_transform.trftosql 필드에 잘못된 값이 있음" -#: pg_dump.c:12548 +#: pg_dump.c:12928 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "postfix 연산자는 더이상 지원하지 않습니다.(\"%s\" 연산자)" -#: pg_dump.c:12718 +#: pg_dump.c:13098 #, c-format msgid "could not find operator with OID %s" msgstr "%s OID의 연산자를 찾을 수 없음" -#: pg_dump.c:12786 +#: pg_dump.c:13166 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "\"%c\" 잘못된 자료형, 해당 접근 방법: \"%s\"" -#: pg_dump.c:13455 pg_dump.c:13514 +#: pg_dump.c:13840 pg_dump.c:13908 #, c-format msgid "unrecognized collation provider: %s" msgstr "알 수 없는 정렬규칙 제공자 이름: %s" -#: pg_dump.c:13464 pg_dump.c:13473 pg_dump.c:13483 pg_dump.c:13498 +#: pg_dump.c:13849 pg_dump.c:13856 pg_dump.c:13867 pg_dump.c:13877 +#: pg_dump.c:13892 #, c-format msgid "invalid collation \"%s\"" msgstr "잘못된 문자정렬규칙 \"%s\"" -#: pg_dump.c:13904 +#: pg_dump.c:14298 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "\"%s\" 집계 함수용 aggfinalmodify 값이 이상함" -#: pg_dump.c:13960 +#: pg_dump.c:14354 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "\"%s\" 집계 함수용 aggmfinalmodify 값이 이상함" -#: pg_dump.c:14677 +#: pg_dump.c:15071 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "기본 접근 권한에서 알 수 없는 객체형이 있음: %d" -#: pg_dump.c:14693 +#: pg_dump.c:15087 #, c-format msgid "could not parse default ACL list (%s)" msgstr "기본 ACL 목록 (%s)을 분석할 수 없음" -#: pg_dump.c:14775 +#: pg_dump.c:15171 #, c-format msgid "" "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "" "초기 ACL 목록 (%s) 또는 default (%s) 분석할 수 없음, 해당 객체: \"%s\" (%s)" -#: pg_dump.c:14800 +#: pg_dump.c:15196 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "ACL 목록 (%s) 또는 default (%s) 분석할 수 없음, 해당 객체: \"%s\" (%s)" -#: pg_dump.c:15341 +#: pg_dump.c:15739 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "\"%s\" 뷰 정의 정보가 없습니다." -#: pg_dump.c:15344 +#: pg_dump.c:15742 #, c-format msgid "" "query to obtain definition of view \"%s\" returned more than one definition" msgstr "\"%s\" 뷰 정의 정보가 하나 이상 있습니다." -#: pg_dump.c:15351 +#: pg_dump.c:15749 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "\"%s\" 뷰의 정의 내용이 비어있습니다." -#: pg_dump.c:15435 +#: pg_dump.c:15834 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS 옵션은 더이상 지원하지 않음 (\"%s\" 테이블)" -#: pg_dump.c:16359 +#: pg_dump.c:16821 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "잘못된 열 번호 %d, 해당 테이블 \"%s\"" -#: pg_dump.c:16437 +#: pg_dump.c:16899 #, c-format msgid "could not parse index statistic columns" msgstr "인덱스 통계정보 칼럼 분석 실패" -#: pg_dump.c:16439 +#: pg_dump.c:16901 #, c-format msgid "could not parse index statistic values" msgstr "인덱스 통계정보 값 분석 실패" -#: pg_dump.c:16441 +#: pg_dump.c:16903 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "인덱스 통계정보용 칼럼수와 값수가 일치하지 않음" -#: pg_dump.c:16657 +#: pg_dump.c:17118 #, c-format msgid "missing index for constraint \"%s\"" msgstr "\"%s\" 제약 조건을 위한 인덱스가 빠졌습니다" -#: pg_dump.c:16892 +#: pg_dump.c:17353 #, c-format msgid "unrecognized constraint type: %c" msgstr "알 수 없는 제약 조건 종류: %c" -#: pg_dump.c:16993 pg_dump.c:17222 +#: pg_dump.c:17454 pg_dump.c:17684 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "" @@ -2355,22 +2510,12 @@ msgid_plural "" msgstr[0] "" "\"%s\" 시퀀스의 데이터를 가져오기 위한 쿼리에서 %d개의 행 반환(1개 필요)" -#: pg_dump.c:17025 +#: pg_dump.c:17486 #, c-format msgid "unrecognized sequence type: %s" msgstr "알 수 없는 시퀀스 형태: %s" -#: pg_dump.c:17314 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "기대되지 않은 tgtype 값: %d" - -#: pg_dump.c:17386 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "잘못된 인수 문자열 (%s), 해당 트리거 \"%s\", 사용되는 테이블 \"%s\"" - -#: pg_dump.c:17655 +#: pg_dump.c:18001 #, c-format msgid "" "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows " @@ -2378,53 +2523,59 @@ msgid "" msgstr "" "\"%s\" 규칙(\"%s\" 테이블)을 가져오기 위한 쿼리 실패: 잘못된 행 수 반환" -#: pg_dump.c:17808 +#: pg_dump.c:18154 #, c-format msgid "could not find referenced extension %u" msgstr "%u 확장기능과 관련된 상위 확장 기능을 찾을 수 없음" -#: pg_dump.c:17898 +#: pg_dump.c:18253 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "확장 모듈용 환경설정 매개변수 수와 조건 수가 일치 하지 않음" -#: pg_dump.c:18030 +#: pg_dump.c:18385 #, c-format msgid "reading dependency data" msgstr "의존 관계 자료 읽는 중" -#: pg_dump.c:18116 +#: pg_dump.c:18471 #, c-format msgid "no referencing object %u %u" msgstr "%u %u 개체의 하위 관련 개체가 없음" -#: pg_dump.c:18127 +#: pg_dump.c:18482 #, c-format msgid "no referenced object %u %u" msgstr "%u %u 개체의 상위 관련 개체가 없음" -#: pg_dump_sort.c:422 +#: pg_dump.c:18907 pg_dump.c:18945 pg_dumpall.c:1962 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "%s 필터(대상 \"%s\")는 허용하지 않음" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "잘못된 dumpId %d" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "잘못된 의존성 %d" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "의존 관계를 식별 할 수 없음" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "다음 데이블 간 참조키가 서로 교차하고 있음:" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "" "You might not be able to restore the dump without using --disable-triggers " @@ -2433,7 +2584,7 @@ msgstr "" "--disable-triggers 옵션으로 복원할 수 있습니다. 또는 임시로 제약 조건을 삭제" "하고 복원하세요." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "" "Consider using a full dump instead of a --data-only dump to avoid this " @@ -2441,12 +2592,12 @@ msgid "" msgstr "" "이 문제를 피하려면, --data-only 덤프 대신에 모든 덤프를 사용하길 권합니다." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "다음 항목 간 의존 관계를 분석할 수 없음:" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " @@ -2455,46 +2606,46 @@ msgstr "" "\"%s\" 프로그램이 %s 작업에서 필요로 하지만, \"%s\" 디렉터리 안에 함께 있지 " "않습니다" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "\"%s\" 프로그램을 \"%s\" 작업 때문에 찾았지만, %s 버전과 같지 않습니다." -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "" -"option --exclude-database cannot be used together with -g/--globals-only, -" -"r/--roles-only, or -t/--tablespaces-only" +"option --exclude-database cannot be used together with -g/--globals-only, " +"-r/--roles-only, or -t/--tablespaces-only" msgstr "" "--exclude-database 옵션은 -g/--globals-only, -r/--roles-only, 또는 -t/--" "tablespaces-only 옵션과 함께 쓸 수 없음" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "-g/--globals-only 옵션과 -r/--roles-only 옵션은 함께 사용할 수 없음" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "" "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "" "-g/--globals-only 옵션과 -t/--tablespaces-only 옵션은 함께 사용할 수 없음" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "" "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "" "-r/--roles-only 옵션과 -t/--tablespaces-only 옵션은 함께 사용할 수 없음" -#: pg_dumpall.c:469 pg_dumpall.c:1750 +#: pg_dumpall.c:474 pg_dumpall.c:1771 #, c-format msgid "could not connect to database \"%s\"" msgstr "\"%s\" 데이터베이스에 접속할 수 없음" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2503,7 +2654,7 @@ msgstr "" "\"postgres\" 또는 \"template1\" 데이터베이스에 연결할 수 없습니다.\n" "다른 데이터베이스를 지정하십시오." -#: pg_dumpall.c:629 +#: pg_dumpall.c:634 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2513,35 +2664,35 @@ msgstr "" "추출하는 프로그램입니다.\n" "\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:636 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [옵션]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:639 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=파일이름 출력 파일 이름\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:646 #, c-format msgid "" " -c, --clean clean (drop) databases before recreating\n" msgstr "" " -c, --clean 다시 만들기 전에 데이터베이스 지우기(삭제)\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:648 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr "" " -g, --globals-only 데이터베이스는 제외하고 글로벌 개체만 덤프\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:649 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner 개체 소유권 복원 건너뛰기\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:650 #, c-format msgid "" " -r, --roles-only dump only roles, no databases or tablespaces\n" @@ -2549,12 +2700,12 @@ msgstr "" " -r, --roles-only 데이터베이스나 테이블스페이스는 제외하고 역할" "만 덤프\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:652 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr " -S, --superuser=NAME 덤프에 사용할 슈퍼유저 사용자 이름\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:653 #, c-format msgid "" " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" @@ -2562,7 +2713,7 @@ msgstr "" " -t, --tablespaces-only 데이터베이스나 역할은 제외하고 테이블스페이스" "만 덤프\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:659 #, c-format msgid "" " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" @@ -2571,20 +2722,27 @@ msgstr "" #: pg_dumpall.c:661 #, c-format +msgid "" +" --filter=FILENAME exclude databases based on expressions in " +"FILENAME\n" +msgstr " --filter=FILENAME 필터 조건이 정의 파일을 사용하여 덤프\n" + +#: pg_dumpall.c:667 +#, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords 롤용 비밀번호를 덤프하지 않음\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:683 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=접속문자열 서버 접속 문자열\n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:685 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=DBNAME 대체용 기본 데이터베이스\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:692 #, c-format msgid "" "\n" @@ -2598,99 +2756,111 @@ msgstr "" "출력에 쓰여집니다.\n" "\n" -#: pg_dumpall.c:828 +#: pg_dumpall.c:837 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "롤 이름이 \"pg_\"로 시작함, 무시함: (%s)" -#: pg_dumpall.c:1050 +#: pg_dumpall.c:1059 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "\"%s\" 롤은 덤프할 수 있는 롤을 포함하고 있지 않습니다" -#: pg_dumpall.c:1185 +#: pg_dumpall.c:1194 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "ACL 목록 (%s)을 분석할 수 없음, 해당 매개변수 \"%s\"" -#: pg_dumpall.c:1303 +#: pg_dumpall.c:1321 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "테이블스페이스 용 ACL 목록 (%s)을 분석할 수 없음, 해당개체 \"%s\"" -#: pg_dumpall.c:1510 +#: pg_dumpall.c:1528 #, c-format msgid "excluding database \"%s\"" msgstr "\"%s\" 데이터베이스를 제외하는 중" -#: pg_dumpall.c:1514 +#: pg_dumpall.c:1532 #, c-format msgid "dumping database \"%s\"" msgstr "\"%s\" 데이터베이스 덤프 중" -#: pg_dumpall.c:1545 +#: pg_dumpall.c:1563 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "\"%s\" 데이터베이스에서 pg_dump 작업 중에 오류가 발생, 끝냅니다." -#: pg_dumpall.c:1551 +#: pg_dumpall.c:1569 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "\"%s\" 출력 파일을 다시 열 수 없음: %m" -#: pg_dumpall.c:1592 +#: pg_dumpall.c:1613 #, c-format msgid "running \"%s\"" msgstr "\"%s\" 가동중" -#: pg_dumpall.c:1793 +#: pg_dumpall.c:1814 #, c-format msgid "could not get server version" msgstr "서버 버전을 알 수 없음" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1817 #, c-format msgid "could not parse server version \"%s\"" msgstr "\"%s\" 서버 버전을 분석할 수 없음" -#: pg_dumpall.c:1866 pg_dumpall.c:1889 +#: pg_dumpall.c:1887 pg_dumpall.c:1910 #, c-format msgid "executing %s" msgstr "실행중: %s" -#: pg_restore.c:313 +#: pg_dumpall.c:1982 +msgid "unsupported filter object" +msgstr "지원하지 않는 필터 객체" + +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "-d/--dbname 옵션 또는 -f/--file 옵션 중 하나를 지정해야 함" -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "-d/--dbname 옵션과 -f/--file 옵션은 함께 사용할 수 없음" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "" +"options -1/--single-transaction and --transaction-size cannot be used " +"together" +msgstr "" +"-1/--single-transaction 옵션과 --transaction-size 옵션은 함께 사용할 수 없음" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "-C/--clean 옵션과 -1/--single-transaction 옵션은 함께 사용할 수 없음" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "--single-transaction 및 병렬 작업을 함께 지정할 수는 없음" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "" "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "" "알 수 없는 아카이브 형식: \"%s\"; 사용할 수 있는 값: \"c\", \"d\", \"t\"" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "복원작업에서의 오류들이 무시되었음: %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2700,47 +2870,47 @@ msgstr "" "그 자료를 일괄 입력합니다.\n" "\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [옵션]... [파일]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NAME 접속할 데이터베이스 이름\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FILENAME 출력 파일 이름 (표준 출력: -)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t 백업 파일 형식 (지정하지 않으면 자동분석)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list 자료의 요약된 목차를 보여줌\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose 자세한 정보 보여줌\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "" "\n" @@ -2749,33 +2919,33 @@ msgstr "" "\n" "리스토어 처리를 위한 옵션들:\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only 스키마는 빼고 자료만 입력함\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create 작업 대상 데이터베이스를 만듦\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr "" " -e, --exit-on-error 오류가 생기면 끝냄, 기본은 계속 진행함\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAME 지정한 인덱스 만듦\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM 여러 병렬 작업을 사용하여 복원\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2784,27 +2954,27 @@ msgstr "" " -L, --use-list=FILENAME 출력을 선택하고 해당 순서를 지정하기 위해\n" " 이 파일의 목차 사용\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME 해당 스키마의 개체들만 복원함\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NAME 해당 스키마의 개체들은 복원 안함\n" -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NAME(args) 지정한 함수 만듦\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only 자료구조(스키마)만 만듦\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid "" " -S, --superuser=NAME superuser user name to use for disabling " @@ -2813,40 +2983,48 @@ msgstr "" " -S, --superuser=NAME 트리거를 사용하지 않기 위해 사용할 슈퍼유저\n" " 사용자 이름\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid "" " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NAME 복원할 객체 이름 (테이블, 뷰, 기타)\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAME 지정한 트리거 만듦\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid "" " -x, --no-privileges skip restoration of access privileges (grant/" "revoke)\n" msgstr " -x, --no-privileges 접근 권한(grant/revoke) 지정 안함\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction 하나의 트랜잭션 작업으로 복원함\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security 로우 보안 활성화\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid "" +" --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr "" +" --filter=FILENAME 지정한 파일의 필터 조건으로 객체를 복원함\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments 코멘트는 복원하지 않음\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not " @@ -2856,32 +3034,32 @@ msgstr "" " --no-data-for-failed-tables 만들 수 없는 테이블에 대해서는 자료를 덤프하" "지 않음\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications 발행 정보는 복원 안함\n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels 보안 라벨을 복원하지 않음\n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions 구독 정보는 복원 안함\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method 테이블 접근 방법 복원 안함\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces 테이블스페이스 할당을 복원하지 않음\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid "" " --section=SECTION restore named section (pre-data, data, or " @@ -2890,12 +3068,17 @@ msgstr "" " --section=SECTION 지정한 섹션만 복원함\n" " 섹션 종류: pre-data, data, post-data\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr " --transaction-size=N N 개의 객체 다음에는 항상 commit\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME 복원 전에 SET ROLE 수행\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "" "\n" @@ -2908,7 +3091,7 @@ msgstr "" "기\n" "위해서 여러번 사용할 수 있습니다.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "" "\n" @@ -2919,6 +3102,22 @@ msgstr "" "사용할 입력 파일을 지정하지 않았다면, 표준 입력(stdin)을 사용합니다.\n" "\n" +#, c-format +#~ msgid "" +#~ "query produced null referenced table name for foreign key trigger \"%s\" " +#~ "on table \"%s\" (OID of table: %u)" +#~ msgstr "" +#~ "쿼리가 참조테이블 정보가 없는 \"%s\" 참조키 트리거를 \"%s\" (해당 OID: " +#~ "%u) 테이블에서 만들었습니다." + +#, c-format +#~ msgid "unexpected tgtype value: %d" +#~ msgstr "기대되지 않은 tgtype 값: %d" + +#, c-format +#~ msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +#~ msgstr "잘못된 인수 문자열 (%s), 해당 트리거 \"%s\", 사용되는 테이블 \"%s\"" + #, c-format #~ msgid " %s" #~ msgstr " %s" diff --git a/src/bin/pg_dump/po/meson.build b/src/bin/pg_dump/po/meson.build index cb4267d613305..7e350c5b819a5 100644 --- a/src/bin/pg_dump/po/meson.build +++ b/src/bin/pg_dump/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_dump-' + pg_version_major.to_string())] diff --git a/src/bin/pg_dump/po/ru.po b/src/bin/pg_dump/po/ru.po index a0a5496656cd8..f0297f30d1455 100644 --- a/src/bin/pg_dump/po/ru.po +++ b/src/bin/pg_dump/po/ru.po @@ -5,13 +5,13 @@ # Oleg Bartunov , 2004. # Sergey Burladyan , 2012. # Dmitriy Olshevskiy , 2014. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_dump (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2023-08-30 14:18+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-07 07:35+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -97,32 +97,47 @@ msgstr "для алгоритма сжатия \"%s\" нельзя задать msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "алгоритм сжатия \"%s\" не поддерживает режим большой дистанции" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "нехватка памяти" @@ -137,6 +152,49 @@ msgstr "нехватка памяти\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -165,7 +223,7 @@ msgstr "дочерний процесс завершён по сигналу %d: #: ../../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" -msgstr "дочерний процесс завершился с нераспознанным состоянием %d" +msgstr "дочерний процесс завершился с нераспознанным кодом состояния %d" #: ../../fe_utils/option_utils.c:69 #, c-format @@ -177,229 +235,252 @@ msgstr "неверное значение \"%s\" для параметра %s" msgid "%s must be in range %d..%d" msgstr "значение %s должно быть в диапазоне %d..%d" -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "чтение расширений" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "выявление членов расширений" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "чтение схем" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "чтение пользовательских таблиц" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "чтение пользовательских функций" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "чтение пользовательских типов" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "чтение процедурных языков" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "чтение пользовательских агрегатных функций" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "чтение пользовательских операторов" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "чтение пользовательских методов доступа" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "чтение пользовательских классов операторов" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "чтение пользовательских семейств операторов" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "чтение пользовательских анализаторов текстового поиска" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "чтение пользовательских шаблонов текстового поиска" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "чтение пользовательских словарей текстового поиска" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "чтение пользовательских конфигураций текстового поиска" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "чтение пользовательских оболочек сторонних данных" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "чтение пользовательских сторонних серверов" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "чтение прав по умолчанию" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "чтение пользовательских правил сортировки" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "чтение пользовательских преобразований" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "чтение приведений типов" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "чтение преобразований" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "чтение информации о наследовании таблиц" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "чтение событийных триггеров" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "поиск таблиц расширений" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "поиск связей наследования" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "чтение информации о столбцах интересующих таблиц" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "пометка наследованных столбцов в подтаблицах" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "чтение информации о секционировании" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "чтение индексов" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "пометка индексов в секционированных таблицах" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "чтение расширенной статистики" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "чтение ограничений" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "чтение триггеров" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "чтение правил перезаписи" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "чтение политик" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "чтение публикаций" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "чтение информации о таблицах, включённых в публикации" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "чтение информации о схемах, включённых в публикации" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "чтение подписок" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "чтение информации о таблицах, включённых в подписки" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "" "нарушение целостности: родительская таблица с OID %u для таблицы \"%s\" (OID " "%u) не найдена" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "неверное число родителей (%d) для таблицы \"%s\"" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "не удалось разобрать числовой массив \"%s\": слишком много чисел" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "не удалось разобрать числовой массив \"%s\": неверный символ в числе" @@ -429,15 +510,20 @@ msgstr "не удалось распаковать данные: %s" msgid "could not close compression library: %s" msgstr "не удалось закрыть библиотеку сжатия: %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "не удалось прочитать входной файл: %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:374 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "не удалось прочитать входной файл: %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:372 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "не удалось прочитать входной файл: конец файла" @@ -477,27 +563,74 @@ msgstr "не удалось завершить распаковку: %s" msgid "could not set compression parameter \"%s\": %s" msgstr "не удалось задать параметр сжатия \"%s\": %s" -#: compress_zstd.c:78 compress_zstd.c:231 compress_zstd.c:490 -#: compress_zstd.c:498 +#: compress_zstd.c:78 compress_zstd.c:232 compress_zstd.c:491 +#: compress_zstd.c:499 #, c-format msgid "could not initialize compression library" msgstr "не удалось инициализировать библиотеку сжатия" -#: compress_zstd.c:194 compress_zstd.c:308 +#: compress_zstd.c:195 compress_zstd.c:309 #, c-format msgid "could not decompress data: %s" msgstr "не удалось распаковать данные: %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "не удалось прочитать входной файл: %m" - -#: compress_zstd.c:501 +#: compress_zstd.c:502 #, c-format msgid "unhandled mode \"%s\"" msgstr "необрабатываемый режим \"%s\"" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "не удалось открыть файл фильтра \"%s\": %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "не удалось закрыть файл фильтра \"%s\": %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "" +"неверный формат в фильтре, прочитанном из стандартного ввода, в строке %d: %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "" +"неверный формат в фильтре, прочитанном из файла \"%s\", в строке %d: %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "не удалось прочитать файл фильтра \"%s\": %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "неожиданный конец файла" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "отсутствует шаблон имени объекта" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "отсутствует команда фильтра (ожидалась \"include\" или \"exclude\")" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "неверная команда фильтра (ожидалась \"include\" или \"exclude\")" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "отсутствует тип объекта фильтра" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "неподдерживаемый тип объекта фильтра: \"%.*s\"" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -581,112 +714,112 @@ msgstr "pgpipe: не удалось подключить сокет (код ош msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: не удалось принять соединение (код ошибки: %d)" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "не удалось закрыть выходной файл: %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "в последовательности элементов архива нарушен порядок разделов" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "неожиданный код раздела %d" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "" "параллельное восстановление не поддерживается с выбранным форматом архивного " "файла" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "" "параллельное восстановление возможно только для архивов, созданных pg_dump " "версии 8.0 и новее" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "восстановить данные из сжатого архива нельзя (%s)" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "подключение к базе данных для восстановления" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "" "прямые подключения к базе данных не поддерживаются в архивах до версии 1.3" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "подразумевается восстановление только данных" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "удаляется %s %s" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "не удалось определить, куда добавить IF EXISTS в оператор \"%s\"" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "предупреждение из исходного файла: %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "создаётся %s \"%s.%s\"" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "создаётся %s \"%s\"" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "подключение к новой базе данных \"%s\"" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "обрабатывается %s" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "обрабатываются данные таблицы \"%s.%s\"" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "выполняется %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "отключаются триггеры таблицы %s" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "включаются триггеры таблицы %s" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "" "internal error -- WriteData cannot be called outside the context of a " @@ -695,12 +828,12 @@ msgstr "" "внутренняя ошибка -- WriteData нельзя вызывать вне контекста процедуры " "DataDumper" -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "выбранный формат не поддерживает выгрузку больших объектов" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" @@ -708,55 +841,55 @@ msgstr[0] "восстановлен %d большой объект" msgstr[1] "восстановлено %d больших объекта" msgstr[2] "восстановлено %d больших объектов" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "восстановление большого объекта с OID %u" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "не удалось создать большой объект %u: %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3740 +#: pg_backup_archiver.c:1486 pg_dump.c:3888 #, c-format msgid "could not open large object %u: %s" msgstr "не удалось открыть большой объект %u: %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "не удалось открыть файл оглавления \"%s\": %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "строка проигнорирована: %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "не найдена запись для ID %d" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "не удалось закрыть файл оглавления: %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "не удалось открыть выходной файл \"%s\": %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "не удалось открыть выходной файл: %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" @@ -764,216 +897,221 @@ msgstr[0] "записан %zu байт данных большого объек msgstr[1] "записано %zu байта данных большого объекта (результат = %d)" msgstr[2] "записано %zu байт данных большого объекта (результат = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "не удалось записать данные в большой объект: %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "при инициализации:" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "при обработке оглавления:" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "при завершении:" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "из записи оглавления %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "неверный dumpId" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "неверный dumpId таблицы в элементе TABLE DATA" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "неожиданный флаг смещения данных: %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "слишком большое смещение в файле выгрузки" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "слишком длинное имя каталога: \"%s\"" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "" "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not " "exist)" msgstr "каталог \"%s\" не похож на архивный (в нём отсутствует \"toc.dat\")" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "не удалось открыть входной файл \"%s\": %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "не удалось открыть входной файл: %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "не удалось прочитать входной файл: %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "входной файл слишком короткий (прочитано байт: %lu, ожидалось: 5)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "" "входной файл, видимо, имеет текстовый формат. Загрузите его с помощью psql." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "входной файл не похож на архив (возможно, слишком мал?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "входной файл не похож на архив" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "не удалось закрыть входной файл: %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "не удалось открыть stdout для добавления вывода: %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "неопознанный формат файла: \"%d\"" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4466 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4647 #, c-format msgid "finished item %d %s %s" msgstr "закончен объект %d %s %s" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4479 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4660 #, c-format msgid "worker process failed: exit code %d" msgstr "рабочий процесс завершился с кодом возврата %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "ID записи %d вне диапазона - возможно повреждено оглавление" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "восстановление таблиц со свойством WITH OIDS больше не поддерживается" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "нераспознанная кодировка \"%s\"" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2823 #, c-format msgid "invalid ENCODING item: %s" msgstr "неверный элемент ENCODING: %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2841 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "неверный элемент STDSTRINGS: %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2866 #, c-format msgid "schema \"%s\" not found" msgstr "схема \"%s\" не найдена" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2873 #, c-format msgid "table \"%s\" not found" msgstr "таблица \"%s\" не найдена" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2880 #, c-format msgid "index \"%s\" not found" msgstr "индекс \"%s\" не найден" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2887 #, c-format msgid "function \"%s\" not found" msgstr "функция \"%s\" не найдена" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2894 #, c-format msgid "trigger \"%s\" not found" msgstr "триггер \"%s\" не найден" -#: pg_backup_archiver.c:3201 +#: pg_backup_archiver.c:3325 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "не удалось переключить пользователя сеанса на \"%s\": %s" -#: pg_backup_archiver.c:3333 +#: pg_backup_archiver.c:3457 +#, c-format +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "не удалось присвоить \"search_path\" значение \"%s\": %s" + +#: pg_backup_archiver.c:3518 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "не удалось присвоить search_path значение \"%s\": %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "не удалось задать для \"default_tablespace\" значение %s: %s" -#: pg_backup_archiver.c:3394 +#: pg_backup_archiver.c:3567 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "не удалось задать для default_tablespace значение %s: %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "не удалось задать \"default_table_access_method\": %s" -#: pg_backup_archiver.c:3443 +#: pg_backup_archiver.c:3616 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "не удалось задать default_table_access_method: %s" +msgid "could not alter table access method: %s" +msgstr "не удалось изменить табличный метод доступа: %s" -#: pg_backup_archiver.c:3548 +#: pg_backup_archiver.c:3717 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "неизвестно, как назначить владельца для объекта типа \"%s\"" -#: pg_backup_archiver.c:3770 +#: pg_backup_archiver.c:4004 #, c-format msgid "did not find magic string in file header" msgstr "в заголовке файла не найдена нужная сигнатура" -#: pg_backup_archiver.c:3784 +#: pg_backup_archiver.c:4018 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "неподдерживаемая версия (%d.%d) в заголовке файла" -#: pg_backup_archiver.c:3789 +#: pg_backup_archiver.c:4023 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "несоответствие размера integer (%lu)" -#: pg_backup_archiver.c:3793 +#: pg_backup_archiver.c:4027 #, c-format msgid "" "archive was made on a machine with larger integers, some operations might " @@ -982,12 +1120,12 @@ msgstr "" "архив был сделан на компьютере большей разрядности -- возможен сбой " "некоторых операций" -#: pg_backup_archiver.c:3803 +#: pg_backup_archiver.c:4037 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "ожидаемый формат (%d) отличается от формата, указанного в файле (%d)" -#: pg_backup_archiver.c:3825 +#: pg_backup_archiver.c:4059 #, c-format msgid "" "archive is compressed, but this installation does not support compression " @@ -996,68 +1134,68 @@ msgstr "" "архив сжат, но установленная версия не поддерживает сжатие (%s) -- данные " "будут недоступны" -#: pg_backup_archiver.c:3861 +#: pg_backup_archiver.c:4095 #, c-format msgid "invalid creation date in header" msgstr "неверная дата создания в заголовке" -#: pg_backup_archiver.c:3995 +#: pg_backup_archiver.c:4229 #, c-format msgid "processing item %d %s %s" msgstr "обработка объекта %d %s %s" -#: pg_backup_archiver.c:4070 +#: pg_backup_archiver.c:4314 #, c-format msgid "entering main parallel loop" msgstr "вход в основной параллельный цикл" -#: pg_backup_archiver.c:4081 +#: pg_backup_archiver.c:4325 #, c-format msgid "skipping item %d %s %s" msgstr "объект %d %s %s пропускается" -#: pg_backup_archiver.c:4090 +#: pg_backup_archiver.c:4334 #, c-format msgid "launching item %d %s %s" msgstr "объект %d %s %s запускается" -#: pg_backup_archiver.c:4144 +#: pg_backup_archiver.c:4388 #, c-format msgid "finished main parallel loop" msgstr "основной параллельный цикл закончен" -#: pg_backup_archiver.c:4180 +#: pg_backup_archiver.c:4424 #, c-format msgid "processing missed item %d %s %s" msgstr "обработка пропущенного объекта %d %s %s" -#: pg_backup_archiver.c:4785 +#: pg_backup_archiver.c:4966 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "создать таблицу \"%s\" не удалось, её данные не будут восстановлены" -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "неверный OID большого объекта" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "ошибка при перемещении в файле: %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "в блоке данных %d задана неверная позиция" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "нераспознанный тип блока данных (%d) при поиске архива" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "" "could not find block ID %d in archive -- possibly due to out-of-order " @@ -1067,54 +1205,54 @@ msgstr "" "последовательного запроса восстановления, который нельзя обработать с " "файлом, не допускающим произвольный доступ" -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "не удалось найти в архиве блок с ID %d -- возможно, архив испорчен" -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "при чтении данных получен неожиданный ID блока (%d) -- ожидался: %d" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "нераспознанный тип блока данных %d при восстановлении архива" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "не удалось определить позицию в файле архива: %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "не удалось закрыть файл архива: %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "повторно открыть можно только входные файлы" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "параллельное восстановление из стандартного ввода не поддерживается" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "" "параллельное восстановление возможно только с файлом произвольного доступа" -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "не удалось задать текущую позицию в файле архива: %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "сжатие активно" @@ -1124,12 +1262,12 @@ msgstr "сжатие активно" msgid "could not get server_version from libpq" msgstr "не удалось получить версию сервера из libpq" -#: pg_backup_db.c:53 pg_dumpall.c:1812 +#: pg_backup_db.c:53 pg_dumpall.c:1830 #, c-format msgid "aborting because of server version mismatch" msgstr "продолжение работы с другой версией сервера невозможно" -#: pg_backup_db.c:54 pg_dumpall.c:1813 +#: pg_backup_db.c:54 pg_dumpall.c:1831 #, c-format msgid "server version: %s; %s version: %s" msgstr "версия сервера: %s; версия %s: %s" @@ -1139,7 +1277,7 @@ msgstr "версия сервера: %s; версия %s: %s" msgid "already connected to a database" msgstr "подключение к базе данных уже установлено" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1659 pg_dumpall.c:1761 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 msgid "Password: " msgstr "Пароль: " @@ -1153,18 +1291,18 @@ msgstr "не удалось переподключиться к базе" msgid "reconnection failed: %s" msgstr "переподключиться не удалось: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1686 pg_dumpall.c:1770 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1875 pg_dumpall.c:1898 +#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 #, c-format msgid "query failed: %s" msgstr "ошибка при выполнении запроса: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1876 pg_dumpall.c:1899 +#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "Query was: %s" msgstr "Выполнялся запрос: %s" @@ -1202,7 +1340,7 @@ msgstr "ошибка в PQputCopyEnd: %s" msgid "COPY failed for table \"%s\": %s" msgstr "сбой команды COPY для таблицы \"%s\": %s" -#: pg_backup_db.c:521 pg_dump.c:2224 +#: pg_backup_db.c:521 pg_dump.c:2283 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "неожиданные лишние результаты получены при COPY для таблицы \"%s\"" @@ -1215,150 +1353,145 @@ msgstr "не удаётся начать транзакцию" msgid "could not commit database transaction" msgstr "не удалось зафиксировать транзакцию" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "выходной каталог не указан" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не удалось прочитать каталог \"%s\": %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не удалось закрыть каталог \"%s\": %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не удалось создать каталог \"%s\": %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "не удалось записать в выходной файл: %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "не удалось закрыть файл данных: %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "не удалось закрыть файл данных \"%s\": %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "" "не удалось открыть для чтения файл оглавления больших объектов \"%s\": %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "неверная строка в файле оглавления больших объектов \"%s\": \"%s\"" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "ошибка чтения файла оглавления больших объектов \"%s\"" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "не удалось закрыть файл оглавления больших объектов \"%s\": %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "не удалось закрыть файл данных LO: %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "не удалось записать в файл оглавления LO: %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" msgstr "не удалось закрыть файл оглавления LO: %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "слишком длинное имя файла: \"%s\"" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "этот формат нельзя прочитать" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "не удалось открыть для записи файл оглавления \"%s\": %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "не удалось открыть для записи файл оглавления: %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "формат архива tar не поддерживает сжатие" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "не удалось открыть для чтения файл оглавления \"%s\": %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "не удалось открыть для чтения файл оглавления: %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "не удалось найти файл \"%s\" в архиве" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "не удалось получить имя для временного файла: %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "недопустимый синтаксис оператора COPY: \"%s\"" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "неверный OID для большого объекта (%u)" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "не удалось закрыть временный файл: %m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "действительная длина файла (%lld) не равна ожидаемой (%lld)" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "в архиве tar не найден заголовок для файла \"%s\"" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "" "restoring data out of order is not supported in this archive format: \"%s\" " @@ -1368,7 +1501,7 @@ msgstr "" "поддерживается: требуется компонент \"%s\", но в файле архива прежде идёт " "\"%s\"." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" @@ -1376,7 +1509,7 @@ msgstr[0] "найден неполный заголовок tar (размер %l msgstr[1] "найден неполный заголовок tar (размер %lu байта)" msgstr[2] "найден неполный заголовок tar (размер %lu байт)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "" "corrupt tar header found in %s (expected %d, computed %d) file position %llu" @@ -1389,10 +1522,10 @@ msgstr "" msgid "unrecognized section name: \"%s\"" msgstr "нераспознанное имя раздела: \"%s\"" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." @@ -1402,41 +1535,41 @@ msgstr "Для дополнительной информации попробу msgid "out of on_exit_nicely slots" msgstr "превышен предел обработчиков штатного выхода" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "параметры -s/--schema-only и -a/--data-only исключают друг друга" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "" "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "" "параметры -s/--schema-only и --include-foreign-data исключают друг друга" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "" "параметр --include-foreign-data не поддерживается при копировании в " "параллельном режиме" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "параметры -c/--clean и -a/--data-only исключают друг друга" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "параметр --if-exists требует указания -c/--clean" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "" "option --on-conflict-do-nothing requires option --inserts, --rows-per-" @@ -1445,49 +1578,49 @@ msgstr "" "параметр --on-conflict-do-nothing требует указания --inserts, --rows-per-" "insert или --column-inserts" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "нераспознанный алгоритм сжатия: \"%s\"" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "неправильное указание сжатия: %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "pg_dump в настоящее время не поддерживает параметр сжатия \"%s\"" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "" "параллельное резервное копирование поддерживается только с форматом " "\"каталог\"" -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "последний системный OID: %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "соответствующие схемы не найдены" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "соответствующие таблицы не найдены" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "соответствующие расширения не найдены" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1496,17 +1629,17 @@ msgstr "" "%s сохраняет резервную копию БД в текстовом файле или другом виде.\n" "\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:635 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [ПАРАМЕТР]... [ИМЯ_БД]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:638 pg_restore.c:455 #, c-format msgid "" "\n" @@ -1515,12 +1648,12 @@ msgstr "" "\n" "Общие параметры:\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=ИМЯ имя выходного файла или каталога\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1530,7 +1663,7 @@ msgstr "" " (пользовательский | каталог | tar |\n" " текстовый (по умолчанию))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr "" @@ -1538,18 +1671,18 @@ msgstr "" "число\n" " заданий\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:640 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose режим подробных сообщений\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:641 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" # well-spelled: ИНФО -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1558,7 +1691,7 @@ msgstr "" " -Z, --compress=МЕТОД[:ДОП_ИНФО]\n" " выполнять сжатие как указано\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:642 #, c-format msgid "" " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" @@ -1566,7 +1699,7 @@ msgstr "" " --lock-wait-timeout=ТАЙМ-АУТ прервать операцию при тайм-ауте блокировки " "таблицы\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:670 #, c-format msgid "" " --no-sync do not wait for changes to be written safely " @@ -1575,12 +1708,17 @@ msgstr "" " --no-sync не ждать надёжного сохранения изменений на " "диске\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" + +#: pg_dump.c:1108 pg_dumpall.c:643 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:644 #, c-format msgid "" "\n" @@ -1589,35 +1727,35 @@ msgstr "" "\n" "Параметры, управляющие выводом:\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:645 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only выгрузить только данные, без схемы\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects выгрузить большие объекты\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr "" " --blobs (устаревшая альтернатива --large-objects)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects исключить из выгрузки большие объекты\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid "" " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr "" " --no-blobs (устаревшая альтернатива --no-large-objects)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid "" " -c, --clean clean (drop) database objects before " @@ -1626,7 +1764,7 @@ msgstr "" " -c, --clean очистить (удалить) объекты БД при " "восстановлении\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid "" " -C, --create include commands to create database in dump\n" @@ -1634,28 +1772,28 @@ msgstr "" " -C, --create добавить в копию команды создания базы " "данных\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr "" " -e, --extension=ШАБЛОН выгрузить только указанное расширение(я)\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:647 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=КОДИРОВКА выгружать данные в заданной кодировке\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=ШАБЛОН выгрузить только указанную схему(ы)\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=ШАБЛОН НЕ выгружать указанную схему(ы)\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1664,12 +1802,12 @@ msgstr "" " -O, --no-owner не восстанавливать владение объектами\n" " при использовании текстового формата\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:651 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr " -s, --schema-only выгрузить только схему, без данных\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid "" " -S, --superuser=NAME superuser user name to use in plain-text " @@ -1678,27 +1816,27 @@ msgstr "" " -S, --superuser=ИМЯ имя пользователя, который будет задействован\n" " при восстановлении из текстового формата\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=ШАБЛОН выгрузить только указанную таблицу(ы)\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=ШАБЛОН НЕ выгружать указанную таблицу(ы)\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:654 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges не выгружать права (назначение/отзыв)\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:655 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade только для утилит обновления БД\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:656 #, c-format msgid "" " --column-inserts dump data as INSERT commands with column " @@ -1707,7 +1845,7 @@ msgstr "" " --column-inserts выгружать данные в виде INSERT с именами " "столбцов\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:657 #, c-format msgid "" " --disable-dollar-quoting disable dollar quoting, use SQL standard " @@ -1716,7 +1854,7 @@ msgstr "" " --disable-dollar-quoting отключить спецстроки с $, выводить строки\n" " по стандарту SQL\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:658 pg_restore.c:483 #, c-format msgid "" " --disable-triggers disable triggers during data-only restore\n" @@ -1724,7 +1862,7 @@ msgstr "" " --disable-triggers отключить триггеры при восстановлении\n" " только данных, без схемы\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid "" " --enable-row-security enable row security (dump only content user " @@ -1735,7 +1873,12 @@ msgstr "" "только\n" " те данные, которые доступны пользователю)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=ШАБЛОН НЕ выгружать указанное расширение(я)\n" + +#: pg_dump.c:1136 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1747,7 +1890,7 @@ msgstr "" " НЕ выгружать указанную таблицу(ы), а также\n" " её секции и дочерние таблицы\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid "" " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" @@ -1755,7 +1898,7 @@ msgstr "" " --exclude-table-data=ШАБЛОН НЕ выгружать данные указанной таблицы " "(таблиц)\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1767,7 +1910,7 @@ msgstr "" "(таблиц),\n" " а также её секций и дочерних таблиц\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:660 #, c-format msgid "" " --extra-float-digits=NUM override default setting for " @@ -1775,13 +1918,24 @@ msgid "" msgstr "" " --extra-float-digits=ЧИСЛО переопределить значение extra_float_digits\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid "" +" --filter=FILENAME include or exclude objects and data from " +"dump\n" +" based on expressions in FILENAME\n" +msgstr "" +" --filter=ИМЯ_ФАЙЛА включать или исключать объекты и данные из\n" +" дампа в соответствии с выражениями в этом " +"файле\n" + +#: pg_dump.c:1146 pg_dumpall.c:662 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr "" " --if-exists применять IF EXISTS при удалении объектов\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1792,7 +1946,7 @@ msgstr "" " включать в копию данные сторонних таблиц с\n" " серверов с именами, подпадающими под ШАБЛОН\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:663 #, c-format msgid "" " --inserts dump data as INSERT commands, rather than " @@ -1801,57 +1955,57 @@ msgstr "" " --inserts выгрузить данные в виде команд INSERT, не " "COPY\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:664 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr "" " --load-via-partition-root загружать секции через главную таблицу\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:665 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments не выгружать комментарии\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:666 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications не выгружать публикации\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:668 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr "" " --no-security-labels не выгружать назначения меток безопасности\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:669 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions не выгружать подписки\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:671 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method не выгружать табличные методы доступа\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:672 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr "" " --no-tablespaces не выгружать назначения табличных " "пространств\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:673 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression не выгружать методы сжатия TOAST\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:674 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr "" " --no-unlogged-table-data не выгружать данные нежурналируемых таблиц\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:675 #, c-format msgid "" " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT " @@ -1860,7 +2014,7 @@ msgstr "" " --on-conflict-do-nothing добавлять ON CONFLICT DO NOTHING в команды " "INSERT\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:676 #, c-format msgid "" " --quote-all-identifiers quote all identifiers, even if not key words\n" @@ -1868,7 +2022,7 @@ msgstr "" " --quote-all-identifiers заключать в кавычки все идентификаторы,\n" " а не только ключевые слова\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:677 #, c-format msgid "" " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" @@ -1876,7 +2030,7 @@ msgstr "" " --rows-per-insert=ЧИСЛО число строк в одном INSERT; подразумевает --" "inserts\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid "" " --section=SECTION dump named section (pre-data, data, or post-" @@ -1885,7 +2039,7 @@ msgstr "" " --section=РАЗДЕЛ выгрузить заданный раздел\n" " (pre-data, data или post-data)\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid "" " --serializable-deferrable wait until the dump can run without " @@ -1894,13 +2048,13 @@ msgstr "" " --serializable-deferrable дождаться момента для выгрузки данных без " "аномалий\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr "" " --snapshot=СНИМОК использовать при выгрузке заданный снимок\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid "" " --strict-names require table and/or schema include patterns " @@ -1913,7 +2067,7 @@ msgstr "" "минимум\n" " один объект\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1923,7 +2077,7 @@ msgstr "" "также\n" " её секции и дочерние таблицы\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:678 pg_restore.c:500 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1935,7 +2089,7 @@ msgstr "" " устанавливать владельца, используя команды\n" " SET SESSION AUTHORIZATION вместо ALTER OWNER\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:682 pg_restore.c:504 #, c-format msgid "" "\n" @@ -1944,33 +2098,34 @@ msgstr "" "\n" "Параметры подключения:\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=БД имя базы данных для выгрузки\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:684 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:686 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=ПОРТ номер порта сервера БД\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:687 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=ИМЯ имя пользователя баз данных\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:688 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:689 pg_restore.c:509 #, c-format msgid "" " -W, --password force password prompt (should happen " @@ -1978,12 +2133,12 @@ msgid "" msgstr "" " -W, --password запрашивать пароль всегда (обычно не требуется)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:690 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ИМЯ_РОЛИ выполнить SET ROLE перед выгрузкой\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "" "\n" @@ -1996,22 +2151,22 @@ msgstr "" "PGDATABASE.\n" "\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:694 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:695 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "указана неверная клиентская кодировка \"%s\"" -#: pg_dump.c:1303 +#: pg_dump.c:1352 #, c-format msgid "" "parallel dumps from standby servers are not supported by this server version" @@ -2019,160 +2174,170 @@ msgstr "" "выгрузка дампа в параллельном режиме с ведомых серверов не поддерживается " "данной версией сервера" -#: pg_dump.c:1368 +#: pg_dump.c:1417 #, c-format msgid "invalid output format \"%s\" specified" msgstr "указан неверный формат вывода: \"%s\"" -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1452 +#: pg_dump.c:1458 pg_dump.c:1514 pg_dump.c:1567 pg_dumpall.c:1467 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неверное полное имя (слишком много компонентов): %s" -#: pg_dump.c:1417 +#: pg_dump.c:1466 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "схемы, соответствующие шаблону \"%s\", не найдены" -#: pg_dump.c:1470 +#: pg_dump.c:1519 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "расширения, соответствующие шаблону \"%s\", не найдены" -#: pg_dump.c:1523 +#: pg_dump.c:1572 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "сторонние серверы, соответствующие шаблону \"%s\", не найдены" -#: pg_dump.c:1594 +#: pg_dump.c:1643 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неверное имя отношения (слишком много компонентов): %s" -#: pg_dump.c:1616 +#: pg_dump.c:1665 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "таблицы, соответствующие шаблону \"%s\", не найдены" -#: pg_dump.c:1643 +#: pg_dump.c:1692 #, c-format msgid "You are currently not connected to a database." msgstr "В данный момент вы не подключены к базе данных." -#: pg_dump.c:1646 +#: pg_dump.c:1695 #, c-format msgid "cross-database references are not implemented: %s" msgstr "ссылки между базами не реализованы: %s" -#: pg_dump.c:2099 +#: pg_dump.c:2154 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "выгрузка содержимого таблицы \"%s.%s\"" -#: pg_dump.c:2205 +#: pg_dump.c:2264 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Ошибка выгрузки таблицы \"%s\": сбой в PQgetCopyData()." -#: pg_dump.c:2206 pg_dump.c:2216 +#: pg_dump.c:2265 pg_dump.c:2275 #, c-format msgid "Error message from server: %s" msgstr "Сообщение об ошибке с сервера: %s" # skip-rule: language-mix -#: pg_dump.c:2207 pg_dump.c:2217 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Command was: %s" msgstr "Выполнялась команда: %s" -#: pg_dump.c:2215 +#: pg_dump.c:2274 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Ошибка выгрузки таблицы \"%s\": сбой в PQgetResult()." -#: pg_dump.c:2297 +#: pg_dump.c:2365 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "из таблицы \"%s\" получено неверное количество полей" -#: pg_dump.c:2995 +#: pg_dump.c:3067 #, c-format msgid "saving database definition" msgstr "сохранение определения базы данных" -#: pg_dump.c:3100 +#: pg_dump.c:3176 #, c-format msgid "unrecognized locale provider: %s" msgstr "нераспознанный провайдер локали: %s" -#: pg_dump.c:3451 +#: pg_dump.c:3537 #, c-format msgid "saving encoding = %s" msgstr "сохранение кодировки (%s)" -#: pg_dump.c:3476 +#: pg_dump.c:3562 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "сохранение standard_conforming_strings (%s)" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "сохранение \"standard_conforming_strings = %s\"" -#: pg_dump.c:3515 +#: pg_dump.c:3601 #, c-format msgid "could not parse result of current_schemas()" msgstr "не удалось разобрать результат current_schemas()" -#: pg_dump.c:3534 +#: pg_dump.c:3620 #, c-format -msgid "saving search_path = %s" -msgstr "сохранение search_path = %s" +msgid "saving \"search_path = %s\"" +msgstr "сохранение \"search_path = %s\"" -#: pg_dump.c:3571 +#: pg_dump.c:3656 #, c-format msgid "reading large objects" msgstr "чтение больших объектов" -#: pg_dump.c:3709 +#: pg_dump.c:3877 #, c-format -msgid "saving large objects" -msgstr "сохранение больших объектов" +msgid "saving large objects \"%s\"" +msgstr "сохранение больших объектов \"%s\"" -#: pg_dump.c:3750 +#: pg_dump.c:3898 #, c-format msgid "error reading large object %u: %s" msgstr "ошибка чтения большого объекта %u: %s" -#: pg_dump.c:3856 +#: pg_dump.c:4001 #, c-format msgid "reading row-level security policies" msgstr "чтение политик защиты на уровне строк" -#: pg_dump.c:3997 +#: pg_dump.c:4142 #, c-format msgid "unexpected policy command type: %c" msgstr "нераспознанный тип команды в политике: %c" -#: pg_dump.c:4447 pg_dump.c:4791 pg_dump.c:12022 pg_dump.c:17932 -#: pg_dump.c:17934 pg_dump.c:18555 +#: pg_dump.c:4592 pg_dump.c:5150 pg_dump.c:12364 pg_dump.c:18249 +#: pg_dump.c:18251 pg_dump.c:18873 #, c-format msgid "could not parse %s array" msgstr "не удалось разобрать массив %s" -#: pg_dump.c:4636 +#: pg_dump.c:4806 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "" "подписки не выгружены, так как текущий пользователь не суперпользователь" -#: pg_dump.c:5183 +#: pg_dump.c:5012 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "подписка с OID %u не существует" + +#: pg_dump.c:5019 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "нарушение целостности: таблица с OID %u не найдена" + +#: pg_dump.c:5582 #, c-format msgid "could not find parent extension for %s %s" msgstr "не удалось найти родительское расширение для %s %s" -#: pg_dump.c:5328 +#: pg_dump.c:5727 #, c-format msgid "schema with OID %u does not exist" msgstr "схема с OID %u не существует" -#: pg_dump.c:6810 pg_dump.c:17196 +#: pg_dump.c:7209 pg_dump.c:17620 #, c-format msgid "" "failed sanity check, parent table with OID %u of sequence with OID %u not " @@ -2181,7 +2346,7 @@ msgstr "" "нарушение целостности: по OID %u не удалось найти родительскую таблицу " "последовательности с OID %u" -#: pg_dump.c:6953 +#: pg_dump.c:7354 #, c-format msgid "" "failed sanity check, table OID %u appearing in pg_partitioned_table not found" @@ -2189,18 +2354,18 @@ msgstr "" "нарушение целостности: таблица с OID %u, фигурирующим в " "pg_partitioned_table, не найдена" -#: pg_dump.c:7184 pg_dump.c:7455 pg_dump.c:7926 pg_dump.c:8590 pg_dump.c:8709 -#: pg_dump.c:8857 +#: pg_dump.c:7585 pg_dump.c:7859 pg_dump.c:8306 pg_dump.c:8920 pg_dump.c:9042 +#: pg_dump.c:9190 #, c-format msgid "unrecognized table OID %u" msgstr "нераспознанный OID таблицы %u" -#: pg_dump.c:7188 +#: pg_dump.c:7589 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "неожиданно получены данные индекса для таблицы \"%s\"" -#: pg_dump.c:7687 +#: pg_dump.c:8091 #, c-format msgid "" "failed sanity check, parent table with OID %u of pg_rewrite entry with OID " @@ -2209,41 +2374,32 @@ msgstr "" "нарушение целостности: по OID %u не удалось найти родительскую таблицу для " "записи pg_rewrite с OID %u" -#: pg_dump.c:7978 -#, c-format -msgid "" -"query produced null referenced table name for foreign key trigger \"%s\" on " -"table \"%s\" (OID of table: %u)" -msgstr "" -"запрос выдал NULL вместо имени целевой таблицы для триггера внешнего ключа " -"\"%s\" в таблице \"%s\" (OID целевой таблицы: %u)" - -#: pg_dump.c:8594 +#: pg_dump.c:8924 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "неожиданно получены данные столбцов для таблицы \"%s\"" -#: pg_dump.c:8623 +#: pg_dump.c:8953 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "неверная нумерация столбцов в таблице \"%s\"" -#: pg_dump.c:8671 +#: pg_dump.c:9004 #, c-format msgid "finding table default expressions" msgstr "поиск выражений по умолчанию для таблиц" -#: pg_dump.c:8713 +#: pg_dump.c:9046 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "неверное значение adnum (%d) в таблице \"%s\"" -#: pg_dump.c:8807 +#: pg_dump.c:9140 #, c-format msgid "finding table check constraints" msgstr "поиск ограничений-проверок для таблиц" -#: pg_dump.c:8861 +#: pg_dump.c:9194 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" @@ -2254,54 +2410,59 @@ msgstr[1] "" msgstr[2] "" "ожидалось %d ограничений-проверок для таблицы \"%s\", но найдено: %d" -#: pg_dump.c:8865 +#: pg_dump.c:9198 #, c-format msgid "The system catalogs might be corrupted." msgstr "Возможно, повреждены системные каталоги." -#: pg_dump.c:9555 +#: pg_dump.c:9888 #, c-format msgid "role with OID %u does not exist" msgstr "роль с OID %u не существует" -#: pg_dump.c:9667 pg_dump.c:9696 +#: pg_dump.c:10000 pg_dump.c:10029 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "неподдерживаемая запись в pg_init_privs: %u %u %d" -#: pg_dump.c:10517 +#: pg_dump.c:10576 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "отсутствуют метаданные о больших объектах \"%s\"" + +#: pg_dump.c:10859 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "у типа данных \"%s\" по-видимому неправильный тип типа" # TO REVEIW -#: pg_dump.c:12091 +#: pg_dump.c:12433 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "недопустимое значение provolatile для функции \"%s\"" # TO REVEIW -#: pg_dump.c:12141 pg_dump.c:14023 +#: pg_dump.c:12483 pg_dump.c:14379 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "недопустимое значение proparallel для функции \"%s\"" -#: pg_dump.c:12271 pg_dump.c:12377 pg_dump.c:12384 +#: pg_dump.c:12613 pg_dump.c:12719 pg_dump.c:12726 #, c-format msgid "could not find function definition for function with OID %u" msgstr "не удалось найти определение функции для функции с OID %u" -#: pg_dump.c:12310 +#: pg_dump.c:12652 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "неприемлемое значение в поле pg_cast.castfunc или pg_cast.castmethod" -#: pg_dump.c:12313 +#: pg_dump.c:12655 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "неприемлемое значение в поле pg_cast.castmethod" -#: pg_dump.c:12403 +#: pg_dump.c:12745 #, c-format msgid "" "bogus transform definition, at least one of trffromsql and trftosql should " @@ -2310,62 +2471,63 @@ msgstr "" "неприемлемое определение преобразования (trffromsql или trftosql должно быть " "ненулевым)" -#: pg_dump.c:12420 +#: pg_dump.c:12762 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "неприемлемое значение в поле pg_transform.trffromsql" -#: pg_dump.c:12441 +#: pg_dump.c:12783 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "неприемлемое значение в поле pg_transform.trftosql" -#: pg_dump.c:12586 +#: pg_dump.c:12928 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "постфиксные операторы больше не поддерживаются (оператор \"%s\")" -#: pg_dump.c:12756 +#: pg_dump.c:13098 #, c-format msgid "could not find operator with OID %s" msgstr "оператор с OID %s не найден" -#: pg_dump.c:12824 +#: pg_dump.c:13166 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "неверный тип \"%c\" метода доступа \"%s\"" -#: pg_dump.c:13493 pg_dump.c:13552 +#: pg_dump.c:13840 pg_dump.c:13908 #, c-format msgid "unrecognized collation provider: %s" msgstr "нераспознанный провайдер правил сортировки: %s" -#: pg_dump.c:13502 pg_dump.c:13511 pg_dump.c:13521 pg_dump.c:13536 +#: pg_dump.c:13849 pg_dump.c:13856 pg_dump.c:13867 pg_dump.c:13877 +#: pg_dump.c:13892 #, c-format msgid "invalid collation \"%s\"" msgstr "неверное правило сортировки \"%s\"" -#: pg_dump.c:13942 +#: pg_dump.c:14298 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "нераспознанное значение aggfinalmodify для агрегата \"%s\"" -#: pg_dump.c:13998 +#: pg_dump.c:14354 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "нераспознанное значение aggmfinalmodify для агрегата \"%s\"" -#: pg_dump.c:14715 +#: pg_dump.c:15071 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "нераспознанный тип объекта в определении прав по умолчанию: %d" -#: pg_dump.c:14731 +#: pg_dump.c:15087 #, c-format msgid "could not parse default ACL list (%s)" msgstr "не удалось разобрать список прав по умолчанию (%s)" -#: pg_dump.c:14813 +#: pg_dump.c:15171 #, c-format msgid "" "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" @@ -2373,20 +2535,20 @@ msgstr "" "не удалось разобрать изначальный список ACL (%s) или ACL по умолчанию (%s) " "для объекта \"%s\" (%s)" -#: pg_dump.c:14838 +#: pg_dump.c:15196 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "" "не удалось разобрать список ACL (%s) или ACL по умолчанию (%s) для объекта " "\"%s\" (%s)" -#: pg_dump.c:15379 +#: pg_dump.c:15739 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "" "запрос на получение определения представления \"%s\" не возвратил данные" -#: pg_dump.c:15382 +#: pg_dump.c:15742 #, c-format msgid "" "query to obtain definition of view \"%s\" returned more than one definition" @@ -2394,49 +2556,49 @@ msgstr "" "запрос на получение определения представления \"%s\" возвратил несколько " "определений" -#: pg_dump.c:15389 +#: pg_dump.c:15749 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "определение представления \"%s\" пустое (длина равна нулю)" -#: pg_dump.c:15473 +#: pg_dump.c:15834 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "свойство WITH OIDS больше не поддерживается (таблица \"%s\")" -#: pg_dump.c:16397 +#: pg_dump.c:16821 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "неверный номер столбца %d для таблицы \"%s\"" -#: pg_dump.c:16475 +#: pg_dump.c:16899 #, c-format msgid "could not parse index statistic columns" msgstr "не удалось разобрать столбцы статистики в индексе" -#: pg_dump.c:16477 +#: pg_dump.c:16901 #, c-format msgid "could not parse index statistic values" msgstr "не удалось разобрать значения статистики в индексе" -#: pg_dump.c:16479 +#: pg_dump.c:16903 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "" "столбцы, задающие статистику индекса, не соответствуют значениям по " "количеству" -#: pg_dump.c:16695 +#: pg_dump.c:17118 #, c-format msgid "missing index for constraint \"%s\"" msgstr "отсутствует индекс для ограничения \"%s\"" -#: pg_dump.c:16930 +#: pg_dump.c:17353 #, c-format msgid "unrecognized constraint type: %c" msgstr "нераспознанный тип ограничения: %c" -#: pg_dump.c:17031 pg_dump.c:17260 +#: pg_dump.c:17454 pg_dump.c:17684 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "" @@ -2451,22 +2613,12 @@ msgstr[2] "" "запрос на получение данных последовательности \"%s\" вернул %d строк " "(ожидалась 1)" -#: pg_dump.c:17063 +#: pg_dump.c:17486 #, c-format msgid "unrecognized sequence type: %s" msgstr "нераспознанный тип последовательности: %s" -#: pg_dump.c:17352 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "неожиданное значение tgtype: %d" - -#: pg_dump.c:17424 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "неверная строка аргументов (%s) для триггера \"%s\" таблицы \"%s\"" - -#: pg_dump.c:17693 +#: pg_dump.c:18001 #, c-format msgid "" "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows " @@ -2475,47 +2627,53 @@ msgstr "" "запрос на получение правила \"%s\" для таблицы \"%s\" возвратил неверное " "число строк" -#: pg_dump.c:17846 +#: pg_dump.c:18154 #, c-format msgid "could not find referenced extension %u" msgstr "не удалось найти упомянутое расширение %u" -#: pg_dump.c:17936 +#: pg_dump.c:18253 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "конфигурации расширения не соответствуют условиям по количеству" -#: pg_dump.c:18068 +#: pg_dump.c:18385 #, c-format msgid "reading dependency data" msgstr "чтение информации о зависимостях" -#: pg_dump.c:18154 +#: pg_dump.c:18471 #, c-format msgid "no referencing object %u %u" msgstr "нет подчинённого объекта %u %u" -#: pg_dump.c:18165 +#: pg_dump.c:18482 #, c-format msgid "no referenced object %u %u" msgstr "нет вышестоящего объекта %u %u" -#: pg_dump_sort.c:422 +#: pg_dump.c:18907 pg_dump.c:18945 pg_dumpall.c:1962 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "фильтр %s для \"%s\" не допускается" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "неверный dumpId %d" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "неверная зависимость %d" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "не удалось определить цикл зависимостей" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" @@ -2523,7 +2681,7 @@ msgstr[0] "в следующей таблице зациклены ограни msgstr[1] "в следующих таблицах зациклены ограничения внешних ключей:" msgstr[2] "в следующих таблицах зациклены ограничения внешних ключей:" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "" "You might not be able to restore the dump without using --disable-triggers " @@ -2532,7 +2690,7 @@ msgstr "" "Возможно, для восстановления базы потребуется использовать --disable-" "triggers или временно удалить ограничения." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "" "Consider using a full dump instead of a --data-only dump to avoid this " @@ -2541,26 +2699,26 @@ msgstr "" "Во избежание этой проблемы, вероятно, стоит выгружать всю базу данных, а не " "только данные (--data-only)." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "не удалось разрешить цикл зависимостей для следующих объектов:" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " "\"%s\"" msgstr "программа \"%s\" нужна для %s, но она не найдена в каталоге \"%s\"" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "программа \"%s\" найдена программой \"%s\", но её версия отличается от " "версии %s" -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "" "option --exclude-database cannot be used together with -g/--globals-only, -" @@ -2569,30 +2727,30 @@ msgstr "" "параметр --exclude-database несовместим с -g/--globals-only, -r/--roles-only " "и -t/--tablespaces-only" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "параметры -g/--globals-only и -r/--roles-only исключают друг друга" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "" "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "" "параметры -g/--globals-only и -t/--tablespaces-only исключают друг друга" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "" "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "параметры -r/--roles-only и -t/--tablespaces-only исключают друг друга" -#: pg_dumpall.c:469 pg_dumpall.c:1753 +#: pg_dumpall.c:474 pg_dumpall.c:1771 #, c-format msgid "could not connect to database \"%s\"" msgstr "не удалось подключиться к базе данных: \"%s\"" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2601,7 +2759,7 @@ msgstr "" "не удалось подключиться к базе данных \"postgres\" или \"template1\"\n" "Укажите другую базу данных." -#: pg_dumpall.c:629 +#: pg_dumpall.c:634 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2610,17 +2768,17 @@ msgstr "" "%s экспортирует всё содержимое кластера баз данных PostgreSQL в SQL-скрипт.\n" "\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:636 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [ПАРАМЕТР]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:639 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=ИМЯ_ФАЙЛА имя выходного файла\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:646 #, c-format msgid "" " -c, --clean clean (drop) databases before recreating\n" @@ -2628,18 +2786,18 @@ msgstr "" " -c, --clean очистить (удалить) базы данных перед\n" " восстановлением\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:648 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr "" " -g, --globals-only выгрузить только глобальные объекты, без баз\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:649 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner не восстанавливать владение объектами\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:650 #, c-format msgid "" " -r, --roles-only dump only roles, no databases or tablespaces\n" @@ -2647,13 +2805,13 @@ msgstr "" " -r, --roles-only выгрузить только роли, без баз данных\n" " и табличных пространств\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:652 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr "" " -S, --superuser=ИМЯ имя пользователя для выполнения выгрузки\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:653 #, c-format msgid "" " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" @@ -2661,7 +2819,7 @@ msgstr "" " -t, --tablespaces-only выгружать только табличные пространства,\n" " без баз данных и ролей\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:659 #, c-format msgid "" " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" @@ -2671,20 +2829,29 @@ msgstr "" #: pg_dumpall.c:661 #, c-format +msgid "" +" --filter=FILENAME exclude databases based on expressions in " +"FILENAME\n" +msgstr "" +" --filter=ИМЯ_ФАЙЛА исключать базы данных в соответствии с\n" +" выражениями в этом файле\n" + +#: pg_dumpall.c:667 +#, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords не выгружать пароли ролей\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:683 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=СТРОКА подключиться с данной строкой подключения\n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:685 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=ИМЯ_БД выбор другой базы данных по умолчанию\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:692 #, c-format msgid "" "\n" @@ -2698,102 +2865,114 @@ msgstr "" "вывод.\n" "\n" -#: pg_dumpall.c:831 +#: pg_dumpall.c:837 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "имя роли, начинающееся с \"pg_\", пропущено (%s)" -#: pg_dumpall.c:1053 +#: pg_dumpall.c:1059 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "не удалось найти подходящий порядок выгрузки для членов роли \"%s\"" -#: pg_dumpall.c:1188 +#: pg_dumpall.c:1194 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "не удалось разобрать список ACL (%s) для параметра \"%s\"" -#: pg_dumpall.c:1306 +#: pg_dumpall.c:1321 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "" "не удалось разобрать список управления доступом (%s) для табл. пространства " "\"%s\"" -#: pg_dumpall.c:1513 +#: pg_dumpall.c:1528 #, c-format msgid "excluding database \"%s\"" msgstr "база данных \"%s\" исключается" -#: pg_dumpall.c:1517 +#: pg_dumpall.c:1532 #, c-format msgid "dumping database \"%s\"" msgstr "выгрузка базы данных \"%s\"" -#: pg_dumpall.c:1548 +#: pg_dumpall.c:1563 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "ошибка при обработке базы \"%s\", pg_dump завершается" -#: pg_dumpall.c:1554 +#: pg_dumpall.c:1569 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "не удалось повторно открыть выходной файл \"%s\": %m" -#: pg_dumpall.c:1595 +#: pg_dumpall.c:1613 #, c-format msgid "running \"%s\"" msgstr "выполняется \"%s\"" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1814 #, c-format msgid "could not get server version" msgstr "не удалось узнать версию сервера" -#: pg_dumpall.c:1799 +#: pg_dumpall.c:1817 #, c-format msgid "could not parse server version \"%s\"" msgstr "не удалось разобрать строку версии сервера \"%s\"" -#: pg_dumpall.c:1869 pg_dumpall.c:1892 +#: pg_dumpall.c:1887 pg_dumpall.c:1910 #, c-format msgid "executing %s" msgstr "выполняется %s" +#: pg_dumpall.c:1982 +msgid "unsupported filter object" +msgstr "неподдерживаемый объект фильтра" + # TO REVEIW -#: pg_restore.c:313 +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "необходимо указать -d/--dbname или -f/--file" # TO REVEIW -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "параметры -d/--dbname и -f/--file исключают друг друга" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "" +"options -1/--single-transaction and --transaction-size cannot be used " +"together" +msgstr "" +"параметры -1/--single-transaction и --transaction-size исключают друг друга" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "параметры -C/--create и -1/--single-transaction исключают друг друга" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "параметр --single-transaction допускается только с одним заданием" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "" "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "нераспознанный формат архива \"%s\"; укажите \"c\", \"d\" или \"t\"" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "при восстановлении проигнорировано ошибок: %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2803,49 +2982,49 @@ msgstr "" "pg_dump.\n" "\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [ПАРАМЕТР]... [ФАЙЛ]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=БД подключиться к указанной базе данных\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr "" " -f, --file=ИМЯ_ФАЙЛА имя выходного файла (или - для вывода в stdout)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr "" " -F, --format=c|d|t формат файла (должен определяться автоматически)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list вывести краткое оглавление архива\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose выводить подробные сообщения\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "" "\n" @@ -2854,35 +3033,35 @@ msgstr "" "\n" "Параметры, управляющие восстановлением:\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only восстановить только данные, без схемы\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create создать целевую базу данных\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr "" " -e, --exit-on-error выйти при ошибке (по умолчанию - продолжать)\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=ИМЯ восстановить указанный индекс\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr "" " -j, --jobs=ЧИСЛО распараллелить восстановление на указанное " "число заданий\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2891,13 +3070,13 @@ msgstr "" " -L, --use-list=ИМЯ_ФАЙЛА использовать оглавление из этого файла для\n" " чтения/упорядочивания данных\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr "" " -n, --schema=ИМЯ восстановить объекты только в этой схеме\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr "" @@ -2905,17 +3084,17 @@ msgstr "" # skip-rule: no-space-before-parentheses # well-spelled: арг -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=ИМЯ(арг-ты) восстановить заданную функцию\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only восстановить только схему, без данных\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid "" " -S, --superuser=NAME superuser user name to use for disabling " @@ -2924,7 +3103,7 @@ msgstr "" " -S, --superuser=ИМЯ имя суперпользователя для отключения " "триггеров\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid "" " -t, --table=NAME restore named relation (table, view, etc.)\n" @@ -2932,12 +3111,12 @@ msgstr "" " -t, --table=ИМЯ восстановить заданное отношение (таблицу, " "представление и т. п.)\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=ИМЯ восстановить заданный триггер\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid "" " -x, --no-privileges skip restoration of access privileges (grant/" @@ -2946,23 +3125,32 @@ msgstr "" " -x, --no-privileges не восстанавливать права доступа\n" " (назначение/отзыв)\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr "" " -1, --single-transaction выполнить восстановление в одной транзакции\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security включить защиту на уровне строк\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid "" +" --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr "" +" --filter=ИМЯ_ФАЙЛА восстанавливать или пропускать объекты\n" +" в соответствии с выражениями в этом файле\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments не восстанавливать комментарии\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not " @@ -2972,35 +3160,35 @@ msgstr "" " --no-data-for-failed-tables не восстанавливать данные таблиц, которые\n" " не удалось создать\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications не восстанавливать публикации\n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels не восстанавливать метки безопасности\n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions не восстанавливать подписки\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr "" " --no-table-access-method не восстанавливать табличные методы доступа\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr "" " --no-tablespaces не восстанавливать назначения табл. " "пространств\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid "" " --section=SECTION restore named section (pre-data, data, or " @@ -3009,12 +3197,18 @@ msgstr "" " --section=РАЗДЕЛ восстановить заданный раздел\n" " (pre-data, data или post-data)\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr "" +" --transaction-size=N выполнять COMMIT после каждых N объектов\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ИМЯ_РОЛИ выполнить SET ROLE перед восстановлением\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "" "\n" @@ -3027,7 +3221,7 @@ msgstr "" "указывать\n" "несколько раз для выбора нескольких объектов.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "" "\n" @@ -3039,6 +3233,22 @@ msgstr "" "ввода.\n" "\n" +#, c-format +#~ msgid "" +#~ "query produced null referenced table name for foreign key trigger \"%s\" " +#~ "on table \"%s\" (OID of table: %u)" +#~ msgstr "" +#~ "запрос выдал NULL вместо имени целевой таблицы для триггера внешнего " +#~ "ключа \"%s\" в таблице \"%s\" (OID целевой таблицы: %u)" + +#, c-format +#~ msgid "unexpected tgtype value: %d" +#~ msgstr "неожиданное значение tgtype: %d" + +#, c-format +#~ msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" +#~ msgstr "неверная строка аргументов (%s) для триггера \"%s\" таблицы \"%s\"" + #, c-format #~ msgid "unrecognized collation provider '%c'" #~ msgstr "нераспознанный провайдер правил сортировки '%c'" @@ -3463,9 +3673,6 @@ msgstr "" #~ msgid "could not write to custom output routine\n" #~ msgstr "не удалось вывести данную в пользовательскую процедуру\n" -#~ msgid "unexpected end of file\n" -#~ msgstr "неожиданный конец файла\n" - #~ msgid "could not write byte: %s\n" #~ msgstr "не удалось записать байт: %s\n" diff --git a/src/bin/pg_dump/po/sv.po b/src/bin/pg_dump/po/sv.po index 2d86236c63129..8fbe8b3636b56 100644 --- a/src/bin/pg_dump/po/sv.po +++ b/src/bin/pg_dump/po/sv.po @@ -1,13 +1,13 @@ # Swedish message translation file for pg_dump # Peter Eisentraut , 2001, 2009, 2010. -# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-23 12:51+0000\n" -"PO-Revision-Date: 2023-08-23 15:31+0200\n" +"POT-Creation-Date: 2024-08-27 15:52+0000\n" +"PO-Revision-Date: 2024-08-27 18:32+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -88,32 +88,47 @@ msgstr "komprimeringsalgoritm \"%s\" stöder inte ett arbetarantal" msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "komprimeringsalgoritmen \"%s\" stöder inte långdistansläge" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "slut på minne" @@ -128,6 +143,49 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -168,227 +226,247 @@ msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" msgid "%s must be in range %d..%d" msgstr "%s måste vara i intervallet %d..%d" -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "läser utökningar" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "identifierar utökningsmedlemmar" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "läser scheman" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "läser användardefinierade tabeller" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "läser användardefinierade funktioner" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "läser användardefinierade typer" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "läser procedurspråk" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "läser användardefinierade aggregatfunktioner" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "läser användardefinierade operatorer" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "läser användardefinierade accessmetoder" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "läser användardefinierade operatorklasser" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "läser användardefinierade operator-familjer" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "läser användardefinierade textsöktolkare" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "läser användardefinierade textsökmallar" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "läser användardefinierade textsökordlistor" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "läser användardefinierade textsökkonfigurationer" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "läser användardefinierade främmande data-omvandlare" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "läser användardefinierade främmande servrar" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "läser standardrättigheter" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "läser användardefinierade jämförelser" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "läser användardefinierade konverteringar" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "läser typomvandlingar" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "läser transformer" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "läser information om arv av tabeller" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "läser händelsetriggrar" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "hittar utökningstabeller" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "hittar arvrelationer" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "läser kolumninfo flr intressanta tabeller" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "markerar ärvda kolumner i undertabeller" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "läser partitioneringsdata" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "läser index" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "flaggar index i partitionerade tabeller" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "läser utökad statistik" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "läser integritetsvillkor" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "läser triggrar" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "läser omskrivningsregler" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "läser policys" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "läser publiceringar" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "läser publiceringsmedlemskap för tabeller" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "läser publiceringsmedlemskap för scheman" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "läser prenumerationer" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "läser prenumerationsmedlemskap för tabeller" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "misslyckades med riktighetskontroll, hittade inte förälder-OID %u för tabell \"%s\" (OID %u)" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "ogiltigt antal (%d) föräldrar för tabell \"%s\"" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "kunde inte tolka numerisk array \"%s\": för många nummer" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "kunde inte tolka numerisk array \"%s\": ogiltigt tecken i nummer" @@ -418,15 +496,20 @@ msgstr "kunde inte packa upp data: %s" msgid "could not close compression library: %s" msgstr "kunde inte stänga komprimeringsbiblioteket: %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "kunde inte läsa från infilen: %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:373 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "kunde inte läsa från infilen: %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "kunde inte läsa från infilen: slut på filen" @@ -477,16 +560,61 @@ msgstr "kunde inte initierar komprimeringsbibliotek" msgid "could not decompress data: %s" msgstr "kunde inte dekomprimera data: %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "kunde inte läsa från infilen: %m" - #: compress_zstd.c:501 #, c-format msgid "unhandled mode \"%s\"" msgstr "kan inte hantera läget \"%s\"" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "kunde inte öppna filterfil \"%s\": %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "kunde inte stänga filterfil \"%s\": %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "ogiltigt format i filter som lästs från standard input på rad %d: %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "ogiltigt format i filter som lästs från fil \"%s\" på rad %d: %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "kunde inte läsa från filterfil \"%s\": %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "oväntat slut på fil" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "saknar mall för objektnamn" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "hittade inte filterkommandon (förväntade \"include\" eller \"exclude\")" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "ogiltigt filterkommando (förväntade \"include\" eller \"exclude\")" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "saknas typ på filterobjekt" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "typen för filterobjekt stöd ej: \"%.*s\"" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -567,512 +695,517 @@ msgstr "pgpipe: kunde itne ansluta till uttag (socket): felkod %d" msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: kunde inte acceptera anslutning: felkod %d" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "kunde inte stänga utdatafilen: %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "arkivobjekten är inte i korrekt sektionsordning" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "oväntad sektionskod %d" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "parallell återställning stöds inte med detta arkivformat" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "parallell återställning stöds inte med arkiv som skapats av en pre-8.0 pg_dump" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "kan inte återställa från komprimerat arkiv (%s)" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "kopplar upp mot databas för återställning" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "direkta databasuppkopplingar stöds inte i arkiv från före version 1.3" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "implicerad återställning av enbart data" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "tar bort %s %s" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "kunde inte hitta var IF EXISTS skulle stoppas in i sats \"%s\"" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "varning från orginaldumpfilen: %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "skapar %s \"%s.%s\"" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "skapar %s \"%s\"" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "kopplar upp mot ny databas \"%s\"" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "processar %s" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "processar data för tabell \"%s.%s\"" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "kör %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "stänger av trigger för %s" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "slår på trigger för %s" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "internt fel -- WriteData kan inte anropas utanför kontexten av en DataDumper-rutin" -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "utmatning av stora objekt stöds inte i det valda formatet" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" msgstr[0] "återställde %d stor objekt" msgstr[1] "återställde %d stora objekt" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "återställer stort objekt med OID %u" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "kunde inte skapa stort objekt %u: %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3718 +#: pg_backup_archiver.c:1486 pg_dump.c:3888 #, c-format msgid "could not open large object %u: %s" msgstr "kunde inte öppna stort objekt %u: %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "kunde inte öppna TOC-filen \"%s\": %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "rad ignorerad: %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "kunde inte hitta en post för ID %d" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "kunde inte stänga TOC-filen: %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "kunde inte öppna utdatafilen \"%s\": %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "kunde inte öppna utdatafilen: %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" msgstr[0] "skrev %zu byte data av stort objekt (resultat = %d)" msgstr[1] "skrev %zu bytes data av stort objekt (resultat = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "kunde inte skriva till stort objekt: %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "vid INITIERING:" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "vid HANTERING AV TOC:" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "vid SLUTFÖRANDE:" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "från TOC-post %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "felaktigt dumpId" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "felaktig tabell-dumpId för TABLE DATA-objekt" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "oväntad data-offset-flagga %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "fil-offset i dumpfilen är för stort" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "katalognamn för långt: \"%s\"" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "katalogen \"%s\" verkar inte vara ett giltigt arkiv (\"toc.dat\" finns inte)" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "kunde inte öppna indatafilen \"%s\": %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "kan inte öppna infil: %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "kan inte läsa infilen: %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "indatafilen är för kort (läste %lu, förväntade 5)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "indatafilen verkar vara en dump i textformat. Använd psql." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "indatafilen verkar inte vara ett korrekt arkiv (för kort?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "indatafilen verkar inte vara ett korrekt arkiv" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "kunde inte stänga indatafilen: %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "kunde inte öppna stdout för append: %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "känner inte igen filformat \"%d\"" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4448 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4647 #, c-format msgid "finished item %d %s %s" msgstr "klar med objekt %d %s %s" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4461 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4660 #, c-format msgid "worker process failed: exit code %d" msgstr "arbetsprocess misslyckades: felkod %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "post-ID %d utanför sitt intervall -- kanske en trasig TOC" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "återeställa tabeller med WITH OIDS stöds inte längre" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "okänd teckenkodning \"%s\"" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2823 #, c-format msgid "invalid ENCODING item: %s" msgstr "ogiltigt ENCODING-val: %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2841 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "ogiltigt STDSTRINGS-val: %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2866 #, c-format msgid "schema \"%s\" not found" msgstr "schema \"%s\" hittades inte" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2873 #, c-format msgid "table \"%s\" not found" msgstr "tabell \"%s\" hittades inte" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2880 #, c-format msgid "index \"%s\" not found" msgstr "index \"%s\" hittades inte" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2887 #, c-format msgid "function \"%s\" not found" msgstr "funktion \"%s\" hittades inte" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2894 #, c-format msgid "trigger \"%s\" not found" msgstr "trigger \"%s\" hittades inte" -#: pg_backup_archiver.c:3183 +#: pg_backup_archiver.c:3325 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "kunde inte sätta sessionsanvändare till \"%s\": %s" -#: pg_backup_archiver.c:3315 +#: pg_backup_archiver.c:3457 +#, c-format +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "kunde inte sätta \"search_path\" till \"%s\": %s" + +#: pg_backup_archiver.c:3518 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "kunde inte sätta search_path till \"%s\": %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "kunde inte sätta \"default_tablespace\" till %s: %s" -#: pg_backup_archiver.c:3376 +#: pg_backup_archiver.c:3567 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "kunde inte sätta default_tablespace till %s: %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "kunde inte sätta \"default_table_access_method\": %s" -#: pg_backup_archiver.c:3425 +#: pg_backup_archiver.c:3616 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "kunde inte sätta default_table_access_method: %s" +msgid "could not alter table access method: %s" +msgstr "kunde inte ändra tabellaccessmetod: %s" -#: pg_backup_archiver.c:3530 +#: pg_backup_archiver.c:3717 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "vet inte hur man sätter ägare för objekttyp \"%s\"" -#: pg_backup_archiver.c:3752 +#: pg_backup_archiver.c:4004 #, c-format msgid "did not find magic string in file header" msgstr "kunde inte hitta den magiska strängen i filhuvudet" -#: pg_backup_archiver.c:3766 +#: pg_backup_archiver.c:4018 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "ej supportad version (%d.%d) i filhuvudet" -#: pg_backup_archiver.c:3771 +#: pg_backup_archiver.c:4023 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "riktighetskontroll på heltalsstorlek (%lu) misslyckades" -#: pg_backup_archiver.c:3775 +#: pg_backup_archiver.c:4027 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "arkivet skapades på en maskin med större heltal, en del operationer kan misslyckas" -#: pg_backup_archiver.c:3785 +#: pg_backup_archiver.c:4037 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "förväntat format (%d) skiljer sig från formatet som fanns i filen (%d)" -#: pg_backup_archiver.c:3807 +#: pg_backup_archiver.c:4059 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "arkivet är komprimerat, men denna installation stödjer inte komprimering (%s) -- ingen data kommer kunna läsas" -#: pg_backup_archiver.c:3843 +#: pg_backup_archiver.c:4095 #, c-format msgid "invalid creation date in header" msgstr "ogiltig skapandedatum i huvud" -#: pg_backup_archiver.c:3977 +#: pg_backup_archiver.c:4229 #, c-format msgid "processing item %d %s %s" msgstr "processar objekt %d %s %s" -#: pg_backup_archiver.c:4052 +#: pg_backup_archiver.c:4314 #, c-format msgid "entering main parallel loop" msgstr "går in i parallella huvudloopen" -#: pg_backup_archiver.c:4063 +#: pg_backup_archiver.c:4325 #, c-format msgid "skipping item %d %s %s" msgstr "hoppar över objekt %d %s %s" -#: pg_backup_archiver.c:4072 +#: pg_backup_archiver.c:4334 #, c-format msgid "launching item %d %s %s" msgstr "startar objekt %d %s %s" -#: pg_backup_archiver.c:4126 +#: pg_backup_archiver.c:4388 #, c-format msgid "finished main parallel loop" msgstr "klar med parallella huvudloopen" -#: pg_backup_archiver.c:4162 +#: pg_backup_archiver.c:4424 #, c-format msgid "processing missed item %d %s %s" msgstr "processar saknat objekt %d %s %s" -#: pg_backup_archiver.c:4767 +#: pg_backup_archiver.c:4966 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "tabell \"%s\" kunde inte skapas, dess data kommer ej återställas" -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "ogiltig OID för stort objekt" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "fel vid sökning: %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "datablock %d har fel sökposition" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "känner inte igen datablocktyp (%d) vid genomsökning av arkiv" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "kunde inte hitta block ID %d i arkiv -- kanske på grund av en återställningbegäran i oordning vilket inte kan hanteras då inputfilen inte är sökbar" -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "kunde inte hitta block ID %d i arkiv -- möjligen ett trasigt arkiv" -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "hittade oväntat block-ID (%d) vid läsning av data -- förväntade %d" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "ej igenkänd datablockstyp %d vid återställande av arkiv" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "kunde inte bestämma sökposition i arkivfil: %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "kan inte stänga arkivfilen: %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "kan inte återöppna indataarkiven" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "parallell återställning från standard in stöds inte" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "parallell återställning för en icke sökbar fil stöds inte" -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "kunde inte söka till rätt position i arkivfilen: %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "komprimerare aktiv" @@ -1082,12 +1215,12 @@ msgstr "komprimerare aktiv" msgid "could not get server_version from libpq" msgstr "kunde inte hämta serverversionen från libpq" -#: pg_backup_db.c:53 pg_dumpall.c:1809 +#: pg_backup_db.c:53 pg_dumpall.c:1830 #, c-format msgid "aborting because of server version mismatch" msgstr "avbryter då serverversionerna i matchar" -#: pg_backup_db.c:54 pg_dumpall.c:1810 +#: pg_backup_db.c:54 pg_dumpall.c:1831 #, c-format msgid "server version: %s; %s version: %s" msgstr "server version: %s; %s version: %s" @@ -1097,7 +1230,7 @@ msgstr "server version: %s; %s version: %s" msgid "already connected to a database" msgstr "är redan uppkopplad mot en databas" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1656 pg_dumpall.c:1758 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 msgid "Password: " msgstr "Lösenord: " @@ -1111,18 +1244,18 @@ msgstr "kunde inte ansluta till databasen" msgid "reconnection failed: %s" msgstr "återanslutning misslyckades: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1683 pg_dumpall.c:1767 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1872 pg_dumpall.c:1895 +#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 #, c-format msgid "query failed: %s" msgstr "fråga misslyckades: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1873 pg_dumpall.c:1896 +#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "Query was: %s" msgstr "Frågan var: %s" @@ -1158,7 +1291,7 @@ msgstr "fel returnerat av PQputCopyEnd: %s" msgid "COPY failed for table \"%s\": %s" msgstr "COPY misslyckades för tabell \"%s\": %s" -#: pg_backup_db.c:521 pg_dump.c:2202 +#: pg_backup_db.c:521 pg_dump.c:2283 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "oväntade extraresultat under kopiering (COPY) av tabell \"%s\"" @@ -1171,161 +1304,156 @@ msgstr "kunde inte starta databastransaktionen" msgid "could not commit database transaction" msgstr "kunde inte genomföra databastransaktionen" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "ingen utdatakatalog angiven" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "kunde inte läsa katalog \"%s\": %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "kunde inte stänga katalog \"%s\": %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "kunde inte skapa katalog \"%s\": %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "kunde inte skriva till utdatafil: %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "kan inte stänga datafil: %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "kan inte stänga datafil \"%s\": %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "kunde inte öppna stora objekts TOC-fil \"%s\" för läsning: %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "ogiltig rad i stora objekts TOC-fil \"%s\": \"%s\"" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "fel vid lösning av stora objekts TOC-fil \"%s\"" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "kunde inte stänga stora objekts TOC-fil \"%s\": %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "kan inte stänga LO-datafil: %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "kunde inte skriva till TOC-fil för LO: %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" msgstr "kunde inte stänga TOC-fil för LO: %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "filnamnet är för långt: \"%s\"" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "detta format kan inte läsas" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "kunde inte öppna TOC-filen \"%s\" för utmatning: %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "kunde inte öppna TOC-filen för utmatning: %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "komprimering är stödjs inte av arkivformatet tar" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "kunde inte öppna TOC-fil \"%s\" för läsning: %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "kunde inte öppna TOC-fil för läsning: %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "kunde inte hitta fil \"%s\" i arkiv" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "kunde inte generera temporärt filnamn: %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "oväntad COPY-satssyntax: \"%s\"" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "ogiltig OID för stort objekt (%u)" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "kunde inte stänga temporär fil: %m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "verklig fillängd (%lld) matchar inte det förväntade (%lld)" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "kunde inte hitta filhuvud för fil \"%s\" i tar-arkiv" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." msgstr "dumpa data i oordning stöds inte av detta arkivformat: \"%s\" krävs, men kommer före \"%s\" i denna arkivfil." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" msgstr[0] "inkomplett tar-huvud hittat (%lu byte)" msgstr[1] "inkomplett tar-huvud hittat (%lu bytes)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "trasigt tar-huvud hittat i %s (förväntade %d, beräknad %d) filposition %llu" @@ -1335,10 +1463,10 @@ msgstr "trasigt tar-huvud hittat i %s (förväntade %d, beräknad %d) filpositio msgid "unrecognized section name: \"%s\"" msgstr "okänt sektionsnamn: \"%s\"" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." @@ -1348,82 +1476,82 @@ msgstr "Försök med \"%s --help\" för mer information." msgid "out of on_exit_nicely slots" msgstr "slut på on_exit_nicely-slottar" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "flaggorna \"bara schema\" (-s) och \"bara data\" (-a) kan inte användas tillsammans" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "flaggorna -s/--schema-only och --include-foreign-data kan inte användas tillsammans" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "flaggan --include-foreign-data stöds inte med parallell backup" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "flaggorna \"nollställ\" (-c) och \"bara data\" (-a) kan inte användas tillsammans" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "flaggan --if-exists kräver flaggan -c/--clean" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "flagga --on-conflict-do-nothing kräver --inserts, --rows-per-insert eller --column-inserts" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "okänd komprimeringsalgoritm: \"%s\"" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "ogiltig inställning för komprimering: %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "komprimeringsflaggan \"%s\" stöds inte än av pg_dump" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "parallell backup stöds bara med katalogformat" -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "sista inbyggda OID är %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "hittade inga matchande scheman" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "hittade inga matchande tabeller" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "hittade inga matchande utökningar" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "" "%s dumps a database as a text file or to other formats.\n" @@ -1432,17 +1560,17 @@ msgstr "" "%s dumpar en databas som en textfil eller i andra format.\n" "\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:635 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [FLAGGA]... [DBNAMN]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:638 pg_restore.c:455 #, c-format msgid "" "\n" @@ -1451,12 +1579,12 @@ msgstr "" "\n" "Allmänna flaggor:\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=FILENAME fil eller katalognamn för utdata\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid "" " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" @@ -1465,22 +1593,22 @@ msgstr "" " -F, --format=c|d|t|p utdatans filformat (egen (c), katalog (d), tar (t),\n" " ren text (p) (standard))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM använd så här många parellella job för att dumpa\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:640 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose visa mer information\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:641 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid "" " -Z, --compress=METHOD[:DETAIL]\n" @@ -1489,22 +1617,27 @@ msgstr "" " -Z, --compress=METOD[:DETALJ]\n" " komprimera som angivet\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:642 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=TIMEOUT misslyckas efter att ha väntat i TIMEOUT på tabellås\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:670 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync vänta inte på att ändingar säkert skrivits till disk\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" + +#: pg_dump.c:1108 pg_dumpall.c:643 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:644 #, c-format msgid "" "\n" @@ -1513,62 +1646,62 @@ msgstr "" "\n" "Flaggor som styr utmatning:\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:645 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only dumpa bara data, inte schema\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects inkludera stora objekt i dumpen\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (samma som --large-objects, obsolet)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -B, --no-large-objects exkludera stora objekt i dumpen\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (samma som --no-large-objects, obsolet)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean nollställ (drop) databasobjekt innan återskapande\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr " -C, --create inkludera kommandon för att skapa databasen i dumpen\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=MALL dumpa bara de angivna utökningarna\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:647 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=KODNING dumpa data i teckenkodning KODNING\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=MALL dumpa bara de angivna scheman\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=MALL dumpa INTE de angivna scheman\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid "" " -O, --no-owner skip restoration of object ownership in\n" @@ -1577,52 +1710,52 @@ msgstr "" " -O, --no-owner hoppa över återställande av objektägare i\n" " textformatdumpar\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:651 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr " -s, --schema-only dumpa bara scheman, inte data\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr " -S, --superuser=NAME namn på superuser för textformatdumpar\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=MALL dumpa bara de angivna tabellerna\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=MALL dumpa INTE de angivna tabellerna\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:654 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges dumpa inte rättigheter (grant/revoke)\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:655 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade används bara av uppgraderingsverktyg\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:656 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr " --column-inserts dumpa data som INSERT med kolumnnamn\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:657 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr " --disable-dollar-quoting slå av dollar-citering, använd standard SQL-citering\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:658 pg_restore.c:483 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr " --disable-triggers slå av triggrar vid återställning av enbart data\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid "" " --enable-row-security enable row security (dump only content user has\n" @@ -1631,7 +1764,12 @@ msgstr "" " --enable-row-security slå på radsäkerhet (dumpa bara data användaren\n" " har rätt till)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=MALL dumpa INTE de angivna utökningarna\n" + +#: pg_dump.c:1136 #, c-format msgid "" " --exclude-table-and-children=PATTERN\n" @@ -1642,12 +1780,12 @@ msgstr "" " dumpa INTE angivna tabeller, inklusive\n" " barn och partitionstabeller\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=MALL dumpa INTE data för de angivna tabellerna\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid "" " --exclude-table-data-and-children=PATTERN\n" @@ -1658,17 +1796,27 @@ msgstr "" " dumpa INTE data för angivna tabeller,\n" " inklusive barn och partitionstabeller\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:660 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=NUM övertrumfa standardinställningen för extra_float_digits\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid "" +" --filter=FILENAME include or exclude objects and data from dump\n" +" based on expressions in FILENAME\n" +msgstr "" +" --filter=FILENAMN inkludera eller exkludera objekt och data\n" +" från dump baserat på uttryck i FILNAMN\n" +"\n" + +#: pg_dump.c:1146 pg_dumpall.c:662 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists använd IF EXISTS när objekt droppas\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid "" " --include-foreign-data=PATTERN\n" @@ -1679,87 +1827,87 @@ msgstr "" " inkludera data i främmande tabeller från\n" " främmande servrar som matchar MALL\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:663 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts dumpa data som INSERT, istället för COPY\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:664 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root ladda partitioner via root-tabellen\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:665 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments dumpa inte kommentarer\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:666 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications dumpa inte publiceringar\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:668 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels dumpa inte tilldelning av säkerhetsetiketter\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:669 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions dumpa inte prenumereringar\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:671 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method dumpa inte tabellaccessmetoder\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:672 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces dumpa inte användning av tabellutymmen\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:673 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression dumpa inte komprimeringsmetoder för TOAST\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:674 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data dumpa inte ologgad tabelldata\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:675 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing addera ON CONFLICT DO NOTHING till INSERT-kommandon\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:676 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr " --quote-all-identifiers citera alla identifierar, även om de inte är nyckelord\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:677 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NRADER antal rader per INSERT; implicerar --inserts\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr " --section=SEKTION dumpa namngiven sektion (pre-data, data eller post-data)\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr " --serializable-deferrable wait until the dump can run without anomalies\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT använda namngivet snapshot för att dumpa\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid "" " --strict-names require table and/or schema include patterns to\n" @@ -1768,7 +1916,7 @@ msgstr "" " --strict-names kräv att mallar för tabeller och/eller scheman matchar\n" " minst en sak var\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid "" " --table-and-children=PATTERN dump only the specified table(s), including\n" @@ -1777,7 +1925,7 @@ msgstr "" " --table-and-children=MALL dumpa bara angivna tabell(er), inklusive\n" " barn och partitionstabeller\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:678 pg_restore.c:500 #, c-format msgid "" " --use-set-session-authorization\n" @@ -1788,7 +1936,7 @@ msgstr "" " använd kommandot SET SESSION AUTHORIZATION istället för\n" " kommandot ALTER OWNER för att sätta ägare\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:682 pg_restore.c:504 #, c-format msgid "" "\n" @@ -1797,42 +1945,42 @@ msgstr "" "\n" "Flaggor för anslutning:\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=DBNAMN databasens som skall dumpas\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:684 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:686 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT databasens värdport\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:687 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAMN anslut med datta användarnamn mot databasen\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:688 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga aldrig efter lösenord\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:689 pg_restore.c:509 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password fråga om lösenord (borde ske automatiskt)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:690 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLLNAMN gör SET ROLE innan dumpen\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "" "\n" @@ -1845,535 +1993,537 @@ msgstr "" "PGDATABASE att användas.\n" "\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:694 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapportera fel till <%s>.\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:695 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "ogiltig klientteckenkodning \"%s\" angiven" -#: pg_dump.c:1303 +#: pg_dump.c:1352 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "parallella dumpar från standby-server stöds inte av denna serverversion" -#: pg_dump.c:1368 +#: pg_dump.c:1417 #, c-format msgid "invalid output format \"%s\" specified" msgstr "ogiltigt utdataformat \"%s\" angivet" -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1449 +#: pg_dump.c:1458 pg_dump.c:1514 pg_dump.c:1567 pg_dumpall.c:1467 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "ej korrekt kvalificerat namn (för många namn med punkt): %s" -#: pg_dump.c:1417 +#: pg_dump.c:1466 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "hittade inga matchande scheman för mallen \"%s\"" -#: pg_dump.c:1470 +#: pg_dump.c:1519 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "hittade inga matchande utökningar för mallen \"%s\"" -#: pg_dump.c:1523 +#: pg_dump.c:1572 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "hittade inga matchande främmande servrar för mallen \"%s\"" -#: pg_dump.c:1594 +#: pg_dump.c:1643 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "ej korrekt relationsnamn (för många namn med punkt): %s" -#: pg_dump.c:1616 +#: pg_dump.c:1665 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "hittade inga matchande tabeller för mallen \"%s\"" -#: pg_dump.c:1643 +#: pg_dump.c:1692 #, c-format msgid "You are currently not connected to a database." msgstr "Du är för närvarande inte uppkopplad mot en databas." -#: pg_dump.c:1646 +#: pg_dump.c:1695 #, c-format msgid "cross-database references are not implemented: %s" msgstr "referenser till andra databaser är inte implementerat: %s" -#: pg_dump.c:2077 +#: pg_dump.c:2154 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "dumpar innehållet i tabell \"%s.%s\"" -#: pg_dump.c:2183 +#: pg_dump.c:2264 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Dumpning av innehållet i tabellen \"%s\" misslyckades: PQendcopy() misslyckades." -#: pg_dump.c:2184 pg_dump.c:2194 +#: pg_dump.c:2265 pg_dump.c:2275 #, c-format msgid "Error message from server: %s" msgstr "Felmeddelandet från servern: %s" -#: pg_dump.c:2185 pg_dump.c:2195 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Command was: %s" msgstr "Kommandot var: %s" -#: pg_dump.c:2193 +#: pg_dump.c:2274 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Dumpning av innehållet i tabellen \"%s\" misslyckades: PQgetResult() misslyckades." -#: pg_dump.c:2275 +#: pg_dump.c:2365 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "fel antal fält hämtades för tabell \"%s\"" -#: pg_dump.c:2973 +#: pg_dump.c:3067 #, c-format msgid "saving database definition" msgstr "sparar databasdefinition" -#: pg_dump.c:3078 +#: pg_dump.c:3176 #, c-format msgid "unrecognized locale provider: %s" msgstr "okänd lokalleverantör: %s" -#: pg_dump.c:3429 +#: pg_dump.c:3537 #, c-format msgid "saving encoding = %s" msgstr "sparar kodning = %s" -#: pg_dump.c:3454 +#: pg_dump.c:3562 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "sparar standard_conforming_strings = %s" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "sparar \"standard_conforming_strings = %s\"" -#: pg_dump.c:3493 +#: pg_dump.c:3601 #, c-format msgid "could not parse result of current_schemas()" msgstr "kunde inte parsa resultat från current_schemas()" -#: pg_dump.c:3512 +#: pg_dump.c:3620 #, c-format -msgid "saving search_path = %s" -msgstr "sparar search_path = %s" +msgid "saving \"search_path = %s\"" +msgstr "sparar \"search_path = %s\"" -#: pg_dump.c:3549 +#: pg_dump.c:3656 #, c-format msgid "reading large objects" msgstr "läser stora objekt" -#: pg_dump.c:3687 +#: pg_dump.c:3877 #, c-format -msgid "saving large objects" -msgstr "sparar stora objekt" +msgid "saving large objects \"%s\"" +msgstr "sparar stora objekt \"%s\"" -#: pg_dump.c:3728 +#: pg_dump.c:3898 #, c-format msgid "error reading large object %u: %s" msgstr "fel vid läsning av stort objekt %u: %s" -#: pg_dump.c:3834 +#: pg_dump.c:4001 #, c-format msgid "reading row-level security policies" msgstr "läser säkerhetspolicy på radnivå" -#: pg_dump.c:3975 +#: pg_dump.c:4142 #, c-format msgid "unexpected policy command type: %c" msgstr "oväntad kommandotyp för policy: %c" -#: pg_dump.c:4425 pg_dump.c:4760 pg_dump.c:11984 pg_dump.c:17894 -#: pg_dump.c:17896 pg_dump.c:18517 +#: pg_dump.c:4592 pg_dump.c:5150 pg_dump.c:12362 pg_dump.c:18246 +#: pg_dump.c:18248 pg_dump.c:18870 #, c-format msgid "could not parse %s array" msgstr "kunde inte parsa arrayen %s" -#: pg_dump.c:4613 +#: pg_dump.c:4806 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "prenumerationer har inte dumpats få aktuell användare inte är en superuser" -#: pg_dump.c:5149 +#: pg_dump.c:5012 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "prenumeration med OID %u existerar inte" + +#: pg_dump.c:5019 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "misslyckades med riktighetskontroll, hittade inte tabell med OID %u" + +#: pg_dump.c:5582 #, c-format msgid "could not find parent extension for %s %s" msgstr "kunde inte hitta föräldrautökning för %s %s" -#: pg_dump.c:5294 +#: pg_dump.c:5727 #, c-format msgid "schema with OID %u does not exist" msgstr "schema med OID %u existerar inte" -#: pg_dump.c:6776 pg_dump.c:17158 +#: pg_dump.c:7209 pg_dump.c:17617 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "misslyckades med riktighetskontroll, föräldratabell med OID %u för sekvens med OID %u hittas inte" -#: pg_dump.c:6919 +#: pg_dump.c:7352 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "misslyckades med riktighetskontroll, hittade inte tabell med OID %u i pg_partitioned_table" -#: pg_dump.c:7150 pg_dump.c:7417 pg_dump.c:7888 pg_dump.c:8552 pg_dump.c:8671 -#: pg_dump.c:8819 +#: pg_dump.c:7583 pg_dump.c:7857 pg_dump.c:8304 pg_dump.c:8918 pg_dump.c:9040 +#: pg_dump.c:9188 #, c-format msgid "unrecognized table OID %u" msgstr "okänt tabell-OID %u" -#: pg_dump.c:7154 +#: pg_dump.c:7587 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "oväntat indexdata för tabell \"%s\"" -#: pg_dump.c:7649 +#: pg_dump.c:8089 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "misslyckades med riktighetskontroll, föräldratabell med OID %u för pg_rewrite-rad med OID %u hittades inte" -#: pg_dump.c:7940 -#, c-format -msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" -msgstr "fråga producerade null som refererad tabell för främmande nyckel-trigger \"%s\" i tabell \"%s\" (OID för tabell : %u)" - -#: pg_dump.c:8556 +#: pg_dump.c:8922 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "oväntad kolumndata för tabell \"%s\"" -#: pg_dump.c:8585 +#: pg_dump.c:8951 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "ogiltigt kolumnnumrering i tabell \"%s\"" -#: pg_dump.c:8633 +#: pg_dump.c:9002 #, c-format msgid "finding table default expressions" msgstr "hittar tabellers default-uttryck" -#: pg_dump.c:8675 +#: pg_dump.c:9044 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "felaktigt adnum-värde %d för tabell \"%s\"" -#: pg_dump.c:8769 +#: pg_dump.c:9138 #, c-format msgid "finding table check constraints" msgstr "hittar tabellers check-villkor" -#: pg_dump.c:8823 +#: pg_dump.c:9192 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" msgstr[0] "förväntade %d check-villkor för tabell \"%s\" men hittade %d" msgstr[1] "förväntade %d check-villkor för tabell \"%s\" men hittade %d" -#: pg_dump.c:8827 +#: pg_dump.c:9196 #, c-format msgid "The system catalogs might be corrupted." msgstr "Systemkatalogerna kan vara trasiga." -#: pg_dump.c:9517 +#: pg_dump.c:9886 #, c-format msgid "role with OID %u does not exist" msgstr "roll med OID %u existerar inte" -#: pg_dump.c:9629 pg_dump.c:9658 +#: pg_dump.c:9998 pg_dump.c:10027 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "ogiltig pg_init_privs-post: %u %u %d" -#: pg_dump.c:10479 +#: pg_dump.c:10574 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "saknar metadata för stort objekt \"%s\"" + +#: pg_dump.c:10857 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "typtype för datatyp \"%s\" verkar vara ogiltig" -#: pg_dump.c:12053 +#: pg_dump.c:12431 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "okänt provolatile-värde för funktion \"%s\"" -#: pg_dump.c:12103 pg_dump.c:13985 +#: pg_dump.c:12481 pg_dump.c:14377 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "okänt proparallel-värde för funktion \"%s\"" -#: pg_dump.c:12233 pg_dump.c:12339 pg_dump.c:12346 +#: pg_dump.c:12611 pg_dump.c:12717 pg_dump.c:12724 #, c-format msgid "could not find function definition for function with OID %u" msgstr "kunde inte hitta funktionsdefinitionen för funktion med OID %u" -#: pg_dump.c:12272 +#: pg_dump.c:12650 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "felaktigt värde i fältet pg_cast.castfunc eller pg_cast.castmethod" -#: pg_dump.c:12275 +#: pg_dump.c:12653 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "felaktigt värde i fältet pg_cast.castmethod" -#: pg_dump.c:12365 +#: pg_dump.c:12743 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "felaktig transform-definition, minst en av trffromsql och trftosql måste vara ickenoll" -#: pg_dump.c:12382 +#: pg_dump.c:12760 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "felaktigt värde i fältet pg_transform.trffromsql" -#: pg_dump.c:12403 +#: pg_dump.c:12781 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "felaktigt värde i fältet pg_transform.trftosql" -#: pg_dump.c:12548 +#: pg_dump.c:12926 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "postfix-operatorer stöds inte längre (operator \"%s\")" -#: pg_dump.c:12718 +#: pg_dump.c:13096 #, c-format msgid "could not find operator with OID %s" msgstr "kunde inte hitta en operator med OID %s." -#: pg_dump.c:12786 +#: pg_dump.c:13164 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "ogiltig typ \"%c\" för accessmetod \"%s\"" -#: pg_dump.c:13455 +#: pg_dump.c:13838 pg_dump.c:13906 #, c-format msgid "unrecognized collation provider: %s" msgstr "okänd jämförelseleverantör: %s" -#: pg_dump.c:13464 pg_dump.c:13473 pg_dump.c:13483 pg_dump.c:13498 +#: pg_dump.c:13847 pg_dump.c:13854 pg_dump.c:13865 pg_dump.c:13875 +#: pg_dump.c:13890 #, c-format msgid "invalid collation \"%s\"" msgstr "ogiltig jämförelse \"%s\"" -#: pg_dump.c:13514 -#, c-format -msgid "unrecognized collation provider '%c'" -msgstr "okänd jämförelseleverantör: '%c'" - -#: pg_dump.c:13904 +#: pg_dump.c:14296 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "okänt aggfinalmodify-värde för aggregat \"%s\"" -#: pg_dump.c:13960 +#: pg_dump.c:14352 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "okänt aggmfinalmodify-värde för aggregat \"%s\"" -#: pg_dump.c:14677 +#: pg_dump.c:15069 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "okänd objekttyp i standardrättigheter: %d" -#: pg_dump.c:14693 +#: pg_dump.c:15085 #, c-format msgid "could not parse default ACL list (%s)" msgstr "kunde inte parsa standard-ACL-lista (%s)" -#: pg_dump.c:14775 +#: pg_dump.c:15169 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "kunde inte parsa initial ACL-lista (%s) eller default (%s) för objekt \"%s\" (%s)" -#: pg_dump.c:14800 +#: pg_dump.c:15194 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "kunde inte parsa ACL-lista (%s) eller default (%s) för objekt \"%s\" (%s)" -#: pg_dump.c:15341 +#: pg_dump.c:15737 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "fråga för att hämta definition av vy \"%s\" returnerade ingen data" -#: pg_dump.c:15344 +#: pg_dump.c:15740 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "fråga för att hämta definition av vy \"%s\" returnerade mer än en definition" -#: pg_dump.c:15351 +#: pg_dump.c:15747 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "definition av vy \"%s\" verkar vara tom (längd noll)" -#: pg_dump.c:15435 +#: pg_dump.c:15832 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS stöds inte längre (tabell \"%s\")" -#: pg_dump.c:16359 +#: pg_dump.c:16819 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "ogiltigt kolumnnummer %d för tabell \"%s\"" -#: pg_dump.c:16437 +#: pg_dump.c:16897 #, c-format msgid "could not parse index statistic columns" msgstr "kunde inte parsa kolumn i indexstatistik" -#: pg_dump.c:16439 +#: pg_dump.c:16899 #, c-format msgid "could not parse index statistic values" msgstr "kunde inte parsa värden i indexstatistik" -#: pg_dump.c:16441 +#: pg_dump.c:16901 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "antal kolumner och värden stämmer inte i indexstatistik" -#: pg_dump.c:16657 +#: pg_dump.c:17116 #, c-format msgid "missing index for constraint \"%s\"" msgstr "saknar index för integritetsvillkor \"%s\"" -#: pg_dump.c:16892 +#: pg_dump.c:17351 #, c-format msgid "unrecognized constraint type: %c" msgstr "oväntad integritetsvillkorstyp: %c" -#: pg_dump.c:16993 pg_dump.c:17222 +#: pg_dump.c:17452 pg_dump.c:17681 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" msgstr[0] "fråga för att hämta data för sekvens \"%s\" returnerade %d rad (förväntade 1)" msgstr[1] "fråga för att hämta data för sekvens \"%s\" returnerade %d rader (förväntade 1)" -#: pg_dump.c:17025 +#: pg_dump.c:17484 #, c-format msgid "unrecognized sequence type: %s" msgstr "okänd sekvenstyp: %s" -#: pg_dump.c:17314 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "oväntat tgtype-värde: %d" - -#: pg_dump.c:17386 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "felaktig argumentsträng (%s) för trigger \"%s\" i tabell \"%s\"" - -#: pg_dump.c:17655 +#: pg_dump.c:17998 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "fråga för att hämta regel \"%s\" för tabell \"%s\" misslyckades: fel antal rader returnerades" -#: pg_dump.c:17808 +#: pg_dump.c:18151 #, c-format msgid "could not find referenced extension %u" msgstr "kunde inte hitta refererad utökning %u" -#: pg_dump.c:17898 +#: pg_dump.c:18250 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "antal konfigurationer och villkor stämmer inte för utökning" -#: pg_dump.c:18030 +#: pg_dump.c:18382 #, c-format msgid "reading dependency data" msgstr "läser beroendedata" -#: pg_dump.c:18116 +#: pg_dump.c:18468 #, c-format msgid "no referencing object %u %u" msgstr "inget refererande objekt %u %u" -#: pg_dump.c:18127 +#: pg_dump.c:18479 #, c-format msgid "no referenced object %u %u" msgstr "inget refererat objekt %u %u" -#: pg_dump_sort.c:422 +#: pg_dump.c:18904 pg_dump.c:18942 pg_dumpall.c:1962 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "%s-filter för \"%s\" tillåts inte" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "ogiltigt dumpId %d" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "ogiltigt beroende %d" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "kunde inte fastställa beroendeloop" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" msgstr[0] "det finns cirkulära främmande nyckelberoenden för denna tabell:" msgstr[1] "det finns cirkulära främmande nyckelberoenden för dessa tabeller:" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "Du kan eventiellt inte återställa dumpen utan att använda --disable-triggers eller temporärt droppa vilkoren." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "Överväg att göra en full dump istället för --data-only för att undvika detta problem." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "kunde inte räta ut beroendeloopen för dessa saker:" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "programmet \"%s\" behövs av %s men hittades inte i samma katalog som \"%s\"" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "programmet \"%s\" hittades av \"%s\" men är inte av samma version som %s" -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "flaggan --exclude-database kan inte användas tillsammans med -g/--globals-only, -r/--roles-only eller -t/--tablespaces-only" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "flaggorna \"bara gobala\" (-g) och \"bara roller\" (-r) kan inte användas tillsammans" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "flaggorna \"bara globala\" (-g) och \"bara tabellutrymmen\" (-t) kan inte användas tillsammans" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "flaggorna \"bara roller\" (-r) och \"bara tabellutrymmen\" (-t) kan inte användas tillsammans" -#: pg_dumpall.c:469 pg_dumpall.c:1750 +#: pg_dumpall.c:474 pg_dumpall.c:1771 #, c-format msgid "could not connect to database \"%s\"" msgstr "kunde inte ansluta till databasen \"%s\"" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "" "could not connect to databases \"postgres\" or \"template1\"\n" @@ -2382,7 +2532,7 @@ msgstr "" "kunde inte ansluta till databasen \"postgres\" eller \"template1\"\n" "Ange en annan databas." -#: pg_dumpall.c:629 +#: pg_dumpall.c:634 #, c-format msgid "" "%s extracts a PostgreSQL database cluster into an SQL script file.\n" @@ -2391,67 +2541,72 @@ msgstr "" "%s extraherar ett PostgreSQL databaskluster till en SQL-scriptfil.\n" "\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:636 #, c-format msgid " %s [OPTION]...\n" msgstr " %s [FLAGGA]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:639 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=FILENAME utdatafilnamn\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:646 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean nollställ (drop) databaser innan återskapning\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:648 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr " -g, --globals-only dumpa bara globala objekt, inte databaser\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:649 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner återställ inte objektägare\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:650 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr " -r, --roles-only dumpa endast roller, inte databaser eller tabellutrymmen\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:652 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr " -S, --superuser=NAMN namn på superuser för användning i dumpen\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:653 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr " -t, --tablespaces-only dumpa endasdt tabellutrymmen, inte databaser eller roller\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:659 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr " --exclude-database=MALL uteslut databaser vars namn matchar MALL\n" #: pg_dumpall.c:661 #, c-format +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr " --filter=FILENAMN exkludera databaser givet uttryck i FILENAMN\n" + +#: pg_dumpall.c:667 +#, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords dumpa inte lösenord för roller\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:683 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=ANSLSTR anslut med anslutningssträng\n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:685 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=DBNAMN alternativ standarddatabas\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:692 #, c-format msgid "" "\n" @@ -2463,97 +2618,106 @@ msgstr "" "Om -f/--file inte används så kommer SQL-skriptet skriva till standard ut.\n" "\n" -#: pg_dumpall.c:828 +#: pg_dumpall.c:837 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "rollnamn som startar med \"pg_\" hoppas över (%s)" -#: pg_dumpall.c:1050 +#: pg_dumpall.c:1059 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "kunde inte hitta en korrekt dumpordning för medlemskap i rollen \"%s\"" -#: pg_dumpall.c:1185 +#: pg_dumpall.c:1194 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "kunde inte parsa ACL-listan (%s) för parameter \"%s\"" -#: pg_dumpall.c:1303 +#: pg_dumpall.c:1321 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "kunde inte tolka ACL-listan (%s) för tabellutrymme \"%s\"" -#: pg_dumpall.c:1510 +#: pg_dumpall.c:1528 #, c-format msgid "excluding database \"%s\"" msgstr "utesluter databas \"%s\"" -#: pg_dumpall.c:1514 +#: pg_dumpall.c:1532 #, c-format msgid "dumping database \"%s\"" msgstr "dumpar databas \"%s\"" -#: pg_dumpall.c:1545 +#: pg_dumpall.c:1563 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "pg_dump misslyckades med databas \"%s\", avslutar" -#: pg_dumpall.c:1551 +#: pg_dumpall.c:1569 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "kunde inte öppna om utdatafilen \"%s\": %m" -#: pg_dumpall.c:1592 +#: pg_dumpall.c:1613 #, c-format msgid "running \"%s\"" msgstr "kör \"%s\"" -#: pg_dumpall.c:1793 +#: pg_dumpall.c:1814 #, c-format msgid "could not get server version" msgstr "kunde inte hämta serverversionen" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1817 #, c-format msgid "could not parse server version \"%s\"" msgstr "kunde inte tolka versionsträngen \"%s\"" -#: pg_dumpall.c:1866 pg_dumpall.c:1889 +#: pg_dumpall.c:1887 pg_dumpall.c:1910 #, c-format msgid "executing %s" msgstr "kör: %s" -#: pg_restore.c:313 +#: pg_dumpall.c:1982 +msgid "unsupported filter object" +msgstr "filterobjektet stöds inte" + +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "en av flaggorna -d/--dbname och -f/--file måste anges" -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "flaggorna -d/--dbname och -f/--file kan inte användas ihop" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "options -1/--single-transaction and --transaction-size cannot be used together" +msgstr "flaggorna -1/--single-transaction och --transaction-size kan inte användas tillsammans" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "flaggorna -C/--create och -1/--single-transaction kan inte användas tillsammans" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "kan inte ange både --single-transaction och multipla job" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "okänt arkivformat \"%s\"; vänligen ange \"c\", \"d\" eller \"t\"" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "fel ignorerade vid återställande: %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "" "%s restores a PostgreSQL database from an archive created by pg_dump.\n" @@ -2562,47 +2726,47 @@ msgstr "" "%s återställer en PostgreSQL-databas från ett arkiv skapat av pg_dump.\n" "\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [FLAGGA]... [FIL]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NAMN koppla upp med databasnamn\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FILNAMN utdatafilnamn (- för stdout)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t backupens filformat (bör ske automatiskt)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list skriv ut summerad TOC för arkivet\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose visa mer information\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "" "\n" @@ -2611,32 +2775,32 @@ msgstr "" "\n" "Flaggor som styr återställning:\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only återställ bara data, inte scheman\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create skapa måldatabasen\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error avsluta vid fel, standard är att fortsätta\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAMN återställ namngivet index\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM använda så här många parallella job för återställning\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid "" " -L, --use-list=FILENAME use table of contents from this file for\n" @@ -2645,62 +2809,71 @@ msgstr "" " -L, --use-list=FILNAMN använd innehållsförteckning från denna fil för\n" " att välja/sortera utdata\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAMN återställ enbart objekt i detta schema\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NAMN återställ inte objekt i detta schema\n" -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NAMN(arg) återställ namngiven funktion\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only återställ bara scheman, inte data\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr " -S, --superuser=NAMN namn på superuser för att slå av triggrar\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NAMN återställ namngiven relation (tabell, vy, osv.)\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAMN återställ namngiven trigger\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges återställ inte åtkomsträttigheter (grant/revoke)\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction återställ i en enda transaktion\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security aktivera radsäkerhet\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid "" +" --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr "" +" --filter=FILENAMN återställ eller hoppa över objekt\n" +" baserat på uttryck i FILENAMN\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments återställ inte kommentarer\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid "" " --no-data-for-failed-tables do not restore data of tables that could not be\n" @@ -2709,42 +2882,47 @@ msgstr "" " --no-data-for-failed-tables återställ inte data för tabeller som\n" " inte kunde skapas\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications återställ inte publiceringar\n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels återställ inte säkerhetsetiketter\n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions återställ inte prenumerationer\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method återställ inte tabellaccessmetoder\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces återställ inte användning av tabellutymmen\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr " --section=SEKTION återställ namngiven sektion (pre-data, data eller post-data)\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr " --transaction-size=N gör commit efter var N:e objekt\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME gör SET ROLE innan återställning\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "" "\n" @@ -2755,7 +2933,7 @@ msgstr "" "Flaggorna -I, -n, -N, -P, -t, -T och --section kan kombineras och anges\n" "många gånger för att välja flera objekt.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "" "\n" @@ -2765,55 +2943,3 @@ msgstr "" "\n" "Om inget indatafilnamn är angivet, så kommer standard in att användas.\n" "\n" - -#, c-format -#~ msgid " %s" -#~ msgstr " %s" - -#, c-format -#~ msgid " -Z, --compress=0-9 compression level for compressed formats\n" -#~ msgstr " -Z, --compress=0-9 komprimeringsnivå för komprimerade format\n" - -#, c-format -#~ msgid "cannot restore from compressed archive (compression not supported in this installation)" -#~ msgstr "kan inte återställa från komprimerat arkiv (inte konfigurerad med stöd för komprimering)" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "kunde inte byta katalog till \"%s\": %m" - -#, c-format -#~ msgid "could not close blob data file: %m" -#~ msgstr "kan inte stänga blobbars datafil: %m" - -#, c-format -#~ msgid "could not close blobs TOC file: %m" -#~ msgstr "kunde inte stänga blobbars TOC-fil: %m" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "kunde inte läsa binär \"%s\"" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "kan inte läsa symbolisk länk \"%s\": %m" - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "ogiltig binär \"%s\"" - -#, c-format -#~ msgid "invalid compression code: %d" -#~ msgstr "ogiltig komprimeringskod: %d" - -#, c-format -#~ msgid "not built with zlib support" -#~ msgstr "ej byggt med zlib-stöd" - -#, c-format -#~ msgid "requested compression not available in this installation -- archive will be uncompressed" -#~ msgstr "efterfrågad komprimering finns inte i denna installation -- arkivet kommer sparas okomprimerat" diff --git a/src/bin/pg_dump/po/uk.po b/src/bin/pg_dump/po/uk.po index 7a6315d2d4fa9..f92561f2eb400 100644 --- a/src/bin/pg_dump/po/uk.po +++ b/src/bin/pg_dump/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:20+0000\n" -"PO-Revision-Date: 2023-12-19 15:37\n" +"POT-Creation-Date: 2024-09-23 10:51+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_dump.pot\n" -"X-Crowdin-File-ID: 945\n" +"X-Crowdin-File: /REL_17_STABLE/pg_dump.pot\n" +"X-Crowdin-File-ID: 986\n" #: ../../../src/common/logging.c:276 #, c-format @@ -89,32 +89,47 @@ msgstr "алгоритм стиснення \"%s\" не приймає кіль msgid "compression algorithm \"%s\" does not support long-distance mode" msgstr "алгоритм стиснення \"%s\" не підтримує режим довгої відстані" -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../../common/exec.c:412 parallel.c:1609 +#: ../../common/exec.c:382 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../../common/exec.c:424 parallel.c:1609 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 msgid "out of memory" msgstr "недостатньо пам'яті" @@ -129,6 +144,49 @@ msgstr "недостатньо пам'яті\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_backup_directory.c:182 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: ../../common/wait_error.c:55 #, c-format msgid "command not executable" @@ -169,227 +227,247 @@ msgstr "неприпустиме значення \"%s\" для параметр msgid "%s must be in range %d..%d" msgstr "%s має бути в діапазоні %d..%d" -#: common.c:132 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: common.c:135 #, c-format msgid "reading extensions" msgstr "читання розширень" -#: common.c:135 +#: common.c:138 #, c-format msgid "identifying extension members" msgstr "ідентифікація членів розширення" -#: common.c:138 +#: common.c:141 #, c-format msgid "reading schemas" msgstr "читання схемів" -#: common.c:147 +#: common.c:150 #, c-format msgid "reading user-defined tables" msgstr "читання користувацьких таблиць" -#: common.c:152 +#: common.c:155 #, c-format msgid "reading user-defined functions" msgstr "читання користувацьких функцій" -#: common.c:156 +#: common.c:159 #, c-format msgid "reading user-defined types" msgstr "читання користувацьких типів" -#: common.c:160 +#: common.c:163 #, c-format msgid "reading procedural languages" msgstr "читання процедурних мов" -#: common.c:163 +#: common.c:166 #, c-format msgid "reading user-defined aggregate functions" msgstr "читання користувацьких агрегатних функцій" -#: common.c:166 +#: common.c:169 #, c-format msgid "reading user-defined operators" msgstr "читання користувацьких операторів" -#: common.c:169 +#: common.c:172 #, c-format msgid "reading user-defined access methods" msgstr "читання користувацьких методів доступу" -#: common.c:172 +#: common.c:175 #, c-format msgid "reading user-defined operator classes" msgstr "читання користувацьких класів операторів" -#: common.c:175 +#: common.c:178 #, c-format msgid "reading user-defined operator families" msgstr "читання користувацьких сімейств операторів" -#: common.c:178 +#: common.c:181 #, c-format msgid "reading user-defined text search parsers" msgstr "читання користувацьких парсерів текстового пошуку" -#: common.c:181 +#: common.c:184 #, c-format msgid "reading user-defined text search templates" msgstr "читання користувацьких шаблонів текстового пошуку" -#: common.c:184 +#: common.c:187 #, c-format msgid "reading user-defined text search dictionaries" msgstr "читання користувацьких словників текстового пошуку" -#: common.c:187 +#: common.c:190 #, c-format msgid "reading user-defined text search configurations" msgstr "читання користувацьких конфігурацій текстового пошуку" -#: common.c:190 +#: common.c:193 #, c-format msgid "reading user-defined foreign-data wrappers" msgstr "читання користувацьких джерел сторонніх даних" -#: common.c:193 +#: common.c:196 #, c-format msgid "reading user-defined foreign servers" msgstr "читання користувацьких сторонніх серверів" -#: common.c:196 +#: common.c:199 #, c-format msgid "reading default privileges" msgstr "читання прав за замовчуванням" -#: common.c:199 +#: common.c:202 #, c-format msgid "reading user-defined collations" msgstr "читання користувацьких сортувань" -#: common.c:202 +#: common.c:205 #, c-format msgid "reading user-defined conversions" msgstr "читання користувацьких перетворень" -#: common.c:205 +#: common.c:208 #, c-format msgid "reading type casts" msgstr "читання типу приведення" -#: common.c:208 +#: common.c:211 #, c-format msgid "reading transforms" msgstr "читання перетворень" -#: common.c:211 +#: common.c:214 #, c-format msgid "reading table inheritance information" msgstr "читання інформації про успадкування таблиці" -#: common.c:214 +#: common.c:217 #, c-format msgid "reading event triggers" msgstr "читання тригерів подій" -#: common.c:218 +#: common.c:221 #, c-format msgid "finding extension tables" msgstr "пошук таблиць розширень" -#: common.c:222 +#: common.c:225 #, c-format msgid "finding inheritance relationships" msgstr "пошук відносин успадкування" -#: common.c:225 +#: common.c:228 #, c-format msgid "reading column info for interesting tables" msgstr "читання інформації про стовпці цікавлячої таблиці" -#: common.c:228 +#: common.c:231 #, c-format msgid "flagging inherited columns in subtables" msgstr "помітка успадкованих стовпців в підтаблицях" -#: common.c:231 +#: common.c:234 #, c-format msgid "reading partitioning data" msgstr "читання даних секції" -#: common.c:234 +#: common.c:237 #, c-format msgid "reading indexes" msgstr "читання індексів" -#: common.c:237 +#: common.c:240 #, c-format msgid "flagging indexes in partitioned tables" msgstr "помітка індексів в секційних таблицях" -#: common.c:240 +#: common.c:243 #, c-format msgid "reading extended statistics" msgstr "читання розширеної статистики" -#: common.c:243 +#: common.c:246 #, c-format msgid "reading constraints" msgstr "читання обмежень" -#: common.c:246 +#: common.c:249 #, c-format msgid "reading triggers" msgstr "читання тригерів" -#: common.c:249 +#: common.c:252 #, c-format msgid "reading rewrite rules" msgstr "читання правил перезаписування" -#: common.c:252 +#: common.c:255 #, c-format msgid "reading policies" msgstr "читання політик" -#: common.c:255 +#: common.c:258 #, c-format msgid "reading publications" msgstr "читання публікацій" -#: common.c:258 +#: common.c:261 #, c-format msgid "reading publication membership of tables" msgstr "читання членства публікації для таблиць" -#: common.c:261 +#: common.c:264 #, c-format msgid "reading publication membership of schemas" msgstr "читання членства публікації для схем" -#: common.c:264 +#: common.c:267 #, c-format msgid "reading subscriptions" msgstr "читання підписок" -#: common.c:327 +#: common.c:270 +#, c-format +msgid "reading subscription membership of tables" +msgstr "читання підписки членства таблиць" + +#: common.c:333 #, c-format msgid "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found" msgstr "помилка перевірки, батьківський елемент ідентифікатора OID %u для таблиці \"%s\" (ідентифікатор OID %u) не знайдено" -#: common.c:369 +#: common.c:375 #, c-format msgid "invalid number of parents %d for table \"%s\"" msgstr "неприпустиме число батьківських елементів %d для таблиці \"%s\"" -#: common.c:1049 +#: common.c:1098 #, c-format msgid "could not parse numeric array \"%s\": too many numbers" msgstr "не вдалося проаналізувати числовий масив \"%s\": забагато чисел" -#: common.c:1061 +#: common.c:1110 #, c-format msgid "could not parse numeric array \"%s\": invalid character in number" msgstr "не вдалося проаналізувати числовий масив \"%s\": неприпустимий характер числа" @@ -419,15 +497,20 @@ msgstr "не вдалося розпакувати дані: %s" msgid "could not close compression library: %s" msgstr "не вдалося закрити бібліотеку стиснення: %s" -#: compress_gzip.c:266 compress_gzip.c:295 compress_lz4.c:608 -#: compress_lz4.c:628 compress_lz4.c:647 compress_none.c:97 compress_none.c:140 +#: compress_gzip.c:266 compress_lz4.c:608 compress_lz4.c:628 compress_lz4.c:647 #, c-format msgid "could not read from input file: %s" msgstr "не вдалося прочитати з вхідного файлу: %s" -#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:142 -#: compress_zstd.c:371 pg_backup_custom.c:653 pg_backup_directory.c:558 -#: pg_backup_tar.c:725 pg_backup_tar.c:748 +#: compress_gzip.c:295 compress_none.c:97 compress_none.c:139 +#: compress_zstd.c:373 pg_backup_custom.c:651 +#, c-format +msgid "could not read from input file: %m" +msgstr "не вдалося прочитати з вхідного файлу: %m" + +#: compress_gzip.c:297 compress_lz4.c:630 compress_none.c:141 +#: compress_zstd.c:371 pg_backup_custom.c:649 pg_backup_directory.c:565 +#: pg_backup_tar.c:740 pg_backup_tar.c:763 #, c-format msgid "could not read from input file: end of file" msgstr "не вдалося прочитати з вхідного файлу: кінець файлу" @@ -478,16 +561,61 @@ msgstr "не вдалося ініціалізувати бібліотеку с msgid "could not decompress data: %s" msgstr "не вдалося розпакувати дані: %s" -#: compress_zstd.c:373 pg_backup_custom.c:655 -#, c-format -msgid "could not read from input file: %m" -msgstr "не вдалося прочитати з вхідного файлу: %m" - #: compress_zstd.c:501 #, c-format msgid "unhandled mode \"%s\"" msgstr "непідтримуваний режим \"%s\"" +#: filter.c:49 +#, c-format +msgid "could not open filter file \"%s\": %m" +msgstr "не вдалося відкрити файл фільтра \"%s\": %m" + +#: filter.c:72 +#, c-format +msgid "could not close filter file \"%s\": %m" +msgstr "не вдалося закрити файл фільтра \"%s\": %m" + +#: filter.c:165 +#, c-format +msgid "invalid format in filter read from standard input on line %d: %s" +msgstr "неприпустимий формат у фільтрі прочитаний з стандартного введення в рядку %d: %s" + +#: filter.c:168 +#, c-format +msgid "invalid format in filter read from file \"%s\" on line %d: %s" +msgstr "неприпустимий формат прочитанний у файлі \"%s\" в рядку %d: %s" + +#: filter.c:241 filter.c:468 +#, c-format +msgid "could not read from filter file \"%s\": %m" +msgstr "не вдалося прочитати з файлу фільтра %s: %m" + +#: filter.c:244 +msgid "unexpected end of file" +msgstr "несподіваний кінець файлу" + +#: filter.c:311 +msgid "missing object name pattern" +msgstr "відсутній шаблон назви об'єкта" + +#: filter.c:422 +msgid "no filter command found (expected \"include\" or \"exclude\")" +msgstr "не знайдено команди фільтрів (очікувалося \"include\" або \"exclude\")" + +#: filter.c:433 +msgid "invalid filter command (expected \"include\" or \"exclude\")" +msgstr "неприпустима команда фільтра (очікувалась \"include\" або \"exclude\")" + +#: filter.c:440 +msgid "missing filter object type" +msgstr "відсутній тип об'єкту фільтру" + +#: filter.c:447 +#, c-format +msgid "unsupported filter object type: \"%.*s\"" +msgstr "непідтримуваний тип об'єкта фільтру: \"%.*s\"" + #: parallel.c:251 #, c-format msgid "%s() failed: error code %d" @@ -565,117 +693,117 @@ msgstr "pgpipe: не вдалося зв'язатися з сокетом: ко msgid "pgpipe: could not accept connection: error code %d" msgstr "pgpipe: не вдалося прийняти зв'язок: код помилки %d" -#: pg_backup_archiver.c:276 pg_backup_archiver.c:1603 +#: pg_backup_archiver.c:261 pg_backup_archiver.c:1706 #, c-format msgid "could not close output file: %m" msgstr "не вдалося закрити вихідний файл: %m" -#: pg_backup_archiver.c:320 pg_backup_archiver.c:324 +#: pg_backup_archiver.c:305 pg_backup_archiver.c:309 #, c-format msgid "archive items not in correct section order" msgstr "елементи архіву в неправильному порядку" -#: pg_backup_archiver.c:330 +#: pg_backup_archiver.c:315 #, c-format msgid "unexpected section code %d" msgstr "неочікуваний код розділу %d" -#: pg_backup_archiver.c:367 +#: pg_backup_archiver.c:352 #, c-format msgid "parallel restore is not supported with this archive file format" msgstr "паралельне відновлення не підтримується з цим файлом архівного формату" -#: pg_backup_archiver.c:371 +#: pg_backup_archiver.c:356 #, c-format msgid "parallel restore is not supported with archives made by pre-8.0 pg_dump" msgstr "паралельне відновлення не підтримується з архівами, зробленими pre-8.0 pg_dump" -#: pg_backup_archiver.c:392 +#: pg_backup_archiver.c:377 #, c-format msgid "cannot restore from compressed archive (%s)" msgstr "не можна відновити зі стиснутого архіву (%s)" -#: pg_backup_archiver.c:412 +#: pg_backup_archiver.c:397 #, c-format msgid "connecting to database for restore" msgstr "підключення до бази даних для відновлення" -#: pg_backup_archiver.c:414 +#: pg_backup_archiver.c:399 #, c-format msgid "direct database connections are not supported in pre-1.3 archives" msgstr "прямі з'днання з базою даних не підтримуються в архівах у версіях до 1.3" -#: pg_backup_archiver.c:457 +#: pg_backup_archiver.c:442 #, c-format msgid "implied data-only restore" msgstr "мається на увазі відновлення лише даних" -#: pg_backup_archiver.c:523 +#: pg_backup_archiver.c:510 #, c-format msgid "dropping %s %s" msgstr "видалення %s %s" -#: pg_backup_archiver.c:623 +#: pg_backup_archiver.c:642 #, c-format msgid "could not find where to insert IF EXISTS in statement \"%s\"" msgstr "не вдалося знайти, куди вставити IF EXISTS в інструкції \"%s\"" -#: pg_backup_archiver.c:778 pg_backup_archiver.c:780 +#: pg_backup_archiver.c:828 pg_backup_archiver.c:830 #, c-format msgid "warning from original dump file: %s" msgstr "попередження з оригінального файлу дамп: %s" -#: pg_backup_archiver.c:795 +#: pg_backup_archiver.c:864 #, c-format msgid "creating %s \"%s.%s\"" msgstr "створення %s \"%s.%s\"" -#: pg_backup_archiver.c:798 +#: pg_backup_archiver.c:867 #, c-format msgid "creating %s \"%s\"" msgstr "створення %s \" \"%s\"" -#: pg_backup_archiver.c:848 +#: pg_backup_archiver.c:917 #, c-format msgid "connecting to new database \"%s\"" msgstr "підключення до нової бази даних \"%s\"" -#: pg_backup_archiver.c:875 +#: pg_backup_archiver.c:944 #, c-format msgid "processing %s" msgstr "обробка %s" -#: pg_backup_archiver.c:897 +#: pg_backup_archiver.c:966 #, c-format msgid "processing data for table \"%s.%s\"" msgstr "обробка даних для таблиці \"%s.%s\"" -#: pg_backup_archiver.c:967 +#: pg_backup_archiver.c:1036 #, c-format msgid "executing %s %s" msgstr "виконання %s %s" -#: pg_backup_archiver.c:1008 +#: pg_backup_archiver.c:1096 #, c-format msgid "disabling triggers for %s" msgstr "вимкнення тригерів для %s" -#: pg_backup_archiver.c:1034 +#: pg_backup_archiver.c:1122 #, c-format msgid "enabling triggers for %s" msgstr "увімкнення тригерів для %s" -#: pg_backup_archiver.c:1099 +#: pg_backup_archiver.c:1187 #, c-format msgid "internal error -- WriteData cannot be called outside the context of a DataDumper routine" msgstr "внутрішня помилка - WriteData не може бути викликана поза контекстом підпрограми DataDumper " -#: pg_backup_archiver.c:1287 +#: pg_backup_archiver.c:1379 #, c-format msgid "large-object output not supported in chosen format" msgstr "вивід великих об'єктів не підтримується у вибраному форматі" -#: pg_backup_archiver.c:1345 +#: pg_backup_archiver.c:1442 #, c-format msgid "restored %d large object" msgid_plural "restored %d large objects" @@ -684,55 +812,55 @@ msgstr[1] "відновлено %d великих об'єкти" msgstr[2] "відновлено %d великих об'єктів" msgstr[3] "відновлено %d великих об'єктів" -#: pg_backup_archiver.c:1366 pg_backup_tar.c:668 +#: pg_backup_archiver.c:1469 pg_backup_tar.c:683 #, c-format msgid "restoring large object with OID %u" msgstr "відновлення великого об'єкту з OID %u" -#: pg_backup_archiver.c:1378 +#: pg_backup_archiver.c:1481 #, c-format msgid "could not create large object %u: %s" msgstr "не вдалося створити великий об'єкт %u: %s" -#: pg_backup_archiver.c:1383 pg_dump.c:3720 +#: pg_backup_archiver.c:1486 pg_dump.c:3888 #, c-format msgid "could not open large object %u: %s" msgstr "не вдалося відкрити великий об'єкт %u: %s" -#: pg_backup_archiver.c:1439 +#: pg_backup_archiver.c:1542 #, c-format msgid "could not open TOC file \"%s\": %m" msgstr "не вдалося відкрити файл TOC \"%s\": %m" -#: pg_backup_archiver.c:1467 +#: pg_backup_archiver.c:1570 #, c-format msgid "line ignored: %s" msgstr "рядок проігноровано: %s" -#: pg_backup_archiver.c:1474 +#: pg_backup_archiver.c:1577 pg_backup_db.c:609 #, c-format msgid "could not find entry for ID %d" msgstr "не вдалося знайти введення для ID %d" -#: pg_backup_archiver.c:1497 pg_backup_directory.c:221 -#: pg_backup_directory.c:606 +#: pg_backup_archiver.c:1600 pg_backup_directory.c:219 +#: pg_backup_directory.c:613 #, c-format msgid "could not close TOC file: %m" msgstr "не вдалося закрити файл TOC: %m" -#: pg_backup_archiver.c:1584 pg_backup_custom.c:156 pg_backup_directory.c:332 -#: pg_backup_directory.c:593 pg_backup_directory.c:658 -#: pg_backup_directory.c:676 pg_dumpall.c:501 +#: pg_backup_archiver.c:1687 pg_backup_custom.c:152 pg_backup_directory.c:333 +#: pg_backup_directory.c:600 pg_backup_directory.c:666 +#: pg_backup_directory.c:684 pg_dumpall.c:506 #, c-format msgid "could not open output file \"%s\": %m" msgstr "не вдалося відкрити вихідний файл \"%s\": %m" -#: pg_backup_archiver.c:1586 pg_backup_custom.c:162 +#: pg_backup_archiver.c:1689 pg_backup_custom.c:158 #, c-format msgid "could not open output file: %m" msgstr "не вдалося відкрити вихідний файл: %m" -#: pg_backup_archiver.c:1669 +#: pg_backup_archiver.c:1772 #, c-format msgid "wrote %zu byte of large object data (result = %d)" msgid_plural "wrote %zu bytes of large object data (result = %d)" @@ -741,340 +869,345 @@ msgstr[1] "записано %zu байти даних великого об'єк msgstr[2] "записано %zu байтів даних великого об'єкта (результат = %d)" msgstr[3] "записано %zu байтів даних великого об'єкта (результат = %d)" -#: pg_backup_archiver.c:1675 +#: pg_backup_archiver.c:1778 #, c-format msgid "could not write to large object: %s" msgstr "не вдалося записати до великого об'єкту: %s" -#: pg_backup_archiver.c:1765 +#: pg_backup_archiver.c:1868 #, c-format msgid "while INITIALIZING:" msgstr "при ІНІЦІАЛІЗАЦІЇ:" -#: pg_backup_archiver.c:1770 +#: pg_backup_archiver.c:1873 #, c-format msgid "while PROCESSING TOC:" msgstr "при ОБРОБЦІ TOC:" -#: pg_backup_archiver.c:1775 +#: pg_backup_archiver.c:1878 #, c-format msgid "while FINALIZING:" msgstr "при ЗАВЕРШЕННІ:" -#: pg_backup_archiver.c:1780 +#: pg_backup_archiver.c:1883 #, c-format msgid "from TOC entry %d; %u %u %s %s %s" msgstr "зі входження до TOC %d; %u %u %s %s %s" -#: pg_backup_archiver.c:1856 +#: pg_backup_archiver.c:1959 #, c-format msgid "bad dumpId" msgstr "невірний dumpId" -#: pg_backup_archiver.c:1877 +#: pg_backup_archiver.c:1980 #, c-format msgid "bad table dumpId for TABLE DATA item" msgstr "невірна таблиця dumpId для елементу даних таблиці" -#: pg_backup_archiver.c:1969 +#: pg_backup_archiver.c:2072 #, c-format msgid "unexpected data offset flag %d" msgstr "неочікувана позначка зсуву даних %d" -#: pg_backup_archiver.c:1982 +#: pg_backup_archiver.c:2085 #, c-format msgid "file offset in dump file is too large" msgstr "зсув файлу у файлі дампу завеликий" -#: pg_backup_archiver.c:2093 +#: pg_backup_archiver.c:2196 #, c-format msgid "directory name too long: \"%s\"" msgstr "ім'я каталогу задовге: \"%s\"" -#: pg_backup_archiver.c:2143 +#: pg_backup_archiver.c:2246 #, c-format msgid "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)" msgstr "каталог \"%s\" не схожий на архівний (\"toc.dat\" не існує)" -#: pg_backup_archiver.c:2151 pg_backup_custom.c:173 pg_backup_custom.c:816 -#: pg_backup_directory.c:206 pg_backup_directory.c:395 +#: pg_backup_archiver.c:2254 pg_backup_custom.c:169 pg_backup_custom.c:812 +#: pg_backup_directory.c:204 pg_backup_directory.c:396 #, c-format msgid "could not open input file \"%s\": %m" msgstr "не вдалося відкрити вхідний файл \"%s\": %m" -#: pg_backup_archiver.c:2158 pg_backup_custom.c:179 +#: pg_backup_archiver.c:2261 pg_backup_custom.c:175 #, c-format msgid "could not open input file: %m" msgstr "не вдалося відкрити вхідний файл: %m" -#: pg_backup_archiver.c:2164 +#: pg_backup_archiver.c:2267 #, c-format msgid "could not read input file: %m" msgstr "не вдалося прочитати вхідний файл: %m" -#: pg_backup_archiver.c:2166 +#: pg_backup_archiver.c:2269 #, c-format msgid "input file is too short (read %lu, expected 5)" msgstr "вхідний файл закороткий (прочитано %lu, очікувалось 5)" -#: pg_backup_archiver.c:2198 +#: pg_backup_archiver.c:2301 #, c-format msgid "input file appears to be a text format dump. Please use psql." msgstr "вхідний файл схожий на дамп текстового формату. Будь ласка, використайте psql." -#: pg_backup_archiver.c:2204 +#: pg_backup_archiver.c:2307 #, c-format msgid "input file does not appear to be a valid archive (too short?)" msgstr "вхідний файл не схожий на архівний (закороткий?)" -#: pg_backup_archiver.c:2210 +#: pg_backup_archiver.c:2313 #, c-format msgid "input file does not appear to be a valid archive" msgstr "вхідний файл не схожий на архівний" -#: pg_backup_archiver.c:2219 +#: pg_backup_archiver.c:2322 #, c-format msgid "could not close input file: %m" msgstr "не вдалося закрити вхідний файл: %m" -#: pg_backup_archiver.c:2297 +#: pg_backup_archiver.c:2401 #, c-format msgid "could not open stdout for appending: %m" msgstr "не вдалося відкрити stdout для додавання: %m" -#: pg_backup_archiver.c:2342 +#: pg_backup_archiver.c:2446 #, c-format msgid "unrecognized file format \"%d\"" msgstr "нерозпізнаний формат файлу \"%d\"" -#: pg_backup_archiver.c:2423 pg_backup_archiver.c:4466 +#: pg_backup_archiver.c:2527 pg_backup_archiver.c:4647 #, c-format msgid "finished item %d %s %s" msgstr "завершений об'єкт %d %s %s" -#: pg_backup_archiver.c:2427 pg_backup_archiver.c:4479 +#: pg_backup_archiver.c:2531 pg_backup_archiver.c:4660 #, c-format msgid "worker process failed: exit code %d" msgstr "помилка при робочому процесі: код виходу %d" -#: pg_backup_archiver.c:2548 +#: pg_backup_archiver.c:2653 #, c-format msgid "entry ID %d out of range -- perhaps a corrupt TOC" msgstr "введення ідентифікатора %d поза діапазоном -- можливо, зміст пошкоджений" -#: pg_backup_archiver.c:2628 +#: pg_backup_archiver.c:2736 #, c-format msgid "restoring tables WITH OIDS is not supported anymore" msgstr "відновлення таблиць WITH OIDS більше не підтримується" -#: pg_backup_archiver.c:2710 +#: pg_backup_archiver.c:2818 #, c-format msgid "unrecognized encoding \"%s\"" msgstr "нерозпізнане кодування \"%s\"" -#: pg_backup_archiver.c:2715 +#: pg_backup_archiver.c:2823 #, c-format msgid "invalid ENCODING item: %s" msgstr "невірний об'єкт КОДУВАННЯ: %s" -#: pg_backup_archiver.c:2733 +#: pg_backup_archiver.c:2841 #, c-format msgid "invalid STDSTRINGS item: %s" msgstr "невірний об'єкт STDSTRINGS: %s" -#: pg_backup_archiver.c:2758 +#: pg_backup_archiver.c:2866 #, c-format msgid "schema \"%s\" not found" msgstr "схему \"%s\" не знайдено" -#: pg_backup_archiver.c:2765 +#: pg_backup_archiver.c:2873 #, c-format msgid "table \"%s\" not found" msgstr "таблицю \"%s\" не знайдено" -#: pg_backup_archiver.c:2772 +#: pg_backup_archiver.c:2880 #, c-format msgid "index \"%s\" not found" msgstr "індекс \"%s\" не знайдено" -#: pg_backup_archiver.c:2779 +#: pg_backup_archiver.c:2887 #, c-format msgid "function \"%s\" not found" msgstr "функцію \"%s\" не знайдено" -#: pg_backup_archiver.c:2786 +#: pg_backup_archiver.c:2894 #, c-format msgid "trigger \"%s\" not found" msgstr "тригер \"%s\" не знайдено" -#: pg_backup_archiver.c:3201 +#: pg_backup_archiver.c:3325 #, c-format msgid "could not set session user to \"%s\": %s" msgstr "не вдалося встановити користувача сеансу для \"%s\": %s" -#: pg_backup_archiver.c:3333 +#: pg_backup_archiver.c:3457 +#, c-format +msgid "could not set \"search_path\" to \"%s\": %s" +msgstr "не вдалося встановити \"search_path\" для \"%s\": %s" + +#: pg_backup_archiver.c:3518 #, c-format -msgid "could not set search_path to \"%s\": %s" -msgstr "не вдалося встановити search_path для \"%s\": %s" +msgid "could not set \"default_tablespace\" to %s: %s" +msgstr "не вдалося встановити \"default_tablespace\" для %s: %s" -#: pg_backup_archiver.c:3394 +#: pg_backup_archiver.c:3567 #, c-format -msgid "could not set default_tablespace to %s: %s" -msgstr "не вдалося встановити default_tablespace для %s: %s" +msgid "could not set \"default_table_access_method\": %s" +msgstr "не вдалося встановити \"default_table_access_method\" для: %s" -#: pg_backup_archiver.c:3443 +#: pg_backup_archiver.c:3616 #, c-format -msgid "could not set default_table_access_method: %s" -msgstr "не вдалося встановити default_table_access_method для : %s" +msgid "could not alter table access method: %s" +msgstr "не вдалося змінити метод доступу до таблиці: %s" -#: pg_backup_archiver.c:3548 +#: pg_backup_archiver.c:3717 #, c-format msgid "don't know how to set owner for object type \"%s\"" msgstr "невідомо, як встановити власника об'єкту типу \"%s\"" -#: pg_backup_archiver.c:3770 +#: pg_backup_archiver.c:4004 #, c-format msgid "did not find magic string in file header" msgstr "в заголовку файлу не знайдено магічного рядка" -#: pg_backup_archiver.c:3784 +#: pg_backup_archiver.c:4018 #, c-format msgid "unsupported version (%d.%d) in file header" msgstr "в заголовку непідтримувана версія (%d.%d)" -#: pg_backup_archiver.c:3789 +#: pg_backup_archiver.c:4023 #, c-format msgid "sanity check on integer size (%lu) failed" msgstr "перевірка на розмір цілого числа (%lu) не вдалася" -#: pg_backup_archiver.c:3793 +#: pg_backup_archiver.c:4027 #, c-format msgid "archive was made on a machine with larger integers, some operations might fail" msgstr "архів зроблено на архітектурі з більшими цілими числами, деякі операції можуть не виконуватися" -#: pg_backup_archiver.c:3803 +#: pg_backup_archiver.c:4037 #, c-format msgid "expected format (%d) differs from format found in file (%d)" msgstr "очікуваний формат (%d) відрізняється від знайденого формату у файлі (%d)" -#: pg_backup_archiver.c:3825 +#: pg_backup_archiver.c:4059 #, c-format msgid "archive is compressed, but this installation does not support compression (%s) -- no data will be available" msgstr "архів стиснено, але ця інсталяція не підтримує стискання (%s) -- дані не будуть доступними" -#: pg_backup_archiver.c:3861 +#: pg_backup_archiver.c:4095 #, c-format msgid "invalid creation date in header" msgstr "неприпустима дата створення у заголовку" -#: pg_backup_archiver.c:3995 +#: pg_backup_archiver.c:4229 #, c-format msgid "processing item %d %s %s" msgstr "обробка елементу %d %s %s" -#: pg_backup_archiver.c:4070 +#: pg_backup_archiver.c:4314 #, c-format msgid "entering main parallel loop" msgstr "введення головного паралельного циклу" -#: pg_backup_archiver.c:4081 +#: pg_backup_archiver.c:4325 #, c-format msgid "skipping item %d %s %s" msgstr "пропускається елемент %d %s %s " -#: pg_backup_archiver.c:4090 +#: pg_backup_archiver.c:4334 #, c-format msgid "launching item %d %s %s" msgstr "запуск елементу %d %s %s " -#: pg_backup_archiver.c:4144 +#: pg_backup_archiver.c:4388 #, c-format msgid "finished main parallel loop" msgstr "головний паралельний цикл завершився" -#: pg_backup_archiver.c:4180 +#: pg_backup_archiver.c:4424 #, c-format msgid "processing missed item %d %s %s" msgstr "обробка втраченого елементу %d %s %s" -#: pg_backup_archiver.c:4785 +#: pg_backup_archiver.c:4966 #, c-format msgid "table \"%s\" could not be created, will not restore its data" msgstr "не вдалося створити таблицю \"%s\", дані не будуть відновлені" -#: pg_backup_custom.c:380 pg_backup_null.c:147 +#: pg_backup_custom.c:376 pg_backup_null.c:143 #, c-format msgid "invalid OID for large object" msgstr "неприпустимий ідентифікатор OID для великого об’єкту" -#: pg_backup_custom.c:445 pg_backup_custom.c:511 pg_backup_custom.c:640 -#: pg_backup_custom.c:874 pg_backup_tar.c:1014 pg_backup_tar.c:1019 +#: pg_backup_custom.c:441 pg_backup_custom.c:507 pg_backup_custom.c:636 +#: pg_backup_custom.c:870 pg_backup_tar.c:1029 pg_backup_tar.c:1034 #, c-format msgid "error during file seek: %m" msgstr "помилка під час пошуку файлу oobe. xml: %m" -#: pg_backup_custom.c:484 +#: pg_backup_custom.c:480 #, c-format msgid "data block %d has wrong seek position" msgstr "блок даних %d має неправильну позицію пошуку" -#: pg_backup_custom.c:501 +#: pg_backup_custom.c:497 #, c-format msgid "unrecognized data block type (%d) while searching archive" msgstr "нерозпізнаний тип блоку даних (%d) під час пошуку архіву" -#: pg_backup_custom.c:523 +#: pg_backup_custom.c:519 #, c-format msgid "could not find block ID %d in archive -- possibly due to out-of-order restore request, which cannot be handled due to non-seekable input file" msgstr "не вдалося зайти в архіві блок з ідентифікатором %d -- можливо, через непослідовність запиту відновлення, який не можна обробити через файл, що не допускає довільний вхід" -#: pg_backup_custom.c:528 +#: pg_backup_custom.c:524 #, c-format msgid "could not find block ID %d in archive -- possibly corrupt archive" msgstr "не вдалося знайти в архіві блок з ідентифікатором %d -- можливо, архів пошкоджений" -#: pg_backup_custom.c:535 +#: pg_backup_custom.c:531 #, c-format msgid "found unexpected block ID (%d) when reading data -- expected %d" msgstr "знайдено неочікуваний блок з ідентифікатором (%d) під час читання даних -- очікувалося %d" -#: pg_backup_custom.c:549 +#: pg_backup_custom.c:545 #, c-format msgid "unrecognized data block type %d while restoring archive" msgstr "нерозпізнаний тип блоку даних %d при відновленні архіву" -#: pg_backup_custom.c:755 pg_backup_custom.c:807 pg_backup_custom.c:952 -#: pg_backup_tar.c:1017 +#: pg_backup_custom.c:751 pg_backup_custom.c:803 pg_backup_custom.c:945 +#: pg_backup_tar.c:1032 #, c-format msgid "could not determine seek position in archive file: %m" msgstr "не вдалося визначити позицію пошуку у файлі архіву: %m" -#: pg_backup_custom.c:771 pg_backup_custom.c:811 +#: pg_backup_custom.c:767 pg_backup_custom.c:807 #, c-format msgid "could not close archive file: %m" msgstr "не вдалося закрити архівний файл: %m" -#: pg_backup_custom.c:794 +#: pg_backup_custom.c:790 #, c-format msgid "can only reopen input archives" msgstr "можливо повторно відкрити лише вхідні архіви" -#: pg_backup_custom.c:801 +#: pg_backup_custom.c:797 #, c-format msgid "parallel restore from standard input is not supported" msgstr "паралельне відновлення зі стандартного вводу не підтримується" -#: pg_backup_custom.c:803 +#: pg_backup_custom.c:799 #, c-format msgid "parallel restore from non-seekable file is not supported" msgstr "паралельне відновлення з файлу без вільного доступу не підтримується" -#: pg_backup_custom.c:819 +#: pg_backup_custom.c:815 #, c-format msgid "could not set seek position in archive file: %m" msgstr "не вдалося набрати позицію пошуку у файлі архіву: %m" -#: pg_backup_custom.c:898 +#: pg_backup_custom.c:894 #, c-format msgid "compressor active" msgstr "ущільнювач активний" @@ -1084,12 +1217,12 @@ msgstr "ущільнювач активний" msgid "could not get server_version from libpq" msgstr "не вдалося отримати версію серверу з libpq" -#: pg_backup_db.c:53 pg_dumpall.c:1809 +#: pg_backup_db.c:53 pg_dumpall.c:1830 #, c-format msgid "aborting because of server version mismatch" msgstr "переривання через невідповідність версії серверу" -#: pg_backup_db.c:54 pg_dumpall.c:1810 +#: pg_backup_db.c:54 pg_dumpall.c:1831 #, c-format msgid "server version: %s; %s version: %s" msgstr "версія серверу: %s; версія %s: %s" @@ -1099,7 +1232,7 @@ msgstr "версія серверу: %s; версія %s: %s" msgid "already connected to a database" msgstr "вже під'єднано до бази даних" -#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1656 pg_dumpall.c:1758 +#: pg_backup_db.c:128 pg_backup_db.c:178 pg_dumpall.c:1677 pg_dumpall.c:1779 msgid "Password: " msgstr "Пароль: " @@ -1113,18 +1246,18 @@ msgstr "не вдалося зв'язатися з базою даних" msgid "reconnection failed: %s" msgstr "помилка повторного підключення: %s" -#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:756 pg_dump_sort.c:1280 -#: pg_dump_sort.c:1300 pg_dumpall.c:1683 pg_dumpall.c:1767 +#: pg_backup_db.c:190 pg_backup_db.c:264 pg_dump.c:788 pg_dump_sort.c:1213 +#: pg_dump_sort.c:1233 pg_dumpall.c:1704 pg_dumpall.c:1788 #, c-format msgid "%s" msgstr "%s" -#: pg_backup_db.c:271 pg_dumpall.c:1872 pg_dumpall.c:1895 +#: pg_backup_db.c:271 pg_dumpall.c:1893 pg_dumpall.c:1916 #, c-format msgid "query failed: %s" msgstr "запит не вдався: %s" -#: pg_backup_db.c:273 pg_dumpall.c:1873 pg_dumpall.c:1896 +#: pg_backup_db.c:273 pg_dumpall.c:1894 pg_dumpall.c:1917 #, c-format msgid "Query was: %s" msgstr "Запит був: %s" @@ -1162,7 +1295,7 @@ msgstr "помилка повернулася від PQputCopyEnd: %s" msgid "COPY failed for table \"%s\": %s" msgstr "КОПІЮВАННЯ для таблиці \"%s\" не вдалося: %s" -#: pg_backup_db.c:521 pg_dump.c:2204 +#: pg_backup_db.c:521 pg_dump.c:2283 #, c-format msgid "unexpected extra results during COPY of table \"%s\"" msgstr "неочікувані зайві результати під час копіювання таблиці \"%s\"" @@ -1175,154 +1308,149 @@ msgstr "не вдалося почати транзакцію бази дани msgid "could not commit database transaction" msgstr "не вдалося затвердити транзакцію бази даних" -#: pg_backup_directory.c:155 +#: pg_backup_directory.c:153 #, c-format msgid "no output directory specified" msgstr "вихідний каталог не вказано" -#: pg_backup_directory.c:184 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не вдалося прочитати каталог \"%s\": %m" - -#: pg_backup_directory.c:188 +#: pg_backup_directory.c:186 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не вдалося закрити каталог \"%s\": %m" -#: pg_backup_directory.c:194 +#: pg_backup_directory.c:192 #, c-format msgid "could not create directory \"%s\": %m" msgstr "не вдалося створити каталог \"%s\": %m" -#: pg_backup_directory.c:356 pg_backup_directory.c:499 -#: pg_backup_directory.c:537 +#: pg_backup_directory.c:357 pg_backup_directory.c:506 +#: pg_backup_directory.c:544 #, c-format msgid "could not write to output file: %s" msgstr "не можливо записати у вихідний файл: %s" -#: pg_backup_directory.c:374 +#: pg_backup_directory.c:375 #, c-format msgid "could not close data file: %m" msgstr "не вдалося закрити файл даних: %m" -#: pg_backup_directory.c:407 +#: pg_backup_directory.c:408 #, c-format msgid "could not close data file \"%s\": %m" msgstr "не вдалося закрити файл даних \"%s\": %m" -#: pg_backup_directory.c:448 +#: pg_backup_directory.c:455 #, c-format msgid "could not open large object TOC file \"%s\" for input: %m" msgstr "не вдалося відкрити великий об'єкт файлу TOC \"%s\" для вводу: %m" -#: pg_backup_directory.c:459 +#: pg_backup_directory.c:466 #, c-format msgid "invalid line in large object TOC file \"%s\": \"%s\"" msgstr "невірна лінія у великому об'єкті файлу TOC \"%s\": \"%s\"" -#: pg_backup_directory.c:468 +#: pg_backup_directory.c:475 #, c-format msgid "error reading large object TOC file \"%s\"" msgstr "помилка читання великого об'єкту файлу TOC \"%s\"" -#: pg_backup_directory.c:472 +#: pg_backup_directory.c:479 #, c-format msgid "could not close large object TOC file \"%s\": %m" msgstr "не вдалося закрити великий об'єкт файлу TOC \"%s\" %m" -#: pg_backup_directory.c:694 +#: pg_backup_directory.c:702 #, c-format msgid "could not close LO data file: %m" msgstr "не вдалося закрити файл даних LO: %m" -#: pg_backup_directory.c:704 +#: pg_backup_directory.c:712 #, c-format msgid "could not write to LOs TOC file: %s" msgstr "не вдалося записати в файл LO TOC: %s" -#: pg_backup_directory.c:720 +#: pg_backup_directory.c:728 #, c-format msgid "could not close LOs TOC file: %m" msgstr "не вдалося закрити файл LO TOC: %m" -#: pg_backup_directory.c:739 +#: pg_backup_directory.c:747 #, c-format msgid "file name too long: \"%s\"" msgstr "ім'я файлу задовге: \"%s\"" -#: pg_backup_null.c:74 +#: pg_backup_null.c:70 #, c-format msgid "this format cannot be read" msgstr "цей формат не може бути прочитаним" -#: pg_backup_tar.c:172 +#: pg_backup_tar.c:168 #, c-format msgid "could not open TOC file \"%s\" for output: %m" msgstr "не вдалося відкрити файл TOC \"%s\" для виводу: %m" -#: pg_backup_tar.c:179 +#: pg_backup_tar.c:175 #, c-format msgid "could not open TOC file for output: %m" msgstr "не вдалося відкрити файл TOC для виводу: %m" -#: pg_backup_tar.c:198 pg_backup_tar.c:334 pg_backup_tar.c:389 -#: pg_backup_tar.c:405 pg_backup_tar.c:891 +#: pg_backup_tar.c:194 pg_backup_tar.c:330 pg_backup_tar.c:385 +#: pg_backup_tar.c:401 pg_backup_tar.c:906 #, c-format msgid "compression is not supported by tar archive format" msgstr "стиснення не підтримується форматом архіватора tar" -#: pg_backup_tar.c:206 +#: pg_backup_tar.c:202 #, c-format msgid "could not open TOC file \"%s\" for input: %m" msgstr "не вдалося відкрити файл TOC \"%s\" для вводу: %m" -#: pg_backup_tar.c:213 +#: pg_backup_tar.c:209 #, c-format msgid "could not open TOC file for input: %m" msgstr "не вдалося відкрити файл TOC для вводу: %m" -#: pg_backup_tar.c:322 +#: pg_backup_tar.c:318 #, c-format msgid "could not find file \"%s\" in archive" msgstr "не вдалося знайти файл \"%s\" в архіві" -#: pg_backup_tar.c:382 +#: pg_backup_tar.c:378 #, c-format msgid "could not generate temporary file name: %m" msgstr "не вдалося згенерувати тимчасове ім'я файлу: %m" -#: pg_backup_tar.c:623 +#: pg_backup_tar.c:619 #, c-format msgid "unexpected COPY statement syntax: \"%s\"" msgstr "неочікуваний синтаксис інструкції копіювання: \"%s\"" -#: pg_backup_tar.c:888 +#: pg_backup_tar.c:903 #, c-format msgid "invalid OID for large object (%u)" msgstr "неприпустимий ідентифікатор OID для великих об’єктів (%u)" -#: pg_backup_tar.c:1033 +#: pg_backup_tar.c:1048 #, c-format msgid "could not close temporary file: %m" msgstr "не вдалося закрити тимчасовий файл oobe. xml: %m" -#: pg_backup_tar.c:1036 +#: pg_backup_tar.c:1051 #, c-format msgid "actual file length (%lld) does not match expected (%lld)" msgstr "фактична довжина файлу (%lld) не відповідає очікуваній (%lld)" -#: pg_backup_tar.c:1082 pg_backup_tar.c:1113 +#: pg_backup_tar.c:1097 pg_backup_tar.c:1128 #, c-format msgid "could not find header for file \"%s\" in tar archive" msgstr "не вдалося знайти верхній колонтитул для файлу oobe. xml \"%s\" в архіві tar" -#: pg_backup_tar.c:1100 +#: pg_backup_tar.c:1115 #, c-format msgid "restoring data out of order is not supported in this archive format: \"%s\" is required, but comes before \"%s\" in the archive file." msgstr "відновлення даних поза замовленням не підтримується у цьому форматі архіву: вимагаєтсья \"%s\", але перед цим іде \"%s\" у файлі архіву." -#: pg_backup_tar.c:1147 +#: pg_backup_tar.c:1162 #, c-format msgid "incomplete tar header found (%lu byte)" msgid_plural "incomplete tar header found (%lu bytes)" @@ -1331,7 +1459,7 @@ msgstr[1] "знайдено незавершений tar-заголовок (%lu msgstr[2] "знайдено незавершений tar-заголовок (%lu байт)" msgstr[3] "знайдено незавершений tar-заголовок (%lu байт)" -#: pg_backup_tar.c:1186 +#: pg_backup_tar.c:1201 #, c-format msgid "corrupt tar header found in %s (expected %d, computed %d) file position %llu" msgstr "знайдено пошкоджений заголовок tar у %s (очікувалося %d, обчислено %d) позиції файлу %llu" @@ -1341,10 +1469,10 @@ msgstr "знайдено пошкоджений заголовок tar у %s (о msgid "unrecognized section name: \"%s\"" msgstr "нерозпізнане ім’я розділу: \"%s\"" -#: pg_backup_utils.c:55 pg_dump.c:662 pg_dump.c:679 pg_dumpall.c:365 -#: pg_dumpall.c:375 pg_dumpall.c:383 pg_dumpall.c:391 pg_dumpall.c:398 -#: pg_dumpall.c:408 pg_dumpall.c:483 pg_restore.c:291 pg_restore.c:307 -#: pg_restore.c:321 +#: pg_backup_utils.c:55 pg_dump.c:694 pg_dump.c:711 pg_dumpall.c:370 +#: pg_dumpall.c:380 pg_dumpall.c:388 pg_dumpall.c:396 pg_dumpall.c:403 +#: pg_dumpall.c:413 pg_dumpall.c:488 pg_restore.c:307 pg_restore.c:323 +#: pg_restore.c:337 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." @@ -1354,274 +1482,284 @@ msgstr "Спробуйте \"%s --help\" для додаткової інфор msgid "out of on_exit_nicely slots" msgstr "перевищено межу on_exit_nicely слотів" -#: pg_dump.c:677 pg_dumpall.c:373 pg_restore.c:305 +#: pg_dump.c:709 pg_dumpall.c:378 pg_restore.c:321 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_dump.c:696 pg_restore.c:328 +#: pg_dump.c:728 pg_restore.c:344 #, c-format msgid "options -s/--schema-only and -a/--data-only cannot be used together" msgstr "параметри -s/--schema-only і -a/--data-only не можуть використовуватись разом" -#: pg_dump.c:699 +#: pg_dump.c:731 #, c-format msgid "options -s/--schema-only and --include-foreign-data cannot be used together" msgstr "параметри -s/--schema-only і --include-foreign-data не можуть використовуватись разом" -#: pg_dump.c:702 +#: pg_dump.c:734 #, c-format msgid "option --include-foreign-data is not supported with parallel backup" msgstr "параметр --include-foreign-data не підтримується з паралельним резервним копіюванням" -#: pg_dump.c:705 pg_restore.c:331 +#: pg_dump.c:737 pg_restore.c:347 #, c-format msgid "options -c/--clean and -a/--data-only cannot be used together" msgstr "параметри -c/--clean і -a/--data-only не можна використовувати разом" -#: pg_dump.c:708 pg_dumpall.c:403 pg_restore.c:356 +#: pg_dump.c:740 pg_dumpall.c:408 pg_restore.c:375 #, c-format msgid "option --if-exists requires option -c/--clean" msgstr "параметр --if-exists потребує параметр -c/--clean" -#: pg_dump.c:715 +#: pg_dump.c:747 #, c-format msgid "option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts" msgstr "параметр --on-conflict-do-nothing вимагає опції --inserts, --rows-per-insert або --column-inserts" -#: pg_dump.c:744 +#: pg_dump.c:776 #, c-format msgid "unrecognized compression algorithm: \"%s\"" msgstr "нерозпізнаний алгоритм стискання: \"%s\"" -#: pg_dump.c:751 +#: pg_dump.c:783 #, c-format msgid "invalid compression specification: %s" msgstr "неприпустима специфікація стискання: %s" -#: pg_dump.c:764 +#: pg_dump.c:796 #, c-format msgid "compression option \"%s\" is not currently supported by pg_dump" msgstr "параметр стиснення \"%s\" в даний час не підтримується pg_dump" -#: pg_dump.c:776 +#: pg_dump.c:808 #, c-format msgid "parallel backup only supported by the directory format" msgstr "паралельне резервне копіювання підтримується лише з форматом \"каталог\"" -#: pg_dump.c:822 +#: pg_dump.c:854 #, c-format msgid "last built-in OID is %u" msgstr "останній вбудований OID %u" -#: pg_dump.c:831 +#: pg_dump.c:863 #, c-format msgid "no matching schemas were found" msgstr "відповідних схем не знайдено" -#: pg_dump.c:848 +#: pg_dump.c:880 #, c-format msgid "no matching tables were found" msgstr "відповідних таблиць не знайдено" -#: pg_dump.c:876 +#: pg_dump.c:908 #, c-format msgid "no matching extensions were found" msgstr "не знайдено відповідних розширень" -#: pg_dump.c:1056 +#: pg_dump.c:1092 #, c-format msgid "%s dumps a database as a text file or to other formats.\n\n" msgstr "%s зберігає резервну копію бази даних в текстовому файлі або в інших форматах.\n\n" -#: pg_dump.c:1057 pg_dumpall.c:630 pg_restore.c:433 +#: pg_dump.c:1093 pg_dumpall.c:635 pg_restore.c:452 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_dump.c:1058 +#: pg_dump.c:1094 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: pg_dump.c:1060 pg_dumpall.c:633 pg_restore.c:436 +#: pg_dump.c:1096 pg_dumpall.c:638 pg_restore.c:455 #, c-format msgid "\n" "General options:\n" msgstr "\n" "Основні налаштування:\n" -#: pg_dump.c:1061 +#: pg_dump.c:1097 #, c-format msgid " -f, --file=FILENAME output file or directory name\n" msgstr " -f, --file=FILENAME ім'я файлу виводу або каталогу\n" -#: pg_dump.c:1062 +#: pg_dump.c:1098 #, c-format msgid " -F, --format=c|d|t|p output file format (custom, directory, tar,\n" " plain text (default))\n" msgstr " -F, --format=c|d|t|p формат файлу виводу (спеціальний, каталог, tar,\n" " звичайний текст (за замовчуванням))\n" -#: pg_dump.c:1064 +#: pg_dump.c:1100 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to dump\n" msgstr " -j, --jobs=NUM використовувати ці паралельні завдання для вивантаження\n" -#: pg_dump.c:1065 pg_dumpall.c:635 +#: pg_dump.c:1101 pg_dumpall.c:640 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose детальний режим\n" -#: pg_dump.c:1066 pg_dumpall.c:636 +#: pg_dump.c:1102 pg_dumpall.c:641 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: pg_dump.c:1067 +#: pg_dump.c:1103 #, c-format msgid " -Z, --compress=METHOD[:DETAIL]\n" " compress as specified\n" msgstr " -Z, --compress=METHOD[:DETAIL]\n" " стискати як вказано\n" -#: pg_dump.c:1069 pg_dumpall.c:637 +#: pg_dump.c:1105 pg_dumpall.c:642 #, c-format msgid " --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n" msgstr " --lock-wait-timeout=TIMEOUT помилка після очікування TIMEOUT для блокування таблиці\n" -#: pg_dump.c:1070 pg_dumpall.c:664 +#: pg_dump.c:1106 pg_dumpall.c:670 #, c-format msgid " --no-sync do not wait for changes to be written safely to disk\n" msgstr " --no-sync не чекати безпечного збереження змін на диск\n" -#: pg_dump.c:1071 pg_dumpall.c:638 +#: pg_dump.c:1107 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод для синхронізації файлів на диск\n" + +#: pg_dump.c:1108 pg_dumpall.c:643 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: pg_dump.c:1073 pg_dumpall.c:639 +#: pg_dump.c:1110 pg_dumpall.c:644 #, c-format msgid "\n" "Options controlling the output content:\n" msgstr "\n" "Параметри, що керують вихідним вмістом:\n" -#: pg_dump.c:1074 pg_dumpall.c:640 +#: pg_dump.c:1111 pg_dumpall.c:645 #, c-format msgid " -a, --data-only dump only the data, not the schema\n" msgstr " -a, --data-only вивантажити лише дані, без схеми\n" -#: pg_dump.c:1075 +#: pg_dump.c:1112 #, c-format msgid " -b, --large-objects include large objects in dump\n" msgstr " -b, --large-objects включити у вивантаження великі об'єкти\n" -#: pg_dump.c:1076 +#: pg_dump.c:1113 #, c-format msgid " --blobs (same as --large-objects, deprecated)\n" msgstr " --blobs (те саме, що --large-objects, застарілий)\n" -#: pg_dump.c:1077 +#: pg_dump.c:1114 #, c-format msgid " -B, --no-large-objects exclude large objects in dump\n" msgstr " -b, --no-large-objects виключити з вивантаження великі об'єкти\n" -#: pg_dump.c:1078 +#: pg_dump.c:1115 #, c-format msgid " --no-blobs (same as --no-large-objects, deprecated)\n" msgstr " --no-blobs (те саме, що --no-large-objects, застарілий)\n" -#: pg_dump.c:1079 pg_restore.c:447 +#: pg_dump.c:1116 pg_restore.c:466 #, c-format msgid " -c, --clean clean (drop) database objects before recreating\n" msgstr " -c, --clean видалити об'єкти бази даних перед перед повторним створенням\n" -#: pg_dump.c:1080 +#: pg_dump.c:1117 #, c-format msgid " -C, --create include commands to create database in dump\n" msgstr " -C, --create включити у вивантаження команди для створення бази даних\n" -#: pg_dump.c:1081 +#: pg_dump.c:1118 #, c-format msgid " -e, --extension=PATTERN dump the specified extension(s) only\n" msgstr " -e, --extension=PATTERN вивантажити лише вказане(і) розширення\n" -#: pg_dump.c:1082 pg_dumpall.c:642 +#: pg_dump.c:1119 pg_dumpall.c:647 #, c-format msgid " -E, --encoding=ENCODING dump the data in encoding ENCODING\n" msgstr " -E, --encoding=ENCODING вивантажити дані в кодуванні ENCODING\n" -#: pg_dump.c:1083 +#: pg_dump.c:1120 #, c-format msgid " -n, --schema=PATTERN dump the specified schema(s) only\n" msgstr " -n, --schema=PATTERN вивантажити лише вказану схему(и)\n" -#: pg_dump.c:1084 +#: pg_dump.c:1121 #, c-format msgid " -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n" msgstr " -N, --exclude-schema=PATTERN НЕ вивантажувати вказану схему(и)\n" -#: pg_dump.c:1085 +#: pg_dump.c:1122 #, c-format msgid " -O, --no-owner skip restoration of object ownership in\n" " plain-text format\n" msgstr " -O, --no-owner пропускати відновлення володіння об'єктами\n" " при використанні текстового формату\n" -#: pg_dump.c:1087 pg_dumpall.c:646 +#: pg_dump.c:1124 pg_dumpall.c:651 #, c-format msgid " -s, --schema-only dump only the schema, no data\n" msgstr " -s, --schema-only вивантажити лише схему, без даних\n" -#: pg_dump.c:1088 +#: pg_dump.c:1125 #, c-format msgid " -S, --superuser=NAME superuser user name to use in plain-text format\n" msgstr " -S, --superuser=NAME ім'я користувача, яке буде використовуватись у звичайних текстових форматах\n" -#: pg_dump.c:1089 +#: pg_dump.c:1126 #, c-format msgid " -t, --table=PATTERN dump only the specified table(s)\n" msgstr " -t, --table=PATTERN вивантажити лише вказані таблиці\n" -#: pg_dump.c:1090 +#: pg_dump.c:1127 #, c-format msgid " -T, --exclude-table=PATTERN do NOT dump the specified table(s)\n" msgstr " -T, --exclude-table=PATTERN НЕ вивантажувати вказані таблиці\n" -#: pg_dump.c:1091 pg_dumpall.c:649 +#: pg_dump.c:1128 pg_dumpall.c:654 #, c-format msgid " -x, --no-privileges do not dump privileges (grant/revoke)\n" msgstr " -x, --no-privileges не вивантажувати права (надання/відкликання)\n" -#: pg_dump.c:1092 pg_dumpall.c:650 +#: pg_dump.c:1129 pg_dumpall.c:655 #, c-format msgid " --binary-upgrade for use by upgrade utilities only\n" msgstr " --binary-upgrade для використання лише утилітами оновлення\n" -#: pg_dump.c:1093 pg_dumpall.c:651 +#: pg_dump.c:1130 pg_dumpall.c:656 #, c-format msgid " --column-inserts dump data as INSERT commands with column names\n" msgstr " --column-inserts вивантажити дані у вигляді команд INSERT з іменами стовпців\n" -#: pg_dump.c:1094 pg_dumpall.c:652 +#: pg_dump.c:1131 pg_dumpall.c:657 #, c-format msgid " --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n" msgstr " --disable-dollar-quoting вимкнути цінову пропозицію $, використовувати SQL стандартну цінову пропозицію\n" -#: pg_dump.c:1095 pg_dumpall.c:653 pg_restore.c:464 +#: pg_dump.c:1132 pg_dumpall.c:658 pg_restore.c:483 #, c-format msgid " --disable-triggers disable triggers during data-only restore\n" msgstr " --disable-triggers вимкнути тригери лише під час відновлення даних\n" -#: pg_dump.c:1096 +#: pg_dump.c:1133 #, c-format msgid " --enable-row-security enable row security (dump only content user has\n" " access to)\n" msgstr " --enable-row-security активувати захист на рівні рядків (вивантажити лише той вміст, до якого\n" " користувач має доступ)\n" -#: pg_dump.c:1098 +#: pg_dump.c:1135 +#, c-format +msgid " --exclude-extension=PATTERN do NOT dump the specified extension(s)\n" +msgstr " --exclude-extension=PATTERN НЕ вивантажувати вказане розширення\n" + +#: pg_dump.c:1136 #, c-format msgid " --exclude-table-and-children=PATTERN\n" " do NOT dump the specified table(s), including\n" @@ -1630,12 +1768,12 @@ msgstr " --exclude-table-and-children=PATTERN\n" " не вивантажувати зазначені таблиці, включно\n" " з дочірніми та секціонованими таблицями\n" -#: pg_dump.c:1101 +#: pg_dump.c:1139 #, c-format msgid " --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n" msgstr " --exclude-table-data=PATTERN НЕ вивантажувати дані вказаних таблиць\n" -#: pg_dump.c:1102 +#: pg_dump.c:1140 #, c-format msgid " --exclude-table-data-and-children=PATTERN\n" " do NOT dump data for the specified table(s),\n" @@ -1644,17 +1782,24 @@ msgstr " --exclude-table-data-and-children=PATTERN\n" " не вивантажувати дані зазначених таблиць,\n" " включно з дочірніми та секціонованими таблицями\n" -#: pg_dump.c:1105 pg_dumpall.c:655 +#: pg_dump.c:1143 pg_dumpall.c:660 #, c-format msgid " --extra-float-digits=NUM override default setting for extra_float_digits\n" msgstr " --extra-float-digits=NUM змінити параметр за замовчуванням для extra_float_digits\n" -#: pg_dump.c:1106 pg_dumpall.c:656 pg_restore.c:466 +#: pg_dump.c:1144 +#, c-format +msgid " --filter=FILENAME include or exclude objects and data from dump\n" +" based on expressions in FILENAME\n" +msgstr " --filter=FILENAME включати або виключати об'єкти та дані з дампу\n" +" на основі виразів у FILENAME\n" + +#: pg_dump.c:1146 pg_dumpall.c:662 pg_restore.c:487 #, c-format msgid " --if-exists use IF EXISTS when dropping objects\n" msgstr " --if-exists використовувати IF EXISTS під час видалення об'єктів\n" -#: pg_dump.c:1107 +#: pg_dump.c:1147 #, c-format msgid " --include-foreign-data=PATTERN\n" " include data of foreign tables on foreign\n" @@ -1663,101 +1808,101 @@ msgstr " --include-foreign-data=ШАБЛОН\n" " включають дані підлеглих таблиць на підлеглих\n" " сервери, що відповідають ШАБЛОНУ\n" -#: pg_dump.c:1110 pg_dumpall.c:657 +#: pg_dump.c:1150 pg_dumpall.c:663 #, c-format msgid " --inserts dump data as INSERT commands, rather than COPY\n" msgstr " --inserts вивантажити дані у вигляді команд INSERT, не COPY\n" -#: pg_dump.c:1111 pg_dumpall.c:658 +#: pg_dump.c:1151 pg_dumpall.c:664 #, c-format msgid " --load-via-partition-root load partitions via the root table\n" msgstr " --load-via-partition-root завантажувати секції через головну таблицю\n" -#: pg_dump.c:1112 pg_dumpall.c:659 +#: pg_dump.c:1152 pg_dumpall.c:665 #, c-format msgid " --no-comments do not dump comments\n" msgstr " --no-comments не вивантажувати коментарі\n" -#: pg_dump.c:1113 pg_dumpall.c:660 +#: pg_dump.c:1153 pg_dumpall.c:666 #, c-format msgid " --no-publications do not dump publications\n" msgstr " --no-publications не вивантажувати публікації\n" -#: pg_dump.c:1114 pg_dumpall.c:662 +#: pg_dump.c:1154 pg_dumpall.c:668 #, c-format msgid " --no-security-labels do not dump security label assignments\n" msgstr " --no-security-labels не вивантажувати завдання міток безпеки\n" -#: pg_dump.c:1115 pg_dumpall.c:663 +#: pg_dump.c:1155 pg_dumpall.c:669 #, c-format msgid " --no-subscriptions do not dump subscriptions\n" msgstr " --no-subscriptions не вивантажувати підписки\n" -#: pg_dump.c:1116 pg_dumpall.c:665 +#: pg_dump.c:1156 pg_dumpall.c:671 #, c-format msgid " --no-table-access-method do not dump table access methods\n" msgstr " --no-table-access-method не вивантажувати табличні методи доступу\n" -#: pg_dump.c:1117 pg_dumpall.c:666 +#: pg_dump.c:1157 pg_dumpall.c:672 #, c-format msgid " --no-tablespaces do not dump tablespace assignments\n" msgstr " --no-tablespaces не вивантажувати призначення табличних просторів\n" -#: pg_dump.c:1118 pg_dumpall.c:667 +#: pg_dump.c:1158 pg_dumpall.c:673 #, c-format msgid " --no-toast-compression do not dump TOAST compression methods\n" msgstr " --no-toast-compression не вивантажувати методи стиснення TOAST\n" -#: pg_dump.c:1119 pg_dumpall.c:668 +#: pg_dump.c:1159 pg_dumpall.c:674 #, c-format msgid " --no-unlogged-table-data do not dump unlogged table data\n" msgstr " --no-unlogged-table-data не вивантажувати дані таблиць, які не журналюються\n" -#: pg_dump.c:1120 pg_dumpall.c:669 +#: pg_dump.c:1160 pg_dumpall.c:675 #, c-format msgid " --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n" msgstr " --on-conflict-do-nothing додавати ON CONFLICT DO NOTHING до команди INSERT\n" -#: pg_dump.c:1121 pg_dumpall.c:670 +#: pg_dump.c:1161 pg_dumpall.c:676 #, c-format msgid " --quote-all-identifiers quote all identifiers, even if not key words\n" msgstr " --quote-all-identifiers укладати в лапки всі ідентифікатори, а не тільки ключові слова\n" -#: pg_dump.c:1122 pg_dumpall.c:671 +#: pg_dump.c:1162 pg_dumpall.c:677 #, c-format msgid " --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n" msgstr " --rows-per-insert=NROWS кількість рядків для INSERT; вимагає параметру --inserts\n" -#: pg_dump.c:1123 +#: pg_dump.c:1163 #, c-format msgid " --section=SECTION dump named section (pre-data, data, or post-data)\n" msgstr " --section=SECTION вивантажити вказану секцію (pre-data, data або post-data)\n" -#: pg_dump.c:1124 +#: pg_dump.c:1164 #, c-format msgid " --serializable-deferrable wait until the dump can run without anomalies\n" msgstr " --serializable-deferrable чекати коли вивантаження можна буде виконати без аномалій\n" -#: pg_dump.c:1125 +#: pg_dump.c:1165 #, c-format msgid " --snapshot=SNAPSHOT use given snapshot for the dump\n" msgstr " --snapshot=SNAPSHOT використовувати під час вивантаження вказаний знімок\n" -#: pg_dump.c:1126 pg_restore.c:476 +#: pg_dump.c:1166 pg_restore.c:497 #, c-format msgid " --strict-names require table and/or schema include patterns to\n" " match at least one entity each\n" msgstr " --strict-names потребувати, щоб при вказівці шаблону включення\n" " таблиці і/або схеми йому відповідав мінімум один об'єкт\n" -#: pg_dump.c:1128 +#: pg_dump.c:1168 #, c-format msgid " --table-and-children=PATTERN dump only the specified table(s), including\n" " child and partition tables\n" msgstr " --table-and-children=PATTERN вивантажувати лише зазначені таблиці,\n" " включно з дочірніми та секціонованими таблицями\n" -#: pg_dump.c:1130 pg_dumpall.c:672 pg_restore.c:478 +#: pg_dump.c:1170 pg_dumpall.c:678 pg_restore.c:500 #, c-format msgid " --use-set-session-authorization\n" " use SET SESSION AUTHORIZATION commands instead of\n" @@ -1766,49 +1911,49 @@ msgstr " --use-set-session-authorization\n" " щоб встановити власника, використати команди SET SESSION AUTHORIZATION,\n" " замість команд ALTER OWNER\n" -#: pg_dump.c:1134 pg_dumpall.c:676 pg_restore.c:482 +#: pg_dump.c:1174 pg_dumpall.c:682 pg_restore.c:504 #, c-format msgid "\n" "Connection options:\n" msgstr "\n" "Налаштування з'єднання:\n" -#: pg_dump.c:1135 +#: pg_dump.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to dump\n" msgstr " -d, --dbname=DBNAME ім'я бази даних для вивантаження\n" -#: pg_dump.c:1136 pg_dumpall.c:678 pg_restore.c:483 +#: pg_dump.c:1176 pg_dumpall.c:684 pg_restore.c:505 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME хост серверу баз даних або каталог сокетів\n" -#: pg_dump.c:1137 pg_dumpall.c:680 pg_restore.c:484 +#: pg_dump.c:1177 pg_dumpall.c:686 pg_restore.c:506 #, c-format msgid " -p, --port=PORT database server port number\n" msgstr " -p, --port=PORT номер порту сервера бази даних\n" -#: pg_dump.c:1138 pg_dumpall.c:681 pg_restore.c:485 +#: pg_dump.c:1178 pg_dumpall.c:687 pg_restore.c:507 #, c-format msgid " -U, --username=NAME connect as specified database user\n" msgstr " -U, --username=NAME підключатись як вказаний користувач бази даних\n" -#: pg_dump.c:1139 pg_dumpall.c:682 pg_restore.c:486 +#: pg_dump.c:1179 pg_dumpall.c:688 pg_restore.c:508 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не запитувати пароль\n" -#: pg_dump.c:1140 pg_dumpall.c:683 pg_restore.c:487 +#: pg_dump.c:1180 pg_dumpall.c:689 pg_restore.c:509 #, c-format msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password запитувати пароль завжди (повинно траплятись автоматично)\n" -#: pg_dump.c:1141 pg_dumpall.c:684 +#: pg_dump.c:1181 pg_dumpall.c:690 #, c-format msgid " --role=ROLENAME do SET ROLE before dump\n" msgstr " --role=ROLENAME виконати SET ROLE до вивантаження\n" -#: pg_dump.c:1143 +#: pg_dump.c:1183 #, c-format msgid "\n" "If no database name is supplied, then the PGDATABASE environment\n" @@ -1816,234 +1961,239 @@ msgid "\n" msgstr "\n" "Якщо ім'я бази даних не вказано, тоді використовується значення змінної середовища PGDATABASE.\n\n" -#: pg_dump.c:1145 pg_dumpall.c:688 pg_restore.c:494 +#: pg_dump.c:1185 pg_dumpall.c:694 pg_restore.c:516 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Повідомляти про помилки на <%s>.\n" -#: pg_dump.c:1146 pg_dumpall.c:689 pg_restore.c:495 +#: pg_dump.c:1186 pg_dumpall.c:695 pg_restore.c:517 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_dump.c:1165 pg_dumpall.c:513 +#: pg_dump.c:1205 pg_dumpall.c:518 #, c-format msgid "invalid client encoding \"%s\" specified" msgstr "вказано неприпустиме клієнтське кодування \"%s\"" -#: pg_dump.c:1303 +#: pg_dump.c:1352 #, c-format msgid "parallel dumps from standby servers are not supported by this server version" msgstr "паралельні вивантаження для резервних серверів не підтримуються цією версію сервера" -#: pg_dump.c:1368 +#: pg_dump.c:1417 #, c-format msgid "invalid output format \"%s\" specified" msgstr "вказано неприпустимий формат виводу \"%s\"" -#: pg_dump.c:1409 pg_dump.c:1465 pg_dump.c:1518 pg_dumpall.c:1449 +#: pg_dump.c:1458 pg_dump.c:1514 pg_dump.c:1567 pg_dumpall.c:1467 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неправильне повне ім'я (забагато компонентів): %s" -#: pg_dump.c:1417 +#: pg_dump.c:1466 #, c-format msgid "no matching schemas were found for pattern \"%s\"" msgstr "не знайдено відповідних схем для візерунку \"%s\"" -#: pg_dump.c:1470 +#: pg_dump.c:1519 #, c-format msgid "no matching extensions were found for pattern \"%s\"" msgstr "не знайдено відповідних розширень для шаблону \"%s\"" -#: pg_dump.c:1523 +#: pg_dump.c:1572 #, c-format msgid "no matching foreign servers were found for pattern \"%s\"" msgstr "не знайдено відповідних підлеглих серверів для шаблону \"%s\"" -#: pg_dump.c:1594 +#: pg_dump.c:1643 #, c-format msgid "improper relation name (too many dotted names): %s" msgstr "неправильне ім'я зв'язку (забагато компонентів): %s" -#: pg_dump.c:1616 +#: pg_dump.c:1665 #, c-format msgid "no matching tables were found for pattern \"%s\"" msgstr "не знайдено відповідних таблиць для візерунку\"%s\"" -#: pg_dump.c:1643 +#: pg_dump.c:1692 #, c-format msgid "You are currently not connected to a database." msgstr "На даний момент ви від'єднанні від бази даних." -#: pg_dump.c:1646 +#: pg_dump.c:1695 #, c-format msgid "cross-database references are not implemented: %s" msgstr "міжбазові посилання не реалізовані: %s" -#: pg_dump.c:2079 +#: pg_dump.c:2154 #, c-format msgid "dumping contents of table \"%s.%s\"" msgstr "вивантажування змісту таблиці \"%s.%s\"" -#: pg_dump.c:2185 +#: pg_dump.c:2264 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed." msgstr "Помилка вивантажування змісту таблиці \"%s\": помилка в PQgetCopyData()." -#: pg_dump.c:2186 pg_dump.c:2196 +#: pg_dump.c:2265 pg_dump.c:2275 #, c-format msgid "Error message from server: %s" msgstr "Повідомлення про помилку від сервера: %s" -#: pg_dump.c:2187 pg_dump.c:2197 +#: pg_dump.c:2266 pg_dump.c:2276 #, c-format msgid "Command was: %s" msgstr "Команда була: %s" -#: pg_dump.c:2195 +#: pg_dump.c:2274 #, c-format msgid "Dumping the contents of table \"%s\" failed: PQgetResult() failed." msgstr "Помилка вивантажування змісту таблиці \"%s\": помилка в PQgetResult(). " -#: pg_dump.c:2277 +#: pg_dump.c:2365 #, c-format msgid "wrong number of fields retrieved from table \"%s\"" msgstr "неправильна кількість полів отриманих з таблиці \"%s\"" -#: pg_dump.c:2975 +#: pg_dump.c:3067 #, c-format msgid "saving database definition" msgstr "збереження визначення бази даних" -#: pg_dump.c:3080 +#: pg_dump.c:3176 #, c-format msgid "unrecognized locale provider: %s" msgstr "нерозпізнаний постачальник локалів: %s" -#: pg_dump.c:3431 +#: pg_dump.c:3537 #, c-format msgid "saving encoding = %s" msgstr "збереження кодування = %s" -#: pg_dump.c:3456 +#: pg_dump.c:3562 #, c-format -msgid "saving standard_conforming_strings = %s" -msgstr "збереження standard_conforming_strings = %s" +msgid "saving \"standard_conforming_strings = %s\"" +msgstr "збереження \"standard_conforming_strings = %s\"" -#: pg_dump.c:3495 +#: pg_dump.c:3601 #, c-format msgid "could not parse result of current_schemas()" msgstr "не вдалося проаналізувати результат current_schemas()" -#: pg_dump.c:3514 +#: pg_dump.c:3620 #, c-format -msgid "saving search_path = %s" -msgstr "збереження search_path = %s" +msgid "saving \"search_path = %s\"" +msgstr "збереження \"search_path = %s\"" -#: pg_dump.c:3551 +#: pg_dump.c:3656 #, c-format msgid "reading large objects" msgstr "читання великих об’єктів" -#: pg_dump.c:3689 +#: pg_dump.c:3877 #, c-format -msgid "saving large objects" -msgstr "збереження великих об’єктів" +msgid "saving large objects \"%s\"" +msgstr "збереження великих об’єктів \"%s\"" -#: pg_dump.c:3730 +#: pg_dump.c:3898 #, c-format msgid "error reading large object %u: %s" msgstr "помилка читання великих об’єктів %u: %s" -#: pg_dump.c:3836 +#: pg_dump.c:4001 #, c-format msgid "reading row-level security policies" msgstr "читання політик безпеки на рівні рядків" -#: pg_dump.c:3977 +#: pg_dump.c:4142 #, c-format msgid "unexpected policy command type: %c" msgstr "неочікуваний тип команди в політиці: %c" -#: pg_dump.c:4427 pg_dump.c:4771 pg_dump.c:11998 pg_dump.c:17908 -#: pg_dump.c:17910 pg_dump.c:18531 +#: pg_dump.c:4592 pg_dump.c:5150 pg_dump.c:12362 pg_dump.c:18247 +#: pg_dump.c:18249 pg_dump.c:18871 #, c-format msgid "could not parse %s array" msgstr "не вдалося аналізувати масив %s" -#: pg_dump.c:4616 +#: pg_dump.c:4806 #, c-format msgid "subscriptions not dumped because current user is not a superuser" msgstr "підписки не вивантажені через те, що чинний користувач не є суперкористувачем" -#: pg_dump.c:5163 +#: pg_dump.c:5012 +#, c-format +msgid "subscription with OID %u does not exist" +msgstr "підписки %u з OID не існує" + +#: pg_dump.c:5019 +#, c-format +msgid "failed sanity check, table with OID %u not found" +msgstr "помилка цілісності, таблиця з OID %u не знайдена" + +#: pg_dump.c:5582 #, c-format msgid "could not find parent extension for %s %s" msgstr "не вдалося знайти батьківський елемент для %s %s" -#: pg_dump.c:5308 +#: pg_dump.c:5727 #, c-format msgid "schema with OID %u does not exist" msgstr "схема з OID %u не існує" -#: pg_dump.c:6790 pg_dump.c:17172 +#: pg_dump.c:7209 pg_dump.c:17618 #, c-format msgid "failed sanity check, parent table with OID %u of sequence with OID %u not found" msgstr "помилка цілісності, за OID %u не вдалося знайти батьківську таблицю послідовності з OID %u" -#: pg_dump.c:6933 +#: pg_dump.c:7352 #, c-format msgid "failed sanity check, table OID %u appearing in pg_partitioned_table not found" msgstr "помилка цілісності, OID %u не знайдено в таблиці pg_partitioned_table" -#: pg_dump.c:7164 pg_dump.c:7431 pg_dump.c:7902 pg_dump.c:8566 pg_dump.c:8685 -#: pg_dump.c:8833 +#: pg_dump.c:7583 pg_dump.c:7857 pg_dump.c:8304 pg_dump.c:8918 pg_dump.c:9040 +#: pg_dump.c:9188 #, c-format msgid "unrecognized table OID %u" msgstr "нерозпізнаний OID таблиці %u" -#: pg_dump.c:7168 +#: pg_dump.c:7587 #, c-format msgid "unexpected index data for table \"%s\"" msgstr "неочікувані дані індексу для таблиці \"%s\"" -#: pg_dump.c:7663 +#: pg_dump.c:8089 #, c-format msgid "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found" msgstr "помилка цілісності, за OID %u не вдалося знайти батьківську таблицю для запису pg_rewrite з OID %u" -#: pg_dump.c:7954 -#, c-format -msgid "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)" -msgstr "запит не повернув ім'я цільової таблиці для тригера зовнішнього ключа \"%s\" в таблиці \"%s\" (OID цільової таблиці: %u)" - -#: pg_dump.c:8570 +#: pg_dump.c:8922 #, c-format msgid "unexpected column data for table \"%s\"" msgstr "неочікувані дані стовпця для таблиці \"%s\"" -#: pg_dump.c:8599 +#: pg_dump.c:8951 #, c-format msgid "invalid column numbering in table \"%s\"" msgstr "неприпустима нумерація стовпців у таблиці \"%s\"" -#: pg_dump.c:8647 +#: pg_dump.c:9002 #, c-format msgid "finding table default expressions" msgstr "пошук виразів за замовчуванням для таблиці" -#: pg_dump.c:8689 +#: pg_dump.c:9044 #, c-format msgid "invalid adnum value %d for table \"%s\"" msgstr "неприпустиме значення adnum %d для таблиці \"%s\"" -#: pg_dump.c:8783 +#: pg_dump.c:9138 #, c-format msgid "finding table check constraints" msgstr "пошук перевірочних обмежень таблиці" -#: pg_dump.c:8837 +#: pg_dump.c:9192 #, c-format msgid "expected %d check constraint on table \"%s\" but found %d" msgid_plural "expected %d check constraints on table \"%s\" but found %d" @@ -2052,172 +2202,178 @@ msgstr[1] "очікувалось %d обмеження-перевірки дл msgstr[2] "очікувалось %d обмежень-перевірок для таблиці \"%s\", але знайдено %d" msgstr[3] "очікувалось %d обмежень-перевірок для таблиці \"%s\", але знайдено %d" -#: pg_dump.c:8841 +#: pg_dump.c:9196 #, c-format msgid "The system catalogs might be corrupted." msgstr "Системні каталоги можуть бути пошкоджені." -#: pg_dump.c:9531 +#: pg_dump.c:9886 #, c-format msgid "role with OID %u does not exist" msgstr "роль з OID %u не існує" -#: pg_dump.c:9643 pg_dump.c:9672 +#: pg_dump.c:9998 pg_dump.c:10027 #, c-format msgid "unsupported pg_init_privs entry: %u %u %d" msgstr "непідтримуваний запис в pg_init_privs: %u %u %d" -#: pg_dump.c:10493 +#: pg_dump.c:10574 +#, c-format +msgid "missing metadata for large objects \"%s\"" +msgstr "відсутні метадані для великих об'єктів \"%s\"" + +#: pg_dump.c:10857 #, c-format msgid "typtype of data type \"%s\" appears to be invalid" msgstr "typtype типу даних \"%s\" має неприпустимий вигляд" -#: pg_dump.c:12067 +#: pg_dump.c:12431 #, c-format msgid "unrecognized provolatile value for function \"%s\"" msgstr "нерозпізнане значення provolatile для функції \"%s\"" -#: pg_dump.c:12117 pg_dump.c:13999 +#: pg_dump.c:12481 pg_dump.c:14377 #, c-format msgid "unrecognized proparallel value for function \"%s\"" msgstr "нерозпізнане значення proparallel для функції \"%s\"" -#: pg_dump.c:12247 pg_dump.c:12353 pg_dump.c:12360 +#: pg_dump.c:12611 pg_dump.c:12717 pg_dump.c:12724 #, c-format msgid "could not find function definition for function with OID %u" msgstr "не вдалося знайти визначення функції для функції з OID %u" -#: pg_dump.c:12286 +#: pg_dump.c:12650 #, c-format msgid "bogus value in pg_cast.castfunc or pg_cast.castmethod field" msgstr "неприпустиме значення в полі pg_cast.castfunc або pg_cast.castmethod" -#: pg_dump.c:12289 +#: pg_dump.c:12653 #, c-format msgid "bogus value in pg_cast.castmethod field" msgstr "неприпустиме значення в полі pg_cast.castmethod" -#: pg_dump.c:12379 +#: pg_dump.c:12743 #, c-format msgid "bogus transform definition, at least one of trffromsql and trftosql should be nonzero" msgstr "неприпустиме визначення перетворення, як мінімум одне з trffromsql і trftosql повинно бути ненульовим" -#: pg_dump.c:12396 +#: pg_dump.c:12760 #, c-format msgid "bogus value in pg_transform.trffromsql field" msgstr "неприпустиме значення в полі pg_transform.trffromsql" -#: pg_dump.c:12417 +#: pg_dump.c:12781 #, c-format msgid "bogus value in pg_transform.trftosql field" msgstr "неприпустиме значення в полі pg_transform.trftosql" -#: pg_dump.c:12562 +#: pg_dump.c:12926 #, c-format msgid "postfix operators are not supported anymore (operator \"%s\")" msgstr "постфіксні оператори більше не підтримуються (оператор \"%s\")" -#: pg_dump.c:12732 +#: pg_dump.c:13096 #, c-format msgid "could not find operator with OID %s" msgstr "не вдалося знайти оператора з OID %s" -#: pg_dump.c:12800 +#: pg_dump.c:13164 #, c-format msgid "invalid type \"%c\" of access method \"%s\"" msgstr "неприпустимий тип \"%c\" методу доступу \"%s\"" -#: pg_dump.c:13469 pg_dump.c:13528 +#: pg_dump.c:13838 pg_dump.c:13906 #, c-format msgid "unrecognized collation provider: %s" msgstr "нерозпізнаний постачальник правил сортування: %s" -#: pg_dump.c:13478 pg_dump.c:13487 pg_dump.c:13497 pg_dump.c:13512 +#: pg_dump.c:13847 pg_dump.c:13854 pg_dump.c:13865 pg_dump.c:13875 +#: pg_dump.c:13890 #, c-format msgid "invalid collation \"%s\"" msgstr "неприпустиме правило сортування \"%s\"" -#: pg_dump.c:13918 +#: pg_dump.c:14296 #, c-format msgid "unrecognized aggfinalmodify value for aggregate \"%s\"" msgstr "нерозпізнане значення aggfinalmodify для агрегату \"%s\"" -#: pg_dump.c:13974 +#: pg_dump.c:14352 #, c-format msgid "unrecognized aggmfinalmodify value for aggregate \"%s\"" msgstr "нерозпізнане значення aggmfinalmodify для агрегату \"%s\"" -#: pg_dump.c:14691 +#: pg_dump.c:15069 #, c-format msgid "unrecognized object type in default privileges: %d" msgstr "нерозпізнаний тип об’єкта у стандартному праві: %d" -#: pg_dump.c:14707 +#: pg_dump.c:15085 #, c-format msgid "could not parse default ACL list (%s)" msgstr "не вдалося проаналізувати стандартний ACL список (%s)" -#: pg_dump.c:14789 +#: pg_dump.c:15169 #, c-format msgid "could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "не вдалося аналізувати початковий список ACL (%s) або за замовченням (%s) для об'єкта \"%s\" (%s)" -#: pg_dump.c:14814 +#: pg_dump.c:15194 #, c-format msgid "could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)" msgstr "не вдалося аналізувати список ACL (%s) або за замовчуванням (%s) для об'єкту \"%s\" (%s)" -#: pg_dump.c:15355 +#: pg_dump.c:15737 #, c-format msgid "query to obtain definition of view \"%s\" returned no data" msgstr "запит на отримання визначення перегляду \"%s\" не повернув дані" -#: pg_dump.c:15358 +#: pg_dump.c:15740 #, c-format msgid "query to obtain definition of view \"%s\" returned more than one definition" msgstr "запит на отримання визначення перегляду \"%s\" повернув більше, ніж одне визначення" -#: pg_dump.c:15365 +#: pg_dump.c:15747 #, c-format msgid "definition of view \"%s\" appears to be empty (length zero)" msgstr "визначення перегляду \"%s\" пусте (довжина нуль)" -#: pg_dump.c:15449 +#: pg_dump.c:15832 #, c-format msgid "WITH OIDS is not supported anymore (table \"%s\")" msgstr "WITH OIDS більше не підтримується (таблиця\"%s\")" -#: pg_dump.c:16373 +#: pg_dump.c:16819 #, c-format msgid "invalid column number %d for table \"%s\"" msgstr "неприпустиме число стовпців %d для таблиці \"%s\"" -#: pg_dump.c:16451 +#: pg_dump.c:16897 #, c-format msgid "could not parse index statistic columns" msgstr "не вдалося проаналізувати стовпці статистики індексів" -#: pg_dump.c:16453 +#: pg_dump.c:16899 #, c-format msgid "could not parse index statistic values" msgstr "не вдалося проаналізувати значення статистики індексів" -#: pg_dump.c:16455 +#: pg_dump.c:16901 #, c-format msgid "mismatched number of columns and values for index statistics" msgstr "невідповідна кількість стовпців і значень для статистики індексів" -#: pg_dump.c:16671 +#: pg_dump.c:17116 #, c-format msgid "missing index for constraint \"%s\"" msgstr "пропущено індекс для обмеження \"%s\"" -#: pg_dump.c:16906 +#: pg_dump.c:17351 #, c-format msgid "unrecognized constraint type: %c" msgstr "нерозпізнаний тип обмеження: %c" -#: pg_dump.c:17007 pg_dump.c:17236 +#: pg_dump.c:17452 pg_dump.c:17682 #, c-format msgid "query to get data of sequence \"%s\" returned %d row (expected 1)" msgid_plural "query to get data of sequence \"%s\" returned %d rows (expected 1)" @@ -2226,67 +2382,63 @@ msgstr[1] "запит на отримання даних послідовнос msgstr[2] "запит на отримання даних послідовності \"%s\" повернув %d рядків (очікувалося 1)" msgstr[3] "запит на отримання даних послідовності \"%s\" повернув %d рядків (очікувалося 1)" -#: pg_dump.c:17039 +#: pg_dump.c:17484 #, c-format msgid "unrecognized sequence type: %s" msgstr "нерозпізнаний тип послідовності: %s" -#: pg_dump.c:17328 -#, c-format -msgid "unexpected tgtype value: %d" -msgstr "неочікуване значення tgtype: %d" - -#: pg_dump.c:17400 -#, c-format -msgid "invalid argument string (%s) for trigger \"%s\" on table \"%s\"" -msgstr "неприпустимий рядок аргументу (%s) для тригера \"%s\" у таблиці \"%s\"" - -#: pg_dump.c:17669 +#: pg_dump.c:17999 #, c-format msgid "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned" msgstr "помилка запиту на отримання правила \"%s\" для таблиці \"%s\": повернено неправильне число рядків " -#: pg_dump.c:17822 +#: pg_dump.c:18152 #, c-format msgid "could not find referenced extension %u" msgstr "не вдалося знайти згадане розширення %u" -#: pg_dump.c:17912 +#: pg_dump.c:18251 #, c-format msgid "mismatched number of configurations and conditions for extension" msgstr "невідповідна кількість конфігурацій і умов для розширення" -#: pg_dump.c:18044 +#: pg_dump.c:18383 #, c-format msgid "reading dependency data" msgstr "читання даних залежності" -#: pg_dump.c:18130 +#: pg_dump.c:18469 #, c-format msgid "no referencing object %u %u" msgstr "немає об’єкту посилання %u %u" -#: pg_dump.c:18141 +#: pg_dump.c:18480 #, c-format msgid "no referenced object %u %u" msgstr "немає посилання на об'єкт %u %u" -#: pg_dump_sort.c:422 +#: pg_dump.c:18905 pg_dump.c:18943 pg_dumpall.c:1962 pg_restore.c:551 +#: pg_restore.c:597 +#, c-format +msgid "%s filter for \"%s\" is not allowed" +msgstr "фільтр %s для \"%s\" не дозволений" + +#: pg_dump_sort.c:424 #, c-format msgid "invalid dumpId %d" msgstr "неприпустимий dumpId %d" -#: pg_dump_sort.c:428 +#: pg_dump_sort.c:430 #, c-format msgid "invalid dependency %d" msgstr "неприпустима залежність %d" -#: pg_dump_sort.c:661 +#: pg_dump_sort.c:594 #, c-format msgid "could not identify dependency loop" msgstr "не вдалося ідентифікувати цикл залежності" -#: pg_dump_sort.c:1276 +#: pg_dump_sort.c:1209 #, c-format msgid "there are circular foreign-key constraints on this table:" msgid_plural "there are circular foreign-key constraints among these tables:" @@ -2295,129 +2447,134 @@ msgstr[1] "у наступних таблицях зациклені зовні msgstr[2] "у наступних таблицях зациклені зовнішні ключі:" msgstr[3] "у наступних таблицях зациклені зовнішні ключі:" -#: pg_dump_sort.c:1281 +#: pg_dump_sort.c:1214 #, c-format msgid "You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints." msgstr "Ви не зможете відновити дамп без використання --disable-triggers або тимчасово розірвати обмеження." -#: pg_dump_sort.c:1282 +#: pg_dump_sort.c:1215 #, c-format msgid "Consider using a full dump instead of a --data-only dump to avoid this problem." msgstr "Можливо, використання повного вивантажування замість --data-only вивантажування допоможе уникнути цієї проблеми." -#: pg_dump_sort.c:1294 +#: pg_dump_sort.c:1227 #, c-format msgid "could not resolve dependency loop among these items:" msgstr "не вдалося вирішити цикл залежності серед цих елементів:" -#: pg_dumpall.c:230 +#: pg_dumpall.c:231 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\"" -#: pg_dumpall.c:233 +#: pg_dumpall.c:234 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "програма \"%s\" знайдена для \"%s\", але має відмінну версію від %s" -#: pg_dumpall.c:382 +#: pg_dumpall.c:387 #, c-format msgid "option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only" msgstr "параметр --exclude-database не можна використовувати разом з -g/--globals-only, -r/--roles-only або -t/--tablespaces-only" -#: pg_dumpall.c:390 +#: pg_dumpall.c:395 #, c-format msgid "options -g/--globals-only and -r/--roles-only cannot be used together" msgstr "параметри -g/--globals-only і -r/--roles-only не можна використовувати разом" -#: pg_dumpall.c:397 +#: pg_dumpall.c:402 #, c-format msgid "options -g/--globals-only and -t/--tablespaces-only cannot be used together" msgstr "параметри -g/--globals-only і -t/--tablespaces-only не можна використовувати разом" -#: pg_dumpall.c:407 +#: pg_dumpall.c:412 #, c-format msgid "options -r/--roles-only and -t/--tablespaces-only cannot be used together" msgstr "параметри -r/--roles-only і -t/--tablespaces-only не можна використовувати разом" -#: pg_dumpall.c:469 pg_dumpall.c:1750 +#: pg_dumpall.c:474 pg_dumpall.c:1771 #, c-format msgid "could not connect to database \"%s\"" msgstr "не вдалося зв'язатися з базою даних \"%s\"" -#: pg_dumpall.c:481 +#: pg_dumpall.c:486 #, c-format msgid "could not connect to databases \"postgres\" or \"template1\"\n" "Please specify an alternative database." msgstr "не вдалося зв'язатися з базами даних \"postgres\" або \"template1\"\n" "Будь ласка, вкажіть альтернативну базу даних." -#: pg_dumpall.c:629 +#: pg_dumpall.c:634 #, c-format msgid "%s extracts a PostgreSQL database cluster into an SQL script file.\n\n" msgstr "%s експортує кластер баз даних PostgreSQL до SQL-скрипту.\n\n" -#: pg_dumpall.c:631 +#: pg_dumpall.c:636 #, c-format msgid " %s [OPTION]...\n" msgstr " %s: [OPTION]...\n" -#: pg_dumpall.c:634 +#: pg_dumpall.c:639 #, c-format msgid " -f, --file=FILENAME output file name\n" msgstr " -f, --file=FILENAME ім'я вихідного файлу\n" -#: pg_dumpall.c:641 +#: pg_dumpall.c:646 #, c-format msgid " -c, --clean clean (drop) databases before recreating\n" msgstr " -c, --clean очистити (видалити) бази даних перед відтворенням\n" -#: pg_dumpall.c:643 +#: pg_dumpall.c:648 #, c-format msgid " -g, --globals-only dump only global objects, no databases\n" msgstr " -g, --globals-only вивантажувати лише глобальні об’єкти, не бази даних\n" -#: pg_dumpall.c:644 pg_restore.c:456 +#: pg_dumpall.c:649 pg_restore.c:475 #, c-format msgid " -O, --no-owner skip restoration of object ownership\n" msgstr " -O, --no-owner пропускається відновлення форми власності об’єктом\n" -#: pg_dumpall.c:645 +#: pg_dumpall.c:650 #, c-format msgid " -r, --roles-only dump only roles, no databases or tablespaces\n" msgstr " -r, --roles-only вивантажувати лише ролі, не бази даних або табличні простори\n" -#: pg_dumpall.c:647 +#: pg_dumpall.c:652 #, c-format msgid " -S, --superuser=NAME superuser user name to use in the dump\n" msgstr " -S, --superuser=NAME ім'я суперкористувача для використання при вивантажуванні\n" -#: pg_dumpall.c:648 +#: pg_dumpall.c:653 #, c-format msgid " -t, --tablespaces-only dump only tablespaces, no databases or roles\n" msgstr " -t, --tablespaces-only вивантажувати лише табличні простори, не бази даних або ролі\n" -#: pg_dumpall.c:654 +#: pg_dumpall.c:659 #, c-format msgid " --exclude-database=PATTERN exclude databases whose name matches PATTERN\n" msgstr " --exclude-database=PATTERN виключити бази даних, ім'я яких відповідає PATTERN\n" #: pg_dumpall.c:661 #, c-format +msgid " --filter=FILENAME exclude databases based on expressions in FILENAME\n" +msgstr " --filter=FILENAME виключити бази даних, на основі виразів у FILENAME\n" + +#: pg_dumpall.c:667 +#, c-format msgid " --no-role-passwords do not dump passwords for roles\n" msgstr " --no-role-passwords не вивантажувати паролі для ролей\n" -#: pg_dumpall.c:677 +#: pg_dumpall.c:683 #, c-format msgid " -d, --dbname=CONNSTR connect using connection string\n" msgstr " -d, --dbname=CONNSTR підключення з використанням рядку підключення \n" -#: pg_dumpall.c:679 +#: pg_dumpall.c:685 #, c-format msgid " -l, --database=DBNAME alternative default database\n" msgstr " -l, --database=DBNAME альтернативна база даних за замовчуванням\n" -#: pg_dumpall.c:686 +#: pg_dumpall.c:692 #, c-format msgid "\n" "If -f/--file is not used, then the SQL script will be written to the standard\n" @@ -2425,277 +2582,298 @@ msgid "\n" msgstr "\n" "Якщо -f/--file не використовується, тоді SQL- сценарій буде записаний до стандартного виводу.\n\n" -#: pg_dumpall.c:828 +#: pg_dumpall.c:837 #, c-format msgid "role name starting with \"pg_\" skipped (%s)" msgstr "пропущено ім’я ролі, що починається з \"pg_\" (%s)" -#: pg_dumpall.c:1050 +#: pg_dumpall.c:1059 #, c-format msgid "could not find a legal dump ordering for memberships in role \"%s\"" msgstr "не вдалося знайти правильний порядок вивантаження членства в ролі \"%s\"" -#: pg_dumpall.c:1185 +#: pg_dumpall.c:1194 #, c-format msgid "could not parse ACL list (%s) for parameter \"%s\"" msgstr "не вдалося аналізувати список ACL (%s) для параметра \"%s\"" -#: pg_dumpall.c:1303 +#: pg_dumpall.c:1321 #, c-format msgid "could not parse ACL list (%s) for tablespace \"%s\"" msgstr "не вдалося аналізувати список ACL (%s) для табличного простору \"%s\"" -#: pg_dumpall.c:1510 +#: pg_dumpall.c:1528 #, c-format msgid "excluding database \"%s\"" msgstr "виключаємо базу даних \"%s\"" -#: pg_dumpall.c:1514 +#: pg_dumpall.c:1532 #, c-format msgid "dumping database \"%s\"" msgstr "вивантажуємо базу даних \"%s\"" -#: pg_dumpall.c:1545 +#: pg_dumpall.c:1563 #, c-format msgid "pg_dump failed on database \"%s\", exiting" msgstr "помилка pg_dump для бази даних \"%s\", завершення роботи" -#: pg_dumpall.c:1551 +#: pg_dumpall.c:1569 #, c-format msgid "could not re-open the output file \"%s\": %m" msgstr "не вдалося повторно відкрити файл виводу \"%s\": %m" -#: pg_dumpall.c:1592 +#: pg_dumpall.c:1613 #, c-format msgid "running \"%s\"" msgstr "виконується \"%s\"" -#: pg_dumpall.c:1793 +#: pg_dumpall.c:1814 #, c-format msgid "could not get server version" msgstr "не вдалося отримати версію серверу" -#: pg_dumpall.c:1796 +#: pg_dumpall.c:1817 #, c-format msgid "could not parse server version \"%s\"" msgstr "не вдалося аналізувати версію серверу \"%s\"" -#: pg_dumpall.c:1866 pg_dumpall.c:1889 +#: pg_dumpall.c:1887 pg_dumpall.c:1910 #, c-format msgid "executing %s" msgstr "виконується %s" -#: pg_restore.c:313 +#: pg_dumpall.c:1982 +msgid "unsupported filter object" +msgstr "непідтримуваний об'єкт фільтру" + +#: pg_restore.c:329 #, c-format msgid "one of -d/--dbname and -f/--file must be specified" msgstr "необхідно вказати один з -d/--dbname або -f/--file" -#: pg_restore.c:320 +#: pg_restore.c:336 #, c-format msgid "options -d/--dbname and -f/--file cannot be used together" msgstr "параметри -d/--dbname і -f/--file не можуть використовуватись разом" -#: pg_restore.c:338 +#: pg_restore.c:350 +#, c-format +msgid "options -1/--single-transaction and --transaction-size cannot be used together" +msgstr "параметри -1/--single-transaction і --transaction-size не можуть використовуватись разом" + +#: pg_restore.c:357 #, c-format msgid "options -C/--create and -1/--single-transaction cannot be used together" msgstr "параметри -C/--create і -1/--single-transaction не можуть використовуватись разом" -#: pg_restore.c:342 +#: pg_restore.c:361 #, c-format msgid "cannot specify both --single-transaction and multiple jobs" msgstr "параметр --single-transaction допускається лише з одним завданням" -#: pg_restore.c:380 +#: pg_restore.c:399 #, c-format msgid "unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" msgstr "нерозпізнаний формат архіву \"%s\"; будь ласка, вкажіть \"c\", \"d\" або \"t\"" -#: pg_restore.c:419 +#: pg_restore.c:438 #, c-format msgid "errors ignored on restore: %d" msgstr "при відновленні проігноровано помилок: %d" -#: pg_restore.c:432 +#: pg_restore.c:451 #, c-format msgid "%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" msgstr "%s відновлює базу даних PostgreSQL з архіву, створеного командою pg_dump.\n\n" -#: pg_restore.c:434 +#: pg_restore.c:453 #, c-format msgid " %s [OPTION]... [FILE]\n" msgstr " %s [OPTION]... [FILE]\n" -#: pg_restore.c:437 +#: pg_restore.c:456 #, c-format msgid " -d, --dbname=NAME connect to database name\n" msgstr " -d, --dbname=NAME підключитись до вказаної бази даних\n" -#: pg_restore.c:438 +#: pg_restore.c:457 #, c-format msgid " -f, --file=FILENAME output file name (- for stdout)\n" msgstr " -f, --file=FILENAME ім'я файлу виводу (- для stdout)\n" -#: pg_restore.c:439 +#: pg_restore.c:458 #, c-format msgid " -F, --format=c|d|t backup file format (should be automatic)\n" msgstr " -F, --format=c|d|t формат файлу резервної копії (розпізнається автоматично)\n" -#: pg_restore.c:440 +#: pg_restore.c:459 #, c-format msgid " -l, --list print summarized TOC of the archive\n" msgstr " -l, --list вивести короткий зміст архіву\n" -#: pg_restore.c:441 +#: pg_restore.c:460 #, c-format msgid " -v, --verbose verbose mode\n" msgstr " -v, --verbose детальний режим\n" -#: pg_restore.c:442 +#: pg_restore.c:461 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: pg_restore.c:443 +#: pg_restore.c:462 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: pg_restore.c:445 +#: pg_restore.c:464 #, c-format msgid "\n" "Options controlling the restore:\n" msgstr "\n" "Параметри, що керують відновленням:\n" -#: pg_restore.c:446 +#: pg_restore.c:465 #, c-format msgid " -a, --data-only restore only the data, no schema\n" msgstr " -a, --data-only відновити лише дані, без схеми\n" -#: pg_restore.c:448 +#: pg_restore.c:467 #, c-format msgid " -C, --create create the target database\n" msgstr " -C, --create створити цільову базу даних\n" -#: pg_restore.c:449 +#: pg_restore.c:468 #, c-format msgid " -e, --exit-on-error exit on error, default is to continue\n" msgstr " -e, --exit-on-error вийти при помилці, продовжувати за замовчуванням\n" -#: pg_restore.c:450 +#: pg_restore.c:469 #, c-format msgid " -I, --index=NAME restore named index\n" msgstr " -I, --index=NAME відновити вказаний індекс\n" -#: pg_restore.c:451 +#: pg_restore.c:470 #, c-format msgid " -j, --jobs=NUM use this many parallel jobs to restore\n" msgstr " -j, --jobs=NUM щоб виконати відновлення, використайте ці паралельні завдання\n" -#: pg_restore.c:452 +#: pg_restore.c:471 #, c-format msgid " -L, --use-list=FILENAME use table of contents from this file for\n" " selecting/ordering output\n" msgstr " -L, --use-list=FILENAME використовувати зміст з цього файлу для \n" " вибору/упорядкування даних\n" -#: pg_restore.c:454 +#: pg_restore.c:473 #, c-format msgid " -n, --schema=NAME restore only objects in this schema\n" msgstr " -n, --schema=NAME відновити об'єкти лише в цій схемі\n" -#: pg_restore.c:455 +#: pg_restore.c:474 #, c-format msgid " -N, --exclude-schema=NAME do not restore objects in this schema\n" msgstr " -N, --exclude-schema=NAME не відновлювати об'єкти в цій схемі\n" -#: pg_restore.c:457 +#: pg_restore.c:476 #, c-format msgid " -P, --function=NAME(args) restore named function\n" msgstr " -P, --function=NAME(args) відновити вказану функцію\n" -#: pg_restore.c:458 +#: pg_restore.c:477 #, c-format msgid " -s, --schema-only restore only the schema, no data\n" msgstr " -s, --schema-only відновити лише схему, без даних\n" -#: pg_restore.c:459 +#: pg_restore.c:478 #, c-format msgid " -S, --superuser=NAME superuser user name to use for disabling triggers\n" msgstr " -S, --superuser=NAME ім'я суперкористувача для вимкнення тригерів\n" -#: pg_restore.c:460 +#: pg_restore.c:479 #, c-format msgid " -t, --table=NAME restore named relation (table, view, etc.)\n" msgstr " -t, --table=NAME відновити вказане відношення (таблицю, подання і т. д.)\n" -#: pg_restore.c:461 +#: pg_restore.c:480 #, c-format msgid " -T, --trigger=NAME restore named trigger\n" msgstr " -T, --trigger=NAME відновити вказаний тригер\n" -#: pg_restore.c:462 +#: pg_restore.c:481 #, c-format msgid " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" msgstr " -x, --no-privileges пропустити відновлення прав доступу (grant/revoke)\n" -#: pg_restore.c:463 +#: pg_restore.c:482 #, c-format msgid " -1, --single-transaction restore as a single transaction\n" msgstr " -1, --single-transaction відновити в одній транзакції\n" -#: pg_restore.c:465 +#: pg_restore.c:484 #, c-format msgid " --enable-row-security enable row security\n" msgstr " --enable-row-security активувати захист на рівні рядків\n" -#: pg_restore.c:467 +#: pg_restore.c:485 +#, c-format +msgid " --filter=FILENAME restore or skip objects based on expressions\n" +" in FILENAME\n" +msgstr " --filter=FILENAME відновлювати або пропускати об'єкти на основі виразів\n" +" у FILENAME\n" + +#: pg_restore.c:488 #, c-format msgid " --no-comments do not restore comments\n" msgstr " --no-comments не відновлювати коментарі\n" -#: pg_restore.c:468 +#: pg_restore.c:489 #, c-format msgid " --no-data-for-failed-tables do not restore data of tables that could not be\n" " created\n" msgstr " --no-data-for-failed-tables не відновлювати дані таблиць, які не вдалося створити\n" -#: pg_restore.c:470 +#: pg_restore.c:491 #, c-format msgid " --no-publications do not restore publications\n" msgstr " --no-publications не відновлювати публікації \n" -#: pg_restore.c:471 +#: pg_restore.c:492 #, c-format msgid " --no-security-labels do not restore security labels\n" msgstr " --no-security-labels не відновлювати мітки безпеки \n" -#: pg_restore.c:472 +#: pg_restore.c:493 #, c-format msgid " --no-subscriptions do not restore subscriptions\n" msgstr " --no-subscriptions не відновлювати підписки\n" -#: pg_restore.c:473 +#: pg_restore.c:494 #, c-format msgid " --no-table-access-method do not restore table access methods\n" msgstr " --no-table-access-method не відновлювати табличний метод доступу\n" -#: pg_restore.c:474 +#: pg_restore.c:495 #, c-format msgid " --no-tablespaces do not restore tablespace assignments\n" msgstr " --no-tablespaces не відновлювати завдання табличного простору\n" -#: pg_restore.c:475 +#: pg_restore.c:496 #, c-format msgid " --section=SECTION restore named section (pre-data, data, or post-data)\n" msgstr " --section=SECTION відновлювати названий розділ (pre-data, data або post-data)\n" -#: pg_restore.c:488 +#: pg_restore.c:499 +#, c-format +msgid " --transaction-size=N commit after every N objects\n" +msgstr " --transaction-size=N затверджувати транзакцію після N об'єктів\n" + +#: pg_restore.c:510 #, c-format msgid " --role=ROLENAME do SET ROLE before restore\n" msgstr " --role=ROLENAME виконати SET ROLE перед відновленням\n" -#: pg_restore.c:490 +#: pg_restore.c:512 #, c-format msgid "\n" "The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" @@ -2704,7 +2882,7 @@ msgstr "\n" "Параметри -I, -n, -N, -P, -t, -T, і --section можна групувати і вказувати\n" "декілька разів для вибору декількох об'єктів.\n" -#: pg_restore.c:493 +#: pg_restore.c:515 #, c-format msgid "\n" "If no input file name is supplied, then standard input is used.\n\n" diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl index b9d13a0e1dee8..0be9f6dd538fd 100644 --- a/src/bin/pg_dump/t/001_basic.pl +++ b/src/bin/pg_dump/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -50,12 +50,30 @@ 'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together' ); +command_fails_like( + [ 'pg_dump', '-s', '--statistics-only' ], + qr/\Qpg_dump: error: options -s\/--schema-only and --statistics-only cannot be used together\E/, + 'pg_dump: error: options -s/--schema-only and --statistics-only cannot be used together' +); + +command_fails_like( + [ 'pg_dump', '-a', '--statistics-only' ], + qr/\Qpg_dump: error: options -a\/--data-only and --statistics-only cannot be used together\E/, + 'pg_dump: error: options -a/--data-only and --statistics-only cannot be used together' +); + command_fails_like( [ 'pg_dump', '-s', '--include-foreign-data=xxx' ], qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/, 'pg_dump: options -s/--schema-only and --include-foreign-data cannot be used together' ); +command_fails_like( + [ 'pg_dump', '--statistics-only', '--no-statistics' ], + qr/\Qpg_dump: error: options --statistics-only and --no-statistics cannot be used together\E/, + 'pg_dump: options --statistics-only and --no-statistics cannot be used together' +); + command_fails_like( [ 'pg_dump', '-j2', '--include-foreign-data=xxx' ], qr/\Qpg_dump: error: option --include-foreign-data is not supported with parallel backup\E/, @@ -219,6 +237,21 @@ 'pg_restore: options -C\/--create and -1\/--single-transaction cannot be used together' ); +command_fails_like( + [ 'pg_restore', '--exclude-database=foo', '--globals-only', '-d', 'xxx' ], + qr/\Qpg_restore: error: option --exclude-database cannot be used together with -g\/--globals-only\E/, + 'pg_restore: option --exclude-database cannot be used together with -g/--globals-only'); + +command_fails_like( + [ 'pg_restore', '--exclude-database=foo', '-d', 'xxx', 'dumpdir' ], + qr/\Qpg_restore: error: option --exclude-database can be used only when restoring an archive created by pg_dumpall\E/, + 'When option --exclude-database is used in pg_restore with dump of pg_dump'); + +command_fails_like( + [ 'pg_restore', '--globals-only', '-d', 'xxx', 'dumpdir' ], + qr/\Qpg_restore: error: option -g\/--globals-only can be used only when restoring an archive created by pg_dumpall\E/, + 'When option --globals-only is not used in pg_restore with dump of pg_dump'); + # also fails for -r and -t, but it seems pointless to add more tests for those. command_fails_like( [ 'pg_dumpall', '--exclude-database=foo', '--globals-only' ], @@ -226,4 +259,8 @@ 'pg_dumpall: option --exclude-database cannot be used together with -g/--globals-only' ); +command_fails_like( + [ 'pg_dumpall', '--format', 'x' ], + qr/\Qpg_dumpall: error: unrecognized output format "x";\E/, + 'pg_dumpall: unrecognized output format'); done_testing(); diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index d3dd8784d64d4..386e21e0c596a 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -61,18 +61,22 @@ my %pgdump_runs = ( binary_upgrade => { dump_cmd => [ - 'pg_dump', - '--no-sync', - '--format=custom', - "--file=$tempdir/binary_upgrade.dump", - '-w', - '--schema-only', + 'pg_dump', '--no-sync', + '--format' => 'custom', + '--file' => "$tempdir/binary_upgrade.dump", + '--no-password', + '--no-data', + '--sequence-data', '--binary-upgrade', - '-d', 'postgres', # alternative way to specify database + '--with-statistics', + '--dbname' => 'postgres', # alternative way to specify database ], restore_cmd => [ - 'pg_restore', '-Fc', '--verbose', - "--file=$tempdir/binary_upgrade.sql", + 'pg_restore', + '--format' => 'custom', + '--verbose', + '--file' => "$tempdir/binary_upgrade.sql", + '--with-statistics', "$tempdir/binary_upgrade.dump", ], }, @@ -82,18 +86,23 @@ test_key => 'compression', compile_option => 'gzip', dump_cmd => [ - 'pg_dump', '--format=custom', - '--compress=1', "--file=$tempdir/compression_gzip_custom.dump", + 'pg_dump', + '--format' => 'custom', + '--compress' => '1', + '--file' => "$tempdir/compression_gzip_custom.dump", + '--with-statistics', 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/compression_gzip_custom.sql", + '--file' => "$tempdir/compression_gzip_custom.sql", + '--with-statistics', "$tempdir/compression_gzip_custom.dump", ], command_like => { command => [ - 'pg_restore', '-l', "$tempdir/compression_gzip_custom.dump", + 'pg_restore', '--list', + "$tempdir/compression_gzip_custom.dump", ], expected => qr/Compression: gzip/, name => 'data content is gzip-compressed' @@ -105,9 +114,13 @@ test_key => 'compression', compile_option => 'gzip', dump_cmd => [ - 'pg_dump', '--jobs=2', - '--format=directory', '--compress=gzip:1', - "--file=$tempdir/compression_gzip_dir", 'postgres', + 'pg_dump', + '--jobs' => '2', + '--format' => 'directory', + '--compress' => 'gzip:1', + '--file' => "$tempdir/compression_gzip_dir", + '--with-statistics', + 'postgres', ], # Give coverage for manually compressed blobs.toc files during # restore. @@ -121,8 +134,10 @@ "$tempdir/compression_gzip_dir/*.dat.gz", ], restore_cmd => [ - 'pg_restore', '--jobs=2', - "--file=$tempdir/compression_gzip_dir.sql", + 'pg_restore', + '--jobs' => '2', + '--file' => "$tempdir/compression_gzip_dir.sql", + '--with-statistics', "$tempdir/compression_gzip_dir", ], }, @@ -131,8 +146,12 @@ test_key => 'compression', compile_option => 'gzip', dump_cmd => [ - 'pg_dump', '--format=plain', '-Z1', - "--file=$tempdir/compression_gzip_plain.sql.gz", 'postgres', + 'pg_dump', + '--format' => 'plain', + '--compress' => '1', + '--file' => "$tempdir/compression_gzip_plain.sql.gz", + '--with-statistics', + 'postgres', ], # Decompress the generated file to run through the tests. compress_cmd => { @@ -146,18 +165,24 @@ test_key => 'compression', compile_option => 'lz4', dump_cmd => [ - 'pg_dump', '--format=custom', - '--compress=lz4', "--file=$tempdir/compression_lz4_custom.dump", + 'pg_dump', + '--format' => 'custom', + '--compress' => 'lz4', + '--file' => "$tempdir/compression_lz4_custom.dump", + '--with-statistics', 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/compression_lz4_custom.sql", + '--file' => "$tempdir/compression_lz4_custom.sql", + '--with-statistics', "$tempdir/compression_lz4_custom.dump", ], command_like => { - command => - [ 'pg_restore', '-l', "$tempdir/compression_lz4_custom.dump", ], + command => [ + 'pg_restore', '--list', + "$tempdir/compression_lz4_custom.dump", + ], expected => qr/Compression: lz4/, name => 'data content is lz4 compressed' }, @@ -168,9 +193,13 @@ test_key => 'compression', compile_option => 'lz4', dump_cmd => [ - 'pg_dump', '--jobs=2', - '--format=directory', '--compress=lz4:1', - "--file=$tempdir/compression_lz4_dir", 'postgres', + 'pg_dump', + '--jobs' => '2', + '--format' => 'directory', + '--compress' => 'lz4:1', + '--file' => "$tempdir/compression_lz4_dir", + '--with-statistics', + 'postgres', ], # Verify that data files were compressed glob_patterns => [ @@ -178,8 +207,10 @@ "$tempdir/compression_lz4_dir/*.dat.lz4", ], restore_cmd => [ - 'pg_restore', '--jobs=2', - "--file=$tempdir/compression_lz4_dir.sql", + 'pg_restore', + '--jobs' => '2', + '--file' => "$tempdir/compression_lz4_dir.sql", + '--with-statistics', "$tempdir/compression_lz4_dir", ], }, @@ -188,8 +219,12 @@ test_key => 'compression', compile_option => 'lz4', dump_cmd => [ - 'pg_dump', '--format=plain', '--compress=lz4', - "--file=$tempdir/compression_lz4_plain.sql.lz4", 'postgres', + 'pg_dump', + '--format' => 'plain', + '--compress' => 'lz4', + '--file' => "$tempdir/compression_lz4_plain.sql.lz4", + '--with-statistics', + 'postgres', ], # Decompress the generated file to run through the tests. compress_cmd => { @@ -206,18 +241,23 @@ test_key => 'compression', compile_option => 'zstd', dump_cmd => [ - 'pg_dump', '--format=custom', - '--compress=zstd', "--file=$tempdir/compression_zstd_custom.dump", + 'pg_dump', + '--format' => 'custom', + '--compress' => 'zstd', + '--file' => "$tempdir/compression_zstd_custom.dump", + '--with-statistics', 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/compression_zstd_custom.sql", + '--file' => "$tempdir/compression_zstd_custom.sql", + '--with-statistics', "$tempdir/compression_zstd_custom.dump", ], command_like => { command => [ - 'pg_restore', '-l', "$tempdir/compression_zstd_custom.dump", + 'pg_restore', '--list', + "$tempdir/compression_zstd_custom.dump", ], expected => qr/Compression: zstd/, name => 'data content is zstd compressed' @@ -228,9 +268,13 @@ test_key => 'compression', compile_option => 'zstd', dump_cmd => [ - 'pg_dump', '--jobs=2', - '--format=directory', '--compress=zstd:1', - "--file=$tempdir/compression_zstd_dir", 'postgres', + 'pg_dump', + '--jobs' => '2', + '--format' => 'directory', + '--compress' => 'zstd:1', + '--file' => "$tempdir/compression_zstd_dir", + '--with-statistics', + 'postgres', ], # Give coverage for manually compressed blobs.toc files during # restore. @@ -247,8 +291,10 @@ "$tempdir/compression_zstd_dir/*.dat.zst", ], restore_cmd => [ - 'pg_restore', '--jobs=2', - "--file=$tempdir/compression_zstd_dir.sql", + 'pg_restore', + '--jobs' => '2', + '--file' => "$tempdir/compression_zstd_dir.sql", + '--with-statistics', "$tempdir/compression_zstd_dir", ], }, @@ -258,8 +304,12 @@ test_key => 'compression', compile_option => 'zstd', dump_cmd => [ - 'pg_dump', '--format=plain', '--compress=zstd:long', - "--file=$tempdir/compression_zstd_plain.sql.zst", 'postgres', + 'pg_dump', + '--format' => 'plain', + '--compress' => 'zstd:long', + '--file' => "$tempdir/compression_zstd_plain.sql.zst", + '--with-statistics', + 'postgres', ], # Decompress the generated file to run through the tests. compress_cmd => { @@ -274,81 +324,87 @@ clean => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/clean.sql", - '-c', - '-d', 'postgres', # alternative way to specify database + 'pg_dump', '--no-sync', + '--file' => "$tempdir/clean.sql", + '--clean', + '--with-statistics', + '--dbname' => 'postgres', # alternative way to specify database ], }, clean_if_exists => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/clean_if_exists.sql", - '-c', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/clean_if_exists.sql", + '--clean', '--if-exists', - '--encoding=UTF8', # no-op, just tests that option is accepted + '--encoding' => 'UTF8', # no-op, just for testing + '--with-statistics', 'postgres', ], }, column_inserts => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/column_inserts.sql", '-a', + '--file' => "$tempdir/column_inserts.sql", + '--data-only', '--column-inserts', 'postgres', ], }, createdb => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/createdb.sql", - '-C', - '-R', # no-op, just for testing - '-v', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/createdb.sql", + '--create', + '--no-reconnect', # no-op, just for testing + '--verbose', + '--with-statistics', 'postgres', ], }, data_only => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/data_only.sql", - '-a', - '--superuser=test_superuser', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/data_only.sql", + '--data-only', + '--superuser' => 'test_superuser', '--disable-triggers', - '-v', # no-op, just make sure it works + '--verbose', # no-op, just make sure it works 'postgres', ], }, defaults => { dump_cmd => [ 'pg_dump', '--no-sync', - '-f', "$tempdir/defaults.sql", + '--file' => "$tempdir/defaults.sql", + '--with-statistics', 'postgres', ], }, defaults_no_public => { database => 'regress_pg_dump_test', dump_cmd => [ - 'pg_dump', '--no-sync', '-f', "$tempdir/defaults_no_public.sql", + 'pg_dump', '--no-sync', + '--file' => "$tempdir/defaults_no_public.sql", + '--with-statistics', 'regress_pg_dump_test', ], }, defaults_no_public_clean => { database => 'regress_pg_dump_test', dump_cmd => [ - 'pg_dump', '--no-sync', '-c', '-f', - "$tempdir/defaults_no_public_clean.sql", + 'pg_dump', '--no-sync', + '--clean', + '--file' => "$tempdir/defaults_no_public_clean.sql", + '--with-statistics', 'regress_pg_dump_test', ], }, defaults_public_owner => { database => 'regress_public_owner', dump_cmd => [ - 'pg_dump', '--no-sync', '-f', - "$tempdir/defaults_public_owner.sql", + 'pg_dump', '--no-sync', + '--file' => "$tempdir/defaults_public_owner.sql", + '--with-statistics', 'regress_public_owner', ], }, @@ -360,17 +416,24 @@ defaults_custom_format => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '-Fc', - "--file=$tempdir/defaults_custom_format.dump", 'postgres', + 'pg_dump', + '--format' => 'custom', + '--file' => "$tempdir/defaults_custom_format.dump", + '--with-statistics', + 'postgres', ], restore_cmd => [ - 'pg_restore', '-Fc', - "--file=$tempdir/defaults_custom_format.sql", + 'pg_restore', + '--format' => 'custom', + '--file' => "$tempdir/defaults_custom_format.sql", + '--with-statistics', "$tempdir/defaults_custom_format.dump", ], command_like => { - command => - [ 'pg_restore', '-l', "$tempdir/defaults_custom_format.dump", ], + command => [ + 'pg_restore', '--list', + "$tempdir/defaults_custom_format.dump", + ], expected => $supports_gzip ? qr/Compression: gzip/ : qr/Compression: none/, @@ -385,17 +448,22 @@ defaults_dir_format => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '-Fd', - "--file=$tempdir/defaults_dir_format", 'postgres', + 'pg_dump', + '--format' => 'directory', + '--file' => "$tempdir/defaults_dir_format", + '--with-statistics', + 'postgres', ], restore_cmd => [ - 'pg_restore', '-Fd', - "--file=$tempdir/defaults_dir_format.sql", + 'pg_restore', + '--format' => 'directory', + '--file' => "$tempdir/defaults_dir_format.sql", + '--with-statistics', "$tempdir/defaults_dir_format", ], command_like => { command => - [ 'pg_restore', '-l', "$tempdir/defaults_dir_format", ], + [ 'pg_restore', '--list', "$tempdir/defaults_dir_format", ], expected => $supports_gzip ? qr/Compression: gzip/ : qr/Compression: none/, name => 'data content is gzip-compressed by default', @@ -412,12 +480,17 @@ defaults_parallel => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '-Fd', '-j2', "--file=$tempdir/defaults_parallel", + 'pg_dump', + '--format' => 'directory', + '--jobs' => 2, + '--file' => "$tempdir/defaults_parallel", + '--with-statistics', 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/defaults_parallel.sql", + '--file' => "$tempdir/defaults_parallel.sql", + '--with-statistics', "$tempdir/defaults_parallel", ], }, @@ -426,224 +499,319 @@ defaults_tar_format => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '-Ft', - "--file=$tempdir/defaults_tar_format.tar", 'postgres', + 'pg_dump', + '--format' => 'tar', + '--file' => "$tempdir/defaults_tar_format.tar", + '--with-statistics', + 'postgres', ], restore_cmd => [ 'pg_restore', - '--format=tar', - "--file=$tempdir/defaults_tar_format.sql", + '--format' => 'tar', + '--file' => "$tempdir/defaults_tar_format.sql", + '--with-statistics', "$tempdir/defaults_tar_format.tar", ], }, exclude_dump_test_schema => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/exclude_dump_test_schema.sql", - '--exclude-schema=dump_test', 'postgres', + '--file' => "$tempdir/exclude_dump_test_schema.sql", + '--exclude-schema' => 'dump_test', + '--with-statistics', + 'postgres', ], }, exclude_test_table => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/exclude_test_table.sql", - '--exclude-table=dump_test.test_table', 'postgres', + '--file' => "$tempdir/exclude_test_table.sql", + '--exclude-table' => 'dump_test.test_table', + '--with-statistics', + 'postgres', ], }, exclude_measurement => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/exclude_measurement.sql", - '--exclude-table-and-children=dump_test.measurement', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/exclude_measurement.sql", + '--exclude-table-and-children' => 'dump_test.measurement', + '--with-statistics', 'postgres', ], }, exclude_measurement_data => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/exclude_measurement_data.sql", - '--exclude-table-data-and-children=dump_test.measurement', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/exclude_measurement_data.sql", + '--exclude-table-data-and-children' => 'dump_test.measurement', '--no-unlogged-table-data', + '--with-statistics', 'postgres', ], }, exclude_test_table_data => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/exclude_test_table_data.sql", - '--exclude-table-data=dump_test.test_table', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/exclude_test_table_data.sql", + '--exclude-table-data' => 'dump_test.test_table', '--no-unlogged-table-data', + '--with-statistics', 'postgres', ], }, inserts => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/inserts.sql", '-a', + '--file' => "$tempdir/inserts.sql", + '--data-only', '--inserts', 'postgres', ], }, pg_dumpall_globals => { dump_cmd => [ - 'pg_dumpall', '-v', "--file=$tempdir/pg_dumpall_globals.sql", - '-g', '--no-sync', + 'pg_dumpall', + '--verbose', + '--file' => "$tempdir/pg_dumpall_globals.sql", + '--globals-only', + '--no-sync', + '--with-statistics', ], }, pg_dumpall_globals_clean => { dump_cmd => [ - 'pg_dumpall', "--file=$tempdir/pg_dumpall_globals_clean.sql", - '-g', '-c', '--no-sync', + 'pg_dumpall', + '--file' => "$tempdir/pg_dumpall_globals_clean.sql", + '--globals-only', + '--clean', + '--no-sync', + '--with-statistics', ], }, pg_dumpall_dbprivs => { dump_cmd => [ 'pg_dumpall', '--no-sync', - "--file=$tempdir/pg_dumpall_dbprivs.sql", + '--file' => "$tempdir/pg_dumpall_dbprivs.sql", + '--with-statistics', ], }, pg_dumpall_exclude => { dump_cmd => [ - 'pg_dumpall', '-v', "--file=$tempdir/pg_dumpall_exclude.sql", - '--exclude-database', '*dump_test*', '--no-sync', + 'pg_dumpall', + '--verbose', + '--file' => "$tempdir/pg_dumpall_exclude.sql", + '--exclude-database' => '*dump_test*', + '--no-sync', + '--with-statistics', ], }, no_toast_compression => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_toast_compression.sql", - '--no-toast-compression', 'postgres', + '--file' => "$tempdir/no_toast_compression.sql", + '--no-toast-compression', + '--with-statistics', + 'postgres', ], }, no_large_objects => { dump_cmd => [ - 'pg_dump', '--no-sync', "--file=$tempdir/no_large_objects.sql", - '-B', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/no_large_objects.sql", + '--no-large-objects', + '--with-statistics', + 'postgres', + ], + }, + no_policies => { + dump_cmd => [ + 'pg_dump', '--no-sync', + '--file' => "$tempdir/no_policies.sql", + '--no-policies', + '--with-statistics', + 'postgres', ], }, no_privs => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_privs.sql", '-x', + '--file' => "$tempdir/no_privs.sql", + '--no-privileges', + '--with-statistics', 'postgres', ], }, no_owner => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_owner.sql", '-O', + '--file' => "$tempdir/no_owner.sql", + '--no-owner', + '--with-statistics', 'postgres', ], }, no_table_access_method => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_table_access_method.sql", - '--no-table-access-method', 'postgres', + '--file' => "$tempdir/no_table_access_method.sql", + '--no-table-access-method', + '--with-statistics', + 'postgres', ], }, only_dump_test_schema => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/only_dump_test_schema.sql", - '--schema=dump_test', 'postgres', + '--file' => "$tempdir/only_dump_test_schema.sql", + '--schema' => 'dump_test', + '--with-statistics', + 'postgres', ], }, only_dump_test_table => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/only_dump_test_table.sql", - '--table=dump_test.test_table', - '--lock-wait-timeout=' - . (1000 * $PostgreSQL::Test::Utils::timeout_default), + 'pg_dump', '--no-sync', + '--file' => "$tempdir/only_dump_test_table.sql", + '--table' => 'dump_test.test_table', + '--lock-wait-timeout' => + (1000 * $PostgreSQL::Test::Utils::timeout_default), + '--with-statistics', 'postgres', ], }, only_dump_measurement => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/only_dump_measurement.sql", - '--table-and-children=dump_test.measurement', - '--lock-wait-timeout=' - . (1000 * $PostgreSQL::Test::Utils::timeout_default), + 'pg_dump', '--no-sync', + '--file' => "$tempdir/only_dump_measurement.sql", + '--table-and-children' => 'dump_test.measurement', + '--lock-wait-timeout' => + (1000 * $PostgreSQL::Test::Utils::timeout_default), + '--with-statistics', 'postgres', ], }, role => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/role.sql", - '--role=regress_dump_test_role', - '--schema=dump_test_second_schema', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/role.sql", + '--role' => 'regress_dump_test_role', + '--schema' => 'dump_test_second_schema', + '--with-statistics', 'postgres', ], }, role_parallel => { test_key => 'role', dump_cmd => [ - 'pg_dump', - '--no-sync', - '--format=directory', - '--jobs=2', - "--file=$tempdir/role_parallel", - '--role=regress_dump_test_role', - '--schema=dump_test_second_schema', + 'pg_dump', '--no-sync', + '--format' => 'directory', + '--jobs' => '2', + '--file' => "$tempdir/role_parallel", + '--role' => 'regress_dump_test_role', + '--schema' => 'dump_test_second_schema', + '--with-statistics', 'postgres', ], restore_cmd => [ - 'pg_restore', "--file=$tempdir/role_parallel.sql", + 'pg_restore', + '--file' => "$tempdir/role_parallel.sql", + '--with-statistics', "$tempdir/role_parallel", ], }, rows_per_insert => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/rows_per_insert.sql", - '-a', - '--rows-per-insert=4', - '--table=dump_test.test_table', - '--table=dump_test.test_fourth_table', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/rows_per_insert.sql", + '--data-only', + '--rows-per-insert' => '4', + '--table' => 'dump_test.test_table', + '--table' => 'dump_test.test_fourth_table', 'postgres', ], }, schema_only => { dump_cmd => [ - 'pg_dump', '--format=plain', - "--file=$tempdir/schema_only.sql", '--no-sync', - '-s', 'postgres', + 'pg_dump', '--no-sync', + '--format' => 'plain', + '--file' => "$tempdir/schema_only.sql", + '--schema-only', + 'postgres', ], }, section_pre_data => { dump_cmd => [ - 'pg_dump', "--file=$tempdir/section_pre_data.sql", - '--section=pre-data', '--no-sync', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/section_pre_data.sql", + '--section' => 'pre-data', + '--with-statistics', 'postgres', ], }, section_data => { dump_cmd => [ - 'pg_dump', "--file=$tempdir/section_data.sql", - '--section=data', '--no-sync', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/section_data.sql", + '--section' => 'data', + '--with-statistics', 'postgres', ], }, section_post_data => { dump_cmd => [ - 'pg_dump', "--file=$tempdir/section_post_data.sql", - '--section=post-data', '--no-sync', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/section_post_data.sql", + '--section' => 'post-data', + '--with-statistics', + 'postgres', ], }, test_schema_plus_large_objects => { dump_cmd => [ - 'pg_dump', "--file=$tempdir/test_schema_plus_large_objects.sql", - - '--schema=dump_test', '-b', '-B', '--no-sync', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/test_schema_plus_large_objects.sql", + '--schema' => 'dump_test', + '--large-objects', + '--no-large-objects', + '--with-statistics', + 'postgres', + ], + }, + no_statistics => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_statistics.sql", '--no-statistics', + 'postgres', + ], + }, + no_data_no_schema => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_data_no_schema.sql", '--no-data', + '--no-schema', 'postgres', + '--with-statistics', + ], + }, + statistics_only => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/statistics_only.sql", '--statistics-only', + 'postgres', + ], + }, + schema_only_with_statistics => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/schema_only_with_statistics.sql", + '--schema-only', '--with-statistics', 'postgres', + ], + }, + no_schema => { + dump_cmd => [ + 'pg_dump', '--no-sync', + "--file=$tempdir/no_schema.sql", '--no-schema', + '--with-statistics', + 'postgres', ], },); @@ -710,11 +878,14 @@ no_toast_compression => 1, no_large_objects => 1, no_owner => 1, + no_policies => 1, no_privs => 1, + no_statistics => 1, no_table_access_method => 1, pg_dumpall_dbprivs => 1, pg_dumpall_exclude => 1, - schema_only => 1,); + schema_only => 1, + schema_only_with_statistics => 1,); # This is where the actual tests are defined. my %tests = ( @@ -912,6 +1083,7 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, }, @@ -919,6 +1091,7 @@ no_large_objects => 1, no_owner => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -1004,6 +1177,114 @@ }, }, + 'CONSTRAINT NOT NULL / NOT VALID' => { + create_sql => 'CREATE TABLE dump_test.test_table_nn ( + col1 int); + CREATE TABLE dump_test.test_table_nn_2 ( + col1 int NOT NULL); + CREATE TABLE dump_test.test_table_nn_chld1 ( + ) INHERITS (dump_test.test_table_nn); + CREATE TABLE dump_test.test_table_nn_chld2 ( + col1 int + ) INHERITS (dump_test.test_table_nn); + CREATE TABLE dump_test.test_table_nn_chld3 ( + ) INHERITS (dump_test.test_table_nn, dump_test.test_table_nn_2); + ALTER TABLE dump_test.test_table_nn ADD CONSTRAINT nn NOT NULL col1 NOT VALID; + ALTER TABLE dump_test.test_table_nn_chld1 VALIDATE CONSTRAINT nn; + ALTER TABLE dump_test.test_table_nn_chld2 VALIDATE CONSTRAINT nn;', + regexp => qr/^ + \QALTER TABLE dump_test.test_table_nn\E \n^\s+ + \QADD CONSTRAINT nn NOT NULL col1 NOT VALID;\E + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + }, + }, + + 'CONSTRAINT NOT NULL / NOT VALID (child1)' => { + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_nn_chld1 (\E\n + ^\s+\QCONSTRAINT nn NOT NULL col1\E$ + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + binary_upgrade => 1, + }, + }, + + 'CONSTRAINT NOT NULL / NOT VALID (child2)' => { + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_nn_chld2 (\E\n + ^\s+\Qcol1 integer CONSTRAINT nn NOT NULL\E$ + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + }, + }, + + 'CONSTRAINT NOT NULL / NOT VALID (child3)' => { + regexp => qr/^ + \QCREATE TABLE dump_test.test_table_nn_chld3 (\E\n + ^\Q)\E$ + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + binary_upgrade => 1, + }, + }, + + 'CONSTRAINT PRIMARY KEY / WITHOUT OVERLAPS' => { + create_sql => 'CREATE TABLE dump_test.test_table_tpk ( + col1 int4range, + col2 tstzrange, + CONSTRAINT test_table_tpk_pkey PRIMARY KEY (col1, col2 WITHOUT OVERLAPS));', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table_tpk\E \n^\s+ + \QADD CONSTRAINT test_table_tpk_pkey PRIMARY KEY (col1, col2 WITHOUT OVERLAPS);\E + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + }, + }, + + 'CONSTRAINT UNIQUE / WITHOUT OVERLAPS' => { + create_sql => 'CREATE TABLE dump_test.test_table_tuq ( + col1 int4range, + col2 tstzrange, + CONSTRAINT test_table_tuq_uq UNIQUE (col1, col2 WITHOUT OVERLAPS));', + regexp => qr/^ + \QALTER TABLE ONLY dump_test.test_table_tuq\E \n^\s+ + \QADD CONSTRAINT test_table_tuq_uq UNIQUE (col1, col2 WITHOUT OVERLAPS);\E + /xm, + like => { + %full_runs, %dump_test_schema_runs, section_post_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + only_dump_measurement => 1, + }, + }, + 'ALTER TABLE (partitioned) ADD CONSTRAINT ... FOREIGN KEY' => { create_order => 4, create_sql => 'CREATE TABLE dump_test.test_table_fk ( @@ -1154,7 +1435,7 @@ 'ALTER FOREIGN TABLE foreign_table ALTER COLUMN c1 OPTIONS' => { regexp => qr/^ - \QALTER FOREIGN TABLE dump_test.foreign_table ALTER COLUMN c1 OPTIONS (\E\n + \QALTER FOREIGN TABLE ONLY dump_test.foreign_table ALTER COLUMN c1 OPTIONS (\E\n \s+\Qcolumn_name 'col1'\E\n \Q);\E\n /xm, @@ -1197,6 +1478,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -1289,11 +1571,13 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, }, unlike => { schema_only => 1, + schema_only_with_statistics => 1, no_large_objects => 1, }, }, @@ -1310,6 +1594,7 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, }, @@ -1317,6 +1602,7 @@ binary_upgrade => 1, no_large_objects => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -1331,6 +1617,7 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, }, @@ -1338,6 +1625,7 @@ binary_upgrade => 1, no_large_objects => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -1497,12 +1785,14 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, }, unlike => { no_large_objects => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -1650,6 +1940,7 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, only_dump_test_table => 1, section_data => 1, }, @@ -1659,6 +1950,7 @@ exclude_test_table => 1, exclude_test_table_data => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1677,12 +1969,14 @@ data_only => 1, exclude_test_table => 1, exclude_test_table_data => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1697,7 +1991,10 @@ \QCOPY dump_test.fk_reference_test_table (col1) FROM stdin;\E \n(?:\d\n){5}\\\.\n /xms, - like => { data_only => 1, }, + like => { + data_only => 1, + no_schema => 1, + }, }, 'COPY test_second_table' => { @@ -1713,12 +2010,14 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1735,12 +2034,14 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1758,12 +2059,14 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1780,12 +2083,14 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -1802,12 +2107,14 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, section_data => 1, }, unlike => { binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -2803,6 +3110,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2824,6 +3132,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2845,6 +3154,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2866,6 +3176,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2887,6 +3198,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2908,6 +3220,7 @@ unlike => { exclude_dump_test_schema => 1, exclude_test_table => 1, + no_policies => 1, only_dump_measurement => 1, }, }, @@ -2950,13 +3263,23 @@ like => { %full_runs, section_post_data => 1, }, }, + 'CREATE PUBLICATION pub5' => { + create_order => 50, + create_sql => + 'CREATE PUBLICATION pub5 WITH (publish_generated_columns = stored);', + regexp => qr/^ + \QCREATE PUBLICATION pub5 WITH (publish = 'insert, update, delete, truncate', publish_generated_columns = stored);\E + /xm, + like => { %full_runs, section_post_data => 1, }, + }, + 'CREATE SUBSCRIPTION sub1' => { create_order => 50, create_sql => 'CREATE SUBSCRIPTION sub1 CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 WITH (connect = false);', regexp => qr/^ - \QCREATE SUBSCRIPTION sub1 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub1');\E + \QCREATE SUBSCRIPTION sub1 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub1', streaming = parallel);\E /xm, like => { %full_runs, section_post_data => 1, }, }, @@ -2965,9 +3288,9 @@ create_order => 50, create_sql => 'CREATE SUBSCRIPTION sub2 CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 - WITH (connect = false, origin = none);', + WITH (connect = false, origin = none, streaming = off);', regexp => qr/^ - \QCREATE SUBSCRIPTION sub2 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub2', origin = none);\E + \QCREATE SUBSCRIPTION sub2 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub2', streaming = off, origin = none);\E /xm, like => { %full_runs, section_post_data => 1, }, }, @@ -2976,13 +3299,17 @@ create_order => 50, create_sql => 'CREATE SUBSCRIPTION sub3 CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 - WITH (connect = false, origin = any);', + WITH (connect = false, origin = any, streaming = on);', regexp => qr/^ - \QCREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub3');\E + \QCREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub3', streaming = on);\E /xm, like => { %full_runs, section_post_data => 1, }, }, + + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub1 ADD TABLE test_table' => { create_order => 51, create_sql => @@ -2991,12 +3318,11 @@ \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_table;\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { - exclude_dump_test_schema => 1, - exclude_test_table => 1, - }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub1 ADD TABLE test_second_table' => { create_order => 52, create_sql => @@ -3005,9 +3331,11 @@ \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_second_table;\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { exclude_dump_test_schema => 1, }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub1 ADD TABLE test_sixth_table (col3, col2)' => { create_order => 52, create_sql => @@ -3016,9 +3344,11 @@ \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_sixth_table (col2, col3);\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { exclude_dump_test_schema => 1, }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub1 ADD TABLE test_seventh_table (col3, col2) WHERE (col1 = 1)' => { create_order => 52, @@ -3028,9 +3358,11 @@ \QALTER PUBLICATION pub1 ADD TABLE ONLY dump_test.test_seventh_table (col2, col3) WHERE ((col1 = 1));\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { exclude_dump_test_schema => 1, }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub3 ADD TABLES IN SCHEMA dump_test' => { create_order => 51, create_sql => @@ -3039,9 +3371,11 @@ \QALTER PUBLICATION pub3 ADD TABLES IN SCHEMA dump_test;\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { exclude_dump_test_schema => 1, }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub3 ADD TABLES IN SCHEMA public' => { create_order => 52, create_sql => 'ALTER PUBLICATION pub3 ADD TABLES IN SCHEMA public;', @@ -3051,6 +3385,9 @@ like => { %full_runs, section_post_data => 1, }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub3 ADD TABLE test_table' => { create_order => 51, create_sql => @@ -3059,12 +3396,11 @@ \QALTER PUBLICATION pub3 ADD TABLE ONLY dump_test.test_table;\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { - exclude_dump_test_schema => 1, - exclude_test_table => 1, - }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub4 ADD TABLE test_table WHERE (col1 > 0);' => { create_order => 51, create_sql => @@ -3073,12 +3409,11 @@ \QALTER PUBLICATION pub4 ADD TABLE ONLY dump_test.test_table WHERE ((col1 > 0));\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { - exclude_dump_test_schema => 1, - exclude_test_table => 1, - }, }, + # Regardless of whether the table or schema is excluded, publications must + # still be dumped, as excluded objects do not apply to publications. We + # perform table and schema exclusion via full_runs. 'ALTER PUBLICATION pub4 ADD TABLE test_second_table WHERE (col2 = \'test\');' => { create_order => 52, @@ -3088,7 +3423,6 @@ \QALTER PUBLICATION pub4 ADD TABLE ONLY dump_test.test_second_table WHERE ((col2 = 'test'::text));\E /xm, like => { %full_runs, section_post_data => 1, }, - unlike => { exclude_dump_test_schema => 1, }, }, 'CREATE SCHEMA public' => { @@ -3188,6 +3522,7 @@ like => { %full_runs, data_only => 1, + no_schema => 1, section_data => 1, only_dump_test_schema => 1, test_schema_plus_large_objects => 1, @@ -3196,6 +3531,7 @@ binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -3304,8 +3640,8 @@ FOR VALUES FROM (\'2006-02-01\') TO (\'2006-03-01\');', regexp => qr/^ \QCREATE TABLE dump_test_second_schema.measurement_y2006m2 (\E\n - \s+\Qcity_id integer DEFAULT nextval('dump_test.measurement_city_id_seq'::regclass) NOT NULL,\E\n - \s+\Qlogdate date NOT NULL,\E\n + \s+\Qcity_id integer DEFAULT nextval('dump_test.measurement_city_id_seq'::regclass) CONSTRAINT measurement_city_id_not_null NOT NULL,\E\n + \s+\Qlogdate date CONSTRAINT measurement_logdate_not_null NOT NULL,\E\n \s+\Qpeaktemp integer,\E\n \s+\Qunitsales integer DEFAULT 0,\E\n \s+\QCONSTRAINT measurement_peaktemp_check CHECK ((peaktemp >= '-460'::integer)),\E\n @@ -3358,6 +3694,7 @@ %full_runs, %dump_test_schema_runs, data_only => 1, + no_schema => 1, only_dump_measurement => 1, section_data => 1, only_dump_test_schema => 1, @@ -3367,6 +3704,7 @@ unlike => { binary_upgrade => 1, schema_only => 1, + schema_only_with_statistics => 1, exclude_measurement => 1, only_dump_test_schema => 1, test_schema_plus_large_objects => 1, @@ -3595,12 +3933,14 @@ create_order => 3, create_sql => 'CREATE TABLE dump_test.test_table_generated ( col1 int primary key, - col2 int generated always as (col1 * 2) stored + col2 int generated always as (col1 * 2) stored, + col3 int generated always as (col1 * 3) virtual );', regexp => qr/^ \QCREATE TABLE dump_test.test_table_generated (\E\n \s+\Qcol1 integer NOT NULL,\E\n - \s+\Qcol2 integer GENERATED ALWAYS AS ((col1 * 2)) STORED\E\n + \s+\Qcol2 integer GENERATED ALWAYS AS ((col1 * 2)) STORED,\E\n + \s+\Qcol3 integer GENERATED ALWAYS AS ((col1 * 3))\E\n \); /xms, like => @@ -3713,7 +4053,7 @@ ) INHERITS (dump_test.test_inheritance_parent);', regexp => qr/^ \QCREATE TABLE dump_test.test_inheritance_child (\E\n - \s+\Qcol1 integer,\E\n + \s+\Qcol1 integer NOT NULL,\E\n \s+\QCONSTRAINT test_inheritance_child CHECK ((col2 >= 142857))\E\n \)\n \QINHERITS (dump_test.test_inheritance_parent);\E\n @@ -4240,6 +4580,7 @@ column_inserts => 1, data_only => 1, inserts => 1, + no_schema => 1, section_data => 1, test_schema_plus_large_objects => 1, binary_upgrade => 1, @@ -4248,6 +4589,7 @@ no_large_objects => 1, no_privs => 1, schema_only => 1, + schema_only_with_statistics => 1, }, }, @@ -4366,6 +4708,7 @@ binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -4382,6 +4725,7 @@ binary_upgrade => 1, exclude_dump_test_schema => 1, schema_only => 1, + schema_only_with_statistics => 1, only_dump_measurement => 1, }, }, @@ -4540,6 +4884,83 @@ }, }, + # + # TABLE and MATVIEW stats will end up in SECTION_DATA. + # INDEX stats (expression columns only) will end up in SECTION_POST_DATA. + # + 'statistics_import' => { + create_sql => ' + CREATE TABLE dump_test.has_stats + AS SELECT g.g AS x, g.g / 2 AS y FROM generate_series(1,100) AS g(g); + CREATE MATERIALIZED VIEW dump_test.has_stats_mv AS SELECT * FROM dump_test.has_stats; + CREATE INDEX """dump_test""\'s post-data index" ON dump_test.has_stats(x, (x - 1)); + ANALYZE dump_test.has_stats, dump_test.has_stats_mv;', + regexp => qr/^ + \QSELECT * FROM pg_catalog.pg_restore_relation_stats(\E\s+ + 'version',\s'\d+'::integer,\s+ + 'schemaname',\s'dump_test',\s+ + 'relname',\s'"dump_test"''s\ post-data\ index',\s+ + 'relpages',\s'\d+'::integer,\s+ + 'reltuples',\s'\d+'::real,\s+ + 'relallvisible',\s'\d+'::integer,\s+ + 'relallfrozen',\s'\d+'::integer\s+ + \);\s+ + \QSELECT * FROM pg_catalog.pg_restore_attribute_stats(\E\s+ + 'version',\s'\d+'::integer,\s+ + 'schemaname',\s'dump_test',\s+ + 'relname',\s'"dump_test"''s\ post-data\ index',\s+ + 'attnum',\s'2'::smallint,\s+ + 'inherited',\s'f'::boolean,\s+ + 'null_frac',\s'0'::real,\s+ + 'avg_width',\s'4'::integer,\s+ + 'n_distinct',\s'-1'::real,\s+ + 'histogram_bounds',\s'\{[0-9,]+\}'::text,\s+ + 'correlation',\s'1'::real\s+ + \);/xm, + like => { + %full_runs, + %dump_test_schema_runs, + no_data_no_schema => 1, + no_schema => 1, + section_post_data => 1, + statistics_only => 1, + schema_only_with_statistics => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + no_statistics => 1, + only_dump_measurement => 1, + schema_only => 1, + }, + }, + + # + # While attribute stats (aka pg_statistic stats) only appear for tables + # that have been analyzed, all tables will have relation stats because + # those come from pg_class. + # + 'relstats_on_unanalyzed_tables' => { + regexp => qr/pg_catalog.pg_restore_relation_stats/, + + like => { + %full_runs, + %dump_test_schema_runs, + no_data_no_schema => 1, + no_schema => 1, + only_dump_test_table => 1, + role => 1, + role_parallel => 1, + section_data => 1, + section_post_data => 1, + statistics_only => 1, + schema_only_with_statistics => 1, + }, + unlike => { + no_statistics => 1, + schema_only => 1, + }, + }, + # CREATE TABLE with partitioned table and various AMs. One # partition uses the same default as the parent, and a second # uses its own AM. @@ -4686,7 +5107,7 @@ # Test connecting to a non-existent database command_fails_like( - [ 'pg_dump', '-p', "$port", 'qqq' ], + [ 'pg_dump', '--port' => $port, 'qqq' ], qr/pg_dump: error: connection to server .* failed: FATAL: database "qqq" does not exist/, 'connecting to a non-existent database'); @@ -4694,7 +5115,7 @@ # Test connecting to an invalid database $node->command_fails_like( - [ 'pg_dump', '-d', 'regression_invalid' ], + [ 'pg_dump', '--dbname' => 'regression_invalid' ], qr/pg_dump: error: connection to server .* failed: FATAL: cannot connect to invalid database "regression_invalid"/, 'connecting to an invalid database'); @@ -4702,7 +5123,7 @@ # Test connecting with an unprivileged user command_fails_like( - [ 'pg_dump', '-p', "$port", '--role=regress_dump_test_role' ], + [ 'pg_dump', '--port' => $port, '--role' => 'regress_dump_test_role' ], qr/\Qpg_dump: error: query failed: ERROR: permission denied for\E/, 'connecting with an unprivileged user'); @@ -4710,22 +5131,32 @@ # Test dumping a non-existent schema, table, and patterns with --strict-names command_fails_like( - [ 'pg_dump', '-p', "$port", '-n', 'nonexistent' ], + [ 'pg_dump', '--port' => $port, '--schema' => 'nonexistent' ], qr/\Qpg_dump: error: no matching schemas were found\E/, 'dumping a non-existent schema'); command_fails_like( - [ 'pg_dump', '-p', "$port", '-t', 'nonexistent' ], + [ 'pg_dump', '--port' => $port, '--table' => 'nonexistent' ], qr/\Qpg_dump: error: no matching tables were found\E/, 'dumping a non-existent table'); command_fails_like( - [ 'pg_dump', '-p', "$port", '--strict-names', '-n', 'nonexistent*' ], + [ + 'pg_dump', + '--port' => $port, + '--strict-names', + '--schema' => 'nonexistent*' + ], qr/\Qpg_dump: error: no matching schemas were found for pattern\E/, 'no matching schemas'); command_fails_like( - [ 'pg_dump', '-p', "$port", '--strict-names', '-t', 'nonexistent*' ], + [ + 'pg_dump', + '--port' => $port, + '--strict-names', + '--table' => 'nonexistent*' + ], qr/\Qpg_dump: error: no matching tables were found for pattern\E/, 'no matching tables'); @@ -4733,26 +5164,31 @@ # Test invalid multipart database names $node->command_fails_like( - [ 'pg_dumpall', '--exclude-database', '.' ], + [ 'pg_dumpall', '--exclude-database' => '.' ], qr/pg_dumpall: error: improper qualified name \(too many dotted names\): \./, 'pg_dumpall: option --exclude-database rejects multipart pattern "."'); $node->command_fails_like( - [ 'pg_dumpall', '--exclude-database', 'myhost.mydb' ], + [ 'pg_dumpall', '--exclude-database' => 'myhost.mydb' ], qr/pg_dumpall: error: improper qualified name \(too many dotted names\): myhost\.mydb/, 'pg_dumpall: option --exclude-database rejects multipart database names'); ############################################################## # Test dumping pg_catalog (for research -- cannot be reloaded) -$node->command_ok([ 'pg_dump', '-p', "$port", '-n', 'pg_catalog' ], +$node->command_ok( + [ 'pg_dump', '--port' => $port, '--schema' => 'pg_catalog' ], 'pg_dump: option -n pg_catalog'); ######################################### # Test valid database exclusion patterns $node->command_ok( - [ 'pg_dumpall', '-p', "$port", '--exclude-database', '"myhost.mydb"' ], + [ + 'pg_dumpall', + '--port' => $port, + '--exclude-database' => '"myhost.mydb"' + ], 'pg_dumpall: option --exclude-database handles database names with embedded dots' ); @@ -4760,28 +5196,28 @@ # Test invalid multipart schema names $node->command_fails_like( - [ 'pg_dump', '--schema', 'myhost.mydb.myschema' ], + [ 'pg_dump', '--schema' => 'myhost.mydb.myschema' ], qr/pg_dump: error: improper qualified name \(too many dotted names\): myhost\.mydb\.myschema/, 'pg_dump: option --schema rejects three-part schema names'); $node->command_fails_like( - [ 'pg_dump', '--schema', 'otherdb.myschema' ], + [ 'pg_dump', '--schema' => 'otherdb.myschema' ], qr/pg_dump: error: cross-database references are not implemented: otherdb\.myschema/, 'pg_dump: option --schema rejects cross-database multipart schema names'); $node->command_fails_like( - [ 'pg_dump', '--schema', '.' ], + [ 'pg_dump', '--schema' => '.' ], qr/pg_dump: error: cross-database references are not implemented: \./, 'pg_dump: option --schema rejects degenerate two-part schema name: "."'); $node->command_fails_like( - [ 'pg_dump', '--schema', '"some.other.db".myschema' ], + [ 'pg_dump', '--schema' => '"some.other.db".myschema' ], qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.myschema/, 'pg_dump: option --schema rejects cross-database multipart schema names with embedded dots' ); $node->command_fails_like( - [ 'pg_dump', '--schema', '..' ], + [ 'pg_dump', '--schema' => '..' ], qr/pg_dump: error: improper qualified name \(too many dotted names\): \.\./, 'pg_dump: option --schema rejects degenerate three-part schema name: ".."' ); @@ -4790,19 +5226,20 @@ # Test invalid multipart relation names $node->command_fails_like( - [ 'pg_dump', '--table', 'myhost.mydb.myschema.mytable' ], + [ 'pg_dump', '--table' => 'myhost.mydb.myschema.mytable' ], qr/pg_dump: error: improper relation name \(too many dotted names\): myhost\.mydb\.myschema\.mytable/, 'pg_dump: option --table rejects four-part table names'); $node->command_fails_like( - [ 'pg_dump', '--table', 'otherdb.pg_catalog.pg_class' ], + [ 'pg_dump', '--table' => 'otherdb.pg_catalog.pg_class' ], qr/pg_dump: error: cross-database references are not implemented: otherdb\.pg_catalog\.pg_class/, 'pg_dump: option --table rejects cross-database three part table names'); command_fails_like( [ - 'pg_dump', '-p', "$port", '--table', - '"some.other.db".pg_catalog.pg_class' + 'pg_dump', + '--port' => $port, + '--table' => '"some.other.db".pg_catalog.pg_class' ], qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.pg_catalog\.pg_class/, 'pg_dump: option --table rejects cross-database three part table names with embedded dots' diff --git a/src/bin/pg_dump/t/003_pg_dump_with_server.pl b/src/bin/pg_dump/t/003_pg_dump_with_server.pl index 3f549f44e7598..8dc014ed6ed34 100644 --- a/src/bin/pg_dump/t/003_pg_dump_with_server.pl +++ b/src/bin/pg_dump/t/003_pg_dump_with_server.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -28,12 +28,23 @@ $node->safe_psql('postgres', "CREATE FOREIGN TABLE t1 (a int) SERVER s1"); command_fails_like( - [ "pg_dump", '-p', $port, '--include-foreign-data=s0', 'postgres' ], + [ + "pg_dump", + '--port' => $port, + '--include-foreign-data' => 's0', + 'postgres' + ], qr/foreign-data wrapper \"dummy\" has no handler\r?\npg_dump: detail: Query was: .*t0/, "correctly fails to dump a foreign table from a dummy FDW"); command_ok( - [ "pg_dump", '-p', $port, '-a', '--include-foreign-data=s2', 'postgres' ], + [ + "pg_dump", + '--port' => $port, + '--data-only', + '--include-foreign-data' => 's2', + 'postgres' + ], "dump foreign server with no tables"); done_testing(); diff --git a/src/bin/pg_dump/t/004_pg_dump_parallel.pl b/src/bin/pg_dump/t/004_pg_dump_parallel.pl index a36ba8cf54887..fcbe74ec8e981 100644 --- a/src/bin/pg_dump/t/004_pg_dump_parallel.pl +++ b/src/bin/pg_dump/t/004_pg_dump_parallel.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -48,33 +48,42 @@ $node->command_ok( [ - 'pg_dump', '-Fd', '--no-sync', '-j2', '-f', "$backupdir/dump1", - $node->connstr($dbname1) + 'pg_dump', + '--format' => 'directory', + '--no-sync', + '--jobs' => 2, + '--file' => "$backupdir/dump1", + $node->connstr($dbname1), ], 'parallel dump'); $node->command_ok( [ - 'pg_restore', '-v', - '-d', $node->connstr($dbname2), - '-j3', "$backupdir/dump1" + 'pg_restore', '--verbose', + '--dbname' => $node->connstr($dbname2), + '--jobs' => 3, + "$backupdir/dump1", ], 'parallel restore'); $node->command_ok( [ - 'pg_dump', '-Fd', - '--no-sync', '-j2', - '-f', "$backupdir/dump2", - '--inserts', $node->connstr($dbname1) + 'pg_dump', + '--format' => 'directory', + '--no-sync', + '--jobs' => 2, + '--file' => "$backupdir/dump2", + '--inserts', + $node->connstr($dbname1), ], 'parallel dump as inserts'); $node->command_ok( [ - 'pg_restore', '-v', - '-d', $node->connstr($dbname3), - '-j3', "$backupdir/dump2" + 'pg_restore', '--verbose', + '--dbname' => $node->connstr($dbname3), + '--jobs' => 3, + "$backupdir/dump2", ], 'parallel restore as inserts'); diff --git a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl index 6025bb296cc40..f05e8a20e0559 100644 --- a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl +++ b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -90,8 +90,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "filter file without patterns"); @@ -117,8 +120,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with filter patterns as well as comments and whitespace"); @@ -143,8 +149,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "filter file without patterns"); @@ -162,8 +171,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with exclusion of a single table"); @@ -183,8 +195,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with wildcard in pattern"); @@ -205,8 +220,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with multiline names requiring quoting"); @@ -223,8 +241,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with filter"); @@ -241,8 +262,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "exclude the public schema"); @@ -263,9 +287,12 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "--filter=$tempdir/inputfile2.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--filter' => "$tempdir/inputfile2.txt", + 'postgres' ], "exclude the public schema with multiple filters"); @@ -284,8 +311,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with filter"); @@ -301,8 +331,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump tables with filter"); @@ -321,8 +354,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/pg_dump: error: no matching foreign servers were found for pattern/, "dump nonexisting foreign server"); @@ -334,8 +370,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "dump foreign_data with filter"); @@ -350,8 +389,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/exclude filter for "foreign data" is not allowed/, "erroneously exclude foreign server"); @@ -367,8 +409,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/invalid filter command/, "invalid syntax: incorrect filter command"); @@ -381,8 +426,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/unsupported filter object type: "xxx"/, "invalid syntax: invalid object type specified, should be table, schema, foreign_data or data" @@ -396,8 +444,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/missing object name/, "invalid syntax: missing object identifier pattern"); @@ -410,8 +461,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/no matching tables were found/, "invalid syntax: extra content after object identifier pattern"); @@ -427,8 +481,10 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", '--strict-names', 'postgres' ], "strict names with matching pattern"); @@ -445,8 +501,10 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", '--strict-names', 'postgres' ], qr/no matching tables were found/, @@ -464,8 +522,10 @@ command_ok( [ - 'pg_dumpall', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_dumpall', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], "dump tables with exclusion of a database"); @@ -478,8 +538,10 @@ # --globals-only with exclusions command_fails_like( [ - 'pg_dumpall', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", + 'pg_dumpall', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", '--globals-only' ], qr/\Qpg_dumpall: error: option --exclude-database cannot be used together with -g\/--globals-only\E/, @@ -494,8 +556,10 @@ command_fails_like( [ - 'pg_dumpall', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_dumpall', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/invalid filter command/, "invalid syntax: incorrect filter command"); @@ -508,8 +572,10 @@ command_fails_like( [ - 'pg_dumpall', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_dumpall', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/unsupported filter object type: "xxx"/, "invalid syntax: exclusion of non-existing object type"); @@ -521,8 +587,10 @@ command_fails_like( [ - 'pg_dumpall', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_dumpall', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/pg_dumpall: error: invalid format in filter/, "invalid syntax: exclusion of unsupported object type"); @@ -532,8 +600,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', "$tempdir/filter_test.dump", - "-Fc", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => "$tempdir/filter_test.dump", + '--format' => 'custom', + 'postgres' ], "dump all tables"); @@ -544,9 +615,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore tables with filter"); @@ -563,8 +637,10 @@ command_fails_like( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/include filter for "table data" is not allowed/, "invalid syntax: inclusion of unallowed object"); @@ -576,8 +652,10 @@ command_fails_like( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/include filter for "extension" is not allowed/, "invalid syntax: inclusion of unallowed object"); @@ -589,8 +667,10 @@ command_fails_like( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/exclude filter for "extension" is not allowed/, "invalid syntax: exclusion of unallowed object"); @@ -602,8 +682,10 @@ command_fails_like( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt" ], qr/exclude filter for "table data" is not allowed/, "invalid syntax: exclusion of unallowed object"); @@ -613,8 +695,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', "$tempdir/filter_test.dump", - "-Fc", 'sourcedb' + 'pg_dump', + '--port' => $port, + '--file' => "$tempdir/filter_test.dump", + '--format' => 'custom', + 'sourcedb' ], "dump all objects from sourcedb"); @@ -625,9 +710,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore function with filter"); @@ -646,9 +734,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore function with filter"); @@ -667,9 +758,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore function with filter"); @@ -687,9 +781,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore function with filter"); @@ -707,9 +804,12 @@ command_ok( [ - 'pg_restore', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", - "-Fc", "$tempdir/filter_test.dump" + 'pg_restore', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + '--format' => 'custom', + "$tempdir/filter_test.dump" ], "restore function with filter"); @@ -733,8 +833,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "filter file without patterns"); @@ -750,8 +853,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "filter file without patterns"); @@ -768,8 +874,11 @@ command_ok( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], "filter file without patterns"); @@ -788,8 +897,11 @@ command_fails_like( [ - 'pg_dump', '-p', $port, '-f', $plainfile, - "--filter=$tempdir/inputfile.txt", 'postgres' + 'pg_dump', + '--port' => $port, + '--file' => $plainfile, + '--filter' => "$tempdir/inputfile.txt", + 'postgres' ], qr/pg_dump: error: no matching extensions were found/, "dump nonexisting extension"); diff --git a/src/bin/pg_dump/t/006_pg_dumpall.pl b/src/bin/pg_dump/t/006_pg_dumpall.pl new file mode 100644 index 0000000000000..0ea02a3a4a940 --- /dev/null +++ b/src/bin/pg_dump/t/006_pg_dumpall.pl @@ -0,0 +1,391 @@ +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $tempdir = PostgreSQL::Test::Utils::tempdir; +my $run_db = 'postgres'; +my $sep = $windows_os ? "\\" : "/"; + +# Tablespace locations used by "restore_tablespace" test case. +my $tablespace1 = "${tempdir}${sep}tbl1"; +my $tablespace2 = "${tempdir}${sep}tbl2"; +mkdir($tablespace1) || die "mkdir $tablespace1 $!"; +mkdir($tablespace2) || die "mkdir $tablespace2 $!"; + +# Scape tablespace locations on Windows. +$tablespace1 = $windows_os ? ($tablespace1 =~ s/\\/\\\\/gr) : $tablespace1; +$tablespace2 = $windows_os ? ($tablespace2 =~ s/\\/\\\\/gr) : $tablespace2; + +# Where pg_dumpall will be executed. +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->start; + + +############################################################### +# Definition of the pg_dumpall test cases to run. +# +# Each of these test cases are named and those names are used for fail +# reporting and also to save the dump and restore information needed for the +# test to assert. +# +# The "setup_sql" is a psql valid script that contains SQL commands to execute +# before of actually execute the tests. The setups are all executed before of +# any test execution. +# +# The "dump_cmd" and "restore_cmd" are the commands that will be executed. The +# "restore_cmd" must have the --file flag to save the restore output so that we +# can assert on it. +# +# The "like" and "unlike" is a regexp that is used to match the pg_restore +# output. It must have at least one of then filled per test cases but it also +# can have both. See "excluding_databases" test case for example. +my %pgdumpall_runs = ( + restore_roles => { + setup_sql => ' + CREATE ROLE dumpall WITH ENCRYPTED PASSWORD \'admin\' SUPERUSER; + CREATE ROLE dumpall2 WITH REPLICATION CONNECTION LIMIT 10;', + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--file' => "$tempdir/restore_roles", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'directory', + '--file' => "$tempdir/restore_roles.sql", + "$tempdir/restore_roles", + ], + like => qr/ + ^\s*\QCREATE ROLE dumpall;\E\s*\n + \s*\QALTER ROLE dumpall WITH SUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS PASSWORD 'SCRAM-SHA-256\E + [^']+';\s*\n + \s*\QCREATE ROLE dumpall2;\E + \s*\QALTER ROLE dumpall2 WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN REPLICATION NOBYPASSRLS CONNECTION LIMIT 10;\E + /xm + }, + + restore_tablespace => { + setup_sql => " + CREATE ROLE tap; + CREATE TABLESPACE tbl1 OWNER tap LOCATION '$tablespace1'; + CREATE TABLESPACE tbl2 OWNER tap LOCATION '$tablespace2' WITH (seq_page_cost=1.0);", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--file' => "$tempdir/restore_tablespace", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'directory', + '--file' => "$tempdir/restore_tablespace.sql", + "$tempdir/restore_tablespace", + ], + # Match "E" as optional since it is added on LOCATION when running on + # Windows. + like => qr/^ + \n\QCREATE TABLESPACE tbl1 OWNER tap LOCATION \E(?:E)?\Q'$tablespace1';\E + \n\QCREATE TABLESPACE tbl2 OWNER tap LOCATION \E(?:E)?\Q'$tablespace2';\E + \n\QALTER TABLESPACE tbl2 SET (seq_page_cost=1.0);\E + /xm, + }, + + restore_grants => { + setup_sql => " + CREATE DATABASE tapgrantsdb; + CREATE SCHEMA private; + CREATE SEQUENCE serial START 101; + CREATE FUNCTION fn() RETURNS void AS \$\$ + BEGIN + END; + \$\$ LANGUAGE plpgsql; + CREATE ROLE super; + CREATE ROLE grant1; + CREATE ROLE grant2; + CREATE ROLE grant3; + CREATE ROLE grant4; + CREATE ROLE grant5; + CREATE ROLE grant6; + CREATE ROLE grant7; + CREATE ROLE grant8; + + CREATE TABLE t (id int); + INSERT INTO t VALUES (1), (2), (3), (4); + + GRANT SELECT ON TABLE t TO grant1; + GRANT INSERT ON TABLE t TO grant2; + GRANT ALL PRIVILEGES ON TABLE t to grant3; + GRANT CONNECT, CREATE ON DATABASE tapgrantsdb TO grant4; + GRANT USAGE, CREATE ON SCHEMA private TO grant5; + GRANT USAGE, SELECT, UPDATE ON SEQUENCE serial TO grant6; + GRANT super TO grant7; + GRANT EXECUTE ON FUNCTION fn() TO grant8; + ", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--file' => "$tempdir/restore_grants", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'directory', + '--file' => "$tempdir/restore_grants.sql", + "$tempdir/restore_grants", + ], + like => qr/^ + \n\QGRANT super TO grant7 WITH INHERIT TRUE GRANTED BY\E + (.*\n)* + \n\QGRANT ALL ON SCHEMA private TO grant5;\E + (.*\n)* + \n\QGRANT ALL ON FUNCTION public.fn() TO grant8;\E + (.*\n)* + \n\QGRANT ALL ON SEQUENCE public.serial TO grant6;\E + (.*\n)* + \n\QGRANT SELECT ON TABLE public.t TO grant1;\E + \n\QGRANT INSERT ON TABLE public.t TO grant2;\E + \n\QGRANT ALL ON TABLE public.t TO grant3;\E + (.*\n)* + \n\QGRANT CREATE,CONNECT ON DATABASE tapgrantsdb TO grant4;\E + /xm, + }, + + excluding_databases => { + setup_sql => 'CREATE DATABASE db1; + \c db1 + CREATE TABLE t1 (id int); + INSERT INTO t1 VALUES (1), (2), (3), (4); + CREATE TABLE t2 (id int); + INSERT INTO t2 VALUES (1), (2), (3), (4); + + CREATE DATABASE db2; + \c db2 + CREATE TABLE t3 (id int); + INSERT INTO t3 VALUES (1), (2), (3), (4); + CREATE TABLE t4 (id int); + INSERT INTO t4 VALUES (1), (2), (3), (4); + + CREATE DATABASE dbex3; + \c dbex3 + CREATE TABLE t5 (id int); + INSERT INTO t5 VALUES (1), (2), (3), (4); + CREATE TABLE t6 (id int); + INSERT INTO t6 VALUES (1), (2), (3), (4); + + CREATE DATABASE dbex4; + \c dbex4 + CREATE TABLE t7 (id int); + INSERT INTO t7 VALUES (1), (2), (3), (4); + CREATE TABLE t8 (id int); + INSERT INTO t8 VALUES (1), (2), (3), (4); + + CREATE DATABASE db5; + \c db5 + CREATE TABLE t9 (id int); + INSERT INTO t9 VALUES (1), (2), (3), (4); + CREATE TABLE t10 (id int); + INSERT INTO t10 VALUES (1), (2), (3), (4); + ', + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--file' => "$tempdir/excluding_databases", + '--exclude-database' => 'dbex*', + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'directory', + '--file' => "$tempdir/excluding_databases.sql", + '--exclude-database' => 'db5', + "$tempdir/excluding_databases", + ], + like => qr/^ + \n\QCREATE DATABASE db1\E + (.*\n)* + \n\QCREATE TABLE public.t1 (\E + (.*\n)* + \n\QCREATE TABLE public.t2 (\E + (.*\n)* + \n\QCREATE DATABASE db2\E + (.*\n)* + \n\QCREATE TABLE public.t3 (\E + (.*\n)* + \n\QCREATE TABLE public.t4 (/xm, + unlike => qr/^ + \n\QCREATE DATABASE db3\E + (.*\n)* + \n\QCREATE TABLE public.t5 (\E + (.*\n)* + \n\QCREATE TABLE public.t6 (\E + (.*\n)* + \n\QCREATE DATABASE db4\E + (.*\n)* + \n\QCREATE TABLE public.t7 (\E + (.*\n)* + \n\QCREATE TABLE public.t8 (\E + \n\QCREATE DATABASE db5\E + (.*\n)* + \n\QCREATE TABLE public.t9 (\E + (.*\n)* + \n\QCREATE TABLE public.t10 (\E + /xm, + }, + + format_directory => { + setup_sql => "CREATE TABLE format_directory(a int, b boolean, c text); + INSERT INTO format_directory VALUES (1, true, 'name1'), (2, false, 'name2');", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--file' => "$tempdir/format_directory", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'directory', + '--file' => "$tempdir/format_directory.sql", + "$tempdir/format_directory", + ], + like => qr/^\n\QCOPY public.format_directory (a, b, c) FROM stdin;/xm + }, + + format_tar => { + setup_sql => "CREATE TABLE format_tar(a int, b boolean, c text); + INSERT INTO format_tar VALUES (1, false, 'name3'), (2, true, 'name4');", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'tar', + '--file' => "$tempdir/format_tar", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'tar', + '--file' => "$tempdir/format_tar.sql", + "$tempdir/format_tar", + ], + like => qr/^\n\QCOPY public.format_tar (a, b, c) FROM stdin;/xm + }, + + format_custom => { + setup_sql => "CREATE TABLE format_custom(a int, b boolean, c text); + INSERT INTO format_custom VALUES (1, false, 'name5'), (2, true, 'name6');", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'custom', + '--file' => "$tempdir/format_custom", + ], + restore_cmd => [ + 'pg_restore', '-C', + '--format' => 'custom', + '--file' => "$tempdir/format_custom.sql", + "$tempdir/format_custom", + ], + like => qr/^ \n\QCOPY public.format_custom (a, b, c) FROM stdin;/xm + }, + + dump_globals_only => { + setup_sql => "CREATE TABLE format_dir(a int, b boolean, c text); + INSERT INTO format_dir VALUES (1, false, 'name5'), (2, true, 'name6');", + dump_cmd => [ + 'pg_dumpall', + '--format' => 'directory', + '--globals-only', + '--file' => "$tempdir/dump_globals_only", + ], + restore_cmd => [ + 'pg_restore', '-C', '--globals-only', + '--format' => 'directory', + '--file' => "$tempdir/dump_globals_only.sql", + "$tempdir/dump_globals_only", + ], + like => qr/ + ^\s*\QCREATE ROLE dumpall;\E\s*\n + /xm + }, ); + +# First execute the setup_sql +foreach my $run (sort keys %pgdumpall_runs) +{ + if ($pgdumpall_runs{$run}->{setup_sql}) + { + $node->safe_psql($run_db, $pgdumpall_runs{$run}->{setup_sql}); + } +} + +# Execute the tests +foreach my $run (sort keys %pgdumpall_runs) +{ + # Create a new target cluster to pg_restore each test case run so that we + # don't need to take care of the cleanup from the target cluster after each + # run. + my $target_node = PostgreSQL::Test::Cluster->new("target_$run"); + $target_node->init; + $target_node->start; + + # Dumpall from node cluster. + $node->command_ok(\@{ $pgdumpall_runs{$run}->{dump_cmd} }, + "$run: pg_dumpall runs"); + + # Restore the dump on "target_node" cluster. + my @restore_cmd = ( + @{ $pgdumpall_runs{$run}->{restore_cmd} }, + '--host', $target_node->host, '--port', $target_node->port); + + my ($stdout, $stderr) = run_command(\@restore_cmd); + + # pg_restore --file output file. + my $output_file = slurp_file("$tempdir/${run}.sql"); + + if (!($pgdumpall_runs{$run}->{like}) && !($pgdumpall_runs{$run}->{unlike})) + { + die "missing \"like\" or \"unlike\" in test \"$run\""; + } + + if ($pgdumpall_runs{$run}->{like}) + { + like($output_file, $pgdumpall_runs{$run}->{like}, "should dump $run"); + } + + if ($pgdumpall_runs{$run}->{unlike}) + { + unlike( + $output_file, + $pgdumpall_runs{$run}->{unlike}, + "should not dump $run"); + } +} + +# Some negative test case with dump of pg_dumpall and restore using pg_restore +# test case 1: when -C is not used in pg_restore with dump of pg_dumpall +$node->command_fails_like( + [ 'pg_restore', + "$tempdir/format_custom", + '--format' => 'custom', + '--file' => "$tempdir/error_test.sql", ], + qr/\Qpg_restore: error: option -C\/--create must be specified when restoring an archive created by pg_dumpall\E/, + 'When -C is not used in pg_restore with dump of pg_dumpall'); + +# test case 2: When --list option is used with dump of pg_dumpall +$node->command_fails_like( + [ 'pg_restore', + "$tempdir/format_custom", '-C', + '--format' => 'custom', '--list', + '--file' => "$tempdir/error_test.sql", ], + qr/\Qpg_restore: error: option -l\/--list cannot be used when restoring an archive created by pg_dumpall\E/, + 'When --list is used in pg_restore with dump of pg_dumpall'); + +# test case 3: When non-exist database is given with -d option +$node->command_fails_like( + [ 'pg_restore', + "$tempdir/format_custom", '-C', + '--format' => 'custom', + '-d' => 'dbpq', ], + qr/\Qpg_restore: error: could not connect to database "dbpq"\E/, + 'When non-existent database is given with -d option in pg_restore with dump of pg_dumpall'); + +$node->stop('fast'); + +done_testing(); diff --git a/src/bin/pg_dump/t/010_dump_connstr.pl b/src/bin/pg_dump/t/010_dump_connstr.pl index 54e2e08cc20bf..bde6096c60d62 100644 --- a/src/bin/pg_dump/t/010_dump_connstr.pl +++ b/src/bin/pg_dump/t/010_dump_connstr.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -51,16 +51,20 @@ my $dst_bootstrap_super = 'boot'; my $node = PostgreSQL::Test::Cluster->new('main'); -$node->init(extra => - [ '-U', $src_bootstrap_super, '--locale=C', '--encoding=LATIN1' ]); +$node->init( + extra => [ + '--username' => $src_bootstrap_super, + '--locale' => 'C', + '--encoding' => 'LATIN1', + ]); # prep pg_hba.conf and pg_ident.conf $node->run_log( [ - $ENV{PG_REGRESS}, '--config-auth', - $node->data_dir, '--user', - $src_bootstrap_super, '--create-role', - "$username1,$username2,$username3,$username4" + $ENV{PG_REGRESS}, + '--config-auth' => $node->data_dir, + '--user' => $src_bootstrap_super, + '--create-role' => "$username1,$username2,$username3,$username4", ]); $node->start; @@ -69,106 +73,158 @@ my $plain = "$backupdir/plain.sql"; my $dirfmt = "$backupdir/dirfmt"; -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname1 ]); $node->run_log( - [ 'createuser', '-U', $src_bootstrap_super, '-s', $username1 ]); -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname2 ]); + [ 'createdb', '--username' => $src_bootstrap_super, $dbname1 ]); +$node->run_log( + [ + 'createuser', + '--username' => $src_bootstrap_super, + '--superuser', + $username1, + ]); +$node->run_log( + [ 'createdb', '--username' => $src_bootstrap_super, $dbname2 ]); $node->run_log( - [ 'createuser', '-U', $src_bootstrap_super, '-s', $username2 ]); -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname3 ]); + [ + 'createuser', + '--username' => $src_bootstrap_super, + '--superuser', + $username2, + ]); $node->run_log( - [ 'createuser', '-U', $src_bootstrap_super, '-s', $username3 ]); -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname4 ]); + [ 'createdb', '--username' => $src_bootstrap_super, $dbname3 ]); $node->run_log( - [ 'createuser', '-U', $src_bootstrap_super, '-s', $username4 ]); + [ + 'createuser', + '--username' => $src_bootstrap_super, + '--superuser', + $username3, + ]); +$node->run_log( + [ 'createdb', '--username' => $src_bootstrap_super, $dbname4 ]); +$node->run_log( + [ + 'createuser', + '--username' => $src_bootstrap_super, + '--superuser', + $username4, + ]); -# For these tests, pg_dumpall -r is used because it produces a short -# dump. +# For these tests, pg_dumpall --roles-only is used because it produces +# a short dump. $node->command_ok( [ - 'pg_dumpall', '-r', '-f', $discard, '--dbname', - $node->connstr($dbname1), - '-U', $username4 + 'pg_dumpall', '--roles-only', + '--file' => $discard, + '--dbname' => $node->connstr($dbname1), + '--username' => $username4, ], 'pg_dumpall with long ASCII name 1'); $node->command_ok( [ - 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', - $node->connstr($dbname2), - '-U', $username3 + 'pg_dumpall', '--no-sync', '--roles-only', + '--file' => $discard, + '--dbname' => $node->connstr($dbname2), + '--username' => $username3, ], 'pg_dumpall with long ASCII name 2'); $node->command_ok( [ - 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', - $node->connstr($dbname3), - '-U', $username2 + 'pg_dumpall', '--no-sync', '--roles-only', + '--file' => $discard, + '--dbname' => $node->connstr($dbname3), + '--username' => $username2, ], 'pg_dumpall with long ASCII name 3'); $node->command_ok( [ - 'pg_dumpall', '--no-sync', '-r', '-f', $discard, '--dbname', - $node->connstr($dbname4), - '-U', $username1 + 'pg_dumpall', '--no-sync', '--roles-only', + '--file' => $discard, + '--dbname' => $node->connstr($dbname4), + '--username' => $username1, ], 'pg_dumpall with long ASCII name 4'); $node->command_ok( [ - 'pg_dumpall', '-U', - $src_bootstrap_super, '--no-sync', - '-r', '-l', - 'dbname=template1' + 'pg_dumpall', '--no-sync', '--roles-only', + '--username' => $src_bootstrap_super, + '--dbname' => 'dbname=template1', ], - 'pg_dumpall -l accepts connection string'); + 'pg_dumpall --dbname accepts connection string'); -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, "foo\n\rbar" ]); +$node->run_log( + [ 'createdb', '--username' => $src_bootstrap_super, "foo\n\rbar" ]); -# not sufficient to use -r here +# not sufficient to use --roles-only here $node->command_fails( - [ 'pg_dumpall', '-U', $src_bootstrap_super, '--no-sync', '-f', $discard ], + [ + 'pg_dumpall', '--no-sync', + '--username' => $src_bootstrap_super, + '--file' => $discard, + ], 'pg_dumpall with \n\r in database name'); -$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, "foo\n\rbar" ]); +$node->run_log( + [ 'dropdb', '--username' => $src_bootstrap_super, "foo\n\rbar" ]); # make a table, so the parallel worker has something to dump $node->safe_psql( $dbname1, 'CREATE TABLE t0()', - extra_params => [ '-U', $src_bootstrap_super ]); + extra_params => [ '--username' => $src_bootstrap_super ]); # XXX no printed message when this fails, just SIGPIPE termination $node->command_ok( [ - 'pg_dump', '-Fd', '--no-sync', '-j2', '-f', $dirfmt, '-U', $username1, - $node->connstr($dbname1) + 'pg_dump', + '--format' => 'directory', + '--no-sync', + '--jobs' => 2, + '--file' => $dirfmt, + '--username' => $username1, + $node->connstr($dbname1), ], 'parallel dump'); # recreate $dbname1 for restore test -$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, $dbname1 ]); -$node->run_log([ 'createdb', '-U', $src_bootstrap_super, $dbname1 ]); +$node->run_log([ 'dropdb', '--username' => $src_bootstrap_super, $dbname1 ]); +$node->run_log( + [ 'createdb', '--username' => $src_bootstrap_super, $dbname1 ]); $node->command_ok( [ - 'pg_restore', '-v', '-d', 'template1', - '-j2', '-U', $username1, $dirfmt + 'pg_restore', + '--verbose', + '--dbname' => 'template1', + '--jobs' => 2, + '--username' => $username1, + $dirfmt, ], 'parallel restore'); -$node->run_log([ 'dropdb', '-U', $src_bootstrap_super, $dbname1 ]); +$node->run_log([ 'dropdb', '--username' => $src_bootstrap_super, $dbname1 ]); $node->command_ok( [ - 'pg_restore', '-C', '-v', '-d', - 'template1', '-j2', '-U', $username1, - $dirfmt + 'pg_restore', + '--create', + '--verbose', + '--dbname' => 'template1', + '--jobs' => 2, + '--username' => $username1, + $dirfmt, ], 'parallel restore with create'); $node->command_ok( - [ 'pg_dumpall', '--no-sync', '-f', $plain, '-U', $username1 ], + [ + 'pg_dumpall', + '--no-sync', + '--file' => $plain, + '--username' => $username1, + ], 'take full dump'); system_log('cat', $plain); my ($stderr, $result); @@ -183,20 +239,29 @@ my $envar_node = PostgreSQL::Test::Cluster->new('destination_envar'); $envar_node->init( - extra => - [ '-U', $dst_bootstrap_super, '--locale=C', '--encoding=LATIN1' ], + extra => [ + '--username' => $dst_bootstrap_super, + '--locale' => 'C', + '--encoding' => 'LATIN1', + ], auth_extra => - [ '--user', $dst_bootstrap_super, '--create-role', $restore_super ]); + [ '--user' => $dst_bootstrap_super, '--create-role' => $restore_super ], +); $envar_node->start; # make superuser for restore $envar_node->run_log( - [ 'createuser', '-U', $dst_bootstrap_super, '-s', $restore_super ]); + [ + 'createuser', + '--username' => $dst_bootstrap_super, + '--superuser', $restore_super, + ]); { local $ENV{PGPORT} = $envar_node->port; local $ENV{PGUSER} = $restore_super; - $result = run_log([ 'psql', '-X', '-f', $plain ], '2>', \$stderr); + $result = run_log([ 'psql', '--no-psqlrc', '--file' => $plain ], + '2>' => \$stderr); } ok($result, 'restore full dump using environment variables for connection parameters' @@ -210,21 +275,32 @@ my $cmdline_node = PostgreSQL::Test::Cluster->new('destination_cmdline'); $cmdline_node->init( - extra => - [ '-U', $dst_bootstrap_super, '--locale=C', '--encoding=LATIN1' ], + extra => [ + '--username' => $dst_bootstrap_super, + '--locale' => 'C', + '--encoding' => 'LATIN1', + ], auth_extra => - [ '--user', $dst_bootstrap_super, '--create-role', $restore_super ]); + [ '--user' => $dst_bootstrap_super, '--create-role' => $restore_super ], +); $cmdline_node->start; $cmdline_node->run_log( - [ 'createuser', '-U', $dst_bootstrap_super, '-s', $restore_super ]); + [ + 'createuser', + '--username' => $dst_bootstrap_super, + '--superuser', + $restore_super, + ]); { $result = run_log( [ - 'psql', '-p', $cmdline_node->port, '-U', - $restore_super, '-X', '-f', $plain + 'psql', + '--port' => $cmdline_node->port, + '--username' => $restore_super, + '--no-psqlrc', + '--file' => $plain, ], - '2>', - \$stderr); + '2>' => \$stderr); } ok($result, 'restore full dump with command-line options for connection parameters'); diff --git a/src/bin/pg_resetwal/Makefile b/src/bin/pg_resetwal/Makefile index 4228a5a772a9f..82bea06dee5a3 100644 --- a/src/bin/pg_resetwal/Makefile +++ b/src/bin/pg_resetwal/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_resetwal # -# Copyright (c) 1998-2024, PostgreSQL Global Development Group +# Copyright (c) 1998-2025, PostgreSQL Global Development Group # # src/bin/pg_resetwal/Makefile # diff --git a/src/bin/pg_resetwal/meson.build b/src/bin/pg_resetwal/meson.build index c1239528db27f..290832b22996f 100644 --- a/src/bin/pg_resetwal/meson.build +++ b/src/bin/pg_resetwal/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_resetwal_sources = files( 'pg_resetwal.c', diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index e9dcb5a6d89d1..e876f35f38ed4 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -19,7 +19,7 @@ * step 2 ... * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_resetwal/pg_resetwal.c @@ -75,6 +75,7 @@ static TimeLineID minXlogTli = 0; static XLogSegNo minXlogSegNo = 0; static int WalSegSz; static int set_wal_segsize; +static int set_char_signedness = -1; static void CheckDataVersion(void); static bool read_controlfile(void); @@ -106,6 +107,7 @@ main(int argc, char *argv[]) {"oldest-transaction-id", required_argument, NULL, 'u'}, {"next-transaction-id", required_argument, NULL, 'x'}, {"wal-segsize", required_argument, NULL, 1}, + {"char-signedness", required_argument, NULL, 2}, {NULL, 0, NULL, 0} }; @@ -302,6 +304,23 @@ main(int argc, char *argv[]) break; } + case 2: + { + errno = 0; + + if (pg_strcasecmp(optarg, "signed") == 0) + set_char_signedness = 1; + else if (pg_strcasecmp(optarg, "unsigned") == 0) + set_char_signedness = 0; + else + { + pg_log_error("invalid argument for option %s", "--char-signedness"); + pg_log_error_hint("Try \"%s --help\" for more information.", progname); + exit(1); + } + break; + } + default: /* getopt_long already emitted a complaint */ pg_log_error_hint("Try \"%s --help\" for more information.", progname); @@ -456,6 +475,9 @@ main(int argc, char *argv[]) if (set_wal_segsize != 0) ControlFile.xlog_seg_size = WalSegSz; + if (set_char_signedness != -1) + ControlFile.default_char_signedness = (set_char_signedness == 1); + if (minXlogSegNo > newXlogSegNo) newXlogSegNo = minXlogSegNo; @@ -724,8 +746,8 @@ PrintControlValues(bool guessed) ControlFile.pg_control_version); printf(_("Catalog version number: %u\n"), ControlFile.catalog_version_no); - printf(_("Database system identifier: %llu\n"), - (unsigned long long) ControlFile.system_identifier); + printf(_("Database system identifier: %" PRIu64 "\n"), + ControlFile.system_identifier); printf(_("Latest checkpoint's TimeLineID: %u\n"), ControlFile.checkPointCopy.ThisTimeLineID); printf(_("Latest checkpoint's full_page_writes: %s\n"), @@ -779,6 +801,8 @@ PrintControlValues(bool guessed) (ControlFile.float8ByVal ? _("by value") : _("by reference"))); printf(_("Data page checksum version: %u\n"), ControlFile.data_checksum_version); + printf(_("Default char data signedness: %s\n"), + (ControlFile.default_char_signedness ? _("signed") : _("unsigned"))); } @@ -1188,6 +1212,7 @@ usage(void) printf(_(" -O, --multixact-offset=OFFSET set next multitransaction offset\n")); printf(_(" -u, --oldest-transaction-id=XID set oldest transaction ID\n")); printf(_(" -x, --next-transaction-id=XID set next transaction ID\n")); + printf(_(" --char-signedness=OPTION set char signedness to \"signed\" or \"unsigned\"\n")); printf(_(" --wal-segsize=SIZE size of WAL segments, in megabytes\n")); printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); diff --git a/src/bin/pg_resetwal/po/es.po b/src/bin/pg_resetwal/po/es.po index cc3e5666478cc..ed1ed5e5c86e2 100644 --- a/src/bin/pg_resetwal/po/es.po +++ b/src/bin/pg_resetwal/po/es.po @@ -4,16 +4,16 @@ # This file is distributed under the same license as the PostgreSQL package. # # Ivan Hernandez , 2003. -# Alvaro Herrera , 2004-2014 +# Alvaro Herrera , 2004-2014, 2024 # Jaime Casanova , 2005 # Martín Marqués , 2013-2014 # msgid "" msgstr "" -"Project-Id-Version: pg_resetwal (PostgreSQL) 16\n" +"Project-Id-Version: pg_resetwal (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-03 07:19+0000\n" -"PO-Revision-Date: 2023-10-03 16:16+0200\n" +"POT-Creation-Date: 2025-02-16 19:50+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -43,6 +43,107 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "no se pudo cerrar el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"posible discordancia en orden de bytes\n" +"El ordenamiento de bytes usado para almacenar el archivo pg_control puede no\n" +"coincidir con el usado por este programa. En tal caso los resultados de abajo\n" +"serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" +"directorio de datos." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "no se pudo escribir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -73,163 +174,168 @@ msgstr "no se pudo re-ejecutar con el token restringido: código de error %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "no se pudo obtener el código de salida del subproceso»: código de error %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "el valor «%s» no es válido para la opción %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s debe estar en el rango %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método de sync no reconocido: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "argumento no válido para la opción %s" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" -msgstr "el «epoch» de ID de transacción (-e) no debe ser -1" +msgstr "el \"epoch\" de ID de transacción (-e) no debe ser -1" -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "el ID de transacción más antiguo (-u) debe ser mayor o igual a %u" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "el ID de transacción (-x) debe ser mayor o igual a %u" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "el ID de transacción (-c) debe ser 0 o bien mayor o igual a 2" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "el ID de transacción (-c) debe ser %u o bien mayor o igual a %u" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) no debe ser cero" -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "el ID de multitransacción (-m) no debe ser 0" -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "el ID de multitransacción más antiguo (-m) no debe ser 0" -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "la posición de multitransacción (-O) no debe ser -1" -#: pg_resetwal.c:296 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "el argumento de --wal-segsize debe ser un número" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "el argumento de %s debe ser una potencia de dos entre 1 y 1024" -#: pg_resetwal.c:298 -#, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "el argumento de --wal-segsize debe ser una potencia de dos entre 1 y 1024" - -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "directorio de datos no especificado" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "no puede ser ejecutado con el usuario «root»" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Debe ejecutar %s con el superusuario de PostgreSQL." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "no se pudo obtener los permisos del directorio «%s»: %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "no se pudo cambiar al directorio «%s»: %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "no se pudo abrir archivo «%s» para lectura: %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "el archivo candado «%s» existe" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "¿Hay un servidor corriendo? Si no, borre el archivo candado e inténtelo de nuevo." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "" -"\n" -"If these values seem acceptable, use -f to force reset.\n" -msgstr "" -"\n" -"Si estos valores parecen aceptables, use -f para forzar reinicio.\n" +msgid "not proceeding because control file values were guessed" +msgstr "no continuando porque los valores del archivo de control fueron asumidos" -#: pg_resetwal.c:479 +#: pg_resetwal.c:476 #, c-format -msgid "" -"The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" -msgstr "" -"El servidor de bases de datos no se apagó limpiamente.\n" -"Restablecer el WAL puede causar pérdida de datos.\n" -"Si quiere continuar de todas formas, use -f para forzar el restablecimiento.\n" +msgid "If these values seem acceptable, use -f to force reset." +msgstr "Si estos valores parecen aceptables, use -f para forzar reinicio." + +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "el directorio de destino no fue apagado limpiamente" + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "Reiniciar el \"write-ahead log\" puede causar pérdida de datos." + +#: pg_resetwal.c:487 +#, c-format +msgid "If you want to proceed anyway, use -f to force reset." +msgstr "Si quiere proceder de todas formas, use -f para forzar reinicio." -#: pg_resetwal.c:493 +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" -msgstr "«Write-ahead log» restablecido\n" +msgstr "\"Write-ahead log\" restablecido\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "archivo vacío inesperado «%s»" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "no se pudo leer el archivo «%s»: %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "el directorio de datos tiene la versión equivocada" -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "El archivo «%s» contiene «%s», que no es compatible con la versión «%s» de este programa." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -240,24 +346,24 @@ msgstr "" " touch %s\n" "y pruebe de nuevo." -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "existe pg_control pero tiene un CRC no válido, proceda con precaución" -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" msgstr[0] "pg_control especifica un tamaño de segmento de WAL no válido (%d byte), proceda con precaución" msgstr[1] "pg_control especifica un tamaño de segmento de WAL no válido (%d bytes), proceda con precaución" -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "existe pg_control pero está roto o tiene la versión equivocada; ignorándolo" -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "" "Guessed pg_control values:\n" @@ -266,7 +372,7 @@ msgstr "" "Valores de pg_control asumidos:\n" "\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "" "Current pg_control values:\n" @@ -275,167 +381,167 @@ msgstr "" "Valores actuales de pg_control:\n" "\n" -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "Número de versión de pg_control: %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "Número de versión de catálogo: %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "Identificador de sistema: %llu\n" -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "TimeLineID del checkpoint más reciente: %u\n" -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "full_page_writes del checkpoint más reciente: %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "desactivado" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "activado" -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID del checkpoint más reciente: %u:%u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID del checkpoint más reciente: %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId del checkpoint más reciente: %u\n" -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset del checkpoint más reciente: %u\n" -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID del checkpoint más reciente: %u\n" -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "BD del oldestXID del checkpoint más reciente: %u\n" -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID del checkpoint más reciente: %u\n" -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid del checkpoint más reciente: %u\n" -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "BD del oldestMultiXid del checkpt. más reciente: %u\n" -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid del último checkpoint: %u\n" -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid del último checkpoint: %u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Máximo alineamiento de datos: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "Tamaño del bloque de la base de datos: %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Bloques por segmento de relación grande: %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "Tamaño del bloque de WAL: %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Bytes por segmento WAL: %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Longitud máxima de identificadores: %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Máximo número de columnas en un índice: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Longitud máxima de un trozo TOAST: %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Longitud máxima de un trozo de objeto grande: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "Tipo de almacenamiento hora/fecha: %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "enteros de 64 bits" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Paso de parámetros float8: %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "por referencia" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "por valor" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "Versión de suma de verificación de datos: %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "" "\n" @@ -448,127 +554,149 @@ msgstr "" "Valores a cambiar:\n" "\n" -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "Primer segmento de log después de reiniciar: %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "Base de datos del OldestMulti: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "Base de datos del OldestXID: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "Epoch del NextXID: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "no se pudo abrir el directorio «%s»: %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "no se pudo leer el directorio «%s»: %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "no se pudo borrar el archivo «%s»: %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "no se pudo escribir el archivo «%s»: %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "error de fsync: %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" "\n" msgstr "" -"%s restablece el WAL («write-ahead log») de PostgreSQL.\n" +"%s restablece el WAL (\"write-ahead log\") de PostgreSQL.\n" "\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 +#, c-format +msgid "Usage:\n" +msgstr "Empleo:\n" + +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [OPCIÓN]... DATADIR\n" + +#: pg_resetwal.c:1172 #, c-format msgid "" -"Usage:\n" -" %s [OPTION]... DATADIR\n" "\n" +"Options:\n" msgstr "" -"Uso:\n" -" %s [OPCIÓN]... DATADIR\n" "\n" +"Opciones:\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1173 #, c-format -msgid "Options:\n" -msgstr "Opciones:\n" +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata=]DATADIR directorio de datos\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1174 +#, c-format +msgid "" +" -f, --force force update to be done even after unclean shutdown or\n" +" if pg_control values had to be guessed\n" +msgstr "" +" -f, --force forzar que la actualización se haga incluso después\n" +" de un apagado no limpio o si los valores de pg_control\n" +" tuvieron que asumirse\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr " -n, --dry-run no actualiza, sólo muestra lo que se haría\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de versión, luego salir\n" + +#: pg_resetwal.c:1178 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda, luego salir\n" + +#: pg_resetwal.c:1180 +#, c-format +msgid "" +"\n" +"Options to override control file values:\n" +msgstr "" +"\n" +"Opciones para sobreescribir valores del archivo de control:\n" + +#: pg_resetwal.c:1181 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -576,87 +704,57 @@ msgid "" " commit timestamp (zero means no change)\n" msgstr "" " -c, --commit-timestamp-ids=XID,XID\n" -" definir la más antigua y la más nueva transacciones\n" -" que llevan timestamp de commit (cero significa no\n" -" cambiar)\n" +" definir la más antigua y la más nueva\n" +" transacciones que llevan timestamp de commit\n" +" (cero significa no cambiar)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]DATADIR directorio de datos\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" -msgstr " -e, --epoch=XIDEPOCH asigna el siguiente «epoch» de ID de transacción\n" - -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr " -f, --force fuerza que la actualización sea hecha\n" +msgstr "" +" -e, --epoch=XIDEPOCH asigna el siguiente \"epoch\" de ID de\n" +" transacción\n" -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr "" -" -l, --next-wal-file=ARCHIVOWAL\n" -" fuerza una ubicación inicial mínima para nuevo WAL\n" +" -l, --next-wal-file=ARCHIVOWAL fuerza una ubicación inicial mínima para\n" +" nuevo WAL\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr "" -" -m, --multixact-ids=MXID,MXID\n" -" asigna el siguiente ID de multitransacción y\n" -" el más antiguo\n" +" -m, --multixact-ids=MXID,MXID asigna el siguiente ID de multitransacción\n" +" y el más antiguo\n" -#: pg_resetwal.c:1138 -#, c-format -msgid " -n, --dry-run no update, just show what would be done\n" -msgstr " -n, --dry-run no actualiza, sólo muestra lo que se haría\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" -msgstr " -o, --next-oid=OID asigna el siguiente OID\n" +msgstr " -o, --next-oid=OID asigna el siguiente OID\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" -msgstr "" -" -O, --multixact-offset=OFFSET\n" -" asigna la siguiente posición de multitransacción\n" +msgstr " -O, --multixact-offset=OFFSET asigna la siguiente pos. de multitransacción\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" -msgstr "" -" -u, --oldest-transaction-id=XID\n" -" asigna el ID de transacción más antiguo\n" +msgstr " -u, --oldest-transaction-id=XID asigna el ID de transacción más antiguo\n" -#: pg_resetwal.c:1142 -#, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version mostrar información de versión y salir\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" -msgstr "" -" -x, --next-transaction-id=XID\n" -" asigna el siguiente ID de transacción\n" +msgstr " -x, --next-transaction-id=XID asigna el siguiente ID de transacción\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" -msgstr " --wal-segsize=TAMAÑO tamaño de segmentos de WAL, en megabytes\n" - -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help mostrar esta ayuda y salir\n" +msgstr " --wal-segsize=TAMAÑO tamaño de segmentos de WAL, en megabytes\n" -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "" "\n" @@ -665,7 +763,7 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" diff --git a/src/bin/pg_resetwal/po/fr.po b/src/bin/pg_resetwal/po/fr.po index 9c02948062513..dac983a2a57ca 100644 --- a/src/bin/pg_resetwal/po/fr.po +++ b/src/bin/pg_resetwal/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-05 17:20+0000\n" -"PO-Revision-Date: 2023-09-05 22:02+0200\n" +"POT-Creation-Date: 2024-08-22 10:21+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -43,6 +43,107 @@ msgstr "détail : " msgid "hint: " msgstr "astuce : " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"possible incohérence dans l'ordre des octets\n" +"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n" +"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n" +"résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" +"est incompatible avec ce répertoire des données." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "impossible d'écrire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -73,166 +174,168 @@ msgstr "n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "valeur « %s » invalide pour l'option %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s doit être compris entre %d et %d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "argument invalide pour l'option %s" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "la valeur epoch de l'identifiant de transaction (-e) ne doit pas être -1" -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "l'identifiant de transaction le plus ancien (-u) doit être supérieur ou égal à %u" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "l'identifiant de transaction (-x) doit être supérieur ou égal à %u" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "l'identifiant de transaction (-c) doit être 0 ou supérieur ou égal à 2" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "l'identifiant de transaction (-c) doit être %u ou supérieur ou égal à %u" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "l'OID (-o) ne doit pas être 0" -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "l'identifiant de multi-transaction (-m) ne doit pas être 0" -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "l'identifiant de multi-transaction le plus ancien (-m) ne doit pas être 0" -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "le décalage de multi-transaction (-O) ne doit pas être -1" -#: pg_resetwal.c:296 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "l'argument de --wal-segsize doit être un nombre" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "l'argument de %s doit être une puissance de 2 comprise entre 1 et 1024" -#: pg_resetwal.c:298 -#, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "l'argument de --wal-segsize doit être une puissance de 2 comprise entre 1 et 1024" - -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "aucun répertoire de données indiqué" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "ne peut pas être exécuté par « root »" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Vous devez exécuter %s en tant que super-utilisateur PostgreSQL." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "n'a pas pu lire les droits du répertoire « %s » : %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "n'a pas pu modifier le répertoire par « %s » : %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "le fichier verrou « %s » existe" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "Le serveur est-il démarré ? Sinon, supprimer le fichier verrou et réessayer." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "" -"\n" -"If these values seem acceptable, use -f to force reset.\n" -msgstr "" -"\n" -"Si ces valeurs semblent acceptables, utiliser -f pour forcer la\n" -"réinitialisation.\n" +msgid "not proceeding because control file values were guessed" +msgstr "ne continue pas car les valeurs du fichier de contrôle devraient être devinées" -#: pg_resetwal.c:479 +#: pg_resetwal.c:476 #, c-format -msgid "" -"The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" -msgstr "" -"Le serveur de bases de données n'a pas été arrêté proprement.\n" -"Ré-initialiser le journal des transactions peut occasionner des pertes de\n" -"données.\n" -"Pour continuer malgré tout, utiliser -f pour forcer la\n" -"réinitialisation.\n" +msgid "If these values seem acceptable, use -f to force reset." +msgstr "Si ces valeurs semblent acceptables, utiliser -f pour forcer la réinitialisation." + +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "le serveur de bases de données n'a pas été arrêté proprement" + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "Réinitialiser les journaux de transactions pourrait causer des pertes de données." -#: pg_resetwal.c:493 +#: pg_resetwal.c:487 +#, c-format +msgid "If you want to proceed anyway, use -f to force reset." +msgstr "Si vous voulez continuer malgré tout, utiliser -f pour forcer la réinitialisation." + +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" msgstr "Réinitialisation des journaux de transactions\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "fichier vide inattendu « %s »" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "n'a pas pu lire le fichier « %s » : %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "le répertoire des données a une mauvaise version" -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "Le fichier « %s » contient « %s », qui n'est pas compatible avec la version « %s » de ce programme." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -243,24 +346,24 @@ msgstr "" " touch %s\n" "et réessayer." -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_control existe mais son CRC est invalide ; agir avec précaution" -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" msgstr[0] "pg_control spécifie une taille invalide de segment WAL (%d octet) ; agir avec précaution" msgstr[1] "pg_control spécifie une taille invalide de segment WAL (%d octets) ; agir avec précaution" -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_control existe mais est corrompu ou de mauvaise version ; ignoré" -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "" "Guessed pg_control values:\n" @@ -269,7 +372,7 @@ msgstr "" "Valeurs de pg_control devinées :\n" "\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "" "Current pg_control values:\n" @@ -278,167 +381,167 @@ msgstr "" "Valeurs actuelles de pg_control :\n" "\n" -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "Numéro de version de pg_control : %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "Numéro de version du catalogue : %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "Identifiant du système de base de données : %llu\n" -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Dernier TimeLineID du point de contrôle : %u\n" -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Dernier full_page_writes du point de contrôle : %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "désactivé" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "activé" -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "Dernier NextXID du point de contrôle : %u:%u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "Dernier NextOID du point de contrôle : %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "Dernier NextMultiXactId du point de contrôle : %u\n" -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "Dernier NextMultiOffset du point de contrôle : %u\n" -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "Dernier oldestXID du point de contrôle : %u\n" -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "Dernier oldestXID du point de contrôle de la base : %u\n" -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "Dernier oldestActiveXID du point de contrôle : %u\n" -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "Dernier oldestMultiXid du point de contrôle : %u\n" -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "Dernier oldestMulti du point de contrôle de la base : %u\n" -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "Dernier oldestCommitTsXid du point de contrôle : %u\n" -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "Dernier newestCommitTsXid du point de contrôle : %u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Alignement maximal des données : %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "Taille du bloc de la base de données : %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Blocs par segment des relations volumineuses : %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "Taille de bloc du journal de transaction : %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Octets par segment du journal de transaction : %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Longueur maximale des identifiants : %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Nombre maximum de colonnes d'un index: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Longueur maximale d'un morceau TOAST : %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Taille d'un morceau de Large Object : %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "Stockage du type date/heure : %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "entiers 64-bits" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Passage d'argument float8 : %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "par référence" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "par valeur" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "Version des sommes de contrôle des pages de données : %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "" "\n" @@ -451,102 +554,82 @@ msgstr "" "Valeurs à changer :\n" "\n" -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "Premier segment du journal après réinitialisation : %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "OldestMulti's DB: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "OldestXID's DB: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "NextXID Epoch: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "n'a pas pu lire le répertoire « %s » : %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "n'a pas pu fermer le répertoire « %s » : %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "n'a pas pu supprimer le fichier « %s » : %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "impossible d'écrire le fichier « %s » : %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "erreur fsync : %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -555,23 +638,64 @@ msgstr "" "%s réinitialise le journal des transactions PostgreSQL.\n" "\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 +#, c-format +msgid "Usage:\n" +msgstr "Usage :\n" + +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [OPTION]... [RÉP_DONNÉES]\n" + +#: pg_resetwal.c:1172 #, c-format msgid "" -"Usage:\n" -" %s [OPTION]... DATADIR\n" "\n" +"Options:\n" msgstr "" -"Usage :\n" -" %s [OPTION]... RÉP_DONNÉES\n" "\n" +"Options :\n" + +#: pg_resetwal.c:1173 +#, c-format +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata] RÉP_DONNEES répertoire de la base de données\n" + +#: pg_resetwal.c:1174 +#, c-format +msgid "" +" -f, --force force update to be done even after unclean shutdown or\n" +" if pg_control values had to be guessed\n" +msgstr " -i, --interactive force la mise à jour, y compris un arrêt pas propre ou si les valeurs de pg_control doivent être devinées\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr "" +" -n, --dry-run pas de mise à jour, affiche\n" +" simplement ce qui sera fait\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1178 #, c-format -msgid "Options:\n" -msgstr "Options :\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1180 +#, c-format +msgid "" +"\n" +"Options to override control file values:\n" +msgstr "" +"\n" +"Options contrôlant les valeurs du fichier de contrôle :\n" + +#: pg_resetwal.c:1181 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -583,86 +707,59 @@ msgstr "" " et la plus récente contenant les dates/heures\n" " de validation (zéro signifie aucun changement)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]RÉP_DONNEES répertoire de la base de données\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr "" " -e, --epoch=XIDEPOCH configure la valeur epoch du prochain\n" " identifiant de transaction\n" -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr " -f, --force force la mise à jour\n" - -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr "" " -l, --next-wal-file=FICHIERWAL configure l'emplacement minimal de début\n" " des WAL du nouveau journal de transactions\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr "" " -m, --multixact-ids=MXID,MXID configure le prochain et le plus ancien\n" " identifiants multi-transactions\n" -#: pg_resetwal.c:1138 -#, c-format -msgid " -n, --dry-run no update, just show what would be done\n" -msgstr "" -" -n, --dry-run pas de mise à jour, affiche\n" -" simplement ce qui sera fait\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID configure le prochain OID\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr "" " -O, --multixact-offset=DÉCALAGE configure le prochain décalage\n" " multitransaction\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr "" " -u, --oldest-transaction-id=XID configure l'identifiant de transaction le\n" " plus ancien\n" -#: pg_resetwal.c:1142 -#, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version affiche la version puis quitte\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr "" " -x, --next-transaction-id=XID configure le prochain identifiant de\n" " transaction\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=TAILLE configure la taille des segments WAL, en Mo\n" -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help affiche cette aide puis quitte\n" - -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "" "\n" @@ -671,167 +768,7 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid " (zero in either value means no change)\n" -#~ msgstr " (zéro dans l'une des deux valeurs signifie aucun changement)\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version afficherla version et quitte\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide, puis quitte\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide et quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version, puis quitte\n" - -#~ msgid " -V, --version output version information, then exit\n" -#~ msgstr " -V, --version affiche la version et quitte\n" - -#~ msgid " -c XID,XID set oldest and newest transactions bearing commit timestamp\n" -#~ msgstr " -c XID,XID configure la plus ancienne et la plus récente transaction\n" - -#~ msgid " -x XID set next transaction ID\n" -#~ msgstr " -x XID fixe le prochain identifiant de transaction\n" - -#~ msgid "%s: WARNING: cannot create restricted tokens on this platform\n" -#~ msgstr "%s : ATTENTION : ne peut pas créer les jetons restreints sur cette plateforme\n" - -#~ msgid "%s: argument of --wal-segsize must be a number\n" -#~ msgstr "%s : l'argument de --wal-segsize doit être un nombre\n" - -#~ msgid "%s: argument of --wal-segsize must be a power of 2 between 1 and 1024\n" -#~ msgstr "%s : l'argument de --wal-segsize doit être une puissance de 2 entre 1 et 1024\n" - -#~ msgid "%s: cannot be executed by \"root\"\n" -#~ msgstr "%s : ne peut pas être exécuté par « root »\n" - -#~ msgid "%s: could not allocate SIDs: error code %lu\n" -#~ msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n" - -#~ msgid "%s: could not change directory to \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu accéder au répertoire « %s » : %s\n" - -#~ msgid "%s: could not close directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu fermer le répertoire « %s » : %s\n" - -#~ msgid "%s: could not create pg_control file: %s\n" -#~ msgstr "%s : n'a pas pu créer le fichier pg_control : %s\n" - -#~ msgid "%s: could not create restricted token: error code %lu\n" -#~ msgstr "%s : n'a pas pu créer le jeton restreint : code d'erreur %lu\n" - -#~ msgid "%s: could not delete file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu supprimer le fichier « %s » : %s\n" - -#~ msgid "%s: could not get exit code from subprocess: error code %lu\n" -#~ msgstr "%s : n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu\n" - -#~ msgid "%s: could not open directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#~ msgid "%s: could not open file \"%s\" for reading: %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » en lecture : %s\n" - -#~ msgid "%s: could not open file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n" - -#~ msgid "%s: could not open process token: error code %lu\n" -#~ msgstr "%s : n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n" - -#~ msgid "%s: could not re-execute with restricted token: error code %lu\n" -#~ msgstr "%s : n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu\n" - -#~ msgid "%s: could not read directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "%s: could not read file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le fichier « %s » : %s\n" - -#~ msgid "%s: could not read from directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "%s: could not read permissions of directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire les droits sur le répertoire « %s » : %s\n" - -#~ msgid "%s: could not start process for command \"%s\": error code %lu\n" -#~ msgstr "%s : n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu\n" - -#~ msgid "%s: could not write file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu écrire le fichier « %s » : %s\n" - -#~ msgid "%s: could not write pg_control file: %s\n" -#~ msgstr "%s : n'a pas pu écrire le fichier pg_control : %s\n" - -#~ msgid "%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n" -#~ msgstr "" -#~ "%s : erreur interne -- sizeof(ControlFileData) est trop important...\n" -#~ "corrigez PG_CONTROL_SIZE\n" - -#~ msgid "%s: invalid argument for option -O\n" -#~ msgstr "%s : argument invalide pour l'option -O\n" - -#~ msgid "%s: invalid argument for option -l\n" -#~ msgstr "%s : argument invalide pour l'option -l\n" - -#~ msgid "%s: invalid argument for option -m\n" -#~ msgstr "%s : argument invalide pour l'option -m\n" - -#~ msgid "%s: invalid argument for option -o\n" -#~ msgstr "%s : argument invalide pour l'option -o\n" - -#~ msgid "%s: invalid argument for option -x\n" -#~ msgstr "%s : argument invalide pour l'option -x\n" - -#~ msgid "%s: no data directory specified\n" -#~ msgstr "%s : aucun répertoire de données indiqué\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "First log file ID after reset: %u\n" -#~ msgstr "Premier identifiant du journal après réinitialisation : %u\n" - -#~ msgid "Float4 argument passing: %s\n" -#~ msgstr "Passage d'argument float4 : %s\n" - -#~ msgid "Transaction log reset\n" -#~ msgstr "Réinitialisation du journal des transactions\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "ne peut pas créer les jetons restreints sur cette plateforme : code d'erreur %lu" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "n'a pas pu charger la bibliothèque « %s » : code d'erreur %lu" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "floating-point numbers" -#~ msgstr "nombres à virgule flottante" - -#~ msgid "transaction ID (-x) must not be 0" -#~ msgstr "l'identifiant de la transaction (-x) ne doit pas être 0" diff --git a/src/bin/pg_resetwal/po/ja.po b/src/bin/pg_resetwal/po/ja.po index c229e1eb4ba26..e0cd4d5748cd1 100644 --- a/src/bin/pg_resetwal/po/ja.po +++ b/src/bin/pg_resetwal/po/ja.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_resetwal (PostgreSQL 17)\n" +"Project-Id-Version: pg_resetwal (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-11 09:39+0900\n" -"PO-Revision-Date: 2023-10-11 11:00+0900\n" +"POT-Creation-Date: 2025-03-31 09:53+0900\n" +"PO-Revision-Date: 2025-03-31 16:31+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -22,26 +22,126 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:389 pg_resetwal.c:547 +#: pg_resetwal.c:595 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ファイル\"%s\"を読み取り用にオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:556 pg_resetwal.c:610 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ファイル\"%s\"の読み取りに失敗しました: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ファイル\"%s\"をクローズできませんでした: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "バイトオーダが合っていません" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"バイトオーダが異なる可能性があります。\n" +"pg_controlファイルを格納するために使用するバイトオーダが本プログラムで使用\n" +"されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" +"PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 pg_resetwal.c:1158 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ファイル\"%s\"をオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1166 pg_resetwal.c:1178 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ファイル\"%s\"を書き出せませんでした: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ファイル\"%s\"をfsyncできませんでした: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "メモリ不足です\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "nullポインタは複製できません(内部エラー)\n" + +#: ../../common/file_utils.c:75 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" + +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ファイル\"%s\"のstatに失敗しました: %m" + +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "このビルドでは同期方式\"%s\"をサポートしていません" + +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_resetwal.c:952 pg_resetwal.c:1005 pg_resetwal.c:1040 pg_resetwal.c:1078 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" + +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 +#: pg_resetwal.c:978 pg_resetwal.c:1019 pg_resetwal.c:1057 pg_resetwal.c:1092 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" + +#: ../../common/file_utils.c:520 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -72,163 +172,168 @@ msgstr "制限付きトークンで再実行できませんでした: %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "サブプロセスの終了コードを入手できませんでした。: エラーコード %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "オプション%2$sに対する不正な値\"%1$s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%sは%d..%dの範囲になければなりません" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "認識できない同期方式: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:166 pg_resetwal.c:179 pg_resetwal.c:192 pg_resetwal.c:205 +#: pg_resetwal.c:212 pg_resetwal.c:231 pg_resetwal.c:244 pg_resetwal.c:252 +#: pg_resetwal.c:272 pg_resetwal.c:283 pg_resetwal.c:317 #, c-format msgid "invalid argument for option %s" msgstr "オプション%sの引数が不正です" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:306 pg_resetwal.c:319 -#: pg_resetwal.c:326 +#: pg_resetwal.c:167 pg_resetwal.c:180 pg_resetwal.c:193 pg_resetwal.c:206 +#: pg_resetwal.c:213 pg_resetwal.c:232 pg_resetwal.c:245 pg_resetwal.c:253 +#: pg_resetwal.c:273 pg_resetwal.c:284 pg_resetwal.c:318 pg_resetwal.c:326 +#: pg_resetwal.c:339 pg_resetwal.c:346 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_resetwal.c:168 +#: pg_resetwal.c:171 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "トランザクションIDの基点(-e)は-1にはできません" -#: pg_resetwal.c:181 +#: pg_resetwal.c:184 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "最古のトランザクションID(-u)は%uもしくはそれ以上でなければなりません" -#: pg_resetwal.c:194 +#: pg_resetwal.c:197 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "トランザクションID(-x)は%uもしくはそれ以上でなければなりません" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:219 pg_resetwal.c:223 #, c-format msgid "transaction ID (-c) must be either %u or greater than or equal to %u" msgstr "トランザクションID(-c)は%uまたは%u以上でなければなりません" -#: pg_resetwal.c:233 +#: pg_resetwal.c:236 #, c-format msgid "OID (-o) must not be 0" msgstr "OID(-o)は0にはできません" -#: pg_resetwal.c:254 +#: pg_resetwal.c:257 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "マルチトランザクションID(-m)は0にはできません" -#: pg_resetwal.c:261 +#: pg_resetwal.c:264 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "最古のマルチトランザクションID(-m)は0にはできません" -#: pg_resetwal.c:274 +#: pg_resetwal.c:277 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "マルチトランザクションオフセット(-O)は-1にはできません" -#: pg_resetwal.c:300 +#: pg_resetwal.c:303 #, c-format msgid "argument of %s must be a power of two between 1 and 1024" msgstr "%sの引数は1から1024までの間の2の累乗でなければなりません" -#: pg_resetwal.c:317 +#: pg_resetwal.c:337 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: pg_resetwal.c:325 +#: pg_resetwal.c:345 #, c-format msgid "no data directory specified" msgstr "データディレクトリが指定されていません" -#: pg_resetwal.c:339 +#: pg_resetwal.c:359 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\"では実行できません" -#: pg_resetwal.c:340 +#: pg_resetwal.c:360 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "PostgreSQLのスーパーユーザーで%sを実行しなければなりません" -#: pg_resetwal.c:350 +#: pg_resetwal.c:370 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "ディレクトリ\"%s\"の権限を読み取れませんでした: %m" -#: pg_resetwal.c:356 +#: pg_resetwal.c:376 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "ディレクトリ\"%s\"に移動できませんでした: %m" -#: pg_resetwal.c:369 pg_resetwal.c:523 pg_resetwal.c:571 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "ファイル\"%s\"を読み取り用にオープンできませんでした: %m" - -#: pg_resetwal.c:374 +#: pg_resetwal.c:394 #, c-format msgid "lock file \"%s\" exists" msgstr "ロックファイル\"%s\"が存在します" -#: pg_resetwal.c:375 +#: pg_resetwal.c:395 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "サーバーが稼動していませんか? そうでなければロックファイルを削除し再実行してください。" -#: pg_resetwal.c:474 +#: pg_resetwal.c:497 #, c-format msgid "not proceeding because control file values were guessed" msgstr "制御ファイルの値が推測値であるため、処理をここで終了します" -#: pg_resetwal.c:475 +#: pg_resetwal.c:498 #, c-format msgid "If these values seem acceptable, use -f to force reset." msgstr "この値を許容できる場合は、-fを使用して強制リセットしてください。" -#: pg_resetwal.c:484 +#: pg_resetwal.c:507 #, c-format msgid "database server was not shut down cleanly" msgstr "ターゲットサーバーはクリーンにシャットダウンされていません" -#: pg_resetwal.c:485 +#: pg_resetwal.c:508 #, c-format msgid "Resetting the write-ahead log might cause data to be lost." msgstr "先行書き込みロ(WAL)グをリセットすると、データが失われる可能性があります。" -#: pg_resetwal.c:486 +#: pg_resetwal.c:509 #, c-format msgid "If you want to proceed anyway, use -f to force reset." msgstr "とにかく続行したいという場合には、-f でリセットを強行できます。" -#: pg_resetwal.c:498 +#: pg_resetwal.c:522 #, c-format msgid "Write-ahead log reset\n" msgstr "先行書き込みログがリセットされました\n" -#: pg_resetwal.c:530 +#: pg_resetwal.c:554 #, c-format msgid "unexpected empty file \"%s\"" msgstr "想定外の空のファイル\"%s\"" -#: pg_resetwal.c:532 pg_resetwal.c:586 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "ファイル\"%s\"の読み取りに失敗しました: %m" - -#: pg_resetwal.c:540 +#: pg_resetwal.c:564 #, c-format msgid "data directory is of wrong version" msgstr "データディレクトリのバージョンが違います" -#: pg_resetwal.c:541 +#: pg_resetwal.c:565 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "ファイル\"%s\"では\"%s\"となっています、これはこのプログラムのバージョン\"%s\"と互換性がありません" -#: pg_resetwal.c:574 +#: pg_resetwal.c:598 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -239,23 +344,23 @@ msgstr "" " touch %s\n" "の後に再実行してください。" -#: pg_resetwal.c:602 +#: pg_resetwal.c:626 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_controlがありましたが、CRCが不正でした; 注意して進めてください" -#: pg_resetwal.c:611 +#: pg_resetwal.c:635 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" msgstr[0] "pg_controlにあるWALセグメントサイズ(%dバイト)は不正です; 注意して進めてください" -#: pg_resetwal.c:622 +#: pg_resetwal.c:646 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_controlがありましたが、破損あるいは間違ったバージョンです; 無視します" -#: pg_resetwal.c:717 +#: pg_resetwal.c:741 #, c-format msgid "" "Guessed pg_control values:\n" @@ -264,7 +369,7 @@ msgstr "" "pg_controlの推測値:\n" "\n" -#: pg_resetwal.c:719 +#: pg_resetwal.c:743 #, c-format msgid "" "Current pg_control values:\n" @@ -273,167 +378,180 @@ msgstr "" "現在のpg_controlの値:\n" "\n" -#: pg_resetwal.c:721 +#: pg_resetwal.c:745 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_controlバージョン番号: %u\n" -#: pg_resetwal.c:723 +#: pg_resetwal.c:747 #, c-format msgid "Catalog version number: %u\n" msgstr "カタログバージョン番号: %u\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:749 #, c-format -msgid "Database system identifier: %llu\n" -msgstr "データベースシステム識別子: %llu\n" +msgid "Database system identifier: %\n" +msgstr "データベースシステム識別子: %\n" -#: pg_resetwal.c:727 +#: pg_resetwal.c:751 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "最終チェックポイントの時系列ID: %u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:753 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "最終チェックポイントのfull_page_writes: %s\n" -#: pg_resetwal.c:730 +#: pg_resetwal.c:754 msgid "off" msgstr "オフ" -#: pg_resetwal.c:730 +#: pg_resetwal.c:754 msgid "on" msgstr "オン" -#: pg_resetwal.c:731 +#: pg_resetwal.c:755 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "最終チェックポイントのNextXID: %u:%u\n" -#: pg_resetwal.c:734 +#: pg_resetwal.c:758 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "最終チェックポイントのNextOID: %u\n" -#: pg_resetwal.c:736 +#: pg_resetwal.c:760 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "最終チェックポイントのNextMultiXactId: %u\n" -#: pg_resetwal.c:738 +#: pg_resetwal.c:762 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "最終チェックポイントのNextMultiOffset: %u\n" -#: pg_resetwal.c:740 +#: pg_resetwal.c:764 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "最終チェックポイントのoldestXID: %u\n" -#: pg_resetwal.c:742 +#: pg_resetwal.c:766 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "最終チェックポイントのoldestXIDのDB: %u\n" -#: pg_resetwal.c:744 +#: pg_resetwal.c:768 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "最終チェックポイントのoldestActiveXID: %u\n" -#: pg_resetwal.c:746 +#: pg_resetwal.c:770 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "最終チェックポイントのoldestMultiXid: %u\n" -#: pg_resetwal.c:748 +#: pg_resetwal.c:772 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "最終チェックポイントのoldestMultiのDB: %u\n" -#: pg_resetwal.c:750 +#: pg_resetwal.c:774 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "最終チェックポイントのoldestCommitTsXid: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:776 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "最終チェックポイントのnewestCommitTsXid: %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:778 #, c-format msgid "Maximum data alignment: %u\n" msgstr "最大データアラインメント: %u\n" -#: pg_resetwal.c:757 +#: pg_resetwal.c:781 #, c-format msgid "Database block size: %u\n" msgstr "データベースのブロックサイズ: %u\n" -#: pg_resetwal.c:759 +#: pg_resetwal.c:783 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "大きなリレーションのセグメント毎のブロック数:%u\n" -#: pg_resetwal.c:761 +#: pg_resetwal.c:785 #, c-format msgid "WAL block size: %u\n" msgstr "WALのブロックサイズ: %u\n" -#: pg_resetwal.c:763 pg_resetwal.c:849 +#: pg_resetwal.c:787 pg_resetwal.c:875 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "WALセグメント当たりのバイト数: %u\n" -#: pg_resetwal.c:765 +#: pg_resetwal.c:789 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "識別子の最大長: %u\n" -#: pg_resetwal.c:767 +#: pg_resetwal.c:791 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "インデックス内の最大列数: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:793 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOASTチャンクの最大サイズ: %u\n" -#: pg_resetwal.c:771 +#: pg_resetwal.c:795 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "ラージオブジェクトチャンクのサイズ: %u\n" -#: pg_resetwal.c:774 +#: pg_resetwal.c:798 #, c-format msgid "Date/time type storage: %s\n" msgstr "日付/時刻型の格納方式: %s\n" -#: pg_resetwal.c:775 +#: pg_resetwal.c:799 msgid "64-bit integers" msgstr "64ビット整数" -#: pg_resetwal.c:776 +#: pg_resetwal.c:800 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8引数の渡し方: %s\n" -#: pg_resetwal.c:777 +#: pg_resetwal.c:801 msgid "by reference" msgstr "参照渡し" -#: pg_resetwal.c:777 +#: pg_resetwal.c:801 msgid "by value" msgstr "値渡し" -#: pg_resetwal.c:778 +#: pg_resetwal.c:802 #, c-format msgid "Data page checksum version: %u\n" msgstr "データベージチェックサムのバージョン: %u\n" -#: pg_resetwal.c:792 +#: pg_resetwal.c:804 +#, c-format +msgid "Default char data signedness: %s\n" +msgstr "デフォルトのchar型の符号あり/なし: %s\n" + +#: pg_resetwal.c:805 +msgid "signed" +msgstr "signed" + +#: pg_resetwal.c:805 +msgid "unsigned" +msgstr "unsigned" + +#: pg_resetwal.c:818 #, c-format msgid "" "\n" @@ -446,102 +564,82 @@ msgstr "" "変更される値:\n" "\n" -#: pg_resetwal.c:796 +#: pg_resetwal.c:822 #, c-format msgid "First log segment after reset: %s\n" msgstr "リセット後最初のWALセグメント: %s\n" -#: pg_resetwal.c:800 +#: pg_resetwal.c:826 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:802 +#: pg_resetwal.c:828 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:804 +#: pg_resetwal.c:830 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "OldestMultiのDB: %u\n" -#: pg_resetwal.c:810 +#: pg_resetwal.c:836 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:816 +#: pg_resetwal.c:842 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:822 +#: pg_resetwal.c:848 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:824 +#: pg_resetwal.c:850 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:826 +#: pg_resetwal.c:852 #, c-format msgid "OldestXID's DB: %u\n" msgstr "OldestXIDのDB: %u\n" -#: pg_resetwal.c:832 +#: pg_resetwal.c:858 #, c-format msgid "NextXID epoch: %u\n" msgstr "NextXID基点: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:864 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:843 +#: pg_resetwal.c:869 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:926 pg_resetwal.c:979 pg_resetwal.c:1014 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" - -#: pg_resetwal.c:952 pg_resetwal.c:993 pg_resetwal.c:1031 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" - -#: pg_resetwal.c:955 pg_resetwal.c:996 pg_resetwal.c:1034 +#: pg_resetwal.c:981 pg_resetwal.c:1022 pg_resetwal.c:1060 pg_resetwal.c:1095 #, c-format msgid "could not close directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" -#: pg_resetwal.c:988 pg_resetwal.c:1026 +#: pg_resetwal.c:1014 pg_resetwal.c:1052 pg_resetwal.c:1087 #, c-format msgid "could not delete file \"%s\": %m" msgstr "ファイル\"%s\"を削除できませんでした: %m" -#: pg_resetwal.c:1098 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "ファイル\"%s\"をオープンできませんでした: %m" - -#: pg_resetwal.c:1106 pg_resetwal.c:1118 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "ファイル\"%s\"を書き出せませんでした: %m" - -#: pg_resetwal.c:1123 +#: pg_resetwal.c:1183 #, c-format msgid "fsync error: %m" msgstr "fsyncエラー: %m" -#: pg_resetwal.c:1132 +#: pg_resetwal.c:1192 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -550,17 +648,17 @@ msgstr "" "%sはPostgreSQLの先行書き込みログをリセットします。\n" "\n" -#: pg_resetwal.c:1133 +#: pg_resetwal.c:1193 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1194 #, c-format msgid " %s [OPTION]... DATADIR\n" msgstr " %s [OPTION]... DATADIR\n" -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1196 #, c-format msgid "" "\n" @@ -569,36 +667,36 @@ msgstr "" "\n" "オプション:\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1197 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR データディレクトリ\n" -#: pg_resetwal.c:1138 +#: pg_resetwal.c:1198 #, c-format msgid "" " -f, --force force update to be done even after unclean shutdown or\n" " if pg_control values had to be guessed\n" msgstr "" -" -f, --force クリーンではないシャットダウンの後、もしくはpg_controlの値の推定が\n" -" 必要となった場合でも更新を強行する\n" +" -f, --force クリーンではないシャットダウンの後、もしくはpg_control\n" +" の値の推定が必要となった場合でも更新を強行する\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1200 #, c-format msgid " -n, --dry-run no update, just show what would be done\n" msgstr " -n, --dry-run 更新をせず、単に何が行なわれるかを表示\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1201 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_resetwal.c:1142 +#: pg_resetwal.c:1202 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1204 #, c-format msgid "" "\n" @@ -607,7 +705,7 @@ msgstr "" "\n" "制御ファイルの値を上書きするためのオプション:\n" -#: pg_resetwal.c:1145 +#: pg_resetwal.c:1205 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -618,47 +716,52 @@ msgstr "" " コミットタイムスタンプを持つ最古と最新の\n" " トランザクション(0は変更しないことを意味する)\n" -#: pg_resetwal.c:1148 +#: pg_resetwal.c:1208 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr " -e, --epoch=XIDEPOCH 次のトランザクションIDの基点を設定\n" -#: pg_resetwal.c:1149 +#: pg_resetwal.c:1209 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr " -l, --next-wal-file=WALFILE 新しいWALの最小開始ポイントを設定\n" -#: pg_resetwal.c:1150 +#: pg_resetwal.c:1210 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr " -m, --multixact-ids=MXID,MXID 次および最古のマルチトランザクションIDを設定\n" -#: pg_resetwal.c:1151 +#: pg_resetwal.c:1211 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID 次のOIDを設定\n" -#: pg_resetwal.c:1152 +#: pg_resetwal.c:1212 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr " -O, --multixact-offset=OFFSET 次のマルチトランザクションオフセットを設定\n" -#: pg_resetwal.c:1153 +#: pg_resetwal.c:1213 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID 最古のトランザクションIDを設定\n" -#: pg_resetwal.c:1154 +#: pg_resetwal.c:1214 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID 次のトランザクションIDを設定\n" -#: pg_resetwal.c:1155 +#: pg_resetwal.c:1215 +#, c-format +msgid " --char-signedness=OPTION set char signedness to \"signed\" or \"unsigned\"\n" +msgstr " --char-signedness=OPTION char型を符号付きまたは符号なしに設定する\n" + +#: pg_resetwal.c:1216 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE WALセグメントのサイズ、単位はメガバイト\n" -#: pg_resetwal.c:1157 +#: pg_resetwal.c:1218 #, c-format msgid "" "\n" @@ -667,7 +770,7 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_resetwal.c:1158 +#: pg_resetwal.c:1219 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" diff --git a/src/bin/pg_resetwal/po/ka.po b/src/bin/pg_resetwal/po/ka.po index 1452936366629..033dd63d4940c 100644 --- a/src/bin/pg_resetwal/po/ka.po +++ b/src/bin/pg_resetwal/po/ka.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_resetwal (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-26 10:51+0000\n" -"PO-Revision-Date: 2024-02-11 16:08+0100\n" +"POT-Creation-Date: 2025-05-02 22:20+0000\n" +"PO-Revision-Date: 2025-05-03 01:24+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,28 +16,127 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:389 pg_resetwal.c:547 +#: pg_resetwal.c:595 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:556 pg_resetwal.c:610 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ფაილის (%s) დახურვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "ბაიტების მიმდევრობა არ ემთხვევა" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"ბაიტების მიმდევრობის შესაძლო შეუსაბამობა pg_control ფაილის შესანახად გამოყენებული \n" +"ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" +"მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 pg_resetwal.c:1158 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1166 pg_resetwal.c:1178 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + +#: ../../common/file_utils.c:75 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" + +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" + +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_resetwal.c:952 pg_resetwal.c:1005 pg_resetwal.c:1040 pg_resetwal.c:1078 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 +#: pg_resetwal.c:978 pg_resetwal.c:1019 pg_resetwal.c:1057 pg_resetwal.c:1092 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/file_utils.c:520 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "გადარქმევის შეცდომა %s - %s: %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -78,173 +177,158 @@ msgstr "არასწორი მნიშვნელობა \"%s\" პა msgid "%s must be in range %d..%d" msgstr "%s არაა საზღვრებში %d-დან %d-მდე" -#: ../../fe_utils/option_utils.c:99 -#, c-format -msgid "this build does not support sync method \"%s\"" -msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" - #: ../../fe_utils/option_utils.c:106 #, c-format msgid "unrecognized sync method: %s" msgstr "უცნობი სინქრონიზაციის მეთოდი: \"%s\"" #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 +#: pg_resetwal.c:166 pg_resetwal.c:179 pg_resetwal.c:192 pg_resetwal.c:205 +#: pg_resetwal.c:212 pg_resetwal.c:231 pg_resetwal.c:244 pg_resetwal.c:252 +#: pg_resetwal.c:272 pg_resetwal.c:283 pg_resetwal.c:317 #, c-format msgid "invalid argument for option %s" msgstr "არასწორი არგუმენტი პარამეტრისთვის: %s" -#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 -#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 -#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 -#: pg_resetwal.c:327 +#: pg_resetwal.c:167 pg_resetwal.c:180 pg_resetwal.c:193 pg_resetwal.c:206 +#: pg_resetwal.c:213 pg_resetwal.c:232 pg_resetwal.c:245 pg_resetwal.c:253 +#: pg_resetwal.c:273 pg_resetwal.c:284 pg_resetwal.c:318 pg_resetwal.c:326 +#: pg_resetwal.c:339 pg_resetwal.c:346 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_resetwal.c:169 +#: pg_resetwal.c:171 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "ტრანზაქციის ID-ის ეპოქა (-e) -1 არ უნდა იყოს" -#: pg_resetwal.c:182 +#: pg_resetwal.c:184 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "ძველი ტრანზაქციის ID (-u) %u-ზე მეტი ან ტოლი უნდა იყოს" -#: pg_resetwal.c:195 +#: pg_resetwal.c:197 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "ტრანზაქციის ID (-x) %u_ზე მეტი ან ტოლი უნდა იყოს" -#: pg_resetwal.c:217 pg_resetwal.c:221 +#: pg_resetwal.c:219 pg_resetwal.c:223 #, c-format msgid "transaction ID (-c) must be either %u or greater than or equal to %u" msgstr "ტრანზაქციის ID (-c) ან %u უნდა იყოს, ან %u-ზე მეტი ან ტოლი" -#: pg_resetwal.c:234 +#: pg_resetwal.c:236 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) 0 არ უნდა იყოს" -#: pg_resetwal.c:255 +#: pg_resetwal.c:257 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "მულტიტრანზაქციის ID (-m) 0 არ უნდა იყო" -#: pg_resetwal.c:262 +#: pg_resetwal.c:264 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "უძველესი მულტრანზაქციის ID (-m) 0 არ უნდა იყოს" -#: pg_resetwal.c:275 +#: pg_resetwal.c:277 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "მულიტრანზაქციის წანაცვლება (-O) -1 არ უნდა იყოს" -#: pg_resetwal.c:301 +#: pg_resetwal.c:303 #, c-format msgid "argument of %s must be a power of two between 1 and 1024" msgstr "%s-ის არგუმენტი 2-ის ხარისხი უნდა იყოს 1-1024 შუალედიდან" -#: pg_resetwal.c:318 +#: pg_resetwal.c:337 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_resetwal.c:326 +#: pg_resetwal.c:345 #, c-format msgid "no data directory specified" msgstr "მონაცემების საქაღალდე მითითებული არაა" -#: pg_resetwal.c:340 +#: pg_resetwal.c:359 #, c-format msgid "cannot be executed by \"root\"" msgstr "root-ით ვერ გაეშვება" -#: pg_resetwal.c:341 +#: pg_resetwal.c:360 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "%s PostgreSQL-ის ზემომხმარებლით უნდა გაუშვათ." -#: pg_resetwal.c:351 +#: pg_resetwal.c:370 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "საქაღალდის წვდომების წაკითხვა შეუძლებელია \"%s\": %m" -#: pg_resetwal.c:357 +#: pg_resetwal.c:376 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "საქაღალდის %s-ზე შეცვლის შეცდომა: %m" -#: pg_resetwal.c:370 pg_resetwal.c:525 pg_resetwal.c:573 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" - -#: pg_resetwal.c:375 +#: pg_resetwal.c:394 #, c-format msgid "lock file \"%s\" exists" msgstr "ბლოკის ფაილი არსებობს: %s" -#: pg_resetwal.c:376 +#: pg_resetwal.c:395 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "სერვერი გაშვებულია? თუ არა, წაშალეთ ბლოკის ფაილი და თავიდან სცადეთ." -#: pg_resetwal.c:475 +#: pg_resetwal.c:497 #, c-format msgid "not proceeding because control file values were guessed" msgstr "არ გავაგრძელებ, რადგან კონტროლი ფაილის მნიშვნელობებს ჩემით მივხვდი" -#: pg_resetwal.c:476 +#: pg_resetwal.c:498 #, c-format msgid "If these values seem acceptable, use -f to force reset." msgstr "თუ ეს მნიშვნელობები მისაღებია, ძალით ჩამოსაყრელად გამოიყენეთ -f ." -#: pg_resetwal.c:485 +#: pg_resetwal.c:507 #, c-format msgid "database server was not shut down cleanly" msgstr "მონაცემთა ბაზა წესების დაცვით არ გათიშულა" -#: pg_resetwal.c:486 +#: pg_resetwal.c:508 #, c-format msgid "Resetting the write-ahead log might cause data to be lost." msgstr "წინასწარ-ჩაწერადი ჟურნალის ჩამოყრამ, შეიძლება, მონაცემების დაკარგვა გამოიწვიოს." -#: pg_resetwal.c:487 +#: pg_resetwal.c:509 #, c-format msgid "If you want to proceed anyway, use -f to force reset." msgstr "თუ ეს მნიშვნელობები მისაღებია, ძალით ჩამოსაყრელად გამოიყენეთ -f ." -#: pg_resetwal.c:500 +#: pg_resetwal.c:522 #, c-format msgid "Write-ahead log reset\n" msgstr "წინასწარ-ჩაწერი ჟურნალის საწყის მნიშვნელობაზე დაბრუნება\n" -#: pg_resetwal.c:532 +#: pg_resetwal.c:554 #, c-format msgid "unexpected empty file \"%s\"" msgstr "მოულოდნელად ფაილი ცარიელია: \"%s\"" -#: pg_resetwal.c:534 pg_resetwal.c:588 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" - -#: pg_resetwal.c:542 +#: pg_resetwal.c:564 #, c-format msgid "data directory is of wrong version" msgstr "მონაცემების საქაღალდე არასწორ ვერსიას ეკუთვნის" -#: pg_resetwal.c:543 +#: pg_resetwal.c:565 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "ფაილი \"%s\" შეიცავს \"%s\"-ს, რომელიც ამ პროგრამის ვერსიასთან (%s) შეუთავსებელია." -#: pg_resetwal.c:576 +#: pg_resetwal.c:598 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -255,24 +339,24 @@ msgstr "" " touch %s\n" "და თავიდან სცადეთ." -#: pg_resetwal.c:604 +#: pg_resetwal.c:626 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_control არსებობს, მაგრამ გააჩნია არასწორი CRC; ფრთხილად" -#: pg_resetwal.c:613 +#: pg_resetwal.c:635 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" msgstr[0] "pg_control WAL-ის არასწორი სეგმენტის ზომას (%d ბაიტი) მიუთითებს; ფრთხილად" msgstr[1] "pg_control WAL-ის არასწორი სეგმენტის ზომას (%d ბაიტი) მიუთითებს; ფრთხილად" -#: pg_resetwal.c:624 +#: pg_resetwal.c:646 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_control არსებობს, მაგრამ ან გაფუჭებულია, ან ძველი ვერსია; იგნორირებულია" -#: pg_resetwal.c:719 +#: pg_resetwal.c:741 #, c-format msgid "" "Guessed pg_control values:\n" @@ -281,7 +365,7 @@ msgstr "" "Pg_control გამოცნობილი მნიშვნელობები:\n" "\n" -#: pg_resetwal.c:721 +#: pg_resetwal.c:743 #, c-format msgid "" "Current pg_control values:\n" @@ -290,167 +374,180 @@ msgstr "" "Pg_control მიმდინარე მნიშვნელობები:\n" "\n" -#: pg_resetwal.c:723 +#: pg_resetwal.c:745 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control ვერსიის ნომერი: %u\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:747 #, c-format msgid "Catalog version number: %u\n" msgstr "კატალოგის ვერსიის ნომერი: %u\n" -#: pg_resetwal.c:727 +#: pg_resetwal.c:749 #, c-format -msgid "Database system identifier: %llu\n" -msgstr "ბაზის სისტემური იდენტიფიკატორი: %llu\n" +msgid "Database system identifier: %\n" +msgstr "ბაზის სისტემური იდენტიფიკატორი: %\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:751 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "უახლესი საკონტროლო წერტილისTimeLineID: %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:753 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "უახლესი უკანასკნელი საკონტროლო წერტილის full_page_writes: %s\n" -#: pg_resetwal.c:732 +#: pg_resetwal.c:754 msgid "off" msgstr "გამორთული" -#: pg_resetwal.c:732 +#: pg_resetwal.c:754 msgid "on" msgstr "ჩართ" -#: pg_resetwal.c:733 +#: pg_resetwal.c:755 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "უახლესი საკონტროლო წერტილის NextXID: %u:%u\n" -#: pg_resetwal.c:736 +#: pg_resetwal.c:758 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextOID: %u\n" -#: pg_resetwal.c:738 +#: pg_resetwal.c:760 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextMultiXactId: %u\n" -#: pg_resetwal.c:740 +#: pg_resetwal.c:762 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "უახლესი საკონტროლო წერტილის NextMultiOffset: %u\n" -#: pg_resetwal.c:742 +#: pg_resetwal.c:764 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestXID: %u\n" -#: pg_resetwal.c:744 +#: pg_resetwal.c:766 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestXID's DB: %u\n" -#: pg_resetwal.c:746 +#: pg_resetwal.c:768 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestActiveXID: %u\n" -#: pg_resetwal.c:748 +#: pg_resetwal.c:770 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestMultiXid: %u\n" -#: pg_resetwal.c:750 +#: pg_resetwal.c:772 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "უახლესი საკონტროლო წერტილის oldestMulti's DB: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:774 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "უახლესი საკონტროლო წერტილის oldestCommitTsXid:%u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:776 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "უახლესი საკონტროლო წერტილის newestCommitTsXid:%u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:778 #, c-format msgid "Maximum data alignment: %u\n" msgstr "მონაცემების სწორების მაქსიმუმი: %u\n" -#: pg_resetwal.c:759 +#: pg_resetwal.c:781 #, c-format msgid "Database block size: %u\n" msgstr "ბაზის ბლოკის ზომა: %u\n" -#: pg_resetwal.c:761 +#: pg_resetwal.c:783 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "დიდი ურთიერთობის სეგმენტები თითოეულ ბლოკში: %u\n" -#: pg_resetwal.c:763 +#: pg_resetwal.c:785 #, c-format msgid "WAL block size: %u\n" msgstr "WAL ბლოკის ზომა: %u\n" -#: pg_resetwal.c:765 pg_resetwal.c:851 +#: pg_resetwal.c:787 pg_resetwal.c:875 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "ბაიტები თითოეულ WAL სეგმენტში: %u\n" -#: pg_resetwal.c:767 +#: pg_resetwal.c:789 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "იდენტიფიკატორების მაქსიმალური სიგრძე: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:791 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "ინდექსში სვეტების მაქსიმალური რაოდენობა: %u\n" -#: pg_resetwal.c:771 +#: pg_resetwal.c:793 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOAST ნაგლეჯის მაქსიმალური ზომა: %u\n" -#: pg_resetwal.c:773 +#: pg_resetwal.c:795 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "დიდი ობიექტის ნაგლეჯის ზომა: %u\n" -#: pg_resetwal.c:776 +#: pg_resetwal.c:798 #, c-format msgid "Date/time type storage: %s\n" msgstr "თარიღის ტიპის საცავი: %s\n" -#: pg_resetwal.c:777 +#: pg_resetwal.c:799 msgid "64-bit integers" msgstr "64-ბიტიანი მთელ რიცხვები" -#: pg_resetwal.c:778 +#: pg_resetwal.c:800 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8 არგუმენტის გადაცემა: %s\n" -#: pg_resetwal.c:779 +#: pg_resetwal.c:801 msgid "by reference" msgstr "ბმით" -#: pg_resetwal.c:779 +#: pg_resetwal.c:801 msgid "by value" msgstr "მნიშვნელობით" -#: pg_resetwal.c:780 +#: pg_resetwal.c:802 #, c-format msgid "Data page checksum version: %u\n" msgstr "მონაცემების გვერდის საკონტროლო ჯამის ვერსია: %u\n" -#: pg_resetwal.c:794 +#: pg_resetwal.c:804 +#, c-format +msgid "Default char data signedness: %s\n" +msgstr "ნაგულისხმევი სტრიქონის მონაცემების ნიშნიანობა: %s\n" + +#: pg_resetwal.c:805 +msgid "signed" +msgstr "ნიშნიანი" + +#: pg_resetwal.c:805 +msgid "unsigned" +msgstr "უნიშნო" + +#: pg_resetwal.c:818 #, c-format msgid "" "\n" @@ -463,102 +560,82 @@ msgstr "" "შესაცვლელი მნიშვნელობები:\n" "\n" -#: pg_resetwal.c:798 +#: pg_resetwal.c:822 #, c-format msgid "First log segment after reset: %s\n" msgstr "საწყის მნიშვნელობაზე დაბრუნების შემდეგ ჟურნალის პირველი სეგმენტი: %s\n" -#: pg_resetwal.c:802 +#: pg_resetwal.c:826 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:804 +#: pg_resetwal.c:828 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:806 +#: pg_resetwal.c:830 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "OldestMulti's DB: %u\n" -#: pg_resetwal.c:812 +#: pg_resetwal.c:836 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:818 +#: pg_resetwal.c:842 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:824 +#: pg_resetwal.c:848 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:826 +#: pg_resetwal.c:850 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:828 +#: pg_resetwal.c:852 #, c-format msgid "OldestXID's DB: %u\n" msgstr "OldestXID's DB: %u\n" -#: pg_resetwal.c:834 +#: pg_resetwal.c:858 #, c-format msgid "NextXID epoch: %u\n" msgstr "NextXID epoch: %u\n" -#: pg_resetwal.c:840 +#: pg_resetwal.c:864 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:845 +#: pg_resetwal.c:869 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" - -#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" - -#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 +#: pg_resetwal.c:981 pg_resetwal.c:1022 pg_resetwal.c:1060 pg_resetwal.c:1095 #, c-format msgid "could not close directory \"%s\": %m" msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" -#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 +#: pg_resetwal.c:1014 pg_resetwal.c:1052 pg_resetwal.c:1087 #, c-format msgid "could not delete file \"%s\": %m" msgstr "ფაილის (\"%s\") წაშლის შეცდომა: %m" -#: pg_resetwal.c:1134 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" - -#: pg_resetwal.c:1142 pg_resetwal.c:1154 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" - -#: pg_resetwal.c:1159 +#: pg_resetwal.c:1183 #, c-format msgid "fsync error: %m" msgstr "fsync error: %m" -#: pg_resetwal.c:1168 +#: pg_resetwal.c:1192 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -567,17 +644,17 @@ msgstr "" "%s PostgreSQL-ის წინასწარ-ჩაწერად ჟურნალს საწყის მნიშვნელობაზე აბრუნებს.\n" "\n" -#: pg_resetwal.c:1169 +#: pg_resetwal.c:1193 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_resetwal.c:1170 +#: pg_resetwal.c:1194 #, c-format msgid " %s [OPTION]... DATADIR\n" msgstr " %s [პარამეტრი]... [მონაცემებისსაქაღალდე]\n" -#: pg_resetwal.c:1172 +#: pg_resetwal.c:1196 #, c-format msgid "" "\n" @@ -586,12 +663,12 @@ msgstr "" "\n" "პარამეტრები:\n" -#: pg_resetwal.c:1173 +#: pg_resetwal.c:1197 #, c-format msgid " [-D, --pgdata=]DATADIR data directory\n" msgstr " [-D, --pgdata=]DATADIR მონაცემების საქაღალდე\n" -#: pg_resetwal.c:1174 +#: pg_resetwal.c:1198 #, c-format msgid "" " -f, --force force update to be done even after unclean shutdown or\n" @@ -600,22 +677,22 @@ msgstr "" " -f, --force ნაძალადევი განახლების შესრულებას მას შემდეგაც კი, თუ პროცესი არასწორად გაითიშა,\n" " ან, თუ pg_control-ის მნიშვნელობების მიხვედრა მომიწია\n" -#: pg_resetwal.c:1176 +#: pg_resetwal.c:1200 #, c-format msgid " -n, --dry-run no update, just show what would be done\n" msgstr " -n, --dry-run განახლების გარეშე. უბრალოდ ნაჩვენები იქნება, რა მოხდებოდა\n" -#: pg_resetwal.c:1177 +#: pg_resetwal.c:1201 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_resetwal.c:1178 +#: pg_resetwal.c:1202 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_resetwal.c:1180 +#: pg_resetwal.c:1204 #, c-format msgid "" "\n" @@ -624,7 +701,7 @@ msgstr "" "\n" "პარამეტრები კონტროლის ფაილის მნიშვნელობის გადასაფარად:\n" -#: pg_resetwal.c:1181 +#: pg_resetwal.c:1205 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -635,47 +712,52 @@ msgstr "" " უახლესი და უძველესი ტრანზაქციების მითითება,\n" " დროის შტამპის მატარებლით(0 ნიშნავს, რომ არ შეიცვლება)\n" -#: pg_resetwal.c:1184 +#: pg_resetwal.c:1208 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr " -e, --epoch=XIDEPOCH შემდეგი ტრანზაქციის ID-ის ეპოქსი დაყენება\n" -#: pg_resetwal.c:1185 +#: pg_resetwal.c:1209 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr " -l, --next-wal-file=WALFILE ახალი WAL-ის მინიმალური საწყისი მდებარეობის დაყენება\n" -#: pg_resetwal.c:1186 +#: pg_resetwal.c:1210 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr " -m, --multixact-ids=MXID,MXID შემდეგი და უძველესი მულტრანზაქციის ID-ების დაყენება\n" -#: pg_resetwal.c:1187 +#: pg_resetwal.c:1211 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID შემდეგი OID-ის დაყენება\n" -#: pg_resetwal.c:1188 +#: pg_resetwal.c:1212 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr " -O, --multixact-offset=წანაცვლება შემდეგი მულტიტრანზაქციის წანაცვლების დაყენება\n" -#: pg_resetwal.c:1189 +#: pg_resetwal.c:1213 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID უძველესი ტრანზაქციის ID-ის დაყენება\n" -#: pg_resetwal.c:1190 +#: pg_resetwal.c:1214 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID შემდეგი ტრანზაქციის ID-ის დაყენება\n" -#: pg_resetwal.c:1191 +#: pg_resetwal.c:1215 +#, c-format +msgid " --char-signedness=OPTION set char signedness to \"signed\" or \"unsigned\"\n" +msgstr " --char-signedness=OPTION სიმბოლოს ნიშნიანობის დაყენება \"signed\"-ზე, ან \"unsigned\"-ზე\n" + +#: pg_resetwal.c:1216 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=ზომა WAL სეგმენტების ზომა, მეგაბაიტებში\n" -#: pg_resetwal.c:1193 +#: pg_resetwal.c:1218 #, c-format msgid "" "\n" @@ -684,7 +766,7 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_resetwal.c:1194 +#: pg_resetwal.c:1219 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" diff --git a/src/bin/pg_resetwal/po/ko.po b/src/bin/pg_resetwal/po/ko.po index 64d8a8fb01b77..c27ba3a26276e 100644 --- a/src/bin/pg_resetwal/po/ko.po +++ b/src/bin/pg_resetwal/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_resetwal (PostgreSQL) 16\n" +"Project-Id-Version: pg_resetwal (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:50+0000\n" -"PO-Revision-Date: 2023-09-08 16:10+0900\n" +"POT-Creation-Date: 2025-01-17 04:50+0000\n" +"PO-Revision-Date: 2025-01-16 16:15+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -35,6 +35,108 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %d / %zu 읽었음" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "\"%s\" 파일을 닫을 수 없음: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 불일치" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"바이트 순서 일치하지 않는 문제\n" +"바이트 순서 정보는 pg_control 파일을 저장할 때 사용되는데,\n" +"이 파일의 바이트 순서 정보와 이 프로그램에서 사용하는 순서 정보가 다릅니다.\n" +"이럴 경우, 출력 결과가 바르지 않을 수 있고,\n" +"설치된 PostgreSQL 프로그램과 데이터 디렉터리가 호환되지 않을 수 있습니다." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "\"%s\" 파일 쓰기 실패: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일 상태 정보를 구할 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -65,166 +167,172 @@ msgstr "상속된 토큰으로 재실행할 수 없음: 오류 코드 %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값이 잘 못됨, 해당 옵션: %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 값의 허용 범위: %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "%s 옵션의 잘못된 인자" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "트랜잭션 ID epoch (-e) 값은 -1이 아니여야함" -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "제일 오래된 트랜잭션 ID (-u)는 %u 보다 크거나 같아야 함" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "트랜잭션 ID (-x)는 %u 보다 크거나 같아야 함" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "-c 옵션으로 지정한 트랜잭션 ID는 0이거나 2이상이어야 함" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "-c 옵션으로 지정한 트랜잭션 ID는 %u이거나 %u이상이어야 함" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) 값은 0이 아니여야함" -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "멀티트랜잭션 ID (-m) 값은 0이 아니여야함" -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "제일 오래된 멀티트랜잭션 ID (-m) 값은 0이 아니여야함" -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "멀티트랜잭션 옵셋 (-O) 값은 -1이 아니여야함" -#: pg_resetwal.c:296 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "--wal-segsize 값은 숫자여야 합니다" - -#: pg_resetwal.c:298 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "--wal-segsize 값은 1부터 1024사이 2^n 값이어야 합니다" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "%s 값은 1부터 1024사이 2^n 값이어야 합니다" -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인수를 지정했습니다. (처음 \"%s\")" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "데이터 디렉터리를 지정하지 않았음" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\" 계정으로는 실행 할 수 없음" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "PostgreSQL superuser로 %s 프로그램을 실행하십시오." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "\"%s\" 디렉터리 읽기 권한 없음: %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "\"%s\" 이름의 디렉터리로 이동할 수 없습니다: %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "\"%s\" 잠금 파일이 있음" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "" "서버가 가동중인가요? 그렇지 않다면, 이 파일을 지우고 다시 시도하십시오." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "" -"\n" -"If these values seem acceptable, use -f to force reset.\n" -msgstr "" -"\n" -"이 설정값들이 타당하다고 판단되면, 강제로 갱신하려면, -f 옵션을 쓰세요.\n" +msgid "not proceeding because control file values were guessed" +msgstr "컨트롤 파일 값들이 추정되었기에 더 이상 진행하지 않습니다." -#: pg_resetwal.c:479 +#: pg_resetwal.c:476 #, c-format -msgid "" -"The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" +msgid "If these values seem acceptable, use -f to force reset." msgstr "" -"이 데이터베이스 서버는 정상적으로 중지되지 못했습니다.\n" -"트랜잭션 로그를 다시 설정하는 것은 자료 손실을 야기할 수 있습니다.\n" -"그럼에도 불구하고 진행하려면, -f 옵션을 사용해서 강제 설정을 하십시오.\n" +"이 설정값들이 타당하다고 판단되면, 강제로 갱신하려면, -f 옵션을 쓰세요." -#: pg_resetwal.c:493 +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "데이터베이스 서버가 깔끔하게 중지 되지 못했습니다." + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "미리 쓰기 로그를 리셋하면 자료를 잃어버릴 수 있습니다." + +#: pg_resetwal.c:487 +#, c-format +msgid "If you want to proceed anyway, use -f to force reset." +msgstr "이 설정값들로 강제로 갱신하려면, -f 옵션을 쓰세요." + +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" msgstr "트랜잭션 로그 재설정\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "\"%s\" 파일은 예상치 않게 비었음" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "\"%s\" 파일을 읽을 수 없음: %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "잘못된 버전의 데이터 디렉터리입니다." -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "" "File \"%s\" contains \"%s\", which is not compatible with this program's " "version \"%s\"." msgstr "\"%s\" 파일 버전은 \"%s\", 이 프로그램 버전은 \"%s\"." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -235,12 +343,12 @@ msgstr "" "보십시오.\n" " touch %s" -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_control 파일이 있지만, CRC값이 잘못되었습니다; 경고와 함께 진행함" -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "" "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" @@ -251,12 +359,12 @@ msgstr[0] "" "pg_control 파일에 잘못된 WAL 조각 파일 크기(%d 바이트)가 지정됨; 경고와 함께 " "진행함" -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_control 파일이 있지만, 손상되었거나 버전을 알 수 없음; 무시함" -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "" "Guessed pg_control values:\n" @@ -265,7 +373,7 @@ msgstr "" "추측된 pg_control 설정값들:\n" "\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "" "Current pg_control values:\n" @@ -274,167 +382,167 @@ msgstr "" "현재 pg_control 설정값들:\n" "\n" -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control 버전 번호: %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "카탈로그 버전 번호: %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "데이터베이스 시스템 식별자: %llu\n" -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "마지막 체크포인트 TimeLineID: %u\n" -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "마지막 체크포인트 full_page_writes: %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "off" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "on" -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "마지막 체크포인트 NextXID: %u:%u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "마지막 체크포인트 NextOID: %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "마지막 체크포인트 NextMultiXactId: %u\n" -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "마지막 체크포인트 NextMultiOffset: %u\n" -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "마지막 체크포인트 제일 오래된 XID: %u\n" -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "마지막 체크포인트 제일 오래된 XID의 DB:%u\n" -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "마지막 체크포인트 제일 오래된 ActiveXID:%u\n" -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "마지막 체크포인트 제일 오래된 MultiXid:%u\n" -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "마지막 체크포인트 제일 오래된 MultiXid의 DB:%u\n" -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "마지막 체크포인트 제일 오래된 CommitTsXid:%u\n" -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "마지막 체크포인트 최신 CommitTsXid: %u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "최대 자료 정렬: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "데이터베이스 블록 크기: %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "대형 릴레이션의 세그먼트당 블럭 갯수: %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "WAL 블록 크기: %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "WAL 세그먼트의 크기(byte): %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "식별자 최대 길이: %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "인덱스에서 사용하는 최대 열 수: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "TOAST 청크의 최대 크기: %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "대형객체 청크의 최대 크기: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "날짜/시간형 자료의 저장방식: %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "64-비트 정수" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Float8 인수 전달: %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "참조별" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "값별" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "데이터 페이지 체크섬 버전: %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "" "\n" @@ -447,102 +555,82 @@ msgstr "" "변경될 값:\n" "\n" -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "리셋 뒤 첫 로그 세그먼트: %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "OldestMultiXid의 DB: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "OldestXID의 DB: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "NextXID epoch: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "제일 오래된 CommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "최근 CommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "\"%s\" 디렉터리 열 수 없음: %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "\"%s\" 파일을 지울 수 없음: %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "\"%s\" 파일 쓰기 실패: %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "fsync 오류: %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -551,23 +639,65 @@ msgstr "" "%s 프로그램은 PostgreSQL 트랜잭션 로그를 다시 설정합니다.\n" "\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 +#, c-format +msgid "Usage:\n" +msgstr "사용법:\n" + +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [옵션]... DATADIR\n" + +#: pg_resetwal.c:1172 #, c-format msgid "" -"Usage:\n" -" %s [OPTION]... DATADIR\n" "\n" +"Options:\n" msgstr "" -"사용법:\n" -" %s [옵션]... DATADIR\n" "\n" +"옵션들:\n" + +#: pg_resetwal.c:1173 +#, c-format +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata=]DATADIR 데이터 디렉터리\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1174 #, c-format -msgid "Options:\n" -msgstr "옵션들:\n" +msgid "" +" -f, --force force update to be done even after unclean shutdown " +"or\n" +" if pg_control values had to be guessed\n" +msgstr "" +" -f, --force 비정상적으로 종료되었거나 pg_control 값을 추측해야\n" +" 하는 경우에도 강제로 갱신함\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr " -n, --dry-run 갱신하지 않음, 컨트롤 값들을 보여주기만함\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" + +#: pg_resetwal.c:1178 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 표시하고 종료\n" + +#: pg_resetwal.c:1180 +#, c-format +msgid "" +"\n" +"Options to override control file values:\n" +msgstr "" +"\n" +"컨트롤 파일 값을 바꿀 옵션들:\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1181 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -580,22 +710,12 @@ msgstr "" "션\n" " ID 값 (0이면 바꾸지 않음)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]DATADIR 데이터 디렉터리\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr " -e, --epoch=XIDEPOCH 다음 트랙잭션 ID epoch 지정\n" -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr " -f, --force 강제로 갱신함\n" - -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid "" " -l, --next-wal-file=WALFILE set minimum starting location for new " @@ -604,58 +724,39 @@ msgstr "" " -l, --next-wal-file=WALFILE 새 트랜잭션 로그를 위한 WAL 최소 시작 위치" "를 강제로 지정\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid "" " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr "" " -m, --multixact-ids=MXID,MXID 다음 제일 오래된 멀티트랜잭션 ID 지정\n" -#: pg_resetwal.c:1138 -#, c-format -msgid "" -" -n, --dry-run no update, just show what would be done\n" -msgstr "" -" -n, --dry-run 갱신하지 않음, 컨트롤 값들을 보여주기만 " -"함\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID 다음 OID 지정\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr " -O, --multixact-offset=OFFSET 다음 멀티트랜잭션 옵셋 지정\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID 제일 오래된 트랜잭션 ID 지정\n" -#: pg_resetwal.c:1142 -#, c-format -msgid "" -" -V, --version output version information, then exit\n" -msgstr " -V, --version 버전 정보를 보여주고 마침\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID 다음 트랜잭션 ID 지정\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE WAL 조각 파일 크기, MB 단위\n" -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help 이 도움말을 표시하고 종료\n" - -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "" "\n" @@ -664,7 +765,25 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" + +#, c-format +#~ msgid "argument of --wal-segsize must be a number" +#~ msgstr "--wal-segsize 값은 숫자여야 합니다" + +#, c-format +#~ msgid "" +#~ "The database server was not shut down cleanly.\n" +#~ "Resetting the write-ahead log might cause data to be lost.\n" +#~ "If you want to proceed anyway, use -f to force reset.\n" +#~ msgstr "" +#~ "이 데이터베이스 서버는 정상적으로 중지되지 못했습니다.\n" +#~ "트랜잭션 로그를 다시 설정하는 것은 자료 손실을 야기할 수 있습니다.\n" +#~ "그럼에도 불구하고 진행하려면, -f 옵션을 사용해서 강제 설정을 하십시오.\n" + +#, c-format +#~ msgid " -f, --force force update to be done\n" +#~ msgstr " -f, --force 강제로 갱신함\n" diff --git a/src/bin/pg_resetwal/po/meson.build b/src/bin/pg_resetwal/po/meson.build index 2f474d8f3480d..017c2c60004ec 100644 --- a/src/bin/pg_resetwal/po/meson.build +++ b/src/bin/pg_resetwal/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_resetwal-' + pg_version_major.to_string())] diff --git a/src/bin/pg_resetwal/po/ru.po b/src/bin/pg_resetwal/po/ru.po index 5f012f91f91b1..c26776baad267 100644 --- a/src/bin/pg_resetwal/po/ru.po +++ b/src/bin/pg_resetwal/po/ru.po @@ -5,13 +5,13 @@ # Oleg Bartunov , 2004. # Sergey Burladyan , 2009. # Dmitriy Olshevskiy , 2014. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_resetxlog (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-11 15:31+0300\n" -"PO-Revision-Date: 2023-09-11 16:14+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-05 12:19+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -41,6 +41,107 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "не удалось закрыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"возможно несоответствие порядка байт\n" +"Порядок байт в файле pg_control может не соответствовать используемому\n" +"этой программой. В этом случае результаты будут неверными и\n" +"установленный PostgreSQL будет несовместим с этим каталогом данных." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не удалось записать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -71,160 +172,170 @@ msgstr "не удалось перезапуститься с ограничен msgid "could not get exit code from subprocess: error code %lu" msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неверное значение \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "значение %s должно быть в диапазоне %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "недопустимый аргумент параметра %s" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "эпоха ID транзакции (-e) не должна быть равна -1" -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "ID старейшей транзакции (-u) должен быть больше или равен %u" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "ID транзакции (-x) должен быть больше или равен %u" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "ID транзакции (-c) должен быть равен 0, либо больше или равен 2" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "ID транзакции (-c) должен быть равен %u, либо больше или равен %u" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) не должен быть равен 0" -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "ID мультитранзакции (-m) не должен быть равен 0" -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "ID старейшей мультитранзакции (-m) не должен быть равен 0" -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "смещение мультитранзакции (-O) не должно быть равно -1" -#: pg_resetwal.c:296 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "аргументом --wal-segsize должно быть число" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "аргументом %s должна быть степень двух от 1 до 1024" -#: pg_resetwal.c:298 -#, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "аргументом --wal-segsize должна быть степень двух от 1 до 1024" - -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "каталог данных не указан" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "программу не должен запускать root" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Запускать %s нужно от имени суперпользователя PostgreSQL." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" -msgstr "не удалось считать права на каталог \"%s\": %m" +msgstr "не удалось прочитать права на каталог \"%s\": %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "не удалось перейти в каталог \"%s\": %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "не удалось открыть файл \"%s\" для чтения: %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "файл блокировки \"%s\" существует" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "" "Возможно, сервер запущен? Если нет, удалите этот файл и попробуйте снова." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "" -"\n" -"If these values seem acceptable, use -f to force reset.\n" +msgid "not proceeding because control file values were guessed" msgstr "" -"\n" -"Если эти значения приемлемы, выполните сброс принудительно, добавив ключ -" -"f.\n" +"выполнение прервано, так как значения из контрольного файла являются " +"предполагаемыми" -#: pg_resetwal.c:479 +#: pg_resetwal.c:476 #, c-format -msgid "" -"The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" +msgid "If these values seem acceptable, use -f to force reset." +msgstr "" +"Если эти значения всё же приемлемы, выполните сброс принудительно, добавив " +"ключ -f." + +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "сервер баз данных не был остановлен штатно" + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "Сброс журнала предзаписи может привести к потере данных." + +#: pg_resetwal.c:487 +#, c-format +msgid "If you want to proceed anyway, use -f to force reset." msgstr "" -"Сервер баз данных был остановлен некорректно.\n" -"Сброс журнала предзаписи может привести к потере данных.\n" -"Если вы хотите сбросить его, несмотря на это, добавьте ключ -f.\n" +"Если вы всё же хотите продолжить, выполните сброс принудительно, добавив " +"ключ -f." -#: pg_resetwal.c:493 +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" msgstr "Журнал предзаписи сброшен\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "файл \"%s\" оказался пустым" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не удалось прочитать файл \"%s\": %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "каталог данных имеет неверную версию" -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "" "File \"%s\" contains \"%s\", which is not compatible with this program's " @@ -232,7 +343,7 @@ msgid "" msgstr "" "Файл \"%s\" содержит строку \"%s\", а ожидается версия программы \"%s\"." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -243,14 +354,14 @@ msgstr "" " touch %s\n" "и повторите попытку." -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "" "pg_control существует, но его контрольная сумма неверна; продолжайте с " "осторожностью" -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "" "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" @@ -267,14 +378,14 @@ msgstr[2] "" "в pg_control указан некорректный размер сегмента WAL (%d Б); продолжайте с " "осторожностью" -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "" "pg_control испорчен или имеет неизвестную либо недопустимую версию; " "игнорируется..." -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "" "Guessed pg_control values:\n" @@ -283,7 +394,7 @@ msgstr "" "Предполагаемые значения pg_control:\n" "\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "" "Current pg_control values:\n" @@ -292,181 +403,181 @@ msgstr "" "Текущие значения pg_control:\n" "\n" -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "Номер версии pg_control: %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "Номер версии каталога: %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "Идентификатор системы баз данных: %llu\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Линия времени последней конт. точки: %u\n" # skip-rule: no-space-after-period -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Режим full_page_writes последней к.т: %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "выкл." -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "вкл." # skip-rule: capital-letter-first -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID последней конт. точки: %u:%u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId послед. конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset послед. конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "БД с oldestXID последней конт. точки: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID последней к. т.: %u\n" # skip-rule: capital-letter-first -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid последней конт. точки: %u\n" # skip-rule: capital-letter-first, double-space -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "БД с oldestMulti последней к. т.: %u\n" # skip-rule: capital-letter-first, double-space -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid последней к. т.: %u\n" # skip-rule: capital-letter-first, double-space -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid последней к. т.: %u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Макс. предел выравнивания данных: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "Размер блока БД: %u\n" # skip-rule: double-space -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Блоков в макс. сегменте отношений: %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "Размер блока WAL: %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Байт в сегменте WAL: %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Максимальная длина идентификаторов: %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Макс. число столбцов в индексе: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Максимальный размер порции TOAST: %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Размер порции большого объекта: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "Формат хранения даты/времени: %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "64-битные целые" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Передача аргумента float8: %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "по ссылке" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "по значению" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "Версия контрольных сумм страниц: %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "" "\n" @@ -479,102 +590,82 @@ msgstr "" "Значения, которые будут изменены:\n" "\n" -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "Первый сегмент журнала после сброса: %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "БД с oldestMultiXid: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "БД с oldestXID: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "Эпоха NextXID: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не удалось открыть каталог \"%s\": %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не удалось прочитать каталог \"%s\": %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не удалось закрыть каталог \"%s\": %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "ошибка удаления файла \"%s\": %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "не удалось записать файл \"%s\": %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "ошибка синхронизации с ФС: %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -583,23 +674,69 @@ msgstr "" "%s сбрасывает журнал предзаписи PostgreSQL.\n" "\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 +#, c-format +msgid "Usage:\n" +msgstr "Использование:\n" + +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [ПАРАМЕТР]... КАТ_ДАННЫХ\n" + +#: pg_resetwal.c:1172 #, c-format msgid "" -"Usage:\n" -" %s [OPTION]... DATADIR\n" "\n" +"Options:\n" msgstr "" -"Использование:\n" -" %s [ПАРАМЕТР]... КАТ_ДАННЫХ\n" "\n" +"Параметры:\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1173 #, c-format -msgid "Options:\n" -msgstr "Параметры:\n" +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata=]КАТ_ДАННЫХ каталог данных\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1174 +#, c-format +msgid "" +" -f, --force force update to be done even after unclean shutdown " +"or\n" +" if pg_control values had to be guessed\n" +msgstr "" +" -f, --force принудительно произвести изменения, даже в случае\n" +" недостоверных значений pg_control или после " +"нештатного\n" +" отключения сервера\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr "" +" -n, --dry-run показать, какие действия будут выполнены, но не\n" +" выполнять их\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_resetwal.c:1178 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_resetwal.c:1180 +#, c-format +msgid "" +"\n" +"Options to override control file values:\n" +msgstr "" +"\n" +"Параметры, переопределяющие значения из контрольного файла:\n" + +#: pg_resetwal.c:1181 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -611,24 +748,13 @@ msgstr "" " задать старейшую и новейшую транзакции,\n" " несущие метки времени (0 — не менять)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]КАТ_ДАННЫХ каталог данных\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr "" " -e, --epoch=XIDEPOCH задать эпоху для ID следующей транзакции\n" -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr "" -" -f, --force принудительное выполнение операции\n" - -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid "" " -l, --next-wal-file=WALFILE set minimum starting location for new " @@ -637,7 +763,7 @@ msgstr "" " -l, --next-wal-file=ФАЙЛ_WAL задать минимальное начальное положение\n" " для нового WAL\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid "" " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" @@ -645,55 +771,35 @@ msgstr "" " -m, --multixact-ids=MXID,MXID задать ID следующей и старейшей\n" " мультитранзакции\n" -#: pg_resetwal.c:1138 -#, c-format -msgid "" -" -n, --dry-run no update, just show what would be done\n" -msgstr "" -" -n, --dry-run показать, какие действия будут " -"выполнены,\n" -" но не выполнять их\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID задать следующий OID\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr "" " -O, --multixact-offset=СМЕЩЕНИЕ задать смещение следующей " "мультитранзакции\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID задать ID старейшей ID\n" -#: pg_resetwal.c:1142 -#, c-format -msgid "" -" -V, --version output version information, then exit\n" -msgstr " -V, --version показать версию и выйти\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID задать ID следующей транзакции\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr "" " --wal-segsize=РАЗМЕР размер сегментов WAL (в мегабайтах)\n" -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help показать эту справку и выйти\n" - -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "" "\n" @@ -702,11 +808,30 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" +#, c-format +#~ msgid "argument of --wal-segsize must be a number" +#~ msgstr "аргументом --wal-segsize должно быть число" + +#, c-format +#~ msgid "" +#~ "The database server was not shut down cleanly.\n" +#~ "Resetting the write-ahead log might cause data to be lost.\n" +#~ "If you want to proceed anyway, use -f to force reset.\n" +#~ msgstr "" +#~ "Сервер баз данных был остановлен некорректно.\n" +#~ "Сброс журнала предзаписи может привести к потере данных.\n" +#~ "Если вы хотите сбросить его, несмотря на это, добавьте ключ -f.\n" + +#, c-format +#~ msgid " -f, --force force update to be done\n" +#~ msgstr "" +#~ " -f, --force принудительное выполнение операции\n" + #, c-format #~ msgid "could not load library \"%s\": error code %lu" #~ msgstr "не удалось загрузить библиотеку \"%s\" (код ошибки: %lu)" diff --git a/src/bin/pg_resetwal/po/sv.po b/src/bin/pg_resetwal/po/sv.po index 7bf463e54b1b4..71529e5ebf276 100644 --- a/src/bin/pg_resetwal/po/sv.po +++ b/src/bin/pg_resetwal/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for resetxlog. -# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Peter Eisentraut , 2010. # Mats Erik Andersson , 2014. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-31 19:50+0000\n" -"PO-Revision-Date: 2023-08-31 22:00+0200\n" +"POT-Creation-Date: 2024-07-12 17:51+0000\n" +"PO-Revision-Date: 2024-07-12 23:47+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -37,6 +37,106 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "kunde inte stänga fil \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"möjligt fel i byteordning\n" +"Den byteordning som filen från pg_control lagrats med passar kanske\n" +"inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" +"och PostgreSQL-installationen vara inkompatibel med databaskatalogen." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "kunde inte skriva fil \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -67,164 +167,168 @@ msgstr "kunde inte köra igen med token för begränsad åtkomst: felkod %lu" msgid "could not get exit code from subprocess: error code %lu" msgstr "kunde inte hämta statuskod för underprocess: felkod %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s måste vara i intervallet %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "ogiltigt argument för flaggan %s" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "Epoch (-e) för transaktions-ID får inte vara -1." -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "äldsta transaktions-ID (-u) måste vara större än eller lika med %u" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "transaktions-ID (-x) måste vara större än eller lika med %u" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "transaktions-ID (-c) måste antingen vara 0 eller större än eller lika med 2" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "transaktions-ID (-c) måste antingen vara %u eller större än eller lika med %u" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) får inte vara 0." -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "Multitransaktions-ID (-m) får inte vara 0." -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "Äldsta multitransaktions-ID (-m) får inte vara 0." -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "Multitransaktionsoffset (-O) får inte vara -1." -#: pg_resetwal.c:296 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "argumentet till --wal-segsize måste vara ett tal" - -#: pg_resetwal.c:298 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "argumentet till --wal-segsize måste vara en tvåpotens mellan 1 och 1024" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "argumentet till %s måste vara en tvåpotens mellan 1 och 1024" -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "ingen datakatalog angiven" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "kan inte köras av \"root\"" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Du måste köra %s som PostgreSQL:s superuser." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "kunde inte läsa rättigheter på katalog \"%s\": %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "kunde inte byta katalog till \"%s\": %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "kunde inte öppna filen \"%s\" för läsning: %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "låsfil med namn \"%s\" finns redan" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "Kör servern redan? Om inte, radera låsfilen och försök igen." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "" -"\n" -"If these values seem acceptable, use -f to force reset.\n" -msgstr "" -"\n" -"Om dessa värden verkar godtagbara, använd då -f för att\n" -"framtvinga återställning.\n" +msgid "not proceeding because control file values were guessed" +msgstr "fortsätter inte eftersom kontrollfilens värden har gissats" -#: pg_resetwal.c:479 +#: pg_resetwal.c:476 #, c-format -msgid "" -"The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" -msgstr "" -"Databasservern stängdes inte av ordentligt. Att återställa\n" -"write-ahead-loggen kan medföra att data förloras. Om du ändå\n" -"vill fortsätta, använd -f för att framtvinga återställning.\n" +msgid "If these values seem acceptable, use -f to force reset." +msgstr "Om dessa värden verkar godtagbara, använd då -f för att framtvinga återställning." + +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "databasservern stångdes inte ner utan fel" + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "Nollställa write-ahead-loggen kan göra att data förloras." + +#: pg_resetwal.c:487 +#, c-format +msgid "If you want to proceed anyway, use -f to force reset." +msgstr "Om du vill fortsätta ändå, använd -f för att framtvinga återställning." -#: pg_resetwal.c:493 +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" msgstr "Återställning av write-ahead-log\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "oväntad tom fil \"%s\"" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "kunde inte läsa fil \"%s\": %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "datakatalogen har fel version" -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "Filen \"%s\" innehåller \"%s\", vilket inte är kompatibelt med detta programmets version \"%s\"." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "" "If you are sure the data directory path is correct, execute\n" @@ -234,24 +338,24 @@ msgstr "" "Om du är säker på att sökvägen till datakatalogen är riktig,\n" "utför då \"touch %s\" och försök sedan igen." -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_control existerar men har ogiltig CRC. Fortsätt med varsamhet." -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" msgstr[0] "pg_control anger ogiltig WAL-segmentstorlek (%d byte); fortsätt med varsamhet." msgstr[1] "pg_control anger ogiltig WAL-segmentstorlek (%d byte); fortsätt med varsamhet." -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_control existerar men är trasig eller har fel version. Den ignoreras." -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "" "Guessed pg_control values:\n" @@ -260,7 +364,7 @@ msgstr "" "Gissade värden för pg_control:\n" "\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "" "Current pg_control values:\n" @@ -272,168 +376,168 @@ msgstr "" # November 26th, 2014: Insert six additional space characters # for best alignment with Swedish translation. # Translations should be checked against those of pg_controldata. -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "Versionsnummer för pg_control: %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "Katalogversion: %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "Databasens systemidentifierare: %llu\n" -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "TimeLineID vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Senaste kontrollpunktens full_page_writes: %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "av" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "på" -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "NextXID vid senaste kontrollpunkt: %u:%u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "NextOID vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "NextMultiXactId vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "NextMultiOffset vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "oldestXID vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "DB för oldestXID vid senaste kontrollpunkt: %u\n" # FIXME: too wide -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "oldestActiveXID vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "oldestMultiXid vid senaste kontrollpunkt: %u\n" -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "DB för oldestMulti vid senaste kontrollpkt: %u\n" -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "oldestCommitTsXid vid senaste kontrollpunkt:%u\n" -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "newestCommitTsXid vid senaste kontrollpunkt:%u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Maximal jämkning av data (alignment): %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "Databasens blockstorlek: %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Block per segment i en stor relation: %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "Blockstorlek i transaktionsloggen: %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Segmentstorlek i transaktionsloggen: %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Maximal längd för identifierare: %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Maximalt antal kolonner i ett index: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Maximal storlek för en TOAST-enhet: %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Storlek för large-object-enheter: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "Representation av dag och tid: %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "64-bitars heltal" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Åtkomst till float8-argument: %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "referens" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "värdeåtkomst" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "Checksummaversion för datasidor: %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "" "\n" @@ -448,102 +552,82 @@ msgstr "" # November 26th, 2014: Insert additional spacing to fit # with the first translated text, which uses most characters. -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "Första loggsegment efter återställning: %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "DB för OldestMulti: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "DB för OldestXID: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "Epoch för NextXID: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "kunde inte öppna katalog \"%s\": %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "kunde inte läsa katalog \"%s\": %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "kunde inte stänga katalog \"%s\": %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "kunde inte radera fil \"%s\": %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "kunde inte skriva fil \"%s\": %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "misslyckad fsync: %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "" "%s resets the PostgreSQL write-ahead log.\n" @@ -552,23 +636,62 @@ msgstr "" "%s återställer write-ahead-log för PostgreSQL.\n" "\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 +#, c-format +msgid "Usage:\n" +msgstr "Användning:\n" + +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [FLAGGA]... DATAKATALOG\n" + +#: pg_resetwal.c:1172 #, c-format msgid "" -"Usage:\n" -" %s [OPTION]... DATADIR\n" "\n" +"Options:\n" msgstr "" -"Användning:\n" -" %s [FLAGGA]... DATAKATALOG\n" "\n" +"Flaggor:\n" + +#: pg_resetwal.c:1173 +#, c-format +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata=]DATADIR datakatalog\n" + +#: pg_resetwal.c:1174 +#, c-format +msgid "" +" -f, --force force update to be done even after unclean shutdown or\n" +" if pg_control values had to be guessed\n" +msgstr "" +" -f, --force tvinga uppdatering även om servern inte stängts ner\n" +" korrekt eller om värden i pg_control har gissats\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr " -n, --dry-run ingen updatering; visa bara planerade åtgärder\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1178 #, c-format -msgid "Options:\n" -msgstr "Flaggor:\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa den här hjälpen, avsluta sedan\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1180 +#, c-format +msgid "" +"\n" +"Options to override control file values:\n" +msgstr "\nFlaggor som övertrumfar värden i kontrollfilen:\n" + +#: pg_resetwal.c:1181 #, c-format msgid "" " -c, --commit-timestamp-ids=XID,XID\n" @@ -580,72 +703,47 @@ msgstr "" " kan ha commit-tidstämpel (noll betyder\n" " ingen ändring)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]DATADIR datakatalog\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr " -e, --epoch=XIDEPOCH sätter epoch för nästa transaktions-ID\n" -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr " -f, --force framtvinga uppdatering\n" - -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr " -l, --next-wal-file=WALFIL sätt minsta startposition för ny WAL\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr " -m, --multixact-ids=MXID,MXID sätt nästa och äldsta multitransaktions-ID\n" -#: pg_resetwal.c:1138 -#, c-format -msgid " -n, --dry-run no update, just show what would be done\n" -msgstr " -n, --dry-run ingen updatering; visa bara planerade åtgärder\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID sätt nästa OID\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr " -O, --multixact-offset=OFFSET sätt nästa multitransaktionsoffset\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID sätt äldsta transaktions-ID\n" -#: pg_resetwal.c:1142 -#, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version visa versionsinformation, avsluta sedan\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID sätt nästa transaktions-ID\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=STORLEK storlek på WAL-segment i megabyte\n" -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help visa denna hjälp, avsluta sedan\n" - -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "" "\n" @@ -654,15 +752,7 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "kan inte skapa token för begränsad åtkomst på denna plattorm: felkod %lu" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "kunde inte ladda länkbibliotek \"%s\": felkod %lu" diff --git a/src/bin/pg_resetwal/po/uk.po b/src/bin/pg_resetwal/po/uk.po index e761d7a0d3d9c..0b18f98387d88 100644 --- a/src/bin/pg_resetwal/po/uk.po +++ b/src/bin/pg_resetwal/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:19+0000\n" -"PO-Revision-Date: 2023-12-20 11:53\n" +"POT-Creation-Date: 2024-08-31 06:21+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_resetwal.pot\n" -"X-Crowdin-File-ID: 939\n" +"X-Crowdin-File: /REL_17_STABLE/pg_resetwal.pot\n" +"X-Crowdin-File-ID: 1010\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,6 +37,102 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../../common/controldata_utils.c:97 pg_resetwal.c:370 pg_resetwal.c:525 +#: pg_resetwal.c:573 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" + +#: ../../common/controldata_utils.c:110 pg_resetwal.c:534 pg_resetwal.c:588 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "неможливо закрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "можлива помилка у послідовності байтів.\n" +"Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 pg_resetwal.c:1134 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 pg_resetwal.c:1142 pg_resetwal.c:1154 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не вдалося записати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_resetwal.c:928 pg_resetwal.c:981 pg_resetwal.c:1016 pg_resetwal.c:1054 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: pg_resetwal.c:954 pg_resetwal.c:995 pg_resetwal.c:1033 pg_resetwal.c:1068 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: ../../common/restricted_token.c:60 #, c-format msgid "could not open process token: error code %lu" @@ -67,159 +163,168 @@ msgstr "не вдалося перезапустити з обмеженим т msgid "could not get exit code from subprocess: error code %lu" msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu" +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неприпустиме значення \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s має бути в діапазоні %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + #. translator: the second %s is a command line argument (-e, etc) -#: pg_resetwal.c:163 pg_resetwal.c:176 pg_resetwal.c:189 pg_resetwal.c:202 -#: pg_resetwal.c:209 pg_resetwal.c:228 pg_resetwal.c:241 pg_resetwal.c:249 -#: pg_resetwal.c:269 pg_resetwal.c:280 +#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 +#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 +#: pg_resetwal.c:270 pg_resetwal.c:281 #, c-format msgid "invalid argument for option %s" msgstr "неприпустимий аргумент для параметру %s" -#: pg_resetwal.c:164 pg_resetwal.c:177 pg_resetwal.c:190 pg_resetwal.c:203 -#: pg_resetwal.c:210 pg_resetwal.c:229 pg_resetwal.c:242 pg_resetwal.c:250 -#: pg_resetwal.c:270 pg_resetwal.c:281 pg_resetwal.c:303 pg_resetwal.c:316 -#: pg_resetwal.c:323 +#: pg_resetwal.c:165 pg_resetwal.c:178 pg_resetwal.c:191 pg_resetwal.c:204 +#: pg_resetwal.c:211 pg_resetwal.c:230 pg_resetwal.c:243 pg_resetwal.c:251 +#: pg_resetwal.c:271 pg_resetwal.c:282 pg_resetwal.c:307 pg_resetwal.c:320 +#: pg_resetwal.c:327 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_resetwal.c:168 +#: pg_resetwal.c:169 #, c-format msgid "transaction ID epoch (-e) must not be -1" msgstr "епоха ID транзакції (-e) не повинна бути -1" -#: pg_resetwal.c:181 +#: pg_resetwal.c:182 #, c-format msgid "oldest transaction ID (-u) must be greater than or equal to %u" msgstr "найстаріший ID транзакції (-u) має бути більший або рівним %u" -#: pg_resetwal.c:194 +#: pg_resetwal.c:195 #, c-format msgid "transaction ID (-x) must be greater than or equal to %u" msgstr "ID транзакції (-x) має бути більшим чи рівним %u" -#: pg_resetwal.c:216 pg_resetwal.c:220 +#: pg_resetwal.c:217 pg_resetwal.c:221 #, c-format -msgid "transaction ID (-c) must be either 0 or greater than or equal to 2" -msgstr "ID транзакції (-c) повинен дорівнювати 0, бути більшим за або дорівнювати 2" +msgid "transaction ID (-c) must be either %u or greater than or equal to %u" +msgstr "ідентифікатор транзакції (-c) має бути або %u, або більше чи дорівнювати %u" -#: pg_resetwal.c:233 +#: pg_resetwal.c:234 #, c-format msgid "OID (-o) must not be 0" msgstr "OID (-o) не може бути 0" -#: pg_resetwal.c:254 +#: pg_resetwal.c:255 #, c-format msgid "multitransaction ID (-m) must not be 0" msgstr "ID мультитранзакції (-m) не повинен бути 0" -#: pg_resetwal.c:261 +#: pg_resetwal.c:262 #, c-format msgid "oldest multitransaction ID (-m) must not be 0" msgstr "найстарший ID мультитранзакції (-m) не повинен бути 0" -#: pg_resetwal.c:274 +#: pg_resetwal.c:275 #, c-format msgid "multitransaction offset (-O) must not be -1" msgstr "зсув мультитранзакції (-O) не повинен бути -1" -#: pg_resetwal.c:296 -#, c-format -msgid "argument of --wal-segsize must be a number" -msgstr "аргумент --wal-segsize повинен бути числом" - -#: pg_resetwal.c:298 +#: pg_resetwal.c:301 #, c-format -msgid "argument of --wal-segsize must be a power of two between 1 and 1024" -msgstr "аргумент --wal-segsize повинен бути ступенем 2 між 1 і 1024" +msgid "argument of %s must be a power of two between 1 and 1024" +msgstr "аргумент %s має бути ступенем двійки в діапазоні від 1 до 1024" -#: pg_resetwal.c:314 +#: pg_resetwal.c:318 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_resetwal.c:322 +#: pg_resetwal.c:326 #, c-format msgid "no data directory specified" msgstr "каталог даних не вказано" -#: pg_resetwal.c:336 +#: pg_resetwal.c:340 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\" не може це виконувати" -#: pg_resetwal.c:337 +#: pg_resetwal.c:341 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Запускати %s треба від суперкористувача PostgreSQL." -#: pg_resetwal.c:347 +#: pg_resetwal.c:351 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "не вдалося прочитати дозволи на каталог \"%s\": %m" -#: pg_resetwal.c:353 +#: pg_resetwal.c:357 #, c-format msgid "could not change directory to \"%s\": %m" msgstr "не вдалося змінити каталог на \"%s\": %m" -#: pg_resetwal.c:366 pg_resetwal.c:518 pg_resetwal.c:566 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "не вдалося відкрити файл \"%s\" для читання: %m" - -#: pg_resetwal.c:371 +#: pg_resetwal.c:375 #, c-format msgid "lock file \"%s\" exists" msgstr "файл блокування \"%s\" вже існує" -#: pg_resetwal.c:372 +#: pg_resetwal.c:376 #, c-format msgid "Is a server running? If not, delete the lock file and try again." msgstr "Чи запущений сервер? Якщо ні, видаліть файл блокування і спробуйте знову." -#: pg_resetwal.c:467 +#: pg_resetwal.c:475 #, c-format -msgid "\n" -"If these values seem acceptable, use -f to force reset.\n" -msgstr "\n" -"Якщо ці значення виглядають допустимими, використайте -f, щоб провести перевстановлення.\n" +msgid "not proceeding because control file values were guessed" +msgstr "не виконується, оскільки значення контрольного файлу були вгадані" + +#: pg_resetwal.c:476 +#, c-format +msgid "If these values seem acceptable, use -f to force reset." +msgstr "Якщо ці значення здаються прийнятними, використовуйте -f для примусового скидання." + +#: pg_resetwal.c:485 +#, c-format +msgid "database server was not shut down cleanly" +msgstr "сервер бази даних завершив роботу некоректно" + +#: pg_resetwal.c:486 +#, c-format +msgid "Resetting the write-ahead log might cause data to be lost." +msgstr "Скидання журналу попереднього запису може призвести до втрати даних." -#: pg_resetwal.c:479 +#: pg_resetwal.c:487 #, c-format -msgid "The database server was not shut down cleanly.\n" -"Resetting the write-ahead log might cause data to be lost.\n" -"If you want to proceed anyway, use -f to force reset.\n" -msgstr "Сервер баз даних був зупинений некоректно.\n" -"Очищення журналу передзапису може привести до втрати даних.\n" -"Якщо ви все одно хочете продовжити, використайте параметр -f.\n" +msgid "If you want to proceed anyway, use -f to force reset." +msgstr "Якщо ви все одно хочете продовжити, використовуйте -f для примусового скидання." -#: pg_resetwal.c:493 +#: pg_resetwal.c:500 #, c-format msgid "Write-ahead log reset\n" msgstr "Журнал передзапису скинуто\n" -#: pg_resetwal.c:525 +#: pg_resetwal.c:532 #, c-format msgid "unexpected empty file \"%s\"" msgstr "неочікуваний порожній файл \"%s\"" -#: pg_resetwal.c:527 pg_resetwal.c:581 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не вдалося прочитати файл \"%s\": %m" - -#: pg_resetwal.c:535 +#: pg_resetwal.c:542 #, c-format msgid "data directory is of wrong version" msgstr "каталог даних неправильної версії" -#: pg_resetwal.c:536 +#: pg_resetwal.c:543 #, c-format msgid "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\"." msgstr "Файл \"%s\" містить \"%s\", який не сумісний з версією цієї програми \"%s\"." -#: pg_resetwal.c:569 +#: pg_resetwal.c:576 #, c-format msgid "If you are sure the data directory path is correct, execute\n" " touch %s\n" @@ -228,12 +333,12 @@ msgstr "Якщо Ви впевнені, що шлях каталогу дани " touch %s\n" "і спробуйте знову." -#: pg_resetwal.c:597 +#: pg_resetwal.c:604 #, c-format msgid "pg_control exists but has invalid CRC; proceed with caution" msgstr "pg_control існує, але має недопустимий CRC; продовжуйте з обережністю" -#: pg_resetwal.c:606 +#: pg_resetwal.c:613 #, c-format msgid "pg_control specifies invalid WAL segment size (%d byte); proceed with caution" msgid_plural "pg_control specifies invalid WAL segment size (%d bytes); proceed with caution" @@ -242,301 +347,320 @@ msgstr[1] "pg_control вказує неприпустимий розмір се msgstr[2] "pg_control вказує неприпустимий розмір сегмента WAL (%d байтів); продовжуйте з обережністю" msgstr[3] "pg_control вказує неприпустимий розмір сегмента WAL (%d байтів); продовжуйте з обережністю" -#: pg_resetwal.c:617 +#: pg_resetwal.c:624 #, c-format msgid "pg_control exists but is broken or wrong version; ignoring it" msgstr "pg_control існує, але зламаний або неправильної версії; ігнорується" -#: pg_resetwal.c:712 +#: pg_resetwal.c:719 #, c-format msgid "Guessed pg_control values:\n\n" msgstr "Припустимі значення pg_control:\n\n" -#: pg_resetwal.c:714 +#: pg_resetwal.c:721 #, c-format msgid "Current pg_control values:\n\n" msgstr "Поточні значення pg_control:\n\n" -#: pg_resetwal.c:716 +#: pg_resetwal.c:723 #, c-format msgid "pg_control version number: %u\n" msgstr "pg_control номер версії: %u\n" -#: pg_resetwal.c:718 +#: pg_resetwal.c:725 #, c-format msgid "Catalog version number: %u\n" msgstr "Номер версії каталогу: %u\n" -#: pg_resetwal.c:720 +#: pg_resetwal.c:727 #, c-format msgid "Database system identifier: %llu\n" msgstr "Системний ідентифікатор бази даних: %llu\n" -#: pg_resetwal.c:722 +#: pg_resetwal.c:729 #, c-format msgid "Latest checkpoint's TimeLineID: %u\n" msgstr "Останній TimeLineID контрольної точки: %u\n" -#: pg_resetwal.c:724 +#: pg_resetwal.c:731 #, c-format msgid "Latest checkpoint's full_page_writes: %s\n" msgstr "Останній full_page_writes контрольної точки: %s\n" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "off" msgstr "вимк" -#: pg_resetwal.c:725 +#: pg_resetwal.c:732 msgid "on" msgstr "увімк" -#: pg_resetwal.c:726 +#: pg_resetwal.c:733 #, c-format msgid "Latest checkpoint's NextXID: %u:%u\n" msgstr "Останній NextXID контрольної точки: %u%u\n" -#: pg_resetwal.c:729 +#: pg_resetwal.c:736 #, c-format msgid "Latest checkpoint's NextOID: %u\n" msgstr "Останній NextOID контрольної точки: %u\n" -#: pg_resetwal.c:731 +#: pg_resetwal.c:738 #, c-format msgid "Latest checkpoint's NextMultiXactId: %u\n" msgstr "Останній NextMultiXactId контрольної точки: %u\n" -#: pg_resetwal.c:733 +#: pg_resetwal.c:740 #, c-format msgid "Latest checkpoint's NextMultiOffset: %u\n" msgstr "Останній NextMultiOffset контрольної точки: %u\n" -#: pg_resetwal.c:735 +#: pg_resetwal.c:742 #, c-format msgid "Latest checkpoint's oldestXID: %u\n" msgstr "Останній oldestXID контрольної точки: %u\n" -#: pg_resetwal.c:737 +#: pg_resetwal.c:744 #, c-format msgid "Latest checkpoint's oldestXID's DB: %u\n" msgstr "Остання DB останнього oldestXID контрольної точки: %u\n" -#: pg_resetwal.c:739 +#: pg_resetwal.c:746 #, c-format msgid "Latest checkpoint's oldestActiveXID: %u\n" msgstr "Останній oldestActiveXID контрольної точки: %u\n" -#: pg_resetwal.c:741 +#: pg_resetwal.c:748 #, c-format msgid "Latest checkpoint's oldestMultiXid: %u\n" msgstr "Останній oldestMultiXid контрольної точки: %u \n" -#: pg_resetwal.c:743 +#: pg_resetwal.c:750 #, c-format msgid "Latest checkpoint's oldestMulti's DB: %u\n" msgstr "Остання DB останньої oldestMulti контрольної точки: %u\n" -#: pg_resetwal.c:745 +#: pg_resetwal.c:752 #, c-format msgid "Latest checkpoint's oldestCommitTsXid:%u\n" msgstr "Останній oldestCommitTsXid контрольної точки:%u\n" -#: pg_resetwal.c:747 +#: pg_resetwal.c:754 #, c-format msgid "Latest checkpoint's newestCommitTsXid:%u\n" msgstr "Останній newestCommitTsXid контрольної точки: %u\n" -#: pg_resetwal.c:749 +#: pg_resetwal.c:756 #, c-format msgid "Maximum data alignment: %u\n" msgstr "Максимальне вирівнювання даних: %u\n" -#: pg_resetwal.c:752 +#: pg_resetwal.c:759 #, c-format msgid "Database block size: %u\n" msgstr "Розмір блоку бази даних: %u\n" -#: pg_resetwal.c:754 +#: pg_resetwal.c:761 #, c-format msgid "Blocks per segment of large relation: %u\n" msgstr "Блоків на сегмент великого відношення: %u\n" -#: pg_resetwal.c:756 +#: pg_resetwal.c:763 #, c-format msgid "WAL block size: %u\n" msgstr "Pозмір блоку WAL: %u\n" -#: pg_resetwal.c:758 pg_resetwal.c:844 +#: pg_resetwal.c:765 pg_resetwal.c:851 #, c-format msgid "Bytes per WAL segment: %u\n" msgstr "Байтів на сегмент WAL: %u\n" -#: pg_resetwal.c:760 +#: pg_resetwal.c:767 #, c-format msgid "Maximum length of identifiers: %u\n" msgstr "Максимальна довжина ідентифікаторів: %u\n" -#: pg_resetwal.c:762 +#: pg_resetwal.c:769 #, c-format msgid "Maximum columns in an index: %u\n" msgstr "Максимальна кількість стовпців в індексі: %u\n" -#: pg_resetwal.c:764 +#: pg_resetwal.c:771 #, c-format msgid "Maximum size of a TOAST chunk: %u\n" msgstr "Максимальний розмір сегменту TOAST: %u\n" -#: pg_resetwal.c:766 +#: pg_resetwal.c:773 #, c-format msgid "Size of a large-object chunk: %u\n" msgstr "Розмір сегменту великих обїєктів: %u\n" -#: pg_resetwal.c:769 +#: pg_resetwal.c:776 #, c-format msgid "Date/time type storage: %s\n" msgstr "Дата/час типу сховища: %s\n" -#: pg_resetwal.c:770 +#: pg_resetwal.c:777 msgid "64-bit integers" msgstr "64-бітні цілі" -#: pg_resetwal.c:771 +#: pg_resetwal.c:778 #, c-format msgid "Float8 argument passing: %s\n" msgstr "Передача аргументу Float8: %s\n" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by reference" msgstr "за посиланням" -#: pg_resetwal.c:772 +#: pg_resetwal.c:779 msgid "by value" msgstr "за значенням" -#: pg_resetwal.c:773 +#: pg_resetwal.c:780 #, c-format msgid "Data page checksum version: %u\n" msgstr "Версія контрольних сум сторінок даних: %u\n" -#: pg_resetwal.c:787 +#: pg_resetwal.c:794 #, c-format msgid "\n\n" "Values to be changed:\n\n" msgstr "\n\n" "Значення, що потребують зміни:\n\n" -#: pg_resetwal.c:791 +#: pg_resetwal.c:798 #, c-format msgid "First log segment after reset: %s\n" msgstr "Перший сегмент журналу після скидання: %s\n" -#: pg_resetwal.c:795 +#: pg_resetwal.c:802 #, c-format msgid "NextMultiXactId: %u\n" msgstr "NextMultiXactId: %u\n" -#: pg_resetwal.c:797 +#: pg_resetwal.c:804 #, c-format msgid "OldestMultiXid: %u\n" msgstr "OldestMultiXid: %u\n" -#: pg_resetwal.c:799 +#: pg_resetwal.c:806 #, c-format msgid "OldestMulti's DB: %u\n" msgstr "OldestMulti's DB: %u\n" -#: pg_resetwal.c:805 +#: pg_resetwal.c:812 #, c-format msgid "NextMultiOffset: %u\n" msgstr "NextMultiOffset: %u\n" -#: pg_resetwal.c:811 +#: pg_resetwal.c:818 #, c-format msgid "NextOID: %u\n" msgstr "NextOID: %u\n" -#: pg_resetwal.c:817 +#: pg_resetwal.c:824 #, c-format msgid "NextXID: %u\n" msgstr "NextXID: %u\n" -#: pg_resetwal.c:819 +#: pg_resetwal.c:826 #, c-format msgid "OldestXID: %u\n" msgstr "OldestXID: %u\n" -#: pg_resetwal.c:821 +#: pg_resetwal.c:828 #, c-format msgid "OldestXID's DB: %u\n" msgstr "OldestXID's DB: %u\n" -#: pg_resetwal.c:827 +#: pg_resetwal.c:834 #, c-format msgid "NextXID epoch: %u\n" msgstr "Епоха NextXID: %u\n" -#: pg_resetwal.c:833 +#: pg_resetwal.c:840 #, c-format msgid "oldestCommitTsXid: %u\n" msgstr "oldestCommitTsXid: %u\n" -#: pg_resetwal.c:838 +#: pg_resetwal.c:845 #, c-format msgid "newestCommitTsXid: %u\n" msgstr "newestCommitTsXid: %u\n" -#: pg_resetwal.c:921 pg_resetwal.c:974 pg_resetwal.c:1009 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не вдалося відкрити каталог \"%s\": %m" - -#: pg_resetwal.c:947 pg_resetwal.c:988 pg_resetwal.c:1026 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не вдалося прочитати каталог \"%s\": %m" - -#: pg_resetwal.c:950 pg_resetwal.c:991 pg_resetwal.c:1029 +#: pg_resetwal.c:957 pg_resetwal.c:998 pg_resetwal.c:1036 pg_resetwal.c:1071 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не вдалося закрити каталог \"%s\": %m" -#: pg_resetwal.c:983 pg_resetwal.c:1021 +#: pg_resetwal.c:990 pg_resetwal.c:1028 pg_resetwal.c:1063 #, c-format msgid "could not delete file \"%s\": %m" msgstr "не вдалося видалити файл \"%s\": %m" -#: pg_resetwal.c:1093 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" - -#: pg_resetwal.c:1101 pg_resetwal.c:1113 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "не вдалося записати файл \"%s\": %m" - -#: pg_resetwal.c:1118 +#: pg_resetwal.c:1159 #, c-format msgid "fsync error: %m" msgstr "помилка fsync: %m" -#: pg_resetwal.c:1127 +#: pg_resetwal.c:1168 #, c-format msgid "%s resets the PostgreSQL write-ahead log.\n\n" msgstr "%s скидає журнал передзапису PostgreSQL.\n\n" -#: pg_resetwal.c:1128 +#: pg_resetwal.c:1169 #, c-format msgid "Usage:\n" -" %s [OPTION]... DATADIR\n\n" msgstr "Використання:\n" -" %s [OPTION]... КАТАЛОГ_ДАНИХ\n\n" -#: pg_resetwal.c:1129 +#: pg_resetwal.c:1170 +#, c-format +msgid " %s [OPTION]... DATADIR\n" +msgstr " %s [OPTION]... DATADIR\n" + +#: pg_resetwal.c:1172 +#, c-format +msgid "\n" +"Options:\n" +msgstr "\n" +"Параметри:\n" + +#: pg_resetwal.c:1173 +#, c-format +msgid " [-D, --pgdata=]DATADIR data directory\n" +msgstr " [-D, --pgdata=]DATADIR каталог з даними\n" + +#: pg_resetwal.c:1174 +#, c-format +msgid " -f, --force force update to be done even after unclean shutdown or\n" +" if pg_control values had to be guessed\n" +msgstr " -f, --force змусити оновлення виконуватися навіть після нечистого вимкнення або\n" +" якщо значення pg_control потрібно було вгадувати\n" + +#: pg_resetwal.c:1176 +#, c-format +msgid " -n, --dry-run no update, just show what would be done\n" +msgstr " -n, --dry-run не оновлювати, просто показати, що було б зроблено\n" + +#: pg_resetwal.c:1177 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію і вийти\n" + +#: pg_resetwal.c:1178 #, c-format -msgid "Options:\n" -msgstr "Параметри:\n" +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку потім вийти\n" -#: pg_resetwal.c:1130 +#: pg_resetwal.c:1180 +#, c-format +msgid "\n" +"Options to override control file values:\n" +msgstr "\n" +"Опції для перевизначення значень контрольного файлу:\n" + +#: pg_resetwal.c:1181 #, c-format msgid " -c, --commit-timestamp-ids=XID,XID\n" " set oldest and newest transactions bearing\n" @@ -545,79 +669,54 @@ msgstr " -c, --commit-timestamp-ids=XID,XID\n" " встановити найстарішу та найновішу транзакції\n" " затвердити позначку часу (нуль означає залишити без змін)\n" -#: pg_resetwal.c:1133 -#, c-format -msgid " [-D, --pgdata=]DATADIR data directory\n" -msgstr " [-D, --pgdata=]DATADIR каталог даних\n" - -#: pg_resetwal.c:1134 +#: pg_resetwal.c:1184 #, c-format msgid " -e, --epoch=XIDEPOCH set next transaction ID epoch\n" msgstr " -e, --epoch=XIDEPOCH встановити наступну епоху ID транзакцій\n" -#: pg_resetwal.c:1135 -#, c-format -msgid " -f, --force force update to be done\n" -msgstr " -f, --force примусово виконати оновлення\n" - -#: pg_resetwal.c:1136 +#: pg_resetwal.c:1185 #, c-format msgid " -l, --next-wal-file=WALFILE set minimum starting location for new WAL\n" msgstr " -l, --next-wal-file=WALFILE задати мінімальне початкове розташування для нового WAL\n" -#: pg_resetwal.c:1137 +#: pg_resetwal.c:1186 #, c-format msgid " -m, --multixact-ids=MXID,MXID set next and oldest multitransaction ID\n" msgstr " -m, --multixact-ids=MXID,MXID задати ID наступної і найстарішої мультитранзакції\n" -#: pg_resetwal.c:1138 -#, c-format -msgid " -n, --dry-run no update, just show what would be done\n" -msgstr " -n, --dry-run без оновлень, просто показати, що буде зроблено\n" - -#: pg_resetwal.c:1139 +#: pg_resetwal.c:1187 #, c-format msgid " -o, --next-oid=OID set next OID\n" msgstr " -o, --next-oid=OID задати наступний OID\n" -#: pg_resetwal.c:1140 +#: pg_resetwal.c:1188 #, c-format msgid " -O, --multixact-offset=OFFSET set next multitransaction offset\n" msgstr " -O, --multixact-offset=OFFSET задати зсув наступної мультитранзакції\n" -#: pg_resetwal.c:1141 +#: pg_resetwal.c:1189 #, c-format msgid " -u, --oldest-transaction-id=XID set oldest transaction ID\n" msgstr " -u, --oldest-transaction-id=XID задати ID найстарішої транзакції\n" -#: pg_resetwal.c:1142 -#, c-format -msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version вивести інформацію про версію і вийти\n" - -#: pg_resetwal.c:1143 +#: pg_resetwal.c:1190 #, c-format msgid " -x, --next-transaction-id=XID set next transaction ID\n" msgstr " -x, --next-transaction-id=XID задати ID наступної транзакції\n" -#: pg_resetwal.c:1144 +#: pg_resetwal.c:1191 #, c-format msgid " --wal-segsize=SIZE size of WAL segments, in megabytes\n" msgstr " --wal-segsize=SIZE розмір сегментів WAL, у мегабайтах\n" -#: pg_resetwal.c:1145 -#, c-format -msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help показати цю довідку і вийти\n" - -#: pg_resetwal.c:1146 +#: pg_resetwal.c:1193 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_resetwal.c:1147 +#: pg_resetwal.c:1194 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" diff --git a/src/bin/pg_resetwal/t/001_basic.pl b/src/bin/pg_resetwal/t/001_basic.pl index 9829e48106eca..d6bbbd0ceda38 100644 --- a/src/bin/pg_resetwal/t/001_basic.pl +++ b/src/bin/pg_resetwal/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -30,7 +30,8 @@ 'check PGDATA permissions'); } -command_ok([ 'pg_resetwal', '-D', $node->data_dir ], 'pg_resetwal runs'); +command_ok([ 'pg_resetwal', '--pgdata' => $node->data_dir ], + 'pg_resetwal runs'); $node->start; is($node->safe_psql("postgres", "SELECT 1;"), 1, 'server running and working after reset'); @@ -46,7 +47,7 @@ qr/database server was not shut down cleanly/, 'does not run after immediate shutdown'); command_ok( - [ 'pg_resetwal', '-f', $node->data_dir ], + [ 'pg_resetwal', '--force', $node->data_dir ], 'runs after immediate shutdown with force'); $node->start; is($node->safe_psql("postgres", "SELECT 1;"), @@ -80,111 +81,117 @@ # error cases # -c command_fails_like( - [ 'pg_resetwal', '-c', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-c' => 'foo', $node->data_dir ], qr/error: invalid argument for option -c/, 'fails with incorrect -c option'); command_fails_like( - [ 'pg_resetwal', '-c', '10,bar', $node->data_dir ], + [ 'pg_resetwal', '-c' => '10,bar', $node->data_dir ], qr/error: invalid argument for option -c/, 'fails with incorrect -c option part 2'); command_fails_like( - [ 'pg_resetwal', '-c', '1,10', $node->data_dir ], + [ 'pg_resetwal', '-c' => '1,10', $node->data_dir ], qr/greater than/, - 'fails with -c value 1 part 1'); + 'fails with -c ids value 1 part 1'); command_fails_like( - [ 'pg_resetwal', '-c', '10,1', $node->data_dir ], + [ 'pg_resetwal', '-c' => '10,1', $node->data_dir ], qr/greater than/, 'fails with -c value 1 part 2'); # -e command_fails_like( - [ 'pg_resetwal', '-e', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-e' => 'foo', $node->data_dir ], qr/error: invalid argument for option -e/, 'fails with incorrect -e option'); command_fails_like( - [ 'pg_resetwal', '-e', '-1', $node->data_dir ], + [ 'pg_resetwal', '-e' => '-1', $node->data_dir ], qr/must not be -1/, 'fails with -e value -1'); # -l command_fails_like( - [ 'pg_resetwal', '-l', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-l' => 'foo', $node->data_dir ], qr/error: invalid argument for option -l/, 'fails with incorrect -l option'); # -m command_fails_like( - [ 'pg_resetwal', '-m', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-m' => 'foo', $node->data_dir ], qr/error: invalid argument for option -m/, 'fails with incorrect -m option'); command_fails_like( - [ 'pg_resetwal', '-m', '10,bar', $node->data_dir ], + [ 'pg_resetwal', '-m' => '10,bar', $node->data_dir ], qr/error: invalid argument for option -m/, 'fails with incorrect -m option part 2'); command_fails_like( - [ 'pg_resetwal', '-m', '0,10', $node->data_dir ], + [ 'pg_resetwal', '-m' => '0,10', $node->data_dir ], qr/must not be 0/, 'fails with -m value 0 part 1'); command_fails_like( - [ 'pg_resetwal', '-m', '10,0', $node->data_dir ], + [ 'pg_resetwal', '-m' => '10,0', $node->data_dir ], qr/must not be 0/, 'fails with -m value 0 part 2'); # -o command_fails_like( - [ 'pg_resetwal', '-o', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-o' => 'foo', $node->data_dir ], qr/error: invalid argument for option -o/, 'fails with incorrect -o option'); command_fails_like( - [ 'pg_resetwal', '-o', '0', $node->data_dir ], + [ 'pg_resetwal', '-o' => '0', $node->data_dir ], qr/must not be 0/, 'fails with -o value 0'); # -O command_fails_like( - [ 'pg_resetwal', '-O', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-O' => 'foo', $node->data_dir ], qr/error: invalid argument for option -O/, 'fails with incorrect -O option'); command_fails_like( - [ 'pg_resetwal', '-O', '-1', $node->data_dir ], + [ 'pg_resetwal', '-O' => '-1', $node->data_dir ], qr/must not be -1/, 'fails with -O value -1'); # --wal-segsize command_fails_like( - [ 'pg_resetwal', '--wal-segsize', 'foo', $node->data_dir ], + [ 'pg_resetwal', '--wal-segsize' => 'foo', $node->data_dir ], qr/error: invalid value/, 'fails with incorrect --wal-segsize option'); command_fails_like( - [ 'pg_resetwal', '--wal-segsize', '13', $node->data_dir ], + [ 'pg_resetwal', '--wal-segsize' => '13', $node->data_dir ], qr/must be a power/, 'fails with invalid --wal-segsize value'); # -u command_fails_like( - [ 'pg_resetwal', '-u', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-u' => 'foo', $node->data_dir ], qr/error: invalid argument for option -u/, 'fails with incorrect -u option'); command_fails_like( - [ 'pg_resetwal', '-u', '1', $node->data_dir ], + [ 'pg_resetwal', '-u' => '1', $node->data_dir ], qr/must be greater than/, 'fails with -u value too small'); # -x command_fails_like( - [ 'pg_resetwal', '-x', 'foo', $node->data_dir ], + [ 'pg_resetwal', '-x' => 'foo', $node->data_dir ], qr/error: invalid argument for option -x/, 'fails with incorrect -x option'); command_fails_like( - [ 'pg_resetwal', '-x', '1', $node->data_dir ], + [ 'pg_resetwal', '-x' => '1', $node->data_dir ], qr/must be greater than/, 'fails with -x value too small'); +# --char-signedness +command_fails_like( + [ 'pg_resetwal', '--char-signedness', 'foo', $node->data_dir ], + qr/error: invalid argument for option --char-signedness/, + 'fails with incorrect --char-signedness option'); + # run with control override options -my $out = (run_command([ 'pg_resetwal', '-n', $node->data_dir ]))[0]; +my $out = (run_command([ 'pg_resetwal', '--dry-run', $node->data_dir ]))[0]; $out =~ /^Database block size: *(\d+)$/m or die; my $blcksz = $1; -my @cmd = ('pg_resetwal', '-D', $node->data_dir); +my @cmd = ('pg_resetwal', '--pgdata' => $node->data_dir); # some not-so-critical hardcoded values -push @cmd, '-e', 1; -push @cmd, '-l', '00000001000000320000004B'; -push @cmd, '-o', 100_000; -push @cmd, '--wal-segsize', 1; +push @cmd, '--epoch' => 1; +push @cmd, '--next-wal-file' => '00000001000000320000004B'; +push @cmd, '--next-oid' => 100_000; +push @cmd, '--wal-segsize' => 1; # these use the guidance from the documentation @@ -202,31 +209,33 @@ sub get_slru_files # XXX: Should there be a multiplier, similar to the other options? # -c argument is "old,new" push @cmd, - '-c', + '--commit-timestamp-ids' => sprintf("%d,%d", hex($files[0]) == 0 ? 3 : hex($files[0]), hex($files[-1])); @files = get_slru_files('pg_multixact/offsets'); $mult = 32 * $blcksz / 4; -# -m argument is "new,old" -push @cmd, '-m', - sprintf("%d,%d", +# --multixact-ids argument is "new,old" +push @cmd, + '--multixact-ids' => sprintf("%d,%d", (hex($files[-1]) + 1) * $mult, hex($files[0]) == 0 ? 1 : hex($files[0] * $mult)); @files = get_slru_files('pg_multixact/members'); $mult = 32 * int($blcksz / 20) * 4; -push @cmd, '-O', (hex($files[-1]) + 1) * $mult; +push @cmd, '--multixact-offset' => (hex($files[-1]) + 1) * $mult; @files = get_slru_files('pg_xact'); $mult = 32 * $blcksz * 4; push @cmd, - '-u', (hex($files[0]) == 0 ? 3 : hex($files[0]) * $mult), - '-x', ((hex($files[-1]) + 1) * $mult); + '--oldest-transaction-id' => + (hex($files[0]) == 0 ? 3 : hex($files[0]) * $mult), + '--next-transaction-id' => ((hex($files[-1]) + 1) * $mult); -command_ok([ @cmd, '-n' ], 'runs with control override options, dry run'); +command_ok([ @cmd, '--dry-run' ], + 'runs with control override options, dry run'); command_ok(\@cmd, 'runs with control override options'); command_like( - [ 'pg_resetwal', '-n', $node->data_dir ], + [ 'pg_resetwal', '--dry-run', $node->data_dir ], qr/^Latest checkpoint's NextOID: *100000$/m, 'spot check that control changes were applied'); diff --git a/src/bin/pg_resetwal/t/002_corrupted.pl b/src/bin/pg_resetwal/t/002_corrupted.pl index c5e09bbb688c8..3c80f6309c9b6 100644 --- a/src/bin/pg_resetwal/t/002_corrupted.pl +++ b/src/bin/pg_resetwal/t/002_corrupted.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for handling a corrupted pg_control @@ -31,7 +31,7 @@ close $fh; command_checks_all( - [ 'pg_resetwal', '-n', $node->data_dir ], + [ 'pg_resetwal', '--dry-run', $node->data_dir ], 0, [qr/pg_control version number/], [ @@ -47,7 +47,7 @@ close $fh; command_checks_all( - [ 'pg_resetwal', '-n', $node->data_dir ], + [ 'pg_resetwal', '--dry-run', $node->data_dir ], 0, [qr/pg_control version number/], [ @@ -60,7 +60,8 @@ [ 'pg_resetwal', $node->data_dir ], qr/not proceeding because control file values were guessed/, 'does not run when control file values were guessed'); -command_ok([ 'pg_resetwal', '-f', $node->data_dir ], +command_ok( + [ 'pg_resetwal', '--force', $node->data_dir ], 'runs with force when control file values were guessed'); done_testing(); diff --git a/src/bin/pg_rewind/Makefile b/src/bin/pg_rewind/Makefile index 12b138b2f2ce3..cbd000b686dba 100644 --- a/src/bin/pg_rewind/Makefile +++ b/src/bin/pg_rewind/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_rewind # -# Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group # # src/bin/pg_rewind/Makefile # diff --git a/src/bin/pg_rewind/datapagemap.c b/src/bin/pg_rewind/datapagemap.c index 1d8be25320c6c..a0645afc83b1c 100644 --- a/src/bin/pg_rewind/datapagemap.c +++ b/src/bin/pg_rewind/datapagemap.c @@ -5,7 +5,7 @@ * * This is a fairly simple bitmap. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/bin/pg_rewind/datapagemap.h b/src/bin/pg_rewind/datapagemap.h index 49124834508dc..a23872231e822 100644 --- a/src/bin/pg_rewind/datapagemap.h +++ b/src/bin/pg_rewind/datapagemap.h @@ -2,7 +2,7 @@ * * datapagemap.h * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -10,7 +10,6 @@ #define DATAPAGEMAP_H #include "storage/block.h" -#include "storage/relfilelocator.h" struct datapagemap { diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c index d93580bb41913..55659ce201f4c 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -8,7 +8,7 @@ * do nothing if it's enabled. You should avoid accessing the target files * directly but if you do, make sure you honor the --dry-run mode! * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -296,7 +296,7 @@ sync_target_dir(void) if (!do_sync || dry_run) return; - sync_pgdata(datadir_target, PG_VERSION_NUM, sync_method); + sync_pgdata(datadir_target, PG_VERSION_NUM, sync_method, true); } @@ -452,7 +452,7 @@ recurse_dir(const char *datadir, const char *parentpath, * to process all the tablespaces. We also follow a symlink if * it's for pg_wal. Symlinks elsewhere are ignored. */ - if ((parentpath && strcmp(parentpath, "pg_tblspc") == 0) || + if ((parentpath && strcmp(parentpath, PG_TBLSPC_DIR) == 0) || strcmp(path, "pg_wal") == 0) recurse_dir(datadir, path, callback); } diff --git a/src/bin/pg_rewind/file_ops.h b/src/bin/pg_rewind/file_ops.h index 8a14d9cd351b7..ee0d01df1ae51 100644 --- a/src/bin/pg_rewind/file_ops.h +++ b/src/bin/pg_rewind/file_ops.h @@ -3,7 +3,7 @@ * file_ops.h * Helper functions for operating on files * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c index 4458324c9d81b..c933871ca9fda 100644 --- a/src/bin/pg_rewind/filemap.c +++ b/src/bin/pg_rewind/filemap.c @@ -16,7 +16,7 @@ * for each file. Finally, it sorts the array to the final order that the * actions should be executed in. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -26,6 +26,7 @@ #include #include +#include "access/xlog_internal.h" #include "catalog/pg_tablespace_d.h" #include "common/file_utils.h" #include "common/hashfn_unstable.h" @@ -38,14 +39,14 @@ * Define a hash table which we can use to store information about the files * appearing in source and target systems. */ -#define SH_PREFIX filehash -#define SH_ELEMENT_TYPE file_entry_t -#define SH_KEY_TYPE const char * -#define SH_KEY path +#define SH_PREFIX filehash +#define SH_ELEMENT_TYPE file_entry_t +#define SH_KEY_TYPE const char * +#define SH_KEY path #define SH_HASH_KEY(tb, key) hash_string(key) #define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0) -#define SH_SCOPE static inline -#define SH_RAW_ALLOCATOR pg_malloc0 +#define SH_SCOPE static inline +#define SH_RAW_ALLOCATOR pg_malloc0 #define SH_DECLARE #define SH_DEFINE #include "lib/simplehash.h" @@ -60,7 +61,36 @@ static char *datasegpath(RelFileLocator rlocator, ForkNumber forknum, static file_entry_t *insert_filehash_entry(const char *path); static file_entry_t *lookup_filehash_entry(const char *path); + +/* + * A separate hash table which tracks WAL files that must not be deleted. + */ +typedef struct keepwal_entry +{ + const char *path; + uint32 status; +} keepwal_entry; + +#define SH_PREFIX keepwal +#define SH_ELEMENT_TYPE keepwal_entry +#define SH_KEY_TYPE const char * +#define SH_KEY path +#define SH_HASH_KEY(tb, key) hash_string(key) +#define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0) +#define SH_SCOPE static inline +#define SH_RAW_ALLOCATOR pg_malloc0 +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" + +#define KEEPWAL_INITIAL_SIZE 1000 + + +static keepwal_hash *keepwal = NULL; +static bool keepwal_entry_exists(const char *path); + static int final_filemap_cmp(const void *a, const void *b); + static bool check_file_excluded(const char *path, bool is_source); /* @@ -97,7 +127,7 @@ static const char *const excludeDirContents[] = * even if the intention is to restore to another primary. See backup.sgml * for a more detailed description. */ - "pg_replslot", + "pg_replslot", /* defined as PG_REPLSLOT_DIR */ /* Contents removed on startup, see dsm_cleanup_for_mmap(). */ "pg_dynshmem", /* defined as PG_DYNSHMEM_DIR */ @@ -206,6 +236,39 @@ lookup_filehash_entry(const char *path) return filehash_lookup(filehash, path); } +/* + * Initialize a hash table to store WAL file names that must be kept. + */ +void +keepwal_init(void) +{ + /* An initial hash size out of thin air */ + keepwal = keepwal_create(KEEPWAL_INITIAL_SIZE, NULL); +} + +/* Mark the given file to prevent its removal */ +void +keepwal_add_entry(const char *path) +{ + keepwal_entry *entry; + bool found; + + /* Should only be called with keepwal initialized */ + Assert(keepwal != NULL); + + entry = keepwal_insert(keepwal, path, &found); + + if (!found) + entry->path = pg_strdup(path); +} + +/* Return true if file is marked as not to be removed, false otherwise */ +static bool +keepwal_entry_exists(const char *path) +{ + return keepwal_lookup(keepwal, path) != NULL; +} + /* * Callback for processing source file list. * @@ -590,18 +653,17 @@ isRelDataFile(const char *path) static char * datasegpath(RelFileLocator rlocator, ForkNumber forknum, BlockNumber segno) { - char *path; + RelPathStr path; char *segpath; path = relpathperm(rlocator, forknum); if (segno > 0) { - segpath = psprintf("%s.%u", path, segno); - pfree(path); + segpath = psprintf("%s.%u", path.str, segno); return segpath; } else - return path; + return pstrdup(path.str); } /* @@ -643,7 +705,7 @@ decide_file_action(file_entry_t *entry) * Don't touch the control file. It is handled specially, after copying * all the other files. */ - if (strcmp(path, "global/pg_control") == 0) + if (strcmp(path, XLOG_CONTROL_FILE) == 0) return FILE_ACTION_NONE; /* Skip macOS system files */ @@ -685,7 +747,15 @@ decide_file_action(file_entry_t *entry) } else if (entry->target_exists && !entry->source_exists) { - /* File exists in target, but not source. Remove it. */ + /* + * For files that exist in target but not in source, we check the + * keepwal hash table; any files listed therein must not be removed. + */ + if (keepwal_entry_exists(path)) + { + pg_log_debug("Not removing file \"%s\" because it is required for recovery", path); + return FILE_ACTION_NONE; + } return FILE_ACTION_REMOVE; } else if (!entry->target_exists && !entry->source_exists) diff --git a/src/bin/pg_rewind/filemap.h b/src/bin/pg_rewind/filemap.h index 007e0f17cf4a9..df78a02e3da03 100644 --- a/src/bin/pg_rewind/filemap.h +++ b/src/bin/pg_rewind/filemap.h @@ -2,7 +2,7 @@ * * filemap.h * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group *------------------------------------------------------------------------- */ #ifndef FILEMAP_H @@ -110,4 +110,7 @@ extern filemap_t *decide_file_actions(void); extern void calculate_totals(filemap_t *filemap); extern void print_filemap(filemap_t *filemap); +extern void keepwal_init(void); +extern void keepwal_add_entry(const char *path); + #endif /* FILEMAP_H */ diff --git a/src/bin/pg_rewind/libpq_source.c b/src/bin/pg_rewind/libpq_source.c index 9378266d28e2f..56c2ad55d4a67 100644 --- a/src/bin/pg_rewind/libpq_source.c +++ b/src/bin/pg_rewind/libpq_source.c @@ -3,7 +3,7 @@ * libpq_source.c * Functions for fetching files from a remote server via libpq. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -11,7 +11,6 @@ #include "catalog/pg_type_d.h" #include "common/connect.h" -#include "datapagemap.h" #include "file_ops.h" #include "filemap.h" #include "lib/stringinfo.h" @@ -294,7 +293,7 @@ libpq_traverse_files(rewind_source *source, process_file_callback_t callback) } path = PQgetvalue(res, i, 0); - filesize = atol(PQgetvalue(res, i, 1)); + filesize = atoll(PQgetvalue(res, i, 1)); isdir = (strcmp(PQgetvalue(res, i, 2), "t") == 0); link_target = PQgetvalue(res, i, 3); @@ -568,8 +567,8 @@ process_queued_fetch_requests(libpq_source *src) } else { - pg_log_debug("received chunk for file \"%s\", offset %lld, size %d", - filename, (long long int) chunkoff, chunksize); + pg_log_debug("received chunk for file \"%s\", offset %" PRId64 ", size %d", + filename, chunkoff, chunksize); if (strcmp(filename, rq->path) != 0) { @@ -577,8 +576,8 @@ process_queued_fetch_requests(libpq_source *src) filename, rq->path); } if (chunkoff != rq->offset) - pg_fatal("received data at offset %lld of file \"%s\", when requested for offset %lld", - (long long int) chunkoff, rq->path, (long long int) rq->offset); + pg_fatal("received data at offset %" PRId64 " of file \"%s\", when requested for offset %lld", + chunkoff, rq->path, (long long int) rq->offset); /* * We should not receive more data than we requested, or diff --git a/src/bin/pg_rewind/local_source.c b/src/bin/pg_rewind/local_source.c index 46c6b72bd71e3..5a6e805c15833 100644 --- a/src/bin/pg_rewind/local_source.c +++ b/src/bin/pg_rewind/local_source.c @@ -3,7 +3,7 @@ * local_source.c * Functions for using a local data directory as the source. * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -12,10 +12,8 @@ #include #include -#include "datapagemap.h" +#include "common/logging.h" #include "file_ops.h" -#include "filemap.h" -#include "pg_rewind.h" #include "rewind_source.h" typedef struct diff --git a/src/bin/pg_rewind/meson.build b/src/bin/pg_rewind/meson.build index e0f88bde22179..36171600ccaf4 100644 --- a/src/bin/pg_rewind/meson.build +++ b/src/bin/pg_rewind/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_rewind_sources = files( 'datapagemap.c', @@ -43,6 +43,7 @@ tests += { 't/007_standby_source.pl', 't/008_min_recovery_point.pl', 't/009_growing_files.pl', + 't/010_keep_recycled_wals.pl', ], }, } diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c index 22f7351fdcdec..2cd44625ca368 100644 --- a/src/bin/pg_rewind/parsexlog.c +++ b/src/bin/pg_rewind/parsexlog.c @@ -3,7 +3,7 @@ * parsexlog.c * Functions for reading Write-Ahead-Log * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *------------------------------------------------------------------------- @@ -175,6 +175,8 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex, XLogReaderState *xlogreader; char *errormsg; XLogPageReadPrivate private; + XLogSegNo current_segno = 0; + TimeLineID current_tli = 0; /* * The given fork pointer points to the end of the last common record, @@ -217,6 +219,25 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex, LSN_FORMAT_ARGS(searchptr)); } + /* Detect if a new WAL file has been opened */ + if (xlogreader->seg.ws_tli != current_tli || + xlogreader->seg.ws_segno != current_segno) + { + char xlogfname[MAXFNAMELEN]; + + snprintf(xlogfname, MAXFNAMELEN, XLOGDIR "/"); + + /* update current values */ + current_tli = xlogreader->seg.ws_tli; + current_segno = xlogreader->seg.ws_segno; + + XLogFileName(xlogfname + sizeof(XLOGDIR), + current_tli, current_segno, WalSegSz); + + /* Track this filename as one to not remove */ + keepwal_add_entry(xlogfname); + } + /* * Check if it is a checkpoint record. This checkpoint record needs to * be the latest checkpoint before WAL forked and not the checkpoint diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c index 0841ab4135bce..9d16c1e6b4757 100644 --- a/src/bin/pg_rewind/pg_rewind.c +++ b/src/bin/pg_rewind/pg_rewind.c @@ -3,7 +3,7 @@ * pg_rewind.c * Synchronizes a PostgreSQL data directory to a new timeline * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -328,7 +328,7 @@ main(int argc, char **argv) * need to make sure by themselves that the target cluster is in a clean * state. */ - buffer = slurpFile(datadir_target, "global/pg_control", &size); + buffer = slurpFile(datadir_target, XLOG_CONTROL_FILE, &size); digestControlFile(&ControlFile_target, buffer, size); pg_free(buffer); @@ -338,12 +338,12 @@ main(int argc, char **argv) { ensureCleanShutdown(argv[0]); - buffer = slurpFile(datadir_target, "global/pg_control", &size); + buffer = slurpFile(datadir_target, XLOG_CONTROL_FILE, &size); digestControlFile(&ControlFile_target, buffer, size); pg_free(buffer); } - buffer = source->fetch_file(source, "global/pg_control", &size); + buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size); digestControlFile(&ControlFile_source, buffer, size); pg_free(buffer); @@ -451,10 +451,14 @@ main(int argc, char **argv) pg_log_info("no rewind required"); if (writerecoveryconf && !dry_run) WriteRecoveryConfig(conn, datadir_target, - GenerateRecoveryConfig(conn, NULL, NULL)); + GenerateRecoveryConfig(conn, NULL, + GetDbnameFromConnectionOptions(connstr_source))); exit(0); } + /* Initialize hashtable that tracks WAL files protected from removal */ + keepwal_init(); + findLastCheckpoint(datadir_target, divergerec, lastcommontliIndex, &chkptrec, &chkpttli, &chkptredo, restore_command); pg_log_info("rewinding from last common checkpoint at %X/%X on timeline %u", @@ -525,7 +529,8 @@ main(int argc, char **argv) /* Also update the standby configuration, if requested. */ if (writerecoveryconf && !dry_run) WriteRecoveryConfig(conn, datadir_target, - GenerateRecoveryConfig(conn, NULL, NULL)); + GenerateRecoveryConfig(conn, NULL, + GetDbnameFromConnectionOptions(connstr_source))); /* don't need the source connection anymore */ source->destroy(source); @@ -631,7 +636,7 @@ perform_rewind(filemap_t *filemap, rewind_source *source, * Fetch the control file from the source last. This ensures that the * minRecoveryPoint is up-to-date. */ - buffer = source->fetch_file(source, "global/pg_control", &size); + buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size); digestControlFile(&ControlFile_source_after, buffer, size); pg_free(buffer); @@ -882,6 +887,7 @@ getTimelineHistory(TimeLineID tli, bool is_source, int *nentries) pg_free(histfile); } + /* In debugging mode, print what we read */ if (debug) { int i; @@ -891,10 +897,7 @@ getTimelineHistory(TimeLineID tli, bool is_source, int *nentries) else pg_log_debug("Target timeline history:"); - /* - * Print the target timeline history. - */ - for (i = 0; i < targetNentries; i++) + for (i = 0; i < *nentries; i++) { TimeLineHistoryEntry *entry; @@ -1006,7 +1009,7 @@ checkControlFile(ControlFileData *ControlFile) /* Calculate CRC */ INIT_CRC32C(crc); - COMP_CRC32C(crc, (char *) ControlFile, offsetof(ControlFileData, crc)); + COMP_CRC32C(crc, ControlFile, offsetof(ControlFileData, crc)); FIN_CRC32C(crc); /* And simply compare it */ @@ -1106,7 +1109,7 @@ getRestoreCommand(const char *argv0) restore_command = pipe_read_line(postgres_cmd->data); if (restore_command == NULL) - pg_fatal("unable to read restore_command from target cluster"); + pg_fatal("could not read \"restore_command\" from target cluster"); (void) pg_strip_crlf(restore_command); diff --git a/src/bin/pg_rewind/pg_rewind.h b/src/bin/pg_rewind/pg_rewind.h index ec43cbe2c67de..9cea144d2b241 100644 --- a/src/bin/pg_rewind/pg_rewind.h +++ b/src/bin/pg_rewind/pg_rewind.h @@ -3,7 +3,7 @@ * pg_rewind.h * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *------------------------------------------------------------------------- @@ -14,10 +14,6 @@ #include "access/timeline.h" #include "common/logging.h" #include "common/file_utils.h" -#include "datapagemap.h" -#include "libpq-fe.h" -#include "storage/block.h" -#include "storage/relfilelocator.h" /* Configuration options */ extern char *datadir_target; diff --git a/src/bin/pg_rewind/po/de.po b/src/bin/pg_rewind/po/de.po index 887def960a642..6c1093dafe57b 100644 --- a/src/bin/pg_rewind/po/de.po +++ b/src/bin/pg_rewind/po/de.po @@ -1,13 +1,13 @@ # German message translation file for pg_rewind -# Copyright (C) 2015-2024 PostgreSQL Global Development Group +# Copyright (C) 2015-2025 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. # msgid "" msgstr "" -"Project-Id-Version: pg_rewind (PostgreSQL) 17\n" +"Project-Id-Version: pg_rewind (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 10:23+0000\n" -"PO-Revision-Date: 2024-06-16 19:04+0200\n" +"POT-Creation-Date: 2025-04-03 12:24+0000\n" +"PO-Revision-Date: 2025-04-03 16:19+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,22 +16,22 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -41,19 +41,19 @@ msgstr "Tipp: " msgid "could not open file \"%s\" for reading: %m" msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m" -#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 -#: local_source.c:163 parsexlog.c:350 +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:102 +#: local_source.c:161 parsexlog.c:371 #, c-format msgid "could not read file \"%s\": %m" msgstr "konnte Datei »%s« nicht lesen: %m" -#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: local_source.c:121 local_source.c:172 +#: local_source.c:119 local_source.c:170 #, c-format msgid "could not close file \"%s\": %m" msgstr "konnte Datei »%s« nicht schließen: %m" @@ -76,10 +76,10 @@ msgstr "" "diesem Fall wären die Ergebnisse unten falsch und die PostgreSQL-Installation\n" "wäre inkompatibel mit diesem Datenverzeichnis." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: parsexlog.c:312 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: parsexlog.c:333 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" @@ -89,8 +89,8 @@ msgstr "konnte Datei »%s« nicht öffnen: %m" msgid "could not write file \"%s\": %m" msgstr "konnte Datei »%s« nicht schreiben: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" @@ -106,34 +106,34 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #: ../../fe_utils/archive.c:86 file_ops.c:417 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 file_ops.c:388 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 file_ops.c:462 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -218,29 +218,34 @@ msgstr "%s muss im Bereich %d..%d sein" msgid "unrecognized sync method: %s" msgstr "unbekannte Sync-Methode: %s" -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" -#: ../../fe_utils/recovery_gen.c:143 +#: ../../fe_utils/recovery_gen.c:144 #, c-format msgid "could not write to file \"%s\": %m" msgstr "konnte nicht in Datei »%s« schreiben: %m" -#: ../../fe_utils/recovery_gen.c:152 +#: ../../fe_utils/recovery_gen.c:153 #, c-format msgid "could not create file \"%s\": %m" msgstr "konnte Datei »%s« nicht erstellen: %m" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/recovery_gen.c:215 pg_rewind.c:311 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" @@ -320,177 +325,177 @@ msgstr "Ziel für symbolische Verknüpfung »%s« ist zu lang" msgid "could not close directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht schließen: %m" -#: filemap.c:235 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "Datendatei »%s« in der Quelle ist keine normale Datei" -#: filemap.c:240 filemap.c:273 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "doppelte Quelldatei »%s«" -#: filemap.c:328 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "unerwartete Seitenänderung für nicht normale Datei »%s«" -#: filemap.c:682 filemap.c:776 +#: filemap.c:743 filemap.c:845 #, c-format msgid "unknown file type for \"%s\"" msgstr "unbekannter Dateityp für »%s«" -#: filemap.c:709 +#: filemap.c:778 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "Datei »%s« hat unterschiedlichen Typ in Quelle und Ziel" -#: filemap.c:781 +#: filemap.c:850 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "konnte nicht entscheiden, was mit Datei »%s« zu tun ist" -#: libpq_source.c:131 +#: libpq_source.c:130 #, c-format msgid "could not clear \"search_path\": %s" msgstr "konnte »search_path« nicht auf leer setzen: %s" -#: libpq_source.c:142 +#: libpq_source.c:141 #, c-format msgid "\"full_page_writes\" must be enabled in the source server" msgstr "»full_page_writes« muss im Quell-Server eingeschaltet sein" -#: libpq_source.c:153 +#: libpq_source.c:152 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "konnte Anfrage zum Holen des Dateiinhalts nicht vorbereiten: %s" -#: libpq_source.c:172 +#: libpq_source.c:171 #, c-format msgid "error running query (%s) on source server: %s" msgstr "Fehler beim Ausführen einer Anfrage (%s) auf dem Quellserver: %s" -#: libpq_source.c:177 +#: libpq_source.c:176 #, c-format msgid "unexpected result set from query" msgstr "Anfrage ergab unerwartete Ergebnismenge" -#: libpq_source.c:199 +#: libpq_source.c:198 #, c-format msgid "error running query (%s) in source server: %s" msgstr "Fehler beim Ausführen einer Anfrage (%s) im Quellserver: %s" -#: libpq_source.c:220 +#: libpq_source.c:219 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "unbekanntes Ergebnis »%s« für aktuelle WAL-Einfügeposition" -#: libpq_source.c:271 +#: libpq_source.c:270 #, c-format msgid "could not fetch file list: %s" msgstr "konnte Dateiliste nicht holen: %s" -#: libpq_source.c:276 +#: libpq_source.c:275 #, c-format msgid "unexpected result set while fetching file list" msgstr "unerwartete Ergebnismenge beim Holen der Dateiliste" -#: libpq_source.c:477 +#: libpq_source.c:476 #, c-format msgid "could not send query: %s" msgstr "konnte Anfrage nicht senden: %s" -#: libpq_source.c:480 +#: libpq_source.c:479 #, c-format msgid "could not set libpq connection to single row mode" msgstr "konnte libpq-Verbindung nicht in den Einzelzeilenmodus setzen" -#: libpq_source.c:510 +#: libpq_source.c:509 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "unerwartetes Ergebnis beim Holen von fernen Dateien: %s" -#: libpq_source.c:515 +#: libpq_source.c:514 #, c-format msgid "received more data chunks than requested" msgstr "mehr Daten-Chunks erhalten als verlangt" -#: libpq_source.c:519 +#: libpq_source.c:518 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "unerwartete Ergebnismengengröße beim Holen von fernen Dateien" -#: libpq_source.c:525 +#: libpq_source.c:524 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "unerwartete Datentypen in Ergebnismenge beim Holen von fernen Dateien: %u %u %u" -#: libpq_source.c:533 +#: libpq_source.c:532 #, c-format msgid "unexpected result format while fetching remote files" msgstr "unerwartetes Ergebnisformat beim Holen von fernen Dateien" -#: libpq_source.c:539 +#: libpq_source.c:538 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "unerwartete NULL-Werte im Ergebnis beim Holen von fernen Dateien" -#: libpq_source.c:543 +#: libpq_source.c:542 #, c-format msgid "unexpected result length while fetching remote files" msgstr "unerwartete Ergebnislänge beim Holen von fernen Dateien" -#: libpq_source.c:576 +#: libpq_source.c:575 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "Daten für Datei »%s« erhalten, aber »%s« wurde verlangt" -#: libpq_source.c:580 +#: libpq_source.c:579 #, c-format -msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" -msgstr "Daten für Offset %lld von Datei »%s« erhalten, aber Offset %lld wurde verlangt" +msgid "received data at offset % of file \"%s\", when requested for offset %lld" +msgstr "Daten für Offset % von Datei »%s« erhalten, aber Offset %lld wurde verlangt" -#: libpq_source.c:592 +#: libpq_source.c:591 #, c-format msgid "received more than requested for file \"%s\"" msgstr "mehr als verlangt erhalten für Datei »%s«" -#: libpq_source.c:605 +#: libpq_source.c:604 #, c-format msgid "unexpected number of data chunks received" msgstr "unerwartete Anzahl Daten-Chunks erhalten" -#: libpq_source.c:648 +#: libpq_source.c:647 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "konnte ferne Datei »%s« nicht holen: %s" -#: libpq_source.c:653 +#: libpq_source.c:652 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "unerwartete Ergebnismenge beim Holen der fernen Datei »%s«" -#: local_source.c:90 local_source.c:142 +#: local_source.c:88 local_source.c:140 #, c-format msgid "could not open source file \"%s\": %m" msgstr "konnte Quelldatei »%s« nicht öffnen: %m" -#: local_source.c:117 +#: local_source.c:115 #, c-format msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "Größe der Quelldatei »%s« nebenläufig verändert: %d Bytes erwartet, %d kopiert" -#: local_source.c:146 +#: local_source.c:144 #, c-format msgid "could not seek in source file: %m" msgstr "konnte Positionszeiger in Quelldatei nicht setzen: %m" -#: local_source.c:165 +#: local_source.c:163 #, c-format msgid "unexpected EOF while reading file \"%s\"" msgstr "unerwartetes EOF beim Lesen der Datei »%s«" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "Speicher aufgebraucht beim Anlegen eines WAL-Leseprozessors" @@ -510,22 +515,22 @@ msgstr "konnte WAL-Eintrag bei %X/%X nicht lesen" msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "Endpunkt %X/%X ist kein gültiger Endpunkt; %X/%X erwartet" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "konnte vorangegangenen WAL-Eintrag bei %X/%X nicht finden: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "konnte vorangegangenen WAL-Eintrag bei %X/%X nicht finden" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "konnte Positionszeiger in Datei »%s« nicht setzen: %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "WAL-Eintrag modifiziert eine Relation, aber Typ des Eintrags wurde nicht erkannt: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" @@ -705,11 +710,6 @@ msgstr "Sie müssen %s als PostgreSQL-Superuser ausführen." msgid "could not read permissions of directory \"%s\": %m" msgstr "konnte Zugriffsrechte von Verzeichnis »%s« nicht lesen: %m" -#: pg_rewind.c:311 -#, c-format -msgid "%s" -msgstr "%s" - #: pg_rewind.c:314 #, c-format msgid "connected to server" @@ -730,154 +730,154 @@ msgstr "Server divergierten bei WAL-Position %X/%X auf Zeitleiste %u" msgid "no rewind required" msgstr "kein Rückspulen nötig" -#: pg_rewind.c:460 +#: pg_rewind.c:464 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "Rückspulen ab letztem gemeinsamen Checkpoint bei %X/%X auf Zeitleiste %u" -#: pg_rewind.c:470 +#: pg_rewind.c:474 #, c-format msgid "reading source file list" msgstr "lese Quelldateiliste" -#: pg_rewind.c:474 +#: pg_rewind.c:478 #, c-format msgid "reading target file list" msgstr "lese Zieldateiliste" -#: pg_rewind.c:483 +#: pg_rewind.c:487 #, c-format msgid "reading WAL in target" msgstr "lese WAL im Ziel-Cluster" -#: pg_rewind.c:504 +#: pg_rewind.c:508 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "%lu MB müssen kopiert werden (Gesamtgröße des Quellverzeichnisses ist %lu MB)" -#: pg_rewind.c:522 +#: pg_rewind.c:526 #, c-format msgid "syncing target data directory" msgstr "synchronisiere Zieldatenverzeichnis" -#: pg_rewind.c:538 +#: pg_rewind.c:543 #, c-format msgid "Done!" msgstr "Fertig!" -#: pg_rewind.c:618 +#: pg_rewind.c:623 #, c-format msgid "no action decided for file \"%s\"" msgstr "keine Aktion bestimmt für Datei »%s«" -#: pg_rewind.c:650 +#: pg_rewind.c:655 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "Quellsystem wurde verändert, während pg_rewind lief" -#: pg_rewind.c:654 +#: pg_rewind.c:659 #, c-format msgid "creating backup label and updating control file" msgstr "erzeuge Backup-Label und aktualisiere Kontrolldatei" -#: pg_rewind.c:704 +#: pg_rewind.c:709 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "Quellsystem war in einem unerwarteten Zustand am Ende des Rückspulens" -#: pg_rewind.c:736 +#: pg_rewind.c:741 #, c-format msgid "source and target clusters are from different systems" msgstr "Quell- und Ziel-Cluster sind von verschiedenen Systemen" -#: pg_rewind.c:744 +#: pg_rewind.c:749 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "die Cluster sind nicht mit dieser Version von pg_rewind kompatibel" -#: pg_rewind.c:754 +#: pg_rewind.c:759 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "Zielserver muss entweder Datenprüfsummen oder »wal_log_hints = on« verwenden" -#: pg_rewind.c:765 +#: pg_rewind.c:770 #, c-format msgid "target server must be shut down cleanly" msgstr "Zielserver muss sauber heruntergefahren worden sein" -#: pg_rewind.c:775 +#: pg_rewind.c:780 #, c-format msgid "source data directory must be shut down cleanly" msgstr "Quelldatenverzeichnis muss sauber heruntergefahren worden sein" -#: pg_rewind.c:822 +#: pg_rewind.c:827 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s kB (%d%%) kopiert" -#: pg_rewind.c:950 +#: pg_rewind.c:953 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "konnte keinen gemeinsamen Anfangspunkt in den Zeitleisten von Quell- und Ziel-Cluster finden" -#: pg_rewind.c:991 +#: pg_rewind.c:994 #, c-format msgid "backup label buffer too small" msgstr "Puffer für Backup-Label ist zu klein" -#: pg_rewind.c:1014 +#: pg_rewind.c:1017 #, c-format msgid "unexpected control file CRC" msgstr "unerwartete CRC in Kontrolldatei" -#: pg_rewind.c:1026 +#: pg_rewind.c:1029 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "unerwartete Kontrolldateigröße %d, erwartet wurde %d" -#: pg_rewind.c:1036 +#: pg_rewind.c:1039 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "ungültige WAL-Segmentgröße in Kontrolldatei (%d Byte)" msgstr[1] "ungültige WAL-Segmentgröße in Kontrolldatei (%d Bytes)" -#: pg_rewind.c:1040 +#: pg_rewind.c:1043 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "Die WAL-Segmentgröße muss eine Zweierpotenz zwischen 1 MB und 1 GB sein." -#: pg_rewind.c:1077 pg_rewind.c:1145 +#: pg_rewind.c:1080 pg_rewind.c:1148 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden" -#: pg_rewind.c:1080 pg_rewind.c:1148 +#: pg_rewind.c:1083 pg_rewind.c:1151 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s" -#: pg_rewind.c:1109 +#: pg_rewind.c:1112 #, c-format -msgid "unable to read restore_command from target cluster" -msgstr "konnte restore_command des Ziel-Clusters nicht lesen" +msgid "could not read \"restore_command\" from target cluster" +msgstr "konnte »restore_command« des Ziel-Clusters nicht lesen" -#: pg_rewind.c:1114 +#: pg_rewind.c:1117 #, c-format msgid "\"restore_command\" is not set in the target cluster" msgstr "»restore_command« ist im Ziel-Cluster nicht gesetzt" -#: pg_rewind.c:1152 +#: pg_rewind.c:1155 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "führe »%s« für Zielserver aus, um Wiederherstellung abzuschließen" -#: pg_rewind.c:1190 +#: pg_rewind.c:1193 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "postgres im Einzelbenutzermodus im Ziel-Cluster fehlgeschlagen" -#: pg_rewind.c:1191 +#: pg_rewind.c:1194 #, c-format msgid "Command was: %s" msgstr "Die Anweisung war: %s" @@ -917,157 +917,157 @@ msgstr "ungültige Daten in History-Datei" msgid "Timeline IDs must be less than child timeline's ID." msgstr "Zeitleisten-IDs müssen kleiner als die Zeitleisten-ID des Kindes sein." -#: xlogreader.c:619 +#: xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ungültiger Datensatz-Offset bei %X/%X: mindestens %u erwartet, %u erhalten" -#: xlogreader.c:628 +#: xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "Contrecord angefordert von %X/%X" -#: xlogreader.c:669 xlogreader.c:1134 +#: xlogreader.c:670 xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ungültige Datensatzlänge bei %X/%X: mindestens %u erwartet, %u erhalten" -#: xlogreader.c:758 +#: xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "keine Contrecord-Flag bei %X/%X" -#: xlogreader.c:771 +#: xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "ungültige Contrecord-Länge %u (erwartet %lld) bei %X/%X" -#: xlogreader.c:1142 +#: xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ungültige Resource-Manager-ID %u bei %X/%X" -#: xlogreader.c:1155 xlogreader.c:1171 +#: xlogreader.c:1156 xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "Datensatz mit falschem Prev-Link %X/%X bei %X/%X" -#: xlogreader.c:1209 +#: xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "ungültige Resource-Manager-Datenprüfsumme in Datensatz bei %X/%X" -#: xlogreader.c:1243 +#: xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ungültige magische Zahl %04X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1258 xlogreader.c:1300 +#: xlogreader.c:1259 xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ungültige Info-Bits %04X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1274 +#: xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %llu, Datenbanksystemidentifikator in pg_control ist %llu" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %, Datenbanksystemidentifikator in pg_control ist %" -#: xlogreader.c:1282 +#: xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche Segmentgröße im Seitenkopf" -#: xlogreader.c:1288 +#: xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche XLOG_BLCKSZ im Seitenkopf" -#: xlogreader.c:1320 +#: xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "unerwartete Pageaddr %X/%X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1346 +#: xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "Zeitleisten-ID %u außer der Reihe (nach %u) in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1749 +#: xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u außer der Reihe bei %X/%X" -#: xlogreader.c:1773 +#: xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA gesetzt, aber keine Daten enthalten bei %X/%X" -#: xlogreader.c:1780 +#: xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA nicht gesetzt, aber Datenlänge ist %u bei %X/%X" -#: xlogreader.c:1816 +#: xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE gesetzt, aber Loch Offset %u Länge %u Block-Abbild-Länge %u bei %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE nicht gesetzt, aber Loch Offset %u Länge %u bei %X/%X" -#: xlogreader.c:1846 +#: xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED gesetzt, aber Block-Abbild-Länge %u bei %X/%X" -#: xlogreader.c:1861 +#: xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "weder BKPIMAGE_HAS_HOLE noch BKPIMAGE_COMPRESSED gesetzt, aber Block-Abbild-Länge ist %u bei %X/%X" -#: xlogreader.c:1877 +#: xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL gesetzt, aber keine vorangehende Relation bei %X/%X" -#: xlogreader.c:1889 +#: xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "ungültige block_id %u bei %X/%X" -#: xlogreader.c:1956 +#: xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "Datensatz mit ungültiger Länge bei %X/%X" -#: xlogreader.c:1982 +#: xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "konnte Backup-Block mit ID %d nicht im WAL-Eintrag finden" -#: xlogreader.c:2066 +#: xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "konnte Abbild bei %X/%X mit ungültigem angegebenen Block %d nicht wiederherstellen" -#: xlogreader.c:2073 +#: xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "konnte Abbild mit ungültigem Zustand bei %X/%X nicht wiederherstellen, Block %d" -#: xlogreader.c:2100 xlogreader.c:2117 +#: xlogreader.c:2110 xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "konnte Abbild bei %X/%X nicht wiederherstellen, komprimiert mit %s, nicht unterstützt von dieser Installation, Block %d" -#: xlogreader.c:2126 +#: xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "konnte Abbild bei %X/%X nicht wiederherstellen, komprimiert mit unbekannter Methode, Block %d" -#: xlogreader.c:2134 +#: xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "konnte Abbild bei %X/%X nicht dekomprimieren, Block %d" diff --git a/src/bin/pg_rewind/po/es.po b/src/bin/pg_rewind/po/es.po index af9a810c7c1d5..794c991edcdc3 100644 --- a/src/bin/pg_rewind/po/es.po +++ b/src/bin/pg_rewind/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_rewind (PostgreSQL) 16\n" +"Project-Id-Version: pg_rewind (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:22+0000\n" -"PO-Revision-Date: 2023-10-04 11:47+0200\n" +"POT-Creation-Date: 2025-02-16 19:52+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -41,6 +41,65 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:371 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "no se pudo cerrar el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "discordancia en orden de bytes" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"posible discordancia en orden de bytes\n" +"El ordenamiento de bytes usado para almacenar el archivo pg_control puede no\n" +"coincidir con el usado por este programa. En tal caso los resultados de abajo\n" +"serían erróneos, y la instalación de PostgreSQL sería incompatible con este\n" +"directorio de datos." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:333 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "no se pudo escribir el archivo «%s»: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -52,6 +111,38 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -107,43 +198,58 @@ msgstr "el archivo «%s» tiene tamaño inesperado: %lld en lugar de %lld" msgid "could not open file \"%s\" restored from archive: %m" msgstr "no se pudo abrir el archivo «%s» restaurado del archivo: %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "no se pudo hacer stat al archivo «%s»: %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "restore_command falló: %s" +msgid "\"restore_command\" failed: %s" +msgstr "«restore_command» falló: %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "no se pudo recuperar el archivo «%s» del archivo" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "memoria agotada" +msgid "invalid value \"%s\" for option %s" +msgstr "el valor «%s» no es válido para la opción %s" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" +msgid "%s must be in range %d..%d" +msgstr "%s debe estar en el rango %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "memoria agotada" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "no se pudo escribir a archivo «%s»: %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "no se pudo crear archivo «%s»: %m" +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -159,11 +265,6 @@ msgstr "no se pudo cerrar el archivo de destino «%s»: %m" msgid "could not seek in target file \"%s\": %m" msgstr "no se pudo posicionar en archivo de destino «%s»: %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "no se pudo escribir el archivo «%s»: %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -209,26 +310,6 @@ msgstr "no se pudo crear el link simbólico en «%s»: %m" msgid "could not remove symbolic link \"%s\": %m" msgstr "no se pudo eliminar el enlace simbólico «%s»: %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "no se pudo abrir archivo «%s» para lectura: %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "no se pudo leer el archivo «%s»: %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "no se pudo abrir el directorio «%s»: %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -239,162 +320,157 @@ msgstr "no se pudo leer el enlace simbólico «%s»: %m" msgid "symbolic link \"%s\" target is too long" msgstr "la ruta «%s» del enlace simbólico es demasiado larga" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "no se pudo leer el directorio «%s»: %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "no se pudo abrir el directorio «%s»: %m" -#: filemap.c:236 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "el archivo de datos «%s» en el origen no es un archivo regular" -#: filemap.c:241 filemap.c:274 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "archivo origen duplicado «%s»" -#: filemap.c:329 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "modificación de página inesperada para el archivo no regular «%s»" -#: filemap.c:679 filemap.c:773 +#: filemap.c:744 filemap.c:846 #, c-format msgid "unknown file type for \"%s\"" msgstr "tipo de archivo desconocido para «%s»" -#: filemap.c:706 +#: filemap.c:779 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "el archivo «%s» tiene un tipo diferente en el origen y en el destino" -#: filemap.c:778 +#: filemap.c:851 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "no se pudo decidir qué hacer con el archivo «%s»" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "no se pudo limpiar search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "no se pudo limpiar «search_path»: %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "full_page_writes debe estar activado en el servidor de origen" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "«full_page_writes» debe estar activado en el servidor de origen" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "no se pudo preparar sentencia para obtener el contenido del archivo: %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "error ejecutando consulta (%s) en el servidor de origen: %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "conjunto de resultados inesperados de la consulta" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "error ejecutando consulta (%s) en el servidor de origen: %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "resultado «%s» no reconocido para la ubicación de inserción WAL actual" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "no se pudo obtener el listado de archivos: %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "conjunto de resultados inesperado mientras se obtenía el listado de archivos" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "no se pudo enviar la consulta: %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "no se pudo establecer la coneción libpq a modo «single row»" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "resultados inesperados mientras se obtenían archivos remotos: %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "se recibieron más trozos de datos que los solicitados" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "tamaño del conjunto de resultados inesperado mientras se obtenían archivos remotos" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "tipos de dato inesperados en el conjunto de resultados mientras se obtenían archivos remotos: %u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "formato de resultados inesperado mientras se obtenían archivos remotos" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "valores nulos inesperados en el resultado mientras se obtenían archivos remotos" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "largo del resultado inesperado mientras se obtenían los archivos remotos" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "se recibieron datos para el archivo «%s», cuando se solicitó para «%s»" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" msgstr "se recibieron datos en la posición %lld del archivo «%s», cuando se solicitó para la posición %lld" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "se recibió más de lo solicitado para el archivo «%s»" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "se recibió un número inesperado de trozos de datos" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "no se pudo obtener el archivo remoto «%s»: %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "conjunto de resultados inesperado mientras se obtenía el archivo remoto «%s»" @@ -409,11 +485,6 @@ msgstr "no se pudo abrir el archivo de origen «%s»: %m" msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "el tamaño del archivo de origen «%s» cambió concurrentemente: se esperaban %d bytes, se copiaron %d" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "no se pudo cerrar el archivo «%s»: %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -424,7 +495,7 @@ msgstr "no se pudo posicionar en archivo de origen: %m" msgid "unexpected EOF while reading file \"%s\"" msgstr "EOF inesperado mientras se leía el archivo «%s»" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "memoria agotada mientras se emplazaba un procesador de lectura de WAL" @@ -444,27 +515,27 @@ msgstr "no se pudo leer el registro WAL en %X/%X" msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "el puntero de término %X/%X no es un punto válido; se esperaba %X/%X" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "no se pudo encontrar el registro WAL anterior en %X/%X: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "no se pudo encontrar el registro WAL anterior en %X/%X" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "no se pudo posicionar (seek) el archivo «%s»: %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "el registro WAL modifica una relación, pero el tipo de registro no es reconocido: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "" "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n" @@ -473,7 +544,7 @@ msgstr "" "%s resincroniza un cluster PostgreSQL con otra copia del cluster.\n" "\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "" "Usage:\n" @@ -484,53 +555,53 @@ msgstr "" " %s [OPCION]...\n" "\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "Opciones:\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format msgid "" -" -c, --restore-target-wal use restore_command in target configuration to\n" +" -c, --restore-target-wal use \"restore_command\" in target configuration to\n" " retrieve WAL files from archives\n" msgstr "" -" -c, --restore-target-wal utilizar restore_command de la configuración\n" +" -c, --restore-target-wal utilizar «restore_command» de la configuración\n" " de destino para obtener archivos WAL\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr " -D, --target-pgdata=DIRECTORIO directorio de datos existente a modificar\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n" msgstr " --source-pgdata=DIRECTORIO directorio de datos de origen a sincronizar\n" -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr " --source-server=CONN servidor de origen a sincronizar\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr " -n, --dry-run detener antes de modificar nada\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written\n" " safely to disk\n" msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress escribir mensajes de progreso\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid "" " -R, --write-recovery-conf write configuration for replication\n" @@ -539,7 +610,7 @@ msgstr "" " -R, --write-recovery-conf escribe configuración para replicación\n" " (requiere --source-server)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -548,29 +619,34 @@ msgstr "" " --config-file=ARCHIVO utilizar el archivo de configuración del servidor\n" " principal especificado al ejecutar el clúster de destino\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr " --debug escribir muchos mensajes de depuración\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n" msgstr "" " --no-ensure-shutdown no corregir automáticamente un apagado\n" " no-limpio\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir el método para sincr. archivos a disco\n" + +#: pg_rewind.c:113 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "" "\n" @@ -579,425 +655,420 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "no se especificó origen (--source-pgdata o --source-server)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "sólo uno de --source-pgdata o --source-server puede ser especificado" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "no se especificó directorio de datos de destino (--target-pgdata)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "no source server information (--source-server) specified for --write-recovery-conf" msgstr "no se especificó información de servidor de origen (--source-server) para --write-recovery-conf" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "no puede ser ejecutado por «root»" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Debe ejecutar %s con el superusuario de PostgreSQL." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "no se pudo obtener los permisos del directorio «%s»: %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "conectado al servidor" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "el cluster de origen y destino están en el mismo timeline" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "servidores divergieron en la posición de WAL %X/%X en el timeline %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "no se requiere rebobinar" -#: pg_rewind.c:451 +#: pg_rewind.c:463 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "rebobinando desde el último checkpoint común en %X/%X en el timeline %u" -#: pg_rewind.c:461 +#: pg_rewind.c:473 #, c-format msgid "reading source file list" msgstr "leyendo la lista de archivos de origen" -#: pg_rewind.c:465 +#: pg_rewind.c:477 #, c-format msgid "reading target file list" msgstr "leyendo la lista de archivos de destino" -#: pg_rewind.c:474 +#: pg_rewind.c:486 #, c-format msgid "reading WAL in target" msgstr "leyendo WAL en destino" -#: pg_rewind.c:495 +#: pg_rewind.c:507 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "se necesitan copiar %lu MB (tamaño total de directorio de origen es %lu MB)" -#: pg_rewind.c:513 +#: pg_rewind.c:525 #, c-format msgid "syncing target data directory" msgstr "sincronizando directorio de datos de destino" -#: pg_rewind.c:529 +#: pg_rewind.c:541 #, c-format msgid "Done!" msgstr "¡Listo!" -#: pg_rewind.c:609 +#: pg_rewind.c:621 #, c-format msgid "no action decided for file \"%s\"" msgstr "no se decidió una acción para el archivo «%s»" -#: pg_rewind.c:641 +#: pg_rewind.c:653 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "el sistema origen fue modificado mientras pg_rewind estaba en ejecución" -#: pg_rewind.c:645 +#: pg_rewind.c:657 #, c-format msgid "creating backup label and updating control file" msgstr "creando etiqueta de respaldo y actualizando archivo de control" -#: pg_rewind.c:695 +#: pg_rewind.c:707 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "el sistema origen estaba en un estado inesperado al final del rebobinado" -#: pg_rewind.c:727 +#: pg_rewind.c:739 #, c-format msgid "source and target clusters are from different systems" msgstr "clusters de origen y destino son de sistemas diferentes" -#: pg_rewind.c:735 +#: pg_rewind.c:747 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "los clusters no son compatibles con esta versión de pg_rewind" -#: pg_rewind.c:745 +#: pg_rewind.c:757 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "el servidor de destino necesita tener sumas de verificación de datos o «wal_log_hints» activados" -#: pg_rewind.c:756 +#: pg_rewind.c:768 #, c-format msgid "target server must be shut down cleanly" msgstr "el directorio de destino debe estar apagado limpiamente" -#: pg_rewind.c:766 +#: pg_rewind.c:778 #, c-format msgid "source data directory must be shut down cleanly" msgstr "el directorio de origen debe estar apagado limpiamente" -#: pg_rewind.c:813 +#: pg_rewind.c:825 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s kB (%d%%) copiados" -#: pg_rewind.c:941 +#: pg_rewind.c:951 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "no se pudo encontrar un ancestro común en el timeline de los clusters de origen y destino" -#: pg_rewind.c:982 +#: pg_rewind.c:992 #, c-format msgid "backup label buffer too small" msgstr "el búfer del backup label es demasiado pequeño" -#: pg_rewind.c:1005 +#: pg_rewind.c:1015 #, c-format msgid "unexpected control file CRC" msgstr "CRC de archivo de control inesperado" -#: pg_rewind.c:1017 +#: pg_rewind.c:1027 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "tamaño del archivo de control %d inesperado, se esperaba %d" -#: pg_rewind.c:1026 +#: pg_rewind.c:1037 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d byte" -msgstr[1] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d bytes" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "tamaño de segmento de WAL no válido (%d byte) en archivo de control" +msgstr[1] "tamaño de segmento de WAL no válido (%d bytes) en archivo de control" -#: pg_rewind.c:1065 pg_rewind.c:1135 +#: pg_rewind.c:1041 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "El tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB." + +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "el programa «%s» es requerido por %s, pero no se encontró en el mismo directorio que «%s»" -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1081 pg_rewind.c:1149 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "el programa «%s» fue encontrado por «%s» pero no es de la misma versión que %s" -#: pg_rewind.c:1101 +#: pg_rewind.c:1110 +#, c-format +msgid "could not read restore_command from target cluster" +msgstr "no se pudo leer restore_command en el clúster de destino" + +#: pg_rewind.c:1115 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "restore_command no está definido en el clúster de destino" +msgid "\"restore_command\" is not set in the target cluster" +msgstr "«restore_command» no está definido en el clúster de destino" -#: pg_rewind.c:1142 +#: pg_rewind.c:1153 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "ejecutando «%s» en el servidor de destino para completar la recuperación de caídas" -#: pg_rewind.c:1180 +#: pg_rewind.c:1191 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "el modo «single-user» en el servidor de destino falló" -#: pg_rewind.c:1181 +#: pg_rewind.c:1192 #, c-format msgid "Command was: %s" msgstr "La orden era: % s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "error de sintaxis en archivo de historia: %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "Se esperaba un ID numérico de timeline." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "Se esperaba una ubicación de punto de cambio del «write-ahead log»." -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "datos no válidos en archivo de historia: %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "IDs de timeline deben ser una secuencia creciente." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "datos no válidos en archivo de historia" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "IDs de timeline deben ser menores que el ID de timeline del hijo." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "desplazamiento de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord solicitado por %X/%X" -#: xlogreader.c:676 xlogreader.c:1123 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "largo de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "memoria agotada mientras se intentaba decodificar un registro de largo %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "largo de registro %u en %X/%X demasiado largo" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "no hay bandera de contrecord en %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "largo de contrecord %u no válido (se esperaba %lld) en %X/%X" -#: xlogreader.c:924 -#, c-format -msgid "missing contrecord at %X/%X" -msgstr "falta un contrecord en %X/%X" - -#: xlogreader.c:1131 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ID de gestor de recursos %u no válido en %X/%X" -#: xlogreader.c:1144 xlogreader.c:1160 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "registro con prev-link %X/%X incorrecto en %X/%X" -#: xlogreader.c:1196 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "suma de verificación de los datos del gestor de recursos incorrecta en el registro en %X/%X" -#: xlogreader.c:1230 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "número mágico %04X no válido en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1245 xlogreader.c:1287 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "info bits %04X no válidos en segment WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1261 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "archivo WAL es de un sistema de bases de datos distinto: identificador de sistema en archivo WAL es %llu, identificador en pg_control es %llu" -#: xlogreader.c:1269 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: tamaño de segmento incorrecto en cabecera de paǵina" -#: xlogreader.c:1275 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: XLOG_BLCKSZ incorrecto en cabecera de paǵina" -#: xlogreader.c:1307 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "pageaddr %X/%X inesperado en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1333 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "ID de timeline %u fuera de secuencia (después de %u) en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1739 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u fuera de orden en %X/%X" -#: xlogreader.c:1763 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA está definido, pero no hay datos en %X/%X" -#: xlogreader.c:1770 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA no está definido, pero el largo de los datos es %u en %X/%X" -#: xlogreader.c:1806 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE está definido, pero posición del agujero es %u largo %u largo de imagen %u en %X/%X" -#: xlogreader.c:1822 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE no está definido, pero posición del agujero es %u largo %u en %X/%X" -#: xlogreader.c:1836 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED definido, pero largo de imagen de bloque es %u en %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_COMPRESSED están definidos, pero el largo de imagen de bloque es %u en %X/%X" -#: xlogreader.c:1867 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL está definido, pero no hay «rel» anterior en %X/%X " -#: xlogreader.c:1879 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "block_id %u no válido en %X/%X" -#: xlogreader.c:1946 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "registro con largo no válido en %X/%X" -#: xlogreader.c:1972 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "no se pudo localizar un bloque de respaldo con ID %d en el registro WAL" -#: xlogreader.c:2056 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "no se pudo restaurar la imagen en %X/%X con bloque especificado %d no válido" -#: xlogreader.c:2063 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "no se pudo restaurar la imagen en %X/%X con estado no válido, bloque %d" -#: xlogreader.c:2090 xlogreader.c:2107 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "no se pudo restaurar la imagen en %X/%X comprimida con %s que no está soportado por esta instalación, bloque %d" -#: xlogreader.c:2116 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "no se pudo restaurar la imagen en %X/%X comprimida con un método desconocido, bloque %d" -#: xlogreader.c:2124 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "no se pudo descomprimir la imagen en %X/%X, bloque %d" diff --git a/src/bin/pg_rewind/po/fr.po b/src/bin/pg_rewind/po/fr.po index d83beaa830c0c..da4f2e145203e 100644 --- a/src/bin/pg_rewind/po/fr.po +++ b/src/bin/pg_rewind/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:21+0000\n" -"PO-Revision-Date: 2023-09-05 07:49+0200\n" +"POT-Creation-Date: 2024-08-29 17:53+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -41,6 +41,65 @@ msgstr "détail : " msgid "hint: " msgstr "astuce : " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:350 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "n'a pas pu fermer le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "différence de l'ordre des octets" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"possible incohérence dans l'ordre des octets\n" +"L'ordre des octets utilisé pour enregistrer le fichier pg_control peut ne\n" +"pas correspondre à celui utilisé par ce programme. Dans ce cas, les\n" +"résultats ci-dessous sont incorrects, et l'installation de PostgreSQL\n" +"est incompatible avec ce répertoire des données." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:312 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "impossible d'écrire le fichier « %s » : %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -52,6 +111,38 @@ msgstr "mémoire épuisée\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -107,43 +198,58 @@ msgstr "taille de fichier inattendu pour « %s » : %lld au lieu de %lld" msgid "could not open file \"%s\" restored from archive: %m" msgstr "n'a pas pu ouvrir le fichier « %s » à partir de l'archive : %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "n'a pas pu tester le fichier « %s » : %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "échec de la restore_command : %s" +msgid "\"restore_command\" failed: %s" +msgstr "échec de « restore_command » : %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "n'a pas pu restaurer le fichier « %s » à partir de l'archive" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "mémoire épuisée" +msgid "invalid value \"%s\" for option %s" +msgstr "valeur « %s » invalide pour l'option %s" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" +msgid "%s must be in range %d..%d" +msgstr "%s doit être compris entre %d et %d" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "mémoire épuisée" + +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "n'a pas pu écrire dans le fichier « %s » : %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "n'a pas pu créer le fichier « %s » : %m" +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -159,11 +265,6 @@ msgstr "n'a pas pu fermer le fichier cible « %s » : %m" msgid "could not seek in target file \"%s\": %m" msgstr "n'a pas pu chercher dans le fichier cible « %s » : %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "impossible d'écrire le fichier « %s » : %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -182,7 +283,7 @@ msgstr "n'a pas pu supprimer le fichier « %s » : %m" #: file_ops.c:218 #, c-format msgid "could not open file \"%s\" for truncation: %m" -msgstr "n'a pas pu ouvrir le fichier « %s » pour le troncage : %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour le tronquage : %m" #: file_ops.c:222 #, c-format @@ -209,26 +310,6 @@ msgstr "n'a pas pu créer le lien symbolique à « %s » : %m" msgid "could not remove symbolic link \"%s\": %m" msgstr "n'a pas pu supprimer le lien symbolique « %s » : %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "n'a pas pu lire le fichier « %s » : %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -239,162 +320,157 @@ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" msgid "symbolic link \"%s\" target is too long" msgstr "la cible du lien symbolique « %s » est trop longue" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "n'a pas pu lire le répertoire « %s » : %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "n'a pas pu fermer le répertoire « %s » : %m" -#: filemap.c:236 +#: filemap.c:235 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "le fichier de données « %s » en source n'est pas un fichier standard" -#: filemap.c:241 filemap.c:274 +#: filemap.c:240 filemap.c:273 #, c-format msgid "duplicate source file \"%s\"" msgstr "fichier source « %s » dupliqué" -#: filemap.c:329 +#: filemap.c:328 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "modification inattendue de page pour le fichier non standard « %s »" -#: filemap.c:679 filemap.c:773 +#: filemap.c:682 filemap.c:776 #, c-format msgid "unknown file type for \"%s\"" msgstr "type de fichier inconnu pour « %s »" -#: filemap.c:706 +#: filemap.c:709 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "le fichier « %s » a un type différent pour la source et la cible" -#: filemap.c:778 +#: filemap.c:781 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "n'a pas pu décider que faire avec le fichier « %s » : %m" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "n'a pas pu effacer search_path : %s" +msgid "could not clear \"search_path\": %s" +msgstr "n'a pas pu effacer « search_path » : %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "full_page_writes doit être activé sur le serveur source" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "« full_page_writes » doit être activé sur le serveur source" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "n'a pas pu préparer l'instruction pour récupérer le contenu du fichier : %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "erreur lors de l'exécution de la requête (%s) sur le serveur source : %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "ensemble de résultats inattendu provenant de la requête" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "erreur lors de l'exécution de la requête (%s) dans le serveur source : %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "résultat non reconnu « %s » pour l'emplacement d'insertion actuel dans les WAL" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "n'a pas pu récupérer la liste des fichiers : %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "ensemble de résultats inattendu lors de la récupération de la liste des fichiers" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "n'a pas pu envoyer la requête : %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "n'a pas pu configurer la connexion libpq en mode ligne seule" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "résultat inattendu lors de la récupération des fichiers cibles : %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "a reçu plus de morceaux de données que demandé" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "taille inattendue de l'ensemble de résultats lors de la récupération des fichiers distants" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "types de données inattendus dans l'ensemble de résultats lors de la récupération des fichiers distants : %u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "format de résultat inattendu lors de la récupération des fichiers distants" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "valeurs NULL inattendues dans le résultat lors de la récupération des fichiers distants" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "longueur de résultats inattendu lors de la récupération des fichiers distants" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "a reçu des données du fichier « %s » alors que « %s » était demandé" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" msgstr "a reçu des données au décalage %lld du fichier « %s » alors que le décalage %lld était demandé" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "a reçu plus que demandé pour le fichier « %s »" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "nombre de morceaux de données reçus inattendu" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "n'a pas pu récupérer le fichier distant « %s » : %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "ensemble de résultats inattendu lors de la récupération du fichier distant « %s »" @@ -409,11 +485,6 @@ msgstr "n'a pas pu ouvrir le fichier source « %s » : %m" msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "la taille du fichier source « %s » a changé : %d octets attendus, %d copiés" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "n'a pas pu fermer le fichier « %s » : %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -464,7 +535,7 @@ msgstr "n'a pas pu parcourir le fichier « %s » : %m" msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "l'enregistrement WAL modifie une relation mais le type d'enregistrement n'est pas reconnu : lsn : %X/%X, rmid : %d, rmgr : %s, info : %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "" "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n" @@ -474,7 +545,7 @@ msgstr "" "l'instance.\n" "\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "" "Usage:\n" @@ -485,42 +556,42 @@ msgstr "" " %s [OPTION]...\n" "\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "Options :\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format msgid "" -" -c, --restore-target-wal use restore_command in target configuration to\n" +" -c, --restore-target-wal use \"restore_command\" in target configuration to\n" " retrieve WAL files from archives\n" msgstr "" -" -c, --restore-target-wal utilise restore_command pour la configuration\n" +" -c, --restore-target-wal utilise « restore_command » pour la configuration\n" " cible de récupération des fichiers WAL des\n" " archives\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr " -D, --target-pgdata=RÉPERTOIRE répertoire de données existant à modifier\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n" msgstr " --source-pgdata=RÉPERTOIRE répertoire des données source\n" -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr " --source-server=CHAÎNE serveur source pour la synchronisation\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr " -n, --dry-run arrête avant de modifier quoi que ce soit\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written\n" @@ -529,12 +600,12 @@ msgstr "" " -N, --nosync n'attend pas que les modifications soient\n" " proprement écrites sur disque\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress écrit les messages de progression\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid "" " -R, --write-recovery-conf write configuration for replication\n" @@ -543,7 +614,7 @@ msgstr "" " -R, --write-recovery-conf écrit la configuration pour la réplication\n" " (requiert --source-server)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -553,29 +624,34 @@ msgstr "" " du serveur principal lors de l'exécution de\n" " l'instance cible\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr " --debug écrit beaucoup de messages de débogage\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n" msgstr "" " --no-ensure-shutdown ne corrige pas automatiquement l'arrêt non\n" " propre\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: pg_rewind.c:113 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version, puis quitte\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide, puis quitte\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "" "\n" @@ -584,729 +660,424 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "aucune source indiquée (--source-pgdata ou --source-server)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "une seule des options --source-pgdata et --source-server peut être indiquée" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "aucun répertoire de données cible indiqué (--target-pgdata)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "no source server information (--source-server) specified for --write-recovery-conf" msgstr "aucune information sur le serveur source (--source-server) indiquée pour --write-recovery-conf" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "ne peut pas être exécuté par « root »" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Vous devez exécuter %s en tant que super-utilisateur PostgreSQL." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "n'a pas pu lire les droits du répertoire « %s » : %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "connecté au serveur" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "les instances source et cible sont sur la même ligne de temps" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "les serveurs ont divergé à la position %X/%X des WAL sur la timeline %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "pas de retour en arrière requis" -#: pg_rewind.c:451 +#: pg_rewind.c:460 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "retour en arrière depuis le dernier checkpoint commun à %X/%X sur la ligne de temps %u" -#: pg_rewind.c:461 +#: pg_rewind.c:470 #, c-format msgid "reading source file list" msgstr "lecture de la liste des fichiers sources" -#: pg_rewind.c:465 +#: pg_rewind.c:474 #, c-format msgid "reading target file list" msgstr "lecture de la liste des fichiers cibles" -#: pg_rewind.c:474 +#: pg_rewind.c:483 #, c-format msgid "reading WAL in target" msgstr "lecture du WAL dans la cible" -#: pg_rewind.c:495 +#: pg_rewind.c:504 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "a besoin de copier %lu Mo (la taille totale du répertoire source est %lu Mo)" -#: pg_rewind.c:513 +#: pg_rewind.c:522 #, c-format msgid "syncing target data directory" msgstr "synchronisation du répertoire des données cible" -#: pg_rewind.c:529 +#: pg_rewind.c:538 #, c-format msgid "Done!" msgstr "Terminé !" -#: pg_rewind.c:609 +#: pg_rewind.c:618 #, c-format msgid "no action decided for file \"%s\"" msgstr "aucune action décidée pour le fichier « %s »" -#: pg_rewind.c:641 +#: pg_rewind.c:650 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "le système source a été modifié alors que pg_rewind était en cours d'exécution" -#: pg_rewind.c:645 +#: pg_rewind.c:654 #, c-format msgid "creating backup label and updating control file" msgstr "création du fichier backup_label et mise à jour du fichier contrôle" -#: pg_rewind.c:695 +#: pg_rewind.c:704 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "le système source était dans un état inattendu en fin de rewind" -#: pg_rewind.c:727 +#: pg_rewind.c:736 #, c-format msgid "source and target clusters are from different systems" msgstr "les instances source et cible proviennent de systèmes différents" -#: pg_rewind.c:735 +#: pg_rewind.c:744 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "les instances ne sont pas compatibles avec cette version de pg_rewind" -#: pg_rewind.c:745 +#: pg_rewind.c:754 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "le serveur cible doit soit utiliser les sommes de contrôle sur les données soit avoir wal_log_hints configuré à on" -#: pg_rewind.c:756 +#: pg_rewind.c:765 #, c-format msgid "target server must be shut down cleanly" msgstr "le serveur cible doit être arrêté proprement" -#: pg_rewind.c:766 +#: pg_rewind.c:775 #, c-format msgid "source data directory must be shut down cleanly" msgstr "le répertoire de données source doit être arrêté proprement" -#: pg_rewind.c:813 +#: pg_rewind.c:822 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s Ko (%d%%) copiés" -#: pg_rewind.c:941 +#: pg_rewind.c:948 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "n'a pas pu trouver l'ancêtre commun des lignes de temps des instances source et cible" -#: pg_rewind.c:982 +#: pg_rewind.c:989 #, c-format msgid "backup label buffer too small" msgstr "tampon du label de sauvegarde trop petit" -#: pg_rewind.c:1005 +#: pg_rewind.c:1012 #, c-format msgid "unexpected control file CRC" msgstr "CRC inattendu pour le fichier de contrôle" -#: pg_rewind.c:1017 +#: pg_rewind.c:1024 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "taille %d inattendue du fichier de contrôle, %d attendu" -#: pg_rewind.c:1026 +#: pg_rewind.c:1034 +#, c-format +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "taille invalide du segment WAL dans le fichier de contrôle (%d octet)" +msgstr[1] "taille invalide du segment WAL dans le fichier de contrôle (%d octets)" + +#: pg_rewind.c:1038 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octet" -msgstr[1] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octets" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go." -#: pg_rewind.c:1065 pg_rewind.c:1135 +#: pg_rewind.c:1075 pg_rewind.c:1143 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé dans le même répertoire que « %s »" -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "le programme « %s » a été trouvé par « %s » mais n'est pas de la même version que %s" -#: pg_rewind.c:1101 +#: pg_rewind.c:1107 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "restore_command n'est pas configuré sur l'instance cible" +msgid "could not read restore_command from target cluster" +msgstr "n'a pas pu lire restore_command à partir de l'instance cible" -#: pg_rewind.c:1142 +#: pg_rewind.c:1112 +#, c-format +msgid "\"restore_command\" is not set in the target cluster" +msgstr "« restore_command» n'est pas configuré sur l'instance cible" + +#: pg_rewind.c:1150 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "exécution de « %s » pour terminer la restauration après crash du serveur cible" -#: pg_rewind.c:1180 +#: pg_rewind.c:1188 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "le mot simple-utilisateur de postgres a échoué pour l'instance cible" -#: pg_rewind.c:1181 +#: pg_rewind.c:1189 #, c-format msgid "Command was: %s" msgstr "La commande était : %s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "erreur de syntaxe dans le fichier historique : %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "Attendait un identifiant timeline numérique." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "Attendait un emplacement de bascule de journal de transactions." -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "données invalides dans le fichier historique : %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "Les identifiants timeline doivent être en ordre croissant." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "données invalides dans le fichier historique" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "" "Les identifiants timeline doivent être plus petits que les enfants des\n" "identifiants timeline." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "décalage invalide de l'enregistrement à %X/%X : attendait au moins %u, a eu %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "« contrecord » est requis par %X/%X" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "longueur invalide de l'enregistrement à %X/%X : attendait au moins %u, a eu %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "manque mémoire lors de la tentative de décodage d'un enregistrement de longueur %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "longueur trop importante de l'enregistrement %u à %X/%X" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "il n'existe pas de drapeau contrecord à %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "longueur %u invalide du contrecord (%lld attendu) à %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "identifiant du gestionnaire de ressources invalide %u à %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "enregistrement avec prev-link %X/%X incorrect à %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "" "somme de contrôle des données du gestionnaire de ressources incorrecte à\n" "l'enregistrement %X/%X" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "numéro magique invalide %04X dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "bits d'information %04X invalides dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "Le fichier WAL provient d'une instance différente : l'identifiant système de la base dans le fichier WAL est %llu, alors que l'identifiant système de la base dans pg_control est %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "Le fichier WAL provient d'une instance différente : taille invalide du segment dans l'en-tête de page" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "Le fichier WAL provient d'une instance différente : XLOG_BLCKSZ incorrect dans l'en-tête de page" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "pageaddr %X/%X inattendue dans le journal de transactions %s, LSN %X/%X, segment %u" -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "identifiant timeline %u hors de la séquence (après %u) dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u désordonné à %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA configuré, mais aucune donnée inclus à %X/%X" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA non configuré, mais la longueur des données est %u à %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE activé, mais décalage trou %u longueur %u longueur image bloc %u à %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE désactivé, mais décalage trou %u longueur %u à %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL configuré, mais pas de relation précédente à %X/%X" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "block_id %u invalide à %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "enregistrement de longueur invalide à %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "n'a pas pu localiser le bloc de sauvegarde d'ID %d dans l'enregistrement WAL" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "n'a pas pu restaurer l'image à %X/%X avec le bloc invalide %d indiqué" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X avec un état invalide, bloc %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X compressé avec %s, qui est non supporté par le serveur, bloc %d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X compressé avec une méthode inconnue, bloc %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "n'a pas pu décompresser l'image à %X/%X, bloc %d" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid " block %u\n" -#~ msgstr " bloc %u\n" - -#, c-format -#~ msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform" -#~ msgstr "« %s » est un lien symbolique mais les liens symboliques ne sont pas supportés sur cette plateforme" - -#~ msgid "\"%s\" is not a directory" -#~ msgstr "« %s » n'est pas un répertoire" - -#~ msgid "\"%s\" is not a regular file" -#~ msgstr "« %s » n'est pas un fichier standard" - -#~ msgid "\"%s\" is not a symbolic link" -#~ msgstr "« %s » n'est pas un lien symbolique" - -#~ msgid "%d: %X/%X - %X/%X\n" -#~ msgstr "%d : %X/%X - %X/%X\n" - -#~ msgid "%s (%s)\n" -#~ msgstr "%s (%s)\n" - -#~ msgid "%s: WARNING: cannot create restricted tokens on this platform\n" -#~ msgstr "%s : ATTENTION : ne peut pas créer les jetons restreints sur cette plateforme\n" - -#~ msgid "%s: could not allocate SIDs: error code %lu\n" -#~ msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n" - -#~ msgid "%s: could not create restricted token: error code %lu\n" -#~ msgstr "%s : n'a pas pu créer le jeton restreint : code d'erreur %lu\n" - -#~ msgid "%s: could not get exit code from subprocess: error code %lu\n" -#~ msgstr "%s : n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu\n" - -#~ msgid "%s: could not open process token: error code %lu\n" -#~ msgstr "%s : n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n" - -#~ msgid "%s: could not re-execute with restricted token: error code %lu\n" -#~ msgstr "%s : n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu\n" - -#~ msgid "%s: could not read permissions of directory \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu lire les droits sur le répertoire « %s » : %s\n" - -#~ msgid "%s: could not start process for command \"%s\": error code %lu\n" -#~ msgstr "%s : n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "Expected a numeric timeline ID.\n" -#~ msgstr "Attendait un identifiant numérique de ligne de temps.\n" - -#~ msgid "Expected a write-ahead log switchpoint location.\n" -#~ msgstr "Attendait un emplacement de bascule de journal de transactions.\n" - -#~ msgid "Failure, exiting\n" -#~ msgstr "Échec, sortie\n" - -#~ msgid "Source timeline history:\n" -#~ msgstr "Historique de la ligne de temps source :\n" - -#~ msgid "Target timeline history:\n" -#~ msgstr "Historique de la ligne de temps cible :\n" - -#~ msgid "" -#~ "The program \"%s\" is needed by %s but was\n" -#~ "not found in the same directory as \"%s\".\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé\n" -#~ "dans le même répertoire que « %s ».\n" -#~ "Vérifiez votre installation." - -#~ msgid "" -#~ "The program \"%s\" was found by \"%s\" but was\n" -#~ "not the same version as %s.\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « %s » a été trouvé par « %s » mais n'était pas de la même version\n" -#~ "que %s.\n" -#~ "Vérifiez votre installation." - -#~ msgid "" -#~ "The program \"initdb\" is needed by %s but was\n" -#~ "not found in the same directory as \"%s\".\n" -#~ "Check your installation.\n" -#~ msgstr "" -#~ "Le programme « initdb » est nécessaire pour %s, mais n'a pas été trouvé\n" -#~ "dans le même répertoire que « %s ».\n" -#~ "Vérifiez votre installation.\n" - -#~ msgid "" -#~ "The program \"initdb\" was found by \"%s\"\n" -#~ "but was not the same version as %s.\n" -#~ "Check your installation.\n" -#~ msgstr "" -#~ "Le programme « initdb » a été trouvé par « %s », mais n'est pas de la même version\n" -#~ "que %s.\n" -#~ "Vérifiez votre installation.\n" - -#~ msgid "" -#~ "The program \"postgres\" is needed by %s but was not found in the\n" -#~ "same directory as \"%s\".\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « postgres » est nécessaire à %s mais n'a pas été trouvé dans\n" -#~ "le même répertoire que « %s ».\n" -#~ "Vérifiez votre installation." - -#~ msgid "" -#~ "The program \"postgres\" was found by \"%s\"\n" -#~ "but was not the same version as %s.\n" -#~ "Check your installation." -#~ msgstr "" -#~ "Le programme « postgres » a été trouvé par « %s » mais n'est pas de la même\n" -#~ "version que « %s ».\n" -#~ "Vérifiez votre installation." - -#~ msgid "Timeline IDs must be in increasing sequence.\n" -#~ msgstr "Les identifiants de ligne de temps doivent être dans une séquence croissante.\n" - -#~ msgid "Timeline IDs must be less than child timeline's ID.\n" -#~ msgstr "Les identifiants de ligne de temps doivent être inférieurs à l'identifiant de la ligne de temps enfant.\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#~ msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header" -#~ msgstr "le fichier WAL provient d'un système différent : XLOG_SEG_SIZE invalide dans l'en-tête de page" - -#~ msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte\n" -#~ msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes\n" -#~ msgstr[0] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octet\n" -#~ msgstr[1] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octets\n" - -#, c-format -#~ msgid "You must run %s as the PostgreSQL superuser.\n" -#~ msgstr "Vous devez exécuter %s en tant que super-utilisateur PostgreSQL.\n" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "ne peut pas créer les jetons restreints sur cette plateforme : code d'erreur %lu" - -#, c-format -#~ msgid "cannot use restore_command with %%r placeholder" -#~ msgstr "ne peut pas utiliser restore_command avec le joker %%r" - -#~ msgid "could not close directory \"%s\": %s\n" -#~ msgstr "n'a pas pu fermer le répertoire « %s » : %s\n" - -#~ msgid "could not close file \"%s\": %s\n" -#~ msgstr "n'a pas pu fermer le fichier « %s » : %s\n" - -#~ msgid "could not connect to server: %s" -#~ msgstr "n'a pas pu se connecter au serveur : %s" - -#~ msgid "could not create directory \"%s\": %s\n" -#~ msgstr "n'a pas pu créer le répertoire « %s » : %s\n" - -#~ msgid "could not create temporary table: %s" -#~ msgstr "n'a pas pu créer la table temporaire : %s" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "n'a pas pu charger la bibliothèque « %s » : code d'erreur %lu" - -#~ msgid "could not open directory \"%s\": %s\n" -#~ msgstr "n'a pas pu ouvrir le répertoire « %s » : %s\n" - -#~ msgid "could not open file \"%s\" for reading: %s\n" -#~ msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %s\n" - -#~ msgid "could not open file \"%s\": %s\n" -#~ msgstr "n'a pas pu ouvrir le fichier « %s » : %s\n" - -#~ msgid "could not read directory \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le répertoire « %s » : %s\n" - -#~ msgid "could not read file \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le fichier « %s » : %s\n" - -#~ msgid "could not read from file \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le fichier « %s » : %s\n" - -#~ msgid "could not read symbolic link \"%s\": %s\n" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %s\n" - -#~ msgid "could not remove directory \"%s\": %s\n" -#~ msgstr "n'a pas pu supprimer le répertoire « %s » : %s\n" - -#~ msgid "could not remove file \"%s\": %s\n" -#~ msgstr "n'a pas pu supprimer le fichier « %s » : %s\n" - -#~ msgid "could not remove symbolic link \"%s\": %s\n" -#~ msgstr "n'a pas pu supprimer le lien symbolique « %s » : %s\n" - -#~ msgid "could not seek in file \"%s\": %s\n" -#~ msgstr "n'a pas pu chercher dans le fichier « %s » : %s\n" - -#~ msgid "could not send COPY data: %s" -#~ msgstr "n'a pas pu envoyer les données COPY : %s" - -#~ msgid "could not send end-of-COPY: %s" -#~ msgstr "n'a pas pu envoyer end-of-COPY : %s" - -#~ msgid "could not send file list: %s" -#~ msgstr "n'a pas pu envoyer la liste de fichiers : %s" - -#~ msgid "could not set up connection context: %s" -#~ msgstr "n'a pas pu initialiser le contexte de connexion : « %s »" - -#~ msgid "could not stat file \"%s\": %s\n" -#~ msgstr "n'a pas pu tester le fichier « %s » : %s\n" - -#~ msgid "could not truncate file \"%s\" to %u: %s\n" -#~ msgstr "n'a pas pu tronquer le fichier « %s » à %u : %s\n" - -#~ msgid "could not write file \"%s\": %s\n" -#~ msgstr "n'a pas pu écrire le fichier « %s » : %s\n" - -#~ msgid "entry \"%s\" excluded from source file list\n" -#~ msgstr "enregistrement « %s » exclus de la liste des fichiers sources\n" - -#~ msgid "entry \"%s\" excluded from target file list\n" -#~ msgstr "enregistrement « %s » exclus de la liste des fichiers cibles\n" - -#, c-format -#~ msgid "failed to locate backup block with ID %d in WAL record" -#~ msgstr "échec de localisation du bloc de sauvegarde d'ID %d dans l'enregistrement WAL" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "fetched file \"%s\", length %d\n" -#~ msgstr "fichier récupéré « %s », longueur %d\n" - -#~ msgid "getting file chunks\n" -#~ msgstr "récupération des parties de fichier\n" - -#, c-format -#~ msgid "image at %X/%X compressed with %s not supported by build, block %d" -#~ msgstr "image à %X/%X compressé avec %s, non supporté, bloc %d" - -#, c-format -#~ msgid "image at %X/%X compressed with unknown method, block %d" -#~ msgstr "image à %X/%X compressé avec une méthode inconnue, bloc %d" - -#, c-format -#~ msgid "invalid compressed image at %X/%X, block %d" -#~ msgstr "image compressée invalide à %X/%X, bloc %d" - -#~ msgid "invalid contrecord length %u at %X/%X reading %X/%X, expected %u" -#~ msgstr "longueur %u invalide du contrecord à %X/%X en lisant %X/%X, attendait %u" - -#, c-format -#~ msgid "invalid control file" -#~ msgstr "fichier de contrôle invalide" - -#~ msgid "invalid data in history file: %s\n" -#~ msgstr "données invalides dans le fichier historique : %s\n" - -#, c-format -#~ msgid "invalid record offset at %X/%X" -#~ msgstr "décalage invalide de l'enregistrement %X/%X" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "contrecord manquant à %X/%X" - -#~ msgid "received data at offset " -#~ msgstr "a reçu des données au décalage " - -#~ msgid "received null value for chunk for file \"%s\", file has been deleted\n" -#~ msgstr "a reçu une valeur NULL pour une partie du fichier « %s », le fichier a été supprimé\n" - -#~ msgid "source file list is empty" -#~ msgstr "la liste de fichiers sources est vide" - -#~ msgid "source server must not be in recovery mode" -#~ msgstr "le serveur source ne doit pas être en mode restauration" - -#~ msgid "symbolic link \"%s\" target is too long\n" -#~ msgstr "la cible du lien symbolique « %s » est trop long\n" - -#~ msgid "sync of target directory failed\n" -#~ msgstr "échec de la synchronisation du répertoire cible\n" - -#~ msgid "syntax error in history file: %s\n" -#~ msgstr "erreur de syntaxe dans le fichier historique : %s\n" - -#~ msgid "there is no contrecord flag at %X/%X reading %X/%X" -#~ msgstr "il n'existe pas de drapeau contrecord à %X/%X en lisant %X/%X" - -#~ msgid "unexpected result while sending file list: %s" -#~ msgstr "résultat inattendu lors de l'envoi de la liste de fichiers : %s" diff --git a/src/bin/pg_rewind/po/ja.po b/src/bin/pg_rewind/po/ja.po index 7f535641aed37..80cdf4e73bada 100644 --- a/src/bin/pg_rewind/po/ja.po +++ b/src/bin/pg_rewind/po/ja.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_rewind (PostgreSQL 17)\n" +"Project-Id-Version: pg_rewind (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:24+0900\n" -"PO-Revision-Date: 2024-06-14 11:29+0900\n" +"POT-Creation-Date: 2025-03-31 09:53+0900\n" +"PO-Revision-Date: 2025-03-31 16:34+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -20,22 +20,22 @@ msgstr "" "X-Generator: Poedit 1.8.13\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " @@ -45,19 +45,19 @@ msgstr "ヒント: " msgid "could not open file \"%s\" for reading: %m" msgstr "ファイル\"%s\"を読み取り用にオープンできませんでした: %m" -#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 -#: local_source.c:163 parsexlog.c:350 +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:102 +#: local_source.c:161 parsexlog.c:371 #, c-format msgid "could not read file \"%s\": %m" msgstr "ファイル\"%s\"の読み取りに失敗しました: %m" -#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: local_source.c:121 local_source.c:172 +#: local_source.c:119 local_source.c:170 #, c-format msgid "could not close file \"%s\": %m" msgstr "ファイル\"%s\"をクローズできませんでした: %m" @@ -79,10 +79,10 @@ msgstr "" "されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" "PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: parsexlog.c:312 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: parsexlog.c:333 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" @@ -92,8 +92,8 @@ msgstr "ファイル\"%s\"をオープンできませんでした: %m" msgid "could not write file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" @@ -109,34 +109,34 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null ポインタを複製できません(内部エラー)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #: ../../fe_utils/archive.c:86 file_ops.c:417 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 file_ops.c:388 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 file_ops.c:462 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -221,29 +221,34 @@ msgstr "%sは%d..%dの範囲になければなりません" msgid "unrecognized sync method: %s" msgstr "認識できない同期方式: %s" -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 #, c-format msgid "out of memory" msgstr "メモリ不足です" -#: ../../fe_utils/recovery_gen.c:143 +#: ../../fe_utils/recovery_gen.c:144 #, c-format msgid "could not write to file \"%s\": %m" msgstr "ファイル\"%s\"を書き出せませんでした: %m" -#: ../../fe_utils/recovery_gen.c:152 +#: ../../fe_utils/recovery_gen.c:153 #, c-format msgid "could not create file \"%s\": %m" msgstr "ファイル\"%s\"を作成できませんでした: %m" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/recovery_gen.c:215 pg_rewind.c:311 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" @@ -323,177 +328,177 @@ msgstr "シンボリックリンク\"%s\"の参照先が長すぎます" msgid "could not close directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" -#: filemap.c:235 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "ソースのデータファイル\"%s\"は通常のファイルではありません" -#: filemap.c:240 filemap.c:273 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "ソースファイル\"%s\"が重複しています" -#: filemap.c:328 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "非通常ファイル\"%s\"に対する想定外のページの書き換えです" -#: filemap.c:682 filemap.c:776 +#: filemap.c:743 filemap.c:845 #, c-format msgid "unknown file type for \"%s\"" msgstr "\"%s\"に対する未知のファイルタイプ" -#: filemap.c:709 +#: filemap.c:778 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "ファイル\"%s\"はソースとターゲットとで異なるタイプです" -#: filemap.c:781 +#: filemap.c:850 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "ファイル\"%s\"の処理を決定できませんでした" -#: libpq_source.c:131 +#: libpq_source.c:130 #, c-format msgid "could not clear \"search_path\": %s" msgstr "\"search_path\"を消去できませんでした: %s" -#: libpq_source.c:142 +#: libpq_source.c:141 #, c-format msgid "\"full_page_writes\" must be enabled in the source server" msgstr "ソースサーバーでは\"full_pate_writes\"は有効でなければなりません" -#: libpq_source.c:153 +#: libpq_source.c:152 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "ファイル内容を取得するための文を準備できませんでした: %s" -#: libpq_source.c:172 +#: libpq_source.c:171 #, c-format msgid "error running query (%s) on source server: %s" msgstr "ソースサーバーで実行中のクエリ(%s)でエラー: %s" -#: libpq_source.c:177 +#: libpq_source.c:176 #, c-format msgid "unexpected result set from query" msgstr "クエリから想定外の結果セット" -#: libpq_source.c:199 +#: libpq_source.c:198 #, c-format msgid "error running query (%s) in source server: %s" msgstr "ソースサーバーの実行中のクエリ(%s)でエラー: %s" -#: libpq_source.c:220 +#: libpq_source.c:219 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "現在のWAL挿入位置として認識不可の結果\"%s\"" -#: libpq_source.c:271 +#: libpq_source.c:270 #, c-format msgid "could not fetch file list: %s" msgstr "ファイルリストをフェッチできませんでした: %s" -#: libpq_source.c:276 +#: libpq_source.c:275 #, c-format msgid "unexpected result set while fetching file list" msgstr "ファイルリストのフェッチ中に想定外の結果セット" -#: libpq_source.c:477 +#: libpq_source.c:476 #, c-format msgid "could not send query: %s" msgstr "クエリを送信できませんでした: %s" -#: libpq_source.c:480 +#: libpq_source.c:479 #, c-format msgid "could not set libpq connection to single row mode" msgstr "libpq接続を単一行モードに設定できませんでした" -#: libpq_source.c:510 +#: libpq_source.c:509 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "リモートファイルをフェッチ中に想定外の結果: %s" -#: libpq_source.c:515 +#: libpq_source.c:514 #, c-format msgid "received more data chunks than requested" msgstr "要求よりも多くのデータチャンクが到着しました" -#: libpq_source.c:519 +#: libpq_source.c:518 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "リモートファイルのフェッチ中に想定外の結果セットサイズ" -#: libpq_source.c:525 +#: libpq_source.c:524 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "リモートファイルのフェッチ中の結果セットに想定外のデータ型: %u %u %u" -#: libpq_source.c:533 +#: libpq_source.c:532 #, c-format msgid "unexpected result format while fetching remote files" msgstr "リモートファイルのフェッチ中に想定外の結果形式" -#: libpq_source.c:539 +#: libpq_source.c:538 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "リモートファイルのフェッチ中の結果に想定外のNULL値" -#: libpq_source.c:543 +#: libpq_source.c:542 #, c-format msgid "unexpected result length while fetching remote files" msgstr "リモートファイルのフェッチ中に想定外の結果の長さ" -#: libpq_source.c:576 +#: libpq_source.c:575 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "ファイル\"%s\"への要求に対してファイル\"%s\"のデータを受信しました" -#: libpq_source.c:580 +#: libpq_source.c:579 #, c-format -msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" -msgstr "ファイル\"%2$s\"のオフセット%3$lldへの要求に対してオフセット%1$lldのデータを受信しました" +msgid "received data at offset % of file \"%s\", when requested for offset %lld" +msgstr "ファイル\"%2$s\"のオフセット%3$lldへの要求しましたが、オフセット%1$のデータを受信しました" -#: libpq_source.c:592 +#: libpq_source.c:591 #, c-format msgid "received more than requested for file \"%s\"" msgstr "ファイル”%s\"に対して要求よりも多量のデータを受信しました" -#: libpq_source.c:605 +#: libpq_source.c:604 #, c-format msgid "unexpected number of data chunks received" msgstr "想定外の数のデータチャンクを受信しました" -#: libpq_source.c:648 +#: libpq_source.c:647 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "リモートファイル\"%s\"をフェッチできませんでした: %s" -#: libpq_source.c:653 +#: libpq_source.c:652 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "リモートファイル\"%s\"のフェッチ中に想定外の結果セット" -#: local_source.c:90 local_source.c:142 +#: local_source.c:88 local_source.c:140 #, c-format msgid "could not open source file \"%s\": %m" msgstr "ソースファイル\"%s\"をオープンすることができませんでした: %m" -#: local_source.c:117 +#: local_source.c:115 #, c-format msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "ファイル\"%s\"のサイズが同時に変更されました。%dバイトを期待していましたが、%dバイトコピーされました" -#: local_source.c:146 +#: local_source.c:144 #, c-format msgid "could not seek in source file: %m" msgstr "ソースファイルをシークすることができませんでした: %m" -#: local_source.c:165 +#: local_source.c:163 #, c-format msgid "unexpected EOF while reading file \"%s\"" msgstr "ファイル\"%s\"を読み込み中に想定外のEOF" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "WAL読み取り機構のメモリ割り当て中にメモリ不足" @@ -513,22 +518,22 @@ msgstr "%X/%XのWALレコードを読み取れませんでした" msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "終了点%X/%Xは妥当な終了点ではありません; %X/%Xを期待していました" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "%X/%Xの前のWALレコードが見つかりませんでした: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "%X/%Xの前のWALレコードが見つかりませんでした" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "ファイル\"%s\"をシークできませんでした: %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "WALレコードはリレーションを更新しますが、レコードの型を認識できません: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" @@ -704,11 +709,6 @@ msgstr "PostgreSQLのスーパーユーザーで%sを実行しなければなり msgid "could not read permissions of directory \"%s\": %m" msgstr "ディレクトリ\"%s\"の権限を読み取れませんでした: %m" -#: pg_rewind.c:311 -#, c-format -msgid "%s" -msgstr "%s" - #: pg_rewind.c:314 #, c-format msgid "connected to server" @@ -729,153 +729,153 @@ msgstr "タイムライン%3$uのWAL位置%1$X/%2$Xで両サーバーが分岐 msgid "no rewind required" msgstr "巻き戻しは必要ありません" -#: pg_rewind.c:460 +#: pg_rewind.c:464 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "タイムライン%3$uの%1$X/%2$Xにある最新の共通チェックポイントから巻き戻しています" -#: pg_rewind.c:470 +#: pg_rewind.c:474 #, c-format msgid "reading source file list" msgstr "ソースファイルリストを読み込んでいます" -#: pg_rewind.c:474 +#: pg_rewind.c:478 #, c-format msgid "reading target file list" msgstr "ターゲットファイルリストを読み込んでいます" -#: pg_rewind.c:483 +#: pg_rewind.c:487 #, c-format msgid "reading WAL in target" msgstr "ターゲットでWALを読み込んでいます" -#: pg_rewind.c:504 +#: pg_rewind.c:508 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "%lu MBコピーする必要があります(ソースディレクトリの合計サイズは%lu MBです)" -#: pg_rewind.c:522 +#: pg_rewind.c:526 #, c-format msgid "syncing target data directory" msgstr "ターゲットデータディレクトリを同期しています" -#: pg_rewind.c:538 +#: pg_rewind.c:543 #, c-format msgid "Done!" msgstr "完了!" -#: pg_rewind.c:618 +#: pg_rewind.c:623 #, c-format msgid "no action decided for file \"%s\"" msgstr "ファイル\"%s\"に対するアクションが決定されていません" -#: pg_rewind.c:650 +#: pg_rewind.c:655 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "pg_rewindの実行中にソースシス7テムが更新されました" -#: pg_rewind.c:654 +#: pg_rewind.c:659 #, c-format msgid "creating backup label and updating control file" msgstr "backup labelを作成して制御ファイルを更新しています" -#: pg_rewind.c:704 +#: pg_rewind.c:709 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "巻き戻し完了時点のソースシステムが想定外の状態でした" -#: pg_rewind.c:736 +#: pg_rewind.c:741 #, c-format msgid "source and target clusters are from different systems" msgstr "ソースクラスタとターゲットクラスタは異なるシステムのものです" -#: pg_rewind.c:744 +#: pg_rewind.c:749 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "クラスタは、このバージョンのpg_rewindとの互換性がありません" -#: pg_rewind.c:754 +#: pg_rewind.c:759 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "ターゲットサーバーはデータチェックサムを利用している、または\"wal_log_hints = on\"である必要があります" -#: pg_rewind.c:765 +#: pg_rewind.c:770 #, c-format msgid "target server must be shut down cleanly" msgstr "ターゲットサーバーはきれいにシャットダウンされていなければなりません" -#: pg_rewind.c:775 +#: pg_rewind.c:780 #, c-format msgid "source data directory must be shut down cleanly" msgstr "ソースデータディレクトリはきれいにシャットダウンされていなければなりません" -#: pg_rewind.c:822 +#: pg_rewind.c:827 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s kB (%d%%) コピーしました" -#: pg_rewind.c:950 +#: pg_rewind.c:953 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "ソースクラスタとターゲットクラスタのタイムラインの共通の祖先を見つけられません" -#: pg_rewind.c:991 +#: pg_rewind.c:994 #, c-format msgid "backup label buffer too small" msgstr "バックアップラベルのバッファが小さすぎます" -#: pg_rewind.c:1014 +#: pg_rewind.c:1017 #, c-format msgid "unexpected control file CRC" msgstr "想定外の制御ファイルCRCです" -#: pg_rewind.c:1026 +#: pg_rewind.c:1029 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "想定外の制御ファイルのサイズ%d、想定は%d" -#: pg_rewind.c:1036 +#: pg_rewind.c:1039 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "制御ファイル中の不正なWALセグメントサイズ (%dバイト)" -#: pg_rewind.c:1040 +#: pg_rewind.c:1043 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WALセグメントサイズは1MBから1GBまでの間の2の累乗でなければなりません。" -#: pg_rewind.c:1077 pg_rewind.c:1145 +#: pg_rewind.c:1080 pg_rewind.c:1148 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "%2$sには\"%1$s\"プログラムが必要ですが、\"%3$s\"と同じディレクトリにありませんでした。" -#: pg_rewind.c:1080 pg_rewind.c:1148 +#: pg_rewind.c:1083 pg_rewind.c:1151 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした。" -#: pg_rewind.c:1109 +#: pg_rewind.c:1112 #, c-format -msgid "unable to read restore_command from target cluster" -msgstr "ターゲットクラスタからrestore_commandが読み取れません" +msgid "could not read \"restore_command\" from target cluster" +msgstr "ターゲットクラスタから\"restore_command\"が読み取れませんでした" -#: pg_rewind.c:1114 +#: pg_rewind.c:1117 #, c-format msgid "\"restore_command\" is not set in the target cluster" msgstr "ターゲットクラスタで\"restore_command\"が設定されていません" -#: pg_rewind.c:1152 +#: pg_rewind.c:1155 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "ターゲットサーバーに対して\"%s\"を実行してクラッシュリカバリを完了させます" -#: pg_rewind.c:1190 +#: pg_rewind.c:1193 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "ターゲットクラスタでのpostgresコマンドのシングルユーザーモード実行に失敗しました" -#: pg_rewind.c:1191 +#: pg_rewind.c:1194 #, c-format msgid "Command was: %s" msgstr "コマンド: %s" @@ -915,157 +915,157 @@ msgstr "履歴ファイル内の無効なデータ" msgid "Timeline IDs must be less than child timeline's ID." msgstr "タイムラインIDは子のタイムラインIDより小さくなければなりません。" -#: xlogreader.c:619 +#: xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "%X/%Xのレコードオフセットが無効です:最低でも%uを期待していましたが、実際は%uでした" -#: xlogreader.c:628 +#: xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "%X/%Xではcontrecordが必要です" -#: xlogreader.c:669 xlogreader.c:1134 +#: xlogreader.c:670 xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "%X/%Xのレコード長が無効です:最低でも%uを期待していましたが、実際は%uでした" -#: xlogreader.c:758 +#: xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "%X/%Xで contrecord フラグがありません" -#: xlogreader.c:771 +#: xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "%3$X/%4$Xの継続レコードの長さ%1$u(正しくは%2$lld)は不正です" -#: xlogreader.c:1142 +#: xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "%2$X/%3$XのリソースマネージャID %1$uが無効です" -#: xlogreader.c:1155 xlogreader.c:1171 +#: xlogreader.c:1156 xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "直前のリンク%1$X/%2$Xが不正なレコードが%3$X/%4$Xにあります" -#: xlogreader.c:1209 +#: xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "%X/%Xのレコード内のリソースマネージャデータのチェックサムが不正です" -#: xlogreader.c:1243 +#: xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%2$s、LSN %3$X/%4$X、オフセット%5$uで不正なマジックナンバー%1$04X" -#: xlogreader.c:1258 xlogreader.c:1300 +#: xlogreader.c:1259 xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント %2$s、LSN %3$X/%4$X、オフセット%5$uで不正な情報ビット列%1$04X" -#: xlogreader.c:1274 +#: xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WALファイルは異なるデータベースシステム由来のものです: WALファイルのデータベースシステム識別子は %lluで、pg_control におけるデータベースシステム識別子は %lluです" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WALファイルは異なるデータベースシステム由来のものです: WALファイルのデータベースシステム識別子は %で、pg_control におけるデータベースシステム識別子は %です" -#: xlogreader.c:1282 +#: xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのセグメントサイズが正しくありません" -#: xlogreader.c:1288 +#: xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのXLOG_BLCKSZが正しくありません" -#: xlogreader.c:1320 +#: xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%3$s、LSN %4$X/%5$X、オフセット%6$uで想定外のページアドレス%1$X/%2$X" -#: xlogreader.c:1346 +#: xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "WALセグメント%3$s、LSN %4$X/%5$X、オフセット%6$uで異常な順序のタイムラインID %1$u(%2$uの後)" -#: xlogreader.c:1749 +#: xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %uが%X/%Xで無効です" -#: xlogreader.c:1773 +#: xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATAが設定されていますが、%X/%Xにデータがありません" -#: xlogreader.c:1780 +#: xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATAが設定されていませんが、%2$X/%3$Xのデータ長は%1$u" -#: xlogreader.c:1816 +#: xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEが設定されていますが、%4$X/%5$Xでホールオフセット%1$u、長さ%2$u、ブロックイメージ長%3$u" -#: xlogreader.c:1832 +#: xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEが設定されていませんが、%3$X/%4$Xにホールオフセット%1$u、長さ%2$u" -#: xlogreader.c:1846 +#: xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSEDが設定されていますが、%2$X/%3$Xにおいてブロックイメージ長が%1$uです" -#: xlogreader.c:1861 +#: xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLEもBKPIMAGE_COMPRESSEDも設定されていませんが、%2$X/%3$Xにおいてブロックイメージ長が%1$uです" -#: xlogreader.c:1877 +#: xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_RELが設定されていますが、%X/%Xにおいて以前のリレーションがありません" -#: xlogreader.c:1889 +#: xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "%2$X/%3$Xにおけるblock_id %1$uが無効です" -#: xlogreader.c:1956 +#: xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "%X/%Xのレコードのサイズが無効です" -#: xlogreader.c:1982 +#: xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "WALレコード中のID %dのバックアップブロックを特定できませんでした" -#: xlogreader.c:2066 +#: xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "%X/%Xで不正なブロック%dが指定されているためイメージが復元できませんでした" -#: xlogreader.c:2073 +#: xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "%X/%Xでブロック%dのイメージが不正な状態であるため復元できませんでした" -#: xlogreader.c:2100 xlogreader.c:2117 +#: xlogreader.c:2110 xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "%1$X/%2$Xで、ブロック%4$dがこのビルドでサポートされない圧縮方式%3$sで圧縮されているため復元できませんでした" -#: xlogreader.c:2126 +#: xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "%X/%Xでブロック%dのイメージが不明な方式で圧縮されているため復元できませんでした" -#: xlogreader.c:2134 +#: xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "%X/%Xのブロック%dが伸張できませんでした" diff --git a/src/bin/pg_rewind/po/ka.po b/src/bin/pg_rewind/po/ka.po index e5aff9132a060..5f0c442e81049 100644 --- a/src/bin/pg_rewind/po/ka.po +++ b/src/bin/pg_rewind/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_rewind (PostgreSQL) 17\n" +"Project-Id-Version: pg_rewind (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:23+0000\n" -"PO-Revision-Date: 2024-06-14 06:15+0200\n" +"POT-Creation-Date: 2025-03-29 21:24+0000\n" +"PO-Revision-Date: 2025-03-30 01:31+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,24 +16,24 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " @@ -43,19 +43,19 @@ msgstr "მინიშნება: " msgid "could not open file \"%s\" for reading: %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 -#: local_source.c:163 parsexlog.c:350 +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:102 +#: local_source.c:161 parsexlog.c:371 #, c-format msgid "could not read file \"%s\": %m" msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 #, c-format msgid "could not read file \"%s\": read %d of %zu" msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: local_source.c:121 local_source.c:172 +#: local_source.c:119 local_source.c:170 #, c-format msgid "could not close file \"%s\": %m" msgstr "ფაილის (%s) დახურვის შეცდომა: %m" @@ -76,10 +76,10 @@ msgstr "" "ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" "მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." -#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 -#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 -#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 -#: parsexlog.c:312 +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:69 +#: ../../common/file_utils.c:370 ../../common/file_utils.c:428 +#: ../../common/file_utils.c:502 ../../fe_utils/recovery_gen.c:141 +#: parsexlog.c:333 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" @@ -89,8 +89,8 @@ msgstr "ფაილის (%s) გახსნის შეცდომა: %m" msgid "could not write file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 -#: ../../common/file_utils.c:488 +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:440 +#: ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" @@ -106,34 +106,34 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #: ../../fe_utils/archive.c:86 file_ops.c:417 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 file_ops.c:388 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 file_ops.c:462 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -218,29 +218,34 @@ msgstr "%s არაა საზღვრებში %d-დან %d-მდე msgid "unrecognized sync method: %s" msgstr "უცნობი სინქრონიზაციის მეთოდი: \"%s\"" -#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 -#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 -#: ../../fe_utils/recovery_gen.c:168 +#: ../../fe_utils/recovery_gen.c:40 ../../fe_utils/recovery_gen.c:51 +#: ../../fe_utils/recovery_gen.c:90 ../../fe_utils/recovery_gen.c:110 +#: ../../fe_utils/recovery_gen.c:169 ../../fe_utils/recovery_gen.c:230 #, c-format msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" -#: ../../fe_utils/recovery_gen.c:143 +#: ../../fe_utils/recovery_gen.c:144 #, c-format msgid "could not write to file \"%s\": %m" msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" -#: ../../fe_utils/recovery_gen.c:152 +#: ../../fe_utils/recovery_gen.c:153 #, c-format msgid "could not create file \"%s\": %m" msgstr "ფაილის (%s) შექმნის შეცდომა: %m" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/recovery_gen.c:215 pg_rewind.c:311 +#, c-format +msgid "%s" +msgstr "%s" + +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" @@ -320,177 +325,177 @@ msgstr "%s: სიმბმული ძალიან გრძელია" msgid "could not close directory \"%s\": %m" msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" -#: filemap.c:235 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "წყაროში არსებული მონაცემების ფალი \"%s\" ჩვეულებრივი ფაილი არაა" -#: filemap.c:240 filemap.c:273 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "დუბლირებული საწყისი ფაილი : \"%s\"" -#: filemap.c:328 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "არაჩვეულებრივი ფაილის (%s) გვერდების მოულოდნელი ცვლილება" -#: filemap.c:682 filemap.c:776 +#: filemap.c:743 filemap.c:845 #, c-format msgid "unknown file type for \"%s\"" msgstr "ფაილის უცნობი ტიპი \"%s\"." -#: filemap.c:709 +#: filemap.c:778 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "ფაილი %s წყაროში და სამიზნეში სხვადასხვა ტიპისაა" -#: filemap.c:781 +#: filemap.c:850 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "ვერ გადავწყვიტე, ფაილს რა ვუყო: %s" -#: libpq_source.c:131 +#: libpq_source.c:130 #, c-format msgid "could not clear \"search_path\": %s" msgstr "\"search_path\"-ის გასუფთავების პრობლემა: %s" -#: libpq_source.c:142 +#: libpq_source.c:141 #, c-format msgid "\"full_page_writes\" must be enabled in the source server" msgstr "საწყის სერვერზე \"full_page_writes\"-ის ჩართვა აუცილებელია" -#: libpq_source.c:153 +#: libpq_source.c:152 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "შეცდომა ფაილის შემცველობის გამოსათხოველი ოპერაციების მომზადებისას: %s" -#: libpq_source.c:172 +#: libpq_source.c:171 #, c-format msgid "error running query (%s) on source server: %s" msgstr "შეცდომა სერვერზე (%2$s) მოთხოვნის (%1$s) შესრულებისას" -#: libpq_source.c:177 +#: libpq_source.c:176 #, c-format msgid "unexpected result set from query" msgstr "მოთხოვნის მოულოდნელი სედეგი" -#: libpq_source.c:199 +#: libpq_source.c:198 #, c-format msgid "error running query (%s) in source server: %s" msgstr "შეცდომა სერვერში (%2$s) მოთხოვნის (%1$s) შესრულებისას" -#: libpq_source.c:220 +#: libpq_source.c:219 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "უცნობი პასუხი მიმდინარე WAL ჩასმის მდებარეობისთვის: %s" -#: libpq_source.c:271 +#: libpq_source.c:270 #, c-format msgid "could not fetch file list: %s" msgstr "ფაილების სიის მიღების პრობლემა: %s" -#: libpq_source.c:276 +#: libpq_source.c:275 #, c-format msgid "unexpected result set while fetching file list" msgstr "მოულოდნელი პასუხი ფაილების სიის მიღებისას" -#: libpq_source.c:477 +#: libpq_source.c:476 #, c-format msgid "could not send query: %s" msgstr "მოთხოვნის გაგზავნის პრობლემა: %s" -#: libpq_source.c:480 +#: libpq_source.c:479 #, c-format msgid "could not set libpq connection to single row mode" msgstr "ერთმწკრივიან რეჟიმში libpq შეერთების დაყენება შეუძლებელია" -#: libpq_source.c:510 +#: libpq_source.c:509 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "დაშორებული ფაილების მიღების მოულოდნელი შედეგი: %s" -#: libpq_source.c:515 +#: libpq_source.c:514 #, c-format msgid "received more data chunks than requested" msgstr "მიღებულია მეტი ნაგლეჯი, ვიდრე მოვითხოვე" -#: libpq_source.c:519 +#: libpq_source.c:518 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "ფაილების გამოთხოვისას მიღებული შედეგების სეტის მოულოდნელი ზომა" -#: libpq_source.c:525 +#: libpq_source.c:524 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "მონაცემების მოულოდნელი ტიპები დაშორებული ფაილების გამოთხოვისას შედეგების სეტში: %u %u %u" -#: libpq_source.c:533 +#: libpq_source.c:532 #, c-format msgid "unexpected result format while fetching remote files" msgstr "დაშორებული ფაილების მიღებისას მიღებული ფორმატი მოულოდნელია" -#: libpq_source.c:539 +#: libpq_source.c:538 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "დაშორებული ფაილების მიღების შედეგი მოულოდნელ ნულოვან მნიშვნელობებს შეიცავს" -#: libpq_source.c:543 +#: libpq_source.c:542 #, c-format msgid "unexpected result length while fetching remote files" msgstr "დაშორებული ფაილის მიღებისას მიღებული შედეგის სიგრძე არასწორია" -#: libpq_source.c:576 +#: libpq_source.c:575 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "მიღებულია მონაცემები ფაილისთვის \"%s\", მაშინ, როცა მოვითხოვე \"%s\"" -#: libpq_source.c:580 +#: libpq_source.c:579 #, c-format -msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" -msgstr "მონაცემები მიღებულია წანაცვლებისთვის %lld ფაილში %s მაშინ, როცა მოთხოვნილი იყო წანაცვლებისთვის %lld" +msgid "received data at offset % of file \"%s\", when requested for offset %lld" +msgstr "მონაცემები მიღებულია წანაცვლებისთვის % ფაილში \"%s\" მაშინ, როცა მოთხოვნილი იყო წანაცვლებისთვის %lld" -#: libpq_source.c:592 +#: libpq_source.c:591 #, c-format msgid "received more than requested for file \"%s\"" msgstr "მიღებულია მეტი, ვიდრე მოთხოვნილია ფაილისთვის: %s" -#: libpq_source.c:605 +#: libpq_source.c:604 #, c-format msgid "unexpected number of data chunks received" msgstr "მონაცემების მიღებული ნაწილების რიცხვი არასწორია" -#: libpq_source.c:648 +#: libpq_source.c:647 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "დაშორებული ფაილის (%s) მიღების შეცდომა: %s" -#: libpq_source.c:653 +#: libpq_source.c:652 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "მოულოდნელი პასუხი დაშორებული ფაილის (%s) მიღებისას" -#: local_source.c:90 local_source.c:142 +#: local_source.c:88 local_source.c:140 #, c-format msgid "could not open source file \"%s\": %m" msgstr "წყაროს ფაილის \"%s\" გახსნის შეცდომა: %m" -#: local_source.c:117 +#: local_source.c:115 #, c-format msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "ფაილის (%s) ზომა პარალელურად შეიცვალა: მოველოდი %d ბაიტს. დაკოპირდა %d" -#: local_source.c:146 +#: local_source.c:144 #, c-format msgid "could not seek in source file: %m" msgstr "საწყის ფაილში გადახვევის პრობლემა: %m" -#: local_source.c:165 +#: local_source.c:163 #, c-format msgid "unexpected EOF while reading file \"%s\"" msgstr "მოულოდნელი EOF ფაილის კითხვისას: %s" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "არასაკმარისი მეხსიერება WAL-ის წამკითხავი პროცესორისთვის" @@ -510,22 +515,22 @@ msgstr "შეცდომა WAL ჩანაწერის კითხვი msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "ბოლოს მაჩვენებელი %X/%X არასწორი ბოლოს მაჩვენებელია. მოველოდი %X/%X" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "წინა WAL ჩანაწერის პოვნა შეუძლებელია მისამართზე %X/%X: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "წინა WAL ჩანაწერის პოვნა შეუძლებელია მისამართზე %X/%X" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "ფაილში (%s) გადახვევის პრობლემა: %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "WAL ჩანაწერი ცვლის ურთიერთობას, მაგრამ ჩანაწერის ტიპი უცნობია: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" @@ -702,11 +707,6 @@ msgstr "%s PostgreSQL-ის ზემომხმარებლით უნ msgid "could not read permissions of directory \"%s\": %m" msgstr "საქაღალდის წვდომების წაკითხვა შეუძლებელია \"%s\": %m" -#: pg_rewind.c:311 -#, c-format -msgid "%s" -msgstr "%s" - #: pg_rewind.c:314 #, c-format msgid "connected to server" @@ -727,154 +727,154 @@ msgstr "სერვერი დაშორდა WAL-ს მდებარ msgid "no rewind required" msgstr "გადახვევა საჭირო არაა" -#: pg_rewind.c:460 +#: pg_rewind.c:464 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "გადახვევა ბოლო საერთო საკონტროლო წერტილიდან მისამართზე %X/%X დროის ხაზზე %u" -#: pg_rewind.c:470 +#: pg_rewind.c:474 #, c-format msgid "reading source file list" msgstr "ფაილების წყაროს სიის კითხვა" -#: pg_rewind.c:474 +#: pg_rewind.c:478 #, c-format msgid "reading target file list" msgstr "სამიზნის ფაილების სიის კითხვა" -#: pg_rewind.c:483 +#: pg_rewind.c:487 #, c-format msgid "reading WAL in target" msgstr "სამიზნეში მყოფი WAL-ის კითხვა" -#: pg_rewind.c:504 +#: pg_rewind.c:508 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "საჭიროა %lu მბ-ის კოპირება (საწყის საქაღალდის სრული ზომაა %lu მბ)" -#: pg_rewind.c:522 +#: pg_rewind.c:526 #, c-format msgid "syncing target data directory" msgstr "მონაცემების სამიზე საქაღალდის სინქრონიზაცია" -#: pg_rewind.c:538 +#: pg_rewind.c:543 #, c-format msgid "Done!" msgstr "შესრულებულია!" -#: pg_rewind.c:618 +#: pg_rewind.c:623 #, c-format msgid "no action decided for file \"%s\"" msgstr "ფაილისთვის %s ქმედება არჩეული არაა" -#: pg_rewind.c:650 +#: pg_rewind.c:655 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "საწყისი ფაილი შეიცვალა, სანამ pg_rewind იყო გაშვებული" -#: pg_rewind.c:654 +#: pg_rewind.c:659 #, c-format msgid "creating backup label and updating control file" msgstr "მარქაფის ჭდის შექმნა და საკონტროლო ფაილის განახლება" -#: pg_rewind.c:704 +#: pg_rewind.c:709 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "საწყისი სისტემა გადახვევისას გაურკვეველ მდგომარეობაში აღმოჩნდა" -#: pg_rewind.c:736 +#: pg_rewind.c:741 #, c-format msgid "source and target clusters are from different systems" msgstr "საწყისი და სამიზნე კლასტერები სხვადასახვა სისტემებიდანაა" -#: pg_rewind.c:744 +#: pg_rewind.c:749 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "კლასტერები pg_rewind-ის ამ ვერსიასთან შეუთავსებელია" -#: pg_rewind.c:754 +#: pg_rewind.c:759 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "სამზნე სერვერზე საჭიროა ან მონაცემების საკონტროლო ჯამების გამოყენება, ან \"wal_log_hints = on\"" -#: pg_rewind.c:765 +#: pg_rewind.c:770 #, c-format msgid "target server must be shut down cleanly" msgstr "სამიზნე ბაზა წესების დაცვით უნდა იყოს გამორთული" -#: pg_rewind.c:775 +#: pg_rewind.c:780 #, c-format msgid "source data directory must be shut down cleanly" msgstr "საწყისი ბაზა წესების დაცვით უნდა იყოს გამორთული" -#: pg_rewind.c:822 +#: pg_rewind.c:827 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s კბ (%d%%) დაკოპირდა" -#: pg_rewind.c:950 +#: pg_rewind.c:953 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "საწყისი და სამიზნე კლასტერების დროის ხაზის საერთო წინაპრის პოვნა შეუძლებელია" -#: pg_rewind.c:991 +#: pg_rewind.c:994 #, c-format msgid "backup label buffer too small" msgstr "მარქაფის ჭდის ბაფერი ძალიან პატარაა" -#: pg_rewind.c:1014 +#: pg_rewind.c:1017 #, c-format msgid "unexpected control file CRC" msgstr "კონტროლის ფაილის მოულოდნელი CRC" -#: pg_rewind.c:1026 +#: pg_rewind.c:1029 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "საკონტროლო ფაილის არასწორი სიგრძე: %d. უნდა იყოს: %d" -#: pg_rewind.c:1036 +#: pg_rewind.c:1039 #, c-format msgid "invalid WAL segment size in control file (%d byte)" msgid_plural "invalid WAL segment size in control file (%d bytes)" msgstr[0] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" msgstr[1] "არასწორი WAL სეგმენტის ზომა კონტროლის ფაილში (%d ბაიტი)" -#: pg_rewind.c:1040 +#: pg_rewind.c:1043 #, c-format msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." msgstr "WAL სეგმენტის ზომა ორის ხარისხი უნდა იყოს, შუალედიდან 1მბ-1გბ." -#: pg_rewind.c:1077 pg_rewind.c:1145 +#: pg_rewind.c:1080 pg_rewind.c:1148 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა" -#: pg_rewind.c:1080 pg_rewind.c:1148 +#: pg_rewind.c:1083 pg_rewind.c:1151 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s" -#: pg_rewind.c:1109 +#: pg_rewind.c:1112 #, c-format -msgid "unable to read restore_command from target cluster" -msgstr "სამიზნე კლასტერიდან restore_command-ის წაკითხვა შეუძლებელია" +msgid "could not read \"restore_command\" from target cluster" +msgstr "სამიზნე კლასტერიდან \"restore_command\"-ის წაკითხვა შეუძლებელია" -#: pg_rewind.c:1114 +#: pg_rewind.c:1117 #, c-format msgid "\"restore_command\" is not set in the target cluster" msgstr "სამიზნე კლასტერში \"restore_command\" დაყენებული არაა" -#: pg_rewind.c:1152 +#: pg_rewind.c:1155 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "ავარიიდან სრულად აღდგენისთვის სამიზნე სერვერზე %s-ის შესრულდება" -#: pg_rewind.c:1190 +#: pg_rewind.c:1193 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "სამიზნე კლასტერში postgres-ის ერთმომხმარებლიანი რეჟიმის შეცდომა" -#: pg_rewind.c:1191 +#: pg_rewind.c:1194 #, c-format msgid "Command was: %s" msgstr "ბრძანება იყო: %s" @@ -914,157 +914,157 @@ msgstr "არასწორი მონაცემები ისტორ msgid "Timeline IDs must be less than child timeline's ID." msgstr "დროის ხაზის ID-ები შვილეული დროის ხაზის ID-ზე ნაკლები უნდა იყოს." -#: xlogreader.c:619 +#: xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი წანაცვლება მისამართზე %X/%X: მინდოდა %u, მივიღე %u" -#: xlogreader.c:628 +#: xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord მოთხოვნილია %X/%X-ის მიერ" -#: xlogreader.c:669 xlogreader.c:1134 +#: xlogreader.c:670 xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი სიგრძე მისამართზე %X/%X: მოველოდი მინიმუმ %u, მივიღე %u" -#: xlogreader.c:758 +#: xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "contrecord ალამი მისამართზე %X/%X არ არსებობს" -#: xlogreader.c:771 +#: xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "contrecord -ის არასწორი სიგრძე %u (მოველოდი %lld) მისამართზე %X/%X" -#: xlogreader.c:1142 +#: xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "რესურსის მმართველის არასწორი ID %u მისამართზე %X/%X" -#: xlogreader.c:1155 xlogreader.c:1171 +#: xlogreader.c:1156 xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "ჩანაწერი არასწორი წინა ბმულით %X/%X მისამართზე %X/%X" -#: xlogreader.c:1209 +#: xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "რესურსის მმართველის მონაცემების არასწორი საკონტროლო რიცხვი ჩანაწერში მისამართზე %X/%X" -#: xlogreader.c:1243 +#: xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი მაგიური რიცხვი %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1258 xlogreader.c:1300 +#: xlogreader.c:1259 xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი საინფორმაციო ბიტები %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1274 +#: xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WAL ფაილი სხვა ბაზიდანაა: WAL ფაილის ბაზის იდენტიფიკატორია %llu, pg_control-ის ბაზის სისტემის იდენტიფიკატორი კი %llu" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WAL ფაილი სხვა ბაზიდანაა: WAL ფაილის ბაზის იდენტიფიკატორია %, pg_control-ის ბაზის სისტემის იდენტიფიკატორი კი %" -#: xlogreader.c:1282 +#: xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL ფაილი სხვა ბაზის სიტემიდანაა: სეგმანტის არასწორი ზომა გვერდის თავსართში" -#: xlogreader.c:1288 +#: xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: გვერდის თავსართში მითითებული XLOG_BLKSZ არასწორია" -#: xlogreader.c:1320 +#: xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "მოულოდნელი pageaddr %X/%X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1346 +#: xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "მიმდევრობის-გარე დროის ხაზის ID %u (%u-ის შემდეგ) ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1749 +#: xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ურიგო block_id %u მისამართზე %X/%X" -#: xlogreader.c:1773 +#: xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ მონაცემები მისამართზე %X/%X არ არსებობს" -#: xlogreader.c:1780 +#: xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ არსებობს მონაცემები სიგრძით %u მისამართზე %X/%X" -#: xlogreader.c:1816 +#: xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებულია, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u ბლოკის ასლის სიგრძე %u მისამართზე %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებული არაა, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u მისანართზე %X/%X" -#: xlogreader.c:1846 +#: xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED დაყენებულია, მაგრამ ბლოკის ასლის სიგრძეა %u მისამართზე %X/%X" -#: xlogreader.c:1861 +#: xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "არც BKPIMAGE_HAS_HOLE და არც BKPIMAGE_COMPRESSED დაყენებული არაა, მაგრამ ბლოკის ასლის სიგრძე %u-ა, მისამართზე %X/%X" -#: xlogreader.c:1877 +#: xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL დაყენებულია, მაგრამ წინა მნიშვნელობა მითითებული არაა მისამართზე %X/%X" -#: xlogreader.c:1889 +#: xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "არასწორი block_id %u %X/%X" -#: xlogreader.c:1956 +#: xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "ჩანაწერი არასწორი სიგრძით მისამართზე %X/%X" -#: xlogreader.c:1982 +#: xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "შეცდომა WAL ჩანაწერში მარქაფი ბლოკის, ID-ით %d, მოძებნისას" -#: xlogreader.c:2066 +#: xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X, როცა მითითებულია არასწორი ბლოკი %d" -#: xlogreader.c:2073 +#: xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X არასწორი მდგომარეობით, ბლოკი %d" -#: xlogreader.c:2100 xlogreader.c:2117 +#: xlogreader.c:2110 xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "%3$s მეთოდით შეკუმშული ასლის აღდგენა მისამართზე %1$X/%2$X, ბლოკი %4$d შეუძლებელია. მხარდაუჭერელია ამ აგების მიერ" -#: xlogreader.c:2126 +#: xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X, შეკუმშულია უცნობი მეთოდით, ბლოკი %d" -#: xlogreader.c:2134 +#: xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "შეუძლებელია ასლის გაშლა მისამართზე %X/%X, ბლოკი %d" diff --git a/src/bin/pg_rewind/po/ko.po b/src/bin/pg_rewind/po/ko.po index 4ca7e7106f81b..459bbd714014e 100644 --- a/src/bin/pg_rewind/po/ko.po +++ b/src/bin/pg_rewind/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_rewind (PostgreSQL) 16\n" +"Project-Id-Version: pg_rewind (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:52+0000\n" -"PO-Revision-Date: 2023-05-26 13:21+0900\n" +"POT-Creation-Date: 2025-01-17 04:53+0000\n" +"PO-Revision-Date: 2025-01-16 16:58+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -37,6 +37,66 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:371 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "\"%s\" 파일을 닫을 수 없음: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "바이트 순서 불일치" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"바이트 순서 일치하지 않는 문제\n" +"바이트 순서 정보는 pg_control 파일을 저장할 때 사용되는데,\n" +"이 파일의 바이트 순서 정보와 이 프로그램에서 사용하는 순서 정보가 다릅니다.\n" +"이럴 경우, 출력 결과가 바르지 않을 수 있고,\n" +"설치된 PostgreSQL 프로그램과 데이터 디렉터리가 호환되지 않을 수 있습니다." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:333 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "\"%s\" 파일 쓰기 실패: %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,6 +108,38 @@ msgstr "메모리 부족\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 복제할 수 없음(내부 오류)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위한 파일 시스템 동기화 실패: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -103,43 +195,58 @@ msgstr "\"%s\" 파일 크기가 이상함: %lld 로 비정상, 정상값 %lld" msgid "could not open file \"%s\" restored from archive: %m" msgstr "아카이브에서 \"%s\" 파일 복원 실패: %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "restore_command 실패: %s" +msgid "\"restore_command\" failed: %s" +msgstr "\"restore_command\" 실패: %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "아카이브에서 \"%s\" 파일 복원 실패" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "메모리 부족" +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값이 잘못됨, 해당 옵션: %s" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" +msgid "%s must be in range %d..%d" +msgstr "%s 값은 %d..%d 범위 안에 있어야 함" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "메모리 부족" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "\"%s\" 파일 쓰기 실패: %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "\"%s\" 파일을 만들 수 없음: %m" +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -155,11 +262,6 @@ msgstr "\"%s\" 대상 파일을 닫을 수 없음: %m" msgid "could not seek in target file \"%s\": %m" msgstr "\"%s\" 대상 파일에서 seek 작업을 할 수 없음: %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "\"%s\" 파일 쓰기 실패: %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -205,26 +307,6 @@ msgstr "\"%s\"에 대한 심볼릭 링크를 만들 수 없음: %m" msgid "could not remove symbolic link \"%s\": %m" msgstr "\"%s\" 심벌릭 링크를 삭제할 수 없음: %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "\"%s\" 파일을 읽을 수 없음: %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "\"%s\" 디렉터리 열 수 없음: %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -235,165 +317,160 @@ msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m" msgid "symbolic link \"%s\" target is too long" msgstr "\"%s\" 심볼릭 링크의 대상이 너무 긺" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m" -#: filemap.c:236 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "\"%s\" 자료 파일은 일반 파일이 아님" -#: filemap.c:241 filemap.c:274 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "\"%s\" 소스 파일을 두 번 지정했습니다" -#: filemap.c:329 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "\"%s\" 비일반 파일의 페이지 변경 정보가 잘못됨" -#: filemap.c:679 filemap.c:773 +#: filemap.c:744 filemap.c:846 #, c-format msgid "unknown file type for \"%s\"" msgstr "\"%s\" 파일 형식을 알 수 없음" -#: filemap.c:706 +#: filemap.c:779 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "\"%s\" 파일 형식이 소스와 타켓이 서로 다름" -#: filemap.c:778 +#: filemap.c:851 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "\"%s\" 파일로 뭘 해야할지 결정할 수 없음" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "search_path를 지울 수 없음: %s" +msgid "could not clear \"search_path\": %s" +msgstr "\"search_path\"를 지울 수 없음: %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "원본 서버는 full_page_writes 옵션으로 운영되어야 함" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "원본 서버는 \"full_page_writes\" 옵션으로 운영되어야 함" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "파일 내용을 뽑기 위한 구문을 준비할 수 없음: %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "원본 서버에서 쿼리 (%s) 실행 오류: %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "쿼리 결과가 바르지 않음" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "원본에서에서 쿼리(%s) 실행 오류: %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "현재 WAL 삽입 위치를 위한 결과가 잘못됨 : \"%s\"" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "파일 목록을 가져올 수 없음: %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "파일 목록을 가져온 결과가 잘못 됨" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "쿼리를 보낼 수 없음: %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "libpq 연결을 단일 로우 모드로 지정할 수 없음" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "원격 파일을 가져오는 도중 결과가 잘못됨: %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "용천 된 것보다 많은 데이터 청크를 받았음" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "원격 파일을 가져오는 도중 결과 집합의 크기가 잘못 됨" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "" "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "원격 파일을 가져오는 도중 결과 집합의 자료형이 잘못 됨: %u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "원격 파일을 가져오는 중 예상치 못한 결과 형식 발견" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "원격 파일을 가져오는 도중 결과안에 null 값이 잘못됨" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "원격 파일을 가져오는 도중 결과 길이가 잘못됨" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "\"%s\" 파일용 데이터를 받았음, \"%s\" 요청 처리용" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "" "received data at offset %lld of file \"%s\", when requested for offset %lld" msgstr "" "%lld 오프셋(해당파일: \"%s\")에 데이터를 받았음, %lld 오프셋 요청 처리용" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "\"%s\" 파일을 위한 보다 많은 요청을 받았음" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "데이터 청크 수신 숫자가 이상함" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "\"%s\" 원격 파일을 가져올 수 없음: %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "\"%s\" 원격파일을 가져오는 도중 결과 집합이 잘못 됨" @@ -409,11 +486,6 @@ msgid "" "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "\"%s\" 소스 파일 크기가 현재 변경 되었음: 기대값: %d, 실재값 %d" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "\"%s\" 파일을 닫을 수 없음: %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -424,7 +496,7 @@ msgstr "원본 파일에서 seek 작업을 할 수 없음: %m" msgid "unexpected EOF while reading file \"%s\"" msgstr "\"%s\" 파일을 읽는 중 예상치 못한 EOF" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "WAL 읽기 프로세서를 할당하는 중 메모리 부족" @@ -444,22 +516,22 @@ msgstr "%X/%X 위치에서 WAL 레코드를 읽을 수 없음" msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "%X/%X 끝 포인터는 바른값이 아님; 기대값: %X/%X" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "%X/%X 위치에서 이전 WAL 레코드를 찾을 수 없음: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "%X/%X 위치에서 이전 WAL 레코드를 찾을 수 없음" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "\"%s\" 파일에서 seek 작업을 할 수 없음: %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "" "WAL record modifies a relation, but record type is not recognized: lsn: %X/" @@ -468,7 +540,7 @@ msgstr "" "WAL 레코드가 릴레이션을 변경하려고 하지만, 레코드 형태가 바르지 않음: lsn: " "%X/%X, rmid: %d, rmgr: %s, info: %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "" "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n" @@ -478,7 +550,7 @@ msgstr "" "니다.\n" "\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "" "Usage:\n" @@ -489,43 +561,43 @@ msgstr "" " %s [옵션]...\n" "\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "옵션들:\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format msgid "" -" -c, --restore-target-wal use restore_command in target configuration " -"to\n" +" -c, --restore-target-wal use \"restore_command\" in target " +"configuration to\n" " retrieve WAL files from archives\n" msgstr "" " -c, --restore-target-wal 아카이브에서 WAL 파일을 가져오기 위해\n" -" 대상 환경 설정 restore_command 사용\n" +" 대상 환경 설정 \"restore_command\" 사용\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr " -D, --target-pgdata=디렉터리 변경하려는 데이터 디렉터리\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid "" " --source-pgdata=DIRECTORY source data directory to synchronize with\n" msgstr " --source-pgdata=디렉터리 동기화 원본이 되는 데이터 디렉터리\n" -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr " --source-server=연결문자열 원본 서버 접속 정보\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr " -n, --dry-run 변경 작업 전에 멈춤(검사, 확인용)\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written\n" @@ -534,12 +606,12 @@ msgstr "" " -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않" "음\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress 진행 과정 메시지를 보여줌\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid "" " -R, --write-recovery-conf write configuration for replication\n" @@ -548,7 +620,7 @@ msgstr "" " -R, --write-recovery-conf 복제를 위한 환경 설정 함\n" " (--source-server 설정 필요함)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -557,30 +629,36 @@ msgstr "" " --config-file=파일이름 대상 클러스터를 실행할 때 사용할\n" " 서버 환경 설정 파일 지정\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr " --debug 디버그 메시지를 보여줌\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid "" " --no-ensure-shutdown do not automatically fix unclean shutdown\n" msgstr "" " --no-ensure-shutdown 비정상 종료 시 자동 뒷정리 작업 안함\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr "" +" --sync-method=METHOD 파일을 디스크에 동기화 하는 방법 지정\n" + +#: pg_rewind.c:113 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "" "\n" @@ -589,152 +667,152 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "" "원본을 지정하지 않았음 (--source-pgdata 또는 --source-server 옵션을 지정 해" "야 함)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "--source-pgdata 또는 --source-server 옵션 중 하나만 지정해야 함" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "대상 데이터 디렉토리가 지정되지 않았음 (--target-pgdata 옵션 사용)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "" "no source server information (--source-server) specified for --write-" "recovery-conf" msgstr "--write-recovery-conf 용 원보 서버 정보(--source-server) 없음" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인수를 지정했습니다. (처음 \"%s\")" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\" 계정으로는 실행 할 수 없음" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "PostgreSQL superuser로 %s 프로그램을 실행하십시오." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "\"%s\" 디렉터리 읽기 권한 없음: %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "서버 접속 완료" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "원본과 대상 클러스터의 타임라인이 같음" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "서버 분기 WAL 위치: %X/%X, 타임라인 %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "되감을 필요 없음" -#: pg_rewind.c:451 +#: pg_rewind.c:463 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "재동기화 시작함, 마지막 체크포인트 위치 %X/%X, 타임라인 %u" -#: pg_rewind.c:461 +#: pg_rewind.c:473 #, c-format msgid "reading source file list" msgstr "원본 파일 목록 읽는 중" -#: pg_rewind.c:465 +#: pg_rewind.c:477 #, c-format msgid "reading target file list" msgstr "대상 파일 목록 읽는 중" -#: pg_rewind.c:474 +#: pg_rewind.c:486 #, c-format msgid "reading WAL in target" msgstr "대상 서버에서 WAL 읽는 중" -#: pg_rewind.c:495 +#: pg_rewind.c:507 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "복사를 위해서 %lu MB 필요함 (원본 디렉토리 전체 크기는 %lu MB)" -#: pg_rewind.c:513 +#: pg_rewind.c:525 #, c-format msgid "syncing target data directory" msgstr "대상 데이터 디렉터리 동기화 중" -#: pg_rewind.c:529 +#: pg_rewind.c:541 #, c-format msgid "Done!" msgstr "완료!" -#: pg_rewind.c:609 +#: pg_rewind.c:621 #, c-format msgid "no action decided for file \"%s\"" msgstr "%s 외부 테이블 접근 권한 없음" -#: pg_rewind.c:641 +#: pg_rewind.c:653 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "pg_rewind 실행 되고 있는 중에 원본 시스템이 변경 되었음" -#: pg_rewind.c:645 +#: pg_rewind.c:657 #, c-format msgid "creating backup label and updating control file" msgstr "백업 라벨을 만들고, 컨트롤 파일을 갱신 중" -#: pg_rewind.c:695 +#: pg_rewind.c:707 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "rewind 끝에 원본 시스템의 상태가 예상값과 다름" -#: pg_rewind.c:727 +#: pg_rewind.c:739 #, c-format msgid "source and target clusters are from different systems" msgstr "원본과 대상 클러스터가 서로 다른 시스템임" -#: pg_rewind.c:735 +#: pg_rewind.c:747 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "해당 클러스터는 이 pg_rewind 버전으로 작업할 수 없음" -#: pg_rewind.c:745 +#: pg_rewind.c:757 #, c-format msgid "" "target server needs to use either data checksums or \"wal_log_hints = on\"" @@ -742,55 +820,54 @@ msgstr "" "대상 서버의 데이터 클러스터가 데이터 체크섬 기능을 켰거나, \"wal_log_hints " "= on\" 설정이 되어야 함" -#: pg_rewind.c:756 +#: pg_rewind.c:768 #, c-format msgid "target server must be shut down cleanly" msgstr "대상 서버는 정상 종료되어야 함" -#: pg_rewind.c:766 +#: pg_rewind.c:778 #, c-format msgid "source data directory must be shut down cleanly" msgstr "원본 데이터 디렉토리는 정상적으로 종료되어야 함" -#: pg_rewind.c:813 +#: pg_rewind.c:825 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s kB (%d%%) 복사됨" -#: pg_rewind.c:941 +#: pg_rewind.c:951 #, c-format msgid "" "could not find common ancestor of the source and target cluster's timelines" msgstr "원본과 대상 서버의 공통된 상위 타임라인을 찾을 수 없음" -#: pg_rewind.c:982 +#: pg_rewind.c:992 #, c-format msgid "backup label buffer too small" msgstr "백업 라벨 버퍼가 너무 작음" -#: pg_rewind.c:1005 +#: pg_rewind.c:1015 #, c-format msgid "unexpected control file CRC" msgstr "컨트롤 파일 CRC 오류" -#: pg_rewind.c:1017 +#: pg_rewind.c:1027 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "컨트롤 파일의 크기가 %d 로 비정상, 정상값 %d" -#: pg_rewind.c:1026 +#: pg_rewind.c:1037 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d bytes" -msgstr[0] "" -"WAL 조각 파일은 1MB부터 1GB 사이 2^n 크기여야 하지만, 컨트롤 파일에는 %d 바이" -"트로 지정되었음" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "컨트롤 파일 안에 잘못된 WAL 조각 크기 (%d 바이트)" + +#: pg_rewind.c:1041 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL 조각 파일은 1MB부터 1GB 사이 2^n 크기여야 함" -#: pg_rewind.c:1065 pg_rewind.c:1135 +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " @@ -799,129 +876,124 @@ msgstr "" "\"%s\" 프로그램이 %s 작업에서 필요합니다. 그런데, 이 파일이 \"%s\" 파일이 있" "는 디렉터리안에 없습니다." -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1081 pg_rewind.c:1149 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "\"%s\" 프로그램을 \"%s\" 작업 때문에 찾았지만 이 파일은 %s 프로그램의 버전과 " "다릅니다." -#: pg_rewind.c:1101 +#: pg_rewind.c:1110 +#, c-format +msgid "could not read restore_command from target cluster" +msgstr "대상 클러스터에 restore_command 설정을 읽을 수 없음" + +#: pg_rewind.c:1115 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "대상 클러스터에 restore_command 설정이 없음" +msgid "\"restore_command\" is not set in the target cluster" +msgstr "대상 클러스터에 \"restore_command\" 설정이 없음" -#: pg_rewind.c:1142 +#: pg_rewind.c:1153 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "대상 서버에서 비정상 종료 후 복구 작업을 위해 \"%s\" 실행 중" -#: pg_rewind.c:1180 +#: pg_rewind.c:1191 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "대상 클러스터를 단일 사용자 모드로 postgres 실행 실패" -#: pg_rewind.c:1181 +#: pg_rewind.c:1192 #, c-format msgid "Command was: %s" msgstr "사용된 명령: %s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "히스토리 파일에서 문법오류: %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "숫자 타임라인 ID가 필요합니다." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "트랜잭션 로그 전환 위치 값이 있어야 함" -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "작업내역 파일에 잘못된 자료가 있음: %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "타임라인 ID 값은 그 값이 증가하는 순번값이어야합니다." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "내역 파일에 잘못된 자료가 있음" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "타임라인 ID는 하위 타임라인 ID보다 작아야 합니다." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 오프셋:위치 %X/%X, 기대값 %u, 실재값 %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "%X/%X에서 contrecord를 필요로 함" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 길이:위치 %X/%X, 기대값 %u, 실재값 %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "%u 길이의 레코드를 디코딩 하는 중 메모리 부족" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "%X/%X 위치에 contrecord 플래그가 없음" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "잘못된 contrecord 길이 %u (기대값: %lld), 위치 %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "잘못된 자원 관리 ID %u, 위치: %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "레코드의 잘못된 프리링크 %X/%X, 해당 레코드 %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "잘못된 자원관리자 데이터 체크섬, 위치: %X/%X 레코드" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "%04X 매직 번호가 잘못됨, WAL 조각파일: %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 정보 비트 %04X, WAL 조각파일: %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -930,7 +1002,7 @@ msgstr "" "WAL 파일이 다른 시스템의 것입니다. WAL 파일의 시스템 식별자는 %llu, " "pg_control 의 식별자는 %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -939,7 +1011,7 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더에 지정된 값이 잘" "못된 조각 크기임" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -948,12 +1020,12 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_BLCKSZ 값" "이 바르지 않음" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 페이지 주소 %X/%X, WAL 조각파일: %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -962,22 +1034,22 @@ msgstr "" "타임라인 범위 벗어남 %u (이전 번호 %u), WAL 조각파일: %s, LSN %X/%X, 오프셋 " "%u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "%u block_id는 범위를 벗어남, 위치 %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정했지만, %X/%X 에 자료가 없음" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정 않았지만, %u 길이의 자료가 있음, 위치 %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -986,19 +1058,19 @@ msgstr "" "BKPIMAGE_HAS_HOLE 설정이 되어 있지만, 옵셋: %u, 길이: %u, 블록 이미지 길이: " "%u, 대상: %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE 설정이 안되어 있지만, 옵셋: %u, 길이: %u, 대상: %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED 설정이 되어 있지만, 블록 이미지 길이: %u, 대상: %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -1007,37 +1079,37 @@ msgstr "" "BKPIMAGE_HAS_HOLE, BKPIMAGE_COMPRESSED 지정 안되어 있으나, 블록 이미지 길이" "는 %u, 대상: %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL 설정이 되어 있지만, %X/%X 에 이전 릴레이션 없음" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "잘못된 block_id %u, 위치 %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "잘못된 레코드 길이, 위치 %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "WAL 레코드에 %d ID 백업 블록이 없음" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "%X/%X 위치에 이미지 복원 실패(%d 블록이 바르지 않음)" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "%X/%X 에 잘못된 상태값으로 이미지 복원 실패, 블록 %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " @@ -1046,13 +1118,13 @@ msgstr "" "%X/%X 위치에 %s 압축된 이미지 복원 실패, 해당 엔진이 지원하지 않음, 해당블" "록: %d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "%X/%X 위치에 알수 없는 압축 방식의 이미지 복원 실패, 해당블록: %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "%X/%X 에서 이미 압축 풀기 실패, 블록 %d" @@ -1060,3 +1132,11 @@ msgstr "%X/%X 에서 이미 압축 풀기 실패, 블록 %d" #, c-format #~ msgid "missing contrecord at %X/%X" #~ msgstr "%X/%X 위치에 contrecord 없음" + +#, c-format +#~ msgid "out of memory while trying to decode a record of length %u" +#~ msgstr "%u 길이의 레코드를 디코딩 하는 중 메모리 부족" + +#, c-format +#~ msgid "record length %u at %X/%X too long" +#~ msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음" diff --git a/src/bin/pg_rewind/po/meson.build b/src/bin/pg_rewind/po/meson.build index 152f1caeb60e4..6ff9790289423 100644 --- a/src/bin/pg_rewind/po/meson.build +++ b/src/bin/pg_rewind/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_rewind-' + pg_version_major.to_string())] diff --git a/src/bin/pg_rewind/po/ru.po b/src/bin/pg_rewind/po/ru.po index 8a705d2d1f076..6f3d63dec583b 100644 --- a/src/bin/pg_rewind/po/ru.po +++ b/src/bin/pg_rewind/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for pg_rewind # Copyright (C) 2015-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2015-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2015-2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_rewind (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2023-08-30 15:22+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-07 13:07+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -37,6 +37,65 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:371 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:373 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "не удалось закрыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "несоответствие порядка байт" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, " +"and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"возможно несоответствие порядка байт\n" +"Порядок байт в файле pg_control может не соответствовать используемому\n" +"этой программой. В этом случае результаты будут неверными и\n" +"установленный PostgreSQL будет несовместим с этим каталогом данных." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:333 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не удалось записать файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,6 +107,38 @@ msgstr "нехватка памяти\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -103,43 +194,61 @@ msgstr "неподходящий размер файла \"%s\": %lld вмест msgid "could not open file \"%s\" restored from archive: %m" msgstr "не удалось открыть файл \"%s\", восстановленный из архива: %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "не удалось получить информацию о файле \"%s\": %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "ошибка при выполнении restore_command: %s" +msgid "\"restore_command\" failed: %s" +msgstr "ошибка при выполнении \"restore_command\": %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "восстановить файл \"%s\" из архива не удалось" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "нехватка памяти" +msgid "invalid value \"%s\" for option %s" +msgstr "неверное значение \"%s\" для параметра %s" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" +msgid "%s must be in range %d..%d" +msgstr "значение %s должно быть в диапазоне %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "нехватка памяти" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "не удалось записать в файл \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "не удалось создать файл \"%s\": %m" +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -155,11 +264,6 @@ msgstr "не удалось закрыть целевой файл \"%s\": %m" msgid "could not seek in target file \"%s\": %m" msgstr "не удалось переместиться в целевом файле \"%s\": %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "не удалось записать файл \"%s\": %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -205,26 +309,6 @@ msgstr "не удалось создать символическую ссылк msgid "could not remove symbolic link \"%s\": %m" msgstr "ошибка при удалении символической ссылки \"%s\": %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "не удалось открыть файл \"%s\" для чтения: %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не удалось прочитать файл \"%s\": %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не удалось открыть каталог \"%s\": %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -235,118 +319,113 @@ msgstr "не удалось прочитать символическую ссы msgid "symbolic link \"%s\" target is too long" msgstr "целевой путь символической ссылки \"%s\" слишком длинный" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не удалось прочитать каталог \"%s\": %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не удалось закрыть каталог \"%s\": %m" -#: filemap.c:236 +#: filemap.c:297 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "файл данных \"%s\" в источнике не является обычным файлом" -#: filemap.c:241 filemap.c:274 +#: filemap.c:302 filemap.c:335 #, c-format msgid "duplicate source file \"%s\"" msgstr "повторный исходный файл \"%s\"" -#: filemap.c:329 +#: filemap.c:390 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "неожиданная модификация страницы для файла особого вида \"%s\"" -#: filemap.c:683 filemap.c:777 +#: filemap.c:744 filemap.c:846 #, c-format msgid "unknown file type for \"%s\"" msgstr "неизвестный тип файла \"%s\"" -#: filemap.c:710 +#: filemap.c:779 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "файл \"%s\" имеет разный тип в исходном и целевом кластере" -#: filemap.c:782 +#: filemap.c:851 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "не удалось определить, что делать с файлом \"%s\"" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "не удалось очистить search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "не удалось очистить \"search_path\": %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "на исходном сервере должен быть включён режим full_page_writes" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "на исходном сервере должен быть включён режим \"full_page_writes\"" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "не удалось подготовить оператор для извлечения содержимого файла: %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "ошибка выполнения запроса (%s) на исходном сервере: %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "неожиданный результат запроса" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "ошибка выполнения запроса (%s) на исходном сервере: %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "" "нераспознанный результат \"%s\" вместо текущей позиции добавления в WAL" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "не удалось получить список файлов: %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "неожиданный результат при получении списка файлов" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "не удалось отправить запрос: %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "не удалось перевести подключение libpq в однострочный режим" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "неожиданный результат при получении файлов с сервера: %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "получено больше сегментов данных, чем запрошено" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "неожиданный размер набора результатов при получении файлов с сервера" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "" "unexpected data types in result set while fetching remote files: %u %u %u" @@ -354,27 +433,27 @@ msgstr "" "неожиданные типы данных в наборе результатов при получении файлов с сервера: " "%u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "неожиданный формат результата при получении файлов с сервера" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "неожиданные значения NULL в результате при получении файлов с сервера" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "неожиданная длина результата при получении файлов с сервера" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "получены данные для файла \"%s\", а запрашивались данные для \"%s\"" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "" "received data at offset %lld of file \"%s\", when requested for offset %lld" @@ -382,22 +461,22 @@ msgstr "" "получены данные по смещению %lld в файле \"%s\", а запрашивались по смещению " "%lld" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "получено больше данных, чем запрошено для файла \"%s\"" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "получено неожиданное количество сегментов данных" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "не удалось получить с сервера файл \"%s\": %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "неожиданный набор результатов при получении файла \"%s\" с сервера" @@ -414,11 +493,6 @@ msgid "" msgstr "" "размер исходного файла \"%s\" изменился, ожидалось байт: %d, скопировано: %d" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "не удалось закрыть файл \"%s\": %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -429,7 +503,7 @@ msgstr "не удалось переместиться в исходном фа msgid "unexpected EOF while reading file \"%s\"" msgstr "неожиданный конец файла при чтении \"%s\"" -#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:199 +#: parsexlog.c:80 parsexlog.c:139 parsexlog.c:201 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "не удалось выделить память для чтения WAL" @@ -450,22 +524,22 @@ msgid "end pointer %X/%X is not a valid end point; expected %X/%X" msgstr "" "конечный указатель %X/%X неверно задаёт конечную точку; ожидается %X/%X" -#: parsexlog.c:212 +#: parsexlog.c:214 #, c-format msgid "could not find previous WAL record at %X/%X: %s" msgstr "не удалось найти предыдущую запись WAL в позиции %X/%X: %s" -#: parsexlog.c:216 +#: parsexlog.c:218 #, c-format msgid "could not find previous WAL record at %X/%X" msgstr "не удалось найти предыдущую запись WAL в позиции %X/%X" -#: parsexlog.c:341 +#: parsexlog.c:362 #, c-format msgid "could not seek in file \"%s\": %m" msgstr "не удалось переместиться в файле \"%s\": %m" -#: parsexlog.c:440 +#: parsexlog.c:461 #, c-format msgid "" "WAL record modifies a relation, but record type is not recognized: lsn: %X/" @@ -474,7 +548,7 @@ msgstr "" "Запись WAL модифицирует отношение, но тип записи не распознан: lsn: %X/%X, " "rmid: %d, rmgr: %s, info: %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "" "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n" @@ -483,7 +557,7 @@ msgstr "" "%s синхронизирует кластер PostgreSQL с другой копией кластера.\n" "\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "" "Usage:\n" @@ -494,30 +568,31 @@ msgstr "" " %s [ПАРАМЕТР]...\n" "\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "Параметры:\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format msgid "" -" -c, --restore-target-wal use restore_command in target configuration " -"to\n" +" -c, --restore-target-wal use \"restore_command\" in target " +"configuration to\n" " retrieve WAL files from archives\n" msgstr "" " -c, --restore-target-wal использовать для получения файлов WAL из\n" -" архива команду restore_command из целевой\n" +" архивов команду \"restore_command\" из " +"целевой\n" " конфигурации\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr "" " -D, --target-pgdata=КАТАЛОГ существующий каталог, куда будут записаны " "данные\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid "" " --source-pgdata=DIRECTORY source data directory to synchronize with\n" @@ -526,21 +601,21 @@ msgstr "" "синхронизация\n" # well-spelled: ПОДКЛ -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr "" " --source-server=СТР_ПОДКЛ сервер, с которым будет проведена " "синхронизация\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr "" " -n, --dry-run остановиться до внесения каких-либо " "изменений\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written\n" @@ -549,12 +624,12 @@ msgstr "" " -N, --no-sync не ждать завершения сохранения данных на " "диске\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress выводить сообщения о ходе процесса\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid "" " -R, --write-recovery-conf write configuration for replication\n" @@ -563,7 +638,7 @@ msgstr "" " -R, --write-recovery-conf записать конфигурацию для репликации\n" " (требуется указание --source-server)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -573,13 +648,13 @@ msgstr "" " конфигурации сервера при запуске целевого\n" " кластера\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr "" " --debug выдавать множество отладочных сообщений\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid "" " --no-ensure-shutdown do not automatically fix unclean shutdown\n" @@ -587,18 +662,23 @@ msgstr "" " --no-ensure-shutdown не исправлять автоматически состояние,\n" " возникающее при нештатном отключении\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" + +#: pg_rewind.c:113 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "" "\n" @@ -607,33 +687,33 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "источник не указан (требуется --source-pgdata или --source-server)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "указать можно только --source-pgdata либо --source-server" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "целевой каталог данных не указан (--target-pgdata)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "" "no source server information (--source-server) specified for --write-" @@ -642,119 +722,119 @@ msgstr "" "отсутствует информация об исходном сервере (--source-server) для --write-" "recovery-conf" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "программу не должен запускать root" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Запускать %s нужно от имени суперпользователя PostgreSQL." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" -msgstr "не удалось считать права на каталог \"%s\": %m" +msgstr "не удалось прочитать права на каталог \"%s\": %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "подключение к серверу установлено" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "исходный и целевой кластер уже на одной линии времени" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "серверы разошлись в позиции WAL %X/%X на линии времени %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "перемотка не требуется" -#: pg_rewind.c:451 +#: pg_rewind.c:463 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "" "перемотка от последней общей контрольной точки в позиции %X/%X на линии " "времени %u" -#: pg_rewind.c:461 +#: pg_rewind.c:473 #, c-format msgid "reading source file list" msgstr "чтение списка исходных файлов" -#: pg_rewind.c:465 +#: pg_rewind.c:477 #, c-format msgid "reading target file list" msgstr "чтение списка целевых файлов" -#: pg_rewind.c:474 +#: pg_rewind.c:486 #, c-format msgid "reading WAL in target" msgstr "чтение WAL в целевом кластере" -#: pg_rewind.c:495 +#: pg_rewind.c:507 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "требуется скопировать %lu МБ (общий размер исходного каталога: %lu МБ)" -#: pg_rewind.c:513 +#: pg_rewind.c:525 #, c-format msgid "syncing target data directory" msgstr "синхронизация целевого каталога данных" -#: pg_rewind.c:529 +#: pg_rewind.c:541 #, c-format msgid "Done!" msgstr "Готово!" -#: pg_rewind.c:609 +#: pg_rewind.c:621 #, c-format msgid "no action decided for file \"%s\"" msgstr "действие не определено для файла \"%s\"" -#: pg_rewind.c:641 +#: pg_rewind.c:653 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "в исходной системе произошли изменения в процессе работы pg_rewind" -#: pg_rewind.c:645 +#: pg_rewind.c:657 #, c-format msgid "creating backup label and updating control file" msgstr "создание метки копии и модификация управляющего файла" -#: pg_rewind.c:695 +#: pg_rewind.c:707 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "исходная система оказалась в неожиданном состоянии после перемотки" -#: pg_rewind.c:727 +#: pg_rewind.c:739 #, c-format msgid "source and target clusters are from different systems" msgstr "исходный и целевой кластеры относятся к разным системам" -#: pg_rewind.c:735 +#: pg_rewind.c:747 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "кластеры несовместимы с этой версией pg_rewind" -#: pg_rewind.c:745 +#: pg_rewind.c:757 #, c-format msgid "" "target server needs to use either data checksums or \"wal_log_hints = on\"" @@ -762,191 +842,192 @@ msgstr "" "на целевом сервере должны быть контрольные суммы данных или \"wal_log_hints " "= on\"" -#: pg_rewind.c:756 +#: pg_rewind.c:768 #, c-format msgid "target server must be shut down cleanly" msgstr "целевой сервер должен быть выключен штатно" -#: pg_rewind.c:766 +#: pg_rewind.c:778 #, c-format msgid "source data directory must be shut down cleanly" msgstr "работа с исходным каталогом данных должна быть завершена штатно" -#: pg_rewind.c:813 +#: pg_rewind.c:825 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s КБ (%d%%) скопировано" -#: pg_rewind.c:941 +#: pg_rewind.c:951 #, c-format msgid "" "could not find common ancestor of the source and target cluster's timelines" msgstr "" "не удалось найти общего предка линий времени исходного и целевого кластеров" -#: pg_rewind.c:982 +#: pg_rewind.c:992 #, c-format msgid "backup label buffer too small" msgstr "буфер для метки копии слишком мал" -#: pg_rewind.c:1005 +#: pg_rewind.c:1015 #, c-format msgid "unexpected control file CRC" msgstr "неверная контрольная сумма управляющего файла" -#: pg_rewind.c:1017 +#: pg_rewind.c:1027 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "неверный размер управляющего файла (%d), ожидалось: %d" -#: pg_rewind.c:1026 +#: pg_rewind.c:1037 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the " -"control file specifies %d bytes" -msgstr[0] "" -"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" -msgstr[1] "" -"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" -msgstr[2] "" -"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в управляющем файле указано значение: %d" - -#: pg_rewind.c:1065 pg_rewind.c:1135 +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[1] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" +msgstr[2] "управляющий файл содержит неверный размер сегмента WAL (%d Б)" + +#: pg_rewind.c:1041 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "" +"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 ГБ." + +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "" "program \"%s\" is needed by %s but was not found in the same directory as " "\"%s\"" msgstr "программа \"%s\" нужна для %s, но она не найдена в каталоге \"%s\"" -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1081 pg_rewind.c:1149 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "" "программа \"%s\" найдена программой \"%s\", но её версия отличается от " "версии %s" -#: pg_rewind.c:1101 +#: pg_rewind.c:1110 +#, c-format +msgid "could not read restore_command from target cluster" +msgstr "не удалось прочитать параметр \"restore_command\" в целевом кластере" + +#: pg_rewind.c:1115 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "команда restore_command в целевом кластере не определена" +msgid "\"restore_command\" is not set in the target cluster" +msgstr "параметр \"restore_command\" в целевом кластере не определён" -#: pg_rewind.c:1142 +#: pg_rewind.c:1153 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "" "выполнение \"%s\" для восстановления согласованности на целевом сервере" -#: pg_rewind.c:1180 +#: pg_rewind.c:1191 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "" "не удалось запустить postgres в целевом кластере в однопользовательском " "режиме" -#: pg_rewind.c:1181 +#: pg_rewind.c:1192 #, c-format msgid "Command was: %s" msgstr "Выполнялась команда: %s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "синтаксическая ошибка в файле истории: %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "Ожидается числовой идентификатор линии времени." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "Ожидается положение точки переключения журнала предзаписи." -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "неверные данные в файле истории: %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "Идентификаторы линий времени должны возрастать." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "неверные данные в файле истории" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "" "Идентификаторы линий времени должны быть меньше идентификатора линии-потомка." -#: xlogreader.c:621 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "" "неверное смещение записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: xlogreader.c:630 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "в позиции %X/%X запрошено продолжение записи" -#: xlogreader.c:671 xlogreader.c:1136 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "" "неверная длина записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: xlogreader.c:760 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "нет флага contrecord в позиции %X/%X" -#: xlogreader.c:773 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неверная длина contrecord: %u (ожидалась %lld) в позиции %X/%X" -#: xlogreader.c:1144 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "неверный ID менеджера ресурсов %u в позиции %X/%X" -#: xlogreader.c:1157 xlogreader.c:1173 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запись с неверной ссылкой назад %X/%X в позиции %X/%X" -#: xlogreader.c:1211 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "" "некорректная контрольная сумма данных менеджера ресурсов в записи в позиции " "%X/%X" -#: xlogreader.c:1245 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверное магическое число %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1260 xlogreader.c:1302 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверные информационные биты %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1276 +#: xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -955,7 +1036,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: в нём указан идентификатор системы БД " "%llu, а идентификатор системы pg_control: %llu" -#: xlogreader.c:1284 +#: xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -964,7 +1045,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный размер сегмента в заголовке " "страницы" -#: xlogreader.c:1290 +#: xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -973,12 +1054,12 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный XLOG_BLCKSZ в заголовке " "страницы" -#: xlogreader.c:1322 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неожиданный pageaddr %X/%X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1348 +#: xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -987,23 +1068,23 @@ msgstr "" "нарушение последовательности ID линии времени %u (после %u) в сегменте WAL " "%s, LSN %X/%X, смещение %u" -#: xlogreader.c:1754 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "идентификатор блока %u идёт не по порядку в позиции %X/%X" -#: xlogreader.c:1778 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA установлен, но данных в позиции %X/%X нет" -#: xlogreader.c:1785 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "" "BKPBLOCK_HAS_DATA не установлен, но длина данных равна %u в позиции %X/%X" -#: xlogreader.c:1821 +#: xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -1012,21 +1093,21 @@ msgstr "" "BKPIMAGE_HAS_HOLE установлен, но для пропуска заданы смещение %u и длина %u " "при длине образа блока %u в позиции %X/%X" -#: xlogreader.c:1837 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE не установлен, но для пропуска заданы смещение %u и длина " "%u в позиции %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED установлен, но длина образа блока равна %u в позиции %X/" "%X" -#: xlogreader.c:1866 +#: xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -1035,41 +1116,41 @@ msgstr "" "ни BKPIMAGE_HAS_HOLE, ни BKPIMAGE_COMPRESSED не установлены, но длина образа " "блока равна %u в позиции %X/%X" -#: xlogreader.c:1882 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "" "BKPBLOCK_SAME_REL установлен, но предыдущее значение не задано в позиции %X/" "%X" -#: xlogreader.c:1894 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "неверный идентификатор блока %u в позиции %X/%X" -#: xlogreader.c:1961 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запись с неверной длиной в позиции %X/%X" -#: xlogreader.c:1987 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не удалось найти копию блока с ID %d в записи журнала WAL" -#: xlogreader.c:2071 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "" "не удалось восстановить образ в позиции %X/%X с указанным неверным блоком %d" -#: xlogreader.c:2078 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "" "не удалось восстановить образ в позиции %X/%X с неверным состоянием, блок %d" -#: xlogreader.c:2105 xlogreader.c:2122 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " @@ -1078,7 +1159,7 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый методом %s, который не " "поддерживается этой сборкой, блок %d" -#: xlogreader.c:2131 +#: xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" @@ -1086,7 +1167,7 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый неизвестным методом, " "блок %d" -#: xlogreader.c:2139 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не удалось развернуть образ в позиции %X/%X, блок %d" diff --git a/src/bin/pg_rewind/po/sv.po b/src/bin/pg_rewind/po/sv.po index 7826919eba45f..7894e029f203e 100644 --- a/src/bin/pg_rewind/po/sv.po +++ b/src/bin/pg_rewind/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_rewind # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-02 03:21+0000\n" -"PO-Revision-Date: 2023-09-05 09:02+0200\n" +"POT-Creation-Date: 2024-08-27 15:53+0000\n" +"PO-Revision-Date: 2024-08-27 18:32+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -37,6 +37,64 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:350 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "kunde inte stänga fil \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "byte-ordning stämmer inte" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"möjligt fel i byteordning\n" +"Den byteordning som filen från pg_control lagrats med passar kanske\n" +"inte detta program. I så fall kan nedanstående resultat vara felaktiga\n" +"och PostgreSQL-installationen vara inkompatibel med databaskatalogen." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:312 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "kunde inte skriva fil \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,6 +106,38 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -103,43 +193,58 @@ msgstr "oväntad filstorlek på \"%s\": %lld istället för %lld" msgid "could not open file \"%s\" restored from archive: %m" msgstr "kunde inte öppna fil \"%s\" återställd från arkiv: %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "kunde inte göra stat() på fil \"%s\": %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "restore_command misslyckades: %s" +msgid "\"restore_command\" failed: %s" +msgstr "\"restore_command\" misslyckades: %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "kunde inte återställa fil \"%s\" från arkiv" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "slut på minne" +msgid "invalid value \"%s\" for option %s" +msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" +msgid "%s must be in range %d..%d" +msgstr "%s måste vara i intervallet %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "slut på minne" + +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "kunde inte skriva till fil \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "kunde inte skapa fil \"%s\": %m" +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -155,11 +260,6 @@ msgstr "kunde inte stänga målfil \"%s\": %m" msgid "could not seek in target file \"%s\": %m" msgstr "kunde inte söka i målfil \"%s\": %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "kunde inte skriva fil \"%s\": %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -205,26 +305,6 @@ msgstr "kunde inte skapa en symnbolisk länk vid \"%s\": %m" msgid "could not remove symbolic link \"%s\": %m" msgstr "kan inte ta bort symbolisk länk \"%s\": %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "kunde inte öppna filen \"%s\" för läsning: %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "kunde inte läsa fil \"%s\": %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "kunde inte läsa fil \"%s\": läste %d av %zu" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "kunde inte öppna katalog \"%s\": %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -235,162 +315,157 @@ msgstr "kan inte läsa symbolisk länk \"%s\": %m" msgid "symbolic link \"%s\" target is too long" msgstr "mål för symbolisk länk \"%s\" är för lång" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "kunde inte läsa katalog \"%s\": %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "kunde inte stänga katalog \"%s\": %m" -#: filemap.c:236 +#: filemap.c:235 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "datafil \"%s\" i källan är inte en vanlig fil" -#: filemap.c:241 filemap.c:274 +#: filemap.c:240 filemap.c:273 #, c-format msgid "duplicate source file \"%s\"" msgstr "duplicerad källflagga \"%s\"" -#: filemap.c:329 +#: filemap.c:328 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "oväntad sidmodifiering för icke-regulär fil \"%s\"" -#: filemap.c:679 filemap.c:773 +#: filemap.c:682 filemap.c:776 #, c-format msgid "unknown file type for \"%s\"" msgstr "okänd filtyp på \"%s\"" -#: filemap.c:706 +#: filemap.c:709 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "filen \"%s\" har olika typ i källa och mål" -#: filemap.c:778 +#: filemap.c:781 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "kunde inte bestämma vad som skulle göras med filen \"%s\"" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "kunde inte nollställa search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "kunde inte nollställa \"search_path\": %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "full_page_writes måste vara påslagen i källservern" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "\"full_page_writes\" måste vara påslagen i källservern" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "kunde inte förbereda satsen för att hämta filinnehåll: %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "fel vid körande av fråga (%s) på källserver: %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "oväntad resultatmängd från fråga" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "fel vid körande av fråga (%s) i källserver: %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "oväntat resultat \"%s\" för nuvarande WAL-insättningsposition" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "kunde inte hämta fillista: %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "oväntad resultatmängd vid hämtning av fillista" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "kunde inte skicka fråga: %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "kunde inte sätta libpq-anslutning till enradsläge" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "oväntat resultat vid hämtning av extern fil: %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "tog emot fler datastycken än efterfrågat" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "oväntad resultatmängdstorlek vid hämtning av externa filer" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "oväntade datayper i resultatmängd vid hämtning av externa filer: %u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "oväntat resultatformat vid hämtning av externa filer" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "oväntade null-värden i resultat vid hämtning av externa filer" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "oväntad resultatlängd vid hämtning av externa filer" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "fick data för filen \"%s\", men efterfrågade för \"%s\"" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" msgstr "fick data från offset %lld i fil \"%s\", men efterfrågade offset %lld" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "tog emot mer än efterfrågat för filen \"%s\"" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "oväntat antal datastycken togs emot" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "kunde inte hämta extern fil \"%s\": %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "oväntat resultatmängd vid hämtning av extern fil \"%s\"" @@ -405,11 +480,6 @@ msgstr "kunde inte öppna källfil \"%s\": %m" msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "storleken på källfilen \"%s\" ändrades under körning: %d byte förväntades, %d kopierades" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "kunde inte stänga fil \"%s\": %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -460,7 +530,7 @@ msgstr "kunde inte söka (seek) i fil \"%s\": %m" msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "WAL-post modifierar en relation, men posttypen känns inte igen: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "" "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n" @@ -469,7 +539,7 @@ msgstr "" "%s resynkroniserar ett PostgreSQL-kluster med en annan kopia av klustret.\n" "\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "" "Usage:\n" @@ -480,41 +550,41 @@ msgstr "" " %s [FLAGGA]...\n" "\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "Flaggor:\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format msgid "" -" -c, --restore-target-wal use restore_command in target configuration to\n" +" -c, --restore-target-wal use \"restore_command\" in target configuration to\n" " retrieve WAL files from archives\n" msgstr "" -" -c, --restore-target-wal använd restore_command i målkonfigurationen\n" -" för att hämta WAL-filer från arkiv\n" +" -c, --restore-target-wal använd \"restore_command\" i målkonfigurationen\n" +" för att hämta WAL-filer från arkiven\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr " -D, --target-pgdata=KATALOG existerande datakatalog att modifiera\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n" msgstr " --source-pgdata=KATALOG källdatakatalog att synkronisera med\n" -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr " --source-server=ANSLSTR källserver att synkronisera med\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr " -n, --dry-run stoppa innan något modifieras\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid "" " -N, --no-sync do not wait for changes to be written\n" @@ -523,12 +593,12 @@ msgstr "" " -N, --no-sync vänta inte på att ändingar säkert\n" " skrivits till disk\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress skriv ut förloppmeddelanden\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid "" " -R, --write-recovery-conf write configuration for replication\n" @@ -537,7 +607,7 @@ msgstr "" " -R, --write-recovery-conf skriv konfiguration för replikering\n" " (kräver --source-server)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid "" " --config-file=FILENAME use specified main server configuration\n" @@ -546,27 +616,32 @@ msgstr "" " --config-file=FILNAMN använd angiven serverkonfiguration när\n" " målklustret körs\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr " --debug skriv ut en massa debugmeddelanden\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n" msgstr " --no-ensure-shutdown ingen automatisk hantering av trasig nedstängning\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" + +#: pg_rewind.c:113 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version skriv ut versioninformation och avsluta sedan\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp och avsluta sedan\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "" "\n" @@ -575,448 +650,420 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "ingen källa angavs (--source-pgdata eller --source-server)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "bara en av --source-pgdata och --source-server får anges" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "ingen måldatakatalog angiven (--target-pgdata)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "no source server information (--source-server) specified for --write-recovery-conf" msgstr "ingen källserverinformation (--source-server) angiven för --write-recovery-conf" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "kan inte köras av \"root\"" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Du måste köra %s som PostgreSQL:s superuser." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "kunde inte läsa rättigheter på katalog \"%s\": %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "ansluten till server" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "källa och målkluster är på samma tidslinje" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "servrarna divergerade vid WAL-position %X/%X på tidslinje %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "ingen rewind krävs" -#: pg_rewind.c:451 +#: pg_rewind.c:460 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "rewind från senaste gemensamma checkpoint vid %X/%X på tidslinje %u" -#: pg_rewind.c:461 +#: pg_rewind.c:470 #, c-format msgid "reading source file list" msgstr "läser källfillista" -#: pg_rewind.c:465 +#: pg_rewind.c:474 #, c-format msgid "reading target file list" msgstr "läser målfillista" -#: pg_rewind.c:474 +#: pg_rewind.c:483 #, c-format msgid "reading WAL in target" msgstr "läser WAL i målet" -#: pg_rewind.c:495 +#: pg_rewind.c:504 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "behöver kopiera %lu MB (total källkatalogstorlek är %lu MB)" -#: pg_rewind.c:513 +#: pg_rewind.c:522 #, c-format msgid "syncing target data directory" msgstr "synkar måldatakatalog" -#: pg_rewind.c:529 +#: pg_rewind.c:538 #, c-format msgid "Done!" msgstr "Klar!" -#: pg_rewind.c:609 +#: pg_rewind.c:618 #, c-format msgid "no action decided for file \"%s\"" msgstr "ingen åtgärd beslutades för filen \"%s\"" -#: pg_rewind.c:641 +#: pg_rewind.c:650 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "källsystemet ändrades samtidigt som pg_rewind kördes" -#: pg_rewind.c:645 +#: pg_rewind.c:654 #, c-format msgid "creating backup label and updating control file" msgstr "skapar backupetikett och uppdaterar kontrollfil" -#: pg_rewind.c:695 +#: pg_rewind.c:704 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "källsystemet var i ett oväntat tillstånd vid slutet av återspolningen" -#: pg_rewind.c:727 +#: pg_rewind.c:736 #, c-format msgid "source and target clusters are from different systems" msgstr "källa och målkluster är från olika system" -#: pg_rewind.c:735 +#: pg_rewind.c:744 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "klustren är inte kompatibla med denna version av pg_rewind" -#: pg_rewind.c:745 +#: pg_rewind.c:754 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "målservern behöver använda antingen datachecksums eller \"wal_log_hints = on\"" -#: pg_rewind.c:756 +#: pg_rewind.c:765 #, c-format msgid "target server must be shut down cleanly" msgstr "målserver måste stängas ner utan fel" -#: pg_rewind.c:766 +#: pg_rewind.c:775 #, c-format msgid "source data directory must be shut down cleanly" msgstr "måldatakatalog måste stängas ner utan fel" -#: pg_rewind.c:813 +#: pg_rewind.c:822 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "%*s/%s kB (%d%%) kopierad" -#: pg_rewind.c:941 +#: pg_rewind.c:948 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "kunde inte finna en gemensam anfader av källa och målklusterets tidslinjer" -#: pg_rewind.c:982 +#: pg_rewind.c:989 #, c-format msgid "backup label buffer too small" msgstr "backupetikett-buffer för liten" -#: pg_rewind.c:1005 +#: pg_rewind.c:1012 #, c-format msgid "unexpected control file CRC" msgstr "oväntad kontrollfil-CRC" -#: pg_rewind.c:1017 +#: pg_rewind.c:1024 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "oväntad kontrollfilstorlek %d, förväntade %d" -#: pg_rewind.c:1026 +#: pg_rewind.c:1034 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte" -msgstr[1] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" +msgstr[1] "ogiltigt WAL-segmentstorlek i kontrollfil (%d byte)" -#: pg_rewind.c:1065 pg_rewind.c:1135 +#: pg_rewind.c:1038 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL-segmentstorleken måste vara en tvåpotens mellan 1 MB och 1 GB." + +#: pg_rewind.c:1075 pg_rewind.c:1143 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "programmet \"%s\" behövs av %s men hittades inte i samma katalog som \"%s\"" -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "programmet \"%s\" hittades av \"%s\" men är inte av samma version som %s" -#: pg_rewind.c:1101 +#: pg_rewind.c:1107 +#, c-format +msgid "could not read restore_command from target cluster" +msgstr "kunde inte läsa restore_command från målklustret" + +#: pg_rewind.c:1112 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "restore_command är inte satt i målklustret" +msgid "\"restore_command\" is not set in the target cluster" +msgstr "\"restore_command\" är inte satt i målklustret" -#: pg_rewind.c:1142 +#: pg_rewind.c:1150 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "kör \"%s\" för målservern för att slutföra krashåterställning" -#: pg_rewind.c:1180 +#: pg_rewind.c:1188 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "postgres enanvändarläge misslyckades i målklustret" -#: pg_rewind.c:1181 +#: pg_rewind.c:1189 #, c-format msgid "Command was: %s" msgstr "Kommandot var: %s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "syntaxfel i history-fil: %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "Förväntade ett numeriskt tidslinje-ID." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "Förväntade en write-ahead-logg:s switchpoint-position." -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "felaktig data i history-fil: %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "Tidslinje-ID måste komma i en stigande sekvens." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "ogiltig data i historikfil" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "Tidslinje-ID:er måste vara mindre än barnens tidslinje-ID:er." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord är begärd vid %X/%X" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "slut på minne vid avkodning av post med längden %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "postlängd %u vid %X/%X är för lång" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "det finns ingen contrecord-flagga vid %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "ogiltig contrecord-längd %u (förväntade %lld) vid %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ogiltigt resurshanterar-ID %u vid %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "post med inkorrekt prev-link %X/%X vid %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "felaktig resurshanterardatakontrollsumma i post vid %X/%X" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "felaktigt magiskt nummer %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ogiltiga infobitar %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL-fil är från ett annat databassystem: WAL-filens databassystemidentifierare är %llu, pg_control databassystemidentifierare är %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt segmentstorlek i sidhuvud" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt XLOG_BLCKSZ i sidhuvud" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "oväntad sidadress %X/%X i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "ej-i-sekvens för tidslinje-ID %u (efter %u) i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ej-i-sekvens block_id %u vid %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA är satt men ingen data inkluderad vid %X/%X" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA är ej satt men datalängden är %u vid %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är satt men håloffset %u längd %u blockavbildlängd %u vid %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är inte satt men håloffset %u längd %u vid %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED är satt men blockavbildlängd %u vid %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "varken BKPIMAGE_HAS_HOLE eller BKPIMAGE_COMPRESSED är satt men blockavbildlängd är %u vid %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL är satt men ingen tidigare rel vid %X/%X" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "ogiltig block_id %u vid %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "post med ogiltig längd vid %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "kunde inte hitta backup-block med ID %d i WAL-post" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt block %d angivet" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt state, block %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med %s stöds inte av bygget, block %d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med okänd metod, block %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "kunde inte packa upp avbild vid %X/%X, block %d" - -#, c-format -#~ msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform" -#~ msgstr "\"%s\" är en symbolisk länk men symboliska länkar stöds inte på denna plattform" - -#, c-format -#~ msgid "cannot create restricted tokens on this platform: error code %lu" -#~ msgstr "kan inte skapa token för begränsad åtkomst på denna plattorm: felkod %lu" - -#, c-format -#~ msgid "cannot use restore_command with %%r placeholder" -#~ msgstr "kan inte använda restore_command med %%r-platshållare" - -#, c-format -#~ msgid "could not load library \"%s\": error code %lu" -#~ msgstr "kunde inte ladda länkbibliotek \"%s\": felkod %lu" - -#, c-format -#~ msgid "invalid control file" -#~ msgstr "ogiltig kontrollfil" - -#, c-format -#~ msgid "invalid record offset at %X/%X" -#~ msgstr "ogiltig postoffset vid %X/%X" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "det finns ingen contrecord vid %X/%X" diff --git a/src/bin/pg_rewind/po/uk.po b/src/bin/pg_rewind/po/uk.po index 3f3b8ab2ee7d8..dfcc9ac3269e6 100644 --- a/src/bin/pg_rewind/po/uk.po +++ b/src/bin/pg_rewind/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:21+0000\n" -"PO-Revision-Date: 2023-12-20 12:10\n" +"POT-Creation-Date: 2024-08-31 06:23+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_rewind.pot\n" -"X-Crowdin-File-ID: 961\n" +"X-Crowdin-File: /REL_17_STABLE/pg_rewind.pot\n" +"X-Crowdin-File-ID: 1030\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,6 +37,60 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../../common/controldata_utils.c:97 file_ops.c:326 file_ops.c:330 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" + +#: ../../common/controldata_utils.c:110 file_ops.c:341 local_source.c:104 +#: local_source.c:163 parsexlog.c:350 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:119 file_ops.c:344 parsexlog.c:352 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: local_source.c:121 local_source.c:172 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "неможливо закрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "неправильний порядок байтів" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "можлива помилка у послідовності байтів.\n" +"Порядок байтів, що використовують для зберігання файлу pg_control, може не відповідати тому, який використовується цією програмою. У такому випадку результати нижче будуть неправильним, і інсталяція PostgreSQL буде несумісною з цим каталогом даних." + +#: ../../common/controldata_utils.c:230 ../../common/file_utils.c:70 +#: ../../common/file_utils.c:347 ../../common/file_utils.c:406 +#: ../../common/file_utils.c:480 ../../fe_utils/recovery_gen.c:140 +#: parsexlog.c:312 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/controldata_utils.c:249 file_ops.c:117 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "не вдалося записати файл \"%s\": %m" + +#: ../../common/controldata_utils.c:268 ../../common/file_utils.c:418 +#: ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,6 +102,38 @@ msgstr "недостатньо пам'яті\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../fe_utils/archive.c:86 file_ops.c:417 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 file_ops.c:388 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 file_ops.c:462 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: ../../common/percentrepl.c:79 ../../common/percentrepl.c:118 #, c-format msgid "invalid value for parameter \"%s\": \"%s\"" @@ -103,43 +189,58 @@ msgstr "неочікуваний розмір файлу для \"%s\": %lld з msgid "could not open file \"%s\" restored from archive: %m" msgstr "не вдалося відкрити файл \"%s\" відновлений з архіву: %m" -#: ../../fe_utils/archive.c:86 file_ops.c:417 -#, c-format -msgid "could not stat file \"%s\": %m" -msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" - #: ../../fe_utils/archive.c:98 #, c-format -msgid "restore_command failed: %s" -msgstr "помилка restore_command: %s" +msgid "\"restore_command\" failed: %s" +msgstr "помилка \"restore_command\": %s" #: ../../fe_utils/archive.c:105 #, c-format msgid "could not restore file \"%s\" from archive" msgstr "не вдалося відновити файл \"%s\" з архіву" -#: ../../fe_utils/recovery_gen.c:34 ../../fe_utils/recovery_gen.c:45 -#: ../../fe_utils/recovery_gen.c:70 ../../fe_utils/recovery_gen.c:90 -#: ../../fe_utils/recovery_gen.c:149 +#: ../../fe_utils/option_utils.c:69 #, c-format -msgid "out of memory" -msgstr "недостатньо пам'яті" +msgid "invalid value \"%s\" for option %s" +msgstr "неприпустиме значення \"%s\" для параметра %s" -#: ../../fe_utils/recovery_gen.c:121 parsexlog.c:312 +#: ../../fe_utils/option_utils.c:76 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" +msgid "%s must be in range %d..%d" +msgstr "%s має бути в діапазоні %d..%d" -#: ../../fe_utils/recovery_gen.c:124 +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: ../../fe_utils/recovery_gen.c:39 ../../fe_utils/recovery_gen.c:50 +#: ../../fe_utils/recovery_gen.c:89 ../../fe_utils/recovery_gen.c:109 +#: ../../fe_utils/recovery_gen.c:168 +#, c-format +msgid "out of memory" +msgstr "недостатньо пам'яті" + +#: ../../fe_utils/recovery_gen.c:143 #, c-format msgid "could not write to file \"%s\": %m" msgstr "неможливо записати до файлу \"%s\": %m" -#: ../../fe_utils/recovery_gen.c:133 +#: ../../fe_utils/recovery_gen.c:152 #, c-format msgid "could not create file \"%s\": %m" msgstr "неможливо створити файл \"%s\": %m" +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + #: file_ops.c:67 #, c-format msgid "could not open target file \"%s\": %m" @@ -155,11 +256,6 @@ msgstr "не вдалося закрити цільовий файл \"%s\": %m" msgid "could not seek in target file \"%s\": %m" msgstr "не вдалося знайти в цільовому файлі \"%s\": %m" -#: file_ops.c:117 -#, c-format -msgid "could not write file \"%s\": %m" -msgstr "не вдалося записати файл \"%s\": %m" - #: file_ops.c:150 file_ops.c:177 #, c-format msgid "undefined file type for \"%s\"" @@ -205,26 +301,6 @@ msgstr "неможливо створити символічне посланн msgid "could not remove symbolic link \"%s\": %m" msgstr "не вдалося видалити символьне посилання \"%s\": %m" -#: file_ops.c:326 file_ops.c:330 -#, c-format -msgid "could not open file \"%s\" for reading: %m" -msgstr "не вдалося відкрити файл \"%s\" для читання: %m" - -#: file_ops.c:341 local_source.c:104 local_source.c:163 parsexlog.c:350 -#, c-format -msgid "could not read file \"%s\": %m" -msgstr "не вдалося прочитати файл \"%s\": %m" - -#: file_ops.c:344 parsexlog.c:352 -#, c-format -msgid "could not read file \"%s\": read %d of %zu" -msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu" - -#: file_ops.c:388 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не вдалося відкрити каталог \"%s\": %m" - #: file_ops.c:441 #, c-format msgid "could not read symbolic link \"%s\": %m" @@ -235,162 +311,157 @@ msgstr "не можливо прочитати символічне послан msgid "symbolic link \"%s\" target is too long" msgstr "таргет символічного посилання \"%s\" задовгий" -#: file_ops.c:462 -#, c-format -msgid "could not read directory \"%s\": %m" -msgstr "не вдалося прочитати каталог \"%s\": %m" - #: file_ops.c:466 #, c-format msgid "could not close directory \"%s\": %m" msgstr "не вдалося закрити каталог \"%s\": %m" -#: filemap.c:236 +#: filemap.c:235 #, c-format msgid "data file \"%s\" in source is not a regular file" msgstr "файл даних \"%s\" в джерелі не є регулярним файлом" -#: filemap.c:241 filemap.c:274 +#: filemap.c:240 filemap.c:273 #, c-format msgid "duplicate source file \"%s\"" msgstr "дублікат вихідного файлу \"%s\"" -#: filemap.c:329 +#: filemap.c:328 #, c-format msgid "unexpected page modification for non-regular file \"%s\"" msgstr "неочікувана модифікація сторінки для нерегулярного файлу \"%s\"" -#: filemap.c:679 filemap.c:773 +#: filemap.c:682 filemap.c:776 #, c-format msgid "unknown file type for \"%s\"" msgstr "невідомий тип файлу для \"%s\"" -#: filemap.c:706 +#: filemap.c:709 #, c-format msgid "file \"%s\" is of different type in source and target" msgstr "файл \"%s\" має різні типи у джерелі та цілі" -#: filemap.c:778 +#: filemap.c:781 #, c-format msgid "could not decide what to do with file \"%s\"" msgstr "не вдалося вирішити, що робити з файлом \"%s\"" -#: libpq_source.c:130 +#: libpq_source.c:131 #, c-format -msgid "could not clear search_path: %s" -msgstr "не вдалося очистити search_path: %s" +msgid "could not clear \"search_path\": %s" +msgstr "не вдалося очистити \"search_path\": %s" -#: libpq_source.c:141 +#: libpq_source.c:142 #, c-format -msgid "full_page_writes must be enabled in the source server" -msgstr "на початковому сервері повинно бути увімкнено full_page_writes" +msgid "\"full_page_writes\" must be enabled in the source server" +msgstr "\"full_page_writes\" слід ввімкнути на вихідному сервері" -#: libpq_source.c:152 +#: libpq_source.c:153 #, c-format msgid "could not prepare statement to fetch file contents: %s" msgstr "не вдалося підготувати інструкцію щоб отримати вміст файлу: %s" -#: libpq_source.c:171 +#: libpq_source.c:172 #, c-format msgid "error running query (%s) on source server: %s" msgstr "помилка при виконанні запиту (%s) на вихідному сервері: %s" -#: libpq_source.c:176 +#: libpq_source.c:177 #, c-format msgid "unexpected result set from query" msgstr "неочікуваний результат запиту" -#: libpq_source.c:198 +#: libpq_source.c:199 #, c-format msgid "error running query (%s) in source server: %s" msgstr "помилка при виконанні запиту (%s) на початковому сервері: %s" -#: libpq_source.c:219 +#: libpq_source.c:220 #, c-format msgid "unrecognized result \"%s\" for current WAL insert location" msgstr "нерозпізнаний результат \"%s\" замість поточної добавленої позиції WAL" -#: libpq_source.c:270 +#: libpq_source.c:271 #, c-format msgid "could not fetch file list: %s" msgstr "не вдалося отримати список файлів: %s" -#: libpq_source.c:275 +#: libpq_source.c:276 #, c-format msgid "unexpected result set while fetching file list" msgstr "неочікуваний результат при отриманні списку файлів" -#: libpq_source.c:467 +#: libpq_source.c:477 #, c-format msgid "could not send query: %s" msgstr "не вдалося надіслати запит: %s" -#: libpq_source.c:470 +#: libpq_source.c:480 #, c-format msgid "could not set libpq connection to single row mode" msgstr "не вдалося встановити libpq з'єднання для однорядкового режиму" -#: libpq_source.c:500 +#: libpq_source.c:510 #, c-format msgid "unexpected result while fetching remote files: %s" msgstr "неочікуваний результат при отриманні віддалених файлів: %s" -#: libpq_source.c:505 +#: libpq_source.c:515 #, c-format msgid "received more data chunks than requested" msgstr "отримано більше фрагментів даних, ніж запитувалось" -#: libpq_source.c:509 +#: libpq_source.c:519 #, c-format msgid "unexpected result set size while fetching remote files" msgstr "неочікуваний розмір набору результатів при отриманні віддалених файлів" -#: libpq_source.c:515 +#: libpq_source.c:525 #, c-format msgid "unexpected data types in result set while fetching remote files: %u %u %u" msgstr "неочікувані типи даних в результаті при отриманні віддалених файлів: %u %u %u" -#: libpq_source.c:523 +#: libpq_source.c:533 #, c-format msgid "unexpected result format while fetching remote files" msgstr "неочікуваний формат результату при отриманні віддалених файлів" -#: libpq_source.c:529 +#: libpq_source.c:539 #, c-format msgid "unexpected null values in result while fetching remote files" msgstr "неочікувані нульові значення в результаті при отриманні віддалених файлів" -#: libpq_source.c:533 +#: libpq_source.c:543 #, c-format msgid "unexpected result length while fetching remote files" msgstr "неочікувана довжина результату при отриманні віддалених файлів" -#: libpq_source.c:566 +#: libpq_source.c:576 #, c-format msgid "received data for file \"%s\", when requested for \"%s\"" msgstr "отримані дані для файлу \"%s\", коли запитувалось для \"%s\"" -#: libpq_source.c:570 +#: libpq_source.c:580 #, c-format msgid "received data at offset %lld of file \"%s\", when requested for offset %lld" msgstr "отримано дані по зсуву %lld файлу \"%s\", коли запитувалось про зсув %lld" -#: libpq_source.c:582 +#: libpq_source.c:592 #, c-format msgid "received more than requested for file \"%s\"" msgstr "отримано більше, ніж запитувалось для файлу \"%s\"" -#: libpq_source.c:595 +#: libpq_source.c:605 #, c-format msgid "unexpected number of data chunks received" msgstr "отримано неочікувану кількість фрагментів даних" -#: libpq_source.c:638 +#: libpq_source.c:648 #, c-format msgid "could not fetch remote file \"%s\": %s" msgstr "не вдалося отримати віддалений файл \"%s\": %s" -#: libpq_source.c:643 +#: libpq_source.c:653 #, c-format msgid "unexpected result set while fetching remote file \"%s\"" msgstr "неочікуваний набір результатів при отриманні віддаленого файлу \"%s\"" @@ -405,11 +476,6 @@ msgstr "не вдалося відкрити вихідний файл \"%s\": % msgid "size of source file \"%s\" changed concurrently: %d bytes expected, %d copied" msgstr "розмір вихідного файлу \"%s\" паралельно змінився: очікувалося %d байт, %d скопійовано" -#: local_source.c:121 local_source.c:172 -#, c-format -msgid "could not close file \"%s\": %m" -msgstr "неможливо закрити файл \"%s\": %m" - #: local_source.c:146 #, c-format msgid "could not seek in source file: %m" @@ -460,508 +526,523 @@ msgstr "не вдалося знайти в файлі \"%s\": %m" msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" msgstr "WAL модифікує відношення, але тип запису не розпізнано: lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X" -#: pg_rewind.c:92 +#: pg_rewind.c:94 #, c-format msgid "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n\n" msgstr "%s синхронізує кластер PostgreSQL з іншою копією кластеру.\n\n" -#: pg_rewind.c:93 +#: pg_rewind.c:95 #, c-format msgid "Usage:\n" " %s [OPTION]...\n\n" msgstr "Використання:\n" " %s [OPTION]...\n\n" -#: pg_rewind.c:94 +#: pg_rewind.c:96 #, c-format msgid "Options:\n" msgstr "Параметри:\n" -#: pg_rewind.c:95 +#: pg_rewind.c:97 #, c-format -msgid " -c, --restore-target-wal use restore_command in target configuration to\n" +msgid " -c, --restore-target-wal use \"restore_command\" in target configuration to\n" " retrieve WAL files from archives\n" -msgstr " -c, --restore-target-wal використовує restore_command в цільовій конфігурації, щоб\n" +msgstr " -c, --restore-target-wal використовує \"restore_command\" в цільовій конфігурації, щоб\n" " отримати файли WAL з архівів\n" -#: pg_rewind.c:97 +#: pg_rewind.c:99 #, c-format msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n" msgstr " -D, --target-pgdata=DIRECTORY існуючий каталог для змін\n" -#: pg_rewind.c:98 +#: pg_rewind.c:100 #, c-format msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n" msgstr " --source-pgdata=DIRECTORY початковий каталог даних для синхронізації\n" -#: pg_rewind.c:99 +#: pg_rewind.c:101 #, c-format msgid " --source-server=CONNSTR source server to synchronize with\n" msgstr " --source-server=CONNSTR початковий сервер для синхронізації\n" -#: pg_rewind.c:100 +#: pg_rewind.c:102 #, c-format msgid " -n, --dry-run stop before modifying anything\n" msgstr " -n, --dry-run зупинитися до внесення будь-яких змін\n" -#: pg_rewind.c:101 +#: pg_rewind.c:103 #, c-format msgid " -N, --no-sync do not wait for changes to be written\n" " safely to disk\n" msgstr " -N, --no-sync не чекати поки зміни будуть записані на диск\n" -#: pg_rewind.c:103 +#: pg_rewind.c:105 #, c-format msgid " -P, --progress write progress messages\n" msgstr " -P, --progress повідомляти про хід процесу\n" -#: pg_rewind.c:104 +#: pg_rewind.c:106 #, c-format msgid " -R, --write-recovery-conf write configuration for replication\n" " (requires --source-server)\n" msgstr " -R, --write-recovery-conf записує конфігурацію для реплікації \n" " (потребує --source-server)\n" -#: pg_rewind.c:106 +#: pg_rewind.c:108 #, c-format msgid " --config-file=FILENAME use specified main server configuration\n" " file when running target cluster\n" msgstr " --config-file=FILENAME використовувати заданий основний файл конфігурації сервера\n" " при запуску цільового кластера\n" -#: pg_rewind.c:108 +#: pg_rewind.c:110 #, c-format msgid " --debug write a lot of debug messages\n" msgstr " --debug виводити багато налагоджувальних повідомлень\n" -#: pg_rewind.c:109 +#: pg_rewind.c:111 #, c-format msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n" msgstr " --no-ensure-shutdown не виправляти автоматично неочищене завершення роботи\n" -#: pg_rewind.c:110 +#: pg_rewind.c:112 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод синхронізації файлів на диск\n" + +#: pg_rewind.c:113 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: pg_rewind.c:111 +#: pg_rewind.c:114 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати довідку, потім вийти\n" -#: pg_rewind.c:112 +#: pg_rewind.c:115 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_rewind.c:113 +#: pg_rewind.c:116 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_rewind.c:223 pg_rewind.c:231 pg_rewind.c:238 pg_rewind.c:245 -#: pg_rewind.c:252 pg_rewind.c:260 +#: pg_rewind.c:232 pg_rewind.c:240 pg_rewind.c:247 pg_rewind.c:254 +#: pg_rewind.c:261 pg_rewind.c:269 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_rewind.c:230 +#: pg_rewind.c:239 #, c-format msgid "no source specified (--source-pgdata or --source-server)" msgstr "джерело не вказано (--source-pgdata чи --source-server)" -#: pg_rewind.c:237 +#: pg_rewind.c:246 #, c-format msgid "only one of --source-pgdata or --source-server can be specified" msgstr "може бути вказано лише --source-pgdata чи --source-server" -#: pg_rewind.c:244 +#: pg_rewind.c:253 #, c-format msgid "no target data directory specified (--target-pgdata)" msgstr "не вказано жодного каталогу цільових даних (--target-pgdata)" -#: pg_rewind.c:251 +#: pg_rewind.c:260 #, c-format msgid "no source server information (--source-server) specified for --write-recovery-conf" msgstr "немає інформації про вихідний сервер (--source-server) вказаної для --write-recovery-conf" -#: pg_rewind.c:258 +#: pg_rewind.c:267 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_rewind.c:273 +#: pg_rewind.c:282 #, c-format msgid "cannot be executed by \"root\"" msgstr "\"root\" не може це виконувати" -#: pg_rewind.c:274 +#: pg_rewind.c:283 #, c-format msgid "You must run %s as the PostgreSQL superuser." msgstr "Запускати %s треба від суперкористувача PostgreSQL." -#: pg_rewind.c:284 +#: pg_rewind.c:293 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "не вдалося прочитати дозволи на каталог \"%s\": %m" -#: pg_rewind.c:302 +#: pg_rewind.c:311 #, c-format msgid "%s" msgstr "%s" -#: pg_rewind.c:305 +#: pg_rewind.c:314 #, c-format msgid "connected to server" msgstr "під'єднано до серверу" -#: pg_rewind.c:366 +#: pg_rewind.c:375 #, c-format msgid "source and target cluster are on the same timeline" msgstr "початковий і цільовий кластери знаходяться на одній лінії часу" -#: pg_rewind.c:387 +#: pg_rewind.c:396 #, c-format msgid "servers diverged at WAL location %X/%X on timeline %u" msgstr "сервери розійшлись в позиції WAL %X/%X на лінії часу %u" -#: pg_rewind.c:442 +#: pg_rewind.c:451 #, c-format msgid "no rewind required" msgstr "перемотування не потрібне" -#: pg_rewind.c:451 +#: pg_rewind.c:460 #, c-format msgid "rewinding from last common checkpoint at %X/%X on timeline %u" msgstr "перемотування від останньої спільної контрольної точки на %X/%X на лінії часу %u" -#: pg_rewind.c:461 +#: pg_rewind.c:470 #, c-format msgid "reading source file list" msgstr "читання списку файлів із джерела" -#: pg_rewind.c:465 +#: pg_rewind.c:474 #, c-format msgid "reading target file list" msgstr "читання списку цільових файлів" -#: pg_rewind.c:474 +#: pg_rewind.c:483 #, c-format msgid "reading WAL in target" msgstr "читання WAL у цілі" -#: pg_rewind.c:495 +#: pg_rewind.c:504 #, c-format msgid "need to copy %lu MB (total source directory size is %lu MB)" msgstr "треба скопіювати %lu МБ (загальний розмір каталогу джерела становить %lu МБ)" -#: pg_rewind.c:513 +#: pg_rewind.c:522 #, c-format msgid "syncing target data directory" msgstr "синхронізація цільового каталогу даних" -#: pg_rewind.c:529 +#: pg_rewind.c:538 #, c-format msgid "Done!" msgstr "Готово!" -#: pg_rewind.c:609 +#: pg_rewind.c:618 #, c-format msgid "no action decided for file \"%s\"" msgstr "жодних дій щодо файлу \"%s\" не прийнято" -#: pg_rewind.c:641 +#: pg_rewind.c:650 #, c-format msgid "source system was modified while pg_rewind was running" msgstr "вихідну систему було змінено під час роботи pg_rewind" -#: pg_rewind.c:645 +#: pg_rewind.c:654 #, c-format msgid "creating backup label and updating control file" msgstr "створення мітки резервного копіювання і оновлення контрольного файлу" -#: pg_rewind.c:695 +#: pg_rewind.c:704 #, c-format msgid "source system was in unexpected state at end of rewind" msgstr "вихідна система була в неочікуваному стані наприкінці перемотування" -#: pg_rewind.c:727 +#: pg_rewind.c:736 #, c-format msgid "source and target clusters are from different systems" msgstr "початковий і цільовий кластер належать до різних систем" -#: pg_rewind.c:735 +#: pg_rewind.c:744 #, c-format msgid "clusters are not compatible with this version of pg_rewind" msgstr "кластери не сумісні з даною версією pg_rewind" -#: pg_rewind.c:745 +#: pg_rewind.c:754 #, c-format msgid "target server needs to use either data checksums or \"wal_log_hints = on\"" msgstr "цільовий сервер потребує використання контрольної суми даних або \"wal_log_hints = on\"" -#: pg_rewind.c:756 +#: pg_rewind.c:765 #, c-format msgid "target server must be shut down cleanly" msgstr "цільовий сервер повинен бути вимкненим штатно" -#: pg_rewind.c:766 +#: pg_rewind.c:775 #, c-format msgid "source data directory must be shut down cleanly" msgstr "робота з початковим каталогом даних повинна бути завершена штатно" -#: pg_rewind.c:813 +#: pg_rewind.c:822 #, c-format msgid "%*s/%s kB (%d%%) copied" msgstr "скопійовано %*s/%s кБ (%d%%)" -#: pg_rewind.c:941 +#: pg_rewind.c:948 #, c-format msgid "could not find common ancestor of the source and target cluster's timelines" msgstr "не вдалося знайти спільного предка ліній часу початкового та цільового кластерів" -#: pg_rewind.c:982 +#: pg_rewind.c:989 #, c-format msgid "backup label buffer too small" msgstr "буфер для мітки резервного копіювання замалий" -#: pg_rewind.c:1005 +#: pg_rewind.c:1012 #, c-format msgid "unexpected control file CRC" msgstr "неочікуваний контрольний файл CRC" -#: pg_rewind.c:1017 +#: pg_rewind.c:1024 #, c-format msgid "unexpected control file size %d, expected %d" msgstr "неочікуваний розмір контрольного файлу %d, очікувалося %d" -#: pg_rewind.c:1026 +#: pg_rewind.c:1034 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes" -msgstr[0] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[1] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[2] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" -msgstr[3] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d" +msgid "invalid WAL segment size in control file (%d byte)" +msgid_plural "invalid WAL segment size in control file (%d bytes)" +msgstr[0] "невірний розмір сегменту WAL у файлі керування (%d байт)" +msgstr[1] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[2] "невірний розмір сегмента WAL у файлі керування (%d байтів)" +msgstr[3] "невірний розмір сегмента WAL у файлі керування (%d байтів)" -#: pg_rewind.c:1065 pg_rewind.c:1135 +#: pg_rewind.c:1038 +#, c-format +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Розмір сегмента WAL повинен бути степенем двійки від 1 МБ до 1 ГБ." + +#: pg_rewind.c:1075 pg_rewind.c:1143 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\"" -#: pg_rewind.c:1068 pg_rewind.c:1138 +#: pg_rewind.c:1078 pg_rewind.c:1146 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "програма \"%s\" знайдена для \"%s\", але має відмінну версію від %s" -#: pg_rewind.c:1101 +#: pg_rewind.c:1107 +#, c-format +msgid "could not read restore_command from target cluster" +msgstr "не вдалося прочитати \"restore_command\" з цільового кластеру" + +#: pg_rewind.c:1112 #, c-format -msgid "restore_command is not set in the target cluster" -msgstr "команда restore_command не встановлена в цільовому кластері" +msgid "\"restore_command\" is not set in the target cluster" +msgstr "команда \"restore_command\" не встановлена в цільовому кластері" -#: pg_rewind.c:1142 +#: pg_rewind.c:1150 #, c-format msgid "executing \"%s\" for target server to complete crash recovery" msgstr "виконання \"%s\" для цільового серверу, щоб завершити відновлення після аварійного завершення роботи" -#: pg_rewind.c:1180 +#: pg_rewind.c:1188 #, c-format msgid "postgres single-user mode in target cluster failed" msgstr "не вдалося ввімкнути однокористувацький режим postgres в цільовому кластері" -#: pg_rewind.c:1181 +#: pg_rewind.c:1189 #, c-format msgid "Command was: %s" msgstr "Команда була: %s" -#: timeline.c:75 timeline.c:81 +#: timeline.c:74 timeline.c:80 #, c-format msgid "syntax error in history file: %s" msgstr "синтаксична помилка у файлі історії: %s" -#: timeline.c:76 +#: timeline.c:75 #, c-format msgid "Expected a numeric timeline ID." msgstr "Очікується числовий ідентифікатор лінії часу." -#: timeline.c:82 +#: timeline.c:81 #, c-format msgid "Expected a write-ahead log switchpoint location." msgstr "Очікується положення точки випереджувального журналювання." -#: timeline.c:87 +#: timeline.c:86 #, c-format msgid "invalid data in history file: %s" msgstr "неприпустимі дані у файлу історії: %s" -#: timeline.c:88 +#: timeline.c:87 #, c-format msgid "Timeline IDs must be in increasing sequence." msgstr "Ідентифікатори ліній часу повинні збільшуватись." -#: timeline.c:108 +#: timeline.c:107 #, c-format msgid "invalid data in history file" msgstr "неприпустимі дані у файлі історії" -#: timeline.c:109 +#: timeline.c:108 #, c-format msgid "Timeline IDs must be less than child timeline's ID." msgstr "Ідентифікатори ліній часу повинні бути меншими від ідентифікатора дочірньої лінії." -#: xlogreader.c:621 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "неприпустиме зміщення запису в %X/%X: очікувалось хоча б %u, отримано %u" -#: xlogreader.c:630 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "по зсуву %X/%X запитано продовження запису" -#: xlogreader.c:671 xlogreader.c:1136 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "неприпустима довжина запису %X/%X: очікувалась мінімум %u, отримано %u" -#: xlogreader.c:760 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "немає прапорця contrecord в позиції %X/%X" -#: xlogreader.c:773 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неприпустима довжина contrecord %u (очікувалось %lld) на %X/%X" -#: xlogreader.c:1144 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "невірний ID менеджера ресурсів %u в %X/%X" -#: xlogreader.c:1157 xlogreader.c:1173 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запис з неправильним попереднім посиланням %X/%X на %X/%X" -#: xlogreader.c:1211 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "некоректна контрольна сума даних менеджера ресурсів у запису по зсуву %X/%X" -#: xlogreader.c:1245 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірне магічне число %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1260 xlogreader.c:1302 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірні інформаційні біти %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1276 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL файл належить іншій системі баз даних: ідентифікатор системи баз даних де міститься WAL файл - %llu, а ідентифікатор системи баз даних pg_control - %llu" -#: xlogreader.c:1284 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний розмір сегменту в заголовку сторінки" -#: xlogreader.c:1290 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний XLOG_BLCKSZ в заголовку сторінки" -#: xlogreader.c:1322 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неочікуваний pageaddr %X/%X у сегменті WAL %s, LSN %X/%X, зміщення %u" -#: xlogreader.c:1348 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "порушення послідовності ID лінії часу %u (після %u) у сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1754 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ідентифікатор блока %u out-of-order в позиції %X/%X" -#: xlogreader.c:1778 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але немає даних в позиції %X/%X" -#: xlogreader.c:1785 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але довжина даних дорівнює %u в позиції %X/%X" -#: xlogreader.c:1821 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE встановлений, але для пропуску задані: зсув %u, довжина %u, при довжині образу блока %u в позиції %X/%X" -#: xlogreader.c:1837 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE не встановлений, але для пропуску задані: зсув %u, довжина %u в позиції %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED встановлений, але довжина образу блока дорівнює %u в позиції %X/%X" -#: xlogreader.c:1866 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ні BKPIMAGE_HAS_HOLE, ні BKPIMAGE_COMPRESSED не встановлені, але довжина образу блока дорівнює %u в позиції %X/%X" -#: xlogreader.c:1882 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL встановлений, але попереднє значення не задано в позиції %X/%X" -#: xlogreader.c:1894 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "невірний ідентифікатор блоку %u в позиції %X/%X" -#: xlogreader.c:1961 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запис з невірною довжиною на %X/%X" -#: xlogreader.c:1987 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не вдалося знайти блок резервної копії з ID %d у записі WAL" -#: xlogreader.c:2071 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "не вдалося відновити зображення %X/%X з недійсним вказаним блоком %d" -#: xlogreader.c:2078 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "не вдалося відновити зображення %X/%X з недійсним станом, блок %d" -#: xlogreader.c:2105 xlogreader.c:2122 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "не вдалося відновити зображення в %X/%X, стиснуте %s, не підтримується збіркою, блок %d" -#: xlogreader.c:2131 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "не вдалося відновити зображення %X/%X стиснуте з невідомим методом, блок %d" -#: xlogreader.c:2139 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не вдалося розпакувати зображення на %X/%X, блок %d" diff --git a/src/bin/pg_rewind/rewind_source.h b/src/bin/pg_rewind/rewind_source.h index 9c4f0aa173a72..8b619a2db40f3 100644 --- a/src/bin/pg_rewind/rewind_source.h +++ b/src/bin/pg_rewind/rewind_source.h @@ -8,7 +8,7 @@ * operations to fetch data from the source system, so that the rest of * the code doesn't need to care what kind of a source its dealing with. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/bin/pg_rewind/t/001_basic.pl b/src/bin/pg_rewind/t/001_basic.pl index d2cc4d22f0ed4..031060db84211 100644 --- a/src/bin/pg_rewind/t/001_basic.pl +++ b/src/bin/pg_rewind/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -106,8 +106,8 @@ sub run_test command_fails( [ 'pg_rewind', '--debug', - '--source-pgdata', $standby_pgdata, - '--target-pgdata', $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, '--no-sync' ], 'pg_rewind with running target'); @@ -118,8 +118,8 @@ sub run_test command_fails( [ 'pg_rewind', '--debug', - '--source-pgdata', $standby_pgdata, - '--target-pgdata', $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, '--no-sync', '--no-ensure-shutdown' ], 'pg_rewind --no-ensure-shutdown with running target'); @@ -131,8 +131,8 @@ sub run_test command_fails( [ 'pg_rewind', '--debug', - '--source-pgdata', $standby_pgdata, - '--target-pgdata', $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, '--no-sync', '--no-ensure-shutdown' ], 'pg_rewind with unexpected running source'); @@ -145,8 +145,8 @@ sub run_test command_ok( [ 'pg_rewind', '--debug', - '--source-pgdata', $standby_pgdata, - '--target-pgdata', $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, '--no-sync', '--dry-run' ], 'pg_rewind --dry-run'); diff --git a/src/bin/pg_rewind/t/002_databases.pl b/src/bin/pg_rewind/t/002_databases.pl index 755ea80e332f9..031c545faa02f 100644 --- a/src/bin/pg_rewind/t/002_databases.pl +++ b/src/bin/pg_rewind/t/002_databases.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_rewind/t/003_extrafiles.pl b/src/bin/pg_rewind/t/003_extrafiles.pl index 097b0fde9d90a..823bcabeb8247 100644 --- a/src/bin/pg_rewind/t/003_extrafiles.pl +++ b/src/bin/pg_rewind/t/003_extrafiles.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test how pg_rewind reacts to extra files and directories in the data dirs. diff --git a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl index 8f63b3707ee07..dd577c0aa09b9 100644 --- a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl +++ b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test pg_rewind when the target's pg_wal directory is a symlink. diff --git a/src/bin/pg_rewind/t/005_same_timeline.pl b/src/bin/pg_rewind/t/005_same_timeline.pl index c8f5365ee7b0c..500b326ead462 100644 --- a/src/bin/pg_rewind/t/005_same_timeline.pl +++ b/src/bin/pg_rewind/t/005_same_timeline.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test that running pg_rewind with the source and target clusters diff --git a/src/bin/pg_rewind/t/006_options.pl b/src/bin/pg_rewind/t/006_options.pl index 5917bb741d510..b7a84ac4d7afb 100644 --- a/src/bin/pg_rewind/t/006_options.pl +++ b/src/bin/pg_rewind/t/006_options.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test checking options of pg_rewind. @@ -17,27 +17,30 @@ my $standby_pgdata = PostgreSQL::Test::Utils::tempdir; command_fails( [ - 'pg_rewind', '--debug', - '--target-pgdata', $primary_pgdata, - '--source-pgdata', $standby_pgdata, + 'pg_rewind', + '--debug', + '--target-pgdata' => $primary_pgdata, + '--source-pgdata' => $standby_pgdata, 'extra_arg1' ], 'too many arguments'); -command_fails([ 'pg_rewind', '--target-pgdata', $primary_pgdata ], +command_fails([ 'pg_rewind', '--target-pgdata' => $primary_pgdata ], 'no source specified'); command_fails( [ - 'pg_rewind', '--debug', - '--target-pgdata', $primary_pgdata, - '--source-pgdata', $standby_pgdata, - '--source-server', 'incorrect_source' + 'pg_rewind', + '--debug', + '--target-pgdata' => $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--source-server' => 'incorrect_source' ], 'both remote and local sources specified'); command_fails( [ - 'pg_rewind', '--debug', - '--target-pgdata', $primary_pgdata, - '--source-pgdata', $standby_pgdata, + 'pg_rewind', + '--debug', + '--target-pgdata' => $primary_pgdata, + '--source-pgdata' => $standby_pgdata, '--write-recovery-conf' ], 'no local source with --write-recovery-conf'); diff --git a/src/bin/pg_rewind/t/007_standby_source.pl b/src/bin/pg_rewind/t/007_standby_source.pl index 7084622758134..583e551a3e895 100644 --- a/src/bin/pg_rewind/t/007_standby_source.pl +++ b/src/bin/pg_rewind/t/007_standby_source.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test using a standby server as the source. @@ -124,10 +124,12 @@ # recovery configuration automatically. command_ok( [ - 'pg_rewind', "--debug", - "--source-server", $node_b->connstr('postgres'), - "--target-pgdata=$node_c_pgdata", "--no-sync", - "--write-recovery-conf" + 'pg_rewind', + '--debug', + '--source-server' => $node_b->connstr('postgres'), + '--target-pgdata' => $node_c_pgdata, + '--no-sync', + '--write-recovery-conf', ], 'pg_rewind remote'); } diff --git a/src/bin/pg_rewind/t/008_min_recovery_point.pl b/src/bin/pg_rewind/t/008_min_recovery_point.pl index 65b66df6333e7..28496afe350e8 100644 --- a/src/bin/pg_rewind/t/008_min_recovery_point.pl +++ b/src/bin/pg_rewind/t/008_min_recovery_point.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Test situation where a target data directory contains @@ -142,8 +142,10 @@ command_ok( [ - 'pg_rewind', "--source-server=$node_1_connstr", - "--target-pgdata=$node_2_pgdata", "--debug" + 'pg_rewind', + '--source-server' => $node_1_connstr, + '--target-pgdata' => $node_2_pgdata, + '--debug', ], 'run pg_rewind'); diff --git a/src/bin/pg_rewind/t/009_growing_files.pl b/src/bin/pg_rewind/t/009_growing_files.pl index 8e59ad6996168..afe68c8bf0d32 100644 --- a/src/bin/pg_rewind/t/009_growing_files.pl +++ b/src/bin/pg_rewind/t/009_growing_files.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -52,12 +52,11 @@ my $ret = run_log( [ 'pg_rewind', '--debug', - '--source-pgdata', $standby_pgdata, - '--target-pgdata', $primary_pgdata, + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, '--no-sync', ], - '2>>', - "$standby_pgdata/tst_both_dir/file1"); + '2>>' => "$standby_pgdata/tst_both_dir/file1"); ok(!$ret, 'Error out on copying growing file'); # Ensure that the files are of different size, the final error message should diff --git a/src/bin/pg_rewind/t/010_keep_recycled_wals.pl b/src/bin/pg_rewind/t/010_keep_recycled_wals.pl new file mode 100644 index 0000000000000..55bf046d9c10c --- /dev/null +++ b/src/bin/pg_rewind/t/010_keep_recycled_wals.pl @@ -0,0 +1,62 @@ +# Copyright (c) 2021-2025, PostgreSQL Global Development Group +# +# Test situation where a target data directory contains +# WAL files that were already recycled by the new primary. +# + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use Test::More; + +use FindBin; +use lib $FindBin::RealBin; +use RewindTest; + +RewindTest::setup_cluster(); +$node_primary->enable_archiving(); +RewindTest::start_primary(); + +RewindTest::create_standby(); +$node_standby->enable_restoring($node_primary, 0); +$node_standby->reload(); + +RewindTest::primary_psql("CHECKPOINT"); # last common checkpoint + +# We use `perl -e "exit(1)"` as an alternative to "false", because the latter +# might not be available on Windows. +my $false = "$^X -e \"exit(1)\""; +$node_primary->append_conf( + 'postgresql.conf', qq( +archive_command = '$false' +)); +$node_primary->reload(); + +# advance WAL on primary; this WAL segment will never make it to the archive +RewindTest::primary_psql("CREATE TABLE t(a int)"); +RewindTest::primary_psql("INSERT INTO t VALUES(0)"); +RewindTest::primary_psql("SELECT pg_switch_wal()"); + +RewindTest::promote_standby; + +# new primary loses diverging WAL segment +RewindTest::standby_psql("INSERT INTO t values(0)"); +RewindTest::standby_psql("SELECT pg_switch_wal()"); + +$node_standby->stop(); +$node_primary->stop(); + +my ($stdout, $stderr) = run_command( + [ + 'pg_rewind', '--debug', + '--source-pgdata' => $node_standby->data_dir, + '--target-pgdata' => $node_primary->data_dir, + '--no-sync', + ]); + +like( + $stderr, + qr/Not removing file .* because it is required for recovery/, + "some WAL files were skipped"); + +done_testing(); diff --git a/src/bin/pg_rewind/t/RewindTest.pm b/src/bin/pg_rewind/t/RewindTest.pm index 0bf59db997359..3efab8317978a 100644 --- a/src/bin/pg_rewind/t/RewindTest.pm +++ b/src/bin/pg_rewind/t/RewindTest.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group package RewindTest; @@ -69,8 +69,9 @@ sub primary_psql my $cmd = shift; my $dbname = shift || 'postgres'; - system_or_bail 'psql', '-q', '--no-psqlrc', '-d', - $node_primary->connstr($dbname), '-c', "$cmd"; + system_or_bail 'psql', '--quiet', '--no-psqlrc', + '--dbname' => $node_primary->connstr($dbname), + '--command' => $cmd; return; } @@ -79,8 +80,9 @@ sub standby_psql my $cmd = shift; my $dbname = shift || 'postgres'; - system_or_bail 'psql', '-q', '--no-psqlrc', '-d', - $node_standby->connstr($dbname), '-c', "$cmd"; + system_or_bail 'psql', '--quiet', '--no-psqlrc', + '--dbname' => $node_standby->connstr($dbname), + '--command' => $cmd; return; } @@ -95,11 +97,12 @@ sub check_query # we want just the output, no formatting my $result = run [ - 'psql', '-q', '-A', '-t', '--no-psqlrc', '-d', - $node_primary->connstr('postgres'), - '-c', $query + 'psql', '--quiet', '--no-align', '--tuples-only', '--no-psqlrc', + '--dbname' => $node_primary->connstr('postgres'), + '--command' => $query ], - '>', \$stdout, '2>', \$stderr; + '>' => \$stdout, + '2>' => \$stderr; is($result, 1, "$test_name: psql exit code"); is($stderr, '', "$test_name: psql no stderr"); @@ -124,7 +127,7 @@ sub setup_cluster $node_primary->init( allows_streaming => 1, extra => $extra, - auth_extra => [ '--create-role', 'rewind_user' ]); + auth_extra => [ '--create-role' => 'rewind_user' ]); # Set wal_keep_size to prevent WAL segment recycling after enforced # checkpoints in the tests. @@ -255,12 +258,11 @@ sub run_pg_rewind command_ok( [ 'pg_rewind', - "--debug", - "--source-pgdata=$standby_pgdata", - "--target-pgdata=$primary_pgdata", - "--no-sync", - "--config-file", - "$tmp_folder/primary-postgresql.conf.tmp" + '--debug', + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, + '--no-sync', + '--config-file' => "$tmp_folder/primary-postgresql.conf.tmp", ], 'pg_rewind local'); } @@ -270,14 +272,21 @@ sub run_pg_rewind # recovery configuration automatically. command_ok( [ - 'pg_rewind', "--debug", - "--source-server", $standby_connstr, - "--target-pgdata=$primary_pgdata", "--no-sync", - "--write-recovery-conf", "--config-file", - "$tmp_folder/primary-postgresql.conf.tmp" + 'pg_rewind', + '--debug', + '--source-server' => $standby_connstr, + '--target-pgdata' => $primary_pgdata, + '--no-sync', + '--write-recovery-conf', + '--config-file' => "$tmp_folder/primary-postgresql.conf.tmp", ], 'pg_rewind remote'); + # Check that pg_rewind with dbname and --write-recovery-conf + # wrote the dbname in the generated primary_conninfo value. + like(slurp_file("$primary_pgdata/postgresql.auto.conf"), + qr/dbname=postgres/m, 'recovery conf file sets dbname'); + # Check that standby.signal is here as recovery configuration # was requested. ok( -e "$primary_pgdata/standby.signal", @@ -327,14 +336,13 @@ sub run_pg_rewind command_ok( [ 'pg_rewind', - "--debug", - "--source-pgdata=$standby_pgdata", - "--target-pgdata=$primary_pgdata", - "--no-sync", - "--no-ensure-shutdown", - "--restore-target-wal", - "--config-file", - "$primary_pgdata/postgresql.conf" + '--debug', + '--source-pgdata' => $standby_pgdata, + '--target-pgdata' => $primary_pgdata, + '--no-sync', + '--no-ensure-shutdown', + '--restore-target-wal', + '--config-file' => "$primary_pgdata/postgresql.conf", ], 'pg_rewind archive'); } diff --git a/src/bin/pg_rewind/timeline.c b/src/bin/pg_rewind/timeline.c index 765b7c7661f5b..4d9f0d8301bf2 100644 --- a/src/bin/pg_rewind/timeline.c +++ b/src/bin/pg_rewind/timeline.c @@ -3,7 +3,7 @@ * timeline.c * timeline-related functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/bin/pg_test_fsync/meson.build b/src/bin/pg_test_fsync/meson.build index b7f35009de6e5..15f3439f99b5b 100644 --- a/src/bin/pg_test_fsync/meson.build +++ b/src/bin/pg_test_fsync/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_fsync_sources = files( 'pg_test_fsync.c', diff --git a/src/bin/pg_test_fsync/pg_test_fsync.c b/src/bin/pg_test_fsync/pg_test_fsync.c index cbf587116eafb..0060ea15902cb 100644 --- a/src/bin/pg_test_fsync/pg_test_fsync.c +++ b/src/bin/pg_test_fsync/pg_test_fsync.c @@ -2,7 +2,7 @@ * * pg_test_fsync --- tests all supported fsync() methods * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/bin/pg_test_fsync/pg_test_fsync.c * @@ -19,7 +19,6 @@ #include #include -#include "access/xlogdefs.h" #include "common/logging.h" #include "common/pg_prng.h" #include "getopt_long.h" @@ -113,11 +112,10 @@ main(int argc, char *argv[]) /* Prevent leaving behind the test file */ pqsignal(SIGINT, signal_cleanup); pqsignal(SIGTERM, signal_cleanup); + + /* the following are not valid on Windows */ #ifndef WIN32 pqsignal(SIGALRM, process_alarm); -#endif -#ifdef SIGHUP - /* Not defined on win32 */ pqsignal(SIGHUP, signal_cleanup); #endif diff --git a/src/bin/pg_test_fsync/po/es.po b/src/bin/pg_test_fsync/po/es.po index b522bdd5b2043..dff84abf1237b 100644 --- a/src/bin/pg_test_fsync/po/es.po +++ b/src/bin/pg_test_fsync/po/es.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_test_fsync (PostgreSQL) 16\n" +"Project-Id-Version: pg_test_fsync (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:22+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:53+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -40,88 +40,99 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f ops/seg %6.0f usegs/op\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "no se pudo crear el thread para la alarma" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "Empleo: %s [-f ARCHIVO] [-s SEG-POR-PRUEBA]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "argumento no válido para la opción %s" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "%s debe estar en el rango %u..%u" -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" msgstr[0] "%u segundo por prueba\n" msgstr[1] "%u segundos por prueba\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "O_DIRECT tiene soporte en esta plataforma para open_datasync y open_sync.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "F_NOCACHE tiene soporte en esta plataforma para open_datasync y open_sync.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "Direct I/O no está soportado en esta plataforma.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:335 pg_test_fsync.c:357 -#: pg_test_fsync.c:381 pg_test_fsync.c:525 pg_test_fsync.c:537 -#: pg_test_fsync.c:553 pg_test_fsync.c:559 pg_test_fsync.c:581 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "no se pudo abrir el archivo de salida" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:344 -#: pg_test_fsync.c:366 pg_test_fsync.c:390 pg_test_fsync.c:429 -#: pg_test_fsync.c:488 pg_test_fsync.c:527 pg_test_fsync.c:555 -#: pg_test_fsync.c:586 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "escritura falló" -#: pg_test_fsync.c:253 pg_test_fsync.c:368 pg_test_fsync.c:392 -#: pg_test_fsync.c:529 pg_test_fsync.c:561 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "fsync falló" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "" "\n" @@ -130,7 +141,7 @@ msgstr "" "\n" "Comparar métodos de sincronización de archivos usando una escritura de %dkB:\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "" "\n" @@ -139,21 +150,21 @@ msgstr "" "\n" "Comparar métodos de sincronización de archivos usando dos escrituras de %dkB:\n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format -msgid "(in wal_sync_method preference order, except fdatasync is Linux's default)\n" -msgstr "(en orden de preferencia de wal_sync_method, excepto en Linux donde fdatasync es el predeterminado)\n" +msgid "(in \"wal_sync_method\" preference order, except fdatasync is Linux's default)\n" +msgstr "(en orden de preferencia de «wal_sync_method», excepto en Linux donde fdatasync es el predeterminado)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:409 pg_test_fsync.c:476 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "n/a*" -#: pg_test_fsync.c:325 pg_test_fsync.c:397 pg_test_fsync.c:435 -#: pg_test_fsync.c:494 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "n/a" -#: pg_test_fsync.c:440 +#: pg_test_fsync.c:446 #, c-format msgid "" "* This file system and its mount options do not support direct\n" @@ -162,7 +173,7 @@ msgstr "" "* Este sistema de archivos con sus opciones de montaje no soportan\n" " Direct I/O, e.g. ext4 en modo journal.\n" -#: pg_test_fsync.c:448 +#: pg_test_fsync.c:454 #, c-format msgid "" "\n" @@ -171,7 +182,7 @@ msgstr "" "\n" "Comparar open_sync con diferentes tamaños de escritura:\n" -#: pg_test_fsync.c:449 +#: pg_test_fsync.c:455 #, c-format msgid "" "(This is designed to compare the cost of writing 16kB in different write\n" @@ -180,27 +191,27 @@ msgstr "" "(Esto está diseñado para comparar el costo de escribir 16kB en diferentes\n" "tamaños de escrituras open_sync.)\n" -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr " 1 * 16kB escritura open_sync" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr " 2 * 8kB escrituras open_sync" -#: pg_test_fsync.c:454 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr " 4 * 4kB escrituras open_sync" -#: pg_test_fsync.c:455 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr " 8 * 2kB escrituras open_sync" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr "16 * 1kB escrituras open_sync" -#: pg_test_fsync.c:510 +#: pg_test_fsync.c:516 #, c-format msgid "" "\n" @@ -209,7 +220,7 @@ msgstr "" "\n" "Probar si se respeta fsync en un descriptor de archivo que no es de escritura:\n" -#: pg_test_fsync.c:511 +#: pg_test_fsync.c:517 #, c-format msgid "" "(If the times are similar, fsync() can sync data written on a different\n" @@ -218,7 +229,7 @@ msgstr "" "(Si los tiempos son similares, fsync() puede sincronizar datos escritos\n" "en un descriptor diferente.)\n" -#: pg_test_fsync.c:576 +#: pg_test_fsync.c:582 #, c-format msgid "" "\n" diff --git a/src/bin/pg_test_fsync/po/fr.po b/src/bin/pg_test_fsync/po/fr.po index dfedfe84e78a1..464f9c6968730 100644 --- a/src/bin/pg_test_fsync/po/fr.po +++ b/src/bin/pg_test_fsync/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-14 10:20+0000\n" -"PO-Revision-Date: 2022-05-14 17:17+0200\n" +"POT-Creation-Date: 2024-08-22 10:24+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,110 +19,121 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "erreur : " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "attention : " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "détail : " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "astuce : " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f ops/sec %6.0f usecs/op\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "n'a pas pu créer un thread pour l'alarme" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s : %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "Usage: %s [-f NOMFICHIER] [-s SECS-PAR-TEST]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "argument invalide pour l'option %s" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "%s doit être compris entre %u et %u" -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" msgstr[0] "%u seconde par test\n" msgstr[1] "%u secondes par test\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "O_DIRECT supporté sur cette plateforme pour open_datasync et open_sync.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "F_NOCACHE supporté sur cette plateforme pour open_datasync et open_sync.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "Direct I/O n'est pas supporté sur cette plateforme.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:336 pg_test_fsync.c:361 -#: pg_test_fsync.c:385 pg_test_fsync.c:529 pg_test_fsync.c:541 -#: pg_test_fsync.c:557 pg_test_fsync.c:563 pg_test_fsync.c:585 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "n'a pas pu ouvrir le fichier en sortie" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:345 -#: pg_test_fsync.c:370 pg_test_fsync.c:394 pg_test_fsync.c:433 -#: pg_test_fsync.c:492 pg_test_fsync.c:531 pg_test_fsync.c:559 -#: pg_test_fsync.c:590 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "échec en écriture" -#: pg_test_fsync.c:253 pg_test_fsync.c:372 pg_test_fsync.c:396 -#: pg_test_fsync.c:533 pg_test_fsync.c:565 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "échec de la synchronisation (fsync)" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "" "\n" @@ -131,7 +142,7 @@ msgstr "" "\n" "Comparer les méthodes de synchronisation de fichier en utilisant une écriture de %d Ko :\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "" "\n" @@ -140,21 +151,21 @@ msgstr "" "\n" "Comparer les méthodes de synchronisation de fichier sur disque en utilisant deux écritures de %d Ko :\n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format -msgid "(in wal_sync_method preference order, except fdatasync is Linux's default)\n" -msgstr "(dans l'ordre de préférence de wal_sync_method, sauf fdatasync qui est la valeur par défaut sous Linux)\n" +msgid "(in \"wal_sync_method\" preference order, except fdatasync is Linux's default)\n" +msgstr "(dans l'ordre de préférence de « wal_sync_method », sauf fdatasync qui est la valeur par défaut sous Linux)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:413 pg_test_fsync.c:480 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "n/a*" -#: pg_test_fsync.c:325 pg_test_fsync.c:351 pg_test_fsync.c:401 -#: pg_test_fsync.c:439 pg_test_fsync.c:498 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "n/a" -#: pg_test_fsync.c:444 +#: pg_test_fsync.c:446 #, c-format msgid "" "* This file system and its mount options do not support direct\n" @@ -163,7 +174,7 @@ msgstr "" "* Ce système de fichiers et ses options de montage ne supportent pas les\n" " I/O directes, par exemple ext4 en journalisé.\n" -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:454 #, c-format msgid "" "\n" @@ -172,7 +183,7 @@ msgstr "" "\n" "Comparer open_sync avec différentes tailles d'écriture :\n" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:455 #, c-format msgid "" "(This is designed to compare the cost of writing 16kB in different write\n" @@ -181,27 +192,27 @@ msgstr "" "(Ceci est conçu pour comparer le coût d'écriture de 16 Ko dans différentes tailles\n" "d'écritures open_sync.)\n" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr " 1 * 16 Ko, écriture avec open_sync" -#: pg_test_fsync.c:457 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr " 2 * 8 Ko, écriture avec open_sync" -#: pg_test_fsync.c:458 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr " 4 * 4 Ko, écriture avec open_sync" -#: pg_test_fsync.c:459 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr " 8 * 2 Ko, écriture avec open_sync" -#: pg_test_fsync.c:460 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr " 16 * 1 Ko, écriture avec open_sync" -#: pg_test_fsync.c:514 +#: pg_test_fsync.c:516 #, c-format msgid "" "\n" @@ -210,7 +221,7 @@ msgstr "" "\n" "Teste si fsync est honoré sur un descripteur de fichiers sans écriture :\n" -#: pg_test_fsync.c:515 +#: pg_test_fsync.c:517 #, c-format msgid "" "(If the times are similar, fsync() can sync data written on a different\n" @@ -219,7 +230,7 @@ msgstr "" "(Si les temps sont similaires, fsync() peut synchroniser sur disque les données écrites sur\n" "un descripteur différent.)\n" -#: pg_test_fsync.c:580 +#: pg_test_fsync.c:582 #, c-format msgid "" "\n" @@ -227,16 +238,3 @@ msgid "" msgstr "" "\n" "%d Ko d'écritures non synchronisées :\n" - -#~ msgid "%s: %s\n" -#~ msgstr "%s : %s\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#~ msgid "seek failed" -#~ msgstr "seek échoué" diff --git a/src/bin/pg_test_fsync/po/ka.po b/src/bin/pg_test_fsync/po/ka.po index 9efe6500a3ae3..7377b96f94c64 100644 --- a/src/bin/pg_test_fsync/po/ka.po +++ b/src/bin/pg_test_fsync/po/ka.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pg_test_fsync (PostgreSQL) 15\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-18 22:24+0000\n" +"POT-Creation-Date: 2024-07-01 03:54+0000\n" "PO-Revision-Date: 2024-05-19 07:15+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" @@ -38,6 +38,17 @@ msgstr "დეტალები: " msgid "hint: " msgstr "მინიშნება: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + #. translator: maintain alignment with NA_FORMAT #: pg_test_fsync.c:38 #, c-format diff --git a/src/bin/pg_test_fsync/po/ko.po b/src/bin/pg_test_fsync/po/ko.po index d26cbae756f2a..787414df1a533 100644 --- a/src/bin/pg_test_fsync/po/ko.po +++ b/src/bin/pg_test_fsync/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_test_fsync (PostgreSQL) 16\n" +"Project-Id-Version: pg_test_fsync (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:52+0000\n" -"PO-Revision-Date: 2023-05-30 12:39+0900\n" +"POT-Creation-Date: 2025-01-17 04:54+0000\n" +"PO-Revision-Date: 2025-01-16 11:05+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -37,89 +37,100 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f ops/sec %6.0f usecs/op\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "알람용 쓰레드를 만들 수 없음" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "사용법: %s [-f 파일이름] [-s 검사초]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "%s 옵션의 잘못된 인자" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "%s 값은 %u부터 %u까지 지정할 수 있습니다." -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인자를 지정했습니다. (처음 \"%s\")" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" msgstr[0] "검사 간격: %u초\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "" "이 플랫폼에서는 open_datasync, open_sync 에서 O_DIRECT 옵션을 지원함.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "" "이 플랫폼에서는 open_datasync, open_sync 에서 F_NOCACHE 옵션을 지원함.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "이 플랫폼은 direct I/O 기능을 지원하지 않음.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:335 pg_test_fsync.c:357 -#: pg_test_fsync.c:381 pg_test_fsync.c:525 pg_test_fsync.c:537 -#: pg_test_fsync.c:553 pg_test_fsync.c:559 pg_test_fsync.c:581 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "출력 파일을 열 수 없음" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:344 -#: pg_test_fsync.c:366 pg_test_fsync.c:390 pg_test_fsync.c:429 -#: pg_test_fsync.c:488 pg_test_fsync.c:527 pg_test_fsync.c:555 -#: pg_test_fsync.c:586 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "쓰기 실패" -#: pg_test_fsync.c:253 pg_test_fsync.c:368 pg_test_fsync.c:392 -#: pg_test_fsync.c:529 pg_test_fsync.c:561 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "fsync 실패" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "" "\n" @@ -128,7 +139,7 @@ msgstr "" "\n" "하나의 %dkB 쓰기에 대한 파일 싱크 방법 비교:\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "" "\n" @@ -137,24 +148,25 @@ msgstr "" "\n" "두개의 %dkB 쓰기에 대한 파일 싱크 방법 비교:\n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format msgid "" -"(in wal_sync_method preference order, except fdatasync is Linux's default)\n" +"(in \"wal_sync_method\" preference order, except fdatasync is Linux's " +"default)\n" msgstr "" -"(fdatasync가 리눅스 기본값이기에 제외하고, wal_sync_method 우선으로 처리 " +"(fdatasync가 리눅스 기본값이기에 제외하고, \"wal_sync_method\" 우선으로 처리 " "함)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:409 pg_test_fsync.c:476 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "n/a*" -#: pg_test_fsync.c:325 pg_test_fsync.c:397 pg_test_fsync.c:435 -#: pg_test_fsync.c:494 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "n/a" -#: pg_test_fsync.c:440 +#: pg_test_fsync.c:446 #, c-format msgid "" "* This file system and its mount options do not support direct\n" @@ -163,7 +175,7 @@ msgstr "" "* 이 파일 시스템과 마운트 옵션이 direct I/O 기능을 지원하지 않음\n" " 예: journaled mode에서 ext4\n" -#: pg_test_fsync.c:448 +#: pg_test_fsync.c:454 #, c-format msgid "" "\n" @@ -172,7 +184,7 @@ msgstr "" "\n" "서로 다른 쓰기량으로 open_sync 비교:\n" -#: pg_test_fsync.c:449 +#: pg_test_fsync.c:455 #, c-format msgid "" "(This is designed to compare the cost of writing 16kB in different write\n" @@ -180,27 +192,27 @@ msgid "" msgstr "" "(서로 다른 크기로 16kB를 쓰는데, open_sync 옵션을 사용할 때의 비용 비교)\n" -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr " 1 * 16kB open_sync 쓰기" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr " 2 * 8kB open_sync 쓰기" -#: pg_test_fsync.c:454 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr " 4 * 4kB open_sync 쓰기" -#: pg_test_fsync.c:455 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr " 8 * 2kB open_sync 쓰기" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr "16 * 1kB open_sync 쓰기" -#: pg_test_fsync.c:510 +#: pg_test_fsync.c:516 #, c-format msgid "" "\n" @@ -209,7 +221,7 @@ msgstr "" "\n" "쓰기 방지 파일에서 fsync 작동 여부 검사:\n" -#: pg_test_fsync.c:511 +#: pg_test_fsync.c:517 #, c-format msgid "" "(If the times are similar, fsync() can sync data written on a different\n" @@ -218,7 +230,7 @@ msgstr "" "(이 값이 비슷하다면, fsync() 호출로 여러 파일 상태에 대해서 sync를 사용\n" "할 수 있음.)\n" -#: pg_test_fsync.c:576 +#: pg_test_fsync.c:582 #, c-format msgid "" "\n" diff --git a/src/bin/pg_test_fsync/po/meson.build b/src/bin/pg_test_fsync/po/meson.build index 5e286a9fc293e..08b2e396c8123 100644 --- a/src/bin/pg_test_fsync/po/meson.build +++ b/src/bin/pg_test_fsync/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_test_fsync-' + pg_version_major.to_string())] diff --git a/src/bin/pg_test_fsync/po/ru.po b/src/bin/pg_test_fsync/po/ru.po index 3ee354d1a9d09..c6fccd00352bf 100644 --- a/src/bin/pg_test_fsync/po/ru.po +++ b/src/bin/pg_test_fsync/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for pg_test_fsync # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2017, 2021, 2022. +# Alexander Lakhin , 2017, 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pg_test_fsync (PostgreSQL) 10\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2022-09-05 13:36+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 18:11+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -37,48 +37,59 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f оп/с %6.0f мкс/оп\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "не удалось создать поток для обработки сигналов" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "Использование: %s [-f ИМЯ_ФАЙЛА ] [-s ТЕСТ_СЕК]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "недопустимый аргумент параметра %s" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "значение %s должно быть в диапазоне %u..%u" -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" @@ -86,42 +97,42 @@ msgstr[0] "на тест отводится %u сек.\n" msgstr[1] "на тест отводится %u сек.\n" msgstr[2] "на тест отводится %u сек.\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "" "O_DIRECT на этой платформе не поддерживается для open_datasync и open_sync.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "" "F_NOCACHE на этой платформе поддерживается для open_datasync и open_sync.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "Прямой ввод/вывод не поддерживается на этой платформе.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:335 pg_test_fsync.c:357 -#: pg_test_fsync.c:381 pg_test_fsync.c:525 pg_test_fsync.c:537 -#: pg_test_fsync.c:553 pg_test_fsync.c:559 pg_test_fsync.c:581 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "не удалось открыть выходной файл" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:344 -#: pg_test_fsync.c:366 pg_test_fsync.c:390 pg_test_fsync.c:429 -#: pg_test_fsync.c:488 pg_test_fsync.c:527 pg_test_fsync.c:555 -#: pg_test_fsync.c:586 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "ошибка записи" -#: pg_test_fsync.c:253 pg_test_fsync.c:368 pg_test_fsync.c:392 -#: pg_test_fsync.c:529 pg_test_fsync.c:561 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "ошибка синхронизации с ФС" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "" "\n" @@ -130,7 +141,7 @@ msgstr "" "\n" "Сравнение методов синхронизации файлов при однократной записи %d КБ:\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "" "\n" @@ -139,24 +150,25 @@ msgstr "" "\n" "Сравнение методов синхронизации файлов при двухкратной записи %d КБ:\n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format msgid "" -"(in wal_sync_method preference order, except fdatasync is Linux's default)\n" +"(in \"wal_sync_method\" preference order, except fdatasync is Linux's " +"default)\n" msgstr "" -"(в порядке предпочтения для wal_sync_method, без учёта наибольшего " -"предпочтения fdatasync в Linux)\n" +"(в порядке предпочтения для \"wal_sync_method\", за исключением того, что в " +"Linux предпочитается fdatasync)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:409 pg_test_fsync.c:476 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "н/д*" -#: pg_test_fsync.c:325 pg_test_fsync.c:397 pg_test_fsync.c:435 -#: pg_test_fsync.c:494 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "н/д" -#: pg_test_fsync.c:440 +#: pg_test_fsync.c:446 #, c-format msgid "" "* This file system and its mount options do not support direct\n" @@ -165,7 +177,7 @@ msgstr "" "* Эта файловая система с текущими параметрами монтирования не поддерживает\n" " прямой ввод/вывод, как например, ext4 в режиме журналирования.\n" -#: pg_test_fsync.c:448 +#: pg_test_fsync.c:454 #, c-format msgid "" "\n" @@ -174,7 +186,7 @@ msgstr "" "\n" "Сравнение open_sync при различных объёмах записываемых данных:\n" -#: pg_test_fsync.c:449 +#: pg_test_fsync.c:455 #, c-format msgid "" "(This is designed to compare the cost of writing 16kB in different write\n" @@ -185,27 +197,27 @@ msgstr "" "записи с open_sync.)\n" # skip-rule: double-space -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr "запись с open_sync 1 * 16 КБ" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr "запись с open_sync 2 * 8 КБ" -#: pg_test_fsync.c:454 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr "запись с open_sync 4 * 4 КБ" -#: pg_test_fsync.c:455 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr "запись с open_sync 8 * 2 КБ" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr "запись с open_sync 16 * 1 КБ" -#: pg_test_fsync.c:510 +#: pg_test_fsync.c:516 #, c-format msgid "" "\n" @@ -215,7 +227,7 @@ msgstr "" "Проверка, производится ли fsync с указателем файла, открытого не для " "записи:\n" -#: pg_test_fsync.c:511 +#: pg_test_fsync.c:517 #, c-format msgid "" "(If the times are similar, fsync() can sync data written on a different\n" @@ -225,7 +237,7 @@ msgstr "" "данные,\n" "записанные через другой дескриптор.)\n" -#: pg_test_fsync.c:576 +#: pg_test_fsync.c:582 #, c-format msgid "" "\n" diff --git a/src/bin/pg_test_fsync/po/sv.po b/src/bin/pg_test_fsync/po/sv.po index 45f059e9db55d..3d03f5afe8c47 100644 --- a/src/bin/pg_test_fsync/po/sv.po +++ b/src/bin/pg_test_fsync/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_test_fsync # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-05-09 18:51+0000\n" -"PO-Revision-Date: 2022-05-09 21:44+0200\n" +"POT-Creation-Date: 2024-07-12 14:25+0000\n" +"PO-Revision-Date: 2024-07-12 19:06+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,108 +17,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../../../src/common/logging.c:277 +#: ../../../src/common/logging.c:276 #, c-format msgid "error: " msgstr "fel: " -#: ../../../src/common/logging.c:284 +#: ../../../src/common/logging.c:283 #, c-format msgid "warning: " msgstr "varning: " -#: ../../../src/common/logging.c:295 +#: ../../../src/common/logging.c:294 #, c-format msgid "detail: " msgstr "detalj: " -#: ../../../src/common/logging.c:302 +#: ../../../src/common/logging.c:301 #, c-format msgid "hint: " msgstr "tips: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f ops/sek %6.0f useks/op\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "kunde inte skapa alarmtråd" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "Användning: %s [-f FILENAMN] [-s SEK-PER-TEST]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "ogiltigt argument för flaggan %s" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "%s måste vara i intervallet %u..%u" -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" msgstr[0] "%u sekund per test\n" msgstr[1] "%u sekunder per test\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "O_DIRECT stöds på denna plattform för open_datasync och open_sync.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "F_NOCACHE stöds på denna plattform för open_datasync och open_sync.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "Direkt I/O stöds inte på denna plattform.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:336 pg_test_fsync.c:361 -#: pg_test_fsync.c:385 pg_test_fsync.c:529 pg_test_fsync.c:541 -#: pg_test_fsync.c:557 pg_test_fsync.c:563 pg_test_fsync.c:585 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "kunde inte öppna utdatafil" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:345 -#: pg_test_fsync.c:370 pg_test_fsync.c:394 pg_test_fsync.c:433 -#: pg_test_fsync.c:492 pg_test_fsync.c:531 pg_test_fsync.c:559 -#: pg_test_fsync.c:590 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "skrivning misslyckades" -#: pg_test_fsync.c:253 pg_test_fsync.c:372 pg_test_fsync.c:396 -#: pg_test_fsync.c:533 pg_test_fsync.c:565 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "fsync misslyckades" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "" "\n" @@ -127,7 +138,7 @@ msgstr "" "\n" "Jämför filsynkningsmetoder genom att använda en %dkB-skrivning:\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "" "\n" @@ -136,21 +147,21 @@ msgstr "" "\n" "Jämför filsynkningsmetoder genom att använda två %dkB-skrivningar:\n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format -msgid "(in wal_sync_method preference order, except fdatasync is Linux's default)\n" -msgstr "(i wal_sync_method inställningsordning, förutom att fdatasync är standard i Linux)\n" +msgid "(in \"wal_sync_method\" preference order, except fdatasync is Linux's default)\n" +msgstr "(i \"wal_sync_method\" inställningsordning, förutom att fdatasync är standard i Linux)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:413 pg_test_fsync.c:480 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "ej tillämpbar*" -#: pg_test_fsync.c:325 pg_test_fsync.c:351 pg_test_fsync.c:401 -#: pg_test_fsync.c:439 pg_test_fsync.c:498 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "ej tillämpbar" -#: pg_test_fsync.c:444 +#: pg_test_fsync.c:446 #, c-format msgid "" "* This file system and its mount options do not support direct\n" @@ -159,7 +170,7 @@ msgstr "" "* Detta filsystem och dess monteringsflaffor stöder inte\n" " direkt I/O, t.ex. ext4 i journalläge.\n" -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:454 #, c-format msgid "" "\n" @@ -168,7 +179,7 @@ msgstr "" "\n" "Jämför open_sync med olika skrivstorlekar:\n" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:455 #, c-format msgid "" "(This is designed to compare the cost of writing 16kB in different write\n" @@ -177,27 +188,27 @@ msgstr "" "(Detta är gjort för att jämföra kostnaden att skriva 16kB med olika\n" "open_sync skrivstorlekar.)\n" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr " 1 * 16kB open_sync skrivning" -#: pg_test_fsync.c:457 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr " 2 * 8kB open_sync skrivningar" -#: pg_test_fsync.c:458 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr " 4 * 4kB open_sync skrivningar" -#: pg_test_fsync.c:459 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr " 8 * 2kB open_sync skrivningar" -#: pg_test_fsync.c:460 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr "16 * 1kB open_sync skrivningar" -#: pg_test_fsync.c:514 +#: pg_test_fsync.c:516 #, c-format msgid "" "\n" @@ -206,7 +217,7 @@ msgstr "" "\n" "Testa om fsync på en icke skrivbar fildeskriptor respekteras:\n" -#: pg_test_fsync.c:515 +#: pg_test_fsync.c:517 #, c-format msgid "" "(If the times are similar, fsync() can sync data written on a different\n" @@ -215,7 +226,7 @@ msgstr "" "(Om tiderna är liknande, så kan fsync() synka data skriven på\n" "olika deskriptorer.)\n" -#: pg_test_fsync.c:580 +#: pg_test_fsync.c:582 #, c-format msgid "" "\n" @@ -223,7 +234,3 @@ msgid "" msgstr "" "\n" "Icke-synkade %dkB-skrivningar:\n" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Försök med \"%s --help\" för mer information.\n" diff --git a/src/bin/pg_test_fsync/po/uk.po b/src/bin/pg_test_fsync/po/uk.po index 00a789b1a426b..a633ea634bef1 100644 --- a/src/bin/pg_test_fsync/po/uk.po +++ b/src/bin/pg_test_fsync/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:51+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:24+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_test_fsync.pot\n" -"X-Crowdin-File-ID: 886\n" +"X-Crowdin-File: /REL_17_STABLE/pg_test_fsync.pot\n" +"X-Crowdin-File-ID: 1020\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,48 +37,59 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + #. translator: maintain alignment with NA_FORMAT -#: pg_test_fsync.c:32 +#: pg_test_fsync.c:38 #, c-format msgid "%13.3f ops/sec %6.0f usecs/op\n" msgstr "%13.3f оп/с %6.0f мкс/оп\n" -#: pg_test_fsync.c:50 +#: pg_test_fsync.c:56 #, c-format msgid "could not create thread for alarm" msgstr "не вдалося створити потік для сигналізації" -#: pg_test_fsync.c:95 +#: pg_test_fsync.c:101 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: pg_test_fsync.c:159 +#: pg_test_fsync.c:165 #, c-format msgid "Usage: %s [-f FILENAME] [-s SECS-PER-TEST]\n" msgstr "Використання: %s [-f FILENAME] [-s SECS-PER-TEST]\n" -#: pg_test_fsync.c:185 +#: pg_test_fsync.c:191 #, c-format msgid "invalid argument for option %s" msgstr "неприпустимий аргумент для параметру %s" -#: pg_test_fsync.c:186 pg_test_fsync.c:198 pg_test_fsync.c:207 +#: pg_test_fsync.c:192 pg_test_fsync.c:204 pg_test_fsync.c:213 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: pg_test_fsync.c:192 +#: pg_test_fsync.c:198 #, c-format msgid "%s must be in range %u..%u" msgstr "%s має бути в діапазоні %u..%u" -#: pg_test_fsync.c:205 +#: pg_test_fsync.c:211 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_test_fsync.c:211 +#: pg_test_fsync.c:217 #, c-format msgid "%u second per test\n" msgid_plural "%u seconds per test\n" @@ -87,122 +98,122 @@ msgstr[1] "%u секунди на тест\n" msgstr[2] "%u секунд на тест\n" msgstr[3] "%u секунд на тест\n" -#: pg_test_fsync.c:216 +#: pg_test_fsync.c:222 #, c-format msgid "O_DIRECT supported on this platform for open_datasync and open_sync.\n" msgstr "O_DIRECT на цій платформі підтримується для open_datasync і open_sync.\n" -#: pg_test_fsync.c:218 +#: pg_test_fsync.c:224 #, c-format msgid "F_NOCACHE supported on this platform for open_datasync and open_sync.\n" msgstr "F_NOCACHE підтримується на цій платформі для open_datasync і open_sync.\n" -#: pg_test_fsync.c:220 +#: pg_test_fsync.c:226 #, c-format msgid "Direct I/O is not supported on this platform.\n" msgstr "Пряме введення/виведення не підтримується на цій платформі.\n" -#: pg_test_fsync.c:245 pg_test_fsync.c:336 pg_test_fsync.c:361 -#: pg_test_fsync.c:385 pg_test_fsync.c:529 pg_test_fsync.c:541 -#: pg_test_fsync.c:557 pg_test_fsync.c:563 pg_test_fsync.c:585 +#: pg_test_fsync.c:251 pg_test_fsync.c:341 pg_test_fsync.c:363 +#: pg_test_fsync.c:387 pg_test_fsync.c:531 pg_test_fsync.c:543 +#: pg_test_fsync.c:559 pg_test_fsync.c:565 pg_test_fsync.c:587 msgid "could not open output file" msgstr "неможливо відкрити файл виводу" -#: pg_test_fsync.c:249 pg_test_fsync.c:319 pg_test_fsync.c:345 -#: pg_test_fsync.c:370 pg_test_fsync.c:394 pg_test_fsync.c:433 -#: pg_test_fsync.c:492 pg_test_fsync.c:531 pg_test_fsync.c:559 -#: pg_test_fsync.c:590 +#: pg_test_fsync.c:255 pg_test_fsync.c:325 pg_test_fsync.c:350 +#: pg_test_fsync.c:372 pg_test_fsync.c:396 pg_test_fsync.c:435 +#: pg_test_fsync.c:494 pg_test_fsync.c:533 pg_test_fsync.c:561 +#: pg_test_fsync.c:592 msgid "write failed" msgstr "записування не вдалося" -#: pg_test_fsync.c:253 pg_test_fsync.c:372 pg_test_fsync.c:396 -#: pg_test_fsync.c:533 pg_test_fsync.c:565 +#: pg_test_fsync.c:259 pg_test_fsync.c:374 pg_test_fsync.c:398 +#: pg_test_fsync.c:535 pg_test_fsync.c:567 msgid "fsync failed" msgstr "помилка fsync" -#: pg_test_fsync.c:292 +#: pg_test_fsync.c:298 #, c-format msgid "\n" "Compare file sync methods using one %dkB write:\n" msgstr "\n" "Порівнювання методів синхронізації файлу, використовуючи один запис %dkB:\n" -#: pg_test_fsync.c:294 +#: pg_test_fsync.c:300 #, c-format msgid "\n" "Compare file sync methods using two %dkB writes:\n" msgstr "\n" "Порівнювання методів синхронізації файлу, використовуючи два записи %dkB: \n" -#: pg_test_fsync.c:295 +#: pg_test_fsync.c:301 #, c-format -msgid "(in wal_sync_method preference order, except fdatasync is Linux's default)\n" -msgstr "(в порядку переваги для wal_sync_method, окрім переваги fdatasync в Linux)\n" +msgid "(in \"wal_sync_method\" preference order, except fdatasync is Linux's default)\n" +msgstr "(в порядку переваги для \"wal_sync_method\", окрім fdatasync за замовчуванням в Linux)\n" -#: pg_test_fsync.c:306 pg_test_fsync.c:413 pg_test_fsync.c:480 +#: pg_test_fsync.c:312 pg_test_fsync.c:415 pg_test_fsync.c:482 msgid "n/a*" msgstr "н/д*" -#: pg_test_fsync.c:325 pg_test_fsync.c:351 pg_test_fsync.c:401 -#: pg_test_fsync.c:439 pg_test_fsync.c:498 +#: pg_test_fsync.c:331 pg_test_fsync.c:403 pg_test_fsync.c:441 +#: pg_test_fsync.c:500 msgid "n/a" msgstr "н/д" -#: pg_test_fsync.c:444 +#: pg_test_fsync.c:446 #, c-format msgid "* This file system and its mount options do not support direct\n" " I/O, e.g. ext4 in journaled mode.\n" msgstr "* Ця файлова система з поточними параметрами монтування не підтримує\n" " пряме введення/виведення, наприклад, ext4 в режимі журналювання.\n" -#: pg_test_fsync.c:452 +#: pg_test_fsync.c:454 #, c-format msgid "\n" "Compare open_sync with different write sizes:\n" msgstr "\n" "Порівняння open_sync з різними розмірами записування:\n" -#: pg_test_fsync.c:453 +#: pg_test_fsync.c:455 #, c-format msgid "(This is designed to compare the cost of writing 16kB in different write\n" "open_sync sizes.)\n" msgstr "(Це створено для порівняння вартості запису 16 КБ з різними розмірами\n" "записування open_sync.)\n" -#: pg_test_fsync.c:456 +#: pg_test_fsync.c:458 msgid " 1 * 16kB open_sync write" msgstr " запис з open_sync 1 * 16 КБ" -#: pg_test_fsync.c:457 +#: pg_test_fsync.c:459 msgid " 2 * 8kB open_sync writes" msgstr " запис з open_sync 2 * 8 КБ" -#: pg_test_fsync.c:458 +#: pg_test_fsync.c:460 msgid " 4 * 4kB open_sync writes" msgstr " запис з open_sync 4 * 4 КБ" -#: pg_test_fsync.c:459 +#: pg_test_fsync.c:461 msgid " 8 * 2kB open_sync writes" msgstr " запис з open_sync 8 * 2 КБ" -#: pg_test_fsync.c:460 +#: pg_test_fsync.c:462 msgid "16 * 1kB open_sync writes" msgstr "запис з open_sync 16 * 1 КБ" -#: pg_test_fsync.c:514 +#: pg_test_fsync.c:516 #, c-format msgid "\n" "Test if fsync on non-write file descriptor is honored:\n" msgstr "\n" "Перевірка, чи здійснюється fsync з дескриптором файлу, відкритого не для запису:\n" -#: pg_test_fsync.c:515 +#: pg_test_fsync.c:517 #, c-format msgid "(If the times are similar, fsync() can sync data written on a different\n" "descriptor.)\n" msgstr "(Якщо час однаковий, fsync() може синхронізувати дані, записані іншим дескриптором.)\n" -#: pg_test_fsync.c:580 +#: pg_test_fsync.c:582 #, c-format msgid "\n" "Non-sync'ed %dkB writes:\n" diff --git a/src/bin/pg_test_fsync/t/001_basic.pl b/src/bin/pg_test_fsync/t/001_basic.pl index e9d2e5261dfe6..7eed51233c481 100644 --- a/src/bin/pg_test_fsync/t/001_basic.pl +++ b/src/bin/pg_test_fsync/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -18,11 +18,11 @@ # Test invalid option combinations command_fails_like( - [ 'pg_test_fsync', '--secs-per-test', 'a' ], + [ 'pg_test_fsync', '--secs-per-test' => 'a' ], qr/\Qpg_test_fsync: error: invalid argument for option --secs-per-test\E/, 'pg_test_fsync: invalid argument for option --secs-per-test'); command_fails_like( - [ 'pg_test_fsync', '--secs-per-test', '0' ], + [ 'pg_test_fsync', '--secs-per-test' => '0' ], qr/\Qpg_test_fsync: error: --secs-per-test must be in range 1..4294967295\E/, 'pg_test_fsync: --secs-per-test must be in range'); diff --git a/src/bin/pg_test_timing/meson.build b/src/bin/pg_test_timing/meson.build index 6dd3274d697bb..64550f5458f08 100644 --- a/src/bin/pg_test_timing/meson.build +++ b/src/bin/pg_test_timing/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_test_timing_sources = files( 'pg_test_timing.c' diff --git a/src/bin/pg_test_timing/po/es.po b/src/bin/pg_test_timing/po/es.po index 47cb27d9a0f69..c8de0f2c870c4 100644 --- a/src/bin/pg_test_timing/po/es.po +++ b/src/bin/pg_test_timing/po/es.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_test_timing (PostgreSQL) 16\n" +"Project-Id-Version: pg_test_timing (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:19+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:50+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -20,6 +20,17 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 2.4.2\n" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + #: pg_test_timing.c:59 #, c-format msgid "Usage: %s [-d DURATION]\n" diff --git a/src/bin/pg_test_timing/po/fr.po b/src/bin/pg_test_timing/po/fr.po index f97ebee84bdce..3be64c4b32ae5 100644 --- a/src/bin/pg_test_timing/po/fr.po +++ b/src/bin/pg_test_timing/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-08-22 10:20+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,7 +19,18 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" #: pg_test_timing.c:59 #, c-format @@ -85,6 +96,3 @@ msgstr "nombre" #, c-format msgid "Histogram of timing durations:\n" msgstr "Histogramme des durées de chronométrage\n" - -#~ msgid "%s: duration must be a positive integer (duration is \"%d\")\n" -#~ msgstr "%s : la durée doit être un entier positif (la durée est « %d »)\n" diff --git a/src/bin/pg_test_timing/po/ka.po b/src/bin/pg_test_timing/po/ka.po index a472b6c8bd75e..6fb64047ee36c 100644 --- a/src/bin/pg_test_timing/po/ka.po +++ b/src/bin/pg_test_timing/po/ka.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: pg_test_timing (PostgreSQL) 15\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-07-02 04:48+0000\n" +"POT-Creation-Date: 2024-07-01 03:51+0000\n" "PO-Revision-Date: 2022-07-04 11:40+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" @@ -18,6 +18,17 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.1\n" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + #: pg_test_timing.c:59 #, c-format msgid "Usage: %s [-d DURATION]\n" diff --git a/src/bin/pg_test_timing/po/ko.po b/src/bin/pg_test_timing/po/ko.po index 1f1da785b3fe8..69ac14f128670 100644 --- a/src/bin/pg_test_timing/po/ko.po +++ b/src/bin/pg_test_timing/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_test_timing (PostgreSQL) 16\n" +"Project-Id-Version: pg_test_timing (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:50+0000\n" -"PO-Revision-Date: 2023-05-30 12:39+0900\n" +"POT-Creation-Date: 2025-01-17 04:50+0000\n" +"PO-Revision-Date: 2025-01-16 11:07+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -17,6 +17,17 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + #: pg_test_timing.c:59 #, c-format msgid "Usage: %s [-d DURATION]\n" diff --git a/src/bin/pg_test_timing/po/meson.build b/src/bin/pg_test_timing/po/meson.build index 7bf27e012bdec..1de9f09083718 100644 --- a/src/bin/pg_test_timing/po/meson.build +++ b/src/bin/pg_test_timing/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_test_timing-' + pg_version_major.to_string())] diff --git a/src/bin/pg_test_timing/po/ru.po b/src/bin/pg_test_timing/po/ru.po index c24e78df428b3..6fdaef839baae 100644 --- a/src/bin/pg_test_timing/po/ru.po +++ b/src/bin/pg_test_timing/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for pg_test_timing # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2017, 2021. +# Alexander Lakhin , 2017, 2021, 2024. msgid "" msgstr "" "Project-Id-Version: pg_test_timing (PostgreSQL) 10\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 06:29+0300\n" -"PO-Revision-Date: 2021-09-04 12:18+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 19:59+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -17,6 +17,17 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + #: pg_test_timing.c:59 #, c-format msgid "Usage: %s [-d DURATION]\n" diff --git a/src/bin/pg_test_timing/po/sv.po b/src/bin/pg_test_timing/po/sv.po index 92c130dced6c3..d1fcae77547e8 100644 --- a/src/bin/pg_test_timing/po/sv.po +++ b/src/bin/pg_test_timing/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_test_timing # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 14\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-11-06 17:16+0000\n" -"PO-Revision-Date: 2021-11-06 21:59+0100\n" +"POT-Creation-Date: 2024-07-12 14:21+0000\n" +"PO-Revision-Date: 2024-07-12 19:07+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,6 +17,17 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + #: pg_test_timing.c:59 #, c-format msgid "Usage: %s [-d DURATION]\n" diff --git a/src/bin/pg_test_timing/po/uk.po b/src/bin/pg_test_timing/po/uk.po index 53135933aa4bf..52837fbbda2c1 100644 --- a/src/bin/pg_test_timing/po/uk.po +++ b/src/bin/pg_test_timing/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:49+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:21+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,19 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pg_test_timing.pot\n" -"X-Crowdin-File-ID: 912\n" +"X-Crowdin-File: /REL_17_STABLE/pg_test_timing.pot\n" +"X-Crowdin-File-ID: 1002\n" + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" #: pg_test_timing.c:59 #, c-format diff --git a/src/bin/pg_test_timing/t/001_basic.pl b/src/bin/pg_test_timing/t/001_basic.pl index e472954b14e3b..6554cd981af8f 100644 --- a/src/bin/pg_test_timing/t/001_basic.pl +++ b/src/bin/pg_test_timing/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -18,11 +18,11 @@ # Test invalid option combinations command_fails_like( - [ 'pg_test_timing', '--duration', 'a' ], + [ 'pg_test_timing', '--duration' => 'a' ], qr/\Qpg_test_timing: invalid argument for option --duration\E/, 'pg_test_timing: invalid argument for option --duration'); command_fails_like( - [ 'pg_test_timing', '--duration', '0' ], + [ 'pg_test_timing', '--duration' => '0' ], qr/\Qpg_test_timing: --duration must be in range 1..4294967295\E/, 'pg_test_timing: --duration must be in range'); diff --git a/src/bin/pg_upgrade/Makefile b/src/bin/pg_upgrade/Makefile index bde91e2beb82c..f83d2b5d30955 100644 --- a/src/bin/pg_upgrade/Makefile +++ b/src/bin/pg_upgrade/Makefile @@ -25,6 +25,7 @@ OBJS = \ relfilenumber.o \ server.o \ tablespace.o \ + task.o \ util.o \ version.o diff --git a/src/bin/pg_upgrade/TESTING b/src/bin/pg_upgrade/TESTING index 00842ac6ec3ab..c3d463c9c292f 100644 --- a/src/bin/pg_upgrade/TESTING +++ b/src/bin/pg_upgrade/TESTING @@ -20,13 +20,13 @@ export oldinstall=...otherversion/ (old version's install base path) See DETAILS below for more information about creation of the dump. You can also test the different transfer modes (--copy, --link, ---clone, --copy-file-range) by setting the environment variable +--clone, --copy-file-range, --swap) by setting the environment variable PG_TEST_PG_UPGRADE_MODE to the respective command-line option, like make check PG_TEST_PG_UPGRADE_MODE=--link -The default is --copy. Note that the other modes are not supported on -all operating systems. +The default is --copy. Note that not all modes are supported on all +operating systems. DETAILS ------- diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5038231731ff2..81865cd3e4859 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -3,7 +3,7 @@ * * server checks and output routines * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/check.c */ @@ -11,14 +11,13 @@ #include "catalog/pg_authid_d.h" #include "catalog/pg_class_d.h" -#include "catalog/pg_collation.h" #include "fe_utils/string_utils.h" -#include "mb/pg_wchar.h" #include "pg_upgrade.h" +#include "common/unicode_version.h" static void check_new_cluster_is_empty(void); static void check_is_install_user(ClusterInfo *cluster); -static void check_proper_datallowconn(ClusterInfo *cluster); +static void check_for_connection_status(ClusterInfo *cluster); static void check_for_prepared_transactions(ClusterInfo *cluster); static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster); static void check_for_user_defined_postfix_ops(ClusterInfo *cluster); @@ -27,6 +26,7 @@ static void check_for_tables_with_oids(ClusterInfo *cluster); static void check_for_pg_role_prefix(ClusterInfo *cluster); static void check_for_new_tablespace_dir(void); static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster); +static void check_for_unicode_update(ClusterInfo *cluster); static void check_new_cluster_logical_replication_slots(void); static void check_new_cluster_subscription_configuration(void); static void check_old_cluster_for_valid_slots(void); @@ -314,6 +314,132 @@ static DataTypesUsageChecks data_types_usage_checks[] = } }; +/* + * Private state for check_for_data_types_usage()'s UpgradeTask. + */ +struct data_type_check_state +{ + DataTypesUsageChecks *check; /* the check for this step */ + bool result; /* true if check failed for any database */ + PQExpBuffer *report; /* buffer for report on failed checks */ +}; + +/* + * Returns a palloc'd query string for the data type check, for use by + * check_for_data_types_usage()'s UpgradeTask. + */ +static char * +data_type_check_query(int checknum) +{ + DataTypesUsageChecks *check = &data_types_usage_checks[checknum]; + + return psprintf("WITH RECURSIVE oids AS ( " + /* start with the type(s) returned by base_query */ + " %s " + " UNION ALL " + " SELECT * FROM ( " + /* inner WITH because we can only reference the CTE once */ + " WITH x AS (SELECT oid FROM oids) " + /* domains on any type selected so far */ + " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' " + " UNION ALL " + /* arrays over any type selected so far */ + " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' " + " UNION ALL " + /* composite types containing any type selected so far */ + " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x " + " WHERE t.typtype = 'c' AND " + " t.oid = c.reltype AND " + " c.oid = a.attrelid AND " + " NOT a.attisdropped AND " + " a.atttypid = x.oid " + " UNION ALL " + /* ranges containing any type selected so far */ + " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x " + " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid" + " ) foo " + ") " + /* now look for stored columns of any such type */ + "SELECT n.nspname, c.relname, a.attname " + "FROM pg_catalog.pg_class c, " + " pg_catalog.pg_namespace n, " + " pg_catalog.pg_attribute a " + "WHERE c.oid = a.attrelid AND " + " NOT a.attisdropped AND " + " a.atttypid IN (SELECT oid FROM oids) AND " + " c.relkind IN (" + CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_MATVIEW) ", " + CppAsString2(RELKIND_INDEX) ") AND " + " c.relnamespace = n.oid AND " + /* exclude possible orphaned temp tables */ + " n.nspname !~ '^pg_temp_' AND " + " n.nspname !~ '^pg_toast_temp_' AND " + /* exclude system catalogs, too */ + " n.nspname NOT IN ('pg_catalog', 'information_schema')", + check->base_query); +} + +/* + * Callback function for processing results of queries for + * check_for_data_types_usage()'s UpgradeTask. If the query returned any rows + * (i.e., the check failed), write the details to the report file. + */ +static void +process_data_type_check(DbInfo *dbinfo, PGresult *res, void *arg) +{ + struct data_type_check_state *state = (struct data_type_check_state *) arg; + int ntups = PQntuples(res); + char output_path[MAXPGPATH]; + int i_nspname = PQfnumber(res, "nspname"); + int i_relname = PQfnumber(res, "relname"); + int i_attname = PQfnumber(res, "attname"); + FILE *script = NULL; + + AssertVariableIsOfType(&process_data_type_check, UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + snprintf(output_path, sizeof(output_path), "%s/%s", + log_opts.basedir, + state->check->report_filename); + + /* + * Make sure we have a buffer to save reports to now that we found a first + * failing check. + */ + if (*state->report == NULL) + *state->report = createPQExpBuffer(); + + /* + * If this is the first time we see an error for the check in question + * then print a status message of the failure. + */ + if (!state->result) + { + pg_log(PG_REPORT, "failed check: %s", _(state->check->status)); + appendPQExpBuffer(*state->report, "\n%s\n%s %s\n", + _(state->check->report_text), + _("A list of the problem columns is in the file:"), + output_path); + } + state->result = true; + + if ((script = fopen_priv(output_path, "a")) == NULL) + pg_fatal("could not open file \"%s\": %m", output_path); + + fprintf(script, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(script, " %s.%s.%s\n", + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_relname), + PQgetvalue(res, rowno, i_attname)); + + fclose(script); +} + /* * check_for_data_types_usage() * Detect whether there are any stored columns depending on given type(s) @@ -334,15 +460,16 @@ static DataTypesUsageChecks data_types_usage_checks[] = * there's no storage involved in a view. */ static void -check_for_data_types_usage(ClusterInfo *cluster, DataTypesUsageChecks *checks) +check_for_data_types_usage(ClusterInfo *cluster) { - bool found = false; - bool *results; - PQExpBufferData report; - DataTypesUsageChecks *tmp = checks; + PQExpBuffer report = NULL; + DataTypesUsageChecks *tmp = data_types_usage_checks; int n_data_types_usage_checks = 0; + UpgradeTask *task = upgrade_task_create(); + char **queries = NULL; + struct data_type_check_state *states; - prep_status("Checking for data type usage"); + prep_status("Checking data type usage"); /* Gather number of checks to perform */ while (tmp->status != NULL) @@ -351,177 +478,62 @@ check_for_data_types_usage(ClusterInfo *cluster, DataTypesUsageChecks *checks) tmp++; } - /* Prepare an array to store the results of checks in */ - results = pg_malloc0(sizeof(bool) * n_data_types_usage_checks); + /* Allocate memory for queries and for task states */ + queries = pg_malloc0(sizeof(char *) * n_data_types_usage_checks); + states = pg_malloc0(sizeof(struct data_type_check_state) * n_data_types_usage_checks); - /* - * Connect to each database in the cluster and run all defined checks - * against that database before trying the next one. - */ - for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) + for (int i = 0; i < n_data_types_usage_checks; i++) { - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); + DataTypesUsageChecks *check = &data_types_usage_checks[i]; - for (int checknum = 0; checknum < n_data_types_usage_checks; checknum++) + if (check->threshold_version == MANUAL_CHECK) { - PGresult *res; - int ntups; - int i_nspname; - int i_relname; - int i_attname; - FILE *script = NULL; - bool db_used = false; - char output_path[MAXPGPATH]; - DataTypesUsageChecks *cur_check = &checks[checknum]; - - if (cur_check->threshold_version == MANUAL_CHECK) - { - Assert(cur_check->version_hook); - - /* - * Make sure that the check applies to the current cluster - * version and skip if not. If no check hook has been defined - * we run the check for all versions. - */ - if (!cur_check->version_hook(cluster)) - continue; - } - else if (cur_check->threshold_version != ALL_VERSIONS) - { - if (GET_MAJOR_VERSION(cluster->major_version) > cur_check->threshold_version) - continue; - } - else - Assert(cur_check->threshold_version == ALL_VERSIONS); - - snprintf(output_path, sizeof(output_path), "%s/%s", - log_opts.basedir, - cur_check->report_filename); + Assert(check->version_hook); /* - * The type(s) of interest might be wrapped in a domain, array, - * composite, or range, and these container types can be nested - * (to varying extents depending on server version, but that's not - * of concern here). To handle all these cases we need a - * recursive CTE. + * Make sure that the check applies to the current cluster version + * and skip it if not. */ - res = executeQueryOrDie(conn, - "WITH RECURSIVE oids AS ( " - /* start with the type(s) returned by base_query */ - " %s " - " UNION ALL " - " SELECT * FROM ( " - /* inner WITH because we can only reference the CTE once */ - " WITH x AS (SELECT oid FROM oids) " - /* domains on any type selected so far */ - " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' " - " UNION ALL " - /* arrays over any type selected so far */ - " SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' " - " UNION ALL " - /* composite types containing any type selected so far */ - " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x " - " WHERE t.typtype = 'c' AND " - " t.oid = c.reltype AND " - " c.oid = a.attrelid AND " - " NOT a.attisdropped AND " - " a.atttypid = x.oid " - " UNION ALL " - /* ranges containing any type selected so far */ - " SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x " - " WHERE t.typtype = 'r' AND r.rngtypid = t.oid AND r.rngsubtype = x.oid" - " ) foo " - ") " - /* now look for stored columns of any such type */ - "SELECT n.nspname, c.relname, a.attname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_namespace n, " - " pg_catalog.pg_attribute a " - "WHERE c.oid = a.attrelid AND " - " NOT a.attisdropped AND " - " a.atttypid IN (SELECT oid FROM oids) AND " - " c.relkind IN (" - CppAsString2(RELKIND_RELATION) ", " - CppAsString2(RELKIND_MATVIEW) ", " - CppAsString2(RELKIND_INDEX) ") AND " - " c.relnamespace = n.oid AND " - /* exclude possible orphaned temp tables */ - " n.nspname !~ '^pg_temp_' AND " - " n.nspname !~ '^pg_toast_temp_' AND " - /* exclude system catalogs, too */ - " n.nspname NOT IN ('pg_catalog', 'information_schema')", - cur_check->base_query); - - ntups = PQntuples(res); + if (!check->version_hook(cluster)) + continue; + } + else if (check->threshold_version != ALL_VERSIONS) + { + if (GET_MAJOR_VERSION(cluster->major_version) > check->threshold_version) + continue; + } + else + Assert(check->threshold_version == ALL_VERSIONS); - /* - * The datatype was found, so extract the data and log to the - * requested filename. We need to open the file for appending - * since the check might have already found the type in another - * database earlier in the loop. - */ - if (ntups) - { - /* - * Make sure we have a buffer to save reports to now that we - * found a first failing check. - */ - if (!found) - initPQExpBuffer(&report); - found = true; - - /* - * If this is the first time we see an error for the check in - * question then print a status message of the failure. - */ - if (!results[checknum]) - { - pg_log(PG_REPORT, " failed check: %s", _(cur_check->status)); - appendPQExpBuffer(&report, "\n%s\n%s %s\n", - _(cur_check->report_text), - _("A list of the problem columns is in the file:"), - output_path); - } - results[checknum] = true; - - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - i_attname = PQfnumber(res, "attname"); - - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "a")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " %s.%s.%s\n", - PQgetvalue(res, rowno, i_nspname), - PQgetvalue(res, rowno, i_relname), - PQgetvalue(res, rowno, i_attname)); - } - - if (script) - { - fclose(script); - script = NULL; - } - } + queries[i] = data_type_check_query(i); - PQclear(res); - } + states[i].check = check; + states[i].report = &report; - PQfinish(conn); + upgrade_task_add_step(task, queries[i], process_data_type_check, + true, &states[i]); } - if (found) - pg_fatal("Data type checks failed: %s", report.data); + /* + * Connect to each database in the cluster and run all defined checks + * against that database before trying the next one. + */ + upgrade_task_run(task, cluster); + upgrade_task_free(task); - pg_free(results); + if (report) + { + pg_fatal("Data type checks failed: %s", report->data); + destroyPQExpBuffer(report); + } + + for (int i = 0; i < n_data_types_usage_checks; i++) + { + if (queries[i]) + pg_free(queries[i]); + } + pg_free(queries); + pg_free(states); check_ok(); } @@ -580,6 +592,12 @@ check_and_dump_old_cluster(void) if (!user_opts.live_check) start_postmaster(&old_cluster, true); + /* + * First check that all databases allow connections since we'll otherwise + * fail in later stages. + */ + check_for_connection_status(&old_cluster); + /* * Extract a list of databases, tables, and logical replication slots from * the old cluster. @@ -595,7 +613,6 @@ check_and_dump_old_cluster(void) * Check for various failure cases */ check_is_install_user(&old_cluster); - check_proper_datallowconn(&old_cluster); check_for_prepared_transactions(&old_cluster); check_for_isn_and_int8_passing_mismatch(&old_cluster); @@ -616,7 +633,13 @@ check_and_dump_old_cluster(void) check_old_cluster_subscription_state(); } - check_for_data_types_usage(&old_cluster, data_types_usage_checks); + check_for_data_types_usage(&old_cluster); + + /* + * Unicode updates can affect some objects that use expressions with + * functions dependent on Unicode. + */ + check_for_unicode_update(&old_cluster); /* * PG 14 changed the function signature of encoding conversion functions. @@ -694,7 +717,34 @@ check_new_cluster(void) check_copy_file_range(); break; case TRANSFER_MODE_LINK: - check_hard_link(); + check_hard_link(TRANSFER_MODE_LINK); + break; + case TRANSFER_MODE_SWAP: + + /* + * We do the hard link check for --swap, too, since it's an easy + * way to verify the clusters are in the same file system. This + * allows us to take some shortcuts in the file synchronization + * step. With some more effort, we could probably support the + * separate-file-system use case, but this mode is unlikely to + * offer much benefit if we have to copy the files across file + * system boundaries. + */ + check_hard_link(TRANSFER_MODE_SWAP); + + /* + * There are a few known issues with using --swap to upgrade from + * versions older than 10. For example, the sequence tuple format + * changed in v10, and the visibility map format changed in 9.6. + * While such problems are not insurmountable (and we may have to + * deal with similar problems in the future, anyway), it doesn't + * seem worth the effort to support swap mode for upgrades from + * long-unsupported versions. + */ + if (GET_MAJOR_VERSION(old_cluster.major_version) < 1000) + pg_fatal("Swap mode can only upgrade clusters from PostgreSQL version %s and later.", + "10"); + break; } @@ -764,9 +814,12 @@ output_completion_banner(char *deletion_script_file_name) } pg_log(PG_REPORT, - "Optimizer statistics are not transferred by pg_upgrade.\n" - "Once you start the new server, consider running:\n" - " %s/vacuumdb %s--all --analyze-in-stages", new_cluster.bindir, user_specification.data); + "Some statistics are not transferred by pg_upgrade.\n" + "Once you start the new server, consider running these two commands:\n" + " %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n" + " %s/vacuumdb %s--all --analyze-only", + new_cluster.bindir, user_specification.data, + new_cluster.bindir, user_specification.data); if (deletion_script_file_name) pg_log(PG_REPORT, @@ -823,6 +876,18 @@ check_cluster_versions(void) GET_MAJOR_VERSION(new_cluster.bin_version)) pg_fatal("New cluster data and binary directories are from different major versions."); + /* + * Since from version 18, newly created database clusters always have + * 'signed' default char-signedness, it makes less sense to use + * --set-char-signedness option for upgrading from version 18 or later. + * Users who want to change the default char signedness of the new + * cluster, they can use pg_resetwal manually before the upgrade. + */ + if (GET_MAJOR_VERSION(old_cluster.major_version) >= 1800 && + user_opts.char_signedness != -1) + pg_fatal("The option %s cannot be used for upgrades from PostgreSQL %s and later.", + "--set-char-signedness", "18"); + check_ok(); } @@ -909,6 +974,7 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name) int tblnum; char old_cluster_pgdata[MAXPGPATH], new_cluster_pgdata[MAXPGPATH]; + char *old_tblspc_suffix; *deletion_script_file_name = psprintf("%sdelete_old_cluster.%s", SCRIPT_PREFIX, SCRIPT_EXT); @@ -973,39 +1039,13 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name) fix_path_separator(old_cluster.pgdata), PATH_QUOTE); /* delete old cluster's alternate tablespaces */ + old_tblspc_suffix = pg_strdup(old_cluster.tablespace_suffix); + fix_path_separator(old_tblspc_suffix); for (tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++) - { - /* - * Do the old cluster's per-database directories share a directory - * with a new version-specific tablespace? - */ - if (strlen(old_cluster.tablespace_suffix) == 0) - { - /* delete per-database directories */ - int dbnum; - - fprintf(script, "\n"); - - for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) - fprintf(script, RMDIR_CMD " %c%s%c%u%c\n", PATH_QUOTE, - fix_path_separator(os_info.old_tablespaces[tblnum]), - PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid, - PATH_QUOTE); - } - else - { - char *suffix_path = pg_strdup(old_cluster.tablespace_suffix); - - /* - * Simply delete the tablespace directory, which might be ".old" - * or a version-specific subdirectory. - */ - fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE, - fix_path_separator(os_info.old_tablespaces[tblnum]), - fix_path_separator(suffix_path), PATH_QUOTE); - pfree(suffix_path); - } - } + fprintf(script, RMDIR_CMD " %c%s%s%c\n", PATH_QUOTE, + fix_path_separator(os_info.old_tablespaces[tblnum]), + old_tblspc_suffix, PATH_QUOTE); + pfree(old_tblspc_suffix); fclose(script); @@ -1077,14 +1117,14 @@ check_is_install_user(ClusterInfo *cluster) /* - * check_proper_datallowconn + * check_for_connection_status * * Ensure that all non-template0 databases allow connections since they * otherwise won't be restored; and that template0 explicitly doesn't allow * connections since it would make pg_dumpall --globals restore fail. */ static void -check_proper_datallowconn(ClusterInfo *cluster) +check_for_connection_status(ClusterInfo *cluster) { int dbnum; PGconn *conn_template1; @@ -1092,6 +1132,7 @@ check_proper_datallowconn(ClusterInfo *cluster) int ntups; int i_datname; int i_datallowconn; + int i_datconnlimit; FILE *script = NULL; char output_path[MAXPGPATH]; @@ -1099,23 +1140,25 @@ check_proper_datallowconn(ClusterInfo *cluster) snprintf(output_path, sizeof(output_path), "%s/%s", log_opts.basedir, - "databases_with_datallowconn_false.txt"); + "databases_cannot_connect_to.txt"); conn_template1 = connectToServer(cluster, "template1"); /* get database names */ dbres = executeQueryOrDie(conn_template1, - "SELECT datname, datallowconn " + "SELECT datname, datallowconn, datconnlimit " "FROM pg_catalog.pg_database"); i_datname = PQfnumber(dbres, "datname"); i_datallowconn = PQfnumber(dbres, "datallowconn"); + i_datconnlimit = PQfnumber(dbres, "datconnlimit"); ntups = PQntuples(dbres); for (dbnum = 0; dbnum < ntups; dbnum++) { char *datname = PQgetvalue(dbres, dbnum, i_datname); char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn); + char *datconnlimit = PQgetvalue(dbres, dbnum, i_datconnlimit); if (strcmp(datname, "template0") == 0) { @@ -1127,10 +1170,11 @@ check_proper_datallowconn(ClusterInfo *cluster) else { /* - * avoid datallowconn == false databases from being skipped on - * restore + * Avoid datallowconn == false databases from being skipped on + * restore, and ensure that no databases are marked invalid with + * datconnlimit == -2. */ - if (strcmp(datallowconn, "f") == 0) + if ((strcmp(datallowconn, "f") == 0) || strcmp(datconnlimit, "-2") == 0) { if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) pg_fatal("could not open file \"%s\": %m", output_path); @@ -1149,11 +1193,11 @@ check_proper_datallowconn(ClusterInfo *cluster) fclose(script); pg_log(PG_REPORT, "fatal"); pg_fatal("All non-template0 databases must allow connections, i.e. their\n" - "pg_database.datallowconn must be true. Your installation contains\n" - "non-template0 databases with their pg_database.datallowconn set to\n" - "false. Consider allowing connection for all non-template0 databases\n" - "or drop the databases which do not allow connections. A list of\n" - "databases with the problem is in the file:\n" + "pg_database.datallowconn must be true and pg_database.datconnlimit\n" + "must not be -2. Your installation contains non-template0 databases\n" + "which cannot be connected to. Consider allowing connection for all\n" + "non-template0 databases or drop the databases which do not allow\n" + "connections. A list of databases with the problem is in the file:\n" " %s", output_path); } else @@ -1194,6 +1238,37 @@ check_for_prepared_transactions(ClusterInfo *cluster) check_ok(); } +/* + * Callback function for processing result of query for + * check_for_isn_and_int8_passing_mismatch()'s UpgradeTask. If the query + * returned any rows (i.e., the check failed), write the details to the report + * file. + */ +static void +process_isn_and_int8_passing_mismatch(DbInfo *dbinfo, PGresult *res, void *arg) +{ + int ntups = PQntuples(res); + int i_nspname = PQfnumber(res, "nspname"); + int i_proname = PQfnumber(res, "proname"); + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + + AssertVariableIsOfType(&process_isn_and_int8_passing_mismatch, + UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " %s.%s\n", + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_proname)); +} /* * check_for_isn_and_int8_passing_mismatch() @@ -1205,9 +1280,13 @@ check_for_prepared_transactions(ClusterInfo *cluster) static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster) { - int dbnum; - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTask *task; + UpgradeTaskReport report; + const char *query = "SELECT n.nspname, p.proname " + "FROM pg_catalog.pg_proc p, " + " pg_catalog.pg_namespace n " + "WHERE p.pronamespace = n.oid AND " + " p.probin = '$libdir/isn'"; prep_status("Checking for contrib/isn with bigint-passing mismatch"); @@ -1219,54 +1298,20 @@ check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster) return; } - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "contrib_isn_and_int8_pass_by_value.txt"); - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_proname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* Find any functions coming from contrib/isn */ - res = executeQueryOrDie(conn, - "SELECT n.nspname, p.proname " - "FROM pg_catalog.pg_proc p, " - " pg_catalog.pg_namespace n " - "WHERE p.pronamespace = n.oid AND " - " p.probin = '$libdir/isn'"); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_proname = PQfnumber(res, "proname"); - for (rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " %s.%s\n", - PQgetvalue(res, rowno, i_nspname), - PQgetvalue(res, rowno, i_proname)); - } - - PQclear(res); - - PQfinish(conn); - } + task = upgrade_task_create(); + upgrade_task_add_step(task, query, process_isn_and_int8_passing_mismatch, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); - if (script) + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains \"contrib/isn\" functions which rely on the\n" "bigint data type. Your old and new clusters pass bigint values\n" @@ -1274,107 +1319,137 @@ check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster) "manually dump databases in the old cluster that use \"contrib/isn\"\n" "facilities, drop them, perform the upgrade, and then restore them. A\n" "list of the problem functions is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); } +/* + * Callback function for processing result of query for + * check_for_user_defined_postfix_ops()'s UpgradeTask. If the query returned + * any rows (i.e., the check failed), write the details to the report file. + */ +static void +process_user_defined_postfix_ops(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_oproid = PQfnumber(res, "oproid"); + int i_oprnsp = PQfnumber(res, "oprnsp"); + int i_oprname = PQfnumber(res, "oprname"); + int i_typnsp = PQfnumber(res, "typnsp"); + int i_typname = PQfnumber(res, "typname"); + + AssertVariableIsOfType(&process_user_defined_postfix_ops, + UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " (oid=%s) %s.%s (%s.%s, NONE)\n", + PQgetvalue(res, rowno, i_oproid), + PQgetvalue(res, rowno, i_oprnsp), + PQgetvalue(res, rowno, i_oprname), + PQgetvalue(res, rowno, i_typnsp), + PQgetvalue(res, rowno, i_typname)); +} + /* * Verify that no user defined postfix operators exist. */ static void check_for_user_defined_postfix_ops(ClusterInfo *cluster) { - int dbnum; - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTaskReport report; + UpgradeTask *task = upgrade_task_create(); + const char *query; + + /* + * The query below hardcodes FirstNormalObjectId as 16384 rather than + * interpolating that C #define into the query because, if that #define is + * ever changed, the cutoff we want to use is the value used by + * pre-version 14 servers, not that of some future version. + */ + query = "SELECT o.oid AS oproid, " + " n.nspname AS oprnsp, " + " o.oprname, " + " tn.nspname AS typnsp, " + " t.typname " + "FROM pg_catalog.pg_operator o, " + " pg_catalog.pg_namespace n, " + " pg_catalog.pg_type t, " + " pg_catalog.pg_namespace tn " + "WHERE o.oprnamespace = n.oid AND " + " o.oprleft = t.oid AND " + " t.typnamespace = tn.oid AND " + " o.oprright = 0 AND " + " o.oid >= 16384"; prep_status("Checking for user-defined postfix operators"); - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "postfix_ops.txt"); - /* Find any user defined postfix operators */ - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_oproid, - i_oprnsp, - i_oprname, - i_typnsp, - i_typname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* - * The query below hardcodes FirstNormalObjectId as 16384 rather than - * interpolating that C #define into the query because, if that - * #define is ever changed, the cutoff we want to use is the value - * used by pre-version 14 servers, not that of some future version. - */ - res = executeQueryOrDie(conn, - "SELECT o.oid AS oproid, " - " n.nspname AS oprnsp, " - " o.oprname, " - " tn.nspname AS typnsp, " - " t.typname " - "FROM pg_catalog.pg_operator o, " - " pg_catalog.pg_namespace n, " - " pg_catalog.pg_type t, " - " pg_catalog.pg_namespace tn " - "WHERE o.oprnamespace = n.oid AND " - " o.oprleft = t.oid AND " - " t.typnamespace = tn.oid AND " - " o.oprright = 0 AND " - " o.oid >= 16384"); - ntups = PQntuples(res); - i_oproid = PQfnumber(res, "oproid"); - i_oprnsp = PQfnumber(res, "oprnsp"); - i_oprname = PQfnumber(res, "oprname"); - i_typnsp = PQfnumber(res, "typnsp"); - i_typname = PQfnumber(res, "typname"); - for (rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && - (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " (oid=%s) %s.%s (%s.%s, NONE)\n", - PQgetvalue(res, rowno, i_oproid), - PQgetvalue(res, rowno, i_oprnsp), - PQgetvalue(res, rowno, i_oprname), - PQgetvalue(res, rowno, i_typnsp), - PQgetvalue(res, rowno, i_typname)); - } - - PQclear(res); - - PQfinish(conn); - } + upgrade_task_add_step(task, query, process_user_defined_postfix_ops, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); - if (script) + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains user-defined postfix operators, which are not\n" "supported anymore. Consider dropping the postfix operators and replacing\n" "them with prefix operators or function calls.\n" "A list of user-defined postfix operators is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); } +/* + * Callback function for processing results of query for + * check_for_incompatible_polymorphics()'s UpgradeTask. If the query returned + * any rows (i.e., the check failed), write the details to the report file. + */ +static void +process_incompat_polymorphics(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_objkind = PQfnumber(res, "objkind"); + int i_objname = PQfnumber(res, "objname"); + + AssertVariableIsOfType(&process_incompat_polymorphics, + UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " %s: %s\n", + PQgetvalue(res, rowno, i_objkind), + PQgetvalue(res, rowno, i_objname)); +} + /* * check_for_incompatible_polymorphics() * @@ -1384,14 +1459,15 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster) static void check_for_incompatible_polymorphics(ClusterInfo *cluster) { - PGresult *res; - FILE *script = NULL; - char output_path[MAXPGPATH]; PQExpBufferData old_polymorphics; + UpgradeTask *task = upgrade_task_create(); + UpgradeTaskReport report; + char *query; prep_status("Checking for incompatible polymorphic functions"); - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "incompatible_polymorphics.txt"); @@ -1415,80 +1491,51 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) ", 'array_positions(anyarray,anyelement)'" ", 'width_bucket(anyelement,anyarray)'"); - for (int dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - bool db_used = false; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - int ntups; - int i_objkind, - i_objname; - - /* - * The query below hardcodes FirstNormalObjectId as 16384 rather than - * interpolating that C #define into the query because, if that - * #define is ever changed, the cutoff we want to use is the value - * used by pre-version 14 servers, not that of some future version. - */ - res = executeQueryOrDie(conn, - /* Aggregate transition functions */ - "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname " - "FROM pg_proc AS p " - "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid " - "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn " - "WHERE p.oid >= 16384 " - "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) " - "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) " - - /* Aggregate final functions */ - "UNION ALL " - "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname " - "FROM pg_proc AS p " - "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid " - "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn " - "WHERE p.oid >= 16384 " - "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) " - "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) " - - /* Operators */ - "UNION ALL " - "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname " - "FROM pg_operator AS op " - "WHERE op.oid >= 16384 " - "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) " - "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);", - old_polymorphics.data, - old_polymorphics.data, - old_polymorphics.data); - - ntups = PQntuples(res); - - i_objkind = PQfnumber(res, "objkind"); - i_objname = PQfnumber(res, "objname"); - - for (int rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && - (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - - fprintf(script, " %s: %s\n", - PQgetvalue(res, rowno, i_objkind), - PQgetvalue(res, rowno, i_objname)); - } - - PQclear(res); - PQfinish(conn); - } + /* + * The query below hardcodes FirstNormalObjectId as 16384 rather than + * interpolating that C #define into the query because, if that #define is + * ever changed, the cutoff we want to use is the value used by + * pre-version 14 servers, not that of some future version. + */ - if (script) + /* Aggregate transition functions */ + query = psprintf("SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname " + "FROM pg_proc AS p " + "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid " + "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn " + "WHERE p.oid >= 16384 " + "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) " + "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) " + + /* Aggregate final functions */ + "UNION ALL " + "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname " + "FROM pg_proc AS p " + "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid " + "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn " + "WHERE p.oid >= 16384 " + "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) " + "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) " + + /* Operators */ + "UNION ALL " + "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname " + "FROM pg_operator AS op " + "WHERE op.oid >= 16384 " + "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) " + "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[])", + old_polymorphics.data, + old_polymorphics.data, + old_polymorphics.data); + + upgrade_task_add_step(task, query, process_incompat_polymorphics, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); + + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains user-defined objects that refer to internal\n" "polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n" @@ -1496,12 +1543,43 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) "afterwards, changing them to refer to the new corresponding functions with\n" "arguments of type \"anycompatiblearray\" and \"anycompatible\".\n" "A list of the problematic objects is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); termPQExpBuffer(&old_polymorphics); + pg_free(query); +} + +/* + * Callback function for processing results of query for + * check_for_tables_with_oids()'s UpgradeTask. If the query returned any rows + * (i.e., the check failed), write the details to the report file. + */ +static void +process_with_oids_check(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_nspname = PQfnumber(res, "nspname"); + int i_relname = PQfnumber(res, "relname"); + + AssertVariableIsOfType(&process_with_oids_check, UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " %s.%s\n", + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_relname)); } /* @@ -1510,67 +1588,36 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster) static void check_for_tables_with_oids(ClusterInfo *cluster) { - int dbnum; - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTaskReport report; + UpgradeTask *task = upgrade_task_create(); + const char *query = "SELECT n.nspname, c.relname " + "FROM pg_catalog.pg_class c, " + " pg_catalog.pg_namespace n " + "WHERE c.relnamespace = n.oid AND " + " c.relhasoids AND" + " n.nspname NOT IN ('pg_catalog')"; prep_status("Checking for tables WITH OIDS"); - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "tables_with_oids.txt"); - /* Find any tables declared WITH OIDS */ - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_nspname, - i_relname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - res = executeQueryOrDie(conn, - "SELECT n.nspname, c.relname " - "FROM pg_catalog.pg_class c, " - " pg_catalog.pg_namespace n " - "WHERE c.relnamespace = n.oid AND " - " c.relhasoids AND" - " n.nspname NOT IN ('pg_catalog')"); - - ntups = PQntuples(res); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - for (rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " %s.%s\n", - PQgetvalue(res, rowno, i_nspname), - PQgetvalue(res, rowno, i_relname)); - } - - PQclear(res); + upgrade_task_add_step(task, query, process_with_oids_check, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); - PQfinish(conn); - } - - if (script) + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains tables declared WITH OIDS, which is not\n" "supported anymore. Consider removing the oid column using\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "A list of tables with the problem is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); @@ -1634,82 +1681,262 @@ check_for_pg_role_prefix(ClusterInfo *cluster) check_ok(); } +/* + * Callback function for processing results of query for + * check_for_user_defined_encoding_conversions()'s UpgradeTask. If the query + * returned any rows (i.e., the check failed), write the details to the report + * file. + */ +static void +process_user_defined_encoding_conversions(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_conoid = PQfnumber(res, "conoid"); + int i_conname = PQfnumber(res, "conname"); + int i_nspname = PQfnumber(res, "nspname"); + + AssertVariableIsOfType(&process_user_defined_encoding_conversions, + UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " (oid=%s) %s.%s\n", + PQgetvalue(res, rowno, i_conoid), + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_conname)); +} + /* * Verify that no user-defined encoding conversions exist. */ static void check_for_user_defined_encoding_conversions(ClusterInfo *cluster) { - int dbnum; - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTaskReport report; + UpgradeTask *task = upgrade_task_create(); + const char *query; prep_status("Checking for user-defined encoding conversions"); - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "encoding_conversions.txt"); - /* Find any user defined encoding conversions */ - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_conoid, - i_conname, - i_nspname; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* - * The query below hardcodes FirstNormalObjectId as 16384 rather than - * interpolating that C #define into the query because, if that - * #define is ever changed, the cutoff we want to use is the value - * used by pre-version 14 servers, not that of some future version. - */ - res = executeQueryOrDie(conn, - "SELECT c.oid as conoid, c.conname, n.nspname " - "FROM pg_catalog.pg_conversion c, " - " pg_catalog.pg_namespace n " - "WHERE c.connamespace = n.oid AND " - " c.oid >= 16384"); - ntups = PQntuples(res); - i_conoid = PQfnumber(res, "conoid"); - i_conname = PQfnumber(res, "conname"); - i_nspname = PQfnumber(res, "nspname"); - for (rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && - (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - fprintf(script, "In database: %s\n", active_db->db_name); - db_used = true; - } - fprintf(script, " (oid=%s) %s.%s\n", - PQgetvalue(res, rowno, i_conoid), - PQgetvalue(res, rowno, i_nspname), - PQgetvalue(res, rowno, i_conname)); - } - - PQclear(res); - - PQfinish(conn); - } - - if (script) + /* + * The query below hardcodes FirstNormalObjectId as 16384 rather than + * interpolating that C #define into the query because, if that #define is + * ever changed, the cutoff we want to use is the value used by + * pre-version 14 servers, not that of some future version. + */ + query = "SELECT c.oid as conoid, c.conname, n.nspname " + "FROM pg_catalog.pg_conversion c, " + " pg_catalog.pg_namespace n " + "WHERE c.connamespace = n.oid AND " + " c.oid >= 16384"; + + upgrade_task_add_step(task, query, + process_user_defined_encoding_conversions, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); + + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains user-defined encoding conversions.\n" "The conversion function parameters changed in PostgreSQL version 14\n" "so this cluster cannot currently be upgraded. You can remove the\n" "encoding conversions in the old cluster and restart the upgrade.\n" "A list of user-defined encoding conversions is in the file:\n" - " %s", output_path); + " %s", report.path); + } + else + check_ok(); +} + +/* + * Callback function for processing results of query for + * check_for_unicode_update()'s UpgradeTask. If the query returned any rows + * (i.e., the check failed), write the details to the report file. + */ +static void +process_unicode_update(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_reloid = PQfnumber(res, "reloid"); + int i_nspname = PQfnumber(res, "nspname"); + int i_relname = PQfnumber(res, "relname"); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + fprintf(report->file, "In database: %s\n", dbinfo->db_name); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, " (oid=%s) %s.%s\n", + PQgetvalue(res, rowno, i_reloid), + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_relname)); +} + +/* + * Check if the Unicode version built into Postgres changed between the old + * cluster and the new cluster. + */ +static bool +unicode_version_changed(ClusterInfo *cluster) +{ + PGconn *conn_template1 = connectToServer(cluster, "template1"); + PGresult *res; + char *old_unicode_version; + bool unicode_updated; + + res = executeQueryOrDie(conn_template1, "SELECT unicode_version()"); + old_unicode_version = PQgetvalue(res, 0, 0); + unicode_updated = (strcmp(old_unicode_version, PG_UNICODE_VERSION) != 0); + + PQclear(res); + PQfinish(conn_template1); + + return unicode_updated; +} + +/* + * check_for_unicode_update() + * + * Check if the version of Unicode in the old server and the new server + * differ. If so, check for indexes, partitioned tables, or constraints that + * use expressions with functions dependent on Unicode behavior. + */ +static void +check_for_unicode_update(ClusterInfo *cluster) +{ + UpgradeTaskReport report; + UpgradeTask *task; + const char *query; + + /* + * The builtin provider did not exist prior to version 17. While there are + * still problems that could potentially be caught from earlier versions, + * such as an index on NORMALIZE(), we don't check for that here. + */ + if (GET_MAJOR_VERSION(cluster->major_version) < 1700) + return; + + prep_status("Checking for objects affected by Unicode update"); + + if (!unicode_version_changed(cluster)) + { + check_ok(); + return; + } + + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", + log_opts.basedir, + "unicode_dependent_rels.txt"); + + query = + /* collations that use built-in Unicode for character semantics */ + "WITH collations(collid) AS ( " + " SELECT oid FROM pg_collation " + " WHERE collprovider='b' AND colllocale IN ('C.UTF-8','PG_UNICODE_FAST') " + /* include default collation, if appropriate */ + " UNION " + " SELECT 'pg_catalog.default'::regcollation FROM pg_database " + " WHERE datname = current_database() AND " + " datlocprovider='b' AND datlocale IN ('C.UTF-8','PG_UNICODE_FAST') " + "), " + /* functions that use built-in Unicode */ + "functions(procid) AS ( " + " SELECT proc.oid FROM pg_proc proc " + " WHERE proname IN ('normalize','unicode_assigned','unicode_version','is_normalized') AND " + " pronamespace='pg_catalog'::regnamespace " + "), " + /* operators that use the input collation for character semantics */ + "coll_operators(operid, procid, collid) AS ( " + " SELECT oper.oid, oper.oprcode, collid FROM pg_operator oper, collations " + " WHERE oprname IN ('~', '~*', '!~', '!~*', '~~*', '!~~*') AND " + " oprnamespace='pg_catalog'::regnamespace AND " + " oprright='text'::regtype " + "), " + /* functions that use the input collation for character semantics */ + "coll_functions(procid, collid) AS ( " + " SELECT proc.oid, collid FROM pg_proc proc, collations " + " WHERE proname IN ('lower','initcap','upper') AND " + " pronamespace='pg_catalog'::regnamespace AND " + " proargtypes[0] = 'text'::regtype " + /* include functions behind the operators listed above */ + " UNION " + " SELECT procid, collid FROM coll_operators " + "), " + + /* + * Generate patterns to search a pg_node_tree for the above functions and + * operators. + */ + "patterns(p) AS ( " + " SELECT '{FUNCEXPR :funcid ' || procid::text || '[ }]' FROM functions " + " UNION " + " SELECT '{OPEXPR :opno ' || operid::text || ' (:\\w+ \\w+ )*' || " + " ':inputcollid ' || collid::text || '[ }]' FROM coll_operators " + " UNION " + " SELECT '{FUNCEXPR :funcid ' || procid::text || ' (:\\w+ \\w+ )*' || " + " ':inputcollid ' || collid::text || '[ }]' FROM coll_functions " + ") " + + /* + * Match the patterns against expressions used for relation contents. + */ + "SELECT reloid, relkind, nspname, relname " + " FROM ( " + " SELECT conrelid " + " FROM pg_constraint, patterns WHERE conbin::text ~ p " + " UNION " + " SELECT indexrelid " + " FROM pg_index, patterns WHERE indexprs::text ~ p OR indpred::text ~ p " + " UNION " + " SELECT partrelid " + " FROM pg_partitioned_table, patterns WHERE partexprs::text ~ p " + " UNION " + " SELECT ev_class " + " FROM pg_rewrite, pg_class, patterns " + " WHERE ev_class = pg_class.oid AND relkind = 'm' AND ev_action::text ~ p" + " ) s(reloid), pg_class c, pg_namespace n, pg_database d " + " WHERE s.reloid = c.oid AND c.relnamespace = n.oid AND " + " d.datname = current_database() AND " + " d.encoding = pg_char_to_encoding('UTF8');"; + + task = upgrade_task_create(); + upgrade_task_add_step(task, query, + process_unicode_update, + true, &report); + upgrade_task_run(task, cluster); + upgrade_task_free(task); + + if (report.file) + { + fclose(report.file); + report_status(PG_WARNING, "warning"); + pg_log(PG_WARNING, "Your installation contains relations that might be affected by a new version of Unicode.\n" + "A list of potentially-affected relations is in the file:\n" + " %s", report.path); } else check_ok(); @@ -1756,7 +1983,7 @@ check_new_cluster_logical_replication_slots(void) nslots_on_new = atoi(PQgetvalue(res, 0, 0)); if (nslots_on_new) - pg_fatal("Expected 0 logical replication slots but found %d.", + pg_fatal("expected 0 logical replication slots but found %d", nslots_on_new); PQclear(res); @@ -1771,7 +1998,7 @@ check_new_cluster_logical_replication_slots(void) wal_level = PQgetvalue(res, 0, 0); if (strcmp(wal_level, "logical") != 0) - pg_fatal("\"wal_level\" must be \"logical\", but is set to \"%s\"", + pg_fatal("\"wal_level\" must be \"logical\" but is set to \"%s\"", wal_level); max_replication_slots = atoi(PQgetvalue(res, 1, 0)); @@ -1790,16 +2017,16 @@ check_new_cluster_logical_replication_slots(void) /* * check_new_cluster_subscription_configuration() * - * Verify that the max_replication_slots configuration specified is enough for - * creating the subscriptions. This is required to create the replication - * origin for each subscription. + * Verify that the max_active_replication_origins configuration specified is + * enough for creating the subscriptions. This is required to create the + * replication origin for each subscription. */ static void check_new_cluster_subscription_configuration(void) { PGresult *res; PGconn *conn; - int max_replication_slots; + int max_active_replication_origins; /* Subscriptions and their dependencies can be migrated since PG17. */ if (GET_MAJOR_VERSION(old_cluster.major_version) < 1700) @@ -1814,16 +2041,16 @@ check_new_cluster_subscription_configuration(void) conn = connectToServer(&new_cluster, "template1"); res = executeQueryOrDie(conn, "SELECT setting FROM pg_settings " - "WHERE name = 'max_replication_slots';"); + "WHERE name = 'max_active_replication_origins';"); if (PQntuples(res) != 1) pg_fatal("could not determine parameter settings on new cluster"); - max_replication_slots = atoi(PQgetvalue(res, 0, 0)); - if (old_cluster.nsubs > max_replication_slots) - pg_fatal("\"max_replication_slots\" (%d) must be greater than or equal to the number of " + max_active_replication_origins = atoi(PQgetvalue(res, 0, 0)); + if (old_cluster.nsubs > max_active_replication_origins) + pg_fatal("\"max_active_replication_origins\" (%d) must be greater than or equal to the number of " "subscriptions (%d) on the old cluster", - max_replication_slots, old_cluster.nsubs); + max_active_replication_origins, old_cluster.nsubs); PQclear(res); PQfinish(conn); @@ -1895,7 +2122,7 @@ check_old_cluster_for_valid_slots(void) fclose(script); pg_log(PG_REPORT, "fatal"); - pg_fatal("Your installation contains logical replication slots that can't be upgraded.\n" + pg_fatal("Your installation contains logical replication slots that cannot be upgraded.\n" "You can remove invalid slots and/or consume the pending WAL for other slots,\n" "and then restart the upgrade.\n" "A list of the problematic slots is in the file:\n" @@ -1905,6 +2132,39 @@ check_old_cluster_for_valid_slots(void) check_ok(); } +/* + * Callback function for processing results of query for + * check_old_cluster_subscription_state()'s UpgradeTask. If the query returned + * any rows (i.e., the check failed), write the details to the report file. + */ +static void +process_old_sub_state_check(DbInfo *dbinfo, PGresult *res, void *arg) +{ + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + int ntups = PQntuples(res); + int i_srsubstate = PQfnumber(res, "srsubstate"); + int i_subname = PQfnumber(res, "subname"); + int i_nspname = PQfnumber(res, "nspname"); + int i_relname = PQfnumber(res, "relname"); + + AssertVariableIsOfType(&process_old_sub_state_check, UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + for (int i = 0; i < ntups; i++) + fprintf(report->file, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n", + PQgetvalue(res, i, i_srsubstate), + dbinfo->db_name, + PQgetvalue(res, i, i_subname), + PQgetvalue(res, i, i_nspname), + PQgetvalue(res, i, i_relname)); +} + /* * check_old_cluster_subscription_state() * @@ -1915,115 +2175,99 @@ check_old_cluster_for_valid_slots(void) static void check_old_cluster_subscription_state(void) { - FILE *script = NULL; - char output_path[MAXPGPATH]; + UpgradeTask *task = upgrade_task_create(); + UpgradeTaskReport report; + const char *query; + PGresult *res; + PGconn *conn; int ntup; prep_status("Checking for subscription state"); - snprintf(output_path, sizeof(output_path), "%s/%s", + report.file = NULL; + snprintf(report.path, sizeof(report.path), "%s/%s", log_opts.basedir, "subs_invalid.txt"); - for (int dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) - { - PGresult *res; - DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(&old_cluster, active_db->db_name); - - /* We need to check for pg_replication_origin only once. */ - if (dbnum == 0) - { - /* - * Check that all the subscriptions have their respective - * replication origin. - */ - res = executeQueryOrDie(conn, - "SELECT d.datname, s.subname " - "FROM pg_catalog.pg_subscription s " - "LEFT OUTER JOIN pg_catalog.pg_replication_origin o " - " ON o.roname = 'pg_' || s.oid " - "INNER JOIN pg_catalog.pg_database d " - " ON d.oid = s.subdbid " - "WHERE o.roname IS NULL;"); - - ntup = PQntuples(res); - for (int i = 0; i < ntup; i++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - fprintf(script, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n", - PQgetvalue(res, i, 0), - PQgetvalue(res, i, 1)); - } - PQclear(res); - } - - /* - * We don't allow upgrade if there is a risk of dangling slot or - * origin corresponding to initial sync after upgrade. - * - * A slot/origin not created yet refers to the 'i' (initialize) state, - * while 'r' (ready) state refers to a slot/origin created previously - * but already dropped. These states are supported for pg_upgrade. The - * other states listed below are not supported: - * - * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state - * would retain a replication slot, which could not be dropped by the - * sync worker spawned after the upgrade because the subscription ID - * used for the slot name won't match anymore. - * - * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state - * would retain the replication origin when there is a failure in - * tablesync worker immediately after dropping the replication slot in - * the publisher. - * - * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on - * a relation upgraded while in this state would expect an origin ID - * with the OID of the subscription used before the upgrade, causing - * it to fail. - * - * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and - * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, - * so we need not allow these states. - */ - res = executeQueryOrDie(conn, - "SELECT r.srsubstate, s.subname, n.nspname, c.relname " - "FROM pg_catalog.pg_subscription_rel r " - "LEFT JOIN pg_catalog.pg_subscription s" - " ON r.srsubid = s.oid " - "LEFT JOIN pg_catalog.pg_class c" - " ON r.srrelid = c.oid " - "LEFT JOIN pg_catalog.pg_namespace n" - " ON c.relnamespace = n.oid " - "WHERE r.srsubstate NOT IN ('i', 'r') " - "ORDER BY s.subname"); - - ntup = PQntuples(res); - for (int i = 0; i < ntup; i++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - - fprintf(script, "The table sync state \"%s\" is not allowed for database:\"%s\" subscription:\"%s\" schema:\"%s\" relation:\"%s\"\n", - PQgetvalue(res, i, 0), - active_db->db_name, - PQgetvalue(res, i, 1), - PQgetvalue(res, i, 2), - PQgetvalue(res, i, 3)); - } - PQclear(res); - PQfinish(conn); + /* + * Check that all the subscriptions have their respective replication + * origin. This check only needs to run once. + */ + conn = connectToServer(&old_cluster, old_cluster.dbarr.dbs[0].db_name); + res = executeQueryOrDie(conn, + "SELECT d.datname, s.subname " + "FROM pg_catalog.pg_subscription s " + "LEFT OUTER JOIN pg_catalog.pg_replication_origin o " + " ON o.roname = 'pg_' || s.oid " + "INNER JOIN pg_catalog.pg_database d " + " ON d.oid = s.subdbid " + "WHERE o.roname IS NULL;"); + ntup = PQntuples(res); + for (int i = 0; i < ntup; i++) + { + if (report.file == NULL && + (report.file = fopen_priv(report.path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report.path); + fprintf(report.file, "The replication origin is missing for database:\"%s\" subscription:\"%s\"\n", + PQgetvalue(res, i, 0), + PQgetvalue(res, i, 1)); } + PQclear(res); + PQfinish(conn); - if (script) + /* + * We don't allow upgrade if there is a risk of dangling slot or origin + * corresponding to initial sync after upgrade. + * + * A slot/origin not created yet refers to the 'i' (initialize) state, + * while 'r' (ready) state refers to a slot/origin created previously but + * already dropped. These states are supported for pg_upgrade. The other + * states listed below are not supported: + * + * a) SUBREL_STATE_DATASYNC: A relation upgraded while in this state would + * retain a replication slot, which could not be dropped by the sync + * worker spawned after the upgrade because the subscription ID used for + * the slot name won't match anymore. + * + * b) SUBREL_STATE_SYNCDONE: A relation upgraded while in this state would + * retain the replication origin when there is a failure in tablesync + * worker immediately after dropping the replication slot in the + * publisher. + * + * c) SUBREL_STATE_FINISHEDCOPY: A tablesync worker spawned to work on a + * relation upgraded while in this state would expect an origin ID with + * the OID of the subscription used before the upgrade, causing it to + * fail. + * + * d) SUBREL_STATE_SYNCWAIT, SUBREL_STATE_CATCHUP and + * SUBREL_STATE_UNKNOWN: These states are not stored in the catalog, so we + * need not allow these states. + */ + query = "SELECT r.srsubstate, s.subname, n.nspname, c.relname " + "FROM pg_catalog.pg_subscription_rel r " + "LEFT JOIN pg_catalog.pg_subscription s" + " ON r.srsubid = s.oid " + "LEFT JOIN pg_catalog.pg_class c" + " ON r.srrelid = c.oid " + "LEFT JOIN pg_catalog.pg_namespace n" + " ON c.relnamespace = n.oid " + "WHERE r.srsubstate NOT IN ('i', 'r') " + "ORDER BY s.subname"; + + upgrade_task_add_step(task, query, process_old_sub_state_check, + true, &report); + + upgrade_task_run(task, &old_cluster); + upgrade_task_free(task); + + if (report.file) { - fclose(script); + fclose(report.file); pg_log(PG_REPORT, "fatal"); pg_fatal("Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" "You can allow the initial sync to finish for all relations and then restart the upgrade.\n" "A list of the problematic subscriptions is in the file:\n" - " %s", output_path); + " %s", report.path); } else check_ok(); diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index 854c6887a23e0..90cef0864de7c 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -3,14 +3,16 @@ * * controldata functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/controldata.c */ #include "postgres_fe.h" #include +#include /* for CHAR_MIN */ +#include "access/xlog_internal.h" #include "common/string.h" #include "pg_upgrade.h" @@ -62,6 +64,7 @@ get_control_data(ClusterInfo *cluster) bool got_date_is_int = false; bool got_data_checksum_version = false; bool got_cluster_state = false; + bool got_default_char_signedness = false; char *lc_collate = NULL; char *lc_ctype = NULL; char *lc_monetary = NULL; @@ -501,6 +504,25 @@ get_control_data(ClusterInfo *cluster) cluster->controldata.data_checksum_version = str2uint(p); got_data_checksum_version = true; } + else if ((p = strstr(bufin, "Default char data signedness:")) != NULL) + { + p = strchr(p, ':'); + + if (p == NULL || strlen(p) <= 1) + pg_fatal("%d: controldata retrieval problem", __LINE__); + + /* Skip the colon and any whitespace after it */ + p++; + while (isspace((unsigned char) *p)) + p++; + + /* The value should be either 'signed' or 'unsigned' */ + if (strcmp(p, "signed") != 0 && strcmp(p, "unsigned") != 0) + pg_fatal("%d: controldata retrieval problem", __LINE__); + + cluster->controldata.default_char_signedness = strcmp(p, "signed") == 0; + got_default_char_signedness = true; + } } rc = pclose(output); @@ -561,6 +583,21 @@ get_control_data(ClusterInfo *cluster) } } + /* + * Pre-v18 database clusters don't have the default char signedness + * information. We use the char signedness of the platform where + * pg_upgrade was built. + */ + if (cluster->controldata.cat_ver < DEFAULT_CHAR_SIGNEDNESS_CAT_VER) + { + Assert(!got_default_char_signedness); +#if CHAR_MIN != 0 + cluster->controldata.default_char_signedness = true; +#else + cluster->controldata.default_char_signedness = false; +#endif + } + /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || !got_multi || !got_oldestxid || @@ -572,7 +609,9 @@ get_control_data(ClusterInfo *cluster) !got_index || !got_toast || (!got_large_object && cluster->controldata.ctrl_ver >= LARGE_OBJECT_SIZE_PG_CONTROL_VER) || - !got_date_is_int || !got_data_checksum_version) + !got_date_is_int || !got_data_checksum_version || + (!got_default_char_signedness && + cluster->controldata.cat_ver >= DEFAULT_CHAR_SIGNEDNESS_CAT_VER)) { if (cluster == &old_cluster) pg_log(PG_REPORT, @@ -641,6 +680,10 @@ get_control_data(ClusterInfo *cluster) if (!got_data_checksum_version) pg_log(PG_REPORT, " data checksum version"); + /* value added in Postgres 18 */ + if (!got_default_char_signedness) + pg_log(PG_REPORT, " default char signedness"); + pg_fatal("Cannot continue without required control information, terminating"); } } @@ -709,25 +752,34 @@ check_control_data(ControlData *oldctrl, void -disable_old_cluster(void) +disable_old_cluster(transferMode transfer_mode) { char old_path[MAXPGPATH], new_path[MAXPGPATH]; /* rename pg_control so old server cannot be accidentally started */ - prep_status("Adding \".old\" suffix to old global/pg_control"); + /* translator: %s is the file path of the control file */ + prep_status("Adding \".old\" suffix to old \"%s\"", XLOG_CONTROL_FILE); - snprintf(old_path, sizeof(old_path), "%s/global/pg_control", old_cluster.pgdata); - snprintf(new_path, sizeof(new_path), "%s/global/pg_control.old", old_cluster.pgdata); + snprintf(old_path, sizeof(old_path), "%s/%s", old_cluster.pgdata, XLOG_CONTROL_FILE); + snprintf(new_path, sizeof(new_path), "%s/%s.old", old_cluster.pgdata, XLOG_CONTROL_FILE); if (pg_mv_file(old_path, new_path) != 0) pg_fatal("could not rename file \"%s\" to \"%s\": %m", old_path, new_path); check_ok(); - pg_log(PG_REPORT, "\n" - "If you want to start the old cluster, you will need to remove\n" - "the \".old\" suffix from %s/global/pg_control.old.\n" - "Because \"link\" mode was used, the old cluster cannot be safely\n" - "started once the new cluster has been started.", - old_cluster.pgdata); + if (transfer_mode == TRANSFER_MODE_LINK) + /* translator: %s/%s is the file path of the control file */ + pg_log(PG_REPORT, "\n" + "If you want to start the old cluster, you will need to remove\n" + "the \".old\" suffix from \"%s/%s.old\".\n" + "Because \"link\" mode was used, the old cluster cannot be safely\n" + "started once the new cluster has been started.", + old_cluster.pgdata, XLOG_CONTROL_FILE); + else if (transfer_mode == TRANSFER_MODE_SWAP) + pg_log(PG_REPORT, "\n" + "Because \"swap\" mode was used, the old cluster can no longer be\n" + "safely started."); + else + pg_fatal("unrecognized transfer mode"); } diff --git a/src/bin/pg_upgrade/dump.c b/src/bin/pg_upgrade/dump.c index 8345f55be8a35..183f08ce1e86f 100644 --- a/src/bin/pg_upgrade/dump.c +++ b/src/bin/pg_upgrade/dump.c @@ -3,7 +3,7 @@ * * dump functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/dump.c */ @@ -52,10 +52,13 @@ generate_old_dump(void) snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid); parallel_exec_prog(log_file_name, NULL, - "\"%s/pg_dump\" %s --schema-only --quote-all-identifiers " + "\"%s/pg_dump\" %s --no-data %s %s --quote-all-identifiers " "--binary-upgrade --format=custom %s --no-sync --file=\"%s/%s\" %s", new_cluster.bindir, cluster_conn_opts(&old_cluster), + (user_opts.transfer_mode == TRANSFER_MODE_SWAP) ? + "" : "--sequence-data", log_opts.verbose ? "--verbose" : "", + user_opts.do_statistics ? "--with-statistics" : "--no-statistics", log_opts.dumpdir, sql_file_name, escaped_connstr.data); diff --git a/src/bin/pg_upgrade/exec.c b/src/bin/pg_upgrade/exec.c index 058530ab3e9e6..63f2815a7cd10 100644 --- a/src/bin/pg_upgrade/exec.c +++ b/src/bin/pg_upgrade/exec.c @@ -3,7 +3,7 @@ * * execution functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/exec.c */ @@ -350,7 +350,7 @@ check_data_dir(ClusterInfo *cluster) check_single_dir(pg_data, "global"); check_single_dir(pg_data, "pg_multixact"); check_single_dir(pg_data, "pg_subtrans"); - check_single_dir(pg_data, "pg_tblspc"); + check_single_dir(pg_data, PG_TBLSPC_DIR); check_single_dir(pg_data, "pg_twophase"); /* pg_xlog has been renamed to pg_wal in v10 */ diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 73932504caefa..91ed16acb088f 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -3,7 +3,7 @@ * * file system operations * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/file.c */ @@ -434,7 +434,7 @@ check_copy_file_range(void) } void -check_hard_link(void) +check_hard_link(transferMode transfer_mode) { char existing_file[MAXPGPATH]; char new_link_file[MAXPGPATH]; @@ -444,8 +444,16 @@ check_hard_link(void) unlink(new_link_file); /* might fail */ if (link(existing_file, new_link_file) < 0) - pg_fatal("could not create hard link between old and new data directories: %m\n" - "In link mode the old and new data directories must be on the same file system."); + { + if (transfer_mode == TRANSFER_MODE_LINK) + pg_fatal("could not create hard link between old and new data directories: %m\n" + "In link mode the old and new data directories must be on the same file system."); + else if (transfer_mode == TRANSFER_MODE_SWAP) + pg_fatal("could not create hard link between old and new data directories: %m\n" + "In swap mode the old and new data directories must be on the same file system."); + else + pg_fatal("unrecognized transfer mode"); + } unlink(new_link_file); } diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index 7e3abed0985d5..9ad53caeebc9d 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -3,7 +3,7 @@ * * server-side function support * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/function.c */ @@ -42,6 +42,30 @@ library_name_compare(const void *p1, const void *p2) ((const LibraryInfo *) p2)->dbnum); } +/* + * Private state for get_loadable_libraries()'s UpgradeTask. + */ +struct loadable_libraries_state +{ + PGresult **ress; /* results for each database */ + int totaltups; /* number of tuples in all results */ +}; + +/* + * Callback function for processing results of query for + * get_loadable_libraries()'s UpgradeTask. This function stores the results + * for later use within get_loadable_libraries(). + */ +static void +process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg) +{ + struct loadable_libraries_state *state = (struct loadable_libraries_state *) arg; + + AssertVariableIsOfType(&process_loadable_libraries, UpgradeTaskProcessCB); + + state->ress[dbinfo - old_cluster.dbarr.dbs] = res; + state->totaltups += PQntuples(res); +} /* * get_loadable_libraries() @@ -54,47 +78,41 @@ library_name_compare(const void *p1, const void *p2) void get_loadable_libraries(void) { - PGresult **ress; int totaltups; int dbnum; int n_libinfos; + UpgradeTask *task = upgrade_task_create(); + struct loadable_libraries_state state; + char *query; - ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *)); - totaltups = 0; + state.ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *)); + state.totaltups = 0; - /* Fetch all library names, removing duplicates within each DB */ - for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) - { - DbInfo *active_db = &old_cluster.dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(&old_cluster, active_db->db_name); + query = psprintf("SELECT DISTINCT probin " + "FROM pg_catalog.pg_proc " + "WHERE prolang = %u AND " + "probin IS NOT NULL AND " + "oid >= %u", + ClanguageId, + FirstNormalObjectId); - /* - * Fetch all libraries containing non-built-in C functions in this DB. - */ - ress[dbnum] = executeQueryOrDie(conn, - "SELECT DISTINCT probin " - "FROM pg_catalog.pg_proc " - "WHERE prolang = %u AND " - "probin IS NOT NULL AND " - "oid >= %u;", - ClanguageId, - FirstNormalObjectId); - totaltups += PQntuples(ress[dbnum]); - - PQfinish(conn); - } + upgrade_task_add_step(task, query, process_loadable_libraries, + false, &state); + + upgrade_task_run(task, &old_cluster); + upgrade_task_free(task); /* * Allocate memory for required libraries and logical replication output * plugins. */ - n_libinfos = totaltups + count_old_cluster_logical_slots(); + n_libinfos = state.totaltups + count_old_cluster_logical_slots(); os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos); totaltups = 0; for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) { - PGresult *res = ress[dbnum]; + PGresult *res = state.ress[dbnum]; int ntups; int rowno; LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr; @@ -129,7 +147,8 @@ get_loadable_libraries(void) } } - pg_free(ress); + pg_free(state.ress); + pg_free(query); os_info.num_libraries = totaltups; } diff --git a/src/bin/pg_upgrade/info.c b/src/bin/pg_upgrade/info.c index 5de5e109452fe..4b7a56f5b3be4 100644 --- a/src/bin/pg_upgrade/info.c +++ b/src/bin/pg_upgrade/info.c @@ -3,7 +3,7 @@ * * information support functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/info.c */ @@ -12,6 +12,7 @@ #include "access/transam.h" #include "catalog/pg_class_d.h" #include "pg_upgrade.h" +#include "pqexpbuffer.h" static void create_rel_filename_map(const char *old_data, const char *new_data, const DbInfo *old_db, const DbInfo *new_db, @@ -22,12 +23,14 @@ static void report_unmatched_relation(const RelInfo *rel, const DbInfo *db, static void free_db_and_rel_infos(DbInfoArr *db_arr); static void get_template0_info(ClusterInfo *cluster); static void get_db_infos(ClusterInfo *cluster); -static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo); +static char *get_rel_infos_query(void); +static void process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg); static void free_rel_infos(RelInfoArr *rel_arr); static void print_db_infos(DbInfoArr *db_arr); static void print_rel_infos(RelInfoArr *rel_arr); static void print_slot_infos(LogicalSlotInfoArr *slot_arr); -static void get_old_cluster_logical_slot_infos(DbInfo *dbinfo); +static char *get_old_cluster_logical_slot_infos_query(void); +static void process_old_cluster_logical_slot_infos(DbInfo *dbinfo, PGresult *res, void *arg); /* @@ -276,7 +279,9 @@ report_unmatched_relation(const RelInfo *rel, const DbInfo *db, bool is_new_db) void get_db_rel_and_slot_infos(ClusterInfo *cluster) { - int dbnum; + UpgradeTask *task = upgrade_task_create(); + char *rel_infos_query = NULL; + char *logical_slot_infos_query = NULL; if (cluster->dbarr.dbs != NULL) free_db_and_rel_infos(&cluster->dbarr); @@ -284,15 +289,37 @@ get_db_rel_and_slot_infos(ClusterInfo *cluster) get_template0_info(cluster); get_db_infos(cluster); - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) + rel_infos_query = get_rel_infos_query(); + upgrade_task_add_step(task, + rel_infos_query, + process_rel_infos, + true, NULL); + + /* + * Logical slots are only carried over to the new cluster when the old + * cluster is on PG17 or newer. This is because before that the logical + * slots are not saved at shutdown, so there is no guarantee that the + * latest confirmed_flush_lsn is saved to disk which can lead to data + * loss. It is still not guaranteed for manually created slots in PG17, so + * subsequent checks done in check_old_cluster_for_valid_slots() would + * raise a FATAL error if such slots are included. + */ + if (cluster == &old_cluster && + GET_MAJOR_VERSION(cluster->major_version) > 1600) { - DbInfo *pDbInfo = &cluster->dbarr.dbs[dbnum]; + logical_slot_infos_query = get_old_cluster_logical_slot_infos_query(); + upgrade_task_add_step(task, + logical_slot_infos_query, + process_old_cluster_logical_slot_infos, + true, NULL); + } - get_rel_infos(cluster, pDbInfo); + upgrade_task_run(task, cluster); + upgrade_task_free(task); - if (cluster == &old_cluster) - get_old_cluster_logical_slot_infos(pDbInfo); - } + pg_free(rel_infos_query); + if (logical_slot_infos_query) + pg_free(logical_slot_infos_query); if (cluster == &old_cluster) pg_log(PG_VERBOSE, "\nsource databases:"); @@ -431,40 +458,21 @@ get_db_infos(ClusterInfo *cluster) /* - * get_rel_infos() + * get_rel_infos_query() * - * gets the relinfos for all the user tables and indexes of the database - * referred to by "dbinfo". + * Returns the query for retrieving the relation information for all the user + * tables and indexes in the database, for use by get_db_rel_and_slot_infos()'s + * UpgradeTask. * - * Note: the resulting RelInfo array is assumed to be sorted by OID. - * This allows later processing to match up old and new databases efficiently. + * Note: the result is assumed to be sorted by OID. This allows later + * processing to match up old and new databases efficiently. */ -static void -get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo) +static char * +get_rel_infos_query(void) { - PGconn *conn = connectToServer(cluster, - dbinfo->db_name); - PGresult *res; - RelInfo *relinfos; - int ntups; - int relnum; - int num_rels = 0; - char *nspname = NULL; - char *relname = NULL; - char *tablespace = NULL; - int i_spclocation, - i_nspname, - i_relname, - i_reloid, - i_indtable, - i_toastheap, - i_relfilenumber, - i_reltablespace; - char query[QUERY_ALLOC]; - char *last_namespace = NULL, - *last_tablespace = NULL; + PQExpBufferData query; - query[0] = '\0'; /* initialize query string to empty */ + initPQExpBuffer(&query); /* * Create a CTE that collects OIDs of regular user tables and matviews, @@ -476,34 +484,36 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo) * output, so we have to copy that system table. It's easiest to do that * by treating it as a user table. */ - snprintf(query + strlen(query), sizeof(query) - strlen(query), - "WITH regular_heap (reloid, indtable, toastheap) AS ( " - " SELECT c.oid, 0::oid, 0::oid " - " FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n " - " ON c.relnamespace = n.oid " - " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", " - CppAsString2(RELKIND_MATVIEW) ") AND " + appendPQExpBuffer(&query, + "WITH regular_heap (reloid, indtable, toastheap) AS ( " + " SELECT c.oid, 0::oid, 0::oid " + " FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n " + " ON c.relnamespace = n.oid " + " WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_MATVIEW) "%s) AND " /* exclude possible orphaned temp tables */ - " ((n.nspname !~ '^pg_temp_' AND " - " n.nspname !~ '^pg_toast_temp_' AND " - " n.nspname NOT IN ('pg_catalog', 'information_schema', " - " 'binary_upgrade', 'pg_toast') AND " - " c.oid >= %u::pg_catalog.oid) OR " - " (n.nspname = 'pg_catalog' AND " - " relname IN ('pg_largeobject') ))), ", - FirstNormalObjectId); + " ((n.nspname !~ '^pg_temp_' AND " + " n.nspname !~ '^pg_toast_temp_' AND " + " n.nspname NOT IN ('pg_catalog', 'information_schema', " + " 'binary_upgrade', 'pg_toast') AND " + " c.oid >= %u::pg_catalog.oid) OR " + " (n.nspname = 'pg_catalog' AND " + " relname IN ('pg_largeobject') ))), ", + (user_opts.transfer_mode == TRANSFER_MODE_SWAP) ? + ", " CppAsString2(RELKIND_SEQUENCE) : "", + FirstNormalObjectId); /* * Add a CTE that collects OIDs of toast tables belonging to the tables * selected by the regular_heap CTE. (We have to do this separately * because the namespace-name rules above don't work for toast tables.) */ - snprintf(query + strlen(query), sizeof(query) - strlen(query), - " toast_heap (reloid, indtable, toastheap) AS ( " - " SELECT c.reltoastrelid, 0::oid, c.oid " - " FROM regular_heap JOIN pg_catalog.pg_class c " - " ON regular_heap.reloid = c.oid " - " WHERE c.reltoastrelid != 0), "); + appendPQExpBufferStr(&query, + " toast_heap (reloid, indtable, toastheap) AS ( " + " SELECT c.reltoastrelid, 0::oid, c.oid " + " FROM regular_heap JOIN pg_catalog.pg_class c " + " ON regular_heap.reloid = c.oid " + " WHERE c.reltoastrelid != 0), "); /* * Add a CTE that collects OIDs of all valid indexes on the previously @@ -511,53 +521,68 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo) * Testing indisready is necessary in 9.2, and harmless in earlier/later * versions. */ - snprintf(query + strlen(query), sizeof(query) - strlen(query), - " all_index (reloid, indtable, toastheap) AS ( " - " SELECT indexrelid, indrelid, 0::oid " - " FROM pg_catalog.pg_index " - " WHERE indisvalid AND indisready " - " AND indrelid IN " - " (SELECT reloid FROM regular_heap " - " UNION ALL " - " SELECT reloid FROM toast_heap)) "); + appendPQExpBufferStr(&query, + " all_index (reloid, indtable, toastheap) AS ( " + " SELECT indexrelid, indrelid, 0::oid " + " FROM pg_catalog.pg_index " + " WHERE indisvalid AND indisready " + " AND indrelid IN " + " (SELECT reloid FROM regular_heap " + " UNION ALL " + " SELECT reloid FROM toast_heap)) "); /* * And now we can write the query that retrieves the data we want for each * heap and index relation. Make sure result is sorted by OID. */ - snprintf(query + strlen(query), sizeof(query) - strlen(query), - "SELECT all_rels.*, n.nspname, c.relname, " - " c.relfilenode, c.reltablespace, " - " pg_catalog.pg_tablespace_location(t.oid) AS spclocation " - "FROM (SELECT * FROM regular_heap " - " UNION ALL " - " SELECT * FROM toast_heap " - " UNION ALL " - " SELECT * FROM all_index) all_rels " - " JOIN pg_catalog.pg_class c " - " ON all_rels.reloid = c.oid " - " JOIN pg_catalog.pg_namespace n " - " ON c.relnamespace = n.oid " - " LEFT OUTER JOIN pg_catalog.pg_tablespace t " - " ON c.reltablespace = t.oid " - "ORDER BY 1;"); - - res = executeQueryOrDie(conn, "%s", query); - - ntups = PQntuples(res); + appendPQExpBufferStr(&query, + "SELECT all_rels.*, n.nspname, c.relname, " + " c.relfilenode, c.reltablespace, " + " pg_catalog.pg_tablespace_location(t.oid) AS spclocation " + "FROM (SELECT * FROM regular_heap " + " UNION ALL " + " SELECT * FROM toast_heap " + " UNION ALL " + " SELECT * FROM all_index) all_rels " + " JOIN pg_catalog.pg_class c " + " ON all_rels.reloid = c.oid " + " JOIN pg_catalog.pg_namespace n " + " ON c.relnamespace = n.oid " + " LEFT OUTER JOIN pg_catalog.pg_tablespace t " + " ON c.reltablespace = t.oid " + "ORDER BY 1"); + + return query.data; +} - relinfos = (RelInfo *) pg_malloc(sizeof(RelInfo) * ntups); +/* + * Callback function for processing results of the query returned by + * get_rel_infos_query(), which is used for get_db_rel_and_slot_infos()'s + * UpgradeTask. This function stores the relation information for later use. + */ +static void +process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg) +{ + int ntups = PQntuples(res); + RelInfo *relinfos = (RelInfo *) pg_malloc(sizeof(RelInfo) * ntups); + int i_reloid = PQfnumber(res, "reloid"); + int i_indtable = PQfnumber(res, "indtable"); + int i_toastheap = PQfnumber(res, "toastheap"); + int i_nspname = PQfnumber(res, "nspname"); + int i_relname = PQfnumber(res, "relname"); + int i_relfilenumber = PQfnumber(res, "relfilenode"); + int i_reltablespace = PQfnumber(res, "reltablespace"); + int i_spclocation = PQfnumber(res, "spclocation"); + int num_rels = 0; + char *nspname = NULL; + char *relname = NULL; + char *tablespace = NULL; + char *last_namespace = NULL; + char *last_tablespace = NULL; - i_reloid = PQfnumber(res, "reloid"); - i_indtable = PQfnumber(res, "indtable"); - i_toastheap = PQfnumber(res, "toastheap"); - i_nspname = PQfnumber(res, "nspname"); - i_relname = PQfnumber(res, "relname"); - i_relfilenumber = PQfnumber(res, "relfilenode"); - i_reltablespace = PQfnumber(res, "reltablespace"); - i_spclocation = PQfnumber(res, "spclocation"); + AssertVariableIsOfType(&process_rel_infos, UpgradeTaskProcessCB); - for (relnum = 0; relnum < ntups; relnum++) + for (int relnum = 0; relnum < ntups; relnum++) { RelInfo *curr = &relinfos[num_rels++]; @@ -610,44 +635,22 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo) /* A zero reltablespace oid indicates the database tablespace. */ curr->tablespace = dbinfo->db_tablespace; } - PQclear(res); - - PQfinish(conn); dbinfo->rel_arr.rels = relinfos; dbinfo->rel_arr.nrels = num_rels; } /* - * get_old_cluster_logical_slot_infos() - * - * Gets the LogicalSlotInfos for all the logical replication slots of the - * database referred to by "dbinfo". The status of each logical slot is gotten - * here, but they are used at the checking phase. See - * check_old_cluster_for_valid_slots(). + * get_old_cluster_logical_slot_infos_query() * - * Note: This function will not do anything if the old cluster is pre-PG17. - * This is because before that the logical slots are not saved at shutdown, so - * there is no guarantee that the latest confirmed_flush_lsn is saved to disk - * which can lead to data loss. It is still not guaranteed for manually created - * slots in PG17, so subsequent checks done in - * check_old_cluster_for_valid_slots() would raise a FATAL error if such slots - * are included. + * Returns the query for retrieving the logical slot information for all the + * logical replication slots in the database, for use by + * get_db_rel_and_slot_infos()'s UpgradeTask. The status of each logical slot + * is checked in check_old_cluster_for_valid_slots(). */ -static void -get_old_cluster_logical_slot_infos(DbInfo *dbinfo) +static char * +get_old_cluster_logical_slot_infos_query(void) { - PGconn *conn; - PGresult *res; - LogicalSlotInfo *slotinfos = NULL; - int num_slots; - - /* Logical slots can be migrated since PG17. */ - if (GET_MAJOR_VERSION(old_cluster.major_version) <= 1600) - return; - - conn = connectToServer(&old_cluster, dbinfo->db_name); - /* * Fetch the logical replication slot information. The check whether the * slot is considered caught up is done by an upgrade function. This @@ -665,18 +668,32 @@ get_old_cluster_logical_slot_infos(DbInfo *dbinfo) * started and stopped several times causing any temporary slots to be * removed. */ - res = executeQueryOrDie(conn, "SELECT slot_name, plugin, two_phase, failover, " - "%s as caught_up, invalidation_reason IS NOT NULL as invalid " - "FROM pg_catalog.pg_replication_slots " - "WHERE slot_type = 'logical' AND " - "database = current_database() AND " - "temporary IS FALSE;", - user_opts.live_check ? "FALSE" : - "(CASE WHEN invalidation_reason IS NOT NULL THEN FALSE " - "ELSE (SELECT pg_catalog.binary_upgrade_logical_slot_has_caught_up(slot_name)) " - "END)"); - - num_slots = PQntuples(res); + return psprintf("SELECT slot_name, plugin, two_phase, failover, " + "%s as caught_up, invalidation_reason IS NOT NULL as invalid " + "FROM pg_catalog.pg_replication_slots " + "WHERE slot_type = 'logical' AND " + "database = current_database() AND " + "temporary IS FALSE;", + user_opts.live_check ? "FALSE" : + "(CASE WHEN invalidation_reason IS NOT NULL THEN FALSE " + "ELSE (SELECT pg_catalog.binary_upgrade_logical_slot_has_caught_up(slot_name)) " + "END)"); +} + +/* + * Callback function for processing results of the query returned by + * get_old_cluster_logical_slot_infos_query(), which is used for + * get_db_rel_and_slot_infos()'s UpgradeTask. This function stores the logical + * slot information for later use. + */ +static void +process_old_cluster_logical_slot_infos(DbInfo *dbinfo, PGresult *res, void *arg) +{ + LogicalSlotInfo *slotinfos = NULL; + int num_slots = PQntuples(res); + + AssertVariableIsOfType(&process_old_cluster_logical_slot_infos, + UpgradeTaskProcessCB); if (num_slots) { @@ -709,9 +726,6 @@ get_old_cluster_logical_slot_infos(DbInfo *dbinfo) } } - PQclear(res); - PQfinish(conn); - dbinfo->slot_arr.slots = slotinfos; dbinfo->slot_arr.nslots = num_slots; } @@ -827,13 +841,13 @@ print_slot_infos(LogicalSlotInfoArr *slot_arr) if (slot_arr->nslots == 0) return; - pg_log(PG_VERBOSE, "Logical replication slots within the database:"); + pg_log(PG_VERBOSE, "Logical replication slots in the database:"); for (int slotnum = 0; slotnum < slot_arr->nslots; slotnum++) { LogicalSlotInfo *slot_info = &slot_arr->slots[slotnum]; - pg_log(PG_VERBOSE, "slot_name: \"%s\", plugin: \"%s\", two_phase: %s", + pg_log(PG_VERBOSE, "slot name: \"%s\", output plugin: \"%s\", two_phase: %s", slot_info->slotname, slot_info->plugin, slot_info->two_phase ? "true" : "false"); diff --git a/src/bin/pg_upgrade/meson.build b/src/bin/pg_upgrade/meson.build index 9825fa3305466..ac992f0d14b1d 100644 --- a/src/bin/pg_upgrade/meson.build +++ b/src/bin/pg_upgrade/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_upgrade_sources = files( 'check.c', @@ -14,6 +14,7 @@ pg_upgrade_sources = files( 'relfilenumber.c', 'server.c', 'tablespace.c', + 'task.c', 'util.c', 'version.c', ) @@ -44,6 +45,8 @@ tests += { 't/002_pg_upgrade.pl', 't/003_logical_slots.pl', 't/004_subscription.pl', + 't/005_char_signedness.pl', + 't/006_transfer_modes.pl', ], 'test_kwargs': {'priority': 40}, # pg_upgrade tests are slow }, diff --git a/src/bin/pg_upgrade/nls.mk b/src/bin/pg_upgrade/nls.mk index db5aa18013b05..d4ae1a95eb5b0 100644 --- a/src/bin/pg_upgrade/nls.mk +++ b/src/bin/pg_upgrade/nls.mk @@ -13,6 +13,7 @@ GETTEXT_FILES = check.c \ relfilenumber.c \ server.c \ tablespace.c \ + task.c \ util.c \ version.c \ ../../common/fe_memutils.c \ diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c index 6f41d63eed431..7fd7f1d33fcb8 100644 --- a/src/bin/pg_upgrade/option.c +++ b/src/bin/pg_upgrade/option.c @@ -3,7 +3,7 @@ * * options functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/option.c */ @@ -60,6 +60,9 @@ parseCommandLine(int argc, char *argv[]) {"copy", no_argument, NULL, 2}, {"copy-file-range", no_argument, NULL, 3}, {"sync-method", required_argument, NULL, 4}, + {"no-statistics", no_argument, NULL, 5}, + {"set-char-signedness", required_argument, NULL, 6}, + {"swap", no_argument, NULL, 7}, {NULL, 0, NULL, 0} }; @@ -70,6 +73,8 @@ parseCommandLine(int argc, char *argv[]) user_opts.do_sync = true; user_opts.transfer_mode = TRANSFER_MODE_COPY; + user_opts.do_statistics = true; + user_opts.char_signedness = -1; os_info.progname = get_progname(argv[0]); @@ -212,6 +217,23 @@ parseCommandLine(int argc, char *argv[]) user_opts.sync_method = pg_strdup(optarg); break; + case 5: + user_opts.do_statistics = false; + break; + + case 6: + if (pg_strcasecmp(optarg, "signed") == 0) + user_opts.char_signedness = 1; + else if (pg_strcasecmp(optarg, "unsigned") == 0) + user_opts.char_signedness = 0; + else + pg_fatal("invalid argument for option %s", "--set-char-signedness"); + break; + + case 7: + user_opts.transfer_mode = TRANSFER_MODE_SWAP; + break; + default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), os_info.progname); @@ -306,6 +328,10 @@ usage(void) printf(_(" --clone clone instead of copying files to new cluster\n")); printf(_(" --copy copy files to new cluster (default)\n")); printf(_(" --copy-file-range copy files to new cluster with copy_file_range\n")); + printf(_(" --no-statistics do not import statistics from old cluster\n")); + printf(_(" --set-char-signedness=OPTION set new cluster char signedness to \"signed\" or\n" + " \"unsigned\"\n")); + printf(_(" --swap move data directories to new cluster\n")); printf(_(" --sync-method=METHOD set method for syncing files to disk\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\n" diff --git a/src/bin/pg_upgrade/parallel.c b/src/bin/pg_upgrade/parallel.c index 05313a9b15641..056aa2edaee3f 100644 --- a/src/bin/pg_upgrade/parallel.c +++ b/src/bin/pg_upgrade/parallel.c @@ -3,7 +3,7 @@ * * multi-process support * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/parallel.c */ @@ -24,7 +24,7 @@ static int parallel_jobs; * it can be passed to WaitForMultipleObjects(). We use two arrays * so the thread_handles array can be passed to WaitForMultipleObjects(). */ -HANDLE *thread_handles; +static HANDLE *thread_handles; typedef struct { @@ -42,11 +42,11 @@ typedef struct char *old_tablespace; } transfer_thread_arg; -exec_thread_arg **exec_thread_args; -transfer_thread_arg **transfer_thread_args; +static exec_thread_arg **exec_thread_args; +static transfer_thread_arg **transfer_thread_args; /* track current thread_args struct so reap_child() can be used for all cases */ -void **cur_thread_args; +static void **cur_thread_args; DWORD win32_exec_prog(exec_thread_arg *args); DWORD win32_transfer_all_new_dbs(transfer_thread_arg *args); diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 99f3d4543e949..536e49d26168b 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -3,7 +3,7 @@ * * main source file * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/pg_upgrade.c */ @@ -32,6 +32,9 @@ * We control all assignments of pg_authid.oid for historical reasons (the * oids used to be stored in pg_largeobject_metadata, which is now copied via * SQL commands), that might change at some point in the future. + * + * We control all assignments of pg_database.oid because we want the directory + * names to match between the old and new cluster. */ @@ -40,10 +43,6 @@ #include -#ifdef HAVE_LANGINFO_H -#include -#endif - #include "catalog/pg_class_d.h" #include "common/file_perm.h" #include "common/logging.h" @@ -58,6 +57,7 @@ */ #define RESTORE_TRANSACTION_SIZE 1000 +static void set_new_cluster_char_signedness(void); static void set_locale_and_encoding(void); static void prepare_new_cluster(void); static void prepare_new_globals(void); @@ -158,6 +158,7 @@ main(int argc, char **argv) */ copy_xact_xlog_xid(); + set_new_cluster_char_signedness(); /* New now using xids of the old system */ @@ -172,12 +173,14 @@ main(int argc, char **argv) /* * Most failures happen in create_new_objects(), which has completed at - * this point. We do this here because it is just before linking, which - * will link the old and new cluster data files, preventing the old - * cluster from being safely started once the new cluster is started. + * this point. We do this here because it is just before file transfer, + * which for --link will make it unsafe to start the old cluster once the + * new cluster is started, and for --swap will make it unsafe to start the + * old cluster at all. */ - if (user_opts.transfer_mode == TRANSFER_MODE_LINK) - disable_old_cluster(); + if (user_opts.transfer_mode == TRANSFER_MODE_LINK || + user_opts.transfer_mode == TRANSFER_MODE_SWAP) + disable_old_cluster(user_opts.transfer_mode); transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr, old_cluster.pgdata, new_cluster.pgdata); @@ -214,8 +217,10 @@ main(int argc, char **argv) { prep_status("Sync data directory to disk"); exec_prog(UTILITY_LOG_FILE, NULL, true, true, - "\"%s/initdb\" --sync-only \"%s\" --sync-method %s", + "\"%s/initdb\" --sync-only %s \"%s\" --sync-method %s", new_cluster.bindir, + (user_opts.transfer_mode == TRANSFER_MODE_SWAP) ? + "--no-sync-data-files" : "", new_cluster.pgdata, user_opts.sync_method); check_ok(); @@ -392,6 +397,38 @@ setup(char *argv0) } } +/* + * Set the new cluster's default char signedness using the old cluster's + * value. + */ +static void +set_new_cluster_char_signedness(void) +{ + bool new_char_signedness; + + /* + * Use the specified char signedness if specified. Otherwise we inherit + * the source database's signedness. + */ + if (user_opts.char_signedness != -1) + new_char_signedness = (user_opts.char_signedness == 1); + else + new_char_signedness = old_cluster.controldata.default_char_signedness; + + /* Change the char signedness of the new cluster, if necessary */ + if (new_cluster.controldata.default_char_signedness != new_char_signedness) + { + prep_status("Setting the default char signedness for new cluster"); + + exec_prog(UTILITY_LOG_FILE, NULL, true, true, + "\"%s/pg_resetwal\" --char-signedness %s \"%s\"", + new_cluster.bindir, + new_char_signedness ? "signed" : "unsigned", + new_cluster.pgdata); + + check_ok(); + } +} /* * Copy locale and encoding information into the new cluster's template0. @@ -420,12 +457,13 @@ set_locale_and_encoding(void) datctype_literal = PQescapeLiteral(conn_new_template1, locale->db_ctype, strlen(locale->db_ctype)); + if (locale->db_locale) datlocale_literal = PQescapeLiteral(conn_new_template1, locale->db_locale, strlen(locale->db_locale)); else - datlocale_literal = pg_strdup("NULL"); + datlocale_literal = "NULL"; /* update template0 in new cluster */ if (GET_MAJOR_VERSION(new_cluster.major_version) >= 1700) @@ -469,7 +507,8 @@ set_locale_and_encoding(void) PQfreemem(datcollate_literal); PQfreemem(datctype_literal); - PQfreemem(datlocale_literal); + if (locale->db_locale) + PQfreemem(datlocale_literal); PQfinish(conn_new_template1); @@ -960,11 +999,11 @@ create_logical_replication_slots(void) LogicalSlotInfo *slot_info = &slot_arr->slots[slotnum]; /* Constructs a query for creating logical replication slots */ - appendPQExpBuffer(query, - "SELECT * FROM " - "pg_catalog.pg_create_logical_replication_slot("); + appendPQExpBufferStr(query, + "SELECT * FROM " + "pg_catalog.pg_create_logical_replication_slot("); appendStringLiteralConn(query, slot_info->slotname, conn); - appendPQExpBuffer(query, ", "); + appendPQExpBufferStr(query, ", "); appendStringLiteralConn(query, slot_info->plugin, conn); appendPQExpBuffer(query, ", false, %s, %s);", diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index cdb6e2b7597b1..69c965bb7d09a 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -1,7 +1,7 @@ /* * pg_upgrade.h * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/pg_upgrade.h */ @@ -125,6 +125,11 @@ extern char *output_files[]; */ #define JSONB_FORMAT_CHANGE_CAT_VER 201409291 +/* + * The control file was changed to have the default char signedness, + * commit 44fe30fdab6746a287163e7cc093fd36cda8eb92 + */ +#define DEFAULT_CHAR_SIGNEDNESS_CAT_VER 202502212 /* * Each relation is represented by a relinfo structure. @@ -245,6 +250,7 @@ typedef struct bool date_is_int; bool float8_pass_by_value; uint32 data_checksum_version; + bool default_char_signedness; } ControlData; /* @@ -256,6 +262,7 @@ typedef enum TRANSFER_MODE_COPY, TRANSFER_MODE_COPY_FILE_RANGE, TRANSFER_MODE_LINK, + TRANSFER_MODE_SWAP, } transferMode; /* @@ -327,6 +334,10 @@ typedef struct int jobs; /* number of processes/threads to use */ char *socketdir; /* directory to use for Unix sockets */ char *sync_method; + bool do_statistics; /* carry over statistics from old cluster */ + int char_signedness; /* default char signedness: -1 for initial + * value, 1 for "signed" and 0 for + * "unsigned" */ } UserOpts; typedef struct @@ -381,7 +392,7 @@ void create_script_for_old_cluster_deletion(char **deletion_script_file_name); void get_control_data(ClusterInfo *cluster); void check_control_data(ControlData *oldctrl, ControlData *newctrl); -void disable_old_cluster(void); +void disable_old_cluster(transferMode transfer_mode); /* dump.c */ @@ -413,7 +424,7 @@ void rewriteVisibilityMap(const char *fromfile, const char *tofile, const char *schemaName, const char *relName); void check_file_clone(void); void check_copy_file_range(void); -void check_hard_link(void); +void check_hard_link(transferMode transfer_mode); /* fopen_priv() is no longer different from fopen() */ #define fopen_priv(path, mode) fopen(path, mode) @@ -471,7 +482,7 @@ int get_user_info(char **user_name_p); void check_ok(void); void report_status(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3); void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3); -void pg_fatal(const char *fmt,...) pg_attribute_printf(1, 2) pg_attribute_noreturn(); +pg_noreturn void pg_fatal(const char *fmt,...) pg_attribute_printf(1, 2); void end_progress_output(void); void cleanup_output_dirs(void); void prep_status(const char *fmt,...) pg_attribute_printf(1, 2); @@ -494,3 +505,24 @@ void parallel_transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr char *old_pgdata, char *new_pgdata, char *old_tablespace); bool reap_child(bool wait_for_child); + +/* task.c */ + +typedef void (*UpgradeTaskProcessCB) (DbInfo *dbinfo, PGresult *res, void *arg); + +/* struct definition is private to task.c */ +typedef struct UpgradeTask UpgradeTask; + +UpgradeTask *upgrade_task_create(void); +void upgrade_task_add_step(UpgradeTask *task, const char *query, + UpgradeTaskProcessCB process_cb, bool free_result, + void *arg); +void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster); +void upgrade_task_free(UpgradeTask *task); + +/* convenient type for common private data needed by several tasks */ +typedef struct +{ + FILE *file; + char path[MAXPGPATH]; +} UpgradeTaskReport; diff --git a/src/bin/pg_upgrade/po/de.po b/src/bin/pg_upgrade/po/de.po index 6ba30754d318d..4a225c29f21cc 100644 --- a/src/bin/pg_upgrade/po/de.po +++ b/src/bin/pg_upgrade/po/de.po @@ -1,13 +1,13 @@ # German message translation file for pg_upgrade -# Copyright (C) 2024 PostgreSQL Global Development Group +# Copyright (C) 2025 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. # msgid "" msgstr "" -"Project-Id-Version: pg_upgrade (PostgreSQL) 17\n" +"Project-Id-Version: pg_upgrade (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-18 04:50+0000\n" -"PO-Revision-Date: 2024-06-19 10:24+0200\n" +"POT-Creation-Date: 2025-04-08 04:51+0000\n" +"PO-Revision-Date: 2025-04-08 08:44+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -45,12 +45,12 @@ msgstr "Benutzer existiert nicht" msgid "user name lookup failure: error code %lu" msgstr "Fehler beim Nachschlagen des Benutzernamens: Fehlercode %lu" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" @@ -229,34 +229,34 @@ msgstr "" "löschen oder in einen anderen Datentyp ändern und das Upgrade neu\n" "starten.\n" -#: check.c:345 +#: check.c:421 #, c-format -msgid "Checking for data type usage" -msgstr "Prüfe Verwendung von Datentypen" - -#: check.c:480 -#, c-format -msgid " failed check: %s" -msgstr " fehlgeschlagene Prüfung: %s" +msgid "failed check: %s" +msgstr "fehlgeschlagene Prüfung: %s" -#: check.c:483 +#: check.c:424 msgid "A list of the problem columns is in the file:" msgstr "Eine Liste der Problemspalten ist in der Datei:" -#: check.c:495 check.c:961 check.c:1134 check.c:1249 check.c:1343 check.c:1471 -#: check.c:1547 check.c:1611 check.c:1684 check.c:1866 check.c:1885 -#: check.c:1954 check.c:2006 file.c:378 file.c:415 function.c:189 option.c:493 -#: version.c:79 version.c:177 +#: check.c:430 check.c:1026 check.c:1177 check.c:1260 check.c:1349 check.c:1440 +#: check.c:1572 check.c:1657 check.c:1704 check.c:1784 check.c:2089 +#: check.c:2108 check.c:2154 check.c:2207 file.c:378 file.c:415 function.c:208 +#: option.c:519 version.c:79 version.c:162 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: check.c:522 +#: check.c:472 +#, c-format +msgid "Checking data type usage" +msgstr "Prüfe Verwendung von Datentypen" + +#: check.c:526 #, c-format msgid "Data type checks failed: %s" msgstr "Datentypprüfungen fehlgeschlagen: %s" -#: check.c:563 +#: check.c:575 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -265,7 +265,7 @@ msgstr "" "Führe Konsistenzprüfungen am alten laufenden Server durch\n" "---------------------------------------------------------" -#: check.c:569 +#: check.c:581 #, c-format msgid "" "Performing Consistency Checks\n" @@ -274,7 +274,13 @@ msgstr "" "Führe Konsistenzprüfungen durch\n" "-------------------------------" -#: check.c:716 +#: check.c:745 +#, fuzzy, c-format +#| msgid "This utility can only upgrade from PostgreSQL version %s and later." +msgid "Swap mode can only upgrade clusters from PostgreSQL version %s and later." +msgstr "Dieses Programm kann nur Upgrades von PostgreSQL Version %s oder später durchführen." + +#: check.c:768 #, c-format msgid "" "\n" @@ -283,7 +289,7 @@ msgstr "" "\n" "*Cluster sind kompatibel*" -#: check.c:724 +#: check.c:776 #, c-format msgid "" "\n" @@ -295,18 +301,19 @@ msgstr "" "neuen Cluster neu mit initdb initialisieren, bevor fortgesetzt\n" "werden kann." -#: check.c:765 +#: check.c:817 #, c-format msgid "" -"Optimizer statistics are not transferred by pg_upgrade.\n" +"Some optimizer statistics may not have been transferred by pg_upgrade.\n" "Once you start the new server, consider running:\n" -" %s/vacuumdb %s--all --analyze-in-stages" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only" msgstr "" -"Optimizer-Statistiken werden von pg_upgrade nicht übertragen. Wenn Sie\n" -"den neuen Server starten, sollte Sie diesen Befehl ausführen:\n" -" %s/vacuumdb %s--all --analyze-in-stages" +"Einige Optimizer-Statistiken wurden möglicherweise von pg_upgrade\n" +"nicht übertragen. Wenn Sie den neuen Server starten, sollte Sie diesen\n" +"Befehl ausführen:\n" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only" -#: check.c:771 +#: check.c:823 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -315,7 +322,7 @@ msgstr "" "Mit diesem Skript können die Dateien des alten Clusters gelöscht werden:\n" " %s" -#: check.c:776 +#: check.c:828 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -328,57 +335,63 @@ msgstr "" "Datenverzeichnis des neuen Clusters im alten Cluster-Verzeichnis\n" "liegen. Der Inhalt des alten Clusters muss von Hand gelöscht werden." -#: check.c:788 +#: check.c:840 #, c-format msgid "Checking cluster versions" msgstr "Prüfe Cluster-Versionen" -#: check.c:800 +#: check.c:852 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "Dieses Programm kann nur Upgrades von PostgreSQL Version %s oder später durchführen." -#: check.c:805 +#: check.c:857 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "Dieses Programm kann nur Upgrades auf PostgreSQL Version %s durchführen." -#: check.c:814 +#: check.c:866 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "Dieses Programm kann keine Downgrades auf ältere Hauptversionen von PostgreSQL durchführen." -#: check.c:819 +#: check.c:871 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "Die Daten- und Programmverzeichnisse des alten Clusters stammen von verschiedenen Hauptversionen." -#: check.c:822 +#: check.c:874 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "Die Daten- und Programmverzeichnisse des neuen Clusters stammen von verschiedenen Hauptversionen." -#: check.c:837 +#: check.c:885 +#, fuzzy, c-format +#| msgid "This utility can only upgrade from PostgreSQL version %s and later." +msgid "%s option cannot be used to upgrade from PostgreSQL %s and later." +msgstr "Dieses Programm kann nur Upgrades von PostgreSQL Version %s oder später durchführen." + +#: check.c:901 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "Wenn ein laufender Server geprüft wird, müssen die alte und die neue Portnummer verschieden sein." -#: check.c:857 +#: check.c:921 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "Datenbank »%s« im neuen Cluster ist nicht leer: Relation »%s.%s« gefunden" -#: check.c:880 +#: check.c:944 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Prüfe Tablespace-Verzeichnisse des neuen Clusters" -#: check.c:891 +#: check.c:955 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "Tablespace-Verzeichnis für neuen Cluster existiert bereits: »%s«" -#: check.c:924 +#: check.c:989 #, c-format msgid "" "\n" @@ -387,7 +400,7 @@ msgstr "" "\n" "WARNUNG: das neue Datenverzeichnis sollte nicht im alten Datenverzeichnis, d.h. %s, liegen" -#: check.c:948 +#: check.c:1013 #, c-format msgid "" "\n" @@ -396,93 +409,93 @@ msgstr "" "\n" "WARNUNG: benutzerdefinierte Tablespace-Pfade sollten nicht im Datenverzeichnis, d.h. %s, liegen" -#: check.c:958 +#: check.c:1023 #, c-format msgid "Creating script to delete old cluster" msgstr "Erzeuge Skript zum Löschen des alten Clusters" -#: check.c:1012 +#: check.c:1051 #, c-format msgid "could not add execute permission to file \"%s\": %m" msgstr "konnte Datei »%s« nicht ausführbar machen: %m" -#: check.c:1032 +#: check.c:1071 #, c-format msgid "Checking database user is the install user" msgstr "Prüfe ob der Datenbankbenutzer der Installationsbenutzer ist" -#: check.c:1048 +#: check.c:1087 #, c-format msgid "database user \"%s\" is not the install user" msgstr "Datenbankbenutzer »%s« ist nicht der Installationsbenutzer" -#: check.c:1059 +#: check.c:1098 #, c-format msgid "could not determine the number of users" msgstr "konnte die Anzahl der Benutzer nicht ermitteln" -#: check.c:1067 +#: check.c:1106 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "Nur der Installationsbenutzer darf im neuen Cluster definiert sein." -#: check.c:1096 +#: check.c:1136 #, c-format msgid "Checking database connection settings" msgstr "Prüfe Verbindungseinstellungen der Datenbank" -#: check.c:1122 +#: check.c:1164 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0 darf keine Verbindungen erlauben, d.h. ihr pg_database.datallowconn muss falsch sein" -#: check.c:1148 check.c:1268 check.c:1365 check.c:1490 check.c:1566 -#: check.c:1624 check.c:1704 check.c:1898 check.c:2023 function.c:210 +#: check.c:1191 check.c:1312 check.c:1408 check.c:1536 check.c:1612 +#: check.c:1670 check.c:1753 check.c:2121 check.c:2263 function.c:229 #, c-format msgid "fatal" msgstr "fatal" -#: check.c:1149 +#: check.c:1192 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" -"pg_database.datallowconn must be true. Your installation contains\n" -"non-template0 databases with their pg_database.datallowconn set to\n" -"false. Consider allowing connection for all non-template0 databases\n" -"or drop the databases which do not allow connections. A list of\n" -"databases with the problem is in the file:\n" +"pg_database.datallowconn must be true and pg_database.datconnlimit\n" +"must not be -2. Your installation contains non-template0 databases\n" +"which cannot be connected to. Consider allowing connection for all\n" +"non-template0 databases or drop the databases which do not allow\n" +"connections. A list of databases with the problem is in the file:\n" " %s" msgstr "" "Alle Datenbanken außer template0 müssen Verbindungen erlauben,\n" -"d.h. ihr pg_database.datallowconn muss wahr sein. Ihre Installation\n" -"enthält Datenbanken außer template0, deren pg_database.datallowconn\n" -"auf falsch gesetzt ist. Sie sollten Verbindungen für alle Datenbanken\n" -"außer template0 erlauben oder die Datenbanken, die keine Verbindungen\n" -"erlauben, löschen. Eine Liste der Datenbanken mit diesem Problem ist\n" -"in der Datei:\n" +"d.h. ihr pg_database.datallowconn muss wahr sein und\n" +"pg_database.datconnlimit darf nicht -2 sein. Ihre Installation enthält\n" +"Datenbanken außer template0, zu denen nicht verbunden werden kann.\n" +"Sie sollten Verbindungen für alle Datenbanken außer template0 erlauben\n" +"oder die Datenbanken, die keine Verbindungen erlauben, löschen. Eine\n" +"Liste der Datenbanken mit diesem Problem ist in der Datei:\n" " %s" -#: check.c:1174 +#: check.c:1217 #, c-format msgid "Checking for prepared transactions" msgstr "Prüfe auf vorbereitete Transaktionen" -#: check.c:1183 +#: check.c:1226 #, c-format msgid "The source cluster contains prepared transactions" msgstr "Der alte Cluster enthält vorbereitete Transaktionen" -#: check.c:1185 +#: check.c:1228 #, c-format msgid "The target cluster contains prepared transactions" msgstr "Der neue Cluster enthält vorbereitete Transaktionen" -#: check.c:1210 +#: check.c:1288 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Prüfe auf contrib/isn mit unpassender bigint-Übergabe" -#: check.c:1269 +#: check.c:1313 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -502,12 +515,12 @@ msgstr "" "der problematischen Funktionen ist in der Datei:\n" " %s" -#: check.c:1291 +#: check.c:1393 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Prüfe auf benutzerdefinierte Postfix-Operatoren" -#: check.c:1366 +#: check.c:1409 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -522,12 +535,12 @@ msgstr "" "Liste der benutzerdefinierten Postfixoperatoren ist in der Datei:\n" " %s" -#: check.c:1390 +#: check.c:1464 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "Prüfe auf inkompatible polymorphische Funktionen" -#: check.c:1491 +#: check.c:1537 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -548,12 +561,12 @@ msgstr "" "Eine Liste der problematischen Objekte ist in der Datei:\n" " %s" -#: check.c:1515 +#: check.c:1597 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Prüfe auf Tabellen mit WITH OIDS" -#: check.c:1567 +#: check.c:1613 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -568,12 +581,12 @@ msgstr "" "Eine Liste der Tabellen mit dem Problem ist in der Datei:\n" " %s" -#: check.c:1594 +#: check.c:1640 #, c-format msgid "Checking for roles starting with \"pg_\"" msgstr "Prüfe auf Rollen, die mit »pg_« anfangen" -#: check.c:1625 +#: check.c:1671 #, c-format msgid "" "Your installation contains roles starting with \"pg_\".\n" @@ -588,12 +601,12 @@ msgstr "" "Eine Liste der Rollen, die mit »pg_« anfangen, ist in der Datei:\n" " %s" -#: check.c:1645 +#: check.c:1725 #, c-format msgid "Checking for user-defined encoding conversions" msgstr "Prüfe auf benutzerdefinierte Kodierungsumwandlungen" -#: check.c:1705 +#: check.c:1754 #, c-format msgid "" "Your installation contains user-defined encoding conversions.\n" @@ -612,55 +625,73 @@ msgstr "" "in der Datei:\n" " %s" -#: check.c:1744 +#: check.c:1839 +#, c-format +msgid "Checking for objects affected by Unicode update" +msgstr "Prüfe auf vom Unicode-Update betroffene Objekte" + +#: check.c:1933 version.c:121 +#, c-format +msgid "warning" +msgstr "Warnung" + +#: check.c:1934 +#, c-format +msgid "" +"Your installation contains relations that may be affected by a new version of Unicode.\n" +"A list of potentially-affected relations is in the file:\n" +" %s" +msgstr "" + +#: check.c:1970 #, c-format msgid "Checking for new cluster logical replication slots" msgstr "Prüfe logische Replikations-Slots des neuen Clusters" -#: check.c:1752 +#: check.c:1978 #, c-format msgid "could not count the number of logical replication slots" msgstr "konnte Anzahl der logischen Replikations-Slots nicht zählen" -#: check.c:1757 +#: check.c:1983 #, c-format -msgid "Expected 0 logical replication slots but found %d." -msgstr "0 logische Replikations-Slots erwartet aber %d gefunden." +msgid "expected 0 logical replication slots but found %d" +msgstr "0 logische Replikations-Slots erwartet aber %d gefunden" -#: check.c:1767 check.c:1821 +#: check.c:1993 check.c:2044 #, c-format msgid "could not determine parameter settings on new cluster" msgstr "konnte Parametereinstellung im neuen Cluster nicht ermitteln" -#: check.c:1772 +#: check.c:1998 #, c-format -msgid "\"wal_level\" must be \"logical\", but is set to \"%s\"" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" msgstr "»wal_level« muss »logical« sein, aber es ist auf »%s« gesetzt" -#: check.c:1778 +#: check.c:2004 #, c-format msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" msgstr "»max_replication_slots« (%d) muss größer als oder gleich der Anzahl der logischen Replikations-Slots (%d) im alten Cluster sein" -#: check.c:1813 +#: check.c:2036 #, c-format msgid "Checking for new cluster configuration for subscriptions" msgstr "Prüfe Konfiguration für Subskriptionen im neuen Cluster" -#: check.c:1825 +#: check.c:2048 #, c-format -msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" -msgstr "»max_replication_slots« (%d) muss größer als oder gleich der Anzahl der Subskriptionen (%d) im alten Cluster sein" +msgid "\"max_active_replication_origins\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "»max_active_replication_origins« (%d) muss größer als oder gleich der Anzahl der Subskriptionen (%d) im alten Cluster sein" -#: check.c:1847 +#: check.c:2070 #, c-format msgid "Checking for valid logical replication slots" msgstr "Prüfe auf gültige logische Replikations-Slots" -#: check.c:1899 +#: check.c:2122 #, c-format msgid "" -"Your installation contains logical replication slots that can't be upgraded.\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" "You can remove invalid slots and/or consume the pending WAL for other slots,\n" "and then restart the upgrade.\n" "A list of the problematic slots is in the file:\n" @@ -673,12 +704,12 @@ msgstr "" "Eine Liste der problematischen Slots ist in der Datei:\n" " %s" -#: check.c:1923 +#: check.c:2182 #, c-format msgid "Checking for subscription state" msgstr "Prüfe Subskriptionszustand" -#: check.c:2024 +#: check.c:2264 #, c-format msgid "" "Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" @@ -693,184 +724,190 @@ msgstr "" "Subskriptionen ist in der Datei:\n" " %s" -#: controldata.c:129 controldata.c:199 +#: controldata.c:133 controldata.c:203 #, c-format msgid "could not get control data using %s: %m" msgstr "konnte Kontrolldaten mit %s nicht ermitteln: %m" -#: controldata.c:139 +#: controldata.c:143 #, c-format msgid "%d: database cluster state problem" msgstr "%d: Problem mit dem Zustand des Clusters" -#: controldata.c:158 +#: controldata.c:162 #, c-format msgid "The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "Der alte Cluster wurde im Wiederherstellungsmodus heruntergefahren. Um ihn zu aktualisieren, verwenden Sie »rsync« wie in der Dokumentation beschrieben oder fahren Sie ihn im Primärmodus herunter." -#: controldata.c:160 +#: controldata.c:164 #, c-format msgid "The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "Der neue Cluster wurde im Wiederherstellungsmodus heruntergefahren. Um ihn zu aktualisieren, verwenden Sie »rsync« wie in der Dokumentation beschrieben oder fahren Sie ihn im Primärmodus herunter." -#: controldata.c:165 +#: controldata.c:169 #, c-format msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "Der alte Cluster wurde nicht sauber heruntergefahren, gemeldeter Status: »%s«" -#: controldata.c:167 +#: controldata.c:171 #, c-format msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "Der neue Cluster wurde nicht sauber heruntergefahren, gemeldeter Status: »%s«" -#: controldata.c:175 controldata.c:507 +#: controldata.c:179 controldata.c:530 #, c-format msgid "could not get control data using %s: %s" msgstr "konnte Kontrolldaten mit %s nicht ermitteln: %s" -#: controldata.c:181 +#: controldata.c:185 #, c-format msgid "The source cluster lacks cluster state information:" msgstr "Im alten Cluster fehlen Cluster-Zustandsinformationen:" -#: controldata.c:183 +#: controldata.c:187 #, c-format msgid "The target cluster lacks cluster state information:" msgstr "Im neuen Cluster fehlen Cluster-Zustandsinformationen:" -#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 -#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 +#: controldata.c:217 dump.c:50 exec.c:118 pg_upgrade.c:603 pg_upgrade.c:643 +#: pg_upgrade.c:992 relfilenumber.c:610 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:220 +#: controldata.c:224 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d: Problem mit pg_resetwal" -#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 -#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 -#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 -#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 -#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 -#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 -#: controldata.c:486 controldata.c:497 +#: controldata.c:234 controldata.c:244 controldata.c:255 controldata.c:266 +#: controldata.c:277 controldata.c:296 controldata.c:307 controldata.c:318 +#: controldata.c:329 controldata.c:340 controldata.c:351 controldata.c:362 +#: controldata.c:365 controldata.c:369 controldata.c:379 controldata.c:391 +#: controldata.c:402 controldata.c:413 controldata.c:424 controldata.c:435 +#: controldata.c:446 controldata.c:457 controldata.c:468 controldata.c:479 +#: controldata.c:490 controldata.c:501 controldata.c:512 controldata.c:521 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d: Problem beim Ermitteln der Kontrolldaten" -#: controldata.c:578 +#: controldata.c:618 #, c-format msgid "The source cluster lacks some required control information:" msgstr "Im alten Cluster fehlen einige notwendige Kontrollinformationen:" -#: controldata.c:581 +#: controldata.c:621 #, c-format msgid "The target cluster lacks some required control information:" msgstr "Im neuen Cluster fehlen einige notwendige Kontrollinformationen:" -#: controldata.c:584 +#: controldata.c:624 #, c-format msgid " checkpoint next XID" msgstr " Checkpoint nächste XID" -#: controldata.c:587 +#: controldata.c:627 #, c-format msgid " latest checkpoint next OID" msgstr " NextOID des letzten Checkpoints" -#: controldata.c:590 +#: controldata.c:630 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " NextMultiXactId des letzten Checkpoints" -#: controldata.c:594 +#: controldata.c:634 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " oldestMultiXid des letzten Checkpoints" -#: controldata.c:597 +#: controldata.c:637 #, c-format msgid " latest checkpoint oldestXID" msgstr " oldestXID des letzten Checkpoints" -#: controldata.c:600 +#: controldata.c:640 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " NextMultiOffset des letzten Checkpoints" -#: controldata.c:603 +#: controldata.c:643 #, c-format msgid " first WAL segment after reset" msgstr " erstes WAL-Segment nach dem Reset" -#: controldata.c:606 +#: controldata.c:646 #, c-format msgid " float8 argument passing method" msgstr " Übergabe von Float8-Argumenten" -#: controldata.c:609 +#: controldata.c:649 #, c-format msgid " maximum alignment" msgstr " maximale Ausrichtung (Alignment)" -#: controldata.c:612 +#: controldata.c:652 #, c-format msgid " block size" msgstr " Blockgröße" -#: controldata.c:615 +#: controldata.c:655 #, c-format msgid " large relation segment size" msgstr " Segmentgröße für große Relationen" -#: controldata.c:618 +#: controldata.c:658 #, c-format msgid " WAL block size" msgstr " WAL-Blockgröße" -#: controldata.c:621 +#: controldata.c:661 #, c-format msgid " WAL segment size" msgstr " WAL-Segmentgröße" -#: controldata.c:624 +#: controldata.c:664 #, c-format msgid " maximum identifier length" msgstr " maximale Bezeichnerlänge" -#: controldata.c:627 +#: controldata.c:667 #, c-format msgid " maximum number of indexed columns" msgstr " maximale Anzahl indizierter Spalten" -#: controldata.c:630 +#: controldata.c:670 #, c-format msgid " maximum TOAST chunk size" msgstr " maximale TOAST-Chunk-Größe" -#: controldata.c:634 +#: controldata.c:674 #, c-format msgid " large-object chunk size" msgstr " Large-Object-Chunk-Größe" -#: controldata.c:637 +#: controldata.c:677 #, c-format msgid " dates/times are integers?" msgstr " Datum/Zeit sind Ganzzahlen?" -#: controldata.c:641 +#: controldata.c:681 #, c-format msgid " data checksum version" msgstr " Datenprüfsummenversion" -#: controldata.c:643 +#: controldata.c:685 +#, fuzzy, c-format +#| msgid " default collation: %s\n" +msgid " default char signedness" +msgstr " Standardsortierfolge: %s\n" + +#: controldata.c:687 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "Kann ohne die benötigten Kontrollinformationen nicht fortsetzen, Programm wird beendet" -#: controldata.c:658 +#: controldata.c:702 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -879,91 +916,106 @@ msgstr "" "altes und neues Alignment in pg_controldata ist ungültig oder stimmt nicht überein\n" "Wahrscheinlich ist ein Cluster eine 32-Bit-Installation und der andere 64-Bit" -#: controldata.c:662 +#: controldata.c:706 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "alte und neue Blockgrößen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:665 +#: controldata.c:709 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "alte und neue maximale Relationssegmentgrößen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:668 +#: controldata.c:712 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "alte und neue WAL-Blockgrößen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:671 +#: controldata.c:715 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "alte und neue WAL-Segmentgrößen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:674 +#: controldata.c:718 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "alte und neue maximale Bezeichnerlängen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:677 +#: controldata.c:721 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "alte und neue Maximalzahlen indizierter Spalten von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:680 +#: controldata.c:724 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "alte und neue maximale TOAST-Chunk-Größen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:685 +#: controldata.c:729 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "alte und neue Large-Object-Chunk-Größen von pg_controldata sind ungültig oder stimmen nicht überein" -#: controldata.c:688 +#: controldata.c:732 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "alte und neue Speicherung von Datums- und Zeittypen von pg_controldata ist ungültig oder stimmt nicht überein" -#: controldata.c:701 +#: controldata.c:745 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "der alte Cluster verwendet keine Datenprüfsummen, aber der neue verwendet sie" -#: controldata.c:704 +#: controldata.c:748 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "die alte Cluster verwendet Datenprüfsummen, aber der neue nicht" -#: controldata.c:706 +#: controldata.c:750 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "Prüfsummenversionen im alten und neuen Cluster stimmen nicht überein" -#: controldata.c:717 -#, c-format -msgid "Adding \".old\" suffix to old global/pg_control" +#: controldata.c:761 +#, fuzzy, c-format +#| msgid "Adding \".old\" suffix to old global/pg_control" +msgid "Adding \".old\" suffix to old " msgstr "Füge Endung ».old« an altes global/pg_control an" -#: controldata.c:722 +#: controldata.c:766 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" -#: controldata.c:726 +#: controldata.c:771 #, c-format msgid "" "\n" "If you want to start the old cluster, you will need to remove\n" -"the \".old\" suffix from %s/global/pg_control.old.\n" +"the \".old\" suffix from %s/%s.old.\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" "started once the new cluster has been started." msgstr "" "\n" "Wenn Sie den alten Cluster starten wollen, müssen Sie die Endung\n" -"».old« von %s/global/pg_control.old entfernen. Da der »link«-Modus\n" +"».old« von %s/%s.old entfernen. Da der »link«-Modus\n" "verwendet wurde, kann der alte Cluster nicht gefahrlos gestartet\n" "werden, nachdem der neue Cluster gestartet worden ist." +#: controldata.c:778 +#, c-format +msgid "" +"\n" +"Because \"swap\" mode was used, the old cluster can no longer be\n" +"safely started." +msgstr "" + +#: controldata.c:782 file.c:455 +#, fuzzy, c-format +#| msgid "unrecognized status code" +msgid "unrecognized transfer mode" +msgstr "nicht erkannter Statuscode" + #: dump.c:20 #, c-format msgid "Creating dump of global objects" @@ -994,7 +1046,7 @@ msgstr "konnte pg_ctl-Version nicht ermitteln von %s" msgid "command too long" msgstr "Befehl zu lang" -#: exec.c:160 pg_upgrade.c:311 +#: exec.c:160 pg_upgrade.c:312 #, c-format msgid "could not open log file \"%s\": %m" msgstr "konnte Logdatei »%s« nicht öffnen: %m" @@ -1031,7 +1083,7 @@ msgstr "" "Prüfen Sie die letzten Zeilen von »%s« für den\n" "wahrscheinlichen Grund für das Scheitern." -#: exec.c:218 pg_upgrade.c:321 +#: exec.c:218 pg_upgrade.c:322 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "konnte nicht in Logdatei »%s «schreiben: %m" @@ -1156,7 +1208,7 @@ msgstr "konnte Dateibereich nicht vom alten in das neue Datenverzeichnis kopiere msgid "copy_file_range not supported on this platform" msgstr "copy_file_range wird auf dieser Plattform nicht unterstützt" -#: file.c:447 +#: file.c:449 #, c-format msgid "" "could not create hard link between old and new data directories: %m\n" @@ -1165,22 +1217,31 @@ msgstr "" "konnte Hard-Link-Verknüpfung zwischen altem und neuen Datenverzeichnis nicht erzeugen: %m\n" "Im Link-Modus müssen das alte und das neue Datenverzeichnis im selben Dateisystem liegen." -#: function.c:154 +#: file.c:452 +#, c-format +msgid "" +"could not create hard link between old and new data directories: %m\n" +"In swap mode the old and new data directories must be on the same file system." +msgstr "" +"konnte Hard-Link-Verknüpfung zwischen altem und neuen Datenverzeichnis nicht erzeugen: %m\n" +"Im Swap-Modus müssen das alte und das neue Datenverzeichnis im selben Dateisystem liegen." + +#: function.c:173 #, c-format msgid "Checking for presence of required libraries" msgstr "Prüfe das Vorhandensein benötigter Bibliotheken" -#: function.c:190 +#: function.c:209 #, c-format msgid "could not load library \"%s\": %s" msgstr "konnte Bibliothek »%s« nicht laden: %s" -#: function.c:201 +#: function.c:220 #, c-format msgid "In database: %s\n" msgstr "In Datenbank: %s\n" -#: function.c:211 +#: function.c:230 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -1196,47 +1257,47 @@ msgstr "" "Datei:\n" " %s" -#: info.c:129 +#: info.c:131 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "Relationsnamen für OID %u in Datenbank »%s« stimmen nicht überein: alten Name »%s.%s«, neuer Name »%s.%s«" -#: info.c:149 +#: info.c:151 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "Alte und neue Tabellen in Datenbank »%s« konnten nicht gepaart werden" -#: info.c:230 +#: info.c:232 #, c-format msgid " which is an index on \"%s.%s\"" msgstr ", ein Index für »%s.%s«" -#: info.c:240 +#: info.c:242 #, c-format msgid " which is an index on OID %u" msgstr ", ein Index für OID %u" -#: info.c:252 +#: info.c:254 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr ", eine TOAST-Tabelle für »%s.%s«" -#: info.c:260 +#: info.c:262 #, c-format msgid " which is the TOAST table for OID %u" msgstr ", eine TOAST-Tabelle für OID %u" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "Keine Übereinstimmung gefunden im alten Cluster für neue Relation mit OID %u in Datenbank »%s«: %s" -#: info.c:267 +#: info.c:269 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "Keine Übereinstimmung gefunden im neuen Cluster für alte Relation mit OID %u in Datenbank »%s«: %s" -#: info.c:308 +#: info.c:325 #, c-format msgid "" "\n" @@ -1245,7 +1306,7 @@ msgstr "" "\n" "Quelldatenbanken:" -#: info.c:310 +#: info.c:327 #, c-format msgid "" "\n" @@ -1254,92 +1315,97 @@ msgstr "" "\n" "Zieldatenbanken:" -#: info.c:354 +#: info.c:371 #, c-format msgid "template0 not found" msgstr "template0 nicht gefunden" -#: info.c:842 +#: info.c:817 #, c-format msgid "Database: \"%s\"" msgstr "Datenbank: »%s«" -#: info.c:855 +#: info.c:830 #, c-format msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" msgstr "relname: »%s.%s«, reloid: %u, reltblspace: »%s«" -#: info.c:869 +#: info.c:844 #, c-format -msgid "Logical replication slots within the database:" +msgid "Logical replication slots in the database:" msgstr "Logische Replikations-Slots in der Datenbank:" -#: info.c:875 +#: info.c:850 #, c-format -msgid "slot_name: \"%s\", plugin: \"%s\", two_phase: %s" -msgstr "Slot-Name: »%s«, Plugin: »%s«, two_phase: %s" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "Slot-Name: »%s«, Ausgabe-Plugin: »%s«, two_phase: %s" -#: option.c:105 +#: option.c:110 #, c-format msgid "%s: cannot be run as root" msgstr "%s: kann nicht als root ausgeführt werden" -#: option.c:172 +#: option.c:177 #, c-format msgid "invalid old port number" msgstr "ungültige alte Portnummer" -#: option.c:177 +#: option.c:182 #, c-format msgid "invalid new port number" msgstr "ungültige neue Portnummer" -#: option.c:216 +#: option.c:230 +#, c-format +msgid "invalid argument for option %s" +msgstr "ungültiges Argument für Option %s" + +#: option.c:238 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n" -#: option.c:223 +#: option.c:245 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: option.c:229 +#: option.c:251 #, c-format msgid "Running in verbose mode" msgstr "Ausführung im Verbose-Modus" -#: option.c:247 +#: option.c:269 msgid "old cluster binaries reside" msgstr "die Programmdateien des alten Clusters liegen" -#: option.c:249 +#: option.c:271 msgid "new cluster binaries reside" msgstr "die Programmdateien des neuen Clusters liegen" -#: option.c:251 +#: option.c:273 msgid "old cluster data resides" msgstr "die Daten das alten Clusters liegen" -#: option.c:253 +#: option.c:275 msgid "new cluster data resides" msgstr "die Daten des neuen Clusters liegen" -#: option.c:255 +#: option.c:277 msgid "sockets will be created" msgstr "die Sockets erzeugt werden sollen" -#: option.c:272 option.c:374 +#: option.c:294 option.c:400 #, c-format msgid "could not determine current directory" msgstr "konnte aktuelles Verzeichnis nicht ermitteln" -#: option.c:275 +#: option.c:297 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "auf Windows kann pg_upgrade nicht von innerhalb des Cluster-Datenverzeichnisses ausgeführt werden" -#: option.c:284 +#: option.c:306 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1348,12 +1414,12 @@ msgstr "" "pg_upgrade aktualisiert einen PostgreSQL-Cluster auf eine neue Hauptversion.\n" "\n" -#: option.c:285 +#: option.c:307 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: option.c:286 +#: option.c:308 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1362,17 +1428,17 @@ msgstr "" " pg_upgrade [OPTION]...\n" "\n" -#: option.c:287 +#: option.c:309 #, c-format msgid "Options:\n" msgstr "Optionen:\n" -#: option.c:288 +#: option.c:310 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINVERZ Programmverzeichnis des alten Clusters\n" -#: option.c:289 +#: option.c:311 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1381,111 +1447,128 @@ msgstr "" " -B, --new-bindir=BINVERZ Programmverzeichnis des neuen Clusters\n" " (Standard: gleiches Verzeichnis wie pg_upgrade)\n" -#: option.c:291 +#: option.c:313 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check nur Cluster prüfen, keine Daten ändern\n" -#: option.c:292 +#: option.c:314 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATENVERZ Datenverzeichnis des alten Clusters\n" -#: option.c:293 +#: option.c:315 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATENVERZ Datenverzeichnis des neuen Clusters\n" -#: option.c:294 +#: option.c:316 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs=NUM Anzahl paralleler Prozesse oder Threads\n" -#: option.c:295 +#: option.c:317 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr " -k, --link Dateien in den neuen Cluster verknüpfen statt kopieren\n" -#: option.c:296 +#: option.c:318 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n" " geschrieben sind\n" -#: option.c:297 +#: option.c:319 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=OPTIONEN Serveroptionen für den alten Cluster\n" -#: option.c:298 +#: option.c:320 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=OPTIONEN Serveroptionen für den neuen Cluster\n" -#: option.c:299 +#: option.c:321 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PORT Portnummer für den alten Cluster (Standard: %d)\n" -#: option.c:300 +#: option.c:322 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT Portnummer für den neuen Cluster (Standard: %d)\n" -#: option.c:301 +#: option.c:323 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain SQL- und Logdateien bei Erfolg aufheben\n" -#: option.c:302 +#: option.c:324 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr " -s, --socketdir=VERZ Verzeichnis für Socket (Standard: aktuelles Verz.)\n" -#: option.c:303 +#: option.c:325 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=NAME Cluster-Superuser (Standard: »%s«)\n" -#: option.c:304 +#: option.c:326 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose »Verbose«-Modus einschalten\n" -#: option.c:305 +#: option.c:327 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: option.c:306 +#: option.c:328 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr " --clone Dateien in den neuen Cluster klonen statt kopieren\n" -#: option.c:307 +#: option.c:329 #, c-format msgid " --copy copy files to new cluster (default)\n" msgstr " --copy Dateien in den neuen Cluster kopieren (Voreinstellung)\n" -#: option.c:308 +#: option.c:330 #, c-format msgid " --copy-file-range copy files to new cluster with copy_file_range\n" msgstr " --copy-file-range Dateien mit copy_file_range in den neuen Cluster kopieren\n" -#: option.c:309 +#: option.c:331 +#, c-format +msgid " --no-statistics do not import statistics from old cluster\n" +msgstr " --no-statistics Statistiken vom alten Cluster nicht importieren\n" + +#: option.c:332 +#, c-format +msgid "" +" --set-char-signedness=OPTION set new cluster char signedness to \"signed\" or\n" +" \"unsigned\"\n" +msgstr "" + +#: option.c:334 +#, c-format +msgid " --swap move data directories to new cluster\n" +msgstr " --swap Datenverzeichnisse in den neuen Cluster verschieben\n" + +#: option.c:335 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHODE Methode zum Synchronisieren von Dateien auf\n" " Festplatte setzen\n" -#: option.c:310 +#: option.c:336 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: option.c:311 +#: option.c:337 #, c-format msgid "" "\n" @@ -1500,7 +1583,7 @@ msgstr "" " den Postmaster für den alten Cluster anhalten\n" " den Postmaster für den neuen Cluster anhalten\n" -#: option.c:316 +#: option.c:342 #, c-format msgid "" "\n" @@ -1517,7 +1600,7 @@ msgstr "" " das »bin«-Verzeichnis der alten Version (-b BINVERZ)\n" " das »bin«-Verzeichnis der neuen Version (-B BINVERZ)\n" -#: option.c:322 +#: option.c:348 #, c-format msgid "" "\n" @@ -1530,7 +1613,7 @@ msgstr "" " pg_upgrade -d alterCluster/data -D neuerCluster/data -b alterCluster/bin -B neuerCluster/bin\n" "oder\n" -#: option.c:327 +#: option.c:353 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1545,7 +1628,7 @@ msgstr "" " $ export PGBINNEW=neuerCluster/bin\n" " $ pg_upgrade\n" -#: option.c:333 +#: option.c:359 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1560,7 +1643,7 @@ msgstr "" " C:\\> set PGBINNEW=neuerCluster/bin\n" " C:\\> pg_upgrade\n" -#: option.c:339 +#: option.c:365 #, c-format msgid "" "\n" @@ -1569,12 +1652,12 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: option.c:340 +#: option.c:366 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: option.c:380 +#: option.c:406 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1583,32 +1666,32 @@ msgstr "" "Sie müssen das Verzeichnis angeben, wo %s.\n" "Bitte verwenden Sie die Kommandzeilenoption %s oder die Umgebungsvariable %s." -#: option.c:433 +#: option.c:459 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Suche das tatsächliche Datenverzeichnis des alten Clusters" -#: option.c:435 +#: option.c:461 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Suche das tatsächliche Datenverzeichnis des neuen Clusters" -#: option.c:448 +#: option.c:474 #, c-format msgid "could not get data directory using %s: %m" msgstr "konnte Datenverzeichnis mit %s nicht ermitteln: %m" -#: option.c:452 +#: option.c:478 #, c-format msgid "could not get data directory using %s: %s" msgstr "konnte Datenverzeichnis mit %s nicht ermitteln: %s" -#: option.c:500 +#: option.c:526 #, c-format msgid "could not read line %d from file \"%s\": %m" msgstr "konnte Zeile %d aus Datei »%s« nicht lesen: %m" -#: option.c:517 +#: option.c:543 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "vom Benutzer angegebene Portnummer %hu wurde auf %hu korrigiert" @@ -1638,12 +1721,12 @@ msgstr "Kindprozess wurde abnormal beendet: Status %d" msgid "child worker exited abnormally: %m" msgstr "Kindprozess wurde abnormal beendet: %m" -#: pg_upgrade.c:115 +#: pg_upgrade.c:111 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "konnte Zugriffsrechte von Verzeichnis »%s« nicht lesen: %m" -#: pg_upgrade.c:147 +#: pg_upgrade.c:143 #, c-format msgid "" "\n" @@ -1654,17 +1737,17 @@ msgstr "" "Führe Upgrade durch\n" "-------------------" -#: pg_upgrade.c:192 +#: pg_upgrade.c:191 #, c-format msgid "Setting next OID for new cluster" msgstr "Setze nächste OID im neuen Cluster" -#: pg_upgrade.c:216 +#: pg_upgrade.c:215 #, c-format msgid "Sync data directory to disk" msgstr "Synchronisiere Datenverzeichnis auf Festplatte" -#: pg_upgrade.c:230 +#: pg_upgrade.c:231 #, c-format msgid "" "\n" @@ -1675,23 +1758,23 @@ msgstr "" "Upgrade abgeschlossen\n" "---------------------" -#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 -#: pg_upgrade.c:308 pg_upgrade.c:319 +#: pg_upgrade.c:264 pg_upgrade.c:277 pg_upgrade.c:284 pg_upgrade.c:291 +#: pg_upgrade.c:309 pg_upgrade.c:320 #, c-format msgid "directory path for new cluster is too long" msgstr "Verzeichnispfad für neuen Cluster ist zu lang" -#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#: pg_upgrade.c:298 pg_upgrade.c:300 pg_upgrade.c:302 pg_upgrade.c:304 #, c-format msgid "could not create directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" -#: pg_upgrade.c:352 +#: pg_upgrade.c:353 #, c-format msgid "%s: could not find own program executable" msgstr "%s: konnte eigene Programmdatei nicht finden" -#: pg_upgrade.c:378 +#: pg_upgrade.c:379 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1700,7 +1783,7 @@ msgstr "" "Es läuft scheinbar ein Postmaster für den alten Cluster.\n" "Bitte beenden Sie diesen Postmaster und versuchen Sie es erneut." -#: pg_upgrade.c:391 +#: pg_upgrade.c:392 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1709,141 +1792,209 @@ msgstr "" "Es läuft scheinbar ein Postmaster für den neuen Cluster.\n" "Bitte beenden Sie diesen Postmaster und versuchen Sie es erneut." -#: pg_upgrade.c:413 +#: pg_upgrade.c:418 +#, fuzzy, c-format +#| msgid "Setting locale and encoding for new cluster" +msgid "Setting the default char signedness for new cluster" +msgstr "Setze Locale und Kodierung für neuen Cluster" + +#: pg_upgrade.c:446 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "Setze Locale und Kodierung für neuen Cluster" -#: pg_upgrade.c:489 +#: pg_upgrade.c:524 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Analysiere alle Zeilen im neuen Cluster" -#: pg_upgrade.c:502 +#: pg_upgrade.c:537 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Friere alle Zeilen im neuen Cluster ein" -#: pg_upgrade.c:522 +#: pg_upgrade.c:557 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Stelle globale Objekte im neuen Cluster wieder her" -#: pg_upgrade.c:538 +#: pg_upgrade.c:574 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "Stelle Datenbankschemas im neuen Cluster wieder her" -#: pg_upgrade.c:662 +#: pg_upgrade.c:709 #, c-format msgid "Deleting files from new %s" msgstr "Lösche Dateien aus neuem %s" -#: pg_upgrade.c:666 +#: pg_upgrade.c:713 #, c-format msgid "could not delete directory \"%s\"" msgstr "konnte Verzeichnis »%s« nicht löschen" -#: pg_upgrade.c:685 +#: pg_upgrade.c:732 #, c-format msgid "Copying old %s to new server" msgstr "Kopiere altes %s zum neuen Server" -#: pg_upgrade.c:711 +#: pg_upgrade.c:758 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Setze älteste XID im neuen Cluster" -#: pg_upgrade.c:719 +#: pg_upgrade.c:766 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "Setze nächste Transaktions-ID und -epoche im neuen Cluster" -#: pg_upgrade.c:749 +#: pg_upgrade.c:796 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "Setze nächste Multixact-ID und nächstes Offset im neuen Cluster" -#: pg_upgrade.c:773 +#: pg_upgrade.c:820 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Setze älteste Multixact-ID im neuen Cluster" -#: pg_upgrade.c:793 +#: pg_upgrade.c:840 #, c-format msgid "Resetting WAL archives" msgstr "Setze WAL-Archive zurück" -#: pg_upgrade.c:836 +#: pg_upgrade.c:883 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Setze frozenxid und minmxid im neuen Cluster" -#: pg_upgrade.c:838 +#: pg_upgrade.c:885 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Setze minmxid im neuen Cluster" -#: pg_upgrade.c:929 +#: pg_upgrade.c:976 #, c-format msgid "Restoring logical replication slots in the new cluster" msgstr "Stelle logische Replikations-Slots im neuen Cluster wieder her" -#: relfilenumber.c:35 +#: relfilenumber.c:68 +#, fuzzy, c-format +#| msgid "could not fsync file \"%s\": %m" +msgid "could not synchronize file \"%s\": %m" +msgstr "konnte Datei »%s« nicht fsyncen: %m" + +#: relfilenumber.c:114 #, c-format msgid "Cloning user relation files" msgstr "Klone Benutzertabellendateien" -#: relfilenumber.c:38 +#: relfilenumber.c:117 #, c-format msgid "Copying user relation files" msgstr "Kopiere Benutzertabellendateien" -#: relfilenumber.c:41 +#: relfilenumber.c:120 #, c-format msgid "Copying user relation files with copy_file_range" msgstr "Kopiere Benutzertabellendateien mit copy_file_range" -#: relfilenumber.c:44 +#: relfilenumber.c:123 #, c-format msgid "Linking user relation files" msgstr "Verknüpfe Benutzertabellendateien" -#: relfilenumber.c:118 +#: relfilenumber.c:126 +#, fuzzy, c-format +#| msgid "syncing data directory" +msgid "Swapping data directories" +msgstr "synchronisiere Datenverzeichnis" + +#: relfilenumber.c:200 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "alte Datenbank »%s« nicht im neuen Cluster gefunden" -#: relfilenumber.c:221 +#: relfilenumber.c:287 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" + +#: relfilenumber.c:293 relfilenumber.c:297 +#, fuzzy, c-format +#| msgid "could not create directory \"%s\": %m" +msgid "could not create directory \"%s\"" +msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" + +#: relfilenumber.c:301 relfilenumber.c:305 +#, fuzzy, c-format +#| msgid "could not rename file \"%s\" to \"%s\": %m" +msgid "could not rename \"%s\" to \"%s\"" +msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" + +#: relfilenumber.c:375 relfilenumber.c:402 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" + +#: relfilenumber.c:393 relfilenumber.c:420 +#, fuzzy, c-format +#| msgid "could not rename file \"%s\" to \"%s\": %m" +msgid "could not rename \"%s\" to \"%s\": %m" +msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" + +#: relfilenumber.c:396 relfilenumber.c:434 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht lesen: %m" + +#: relfilenumber.c:439 +#, fuzzy, c-format +#| msgid "could not close directory \"%s\": %m" +msgid "could not synchronize directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht schließen: %m" + +#: relfilenumber.c:441 +#, fuzzy, c-format +#| msgid "could not create directory \"%s\": %m" +msgid "could not synchronize parent directory of \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m" + +#: relfilenumber.c:598 #, c-format msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" msgstr "Fehler beim Prüfen auf Existenz der Datei für »%s.%s« (»%s« nach »%s«): %m" -#: relfilenumber.c:238 +#: relfilenumber.c:615 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "konvertiere »%s« nach »%s«" -#: relfilenumber.c:246 +#: relfilenumber.c:623 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "klone »%s« nach »%s«" -#: relfilenumber.c:251 +#: relfilenumber.c:628 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "kopiere »%s« nach »%s«" -#: relfilenumber.c:256 +#: relfilenumber.c:633 #, c-format msgid "copying \"%s\" to \"%s\" with copy_file_range" msgstr "kopiere »%s« nach »%s« mit copy_file_range" -#: relfilenumber.c:261 +#: relfilenumber.c:638 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "verknüpfe »%s« nach »%s«" +#: relfilenumber.c:644 +#, c-format +msgid "should never happen" +msgstr "" + #: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" @@ -1875,7 +2026,7 @@ msgstr "konnte Versionsdatei »%s« nicht öffnen: %m" msgid "could not parse version file \"%s\"" msgstr "konnte Versionsdatei »%s« nicht interpretieren" -#: server.c:310 +#: server.c:317 #, c-format msgid "" "\n" @@ -1884,7 +2035,7 @@ msgstr "" "\n" "%s" -#: server.c:314 +#: server.c:321 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1893,7 +2044,7 @@ msgstr "" "konnte nicht mit dem Postmaster für den alten Cluster verbinden, gestartet mit dem Befehl:\n" "%s" -#: server.c:318 +#: server.c:325 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1902,22 +2053,22 @@ msgstr "" "konnte nicht mit dem Postmaster für den neuen Cluster verbinden, gestartet mit dem Befehl:\n" "%s" -#: server.c:332 +#: server.c:339 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl konnte den Quellserver nicht starten, oder Verbindung fehlgeschlagen" -#: server.c:334 +#: server.c:341 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl konnte den Zielserver nicht starten, oder Verbindung fehlgeschlagen" -#: server.c:379 +#: server.c:386 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" -#: server.c:392 +#: server.c:399 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "libpq-Umgebungsvariable %s hat einen nicht lokalen Serverwert: %s" @@ -1966,11 +2117,6 @@ msgstr "ok" msgid "Checking for hash indexes" msgstr "Prüfe auf Hash-Indexe" -#: version.c:121 -#, c-format -msgid "warning" -msgstr "Warnung" - #: version.c:123 #, c-format msgid "" @@ -2006,17 +2152,17 @@ msgstr "" "ungültigen Indexe neu zu erzeugen. Bis dahin werden diese Indexe nicht\n" "verwendet werden." -#: version.c:153 +#: version.c:187 #, c-format msgid "Checking for extension updates" msgstr "Prüfe auf Aktualisierungen von Erweiterungen" -#: version.c:200 +#: version.c:201 #, c-format msgid "notice" msgstr "Hinweis" -#: version.c:201 +#: version.c:202 #, c-format msgid "" "\n" diff --git a/src/bin/pg_upgrade/po/es.po b/src/bin/pg_upgrade/po/es.po index b5f6055b2a48f..ea5213cd854ea 100644 --- a/src/bin/pg_upgrade/po/es.po +++ b/src/bin/pg_upgrade/po/es.po @@ -1,18 +1,18 @@ # spanish message translation file for pg_upgrade # -# Copyright (c) 2017-2021, PostgreSQL Global Development Group +# Copyright (c) 2017-2024, PostgreSQL Global Development Group # # This file is distributed under the same license as the PostgreSQL package. -# Álvaro Herrera , 2017. +# Álvaro Herrera , 2017, 2024. # Carlos Chapi , 2021. # msgid "" msgstr "" -"Project-Id-Version: pg_upgrade (PostgreSQL) 16\n" +"Project-Id-Version: pg_upgrade (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:19+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" -"Last-Translator: Carlos Chapi \n" +"POT-Creation-Date: 2025-02-16 19:49+0000\n" +"PO-Revision-Date: 2024-11-16 09:10+0100\n" +"Last-Translator: Álvaro Herrera \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" "MIME-Version: 1.0\n" @@ -20,7 +20,243 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: BlackCAT 1.1\n" -#: check.c:69 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "no se pudo obtener el código de salida del subproceso: código de error %lu" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "no se pudo buscar el ID de usuario efectivo %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "el usuario no existe" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "fallo en la búsqueda de nombre de usuario: código de error %lu" + +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "Verificando tipos compuestos definidos por el sistema en tablas de usuario" + +#: check.c:118 +msgid "" +"Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene tipos compuestos definidos por el sistema en\n" +"tablas de usuario. Los OIDs de estos tipos no son estables entre diferentes\n" +"versiones de PostgreSQL, por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "Verificando datos de usuario de tipo «line» incompatible" + +#: check.c:137 +msgid "" +"Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo de dato «line» en tablas de usuario. Este\n" +"tipo de dato cambió su formato interno y de entrada/salida entre las\n" +"versiones de sus clústers antiguo y nuevo, por lo que este clúster no puede\n" +"actualmente ser actualizado. Puede eliminar las columnas problemáticas y\n" +"reiniciar la actualización.\n" + +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "Verificando tipos de datos reg* en datos de usuario" + +#: check.c:181 +msgid "" +"Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene uno de los tipos reg* en tablas de usuario. Estos tipos\n" +"de dato hacen referencia a OIDs de sistema que no son preservados por pg_upgrade,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "Verificando datos de usuario de tipo «aclitem» incompatible" + +#: check.c:198 +msgid "" +"Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «aclitem» en tablas de usuario.\n" +"El formato interno de «aclitem» cambió en PostgreSQL versión 16,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "Verificando columnas de usuario del tipo no válido «unknown»" + +#: check.c:222 +msgid "" +"Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «unknown» en tablas de usuario.\n" +"Este tipo ya no es permitido en tablas,\n" +"por lo que este clúster no puede ser actualizado. Puede\n" +"eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "Verificando columnas de usuario del tipo «sql_identifier»" + +#: check.c:244 +msgid "" +"Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo de dato «sql_identifier» en tablas de usuario.\n" +"El formato en disco para este tipo de dato ha cambiado, por lo que\n" +"este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "Verificando datos de usuario de tipo «jsonb» incompatible" + +#: check.c:260 +msgid "" +"Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «jsonb» en tablas de usuario.\n" +"El formato interno de «jsonb» cambió durante 9.4 beta,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "Verificando tipo de datos «abstime» eliminado en tablas de usuario" + +#: check.c:277 +msgid "" +"Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «abstime» en tablas de usuario.\n" +"El tipo «abstime» fue eliminado en la versión 12 de PostgreSQL,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas, o cambiarlas a otro\n" +"tipo de dato, y reiniciar la actualización.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "Verificando tipo de datos «reltime» eliminado en tablas de usuario" + +#: check.c:290 +msgid "" +"Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «reltime» en tablas de usuario.\n" +"El tipo «reltime» fue eliminado en la versión 12 de PostgreSQL,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas, o cambiarlas a otro\n" +"tipo de dato, y reiniciar la actualización.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "Verificando tipo de datos «tinterval» eliminado en tablas de usuario" + +#: check.c:303 +msgid "" +"Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Su instalación contiene el tipo «tinterval» en tablas de usuario.\n" +"El tipo «tinterval» fue eliminado en la versión 12 de PostgreSQL,\n" +"por lo que este clúster no puede ser actualizado.\n" +"Puede eliminar las columnas problemáticas, o cambiarlas a otro\n" +"tipo de dato, y reiniciar la actualización.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "Verificando el uso de tipos de datos" + +#: check.c:480 +#, c-format +msgid "failed check: %s" +msgstr "falló la comprobación: %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "Una lista de las columnas problemáticas está en el archivo:" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +# FIXME this should probably use plural msgfmt +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "Verificaciones de tipos de datos fallidas: %s" + +#: check.c:563 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -29,7 +265,7 @@ msgstr "" "Verificando Consistencia en Vivo en el Servidor Antiguo\n" "-------------------------------------------------------" -#: check.c:75 +#: check.c:569 #, c-format msgid "" "Performing Consistency Checks\n" @@ -38,7 +274,7 @@ msgstr "" "Verificando Consistencia\n" "------------------------" -#: check.c:221 +#: check.c:718 #, c-format msgid "" "\n" @@ -47,7 +283,7 @@ msgstr "" "\n" "*Los clústers son compatibles*" -#: check.c:229 +#: check.c:726 #, c-format msgid "" "\n" @@ -58,7 +294,7 @@ msgstr "" "Si pg_upgrade falla a partir de este punto, deberá re-ejecutar initdb\n" "en el clúster nuevo antes de continuar." -#: check.c:270 +#: check.c:767 #, c-format msgid "" "Optimizer statistics are not transferred by pg_upgrade.\n" @@ -69,7 +305,7 @@ msgstr "" "Una vez que inicie el servidor nuevo, considere ejecutar:\n" " %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:276 +#: check.c:773 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -78,7 +314,7 @@ msgstr "" "Ejecutando este script se borrarán los archivos de datos del servidor antiguo:\n" " %s" -#: check.c:281 +#: check.c:778 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -91,57 +327,57 @@ msgstr "" "o el directorio de datos del servidor nuevo. El contenido del servidor\n" "antiguo debe ser borrado manualmente." -#: check.c:293 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "Verificando las versiones de los clústers" -#: check.c:305 +#: check.c:802 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "Este programa sólo puede actualizar desde PostgreSQL versión %s y posterior." -#: check.c:310 +#: check.c:807 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "Este programa sólo puede actualizar a PostgreSQL versión %s." -#: check.c:319 +#: check.c:816 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "Este programa no puede usarse para volver a versiones anteriores de PostgreSQL." -#: check.c:324 +#: check.c:821 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "El directorio de datos antiguo y el directorio de binarios antiguo son de versiones diferentes." -#: check.c:327 +#: check.c:824 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "El directorio de datos nuevo y el directorio de binarios nuevo son de versiones diferentes." -#: check.c:342 +#: check.c:839 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "Al verificar servidores en caliente, los números de port antiguo y nuevo deben ser diferentes." -#: check.c:362 +#: check.c:859 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "La base de datos «%s» del clúster nuevo no está vacía: se encontró la relación «%s.%s»" -#: check.c:385 +#: check.c:882 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Verificando los directorios de tablespaces para el nuevo clúster" -#: check.c:396 +#: check.c:893 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "directorio de tablespace para el nuevo clúster ya existe: «%s»" -#: check.c:429 +#: check.c:926 #, c-format msgid "" "\n" @@ -151,7 +387,7 @@ msgstr "" "ADVERTENCIA: el directorio de datos nuevo no debería estar dentro del directorio antiguo,\n" "esto es, %s" -#: check.c:453 +#: check.c:950 #, c-format msgid "" "\n" @@ -160,61 +396,53 @@ msgstr "" "\n" "ADVERTENCIA: las ubicaciones de tablespaces definidos por el usuario no deberían estar dentro del directorio de datos, esto es, %s" -#: check.c:463 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "Creando un script para borrar el clúster antiguo" -#: check.c:466 check.c:639 check.c:755 check.c:850 check.c:979 check.c:1056 -#: check.c:1299 check.c:1373 file.c:339 function.c:163 option.c:476 -#: version.c:116 version.c:292 version.c:426 +#: check.c:1014 #, c-format -msgid "could not open file \"%s\": %s" -msgstr "no se pudo abrir el archivo «%s»: %s" +msgid "could not add execute permission to file \"%s\": %m" +msgstr "no se pudo agregar permisos de ejecución al archivo «%s»: %m" -#: check.c:517 -#, c-format -msgid "could not add execute permission to file \"%s\": %s" -msgstr "no se pudo agregar permisos de ejecución al archivo «%s»: %s" - -#: check.c:537 +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "Verificando que el usuario de base de datos es el usuario de instalación" -#: check.c:553 +#: check.c:1050 #, c-format msgid "database user \"%s\" is not the install user" msgstr "el usuario de base de datos «%s» no es el usuario de instalación" -#: check.c:564 +#: check.c:1061 #, c-format msgid "could not determine the number of users" msgstr "no se pudo determinar el número de usuarios" -#: check.c:572 +#: check.c:1069 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "Sólo el usuario de instalación puede estar definido en el nuevo clúster." -#: check.c:601 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "Verificando los parámetros de conexión de bases de datos" -#: check.c:627 +#: check.c:1124 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0 no debe permitir conexiones, es decir su pg_database.datallowconn debe ser «false»" -#: check.c:654 check.c:775 check.c:873 check.c:999 check.c:1076 check.c:1135 -#: check.c:1196 check.c:1224 check.c:1254 check.c:1313 check.c:1394 -#: function.c:185 version.c:192 version.c:232 version.c:378 +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 #, c-format msgid "fatal" msgstr "fatal" -#: check.c:655 +#: check.c:1151 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" @@ -233,27 +461,27 @@ msgstr "" "conexión. Un listado de las bases de datos con el problema se encuentra en:\n" " %s" -#: check.c:680 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "Verificando transacciones preparadas" -#: check.c:689 +#: check.c:1185 #, c-format msgid "The source cluster contains prepared transactions" msgstr "El clúster de origen contiene transacciones preparadas" -#: check.c:691 +#: check.c:1187 #, c-format msgid "The target cluster contains prepared transactions" msgstr "El clúster de destino contiene transacciones preparadas" -#: check.c:716 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Verificando contrib/isn con discordancia en mecanismo de paso de bigint" -#: check.c:776 +#: check.c:1271 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -272,12 +500,12 @@ msgstr "" "Un listado de funciones problemáticas está en el archivo:\n" " %s" -#: check.c:798 +#: check.c:1293 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Verificando operadores postfix definidos por el usuario" -#: check.c:874 +#: check.c:1368 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -292,12 +520,12 @@ msgstr "" "Una lista de operadores postfix definidos por el usuario aparece en el archivo:\n" " %s" -#: check.c:898 +#: check.c:1392 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "Verificando funciones polimórficas incompatibles" -#: check.c:1000 +#: check.c:1493 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -316,12 +544,12 @@ msgstr "" "«anycompatible». Una lista de los objetos problemáticos está en el archivo:\n" " %s" -#: check.c:1024 +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Verificando tablas WITH OIDS" -#: check.c:1077 +#: check.c:1569 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -336,149 +564,132 @@ msgstr "" "Una lista de tablas con este problema aparece en el archivo:\n" " %s" -#: check.c:1105 +#: check.c:1596 #, c-format -msgid "Checking for system-defined composite types in user tables" -msgstr "Verificando tipos compuestos definidos por el sistema en tablas de usuario" +msgid "Checking for roles starting with \"pg_\"" +msgstr "Verificando roles que empiecen con «pg_»" -#: check.c:1136 +#: check.c:1627 #, c-format msgid "" -"Your installation contains system-defined composite type(s) in user tables.\n" -"These type OIDs are not stable across PostgreSQL versions,\n" -"so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" " %s" msgstr "" -"Su instalación contiene uno o varios tipos compuestos definidos por el sistema en\n" -"tablas de usuario. Los OIDs de estos tipos no son estables entre diferentes\n" -"versiones de PostgreSQL, por lo que este clúster no puede ser actualizado.\n" -"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" -"Un listado de las columnas problemáticas está en el archivo:\n" +"Su instalación contiene nombres de rol que comienzan con «pg_».\n" +"«pg_» es un prefijo reservado para roles de sistema. El clúster\n" +"no puede ser actualizado hasta que esos roles hayan sido renombrados.\n" +"Un listado de los roles que empiezan con «pg_» está en el archivo:\n" " %s" -#: check.c:1164 +#: check.c:1647 #, c-format -msgid "Checking for reg* data types in user tables" -msgstr "Verificando tipos de datos reg* en datos de usuario" +msgid "Checking for user-defined encoding conversions" +msgstr "Verificando conversiones de codificación definidas por el usuario" -#: check.c:1197 +#: check.c:1707 #, c-format msgid "" -"Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains user-defined encoding conversions.\n" +"The conversion function parameters changed in PostgreSQL version 14\n" +"so this cluster cannot currently be upgraded. You can remove the\n" +"encoding conversions in the old cluster and restart the upgrade.\n" +"A list of user-defined encoding conversions is in the file:\n" " %s" msgstr "" -"Su instalación contiene uno de los tipos reg* en tablas de usuario. Estos tipos\n" -"de dato hacen referencia a OIDs de sistema que no son preservados por pg_upgrade,\n" -"por lo que este clúster no puede ser actualizado.\n" -"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" -"Un listado de las columnas problemáticas está en el archivo:\n" +"Su instalación contiene conversiones de codificación definidas por el usuario.\n" +"Los parámetros de la función de conversión cambiaron en PostgreSQL 14\n" +"por lo que este clúster no puede ser actualizado. Puede eliminar\n" +"las conversiones de codificación en el clúster antiguo y reiniciar la actualización.\n" +"Un listado de las conversiones de codificación definidas por el usuario está en el archivo:\n" " %s" -#: check.c:1218 +#: check.c:1746 #, c-format -#| msgid "Checking for incompatible aclitem data type in user tables" -msgid "Checking for incompatible \"aclitem\" data type in user tables" -msgstr "Verificando datos de usuario de tipo «aclitem» incompatible" +msgid "Checking for new cluster logical replication slots" +msgstr "Verificando slots de replicación lógica en el clúster nuevo" -#: check.c:1225 +#: check.c:1754 #, c-format -msgid "" -"Your installation contains the \"aclitem\" data type in user tables.\n" -"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" -"so this cluster cannot currently be upgraded. You can drop the\n" -"problem columns and restart the upgrade. A list of the problem\n" -"columns is in the file:\n" -" %s" -msgstr "" -"Su instalación contiene el tipo «jsonb» en tablas de usuario.\n" -"El formato interno de «jsonb» cambió durante 9.4 beta,\n" -"por lo que este clúster no puede ser actualizado.\n" -"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" -"Un listado de las columnas problemáticas está en el archivo:\n" -" %s" +msgid "could not count the number of logical replication slots" +msgstr "no se pudo contar el número de slots de replicación lógica" -#: check.c:1246 +#: check.c:1759 #, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "Verificando datos de usuario en tipo «jsonb» incompatible" +msgid "expected 0 logical replication slots but found %d" +msgstr "se esperaban 0 slots de replicación lógica pero se encontraron %d" -#: check.c:1255 +#: check.c:1769 check.c:1820 #, c-format -msgid "" -"Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Su instalación contiene el tipo «jsonb» en tablas de usuario.\n" -"El formato interno de «jsonb» cambió durante 9.4 beta,\n" -"por lo que este clúster no puede ser actualizado.\n" -"Puede eliminar las columnas problemáticas y reiniciar la actualización.\n" -"Un listado de las columnas problemáticas está en el archivo:\n" -" %s" +msgid "could not determine parameter settings on new cluster" +msgstr "no se pudo determinar el valor de los parámetros en el clúster nuevo" -#: check.c:1282 +#: check.c:1774 #, c-format -msgid "Checking for roles starting with \"pg_\"" -msgstr "Verificando roles que empiecen con «pg_»" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "«wal_level» debe ser «logical», pero está definido a «%s»" + +#: check.c:1780 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" +msgstr "«max_replicacion_slots» (%d) debe ser mayor o igual al número de slots de replicación lógica en el cluster antiguo (%d)" + +#: check.c:1812 +#, c-format +msgid "Checking for new cluster configuration for subscriptions" +msgstr "Verificando configuraciones del clúster nuevo para suscripciones" -#: check.c:1314 +#: check.c:1824 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "«max_replication_slots» (%d) debe ser mayor o igual al número de suscripciones en el clúster antiguo (%d)" + +#: check.c:1846 +#, c-format +msgid "Checking for valid logical replication slots" +msgstr "Verificando los slots de replicación lógica válidos" + +#: check.c:1898 #, c-format -#| msgid "" -#| "Your installation contains roles starting with \"pg_\".\n" -#| "\"pg_\" is a reserved prefix for system roles, the cluster\n" -#| "cannot be upgraded until these roles are renamed.\n" -#| "A list of roles starting with \"pg_\" is in the file:\n" -#| " %s" msgid "" -"Your installation contains roles starting with \"pg_\".\n" -"\"pg_\" is a reserved prefix for system roles. The cluster\n" -"cannot be upgraded until these roles are renamed.\n" -"A list of roles starting with \"pg_\" is in the file:\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" " %s" msgstr "" -"Su instalación contiene nombres de rol que comienzan con «pg_».\n" -"«pg_» es un prefijo reservado para roles de sistema. El clúster\n" -"no puede ser actualizado hasta que esos roles hayan sido renombrados.\n" -"Un listado de los roles que empiezan con «pg_» está en el archivo:\n" +"Su instalación contiene slots de replicación lógica que no pueden ser actualizados.\n" +"Puede eliminar slots inválidos y/o consumir el WAL pendiente en los otros slots,\n" +"y reiniciar la actualización.\n" +"Un listado de los slots problemáticos está en el archivo:\n" " %s" -#: check.c:1334 +#: check.c:1922 #, c-format -msgid "Checking for user-defined encoding conversions" -msgstr "Verificando conversiones de codificación definidas por el usuario" +msgid "Checking for subscription state" +msgstr "Verificando el estado de suscripción" -#: check.c:1395 +#: check.c:2023 #, c-format msgid "" -"Your installation contains user-defined encoding conversions.\n" -"The conversion function parameters changed in PostgreSQL version 14\n" -"so this cluster cannot currently be upgraded. You can remove the\n" -"encoding conversions in the old cluster and restart the upgrade.\n" -"A list of user-defined encoding conversions is in the file:\n" +"Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" " %s" msgstr "" -"Su instalación contiene conversiones de codificación definidas por el usuario.\n" -"Los parámetros de la función de conversión cambiaron en PostgreSQL 14\n" -"por lo que este clúster no puede ser actualizado. Puede eliminar\n" -"las conversiones de codificación en el clúster antiguo y reiniciar la actualización.\n" -"Un listado de las conversiones de codificación definidas por el usuario está en el archivo:\n" +"Su instalación contiene suscripciones sin origen o que tiene relaciones que no están en estado i (inicializar) o r (listo).\n" +"Puede permitir que la sincronización inicial termine para todas las relaciones y luego reiniciar la actualización.\n" +"Una lista de las suscripciones problemáticas está en el archivo:\n" " %s" -#: controldata.c:129 controldata.c:175 controldata.c:199 controldata.c:508 +#: controldata.c:129 controldata.c:199 #, c-format -msgid "could not get control data using %s: %s" -msgstr "no se pudo obtener datos de control usando %s: %s" +msgid "could not get control data using %s: %m" +msgstr "no se pudo obtener datos de control usando %s: %m" -#: controldata.c:140 +#: controldata.c:139 #, c-format msgid "%d: database cluster state problem" msgstr "%d: problema de estado del clúster" @@ -495,13 +706,18 @@ msgstr "El clúster de destino fue apagado mientras estaba en modo de recuperaci #: controldata.c:165 #, c-format -msgid "The source cluster was not shut down cleanly." -msgstr "El clúster de origen no fue apagado limpiamente." +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "El clúster de origen no fue apagado limpiamente, el estado fue reportado como: «%s»" #: controldata.c:167 #, c-format -msgid "The target cluster was not shut down cleanly." -msgstr "El clúster de destino no fue apagado limpiamente." +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "El clúster de destino no fue apagado limpiamente, el estado fue reportado como: «%s»" + +#: controldata.c:175 controldata.c:507 +#, c-format +msgid "could not get control data using %s: %s" +msgstr "no se pudo obtener datos de control usando %s: %s" #: controldata.c:181 #, c-format @@ -513,139 +729,139 @@ msgstr "Al clúster de origen le falta información de estado:" msgid "The target cluster lacks cluster state information:" msgstr "Al cluster de destino le falta información de estado:" -#: controldata.c:214 dump.c:50 exec.c:119 pg_upgrade.c:517 pg_upgrade.c:554 -#: relfilenumber.c:231 server.c:34 util.c:337 +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:221 +#: controldata.c:220 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d: problema en pg_resetwal" -#: controldata.c:231 controldata.c:241 controldata.c:252 controldata.c:263 -#: controldata.c:274 controldata.c:293 controldata.c:304 controldata.c:315 -#: controldata.c:326 controldata.c:337 controldata.c:348 controldata.c:359 -#: controldata.c:362 controldata.c:366 controldata.c:376 controldata.c:388 -#: controldata.c:399 controldata.c:410 controldata.c:421 controldata.c:432 -#: controldata.c:443 controldata.c:454 controldata.c:465 controldata.c:476 -#: controldata.c:487 controldata.c:498 +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d: problema de extracción de controldata" -#: controldata.c:579 +#: controldata.c:578 #, c-format msgid "The source cluster lacks some required control information:" msgstr "Al clúster de origen le falta información de control requerida:" -#: controldata.c:582 +#: controldata.c:581 #, c-format msgid "The target cluster lacks some required control information:" msgstr "Al clúster de destino le falta información de control requerida:" -#: controldata.c:585 +#: controldata.c:584 #, c-format msgid " checkpoint next XID" msgstr " siguiente XID del último checkpoint" -#: controldata.c:588 +#: controldata.c:587 #, c-format msgid " latest checkpoint next OID" msgstr " siguiente OID del último checkpoint" -#: controldata.c:591 +#: controldata.c:590 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " siguiente MultiXactId del último checkpoint" -#: controldata.c:595 +#: controldata.c:594 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " MultiXactId más antiguo del último checkpoint" -#: controldata.c:598 +#: controldata.c:597 #, c-format msgid " latest checkpoint oldestXID" msgstr " XID más antiguo del último checkpoint" -#: controldata.c:601 +#: controldata.c:600 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " siguiente MultiXactOffset del siguiente checkpoint" -#: controldata.c:604 +#: controldata.c:603 #, c-format msgid " first WAL segment after reset" msgstr " primer segmento de WAL después del reinicio" -#: controldata.c:607 +#: controldata.c:606 #, c-format msgid " float8 argument passing method" msgstr " método de paso de argumentos float8" -#: controldata.c:610 +#: controldata.c:609 #, c-format msgid " maximum alignment" msgstr " alineamiento máximo" -#: controldata.c:613 +#: controldata.c:612 #, c-format msgid " block size" msgstr " tamaño de bloques" -#: controldata.c:616 +#: controldata.c:615 #, c-format msgid " large relation segment size" msgstr " tamaño de segmento de relación grande" -#: controldata.c:619 +#: controldata.c:618 #, c-format msgid " WAL block size" msgstr " tamaño de bloque de WAL" -#: controldata.c:622 +#: controldata.c:621 #, c-format msgid " WAL segment size" msgstr " tamaño de segmento de WAL" -#: controldata.c:625 +#: controldata.c:624 #, c-format msgid " maximum identifier length" msgstr " máximo largo de identificadores" -#: controldata.c:628 +#: controldata.c:627 #, c-format msgid " maximum number of indexed columns" msgstr " máximo número de columnas indexadas" -#: controldata.c:631 +#: controldata.c:630 #, c-format msgid " maximum TOAST chunk size" msgstr " tamaño máximo de trozos TOAST" -#: controldata.c:635 +#: controldata.c:634 #, c-format msgid " large-object chunk size" msgstr " tamaño de trozos de objetos grandes" -#: controldata.c:638 +#: controldata.c:637 #, c-format msgid " dates/times are integers?" msgstr " fechas/horas son enteros?" -#: controldata.c:642 +#: controldata.c:641 #, c-format msgid " data checksum version" msgstr " versión del checksum de datos" -#: controldata.c:644 +#: controldata.c:643 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "No se puede continuar sin la información de control requerida. Terminando" -#: controldata.c:659 +#: controldata.c:658 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -654,77 +870,77 @@ msgstr "" "Alineamientos de pg_controldata antiguo y nuevo no son válidos o no coinciden.\n" "Seguramente un clúster es 32-bit y el otro es 64-bit" -#: controldata.c:663 +#: controldata.c:662 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "Los tamaños de bloque antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:666 +#: controldata.c:665 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "El tamaño máximo de segmento de relación antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:669 +#: controldata.c:668 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "El tamaño de bloques de WAL antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:672 +#: controldata.c:671 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "El tamaño de segmentos de WAL antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:675 +#: controldata.c:674 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "Los máximos largos de identificador antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:678 +#: controldata.c:677 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "La cantidad máxima de columnas indexadas antigua y nueva no son válidos o no coinciden" -#: controldata.c:681 +#: controldata.c:680 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "Los máximos de trozos TOAST antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:686 +#: controldata.c:685 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "Los tamaños de trozos de objetos grandes antiguo y nuevo no son válidos o no coinciden" -#: controldata.c:689 +#: controldata.c:688 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "Los tipos de almacenamiento de fecha/hora antiguo y nuevo no coinciden" -#: controldata.c:702 +#: controldata.c:701 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "El clúster antiguo no usa checksums de datos pero el nuevo sí" -#: controldata.c:705 +#: controldata.c:704 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "El clúster antiguo usa checksums de datos pero el nuevo no" -#: controldata.c:707 +#: controldata.c:706 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "Las versiones de checksum de datos antigua y nueva no coinciden" -#: controldata.c:718 +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "Agregando el sufijo «.old» a global/pg_control" -#: controldata.c:723 +#: controldata.c:722 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" -#: controldata.c:727 +#: controldata.c:726 #, c-format msgid "" "\n" @@ -749,27 +965,32 @@ msgstr "Creando el volcado de objetos globales" msgid "Creating dump of database schemas" msgstr "Creando el volcado de esquemas de bases de datos" -#: exec.c:47 exec.c:52 +#: exec.c:47 +#, c-format +msgid "could not get pg_ctl version data using %s: %m" +msgstr "no se pudo obtener datos de versión de pg_ctl usando %s: %m" + +#: exec.c:51 #, c-format msgid "could not get pg_ctl version data using %s: %s" msgstr "no se pudo obtener datos de versión de pg_ctl usando %s: %s" -#: exec.c:56 +#: exec.c:55 #, c-format msgid "could not get pg_ctl version output from %s" msgstr "no se pudo obtener la salida de versión de pg_ctl de %s" -#: exec.c:113 exec.c:117 +#: exec.c:112 exec.c:116 #, c-format msgid "command too long" msgstr "orden demasiado larga" -#: exec.c:161 pg_upgrade.c:286 +#: exec.c:160 pg_upgrade.c:311 #, c-format msgid "could not open log file \"%s\": %m" msgstr "no se pudo abrir el archivo de registro «%s»: %m" -#: exec.c:193 +#: exec.c:192 #, c-format msgid "" "\n" @@ -778,12 +999,12 @@ msgstr "" "\n" "*falló*" -#: exec.c:196 +#: exec.c:195 #, c-format msgid "There were problems executing \"%s\"" msgstr "Hubo problemas ejecutando «%s»" -#: exec.c:199 +#: exec.c:198 #, c-format msgid "" "Consult the last few lines of \"%s\" or \"%s\" for\n" @@ -792,7 +1013,7 @@ msgstr "" "Consulte las últimas línea de «%s» o «%s» para\n" "saber la causa probable de la falla." -#: exec.c:204 +#: exec.c:203 #, c-format msgid "" "Consult the last few lines of \"%s\" for\n" @@ -801,141 +1022,156 @@ msgstr "" "Consulte las últimas líneas de «%s» para saber\n" "la causa probable de la falla." -#: exec.c:219 pg_upgrade.c:296 +#: exec.c:218 pg_upgrade.c:321 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "no se pudo escribir al archivo de log «%s»" -#: exec.c:245 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s" -msgstr "no se pudo abrir el archivo «%s» para lectura: %s" +msgid "could not open file \"%s\" for reading: %m" +msgstr "no se pudo abrir archivo «%s» para lectura: %m" -#: exec.c:272 +#: exec.c:270 #, c-format msgid "You must have read and write access in the current directory." msgstr "Debe tener privilegios de lectura y escritura en el directorio actual." -#: exec.c:325 exec.c:391 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s" -msgstr "la comprobación de «%s» falló: %s" +msgid "check for \"%s\" failed: %m" +msgstr "la comprobación de «%s» falló: %m" -#: exec.c:328 exec.c:394 +#: exec.c:326 exec.c:392 #, c-format msgid "\"%s\" is not a directory" msgstr "«%s» no es un directorio" -#: exec.c:441 -#, c-format -msgid "check for \"%s\" failed: %m" -msgstr "la comprobación de «%s» falló: %m" - -#: exec.c:446 +#: exec.c:444 #, c-format msgid "check for \"%s\" failed: cannot execute" msgstr "La comprobación de «%s» falló: no se puede ejecutar" -#: exec.c:456 +#: exec.c:454 #, c-format msgid "check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" msgstr "La comprobación de «%s» falló: versión incorrecta: se encontró «%s», se esperaba «%s»" -#: file.c:43 file.c:64 +#: file.c:44 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "error mientras se clonaba la relación «%s.%s» («%s» a «%s»): %s" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "error mientras se clonaba la relación «%s.%s» («%s» a «%s»): %m" + +#: file.c:51 +#, c-format +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "error mientras se clonaba la relación «%s.%s»: no se pudo abrir el archivo «%s»: %m" -#: file.c:50 +#: file.c:56 #, c-format -msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "error mientras se clonaba la relación «%s.%s»: no se pudo abrir el archivo «%s»: %s" +msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "error mientras se clonaba la relación «%s.%s»: no se pudo crear el archivo «%s»: %m" -#: file.c:55 +#: file.c:65 #, c-format -msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "error mientras se clonaba la relación «%s.%s»: no se pudo crear el archivo «%s»: %s" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "error mientras se clonaba la relación «%s.%s» («%s» a «%s»): %s" -#: file.c:90 file.c:193 +#: file.c:91 file.c:160 file.c:233 #, c-format -msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo leer el archivo «%s»: %s" +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo abrir el archivo «%s»: %m" -#: file.c:95 file.c:202 +#: file.c:96 file.c:165 file.c:242 #, c-format -msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo crear el archivo «%s»: %s" +msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo crear el archivo «%s»: %m" -#: file.c:109 file.c:226 +#: file.c:110 file.c:266 #, c-format -msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %s" -msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo leer el archivo «%s»: %s" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo leer el archivo «%s»: %m" -#: file.c:121 file.c:304 +#: file.c:122 file.c:344 #, c-format -msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %s" -msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo escribir el archivo «%s»: %s" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo escribir el archivo «%s»: %m" -#: file.c:135 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "error mientras se copiaba la relación «%s.%s» («%s» a «%s»): %s" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "error mientras se copiaba la relación «%s.%s» («%s» a «%s»): %m" -#: file.c:154 +#: file.c:172 #, c-format -msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "error mientras se creaba el link para la relación «%s.%s» («%s» a «%s»): %s" +msgid "error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo copiar el rango desde «%s» a «%s»: %m" -#: file.c:197 +#: file.c:194 #, c-format -msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %s" -msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo hacer stat a «%s»: %s" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "error mientras se creaba el link para la relación «%s.%s» («%s» a «%s»): %m" -#: file.c:229 +#: file.c:237 +#, c-format +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" +msgstr "error mientras se copiaba la relación «%s.%s»: no se pudo hacer stat a «%s»: %m" + +#: file.c:269 #, c-format msgid "error while copying relation \"%s.%s\": partial page found in file \"%s\"" msgstr "error mientras se copiaba la relación «%s.%s»: se encontró una página parcial en el archivo «%s»" -#: file.c:331 file.c:348 +#: file.c:371 file.c:387 #, c-format -msgid "could not clone file between old and new data directories: %s" -msgstr "no se pudo clonar el archivo entre los directorios viejo y nuevo: %s" +msgid "could not clone file between old and new data directories: %m" +msgstr "no se pudo clonar el archivo entre los directorios viejo y nuevo: %m" -#: file.c:344 +#: file.c:383 file.c:420 #, c-format -msgid "could not create file \"%s\": %s" -msgstr "no se pudo crear el archivo «%s»: %s" +msgid "could not create file \"%s\": %m" +msgstr "no se pudo crear archivo «%s»: %m" -#: file.c:355 +#: file.c:393 #, c-format msgid "file cloning not supported on this platform" msgstr "el clonado de archivos no está soportado en esta plataforma" -#: file.c:372 +#: file.c:424 +#, c-format +msgid "could not copy file range between old and new data directories: %m" +msgstr "no se pudo clonar el archivo entre los directorios viejo y nuevo: %m" + +#: file.c:430 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range no está soportado en esta plataforma" + +#: file.c:447 #, c-format msgid "" -"could not create hard link between old and new data directories: %s\n" +"could not create hard link between old and new data directories: %m\n" "In link mode the old and new data directories must be on the same file system." msgstr "" -"No se pudo crear un link duro entre los directorios de datos nuevo y antiguo: %s\n" +"No se pudo crear un link duro entre los directorios de datos nuevo y antiguo: %m\n" "En modo link los directorios de dato nuevo y antiguo deben estar en el mismo sistema de archivos." -#: function.c:128 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "Verificando la presencia de las bibliotecas requeridas" -#: function.c:165 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "no se pudo cargar la biblioteca «%s»: %s" -#: function.c:176 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "En la base de datos: %s\n" -#: function.c:186 +#: function.c:211 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -950,51 +1186,51 @@ msgstr "" "de las bibliotecas problemáticas está en el archivo:\n" " %s" -#: info.c:126 +#: info.c:128 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "Los nombres de relación para OID %u en la base de datos «%s» no coinciden: nombre antiguo «%s.%s», nombre nuevo «%s.%s»" -#: info.c:146 +#: info.c:148 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "No hubo coincidencia en las tablas nueva y antigua en la base de datos «%s»" -#: info.c:227 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " que es un índice en «%s.%s»" -#: info.c:237 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " que es un índice en el OID %u" -#: info.c:249 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " que es la tabla TOAST para «%s.%s»" -#: info.c:257 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " que es la tabla TOAST para el OID %u" -#: info.c:261 +#: info.c:263 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "" "No se encontró equivalente en el clúster antiguo para la relación nueva con OID %u\n" "en la base de datos «%s»: %s" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "" "No se encontró equivalente en el clúster nuevo para la antigua relación con OID %u\n" "en la base de datos «%s»: %s" -#: info.c:289 +#: info.c:300 #, c-format msgid "" "\n" @@ -1003,7 +1239,7 @@ msgstr "" "\n" "bases de datos de origen:" -#: info.c:291 +#: info.c:302 #, c-format msgid "" "\n" @@ -1012,94 +1248,104 @@ msgstr "" "\n" "bases de datos de destino:" -#: info.c:329 +#: info.c:346 #, c-format msgid "template0 not found" msgstr "template0 no encontrado" -#: info.c:645 +#: info.c:805 #, c-format -msgid "Database: %s" -msgstr "Base de datos: %s" +msgid "Database: \"%s\"" +msgstr "Base de datos: «%s»" -#: info.c:657 +#: info.c:818 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s" -msgstr "relname: %s.%s: reloid: %u reltblspace: %s" +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "relname: «%s.%s»: reloid: %u reltblspace: «%s»" -#: option.c:101 +#: info.c:832 +#, c-format +msgid "Logical replication slots in the database:" +msgstr "Slots de replicación lógica en la base de datos:" + +#: info.c:838 +#, c-format +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "nombre de slot: «%s», plugin de salida: «%s», two_phase: %s" + +#: option.c:105 #, c-format msgid "%s: cannot be run as root" msgstr "%s: no puede ejecutarse como root" -#: option.c:168 +#: option.c:172 #, c-format msgid "invalid old port number" msgstr "número de puerto antiguo no válido" -#: option.c:173 +#: option.c:177 #, c-format msgid "invalid new port number" msgstr "número de puerto nuevo no válido" -#: option.c:203 +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Pruebe «%s --help» para mayor información.\n" -#: option.c:210 +#: option.c:223 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: option.c:213 +#: option.c:229 #, c-format msgid "Running in verbose mode" msgstr "Ejecutando en modo verboso" -#: option.c:231 +#: option.c:247 msgid "old cluster binaries reside" msgstr "residen los binarios del clúster antiguo" -#: option.c:233 +#: option.c:249 msgid "new cluster binaries reside" msgstr "residen los binarios del clúster nuevo" -#: option.c:235 +#: option.c:251 msgid "old cluster data resides" msgstr "residen los datos del clúster antiguo" -#: option.c:237 +#: option.c:253 msgid "new cluster data resides" msgstr "residen los datos del clúster nuevo" -#: option.c:239 +#: option.c:255 msgid "sockets will be created" msgstr "se crearán los sockets" -#: option.c:256 option.c:356 +#: option.c:272 option.c:374 #, c-format msgid "could not determine current directory" msgstr "no se pudo identificar el directorio actual" -#: option.c:259 +#: option.c:275 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "no se puede ejecutar pg_upgrade desde dentro del directorio de datos del clúster nuevo en Windows" -#: option.c:268 +#: option.c:284 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" "\n" msgstr "pg_upgrade actualiza un clúster PostgreSQL a una versión «mayor» diferente.\n" -#: option.c:269 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: option.c:270 +#: option.c:286 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1108,17 +1354,17 @@ msgstr "" " pg_upgrade [OPCIÓN]...\n" "\n" -#: option.c:271 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "Opciones:\n" -#: option.c:272 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINDIR directorio de ejecutables del clúster antiguo\n" -#: option.c:273 +#: option.c:289 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1127,97 +1373,107 @@ msgstr "" " -B, --new-bindir=BINDIR directorio de ejecutables del clúster nuevo\n" " (por omisión el mismo directorio que pg_upgrade)\n" -#: option.c:275 +#: option.c:291 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check sólo verificar clústers, no cambiar datos\n" -#: option.c:276 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATADIR directorio de datos del clúster antiguo\n" -#: option.c:277 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATADIR directorio de datos del clúster nuevo\n" -#: option.c:278 +#: option.c:294 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs=NUM máximo de procesos paralelos para restaurar\n" -#: option.c:279 +#: option.c:295 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr " -k, --link enlazar (link) archivos en vez de copiarlos\n" -#: option.c:280 +#: option.c:296 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n" -#: option.c:281 +#: option.c:297 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=OPCIONES opciones a pasar al servidor antiguo\n" -#: option.c:282 +#: option.c:298 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=OPCIONES opciones a pasar al servidor nuevo\n" -#: option.c:283 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PUERTO número de puerto del clúster antiguo (def. %d)\n" -#: option.c:284 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PUERTO número de puerto del clúster nuevo (def. %d)\n" -#: option.c:285 +#: option.c:301 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain preservar archivos SQL y logs en caso de éxito\n" -#: option.c:286 +#: option.c:302 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr " -s, --socketdir=DIR directorio de sockets a usar (omisión: dir. actual)\n" -#: option.c:287 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=NOMBRE superusuario del clúster (def. «%s»)\n" -#: option.c:288 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose activar registro interno verboso\n" -#: option.c:289 +#: option.c:305 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: option.c:290 +#: option.c:306 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr " --clone clonar los archivos en vez de copiarlos\n" -#: option.c:291 +#: option.c:307 #, c-format msgid " --copy copy files to new cluster (default)\n" msgstr " --copy copiar los archivos al clúster nuevo (por omisión)\n" -#: option.c:292 +#: option.c:308 +#, c-format +msgid " --copy-file-range copy files to new cluster with copy_file_range\n" +msgstr " --copy-file-range copiar archivos usando copy_file_range\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=MÉTODO definir método de sincronizar archivos a disco\n" + +#: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: option.c:293 +#: option.c:311 #, c-format msgid "" "\n" @@ -1232,7 +1488,7 @@ msgstr "" " apagar el postmaster que atiende al clúster antiguo\n" " apagar el postmaster que atiende al clúster nuevo\n" -#: option.c:298 +#: option.c:316 #, c-format msgid "" "\n" @@ -1249,7 +1505,7 @@ msgstr "" " el directorio «bin» para la versión antigua (-b BINDIR)\n" " el directorio «bin» para la versión nueva (-B BINDIR)\n" -#: option.c:304 +#: option.c:322 #, c-format msgid "" "\n" @@ -1262,7 +1518,7 @@ msgstr "" " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n" "o\n" -#: option.c:309 +#: option.c:327 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1277,7 +1533,7 @@ msgstr "" " $ export PGBINNEW=clusterNuevo/bin\n" " $ pg_upgrade\n" -#: option.c:315 +#: option.c:333 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1292,7 +1548,7 @@ msgstr "" " C:\\> set PGBINNEW=clusterNuevo/bin\n" " C:\\> pg_upgrade\n" -#: option.c:321 +#: option.c:339 #, c-format msgid "" "\n" @@ -1301,12 +1557,12 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: option.c:322 +#: option.c:340 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: option.c:362 +#: option.c:380 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1315,45 +1571,50 @@ msgstr "" "Debe identificar el directorio donde %s.\n" "Por favor use la opción %s o la variable de ambiente %s." -#: option.c:415 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Buscando el directorio de datos real para el clúster de origen" -#: option.c:417 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Buscando el directorio de datos real para el clúster de destino" -#: option.c:430 option.c:435 +#: option.c:448 +#, c-format +msgid "could not get data directory using %s: %m" +msgstr "no se pudo obtener el directorio de datos usando %s: %m" + +#: option.c:452 #, c-format msgid "could not get data directory using %s: %s" msgstr "no se pudo obtener el directorio de datos usando %s: %s" -#: option.c:484 +#: option.c:500 #, c-format -msgid "could not read line %d from file \"%s\": %s" -msgstr "no se pudo leer la línea %d del archivo «%s»: %s" +msgid "could not read line %d from file \"%s\": %m" +msgstr "no se pudo leer la línea %d del archivo «%s»: %m" -#: option.c:501 +#: option.c:517 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "número de port entregado por el usuario %hu corregido a %hu" #: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker process: %s" -msgstr "no se pudo crear el proceso hijo: %s" +msgid "could not create worker process: %m" +msgstr "no se pudo crear el proceso hijo: %m" #: parallel.c:143 parallel.c:253 #, c-format -msgid "could not create worker thread: %s" -msgstr "no se pudo crear el thread: %s" +msgid "could not create worker thread: %m" +msgstr "no se pudo crear el thread trabajador: %m" #: parallel.c:294 #, c-format -msgid "%s() failed: %s" -msgstr "%s() falló: %s" +msgid "%s() failed: %m" +msgstr "%s() falló: %m" #: parallel.c:298 #, c-format @@ -1362,15 +1623,15 @@ msgstr "el proceso hijo terminó anormalmente: estado %d" #: parallel.c:313 #, c-format -msgid "child worker exited abnormally: %s" -msgstr "el thread terminó anormalmente: %s" +msgid "child worker exited abnormally: %m" +msgstr "el hijo trabajador terminó anormalmente: %m" -#: pg_upgrade.c:107 +#: pg_upgrade.c:115 #, c-format -msgid "could not read permissions of directory \"%s\": %s" -msgstr "no se pudo obtener los permisos del directorio «%s»: %s" +msgid "could not read permissions of directory \"%s\": %m" +msgstr "no se pudo obtener los permisos del directorio «%s»: %m" -#: pg_upgrade.c:139 +#: pg_upgrade.c:147 #, c-format msgid "" "\n" @@ -1381,17 +1642,17 @@ msgstr "" "Llevando a cabo el Upgrade\n" "--------------------------" -#: pg_upgrade.c:184 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "Seteando siguiente OID para el nuevo clúster" -#: pg_upgrade.c:193 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "Sincronizando directorio de datos a disco" -#: pg_upgrade.c:205 +#: pg_upgrade.c:230 #, c-format msgid "" "\n" @@ -1402,23 +1663,23 @@ msgstr "" "Actualización Completa\n" "----------------------" -#: pg_upgrade.c:238 pg_upgrade.c:251 pg_upgrade.c:258 pg_upgrade.c:265 -#: pg_upgrade.c:283 pg_upgrade.c:294 +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 #, c-format msgid "directory path for new cluster is too long" msgstr "nombre de directorio para el nuevo clúster es demasiado largo" -#: pg_upgrade.c:272 pg_upgrade.c:274 pg_upgrade.c:276 pg_upgrade.c:278 +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 #, c-format msgid "could not create directory \"%s\": %m" msgstr "no se pudo crear el directorio «%s»: %m" -#: pg_upgrade.c:327 +#: pg_upgrade.c:352 #, c-format msgid "%s: could not find own program executable" msgstr "%s: no se pudo encontrar el ejecutable propio" -#: pg_upgrade.c:353 +#: pg_upgrade.c:378 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1427,7 +1688,7 @@ msgstr "" "Parece haber un postmaster sirviendo el clúster antiguo.\n" "Por favor detenga ese postmaster e inténtelo nuevamente." -#: pg_upgrade.c:366 +#: pg_upgrade.c:391 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1436,81 +1697,86 @@ msgstr "" "Parece haber un postmaster sirviendo el clúster nuevo.\n" "Por favor detenga ese postmaster e inténtelo nuevamente." -#: pg_upgrade.c:388 +#: pg_upgrade.c:413 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "Estableciendo la configuración regional y codificación para el nuevo clúster" -#: pg_upgrade.c:450 +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Analizando todas las filas en el clúster nuevo" -#: pg_upgrade.c:463 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Congelando todas las filas en el nuevo clúster" -#: pg_upgrade.c:483 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Restaurando objetos globales en el nuevo clúster" -#: pg_upgrade.c:499 +#: pg_upgrade.c:538 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "Restaurando esquemas de bases de datos en el clúster nuevo" -#: pg_upgrade.c:605 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "Eliminando archivos del nuevo %s" -#: pg_upgrade.c:609 +#: pg_upgrade.c:666 #, c-format msgid "could not delete directory \"%s\"" msgstr "no se pudo eliminar directorio «%s»" -#: pg_upgrade.c:628 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "Copiando el %s antiguo al nuevo servidor" -#: pg_upgrade.c:654 +#: pg_upgrade.c:711 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Estableciendo XID más antiguo para el nuevo clúster" -#: pg_upgrade.c:662 +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "Seteando el ID de transacción y «época» siguientes en el nuevo clúster" -#: pg_upgrade.c:692 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "Seteando el multixact ID y offset siguientes en el nuevo clúster" -#: pg_upgrade.c:716 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Seteando el multixact ID más antiguo en el nuevo clúster" -#: pg_upgrade.c:736 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "Reseteando los archivos de WAL" -#: pg_upgrade.c:779 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Seteando contadores frozenxid y minmxid en el clúster nuevo" -#: pg_upgrade.c:781 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Seteando contador minmxid en el clúster nuevo" +#: pg_upgrade.c:929 +#, c-format +msgid "Restoring logical replication slots in the new cluster" +msgstr "Restaurando slots de replicación lógica en el nuevo clúster" + #: relfilenumber.c:35 #, c-format msgid "Cloning user relation files" @@ -1523,35 +1789,45 @@ msgstr "Copiando archivos de relaciones de usuario" #: relfilenumber.c:41 #, c-format +msgid "Copying user relation files with copy_file_range" +msgstr "Copiando archivos de relaciones de usuario con copy_file_range" + +#: relfilenumber.c:44 +#, c-format msgid "Linking user relation files" msgstr "Enlazando archivos de relaciones de usuario" -#: relfilenumber.c:115 +#: relfilenumber.c:118 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "la base de datos «%s» no se encontró en el clúster nuevo" -#: relfilenumber.c:218 +#: relfilenumber.c:221 #, c-format -msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "error mientras se comprobaba la existencia del archivo «%s.%s» («%s» a «%s»); %s" +msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "error mientras se comprobaba la existencia del archivo «%s.%s» («%s» a «%s»); %m" -#: relfilenumber.c:236 +#: relfilenumber.c:238 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "reescribiendo «%s» a «%s»" -#: relfilenumber.c:244 +#: relfilenumber.c:246 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "clonando «%s» a «%s»" -#: relfilenumber.c:249 +#: relfilenumber.c:251 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "copiando «%s» a «%s»" -#: relfilenumber.c:254 +#: relfilenumber.c:256 +#, c-format +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "copiando «%s» a «%s» con copy_file_range" + +#: relfilenumber.c:261 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "enlazando «%s» a «%s»" @@ -1587,7 +1863,7 @@ msgstr "no se pudo abrir el archivo de versión «%s»: %m" msgid "could not parse version file \"%s\"" msgstr "no se pudo interpretar el archivo de versión «%s»" -#: server.c:288 +#: server.c:310 #, c-format msgid "" "\n" @@ -1596,7 +1872,7 @@ msgstr "" "\n" "%s" -#: server.c:292 +#: server.c:314 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1605,7 +1881,7 @@ msgstr "" "no se pudo conectar al postmaster de origen iniciado con la orden:\n" "%s" -#: server.c:296 +#: server.c:318 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1614,22 +1890,22 @@ msgstr "" "no se pudo conectar al postmaster de destino iniciado con la orden:\n" "%s" -#: server.c:310 +#: server.c:332 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl no pudo iniciar el servidor de origen, o la conexión falló" -#: server.c:312 +#: server.c:334 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl no pudo iniciar el servidor de destino, o la conexión falló" -#: server.c:357 +#: server.c:379 #, c-format msgid "out of memory" msgstr "memoria agotada" -#: server.c:370 +#: server.c:392 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "la variable de ambiente libpq %s tiene un valor de servidor no-local: %s" @@ -1650,8 +1926,8 @@ msgstr "el directorio de tablespace «%s» no existe" #: tablespace.c:87 #, c-format -msgid "could not stat tablespace directory \"%s\": %s" -msgstr "no se pudo hace stat al directorio de tablespace «%s»: %s" +msgid "could not stat tablespace directory \"%s\": %m" +msgstr "no se pudo hace stat al directorio de tablespace «%s»: %m" #: tablespace.c:92 #, c-format @@ -1673,63 +1949,17 @@ msgstr "no se pudo acceder al directorio «%s»: %m" msgid "ok" msgstr "éxito" -#: version.c:184 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "Verificando datos de usuario de tipo «line» incompatible" - -#: version.c:193 -#, c-format -msgid "" -"Your installation contains the \"line\" data type in user tables.\n" -"This data type changed its internal and input/output format\n" -"between your old and new versions so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Su instalación contiene el tipo de dato «line» en tablas de usuario. Este\n" -"tipo de dato cambió su formato interno y de entrada/salida entre las\n" -"versiones de sus clústers antiguo y nuevo, por lo que este clúster no puede\n" -"actualmente ser actualizado. Puede eliminar las columnas problemáticas y\n" -"reiniciar la actualización. Un listado de las columnas problemáticas está\n" -"en el archivo:\n" -" %s" - -#: version.c:224 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "Verificando columnas de usuario del tipo no válido «unknown»" - -#: version.c:233 -#, c-format -msgid "" -"Your installation contains the \"unknown\" data type in user tables.\n" -"This data type is no longer allowed in tables, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Su instalación contiene el tipo «unknown» en tablas de usuario.\n" -"Este tipo ya no es permitido en tablas,\n" -"por lo que este clúster no puede ser actualizado. Puede\n" -"eliminar las columnas problemáticas y reiniciar la actualización.\n" -"Un listado de las columnas problemáticas está en el archivo:\n" -" %s" - -#: version.c:257 +#: version.c:44 #, c-format msgid "Checking for hash indexes" msgstr "Verificando índices hash" -#: version.c:335 +#: version.c:121 #, c-format msgid "warning" msgstr "atención" -#: version.c:337 +#: version.c:123 #, c-format msgid "" "\n" @@ -1744,7 +1974,7 @@ msgstr "" "con la orden REINDEX. Después de la actualización, se le entregarán\n" "instrucciones de REINDEX." -#: version.c:343 +#: version.c:129 #, c-format msgid "" "\n" @@ -1763,39 +1993,17 @@ msgstr "" "cuando se ejecute en psql con el superusuario de la base de datos recreará\n" "los índices no válidos; hasta entonces, ninguno de esos índices será usado." -#: version.c:369 -#, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "Verificando columnas de usuario del tipo «sql_identifier»" - -#: version.c:379 -#, c-format -msgid "" -"Your installation contains the \"sql_identifier\" data type in user tables.\n" -"The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Su instalación contiene el tipo de dato «sql_identifier» en tablas de usuario.\n" -"El formato en disco para este tipo de dato ha cambiado, por lo que\n" -"este clúster no puede ser actualizado.\n" -"Puede eliminar las columnas problemáticas y reiniciar la actualización\n" -"Un listado de las columnas problemáticas está en el archivo:\n" -" %s" - -#: version.c:402 +#: version.c:153 #, c-format msgid "Checking for extension updates" msgstr "Verificando actualizaciones para extensiones" -#: version.c:450 +#: version.c:200 #, c-format msgid "notice" msgstr "aviso" -#: version.c:451 +#: version.c:201 #, c-format msgid "" "\n" diff --git a/src/bin/pg_upgrade/po/fr.po b/src/bin/pg_upgrade/po/fr.po index 94d1775115555..6117d1fb48d91 100644 --- a/src/bin/pg_upgrade/po/fr.po +++ b/src/bin/pg_upgrade/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:19+0000\n" -"PO-Revision-Date: 2023-07-30 10:37+0200\n" +"POT-Creation-Date: 2024-10-29 18:20+0000\n" +"PO-Revision-Date: 2024-10-30 07:41+0100\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,9 +19,244 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: check.c:69 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "n'a pas pu trouver l'identifiant réel %ld de l'utilisateur : %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "l'utilisateur n'existe pas" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "Vérification des types composites définis par le système dans les tables utilisateurs" + +#: check.c:118 +msgid "" +"Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient des types composites définis par le système dans vos tables\n" +"utilisateurs. Les OID de ces types ne sont pas stables entre différentes versions\n" +"de PostgreSQL, donc cette instance ne peut pas être mise à jour actuellement. Vous pouvez\n" +"supprimer les colonnes problématiques, puis relancer la mise à jour.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "Vérification des types de données line incompatibles" + +#: check.c:137 +msgid "" +"Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « line » dans vos tables utilisateurs.\n" +"Ce type de données a changé de format interne et en entrée/sortie entre vos ancienne\n" +"et nouvelle versions, donc cette instance ne peut pas être mise à jour\n" +"actuellement. Vous pouvez supprimer les colonnes problématiques et relancer la mise à jour.\n" + +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "Vérification des types de données reg* dans les tables utilisateurs" + +#: check.c:181 +msgid "" +"Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient un des types de données reg* dans vos tables\n" +"utilisateurs. Ces types de données référencent des OID système qui ne sont\n" +"pas préservés par pg_upgrade, donc cette instance ne peut pas être mise à\n" +"jour actuellement. Vous pouvez supprimer les colonnes problématiques et relancer\n" +"la mise à jour.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "Vérification des types de données « aclitem » incompatibles" + +#: check.c:198 +msgid "" +"Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient un type de données « aclitem » dans vos tables utilisateurs.\n" +"Le format interne de « aclitem » a changé lors du développement de la version 16, donc\n" +"cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer les\n" +"colonnes problématiques et relancer la mise à jour.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "Vérification des colonnes utilisateurs « unknown » invalides" + +#: check.c:222 +msgid "" +"Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « unknown » dans vos tables\n" +"utilisateurs. Ce type de données n'est plus autorisé dans les tables, donc\n" +"cette instance ne peut pas être mise à jour pour l'instant. Vous pouvez\n" +"supprimer les colonnes problématiques, puis relancer la mise à jour.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "Vérification des colonnes utilisateurs « sql_identifier » invalides" + +#: check.c:244 +msgid "" +"Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « sql_identifier » dans les tables\n" +"utilisateurs. Le format sur disque pour ce type de données a changé,\n" +"donc cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer\n" +"les colonnes problématiques, puis relancer la mise à jour.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "Vérification du type de données « json » incompatible dans les tables utilisateurs" + +#: check.c:260 +msgid "" +"Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "" +"Votre installation contient un type de données « jsonb » dans vos tables utilisateurs.\n" +"Le format interne de « jsonb » a changé lors du développement de la version 9.4 beta, donc\n" +"cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer les\n" +"colonnes problématiques et relancer la mise à jour.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "Vérification du type de données « abstime » supprimé dans les tables utilisateurs" + +#: check.c:277 +msgid "" +"Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « abstime » dans les tables utilisateurs.\n" +"Le type «abstime » a été supprimé dans PostgreSQL version 12,\n" +"donc cette instance ne peut pas être mise à jour pour l'instant. Vous pouvez\n" +"supprimer les colonnes problématiques ou les convertir en un autre type de données,\n" +"et relancer la mise à jour.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "Vérification du type de données « reltime » supprimé dans les tables utilisateurs" + +#: check.c:290 +msgid "" +"Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « reltime » dans les tables utilisateurs.\n" +"Le type «reltime » a été supprimé dans PostgreSQL version 12,\n" +"donc cette instance ne peut pas être mise à jour pour l'instant. Vous pouvez\n" +"supprimer les colonnes problématiques ou les convertir en un autre type de données,\n" +"et relancer la mise à jour.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "Vérification du type de données « tinterval » supprimé dans les tables utilisateurs" + +#: check.c:303 +msgid "" +"Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Votre installation contient le type de données « tinterval » dans les tables utilisateurs.\n" +"Le type « tinterval » a été supprimé dans PostgreSQL version 12,\n" +"donc cette instance ne peut pas être mise à jour pour l'instant. Vous pouvez\n" +"supprimer les colonnes problématiques ou les convertir en un autre type de données,\n" +"et relancer la mise à jour.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "Vérification de l'utilisation du type de données" + +#: check.c:480 +#, c-format +msgid "failed check: %s" +msgstr "vérification échouée : %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "Une liste des colonnes problématiques se trouve dans le fichier :" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "Échec de la vérification des types de données : %s" + +#: check.c:563 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -30,7 +265,7 @@ msgstr "" "Exécution de tests de cohérence sur l'ancien serveur\n" "----------------------------------------------------" -#: check.c:75 +#: check.c:569 #, c-format msgid "" "Performing Consistency Checks\n" @@ -39,7 +274,7 @@ msgstr "" "Exécution de tests de cohérence\n" "-------------------------------" -#: check.c:221 +#: check.c:718 #, c-format msgid "" "\n" @@ -48,7 +283,7 @@ msgstr "" "\n" "*Les instances sont compatibles*" -#: check.c:229 +#: check.c:726 #, c-format msgid "" "\n" @@ -59,7 +294,7 @@ msgstr "" "Si pg_upgrade échoue après cela, vous devez ré-exécuter initdb\n" "sur la nouvelle instance avant de continuer." -#: check.c:270 +#: check.c:767 #, c-format msgid "" "Optimizer statistics are not transferred by pg_upgrade.\n" @@ -70,7 +305,7 @@ msgstr "" "Une fois le nouveau serveur démarré, pensez à exécuter :\n" " %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:276 +#: check.c:773 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -79,7 +314,7 @@ msgstr "" "Exécuter ce script supprimera les fichiers de données de l'ancienne instance :\n" " %s" -#: check.c:281 +#: check.c:778 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -93,57 +328,57 @@ msgstr "" "de l'ancienne instance. Le contenu de l'ancienne instance doit être supprimé\n" "manuellement." -#: check.c:293 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "Vérification des versions des instances" -#: check.c:305 +#: check.c:802 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "Cet outil peut seulement mettre à jour les versions %s et ultérieures de PostgreSQL." -#: check.c:310 +#: check.c:807 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "Cet outil peut seulement mettre à jour vers la version %s de PostgreSQL." -#: check.c:319 +#: check.c:816 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "Cet outil ne peut pas être utilisé pour mettre à jour vers des versions majeures plus anciennes de PostgreSQL." -#: check.c:324 +#: check.c:821 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "Les répertoires des données de l'ancienne instance et des binaires sont de versions majeures différentes." -#: check.c:327 +#: check.c:824 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "Les répertoires des données de la nouvelle instance et des binaires sont de versions majeures différentes." -#: check.c:342 +#: check.c:839 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "Lors de la vérification d'un serveur en production, l'ancien numéro de port doit être différent du nouveau." -#: check.c:362 +#: check.c:859 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "La nouvelle instance « %s » n'est pas vide : relation « %s.%s » trouvée" -#: check.c:385 +#: check.c:882 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Vérification des répertoires de tablespace de la nouvelle instance" -#: check.c:396 +#: check.c:893 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "le répertoire du tablespace de la nouvelle instance existe déjà : « %s »" -#: check.c:429 +#: check.c:926 #, c-format msgid "" "\n" @@ -152,7 +387,7 @@ msgstr "" "\n" "AVERTISSEMENT : le nouveau répertoire de données ne doit pas être à l'intérieur de l'ancien répertoire de données, %s" -#: check.c:453 +#: check.c:950 #, c-format msgid "" "\n" @@ -161,61 +396,53 @@ msgstr "" "\n" "AVERTISSEMENT : les emplacements des tablespaces utilisateurs ne doivent pas être à l'intérieur du répertoire de données, %s" -#: check.c:463 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "Création du script pour supprimer l'ancienne instance" -#: check.c:466 check.c:639 check.c:755 check.c:850 check.c:979 check.c:1056 -#: check.c:1299 check.c:1373 file.c:339 function.c:163 option.c:476 -#: version.c:116 version.c:292 version.c:426 +#: check.c:1014 #, c-format -msgid "could not open file \"%s\": %s" -msgstr "n'a pas pu ouvrir le fichier « %s » : %s" +msgid "could not add execute permission to file \"%s\": %m" +msgstr "n'a pas pu ajouter les droits d'exécution pour le fichier « %s » : %m" -#: check.c:517 -#, c-format -msgid "could not add execute permission to file \"%s\": %s" -msgstr "n'a pas pu ajouter les droits d'exécution pour le fichier « %s » : %s" - -#: check.c:537 +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "Vérification que l'utilisateur de la base de données est l'utilisateur d'installation" -#: check.c:553 +#: check.c:1050 #, c-format msgid "database user \"%s\" is not the install user" msgstr "l'utilisateur de la base de données « %s » n'est pas l'utilisateur d'installation" -#: check.c:564 +#: check.c:1061 #, c-format msgid "could not determine the number of users" msgstr "n'a pas pu déterminer le nombre d'utilisateurs" -#: check.c:572 +#: check.c:1069 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "Seul l'utilisateur d'installation peut être défini dans la nouvelle instance." -#: check.c:601 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "Vérification des paramètres de connexion de la base de données" -#: check.c:627 +#: check.c:1124 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0 ne doit pas autoriser les connexions, ie pg_database.datallowconn doit valoir false" -#: check.c:654 check.c:775 check.c:873 check.c:999 check.c:1076 check.c:1135 -#: check.c:1196 check.c:1224 check.c:1254 check.c:1313 check.c:1394 -#: function.c:185 version.c:192 version.c:232 version.c:378 +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 #, c-format msgid "fatal" msgstr "fatal" -#: check.c:655 +#: check.c:1151 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" @@ -234,27 +461,27 @@ msgstr "" "le fichier :\n" " %s" -#: check.c:680 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "Vérification des transactions préparées" -#: check.c:689 +#: check.c:1185 #, c-format msgid "The source cluster contains prepared transactions" msgstr "L'instance source contient des transactions préparées" -#: check.c:691 +#: check.c:1187 #, c-format msgid "The target cluster contains prepared transactions" msgstr "L'instance cible contient des transactions préparées" -#: check.c:716 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Vérification de contrib/isn avec une différence sur le passage des bigint" -#: check.c:776 +#: check.c:1271 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -275,12 +502,12 @@ msgstr "" "dans le fichier :\n" " %s" -#: check.c:798 +#: check.c:1293 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Vérification des opérateurs postfixes définis par les utilisateurs" -#: check.c:874 +#: check.c:1368 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -295,12 +522,12 @@ msgstr "" "Une liste des opérateurs postfixes définis par les utilisateurs se trouve dans le fichier :\n" " %s" -#: check.c:898 +#: check.c:1392 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "Vérification des fonctions polymorphiques incompatibles" -#: check.c:1000 +#: check.c:1493 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -320,12 +547,12 @@ msgstr "" "des objets problématiques se trouve dans le fichier\n" " %s" -#: check.c:1024 +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Vérification des tables WITH OIDS" -#: check.c:1077 +#: check.c:1569 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -340,143 +567,133 @@ msgstr "" "Une liste des tables ayant ce problème se trouve dans le fichier :\n" " %s" -#: check.c:1105 +#: check.c:1596 #, c-format -msgid "Checking for system-defined composite types in user tables" -msgstr "Vérification des types composites définis par le système dans les tables utilisateurs" +msgid "Checking for roles starting with \"pg_\"" +msgstr "Vérification des rôles commençant avec « pg_ »" -#: check.c:1136 +#: check.c:1627 #, c-format msgid "" -"Your installation contains system-defined composite type(s) in user tables.\n" -"These type OIDs are not stable across PostgreSQL versions,\n" -"so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" " %s" msgstr "" -"Votre installation contient des types composites définis par le système dans vos tables\n" -"utilisateurs. Les OID de ces types ne sont pas stables entre différentes versions majeures\n" -"de PostgreSQL, donc cette instance ne peut pas être mise à jour actuellement. Vous pouvez\n" -"supprimer les colonnes problématiques, puis relancer la mise à jour. Vous trouverez\n" -"une liste des colonnes problématiques dans le fichier :\n" +"Votre installation contient des rôles commençant par « pg_ ».\n" +"\"pg_\" est un préfixe réservé aux rôles systèmes. L'instance\n" +"ne peut pas être mise à jour tant que ces rôles ne sont pas renommés.\n" +"Une liste des rôles commençant par « pg_ » se trouve dans le fichier :\n" " %s" -#: check.c:1164 +#: check.c:1647 #, c-format -msgid "Checking for reg* data types in user tables" -msgstr "Vérification des types de données reg* dans les tables utilisateurs" +msgid "Checking for user-defined encoding conversions" +msgstr "Vérification des conversions d'encodage définies par les utilisateurs" -#: check.c:1197 +#: check.c:1707 #, c-format msgid "" -"Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains user-defined encoding conversions.\n" +"The conversion function parameters changed in PostgreSQL version 14\n" +"so this cluster cannot currently be upgraded. You can remove the\n" +"encoding conversions in the old cluster and restart the upgrade.\n" +"A list of user-defined encoding conversions is in the file:\n" " %s" msgstr "" -"Votre installation contient un des types de données reg* dans vos tables\n" -"utilisateurs. Ces types de données référencent des OID système qui ne sont\n" -"pas préservés par pg_upgrade, donc cette instance ne peut pas être mise à\n" -"jour actuellement. Vous pouvez supprimer les colonnes problématiques et relancer\n" -"la mise à jour. Une liste des colonnes problématiques est disponible dans le\n" -"fichier :\n" +"Votre installation contient des conversions définies par un utilisateur.\n" +"Les paramètres des fonctions de conversion ont changé dans PostgreSQL version 14\n" +"donc cette instance ne peut pas être mise à jour actuellement. Vous devez supprimer\n" +"les conversions d'encodage de l'ancienne instance puis relancer la mise à jour.\n" +"Une liste des conversions d'encodage définies par l'utilisateur se trouve dans le fichier :\n" " %s" -#: check.c:1218 +#: check.c:1746 #, c-format -msgid "Checking for incompatible \"aclitem\" data type in user tables" -msgstr "Vérification du type de données aclitem incompatible dans les tables utilisateurs" +msgid "Checking for new cluster logical replication slots" +msgstr "Vérification des slots de réplication logique de la nouvelle instance" -#: check.c:1225 +#: check.c:1754 #, c-format -msgid "" -"Your installation contains the \"aclitem\" data type in user tables.\n" -"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" -"so this cluster cannot currently be upgraded. You can drop the\n" -"problem columns and restart the upgrade. A list of the problem\n" -"columns is in the file:\n" -" %s" -msgstr "" -"Votre installation contient un type de données « aclitem » dans vos tables utilisateurs.\n" -"Le format interne de « aclitem » a changé lors du développement de la version 16, donc\n" -"cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer les\n" -"colonnes problématiques et relancer la mise à jour. Une liste des colonnes problématiques\n" -"est disponible dans le fichier :\n" -" %s" +msgid "could not count the number of logical replication slots" +msgstr "n'a pas pu compter le nombre de slots de réplication logique" -#: check.c:1246 +#: check.c:1759 #, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "Vérification des types de données « jsonb » incompatibles" +msgid "expected 0 logical replication slots but found %d" +msgstr "attendait 0 slot de réplication logique mais en a trouvé %d" -#: check.c:1255 +#: check.c:1769 check.c:1820 #, c-format -msgid "" -"Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Votre installation contient un type de données « jsonb » dans vos tables utilisateurs.\n" -"Le format interne de « jsonb » a changé lors du développement de la version 9.4 beta, donc\n" -"cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer les\n" -"colonnes problématiques et relancer la mise à jour. Une liste des colonnes problématiques\n" -"est disponible dans le fichier :\n" -" %s" +msgid "could not determine parameter settings on new cluster" +msgstr "n'a pas pu déterminer la configuration sur la nouvelle instance" -#: check.c:1282 +#: check.c:1774 #, c-format -msgid "Checking for roles starting with \"pg_\"" -msgstr "Vérification des rôles commençant avec « pg_ »" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "« wal_level » doit être configuré à « logical » mais est configuré à « %s »" + +#: check.c:1780 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" +msgstr "« max_replication_slots » (%d) doit être supérieur ou égal au nombre de slots de réplication logique (%d) sur l'ancienne instance" + +#: check.c:1812 +#, c-format +msgid "Checking for new cluster configuration for subscriptions" +msgstr "Vérification de la configuration de la nouvelle instance pour les souscriptions" + +#: check.c:1824 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "« max_replication_slots » (%d) doit être supérieur ou égal au nombre de souscriptions (%d) sur l'ancienne instance" -#: check.c:1314 +#: check.c:1846 +#, c-format +msgid "Checking for valid logical replication slots" +msgstr "Vérification des slots de réplication logique valides" + +#: check.c:1898 #, c-format msgid "" -"Your installation contains roles starting with \"pg_\".\n" -"\"pg_\" is a reserved prefix for system roles. The cluster\n" -"cannot be upgraded until these roles are renamed.\n" -"A list of roles starting with \"pg_\" is in the file:\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" " %s" msgstr "" -"Votre installation contient des rôles commençant par « pg_ ».\n" -"\"pg_\" est un préfixe réservé aux rôles systèmes. L'instance\n" -"ne peut pas être mise à jour tant que ces rôles ne sont pas renommés.\n" -"Une liste des rôles commençant par « pg_ » se trouve dans le fichier :\n" +"Votre installation contient des slots de réplication logique qui ne peuvent pas\n" +"être mis à jour. Vous pouvez supprimer les slots invalides et/ou consommer le\n" +"WAL en attente pour les autres slots, puis relancer la mise à jour. Vous trouverez\n" +"une liste des slots problématiques dans le fichier :\n" " %s" -#: check.c:1334 +#: check.c:1922 #, c-format -msgid "Checking for user-defined encoding conversions" -msgstr "Vérification des conversions d'encodage définies par les utilisateurs" +msgid "Checking for subscription state" +msgstr "Vérification de l'état de souscription" -#: check.c:1395 +#: check.c:2023 #, c-format msgid "" -"Your installation contains user-defined encoding conversions.\n" -"The conversion function parameters changed in PostgreSQL version 14\n" -"so this cluster cannot currently be upgraded. You can remove the\n" -"encoding conversions in the old cluster and restart the upgrade.\n" -"A list of user-defined encoding conversions is in the file:\n" +"Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" " %s" msgstr "" -"Votre installation contient des conversions définies par un utilisateur.\n" -"Les paramètres des fonctions de conversion ont changé dans PostgreSQL version 14\n" -"donc cette instance ne peut pas être mise à jour actuellement. Vous devez supprimer\n" -"les conversions d'encodage de l'ancienne instance puis relancer la mise à jour.\n" -"Une liste des conversions d'encodage définies par l'utilisateur se trouve dans le fichier :\n" +"Votre installation contient des souscriptions sans origine ou ont des relations qui\n" +"ne sont ni dans l'état « initialize » ni dans l'état « ready ». Vous pouvez permettre la\n" +"réalisation de la synchronisation initiale pour toutes les relations, puis relancer la\n" +"mise à jour. Vous trouverez une liste des souscriptions problématiques dans le fichier :\n" " %s" -#: controldata.c:129 controldata.c:175 controldata.c:199 controldata.c:508 +#: controldata.c:129 controldata.c:199 #, c-format -msgid "could not get control data using %s: %s" -msgstr "n'a pas pu obtenir les données de contrôle en utilisant %s : %s" +msgid "could not get control data using %s: %m" +msgstr "n'a pas pu obtenir les données de contrôle en utilisant %s : %m" -#: controldata.c:140 +#: controldata.c:139 #, c-format msgid "%d: database cluster state problem" msgstr "%d : problème sur l'état de l'instance de la base de données" @@ -493,13 +710,18 @@ msgstr "L'instance cible a été arrêté alors qu'elle était en mode restaurat #: controldata.c:165 #, c-format -msgid "The source cluster was not shut down cleanly." -msgstr "L'instance source n'a pas été arrêtée proprement." +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "L'instance source n'a pas été arrêtée proprement, état reporté comme : « %s »" #: controldata.c:167 #, c-format -msgid "The target cluster was not shut down cleanly." -msgstr "L'instance cible n'a pas été arrêtée proprement." +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "L'instance cible n'a pas été arrêtée proprement, état reporté comme : « %s »" + +#: controldata.c:175 controldata.c:507 +#, c-format +msgid "could not get control data using %s: %s" +msgstr "n'a pas pu obtenir les données de contrôle en utilisant %s : %s" #: controldata.c:181 #, c-format @@ -511,139 +733,139 @@ msgstr "Il manque certaines informations d'état requises sur l'instance source msgid "The target cluster lacks cluster state information:" msgstr "Il manque certaines informations d'état requises sur l'instance cible :" -#: controldata.c:214 dump.c:50 exec.c:119 pg_upgrade.c:517 pg_upgrade.c:554 -#: relfilenumber.c:231 server.c:34 util.c:337 +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:221 +#: controldata.c:220 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d : problème avec pg_resetwal" -#: controldata.c:231 controldata.c:241 controldata.c:252 controldata.c:263 -#: controldata.c:274 controldata.c:293 controldata.c:304 controldata.c:315 -#: controldata.c:326 controldata.c:337 controldata.c:348 controldata.c:359 -#: controldata.c:362 controldata.c:366 controldata.c:376 controldata.c:388 -#: controldata.c:399 controldata.c:410 controldata.c:421 controldata.c:432 -#: controldata.c:443 controldata.c:454 controldata.c:465 controldata.c:476 -#: controldata.c:487 controldata.c:498 +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d : problème de récupération des controldata" -#: controldata.c:579 +#: controldata.c:578 #, c-format msgid "The source cluster lacks some required control information:" msgstr "Il manque certaines informations de contrôle requises sur l'instance source :" -#: controldata.c:582 +#: controldata.c:581 #, c-format msgid "The target cluster lacks some required control information:" msgstr "Il manque certaines informations de contrôle requises sur l'instance cible :" -#: controldata.c:585 +#: controldata.c:584 #, c-format msgid " checkpoint next XID" msgstr " XID du prochain checkpoint" -#: controldata.c:588 +#: controldata.c:587 #, c-format msgid " latest checkpoint next OID" msgstr " prochain OID du dernier checkpoint" -#: controldata.c:591 +#: controldata.c:590 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " prochain MultiXactId du dernier checkpoint" -#: controldata.c:595 +#: controldata.c:594 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " plus ancien MultiXactId du dernier checkpoint" -#: controldata.c:598 +#: controldata.c:597 #, c-format msgid " latest checkpoint oldestXID" msgstr " oldestXID du dernier checkpoint" -#: controldata.c:601 +#: controldata.c:600 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " prochain MultiXactOffset du dernier checkpoint" -#: controldata.c:604 +#: controldata.c:603 #, c-format msgid " first WAL segment after reset" msgstr " premier segment WAL après réinitialisation" -#: controldata.c:607 +#: controldata.c:606 #, c-format msgid " float8 argument passing method" msgstr " méthode de passage de arguments float8" -#: controldata.c:610 +#: controldata.c:609 #, c-format msgid " maximum alignment" msgstr " alignement maximale" -#: controldata.c:613 +#: controldata.c:612 #, c-format msgid " block size" msgstr " taille de bloc" -#: controldata.c:616 +#: controldata.c:615 #, c-format msgid " large relation segment size" msgstr " taille de segment des relations" -#: controldata.c:619 +#: controldata.c:618 #, c-format msgid " WAL block size" msgstr " taille de bloc d'un WAL" -#: controldata.c:622 +#: controldata.c:621 #, c-format msgid " WAL segment size" msgstr " taille d'un segment WAL" -#: controldata.c:625 +#: controldata.c:624 #, c-format msgid " maximum identifier length" msgstr " longueur maximum d'un identifiant" -#: controldata.c:628 +#: controldata.c:627 #, c-format msgid " maximum number of indexed columns" msgstr " nombre maximum de colonnes indexées" -#: controldata.c:631 +#: controldata.c:630 #, c-format msgid " maximum TOAST chunk size" msgstr " taille maximale d'un morceau de TOAST" -#: controldata.c:635 +#: controldata.c:634 #, c-format msgid " large-object chunk size" msgstr " taille d'un morceau Large-Object" -#: controldata.c:638 +#: controldata.c:637 #, c-format msgid " dates/times are integers?" msgstr " les dates/heures sont-ils des integers?" -#: controldata.c:642 +#: controldata.c:641 #, c-format msgid " data checksum version" msgstr " version des sommes de contrôle des données" -#: controldata.c:644 +#: controldata.c:643 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "Ne peut pas continuer sans les informations de contrôle requises, en arrêt" -#: controldata.c:659 +#: controldata.c:658 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -652,77 +874,77 @@ msgstr "" "les alignements sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata.\n" "Il est probable qu'une installation soit en 32 bits et l'autre en 64 bits." -#: controldata.c:663 +#: controldata.c:662 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "les tailles de bloc sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:666 +#: controldata.c:665 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "les tailles maximales de segment de relation sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:669 +#: controldata.c:668 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "les tailles de bloc des WAL sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:672 +#: controldata.c:671 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "les tailles de segment de WAL sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:675 +#: controldata.c:674 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "les longueurs maximales des identifiants sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:678 +#: controldata.c:677 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "les nombres maximums de colonnes indexées sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:681 +#: controldata.c:680 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "les tailles maximales de morceaux des TOAST sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:686 +#: controldata.c:685 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "les tailles des morceaux de Large Objects sont invalides ou ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:689 +#: controldata.c:688 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "les types de stockage date/heure ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:702 +#: controldata.c:701 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "l'ancienne instance n'utilise pas les sommes de contrôle alors que la nouvelle les utilise" -#: controldata.c:705 +#: controldata.c:704 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "l'ancienne instance utilise les sommes de contrôle alors que la nouvelle ne les utilise pas" -#: controldata.c:707 +#: controldata.c:706 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "les versions des sommes de contrôle ne correspondent pas entre l'ancien et le nouveau pg_controldata." -#: controldata.c:718 +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "Ajout du suffixe « .old » à l'ancien global/pg_control" -#: controldata.c:723 +#: controldata.c:722 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" -#: controldata.c:727 +#: controldata.c:726 #, c-format msgid "" "\n" @@ -748,27 +970,32 @@ msgstr "Création de la sauvegarde des objets globaux" msgid "Creating dump of database schemas" msgstr "Création de la sauvegarde des schémas des bases" -#: exec.c:47 exec.c:52 +#: exec.c:47 +#, c-format +msgid "could not get pg_ctl version data using %s: %m" +msgstr "n'a pas pu obtenir la version de pg_ctl en utilisant %s : %m" + +#: exec.c:51 #, c-format msgid "could not get pg_ctl version data using %s: %s" msgstr "n'a pas pu obtenir la version de pg_ctl en utilisant %s : %s" -#: exec.c:56 +#: exec.c:55 #, c-format msgid "could not get pg_ctl version output from %s" msgstr "n'a pas pu obtenir la version de pg_ctl à partir de %s" -#: exec.c:113 exec.c:117 +#: exec.c:112 exec.c:116 #, c-format msgid "command too long" msgstr "commande trop longue" -#: exec.c:161 pg_upgrade.c:286 +#: exec.c:160 pg_upgrade.c:311 #, c-format msgid "could not open log file \"%s\": %m" msgstr "n'a pas pu ouvrir le journal applicatif « %s » : %m" -#: exec.c:193 +#: exec.c:192 #, c-format msgid "" "\n" @@ -777,12 +1004,12 @@ msgstr "" "\n" "*échec*" -#: exec.c:196 +#: exec.c:195 #, c-format msgid "There were problems executing \"%s\"" msgstr "Il y a eu des problèmes lors de l'exécution de « %s »" -#: exec.c:199 +#: exec.c:198 #, c-format msgid "" "Consult the last few lines of \"%s\" or \"%s\" for\n" @@ -791,7 +1018,7 @@ msgstr "" "Consultez les dernières lignes de « %s » ou « %s » pour\n" "trouver la cause probable de l'échec." -#: exec.c:204 +#: exec.c:203 #, c-format msgid "" "Consult the last few lines of \"%s\" for\n" @@ -800,141 +1027,156 @@ msgstr "" "Consultez les dernières lignes de « %s » pour\n" "trouver la cause probable de l'échec." -#: exec.c:219 pg_upgrade.c:296 +#: exec.c:218 pg_upgrade.c:321 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "n'a pas pu écrire dans le fichier de traces « %s »" -#: exec.c:245 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s" -msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %s" +msgid "could not open file \"%s\" for reading: %m" +msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m" -#: exec.c:272 +#: exec.c:270 #, c-format msgid "You must have read and write access in the current directory." msgstr "Vous devez avoir les droits de lecture et d'écriture dans le répertoire actuel." -#: exec.c:325 exec.c:391 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s" -msgstr "échec de la vérification de « %s » : %s" +msgid "check for \"%s\" failed: %m" +msgstr "échec de la vérification de « %s » : %m" -#: exec.c:328 exec.c:394 +#: exec.c:326 exec.c:392 #, c-format msgid "\"%s\" is not a directory" msgstr "« %s » n'est pas un répertoire" -#: exec.c:441 -#, c-format -msgid "check for \"%s\" failed: %m" -msgstr "échec de la vérification de « %s » : %m" - -#: exec.c:446 +#: exec.c:444 #, c-format msgid "check for \"%s\" failed: cannot execute" msgstr "échec de la vérification de « %s » : ne peut pas exécuter" -#: exec.c:456 +#: exec.c:454 #, c-format msgid "check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" msgstr "échec de la vérification de « %s » : version incorrecte : « %s » trouvée, « %s » attendue" -#: file.c:43 file.c:64 +#: file.c:44 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "erreur lors du clonage de la relation « %s.%s » (« %s » à « %s ») : %s" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "erreur lors du clonage de la relation « %s.%s » (« %s » à « %s ») : %m" -#: file.c:50 +#: file.c:51 #, c-format -msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "erreur lors du clonage de la relation « %s.%s » : n'a pas pu ouvrir le fichier « %s » : %s" +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "erreur lors du clonage de la relation « %s.%s » : n'a pas pu ouvrir le fichier « %s » : %m" + +#: file.c:56 +#, c-format +msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "erreur lors du clonage de la relation « %s.%s » : n'a pas pu créer le fichier « %s » : %m" + +#: file.c:65 +#, c-format +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "erreur lors du clonage de la relation « %s.%s » (« %s » à « %s ») : %s" -#: file.c:55 +#: file.c:91 file.c:160 file.c:233 #, c-format -msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "erreur lors du clonage de la relation « %s.%s » : n'a pas pu créer le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu ouvrir le fichier « %s » : %m" -#: file.c:90 file.c:193 +#: file.c:96 file.c:165 file.c:242 #, c-format -msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu ouvrir le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu créer le fichier « %s » : %m" -#: file.c:95 file.c:202 +#: file.c:110 file.c:266 #, c-format -msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu créer le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu lire le fichier « %s » : %m" -#: file.c:109 file.c:226 +#: file.c:122 file.c:344 #, c-format -msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %s" -msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu lire le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu écrire le fichier « %s » : %m" -#: file.c:121 file.c:304 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %s" -msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu écrire le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "erreur lors de la copie de la relation « %s.%s » (« %s » à « %s ») : %m" -#: file.c:135 +#: file.c:172 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "erreur lors de la copie de la relation « %s.%s » (« %s » à « %s ») : %s" +msgid "error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu exécuter copy_file_range du fichier « %s » au fichier « %s » : %m" -#: file.c:154 +#: file.c:194 #, c-format -msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "erreur lors de la création du lien pour la relation « %s.%s » (« %s » à « %s ») : %s" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "erreur lors de la création du lien pour la relation « %s.%s » (« %s » à « %s ») : %m" -#: file.c:197 +#: file.c:237 #, c-format -msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %s" -msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu tester le fichier « %s » : %s" +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" +msgstr "erreur lors de la copie de la relation « %s.%s » : n'a pas pu tester le fichier « %s » : %m" -#: file.c:229 +#: file.c:269 #, c-format msgid "error while copying relation \"%s.%s\": partial page found in file \"%s\"" msgstr "erreur lors de la copie de la relation « %s.%s » : page partielle trouvée dans le fichier « %s »" -#: file.c:331 file.c:348 +#: file.c:371 file.c:387 #, c-format -msgid "could not clone file between old and new data directories: %s" -msgstr "n'a pas pu cloner le fichier entre l'ancien et le nouveau répertoires : %s" +msgid "could not clone file between old and new data directories: %m" +msgstr "n'a pas pu cloner le fichier entre l'ancien et le nouveau répertoires de données : %m" -#: file.c:344 +#: file.c:383 file.c:420 #, c-format -msgid "could not create file \"%s\": %s" -msgstr "n'a pas pu créer le fichier « %s » : %s" +msgid "could not create file \"%s\": %m" +msgstr "n'a pas pu créer le fichier « %s » : %m" -#: file.c:355 +#: file.c:393 #, c-format msgid "file cloning not supported on this platform" msgstr "clonage de fichiers non supporté sur cette plateforme" -#: file.c:372 +#: file.c:424 +#, c-format +msgid "could not copy file range between old and new data directories: %m" +msgstr "n'a pas pu exécuter copy_file_range entre l'ancien et le nouveau répertoires de données : %m" + +#: file.c:430 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range non supporté sur cette plateforme" + +#: file.c:447 #, c-format msgid "" -"could not create hard link between old and new data directories: %s\n" +"could not create hard link between old and new data directories: %m\n" "In link mode the old and new data directories must be on the same file system." msgstr "" -"n'a pas pu créer le lien physique entre l'ancien et le nouveau répertoires de données : %s\n" +"n'a pas pu créer le lien physique entre l'ancien et le nouveau répertoires de données : %m\n" "Dans le mode lien, les ancien et nouveau répertoires de données doivent être sur le même système de fichiers." -#: function.c:128 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "Vérification de la présence des bibliothèques requises" -#: function.c:165 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "n'a pas pu charger la bibliothèque « %s » : %s" -#: function.c:176 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "Dans la base de données : %s\n" -#: function.c:186 +#: function.c:211 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -949,47 +1191,47 @@ msgstr "" "Une liste des bibliothèques problématiques est disponible dans le fichier :\n" " %s" -#: info.c:126 +#: info.c:128 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "Les noms de relation pour l'OID %u dans la base de données « %s » ne correspondent pas : ancien nom « %s.%s », nouveau nom « %s.%s »" -#: info.c:146 +#: info.c:148 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "Échec de correspondance des anciennes et nouvelles tables dans la base de données « %s »" -#: info.c:227 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " qui est un index sur \"%s.%s\"" -#: info.c:237 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " qui est un index sur l'OID %u" -#: info.c:249 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " qui est la table TOAST pour « %s.%s »" -#: info.c:257 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " qui est la table TOAST pour l'OID %u" -#: info.c:261 +#: info.c:263 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "Aucune correspondance trouvée dans l'ancienne instance pour la nouvelle relation d'OID %u dans la base de données « %s » : %s" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "Aucune correspondance trouvée dans la nouvelle instance pour la nouvelle relation d'OID %u dans la base de données « %s » : %s" -#: info.c:289 +#: info.c:300 #, c-format msgid "" "\n" @@ -998,7 +1240,7 @@ msgstr "" "\n" "bases de données sources :" -#: info.c:291 +#: info.c:302 #, c-format msgid "" "\n" @@ -1013,82 +1255,92 @@ msgstr "" # (errcode(ERRCODE_CASE_NOT_FOUND), # errmsg("case not found"), # errhint("CASE statement is missing ELSE part."))); -#: info.c:329 +#: info.c:346 #, c-format msgid "template0 not found" msgstr "template0 introuvable" -#: info.c:645 +#: info.c:805 #, c-format -msgid "Database: %s" -msgstr "Base de données : %s" +msgid "Database: \"%s\"" +msgstr "Base de données : « %s »" -#: info.c:657 +#: info.c:818 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s" -msgstr "relname : %s.%s : reloid : %u reltblspace : %s" +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "relname : « %s.%s », reloid : %u, reltblspace : « %s »" -#: option.c:101 +#: info.c:832 +#, c-format +msgid "Logical replication slots in the database:" +msgstr "Les slots de réplication logique dans la base de données :" + +#: info.c:838 +#, c-format +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "nom du slot « %s », plugin de sortie « %s », two_phase %s" + +#: option.c:105 #, c-format msgid "%s: cannot be run as root" msgstr "%s : ne peut pas être exécuté en tant que root" -#: option.c:168 +#: option.c:172 #, c-format msgid "invalid old port number" msgstr "ancien numéro de port invalide" -#: option.c:173 +#: option.c:177 #, c-format msgid "invalid new port number" msgstr "nouveau numéro de port invalide" -#: option.c:203 +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Essayez « %s --help » pour plus d'informations.\n" -#: option.c:210 +#: option.c:223 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: option.c:213 +#: option.c:229 #, c-format msgid "Running in verbose mode" msgstr "Exécution en mode verbeux" -#: option.c:231 +#: option.c:247 msgid "old cluster binaries reside" msgstr "les binaires de l'ancienne instance résident" -#: option.c:233 +#: option.c:249 msgid "new cluster binaries reside" msgstr "les binaires de la nouvelle instance résident" -#: option.c:235 +#: option.c:251 msgid "old cluster data resides" msgstr "les données de l'ancienne instance résident" -#: option.c:237 +#: option.c:253 msgid "new cluster data resides" msgstr "les données de la nouvelle instance résident" -#: option.c:239 +#: option.c:255 msgid "sockets will be created" msgstr "les sockets seront créés" -#: option.c:256 option.c:356 +#: option.c:272 option.c:374 #, c-format msgid "could not determine current directory" msgstr "n'a pas pu déterminer le répertoire courant" -#: option.c:259 +#: option.c:275 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "ne peut pas exécuter pg_upgrade depuis le répertoire de données de la nouvelle instance sur Windows" -#: option.c:268 +#: option.c:284 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1097,12 +1349,12 @@ msgstr "" "pg_upgrade met à jour une instance PostgreSQL vers une version majeure\n" "différente.\n" -#: option.c:269 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: option.c:270 +#: option.c:286 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1111,19 +1363,19 @@ msgstr "" " pg_upgrade [OPTION]...\n" "\n" -#: option.c:271 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "Options :\n" -#: option.c:272 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr "" " -b, --old-bindir=RÉP_BIN répertoire des exécutables de l'ancienne\n" " instance\n" -#: option.c:273 +#: option.c:289 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1133,121 +1385,131 @@ msgstr "" " instance (par défaut, le même répertoire que\n" " pg_upgrade)\n" -#: option.c:275 +#: option.c:291 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr "" " -c, --check vérifie seulement les instances, pas de\n" " modifications\n" -#: option.c:276 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=RÉP_DONNÉES répertoire des données de l'ancienne instance\n" -#: option.c:277 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=RÉP_DONNÉES répertoire des données de la nouvelle instance\n" -#: option.c:278 +#: option.c:294 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr "" " -j, --jobs=NUM nombre de processus ou threads simultanés à\n" " utiliser\n" -#: option.c:279 +#: option.c:295 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr "" " -k, --link lie les fichiers au lieu de les copier vers la\n" " nouvelle instance\n" -#: option.c:280 +#: option.c:296 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr "" " -N, --nosync n'attend pas que les modifications soient proprement\n" " écrites sur disque\n" -#: option.c:281 +#: option.c:297 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr "" " -o, --old-options=OPTIONS options à passer au serveur de l'ancienne\n" " instance\n" -#: option.c:282 +#: option.c:298 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr "" " -O, --new-options=OPTIONS options à passer au serveur de la nouvelle\n" " instance\n" -#: option.c:283 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr "" " -p, --old-port=PORT numéro de port de l'ancienne instance (par\n" " défaut %d)\n" -#: option.c:284 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr "" " -P, --new-port=PORT numéro de port de la nouvelle instance (par\n" " défaut %d)\n" -#: option.c:285 +#: option.c:301 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr "" " -r, --retain conserve les fichiers SQL et de traces en cas\n" " de succès\n" -#: option.c:286 +#: option.c:302 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr "" " -s, --socketdir=RÉP_SOCKET répertoire de la socket à utiliser (par défaut\n" " le répertoire courant)\n" -#: option.c:287 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr "" " -U, --username=NOM super-utilisateur de l'instance (par défaut\n" " « %s »)\n" -#: option.c:288 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose active des traces internes verbeuses\n" -#: option.c:289 +#: option.c:305 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version affiche la version, puis quitte\n" -#: option.c:290 +#: option.c:306 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr "" " --clone clone au lieu de copier les fichiers vers la\n" " nouvelle instance\n" -#: option.c:291 +#: option.c:307 #, c-format msgid " --copy copy files to new cluster (default)\n" -msgstr " --copy copie les fichiers vers la nouvelle instance (par défaut)\n" +msgstr " --copy copie les fichiers vers la nouvelle instance (par défaut)\n" -#: option.c:292 +#: option.c:308 +#, c-format +msgid " --copy-file-range copy files to new cluster with copy_file_range\n" +msgstr " --copy-file-range copie les fichiers vers la nouvelle instance avec copy_file_range\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHODE configure la méthode pour synchroniser les fichiers sur disque\n" + +#: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide, puis quitte\n" -#: option.c:293 +#: option.c:311 #, c-format msgid "" "\n" @@ -1263,7 +1525,7 @@ msgstr "" " arrêter le postmaster de la nouvelle instance\n" "\n" -#: option.c:298 +#: option.c:316 #, c-format msgid "" "\n" @@ -1280,7 +1542,7 @@ msgstr "" " le répertoire « bin » pour l'ancienne version (-b RÉP_BIN)\n" " le répertoire « bin » pour la nouvelle version (-B RÉP_BIN)\n" -#: option.c:304 +#: option.c:322 #, c-format msgid "" "\n" @@ -1293,7 +1555,7 @@ msgstr "" " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n" "ou\n" -#: option.c:309 +#: option.c:327 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1308,7 +1570,7 @@ msgstr "" " $ export PGBINNEW=newCluster/bin\n" " $ pg_upgrade\n" -#: option.c:315 +#: option.c:333 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1323,7 +1585,7 @@ msgstr "" " C:\\> set PGBINNEW=newCluster/bin\n" " C:\\> pg_upgrade\n" -#: option.c:321 +#: option.c:339 #, c-format msgid "" "\n" @@ -1332,12 +1594,12 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: option.c:322 +#: option.c:340 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: option.c:362 +#: option.c:380 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1346,45 +1608,50 @@ msgstr "" "Vous devez identifier le répertoire où le %s.\n" "Merci d'utiliser l'option en ligne de commande %s ou la variable d'environnement %s." -#: option.c:415 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Recherche du vrai répertoire des données pour l'instance source" -#: option.c:417 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Recherche du vrai répertoire des données pour l'instance cible" -#: option.c:430 option.c:435 +#: option.c:448 +#, c-format +msgid "could not get data directory using %s: %m" +msgstr "n'a pas pu obtenir le répertoire des données en utilisant %s : %m" + +#: option.c:452 #, c-format msgid "could not get data directory using %s: %s" msgstr "n'a pas pu obtenir le répertoire des données en utilisant %s : %s" -#: option.c:484 +#: option.c:500 #, c-format -msgid "could not read line %d from file \"%s\": %s" -msgstr "n'a pas pu lire la ligne %d du fichier « %s » : %s" +msgid "could not read line %d from file \"%s\": %m" +msgstr "n'a pas pu lire la ligne %d du fichier « %s » : %m" -#: option.c:501 +#: option.c:517 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "ancien numéro de port %hu fourni par l'utilisateur corrigé en %hu" #: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker process: %s" -msgstr "n'a pas pu créer le processus de travail : %s" +msgid "could not create worker process: %m" +msgstr "n'a pas pu créer le processus worker : %m" #: parallel.c:143 parallel.c:253 #, c-format -msgid "could not create worker thread: %s" -msgstr "n'a pas pu créer le fil de travail: %s" +msgid "could not create worker thread: %m" +msgstr "n'a pas pu créer le fil de travail: %m" #: parallel.c:294 #, c-format -msgid "%s() failed: %s" -msgstr "échec de %s() : %s" +msgid "%s() failed: %m" +msgstr "échec de %s() : %m" #: parallel.c:298 #, c-format @@ -1393,15 +1660,15 @@ msgstr "le processus fils a quitté anormalement : statut %d" #: parallel.c:313 #, c-format -msgid "child worker exited abnormally: %s" -msgstr "le processus fils a quitté anormalement : %s" +msgid "child worker exited abnormally: %m" +msgstr "le processus fils a quitté anormalement : %m" -#: pg_upgrade.c:107 +#: pg_upgrade.c:115 #, c-format -msgid "could not read permissions of directory \"%s\": %s" -msgstr "n'a pas pu lire les droits du répertoire « %s » : %s" +msgid "could not read permissions of directory \"%s\": %m" +msgstr "n'a pas pu lire les droits du répertoire « %s » : %m" -#: pg_upgrade.c:139 +#: pg_upgrade.c:147 #, c-format msgid "" "\n" @@ -1412,17 +1679,17 @@ msgstr "" "Réalisation de la mise à jour\n" "-----------------------------" -#: pg_upgrade.c:184 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "Configuration du prochain OID sur la nouvelle instance" -#: pg_upgrade.c:193 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "Synchronisation du répertoire des données sur disque" -#: pg_upgrade.c:205 +#: pg_upgrade.c:230 #, c-format msgid "" "\n" @@ -1433,23 +1700,23 @@ msgstr "" "Mise à jour terminée\n" "--------------------" -#: pg_upgrade.c:238 pg_upgrade.c:251 pg_upgrade.c:258 pg_upgrade.c:265 -#: pg_upgrade.c:283 pg_upgrade.c:294 +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 #, c-format msgid "directory path for new cluster is too long" msgstr "le chemin du répertoire pour la nouvelle instance est trop long" -#: pg_upgrade.c:272 pg_upgrade.c:274 pg_upgrade.c:276 pg_upgrade.c:278 +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 #, c-format msgid "could not create directory \"%s\": %m" msgstr "n'a pas pu créer le répertoire « %s » : %m" -#: pg_upgrade.c:327 +#: pg_upgrade.c:352 #, c-format msgid "%s: could not find own program executable" msgstr "%s : n'a pas pu trouver l'exécutable du programme" -#: pg_upgrade.c:353 +#: pg_upgrade.c:378 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1458,7 +1725,7 @@ msgstr "" "Il semble qu'un postmaster est démarré sur l'ancienne instance.\n" "Merci d'arrêter ce postmaster et d'essayer de nouveau." -#: pg_upgrade.c:366 +#: pg_upgrade.c:391 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1467,81 +1734,86 @@ msgstr "" "Il semble qu'un postmaster est démarré sur la nouvelle instance.\n" "Merci d'arrêter ce postmaster et d'essayer de nouveau." -#: pg_upgrade.c:388 +#: pg_upgrade.c:413 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "Configuration de la locale et de l'encodage pour la nouvelle instance" -#: pg_upgrade.c:450 +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Analyse de toutes les lignes dans la nouvelle instance" -#: pg_upgrade.c:463 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Gel de toutes les lignes dans la nouvelle instance" -#: pg_upgrade.c:483 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Restauration des objets globaux dans la nouvelle instance" -#: pg_upgrade.c:499 +#: pg_upgrade.c:538 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "Restauration des schémas des bases de données dans la nouvelle instance" -#: pg_upgrade.c:605 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "Suppression des fichiers à partir du nouveau %s" -#: pg_upgrade.c:609 +#: pg_upgrade.c:666 #, c-format msgid "could not delete directory \"%s\"" msgstr "n'a pas pu supprimer le répertoire « %s »" -#: pg_upgrade.c:628 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "Copie de l'ancien %s vers le nouveau serveur" -#: pg_upgrade.c:654 +#: pg_upgrade.c:711 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Configuration du plus ancien XID sur la nouvelle instance" -#: pg_upgrade.c:662 +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "Configuration du prochain identifiant de transaction et de l'epoch pour la nouvelle instance" -#: pg_upgrade.c:692 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "Configuration du prochain MultiXactId et décalage pour la nouvelle instance" -#: pg_upgrade.c:716 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Configuration du plus ancien identifiant multixact sur la nouvelle instance" -#: pg_upgrade.c:736 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "Réinitialisation des archives WAL" -#: pg_upgrade.c:779 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Configuration des compteurs frozenxid et minmxid dans la nouvelle instance" -#: pg_upgrade.c:781 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Configuration du compteur minmxid dans la nouvelle instance" +#: pg_upgrade.c:929 +#, c-format +msgid "Restoring logical replication slots in the new cluster" +msgstr "Restauration des slots de réplication logique dans la nouvelle instance" + #: relfilenumber.c:35 #, c-format msgid "Cloning user relation files" @@ -1554,35 +1826,45 @@ msgstr "Copie des fichiers des relations utilisateurs" #: relfilenumber.c:41 #, c-format +msgid "Copying user relation files with copy_file_range" +msgstr "Copie des fichiers des relations utilisateurs avec copy_file_range" + +#: relfilenumber.c:44 +#, c-format msgid "Linking user relation files" msgstr "Création des liens pour les fichiers des relations utilisateurs" -#: relfilenumber.c:115 +#: relfilenumber.c:118 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "ancienne base de données « %s » introuvable dans la nouvelle instance" -#: relfilenumber.c:218 +#: relfilenumber.c:221 #, c-format -msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "erreur lors de la vérification de l'existence du fichier « %s.%s » (« %s » vers « %s ») : %s" +msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "erreur lors de la vérification de l'existence du fichier « %s.%s » (« %s » vers « %s ») : %m" -#: relfilenumber.c:236 +#: relfilenumber.c:238 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "réécriture de « %s » en « %s »" -#: relfilenumber.c:244 +#: relfilenumber.c:246 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "clonage de « %s » en « %s »" -#: relfilenumber.c:249 +#: relfilenumber.c:251 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "copie de « %s » en « %s »" -#: relfilenumber.c:254 +#: relfilenumber.c:256 +#, c-format +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "copie de « %s » en « %s » avec copy_file_range" + +#: relfilenumber.c:261 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "lien de « %s » vers « %s »" @@ -1618,7 +1900,7 @@ msgstr "n'a pas pu ouvrir le fichier de version « %s » : %m" msgid "could not parse version file \"%s\"" msgstr "n'a pas pu analyser le fichier de version « %s »" -#: server.c:288 +#: server.c:310 #, c-format msgid "" "\n" @@ -1627,7 +1909,7 @@ msgstr "" "\n" "%s" -#: server.c:292 +#: server.c:314 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1636,7 +1918,7 @@ msgstr "" "n'a pas pu se connecter au postmaster source lancé avec la commande :\n" "%s" -#: server.c:296 +#: server.c:318 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1645,22 +1927,22 @@ msgstr "" "n'a pas pu se connecter au postmaster cible lancé avec la commande :\n" "%s" -#: server.c:310 +#: server.c:332 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl a échoué à démarrer le serveur source ou connexion échouée" -#: server.c:312 +#: server.c:334 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl a échoué à démarrer le serveur cible ou connexion échouée" -#: server.c:357 +#: server.c:379 #, c-format msgid "out of memory" msgstr "mémoire épuisée" -#: server.c:370 +#: server.c:392 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "la variable d'environnement libpq %s a une valeur serveur non locale : %s" @@ -1681,8 +1963,8 @@ msgstr "le répertoire « %s » du tablespace n'existe pas" #: tablespace.c:87 #, c-format -msgid "could not stat tablespace directory \"%s\": %s" -msgstr "n'a pas pu tester le répertoire « %s » du tablespace : %s" +msgid "could not stat tablespace directory \"%s\": %m" +msgstr "n'a pas pu tester le répertoire « %s » du tablespace : %m" #: tablespace.c:92 #, c-format @@ -1704,62 +1986,17 @@ msgstr "n'a pas pu accéder au répertoire « %s » : %m" msgid "ok" msgstr "ok" -#: version.c:184 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "Vérification des types de données line incompatibles" - -#: version.c:193 -#, c-format -msgid "" -"Your installation contains the \"line\" data type in user tables.\n" -"This data type changed its internal and input/output format\n" -"between your old and new versions so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Votre installation contient le type de données « line » dans vos tables utilisateurs.\n" -"Ce type de données a changé de format interne et en entrée/sortie entre vos ancienne\n" -"et nouvelle versions, donc cette instance ne peut pas être mise à jour\n" -"actuellement. Vous pouvez supprimer les colonnes problématiques et relancer la mise à jour.\n" -"Une liste des colonnes problématiques se trouve dans le fichier :\n" -" %s" - -#: version.c:224 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "Vérification des colonnes utilisateurs « unknown » invalides" - -#: version.c:233 -#, c-format -msgid "" -"Your installation contains the \"unknown\" data type in user tables.\n" -"This data type is no longer allowed in tables, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Votre installation contient le type de données « unknown » dans vos tables\n" -"utilisateurs. Ce type de données n'est plus autorisé dans les tables, donc\n" -"cette instance ne peut pas être mise à jour pour l'instant. Vous pouvez\n" -"supprimer les colonnes problématiques, puis relancer la mise à jour. Vous trouverez\n" -"une liste des colonnes problématiques dans le fichier :\n" -" %s" - -#: version.c:257 +#: version.c:44 #, c-format msgid "Checking for hash indexes" msgstr "Vérification des index hash" -#: version.c:335 +#: version.c:121 #, c-format msgid "warning" msgstr "attention" -#: version.c:337 +#: version.c:123 #, c-format msgid "" "\n" @@ -1774,7 +2011,7 @@ msgstr "" "être recréés avec la commande REINDEX. Après la mise à jour, les instructions\n" "REINDEX vous seront données." -#: version.c:343 +#: version.c:129 #, c-format msgid "" "\n" @@ -1793,39 +2030,17 @@ msgstr "" "une fois exécuté par psql en tant que superutilisateur va recréer tous les\n" "index invalides. Avant cela, aucun de ces index ne sera utilisé." -#: version.c:369 -#, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "Vérification des colonnes utilisateurs « sql_identifier » invalides" - -#: version.c:379 -#, c-format -msgid "" -"Your installation contains the \"sql_identifier\" data type in user tables.\n" -"The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Votre installation contient le type de données « sql_identifier » dans les tables\n" -"utilisateurs. Le format sur disque pour ce type de données a changé,\n" -"donc cette instance ne peut pas être mise à jour actuellement. Vous pouvez supprimer\n" -"les colonnes problématiques, puis relancer la mise à jour.\n" -"Une liste des colonnes problématiques se trouve dans le fichier :\n" -" %s" - -#: version.c:402 +#: version.c:153 #, c-format msgid "Checking for extension updates" msgstr "Vérification des mises à jour d'extension" -#: version.c:450 +#: version.c:200 #, c-format msgid "notice" msgstr "notice" -#: version.c:451 +#: version.c:201 #, c-format msgid "" "\n" @@ -1841,295 +2056,3 @@ msgstr "" " %s\n" "une fois exécuté par psql par le superutilisateur mettre à jour\n" "ces extensions." - -#, c-format -#~ msgid "" -#~ "\n" -#~ "\n" -#~ msgstr "" -#~ "\n" -#~ "\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#, c-format -#~ msgid "" -#~ "\n" -#~ "The old cluster has a \"plpython_call_handler\" function defined\n" -#~ "in the \"public\" schema which is a duplicate of the one defined\n" -#~ "in the \"pg_catalog\" schema. You can confirm this by executing\n" -#~ "in psql:\n" -#~ "\n" -#~ " \\df *.plpython_call_handler\n" -#~ "\n" -#~ "The \"public\" schema version of this function was created by a\n" -#~ "pre-8.1 install of plpython, and must be removed for pg_upgrade\n" -#~ "to complete because it references a now-obsolete \"plpython\"\n" -#~ "shared object file. You can remove the \"public\" schema version\n" -#~ "of this function by running the following command:\n" -#~ "\n" -#~ " DROP FUNCTION public.plpython_call_handler()\n" -#~ "\n" -#~ "in each affected database:\n" -#~ "\n" -#~ msgstr "" -#~ "\n" -#~ "L'ancienne instance comprend une fonction « plpython_call_handler »\n" -#~ "définie dans le schéma « public » qui est un duplicat de celle définie\n" -#~ "dans le schéma « pg_catalog ». Vous pouvez confirmer cela en\n" -#~ "exécutant dans psql :\n" -#~ "\n" -#~ " \\df *.plpython_call_handler\n" -#~ "\n" -#~ "La version de cette fonction dans le schéma « public » a été créée\n" -#~ "par une installation de plpython antérieure à la version 8.1 et doit\n" -#~ "être supprimée pour que pg_upgrade puisse termine parce qu'elle\n" -#~ "référence un fichier objet partagé « plpython » maintenant obsolète.\n" -#~ "Vous pouvez supprimer la version de cette fonction dans le schéma\n" -#~ "« public » en exécutant la commande suivante :\n" -#~ "\n" -#~ " DROP FUNCTION public.plpython_call_handler()\n" -#~ "\n" -#~ "dans chaque base de données affectée :\n" -#~ "\n" - -#, c-format -#~ msgid "" -#~ "\n" -#~ "Your installation contains large objects. The new database has an\n" -#~ "additional large object permission table, so default permissions must be\n" -#~ "defined for all large objects. The file\n" -#~ " %s\n" -#~ "when executed by psql by the database superuser will set the default\n" -#~ "permissions.\n" -#~ "\n" -#~ msgstr "" -#~ "\n" -#~ "Votre installation contient des Large Objects. La nouvelle base de données\n" -#~ "a une table de droit supplémentaire pour les Large Objects, donc les droits\n" -#~ "par défaut doivent être définies pour tous les Large Objects. Le fichier\n" -#~ " %s\n" -#~ "une fois exécuté par psql avec un superutilisateur définira les droits par\n" -#~ "défaut.\n" -#~ "\n" - -#, c-format -#~ msgid "" -#~ "\n" -#~ "Your installation contains large objects. The new database has an\n" -#~ "additional large object permission table. After upgrading, you will be\n" -#~ "given a command to populate the pg_largeobject_metadata table with\n" -#~ "default permissions.\n" -#~ "\n" -#~ msgstr "" -#~ "\n" -#~ "Votre installation contient des Large Objects. La nouvelle base de données a une table de droit supplémentaire sur les Large Objects.\n" -#~ "Après la mise à jour, vous disposerez d'une commande pour peupler la table pg_largeobject_metadata avec les droits par défaut.\n" -#~ "\n" - -#~ msgid "" -#~ "\n" -#~ "connection to database failed: %s" -#~ msgstr "" -#~ "\n" -#~ "échec de la connexion à la base de données : %s" - -#, c-format -#~ msgid " " -#~ msgstr " " - -#, c-format -#~ msgid " %s\n" -#~ msgstr " %s\n" - -#~ msgid "" -#~ " --index-collation-versions-unknown\n" -#~ " mark text indexes as needing to be rebuilt\n" -#~ msgstr "" -#~ " --index-collation-versions-unknown\n" -#~ " marque les index de colonnes de type text comme nécessitant une reconstruction\n" - -#, c-format -#~ msgid "\"%s\" is not a directory\n" -#~ msgstr "« %s » n'est pas un répertoire\n" - -#, c-format -#~ msgid "%-*s\n" -#~ msgstr "%-*s\n" - -#, c-format -#~ msgid "%s\n" -#~ msgstr "%s\n" - -#~ msgid "%s is not a directory\n" -#~ msgstr "%s n'est pas un répertoire\n" - -#, c-format -#~ msgid "%s.%s: %u to %u\n" -#~ msgstr "%s.%s : %u vers %u\n" - -#~ msgid "----------------\n" -#~ msgstr "----------------\n" - -#~ msgid "------------------\n" -#~ msgstr "------------------\n" - -#~ msgid "-----------------------------\n" -#~ msgstr "-----------------------------\n" - -#~ msgid "------------------------------------------------\n" -#~ msgstr "------------------------------------------------\n" - -#, c-format -#~ msgid "All non-template0 databases must allow connections, i.e. their pg_database.datallowconn must be true\n" -#~ msgstr "Toutes les bases de données, autre que template0, doivent autoriser les connexions, ie pg_database.datallowconn doit valoir true\n" - -#~ msgid "Cannot open file %s: %m\n" -#~ msgstr "Ne peut pas ouvrir le fichier %s : %m\n" - -#~ msgid "Cannot read line %d from %s: %m\n" -#~ msgstr "Ne peut pas lire la ligne %d à partir de %s : %m\n" - -#, c-format -#~ msgid "Checking for large objects" -#~ msgstr "Vérification des Large Objects" - -#~ msgid "Creating script to analyze new cluster" -#~ msgstr "Création d'un script pour analyser la nouvelle instance" - -#, c-format -#~ msgid "ICU locale values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "les valeurs de la locale ICU de la base de données « %s » ne correspondent pas : ancien « %s », nouveau « %s »\n" - -#~ msgid "" -#~ "Optimizer statistics and free space information are not transferred\n" -#~ "by pg_upgrade so, once you start the new server, consider running:\n" -#~ " %s\n" -#~ "\n" -#~ msgstr "" -#~ "Les statistiques de l'optimiseur et les informations sur l'espace libre\n" -#~ "ne sont pas transférées par pg_upgrade, donc une fois le nouveau\n" -#~ "serveur démarré, pensez à exécuter :\n" -#~ " %s\n" -#~ "\n" - -#, c-format -#~ msgid "Remove the problem functions from the old cluster to continue.\n" -#~ msgstr "Supprimez les fonctions problématiques de l'ancienne instance pour continuer.\n" - -#, c-format -#~ msgid "The source cluster contains roles starting with \"pg_\"\n" -#~ msgstr "L'instance source contient des rôles commençant avec « pg_ »\n" - -#, c-format -#~ msgid "The target cluster contains roles starting with \"pg_\"\n" -#~ msgstr "L'instance cible contient des rôles commençant avec « pg_ »\n" - -#~ msgid "" -#~ "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n" -#~ "because of backend API changes made during development.\n" -#~ msgstr "" -#~ "Cet outil peut seulement mettre à jour à partir de la version 9.0 de PostgreSQL (après le 11 janvier 2010)\n" -#~ "à cause de changements dans l'API du moteur fait lors du développement.\n" - -#, c-format -#~ msgid "Unable to rename %s to %s.\n" -#~ msgstr "Incapable de renommer %s à %s.\n" - -#, c-format -#~ msgid "When checking a pre-PG 9.1 live old server, you must specify the old server's port number.\n" -#~ msgstr "Lors de la vérification d'un serveur antérieur à la 9.1, vous devez spécifier le numéro de port de l'ancien serveur.\n" - -#~ msgid "cannot find current directory\n" -#~ msgstr "ne peut pas trouver le répertoire courant\n" - -#~ msgid "cannot write to log file %s\n" -#~ msgstr "ne peut pas écrire dans le fichier de traces %s\n" - -#, c-format -#~ msgid "check for \"%s\" failed: cannot execute (permission denied)\n" -#~ msgstr "échec de la vérification de « %s » : ne peut pas exécuter (droit refusé)\n" - -#~ msgid "check for \"%s\" failed: cannot read file (permission denied)\n" -#~ msgstr "échec de la vérification de « %s » : ne peut pas lire le fichier (droit refusé)\n" - -#, c-format -#~ msgid "check for \"%s\" failed: not a regular file\n" -#~ msgstr "échec de la vérification de « %s » : pas un fichier régulier\n" - -#~ msgid "connection to database failed: %s" -#~ msgstr "échec de la connexion à la base de données : %s" - -#, c-format -#~ msgid "could not access directory \"%s\": %m\n" -#~ msgstr "n'a pas pu accéder au répertoire « %s » : %m\n" - -#, c-format -#~ msgid "could not create directory \"%s\": %m\n" -#~ msgstr "n'a pas pu créer le répertoire « %s » : %m\n" - -#~ msgid "" -#~ "could not load library \"%s\":\n" -#~ "%s\n" -#~ msgstr "" -#~ "n'a pas pu charger la biblothèque « %s »:\n" -#~ "%s\n" - -#, c-format -#~ msgid "could not open file \"%s\": %s\n" -#~ msgstr "n'a pas pu ouvrir le fichier « %s » : %s\n" - -#, c-format -#~ msgid "could not open log file \"%s\": %m\n" -#~ msgstr "n'a pas pu ouvrir le journal applicatif « %s » : %m\n" - -#~ msgid "could not parse PG_VERSION file from %s\n" -#~ msgstr "n'a pas pu analyser le fichier PG_VERSION à partir de %s\n" - -#, c-format -#~ msgid "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "les encodages de la base de données « %s » ne correspondent pas : ancien « %s », nouveau « %s »\n" - -#, c-format -#~ msgid "failed to get system locale name for \"%s\"\n" -#~ msgstr "a échoué pour obtenir le nom de la locale système « %s »\n" - -#, c-format -#~ msgid "failed to get the current locale\n" -#~ msgstr "a échoué pour obtenir la locale courante\n" - -#, c-format -#~ msgid "failed to restore old locale \"%s\"\n" -#~ msgstr "a échoué pour restaurer l'ancienne locale « %s »\n" - -#, c-format -#~ msgid "lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "les valeurs de lc_collate de la base de données « %s » ne correspondent pas : ancien « %s », nouveau « %s »\n" - -#, c-format -#~ msgid "lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "les valeurs de lc_ctype de la base de données « %s » ne correspondent pas : ancien « %s », nouveau « %s »\n" - -#, c-format -#~ msgid "locale providers for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "les fournisseurs de locale pour la base de données « %s » ne correspondent pas : ancien « %s », nouveau « %s »\n" - -#, c-format -#~ msgid "mappings for database \"%s\":\n" -#~ msgstr "correspondances pour la base de données « %s » :\n" - -#, c-format -#~ msgid "out of memory\n" -#~ msgstr "mémoire épuisée\n" - -#, c-format -#~ msgid "too many command-line arguments (first is \"%s\")\n" -#~ msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "waitpid() failed: %s\n" -#~ msgstr "échec de waitpid() : %s\n" diff --git a/src/bin/pg_upgrade/po/ja.po b/src/bin/pg_upgrade/po/ja.po index 91f5bd9b843bf..0994211cdf4aa 100644 --- a/src/bin/pg_upgrade/po/ja.po +++ b/src/bin/pg_upgrade/po/ja.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_upgrade (PostgreSQL 17)\n" +"Project-Id-Version: pg_upgrade (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:24+0900\n" -"PO-Revision-Date: 2024-06-14 11:30+0900\n" +"POT-Creation-Date: 2025-04-14 09:41+0900\n" +"PO-Revision-Date: 2025-04-14 10:26+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -50,12 +50,12 @@ msgstr "ユーザーが存在しません" msgid "user name lookup failure: error code %lu" msgstr "ユーザー名の参照に失敗: エラーコード %lu" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" @@ -225,34 +225,34 @@ msgstr "" "このクラスタは現時点ではアップグレードできません。問題の列を削除するか、\n" "他のデータ型に変更した後にアップグレードを再実行できます。\n" -#: check.c:345 +#: check.c:421 #, c-format -msgid "Checking for data type usage" -msgstr "データ型の使用を確認しています" - -#: check.c:480 -#, c-format -msgid " failed check: %s" -msgstr " 問題を検出した項目: %s" +msgid "failed check: %s" +msgstr "問題を検出した項目: %s" -#: check.c:483 +#: check.c:424 msgid "A list of the problem columns is in the file:" msgstr "問題の列の一覧は以下のファイルにあります:" -#: check.c:495 check.c:961 check.c:1134 check.c:1249 check.c:1343 check.c:1471 -#: check.c:1547 check.c:1611 check.c:1684 check.c:1866 check.c:1885 -#: check.c:1954 check.c:2006 file.c:378 file.c:415 function.c:189 option.c:493 -#: version.c:79 version.c:177 +#: check.c:430 check.c:1026 check.c:1177 check.c:1260 check.c:1349 check.c:1440 +#: check.c:1572 check.c:1657 check.c:1704 check.c:1784 check.c:2089 +#: check.c:2108 check.c:2154 check.c:2207 file.c:378 file.c:415 function.c:208 +#: option.c:519 version.c:79 version.c:162 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: check.c:522 +#: check.c:472 +#, c-format +msgid "Checking data type usage" +msgstr "データ型の使用を確認しています" + +#: check.c:526 #, c-format msgid "Data type checks failed: %s" msgstr "問題を検出したデータ型確認項目: %s" -#: check.c:563 +#: check.c:575 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -261,7 +261,7 @@ msgstr "" "元の実行中サーバーの一貫性チェックを実行しています。\n" "--------------------------------------------------" -#: check.c:569 +#: check.c:581 #, c-format msgid "" "Performing Consistency Checks\n" @@ -270,7 +270,12 @@ msgstr "" "整合性チェックを実行しています。\n" "-----------------------------" -#: check.c:716 +#: check.c:745 +#, c-format +msgid "Swap mode can only upgrade clusters from PostgreSQL version %s and later." +msgstr "スワップモードはPostgreSQL %s以降のバージョンからのアップグレードのみ可能です。" + +#: check.c:768 #, c-format msgid "" "\n" @@ -279,7 +284,7 @@ msgstr "" "\n" "* クラスタは互換性があります *" -#: check.c:724 +#: check.c:776 #, c-format msgid "" "\n" @@ -290,18 +295,18 @@ msgstr "" "この後pg_upgradeが失敗した場合は、続ける前に新しいクラスタを\n" "initdbで再作成する必要があります。" -#: check.c:765 +#: check.c:817 #, c-format msgid "" -"Optimizer statistics are not transferred by pg_upgrade.\n" +"Some optimizer statistics may not have been transferred by pg_upgrade.\n" "Once you start the new server, consider running:\n" -" %s/vacuumdb %s--all --analyze-in-stages" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only" msgstr "" -"オプティマイザーの統計は、pg_upgrade では転送されません。そのため\n" -"新サーバーを起動した後、以下を行うことを検討してください。\n" -" %s/vacuumdb %s--all --analyze-in-stages" +"オプティマイザー統計の一部は pg_upgrade で転送されなかった可能性があります。\n" +"新しいサーバーを起動した後、次の操作を検討してください。\n" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only" -#: check.c:771 +#: check.c:823 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -310,7 +315,7 @@ msgstr "" "このスクリプトを実行すると、旧クラスタのデータファイルが削除されます:\n" " %s" -#: check.c:776 +#: check.c:828 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -323,57 +328,62 @@ msgstr "" "ファイルを削除するためのスクリプトを作成できませんでした。 古い\n" "クラスタの内容は手動で削除する必要があります。" -#: check.c:788 +#: check.c:840 #, c-format msgid "Checking cluster versions" msgstr "クラスタのバージョンを確認しています" -#: check.c:800 +#: check.c:852 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "このユーティリティではPostgreSQLバージョン%s以降のバージョンからのみアップグレードできます。" -#: check.c:805 +#: check.c:857 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "このユーティリティは、PostgreSQLバージョン%sにのみアップグレードできます。" -#: check.c:814 +#: check.c:866 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "このユーティリティは PostgreSQL の過去のメジャーバージョンにダウングレードする用途では使用できません。" -#: check.c:819 +#: check.c:871 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "旧クラスタのデータとバイナリのディレクトリは異なるメジャーバージョンのものです。" -#: check.c:822 +#: check.c:874 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "新クラスタのデータとバイナリのディレクトリは異なるメジャーバージョンのものです。" -#: check.c:837 +#: check.c:885 +#, c-format +msgid "%s option cannot be used to upgrade from PostgreSQL %s and later." +msgstr "PostgreSQL %s以降からのアップグレードでは %s オプションは使用できません。" + +#: check.c:901 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "稼働中のサーバーをチェックする場合、新旧のポート番号が異なっている必要があります。" -#: check.c:857 +#: check.c:921 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "新クラスタのデータベース\"%s\"が空ではありません: リレーション\"%s.%s\"が見つかりました" -#: check.c:880 +#: check.c:944 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "新しいクラスタのテーブル空間ディレクトリを確認しています" -#: check.c:891 +#: check.c:955 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "新しいクラスタのテーブル空間ディレクトリはすでに存在します: \"%s\"" -#: check.c:924 +#: check.c:989 #, c-format msgid "" "\n" @@ -382,7 +392,7 @@ msgstr "" "\n" "警告: 新データディレクトリが旧データディレクトリ、つまり %sの中にあってはなりません" -#: check.c:948 +#: check.c:1013 #, c-format msgid "" "\n" @@ -391,92 +401,92 @@ msgstr "" "\n" "警告: ユーザー定義テーブル空間の場所がデータディレクトリ、つまり %s の中にあってはなりません。" -#: check.c:958 +#: check.c:1023 #, c-format msgid "Creating script to delete old cluster" msgstr "旧クラスタを削除するスクリプトを作成しています" -#: check.c:1012 +#: check.c:1051 #, c-format msgid "could not add execute permission to file \"%s\": %m" msgstr "ファイル\"%s\"に実行権限を追加できませんでした: %m" -#: check.c:1032 +#: check.c:1071 #, c-format msgid "Checking database user is the install user" msgstr "データベースユーザーがインストールユーザーかどうかをチェックしています" -#: check.c:1048 +#: check.c:1087 #, c-format msgid "database user \"%s\" is not the install user" msgstr "データベースユーザー\"%s\"がインストールユーザーではありません" -#: check.c:1059 +#: check.c:1098 #, c-format msgid "could not determine the number of users" msgstr "ユーザー数を特定できませんでした" -#: check.c:1067 +#: check.c:1106 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "新クラスタ内で定義できるのはインストールユーザーのみです。" -#: check.c:1096 +#: check.c:1136 #, c-format msgid "Checking database connection settings" msgstr "データベース接続の設定を確認しています" -#: check.c:1122 +#: check.c:1164 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0 には接続を許可してはなりません。すなわち、pg_database.datallowconn は false である必要があります" -#: check.c:1148 check.c:1268 check.c:1365 check.c:1490 check.c:1566 -#: check.c:1624 check.c:1704 check.c:1898 check.c:2023 function.c:210 +#: check.c:1191 check.c:1312 check.c:1408 check.c:1536 check.c:1612 +#: check.c:1670 check.c:1753 check.c:2121 check.c:2263 function.c:229 #, c-format msgid "fatal" msgstr "致命的" -#: check.c:1149 +#: check.c:1192 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" -"pg_database.datallowconn must be true. Your installation contains\n" -"non-template0 databases with their pg_database.datallowconn set to\n" -"false. Consider allowing connection for all non-template0 databases\n" -"or drop the databases which do not allow connections. A list of\n" -"databases with the problem is in the file:\n" +"pg_database.datallowconn must be true and pg_database.datconnlimit\n" +"must not be -2. Your installation contains non-template0 databases\n" +"which cannot be connected to. Consider allowing connection for all\n" +"non-template0 databases or drop the databases which do not allow\n" +"connections. A list of databases with the problem is in the file:\n" " %s" msgstr "" "template0ではないすべてのデータベースは接続を許可しなければなりません、つまり\n" -"pg_database.datallowconnがtrueでなければなりません。このクラスタには\n" -"pg_database.datallowconnがfalseとなっているtemplate0以外のデータベースが\n" +"pg_database.datallowconnがtrue、そしてpg_database.datconnlimitが-2以外の\n" +"値でなければなりません。このクラスタには接続不可なtemplate0以外のデータベースが\n" "存在しています。template0以外のすべてのデータベースへの接続を許可するか、接続が\n" -"許可されないデータベースをすべて削除することを検討してください。問題のあるデータベースの\n" +"許可されないデータベースを削除することを検討してください。問題のあるデータベースの\n" "一覧が以下のファイルにあります:\n" " %s" -#: check.c:1174 +#: check.c:1217 #, c-format msgid "Checking for prepared transactions" msgstr "準備済みトランザクションをチェックしています" -#: check.c:1183 +#: check.c:1226 #, c-format msgid "The source cluster contains prepared transactions" msgstr "移行元クラスタに準備済みトランザクションがあります" -#: check.c:1185 +#: check.c:1228 #, c-format msgid "The target cluster contains prepared transactions" msgstr "移行先クラスタに準備済みトランザクションがあります" -#: check.c:1210 +#: check.c:1288 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "bigint を渡す際にミスマッチが発生する contrib/isn をチェックしています" -#: check.c:1269 +#: check.c:1313 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -496,12 +506,12 @@ msgstr "" "問題のある関数の一覧は以下のファイルにあります:\n" " %s" -#: check.c:1291 +#: check.c:1393 #, c-format msgid "Checking for user-defined postfix operators" msgstr "ユーザー定義の後置演算子を確認しています" -#: check.c:1366 +#: check.c:1409 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -516,12 +526,12 @@ msgstr "" "以下のファイルにユーザー定義後置演算子の一覧があります:\n" " %s" -#: check.c:1390 +#: check.c:1464 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "非互換の多態関数を確認しています" -#: check.c:1491 +#: check.c:1537 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -539,12 +549,12 @@ msgstr "" "問題となるオブジェクトの一覧は以下のファイルにあります:\n" " %s" -#: check.c:1515 +#: check.c:1597 #, c-format msgid "Checking for tables WITH OIDS" msgstr "WITH OIDS宣言されたテーブルをチェックしています" -#: check.c:1567 +#: check.c:1613 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -559,12 +569,12 @@ msgstr "" "以下のファイルにこの問題を抱えるテーブルの一覧があります:\n" " %s" -#: check.c:1594 +#: check.c:1640 #, c-format msgid "Checking for roles starting with \"pg_\"" msgstr "'pg_' で始まるロールをチェックしています" -#: check.c:1625 +#: check.c:1671 #, c-format msgid "" "Your installation contains roles starting with \"pg_\".\n" @@ -580,12 +590,12 @@ msgstr "" "\"pg_\"で始まるロールの一覧は以下のファイルにあります:\n" " %s" -#: check.c:1645 +#: check.c:1725 #, c-format msgid "Checking for user-defined encoding conversions" msgstr "ユーザー定義のエンコーディング変換を確認しています" -#: check.c:1705 +#: check.c:1754 #, c-format msgid "" "Your installation contains user-defined encoding conversions.\n" @@ -603,55 +613,76 @@ msgstr "" "ユーザー定義のエンコーディング変換の一覧は以下のファイルにあります:\n" " %s" -#: check.c:1744 +#: check.c:1839 +#, c-format +msgid "Checking for objects affected by Unicode update" +msgstr "Unicodeの更新によって影響を受けるオブジェクトを確認しています" + +#: check.c:1933 version.c:121 +#, c-format +msgid "warning" +msgstr "警告" + +#: check.c:1934 +#, c-format +msgid "" +"Your installation contains relations that may be affected by a new version of Unicode.\n" +"A list of potentially-affected relations is in the file:\n" +" %s" +msgstr "" +"このクラスタにはUnicodeの新しいバージョンの影響を受ける可能性があるリレーションが含まれています。\n" +"影響を受ける可能性があるリレーションの一覧は以下のファイルにあります:\n" +" %s" + +#: check.c:1970 #, c-format msgid "Checking for new cluster logical replication slots" msgstr "新しいクラスタの論理レプリケーションスロットを確認しています" -#: check.c:1752 +#: check.c:1978 #, c-format msgid "could not count the number of logical replication slots" msgstr "論理レプリケーションスロットの数を数えられませんでした" -#: check.c:1757 +#: check.c:1983 #, c-format -msgid "Expected 0 logical replication slots but found %d." -msgstr "物理レプリケーションスロット数は0であることを期待していましたが %d スロットありました。" +msgid "expected 0 logical replication slots but found %d" +msgstr "論理レプリケーションスロット数は0であることを期待していましたが、%d個ありました" -#: check.c:1767 check.c:1821 +#: check.c:1993 check.c:2044 #, c-format msgid "could not determine parameter settings on new cluster" msgstr "新クラスタ上のパラメータ設定を決定できませんでした" -#: check.c:1772 +#: check.c:1998 #, c-format -msgid "\"wal_level\" must be \"logical\", but is set to \"%s\"" -msgstr "\"wal_level\"は\"logical\"でなければなりませんが、\"%s\"に設定されています" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "\"wal_level\"は\"logical\"でなければなりませんが\"%s\"に設定されています" -#: check.c:1778 +#: check.c:2004 #, c-format msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" msgstr "\"max_replication_slots\" (%d) は旧クラスタにおける論理レプリケーションスロットの数(%d)以上でなければなりません" -#: check.c:1813 +#: check.c:2036 #, c-format msgid "Checking for new cluster configuration for subscriptions" msgstr "新しいクラスタの構成のサブスクリプションを確認しています" -#: check.c:1825 +#: check.c:2048 #, c-format -msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" -msgstr "\"max_replication_slots\" (%d) は旧クラスタにおけるサブスクリプションの数(%d)以上でなければなりません" +msgid "\"max_active_replication_origins\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "\"max_active_replication_origins\" (%d) は旧クラスタにおけるサブスクリプションの数(%d)以上でなければなりません" -#: check.c:1847 +#: check.c:2070 #, c-format msgid "Checking for valid logical replication slots" msgstr "有効な論理レプリケーションスロットを確認しています" -#: check.c:1899 +#: check.c:2122 #, c-format msgid "" -"Your installation contains logical replication slots that can't be upgraded.\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" "You can remove invalid slots and/or consume the pending WAL for other slots,\n" "and then restart the upgrade.\n" "A list of the problematic slots is in the file:\n" @@ -663,12 +694,12 @@ msgstr "" "問題のある列の一覧は、以下のファイルにあります: \n" " %s" -#: check.c:1923 +#: check.c:2182 #, c-format msgid "Checking for subscription state" msgstr "サブスクリプション状態を確認しています" -#: check.c:2024 +#: check.c:2264 #, c-format msgid "" "Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" @@ -682,184 +713,189 @@ msgstr "" "問題のあるサブスクリプションの一覧は、以下のファイルにあります: \n" " %s" -#: controldata.c:129 controldata.c:199 +#: controldata.c:133 controldata.c:203 #, c-format msgid "could not get control data using %s: %m" msgstr "%sで制御情報が取得できませんでした: %m" -#: controldata.c:139 +#: controldata.c:143 #, c-format msgid "%d: database cluster state problem" msgstr "%d: データベースクラスタの状態異常" -#: controldata.c:158 +#: controldata.c:162 #, c-format msgid "The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "移行元クラスタはリカバリモード中にシャットダウンされています。アップグレードをするにはドキュメントの通りに \"rsync\" を実行するか、プライマリとしてシャットダウンしてください。" -#: controldata.c:160 +#: controldata.c:164 #, c-format msgid "The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "移行先クラスタはリカバリモード中にシャットダウンされています。アップグレードをするにはドキュメントの通りに \"rsync\" を実行するか、プライマリとしてシャットダウンしてください。" -#: controldata.c:165 +#: controldata.c:169 #, c-format msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "移行元クラスタはクリーンにシャットダウンされていません、状態は以下のように報告されています: \"%s\"" -#: controldata.c:167 +#: controldata.c:171 #, c-format msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "移行先クラスタはクリーンにシャットダウンされていません、状態は以下のように報告されています: \"%s\"" -#: controldata.c:175 controldata.c:507 +#: controldata.c:179 controldata.c:530 #, c-format msgid "could not get control data using %s: %s" msgstr "%s で制御情報が取得できませんでした。: %s" -#: controldata.c:181 +#: controldata.c:185 #, c-format msgid "The source cluster lacks cluster state information:" msgstr "移行元クラスタにクラスタ状態情報がありません:" -#: controldata.c:183 +#: controldata.c:187 #, c-format msgid "The target cluster lacks cluster state information:" msgstr "移行先クラスタにクラスタ状態情報がありません:" -#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 -#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 +#: controldata.c:217 dump.c:50 exec.c:118 pg_upgrade.c:606 pg_upgrade.c:646 +#: pg_upgrade.c:995 relfilenumber.c:610 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:220 +#: controldata.c:224 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d: pg_resetwal で問題発生" -#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 -#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 -#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 -#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 -#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 -#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 -#: controldata.c:486 controldata.c:497 +#: controldata.c:234 controldata.c:244 controldata.c:255 controldata.c:266 +#: controldata.c:277 controldata.c:296 controldata.c:307 controldata.c:318 +#: controldata.c:329 controldata.c:340 controldata.c:351 controldata.c:362 +#: controldata.c:365 controldata.c:369 controldata.c:379 controldata.c:391 +#: controldata.c:402 controldata.c:413 controldata.c:424 controldata.c:435 +#: controldata.c:446 controldata.c:457 controldata.c:468 controldata.c:479 +#: controldata.c:490 controldata.c:501 controldata.c:512 controldata.c:521 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d: 制御情報の取得で問題発生" -#: controldata.c:578 +#: controldata.c:618 #, c-format msgid "The source cluster lacks some required control information:" msgstr "移行元クラスタに必要な制御情報の一部がありません:" -#: controldata.c:581 +#: controldata.c:621 #, c-format msgid "The target cluster lacks some required control information:" msgstr "移行先クラスタに必要な制御情報の一部がありません:" -#: controldata.c:584 +#: controldata.c:624 #, c-format msgid " checkpoint next XID" msgstr " チェックポイントにおける次のXID" -#: controldata.c:587 +#: controldata.c:627 #, c-format msgid " latest checkpoint next OID" msgstr " 最新のチェックポイントにおける次のOID" -#: controldata.c:590 +#: controldata.c:630 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " 最新のチェックポイントにおける次のMultiXactId" -#: controldata.c:594 +#: controldata.c:634 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " 最新のチェックポイントにおける最古のMultiXactId" -#: controldata.c:597 +#: controldata.c:637 #, c-format msgid " latest checkpoint oldestXID" msgstr " 最新のチェックポイントにおける最古のXID" -#: controldata.c:600 +#: controldata.c:640 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " 最新のチェックポイントにおける次のMultiXactOffset" -#: controldata.c:603 +#: controldata.c:643 #, c-format msgid " first WAL segment after reset" msgstr " リセット後の最初のWALセグメント" -#: controldata.c:606 +#: controldata.c:646 #, c-format msgid " float8 argument passing method" msgstr " float8引数の引き渡し方法" -#: controldata.c:609 +#: controldata.c:649 #, c-format msgid " maximum alignment" msgstr " 最大アラインメント" -#: controldata.c:612 +#: controldata.c:652 #, c-format msgid " block size" msgstr " ブロックサイズ" -#: controldata.c:615 +#: controldata.c:655 #, c-format msgid " large relation segment size" msgstr " 大きなリレーションセグメントのサイズ" -#: controldata.c:618 +#: controldata.c:658 #, c-format msgid " WAL block size" msgstr " WALのブロックサイズ" -#: controldata.c:621 +#: controldata.c:661 #, c-format msgid " WAL segment size" msgstr " WALのセグメントサイズ" -#: controldata.c:624 +#: controldata.c:664 #, c-format msgid " maximum identifier length" msgstr " 識別子の最大長" -#: controldata.c:627 +#: controldata.c:667 #, c-format msgid " maximum number of indexed columns" msgstr " インデックス対象カラムの最大数" -#: controldata.c:630 +#: controldata.c:670 #, c-format msgid " maximum TOAST chunk size" msgstr " 最大のTOASTチャンクサイズ" -#: controldata.c:634 +#: controldata.c:674 #, c-format msgid " large-object chunk size" msgstr " ラージオブジェクトのチャンクサイズ" -#: controldata.c:637 +#: controldata.c:677 #, c-format msgid " dates/times are integers?" msgstr " 日付/時間が整数?" -#: controldata.c:641 +#: controldata.c:681 #, c-format msgid " data checksum version" msgstr " データチェックサムのバージョン" -#: controldata.c:643 +#: controldata.c:685 +#, c-format +msgid " default char signedness" +msgstr " デフォルトのchar型の符号の有無" + +#: controldata.c:687 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "必要な制御情報がないので続行できません。終了します" -#: controldata.c:658 +#: controldata.c:702 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -868,91 +904,106 @@ msgstr "" "新旧のpg_controldataのアラインメントが不正であるかかまたは一致しません\n" "一方のクラスタが32ビットで、他方が64ビットである可能性が高いです" -#: controldata.c:662 +#: controldata.c:706 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "新旧の pg_controldata におけるブロックサイズが有効でないかまたは一致しません" -#: controldata.c:665 +#: controldata.c:709 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "新旧の pg_controldata におけるリレーションの最大セグメントサイズが有効でないか一致しません" -#: controldata.c:668 +#: controldata.c:712 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "新旧の pg_controldata における WAL ブロックサイズが有効でないか一致しません" -#: controldata.c:671 +#: controldata.c:715 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "新旧の pg_controldata におけるWALセグメントサイズが有効でないか一致しません" -#: controldata.c:674 +#: controldata.c:718 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "新旧の pg_controldata における識別子の最大長が有効でないか一致しません" -#: controldata.c:677 +#: controldata.c:721 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "新旧の pg_controldata におけるインデックス付き列の最大数が有効でないか一致しません" -#: controldata.c:680 +#: controldata.c:724 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "新旧の pg_controldata におけるTOASTチャンクサイズの最大値が有効でないか一致しません" -#: controldata.c:685 +#: controldata.c:729 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "新旧の pg_controldata におけるラージオブジェクトのチャンクサイズが有効でないかまたは一致しません" -#: controldata.c:688 +#: controldata.c:732 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "新旧の pg_controldata における日付/時刻型データの保存バイト数が一致しません" -#: controldata.c:701 +#: controldata.c:745 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "旧クラスタではデータチェックサムを使用していませんが、新クラスタでは使用しています" -#: controldata.c:704 +#: controldata.c:748 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "旧クラスタではデータチェックサムを使用していますが、新クラスタでは使用していません" -#: controldata.c:706 +#: controldata.c:750 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "新旧の pg_controldata 間でチェックサムのバージョンが一致しません" -#: controldata.c:717 +#: controldata.c:761 #, c-format -msgid "Adding \".old\" suffix to old global/pg_control" -msgstr "旧の global/pg_control に \".old\" サフィックスを追加しています" +msgid "Adding \".old\" suffix to old " +msgstr "古い global/pg_control に \".old\" サフィックスを追加しています" -#: controldata.c:722 +#: controldata.c:766 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" -#: controldata.c:726 +#: controldata.c:771 #, c-format msgid "" "\n" "If you want to start the old cluster, you will need to remove\n" -"the \".old\" suffix from %s/global/pg_control.old.\n" +"the \".old\" suffix from %s/%s.old.\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" "started once the new cluster has been started." msgstr "" "\n" -"旧クラスタを起動する場合、%s/global/pg_control.oldから\n" +"旧クラスタを起動する場合、%s/%s.oldから\n" "\".old\"拡張子を削除する必要があります。「リンク」モードが使われて\n" "いるため、一度新クラスタを起動してしまうと旧クラスタは安全に起動\n" "することができなくなります。" +#: controldata.c:778 +#, c-format +msgid "" +"\n" +"Because \"swap\" mode was used, the old cluster can no longer be\n" +"safely started." +msgstr "" +"\n" +"\"swap\"モードが使用されているため, 古いクラスタは今後安全に起動できません" + +#: controldata.c:782 file.c:455 +#, c-format +msgid "unrecognized transfer mode" +msgstr "識別できない転送モード" + #: dump.c:20 #, c-format msgid "Creating dump of global objects" @@ -983,7 +1034,7 @@ msgstr "%s からpg_ctlのバージョン出力を取得できませんでした msgid "command too long" msgstr "コマンドが長すぎます" -#: exec.c:160 pg_upgrade.c:311 +#: exec.c:160 pg_upgrade.c:315 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ロックファイル\"%s\"をオープンできませんでした: %m" @@ -1018,7 +1069,7 @@ msgid "" "the probable cause of the failure." msgstr "ありうる失敗の原因については、\"%s\"の最後の数行を参照してください。" -#: exec.c:218 pg_upgrade.c:321 +#: exec.c:218 pg_upgrade.c:325 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "ログファイル\"%s\"に書き込めませんでした: %m" @@ -1143,7 +1194,7 @@ msgstr "新旧ディレクトリ間のファイルの範囲コピーができま msgid "copy_file_range not supported on this platform" msgstr "このプラットフォームではcopy_file_rangeはサポートされません" -#: file.c:447 +#: file.c:449 #, c-format msgid "" "could not create hard link between old and new data directories: %m\n" @@ -1152,22 +1203,31 @@ msgstr "" "新旧のデータディレクトリ間でハードリンクを作成できませんでした: %m\n" "リンクモードでは、新旧のデータディレクトリが同じファイルシステム上にある必要があります。" -#: function.c:154 +#: file.c:452 +#, c-format +msgid "" +"could not create hard link between old and new data directories: %m\n" +"In swap mode the old and new data directories must be on the same file system." +msgstr "" +"新旧のデータディレクトリ間でハードリンクを作成できませんでした: %m\n" +"スワップモードでは、新旧のデータディレクトリが同じファイルシステム上にある必要があります。" + +#: function.c:173 #, c-format msgid "Checking for presence of required libraries" msgstr "必要なライブラリの有無を確認しています" -#: function.c:190 +#: function.c:209 #, c-format msgid "could not load library \"%s\": %s" msgstr "ライブラリ\"%s\"をロードできませんでした: %s" -#: function.c:201 +#: function.c:220 #, c-format msgid "In database: %s\n" msgstr "データベース: %s\n" -#: function.c:211 +#: function.c:230 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -1182,47 +1242,47 @@ msgstr "" "以下のファイルに入っています:\n" " %s" -#: info.c:129 +#: info.c:131 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "データベース\"%2$s\"で OID %1$u のリレーション名が一致しません: 元の名前 \"%3$s.%4$s\"、新しい名前 \"%5$s.%6$s\"" -#: info.c:149 +#: info.c:151 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "データベース\"%s\"で新旧のテーブルの照合に失敗しました" -#: info.c:230 +#: info.c:232 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " これは \"%s.%s\" 上のインデックスです" -#: info.c:240 +#: info.c:242 #, c-format msgid " which is an index on OID %u" msgstr " これは OID %u 上のインデックスです" -#: info.c:252 +#: info.c:254 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " これは \"%s.%s\" の TOAST テーブルです" -#: info.c:260 +#: info.c:262 #, c-format msgid " which is the TOAST table for OID %u" msgstr " これは OID %u の TOAST テーブルです" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "データベース\"%2$s\"でOID%1$uを持つ新リレーションに対応するリレーションが旧クラスタ内にありません: %3$s" -#: info.c:267 +#: info.c:269 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "データベース\"%2$s\"でOID %1$uを持つ旧リレーションに対応するリレーションが新クラスタ内にありません: %3$s" -#: info.c:308 +#: info.c:325 #, c-format msgid "" "\n" @@ -1231,7 +1291,7 @@ msgstr "" "\n" "移行元データベース:" -#: info.c:310 +#: info.c:327 #, c-format msgid "" "\n" @@ -1240,92 +1300,97 @@ msgstr "" "\n" "移行先データベース:" -#: info.c:354 +#: info.c:371 #, c-format msgid "template0 not found" msgstr "template0が見つかりません" -#: info.c:842 +#: info.c:817 #, c-format msgid "Database: \"%s\"" msgstr "データベース: \"%s\"" -#: info.c:855 +#: info.c:830 #, c-format msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" msgstr "relname: \"%s.%s\": reloid: %u reltblspace: \"%s\"" -#: info.c:869 +#: info.c:844 #, c-format -msgid "Logical replication slots within the database:" -msgstr "このデータベース内の論理レプリケーションスロット: " +msgid "Logical replication slots in the database:" +msgstr "このデータベースの論理レプリケーションスロット: " -#: info.c:875 +#: info.c:850 #, c-format -msgid "slot_name: \"%s\", plugin: \"%s\", two_phase: %s" -msgstr "slot_name: \"%s\", plugin: \"%s\", two_phase: %s" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "スロット名: \"%s\", 出力プラグイン: \"%s\", two_phase: %s" -#: option.c:105 +#: option.c:110 #, c-format msgid "%s: cannot be run as root" msgstr "%s: rootでは実行できません" -#: option.c:172 +#: option.c:177 #, c-format msgid "invalid old port number" msgstr "不正な旧ポート番号" -#: option.c:177 +#: option.c:182 #, c-format msgid "invalid new port number" msgstr "不正な新ポート番号" -#: option.c:216 +#: option.c:230 +#, c-format +msgid "invalid argument for option %s" +msgstr "オプション%sの引数が不正です" + +#: option.c:238 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "詳細は\"%s --help\"を参照してください。\n" -#: option.c:223 +#: option.c:245 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: option.c:229 +#: option.c:251 #, c-format msgid "Running in verbose mode" msgstr "詳細表示モードで実行しています" -#: option.c:247 +#: option.c:269 msgid "old cluster binaries reside" msgstr "旧クラスタのバイナリが置かれている" -#: option.c:249 +#: option.c:271 msgid "new cluster binaries reside" msgstr "新クラスタのバイナリが置かれている" -#: option.c:251 +#: option.c:273 msgid "old cluster data resides" msgstr "旧クラスタのデータが置かれている" -#: option.c:253 +#: option.c:275 msgid "new cluster data resides" msgstr "新クラスタのデータが置かれている" -#: option.c:255 +#: option.c:277 msgid "sockets will be created" msgstr "ソケットが作成される" -#: option.c:272 option.c:374 +#: option.c:294 option.c:400 #, c-format msgid "could not determine current directory" msgstr "カレントディレクトリを特定できませんでした" -#: option.c:275 +#: option.c:297 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "Windowsでは、新クラスタのデータディレクトリの中でpg_upgradeを実行することはできません" -#: option.c:284 +#: option.c:306 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1334,12 +1399,12 @@ msgstr "" "pg_upgradeは、PostgreSQLのクラスタを別のメジャーバージョンにアップグレードします。\n" "\n" -#: option.c:285 +#: option.c:307 #, c-format msgid "Usage:\n" msgstr "使い方:\n" -#: option.c:286 +#: option.c:308 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1348,17 +1413,17 @@ msgstr "" " pg_upgrade [オプション]...\n" "\n" -#: option.c:287 +#: option.c:309 #, c-format msgid "Options:\n" msgstr "オプション:\n" -#: option.c:288 +#: option.c:310 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINDIR 旧クラスタの実行ファイルディレクトリ\n" -#: option.c:289 +#: option.c:311 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1367,115 +1432,137 @@ msgstr "" " -B, --new-bindir=BINDIR 新クラスタの実行ファイルディレクトリ(デフォルト\n" " はpg_upgradeと同じディレクトリ)\n" -#: option.c:291 +#: option.c:313 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check クラスタのチェックのみ、データを一切変更しない\n" -#: option.c:292 +#: option.c:314 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATADIR 旧クラスタのデータディレクトリ\n" -#: option.c:293 +#: option.c:315 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATADIR 新クラスタのデータディレクトリ\n" -#: option.c:294 +#: option.c:316 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs 使用する同時実行プロセスまたはスレッドの数\n" -#: option.c:295 +#: option.c:317 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr "" " -k, --link 新クラスタにファイルをコピーする代わりに\n" " リンクする\n" -#: option.c:296 +#: option.c:318 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync 変更のディスクへの確実な書き出しを待機しない\n" -#: option.c:297 +#: option.c:319 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=OPTIONS サーバーに渡す旧クラスタのオプション\n" -#: option.c:298 +#: option.c:320 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=OPTIONS サーバーに渡す新クラスタのオプション\n" -#: option.c:299 +#: option.c:321 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PORT 旧クラスタのポート番号(デフォルト %d)\n" -#: option.c:300 +#: option.c:322 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT 新クラスタのポート番号(デフォルト %d)\n" -#: option.c:301 +#: option.c:323 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain SQLとログファイルを、成功後も消さずに残す\n" -#: option.c:302 +#: option.c:324 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr "" " -s, --socketdir=DIR 使用するソケットディレクトリ(デフォルトは\n" " カレントディレクトリ)\n" -#: option.c:303 +#: option.c:325 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=NAME クラスタのスーパーユーザー(デフォルト\"%s\")\n" -#: option.c:304 +#: option.c:326 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose 詳細な内部ログを有効化\n" -#: option.c:305 +#: option.c:327 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: option.c:306 +#: option.c:328 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr "" " --clone 新クラスタにファイルをコピーする代わりに\n" " クローンする\n" -#: option.c:307 +#: option.c:329 #, c-format msgid " --copy copy files to new cluster (default)\n" msgstr " --copy 新クラスタにファイルをコピーする(デフォルト)\n" -#: option.c:308 +#: option.c:330 #, c-format msgid " --copy-file-range copy files to new cluster with copy_file_range\n" -msgstr " --copy-file-range ファイルの新クラスタへのコピーをcopy_file_rangeで行う\n" +msgstr "" +" --copy-file-range ファイルの新クラスタへのコピーをcopy_file_range\n" +" で行う\n" -#: option.c:309 +#: option.c:331 +#, c-format +msgid " --no-statistics do not import statistics from old cluster\n" +msgstr " --no-statistics 旧クラスタから統計情報をインポートしない\n" + +#: option.c:332 +#, c-format +msgid "" +" --set-char-signedness=OPTION set new cluster char signedness to \"signed\" or\n" +" \"unsigned\"\n" +msgstr "" +" --set-char-signedness=オプション\n" +" 新しいクラスタでの、char型を符号付き(signed)\n" +" または符号なし(unsigned)を設定する\n" + +#: option.c:334 +#, c-format +msgid " --swap move data directories to new cluster\n" +msgstr " --swap 新クラスタにファイルを移動する\n" + +#: option.c:335 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr "" " --sync-method=METHOD ファイルをディスクに同期させる方法を指定\n" "\n" -#: option.c:310 +#: option.c:336 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: option.c:311 +#: option.c:337 #, c-format msgid "" "\n" @@ -1490,7 +1577,7 @@ msgstr "" " 旧クラスタのpostmasterをシャットダウンする\n" " 新クラスタのpostmasterをシャットダウンする\n" -#: option.c:316 +#: option.c:342 #, c-format msgid "" "\n" @@ -1507,7 +1594,7 @@ msgstr "" " 旧バージョンの\"bin\"ディレクトリ (-b BINDIR)\n" " 新バージョンの\"bin\"ディレクトリ(-B BINDIR)\n" -#: option.c:322 +#: option.c:348 #, c-format msgid "" "\n" @@ -1520,7 +1607,7 @@ msgstr "" " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n" "または\n" -#: option.c:327 +#: option.c:353 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1535,7 +1622,7 @@ msgstr "" " $ export PGBINNEW=newCluster/bin\n" " $ pg_upgrade\n" -#: option.c:333 +#: option.c:359 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1550,7 +1637,7 @@ msgstr "" " C:\\> set PGBINNEW=newCluster/bin\n" " C:\\> pg_upgrade\n" -#: option.c:339 +#: option.c:365 #, c-format msgid "" "\n" @@ -1559,12 +1646,12 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: option.c:340 +#: option.c:366 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: option.c:380 +#: option.c:406 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1573,32 +1660,32 @@ msgstr "" "%sディレクトリを指定する必要があります。\n" "コマンドラインオプション %s または環境変数 %s を使用してください。" -#: option.c:433 +#: option.c:459 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "移行元クラスタの実際のデータディレクトリを探しています" -#: option.c:435 +#: option.c:461 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "移行先クラスタの実際のデータディレクトリを探しています" -#: option.c:448 +#: option.c:474 #, c-format msgid "could not get data directory using %s: %m" msgstr "%sでデータディレクトリを取得できませんでした。: %m" -#: option.c:452 +#: option.c:478 #, c-format msgid "could not get data directory using %s: %s" msgstr "%s でデータディレクトリを取得できませんでした。: %s" -#: option.c:500 +#: option.c:526 #, c-format msgid "could not read line %d from file \"%s\": %m" msgstr "ファイル\"%2$s\"の%1$d行目を読み取れませんでした: %3$m" -#: option.c:517 +#: option.c:543 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "ユーザー指定の旧ポート番号%huは%huに訂正されました" @@ -1628,12 +1715,12 @@ msgstr "子プロセスが異常終了しました: ステータス %d" msgid "child worker exited abnormally: %m" msgstr "子ワーカーが異常終了しました: %m" -#: pg_upgrade.c:115 +#: pg_upgrade.c:114 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "ディレクトリ\"%s\"の権限を読み取れませんでした: %m" -#: pg_upgrade.c:147 +#: pg_upgrade.c:146 #, c-format msgid "" "\n" @@ -1644,17 +1731,17 @@ msgstr "" "アップグレードを実行しています。\n" "------------------" -#: pg_upgrade.c:192 +#: pg_upgrade.c:194 #, c-format msgid "Setting next OID for new cluster" msgstr "新クラスタの、次の OID を設定しています" -#: pg_upgrade.c:216 +#: pg_upgrade.c:218 #, c-format msgid "Sync data directory to disk" msgstr "データディレクトリをディスクに同期します" -#: pg_upgrade.c:230 +#: pg_upgrade.c:234 #, c-format msgid "" "\n" @@ -1665,23 +1752,23 @@ msgstr "" "アップグレードが完了しました\n" "----------------" -#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 -#: pg_upgrade.c:308 pg_upgrade.c:319 +#: pg_upgrade.c:267 pg_upgrade.c:280 pg_upgrade.c:287 pg_upgrade.c:294 +#: pg_upgrade.c:312 pg_upgrade.c:323 #, c-format msgid "directory path for new cluster is too long" msgstr "新クラスタのディレクトリ・パスが長すぎます" -#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#: pg_upgrade.c:301 pg_upgrade.c:303 pg_upgrade.c:305 pg_upgrade.c:307 #, c-format msgid "could not create directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を作成できませんでした: %m" -#: pg_upgrade.c:352 +#: pg_upgrade.c:356 #, c-format msgid "%s: could not find own program executable" msgstr "%s: 自身の実行ファイルが見つかりませんでした" -#: pg_upgrade.c:378 +#: pg_upgrade.c:382 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1690,7 +1777,7 @@ msgstr "" "旧クラスタで稼働中のpostmasterがあるようです。\n" "そのpostmasterをシャットダウンしたのちにやり直してください。" -#: pg_upgrade.c:391 +#: pg_upgrade.c:395 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1699,141 +1786,201 @@ msgstr "" "新クラスタで稼働中のpostmasterがあるようです。\n" "そのpostmasterをシャットダウンしたのちやり直してください。" -#: pg_upgrade.c:413 +#: pg_upgrade.c:421 +#, c-format +msgid "Setting the default char signedness for new cluster" +msgstr "新クラスタの、デフォルトのchar型の符号の有無を設定しています" + +#: pg_upgrade.c:449 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "新クラスタの、ロケールとエンコーディングを設定しています" -#: pg_upgrade.c:489 +#: pg_upgrade.c:527 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "新クラスタ内のすべての行を分析しています" -#: pg_upgrade.c:502 +#: pg_upgrade.c:540 #, c-format msgid "Freezing all rows in the new cluster" msgstr "新クラスタ内のすべての行を凍結しています" -#: pg_upgrade.c:522 +#: pg_upgrade.c:560 #, c-format msgid "Restoring global objects in the new cluster" msgstr "新クラスタ内のグローバルオブジェクトを復元しています" -#: pg_upgrade.c:538 +#: pg_upgrade.c:577 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "新クラスタ内にデータベーススキーマを復元しています" -#: pg_upgrade.c:662 +#: pg_upgrade.c:712 #, c-format msgid "Deleting files from new %s" msgstr "新しい %s からファイルを削除しています" -#: pg_upgrade.c:666 +#: pg_upgrade.c:716 #, c-format msgid "could not delete directory \"%s\"" msgstr "ディレクトリ\"%s\"を削除できませんでした" -#: pg_upgrade.c:685 +#: pg_upgrade.c:735 #, c-format msgid "Copying old %s to new server" msgstr "旧の %s を新サーバーにコピーしています" -#: pg_upgrade.c:711 +#: pg_upgrade.c:761 #, c-format msgid "Setting oldest XID for new cluster" msgstr "新クラスタの、最古のXIDを設定しています" -#: pg_upgrade.c:719 +#: pg_upgrade.c:769 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "新クラスタの、次のトランザクションIDと基点を設定しています" -#: pg_upgrade.c:749 +#: pg_upgrade.c:799 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "新クラスタの、次のmultixact IDとオフセットを設定しています" -#: pg_upgrade.c:773 +#: pg_upgrade.c:823 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "新クラスタの最古のmultixact IDを設定しています" -#: pg_upgrade.c:793 +#: pg_upgrade.c:843 #, c-format msgid "Resetting WAL archives" msgstr "WAL アーカイブをリセットしています" -#: pg_upgrade.c:836 +#: pg_upgrade.c:886 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "新クラスタのfrozenxidとminmxidカウンタを設定しています" -#: pg_upgrade.c:838 +#: pg_upgrade.c:888 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "新クラスタのminmxidカウンタを設定しています" -#: pg_upgrade.c:929 +#: pg_upgrade.c:979 #, c-format msgid "Restoring logical replication slots in the new cluster" msgstr "新クラスタ内の論理レプリケーションスロットを復元しています" -#: relfilenumber.c:35 +#: relfilenumber.c:68 +#, c-format +msgid "could not synchronize file \"%s\": %m" +msgstr "ファイル\"%s\"を同期できませんでした: %m" + +#: relfilenumber.c:114 #, c-format msgid "Cloning user relation files" msgstr "ユーザーリレーションファイルをクローニングしています" -#: relfilenumber.c:38 +#: relfilenumber.c:117 #, c-format msgid "Copying user relation files" msgstr "ユーザーリレーションのファイルをコピーしています" -#: relfilenumber.c:41 +#: relfilenumber.c:120 #, c-format msgid "Copying user relation files with copy_file_range" msgstr "ユーザーリレーションのファイルをcopy_file_rangeを使ってコピーしています" -#: relfilenumber.c:44 +#: relfilenumber.c:123 #, c-format msgid "Linking user relation files" msgstr "ユーザーリレーションのファイルをリンクしています" -#: relfilenumber.c:118 +#: relfilenumber.c:126 +#, c-format +msgid "Swapping data directories" +msgstr "データディレクトリを交換しています" + +#: relfilenumber.c:200 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "新クラスタ内に旧データベース\"%s\"が見つかりません" -#: relfilenumber.c:221 +#: relfilenumber.c:287 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ファイル\"%s\"のstatに失敗しました: %m" + +#: relfilenumber.c:293 relfilenumber.c:297 +#, c-format +msgid "could not create directory \"%s\"" +msgstr "ディレクトリ\"%s\"を作成できませんでした" + +#: relfilenumber.c:301 relfilenumber.c:305 +#, c-format +msgid "could not rename \"%s\" to \"%s\"" +msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした" + +#: relfilenumber.c:375 relfilenumber.c:402 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" + +#: relfilenumber.c:393 relfilenumber.c:420 +#, c-format +msgid "could not rename \"%s\" to \"%s\": %m" +msgstr "\"%s\"の名前を\"%s\"に変更できませんでした: %m" + +#: relfilenumber.c:396 relfilenumber.c:434 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" + +#: relfilenumber.c:439 +#, c-format +msgid "could not synchronize directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"を同期できませんでした: %m" + +#: relfilenumber.c:441 +#, c-format +msgid "could not synchronize parent directory of \"%s\": %m" +msgstr "\"%s\"の親ディレクトリを同期できませんでした: %m" + +#: relfilenumber.c:598 #, c-format msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" msgstr "\"%s.%s\"ファイル (\"%s\"から\"%s\")の存在確認中のエラー: %m" -#: relfilenumber.c:238 +#: relfilenumber.c:615 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "\"%s\"を\"%s\"に書き換えています" -#: relfilenumber.c:246 +#: relfilenumber.c:623 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "\"%s\"から\"%s\"へクローンしています" -#: relfilenumber.c:251 +#: relfilenumber.c:628 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "\"%s\"を\"%s\"にコピーしています" -#: relfilenumber.c:256 +#: relfilenumber.c:633 #, c-format msgid "copying \"%s\" to \"%s\" with copy_file_range" msgstr "\"%s\"を\"%s\"にcopy_file_rangeを使ってコピーしています" -#: relfilenumber.c:261 +#: relfilenumber.c:638 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "\"%s\"から\"%s\"へリンクを作成しています" +#: relfilenumber.c:644 +#, c-format +msgid "should never happen" +msgstr "想定外のコードパス" + #: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" @@ -1865,7 +2012,7 @@ msgstr "バージョンファイル\"%s\"をオープンできませんでした msgid "could not parse version file \"%s\"" msgstr "バージョンファイル\"%s\"をパースできませんでした" -#: server.c:310 +#: server.c:317 #, c-format msgid "" "\n" @@ -1874,7 +2021,7 @@ msgstr "" "\n" "%s" -#: server.c:314 +#: server.c:321 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1883,7 +2030,7 @@ msgstr "" "以下のコマンドで起動した移行元postmasterに接続できませんでした:\n" "%s" -#: server.c:318 +#: server.c:325 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1892,22 +2039,22 @@ msgstr "" "以下のコマンドで起動した移行先postmasterに接続できませんでした:\n" "%s" -#: server.c:332 +#: server.c:339 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl が移行元サーバーの起動に失敗した、あるいは接続に失敗しました" -#: server.c:334 +#: server.c:341 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl が移行先サーバーの起動に失敗した、あるいは接続に失敗しました" -#: server.c:379 +#: server.c:386 #, c-format msgid "out of memory" msgstr "メモリ不足です" -#: server.c:392 +#: server.c:399 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "libpq の環境変数 %s で、ローカルでないサーバー値が設定されています: %s" @@ -1936,6 +2083,26 @@ msgstr "テーブル空間のディレクトリ\"%s\"をstatできませんで msgid "tablespace path \"%s\" is not a directory" msgstr "テーブル空間のパス\"%s\"がディレクトリではありません" +#: task.c:195 +#, c-format +msgid "failed to create connection with connection string: \"%s\"" +msgstr "次の接続文字列で接続できませんでした: \"%s\"" + +#: task.c:217 task.c:268 task.c:283 task.c:294 +#, c-format +msgid "connection failure: %s" +msgstr "接続失敗: %s" + +#: task.c:396 +#, c-format +msgid "invalid socket" +msgstr "不正なソケットです" + +#: task.c:405 +#, c-format +msgid "select() failed: %m" +msgstr "select() が失敗しました: %m" + #: util.c:53 util.c:56 util.c:139 util.c:170 util.c:172 #, c-format msgid "%-*s" @@ -1956,11 +2123,6 @@ msgstr "ok" msgid "Checking for hash indexes" msgstr "ハッシュインデックスをチェックしています" -#: version.c:121 -#, c-format -msgid "warning" -msgstr "警告" - #: version.c:123 #, c-format msgid "" @@ -1995,17 +2157,17 @@ msgstr "" "インデックスを再構築できます。\n" "それまでは、これらのインデックスは使用されません。" -#: version.c:153 +#: version.c:187 #, c-format msgid "Checking for extension updates" msgstr "機能拡張のアップデートを確認しています" -#: version.c:200 +#: version.c:201 #, c-format msgid "notice" msgstr "注意" -#: version.c:201 +#: version.c:202 #, c-format msgid "" "\n" diff --git a/src/bin/pg_upgrade/po/ka.po b/src/bin/pg_upgrade/po/ka.po index a9b1213aa764f..2160e67da18ef 100644 --- a/src/bin/pg_upgrade/po/ka.po +++ b/src/bin/pg_upgrade/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_upgrade (PostgreSQL) 17\n" +"Project-Id-Version: pg_upgrade (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:20+0000\n" -"PO-Revision-Date: 2024-06-14 06:15+0200\n" +"POT-Creation-Date: 2025-05-02 22:20+0000\n" +"PO-Revision-Date: 2025-05-03 01:23+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 @@ -48,12 +48,12 @@ msgstr "მომხმარებელი არ არსებობს" msgid "user name lookup failure: error code %lu" msgstr "მომხარებლის სახელის ამოხსნის პრობლემა: შეცდომის კოდი: %lu" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" @@ -226,34 +226,34 @@ msgstr "" "შეუძლებელია შეგიძლიათ წაშალოთ პრობლემური სვეტები,\n" "ან შეცვალოთ მათი ტიპი და განახლება თავიდან გაუშვათ.\n" -#: check.c:345 +#: check.c:421 #, c-format -msgid "Checking for data type usage" -msgstr "მონაცემის ტიპის გამოყენების შემოწმება" - -#: check.c:480 -#, c-format -msgid " failed check: %s" -msgstr " ჩავარდა შემოწმება: %s" +msgid "failed check: %s" +msgstr "ჩავარდა შემოწმება: %s" -#: check.c:483 +#: check.c:424 msgid "A list of the problem columns is in the file:" msgstr "პრობლემური სვეტების სია არის ფაილში:" -#: check.c:495 check.c:961 check.c:1134 check.c:1249 check.c:1343 check.c:1471 -#: check.c:1547 check.c:1611 check.c:1684 check.c:1866 check.c:1885 -#: check.c:1954 check.c:2006 file.c:378 file.c:415 function.c:189 option.c:493 -#: version.c:79 version.c:177 +#: check.c:430 check.c:1029 check.c:1180 check.c:1263 check.c:1352 check.c:1443 +#: check.c:1575 check.c:1660 check.c:1707 check.c:1787 check.c:2092 +#: check.c:2111 check.c:2157 check.c:2210 file.c:378 file.c:415 function.c:208 +#: option.c:519 version.c:79 version.c:162 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: check.c:522 +#: check.c:472 +#, c-format +msgid "Checking data type usage" +msgstr "მონაცემის ტიპის გამოყენების შემოწმება" + +#: check.c:526 #, c-format msgid "Data type checks failed: %s" msgstr "მონაცემის ტიპის შემოწმებები ჩავარდა: %s" -#: check.c:563 +#: check.c:575 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -262,7 +262,7 @@ msgstr "" "თანმიმდევრულობის შემოწმების შესრულება ძველ ცოცხალ სერვერზე\n" "------------------------------------------------" -#: check.c:569 +#: check.c:581 #, c-format msgid "" "Performing Consistency Checks\n" @@ -271,7 +271,12 @@ msgstr "" "თანმიმდევრულობის შემოწმების ჩატარება\n" "-----------------------------" -#: check.c:716 +#: check.c:745 +#, c-format +msgid "Swap mode can only upgrade clusters from PostgreSQL version %s and later." +msgstr "რეჟიმის 'swap' გამოყენება კლასტერის ვერსიის ასაწევად შესაძლებელია PostgreSQL-ის ვერსიაში %s და შემდეგ." + +#: check.c:768 #, c-format msgid "" "\n" @@ -280,7 +285,7 @@ msgstr "" "\n" "*კლასტერები თავსებადია *" -#: check.c:724 +#: check.c:776 #, c-format msgid "" "\n" @@ -291,18 +296,20 @@ msgstr "" "თუ ამ წერტილის შემდეგ pg_upgrade ავარიულად დასრულდება, გაგრძელებამდე\n" "ახალი კლასტერის init-db-ის გაკეთება შეიძლება თავიდან მოგიწიოთ." -#: check.c:765 +#: check.c:817 #, c-format msgid "" -"Optimizer statistics are not transferred by pg_upgrade.\n" -"Once you start the new server, consider running:\n" -" %s/vacuumdb %s--all --analyze-in-stages" +"Some statistics are not transferred by pg_upgrade.\n" +"Once you start the new server, consider running these two commands:\n" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n" +" %s/vacuumdb %s--all --analyze-only" msgstr "" -"ოპტიმიზატორის სტატისტიკ-ის გადატანა pg_upgrade-ის მიერ არ ხდება.\n" -"როცა ახალ სერვერს გაუშვებთ, შეასრულეთ ბრძანება:\n" -" %s/vacuumdb %s--all --analyze-in-stages" +"ზოგიერთი სტატისტიკის გადატანა pg_upgrade-ის მიერ, შეიძლება, არ მოხდეს.\n" +"როცა ახალ სერვერს გაუშვებთ, შეასრულეთ ეს ორი ბრძანება:\n" +" %s/vacuumdb %s--all --analyze-in-stages --missing-stats-only\n" +" %s/vacuumdb %s--all --analyze-only" -#: check.c:771 +#: check.c:826 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -311,7 +318,7 @@ msgstr "" "ამ სკრიპტის გაშვება ძველი კლასტერის მონაცემების ფაილებს წაშლის:\n" " %s" -#: check.c:776 +#: check.c:831 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -324,57 +331,62 @@ msgstr "" "ძველი კლასტერის მონაცემების წაშლის სკრიპტის შექმნა შეუძლებელია. ძველი კლასტერის\n" " შემცველობა ხელით უნდა წაშალოთ." -#: check.c:788 +#: check.c:843 #, c-format msgid "Checking cluster versions" msgstr "კლასტერის ვერსიების შემოწმება" -#: check.c:800 +#: check.c:855 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "ამ პროგრამას განახლება PostgreSQL-ის ვერსიის %s-დან და ზემოთ შეუძლია." -#: check.c:805 +#: check.c:860 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "ამ პროგრამას შეუძლია მხოლოდ PostgreSQL ვერსიაზე გადასვლა %s." -#: check.c:814 +#: check.c:869 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "ეს პროგრამა არ შეიძლება გამოყენებულ იქნას უფრო ძველი ძირითადი PostgreSQL ვერსიების ჩამოსაწევად." -#: check.c:819 +#: check.c:874 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "ძველი კლასტერის მონაცემები და გამშვები ფაილის საქაღალდეები სხვადასხვა ძირითადი ვერსიიდანაა." -#: check.c:822 +#: check.c:877 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "ახალი კლასტერის მონაცემებისა და გამშვები ფაილების საქაღალდეები სხვადასხვა ძირითად ვერსიებს მიეკუთვნება." -#: check.c:837 +#: check.c:888 +#, c-format +msgid "%s option cannot be used to upgrade from PostgreSQL %s and later." +msgstr "პარამეტრს %s ვერ გამოიყენებთ PostgreSQL %s-დან და უფრო ახლიდან განახლებისას." + +#: check.c:904 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "ცოცხალი სერვერის შემოწმებისას ძველი და ახალი პორტის ნომრები სხვადასხვა უნდა იყოს." -#: check.c:857 +#: check.c:924 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "ახალი კლასტერული მონაცემთა ბაზა \"%s\" ცარიელი არაა: ნაპოვნია ურთიერთობა \"%s.%s\"" -#: check.c:880 +#: check.c:947 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "ახალი კლასტერის ცხრილების სივრცის საქაღალდეების შემოწმება" -#: check.c:891 +#: check.c:958 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "ახალი კლასტერის ცხრილების სივრცის საქაღალდე უკვე არსებობს: \"%s\"" -#: check.c:924 +#: check.c:992 #, c-format msgid "" "\n" @@ -383,7 +395,7 @@ msgstr "" "\n" "გაფრთხილება: ახალი მონაცემების საქაღალდე ძველი მონაცემების საქაღალდის შიგნით არ უნდა იყოს. მაგ: %s" -#: check.c:948 +#: check.c:1016 #, c-format msgid "" "\n" @@ -392,92 +404,92 @@ msgstr "" "\n" "გაფრთხილება: მომხმარებლის მიერ აღწერილი ცხრილის სივრცეების მდებარეობები მონაცემების საქაღალდის შიგნით არ უნდა იყოს. მაგ: %s" -#: check.c:958 +#: check.c:1026 #, c-format msgid "Creating script to delete old cluster" msgstr "ძველი კლასტერის წასაშლელად სკრიპტის შექმნა" -#: check.c:1012 +#: check.c:1054 #, c-format msgid "could not add execute permission to file \"%s\": %m" msgstr "ფაილზე \"%s\" გაშვების წვდომის დამატების შეცდომა: %m" -#: check.c:1032 +#: check.c:1074 #, c-format msgid "Checking database user is the install user" msgstr "შემოწმება, დამყენებელი მომხმარებელი დაყენების მომხმარებელს თუ უდრის" -#: check.c:1048 +#: check.c:1090 #, c-format msgid "database user \"%s\" is not the install user" msgstr "მონაცემთა ბაზის მომხმარებელი \"%s\" არ არის დაყენების მომხმარებელი" -#: check.c:1059 +#: check.c:1101 #, c-format msgid "could not determine the number of users" msgstr "ვერ დადგინდა მომხმარებელთა რაოდენობა" -#: check.c:1067 +#: check.c:1109 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "ახალი კლასტერისთვის მხოლოდ დაყენების მომხმარებლის მითითებაა შესაძლებელი." -#: check.c:1096 +#: check.c:1139 #, c-format msgid "Checking database connection settings" msgstr "მონაცემთა ბაზის კავშირის პარამეტრების შემოწმება" -#: check.c:1122 +#: check.c:1167 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0-თან დაკავშირება შეუძლებელი უნდა იყოს. ანუ, მისი pg_database.datallowconn პარამეტრი false უნდა იყოს" -#: check.c:1148 check.c:1268 check.c:1365 check.c:1490 check.c:1566 -#: check.c:1624 check.c:1704 check.c:1898 check.c:2023 function.c:210 +#: check.c:1194 check.c:1315 check.c:1411 check.c:1539 check.c:1615 +#: check.c:1673 check.c:1756 check.c:2124 check.c:2266 function.c:229 #, c-format msgid "fatal" msgstr "ფატალური" -#: check.c:1149 +#: check.c:1195 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" -"pg_database.datallowconn must be true. Your installation contains\n" -"non-template0 databases with their pg_database.datallowconn set to\n" -"false. Consider allowing connection for all non-template0 databases\n" -"or drop the databases which do not allow connections. A list of\n" -"databases with the problem is in the file:\n" +"pg_database.datallowconn must be true and pg_database.datconnlimit\n" +"must not be -2. Your installation contains non-template0 databases\n" +"which cannot be connected to. Consider allowing connection for all\n" +"non-template0 databases or drop the databases which do not allow\n" +"connections. A list of databases with the problem is in the file:\n" " %s" msgstr "" -"ყველა არა-template0 ბაზაზე მიერთება შესაძლებელი უნდა იყოს, ანუ მათი\n" -"pg_database.datallowconn -ი true-ს უნდა უნდოდეს. თქვენი ვერსია შეიცავს\n" -"არა-template0 ბაზებს, რომლების pg_database.datallowconn -ი false-ზეა დაყენებული.\n" -"სასურველია დაუშვათ მიერთება ყველა არა-template0 ბაზაზე, ან\n" -"წაშალოთ ბაზები, რომლებზეც წვდომა არ არსებობს.\n" -"პრობლემური ბაზების სიის ნახვა შეგიძლიათ ფაილში:\n" -" %s" +"ყველა არა-template0 მონაცემთა ბაზა უნდა უშვებდეს მიერთებას, ანუ მათი\n" +"pg_database.datallowconn ჭეშმარიტი უნდა იყოს და pg_database.datconnlimit არ\n" +"უნდა იყოს -2. ბაზის თქვენი ვარიანტი შეიცავს არა-template0 მონაცემთა ბაზებს,\n" +"რომლებთანაც მიერთება შეუძლებელია. იფიქრეთ, რომ დაუშვათ მიერთება ყველა\n" +"არა-template0 მონაცემთა ბაზებთან, ან წაშალეთ ბაზები, რომლებიც არ უშვებენ კავშირს.\n" +"ამ პრობლემის მქონე მონაცემთა ბაზების შენახულია ფაილში:\n" +" %s" -#: check.c:1174 +#: check.c:1220 #, c-format msgid "Checking for prepared transactions" msgstr "მომზადებული ტრანზაქციების შემოწმება" -#: check.c:1183 +#: check.c:1229 #, c-format msgid "The source cluster contains prepared transactions" msgstr "საწყისი კლასტერი მომზადებულ ტრანზაქციებს შეიცავს" -#: check.c:1185 +#: check.c:1231 #, c-format msgid "The target cluster contains prepared transactions" msgstr "სამიზნე კლასტერი მომზადებულ ტრანზაქციებს შეიცავს" -#: check.c:1210 +#: check.c:1291 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "\"contrib/isn\"-ის bgint-passing-ის არ-დამთხვევაზე შემოწმება" -#: check.c:1269 +#: check.c:1316 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -494,12 +506,12 @@ msgstr "" ", განაახლოთ ბაზა და აღადგინოთ ფუნქციები. პრობლემური ფუნქციების სია შეგიძლიათ იხილოთ ფაილში:\n" " %s" -#: check.c:1291 +#: check.c:1396 #, c-format msgid "Checking for user-defined postfix operators" msgstr "მომხმარებლის მიერ აღწერილი postfix ოპერატორების არსებობის შემოწმება" -#: check.c:1366 +#: check.c:1412 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -514,12 +526,12 @@ msgstr "" "მომხმარებლის მიერ აღწერილი postfix ოპერატორების სიის ნახვა შეგიძლიათ ფაილში:\n" " %s" -#: check.c:1390 +#: check.c:1467 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "შეუთავსებელი პოლიმორფული ფუნქციების არსებობის შემოწმება" -#: check.c:1491 +#: check.c:1540 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -538,12 +550,12 @@ msgstr "" "ფაილში არსებული პრობლემური ობიექტები:\n" " %s" -#: check.c:1515 +#: check.c:1600 #, c-format msgid "Checking for tables WITH OIDS" msgstr "WITH OIDS ცხრილების შემოწმება" -#: check.c:1567 +#: check.c:1616 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -558,12 +570,12 @@ msgstr "" "ცხრილების სია, რომელსაც ეს პრობლემა გააჩნიათ, შეგიძლიათ იხილოთ ფაილში:\n" " %s" -#: check.c:1594 +#: check.c:1643 #, c-format msgid "Checking for roles starting with \"pg_\"" msgstr "როლების შემოწმება, რომლებიც \"pg_\"-ით იწყება" -#: check.c:1625 +#: check.c:1674 #, c-format msgid "" "Your installation contains roles starting with \"pg_\".\n" @@ -578,12 +590,12 @@ msgstr "" "როლების სია, რომლებიც \"pg_\"-ით იწყებიან, შეგიძლიათ იპოვოთ ფაილში:\n" " %s" -#: check.c:1645 +#: check.c:1728 #, c-format msgid "Checking for user-defined encoding conversions" msgstr "მომხმარებლის მიერ განსაზღვრული კოდირების კონვერტაციის შემოწმება" -#: check.c:1705 +#: check.c:1757 #, c-format msgid "" "Your installation contains user-defined encoding conversions.\n" @@ -599,55 +611,76 @@ msgstr "" "მომხმარებლის მიერ აღწერილი გადაყვანების ნახვა შეგიძლიათ ფაილში:\n" " %s" -#: check.c:1744 +#: check.c:1842 +#, c-format +msgid "Checking for objects affected by Unicode update" +msgstr "უნიკოდის განახლების გავლენის ქვეშ მოქცეული ობიექტების შემოწმება" + +#: check.c:1936 version.c:121 +#, c-format +msgid "warning" +msgstr "გაფრთხილება" + +#: check.c:1937 +#, c-format +msgid "" +"Your installation contains relations that may be affected by a new version of Unicode.\n" +"A list of potentially-affected relations is in the file:\n" +" %s" +msgstr "" +"პროგრამის თქვენი ვერსია შეიცავს ურთიერთობას, რომელზეც, შეიძლება, უნიკოდის ახალ ვერსიას ჰქონდეს გავლენა.\n" +"პოტენციურად გავლენის ქვეშ მოქცეული ურთიერთობები შენახულია ფაილში:\n" +" %s" + +#: check.c:1973 #, c-format msgid "Checking for new cluster logical replication slots" msgstr "ახალი კლასტერის ლოგიკური რეპლიკაციის სლოტების შემოწმება" -#: check.c:1752 +#: check.c:1981 #, c-format msgid "could not count the number of logical replication slots" msgstr "ლოგიკური რეპლიკაციის სლოტების რაოდენობის დათვლა შეუძლებელია" -#: check.c:1757 +#: check.c:1986 #, c-format -msgid "Expected 0 logical replication slots but found %d." -msgstr "მოველოდი 0 ლოგიკური რეპლიკაციის სლოტს. მივიღე %d." +msgid "expected 0 logical replication slots but found %d" +msgstr "მოველოდი 0 ლოგიკური რეპლიკაციის სლოტს, მაგრამ, მივიღე %d" -#: check.c:1767 check.c:1821 +#: check.c:1996 check.c:2047 #, c-format msgid "could not determine parameter settings on new cluster" msgstr "ახალ კლასტერზე პარამეტრის მნიშვნელობების დადგენა შეუძლებელია" -#: check.c:1772 +#: check.c:2001 #, c-format -msgid "\"wal_level\" must be \"logical\", but is set to \"%s\"" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" msgstr "\"wal_level\" უნდა იყოს \"logical\", მაგრამ მნიშვნელობაა \"%s\"" -#: check.c:1778 +#: check.c:2007 #, c-format msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" msgstr "\"max_replication_slots\" (%d) ძველი კლასტერის ლოგიკური რეპლიკაციების სლოტების რაოდენობაზე (%d) მეტი ან ტოლი უნდა იყოს" -#: check.c:1813 +#: check.c:2039 #, c-format msgid "Checking for new cluster configuration for subscriptions" msgstr "ახალი კლასტერის კონფიგურაციის გამოწერებზე შემოწმება" -#: check.c:1825 +#: check.c:2051 #, c-format -msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" -msgstr "\"max_replication_slots\" (%d) ძველი კლასტერის გამოწერების რაოდენობაზე (%d) მეტი ან ტოლი უნდა იყოს" +msgid "\"max_active_replication_origins\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "\"max_active_replication_origins\" (%d) ძველი კლასტერის გამოწერების რაოდენობაზე (%d) მეტი ან ტოლი უნდა იყოს" -#: check.c:1847 +#: check.c:2073 #, c-format msgid "Checking for valid logical replication slots" msgstr "სწორ ლოგიკური რეპლიკაციის სლოტებზე შემოწმება" -#: check.c:1899 +#: check.c:2125 #, c-format msgid "" -"Your installation contains logical replication slots that can't be upgraded.\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" "You can remove invalid slots and/or consume the pending WAL for other slots,\n" "and then restart the upgrade.\n" "A list of the problematic slots is in the file:\n" @@ -659,12 +692,12 @@ msgstr "" "პრობლემური სლოტების ნახვა შეგიძლიათ ფაილში:\n" " %s" -#: check.c:1923 +#: check.c:2185 #, c-format msgid "Checking for subscription state" msgstr "გამოწერის მდგომარეობის შემოწმება" -#: check.c:2024 +#: check.c:2267 #, c-format msgid "" "Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" @@ -677,184 +710,189 @@ msgstr "" "პრობლემური სვეტების ნახვა შეგიძლიათ ფაილში:\n" " %s" -#: controldata.c:129 controldata.c:199 +#: controldata.c:133 controldata.c:203 #, c-format msgid "could not get control data using %s: %m" msgstr "%s-ის გამოყენებით საკონტროლო მონაცემების მიღება შეუძლებელია: %m" -#: controldata.c:139 +#: controldata.c:143 #, c-format msgid "%d: database cluster state problem" msgstr "%d: ბაზის კლასტერის მდგომარეობის პრობლემა" -#: controldata.c:158 +#: controldata.c:162 #, c-format msgid "The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "საწყისი კლასტერი აღდგენის რეჟიმში იყო, როცა გაითიშა. განსაახლებლად გამოიყენეთ \"rsync\", როგორც ეს დოკუმენტაციაშია, ან გამორთეთ, როგორც ძირითადი." -#: controldata.c:160 +#: controldata.c:164 #, c-format msgid "The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." msgstr "სამიზნე კლასტერი აღდგენის რეჟიმში იყო, როცა გაითიშა. განსაახლებლად, გამოიყენეთ \"rsync\", როგორც ეს დოკუმენტაციაშია, ან გამორთეთ, როგორც ძირითადი." -#: controldata.c:165 +#: controldata.c:169 #, c-format msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "წყარო კლასტერი წესების დაცვით არ გამორთულა. მიღებული მდგომარეობაა: \"%s\"" -#: controldata.c:167 +#: controldata.c:171 #, c-format msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" msgstr "სამიზნე კლასტერი წესების დაცვით არ გამორთულა. მიღებული მდგომარეობაა: \"%s\"" -#: controldata.c:175 controldata.c:507 +#: controldata.c:179 controldata.c:530 #, c-format msgid "could not get control data using %s: %s" msgstr "%s-სთვის საკონტროლო მონაცემების მიღების შეცდომა: %s" -#: controldata.c:181 +#: controldata.c:185 #, c-format msgid "The source cluster lacks cluster state information:" msgstr "საწყის კლასტერს მდგომარეობის ინფორმაცია არ გააჩნია:" -#: controldata.c:183 +#: controldata.c:187 #, c-format msgid "The target cluster lacks cluster state information:" msgstr "სამიზნე კლასტერს მდგომარეობის ინფორმაცია არ გააჩნია:" -#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 -#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 +#: controldata.c:217 dump.c:50 exec.c:118 pg_upgrade.c:606 pg_upgrade.c:646 +#: pg_upgrade.c:995 relfilenumber.c:610 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:220 +#: controldata.c:224 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d: pg_resetwal -ის პრობლემა" -#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 -#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 -#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 -#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 -#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 -#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 -#: controldata.c:486 controldata.c:497 +#: controldata.c:234 controldata.c:244 controldata.c:255 controldata.c:266 +#: controldata.c:277 controldata.c:296 controldata.c:307 controldata.c:318 +#: controldata.c:329 controldata.c:340 controldata.c:351 controldata.c:362 +#: controldata.c:365 controldata.c:369 controldata.c:379 controldata.c:391 +#: controldata.c:402 controldata.c:413 controldata.c:424 controldata.c:435 +#: controldata.c:446 controldata.c:457 controldata.c:468 controldata.c:479 +#: controldata.c:490 controldata.c:501 controldata.c:512 controldata.c:521 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d: controldata -ის მიღების შეცდომა" -#: controldata.c:578 +#: controldata.c:618 #, c-format msgid "The source cluster lacks some required control information:" msgstr "საწყის კლასტერს ზოგიერთი საჭირო კონტროლის ინფორმაცია არ გააჩნია:" -#: controldata.c:581 +#: controldata.c:621 #, c-format msgid "The target cluster lacks some required control information:" msgstr "სამიზნე კლასტერს ზოგიერთი საჭირო კონტროლის ინფორმაცია არ გააჩნია:" -#: controldata.c:584 +#: controldata.c:624 #, c-format msgid " checkpoint next XID" msgstr " საკონტროლო წერტილის შემდეგი XID" -#: controldata.c:587 +#: controldata.c:627 #, c-format msgid " latest checkpoint next OID" msgstr " უახლესი საკონტროლო წერტილის შემდეგი OID" -#: controldata.c:590 +#: controldata.c:630 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " უახლესი საკონტროლო წერტილის შემდეგი MultiXactId" -#: controldata.c:594 +#: controldata.c:634 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " უახლესი საკონტროლო წერტილის უძველესი MultiXactId" -#: controldata.c:597 +#: controldata.c:637 #, c-format msgid " latest checkpoint oldestXID" msgstr " უახლესი საკონტროლო წერტილის უძველესი XID" -#: controldata.c:600 +#: controldata.c:640 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " უახლესი საკონტროლო წერტილის შემდეგი MultiXactOffset" -#: controldata.c:603 +#: controldata.c:643 #, c-format msgid " first WAL segment after reset" msgstr " პირველი WAL სეგმენტი გადატვირთვის შემდეგ" -#: controldata.c:606 +#: controldata.c:646 #, c-format msgid " float8 argument passing method" msgstr " float8 არგუმენტი გავლის მეთოდი" -#: controldata.c:609 +#: controldata.c:649 #, c-format msgid " maximum alignment" msgstr " მაქსიმალური სწორება" -#: controldata.c:612 +#: controldata.c:652 #, c-format msgid " block size" msgstr " ბლოკის ზომა" -#: controldata.c:615 +#: controldata.c:655 #, c-format msgid " large relation segment size" msgstr " დიდი ურთიერთობის სეგმენტის ზომა" -#: controldata.c:618 +#: controldata.c:658 #, c-format msgid " WAL block size" msgstr " WAL ბლოკის ზომა" -#: controldata.c:621 +#: controldata.c:661 #, c-format msgid " WAL segment size" msgstr " WAL-ის სეგმენტის ზომა" -#: controldata.c:624 +#: controldata.c:664 #, c-format msgid " maximum identifier length" msgstr " იდენტიფიკატორის მაქსიმალური სიგრძე" -#: controldata.c:627 +#: controldata.c:667 #, c-format msgid " maximum number of indexed columns" msgstr " ინდექსირებული სვეტების მაქსიმალური რაოდენობა" -#: controldata.c:630 +#: controldata.c:670 #, c-format msgid " maximum TOAST chunk size" msgstr " TOAST ნაგლეჯის მაქსიმალური ზომა" -#: controldata.c:634 +#: controldata.c:674 #, c-format msgid " large-object chunk size" msgstr " დიდი ობიექტის ნაგლეჯის ზომა" -#: controldata.c:637 +#: controldata.c:677 #, c-format msgid " dates/times are integers?" msgstr " დროები და თარიღები მთელი რიცხვებია?" -#: controldata.c:641 +#: controldata.c:681 #, c-format msgid " data checksum version" msgstr " მონაცემების საკონტროლო ჯამის ვერსია" -#: controldata.c:643 +#: controldata.c:685 +#, c-format +msgid " default char signedness" +msgstr " ნაგულისხმევი სიმბოლოს ნიშნიანობა" + +#: controldata.c:687 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "ვერ გაგრძელდება საჭირო კონტროლის ინფორმაციის გარეშე, დასრულება" -#: controldata.c:658 +#: controldata.c:702 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -863,91 +901,109 @@ msgstr "" "ძველი და ახალი pg_controldata სწორებები ბათილია ან არ ემთხვევა\n" "სავარაუდოდ, ერთი კლასტერი 32-ბიტიანია, დანარჩენი კი 64" -#: controldata.c:662 +#: controldata.c:706 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata ბლოკის ზომები ბათილია ან არ ემთხვევა" -#: controldata.c:665 +#: controldata.c:709 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata მაქსიმალური ურთიერთობის სეგმენტის ზომები ბათილია ან არ ემთხვევა" -#: controldata.c:668 +#: controldata.c:712 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის WAL-ის ბლოკის ზომები არასწორია ან არ ემთხვევა" -#: controldata.c:671 +#: controldata.c:715 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის WAL-ის სეგმენტის ზომები არასწორია ან არ ემთხვევა" -#: controldata.c:674 +#: controldata.c:718 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის იდენტიფიკატორის მაქსიმალური სიგრძეები არასწორია ან არ ემთხვევა" -#: controldata.c:677 +#: controldata.c:721 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის მაქსიმალური ინდექსირებული სვეტები არასწორია ან არ ემთხვევა" -#: controldata.c:680 +#: controldata.c:724 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის TOAST-ის მაქსიმალური ნაგლეჯის ზომები არასწორია ან არ ემთხვევა" -#: controldata.c:685 +#: controldata.c:729 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "ძველი და ახალი pg_controldata-ის დიდი ობიექტის ნაგლეჯის ზომები არასწორია ან არ ემთხვევა" -#: controldata.c:688 +#: controldata.c:732 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "ძველი და ახალი pg_controldata-ის თარიღი/დროის შენახვის ტიპები არ ემთხვევა" -#: controldata.c:701 +#: controldata.c:745 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "ძველი კლასტერი არ იყენებს მონაცემთა შემოწმებას, მაგრამ ახალი აკეთებს" -#: controldata.c:704 +#: controldata.c:748 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "ძველი კლასტერი იყენებს მონაცემთა შემოწმებას, ახალი კი არა" -#: controldata.c:706 +#: controldata.c:750 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "ძველი და ახალი კლასტერების pg_controldata -ის საკონტროლო ჯამის ვერსიები არ ემთხვევა" -#: controldata.c:717 +#. translator: %s is the file path of the control file +#: controldata.c:762 #, c-format -msgid "Adding \".old\" suffix to old global/pg_control" -msgstr "ძველ გლობალურ/pg_control-ზე \".old\" სუფიქსის დამატება" +msgid "Adding \".old\" suffix to old \"%s\"" +msgstr "'.old\" სუფიქსის დამატება ძველ \"%s\"-ზე" -#: controldata.c:722 +#: controldata.c:767 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" -#: controldata.c:726 +#. translator: %s/%s is the file path of the control file +#: controldata.c:773 #, c-format msgid "" "\n" "If you want to start the old cluster, you will need to remove\n" -"the \".old\" suffix from %s/global/pg_control.old.\n" +"the \".old\" suffix from \"%s/%s.old\".\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" "started once the new cluster has been started." msgstr "" "\n" "თუ გნებავთ, გაუშვათ ძველი კლასტერი, საჭიროა\n" -"წაშალოთ .old სუფიქსი %s/global/pg_control.old-დან.\n" +"წაშალოთ .old სუფიქსი %s/%s.old-დან.\n" "იმის გამო, რომ გამოყენებული იყო \"ბმულის\" რეჟიმი, ძველი კლასტერის გაშვება მას შემდეგ, რაც\n" "ახალი სერვერი გაეშვა, ძველის გაშვება უსაფრთხო აღარაა." +#: controldata.c:780 +#, c-format +msgid "" +"\n" +"Because \"swap\" mode was used, the old cluster can no longer be\n" +"safely started." +msgstr "" +"\n" +"იმიტოს გამო, რომ გამოყენებული იყო რეჟიმი 'swap', ძველი კლასტერის გაშვება\n" +"უსაფრთხო აღარაა." + +#: controldata.c:784 file.c:455 +#, c-format +msgid "unrecognized transfer mode" +msgstr "უცნობი გადაცემის რეჟიმი" + #: dump.c:20 #, c-format msgid "Creating dump of global objects" @@ -978,7 +1034,7 @@ msgstr "%s გამოყენებით pg_ctl ვერსია ვერ msgid "command too long" msgstr "ბრძანება ძალიან გრძელია" -#: exec.c:160 pg_upgrade.c:311 +#: exec.c:160 pg_upgrade.c:315 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ჟურნალის ფაილის გახსნის შეცდომა \"%s\": %m" @@ -1015,7 +1071,7 @@ msgstr "" "ავარიის მიზეზის გამოსავლენად გადაავლეთ თვალი\n" "\"%s\"-ის ბოლო რამდენიმე ხაზს." -#: exec.c:218 pg_upgrade.c:321 +#: exec.c:218 pg_upgrade.c:325 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "ჟურნალის ფაილში (%s) ჩაწერის შეცდომა: %m" @@ -1140,7 +1196,7 @@ msgstr "მონაცემების ძველ და ახალ ს msgid "copy_file_range not supported on this platform" msgstr "ამ პლატფორმაზე copy_file_range მხარდაჭერილი არაა" -#: file.c:447 +#: file.c:449 #, c-format msgid "" "could not create hard link between old and new data directories: %m\n" @@ -1149,22 +1205,31 @@ msgstr "" "ძველი და ახალი მონაცემების საქაღალდეებს შუა მყარი ბმულის შექმნა შეუძლებელია: %m\n" "ბმულის რეჟიმში ძველი და ახალი მონაცემების საქაღალდეები ერთი და იგივე ფაილურ სისტემაზე უნდა იყოს." -#: function.c:154 +#: file.c:452 +#, c-format +msgid "" +"could not create hard link between old and new data directories: %m\n" +"In swap mode the old and new data directories must be on the same file system." +msgstr "" +"ძველი და ახალი მონაცემების საქაღალდეებს შუა მყარი ბმულის შექმნა შეუძლებელია: %m\n" +"რეჟიმში 'swap' ძველი და ახალი მონაცემების საქაღალდეები ერთი და იგივე ფაილურ სისტემაზე უნდა იყოს." + +#: function.c:173 #, c-format msgid "Checking for presence of required libraries" msgstr "საჭირო ბიბლიოთეკების არსებობის შემოწმება" -#: function.c:190 +#: function.c:209 #, c-format msgid "could not load library \"%s\": %s" msgstr "ბიბლიოთეკის (\"%s\") ჩატვირთვის შეცდომა: %s" -#: function.c:201 +#: function.c:220 #, c-format msgid "In database: %s\n" msgstr "მონაცემთა ბაზაში: %s\n" -#: function.c:211 +#: function.c:230 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -1179,47 +1244,47 @@ msgstr "" "პრობლემური ბიბლიოთეკების სიის ნახვა შეგიძლიათ ფაილში:\n" " %s" -#: info.c:129 +#: info.c:131 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "ურთიერთობის სახელები OID-ით %u ბაზაში \"%s\" არ ემთხვევა: ძველი სახელი \"%s.%s.\", ახალი კი \"%s.%s\"" -#: info.c:149 +#: info.c:151 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "შეცდომა ძველ და ახალ ცხრილებს შორის დამთხვევისას ბაზაში \"%s\"" -#: info.c:230 +#: info.c:232 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " რომელიც ინდექსია \"%s.%s\"" -#: info.c:240 +#: info.c:242 #, c-format msgid " which is an index on OID %u" msgstr " რაც არის ინდექსი OID-ზე %u" -#: info.c:252 +#: info.c:254 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " რომელიც TOAST ცხრილია \"%s.%s\"-სთვის" -#: info.c:260 +#: info.c:262 #, c-format msgid " which is the TOAST table for OID %u" msgstr " რომელიც TOAST ცხრილია %u-ე OID-სთვის" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "ძველ კლასტერში ახალი ურთიერთობისთვის OID -ით %u ბაზაში \"%s\" დამთხვევა ვერ ვიპოვე: %s" -#: info.c:267 +#: info.c:269 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "ახალ კლასტერში ძველი ურთიერთობისთვის OID -ით %u ბაზაში \"%s\" დამთხვევა ვერ ვიპოვე: %s" -#: info.c:308 +#: info.c:325 #, c-format msgid "" "\n" @@ -1228,7 +1293,7 @@ msgstr "" "\n" "საწყისი ბაზები:" -#: info.c:310 +#: info.c:327 #, c-format msgid "" "\n" @@ -1237,92 +1302,97 @@ msgstr "" "\n" "სამიზნე ბაზები:" -#: info.c:354 +#: info.c:371 #, c-format msgid "template0 not found" msgstr "template0 ნაპოვნი არაა" -#: info.c:842 +#: info.c:817 #, c-format msgid "Database: \"%s\"" msgstr "მონაცემთა ბაზაში: \"%s\"" -#: info.c:855 +#: info.c:830 #, c-format msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" msgstr "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" -#: info.c:869 +#: info.c:844 #, c-format -msgid "Logical replication slots within the database:" -msgstr "ლოგიკური რეპლიკაციის სლოტები მონაცემთა ბაზის შიგნით:" +msgid "Logical replication slots in the database:" +msgstr "ლოგიკური რეპლიკაციის სლოტები მონაცემთა ბაზაში:" -#: info.c:875 +#: info.c:850 #, c-format -msgid "slot_name: \"%s\", plugin: \"%s\", two_phase: %s" -msgstr "slot_name: \"%s\", plugin: \"%s\", two_phase: %s" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "სლოტი სახელი: \"%s\", გამოტანის დამატება: \"%s\", two_phase: %s" -#: option.c:105 +#: option.c:110 #, c-format msgid "%s: cannot be run as root" msgstr "%s: root-ით ვერ გაუშვებთ" -#: option.c:172 +#: option.c:177 #, c-format msgid "invalid old port number" msgstr "არასწორი ძველი პორტის ნომერი" -#: option.c:177 +#: option.c:182 #, c-format msgid "invalid new port number" msgstr "ახალი პორტის არასწორი ნომერი" -#: option.c:216 +#: option.c:230 +#, c-format +msgid "invalid argument for option %s" +msgstr "არასწორი არგუმენტი პარამეტრისთვის: %s" + +#: option.c:238 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'.\n" -#: option.c:223 +#: option.c:245 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: option.c:229 +#: option.c:251 #, c-format msgid "Running in verbose mode" msgstr "დამატებითი შეტყობინებების ჩართვა" -#: option.c:247 +#: option.c:269 msgid "old cluster binaries reside" msgstr "ძველი კლასტერის გამშვები ფაილები მდებარეობს" -#: option.c:249 +#: option.c:271 msgid "new cluster binaries reside" msgstr "ახალი კლასტერის გამშვები ფაილები მდებარეობს" -#: option.c:251 +#: option.c:273 msgid "old cluster data resides" msgstr "ძველი კლასტერის მონაცემები მდებარეობს" -#: option.c:253 +#: option.c:275 msgid "new cluster data resides" msgstr "ახალი კლასტერის მონაცემები მდებარეობს" -#: option.c:255 +#: option.c:277 msgid "sockets will be created" msgstr "სოკეტები შეიქმნება" -#: option.c:272 option.c:374 +#: option.c:294 option.c:400 #, c-format msgid "could not determine current directory" msgstr "მიმდინარე საქაღალდის იდენტიფიკაციის პრობლემა" -#: option.c:275 +#: option.c:297 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "pg_upgrade-ის გაშვება Windows-ზე ახალი კლასტერის მონაცემების საქაღალდიდან შეუძლებელია" -#: option.c:284 +#: option.c:306 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1331,12 +1401,12 @@ msgstr "" "pg_upgrade -ი PostgreSQL კლასტერს სხვა მთავარ ვერსიაზე განაახლებს.\n" "\n" -#: option.c:285 +#: option.c:307 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: option.c:286 +#: option.c:308 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1345,17 +1415,17 @@ msgstr "" " pg_upgrade [პარამეტრი]...\n" "\n" -#: option.c:287 +#: option.c:309 #, c-format msgid "Options:\n" msgstr "პარამეტრები:\n" -#: option.c:288 +#: option.c:310 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINDIR ძველი კლასტერის გამშვები ფაილების საქაღალდე\n" -#: option.c:289 +#: option.c:311 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1364,107 +1434,126 @@ msgstr "" " -B, --new-bindir=BINDIR ახალი კლასტერის გამშვები ფაილების საქაღალდე (ნაგულისხმები\n" " იგივე საქაღლდე, რაც pg_upgrade)\n" -#: option.c:291 +#: option.c:313 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check კლასტერების მხოლოდ შემოწმება. მონაცემები არ შეიცვლება\n" -#: option.c:292 +#: option.c:314 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATADIR ძველი კლასტერის მონაცემთა საქაღალდე\n" -#: option.c:293 +#: option.c:315 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATADIR ახალი კლასტერის მონაცემთა საქაღალდე\n" -#: option.c:294 +#: option.c:316 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs=NUM ერთდროულად გასაშვები პროცესების ან ნაკადების რიცხვი\n" -#: option.c:295 +#: option.c:317 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr " -k, --link ახალ კლასტერში ფაილების გადაბმა, კოპირების ნაცვლად\n" -#: option.c:296 +#: option.c:318 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync არ დაველოდო ცვლილებების დისკზე უსაფრთხოდ ჩაწერას\n" -#: option.c:297 +#: option.c:319 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, -old-options=OPTIONS სერვერზე გადასაცემი ძველი კლასტერის პარამეტრები\n" -#: option.c:298 +#: option.c:320 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, -new-options=OPTIONS სერვერზე გადასაცემი ახალი კლასტერის პარამეტრები\n" -#: option.c:299 +#: option.c:321 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, -old-port=PORT ძველი კლასტერის პორტის ნომერი (ნაგულისხმები %d)\n" -#: option.c:300 +#: option.c:322 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT ახალი კლასტერის პორტის ნომერი (ნაგულისხმები %d)\n" -#: option.c:301 +#: option.c:323 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain SQL და ჟურნალის ფაილებს დატოვება წარმატების შემდეგ \n" -#: option.c:302 +#: option.c:324 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr " -s, --socketdir=DIR სოკეტის საქაღალდე (ნაგულისხმებია მიმდინარე.)\n" -#: option.c:303 +#: option.c:325 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=მომხმარებელი კლასტერის ზემომხმარებლის სახელი (ნაგულისხმები: \"%s\")\n" -#: option.c:304 +#: option.c:326 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose შიდა დამატებითი ჟურნალის ჩართვა\n" -#: option.c:305 +#: option.c:327 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის ჩვენება და გასვლა\n" -#: option.c:306 +#: option.c:328 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr " --clone ახალ კლასტერში ფაილების კლონირება კოპირების ნაცვლად \n" -#: option.c:307 +#: option.c:329 #, c-format msgid " --copy copy files to new cluster (default)\n" msgstr " --clone ახალ კლასტერში ფაილების კლონირება კოპირების ნაცვლად (ნაგულისხმები)\n" -#: option.c:308 +#: option.c:330 #, c-format msgid " --copy-file-range copy files to new cluster with copy_file_range\n" msgstr " --copy-file-range ფაილების კოპირება ახალ კლასტერში copy_file_range-ით\n" -#: option.c:309 +#: option.c:331 +#, c-format +msgid " --no-statistics do not import statistics from old cluster\n" +msgstr " --no-statistics ძველი კლასტერიდან სტატისტიკა შემოტანილი არ იქნება\n" + +#: option.c:332 +#, c-format +msgid "" +" --set-char-signedness=OPTION set new cluster char signedness to \"signed\" or\n" +" \"unsigned\"\n" +msgstr "" +" --set-char-signedness=OPTION ახალი კლასტერის სიმბოლოს ნიშნანობის დაყენება \"signed\"-ზე ან\n" +" \"unsigned\"-ზე\n" + +#: option.c:334 +#, c-format +msgid " --swap move data directories to new cluster\n" +msgstr " --swap მონაცემებთა საქაღალდეების გადატანა ახალ კლასტერში\n" + +#: option.c:335 #, c-format msgid " --sync-method=METHOD set method for syncing files to disk\n" msgstr " --sync-method=მეთოდი ფაილების დისკზე სინქრონიზაციის მეთოდის დაყენება\n" -#: option.c:310 +#: option.c:336 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: option.c:311 +#: option.c:337 #, c-format msgid "" "\n" @@ -1479,7 +1568,7 @@ msgstr "" " გამორთოთ postmaster სერვისი ძველ კლასტერზე\n" " გამორთოთ postmaster სერვისი ახალ კლასტერზე\n" -#: option.c:316 +#: option.c:342 #, c-format msgid "" "\n" @@ -1496,7 +1585,7 @@ msgstr "" " ძველი ვერსიის \"bin\" საქაღალდე (-b BINDIR)\n" " ახალი ვერსიის \"bin\" საქაღალდე (-B BINDIR)\n" -#: option.c:322 +#: option.c:348 #, c-format msgid "" "\n" @@ -1509,7 +1598,7 @@ msgstr "" " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B newCluster/bin\n" "ან\n" -#: option.c:327 +#: option.c:353 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1524,7 +1613,7 @@ msgstr "" " $ export PGBINNEW=newCluster/bin\n" " $ pg_upgrade\n" -#: option.c:333 +#: option.c:359 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1539,7 +1628,7 @@ msgstr "" " C:\\> set PGBINNEW=newCluster/bin\n" " C:\\> pg_upgrade\n" -#: option.c:339 +#: option.c:365 #, c-format msgid "" "\n" @@ -1548,12 +1637,12 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: option.c:340 +#: option.c:366 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: option.c:380 +#: option.c:406 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1562,32 +1651,32 @@ msgstr "" "%s-ის საქაღალდის იდენტიფიკაცია აუცილებელია.\n" "გამოიყენეთ ბრძანების სტრიქონის %s პარამეტრი ან გარემოს ცვლადი %s." -#: option.c:433 +#: option.c:459 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "საწყისი კლასტერის რეალური მონაცემთა საქაღალდის პოვნა" -#: option.c:435 +#: option.c:461 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "სამიზნე კლასტერის რეალური მონაცემთა საქაღალდის პოვნა" -#: option.c:448 +#: option.c:474 #, c-format msgid "could not get data directory using %s: %m" msgstr "ვერ მივიღე მონაცემთა საქაღალდე %s გამოყენებით: %m" -#: option.c:452 +#: option.c:478 #, c-format msgid "could not get data directory using %s: %s" msgstr "ვერ მივიღე მონაცემთა საქაღალდე %s გამოყენებით: %s" -#: option.c:500 +#: option.c:526 #, c-format msgid "could not read line %d from file \"%s\": %m" msgstr "ფაილიდან (%2$s) %1$d-ე ხაზის წაკითხვა შეუძლებელია: %3$m" -#: option.c:517 +#: option.c:543 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "მომხმარებლის მიერ მოწოდებული ძველი პორტის ნომერი %hu შესწორებულია %hu" @@ -1617,12 +1706,12 @@ msgstr "შვილი პროცესი არანორმალურ msgid "child worker exited abnormally: %m" msgstr "შვილი დამხმარე პროცესი არანორმალურად დასრულდა სტატუსით %m" -#: pg_upgrade.c:115 +#: pg_upgrade.c:114 #, c-format msgid "could not read permissions of directory \"%s\": %m" msgstr "საქაღალდის წვდომების წაკითხვა შეუძლებელია \"%s\": %m" -#: pg_upgrade.c:147 +#: pg_upgrade.c:146 #, c-format msgid "" "\n" @@ -1633,17 +1722,17 @@ msgstr "" "მიმდინარეობს განახლება\n" "------------------" -#: pg_upgrade.c:192 +#: pg_upgrade.c:194 #, c-format msgid "Setting next OID for new cluster" msgstr "ახალი კლასტერისთვის შემდეგი OID დაყენება" -#: pg_upgrade.c:216 +#: pg_upgrade.c:218 #, c-format msgid "Sync data directory to disk" msgstr "მონაცემების საქაღალდის დისკთან სინქრონიზაცია" -#: pg_upgrade.c:230 +#: pg_upgrade.c:234 #, c-format msgid "" "\n" @@ -1654,23 +1743,23 @@ msgstr "" "განახლება დასრულებულია\n" "----------------" -#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 -#: pg_upgrade.c:308 pg_upgrade.c:319 +#: pg_upgrade.c:267 pg_upgrade.c:280 pg_upgrade.c:287 pg_upgrade.c:294 +#: pg_upgrade.c:312 pg_upgrade.c:323 #, c-format msgid "directory path for new cluster is too long" msgstr "ახალი კლასტერის საქაღალდის ბილიკი ძალიან გრძელია" -#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#: pg_upgrade.c:301 pg_upgrade.c:303 pg_upgrade.c:305 pg_upgrade.c:307 #, c-format msgid "could not create directory \"%s\": %m" msgstr "საქაღალდის (%s) შექმნის შეცდომა: %m" -#: pg_upgrade.c:352 +#: pg_upgrade.c:356 #, c-format msgid "%s: could not find own program executable" msgstr "%s: საკუთარი პროგრამის გამშვები ფაილის პოვნა შეუძლებელია" -#: pg_upgrade.c:378 +#: pg_upgrade.c:382 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1679,7 +1768,7 @@ msgstr "" "როგორც ჩანს, ძველ კლასტერს postmaster ჯერ კიდევ ემსახურება.\n" "გამორთეთ postmaster და თავიდან სცადეთ." -#: pg_upgrade.c:391 +#: pg_upgrade.c:395 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1688,141 +1777,201 @@ msgstr "" "როგორც ჩანს, ახალ კლასტერს postmaster ემსახურება.\n" "გამორთეთ postmaster და თავიდან სცადეთ." -#: pg_upgrade.c:413 +#: pg_upgrade.c:421 +#, c-format +msgid "Setting the default char signedness for new cluster" +msgstr "ნაგულისხმევი სიმბოლოს ნიშნიანობის დაყენება ახალი კლასტერისთვის" + +#: pg_upgrade.c:449 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "ახალი კლასტერის ლოკალის და კოდირების დაყენება" -#: pg_upgrade.c:489 +#: pg_upgrade.c:527 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "ახალ კლასტერში ყველა მწკრივის ანალიზი" -#: pg_upgrade.c:502 +#: pg_upgrade.c:540 #, c-format msgid "Freezing all rows in the new cluster" msgstr "ახალ კლასტერში ყველა მწკრივის გაყინვა" -#: pg_upgrade.c:522 +#: pg_upgrade.c:560 #, c-format msgid "Restoring global objects in the new cluster" msgstr "ახალი კლასტერში გლობალური ობიექტების აღდგენა" -#: pg_upgrade.c:538 +#: pg_upgrade.c:577 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "ახალ კლასტერში ბაზის სქემების აღდგენა" -#: pg_upgrade.c:662 +#: pg_upgrade.c:712 #, c-format msgid "Deleting files from new %s" msgstr "ფაილების წაშლა ახალი %s-დან" -#: pg_upgrade.c:666 +#: pg_upgrade.c:716 #, c-format msgid "could not delete directory \"%s\"" msgstr "საქაღალდის (\"%s\") წაშლის შეცდომა" -#: pg_upgrade.c:685 +#: pg_upgrade.c:735 #, c-format msgid "Copying old %s to new server" msgstr "ძველი %s -ის კოპირება ახალ სერვერზე" -#: pg_upgrade.c:711 +#: pg_upgrade.c:761 #, c-format msgid "Setting oldest XID for new cluster" msgstr "უძველესი XID დაყენება ახალი კლასტერისთვის" -#: pg_upgrade.c:719 +#: pg_upgrade.c:769 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "ახალი კლასტერისთვის შემდეგი ტრანზაქციის ეპოქისა და ID-ის დაყენება" -#: pg_upgrade.c:749 +#: pg_upgrade.c:799 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "ახალი კლასტერისთვის შემდეგი მულტიტრანზაქციის წანაცვლებისა და ID-ის დაყენება" -#: pg_upgrade.c:773 +#: pg_upgrade.c:823 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "ახალ კლასტერში უძველესი მულტიტრანზაქციის ID-ის დაყენება" -#: pg_upgrade.c:793 +#: pg_upgrade.c:843 #, c-format msgid "Resetting WAL archives" msgstr "WAL არქივების გადატვირთვა" -#: pg_upgrade.c:836 +#: pg_upgrade.c:886 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "ახალ კლასტერში frozenxid და minmxid მთვლელების დაყენება" -#: pg_upgrade.c:838 +#: pg_upgrade.c:888 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "ახალ კლასტერში minmxid მთვლელის დაყენება" -#: pg_upgrade.c:929 +#: pg_upgrade.c:979 #, c-format msgid "Restoring logical replication slots in the new cluster" msgstr "ახალი კლასტერში ლოგიკური რეპლიკაციის სლოტების აღდგენა" -#: relfilenumber.c:35 +#: relfilenumber.c:68 +#, c-format +msgid "could not synchronize file \"%s\": %m" +msgstr "ფაილის (%s) სინქრონიზაციის შეცდომა: %m" + +#: relfilenumber.c:114 #, c-format msgid "Cloning user relation files" msgstr "მომხმარებლის ურთიერთობის ფაილების კლონირება" -#: relfilenumber.c:38 +#: relfilenumber.c:117 #, c-format msgid "Copying user relation files" msgstr "მომხმარებლის ურთიერთობის ფაილების კოპირება" -#: relfilenumber.c:41 +#: relfilenumber.c:120 #, c-format msgid "Copying user relation files with copy_file_range" msgstr "მომხმარებლის ურთიერთობის ფაილების კოპირება copy_file_range-ით" -#: relfilenumber.c:44 +#: relfilenumber.c:123 #, c-format msgid "Linking user relation files" msgstr "მომხმარებლის ურთიერთობის ფაილების გადაბმა" -#: relfilenumber.c:118 +#: relfilenumber.c:126 +#, c-format +msgid "Swapping data directories" +msgstr "მონაცემების საქაღალდის შეცვლა" + +#: relfilenumber.c:200 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "ძველი მონაცემთა ბაზა \"%s\" ახალ კლასტერში არ არის ნაპოვნი" -#: relfilenumber.c:221 +#: relfilenumber.c:287 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: relfilenumber.c:293 relfilenumber.c:297 +#, c-format +msgid "could not create directory \"%s\"" +msgstr "საქაღალდის (%s) შექმნის შეცდომა" + +#: relfilenumber.c:301 relfilenumber.c:305 +#, c-format +msgid "could not rename \"%s\" to \"%s\"" +msgstr "სახელის გადარქმევის შეცდომა \"%s\"-დან \"%s\"-ზე" + +#: relfilenumber.c:375 relfilenumber.c:402 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: relfilenumber.c:393 relfilenumber.c:420 +#, c-format +msgid "could not rename \"%s\" to \"%s\": %m" +msgstr "სახელის გადარქმევის შეცდომა \"%s\"-დან \"%s\"-ზე: %m" + +#: relfilenumber.c:396 relfilenumber.c:434 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: relfilenumber.c:439 +#, c-format +msgid "could not synchronize directory \"%s\": %m" +msgstr "საქაღალდის \"%s\" სინქრონიზაცია შეუძლებელია: %m" + +#: relfilenumber.c:441 +#, c-format +msgid "could not synchronize parent directory of \"%s\": %m" +msgstr "\"%s\"-ის მშობელი საქაღალდის სინქრონიზაცია შეუძლებელია: %m" + +#: relfilenumber.c:598 #, c-format msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" msgstr "შეცდომა ფაილის არსებობის შემოწმებისას \"%s.%s\" (\"%s\" \"%s\"): %m" -#: relfilenumber.c:238 +#: relfilenumber.c:615 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "გადაწერა \"%s\"-დან \"%s\"-მდე" -#: relfilenumber.c:246 +#: relfilenumber.c:623 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "კლონირება \"%s\"-დან \"%s\"-მდე" -#: relfilenumber.c:251 +#: relfilenumber.c:628 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "კოპირება \"%s\"-დან \"%s\"-მდე" -#: relfilenumber.c:256 +#: relfilenumber.c:633 #, c-format msgid "copying \"%s\" to \"%s\" with copy_file_range" msgstr "კოპირება \"%s\"-დან \"%s\"-მდე copy_file_range-ით" -#: relfilenumber.c:261 +#: relfilenumber.c:638 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "ბმა \"%s\"-დან \"%s\"-მდე" +#: relfilenumber.c:644 +#, c-format +msgid "should never happen" +msgstr "არასდროს უნდა მომხდარიყო" + #: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" @@ -1854,7 +2003,7 @@ msgstr "ვერსიის ფაილის გახსნის შეც msgid "could not parse version file \"%s\"" msgstr "ვერსიის ფაილის დამუშავების შეცდომა \"%s\"" -#: server.c:310 +#: server.c:317 #, c-format msgid "" "\n" @@ -1863,7 +2012,7 @@ msgstr "" "\n" "%s" -#: server.c:314 +#: server.c:321 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1872,7 +2021,7 @@ msgstr "" "ვერ ვუკავშირდები საწყის postmaster-ს, რომელიც შემდეგი ბრძანებით გაეშვა:\n" "%s" -#: server.c:318 +#: server.c:325 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1881,22 +2030,22 @@ msgstr "" "ვერ ვუკავშირდები სამიზნე postmaster-ს, რომელიც შემდეგი ბრძანებით გაეშვა:\n" "%s" -#: server.c:332 +#: server.c:339 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl-ის შეცდომა საწყისი სერვერის გაშვებისას ან შეერთების შეცდომა" -#: server.c:334 +#: server.c:341 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl-ის შეცდომა სამიზნე სერვერის გაშვებისას ან შეერთების შეცდომა" -#: server.c:379 +#: server.c:386 #, c-format msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" -#: server.c:392 +#: server.c:399 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "libpq-ის გარემოს ცვლად %s-ს არალოკალური სერვერის მნიშვნელობა: %s გააჩნია" @@ -1925,6 +2074,26 @@ msgstr "ცხრილების სივრცის საქაღალ msgid "tablespace path \"%s\" is not a directory" msgstr "ცხრილების სივრცის ბილიკი %s საქაღალდეს არ წარმოადგენს" +#: task.c:195 +#, c-format +msgid "failed to create connection with connection string: \"%s\"" +msgstr "ჩავარდა მიერთების შექმნა მიერთების სტრიქონით: \"%s\"" + +#: task.c:217 task.c:268 task.c:283 task.c:294 +#, c-format +msgid "connection failure: %s" +msgstr "მიერთების შეცდომა: %s" + +#: task.c:396 +#, c-format +msgid "invalid socket" +msgstr "არასწორი სოკეტი" + +#: task.c:405 +#, c-format +msgid "select() failed: %m" +msgstr "select() ჩავარდა: %m" + #: util.c:53 util.c:56 util.c:139 util.c:170 util.c:172 #, c-format msgid "%-*s" @@ -1945,11 +2114,6 @@ msgstr "დიახ" msgid "Checking for hash indexes" msgstr "ჰეშის ინდექსების შემოწმება" -#: version.c:121 -#, c-format -msgid "warning" -msgstr "გაფრთხილება" - #: version.c:123 #, c-format msgid "" @@ -1984,17 +2148,17 @@ msgstr "" ", შესრულებული psql-ით მონაცემთა ბაზის ზემომხმარებლის მიერ, თავიდან შექნის ყველა\n" "არასწორ ინდექსს. მანამდე კი, ამ ინდექსებიდან არც ერთი გამოყენებული არ იქნება." -#: version.c:153 +#: version.c:187 #, c-format msgid "Checking for extension updates" msgstr "გაფართოების განახლებების შემოწმება" -#: version.c:200 +#: version.c:201 #, c-format msgid "notice" msgstr "გაფრთხილება" -#: version.c:201 +#: version.c:202 #, c-format msgid "" "\n" diff --git a/src/bin/pg_upgrade/po/ko.po b/src/bin/pg_upgrade/po/ko.po index 5fa498a22035a..800eb1a2f0fea 100644 --- a/src/bin/pg_upgrade/po/ko.po +++ b/src/bin/pg_upgrade/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_upgrade (PostgreSQL) 13\n" +"Project-Id-Version: pg_upgrade (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2020-10-05 20:45+0000\n" -"PO-Revision-Date: 2020-10-06 14:02+0900\n" +"POT-Creation-Date: 2025-01-17 04:50+0000\n" +"PO-Revision-Date: 2025-01-17 15:47+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -17,286 +17,477 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: check.c:66 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "하위 프로세스의 종료 코드를 못 받았음: 오류 코드 %lu" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "%ld 사용자 ID에 대한 사용자를 찾지 못함: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "사용자 없음" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "사용자 이름 찾기 실패: 오류 코드 %lu" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "사용자가 만든 테이블에 내장 복합 자료형을 쓰는지 확인 중" + +#: check.c:118 +msgid "" +"Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"해당 데이터베이스 사용자가 만든 테이블에서 내장 복합 자료형을 사용하고 있습니" +"다.\n" +"이 자료형의 OID 값이 PostgreSQL 버전별로 다를 수 있어,\n" +"업그레이드 할 수 없습니다. 해당 칼럼을 삭제한 뒤 다시 업그레이드하세요.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "\"line\" 자료형 호환성 확인 중" + +#: check.c:137 +msgid "" +"Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"해당 데이터베이스에서 \"line\" 자료형을 사용하는 테이블이 있습니다.\n" +"이 자료형의 입출력 방식이 옛 버전과 새 버전에서 서로 호환하지 않습니다.\n" +"먼저 이 자료형을 사용하는 테이블을 삭제 후 업그레이드 작업을 하세요.\n" + +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "사용자가 만든 테이블에 reg* 자료형을 쓰는지 확인 중" + +#: check.c:181 +msgid "" +"Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"옛 서버에서 사용자가 만든 테이블에서 reg* 자료형을 사용하고 있습니다.\n" +"이 자료형들은 pg_upgrade 명령으로 내정된 시스템 OID를 사용하지 못할 수\n" +"있습니다. 그래서 업그레이드 작업을 진행할 수 없습니다.\n" +"사용하고 있는 칼럼을 지우고 업그레이드 작업을 다시 시도하세요.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "\"aclitem\" 자료형 호환성 확인 중" + +#: check.c:198 +msgid "" +"Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"사용자 테이블에서 \"jsonb\" 자료형을 사용하고 있습니다.\n" +"9.4 베타 비전 이후 \"jsonb\" 내부 자료 구조가 바뀌었습니다.\n" +"그래서, 업그레이드 작업이 불가능합니다.\n" +"해당 칼럼들을 지우고 업그레이드 작업을 진행하세요.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "잘못된 \"unknown\" 사용자 칼럼을 확인 중" + +#: check.c:222 +msgid "" +"Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "" +"해당 데이터베이스에서 사용자 테이블에서 \"unknown\" 자료형을 사용하고 있습니" +"다.\n" +"이 자료형은 더 이상 사용할 수 없습니다. 이 문제를 옛 버전에서 먼저 정리하고\n" +"업그레이드 작업을 진행하세요.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "잘못된 \"sql_identifier\" 사용자 칼럼을 확인 중" + +#: check.c:244 +msgid "" +"Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "" +"사용자 테이블 또는 인덱스에 \"sql_identifier\" 자료형을 사용하고\n" +"있습니다. 이 자료형의 저장 양식이 바뀌었기에, 업그레이드 할 수\n" +"없습니다. 해당 테이블의 칼럼을 지우고 다시 업그레이드 하십시오.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "사용자 테이블에서 \"jsonb\" 자료형 호환성 검사 중" + +#: check.c:260 +msgid "" +"Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "" +"사용자 테이블에서 \"jsonb\" 자료형을 사용하고 있습니다.\n" +"9.4 베타 비전 이후 \"jsonb\" 내부 자료 구조가 바뀌었습니다.\n" +"그래서, 업그레이드 작업이 불가능합니다.\n" +"해당 칼럼들을 지우고 업그레이드 작업을 진행하세요.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "사용자가 만든 테이블에 \"abstime\" 자료형을 쓰는지 확인 중" + +#: check.c:277 +msgid "" +"Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"사용자 테이블에서 \"abstime\" 자료형을 사용하고 있습니다.\n" +"12 비전 이후 \"abstime\" 자료형을 지원하지 않습니다.\n" +"그래서, 업그레이드 작업이 불가능합니다.\n" +"해당 칼럼들을 지우거나, 다른 자료형으로 바꾼 뒤,\n" +"업그레이드 작업을 진행하세요.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "사용자가 만든 테이블에 \"reltime\" 자료형을 쓰는지 확인 중" + +#: check.c:290 +msgid "" +"Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"사용자 테이블에서 \"reltime\" 자료형을 사용하고 있습니다.\n" +"12 비전 이후 \"reltime\" 자료형을 지원하지 않습니다.\n" +"그래서, 업그레이드 작업이 불가능합니다.\n" +"해당 칼럼들을 지우거나, 다른 자료형으로 바꾼 뒤,\n" +"업그레이드 작업을 진행하세요.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "사용자가 만든 테이블에 \"tinterval\" 자료형을 쓰는지 확인 중" + +#: check.c:303 +msgid "" +"Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"사용자 테이블에서 \"tinterval\" 자료형을 사용하고 있습니다.\n" +"12 비전 이후 \"tinterval\" 자료형을 지원하지 않습니다.\n" +"그래서, 업그레이드 작업이 불가능합니다.\n" +"해당 칼럼들을 지우거나, 다른 자료형으로 바꾼 뒤,\n" +"업그레이드 작업을 진행하세요.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "자료형 사용 현황 검사 중" + +#: check.c:480 +#, c-format +msgid "failed check: %s" +msgstr "검사 실패: %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "문제 칼럼 목록을 다음 파일 안에 있습니다:" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "자료형 검사 실패: %s" + +#: check.c:563 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" -"------------------------------------------------\n" +"------------------------------------------------" msgstr "" "옛 운영 서버에서 일관성 검사를 진행합니다.\n" -"------------------------------------------\n" +"------------------------------------------" -#: check.c:72 +#: check.c:569 #, c-format msgid "" "Performing Consistency Checks\n" -"-----------------------------\n" +"-----------------------------" msgstr "" "일관성 검사 수행중\n" -"------------------\n" +"------------------" -#: check.c:190 +#: check.c:718 #, c-format msgid "" "\n" -"*Clusters are compatible*\n" +"*Clusters are compatible*" msgstr "" "\n" -"*클러스터 호환성*\n" +"*클러스터 호환성*" -#: check.c:196 +#: check.c:726 #, c-format msgid "" "\n" "If pg_upgrade fails after this point, you must re-initdb the\n" -"new cluster before continuing.\n" +"new cluster before continuing." msgstr "" "\n" "여기서 pg_upgrade 작업을 실패한다면, 재시도 하기 전에 먼저\n" -"새 클러스터를 처음부터 다시 만들어 진행해야 합니다.\n" +"새 클러스터를 처음부터 다시 만들어 진행해야 합니다." -#: check.c:232 +#: check.c:767 #, c-format msgid "" -"Optimizer statistics are not transferred by pg_upgrade so,\n" -"once you start the new server, consider running:\n" -" %s\n" -"\n" +"Optimizer statistics are not transferred by pg_upgrade.\n" +"Once you start the new server, consider running:\n" +" %s/vacuumdb %s--all --analyze-in-stages" msgstr "" "pg_upgrade 작업에서는 최적화기를 위한 통계 정보까지 업그레이드\n" "하지는 않습니다. 새 서버가 실행 될 때, 다음 명령을 수행하길 권합니다:\n" -" %s\n" -"\n" +" %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:237 -#, c-format -msgid "" -"Optimizer statistics and free space information are not transferred\n" -"by pg_upgrade so, once you start the new server, consider running:\n" -" %s\n" -"\n" -msgstr "" -"pg_upgrade 작업으로는 통계 정보와 빈 공간 정보는 업그레이드 되지\n" -"않습니다. 새 서버가 실행 될 때, 다음 명령을 수행하길 권합니다:\n" -" %s\n" -"\n" - -#: check.c:244 +#: check.c:773 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" -" %s\n" +" %s" msgstr "" "아래 스크립트를 실행하면, 옛 클러스터 자료를 지울 것입니다:\n" -" %s\n" +" %s" -#: check.c:249 +#: check.c:778 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" "because user-defined tablespaces or the new cluster's data directory\n" "exist in the old cluster directory. The old cluster's contents must\n" -"be deleted manually.\n" +"be deleted manually." msgstr "" "옛 클러스터 자료 파일을 지우는 스크립트를 만들지 못했습니다.\n" "사용자 정의 테이블스페이스나, 새 클러스터가 옛 클러스터 안에\n" -"있기 때문입니다. 옛 클러스터 자료는 직접 찾아서 지우세요.\n" +"있기 때문입니다. 옛 클러스터 자료는 직접 찾아서 지우세요." -#: check.c:259 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "클러스터 버전 검사 중" -#: check.c:271 +#: check.c:802 #, c-format -msgid "This utility can only upgrade from PostgreSQL version 8.4 and later.\n" -msgstr "이 도구는 PostgreSQL 8.4 이상 버전에서 사용할 수 있습니다.\n" +msgid "This utility can only upgrade from PostgreSQL version %s and later." +msgstr "이 도구는 PostgreSQL %s 과 그 이상 버전에서 사용할 수 있습니다." -#: check.c:275 +#: check.c:807 #, c-format -msgid "This utility can only upgrade to PostgreSQL version %s.\n" -msgstr "이 도구는 PostgreSQL %s 버전으로만 업그레이드 할 수 있습니다.\n" +msgid "This utility can only upgrade to PostgreSQL version %s." +msgstr "이 도구는 PostgreSQL %s 버전으로만 업그레이드 할 수 있습니다." -#: check.c:284 +#: check.c:816 #, c-format msgid "" -"This utility cannot be used to downgrade to older major PostgreSQL " -"versions.\n" +"This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "" "이 도구는 더 낮은 메이져 PostgreSQL 버전으로 다운그레이드하는데 사용할 수 없" -"습니다.\n" +"습니다." -#: check.c:289 +#: check.c:821 #, c-format msgid "" -"Old cluster data and binary directories are from different major versions.\n" -msgstr "옛 클러스터 자료와 실행파일 디렉터리가 서로 메이져 버전이 다릅니다.\n" +"Old cluster data and binary directories are from different major versions." +msgstr "옛 클러스터 자료와 실행파일 디렉터리가 서로 메이져 버전이 다릅니다." -#: check.c:292 +#: check.c:824 #, c-format msgid "" -"New cluster data and binary directories are from different major versions.\n" -msgstr "새 클러스터 자료와 실행파일 디렉터리가 서로 메이져 버전이 다릅니다.\n" +"New cluster data and binary directories are from different major versions." +msgstr "새 클러스터 자료와 실행파일 디렉터리가 서로 메이져 버전이 다릅니다." -#: check.c:309 +#: check.c:839 #, c-format msgid "" -"When checking a pre-PG 9.1 live old server, you must specify the old " -"server's port number.\n" +"When checking a live server, the old and new port numbers must be different." msgstr "" -"옛 서버가 9.1 버전 이전 이라면 옛 서버의 포트를 반드시 지정해야 합니다.\n" +"운영 서버 검사를 할 때는, 옛 서버, 새 서버의 포트를 다르게 지정해야 합니다." -#: check.c:313 +#: check.c:859 #, c-format -msgid "" -"When checking a live server, the old and new port numbers must be " -"different.\n" +msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "" -"운영 서버 검사를 할 때는, 옛 서버, 새 서버의 포트를 다르게 지정해야 합니다.\n" +"\"%s\" 새 데이터베이스 클러스터가 비어있지 않음: \"%s.%s\" 릴레이션을 찾았음" -#: check.c:328 +#: check.c:882 #, c-format -msgid "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"\"%s\" 데이터베이스의 인코딩이 서로 다릅니다: 옛 서버 \"%s\", 새 서버 \"%s" -"\"\n" +msgid "Checking for new cluster tablespace directories" +msgstr "새 클러스터 테이블스페이스 디렉터리 검사 중" -#: check.c:333 +#: check.c:893 #, c-format -msgid "" -"lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"\"%s\" 데이터베이스의 lc_collate 값이 서로 다릅니다: 옛 서버 \"%s\", 새 서버 " -"\"%s\"\n" +msgid "new cluster tablespace directory already exists: \"%s\"" +msgstr "새 클러스터 테이블스페이스 디렉터리가 이미 있음: \"%s\"" -#: check.c:336 -#, c-format -msgid "" -"lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"\"%s\" 데이터베이스의 lc_ctype 값이 서로 다릅니다: 옛 서버 \"%s\", 새 서버 " -"\"%s\"\n" - -#: check.c:409 -#, c-format -msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"\n" -msgstr "" -"\"%s\" 새 데이터베이스 클러스터가 비어있지 않습니다.\n" -" -- \"%s.%s\" 릴레이션을 찾았음\n" - -#: check.c:458 -#, c-format -msgid "Creating script to analyze new cluster" -msgstr "새 클러스터 통계정보 수집 스크립트를 만듭니다" - -#: check.c:472 check.c:600 check.c:864 check.c:943 check.c:1053 check.c:1144 -#: file.c:336 function.c:240 option.c:497 version.c:54 version.c:199 -#: version.c:341 -#, c-format -msgid "could not open file \"%s\": %s\n" -msgstr "\"%s\" 파일을 열 수 없음: %s\n" - -#: check.c:527 check.c:656 -#, c-format -msgid "could not add execute permission to file \"%s\": %s\n" -msgstr "\"%s\" 파일에 실행 권한을 추가 할 수 없음: %s\n" - -#: check.c:563 +#: check.c:926 #, c-format msgid "" "\n" -"WARNING: new data directory should not be inside the old data directory, e." -"g. %s\n" +"WARNING: new data directory should not be inside the old data directory, " +"i.e. %s" msgstr "" "\n" -"경고: 새 데이터 디렉터리는 옛 데이터 디렉터리 안에 둘 수 없습니다, 예: %s\n" +"경고: 새 데이터 디렉터리는 옛 데이터 디렉터리 안에 둘 수 없습니다, 예: %s" -#: check.c:587 +#: check.c:950 #, c-format msgid "" "\n" "WARNING: user-defined tablespace locations should not be inside the data " -"directory, e.g. %s\n" +"directory, i.e. %s" msgstr "" "\n" "경고: 사용자 정의 테이블스페이스 위치를 데이터 디렉터리 안에 둘 수 없습니다, " -"예: %s\n" +"예: %s" -#: check.c:597 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "옛 클러스터를 지우는 스크립트를 만듭니다" -#: check.c:676 +#: check.c:1014 +#, c-format +msgid "could not add execute permission to file \"%s\": %m" +msgstr "\"%s\" 파일에 실행 권한을 추가 할 수 없음: %m" + +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "데이터베이스 사용자가 설치 작업을 한 사용자인지 확인합니다" -#: check.c:692 +#: check.c:1050 #, c-format -msgid "database user \"%s\" is not the install user\n" -msgstr "\"%s\" 데이터베이스 사용자는 설치 작업을 한 사용자가 아닙니다\n" +msgid "database user \"%s\" is not the install user" +msgstr "\"%s\" 데이터베이스 사용자는 설치 작업을 한 사용자가 아닙니다" -#: check.c:703 +#: check.c:1061 #, c-format -msgid "could not determine the number of users\n" -msgstr "사용자 수를 확인할 수 없음\n" +msgid "could not determine the number of users" +msgstr "사용자 수를 확인할 수 없음" -#: check.c:711 +#: check.c:1069 #, c-format -msgid "Only the install user can be defined in the new cluster.\n" -msgstr "새 클러스터에서만 설치 사용 사용자가 정의될 수 있음\n" +msgid "Only the install user can be defined in the new cluster." +msgstr "새 클러스터에서만 설치 사용 사용자가 정의될 수 있음" -#: check.c:731 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "데이터베이스 연결 설정을 확인 중" -#: check.c:753 +#: check.c:1124 #, c-format msgid "" "template0 must not allow connections, i.e. its pg_database.datallowconn must " -"be false\n" +"be false" msgstr "" "template0 데이터베이스 접속을 금지해야 합니다. 예: 해당 데이터베이스의 " -"pg_database.datallowconn 값이 false여야 합니다.\n" +"pg_database.datallowconn 값이 false여야 합니다." + +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 +#, c-format +msgid "fatal" +msgstr "치명적 오류" -#: check.c:763 +#: check.c:1151 #, c-format msgid "" -"All non-template0 databases must allow connections, i.e. their pg_database." -"datallowconn must be true\n" +"All non-template0 databases must allow connections, i.e. their\n" +"pg_database.datallowconn must be true. Your installation contains\n" +"non-template0 databases with their pg_database.datallowconn set to\n" +"false. Consider allowing connection for all non-template0 databases\n" +"or drop the databases which do not allow connections. A list of\n" +"databases with the problem is in the file:\n" +" %s" msgstr "" -"template0 데이터베이스를 제외한 다른 모든 데이터베이스는 접속이 가능해야합니" -"다. 예: 그들의 pg_database.datallowconn 값은 true여야 합니다.\n" +"template0이 아닌 모든 데이터베이스는 연결을 허용해야하며, 즉 \n" +"pg_database.datallowconn 값이 true여야합니다. 설치된 데이터베이스\n" +"중 pg_database.datallowconn 값이 false로 설정된 template0이 아닌\n" +"데이터베이스가 있습니다. template0이 아닌 데이터베이스의 모든 연결을\n" +"허용하거나 연결을 허용하지 않는 데이터베이스를 삭제하는 것이 좋습니다.\n" +"문제가 있는 데이터베이스 목록은 다음 파일에 기록해 두었습니다:\n" +" %s" -#: check.c:788 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "미리 준비된 트랜잭션을 확인 중" -#: check.c:797 +#: check.c:1185 #, c-format -msgid "The source cluster contains prepared transactions\n" -msgstr "옛 클러스터에 미리 준비된 트랜잭션이 있음\n" +msgid "The source cluster contains prepared transactions" +msgstr "옛 클러스터에 미리 준비된 트랜잭션이 있음" -#: check.c:799 +#: check.c:1187 #, c-format -msgid "The target cluster contains prepared transactions\n" -msgstr "새 클러스터에 미리 준비된 트랜잭션이 있음\n" +msgid "The target cluster contains prepared transactions" +msgstr "새 클러스터에 미리 준비된 트랜잭션이 있음" -#: check.c:825 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "contrib/isn 모듈의 bigint 처리가 서로 같은지 확인 중" -#: check.c:886 check.c:965 check.c:1076 check.c:1167 function.c:262 -#: version.c:245 version.c:282 version.c:425 -#, c-format -msgid "fatal\n" -msgstr "치명적 오류\n" - -#: check.c:887 +#: check.c:1271 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -305,444 +496,547 @@ msgid "" "manually dump databases in the old cluster that use \"contrib/isn\"\n" "facilities, drop them, perform the upgrade, and then restore them. A\n" "list of the problem functions is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "설치되어 있는 \"contrib/isn\" 모듈은 bigint 자료형을 사용합니다.\n" "이 bigint 자료형의 처리 방식이 새 버전과 옛 버전 사이 호환성이 없어,\n" "이 클러스터 업그레이드를 할 수 없습니다. 먼저 수동으로 데이터베이스를 \n" "덤프하고, 해당 모듈을 삭제하고, 업그레이드 한 뒤 다시 덤프 파일을 이용해\n" "복원할 수 있습니다. 문제가 있는 함수는 아래 파일 안에 있습니다:\n" -" %s\n" -"\n" +" %s" + +#: check.c:1293 +#, c-format +msgid "Checking for user-defined postfix operators" +msgstr "사용자 정의 postfix 연산자를 검사 중" + +#: check.c:1368 +#, c-format +msgid "" +"Your installation contains user-defined postfix operators, which are not\n" +"supported anymore. Consider dropping the postfix operators and replacing\n" +"them with prefix operators or function calls.\n" +"A list of user-defined postfix operators is in the file:\n" +" %s" +msgstr "" +"더 이상 사용자 정의 postfix 연산자를 지원하지 않습니다.\n" +"해당 연산자를 지우고, prefix 연산자로 바꾸거나, 함수 호출\n" +"방식으로 바꾸는 것을 고려해 보십시오.\n" +"관련 사용자 정의 postfix 연산자 목록은 아래 파일 안에 있습니다:\n" +" %s" + +#: check.c:1392 +#, c-format +msgid "Checking for incompatible polymorphic functions" +msgstr "불완전한 다형 함수를 확인합니다" -#: check.c:911 +#: check.c:1493 +#, c-format +msgid "" +"Your installation contains user-defined objects that refer to internal\n" +"polymorphic functions with arguments of type \"anyarray\" or " +"\"anyelement\".\n" +"These user-defined objects must be dropped before upgrading and restored\n" +"afterwards, changing them to refer to the new corresponding functions with\n" +"arguments of type \"anycompatiblearray\" and \"anycompatible\".\n" +"A list of the problematic objects is in the file:\n" +" %s" +msgstr "" +"이 서버에는 \"anyarray\" 또는 \"anyelement\" 유형의 인수를 사용하는 \n" +"내부 다형 함수를 참조하는 사용자 정의 객체가 있습니다. \n" +"이러한 사용자 정의 객체는 업그레이드하기 전에 삭제하고, \n" +"\"anycompatiblearray\" 또는 \"anycompatible\" 유형의 새로운 대응 함수를\n" +"참조하도록 변경한 후 다시 복원해야합니다. 문제가 있는 객체 목록은\n" +"다음 파일 안에 있습니다:\n" +" %s" + +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "WITH OIDS 옵션 있는 테이블 확인 중" -#: check.c:966 +#: check.c:1569 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" "supported anymore. Consider removing the oid column using\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "A list of tables with the problem is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "더 이상 WITH OIDS 옵션을 사용하는 테이블을 지원하지 않습니다.\n" "먼저 oid 칼럼이 있는 기존 테이블을 대상으로 다음 명령을 실행해서\n" "이 옵션을 뺄 것을 고려해 보십시오.\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "관련 테이블 목록은 아래 파일 안에 있습니다:\n" -" %s\n" -"\n" +" %s" -#: check.c:996 +#: check.c:1596 #, c-format -msgid "Checking for reg* data types in user tables" -msgstr "사용자가 만든 테이블에 reg* 자료형을 쓰는지 확인 중" +msgid "Checking for roles starting with \"pg_\"" +msgstr "\"pg_\"로 시작하는 롤 확인 중" -#: check.c:1077 +#: check.c:1627 #, c-format msgid "" -"Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"remove the problem tables and restart the upgrade. A list of the\n" -"problem columns is in the file:\n" -" %s\n" -"\n" +"Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" +" %s" msgstr "" -"옛 서버에서 사용자가 만든 테이블에서 reg* 자료형을 사용하고 있습니다.\n" -"이 자료형들은 pg_upgrade 명령으로 내정된 시스템 OID를 사용하지 못할 수\n" -"있습니다. 그래서 업그레이드 작업을 진행할 수 없습니다.\n" -"사용하고 있는 테이블들을 지우고 업그레이드 작업을 다시 시도하세요.\n" -"이런 자료형을 사용하는 칼럼들은 아래 파일 안에 있습니다:\n" -" %s\n" -"\n" +"기존 데이터베이스에 사용자가 만든 \"pg_\"로 시작하는 롤이\n" +"있습니다. \"pg_\"는 시스템 롤로 예약된 접두어입니다.\n" +"이 롤들을 다른 이름으로 바꿔야 업그레이드가 가능합니다.\n" +"\"pg_\"로 시작하는 롤 이름 목록은 다음 파일에 있습니다:\n" +" %s" -#: check.c:1102 +#: check.c:1647 #, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "\"jsonb\" 자료형 호환성 확인 중" +msgid "Checking for user-defined encoding conversions" +msgstr "사용자 정의 인코딩 변환규칙을 검사 중" -#: check.c:1168 +#: check.c:1707 #, c-format msgid "" -"Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can remove the problem\n" -"tables and restart the upgrade. A list of the problem columns is\n" -"in the file:\n" -" %s\n" -"\n" +"Your installation contains user-defined encoding conversions.\n" +"The conversion function parameters changed in PostgreSQL version 14\n" +"so this cluster cannot currently be upgraded. You can remove the\n" +"encoding conversions in the old cluster and restart the upgrade.\n" +"A list of user-defined encoding conversions is in the file:\n" +" %s" msgstr "" -"사용자 테이블에서 \"jsonb\" 자료형을 사용하고 있습니다.\n" -"9.4 베타 비전 이후 JSONB 내부 자료 구조가 바뀌었습니다.\n" +"사용자 정의 인코딩 변환 규칙용 변환 함수 매개 변수가\n" +"PostgreSQL 14 비전 이후 바뀌었습니다.\n" "그래서, 업그레이드 작업이 불가능합니다.\n" -"해당 테이블들을 지우고 업그레이드 작업을 진행하세요\n" -"해당 자료형을 칼럼들은 아래 파일 안에 있습니다:\n" -" %s\n" -"\n" +"먼저 이런 변환 규칙을 옛 서버에서 지우고 다시 시도하세요.\n" +"해당 변환 규칙 목록은 아래 파일 안에 있습니다:\n" +" %s" -#: check.c:1190 +#: check.c:1746 #, c-format -msgid "Checking for roles starting with \"pg_\"" -msgstr "\"pg_\"로 시작하는 롤 확인 중" +msgid "Checking for new cluster logical replication slots" +msgstr "새 클러스터 논리 복제 슬롯 검사 중" + +#: check.c:1754 +#, c-format +msgid "could not count the number of logical replication slots" +msgstr "논리 복제 슬롯 개수를 파악할 수 없음" + +#: check.c:1759 +#, c-format +msgid "expected 0 logical replication slots but found %d" +msgstr "논리 복제 슬롯이 없다고 판단했는데, %d개 발견 됨" + +#: check.c:1769 check.c:1820 +#, c-format +msgid "could not determine parameter settings on new cluster" +msgstr "새 클러스터용 매개변수 설정을 조사 할 수 없음" + +#: check.c:1774 +#, c-format +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "\"wal_level\" 설정값은 \"logical\"이어야 하는데, \"%s\"임" -#: check.c:1200 +#: check.c:1780 #, c-format -msgid "The source cluster contains roles starting with \"pg_\"\n" -msgstr "옛 클러스터에 \"pg_\" 시작하는 롤이 있습니다.\n" +msgid "" +"\"max_replication_slots\" (%d) must be greater than or equal to the number " +"of logical replication slots (%d) on the old cluster" +msgstr "" +"\"max_replication_slots\" 설정값(%d)이 옛 클러스터 논리 복제 슬롯 수(%d)와 같" +"거나 커야 함" -#: check.c:1202 +#: check.c:1812 #, c-format -msgid "The target cluster contains roles starting with \"pg_\"\n" -msgstr "새 클러스터에 \"pg_\"로 시작하는 롤이 있습니다.\n" +msgid "Checking for new cluster configuration for subscriptions" +msgstr "구독을 위한 새 클러스터 환경 설정을 검사 중" -#: check.c:1228 +#: check.c:1824 #, c-format -msgid "failed to get the current locale\n" -msgstr "현재 로케일을 확인 할 수 없음\n" +msgid "" +"\"max_replication_slots\" (%d) must be greater than or equal to the number " +"of subscriptions (%d) on the old cluster" +msgstr "" +"\"max_replication_slots\" 설정값(%d)이 옛 클러스터 구독 수(%d)와 같거나 커야 " +"함" -#: check.c:1237 +#: check.c:1846 #, c-format -msgid "failed to get system locale name for \"%s\"\n" -msgstr "\"%s\"용 시스템 로케일 이름을 알 수 없음\n" +msgid "Checking for valid logical replication slots" +msgstr "논리 복제 슬롯 유효성 검사 중" -#: check.c:1243 +#: check.c:1898 #, c-format -msgid "failed to restore old locale \"%s\"\n" -msgstr "\"%s\" 옛 로케일을 복원할 수 없음\n" +msgid "" +"Your installation contains logical replication slots that cannot be " +"upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other " +"slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" +" %s" +msgstr "" +"옛 클러스터에 업그레이드 할 수 없는 논리 복제 슬롯이 있습니다.\n" +"필요 없는 슬롯을 지우거나 지연된 WAL 소비를 한 뒤에,\n" +"업그레이드 작업을 진행하세요.\n" +"해당 문제의 슬롯 목록은 다음 파일 안에 있습니다:\n" +" %s" + +#: check.c:1922 +#, c-format +msgid "Checking for subscription state" +msgstr "구독 상태 검사 중" + +#: check.c:2023 +#, c-format +msgid "" +"Your installation contains subscriptions without origin or having relations " +"not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart " +"the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" +" %s" +msgstr "" +"오리진 없는 구독이 있거나, i(초기화), r(준비) 상태가 아닌 릴레이션을 포함하" +"는 구독이 있습니다.\n" +"구독의 자료 일관성을 모두 맞춘 다음 업그레이드 작업을 진행하세요.\n" +"해당 문제의 구독 목록은 다음 파일 안에 있습니다:\n" +" %s" -#: controldata.c:127 controldata.c:195 +#: controldata.c:129 controldata.c:199 #, c-format -msgid "could not get control data using %s: %s\n" -msgstr "%s 사용하는 컨트롤 자료를 구할 수 없음: %s\n" +msgid "could not get control data using %s: %m" +msgstr "%s 사용하는 컨트롤 자료를 구할 수 없음: %m" -#: controldata.c:138 +#: controldata.c:139 #, c-format -msgid "%d: database cluster state problem\n" -msgstr "%d: 데이터베이스 클러스터 상태 문제\n" +msgid "%d: database cluster state problem" +msgstr "%d: 데이터베이스 클러스터 상태 문제" -#: controldata.c:156 +#: controldata.c:158 #, c-format msgid "" "The source cluster was shut down while in recovery mode. To upgrade, use " -"\"rsync\" as documented or shut it down as a primary.\n" +"\"rsync\" as documented or shut it down as a primary." msgstr "" "원본 클러스터는 복구 모드(대기 서버 모드나, 복구 중) 상태에서 중지 되었습니" "다. 업그레이드 하려면, 문서에 언급한 것 처럼 \"rsync\"를 사용하든가, 그 서버" -"를 운영 서버 모드로 바꾼 뒤 중지하고 작업하십시오.\n" +"를 운영 서버 모드로 바꾼 뒤 중지하고 작업하십시오." -#: controldata.c:158 +#: controldata.c:160 #, c-format msgid "" "The target cluster was shut down while in recovery mode. To upgrade, use " -"\"rsync\" as documented or shut it down as a primary.\n" +"\"rsync\" as documented or shut it down as a primary." msgstr "" "대상 클러스터는 복구 모드(대기 서버 모드나, 복구 중) 상태에서 중지 되었습니" "다. 업그레이드 하려면, 문서에 언급한 것 처럼 \"rsync\"를 사용하든가, 그 서버" -"를 운영 서버 모드로 바꾼 뒤 중지하고 작업하십시오.\n" +"를 운영 서버 모드로 바꾼 뒤 중지하고 작업하십시오." -#: controldata.c:163 +#: controldata.c:165 #, c-format -msgid "The source cluster was not shut down cleanly.\n" -msgstr "원본 클러스터는 정상적으로 종료되어야 함\n" +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "원본 클러스터는 정상적으로 종료되어야 함, 종료 상태값: \"%s\"" -#: controldata.c:165 +#: controldata.c:167 #, c-format -msgid "The target cluster was not shut down cleanly.\n" -msgstr "대상 클러스터는 정상 종료되어야 함\n" +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "대상 클러스터는 정상 종료되어야 함, 종료 상태값: \"%s\"" -#: controldata.c:176 +#: controldata.c:175 controldata.c:507 #, c-format -msgid "The source cluster lacks cluster state information:\n" -msgstr "원본 클러스터에 클러스터 상태 정보가 없음:\n" +msgid "could not get control data using %s: %s" +msgstr "%s 사용하는 컨트롤 자료를 구할 수 없음: %s" -#: controldata.c:178 +#: controldata.c:181 #, c-format -msgid "The target cluster lacks cluster state information:\n" -msgstr "대상 클러스터에 클러스터 상태 정보가 없음:\n" +msgid "The source cluster lacks cluster state information:" +msgstr "원본 클러스터에 클러스터 상태 정보가 없음:" -#: controldata.c:208 dump.c:49 pg_upgrade.c:339 pg_upgrade.c:375 -#: relfilenode.c:247 util.c:79 +#: controldata.c:183 +#, c-format +msgid "The target cluster lacks cluster state information:" +msgstr "대상 클러스터에 클러스터 상태 정보가 없음:" + +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:215 +#: controldata.c:220 #, c-format -msgid "%d: pg_resetwal problem\n" -msgstr "%d: pg_resetwal 문제\n" +msgid "%d: pg_resetwal problem" +msgstr "%d: pg_resetwal 문제" -#: controldata.c:225 controldata.c:235 controldata.c:246 controldata.c:257 -#: controldata.c:268 controldata.c:287 controldata.c:298 controldata.c:309 -#: controldata.c:320 controldata.c:331 controldata.c:342 controldata.c:345 -#: controldata.c:349 controldata.c:359 controldata.c:371 controldata.c:382 -#: controldata.c:393 controldata.c:404 controldata.c:415 controldata.c:426 -#: controldata.c:437 controldata.c:448 controldata.c:459 controldata.c:470 -#: controldata.c:481 +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 #, c-format -msgid "%d: controldata retrieval problem\n" -msgstr "%d: controldata 복원 문제\n" +msgid "%d: controldata retrieval problem" +msgstr "%d: controldata 복원 문제" -#: controldata.c:546 +#: controldata.c:578 #, c-format -msgid "The source cluster lacks some required control information:\n" -msgstr "옛 클러스터에 필요한 컨트롤 정보가 몇몇 빠져있음:\n" +msgid "The source cluster lacks some required control information:" +msgstr "옛 클러스터에 필요한 컨트롤 정보가 몇몇 빠져있음:" -#: controldata.c:549 +#: controldata.c:581 #, c-format -msgid "The target cluster lacks some required control information:\n" -msgstr "새 클러스터에 필요한 컨트롤 정보가 몇몇 빠져있음:\n" +msgid "The target cluster lacks some required control information:" +msgstr "새 클러스터에 필요한 컨트롤 정보가 몇몇 빠져있음:" -#: controldata.c:552 +#: controldata.c:584 #, c-format -msgid " checkpoint next XID\n" -msgstr " 체크포인트 다음 XID\n" +msgid " checkpoint next XID" +msgstr " 체크포인트 다음 XID" -#: controldata.c:555 +#: controldata.c:587 #, c-format -msgid " latest checkpoint next OID\n" -msgstr " 마지막 체크포인트 다음 OID\n" +msgid " latest checkpoint next OID" +msgstr " 마지막 체크포인트 다음 OID" -#: controldata.c:558 +#: controldata.c:590 #, c-format -msgid " latest checkpoint next MultiXactId\n" -msgstr " 마지막 체크포인트 다음 MultiXactId\n" +msgid " latest checkpoint next MultiXactId" +msgstr " 마지막 체크포인트 다음 MultiXactId" -#: controldata.c:562 +#: controldata.c:594 #, c-format -msgid " latest checkpoint oldest MultiXactId\n" -msgstr " 마지막 체크포인트 제일 오래된 MultiXactId\n" +msgid " latest checkpoint oldest MultiXactId" +msgstr " 마지막 체크포인트 제일 오래된 MultiXactId" -#: controldata.c:565 +#: controldata.c:597 #, c-format -msgid " latest checkpoint next MultiXactOffset\n" -msgstr " 마지막 체크포인트 다음 MultiXactOffset\n" +msgid " latest checkpoint oldestXID" +msgstr " 마지막 체크포인트 제일 오래된 XID" -#: controldata.c:568 +#: controldata.c:600 #, c-format -msgid " first WAL segment after reset\n" -msgstr " 리셋 뒤 첫 WAL 조각\n" +msgid " latest checkpoint next MultiXactOffset" +msgstr " 마지막 체크포인트 다음 MultiXactOffset" -#: controldata.c:571 +#: controldata.c:603 #, c-format -msgid " float8 argument passing method\n" -msgstr " float8 인자 처리 방식\n" +msgid " first WAL segment after reset" +msgstr " 리셋 뒤 첫 WAL 조각" -#: controldata.c:574 +#: controldata.c:606 #, c-format -msgid " maximum alignment\n" -msgstr " 최대 정렬\n" +msgid " float8 argument passing method" +msgstr " float8 인자 처리 방식" -#: controldata.c:577 +#: controldata.c:609 #, c-format -msgid " block size\n" -msgstr " 블록 크기\n" +msgid " maximum alignment" +msgstr " 최대 정렬" -#: controldata.c:580 +#: controldata.c:612 #, c-format -msgid " large relation segment size\n" -msgstr " 대형 릴레이션 조각 크기\n" +msgid " block size" +msgstr " 블록 크기" -#: controldata.c:583 +#: controldata.c:615 #, c-format -msgid " WAL block size\n" -msgstr " WAL 블록 크기\n" +msgid " large relation segment size" +msgstr " 대형 릴레이션 조각 크기" -#: controldata.c:586 +#: controldata.c:618 #, c-format -msgid " WAL segment size\n" -msgstr " WAL 조각 크기\n" +msgid " WAL block size" +msgstr " WAL 블록 크기" -#: controldata.c:589 +#: controldata.c:621 #, c-format -msgid " maximum identifier length\n" -msgstr " 최대 식별자 길이\n" +msgid " WAL segment size" +msgstr " WAL 조각 크기" -#: controldata.c:592 +#: controldata.c:624 #, c-format -msgid " maximum number of indexed columns\n" -msgstr " 최대 인덱스 칼럼 수\n" +msgid " maximum identifier length" +msgstr " 최대 식별자 길이" -#: controldata.c:595 +#: controldata.c:627 #, c-format -msgid " maximum TOAST chunk size\n" -msgstr " 최대 토스트 조각 크기\n" +msgid " maximum number of indexed columns" +msgstr " 최대 인덱스 칼럼 수" -#: controldata.c:599 +#: controldata.c:630 #, c-format -msgid " large-object chunk size\n" -msgstr " 대형 객체 조각 크기\n" +msgid " maximum TOAST chunk size" +msgstr " 최대 토스트 조각 크기" -#: controldata.c:602 +#: controldata.c:634 #, c-format -msgid " dates/times are integers?\n" -msgstr " date/time 자료형을 정수로?\n" +msgid " large-object chunk size" +msgstr " 대형 객체 조각 크기" -#: controldata.c:606 +#: controldata.c:637 #, c-format -msgid " data checksum version\n" -msgstr " 자료 체크섬 버전\n" +msgid " dates/times are integers?" +msgstr " date/time 자료형을 정수로?" -#: controldata.c:608 +#: controldata.c:641 #, c-format -msgid "Cannot continue without required control information, terminating\n" -msgstr "필요한 컨트롤 정보 없이는 진행할 수 없음, 중지 함\n" +msgid " data checksum version" +msgstr " 자료 체크섬 버전" -#: controldata.c:623 +#: controldata.c:643 +#, c-format +msgid "Cannot continue without required control information, terminating" +msgstr "필요한 컨트롤 정보 없이는 진행할 수 없음, 중지 함" + +#: controldata.c:658 #, c-format msgid "" -"old and new pg_controldata alignments are invalid or do not match\n" -"Likely one cluster is a 32-bit install, the other 64-bit\n" +"old and new pg_controldata alignments are invalid or do not match.\n" +"Likely one cluster is a 32-bit install, the other 64-bit" msgstr "" "클러스터간 pg_controldata 정렬이 서로 다릅니다.\n" -"하나는 32비트고, 하나는 64비트인 경우 같습니다\n" +"하나는 32비트고, 하나는 64비트인 경우 같습니다." -#: controldata.c:627 +#: controldata.c:662 #, c-format -msgid "old and new pg_controldata block sizes are invalid or do not match\n" -msgstr "클러스터간 pg_controldata 블록 크기가 서로 다릅니다.\n" +msgid "old and new pg_controldata block sizes are invalid or do not match" +msgstr "클러스터간 pg_controldata 블록 크기가 서로 다릅니다." -#: controldata.c:630 +#: controldata.c:665 #, c-format msgid "" "old and new pg_controldata maximum relation segment sizes are invalid or do " -"not match\n" -msgstr "클러스터간 pg_controldata 최대 릴레이션 조각 크가가 서로 다릅니다.\n" +"not match" +msgstr "클러스터간 pg_controldata 최대 릴레이션 조각 크가가 서로 다릅니다." -#: controldata.c:633 +#: controldata.c:668 #, c-format -msgid "" -"old and new pg_controldata WAL block sizes are invalid or do not match\n" -msgstr "클러스터간 pg_controldata WAL 블록 크기가 서로 다릅니다.\n" +msgid "old and new pg_controldata WAL block sizes are invalid or do not match" +msgstr "클러스터간 pg_controldata WAL 블록 크기가 서로 다릅니다." -#: controldata.c:636 +#: controldata.c:671 #, c-format msgid "" -"old and new pg_controldata WAL segment sizes are invalid or do not match\n" -msgstr "클러스터간 pg_controldata WAL 조각 크기가 서로 다릅니다.\n" +"old and new pg_controldata WAL segment sizes are invalid or do not match" +msgstr "클러스터간 pg_controldata WAL 조각 크기가 서로 다릅니다." -#: controldata.c:639 +#: controldata.c:674 #, c-format msgid "" "old and new pg_controldata maximum identifier lengths are invalid or do not " -"match\n" -msgstr "클러스터간 pg_controldata 최대 식별자 길이가 서로 다릅니다.\n" +"match" +msgstr "클러스터간 pg_controldata 최대 식별자 길이가 서로 다릅니다." -#: controldata.c:642 +#: controldata.c:677 #, c-format msgid "" "old and new pg_controldata maximum indexed columns are invalid or do not " -"match\n" -msgstr "클러스터간 pg_controldata 최대 인덱스 칼럼수가 서로 다릅니다.\n" +"match" +msgstr "클러스터간 pg_controldata 최대 인덱스 칼럼수가 서로 다릅니다." -#: controldata.c:645 +#: controldata.c:680 #, c-format msgid "" "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not " -"match\n" -msgstr "클러스터간 pg_controldata 최대 토스트 조각 크기가 서로 다릅니다.\n" +"match" +msgstr "클러스터간 pg_controldata 최대 토스트 조각 크기가 서로 다릅니다." -#: controldata.c:650 +#: controldata.c:685 #, c-format msgid "" "old and new pg_controldata large-object chunk sizes are invalid or do not " -"match\n" -msgstr "클러스터간 pg_controldata 대형 객체 조각 크기가 서로 다릅니다.\n" +"match" +msgstr "클러스터간 pg_controldata 대형 객체 조각 크기가 서로 다릅니다." -#: controldata.c:653 +#: controldata.c:688 #, c-format -msgid "old and new pg_controldata date/time storage types do not match\n" -msgstr "클러스터간 pg_controldata date/time 저장 크기가 서로 다릅니다.\n" +msgid "old and new pg_controldata date/time storage types do not match" +msgstr "클러스터간 pg_controldata date/time 저장 크기가 서로 다릅니다." -#: controldata.c:666 +#: controldata.c:701 #, c-format -msgid "old cluster does not use data checksums but the new one does\n" +msgid "old cluster does not use data checksums but the new one does" msgstr "" "옛 클러스터는 데이터 체크섬 기능을 사용하지 않고, 새 클러스터는 사용하고 있습" -"니다.\n" +"니다." -#: controldata.c:669 +#: controldata.c:704 #, c-format -msgid "old cluster uses data checksums but the new one does not\n" +msgid "old cluster uses data checksums but the new one does not" msgstr "" "옛 클러스터는 데이터 체크섬 기능을 사용하고, 새 클러스터는 사용하고 있지 않습" -"니다.\n" +"니다." -#: controldata.c:671 +#: controldata.c:706 #, c-format -msgid "old and new cluster pg_controldata checksum versions do not match\n" -msgstr "클러스터간 pg_controldata 체크섬 버전이 서로 다릅니다.\n" +msgid "old and new cluster pg_controldata checksum versions do not match" +msgstr "클러스터간 pg_controldata 체크섬 버전이 서로 다릅니다." -#: controldata.c:682 +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "옛 global/pg_control 파일에 \".old\" 이름을 덧붙입니다." -#: controldata.c:687 +#: controldata.c:722 #, c-format -msgid "Unable to rename %s to %s.\n" -msgstr "%s 이름을 %s 이름으로 바꿀 수 없음.\n" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" -#: controldata.c:690 +#: controldata.c:726 #, c-format msgid "" "\n" "If you want to start the old cluster, you will need to remove\n" "the \".old\" suffix from %s/global/pg_control.old.\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" -"started once the new cluster has been started.\n" -"\n" +"started once the new cluster has been started." msgstr "" "\n" "옛 버전으로 옛 클러스터를 사용해서 서버를 실행하려면,\n" "%s/global/pg_control.old 파일의 이름을 \".old\" 빼고 바꾸어\n" "사용해야합니다. 업그레이드를 \"link\" 모드로 했기 때문에,\n" "한번이라도 새 버전의 서버가 이 클러스터를 이용해서 실행되었다면,\n" -"이 파일이 더 이상 안전하지 않기 때문입니다.\n" -"\n" +"이 파일이 더 이상 안전하지 않기 때문입니다." #: dump.c:20 #, c-format msgid "Creating dump of global objects" msgstr "전역 객체 덤프를 만듭니다" -#: dump.c:31 +#: dump.c:32 #, c-format -msgid "Creating dump of database schemas\n" -msgstr "데이터베이스 스키마 덤프를 만듭니다\n" +msgid "Creating dump of database schemas" +msgstr "데이터베이스 스키마 덤프를 만듭니다" -#: exec.c:44 +#: exec.c:47 #, c-format -msgid "could not get pg_ctl version data using %s: %s\n" -msgstr "%s 명령을 사용해서 pg_ctl 버전 자료를 구할 수 없음: %s\n" +msgid "could not get pg_ctl version data using %s: %m" +msgstr "%s 명령을 사용해서 pg_ctl 버전 자료를 구할 수 없음: %m" -#: exec.c:50 +#: exec.c:51 #, c-format -msgid "could not get pg_ctl version output from %s\n" -msgstr "%s에서 pg_ctl 버전을 알 수 없음\n" +msgid "could not get pg_ctl version data using %s: %s" +msgstr "%s 명령을 사용해서 pg_ctl 버전 자료를 구할 수 없음: %s" -#: exec.c:104 exec.c:108 +#: exec.c:55 #, c-format -msgid "command too long\n" -msgstr "명령이 너무 긺\n" +msgid "could not get pg_ctl version output from %s" +msgstr "%s에서 pg_ctl 버전을 알 수 없음" -#: exec.c:110 util.c:37 util.c:225 +#: exec.c:112 exec.c:116 #, c-format -msgid "%s\n" -msgstr "%s\n" +msgid "command too long" +msgstr "명령이 너무 긺" -#: exec.c:149 option.c:217 +#: exec.c:160 pg_upgrade.c:311 #, c-format -msgid "could not open log file \"%s\": %m\n" -msgstr "\"%s\" 로그 파일을 열 수 없음: %m\n" +msgid "could not open log file \"%s\": %m" +msgstr "\"%s\" 로그 파일을 열 수 없음: %m" -#: exec.c:178 +#: exec.c:192 #, c-format msgid "" "\n" @@ -751,414 +1045,371 @@ msgstr "" "\n" "*실패*" -#: exec.c:181 +#: exec.c:195 #, c-format -msgid "There were problems executing \"%s\"\n" -msgstr "\"%s\" 실행에서 문제 발생\n" +msgid "There were problems executing \"%s\"" +msgstr "\"%s\" 실행에서 문제 발생" -#: exec.c:184 +#: exec.c:198 #, c-format msgid "" "Consult the last few lines of \"%s\" or \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "" "\"%s\" 또는 \"%s\" 파일의 마지막 부분을 살펴보면\n" -"이 문제를 풀 실마리가 보일 것입니다.\n" +"이 문제를 풀 실마리가 보일 것입니다." -#: exec.c:189 +#: exec.c:203 #, c-format msgid "" "Consult the last few lines of \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "" "\"%s\" 파일의 마지막 부분을 살펴보면\n" -"이 문제를 풀 실마리가 보일 것입니다.\n" +"이 문제를 풀 실마리가 보일 것입니다." -#: exec.c:204 option.c:226 +#: exec.c:218 pg_upgrade.c:321 #, c-format -msgid "could not write to log file \"%s\": %m\n" -msgstr "\"%s\" 로그 파일을 쓸 수 없음: %m\n" +msgid "could not write to log file \"%s\": %m" +msgstr "\"%s\" 로그 파일을 쓸 수 없음: %m" -#: exec.c:230 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s\n" -msgstr "\"%s\" 파일을 읽기 위해 열 수 없습니다: %s\n" +msgid "could not open file \"%s\" for reading: %m" +msgstr "\"%s\" 파일을 읽기 위해 열 수 없습니다: %m" -#: exec.c:257 +#: exec.c:270 #, c-format -msgid "You must have read and write access in the current directory.\n" -msgstr "현재 디렉터리의 읽기 쓰기 권한을 부여하세요.\n" +msgid "You must have read and write access in the current directory." +msgstr "현재 디렉터리의 읽기 쓰기 권한을 부여하세요." -#: exec.c:310 exec.c:372 exec.c:436 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s\n" -msgstr "\"%s\" 검사 실패: %s\n" +msgid "check for \"%s\" failed: %m" +msgstr "\"%s\" 검사 실패: %m" -#: exec.c:313 exec.c:375 +#: exec.c:326 exec.c:392 #, c-format -msgid "\"%s\" is not a directory\n" -msgstr "\"%s\" 파일은 디렉터리가 아닙니다.\n" +msgid "\"%s\" is not a directory" +msgstr "\"%s\" 파일은 디렉터리가 아닙니다." -#: exec.c:439 +#: exec.c:444 #, c-format -msgid "check for \"%s\" failed: not a regular file\n" -msgstr "\"%s\" 검사 실패: 일반 파일이 아닙니다\n" +msgid "check for \"%s\" failed: cannot execute" +msgstr "\"%s\" 검사 실패: 실행할 수 없음" -#: exec.c:451 +#: exec.c:454 #, c-format -msgid "check for \"%s\" failed: cannot read file (permission denied)\n" -msgstr "\"%s\" 검사 실패: 해당 파일을 읽을 수 없음 (접근 권한 없음)\n" +msgid "" +"check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" +msgstr "\"%s\" 검사 실패: 잘못된 버전: 현재 \"%s\", 기대값 \"%s\"" -#: exec.c:459 +#: file.c:44 #, c-format -msgid "check for \"%s\" failed: cannot execute (permission denied)\n" -msgstr "\"%s\" 검사 실패: 실행할 수 없음 (접근 권한 없음)\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 클론 중 오류: %m" -#: file.c:43 file.c:61 +#: file.c:51 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 클론 중 오류: %s\n" +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 클론 중 오류: \"%s\" 파일을 열 수 없음: %m" -#: file.c:50 +#: file.c:56 #, c-format msgid "" -"error while cloning relation \"%s.%s\": could not open file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 클론 중 오류: \"%s\" 파일을 열 수 없음: %s\n" +"error while cloning relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 클론 중 오류: \"%s\" 파일을 만들 수 없음: %m" -#: file.c:55 +#: file.c:65 #, c-format -msgid "" -"error while cloning relation \"%s.%s\": could not create file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 클론 중 오류: \"%s\" 파일을 만들 수 없음: %s\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 클론 중 오류: %s" -#: file.c:87 file.c:190 +#: file.c:91 file.c:160 file.c:233 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not open file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 열 수 없음: %s\n" +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 열 수 없음: %m" -#: file.c:92 file.c:199 +#: file.c:96 file.c:165 file.c:242 #, c-format msgid "" -"error while copying relation \"%s.%s\": could not create file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 만들 수 없음: %s\n" +"error while copying relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 만들 수 없음: %m" -#: file.c:106 file.c:223 +#: file.c:110 file.c:266 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not read file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 읽을 수 없음: %s\n" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 읽을 수 없음: %m" -#: file.c:118 file.c:301 +#: file.c:122 file.c:344 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not write file \"%s\": %s\n" -msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 쓸 수 없음: %s\n" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일을 쓸 수 없음: %m" -#: file.c:132 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 복사 중 오류: %s\n" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 복사 중 오류: %m" -#: file.c:151 +#: file.c:172 #, c-format msgid "" -"error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 링크 만드는 중 오류: %s\n" +"error while copying relation \"%s.%s\": could not copy file range from " +"\"%s\" to \"%s\": %m" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: 실패 복사 범위: \"%s\" - \"%s\": %m" #: file.c:194 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not stat file \"%s\": %s\n" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "\"%s.%s\" (\"%s\" / \"%s\") 릴레이션 링크 만드는 중 오류: %m" + +#: file.c:237 +#, c-format +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" msgstr "" -"\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일 상태 정보를 알 수 없음: %s\n" +"\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일 상태 정보를 알 수 없음: %m" -#: file.c:226 +#: file.c:269 #, c-format msgid "" -"error while copying relation \"%s.%s\": partial page found in file \"%s\"\n" -msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일에 페이지가 손상되었음\n" +"error while copying relation \"%s.%s\": partial page found in file \"%s\"" +msgstr "\"%s.%s\" 릴레이션 복사 중 오류: \"%s\" 파일에 페이지가 손상되었음" -#: file.c:328 file.c:345 +#: file.c:371 file.c:387 #, c-format -msgid "could not clone file between old and new data directories: %s\n" -msgstr "옛 데이터 디렉터리와 새 데이터 디렉터리 사이 파일 클론 실패: %s\n" +msgid "could not clone file between old and new data directories: %m" +msgstr "옛 데이터 디렉터리와 새 데이터 디렉터리 사이 파일 클론 실패: %m" -#: file.c:341 +#: file.c:383 file.c:420 #, c-format -msgid "could not create file \"%s\": %s\n" -msgstr "\"%s\" 파일을 만들 수 없음: %s\n" +msgid "could not create file \"%s\": %m" +msgstr "\"%s\" 파일을 만들 수 없음: %m" -#: file.c:352 +#: file.c:393 #, c-format -msgid "file cloning not supported on this platform\n" -msgstr "이 운영체제는 파일 클론 기능을 제공하지 않습니다.\n" +msgid "file cloning not supported on this platform" +msgstr "이 운영체제는 파일 클론 기능을 제공하지 않습니다." -#: file.c:369 +#: file.c:424 #, c-format -msgid "" -"could not create hard link between old and new data directories: %s\n" -"In link mode the old and new data directories must be on the same file " -"system.\n" -msgstr "" -"데이터 디렉터리간 하드 링크를 만들 수 없음: %s\n" -"하드 링크를 사용하려면, 두 디렉터리가 같은 시스템 볼륨 안에 있어야 합니다.\n" +msgid "could not copy file range between old and new data directories: %m" +msgstr "옛 데이터 디렉터리와 새 데이터 디렉터리 사이 파일 클론 실패: %m" -#: function.c:114 +#: file.c:430 #, c-format -msgid "" -"\n" -"The old cluster has a \"plpython_call_handler\" function defined\n" -"in the \"public\" schema which is a duplicate of the one defined\n" -"in the \"pg_catalog\" schema. You can confirm this by executing\n" -"in psql:\n" -"\n" -" \\df *.plpython_call_handler\n" -"\n" -"The \"public\" schema version of this function was created by a\n" -"pre-8.1 install of plpython, and must be removed for pg_upgrade\n" -"to complete because it references a now-obsolete \"plpython\"\n" -"shared object file. You can remove the \"public\" schema version\n" -"of this function by running the following command:\n" -"\n" -" DROP FUNCTION public.plpython_call_handler()\n" -"\n" -"in each affected database:\n" -"\n" -msgstr "" -"\n" -"옛 클러스터는 \"plpython_call_handler\" 함수가 \"public\" 스키마 안에\n" -"정의 되어있습니다. 이 함수는 \"pg_catalog\" 스키마 안에 있어야합니다.\n" -"psql에서 다음 명령으로 이 함수의 위치를 살펴 볼 수 있습니다:\n" -"\n" -" \\df *.plpython_call_handler\n" -"\n" -"\"public\" 스키마 안에 이 함수가 있는 경우는 8.1 버전 이전 버전이었습니다.\n" -"업그레이드 작업을 정상적으로 마치려면, 먼저 \"plpython\" 관련 객체들을 먼저\n" -"모두 지우고, 새 버전용 모듈을 설치해서 사용해야 합니다.\n" -"이 삭제 작업은 다음과 같이 진행합니다:\n" -"\n" -" DROP FUNCTION public.plpython_call_handler()\n" -"\n" -"이 작업은 관련 모든 데이터베이스 단위로 진행되어야 합니다.\n" -"\n" +msgid "copy_file_range not supported on this platform" +msgstr "이 운영체제는 copy_file_range 기능을 제공하지 않습니다." -#: function.c:132 +#: file.c:447 #, c-format -msgid " %s\n" -msgstr " %s\n" - -#: function.c:142 -#, c-format -msgid "Remove the problem functions from the old cluster to continue.\n" -msgstr "옛 클러스터에서 문제가 있는 함수들을 삭제하고 진행하세요.\n" +msgid "" +"could not create hard link between old and new data directories: %m\n" +"In link mode the old and new data directories must be on the same file " +"system." +msgstr "" +"데이터 디렉터리간 하드 링크를 만들 수 없음: %m\n" +"하드 링크를 사용하려면, 두 디렉터리가 같은 시스템 볼륨 안에 있어야 합니다." -#: function.c:189 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "필요한 라이브러리 확인 중" -#: function.c:242 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "\"%s\" 라이브러리 로드 실패: %s" -#: function.c:253 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "데이터베이스: %s\n" -#: function.c:263 +#: function.c:211 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" "new installation. You can add these libraries to the new installation,\n" "or remove the functions using them from the old installation. A list of\n" "problem libraries is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "옛 버전에는 있고, 새 버전에는 없는 라이브러리들이 있습니다. 새 버전에\n" "해당 라이브러리들을 설치하거나, 옛 버전에서 해당 라이브러리를 삭제하고,\n" "업그레이드 작업을 해야합니다. 문제가 있는 라이브러리들은 다음과 같습니다:\n" -" %s\n" -"\n" +" %s" -#: info.c:131 +#: info.c:128 #, c-format msgid "" -"Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s" -"\", new name \"%s.%s\"\n" +"Relation names for OID %u in database \"%s\" do not match: old name \"%s." +"%s\", new name \"%s.%s\"" msgstr "" "%u OID에 대한 \"%s\" 데이터베이스 이름이 서로 다릅니다: 옛 이름: \"%s.%s\", " -"새 이름: \"%s.%s\"\n" +"새 이름: \"%s.%s\"" -#: info.c:151 +#: info.c:148 #, c-format -msgid "Failed to match up old and new tables in database \"%s\"\n" -msgstr "\"%s\" 데이터베이스 내 테이블 이름이 서로 다릅니다:\n" +msgid "Failed to match up old and new tables in database \"%s\"" +msgstr "\"%s\" 데이터베이스 내 테이블 이름이 서로 다릅니다" -#: info.c:240 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " 해당 인덱스: \"%s.%s\"" -#: info.c:250 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " 해당 인덱스의 OID: %u" -#: info.c:262 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " \"%s.%s\" 객체의 토스트 테이블" -#: info.c:270 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " 해당 토스트 베이블의 OID: %u" -#: info.c:274 +#: info.c:263 #, c-format msgid "" -"No match found in old cluster for new relation with OID %u in database \"%s" -"\": %s\n" +"No match found in old cluster for new relation with OID %u in database " +"\"%s\": %s" msgstr "" -"새 클러스터의 %u OID (해당 데이터베이스: \"%s\")가 옛 클러스터에 없음: %s\n" +"새 클러스터의 %u OID (해당 데이터베이스: \"%s\")가 옛 클러스터에 없음: %s" -#: info.c:277 +#: info.c:266 #, c-format msgid "" -"No match found in new cluster for old relation with OID %u in database \"%s" -"\": %s\n" +"No match found in new cluster for old relation with OID %u in database " +"\"%s\": %s" msgstr "" -"옛 클러스터의 %u OID (해당 데이터베이스: \"%s\")가 새 클러스터에 없음: %s\n" +"옛 클러스터의 %u OID (해당 데이터베이스: \"%s\")가 새 클러스터에 없음: %s" -#: info.c:289 -#, c-format -msgid "mappings for database \"%s\":\n" -msgstr "\"%s\" 데이터베이스 맵핑 중:\n" - -#: info.c:292 -#, c-format -msgid "%s.%s: %u to %u\n" -msgstr "%s.%s: %u / %u\n" - -#: info.c:297 info.c:633 +#: info.c:300 #, c-format msgid "" "\n" -"\n" +"source databases:" msgstr "" "\n" -"\n" +"원본 데이터베이스:" -#: info.c:322 +#: info.c:302 #, c-format msgid "" "\n" -"source databases:\n" +"target databases:" msgstr "" "\n" -"원본 데이터베이스:\n" +"대상 데이터베이스:" -#: info.c:324 +#: info.c:346 #, c-format -msgid "" -"\n" -"target databases:\n" -msgstr "" -"\n" -"대상 데이터베이스:\n" +msgid "template0 not found" +msgstr "template0 찾을 수 없음" -#: info.c:631 +#: info.c:805 #, c-format -msgid "Database: %s\n" -msgstr "데이터베이스: %s\n" +msgid "Database: \"%s\"" +msgstr "데이터베이스: \"%s\"" + +#: info.c:818 +#, c-format +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "relname: \"%s.%s\": reloid: %u reltblspace: \"%s\"" -#: info.c:644 +#: info.c:832 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s\n" -msgstr "relname: %s.%s: reloid: %u reltblspace: %s\n" +msgid "Logical replication slots in the database:" +msgstr "해당 데이터베이스 안에 있는 논리 복제 슬롯들:" -#: option.c:102 +#: info.c:838 #, c-format -msgid "%s: cannot be run as root\n" -msgstr "%s: root 권한으로 실행할 수 없음\n" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "슬롯 이름: \"%s\", 출력 플러그인: \"%s\", two_phase: %s" -#: option.c:170 +#: option.c:105 #, c-format -msgid "invalid old port number\n" -msgstr "잘못된 옛 포트 번호\n" +msgid "%s: cannot be run as root" +msgstr "%s: root 권한으로 실행할 수 없음" -#: option.c:175 +#: option.c:172 #, c-format -msgid "invalid new port number\n" -msgstr "잘못된 새 포트 번호\n" +msgid "invalid old port number" +msgstr "잘못된 옛 포트 번호" -#: option.c:207 +#: option.c:177 +#, c-format +msgid "invalid new port number" +msgstr "잘못된 새 포트 번호" + +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "보다 자세한 사용법은 \"%s --help\" 명령을 이용하세요.\n" -#: option.c:214 +#: option.c:223 #, c-format -msgid "too many command-line arguments (first is \"%s\")\n" -msgstr "너무 많은 명령행 인자를 지정 했음 (시작: \"%s\")\n" +msgid "too many command-line arguments (first is \"%s\")" +msgstr "너무 많은 명령행 인자를 지정 했음 (시작: \"%s\")" -#: option.c:220 +#: option.c:229 #, c-format -msgid "Running in verbose mode\n" -msgstr "작업 내역을 자세히 봄\n" +msgid "Running in verbose mode" +msgstr "작업 내역을 자세히 봄" -#: option.c:251 +#: option.c:247 msgid "old cluster binaries reside" msgstr "옛 클러스터 실행파일 위치" -#: option.c:253 +#: option.c:249 msgid "new cluster binaries reside" msgstr "새 클러스터 실팽파일 위치" -#: option.c:255 +#: option.c:251 msgid "old cluster data resides" msgstr "옛 클러스터 자료 위치" -#: option.c:257 +#: option.c:253 msgid "new cluster data resides" msgstr "새 클러스터 자료 위치" -#: option.c:259 +#: option.c:255 msgid "sockets will be created" msgstr "소켓 파일 만들 위치" -#: option.c:276 option.c:374 +#: option.c:272 option.c:374 #, c-format -msgid "could not determine current directory\n" -msgstr "현재 디렉터리 위치를 알 수 없음\n" +msgid "could not determine current directory" +msgstr "현재 디렉터리 위치를 알 수 없음" -#: option.c:279 +#: option.c:275 #, c-format msgid "" -"cannot run pg_upgrade from inside the new cluster data directory on Windows\n" +"cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "" "윈도우즈 환경에서는 pg_upgrade 명령은 새 클러스터 데이터 디렉터리 안에서는 실" -"행할 수 없음\n" +"행할 수 없음" -#: option.c:288 +#: option.c:284 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" "\n" msgstr "" -"새 데이터 클러스터 버전과 pg_upgrade 버전의 메이저 버전이 서로 다릅니다.\n" +"pg_upgrade는 다른 메이저 버전으로 PostgreSQL 클러스터를 업그레이드합니다.\n" "\n" -#: option.c:289 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: option.c:290 +#: option.c:286 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1167,17 +1418,17 @@ msgstr "" " pg_upgrade [옵션]...\n" "\n" -#: option.c:291 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "옵션:\n" -#: option.c:292 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINDIR 옛 클러스터 실행 파일의 디렉터리\n" -#: option.c:293 +#: option.c:289 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1186,23 +1437,23 @@ msgstr "" " -B, --new-bindir=BINDIR 새 클러스터 실행 파일의 디렉터리 (기본값:\n" " pg_upgrade가 있는 디렉터리)\n" -#: option.c:295 +#: option.c:291 #, c-format msgid "" " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check 실 작업 없이, 그냥 검사만\n" -#: option.c:296 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATADIR 옛 클러스터 데이터 디렉터리\n" -#: option.c:297 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATADIR 새 클러스터 데이터 디렉터리\n" -#: option.c:298 +#: option.c:294 #, c-format msgid "" " -j, --jobs=NUM number of simultaneous processes or threads " @@ -1210,7 +1461,7 @@ msgid "" msgstr "" " -j, --jobs=NUM 동시에 작업할 프로세스 또는 쓰레드 수\n" -#: option.c:299 +#: option.c:295 #, c-format msgid "" " -k, --link link instead of copying files to new " @@ -1218,36 +1469,44 @@ msgid "" msgstr "" " -k, --link 새 클러스터 구축을 복사 대신 링크 사용\n" -#: option.c:300 +#: option.c:296 +#, c-format +msgid "" +" -N, --no-sync do not wait for changes to be written safely " +"to disk\n" +msgstr "" +" -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않음\n" + +#: option.c:297 #, c-format msgid "" " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=옵션 옛 서버에서 사용할 서버 옵션들\n" -#: option.c:301 +#: option.c:298 #, c-format msgid "" " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=옵션 새 서버에서 사용할 서버 옵션들\n" -#: option.c:302 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PORT 옛 클러스터 포트 번호 (기본값 %d)\n" -#: option.c:303 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT 새 클러스터 포트 번호 (기본값 %d)\n" -#: option.c:304 +#: option.c:301 #, c-format msgid "" " -r, --retain retain SQL and log files after success\n" msgstr "" " -r, --retain 작업 완료 후 사용했던 SQL과 로그 파일 남김\n" -#: option.c:305 +#: option.c:302 #, c-format msgid "" " -s, --socketdir=DIR socket directory to use (default current " @@ -1256,23 +1515,23 @@ msgstr "" " -s, --socketdir=DIR 사용할 소켓 디렉터리 (기본값: 현재 디렉터" "리)\n" -#: option.c:306 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=이름 클러스터 슈퍼유저 (기본값 \"%s\")\n" -#: option.c:307 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose 작업 내역을 자세히 남김\n" -#: option.c:308 +#: option.c:305 #, c-format msgid "" " -V, --version display version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: option.c:309 +#: option.c:306 #, c-format msgid "" " --clone clone instead of copying files to new " @@ -1280,6 +1539,24 @@ msgid "" msgstr "" " --clone 새 클러스터 구축을 복사 대신 클론 사용\n" +#: option.c:307 +#, c-format +msgid " --copy copy files to new cluster (default)\n" +msgstr " --copy 새 클러스터로 파일 복사 (기본값)\n" + +#: option.c:308 +#, c-format +msgid "" +" --copy-file-range copy files to new cluster with " +"copy_file_range\n" +msgstr " --copy-file-range copy_file_range 기능을 이용해서 복사\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr "" +" --sync-method=METHOD 파일을 디스크에 동기화 하는 방법 지정\n" + #: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" @@ -1330,7 +1607,7 @@ msgstr "" "사용예:\n" " pg_upgrade -d oldCluster/data -D newCluster/data -b oldCluster/bin -B " "newCluster/bin\n" -"or\n" +"또는\n" #: option.c:327 #, c-format @@ -1380,248 +1657,284 @@ msgstr "%s 홈페이지: <%s>\n" #, c-format msgid "" "You must identify the directory where the %s.\n" -"Please use the %s command-line option or the %s environment variable.\n" +"Please use the %s command-line option or the %s environment variable." msgstr "" "%s 위치의 디렉터리를 알고 있어야 함.\n" -"%s 명령행 옵션이나, %s 환경 변수를 사용하세요.\n" +"%s 명령행 옵션이나, %s 환경 변수를 사용하세요." -#: option.c:432 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "원본 클러스터용 실 데이터 디렉터리를 찾는 중" -#: option.c:434 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "대상 클러스터용 실 데이터 디렉터리를 찾는 중" -#: option.c:446 +#: option.c:448 +#, c-format +msgid "could not get data directory using %s: %m" +msgstr "%s 지정한 데이터 디렉터리를 찾을 수 없음: %m" + +#: option.c:452 #, c-format -msgid "could not get data directory using %s: %s\n" -msgstr "%s 지정한 데이터 디렉터리를 찾을 수 없음: %s\n" +msgid "could not get data directory using %s: %s" +msgstr "%s 지정한 데이터 디렉터리를 찾을 수 없음: %s" -#: option.c:505 +#: option.c:500 #, c-format -msgid "could not read line %d from file \"%s\": %s\n" -msgstr "%d 번째 줄을 \"%s\" 파일에서 읽을 수 없음: %s\n" +msgid "could not read line %d from file \"%s\": %m" +msgstr "%d 번째 줄을 \"%s\" 파일에서 읽을 수 없음: %m" -#: option.c:522 +#: option.c:517 #, c-format -msgid "user-supplied old port number %hu corrected to %hu\n" -msgstr "지정한 %hu 옛 포트 번호를 %hu 번호로 바꿈\n" +msgid "user-supplied old port number %hu corrected to %hu" +msgstr "지정한 %hu 옛 포트 번호를 %hu 번호로 바꿈" -#: parallel.c:127 parallel.c:238 +#: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker process: %s\n" -msgstr "작업용 프로세스를 만들 수 없음: %s\n" +msgid "could not create worker process: %m" +msgstr "작업용 프로세스를 만들 수 없음: %m" -#: parallel.c:146 parallel.c:259 +#: parallel.c:143 parallel.c:253 #, c-format -msgid "could not create worker thread: %s\n" -msgstr "작업용 쓰레드를 만들 수 없음: %s\n" +msgid "could not create worker thread: %m" +msgstr "작업용 쓰레드를 만들 수 없음: %m" -#: parallel.c:300 +#: parallel.c:294 #, c-format -msgid "waitpid() failed: %s\n" -msgstr "waitpid() 실패: %s\n" +msgid "%s() failed: %m" +msgstr "%s() 실패: %m" -#: parallel.c:304 +#: parallel.c:298 #, c-format -msgid "child process exited abnormally: status %d\n" -msgstr "하위 작업자가 비정상 종료됨: 상태값 %d\n" +msgid "child process exited abnormally: status %d" +msgstr "하위 작업자가 비정상 종료됨: 상태값 %d" -#: parallel.c:319 +#: parallel.c:313 #, c-format -msgid "child worker exited abnormally: %s\n" -msgstr "하위 작업자가 비정상 종료됨: %s\n" +msgid "child worker exited abnormally: %m" +msgstr "하위 작업자가 비정상 종료됨: %m" -#: pg_upgrade.c:108 +#: pg_upgrade.c:115 #, c-format -msgid "could not read permissions of directory \"%s\": %s\n" -msgstr "\"%s\" 디렉터리 읽기 권한 없음: %s\n" +msgid "could not read permissions of directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 접근권한을 읽을 수 없음: %m" -#: pg_upgrade.c:123 +#: pg_upgrade.c:147 #, c-format msgid "" "\n" "Performing Upgrade\n" -"------------------\n" +"------------------" msgstr "" "\n" "업그레이드 진행 중\n" -"------------------\n" +"------------------" -#: pg_upgrade.c:166 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "새 클러스터용 다음 OID 설정 중" -#: pg_upgrade.c:173 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "데이터 디렉터리 fsync 작업 중" -#: pg_upgrade.c:185 +#: pg_upgrade.c:230 #, c-format msgid "" "\n" "Upgrade Complete\n" -"----------------\n" +"----------------" msgstr "" "\n" -"업그레이드 완료\n" -"---------------\n" +"업그레이드 마침\n" +"---------------" + +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 +#, c-format +msgid "directory path for new cluster is too long" +msgstr "새 클러스터용 디렉터리 이름이 너무 김" + +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 만들 수 없음: %m" -#: pg_upgrade.c:220 +#: pg_upgrade.c:352 #, c-format -msgid "%s: could not find own program executable\n" -msgstr "%s: 실행할 프로그램을 찾을 수 없습니다.\n" +msgid "%s: could not find own program executable" +msgstr "%s: 실행할 프로그램을 찾을 수 없습니다." -#: pg_upgrade.c:246 +#: pg_upgrade.c:378 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "" "옛 서버가 현재 운영 되고 있습니다.\n" -"먼저 서버를 중지하고 진행하세요.\n" +"먼저 서버를 중지하고 진행하세요." -#: pg_upgrade.c:259 +#: pg_upgrade.c:391 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "" "새 서버가 현재 운영 되고 있습니다.\n" -"먼저 서버를 중지하고 진행하세요.\n" +"먼저 서버를 중지하고 진행하세요." -#: pg_upgrade.c:273 +#: pg_upgrade.c:413 +#, c-format +msgid "Setting locale and encoding for new cluster" +msgstr "새 클러스터용 로케일과 인코딩 설정 중" + +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "새 클러스터의 모든 로우에 대해서 통계 정보 수집 중" -#: pg_upgrade.c:286 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "새 클러스터의 모든 로우에 대해서 영구 격리(freeze) 중" -#: pg_upgrade.c:306 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "새 클러스터에 전역 객체를 복원 중" -#: pg_upgrade.c:321 +#: pg_upgrade.c:538 #, c-format -msgid "Restoring database schemas in the new cluster\n" -msgstr "새 클러스터에 데이터베이스 스키마 복원 중\n" +msgid "Restoring database schemas in the new cluster" +msgstr "새 클러스터에 데이터베이스 스키마 복원 중" -#: pg_upgrade.c:425 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "새 %s에서 파일 지우는 중" -#: pg_upgrade.c:429 +#: pg_upgrade.c:666 #, c-format -msgid "could not delete directory \"%s\"\n" -msgstr "\"%s\" 디렉터리를 삭제 할 수 없음\n" +msgid "could not delete directory \"%s\"" +msgstr "\"%s\" 디렉터리를 삭제 할 수 없음" -#: pg_upgrade.c:448 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "옛 %s 객체를 새 서버로 복사 중" -#: pg_upgrade.c:475 +#: pg_upgrade.c:711 +#, c-format +msgid "Setting oldest XID for new cluster" +msgstr "새 클러스터용 제일 오래된 XID 설정 중" + +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "새 클러스터용 다음 트랜잭션 ID와 epoch 값 설정 중" -#: pg_upgrade.c:505 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "새 클러스터용 다음 멀티 트랜잭션 ID와 위치 값 설정 중" -#: pg_upgrade.c:529 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "새 클러스터용 제일 오래된 멀티 트랜잭션 ID 설정 중" -#: pg_upgrade.c:549 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "WAL 아카이브 재설정 중" -#: pg_upgrade.c:592 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "새 클러스터에서 frozenxid, minmxid 값 설정 중" -#: pg_upgrade.c:594 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "새 클러스터에서 minmxid 값 설정 중" -#: relfilenode.c:35 +#: pg_upgrade.c:929 #, c-format -msgid "Cloning user relation files\n" -msgstr "사용자 릴레이션 파일 클론 중\n" +msgid "Restoring logical replication slots in the new cluster" +msgstr "새 클러스터에 논리 복제 슬롯을 복원 중" -#: relfilenode.c:38 +#: relfilenumber.c:35 #, c-format -msgid "Copying user relation files\n" -msgstr "사용자 릴레이션 파일 복사 중\n" +msgid "Cloning user relation files" +msgstr "사용자 릴레이션 파일 클론 중" -#: relfilenode.c:41 +#: relfilenumber.c:38 #, c-format -msgid "Linking user relation files\n" -msgstr "사용자 릴레이션 파일 링크 중\n" +msgid "Copying user relation files" +msgstr "사용자 릴레이션 파일 복사 중" -#: relfilenode.c:115 +#: relfilenumber.c:41 #, c-format -msgid "old database \"%s\" not found in the new cluster\n" -msgstr "\"%s\" 이름의 옛 데이터베이스를 새 클러스터에서 찾을 수 없음\n" +msgid "Copying user relation files with copy_file_range" +msgstr "사용자 릴레이션 파일을 copy_file_range 기능으로 복사 중" -#: relfilenode.c:234 +#: relfilenumber.c:44 +#, c-format +msgid "Linking user relation files" +msgstr "사용자 릴레이션 파일 링크 중" + +#: relfilenumber.c:118 +#, c-format +msgid "old database \"%s\" not found in the new cluster" +msgstr "\"%s\" 이름의 옛 데이터베이스를 새 클러스터에서 찾을 수 없음" + +#: relfilenumber.c:221 #, c-format msgid "" -"error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "\"%s.%s\" (\"%s\" / \"%s\") 파일이 있는지 확인 도중 오류 발생: %s\n" +"error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "\"%s.%s\" (\"%s\" / \"%s\") 파일이 있는지 확인 도중 오류 발생: %m" -#: relfilenode.c:252 +#: relfilenumber.c:238 #, c-format -msgid "rewriting \"%s\" to \"%s\"\n" -msgstr "\"%s\" 객체를 \"%s\" 객체로 다시 쓰는 중\n" +msgid "rewriting \"%s\" to \"%s\"" +msgstr "\"%s\" 객체를 \"%s\" 객체로 다시 쓰는 중" -#: relfilenode.c:260 +#: relfilenumber.c:246 #, c-format -msgid "cloning \"%s\" to \"%s\"\n" -msgstr "\"%s\" 객체를 \"%s\" 객체로 클론 중\n" +msgid "cloning \"%s\" to \"%s\"" +msgstr "\"%s\" 객체를 \"%s\" 객체로 클론 중" -#: relfilenode.c:265 +#: relfilenumber.c:251 #, c-format -msgid "copying \"%s\" to \"%s\"\n" -msgstr "\"%s\" 객체를 \"%s\" 객체로 복사 중\n" +msgid "copying \"%s\" to \"%s\"" +msgstr "\"%s\" 객체를 \"%s\" 객체로 복사 중" -#: relfilenode.c:270 +#: relfilenumber.c:256 #, c-format -msgid "linking \"%s\" to \"%s\"\n" -msgstr "\"%s\" 객체를 \"%s\" 객체로 링크 중\n" +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "\"%s\" 객체를 \"%s\" 객체로 copy_file_range 기능으로 복사 중" -#: server.c:33 +#: relfilenumber.c:261 #, c-format -msgid "connection to database failed: %s" -msgstr "데이터베이스 연결 실패: %s" +msgid "linking \"%s\" to \"%s\"" +msgstr "\"%s\" 객체를 \"%s\" 객체로 링크 중" -#: server.c:39 server.c:141 util.c:135 util.c:165 +#: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" msgstr "실패, 종료함\n" -#: server.c:131 +#: server.c:133 #, c-format -msgid "executing: %s\n" -msgstr "실행중: %s\n" +msgid "executing: %s" +msgstr "실행중: %s" -#: server.c:137 +#: server.c:139 #, c-format msgid "" "SQL command failed\n" @@ -1632,218 +1945,128 @@ msgstr "" "%s\n" "%s" -#: server.c:167 +#: server.c:169 #, c-format -msgid "could not open version file \"%s\": %m\n" -msgstr "\"%s\" 버전 파일 열기 실패: %m\n" +msgid "could not open version file \"%s\": %m" +msgstr "\"%s\" 버전 파일 열기 실패: %m" -#: server.c:171 +#: server.c:173 #, c-format -msgid "could not parse version file \"%s\"\n" -msgstr "\"%s\" 버전 파일 구문 분석 실패\n" +msgid "could not parse version file \"%s\"" +msgstr "\"%s\" 버전 파일 구문 분석 실패" -#: server.c:297 +#: server.c:310 #, c-format msgid "" "\n" -"connection to database failed: %s" +"%s" msgstr "" "\n" -"데이터베이스 연결 실패: %s" +"%s" -#: server.c:302 +#: server.c:314 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" -"%s\n" +"%s" msgstr "" "다음 명령으로 실행된 원본 서버로 접속할 수 없음:\n" -"%s\n" +"%s" -#: server.c:306 +#: server.c:318 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" -"%s\n" +"%s" msgstr "" "다음 명령으로 실행된 대상 서버로 접속할 수 없음:\n" -"%s\n" +"%s" -#: server.c:320 +#: server.c:332 #, c-format -msgid "pg_ctl failed to start the source server, or connection failed\n" -msgstr "원본 서버를 실행하는 pg_ctl 작업 실패, 또는 연결 실패\n" +msgid "pg_ctl failed to start the source server, or connection failed" +msgstr "원본 서버를 실행하는 pg_ctl 작업 실패, 또는 연결 실패" -#: server.c:322 +#: server.c:334 #, c-format -msgid "pg_ctl failed to start the target server, or connection failed\n" -msgstr "대상 서버를 실행하는 pg_ctl 작업 실패, 또는 연결 실패\n" +msgid "pg_ctl failed to start the target server, or connection failed" +msgstr "대상 서버를 실행하는 pg_ctl 작업 실패, 또는 연결 실패" -#: server.c:367 +#: server.c:379 #, c-format -msgid "out of memory\n" -msgstr "메모리 부족\n" +msgid "out of memory" +msgstr "메모리 부족" -#: server.c:380 +#: server.c:392 #, c-format -msgid "libpq environment variable %s has a non-local server value: %s\n" -msgstr "%s libpq 환경 변수가 로컬 서버 값이 아님: %s\n" +msgid "libpq environment variable %s has a non-local server value: %s" +msgstr "%s libpq 환경 변수가 로컬 서버 값이 아님: %s" #: tablespace.c:28 #, c-format msgid "" "Cannot upgrade to/from the same system catalog version when\n" -"using tablespaces.\n" +"using tablespaces." msgstr "" "사용자 정의 테이블스페이스를 사용하는 경우 같은 시스템 카탈로그 버전으로\n" -"업그레이드 작업을 진행할 수 없습니다.\n" +"업그레이드 작업을 진행할 수 없습니다." -#: tablespace.c:86 +#: tablespace.c:83 #, c-format -msgid "tablespace directory \"%s\" does not exist\n" -msgstr "\"%s\" 이름의 테이블스페이스 디렉터리가 없음\n" +msgid "tablespace directory \"%s\" does not exist" +msgstr "\"%s\" 이름의 테이블스페이스 디렉터리가 없음" -#: tablespace.c:90 +#: tablespace.c:87 #, c-format -msgid "could not stat tablespace directory \"%s\": %s\n" -msgstr "\"%s\" 테이블스페이스 디렉터리의 상태 정보를 구할 수 없음: %s\n" +msgid "could not stat tablespace directory \"%s\": %m" +msgstr "\"%s\" 테이블스페이스 디렉터리의 상태 정보를 구할 수 없음: %m" -#: tablespace.c:95 +#: tablespace.c:92 #, c-format -msgid "tablespace path \"%s\" is not a directory\n" -msgstr "\"%s\" 테이블스페이스 경로는 디렉터리가 아님\n" +msgid "tablespace path \"%s\" is not a directory" +msgstr "\"%s\" 테이블스페이스 경로는 디렉터리가 아님" -#: util.c:49 -#, c-format -msgid " " -msgstr " " - -#: util.c:82 +#: util.c:53 util.c:56 util.c:139 util.c:170 util.c:172 #, c-format msgid "%-*s" msgstr "%-*s" -#: util.c:174 +#: util.c:107 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 액세스할 수 없습니다: %m" + +#: util.c:287 #, c-format msgid "ok" msgstr "ok" -#: version.c:29 +#: version.c:44 #, c-format -msgid "Checking for large objects" -msgstr "대형 객체 확인 중" +msgid "Checking for hash indexes" +msgstr "해쉬 인덱스 확인 중" -#: version.c:77 version.c:384 +#: version.c:121 #, c-format msgid "warning" msgstr "경고" -#: version.c:79 -#, c-format -msgid "" -"\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table. After upgrading, you will be\n" -"given a command to populate the pg_largeobject_metadata table with\n" -"default permissions.\n" -"\n" -msgstr "" -"\n" -"이 데이터베이스는 대형 객체를 사용하고 있습니다. 새 데이터베이스에서는\n" -"이들의 접근 권한 제어를 위해 추가적인 테이블을 사용합니다. 업그레이드 후\n" -"이 객체들의 접근 권한은 pg_largeobject_metadata 테이블에 기본값으로 지정됩니" -"다.\n" -"\n" - -#: version.c:85 -#, c-format -msgid "" -"\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table, so default permissions must be\n" -"defined for all large objects. The file\n" -" %s\n" -"when executed by psql by the database superuser will set the default\n" -"permissions.\n" -"\n" -msgstr "" -"\n" -"이 데이터베이스는 대형 객체를 사용하고 있습니다. 새 데이터베이스에서는\n" -"이들의 접근 권한 제어를 위해 추가적인 테이블을 사용합니다. 그래서\n" -"이들의 접근 권한을 기본값으로 설정하려면,\n" -" %s\n" -"파일을 새 서버가 실행 되었을 때 슈퍼유저 권한으로 psql 명령으로\n" -"실행 하세요.\n" -"\n" - -#: version.c:239 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "\"line\" 자료형 호환성 확인 중" - -#: version.c:246 -#, c-format -msgid "" -"Your installation contains the \"line\" data type in user tables. This\n" -"data type changed its internal and input/output format between your old\n" -"and new clusters so this cluster cannot currently be upgraded. You can\n" -"remove the problem tables and restart the upgrade. A list of the problem\n" -"columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"해당 데이터베이스에서 \"line\" 자료형을 사용하는 칼럼이 있습니다.\n" -"이 자료형의 입출력 방식이 옛 버전과 새 버전에서 서로 호환하지 않습니다.\n" -"먼저 이 자료형을 사용하는 테이블을 삭제 후 업그레이드 작업을 하고,\n" -"수동으로 복원 작업을 해야 합니다. 해당 파일들은 다음과 같습니다:\n" -" %s\n" -"\n" - -#: version.c:276 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "잘못된 \"unknown\" 사용자 칼럼을 확인 중" - -#: version.c:283 -#, c-format -msgid "" -"Your installation contains the \"unknown\" data type in user tables. This\n" -"data type is no longer allowed in tables, so this cluster cannot currently\n" -"be upgraded. You can remove the problem tables and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"해당 데이터베이스에서 사용자 테이블에서 \"unknown\" 자료형을 사용하고 있습니" -"다.\n" -"이 자료형은 더 이상 사용할 수 없습니다. 이 문제를 옛 버전에서 먼저 정리하고\n" -"업그레이드 작업을 진행하세요. 해당 파일은 다음과 같습니다:\n" -" %s\n" -"\n" - -#: version.c:306 -#, c-format -msgid "Checking for hash indexes" -msgstr "해쉬 인덱스 확인 중" - -#: version.c:386 +#: version.c:123 #, c-format msgid "" "\n" "Your installation contains hash indexes. These indexes have different\n" "internal formats between your old and new clusters, so they must be\n" "reindexed with the REINDEX command. After upgrading, you will be given\n" -"REINDEX instructions.\n" -"\n" +"REINDEX instructions." msgstr "" "\n" "해당 데이터베이스에서 해쉬 인덱스를 사용하고 있습니다. 해쉬 인덱스 자료구조" "가\n" "새 버전에서 호환되지 않습니다. 업그레이드 후에 해당 인덱스들을\n" -"REINDEX 명령으로 다시 만들어야 합니다.\n" -"\n" +"REINDEX 명령으로 다시 만들어야 합니다." -#: version.c:392 +#: version.c:129 #, c-format msgid "" "\n" @@ -1852,8 +2075,7 @@ msgid "" "reindexed with the REINDEX command. The file\n" " %s\n" "when executed by psql by the database superuser will recreate all invalid\n" -"indexes; until then, none of these indexes will be used.\n" -"\n" +"indexes; until then, none of these indexes will be used." msgstr "" "\n" "해당 데이터베이스에서 해쉬 인덱스를 사용하고 있습니다. 해쉬 인덱스 자료구조" @@ -1861,29 +2083,35 @@ msgstr "" "새 버전에서 호환되지 않습니다. 업그레이드 후 다음 파일을\n" "슈퍼유저 권한으로 실행한 psql에서 실행해서, REINDEX 작업을 진행하세요:\n" " %s\n" -"이 작업이 있기 전까지는 해당 인덱스는 invalid 상태로 사용할 수 없게 됩니다.\n" -"\n" +"이 작업이 있기 전까지는 해당 인덱스는 invalid 상태로 사용할 수 없게 됩니다." -#: version.c:418 +#: version.c:153 #, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "잘못된 \"sql_identifier\" 사용자 칼럼을 확인 중" +msgid "Checking for extension updates" +msgstr "확장 모듈 업데이트 확인 중" + +#: version.c:200 +#, c-format +msgid "notice" +msgstr "알림" -#: version.c:426 +#: version.c:201 #, c-format msgid "" -"Your installation contains the \"sql_identifier\" data type in user tables\n" -"and/or indexes. The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can remove the problem tables or\n" -"change the data type to \"name\" and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" "\n" -msgstr "" -"사용자 테이블 또는/이나 인덱스에 \"sql_identifier\" 자료형을 사용하고\n" -"있습니다. 이 자료형의 저장 양식이 바뀌었기에, 이 클러스터는 업그레이드\n" -"되어야합니다. 해당 테이블을 지우거나, 해당 칼럼의 자료형을 \"name\" 형으로\n" -"바꾸고, 서버를 재실행 한 뒤 업그레이드 하십시오.\n" -"문제의 칼럼이 있는 파일들은 다음과 같습니다:\n" +"Your installation contains extensions that should be updated\n" +"with the ALTER EXTENSION command. The file\n" " %s\n" +"when executed by psql by the database superuser will update\n" +"these extensions." +msgstr "" "\n" +"해당 서버에는 업데이트 해야하는 확장 모듈이 있습니다.\n" +"이 작업은 ALTER EXTENSION 명령으로 할 수 있으며, 작업 명령은\n" +" %s\n" +"파일 안에 있습니다. 데이터베이스 슈퍼유저로 psql로 접속해서\n" +"이 파일 안에 있는 명령을 수행하면 확장 모듈을 업데이트 할 수 있습니다." + +#, c-format +#~ msgid "Checking for incompatible \"jsonb\" data type" +#~ msgstr "\"jsonb\" 자료형 호환성 확인 중" diff --git a/src/bin/pg_upgrade/po/meson.build b/src/bin/pg_upgrade/po/meson.build index 30ec8337ebc7f..2b2c004bb2dfb 100644 --- a/src/bin/pg_upgrade/po/meson.build +++ b/src/bin/pg_upgrade/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_upgrade-' + pg_version_major.to_string())] diff --git a/src/bin/pg_upgrade/po/ru.po b/src/bin/pg_upgrade/po/ru.po index e26ade17a167f..71fa979972e85 100644 --- a/src/bin/pg_upgrade/po/ru.po +++ b/src/bin/pg_upgrade/po/ru.po @@ -1,306 +1,532 @@ # Russian message translation file for pg_upgrade # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2017, 2018, 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Maxim Yablokov , 2021. msgid "" msgstr "" "Project-Id-Version: pg_upgrade (PostgreSQL) 10\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 06:29+0300\n" -"PO-Revision-Date: 2022-01-19 16:26+0300\n" +"POT-Creation-Date: 2024-11-02 08:21+0300\n" +"PO-Revision-Date: 2024-11-02 08:31+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: check.c:70 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "выяснить эффективный идентификатор пользователя (%ld) не удалось: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "пользователь не существует" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "распознать имя пользователя не удалось (код ошибки: %lu)" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "Проверка системных составных типов в пользовательских таблицах" + +#: check.c:118 +msgid "" +"Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют системные составные\n" +"типы. OID таких типов могут различаться в разных версиях PostgreSQL, поэтому " +"в\n" +"настоящем состоянии обновить кластер невозможно. Вы можете удалить " +"проблемные\n" +"столбцы и перезапустить обновление.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "Проверка несовместимого типа данных \"line\"" + +#: check.c:137 +msgid "" +"Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"line\".\n" +"В старом кластере внутренний формат и формат ввода/вывода этого типа " +"отличается\n" +"от нового, поэтому в настоящем состоянии обновить кластер невозможно. Вы " +"можете\n" +"удалить проблемные столбцы и перезапустить обновление.\n" + +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "Проверка типов данных reg* в пользовательских таблицах" + +#: check.c:181 +msgid "" +"Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы содержат один из типов reg*.\n" +"Эти типы данных ссылаются на системные OID, которые не сохраняются утилитой\n" +"pg_upgrade, так что обновление кластера в текущем состоянии невозможно. Вы\n" +"можете удалить проблемные столбцы и перезапустить обновление.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "Проверка несовместимого типа данных \"aclitem\"" + +#: check.c:198 +msgid "" +"Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"aclitem\".\n" +"Внутренний формат \"aclitem\" изменился в PostgreSQL версии 16, поэтому " +"обновить\n" +"кластер в текущем состоянии невозможно. Вы можете удалить проблемные столбцы " +"и\n" +"перезапустить обновление.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "Проверка неправильных пользовательских столбцов типа \"unknown\"" + +#: check.c:222 +msgid "" +"Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"unknown\".\n" +"Теперь использование этого типа данных в таблицах не допускается, поэтому\n" +"в настоящем состоянии обновить кластер невозможно. Вы можете удалить " +"проблемные\n" +"столбцы и перезапустить обновление.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "" +"Проверка неправильных пользовательских столбцов типа \"sql_identifier\"" + +#: check.c:244 +msgid "" +"Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных\n" +"\"sql_identifier\". Формат хранения таких данных на диске поменялся,\n" +"поэтому обновить данный кластер невозможно. Вы можете удалить проблемные\n" +"столбцы и перезапустить обновление.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "" +"Проверка несовместимого типа данных \"jsonb\" в пользовательских таблицах" + +#: check.c:260 +msgid "" +"Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "" +"В вашей инсталляции таблицы используют тип данных \"jsonb\".\n" +"Внутренний формат \"jsonb\" изменился в версии 9.4 beta, поэтому обновить\n" +"кластер в текущем состоянии невозможно. Вы можете удалить проблемные столбцы " +"и\n" +"перезапустить обновление.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "" +"Проверка удалённого типа данных \"abstime\" в пользовательских таблицах" + +#: check.c:277 +msgid "" +"Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"abstime\".\n" +"Тип \"abstime\" был удалён в PostgreSQL версии 12, поэтому обновить кластер " +"в\n" +"текущем состоянии невозможно. Вы можете удалить проблемные столбцы или " +"поменять\n" +"их тип на другой, а затем перезапустить обновление.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "" +"Проверка удалённого типа данных \"reltime\" в пользовательских таблицах" + +#: check.c:290 +msgid "" +"Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"reltime\".\n" +"Тип \"reltime\" был удалён в PostgreSQL версии 12, поэтому обновить кластер " +"в\n" +"текущем состоянии невозможно. Вы можете удалить проблемные столбцы или " +"поменять\n" +"их тип на другой, а затем перезапустить обновление.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "" +"Проверка удалённого типа данных \"tinterval\" в пользовательских таблицах" + +#: check.c:303 +msgid "" +"Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"В вашей инсталляции пользовательские таблицы используют тип данных " +"\"tinterval\".\n" +"Тип \"tinterval\" был удалён в PostgreSQL версии 12, поэтому обновить " +"кластер в\n" +"текущем состоянии невозможно. Вы можете удалить проблемные столбцы или " +"поменять\n" +"их тип на другой, а затем перезапустить обновление.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "Проверка использования типов данных" + +#: check.c:480 +#, c-format +msgid "failed check: %s" +msgstr "не пройдена проверка: %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "Список проблемных столбцов приведён в файле:" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "Проверки типов данных не пройдены: %s" + +#: check.c:563 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" -"------------------------------------------------\n" +"------------------------------------------------" msgstr "" "Проверка целостности на старом работающем сервере\n" -"-------------------------------------------------\n" +"-------------------------------------------------" -#: check.c:76 +#: check.c:569 #, c-format msgid "" "Performing Consistency Checks\n" -"-----------------------------\n" +"-----------------------------" msgstr "" "Проведение проверок целостности\n" -"-------------------------------\n" +"-------------------------------" -#: check.c:213 +#: check.c:718 #, c-format msgid "" "\n" -"*Clusters are compatible*\n" +"*Clusters are compatible*" msgstr "" "\n" -"*Кластеры совместимы*\n" +"*Кластеры совместимы*" -#: check.c:219 +#: check.c:726 #, c-format msgid "" "\n" "If pg_upgrade fails after this point, you must re-initdb the\n" -"new cluster before continuing.\n" +"new cluster before continuing." msgstr "" "\n" "Если работа pg_upgrade после этого прервётся, вы должны заново выполнить " "initdb\n" -"для нового кластера, чтобы продолжить.\n" +"для нового кластера, чтобы продолжить." -#: check.c:264 +#: check.c:767 #, c-format msgid "" "Optimizer statistics are not transferred by pg_upgrade.\n" "Once you start the new server, consider running:\n" -" %s/vacuumdb %s--all --analyze-in-stages\n" -"\n" +" %s/vacuumdb %s--all --analyze-in-stages" msgstr "" "Статистика оптимизатора утилитой pg_upgrade не переносится.\n" "Запустив новый сервер, имеет смысл выполнить:\n" -" %s/vacuumdb %s--all --analyze-in-stages\n" -"\n" +" %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:270 +#: check.c:773 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" -" %s\n" +" %s" msgstr "" "При запуске этого скрипта будут удалены файлы данных старого кластера:\n" -" %s\n" +" %s" -#: check.c:275 +#: check.c:778 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" "because user-defined tablespaces or the new cluster's data directory\n" "exist in the old cluster directory. The old cluster's contents must\n" -"be deleted manually.\n" +"be deleted manually." msgstr "" "Не удалось создать скрипт для удаления файлов данных старого кластера,\n" "так как каталог старого кластера содержит пользовательские табличные\n" "пространства или каталог данных нового кластера.\n" -"Содержимое старого кластера нужно будет удалить вручную.\n" +"Содержимое старого кластера нужно будет удалить вручную." -#: check.c:287 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "Проверка версий кластеров" -#: check.c:299 +#: check.c:802 #, c-format -msgid "This utility can only upgrade from PostgreSQL version 8.4 and later.\n" +msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "" -"Эта утилита может производить обновление только с версии PostgreSQL 8.4 и " -"новее.\n" +"Эта утилита может производить обновление только с версии PostgreSQL %s и " +"новее." -#: check.c:303 +#: check.c:807 #, c-format -msgid "This utility can only upgrade to PostgreSQL version %s.\n" -msgstr "Эта утилита может только повышать версию PostgreSQL до %s.\n" +msgid "This utility can only upgrade to PostgreSQL version %s." +msgstr "Эта утилита может повышать версию PostgreSQL только до %s." -#: check.c:312 +#: check.c:816 #, c-format msgid "" -"This utility cannot be used to downgrade to older major PostgreSQL " -"versions.\n" +"This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "" "Эта утилита не может понижать версию до более старой основной версии " -"PostgreSQL.\n" +"PostgreSQL." -#: check.c:317 +#: check.c:821 #, c-format msgid "" -"Old cluster data and binary directories are from different major versions.\n" +"Old cluster data and binary directories are from different major versions." msgstr "" "Каталоги данных и исполняемых файлов старого кластера относятся к разным " -"основным версиям.\n" +"основным версиям." -#: check.c:320 +#: check.c:824 #, c-format msgid "" -"New cluster data and binary directories are from different major versions.\n" +"New cluster data and binary directories are from different major versions." msgstr "" "Каталоги данных и исполняемых файлов нового кластера относятся к разным " -"основным версиям.\n" - -#: check.c:337 -#, c-format -msgid "" -"When checking a pre-PG 9.1 live old server, you must specify the old " -"server's port number.\n" -msgstr "" -"Для проверки старого работающего сервера версии до 9.1 необходимо указать " -"номер порта этого сервера.\n" +"основным версиям." -#: check.c:341 +#: check.c:839 #, c-format msgid "" -"When checking a live server, the old and new port numbers must be " -"different.\n" +"When checking a live server, the old and new port numbers must be different." msgstr "" "Для проверки работающего сервера новый номер порта должен отличаться от " -"старого.\n" - -#: check.c:356 -#, c-format -msgid "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"кодировки в базе данных \"%s\" различаются: старая - \"%s\", новая - \"%s" -"\"\n" - -#: check.c:361 -#, c-format -msgid "" -"lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"значения lc_collate в базе данных \"%s\" различаются: старое - \"%s\", " -"новое - \"%s\"\n" - -#: check.c:364 -#, c-format -msgid "" -"lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "" -"значения lc_ctype в базе данных \"%s\" различаются: старое - \"%s\", новое " -"- \"%s\"\n" +"старого." -#: check.c:437 +#: check.c:859 #, c-format -msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"\n" +msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "" -"Новая база данных кластера \"%s\" не пустая: найдено отношение \"%s.%s\"\n" +"Новая база данных кластера \"%s\" не пустая: найдено отношение \"%s.%s\"" -#: check.c:494 +#: check.c:882 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Проверка каталогов табличных пространств в новом кластере" -#: check.c:505 +#: check.c:893 #, c-format -msgid "new cluster tablespace directory already exists: \"%s\"\n" +msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "" -"каталог табличного пространства в новом кластере уже существует: \"%s\"\n" +"каталог табличного пространства в новом кластере уже существует: \"%s\"" -#: check.c:538 +#: check.c:926 #, c-format msgid "" "\n" -"WARNING: new data directory should not be inside the old data directory, e." -"g. %s\n" +"WARNING: new data directory should not be inside the old data directory, i." +"e. %s" msgstr "" "\n" "ПРЕДУПРЕЖДЕНИЕ: новый каталог данных не должен располагаться внутри старого " -"каталога данных, то есть, в %s\n" +"каталога данных, то есть, в %s" -#: check.c:562 +#: check.c:950 #, c-format msgid "" "\n" "WARNING: user-defined tablespace locations should not be inside the data " -"directory, e.g. %s\n" +"directory, i.e. %s" msgstr "" "\n" "ПРЕДУПРЕЖДЕНИЕ: пользовательские табличные пространства не должны " -"располагаться внутри каталога данных, то есть, в %s\n" +"располагаться внутри каталога данных, то есть, в %s" -#: check.c:572 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "Создание скрипта для удаления старого кластера" -#: check.c:575 check.c:839 check.c:937 check.c:1016 check.c:1278 file.c:336 -#: function.c:240 option.c:497 version.c:54 version.c:204 version.c:376 -#: version.c:511 +#: check.c:1014 #, c-format -msgid "could not open file \"%s\": %s\n" -msgstr "не удалось открыть файл \"%s\": %s\n" +msgid "could not add execute permission to file \"%s\": %m" +msgstr "не удалось добавить право выполнения для файла \"%s\": %m" -#: check.c:631 -#, c-format -msgid "could not add execute permission to file \"%s\": %s\n" -msgstr "не удалось добавить право выполнения для файла \"%s\": %s\n" - -#: check.c:651 +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "Проверка, является ли пользователь БД стартовым пользователем" -#: check.c:667 +#: check.c:1050 #, c-format -msgid "database user \"%s\" is not the install user\n" -msgstr "пользователь БД \"%s\" не является стартовым пользователем\n" +msgid "database user \"%s\" is not the install user" +msgstr "пользователь БД \"%s\" не является стартовым пользователем" -#: check.c:678 +#: check.c:1061 #, c-format -msgid "could not determine the number of users\n" -msgstr "не удалось определить количество пользователей\n" +msgid "could not determine the number of users" +msgstr "не удалось определить количество пользователей" -#: check.c:686 +#: check.c:1069 #, c-format -msgid "Only the install user can be defined in the new cluster.\n" -msgstr "В новом кластере может быть определён только стартовый пользователь.\n" +msgid "Only the install user can be defined in the new cluster." +msgstr "В новом кластере может быть определён только стартовый пользователь." -#: check.c:706 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "Проверка параметров подключения к базе данных" -#: check.c:728 +#: check.c:1124 #, c-format msgid "" "template0 must not allow connections, i.e. its pg_database.datallowconn must " -"be false\n" +"be false" msgstr "" -"База template0 не должна допускать подключения, то есть её свойство " -"pg_database.datallowconn должно быть false\n" +"база template0 не должна допускать подключения, то есть её свойство " +"pg_database.datallowconn должно быть false" + +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 +#, c-format +msgid "fatal" +msgstr "сбой" -#: check.c:738 +#: check.c:1151 #, c-format msgid "" -"All non-template0 databases must allow connections, i.e. their pg_database." -"datallowconn must be true\n" +"All non-template0 databases must allow connections, i.e. their\n" +"pg_database.datallowconn must be true. Your installation contains\n" +"non-template0 databases with their pg_database.datallowconn set to\n" +"false. Consider allowing connection for all non-template0 databases\n" +"or drop the databases which do not allow connections. A list of\n" +"databases with the problem is in the file:\n" +" %s" msgstr "" "Все базы, кроме template0, должны допускать подключения, то есть их свойство " -"pg_database.datallowconn должно быть true\n" +"pg_database.datallowconn должно быть true. В вашей инсталляции содержатся\n" +"базы (не считая template0), у которых pg_database.datallowconn — false.\n" +"Имеет смысл разрешить подключения для всех баз данных, кроме template0,\n" +"или удалить базы, к которым нельзя подключаться. Список баз данных\n" +"с этой проблемой содержится в файле:\n" +" %s" -#: check.c:763 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "Проверка наличия подготовленных транзакций" -#: check.c:772 +#: check.c:1185 #, c-format -msgid "The source cluster contains prepared transactions\n" -msgstr "Исходный кластер содержит подготовленные транзакции\n" +msgid "The source cluster contains prepared transactions" +msgstr "Исходный кластер содержит подготовленные транзакции" -#: check.c:774 +#: check.c:1187 #, c-format -msgid "The target cluster contains prepared transactions\n" -msgstr "Целевой кластер содержит подготовленные транзакции\n" +msgid "The target cluster contains prepared transactions" +msgstr "Целевой кластер содержит подготовленные транзакции" -#: check.c:800 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Проверка несоответствия при передаче bigint в contrib/isn" -#: check.c:861 check.c:962 check.c:1038 check.c:1095 check.c:1154 check.c:1183 -#: check.c:1301 function.c:262 version.c:278 version.c:316 version.c:460 -#, c-format -msgid "fatal\n" -msgstr "сбой\n" - -#: check.c:862 +#: check.c:1271 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -309,8 +535,7 @@ msgid "" "manually dump databases in the old cluster that use \"contrib/isn\"\n" "facilities, drop them, perform the upgrade, and then restore them. A\n" "list of the problem functions is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "В вашей инсталляции имеются функции \"contrib/isn\", задействующие тип " "biging.\n" @@ -321,537 +546,569 @@ msgstr "" "или удалить \"contrib/isn\" из старого кластера и перезапустить обновление. " "Список\n" "проблемных функций приведён в файле:\n" -" %s\n" -"\n" +" %s" -#: check.c:885 +#: check.c:1293 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Проверка пользовательских постфиксных операторов" -#: check.c:963 +#: check.c:1368 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" "supported anymore. Consider dropping the postfix operators and replacing\n" "them with prefix operators or function calls.\n" "A list of user-defined postfix operators is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "В вашей инсталляции содержатся пользовательские постфиксные операторы, " "которые\n" "теперь не поддерживаются. Их следует удалить и использовать вместо них\n" "префиксные операторы или функции.\n" "Список пользовательских постфиксных операторов приведён в файле:\n" -" %s\n" -"\n" +" %s" -#: check.c:984 +#: check.c:1392 +#, c-format +msgid "Checking for incompatible polymorphic functions" +msgstr "Проверка несовместимых полиморфных функций" + +#: check.c:1493 +#, c-format +msgid "" +"Your installation contains user-defined objects that refer to internal\n" +"polymorphic functions with arguments of type \"anyarray\" or " +"\"anyelement\".\n" +"These user-defined objects must be dropped before upgrading and restored\n" +"afterwards, changing them to refer to the new corresponding functions with\n" +"arguments of type \"anycompatiblearray\" and \"anycompatible\".\n" +"A list of the problematic objects is in the file:\n" +" %s" +msgstr "" +"В вашей инсталляции содержатся пользовательские объекты, обращающиеся\n" +"к внутренним полиморфным функциям с аргументами типа \"anyarray\" или " +"\"anyelement\".\n" +"Такие объекты необходимо удалить перед процедурой обновления и восстановить\n" +"после, изменив их так, чтобы они обращались к новым аналогичным функциям\n" +"с аргументами типа \"anycompatiblearray\" и \"anycompatible\".\n" +"Список проблемных объектов приведён в файле:\n" +" %s" + +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Проверка таблиц со свойством WITH OIDS" -#: check.c:1039 +#: check.c:1569 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" "supported anymore. Consider removing the oid column using\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "A list of tables with the problem is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "В вашей инсталляции содержатся таблицы со свойством WITH OIDS, которое " "теперь\n" "не поддерживается. Отказаться от использования столбцов oid можно так:\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "Список проблемных таблиц приведён в файле:\n" -" %s\n" -"\n" +" %s" -#: check.c:1067 +#: check.c:1596 #, c-format -msgid "Checking for system-defined composite types in user tables" -msgstr "Проверка системных составных типов в пользовательских таблицах" +msgid "Checking for roles starting with \"pg_\"" +msgstr "Проверка ролей с именами, начинающимися с \"pg_\"" -#: check.c:1096 +#: check.c:1627 #, c-format msgid "" -"Your installation contains system-defined composite type(s) in user tables.\n" -"These type OIDs are not stable across PostgreSQL versions,\n" -"so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" +"Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" +" %s" msgstr "" -"В вашей инсталляции пользовательские таблицы используют системные составные " -"типы.\n" -"OID таких типов могут различаться в разных версиях PostgreSQL, в настоящем\n" -"состоянии обновить кластер невозможно. Вы можете удалить проблемные столбцы\n" -"и перезапустить обновление. Список проблемных столбцов приведён в файле:\n" -" %s\n" -"\n" +"В вашей инсталляции имеются роли с именами, начинающимися с \"pg_\".\n" +"Префикс \"pg_\" зарезервирован для системных ролей. Пока эти роли\n" +"не будут переименованы, обновить кластер невозможно.\n" +"Список ролей с префиксом \"pg_\" приведён в файле:\n" +" %s" -#: check.c:1124 +#: check.c:1647 #, c-format -msgid "Checking for reg* data types in user tables" -msgstr "Проверка типов данных reg* в пользовательских таблицах" +msgid "Checking for user-defined encoding conversions" +msgstr "Проверка пользовательских перекодировок" -#: check.c:1155 +#: check.c:1707 #, c-format msgid "" -"Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" +"Your installation contains user-defined encoding conversions.\n" +"The conversion function parameters changed in PostgreSQL version 14\n" +"so this cluster cannot currently be upgraded. You can remove the\n" +"encoding conversions in the old cluster and restart the upgrade.\n" +"A list of user-defined encoding conversions is in the file:\n" +" %s" msgstr "" -"В вашей инсталляции пользовательские таблицы содержат один из типов reg*.\n" -"Эти типы данных ссылаются на системные OID, которые не сохраняются утилитой\n" -"pg_upgrade, так что обновление кластера в текущем состоянии невозможно. Вы\n" -"можете удалить проблемные столбцы и перезапустить обновление. Список " -"проблемных\n" -"столбцов приведён в файле:\n" -" %s\n" -"\n" +"В вашей инсталляции имеются пользовательские перекодировки.\n" +"У функций перекодировок в PostgreSQL 14 поменялись параметры, поэтому\n" +"в настоящем состоянии обновить кластер невозможно. Вы можете удалить\n" +"перекодировки в старом кластере и перезапустить обновление.\n" +"Список пользовательских перекодировок приведён в файле:\n" +" %s" -#: check.c:1177 +#: check.c:1746 #, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "Проверка несовместимого типа данных \"jsonb\"" +msgid "Checking for new cluster logical replication slots" +msgstr "Проверка слотов логической репликации в новом кластере" -#: check.c:1184 +#: check.c:1754 #, c-format -msgid "" -"Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"В вашей инсталляции таблицы используют тип данных jsonb.\n" -"Внутренний формат \"jsonb\" изменился в версии 9.4 beta, поэтому обновить " -"кластер\n" -"в текущем состоянии невозможно. Вы можете удалить проблемные столбцы и\n" -"перезапустить обновление. Список проблемных столбцов приведён в файле:\n" -" %s\n" -"\n" +msgid "could not count the number of logical replication slots" +msgstr "не удалось получить количество слотов логической репликации" -#: check.c:1206 +#: check.c:1759 #, c-format -msgid "Checking for roles starting with \"pg_\"" -msgstr "Проверка ролей с именами, начинающимися с \"pg_\"" +msgid "expected 0 logical replication slots but found %d" +msgstr "обнаружено слотов логической репликации: %d, тогда как ожидалось 0" -#: check.c:1216 +#: check.c:1769 check.c:1820 #, c-format -msgid "The source cluster contains roles starting with \"pg_\"\n" -msgstr "В исходном кластере есть роли, имена которых начинаются с \"pg_\"\n" +msgid "could not determine parameter settings on new cluster" +msgstr "не удалось получить значения параметров в новом кластере" -#: check.c:1218 +#: check.c:1774 #, c-format -msgid "The target cluster contains roles starting with \"pg_\"\n" -msgstr "В целевом кластере есть роли, имена которых начинаются с \"pg_\"\n" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "\"wal_level\" должен иметь значение \"logical\", а имеет \"%s\"" -#: check.c:1239 +#: check.c:1780 #, c-format -msgid "Checking for user-defined encoding conversions" -msgstr "Проверка пользовательских перекодировок" +msgid "" +"\"max_replication_slots\" (%d) must be greater than or equal to the number " +"of logical replication slots (%d) on the old cluster" +msgstr "" +"значение \"max_replication_slots\" (%d) должно быть больше или равно числу " +"слотов логической репликации (%d) в старом кластере" -#: check.c:1302 +#: check.c:1812 +#, c-format +msgid "Checking for new cluster configuration for subscriptions" +msgstr "Проверка конфигурации нового кластера для использования подписок" + +#: check.c:1824 #, c-format msgid "" -"Your installation contains user-defined encoding conversions.\n" -"The conversion function parameters changed in PostgreSQL version 14\n" -"so this cluster cannot currently be upgraded. You can remove the\n" -"encoding conversions in the old cluster and restart the upgrade.\n" -"A list of user-defined encoding conversions is in the file:\n" -" %s\n" -"\n" +"\"max_replication_slots\" (%d) must be greater than or equal to the number " +"of subscriptions (%d) on the old cluster" msgstr "" -"В вашей инсталляции имеются пользовательские перекодировки.\n" -"У функций перекодировок в PostgreSQL 14 поменялись параметры, поэтому\n" -"в настоящем состоянии обновить кластер невозможно. Вы можете удалить\n" -"перекодировки в старом кластере и перезапустить обновление.\n" -"Список пользовательских перекодировок приведён в файле:\n" -" %s\n" -"\n" +"значение \"max_replication_slots\" (%d) должно быть больше или равно числу " +"подписок (%d) в старом кластере" -#: check.c:1329 +#: check.c:1846 #, c-format -msgid "failed to get the current locale\n" -msgstr "не удалось получить текущую локаль\n" +msgid "Checking for valid logical replication slots" +msgstr "Проверка корректности слотов логической репликации" -#: check.c:1338 +#: check.c:1898 #, c-format -msgid "failed to get system locale name for \"%s\"\n" -msgstr "не удалось получить системное имя локали для \"%s\"\n" +msgid "" +"Your installation contains logical replication slots that cannot be " +"upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other " +"slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" +" %s" +msgstr "" +"В вашей инсталляции используются слоты логической репликации, которые " +"нельзя\n" +"обновить. Вы можете удалить неподходящие слоты и/или добиться, чтобы другие\n" +"слоты прочитали ожидающий обработки WAL, а затем перезапустить обновление.\n" +"Список проблемных слотов приведён в файле:\n" +" %s" -#: check.c:1344 +#: check.c:1922 #, c-format -msgid "failed to restore old locale \"%s\"\n" -msgstr "не удалось восстановить старую локаль \"%s\"\n" +msgid "Checking for subscription state" +msgstr "Проверка состояния подписок" -#: controldata.c:128 controldata.c:196 +#: check.c:2023 #, c-format -msgid "could not get control data using %s: %s\n" -msgstr "не удалось получить управляющие данные, выполнив %s: %s\n" +msgid "" +"Your installation contains subscriptions without origin or having relations " +"not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart " +"the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" +" %s" +msgstr "" +"В вашей инсталляции имеются подписки с отсутствующим источником или с\n" +"отношениями, находящимися не в состоянии i (инициализировано) или r " +"(готово).\n" +"Вы можете добиться завершения начальной синхронизации для всех отношений, а\n" +"затем перезапустить обновление.\n" +"Список проблемных подписок приведён в файле:\n" +" %s" + +#: controldata.c:129 controldata.c:199 +#, c-format +msgid "could not get control data using %s: %m" +msgstr "не удалось получить управляющие данные, выполнив %s: %m" #: controldata.c:139 #, c-format -msgid "%d: database cluster state problem\n" -msgstr "%d: недопустимое состояние кластера баз данных\n" +msgid "%d: database cluster state problem" +msgstr "%d: недопустимое состояние кластера баз данных" -#: controldata.c:157 +#: controldata.c:158 #, c-format msgid "" "The source cluster was shut down while in recovery mode. To upgrade, use " -"\"rsync\" as documented or shut it down as a primary.\n" +"\"rsync\" as documented or shut it down as a primary." msgstr "" "Исходный кластер был отключён в режиме восстановления. Чтобы произвести " "обновление, используйте документированный способ с rsync или отключите его в " -"режиме главного сервера.\n" +"режиме главного сервера." -#: controldata.c:159 +#: controldata.c:160 #, c-format msgid "" "The target cluster was shut down while in recovery mode. To upgrade, use " -"\"rsync\" as documented or shut it down as a primary.\n" +"\"rsync\" as documented or shut it down as a primary." msgstr "" "Целевой кластер был отключён в режиме восстановления. Чтобы произвести " "обновление, используйте документированный способ с rsync или отключите его в " -"режиме главного сервера.\n" +"режиме главного сервера." -#: controldata.c:164 +#: controldata.c:165 #, c-format -msgid "The source cluster was not shut down cleanly.\n" -msgstr "Исходный кластер не был отключён штатным образом.\n" - -#: controldata.c:166 -#, c-format -msgid "The target cluster was not shut down cleanly.\n" -msgstr "Целевой кластер не был отключён штатным образом.\n" +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "" +"Исходный кластер не был отключён штатным образом, записанное состояние: " +"\"%s\"" -#: controldata.c:177 +#: controldata.c:167 #, c-format -msgid "The source cluster lacks cluster state information:\n" -msgstr "В исходном кластере не хватает информации о состоянии кластера:\n" +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "" +"Целевой кластер не был отключён штатным образом, записанное состояние: \"%s\"" -#: controldata.c:179 +#: controldata.c:175 controldata.c:507 #, c-format -msgid "The target cluster lacks cluster state information:\n" -msgstr "В целевом кластере не хватает информации о состоянии кластера:\n" +msgid "could not get control data using %s: %s" +msgstr "не удалось получить управляющие данные, выполнив %s: %s" -#: controldata.c:209 dump.c:49 pg_upgrade.c:335 pg_upgrade.c:371 -#: relfilenode.c:243 server.c:33 util.c:79 +#: controldata.c:181 #, c-format -msgid "%s" -msgstr "%s" +msgid "The source cluster lacks cluster state information:" +msgstr "В исходном кластере не хватает информации о состоянии кластера:" -#: controldata.c:216 +#: controldata.c:183 #, c-format -msgid "%d: pg_resetwal problem\n" -msgstr "%d: проблема с выводом pg_resetwal\n" +msgid "The target cluster lacks cluster state information:" +msgstr "В целевом кластере не хватает информации о состоянии кластера:" -#: controldata.c:226 controldata.c:236 controldata.c:247 controldata.c:258 -#: controldata.c:269 controldata.c:288 controldata.c:299 controldata.c:310 -#: controldata.c:321 controldata.c:332 controldata.c:343 controldata.c:354 -#: controldata.c:357 controldata.c:361 controldata.c:371 controldata.c:383 -#: controldata.c:394 controldata.c:405 controldata.c:416 controldata.c:427 -#: controldata.c:438 controldata.c:449 controldata.c:460 controldata.c:471 -#: controldata.c:482 controldata.c:493 +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 #, c-format -msgid "%d: controldata retrieval problem\n" -msgstr "%d: проблема с получением управляющих данных\n" +msgid "%s" +msgstr "%s" -#: controldata.c:572 +#: controldata.c:220 #, c-format -msgid "The source cluster lacks some required control information:\n" -msgstr "В исходном кластере не хватает необходимой управляющей информации:\n" +msgid "%d: pg_resetwal problem" +msgstr "%d: проблема с выводом pg_resetwal" -#: controldata.c:575 +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 #, c-format -msgid "The target cluster lacks some required control information:\n" -msgstr "В целевом кластере не хватает необходимой управляющей информации:\n" +msgid "%d: controldata retrieval problem" +msgstr "%d: проблема с получением управляющих данных" -# skip-rule: capital-letter-first #: controldata.c:578 #, c-format -msgid " checkpoint next XID\n" -msgstr " следующий XID последней конт. точки\n" +msgid "The source cluster lacks some required control information:" +msgstr "В исходном кластере не хватает необходимой управляющей информации:" -# skip-rule: capital-letter-first #: controldata.c:581 #, c-format -msgid " latest checkpoint next OID\n" -msgstr " следующий OID последней конт. точки\n" +msgid "The target cluster lacks some required control information:" +msgstr "В целевом кластере не хватает необходимой управляющей информации:" # skip-rule: capital-letter-first #: controldata.c:584 #, c-format -msgid " latest checkpoint next MultiXactId\n" -msgstr " следующий MultiXactId последней конт. точки\n" +msgid " checkpoint next XID" +msgstr " следующий XID конт. точки" # skip-rule: capital-letter-first -#: controldata.c:588 +#: controldata.c:587 #, c-format -msgid " latest checkpoint oldest MultiXactId\n" -msgstr " старейший MultiXactId последней конт. точки\n" +msgid " latest checkpoint next OID" +msgstr " следующий OID последней конт. точки" # skip-rule: capital-letter-first -#: controldata.c:591 +#: controldata.c:590 #, c-format -msgid " latest checkpoint oldestXID\n" -msgstr " oldestXID последней конт. точки\n" +msgid " latest checkpoint next MultiXactId" +msgstr " следующий MultiXactId последней конт. точки" # skip-rule: capital-letter-first #: controldata.c:594 #, c-format -msgid " latest checkpoint next MultiXactOffset\n" -msgstr " следующий MultiXactOffset последней конт. точки\n" +msgid " latest checkpoint oldest MultiXactId" +msgstr " старейший MultiXactId последней конт. точки" +# skip-rule: capital-letter-first #: controldata.c:597 #, c-format -msgid " first WAL segment after reset\n" -msgstr " первый сегмент WAL после сброса\n" +msgid " latest checkpoint oldestXID" +msgstr " oldestXID последней конт. точки" +# skip-rule: capital-letter-first #: controldata.c:600 #, c-format -msgid " float8 argument passing method\n" -msgstr " метод передачи аргумента float8\n" +msgid " latest checkpoint next MultiXactOffset" +msgstr " следующий MultiXactOffset последней конт. точки" #: controldata.c:603 #, c-format -msgid " maximum alignment\n" -msgstr " максимальное выравнивание\n" +msgid " first WAL segment after reset" +msgstr " первый сегмент WAL после сброса" #: controldata.c:606 #, c-format -msgid " block size\n" -msgstr " размер блока\n" +msgid " float8 argument passing method" +msgstr " метод передачи аргумента float8" #: controldata.c:609 #, c-format -msgid " large relation segment size\n" -msgstr " размер сегмента большого отношения\n" +msgid " maximum alignment" +msgstr " максимальное выравнивание" #: controldata.c:612 #, c-format -msgid " WAL block size\n" -msgstr " размер блока WAL\n" +msgid " block size" +msgstr " размер блока" #: controldata.c:615 #, c-format -msgid " WAL segment size\n" -msgstr " размер сегмента WAL\n" +msgid " large relation segment size" +msgstr " размер сегмента большого отношения" #: controldata.c:618 #, c-format -msgid " maximum identifier length\n" -msgstr " максимальная длина идентификатора\n" +msgid " WAL block size" +msgstr " размер блока WAL" #: controldata.c:621 #, c-format -msgid " maximum number of indexed columns\n" -msgstr " максимальное число столбцов в индексе\n" +msgid " WAL segment size" +msgstr " размер сегмента WAL" #: controldata.c:624 #, c-format -msgid " maximum TOAST chunk size\n" -msgstr " максимальный размер порции TOAST\n" +msgid " maximum identifier length" +msgstr " максимальная длина идентификатора" -#: controldata.c:628 +#: controldata.c:627 #, c-format -msgid " large-object chunk size\n" -msgstr " размер порции большого объекта\n" +msgid " maximum number of indexed columns" +msgstr " максимальное число столбцов в индексе" -#: controldata.c:631 +#: controldata.c:630 #, c-format -msgid " dates/times are integers?\n" -msgstr " дата/время представлены целыми числами?\n" +msgid " maximum TOAST chunk size" +msgstr " максимальный размер порции TOAST" -#: controldata.c:635 +#: controldata.c:634 #, c-format -msgid " data checksum version\n" -msgstr " версия контрольных сумм данных\n" +msgid " large-object chunk size" +msgstr " размер порции большого объекта" #: controldata.c:637 #, c-format -msgid "Cannot continue without required control information, terminating\n" +msgid " dates/times are integers?" +msgstr " дата/время представлены целыми числами?" + +#: controldata.c:641 +#, c-format +msgid " data checksum version" +msgstr " версия контрольных сумм данных" + +#: controldata.c:643 +#, c-format +msgid "Cannot continue without required control information, terminating" msgstr "" -"Нет необходимой управляющей информации для продолжения, работа прерывается\n" +"Нет необходимой управляющей информации для продолжения, работа прерывается" -#: controldata.c:652 +#: controldata.c:658 #, c-format msgid "" -"old and new pg_controldata alignments are invalid or do not match\n" -"Likely one cluster is a 32-bit install, the other 64-bit\n" +"old and new pg_controldata alignments are invalid or do not match.\n" +"Likely one cluster is a 32-bit install, the other 64-bit" msgstr "" "старое и новое выравнивание в pg_controldata различаются или некорректны\n" -"Вероятно, один кластер установлен в 32-битной системе, а другой ~ в 64-" -"битной\n" +"Вероятно, один кластер установлен в 32-битной системе, а другой ~ в 64-битной" -#: controldata.c:656 +#: controldata.c:662 #, c-format -msgid "old and new pg_controldata block sizes are invalid or do not match\n" +msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "" -"старый и новый размер блоков в pg_controldata различаются или некорректны\n" +"старый и новый размер блоков в pg_controldata различаются или некорректны" -#: controldata.c:659 +#: controldata.c:665 #, c-format msgid "" "old and new pg_controldata maximum relation segment sizes are invalid or do " -"not match\n" +"not match" msgstr "" "старый и новый максимальный размер сегментов отношений в pg_controldata " -"различаются или некорректны\n" +"различаются или некорректны" -#: controldata.c:662 +#: controldata.c:668 #, c-format -msgid "" -"old and new pg_controldata WAL block sizes are invalid or do not match\n" +msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "" -"старый и новый размер блоков WAL в pg_controldata различаются или " -"некорректны\n" +"старый и новый размер блоков WAL в pg_controldata различаются или некорректны" -#: controldata.c:665 +#: controldata.c:671 #, c-format msgid "" -"old and new pg_controldata WAL segment sizes are invalid or do not match\n" +"old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "" "старый и новый размер сегментов WAL в pg_controldata различаются или " -"некорректны\n" +"некорректны" -#: controldata.c:668 +#: controldata.c:674 #, c-format msgid "" "old and new pg_controldata maximum identifier lengths are invalid or do not " -"match\n" +"match" msgstr "" "старая и новая максимальная длина идентификаторов в pg_controldata " -"различаются или некорректны\n" +"различаются или некорректны" -#: controldata.c:671 +#: controldata.c:677 #, c-format msgid "" "old and new pg_controldata maximum indexed columns are invalid or do not " -"match\n" +"match" msgstr "" "старый и новый максимум числа столбцов, составляющих индексы, в " -"pg_controldata различаются или некорректны\n" +"pg_controldata различаются или некорректны" -#: controldata.c:674 +#: controldata.c:680 #, c-format msgid "" "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not " -"match\n" +"match" msgstr "" "старый и новый максимальный размер порции TOAST в pg_controldata различаются " -"или некорректны\n" +"или некорректны" -#: controldata.c:679 +#: controldata.c:685 #, c-format msgid "" "old and new pg_controldata large-object chunk sizes are invalid or do not " -"match\n" +"match" msgstr "" -"старый и новый размер порции большого объекта различаются или некорректны\n" +"старый и новый размер порции большого объекта различаются или некорректны" -#: controldata.c:682 +#: controldata.c:688 #, c-format -msgid "old and new pg_controldata date/time storage types do not match\n" +msgid "old and new pg_controldata date/time storage types do not match" msgstr "" "старый и новый тип хранения даты/времени в pg_controldata различаются или " -"некорректны\n" +"некорректны" -#: controldata.c:695 +#: controldata.c:701 #, c-format -msgid "old cluster does not use data checksums but the new one does\n" +msgid "old cluster does not use data checksums but the new one does" msgstr "" "в старом кластере не применялись контрольные суммы данных, но в новом они " -"есть\n" +"есть" -#: controldata.c:698 +#: controldata.c:704 #, c-format -msgid "old cluster uses data checksums but the new one does not\n" +msgid "old cluster uses data checksums but the new one does not" msgstr "" -"в старом кластере применялись контрольные суммы данных, но в новом их нет\n" +"в старом кластере применялись контрольные суммы данных, но в новом их нет" -#: controldata.c:700 +#: controldata.c:706 #, c-format -msgid "old and new cluster pg_controldata checksum versions do not match\n" +msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "" -"старая и новая версия контрольных сумм кластера в pg_controldata " -"различаются\n" +"старая и новая версия контрольных сумм кластера в pg_controldata различаются" -#: controldata.c:711 +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "Добавление расширения \".old\" к старому файлу global/pg_control" -#: controldata.c:716 +#: controldata.c:722 #, c-format -msgid "Unable to rename %s to %s.\n" -msgstr "Не удалось переименовать %s в %s.\n" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" -#: controldata.c:719 +#: controldata.c:726 #, c-format msgid "" "\n" "If you want to start the old cluster, you will need to remove\n" "the \".old\" suffix from %s/global/pg_control.old.\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" -"started once the new cluster has been started.\n" -"\n" +"started once the new cluster has been started." msgstr "" "\n" "Если вы захотите запустить старый кластер, вам нужно будет убрать\n" "расширение \".old\" у файла %s/global/pg_control.old.\n" "Так как применялся режим \"ссылок\", работа старого кластера\n" -"после того, как будет запущен новый, не гарантируется.\n" -"\n" +"после того, как будет запущен новый, не гарантируется." #: dump.c:20 #, c-format msgid "Creating dump of global objects" msgstr "Формирование выгрузки глобальных объектов" -#: dump.c:31 +#: dump.c:32 #, c-format -msgid "Creating dump of database schemas\n" -msgstr "Формирование выгрузки схем базы данных\n" +msgid "Creating dump of database schemas" +msgstr "Формирование выгрузки схем базы данных" -#: exec.c:45 +#: exec.c:47 #, c-format -msgid "could not get pg_ctl version data using %s: %s\n" -msgstr "не удалось получить данные версии pg_ctl, выполнив %s: %s\n" +msgid "could not get pg_ctl version data using %s: %m" +msgstr "не удалось получить данные версии pg_ctl, выполнив %s: %m" #: exec.c:51 #, c-format -msgid "could not get pg_ctl version output from %s\n" -msgstr "не удалось получить версию pg_ctl из результата %s\n" +msgid "could not get pg_ctl version data using %s: %s" +msgstr "не удалось получить данные версии pg_ctl, выполнив %s: %s" -#: exec.c:105 exec.c:109 +#: exec.c:55 #, c-format -msgid "command too long\n" -msgstr "команда слишком длинная\n" +msgid "could not get pg_ctl version output from %s" +msgstr "не удалось получить версию pg_ctl из результата %s" -#: exec.c:111 util.c:37 util.c:225 +#: exec.c:112 exec.c:116 #, c-format -msgid "%s\n" -msgstr "%s\n" +msgid "command too long" +msgstr "команда слишком длинная" -#: exec.c:150 option.c:217 +#: exec.c:160 pg_upgrade.c:311 #, c-format -msgid "could not open log file \"%s\": %m\n" -msgstr "не удалось открыть файл протокола \"%s\": %m\n" +msgid "could not open log file \"%s\": %m" +msgstr "не удалось открыть файл протокола \"%s\": %m" -#: exec.c:179 +#: exec.c:192 #, c-format msgid "" "\n" @@ -860,432 +1117,382 @@ msgstr "" "\n" "*ошибка*" -#: exec.c:182 +#: exec.c:195 #, c-format -msgid "There were problems executing \"%s\"\n" -msgstr "При выполнении \"%s\" возникли проблемы\n" +msgid "There were problems executing \"%s\"" +msgstr "При выполнении \"%s\" возникли проблемы" -#: exec.c:185 +#: exec.c:198 #, c-format msgid "" "Consult the last few lines of \"%s\" or \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "" "Чтобы понять причину ошибки, просмотрите последние несколько строк\n" -"файла \"%s\" или \"%s\".\n" +"файла \"%s\" или \"%s\"." -#: exec.c:190 +#: exec.c:203 #, c-format msgid "" "Consult the last few lines of \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "" "Чтобы понять причину ошибки, просмотрите последние несколько строк\n" -"файла \"%s\".\n" +"файла \"%s\"." -#: exec.c:205 option.c:226 +#: exec.c:218 pg_upgrade.c:321 #, c-format -msgid "could not write to log file \"%s\": %m\n" -msgstr "не удалось записать в файл протокола \"%s\": %m\n" +msgid "could not write to log file \"%s\": %m" +msgstr "не удалось записать в файл протокола \"%s\": %m" -#: exec.c:231 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s\n" -msgstr "не удалось открыть файл \"%s\" для чтения: %s\n" +msgid "could not open file \"%s\" for reading: %m" +msgstr "не удалось открыть файл \"%s\" для чтения: %m" -#: exec.c:258 +#: exec.c:270 #, c-format -msgid "You must have read and write access in the current directory.\n" -msgstr "У вас должны быть права на чтение и запись в текущем каталоге.\n" +msgid "You must have read and write access in the current directory." +msgstr "У вас должны быть права на чтение и запись в текущем каталоге." -#: exec.c:311 exec.c:377 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s\n" -msgstr "проверка существования \"%s\" не пройдена: %s\n" +msgid "check for \"%s\" failed: %m" +msgstr "файл \"%s\" не прошёл проверку: %m" -#: exec.c:314 exec.c:380 +#: exec.c:326 exec.c:392 #, c-format -msgid "\"%s\" is not a directory\n" -msgstr "\"%s\" не является каталогом\n" +msgid "\"%s\" is not a directory" +msgstr "\"%s\" не является каталогом" -#: exec.c:430 +#: exec.c:444 #, c-format -msgid "check for \"%s\" failed: not a regular file\n" -msgstr "программа \"%s\" не прошла проверку: это не обычный файл\n" +msgid "check for \"%s\" failed: cannot execute" +msgstr "программа \"%s\" не прошла проверку: ошибка выполнения" -#: exec.c:433 -#, c-format -msgid "check for \"%s\" failed: cannot execute (permission denied)\n" -msgstr "программа \"%s\" не прошла проверку: ошибка выполнения (нет доступа)\n" - -#: exec.c:439 -#, c-format -msgid "check for \"%s\" failed: cannot execute\n" -msgstr "программа \"%s\" не прошла проверку: ошибка выполнения\n" - -#: exec.c:449 +#: exec.c:454 #, c-format msgid "" -"check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"\n" +"check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" msgstr "" "программа \"%s\" не прошла проверку: получена некорректная версия \"%s\", " -"ожидалась \"%s\"\n" +"ожидалась \"%s\"" -#: file.c:43 file.c:61 +#: file.c:44 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "ошибка при клонировании отношения \"%s.%s\" (из \"%s\" в \"%s\"): %s\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "ошибка при клонировании отношения \"%s.%s\" (из \"%s\" в \"%s\"): %m" -#: file.c:50 +#: file.c:51 #, c-format -msgid "" -"error while cloning relation \"%s.%s\": could not open file \"%s\": %s\n" +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" msgstr "" "ошибка при клонировании отношения \"%s.%s\": не удалось открыть файл \"%s\": " -"%s\n" +"%m" -#: file.c:55 +#: file.c:56 #, c-format msgid "" -"error while cloning relation \"%s.%s\": could not create file \"%s\": %s\n" +"error while cloning relation \"%s.%s\": could not create file \"%s\": %m" msgstr "" "ошибка при клонировании отношения \"%s.%s\": не удалось создать файл \"%s\": " -"%s\n" +"%m" -#: file.c:87 file.c:190 +#: file.c:65 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not open file \"%s\": %s\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "ошибка при клонировании отношения \"%s.%s\" (из \"%s\" в \"%s\"): %s" + +#: file.c:91 file.c:160 file.c:233 +#, c-format +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" msgstr "" "ошибка при копировании отношения \"%s.%s\": не удалось открыть файл \"%s\": " -"%s\n" +"%m" -#: file.c:92 file.c:199 +#: file.c:96 file.c:165 file.c:242 #, c-format msgid "" -"error while copying relation \"%s.%s\": could not create file \"%s\": %s\n" +"error while copying relation \"%s.%s\": could not create file \"%s\": %m" msgstr "" "ошибка при копировании отношения \"%s.%s\": не удалось создать файл \"%s\": " -"%s\n" +"%m" -#: file.c:106 file.c:223 +#: file.c:110 file.c:266 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not read file \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" msgstr "" -"ошибка при копировании отношения \"%s.%s\": не удалось прочитать файл \"%s" -"\": %s\n" +"ошибка при копировании отношения \"%s.%s\": не удалось прочитать файл " +"\"%s\": %m" -#: file.c:118 file.c:301 +#: file.c:122 file.c:344 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not write file \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" msgstr "" -"ошибка при копировании отношения \"%s.%s\": не удалось записать в файл \"%s" -"\": %s\n" +"ошибка при копировании отношения \"%s.%s\": не удалось записать файл \"%s\": " +"%m" -#: file.c:132 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "ошибка при копировании отношения \"%s.%s\" (из \"%s\" в \"%s\"): %s\n" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "ошибка при копировании отношения \"%s.%s\" (из \"%s\" в \"%s\"): %m" -#: file.c:151 +#: file.c:172 #, c-format msgid "" -"error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" +"error while copying relation \"%s.%s\": could not copy file range from " +"\"%s\" to \"%s\": %m" msgstr "" -"ошибка при создании ссылки для отношения \"%s.%s\" (из \"%s\" в \"%s\"): %s\n" +"ошибка при копировании отношения \"%s.%s\": не удалось скопировать фрагмент " +"файла \"%s\" в \"%s\": %m" #: file.c:194 #, c-format -msgid "" -"error while copying relation \"%s.%s\": could not stat file \"%s\": %s\n" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "" +"ошибка при создании ссылки для отношения \"%s.%s\" (из \"%s\" в \"%s\"): %m" + +#: file.c:237 +#, c-format +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" msgstr "" "ошибка при копировании отношения \"%s.%s\": не удалось получить информацию о " -"файле \"%s\": %s\n" +"файле \"%s\": %m" -#: file.c:226 +#: file.c:269 #, c-format msgid "" -"error while copying relation \"%s.%s\": partial page found in file \"%s\"\n" +"error while copying relation \"%s.%s\": partial page found in file \"%s\"" msgstr "" "ошибка при копировании отношения \"%s.%s\": в файле \"%s\" обнаружена " -"неполная страница\n" +"неполная страница" -#: file.c:328 file.c:345 +#: file.c:371 file.c:387 #, c-format -msgid "could not clone file between old and new data directories: %s\n" -msgstr "не удалось клонировать файл из старого каталога данных в новый: %s\n" +msgid "could not clone file between old and new data directories: %m" +msgstr "не удалось клонировать файл из старого каталога данных в новый: %m" -#: file.c:341 +#: file.c:383 file.c:420 #, c-format -msgid "could not create file \"%s\": %s\n" -msgstr "не удалось создать файл \"%s\": %s\n" +msgid "could not create file \"%s\": %m" +msgstr "не удалось создать файл \"%s\": %m" -#: file.c:352 +#: file.c:393 #, c-format -msgid "file cloning not supported on this platform\n" -msgstr "клонирование файлов не поддерживается в этой ОС\n" +msgid "file cloning not supported on this platform" +msgstr "клонирование файлов не поддерживается в этой ОС" -#: file.c:369 +#: file.c:424 #, c-format -msgid "" -"could not create hard link between old and new data directories: %s\n" -"In link mode the old and new data directories must be on the same file " -"system.\n" +msgid "could not copy file range between old and new data directories: %m" msgstr "" -"не удалось создать жёсткую ссылку между старым и новым каталогами данных: " -"%s\n" -"В режиме \"ссылок\" старый и новый каталоги данных должны находиться в одной " -"файловой системе.\n" - -#: function.c:114 -#, c-format -msgid "" -"\n" -"The old cluster has a \"plpython_call_handler\" function defined\n" -"in the \"public\" schema which is a duplicate of the one defined\n" -"in the \"pg_catalog\" schema. You can confirm this by executing\n" -"in psql:\n" -"\n" -" \\df *.plpython_call_handler\n" -"\n" -"The \"public\" schema version of this function was created by a\n" -"pre-8.1 install of plpython, and must be removed for pg_upgrade\n" -"to complete because it references a now-obsolete \"plpython\"\n" -"shared object file. You can remove the \"public\" schema version\n" -"of this function by running the following command:\n" -"\n" -" DROP FUNCTION public.plpython_call_handler()\n" -"\n" -"in each affected database:\n" -"\n" -msgstr "" -"\n" -"В старом кластере имеется функция \"plpython_call_handler\",\n" -"определённая в схеме \"public\", представляющая собой копию функции,\n" -"определённой в схеме \"pg_catalog\". Вы можете убедиться в этом,\n" -"выполнив в psql:\n" -"\n" -" \\df *.plpython_call_handler\n" -"\n" -"Версия этой функции в схеме \"public\" была создана инсталляцией\n" -"plpython версии до 8.1 и должна быть удалена для завершения процедуры\n" -"pg_upgrade, так как она ссылается на ставший устаревшим\n" -"разделяемый объектный файл \"plpython\". Вы можете удалить версию этой " -"функции\n" -"из схемы \"public\", выполнив следующую команду:\n" -"\n" -" DROP FUNCTION public.plpython_call_handler()\n" -"\n" -"в каждой затронутой базе данных:\n" -"\n" +"не удалось скопировать фрагмент файла из старого каталога данных в новый: %m" -#: function.c:132 +#: file.c:430 #, c-format -msgid " %s\n" -msgstr " %s\n" +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range не поддерживается в этой ОС" -#: function.c:142 +#: file.c:447 #, c-format -msgid "Remove the problem functions from the old cluster to continue.\n" -msgstr "Удалите проблемные функции из старого кластера для продолжения.\n" +msgid "" +"could not create hard link between old and new data directories: %m\n" +"In link mode the old and new data directories must be on the same file " +"system." +msgstr "" +"не удалось создать жёсткую ссылку между старым и новым каталогами данных: " +"%m\n" +"В режиме \"ссылок\" старый и новый каталоги данных должны находиться в одной " +"файловой системе." -#: function.c:189 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "Проверка наличия требуемых библиотек" -#: function.c:242 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "загрузить библиотеку \"%s\" не удалось: %s" -#: function.c:253 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "В базе данных: %s\n" -#: function.c:263 +#: function.c:211 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" "new installation. You can add these libraries to the new installation,\n" "or remove the functions using them from the old installation. A list of\n" "problem libraries is in the file:\n" -" %s\n" -"\n" +" %s" msgstr "" "В вашей инсталляции есть ссылки на загружаемые библиотеки, отсутствующие\n" "в новой инсталляции. Вы можете добавить эти библиотеки в новую инсталляцию\n" "или удалить функции, использующие их, из старой. Список проблемных\n" "библиотек приведён в файле:\n" -" %s\n" -"\n" +" %s" -#: info.c:131 +#: info.c:128 #, c-format msgid "" -"Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s" -"\", new name \"%s.%s\"\n" +"Relation names for OID %u in database \"%s\" do not match: old name \"%s." +"%s\", new name \"%s.%s\"" msgstr "" "Имена отношения с OID %u в базе данных \"%s\" различаются: старое имя - \"%s." -"%s\", новое - \"%s.%s\"\n" +"%s\", новое - \"%s.%s\"" -#: info.c:151 +#: info.c:148 #, c-format -msgid "Failed to match up old and new tables in database \"%s\"\n" -msgstr "Не удалось сопоставить старые таблицы с новыми в базе данных \"%s\"\n" +msgid "Failed to match up old and new tables in database \"%s\"" +msgstr "Не удалось сопоставить старые таблицы с новыми в базе данных \"%s\"" -#: info.c:240 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " это индекс в \"%s.%s\"" -#: info.c:250 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " это индекс в отношении с OID %u" -#: info.c:262 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " это TOAST-таблица для \"%s.%s\"" -#: info.c:270 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " это TOAST-таблица для отношения с OID %u" -#: info.c:274 +#: info.c:263 #, c-format msgid "" -"No match found in old cluster for new relation with OID %u in database \"%s" -"\": %s\n" +"No match found in old cluster for new relation with OID %u in database " +"\"%s\": %s" msgstr "" "В старом кластере не нашлось соответствия для нового отношения с OID %u в " -"базе данных \"%s\": %s\n" +"базе данных \"%s\": %s" -#: info.c:277 +#: info.c:266 #, c-format msgid "" -"No match found in new cluster for old relation with OID %u in database \"%s" -"\": %s\n" +"No match found in new cluster for old relation with OID %u in database " +"\"%s\": %s" msgstr "" "В новом кластере не нашлось соответствия для старого отношения с OID %u в " -"базе данных \"%s\": %s\n" - -#: info.c:289 -#, c-format -msgid "mappings for database \"%s\":\n" -msgstr "отображения для базы данных \"%s\":\n" - -#: info.c:292 -#, c-format -msgid "%s.%s: %u to %u\n" -msgstr "%s.%s: %u в %u\n" +"базе данных \"%s\": %s" -#: info.c:297 info.c:633 +#: info.c:300 #, c-format msgid "" "\n" -"\n" +"source databases:" msgstr "" "\n" -"\n" +"исходные базы данных:" -#: info.c:322 +#: info.c:302 #, c-format msgid "" "\n" -"source databases:\n" +"target databases:" msgstr "" "\n" -"исходные базы данных:\n" +"целевые базы данных:" -#: info.c:324 +#: info.c:346 #, c-format -msgid "" -"\n" -"target databases:\n" -msgstr "" -"\n" -"целевые базы данных:\n" +msgid "template0 not found" +msgstr "база template0 не найдена" + +#: info.c:805 +#, c-format +msgid "Database: \"%s\"" +msgstr "База данных: \"%s\"" -#: info.c:631 +#: info.c:818 #, c-format -msgid "Database: %s\n" -msgstr "База данных: %s\n" +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "имя_отношения: \"%s.%s\", oid_отношения: %u, табл_пространство: %s\"" -#: info.c:644 +#: info.c:832 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s\n" -msgstr "имя_отношения: %s.%s: oid_отношения: %u табл_пространство: %s\n" +msgid "Logical replication slots in the database:" +msgstr "Слоты логической репликации в базе данных:" -#: option.c:102 +#: info.c:838 #, c-format -msgid "%s: cannot be run as root\n" -msgstr "%s: программу не должен запускать root\n" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "слот: \"%s\", модуль вывода: \"%s\", двухфазный: %s" -#: option.c:170 +#: option.c:105 #, c-format -msgid "invalid old port number\n" -msgstr "неверный старый номер порта\n" +msgid "%s: cannot be run as root" +msgstr "%s: программу не должен запускать root" -#: option.c:175 +#: option.c:172 #, c-format -msgid "invalid new port number\n" -msgstr "неверный новый номер порта\n" +msgid "invalid old port number" +msgstr "неверный старый номер порта" -#: option.c:207 +#: option.c:177 +#, c-format +msgid "invalid new port number" +msgstr "неверный новый номер порта" + +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Для дополнительной информации попробуйте \"%s --help\".\n" -#: option.c:214 +#: option.c:223 #, c-format -msgid "too many command-line arguments (first is \"%s\")\n" -msgstr "слишком много аргументов командной строки (первый: \"%s\")\n" +msgid "too many command-line arguments (first is \"%s\")" +msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: option.c:220 +#: option.c:229 #, c-format -msgid "Running in verbose mode\n" -msgstr "Программа запущена в режиме подробных сообщений\n" +msgid "Running in verbose mode" +msgstr "Программа запущена в режиме подробных сообщений" -#: option.c:251 +#: option.c:247 msgid "old cluster binaries reside" msgstr "расположение исполняемых файлов старого кластера" -#: option.c:253 +#: option.c:249 msgid "new cluster binaries reside" msgstr "расположение исполняемых файлов нового кластера" -#: option.c:255 +#: option.c:251 msgid "old cluster data resides" msgstr "расположение данных старого кластера" -#: option.c:257 +#: option.c:253 msgid "new cluster data resides" msgstr "расположение данных нового кластера" -#: option.c:259 +#: option.c:255 msgid "sockets will be created" msgstr "расположение сокетов" -#: option.c:276 option.c:374 +#: option.c:272 option.c:374 #, c-format -msgid "could not determine current directory\n" -msgstr "не удалось определить текущий каталог\n" +msgid "could not determine current directory" +msgstr "не удалось определить текущий каталог" -#: option.c:279 +#: option.c:275 #, c-format msgid "" -"cannot run pg_upgrade from inside the new cluster data directory on Windows\n" +"cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "" -"в Windows нельзя запустить pg_upgrade внутри каталога данных нового " -"кластера\n" +"в Windows нельзя запустить pg_upgrade внутри каталога данных нового кластера" -#: option.c:288 +#: option.c:284 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1294,12 +1501,12 @@ msgstr "" "pg_upgrade обновляет кластер PostgreSQL до другой основной версии.\n" "\n" -#: option.c:289 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: option.c:290 +#: option.c:286 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1308,18 +1515,18 @@ msgstr "" " pg_upgrade [ПАРАМЕТР]...\n" "\n" -#: option.c:291 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "Параметры:\n" -#: option.c:292 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr "" " -b, --old-bindir=КАТ_BIN каталог исполняемых файлов старого кластера\n" -#: option.c:293 +#: option.c:289 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1328,7 +1535,7 @@ msgstr "" " -B, --new-bindir=КАТ_BIN каталог исполняемых файлов нового кластера\n" " (по умолчанию каталог программы pg_upgrade)\n" -#: option.c:295 +#: option.c:291 #, c-format msgid "" " -c, --check check clusters only, don't change any data\n" @@ -1336,17 +1543,17 @@ msgstr "" " -c, --check только проверить кластеры, не меняя никакие " "данные\n" -#: option.c:296 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" -msgstr " -d, --old-datadir=КАТ_DATA каталог данных старого кластера\n" +msgstr " -d, --old-datadir=КАТ_ДАННЫХ каталог данных старого кластера\n" -#: option.c:297 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" -msgstr " -D, --new-datadir=КАТ_DATA каталог данных нового кластера\n" +msgstr " -D, --new-datadir=КАТ_ДАННЫХ каталог данных нового кластера\n" -#: option.c:298 +#: option.c:294 #, c-format msgid "" " -j, --jobs=NUM number of simultaneous processes or threads " @@ -1356,7 +1563,7 @@ msgstr "" "или\n" " потоков\n" -#: option.c:299 +#: option.c:295 #, c-format msgid "" " -k, --link link instead of copying files to new " @@ -1366,7 +1573,16 @@ msgstr "" "файлов\n" " в новый кластер\n" -#: option.c:300 +#: option.c:296 +#, c-format +msgid "" +" -N, --no-sync do not wait for changes to be written safely " +"to disk\n" +msgstr "" +" -N, --no-sync не ждать завершения сохранения данных на " +"диске\n" + +#: option.c:297 #, c-format msgid "" " -o, --old-options=OPTIONS old cluster options to pass to the server\n" @@ -1374,7 +1590,7 @@ msgstr "" " -o, --old-options=ПАРАМЕТРЫ параметры старого кластера, передаваемые " "серверу\n" -#: option.c:301 +#: option.c:298 #, c-format msgid "" " -O, --new-options=OPTIONS new cluster options to pass to the server\n" @@ -1382,21 +1598,21 @@ msgstr "" " -O, --new-options=ПАРАМЕТРЫ параметры нового кластера, передаваемые " "серверу\n" -#: option.c:302 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr "" " -p, --old-port=ПОРТ номер порта старого кластера (по умолчанию " "%d)\n" -#: option.c:303 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr "" " -P, --new-port=ПОРТ номер порта нового кластера (по умолчанию " "%d)\n" -#: option.c:304 +#: option.c:301 #, c-format msgid "" " -r, --retain retain SQL and log files after success\n" @@ -1404,7 +1620,7 @@ msgstr "" " -r, --retain сохранить файлы журналов и SQL в случае " "успеха\n" -#: option.c:305 +#: option.c:302 #, c-format msgid "" " -s, --socketdir=DIR socket directory to use (default current " @@ -1412,27 +1628,27 @@ msgid "" msgstr "" " -s, --socketdir=КАТАЛОГ каталог сокетов (по умолчанию текущий)\n" -#: option.c:306 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr "" -" -U, --username=ИМЯ суперпользователь кластера (по умолчанию \"%s" -"\")\n" +" -U, --username=ИМЯ суперпользователь кластера (по умолчанию " +"\"%s\")\n" -#: option.c:307 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr "" " -v, --verbose включить вывод подробных внутренних " "сообщений\n" -#: option.c:308 +#: option.c:305 #, c-format msgid "" " -V, --version display version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: option.c:309 +#: option.c:306 #, c-format msgid "" " --clone clone instead of copying files to new " @@ -1441,6 +1657,27 @@ msgstr "" " --clone клонировать, а не копировать файлы в новый " "кластер\n" +#: option.c:307 +#, c-format +msgid " --copy copy files to new cluster (default)\n" +msgstr "" +" --copy копировать файлы в новый кластер (по " +"умолчанию)\n" + +#: option.c:308 +#, c-format +msgid "" +" --copy-file-range copy files to new cluster with " +"copy_file_range\n" +msgstr "" +" --copy-file-range копировать файлы в новый кластер, используя\n" +" функцию copy_file_range\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=МЕТОД метод синхронизации файлов с ФС\n" + #: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" @@ -1541,254 +1778,291 @@ msgstr "Домашняя страница %s: <%s>\n" #, c-format msgid "" "You must identify the directory where the %s.\n" -"Please use the %s command-line option or the %s environment variable.\n" +"Please use the %s command-line option or the %s environment variable." msgstr "" "Вы должны указать каталог, где находится %s.\n" "Воспользуйтесь для этого ключом командной строки %s или переменной окружения " -"%s.\n" +"%s." -#: option.c:432 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Поиск фактического каталога данных для исходного кластера" -#: option.c:434 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Поиск фактического каталога данных для целевого кластера" -#: option.c:446 +#: option.c:448 #, c-format -msgid "could not get data directory using %s: %s\n" -msgstr "не удалось получить каталог данных, выполнив %s: %s\n" +msgid "could not get data directory using %s: %m" +msgstr "не удалось получить каталог данных, выполнив %s: %m" -#: option.c:505 +#: option.c:452 #, c-format -msgid "could not read line %d from file \"%s\": %s\n" -msgstr "не удалось прочитать строку %d из файла \"%s\": %s\n" +msgid "could not get data directory using %s: %s" +msgstr "не удалось получить каталог данных, выполнив %s: %s" -#: option.c:522 +#: option.c:500 #, c-format -msgid "user-supplied old port number %hu corrected to %hu\n" -msgstr "заданный пользователем старый номер порта %hu изменён на %hu\n" +msgid "could not read line %d from file \"%s\": %m" +msgstr "не удалось прочитать строку %d из файла \"%s\": %m" -#: parallel.c:127 parallel.c:238 +#: option.c:517 #, c-format -msgid "could not create worker process: %s\n" -msgstr "не удалось создать рабочий процесс: %s\n" +msgid "user-supplied old port number %hu corrected to %hu" +msgstr "заданный пользователем старый номер порта %hu изменён на %hu" -#: parallel.c:146 parallel.c:259 +#: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker thread: %s\n" -msgstr "не удалось создать рабочий поток: %s\n" +msgid "could not create worker process: %m" +msgstr "не удалось создать рабочий процесс: %m" -#: parallel.c:300 +#: parallel.c:143 parallel.c:253 #, c-format -msgid "%s() failed: %s\n" -msgstr "ошибка в %s(): %s\n" +msgid "could not create worker thread: %m" +msgstr "не удалось создать рабочий поток: %m" -#: parallel.c:304 +#: parallel.c:294 #, c-format -msgid "child process exited abnormally: status %d\n" -msgstr "дочерний процесс завершился нештатно с ошибкой %d\n" +msgid "%s() failed: %m" +msgstr "ошибка в %s(): %m" -#: parallel.c:319 +#: parallel.c:298 #, c-format -msgid "child worker exited abnormally: %s\n" -msgstr "дочерний процесс завершился аварийно: %s\n" +msgid "child process exited abnormally: status %d" +msgstr "дочерний процесс завершился нештатно с ошибкой %d" -#: pg_upgrade.c:107 +#: parallel.c:313 #, c-format -msgid "could not read permissions of directory \"%s\": %s\n" -msgstr "не удалось считать права на каталог \"%s\": %s\n" +msgid "child worker exited abnormally: %m" +msgstr "дочерний процесс завершился аварийно: %m" -#: pg_upgrade.c:122 +#: pg_upgrade.c:115 +#, c-format +msgid "could not read permissions of directory \"%s\": %m" +msgstr "не удалось прочитать права на каталог \"%s\": %m" + +#: pg_upgrade.c:147 #, c-format msgid "" "\n" "Performing Upgrade\n" -"------------------\n" +"------------------" msgstr "" "\n" "Выполнение обновления\n" -"---------------------\n" +"---------------------" -#: pg_upgrade.c:165 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "Установка следующего OID для нового кластера" -#: pg_upgrade.c:172 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "Синхронизация каталога данных с ФС" -#: pg_upgrade.c:183 +#: pg_upgrade.c:230 #, c-format msgid "" "\n" "Upgrade Complete\n" -"----------------\n" +"----------------" msgstr "" "\n" "Обновление завершено\n" -"--------------------\n" +"--------------------" -#: pg_upgrade.c:216 +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 +#, c-format +msgid "directory path for new cluster is too long" +msgstr "путь к каталогу данных нового кластера слишком длинный" + +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не удалось создать каталог \"%s\": %m" + +#: pg_upgrade.c:352 #, c-format -msgid "%s: could not find own program executable\n" -msgstr "%s: не удалось найти свой исполняемый файл\n" +msgid "%s: could not find own program executable" +msgstr "%s: не удалось найти свой исполняемый файл" -#: pg_upgrade.c:242 +#: pg_upgrade.c:378 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "" "Видимо, запущен процесс postmaster, обслуживающий старый кластер.\n" -"Остановите его и попробуйте ещё раз.\n" +"Остановите его и попробуйте ещё раз." -#: pg_upgrade.c:255 +#: pg_upgrade.c:391 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "" "Видимо, запущен процесс postmaster, обслуживающий новый кластер.\n" -"Остановите его и попробуйте ещё раз.\n" +"Остановите его и попробуйте ещё раз." -#: pg_upgrade.c:269 +#: pg_upgrade.c:413 +#, c-format +msgid "Setting locale and encoding for new cluster" +msgstr "Установка локали и кодировки для нового кластера" + +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Анализ всех строк в новом кластере" -#: pg_upgrade.c:282 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Замораживание всех строк в новом кластере" -#: pg_upgrade.c:302 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Восстановление глобальных объектов в новом кластере" -#: pg_upgrade.c:317 +#: pg_upgrade.c:538 #, c-format -msgid "Restoring database schemas in the new cluster\n" -msgstr "Восстановление схем баз данных в новом кластере\n" +msgid "Restoring database schemas in the new cluster" +msgstr "Восстановление схем баз данных в новом кластере" -#: pg_upgrade.c:421 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "Удаление файлов из нового каталога %s" -#: pg_upgrade.c:425 +#: pg_upgrade.c:666 #, c-format -msgid "could not delete directory \"%s\"\n" -msgstr "ошибка при удалении каталога \"%s\"\n" +msgid "could not delete directory \"%s\"" +msgstr "ошибка при удалении каталога \"%s\"" -#: pg_upgrade.c:444 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "Копирование старого каталога %s на новый сервер" -#: pg_upgrade.c:470 +#: pg_upgrade.c:711 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Установка старейшего OID для нового кластера" -#: pg_upgrade.c:478 +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "" "Установка следующего идентификатора транзакции и эпохи для нового кластера" -#: pg_upgrade.c:508 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "" "Установка следующего идентификатора и смещения мультитранзакции для нового " "кластера" -#: pg_upgrade.c:532 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Установка старейшего идентификатора мультитранзакции в новом кластере" -#: pg_upgrade.c:552 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "Сброс архивов WAL" -#: pg_upgrade.c:595 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Установка счётчиков frozenxid и minmxid в новом кластере" -#: pg_upgrade.c:597 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Установка счётчика minmxid в новом кластере" -#: relfilenode.c:35 +#: pg_upgrade.c:929 +#, c-format +msgid "Restoring logical replication slots in the new cluster" +msgstr "Восстановление слотов логической репликации в новом кластере" + +#: relfilenumber.c:35 #, c-format -msgid "Cloning user relation files\n" -msgstr "Клонирование файлов пользовательских отношений\n" +msgid "Cloning user relation files" +msgstr "Клонирование файлов пользовательских отношений" -#: relfilenode.c:38 +#: relfilenumber.c:38 #, c-format -msgid "Copying user relation files\n" -msgstr "Копирование файлов пользовательских отношений\n" +msgid "Copying user relation files" +msgstr "Копирование файлов пользовательских отношений" -#: relfilenode.c:41 +#: relfilenumber.c:41 #, c-format -msgid "Linking user relation files\n" -msgstr "Подключение файлов пользовательских отношений ссылками\n" +msgid "Copying user relation files with copy_file_range" +msgstr "" +"Копирование файлов пользовательских отношений с помощью copy_file_range" + +#: relfilenumber.c:44 +#, c-format +msgid "Linking user relation files" +msgstr "Подключение файлов пользовательских отношений ссылками" -#: relfilenode.c:115 +#: relfilenumber.c:118 #, c-format -msgid "old database \"%s\" not found in the new cluster\n" -msgstr "старая база данных \"%s\" не найдена в новом кластере\n" +msgid "old database \"%s\" not found in the new cluster" +msgstr "старая база данных \"%s\" не найдена в новом кластере" -#: relfilenode.c:230 +#: relfilenumber.c:221 #, c-format msgid "" -"error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s\n" +"error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" msgstr "" -"ошибка при проверке существования файла отношения \"%s.%s\" (перенос \"%s\" " -"в \"%s\"): %s\n" +"ошибка при проверке существования файла \"%s.%s\" (перенос \"%s\" в \"%s\"): " +"%m" + +#: relfilenumber.c:238 +#, c-format +msgid "rewriting \"%s\" to \"%s\"" +msgstr "переписывание \"%s\" в \"%s\"" -#: relfilenode.c:248 +#: relfilenumber.c:246 #, c-format -msgid "rewriting \"%s\" to \"%s\"\n" -msgstr "переписывание \"%s\" в \"%s\"\n" +msgid "cloning \"%s\" to \"%s\"" +msgstr "клонирование \"%s\" в \"%s\"" -#: relfilenode.c:256 +#: relfilenumber.c:251 #, c-format -msgid "cloning \"%s\" to \"%s\"\n" -msgstr "клонирование \"%s\" в \"%s\"\n" +msgid "copying \"%s\" to \"%s\"" +msgstr "копирование \"%s\" в \"%s\"" -#: relfilenode.c:261 +#: relfilenumber.c:256 #, c-format -msgid "copying \"%s\" to \"%s\"\n" -msgstr "копирование \"%s\" в \"%s\"\n" +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "копирование \"%s\" в \"%s\" с помощью copy_file_range" -#: relfilenode.c:266 +#: relfilenumber.c:261 #, c-format -msgid "linking \"%s\" to \"%s\"\n" -msgstr "создание ссылки на \"%s\" в \"%s\"\n" +msgid "linking \"%s\" to \"%s\"" +msgstr "создание ссылки на \"%s\" в \"%s\"" -#: server.c:38 server.c:142 util.c:135 util.c:165 +#: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" msgstr "Ошибка, выполняется выход\n" -#: server.c:132 +#: server.c:133 #, c-format -msgid "executing: %s\n" -msgstr "выполняется: %s\n" +msgid "executing: %s" +msgstr "выполняется: %s" -#: server.c:138 +#: server.c:139 #, c-format msgid "" "SQL command failed\n" @@ -1799,17 +2073,17 @@ msgstr "" "%s\n" "%s" -#: server.c:168 +#: server.c:169 #, c-format -msgid "could not open version file \"%s\": %m\n" -msgstr "не удалось открыть файл с версией \"%s\": %m\n" +msgid "could not open version file \"%s\": %m" +msgstr "не удалось открыть файл с версией \"%s\": %m" -#: server.c:172 +#: server.c:173 #, c-format -msgid "could not parse version file \"%s\"\n" -msgstr "не удалось разобрать файл с версией \"%s\"\n" +msgid "could not parse version file \"%s\"" +msgstr "не удалось разобрать файл с версией \"%s\"" -#: server.c:298 +#: server.c:310 #, c-format msgid "" "\n" @@ -1818,217 +2092,117 @@ msgstr "" "\n" "%s" -#: server.c:302 +#: server.c:314 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" -"%s\n" +"%s" msgstr "" "не удалось подключиться к главному процессу исходного сервера, запущенному " "командой:\n" -"%s\n" +"%s" -#: server.c:306 +#: server.c:318 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" -"%s\n" +"%s" msgstr "" "не удалось подключиться к главному процессу целевого сервера, запущенному " "командой:\n" -"%s\n" +"%s" -#: server.c:320 +#: server.c:332 #, c-format -msgid "pg_ctl failed to start the source server, or connection failed\n" +msgid "pg_ctl failed to start the source server, or connection failed" msgstr "" "программа pg_ctl не смогла запустить исходный сервер, либо к нему не удалось " -"подключиться\n" +"подключиться" -#: server.c:322 +#: server.c:334 #, c-format -msgid "pg_ctl failed to start the target server, or connection failed\n" +msgid "pg_ctl failed to start the target server, or connection failed" msgstr "" "программа pg_ctl не смогла запустить целевой сервер, либо к нему не удалось " -"подключиться\n" +"подключиться" -#: server.c:367 +#: server.c:379 #, c-format -msgid "out of memory\n" -msgstr "нехватка памяти\n" +msgid "out of memory" +msgstr "нехватка памяти" -#: server.c:380 +#: server.c:392 #, c-format -msgid "libpq environment variable %s has a non-local server value: %s\n" -msgstr "в переменной окружения для libpq %s задано не локальное значение: %s\n" +msgid "libpq environment variable %s has a non-local server value: %s" +msgstr "" +"в переменной окружения %s для libpq указан адрес не локального сервера: %s" #: tablespace.c:28 #, c-format msgid "" "Cannot upgrade to/from the same system catalog version when\n" -"using tablespaces.\n" +"using tablespaces." msgstr "" "Обновление в рамках одной версии системного каталога невозможно,\n" -"если используются табличные пространства.\n" +"если используются табличные пространства." -#: tablespace.c:86 +#: tablespace.c:83 #, c-format -msgid "tablespace directory \"%s\" does not exist\n" -msgstr "каталог табличного пространства \"%s\" не существует\n" +msgid "tablespace directory \"%s\" does not exist" +msgstr "каталог табличного пространства \"%s\" не существует" -#: tablespace.c:90 +#: tablespace.c:87 #, c-format -msgid "could not stat tablespace directory \"%s\": %s\n" +msgid "could not stat tablespace directory \"%s\": %m" msgstr "" -"не удалось получить информацию о каталоге табличного пространства \"%s\": " -"%s\n" - -#: tablespace.c:95 -#, c-format -msgid "tablespace path \"%s\" is not a directory\n" -msgstr "путь табличного пространства \"%s\" не указывает на каталог\n" +"не удалось получить информацию о каталоге табличного пространства \"%s\": %m" -#: util.c:49 +#: tablespace.c:92 #, c-format -msgid " " -msgstr " " +msgid "tablespace path \"%s\" is not a directory" +msgstr "путь табличного пространства \"%s\" не указывает на каталог" -#: util.c:82 +#: util.c:53 util.c:56 util.c:139 util.c:170 util.c:172 #, c-format msgid "%-*s" msgstr "%-*s" -#: util.c:174 +#: util.c:107 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" + +#: util.c:287 #, c-format msgid "ok" msgstr "ок" -#: version.c:29 +#: version.c:44 #, c-format -msgid "Checking for large objects" -msgstr "Проверка больших объектов" +msgid "Checking for hash indexes" +msgstr "Проверка хеш-индексов" -#: version.c:77 version.c:419 +#: version.c:121 #, c-format msgid "warning" msgstr "предупреждение" -#: version.c:79 -#, c-format -msgid "" -"\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table. After upgrading, you will be\n" -"given a command to populate the pg_largeobject_metadata table with\n" -"default permissions.\n" -"\n" -msgstr "" -"\n" -"В вашей инсталляции используются большие объекты. В новой базе данных\n" -"имеется дополнительная таблица с правами для больших объектов. После " -"обновления\n" -"вам будет представлена команда для наполнения таблицы прав\n" -"pg_largeobject_metadata правами по умолчанию.\n" -"\n" - -#: version.c:85 -#, c-format -msgid "" -"\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table, so default permissions must be\n" -"defined for all large objects. The file\n" -" %s\n" -"when executed by psql by the database superuser will set the default\n" -"permissions.\n" -"\n" -msgstr "" -"\n" -"В вашей инсталляции используются большие объекты. В новой базе данных\n" -"имеется дополнительная таблица с правами для больших объектов, поэтому\n" -"для всех больших объектов должны определяться права по умолчанию. Скрипт\n" -" %s\n" -"будучи выполненным администратором БД в psql, установит нужные права\n" -"по умолчанию.\n" -"\n" - -#: version.c:272 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "Проверка несовместимого типа данных \"line\"" - -#: version.c:279 -#, c-format -msgid "" -"Your installation contains the \"line\" data type in user tables.\n" -"This data type changed its internal and input/output format\n" -"between your old and new versions so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"В вашей инсталляции пользовательские таблицы используют тип данных \"line" -"\".\n" -"В старом кластере внутренний формат и формат ввода/вывода этого типа " -"отличается\n" -"от нового, поэтому в настоящем состоянии обновить кластер невозможно. Вы " -"можете\n" -"удалить проблемные столбцы и перезапустить обновление. Список проблемных\n" -"столбцов приведён в файле:\n" -" %s\n" -"\n" - -#: version.c:310 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "Проверка неправильных пользовательских столбцов типа \"unknown\"" - -#: version.c:317 -#, c-format -msgid "" -"Your installation contains the \"unknown\" data type in user tables.\n" -"This data type is no longer allowed in tables, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"В вашей инсталляции пользовательские таблицы используют тип данных \"unknown" -"\".\n" -"Теперь использование этого типа данных в таблицах не допускается, поэтому\n" -"в настоящем состоянии обновить кластер невозможно. Вы можете удалить " -"проблемные\n" -"столбцы и перезапустить обновление. Список проблемных столбцов приведён в " -"файле:\n" -" %s\n" -"\n" - -#: version.c:341 -#, c-format -msgid "Checking for hash indexes" -msgstr "Проверка хеш-индексов" - -#: version.c:421 +#: version.c:123 #, c-format msgid "" "\n" "Your installation contains hash indexes. These indexes have different\n" "internal formats between your old and new clusters, so they must be\n" "reindexed with the REINDEX command. After upgrading, you will be given\n" -"REINDEX instructions.\n" -"\n" +"REINDEX instructions." msgstr "" "\n" "В вашей инсталляции используются хеш-индексы. Эти индексы имеют разные\n" "внутренние форматы в старом и новом кластерах, поэтому их необходимо\n" "перестроить с помощью команды REINDEX. По завершении обновления вы получите\n" -"инструкции по выполнению REINDEX.\n" -"\n" +"инструкции по выполнению REINDEX." -#: version.c:427 +#: version.c:129 #, c-format msgid "" "\n" @@ -2037,8 +2211,7 @@ msgid "" "reindexed with the REINDEX command. The file\n" " %s\n" "when executed by psql by the database superuser will recreate all invalid\n" -"indexes; until then, none of these indexes will be used.\n" -"\n" +"indexes; until then, none of these indexes will be used." msgstr "" "\n" "В вашей инсталляции используются хеш-индексы. Эти индексы имеют разные\n" @@ -2046,45 +2219,19 @@ msgstr "" "перестроить с помощью команды REINDEX. Скрипт\n" " %s\n" "будучи выполненным администратором БД в psql, пересоздаст все неправильные\n" -"индексы; до этого никакие хеш-индексы не будут использоваться.\n" -"\n" - -#: version.c:453 -#, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "" -"Проверка неправильных пользовательских столбцов типа \"sql_identifier\"" - -#: version.c:461 -#, c-format -msgid "" -"Your installation contains the \"sql_identifier\" data type in user tables.\n" -"The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n" -"\n" -msgstr "" -"В вашей инсталляции пользовательские таблицы используют тип данных\n" -"\"sql_identifier\". Формат хранения таких данных на диске поменялся,\n" -"поэтому обновить данный кластер невозможно. Вы можете удалить проблемные\n" -"столбцы и перезапустить обновление.\n" -"Список проблемных столбцов приведён в файле:\n" -" %s\n" -"\n" +"индексы; до этого никакие хеш-индексы не будут использоваться." -#: version.c:485 +#: version.c:153 #, c-format msgid "Checking for extension updates" msgstr "Проверка обновлённых расширений" -#: version.c:537 +#: version.c:200 #, c-format msgid "notice" msgstr "замечание" -#: version.c:538 +#: version.c:201 #, c-format msgid "" "\n" @@ -2092,16 +2239,210 @@ msgid "" "with the ALTER EXTENSION command. The file\n" " %s\n" "when executed by psql by the database superuser will update\n" -"these extensions.\n" -"\n" +"these extensions." msgstr "" "\n" "В вашей инсталляции есть расширения, которые надо обновить\n" "командой ALTER EXTENSION. Скрипт\n" " %s\n" "будучи выполненным администратором БД в psql, обновит все\n" -"эти расширения.\n" -"\n" +"эти расширения." + +#, c-format +#~ msgid "Checking for incompatible \"jsonb\" data type" +#~ msgstr "Проверка несовместимого типа данных \"jsonb\"" + +#, c-format +#~ msgid "" +#~ "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" +#~ msgstr "" +#~ "кодировки в базе данных \"%s\" различаются: старая - \"%s\", новая - " +#~ "\"%s\"\n" + +#, c-format +#~ msgid "" +#~ "lc_collate values for database \"%s\" do not match: old \"%s\", new " +#~ "\"%s\"\n" +#~ msgstr "" +#~ "значения lc_collate в базе данных \"%s\" различаются: старое - \"%s\", " +#~ "новое - \"%s\"\n" + +#, c-format +#~ msgid "" +#~ "lc_ctype values for database \"%s\" do not match: old \"%s\", new " +#~ "\"%s\"\n" +#~ msgstr "" +#~ "значения lc_ctype в базе данных \"%s\" различаются: старое - \"%s\", " +#~ "новое - \"%s\"\n" + +#, c-format +#~ msgid "" +#~ "locale providers for database \"%s\" do not match: old \"%s\", new " +#~ "\"%s\"\n" +#~ msgstr "" +#~ "провайдеры локали в базе данных \"%s\" различаются: старый - \"%s\", " +#~ "новый - \"%s\"\n" + +#, c-format +#~ msgid "" +#~ "ICU locale values for database \"%s\" do not match: old \"%s\", new " +#~ "\"%s\"\n" +#~ msgstr "" +#~ "значения локали ICU для базы данных \"%s\" различаются: старое - \"%s\", " +#~ "новое - \"%s\"\n" + +#, c-format +#~ msgid "The source cluster contains roles starting with \"pg_\"\n" +#~ msgstr "В исходном кластере есть роли, имена которых начинаются с \"pg_\"\n" + +#, c-format +#~ msgid "The target cluster contains roles starting with \"pg_\"\n" +#~ msgstr "В целевом кластере есть роли, имена которых начинаются с \"pg_\"\n" + +#, c-format +#~ msgid "failed to get the current locale\n" +#~ msgstr "не удалось получить текущую локаль\n" + +#, c-format +#~ msgid "failed to get system locale name for \"%s\"\n" +#~ msgstr "не удалось получить системное имя локали для \"%s\"\n" + +#, c-format +#~ msgid "failed to restore old locale \"%s\"\n" +#~ msgstr "не удалось восстановить старую локаль \"%s\"\n" + +#, c-format +#~ msgid "Unable to rename %s to %s.\n" +#~ msgstr "Не удалось переименовать %s в %s.\n" + +#, c-format +#~ msgid "%s\n" +#~ msgstr "%s\n" + +#, c-format +#~ msgid "check for \"%s\" failed: not a regular file\n" +#~ msgstr "программа \"%s\" не прошла проверку: это не обычный файл\n" + +#, c-format +#~ msgid "check for \"%s\" failed: cannot execute (permission denied)\n" +#~ msgstr "" +#~ "программа \"%s\" не прошла проверку: ошибка выполнения (нет доступа)\n" + +#, c-format +#~ msgid "" +#~ "\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "\n" + +#, c-format +#~ msgid "%-*s\n" +#~ msgstr "%-*s\n" + +#~ msgid "" +#~ "When checking a pre-PG 9.1 live old server, you must specify the old " +#~ "server's port number.\n" +#~ msgstr "" +#~ "Для проверки старого работающего сервера версии до 9.1 необходимо указать " +#~ "номер порта этого сервера.\n" + +#~ msgid "" +#~ "All non-template0 databases must allow connections, i.e. their " +#~ "pg_database.datallowconn must be true\n" +#~ msgstr "" +#~ "Все базы, кроме template0, должны допускать подключения, то есть их " +#~ "свойство pg_database.datallowconn должно быть true\n" + +#~ msgid "" +#~ "\n" +#~ "The old cluster has a \"plpython_call_handler\" function defined\n" +#~ "in the \"public\" schema which is a duplicate of the one defined\n" +#~ "in the \"pg_catalog\" schema. You can confirm this by executing\n" +#~ "in psql:\n" +#~ "\n" +#~ " \\df *.plpython_call_handler\n" +#~ "\n" +#~ "The \"public\" schema version of this function was created by a\n" +#~ "pre-8.1 install of plpython, and must be removed for pg_upgrade\n" +#~ "to complete because it references a now-obsolete \"plpython\"\n" +#~ "shared object file. You can remove the \"public\" schema version\n" +#~ "of this function by running the following command:\n" +#~ "\n" +#~ " DROP FUNCTION public.plpython_call_handler()\n" +#~ "\n" +#~ "in each affected database:\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "В старом кластере имеется функция \"plpython_call_handler\",\n" +#~ "определённая в схеме \"public\", представляющая собой копию функции,\n" +#~ "определённой в схеме \"pg_catalog\". Вы можете убедиться в этом,\n" +#~ "выполнив в psql:\n" +#~ "\n" +#~ " \\df *.plpython_call_handler\n" +#~ "\n" +#~ "Версия этой функции в схеме \"public\" была создана инсталляцией\n" +#~ "plpython версии до 8.1 и должна быть удалена для завершения процедуры\n" +#~ "pg_upgrade, так как она ссылается на ставший устаревшим\n" +#~ "разделяемый объектный файл \"plpython\". Вы можете удалить версию этой " +#~ "функции\n" +#~ "из схемы \"public\", выполнив следующую команду:\n" +#~ "\n" +#~ " DROP FUNCTION public.plpython_call_handler()\n" +#~ "\n" +#~ "в каждой затронутой базе данных:\n" +#~ "\n" + +#~ msgid " %s\n" +#~ msgstr " %s\n" + +#~ msgid "Remove the problem functions from the old cluster to continue.\n" +#~ msgstr "Удалите проблемные функции из старого кластера для продолжения.\n" + +#~ msgid "mappings for database \"%s\":\n" +#~ msgstr "отображения для базы данных \"%s\":\n" + +#~ msgid "%s.%s: %u to %u\n" +#~ msgstr "%s.%s: %u в %u\n" + +#~ msgid " " +#~ msgstr " " + +#~ msgid "" +#~ "\n" +#~ "Your installation contains large objects. The new database has an\n" +#~ "additional large object permission table. After upgrading, you will be\n" +#~ "given a command to populate the pg_largeobject_metadata table with\n" +#~ "default permissions.\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "В вашей инсталляции используются большие объекты. В новой базе данных\n" +#~ "имеется дополнительная таблица с правами для больших объектов. После " +#~ "обновления\n" +#~ "вам будет представлена команда для наполнения таблицы прав\n" +#~ "pg_largeobject_metadata правами по умолчанию.\n" +#~ "\n" + +#~ msgid "" +#~ "\n" +#~ "Your installation contains large objects. The new database has an\n" +#~ "additional large object permission table, so default permissions must be\n" +#~ "defined for all large objects. The file\n" +#~ " %s\n" +#~ "when executed by psql by the database superuser will set the default\n" +#~ "permissions.\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "В вашей инсталляции используются большие объекты. В новой базе данных\n" +#~ "имеется дополнительная таблица с правами для больших объектов, поэтому\n" +#~ "для всех больших объектов должны определяться права по умолчанию. Скрипт\n" +#~ " %s\n" +#~ "будучи выполненным администратором БД в psql, установит нужные права\n" +#~ "по умолчанию.\n" +#~ "\n" #~ msgid "Creating script to analyze new cluster" #~ msgstr "Создание скрипта для анализа нового кластера" diff --git a/src/bin/pg_upgrade/po/sv.po b/src/bin/pg_upgrade/po/sv.po index c8dbe9e9d9078..51ad41bff555c 100644 --- a/src/bin/pg_upgrade/po/sv.po +++ b/src/bin/pg_upgrade/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_upgrade # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-02 03:18+0000\n" -"PO-Revision-Date: 2023-08-02 12:02+0200\n" +"POT-Creation-Date: 2025-02-12 13:50+0000\n" +"PO-Revision-Date: 2025-02-12 20:38+0100\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,7 +17,239 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: check.c:69 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "kunde inte hämta statuskod för underprocess: felkod %lu" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "kunde inte slå upp effektivt användar-id %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "användaren finns inte" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "misslyckad sökning efter användarnamn: felkod %lu" + +#: ../../fe_utils/string_utils.c:608 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:781 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "Letar i användartabeller efter systemdefinierade typer av sorten \"composite\"" + +#: check.c:118 +msgid "" +"Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Din installation innehåller användartabeller med systemdefinierade typer\n" +"av sorten \"composite\". OID:er för dessa typer är inte stabila över\n" +"PostgreSQL-versioner så detta kluster kan inte uppgraderas för tillfället.\n" +"Du kan slänga problemkolumnerna och återstarta uppgraderingen.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "Letar efter inkompatibel \"line\"-datatyp" + +#: check.c:137 +msgid "" +"Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"line\" i användartabeller. Denna\n" +"datatype har ändrat sitt interna format samt sitt in/ut-format mellan din\n" +"gamla och nya version så detta kluster kan för närvarande inte uppgraderas.\n" +"Du kan radera problemkolumnerna och återstarta uppgraderingen.\n" + +# FIXME: is this msgid correct? +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "Letar efter reg*-datatyper i användartabeller" + +#: check.c:181 +msgid "" +"Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "" +"Din installation använder en av reg*-datatyperna i en användartabell.\n" +"Dessa datatyper refererar system-OID:er som inte bevaras av pg_upgrade\n" +"så detta kluster kan för närvarande inte uppgraderas. Du kan ta bort\n" +"problemkolumnerna och starta om uppgraderingen.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "Letar efter inkompatibel datatype \"aclitem\"" + +#: check.c:198 +msgid "" +"Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"aclitem\" i användartabeller.\n" +"Interna formatet för \"aclitem\" ändrades i PostgreSQL 16 så detta kluster\n" +"kan för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna\n" +"och starta om uppgraderingen.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "Letar efter ogiltiga användarkolumner av typen \"unknown\"" + +#: check.c:222 +msgid "" +"Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"unknown\" i användartabeller.\n" +"Denna datatyp tillåts inte längre i tabeller så detta kluster kan\n" +"för närvarande inte uppgraderas. Du kan radera problemkolumnerna och\n" +"återstarta uppgraderingen.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "Letar efter ogiltiga användarkolumner av typen \"sql_identifier\"" + +#: check.c:244 +msgid "" +"Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"sql_identifier\" i användartabeller.\n" +"Formatet på disk för denna datatyp har ändrats så detta kluster kan för\n" +"närvarande inte uppgraderas. Du kan radera problemkolumnerna och\n" +"återstarta uppgraderingen.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "Letar efter inkompatibel datatyp \"jsonb\"-datatyp i användartabeller" + +#: check.c:260 +msgid "" +"Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"jsonb\" i användartabeller.\n" +"Interna formatet för \"jsonb\" ändrades under 9.4-betan så detta kluster kan\n" +"för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna och\n" +"starta om uppgraderingen.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "Letar efter borttagen datatype \"abstime\" i användartabeller" + +#: check.c:277 +msgid "" +"Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"abstime\" i användartabeller.\n" +"Datatypen \"abstime\" togs bort i PostgreSQL version 12 så detta kluster\n" +"kan för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna\n" +"eller ändra dem till en annan datatype och starta om uppgraderingen.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "Letar efter borttagen datatype \"reltime\" i användartabeller" + +#: check.c:290 +msgid "" +"Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"reltime\" i användartabeller.\n" +"Datatypen \"reltime\" togs bort i PostgreSQL version 12 så detta kluster\n" +"kan för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna\n" +"eller ändra dem till en annan datatype och starta om uppgraderingen.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "Letar efter borttagen datatype \"tinterval\" i användartabeller" + +#: check.c:303 +msgid "" +"Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "" +"Din installation innehåller datatypen \"tinterval\" i användartabeller.\n" +"Datatypen \"tinterval\" togs bort i PostgreSQL version 12 så detta kluster\n" +"kan för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna\n" +"eller ändra dem till en annan datatype och starta om uppgraderingen.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "Letar efter användning av datatyp" + +#: check.c:480 +#, c-format +msgid "failed check: %s" +msgstr "misslyckad kontroll: %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "En lista med problemkolumner finns i filen:" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "Kontroll av datatyper misslyckades: %s" + +#: check.c:563 #, c-format msgid "" "Performing Consistency Checks on Old Live Server\n" @@ -26,7 +258,7 @@ msgstr "" "Utför konsistenskontroller på gamla live-servern\n" "------------------------------------------------" -#: check.c:75 +#: check.c:569 #, c-format msgid "" "Performing Consistency Checks\n" @@ -35,14 +267,16 @@ msgstr "" "Utför konsistenskontroller\n" "--------------------------" -#: check.c:221 +#: check.c:718 #, c-format msgid "" "\n" "*Clusters are compatible*" -msgstr "\n*Klustren är kompatibla*" +msgstr "" +"\n" +"*Klustren är kompatibla*" -#: check.c:229 +#: check.c:726 #, c-format msgid "" "\n" @@ -53,7 +287,7 @@ msgstr "" "Om pg_upgrade misslyckas efter denna punkt så måste du\n" "köra om initdb på nya klustret innan du fortsätter." -#: check.c:270 +#: check.c:767 #, c-format msgid "" "Optimizer statistics are not transferred by pg_upgrade.\n" @@ -64,7 +298,7 @@ msgstr "" "När du startar nya servern så vill du nog köra:\n" " %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:276 +#: check.c:773 #, c-format msgid "" "Running this script will delete the old cluster's data files:\n" @@ -73,7 +307,7 @@ msgstr "" "När detta skript körs så raderas gamla klustrets datafiler:\n" " %s" -#: check.c:281 +#: check.c:778 #, c-format msgid "" "Could not create a script to delete the old cluster's data files\n" @@ -86,125 +320,121 @@ msgstr "" "ligger i gamla klusterkatalogen. Det gamla klustrets innehåll\n" "måste raderas för hand." -#: check.c:293 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "Kontrollerar klustrets versioner" -#: check.c:305 +#: check.c:802 #, c-format msgid "This utility can only upgrade from PostgreSQL version %s and later." msgstr "Detta verktyg kan bara uppgradera från PostgreSQL version %s eller senare." -#: check.c:310 +#: check.c:807 #, c-format msgid "This utility can only upgrade to PostgreSQL version %s." msgstr "Detta verktyg kan bara uppgradera till PostgreSQL version %s." -#: check.c:319 +#: check.c:816 #, c-format msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." msgstr "Detta verktyg kan inte användas för att nergradera till äldre major-versioner av PostgreSQL." -#: check.c:324 +#: check.c:821 #, c-format msgid "Old cluster data and binary directories are from different major versions." msgstr "Gammal klusterdata och binära kataloger är från olika major-versioner." -#: check.c:327 +#: check.c:824 #, c-format msgid "New cluster data and binary directories are from different major versions." msgstr "Nya klusterdata och binära kataloger är från olika major-versioner." -#: check.c:342 +#: check.c:839 #, c-format msgid "When checking a live server, the old and new port numbers must be different." msgstr "Vid kontroll av en live-server så måste gamla och nya portnumren vara olika." -#: check.c:362 +#: check.c:859 #, c-format msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" msgstr "Nya databasklustret \"%s\" är inte tomt: hittade relation \"%s.%s\"" -#: check.c:385 +#: check.c:882 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Letar efter nya tablespace-kataloger i klustret" -#: check.c:396 +#: check.c:893 #, c-format msgid "new cluster tablespace directory already exists: \"%s\"" msgstr "i klustret finns redan ny tablespace-katalog: \"%s\"" -#: check.c:429 +#: check.c:926 #, c-format msgid "" "\n" "WARNING: new data directory should not be inside the old data directory, i.e. %s" -msgstr "\nVARNING: nya datakatalogen skall inte ligga inuti den gamla datakatalogen, dvs. %s" +msgstr "" +"\n" +"VARNING: nya datakatalogen skall inte ligga inuti den gamla datakatalogen, dvs. %s" -#: check.c:453 +#: check.c:950 #, c-format msgid "" "\n" "WARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s" -msgstr "\nVARNING: användardefinierade tabellutrymmens plats skall inte vara i datakatalogen, dvs. %s" +msgstr "" +"\n" +"VARNING: användardefinierade tabellutrymmens plats skall inte vara i datakatalogen, dvs. %s" -#: check.c:463 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "Skapar skript för att radera gamla klustret" -#: check.c:466 check.c:639 check.c:755 check.c:850 check.c:979 check.c:1056 -#: check.c:1299 check.c:1373 file.c:339 function.c:163 option.c:476 -#: version.c:116 version.c:292 version.c:426 -#, c-format -msgid "could not open file \"%s\": %s" -msgstr "kunde inte öppna fil \"%s\": %s" - -#: check.c:517 +#: check.c:1014 #, c-format -msgid "could not add execute permission to file \"%s\": %s" -msgstr "kan inte sätta rättigheten \"körbar\" på filen \"%s\": %s" +msgid "could not add execute permission to file \"%s\": %m" +msgstr "kunde inte lägga till rättigheten \"körbar\" på filen \"%s\": %m" -#: check.c:537 +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "Kontrollerar att databasanvändaren är installationsanvändaren" -#: check.c:553 +#: check.c:1050 #, c-format msgid "database user \"%s\" is not the install user" msgstr "databasanvändare \"%s\" är inte installationsanvändaren" -#: check.c:564 +#: check.c:1061 #, c-format msgid "could not determine the number of users" msgstr "kunde inte bestämma antalet användare" -#: check.c:572 +#: check.c:1069 #, c-format msgid "Only the install user can be defined in the new cluster." msgstr "Bara installationsanvändaren får finnas i nya klustret." -#: check.c:601 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "Kontrollerar databasens anslutningsinställningar" -#: check.c:627 +#: check.c:1124 #, c-format msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" msgstr "template0 får inte tillåta anslutningar, dvs dess pg_database.datallowconn måste vara false" -#: check.c:654 check.c:775 check.c:873 check.c:999 check.c:1076 check.c:1135 -#: check.c:1196 check.c:1224 check.c:1254 check.c:1313 check.c:1394 -#: function.c:185 version.c:192 version.c:232 version.c:378 +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 #, c-format msgid "fatal" msgstr "fatalt" -#: check.c:655 +#: check.c:1151 #, c-format msgid "" "All non-template0 databases must allow connections, i.e. their\n" @@ -223,27 +453,27 @@ msgstr "" "problemdatabaser finns i filen:\n" " %s" -#: check.c:680 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "Letar efter förberedda transaktioner" -#: check.c:689 +#: check.c:1185 #, c-format msgid "The source cluster contains prepared transactions" msgstr "Källklustret innehåller förberedda transaktioner" -#: check.c:691 +#: check.c:1187 #, c-format msgid "The target cluster contains prepared transactions" msgstr "Målklustret innehåller förberedda transaktioner" -#: check.c:716 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Letar efter contrib/isn med bigint-anropsfel" -#: check.c:776 +#: check.c:1271 #, c-format msgid "" "Your installation contains \"contrib/isn\" functions which rely on the\n" @@ -262,12 +492,12 @@ msgstr "" "En lista med problemfunktionerna finns i filen:\n" " %s" -#: check.c:798 +#: check.c:1293 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Letar efter användardefinierade postfix-operatorer" -#: check.c:874 +#: check.c:1368 #, c-format msgid "" "Your installation contains user-defined postfix operators, which are not\n" @@ -282,12 +512,12 @@ msgstr "" "En lista med användardefinierade postfix-operatorer finns i filen:\n" " %s" -#: check.c:898 +#: check.c:1392 #, c-format msgid "Checking for incompatible polymorphic functions" msgstr "Letar efter inkompatibla polymorfa funktioner" -#: check.c:1000 +#: check.c:1493 #, c-format msgid "" "Your installation contains user-defined objects that refer to internal\n" @@ -308,12 +538,12 @@ msgstr "" "En lista med problemobjekten finns i filen:\n" " %s" -#: check.c:1024 +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Letar efter tabeller med WITH OIDS" -#: check.c:1077 +#: check.c:1569 #, c-format msgid "" "Your installation contains tables declared WITH OIDS, which is not\n" @@ -328,146 +558,134 @@ msgstr "" "En lista över tabeller med detta problem finns i filen:\n" " %s" -# FIXME: is this msgid correct? -#: check.c:1105 +#: check.c:1596 #, c-format -msgid "Checking for system-defined composite types in user tables" -msgstr "Letar i användartabeller efter systemdefinierade typer av sorten \"composite\"" +msgid "Checking for roles starting with \"pg_\"" +msgstr "Letar efter roller som startar med \"pg_\"" -#: check.c:1136 +#: check.c:1627 #, c-format msgid "" -"Your installation contains system-defined composite type(s) in user tables.\n" -"These type OIDs are not stable across PostgreSQL versions,\n" -"so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" " %s" msgstr "" -"Din installation innehåller användartabeller med systemdefinierade typer\n" -"av sorten \"composite\". OID:er för dessa typer är inte stabila över\n" -"PostgreSQL-versioner så detta kluster kan inte uppgraderas för tillfället.\n" -"Du kan slänga problemkolumnerna och återstarta uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" +"Din installation innehåller roller som startar på \"pg_\".\n" +"\"pg_\" är ett reserverat prefix för systemroller. Klustret\n" +"kan inte uppgraderas innan dessa roller har bytt namn.\n" +"En lista med rollerna som startar på \"pg_\" finns i denna fil:\n" " %s" -# FIXME: is this msgid correct? -#: check.c:1164 +#: check.c:1647 #, c-format -msgid "Checking for reg* data types in user tables" -msgstr "Letar efter reg*-datatyper i användartabeller" +msgid "Checking for user-defined encoding conversions" +msgstr "Letar efter användardefinierade teckenkodkonverteringar" -#: check.c:1197 +#: check.c:1707 #, c-format msgid "" -"Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" +"Your installation contains user-defined encoding conversions.\n" +"The conversion function parameters changed in PostgreSQL version 14\n" +"so this cluster cannot currently be upgraded. You can remove the\n" +"encoding conversions in the old cluster and restart the upgrade.\n" +"A list of user-defined encoding conversions is in the file:\n" " %s" msgstr "" -"Din installation använder en av reg*-datatyperna i en användartabell.\n" -"Dessa datatyper refererar system-OID:er som inte bevaras av pg_upgrade\n" -"så detta kluster kan för närvarande inte uppgraderas. Du kan ta bort\n" -"problemkolumnerna och starta om uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" +"Din installation innehåller användardefinierade teckenkodkonverteringar.\n" +"Parametrar till konverteringsfunktioner ändrades i PostgreSQL 14 så\n" +"detta kluster kan för närvarande inte uppgraderas. Du kan ta bort\n" +"teckenkodkonverteringarna i gamla klustret och starta om uppgraderingen.\n" +"En lista med användardefinierade teckenkodkonverteringar finns i filen:\n" " %s" -# FIXME: is this msgid correct? -#: check.c:1218 +#: check.c:1746 #, c-format -msgid "Checking for incompatible \"aclitem\" data type in user tables" -msgstr "Letar efter inkompatibel \"aclitem\"-datatyp i användartabeller" +msgid "Checking for new cluster logical replication slots" +msgstr "Letar efter replikeringsslottar i nya klustret" -#: check.c:1225 +#: check.c:1754 #, c-format -msgid "" -"Your installation contains the \"aclitem\" data type in user tables.\n" -"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" -"so this cluster cannot currently be upgraded. You can drop the\n" -"problem columns and restart the upgrade. A list of the problem\n" -"columns is in the file:\n" -" %s" -msgstr "" -"Din installation innehåller \"aclitem\"-datatypen i användartabeller.\n" -"Interna formatet för \"aclitem\" ändrades i PostgreSQL 16 så detta kluster\n" -"kan för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna\n" -"och starta om uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" -" %s" +msgid "could not count the number of logical replication slots" +msgstr "kunde inte räkna antalet logiska replikeringsslottar" -# FIXME: is this msgid correct? -#: check.c:1246 +#: check.c:1759 #, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "Letar efter inkompatibel \"jsonb\"-datatyp" +msgid "expected 0 logical replication slots but found %d" +msgstr "förväntade 0 logiska replikeringsslottar men hittade %d." -#: check.c:1255 +#: check.c:1769 check.c:1820 #, c-format -msgid "" -"Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Din installation innehåller \"jsonb\"-datatypen i användartabeller.\n" -"Interna formatet för \"jsonb\" ändrades under 9.4-betan så detta kluster kan\n" -"för närvarande inte uppgraderas. Du kan ta bort problemkolumnerna och\n" -"starta om uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" -" %s" +msgid "could not determine parameter settings on new cluster" +msgstr "kunde inte plocka fram inställningar i det nya klustret" -#: check.c:1282 +#: check.c:1774 #, c-format -msgid "Checking for roles starting with \"pg_\"" -msgstr "Letar efter roller som startar med \"pg_\"" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "\"wal_level\" måste vara satt till \"logical\" men är satt som \"%s\"" + +#: check.c:1780 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" +msgstr "\"max_replication_slots\" (%d) måste vara större än eller lika med antalet logiska replikeringsslottar (%d) i gamla klustret" + +#: check.c:1812 +#, c-format +msgid "Checking for new cluster configuration for subscriptions" +msgstr "Letar efter konfiguration för prenumerationer i nya klustret" -#: check.c:1314 +#: check.c:1824 +#, c-format +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "\"max_replication_slots\" (%d) måste vara större än eller lika med antaler prenumerationer (%d) i gamla klustret" + +#: check.c:1846 +#, c-format +msgid "Checking for valid logical replication slots" +msgstr "Letar efter giltiga logiska replikeringsslottar" + +#: check.c:1898 #, c-format msgid "" -"Your installation contains roles starting with \"pg_\".\n" -"\"pg_\" is a reserved prefix for system roles. The cluster\n" -"cannot be upgraded until these roles are renamed.\n" -"A list of roles starting with \"pg_\" is in the file:\n" +"Your installation contains logical replication slots that cannot be upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" " %s" msgstr "" -"Din installation innehåller roller som startar på \"pg_\".\n" -"\"pg_\" är ett reserverat prefix för systemroller. Klustret\n" -"kan inte uppgraderas innan dessa roller har bytt namn.\n" -"En lista med rollerna som startar på \"pg_\" finns i denna fil:\n" +"Din installation innehåller logiska replikeringsslottar som inte\n" +"kan uppgraderas. Du kan ta bort ogiltiga slottar och/eller konsumera\n" +"köad WAL för andra slottar och sedan återstarta uppgraderingen.\n" +"En lista med problemkolumner finns i filen:\n" " %s" -#: check.c:1334 +#: check.c:1922 #, c-format -msgid "Checking for user-defined encoding conversions" -msgstr "Letar efter användardefinierade teckenkodkonverteringar" +msgid "Checking for subscription state" +msgstr "Kontrollerar läget för prenumerationer" -#: check.c:1395 +#: check.c:2023 #, c-format msgid "" -"Your installation contains user-defined encoding conversions.\n" -"The conversion function parameters changed in PostgreSQL version 14\n" -"so this cluster cannot currently be upgraded. You can remove the\n" -"encoding conversions in the old cluster and restart the upgrade.\n" -"A list of user-defined encoding conversions is in the file:\n" +"Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" " %s" msgstr "" -"Din installation innehåller användardefinierade teckenkodkonverteringar.\n" -"Parametrar till konverteringsfunktioner ändrades i PostgreSQL 14 så\n" -"detta kluster kan för närvarande inte uppgraderas. Du kan ta bort\n" -"teckenkodkonverteringarna i gamla klustret och starta om uppgraderingen.\n" -"En lista med användardefinierade teckenkodkonverteringar finns i filen:\n" +"Din installation innehåller prenumerationer utan origin eller har\n" +"relationer som inte är i läget i (initialize) eller r (ready).\n" +"Du kan låta den initiala synken gå klart för alla relationer och\n" +"sedan återuppta uppgraderingen.\n" +"En lista med problemkolumner finns i filen:\n" " %s" -#: controldata.c:129 controldata.c:175 controldata.c:199 controldata.c:508 +#: controldata.c:129 controldata.c:199 #, c-format -msgid "could not get control data using %s: %s" -msgstr "kunde inte hämta kontrolldata med %s: %s" +msgid "could not get control data using %s: %m" +msgstr "kunde inte hämta kontrolldata med %s: %m" -#: controldata.c:140 +#: controldata.c:139 #, c-format msgid "%d: database cluster state problem" msgstr "%d: state-problem för databaskluster" @@ -484,13 +702,18 @@ msgstr "Målklustret stängdes ner när det var i återställningsläge. För at #: controldata.c:165 #, c-format -msgid "The source cluster was not shut down cleanly." -msgstr "Källklustret har inte stängts ner på ett korrekt sätt." +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "Källklustret har inte stängts ner på ett korrekt sätt, dess tillstånd rapporteras som: \"%s\"" #: controldata.c:167 #, c-format -msgid "The target cluster was not shut down cleanly." -msgstr "Målklustret har inte stängts ner på ett korrekt sätt." +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "Målklustret har inte stängts ner på ett korrekt sätt, dess tillstånd rapporteras som: \"%s\"." + +#: controldata.c:175 controldata.c:507 +#, c-format +msgid "could not get control data using %s: %s" +msgstr "kunde inte hämta kontrolldata med %s: %s" #: controldata.c:181 #, c-format @@ -502,139 +725,139 @@ msgstr "Källklustret saknar information om kluster-state:" msgid "The target cluster lacks cluster state information:" msgstr "Målklustret saknar information om kluster-state:" -#: controldata.c:214 dump.c:50 exec.c:119 pg_upgrade.c:517 pg_upgrade.c:554 -#: relfilenumber.c:231 server.c:34 util.c:337 +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 #, c-format msgid "%s" msgstr "%s" -#: controldata.c:221 +#: controldata.c:220 #, c-format msgid "%d: pg_resetwal problem" msgstr "%d: pg_resetwal-problem" -#: controldata.c:231 controldata.c:241 controldata.c:252 controldata.c:263 -#: controldata.c:274 controldata.c:293 controldata.c:304 controldata.c:315 -#: controldata.c:326 controldata.c:337 controldata.c:348 controldata.c:359 -#: controldata.c:362 controldata.c:366 controldata.c:376 controldata.c:388 -#: controldata.c:399 controldata.c:410 controldata.c:421 controldata.c:432 -#: controldata.c:443 controldata.c:454 controldata.c:465 controldata.c:476 -#: controldata.c:487 controldata.c:498 +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 #, c-format msgid "%d: controldata retrieval problem" msgstr "%d: problem vid hämtning av kontrolldata" -#: controldata.c:579 +#: controldata.c:578 #, c-format msgid "The source cluster lacks some required control information:" msgstr "Källklustret saknar lite kontrolldata som krävs:" -#: controldata.c:582 +#: controldata.c:581 #, c-format msgid "The target cluster lacks some required control information:" msgstr "Målklustret saknar lite kontrolldata som krävs:" -#: controldata.c:585 +#: controldata.c:584 #, c-format msgid " checkpoint next XID" msgstr " checkpoint nästa-XID" -#: controldata.c:588 +#: controldata.c:587 #, c-format msgid " latest checkpoint next OID" msgstr " senaste checkpoint nästa-OID" -#: controldata.c:591 +#: controldata.c:590 #, c-format msgid " latest checkpoint next MultiXactId" msgstr " senaster checkpoint nästa-MultiXactId" -#: controldata.c:595 +#: controldata.c:594 #, c-format msgid " latest checkpoint oldest MultiXactId" msgstr " senaste checkpoint äldsta-MultiXactId" -#: controldata.c:598 +#: controldata.c:597 #, c-format msgid " latest checkpoint oldestXID" msgstr " senaste checkpoint äldsta-XID" -#: controldata.c:601 +#: controldata.c:600 #, c-format msgid " latest checkpoint next MultiXactOffset" msgstr " senaste checkpoint nästa-MultiXactOffset" -#: controldata.c:604 +#: controldata.c:603 #, c-format msgid " first WAL segment after reset" msgstr " första WAL-segmentet efter reset" -#: controldata.c:607 +#: controldata.c:606 #, c-format msgid " float8 argument passing method" msgstr " float8 argumentöverföringsmetod" -#: controldata.c:610 +#: controldata.c:609 #, c-format msgid " maximum alignment" msgstr " maximal alignment" -#: controldata.c:613 +#: controldata.c:612 #, c-format msgid " block size" msgstr " blockstorlek" -#: controldata.c:616 +#: controldata.c:615 #, c-format msgid " large relation segment size" msgstr " stora relationers segmentstorlek" -#: controldata.c:619 +#: controldata.c:618 #, c-format msgid " WAL block size" msgstr " WAL-blockstorlek" -#: controldata.c:622 +#: controldata.c:621 #, c-format msgid " WAL segment size" msgstr " WAL-segmentstorlek" -#: controldata.c:625 +#: controldata.c:624 #, c-format msgid " maximum identifier length" msgstr " maximal identifierarlängd" -#: controldata.c:628 +#: controldata.c:627 #, c-format msgid " maximum number of indexed columns" msgstr " maximalt antal indexerade kolumner" -#: controldata.c:631 +#: controldata.c:630 #, c-format msgid " maximum TOAST chunk size" msgstr " maximal TOAST-chunkstorlek" -#: controldata.c:635 +#: controldata.c:634 #, c-format msgid " large-object chunk size" msgstr " stora-objekt chunkstorlek" -#: controldata.c:638 +#: controldata.c:637 #, c-format msgid " dates/times are integers?" msgstr " datum/tid är heltal?" -#: controldata.c:642 +#: controldata.c:641 #, c-format msgid " data checksum version" msgstr " datachecksumversion" -#: controldata.c:644 +#: controldata.c:643 #, c-format msgid "Cannot continue without required control information, terminating" msgstr "Kan inte fortsätta utan kontrollinformation som krävs, avslutar" -#: controldata.c:659 +#: controldata.c:658 #, c-format msgid "" "old and new pg_controldata alignments are invalid or do not match.\n" @@ -643,77 +866,77 @@ msgstr "" "gamla och nya pg_controldata-alignments är ogiltiga eller matchar inte.\n" "Troligen är ett kluster en 32-bitars-installation och den andra 64-bitars" -#: controldata.c:663 +#: controldata.c:662 #, c-format msgid "old and new pg_controldata block sizes are invalid or do not match" msgstr "gamla och nya pg_controldata-blockstorlekar är ogiltiga eller matchar inte" -#: controldata.c:666 +#: controldata.c:665 #, c-format msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" msgstr "gamla och nya pg_controldata maximala relationssegmentstorlekar är ogiltiga eller matchar inte" -#: controldata.c:669 +#: controldata.c:668 #, c-format msgid "old and new pg_controldata WAL block sizes are invalid or do not match" msgstr "gamla och nya pg_controldata WAL-blockstorlekar är ogiltiga eller matchar inte" -#: controldata.c:672 +#: controldata.c:671 #, c-format msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" msgstr "gamla och nya pg_controldata WAL-segmentstorlekar är ogiltiga eller matchar inte" -#: controldata.c:675 +#: controldata.c:674 #, c-format msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" msgstr "gamla och nya pg_controldata maximal identifierarlängder är ogiltiga eller matchar inte" -#: controldata.c:678 +#: controldata.c:677 #, c-format msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" msgstr "gamla och nya pg_controldata maximalt indexerade kolumner ogiltiga eller matchar inte" -#: controldata.c:681 +#: controldata.c:680 #, c-format msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" msgstr "gamla och nya pg_controldata maximal TOAST-chunkstorlek ogiltiga eller matchar inte" -#: controldata.c:686 +#: controldata.c:685 #, c-format msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" msgstr "gamla och nya pg_controldata stora-objekt-chunkstorlekar är ogiltiga eller matchar inte" -#: controldata.c:689 +#: controldata.c:688 #, c-format msgid "old and new pg_controldata date/time storage types do not match" msgstr "gamla och nya pg_controldata datum/tid-lagringstyper matchar inte" -#: controldata.c:702 +#: controldata.c:701 #, c-format msgid "old cluster does not use data checksums but the new one does" msgstr "gamla klustret använder inte datachecksummor men nya gör det" -#: controldata.c:705 +#: controldata.c:704 #, c-format msgid "old cluster uses data checksums but the new one does not" msgstr "gamla klustret använder datachecksummor men nya gör inte det" -#: controldata.c:707 +#: controldata.c:706 #, c-format msgid "old and new cluster pg_controldata checksum versions do not match" msgstr "gamla och nya klustrets pg_controldata checksumversioner matchar inte" -#: controldata.c:718 +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "Lägger till \".old\"-suffix till gamla global/pg_control" -#: controldata.c:723 +#: controldata.c:722 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" -#: controldata.c:727 +#: controldata.c:726 #, c-format msgid "" "\n" @@ -738,27 +961,32 @@ msgstr "Skapar dump med globala objekt" msgid "Creating dump of database schemas" msgstr "Skapar dump innehållande databasscheman" -#: exec.c:47 exec.c:52 +#: exec.c:47 +#, c-format +msgid "could not get pg_ctl version data using %s: %m" +msgstr "kunde inte hämta pg_ctl versionsdata med %s: %m" + +#: exec.c:51 #, c-format msgid "could not get pg_ctl version data using %s: %s" msgstr "kunde inte hämta pg_ctl versionsdata med %s: %s" -#: exec.c:56 +#: exec.c:55 #, c-format msgid "could not get pg_ctl version output from %s" msgstr "kunde inte läsa versionutdata för pg_ctl från %s" -#: exec.c:113 exec.c:117 +#: exec.c:112 exec.c:116 #, c-format msgid "command too long" msgstr "kommandot för långt" -#: exec.c:161 pg_upgrade.c:286 +#: exec.c:160 pg_upgrade.c:311 #, c-format msgid "could not open log file \"%s\": %m" msgstr "kunde inte öppna loggfil \"%s\": %m" -#: exec.c:193 +#: exec.c:192 #, c-format msgid "" "\n" @@ -767,12 +995,12 @@ msgstr "" "\n" "*misslyckande*" -#: exec.c:196 +#: exec.c:195 #, c-format msgid "There were problems executing \"%s\"" msgstr "Det var problem med att köra \"%s\"" -#: exec.c:199 +#: exec.c:198 #, c-format msgid "" "Consult the last few lines of \"%s\" or \"%s\" for\n" @@ -781,7 +1009,7 @@ msgstr "" "Se de sista raderna i \"%s\" eller \"%s\" för\n" "en trolig orsak till misslyckandet." -#: exec.c:204 +#: exec.c:203 #, c-format msgid "" "Consult the last few lines of \"%s\" for\n" @@ -790,141 +1018,156 @@ msgstr "" "Se de sista raderna i \"%s\" för\n" "en trolig orsak till misslyckandet." -#: exec.c:219 pg_upgrade.c:296 +#: exec.c:218 pg_upgrade.c:321 #, c-format msgid "could not write to log file \"%s\": %m" msgstr "kunde inte skriva till loggfil \"%s\": %m" -#: exec.c:245 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s" -msgstr "kunde inte öppna fil \"%s\" för läsning: %s" +msgid "could not open file \"%s\" for reading: %m" +msgstr "kunde inte öppna filen \"%s\" för läsning: %m" -#: exec.c:272 +#: exec.c:270 #, c-format msgid "You must have read and write access in the current directory." msgstr "Du måste ha läs och skrivrättigheter till den aktuella katalogen." -#: exec.c:325 exec.c:391 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s" -msgstr "kontroll av \"%s\" misslyckades: %s" +msgid "check for \"%s\" failed: %m" +msgstr "kontroll av \"%s\" misslyckades: %m" -#: exec.c:328 exec.c:394 +#: exec.c:326 exec.c:392 #, c-format msgid "\"%s\" is not a directory" msgstr "\"%s\" är inte en katalog" -#: exec.c:441 -#, c-format -msgid "check for \"%s\" failed: %m" -msgstr "kontroll av \"%s\" misslyckades: %m" - -#: exec.c:446 +#: exec.c:444 #, c-format msgid "check for \"%s\" failed: cannot execute" msgstr "kontroll av \"%s\" misslyckades: kan inte exekvera" -#: exec.c:456 +#: exec.c:454 #, c-format msgid "check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" msgstr "kontroll av \"%s\" misslyckades: hittade felaktig version \"%s\", förväntade \"%s\"" -#: file.c:43 file.c:64 +#: file.c:44 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "fel vid kloning av relation \"%s.%s\" (\"%s\" till \"%s\"): %s" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "fel vid kloning av relation \"%s.%s\" (\"%s\" till \"%s\"): %m" -#: file.c:50 +#: file.c:51 #, c-format -msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "fel vid kloning av relation \"%s.%s\": kunde inte öppna filen \"%s\": %s" +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "fel vid kloning av relation \"%s.%s\": kunde inte öppna filen \"%s\": %m" -#: file.c:55 +#: file.c:56 #, c-format -msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "fel vid kloning av relation \"%s.%s\": kunde inte skapa filen \"%s\": %s" +msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "fel vid kloning av relation \"%s.%s\": kunde inte skapa filen \"%s\": %m" + +#: file.c:65 +#, c-format +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "fel vid kloning av relation \"%s.%s\" (\"%s\" till \"%s\"): %s" -#: file.c:90 file.c:193 +#: file.c:91 file.c:160 file.c:233 #, c-format -msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %s" -msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte öppna filen \"%s\": %s" +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte öppna filen \"%s\": %m" -#: file.c:95 file.c:202 +#: file.c:96 file.c:165 file.c:242 #, c-format -msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %s" -msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte skapa filen \"%s\": %s" +msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte skapa filen \"%s\": %m" -#: file.c:109 file.c:226 +#: file.c:110 file.c:266 #, c-format -msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %s" -msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte läsa filen \"%s\": %s" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte läsa filen \"%s\": %m" -#: file.c:121 file.c:304 +#: file.c:122 file.c:344 #, c-format -msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %s" -msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte skriva filen \"%s\": %s" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte skriva filen \"%s\": %m" -#: file.c:135 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "fel vid kopiering av relation \"%s.%s\" (\"%s\" till \"%s\"): %s" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "fel vid kopiering av relation \"%s.%s\" (\"%s\" till \"%s\"): %m" -#: file.c:154 +#: file.c:172 #, c-format -msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "fel vid skapande av länk för relation \"%s.%s\" (\"%s\" till \"%s\"): %s" +msgid "error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte kopiera filintervall från \"%s\" till \"%s\": %m" -#: file.c:197 +#: file.c:194 #, c-format -msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %s" -msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte göra stat på file \"%s\": %s" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "fel vid skapande av länk för relation \"%s.%s\" (\"%s\" till \"%s\"): %m" -#: file.c:229 +#: file.c:237 +#, c-format +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" +msgstr "fel vid kopiering av relation \"%s.%s\": kunde inte göra stat på file \"%s\": %m" + +#: file.c:269 #, c-format msgid "error while copying relation \"%s.%s\": partial page found in file \"%s\"" msgstr "fel vid kopiering av relation \"%s.%s\": partiell sida hittad i fil \"%s\"" -#: file.c:331 file.c:348 +#: file.c:371 file.c:387 #, c-format -msgid "could not clone file between old and new data directories: %s" -msgstr "kunde inte klona fil mellan gamla och nya datakatalogen: %s" +msgid "could not clone file between old and new data directories: %m" +msgstr "kunde inte klona fil mellan gamla och nya datakatalogen: %m" -#: file.c:344 +#: file.c:383 file.c:420 #, c-format -msgid "could not create file \"%s\": %s" -msgstr "kan inte skapa fil \"%s\": %s" +msgid "could not create file \"%s\": %m" +msgstr "kunde inte skapa fil \"%s\": %m" -#: file.c:355 +#: file.c:393 #, c-format msgid "file cloning not supported on this platform" msgstr "filkloning stöds inte på denna plattform" -#: file.c:372 +#: file.c:424 +#, c-format +msgid "could not copy file range between old and new data directories: %m" +msgstr "kunde inte kopiera filintervall mellan gamla och nya datakatalogerna: %m" + +#: file.c:430 +#, c-format +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range stöds inte på denna plattform" + +#: file.c:447 #, c-format msgid "" -"could not create hard link between old and new data directories: %s\n" +"could not create hard link between old and new data directories: %m\n" "In link mode the old and new data directories must be on the same file system." msgstr "" -"kunde inte skapa hård länk mellan gamla och nya datakatalogerna: %s\n" +"kunde inte skapa hård länk mellan gamla och nya datakatalogerna: %m\n" "I länk-läge måste gamla och nya datakatalogerna vara i samma filsystem." -#: function.c:128 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "Kontrollerar att krävda länkbibliotek finns" -#: function.c:165 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "kunde inte ladda länkbibliotek \"%s\": %s" -#: function.c:176 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "I databas: %s\n" -#: function.c:186 +#: function.c:211 #, c-format msgid "" "Your installation references loadable libraries that are missing from the\n" @@ -939,137 +1182,151 @@ msgstr "" "med problembiblioteken finns i filen:\n" " %s" -#: info.c:126 +#: info.c:128 #, c-format msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" msgstr "Relationsname för OID %u i databas \"%s\" matchar inte: gammalt namn \"%s.%s\", nytt namn \"%s.%s\"" -#: info.c:146 +#: info.c:148 #, c-format msgid "Failed to match up old and new tables in database \"%s\"" msgstr "Misslyckades med att matcha ihop gamla och nya tabeller i databas \"%s\"" -#: info.c:227 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " vilket är ett index för \"%s.%s\"" -#: info.c:237 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " vilket är ett index för OID %u" -#: info.c:249 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " vilket är TOAST-tabellen för \"%s.%s\"" -#: info.c:257 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " vilket är TOAST-tabellen för OID %u" -#: info.c:261 +#: info.c:263 #, c-format msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" msgstr "Ingen träff hittad i gamla klustret för ny relation med OID %u i databas \"%s\": %s" -#: info.c:264 +#: info.c:266 #, c-format msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" msgstr "Ingen träff hittad i nya klustret för gammal relation med OID %u i databas \"%s\": %s" -#: info.c:289 +#: info.c:300 #, c-format msgid "" "\n" "source databases:" -msgstr "\nkälldatabaser:" +msgstr "" +"\n" +"källdatabaser:" -#: info.c:291 +#: info.c:302 #, c-format msgid "" "\n" "target databases:" -msgstr "\nmåldatabaser:" +msgstr "" +"\n" +"måldatabaser:" -#: info.c:329 +#: info.c:346 #, c-format msgid "template0 not found" msgstr "hittade inte template0" -#: info.c:645 +#: info.c:805 #, c-format -msgid "Database: %s" -msgstr "Databas: %s" +msgid "Database: \"%s\"" +msgstr "Databas: \"%s\"" -#: info.c:657 +#: info.c:818 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s" -msgstr "relnamn: %s.%s: reloid: %u reltblutrymme: %s" +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "relnamn: \"%s.%s\": reloid: %u reltblutrymme: \"%s\"" -#: option.c:101 +#: info.c:832 +#, c-format +msgid "Logical replication slots in the database:" +msgstr "Logiska replikeringsslottar i databasen:" + +#: info.c:838 +#, c-format +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "slot_name \"%s\", utdata-plugin \"%s\", two_phase \"%s\"" + +#: option.c:105 #, c-format msgid "%s: cannot be run as root" msgstr "%s: kan inte köras som root" -#: option.c:168 +#: option.c:172 #, c-format msgid "invalid old port number" msgstr "ogiltigt gammalt portnummer" -#: option.c:173 +#: option.c:177 #, c-format msgid "invalid new port number" msgstr "ogiltigt nytt portnummer" -#: option.c:203 +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Försök med \"%s --help\" för mer information.\n" -#: option.c:210 +#: option.c:223 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: option.c:213 +#: option.c:229 #, c-format msgid "Running in verbose mode" msgstr "Kör i utförligt läge" # FIXME: the source code need to be fixed here. it paste words together -#: option.c:231 +#: option.c:247 msgid "old cluster binaries reside" msgstr "gamla klusterbinärer är i" -#: option.c:233 +#: option.c:249 msgid "new cluster binaries reside" msgstr "nya klusterbinärer är i" -#: option.c:235 +#: option.c:251 msgid "old cluster data resides" msgstr "gamla klusterdatan är i" -#: option.c:237 +#: option.c:253 msgid "new cluster data resides" msgstr "nya klusterdatan är i" -#: option.c:239 +#: option.c:255 msgid "sockets will be created" msgstr "uttag kommer skapas" -#: option.c:256 option.c:356 +#: option.c:272 option.c:374 #, c-format msgid "could not determine current directory" msgstr "kunde inte bestämma aktuell katalog" -#: option.c:259 +#: option.c:275 #, c-format msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" msgstr "kan inte köra pg_upgrade inifrån nya klusterdatakatalogen i Windows" -#: option.c:268 +#: option.c:284 #, c-format msgid "" "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n" @@ -1078,12 +1335,12 @@ msgstr "" "pg_upgrade uppgraderar ett PostgreSQL-kluster till en annan major-version.\n" "\n" -#: option.c:269 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: option.c:270 +#: option.c:286 #, c-format msgid "" " pg_upgrade [OPTION]...\n" @@ -1092,17 +1349,17 @@ msgstr "" " pg_upgrade [FLAGGA]...\n" "\n" -#: option.c:271 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "Flaggor:\n" -#: option.c:272 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINKAT gamla klustrets katalog för körbara filer\n" -#: option.c:273 +#: option.c:289 #, c-format msgid "" " -B, --new-bindir=BINDIR new cluster executable directory (default\n" @@ -1111,97 +1368,107 @@ msgstr "" " -B, --new-bindir=BINKAT nya klustrets katalog för körbara filer\n" " (standard är samma som för pg_upgrade)\n" -#: option.c:275 +#: option.c:291 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check testa klustren bara, ändra ingen data\n" -#: option.c:276 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATAKAT gamla klustrets datakatalog\n" -#: option.c:277 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATAKAT nya klustrets datakatalog\n" -#: option.c:278 +#: option.c:294 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs=NUM antal samtidiga processer eller trådar att använda\n" -#: option.c:279 +#: option.c:295 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr " -k, --link länka istället för att kopiera filer till nya klustret\n" -#: option.c:280 +#: option.c:296 #, c-format msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" msgstr " -N, --no-sync vänta inte på att ändingar säkert skrivits till disk\n" -#: option.c:281 +#: option.c:297 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=FLAGGOR serverflaggor för gamla klustret\n" -#: option.c:282 +#: option.c:298 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=FLAGGOR serverflaggor för nya klustret\n" -#: option.c:283 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PORT gamla klustrets portnummer (standard %d)\n" -#: option.c:284 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT nya klustrets portnummer (standard %d)\n" -#: option.c:285 +#: option.c:301 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain behåll SQL och loggfiler efter lyckad uppgradering\n" -#: option.c:286 +#: option.c:302 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr " -s, --socketdir=KAT uttagskatalog (standard är aktuell katalog.)\n" -#: option.c:287 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=NAMN klustrets superuser (standard \"%s\")\n" -#: option.c:288 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose slå på utförligt intern loggning\n" -#: option.c:289 +#: option.c:305 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: option.c:290 +#: option.c:306 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr " -clone klona istället för att kopiera filer till nya klustret\n" -#: option.c:291 +#: option.c:307 #, c-format msgid " --copy copy files to new cluster (default)\n" msgstr " --copy kopiera filer till nya klustret (standard)\n" -#: option.c:292 +#: option.c:308 +#, c-format +msgid " --copy-file-range copy files to new cluster with copy_file_range\n" +msgstr " --copy-file-range kopiera filer till nya klustret med copy_file_range\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METOD sätt synkmetod för att synka filer till disk\n" + +#: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denns hjälp, avsluta sedan\n" -#: option.c:293 +#: option.c:311 #, c-format msgid "" "\n" @@ -1216,7 +1483,7 @@ msgstr "" " stänga ner den postmaster som hanterar gamla klustret\n" " stänga ner den postmaster som hanterar nya klustret\n" -#: option.c:298 +#: option.c:316 #, c-format msgid "" "\n" @@ -1233,7 +1500,7 @@ msgstr "" " \"bin\"-katalogen för gamla versionen (-b BINKAT)\n" " \"bin\"-katalogen för nya versionen (-B BINKAT)\n" -#: option.c:304 +#: option.c:322 #, c-format msgid "" "\n" @@ -1246,7 +1513,7 @@ msgstr "" " pg_upgrade -d gammaltKluster/data -D nyttKluster/data -b gammaltKluster/bin -B nyttKluster/bin\n" "eller\n" -#: option.c:309 +#: option.c:327 #, c-format msgid "" " $ export PGDATAOLD=oldCluster/data\n" @@ -1261,7 +1528,7 @@ msgstr "" " $ export PGBINNEW=nyttKluster/bin\n" " $ pg_upgrade\n" -#: option.c:315 +#: option.c:333 #, c-format msgid "" " C:\\> set PGDATAOLD=oldCluster/data\n" @@ -1276,7 +1543,7 @@ msgstr "" " C:\\> set PGBINNEW=nyttKluster/bin\n" " C:\\> pg_upgrade\n" -#: option.c:321 +#: option.c:339 #, c-format msgid "" "\n" @@ -1285,12 +1552,12 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: option.c:322 +#: option.c:340 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: option.c:362 +#: option.c:380 #, c-format msgid "" "You must identify the directory where the %s.\n" @@ -1299,45 +1566,50 @@ msgstr "" "Du måste identifiera katalogen där %s.\n" "Använd kommandoradsflaggan %s eller omgivningsvariabeln %s." -#: option.c:415 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Letar efter den riktiga datakatalogen i källklustret" -#: option.c:417 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Letar efter den riktiga datakatalogen för målklustret" -#: option.c:430 option.c:435 +#: option.c:448 +#, c-format +msgid "could not get data directory using %s: %m" +msgstr "kunde inte hämta datakatalogen med %s: %m" + +#: option.c:452 #, c-format msgid "could not get data directory using %s: %s" msgstr "kunde inte hämta datakatalogen med %s: %s" -#: option.c:484 +#: option.c:500 #, c-format -msgid "could not read line %d from file \"%s\": %s" -msgstr "kunde inte läsa rad %d från fil \"%s\": %s" +msgid "could not read line %d from file \"%s\": %m" +msgstr "kunde inte läsa rad %d från fil \"%s\": %m" -#: option.c:501 +#: option.c:517 #, c-format msgid "user-supplied old port number %hu corrected to %hu" msgstr "användarangivet gammalt portnummer %hu korrigerat till %hu" #: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker process: %s" -msgstr "kunde inte skapa arbetsprocess: %s" +msgid "could not create worker process: %m" +msgstr "kunde inte skapa arbetsprocess: %m" #: parallel.c:143 parallel.c:253 #, c-format -msgid "could not create worker thread: %s" -msgstr "kunde inte skapa arbetstråd: %s" +msgid "could not create worker thread: %m" +msgstr "kunde inte skapa arbetstråd: %m" #: parallel.c:294 #, c-format -msgid "%s() failed: %s" -msgstr "%s() misslyckades: %s" +msgid "%s() failed: %m" +msgstr "%s() misslyckades: %m" #: parallel.c:298 #, c-format @@ -1346,15 +1618,15 @@ msgstr "barnprocess avslutade felaktigt: status %d" #: parallel.c:313 #, c-format -msgid "child worker exited abnormally: %s" -msgstr "barnprocess avslutade felaktigt: %s" +msgid "child worker exited abnormally: %m" +msgstr "barnprocess avslutade felaktigt: %m" -#: pg_upgrade.c:107 +#: pg_upgrade.c:115 #, c-format -msgid "could not read permissions of directory \"%s\": %s" -msgstr "kunde inte läsa rättigheter på katalog \"%s\": %s" +msgid "could not read permissions of directory \"%s\": %m" +msgstr "kunde inte läsa rättigheter på katalog \"%s\": %m" -#: pg_upgrade.c:139 +#: pg_upgrade.c:147 #, c-format msgid "" "\n" @@ -1365,17 +1637,17 @@ msgstr "" "Utför uppgradering\n" "------------------" -#: pg_upgrade.c:184 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "Sätter nästa OID för nya klustret" -#: pg_upgrade.c:193 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "Synkar datakatalog till disk" -#: pg_upgrade.c:205 +#: pg_upgrade.c:230 #, c-format msgid "" "\n" @@ -1386,23 +1658,23 @@ msgstr "" "Uppgradering klar\n" "-----------------" -#: pg_upgrade.c:238 pg_upgrade.c:251 pg_upgrade.c:258 pg_upgrade.c:265 -#: pg_upgrade.c:283 pg_upgrade.c:294 +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 #, c-format msgid "directory path for new cluster is too long" msgstr "katalogsökväg för nytt kluster är för lång" -#: pg_upgrade.c:272 pg_upgrade.c:274 pg_upgrade.c:276 pg_upgrade.c:278 +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 #, c-format msgid "could not create directory \"%s\": %m" msgstr "kunde inte skapa katalog \"%s\": %m" -#: pg_upgrade.c:327 +#: pg_upgrade.c:352 #, c-format msgid "%s: could not find own program executable" msgstr "%s: kunde inte hitta det egna programmets körbara fil" -#: pg_upgrade.c:353 +#: pg_upgrade.c:378 #, c-format msgid "" "There seems to be a postmaster servicing the old cluster.\n" @@ -1411,7 +1683,7 @@ msgstr "" "Det verkar vara en postmaster igång som hanterar gamla klustret.\n" "Stänga ner den postmastern och försök igen." -#: pg_upgrade.c:366 +#: pg_upgrade.c:391 #, c-format msgid "" "There seems to be a postmaster servicing the new cluster.\n" @@ -1420,81 +1692,86 @@ msgstr "" "Det verkar vara en postmaster igång som hanterar nya klustret.\n" "Stänga ner den postmastern och försök igen." -#: pg_upgrade.c:388 +#: pg_upgrade.c:413 #, c-format msgid "Setting locale and encoding for new cluster" msgstr "Sätter lokal och teckenkodning för nya klustret" -#: pg_upgrade.c:450 +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Analyserar alla rader i nya klustret" -#: pg_upgrade.c:463 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Fryser alla rader i nya klustret" -#: pg_upgrade.c:483 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Återställer globala objekt i nya klustret" -#: pg_upgrade.c:499 +#: pg_upgrade.c:538 #, c-format msgid "Restoring database schemas in the new cluster" msgstr "Återställer databasscheman i nya klustret" -#: pg_upgrade.c:605 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "Raderar filer från ny %s" -#: pg_upgrade.c:609 +#: pg_upgrade.c:666 #, c-format msgid "could not delete directory \"%s\"" msgstr "kunde inte ta bort katalog \"%s\"" -#: pg_upgrade.c:628 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "Kopierar gammal %s till ny server" -#: pg_upgrade.c:654 +#: pg_upgrade.c:711 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Sätter äldsta XID för nya klustret" -#: pg_upgrade.c:662 +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "Sätter nästa transaktions-ID och epoch för nytt kluster" -#: pg_upgrade.c:692 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "Sätter nästa multixact-ID och offset för nytt kluster" -#: pg_upgrade.c:716 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Sätter äldsta multixact-ID i nytt kluster" -#: pg_upgrade.c:736 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "Resettar WAL-arkiv" -#: pg_upgrade.c:779 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Sätter räknarna frozenxid och minmxid för nytt kluster" -#: pg_upgrade.c:781 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Sätter räknarenm minmxid för nytt kluster" +#: pg_upgrade.c:929 +#, c-format +msgid "Restoring logical replication slots in the new cluster" +msgstr "Återställer logiska replikeringsslottar i nya klustret" + #: relfilenumber.c:35 #, c-format msgid "Cloning user relation files" @@ -1507,35 +1784,45 @@ msgstr "Kopierar användarens relationsfiler" #: relfilenumber.c:41 #, c-format +msgid "Copying user relation files with copy_file_range" +msgstr "Kopierar användarens relationsfiler med copy_file_range" + +#: relfilenumber.c:44 +#, c-format msgid "Linking user relation files" msgstr "Länkar användarens relationsfiler" -#: relfilenumber.c:115 +#: relfilenumber.c:118 #, c-format msgid "old database \"%s\" not found in the new cluster" msgstr "gamla databasen \"%s\" kan inte hittas i nya klustret" -#: relfilenumber.c:218 +#: relfilenumber.c:221 #, c-format -msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s" -msgstr "fel vid kontroll av filexistens \"%s.%s\" (\"%s\" till \"%s\"): %s" +msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "fel vid kontroll av filexistens \"%s.%s\" (\"%s\" till \"%s\"): %m" -#: relfilenumber.c:236 +#: relfilenumber.c:238 #, c-format msgid "rewriting \"%s\" to \"%s\"" msgstr "skriver om \"%s\" till \"%s\"" -#: relfilenumber.c:244 +#: relfilenumber.c:246 #, c-format msgid "cloning \"%s\" to \"%s\"" msgstr "klonar \"%s\" till \"%s\"" -#: relfilenumber.c:249 +#: relfilenumber.c:251 #, c-format msgid "copying \"%s\" to \"%s\"" msgstr "kopierar \"%s\" till \"%s\"" -#: relfilenumber.c:254 +#: relfilenumber.c:256 +#, c-format +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "kopierar \"%s\" till \"%s\" med copy_file_range" + +#: relfilenumber.c:261 #, c-format msgid "linking \"%s\" to \"%s\"" msgstr "länkar \"%s\" till \"%s\"" @@ -1571,7 +1858,7 @@ msgstr "kunde inte öppna versionsfil \"%s\": %m" msgid "could not parse version file \"%s\"" msgstr "kunde inte tolka versionsfil \"%s\"" -#: server.c:288 +#: server.c:310 #, c-format msgid "" "\n" @@ -1580,7 +1867,7 @@ msgstr "" "\n" "%s" -#: server.c:292 +#: server.c:314 #, c-format msgid "" "could not connect to source postmaster started with the command:\n" @@ -1589,7 +1876,7 @@ msgstr "" "kunde inte ansluta till käll-postmaster som startats med kommandot:\n" "%s" -#: server.c:296 +#: server.c:318 #, c-format msgid "" "could not connect to target postmaster started with the command:\n" @@ -1598,22 +1885,22 @@ msgstr "" "kunde inte ansluta till mål-postmaster som startats med kommandot:\n" "%s" -#: server.c:310 +#: server.c:332 #, c-format msgid "pg_ctl failed to start the source server, or connection failed" msgstr "pg_ctl misslyckades att start källservern eller så misslyckades anslutningen" -#: server.c:312 +#: server.c:334 #, c-format msgid "pg_ctl failed to start the target server, or connection failed" msgstr "pg_ctl misslyckades att start målservern eller så misslyckades anslutningen" -#: server.c:357 +#: server.c:379 #, c-format msgid "out of memory" msgstr "slut på minne" -#: server.c:370 +#: server.c:392 #, c-format msgid "libpq environment variable %s has a non-local server value: %s" msgstr "libpq:s omgivningsvariabel %s har ett icke-lokalt servervärde: %s" @@ -1634,8 +1921,8 @@ msgstr "tablespace-katalogen \"%s\" finns inte" #: tablespace.c:87 #, c-format -msgid "could not stat tablespace directory \"%s\": %s" -msgstr "kunde inte göra stat på tablespace-katalog \"%s\": %s" +msgid "could not stat tablespace directory \"%s\": %m" +msgstr "kunde inte göra stat på tablespace-katalog \"%s\": %m" #: tablespace.c:92 #, c-format @@ -1657,63 +1944,17 @@ msgstr "kunde inte komma åt katalog \"%s\": %m" msgid "ok" msgstr "ok" -# FIXME: is this msgid correct? -#: version.c:184 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "Letar efter inkompatibel \"line\"-datatyp" - -#: version.c:193 -#, c-format -msgid "" -"Your installation contains the \"line\" data type in user tables.\n" -"This data type changed its internal and input/output format\n" -"between your old and new versions so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Din installation innehåller datatypen \"line\" i användartabeller. Denna\n" -"datatype har ändrat sitt interna format samt sitt in/ut-format mellan din\n" -"gamla och nya version så detta kluster kan för närvarande inte uppgraderas.\n" -"Du kan radera problemkolumnerna och återstarta uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" -" %s" - -#: version.c:224 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "Letar efter ogiltiga användarkolumner av typen \"unknown\"" - -#: version.c:233 -#, c-format -msgid "" -"Your installation contains the \"unknown\" data type in user tables.\n" -"This data type is no longer allowed in tables, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Din installation innehåller datatypen \"unknown\" i användartabeller.\n" -"Denna datatyp tillåts inte längre i tabeller så detta kluster kan\n" -"för närvarande inte uppgraderas. Du kan radera problemkolumnerna och\n" -"återstarta uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" -" %s" - -#: version.c:257 +#: version.c:44 #, c-format msgid "Checking for hash indexes" msgstr "Letar efter hash-index" -#: version.c:335 +#: version.c:121 #, c-format msgid "warning" msgstr "varning" -#: version.c:337 +#: version.c:123 #, c-format msgid "" "\n" @@ -1728,7 +1969,7 @@ msgstr "" "kommandot REINDEX. Efter uppgraderingen så kommer du få\n" "REINDEX-instruktioner." -#: version.c:343 +#: version.c:129 #, c-format msgid "" "\n" @@ -1747,39 +1988,17 @@ msgstr "" "kan köras med psql av databasens superuser och kommer återskapa alla\n" "ogiltiga index; innan dess så kommer inget av dess index användas." -#: version.c:369 -#, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "Letar efter ogiltiga användarkolumner av typen \"sql_identifier\"" - -#: version.c:379 -#, c-format -msgid "" -"Your installation contains the \"sql_identifier\" data type in user tables.\n" -"The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s" -msgstr "" -"Din installation innehåller datatypen \"sql_identifier\" i användartabeller.\n" -"Formatet på disk för denna datatyp har ändrats så detta kluster kan för\n" -"närvarande inte uppgraderas. Du kan radera problemkolumnerna och\n" -"återstarta uppgraderingen.\n" -"En lista med problemkolumner finns i filen:\n" -" %s" - -#: version.c:402 +#: version.c:153 #, c-format msgid "Checking for extension updates" msgstr "Letar efter uppdatering av utökningar" -#: version.c:450 +#: version.c:200 #, c-format msgid "notice" msgstr "notis" -#: version.c:451 +#: version.c:201 #, c-format msgid "" "\n" @@ -1795,99 +2014,3 @@ msgstr "" " %s\n" "kan köras med psql av databasens superuser och kommer uppdatera\n" "dessa utökningar." - -#, c-format -#~ msgid "" -#~ "\n" -#~ "\n" -#~ msgstr "" -#~ "\n" -#~ "\n" - -#, c-format -#~ msgid "%-*s\n" -#~ msgstr "%-*s\n" - -#, c-format -#~ msgid "%s\n" -#~ msgstr "%s\n" - -#, c-format -#~ msgid "%s() failed: %s\n" -#~ msgstr "%s() misslyckades: %s\n" - -#, c-format -#~ msgid "ICU locale values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "inställning av ICU-lokal för databasen \"%s\" matchar inte: gammal \"%s\", ny \"%s\"\n" - -#, c-format -#~ msgid "The source cluster contains roles starting with \"pg_\"\n" -#~ msgstr "Källklustret innehåller roller som startar med \"pg_\"\n" - -#, c-format -#~ msgid "The target cluster contains roles starting with \"pg_\"\n" -#~ msgstr "Målklustret innehåller roller som startar med \"pg_\"\n" - -#, c-format -#~ msgid "Unable to rename %s to %s.\n" -#~ msgstr "Kan inte byta namn på %s till %s.\n" - -#, c-format -#~ msgid "check for \"%s\" failed: cannot execute (permission denied)\n" -#~ msgstr "kontroll av \"%s\" misslyckades: kan inte exekvera (rättighet saknas)\n" - -#, c-format -#~ msgid "check for \"%s\" failed: not a regular file\n" -#~ msgstr "kontroll av \"%s\" misslyckades: inte en vanlig fil\n" - -#, c-format -#~ msgid "could not access directory \"%s\": %m\n" -#~ msgstr "kunde inte komma åt katalog \"%s\": %m\n" - -#, c-format -#~ msgid "could not create directory \"%s\": %m\n" -#~ msgstr "kunde inte skapa katalog \"%s\": %m\n" - -#, c-format -#~ msgid "could not open file \"%s\": %s\n" -#~ msgstr "kan inte öppna fil \"%s\": %s\n" - -#, c-format -#~ msgid "could not open log file \"%s\": %m\n" -#~ msgstr "kunde inte öppna loggfil \"%s\": %m\n" - -#, c-format -#~ msgid "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "kodning för databasen \"%s\" matchar inte: gammal \"%s\", ny \"%s\"\n" - -#, c-format -#~ msgid "failed to get system locale name for \"%s\"\n" -#~ msgstr "misslyckades med att hämta systemlokalnamn för \"%s\"\n" - -#, c-format -#~ msgid "failed to get the current locale\n" -#~ msgstr "misslyckades med att hämta aktuell lokal\n" - -#, c-format -#~ msgid "failed to restore old locale \"%s\"\n" -#~ msgstr "misslyckades med att återställa gamla lokalen \"%s\"\n" - -#, c-format -#~ msgid "lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "lc_collate-värden för databasen \"%s\" matchar inte: gammal \"%s\", ny \"%s\"\n" - -#, c-format -#~ msgid "lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "lc_ctype-värden för databasen \"%s\" matchar inte: gammal \"%s\", ny \"%s\"\n" - -#, c-format -#~ msgid "locale providers for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -#~ msgstr "localleverantörer för databasen \"%s\" matchar inte: gammal \"%s\", ny \"%s\"\n" - -#, c-format -#~ msgid "out of memory\n" -#~ msgstr "slut på minne\n" - -#, c-format -#~ msgid "too many command-line arguments (first is \"%s\")\n" -#~ msgstr "för många kommandoradsargument (första är \"%s\")\n" diff --git a/src/bin/pg_upgrade/po/uk.po b/src/bin/pg_upgrade/po/uk.po index dc300e50bc4e0..4a0ec9a1eda8c 100644 --- a/src/bin/pg_upgrade/po/uk.po +++ b/src/bin/pg_upgrade/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-17 08:46+0000\n" -"PO-Revision-Date: 2021-08-17 11:18\n" +"POT-Creation-Date: 2024-08-31 06:20+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,229 +14,425 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_14_DEV/pg_upgrade.pot\n" -"X-Crowdin-File-ID: 778\n" +"X-Crowdin-File: /REL_17_STABLE/pg_upgrade.pot\n" +"X-Crowdin-File-ID: 1028\n" -#: check.c:70 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/restricted_token.c:168 +#, c-format +msgid "could not get exit code from subprocess: error code %lu" +msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu" + +#: ../../common/username.c:43 +#, c-format +msgid "could not look up effective user ID %ld: %s" +msgstr "не можу знайти користувача з ефективним ID %ld: %s" + +#: ../../common/username.c:45 +msgid "user does not exist" +msgstr "користувача не існує" + +#: ../../common/username.c:60 +#, c-format +msgid "user name lookup failure: error code %lu" +msgstr "невдала підстановка імені користувача: код помилки %lu" + +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: check.c:111 +msgid "Checking for system-defined composite types in user tables" +msgstr "Перевірка складених типів визначених системою у таблицях користувача" + +#: check.c:118 +msgid "Your installation contains system-defined composite types in user tables.\n" +"These type OIDs are not stable across PostgreSQL versions,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить системно визначені складені типи у таблицях користувачів.\n" +"OID цих типів не стабільні між версіями PostgreSQL, тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:132 +msgid "Checking for incompatible \"line\" data type" +msgstr "Перевірка несумісного типу даних \"line\"" + +#: check.c:137 +msgid "Your installation contains the \"line\" data type in user tables.\n" +"This data type changed its internal and input/output format\n" +"between your old and new versions so this\n" +"cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить тип даних \"line\" в таблицях користувача.\n" +"Внутрішній формат та формат вводу/виводу цього типу даних змінено між вашою старою та новими версіями,\n" +"тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:154 +msgid "Checking for reg* data types in user tables" +msgstr "Перевірка типів даних reg* в користувацьких таблицях" + +#: check.c:181 +msgid "Your installation contains one of the reg* data types in user tables.\n" +"These data types reference system OIDs that are not preserved by\n" +"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" +"drop the problem columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить один з типів даних reg* у таблицях користувача.\n" +"Ці типи даних посилаються на OID системи, які не зберігаються за допомогою pg_upgrade, тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:193 +msgid "Checking for incompatible \"aclitem\" data type" +msgstr "Перевірка несумісного типу даних \"aclitem\"" + +#: check.c:198 +msgid "Your installation contains the \"aclitem\" data type in user tables.\n" +"The internal format of \"aclitem\" changed in PostgreSQL version 16\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить тип даних \"aclitem\" у таблицях користувача. Внутрішній формат \"aclitem\" змінено під час версії 16,\n" +"тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:217 +msgid "Checking for invalid \"unknown\" user columns" +msgstr "Перевірка неприпустимих користувацьких стовпців \"unknown\"" + +#: check.c:222 +msgid "Your installation contains the \"unknown\" data type in user tables.\n" +"This data type is no longer allowed in tables, so this cluster\n" +"cannot currently be upgraded. You can drop the problem columns\n" +"and restart the upgrade.\n" +msgstr "Ваша інсталяція містить \"unknown\" тип даних у таблицях користувача.\n" +"Цей тип даних більше не допускається в таблицях,\n" +"тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:239 +msgid "Checking for invalid \"sql_identifier\" user columns" +msgstr "Перевірка неприпустимих користувацьких стовпців \"sql_identifier\"" + +#: check.c:244 +msgid "Your installation contains the \"sql_identifier\" data type in user tables.\n" +"The on-disk format for this data type has changed, so this\n" +"cluster cannot currently be upgraded. You can drop the problem\n" +"columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить \"sql_identifier\" тип даних у таблицях користувача.\n" +"Формат зберігання для цього типу даних змінено,\n" +"тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:255 +msgid "Checking for incompatible \"jsonb\" data type in user tables" +msgstr "Перевірка несумісного типу даних \"jsonb\" в користувацьких таблицях" + +#: check.c:260 +msgid "Your installation contains the \"jsonb\" data type in user tables.\n" +"The internal format of \"jsonb\" changed during 9.4 beta so this\n" +"cluster cannot currently be upgraded. You can drop the problem \n" +"columns and restart the upgrade.\n" +msgstr "Ваша інсталяція містить тип даних \"jsonb\" у таблицях користувача.\n" +"Внутрішній формат \"jsonb\" змінено під час версії 9.4 beta,\n" +"тому цей кластер наразі не може бути оновлений.\n" +"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" + +#: check.c:272 +msgid "Checking for removed \"abstime\" data type in user tables" +msgstr "Перевірка видаленого типу даних \"abstime\" в користувацьких таблицях" + +#: check.c:277 +msgid "Your installation contains the \"abstime\" data type in user tables.\n" +"The \"abstime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "Користувацькі таблиці у вашій інсталяції містять тип даних \"abstime\".\n" +"Тип \"abstime\" був видалений з версії PostgreSQL 12, тому цей кластер \n" +"наразі не може бути оновлений. Ви можете видалите проблемні \n" +"стовпці або змінити їх на інший тип даних, і перезапустити\n" +"оновлення.\n" + +#: check.c:285 +msgid "Checking for removed \"reltime\" data type in user tables" +msgstr "Перевірка видаленого типу даних \"reltime\" в користувацьких таблицях" + +#: check.c:290 +msgid "Your installation contains the \"reltime\" data type in user tables.\n" +"The \"reltime\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "Користувацькі таблиці у вашій інсталяції містять тип даних \"reltime\".\n" +"Тип \"reltime\" був видалений з версії PostgreSQL 12, тому цей кластер \n" +"наразі не може бути оновлений. Ви можете видалите проблемні \n" +"стовпці або змінити їх на інший тип даних, і перезапустити\n" +"оновлення.\n" + +#: check.c:298 +msgid "Checking for removed \"tinterval\" data type in user tables" +msgstr "Перевірка видаленого типу даних \"tinterval\" в користувацьких таблицях" + +#: check.c:303 +msgid "Your installation contains the \"tinterval\" data type in user tables.\n" +"The \"tinterval\" type has been removed in PostgreSQL version 12,\n" +"so this cluster cannot currently be upgraded. You can drop the\n" +"problem columns, or change them to another data type, and restart\n" +"the upgrade.\n" +msgstr "Користувацькі таблиці у вашій інсталяції містять тип даних \"tinterval\".\n" +"Тип \"tinterval\" був видалений з версії PostgreSQL 12, тому цей кластер \n" +"наразі не може бути оновлений. Ви можете видалите проблемні \n" +"стовпці або змінити їх на інший тип даних, і перезапустити\n" +"оновлення.\n" + +#: check.c:345 +#, c-format +msgid "Checking data type usage" +msgstr "Перевірка використання типів даних" + +#: check.c:480 +#, c-format +msgid " failed check: %s" +msgstr " помилка перевірки: %s" + +#: check.c:483 +msgid "A list of the problem columns is in the file:" +msgstr "Список проблемних стовпців знаходиться у файлі:" + +#: check.c:495 check.c:963 check.c:1136 check.c:1251 check.c:1345 check.c:1473 +#: check.c:1549 check.c:1613 check.c:1686 check.c:1865 check.c:1884 +#: check.c:1953 check.c:2005 file.c:378 file.c:415 function.c:189 option.c:493 +#: version.c:79 version.c:177 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: check.c:522 +#, c-format +msgid "Data type checks failed: %s" +msgstr "Помилка перевірки типів даних: %s" + +#: check.c:563 #, c-format msgid "Performing Consistency Checks on Old Live Server\n" -"------------------------------------------------\n" +"------------------------------------------------" msgstr "Перевірка цілістності на старому працюючому сервері\n" -"------------------------------------------------\n" +"------------------------------------------------" -#: check.c:76 +#: check.c:569 #, c-format msgid "Performing Consistency Checks\n" -"-----------------------------\n" +"-----------------------------" msgstr "Проведення перевірок цілістності\n" -"-----------------------------\n" +"-----------------------------" -#: check.c:213 +#: check.c:718 #, c-format msgid "\n" -"*Clusters are compatible*\n" +"*Clusters are compatible*" msgstr "\n" -"*Кластери сумісні*\n" +"*Кластери сумісні*" -#: check.c:219 +#: check.c:726 #, c-format msgid "\n" "If pg_upgrade fails after this point, you must re-initdb the\n" -"new cluster before continuing.\n" +"new cluster before continuing." msgstr "\n" "Якщо робота pg_upgrade після цієї точки перерветься, вам потрібно буде заново виконати initdb \n" -"для нового кластера, перед продовженням.\n" +"для нового кластера, перед продовженням." -#: check.c:264 +#: check.c:767 #, c-format msgid "Optimizer statistics are not transferred by pg_upgrade.\n" "Once you start the new server, consider running:\n" -" %s/vacuumdb %s--all --analyze-in-stages\n\n" +" %s/vacuumdb %s--all --analyze-in-stages" msgstr "Статистика оптимізатора не передається за допомогою pg_upgrade.\n" -"Після запуску нового серверу, розгляньте можливість запуску:\n" -" %s/vacuumdb %s--all --analyze-in-stages\n\n" +"Після запуску нового серверу розгляньте можливість запуску:\n" +" %s/vacuumdb %s--all --analyze-in-stages" -#: check.c:270 +#: check.c:773 #, c-format msgid "Running this script will delete the old cluster's data files:\n" -" %s\n" +" %s" msgstr "При запуску цього скрипту файли даних старого кластера будуть видалені:\n" -" %s\n" +" %s" -#: check.c:275 +#: check.c:778 #, c-format msgid "Could not create a script to delete the old cluster's data files\n" "because user-defined tablespaces or the new cluster's data directory\n" "exist in the old cluster directory. The old cluster's contents must\n" -"be deleted manually.\n" +"be deleted manually." msgstr "Не вдалося створити скрипт для видалення файлів даних старого кластеру,\n" "тому що каталог даних старого кластера містить користувацькі табличні\n" "простори або каталог даних нового кластера. Вміст старого кластера\n" -"треба буде видалити вручну.\n" +"треба буде видалити вручну." -#: check.c:287 +#: check.c:790 #, c-format msgid "Checking cluster versions" msgstr "Перевірка версій кластерів" -#: check.c:299 -#, c-format -msgid "This utility can only upgrade from PostgreSQL version 8.4 and later.\n" -msgstr "Ця утиліта може виконувати оновлення тільки з версії PostgreSQL 8.4 і новіше.\n" - -#: check.c:303 +#: check.c:802 #, c-format -msgid "This utility can only upgrade to PostgreSQL version %s.\n" -msgstr "Ця утиліта може тільки підвищувати версію PostgreSQL до %s.\n" +msgid "This utility can only upgrade from PostgreSQL version %s and later." +msgstr "Ця утиліта може виконувати оновлення тільки з версії PostgreSQL %s і новіше." -#: check.c:312 +#: check.c:807 #, c-format -msgid "This utility cannot be used to downgrade to older major PostgreSQL versions.\n" -msgstr "Ця утиліта не може не може використовуватись щоб понижувати версію до більш старих основних версій PostgreSQL.\n" +msgid "This utility can only upgrade to PostgreSQL version %s." +msgstr "Ця утиліта може тільки підвищувати версію PostgreSQL до версії %s." -#: check.c:317 +#: check.c:816 #, c-format -msgid "Old cluster data and binary directories are from different major versions.\n" -msgstr "Каталог даних і двійковий каталог старого кластера з різних основних версій.\n" +msgid "This utility cannot be used to downgrade to older major PostgreSQL versions." +msgstr "Ця утиліта не може використовуватись для пониження версії до більш старих основних версій PostgreSQL." -#: check.c:320 +#: check.c:821 #, c-format -msgid "New cluster data and binary directories are from different major versions.\n" -msgstr "Каталог даних і двійковий каталог нового кластера з різних основних версій.\n" +msgid "Old cluster data and binary directories are from different major versions." +msgstr "Каталог даних і двійковий каталог старого кластера з різних основних версій." -#: check.c:337 +#: check.c:824 #, c-format -msgid "When checking a pre-PG 9.1 live old server, you must specify the old server's port number.\n" -msgstr "Для перевірки старого працюючого сервера до версії 9.1, вам необхідно вказати номер порта цього сервера.\n" +msgid "New cluster data and binary directories are from different major versions." +msgstr "Каталог даних нового кластера і двійковий каталог з різних основних версій." -#: check.c:341 +#: check.c:839 #, c-format -msgid "When checking a live server, the old and new port numbers must be different.\n" -msgstr "Для перевірки працюючого сервера, старий і новий номер порта повинні бути різними.\n" +msgid "When checking a live server, the old and new port numbers must be different." +msgstr "Для перевірки працюючого сервера, старий і новий номер порта повинні бути різними." -#: check.c:356 +#: check.c:859 #, c-format -msgid "encodings for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "кодування для бази даних \"%s\" не збігаються: старе \"%s\", нове \"%s\"\n" +msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"" +msgstr "Новий кластер бази даних \"%s\" не порожній: знайдено відношення \"%s.%s\"" -#: check.c:361 -#, c-format -msgid "lc_collate values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "значення lc_collate для бази даних \"%s\" не збігаються: старе \"%s\", нове \"%s\"\n" - -#: check.c:364 -#, c-format -msgid "lc_ctype values for database \"%s\" do not match: old \"%s\", new \"%s\"\n" -msgstr "значення lc_ctype для бази даних \"%s\" не збігаються: старе \"%s\", нове \"%s\"\n" - -#: check.c:437 -#, c-format -msgid "New cluster database \"%s\" is not empty: found relation \"%s.%s\"\n" -msgstr "Новий кластер бази даних \"%s\" не порожній: знайдено відношення \"%s.%s\"\n" - -#: check.c:494 +#: check.c:882 #, c-format msgid "Checking for new cluster tablespace directories" msgstr "Перевірка каталогів табличних просторів кластера" -#: check.c:505 +#: check.c:893 #, c-format -msgid "new cluster tablespace directory already exists: \"%s\"\n" -msgstr "каталог нового кластерного табличного простору вже існує: \"%s\"\n" +msgid "new cluster tablespace directory already exists: \"%s\"" +msgstr "каталог нового кластерного табличного простору вже існує: \"%s\"" -#: check.c:538 +#: check.c:926 #, c-format msgid "\n" -"WARNING: new data directory should not be inside the old data directory, e.g. %s\n" +"WARNING: new data directory should not be inside the old data directory, i.e. %s" msgstr "\n" -"ПОПЕРЕДЖЕННЯ: новий каталог даних не повинен бути всередині старого каталогу даних, наприклад %s\n" +"ПОПЕРЕДЖЕННЯ: новий каталог даних не повинен бути всередині старого каталогу даних, наприклад %s" -#: check.c:562 +#: check.c:950 #, c-format msgid "\n" -"WARNING: user-defined tablespace locations should not be inside the data directory, e.g. %s\n" +"WARNING: user-defined tablespace locations should not be inside the data directory, i.e. %s" msgstr "\n" -"ПОПЕРЕДЖЕННЯ: користувацькі розташування табличних просторів не повинні бути всередині каталогу даних, наприклад %s\n" +"ПОПЕРЕДЖЕННЯ: користувацькі розташування табличних просторів не повинні бути всередині каталогу даних, наприклад %s" -#: check.c:572 +#: check.c:960 #, c-format msgid "Creating script to delete old cluster" msgstr "Створення скрипту для видалення старого кластеру" -#: check.c:575 check.c:839 check.c:937 check.c:1016 check.c:1278 file.c:336 -#: function.c:240 option.c:497 version.c:54 version.c:204 version.c:376 -#: version.c:511 -#, c-format -msgid "could not open file \"%s\": %s\n" -msgstr "не вдалося відкрити файл \"%s\": %s\n" - -#: check.c:631 +#: check.c:1014 #, c-format -msgid "could not add execute permission to file \"%s\": %s\n" -msgstr "не вдалося додати право виконання для файлу \"%s\": %s\n" +msgid "could not add execute permission to file \"%s\": %m" +msgstr "не вдалося додати право виконання для файлу \"%s\": %m" -#: check.c:651 +#: check.c:1034 #, c-format msgid "Checking database user is the install user" msgstr "Перевірка, чи є користувач бази даних стартовим користувачем" -#: check.c:667 +#: check.c:1050 #, c-format -msgid "database user \"%s\" is not the install user\n" -msgstr "користувач бази даних \"%s\" не є стартовим користувачем\n" +msgid "database user \"%s\" is not the install user" +msgstr "користувач бази даних \"%s\" не є стартовим користувачем" -#: check.c:678 +#: check.c:1061 #, c-format -msgid "could not determine the number of users\n" -msgstr "не вдалося визначити кількість користувачів\n" +msgid "could not determine the number of users" +msgstr "не вдалося визначити кількість користувачів" -#: check.c:686 +#: check.c:1069 #, c-format -msgid "Only the install user can be defined in the new cluster.\n" -msgstr "В новому кластері може бути визначеним тільки стартовий користувач.\n" +msgid "Only the install user can be defined in the new cluster." +msgstr "В новому кластері може бути визначеним тільки стартовий користувач." -#: check.c:706 +#: check.c:1098 #, c-format msgid "Checking database connection settings" msgstr "Перевірка параметрів підключення до бази даних" -#: check.c:728 +#: check.c:1124 +#, c-format +msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false" +msgstr "template0 не повинна дозволяти підключення, тобто pg_database.datallowconn повинно бути false" + +#: check.c:1150 check.c:1270 check.c:1367 check.c:1492 check.c:1568 +#: check.c:1626 check.c:1706 check.c:1897 check.c:2022 function.c:210 #, c-format -msgid "template0 must not allow connections, i.e. its pg_database.datallowconn must be false\n" -msgstr "template0 не повинна дозволяти підключення, тобто pg_database.datallowconn повинно бути false\n" +msgid "fatal" +msgstr "збій" -#: check.c:738 +#: check.c:1151 #, c-format -msgid "All non-template0 databases must allow connections, i.e. their pg_database.datallowconn must be true\n" -msgstr "Всі бази даних, окрім template0, повинні дозволяти підключення, тобто pg_database.datallowconn повинно бути true\n" +msgid "All non-template0 databases must allow connections, i.e. their\n" +"pg_database.datallowconn must be true. Your installation contains\n" +"non-template0 databases with their pg_database.datallowconn set to\n" +"false. Consider allowing connection for all non-template0 databases\n" +"or drop the databases which do not allow connections. A list of\n" +"databases with the problem is in the file:\n" +" %s" +msgstr "Всі бази даних, окрім template0, повинні дозволяти підключення, тобто\n" +"pg_database.datallowconn повинно бути true. Ваша інсталяція містить\n" +"бази даних окрім template0 значення pg_database.datallowconn яких дорівнює \n" +"false. Розгляньте можливість надати дозвіл на з’єднання для всіх баз даних, \n" +"які не є шаблоном, або видалити баз даних, які не дозволяють з’єднання. \n" +"Список баз даних з проблемою знаходиться у файлі:\n" +" %s" -#: check.c:763 +#: check.c:1176 #, c-format msgid "Checking for prepared transactions" msgstr "Перевірка підготовлених транзакцій" -#: check.c:772 +#: check.c:1185 #, c-format -msgid "The source cluster contains prepared transactions\n" -msgstr "Початковий кластер містить підготовлені транзакції\n" +msgid "The source cluster contains prepared transactions" +msgstr "Початковий кластер містить підготовлені транзакції" -#: check.c:774 +#: check.c:1187 #, c-format -msgid "The target cluster contains prepared transactions\n" -msgstr "Цільовий кластер містить підготовлені транзакції\n" +msgid "The target cluster contains prepared transactions" +msgstr "Цільовий кластер містить підготовлені транзакції" -#: check.c:800 +#: check.c:1212 #, c-format msgid "Checking for contrib/isn with bigint-passing mismatch" msgstr "Перевірка невідповідності при передаванні bigint в contrib/isn" -#: check.c:861 check.c:962 check.c:1038 check.c:1095 check.c:1154 check.c:1183 -#: check.c:1301 function.c:262 version.c:278 version.c:316 version.c:460 -#, c-format -msgid "fatal\n" -msgstr "збій\n" - -#: check.c:862 +#: check.c:1271 #, c-format msgid "Your installation contains \"contrib/isn\" functions which rely on the\n" "bigint data type. Your old and new clusters pass bigint values\n" @@ -244,909 +440,932 @@ msgid "Your installation contains \"contrib/isn\" functions which rely on the\n" "manually dump databases in the old cluster that use \"contrib/isn\"\n" "facilities, drop them, perform the upgrade, and then restore them. A\n" "list of the problem functions is in the file:\n" -" %s\n\n" +" %s" msgstr "Ваша інсталяція містить функції \"contrib/isn\", що використовують тип даних bigint. Старі та нові кластери передають значення bigint по-різному, тому цей кластер наразі неможливо оновити. Ви можете вручну вивантажити бази даних зі старого кластеру, що використовує засоби \"contrib/isn\", видалити їх, виконати оновлення, а потім відновити їх. Список проблемних функцій подано у файлі:\n" -" %s\n\n" +" %s" -#: check.c:885 +#: check.c:1293 #, c-format msgid "Checking for user-defined postfix operators" msgstr "Перевірка постфіксних операторів визначених користувачем" -#: check.c:963 +#: check.c:1368 #, c-format msgid "Your installation contains user-defined postfix operators, which are not\n" "supported anymore. Consider dropping the postfix operators and replacing\n" "them with prefix operators or function calls.\n" "A list of user-defined postfix operators is in the file:\n" -" %s\n\n" +" %s" msgstr "Ваша інсталяція містить користувацькі постфіксні оператори, що більше не підтримуються.\n" "Розгляньте можливість видалення постфіксних операторів та заміни їх на префіксні оператори або виклики функцій.\n" "Список користувацьких постфіксних операторів знаходиться у файлі:\n" -" %s\n\n" +" %s" -#: check.c:984 +#: check.c:1392 +#, c-format +msgid "Checking for incompatible polymorphic functions" +msgstr "Перевірка несумісних поліморфних функцій" + +#: check.c:1493 +#, c-format +msgid "Your installation contains user-defined objects that refer to internal\n" +"polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n" +"These user-defined objects must be dropped before upgrading and restored\n" +"afterwards, changing them to refer to the new corresponding functions with\n" +"arguments of type \"anycompatiblearray\" and \"anycompatible\".\n" +"A list of the problematic objects is in the file:\n" +" %s" +msgstr "У вашій інсталяції містяться користувацькі об'єкти, які посилаються на внутрішні\n" +"поліморфні функції з аргументами типу \"anyarray\" або \"anyelement\".\n" +"Ці користувацькі об'єкти повинні бути видалені перед оновленням і відновлені\n" +"після цього, змінивши їх посилання на нові відповідні функції з\n" +"аргументами типу \"anycompatiblearray\" і \"anycompatible\".\n" +"Список проблемних об'єктів знаходиться у файлі:\n" +" %s" + +#: check.c:1517 #, c-format msgid "Checking for tables WITH OIDS" msgstr "Перевірка таблиць WITH OIDS" -#: check.c:1039 +#: check.c:1569 #, c-format msgid "Your installation contains tables declared WITH OIDS, which is not\n" "supported anymore. Consider removing the oid column using\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "A list of tables with the problem is in the file:\n" -" %s\n\n" +" %s" msgstr "Ваша інсталяція містить таблиці, створені як WITH OIDS, що більше не підтримуються. Розгляньте видалення стовпців, що містять oid за допомогою\n" " ALTER TABLE ... SET WITHOUT OIDS;\n" "Список проблемних таблиць подано у файлі:\n" -" %s\n\n" - -#: check.c:1067 -#, c-format -msgid "Checking for system-defined composite types in user tables" -msgstr "Перевірка складених типів визначених системою у таблицях користувача" - -#: check.c:1096 -#, c-format -msgid "Your installation contains system-defined composite type(s) in user tables.\n" -"These type OIDs are not stable across PostgreSQL versions,\n" -"so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить складені типи визначені системою у таблицях користувача.\n" -"Ці типи OID не стабільні між версіями PostgreSQL, тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" - -#: check.c:1124 -#, c-format -msgid "Checking for reg* data types in user tables" -msgstr "Перевірка типів даних reg* в користувацьких таблицях" +" %s" -#: check.c:1155 -#, c-format -msgid "Your installation contains one of the reg* data types in user tables.\n" -"These data types reference system OIDs that are not preserved by\n" -"pg_upgrade, so this cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить один з типів даних reg* у таблицях користувача.\n" -"Ці типи даних посилаються на OID системи, які не зберігаються за допомогою pg_upgrade, тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" - -#: check.c:1177 -#, c-format -msgid "Checking for incompatible \"jsonb\" data type" -msgstr "Перевірка несумісного типу даних \"jsonb\"" - -#: check.c:1184 -#, c-format -msgid "Your installation contains the \"jsonb\" data type in user tables.\n" -"The internal format of \"jsonb\" changed during 9.4 beta so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить тип даних \"jsonb\" у таблицях користувача.\n" -"Внутрішній формат \"jsonb\" змінено під час версії 9.4 beta,\n" -"тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" - -#: check.c:1206 +#: check.c:1596 #, c-format msgid "Checking for roles starting with \"pg_\"" msgstr "Перевірка ролей, які починаються з \"pg_\"" -#: check.c:1216 +#: check.c:1627 #, c-format -msgid "The source cluster contains roles starting with \"pg_\"\n" -msgstr "Початковий кластер містить ролі, які починаються з \"pg_\"\n" +msgid "Your installation contains roles starting with \"pg_\".\n" +"\"pg_\" is a reserved prefix for system roles. The cluster\n" +"cannot be upgraded until these roles are renamed.\n" +"A list of roles starting with \"pg_\" is in the file:\n" +" %s" +msgstr "Ваша інсталяція містить ролі, які починаються з \"pg_\".\n" +"\"pg_\" є зарезервованим префіксом для системних ролей. Кластер\n" +"не може бути оновлений, поки ці ролі не будуть перейменовані.\n" +"Список ролей, які починаються з \"pg_\" у файлі:\n" +" %s" -#: check.c:1218 -#, c-format -msgid "The target cluster contains roles starting with \"pg_\"\n" -msgstr "Цільовий кластер містить ролі, які починаються з \"pg_\"\n" - -#: check.c:1239 +#: check.c:1647 #, c-format msgid "Checking for user-defined encoding conversions" msgstr "Перевірка користувацьких перетворення кодувань" -#: check.c:1302 +#: check.c:1707 #, c-format msgid "Your installation contains user-defined encoding conversions.\n" "The conversion function parameters changed in PostgreSQL version 14\n" "so this cluster cannot currently be upgraded. You can remove the\n" "encoding conversions in the old cluster and restart the upgrade.\n" "A list of user-defined encoding conversions is in the file:\n" -" %s\n\n" +" %s" msgstr "Ваша інсталяція містить користувацькі перетворення кодувань.\n" "Параметри функції перетворення змінено у версії PostgreSQL 14,\n" "тому цей кластер наразі не може бути оновлений.\n" "Ви можете видалити перетворення кодувань в старому кластері та перезапустити оновлення.\n" "Список перетворень кодувань знаходиться у файлі:\n" -" %s\n\n" +" %s" -#: check.c:1329 +#: check.c:1746 #, c-format -msgid "failed to get the current locale\n" -msgstr "не вдалося отримати поточну локаль\n" +msgid "Checking for new cluster logical replication slots" +msgstr "Перевірка наявності нових слотів логічної реплікації кластера" -#: check.c:1338 +#: check.c:1754 #, c-format -msgid "failed to get system locale name for \"%s\"\n" -msgstr "не вдалося отримати системне ім'я локалі для \"%s\"\n" +msgid "could not count the number of logical replication slots" +msgstr "не вдалося порахувати кількість слотів логічної реплікації" -#: check.c:1344 +#: check.c:1759 #, c-format -msgid "failed to restore old locale \"%s\"\n" -msgstr "не вдалося відновити стару локаль \"%s\"\n" +msgid "expected 0 logical replication slots but found %d" +msgstr "очікувалося 0 слотів логічної реплікації, але знайдено %d" -#: controldata.c:128 controldata.c:196 +#: check.c:1769 check.c:1820 #, c-format -msgid "could not get control data using %s: %s\n" -msgstr "не вдалося отримати контрольні дані за допомогою %s: %s\n" +msgid "could not determine parameter settings on new cluster" +msgstr "не вдалося визначити налаштування параметрів на новому кластері" -#: controldata.c:139 +#: check.c:1774 #, c-format -msgid "%d: database cluster state problem\n" -msgstr "%d: неприпустимий стан кластера баз даних\n" +msgid "\"wal_level\" must be \"logical\" but is set to \"%s\"" +msgstr "\"wal_level\" має бути \"logical\", але встановлено значення \"%s\"" -#: controldata.c:157 +#: check.c:1780 #, c-format -msgid "The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.\n" -msgstr "Початковий кластер завершив роботу в режимі відновлення. Щоб виконати оновлення, використайте документований спосіб з \"rsync\" або вимкніть його в режимі головного сервера.\n" +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of logical replication slots (%d) on the old cluster" +msgstr "\"max_replication_slots\" (%d) має бути більше або дорівнювати кількості слотів логічної реплікації (%d) на старому кластері" -#: controldata.c:159 +#: check.c:1812 #, c-format -msgid "The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary.\n" -msgstr "Цільовий кластер завершив роботу в режимі відновлення. Щоб виконати оновлення, використайте документований спосіб з \"rsync\" або вимкніть його в режимі головного сервера.\n" +msgid "Checking for new cluster configuration for subscriptions" +msgstr "Перевірка нової конфігурації кластера для підписок" -#: controldata.c:164 +#: check.c:1824 #, c-format -msgid "The source cluster was not shut down cleanly.\n" -msgstr "Початковий кластер завершив роботу некоректно.\n" +msgid "\"max_replication_slots\" (%d) must be greater than or equal to the number of subscriptions (%d) on the old cluster" +msgstr "\"max_replication_slots\" (%d) має бути більше або дорівнювати кількості підписок (%d) на старому кластері" -#: controldata.c:166 +#: check.c:1846 #, c-format -msgid "The target cluster was not shut down cleanly.\n" -msgstr "Цільовий кластер завершив роботу некоректно.\n" +msgid "Checking for valid logical replication slots" +msgstr "Перевірка дійсних слотів логічної реплікації" -#: controldata.c:177 +#: check.c:1898 #, c-format -msgid "The source cluster lacks cluster state information:\n" -msgstr "В початковому кластері відсутня інформація про стан кластеру:\n" +msgid "Your installation contains logical replication slots that cannot be upgraded.\n" +"You can remove invalid slots and/or consume the pending WAL for other slots,\n" +"and then restart the upgrade.\n" +"A list of the problematic slots is in the file:\n" +" %s" +msgstr "Ваша інсталяція містить слоти логічної реплікації, які не можуть бути оновлені.\n" +"Ви можете видалити недійсні слоти та/або використати відкладений WAL для інших слотів,\n" +"і потім перезавантажити оновлення.\n" +"Список проблемних слотів знаходиться у файлі:\n" +" %s" -#: controldata.c:179 +#: check.c:1922 #, c-format -msgid "The target cluster lacks cluster state information:\n" -msgstr "В цільовому кластері відсутня інформація про стан кластеру:\n" +msgid "Checking for subscription state" +msgstr "Перевірка стану підписки" -#: controldata.c:209 dump.c:49 pg_upgrade.c:335 pg_upgrade.c:371 -#: relfilenode.c:243 server.c:33 util.c:79 +#: check.c:2023 #, c-format -msgid "%s" -msgstr "%s" +msgid "Your installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state.\n" +"You can allow the initial sync to finish for all relations and then restart the upgrade.\n" +"A list of the problematic subscriptions is in the file:\n" +" %s" +msgstr "У вашій інсталяції є підписки, які не мають походження або мають зв'язки, що не перебувають у стані i (ініціалізація) або r (готовність).\n" +"Ви можете дозволити початковій синхронізації завершитися для всіх зв'язків, а потім перезапустити оновлення.\n" +"Список проблемних підписок знаходиться у файлі:\n" +" %s" + +#: controldata.c:129 controldata.c:199 +#, c-format +msgid "could not get control data using %s: %m" +msgstr "не вдалося отримати контрольні дані за допомогою %s: %m" + +#: controldata.c:139 +#, c-format +msgid "%d: database cluster state problem" +msgstr "%d: неприпустимий стан кластера баз даних" -#: controldata.c:216 +#: controldata.c:158 #, c-format -msgid "%d: pg_resetwal problem\n" -msgstr "%d: проблема pg_resetwal\n" +msgid "The source cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." +msgstr "Початковий кластер завершив роботу в режимі відновлення. Щоб виконати оновлення, використайте документований спосіб з \"rsync\" або вимкніть його в режимі головного серверу." -#: controldata.c:226 controldata.c:236 controldata.c:247 controldata.c:258 -#: controldata.c:269 controldata.c:288 controldata.c:299 controldata.c:310 -#: controldata.c:321 controldata.c:332 controldata.c:343 controldata.c:354 -#: controldata.c:357 controldata.c:361 controldata.c:371 controldata.c:383 -#: controldata.c:394 controldata.c:405 controldata.c:416 controldata.c:427 -#: controldata.c:438 controldata.c:449 controldata.c:460 controldata.c:471 -#: controldata.c:482 controldata.c:493 +#: controldata.c:160 #, c-format -msgid "%d: controldata retrieval problem\n" -msgstr "%d: проблема з отриманням контрольних даних\n" +msgid "The target cluster was shut down while in recovery mode. To upgrade, use \"rsync\" as documented or shut it down as a primary." +msgstr "Цільовий кластер завершив роботу в режимі відновлення. Щоб виконати оновлення, використайте документований спосіб з \"rsync\" або вимкніть його в режимі головного серверу." -#: controldata.c:572 +#: controldata.c:165 #, c-format -msgid "The source cluster lacks some required control information:\n" -msgstr "У початковому кластері відсутня необхідна контрольна інформація:\n" +msgid "The source cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "Кластер джерел не був вимкнений повністю, про що повідомлялося у звітах стану: \"%s\"" -#: controldata.c:575 +#: controldata.c:167 #, c-format -msgid "The target cluster lacks some required control information:\n" -msgstr "У цільовому кластері відсутня необхідна контрольна інформація:\n" +msgid "The target cluster was not shut down cleanly, state reported as: \"%s\"" +msgstr "Цільовий кластер не був закритий \"чисто\", про що повідомив стан: \"%s\"" + +#: controldata.c:175 controldata.c:507 +#, c-format +msgid "could not get control data using %s: %s" +msgstr "не вдалося отримати контрольні дані за допомогою %s: %s" + +#: controldata.c:181 +#, c-format +msgid "The source cluster lacks cluster state information:" +msgstr "В початковому кластері відсутня інформація про стан кластера:" + +#: controldata.c:183 +#, c-format +msgid "The target cluster lacks cluster state information:" +msgstr "В цільовому кластері відсутня інформація про стан кластера:" + +#: controldata.c:213 dump.c:50 exec.c:118 pg_upgrade.c:556 pg_upgrade.c:596 +#: pg_upgrade.c:945 relfilenumber.c:233 server.c:34 util.c:337 +#, c-format +msgid "%s" +msgstr "%s" + +#: controldata.c:220 +#, c-format +msgid "%d: pg_resetwal problem" +msgstr "%d: проблема pg_resetwal" + +#: controldata.c:230 controldata.c:240 controldata.c:251 controldata.c:262 +#: controldata.c:273 controldata.c:292 controldata.c:303 controldata.c:314 +#: controldata.c:325 controldata.c:336 controldata.c:347 controldata.c:358 +#: controldata.c:361 controldata.c:365 controldata.c:375 controldata.c:387 +#: controldata.c:398 controldata.c:409 controldata.c:420 controldata.c:431 +#: controldata.c:442 controldata.c:453 controldata.c:464 controldata.c:475 +#: controldata.c:486 controldata.c:497 +#, c-format +msgid "%d: controldata retrieval problem" +msgstr "%d: проблема з отриманням контрольних даних" #: controldata.c:578 #, c-format -msgid " checkpoint next XID\n" -msgstr " наступний XID контрольної точки\n" +msgid "The source cluster lacks some required control information:" +msgstr "У початковому кластері відсутня необхідна контрольна інформація:" #: controldata.c:581 #, c-format -msgid " latest checkpoint next OID\n" -msgstr " наступний OID останньої контрольної точки\n" +msgid "The target cluster lacks some required control information:" +msgstr "У цільовому кластері відсутня необхідна контрольна інформація:" #: controldata.c:584 #, c-format -msgid " latest checkpoint next MultiXactId\n" -msgstr " наступний MultiXactId останньої контрольної точки\n" +msgid " checkpoint next XID" +msgstr " наступний XID контрольної точки" -#: controldata.c:588 +#: controldata.c:587 #, c-format -msgid " latest checkpoint oldest MultiXactId\n" -msgstr " найстарший MultiXactId останньої контрольної точки\n" +msgid " latest checkpoint next OID" +msgstr " наступний OID останньої контрольної точки" -#: controldata.c:591 +#: controldata.c:590 #, c-format -msgid " latest checkpoint oldestXID\n" -msgstr " найстарший oldestXID останньої контрольної точки\n" +msgid " latest checkpoint next MultiXactId" +msgstr " наступний MultiXactId останньої контрольної точки" #: controldata.c:594 #, c-format -msgid " latest checkpoint next MultiXactOffset\n" -msgstr " наступний MultiXactOffset останньої контрольної точки\n" +msgid " latest checkpoint oldest MultiXactId" +msgstr " найстарший MultiXactId останньої контрольної точки" #: controldata.c:597 #, c-format -msgid " first WAL segment after reset\n" -msgstr " перший сегмет WAL після скидання\n" +msgid " latest checkpoint oldestXID" +msgstr " найстарший oldestXID останньої контрольної точки" #: controldata.c:600 #, c-format -msgid " float8 argument passing method\n" -msgstr " метод передачі аргументу float8\n" +msgid " latest checkpoint next MultiXactOffset" +msgstr " наступний MultiXactOffset останньої контрольної точки" #: controldata.c:603 #, c-format -msgid " maximum alignment\n" -msgstr " максимальне вирівнювання\n" +msgid " first WAL segment after reset" +msgstr " перший сегмет WAL після скидання" #: controldata.c:606 #, c-format -msgid " block size\n" -msgstr " розмір блоку\n" +msgid " float8 argument passing method" +msgstr " метод передачі аргументу float8" #: controldata.c:609 #, c-format -msgid " large relation segment size\n" -msgstr " розмір сегменту великого відношення\n" +msgid " maximum alignment" +msgstr " максимальне вирівнювання" #: controldata.c:612 #, c-format -msgid " WAL block size\n" -msgstr " розмір блоку WAL\n" +msgid " block size" +msgstr " розмір блоку" #: controldata.c:615 #, c-format -msgid " WAL segment size\n" -msgstr " розмір сегменту WAL\n" +msgid " large relation segment size" +msgstr " розмір сегменту великого відношення" #: controldata.c:618 #, c-format -msgid " maximum identifier length\n" -msgstr " максимальна довжина ідентифікатора\n" +msgid " WAL block size" +msgstr " розмір блоку WAL" #: controldata.c:621 #, c-format -msgid " maximum number of indexed columns\n" -msgstr " максимальна кількість індексованих стовпців\n" +msgid " WAL segment size" +msgstr " розмір сегменту WAL" #: controldata.c:624 #, c-format -msgid " maximum TOAST chunk size\n" -msgstr " максимальний розмір порції TOAST\n" +msgid " maximum identifier length" +msgstr " максимальна довжина ідентифікатора" -#: controldata.c:628 +#: controldata.c:627 #, c-format -msgid " large-object chunk size\n" -msgstr " розмір порції великого об'єкту\n" +msgid " maximum number of indexed columns" +msgstr " максимальна кількість індексованих стовпців" -#: controldata.c:631 +#: controldata.c:630 #, c-format -msgid " dates/times are integers?\n" -msgstr " дата/час представлені цілими числами?\n" +msgid " maximum TOAST chunk size" +msgstr " максимальний розмір порції TOAST" -#: controldata.c:635 +#: controldata.c:634 #, c-format -msgid " data checksum version\n" -msgstr " версія контрольних сум даних\n" +msgid " large-object chunk size" +msgstr " розмір порції великого об'єкту" #: controldata.c:637 #, c-format -msgid "Cannot continue without required control information, terminating\n" -msgstr "Не можна продовжити без необхідної контрольної інформації, завершення\n" +msgid " dates/times are integers?" +msgstr " дата/час представлені цілими числами?" -#: controldata.c:652 +#: controldata.c:641 #, c-format -msgid "old and new pg_controldata alignments are invalid or do not match\n" -"Likely one cluster is a 32-bit install, the other 64-bit\n" -msgstr "старе і нове вирівнювання в pg_controldata неприпустимі або не збігаються\n" -"Ймовірно, один кластер встановлений у 32-бітній системі, а інший - у 64-бітній\n" +msgid " data checksum version" +msgstr " версія контрольних сум даних" -#: controldata.c:656 +#: controldata.c:643 #, c-format -msgid "old and new pg_controldata block sizes are invalid or do not match\n" -msgstr "старий і новий розмір блоків в pg_controldata неприпустимі або не збігаються\n" +msgid "Cannot continue without required control information, terminating" +msgstr "Не можна продовжити без необхідної контрольної інформації, завершення" -#: controldata.c:659 +#: controldata.c:658 #, c-format -msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match\n" -msgstr "старий і новий максимальний розмір сегментів відношень в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata alignments are invalid or do not match.\n" +"Likely one cluster is a 32-bit install, the other 64-bit" +msgstr "старе і нове вирівнювання в pg_controldata неприпустимі або не збігаються\n" +"Ймовірно, один кластер встановлений у 32-бітній системі, а інший - у 64-бітній" #: controldata.c:662 #, c-format -msgid "old and new pg_controldata WAL block sizes are invalid or do not match\n" -msgstr "старий і новий розмір блоків WAL в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata block sizes are invalid or do not match" +msgstr "старий і новий розмір блоків в pg_controldata неприпустимі або не збігаються" #: controldata.c:665 #, c-format -msgid "old and new pg_controldata WAL segment sizes are invalid or do not match\n" -msgstr "старий і новий розмір сегментів WAL в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata maximum relation segment sizes are invalid or do not match" +msgstr "старий і новий максимальний розмір сегментів відношень в pg_controldata неприпустимі або не збігаються" #: controldata.c:668 #, c-format -msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match\n" -msgstr "стара і нова максимальна довжина ідентифікаторів в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata WAL block sizes are invalid or do not match" +msgstr "старий і новий розмір блоків WAL в pg_controldata неприпустимі або не збігаються" #: controldata.c:671 #, c-format -msgid "old and new pg_controldata maximum indexed columns are invalid or do not match\n" -msgstr "стара і нова максимальна кількість індексованих стовпців в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata WAL segment sizes are invalid or do not match" +msgstr "старий і новий розмір сегментів WAL в pg_controldata неприпустимі або не збігаються" #: controldata.c:674 #, c-format -msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match\n" -msgstr "старий і новий максимальний розмір порції TOAST в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata maximum identifier lengths are invalid or do not match" +msgstr "стара і нова максимальна довжина ідентифікаторів в pg_controldata неприпустимі або не збігаються" -#: controldata.c:679 +#: controldata.c:677 #, c-format -msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match\n" -msgstr "старий і новий розмір порції великого об'єкту в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata maximum indexed columns are invalid or do not match" +msgstr "стара і нова максимальна кількість індексованих стовпців в pg_controldata неприпустимі або не збігаються" -#: controldata.c:682 +#: controldata.c:680 #, c-format -msgid "old and new pg_controldata date/time storage types do not match\n" -msgstr "старий і новий тип сховища дати/часу в pg_controldata неприпустимі або не збігаються\n" +msgid "old and new pg_controldata maximum TOAST chunk sizes are invalid or do not match" +msgstr "старий і новий максимальний розмір порції TOAST в pg_controldata неприпустимі або не збігаються" -#: controldata.c:695 +#: controldata.c:685 #, c-format -msgid "old cluster does not use data checksums but the new one does\n" -msgstr "старий кластер не використовує контрольні суми даних, але новий використовує\n" +msgid "old and new pg_controldata large-object chunk sizes are invalid or do not match" +msgstr "старий і новий розмір порції великого об'єкту в pg_controldata неприпустимі або не збігаються" -#: controldata.c:698 +#: controldata.c:688 #, c-format -msgid "old cluster uses data checksums but the new one does not\n" -msgstr "старий кластер використовує контрольні суми даних, але новий не використовує\n" +msgid "old and new pg_controldata date/time storage types do not match" +msgstr "старий і новий тип сховища дати/часу в pg_controldata неприпустимі або не збігаються" -#: controldata.c:700 +#: controldata.c:701 #, c-format -msgid "old and new cluster pg_controldata checksum versions do not match\n" -msgstr "стара і нова версія контрольних сум кластера в pg_controldata не збігаються\n" +msgid "old cluster does not use data checksums but the new one does" +msgstr "старий кластер не використовує контрольні суми даних, але новий використовує" -#: controldata.c:711 +#: controldata.c:704 +#, c-format +msgid "old cluster uses data checksums but the new one does not" +msgstr "старий кластер використовує контрольні суми даних, але новий не використовує" + +#: controldata.c:706 +#, c-format +msgid "old and new cluster pg_controldata checksum versions do not match" +msgstr "стара і нова версія контрольних сум кластера в pg_controldata не збігаються" + +#: controldata.c:717 #, c-format msgid "Adding \".old\" suffix to old global/pg_control" msgstr "Додавання суфікса \".old\" до старого файла global/pg_control" -#: controldata.c:716 +#: controldata.c:722 #, c-format -msgid "Unable to rename %s to %s.\n" -msgstr "Не вдалося перейменувати %s на %s.\n" +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" -#: controldata.c:719 +#: controldata.c:726 #, c-format msgid "\n" "If you want to start the old cluster, you will need to remove\n" "the \".old\" suffix from %s/global/pg_control.old.\n" "Because \"link\" mode was used, the old cluster cannot be safely\n" -"started once the new cluster has been started.\n\n" +"started once the new cluster has been started." msgstr "\n" "Якщо ви хочете запустити старий кластер, вам необхідно видалити\n" "суфікс \".old\" з файлу %s/global/pg_control.old. Через використання\n" "режиму \"link\" робота старого кластера після запуску нового може бути\n" -"небезпечна.\n\n" +"небезпечна." #: dump.c:20 #, c-format msgid "Creating dump of global objects" msgstr "Створення вивантаження глобальних об'єктів" -#: dump.c:31 +#: dump.c:32 #, c-format -msgid "Creating dump of database schemas\n" -msgstr "Створення вивантаження схем бази даних\n" +msgid "Creating dump of database schemas" +msgstr "Створення дампу схем бази даних" -#: exec.c:45 +#: exec.c:47 #, c-format -msgid "could not get pg_ctl version data using %s: %s\n" -msgstr "не вдалося отримати дані версії pg_ctl, виконавши %s: %s\n" +msgid "could not get pg_ctl version data using %s: %m" +msgstr "не вдалося отримати дані версії pg_ctl, виконавши %s: %m" #: exec.c:51 #, c-format -msgid "could not get pg_ctl version output from %s\n" -msgstr "не вдалося отримати версію pg_ctl з результату %s\n" +msgid "could not get pg_ctl version data using %s: %s" +msgstr "не вдалося отримати дані версії pg_ctl, виконавши %s: %s" -#: exec.c:105 exec.c:109 +#: exec.c:55 #, c-format -msgid "command too long\n" -msgstr "команда занадто довга\n" +msgid "could not get pg_ctl version output from %s" +msgstr "не вдалося отримати версію pg_ctl з результату %s" -#: exec.c:111 util.c:37 util.c:225 +#: exec.c:112 exec.c:116 #, c-format -msgid "%s\n" -msgstr "%s\n" +msgid "command too long" +msgstr "команда занадто довга" -#: exec.c:150 option.c:217 +#: exec.c:160 pg_upgrade.c:311 #, c-format -msgid "could not open log file \"%s\": %m\n" -msgstr "не вдалося відкрити файл журналу \"%s\": %m\n" +msgid "could not open log file \"%s\": %m" +msgstr "не вдалося відкрити файл журналу \"%s\": %m" -#: exec.c:179 +#: exec.c:192 #, c-format msgid "\n" "*failure*" msgstr "\n" "*неполадка*" -#: exec.c:182 +#: exec.c:195 #, c-format -msgid "There were problems executing \"%s\"\n" -msgstr "Під час виконання \"%s\" виникли проблеми\n" +msgid "There were problems executing \"%s\"" +msgstr "Під час виконання \"%s\" виникли проблеми" -#: exec.c:185 +#: exec.c:198 #, c-format msgid "Consult the last few lines of \"%s\" or \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "Щоб зрозуміти причину неполадки, зверніться до декількох останніх рядків\n" -"файлу \"%s\" або \"%s\".\n" +"файлу \"%s\" або \"%s\"." -#: exec.c:190 +#: exec.c:203 #, c-format msgid "Consult the last few lines of \"%s\" for\n" -"the probable cause of the failure.\n" +"the probable cause of the failure." msgstr "Щоб зрозуміти причину неполадки, зверніться до декількох останніх рядків\n" -"файлу \"%s\".\n" +"файлу \"%s\"." -#: exec.c:205 option.c:226 +#: exec.c:218 pg_upgrade.c:321 #, c-format -msgid "could not write to log file \"%s\": %m\n" -msgstr "не вдалося записати до файлу журналу \"%s\": %m\n" +msgid "could not write to log file \"%s\": %m" +msgstr "не вдалося записати до файлу журналу \"%s\": %m" -#: exec.c:231 +#: exec.c:244 #, c-format -msgid "could not open file \"%s\" for reading: %s\n" -msgstr "не вдалося відкрити файл \"%s\" для читання: %s\n" +msgid "could not open file \"%s\" for reading: %m" +msgstr "не вдалося відкрити файл \"%s\" для читання: %m" -#: exec.c:258 +#: exec.c:270 #, c-format -msgid "You must have read and write access in the current directory.\n" -msgstr "Ви повинні мати права на читання і запис в поточному каталозі.\n" +msgid "You must have read and write access in the current directory." +msgstr "Ви повинні мати права на читання і запис в поточному каталозі." -#: exec.c:311 exec.c:377 +#: exec.c:323 exec.c:389 exec.c:439 #, c-format -msgid "check for \"%s\" failed: %s\n" -msgstr "перевірка \"%s\" провалена: %s\n" +msgid "check for \"%s\" failed: %m" +msgstr "перевірка \"%s\" провалена: %m" -#: exec.c:314 exec.c:380 +#: exec.c:326 exec.c:392 #, c-format -msgid "\"%s\" is not a directory\n" -msgstr "\"%s\" не є каталогом\n" +msgid "\"%s\" is not a directory" +msgstr "\"%s\" не є каталогом" -#: exec.c:430 +#: exec.c:444 #, c-format -msgid "check for \"%s\" failed: not a regular file\n" -msgstr "перевірка \"%s\" провалена: це не звичайний файл\n" +msgid "check for \"%s\" failed: cannot execute" +msgstr "помилка перевірки \"%s\": не можна виконати" -#: exec.c:433 +#: exec.c:454 #, c-format -msgid "check for \"%s\" failed: cannot execute (permission denied)\n" -msgstr "перевірка \"%s\" провалена: виконання неможливе (немає доступу)\n" +msgid "check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"" +msgstr "помилка перевірки \"%s\": неправильна версія: знайдено \"%s\", очікувалось \"%s\"" -#: exec.c:439 +#: file.c:44 #, c-format -msgid "check for \"%s\" failed: cannot execute\n" -msgstr "помилка перевірки \"%s\": не можна виконати\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "помилка при клонуванні відношення \"%s.%s\" (\"%s\" до \"%s\"): %m" -#: exec.c:449 +#: file.c:51 #, c-format -msgid "check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"\n" -msgstr "помилка перевірки \"%s\": неправильна версія: знайдено \"%s\", очікувалось \"%s\"\n" +msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "помилка при клонуванні відношення \"%s.%s\": не вдалося відкрити файл \"%s\": %m" -#: file.c:43 file.c:61 +#: file.c:56 #, c-format -msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "помилка при клонуванні відношення \"%s.%s\" (\"%s\" до \"%s\"): %s\n" +msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "помилка при клонуванні відношення \"%s.%s\": не вдалося створити файл \"%s\": %m" -#: file.c:50 +#: file.c:65 #, c-format -msgid "error while cloning relation \"%s.%s\": could not open file \"%s\": %s\n" -msgstr "помилка при клонуванні відношення \"%s.%s\": не вдалося відкрити файл \"%s\": %s\n" +msgid "error while cloning relation \"%s.%s\" (\"%s\" to \"%s\"): %s" +msgstr "помилка при клонуванні відношення \"%s.%s\" (\"%s\" до \"%s\"): %s" -#: file.c:55 +#: file.c:91 file.c:160 file.c:233 #, c-format -msgid "error while cloning relation \"%s.%s\": could not create file \"%s\": %s\n" -msgstr "помилка при клонуванні відношення \"%s.%s\": не вдалося створити файл \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося відкрити файл \"%s\": %m" -#: file.c:87 file.c:190 +#: file.c:96 file.c:165 file.c:242 #, c-format -msgid "error while copying relation \"%s.%s\": could not open file \"%s\": %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося відкрити файл \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося створити файл \"%s\": %m" -#: file.c:92 file.c:199 +#: file.c:110 file.c:266 #, c-format -msgid "error while copying relation \"%s.%s\": could not create file \"%s\": %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося створити файл \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося прочитати файл \"%s\": %m" -#: file.c:106 file.c:223 +#: file.c:122 file.c:344 #, c-format -msgid "error while copying relation \"%s.%s\": could not read file \"%s\": %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося прочитати файл \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося записати до файлу \"%s\": %m" -#: file.c:118 file.c:301 +#: file.c:136 #, c-format -msgid "error while copying relation \"%s.%s\": could not write file \"%s\": %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося записати до файлу \"%s\": %s\n" +msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "помилка під час копіювання відношення \"%s.%s\" ( з \"%s\" в \"%s\"): %m" -#: file.c:132 +#: file.c:172 #, c-format -msgid "error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\" ( з \"%s\" в \"%s\"): %s\n" - -#: file.c:151 -#, c-format -msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "помилка під час створення посилання для відношення \"%s.%s\" ( з \"%s\" в \"%s\"): %s\n" +msgid "error while copying relation \"%s.%s\": could not copy file range from \"%s\" to \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося скопіювати діапазон файлу з \"%s\" до \"%s\": %m" #: file.c:194 #, c-format -msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %s\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося отримати стан файлу \"%s\": %s\n" +msgid "error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "помилка під час створення посилання для відношення \"%s.%s\" ( з \"%s\" в \"%s\"): %m" -#: file.c:226 +#: file.c:237 #, c-format -msgid "error while copying relation \"%s.%s\": partial page found in file \"%s\"\n" -msgstr "помилка під час копіювання відношення \"%s.%s\": у файлі \"%s\" знайдена часткова сторінка\n" +msgid "error while copying relation \"%s.%s\": could not stat file \"%s\": %m" +msgstr "помилка під час копіювання відношення \"%s.%s\": не вдалося отримати стан файлу \"%s\": %m" -#: file.c:328 file.c:345 +#: file.c:269 #, c-format -msgid "could not clone file between old and new data directories: %s\n" -msgstr "не вдалося клонувати файл між старим і новим каталогами даних: %s\n" +msgid "error while copying relation \"%s.%s\": partial page found in file \"%s\"" +msgstr "помилка під час копіювання відношення \"%s.%s\": у файлі \"%s\" знайдена часткова сторінка" -#: file.c:341 +#: file.c:371 file.c:387 #, c-format -msgid "could not create file \"%s\": %s\n" -msgstr "не можливо створити файл \"%s\": %s\n" +msgid "could not clone file between old and new data directories: %m" +msgstr "не вдалося клонувати файл між старим і новим каталогами даних: %m" -#: file.c:352 +#: file.c:383 file.c:420 #, c-format -msgid "file cloning not supported on this platform\n" -msgstr "клонування файлів не підтримується на цій платформі\n" +msgid "could not create file \"%s\": %m" +msgstr "неможливо створити файл \"%s\": %m" -#: file.c:369 +#: file.c:393 #, c-format -msgid "could not create hard link between old and new data directories: %s\n" -"In link mode the old and new data directories must be on the same file system.\n" -msgstr "не вдалося створити жорстке посилання між старим і новим каталогами даних: %s\n" -"В режимі посилань старий і новий каталоги даних повинні знаходитись в одній файловій системі.\n" +msgid "file cloning not supported on this platform" +msgstr "клонування файлів не підтримується на цій платформі" -#: function.c:114 +#: file.c:424 #, c-format -msgid "\n" -"The old cluster has a \"plpython_call_handler\" function defined\n" -"in the \"public\" schema which is a duplicate of the one defined\n" -"in the \"pg_catalog\" schema. You can confirm this by executing\n" -"in psql:\n\n" -" \\df *.plpython_call_handler\n\n" -"The \"public\" schema version of this function was created by a\n" -"pre-8.1 install of plpython, and must be removed for pg_upgrade\n" -"to complete because it references a now-obsolete \"plpython\"\n" -"shared object file. You can remove the \"public\" schema version\n" -"of this function by running the following command:\n\n" -" DROP FUNCTION public.plpython_call_handler()\n\n" -"in each affected database:\n\n" -msgstr "\n" -"Старий кластер має функцію \"plpython_call_handler\", визначену в схемі\n" -"\"public\", яка є дублікатом функції, визначеної в схемі \"pg_catalog\". Ви\n" -"можете переконатися в цьому, виконавши в psql:\n\n" -" \\df *.plpython_call_handler\n\n" -"Версія цієї функції в схемі \"public\" була створена встановленням plpython \n" -"версії до 8.1 і повинна бути видалена до завершення процедури pg_upgrade,\n" -"адже вона посилається на застарілий спільний об'єктний файл \"plpython\". Ви\n" -"можете видалити версію цієї функції зі схеми \"public\", виконавши наступну\n" -"команду:\n\n" -" DROP FUNCTION public.plpython_call_handler()\n\n" -"у кожній базі даних, якої це стосується:\n\n" +msgid "could not copy file range between old and new data directories: %m" +msgstr "не вдалося скопіювати діапазон файлу між старим і новим каталогами даних: %m" -#: function.c:132 +#: file.c:430 #, c-format -msgid " %s\n" -msgstr " %s\n" +msgid "copy_file_range not supported on this platform" +msgstr "copy_file_range не підтримується на цій платформі" -#: function.c:142 +#: file.c:447 #, c-format -msgid "Remove the problem functions from the old cluster to continue.\n" -msgstr "Видаліть проблемні функції старого кластера для продовження.\n" +msgid "could not create hard link between old and new data directories: %m\n" +"In link mode the old and new data directories must be on the same file system." +msgstr "не вдалося створити жорстке посилання між старим і новим каталогами даних: %m\n" +"В режимі посилань старий і новий каталоги даних повинні знаходитись в одній файловій системі." -#: function.c:189 +#: function.c:154 #, c-format msgid "Checking for presence of required libraries" msgstr "Перевірка наявності необхідних бібліотек" -#: function.c:242 +#: function.c:190 #, c-format msgid "could not load library \"%s\": %s" msgstr "не вдалося завантажити бібліотеку \"%s\": %s" -#: function.c:253 +#: function.c:201 #, c-format msgid "In database: %s\n" msgstr "У базі даних: %s\n" -#: function.c:263 +#: function.c:211 #, c-format msgid "Your installation references loadable libraries that are missing from the\n" "new installation. You can add these libraries to the new installation,\n" "or remove the functions using them from the old installation. A list of\n" "problem libraries is in the file:\n" -" %s\n\n" +" %s" msgstr "У вашій інсталяції є посилання на завантажувані бібліотеки, що \n" "відсутні в новій інсталяції. Ви можете додати ці бібліотеки до нової інсталяції\n" "або видалити функції, які використовують їх зі старої інсталяції. Список\n" "проблемних бібліотек подано у файлі:\n" -" %s\n\n" +" %s" -#: info.c:131 +#: info.c:128 #, c-format -msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"\n" -msgstr "Імена відношень з OID %u в базі даних \"%s\" не збігаються: старе ім'я \"%s.%s\", нове ім'я \"%s.%s\"\n" +msgid "Relation names for OID %u in database \"%s\" do not match: old name \"%s.%s\", new name \"%s.%s\"" +msgstr "Імена відношень з OID %u в базі даних \"%s\" не збігаються: старе ім'я \"%s.%s\", нове ім'я \"%s.%s\"" -#: info.c:151 +#: info.c:148 #, c-format -msgid "Failed to match up old and new tables in database \"%s\"\n" -msgstr "Не вдалося зіставити старі таблиці з новими в базі даних \"%s\"\n" +msgid "Failed to match up old and new tables in database \"%s\"" +msgstr "Не вдалося зіставити старі таблиці з новими в базі даних \"%s\"" -#: info.c:240 +#: info.c:229 #, c-format msgid " which is an index on \"%s.%s\"" msgstr " це індекс в \"%s.%s\"" -#: info.c:250 +#: info.c:239 #, c-format msgid " which is an index on OID %u" msgstr " це індекс у відношенні з OID %u" -#: info.c:262 +#: info.c:251 #, c-format msgid " which is the TOAST table for \"%s.%s\"" msgstr " це TOAST-таблиця для \"%s.%s\"" -#: info.c:270 +#: info.c:259 #, c-format msgid " which is the TOAST table for OID %u" msgstr " це TOAST-таблиця для відношення з OID %u" -#: info.c:274 +#: info.c:263 #, c-format -msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s\n" -msgstr "У старому кластері не знайдено відповідності для нового відношення з OID %u в базі даних %s\": %s\n" +msgid "No match found in old cluster for new relation with OID %u in database \"%s\": %s" +msgstr "У старому кластері не знайдено відповідності для нового відношення з OID %u в базі даних %s\": %s" -#: info.c:277 +#: info.c:266 #, c-format -msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s\n" -msgstr "У новому кластері не знайдено відповідності для старого відношення з OID %u в базі даних \"%s\": %s\n" +msgid "No match found in new cluster for old relation with OID %u in database \"%s\": %s" +msgstr "У новому кластері не знайдено відповідності для старого відношення з OID %u в базі даних \"%s\": %s" -#: info.c:289 +#: info.c:300 #, c-format -msgid "mappings for database \"%s\":\n" -msgstr "відображення для бази даних \"%s\":\n" +msgid "\n" +"source databases:" +msgstr "\n" +"вихідні бази даних:" -#: info.c:292 +#: info.c:302 #, c-format -msgid "%s.%s: %u to %u\n" -msgstr "%s.%s: %u в %u\n" +msgid "\n" +"target databases:" +msgstr "\n" +"цільові бази даних:" -#: info.c:297 info.c:633 +#: info.c:346 #, c-format -msgid "\n\n" -msgstr "\n\n" +msgid "template0 not found" +msgstr "template0 не знайдено" -#: info.c:322 +#: info.c:805 #, c-format -msgid "\n" -"source databases:\n" -msgstr "\n" -"вихідні бази даних:\n" +msgid "Database: \"%s\"" +msgstr "База даних: %s\"" -#: info.c:324 +#: info.c:818 #, c-format -msgid "\n" -"target databases:\n" -msgstr "\n" -"цільові бази даних:\n" +msgid "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" +msgstr "relname: \"%s.%s\", reloid: %u, reltblspace: \"%s\"" -#: info.c:631 +#: info.c:832 #, c-format -msgid "Database: %s\n" -msgstr "База даних: %s\n" +msgid "Logical replication slots in the database:" +msgstr "Логічні слоти реплікації в базі даних:" -#: info.c:644 +#: info.c:838 #, c-format -msgid "relname: %s.%s: reloid: %u reltblspace: %s\n" -msgstr "ім'я_відношення: %s.%s: oid_відношення: %u табл_простір: %s\n" +msgid "slot name: \"%s\", output plugin: \"%s\", two_phase: %s" +msgstr "назва слоту: \"%s\", плагін виводу: \"%s\", two_phase: %s" -#: option.c:102 +#: option.c:105 #, c-format -msgid "%s: cannot be run as root\n" -msgstr "%s: не може виконуватись як root\n" +msgid "%s: cannot be run as root" +msgstr "%s: не можна запустити як root" -#: option.c:170 +#: option.c:172 #, c-format -msgid "invalid old port number\n" -msgstr "неприпустимий старий номер порту\n" +msgid "invalid old port number" +msgstr "неприпустимий старий номер порту" -#: option.c:175 +#: option.c:177 #, c-format -msgid "invalid new port number\n" -msgstr "неприпустимий новий номер порту\n" +msgid "invalid new port number" +msgstr "неприпустимий новий номер порту" -#: option.c:207 +#: option.c:216 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Спробуйте \"%s --help\" для додаткової інформації.\n" -#: option.c:214 +#: option.c:223 #, c-format -msgid "too many command-line arguments (first is \"%s\")\n" -msgstr "забагато аргументів у командному рядку (перший \"%s\")\n" +msgid "too many command-line arguments (first is \"%s\")" +msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: option.c:220 +#: option.c:229 #, c-format -msgid "Running in verbose mode\n" -msgstr "Виконується в детальному режимі\n" +msgid "Running in verbose mode" +msgstr "Виконується в детальному режимі" -#: option.c:251 +#: option.c:247 msgid "old cluster binaries reside" msgstr "розташування двійкових даних старого кластера" -#: option.c:253 +#: option.c:249 msgid "new cluster binaries reside" msgstr "розташування двійкових даних нового кластера" -#: option.c:255 +#: option.c:251 msgid "old cluster data resides" msgstr "розташування даних старого кластера" -#: option.c:257 +#: option.c:253 msgid "new cluster data resides" msgstr "розташування даних нового кластера" -#: option.c:259 +#: option.c:255 msgid "sockets will be created" msgstr "сокети будуть створені" -#: option.c:276 option.c:374 +#: option.c:272 option.c:374 #, c-format -msgid "could not determine current directory\n" -msgstr "не вдалося визначити поточний каталог\n" +msgid "could not determine current directory" +msgstr "не вдалося визначити поточний каталог" -#: option.c:279 +#: option.c:275 #, c-format -msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows\n" -msgstr "у Windows не можна виконати pg_upgrade всередині каталогу даних нового кластера\n" +msgid "cannot run pg_upgrade from inside the new cluster data directory on Windows" +msgstr "у Windows не можна виконати pg_upgrade всередині каталогу даних нового кластера" -#: option.c:288 +#: option.c:284 #, c-format msgid "pg_upgrade upgrades a PostgreSQL cluster to a different major version.\n\n" msgstr "pg_upgrade оновлює кластер PostgreSQL до іншої основної версії.\n\n" -#: option.c:289 +#: option.c:285 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: option.c:290 +#: option.c:286 #, c-format msgid " pg_upgrade [OPTION]...\n\n" msgstr " pg_upgrade [OPTION]...\n\n" -#: option.c:291 +#: option.c:287 #, c-format msgid "Options:\n" msgstr "Параметри:\n" -#: option.c:292 +#: option.c:288 #, c-format msgid " -b, --old-bindir=BINDIR old cluster executable directory\n" msgstr " -b, --old-bindir=BINDIR каталог виконуваних файлів старого кластера\n" -#: option.c:293 +#: option.c:289 #, c-format msgid " -B, --new-bindir=BINDIR new cluster executable directory (default\n" " same directory as pg_upgrade)\n" msgstr " -B, --new-bindir=BINDIR каталог виконуваних файлів нового кластера (за замовчуванням\n" " той самий каталог, що і pg_upgrade)\n" -#: option.c:295 +#: option.c:291 #, c-format msgid " -c, --check check clusters only, don't change any data\n" msgstr " -c, --check тільки перевірити кластери, не змінювати ніякі дані\n" -#: option.c:296 +#: option.c:292 #, c-format msgid " -d, --old-datadir=DATADIR old cluster data directory\n" msgstr " -d, --old-datadir=DATADIR каталог даних старого кластера\n" -#: option.c:297 +#: option.c:293 #, c-format msgid " -D, --new-datadir=DATADIR new cluster data directory\n" msgstr " -D, --new-datadir=DATADIR каталог даних нового кластера\n" -#: option.c:298 +#: option.c:294 #, c-format msgid " -j, --jobs=NUM number of simultaneous processes or threads to use\n" msgstr " -j, --jobs=NUM число одночасних процесів або потоків для використання\n" -#: option.c:299 +#: option.c:295 #, c-format msgid " -k, --link link instead of copying files to new cluster\n" msgstr " -k, --link встановлювати посилання замість копіювання файлів до нового кластера\n" -#: option.c:300 +#: option.c:296 +#, c-format +msgid " -N, --no-sync do not wait for changes to be written safely to disk\n" +msgstr " -N, --no-sync не чекати завершення збереження змін на диску\n" + +#: option.c:297 #, c-format msgid " -o, --old-options=OPTIONS old cluster options to pass to the server\n" msgstr " -o, --old-options=OPTIONS параметри старого кластера, які передаються серверу\n" -#: option.c:301 +#: option.c:298 #, c-format msgid " -O, --new-options=OPTIONS new cluster options to pass to the server\n" msgstr " -O, --new-options=OPTIONS параметри нового кластера, які передаються серверу\n" -#: option.c:302 +#: option.c:299 #, c-format msgid " -p, --old-port=PORT old cluster port number (default %d)\n" msgstr " -p, --old-port=PORT номер порту старого кластера (за замовчуванням %d)\n" -#: option.c:303 +#: option.c:300 #, c-format msgid " -P, --new-port=PORT new cluster port number (default %d)\n" msgstr " -P, --new-port=PORT номер порту нового кластера (за замовчуванням %d)\n" -#: option.c:304 +#: option.c:301 #, c-format msgid " -r, --retain retain SQL and log files after success\n" msgstr " -r, --retain зберегти файли журналів і SQL після успішного завершення\n" -#: option.c:305 +#: option.c:302 #, c-format msgid " -s, --socketdir=DIR socket directory to use (default current dir.)\n" msgstr " -s, --socketdir=DIR директорія сокету для використання (за замовчування поточна директорія)\n" -#: option.c:306 +#: option.c:303 #, c-format msgid " -U, --username=NAME cluster superuser (default \"%s\")\n" msgstr " -U, --username=NAME суперкористувач кластера (за замовчуванням \"%s\")\n" -#: option.c:307 +#: option.c:304 #, c-format msgid " -v, --verbose enable verbose internal logging\n" msgstr " -v, --verbose активувати виведення детальних внутрішніх повідомлень\n" -#: option.c:308 +#: option.c:305 #, c-format msgid " -V, --version display version information, then exit\n" msgstr " -V, --version відобразити інформацію про версію, потім вийти\n" -#: option.c:309 +#: option.c:306 #, c-format msgid " --clone clone instead of copying files to new cluster\n" msgstr " --clone клонувати замість копіювання файлів до нового кластера\n" +#: option.c:307 +#, c-format +msgid " --copy copy files to new cluster (default)\n" +msgstr " --copy копіювати файли до нового кластеру (за замовчуванням)\n" + +#: option.c:308 +#, c-format +msgid " --copy-file-range copy files to new cluster with copy_file_range\n" +msgstr " --copy-file-range копіювати файли в новий кластер за допомогою copy_file_range\n" + +#: option.c:309 +#, c-format +msgid " --sync-method=METHOD set method for syncing files to disk\n" +msgstr " --sync-method=METHOD встановити метод синхронізації файлів на диск\n" + #: option.c:310 #, c-format msgid " -?, --help show this help, then exit\n" @@ -1232,238 +1451,274 @@ msgstr "Домашня сторінка %s: <%s>\n" #: option.c:380 #, c-format msgid "You must identify the directory where the %s.\n" -"Please use the %s command-line option or the %s environment variable.\n" +"Please use the %s command-line option or the %s environment variable." msgstr "Ви повинні визначити каталог, де знаходиться %s.\n" -"Будь ласка, використайте параметр командного рядка %s або змінну середовища %s.\n" +"Будь ласка, використайте параметр командного рядка %s або змінну середовища %s." -#: option.c:432 +#: option.c:433 #, c-format msgid "Finding the real data directory for the source cluster" msgstr "Пошук дійсного каталогу даних для початкового кластера" -#: option.c:434 +#: option.c:435 #, c-format msgid "Finding the real data directory for the target cluster" msgstr "Пошук дійсного каталогу даних для цільового кластера" -#: option.c:446 +#: option.c:448 +#, c-format +msgid "could not get data directory using %s: %m" +msgstr "не вдалося отримати каталог даних, виконавши %s: %m" + +#: option.c:452 #, c-format -msgid "could not get data directory using %s: %s\n" -msgstr "не вдалося отримати каталог даних, виконавши %s: %s\n" +msgid "could not get data directory using %s: %s" +msgstr "не вдалося отримати каталог даних, виконавши %s: %s" -#: option.c:505 +#: option.c:500 #, c-format -msgid "could not read line %d from file \"%s\": %s\n" -msgstr "не вдалося прочитати рядок %d з файлу \"%s\": %s\n" +msgid "could not read line %d from file \"%s\": %m" +msgstr "не вдалося прочитати рядок %d з файлу \"%s\": %m" -#: option.c:522 +#: option.c:517 #, c-format -msgid "user-supplied old port number %hu corrected to %hu\n" -msgstr "вказаний користувачем старий номер порту %hu змінений на %hu\n" +msgid "user-supplied old port number %hu corrected to %hu" +msgstr "вказаний користувачем старий номер порту %hu змінений на %hu" -#: parallel.c:127 parallel.c:238 +#: parallel.c:127 parallel.c:235 #, c-format -msgid "could not create worker process: %s\n" -msgstr "не вдалося створити робочий процес: %s\n" +msgid "could not create worker process: %m" +msgstr "не вдалося створити робочий процес: %m" -#: parallel.c:146 parallel.c:259 +#: parallel.c:143 parallel.c:253 #, c-format -msgid "could not create worker thread: %s\n" -msgstr "не вдалося створити робочий потік: %s\n" +msgid "could not create worker thread: %m" +msgstr "не вдалося створити робочий потік: %m" -#: parallel.c:300 +#: parallel.c:294 #, c-format -msgid "%s() failed: %s\n" -msgstr "%s() помилка: %s\n" +msgid "%s() failed: %m" +msgstr "%s() помилка: %m" -#: parallel.c:304 +#: parallel.c:298 #, c-format -msgid "child process exited abnormally: status %d\n" -msgstr "дочірній процес завершився ненормально: статус %d\n" +msgid "child process exited abnormally: status %d" +msgstr "дочірній процес завершився ненормально: статус %d" -#: parallel.c:319 +#: parallel.c:313 #, c-format -msgid "child worker exited abnormally: %s\n" -msgstr "дочірній процес завершився аварійно: %s\n" +msgid "child worker exited abnormally: %m" +msgstr "дочірній процес завершився аварійно: %m" -#: pg_upgrade.c:107 +#: pg_upgrade.c:115 #, c-format -msgid "could not read permissions of directory \"%s\": %s\n" -msgstr "не вдалося прочитати права на каталог \"%s\": %s\n" +msgid "could not read permissions of directory \"%s\": %m" +msgstr "не вдалося прочитати дозволи на каталог \"%s\": %m" -#: pg_upgrade.c:122 +#: pg_upgrade.c:147 #, c-format msgid "\n" "Performing Upgrade\n" -"------------------\n" +"------------------" msgstr "\n" "Виконання оновлення\n" -"------------------\n" +"------------------" -#: pg_upgrade.c:165 +#: pg_upgrade.c:192 #, c-format msgid "Setting next OID for new cluster" msgstr "Встановлення наступного OID для нового кластера" -#: pg_upgrade.c:172 +#: pg_upgrade.c:216 #, c-format msgid "Sync data directory to disk" msgstr "Синхронізація каталогу даних на диск" -#: pg_upgrade.c:183 +#: pg_upgrade.c:230 #, c-format msgid "\n" "Upgrade Complete\n" -"----------------\n" +"----------------" msgstr "\n" "Оновлення завершено\n" -"----------------\n" +"----------------" -#: pg_upgrade.c:216 +#: pg_upgrade.c:263 pg_upgrade.c:276 pg_upgrade.c:283 pg_upgrade.c:290 +#: pg_upgrade.c:308 pg_upgrade.c:319 +#, c-format +msgid "directory path for new cluster is too long" +msgstr "шлях каталогу для нового кластеру занадто довгий" + +#: pg_upgrade.c:297 pg_upgrade.c:299 pg_upgrade.c:301 pg_upgrade.c:303 +#, c-format +msgid "could not create directory \"%s\": %m" +msgstr "не вдалося створити каталог \"%s\": %m" + +#: pg_upgrade.c:352 #, c-format -msgid "%s: could not find own program executable\n" -msgstr "%s: не вдалося знайти ехе файл власної програми\n" +msgid "%s: could not find own program executable" +msgstr "%s: не вдалося знайти файл виконання власної програми" -#: pg_upgrade.c:242 +#: pg_upgrade.c:378 #, c-format msgid "There seems to be a postmaster servicing the old cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "Мабуть, запущений процес postmaster, який обслуговує старий кластер.\n" -"Будь ласка, завершіть роботу процесу і спробуйте знову.\n" +"Будь ласка, завершіть роботу процесу і спробуйте знову." -#: pg_upgrade.c:255 +#: pg_upgrade.c:391 #, c-format msgid "There seems to be a postmaster servicing the new cluster.\n" -"Please shutdown that postmaster and try again.\n" +"Please shutdown that postmaster and try again." msgstr "Мабуть, запущений процес postmaster, який обслуговує новий кластер.\n" -"Будь ласка, завершіть роботу процесу і спробуйте знову.\n" +"Будь ласка, завершіть роботу процесу і спробуйте знову." + +#: pg_upgrade.c:413 +#, c-format +msgid "Setting locale and encoding for new cluster" +msgstr "Установка локалі та кодування для нового кластеру" -#: pg_upgrade.c:269 +#: pg_upgrade.c:489 #, c-format msgid "Analyzing all rows in the new cluster" msgstr "Аналіз всіх рядків у новому кластері" -#: pg_upgrade.c:282 +#: pg_upgrade.c:502 #, c-format msgid "Freezing all rows in the new cluster" msgstr "Закріплення всіх рядків у новому кластері" -#: pg_upgrade.c:302 +#: pg_upgrade.c:522 #, c-format msgid "Restoring global objects in the new cluster" msgstr "Відновлення глобальних об'єктів у новому кластері" -#: pg_upgrade.c:317 +#: pg_upgrade.c:538 #, c-format -msgid "Restoring database schemas in the new cluster\n" -msgstr "Відновлення схем баз даних у новому кластері\n" +msgid "Restoring database schemas in the new cluster" +msgstr "Відновлення схем баз даних у новому кластері" -#: pg_upgrade.c:421 +#: pg_upgrade.c:662 #, c-format msgid "Deleting files from new %s" msgstr "Видалення файлів з нового %s" -#: pg_upgrade.c:425 +#: pg_upgrade.c:666 #, c-format -msgid "could not delete directory \"%s\"\n" -msgstr "не вдалося видалити каталог \"%s\"\n" +msgid "could not delete directory \"%s\"" +msgstr "не вдалося видалити каталог \"%s\"" -#: pg_upgrade.c:444 +#: pg_upgrade.c:685 #, c-format msgid "Copying old %s to new server" msgstr "Копіювання старого %s до нового серверу" -#: pg_upgrade.c:470 +#: pg_upgrade.c:711 #, c-format msgid "Setting oldest XID for new cluster" msgstr "Встановлення найстарішого XID для нового кластеру" -#: pg_upgrade.c:478 +#: pg_upgrade.c:719 #, c-format msgid "Setting next transaction ID and epoch for new cluster" msgstr "Установка наступного ID транзакції й епохи для нового кластера" -#: pg_upgrade.c:508 +#: pg_upgrade.c:749 #, c-format msgid "Setting next multixact ID and offset for new cluster" msgstr "Установка наступного ID і зсуву мультитранзакції для нового кластера" -#: pg_upgrade.c:532 +#: pg_upgrade.c:773 #, c-format msgid "Setting oldest multixact ID in new cluster" msgstr "Установка найстаршого ID мультитранзакції в новому кластері" -#: pg_upgrade.c:552 +#: pg_upgrade.c:793 #, c-format msgid "Resetting WAL archives" msgstr "Скидання архівів WAL" -#: pg_upgrade.c:595 +#: pg_upgrade.c:836 #, c-format msgid "Setting frozenxid and minmxid counters in new cluster" msgstr "Установка лічильників frozenxid і minmxid у новому кластері" -#: pg_upgrade.c:597 +#: pg_upgrade.c:838 #, c-format msgid "Setting minmxid counter in new cluster" msgstr "Установка лічильника minmxid у новому кластері" -#: relfilenode.c:35 +#: pg_upgrade.c:929 #, c-format -msgid "Cloning user relation files\n" -msgstr "Клонування файлів користувацьких відношень\n" +msgid "Restoring logical replication slots in the new cluster" +msgstr "Відновлення слотів логічної реплікації в новому кластері" -#: relfilenode.c:38 +#: relfilenumber.c:35 #, c-format -msgid "Copying user relation files\n" -msgstr "Копіювання файлів користувацьких відношень\n" +msgid "Cloning user relation files" +msgstr "Клонування файлів користувацьких відношень" -#: relfilenode.c:41 +#: relfilenumber.c:38 #, c-format -msgid "Linking user relation files\n" -msgstr "Підключення файлів користувацьких відношень посиланнями\n" +msgid "Copying user relation files" +msgstr "Копіювання файлів користувацьких відношень" -#: relfilenode.c:115 +#: relfilenumber.c:41 #, c-format -msgid "old database \"%s\" not found in the new cluster\n" -msgstr "стара база даних \"%s\" не знайдена в новому кластері\n" +msgid "Copying user relation files with copy_file_range" +msgstr "Копіювання файлів користувацьких відношень за допомогою copy_file_range" -#: relfilenode.c:230 +#: relfilenumber.c:44 #, c-format -msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %s\n" -msgstr "помилка під час перевірки існування файлу \"%s.%s\" (з \"%s\" в \"%s\"): %s\n" +msgid "Linking user relation files" +msgstr "Приєднання файлів користувацьких відношень" -#: relfilenode.c:248 +#: relfilenumber.c:118 #, c-format -msgid "rewriting \"%s\" to \"%s\"\n" -msgstr "перезаписування \"%s\" в \"%s\"\n" +msgid "old database \"%s\" not found in the new cluster" +msgstr "стара база даних \"%s\" не знайдена в новому кластері" -#: relfilenode.c:256 +#: relfilenumber.c:221 #, c-format -msgid "cloning \"%s\" to \"%s\"\n" -msgstr "клонування \"%s\" до \"%s\"\n" +msgid "error while checking for file existence \"%s.%s\" (\"%s\" to \"%s\"): %m" +msgstr "помилка під час перевірки існування файлу \"%s.%s\" (з \"%s\" в \"%s\"): %m" -#: relfilenode.c:261 +#: relfilenumber.c:238 #, c-format -msgid "copying \"%s\" to \"%s\"\n" -msgstr "копіювання \"%s\" в \"%s\"\n" +msgid "rewriting \"%s\" to \"%s\"" +msgstr "переписування \"%s\" на \"%s\"" -#: relfilenode.c:266 +#: relfilenumber.c:246 #, c-format -msgid "linking \"%s\" to \"%s\"\n" -msgstr "створення посилання на \"%s\" в \"%s\"\n" +msgid "cloning \"%s\" to \"%s\"" +msgstr "клонування \"%s\" до \"%s\"" -#: server.c:38 server.c:142 util.c:135 util.c:165 +#: relfilenumber.c:251 +#, c-format +msgid "copying \"%s\" to \"%s\"" +msgstr "копіювання \"%s\" в \"%s\"" + +#: relfilenumber.c:256 +#, c-format +msgid "copying \"%s\" to \"%s\" with copy_file_range" +msgstr "" + +#: relfilenumber.c:261 +#, c-format +msgid "linking \"%s\" to \"%s\"" +msgstr "створення посилання на \"%s\" в \"%s\"" + +#: server.c:39 server.c:143 util.c:248 util.c:278 #, c-format msgid "Failure, exiting\n" msgstr "Помилка, вихід\n" -#: server.c:132 +#: server.c:133 #, c-format -msgid "executing: %s\n" -msgstr "виконується: %s\n" +msgid "executing: %s" +msgstr "виконується: %s" -#: server.c:138 +#: server.c:139 #, c-format msgid "SQL command failed\n" "%s\n" @@ -1472,192 +1727,117 @@ msgstr "Помилка SQL-команди\n" "%s\n" "%s" -#: server.c:168 +#: server.c:169 #, c-format -msgid "could not open version file \"%s\": %m\n" -msgstr "не вдалося відкрити файл версії \"%s\": %m\n" +msgid "could not open version file \"%s\": %m" +msgstr "не вдалося відкрити файл версії \"%s\": %m" -#: server.c:172 +#: server.c:173 #, c-format -msgid "could not parse version file \"%s\"\n" -msgstr "не вдалося проаналізувати файл версії \"%s\"\n" +msgid "could not parse version file \"%s\"" +msgstr "не вдалося проаналізувати файл версії \"%s\"" -#: server.c:298 +#: server.c:310 #, c-format msgid "\n" "%s" msgstr "\n" "%s" -#: server.c:302 +#: server.c:314 #, c-format msgid "could not connect to source postmaster started with the command:\n" -"%s\n" +"%s" msgstr "не вдалося підключитися до початкового процесу postmaster, запущеного командою:\n" -"%s\n" +"%s" -#: server.c:306 +#: server.c:318 #, c-format msgid "could not connect to target postmaster started with the command:\n" -"%s\n" +"%s" msgstr "не вдалося підключитися до цільового процесу postmaster, запущеного командою:\n" -"%s\n" +"%s" -#: server.c:320 +#: server.c:332 #, c-format -msgid "pg_ctl failed to start the source server, or connection failed\n" -msgstr "pg_ctl не зміг запустити початковий сервер або сталася помилка підключення\n" +msgid "pg_ctl failed to start the source server, or connection failed" +msgstr "pg_ctl не зміг запустити початковий сервер або сталася помилка підключення" -#: server.c:322 +#: server.c:334 #, c-format -msgid "pg_ctl failed to start the target server, or connection failed\n" -msgstr "pg_ctl не зміг запустити цільовий сервер або сталася помилка підключення\n" +msgid "pg_ctl failed to start the target server, or connection failed" +msgstr "pg_ctl не зміг запустити цільовий сервер або сталася помилка підключення" -#: server.c:367 +#: server.c:379 #, c-format -msgid "out of memory\n" -msgstr "недостатньо пам'яті\n" +msgid "out of memory" +msgstr "недостатньо пам'яті" -#: server.c:380 +#: server.c:392 #, c-format -msgid "libpq environment variable %s has a non-local server value: %s\n" -msgstr "у змінній середовища для libpq %s задано не локальне значення: %s\n" +msgid "libpq environment variable %s has a non-local server value: %s" +msgstr "у змінній середовища для libpq %s задано не локальне значення: %s" #: tablespace.c:28 #, c-format msgid "Cannot upgrade to/from the same system catalog version when\n" -"using tablespaces.\n" +"using tablespaces." msgstr "Оновлення в межах однієї версії системного каталогу неможливе,\n" -"якщо використовуються табличні простори.\n" - -#: tablespace.c:86 -#, c-format -msgid "tablespace directory \"%s\" does not exist\n" -msgstr "каталог табличного простору \"%s\" не існує\n" +"якщо використовуються табличні простори." -#: tablespace.c:90 +#: tablespace.c:83 #, c-format -msgid "could not stat tablespace directory \"%s\": %s\n" -msgstr "не вдалося отримати стан каталогу табличного простору \"%s\": %s\n" +msgid "tablespace directory \"%s\" does not exist" +msgstr "каталог табличного простору \"%s\" не існує" -#: tablespace.c:95 +#: tablespace.c:87 #, c-format -msgid "tablespace path \"%s\" is not a directory\n" -msgstr "шлях табличного простору \"%s\" не вказує на каталог\n" +msgid "could not stat tablespace directory \"%s\": %m" +msgstr "" -#: util.c:49 +#: tablespace.c:92 #, c-format -msgid " " -msgstr " " +msgid "tablespace path \"%s\" is not a directory" +msgstr "шлях табличного простору \"%s\" не вказує на каталог" -#: util.c:82 +#: util.c:53 util.c:56 util.c:139 util.c:170 util.c:172 #, c-format msgid "%-*s" msgstr "%-*s" -#: util.c:174 +#: util.c:107 +#, c-format +msgid "could not access directory \"%s\": %m" +msgstr "немає доступу до каталогу \"%s\": %m" + +#: util.c:287 #, c-format msgid "ok" msgstr "ok" -#: version.c:29 +#: version.c:44 #, c-format -msgid "Checking for large objects" -msgstr "Перевірка великих об'єктів" +msgid "Checking for hash indexes" +msgstr "Перевірка геш-індексів" -#: version.c:77 version.c:419 +#: version.c:121 #, c-format msgid "warning" msgstr "попередження" -#: version.c:79 -#, c-format -msgid "\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table. After upgrading, you will be\n" -"given a command to populate the pg_largeobject_metadata table with\n" -"default permissions.\n\n" -msgstr "\n" -"Ваша інсталяція містить великі об'єкти. Нова база даних має\n" -"додаткову таблицю з правами для великих об'єктів. Після оновлення ви отримаєте команду для заповнення таблиці pg_largeobject_metadata \n" -"з правами за замовчуванням.\n\n" - -#: version.c:85 -#, c-format -msgid "\n" -"Your installation contains large objects. The new database has an\n" -"additional large object permission table, so default permissions must be\n" -"defined for all large objects. The file\n" -" %s\n" -"when executed by psql by the database superuser will set the default\n" -"permissions.\n\n" -msgstr "\n" -"Ваша інсталяція містить великі об'єкти. Нова база даних має\n" -"додаткову таблицю з правами для великих об'єктів, тож для всіх\n" -"великих об'єктів повинні визначатись права за замовчуванням. Файл\n" -" %s\n" -"дозволяє встановити такі права (він призначений для виконання в psql\n" -"суперкористувачем бази даних).\n\n" - -#: version.c:272 -#, c-format -msgid "Checking for incompatible \"line\" data type" -msgstr "Перевірка несумісного типу даних \"line\"" - -#: version.c:279 -#, c-format -msgid "Your installation contains the \"line\" data type in user tables.\n" -"This data type changed its internal and input/output format\n" -"between your old and new versions so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить тип даних \"line\" в таблицях користувача.\n" -"Внутрішній формат та формат вводу/виводу цього типу даних змінено між вашою старою та новими версіями,\n" -"тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" - -#: version.c:310 -#, c-format -msgid "Checking for invalid \"unknown\" user columns" -msgstr "Перевірка неприпустимих користувацьких стовпців \"unknown\"" - -#: version.c:317 -#, c-format -msgid "Your installation contains the \"unknown\" data type in user tables.\n" -"This data type is no longer allowed in tables, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить \"unknown\" тип даних у таблицях користувача.\n" -"Цей тип даних більше не допускається в таблицях,\n" -"тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" - -#: version.c:341 -#, c-format -msgid "Checking for hash indexes" -msgstr "Перевірка геш-індексів" - -#: version.c:421 +#: version.c:123 #, c-format msgid "\n" "Your installation contains hash indexes. These indexes have different\n" "internal formats between your old and new clusters, so they must be\n" "reindexed with the REINDEX command. After upgrading, you will be given\n" -"REINDEX instructions.\n\n" +"REINDEX instructions." msgstr "\n" "Ваша інсталяція містить геш-індекси. Ці індекси мають різні внутрішні\n" "формати в старому і новому кластерах, тож їх потрібно повторно індексувати\n" -"за допомогою команди REINDEX. Після оновлення вам буде надано інструкції REINDEX.\n\n" +"за допомогою команди REINDEX. Після оновлення вам буде надано інструкції REINDEX." -#: version.c:427 +#: version.c:129 #, c-format msgid "\n" "Your installation contains hash indexes. These indexes have different\n" @@ -1665,57 +1845,37 @@ msgid "\n" "reindexed with the REINDEX command. The file\n" " %s\n" "when executed by psql by the database superuser will recreate all invalid\n" -"indexes; until then, none of these indexes will be used.\n\n" +"indexes; until then, none of these indexes will be used." msgstr "\n" "Ваша інсталяція містить геш-індекси. Ці індекси мають різні внутрішні\n" "формати в старому і новому кластерах, тож їх потрібно повторно індексувати\n" "за допомогою команди REINDEX. Файл\n" " %s\n" "після виконання суперкористувачем бази даних в psql, повторно створить\n" -"всі неприпустимі індекси; до цього ніякі геш-індекси не будуть використовуватись.\n\n" - -#: version.c:453 -#, c-format -msgid "Checking for invalid \"sql_identifier\" user columns" -msgstr "Перевірка неприпустимих користувацьких стовпців \"sql_identifier\"" - -#: version.c:461 -#, c-format -msgid "Your installation contains the \"sql_identifier\" data type in user tables.\n" -"The on-disk format for this data type has changed, so this\n" -"cluster cannot currently be upgraded. You can\n" -"drop the problem columns and restart the upgrade.\n" -"A list of the problem columns is in the file:\n" -" %s\n\n" -msgstr "Ваша інсталяція містить \"sql_identifier\" тип даних у таблицях користувача.\n" -"Формат зберігання для цього типу даних змінено,\n" -"тому цей кластер наразі не може бути оновлений.\n" -"Ви можете видалити проблемні стовпці та перезапустити оновлення.\n" -"Список проблемних стовпців знаходиться у файлі:\n" -" %s\n\n" +"всі неприпустимі індекси; до цього ніякі геш-індекси не будуть використовуватись." -#: version.c:485 +#: version.c:153 #, c-format msgid "Checking for extension updates" msgstr "Перевірка оновлень розширення" -#: version.c:537 +#: version.c:200 #, c-format msgid "notice" msgstr "повідомлення" -#: version.c:538 +#: version.c:201 #, c-format msgid "\n" "Your installation contains extensions that should be updated\n" "with the ALTER EXTENSION command. The file\n" " %s\n" "when executed by psql by the database superuser will update\n" -"these extensions.\n\n" +"these extensions." msgstr "\n" "Ваша інсталяція містить розширення, які потрібно оновити\n" -"командою ALTER EXTENSION . Файл\n" +"командою ALTER EXTENSION. Файл\n" " %s,\n" "коли виконується суперкористувачем бази даних за допомогою\n" -"psql, оновить ці розширення.\n\n" +"psql, оновить ці розширення." diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index 1d3054d78bdb1..8d8e816a01fa4 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -3,7 +3,7 @@ * * relfilenumber functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/relfilenumber.c */ @@ -11,13 +11,92 @@ #include -#include "access/transam.h" -#include "catalog/pg_class_d.h" +#include "common/file_perm.h" +#include "common/file_utils.h" +#include "common/int.h" +#include "common/logging.h" #include "pg_upgrade.h" static void transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace); static void transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_frozenbit); +/* + * The following set of sync_queue_* functions are used for --swap to reduce + * the amount of time spent synchronizing the swapped catalog files. When a + * file is added to the queue, we also alert the file system that we'd like it + * to be persisted to disk in the near future (if that operation is supported + * by the current platform). Once the queue is full, all of the files are + * synchronized to disk. This strategy should generally be much faster than + * simply calling fsync() on the files right away. + * + * The general usage pattern should be something like: + * + * for (int i = 0; i < num_files; i++) + * sync_queue_push(files[i]); + * + * // be sure to sync any remaining files in the queue + * sync_queue_sync_all(); + * sync_queue_destroy(); + */ + +#define SYNC_QUEUE_MAX_LEN (1024) + +static char *sync_queue[SYNC_QUEUE_MAX_LEN]; +static bool sync_queue_inited; +static int sync_queue_len; + +static inline void +sync_queue_init(void) +{ + if (sync_queue_inited) + return; + + sync_queue_inited = true; + for (int i = 0; i < SYNC_QUEUE_MAX_LEN; i++) + sync_queue[i] = palloc(MAXPGPATH); +} + +static inline void +sync_queue_sync_all(void) +{ + if (!sync_queue_inited) + return; + + for (int i = 0; i < sync_queue_len; i++) + { + if (fsync_fname(sync_queue[i], false) != 0) + pg_fatal("could not synchronize file \"%s\": %m", sync_queue[i]); + } + + sync_queue_len = 0; +} + +static inline void +sync_queue_push(const char *fname) +{ + sync_queue_init(); + + pre_sync_fname(fname, false); + + strncpy(sync_queue[sync_queue_len++], fname, MAXPGPATH); + if (sync_queue_len >= SYNC_QUEUE_MAX_LEN) + sync_queue_sync_all(); +} + +static inline void +sync_queue_destroy(void) +{ + if (!sync_queue_inited) + return; + + sync_queue_inited = false; + sync_queue_len = 0; + for (int i = 0; i < SYNC_QUEUE_MAX_LEN; i++) + { + pfree(sync_queue[i]); + sync_queue[i] = NULL; + } +} /* * transfer_all_new_tablespaces() @@ -43,6 +122,9 @@ transfer_all_new_tablespaces(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, case TRANSFER_MODE_LINK: prep_status_progress("Linking user relation files"); break; + case TRANSFER_MODE_SWAP: + prep_status_progress("Swapping data directories"); + break; } /* @@ -127,6 +209,287 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr, DbInfoArr *new_db_arr, /* We allocate something even for n_maps == 0 */ pg_free(mappings); } + + /* + * Make sure anything pending synchronization in swap mode is fully + * persisted to disk. This is a no-op for other transfer modes. + */ + sync_queue_sync_all(); + sync_queue_destroy(); +} + +/* + * prepare_for_swap() + * + * This function moves the database directory from the old cluster to the new + * cluster in preparation for moving the pg_restore-generated catalog files + * into place. Returns false if the database with the given OID does not have + * a directory in the given tablespace, otherwise returns true. + * + * This function will return paths in the following variables, which the caller + * must ensure are sized to MAXPGPATH bytes: + * + * old_catalog_dir: The directory for the old cluster's catalog files. + * new_db_dir: The new cluster's database directory for db_oid. + * moved_db_dir: Destination for the pg_restore-generated database directory. + */ +static bool +prepare_for_swap(const char *old_tablespace, Oid db_oid, + char *old_catalog_dir, char *new_db_dir, char *moved_db_dir) +{ + const char *new_tablespace; + const char *old_tblspc_suffix; + const char *new_tblspc_suffix; + char old_tblspc[MAXPGPATH]; + char new_tblspc[MAXPGPATH]; + char moved_tblspc[MAXPGPATH]; + char old_db_dir[MAXPGPATH]; + struct stat st; + + if (strcmp(old_tablespace, old_cluster.pgdata) == 0) + { + new_tablespace = new_cluster.pgdata; + new_tblspc_suffix = "/base"; + old_tblspc_suffix = "/base"; + } + else + { + /* + * XXX: The below line is a hack to deal with the fact that we + * presently don't have an easy way to find the corresponding new + * tablespace's path. This will need to be fixed if/when we add + * pg_upgrade support for in-place tablespaces. + */ + new_tablespace = old_tablespace; + + new_tblspc_suffix = new_cluster.tablespace_suffix; + old_tblspc_suffix = old_cluster.tablespace_suffix; + } + + /* Old and new cluster paths. */ + snprintf(old_tblspc, sizeof(old_tblspc), "%s%s", old_tablespace, old_tblspc_suffix); + snprintf(new_tblspc, sizeof(new_tblspc), "%s%s", new_tablespace, new_tblspc_suffix); + snprintf(old_db_dir, sizeof(old_db_dir), "%s/%u", old_tblspc, db_oid); + snprintf(new_db_dir, MAXPGPATH, "%s/%u", new_tblspc, db_oid); + + /* + * Paths for "moved aside" stuff. We intentionally put these in the old + * cluster so that the delete_old_cluster.{sh,bat} script handles them. + */ + snprintf(moved_tblspc, sizeof(moved_tblspc), "%s/moved_for_upgrade", old_tblspc); + snprintf(old_catalog_dir, MAXPGPATH, "%s/%u_old_catalogs", moved_tblspc, db_oid); + snprintf(moved_db_dir, MAXPGPATH, "%s/%u", moved_tblspc, db_oid); + + /* Check that the database directory exists in the given tablespace. */ + if (stat(old_db_dir, &st) != 0) + { + if (errno != ENOENT) + pg_fatal("could not stat file \"%s\": %m", old_db_dir); + return false; + } + + /* Create directory for stuff that is moved aside. */ + if (pg_mkdir_p(moved_tblspc, pg_dir_create_mode) != 0 && errno != EEXIST) + pg_fatal("could not create directory \"%s\": %m", moved_tblspc); + + /* Create directory for old catalog files. */ + if (pg_mkdir_p(old_catalog_dir, pg_dir_create_mode) != 0) + pg_fatal("could not create directory \"%s\": %m", old_catalog_dir); + + /* Move the new cluster's database directory aside. */ + if (rename(new_db_dir, moved_db_dir) != 0) + pg_fatal("could not rename directory \"%s\" to \"%s\": %m", new_db_dir, moved_db_dir); + + /* Move the old cluster's database directory into place. */ + if (rename(old_db_dir, new_db_dir) != 0) + pg_fatal("could not rename directory \"%s\" to \"%s\": %m", old_db_dir, new_db_dir); + + return true; +} + +/* + * FileNameMapCmp() + * + * qsort() comparator for FileNameMap that sorts by RelFileNumber. + */ +static int +FileNameMapCmp(const void *a, const void *b) +{ + const FileNameMap *map1 = (const FileNameMap *) a; + const FileNameMap *map2 = (const FileNameMap *) b; + + return pg_cmp_u32(map1->relfilenumber, map2->relfilenumber); +} + +/* + * parse_relfilenumber() + * + * Attempt to parse the RelFileNumber of the given file name. If we can't, + * return InvalidRelFileNumber. Note that this code snippet is lifted from + * parse_filename_for_nontemp_relation(). + */ +static RelFileNumber +parse_relfilenumber(const char *filename) +{ + char *endp; + unsigned long n; + + if (filename[0] < '1' || filename[0] > '9') + return InvalidRelFileNumber; + + errno = 0; + n = strtoul(filename, &endp, 10); + if (errno || filename == endp || n <= 0 || n > PG_UINT32_MAX) + return InvalidRelFileNumber; + + return (RelFileNumber) n; +} + +/* + * swap_catalog_files() + * + * Moves the old catalog files aside, and moves the new catalog files into + * place. prepare_for_swap() should have already been called (and returned + * true) for the tablespace/database being transferred. + * + * The arguments for the following parameters should be the corresponding + * variables returned by prepare_for_swap(): + * + * old_catalog_dir: The directory for the old cluster's catalog files. + * new_db_dir: New cluster's database directory (for DB being transferred). + * moved_db_dir: Moved-aside pg_restore-generated database directory. + */ +static void +swap_catalog_files(FileNameMap *maps, int size, const char *old_catalog_dir, + const char *new_db_dir, const char *moved_db_dir) +{ + DIR *dir; + struct dirent *de; + char path[MAXPGPATH]; + char dest[MAXPGPATH]; + RelFileNumber rfn; + + /* Move the old catalog files aside. */ + dir = opendir(new_db_dir); + if (dir == NULL) + pg_fatal("could not open directory \"%s\": %m", new_db_dir); + while (errno = 0, (de = readdir(dir)) != NULL) + { + snprintf(path, sizeof(path), "%s/%s", new_db_dir, de->d_name); + if (get_dirent_type(path, de, false, PG_LOG_ERROR) != PGFILETYPE_REG) + continue; + + rfn = parse_relfilenumber(de->d_name); + if (RelFileNumberIsValid(rfn)) + { + FileNameMap key = {.relfilenumber = rfn}; + + if (bsearch(&key, maps, size, sizeof(FileNameMap), FileNameMapCmp)) + continue; + } + + snprintf(dest, sizeof(dest), "%s/%s", old_catalog_dir, de->d_name); + if (rename(path, dest) != 0) + pg_fatal("could not rename file \"%s\" to \"%s\": %m", path, dest); + } + if (errno) + pg_fatal("could not read directory \"%s\": %m", new_db_dir); + (void) closedir(dir); + + /* Move the new catalog files into place. */ + dir = opendir(moved_db_dir); + if (dir == NULL) + pg_fatal("could not open directory \"%s\": %m", moved_db_dir); + while (errno = 0, (de = readdir(dir)) != NULL) + { + snprintf(path, sizeof(path), "%s/%s", moved_db_dir, de->d_name); + if (get_dirent_type(path, de, false, PG_LOG_ERROR) != PGFILETYPE_REG) + continue; + + rfn = parse_relfilenumber(de->d_name); + if (RelFileNumberIsValid(rfn)) + { + FileNameMap key = {.relfilenumber = rfn}; + + if (bsearch(&key, maps, size, sizeof(FileNameMap), FileNameMapCmp)) + continue; + } + + snprintf(dest, sizeof(dest), "%s/%s", new_db_dir, de->d_name); + if (rename(path, dest) != 0) + pg_fatal("could not rename file \"%s\" to \"%s\": %m", path, dest); + + /* + * We don't fsync() the database files in the file synchronization + * stage of pg_upgrade in swap mode, so we need to synchronize them + * ourselves. We only do this for the catalog files because they were + * created during pg_restore with fsync=off. We assume that the user + * data files were properly persisted to disk when the user last shut + * it down. + */ + if (user_opts.do_sync) + sync_queue_push(dest); + } + if (errno) + pg_fatal("could not read directory \"%s\": %m", moved_db_dir); + (void) closedir(dir); + + /* Ensure the directory entries are persisted to disk. */ + if (fsync_fname(new_db_dir, true) != 0) + pg_fatal("could not synchronize directory \"%s\": %m", new_db_dir); + if (fsync_parent_path(new_db_dir) != 0) + pg_fatal("could not synchronize parent directory of \"%s\": %m", new_db_dir); +} + +/* + * do_swap() + * + * Perform the required steps for --swap for a single database. In short this + * moves the old cluster's database directory into the new cluster and then + * replaces any files for system catalogs with the ones that were generated + * during pg_restore. + */ +static void +do_swap(FileNameMap *maps, int size, char *old_tablespace) +{ + char old_catalog_dir[MAXPGPATH]; + char new_db_dir[MAXPGPATH]; + char moved_db_dir[MAXPGPATH]; + + /* + * We perform many lookups on maps by relfilenumber in swap mode, so make + * sure it's sorted by relfilenumber. maps should already be sorted by + * OID, so in general this shouldn't have much work to do. + */ + qsort(maps, size, sizeof(FileNameMap), FileNameMapCmp); + + /* + * If an old tablespace is given, we only need to process that one. If no + * old tablespace is specified, we need to process all the tablespaces on + * the system. + */ + if (old_tablespace) + { + if (prepare_for_swap(old_tablespace, maps[0].db_oid, + old_catalog_dir, new_db_dir, moved_db_dir)) + swap_catalog_files(maps, size, + old_catalog_dir, new_db_dir, moved_db_dir); + } + else + { + if (prepare_for_swap(old_cluster.pgdata, maps[0].db_oid, + old_catalog_dir, new_db_dir, moved_db_dir)) + swap_catalog_files(maps, size, + old_catalog_dir, new_db_dir, moved_db_dir); + + for (int tblnum = 0; tblnum < os_info.num_old_tablespaces; tblnum++) + { + if (prepare_for_swap(os_info.old_tablespaces[tblnum], maps[0].db_oid, + old_catalog_dir, new_db_dir, moved_db_dir)) + swap_catalog_files(maps, size, + old_catalog_dir, new_db_dir, moved_db_dir); + } + } } /* @@ -147,6 +510,20 @@ transfer_single_new_db(FileNameMap *maps, int size, char *old_tablespace) new_cluster.controldata.cat_ver >= VISIBILITY_MAP_FROZEN_BIT_CAT_VER) vm_must_add_frozenbit = true; + /* --swap has its own subroutine */ + if (user_opts.transfer_mode == TRANSFER_MODE_SWAP) + { + /* + * We don't support --swap to upgrade from versions that require + * rewriting the visibility map. We should've failed already if + * someone tries to do that. + */ + Assert(!vm_must_add_frozenbit); + + do_swap(maps, size, old_tablespace); + return; + } + for (mapnum = 0; mapnum < size; mapnum++) { if (old_tablespace == NULL || @@ -261,6 +638,11 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro pg_log(PG_VERBOSE, "linking \"%s\" to \"%s\"", old_file, new_file); linkFile(old_file, new_file, map->nspname, map->relname); + break; + case TRANSFER_MODE_SWAP: + /* swap mode is handled in its own code path */ + pg_fatal("should never happen"); + break; } } } diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c index 91bcb4dbc7e69..873e5b5117bf9 100644 --- a/src/bin/pg_upgrade/server.c +++ b/src/bin/pg_upgrade/server.c @@ -3,7 +3,7 @@ * * database server functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/server.c */ @@ -252,6 +252,13 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error) if (GET_MAJOR_VERSION(cluster->major_version) >= 1700) appendPQExpBufferStr(&pgoptions, " -c max_slot_wal_keep_size=-1"); + /* + * Use idle_replication_slot_timeout=0 to prevent slot invalidation due to + * idle_timeout by checkpointer process during upgrade. + */ + if (GET_MAJOR_VERSION(cluster->major_version) >= 1800) + appendPQExpBufferStr(&pgoptions, " -c idle_replication_slot_timeout=0"); + /* * Use -b to disable autovacuum and logical replication launcher * (effective in PG17 or later for the latter). diff --git a/src/bin/pg_upgrade/t/001_basic.pl b/src/bin/pg_upgrade/t/001_basic.pl index e8e2edb58dc1b..1eec35d436deb 100644 --- a/src/bin/pg_upgrade/t/001_basic.pl +++ b/src/bin/pg_upgrade/t/001_basic.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl index 17af2ce61efdc..7d82593879d57 100644 --- a/src/bin/pg_upgrade/t/002_pg_upgrade.pl +++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Set of tests for pg_upgrade, including cross-version checks. use strict; @@ -6,18 +6,20 @@ use Cwd qw(abs_path); use File::Basename qw(dirname); -use File::Compare; -use File::Find qw(find); -use File::Path qw(rmtree); +use File::Find qw(find); +use File::Path qw(rmtree); use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; +use PostgreSQL::Test::AdjustDump; use PostgreSQL::Test::AdjustUpgrade; use Test::More; # Can be changed to test the other modes. my $mode = $ENV{PG_TEST_PG_UPGRADE_MODE} || '--copy'; +my $tempdir = PostgreSQL::Test::Utils::tempdir; + # Generate a database with a name made of a range of ASCII characters. sub generate_db { @@ -36,8 +38,8 @@ sub generate_db "created database with ASCII characters from $from_char to $to_char"); } -# Filter the contents of a dump before its use in a content comparison. -# This returns the path to the filtered dump. +# Filter the contents of a dump before its use in a content comparison for +# upgrade testing. This returns the path to the filtered dump. sub filter_dump { my ($is_old, $old_version, $dump_file) = @_; @@ -61,6 +63,40 @@ sub filter_dump return $dump_file_filtered; } +# Dump database db from the given node in plain format and adjust it for +# comparing dumps from the original and the restored database. +# +# file_prefix is used to create unique names for all dump files so that they +# remain available for debugging in case the test fails. +# +# adjust_child_columns is passed to adjust_regress_dumpfile() which actually +# adjusts the dump output. +# +# The name of the file containing adjusted dump is returned. +sub get_dump_for_comparison +{ + my ($node, $db, $file_prefix, $adjust_child_columns) = @_; + + my $dumpfile = $tempdir . '/' . $file_prefix . '.sql'; + my $dump_adjusted = "${dumpfile}_adjusted"; + + open(my $dh, '>', $dump_adjusted) + || die "could not open $dump_adjusted for writing $!"; + + $node->run_log( + [ + 'pg_dump', '--no-sync', + '-d' => $node->connstr($db), + '-f' => $dumpfile + ]); + + print $dh adjust_regress_dumpfile(slurp_file($dumpfile), + $adjust_child_columns); + close($dh); + + return $dump_adjusted; +} + # The test of pg_upgrade requires two clusters, an old one and a new one # that gets upgraded. Before running the upgrade, a logical dump of the # old cluster is taken, and a second logical dump of the new one is taken @@ -81,7 +117,6 @@ sub filter_dump } # Paths to the dumps taken during the tests. -my $tempdir = PostgreSQL::Test::Utils::tempdir; my $dump1_file = "$tempdir/dump1.sql"; my $dump2_file = "$tempdir/dump2.sql"; @@ -92,7 +127,7 @@ sub filter_dump PostgreSQL::Test::Cluster->new('old_node', install_path => $ENV{oldinstall}); -my %node_params = (); +my %old_node_params = (); # To increase coverage of non-standard segment size and group access without # increasing test runtime, run these tests with a custom setting. @@ -158,30 +193,37 @@ sub filter_dump my %encodings = ('UTF-8' => 6, 'SQL_ASCII' => 0); my $original_encoding = $encodings{$original_enc_name}; -my @initdb_params = @custom_opts; +my @old_initdb_params = @custom_opts; -push @initdb_params, ('--encoding', $original_enc_name); -push @initdb_params, ('--lc-collate', $original_datcollate); -push @initdb_params, ('--lc-ctype', $original_datctype); +push @old_initdb_params, ('--encoding', $original_enc_name); +push @old_initdb_params, ('--lc-collate', $original_datcollate); +push @old_initdb_params, ('--lc-ctype', $original_datctype); # add --locale-provider, if supported my %provider_name = ('b' => 'builtin', 'i' => 'icu', 'c' => 'libc'); if ($oldnode->pg_version >= 15) { - push @initdb_params, + push @old_initdb_params, ('--locale-provider', $provider_name{$original_provider}); if ($original_provider eq 'b') { - push @initdb_params, ('--builtin-locale', $original_datlocale); + push @old_initdb_params, ('--builtin-locale', $original_datlocale); } elsif ($original_provider eq 'i') { - push @initdb_params, ('--icu-locale', $original_datlocale); + push @old_initdb_params, ('--icu-locale', $original_datlocale); } } -$node_params{extra} = \@initdb_params; -$oldnode->init(%node_params); +# Since checksums are now enabled by default, and weren't before 18, +# pass '-k' to initdb on old versions so that upgrades work. +push @old_initdb_params, '-k' if $oldnode->pg_version < 18; + +$old_node_params{extra} = \@old_initdb_params; +$oldnode->init(%old_node_params); +# Override log_statement=all set by Cluster.pm. This avoids large amounts +# of log traffic that slow this test down even more when run under valgrind. +$oldnode->append_conf('postgresql.conf', 'log_statement = none'); $oldnode->start; my $result; @@ -205,7 +247,8 @@ sub filter_dump # Load the dump using the "postgres" database as "regression" does # not exist yet, and we are done here. - $oldnode->command_ok([ 'psql', '-X', '-f', $olddumpfile, 'postgres' ], + $oldnode->command_ok( + [ 'psql', '--no-psqlrc', '--file' => $olddumpfile, 'postgres' ], 'loaded old dump file'); } else @@ -263,17 +306,20 @@ sub filter_dump # Initialize a new node for the upgrade. my $newnode = PostgreSQL::Test::Cluster->new('new_node'); -# Reset to original parameters. -@initdb_params = @custom_opts; - # The new cluster will be initialized with different locale settings, # but these settings will be overwritten with those of the original # cluster. -push @initdb_params, ('--encoding', 'SQL_ASCII'); -push @initdb_params, ('--locale-provider', 'libc'); - -$node_params{extra} = \@initdb_params; -$newnode->init(%node_params); +my %new_node_params = %old_node_params; +my @new_initdb_params = @custom_opts; +push @new_initdb_params, ('--encoding', 'SQL_ASCII'); +push @new_initdb_params, ('--locale-provider', 'libc'); +$new_node_params{extra} = \@new_initdb_params; +$newnode->init(%new_node_params); +# Avoid unnecessary log noise +$newnode->append_conf('postgresql.conf', 'log_statement = none'); + +# Stabilize stats for comparison. +$newnode->append_conf('postgresql.conf', 'autovacuum = off'); my $newbindir = $newnode->config_data('--bindir'); my $oldbindir = $oldnode->config_data('--bindir'); @@ -297,25 +343,89 @@ sub filter_dump my @command_args = (); for my $upcmd (@{ $adjust_cmds->{$updb} }) { - push @command_args, '-c', $upcmd; + push @command_args, '--command' => $upcmd; } # For simplicity, use the newer version's psql to issue the commands. $newnode->command_ok( [ - 'psql', '-X', '-v', 'ON_ERROR_STOP=1', - '-d', $oldnode->connstr($updb), + 'psql', '--no-psqlrc', + '--set' => 'ON_ERROR_STOP=1', + '--dbname' => $oldnode->connstr($updb), @command_args, ], "ran version adaptation commands for database $updb"); } } +# Stabilize stats before pg_dump / pg_dumpall. Doing it after initializing +# the new node gives enough time for autovacuum to update statistics on the +# old node. +$oldnode->append_conf('postgresql.conf', 'autovacuum = off'); +$oldnode->restart; + +# Test that dump/restore of the regression database roundtrips cleanly. This +# doesn't work well when the nodes are different versions, so skip it in that +# case. Note that this isn't a pg_upgrade test, but it's convenient to do it +# here because we've gone to the trouble of creating the regression database. +# +# Do this while the old cluster is running before it is shut down by the +# upgrade test but after turning its autovacuum off for stable statistics. +SKIP: +{ + my $dstnode = PostgreSQL::Test::Cluster->new('dst_node'); + + skip "different Postgres versions" + if ($oldnode->pg_version != $dstnode->pg_version); + skip "source node not using default install" + if (defined $oldnode->install_path); + + # Setup destination database cluster with the same configuration as the + # source cluster to avoid any differences between dumps taken from both the + # clusters caused by differences in their configurations. + $dstnode->init(%old_node_params); + # Avoid unnecessary log noise + $dstnode->append_conf('postgresql.conf', 'log_statement = none'); + # Stabilize stats for comparison. + $dstnode->append_conf('postgresql.conf', 'autovacuum = off'); + $dstnode->start; + + # Use --create in dump and restore commands so that the restored + # database has the same configurable variable settings as the original + # database so that the dumps taken from both databases taken do not + # differ because of locale changes. Additionally this provides test + # coverage for --create option. + # + # Use directory format so that we can use parallel dump/restore. + my $dump_file = "$tempdir/regression.dump"; + $oldnode->command_ok( + [ + 'pg_dump', '-Fd', '-j2', '--no-sync', + '-d' => $oldnode->connstr('regression'), + '--create', '-f' => $dump_file + ], + 'pg_dump on source instance'); + + $dstnode->command_ok( + [ 'pg_restore', '--create', '-j2', '-d' => 'postgres', $dump_file ], + 'pg_restore to destination instance'); + + # Dump original and restored database for comparison. + my $src_dump = + get_dump_for_comparison($oldnode, 'regression', 'src_dump', 1); + my $dst_dump = + get_dump_for_comparison($dstnode, 'regression', 'dest_dump', 0); + + compare_files($src_dump, $dst_dump, + 'dump outputs from original and restored regression databases match'); +} + # Take a dump before performing the upgrade as a base comparison. Note # that we need to use pg_dumpall from the new node here. my @dump_command = ( - 'pg_dumpall', '--no-sync', '-d', $oldnode->connstr('postgres'), - '-f', $dump1_file); + 'pg_dumpall', '--no-sync', + '--dbname' => $oldnode->connstr('postgres'), + '--file' => $dump1_file); # --extra-float-digits is needed when upgrading from a version older than 11. push(@dump_command, '--extra-float-digits', '0') if ($oldnode->pg_version < 12); @@ -386,18 +496,21 @@ sub filter_dump # Cause a failure at the start of pg_upgrade, this should create the logging # directory pg_upgrade_output.d but leave it around. Keep --check for an # early exit. -command_fails( +command_checks_all( [ 'pg_upgrade', '--no-sync', - '-d', $oldnode->data_dir, - '-D', $newnode->data_dir, - '-b', $oldbindir . '/does/not/exist/', - '-B', $newbindir, - '-s', $newnode->host, - '-p', $oldnode->port, - '-P', $newnode->port, + '--old-datadir' => $oldnode->data_dir, + '--new-datadir' => $newnode->data_dir, + '--old-bindir' => $oldbindir . '/does/not/exist/', + '--new-bindir' => $newbindir, + '--socketdir' => $newnode->host, + '--old-port' => $oldnode->port, + '--new-port' => $newnode->port, $mode, '--check', ], + 1, + [qr{check for ".*?does/not/exist" failed}], + [], 'run of pg_upgrade --check for new instance with incorrect binary path'); ok(-d $newnode->data_dir . "/pg_upgrade_output.d", "pg_upgrade_output.d/ not removed after pg_upgrade failure"); @@ -414,17 +527,17 @@ sub filter_dump command_checks_all( [ 'pg_upgrade', '--no-sync', - '-d', $oldnode->data_dir, - '-D', $newnode->data_dir, - '-b', $oldbindir, - '-B', $newbindir, - '-s', $newnode->host, - '-p', $oldnode->port, - '-P', $newnode->port, + '--old-datadir' => $oldnode->data_dir, + '--new-datadir' => $newnode->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $newnode->host, + '--old-port' => $oldnode->port, + '--new-port' => $newnode->port, $mode, '--check', ], 1, - [qr/invalid/], # pg_upgrade prints errors on stdout :( + [qr/datconnlimit/], [qr/^$/], 'invalid database causes failure'); rmtree($newnode->data_dir . "/pg_upgrade_output.d"); @@ -438,10 +551,14 @@ sub filter_dump # --check command works here, cleans up pg_upgrade_output.d. command_ok( [ - 'pg_upgrade', '--no-sync', '-d', $oldnode->data_dir, - '-D', $newnode->data_dir, '-b', $oldbindir, - '-B', $newbindir, '-s', $newnode->host, - '-p', $oldnode->port, '-P', $newnode->port, + 'pg_upgrade', '--no-sync', + '--old-datadir' => $oldnode->data_dir, + '--new-datadir' => $newnode->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $newnode->host, + '--old-port' => $oldnode->port, + '--new-port' => $newnode->port, $mode, '--check', ], 'run of pg_upgrade --check for new instance'); @@ -451,10 +568,14 @@ sub filter_dump # Actual run, pg_upgrade_output.d is removed at the end. command_ok( [ - 'pg_upgrade', '--no-sync', '-d', $oldnode->data_dir, - '-D', $newnode->data_dir, '-b', $oldbindir, - '-B', $newbindir, '-s', $newnode->host, - '-p', $oldnode->port, '-P', $newnode->port, + 'pg_upgrade', '--no-sync', + '--old-datadir' => $oldnode->data_dir, + '--new-datadir' => $newnode->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $newnode->host, + '--old-port' => $oldnode->port, + '--new-port' => $newnode->port, $mode, ], 'run of pg_upgrade for new instance'); @@ -475,9 +596,14 @@ sub filter_dump if $File::Find::name =~ m/.*\.log/; }, $newnode->data_dir . "/pg_upgrade_output.d"); + + my $test_logfile = $PostgreSQL::Test::Utils::test_logfile; + + note "=== pg_upgrade logs found - appending to $test_logfile ===\n"; foreach my $log (@log_files) { - note "=== contents of $log ===\n"; + note "=== appending $log ===\n"; + print "=== contents of $log ===\n"; print slurp_file($log); print "=== EOF ===\n"; } @@ -494,10 +620,11 @@ sub filter_dump # Second dump from the upgraded instance. @dump_command = ( - 'pg_dumpall', '--no-sync', '-d', $newnode->connstr('postgres'), - '-f', $dump2_file); + 'pg_dumpall', '--no-sync', + '--dbname' => $newnode->connstr('postgres'), + '--file' => $dump2_file); # --extra-float-digits is needed when upgrading from a version older than 11. -push(@dump_command, '--extra-float-digits', '0') +push(@dump_command, '--extra-float-digits' => '0') if ($oldnode->pg_version < 12); $newnode->command_ok(\@dump_command, 'dump after running pg_upgrade'); @@ -506,20 +633,7 @@ sub filter_dump my $dump2_filtered = filter_dump(0, $oldnode->pg_version, $dump2_file); # Compare the two dumps, there should be no differences. -my $compare_res = compare($dump1_filtered, $dump2_filtered); -is($compare_res, 0, 'old and new dumps match after pg_upgrade'); - -# Provide more context if the dumps do not match. -if ($compare_res != 0) -{ - my ($stdout, $stderr) = - run_command([ 'diff', '-u', $dump1_filtered, $dump2_filtered ]); - print "=== diff of $dump1_filtered and $dump2_filtered\n"; - print "=== stdout ===\n"; - print $stdout; - print "=== stderr ===\n"; - print $stderr; - print "=== EOF ===\n"; -} +compare_files($dump1_filtered, $dump2_filtered, + 'old and new dumps match after pg_upgrade'); done_testing(); diff --git a/src/bin/pg_upgrade/t/003_logical_slots.pl b/src/bin/pg_upgrade/t/003_logical_slots.pl index 87c471a6eade7..75db4911730be 100644 --- a/src/bin/pg_upgrade/t/003_logical_slots.pl +++ b/src/bin/pg_upgrade/t/003_logical_slots.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Tests for upgrading logical replication slots @@ -40,13 +40,13 @@ # Setup a common pg_upgrade command to be used by all the test cases my @pg_upgrade_cmd = ( 'pg_upgrade', '--no-sync', - '-d', $oldpub->data_dir, - '-D', $newpub->data_dir, - '-b', $oldpub->config_data('--bindir'), - '-B', $newpub->config_data('--bindir'), - '-s', $newpub->host, - '-p', $oldpub->port, - '-P', $newpub->port, + '--old-datadir' => $oldpub->data_dir, + '--new-datadir' => $newpub->data_dir, + '--old-bindir' => $oldpub->config_data('--bindir'), + '--new-bindir' => $newpub->config_data('--bindir'), + '--socketdir' => $newpub->host, + '--old-port' => $oldpub->port, + '--new-port' => $newpub->port, $mode); # In a VPATH build, we'll be started in the source directory, but we want @@ -117,7 +117,7 @@ [@pg_upgrade_cmd], 1, [ - qr/Your installation contains logical replication slots that can't be upgraded./ + qr/Your installation contains logical replication slots that cannot be upgraded./ ], [qr//], 'run of pg_upgrade of old cluster with slots having unconsumed WAL records' diff --git a/src/bin/pg_upgrade/t/004_subscription.pl b/src/bin/pg_upgrade/t/004_subscription.pl index c59b83af9cc10..c545abf65816e 100644 --- a/src/bin/pg_upgrade/t/004_subscription.pl +++ b/src/bin/pg_upgrade/t/004_subscription.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Test for pg_upgrade of logical subscription. Note that after the successful # upgrade test, we can't use the old cluster to prevent failing in --link mode. @@ -41,8 +41,9 @@ my $connstr = $publisher->connstr . ' dbname=postgres'; # ------------------------------------------------------ -# Check that pg_upgrade fails when max_replication_slots configured in the new -# cluster is less than the number of subscriptions in the old cluster. +# Check that pg_upgrade fails when max_active_replication_origins configured +# in the new cluster is less than the number of subscriptions in the old +# cluster. # ------------------------------------------------------ # It is sufficient to use disabled subscription to test upgrade failure. $publisher->safe_psql('postgres', "CREATE PUBLICATION regress_pub1"); @@ -52,28 +53,34 @@ $old_sub->stop; -$new_sub->append_conf('postgresql.conf', "max_replication_slots = 0"); +$new_sub->append_conf('postgresql.conf', "max_active_replication_origins = 0"); # pg_upgrade will fail because the new cluster has insufficient -# max_replication_slots. +# max_active_replication_origins. command_checks_all( [ - 'pg_upgrade', '--no-sync', '-d', $old_sub->data_dir, - '-D', $new_sub->data_dir, '-b', $oldbindir, - '-B', $newbindir, '-s', $new_sub->host, - '-p', $old_sub->port, '-P', $new_sub->port, - $mode, '--check', + 'pg_upgrade', + '--no-sync', + '--old-datadir' => $old_sub->data_dir, + '--new-datadir' => $new_sub->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $new_sub->host, + '--old-port' => $old_sub->port, + '--new-port' => $new_sub->port, + $mode, + '--check', ], 1, [ - qr/"max_replication_slots" \(0\) must be greater than or equal to the number of subscriptions \(1\) on the old cluster/ + qr/"max_active_replication_origins" \(0\) must be greater than or equal to the number of subscriptions \(1\) on the old cluster/ ], [qr//], - 'run of pg_upgrade where the new cluster has insufficient max_replication_slots' + 'run of pg_upgrade where the new cluster has insufficient max_active_replication_origins' ); -# Reset max_replication_slots -$new_sub->append_conf('postgresql.conf', "max_replication_slots = 10"); +# Reset max_active_replication_origins +$new_sub->append_conf('postgresql.conf', "max_active_replication_origins = 10"); # Cleanup $publisher->safe_psql('postgres', "DROP PUBLICATION regress_pub1"); @@ -124,14 +131,25 @@ $old_sub->stop; -command_fails( +command_checks_all( + [ + 'pg_upgrade', + '--no-sync', + '--old-datadir' => $old_sub->data_dir, + '--new-datadir' => $new_sub->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $new_sub->host, + '--old-port' => $old_sub->port, + '--new-port' => $new_sub->port, + $mode, + '--check', + ], + 1, [ - 'pg_upgrade', '--no-sync', '-d', $old_sub->data_dir, - '-D', $new_sub->data_dir, '-b', $oldbindir, - '-B', $newbindir, '-s', $new_sub->host, - '-p', $old_sub->port, '-P', $new_sub->port, - $mode, '--check', + qr/\QYour installation contains subscriptions without origin or having relations not in i (initialize) or r (ready) state\E/ ], + [], 'run of pg_upgrade --check for old instance with relation in \'d\' datasync(invalid) state and missing replication origin' ); @@ -254,10 +272,15 @@ # ------------------------------------------------------ command_ok( [ - 'pg_upgrade', '--no-sync', '-d', $old_sub->data_dir, - '-D', $new_sub->data_dir, '-b', $oldbindir, - '-B', $newbindir, '-s', $new_sub->host, - '-p', $old_sub->port, '-P', $new_sub->port, + 'pg_upgrade', + '--no-sync', + '--old-datadir' => $old_sub->data_dir, + '--new-datadir' => $new_sub->data_dir, + '--old-bindir' => $oldbindir, + '--new-bindir' => $newbindir, + '--socketdir' => $new_sub->host, + '--old-port' => $old_sub->port, + '--new-port' => $new_sub->port, $mode ], 'run of pg_upgrade for old instance when the subscription tables are in init/ready state' diff --git a/src/bin/pg_upgrade/t/005_char_signedness.pl b/src/bin/pg_upgrade/t/005_char_signedness.pl new file mode 100644 index 0000000000000..cd8cff6f5132d --- /dev/null +++ b/src/bin/pg_upgrade/t/005_char_signedness.pl @@ -0,0 +1,95 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +# Tests for handling the default char signedness during upgrade. + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Can be changed to test the other modes +my $mode = $ENV{PG_TEST_PG_UPGRADE_MODE} || '--copy'; + +# Initialize old and new clusters +my $old = PostgreSQL::Test::Cluster->new('old'); +my $new = PostgreSQL::Test::Cluster->new('new'); +$old->init(); +$new->init(); + +# Check the default char signedness of both the old and the new clusters. +# Newly created clusters unconditionally use 'signed'. +command_like( + [ 'pg_controldata', $old->data_dir ], + qr/Default char data signedness:\s+signed/, + 'default char signedness of old cluster is signed in control file'); +command_like( + [ 'pg_controldata', $new->data_dir ], + qr/Default char data signedness:\s+signed/, + 'default char signedness of new cluster is signed in control file'); + +# Set the old cluster's default char signedness to unsigned for test. +command_ok( + [ + 'pg_resetwal', + '--char-signedness' => 'unsigned', + '--force', + $old->data_dir + ], + "set old cluster's default char signedness to unsigned"); + +# Check if the value is successfully updated. +command_like( + [ 'pg_controldata', $old->data_dir ], + qr/Default char data signedness:\s+unsigned/, + 'updated default char signedness is unsigned in control file'); + +# In a VPATH build, we'll be started in the source directory, but we want +# to run pg_upgrade in the build directory so that any files generated finish +# in it, like delete_old_cluster.{sh,bat}. +chdir ${PostgreSQL::Test::Utils::tmp_check}; + +# Cannot use --set-char-signedness option for upgrading from v18+ +command_checks_all( + [ + 'pg_upgrade', '--no-sync', + '--old-datadir' => $old->data_dir, + '--new-datadir' => $new->data_dir, + '--old-bindir' => $old->config_data('--bindir'), + '--new-bindir' => $new->config_data('--bindir'), + '--socketdir' => $new->host, + '--old-port' => $old->port, + '--new-port' => $new->port, + '--set-char-signedness' => 'signed', + $mode + ], + 1, + [qr/option --set-char-signedness cannot be used/], + [], + '--set-char-signedness option cannot be used for upgrading from v18 or later' +); + +# pg_upgrade should be successful. +command_ok( + [ + 'pg_upgrade', '--no-sync', + '--old-datadir' => $old->data_dir, + '--new-datadir' => $new->data_dir, + '--old-bindir' => $old->config_data('--bindir'), + '--new-bindir' => $new->config_data('--bindir'), + '--socketdir' => $new->host, + '--old-port' => $old->port, + '--new-port' => $new->port, + $mode + ], + 'run of pg_upgrade'); + +# Check if the default char signedness of the new cluster inherited +# the old cluster's value. +command_like( + [ 'pg_controldata', $new->data_dir ], + qr/Default char data signedness:\s+unsigned/, + 'the default char signedness is updated during pg_upgrade'); + +done_testing(); diff --git a/src/bin/pg_upgrade/t/006_transfer_modes.pl b/src/bin/pg_upgrade/t/006_transfer_modes.pl new file mode 100644 index 0000000000000..550a63fdf7d47 --- /dev/null +++ b/src/bin/pg_upgrade/t/006_transfer_modes.pl @@ -0,0 +1,116 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +# Tests for file transfer modes + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +sub test_mode +{ + my ($mode) = @_; + + my $old = PostgreSQL::Test::Cluster->new('old', install_path => $ENV{oldinstall}); + my $new = PostgreSQL::Test::Cluster->new('new'); + + # --swap can't be used to upgrade from versions older than 10, so just skip + # the test if the old cluster version is too old. + if ($old->pg_version < 10 && $mode eq "--swap") + { + $old->clean_node(); + $new->clean_node(); + return; + } + + if (defined($ENV{oldinstall})) + { + # Checksums are now enabled by default, but weren't before 18, so pass + # '-k' to initdb on older versions so that upgrades work. + $old->init(extra => ['-k']); + } + else + { + $old->init(); + } + $new->init(); + + # Create a small variety of simple test objects on the old cluster. We'll + # check that these reach the new version after upgrading. + $old->start; + $old->safe_psql('postgres', "CREATE TABLE test1 AS SELECT generate_series(1, 100)"); + $old->safe_psql('postgres', "CREATE DATABASE testdb1"); + $old->safe_psql('testdb1', "CREATE TABLE test2 AS SELECT generate_series(200, 300)"); + $old->safe_psql('testdb1', "VACUUM FULL test2"); + $old->safe_psql('testdb1', "CREATE SEQUENCE testseq START 5432"); + + # For cross-version tests, we can also check that pg_upgrade handles + # tablespaces. + if (defined($ENV{oldinstall})) + { + my $tblspc = PostgreSQL::Test::Utils::tempdir_short(); + $old->safe_psql('postgres', "CREATE TABLESPACE test_tblspc LOCATION '$tblspc'"); + $old->safe_psql('postgres', "CREATE DATABASE testdb2 TABLESPACE test_tblspc"); + $old->safe_psql('postgres', "CREATE TABLE test3 TABLESPACE test_tblspc AS SELECT generate_series(300, 401)"); + $old->safe_psql('testdb2', "CREATE TABLE test4 AS SELECT generate_series(400, 502)"); + } + $old->stop; + + my $result = command_ok_or_fails_like( + [ + 'pg_upgrade', '--no-sync', + '--old-datadir' => $old->data_dir, + '--new-datadir' => $new->data_dir, + '--old-bindir' => $old->config_data('--bindir'), + '--new-bindir' => $new->config_data('--bindir'), + '--socketdir' => $new->host, + '--old-port' => $old->port, + '--new-port' => $new->port, + $mode + ], + qr/.* not supported on this platform|could not .* between old and new data directories: .*/, + qr/^$/, + "pg_upgrade with transfer mode $mode"); + + # If pg_upgrade was successful, check that all of our test objects reached + # the new version. + if ($result) + { + $new->start; + $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test1"); + is($result, '100', "test1 data after pg_upgrade $mode"); + $result = $new->safe_psql('testdb1', "SELECT COUNT(*) FROM test2"); + is($result, '101', "test2 data after pg_upgrade $mode"); + $result = $new->safe_psql('testdb1', "SELECT nextval('testseq')"); + is($result, '5432', "sequence data after pg_upgrade $mode"); + + # For cross-version tests, we should have some objects in a non-default + # tablespace. + if (defined($ENV{oldinstall})) + { + $result = $new->safe_psql('postgres', "SELECT COUNT(*) FROM test3"); + is($result, '102', "test3 data after pg_upgrade $mode"); + $result = $new->safe_psql('testdb2', "SELECT COUNT(*) FROM test4"); + is($result, '103', "test4 data after pg_upgrade $mode"); + } + $new->stop; + } + + $old->clean_node(); + $new->clean_node(); +} + +# Run pg_upgrade in tmp_check to avoid leaving files like +# delete_old_cluster.{sh,bat} in the source directory for VPATH and meson +# builds. +chdir ${PostgreSQL::Test::Utils::tmp_check}; + +test_mode('--clone'); +test_mode('--copy'); +test_mode('--copy-file-range'); +test_mode('--link'); +test_mode('--swap'); + +done_testing(); diff --git a/src/bin/pg_upgrade/tablespace.c b/src/bin/pg_upgrade/tablespace.c index 043e5e721bd34..3520a75ba317d 100644 --- a/src/bin/pg_upgrade/tablespace.c +++ b/src/bin/pg_upgrade/tablespace.c @@ -3,7 +3,7 @@ * * tablespace functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/tablespace.c */ diff --git a/src/bin/pg_upgrade/task.c b/src/bin/pg_upgrade/task.c new file mode 100644 index 0000000000000..ee0e245715215 --- /dev/null +++ b/src/bin/pg_upgrade/task.c @@ -0,0 +1,442 @@ +/* + * task.c + * framework for parallelizing pg_upgrade's once-in-each-database tasks + * + * This framework provides an efficient way of running the various + * once-in-each-database tasks required by pg_upgrade. Specifically, it + * parallelizes these tasks by managing a set of slots that follow a simple + * state machine and by using libpq's asynchronous APIs to establish the + * connections and run the queries. Callers simply need to create a callback + * function and build/execute an UpgradeTask. A simple example follows: + * + * static void + * my_process_cb(DbInfo *dbinfo, PGresult *res, void *arg) + * { + * for (int i = 0; i < PQntuples(res); i++) + * { + * ... process results ... + * } + * } + * + * void + * my_task(ClusterInfo *cluster) + * { + * UpgradeTask *task = upgrade_task_create(); + * + * upgrade_task_add_step(task, + * "... query text ...", + * my_process_cb, + * true, // let the task free the PGresult + * NULL); // "arg" pointer for callback + * upgrade_task_run(task, cluster); + * upgrade_task_free(task); + * } + * + * Note that multiple steps can be added to a given task. When there are + * multiple steps, the task will run all of the steps consecutively in the same + * database connection before freeing the connection and moving on. In other + * words, it only ever initiates one connection to each database in the + * cluster for a given run. + * + * Copyright (c) 2024-2025, PostgreSQL Global Development Group + * src/bin/pg_upgrade/task.c + */ + +#include "postgres_fe.h" + +#include "common/connect.h" +#include "fe_utils/string_utils.h" +#include "pg_upgrade.h" + +/* + * dbs_complete stores the number of databases that we have completed + * processing. When this value equals the number of databases in the cluster, + * the task is finished. + */ +static int dbs_complete; + +/* + * dbs_processing stores the index of the next database in the cluster's array + * of databases that will be picked up for processing. It will always be + * greater than or equal to dbs_complete. + */ +static int dbs_processing; + +/* + * This struct stores the information for a single step of a task. Note that + * the query string is stored in the "queries" PQExpBuffer for the UpgradeTask. + * All steps in a task are run in a single connection before moving on to the + * next database (which requires a new connection). + */ +typedef struct UpgradeTaskStep +{ + UpgradeTaskProcessCB process_cb; /* processes the results of the query */ + bool free_result; /* should we free the result? */ + void *arg; /* pointer passed to process_cb */ +} UpgradeTaskStep; + +/* + * This struct is a thin wrapper around an array of steps, i.e., + * UpgradeTaskStep, plus a PQExpBuffer for all the query strings. + */ +struct UpgradeTask +{ + UpgradeTaskStep *steps; + int num_steps; + PQExpBuffer queries; +}; + +/* + * The different states for a parallel slot. + */ +typedef enum UpgradeTaskSlotState +{ + FREE, /* slot available for use in a new database */ + CONNECTING, /* waiting for connection to be established */ + RUNNING_QUERIES, /* running/processing queries in the task */ +} UpgradeTaskSlotState; + +/* + * We maintain an array of user_opts.jobs slots to execute the task. + */ +typedef struct UpgradeTaskSlot +{ + UpgradeTaskSlotState state; /* state of the slot */ + int db_idx; /* index of the database assigned to slot */ + int step_idx; /* index of the current step of task */ + PGconn *conn; /* current connection managed by slot */ + bool ready; /* slot is ready for processing */ + bool select_mode; /* select() mode: true->read, false->write */ + int sock; /* file descriptor for connection's socket */ +} UpgradeTaskSlot; + +/* + * Initializes an UpgradeTask. + */ +UpgradeTask * +upgrade_task_create(void) +{ + UpgradeTask *task = pg_malloc0(sizeof(UpgradeTask)); + + task->queries = createPQExpBuffer(); + + /* All tasks must first set a secure search_path. */ + upgrade_task_add_step(task, ALWAYS_SECURE_SEARCH_PATH_SQL, NULL, true, NULL); + + return task; +} + +/* + * Frees all storage associated with an UpgradeTask. + */ +void +upgrade_task_free(UpgradeTask *task) +{ + destroyPQExpBuffer(task->queries); + pg_free(task->steps); + pg_free(task); +} + +/* + * Adds a step to an UpgradeTask. The steps will be executed in each database + * in the order in which they are added. + * + * task: task object that must have been initialized via upgrade_task_create() + * query: the query text + * process_cb: function that processes the results of the query + * free_result: should we free the PGresult, or leave it to the caller? + * arg: pointer to task-specific data that is passed to each callback + */ +void +upgrade_task_add_step(UpgradeTask *task, const char *query, + UpgradeTaskProcessCB process_cb, bool free_result, + void *arg) +{ + UpgradeTaskStep *new_step; + + task->steps = pg_realloc(task->steps, + ++task->num_steps * sizeof(UpgradeTaskStep)); + + new_step = &task->steps[task->num_steps - 1]; + new_step->process_cb = process_cb; + new_step->free_result = free_result; + new_step->arg = arg; + + appendPQExpBuffer(task->queries, "%s;", query); +} + +/* + * Build a connection string for the slot's current database and asynchronously + * start a new connection, but do not wait for the connection to be + * established. + */ +static void +start_conn(const ClusterInfo *cluster, UpgradeTaskSlot *slot) +{ + PQExpBufferData conn_opts; + DbInfo *dbinfo = &cluster->dbarr.dbs[slot->db_idx]; + + /* Build connection string with proper quoting */ + initPQExpBuffer(&conn_opts); + appendPQExpBufferStr(&conn_opts, "dbname="); + appendConnStrVal(&conn_opts, dbinfo->db_name); + appendPQExpBufferStr(&conn_opts, " user="); + appendConnStrVal(&conn_opts, os_info.user); + appendPQExpBuffer(&conn_opts, " port=%d", cluster->port); + if (cluster->sockdir) + { + appendPQExpBufferStr(&conn_opts, " host="); + appendConnStrVal(&conn_opts, cluster->sockdir); + } + + slot->conn = PQconnectStart(conn_opts.data); + + if (!slot->conn) + pg_fatal("out of memory"); + + termPQExpBuffer(&conn_opts); +} + +/* + * Run the process_cb callback function to process the result of a query, and + * free the result if the caller indicated we should do so. + */ +static void +process_query_result(const ClusterInfo *cluster, UpgradeTaskSlot *slot, + const UpgradeTask *task) +{ + UpgradeTaskStep *steps = &task->steps[slot->step_idx]; + UpgradeTaskProcessCB process_cb = steps->process_cb; + DbInfo *dbinfo = &cluster->dbarr.dbs[slot->db_idx]; + PGresult *res = PQgetResult(slot->conn); + + if (PQstatus(slot->conn) == CONNECTION_BAD || + (PQresultStatus(res) != PGRES_TUPLES_OK && + PQresultStatus(res) != PGRES_COMMAND_OK)) + pg_fatal("connection failure: %s", PQerrorMessage(slot->conn)); + + /* + * We assume that a NULL process_cb callback function means there's + * nothing to process. This is primarily intended for the initial step in + * every task that sets a safe search_path. + */ + if (process_cb) + (*process_cb) (dbinfo, res, steps->arg); + + if (steps->free_result) + PQclear(res); +} + +/* + * Advances the state machine for a given slot as necessary. + */ +static void +process_slot(const ClusterInfo *cluster, UpgradeTaskSlot *slot, const UpgradeTask *task) +{ + PostgresPollingStatusType status; + + if (!slot->ready) + return; + + switch (slot->state) + { + case FREE: + + /* + * If all of the databases in the cluster have been processed or + * are currently being processed by other slots, we are done. + */ + if (dbs_processing >= cluster->dbarr.ndbs) + return; + + /* + * Claim the next database in the cluster's array and initiate a + * new connection. + */ + slot->db_idx = dbs_processing++; + slot->state = CONNECTING; + start_conn(cluster, slot); + + return; + + case CONNECTING: + + /* Check for connection failure. */ + status = PQconnectPoll(slot->conn); + if (status == PGRES_POLLING_FAILED) + pg_fatal("connection failure: %s", PQerrorMessage(slot->conn)); + + /* Check whether the connection is still establishing. */ + if (status != PGRES_POLLING_OK) + { + slot->select_mode = (status == PGRES_POLLING_READING); + return; + } + + /* + * Move on to running/processing the queries in the task. + */ + slot->state = RUNNING_QUERIES; + slot->select_mode = true; /* wait until ready for reading */ + if (!PQsendQuery(slot->conn, task->queries->data)) + pg_fatal("connection failure: %s", PQerrorMessage(slot->conn)); + + return; + + case RUNNING_QUERIES: + + /* + * Consume any available data and clear the read-ready indicator + * for the connection. + */ + if (!PQconsumeInput(slot->conn)) + pg_fatal("connection failure: %s", PQerrorMessage(slot->conn)); + + /* + * Process any results that are ready so that we can free up this + * slot for another database as soon as possible. + */ + for (; slot->step_idx < task->num_steps; slot->step_idx++) + { + /* If no more results are available yet, move on. */ + if (PQisBusy(slot->conn)) + return; + + process_query_result(cluster, slot, task); + } + + /* + * If we just finished processing the result of the last step in + * the task, free the slot. We recursively call this function on + * the newly-freed slot so that we can start initiating the next + * connection immediately instead of waiting for the next loop + * through the slots. + */ + dbs_complete++; + PQfinish(slot->conn); + memset(slot, 0, sizeof(UpgradeTaskSlot)); + slot->ready = true; + + process_slot(cluster, slot, task); + + return; + } +} + +/* + * Returns -1 on error, else the number of ready descriptors. + */ +static int +select_loop(int maxFd, fd_set *input, fd_set *output) +{ + fd_set save_input = *input; + fd_set save_output = *output; + + if (maxFd == 0) + return 0; + + for (;;) + { + int i; + + *input = save_input; + *output = save_output; + + i = select(maxFd + 1, input, output, NULL, NULL); + +#ifndef WIN32 + if (i < 0 && errno == EINTR) + continue; +#else + if (i == SOCKET_ERROR && WSAGetLastError() == WSAEINTR) + continue; +#endif + return i; + } +} + +/* + * Wait on the slots to either finish connecting or to receive query results if + * possible. This avoids a tight loop in upgrade_task_run(). + */ +static void +wait_on_slots(UpgradeTaskSlot *slots, int numslots) +{ + fd_set input; + fd_set output; + int maxFd = 0; + + FD_ZERO(&input); + FD_ZERO(&output); + + for (int i = 0; i < numslots; i++) + { + /* + * We assume the previous call to process_slot() handled everything + * that was marked ready in the previous call to wait_on_slots(), if + * any. + */ + slots[i].ready = false; + + /* + * This function should only ever see free slots as we are finishing + * processing the last few databases, at which point we don't have any + * databases left for them to process. We'll never use these slots + * again, so we can safely ignore them. + */ + if (slots[i].state == FREE) + continue; + + /* + * Add the socket to the set. + */ + slots[i].sock = PQsocket(slots[i].conn); + if (slots[i].sock < 0) + pg_fatal("invalid socket"); + FD_SET(slots[i].sock, slots[i].select_mode ? &input : &output); + maxFd = Max(maxFd, slots[i].sock); + } + + /* + * If we found socket(s) to wait on, wait. + */ + if (select_loop(maxFd, &input, &output) == -1) + pg_fatal("%s() failed: %m", "select"); + + /* + * Mark which sockets appear to be ready. + */ + for (int i = 0; i < numslots; i++) + slots[i].ready |= (FD_ISSET(slots[i].sock, &input) || + FD_ISSET(slots[i].sock, &output)); +} + +/* + * Runs all the steps of the task in every database in the cluster using + * user_opts.jobs parallel slots. + */ +void +upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster) +{ + int jobs = Max(1, user_opts.jobs); + UpgradeTaskSlot *slots = pg_malloc0(sizeof(UpgradeTaskSlot) * jobs); + + dbs_complete = 0; + dbs_processing = 0; + + /* + * Process every slot the first time round. + */ + for (int i = 0; i < jobs; i++) + slots[i].ready = true; + + while (dbs_complete < cluster->dbarr.ndbs) + { + for (int i = 0; i < jobs; i++) + process_slot(cluster, &slots[i], task); + + wait_on_slots(slots, jobs); + } + + pg_free(slots); +} diff --git a/src/bin/pg_upgrade/util.c b/src/bin/pg_upgrade/util.c index 2478372992b74..de0673f11d69a 100644 --- a/src/bin/pg_upgrade/util.c +++ b/src/bin/pg_upgrade/util.c @@ -3,7 +3,7 @@ * * utility functions * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/util.c */ diff --git a/src/bin/pg_upgrade/version.c b/src/bin/pg_upgrade/version.c index 2de6dffccdab4..3ad5a991a30ea 100644 --- a/src/bin/pg_upgrade/version.c +++ b/src/bin/pg_upgrade/version.c @@ -3,7 +3,7 @@ * * Postgres-version-specific routines * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * src/bin/pg_upgrade/version.c */ @@ -139,6 +139,38 @@ old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) check_ok(); } +/* + * Callback function for processing results of query for + * report_extension_updates()'s UpgradeTask. If the query returned any rows, + * write the details to the report file. + */ +static void +process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg) +{ + int ntups = PQntuples(res); + int i_name = PQfnumber(res, "name"); + UpgradeTaskReport *report = (UpgradeTaskReport *) arg; + PQExpBufferData connectbuf; + + AssertVariableIsOfType(&process_extension_updates, UpgradeTaskProcessCB); + + if (ntups == 0) + return; + + if (report->file == NULL && + (report->file = fopen_priv(report->path, "w")) == NULL) + pg_fatal("could not open file \"%s\": %m", report->path); + + initPQExpBuffer(&connectbuf); + appendPsqlMetaConnect(&connectbuf, dbinfo->db_name); + fputs(connectbuf.data, report->file); + termPQExpBuffer(&connectbuf); + + for (int rowno = 0; rowno < ntups; rowno++) + fprintf(report->file, "ALTER EXTENSION %s UPDATE;\n", + quote_identifier(PQgetvalue(res, rowno, i_name))); +} + /* * report_extension_updates() * Report extensions that should be updated. @@ -146,57 +178,26 @@ old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode) void report_extension_updates(ClusterInfo *cluster) { - int dbnum; - FILE *script = NULL; - char *output_path = "update_extensions.sql"; + UpgradeTaskReport report; + UpgradeTask *task = upgrade_task_create(); + const char *query = "SELECT name " + "FROM pg_available_extensions " + "WHERE installed_version != default_version"; prep_status("Checking for extension updates"); - for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++) - { - PGresult *res; - bool db_used = false; - int ntups; - int rowno; - int i_name; - DbInfo *active_db = &cluster->dbarr.dbs[dbnum]; - PGconn *conn = connectToServer(cluster, active_db->db_name); - - /* find extensions needing updates */ - res = executeQueryOrDie(conn, - "SELECT name " - "FROM pg_available_extensions " - "WHERE installed_version != default_version" - ); - - ntups = PQntuples(res); - i_name = PQfnumber(res, "name"); - for (rowno = 0; rowno < ntups; rowno++) - { - if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL) - pg_fatal("could not open file \"%s\": %m", output_path); - if (!db_used) - { - PQExpBufferData connectbuf; - - initPQExpBuffer(&connectbuf); - appendPsqlMetaConnect(&connectbuf, active_db->db_name); - fputs(connectbuf.data, script); - termPQExpBuffer(&connectbuf); - db_used = true; - } - fprintf(script, "ALTER EXTENSION %s UPDATE;\n", - quote_identifier(PQgetvalue(res, rowno, i_name))); - } + report.file = NULL; + strcpy(report.path, "update_extensions.sql"); - PQclear(res); + upgrade_task_add_step(task, query, process_extension_updates, + true, &report); - PQfinish(conn); - } + upgrade_task_run(task, cluster); + upgrade_task_free(task); - if (script) + if (report.file) { - fclose(script); + fclose(report.file); report_status(PG_REPORT, "notice"); pg_log(PG_REPORT, "\n" "Your installation contains extensions that should be updated\n" @@ -204,7 +205,7 @@ report_extension_updates(ClusterInfo *cluster) " %s\n" "when executed by psql by the database superuser will update\n" "these extensions.", - output_path); + report.path); } else check_ok(); diff --git a/src/bin/pg_verifybackup/Makefile b/src/bin/pg_verifybackup/Makefile index 7c045f142e8d7..374d4a8afd175 100644 --- a/src/bin/pg_verifybackup/Makefile +++ b/src/bin/pg_verifybackup/Makefile @@ -17,10 +17,12 @@ top_builddir = ../../.. include $(top_builddir)/src/Makefile.global # We need libpq only because fe_utils does. +override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport) OBJS = \ $(WIN32RES) \ + astreamer_verify.o \ pg_verifybackup.o all: pg_verifybackup diff --git a/src/bin/pg_verifybackup/astreamer_verify.c b/src/bin/pg_verifybackup/astreamer_verify.c new file mode 100644 index 0000000000000..33cf67670a70d --- /dev/null +++ b/src/bin/pg_verifybackup/astreamer_verify.c @@ -0,0 +1,432 @@ +/*------------------------------------------------------------------------- + * + * astreamer_verify.c + * + * Archive streamer for verification of a tar format backup (including + * compressed tar format backups). + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * + * src/bin/pg_verifybackup/astreamer_verify.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include "access/xlog_internal.h" +#include "catalog/pg_control.h" +#include "pg_verifybackup.h" + +typedef struct astreamer_verify +{ + /* These fields don't change once initialized. */ + astreamer base; + verifier_context *context; + char *archive_name; + Oid tblspc_oid; + + /* These fields change for each archive member. */ + manifest_file *mfile; + bool verify_checksum; + bool verify_control_data; + pg_checksum_context *checksum_ctx; + uint64 checksum_bytes; + ControlFileData control_file; + uint64 control_file_bytes; +} astreamer_verify; + +static void astreamer_verify_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_verify_finalize(astreamer *streamer); +static void astreamer_verify_free(astreamer *streamer); + +static void member_verify_header(astreamer *streamer, astreamer_member *member); +static void member_compute_checksum(astreamer *streamer, + astreamer_member *member, + const char *data, int len); +static void member_verify_checksum(astreamer *streamer); +static void member_copy_control_data(astreamer *streamer, + astreamer_member *member, + const char *data, int len); +static void member_verify_control_data(astreamer *streamer); +static void member_reset_info(astreamer *streamer); + +static const astreamer_ops astreamer_verify_ops = { + .content = astreamer_verify_content, + .finalize = astreamer_verify_finalize, + .free = astreamer_verify_free +}; + +/* + * Create an astreamer that can verify a tar file. + */ +astreamer * +astreamer_verify_content_new(astreamer *next, verifier_context *context, + char *archive_name, Oid tblspc_oid) +{ + astreamer_verify *streamer; + + streamer = palloc0(sizeof(astreamer_verify)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_verify_ops; + + streamer->base.bbs_next = next; + streamer->context = context; + streamer->archive_name = archive_name; + streamer->tblspc_oid = tblspc_oid; + + if (!context->skip_checksums) + streamer->checksum_ctx = pg_malloc(sizeof(pg_checksum_context)); + + return &streamer->base; +} + +/* + * Main entry point of the archive streamer for verifying tar members. + */ +static void +astreamer_verify_content(astreamer *streamer, astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + + Assert(context != ASTREAMER_UNKNOWN); + + switch (context) + { + case ASTREAMER_MEMBER_HEADER: + /* Initial setup plus decide which checks to perform. */ + member_verify_header(streamer, member); + break; + + case ASTREAMER_MEMBER_CONTENTS: + /* Incremental work required to verify file contents. */ + if (mystreamer->verify_checksum) + member_compute_checksum(streamer, member, data, len); + if (mystreamer->verify_control_data) + member_copy_control_data(streamer, member, data, len); + break; + + case ASTREAMER_MEMBER_TRAILER: + /* Now we've got all the file data. */ + if (mystreamer->verify_checksum) + member_verify_checksum(streamer); + if (mystreamer->verify_control_data) + member_verify_control_data(streamer); + + /* Reset for next archive member. */ + member_reset_info(streamer); + break; + + case ASTREAMER_ARCHIVE_TRAILER: + break; + + default: + /* Shouldn't happen. */ + pg_fatal("unexpected state while parsing tar archive"); + } +} + +/* + * End-of-stream processing for a astreamer_verify stream. + */ +static void +astreamer_verify_finalize(astreamer *streamer) +{ + Assert(streamer->bbs_next == NULL); +} + +/* + * Free memory associated with a astreamer_verify stream. + */ +static void +astreamer_verify_free(astreamer *streamer) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + + if (mystreamer->checksum_ctx) + pfree(mystreamer->checksum_ctx); + + pfree(streamer); +} + +/* + * Prepare to validate the next archive member. + */ +static void +member_verify_header(astreamer *streamer, astreamer_member *member) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + manifest_file *m; + char pathname[MAXPGPATH]; + + /* We are only interested in normal files. */ + if (member->is_directory || member->is_link) + return; + + /* + * The backup manifest stores a relative path to the base directory for + * files belonging to a tablespace, while the tablespace backup tar + * archive does not include this path. + * + * The pathname taken from the tar file could contain '.' or '..' + * references, which we want to remove, so apply canonicalize_path(). It + * could also be an absolute pathname, which we want to treat as a + * relative path, so prepend "./" if we're not adding a tablespace prefix + * to make sure that canonicalize_path() does what we want. + */ + if (OidIsValid(mystreamer->tblspc_oid)) + snprintf(pathname, MAXPGPATH, "%s/%u/%s", + "pg_tblspc", mystreamer->tblspc_oid, member->pathname); + else + snprintf(pathname, MAXPGPATH, "./%s", member->pathname); + canonicalize_path(pathname); + + /* Ignore any files that are listed in the ignore list. */ + if (should_ignore_relpath(mystreamer->context, pathname)) + return; + + /* Check whether there's an entry in the manifest hash. */ + m = manifest_files_lookup(mystreamer->context->manifest->files, pathname); + if (m == NULL) + { + report_backup_error(mystreamer->context, + "file \"%s\" is present in archive \"%s\" but not in the manifest", + member->pathname, mystreamer->archive_name); + return; + } + mystreamer->mfile = m; + + /* Flag this entry as having been encountered in a tar archive. */ + m->matched = true; + + /* Check that the size matches. */ + if (m->size != member->size) + { + report_backup_error(mystreamer->context, + "file \"%s\" has size %llu in archive \"%s\" but size %" PRIu64 " in the manifest", + member->pathname, + (unsigned long long) member->size, + mystreamer->archive_name, + m->size); + m->bad = true; + return; + } + + /* + * Decide whether we're going to verify the checksum for this file, and + * whether we're going to perform the additional validation that we do + * only for the control file. + */ + mystreamer->verify_checksum = + (!mystreamer->context->skip_checksums && should_verify_checksum(m)); + mystreamer->verify_control_data = + mystreamer->context->manifest->version != 1 && + !m->bad && strcmp(m->pathname, XLOG_CONTROL_FILE) == 0; + + /* If we're going to verify the checksum, initial a checksum context. */ + if (mystreamer->verify_checksum && + pg_checksum_init(mystreamer->checksum_ctx, m->checksum_type) < 0) + { + report_backup_error(mystreamer->context, + "%s: could not initialize checksum of file \"%s\"", + mystreamer->archive_name, m->pathname); + + /* + * Checksum verification cannot be performed without proper context + * initialization. + */ + mystreamer->verify_checksum = false; + } +} + +/* + * Computes the checksum incrementally for the received file content. + * + * Should have a correctly initialized checksum_ctx, which will be used for + * incremental checksum computation. + */ +static void +member_compute_checksum(astreamer *streamer, astreamer_member *member, + const char *data, int len) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + pg_checksum_context *checksum_ctx = mystreamer->checksum_ctx; + manifest_file *m = mystreamer->mfile; + + Assert(mystreamer->verify_checksum); + Assert(m->checksum_type == checksum_ctx->type); + + /* + * Update the total count of computed checksum bytes so that we can + * cross-check against the file size. + */ + mystreamer->checksum_bytes += len; + + /* Feed these bytes to the checksum calculation. */ + if (pg_checksum_update(checksum_ctx, (uint8 *) data, len) < 0) + { + report_backup_error(mystreamer->context, + "could not update checksum of file \"%s\"", + m->pathname); + mystreamer->verify_checksum = false; + } +} + +/* + * Perform the final computation and checksum verification after the entire + * file content has been processed. + */ +static void +member_verify_checksum(astreamer *streamer) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + manifest_file *m = mystreamer->mfile; + uint8 checksumbuf[PG_CHECKSUM_MAX_LENGTH]; + int checksumlen; + + Assert(mystreamer->verify_checksum); + + /* + * It's unclear how this could fail, but let's check anyway to be safe. + */ + if (mystreamer->checksum_bytes != m->size) + { + report_backup_error(mystreamer->context, + "file \"%s\" in archive \"%s\" should contain %" PRIu64 " bytes, but %" PRIu64 " bytes were read", + m->pathname, mystreamer->archive_name, + m->size, + mystreamer->checksum_bytes); + return; + } + + /* Get the final checksum. */ + checksumlen = pg_checksum_final(mystreamer->checksum_ctx, checksumbuf); + if (checksumlen < 0) + { + report_backup_error(mystreamer->context, + "could not finalize checksum of file \"%s\"", + m->pathname); + return; + } + + /* And check it against the manifest. */ + if (checksumlen != m->checksum_length) + report_backup_error(mystreamer->context, + "file \"%s\" in archive \"%s\" has checksum of length %d, but expected %d", + m->pathname, mystreamer->archive_name, + m->checksum_length, checksumlen); + else if (memcmp(checksumbuf, m->checksum_payload, checksumlen) != 0) + report_backup_error(mystreamer->context, + "checksum mismatch for file \"%s\" in archive \"%s\"", + m->pathname, mystreamer->archive_name); +} + +/* + * Stores the pg_control file contents into a local buffer; we need the entire + * control file data for verification. + */ +static void +member_copy_control_data(astreamer *streamer, astreamer_member *member, + const char *data, int len) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + + /* Should be here only for control file */ + Assert(mystreamer->verify_control_data); + + /* + * Copy the new data into the control file buffer, but do not overrun the + * buffer. Note that the on-disk length of the control file is expected to + * be PG_CONTROL_FILE_SIZE, but the part that fits in our buffer is + * shorter, just sizeof(ControlFileData). + */ + if (mystreamer->control_file_bytes < sizeof(ControlFileData)) + { + size_t remaining; + + remaining = sizeof(ControlFileData) - mystreamer->control_file_bytes; + memcpy(((char *) &mystreamer->control_file) + + mystreamer->control_file_bytes, + data, Min((size_t) len, remaining)); + } + + /* Remember how many bytes we saw, even if we didn't buffer them. */ + mystreamer->control_file_bytes += len; +} + +/* + * Performs the CRC calculation of pg_control data and then calls the routines + * that execute the final verification of the control file information. + */ +static void +member_verify_control_data(astreamer *streamer) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + manifest_data *manifest = mystreamer->context->manifest; + pg_crc32c crc; + + /* Should be here only for control file */ + Assert(strcmp(mystreamer->mfile->pathname, XLOG_CONTROL_FILE) == 0); + Assert(mystreamer->verify_control_data); + + /* + * If the control file is not the right length, that's a big problem. + * + * NB: There is a theoretical overflow risk here from casting to int, but + * it isn't likely to be a real problem and this enables us to match the + * same format string that pg_rewind uses for this case. Perhaps both this + * and pg_rewind should use an unsigned 64-bit value, but for now we don't + * worry about it. + */ + if (mystreamer->control_file_bytes != PG_CONTROL_FILE_SIZE) + report_fatal_error("unexpected control file size %d, expected %d", + (int) mystreamer->control_file_bytes, + PG_CONTROL_FILE_SIZE); + + /* Compute the CRC. */ + INIT_CRC32C(crc); + COMP_CRC32C(crc, &mystreamer->control_file, + offsetof(ControlFileData, crc)); + FIN_CRC32C(crc); + + /* Control file contents not meaningful if CRC is bad. */ + if (!EQ_CRC32C(crc, mystreamer->control_file.crc)) + report_fatal_error("%s: %s: CRC is incorrect", + mystreamer->archive_name, + mystreamer->mfile->pathname); + + /* Can't interpret control file if not current version. */ + if (mystreamer->control_file.pg_control_version != PG_CONTROL_VERSION) + report_fatal_error("%s: %s: unexpected control file version", + mystreamer->archive_name, + mystreamer->mfile->pathname); + + /* System identifiers should match. */ + if (manifest->system_identifier != + mystreamer->control_file.system_identifier) + report_fatal_error("%s: %s: manifest system identifier is %" PRIu64 ", but control file has %" PRIu64, + mystreamer->archive_name, + mystreamer->mfile->pathname, + manifest->system_identifier, + mystreamer->control_file.system_identifier); +} + +/* + * Reset flags and free memory allocations for member file verification. + */ +static void +member_reset_info(astreamer *streamer) +{ + astreamer_verify *mystreamer = (astreamer_verify *) streamer; + + mystreamer->mfile = NULL; + mystreamer->verify_checksum = false; + mystreamer->verify_control_data = false; + mystreamer->checksum_bytes = 0; + mystreamer->control_file_bytes = 0; +} diff --git a/src/bin/pg_verifybackup/meson.build b/src/bin/pg_verifybackup/meson.build index 7c7d31a0350a3..9567d55500d0a 100644 --- a/src/bin/pg_verifybackup/meson.build +++ b/src/bin/pg_verifybackup/meson.build @@ -1,6 +1,7 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_verifybackup_sources = files( + 'astreamer_verify.c', 'pg_verifybackup.c' ) diff --git a/src/bin/pg_verifybackup/nls.mk b/src/bin/pg_verifybackup/nls.mk index 6ad078350f607..2dfe7eb22c6d2 100644 --- a/src/bin/pg_verifybackup/nls.mk +++ b/src/bin/pg_verifybackup/nls.mk @@ -1,13 +1,18 @@ # src/bin/pg_verifybackup/nls.mk CATALOG_NAME = pg_verifybackup GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ + astreamer_verify.c \ pg_verifybackup.c \ ../../common/controldata_utils.c \ ../../common/cryptohash.c \ ../../common/cryptohash_openssl.c \ ../../common/fe_memutils.c \ ../../common/jsonapi.c \ - ../../common/parse_manifest.c + ../../common/parse_manifest.c \ + ../../fe_utils/astreamer_gzip.c \ + ../../fe_utils/astreamer_lz4.c \ + ../../fe_utils/astreamer_tar.c \ + ../../fe_utils/astreamer_zstd.c GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS) \ json_token_error:2 \ json_manifest_parse_failure:2 \ diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c index d77e70fbe3874..48994ef9bc6fc 100644 --- a/src/bin/pg_verifybackup/pg_verifybackup.c +++ b/src/bin/pg_verifybackup/pg_verifybackup.c @@ -3,7 +3,7 @@ * pg_verifybackup.c * Verify a backup against a backup manifest. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pg_verifybackup/pg_verifybackup.c @@ -15,15 +15,16 @@ #include #include +#include #include #include -#include "common/controldata_utils.h" -#include "common/hashfn_unstable.h" +#include "access/xlog_internal.h" #include "common/logging.h" #include "common/parse_manifest.h" #include "fe_utils/simple_list.h" #include "getopt_long.h" +#include "pg_verifybackup.h" #include "pgtime.h" /* @@ -46,76 +47,14 @@ #define READ_CHUNK_SIZE (128 * 1024) /* - * Each file described by the manifest file is parsed to produce an object - * like this. + * Tar file information needed for content verification. */ -typedef struct manifest_file +typedef struct tar_file { - uint32 status; /* hash status */ - const char *pathname; - size_t size; - pg_checksum_type checksum_type; - int checksum_length; - uint8 *checksum_payload; - bool matched; - bool bad; -} manifest_file; - -#define should_verify_checksum(m) \ - (((m)->matched) && !((m)->bad) && (((m)->checksum_type) != CHECKSUM_TYPE_NONE)) - -/* - * Define a hash table which we can use to store information about the files - * mentioned in the backup manifest. - */ -#define SH_PREFIX manifest_files -#define SH_ELEMENT_TYPE manifest_file -#define SH_KEY_TYPE const char * -#define SH_KEY pathname -#define SH_HASH_KEY(tb, key) hash_string(key) -#define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0) -#define SH_SCOPE static inline -#define SH_RAW_ALLOCATOR pg_malloc0 -#define SH_DECLARE -#define SH_DEFINE -#include "lib/simplehash.h" - -/* - * Each WAL range described by the manifest file is parsed to produce an - * object like this. - */ -typedef struct manifest_wal_range -{ - TimeLineID tli; - XLogRecPtr start_lsn; - XLogRecPtr end_lsn; - struct manifest_wal_range *next; - struct manifest_wal_range *prev; -} manifest_wal_range; - -/* - * All the data parsed from a backup_manifest file. - */ -typedef struct manifest_data -{ - int version; - uint64 system_identifier; - manifest_files_hash *files; - manifest_wal_range *first_wal_range; - manifest_wal_range *last_wal_range; -} manifest_data; - -/* - * All of the context information we need while checking a backup manifest. - */ -typedef struct verifier_context -{ - manifest_data *manifest; - char *backup_directory; - SimpleStringList ignore_list; - bool exit_on_error; - bool saw_any_error; -} verifier_context; + char *relpath; + Oid tblspc_oid; + pg_compress_algorithm compress_algorithm; +} tar_file; static manifest_data *parse_manifest_file(char *manifest_path); static void verifybackup_version_cb(JsonManifestParseContext *context, @@ -123,7 +62,7 @@ static void verifybackup_version_cb(JsonManifestParseContext *context, static void verifybackup_system_identifier(JsonManifestParseContext *context, uint64 manifest_system_identifier); static void verifybackup_per_file_cb(JsonManifestParseContext *context, - const char *pathname, size_t size, + const char *pathname, uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload); @@ -131,16 +70,22 @@ static void verifybackup_per_wal_range_cb(JsonManifestParseContext *context, TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn); -static void report_manifest_error(JsonManifestParseContext *context, - const char *fmt,...) - pg_attribute_printf(2, 3) pg_attribute_noreturn(); - -static void verify_backup_directory(verifier_context *context, - char *relpath, char *fullpath); -static void verify_backup_file(verifier_context *context, - char *relpath, char *fullpath); +pg_noreturn static void report_manifest_error(JsonManifestParseContext *context, + const char *fmt,...) + pg_attribute_printf(2, 3); + +static void verify_tar_backup(verifier_context *context, DIR *dir); +static void verify_plain_backup_directory(verifier_context *context, + char *relpath, char *fullpath, + DIR *dir); +static void verify_plain_backup_file(verifier_context *context, char *relpath, + char *fullpath); static void verify_control_file(const char *controlpath, uint64 manifest_system_identifier); +static void precheck_tar_backup_file(verifier_context *context, char *relpath, + char *fullpath, SimplePtrList *tarfiles); +static void verify_tar_file(verifier_context *context, char *relpath, + char *fullpath, astreamer *streamer); static void report_extra_backup_files(verifier_context *context); static void verify_backup_checksums(verifier_context *context); static void verify_file_checksum(verifier_context *context, @@ -149,22 +94,18 @@ static void verify_file_checksum(verifier_context *context, static void parse_required_wal(verifier_context *context, char *pg_waldump_path, char *wal_directory); - -static void report_backup_error(verifier_context *context, - const char *pg_restrict fmt,...) - pg_attribute_printf(2, 3); -static void report_fatal_error(const char *pg_restrict fmt,...) - pg_attribute_printf(1, 2) pg_attribute_noreturn(); -static bool should_ignore_relpath(verifier_context *context, const char *relpath); +static astreamer *create_archive_verifier(verifier_context *context, + char *archive_name, + Oid tblspc_oid, + pg_compress_algorithm compress_algo); static void progress_report(bool finished); static void usage(void); static const char *progname; -/* options */ +/* is progress reporting enabled? */ static bool show_progress = false; -static bool skip_checksums = false; /* Progress indicators */ static uint64 total_size = 0; @@ -180,6 +121,7 @@ main(int argc, char **argv) {"exit-on-error", no_argument, NULL, 'e'}, {"ignore", required_argument, NULL, 'i'}, {"manifest-path", required_argument, NULL, 'm'}, + {"format", required_argument, NULL, 'F'}, {"no-parse-wal", no_argument, NULL, 'n'}, {"progress", no_argument, NULL, 'P'}, {"quiet", no_argument, NULL, 'q'}, @@ -195,6 +137,7 @@ main(int argc, char **argv) bool quiet = false; char *wal_directory = NULL; char *pg_waldump_path = NULL; + DIR *dir; pg_logging_init(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_verifybackup")); @@ -237,7 +180,7 @@ main(int argc, char **argv) simple_string_list_append(&context.ignore_list, "recovery.signal"); simple_string_list_append(&context.ignore_list, "standby.signal"); - while ((c = getopt_long(argc, argv, "ei:m:nPqsw:", long_options, NULL)) != -1) + while ((c = getopt_long(argc, argv, "eF:i:m:nPqsw:", long_options, NULL)) != -1) { switch (c) { @@ -256,6 +199,15 @@ main(int argc, char **argv) manifest_path = pstrdup(optarg); canonicalize_path(manifest_path); break; + case 'F': + if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0) + context.format = 'p'; + else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0) + context.format = 't'; + else + pg_fatal("invalid backup format \"%s\", must be \"plain\" or \"tar\"", + optarg); + break; case 'n': no_parse_wal = true; break; @@ -266,7 +218,7 @@ main(int argc, char **argv) quiet = true; break; case 's': - skip_checksums = true; + context.skip_checksums = true; break; case 'w': wal_directory = pstrdup(optarg); @@ -345,25 +297,75 @@ main(int argc, char **argv) context.manifest = parse_manifest_file(manifest_path); /* - * Now scan the files in the backup directory. At this stage, we verify - * that every file on disk is present in the manifest and that the sizes - * match. We also set the "matched" flag on every manifest entry that - * corresponds to a file on disk. + * If the backup directory cannot be found, treat this as a fatal error. + */ + dir = opendir(context.backup_directory); + if (dir == NULL) + report_fatal_error("could not open directory \"%s\": %m", + context.backup_directory); + + /* + * At this point, we know that the backup directory exists, so it's now + * reasonable to check for files immediately inside it. Thus, before going + * further, if the user did not specify the backup format, check for + * PG_VERSION to distinguish between tar and plain format. */ - verify_backup_directory(&context, NULL, context.backup_directory); + if (context.format == '\0') + { + struct stat sb; + char *path; + + path = psprintf("%s/%s", context.backup_directory, "PG_VERSION"); + if (stat(path, &sb) == 0) + context.format = 'p'; + else if (errno != ENOENT) + { + pg_log_error("could not stat file \"%s\": %m", path); + exit(1); + } + else + { + /* No PG_VERSION, so assume tar format. */ + context.format = 't'; + } + pfree(path); + } + + /* + * XXX: In the future, we should consider enhancing pg_waldump to read WAL + * files from an archive. + */ + if (!no_parse_wal && context.format == 't') + { + pg_log_error("pg_waldump cannot read tar files"); + pg_log_error_hint("You must use -n/--no-parse-wal when verifying a tar-format backup."); + exit(1); + } + + /* + * Perform the appropriate type of verification appropriate based on the + * backup format. This will close 'dir'. + */ + if (context.format == 'p') + verify_plain_backup_directory(&context, NULL, context.backup_directory, + dir); + else + verify_tar_backup(&context, dir); /* * The "matched" flag should now be set on every entry in the hash table. * Any entries for which the bit is not set are files mentioned in the - * manifest that don't exist on disk. + * manifest that don't exist on disk (or in the relevant tar files). */ report_extra_backup_files(&context); /* - * Now do the expensive work of verifying file checksums, unless we were - * told to skip it. + * If this is a tar-format backup, checksums were already verified above; + * but if it's a plain-format backup, we postpone it until this point, + * since the earlier checks can be performed just by knowing which files + * are present, without needing to read all of them. */ - if (!skip_checksums) + if (context.format == 'p' && !context.skip_checksums) verify_backup_checksums(&context); /* @@ -546,7 +548,7 @@ verifybackup_system_identifier(JsonManifestParseContext *context, */ static void verifybackup_per_file_cb(JsonManifestParseContext *context, - const char *pathname, size_t size, + const char *pathname, uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload) { @@ -598,35 +600,27 @@ verifybackup_per_wal_range_cb(JsonManifestParseContext *context, } /* - * Verify one directory. + * Verify one directory of a plain-format backup. * * 'relpath' is NULL if we are to verify the top-level backup directory, * and otherwise the relative path to the directory that is to be verified. * * 'fullpath' is the backup directory with 'relpath' appended; i.e. the actual * filesystem path at which it can be found. + * + * 'dir' is an open directory handle, or NULL if the caller wants us to + * open it. If the caller chooses to pass a handle, we'll close it when + * we're done with it. */ static void -verify_backup_directory(verifier_context *context, char *relpath, - char *fullpath) +verify_plain_backup_directory(verifier_context *context, char *relpath, + char *fullpath, DIR *dir) { - DIR *dir; struct dirent *dirent; - dir = opendir(fullpath); - if (dir == NULL) + /* Open the directory unless the caller did it. */ + if (dir == NULL && ((dir = opendir(fullpath)) == NULL)) { - /* - * If even the toplevel backup directory cannot be found, treat this - * as a fatal error. - */ - if (relpath == NULL) - report_fatal_error("could not open directory \"%s\": %m", fullpath); - - /* - * Otherwise, treat this as a non-fatal error, but ignore any further - * errors related to this path and anything beneath it. - */ report_backup_error(context, "could not open directory \"%s\": %m", fullpath); simple_string_list_append(&context->ignore_list, relpath); @@ -651,7 +645,7 @@ verify_backup_directory(verifier_context *context, char *relpath, newrelpath = psprintf("%s/%s", relpath, filename); if (!should_ignore_relpath(context, newrelpath)) - verify_backup_file(context, newrelpath, newfullpath); + verify_plain_backup_file(context, newrelpath, newfullpath); pfree(newfullpath); pfree(newrelpath); @@ -668,11 +662,12 @@ verify_backup_directory(verifier_context *context, char *relpath, /* * Verify one file (which might actually be a directory or a symlink). * - * The arguments to this function have the same meaning as the arguments to - * verify_backup_directory. + * The arguments to this function have the same meaning as the similarly named + * arguments to verify_plain_backup_directory. */ static void -verify_backup_file(verifier_context *context, char *relpath, char *fullpath) +verify_plain_backup_file(verifier_context *context, char *relpath, + char *fullpath) { struct stat sb; manifest_file *m; @@ -695,15 +690,15 @@ verify_backup_file(verifier_context *context, char *relpath, char *fullpath) /* If it's a directory, just recurse. */ if (S_ISDIR(sb.st_mode)) { - verify_backup_directory(context, relpath, fullpath); + verify_plain_backup_directory(context, relpath, fullpath, NULL); return; } - /* If it's not a directory, it should be a plain file. */ + /* If it's not a directory, it should be a regular file. */ if (!S_ISREG(sb.st_mode)) { report_backup_error(context, - "\"%s\" is not a file or directory", + "\"%s\" is not a regular file or directory", relpath); return; } @@ -725,8 +720,9 @@ verify_backup_file(verifier_context *context, char *relpath, char *fullpath) if (m->size != sb.st_size) { report_backup_error(context, - "\"%s\" has size %lld on disk but size %zu in the manifest", - relpath, (long long int) sb.st_size, m->size); + "\"%s\" has size %llu on disk but size %llu in the manifest", + relpath, (unsigned long long) sb.st_size, + (unsigned long long) m->size); m->bad = true; } @@ -735,11 +731,12 @@ verify_backup_file(verifier_context *context, char *relpath, char *fullpath) * version 1. */ if (context->manifest->version != 1 && - strcmp(relpath, "global/pg_control") == 0) + strcmp(relpath, XLOG_CONTROL_FILE) == 0) verify_control_file(fullpath, context->manifest->system_identifier); /* Update statistics for progress report, if necessary */ - if (show_progress && !skip_checksums && should_verify_checksum(m)) + if (show_progress && !context->skip_checksums && + should_verify_checksum(m)) total_size += m->size; /* @@ -774,15 +771,266 @@ verify_control_file(const char *controlpath, uint64 manifest_system_identifier) /* System identifiers should match. */ if (manifest_system_identifier != control_file->system_identifier) - report_fatal_error("%s: manifest system identifier is %llu, but control file has %llu", + report_fatal_error("%s: manifest system identifier is %" PRIu64 ", but control file has %" PRIu64, controlpath, - (unsigned long long) manifest_system_identifier, - (unsigned long long) control_file->system_identifier); + manifest_system_identifier, + control_file->system_identifier); /* Release memory. */ pfree(control_file); } +/* + * Verify tar backup. + * + * The caller should pass a handle to the target directory, which we will + * close when we're done with it. + */ +static void +verify_tar_backup(verifier_context *context, DIR *dir) +{ + struct dirent *dirent; + SimplePtrList tarfiles = {NULL, NULL}; + SimplePtrListCell *cell; + + Assert(context->format != 'p'); + + progress_report(false); + + /* First pass: scan the directory for tar files. */ + while (errno = 0, (dirent = readdir(dir)) != NULL) + { + char *filename = dirent->d_name; + + /* Skip "." and ".." */ + if (filename[0] == '.' && (filename[1] == '\0' + || strcmp(filename, "..") == 0)) + continue; + + /* + * Unless it's something we should ignore, perform prechecks and add + * it to the list. + */ + if (!should_ignore_relpath(context, filename)) + { + char *fullpath; + + fullpath = psprintf("%s/%s", context->backup_directory, filename); + precheck_tar_backup_file(context, filename, fullpath, &tarfiles); + pfree(fullpath); + } + } + + if (closedir(dir)) + { + report_backup_error(context, + "could not close directory \"%s\": %m", + context->backup_directory); + return; + } + + /* Second pass: Perform the final verification of the tar contents. */ + for (cell = tarfiles.head; cell != NULL; cell = cell->next) + { + tar_file *tar = (tar_file *) cell->ptr; + astreamer *streamer; + char *fullpath; + + /* + * Prepares the archive streamer stack according to the tar + * compression format. + */ + streamer = create_archive_verifier(context, + tar->relpath, + tar->tblspc_oid, + tar->compress_algorithm); + + /* Compute the full pathname to the target file. */ + fullpath = psprintf("%s/%s", context->backup_directory, + tar->relpath); + + /* Invoke the streamer for reading, decompressing, and verifying. */ + verify_tar_file(context, tar->relpath, fullpath, streamer); + + /* Cleanup. */ + pfree(tar->relpath); + pfree(tar); + pfree(fullpath); + + astreamer_finalize(streamer); + astreamer_free(streamer); + } + simple_ptr_list_destroy(&tarfiles); + + progress_report(true); +} + +/* + * Preparatory steps for verifying files in tar format backups. + * + * Carries out basic validation of the tar format backup file, detects the + * compression type, and appends that information to the tarfiles list. An + * error will be reported if the tar file is inaccessible, or if the file type, + * name, or compression type is not as expected. + * + * The arguments to this function are mostly the same as the + * verify_plain_backup_file. The additional argument outputs a list of valid + * tar files. + */ +static void +precheck_tar_backup_file(verifier_context *context, char *relpath, + char *fullpath, SimplePtrList *tarfiles) +{ + struct stat sb; + Oid tblspc_oid = InvalidOid; + pg_compress_algorithm compress_algorithm; + tar_file *tar; + char *suffix = NULL; + + /* Should be tar format backup */ + Assert(context->format == 't'); + + /* Get file information */ + if (stat(fullpath, &sb) != 0) + { + report_backup_error(context, + "could not stat file or directory \"%s\": %m", + relpath); + return; + } + + /* In a tar format backup, we expect only regular files. */ + if (!S_ISREG(sb.st_mode)) + { + report_backup_error(context, + "file \"%s\" is not a regular file", + relpath); + return; + } + + /* + * We expect tar files for backing up the main directory, tablespace, and + * pg_wal directory. + * + * pg_basebackup writes the main data directory to an archive file named + * base.tar, the pg_wal directory to pg_wal.tar, and the tablespace + * directory to .tar, each followed by a compression type + * extension such as .gz, .lz4, or .zst. + */ + if (strncmp("base", relpath, 4) == 0) + suffix = relpath + 4; + else if (strncmp("pg_wal", relpath, 6) == 0) + suffix = relpath + 6; + else + { + /* Expected a .tar file here. */ + uint64 num = strtoul(relpath, &suffix, 10); + + /* + * Report an error if we didn't consume at least one character, if the + * result is 0, or if the value is too large to be a valid OID. + */ + if (suffix == NULL || num <= 0 || num > OID_MAX) + { + report_backup_error(context, + "file \"%s\" is not expected in a tar format backup", + relpath); + return; + } + tblspc_oid = (Oid) num; + } + + /* Now, check the compression type of the tar */ + if (strcmp(suffix, ".tar") == 0) + compress_algorithm = PG_COMPRESSION_NONE; + else if (strcmp(suffix, ".tgz") == 0) + compress_algorithm = PG_COMPRESSION_GZIP; + else if (strcmp(suffix, ".tar.gz") == 0) + compress_algorithm = PG_COMPRESSION_GZIP; + else if (strcmp(suffix, ".tar.lz4") == 0) + compress_algorithm = PG_COMPRESSION_LZ4; + else if (strcmp(suffix, ".tar.zst") == 0) + compress_algorithm = PG_COMPRESSION_ZSTD; + else + { + report_backup_error(context, + "file \"%s\" is not expected in a tar format backup", + relpath); + return; + } + + /* + * Ignore WALs, as reading and verification will be handled through + * pg_waldump. + */ + if (strncmp("pg_wal", relpath, 6) == 0) + return; + + /* + * Append the information to the list for complete verification at a later + * stage. + */ + tar = pg_malloc(sizeof(tar_file)); + tar->relpath = pstrdup(relpath); + tar->tblspc_oid = tblspc_oid; + tar->compress_algorithm = compress_algorithm; + + simple_ptr_list_append(tarfiles, tar); + + /* Update statistics for progress report, if necessary */ + if (show_progress) + total_size += sb.st_size; +} + +/* + * Verification of a single tar file content. + * + * It reads a given tar archive in predefined chunks and passes it to the + * streamer, which initiates routines for decompression (if necessary) and then + * verifies each member within the tar file. + */ +static void +verify_tar_file(verifier_context *context, char *relpath, char *fullpath, + astreamer *streamer) +{ + int fd; + int rc; + char *buffer; + + pg_log_debug("reading \"%s\"", fullpath); + + /* Open the target file. */ + if ((fd = open(fullpath, O_RDONLY | PG_BINARY, 0)) < 0) + { + report_backup_error(context, "could not open file \"%s\": %m", + relpath); + return; + } + + buffer = pg_malloc(READ_CHUNK_SIZE * sizeof(uint8)); + + /* Perform the reads */ + while ((rc = read(fd, buffer, READ_CHUNK_SIZE)) > 0) + { + astreamer_content(streamer, NULL, buffer, rc, ASTREAMER_UNKNOWN); + + /* Report progress */ + done_size += rc; + progress_report(false); + } + + pg_free(buffer); + + if (rc < 0) + report_backup_error(context, "could not read file \"%s\": %m", + relpath); + + /* Close the file. */ + if (close(fd) != 0) + report_backup_error(context, "could not close file \"%s\": %m", + relpath); +} + /* * Scan the hash table for entries where the 'matched' flag is not set; report * that such files are present in the manifest but not on disk. @@ -855,7 +1103,7 @@ verify_file_checksum(verifier_context *context, manifest_file *m, const char *relpath = m->pathname; int fd; int rc; - size_t bytes_read = 0; + uint64 bytes_read = 0; uint8 checksumbuf[PG_CHECKSUM_MAX_LENGTH]; int checksumlen; @@ -910,15 +1158,15 @@ verify_file_checksum(verifier_context *context, manifest_file *m, /* * Double-check that we read the expected number of bytes from the file. - * Normally, a file size mismatch would be caught in verify_backup_file - * and this check would never be reached, but this provides additional - * safety and clarity in the event of concurrent modifications or - * filesystem misbehavior. + * Normally, mismatches would be caught in verify_plain_backup_file and + * this check would never be reached, but this provides additional safety + * and clarity in the event of concurrent modifications or filesystem + * misbehavior. */ if (bytes_read != m->size) { report_backup_error(context, - "file \"%s\" should contain %zu bytes, but read %zu bytes", + "file \"%s\" should contain %" PRIu64 " bytes, but read %" PRIu64, relpath, m->size, bytes_read); return; } @@ -979,7 +1227,7 @@ parse_required_wal(verifier_context *context, char *pg_waldump_path, * Update the context to indicate that we saw an error, and exit if the * context says we should. */ -static void +void report_backup_error(verifier_context *context, const char *pg_restrict fmt,...) { va_list ap; @@ -996,7 +1244,7 @@ report_backup_error(verifier_context *context, const char *pg_restrict fmt,...) /* * Report a fatal error and exit */ -static void +void report_fatal_error(const char *pg_restrict fmt,...) { va_list ap; @@ -1015,7 +1263,7 @@ report_fatal_error(const char *pg_restrict fmt,...) * Note that by "prefix" we mean a parent directory; for this purpose, * "aa/bb" is not a prefix of "aa/bbb", but it is a prefix of "aa/bb/cc". */ -static bool +bool should_ignore_relpath(verifier_context *context, const char *relpath) { SimpleStringListCell *cell; @@ -1035,6 +1283,37 @@ should_ignore_relpath(verifier_context *context, const char *relpath) return false; } +/* + * Create a chain of archive streamers appropriate for verifying a given + * archive. + */ +static astreamer * +create_archive_verifier(verifier_context *context, char *archive_name, + Oid tblspc_oid, pg_compress_algorithm compress_algo) +{ + astreamer *streamer = NULL; + + /* Should be here only for tar backup */ + Assert(context->format == 't'); + + /* Last step is the actual verification. */ + streamer = astreamer_verify_content_new(streamer, context, archive_name, + tblspc_oid); + + /* Before that we must parse the tar file. */ + streamer = astreamer_tar_parser_new(streamer); + + /* Before that we must decompress, if archive is compressed. */ + if (compress_algo == PG_COMPRESSION_GZIP) + streamer = astreamer_gzip_decompressor_new(streamer); + else if (compress_algo == PG_COMPRESSION_LZ4) + streamer = astreamer_lz4_decompressor_new(streamer); + else if (compress_algo == PG_COMPRESSION_ZSTD) + streamer = astreamer_zstd_decompressor_new(streamer); + + return streamer; +} + /* * Print a progress report based on the global variables. * @@ -1090,6 +1369,7 @@ usage(void) printf(_("Usage:\n %s [OPTION]... BACKUPDIR\n\n"), progname); printf(_("Options:\n")); printf(_(" -e, --exit-on-error exit immediately on error\n")); + printf(_(" -F, --format=p|t backup format (plain, tar)\n")); printf(_(" -i, --ignore=RELATIVE_PATH ignore indicated path\n")); printf(_(" -m, --manifest-path=PATH use specified path for manifest\n")); printf(_(" -n, --no-parse-wal do not try to parse WAL files\n")); diff --git a/src/bin/pg_verifybackup/pg_verifybackup.h b/src/bin/pg_verifybackup/pg_verifybackup.h new file mode 100644 index 0000000000000..8cb6f9c53ad85 --- /dev/null +++ b/src/bin/pg_verifybackup/pg_verifybackup.h @@ -0,0 +1,111 @@ +/*------------------------------------------------------------------------- + * + * pg_verifybackup.h + * Verify a backup against a backup manifest. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_verifybackup/pg_verifybackup.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_VERIFYBACKUP_H +#define PG_VERIFYBACKUP_H + +#include "common/controldata_utils.h" +#include "common/hashfn_unstable.h" +#include "common/logging.h" +#include "common/parse_manifest.h" +#include "fe_utils/astreamer.h" +#include "fe_utils/simple_list.h" + +/* + * Each file described by the manifest file is parsed to produce an object + * like this. + */ +typedef struct manifest_file +{ + uint32 status; /* hash status */ + const char *pathname; + uint64 size; + pg_checksum_type checksum_type; + int checksum_length; + uint8 *checksum_payload; + bool matched; + bool bad; +} manifest_file; + +#define should_verify_checksum(m) \ + (((m)->matched) && !((m)->bad) && (((m)->checksum_type) != CHECKSUM_TYPE_NONE)) + +/* + * Define a hash table which we can use to store information about the files + * mentioned in the backup manifest. + */ +#define SH_PREFIX manifest_files +#define SH_ELEMENT_TYPE manifest_file +#define SH_KEY_TYPE const char * +#define SH_KEY pathname +#define SH_HASH_KEY(tb, key) hash_string(key) +#define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0) +#define SH_SCOPE static inline +#define SH_RAW_ALLOCATOR pg_malloc0 +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" + +/* + * Each WAL range described by the manifest file is parsed to produce an + * object like this. + */ +typedef struct manifest_wal_range +{ + TimeLineID tli; + XLogRecPtr start_lsn; + XLogRecPtr end_lsn; + struct manifest_wal_range *next; + struct manifest_wal_range *prev; +} manifest_wal_range; + +/* + * All the data parsed from a backup_manifest file. + */ +typedef struct manifest_data +{ + int version; + uint64 system_identifier; + manifest_files_hash *files; + manifest_wal_range *first_wal_range; + manifest_wal_range *last_wal_range; +} manifest_data; + +/* + * All of the context information we need while checking a backup manifest. + */ +typedef struct verifier_context +{ + manifest_data *manifest; + char *backup_directory; + SimpleStringList ignore_list; + char format; /* backup format: p(lain)/t(ar) */ + bool skip_checksums; + bool exit_on_error; + bool saw_any_error; +} verifier_context; + +extern void report_backup_error(verifier_context *context, + const char *pg_restrict fmt,...) + pg_attribute_printf(2, 3); +pg_noreturn extern void report_fatal_error(const char *pg_restrict fmt,...) + pg_attribute_printf(1, 2); +extern bool should_ignore_relpath(verifier_context *context, + const char *relpath); + +extern astreamer *astreamer_verify_content_new(astreamer *next, + verifier_context *context, + char *archive_name, + Oid tblspc_oid); + +#endif /* PG_VERIFYBACKUP_H */ diff --git a/src/bin/pg_verifybackup/po/de.po b/src/bin/pg_verifybackup/po/de.po index 7cc195ecc94a5..a9e24931100c0 100644 --- a/src/bin/pg_verifybackup/po/de.po +++ b/src/bin/pg_verifybackup/po/de.po @@ -1,13 +1,13 @@ # German message translation file for pg_verifybackup -# Copyright (C) 2020-2024 PostgreSQL Global Development Group +# Copyright (C) 2020-2025 PostgreSQL Global Development Group # This file is distributed under the same license as the pg_verifybackup (PostgreSQL) package. # msgid "" msgstr "" -"Project-Id-Version: pg_verifybackup (PostgreSQL) 17\n" +"Project-Id-Version: pg_verifybackup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 07:48+0000\n" -"PO-Revision-Date: 2024-05-24 15:40+0200\n" +"POT-Creation-Date: 2025-04-29 14:48+0000\n" +"PO-Revision-Date: 2025-04-29 18:57+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -15,22 +15,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -40,8 +40,8 @@ msgstr "Tipp: " msgid "could not open file \"%s\" for reading: %m" msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m" -#: ../../common/controldata_utils.c:110 pg_verifybackup.c:438 -#: pg_verifybackup.c:476 pg_verifybackup.c:896 +#: ../../common/controldata_utils.c:110 pg_verifybackup.c:440 +#: pg_verifybackup.c:478 pg_verifybackup.c:1025 pg_verifybackup.c:1144 #, c-format msgid "could not read file \"%s\": %m" msgstr "konnte Datei »%s« nicht lesen: %m" @@ -52,7 +52,7 @@ msgid "could not read file \"%s\": read %d of %zu" msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen" #: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 -#: pg_verifybackup.c:902 +#: pg_verifybackup.c:1030 pg_verifybackup.c:1150 #, c-format msgid "could not close file \"%s\": %m" msgstr "konnte Datei »%s« nicht schließen: %m" @@ -75,8 +75,8 @@ msgstr "" "diesem Fall wären die Ergebnisse unten falsch und die PostgreSQL-Installation\n" "wäre inkompatibel mit diesem Datenverzeichnis." -#: ../../common/controldata_utils.c:230 pg_verifybackup.c:406 -#: pg_verifybackup.c:865 +#: ../../common/controldata_utils.c:230 pg_verifybackup.c:408 +#: pg_verifybackup.c:1005 pg_verifybackup.c:1113 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" @@ -92,7 +92,8 @@ msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" #: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" @@ -121,405 +122,603 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/jsonapi.c:2121 +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "Parser mit rekursivem Abstieg kann inkrementellen Lexer nicht benutzen." -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "Inkrementeller Parser benötigt inkrementellen Lexer." -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSON zu tief geschachtelt, maximale erlaubte Tiefe ist 6400." -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "Escape-Sequenz »\\%.*s« ist nicht gültig." -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "Zeichen mit Wert 0x%02x muss escapt werden." -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "Ende der Eingabe erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "Array-Element oder »]« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "»,« oder »]« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "»:« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "JSON-Wert erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "Die Eingabezeichenkette endete unerwartet." -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "Zeichenkette oder »}« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "»,« oder »}« erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "Zeichenkette erwartet, aber »%.*s« gefunden." -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "Token »%.*s« ist ungültig." -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 kann nicht in »text« umgewandelt werden." -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "Nach »\\u« müssen vier Hexadezimalziffern folgen." -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "Unicode-Escape-Werte können nicht für Code-Punkt-Werte über 007F verwendet werden, wenn die Kodierung nicht UTF8 ist." -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Unicode-Escape-Wert konnte nicht in die Serverkodierung %s umgewandelt werden." -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicode-High-Surrogate darf nicht auf ein High-Surrogate folgen." -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicode-Low-Surrogate muss auf ein High-Surrogate folgen." -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "Speicher aufgebraucht beim Konstruieren der Fehlerbeschreibung" + +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht initialisieren" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "Manifest endete unerwartet" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht aktualisieren" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "unerwarteter Objektstart" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "unerwartetes Objektende" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "unerwarteter Array-Start" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "unerwartetes Array-Ende" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "unerwartete Versionskennzeichnung" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "unbekanntes Feld auf oberster Ebene" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "unerwartetes Feld für Datei" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "unerwartetes Feld für WAL-Bereich" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "unbekanntes Feld für Objekt" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "unerwarteter Skalar" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "Manifestversion ist keine ganze Zahl" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "unerwartete Manifestversion" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" msgstr "Systemidentifikator im Manifest ist keine ganze Zahl" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "fehlender Pfadname" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "sowohl Pfadname als auch kodierter Pfadname angegeben" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "Größenangabe fehlt" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "Prüfsumme ohne Algorithmus" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "konnte Dateinamen nicht dekodieren" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "Dateigröße ist keine ganze Zahl" -#: ../../common/parse_manifest.c:700 +#: ../../common/parse_manifest.c:699 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "unbekannter Prüfsummenalgorithmus: »%s«" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "ungültige Prüfsumme für Datei »%s«: »%s«" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "Zeitleiste fehlt" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "Start-LSN fehlt" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "End-LSN fehlt" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "Zeitleiste ist keine ganze Zahl" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "konnte Start-LSN nicht parsen" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "konnte End-LSN nicht parsen" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "mindestens 2 Zeilen erwartet" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "letzte Zeile nicht durch Newline abgeschlossen" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "konnte Prüfsumme des Manifests nicht abschließen" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "Manifest hat keine Prüfsumme" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "ungültige Manifestprüfsumme: »%s«" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "Manifestprüfsumme stimmt nicht überein" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "konnte Backup-Manifest nicht parsen: %s" -#: pg_verifybackup.c:277 pg_verifybackup.c:286 pg_verifybackup.c:297 +#: ../../fe_utils/astreamer_gzip.c:115 +#, c-format +msgid "could not create compressed file \"%s\": %m" +msgstr "konnte komprimierte Datei »%s« nicht erzeugen: %m" + +#: ../../fe_utils/astreamer_gzip.c:127 +#, c-format +msgid "could not duplicate stdout: %m" +msgstr "konnte Standardausgabe nicht duplizieren: %m" + +#: ../../fe_utils/astreamer_gzip.c:131 +#, c-format +msgid "could not open output file: %m" +msgstr "konnte Ausgabedatei nicht öffnen: %m" + +#: ../../fe_utils/astreamer_gzip.c:135 +#, c-format +msgid "could not set compression level %d: %s" +msgstr "konnte Komprimierungsniveau %d nicht setzen: %s" + +#: ../../fe_utils/astreamer_gzip.c:140 ../../fe_utils/astreamer_gzip.c:273 +#: ../../fe_utils/astreamer_lz4.c:102 ../../fe_utils/astreamer_lz4.c:300 +#: ../../fe_utils/astreamer_zstd.c:133 ../../fe_utils/astreamer_zstd.c:288 +#, c-format +msgid "this build does not support compression with %s" +msgstr "diese Installation unterstützt keine Komprimierung mit %s" + +#: ../../fe_utils/astreamer_gzip.c:167 +#, c-format +msgid "could not write to compressed file \"%s\": %s" +msgstr "konnte nicht in komprimierte Datei »%s« schreiben: %s" + +#: ../../fe_utils/astreamer_gzip.c:191 +#, c-format +msgid "could not close compressed file \"%s\": %m" +msgstr "konnte komprimierte Datei »%s« nicht schließen: %m" + +#: ../../fe_utils/astreamer_gzip.c:269 +#, c-format +msgid "could not initialize compression library" +msgstr "konnte Komprimierungsbibliothek nicht initialisieren" + +#: ../../fe_utils/astreamer_gzip.c:320 ../../fe_utils/astreamer_lz4.c:356 +#: ../../fe_utils/astreamer_zstd.c:333 +#, c-format +msgid "could not decompress data: %s" +msgstr "konnte Daten nicht dekomprimieren: %s" + +#: ../../fe_utils/astreamer_lz4.c:97 +#, c-format +msgid "could not create lz4 compression context: %s" +msgstr "konnte lz4-Komprimierungskontext nicht erzeugen: %s" + +#: ../../fe_utils/astreamer_lz4.c:142 +#, c-format +msgid "could not write lz4 header: %s" +msgstr "konnte lz4-Header nicht schreiben: %s" + +#: ../../fe_utils/astreamer_lz4.c:191 ../../fe_utils/astreamer_zstd.c:185 +#: ../../fe_utils/astreamer_zstd.c:227 +#, c-format +msgid "could not compress data: %s" +msgstr "konnte Daten nicht komprimieren: %s" + +#: ../../fe_utils/astreamer_lz4.c:243 +#, c-format +msgid "could not end lz4 compression: %s" +msgstr "konnte lz4-Komprimierung nicht beenden: %s" + +#: ../../fe_utils/astreamer_lz4.c:295 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "konnte Komprimierungsbibliothek nicht initialisieren: %s" + +#: ../../fe_utils/astreamer_tar.c:244 +#, c-format +msgid "tar file trailer exceeds 2 blocks" +msgstr "Tar-Datei-Trailer überschreitet 2 Blöcke" + +#: ../../fe_utils/astreamer_tar.c:249 astreamer_verify.c:130 +#, c-format +msgid "unexpected state while parsing tar archive" +msgstr "unerwarteter Zustand beim Parsen des Tar-Archivs" + +#: ../../fe_utils/astreamer_tar.c:292 +#, c-format +msgid "tar member has empty name" +msgstr "Tar-Mitglied hat leeren Namen" + +#: ../../fe_utils/astreamer_tar.c:326 +#, c-format +msgid "COPY stream ended before last file was finished" +msgstr "COPY-Strom endete vor dem Ende der letzten Datei" + +#: ../../fe_utils/astreamer_zstd.c:89 +#, c-format +msgid "could not create zstd compression context" +msgstr "konnte zstd-Komprimierungskontext nicht erzeugen" + +#: ../../fe_utils/astreamer_zstd.c:95 +#, c-format +msgid "could not set zstd compression level to %d: %s" +msgstr "konnte zstd-Komprimierungsniveau nicht auf %d setzen: %s" + +#: ../../fe_utils/astreamer_zstd.c:109 +#, c-format +msgid "could not set compression worker count to %d: %s" +msgstr "konnte Komprimierungs-Worker-Anzahl nicht auf %d setzen: %s" + +#: ../../fe_utils/astreamer_zstd.c:120 +#, c-format +msgid "could not enable long-distance mode: %s" +msgstr "konnte Long-Distance-Modus nicht einschalten: %s" + +#: ../../fe_utils/astreamer_zstd.c:279 +#, c-format +msgid "could not create zstd decompression context" +msgstr "konnte zstd-Dekomprimierungskontext nicht erzeugen" + +#: astreamer_verify.c:198 +#, c-format +msgid "file \"%s\" is present in archive \"%s\" but not in the manifest" +msgstr "Datei »%s« ist im Archiv »%s« vorhanden, aber nicht im Manifest" + +#: astreamer_verify.c:211 +#, c-format +msgid "file \"%s\" has size %llu in archive \"%s\" but size % in the manifest" +msgstr "Datei »%s« hat Größe %llu im Archiv »%s« aber Größe % im Manifest" + +#: astreamer_verify.c:236 +#, c-format +msgid "%s: could not initialize checksum of file \"%s\"" +msgstr "%s: konnte Prüfsumme der Datei »%s« nicht initialisieren" + +#: astreamer_verify.c:274 pg_verifybackup.c:1133 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "konnte Prüfsumme der Datei »%s« nicht aktualisieren" + +#: astreamer_verify.c:300 +#, c-format +msgid "file \"%s\" in archive \"%s\" should contain % bytes, but % bytes were read" +msgstr "Datei »%s« in Archiv »%s« sollte % Bytes enthalten, aber % Bytes wurden gelesen" + +#: astreamer_verify.c:312 pg_verifybackup.c:1179 +#, c-format +msgid "could not finalize checksum of file \"%s\"" +msgstr "konnte Prüfsumme der Datei »%s« nicht abschließen" + +#: astreamer_verify.c:320 +#, c-format +msgid "file \"%s\" in archive \"%s\" has checksum of length %d, but expected %d" +msgstr "Datei »%s« in Archiv »%s« hat Prüfsumme mit Länge %d, aber %d wurde erwartet" + +#: astreamer_verify.c:325 +#, c-format +msgid "checksum mismatch for file \"%s\" in archive \"%s\"" +msgstr "Prüfsumme stimmt nicht überein für Datei »%s« in Archiv »%s«" + +#: astreamer_verify.c:387 +#, c-format +msgid "unexpected control file size %d, expected %d" +msgstr "unerwartete Kontrolldateigröße %d, erwartet wurde %d" + +#: astreamer_verify.c:399 +#, c-format +msgid "%s: %s: CRC is incorrect" +msgstr "%s: %s: CRC ist falsch" + +#: astreamer_verify.c:405 +#, c-format +msgid "%s: %s: unexpected control file version" +msgstr "%s: %s: unerwartete Kontrolldateiversion" + +#: astreamer_verify.c:412 +#, c-format +msgid "%s: %s: manifest system identifier is %, but control file has %" +msgstr "%s: %s: Systemidentifikator im Manifest ist %, aber Kontrolldatei hat %" + +#: pg_verifybackup.c:208 +#, c-format +msgid "invalid backup format \"%s\", must be \"plain\" or \"tar\"" +msgstr "ungültiges Backup-Format »%s«, muss »plain« oder »tar« sein" + +#: pg_verifybackup.c:229 pg_verifybackup.c:238 pg_verifybackup.c:249 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: pg_verifybackup.c:285 +#: pg_verifybackup.c:237 #, c-format msgid "no backup directory specified" msgstr "kein Backup-Verzeichnis angegeben" -#: pg_verifybackup.c:295 +#: pg_verifybackup.c:247 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: pg_verifybackup.c:303 +#: pg_verifybackup.c:255 #, c-format msgid "cannot specify both %s and %s" msgstr "%s und %s können nicht beide angegeben werden" -#: pg_verifybackup.c:323 +#: pg_verifybackup.c:275 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "Programm »%s« wird von %s benötigt, aber wurde nicht im selben Verzeichnis wie »%s« gefunden" -#: pg_verifybackup.c:326 +#: pg_verifybackup.c:278 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "Programm »%s« wurde von »%s« gefunden, aber es hatte nicht die gleiche Version wie %s" -#: pg_verifybackup.c:381 +#: pg_verifybackup.c:304 pg_verifybackup.c:625 #, c-format -msgid "backup successfully verified\n" -msgstr "Backup erfolgreich überprüft\n" +msgid "could not open directory \"%s\": %m" +msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: pg_verifybackup.c:410 +#: pg_verifybackup.c:323 pg_verifybackup.c:412 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: pg_verifybackup.c:440 +#: pg_verifybackup.c:340 +#, c-format +msgid "pg_waldump cannot read tar files" +msgstr "pg_waldump kann keine Tar-Dateien lesen" + +#: pg_verifybackup.c:341 +#, c-format +msgid "You must use -n/--no-parse-wal when verifying a tar-format backup." +msgstr "Sie müssen -n/--no-parse-wal verwenden, wenn ein Backup im Tar-Format überprüft wird." + +#: pg_verifybackup.c:383 +#, c-format +msgid "backup successfully verified\n" +msgstr "Backup erfolgreich überprüft\n" + +#: pg_verifybackup.c:442 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "konnte Datei »%s« nicht lesen: %d von %lld gelesen" -#: pg_verifybackup.c:478 +#: pg_verifybackup.c:480 #, c-format msgid "could not read file \"%s\": read %lld of %lld" msgstr "konnte Datei »%s« nicht lesen: %lld von %lld gelesen" -#: pg_verifybackup.c:561 +#: pg_verifybackup.c:563 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "doppelter Pfadname im Backup-Manifest: »%s«" -#: pg_verifybackup.c:624 pg_verifybackup.c:631 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" - -#: pg_verifybackup.c:663 +#: pg_verifybackup.c:657 pg_verifybackup.c:827 #, c-format msgid "could not close directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht schließen: %m" -#: pg_verifybackup.c:683 +#: pg_verifybackup.c:678 pg_verifybackup.c:897 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "konnte »stat« für Datei oder Verzeichnis »%s« nicht ausführen: %m" -#: pg_verifybackup.c:706 +#: pg_verifybackup.c:701 #, c-format -msgid "\"%s\" is not a file or directory" -msgstr "»%s« ist keine Datei und kein Verzeichnis" +msgid "\"%s\" is not a regular file or directory" +msgstr "»%s« ist keine normale Datei und kein Verzeichnis" -#: pg_verifybackup.c:716 +#: pg_verifybackup.c:711 #, c-format msgid "\"%s\" is present on disk but not in the manifest" msgstr "»%s« ist auf der Festplatte vorhanden, aber nicht im Manifest" -#: pg_verifybackup.c:728 +#: pg_verifybackup.c:723 #, c-format -msgid "\"%s\" has size %lld on disk but size %zu in the manifest" -msgstr "»%s« hat Größe %lld auf Festplatte aber Größe %zu im Manifest" +msgid "\"%s\" has size %llu on disk but size %llu in the manifest" +msgstr "»%s« hat Größe %llu auf Festplatte aber Größe %llu im Manifest" -#: pg_verifybackup.c:768 +#: pg_verifybackup.c:765 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRC ist falsch" -#: pg_verifybackup.c:772 +#: pg_verifybackup.c:769 #, c-format msgid "%s: unexpected control file version" msgstr "%s: unerwartete Kontrolldateiversion" -#: pg_verifybackup.c:777 +#: pg_verifybackup.c:774 #, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: Systemidentifikator im Manifest ist %llu, aber Kontrolldatei hat %llu" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: Systemidentifikator im Manifest ist %, aber Kontrolldatei hat %" -#: pg_verifybackup.c:801 +#: pg_verifybackup.c:906 #, c-format -msgid "\"%s\" is present in the manifest but not on disk" -msgstr "»%s« steht im Manifest, ist aber nicht auf der Festplatte vorhanden" +msgid "file \"%s\" is not a regular file" +msgstr "Datei »%s« ist keine normale Datei" -#: pg_verifybackup.c:873 +#: pg_verifybackup.c:936 pg_verifybackup.c:957 #, c-format -msgid "could not initialize checksum of file \"%s\"" -msgstr "konnte Prüfsumme der Datei »%s« nicht initialisieren" +msgid "file \"%s\" is not expected in a tar format backup" +msgstr "Datei »%s« wird in einem Backup im Tar-Format nicht erwartet" -#: pg_verifybackup.c:885 +#: pg_verifybackup.c:1049 #, c-format -msgid "could not update checksum of file \"%s\"" -msgstr "konnte Prüfsumme der Datei »%s« nicht aktualisieren" +msgid "\"%s\" is present in the manifest but not on disk" +msgstr "»%s« steht im Manifest, ist aber nicht auf der Festplatte vorhanden" -#: pg_verifybackup.c:921 +#: pg_verifybackup.c:1121 #, c-format -msgid "file \"%s\" should contain %zu bytes, but read %zu bytes" -msgstr "Datei »%s« sollte %zu Bytes enthalten, aber %zu Bytes wurden gelesen" +msgid "could not initialize checksum of file \"%s\"" +msgstr "konnte Prüfsumme der Datei »%s« nicht initialisieren" -#: pg_verifybackup.c:931 +#: pg_verifybackup.c:1169 #, c-format -msgid "could not finalize checksum of file \"%s\"" -msgstr "konnte Prüfsumme der Datei »%s« nicht abschließen" +msgid "file \"%s\" should contain % bytes, but read %" +msgstr "Datei »%s« sollte % Bytes enthalten, aber % Bytes wurden gelesen" -#: pg_verifybackup.c:939 +#: pg_verifybackup.c:1187 #, c-format msgid "file \"%s\" has checksum of length %d, but expected %d" msgstr "Datei »%s« hat Prüfsumme mit Länge %d, aber %d wurde erwartet" -#: pg_verifybackup.c:943 +#: pg_verifybackup.c:1191 #, c-format msgid "checksum mismatch for file \"%s\"" msgstr "Prüfsumme stimmt nicht überein für Datei »%s«" -#: pg_verifybackup.c:969 +#: pg_verifybackup.c:1217 #, c-format msgid "WAL parsing failed for timeline %u" msgstr "Parsen des WAL fehlgeschlagen für Zeitleiste %u" -#: pg_verifybackup.c:1072 +#: pg_verifybackup.c:1351 #, c-format msgid "%*s/%s kB (%d%%) verified" msgstr "%*s/%s kB (%d%%) überprüft" -#: pg_verifybackup.c:1089 +#: pg_verifybackup.c:1368 #, c-format msgid "" "%s verifies a backup against the backup manifest.\n" @@ -528,7 +727,7 @@ msgstr "" "%s überprüft ein Backup anhand eines Backup-Manifests.\n" "\n" -#: pg_verifybackup.c:1090 +#: pg_verifybackup.c:1369 #, c-format msgid "" "Usage:\n" @@ -539,62 +738,67 @@ msgstr "" " %s [OPTION]... BACKUPVERZ\n" "\n" -#: pg_verifybackup.c:1091 +#: pg_verifybackup.c:1370 #, c-format msgid "Options:\n" msgstr "Optionen:\n" -#: pg_verifybackup.c:1092 +#: pg_verifybackup.c:1371 #, c-format msgid " -e, --exit-on-error exit immediately on error\n" msgstr " -e, --exit-on-error bei Fehler sofort beenden\n" -#: pg_verifybackup.c:1093 +#: pg_verifybackup.c:1372 +#, c-format +msgid " -F, --format=p|t backup format (plain, tar)\n" +msgstr " -F, --format=p|t Backup-Format (plain, tar)\n" + +#: pg_verifybackup.c:1373 #, c-format msgid " -i, --ignore=RELATIVE_PATH ignore indicated path\n" msgstr " -i, --ignore=REL-PFAD angegebenen Pfad ignorieren\n" -#: pg_verifybackup.c:1094 +#: pg_verifybackup.c:1374 #, c-format msgid " -m, --manifest-path=PATH use specified path for manifest\n" msgstr " -m, --manifest-path=PFAD angegebenen Pfad für Manifest verwenden\n" -#: pg_verifybackup.c:1095 +#: pg_verifybackup.c:1375 #, c-format msgid " -n, --no-parse-wal do not try to parse WAL files\n" msgstr " -n, --no-parse-wal nicht versuchen WAL-Dateien zu parsen\n" -#: pg_verifybackup.c:1096 +#: pg_verifybackup.c:1376 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress Fortschrittsinformationen zeigen\n" -#: pg_verifybackup.c:1097 +#: pg_verifybackup.c:1377 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet keine Ausgabe, außer Fehler\n" -#: pg_verifybackup.c:1098 +#: pg_verifybackup.c:1378 #, c-format msgid " -s, --skip-checksums skip checksum verification\n" msgstr " -s, --skip-checksums Überprüfung der Prüfsummen überspringen\n" -#: pg_verifybackup.c:1099 +#: pg_verifybackup.c:1379 #, c-format msgid " -w, --wal-directory=PATH use specified path for WAL files\n" msgstr " -w, --wal-directory=PFAD angegebenen Pfad für WAL-Dateien verwenden\n" -#: pg_verifybackup.c:1100 +#: pg_verifybackup.c:1380 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: pg_verifybackup.c:1101 +#: pg_verifybackup.c:1381 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: pg_verifybackup.c:1102 +#: pg_verifybackup.c:1382 #, c-format msgid "" "\n" @@ -603,7 +807,7 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: pg_verifybackup.c:1103 +#: pg_verifybackup.c:1383 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" diff --git a/src/bin/pg_verifybackup/po/ja.po b/src/bin/pg_verifybackup/po/ja.po index 3466239c57da7..c910fb236cc6b 100644 --- a/src/bin/pg_verifybackup/po/ja.po +++ b/src/bin/pg_verifybackup/po/ja.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_verifybackup (PostgreSQL 17)\n" +"Project-Id-Version: pg_verifybackup (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-24 10:24+0900\n" -"PO-Revision-Date: 2024-05-24 10:47+0900\n" +"POT-Creation-Date: 2025-04-14 09:42+0900\n" +"PO-Revision-Date: 2025-04-14 10:32+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -17,26 +17,101 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ファイル\"%s\"を読み込み用にオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:110 pg_verifybackup.c:440 +#: pg_verifybackup.c:478 pg_verifybackup.c:1025 pg_verifybackup.c:1144 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ファイル\"%s\"の読み取りに失敗しました: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: pg_verifybackup.c:1030 pg_verifybackup.c:1150 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ファイル\"%s\"をクローズできませんでした: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "バイトオーダが合っていません" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"バイトオーダが異なる可能性があります。\n" +"pg_controlファイルを格納するために使用するバイトオーダが本プログラムで使用\n" +"されるものと一致しないようです。この場合以下の結果は不正確になります。また、\n" +"PostgreSQLインストレーションはこのデータディレクトリと互換性がなくなります。" + +#: ../../common/controldata_utils.c:230 pg_verifybackup.c:408 +#: pg_verifybackup.c:1005 pg_verifybackup.c:1113 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ファイル\"%s\"をオープンできませんでした: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ファイル\"%s\"を書き出せませんでした: %m" + +#: ../../common/controldata_utils.c:268 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ファイル\"%s\"をfsyncできませんでした: %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "メモリ不足です" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "成功" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "出力先バッファが小さすぎます" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "OpenSSLのエラー" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -48,425 +123,489 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null ポインタを複製できません (内部エラー)\n" -#: ../../common/jsonapi.c:2121 +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "再帰降下パーサーは差分字句解析器を使用できません。" -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "差分パーサーは差分字句解析器を必要とします。" -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSONのネストが深すぎます、可能な最大の深さは6400です。" -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "エスケープシーケンス\"\\%.*s\"は不正です。" -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "0x%02x値を持つ文字はエスケープしなければなりません" -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "入力の終端を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "配列要素または\"]\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "\",\"または\"]\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "\":\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "JSON値を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "入力文字列が予期せず終了しました。" -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "文字列または\"}\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "\",\"または\"}\"を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "文字列を想定していましたが、\"\\%.*s\"でした。" -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "トークン\"\\%.*s\"は不正です。" -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 はテキストに変換できません。" -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\"の後には16進数の4桁が続かなければなりません。" -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "エンコーディングがUTF-8ではない場合、コードポイントの値が 007F 以上についてはUnicodeエスケープの値は使用できません。" -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "Unicodeエスケープの値がサーバーエンコーディング%sに変換できませんでした。" -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "Unicodeのハイサロゲートはハイサロゲートに続いてはいけません。" -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "Unicodeのローサロゲートはハイサロゲートに続かなければなりません。" -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 -#, c-format -msgid "out of memory" -msgstr "メモリ不足です" +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "エラー記述の構築中にメモリ不足" -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "目録のチェックサムの初期化ができませんでした" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "目録が予期せず終了しました。" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "目録のチェックサムの更新ができませんでした" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "予期しないオブジェクトの開始" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "予期しないオブジェクトの終わり" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "予期しない配列の開始" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "予期しない配列の終わり" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "バージョン指示子を想定していました" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "認識できないトップレベルフィールド" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "予期しないファイルフィールド" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "予期しないWAL範囲フィールド" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "予期しないオブジェクトフィールド" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "予期しないスカラー" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "目録バージョンが整数ではありません" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "予期しない目録バージョン" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" -msgstr "目録のシステム識別子が整数ではありません" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "目録中のシステム識別子が整数ではありません" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "パス名がありません" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "パス名とエンコードされたパス名の両方" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "サイズがありません" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "アルゴリズムなしのチェックサム" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ファイル名をデコードできませんでした" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ファイルサイズが整数ではありません" -#: ../../common/parse_manifest.c:700 +#: ../../common/parse_manifest.c:699 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "認識できないチェックサムアルゴリズム: \"%s\"" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "\"%s\" ファイルのチェックサムが無効: \"%s\"" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "タイムラインがありません" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "開始LSNがありません" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "終了LSNがありません" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "タイムラインが整数ではありません" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "開始LSNをパースできませんでした" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "終了LSNをパースできませんでした" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "少なくとも2行が必要です" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "最後の行が改行で終わっていません" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "目録のチェックサムの完了ができませんでした" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "目録にチェックサムがありません" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "無効な目録チェックサム: \"%s\"" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "目録チェックサムの不一致" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "バックアップ目録をパースできませんでした: %s" -#: pg_verifybackup.c:277 pg_verifybackup.c:286 pg_verifybackup.c:297 +#: astreamer_verify.c:130 +#, c-format +msgid "unexpected state while parsing tar file" +msgstr "tarファイルのパース中に想定外の状態" + +#: astreamer_verify.c:198 +#, c-format +msgid "\"%s\" is present in \"%s\" but not in the manifest" +msgstr "\"%s\"は\"%s\"には存在しますが、目録には存在しません" + +#: astreamer_verify.c:211 +#, c-format +msgid "\"%s\" has size %llu in \"%s\" but size % in the manifest" +msgstr "\"%1$s\"は\"%3$s\"内でのサイズは%2$lluですが、目録上は%4$となっています" + +#: astreamer_verify.c:236 +#, c-format +msgid "%s: could not initialize checksum of file \"%s\"" +msgstr "%s: ファイル\"%s\"のチェックサムの初期化ができませんでした" + +#: astreamer_verify.c:274 pg_verifybackup.c:1133 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "ファイル\"%s\"のチェックサムの更新ができませんでした" + +#: astreamer_verify.c:300 +#, c-format +msgid "file \"%s\" in \"%s\" should contain % bytes, but read % bytes" +msgstr "ファイル\"%s\"は\"%s\"内では%バイトを含んでいるはずですが、%バイトしか読み込まれませんでした" + +#: astreamer_verify.c:312 pg_verifybackup.c:1179 +#, c-format +msgid "could not finalize checksum of file \"%s\"" +msgstr "ファイル\"%s\"のチェックサムの完了ができませんでした" + +#: astreamer_verify.c:320 +#, c-format +msgid "file \"%s\" in \"%s\" has checksum of length %d, but expected %d" +msgstr "ファイル\"%s\"の\"%s\"内でのチェックサムの長さは%dですが、期待している長さは%dです" + +#: astreamer_verify.c:325 +#, c-format +msgid "checksum mismatch for file \"%s\" in \"%s\"" +msgstr "\"%s\"内のファイル\"%s\"のチェックサムが一致しません" + +#: astreamer_verify.c:387 +#, c-format +msgid "unexpected control file size %d, expected %d" +msgstr "想定外の制御ファイルのサイズ%d、想定は%d" + +#: astreamer_verify.c:399 +#, c-format +msgid "%s: %s: CRC is incorrect" +msgstr "%s: %s: CRCが正しくありません" + +#: astreamer_verify.c:405 +#, c-format +msgid "%s: %s: unexpected control file version" +msgstr "%s: %s: 予期しない制御ファイルバージョン" + +#: astreamer_verify.c:412 +#, c-format +msgid "%s: %s: manifest system identifier is %, but control file has %" +msgstr "%s: %s: 目録のシステム識別子が%ですが、制御ファイルでは%です" + +#: pg_verifybackup.c:208 +#, c-format +msgid "invalid backup format \"%s\", must be \"plain\" or \"tar\"" +msgstr "不正なバックアップフォーマット\"%s\"、\"plain\"か\"tar\"でなければなりません" + +#: pg_verifybackup.c:229 pg_verifybackup.c:238 pg_verifybackup.c:249 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: pg_verifybackup.c:285 +#: pg_verifybackup.c:237 #, c-format msgid "no backup directory specified" msgstr "バックアップディレクトリが指定されていません" -#: pg_verifybackup.c:295 +#: pg_verifybackup.c:247 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: pg_verifybackup.c:303 +#: pg_verifybackup.c:255 #, c-format msgid "cannot specify both %s and %s" msgstr "%sと%sの両方を同時には指定できません" -#: pg_verifybackup.c:323 +#: pg_verifybackup.c:275 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "%2$sにはプログラム\"%1$s\"が必要ですが、\"%3$s\"と同じディレクトリにありませんでした" -#: pg_verifybackup.c:326 +#: pg_verifybackup.c:278 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じバージョンではありませんでした" -#: pg_verifybackup.c:381 +#: pg_verifybackup.c:304 pg_verifybackup.c:625 #, c-format -msgid "backup successfully verified\n" -msgstr "バックアップが正常に検証されました\n" - -#: pg_verifybackup.c:406 pg_verifybackup.c:865 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "ファイル\"%s\"をオープンできませんでした: %m" +msgid "could not open directory \"%s\": %m" +msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: pg_verifybackup.c:410 +#: pg_verifybackup.c:323 pg_verifybackup.c:412 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: pg_verifybackup.c:438 pg_verifybackup.c:476 pg_verifybackup.c:896 +#: pg_verifybackup.c:340 #, c-format -msgid "could not read file \"%s\": %m" -msgstr "ファイル\"%s\"の読み取りに失敗しました: %m" +msgid "pg_waldump cannot read tar files" +msgstr "pg_waldumpはtarファイルを読めません" + +#: pg_verifybackup.c:341 +#, c-format +msgid "You must use -n or --no-parse-wal when verifying a tar-format backup." +msgstr "tarフォーマットのバックアップを検証するときには -n または --no-parse-wal を使う必要があります。" -#: pg_verifybackup.c:440 +#: pg_verifybackup.c:383 +#, c-format +msgid "backup successfully verified\n" +msgstr "バックアップが正常に検証されました\n" + +#: pg_verifybackup.c:442 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイトのうち%2$dバイトを読み込みました" -#: pg_verifybackup.c:478 +#: pg_verifybackup.c:480 #, c-format msgid "could not read file \"%s\": read %lld of %lld" msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$lldバイトのうち%2$lldバイトを読み込みました" -#: pg_verifybackup.c:561 +#: pg_verifybackup.c:563 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "バックアップ目録内の重複パス名: \"%s\"" -#: pg_verifybackup.c:624 pg_verifybackup.c:631 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" - -#: pg_verifybackup.c:663 +#: pg_verifybackup.c:657 pg_verifybackup.c:827 #, c-format msgid "could not close directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m" -#: pg_verifybackup.c:683 +#: pg_verifybackup.c:678 pg_verifybackup.c:897 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "\"%s\"というファイルまたはディレクトリの情報を取得できませんでした: %m" -#: pg_verifybackup.c:706 +#: pg_verifybackup.c:701 #, c-format msgid "\"%s\" is not a file or directory" msgstr "\"%s\"はファイルまたはディレクトリではありません" -#: pg_verifybackup.c:716 +#: pg_verifybackup.c:711 #, c-format msgid "\"%s\" is present on disk but not in the manifest" msgstr "\"%s\"はディスクに存在しますが、目録には存在しません" -#: pg_verifybackup.c:728 +#: pg_verifybackup.c:723 #, c-format -msgid "\"%s\" has size %lld on disk but size %zu in the manifest" -msgstr "\"%s\"はディスク上でのサイズは%lldですが、目録上は%zuとなっています" +msgid "\"%s\" has size %llu on disk but size %llu in the manifest" +msgstr "\"%s\"はディスク上でのサイズは%lluですが、目録上は%lluとなっています" -#: pg_verifybackup.c:768 +#: pg_verifybackup.c:765 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRCが正しくありません" -#: pg_verifybackup.c:772 +#: pg_verifybackup.c:769 #, c-format msgid "%s: unexpected control file version" msgstr "%s: 予期しない制御ファイルバージョン" -#: pg_verifybackup.c:777 -#, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: 目録のシステム識別子が%lluですが、制御ファイルでは%lluです" - -#: pg_verifybackup.c:801 +#: pg_verifybackup.c:774 #, c-format -msgid "\"%s\" is present in the manifest but not on disk" -msgstr "\"%s\"は目録には存在しますが、ディスクには存在しません" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: 目録のシステム識別子が%ですが、制御ファイルでは%です" -#: pg_verifybackup.c:873 +#: pg_verifybackup.c:906 #, c-format -msgid "could not initialize checksum of file \"%s\"" -msgstr "ファイル\"%s\"のチェックサムの初期化ができませんでした" +msgid "\"%s\" is not a plain file" +msgstr "\"%s\"は通常ファイルではありません" -#: pg_verifybackup.c:885 +#: pg_verifybackup.c:936 pg_verifybackup.c:957 #, c-format -msgid "could not update checksum of file \"%s\"" -msgstr "ファイル\"%s\"のチェックサムの更新ができませんでした" +msgid "file \"%s\" is not expected in a tar format backup" +msgstr "tar形式のバックアップではファイル\"%s\"は想定外です" -#: pg_verifybackup.c:902 +#: pg_verifybackup.c:1049 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "ファイル\"%s\"をクローズできませんでした: %m" +msgid "\"%s\" is present in the manifest but not on disk" +msgstr "\"%s\"は目録には存在しますが、ディスクには存在しません" -#: pg_verifybackup.c:921 +#: pg_verifybackup.c:1121 #, c-format -msgid "file \"%s\" should contain %zu bytes, but read %zu bytes" -msgstr "file\"%s\"は%zuバイトを含む必要がありますが、%zuバイトが読み込まれました" +msgid "could not initialize checksum of file \"%s\"" +msgstr "ファイル\"%s\"のチェックサムの初期化ができませんでした" -#: pg_verifybackup.c:931 +#: pg_verifybackup.c:1169 #, c-format -msgid "could not finalize checksum of file \"%s\"" -msgstr "ファイル\"%s\"のチェックサムの完了ができませんでした" +msgid "file \"%s\" should contain % bytes, but read %" +msgstr "ファイル\"%s\"は%バイトを含んでいるはずですが、%バイトしか読み込まれませんでした" -#: pg_verifybackup.c:939 +#: pg_verifybackup.c:1187 #, c-format msgid "file \"%s\" has checksum of length %d, but expected %d" msgstr "ファイル\"%s\"のチェックサムの長さは%dですが、予期されるのは%dです" -#: pg_verifybackup.c:943 +#: pg_verifybackup.c:1191 #, c-format msgid "checksum mismatch for file \"%s\"" msgstr "ファイル\"%s\"のチェックサムが一致しません" -#: pg_verifybackup.c:969 +#: pg_verifybackup.c:1217 #, c-format msgid "WAL parsing failed for timeline %u" msgstr "タイムライン%uのWALのパースに失敗しました" -#: pg_verifybackup.c:1072 +#: pg_verifybackup.c:1351 #, c-format msgid "%*s/%s kB (%d%%) verified" msgstr "%*s/%s kB (%d%%) 検証しました" -#: pg_verifybackup.c:1089 +#: pg_verifybackup.c:1368 #, c-format msgid "" "%s verifies a backup against the backup manifest.\n" @@ -475,7 +614,7 @@ msgstr "" "%sはバックアップ目録に対してバックアップを検証します。\n" "\n" -#: pg_verifybackup.c:1090 +#: pg_verifybackup.c:1369 #, c-format msgid "" "Usage:\n" @@ -486,62 +625,67 @@ msgstr "" " %s [オプション]... BACKUPDIR\n" "\n" -#: pg_verifybackup.c:1091 +#: pg_verifybackup.c:1370 #, c-format msgid "Options:\n" msgstr "オプション:\n" -#: pg_verifybackup.c:1092 +#: pg_verifybackup.c:1371 #, c-format msgid " -e, --exit-on-error exit immediately on error\n" msgstr " -e, --exit-on-error エラー時に直ちに終了する\n" -#: pg_verifybackup.c:1093 +#: pg_verifybackup.c:1372 +#, c-format +msgid " -F, --format=p|t backup format (plain, tar)\n" +msgstr " -F, --format=p|t 出力フォーマット(plain, tar)\n" + +#: pg_verifybackup.c:1373 #, c-format msgid " -i, --ignore=RELATIVE_PATH ignore indicated path\n" msgstr " -i, --ignore=RELATIVE_PATH 指示されたパスを無視\n" -#: pg_verifybackup.c:1094 +#: pg_verifybackup.c:1374 #, c-format msgid " -m, --manifest-path=PATH use specified path for manifest\n" msgstr " -m, --manifest-path=PATH 目録として指定したパスを使用する\n" -#: pg_verifybackup.c:1095 +#: pg_verifybackup.c:1375 #, c-format msgid " -n, --no-parse-wal do not try to parse WAL files\n" msgstr " -n, --no-parse-wal WALファイルをパースしようとしない\n" -#: pg_verifybackup.c:1096 +#: pg_verifybackup.c:1376 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress 進行状況を表示\n" -#: pg_verifybackup.c:1097 +#: pg_verifybackup.c:1377 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet エラー以外何も出力しない\n" -#: pg_verifybackup.c:1098 +#: pg_verifybackup.c:1378 #, c-format msgid " -s, --skip-checksums skip checksum verification\n" msgstr " -s, --skip-checksums チェックサム検証をスキップ\n" -#: pg_verifybackup.c:1099 +#: pg_verifybackup.c:1379 #, c-format msgid " -w, --wal-directory=PATH use specified path for WAL files\n" msgstr " -w, --wal-directory=PATH WALファイルに指定したパスを使用する\n" -#: pg_verifybackup.c:1100 +#: pg_verifybackup.c:1380 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: pg_verifybackup.c:1101 +#: pg_verifybackup.c:1381 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: pg_verifybackup.c:1102 +#: pg_verifybackup.c:1382 #, c-format msgid "" "\n" @@ -550,7 +694,7 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: pg_verifybackup.c:1103 +#: pg_verifybackup.c:1383 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" diff --git a/src/bin/pg_verifybackup/po/ka.po b/src/bin/pg_verifybackup/po/ka.po index b787426b173f0..982751984c784 100644 --- a/src/bin/pg_verifybackup/po/ka.po +++ b/src/bin/pg_verifybackup/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_verifybackup (PostgreSQL) 16\n" +"Project-Id-Version: pg_verifybackup (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-04 22:18+0000\n" -"PO-Revision-Date: 2024-06-05 01:39+0200\n" +"POT-Creation-Date: 2025-05-02 22:18+0000\n" +"PO-Revision-Date: 2025-05-03 01:22+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,28 +16,102 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " +#: ../../common/controldata_utils.c:97 +#, c-format +msgid "could not open file \"%s\" for reading: %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:110 pg_verifybackup.c:440 +#: pg_verifybackup.c:478 pg_verifybackup.c:1025 pg_verifybackup.c:1144 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:119 +#, c-format +msgid "could not read file \"%s\": read %d of %zu" +msgstr "\"%s\"-ის წაკითხვის შეცდომა: წაკითხულია %d %zu-დან" + +#: ../../common/controldata_utils.c:132 ../../common/controldata_utils.c:280 +#: pg_verifybackup.c:1030 pg_verifybackup.c:1150 +#, c-format +msgid "could not close file \"%s\": %m" +msgstr "ფაილის (%s) დახურვის შეცდომა: %m" + +#: ../../common/controldata_utils.c:168 +msgid "byte ordering mismatch" +msgstr "ბაიტების მიმდევრობა არ ემთხვევა" + +#: ../../common/controldata_utils.c:170 +#, c-format +msgid "" +"possible byte ordering mismatch\n" +"The byte ordering used to store the pg_control file might not match the one\n" +"used by this program. In that case the results below would be incorrect, and\n" +"the PostgreSQL installation would be incompatible with this data directory." +msgstr "" +"ბაიტების მიმდევრობის შესაძლო შეუსაბამობა pg_control ფაილის შესანახად გამოყენებული \n" +"ბაიტების მიმდევრობა შესაძლოა არ ემთხვეოდეს ამ პროგრამის მიერ გამოყენებულს. ამ შემთხვევაში ქვემოთ \n" +"მოცემული შედეგები არასწორი იქნება და PostgreSQL ეს აგება ამ მონაცემთა საქაღალდესთან შეუთავსებელი იქნება." + +#: ../../common/controldata_utils.c:230 pg_verifybackup.c:408 +#: pg_verifybackup.c:1005 pg_verifybackup.c:1113 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/controldata_utils.c:249 +#, c-format +msgid "could not write file \"%s\": %m" +msgstr "ფაილში (%s) ჩაწერის შეცდომა: %m" + +#: ../../common/controldata_utils.c:268 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/cryptohash.c:261 ../../common/cryptohash_openssl.c:356 +#: ../../common/jsonapi.c:2407 ../../common/parse_manifest.c:157 +#: ../../common/parse_manifest.c:852 +#, c-format +msgid "out of memory" +msgstr "არასაკმარისი მეხსიერება" + +#: ../../common/cryptohash.c:266 ../../common/cryptohash.c:272 +#: ../../common/cryptohash_openssl.c:368 ../../common/cryptohash_openssl.c:376 +msgid "success" +msgstr "წარმატება" + +#: ../../common/cryptohash.c:268 ../../common/cryptohash_openssl.c:370 +msgid "destination buffer too small" +msgstr "სამიზნე ბუფერი ძალიან პატარაა" + +#: ../../common/cryptohash_openssl.c:372 +msgid "OpenSSL failure" +msgstr "OpenSSL -ის სეცდომა" + #: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 #: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format @@ -49,432 +123,610 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/jsonapi.c:2121 +#: ../../common/jsonapi.c:2432 msgid "Recursive descent parser cannot use incremental lexer." msgstr "რეკურსიულ დაღმავალ დამმუშავებელს ინკრემენტული lexer-ის გამოყენება არ შეუძლია." -#: ../../common/jsonapi.c:2123 +#: ../../common/jsonapi.c:2434 msgid "Incremental parser requires incremental lexer." msgstr "ინკრემენტულ დამმუშავებელს ინკრემენტული lexer სჭირდება." -#: ../../common/jsonapi.c:2125 +#: ../../common/jsonapi.c:2436 msgid "JSON nested too deep, maximum permitted depth is 6400." msgstr "JSON მეტისმეტად ღრმადაა ერთმანეთში ჩალაგებული. მაქსიმალური დასაშვები სიღრმეა 6400." -#: ../../common/jsonapi.c:2127 +#: ../../common/jsonapi.c:2438 #, c-format msgid "Escape sequence \"\\%.*s\" is invalid." msgstr "სპეციალური მიმდევრობა \"\\%.*s\" არასწორია." -#: ../../common/jsonapi.c:2131 +#: ../../common/jsonapi.c:2442 #, c-format msgid "Character with value 0x%02x must be escaped." msgstr "სიმბოლო კოდით 0x%02x აუცილებლად ეკრანირებული უნდა იყოს." -#: ../../common/jsonapi.c:2135 +#: ../../common/jsonapi.c:2446 #, c-format msgid "Expected end of input, but found \"%.*s\"." msgstr "მოველოდი შეყვანის დასასრულს, მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2138 +#: ../../common/jsonapi.c:2449 #, c-format msgid "Expected array element or \"]\", but found \"%.*s\"." msgstr "მოველოდი მასივის ელემენტს ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2141 +#: ../../common/jsonapi.c:2452 #, c-format msgid "Expected \",\" or \"]\", but found \"%.*s\"." msgstr "მოველოდი \",\" ან \"]\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2144 +#: ../../common/jsonapi.c:2455 #, c-format msgid "Expected \":\", but found \"%.*s\"." msgstr "მოველოდი \":\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2147 +#: ../../common/jsonapi.c:2458 #, c-format msgid "Expected JSON value, but found \"%.*s\"." msgstr "მოველოდი JSON მნიშვნელობას. მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2150 +#: ../../common/jsonapi.c:2461 msgid "The input string ended unexpectedly." msgstr "შეყვანის სტრიქონი მოულოდნელად დასრულდა." -#: ../../common/jsonapi.c:2152 +#: ../../common/jsonapi.c:2463 #, c-format msgid "Expected string or \"}\", but found \"%.*s\"." msgstr "მოველოდი სტრიქონს ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2155 +#: ../../common/jsonapi.c:2466 #, c-format msgid "Expected \",\" or \"}\", but found \"%.*s\"." msgstr "მოველოდი \",\", ან \"}\", მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2158 +#: ../../common/jsonapi.c:2469 #, c-format msgid "Expected string, but found \"%.*s\"." msgstr "მოველოდი სტრიქონს, მაგრამ მივიღე \"%.*s\"." -#: ../../common/jsonapi.c:2161 +#: ../../common/jsonapi.c:2472 #, c-format msgid "Token \"%.*s\" is invalid." msgstr "კოდი \"%.*s\" არასწორია." -#: ../../common/jsonapi.c:2164 +#: ../../common/jsonapi.c:2478 msgid "\\u0000 cannot be converted to text." msgstr "\\u0000 ტექსტად ვერ გარდაიქმნება." -#: ../../common/jsonapi.c:2166 +#: ../../common/jsonapi.c:2480 msgid "\"\\u\" must be followed by four hexadecimal digits." msgstr "\"\\u\" ს თექვსმეტობითი ციფრები უნდა მოჰყვებოდეს." -#: ../../common/jsonapi.c:2169 +#: ../../common/jsonapi.c:2483 msgid "Unicode escape values cannot be used for code point values above 007F when the encoding is not UTF8." msgstr "უნიკოდის სპეციალური კოდების გამოყენება კოდის წერტილის მნიშვნელობებად 007F-ის ზემოთ შეუძლებელია, თუ კოდირება UTF-8 არაა." -#: ../../common/jsonapi.c:2178 +#: ../../common/jsonapi.c:2492 #, c-format msgid "Unicode escape value could not be translated to the server's encoding %s." msgstr "უნიკოდის სპეციალური სიმბოლოს მნიშვნელობის თარგმნა სერვერის კოდირებაში %s შეუძლებელია." -#: ../../common/jsonapi.c:2185 +#: ../../common/jsonapi.c:2499 msgid "Unicode high surrogate must not follow a high surrogate." msgstr "უნიკოდის მაღალ სუროგატს მაღალი სუროგატი არ უნდა მოსდევდეს." -#: ../../common/jsonapi.c:2187 +#: ../../common/jsonapi.c:2501 msgid "Unicode low surrogate must follow a high surrogate." msgstr "უნიკოდის დაბალი სუროგატი მაღალ სუროგატს უნდა მისდევდეს." -#: ../../common/parse_manifest.c:157 ../../common/parse_manifest.c:853 -#, c-format -msgid "out of memory" -msgstr "არასაკმარისი მეხსიერება" +#: ../../common/jsonapi.c:2523 +msgid "out of memory while constructing error description" +msgstr "არასაკმარისი მეხსიერება შეცდომის აღწერის აგებისას" -#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:855 +#: ../../common/parse_manifest.c:159 ../../common/parse_manifest.c:854 #, c-format msgid "could not initialize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის ინიციალიზაციის შეცდომა" -#: ../../common/parse_manifest.c:204 ../../common/parse_manifest.c:261 +#: ../../common/parse_manifest.c:203 ../../common/parse_manifest.c:260 msgid "manifest ended unexpectedly" msgstr "მანიფესტი მოულოდნელად დასრულდა" -#: ../../common/parse_manifest.c:210 ../../common/parse_manifest.c:862 +#: ../../common/parse_manifest.c:209 ../../common/parse_manifest.c:861 #, c-format msgid "could not update checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის განახლების შეცდომა" -#: ../../common/parse_manifest.c:302 +#: ../../common/parse_manifest.c:301 msgid "unexpected object start" msgstr "ობიექტის მოულოდნელი დასაწყისი" -#: ../../common/parse_manifest.c:337 +#: ../../common/parse_manifest.c:336 msgid "unexpected object end" msgstr "ობიექტის მოულოდნელი დასასრული" -#: ../../common/parse_manifest.c:366 +#: ../../common/parse_manifest.c:365 msgid "unexpected array start" msgstr "მასივის მოულოდნელი დასაწყისი" -#: ../../common/parse_manifest.c:391 +#: ../../common/parse_manifest.c:390 msgid "unexpected array end" msgstr "მასივის მოულოდნელი დასასრული" -#: ../../common/parse_manifest.c:418 +#: ../../common/parse_manifest.c:417 msgid "expected version indicator" msgstr "მოსალოდნელი ვერსიის მაჩვენებელი" -#: ../../common/parse_manifest.c:454 +#: ../../common/parse_manifest.c:453 msgid "unrecognized top-level field" msgstr "უცნობი ველი ზედა დონეზე" -#: ../../common/parse_manifest.c:473 +#: ../../common/parse_manifest.c:472 msgid "unexpected file field" msgstr "მოულოდნელი ველი ფაილისთვის" -#: ../../common/parse_manifest.c:487 +#: ../../common/parse_manifest.c:486 msgid "unexpected WAL range field" msgstr "მოულოდნელი ველი WAL-ის დიაპაზონისთვის" -#: ../../common/parse_manifest.c:493 +#: ../../common/parse_manifest.c:492 msgid "unexpected object field" msgstr "ობიექტის მოულოდნელი ველი" -#: ../../common/parse_manifest.c:583 +#: ../../common/parse_manifest.c:582 msgid "unexpected scalar" msgstr "მოულოდნელი სკალარი" -#: ../../common/parse_manifest.c:609 +#: ../../common/parse_manifest.c:608 msgid "manifest version not an integer" msgstr "მანიფესტის ვერსია მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:613 +#: ../../common/parse_manifest.c:612 msgid "unexpected manifest version" msgstr "მანიფესტის მოულოდნელი ვერსია" -#: ../../common/parse_manifest.c:637 -msgid "manifest system identifier not an integer" -msgstr "მანიფესტის სისტემის იდენფიტიკატორი მთელი რიცხვი არაა" +#: ../../common/parse_manifest.c:636 +msgid "system identifier in manifest not an integer" +msgstr "სისტემის იდენფიტიკატორი მანიფესტში მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:662 +#: ../../common/parse_manifest.c:661 msgid "missing path name" msgstr "აკლია ბილიკის სახელი" -#: ../../common/parse_manifest.c:665 +#: ../../common/parse_manifest.c:664 msgid "both path name and encoded path name" msgstr "ორივე, ბილიკის სახელი და ბილიკის კოდირებული სახელი" -#: ../../common/parse_manifest.c:667 +#: ../../common/parse_manifest.c:666 msgid "missing size" msgstr "ზომა აკლია" -#: ../../common/parse_manifest.c:670 +#: ../../common/parse_manifest.c:669 msgid "checksum without algorithm" msgstr "საკონტროლო ჯამი ალგორითმის გარეშე" -#: ../../common/parse_manifest.c:684 +#: ../../common/parse_manifest.c:683 msgid "could not decode file name" msgstr "ფაილის სახელის გაშიფვრის შეცდომა" -#: ../../common/parse_manifest.c:694 +#: ../../common/parse_manifest.c:693 msgid "file size is not an integer" msgstr "ფაილის ზომა მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:700 +#: ../../common/parse_manifest.c:699 #, c-format msgid "unrecognized checksum algorithm: \"%s\"" msgstr "საკონტროლო ჯამის უცნობი ალგორითმი: \"%s\"" -#: ../../common/parse_manifest.c:719 +#: ../../common/parse_manifest.c:718 #, c-format msgid "invalid checksum for file \"%s\": \"%s\"" msgstr "არასწორი საკონტროლო ჯამი ფაილისთვის \"%s\": \"%s\"" -#: ../../common/parse_manifest.c:762 +#: ../../common/parse_manifest.c:761 msgid "missing timeline" msgstr "აკლია დროის ხაზი" -#: ../../common/parse_manifest.c:764 +#: ../../common/parse_manifest.c:763 msgid "missing start LSN" msgstr "აკლია საწყისი LSN" -#: ../../common/parse_manifest.c:766 +#: ../../common/parse_manifest.c:765 msgid "missing end LSN" msgstr "აკლია დასასრულის LSN" -#: ../../common/parse_manifest.c:772 +#: ../../common/parse_manifest.c:771 msgid "timeline is not an integer" msgstr "დროის ხაზი მთელი რიცხვი არაა" -#: ../../common/parse_manifest.c:775 +#: ../../common/parse_manifest.c:774 msgid "could not parse start LSN" msgstr "საწყისი LSN-ის დამუშავების შეცდომა" -#: ../../common/parse_manifest.c:778 +#: ../../common/parse_manifest.c:777 msgid "could not parse end LSN" msgstr "საბოლოო LSN-ის დამუშავების შეცდომა" -#: ../../common/parse_manifest.c:843 +#: ../../common/parse_manifest.c:842 msgid "expected at least 2 lines" msgstr "ველოდებოდი სულ ცოტა 2 ხაზს" -#: ../../common/parse_manifest.c:846 +#: ../../common/parse_manifest.c:845 msgid "last line not newline-terminated" msgstr "ბოლო ხაზი ხაზის გადატანით არ სრულდება" -#: ../../common/parse_manifest.c:865 +#: ../../common/parse_manifest.c:864 #, c-format msgid "could not finalize checksum of manifest" msgstr "მანიფესტის საკონტროლო ჯამის დასრულების შეცდომა" -#: ../../common/parse_manifest.c:869 +#: ../../common/parse_manifest.c:868 #, c-format msgid "manifest has no checksum" msgstr "მანიფესტის საკონტროლო ჯამი არ გააჩნია" -#: ../../common/parse_manifest.c:873 +#: ../../common/parse_manifest.c:872 #, c-format msgid "invalid manifest checksum: \"%s\"" msgstr "მანიფესტის საკონტროლო ჯამის არასწორია: %s" -#: ../../common/parse_manifest.c:877 +#: ../../common/parse_manifest.c:876 #, c-format msgid "manifest checksum mismatch" msgstr "მანიფესტის საკონტროლო ჯამი არ ემთხვევა" -#: ../../common/parse_manifest.c:892 +#: ../../common/parse_manifest.c:891 #, c-format msgid "could not parse backup manifest: %s" msgstr "მარქაფის მანიფესტის დამუშავების შეცრომა: %s" -#: pg_verifybackup.c:277 pg_verifybackup.c:286 pg_verifybackup.c:297 +#: ../../fe_utils/astreamer_gzip.c:115 +#, c-format +msgid "could not create compressed file \"%s\": %m" +msgstr "ვერ შექმნა შეკუმშული ფაილი \"%s\": %m" + +#: ../../fe_utils/astreamer_gzip.c:127 +#, c-format +msgid "could not duplicate stdout: %m" +msgstr "stdout-ის დუბლირების შეცდომა: %m" + +#: ../../fe_utils/astreamer_gzip.c:131 +#, c-format +msgid "could not open output file: %m" +msgstr "გამოტანის ფაილის გახსნის შეცდომა: %m" + +#: ../../fe_utils/astreamer_gzip.c:135 +#, c-format +msgid "could not set compression level %d: %s" +msgstr "შეკუმშვის დონის დაყენების შეცდომა %d: %s" + +#: ../../fe_utils/astreamer_gzip.c:140 ../../fe_utils/astreamer_gzip.c:273 +#: ../../fe_utils/astreamer_lz4.c:102 ../../fe_utils/astreamer_lz4.c:300 +#: ../../fe_utils/astreamer_zstd.c:133 ../../fe_utils/astreamer_zstd.c:288 +#, c-format +msgid "this build does not support compression with %s" +msgstr "ამ აგებაში %s-ით შეკუმშვის მხარდაჭრა არ არსებობს" + +#: ../../fe_utils/astreamer_gzip.c:167 +#, c-format +msgid "could not write to compressed file \"%s\": %s" +msgstr "შეკუმშული ფაილში (\"%s\") ჩაწერის შეცდომა: %s" + +#: ../../fe_utils/astreamer_gzip.c:191 +#, c-format +msgid "could not close compressed file \"%s\": %m" +msgstr "შეკუმშული ფაილის (\"%s\") დახურვის შეცდომა: %m" + +#: ../../fe_utils/astreamer_gzip.c:269 +#, c-format +msgid "could not initialize compression library" +msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზაციის შეცდომა" + +#: ../../fe_utils/astreamer_gzip.c:320 ../../fe_utils/astreamer_lz4.c:356 +#: ../../fe_utils/astreamer_zstd.c:333 +#, c-format +msgid "could not decompress data: %s" +msgstr "მონაცემების გაშლის შეცდომა: %s" + +#: ../../fe_utils/astreamer_lz4.c:97 +#, c-format +msgid "could not create lz4 compression context: %s" +msgstr "lz4 შეკუმშვის კონტექსტის შექმნის შეცდომა: %s" + +#: ../../fe_utils/astreamer_lz4.c:142 +#, c-format +msgid "could not write lz4 header: %s" +msgstr "lz4 თავსართის ჩაწერის შეცდოა: %s" + +#: ../../fe_utils/astreamer_lz4.c:191 ../../fe_utils/astreamer_zstd.c:185 +#: ../../fe_utils/astreamer_zstd.c:227 +#, c-format +msgid "could not compress data: %s" +msgstr "მონაცემების შეკუმშვა შეუძლებელია: %s" + +#: ../../fe_utils/astreamer_lz4.c:243 +#, c-format +msgid "could not end lz4 compression: %s" +msgstr "lz4 შეკუმშვის დასრულების შეცდომა: %s" + +#: ../../fe_utils/astreamer_lz4.c:295 +#, c-format +msgid "could not initialize compression library: %s" +msgstr "შეკუმშვის ბიბლიოთეკის ინიციალიზება ვერ მოხერხდა: %s" + +#: ../../fe_utils/astreamer_tar.c:244 +#, c-format +msgid "tar file trailer exceeds 2 blocks" +msgstr "tar ფაილის ბოლოსართი 2 ბლოკს სცდება" + +#: ../../fe_utils/astreamer_tar.c:249 astreamer_verify.c:130 +#, c-format +msgid "unexpected state while parsing tar archive" +msgstr "მოულოდნელი მდგომარეობა tar არქივის დამუშავებისას" + +#: ../../fe_utils/astreamer_tar.c:292 +#, c-format +msgid "tar member has empty name" +msgstr "tar-ის წევრს ცარიელი სახელი აქვს" + +#: ../../fe_utils/astreamer_tar.c:326 +#, c-format +msgid "COPY stream ended before last file was finished" +msgstr "COPY-ის ნაკადი ბოლო ფაილის დასრულებამდე დასრულდა" + +#: ../../fe_utils/astreamer_zstd.c:89 +#, c-format +msgid "could not create zstd compression context" +msgstr "zstd შეკუმშვის კონტექსტის შექმნის შეცდომა" + +#: ../../fe_utils/astreamer_zstd.c:95 +#, c-format +msgid "could not set zstd compression level to %d: %s" +msgstr "zstd შეკუმშვის დონის %d-ზე დაყენების შეცდომა: %s" + +#: ../../fe_utils/astreamer_zstd.c:109 +#, c-format +msgid "could not set compression worker count to %d: %s" +msgstr "შეკუმშვის დამხმარე პროცესების რიცხვის %d-ზე დაყენების შეცდომა: %s" + +#: ../../fe_utils/astreamer_zstd.c:120 +#, c-format +msgid "could not enable long-distance mode: %s" +msgstr "long-distance რეჟიმი ვერ ჩავრთე: %s" + +#: ../../fe_utils/astreamer_zstd.c:279 +#, c-format +msgid "could not create zstd decompression context" +msgstr "zstd გაშლის კონტექსტის შექმნის შეცდომა" + +#: astreamer_verify.c:198 +#, c-format +msgid "file \"%s\" is present in archive \"%s\" but not in the manifest" +msgstr "ფაილი \"%s\" არსებობს არქივში \"%s\", მაგრამ არა მანიფესტში" + +#: astreamer_verify.c:211 +#, c-format +msgid "file \"%s\" has size %llu in archive \"%s\" but size % in the manifest" +msgstr "ფაილის \"%s\" ზომაა %llu არქივში \"%s\", მაგრამ მანიფესტში მითითებული ზომაა %" + +#: astreamer_verify.c:236 +#, c-format +msgid "%s: could not initialize checksum of file \"%s\"" +msgstr "%s: ფაილის (\"%s\") საკონტროლო ჯამის ინიციალიზაციის შეცდომა" + +#: astreamer_verify.c:274 pg_verifybackup.c:1133 +#, c-format +msgid "could not update checksum of file \"%s\"" +msgstr "ფაილის (\"%s\") საკონტროლო ჯამის განახლების შეცდომა" + +#: astreamer_verify.c:300 +#, c-format +msgid "file \"%s\" in archive \"%s\" should contain % bytes, but % bytes were read" +msgstr "ფაილი \"%s\" არქივში \"%s\" უნდა შეიცავდეს % ბაიტს მაგრამ წაკითხულია % ბაიტი" + +#: astreamer_verify.c:312 pg_verifybackup.c:1179 +#, c-format +msgid "could not finalize checksum of file \"%s\"" +msgstr "ფაილის (\"%s\") საკონტროლო ჯამის დასრულების შეცდომა" + +#: astreamer_verify.c:320 +#, c-format +msgid "file \"%s\" in archive \"%s\" has checksum of length %d, but expected %d" +msgstr "ფაილის \"%s\" არქივში \"%s\" საკონტროლო ჯამის სიგრძეა %d, მოველოდით სიგრძეს %d" + +#: astreamer_verify.c:325 +#, c-format +msgid "checksum mismatch for file \"%s\" in archive \"%s\"" +msgstr "არასწორი საკონტროლო ჯამი ფაილისთვის \"%s\" არქივში \"%s\"" + +#: astreamer_verify.c:387 +#, c-format +msgid "unexpected control file size %d, expected %d" +msgstr "საკონტროლო ფაილის არასწორი სიგრძე: %d. უნდა იყოს: %d" + +#: astreamer_verify.c:399 +#, c-format +msgid "%s: %s: CRC is incorrect" +msgstr "%s: %s: CRC არასწორია" + +#: astreamer_verify.c:405 +#, c-format +msgid "%s: %s: unexpected control file version" +msgstr "%s: %s: მოულოდნელი საკონტროლო ფაილის ვერსია" + +#: astreamer_verify.c:412 +#, c-format +msgid "%s: %s: manifest system identifier is %, but control file has %" +msgstr "%s: %s: მანიფესტის სისტემური იდენტიფიკატორია %, მაგრამ კონტროლის ფაილი შეიცავს %-ს" + +#: pg_verifybackup.c:208 +#, c-format +msgid "invalid backup format \"%s\", must be \"plain\" or \"tar\"" +msgstr "მარქაფის არასწორი ფორმატი \"%s\". უნდა იყოს: \"plain\" ან \"tar\"" + +#: pg_verifybackup.c:229 pg_verifybackup.c:238 pg_verifybackup.c:249 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: pg_verifybackup.c:285 +#: pg_verifybackup.c:237 #, c-format msgid "no backup directory specified" msgstr "მარქაფის საქაღალდე მითითებული არაა" -#: pg_verifybackup.c:295 +#: pg_verifybackup.c:247 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_verifybackup.c:303 +#: pg_verifybackup.c:255 #, c-format msgid "cannot specify both %s and %s" msgstr "ორივე, %s და %s ერთად მითითება შეუძლებელია" -#: pg_verifybackup.c:323 +#: pg_verifybackup.c:275 #, c-format msgid "program \"%s\" is needed by %s but was not found in the same directory as \"%s\"" msgstr "პროგრამა \"%s\" სჭირდება \"%s\"-ს, მაგრამ იგივე საქაღალდეში, სადაც \"%s\", ნაპოვნი არაა" -#: pg_verifybackup.c:326 +#: pg_verifybackup.c:278 #, c-format msgid "program \"%s\" was found by \"%s\" but was not the same version as %s" msgstr "პროგრამა „%s“ ნაპოვნია „%s“-ის მიერ, მაგრამ ვერსია, იგივეა არაა, რაც %s" -#: pg_verifybackup.c:381 -#, c-format -msgid "backup successfully verified\n" -msgstr "მარქაფი წარმატებით შემოწმდა\n" - -#: pg_verifybackup.c:406 pg_verifybackup.c:865 +#: pg_verifybackup.c:304 pg_verifybackup.c:625 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: pg_verifybackup.c:410 +#: pg_verifybackup.c:323 pg_verifybackup.c:412 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: pg_verifybackup.c:438 pg_verifybackup.c:476 pg_verifybackup.c:896 +#: pg_verifybackup.c:340 #, c-format -msgid "could not read file \"%s\": %m" -msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" +msgid "pg_waldump cannot read tar files" +msgstr "pg_waldump-ს tar ფაილების წაკითხვა არ შეუძლია" + +#: pg_verifybackup.c:341 +#, c-format +msgid "You must use -n/--no-parse-wal when verifying a tar-format backup." +msgstr "Tar-ის ფორმატში არსებული მარქაფების გადამოწმებისას უნდა გამოიყენოთ პარამეტრი -n ან --no-parse-wal." -#: pg_verifybackup.c:440 +#: pg_verifybackup.c:383 +#, c-format +msgid "backup successfully verified\n" +msgstr "მარქაფი წარმატებით შემოწმდა\n" + +#: pg_verifybackup.c:442 #, c-format msgid "could not read file \"%s\": read %d of %lld" msgstr "ფაილის \"%s\" წაკითხვა შეუძლებელია: წაკითხულია %d %lld-დან" -#: pg_verifybackup.c:478 +#: pg_verifybackup.c:480 #, c-format msgid "could not read file \"%s\": read %lld of %lld" msgstr "ფაილის \"%s\" წაკითხვა შეუძლებელია: წაკითხულია %lld %lld-დან" -#: pg_verifybackup.c:561 +#: pg_verifybackup.c:563 #, c-format msgid "duplicate path name in backup manifest: \"%s\"" msgstr "მარქაფს მანიფესტში მითითებული ბილიკის სახელი დუბლირებულია: %s" -#: pg_verifybackup.c:624 pg_verifybackup.c:631 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" - -#: pg_verifybackup.c:663 +#: pg_verifybackup.c:657 pg_verifybackup.c:827 #, c-format msgid "could not close directory \"%s\": %m" msgstr "საქაღალდის %s-ზე დახურვის შეცდომა: %m" -#: pg_verifybackup.c:683 +#: pg_verifybackup.c:678 pg_verifybackup.c:897 #, c-format msgid "could not stat file or directory \"%s\": %m" msgstr "ფაილის ან საქაღალდის \"%s\" პოვნა შეუძლებელია: %m" -#: pg_verifybackup.c:706 +#: pg_verifybackup.c:701 #, c-format -msgid "\"%s\" is not a file or directory" -msgstr "\"%s\" არც ფაილია, არც საქაღალდე" +msgid "\"%s\" is not a regular file or directory" +msgstr "\"%s\" არც ჩვეულებრივი ფაილია, არც საქაღალდე" -#: pg_verifybackup.c:716 +#: pg_verifybackup.c:711 #, c-format msgid "\"%s\" is present on disk but not in the manifest" msgstr "\"%s\" დისკზე არსებობს, მაგრამ არა მანიფესტში" -#: pg_verifybackup.c:728 +#: pg_verifybackup.c:723 #, c-format -msgid "\"%s\" has size %lld on disk but size %zu in the manifest" -msgstr "დისკზე \"%s\"-ის ზომაა %lld, მაგრამ მანიფესტში მითითებული ზომაა %zu" +msgid "\"%s\" has size %llu on disk but size %llu in the manifest" +msgstr "დისკზე \"%s\"-ის ზომაა %llu, მაგრამ მანიფესტში მითითებული ზომაა %llu" -#: pg_verifybackup.c:768 +#: pg_verifybackup.c:765 #, c-format msgid "%s: CRC is incorrect" msgstr "%s: CRC არასწორია" -#: pg_verifybackup.c:772 +#: pg_verifybackup.c:769 #, c-format msgid "%s: unexpected control file version" msgstr "%s: მოულოდნელი საკონტროლო ფაილის ვერსია" -#: pg_verifybackup.c:777 -#, c-format -msgid "%s: manifest system identifier is %llu, but control file has %llu" -msgstr "%s: მანიფესტის სისტემის იდენტიფიკატორია %llu, მაგრამ კონტროლის ფაილი შეიცავს %llu" - -#: pg_verifybackup.c:801 +#: pg_verifybackup.c:774 #, c-format -msgid "\"%s\" is present in the manifest but not on disk" -msgstr "\"%s\" არსებობს მანიფესტში, მაგრამ არა დისკზე" +msgid "%s: manifest system identifier is %, but control file has %" +msgstr "%s: მანიფესტის სისტემის იდენტიფიკატორია %, მაგრამ კონტროლის ფაილი შეიცავს %-ს" -#: pg_verifybackup.c:873 +#: pg_verifybackup.c:906 #, c-format -msgid "could not initialize checksum of file \"%s\"" -msgstr "ფაილის (\"%s\") საკონტროლო ჯამის ინიციალიზაციის შეცდომა" +msgid "file \"%s\" is not a regular file" +msgstr "ფაილ \"%s\" ჩვეულებრივი ფაილი არაა" -#: pg_verifybackup.c:885 +#: pg_verifybackup.c:936 pg_verifybackup.c:957 #, c-format -msgid "could not update checksum of file \"%s\"" -msgstr "ფაილის (\"%s\") საკონტროლო ჯამის განახლების შეცდომა" +msgid "file \"%s\" is not expected in a tar format backup" +msgstr "ფაილი \"%s\" მოულოდნელია tar ფორმატის მარქაფში" -#: pg_verifybackup.c:902 +#: pg_verifybackup.c:1049 #, c-format -msgid "could not close file \"%s\": %m" -msgstr "ფაილის (%s) დახურვის შეცდომა: %m" +msgid "\"%s\" is present in the manifest but not on disk" +msgstr "\"%s\" არსებობს მანიფესტში, მაგრამ არა დისკზე" -#: pg_verifybackup.c:921 +#: pg_verifybackup.c:1121 #, c-format -msgid "file \"%s\" should contain %zu bytes, but read %zu bytes" -msgstr "ფაილი \"%s\" უნდა შეიცავდეს %zu ბაიტს მაგრამ წაკითხულია %zu ბაიტი" +msgid "could not initialize checksum of file \"%s\"" +msgstr "ფაილის (\"%s\") საკონტროლო ჯამის ინიციალიზაციის შეცდომა" -#: pg_verifybackup.c:931 +#: pg_verifybackup.c:1169 #, c-format -msgid "could not finalize checksum of file \"%s\"" -msgstr "ფაილის (\"%s\") საკონტროლო ჯამის დასრულების შეცდომა" +msgid "file \"%s\" should contain % bytes, but read %" +msgstr "ფაილი \"%s\" უნდა შეიცავდეს % ბაიტს მაგრამ წაკითხულია % ბაიტი" -#: pg_verifybackup.c:939 +#: pg_verifybackup.c:1187 #, c-format msgid "file \"%s\" has checksum of length %d, but expected %d" msgstr "ფაილის \"%s\" საკონტროლო ჯამის სიგრძეა %d, მოველოდით %d" -#: pg_verifybackup.c:943 +#: pg_verifybackup.c:1191 #, c-format msgid "checksum mismatch for file \"%s\"" msgstr "არასწორი საკონტროლო ჯამი ფაილისთვის \"%s\"" -#: pg_verifybackup.c:969 +#: pg_verifybackup.c:1217 #, c-format msgid "WAL parsing failed for timeline %u" msgstr "WAL-ის დამუშავების შეცდომა დროის ხაზისთვის %u" -#: pg_verifybackup.c:1072 +#: pg_verifybackup.c:1351 #, c-format msgid "%*s/%s kB (%d%%) verified" msgstr "%*s/%s კბ (%d%%) გადამოწმდა" -#: pg_verifybackup.c:1089 +#: pg_verifybackup.c:1368 #, c-format msgid "" "%s verifies a backup against the backup manifest.\n" "\n" msgstr "%s მარქაფს მის მანიფესტს შეადარებს\n" -#: pg_verifybackup.c:1090 +#: pg_verifybackup.c:1369 #, c-format msgid "" "Usage:\n" @@ -485,62 +737,67 @@ msgstr "" " %s [პარამეტრი]... მარქაფისსაქაღალდე\n" "\n" -#: pg_verifybackup.c:1091 +#: pg_verifybackup.c:1370 #, c-format msgid "Options:\n" msgstr "პარამეტრები:\n" -#: pg_verifybackup.c:1092 +#: pg_verifybackup.c:1371 #, c-format msgid " -e, --exit-on-error exit immediately on error\n" msgstr " -e, --exit-on-error დაუყოვნებლივი გამოსვლა შეცდომის შემთხვევაში\n" -#: pg_verifybackup.c:1093 +#: pg_verifybackup.c:1372 +#, c-format +msgid " -F, --format=p|t backup format (plain, tar)\n" +msgstr " -F, --format=p|t მარქაფის ფორმატი (plain, tar)\n" + +#: pg_verifybackup.c:1373 #, c-format msgid " -i, --ignore=RELATIVE_PATH ignore indicated path\n" msgstr " -i, --ignore=შედარებითი_ბილიკ ბითითებული ბილიკის იგნორი\n" -#: pg_verifybackup.c:1094 +#: pg_verifybackup.c:1374 #, c-format msgid " -m, --manifest-path=PATH use specified path for manifest\n" msgstr " -m, --manifest-path=ბილიკი მანიფესტისთვის მითითებული ბილიკის გამოყენება\n" -#: pg_verifybackup.c:1095 +#: pg_verifybackup.c:1375 #, c-format msgid " -n, --no-parse-wal do not try to parse WAL files\n" msgstr " -n, --no-parse-wal WAL ფაილები არ დამუშავდება\n" -#: pg_verifybackup.c:1096 +#: pg_verifybackup.c:1376 #, c-format msgid " -P, --progress show progress information\n" msgstr " -P, --progress მიმდინარეობის ინფორმაციის ჩვენება\n" -#: pg_verifybackup.c:1097 +#: pg_verifybackup.c:1377 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet შეცდომების გარდა ეკრანზე არაფერი გამოჩნდება\n" -#: pg_verifybackup.c:1098 +#: pg_verifybackup.c:1378 #, c-format msgid " -s, --skip-checksums skip checksum verification\n" msgstr " -s, --skip-checksums საკონტროლო ჯამების შემოწმების გამოტოვება\n" -#: pg_verifybackup.c:1099 +#: pg_verifybackup.c:1379 #, c-format msgid " -w, --wal-directory=PATH use specified path for WAL files\n" msgstr " -w, --wal-directory=ბილიკი WAL ფაილებისთვის მითითებული ბილიკის გამოყენება\n" -#: pg_verifybackup.c:1100 +#: pg_verifybackup.c:1380 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: pg_verifybackup.c:1101 +#: pg_verifybackup.c:1381 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_verifybackup.c:1102 +#: pg_verifybackup.c:1382 #, c-format msgid "" "\n" @@ -549,14 +806,22 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_verifybackup.c:1103 +#: pg_verifybackup.c:1383 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" +#, c-format +#~ msgid "\"%s\" is not a plain file" +#~ msgstr "\"%s\" უბრალო ფაილი არაა" + #~ msgid "parsing failed" #~ msgstr "დამუშავების შეცდომა" #, c-format #~ msgid "unexpected json parse error type: %d" #~ msgstr "მოულოდნელი json-ის დამუშავების შეცდომის ტიპი: %d" + +#, c-format +#~ msgid "unexpected state while parsing tar file" +#~ msgstr "მოულოდნელი მდგომარეობა tar არქივის დამუშავებისას" diff --git a/src/bin/pg_verifybackup/po/meson.build b/src/bin/pg_verifybackup/po/meson.build index e0a83002ea5db..7e6ddbbc9dce8 100644 --- a/src/bin/pg_verifybackup/po/meson.build +++ b/src/bin/pg_verifybackup/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_verifybackup-' + pg_version_major.to_string())] diff --git a/src/bin/pg_verifybackup/t/001_basic.pl b/src/bin/pg_verifybackup/t/001_basic.pl index 2f3e52d296f38..ded3011df5f42 100644 --- a/src/bin/pg_verifybackup/t/001_basic.pl +++ b/src/bin/pg_verifybackup/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -31,7 +31,11 @@ # but then try to use an alternate, nonexisting manifest command_fails_like( - [ 'pg_verifybackup', '-m', "$tempdir/not_the_manifest", $tempdir ], + [ + 'pg_verifybackup', + '--manifest-path' => "$tempdir/not_the_manifest", + $tempdir, + ], qr/could not open file.*\/not_the_manifest\"/, 'pg_verifybackup respects -m flag'); diff --git a/src/bin/pg_verifybackup/t/002_algorithm.pl b/src/bin/pg_verifybackup/t/002_algorithm.pl index fb2a1fd7c4e1a..ae16c11bc4dd1 100644 --- a/src/bin/pg_verifybackup/t/002_algorithm.pl +++ b/src/bin/pg_verifybackup/t/002_algorithm.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify that we can take and verify backups with various checksum types. @@ -14,24 +14,39 @@ $primary->init(allows_streaming => 1); $primary->start; -for my $algorithm (qw(bogus none crc32c sha224 sha256 sha384 sha512)) +sub test_checksums { - my $backup_path = $primary->backup_dir . '/' . $algorithm; + my ($format, $algorithm) = @_; + my $backup_path = $primary->backup_dir . '/' . $format . '/' . $algorithm; my @backup = ( - 'pg_basebackup', '-D', $backup_path, - '--manifest-checksums', $algorithm, '--no-sync', '-cfast'); - my @verify = ('pg_verifybackup', '-e', $backup_path); + 'pg_basebackup', + '--pgdata' => $backup_path, + '--manifest-checksums' => $algorithm, + '--no-sync', + '--checkpoint' => 'fast'); + my @verify = ('pg_verifybackup', '--exit-on-error', $backup_path); + + if ($format eq 'tar') + { + # Add switch to get a tar-format backup + push @backup, ('--format' => 'tar'); + + # Add switch to skip WAL verification, which is not yet supported for + # tar-format backups + push @verify, ('--no-parse-wal'); + } # A backup with a bogus algorithm should fail. if ($algorithm eq 'bogus') { $primary->command_fails(\@backup, - "backup fails with algorithm \"$algorithm\""); - next; + "$format format backup fails with algorithm \"$algorithm\""); + return; } # A backup with a valid algorithm should work. - $primary->command_ok(\@backup, "backup ok with algorithm \"$algorithm\""); + $primary->command_ok(\@backup, + "$format format backup ok with algorithm \"$algorithm\""); # We expect each real checksum algorithm to be mentioned on every line of # the backup manifest file except the first and last; for simplicity, we @@ -39,7 +54,8 @@ # is none, we just check that the manifest exists. if ($algorithm eq 'none') { - ok(-f "$backup_path/backup_manifest", "backup manifest exists"); + ok( -f "$backup_path/backup_manifest", + "$format format backup manifest exists"); } else { @@ -52,10 +68,19 @@ # Make sure that it verifies OK. $primary->command_ok(\@verify, - "verify backup with algorithm \"$algorithm\""); + "verify $format format backup with algorithm \"$algorithm\""); # Remove backup immediately to save disk space. rmtree($backup_path); } +# Do the check +for my $format (qw(plain tar)) +{ + for my $algorithm (qw(bogus none crc32c sha224 sha256 sha384 sha512)) + { + test_checksums($format, $algorithm); + } +} + done_testing(); diff --git a/src/bin/pg_verifybackup/t/003_corruption.pl b/src/bin/pg_verifybackup/t/003_corruption.pl index ae91e04338460..1dd60f709cf66 100644 --- a/src/bin/pg_verifybackup/t/003_corruption.pl +++ b/src/bin/pg_verifybackup/t/003_corruption.pl @@ -1,16 +1,19 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify that various forms of corruption are detected by pg_verifybackup. use strict; use warnings FATAL => 'all'; +use Cwd; use File::Path qw(rmtree); use File::Copy; use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; use Test::More; +my $tar = $ENV{TAR}; + my $primary = PostgreSQL::Test::Cluster->new('primary'); $primary->init(allows_streaming => 1); $primary->start; @@ -34,35 +37,37 @@ 'name' => 'extra_file', 'mutilate' => \&mutilate_extra_file, 'fails_like' => - qr/extra_file.*present on disk but not in the manifest/ + qr/extra_file.*present (on disk|in archive "[^"]+") but not in the manifest/ }, { 'name' => 'extra_tablespace_file', 'mutilate' => \&mutilate_extra_tablespace_file, 'fails_like' => - qr/extra_ts_file.*present on disk but not in the manifest/ + qr/extra_ts_file.*present (on disk|in archive "[^"]+") but not in the manifest/ }, { 'name' => 'missing_file', 'mutilate' => \&mutilate_missing_file, 'fails_like' => - qr/pg_xact\/0000.*present in the manifest but not on disk/ + qr/pg_xact\/0000.*present in the manifest but not (on disk|in archive "[^"]+")/ }, { 'name' => 'missing_tablespace', 'mutilate' => \&mutilate_missing_tablespace, 'fails_like' => - qr/pg_tblspc.*present in the manifest but not on disk/ + qr/pg_tblspc.*present in the manifest but not (on disk|in archive "[^"]+")/ }, { 'name' => 'append_to_file', 'mutilate' => \&mutilate_append_to_file, - 'fails_like' => qr/has size \d+ on disk but size \d+ in the manifest/ + 'fails_like' => + qr/has size \d+ (on disk|in archive "[^"]+") but size \d+ in the manifest/ }, { 'name' => 'truncate_file', 'mutilate' => \&mutilate_truncate_file, - 'fails_like' => qr/has size 0 on disk but size \d+ in the manifest/ + 'fails_like' => + qr/has size 0 (on disk|in archive "[^"]+") but size \d+ in the manifest/ }, { 'name' => 'replace_file', @@ -84,21 +89,21 @@ 'name' => 'open_file_fails', 'mutilate' => \&mutilate_open_file_fails, 'fails_like' => qr/could not open file/, - 'skip_on_windows' => 1 + 'needs_unix_permissions' => 1 }, { 'name' => 'open_directory_fails', 'mutilate' => \&mutilate_open_directory_fails, 'cleanup' => \&cleanup_open_directory_fails, 'fails_like' => qr/could not open directory/, - 'skip_on_windows' => 1 + 'needs_unix_permissions' => 1 }, { 'name' => 'search_directory_fails', 'mutilate' => \&mutilate_search_directory_fails, 'cleanup' => \&cleanup_search_directory_fails, 'fails_like' => qr/could not stat file or directory/, - 'skip_on_windows' => 1 + 'needs_unix_permissions' => 1 }); for my $scenario (@scenario) @@ -108,7 +113,7 @@ SKIP: { skip "unix-style permissions not supported on Windows", 4 - if ($scenario->{'skip_on_windows'} + if ($scenario->{'needs_unix_permissions'} && ($windows_os || $Config::Config{osname} eq 'cygwin')); # Take a backup and check that it verifies OK. @@ -120,8 +125,12 @@ local $ENV{MSYS2_ARG_CONV_EXCL} = $source_ts_prefix; $primary->command_ok( [ - 'pg_basebackup', '-D', $backup_path, '--no-sync', '-cfast', - '-T', "${source_ts_path}=${backup_ts_path}" + 'pg_basebackup', + '--pgdata' => $backup_path, + '--no-sync', + '--checkpoint' => 'fast', + '--tablespace-mapping' => + "${source_ts_path}=${backup_ts_path}", ], "base backup ok"); command_ok([ 'pg_verifybackup', $backup_path ], @@ -140,7 +149,62 @@ $scenario->{'cleanup'}->($backup_path) if exists $scenario->{'cleanup'}; - # Finally, use rmtree to reclaim space. + # Turn it into a tar-format backup and see if we can still detect the + # same problem, unless the scenario needs UNIX permissions or we don't + # have a TAR program available. Note that this destructively modifies + # the backup directory. + if ( !$scenario->{'needs_unix_permissions'} + || !defined $tar + || $tar eq '') + { + my $tar_backup_path = $primary->backup_dir . '/tar_' . $name; + mkdir($tar_backup_path) || die "mkdir $tar_backup_path: $!"; + + # tar and then remove each tablespace. We remove the original files + # so that they don't also end up in base.tar. + my @tsoid = grep { $_ ne '.' && $_ ne '..' } + slurp_dir("$backup_path/pg_tblspc"); + my $cwd = getcwd; + for my $tsoid (@tsoid) + { + my $tspath = $backup_path . '/pg_tblspc/' . $tsoid; + + chdir($tspath) || die "chdir: $!"; + command_ok( + [ $tar, '-cf', "$tar_backup_path/$tsoid.tar", '.' ]); + chdir($cwd) || die "chdir: $!"; + rmtree($tspath); + } + + # tar and remove pg_wal + chdir($backup_path . '/pg_wal') || die "chdir: $!"; + command_ok([ $tar, '-cf', "$tar_backup_path/pg_wal.tar", '.' ]); + chdir($cwd) || die "chdir: $!"; + rmtree($backup_path . '/pg_wal'); + + # move the backup manifest + move( + $backup_path . '/backup_manifest', + $tar_backup_path . '/backup_manifest' + ) or die "could not copy manifest to $tar_backup_path"; + + # Construct base.tar with what's left. + chdir($backup_path) || die "chdir: $!"; + command_ok([ $tar, '-cf' => "$tar_backup_path/base.tar", '.' ]); + chdir($cwd) || die "chdir: $!"; + + # Now check that the backup no longer verifies. We must use -n + # here, because pg_waldump can't yet read WAL from a tarfile. + command_fails_like( + [ 'pg_verifybackup', '--no-parse-wal', $tar_backup_path ], + $scenario->{'fails_like'}, + "corrupt backup fails verification: $name"); + + # Use rmtree to reclaim space. + rmtree($tar_backup_path); + } + + # Use rmtree to reclaim space. rmtree($backup_path); } } diff --git a/src/bin/pg_verifybackup/t/004_options.pl b/src/bin/pg_verifybackup/t/004_options.pl index 8ed2214408ef0..3cdbe816862e1 100644 --- a/src/bin/pg_verifybackup/t/004_options.pl +++ b/src/bin/pg_verifybackup/t/004_options.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify the behavior of assorted pg_verifybackup options. @@ -16,17 +16,45 @@ $primary->start; my $backup_path = $primary->backup_dir . '/test_options'; $primary->command_ok( - [ 'pg_basebackup', '-D', $backup_path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup_path, + '--no-sync', + '--checkpoint' => 'fast' + ], "base backup ok"); -# Verify that pg_verifybackup -q succeeds and produces no output. +# Verify that pg_verifybackup --quiet succeeds and produces no output. my $stdout; my $stderr; -my $result = IPC::Run::run [ 'pg_verifybackup', '-q', $backup_path ], - '>', \$stdout, '2>', \$stderr; -ok($result, "-q succeeds: exit code 0"); -is($stdout, '', "-q succeeds: no stdout"); -is($stderr, '', "-q succeeds: no stderr"); +my $result = IPC::Run::run [ 'pg_verifybackup', '--quiet', $backup_path ], + '>' => \$stdout, + '2>' => \$stderr; +ok($result, "--quiet succeeds: exit code 0"); +is($stdout, '', "--quiet succeeds: no stdout"); +is($stderr, '', "--quiet succeeds: no stderr"); + +# Should still work if we specify --format=plain. +$primary->command_ok( + [ 'pg_verifybackup', '--format' => 'plain', $backup_path ], + "verifies with --format=plain"); + +# Should not work if we specify --format=y because that's invalid. +$primary->command_fails_like( + [ 'pg_verifybackup', '--format' => 'y', $backup_path ], + qr(invalid backup format "y", must be "plain" or "tar"), + "does not verify with --format=y"); + +# Should produce a lengthy list of errors; we test for just one of those. +$primary->command_fails_like( + [ + 'pg_verifybackup', + '--format' => 'tar', + '--no-parse-wal', + $backup_path + ], + qr("pg_multixact" is not a regular file), + "does not verify with --format=tar --no-parse-wal"); # Test invalid options command_fails_like( @@ -43,25 +71,30 @@ # Verify that pg_verifybackup -q now fails. command_fails_like( - [ 'pg_verifybackup', '-q', $backup_path ], + [ 'pg_verifybackup', '--quiet', $backup_path ], qr/checksum mismatch for file \"PG_VERSION\"/, - '-q checksum mismatch'); + '--quiet checksum mismatch'); # Since we didn't change the length of the file, verification should succeed # if we ignore checksums. Check that we get the right message, too. command_like( - [ 'pg_verifybackup', '-s', $backup_path ], + [ 'pg_verifybackup', '--skip-checksums', $backup_path ], qr/backup successfully verified/, - '-s skips checksumming'); + '--skip-checksums skips checksumming'); # Validation should succeed if we ignore the problem file. Also, check # the progress information. command_checks_all( - [ 'pg_verifybackup', '--progress', '-i', 'PG_VERSION', $backup_path ], + [ + 'pg_verifybackup', + '--progress', + '--ignore' => 'PG_VERSION', + $backup_path + ], 0, [qr/backup successfully verified/], [qr{(\d+/\d+ kB \(\d+%\) verified)+}], - '-i ignores problem file'); + '--ignore ignores problem file'); # PG_VERSION is already corrupt; let's try also removing all of pg_xact. rmtree($backup_path . "/pg_xact"); @@ -69,19 +102,25 @@ # We're ignoring the problem with PG_VERSION, but not the problem with # pg_xact, so verification should fail here. command_fails_like( - [ 'pg_verifybackup', '-i', 'PG_VERSION', $backup_path ], + [ 'pg_verifybackup', '--ignore' => 'PG_VERSION', $backup_path ], qr/pg_xact.*is present in the manifest but not on disk/, - '-i does not ignore all problems'); + '--ignore does not ignore all problems'); -# If we use -i twice, we should be able to ignore all of the problems. +# If we use --ignore twice, we should be able to ignore all of the problems. command_like( - [ 'pg_verifybackup', '-i', 'PG_VERSION', '-i', 'pg_xact', $backup_path ], + [ + 'pg_verifybackup', + '--ignore' => 'PG_VERSION', + '--ignore' => 'pg_xact', + $backup_path + ], qr/backup successfully verified/, - 'multiple -i options work'); + 'multiple --ignore options work'); -# Verify that when -i is not used, both problems are reported. +# Verify that when --ignore is not used, both problems are reported. $result = IPC::Run::run [ 'pg_verifybackup', $backup_path ], - '>', \$stdout, '2>', \$stderr; + '>' => \$stdout, + '2>' => \$stderr; ok(!$result, "multiple problems: fails"); like( $stderr, @@ -92,24 +131,28 @@ qr/checksum mismatch for file \"PG_VERSION\"/, "multiple problems: checksum mismatch reported"); -# Verify that when -e is used, only the problem detected first is reported. -$result = IPC::Run::run [ 'pg_verifybackup', '-e', $backup_path ], - '>', \$stdout, '2>', \$stderr; -ok(!$result, "-e reports 1 error: fails"); +# Verify that when --exit-on-error is used, only the problem detected +# first is reported. +$result = + IPC::Run::run [ 'pg_verifybackup', '--exit-on-error', $backup_path ], + '>' => \$stdout, + '2>' => \$stderr; +ok(!$result, "--exit-on-error reports 1 error: fails"); like( $stderr, qr/pg_xact.*is present in the manifest but not on disk/, - "-e reports 1 error: missing files reported"); + "--exit-on-error reports 1 error: missing files reported"); unlike( $stderr, qr/checksum mismatch for file \"PG_VERSION\"/, - "-e reports 1 error: checksum mismatch not reported"); + "--exit-on-error reports 1 error: checksum mismatch not reported"); # Test valid manifest with nonexistent backup directory. command_fails_like( [ - 'pg_verifybackup', '-m', - "$backup_path/backup_manifest", "$backup_path/fake" + 'pg_verifybackup', + '--manifest-path' => "$backup_path/backup_manifest", + "$backup_path/fake" ], qr/could not open directory/, 'nonexistent backup directory'); diff --git a/src/bin/pg_verifybackup/t/005_bad_manifest.pl b/src/bin/pg_verifybackup/t/005_bad_manifest.pl index c4ed64b62d5f9..d373829645402 100644 --- a/src/bin/pg_verifybackup/t/005_bad_manifest.pl +++ b/src/bin/pg_verifybackup/t/005_bad_manifest.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test the behavior of pg_verifybackup when the backup manifest has # problems. diff --git a/src/bin/pg_verifybackup/t/006_encoding.pl b/src/bin/pg_verifybackup/t/006_encoding.pl index b93d14f1492d9..c243153c5f940 100644 --- a/src/bin/pg_verifybackup/t/006_encoding.pl +++ b/src/bin/pg_verifybackup/t/006_encoding.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify that pg_verifybackup handles hex-encoded filenames correctly. @@ -15,9 +15,11 @@ my $backup_path = $primary->backup_dir . '/test_encoding'; $primary->command_ok( [ - 'pg_basebackup', '-D', - $backup_path, '--no-sync', - '-cfast', '--manifest-force-encode' + 'pg_basebackup', + '--pgdata' => $backup_path, + '--no-sync', + '--checkpoint' => 'fast', + '--manifest-force-encode', ], "backup ok with forced hex encoding"); @@ -27,7 +29,7 @@ '>', 100, "many paths are encoded in the manifest"); command_like( - [ 'pg_verifybackup', '-s', $backup_path ], + [ 'pg_verifybackup', '--skip-checksums', $backup_path ], qr/backup successfully verified/, 'backup with forced encoding verified'); diff --git a/src/bin/pg_verifybackup/t/007_wal.pl b/src/bin/pg_verifybackup/t/007_wal.pl index 18852ad5bb30e..babc4f0a86b85 100644 --- a/src/bin/pg_verifybackup/t/007_wal.pl +++ b/src/bin/pg_verifybackup/t/007_wal.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test pg_verifybackup's WAL verification. @@ -15,7 +15,12 @@ $primary->start; my $backup_path = $primary->backup_dir . '/test_wal'; $primary->command_ok( - [ 'pg_basebackup', '-D', $backup_path, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup_path, + '--no-sync', + '--checkpoint' => 'fast' + ], "base backup ok"); # Rename pg_wal. @@ -30,13 +35,17 @@ 'missing pg_wal causes failure'); # Should work if we skip WAL verification. -command_ok( - [ 'pg_verifybackup', '-n', $backup_path ], +command_ok([ 'pg_verifybackup', '--no-parse-wal', $backup_path ], 'missing pg_wal OK if not verifying WAL'); # Should also work if we specify the correct WAL location. -command_ok([ 'pg_verifybackup', '-w', $relocated_pg_wal, $backup_path ], - '-w can be used to specify WAL directory'); +command_ok( + [ + 'pg_verifybackup', + '--wal-directory' => $relocated_pg_wal, + $backup_path + ], + '--wal-directory can be used to specify WAL directory'); # Move directory back to original location. rename($relocated_pg_wal, $original_pg_wal) || die "rename pg_wal back: $!"; @@ -70,7 +79,12 @@ # The base backup run below does a checkpoint, that removes the first segment # of the current timeline. $primary->command_ok( - [ 'pg_basebackup', '-D', $backup_path2, '--no-sync', '-cfast' ], + [ + 'pg_basebackup', + '--pgdata' => $backup_path2, + '--no-sync', + '--checkpoint' => 'fast' + ], "base backup 2 ok"); command_ok( [ 'pg_verifybackup', $backup_path2 ], diff --git a/src/bin/pg_verifybackup/t/008_untar.pl b/src/bin/pg_verifybackup/t/008_untar.pl index 7a09f3b75b2a7..deed3ec247d2d 100644 --- a/src/bin/pg_verifybackup/t/008_untar.pl +++ b/src/bin/pg_verifybackup/t/008_untar.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This test case aims to verify that server-side backups and server-side # backup compression work properly, and it also aims to verify that @@ -16,6 +16,20 @@ $primary->init(allows_streaming => 1); $primary->start; +# Create a tablespace directory. +my $source_ts_path = PostgreSQL::Test::Utils::tempdir_short(); + +# Create a tablespace with table in it. +$primary->safe_psql( + 'postgres', qq( + CREATE TABLESPACE regress_ts1 LOCATION '$source_ts_path'; + SELECT oid FROM pg_tablespace WHERE spcname = 'regress_ts1'; + CREATE TABLE regress_tbl1(i int) TABLESPACE regress_ts1; + INSERT INTO regress_tbl1 VALUES(generate_series(1,5));)); +my $tsoid = $primary->safe_psql( + 'postgres', qq( + SELECT oid FROM pg_tablespace WHERE spcname = 'regress_ts1')); + my $backup_path = $primary->backup_dir . '/server-backup'; my $extract_path = $primary->backup_dir . '/extracted-backup'; @@ -23,39 +37,31 @@ { 'compression_method' => 'none', 'backup_flags' => [], - 'backup_archive' => 'base.tar', + 'backup_archive' => [ 'base.tar', "$tsoid.tar" ], 'enabled' => 1 }, { 'compression_method' => 'gzip', 'backup_flags' => [ '--compress', 'server-gzip' ], - 'backup_archive' => 'base.tar.gz', - 'decompress_program' => $ENV{'GZIP_PROGRAM'}, - 'decompress_flags' => ['-d'], + 'backup_archive' => [ 'base.tar.gz', "$tsoid.tar.gz" ], 'enabled' => check_pg_config("#define HAVE_LIBZ 1") }, { 'compression_method' => 'lz4', 'backup_flags' => [ '--compress', 'server-lz4' ], - 'backup_archive' => 'base.tar.lz4', - 'decompress_program' => $ENV{'LZ4'}, - 'decompress_flags' => [ '-d', '-m' ], + 'backup_archive' => [ 'base.tar.lz4', "$tsoid.tar.lz4" ], 'enabled' => check_pg_config("#define USE_LZ4 1") }, { 'compression_method' => 'zstd', 'backup_flags' => [ '--compress', 'server-zstd' ], - 'backup_archive' => 'base.tar.zst', - 'decompress_program' => $ENV{'ZSTD'}, - 'decompress_flags' => ['-d'], + 'backup_archive' => [ 'base.tar.zst', "$tsoid.tar.zst" ], 'enabled' => check_pg_config("#define USE_ZSTD 1") }, { 'compression_method' => 'zstd', 'backup_flags' => [ '--compress', 'server-zstd:level=1,long' ], - 'backup_archive' => 'base.tar.zst', - 'decompress_program' => $ENV{'ZSTD'}, - 'decompress_flags' => ['-d'], + 'backup_archive' => [ 'base.tar.zst', "$tsoid.tar.zst" ], 'enabled' => check_pg_config("#define USE_ZSTD 1") }); @@ -73,12 +79,14 @@ || $tc->{'decompress_program'} eq ''); # Take a server-side backup. - my @backup = ( - 'pg_basebackup', '--no-sync', - '-cfast', '--target', - "server:$backup_path", '-Xfetch'); - push @backup, @{ $tc->{'backup_flags'} }; - $primary->command_ok(\@backup, + $primary->command_ok( + [ + 'pg_basebackup', '--no-sync', + '--checkpoint' => 'fast', + '--target' => "server:$backup_path", + '--wal-method' => 'fetch', + @{ $tc->{'backup_flags'} }, + ], "server side backup, compression $method"); @@ -86,47 +94,20 @@ my $backup_files = join(',', sort grep { $_ ne '.' && $_ ne '..' } slurp_dir($backup_path)); my $expected_backup_files = - join(',', sort ('backup_manifest', $tc->{'backup_archive'})); + join(',', sort ('backup_manifest', @{ $tc->{'backup_archive'} })); is($backup_files, $expected_backup_files, "found expected backup files, compression $method"); - # Decompress. - if (exists $tc->{'decompress_program'}) - { - my @decompress = ($tc->{'decompress_program'}); - push @decompress, @{ $tc->{'decompress_flags'} } - if $tc->{'decompress_flags'}; - push @decompress, $backup_path . '/' . $tc->{'backup_archive'}; - system_or_bail(@decompress); - } - - SKIP: - { - my $tar = $ENV{TAR}; - # don't check for a working tar here, to accommodate various odd - # cases. If tar doesn't work the init_from_backup below will fail. - skip "no tar program available", 1 - if (!defined $tar || $tar eq ''); - - # Untar. - mkdir($extract_path); - system_or_bail($tar, 'xf', $backup_path . '/base.tar', - '-C', $extract_path); - - # Verify. - $primary->command_ok( - [ - 'pg_verifybackup', '-n', - '-m', "$backup_path/backup_manifest", - '-e', $extract_path - ], - "verify backup, compression $method"); - } + # Verify tar backup. + $primary->command_ok( + [ + 'pg_verifybackup', '--no-parse-wal', + '--exit-on-error', $backup_path, + ], + "verify backup, compression $method"); # Cleanup. - unlink($backup_path . '/backup_manifest'); - unlink($backup_path . '/base.tar'); - unlink($backup_path . '/' . $tc->{'backup_archive'}); + rmtree($backup_path); rmtree($extract_path); } } diff --git a/src/bin/pg_verifybackup/t/009_extract.pl b/src/bin/pg_verifybackup/t/009_extract.pl index 1d531dc20d52a..2560529121700 100644 --- a/src/bin/pg_verifybackup/t/009_extract.pl +++ b/src/bin/pg_verifybackup/t/009_extract.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This test aims to verify that the client can decompress and extract # a backup which was compressed by the server. @@ -53,19 +53,21 @@ skip "$method compression not supported by this build", 2 if !$tc->{'enabled'}; - # Take backup with server compression enabled. - my @backup = ( - 'pg_basebackup', '-D', $backup_path, - '-Xfetch', '--no-sync', '-cfast', '-Fp'); - push @backup, @{ $tc->{'backup_flags'} }; - - my @verify = ('pg_verifybackup', '-e', $backup_path); - # A backup with a valid compression method should work. my $backup_stdout = ''; my $backup_stderr = ''; - my $backup_result = $primary->run_log(\@backup, '>', \$backup_stdout, - '2>', \$backup_stderr); + my $backup_result = $primary->run_log( + [ + 'pg_basebackup', + '--pgdata' => $backup_path, + '--wal-method' => 'fetch', + '--no-sync', + '--checkpoint' => 'fast', + '--format' => 'plain', + @{ $tc->{'backup_flags'} }, + ], + '>' => \$backup_stdout, + '2>' => \$backup_stderr); if ($backup_stdout ne '') { print "# standard output was:\n$backup_stdout"; @@ -86,7 +88,8 @@ } # Make sure that it verifies OK. - $primary->command_ok(\@verify, + $primary->command_ok( + [ 'pg_verifybackup', '--exit-on-error', $backup_path ], "backup verified, compression method \"$method\""); } diff --git a/src/bin/pg_verifybackup/t/010_client_untar.pl b/src/bin/pg_verifybackup/t/010_client_untar.pl index 8c076d46dee00..d8d2b06c7ee86 100644 --- a/src/bin/pg_verifybackup/t/010_client_untar.pl +++ b/src/bin/pg_verifybackup/t/010_client_untar.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This test case aims to verify that client-side backup compression work # properly, and it also aims to verify that pg_verifybackup can verify a base @@ -29,41 +29,30 @@ 'compression_method' => 'gzip', 'backup_flags' => [ '--compress', 'client-gzip:5' ], 'backup_archive' => 'base.tar.gz', - 'decompress_program' => $ENV{'GZIP_PROGRAM'}, - 'decompress_flags' => ['-d'], 'enabled' => check_pg_config("#define HAVE_LIBZ 1") }, { 'compression_method' => 'lz4', 'backup_flags' => [ '--compress', 'client-lz4:5' ], 'backup_archive' => 'base.tar.lz4', - 'decompress_program' => $ENV{'LZ4'}, - 'decompress_flags' => ['-d'], - 'output_file' => 'base.tar', 'enabled' => check_pg_config("#define USE_LZ4 1") }, { 'compression_method' => 'zstd', 'backup_flags' => [ '--compress', 'client-zstd:5' ], 'backup_archive' => 'base.tar.zst', - 'decompress_program' => $ENV{'ZSTD'}, - 'decompress_flags' => ['-d'], 'enabled' => check_pg_config("#define USE_ZSTD 1") }, { 'compression_method' => 'zstd', 'backup_flags' => [ '--compress', 'client-zstd:level=1,long' ], 'backup_archive' => 'base.tar.zst', - 'decompress_program' => $ENV{'ZSTD'}, - 'decompress_flags' => ['-d'], 'enabled' => check_pg_config("#define USE_ZSTD 1") }, { 'compression_method' => 'parallel zstd', 'backup_flags' => [ '--compress', 'client-zstd:workers=3' ], 'backup_archive' => 'base.tar.zst', - 'decompress_program' => $ENV{'ZSTD'}, - 'decompress_flags' => ['-d'], 'enabled' => check_pg_config("#define USE_ZSTD 1"), 'possibly_unsupported' => qr/could not set compression worker count to 3: Unsupported parameter/ @@ -83,14 +72,19 @@ || $tc->{'decompress_program'} eq ''); # Take a client-side backup. - my @backup = ( - 'pg_basebackup', '-D', $backup_path, - '-Xfetch', '--no-sync', '-cfast', '-Ft'); - push @backup, @{ $tc->{'backup_flags'} }; my $backup_stdout = ''; my $backup_stderr = ''; - my $backup_result = $primary->run_log(\@backup, '>', \$backup_stdout, - '2>', \$backup_stderr); + my $backup_result = $primary->run_log( + [ + 'pg_basebackup', '--no-sync', + '--pgdata' => $backup_path, + '--wal-method' => 'fetch', + '--checkpoint' => 'fast', + '--format' => 'tar', + @{ $tc->{'backup_flags'} } + ], + '>' => \$backup_stdout, + '2>' => \$backup_stderr); if ($backup_stdout ne '') { print "# standard output was:\n$backup_stdout"; @@ -118,40 +112,13 @@ is($backup_files, $expected_backup_files, "found expected backup files, compression $method"); - # Decompress. - if (exists $tc->{'decompress_program'}) - { - my @decompress = ($tc->{'decompress_program'}); - push @decompress, @{ $tc->{'decompress_flags'} } - if $tc->{'decompress_flags'}; - push @decompress, $backup_path . '/' . $tc->{'backup_archive'}; - push @decompress, $backup_path . '/' . $tc->{'output_file'} - if $tc->{'output_file'}; - system_or_bail(@decompress); - } - - SKIP: - { - my $tar = $ENV{TAR}; - # don't check for a working tar here, to accommodate various odd - # cases. If tar doesn't work the init_from_backup below will fail. - skip "no tar program available", 1 - if (!defined $tar || $tar eq ''); - - # Untar. - mkdir($extract_path); - system_or_bail($tar, 'xf', $backup_path . '/base.tar', - '-C', $extract_path); - - # Verify. - $primary->command_ok( - [ - 'pg_verifybackup', '-n', - '-m', "$backup_path/backup_manifest", - '-e', $extract_path - ], - "verify backup, compression $method"); - } + # Verify tar backup. + $primary->command_ok( + [ + 'pg_verifybackup', '--no-parse-wal', + '--exit-on-error', $backup_path, + ], + "verify backup, compression $method"); # Cleanup. rmtree($extract_path); diff --git a/src/bin/pg_waldump/compat.c b/src/bin/pg_waldump/compat.c index 1541eac6115cb..2529d3e6d177d 100644 --- a/src/bin/pg_waldump/compat.c +++ b/src/bin/pg_waldump/compat.c @@ -3,7 +3,7 @@ * compat.c * Reimplementations of various backend functions. * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_waldump/compat.c diff --git a/src/bin/pg_waldump/meson.build b/src/bin/pg_waldump/meson.build index bb30f0fe08e87..937e0d688414e 100644 --- a/src/bin/pg_waldump/meson.build +++ b/src/bin/pg_waldump/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_waldump_sources = files( 'compat.c', diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index 1f9403fc5cf4b..51fb76efc489e 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -2,7 +2,7 @@ * * pg_waldump.c - decode and display WAL * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_waldump/pg_waldump.c @@ -610,10 +610,10 @@ XLogDumpStatsRow(const char *name, tot_len_pct = 100 * (double) tot_len / total_len; printf("%-27s " - "%20" INT64_MODIFIER "u (%6.02f) " - "%20" INT64_MODIFIER "u (%6.02f) " - "%20" INT64_MODIFIER "u (%6.02f) " - "%20" INT64_MODIFIER "u (%6.02f)\n", + "%20" PRIu64 " (%6.02f) " + "%20" PRIu64 " (%6.02f) " + "%20" PRIu64 " (%6.02f) " + "%20" PRIu64 " (%6.02f)\n", name, n, n_pct, rec_len, rec_len_pct, fpi_len, fpi_len_pct, tot_len, tot_len_pct); } @@ -742,10 +742,10 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats) fpi_len_pct = 100 * (double) total_fpi_len / total_len; printf("%-27s " - "%20" INT64_MODIFIER "u %-9s" - "%20" INT64_MODIFIER "u %-9s" - "%20" INT64_MODIFIER "u %-9s" - "%20" INT64_MODIFIER "u %-6s\n", + "%20" PRIu64 " %-9s" + "%20" PRIu64 " %-9s" + "%20" PRIu64 " %-9s" + "%20" PRIu64 " %-6s\n", "Total", stats->count, "", total_rec_len, psprintf("[%.02f%%]", rec_len_pct), total_fpi_len, psprintf("[%.02f%%]", fpi_len_pct), diff --git a/src/bin/pg_waldump/po/de.po b/src/bin/pg_waldump/po/de.po index 05af08b503ce6..8c5487e6487f4 100644 --- a/src/bin/pg_waldump/po/de.po +++ b/src/bin/pg_waldump/po/de.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_waldump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 07:49+0000\n" -"PO-Revision-Date: 2024-03-26 11:07+0100\n" +"POT-Creation-Date: 2025-04-03 12:20+0000\n" +"PO-Revision-Date: 2025-04-03 16:18+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,22 +16,22 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -47,45 +47,45 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 pg_waldump.c:199 #: pg_waldump.c:532 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #: pg_waldump.c:1104 pg_waldump.c:1127 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -452,157 +452,157 @@ msgstr "Fehler in WAL-Eintrag bei %X/%X: %s" msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: xlogreader.c:619 +#: xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ungültiger Datensatz-Offset bei %X/%X: mindestens %u erwartet, %u erhalten" -#: xlogreader.c:628 +#: xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "Contrecord angefordert von %X/%X" -#: xlogreader.c:669 xlogreader.c:1134 +#: xlogreader.c:670 xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ungültige Datensatzlänge bei %X/%X: mindestens %u erwartet, %u erhalten" -#: xlogreader.c:758 +#: xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "keine Contrecord-Flag bei %X/%X" -#: xlogreader.c:771 +#: xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "ungültige Contrecord-Länge %u (erwartet %lld) bei %X/%X" -#: xlogreader.c:1142 +#: xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ungültige Resource-Manager-ID %u bei %X/%X" -#: xlogreader.c:1155 xlogreader.c:1171 +#: xlogreader.c:1156 xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "Datensatz mit falschem Prev-Link %X/%X bei %X/%X" -#: xlogreader.c:1209 +#: xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "ungültige Resource-Manager-Datenprüfsumme in Datensatz bei %X/%X" -#: xlogreader.c:1243 +#: xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ungültige magische Zahl %04X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1258 xlogreader.c:1300 +#: xlogreader.c:1259 xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ungültige Info-Bits %04X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1274 +#: xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %llu, Datenbanksystemidentifikator in pg_control ist %llu" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %, Datenbanksystemidentifikator in pg_control ist %" -#: xlogreader.c:1282 +#: xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche Segmentgröße im Seitenkopf" -#: xlogreader.c:1288 +#: xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche XLOG_BLCKSZ im Seitenkopf" -#: xlogreader.c:1320 +#: xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "unerwartete Pageaddr %X/%X in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1346 +#: xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "Zeitleisten-ID %u außer der Reihe (nach %u) in WAL-Segment %s, LSN %X/%X, Offset %u" -#: xlogreader.c:1749 +#: xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u außer der Reihe bei %X/%X" -#: xlogreader.c:1773 +#: xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA gesetzt, aber keine Daten enthalten bei %X/%X" -#: xlogreader.c:1780 +#: xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA nicht gesetzt, aber Datenlänge ist %u bei %X/%X" -#: xlogreader.c:1816 +#: xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE gesetzt, aber Loch Offset %u Länge %u Block-Abbild-Länge %u bei %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE nicht gesetzt, aber Loch Offset %u Länge %u bei %X/%X" -#: xlogreader.c:1846 +#: xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED gesetzt, aber Block-Abbild-Länge %u bei %X/%X" -#: xlogreader.c:1861 +#: xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "weder BKPIMAGE_HAS_HOLE noch BKPIMAGE_COMPRESSED gesetzt, aber Block-Abbild-Länge ist %u bei %X/%X" -#: xlogreader.c:1877 +#: xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL gesetzt, aber keine vorangehende Relation bei %X/%X" -#: xlogreader.c:1889 +#: xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "ungültige block_id %u bei %X/%X" -#: xlogreader.c:1956 +#: xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "Datensatz mit ungültiger Länge bei %X/%X" -#: xlogreader.c:1982 +#: xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "konnte Backup-Block mit ID %d nicht im WAL-Eintrag finden" -#: xlogreader.c:2066 +#: xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "konnte Abbild bei %X/%X mit ungültigem angegebenen Block %d nicht wiederherstellen" -#: xlogreader.c:2073 +#: xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "konnte Abbild mit ungültigem Zustand bei %X/%X nicht wiederherstellen, Block %d" -#: xlogreader.c:2100 xlogreader.c:2117 +#: xlogreader.c:2110 xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "konnte Abbild bei %X/%X nicht wiederherstellen, komprimiert mit %s, nicht unterstützt von dieser Installation, Block %d" -#: xlogreader.c:2126 +#: xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "konnte Abbild bei %X/%X nicht wiederherstellen, komprimiert mit unbekannter Methode, Block %d" -#: xlogreader.c:2134 +#: xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "konnte Abbild bei %X/%X nicht dekomprimieren, Block %d" diff --git a/src/bin/pg_waldump/po/es.po b/src/bin/pg_waldump/po/es.po index 67a0cf3e2b0f5..18864a7bcd4a6 100644 --- a/src/bin/pg_waldump/po/es.po +++ b/src/bin/pg_waldump/po/es.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_waldump (PostgreSQL) 16\n" +"Project-Id-Version: pg_waldump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:18+0000\n" -"PO-Revision-Date: 2023-09-05 07:35+0200\n" +"POT-Creation-Date: 2025-02-16 19:48+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -40,6 +40,60 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -55,74 +109,74 @@ msgstr "el directorio «%s» existe pero no está vacío" msgid "could not access directory \"%s\": %m" msgstr "no se pudo acceder al directorio «%s»: %m" -#: pg_waldump.c:199 pg_waldump.c:527 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "no se pudo abrir el archivo «%s»: %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "el archivo WAL «%s» especifica un tamaño de segmento de WAL no válido (%d byte)" +msgstr[1] "el archivo WAL «%s» especifica un tamaño de segmento de WAL no válido (%d bytes)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes" -msgstr[0] "el tamaño de segmento WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero la cabecera del archivo WAL «%s» especifica %d byte" -msgstr[1] "el tamaño de segmento WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero la cabecera del archivo WAL «%s» especifica %d bytes" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "El tamaño de segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "no se pudo leer el archivo «%s»: %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "no se pudo leer el archivo «%s»: leídos %d de %d" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "no se pudo ubicar el archivo WAL «%s»" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "no se pudo encontrar ningún archivo WAL" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "no se pudo encontrar el archivo «%s»: %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" +msgid "could not read from file \"%s\", offset %d: %m" msgstr "no se pudo leer desde el archivo «%s» en la posición %d: %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" -msgstr "no se pudo leer del archivo %s, posición %d: leídos %d de %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" +msgstr "no se pudo leer del archivo «%s», posición %d: leídos %d de %d" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "número de “fork” no válido: %u" -#: pg_waldump.c:530 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "no se pudo escribir el archivo «%s»: %m" -#: pg_waldump.c:533 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "no se pudo cerrar el archivo «%s»: %m" -#: pg_waldump.c:753 +#: pg_waldump.c:758 #, c-format msgid "" "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n" @@ -131,17 +185,17 @@ msgstr "" "%s decodifica y muestra segmentos de WAL de PostgreSQL para depuración.\n" "\n" -#: pg_waldump.c:755 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: pg_waldump.c:756 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [OPCIÓN]... [SEGINICIAL [SEGFINAL]]\n" -#: pg_waldump.c:757 +#: pg_waldump.c:762 #, c-format msgid "" "\n" @@ -150,29 +204,29 @@ msgstr "" "\n" "Opciones:\n" -#: pg_waldump.c:758 +#: pg_waldump.c:763 #, c-format msgid " -b, --bkp-details output detailed information about backup blocks\n" msgstr " -b, --bkp-details mostrar información detallada sobre bloques de respaldo\n" -#: pg_waldump.c:759 +#: pg_waldump.c:764 #, c-format msgid " -B, --block=N with --relation, only show records that modify block N\n" msgstr "" " -B, --block=N con --relation, sólo mostrar registros que modifican\n" " el bloque N\n" -#: pg_waldump.c:760 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr " -e, --end=RECPTR detener la lectura del WAL en la posición RECPTR\n" -#: pg_waldump.c:761 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr " -f, --follow seguir reintentando después de alcanzar el final del WAL\n" -#: pg_waldump.c:762 +#: pg_waldump.c:767 #, c-format msgid "" " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" @@ -181,12 +235,12 @@ msgstr "" " -F, --form=FORK sólo mostrar registros que modifican bloques en el\n" " «fork» FORK; nombres válidos son main, fsm, vm, init\n" -#: pg_waldump.c:764 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N número de registros a mostrar\n" -#: pg_waldump.c:765 +#: pg_waldump.c:770 #, c-format msgid "" " -p, --path=PATH directory in which to find WAL segment files or a\n" @@ -197,12 +251,12 @@ msgstr "" " contenga un directorio ./pg_wal con dichos archivos\n" " (por omisión: directorio actual, ./pg_wal, $PGDATA/pg_wal)\n" -#: pg_waldump.c:768 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet no escribir ningún mensaje, excepto errores\n" -#: pg_waldump.c:769 +#: pg_waldump.c:774 #, c-format msgid "" " -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n" @@ -211,17 +265,17 @@ msgstr "" " -r, --rmgr=GREC sólo mostrar registros generados por el gestor de\n" " recursos GREC; use --rmgr=list para listar nombres válidos\n" -#: pg_waldump.c:771 +#: pg_waldump.c:776 #, c-format msgid " -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n" msgstr " -R, --relation=T/D/R sólo mostrar registros que modifican bloques en relación T/D/R\n" -#: pg_waldump.c:772 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr " -s, --start=RECPTR empezar a leer el WAL en la posición RECPTR\n" -#: pg_waldump.c:773 +#: pg_waldump.c:778 #, c-format msgid "" " -t, --timeline=TLI timeline from which to read WAL records\n" @@ -230,22 +284,22 @@ msgstr "" " -t, --timeline=TLI “timeline” del cual leer registros WAL\n" " (por omisión: 1 o el valor usado en SEGINICIAL)\n" -#: pg_waldump.c:775 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión, luego salir\n" -#: pg_waldump.c:776 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr " -w, --fullpage sólo mostrar registros con escrituras de página completa\n" -#: pg_waldump.c:777 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr " -x, --xid=XID sólo mostrar registros con el id de transacción XID\n" -#: pg_waldump.c:778 +#: pg_waldump.c:783 #, c-format msgid "" " -z, --stats[=record] show statistics instead of records\n" @@ -254,17 +308,17 @@ msgstr "" " -z, --stats[=registro] mostrar estadísticas en lugar de registros\n" " (opcionalmente, mostrar estadísticas por registro)\n" -#: pg_waldump.c:780 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr " --save-fullpage=DIR guardar imágenes de página completa en DIR\n" -#: pg_waldump.c:781 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda, luego salir\n" -#: pg_waldump.c:782 +#: pg_waldump.c:787 #, c-format msgid "" "\n" @@ -273,304 +327,284 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: pg_waldump.c:783 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: pg_waldump.c:879 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "no se especificó ningún argumento" -#: pg_waldump.c:895 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "número de bloque no válido: «%s»" -#: pg_waldump.c:904 pg_waldump.c:1002 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "ubicación de WAL no válida: «%s»" -#: pg_waldump.c:917 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "nombre de «fork» no válido: «%s»" -#: pg_waldump.c:925 pg_waldump.c:1028 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "el valor «%s» no es válido para la opción «%s»" -#: pg_waldump.c:956 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "el gestor de recursos personalizado «%s» no existe" -#: pg_waldump.c:977 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "el gestor de recursos «%s» no existe" -#: pg_waldump.c:992 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "especificación de relación no válida: «%s»" -#: pg_waldump.c:993 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "Se esperaba «OID de tablespace/OID de base de datos/filenode de relación»." -#: pg_waldump.c:1035 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "%s debe estar en el rango %u..%u" -#: pg_waldump.c:1050 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "especificación de ID de transacción no válida: «%s»" -#: pg_waldump.c:1065 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "valor no reconocido para la opción %s: %s" -#: pg_waldump.c:1082 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "la opción %s requiere que se especifique la opción %s" -#: pg_waldump.c:1089 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: pg_waldump.c:1099 pg_waldump.c:1122 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "no se pudo abrir el directorio «%s»: %m" - -#: pg_waldump.c:1128 pg_waldump.c:1158 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "no se pudo abrir el archivo «%s»" -#: pg_waldump.c:1138 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "la posición inicial de WAL %X/%X no está en el archivo «%s»" -#: pg_waldump.c:1165 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "SEGFINAL %s está antes del SEGINICIAL %s" -#: pg_waldump.c:1180 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "la posición final de WAL %X/%X no está en el archivo «%s»" -#: pg_waldump.c:1192 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "no se especificó posición inicial de WAL" -#: pg_waldump.c:1206 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "se agotó la memoria mientras se emplazaba un procesador de lectura de WAL" -#: pg_waldump.c:1212 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" msgstr "no se pudo encontrar un registro válido después de %X/%X" -#: pg_waldump.c:1222 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" -msgstr[0] "el primer registro está ubicado después de %X/%X, en %X/%X, saltándose %u byte\n" -msgstr[1] "el primer registro está ubicado después de %X/%X, en %X/%X, saltándose %u bytes\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" +msgstr[0] "el primer registro está ubicado después de %X/%X, en %X/%X, saltándose %u byte" +msgstr[1] "el primer registro está ubicado después de %X/%X, en %X/%X, saltándose %u bytes" -#: pg_waldump.c:1307 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "error en registro de WAL en %X/%X: %s" -#: pg_waldump.c:1316 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "desplazamiento de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord solicitado por %X/%X" -#: xlogreader.c:676 xlogreader.c:1123 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "largo de registro no válido en %X/%X: se esperaba al menos %u, se obtuvo %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "memoria agotada mientras se intentaba decodificar un registro de largo %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "largo de registro %u en %X/%X demasiado largo" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "no hay bandera de contrecord en %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "largo de contrecord %u no válido (se esperaba %lld) en %X/%X" -#: xlogreader.c:924 -#, c-format -msgid "missing contrecord at %X/%X" -msgstr "falta contrecord en %X/%X" - -#: xlogreader.c:1131 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ID de gestor de recursos %u no válido en %X/%X" -#: xlogreader.c:1144 xlogreader.c:1160 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "registro con prev-link %X/%X incorrecto en %X/%X" -#: xlogreader.c:1196 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "suma de verificación de los datos del gestor de recursos incorrecta en el registro en %X/%X" -#: xlogreader.c:1230 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "número mágico %04X no válido en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1245 xlogreader.c:1287 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "info bits %04X no válidos en segment WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1261 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "archivo WAL es de un sistema de bases de datos distinto: identificador de sistema en archivo WAL es %llu, identificador en pg_control es %llu" -#: xlogreader.c:1269 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: tamaño de segmento incorrecto en cabecera de paǵina" -#: xlogreader.c:1275 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "archivo WAL es de un sistema de bases de datos distinto: XLOG_BLCKSZ incorrecto en cabecera de paǵina" -#: xlogreader.c:1307 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "pageaddr %X/%X inesperado en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1333 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "ID de timeline %u fuera de secuencia (después de %u) en segmento WAL %s, LSN %X/%X, posición %u" -#: xlogreader.c:1739 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u fuera de orden en %X/%X" -#: xlogreader.c:1763 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA está definido, pero no hay datos en %X/%X" -#: xlogreader.c:1770 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA no está definido, pero el largo de los datos es %u en %X/%X" -#: xlogreader.c:1806 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE está definido, pero posición del agujero es %u largo %u largo de imagen %u en %X/%X" -#: xlogreader.c:1822 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE no está definido, pero posición del agujero es %u largo %u en %X/%X" -#: xlogreader.c:1836 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED definido, pero largo de imagen de bloque es %u en %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_COMPRESSED están definidos, pero el largo de imagen de bloque es %u en %X/%X" -#: xlogreader.c:1867 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL está definido, pero no hay «rel» anterior en %X/%X " -#: xlogreader.c:1879 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "block_id %u no válido en %X/%X" -#: xlogreader.c:1946 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "registro con largo no válido en %X/%X" -#: xlogreader.c:1972 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "no se pudo localizar un bloque de respaldo con ID %d en el registro WAL" -#: xlogreader.c:2056 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" -msgstr "no se pudo restaurar imagen en %X/%X con bloque especificado %d no válido" +msgstr "no se pudo restaurar la imagen en %X/%X con bloque especificado %d no válido" -#: xlogreader.c:2063 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" -msgstr "no se pudo restaurar imagen en %X/%X con estado no válido, bloque %d" +msgstr "no se pudo restaurar la imagen en %X/%X con estado no válido, bloque %d" -#: xlogreader.c:2090 xlogreader.c:2107 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" -msgstr "no se pudo restaurar imagen en %X/%X comprimida con %s no soportado por esta instalación, bloque %d" +msgstr "no se pudo restaurar la imagen en %X/%X comprimida con %s que no está soportado por esta instalación, bloque %d" -#: xlogreader.c:2116 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" -msgstr "no se pudo restaurar imagen en %X/%X comprimida método desconocido, bloque %d" +msgstr "no se pudo restaurar la imagen en %X/%X comprimida con un método desconocido, bloque %d" -#: xlogreader.c:2124 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" -msgstr "no se pudo descomprimir imagen en %X/%X, bloque %d" +msgstr "no se pudo descomprimir la imagen en %X/%X, bloque %d" diff --git a/src/bin/pg_waldump/po/fr.po b/src/bin/pg_waldump/po/fr.po index b5cb1c6a017c0..f127e5e7aabe5 100644 --- a/src/bin/pg_waldump/po/fr.po +++ b/src/bin/pg_waldump/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:18+0000\n" -"PO-Revision-Date: 2023-09-05 07:50+0200\n" +"POT-Creation-Date: 2024-08-22 10:19+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -41,6 +41,60 @@ msgstr "détail : " msgid "hint: " msgstr "astuce : " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -56,74 +110,74 @@ msgstr "le répertoire « %s » existe mais n'est pas vide" msgid "could not access directory \"%s\": %m" msgstr "n'a pas pu accéder au répertoire « %s » : %m" -#: pg_waldump.c:199 pg_waldump.c:528 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "n'a pas pu ouvrir le fichier « %s » : %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "taille invalide du segment WAL dans le fichier WAL « %s » (%d octet)" +msgstr[1] "taille invalide du segment WAL dans le fichier WAL « %s » (%d octets)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes" -msgstr[0] "La taille du segment WAL doit être une puissance de deux entre 1 Mo et 1 Go, mais l'en-tête du fichier WAL « %s » indique %d octet" -msgstr[1] "La taille du segment WAL doit être une puissance de deux entre 1 Mo et 1 Go, mais l'en-tête du fichier WAL « %s » indique %d octets" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "n'a pas pu lire le fichier « %s » : %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %d" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "n'a pas pu trouver le fichier WAL « %s »" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "n'a pas pu trouver un seul fichier WAL" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "n'a pas pu trouver le fichier « %s » : %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" -msgstr "n'a pas pu lire à partir du fichier %s, décalage %d : %m" +msgid "could not read from file \"%s\", offset %d: %m" +msgstr "n'a pas pu lire à partir du fichier « %s », décalage %d : %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" -msgstr "n'a pas pu lire à partir du fichier %s, décalage %d : %d lu sur %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" +msgstr "n'a pas pu lire à partir du fichier « %s », décalage %d : %d lu sur %d" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "numéro du fork invalide : %u" -#: pg_waldump.c:531 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "impossible d'écrire le fichier « %s » : %m" -#: pg_waldump.c:534 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "n'a pas pu fermer le fichier « %s » : %m" -#: pg_waldump.c:754 +#: pg_waldump.c:758 #, c-format msgid "" "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n" @@ -133,17 +187,17 @@ msgstr "" "débogage.\n" "\n" -#: pg_waldump.c:756 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: pg_waldump.c:757 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [OPTION]... [SEG_DEBUT [SEG_FIN]]\n" -#: pg_waldump.c:758 +#: pg_waldump.c:762 #, c-format msgid "" "\n" @@ -152,35 +206,35 @@ msgstr "" "\n" "Options :\n" -#: pg_waldump.c:759 +#: pg_waldump.c:763 #, c-format msgid " -b, --bkp-details output detailed information about backup blocks\n" msgstr "" " -b, --bkp-details affiche des informations détaillées sur les\n" " blocs de sauvegarde\n" -#: pg_waldump.c:760 +#: pg_waldump.c:764 #, c-format msgid " -B, --block=N with --relation, only show records that modify block N\n" msgstr "" " -B, --block=N avec --relation, affiche seulement les enregistrements\n" " qui modifient le bloc N\n" -#: pg_waldump.c:761 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr "" " -e, --end=RECPTR arrête la lecture des journaux de transactions à\n" " l'emplacement RECPTR\n" -#: pg_waldump.c:762 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr "" " -f, --follow continue après avoir atteint la fin des journaux\n" " de transactions\n" -#: pg_waldump.c:763 +#: pg_waldump.c:767 #, c-format msgid "" " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" @@ -190,12 +244,12 @@ msgstr "" " des blocs dans le fork FORK ;\n" " les noms valides sont main, fsm, vm, init\n" -#: pg_waldump.c:765 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N nombre d'enregistrements à afficher\n" -#: pg_waldump.c:766 +#: pg_waldump.c:770 #, c-format msgid "" " -p, --path=PATH directory in which to find WAL segment files or a\n" @@ -208,12 +262,12 @@ msgstr "" " défaut : répertoire courant, ./pg_wal,\n" " $PGDATA/pg_wal)\n" -#: pg_waldump.c:769 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet n'écrit aucun message, sauf en cas d'erreur\n" -#: pg_waldump.c:770 +#: pg_waldump.c:774 #, c-format msgid "" " -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n" @@ -224,21 +278,21 @@ msgstr "" " --rmgr=list pour avoir une liste des noms valides\n" " de gestionnaires de ressources\n" -#: pg_waldump.c:772 +#: pg_waldump.c:776 #, c-format msgid " -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n" msgstr "" " -R, --relation=T/D/R affiche seulement les enregistrements qui modifient\n" " les blocs de la relation T/D/R\n" -#: pg_waldump.c:773 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr "" " -s, --start=RECPTR commence à lire à l'emplacement RECPTR des\n" " journaux de transactions\n" -#: pg_waldump.c:774 +#: pg_waldump.c:778 #, c-format msgid "" " -t, --timeline=TLI timeline from which to read WAL records\n" @@ -248,26 +302,26 @@ msgstr "" " enregistrements des journaux (par défaut : 1 ou\n" " la valeur utilisée dans SEG_DÉBUT)\n" -#: pg_waldump.c:776 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: pg_waldump.c:777 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr "" " -w, --fullpage affiche seulement les enregistrements avec\n" " un bloc complet (FPW)\n" -#: pg_waldump.c:778 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr "" " -x, --xid=XID affiche seulement des enregistrements avec\n" " l'identifiant de transaction XID\n" -#: pg_waldump.c:779 +#: pg_waldump.c:783 #, c-format msgid "" " -z, --stats[=record] show statistics instead of records\n" @@ -277,17 +331,17 @@ msgstr "" " d'enregistrements (en option, affiche des\n" " statistiques par enregistrement)\n" -#: pg_waldump.c:781 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr " --save-fullpage=RÉP sauvegarde les images complètes dans RÉP\n" -#: pg_waldump.c:782 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: pg_waldump.c:783 +#: pg_waldump.c:787 #, c-format msgid "" "\n" @@ -296,398 +350,286 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: pg_waldump.c:784 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: pg_waldump.c:880 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "aucun argument spécifié" -#: pg_waldump.c:896 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "numéro de bloc invalide : « %s »" -#: pg_waldump.c:905 pg_waldump.c:1003 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "emplacement WAL invalide : « %s »" -#: pg_waldump.c:918 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "nom du fork invalide : « %s »" -#: pg_waldump.c:926 pg_waldump.c:1029 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "valeur « %s » invalide pour l'option %s" -#: pg_waldump.c:957 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "le gestionnaire de ressources personnalisé « %s » n'existe pas" -#: pg_waldump.c:978 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "le gestionnaire de ressources « %s » n'existe pas" -#: pg_waldump.c:993 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "spécification de relation invalide : « %s »" -#: pg_waldump.c:994 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "Attendait « OID tablespace/OID base/filenode relation »." -#: pg_waldump.c:1036 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "%s doit être compris entre %u et %u" -#: pg_waldump.c:1051 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "spécification d'identifiant de transaction invalide : « %s »" -#: pg_waldump.c:1066 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "valeur non reconnue pour l'option %s : %s" -#: pg_waldump.c:1083 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "l'option %s requiert la spécification de l'option %s" -#: pg_waldump.c:1090 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: pg_waldump.c:1100 pg_waldump.c:1123 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" - -#: pg_waldump.c:1129 pg_waldump.c:1159 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "n'a pas pu ouvrir le fichier « %s »" -#: pg_waldump.c:1139 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "l'emplacement de début des journaux de transactions %X/%X n'est pas à l'intérieur du fichier « %s »" -#: pg_waldump.c:1166 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "SEG_FIN %s est avant SEG_DÉBUT %s" -#: pg_waldump.c:1181 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "l'emplacement de fin des journaux de transactions %X/%X n'est pas à l'intérieur du fichier « %s »" -#: pg_waldump.c:1193 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "pas d'emplacement donné de début du journal de transactions" -#: pg_waldump.c:1207 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "plus de mémoire lors de l'allocation d'un processeur de lecture de journaux de transactions" -#: pg_waldump.c:1213 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" msgstr "n'a pas pu trouver un enregistrement valide après %X/%X" -#: pg_waldump.c:1223 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" -msgstr[0] "le premier enregistrement se trouve après %X/%X, à %X/%X, ignore %u octet\n" -msgstr[1] "le premier enregistrement se trouve après %X/%X, à %X/%X, ignore %u octets\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" +msgstr[0] "le premier enregistrement se trouve après %X/%X, à %X/%X, ignore %u octet" +msgstr[1] "le premier enregistrement se trouve après %X/%X, à %X/%X, ignore %u octets" -#: pg_waldump.c:1308 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "erreur dans l'enregistrement des journaux de transactions à %X/%X : %s" -#: pg_waldump.c:1317 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "décalage invalide de l'enregistrement à %X/%X : attendait au moins %u, a eu %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "« contrecord » est requis par %X/%X" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "longueur invalide de l'enregistrement à %X/%X : attendait au moins %u, a eu %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "manque mémoire lors de la tentative de décodage d'un enregistrement de longueur %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "longueur trop importante de l'enregistrement %u à %X/%X" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "il n'existe pas de drapeau contrecord à %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "longueur %u invalide du contrecord (%lld attendu) à %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "identifiant du gestionnaire de ressources invalide %u à %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "enregistrement avec prev-link %X/%X incorrect à %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "" "somme de contrôle des données du gestionnaire de ressources incorrecte à\n" "l'enregistrement %X/%X" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "numéro magique invalide %04X dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "bits d'information %04X invalides dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "Le fichier WAL provient d'une instance différente : l'identifiant système de la base dans le fichier WAL est %llu, alors que l'identifiant système de la base dans pg_control est %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "Le fichier WAL provient d'une instance différente : taille invalide du segment dans l'en-tête de page" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "Le fichier WAL provient d'une instance différente : XLOG_BLCKSZ incorrect dans l'en-tête de page" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "pageaddr %X/%X inattendue dans le journal de transactions %s, LSN %X/%X, segment %u" -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "identifiant timeline %u hors de la séquence (après %u) dans le segment WAL %s, LSN %X/%X, décalage %u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "block_id %u désordonné à %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA configuré, mais aucune donnée inclus à %X/%X" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA non configuré, mais la longueur des données est %u à %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE activé, mais décalage trou %u longueur %u longueur image bloc %u à %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE désactivé, mais décalage trou %u longueur %u à %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL configuré, mais pas de relation précédente à %X/%X" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "block_id %u invalide à %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "enregistrement de longueur invalide à %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "n'a pas pu localiser le bloc de sauvegarde d'ID %d dans l'enregistrement WAL" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "n'a pas pu restaurer l'image à %X/%X avec le bloc invalide %d indiqué" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X avec un état invalide, bloc %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X compressé avec %s, qui est non supporté par le serveur, bloc %d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "n'a pas pu restaurer l'image à %X/%X compressé avec une méthode inconnue, bloc %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "n'a pas pu décompresser l'image à %X/%X, bloc %d" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid "%s: FATAL: " -#~ msgstr "%s : FATAL : " - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#~ msgid "cannot open directory \"%s\": %s" -#~ msgstr "ne peut pas ouvrir le répertoire « %s » : %s" - -#~ msgid "could not open directory \"%s\": %s" -#~ msgstr "n'a pas pu ouvrir le répertoire « %s » : %s" - -#~ msgid "could not open file \"%s\": %s" -#~ msgstr "n'a pas pu ouvrir le fichier « %s » : %s" - -#, c-format -#~ msgid "could not parse \"%s\" as a transaction ID" -#~ msgstr "n'a pas pu analyser « %s » comme un identifiant de transaction" - -#, c-format -#~ msgid "could not parse end WAL location \"%s\"" -#~ msgstr "n'a pas pu analyser l'emplacement de fin du journal de transactions « %s »" - -#, c-format -#~ msgid "could not parse fork \"%s\"" -#~ msgstr "n'a pas pu analyser le fork « %s »" - -#, c-format -#~ msgid "could not parse limit \"%s\"" -#~ msgstr "n'a pas pu analyser la limite « %s »" - -#, c-format -#~ msgid "could not parse start WAL location \"%s\"" -#~ msgstr "n'a pas pu analyser l'emplacement de début du journal de transactions « %s »" - -#, c-format -#~ msgid "could not parse timeline \"%s\"" -#~ msgstr "n'a pas pu analyser la timeline « %s »" - -#, c-format -#~ msgid "could not parse valid block number \"%s\"" -#~ msgstr "n'a pas pu analyser le numéro de bloc valide « %s »" - -#~ msgid "could not read file \"%s\": %s" -#~ msgstr "n'a pas pu lire le fichier « %s » : %s" - -#, c-format -#~ msgid "could not read file \"%s\": read %d of %zu" -#~ msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu" - -#~ msgid "could not read from log file %s, offset %u, length %d: %s" -#~ msgstr "n'a pas pu lire à partir du segment %s du journal de transactions, décalage %u, longueur %d : %s" - -#~ msgid "could not seek in log file %s to offset %u: %s" -#~ msgstr "n'a pas pu se déplacer dans le fichier de transactions %s au décalage %u : %s" - -#~ msgid "could not seek in log segment %s to offset %u: %s" -#~ msgstr "n'a pas pu rechercher dans le segment %s du journal de transactions au décalage %u : %s" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#, c-format -#~ msgid "invalid record offset at %X/%X" -#~ msgstr "décalage invalide de l'enregistrement %X/%X" - -#, c-format -#~ msgid "invalid timeline specification: \"%s\"" -#~ msgstr "spécification de timeline invalide : « %s »" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "contrecord manquant à %X/%X" - -#~ msgid "not enough data in file \"%s\"" -#~ msgstr "données insuffisantes dans le fichier « %s »" - -#, c-format -#~ msgid "out of memory" -#~ msgstr "mémoire épuisée" - -#~ msgid "path \"%s\" could not be opened: %s" -#~ msgstr "le chemin « %s » n'a pas pu être ouvert : %s" - -#, c-format -#~ msgid "unrecognized argument to --stats: %s" -#~ msgstr "argument non reconnu pour --stats : %s" diff --git a/src/bin/pg_waldump/po/ka.po b/src/bin/pg_waldump/po/ka.po index 7b605d657b894..5a73cda44f76c 100644 --- a/src/bin/pg_waldump/po/ka.po +++ b/src/bin/pg_waldump/po/ka.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_waldump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-11 09:48+0000\n" -"PO-Revision-Date: 2024-02-11 16:23+0100\n" +"POT-Creation-Date: 2025-03-29 21:20+0000\n" +"PO-Revision-Date: 2025-03-30 01:31+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,28 +16,82 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "გაფრთხილება: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" + +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "ფაილის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:75 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" + +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" + +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/file_utils.c:520 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "გადარქმევის შეცდომა %s - %s: %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -53,11 +107,6 @@ msgstr "საქაღალდე \"%s\" არსებობს, მაგ msgid "could not access directory \"%s\": %m" msgstr "საქაღალდის (%s) წვდომის შეცდომა: %m" -#: pg_waldump.c:199 pg_waldump.c:532 -#, c-format -msgid "could not open file \"%s\": %m" -msgstr "ფაილის (%s) გახსნის შეცდომა: %m" - #: pg_waldump.c:256 #, c-format msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" @@ -349,11 +398,6 @@ msgstr "პარამეტრს %s თავის მხრივ სჭი msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: pg_waldump.c:1104 pg_waldump.c:1127 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" - #: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" @@ -406,157 +450,157 @@ msgstr "შეცდომა WAL ჩანაწერში %X/%X: %s" msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: xlogreader.c:621 +#: xlogreader.c:620 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი წანაცვლება მისამართზე %X/%X: მოველოდი მინიმუმ %u, მივიღე %u" -#: xlogreader.c:630 +#: xlogreader.c:629 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord მოთხოვნილია %X/%X-ის მიერ" -#: xlogreader.c:671 xlogreader.c:1136 +#: xlogreader.c:670 xlogreader.c:1135 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ჩანაწერის არასწორი სიგრძე მისამართზე %X/%X: მოველოდი მინიმუმ %u, მივიღე %u" -#: xlogreader.c:760 +#: xlogreader.c:759 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "contrecord ალამი მისამართზე %X/%X არ არსებობს" -#: xlogreader.c:773 +#: xlogreader.c:772 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "contrecord -ის არასწორი სიგრძე %u (მოველოდი %lld) მისამართზე %X/%X" -#: xlogreader.c:1144 +#: xlogreader.c:1143 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "რესურსის მმართველის არასწორი ID %u მისამართზე %X/%X" -#: xlogreader.c:1157 xlogreader.c:1173 +#: xlogreader.c:1156 xlogreader.c:1172 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "ჩანაწერი არასწორი წინა ბმულით %X/%X მისამართზე %X/%X" -#: xlogreader.c:1211 +#: xlogreader.c:1210 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "რესურსის მმართველის მონაცემების არასწორი საკონტროლო რიცხვი ჩანაწერში მისამართზე %X/%X" -#: xlogreader.c:1245 +#: xlogreader.c:1244 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი მაგიური რიცხვი %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1260 xlogreader.c:1302 +#: xlogreader.c:1259 xlogreader.c:1301 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "არასწორი საინფორმაციო ბიტები %04X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1276 +#: xlogreader.c:1275 #, c-format -msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" -msgstr "WAL ფაილი სხვა ბაზიდანაა: WAL ფაილის ბაზის იდენტიფიკატორია %llu, pg_control-ის ბაზის სისტემის იდენტიფიკატორი კი %llu" +msgid "WAL file is from different database system: WAL file database system identifier is %, pg_control database system identifier is %" +msgstr "WAL ფაილი სხვა ბაზიდანაა: WAL ფაილის ბაზის იდენტიფიკატორია %, pg_control-ის ბაზის სისტემის იდენტიფიკატორი კი %" -#: xlogreader.c:1284 +#: xlogreader.c:1283 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL ფაილი სხვა ბაზის სიტემიდანაა: სეგმანტის არასწორი ზომა გვერდის თავსართში" -#: xlogreader.c:1290 +#: xlogreader.c:1289 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL ფაილი სხვა მონაცემთა ბაზის სისტემიდანაა: გვერდის თავსართში მითითებული XLOG_BLKSZ არასწორია" -#: xlogreader.c:1322 +#: xlogreader.c:1321 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "მოულოდნელი pageaddr %X/%X ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1348 +#: xlogreader.c:1347 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "მიმდევრობის-გარე დროის ხაზის ID %u (%u-ის შემდეგ) ჟურნალის სეგმენტში %s, LSN %X/%X, წანაცვლება %u" -#: xlogreader.c:1754 +#: xlogreader.c:1759 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ურიგო block_id %u მისამართზე %X/%X" -#: xlogreader.c:1778 +#: xlogreader.c:1783 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ მონაცემები მისამართზე %X/%X არ არსებობს" -#: xlogreader.c:1785 +#: xlogreader.c:1790 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA დაყენებულია, მაგრამ არსებობს მონაცემები სიგრძით %u მისამართზე %X/%X" -#: xlogreader.c:1821 +#: xlogreader.c:1826 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებულია, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u ბლოკის ასლის სიგრძე %u მისამართზე %X/%X" -#: xlogreader.c:1837 +#: xlogreader.c:1842 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE დაყენებული არაა, მაგრამ ნახვრეტის წანაცვლება %u სიგრძე %u მისანართზე %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1856 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED დაყენებულია, მაგრამ ბლოკის ასლის სიგრძეა %u მისამართზე %X/%X" -#: xlogreader.c:1866 +#: xlogreader.c:1871 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "არც BKPIMAGE_HAS_HOLE და არც BKPIMAGE_COMPRESSED დაყენებული არაა, მაგრამ ბლოკის ასლის სიგრძე %u-ა, მისამართზე %X/%X" -#: xlogreader.c:1882 +#: xlogreader.c:1887 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL დაყენებულია, მაგრამ წინა მნიშვნელობა მითითებული არაა მისამართზე %X/%X" -#: xlogreader.c:1894 +#: xlogreader.c:1899 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "არასწორი block_id %u %X/%X" -#: xlogreader.c:1961 +#: xlogreader.c:1966 #, c-format msgid "record with invalid length at %X/%X" msgstr "ჩანაწერი არასწორი სიგრძით მისამართზე %X/%X" -#: xlogreader.c:1987 +#: xlogreader.c:1992 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "შეცდომა WAL ჩანაწერში მარქაფი ბლოკის, ID-ით %d, მოძებნისას" -#: xlogreader.c:2071 +#: xlogreader.c:2076 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X, როცა მითითებულია არასწორი ბლოკი %d" -#: xlogreader.c:2078 +#: xlogreader.c:2083 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X არასწორი მდგომარეობით, ბლოკი %d" -#: xlogreader.c:2105 xlogreader.c:2122 +#: xlogreader.c:2110 xlogreader.c:2127 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "%3$s მეთოდით შეკუმშული ასლის აღდგენა მისამართზე %1$X/%2$X, ბლოკი %4$d შეუძლებელია. მხარდაუჭერელია ამ აგების მიერ" -#: xlogreader.c:2131 +#: xlogreader.c:2136 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "შეუძლებელია ასლის აღდგენა მისამართზე %X/%X, შეკუმშულია უცნობი მეთოდით, ბლოკი %d" -#: xlogreader.c:2139 +#: xlogreader.c:2144 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "შეუძლებელია ასლის გაშლა მისამართზე %X/%X, ბლოკი %d" diff --git a/src/bin/pg_waldump/po/ko.po b/src/bin/pg_waldump/po/ko.po index 3594b9bc3ceba..25e4c0cfe2c95 100644 --- a/src/bin/pg_waldump/po/ko.po +++ b/src/bin/pg_waldump/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pg_waldump (PostgreSQL) 16\n" +"Project-Id-Version: pg_waldump (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:48+0000\n" -"PO-Revision-Date: 2023-05-26 13:22+0900\n" +"POT-Creation-Date: 2025-01-17 04:48+0000\n" +"PO-Revision-Date: 2025-01-16 14:06+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -37,6 +37,60 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "널 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위해 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일 상태 값을 구할 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -52,96 +106,90 @@ msgstr "\"%s\" 디렉터리가 있지만, 비어있지 않음" msgid "could not access directory \"%s\": %m" msgstr "\"%s\" 디렉터리에 접근 할 수 없음: %m" -#: pg_waldump.c:199 pg_waldump.c:528 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "\"%s\" 파일을 열 수 없음: %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "\"%s\" WAL 파일 안에 잘못된 WAL 조각 크기 (%d 바이트)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL " -"file \"%s\" header specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL " -"file \"%s\" header specifies %d bytes" -msgstr[0] "" -"WAL 조각 파일 크기는 1MB에서 1GB사이 2^n 이어야하지만, \"%s\" WAL 파일 헤더에" -"는 %d 바이트로 지정되어있습니다" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL 조각 파일 크기는 1MB에서 1GB사이 2^n 이어야 합니다." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "\"%s\" 파일을 읽을 수 없음: %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %d" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "\"%s\" WAL 파일 찾기 실패" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "어떤 WAL 파일도 찾을 수 없음" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "\"%s\" 파일을 찾을 수 없음: %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" +msgid "could not read from file \"%s\", offset %d: %m" msgstr "\"%s\" 파일에서 %d 위치를 읽을 수 없음: %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" msgstr "%s 파일에서 %d 위치에서 읽기 실패: %d 읽음, 전체 %d" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "잘못된 포크 번호: %u" -#: pg_waldump.c:531 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "\"%s\" 파일을 쓸 수 없음: %m" -#: pg_waldump.c:534 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "\"%s\" 파일을 닫을 수 없음: %m" -#: pg_waldump.c:754 +#: pg_waldump.c:758 #, c-format msgid "" "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n" "\n" msgstr "%s 명령은 디버깅을 위해 PostgreSQL 미리 쓰기 로그(WAL)를 분석합니다.\n" -#: pg_waldump.c:756 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: pg_waldump.c:757 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [옵션]... [시작파일 [마침파일]]\n" -#: pg_waldump.c:758 +#: pg_waldump.c:762 #, c-format msgid "" "\n" @@ -150,13 +198,13 @@ msgstr "" "\n" "옵션들:\n" -#: pg_waldump.c:759 +#: pg_waldump.c:763 #, c-format msgid "" " -b, --bkp-details output detailed information about backup blocks\n" msgstr " -b, --bkp-details 백업 블록에 대한 자세한 정보도 출력함\n" -#: pg_waldump.c:760 +#: pg_waldump.c:764 #, c-format msgid "" " -B, --block=N with --relation, only show records that modify " @@ -165,17 +213,17 @@ msgstr "" " -B, --block=N --relation 옵션과 함께, 변경된 N번 블록의 레코드만" "봄\n" -#: pg_waldump.c:761 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr " -e, --end=RECPTR RECPTR WAL 위치에서 읽기 멈춤\n" -#: pg_waldump.c:762 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr " -f, --follow WAL 끝까지 읽은 뒤에도 계속 진행함\n" -#: pg_waldump.c:763 +#: pg_waldump.c:767 #, c-format msgid "" " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" @@ -184,12 +232,12 @@ msgstr "" " -F, --fork=FORK 지정한 FORK 종류 포크의 변경 블록의 레코드만\n" " 사용가능한 포크: main, fsm, vm, init\n" -#: pg_waldump.c:765 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N 출력할 레코드 수\n" -#: pg_waldump.c:766 +#: pg_waldump.c:770 #, c-format msgid "" " -p, --path=PATH directory in which to find WAL segment files or a\n" @@ -201,12 +249,12 @@ msgstr "" " ./pg_wal 디렉터리가 있는 디렉터리 지정\n" " (기본값: 현재 디렉터리, ./pg_wal, PGDATA/pg_wal)\n" -#: pg_waldump.c:769 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet 오류를 빼고 나머지는 아무 것도 안 보여줌\n" -#: pg_waldump.c:770 +#: pg_waldump.c:774 #, c-format msgid "" " -r, --rmgr=RMGR only show records generated by resource manager " @@ -217,7 +265,7 @@ msgstr "" " -r, --rmgr=RMGR 리소스 관리자 RMGR에서 만든 레코드만 출력함\n" " 리소스 관리자 이들을 --rmgr=list 로 봄\n" -#: pg_waldump.c:772 +#: pg_waldump.c:776 #, c-format msgid "" " -R, --relation=T/D/R only show records that modify blocks in relation T/" @@ -225,12 +273,12 @@ msgid "" msgstr "" " -R, --relation=T/D/R T/D/R 릴레이션에서 변경 블록 레코드만 보여줌\n" -#: pg_waldump.c:773 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr " -s, --start=RECPTR WAL RECPTR 위치에서 읽기 시작\n" -#: pg_waldump.c:774 +#: pg_waldump.c:778 #, c-format msgid "" " -t, --timeline=TLI timeline from which to read WAL records\n" @@ -239,22 +287,22 @@ msgstr "" " -t, --timeline=TLI WAL 레코드를 시작할 타임라인 번호\n" " (기본값: 1 또는 STARTSEG에 사용된 값)\n" -#: pg_waldump.c:776 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보 보여주고 마침\n" -#: pg_waldump.c:777 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr " -w, --fullpage full page write 레코드만 보여줌\n" -#: pg_waldump.c:778 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr " -x, --xid=XID 트랜잭션 XID 레코드만 출력\n" -#: pg_waldump.c:779 +#: pg_waldump.c:783 #, c-format msgid "" " -z, --stats[=record] show statistics instead of records\n" @@ -263,17 +311,17 @@ msgstr "" " -z, --stats[=record] 레크드 통계 정보를 보여줌\n" " (추가로, 레코드당 통계정보를 출력)\n" -#: pg_waldump.c:781 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr " --save-fullpage=DIR DIR에 전체 페이지 이미지 저장\n" -#: pg_waldump.c:782 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: pg_waldump.c:783 +#: pg_waldump.c:787 #, c-format msgid "" "\n" @@ -282,198 +330,183 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: pg_waldump.c:784 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: pg_waldump.c:880 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "인자를 지정하세요" -#: pg_waldump.c:896 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "잘못된 블록 번호: \"%s\"" -#: pg_waldump.c:905 pg_waldump.c:1003 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "잘못된 WAL 위치: \"%s\"" -#: pg_waldump.c:918 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "잘못된 포크 이름: \"%s\"" -#: pg_waldump.c:926 pg_waldump.c:1029 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "\"%s\" 값은 %s 옵션 값으로 유효하지 않음" -#: pg_waldump.c:957 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "\"%s\" 이름의 사용자 정의 리소스 관리자가 없음" -#: pg_waldump.c:978 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "\"%s\" 이름의 리소스 관리자가 없음" -#: pg_waldump.c:993 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "잘못된 릴레이션 양식: \"%s\"" -#: pg_waldump.c:994 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "\"테이블스페이스OID/데이터베이스OID/릴레이션 filenode\" 양식을 기대함" -#: pg_waldump.c:1036 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "%s 값은 %u부터 %u까지만 허용함" -#: pg_waldump.c:1051 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "잘못된 트랜잭션 ID 양식: \"%s\"" -#: pg_waldump.c:1066 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "%s 옵션에 대한 알 수 없는 값: %s" -#: pg_waldump.c:1083 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "%s 옵션은 %s 옵션 설정이 필요합니다." -#: pg_waldump.c:1090 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "너무 많은 명령행 인수를 지정했습니다. (처음 \"%s\")" -#: pg_waldump.c:1100 pg_waldump.c:1123 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "\"%s\" 디렉터리 열 수 없음: %m" - -#: pg_waldump.c:1129 pg_waldump.c:1159 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "\"%s\" 파일을 열 수 없음" -#: pg_waldump.c:1139 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "%X/%X WAL 시작 위치가 \"%s\" 파일에 없음" -#: pg_waldump.c:1166 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "%s ENDSEG가 %s STARTSEG 앞에 있음" -#: pg_waldump.c:1181 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "%X/%X WAL 끝 위치가 \"%s\" 파일에 없음" -#: pg_waldump.c:1193 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "입력한 WAL 위치에서 시작할 수 없음" -#: pg_waldump.c:1207 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "WAL 읽기 프로세서를 할당하는 중에 메모리 부족 발생" -#: pg_waldump.c:1213 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" msgstr "%X/%X 위치 뒤에 올바른 레코드가 없음" -#: pg_waldump.c:1223 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" -msgstr[0] "첫 레코드가 %X/%X 뒤에 있고, (%X/%X), %u 바이트 건너 뜀\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" +msgstr[0] "첫 레코드가 %X/%X 뒤에 있고, (%X/%X), %u 바이트 건너 뜀" -#: pg_waldump.c:1308 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "%X/%X 위치에서 WAL 레코드 오류: %s" -#: pg_waldump.c:1317 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 오프셋: 위치 %X/%X, 기대값 %u, 실재값 %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "%X/%X에서 contrecord를 필요로 함" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "잘못된 레코드 길이: 위치 %X/%X, 기대값 %u, 실재값 %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "%u 길이 레코드를 디코드 작업을 위한 메모리가 부족함" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "%X/%X 위치에 contrecord 플래그가 없음" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "잘못된 contrecord 길이 %u (기대값: %lld), 위치 %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "잘못된 자원 관리 ID %u, 위치: %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "레코드의 잘못된 프리링크 %X/%X, 해당 레코드 %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "잘못된 자원관리자 데이터 체크섬, 위치: %X/%X 레코드" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "%04X 매직 번호가 잘못됨, WAL 조각 파일 %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 정보 비트 %04X, WAL 조각 파일 %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -482,7 +515,7 @@ msgstr "" "WAL 파일이 다른 시스템의 것입니다. WAL 파일의 시스템 식별자는 %llu, " "pg_control 의 식별자는 %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -491,7 +524,7 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더에 지정된 값이 잘" "못된 조각 크기임" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -500,12 +533,12 @@ msgstr "" "WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_BLCKSZ 값" "이 바르지 않음" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "잘못된 페이지 주소 %X/%X, WAL 조각 파일 %s, LSN %X/%X, 오프셋 %u" -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -514,22 +547,22 @@ msgstr "" "타임라인 범위 벗어남 %u (이전 번호 %u), WAL 조각 파일 %s, LSN %X/%X, 오프셋 " "%u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "%u block_id는 범위를 벗어남, 위치 %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정했지만, %X/%X 에 자료가 없음" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA 지정 않았지만, %u 길이의 자료가 있음, 위치 %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -538,19 +571,19 @@ msgstr "" "BKPIMAGE_HAS_HOLE 설정이 되어 있지만, 옵셋: %u, 길이: %u, 블록 이미지 길이: " "%u, 대상: %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE 설정이 안되어 있지만, 옵셋: %u, 길이: %u, 대상: %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED 설정이 되어 있지만, 블록 이미지 길이: %u, 대상: %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -559,37 +592,37 @@ msgstr "" "BKPIMAGE_HAS_HOLE, BKPIMAGE_COMPRESSED 지정 안되어 있으나, 블록 이미지 길이" "는 %u, 대상: %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL 설정이 되어 있지만, %X/%X 에 이전 릴레이션 없음" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "잘못된 block_id %u, 위치 %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "잘못된 레코드 길이, 위치 %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "WAL 레코드에서 %d ID의 백업 블록 위치를 바르게 잡을 수 없음" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "%X/%X 위치에 이미지를 복원할 수 없음, 해당 %d 블록이 깨졌음" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "이미지 복원 실패, 잘못된 상태의 압축 이미지, 위치 %X/%X, 블록 %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " @@ -598,14 +631,14 @@ msgstr "" "%X/%X 압축 위치에 이미지 복원할 수 없음, %s 압축을 지원하지 않음, 해당 블록: " "%d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "" "%X/%X 압축 위치에 이미지 복원할 수 없음, 알 수 없은 방법, 해당 블록: %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "압축 이미지 풀기 실패, 위치 %X/%X, 블록 %d" @@ -613,3 +646,11 @@ msgstr "압축 이미지 풀기 실패, 위치 %X/%X, 블록 %d" #, c-format #~ msgid "missing contrecord at %X/%X" #~ msgstr "%X/%X 위치에 contrecord 없음" + +#, c-format +#~ msgid "out of memory while trying to decode a record of length %u" +#~ msgstr "%u 길이 레코드를 디코드 작업을 위한 메모리가 부족함" + +#, c-format +#~ msgid "record length %u at %X/%X too long" +#~ msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음" diff --git a/src/bin/pg_waldump/po/meson.build b/src/bin/pg_waldump/po/meson.build index dcad78703a7e5..b69469699e959 100644 --- a/src/bin/pg_waldump/po/meson.build +++ b/src/bin/pg_waldump/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_waldump-' + pg_version_major.to_string())] diff --git a/src/bin/pg_waldump/po/ru.po b/src/bin/pg_waldump/po/ru.po index 4a2754d7ea93b..bafe5a3233c66 100644 --- a/src/bin/pg_waldump/po/ru.po +++ b/src/bin/pg_waldump/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for pg_waldump # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2017, 2018, 2019, 2020, 2022, 2023. +# Alexander Lakhin , 2017, 2018, 2019, 2020, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pg_waldump (PostgreSQL) 10\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-02 18:10+0300\n" -"PO-Revision-Date: 2023-08-30 15:41+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-07 08:59+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -37,6 +37,60 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -50,88 +104,79 @@ msgstr "каталог \"%s\" существует, но он не пуст" #: pg_waldump.c:150 #, c-format msgid "could not access directory \"%s\": %m" -msgstr "ошибка доступа к каталогу \"%s\": %m" +msgstr "ошибка при обращении к каталогу \"%s\": %m" -#: pg_waldump.c:199 pg_waldump.c:528 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не удалось открыть файл \"%s\": %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "WAL-файл \"%s\" содержит неверный размер сегмента WAL (%d Б)" +msgstr[1] "WAL-файл \"%s\" содержит неверный размер сегмента WAL (%d Б)" +msgstr[2] "WAL-файл \"%s\" содержит неверный размер сегмента WAL (%d Б)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL " -"file \"%s\" header specifies %d byte" -msgid_plural "" -"WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL " -"file \"%s\" header specifies %d bytes" -msgstr[0] "" -"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в заголовке файла WAL \"%s\" указано значение: %d" -msgstr[1] "" -"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в заголовке файла WAL \"%s\" указано значение: %d" -msgstr[2] "" -"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 " -"ГБ, но в заголовке файла WAL \"%s\" указано значение: %d" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "" +"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 ГБ." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "не удалось прочитать файл \"%s\": %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %d)" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "не удалось найти файл WAL \"%s\"" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "не удалось найти ни одного файла WAL" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "не удалось найти файл \"%s\": %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" -msgstr "не удалось прочитать из файла %s по смещению %d: %m" +msgid "could not read from file \"%s\", offset %d: %m" +msgstr "не удалось прочитать файл \"%s\" по смещению %d: %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" msgstr "" -"не удалось прочитать из файла %s по смещению %d (прочитано байт: %d из %d)" +"не удалось прочитать файл \"%s\" по смещению %d (прочитано байт: %d из %d)" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "неверный номер слоя: %u" -#: pg_waldump.c:531 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "не удалось записать файл \"%s\": %m" -#: pg_waldump.c:534 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "не удалось закрыть файл \"%s\": %m" -#: pg_waldump.c:754 +#: pg_waldump.c:758 #, c-format msgid "" "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n" @@ -140,17 +185,17 @@ msgstr "" "%s декодирует и показывает журналы предзаписи PostgreSQL для целей отладки.\n" "\n" -#: pg_waldump.c:756 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: pg_waldump.c:757 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [ПАРАМЕТР]... [НАЧАЛЬНЫЙ_СЕГМЕНТ [КОНЕЧНЫЙ_СЕГМЕНТ]]\n" -#: pg_waldump.c:758 +#: pg_waldump.c:762 #, c-format msgid "" "\n" @@ -159,14 +204,14 @@ msgstr "" "\n" "Параметры:\n" -#: pg_waldump.c:759 +#: pg_waldump.c:763 #, c-format msgid "" " -b, --bkp-details output detailed information about backup blocks\n" msgstr "" " -b, --bkp-details вывести подробную информацию о копиях страниц\n" -#: pg_waldump.c:760 +#: pg_waldump.c:764 #, c-format msgid "" " -B, --block=N with --relation, only show records that modify " @@ -176,20 +221,20 @@ msgstr "" " записи, в которых меняется блок N\n" # well-spelled: ПОЗЗАП -#: pg_waldump.c:761 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr "" " -e, --end=ПОЗЗАП прекратить чтение в заданной позиции записи в WAL\n" -#: pg_waldump.c:762 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr "" " -f, --follow повторять попытки чтения по достижении конца WAL\n" # well-spelled: МНГР -#: pg_waldump.c:763 +#: pg_waldump.c:767 #, c-format msgid "" " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" @@ -199,13 +244,13 @@ msgstr "" "СЛОЕ\n" " с именем из списка: main, fsm, vm, init\n" -#: pg_waldump.c:765 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N число выводимых записей\n" # skip-rule: space-before-period -#: pg_waldump.c:766 +#: pg_waldump.c:770 #, c-format msgid "" " -p, --path=PATH directory in which to find WAL segment files or a\n" @@ -219,13 +264,13 @@ msgstr "" " (по умолчанию: текущий каталог,\n" " ./pg_wal, $PGDATA/pg_wal)\n" -#: pg_waldump.c:769 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet не выводить никаких сообщений, кроме ошибок\n" # well-spelled: МНГР -#: pg_waldump.c:770 +#: pg_waldump.c:774 #, c-format msgid "" " -r, --rmgr=RMGR only show records generated by resource manager " @@ -237,7 +282,7 @@ msgstr "" " для просмотра списка доступных менеджеров ресурсов\n" " укажите --rmgr=list\n" -#: pg_waldump.c:772 +#: pg_waldump.c:776 #, c-format msgid "" " -R, --relation=T/D/R only show records that modify blocks in relation T/" @@ -247,14 +292,14 @@ msgstr "" " в отношении T/D/R\n" # well-spelled: ПОЗЗАП -#: pg_waldump.c:773 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr "" " -s, --start=ПОЗЗАП начать чтение с заданной позиции записи в WAL\n" # well-spelled: ЛВР -#: pg_waldump.c:774 +#: pg_waldump.c:778 #, c-format msgid "" " -t, --timeline=TLI timeline from which to read WAL records\n" @@ -265,25 +310,25 @@ msgstr "" "аргументом\n" " НАЧАЛЬНЫЙ_СЕГМЕНТ)\n" -#: pg_waldump.c:776 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: pg_waldump.c:777 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr "" " -w, --fullpage выводить только записи, содержащие полные страницы\n" -#: pg_waldump.c:778 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr "" " -x, --xid=XID выводить только записи с заданным\n" " идентификатором транзакции\n" -#: pg_waldump.c:779 +#: pg_waldump.c:783 #, c-format msgid "" " -z, --stats[=record] show statistics instead of records\n" @@ -292,19 +337,19 @@ msgstr "" " -z, --stats[=record] показывать статистику вместо записей\n" " (также возможно получить статистику по записям)\n" -#: pg_waldump.c:781 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr "" " --save-fullpage=ПУТЬ записывать полные образы страниц в заданный " "каталог\n" -#: pg_waldump.c:782 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: pg_waldump.c:783 +#: pg_waldump.c:787 #, c-format msgid "" "\n" @@ -313,200 +358,195 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: pg_waldump.c:784 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: pg_waldump.c:880 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "аргументы не указаны" -#: pg_waldump.c:896 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "неверный номер блока: \"%s\"" -#: pg_waldump.c:905 pg_waldump.c:1003 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "неверная позиция в WAL: \"%s\"" -#: pg_waldump.c:918 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "неверное имя слоя: \"%s\"" -#: pg_waldump.c:926 pg_waldump.c:1029 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "неверное значение \"%s\" для параметра %s" -#: pg_waldump.c:957 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "пользовательский менеджер ресурсов \"%s\" не существует" -#: pg_waldump.c:978 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "менеджер ресурсов \"%s\" не существует" -#: pg_waldump.c:993 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "неверное указание отношения: \"%s\"" -#: pg_waldump.c:994 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "" "Ожидается \"OID табл. пространства/OID базы данных/файловый узел отношения\"." -#: pg_waldump.c:1036 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "значение %s должно быть в диапазоне %u..%u" -#: pg_waldump.c:1051 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "неверное указание ID транзакции: \"%s\"" -#: pg_waldump.c:1066 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "нераспознанное значение параметра %s: %s" -#: pg_waldump.c:1083 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "параметр %s требует указания параметра %s" -#: pg_waldump.c:1090 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: pg_waldump.c:1100 pg_waldump.c:1123 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не удалось открыть каталог \"%s\": %m" - -#: pg_waldump.c:1129 pg_waldump.c:1159 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "не удалось открыть файл \"%s\"" -#: pg_waldump.c:1139 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "начальная позиция в WAL %X/%X находится не в файле \"%s\"" -#: pg_waldump.c:1166 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "КОНЕЧНЫЙ_СЕГМЕНТ %s меньше, чем НАЧАЛЬНЫЙ_СЕГМЕНТ %s" -#: pg_waldump.c:1181 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "конечная позиция в WAL %X/%X находится не в файле \"%s\"" -#: pg_waldump.c:1193 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "начальная позиция в WAL не задана" -#: pg_waldump.c:1207 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "не удалось выделить память для чтения WAL" -#: pg_waldump.c:1213 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" -msgstr "не удалось найти действительную запись после позиции %X/%X" +msgstr "не удалось найти корректную запись после %X/%X" -#: pg_waldump.c:1223 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" msgstr[0] "" -"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б\n" +"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б" msgstr[1] "" -"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б\n" +"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б" msgstr[2] "" -"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б\n" +"первая запись обнаружена после %X/%X, в позиции %X/%X, пропускается %u Б" -#: pg_waldump.c:1308 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "ошибка в записи WAL в позиции %X/%X: %s" -#: pg_waldump.c:1317 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: xlogreader.c:621 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "" "неверное смещение записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: xlogreader.c:630 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "в позиции %X/%X запрошено продолжение записи" -#: xlogreader.c:671 xlogreader.c:1136 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "" "неверная длина записи в позиции %X/%X: ожидалось минимум %u, получено %u" -#: xlogreader.c:760 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "нет флага contrecord в позиции %X/%X" -#: xlogreader.c:773 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неверная длина contrecord: %u (ожидалась %lld) в позиции %X/%X" -#: xlogreader.c:1144 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "неверный ID менеджера ресурсов %u в позиции %X/%X" -#: xlogreader.c:1157 xlogreader.c:1173 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запись с неверной ссылкой назад %X/%X в позиции %X/%X" -#: xlogreader.c:1211 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "" "некорректная контрольная сумма данных менеджера ресурсов в записи в позиции " "%X/%X" -#: xlogreader.c:1245 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверное магическое число %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1260 xlogreader.c:1302 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "" "неверные информационные биты %04X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1276 +#: xlogreader.c:1274 #, c-format msgid "" "WAL file is from different database system: WAL file database system " @@ -515,7 +555,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: в нём указан идентификатор системы БД " "%llu, а идентификатор системы pg_control: %llu" -#: xlogreader.c:1284 +#: xlogreader.c:1282 #, c-format msgid "" "WAL file is from different database system: incorrect segment size in page " @@ -524,7 +564,7 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный размер сегмента в заголовке " "страницы" -#: xlogreader.c:1290 +#: xlogreader.c:1288 #, c-format msgid "" "WAL file is from different database system: incorrect XLOG_BLCKSZ in page " @@ -533,12 +573,12 @@ msgstr "" "файл WAL принадлежит другой СУБД: некорректный XLOG_BLCKSZ в заголовке " "страницы" -#: xlogreader.c:1322 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неожиданный pageaddr %X/%X в сегменте WAL %s, LSN %X/%X, смещение %u" -#: xlogreader.c:1348 +#: xlogreader.c:1346 #, c-format msgid "" "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, " @@ -547,23 +587,23 @@ msgstr "" "нарушение последовательности ID линии времени %u (после %u) в сегменте WAL " "%s, LSN %X/%X, смещение %u" -#: xlogreader.c:1754 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "идентификатор блока %u идёт не по порядку в позиции %X/%X" -#: xlogreader.c:1778 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA установлен, но данных в позиции %X/%X нет" -#: xlogreader.c:1785 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "" "BKPBLOCK_HAS_DATA не установлен, но длина данных равна %u в позиции %X/%X" -#: xlogreader.c:1821 +#: xlogreader.c:1816 #, c-format msgid "" "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at " @@ -572,21 +612,21 @@ msgstr "" "BKPIMAGE_HAS_HOLE установлен, но для пропуска заданы смещение %u и длина %u " "при длине образа блока %u в позиции %X/%X" -#: xlogreader.c:1837 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "" "BKPIMAGE_HAS_HOLE не установлен, но для пропуска заданы смещение %u и длина " "%u в позиции %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "" "BKPIMAGE_COMPRESSED установлен, но длина образа блока равна %u в позиции %X/" "%X" -#: xlogreader.c:1866 +#: xlogreader.c:1861 #, c-format msgid "" "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image " @@ -595,41 +635,41 @@ msgstr "" "ни BKPIMAGE_HAS_HOLE, ни BKPIMAGE_COMPRESSED не установлены, но длина образа " "блока равна %u в позиции %X/%X" -#: xlogreader.c:1882 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "" "BKPBLOCK_SAME_REL установлен, но предыдущее значение не задано в позиции %X/" "%X" -#: xlogreader.c:1894 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "неверный идентификатор блока %u в позиции %X/%X" -#: xlogreader.c:1961 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запись с неверной длиной в позиции %X/%X" -#: xlogreader.c:1987 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не удалось найти копию блока с ID %d в записи журнала WAL" -#: xlogreader.c:2071 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "" "не удалось восстановить образ в позиции %X/%X с указанным неверным блоком %d" -#: xlogreader.c:2078 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "" "не удалось восстановить образ в позиции %X/%X с неверным состоянием, блок %d" -#: xlogreader.c:2105 xlogreader.c:2122 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "" "could not restore image at %X/%X compressed with %s not supported by build, " @@ -638,7 +678,7 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый методом %s, который не " "поддерживается этой сборкой, блок %d" -#: xlogreader.c:2131 +#: xlogreader.c:2126 #, c-format msgid "" "could not restore image at %X/%X compressed with unknown method, block %d" @@ -646,7 +686,7 @@ msgstr "" "не удалось восстановить образ в позиции %X/%X, сжатый неизвестным методом, " "блок %d" -#: xlogreader.c:2139 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не удалось развернуть образ в позиции %X/%X, блок %d" @@ -702,8 +742,5 @@ msgstr "не удалось развернуть образ в позиции %X #~ msgid "not enough data in file \"%s\"" #~ msgstr "недостаточно данных в файле \"%s\"" -#~ msgid "out of memory" -#~ msgstr "нехватка памяти" - #~ msgid "path \"%s\" could not be opened: %s" #~ msgstr "не удалось открыть путь \"%s\": %s" diff --git a/src/bin/pg_waldump/po/sv.po b/src/bin/pg_waldump/po/sv.po index 4fd2ceb7b037a..24173636e1a90 100644 --- a/src/bin/pg_waldump/po/sv.po +++ b/src/bin/pg_waldump/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pg_waldump # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-02 03:17+0000\n" -"PO-Revision-Date: 2023-08-30 08:59+0200\n" +"POT-Creation-Date: 2024-07-12 14:19+0000\n" +"PO-Revision-Date: 2024-07-12 19:11+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -37,6 +37,60 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -52,91 +106,91 @@ msgstr "katalogen \"%s\" existerar men är inte tom" msgid "could not access directory \"%s\": %m" msgstr "kunde inte komma åt katalog \"%s\": %m" -#: pg_waldump.c:199 pg_waldump.c:528 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "kunde inte öppna fil \"%s\": %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "ogiltigt WAL-segmentstorlek i WAL-fil \"%s\" (%d byte)" +msgstr[1] "ogiltigt WAL-segmentstorlek i WAL-fil \"%s\" (%d byte)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes" -msgstr[0] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men headern i WAL-filen \"%s\" anger %d byte" -msgstr[1] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men headern i WAL-filen \"%s\" anger %d byte" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "WAL-segmentstorleken måste vara en tvåpotens mellan 1 MB och 1 GB." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "kunde inte läsa fil \"%s\": %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "kunde inte läsa fil \"%s\": läste %d av %d" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "kunde inte lokalisera WAL-fil \"%s\"" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "kunde inte hitta några WAL-filer" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "kunde inte hitta filen \"%s\": %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" -msgstr "Kunde inte läsa från fil %s på offset %d: %m" +msgid "could not read from file \"%s\", offset %d: %m" +msgstr "Kunde inte läsa från fil \"%s\", offset %d: %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" -msgstr "kunde inte läsa från fil %s, offset %d, läste %d av %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" +msgstr "kunde inte läsa från fil \"%s\", offset %d, läste %d av %d" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "ogiltigt fork-nummer: %u" -#: pg_waldump.c:531 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "kunde inte skriva fil \"%s\": %m" -#: pg_waldump.c:534 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "kunde inte stänga fil \"%s\": %m" -#: pg_waldump.c:754 +#: pg_waldump.c:758 #, c-format msgid "" "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n" "\n" msgstr "%s avkodar och visar PostgreSQLs write-ahead-logg för debuggning.\n" -#: pg_waldump.c:756 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: pg_waldump.c:757 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [FLAGGA]... [STARTSEG [SLUTSEG]]\n" -#: pg_waldump.c:758 +#: pg_waldump.c:762 #, c-format msgid "" "\n" @@ -145,29 +199,29 @@ msgstr "" "\n" "Flaggor:\n" -#: pg_waldump.c:759 +#: pg_waldump.c:763 #, c-format msgid " -b, --bkp-details output detailed information about backup blocks\n" msgstr " -b, --bkp-details skriv detaljerad information om backupblock\n" -#: pg_waldump.c:760 +#: pg_waldump.c:764 #, c-format msgid " -B, --block=N with --relation, only show records that modify block N\n" msgstr "" " -B, --block=N tillsammans med --relation, visa bara poster som\n" " modifierar block N\n" -#: pg_waldump.c:761 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr " -e, --end=RECPTR stoppa läsning vid WAL-position RECPTR\n" -#: pg_waldump.c:762 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr " -f, --follow fortsätt försök efter att ha nått slutet av WAL\n" -#: pg_waldump.c:763 +#: pg_waldump.c:767 #, c-format msgid "" " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" @@ -176,12 +230,12 @@ msgstr "" " -F, --fork=GREN visa bara poster som modifierar block i grenen GREN\n" " gilriga namn är main, fsm, vm och init\n" -#: pg_waldump.c:765 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N antal poster att visa\n" -#: pg_waldump.c:766 +#: pg_waldump.c:770 #, c-format msgid "" " -p, --path=PATH directory in which to find WAL segment files or a\n" @@ -192,12 +246,12 @@ msgstr "" " katalog med en ./pg_wal som innehåller sådana filer\n" " (standard: aktuell katalog, ./pg_wal, $PGDATA/pg_wal)\n" -#: pg_waldump.c:769 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet skriv inte ut några meddelanden förutom fel\n" -#: pg_waldump.c:770 +#: pg_waldump.c:774 #, c-format msgid "" " -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n" @@ -206,19 +260,19 @@ msgstr "" " -r, --rmgr=RMGR visa bara poster skapade av resurshanteraren RMGR;\n" " använd --rmgr=list för att lista giltiga resurshanterarnamn\n" -#: pg_waldump.c:772 +#: pg_waldump.c:776 #, c-format msgid " -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n" msgstr "" " -R, --relation=T/D/R visa bara poster som modifierar block i\n" " relationen T/D/R\n" -#: pg_waldump.c:773 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr " -s, --start=RECPTR börja läsning vid WAL-position RECPTR\n" -#: pg_waldump.c:774 +#: pg_waldump.c:778 #, c-format msgid "" " -t, --timeline=TLI timeline from which to read WAL records\n" @@ -227,22 +281,22 @@ msgstr "" " -t, --timeline=TLI tidslinje från vilken vi läser WAL-poster\n" " (standard: 1 eller värdet som används i STARTSEG)\n" -#: pg_waldump.c:776 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: pg_waldump.c:777 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr " -w, --fullpage visa bara poster som skrivit hela sidor\n" -#: pg_waldump.c:778 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr " -x, --xid=XID visa baras poster med transaktions-ID XID\n" -#: pg_waldump.c:779 +#: pg_waldump.c:783 #, c-format msgid "" " -z, --stats[=record] show statistics instead of records\n" @@ -251,17 +305,17 @@ msgstr "" " -z, --stats[=post] visa statistik istället för poster\n" " (alternativt, visa statistik per post)\n" -#: pg_waldump.c:781 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr " --save-fullpage=KAT spara kopia av hela sidor till KAT\n" -#: pg_waldump.c:782 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa den här hjälpen, avsluta sedan\n" -#: pg_waldump.c:783 +#: pg_waldump.c:787 #, c-format msgid "" "\n" @@ -270,312 +324,285 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: pg_waldump.c:784 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: pg_waldump.c:880 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "inga argument angivna" -#: pg_waldump.c:896 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "ogiltigt portnummer \"%s\"" -#: pg_waldump.c:905 pg_waldump.c:1003 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "ogiltig WAL-position: \"%s\"" -#: pg_waldump.c:918 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "ogiltigt fork-namn: \"%s\"" -#: pg_waldump.c:926 pg_waldump.c:1029 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" -#: pg_waldump.c:957 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "egendefinierad resurshanterare \"%s\" finns inte" -#: pg_waldump.c:978 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "resurshanterare \"%s\" finns inte" -#: pg_waldump.c:993 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "ogiltig inställning av relation: \"%s\"" -#: pg_waldump.c:994 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "Skall vara en av \"OID för tabellutrymme/OID för databas/relations filnod\"." -#: pg_waldump.c:1036 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "%s måste vara i intervallet %u..%u" -#: pg_waldump.c:1051 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "ogiltig inställning av transaktions-ID: %s" -#: pg_waldump.c:1066 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "okänt värde för flaggan %s: %s" -#: pg_waldump.c:1083 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "flaggan %s kräver att flaggan %s också anges" -#: pg_waldump.c:1090 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: pg_waldump.c:1100 pg_waldump.c:1123 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "kunde inte öppna katalog \"%s\": %m" - -#: pg_waldump.c:1129 pg_waldump.c:1159 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "kunde inte öppna filen \"%s\"" -#: pg_waldump.c:1139 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "start-WAL-position %X/%X är inte i filen \"%s\"" -#: pg_waldump.c:1166 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "SLUTSEG %s är före STARTSEG %s" -#: pg_waldump.c:1181 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "slut-WAL-position %X/%X är inte i filen \"%s\"" -#: pg_waldump.c:1193 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "ingen start-WAL-position angiven" -#: pg_waldump.c:1207 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "slut på minne vid allokering av en WAL-läs-processor" -#: pg_waldump.c:1213 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" msgstr "kunde inte hitta en giltig post efter %X/%X" -#: pg_waldump.c:1223 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" -msgstr[0] "första posten efter %X/%X, vid %X/%X, hoppar över %u byte\n" -msgstr[1] "första posten efter %X/%X, vid %X/%X, hoppar över %u byte\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" +msgstr[0] "första posten är efter %X/%X, vid %X/%X, hoppar över %u byte" +msgstr[1] "första posten är efter %X/%X, vid %X/%X, hoppar över %u byte" -#: pg_waldump.c:1308 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "fel i WAL-post vid %X/%X: %s" -#: pg_waldump.c:1317 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: xlogreader.c:626 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "ogiltig postoffset vid %X/%X: förväntade minst %u, fick %u" -#: xlogreader.c:635 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "contrecord är begärd vid %X/%X" -#: xlogreader.c:676 xlogreader.c:1119 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "ogiltig postlängd vid %X/%X: förväntade minst %u, fick %u" -#: xlogreader.c:705 -#, c-format -msgid "out of memory while trying to decode a record of length %u" -msgstr "slut på minne vid avkodning av post med längden %u" - -#: xlogreader.c:727 -#, c-format -msgid "record length %u at %X/%X too long" -msgstr "postlängd %u vid %X/%X är för lång" - -#: xlogreader.c:776 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "det finns ingen contrecord-flagga vid %X/%X" -#: xlogreader.c:789 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "ogiltig contrecord-längd %u (förväntade %lld) vid %X/%X" -#: xlogreader.c:1127 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "ogiltigt resurshanterar-ID %u vid %X/%X" -#: xlogreader.c:1140 xlogreader.c:1156 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "post med inkorrekt prev-link %X/%X vid %X/%X" -#: xlogreader.c:1192 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "felaktig resurshanterardatakontrollsumma i post vid %X/%X" -#: xlogreader.c:1226 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "felaktigt magiskt nummer %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1241 xlogreader.c:1283 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "ogiltiga infobitar %04X i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1257 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL-fil är från ett annat databassystem: WAL-filens databassystemidentifierare är %llu, pg_control databassystemidentifierare är %llu" -#: xlogreader.c:1265 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt segmentstorlek i sidhuvud" -#: xlogreader.c:1271 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "WAL-fil är från ett annat databassystem: inkorrekt XLOG_BLCKSZ i sidhuvud" -#: xlogreader.c:1303 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "oväntad sidadress %X/%X i WAL-segment %s, LSN %X/%X, offset %u" # FIXME -#: xlogreader.c:1329 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "\"ej i sekvens\"-fel på tidslinje-ID %u (efter %u) i WAL-segment %s, LSN %X/%X, offset %u" -#: xlogreader.c:1735 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "\"ej i sekvens\"-block_id %u vid %X/%X" -#: xlogreader.c:1759 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA är satt men ingen data inkluderad vid %X/%X" -#: xlogreader.c:1766 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA är ej satt men datalängden är %u vid %X/%X" -#: xlogreader.c:1802 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är satt men håloffset %u längd %u blockavbildlängd %u vid %X/%X" -#: xlogreader.c:1818 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE är inte satt men håloffset %u längd %u vid %X/%X" -#: xlogreader.c:1832 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED är satt men blockavbildlängd %u vid %X/%X" -#: xlogreader.c:1847 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "varken BKPIMAGE_HAS_HOLE eller BKPIMAGE_COMPRESSED är satt men blockavbildlängd är %u vid %X/%X" -#: xlogreader.c:1863 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL är satt men ingen tidigare rel vid %X/%X" -#: xlogreader.c:1875 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "ogiltig block_id %u vid %X/%X" -#: xlogreader.c:1942 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "post med ogiltig längd vid %X/%X" -#: xlogreader.c:1968 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "kunde inte hitta backup-block med ID %d i WAL-post" -#: xlogreader.c:2052 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt block %d angivet" -#: xlogreader.c:2059 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "kunde inte återställa avbild vid %X/%X med ogiltigt state, block %d" -#: xlogreader.c:2086 xlogreader.c:2103 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med %s stöds inte av bygget, block %d" -#: xlogreader.c:2112 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "kunde inte återställa avbild vid %X/%X, komprimerad med okänd metod, block %d" -#: xlogreader.c:2120 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "kunde inte packa upp avbild vid %X/%X, block %d" - -#, c-format -#~ msgid "invalid record offset at %X/%X" -#~ msgstr "ogiltig postoffset vid %X/%X" - -#, c-format -#~ msgid "invalid timeline specification: \"%s\"" -#~ msgstr "ogiltig inställning av tidslinje: %s" - -#, c-format -#~ msgid "missing contrecord at %X/%X" -#~ msgstr "det saknas en contrecord vid %X/%X" diff --git a/src/bin/pg_waldump/po/uk.po b/src/bin/pg_waldump/po/uk.po index 00373f44fd463..09da6eebce3ec 100644 --- a/src/bin/pg_waldump/po/uk.po +++ b/src/bin/pg_waldump/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-09 18:17+0000\n" -"PO-Revision-Date: 2024-02-11 16:35\n" +"POT-Creation-Date: 2024-08-31 06:19+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pg_waldump.pot\n" -"X-Crowdin-File-ID: 979\n" +"X-Crowdin-File: /REL_17_STABLE/pg_waldump.pot\n" +"X-Crowdin-File-ID: 984\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,6 +37,60 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 pg_waldump.c:199 +#: pg_waldump.c:532 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: pg_waldump.c:1104 pg_waldump.c:1127 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: pg_waldump.c:137 #, c-format msgid "could not create directory \"%s\": %m" @@ -52,130 +106,130 @@ msgstr "каталог \"%s\" існує, але він не порожній" msgid "could not access directory \"%s\": %m" msgstr "немає доступу до каталогу \"%s\": %m" -#: pg_waldump.c:199 pg_waldump.c:528 +#: pg_waldump.c:256 #, c-format -msgid "could not open file \"%s\": %m" -msgstr "не можливо відкрити файл \"%s\": %m" +msgid "invalid WAL segment size in WAL file \"%s\" (%d byte)" +msgid_plural "invalid WAL segment size in WAL file \"%s\" (%d bytes)" +msgstr[0] "невірний розмір сегмента WAL у файлі WAL \"%s\" (%d байт)" +msgstr[1] "невірний розмір сегмента WAL у файлі WAL \"%s\" (%d байт)" +msgstr[2] "невірний розмір сегмента WAL у файлі WAL \"%s\" (%d байт)" +msgstr[3] "невірний розмір сегмента WAL у файлі WAL \"%s\" (%d байт)" -#: pg_waldump.c:255 +#: pg_waldump.c:260 #, c-format -msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte" -msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes" -msgstr[0] "Розмір сегмента WAL повинен задаватись ступенем двійки в інтервалі між 1 MB і 1 GB, але у заголовку файлу WAL \"%s\" вказано %d байт" -msgstr[1] "Розмір сегмента WAL повинен задаватись ступенем двійки в інтервалі між 1 MB і 1 GB, але у заголовку файлу WAL \"%s\" вказано %d байти" -msgstr[2] "Розмір сегмента WAL повинен задаватись ступенем двійки в інтервалі між 1 MB і 1 GB, але у заголовку файлу WAL \"%s\" вказано %d байтів" -msgstr[3] "Розмір сегмента WAL повинен задаватись ступенем двійки в інтервалі між 1 MB і 1 GB, але у заголовку файлу WAL \"%s\" вказано %d байтів" +msgid "The WAL segment size must be a power of two between 1 MB and 1 GB." +msgstr "Розмір сегмента WAL повинен бути степенем двійки від 1 МБ до 1 ГБ." -#: pg_waldump.c:261 +#: pg_waldump.c:265 #, c-format msgid "could not read file \"%s\": %m" msgstr "не вдалося прочитати файл \"%s\": %m" -#: pg_waldump.c:264 +#: pg_waldump.c:268 #, c-format msgid "could not read file \"%s\": read %d of %d" msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %d" -#: pg_waldump.c:325 +#: pg_waldump.c:329 #, c-format msgid "could not locate WAL file \"%s\"" msgstr "не вдалося знайти WAL файл \"%s\"" -#: pg_waldump.c:327 +#: pg_waldump.c:331 #, c-format msgid "could not find any WAL file" msgstr "не вдалося знайти жодного WAL файлу" -#: pg_waldump.c:368 +#: pg_waldump.c:372 #, c-format msgid "could not find file \"%s\": %m" msgstr "не вдалося знайти файл \"%s\": %m" -#: pg_waldump.c:417 +#: pg_waldump.c:421 #, c-format -msgid "could not read from file %s, offset %d: %m" -msgstr "не вдалося прочитати файл %s, зсув %d: %m" +msgid "could not read from file \"%s\", offset %d: %m" +msgstr "не вдалося прочитати з файлу \"%s\", зсув %d: %m" -#: pg_waldump.c:421 +#: pg_waldump.c:425 #, c-format -msgid "could not read from file %s, offset %d: read %d of %d" -msgstr "не вдалося прочитати з файлу %s, зсув %d: прочитано %d з %d" +msgid "could not read from file \"%s\", offset %d: read %d of %d" +msgstr "не вдалося прочитати з файлу \"%s\", зсув %d: прочитано %d з %d" -#: pg_waldump.c:511 +#: pg_waldump.c:515 #, c-format msgid "%s" msgstr "%s" -#: pg_waldump.c:519 +#: pg_waldump.c:523 #, c-format msgid "invalid fork number: %u" msgstr "неприпустимий номер форку: %u" -#: pg_waldump.c:531 +#: pg_waldump.c:535 #, c-format msgid "could not write file \"%s\": %m" msgstr "не вдалося записати файл \"%s\": %m" -#: pg_waldump.c:534 +#: pg_waldump.c:538 #, c-format msgid "could not close file \"%s\": %m" msgstr "неможливо закрити файл \"%s\": %m" -#: pg_waldump.c:754 +#: pg_waldump.c:758 #, c-format msgid "%s decodes and displays PostgreSQL write-ahead logs for debugging.\n\n" msgstr "%s декодує і відображає журнали попереднього запису PostgreSQL для налагодження.\n\n" -#: pg_waldump.c:756 +#: pg_waldump.c:760 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: pg_waldump.c:757 +#: pg_waldump.c:761 #, c-format msgid " %s [OPTION]... [STARTSEG [ENDSEG]]\n" msgstr " %s [OPTION]...[STARTSEG [ENDSEG]]\n" -#: pg_waldump.c:758 +#: pg_waldump.c:762 #, c-format msgid "\n" "Options:\n" msgstr "\n" "Параметри:\n" -#: pg_waldump.c:759 +#: pg_waldump.c:763 #, c-format msgid " -b, --bkp-details output detailed information about backup blocks\n" msgstr " -b, --bkp-details виводити детальну інформацію про блоки резервних копій\n" -#: pg_waldump.c:760 +#: pg_waldump.c:764 #, c-format msgid " -B, --block=N with --relation, only show records that modify block N\n" msgstr " -B, --block=N з --relation, лише показати записи, які змінюють блок N\n" -#: pg_waldump.c:761 +#: pg_waldump.c:765 #, c-format msgid " -e, --end=RECPTR stop reading at WAL location RECPTR\n" msgstr " -e, --end=RECPTR зупинити читання WAL з місця RECPTR\n" -#: pg_waldump.c:762 +#: pg_waldump.c:766 #, c-format msgid " -f, --follow keep retrying after reaching end of WAL\n" msgstr " -f, --follow повторювати спроби після досягнення кінця WAL\n" -#: pg_waldump.c:763 +#: pg_waldump.c:767 #, c-format msgid " -F, --fork=FORK only show records that modify blocks in fork FORK;\n" " valid names are main, fsm, vm, init\n" msgstr " -F, --fork=FORK показати лише записи, які змінюють блоки в форці FORK;\n" " дійсні імена: main, fsm, vm, init\n" -#: pg_waldump.c:765 +#: pg_waldump.c:769 #, c-format msgid " -n, --limit=N number of records to display\n" msgstr " -n, --limit=N число записів для відображення\n" -#: pg_waldump.c:766 +#: pg_waldump.c:770 #, c-format msgid " -p, --path=PATH directory in which to find WAL segment files or a\n" " directory with a ./pg_wal that contains such files\n" @@ -184,358 +238,353 @@ msgstr " -p, --path=PATH каталог, у якому шукати фа " або каталог з ./pg_wal, що містить такі файли\n" " (за замовчуванням: чинний каталог, ./pg_wal, $PGDATA/pg_wal)\n" -#: pg_waldump.c:769 +#: pg_waldump.c:773 #, c-format msgid " -q, --quiet do not print any output, except for errors\n" msgstr " -q, --quiet не друкувати жодного виводу, окрім помилок\n" -#: pg_waldump.c:770 +#: pg_waldump.c:774 #, c-format msgid " -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n" " use --rmgr=list to list valid resource manager names\n" msgstr " -r, --rmgr=RMGR відображати записи, згенеровані лише ресурсним менеджером RMGR;\n" " використовувати --rmgr=list для перегляду списку припустимих імен ресурсного менеджера\n" -#: pg_waldump.c:772 +#: pg_waldump.c:776 #, c-format msgid " -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n" msgstr " -R, --relation=T/D/R відобразити тільки записи, які змінюють блоки у відношенні T/D/R\n" -#: pg_waldump.c:773 +#: pg_waldump.c:777 #, c-format msgid " -s, --start=RECPTR start reading at WAL location RECPTR\n" msgstr " -s, --start=RECPTR почати читання WAL з місця RECPTR\n" -#: pg_waldump.c:774 +#: pg_waldump.c:778 #, c-format msgid " -t, --timeline=TLI timeline from which to read WAL records\n" " (default: 1 or the value used in STARTSEG)\n" msgstr " -t, --timeline=TLI часова шкала, WAL-записи якої будуть прочитані\n" " (за замовчуванням: 1 або значення, що використовується у STARTSEG)\n" -#: pg_waldump.c:776 +#: pg_waldump.c:780 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: pg_waldump.c:777 +#: pg_waldump.c:781 #, c-format msgid " -w, --fullpage only show records with a full page write\n" msgstr " -w, --fullpage показувати записи лише з повним записом на сторінці\n" -#: pg_waldump.c:778 +#: pg_waldump.c:782 #, c-format msgid " -x, --xid=XID only show records with transaction ID XID\n" msgstr " -x, --xid=XID показати записи лише з ідентифікатором транзакцій XID\n" -#: pg_waldump.c:779 +#: pg_waldump.c:783 #, c-format msgid " -z, --stats[=record] show statistics instead of records\n" " (optionally, show per-record statistics)\n" msgstr " -z, --stats[=record] показати статистику замість записів (необов'язково, відобразити щорядкову статистику)\n" -#: pg_waldump.c:781 +#: pg_waldump.c:785 #, c-format msgid " --save-fullpage=DIR save full page images to DIR\n" msgstr " --save-fullpage=DIR зберігати повні зображення сторінок в DIR\n" -#: pg_waldump.c:782 +#: pg_waldump.c:786 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку потім вийти\n" -#: pg_waldump.c:783 +#: pg_waldump.c:787 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: pg_waldump.c:784 +#: pg_waldump.c:788 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: pg_waldump.c:880 +#: pg_waldump.c:884 #, c-format msgid "no arguments specified" msgstr "не вказано аргументів" -#: pg_waldump.c:896 +#: pg_waldump.c:900 #, c-format msgid "invalid block number: \"%s\"" msgstr "неприпустимий номер блоку: \"%s\"" -#: pg_waldump.c:905 pg_waldump.c:1003 +#: pg_waldump.c:909 pg_waldump.c:1007 #, c-format msgid "invalid WAL location: \"%s\"" msgstr "неприпустиме розташування WAL: \"%s\"" -#: pg_waldump.c:918 +#: pg_waldump.c:922 #, c-format msgid "invalid fork name: \"%s\"" msgstr "неприпустиме ім'я форку: \"%s\"" -#: pg_waldump.c:926 pg_waldump.c:1029 +#: pg_waldump.c:930 pg_waldump.c:1033 #, c-format msgid "invalid value \"%s\" for option %s" msgstr "неприпустиме значення \"%s\" для параметра %s" -#: pg_waldump.c:957 +#: pg_waldump.c:961 #, c-format msgid "custom resource manager \"%s\" does not exist" msgstr "користувацький менеджер ресурсів \"%s\" не існує" -#: pg_waldump.c:978 +#: pg_waldump.c:982 #, c-format msgid "resource manager \"%s\" does not exist" msgstr "менеджер ресурсів \"%s\" не існує" -#: pg_waldump.c:993 +#: pg_waldump.c:997 #, c-format msgid "invalid relation specification: \"%s\"" msgstr "неприпустима специфікація відношення: \"%s\"" -#: pg_waldump.c:994 +#: pg_waldump.c:998 #, c-format msgid "Expecting \"tablespace OID/database OID/relation filenode\"." msgstr "Очікуємо \"tablespace OID/database OID/relation filenode\"." -#: pg_waldump.c:1036 +#: pg_waldump.c:1040 #, c-format msgid "%s must be in range %u..%u" msgstr "%s має бути в діапазоні %u..%u" -#: pg_waldump.c:1051 +#: pg_waldump.c:1055 #, c-format msgid "invalid transaction ID specification: \"%s\"" msgstr "неприпустима специфікація ідентифікатора транзакції: \"%s\"" -#: pg_waldump.c:1066 +#: pg_waldump.c:1070 #, c-format msgid "unrecognized value for option %s: %s" msgstr "нерозпізнане значення параметра %s: %s" -#: pg_waldump.c:1083 +#: pg_waldump.c:1087 #, c-format msgid "option %s requires option %s to be specified" msgstr "параметр %s вимагає використання параметру %s" -#: pg_waldump.c:1090 +#: pg_waldump.c:1094 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: pg_waldump.c:1100 pg_waldump.c:1123 -#, c-format -msgid "could not open directory \"%s\": %m" -msgstr "не вдалося відкрити каталог \"%s\": %m" - -#: pg_waldump.c:1129 pg_waldump.c:1159 +#: pg_waldump.c:1133 pg_waldump.c:1163 #, c-format msgid "could not open file \"%s\"" msgstr "не вдалося відкрити файл \"%s\"" -#: pg_waldump.c:1139 +#: pg_waldump.c:1143 #, c-format msgid "start WAL location %X/%X is not inside file \"%s\"" msgstr "початкове розташування WAL %X/%X не всередині файлу \"%s\"" -#: pg_waldump.c:1166 +#: pg_waldump.c:1170 #, c-format msgid "ENDSEG %s is before STARTSEG %s" msgstr "ENDSEG %s перед STARTSEG %s" -#: pg_waldump.c:1181 +#: pg_waldump.c:1185 #, c-format msgid "end WAL location %X/%X is not inside file \"%s\"" msgstr "кінцеве розташування WAL %X/%X не всередині файлу \"%s\"" -#: pg_waldump.c:1193 +#: pg_waldump.c:1197 #, c-format msgid "no start WAL location given" msgstr "не задано початкове розташування WAL" -#: pg_waldump.c:1207 +#: pg_waldump.c:1211 #, c-format msgid "out of memory while allocating a WAL reading processor" msgstr "недостатньо пам'яті під час виділення обробника читання WAL" -#: pg_waldump.c:1213 +#: pg_waldump.c:1217 #, c-format msgid "could not find a valid record after %X/%X" msgstr "не вдалося знайти припустимий запис після %X/%X" -#: pg_waldump.c:1223 +#: pg_waldump.c:1227 #, c-format -msgid "first record is after %X/%X, at %X/%X, skipping over %u byte\n" -msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes\n" -msgstr[0] "перший запис після %X/%X, у %X/%X, пропускається %u байт\n" -msgstr[1] "перший запис після %X/%X, у %X/%X, пропускається %u байти\n" -msgstr[2] "перший запис після %X/%X, у %X/%X, пропускається %u байтів\n" -msgstr[3] "перший запис після %X/%X, у %X/%X, пропускається %u байти\n" +msgid "first record is after %X/%X, at %X/%X, skipping over %u byte" +msgid_plural "first record is after %X/%X, at %X/%X, skipping over %u bytes" +msgstr[0] "перший запис після %X/%X, за адресою %X/%X, пропускаючи байт %u" +msgstr[1] "перший запис після %X/%X, за адресою %X/%X, пропускаючи %u байти" +msgstr[2] "перший запис після %X/%X, за адресою %X/%X, пропускаючи %u байти" +msgstr[3] "перший запис після %X/%X, за адресою %X/%X, пропускаючи %u байти" -#: pg_waldump.c:1308 +#: pg_waldump.c:1312 #, c-format msgid "error in WAL record at %X/%X: %s" msgstr "помилка у записі WAL у %X/%X: %s" -#: pg_waldump.c:1317 +#: pg_waldump.c:1321 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: xlogreader.c:621 +#: xlogreader.c:619 #, c-format msgid "invalid record offset at %X/%X: expected at least %u, got %u" msgstr "неприпустиме зміщення запису в %X/%X: очікувалось хоча б %u, отримано %u" -#: xlogreader.c:630 +#: xlogreader.c:628 #, c-format msgid "contrecord is requested by %X/%X" msgstr "по зсуву %X/%X запитано продовження запису" -#: xlogreader.c:671 xlogreader.c:1136 +#: xlogreader.c:669 xlogreader.c:1134 #, c-format msgid "invalid record length at %X/%X: expected at least %u, got %u" msgstr "неприпустима довжина запису %X/%X: очікувалась мінімум %u, отримано %u" -#: xlogreader.c:760 +#: xlogreader.c:758 #, c-format msgid "there is no contrecord flag at %X/%X" msgstr "немає прапорця contrecord в позиції %X/%X" -#: xlogreader.c:773 +#: xlogreader.c:771 #, c-format msgid "invalid contrecord length %u (expected %lld) at %X/%X" msgstr "неприпустима довжина contrecord %u (очікувалось %lld) на %X/%X" -#: xlogreader.c:1144 +#: xlogreader.c:1142 #, c-format msgid "invalid resource manager ID %u at %X/%X" msgstr "невірний ID менеджера ресурсів %u в %X/%X" -#: xlogreader.c:1157 xlogreader.c:1173 +#: xlogreader.c:1155 xlogreader.c:1171 #, c-format msgid "record with incorrect prev-link %X/%X at %X/%X" msgstr "запис з неправильним попереднім посиланням %X/%X на %X/%X" -#: xlogreader.c:1211 +#: xlogreader.c:1209 #, c-format msgid "incorrect resource manager data checksum in record at %X/%X" msgstr "некоректна контрольна сума даних менеджера ресурсів у запису по зсуву %X/%X" -#: xlogreader.c:1245 +#: xlogreader.c:1243 #, c-format msgid "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірне магічне число %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1260 xlogreader.c:1302 +#: xlogreader.c:1258 xlogreader.c:1300 #, c-format msgid "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u" msgstr "невірні інформаційні біти %04X в сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1276 +#: xlogreader.c:1274 #, c-format msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu" msgstr "WAL файл належить іншій системі баз даних: ідентифікатор системи баз даних де міститься WAL файл - %llu, а ідентифікатор системи баз даних pg_control - %llu" -#: xlogreader.c:1284 +#: xlogreader.c:1282 #, c-format msgid "WAL file is from different database system: incorrect segment size in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний розмір сегменту в заголовку сторінки" -#: xlogreader.c:1290 +#: xlogreader.c:1288 #, c-format msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header" msgstr "Файл WAL належить іншій системі баз даних: некоректний XLOG_BLCKSZ в заголовку сторінки" -#: xlogreader.c:1322 +#: xlogreader.c:1320 #, c-format msgid "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u" msgstr "неочікуваний pageaddr %X/%X у сегменті WAL %s, LSN %X/%X, зміщення %u" -#: xlogreader.c:1348 +#: xlogreader.c:1346 #, c-format msgid "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u" msgstr "порушення послідовності ID лінії часу %u (після %u) у сегменті WAL %s, LSN %X/%X, зсув %u" -#: xlogreader.c:1754 +#: xlogreader.c:1749 #, c-format msgid "out-of-order block_id %u at %X/%X" msgstr "ідентифікатор блока %u out-of-order в позиції %X/%X" -#: xlogreader.c:1778 +#: xlogreader.c:1773 #, c-format msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але немає даних в позиції %X/%X" -#: xlogreader.c:1785 +#: xlogreader.c:1780 #, c-format msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X" msgstr "BKPBLOCK_HAS_DATA встановлений, але довжина даних дорівнює %u в позиції %X/%X" -#: xlogreader.c:1821 +#: xlogreader.c:1816 #, c-format msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE встановлений, але для пропуску задані: зсув %u, довжина %u, при довжині образу блока %u в позиції %X/%X" -#: xlogreader.c:1837 +#: xlogreader.c:1832 #, c-format msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X" msgstr "BKPIMAGE_HAS_HOLE не встановлений, але для пропуску задані: зсув %u, довжина %u в позиції %X/%X" -#: xlogreader.c:1851 +#: xlogreader.c:1846 #, c-format msgid "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X" msgstr "BKPIMAGE_COMPRESSED встановлений, але довжина образу блока дорівнює %u в позиції %X/%X" -#: xlogreader.c:1866 +#: xlogreader.c:1861 #, c-format msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X" msgstr "ні BKPIMAGE_HAS_HOLE, ні BKPIMAGE_COMPRESSED не встановлені, але довжина образу блока дорівнює %u в позиції %X/%X" -#: xlogreader.c:1882 +#: xlogreader.c:1877 #, c-format msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X" msgstr "BKPBLOCK_SAME_REL встановлений, але попереднє значення не задано в позиції %X/%X" -#: xlogreader.c:1894 +#: xlogreader.c:1889 #, c-format msgid "invalid block_id %u at %X/%X" msgstr "невірний ідентифікатор блоку %u в позиції %X/%X" -#: xlogreader.c:1961 +#: xlogreader.c:1956 #, c-format msgid "record with invalid length at %X/%X" msgstr "запис з невірною довжиною на %X/%X" -#: xlogreader.c:1987 +#: xlogreader.c:1982 #, c-format msgid "could not locate backup block with ID %d in WAL record" msgstr "не вдалося знайти блок резервної копії з ID %d у записі WAL" -#: xlogreader.c:2071 +#: xlogreader.c:2066 #, c-format msgid "could not restore image at %X/%X with invalid block %d specified" msgstr "не вдалося відновити зображення %X/%X з недійсним вказаним блоком %d" -#: xlogreader.c:2078 +#: xlogreader.c:2073 #, c-format msgid "could not restore image at %X/%X with invalid state, block %d" msgstr "не вдалося відновити зображення %X/%X з недійсним станом, блок %d" -#: xlogreader.c:2105 xlogreader.c:2122 +#: xlogreader.c:2100 xlogreader.c:2117 #, c-format msgid "could not restore image at %X/%X compressed with %s not supported by build, block %d" msgstr "не вдалося відновити зображення в %X/%X, стиснуте %s, не підтримується збіркою, блок %d" -#: xlogreader.c:2131 +#: xlogreader.c:2126 #, c-format msgid "could not restore image at %X/%X compressed with unknown method, block %d" msgstr "не вдалося відновити зображення %X/%X стиснуте з невідомим методом, блок %d" -#: xlogreader.c:2139 +#: xlogreader.c:2134 #, c-format msgid "could not decompress image at %X/%X, block %d" msgstr "не вдалося розпакувати зображення на %X/%X, блок %d" diff --git a/src/bin/pg_waldump/rmgrdesc.c b/src/bin/pg_waldump/rmgrdesc.c index 6b8c17bb4c4ec..fac509ed134e5 100644 --- a/src/bin/pg_waldump/rmgrdesc.c +++ b/src/bin/pg_waldump/rmgrdesc.c @@ -41,8 +41,8 @@ static const RmgrDescData RmgrDescTable[RM_N_BUILTIN_IDS] = { #define CUSTOM_NUMERIC_NAME_LEN sizeof("custom###") -static char CustomNumericNames[RM_N_CUSTOM_IDS][CUSTOM_NUMERIC_NAME_LEN] = {{0}}; -static RmgrDescData CustomRmgrDesc[RM_N_CUSTOM_IDS] = {{0}}; +static char CustomNumericNames[RM_N_CUSTOM_IDS][CUSTOM_NUMERIC_NAME_LEN] = {0}; +static RmgrDescData CustomRmgrDesc[RM_N_CUSTOM_IDS] = {0}; static bool CustomRmgrDescInitialized = false; /* diff --git a/src/bin/pg_waldump/t/001_basic.pl b/src/bin/pg_waldump/t/001_basic.pl index 578e473139432..f26d75e01cfd3 100644 --- a/src/bin/pg_waldump/t/001_basic.pl +++ b/src/bin/pg_waldump/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -21,31 +21,31 @@ # invalid option arguments command_fails_like( - [ 'pg_waldump', '--block', 'bad' ], + [ 'pg_waldump', '--block' => 'bad' ], qr/error: invalid block number/, 'invalid block number'); command_fails_like( - [ 'pg_waldump', '--fork', 'bad' ], + [ 'pg_waldump', '--fork' => 'bad' ], qr/error: invalid fork name/, 'invalid fork name'); command_fails_like( - [ 'pg_waldump', '--limit', 'bad' ], + [ 'pg_waldump', '--limit' => 'bad' ], qr/error: invalid value/, 'invalid limit'); command_fails_like( - [ 'pg_waldump', '--relation', 'bad' ], + [ 'pg_waldump', '--relation' => 'bad' ], qr/error: invalid relation/, 'invalid relation specification'); command_fails_like( - [ 'pg_waldump', '--rmgr', 'bad' ], + [ 'pg_waldump', '--rmgr' => 'bad' ], qr/error: resource manager .* does not exist/, 'invalid rmgr name'); command_fails_like( - [ 'pg_waldump', '--start', 'bad' ], + [ 'pg_waldump', '--start' => 'bad' ], qr/error: invalid WAL location/, 'invalid start LSN'); command_fails_like( - [ 'pg_waldump', '--end', 'bad' ], + [ 'pg_waldump', '--end' => 'bad' ], qr/error: invalid WAL location/, 'invalid end LSN'); @@ -199,18 +199,24 @@ qr/./, 'runs with start and end segment specified'); command_fails_like( - [ 'pg_waldump', '-p', $node->data_dir ], + [ 'pg_waldump', '--path' => $node->data_dir ], qr/error: no start WAL location given/, 'path option requires start location'); command_like( [ - 'pg_waldump', '-p', $node->data_dir, '--start', - $start_lsn, '--end', $end_lsn + 'pg_waldump', + '--path' => $node->data_dir, + '--start' => $start_lsn, + '--end' => $end_lsn, ], qr/./, 'runs with path option and start and end locations'); command_fails_like( - [ 'pg_waldump', '-p', $node->data_dir, '--start', $start_lsn ], + [ + 'pg_waldump', + '--path' => $node->data_dir, + '--start' => $start_lsn, + ], qr/error: error in WAL record at/, 'falling off the end of the WAL results in an error'); @@ -222,7 +228,11 @@ qr/^$/, 'no output with --quiet option'); command_fails_like( - [ 'pg_waldump', '--quiet', '-p', $node->data_dir, '--start', $start_lsn ], + [ + 'pg_waldump', '--quiet', + '--path' => $node->data_dir, + '--start' => $start_lsn + ], qr/error: error in WAL record at/, 'errors are shown with --quiet'); @@ -237,12 +247,15 @@ $lsn2++; my $new_start = sprintf("%s/%X", $part1, $lsn2); - my (@cmd, $stdout, $stderr, $result); + my ($stdout, $stderr); - @cmd = ( - 'pg_waldump', '--start', $new_start, - $node->data_dir . '/pg_wal/' . $start_walfile); - $result = IPC::Run::run \@cmd, '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run [ + 'pg_waldump', + '--start' => $new_start, + $node->data_dir . '/pg_wal/' . $start_walfile + ], + '>' => \$stdout, + '2>' => \$stderr; ok($result, "runs with start segment and start LSN specified"); like($stderr, qr/first record is after/, 'info message printed'); } @@ -255,16 +268,20 @@ sub test_pg_waldump local $Test::Builder::Level = $Test::Builder::Level + 1; my @opts = @_; - my (@cmd, $stdout, $stderr, $result, @lines); + my ($stdout, $stderr); - @cmd = ( - 'pg_waldump', '-p', $node->data_dir, '--start', $start_lsn, '--end', - $end_lsn); - push @cmd, @opts; - $result = IPC::Run::run \@cmd, '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run [ + 'pg_waldump', + '--path' => $node->data_dir, + '--start' => $start_lsn, + '--end' => $end_lsn, + @opts + ], + '>' => \$stdout, + '2>' => \$stderr; ok($result, "pg_waldump @opts: runs ok"); is($stderr, '', "pg_waldump @opts: no stderr"); - @lines = split /\n/, $stdout; + my @lines = split /\n/, $stdout; ok(@lines > 0, "pg_waldump @opts: some lines are output"); return @lines; } @@ -274,7 +291,7 @@ sub test_pg_waldump @lines = test_pg_waldump; is(grep(!/^rmgr: \w/, @lines), 0, 'all output lines are rmgr lines'); -@lines = test_pg_waldump('--limit', 6); +@lines = test_pg_waldump('--limit' => 6); is(@lines, 6, 'limit option observed'); @lines = test_pg_waldump('--fullpage'); @@ -288,21 +305,20 @@ sub test_pg_waldump like($lines[0], qr/WAL statistics/, "statistics on stdout"); is(grep(/^rmgr:/, @lines), 0, 'no rmgr lines output'); -@lines = test_pg_waldump('--rmgr', 'Btree'); +@lines = test_pg_waldump('--rmgr' => 'Btree'); is(grep(!/^rmgr: Btree/, @lines), 0, 'only Btree lines'); -@lines = test_pg_waldump('--fork', 'init'); +@lines = test_pg_waldump('--fork' => 'init'); is(grep(!/fork init/, @lines), 0, 'only init fork lines'); -@lines = test_pg_waldump('--relation', - "$default_ts_oid/$postgres_db_oid/$rel_t1_oid"); +@lines = test_pg_waldump( + '--relation' => "$default_ts_oid/$postgres_db_oid/$rel_t1_oid"); is(grep(!/rel $default_ts_oid\/$postgres_db_oid\/$rel_t1_oid/, @lines), 0, 'only lines for selected relation'); -@lines = - test_pg_waldump('--relation', - "$default_ts_oid/$postgres_db_oid/$rel_i1a_oid", - '--block', 1); +@lines = test_pg_waldump( + '--relation' => "$default_ts_oid/$postgres_db_oid/$rel_i1a_oid", + '--block' => 1); is(grep(!/\bblk 1\b/, @lines), 0, 'only lines for selected block'); diff --git a/src/bin/pg_waldump/t/002_save_fullpage.pl b/src/bin/pg_waldump/t/002_save_fullpage.pl index 1f398b043a91f..17b15e3a649ec 100644 --- a/src/bin/pg_waldump/t/002_save_fullpage.pl +++ b/src/bin/pg_waldump/t/002_save_fullpage.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -71,9 +71,10 @@ sub get_block_lsn $node->command_ok( [ - 'pg_waldump', '--quiet', - '--save-fullpage', "$tmp_folder/raw", - '--relation', $relation, + 'pg_waldump', + '--quiet', + '--save-fullpage' => "$tmp_folder/raw", + '--relation' => $relation, $walfile ], 'pg_waldump with --save-fullpage runs'); diff --git a/src/bin/pg_walsummary/Makefile b/src/bin/pg_walsummary/Makefile index 1886c39e98b19..1bc620572d279 100644 --- a/src/bin/pg_walsummary/Makefile +++ b/src/bin/pg_walsummary/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pg_walsummary # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/pg_walsummary/Makefile diff --git a/src/bin/pg_walsummary/meson.build b/src/bin/pg_walsummary/meson.build index 86b046e896de7..fe9af967b123b 100644 --- a/src/bin/pg_walsummary/meson.build +++ b/src/bin/pg_walsummary/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_walsummary_sources = files( 'pg_walsummary.c', diff --git a/src/bin/pg_walsummary/nls.mk b/src/bin/pg_walsummary/nls.mk index b22905e447b15..711729399219f 100644 --- a/src/bin/pg_walsummary/nls.mk +++ b/src/bin/pg_walsummary/nls.mk @@ -1,4 +1,4 @@ -# src/bin/pg_combinebackup/nls.mk +# src/bin/pg_walsummary/nls.mk CATALOG_NAME = pg_walsummary GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ pg_walsummary.c \ diff --git a/src/bin/pg_walsummary/pg_walsummary.c b/src/bin/pg_walsummary/pg_walsummary.c index 93f6e6d408a80..cd7a6b147b289 100644 --- a/src/bin/pg_walsummary/pg_walsummary.c +++ b/src/bin/pg_walsummary/pg_walsummary.c @@ -3,7 +3,7 @@ * pg_walsummary.c * Prints the contents of WAL summary files. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/bin/pg_walsummary/pg_walsummary.c @@ -20,7 +20,6 @@ #include "common/logging.h" #include "fe_utils/option_utils.h" #include "getopt_long.h" -#include "lib/stringinfo.h" typedef struct ws_options { @@ -71,7 +70,7 @@ main(int argc, char *argv[]) handle_help_version_opts(argc, argv, progname, help); /* process command-line options */ - while ((c = getopt_long(argc, argv, "f:iqw:", + while ((c = getopt_long(argc, argv, "iq", long_options, &optindex)) != -1) { switch (c) diff --git a/src/bin/pg_walsummary/po/LINGUAS b/src/bin/pg_walsummary/po/LINGUAS index c675cfe1c72a6..a6af4f7c83594 100644 --- a/src/bin/pg_walsummary/po/LINGUAS +++ b/src/bin/pg_walsummary/po/LINGUAS @@ -1 +1 @@ -de ja ka +de es fr ja ka ko ru sv uk diff --git a/src/bin/pg_walsummary/po/es.po b/src/bin/pg_walsummary/po/es.po new file mode 100644 index 0000000000000..7584da24ef575 --- /dev/null +++ b/src/bin/pg_walsummary/po/es.po @@ -0,0 +1,187 @@ +# Spanish translation file for pg_walsummary +# +# Copyright (c) 2024, PostgreSQL Global Development Group +# This file is distributed under the same license as the PostgreSQL package. +# +# Alvaro Herrera , 2024 +# +msgid "" +msgstr "" +"Project-Id-Version: pg_walsummary (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-11-16 05:23+0000\n" +"PO-Revision-Date: 2024-08-01 12:41-0400\n" +"Last-Translator: Álvaor Herrera \n" +"Language-Team: PgSQL-es-Ayuda \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Vim\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "error: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "precaución: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "detalle: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "consejo: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "memoria agotada\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "no se puede duplicar un puntero nulo (error interno)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "el valor «%s» no es válido para la opción %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s debe estar en el rango %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Pruebe «%s --help» para mayor información." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "no se especificaron archivos de entrada" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "no se pudo leer el archivo «%s»: %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "" +"%s prints the contents of a WAL summary file.\n" +"\n" +msgstr "" +"%s imprime el contenido de un archivo de resumen de WAL.\n" +"\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "Empleo:\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [OPCIÓN]... ARCHIVO...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Opciones:\n" + +#: pg_walsummary.c:271 +#, c-format +msgid " -i, --individual list block numbers individually, not as ranges\n" +msgstr " -i, --individual listar números de bloque individualmente, no como rangos\n" + +#: pg_walsummary.c:272 +#, c-format +msgid " -q, --quiet don't print anything, just parse the files\n" +msgstr " -q, --quiet no escribir nada, sólo procesar los archivos\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version mostrar información de version y salir\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help mostrar esta ayuda y salir\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Reporte errores a <%s>.\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Sitio web de %s: <%s>\n" diff --git a/src/bin/pg_walsummary/po/fr.po b/src/bin/pg_walsummary/po/fr.po new file mode 100644 index 0000000000000..cdedfd51bdf22 --- /dev/null +++ b/src/bin/pg_walsummary/po/fr.po @@ -0,0 +1,185 @@ +# LANGUAGE message translation file for pg_walsummary +# Copyright (C) 2024 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_walsummary (PostgreSQL) package. +# FIRST AUTHOR , 2024. +# +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-08-23 10:22+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" +"Last-Translator: Guillaume Lelarge \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.5\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "erreur : " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "attention : " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "détail : " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "astuce : " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "mémoire épuisée\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "valeur « %s » invalide pour l'option %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s doit être compris entre %d et %d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Essayez « %s --help » pour plus d'informations." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "aucun fichier spécifié en entrée" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "n'a pas pu lire le fichier « %s » : %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "" +"%s prints the contents of a WAL summary file.\n" +"\n" +msgstr "" +"%s affiche le contenu d'un fichier de résumé de WAL.\n" +"\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "Usage :\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [OPTION]... FICHIER...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Options :\n" + +#: pg_walsummary.c:271 +#, c-format +msgid " -i, --individual list block numbers individually, not as ranges\n" +msgstr " -i, --individual liste les numéros de bloc individuellement, pas sous la forme d'intervalles\n" + +#: pg_walsummary.c:272 +#, c-format +msgid " -q, --quiet don't print anything, just parse the files\n" +msgstr " -q, --quiet n'affiche rien, analyse uniquement les fichiers\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version affiche la version puis quitte\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help affiche cette aide puis quitte\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Rapporter les bogues à <%s>.\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Page d'accueil de %s : <%s>\n" diff --git a/src/bin/pg_walsummary/po/ka.po b/src/bin/pg_walsummary/po/ka.po index 0552b378d6cec..90157c57b0e65 100644 --- a/src/bin/pg_walsummary/po/ka.po +++ b/src/bin/pg_walsummary/po/ka.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: pg_walsummary (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-02-11 23:52+0000\n" -"PO-Revision-Date: 2024-02-12 04:18+0100\n" +"POT-Creation-Date: 2024-06-24 21:54+0000\n" +"PO-Revision-Date: 2024-06-25 05:47+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: \n" "Language: ka\n" @@ -37,27 +37,91 @@ msgstr "დეტალები: " msgid "hint: " msgstr "მინიშნება: " -#: pg_walsummary.c:85 pg_walsummary.c:93 +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 #, c-format -msgid "Try \"%s --help\" for more information." -msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." +msgid "out of memory\n" +msgstr "არასაკმარისი მეხსიერება\n" -#: pg_walsummary.c:92 +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 #, c-format -msgid "%s: no input files specified" -msgstr "%s: შეყვანის ფაილები მითითებული არაა" +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: pg_walsummary.c:107 +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: pg_walsummary.c:255 +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "ფაილი \"%s\" არ არსებობს: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "გადარქმევის შეცდომა %s - %s: %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "არასწორი მნიშვნელობა \"%s\" პარამეტრისთვის %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s არაა საზღვრებში %d-დან %d-მდე" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "უცნობი სინქრონიზაციის მეთოდი: \"%s\"" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "შეყვანის ფაილები მითითებული არაა" + +#: pg_walsummary.c:252 #, c-format msgid "could not read file \"%s\": %m" msgstr "ფაილის (%s) წაკითხვის შეცდომა: %m" -#: pg_walsummary.c:270 +#: pg_walsummary.c:267 #, c-format msgid "" "%s prints the contents of a WAL summary file.\n" @@ -66,17 +130,17 @@ msgstr "" "%s WAL შეჯამების ფაილის შემცველობას გამოიტანს.\n" "\n" -#: pg_walsummary.c:271 +#: pg_walsummary.c:268 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: pg_walsummary.c:272 +#: pg_walsummary.c:269 #, c-format msgid " %s [OPTION]... FILE...\n" msgstr " %s [პარამეტრი]... ფაილი...\n" -#: pg_walsummary.c:273 +#: pg_walsummary.c:270 #, c-format msgid "" "\n" @@ -85,22 +149,27 @@ msgstr "" "\n" "პარამეტრები:\n" -#: pg_walsummary.c:274 +#: pg_walsummary.c:271 #, c-format msgid " -i, --individual list block numbers individually, not as ranges\n" msgstr " -i, --individual ბლოკის ნომრების ცალ-ცალკე გამოტანა, შუალედების მაგიერ\n" -#: pg_walsummary.c:275 +#: pg_walsummary.c:272 #, c-format msgid " -q, --quiet don't print anything, just parse the files\n" msgstr " -q, --quiet ეკრანზე არაფერი გამოიტანო. უბრალოდ, ფაილები დაამუშავე\n" -#: pg_walsummary.c:276 +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" + +#: pg_walsummary.c:274 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: pg_walsummary.c:278 +#: pg_walsummary.c:276 #, c-format msgid "" "\n" @@ -109,7 +178,7 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: pg_walsummary.c:279 +#: pg_walsummary.c:277 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" diff --git a/src/bin/pg_walsummary/po/ko.po b/src/bin/pg_walsummary/po/ko.po new file mode 100644 index 0000000000000..fdd116411d8fa --- /dev/null +++ b/src/bin/pg_walsummary/po/ko.po @@ -0,0 +1,187 @@ +# Korean message translation file for pg_combinebackup +# Copyright (C) 2025 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_combinebackup (PostgreSQL) package. +# Ioseph Kim , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: pg_walsummary (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2025-01-17 04:53+0000\n" +"PO-Revision-Date: 2025-01-16 14:00+0900\n" +"Last-Translator: Ioseph Kim \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "오류: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "경고: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "상세정보: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "힌트: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "메모리 부족\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "null 포인터를 중복할 수 없음 (내부 오류)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일 대상으로 파일 시스템 동기화를 할 수 없습니다: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일 fsync 실패: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "\"%s\" 값은 %s 옵션의 값으로 적당하지 않음" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s 값은 %d부터 %d까지만 허용합니다" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "입력 파일을 지정하지 않았음" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "\"%s\" 파일을 읽을 수 없음: %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "" +"%s prints the contents of a WAL summary file.\n" +"\n" +msgstr "" +"%s 프로그램은 WAL 요약 파일의 내용을 보여줍니다.\n" +"\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "사용법:\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [OPTION]... 파일...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"옵션들:\n" + +#: pg_walsummary.c:271 +#, c-format +msgid "" +" -i, --individual list block numbers individually, not as ranges\n" +msgstr "" +" -i, --individual 블록 번호를 범위로 보여주지 않고, 각각 나일함\n" + +#: pg_walsummary.c:272 +#, c-format +msgid "" +" -q, --quiet don't print anything, just parse the files\n" +msgstr "" +" -q, --quiet 어떤 정보도 보여주지 않고, 그냥 분석만 함\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version 버전 정보를 보여주고 마침\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help 이 도움말을 보여주고 마침\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"문제점 보고 주소: <%s>\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "%s 홈페이지: <%s>\n" diff --git a/src/bin/pg_walsummary/po/meson.build b/src/bin/pg_walsummary/po/meson.build index e8ce4a6a20c3b..40ed4cdde42b4 100644 --- a/src/bin/pg_walsummary/po/meson.build +++ b/src/bin/pg_walsummary/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pg_walsummary-' + pg_version_major.to_string())] diff --git a/src/bin/pg_walsummary/po/ru.po b/src/bin/pg_walsummary/po/ru.po new file mode 100644 index 0000000000000..1dcd7aaf72aec --- /dev/null +++ b/src/bin/pg_walsummary/po/ru.po @@ -0,0 +1,187 @@ +# Alexander Lakhin , 2024. +msgid "" +msgstr "" +"Project-Id-Version: pg_walsummary (PostgreSQL) 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-09-02 09:31+0300\n" +"PO-Revision-Date: 2024-09-05 14:47+0300\n" +"Last-Translator: Alexander Lakhin \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Lokalize 21.12.3\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "ошибка: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "предупреждение: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "подробности: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "подсказка: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "нехватка памяти\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неверное значение \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "значение %s должно быть в диапазоне %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Для дополнительной информации попробуйте \"%s --help\"." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "нет входных файлов" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не удалось прочитать файл \"%s\": %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "" +"%s prints the contents of a WAL summary file.\n" +"\n" +msgstr "" +"%s выводит содержимое файла обобщения WAL.\n" +"\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "Использование:\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [ПАРАМЕТР]... [ФАЙЛ]...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Параметры:\n" + +#: pg_walsummary.c:271 +#, c-format +msgid "" +" -i, --individual list block numbers individually, not as ranges\n" +msgstr "" +" -i, --individual выводить номера блоков по одному, не " +"диапазонами\n" + +#: pg_walsummary.c:272 +#, c-format +msgid "" +" -q, --quiet don't print anything, just parse the files\n" +msgstr "" +" -q, --quiet не выводить ничего, только разобрать файлы\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version показать версию и выйти\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показать эту справку и выйти\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Об ошибках сообщайте по адресу <%s>.\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашняя страница %s: <%s>\n" diff --git a/src/bin/pg_walsummary/po/sv.po b/src/bin/pg_walsummary/po/sv.po new file mode 100644 index 0000000000000..14e987f3aafe2 --- /dev/null +++ b/src/bin/pg_walsummary/po/sv.po @@ -0,0 +1,181 @@ +# Swedish message translation file for pg_walsummary +# Copyright (C) 2024 PostgreSQL Global Development Group +# This file is distributed under the same license as the pg_walsummary (PostgreSQL) package. +# Dennis Björklund , 2024. +msgid "" +msgstr "" +"Project-Id-Version: PostgreSQL 17\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-07-12 17:54+0000\n" +"PO-Revision-Date: 2024-07-12 23:39+0200\n" +"Last-Translator: Dennis Björklund \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "fel: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "varning: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "detalj: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "tips: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "slut på minne\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "kan inte duplicera null-pekare (internt fel)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s måste vara i intervallet %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Försök med \"%s --help\" för mer information." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "inga inputfiler angivna" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "kunde inte läsa fil \"%s\": %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "" +"%s prints the contents of a WAL summary file.\n" +"\n" +msgstr "%s skriver ut innehållet av WAL-summeringsfilen.\n\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "Användning:\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [FLAGGA]... FIL...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "" +"\n" +"Options:\n" +msgstr "" +"\n" +"Flaggor:\n" + +#: pg_walsummary.c:271 +#, c-format +msgid " -i, --individual list block numbers individually, not as ranges\n" +msgstr " -i, --individual lista blocknummer individuellt, inte som intervall\n" + +#: pg_walsummary.c:272 +#, c-format +msgid " -q, --quiet don't print anything, just parse the files\n" +msgstr " -q, --quiet skriv ingenting, bara parsa filerna\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version visa versionsinformation, avsluta sedan\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help visa denna hjälp, avsluta sedan\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "" +"\n" +"Report bugs to <%s>.\n" +msgstr "" +"\n" +"Rapportera fel till <%s>.\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "hemsida för %s: <%s>\n" diff --git a/src/bin/pg_walsummary/po/uk.po b/src/bin/pg_walsummary/po/uk.po new file mode 100644 index 0000000000000..523b46a7f12e8 --- /dev/null +++ b/src/bin/pg_walsummary/po/uk.po @@ -0,0 +1,177 @@ +msgid "" +msgstr "" +"Project-Id-Version: postgresql\n" +"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" +"POT-Creation-Date: 2024-08-31 06:24+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" +"Last-Translator: \n" +"Language-Team: Ukrainian\n" +"Language: uk_UA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n" +"X-Crowdin-Project: postgresql\n" +"X-Crowdin-Project-ID: 324573\n" +"X-Crowdin-Language: uk\n" +"X-Crowdin-File: /REL_17_STABLE/pg_walsummary.pot\n" +"X-Crowdin-File-ID: 992\n" + +#: ../../../src/common/logging.c:276 +#, c-format +msgid "error: " +msgstr "помилка: " + +#: ../../../src/common/logging.c:283 +#, c-format +msgid "warning: " +msgstr "попередження: " + +#: ../../../src/common/logging.c:294 +#, c-format +msgid "detail: " +msgstr "деталі: " + +#: ../../../src/common/logging.c:301 +#, c-format +msgid "hint: " +msgstr "підказка: " + +#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75 +#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:161 +#, c-format +msgid "out of memory\n" +msgstr "недостатньо пам'яті\n" + +#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:153 +#, c-format +msgid "cannot duplicate null pointer (internal error)\n" +msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" + +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: pg_walsummary.c:109 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + +#: ../../fe_utils/option_utils.c:69 +#, c-format +msgid "invalid value \"%s\" for option %s" +msgstr "неприпустиме значення \"%s\" для параметра %s" + +#: ../../fe_utils/option_utils.c:76 +#, c-format +msgid "%s must be in range %d..%d" +msgstr "%s має бути в діапазоні %d..%d" + +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + +#: pg_walsummary.c:87 pg_walsummary.c:95 +#, c-format +msgid "Try \"%s --help\" for more information." +msgstr "Спробуйте \"%s --help\" для додаткової інформації." + +#: pg_walsummary.c:94 +#, c-format +msgid "no input files specified" +msgstr "не вказано вхідні файли" + +#: pg_walsummary.c:252 +#, c-format +msgid "could not read file \"%s\": %m" +msgstr "не вдалося прочитати файл \"%s\": %m" + +#: pg_walsummary.c:267 +#, c-format +msgid "%s prints the contents of a WAL summary file.\n\n" +msgstr "%s друкує вміст файлу зведення WAL.\n\n" + +#: pg_walsummary.c:268 +#, c-format +msgid "Usage:\n" +msgstr "Використання:\n" + +#: pg_walsummary.c:269 +#, c-format +msgid " %s [OPTION]... FILE...\n" +msgstr " %s [OPTION]... FILE...\n" + +#: pg_walsummary.c:270 +#, c-format +msgid "\n" +"Options:\n" +msgstr "\n" +"Параметри:\n" + +#: pg_walsummary.c:271 +#, c-format +msgid " -i, --individual list block numbers individually, not as ranges\n" +msgstr " -i, --individual вивести номера блоків індивідуально, не як діапазони\n" + +#: pg_walsummary.c:272 +#, c-format +msgid " -q, --quiet don't print anything, just parse the files\n" +msgstr " -q, --quiet не друкувати нічого, просто розібрати файли\n" + +#: pg_walsummary.c:273 +#, c-format +msgid " -V, --version output version information, then exit\n" +msgstr " -V, --version вивести інформацію про версію і вийти\n" + +#: pg_walsummary.c:274 +#, c-format +msgid " -?, --help show this help, then exit\n" +msgstr " -?, --help показати цю довідку, потім вийти\n" + +#: pg_walsummary.c:276 +#, c-format +msgid "\n" +"Report bugs to <%s>.\n" +msgstr "\n" +"Повідомляти про помилки на <%s>.\n" + +#: pg_walsummary.c:277 +#, c-format +msgid "%s home page: <%s>\n" +msgstr "Домашня сторінка %s: <%s>\n" + diff --git a/src/bin/pg_walsummary/t/001_basic.pl b/src/bin/pg_walsummary/t/001_basic.pl index 4a1555091a6f0..65509eef61ad8 100644 --- a/src/bin/pg_walsummary/t/001_basic.pl +++ b/src/bin/pg_walsummary/t/001_basic.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/pg_walsummary/t/002_blocks.pl b/src/bin/pg_walsummary/t/002_blocks.pl index 0fddbaa22f418..270332780a453 100644 --- a/src/bin/pg_walsummary/t/002_blocks.pl +++ b/src/bin/pg_walsummary/t/002_blocks.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -46,6 +46,13 @@ EOM ok($result, "WAL summarization caught up after insert"); +# The WAL summarizer should have generated some IO statistics. +my $stats_reads = $node1->safe_psql( + 'postgres', + qq{SELECT sum(reads) > 0 FROM pg_stat_io + WHERE backend_type = 'walsummarizer' AND object = 'wal'}); +is($stats_reads, 't', "WAL summarizer generates statistics for WAL reads"); + # Find the highest LSN that is summarized on disk. my $summarized_lsn = $node1->safe_psql('postgres', < 2) expr_yyerror_more(yyscanner, "unexpected number of arguments", @@ -485,11 +485,12 @@ make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args) if (len == 1) { PgBenchExpr *var = make_variable("default_seed"); + args = make_elist(var, args); } break; - /* pseudorandom permutation function with optional seed argument */ + /* pseudorandom permutation function with optional seed argument */ case PGBENCH_NARGS_PERMUTE: if (len < 2 || len > 3) expr_yyerror_more(yyscanner, "unexpected number of arguments", @@ -498,11 +499,12 @@ make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args) if (len == 2) { PgBenchExpr *var = make_variable("default_seed"); + args = make_elist(var, args); } break; - /* common case: positive arguments number */ + /* common case: positive arguments number */ default: Assert(PGBENCH_FUNCTIONS[fnumber].nargs >= 0); diff --git a/src/bin/pgbench/exprscan.l b/src/bin/pgbench/exprscan.l index e8fd13acd1354..5747af38cb2ca 100644 --- a/src/bin/pgbench/exprscan.l +++ b/src/bin/pgbench/exprscan.l @@ -15,7 +15,7 @@ * * Note that this lexer operates within the framework created by psqlscan.l, * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/pgbench/exprscan.l @@ -44,15 +44,6 @@ static const char *expr_command = NULL; /* indicates whether last yylex() call read a newline */ static bool last_was_newline = false; -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int expr_yyget_column(yyscan_t yyscanner); -extern void expr_yyset_column(int column_no, yyscan_t yyscanner); - /* LCOV_EXCL_START */ %} @@ -280,10 +271,14 @@ void expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more) { PsqlScanState state = yyget_extra(yyscanner); - int error_detection_offset = expr_scanner_offset(state) - 1; + int lineno; + int error_detection_offset; YYSTYPE lval; char *full_line; + psql_scan_get_location(state, &lineno, &error_detection_offset); + error_detection_offset--; + /* * While parsing an expression, we may not have collected the whole line * yet from the input source. Lex till EOL so we can report whole line. @@ -298,15 +293,18 @@ expr_yyerror_more(yyscan_t yyscanner, const char *message, const char *more) /* Extract the line, trimming trailing newline if any */ full_line = expr_scanner_get_substring(state, expr_start_offset, - expr_scanner_offset(state), true); syntax_error(expr_source, expr_lineno, full_line, expr_command, message, more, error_detection_offset - expr_start_offset); } +/* + * (The first argument is enforced by Bison to match the first argument of + * yyparse(), but it is not used here.) + */ void -expr_yyerror(yyscan_t yyscanner, const char *message) +expr_yyerror(PgBenchExpr **expr_parse_result_p, yyscan_t yyscanner, const char *message) { expr_yyerror_more(yyscanner, message, NULL); } @@ -341,12 +339,15 @@ expr_lex_one_word(PsqlScanState state, PQExpBuffer word_buf, int *offset) /* And lex. */ lexresult = yylex(&lval, state->scanner); - /* - * Save start offset of word, if any. We could do this more efficiently, - * but for now this seems fine. - */ + /* Save start offset of word, if any. */ if (lexresult) - *offset = expr_scanner_offset(state) - word_buf->len; + { + int lineno; + int end_offset; + + psql_scan_get_location(state, &lineno, &end_offset); + *offset = end_offset - word_buf->len; + } else *offset = -1; @@ -409,35 +410,25 @@ expr_scanner_finish(yyscan_t yyscanner) } /* - * Get offset from start of string to end of current lexer token. + * Get a malloc'd copy of the lexer input string from start_offset + * to end of current lexer token. If chomp is true, drop any trailing + * newline(s). * * We rely on the knowledge that flex modifies the scan buffer by storing * a NUL at the end of the current token (yytext). Note that this might * not work quite right if we were parsing a sub-buffer, but since pgbench - * never invokes that functionality, it doesn't matter. - */ -int -expr_scanner_offset(PsqlScanState state) -{ - return strlen(state->scanbuf); -} - -/* - * Get a malloc'd copy of the lexer input string from start_offset - * to just before end_offset. If chomp is true, drop any trailing - * newline(s). + * never invokes that functionality, it doesn't matter. Also, this will + * give the wrong answer (the whole remainder of the input) if called + * before any yylex() call has been done. */ char * expr_scanner_get_substring(PsqlScanState state, - int start_offset, int end_offset, + int start_offset, bool chomp) { char *result; const char *scanptr = state->scanbuf + start_offset; - int slen = end_offset - start_offset; - - Assert(slen >= 0); - Assert(end_offset <= strlen(state->scanbuf)); + size_t slen = strlen(scanptr); if (chomp) { @@ -452,22 +443,3 @@ expr_scanner_get_substring(PsqlScanState state, return result; } - -/* - * Get the line number associated with the given string offset - * (which must not be past the end of where we've lexed to). - */ -int -expr_scanner_get_lineno(PsqlScanState state, int offset) -{ - int lineno = 1; - const char *p = state->scanbuf; - - while (*p && offset > 0) - { - if (*p == '\n') - lineno++; - p++, offset--; - } - return lineno; -} diff --git a/src/bin/pgbench/meson.build b/src/bin/pgbench/meson.build index d330bb5eb0d5c..a2a909a8442b1 100644 --- a/src/bin/pgbench/meson.build +++ b/src/bin/pgbench/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgbench_sources = files( 'pgbench.c', diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 61618f2e188fc..497a936c141f3 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -5,7 +5,7 @@ * Originally written by Tatsuo Ishii and enhanced by many contributors. * * src/bin/pgbench/pgbench.c - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * ALL RIGHTS RESERVED; * * Permission to use, copy, modify, and distribute this software and its @@ -53,6 +53,7 @@ #include #endif +#include "catalog/pg_class_d.h" #include "common/int.h" #include "common/logging.h" #include "common/pg_prng.h" @@ -848,6 +849,31 @@ static const PsqlScanCallbacks pgbench_callbacks = { NULL, /* don't need get_variable functionality */ }; +static char +get_table_relkind(PGconn *con, const char *table) +{ + PGresult *res; + char *val; + char relkind; + const char *params[1] = {table}; + const char *sql = + "SELECT relkind FROM pg_catalog.pg_class WHERE oid=$1::pg_catalog.regclass"; + + res = PQexecParams(con, sql, 1, NULL, params, NULL, NULL, 0); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + pg_log_error("query failed: %s", PQerrorMessage(con)); + pg_log_error_detail("Query was: %s", sql); + exit(1); + } + val = PQgetvalue(res, 0, 0); + Assert(strlen(val) == 1); + relkind = val[0]; + PQclear(res); + + return relkind; +} + static inline pg_time_usec_t pg_time_now(void) { @@ -2253,15 +2279,10 @@ evalStandardFunc(CState *st, { /* evaluate all function arguments */ int nargs = 0; + PgBenchValue vargs[MAX_FARGS] = {0}; PgBenchExprLink *l = args; bool has_null = false; - /* - * This value is double braced to workaround GCC bug 53119, which seems to - * exist at least on gcc (Debian 4.7.2-5) 4.7.2, 32-bit. - */ - PgBenchValue vargs[MAX_FARGS] = {{0}}; - for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next) { if (!evaluateExpr(st, l->expr, &vargs[nargs])) @@ -3880,8 +3901,14 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) switch (conditional_stack_peek(st->cstack)) { case IFSTATE_FALSE: - if (command->meta == META_IF || - command->meta == META_ELIF) + if (command->meta == META_IF) + { + /* nested if in skipped branch - ignore */ + conditional_stack_push(st->cstack, + IFSTATE_IGNORED); + st->command++; + } + else if (command->meta == META_ELIF) { /* we must evaluate the condition */ st->state = CSTATE_START_COMMAND; @@ -3900,11 +3927,7 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) conditional_stack_pop(st->cstack); if (conditional_active(st->cstack)) st->state = CSTATE_START_COMMAND; - - /* - * else state remains in - * CSTATE_SKIP_COMMAND - */ + /* else state remains CSTATE_SKIP_COMMAND */ st->command++; } break; @@ -4865,7 +4888,7 @@ initCreateTables(PGconn *con) /* Construct new create table statement. */ printfPQExpBuffer(&query, "create%s table %s(%s)", - unlogged_tables ? " unlogged" : "", + (unlogged_tables && partition_method == PART_NONE) ? " unlogged" : "", ddl->table, (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols); @@ -4944,6 +4967,7 @@ initPopulateTable(PGconn *con, const char *table, int64 base, int n; int64 k; int chars = 0; + int prev_chars = 0; PGresult *res; PQExpBufferData sql; char copy_statement[256]; @@ -4959,16 +4983,11 @@ initPopulateTable(PGconn *con, const char *table, int64 base, initPQExpBuffer(&sql); - /* - * Use COPY with FREEZE on v14 and later for all the tables except - * pgbench_accounts when it is partitioned. - */ - if (PQserverVersion(con) >= 140000) - { - if (strcmp(table, "pgbench_accounts") != 0 || - partitions == 0) - copy_statement_fmt = "copy %s from stdin with (freeze on)"; - } + /* Use COPY with FREEZE on v14 and later for all ordinary tables */ + if ((PQserverVersion(con) >= 140000) && + get_table_relkind(con, table) == RELKIND_RELATION) + copy_statement_fmt = "copy %s from stdin with (freeze on)"; + n = pg_snprintf(copy_statement, sizeof(copy_statement), copy_statement_fmt, table); if (n >= sizeof(copy_statement)) @@ -5004,10 +5023,20 @@ initPopulateTable(PGconn *con, const char *table, int64 base, double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start); double remaining_sec = ((double) total - j) * elapsed_sec / j; - chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)%c", + chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)", j, total, (int) ((j * 100) / total), - table, elapsed_sec, remaining_sec, eol); + table, elapsed_sec, remaining_sec); + + /* + * If the previous progress message is longer than the current + * one, add spaces to the current line to fully overwrite any + * remaining characters from the previous message. + */ + if (prev_chars > chars) + fprintf(stderr, "%*c", prev_chars - chars, ' '); + fputc(eol, stderr); + prev_chars = chars; } /* let's not call the timing for each row, but only each 100 rows */ else if (use_quiet && (j % 100 == 0)) @@ -5018,10 +5047,20 @@ initPopulateTable(PGconn *con, const char *table, int64 base, /* have we reached the next interval (or end)? */ if ((j == total) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS)) { - chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)%c", + chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)", j, total, (int) ((j * 100) / total), - table, elapsed_sec, remaining_sec, eol); + table, elapsed_sec, remaining_sec); + + /* + * If the previous progress message is longer than the current + * one, add spaces to the current line to fully overwrite any + * remaining characters from the previous message. + */ + if (prev_chars > chars) + fprintf(stderr, "%*c", prev_chars - chars, ' '); + fputc(eol, stderr); + prev_chars = chars; /* skip to the next interval */ log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS); @@ -5030,7 +5069,7 @@ initPopulateTable(PGconn *con, const char *table, int64 base, } if (chars != 0 && eol != '\n') - fprintf(stderr, "%*c\r", chars - 1, ' '); /* Clear the current line */ + fprintf(stderr, "%*c\r", chars, ' '); /* Clear the current line */ if (PQputline(con, "\\.\n")) pg_fatal("very last PQputline failed"); @@ -5633,22 +5672,17 @@ postprocess_sql_command(Command *my_command) * At call, we have scanned only the initial backslash. */ static Command * -process_backslash_command(PsqlScanState sstate, const char *source) +process_backslash_command(PsqlScanState sstate, const char *source, + int lineno, int start_offset) { Command *my_command; PQExpBufferData word_buf; int word_offset; int offsets[MAX_ARGS]; /* offsets of argument words */ - int start_offset; - int lineno; int j; initPQExpBuffer(&word_buf); - /* Remember location of the backslash */ - start_offset = expr_scanner_offset(sstate) - 1; - lineno = expr_scanner_get_lineno(sstate, start_offset); - /* Collect first word of command */ if (!expr_lex_one_word(sstate, &word_buf, &word_offset)) { @@ -5693,19 +5727,16 @@ process_backslash_command(PsqlScanState sstate, const char *source) yyscanner = expr_scanner_init(sstate, source, lineno, start_offset, my_command->argv[0]); - if (expr_yyparse(yyscanner) != 0) + if (expr_yyparse(&my_command->expr, yyscanner) != 0) { /* dead code: exit done from syntax_error called by yyerror */ exit(1); } - my_command->expr = expr_parse_result; - /* Save line, trimming any trailing newline */ my_command->first_line = expr_scanner_get_substring(sstate, start_offset, - expr_scanner_offset(sstate), true); expr_scanner_finish(yyscanner); @@ -5735,7 +5766,6 @@ process_backslash_command(PsqlScanState sstate, const char *source) my_command->first_line = expr_scanner_get_substring(sstate, start_offset, - expr_scanner_offset(sstate), true); if (my_command->meta == META_SLEEP) @@ -5910,8 +5940,6 @@ ParseScript(const char *script, const char *desc, int weight) PQExpBufferData line_buf; int alloc_num; int index; - int lineno; - int start_offset; #define COMMANDS_ALLOC_NUM 128 alloc_num = COMMANDS_ALLOC_NUM; @@ -5935,7 +5963,6 @@ ParseScript(const char *script, const char *desc, int weight) * stdstrings should be true, which is a bit riskier. */ psql_scan_setup(sstate, script, strlen(script), 0, true); - start_offset = expr_scanner_offset(sstate) - 1; initPQExpBuffer(&line_buf); @@ -5948,7 +5975,6 @@ ParseScript(const char *script, const char *desc, int weight) Command *command = NULL; resetPQExpBuffer(&line_buf); - lineno = expr_scanner_get_lineno(sstate, start_offset); sr = psql_scan(sstate, &line_buf, &prompt); @@ -5962,7 +5988,15 @@ ParseScript(const char *script, const char *desc, int weight) /* If we reached a backslash, process that */ if (sr == PSCAN_BACKSLASH) { - command = process_backslash_command(sstate, desc); + int lineno; + int start_offset; + + /* Capture location of the backslash */ + psql_scan_get_location(sstate, &lineno, &start_offset); + start_offset--; + + command = process_backslash_command(sstate, desc, + lineno, start_offset); if (command) { @@ -6391,6 +6425,13 @@ printResults(StatsData *total, total->cnt); } + /* + * Remaining stats are nonsensical if we failed to execute any xacts due + * to others than serialization or deadlock errors + */ + if (total_cnt <= 0) + return; + printf("number of failed transactions: " INT64_FORMAT " (%.3f%%)\n", failures, 100.0 * failures / total_cnt); @@ -6412,10 +6453,6 @@ printResults(StatsData *total, printf("total number of retries: " INT64_FORMAT "\n", total->retries); } - /* Remaining stats are nonsensical if we failed to execute any xacts */ - if (total->cnt + total->skipped <= 0) - return; - if (throttle_delay && latency_limit) printf("number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n", total->skipped, 100.0 * total->skipped / total_cnt); @@ -6483,45 +6520,53 @@ printResults(StatsData *total, printf("SQL script %d: %s\n" " - weight: %d (targets %.1f%% of total)\n" - " - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n", + " - " INT64_FORMAT " transactions (%.1f%% of total)\n", i + 1, sql_script[i].desc, sql_script[i].weight, 100.0 * sql_script[i].weight / total_weight, - sstats->cnt, - 100.0 * sstats->cnt / total->cnt, - sstats->cnt / bench_duration); + script_total_cnt, + 100.0 * script_total_cnt / total_cnt); - printf(" - number of failed transactions: " INT64_FORMAT " (%.3f%%)\n", - script_failures, - 100.0 * script_failures / script_total_cnt); - - if (failures_detailed) + if (script_total_cnt > 0) { - printf(" - number of serialization failures: " INT64_FORMAT " (%.3f%%)\n", - sstats->serialization_failures, - (100.0 * sstats->serialization_failures / - script_total_cnt)); - printf(" - number of deadlock failures: " INT64_FORMAT " (%.3f%%)\n", - sstats->deadlock_failures, - (100.0 * sstats->deadlock_failures / - script_total_cnt)); - } + printf(" - number of transactions actually processed: " INT64_FORMAT " (tps = %f)\n", + sstats->cnt, sstats->cnt / bench_duration); - /* it can be non-zero only if max_tries is not equal to one */ - if (max_tries != 1) - { - printf(" - number of transactions retried: " INT64_FORMAT " (%.3f%%)\n", - sstats->retried, - 100.0 * sstats->retried / script_total_cnt); - printf(" - total number of retries: " INT64_FORMAT "\n", - sstats->retries); - } + printf(" - number of failed transactions: " INT64_FORMAT " (%.3f%%)\n", + script_failures, + 100.0 * script_failures / script_total_cnt); - if (throttle_delay && latency_limit && script_total_cnt > 0) - printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n", - sstats->skipped, - 100.0 * sstats->skipped / script_total_cnt); + if (failures_detailed) + { + printf(" - number of serialization failures: " INT64_FORMAT " (%.3f%%)\n", + sstats->serialization_failures, + (100.0 * sstats->serialization_failures / + script_total_cnt)); + printf(" - number of deadlock failures: " INT64_FORMAT " (%.3f%%)\n", + sstats->deadlock_failures, + (100.0 * sstats->deadlock_failures / + script_total_cnt)); + } + /* + * it can be non-zero only if max_tries is not equal to + * one + */ + if (max_tries != 1) + { + printf(" - number of transactions retried: " INT64_FORMAT " (%.3f%%)\n", + sstats->retried, + 100.0 * sstats->retried / script_total_cnt); + printf(" - total number of retries: " INT64_FORMAT "\n", + sstats->retries); + } + + if (throttle_delay && latency_limit) + printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n", + sstats->skipped, + 100.0 * sstats->skipped / script_total_cnt); + + } printSimpleStats(" - latency", &sstats->latency); } @@ -6546,13 +6591,13 @@ printResults(StatsData *total, SimpleStats *cstats = &(*commands)->stats; if (max_tries == 1) - printf(" %11.3f %10" INT64_MODIFIER "d %s\n", + printf(" %11.3f %10" PRId64 " %s\n", (cstats->count > 0) ? 1000.0 * cstats->sum / cstats->count : 0.0, (*commands)->failures, (*commands)->first_line); else - printf(" %11.3f %10" INT64_MODIFIER "d %10" INT64_MODIFIER "d %s\n", + printf(" %11.3f %10" PRId64 " %10" PRId64 " %s\n", (cstats->count > 0) ? 1000.0 * cstats->sum / cstats->count : 0.0, (*commands)->failures, @@ -6589,27 +6634,23 @@ set_random_seed(const char *seed) } else { - /* parse unsigned-int seed value */ - unsigned long ulseed; char garbage; - /* Don't try to use UINT64_FORMAT here; it might not work for sscanf */ - if (sscanf(seed, "%lu%c", &ulseed, &garbage) != 1) + if (sscanf(seed, "%" SCNu64 "%c", &iseed, &garbage) != 1) { pg_log_error("unrecognized random seed option \"%s\"", seed); pg_log_error_detail("Expecting an unsigned integer, \"time\" or \"rand\"."); return false; } - iseed = (uint64) ulseed; } if (seed != NULL) - pg_log_info("setting random seed to %llu", (unsigned long long) iseed); + pg_log_info("setting random seed to %" PRIu64, iseed); random_seed = iseed; /* Initialize base_random_sequence using seed */ - pg_prng_seed(&base_random_sequence, (uint64) iseed); + pg_prng_seed(&base_random_sequence, iseed); return true; } @@ -6762,13 +6803,26 @@ main(int argc, char **argv) #ifdef HAVE_GETRLIMIT if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) pg_fatal("getrlimit failed: %m"); - if (rlim.rlim_cur < nclients + 3) + + if (rlim.rlim_max < nclients + 3) { pg_log_error("need at least %d open files, but system limit is %ld", - nclients + 3, (long) rlim.rlim_cur); + nclients + 3, (long) rlim.rlim_max); pg_log_error_hint("Reduce number of clients, or use limit/ulimit to increase the system limit."); exit(1); } + + if (rlim.rlim_cur < nclients + 3) + { + rlim.rlim_cur = nclients + 3; + if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) + { + pg_log_error("need at least %d open files, but couldn't raise the limit: %m", + nclients + 3); + pg_log_error_hint("Reduce number of clients, or use limit/ulimit to increase the system limit."); + exit(1); + } + } #endif /* HAVE_GETRLIMIT */ break; case 'C': diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index 177f218c223c7..e053c9e2eb63d 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/pgbench/pgbench.h @@ -2,7 +2,7 @@ * * pgbench.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *------------------------------------------------------------------------- @@ -138,28 +138,24 @@ struct PgBenchExprList PgBenchExprLink *tail; }; -extern PgBenchExpr *expr_parse_result; - -extern int expr_yyparse(yyscan_t yyscanner); +extern int expr_yyparse(PgBenchExpr **expr_parse_result_p, yyscan_t yyscanner); extern int expr_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner); -extern void expr_yyerror(yyscan_t yyscanner, const char *message) pg_attribute_noreturn(); -extern void expr_yyerror_more(yyscan_t yyscanner, const char *message, - const char *more) pg_attribute_noreturn(); +pg_noreturn extern void expr_yyerror(PgBenchExpr **expr_parse_result_p, yyscan_t yyscanner, const char *message); +pg_noreturn extern void expr_yyerror_more(yyscan_t yyscanner, const char *message, + const char *more); extern bool expr_lex_one_word(PsqlScanState state, PQExpBuffer word_buf, int *offset); extern yyscan_t expr_scanner_init(PsqlScanState state, const char *source, int lineno, int start_offset, const char *command); extern void expr_scanner_finish(yyscan_t yyscanner); -extern int expr_scanner_offset(PsqlScanState state); extern char *expr_scanner_get_substring(PsqlScanState state, - int start_offset, int end_offset, + int start_offset, bool chomp); -extern int expr_scanner_get_lineno(PsqlScanState state, int offset); -extern void syntax_error(const char *source, int lineno, const char *line, - const char *command, const char *msg, - const char *more, int column) pg_attribute_noreturn(); +pg_noreturn extern void syntax_error(const char *source, int lineno, const char *line, + const char *command, const char *msg, + const char *more, int column); extern bool strtoint64(const char *str, bool errorOK, int64 *result); extern bool strtodouble(const char *str, bool errorOK, double *dv); diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index 956e290f3efab..7dd7894030032 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -213,7 +213,7 @@ sub check_data_state { my ($stderr); - run_log([ 'pgbench', '-j', '2', '--bad-option' ], '2>', \$stderr); + run_log([ 'pgbench', '--jobs' => '2', '--bad-option' ], '2>' => \$stderr); $nthreads = 1 if $stderr =~ m/threads are not supported on this platform/; } @@ -668,6 +668,56 @@ sub check_data_state } }); +# test nested \if constructs +$node->pgbench( + '--no-vacuum --client=1 --exit-on-abort --transactions=1', + 0, + [qr{actually processed}], + [qr{^$}], + 'nested ifs', + { + 'pgbench_nested_if' => q( + \if false + SELECT 1 / 0; + \if true + SELECT 1 / 0; + \elif true + SELECT 1 / 0; + \else + SELECT 1 / 0; + \endif + SELECT 1 / 0; + \elif false + \if true + SELECT 1 / 0; + \elif true + SELECT 1 / 0; + \else + SELECT 1 / 0; + \endif + \else + \if false + SELECT 1 / 0; + \elif false + SELECT 1 / 0; + \else + SELECT 'correct'; + \endif + \endif + \if true + SELECT 'correct'; + \else + \if true + SELECT 1 / 0; + \elif true + SELECT 1 / 0; + \else + SELECT 1 / 0; + \endif + \endif + ) + }); + # random determinism when seeded $node->safe_psql('postgres', 'CREATE UNLOGGED TABLE seeded_random(seed INT8 NOT NULL, rand TEXT NOT NULL, val INTEGER NOT NULL);' @@ -968,6 +1018,180 @@ sub check_data_state } }); +# Try SET LOCAL as first pipeline command. This succeeds and the first +# command is not executed inside an implicit transaction block, causing +# a WARNING. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [qr{WARNING: SET LOCAL can only be used in transaction blocks}], + 'SET LOCAL outside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_set_local_1' => q{ +\startpipeline +SET LOCAL statement_timeout='1h'; +\endpipeline +} + }); + +# Try SET LOCAL as second pipeline command. This succeeds and the second +# command does not cause a WARNING to be generated. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [qr{^$}], + 'SET LOCAL inside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_set_local_2' => q{ +\startpipeline +SELECT 1; +SET LOCAL statement_timeout='1h'; +\endpipeline +} + }); + +# Try SET LOCAL with \syncpipeline. This succeeds and the command +# launched after the sync is outside the implicit transaction block +# of the pipeline, causing a WARNING. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [qr{WARNING: SET LOCAL can only be used in transaction blocks}], + 'SET LOCAL and \syncpipeline', + { + '001_pgbench_pipeline_set_local_3' => q{ +\startpipeline +SELECT 1; +\syncpipeline +SET LOCAL statement_timeout='1h'; +\endpipeline +} + }); + +# Try REINDEX CONCURRENTLY as first pipeline command. This succeeds +# as the first command is outside the implicit transaction block of +# a pipeline. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [], + 'REINDEX CONCURRENTLY outside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_reindex_1' => q{ +\startpipeline +REINDEX TABLE CONCURRENTLY pgbench_accounts; +SELECT 1; +\endpipeline +} + }); + +# Try REINDEX CONCURRENTLY as second pipeline command. This fails +# as the second command is inside an implicit transaction block. +$node->pgbench( + '-t 1 -n -M extended', + 2, + [], + [], + 'error: REINDEX CONCURRENTLY inside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_reindex_2' => q{ +\startpipeline +SELECT 1; +REINDEX TABLE CONCURRENTLY pgbench_accounts; +\endpipeline +} + }); + +# Try VACUUM as first pipeline command. Like REINDEX CONCURRENTLY, this +# succeeds as this is outside the implicit transaction block of a pipeline. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [], + 'VACUUM outside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_vacuum_1' => q{ +\startpipeline +VACUUM pgbench_accounts; +\endpipeline +} + }); + +# Try VACUUM as second pipeline command. This fails, as the second command +# of a pipeline is inside an implicit transaction block. +$node->pgbench( + '-t 1 -n -M extended', + 2, + [], + [], + 'error: VACUUM inside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_vacuum_2' => q{ +\startpipeline +SELECT 1; +VACUUM pgbench_accounts; +\endpipeline +} + }); + +# Try subtransactions in a pipeline. These are forbidden in implicit +# transaction blocks. +$node->pgbench( + '-t 1 -n -M extended', + 2, + [], + [], + 'error: subtransactions not allowed in pipeline', + { + '001_pgbench_pipeline_subtrans' => q{ +\startpipeline +SAVEPOINT a; +SELECT 1; +ROLLBACK TO SAVEPOINT a; +SELECT 2; +\endpipeline +} + }); + +# Try LOCK TABLE as first pipeline command. This fails as LOCK is outside +# an implicit transaction block. +$node->pgbench( + '-t 1 -n -M extended', + 2, + [], + [], + 'error: LOCK TABLE outside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_lock_1' => q{ +\startpipeline +LOCK pgbench_accounts; +SELECT 1; +\endpipeline +} + }); + +# Try LOCK TABLE as second pipeline command. This succeeds as LOCK is inside +# an implicit transaction block. +$node->pgbench( + '-t 1 -n -M extended', + 0, + [], + [], + 'LOCK TABLE inside implicit transaction block of pipeline', + { + '001_pgbench_pipeline_lock_2' => q{ +\startpipeline +SELECT 1; +LOCK pgbench_accounts; +\endpipeline +} + }); + # Working \startpipeline in prepared query mode with serializable $node->pgbench( '-c4 -t 10 -n -M prepared', diff --git a/src/bin/pgbench/t/002_pgbench_no_server.pl b/src/bin/pgbench/t/002_pgbench_no_server.pl index a04b3531f42d3..f975c73dd758a 100644 --- a/src/bin/pgbench/t/002_pgbench_no_server.pl +++ b/src/bin/pgbench/t/002_pgbench_no_server.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # pgbench tests which do not need a server @@ -50,7 +50,7 @@ sub pgbench_scripts # cleanup from prior runs unlink $filename; append_to_file($filename, $$files{$fn}); - push @cmd, '-f', $filename; + push @cmd, '--file' => $filename; } } command_checks_all(\@cmd, $stat, $out, $err, $name); diff --git a/src/bin/pgevent/Makefile b/src/bin/pgevent/Makefile index c2207a0f4b599..f2adcce990f69 100644 --- a/src/bin/pgevent/Makefile +++ b/src/bin/pgevent/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/pgevent # -# Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Copyright (c) 1996-2025, PostgreSQL Global Development Group # #------------------------------------------------------------------------- diff --git a/src/bin/pgevent/meson.build b/src/bin/pgevent/meson.build index 5c2d296fef918..6ec04e9548d39 100644 --- a/src/bin/pgevent/meson.build +++ b/src/bin/pgevent/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if host_system != 'windows' subdir_done() @@ -21,13 +21,11 @@ if cc.get_id() == 'msvc' pgevent_link_args += '/ignore:4104' endif -pgevent = shared_library('pgevent', +pgevent = shared_module('pgevent', pgevent_sources, dependencies: [frontend_code], link_args: pgevent_link_args, vs_module_defs: 'pgevent.def', - kwargs: default_lib_args + { - 'name_prefix': '', - }, + kwargs: default_mod_args, ) bin_targets += pgevent diff --git a/src/bin/pgevent/pgevent.c b/src/bin/pgevent/pgevent.c index 807a2c93120d6..020893342aaa7 100644 --- a/src/bin/pgevent/pgevent.c +++ b/src/bin/pgevent/pgevent.c @@ -15,14 +15,14 @@ #include /* Global variables */ -HANDLE g_module = NULL; /* hModule of DLL */ +static HANDLE g_module = NULL; /* hModule of DLL */ /* * The event source is stored as a registry key. * The maximum length of a registry key is 255 characters. * http://msdn.microsoft.com/en-us/library/ms724872(v=vs.85).aspx */ -char event_source[256] = DEFAULT_EVENT_SOURCE; +static char event_source[256] = DEFAULT_EVENT_SOURCE; /* Prototypes */ HRESULT DllInstall(BOOL bInstall, LPCWSTR pszCmdLine); diff --git a/src/bin/psql/.gitignore b/src/bin/psql/.gitignore index 10b6dd3a6bd4d..7272f6e35db2e 100644 --- a/src/bin/psql/.gitignore +++ b/src/bin/psql/.gitignore @@ -1,4 +1,5 @@ /psqlscanslash.c +/tab-complete.c /sql_help.h /sql_help.c /psql diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile index 374c4c3ab8f83..5b1545d9948ad 100644 --- a/src/bin/psql/Makefile +++ b/src/bin/psql/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/psql # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/psql/Makefile @@ -60,7 +60,9 @@ sql_help.h: create_help.pl $(wildcard $(REFDOCDIR)/*.sgml) psqlscanslash.c: FLEXFLAGS = -Cfe -p -p psqlscanslash.c: FLEX_NO_BACKUP=yes -psqlscanslash.c: FLEX_FIX_WARNING=yes + +tab-complete.c: gen_tabcomplete.pl tab-complete.in.c + $(PERL) $^ --outfile $@ install: all installdirs $(INSTALL_PROGRAM) psql$(X) '$(DESTDIR)$(bindir)/psql$(X)' @@ -75,7 +77,7 @@ uninstall: clean distclean: rm -f psql$(X) $(OBJS) lex.backup rm -rf tmp_check - rm -f sql_help.h sql_help.c psqlscanslash.c + rm -f sql_help.h sql_help.c psqlscanslash.c tab-complete.c check: $(prove_check) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 180781ecd0525..83e84a778411a 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/command.c */ @@ -30,7 +30,6 @@ #include "common/logging.h" #include "common/string.h" #include "copy.h" -#include "crosstabview.h" #include "describe.h" #include "fe_utils/cancel.h" #include "fe_utils/print.h" @@ -38,10 +37,8 @@ #include "help.h" #include "input.h" #include "large_obj.h" -#include "libpq-fe.h" #include "libpq/pqcomm.h" #include "mainloop.h" -#include "portability/instr_time.h" #include "pqexpbuffer.h" #include "psqlscanslash.h" #include "settings.h" @@ -64,10 +61,14 @@ static backslashResult exec_command(const char *cmd, PQExpBuffer previous_buf); static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_bind(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_bind_named(PsqlScanState scan_state, bool active_branch, + const char *cmd); static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd); +static backslashResult exec_command_close(PsqlScanState scan_state, bool active_branch, + const char *cmd); static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch); @@ -89,9 +90,12 @@ static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalSt PQExpBuffer query_buf); static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack, PQExpBuffer query_buf); +static backslashResult exec_command_endpipeline(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_flush(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_flushrequest(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd); static backslashResult process_command_g_options(char *first_option, @@ -102,6 +106,7 @@ static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_ static backslashResult exec_command_getenv(PsqlScanState scan_state, bool active_branch, const char *cmd); static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_getresults(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch); @@ -116,6 +121,8 @@ static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_bra static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch, PQExpBuffer query_buf, PQExpBuffer previous_buf); +static backslashResult exec_command_parse(PsqlScanState scan_state, bool active_branch, + const char *cmd); static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch, const char *cmd); @@ -124,11 +131,14 @@ static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_b static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch, PQExpBuffer query_buf); static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch, const char *cmd); static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch, const char *cmd, bool is_func); +static backslashResult exec_command_startpipeline(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_syncpipeline(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch); @@ -312,12 +322,16 @@ exec_command(const char *cmd, status = exec_command_a(scan_state, active_branch); else if (strcmp(cmd, "bind") == 0) status = exec_command_bind(scan_state, active_branch); + else if (strcmp(cmd, "bind_named") == 0) + status = exec_command_bind_named(scan_state, active_branch, cmd); else if (strcmp(cmd, "C") == 0) status = exec_command_C(scan_state, active_branch); else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0) status = exec_command_connect(scan_state, active_branch); else if (strcmp(cmd, "cd") == 0) status = exec_command_cd(scan_state, active_branch, cmd); + else if (strcmp(cmd, "close") == 0) + status = exec_command_close(scan_state, active_branch, cmd); else if (strcmp(cmd, "conninfo") == 0) status = exec_command_conninfo(scan_state, active_branch); else if (pg_strcasecmp(cmd, "copy") == 0) @@ -344,18 +358,26 @@ exec_command(const char *cmd, status = exec_command_else(scan_state, cstack, query_buf); else if (strcmp(cmd, "endif") == 0) status = exec_command_endif(scan_state, cstack, query_buf); + else if (strcmp(cmd, "endpipeline") == 0) + status = exec_command_endpipeline(scan_state, active_branch); else if (strcmp(cmd, "encoding") == 0) status = exec_command_encoding(scan_state, active_branch); else if (strcmp(cmd, "errverbose") == 0) status = exec_command_errverbose(scan_state, active_branch); else if (strcmp(cmd, "f") == 0) status = exec_command_f(scan_state, active_branch); + else if (strcmp(cmd, "flush") == 0) + status = exec_command_flush(scan_state, active_branch); + else if (strcmp(cmd, "flushrequest") == 0) + status = exec_command_flushrequest(scan_state, active_branch); else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0) status = exec_command_g(scan_state, active_branch, cmd); else if (strcmp(cmd, "gdesc") == 0) status = exec_command_gdesc(scan_state, active_branch); else if (strcmp(cmd, "getenv") == 0) status = exec_command_getenv(scan_state, active_branch, cmd); + else if (strcmp(cmd, "getresults") == 0) + status = exec_command_getresults(scan_state, active_branch); else if (strcmp(cmd, "gexec") == 0) status = exec_command_gexec(scan_state, active_branch); else if (strcmp(cmd, "gset") == 0) @@ -370,7 +392,10 @@ exec_command(const char *cmd, else if (strcmp(cmd, "if") == 0) status = exec_command_if(scan_state, cstack, query_buf); else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || - strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + strcmp(cmd, "lx") == 0 || strcmp(cmd, "listx") == 0 || + strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0 || + strcmp(cmd, "lx+") == 0 || strcmp(cmd, "listx+") == 0 || + strcmp(cmd, "l+x") == 0 || strcmp(cmd, "list+x") == 0) status = exec_command_list(scan_state, active_branch, cmd); else if (strncmp(cmd, "lo_", 3) == 0) status = exec_command_lo(scan_state, active_branch, cmd); @@ -379,6 +404,8 @@ exec_command(const char *cmd, else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0) status = exec_command_print(scan_state, active_branch, query_buf, previous_buf); + else if (strcmp(cmd, "parse") == 0) + status = exec_command_parse(scan_state, active_branch, cmd); else if (strcmp(cmd, "password") == 0) status = exec_command_password(scan_state, active_branch); else if (strcmp(cmd, "prompt") == 0) @@ -391,6 +418,8 @@ exec_command(const char *cmd, status = exec_command_reset(scan_state, active_branch, query_buf); else if (strcmp(cmd, "s") == 0) status = exec_command_s(scan_state, active_branch); + else if (strcmp(cmd, "sendpipeline") == 0) + status = exec_command_sendpipeline(scan_state, active_branch); else if (strcmp(cmd, "set") == 0) status = exec_command_set(scan_state, active_branch); else if (strcmp(cmd, "setenv") == 0) @@ -399,6 +428,10 @@ exec_command(const char *cmd, status = exec_command_sf_sv(scan_state, active_branch, cmd, true); else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0) status = exec_command_sf_sv(scan_state, active_branch, cmd, false); + else if (strcmp(cmd, "startpipeline") == 0) + status = exec_command_startpipeline(scan_state, active_branch); + else if (strcmp(cmd, "syncpipeline") == 0) + status = exec_command_syncpipeline(scan_state, active_branch); else if (strcmp(cmd, "t") == 0) status = exec_command_t(scan_state, active_branch); else if (strcmp(cmd, "T") == 0) @@ -415,7 +448,9 @@ exec_command(const char *cmd, query_buf, previous_buf); else if (strcmp(cmd, "x") == 0) status = exec_command_x(scan_state, active_branch); - else if (strcmp(cmd, "z") == 0 || strcmp(cmd, "zS") == 0) + else if (strcmp(cmd, "z") == 0 || + strcmp(cmd, "zS") == 0 || strcmp(cmd, "zx") == 0 || + strcmp(cmd, "zSx") == 0 || strcmp(cmd, "zxS") == 0) status = exec_command_z(scan_state, active_branch, cmd); else if (strcmp(cmd, "!") == 0) status = exec_command_shell_escape(scan_state, active_branch); @@ -471,7 +506,7 @@ exec_command_bind(PsqlScanState scan_state, bool active_branch) int nparams = 0; int nalloc = 0; - pset.bind_params = NULL; + clean_extended_state(); while ((opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false))) { @@ -485,7 +520,56 @@ exec_command_bind(PsqlScanState scan_state, bool active_branch) } pset.bind_nparams = nparams; - pset.bind_flag = true; + pset.send_mode = PSQL_SEND_EXTENDED_QUERY_PARAMS; + } + else + ignore_slash_options(scan_state); + + return status; +} + +/* + * \bind_named -- set query parameters for an existing prepared statement + */ +static backslashResult +exec_command_bind_named(PsqlScanState scan_state, bool active_branch, + const char *cmd) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + char *opt; + int nparams = 0; + int nalloc = 0; + + clean_extended_state(); + + /* get the mandatory prepared statement name */ + opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); + if (!opt) + { + pg_log_error("\\%s: missing required argument", cmd); + status = PSQL_CMD_ERROR; + } + else + { + pset.stmtName = opt; + pset.send_mode = PSQL_SEND_EXTENDED_QUERY_PREPARED; + + /* set of parameters */ + while ((opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false))) + { + nparams++; + if (nparams > nalloc) + { + nalloc = nalloc ? nalloc * 2 : 1; + pset.bind_params = pg_realloc_array(pset.bind_params, char *, nalloc); + } + pset.bind_params[nparams - 1] = opt; + } + pset.bind_nparams = nparams; + } } else ignore_slash_options(scan_state); @@ -644,45 +728,209 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd) } /* - * \conninfo -- display information about the current connection + * \close -- close a previously prepared statement */ static backslashResult -exec_command_conninfo(PsqlScanState scan_state, bool active_branch) +exec_command_close(PsqlScanState scan_state, bool active_branch, const char *cmd) { + backslashResult status = PSQL_CMD_SKIP_LINE; + if (active_branch) { - char *db = PQdb(pset.db); + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + clean_extended_state(); - if (db == NULL) - printf(_("You are currently not connected to a database.\n")); + if (!opt) + { + pg_log_error("\\%s: missing required argument", cmd); + status = PSQL_CMD_ERROR; + } else { - char *host = PQhost(pset.db); - char *hostaddr = PQhostaddr(pset.db); + pset.stmtName = opt; + pset.send_mode = PSQL_SEND_EXTENDED_CLOSE; + status = PSQL_CMD_SEND; + } + } + else + ignore_slash_options(scan_state); - if (is_unixsock_path(host)) - { - /* hostaddr overrides host */ - if (hostaddr && *hostaddr) - printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"), - db, PQuser(pset.db), hostaddr, PQport(pset.db)); - else - printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"), - db, PQuser(pset.db), host, PQport(pset.db)); - } - else - { - if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0) - printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"), - db, PQuser(pset.db), host, hostaddr, PQport(pset.db)); - else - printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"), - db, PQuser(pset.db), host, PQport(pset.db)); - } - printSSLInfo(); - printGSSInfo(); + return status; +} + +/* + * \conninfo -- display information about the current connection + */ +static backslashResult +exec_command_conninfo(PsqlScanState scan_state, bool active_branch) +{ + printTableContent cont; + int rows, + cols; + char *db; + char *host; + bool print_hostaddr; + char *hostaddr; + char *protocol_version, + *backend_pid; + int ssl_in_use, + password_used, + gssapi_used; + int version_num; + char *paramval; + + if (!active_branch) + return PSQL_CMD_SKIP_LINE; + + db = PQdb(pset.db); + if (db == NULL) + { + printf(_("You are currently not connected to a database.\n")); + return PSQL_CMD_SKIP_LINE; + } + + /* Get values for the parameters */ + host = PQhost(pset.db); + hostaddr = PQhostaddr(pset.db); + version_num = PQfullProtocolVersion(pset.db); + protocol_version = psprintf("%d.%d", version_num / 10000, + version_num % 10000); + ssl_in_use = PQsslInUse(pset.db); + password_used = PQconnectionUsedPassword(pset.db); + gssapi_used = PQconnectionUsedGSSAPI(pset.db); + backend_pid = psprintf("%d", PQbackendPID(pset.db)); + + /* Only print hostaddr if it differs from host, and not if unixsock */ + print_hostaddr = (!is_unixsock_path(host) && + hostaddr && *hostaddr && strcmp(host, hostaddr) != 0); + + /* Determine the exact number of rows to print */ + rows = 12; + cols = 2; + if (ssl_in_use) + rows += 6; + if (print_hostaddr) + rows++; + + /* Set it all up */ + printTableInit(&cont, &pset.popt.topt, _("Connection Information"), cols, rows); + printTableAddHeader(&cont, _("Parameter"), true, 'l'); + printTableAddHeader(&cont, _("Value"), true, 'l'); + + /* Database */ + printTableAddCell(&cont, _("Database"), false, false); + printTableAddCell(&cont, db, false, false); + + /* Client User */ + printTableAddCell(&cont, _("Client User"), false, false); + printTableAddCell(&cont, PQuser(pset.db), false, false); + + /* Host/hostaddr/socket */ + if (is_unixsock_path(host)) + { + /* hostaddr if specified overrides socket, so suppress the latter */ + if (hostaddr && *hostaddr) + { + printTableAddCell(&cont, _("Host Address"), false, false); + printTableAddCell(&cont, hostaddr, false, false); + } + else + { + printTableAddCell(&cont, _("Socket Directory"), false, false); + printTableAddCell(&cont, host, false, false); } } + else + { + printTableAddCell(&cont, _("Host"), false, false); + printTableAddCell(&cont, host, false, false); + if (print_hostaddr) + { + printTableAddCell(&cont, _("Host Address"), false, false); + printTableAddCell(&cont, hostaddr, false, false); + } + } + + /* Server Port */ + printTableAddCell(&cont, _("Server Port"), false, false); + printTableAddCell(&cont, PQport(pset.db), false, false); + + /* Options */ + printTableAddCell(&cont, _("Options"), false, false); + printTableAddCell(&cont, PQoptions(pset.db), false, false); + + /* Protocol Version */ + printTableAddCell(&cont, _("Protocol Version"), false, false); + printTableAddCell(&cont, protocol_version, false, false); + + /* Password Used */ + printTableAddCell(&cont, _("Password Used"), false, false); + printTableAddCell(&cont, password_used ? _("true") : _("false"), false, false); + + /* GSSAPI Authenticated */ + printTableAddCell(&cont, _("GSSAPI Authenticated"), false, false); + printTableAddCell(&cont, gssapi_used ? _("true") : _("false"), false, false); + + /* Backend PID */ + printTableAddCell(&cont, _("Backend PID"), false, false); + printTableAddCell(&cont, backend_pid, false, false); + + /* SSL Connection */ + printTableAddCell(&cont, _("SSL Connection"), false, false); + printTableAddCell(&cont, ssl_in_use ? _("true") : _("false"), false, false); + + /* SSL Information */ + if (ssl_in_use) + { + char *library, + *protocol, + *key_bits, + *cipher, + *compression, + *alpn; + + library = (char *) PQsslAttribute(pset.db, "library"); + protocol = (char *) PQsslAttribute(pset.db, "protocol"); + key_bits = (char *) PQsslAttribute(pset.db, "key_bits"); + cipher = (char *) PQsslAttribute(pset.db, "cipher"); + compression = (char *) PQsslAttribute(pset.db, "compression"); + alpn = (char *) PQsslAttribute(pset.db, "alpn"); + + printTableAddCell(&cont, _("SSL Library"), false, false); + printTableAddCell(&cont, library ? library : _("unknown"), false, false); + + printTableAddCell(&cont, _("SSL Protocol"), false, false); + printTableAddCell(&cont, protocol ? protocol : _("unknown"), false, false); + + printTableAddCell(&cont, _("SSL Key Bits"), false, false); + printTableAddCell(&cont, key_bits ? key_bits : _("unknown"), false, false); + + printTableAddCell(&cont, _("SSL Cipher"), false, false); + printTableAddCell(&cont, cipher ? cipher : _("unknown"), false, false); + + printTableAddCell(&cont, _("SSL Compression"), false, false); + printTableAddCell(&cont, (compression && strcmp(compression, "off") != 0) ? + _("true") : _("false"), false, false); + + printTableAddCell(&cont, _("ALPN"), false, false); + printTableAddCell(&cont, (alpn && alpn[0] != '\0') ? alpn : _("none"), false, false); + } + + paramval = (char *) PQparameterStatus(pset.db, "is_superuser"); + printTableAddCell(&cont, "Superuser", false, false); + printTableAddCell(&cont, paramval ? paramval : _("unknown"), false, false); + + paramval = (char *) PQparameterStatus(pset.db, "in_hot_standby"); + printTableAddCell(&cont, "Hot Standby", false, false); + printTableAddCell(&cont, paramval ? paramval : _("unknown"), false, false); + + printTable(&cont, pset.queryFout, false, pset.logfile); + printTableCleanup(&cont); + + pfree(protocol_version); + pfree(backend_pid); return PSQL_CMD_SKIP_LINE; } @@ -759,6 +1007,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) char *pattern; bool show_verbose, show_system; + unsigned short int save_expanded; /* We don't do SQLID reduction on the pattern yet */ pattern = psql_scan_slash_option(scan_state, @@ -767,6 +1016,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) show_verbose = strchr(cmd, '+') ? true : false; show_system = strchr(cmd, 'S') ? true : false; + /* + * The 'x' option turns expanded mode on for this command only. This + * is allowed in all \d* commands, except \d by itself, since \dx is a + * separate command. So the 'x' option cannot appear immediately after + * \d, but it can appear after \d followed by other options. + */ + save_expanded = pset.popt.topt.expanded; + if (cmd[1] != '\0' && strchr(&cmd[2], 'x')) + pset.popt.topt.expanded = 1; + switch (cmd[1]) { case '\0': @@ -782,13 +1041,14 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { char *pattern2 = NULL; - if (pattern && cmd[2] != '\0' && cmd[2] != '+') + if (pattern && cmd[2] != '\0' && cmd[2] != '+' && cmd[2] != 'x') pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); switch (cmd[2]) { case '\0': case '+': + case 'x': success = describeAccessMethods(pattern, show_verbose); break; case 'c': @@ -850,6 +1110,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 'p': case 't': case 'w': + case 'x': success = exec_command_dfo(scan_state, cmd, pattern, show_verbose, show_system); break; @@ -890,6 +1151,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) case 't': case 'i': case 'n': + case 'x': success = listPartitionedTables(&cmd[2], pattern, show_verbose); break; default: @@ -950,6 +1212,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) { case '\0': case '+': + case 'x': success = listTSConfigs(pattern, show_verbose); break; case 'p': @@ -1002,6 +1265,9 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd) status = PSQL_CMD_UNKNOWN; } + /* Restore original expanded mode */ + pset.popt.topt.expanded = save_expanded; + free(pattern); } else @@ -1110,7 +1376,7 @@ exec_command_edit(PsqlScanState scan_state, bool active_branch, expand_tilde(&fname); if (fname) { - canonicalize_path(fname); + canonicalize_path_enc(fname, pset.encoding); /* Always clear buffer if the file isn't modified */ discard_on_quit = true; } @@ -1336,6 +1602,7 @@ exec_command_encoding(PsqlScanState scan_state, bool active_branch) /* save encoding info into psql internal data */ pset.encoding = PQclientEncoding(pset.db); pset.popt.topt.encoding = pset.encoding; + setFmtEncoding(pset.encoding); SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); } @@ -1400,6 +1667,44 @@ exec_command_f(PsqlScanState scan_state, bool active_branch) return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR; } +/* + * \flush -- call PQflush() on the connection + */ +static backslashResult +exec_command_flush(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + pset.send_mode = PSQL_SEND_FLUSH; + status = PSQL_CMD_SEND; + } + else + ignore_slash_options(scan_state); + + return status; +} + +/* + * \flushrequest -- call PQsendFlushRequest() on the connection + */ +static backslashResult +exec_command_flushrequest(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + pset.send_mode = PSQL_SEND_FLUSH_REQUEST; + status = PSQL_CMD_SEND; + } + else + ignore_slash_options(scan_state); + + return status; +} + /* * \g [(pset-option[=pset-value] ...)] [filename/shell-command] * \gx [(pset-option[=pset-value] ...)] [filename/shell-command] @@ -1435,6 +1740,14 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd) if (status == PSQL_CMD_SKIP_LINE && active_branch) { + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pg_log_error("\\%s not allowed in pipeline mode", cmd); + clean_extended_state(); + free(fname); + return PSQL_CMD_ERROR; + } + if (!fname) pset.gfname = NULL; else @@ -1588,6 +1901,42 @@ exec_command_getenv(PsqlScanState scan_state, bool active_branch, return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR; } +/* + * \getresults -- read results + */ +static backslashResult +exec_command_getresults(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + char *opt; + int num_results; + + pset.send_mode = PSQL_SEND_GET_RESULTS; + status = PSQL_CMD_SEND; + opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); + + pset.requested_results = 0; + if (opt != NULL) + { + num_results = atoi(opt); + if (num_results < 0) + { + pg_log_error("\\getresults: invalid number of requested results"); + return PSQL_CMD_ERROR; + } + pset.requested_results = num_results; + } + } + else + ignore_slash_options(scan_state); + + return status; +} + + /* * \gexec -- send query and execute each field of result */ @@ -1598,6 +1947,12 @@ exec_command_gexec(PsqlScanState scan_state, bool active_branch) if (active_branch) { + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pg_log_error("\\%s not allowed in pipeline mode", "gexec"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } pset.gexec_flag = true; status = PSQL_CMD_SEND; } @@ -1618,6 +1973,13 @@ exec_command_gset(PsqlScanState scan_state, bool active_branch) char *prefix = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pg_log_error("\\%s not allowed in pipeline mode", "gset"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } + if (prefix) pset.gset_prefix = prefix; else @@ -1953,14 +2315,23 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd) { char *pattern; bool show_verbose; + unsigned short int save_expanded; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); show_verbose = strchr(cmd, '+') ? true : false; + /* if 'x' option specified, force expanded mode */ + save_expanded = pset.popt.topt.expanded; + if (strchr(cmd, 'x')) + pset.popt.topt.expanded = 1; + success = listAllDbs(pattern, show_verbose); + /* restore original expanded mode */ + pset.popt.topt.expanded = save_expanded; + free(pattern); } else @@ -2016,10 +2387,23 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd) } } - else if (strcmp(cmd + 3, "list") == 0) - success = listLargeObjects(false); - else if (strcmp(cmd + 3, "list+") == 0) - success = listLargeObjects(true); + else if (strncmp(cmd + 3, "list", 4) == 0) + { + bool show_verbose; + unsigned short int save_expanded; + + show_verbose = strchr(cmd, '+') ? true : false; + + /* if 'x' option specified, force expanded mode */ + save_expanded = pset.popt.topt.expanded; + if (strchr(cmd, 'x')) + pset.popt.topt.expanded = 1; + + success = listLargeObjects(show_verbose); + + /* restore original expanded mode */ + pset.popt.topt.expanded = save_expanded; + } else if (strcmp(cmd + 3, "unlink") == 0) { @@ -2096,6 +2480,40 @@ exec_command_print(PsqlScanState scan_state, bool active_branch, return PSQL_CMD_SKIP_LINE; } +/* + * \parse -- parse query + */ +static backslashResult +exec_command_parse(PsqlScanState scan_state, bool active_branch, + const char *cmd) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + clean_extended_state(); + + if (!opt) + { + pg_log_error("\\%s: missing required argument", cmd); + status = PSQL_CMD_ERROR; + } + else + { + pset.stmtName = opt; + pset.send_mode = PSQL_SEND_EXTENDED_PARSE; + status = PSQL_CMD_SEND; + } + } + else + ignore_slash_options(scan_state); + + return status; +} + /* * \password -- set user password */ @@ -2363,6 +2781,43 @@ exec_command_s(PsqlScanState scan_state, bool active_branch) return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR; } +/* + * \sendpipeline -- send an extended query to an ongoing pipeline + */ +static backslashResult +exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + if (pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PREPARED || + pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PARAMS) + { + status = PSQL_CMD_SEND; + } + else + { + pg_log_error("\\sendpipeline must be used after \\bind or \\bind_named"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } + } + else + { + pg_log_error("\\sendpipeline not allowed outside of pipeline mode"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } + } + else + ignore_slash_options(scan_state); + + return status; +} + /* * \set -- set variable */ @@ -2547,6 +3002,63 @@ exec_command_sf_sv(PsqlScanState scan_state, bool active_branch, return status; } +/* + * \startpipeline -- enter pipeline mode + */ +static backslashResult +exec_command_startpipeline(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + pset.send_mode = PSQL_SEND_START_PIPELINE_MODE; + status = PSQL_CMD_SEND; + } + else + ignore_slash_options(scan_state); + + return status; +} + +/* + * \syncpipeline -- send a sync message to an active pipeline + */ +static backslashResult +exec_command_syncpipeline(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + pset.send_mode = PSQL_SEND_PIPELINE_SYNC; + status = PSQL_CMD_SEND; + } + else + ignore_slash_options(scan_state); + + return status; +} + +/* + * \endpipeline -- end pipeline mode + */ +static backslashResult +exec_command_endpipeline(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + pset.send_mode = PSQL_SEND_END_PIPELINE_MODE; + status = PSQL_CMD_SEND; + } + else + ignore_slash_options(scan_state); + + return status; +} + /* * \t -- turn off table headers and row count */ @@ -2694,7 +3206,7 @@ exec_command_write(PsqlScanState scan_state, bool active_branch, } else { - canonicalize_path(fname); + canonicalize_path_enc(fname, pset.encoding); fd = fopen(fname, "w"); } if (!fd) @@ -2769,14 +3281,23 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch, bool have_sleep = false; bool have_iter = false; bool have_min_rows = false; - double sleep = 2; + double sleep = pset.watch_interval; int iter = 0; int min_rows = 0; + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pg_log_error("\\%s not allowed in pipeline mode", "watch"); + clean_extended_state(); + success = false; + } + /* * Parse arguments. We allow either an unlabeled interval or * "name=value", where name is from the set ('i', 'interval', 'c', - * 'count', 'm', 'min_rows'). + * 'count', 'm', 'min_rows'). The parsing of interval value should be + * kept in sync with ParseVariableDouble which is used for setting the + * default interval value. */ while (success) { @@ -2936,14 +3457,23 @@ exec_command_z(PsqlScanState scan_state, bool active_branch, const char *cmd) { char *pattern; bool show_system; + unsigned short int save_expanded; pattern = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true); show_system = strchr(cmd, 'S') ? true : false; + /* if 'x' option specified, force expanded mode */ + save_expanded = pset.popt.topt.expanded; + if (strchr(cmd, 'x')) + pset.popt.topt.expanded = 1; + success = permissionsList(pattern, show_system); + /* restore original expanded mode */ + pset.popt.topt.expanded = save_expanded; + free(pattern); } else @@ -3956,7 +4486,10 @@ SyncVariables(void) pset.popt.topt.encoding = pset.encoding; pset.sversion = PQserverVersion(pset.db); + setFmtEncoding(pset.encoding); + SetVariable(pset.vars, "DBNAME", PQdb(pset.db)); + SetVariable(pset.vars, "SERVICE", PQservice(pset.db)); SetVariable(pset.vars, "USER", PQuser(pset.db)); SetVariable(pset.vars, "HOST", PQhost(pset.db)); SetVariable(pset.vars, "PORT", PQport(pset.db)); @@ -3990,6 +4523,7 @@ void UnsyncVariables(void) { SetVariable(pset.vars, "DBNAME", NULL); + SetVariable(pset.vars, "SERVICE", NULL); SetVariable(pset.vars, "USER", NULL); SetVariable(pset.vars, "HOST", NULL); SetVariable(pset.vars, "PORT", NULL); @@ -4298,7 +4832,7 @@ process_file(char *filename, bool use_relative_path) } else if (strcmp(filename, "-") != 0) { - canonicalize_path(filename); + canonicalize_path_enc(filename, pset.encoding); /* * If we were asked to resolve the pathname relative to the location @@ -4312,7 +4846,7 @@ process_file(char *filename, bool use_relative_path) strlcpy(relpath, pset.inputfile, sizeof(relpath)); get_parent_directory(relpath); join_path_components(relpath, relpath, filename); - canonicalize_path(relpath); + canonicalize_path_enc(relpath, pset.encoding); filename = relpath; } @@ -5231,6 +5765,10 @@ do_shell(const char *command) * * We break this out of exec_command to avoid having to plaster "volatile" * onto a bunch of exec_command's variables to silence stupider compilers. + * + * "sleep" is the amount of time to sleep during each loop, measured in + * seconds. The internals of this function should use "sleep_ms" for + * precise sleep time calculations. */ static bool do_watch(PQExpBuffer query_buf, double sleep, int iter, int min_rows) @@ -5356,10 +5894,10 @@ do_watch(PQExpBuffer query_buf, double sleep, int iter, int min_rows) if (user_title) snprintf(title, title_len, _("%s\t%s (every %gs)\n"), - user_title, timebuf, sleep); + user_title, timebuf, sleep_ms / 1000.0); else snprintf(title, title_len, _("%s (every %gs)\n"), - timebuf, sleep); + timebuf, sleep_ms / 1000.0); myopt.title = title; /* Run the query and print out the result */ @@ -5380,7 +5918,8 @@ do_watch(PQExpBuffer query_buf, double sleep, int iter, int min_rows) if (pagerpipe && ferror(pagerpipe)) break; - if (sleep == 0) + /* Tight loop, no wait needed */ + if (sleep_ms == 0) continue; #ifdef WIN32 diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h index b41065d5a966a..ae2d66ea81774 100644 --- a/src/bin/psql/command.h +++ b/src/bin/psql/command.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/command.h */ diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index fe8e049c4c1a2..b53cd8ab69880 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/common.c */ @@ -121,6 +121,18 @@ CloseGOutput(FILE *gfile_fout, bool is_pipe) } } +/* + * Reset pset pipeline state + */ +static void +pipelineReset(void) +{ + pset.piped_syncs = 0; + pset.piped_commands = 0; + pset.available_results = 0; + pset.requested_results = 0; +} + /* * setQFout * -- handler for -o command line option and \o command @@ -354,6 +366,7 @@ CheckConnection(void) fprintf(stderr, _("The connection to the server was lost. Attempting reset: ")); PQreset(pset.db); + pipelineReset(); OK = ConnectionUp(); if (!OK) { @@ -415,10 +428,12 @@ AcceptResult(const PGresult *result, bool show_error) case PGRES_EMPTY_QUERY: case PGRES_COPY_IN: case PGRES_COPY_OUT: + case PGRES_PIPELINE_SYNC: /* Fine, do nothing */ OK = true; break; + case PGRES_PIPELINE_ABORTED: case PGRES_BAD_RESPONSE: case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: @@ -509,6 +524,26 @@ SetShellResultVariables(int wait_result) } +/* + * Set special pipeline variables + * - PIPELINE_SYNC_COUNT: The number of piped syncs + * - PIPELINE_COMMAND_COUNT: The number of piped commands + * - PIPELINE_RESULT_COUNT: The number of results available to read + */ +static void +SetPipelineVariables(void) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%d", pset.piped_syncs); + SetVariable(pset.vars, "PIPELINE_SYNC_COUNT", buf); + snprintf(buf, sizeof(buf), "%d", pset.piped_commands); + SetVariable(pset.vars, "PIPELINE_COMMAND_COUNT", buf); + snprintf(buf, sizeof(buf), "%d", pset.available_results); + SetVariable(pset.vars, "PIPELINE_RESULT_COUNT", buf); +} + + /* * ClearOrSaveResult * @@ -1050,6 +1085,7 @@ PrintQueryResult(PGresult *result, bool last, success = true; break; + case PGRES_PIPELINE_ABORTED: case PGRES_BAD_RESPONSE: case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: @@ -1274,15 +1310,8 @@ SendQuery(const char *query) pset.gsavepopt = NULL; } - /* clean up after \bind */ - if (pset.bind_flag) - { - for (i = 0; i < pset.bind_nparams; i++) - free(pset.bind_params[i]); - free(pset.bind_params); - pset.bind_params = NULL; - pset.bind_flag = false; - } + /* clean up after extended protocol queries */ + clean_extended_state(); /* reset \gset trigger */ if (pset.gset_prefix) @@ -1375,7 +1404,7 @@ DescribeQuery(const char *query, double *elapsed_msec) char *escname; if (i > 0) - appendPQExpBufferStr(&buf, ","); + appendPQExpBufferChar(&buf, ','); name = PQfname(result, i); escname = PQescapeLiteral(pset.db, name, strlen(name)); @@ -1425,6 +1454,80 @@ DescribeQuery(const char *query, double *elapsed_msec) return OK; } +/* + * Read and discard all results in an aborted pipeline. + * + * If a synchronisation point is found, we can stop discarding results as + * the pipeline will switch back to a clean state. If no synchronisation + * point is available, we need to stop when there are no more pending + * results, otherwise, calling PQgetResult() would block. + */ +static PGresult * +discardAbortedPipelineResults(void) +{ + for (;;) + { + PGresult *res = PQgetResult(pset.db); + ExecStatusType result_status = PQresultStatus(res); + + if (result_status == PGRES_PIPELINE_SYNC) + { + /* + * Found a synchronisation point. The sync counter is decremented + * by the caller. + */ + return res; + } + else if (res != NULL && result_status == PGRES_FATAL_ERROR) + { + /* + * Found a FATAL error sent by the backend, and we cannot recover + * from this state. Instead, return the last result and let the + * outer loop handle it. + */ + PGresult *fatal_res PG_USED_FOR_ASSERTS_ONLY; + + /* + * Fetch result to consume the end of the current query being + * processed. + */ + fatal_res = PQgetResult(pset.db); + Assert(fatal_res == NULL); + return res; + } + else if (res == NULL) + { + /* A query was processed, decrement the counters */ + Assert(pset.available_results > 0); + Assert(pset.requested_results > 0); + pset.available_results--; + pset.requested_results--; + } + + if (pset.requested_results == 0) + { + /* We have read all the requested results, leave */ + return res; + } + + if (pset.available_results == 0 && pset.piped_syncs == 0) + { + /* + * There are no more results to get and there is no + * synchronisation point to stop at. This will leave the pipeline + * in an aborted state. + */ + return res; + } + + /* + * An aborted pipeline will have either NULL results or results in an + * PGRES_PIPELINE_ABORTED status. + */ + Assert(res == NULL || result_status == PGRES_PIPELINE_ABORTED); + PQclear(res); + } +} /* * ExecQueryAndProcessResults: utility function for use by SendQuery() @@ -1437,7 +1540,7 @@ DescribeQuery(const char *query, double *elapsed_msec) * input or output stream. In that event, we'll marshal data for the COPY. * * For other commands, the results are processed normally, depending on their - * status. + * status and the status of a pipeline. * * When invoked from \watch, is_watch is true and min_rows is the value * of that option, or 0 if it wasn't set. @@ -1456,8 +1559,9 @@ ExecQueryAndProcessResults(const char *query, const printQueryOpt *opt, FILE *printQueryFout) { bool timing = pset.timing; - bool success; + bool success = false; bool return_early = false; + bool end_pipeline = false; instr_time before, after; PGresult *result; @@ -1469,10 +1573,129 @@ ExecQueryAndProcessResults(const char *query, else INSTR_TIME_SET_ZERO(before); - if (pset.bind_flag) - success = PQsendQueryParams(pset.db, query, pset.bind_nparams, NULL, (const char *const *) pset.bind_params, NULL, NULL, 0); - else - success = PQsendQuery(pset.db, query); + switch (pset.send_mode) + { + case PSQL_SEND_EXTENDED_CLOSE: + success = PQsendClosePrepared(pset.db, pset.stmtName); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + pset.piped_commands++; + break; + case PSQL_SEND_EXTENDED_PARSE: + success = PQsendPrepare(pset.db, pset.stmtName, query, 0, NULL); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + pset.piped_commands++; + break; + case PSQL_SEND_EXTENDED_QUERY_PARAMS: + Assert(pset.stmtName == NULL); + success = PQsendQueryParams(pset.db, query, + pset.bind_nparams, NULL, + (const char *const *) pset.bind_params, + NULL, NULL, 0); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + pset.piped_commands++; + break; + case PSQL_SEND_EXTENDED_QUERY_PREPARED: + Assert(pset.stmtName != NULL); + success = PQsendQueryPrepared(pset.db, pset.stmtName, + pset.bind_nparams, + (const char *const *) pset.bind_params, + NULL, NULL, 0); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + pset.piped_commands++; + break; + case PSQL_SEND_START_PIPELINE_MODE: + success = PQenterPipelineMode(pset.db); + break; + case PSQL_SEND_END_PIPELINE_MODE: + success = PQpipelineSync(pset.db); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + /* + * End of the pipeline, all queued commands need to be + * processed. + */ + end_pipeline = true; + pset.piped_syncs++; + + /* + * The server will send a ReadyForQuery after a Sync is + * processed, flushing all the results back to the client. + */ + pset.available_results += pset.piped_commands; + pset.piped_commands = 0; + + /* We want to read all results */ + pset.requested_results = pset.available_results + pset.piped_syncs; + } + break; + case PSQL_SEND_PIPELINE_SYNC: + success = PQsendPipelineSync(pset.db); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pset.piped_syncs++; + + /* + * The server will send a ReadyForQuery after a Sync is + * processed, flushing all the results back to the client. + */ + pset.available_results += pset.piped_commands; + pset.piped_commands = 0; + } + break; + case PSQL_SEND_FLUSH: + success = PQflush(pset.db); + break; + case PSQL_SEND_FLUSH_REQUEST: + success = PQsendFlushRequest(pset.db); + if (success && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + /* + * With the flush request, all commands in the pipeline are + * pushed and the server will flush the results back to the + * client, making them available. + */ + pset.available_results += pset.piped_commands; + pset.piped_commands = 0; + } + break; + case PSQL_SEND_GET_RESULTS: + if (pset.available_results == 0 && pset.piped_syncs == 0) + { + /* + * If no sync or flush request were sent, PQgetResult() would + * block as there are no results available. Forbid any + * attempt to get pending results should we try to reach this + * state. + */ + pg_log_info("No pending results to get"); + success = false; + pset.requested_results = 0; + } + else + { + success = true; + + /* + * Cap requested_results to the maximum number of known + * results. + */ + if (pset.requested_results == 0 || + pset.requested_results > (pset.available_results + pset.piped_syncs)) + pset.requested_results = pset.available_results + pset.piped_syncs; + } + break; + case PSQL_SEND_QUERY: + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + success = PQsendQueryParams(pset.db, query, + 0, NULL, NULL, NULL, NULL, 0); + if (success) + pset.piped_commands++; + } + else + success = PQsendQuery(pset.db, query); + break; + } if (!success) { @@ -1483,9 +1706,23 @@ ExecQueryAndProcessResults(const char *query, CheckConnection(); + SetPipelineVariables(); + return -1; } + if (pset.requested_results == 0 && !end_pipeline && + PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + /* + * We are in a pipeline and have not reached the pipeline end, or + * there was no request to read pipeline results. Update the psql + * variables tracking the pipeline activity and exit. + */ + SetPipelineVariables(); + return 1; + } + /* * Fetch the result in chunks if FETCH_COUNT is set, except when: * @@ -1533,7 +1770,7 @@ ExecQueryAndProcessResults(const char *query, { ExecStatusType result_status; bool is_chunked_result = false; - PGresult *next_result; + PGresult *next_result = NULL; bool last; if (!AcceptResult(result, false)) @@ -1556,13 +1793,16 @@ ExecQueryAndProcessResults(const char *query, ClearOrSaveResult(result); success = false; + if (result_status == PGRES_PIPELINE_ABORTED) + pg_log_info("Pipeline aborted, command did not run"); + /* * switch to next result */ if (result_status == PGRES_COPY_BOTH || result_status == PGRES_COPY_OUT || result_status == PGRES_COPY_IN) - + { /* * For some obscure reason PQgetResult does *not* return a * NULL in copy cases despite the result having been cleared, @@ -1570,6 +1810,23 @@ ExecQueryAndProcessResults(const char *query, * ignore manually. */ result = NULL; + } + else if ((end_pipeline || pset.requested_results > 0) + && PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + /* + * Error within a pipeline. All commands are aborted until + * the next synchronisation point. We need to consume all the + * results until this synchronisation point, or stop when + * there are no more result to discard. + * + * Checking the pipeline status is necessary for the case + * where the connection was reset. The new connection is not + * in any kind of pipeline state and thus has no result to + * discard. + */ + result = discardAbortedPipelineResults(); + } else result = PQgetResult(pset.db); @@ -1610,6 +1867,33 @@ ExecQueryAndProcessResults(const char *query, { FILE *copy_stream = NULL; + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + /* + * Running COPY within a pipeline can break the protocol + * synchronisation in multiple ways, and psql shows its limits + * when it comes to tracking this information. + * + * While in COPY mode, the backend process ignores additional + * Sync messages and will not send the matching ReadyForQuery + * expected by the frontend. + * + * Additionally, libpq automatically sends a Sync with the + * Copy message, creating an unexpected synchronisation point. + * A failure during COPY would leave the pipeline in an + * aborted state while the backend would be in a clean state, + * ready to process commands. + * + * Improving those issues would require modifications in how + * libpq handles pipelines and COPY. Hence, for the time + * being, we forbid the use of COPY within a pipeline, + * aborting the connection to avoid an inconsistent state on + * psql side if trying to use a COPY command. + */ + pg_log_info("COPY in a pipeline is not supported, aborting connection"); + exit(EXIT_BADCONN); + } + /* * For COPY OUT, direct the output to the default place (probably * a pager pipe) for \watch, or to pset.copyStream for \copy, @@ -1680,7 +1964,7 @@ ExecQueryAndProcessResults(const char *query, { /* * Display the current chunk of results, unless the output - * stream stopped working or we got cancelled. We skip use of + * stream stopped working or we got canceled. We skip use of * PrintQueryResult and go directly to printQuery, so that we * can pass the correct is_pager value and because we don't * want PrintQueryStatus to happen yet. Above, we rejected @@ -1756,12 +2040,66 @@ ExecQueryAndProcessResults(const char *query, } } + if (result_status == PGRES_PIPELINE_SYNC) + { + Assert(pset.piped_syncs > 0); + + /* + * Sync response, decrease the sync and requested_results + * counters. + */ + pset.piped_syncs--; + pset.requested_results--; + + /* + * After a synchronisation point, reset success state to print + * possible successful results that will be processed after this. + */ + success = true; + + /* + * If all syncs were processed and pipeline end was requested, + * exit pipeline mode. + */ + if (end_pipeline && pset.piped_syncs == 0) + success &= PQexitPipelineMode(pset.db); + } + else if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF && + result_status != PGRES_PIPELINE_SYNC) + { + /* + * In a pipeline with a non-sync response? Decrease the result + * counters. + */ + pset.available_results--; + pset.requested_results--; + } + /* * Check PQgetResult() again. In the typical case of a single-command * string, it will return NULL. Otherwise, we'll have other results * to process. We need to do that to check whether this is the last. */ - next_result = PQgetResult(pset.db); + if (PQpipelineStatus(pset.db) == PQ_PIPELINE_OFF) + next_result = PQgetResult(pset.db); + else + { + /* + * In pipeline mode, a NULL result indicates the end of the + * current query being processed. Call PQgetResult() once to + * consume this state. + */ + if (result_status != PGRES_PIPELINE_SYNC) + { + next_result = PQgetResult(pset.db); + Assert(next_result == NULL); + } + + /* Now, we can get the next result in the pipeline. */ + if (pset.requested_results > 0) + next_result = PQgetResult(pset.db); + } + last = (next_result == NULL); /* @@ -1783,8 +2121,13 @@ ExecQueryAndProcessResults(const char *query, *elapsed_msec = INSTR_TIME_GET_MILLISEC(after); } - /* this may or may not print something depending on settings */ - if (result != NULL) + /* + * This may or may not print something depending on settings. + * + * A pipeline sync will have a non-NULL result but does not have + * anything to print, thus ignore results in this case. + */ + if (result != NULL && result_status != PGRES_PIPELINE_SYNC) { /* * If results need to be printed into the file specified by \g, @@ -1810,9 +2153,15 @@ ExecQueryAndProcessResults(const char *query, ClearOrSaveResult(result); result = next_result; - if (cancel_pressed) + if (cancel_pressed && PQpipelineStatus(pset.db) == PQ_PIPELINE_OFF) { - /* drop this next result, as well as any others not yet read */ + /* + * Outside of a pipeline, drop the next result, as well as any + * others not yet read. + * + * Within a pipeline, we can let the outer loop handle this as an + * aborted pipeline, which will discard then all the results. + */ ClearOrSaveResult(result); ClearOrSaveAllResults(); break; @@ -1822,6 +2171,18 @@ ExecQueryAndProcessResults(const char *query, /* close \g file if we opened it */ CloseGOutput(gfile_fout, gfile_is_pipe); + if (end_pipeline) + { + /* after a pipeline is processed, pipeline piped_syncs should be 0 */ + Assert(pset.piped_syncs == 0); + /* all commands have been processed */ + Assert(pset.piped_commands == 0); + /* all results were read */ + Assert(pset.available_results == 0); + } + Assert(pset.requested_results == 0); + SetPipelineVariables(); + /* may need this to recover from conn loss during COPY */ if (!CheckConnection()) return -1; @@ -2252,6 +2613,49 @@ uri_prefix_length(const char *connstr) return 0; } +/* + * Reset state related to extended query protocol + * + * Clean up any state related to bind parameters, statement name and + * PSQL_SEND_MODE. This needs to be called after processing a query or when + * running a new meta-command that uses the extended query protocol, like + * \parse, \bind, etc. + */ +void +clean_extended_state(void) +{ + int i; + + switch (pset.send_mode) + { + case PSQL_SEND_EXTENDED_CLOSE: /* \close */ + free(pset.stmtName); + break; + case PSQL_SEND_EXTENDED_PARSE: /* \parse */ + free(pset.stmtName); + break; + case PSQL_SEND_EXTENDED_QUERY_PARAMS: /* \bind */ + case PSQL_SEND_EXTENDED_QUERY_PREPARED: /* \bind_named */ + for (i = 0; i < pset.bind_nparams; i++) + free(pset.bind_params[i]); + free(pset.bind_params); + free(pset.stmtName); + pset.bind_params = NULL; + break; + case PSQL_SEND_QUERY: + case PSQL_SEND_START_PIPELINE_MODE: /* \startpipeline */ + case PSQL_SEND_END_PIPELINE_MODE: /* \endpipeline */ + case PSQL_SEND_PIPELINE_SYNC: /* \syncpipeline */ + case PSQL_SEND_FLUSH: /* \flush */ + case PSQL_SEND_GET_RESULTS: /* \getresults */ + case PSQL_SEND_FLUSH_REQUEST: /* \flushrequest */ + break; + } + + pset.stmtName = NULL; + pset.send_mode = PSQL_SEND_QUERY; +} + /* * Recognized connection string either starts with a valid URI prefix or * contains a "=" in it. diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index 6efe12274fe59..7f1a23de1e82d 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/common.h */ @@ -41,6 +41,7 @@ extern bool standard_strings(void); extern const char *session_username(void); extern void expand_tilde(char **filename); +extern void clean_extended_state(void); extern bool recognized_connection_string(const char *connstr); diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c index 961ae3269493a..92c955b637a43 100644 --- a/src/bin/psql/copy.c +++ b/src/bin/psql/copy.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/copy.c */ @@ -280,7 +280,7 @@ do_copy(const char *args) /* prepare to read or write the target file */ if (options->file && !options->program) - canonicalize_path(options->file); + canonicalize_path_enc(options->file, pset.encoding); if (options->from) { @@ -620,20 +620,29 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res) /* current line is done? */ if (buf[buflen - 1] == '\n') { - /* check for EOF marker, but not on a partial line */ - if (at_line_begin) + /* + * When at the beginning of the line and the data is + * inlined, check for EOF marker. If the marker is found, + * we must stop at this point. If not, the \. line can be + * sent to the server, and we let it decide whether it's + * an EOF or not depending on the format: in TEXT mode, \. + * will be interpreted as an EOF, in CSV, it will not. + */ + if (at_line_begin && copystream == pset.cur_cmd_source) { - /* - * This code erroneously assumes '\.' on a line alone - * inside a quoted CSV string terminates the \copy. - * https://www.postgresql.org/message-id/E1TdNVQ-0001ju-GO@wrigleys.postgresql.org - * - * https://www.postgresql.org/message-id/bfcd57e4-8f23-4c3e-a5db-2571d09208e2@beta.fastmail.com - */ if ((linelen == 3 && memcmp(fgresult, "\\.\n", 3) == 0) || (linelen == 4 && memcmp(fgresult, "\\.\r\n", 4) == 0)) { copydone = true; + + /* + * Remove the EOF marker from the data sent. In + * CSV mode, the EOF marker must be removed, + * otherwise it would be interpreted by the server + * as valid data. + */ + *fgresult = '\0'; + buflen -= linelen; } } diff --git a/src/bin/psql/copy.h b/src/bin/psql/copy.h index c99daadc058a7..2a3e593d4eaa8 100644 --- a/src/bin/psql/copy.h +++ b/src/bin/psql/copy.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/copy.h */ diff --git a/src/bin/psql/create_help.pl b/src/bin/psql/create_help.pl index e2fdc25570c11..5964b49798345 100644 --- a/src/bin/psql/create_help.pl +++ b/src/bin/psql/create_help.pl @@ -3,7 +3,7 @@ ################################################################# # create_help.pl -- converts SGML docs to internal psql help # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group # # src/bin/psql/create_help.pl ################################################################# diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index 305ed4ab0a88f..3e5cd0a96d4fa 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/crosstabview.c */ diff --git a/src/bin/psql/crosstabview.h b/src/bin/psql/crosstabview.h index 503ac28af9d0e..a3b96d28a9f23 100644 --- a/src/bin/psql/crosstabview.h +++ b/src/bin/psql/crosstabview.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/crosstabview.h */ diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 7c9a1f234c626..dd25d2fe7b8a7 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -7,7 +7,7 @@ * information for an old server, but not to fail outright. (But failing * against a pre-9.2 server is allowed.) * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/describe.c */ @@ -15,11 +15,19 @@ #include -#include "catalog/pg_am.h" +#include "catalog/pg_am_d.h" +#include "catalog/pg_amop_d.h" #include "catalog/pg_attribute_d.h" #include "catalog/pg_cast_d.h" #include "catalog/pg_class_d.h" +#include "catalog/pg_collation_d.h" +#include "catalog/pg_constraint_d.h" #include "catalog/pg_default_acl_d.h" +#include "catalog/pg_proc_d.h" +#include "catalog/pg_publication_d.h" +#include "catalog/pg_statistic_ext_d.h" +#include "catalog/pg_subscription_d.h" +#include "catalog/pg_type_d.h" #include "common.h" #include "common/logging.h" #include "describe.h" @@ -27,7 +35,6 @@ #include "fe_utils/print.h" #include "fe_utils/string_utils.h" #include "settings.h" -#include "variables.h" static const char *map_typename_pattern(const char *pattern); static bool describeOneTableDetails(const char *schemaname, @@ -94,7 +101,7 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n" "FROM pg_catalog.pg_proc p\n" " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" - "WHERE p.prokind = 'a'\n", + "WHERE p.prokind = " CppAsString2(PROKIND_AGGREGATE) "\n", gettext_noop("Description")); else appendPQExpBuffer(&buf, @@ -160,8 +167,8 @@ describeAccessMethods(const char *pattern, bool verbose) printfPQExpBuffer(&buf, "SELECT amname AS \"%s\",\n" " CASE amtype" - " WHEN 'i' THEN '%s'" - " WHEN 't' THEN '%s'" + " WHEN " CppAsString2(AMTYPE_INDEX) " THEN '%s'" + " WHEN " CppAsString2(AMTYPE_TABLE) " THEN '%s'" " END AS \"%s\"", gettext_noop("Name"), gettext_noop("Index"), @@ -289,6 +296,7 @@ describeFunctions(const char *functypes, const char *func_pattern, char **arg_patterns, int num_arg_patterns, bool verbose, bool showSystem) { + const char *df_options = "anptwSx+"; bool showAggregate = strchr(functypes, 'a') != NULL; bool showNormal = strchr(functypes, 'n') != NULL; bool showProcedure = strchr(functypes, 'p') != NULL; @@ -298,14 +306,14 @@ describeFunctions(const char *functypes, const char *func_pattern, PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false}; + static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, true, false, false, false, false}; /* No "Parallel" column before 9.6 */ - static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false}; + static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, true, false, false, false, false}; - if (strlen(functypes) != strspn(functypes, "anptwS+")) + if (strlen(functypes) != strspn(functypes, df_options)) { - pg_log_error("\\df only takes [anptwS+] as options"); + pg_log_error("\\df only takes [%s] as options", df_options); return true; } @@ -340,9 +348,9 @@ describeFunctions(const char *functypes, const char *func_pattern, " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n" " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n" " CASE p.prokind\n" - " WHEN 'a' THEN '%s'\n" - " WHEN 'w' THEN '%s'\n" - " WHEN 'p' THEN '%s'\n" + " WHEN " CppAsString2(PROKIND_AGGREGATE) " THEN '%s'\n" + " WHEN " CppAsString2(PROKIND_WINDOW) " THEN '%s'\n" + " WHEN " CppAsString2(PROKIND_PROCEDURE) " THEN '%s'\n" " ELSE '%s'\n" " END as \"%s\"", gettext_noop("Result data type"), @@ -376,9 +384,12 @@ describeFunctions(const char *functypes, const char *func_pattern, { appendPQExpBuffer(&buf, ",\n CASE\n" - " WHEN p.provolatile = 'i' THEN '%s'\n" - " WHEN p.provolatile = 's' THEN '%s'\n" - " WHEN p.provolatile = 'v' THEN '%s'\n" + " WHEN p.provolatile = " + CppAsString2(PROVOLATILE_IMMUTABLE) " THEN '%s'\n" + " WHEN p.provolatile = " + CppAsString2(PROVOLATILE_STABLE) " THEN '%s'\n" + " WHEN p.provolatile = " + CppAsString2(PROVOLATILE_VOLATILE) " THEN '%s'\n" " END as \"%s\"", gettext_noop("immutable"), gettext_noop("stable"), @@ -387,9 +398,12 @@ describeFunctions(const char *functypes, const char *func_pattern, if (pset.sversion >= 90600) appendPQExpBuffer(&buf, ",\n CASE\n" - " WHEN p.proparallel = 'r' THEN '%s'\n" - " WHEN p.proparallel = 's' THEN '%s'\n" - " WHEN p.proparallel = 'u' THEN '%s'\n" + " WHEN p.proparallel = " + CppAsString2(PROPARALLEL_RESTRICTED) " THEN '%s'\n" + " WHEN p.proparallel = " + CppAsString2(PROPARALLEL_SAFE) " THEN '%s'\n" + " WHEN p.proparallel = " + CppAsString2(PROPARALLEL_UNSAFE) " THEN '%s'\n" " END as \"%s\"", gettext_noop("restricted"), gettext_noop("safe"), @@ -397,11 +411,15 @@ describeFunctions(const char *functypes, const char *func_pattern, gettext_noop("Parallel")); appendPQExpBuffer(&buf, ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\"" - ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"", + ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"" + ",\n CASE WHEN p.proleakproof THEN '%s' ELSE '%s' END as \"%s\"", gettext_noop("Owner"), gettext_noop("definer"), gettext_noop("invoker"), - gettext_noop("Security")); + gettext_noop("Security"), + gettext_noop("yes"), + gettext_noop("no"), + gettext_noop("Leakproof?")); appendPQExpBufferStr(&buf, ",\n "); printACLColumn(&buf, "p.proacl"); appendPQExpBuffer(&buf, @@ -448,7 +466,8 @@ describeFunctions(const char *functypes, const char *func_pattern, have_where = true; } if (pset.sversion >= 110000) - appendPQExpBufferStr(&buf, "p.prokind <> 'a'\n"); + appendPQExpBufferStr(&buf, "p.prokind <> " + CppAsString2(PROKIND_AGGREGATE) "\n"); else appendPQExpBufferStr(&buf, "NOT p.proisagg\n"); } @@ -461,7 +480,8 @@ describeFunctions(const char *functypes, const char *func_pattern, appendPQExpBufferStr(&buf, "WHERE "); have_where = true; } - appendPQExpBufferStr(&buf, "p.prokind <> 'p'\n"); + appendPQExpBufferStr(&buf, "p.prokind <> " + CppAsString2(PROKIND_PROCEDURE) "\n"); } if (!showTrigger) { @@ -484,7 +504,8 @@ describeFunctions(const char *functypes, const char *func_pattern, have_where = true; } if (pset.sversion >= 110000) - appendPQExpBufferStr(&buf, "p.prokind <> 'w'\n"); + appendPQExpBufferStr(&buf, "p.prokind <> " + CppAsString2(PROKIND_WINDOW) "\n"); else appendPQExpBufferStr(&buf, "NOT p.proiswindow\n"); } @@ -499,7 +520,8 @@ describeFunctions(const char *functypes, const char *func_pattern, if (showAggregate) { if (pset.sversion >= 110000) - appendPQExpBufferStr(&buf, "p.prokind = 'a'\n"); + appendPQExpBufferStr(&buf, "p.prokind = " + CppAsString2(PROKIND_AGGREGATE) "\n"); else appendPQExpBufferStr(&buf, "p.proisagg\n"); needs_or = true; @@ -516,7 +538,8 @@ describeFunctions(const char *functypes, const char *func_pattern, { if (needs_or) appendPQExpBufferStr(&buf, " OR "); - appendPQExpBufferStr(&buf, "p.prokind = 'p'\n"); + appendPQExpBufferStr(&buf, "p.prokind = " + CppAsString2(PROKIND_PROCEDURE) "\n"); needs_or = true; } if (showWindow) @@ -524,7 +547,8 @@ describeFunctions(const char *functypes, const char *func_pattern, if (needs_or) appendPQExpBufferStr(&buf, " OR "); if (pset.sversion >= 110000) - appendPQExpBufferStr(&buf, "p.prokind = 'w'\n"); + appendPQExpBufferStr(&buf, "p.prokind = " + CppAsString2(PROKIND_WINDOW) "\n"); else appendPQExpBufferStr(&buf, "p.proiswindow\n"); } @@ -774,6 +798,7 @@ describeOperators(const char *oper_pattern, PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, false, false, false, false, true, false}; initPQExpBuffer(&buf); @@ -807,8 +832,12 @@ describeOperators(const char *oper_pattern, if (verbose) appendPQExpBuffer(&buf, - " o.oprcode AS \"%s\",\n", - gettext_noop("Function")); + " o.oprcode AS \"%s\",\n" + " CASE WHEN p.proleakproof THEN '%s' ELSE '%s' END AS \"%s\",\n", + gettext_noop("Function"), + gettext_noop("yes"), + gettext_noop("no"), + gettext_noop("Leakproof?")); appendPQExpBuffer(&buf, " coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n" @@ -833,6 +862,10 @@ describeOperators(const char *oper_pattern, " LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n"); } + if (verbose) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_proc p ON p.oid = o.oprcode\n"); + if (!showSystem && !oper_pattern) appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" " AND n.nspname <> 'information_schema'\n"); @@ -890,6 +923,8 @@ describeOperators(const char *oper_pattern, myopt.title = _("List of operators"); myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); printQuery(res, &myopt, pset.queryFout, false, pset.logfile); @@ -926,7 +961,11 @@ listAllDbs(const char *pattern, bool verbose) gettext_noop("Encoding")); if (pset.sversion >= 150000) appendPQExpBuffer(&buf, - " CASE d.datlocprovider WHEN 'b' THEN 'builtin' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n", + " CASE d.datlocprovider " + "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' " + "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' " + "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' " + "END AS \"%s\",\n", gettext_noop("Locale Provider")); else appendPQExpBuffer(&buf, @@ -1184,7 +1223,9 @@ listDefaultACLs(const char *pattern) printfPQExpBuffer(&buf, "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n" " n.nspname AS \"%s\",\n" - " CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n" + " CASE d.defaclobjtype " + " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'" + " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n" " ", gettext_noop("Owner"), gettext_noop("Schema"), @@ -1198,6 +1239,8 @@ listDefaultACLs(const char *pattern) gettext_noop("type"), DEFACLOBJ_NAMESPACE, gettext_noop("schema"), + DEFACLOBJ_LARGEOBJECT, + gettext_noop("large object"), gettext_noop("Type")); printACLColumn(&buf, "d.defaclacl"); @@ -1703,7 +1746,7 @@ describeOneTableDetails(const char *schemaname, *(PQgetvalue(res, 0, 13)) : 'd'; if (pset.sversion >= 120000) tableinfo.relam = PQgetisnull(res, 0, 14) ? - (char *) NULL : pg_strdup(PQgetvalue(res, 0, 14)); + NULL : pg_strdup(PQgetvalue(res, 0, 14)); else tableinfo.relam = NULL; PQclear(res); @@ -1812,7 +1855,7 @@ describeOneTableDetails(const char *schemaname, } PQclear(result); - if (tableinfo.relpersistence == 'u') + if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) printfPQExpBuffer(&title, _("Unlogged sequence \"%s.%s\""), schemaname, relationname); else @@ -1958,7 +2001,7 @@ describeOneTableDetails(const char *schemaname, switch (tableinfo.relkind) { case RELKIND_RELATION: - if (tableinfo.relpersistence == 'u') + if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""), schemaname, relationname); else @@ -1970,15 +2013,11 @@ describeOneTableDetails(const char *schemaname, schemaname, relationname); break; case RELKIND_MATVIEW: - if (tableinfo.relpersistence == 'u') - printfPQExpBuffer(&title, _("Unlogged materialized view \"%s.%s\""), - schemaname, relationname); - else - printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""), - schemaname, relationname); + printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""), + schemaname, relationname); break; case RELKIND_INDEX: - if (tableinfo.relpersistence == 'u') + if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) printfPQExpBuffer(&title, _("Unlogged index \"%s.%s\""), schemaname, relationname); else @@ -1986,7 +2025,7 @@ describeOneTableDetails(const char *schemaname, schemaname, relationname); break; case RELKIND_PARTITIONED_INDEX: - if (tableinfo.relpersistence == 'u') + if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) printfPQExpBuffer(&title, _("Unlogged partitioned index \"%s.%s\""), schemaname, relationname); else @@ -2006,7 +2045,7 @@ describeOneTableDetails(const char *schemaname, schemaname, relationname); break; case RELKIND_PARTITIONED_TABLE: - if (tableinfo.relpersistence == 'u') + if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED) printfPQExpBuffer(&title, _("Unlogged partitioned table \"%s.%s\""), schemaname, relationname); else @@ -2089,6 +2128,12 @@ describeOneTableDetails(const char *schemaname, PQgetvalue(res, i, attrdef_col)); mustfree = true; } + else if (generated[0] == ATTRIBUTE_GENERATED_VIRTUAL) + { + default_str = psprintf("generated always as (%s)", + PQgetvalue(res, i, attrdef_col)); + mustfree = true; + } else default_str = PQgetvalue(res, i, attrdef_col); @@ -2111,10 +2156,10 @@ describeOneTableDetails(const char *schemaname, char *storage = PQgetvalue(res, i, attstorage_col); /* these strings are literal in our syntax, so not translated. */ - printTableAddCell(&cont, (storage[0] == 'p' ? "plain" : - (storage[0] == 'm' ? "main" : - (storage[0] == 'x' ? "extended" : - (storage[0] == 'e' ? "external" : + printTableAddCell(&cont, (storage[0] == TYPSTORAGE_PLAIN ? "plain" : + (storage[0] == TYPSTORAGE_MAIN ? "main" : + (storage[0] == TYPSTORAGE_EXTENDED ? "extended" : + (storage[0] == TYPSTORAGE_EXTERNAL ? "external" : "???")))), false, false); } @@ -2262,13 +2307,17 @@ describeOneTableDetails(const char *schemaname, "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " "WHERE conrelid = i.indrelid AND " "conindid = i.indexrelid AND " - "contype IN ('p','u','x') AND " + "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) "," + CppAsString2(CONSTRAINT_UNIQUE) "," + CppAsString2(CONSTRAINT_EXCLUSION) ") AND " "condeferrable) AS condeferrable,\n" " (NOT i.indimmediate) AND " "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " "WHERE conrelid = i.indrelid AND " "conindid = i.indexrelid AND " - "contype IN ('p','u','x') AND " + "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) "," + CppAsString2(CONSTRAINT_UNIQUE) "," + CppAsString2(CONSTRAINT_EXCLUSION) ") AND " "condeferred) AS condeferred,\n"); if (pset.sversion >= 90400) @@ -2383,9 +2432,16 @@ describeOneTableDetails(const char *schemaname, else appendPQExpBufferStr(&buf, ", false AS indisreplident"); appendPQExpBufferStr(&buf, ", c2.reltablespace"); + if (pset.sversion >= 180000) + appendPQExpBufferStr(&buf, ", con.conperiod"); + else + appendPQExpBufferStr(&buf, ", false AS conperiod"); appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n" - " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n" + " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN (" + CppAsString2(CONSTRAINT_PRIMARY) "," + CppAsString2(CONSTRAINT_UNIQUE) "," + CppAsString2(CONSTRAINT_EXCLUSION) "))\n" "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" "ORDER BY i.indisprimary DESC, c2.relname;", oid); @@ -2404,8 +2460,12 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&buf, " \"%s\"", PQgetvalue(result, i, 0)); - /* If exclusion constraint, print the constraintdef */ - if (strcmp(PQgetvalue(result, i, 7), "x") == 0) + /* + * If exclusion constraint or PK/UNIQUE constraint WITHOUT + * OVERLAPS, print the constraintdef + */ + if (strcmp(PQgetvalue(result, i, 7), "x") == 0 || + strcmp(PQgetvalue(result, i, 12), "t") == 0) { appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 6)); @@ -2469,7 +2529,8 @@ describeOneTableDetails(const char *schemaname, "SELECT r.conname, " "pg_catalog.pg_get_constraintdef(r.oid, true)\n" "FROM pg_catalog.pg_constraint r\n" - "WHERE r.conrelid = '%s' AND r.contype = 'c'\n" + "WHERE r.conrelid = '%s' " + "AND r.contype = " CppAsString2(CONSTRAINT_CHECK) "\n" "ORDER BY 1;", oid); result = PSQLexec(buf.data); @@ -2494,136 +2555,124 @@ describeOneTableDetails(const char *schemaname, PQclear(result); } - /* - * Print foreign-key constraints (there are none if no triggers, - * except if the table is partitioned, in which case the triggers - * appear in the partitions) - */ - if (tableinfo.hastriggers || - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) + /* Print foreign-key constraints */ + if (pset.sversion >= 120000 && + (tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE)) { - if (pset.sversion >= 120000 && - (tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE)) - { - /* - * Put the constraints defined in this table first, followed - * by the constraints defined in ancestor partitioned tables. - */ - printfPQExpBuffer(&buf, - "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n" - " conname,\n" - " pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n" - " conrelid::pg_catalog.regclass AS ontable\n" - " FROM pg_catalog.pg_constraint,\n" - " pg_catalog.pg_partition_ancestors('%s')\n" - " WHERE conrelid = relid AND contype = 'f' AND conparentid = 0\n" - "ORDER BY sametable DESC, conname;", - oid, oid); - } - else - { - printfPQExpBuffer(&buf, - "SELECT true as sametable, conname,\n" - " pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n" - " conrelid::pg_catalog.regclass AS ontable\n" - "FROM pg_catalog.pg_constraint r\n" - "WHERE r.conrelid = '%s' AND r.contype = 'f'\n", - oid); - - if (pset.sversion >= 120000) - appendPQExpBufferStr(&buf, " AND conparentid = 0\n"); - appendPQExpBufferStr(&buf, "ORDER BY conname"); - } + /* + * Put the constraints defined in this table first, followed by + * the constraints defined in ancestor partitioned tables. + */ + printfPQExpBuffer(&buf, + "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n" + " conname,\n" + " pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n" + " conrelid::pg_catalog.regclass AS ontable\n" + " FROM pg_catalog.pg_constraint,\n" + " pg_catalog.pg_partition_ancestors('%s')\n" + " WHERE conrelid = relid AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n" + "ORDER BY sametable DESC, conname;", + oid, oid); + } + else + { + printfPQExpBuffer(&buf, + "SELECT true as sametable, conname,\n" + " pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n" + " conrelid::pg_catalog.regclass AS ontable\n" + "FROM pg_catalog.pg_constraint r\n" + "WHERE r.conrelid = '%s' AND r.contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n", + oid); - result = PSQLexec(buf.data); - if (!result) - goto error_return; - else - tuples = PQntuples(result); + if (pset.sversion >= 120000) + appendPQExpBufferStr(&buf, " AND conparentid = 0\n"); + appendPQExpBufferStr(&buf, "ORDER BY conname"); + } - if (tuples > 0) - { - int i_sametable = PQfnumber(result, "sametable"), - i_conname = PQfnumber(result, "conname"), - i_condef = PQfnumber(result, "condef"), - i_ontable = PQfnumber(result, "ontable"); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); - printTableAddFooter(&cont, _("Foreign-key constraints:")); - for (i = 0; i < tuples; i++) - { - /* - * Print untranslated constraint name and definition. Use - * a "TABLE tab" prefix when the constraint is defined in - * a parent partitioned table. - */ - if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0) - printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", - PQgetvalue(result, i, i_ontable), - PQgetvalue(result, i, i_conname), - PQgetvalue(result, i, i_condef)); - else - printfPQExpBuffer(&buf, " \"%s\" %s", - PQgetvalue(result, i, i_conname), - PQgetvalue(result, i, i_condef)); + if (tuples > 0) + { + int i_sametable = PQfnumber(result, "sametable"), + i_conname = PQfnumber(result, "conname"), + i_condef = PQfnumber(result, "condef"), + i_ontable = PQfnumber(result, "ontable"); - printTableAddFooter(&cont, buf.data); - } + printTableAddFooter(&cont, _("Foreign-key constraints:")); + for (i = 0; i < tuples; i++) + { + /* + * Print untranslated constraint name and definition. Use a + * "TABLE tab" prefix when the constraint is defined in a + * parent partitioned table. + */ + if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0) + printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", + PQgetvalue(result, i, i_ontable), + PQgetvalue(result, i, i_conname), + PQgetvalue(result, i, i_condef)); + else + printfPQExpBuffer(&buf, " \"%s\" %s", + PQgetvalue(result, i, i_conname), + PQgetvalue(result, i, i_condef)); + + printTableAddFooter(&cont, buf.data); } - PQclear(result); } + PQclear(result); /* print incoming foreign-key references */ - if (tableinfo.hastriggers || - tableinfo.relkind == RELKIND_PARTITIONED_TABLE) + if (pset.sversion >= 120000) { - if (pset.sversion >= 120000) - { - printfPQExpBuffer(&buf, - "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" - " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" - " FROM pg_catalog.pg_constraint c\n" - " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n" - " UNION ALL VALUES ('%s'::pg_catalog.regclass))\n" - " AND contype = 'f' AND conparentid = 0\n" - "ORDER BY conname;", - oid, oid); - } - else - { - printfPQExpBuffer(&buf, - "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" - " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" - " FROM pg_catalog.pg_constraint\n" - " WHERE confrelid = %s AND contype = 'f'\n" - "ORDER BY conname;", - oid); - } + printfPQExpBuffer(&buf, + "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" + " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" + " FROM pg_catalog.pg_constraint c\n" + " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n" + " UNION ALL VALUES ('%s'::pg_catalog.regclass))\n" + " AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n" + "ORDER BY conname;", + oid, oid); + } + else + { + printfPQExpBuffer(&buf, + "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n" + " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n" + " FROM pg_catalog.pg_constraint\n" + " WHERE confrelid = %s AND contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n" + "ORDER BY conname;", + oid); + } - result = PSQLexec(buf.data); - if (!result) - goto error_return; - else - tuples = PQntuples(result); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); - if (tuples > 0) - { - int i_conname = PQfnumber(result, "conname"), - i_ontable = PQfnumber(result, "ontable"), - i_condef = PQfnumber(result, "condef"); + if (tuples > 0) + { + int i_conname = PQfnumber(result, "conname"), + i_ontable = PQfnumber(result, "ontable"), + i_condef = PQfnumber(result, "condef"); - printTableAddFooter(&cont, _("Referenced by:")); - for (i = 0; i < tuples; i++) - { - printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", - PQgetvalue(result, i, i_ontable), - PQgetvalue(result, i, i_conname), - PQgetvalue(result, i, i_condef)); + printTableAddFooter(&cont, _("Referenced by:")); + for (i = 0; i < tuples; i++) + { + printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", + PQgetvalue(result, i, i_ontable), + PQgetvalue(result, i, i_conname), + PQgetvalue(result, i, i_condef)); - printTableAddFooter(&cont, buf.data); - } + printTableAddFooter(&cont, buf.data); } - PQclear(result); } + PQclear(result); /* print any row-level policies */ if (pset.sversion >= 90500) @@ -2716,9 +2765,9 @@ describeOneTableDetails(const char *schemaname, "stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS nsp, " "stxname,\n" "pg_catalog.pg_get_statisticsobjdef_columns(oid) AS columns,\n" - " 'd' = any(stxkind) AS ndist_enabled,\n" - " 'f' = any(stxkind) AS deps_enabled,\n" - " 'm' = any(stxkind) AS mcv_enabled,\n" + " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n" + " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n" + " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n" "stxstattarget\n" "FROM pg_catalog.pg_statistic_ext\n" "WHERE stxrelid = '%s'\n" @@ -2817,9 +2866,9 @@ describeOneTableDetails(const char *schemaname, " FROM pg_catalog.unnest(stxkeys) s(attnum)\n" " JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n" " a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n" - " 'd' = any(stxkind) AS ndist_enabled,\n" - " 'f' = any(stxkind) AS deps_enabled,\n" - " 'm' = any(stxkind) AS mcv_enabled,\n"); + " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n" + " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n" + " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n"); if (pset.sversion >= 130000) appendPQExpBufferStr(&buf, " stxstattarget\n"); @@ -3050,6 +3099,53 @@ describeOneTableDetails(const char *schemaname, } PQclear(result); } + + /* + * If verbose, print NOT NULL constraints. + */ + if (verbose) + { + printfPQExpBuffer(&buf, + "SELECT c.conname, a.attname, c.connoinherit,\n" + " c.conislocal, c.coninhcount <> 0,\n" + " c.convalidated\n" + "FROM pg_catalog.pg_constraint c JOIN\n" + " pg_catalog.pg_attribute a ON\n" + " (a.attrelid = c.conrelid AND a.attnum = c.conkey[1])\n" + "WHERE c.contype = " CppAsString2(CONSTRAINT_NOTNULL) " AND\n" + " c.conrelid = '%s'::pg_catalog.regclass\n" + "ORDER BY a.attnum", + oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + printTableAddFooter(&cont, _("Not-null constraints:")); + + /* Might be an empty set - that's ok */ + for (i = 0; i < tuples; i++) + { + bool islocal = PQgetvalue(result, i, 3)[0] == 't'; + bool inherited = PQgetvalue(result, i, 4)[0] == 't'; + bool validated = PQgetvalue(result, i, 5)[0] == 't'; + + printfPQExpBuffer(&buf, " \"%s\" NOT NULL \"%s\"%s%s", + PQgetvalue(result, i, 0), + PQgetvalue(result, i, 1), + PQgetvalue(result, i, 2)[0] == 't' ? + " NO INHERIT" : + islocal && inherited ? _(" (local, inherited)") : + inherited ? _(" (inherited)") : "", + !validated ? " NOT VALID" : ""); + + printTableAddFooter(&cont, buf.data); + } + PQclear(result); + } } /* Get view_def if table is a view or materialized view */ @@ -3479,16 +3575,18 @@ describeOneTableDetails(const char *schemaname, * No need to display default values; we already display a REPLICA * IDENTITY marker on indexes. */ - tableinfo.relreplident != 'i' && - ((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') || - (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n'))) + tableinfo.relreplident != REPLICA_IDENTITY_INDEX && + ((strcmp(schemaname, "pg_catalog") != 0 && + tableinfo.relreplident != REPLICA_IDENTITY_DEFAULT) || + (strcmp(schemaname, "pg_catalog") == 0 && + tableinfo.relreplident != REPLICA_IDENTITY_NOTHING))) { const char *s = _("Replica Identity"); printfPQExpBuffer(&buf, "%s: %s", s, - tableinfo.relreplident == 'f' ? "FULL" : - tableinfo.relreplident == 'n' ? "NOTHING" : + tableinfo.relreplident == REPLICA_IDENTITY_FULL ? "FULL" : + tableinfo.relreplident == REPLICA_IDENTITY_DEFAULT ? "NOTHING" : "???"); printTableAddFooter(&cont, buf.data); @@ -3915,14 +4013,18 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys bool showSeq = strchr(tabtypes, 's') != NULL; bool showForeign = strchr(tabtypes, 'E') != NULL; + int ntypes; PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; int cols_so_far; bool translate_columns[] = {false, false, true, false, false, false, false, false, false}; - /* If tabtypes is empty, we default to \dtvmsE (but see also command.c) */ - if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign)) + /* Count the number of explicitly-requested relation types */ + ntypes = showTables + showIndexes + showViews + showMatViews + + showSeq + showForeign; + /* If none, we default to \dtvmsE (but see also command.c) */ + if (ntypes == 0) showTables = showViews = showMatViews = showSeq = showForeign = true; initPQExpBuffer(&buf); @@ -3971,7 +4073,11 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys * Show whether a relation is permanent, temporary, or unlogged. */ appendPQExpBuffer(&buf, - ",\n CASE c.relpersistence WHEN 'p' THEN '%s' WHEN 't' THEN '%s' WHEN 'u' THEN '%s' END as \"%s\"", + ",\n CASE c.relpersistence " + "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' " + "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' " + "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' " + "END as \"%s\"", gettext_noop("permanent"), gettext_noop("temporary"), gettext_noop("unlogged"), @@ -4069,14 +4175,63 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys if (PQntuples(res) == 0 && !pset.quiet) { if (pattern) - pg_log_error("Did not find any relation named \"%s\".", - pattern); + { + if (ntypes != 1) + pg_log_error("Did not find any relations named \"%s\".", + pattern); + else if (showTables) + pg_log_error("Did not find any tables named \"%s\".", + pattern); + else if (showIndexes) + pg_log_error("Did not find any indexes named \"%s\".", + pattern); + else if (showViews) + pg_log_error("Did not find any views named \"%s\".", + pattern); + else if (showMatViews) + pg_log_error("Did not find any materialized views named \"%s\".", + pattern); + else if (showSeq) + pg_log_error("Did not find any sequences named \"%s\".", + pattern); + else if (showForeign) + pg_log_error("Did not find any foreign tables named \"%s\".", + pattern); + else /* should not get here */ + pg_log_error_internal("Did not find any ??? named \"%s\".", + pattern); + } else - pg_log_error("Did not find any relations."); + { + if (ntypes != 1) + pg_log_error("Did not find any relations."); + else if (showTables) + pg_log_error("Did not find any tables."); + else if (showIndexes) + pg_log_error("Did not find any indexes."); + else if (showViews) + pg_log_error("Did not find any views."); + else if (showMatViews) + pg_log_error("Did not find any materialized views."); + else if (showSeq) + pg_log_error("Did not find any sequences."); + else if (showForeign) + pg_log_error("Did not find any foreign tables."); + else /* should not get here */ + pg_log_error_internal("Did not find any ??? relations."); + } } else { - myopt.title = _("List of relations"); + myopt.title = + (ntypes != 1) ? _("List of relations") : + (showTables) ? _("List of tables") : + (showIndexes) ? _("List of indexes") : + (showViews) ? _("List of views") : + (showMatViews) ? _("List of materialized views") : + (showSeq) ? _("List of sequences") : + (showForeign) ? _("List of foreign tables") : + "List of ???"; /* should not get here */ myopt.translate_header = true; myopt.translate_columns = translate_columns; myopt.n_translate_columns = lengthof(translate_columns); @@ -4407,7 +4562,7 @@ listDomains(const char *pattern, bool verbose, bool showSystem) " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n" " t.typdefault as \"%s\",\n" " pg_catalog.array_to_string(ARRAY(\n" - " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid AND r.contype = 'c' ORDER BY r.conname\n" + " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid AND r.contype = " CppAsString2(CONSTRAINT_CHECK) " ORDER BY r.conname\n" " ), ' ') as \"%s\"", gettext_noop("Schema"), gettext_noop("Name"), @@ -4744,9 +4899,9 @@ listExtendedStats(const char *pattern) gettext_noop("Definition")); appendPQExpBuffer(&buf, - ",\nCASE WHEN 'd' = any(es.stxkind) THEN 'defined' \n" + ",\nCASE WHEN " CppAsString2(STATS_EXT_NDISTINCT) " = any(es.stxkind) THEN 'defined' \n" "END AS \"%s\", \n" - "CASE WHEN 'f' = any(es.stxkind) THEN 'defined' \n" + "CASE WHEN " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(es.stxkind) THEN 'defined' \n" "END AS \"%s\"", gettext_noop("Ndistinct"), gettext_noop("Dependencies")); @@ -4757,7 +4912,7 @@ listExtendedStats(const char *pattern) if (pset.sversion >= 120000) { appendPQExpBuffer(&buf, - ",\nCASE WHEN 'm' = any(es.stxkind) THEN 'defined' \n" + ",\nCASE WHEN " CppAsString2(STATS_EXT_MCV) " = any(es.stxkind) THEN 'defined' \n" "END AS \"%s\" ", gettext_noop("MCV")); } @@ -4802,7 +4957,7 @@ listCasts(const char *pattern, bool verbose) PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, false, false, true, false}; + static const bool translate_columns[] = {false, false, false, true, true, false}; initPQExpBuffer(&buf); @@ -4840,7 +4995,13 @@ listCasts(const char *pattern, bool verbose) if (verbose) appendPQExpBuffer(&buf, - ",\n d.description AS \"%s\"", + ",\n CASE WHEN p.proleakproof THEN '%s'\n" + " ELSE '%s'\n" + " END AS \"%s\",\n" + " d.description AS \"%s\"", + gettext_noop("yes"), + gettext_noop("no"), + gettext_noop("Leakproof?"), gettext_noop("Description")); /* @@ -4933,7 +5094,12 @@ listCollations(const char *pattern, bool verbose, bool showSystem) if (pset.sversion >= 100000) appendPQExpBuffer(&buf, - " CASE c.collprovider WHEN 'd' THEN 'default' WHEN 'b' THEN 'builtin' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n", + " CASE c.collprovider " + "WHEN " CppAsString2(COLLPROVIDER_DEFAULT) " THEN 'default' " + "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' " + "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' " + "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' " + "END AS \"%s\",\n", gettext_noop("Provider")); else appendPQExpBuffer(&buf, @@ -6018,13 +6184,16 @@ listExtensions(const char *pattern) initPQExpBuffer(&buf); printfPQExpBuffer(&buf, "SELECT e.extname AS \"%s\", " - "e.extversion AS \"%s\", n.nspname AS \"%s\", c.description AS \"%s\"\n" + "e.extversion AS \"%s\", ae.default_version AS \"%s\"," + "n.nspname AS \"%s\", d.description AS \"%s\"\n" "FROM pg_catalog.pg_extension e " "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace " - "LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid " - "AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass\n", + "LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid " + "AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass " + "LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname\n", gettext_noop("Name"), gettext_noop("Version"), + gettext_noop("Default version"), gettext_noop("Schema"), gettext_noop("Description")); @@ -6229,7 +6398,7 @@ listPublications(const char *pattern) PQExpBufferData buf; PGresult *res; printQueryOpt myopt = pset.popt; - static const bool translate_columns[] = {false, false, false, false, false, false, false, false}; + static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false}; if (pset.sversion < 100000) { @@ -6260,6 +6429,15 @@ listPublications(const char *pattern) appendPQExpBuffer(&buf, ",\n pubtruncate AS \"%s\"", gettext_noop("Truncates")); + if (pset.sversion >= 180000) + appendPQExpBuffer(&buf, + ",\n (CASE pubgencols\n" + " WHEN '%c' THEN 'none'\n" + " WHEN '%c' THEN 'stored'\n" + " END) AS \"%s\"", + PUBLISH_GENCOLS_NONE, + PUBLISH_GENCOLS_STORED, + gettext_noop("Generated columns")); if (pset.sversion >= 130000) appendPQExpBuffer(&buf, ",\n pubviaroot AS \"%s\"", @@ -6352,6 +6530,7 @@ describePublications(const char *pattern) int i; PGresult *res; bool has_pubtruncate; + bool has_pubgencols; bool has_pubviaroot; PQExpBufferData title; @@ -6368,6 +6547,7 @@ describePublications(const char *pattern) } has_pubtruncate = (pset.sversion >= 110000); + has_pubgencols = (pset.sversion >= 180000); has_pubviaroot = (pset.sversion >= 130000); initPQExpBuffer(&buf); @@ -6379,9 +6559,30 @@ describePublications(const char *pattern) if (has_pubtruncate) appendPQExpBufferStr(&buf, ", pubtruncate"); + else + appendPQExpBufferStr(&buf, + ", false AS pubtruncate"); + + if (has_pubgencols) + appendPQExpBuffer(&buf, + ", (CASE pubgencols\n" + " WHEN '%c' THEN 'none'\n" + " WHEN '%c' THEN 'stored'\n" + " END) AS \"%s\"\n", + PUBLISH_GENCOLS_NONE, + PUBLISH_GENCOLS_STORED, + gettext_noop("Generated columns")); + else + appendPQExpBufferStr(&buf, + ", 'none' AS pubgencols"); + if (has_pubviaroot) appendPQExpBufferStr(&buf, ", pubviaroot"); + else + appendPQExpBufferStr(&buf, + ", false AS pubviaroot"); + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_publication\n"); @@ -6431,6 +6632,8 @@ describePublications(const char *pattern) if (has_pubtruncate) ncols++; + if (has_pubgencols) + ncols++; if (has_pubviaroot) ncols++; @@ -6445,6 +6648,8 @@ describePublications(const char *pattern) printTableAddHeader(&cont, gettext_noop("Deletes"), true, align); if (has_pubtruncate) printTableAddHeader(&cont, gettext_noop("Truncates"), true, align); + if (has_pubgencols) + printTableAddHeader(&cont, gettext_noop("Generated columns"), true, align); if (has_pubviaroot) printTableAddHeader(&cont, gettext_noop("Via root"), true, align); @@ -6455,8 +6660,10 @@ describePublications(const char *pattern) printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false); if (has_pubtruncate) printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false); - if (has_pubviaroot) + if (has_pubgencols) printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false); + if (has_pubviaroot) + printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false); if (!puballtables) { @@ -6575,9 +6782,9 @@ describeSubscriptions(const char *pattern, bool verbose) if (pset.sversion >= 160000) appendPQExpBuffer(&buf, ", (CASE substream\n" - " WHEN 'f' THEN 'off'\n" - " WHEN 't' THEN 'on'\n" - " WHEN 'p' THEN 'parallel'\n" + " WHEN " CppAsString2(LOGICALREP_STREAM_OFF) " THEN 'off'\n" + " WHEN " CppAsString2(LOGICALREP_STREAM_ON) " THEN 'on'\n" + " WHEN " CppAsString2(LOGICALREP_STREAM_PARALLEL) " THEN 'parallel'\n" " END) AS \"%s\"\n", gettext_noop("Streaming")); else @@ -6670,7 +6877,7 @@ printACLColumn(PQExpBuffer buf, const char *colname) { appendPQExpBuffer(buf, "CASE" - " WHEN pg_catalog.cardinality(%s) = 0 THEN '%s'" + " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'" " ELSE pg_catalog.array_to_string(%s, E'\\n')" " END AS \"%s\"", colname, gettext_noop("(none)"), @@ -6882,7 +7089,7 @@ listOpFamilyOperators(const char *access_method_pattern, printQueryOpt myopt = pset.popt; bool have_where = false; - static const bool translate_columns[] = {false, false, false, false, false, false}; + static const bool translate_columns[] = {false, false, false, false, false, false, true}; initPQExpBuffer(&buf); @@ -6897,8 +7104,8 @@ listOpFamilyOperators(const char *access_method_pattern, " o.amopopr::pg_catalog.regoperator AS \"%s\"\n," " o.amopstrategy AS \"%s\",\n" " CASE o.amoppurpose\n" - " WHEN 'o' THEN '%s'\n" - " WHEN 's' THEN '%s'\n" + " WHEN " CppAsString2(AMOP_ORDER) " THEN '%s'\n" + " WHEN " CppAsString2(AMOP_SEARCH) " THEN '%s'\n" " END AS \"%s\"\n", gettext_noop("AM"), gettext_noop("Operator family"), @@ -6910,8 +7117,15 @@ listOpFamilyOperators(const char *access_method_pattern, if (verbose) appendPQExpBuffer(&buf, - ", ofs.opfname AS \"%s\"\n", - gettext_noop("Sort opfamily")); + ", ofs.opfname AS \"%s\",\n" + " CASE\n" + " WHEN p.proleakproof THEN '%s'\n" + " ELSE '%s'\n" + " END AS \"%s\"\n", + gettext_noop("Sort opfamily"), + gettext_noop("yes"), + gettext_noop("no"), + gettext_noop("Leakproof?")); appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_amop o\n" " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n" @@ -6919,7 +7133,9 @@ listOpFamilyOperators(const char *access_method_pattern, " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n"); if (verbose) appendPQExpBufferStr(&buf, - " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"); + " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n" + " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n" + " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n"); if (access_method_pattern) { diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 273f974538e4a..18ecaa60949d6 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/describe.h */ diff --git a/src/bin/psql/gen_tabcomplete.pl b/src/bin/psql/gen_tabcomplete.pl new file mode 100644 index 0000000000000..37899dd02bc19 --- /dev/null +++ b/src/bin/psql/gen_tabcomplete.pl @@ -0,0 +1,307 @@ +#---------------------------------------------------------------------- +# +# gen_tabcomplete.pl +# Perl script that transforms tab-complete.in.c to tab-complete.c. +# +# This script converts a C else-if chain into a switch statement. +# The else-if statements to be processed must appear at single-tab-stop +# indentation between lines reading +# /* BEGIN GEN_TABCOMPLETE */ +# /* END GEN_TABCOMPLETE */ +# The first clause in each if-condition must be a call of one of the +# functions Matches, HeadMatches, TailMatches, MatchesCS, HeadMatchesCS, +# or TailMatchesCS. Its argument(s) must be string literals or macros +# that expand to string literals or NULL. These clauses are removed from +# the code and replaced by "break; case N:", where N is a unique number +# for each such case label. +# The BEGIN GEN_TABCOMPLETE and END GEN_TABCOMPLETE lines are replaced +# by "switch (pattern_id) {" and "}" wrapping to make a valid switch. +# The remainder of the code is copied verbatim. +# +# An if-condition can also be an OR ("||") of several *Matches function +# calls, or it can be an AND ("&&") of a *Matches call with some other +# condition. For example, +# +# else if (HeadMatches("DROP", "DATABASE") && ends_with(prev_wd, '(')) +# +# will be transformed to +# +# break; +# case N: +# if (ends_with(prev_wd, '(')) +# +# In addition, there must be one input line that reads +# /* Insert tab-completion pattern data here. */ +# This line is replaced in the output file by macro calls, one for each +# replaced match condition. The output for the above example would be +# TCPAT(N, HeadMatch, "DROP", "DATABASE"), +# where N is the replacement case label, "HeadMatch" is the original +# function name minus "es", and the rest are the function arguments. +# The tab-completion data line must appear before BEGIN GEN_TABCOMPLETE. +# +# +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/bin/psql/gen_tabcomplete.pl +# +#---------------------------------------------------------------------- + +use strict; +use warnings FATAL => 'all'; +use Getopt::Long; + +my $outfile = ''; + +GetOptions('outfile=s' => \$outfile) or die "$0: wrong arguments"; + +my $infile = $ARGV[0]; +open my $infh, '<', $infile + or die "$0: could not open input file '$infile': $!\n"; + +my $outfh; +if ($outfile) +{ + open $outfh, '>', $outfile + or die "$0: could not open output file '$outfile': $!\n"; +} +else +{ + $outfh = *STDOUT; +} + +# Opening boilerplate for output file. +printf $outfh <) +{ + chomp; + last if m|^\s*/\* Insert tab-completion pattern data here\. \*/\s*$|; + print $outfh "$_\n"; +} + +# $table_data collects what we will substitute for the "pattern data" line. +my $table_data = ''; +# $output_code collects code that we can't emit till after $table_data. +my $output_code = ''; +# last case label assigned +my $last_case_label = 0; + +# We emit #line directives to keep the output file's line numbering in sync +# with the line numbering of the original, to simplify compiler error message +# reading and debugging. +my $next_line_no = $. + 1; +$output_code .= "#line ${next_line_no} \"${infile}\"\n"; + +# Scan until we find the BEGIN GEN_TABCOMPLETE line. +# Add the scanned code to $output_code verbatim. +while (<$infh>) +{ + chomp; + last if m|^\s*/\* BEGIN GEN_TABCOMPLETE \*/\s*$|; + $output_code .= $_ . "\n"; +} + +# Emit the switch-starting lines. +$output_code .= "\tswitch (pattern_id)\n"; +$output_code .= "\t{\n"; + +# Keep line numbering in sync. +$next_line_no = $. + 1; +$output_code .= "#line ${next_line_no} \"${infile}\"\n"; + +# Scan input file, collecting outer-level else-if conditions +# to pass to process_else_if. +# Lines that aren't else-if conditions go to $output_code verbatim. +# True if we're handling a multiline else-if condition +my $in_else_if = 0; +# The accumulated line +my $else_if_line; +my $else_if_lineno; + +while (<$infh>) +{ + chomp; + last if m|^\s*/\* END GEN_TABCOMPLETE \*/\s*$|; + if ($in_else_if) + { + my $rest = $_; + # collapse leading whitespace + $rest =~ s/^\s+//; + $else_if_line .= ' ' . $rest; + # Double right paren is currently sufficient to detect completion + if ($else_if_line =~ m/\)\)$/) + { + process_else_if($else_if_line, $else_if_lineno, $.); + $in_else_if = 0; + } + } + elsif (m/^\telse if \(/) + { + $else_if_line = $_; + $else_if_lineno = $.; + # Double right paren is currently sufficient to detect completion + if ($else_if_line =~ m/\)\)$/) + { + process_else_if($else_if_line, $else_if_lineno, $.); + } + else + { + $in_else_if = 1; + } + } + else + { + $output_code .= $_ . "\n"; + } +} + +die "unfinished else-if" if $in_else_if; + +# Emit the switch-ending lines. +$output_code .= "\tbreak;\n"; +$output_code .= "\tdefault:\n"; +$output_code .= "\t\tAssert(false);\n"; +$output_code .= "\t\tbreak;\n"; +$output_code .= "\t}\n"; + +# Keep line numbering in sync. +$next_line_no = $. + 1; +$output_code .= "#line ${next_line_no} \"${infile}\"\n"; + +# Scan the rest, adding it to $output_code verbatim. +while (<$infh>) +{ + chomp; + $output_code .= $_ . "\n"; +} + +# Dump out the table data. +print $outfh $table_data; + +# Dump out the modified code, and we're done! +print $outfh $output_code; + +close($infh); +close($outfh); + +# Disassemble an else-if condition. +# Add the generated table-contents macro(s) to $table_data, +# and add the replacement case label(s) to $output_code. +sub process_else_if +{ + my ($else_if_line, $else_if_lineno, $end_lineno) = @_; + + # Strip the initial "else if (", which we know is there + $else_if_line =~ s/^\telse if \(//; + + # Handle OR'd conditions + my $isfirst = 1; + while ($else_if_line =~ + s/^(Head|Tail|)Matches(CS|)\((("[^"]*"|MatchAnyExcept\("[^"]*"\)|[A-Za-z,\s])+)\)\s*\|\|\s*// + ) + { + my $typ = $1; + my $cs = $2; + my $args = $3; + process_match($typ, $cs, $args, $else_if_lineno, $isfirst); + $isfirst = 0; + } + + # Check for AND'd condition + if ($else_if_line =~ + s/^(Head|Tail|)Matches(CS|)\((("[^"]*"|MatchAnyExcept\("[^"]*"\)|[A-Za-z,\s])+)\)\s*&&\s*// + ) + { + my $typ = $1; + my $cs = $2; + my $args = $3; + warn + "could not process OR/ANDed if condition at line $else_if_lineno\n" + if !$isfirst; + process_match($typ, $cs, $args, $else_if_lineno, $isfirst); + $isfirst = 0; + # approximate line positioning of AND'd condition + $output_code .= "#line ${end_lineno} \"${infile}\"\n"; + $output_code .= "\tif ($else_if_line\n"; + } + elsif ($else_if_line =~ + s/^(Head|Tail|)Matches(CS|)\((("[^"]*"|MatchAnyExcept\("[^"]*"\)|[A-Za-z,\s])+)\)\)$// + ) + { + my $typ = $1; + my $cs = $2; + my $args = $3; + process_match($typ, $cs, $args, $else_if_lineno, $isfirst); + $isfirst = 0; + } + else + { + warn + "could not process if condition at line $else_if_lineno: the rest looks like $else_if_line\n"; + $output_code .= "\telse if ($else_if_line\n"; + } + + # Keep line numbering in sync. + if ($end_lineno != $else_if_lineno) + { + my $next_lineno = $end_lineno + 1; + $output_code .= "#line ${next_lineno} \"${infile}\"\n"; + } +} + +sub process_match +{ + my ($typ, $cs, $args, $lineno, $isfirst) = @_; + + # Assign a new case label only for the first pattern in an OR group. + if ($isfirst) + { + $last_case_label++; + + # We intentionally keep the "break;" and the "case" on one line, so + # that they have the same line number as the original "else if"'s + # first line. This avoids misleading displays in, e.g., lcov. + $output_code .= "\t"; + $output_code .= "break; " if $last_case_label > 1; + $output_code .= "case $last_case_label:\n"; + } + + $table_data .= + "\tTCPAT(${last_case_label}, ${typ}Match${cs}, ${args}),\n"; +} + + +sub usage +{ + die <] input_file + --outfile Output file (default is stdout) + +gen_tabcomplete.pl transforms tab-complete.in.c to tab-complete.c. +EOM +} diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 6f58a11074806..db6adec8b692b 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/help.c */ @@ -21,9 +21,6 @@ #include #endif -#include "common.h" -#include "common/logging.h" -#include "common/username.h" #include "help.h" #include "input.h" #include "settings.h" @@ -164,7 +161,6 @@ slashUsage(unsigned short int pager) initPQExpBuffer(&buf); HELP0("General\n"); - HELP0(" \\bind [PARAM]... set query parameters\n"); HELP0(" \\copyright show PostgreSQL usage and distribution terms\n"); HELP0(" \\crosstabview [COLUMNS] execute query and display result in crosstab\n"); HELP0(" \\errverbose show most recent error message at maximum verbosity\n"); @@ -218,67 +214,68 @@ slashUsage(unsigned short int pager) HELP0("\n"); HELP0("Informational\n"); - HELP0(" (options: S = show system objects, + = additional detail)\n"); - HELP0(" \\d[S+] list tables, views, and sequences\n"); - HELP0(" \\d[S+] NAME describe table, view, sequence, or index\n"); - HELP0(" \\da[S] [PATTERN] list aggregates\n"); - HELP0(" \\dA[+] [PATTERN] list access methods\n"); - HELP0(" \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n"); - HELP0(" \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n"); - HELP0(" \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n"); - HELP0(" \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n"); - HELP0(" \\db[+] [PATTERN] list tablespaces\n"); - HELP0(" \\dc[S+] [PATTERN] list conversions\n"); - HELP0(" \\dconfig[+] [PATTERN] list configuration parameters\n"); - HELP0(" \\dC[+] [PATTERN] list casts\n"); - HELP0(" \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n"); - HELP0(" \\dD[S+] [PATTERN] list domains\n"); - HELP0(" \\ddp [PATTERN] list default privileges\n"); - HELP0(" \\dE[S+] [PATTERN] list foreign tables\n"); - HELP0(" \\des[+] [PATTERN] list foreign servers\n"); - HELP0(" \\det[+] [PATTERN] list foreign tables\n"); - HELP0(" \\deu[+] [PATTERN] list user mappings\n"); - HELP0(" \\dew[+] [PATTERN] list foreign-data wrappers\n"); - HELP0(" \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" + HELP0(" (options: S = show system objects, x = expanded mode, + = additional detail)\n"); + HELP0(" \\d[Sx+] list tables, views, and sequences\n"); + HELP0(" \\d[S+] NAME describe table, view, sequence, or index\n"); + HELP0(" \\da[Sx] [PATTERN] list aggregates\n"); + HELP0(" \\dA[x+] [PATTERN] list access methods\n"); + HELP0(" \\dAc[x+] [AMPTRN [TYPEPTRN]] list operator classes\n"); + HELP0(" \\dAf[x+] [AMPTRN [TYPEPTRN]] list operator families\n"); + HELP0(" \\dAo[x+] [AMPTRN [OPFPTRN]] list operators of operator families\n"); + HELP0(" \\dAp[x+] [AMPTRN [OPFPTRN]] list support functions of operator families\n"); + HELP0(" \\db[x+] [PATTERN] list tablespaces\n"); + HELP0(" \\dc[Sx+] [PATTERN] list conversions\n"); + HELP0(" \\dconfig[x+] [PATTERN] list configuration parameters\n"); + HELP0(" \\dC[x+] [PATTERN] list casts\n"); + HELP0(" \\dd[Sx] [PATTERN] show object descriptions not displayed elsewhere\n"); + HELP0(" \\dD[Sx+] [PATTERN] list domains\n"); + HELP0(" \\ddp[x] [PATTERN] list default privileges\n"); + HELP0(" \\dE[Sx+] [PATTERN] list foreign tables\n"); + HELP0(" \\des[x+] [PATTERN] list foreign servers\n"); + HELP0(" \\det[x+] [PATTERN] list foreign tables\n"); + HELP0(" \\deu[x+] [PATTERN] list user mappings\n"); + HELP0(" \\dew[x+] [PATTERN] list foreign-data wrappers\n"); + HELP0(" \\df[anptw][Sx+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] functions\n"); - HELP0(" \\dF[+] [PATTERN] list text search configurations\n"); - HELP0(" \\dFd[+] [PATTERN] list text search dictionaries\n"); - HELP0(" \\dFp[+] [PATTERN] list text search parsers\n"); - HELP0(" \\dFt[+] [PATTERN] list text search templates\n"); - HELP0(" \\dg[S+] [PATTERN] list roles\n"); - HELP0(" \\di[S+] [PATTERN] list indexes\n"); - HELP0(" \\dl[+] list large objects, same as \\lo_list\n"); - HELP0(" \\dL[S+] [PATTERN] list procedural languages\n"); - HELP0(" \\dm[S+] [PATTERN] list materialized views\n"); - HELP0(" \\dn[S+] [PATTERN] list schemas\n"); - HELP0(" \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" + HELP0(" \\dF[x+] [PATTERN] list text search configurations\n"); + HELP0(" \\dFd[x+] [PATTERN] list text search dictionaries\n"); + HELP0(" \\dFp[x+] [PATTERN] list text search parsers\n"); + HELP0(" \\dFt[x+] [PATTERN] list text search templates\n"); + HELP0(" \\dg[Sx+] [PATTERN] list roles\n"); + HELP0(" \\di[Sx+] [PATTERN] list indexes\n"); + HELP0(" \\dl[x+] list large objects, same as \\lo_list\n"); + HELP0(" \\dL[Sx+] [PATTERN] list procedural languages\n"); + HELP0(" \\dm[Sx+] [PATTERN] list materialized views\n"); + HELP0(" \\dn[Sx+] [PATTERN] list schemas\n"); + HELP0(" \\do[Sx+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n"); - HELP0(" \\dO[S+] [PATTERN] list collations\n"); - HELP0(" \\dp[S] [PATTERN] list table, view, and sequence access privileges\n"); - HELP0(" \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n"); - HELP0(" \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n"); - HELP0(" \\drg[S] [PATTERN] list role grants\n"); - HELP0(" \\dRp[+] [PATTERN] list replication publications\n"); - HELP0(" \\dRs[+] [PATTERN] list replication subscriptions\n"); - HELP0(" \\ds[S+] [PATTERN] list sequences\n"); - HELP0(" \\dt[S+] [PATTERN] list tables\n"); - HELP0(" \\dT[S+] [PATTERN] list data types\n"); - HELP0(" \\du[S+] [PATTERN] list roles\n"); - HELP0(" \\dv[S+] [PATTERN] list views\n"); - HELP0(" \\dx[+] [PATTERN] list extensions\n"); - HELP0(" \\dX [PATTERN] list extended statistics\n"); - HELP0(" \\dy[+] [PATTERN] list event triggers\n"); - HELP0(" \\l[+] [PATTERN] list databases\n"); - HELP0(" \\sf[+] FUNCNAME show a function's definition\n"); - HELP0(" \\sv[+] VIEWNAME show a view's definition\n"); - HELP0(" \\z[S] [PATTERN] same as \\dp\n"); + HELP0(" \\dO[Sx+] [PATTERN] list collations\n"); + HELP0(" \\dp[Sx] [PATTERN] list table, view, and sequence access privileges\n"); + HELP0(" \\dP[itnx+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n"); + HELP0(" \\drds[x] [ROLEPTRN [DBPTRN]]\n" + " list per-database role settings\n"); + HELP0(" \\drg[Sx] [PATTERN] list role grants\n"); + HELP0(" \\dRp[x+] [PATTERN] list replication publications\n"); + HELP0(" \\dRs[x+] [PATTERN] list replication subscriptions\n"); + HELP0(" \\ds[Sx+] [PATTERN] list sequences\n"); + HELP0(" \\dt[Sx+] [PATTERN] list tables\n"); + HELP0(" \\dT[Sx+] [PATTERN] list data types\n"); + HELP0(" \\du[Sx+] [PATTERN] list roles\n"); + HELP0(" \\dv[Sx+] [PATTERN] list views\n"); + HELP0(" \\dx[x+] [PATTERN] list extensions\n"); + HELP0(" \\dX[x] [PATTERN] list extended statistics\n"); + HELP0(" \\dy[x+] [PATTERN] list event triggers\n"); + HELP0(" \\l[x+] [PATTERN] list databases\n"); + HELP0(" \\sf[+] FUNCNAME show a function's definition\n"); + HELP0(" \\sv[+] VIEWNAME show a view's definition\n"); + HELP0(" \\z[Sx] [PATTERN] same as \\dp\n"); HELP0("\n"); HELP0("Large Objects\n"); HELP0(" \\lo_export LOBOID FILE write large object to file\n"); HELP0(" \\lo_import FILE [COMMENT]\n" " read large object from file\n"); - HELP0(" \\lo_list[+] list large objects\n"); + HELP0(" \\lo_list[x+] list large objects\n"); HELP0(" \\lo_unlink LOBOID delete a large object\n"); HELP0("\n"); @@ -294,7 +291,7 @@ slashUsage(unsigned short int pager) " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" - " unicode_header_linestyle)\n"); + " unicode_header_linestyle|xheader_width)\n"); HELPN(" \\t [on|off] show only rows (currently %s)\n", ON(pset.popt.topt.tuples_only)); HELP0(" \\T [STRING] set HTML
tag attributes, or unset if none\n"); @@ -328,6 +325,21 @@ slashUsage(unsigned short int pager) HELP0(" \\prompt [TEXT] NAME prompt user to set internal variable\n"); HELP0(" \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n"); HELP0(" \\unset NAME unset (delete) internal variable\n"); + HELP0("\n"); + + HELP0("Extended Query Protocol\n"); + HELP0(" \\bind [PARAM]... set query parameters\n"); + HELP0(" \\bind_named STMT_NAME [PARAM]...\n" + " set query parameters for an existing prepared statement\n"); + HELP0(" \\close STMT_NAME close an existing prepared statement\n"); + HELP0(" \\endpipeline exit pipeline mode\n"); + HELP0(" \\flush flush output data to the server\n"); + HELP0(" \\flushrequest send request to the server to flush its output buffer\n"); + HELP0(" \\getresults [NUM_RES] read NUM_RES pending results, or all if no argument\n"); + HELP0(" \\parse STMT_NAME create a prepared statement\n"); + HELP0(" \\sendpipeline send an extended query to an ongoing pipeline\n"); + HELP0(" \\startpipeline enter pipeline mode\n"); + HELP0(" \\syncpipeline add a synchronisation point to an ongoing pipeline\n"); /* Now we can count the lines. */ nlcount = 0; @@ -451,6 +463,9 @@ helpVariables(unsigned short int pager) " VERSION_NAME\n" " VERSION_NUM\n" " psql's version (in verbose string, short string, or numeric format)\n"); + HELPN(" WATCH_INTERVAL\n" + " number of seconds \\watch waits between executions (default %s)\n", + DEFAULT_WATCH_INTERVAL); HELP0("\nDisplay settings:\n"); HELP0("Usage:\n"); @@ -494,6 +509,9 @@ helpVariables(unsigned short int pager) " unicode_column_linestyle\n" " unicode_header_linestyle\n" " set the style of Unicode line drawing [single, double]\n"); + HELP0(" xheader_width\n" + " set the maximum width of the header for expanded output\n" + " [full, column, page, integer value]\n"); HELP0("\nEnvironment variables:\n"); HELP0("Usage:\n"); @@ -730,7 +748,7 @@ print_copyright(void) { puts("PostgreSQL Database Management System\n" "(formerly known as Postgres, then as Postgres95)\n\n" - "Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group\n\n" + "Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group\n\n" "Portions Copyright (c) 1994, The Regents of the University of California\n\n" "Permission to use, copy, modify, and distribute this software and its\n" "documentation for any purpose, without fee, and without a written agreement\n" diff --git a/src/bin/psql/help.h b/src/bin/psql/help.h index a5acce4cfb191..4a6c566d45f9f 100644 --- a/src/bin/psql/help.h +++ b/src/bin/psql/help.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/help.h */ diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c index 01b7ef74c30c6..d0156ac4de21b 100644 --- a/src/bin/psql/input.c +++ b/src/bin/psql/input.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/input.c */ diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h index 4c486d67d292c..6b2f84e0d0cf4 100644 --- a/src/bin/psql/input.h +++ b/src/bin/psql/input.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/input.h */ diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index e58a9c647e06e..28f8c414b672c 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/large_obj.c */ diff --git a/src/bin/psql/large_obj.h b/src/bin/psql/large_obj.h index 3c3cbe1672ce1..c6467f80f5a1a 100644 --- a/src/bin/psql/large_obj.h +++ b/src/bin/psql/large_obj.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/large_obj.h */ diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index c24e38d988c73..0e0baa3540b14 100644 --- a/src/bin/psql/mainloop.c +++ b/src/bin/psql/mainloop.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/mainloop.c */ @@ -69,7 +69,7 @@ MainLoop(FILE *source) /* Create working state */ scan_state = psql_scan_create(&psqlscan_callbacks); cond_stack = conditional_stack_create(); - psql_scan_set_passthrough(scan_state, (void *) cond_stack); + psql_scan_set_passthrough(scan_state, cond_stack); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); diff --git a/src/bin/psql/mainloop.h b/src/bin/psql/mainloop.h index 6bf00d299c083..075bbfed41b4f 100644 --- a/src/bin/psql/mainloop.h +++ b/src/bin/psql/mainloop.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/mainloop.h */ diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build index f3a6392138abf..f795ff282711c 100644 --- a/src/bin/psql/meson.build +++ b/src/bin/psql/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group psql_sources = files( 'command.c', @@ -13,17 +13,27 @@ psql_sources = files( 'prompt.c', 'startup.c', 'stringutils.c', - 'tab-complete.c', 'variables.c', ) psqlscanslash = custom_target('psqlscanslash', input: 'psqlscanslash.l', output: 'psqlscanslash.c', - command: [flex_cmd, '--no-backup', '--fix-warnings', '--', '-Cfe', '-p', '-p']) + command: [flex_cmd, '--no-backup', '--', '-Cfe', '-p', '-p']) generated_sources += psqlscanslash psql_sources += psqlscanslash +tabcomplete = custom_target('tabcomplete', + input: 'tab-complete.in.c', + output: 'tab-complete.c', + command: [ + perl, files('gen_tabcomplete.pl'), '@INPUT@', + '--outfile', '@OUTPUT@', + ], +) +generated_sources += tabcomplete +psql_sources += tabcomplete + sql_help = custom_target('psql_help', output: ['sql_help.c', 'sql_help.h'], depfile: 'sql_help.dep', diff --git a/src/bin/psql/nls.mk b/src/bin/psql/nls.mk index 7fd8fedead4f5..ef80163f9a48a 100644 --- a/src/bin/psql/nls.mk +++ b/src/bin/psql/nls.mk @@ -23,8 +23,7 @@ GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) \ ../../common/exec.c \ ../../common/fe_memutils.c \ ../../common/username.c \ - ../../common/wait_error.c \ - ../../port/user.c + ../../common/wait_error.c GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS) \ HELP0 HELPN N_ simple_prompt simple_prompt_extended GETTEXT_FLAGS = $(FRONTEND_COMMON_GETTEXT_FLAGS) \ diff --git a/src/bin/psql/po/cs.po b/src/bin/psql/po/cs.po index e50d301a2fff1..9b8240cb9bbc4 100644 --- a/src/bin/psql/po/cs.po +++ b/src/bin/psql/po/cs.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: psql-cs (PostgreSQL 9.3)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2020-10-31 16:14+0000\n" -"PO-Revision-Date: 2023-09-05 09:51+0200\n" +"PO-Revision-Date: 2024-06-26 09:15+0200\n" "Last-Translator: Tomas Vondra \n" "Language-Team: Czech \n" "Language: cs\n" @@ -2421,7 +2421,6 @@ msgstr "" " -v, --set=, --variable=JMÉNO=HODNOTA\n" " nastaví psql proměnnou JMÉNO na HODNOTA\n" " (e.g., -v ON_ERROR_STOP=1)\n" -"\n" #: help.c:89 #, c-format @@ -2799,7 +2798,7 @@ msgstr " \\copy ... provede SQL COPY s tokem dat na klienta\n" #, c-format msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr "" -" \\echo [-n] [ŘETĚZEC] vypsání textu na standardní výstup (-n pro potlačení\n" +" \\echo [-n] [ŘETĚZEC] vypsání textu na standardní výstup (-n pro potlačení\n" " nového řádku)\n" #: help.c:211 diff --git a/src/bin/psql/po/de.po b/src/bin/psql/po/de.po index 195c027d79cf2..78747ffc1a065 100644 --- a/src/bin/psql/po/de.po +++ b/src/bin/psql/po/de.po @@ -1,14 +1,14 @@ # German message translation file for psql -# Peter Eisentraut , 2001 - 2024. +# Peter Eisentraut , 2001 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 10:18+0000\n" -"PO-Revision-Date: 2024-06-16 19:02+0200\n" +"POT-Creation-Date: 2025-04-27 00:48+0000\n" +"PO-Revision-Date: 2025-04-27 16:04+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -17,22 +17,22 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -57,28 +57,28 @@ msgstr "konnte kein »%s« zum Ausführen finden" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "konnte Pfad »%s« nicht in absolute Form auflösen: %m" -#: ../../common/exec.c:382 copy.c:326 +#: ../../common/exec.c:363 copy.c:326 #, c-format msgid "could not execute command \"%s\": %m" msgstr "konnte Befehl »%s« nicht ausführen: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "konnte nicht von Befehl »%s« lesen: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "Befehl »%s« gab keine Daten zurück" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s() fehlgeschlagen: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 -#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 +#: command.c:1636 command.c:3985 command.c:4034 command.c:4159 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -100,7 +100,7 @@ msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" msgid "could not look up effective user ID %ld: %s" msgstr "konnte effektive Benutzer-ID %ld nicht nachschlagen: %s" -#: ../../common/username.c:45 command.c:616 +#: ../../common/username.c:45 command.c:700 msgid "user does not exist" msgstr "Benutzer existiert nicht" @@ -161,8 +161,8 @@ msgstr "Unterbrochen\n" #: ../../fe_utils/print.c:3188 #, c-format -msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" -msgstr "Kann Tabelleninhalt nicht ausgeben: Anzahl der Zellen %lld ist gleich oder überschreitet Maximum %lld.\n" +msgid "Cannot print table contents: number of cells % is equal to or exceeds maximum %zu.\n" +msgstr "Kann Tabelleninhalt nicht ausgeben: Anzahl der Zellen % ist gleich oder überschreitet Maximum %zu.\n" #: ../../fe_utils/print.c:3229 #, c-format @@ -171,325 +171,434 @@ msgstr "Kann keinen weiteren Spaltenkopf zur Tabelle hinzufügen: Spaltenzahl %d #: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" -msgstr "Kann keine weitere Zelle zur Tabelle hinzufügen: Zellengesamtzahl %lld überschritten.\n" +msgid "Cannot add cell to table content: total cell count of % exceeded.\n" +msgstr "Kann keine weitere Zelle zur Tabelle hinzufügen: Zellengesamtzahl % überschritten.\n" #: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "ungültiges Ausgabeformat (interner Fehler): %d" -#: ../../fe_utils/psqlscan.l:718 +#: ../../fe_utils/psqlscan.l:723 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "rekursive Auswertung der Variable »%s« wird ausgelassen" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" -#: ../../port/user.c:43 ../../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "konnte lokale Benutzer-ID %d nicht nachschlagen: %s" - -#: ../../port/user.c:48 ../../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "lokaler Benutzer mit ID %d existiert nicht" - -#: command.c:235 +#: command.c:245 #, c-format msgid "invalid command \\%s" msgstr "ungültige Anweisung \\%s" -#: command.c:237 +#: command.c:247 #, c-format msgid "Try \\? for help." msgstr "Versuchen Sie \\? für Hilfe." -#: command.c:255 +#: command.c:265 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: überflüssiges Argument »%s« ignoriert" -#: command.c:307 +#: command.c:317 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "Befehl \\%s ignoriert; verwenden Sie \\endif oder Strg-C um den aktuellen \\if-Block zu beenden" -#: command.c:614 +#: command.c:552 command.c:747 command.c:1882 command.c:2050 command.c:2363 +#: command.c:2377 command.c:2409 command.c:2498 command.c:2611 command.c:2889 +#: command.c:3151 command.c:3191 +#, c-format +msgid "\\%s: missing required argument" +msgstr "\\%s: notwendiges Argument fehlt" + +#: command.c:698 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "konnte Home-Verzeichnis für Benutzer-ID %ld nicht ermitteln: %s" -#: command.c:633 +#: command.c:717 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: konnte nicht in das Verzeichnis »%s« wechseln: %m" -#: command.c:657 +#: command.c:789 #, c-format msgid "You are currently not connected to a database.\n" msgstr "Sie sind gegenwärtig nicht mit einer Datenbank verbunden.\n" -#: command.c:667 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" -msgstr "Sie sind verbunden mit der Datenbank »%s« als Benutzer »%s« auf Adresse »%s« auf Port »%s«.\n" +#: command.c:815 +msgid "Connection Information" +msgstr "Verbindungsinformationen" -#: command.c:670 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" -msgstr "Sie sind verbunden mit der Datenbank »%s« als Benutzer »%s« via Socket in »%s« auf Port »%s«.\n" +#: command.c:816 describe.c:4721 +msgid "Parameter" +msgstr "Parameter" -#: command.c:676 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" -msgstr "Sie sind verbunden mit der Datenbank »%s« als Benutzer »%s« auf Host »%s« (Adresse »%s«) auf Port »%s«.\n" +#: command.c:817 describe.c:4722 +msgid "Value" +msgstr "Wert" -#: command.c:679 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" -msgstr "Sie sind verbunden mit der Datenbank »%s« als Benutzer »%s« auf Host »%s« auf Port »%s«.\n" +#: command.c:820 describe.c:3873 +msgid "Database" +msgstr "Datenbank" + +#: command.c:824 +msgid "Client User" +msgstr "Client-Benutzer" + +#: command.c:833 command.c:848 +msgid "Host Address" +msgstr "Hostadresse" + +#: command.c:838 +msgid "Socket Directory" +msgstr "Socket-Verzeichnis" + +#: command.c:844 +msgid "Host" +msgstr "Host" + +#: command.c:854 +msgid "Server Port" +msgstr "Serverport" + +#: command.c:858 describe.c:246 describe.c:3614 describe.c:3954 +msgid "Options" +msgstr "Optionen" + +#: command.c:862 +msgid "Protocol Version" +msgstr "Protokollversion" + +#: command.c:866 +msgid "Password Used" +msgstr "Passwort verwendet" + +#: command.c:867 command.c:871 command.c:879 command.c:912 +msgid "false" +msgstr "falsch" + +#: command.c:867 command.c:871 command.c:879 command.c:912 +msgid "true" +msgstr "wahr" + +#: command.c:870 +#, fuzzy +#| msgid "GSSAPI authentication not supported" +msgid "GSSAPI Authenticated" +msgstr "Authentifizierung mit GSSAPI nicht unterstützt" + +#: command.c:874 +msgid "Backend PID" +msgstr "Backend-PID" -#: command.c:1069 command.c:1170 command.c:2675 +#: command.c:878 +msgid "TLS Connection" +msgstr "TLS-Verbindung" + +#: command.c:898 +msgid "TLS Library" +msgstr "TLS-Bibliothek" + +#: command.c:899 command.c:902 command.c:905 command.c:908 command.c:920 +#: command.c:924 command.c:4423 command.c:4424 +msgid "unknown" +msgstr "unbekannt" + +#: command.c:901 +msgid "TLS Protocol" +msgstr "TLS-Protokoll" + +#: command.c:904 +msgid "TLS Key Bits" +msgstr "TLS-Schlüssel-Bits" + +#: command.c:907 +msgid "TLS Cipher" +msgstr "TLS-Verschlüsselungsmethode" + +#: command.c:910 +msgid "TLS Compression" +msgstr "TLS-Komprimierung" + +#: command.c:914 +msgid "ALPN" +msgstr "ALPN" + +#: command.c:915 command.c:4426 +msgid "none" +msgstr "keine" + +#: command.c:1332 command.c:1433 command.c:3184 #, c-format msgid "no query buffer" msgstr "kein Anfragepuffer" -#: command.c:1102 command.c:5771 +#: command.c:1365 command.c:6307 #, c-format msgid "invalid line number: %s" msgstr "ungültige Zeilennummer: %s" -#: command.c:1248 +#: command.c:1511 msgid "No changes" msgstr "keine Änderungen" -#: command.c:1333 +#: command.c:1596 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: ungültiger Kodierungsname oder Umwandlungsprozedur nicht gefunden" -#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5877 -#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 -#: common.c:1228 common.c:1347 common.c:1385 common.c:1482 common.c:1548 -#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 -#: startup.c:304 +#: command.c:1632 command.c:2572 command.c:3981 command.c:4179 command.c:6413 +#: common.c:233 common.c:282 common.c:455 common.c:1178 common.c:1196 +#: common.c:1264 common.c:1376 common.c:1414 common.c:1705 common.c:1785 +#: copy.c:486 copy.c:731 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:309 #, c-format msgid "%s" msgstr "%s" -#: command.c:1375 +#: command.c:1639 msgid "There is no previous error." msgstr "Es gibt keinen vorangegangenen Fehler." -#: command.c:1488 +#: command.c:1742 +#, c-format +msgid "\\%s not allowed in pipeline mode" +msgstr "\\%s im Pipeline-Modus nicht erlaubt" + +#: command.c:1798 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: rechte Klammer fehlt" -#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 -#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 +#: command.c:1924 #, c-format -msgid "\\%s: missing required argument" -msgstr "\\%s: notwendiges Argument fehlt" +msgid "\\getresults: invalid number of requested results" +msgstr "" + +#: command.c:1949 +#, c-format +msgid "\\gexec not allowed in pipeline mode" +msgstr "\\gexec im Pipeline-Modus nicht erlaubt" -#: command.c:1822 +#: command.c:1975 +#, c-format +msgid "\\gset not allowed in pipeline mode" +msgstr "\\gset im Pipeline-Modus nicht erlaubt" + +#: command.c:2181 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: kann nicht nach \\else kommen" -#: command.c:1827 +#: command.c:2186 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: kein passendes \\if" -#: command.c:1891 +#: command.c:2250 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: kann nicht nach \\else kommen" -#: command.c:1896 +#: command.c:2255 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: kein passendes \\if" -#: command.c:1936 +#: command.c:2295 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: kein passendes \\if" -#: command.c:2092 +#: command.c:2473 msgid "Query buffer is empty." msgstr "Anfragepuffer ist leer." -#: command.c:2135 +#: command.c:2550 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Neues Passwort für Benutzer »%s« eingeben: " -#: command.c:2139 +#: command.c:2554 msgid "Enter it again: " msgstr "Geben Sie es noch einmal ein: " -#: command.c:2148 +#: command.c:2563 #, c-format msgid "Passwords didn't match." msgstr "Passwörter stimmten nicht überein." -#: command.c:2231 +#: command.c:2646 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: konnte Wert für Variable nicht lesen" -#: command.c:2333 +#: command.c:2748 msgid "Query buffer reset (cleared)." msgstr "Anfragepuffer wurde gelöscht." -#: command.c:2355 +#: command.c:2770 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "Befehlsgeschichte in Datei »%s« geschrieben.\n" -#: command.c:2442 +#: command.c:2800 +#, c-format +msgid "\\sendpipeline must be used after \\bind or \\bind_named" +msgstr "\\sendpipeline muss nach \\bind oder \\bind_named verwendet werden" + +#: command.c:2807 +#, c-format +msgid "\\sendpipeline not allowed outside of pipeline mode" +msgstr "\\sendpipeline ist außerhalb des Pipeline-Modus nicht erlaubt" + +#: command.c:2894 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: Name der Umgebungsvariable darf kein »=« enthalten" -#: command.c:2490 +#: command.c:2942 #, c-format msgid "function name is required" msgstr "Funktionsname wird benötigt" -#: command.c:2492 +#: command.c:2944 #, c-format msgid "view name is required" msgstr "Sichtname wird benötigt" -#: command.c:2614 +#: command.c:3123 msgid "Timing is on." msgstr "Zeitmessung ist an." -#: command.c:2616 +#: command.c:3125 msgid "Timing is off." msgstr "Zeitmessung ist aus." -#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 -#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 -#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 -#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 +#: command.c:3211 command.c:3249 command.c:4694 command.c:4697 command.c:4700 +#: command.c:4706 command.c:4708 command.c:4734 command.c:4744 command.c:4756 +#: command.c:4770 command.c:4797 command.c:4855 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:797 psqlscanslash.l:809 psqlscanslash.l:827 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2729 copy.c:388 +#: command.c:3238 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2801 command.c:2867 +#: command.c:3287 +#, c-format +msgid "\\watch not allowed in pipeline mode" +msgstr "\\watch im Pipeline-Modus nicht erlaubt" + +#: command.c:3319 command.c:3385 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: Intervallwert mehrmals angegeben" -#: command.c:2811 command.c:2877 +#: command.c:3329 command.c:3395 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: falscher Intervallwert »%s«" -#: command.c:2821 +#: command.c:3339 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: Wiederholungszahl mehrmals angegeben" -#: command.c:2831 +#: command.c:3349 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: falsche Wiederholungszahl »%s«" -#: command.c:2841 +#: command.c:3359 #, c-format msgid "\\watch: minimum row count specified more than once" msgstr "\\watch: Mindestzeilenzahl mehrmals angegeben" -#: command.c:2851 +#: command.c:3369 #, c-format msgid "\\watch: incorrect minimum row count \"%s\"" msgstr "\\watch: falsche Mindestzeilenzahl »%s«" -#: command.c:2858 +#: command.c:3376 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: unbekannter Parameter »%s«" -#: command.c:3255 startup.c:243 startup.c:293 +#: command.c:3782 startup.c:248 startup.c:298 msgid "Password: " msgstr "Passwort: " -#: command.c:3260 startup.c:290 +#: command.c:3787 startup.c:295 #, c-format msgid "Password for user %s: " msgstr "Passwort für Benutzer %s: " -#: command.c:3316 +#: command.c:3843 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "Geben Sie Benutzer, Host oder Port nicht separat an, wenn eine Verbindungsangabe verwendet wird" -#: command.c:3351 +#: command.c:3878 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "Es gibt keine Verbindung, von der die Parameter verwendet werden können" -#: command.c:3658 +#: command.c:4185 #, c-format msgid "Previous connection kept" msgstr "Vorherige Verbindung wurde behalten" -#: command.c:3664 +#: command.c:4191 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3720 +#: command.c:4247 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Sie sind jetzt verbunden mit der Datenbank »%s« als Benutzer »%s« auf Adresse »%s« auf Port »%s«.\n" -#: command.c:3723 +#: command.c:4250 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Sie sind jetzt verbunden mit der Datenbank »%s« als Benutzer »%s« via Socket in »%s« auf Port »%s«.\n" -#: command.c:3729 +#: command.c:4256 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Sie sind jetzt verbunden mit der Datenbank »%s« als Benutzer »%s« auf Host »%s« (Adresse »%s«) auf Port »%s«.\n" -#: command.c:3732 +#: command.c:4259 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Sie sind jetzt verbunden mit der Datenbank »%s« als Benutzer »%s« auf Host »%s« auf Port »%s«.\n" -#: command.c:3737 +#: command.c:4264 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Sie sind jetzt verbunden mit der Datenbank »%s« als Benutzer »%s«.\n" -#: command.c:3843 +#: command.c:4370 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, Server %s)\n" -#: command.c:3856 +#: command.c:4383 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -498,33 +607,25 @@ msgstr "" "WARNUNG: %s-Hauptversion %s, Server-Hauptversion %s.\n" " Einige Features von psql werden eventuell nicht funktionieren.\n" -#: command.c:3895 +#: command.c:4422 #, c-format msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" msgstr "SSL-Verbindung (Protokoll: %s, Verschlüsselungsmethode: %s, Komprimierung: %s, ALPN: %s)\n" -#: command.c:3896 command.c:3897 -msgid "unknown" -msgstr "unbekannt" - -#: command.c:3898 help.c:42 +#: command.c:4425 help.c:39 msgid "off" msgstr "aus" -#: command.c:3898 help.c:42 +#: command.c:4425 help.c:39 msgid "on" msgstr "an" -#: command.c:3899 -msgid "none" -msgstr "keine" - -#: command.c:3913 +#: command.c:4440 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "GSSAPI-verschlüsselte Verbindung\n" -#: command.c:3933 +#: command.c:4460 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -536,284 +637,284 @@ msgstr "" " richtig. Einzelheiten finden Sie auf der psql-Handbuchseite unter\n" " »Notes for Windows users«.\n" -#: command.c:4038 +#: command.c:4569 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "Umgebungsvariable PSQL_EDITOR_LINENUMBER_ARG muss gesetzt werden, um eine Zeilennummer angeben zu können" -#: command.c:4068 +#: command.c:4599 #, c-format msgid "could not start editor \"%s\"" msgstr "konnte Editor »%s« nicht starten" -#: command.c:4070 +#: command.c:4601 #, c-format msgid "could not start /bin/sh" msgstr "konnte /bin/sh nicht starten" -#: command.c:4120 +#: command.c:4651 #, c-format msgid "could not locate temporary directory: %s" msgstr "konnte temporäres Verzeichnis nicht finden: %s" -#: command.c:4147 +#: command.c:4678 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "konnte temporäre Datei »%s« nicht öffnen: %m" -#: command.c:4483 +#: command.c:5014 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: Abkürzung »%s« ist nicht eindeutig, passt auf »%s« und »%s«" -#: command.c:4503 +#: command.c:5034 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset: zulässige Formate sind aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4522 +#: command.c:5053 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: zulässige Linienstile sind ascii, old-ascii, unicode" -#: command.c:4537 +#: command.c:5068 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: zulässige Unicode-Rahmnenlinienstile sind single, double" -#: command.c:4552 +#: command.c:5083 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: zulässige Unicode-Spaltenlinienstile sind single, double" -#: command.c:4567 +#: command.c:5098 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: zulässige Unicode-Kopflinienstile sind single, double" -#: command.c:4619 +#: command.c:5150 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: zulässige Werte für xheader_width sind »%s« (Standard), »%s«, »%s« oder eine Zahl, die die genaue Breite angibt" -#: command.c:4636 +#: command.c:5167 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep muss ein einzelnes Ein-Byte-Zeichen sein" -#: command.c:4641 +#: command.c:5172 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldsep kann nicht doppeltes Anführungszeichen, Newline oder Carriage Return sein" -#: command.c:4779 command.c:4980 +#: command.c:5310 command.c:5511 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: unbekannte Option: %s" -#: command.c:4799 +#: command.c:5330 #, c-format msgid "Border style is %d.\n" msgstr "Rahmenstil ist %d.\n" -#: command.c:4805 +#: command.c:5336 #, c-format msgid "Target width is unset.\n" msgstr "Zielbreite ist nicht gesetzt.\n" -#: command.c:4807 +#: command.c:5338 #, c-format msgid "Target width is %d.\n" msgstr "Zielbreite ist %d.\n" -#: command.c:4814 +#: command.c:5345 #, c-format msgid "Expanded display is on.\n" msgstr "Erweiterte Anzeige ist an.\n" -#: command.c:4816 +#: command.c:5347 #, c-format msgid "Expanded display is used automatically.\n" msgstr "Erweiterte Anzeige wird automatisch verwendet.\n" -#: command.c:4818 +#: command.c:5349 #, c-format msgid "Expanded display is off.\n" msgstr "Erweiterte Anzeige ist aus.\n" -#: command.c:4825 command.c:4827 command.c:4829 +#: command.c:5356 command.c:5358 command.c:5360 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "Erweiterte Kopfzeilenbreite ist »%s«.\n" -#: command.c:4831 +#: command.c:5362 #, c-format msgid "Expanded header width is %d.\n" msgstr "Erweiterte Kopfzeilenbreite ist %d.\n" -#: command.c:4837 +#: command.c:5368 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "Feldtrennzeichen für CSV ist »%s«.\n" -#: command.c:4845 command.c:4853 +#: command.c:5376 command.c:5384 #, c-format msgid "Field separator is zero byte.\n" msgstr "Feldtrennzeichen ist ein Null-Byte.\n" -#: command.c:4847 +#: command.c:5378 #, c-format msgid "Field separator is \"%s\".\n" msgstr "Feldtrennzeichen ist »%s«.\n" -#: command.c:4860 +#: command.c:5391 #, c-format msgid "Default footer is on.\n" msgstr "Standardfußzeile ist an.\n" -#: command.c:4862 +#: command.c:5393 #, c-format msgid "Default footer is off.\n" msgstr "Standardfußzeile ist aus.\n" -#: command.c:4868 +#: command.c:5399 #, c-format msgid "Output format is %s.\n" msgstr "Ausgabeformat ist »%s«.\n" -#: command.c:4874 +#: command.c:5405 #, c-format msgid "Line style is %s.\n" msgstr "Linienstil ist %s.\n" -#: command.c:4881 +#: command.c:5412 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null-Anzeige ist »%s«.\n" -#: command.c:4889 +#: command.c:5420 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "Lokalisiertes Format für numerische Daten ist an.\n" -#: command.c:4891 +#: command.c:5422 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "Lokalisiertes Format für numerische Daten ist aus.\n" -#: command.c:4898 +#: command.c:5429 #, c-format msgid "Pager is used for long output.\n" msgstr "Pager wird für lange Ausgaben verwendet.\n" -#: command.c:4900 +#: command.c:5431 #, c-format msgid "Pager is always used.\n" msgstr "Pager wird immer verwendet.\n" -#: command.c:4902 +#: command.c:5433 #, c-format msgid "Pager usage is off.\n" msgstr "Pager-Verwendung ist aus.\n" -#: command.c:4908 +#: command.c:5439 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "Pager wird nicht für weniger als %d Zeile verwendet werden.\n" msgstr[1] "Pager wird nicht für weniger als %d Zeilen verwendet werden.\n" -#: command.c:4918 command.c:4928 +#: command.c:5449 command.c:5459 #, c-format msgid "Record separator is zero byte.\n" msgstr "Satztrennzeichen ist ein Null-Byte.\n" -#: command.c:4920 +#: command.c:5451 #, c-format msgid "Record separator is .\n" msgstr "Satztrennzeichen ist .\n" -#: command.c:4922 +#: command.c:5453 #, c-format msgid "Record separator is \"%s\".\n" msgstr "Satztrennzeichen ist »%s«.\n" -#: command.c:4935 +#: command.c:5466 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Tabellenattribute sind »%s«.\n" -#: command.c:4938 +#: command.c:5469 #, c-format msgid "Table attributes unset.\n" msgstr "Tabellenattribute sind nicht gesetzt.\n" -#: command.c:4945 +#: command.c:5476 #, c-format msgid "Title is \"%s\".\n" msgstr "Titel ist »%s«.\n" -#: command.c:4947 +#: command.c:5478 #, c-format msgid "Title is unset.\n" msgstr "Titel ist nicht gesetzt.\n" -#: command.c:4954 +#: command.c:5485 #, c-format msgid "Tuples only is on.\n" msgstr "Nur Datenzeilen ist an.\n" -#: command.c:4956 +#: command.c:5487 #, c-format msgid "Tuples only is off.\n" msgstr "Nur Datenzeilen ist aus.\n" -#: command.c:4962 +#: command.c:5493 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Unicode-Rahmenlinienstil ist »%s«.\n" -#: command.c:4968 +#: command.c:5499 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Unicode-Spaltenlinienstil ist »%s«.\n" -#: command.c:4974 +#: command.c:5505 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Unicode-Kopflinienstil ist »%s«.\n" -#: command.c:5223 +#: command.c:5754 #, c-format msgid "\\!: failed" msgstr "\\!: fehlgeschlagen" -#: command.c:5257 +#: command.c:5792 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch kann nicht mit einer leeren Anfrage verwendet werden" -#: command.c:5289 +#: command.c:5824 #, c-format msgid "could not set timer: %m" msgstr "konnte Timer nicht setzen: %m" -#: command.c:5358 +#: command.c:5893 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (alle %gs)\n" -#: command.c:5361 +#: command.c:5896 #, c-format msgid "%s (every %gs)\n" msgstr "%s (alle %gs)\n" -#: command.c:5424 +#: command.c:5960 #, c-format msgid "could not wait for signals: %m" msgstr "konnte nicht auf Signale warten: %m" -#: command.c:5480 command.c:5487 common.c:632 common.c:639 common.c:1123 +#: command.c:6016 command.c:6023 common.c:667 common.c:674 common.c:1159 #, c-format msgid "" "/******** QUERY *********/\n" @@ -826,107 +927,107 @@ msgstr "" "/************************/\n" "\n" -#: command.c:5666 +#: command.c:6202 #, c-format msgid "\"%s.%s\" is not a view" msgstr "»%s.%s« ist keine Sicht" -#: command.c:5682 +#: command.c:6218 #, c-format msgid "could not parse reloptions array" msgstr "konnte reloptions-Array nicht interpretieren" -#: common.c:206 +#: common.c:218 #, c-format msgid "cannot escape without active connection" msgstr "Escape kann nicht ohne aktive Verbindung ausgeführt werden" -#: common.c:247 +#: common.c:259 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«" -#: common.c:351 +#: common.c:363 #, c-format msgid "connection to server was lost" msgstr "Verbindung zum Server wurde verloren" -#: common.c:355 +#: common.c:367 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "Die Verbindung zum Server wurde verloren. Versuche Reset: " -#: common.c:360 +#: common.c:373 #, c-format msgid "Failed.\n" msgstr "Fehlgeschlagen.\n" -#: common.c:377 +#: common.c:390 #, c-format msgid "Succeeded.\n" msgstr "Erfolgreich.\n" -#: common.c:430 common.c:1061 +#: common.c:445 common.c:1097 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "unerwarteter PQresultStatus: %d" -#: common.c:571 +#: common.c:606 #, c-format msgid "Time: %.3f ms\n" msgstr "Zeit: %.3f ms\n" -#: common.c:586 +#: common.c:621 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Zeit: %.3f ms (%02d:%06.3f)\n" -#: common.c:595 +#: common.c:630 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Zeit: %.3f ms (%02d:%02d:%06.3f)\n" -#: common.c:602 +#: common.c:637 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Zeit: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:626 common.c:683 common.c:1094 describe.c:6192 +#: common.c:661 common.c:718 common.c:1130 describe.c:6370 #, c-format msgid "You are currently not connected to a database." msgstr "Sie sind gegenwärtig nicht mit einer Datenbank verbunden." -#: common.c:714 +#: common.c:749 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "Asynchrone Benachrichtigung »%s« mit Daten »%s« vom Serverprozess mit PID %d empfangen.\n" -#: common.c:717 +#: common.c:752 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "Asynchrone Benachrichtigung »%s« vom Serverprozess mit PID %d empfangen.\n" -#: common.c:748 +#: common.c:783 #, c-format msgid "could not print result table: %m" msgstr "konnte Ergebnistabelle nicht ausgeben: %m" -#: common.c:768 +#: common.c:803 #, c-format msgid "no rows returned for \\gset" msgstr "keine Zeilen für \\gset zurückgegeben" -#: common.c:773 +#: common.c:808 #, c-format msgid "more than one row returned for \\gset" msgstr "mehr als eine Zeile für \\gset zurückgegeben" -#: common.c:791 +#: common.c:826 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "Versuch von \\gset in besonders behandelte Variable »%s« ignoriert" -#: common.c:1103 +#: common.c:1139 #, c-format msgid "" "/**(Single step mode: verify command)******************************************/\n" @@ -937,37 +1038,47 @@ msgstr "" "%s\n" "/**(Drücken Sie die Eingabetaste um fortzufahren oder »x« um abzubrechen)******/\n" -#: common.c:1180 +#: common.c:1216 #, c-format msgid "STATEMENT: %s" msgstr "ANWEISUNG: %s" -#: common.c:1216 +#: common.c:1252 #, c-format msgid "unexpected transaction status (%d)" msgstr "unerwarteter Transaktionsstatus (%d)" -#: common.c:1369 describe.c:2025 +#: common.c:1398 describe.c:2063 msgid "Column" msgstr "Spalte" -#: common.c:1370 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 -#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 -#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 -#: describe.c:5829 +#: common.c:1399 describe.c:176 describe.c:362 describe.c:380 describe.c:1081 +#: describe.c:1243 describe.c:1773 describe.c:1797 describe.c:2064 +#: describe.c:4057 describe.c:4321 describe.c:4568 describe.c:4728 +#: describe.c:6004 msgid "Type" msgstr "Typ" -#: common.c:1419 +#: common.c:1448 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "Der Befehl hat kein Ergebnis oder das Ergebnis hat keine Spalten.\n" -#: common.c:1511 +#: common.c:1670 +#, c-format +msgid "No pending results to get" +msgstr "" + +#: common.c:1748 #, c-format msgid "fetching results in chunked mode failed" msgstr "Empfangen der Ergebnisse im Chunked-Modus fehlgeschlagen" +#: common.c:1797 +#, c-format +msgid "Pipeline aborted, command did not run" +msgstr "" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -1020,11 +1131,11 @@ msgstr "" "Geben Sie die zu kopierenden Daten ein, gefolgt von einem Zeilenende.\n" "Beenden Sie mit einem Backslash und einem Punkt alleine auf einer Zeile, oder einem EOF-Signal." -#: copy.c:684 +#: copy.c:693 msgid "aborted because of read failure" msgstr "abgebrochen wegen Lesenfehlers" -#: copy.c:718 +#: copy.c:727 msgid "trying to exit copy mode" msgstr "versuche, den COPY-Modus zu verlassen" @@ -1073,1162 +1184,1256 @@ msgstr "\\crosstabview: zweideutiger Spaltenname: »%s«" msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: Spaltenname nicht gefunden: »%s«" -#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 -#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 -#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 -#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 -#: describe.c:5542 describe.c:5941 describe.c:6018 +#: describe.c:94 describe.c:342 describe.c:649 describe.c:826 describe.c:1073 +#: describe.c:1230 describe.c:1306 describe.c:4046 describe.c:4308 +#: describe.c:4566 describe.c:4647 describe.c:4879 describe.c:5091 +#: describe.c:5340 describe.c:5581 describe.c:5650 describe.c:5661 +#: describe.c:5717 describe.c:6116 describe.c:6196 msgid "Schema" msgstr "Schema" -#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 -#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 -#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 -#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 -#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 -#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 -#: describe.c:6016 describe.c:6243 describe.c:6551 +#: describe.c:95 describe.c:173 describe.c:234 describe.c:343 describe.c:650 +#: describe.c:827 describe.c:958 describe.c:1074 describe.c:1307 +#: describe.c:4047 describe.c:4309 describe.c:4483 describe.c:4567 +#: describe.c:4648 describe.c:4809 describe.c:4880 describe.c:5092 +#: describe.c:5213 describe.c:5341 describe.c:5582 describe.c:5651 +#: describe.c:5662 describe.c:5718 describe.c:5915 describe.c:5985 +#: describe.c:6193 describe.c:6421 describe.c:6767 msgid "Name" msgstr "Name" -#: describe.c:89 describe.c:348 describe.c:366 +#: describe.c:96 describe.c:355 describe.c:373 msgid "Result data type" msgstr "Ergebnisdatentyp" -#: describe.c:90 describe.c:349 describe.c:367 +#: describe.c:97 describe.c:356 describe.c:374 msgid "Argument data types" msgstr "Argumentdatentypen" -#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 -#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 -#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 -#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 -#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 -#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 -#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 -#: describe.c:6019 describe.c:7078 +#: describe.c:105 describe.c:112 describe.c:184 describe.c:248 describe.c:432 +#: describe.c:681 describe.c:846 describe.c:1010 describe.c:1309 +#: describe.c:2084 describe.c:3773 describe.c:4105 describe.c:4362 +#: describe.c:4507 describe.c:4580 describe.c:4657 describe.c:4822 +#: describe.c:5004 describe.c:5150 describe.c:5222 describe.c:5342 +#: describe.c:5492 describe.c:5533 describe.c:5598 describe.c:5654 +#: describe.c:5663 describe.c:5719 describe.c:5933 describe.c:6007 +#: describe.c:6130 describe.c:6197 describe.c:7303 msgid "Description" msgstr "Beschreibung" -#: describe.c:127 +#: describe.c:134 msgid "List of aggregate functions" msgstr "Liste der Aggregatfunktionen" -#: describe.c:152 +#: describe.c:159 #, c-format msgid "The server (version %s) does not support access methods." msgstr "Der Server (Version %s) unterstützt keine Zugriffsmethoden." -#: describe.c:167 +#: describe.c:174 msgid "Index" msgstr "Index" -#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 +#: describe.c:175 describe.c:4065 describe.c:4334 describe.c:6117 msgid "Table" msgstr "Tabelle" -#: describe.c:176 describe.c:5742 +#: describe.c:183 describe.c:5917 msgid "Handler" msgstr "Handler" -#: describe.c:199 +#: describe.c:206 msgid "List of access methods" msgstr "Liste der Zugriffsmethoden" -#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 -#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 -#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 -#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 -#: describe.c:7066 +#: describe.c:235 describe.c:415 describe.c:674 describe.c:959 describe.c:1229 +#: describe.c:4058 describe.c:4310 describe.c:4484 describe.c:4811 +#: describe.c:5214 describe.c:5916 describe.c:5986 describe.c:6422 +#: describe.c:6643 describe.c:6768 describe.c:6938 describe.c:7023 +#: describe.c:7291 msgid "Owner" msgstr "Eigentümer" -#: describe.c:229 +#: describe.c:236 msgid "Location" msgstr "Pfad" -#: describe.c:239 describe.c:3517 describe.c:3857 -msgid "Options" -msgstr "Optionen" - -#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 +#: describe.c:247 describe.c:672 describe.c:1008 describe.c:4104 msgid "Size" msgstr "Größe" -#: describe.c:263 +#: describe.c:270 msgid "List of tablespaces" msgstr "Liste der Tablespaces" -#: describe.c:308 +#: describe.c:315 #, c-format -msgid "\\df only takes [anptwS+] as options" -msgstr "\\df akzeptiert nur [anptwS+] als Optionen" +msgid "\\df only takes [anptwSx+] as options" +msgstr "\\df akzeptiert nur [anptwSx+] als Optionen" -#: describe.c:316 +#: describe.c:323 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df akzeptiert die Option »%c« nicht mit Serverversion %s" #. translator: "agg" is short for "aggregate" -#: describe.c:351 describe.c:369 +#: describe.c:358 describe.c:376 msgid "agg" msgstr "Agg" -#: describe.c:352 describe.c:370 +#: describe.c:359 describe.c:377 msgid "window" msgstr "Fenster" -#: describe.c:353 +#: describe.c:360 msgid "proc" msgstr "Proz" -#: describe.c:354 describe.c:372 +#: describe.c:361 describe.c:379 msgid "func" msgstr "Funk" -#: describe.c:371 describe.c:1397 +#: describe.c:378 describe.c:1439 msgid "trigger" msgstr "Trigger" -#: describe.c:383 +#: describe.c:393 msgid "immutable" msgstr "unveränderlich" -#: describe.c:384 +#: describe.c:394 msgid "stable" msgstr "stabil" -#: describe.c:385 +#: describe.c:395 msgid "volatile" msgstr "volatil" -#: describe.c:386 +#: describe.c:396 msgid "Volatility" msgstr "Volatilität" -#: describe.c:394 +#: describe.c:407 msgid "restricted" msgstr "beschränkt" -#: describe.c:395 +#: describe.c:408 msgid "safe" msgstr "sicher" -#: describe.c:396 +#: describe.c:409 msgid "unsafe" msgstr "unsicher" -#: describe.c:397 +#: describe.c:410 msgid "Parallel" msgstr "Parallel" -#: describe.c:402 +#: describe.c:416 msgid "definer" msgstr "definer" -#: describe.c:403 +#: describe.c:417 msgid "invoker" msgstr "invoker" -#: describe.c:404 +#: describe.c:418 msgid "Security" msgstr "Sicherheit" -#: describe.c:409 +#: describe.c:419 describe.c:837 describe.c:1778 describe.c:1802 +#: describe.c:1931 describe.c:4651 describe.c:4992 describe.c:5001 +#: describe.c:5139 describe.c:5144 describe.c:6926 describe.c:7125 +msgid "yes" +msgstr "ja" + +#: describe.c:420 describe.c:838 describe.c:1779 describe.c:1803 +#: describe.c:1932 describe.c:4651 describe.c:4989 describe.c:5002 +#: describe.c:5139 describe.c:6927 describe.c:7126 +msgid "no" +msgstr "nein" + +#: describe.c:421 describe.c:839 describe.c:5003 describe.c:7127 +msgid "Leakproof?" +msgstr "" + +#: describe.c:426 msgid "Language" msgstr "Sprache" -#: describe.c:412 describe.c:648 +#: describe.c:429 describe.c:671 msgid "Internal name" msgstr "Interner Name" -#: describe.c:585 +#: describe.c:608 msgid "List of functions" msgstr "Liste der Funktionen" -#: describe.c:650 +#: describe.c:673 msgid "Elements" msgstr "Elemente" -#: describe.c:701 +#: describe.c:724 msgid "List of data types" msgstr "Liste der Datentypen" -#: describe.c:804 +#: describe.c:828 msgid "Left arg type" msgstr "Linker Typ" -#: describe.c:805 +#: describe.c:829 msgid "Right arg type" msgstr "Rechter Typ" -#: describe.c:806 +#: describe.c:830 msgid "Result type" msgstr "Ergebnistyp" -#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 -#: describe.c:6996 describe.c:7000 +#: describe.c:836 describe.c:4817 describe.c:4981 describe.c:5491 +#: describe.c:7221 describe.c:7225 msgid "Function" msgstr "Funktion" -#: describe.c:891 +#: describe.c:923 msgid "List of operators" msgstr "Liste der Operatoren" -#: describe.c:926 +#: describe.c:960 msgid "Encoding" msgstr "Kodierung" -#: describe.c:930 describe.c:934 +#: describe.c:968 describe.c:972 msgid "Locale Provider" msgstr "Locale-Provider" -#: describe.c:938 describe.c:4936 +#: describe.c:976 describe.c:5111 msgid "Collate" msgstr "Sortierfolge" -#: describe.c:939 describe.c:4937 +#: describe.c:977 describe.c:5112 msgid "Ctype" msgstr "Zeichentyp" -#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 -#: describe.c:4950 +#: describe.c:981 describe.c:985 describe.c:989 describe.c:5117 describe.c:5121 +#: describe.c:5125 msgid "Locale" msgstr "Locale" -#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 +#: describe.c:993 describe.c:997 describe.c:5130 describe.c:5134 msgid "ICU Rules" msgstr "ICU-Regeln" -#: describe.c:971 +#: describe.c:1009 msgid "Tablespace" msgstr "Tablespace" -#: describe.c:996 +#: describe.c:1034 msgid "List of databases" msgstr "Liste der Datenbanken" -#: describe.c:1037 describe.c:1192 describe.c:3947 +#: describe.c:1075 describe.c:1232 describe.c:4048 msgid "table" msgstr "Tabelle" -#: describe.c:1038 describe.c:3948 +#: describe.c:1076 describe.c:4049 msgid "view" msgstr "Sicht" -#: describe.c:1039 describe.c:3949 +#: describe.c:1077 describe.c:4050 msgid "materialized view" msgstr "materialisierte Sicht" -#: describe.c:1040 describe.c:1194 describe.c:3951 +#: describe.c:1078 describe.c:1234 describe.c:4052 msgid "sequence" msgstr "Sequenz" -#: describe.c:1041 describe.c:3953 +#: describe.c:1079 describe.c:4054 msgid "foreign table" msgstr "Fremdtabelle" -#: describe.c:1042 describe.c:3954 describe.c:4165 +#: describe.c:1080 describe.c:4055 describe.c:4319 msgid "partitioned table" msgstr "partitionierte Tabelle" -#: describe.c:1058 +#: describe.c:1096 msgid "Column privileges" msgstr "Spaltenprivilegien" -#: describe.c:1089 describe.c:1123 +#: describe.c:1127 describe.c:1161 msgid "Policies" msgstr "Policys" -#: describe.c:1151 describe.c:4570 describe.c:6667 +#: describe.c:1189 describe.c:4734 describe.c:6883 msgid "Access privileges" msgstr "Zugriffsprivilegien" -#: describe.c:1196 +#: describe.c:1236 msgid "function" msgstr "Funktion" -#: describe.c:1198 +#: describe.c:1238 msgid "type" msgstr "Typ" -#: describe.c:1200 +#: describe.c:1240 msgid "schema" msgstr "Schema" -#: describe.c:1222 +#: describe.c:1242 +msgid "large object" +msgstr "Large Object" + +#: describe.c:1264 msgid "Default access privileges" msgstr "Vorgegebene Zugriffsprivilegien" -#: describe.c:1266 +#: describe.c:1308 msgid "Object" msgstr "Objekt" -#: describe.c:1280 +#: describe.c:1322 msgid "table constraint" msgstr "Tabellen-Constraint" -#: describe.c:1304 +#: describe.c:1346 msgid "domain constraint" msgstr "Domänen-Constraint" -#: describe.c:1328 +#: describe.c:1370 msgid "operator class" msgstr "Operatorklasse" -#: describe.c:1352 +#: describe.c:1394 msgid "operator family" msgstr "Operatorfamilie" -#: describe.c:1375 +#: describe.c:1417 msgid "rule" msgstr "Rule" -#: describe.c:1420 +#: describe.c:1462 msgid "Object descriptions" msgstr "Objektbeschreibungen" -#: describe.c:1485 describe.c:4072 +#: describe.c:1527 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "Keine Relation namens »%s« gefunden" -#: describe.c:1488 describe.c:4075 +#: describe.c:1530 describe.c:4206 #, c-format msgid "Did not find any relations." msgstr "Keine Relationen gefunden" -#: describe.c:1684 +#: describe.c:1726 #, c-format msgid "Did not find any relation with OID %s." msgstr "Keine Relation mit OID %s gefunden" -#: describe.c:1732 describe.c:1756 +#: describe.c:1774 describe.c:1798 msgid "Start" msgstr "Start" -#: describe.c:1733 describe.c:1757 +#: describe.c:1775 describe.c:1799 msgid "Minimum" msgstr "Minimum" -#: describe.c:1734 describe.c:1758 +#: describe.c:1776 describe.c:1800 msgid "Maximum" msgstr "Maximum" -#: describe.c:1735 describe.c:1759 +#: describe.c:1777 describe.c:1801 msgid "Increment" msgstr "Inkrement" -#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 -#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 -msgid "yes" -msgstr "ja" - -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 -#: describe.c:4825 describe.c:4964 describe.c:6711 -msgid "no" -msgstr "nein" - -#: describe.c:1738 describe.c:1762 +#: describe.c:1780 describe.c:1804 msgid "Cycles?" msgstr "Zyklisch?" -#: describe.c:1739 describe.c:1763 +#: describe.c:1781 describe.c:1805 msgid "Cache" msgstr "Cache" -#: describe.c:1804 +#: describe.c:1846 #, c-format msgid "Owned by: %s" msgstr "Eigentümer: %s" -#: describe.c:1808 +#: describe.c:1850 #, c-format msgid "Sequence for identity column: %s" msgstr "Sequenz für Identitätsspalte: %s" -#: describe.c:1816 +#: describe.c:1858 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Ungeloggte Sequenz »%s.%s«" -#: describe.c:1819 +#: describe.c:1861 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Sequenz »%s.%s«" -#: describe.c:1962 +#: describe.c:2004 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Ungeloggte Tabelle »%s.%s«" -#: describe.c:1965 +#: describe.c:2007 #, c-format msgid "Table \"%s.%s\"" msgstr "Tabelle »%s.%s«" -#: describe.c:1969 +#: describe.c:2011 #, c-format msgid "View \"%s.%s\"" msgstr "Sicht »%s.%s«" -#: describe.c:1974 -#, c-format -msgid "Unlogged materialized view \"%s.%s\"" -msgstr "Ungeloggte materialisierte Sicht »%s.%s«" - -#: describe.c:1977 +#: describe.c:2015 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Materialisierte Sicht »%s.%s«" -#: describe.c:1982 +#: describe.c:2020 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Ungeloggter Index »%s.%s«" -#: describe.c:1985 +#: describe.c:2023 #, c-format msgid "Index \"%s.%s\"" msgstr "Index »%s.%s«" -#: describe.c:1990 +#: describe.c:2028 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Ungeloggter partitionierter Index »%s.%s«" -#: describe.c:1993 +#: describe.c:2031 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Partitionierter Index »%s.%s«" -#: describe.c:1997 +#: describe.c:2035 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "TOAST-Tabelle »%s.%s«" -#: describe.c:2001 +#: describe.c:2039 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Zusammengesetzter Typ »%s.%s«" -#: describe.c:2005 +#: describe.c:2043 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Fremdtabelle »%s.%s«" -#: describe.c:2010 +#: describe.c:2048 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Ungeloggte partitionierte Tabelle »%s.%s«" -#: describe.c:2013 +#: describe.c:2051 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Partitionierte Tabelle »%s.%s«" -#: describe.c:2029 describe.c:4405 +#: describe.c:2067 describe.c:4569 msgid "Collation" msgstr "Sortierfolge" -#: describe.c:2030 describe.c:4406 +#: describe.c:2068 describe.c:4570 msgid "Nullable" msgstr "NULL erlaubt?" -#: describe.c:2031 describe.c:4407 +#: describe.c:2069 describe.c:4571 msgid "Default" msgstr "Vorgabewert" -#: describe.c:2034 +#: describe.c:2072 msgid "Key?" msgstr "Schlüssel?" -#: describe.c:2036 describe.c:4723 describe.c:4734 +#: describe.c:2074 describe.c:4887 describe.c:4898 msgid "Definition" msgstr "Definition" -#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 -#: describe.c:5954 +#: describe.c:2076 describe.c:5932 describe.c:6006 describe.c:6071 +#: describe.c:6129 msgid "FDW options" msgstr "FDW-Optionen" -#: describe.c:2040 +#: describe.c:2078 msgid "Storage" msgstr "Speicherung" -#: describe.c:2042 +#: describe.c:2080 msgid "Compression" msgstr "Kompression" -#: describe.c:2044 +#: describe.c:2082 msgid "Stats target" msgstr "Statistikziel" -#: describe.c:2180 +#: describe.c:2224 #, c-format msgid "Partition of: %s %s%s" msgstr "Partition von: %s %s%s" -#: describe.c:2193 +#: describe.c:2237 msgid "No partition constraint" msgstr "Kein Partitions-Constraint" -#: describe.c:2195 +#: describe.c:2239 #, c-format msgid "Partition constraint: %s" msgstr "Partitions-Constraint: %s" -#: describe.c:2219 +#: describe.c:2263 #, c-format msgid "Partition key: %s" msgstr "Partitionsschlüssel: %s" -#: describe.c:2245 +#: describe.c:2289 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Gehört zu Tabelle: »%s.%s«" -#: describe.c:2314 +#: describe.c:2362 msgid "primary key, " msgstr "Primärschlüssel, " -#: describe.c:2317 +#: describe.c:2365 msgid "unique" msgstr "unique" -#: describe.c:2319 +#: describe.c:2367 msgid " nulls not distinct" msgstr " nulls not distinct" -#: describe.c:2320 +#: describe.c:2368 msgid ", " msgstr ", " -#: describe.c:2327 +#: describe.c:2375 #, c-format msgid "for table \"%s.%s\"" msgstr "für Tabelle »%s.%s«" -#: describe.c:2331 +#: describe.c:2379 #, c-format msgid ", predicate (%s)" msgstr ", Prädikat (%s)" -#: describe.c:2334 +#: describe.c:2382 msgid ", clustered" msgstr ", geclustert" -#: describe.c:2337 +#: describe.c:2385 msgid ", invalid" msgstr ", ungültig" -#: describe.c:2340 +#: describe.c:2388 msgid ", deferrable" msgstr ", DEFERRABLE" -#: describe.c:2343 +#: describe.c:2391 msgid ", initially deferred" msgstr ", INITIALLY DEFERRED" -#: describe.c:2346 +#: describe.c:2394 msgid ", replica identity" msgstr ", Replika-Identität" -#: describe.c:2400 +#: describe.c:2455 msgid "Indexes:" msgstr "Indexe:" -#: describe.c:2483 +#: describe.c:2543 msgid "Check constraints:" msgstr "Check-Constraints:" -#: describe.c:2551 +#: describe.c:2604 msgid "Foreign-key constraints:" msgstr "Fremdschlüssel-Constraints:" -#: describe.c:2614 +#: describe.c:2663 msgid "Referenced by:" msgstr "Fremdschlüsselverweise von:" -#: describe.c:2664 +#: describe.c:2712 msgid "Policies:" msgstr "Policys:" -#: describe.c:2667 +#: describe.c:2715 msgid "Policies (forced row security enabled):" msgstr "Policys (Sicherheit auf Zeilenebene erzwungen):" -#: describe.c:2670 +#: describe.c:2718 msgid "Policies (row security enabled): (none)" msgstr "Policys (Sicherheit auf Zeilenebene eingeschaltet): (keine)" -#: describe.c:2673 +#: describe.c:2721 msgid "Policies (forced row security enabled): (none)" msgstr "Policys (Sicherheit auf Zeilenebene erzwungen): (keine)" -#: describe.c:2676 +#: describe.c:2724 msgid "Policies (row security disabled):" msgstr "Policys (Sicherheit auf Zeilenebene ausgeschaltet):" -#: describe.c:2736 describe.c:2841 +#: describe.c:2784 describe.c:2889 msgid "Statistics objects:" msgstr "Statistikobjekte:" -#: describe.c:2943 describe.c:3096 +#: describe.c:2991 describe.c:3191 msgid "Rules:" msgstr "Regeln:" -#: describe.c:2946 +#: describe.c:2994 msgid "Disabled rules:" msgstr "Abgeschaltete Regeln:" -#: describe.c:2949 +#: describe.c:2997 msgid "Rules firing always:" msgstr "Regeln, die immer aktiv werden:" -#: describe.c:2952 +#: describe.c:3000 msgid "Rules firing on replica only:" msgstr "Regeln, die nur im Replikat aktiv werden:" -#: describe.c:3031 describe.c:5100 +#: describe.c:3079 describe.c:5275 msgid "Publications:" msgstr "Publikationen:" -#: describe.c:3079 +#: describe.c:3126 +msgid "Not-null constraints:" +msgstr "Not-Null-Constraints:" + +#: describe.c:3140 +#, fuzzy +#| msgid "No inheritance" +msgid " (local, inherited)" +msgstr "keine Vererbung" + +#: describe.c:3141 +#, fuzzy +#| msgid "No inheritance" +msgid " (inherited)" +msgstr "keine Vererbung" + +#: describe.c:3174 msgid "View definition:" msgstr "Sichtdefinition:" -#: describe.c:3242 +#: describe.c:3337 msgid "Triggers:" msgstr "Trigger:" -#: describe.c:3245 +#: describe.c:3340 msgid "Disabled user triggers:" msgstr "Abgeschaltete Benutzer-Trigger:" -#: describe.c:3248 +#: describe.c:3343 msgid "Disabled internal triggers:" msgstr "Abgeschaltete interne Trigger:" -#: describe.c:3251 +#: describe.c:3346 msgid "Triggers firing always:" msgstr "Trigger, die immer aktiv werden:" -#: describe.c:3254 +#: describe.c:3349 msgid "Triggers firing on replica only:" msgstr "Trigger, die nur im Replikat aktiv werden:" -#: describe.c:3325 +#: describe.c:3420 #, c-format msgid "Server: %s" msgstr "Server: %s" -#: describe.c:3333 +#: describe.c:3428 #, c-format msgid "FDW options: (%s)" msgstr "FDW-Optionen: (%s)" -#: describe.c:3354 +#: describe.c:3449 msgid "Inherits" msgstr "Erbt von" -#: describe.c:3419 +#: describe.c:3514 #, c-format msgid "Number of partitions: %d" msgstr "Anzahl Partitionen: %d" -#: describe.c:3428 +#: describe.c:3523 #, c-format msgid "Number of partitions: %d (Use \\d+ to list them.)" msgstr "Anzahl Partitionen: %d (Mit \\d+ alle anzeigen.)" -#: describe.c:3430 +#: describe.c:3525 #, c-format msgid "Number of child tables: %d (Use \\d+ to list them.)" msgstr "Anzahl Kindtabellen: %d (Mit \\d+ alle anzeigen.)" -#: describe.c:3437 +#: describe.c:3532 msgid "Child tables" msgstr "Kindtabellen" -#: describe.c:3437 +#: describe.c:3532 msgid "Partitions" msgstr "Partitionen" -#: describe.c:3470 +#: describe.c:3565 #, c-format msgid "Typed table of type: %s" msgstr "Getypte Tabelle vom Typ: %s" -#: describe.c:3486 +#: describe.c:3583 msgid "Replica Identity" msgstr "Replika-Identität" -#: describe.c:3499 +#: describe.c:3596 msgid "Has OIDs: yes" msgstr "Hat OIDs: ja" -#: describe.c:3508 +#: describe.c:3605 #, c-format msgid "Access method: %s" msgstr "Zugriffsmethode: %s" -#: describe.c:3585 +#: describe.c:3682 #, c-format msgid "Tablespace: \"%s\"" msgstr "Tablespace: »%s«" #. translator: before this string there's an index description like #. '"foo_pkey" PRIMARY KEY, btree (a)' -#: describe.c:3597 +#: describe.c:3694 #, c-format msgid ", tablespace \"%s\"" msgstr ", Tablespace »%s«" -#: describe.c:3670 +#: describe.c:3767 msgid "List of roles" msgstr "Liste der Rollen" -#: describe.c:3672 describe.c:3840 +#: describe.c:3769 describe.c:3937 msgid "Role name" msgstr "Rollenname" -#: describe.c:3673 +#: describe.c:3770 msgid "Attributes" msgstr "Attribute" -#: describe.c:3684 +#: describe.c:3781 msgid "Superuser" msgstr "Superuser" -#: describe.c:3687 +#: describe.c:3784 msgid "No inheritance" msgstr "keine Vererbung" -#: describe.c:3690 +#: describe.c:3787 msgid "Create role" msgstr "Rolle erzeugen" -#: describe.c:3693 +#: describe.c:3790 msgid "Create DB" msgstr "DB erzeugen" -#: describe.c:3696 +#: describe.c:3793 msgid "Cannot login" msgstr "kann nicht einloggen" -#: describe.c:3699 +#: describe.c:3796 msgid "Replication" msgstr "Replikation" -#: describe.c:3703 +#: describe.c:3800 msgid "Bypass RLS" msgstr "Bypass RLS" -#: describe.c:3712 +#: describe.c:3809 msgid "No connections" msgstr "keine Verbindungen" -#: describe.c:3714 +#: describe.c:3811 #, c-format msgid "%d connection" msgid_plural "%d connections" msgstr[0] "%d Verbindung" msgstr[1] "%d Verbindungen" -#: describe.c:3724 +#: describe.c:3821 msgid "Password valid until " msgstr "Passwort gültig bis " -#: describe.c:3775 +#: describe.c:3872 msgid "Role" msgstr "Rolle" -#: describe.c:3776 -msgid "Database" -msgstr "Datenbank" - -#: describe.c:3777 +#: describe.c:3874 msgid "Settings" msgstr "Einstellung" -#: describe.c:3801 +#: describe.c:3898 #, c-format msgid "Did not find any settings for role \"%s\" and database \"%s\"." msgstr "Keine Einstellungen für Rolle »%s« und Datenbank »%s« gefunden" -#: describe.c:3804 +#: describe.c:3901 #, c-format msgid "Did not find any settings for role \"%s\"." msgstr "Keine Einstellungen für Rolle »%s« gefunden" -#: describe.c:3807 +#: describe.c:3904 #, c-format msgid "Did not find any settings." msgstr "Keine Einstellungen gefunden" -#: describe.c:3811 +#: describe.c:3908 msgid "List of settings" msgstr "Liste der Einstellungen" -#: describe.c:3841 +#: describe.c:3938 msgid "Member of" msgstr "Mitglied von" -#: describe.c:3858 +#: describe.c:3955 msgid "Grantor" msgstr "Grantor" -#: describe.c:3884 +#: describe.c:3981 msgid "List of role grants" msgstr "Liste der Rollen-Grants" -#: describe.c:3950 +#: describe.c:4051 msgid "index" msgstr "Index" -#: describe.c:3952 +#: describe.c:4053 msgid "TOAST table" msgstr "TOAST-Tabelle" -#: describe.c:3955 describe.c:4166 +#: describe.c:4056 describe.c:4320 msgid "partitioned index" msgstr "partitionierter Index" -#: describe.c:3975 +#: describe.c:4080 msgid "permanent" msgstr "permanent" -#: describe.c:3976 +#: describe.c:4081 msgid "temporary" msgstr "temporär" -#: describe.c:3977 +#: describe.c:4082 msgid "unlogged" msgstr "ungeloggt" -#: describe.c:3978 +#: describe.c:4083 msgid "Persistence" msgstr "Persistenz" -#: describe.c:3994 +#: describe.c:4099 describe.c:4343 msgid "Access method" msgstr "Zugriffsmethode" -#: describe.c:4079 +#: describe.c:4179 +#, c-format +msgid "Did not find any relations named \"%s\"." +msgstr "Keine Relationen namens »%s« gefunden" + +#: describe.c:4182 +#, c-format +msgid "Did not find any tables named \"%s\"." +msgstr "Keine Tabellen namens »%s« gefunden" + +#: describe.c:4185 +#, c-format +msgid "Did not find any indexes named \"%s\"." +msgstr "Keine Indexe namens »%s« gefunden" + +#: describe.c:4188 +#, c-format +msgid "Did not find any views named \"%s\"." +msgstr "Keine Sichten namens »%s« gefunden" + +#: describe.c:4191 +#, c-format +msgid "Did not find any materialized views named \"%s\"." +msgstr "Keine materialisierten Sichten namens »%s« gefunden" + +#: describe.c:4194 +#, c-format +msgid "Did not find any sequences named \"%s\"." +msgstr "Keine Sequenzen namens »%s« gefunden" + +#: describe.c:4197 +#, c-format +msgid "Did not find any foreign tables named \"%s\"." +msgstr "Keine Fremdtabellen namens »%s« gefunden" + +#: describe.c:4208 +#, c-format +msgid "Did not find any tables." +msgstr "Keine Tabellen gefunden" + +#: describe.c:4210 +#, c-format +msgid "Did not find any indexes." +msgstr "Keine Indexe gefunden" + +#: describe.c:4212 +#, c-format +msgid "Did not find any views." +msgstr "Keine Sichten gefunden" + +#: describe.c:4214 +#, c-format +msgid "Did not find any materialized views." +msgstr "Keine materialisierten Sichten gefunden" + +#: describe.c:4216 +#, c-format +msgid "Did not find any sequences." +msgstr "Keine Sequenzen gefunden" + +#: describe.c:4218 +#, c-format +msgid "Did not find any foreign tables." +msgstr "Keine Fremdtabellen gefunden" + +#: describe.c:4226 msgid "List of relations" msgstr "Liste der Relationen" -#: describe.c:4127 +#: describe.c:4227 +msgid "List of tables" +msgstr "Liste der Tabellen" + +#: describe.c:4228 +msgid "List of indexes" +msgstr "Liste der Indexe" + +#: describe.c:4229 +msgid "List of views" +msgstr "Liste der Sichten" + +#: describe.c:4230 +msgid "List of materialized views" +msgstr "Liste der materialisierten Sichten" + +#: describe.c:4231 +msgid "List of sequences" +msgstr "Liste der Sequenzen" + +#: describe.c:4232 describe.c:6162 +msgid "List of foreign tables" +msgstr "Liste der Fremdtabellen" + +#: describe.c:4281 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "Der Server (Version %s) unterstützt keine deklarative Tabellenpartitionierung." -#: describe.c:4138 +#: describe.c:4292 msgid "List of partitioned indexes" msgstr "Liste partitionierter Indexe" -#: describe.c:4140 +#: describe.c:4294 msgid "List of partitioned tables" msgstr "Liste partitionierte Tabellen" -#: describe.c:4144 +#: describe.c:4298 msgid "List of partitioned relations" msgstr "Liste partitionierter Relationen" -#: describe.c:4175 +#: describe.c:4329 msgid "Parent name" msgstr "Elternname" -#: describe.c:4188 +#: describe.c:4349 msgid "Leaf partition size" msgstr "Größe Leaf-Partition" -#: describe.c:4191 describe.c:4197 +#: describe.c:4352 describe.c:4358 msgid "Total size" msgstr "Gesamtgröße" -#: describe.c:4321 +#: describe.c:4485 msgid "Trusted" msgstr "Vertraut" -#: describe.c:4330 +#: describe.c:4494 msgid "Internal language" msgstr "Interne Sprache" -#: describe.c:4331 +#: describe.c:4495 msgid "Call handler" msgstr "Call-Handler" -#: describe.c:4332 describe.c:5743 +#: describe.c:4496 describe.c:5918 msgid "Validator" msgstr "Validator" -#: describe.c:4333 +#: describe.c:4497 msgid "Inline handler" msgstr "Inline-Handler" -#: describe.c:4367 +#: describe.c:4531 msgid "List of languages" msgstr "Liste der Sprachen" -#: describe.c:4408 +#: describe.c:4572 msgid "Check" msgstr "Check" -#: describe.c:4451 +#: describe.c:4615 msgid "List of domains" msgstr "Liste der Domänen" -#: describe.c:4485 +#: describe.c:4649 msgid "Source" msgstr "Quelle" -#: describe.c:4486 +#: describe.c:4650 msgid "Destination" msgstr "Ziel" -#: describe.c:4488 describe.c:6712 +#: describe.c:4652 describe.c:6928 msgid "Default?" msgstr "Standard?" -#: describe.c:4529 +#: describe.c:4693 msgid "List of conversions" msgstr "Liste der Konversionen" -#: describe.c:4557 -msgid "Parameter" -msgstr "Parameter" - -#: describe.c:4558 -msgid "Value" -msgstr "Wert" - -#: describe.c:4565 +#: describe.c:4729 msgid "Context" msgstr "Kontext" -#: describe.c:4597 +#: describe.c:4761 msgid "List of configuration parameters" msgstr "Liste der Konfigurationsparameter" -#: describe.c:4599 +#: describe.c:4763 msgid "List of non-default configuration parameters" msgstr "Liste der veränderten Konfigurationsparameter" -#: describe.c:4626 +#: describe.c:4790 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "Der Server (Version %s) unterstützt keine Ereignistrigger." -#: describe.c:4646 +#: describe.c:4810 msgid "Event" msgstr "Ereignis" -#: describe.c:4648 +#: describe.c:4812 msgid "enabled" msgstr "eingeschaltet" -#: describe.c:4649 +#: describe.c:4813 msgid "replica" msgstr "Replika" -#: describe.c:4650 +#: describe.c:4814 msgid "always" msgstr "immer" -#: describe.c:4651 +#: describe.c:4815 msgid "disabled" msgstr "ausgeschaltet" -#: describe.c:4652 describe.c:6553 +#: describe.c:4816 describe.c:6769 msgid "Enabled" msgstr "Eingeschaltet" -#: describe.c:4654 +#: describe.c:4818 msgid "Tags" msgstr "Tags" -#: describe.c:4677 +#: describe.c:4841 msgid "List of event triggers" msgstr "Liste der Ereignistrigger" -#: describe.c:4704 +#: describe.c:4868 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "Der Server (Version %s) unterstützt keine erweiterten Statistiken." -#: describe.c:4741 +#: describe.c:4905 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4742 +#: describe.c:4906 msgid "Dependencies" msgstr "Abhängigkeiten" -#: describe.c:4752 +#: describe.c:4916 msgid "MCV" msgstr "MCV" -#: describe.c:4775 +#: describe.c:4939 msgid "List of extended statistics" msgstr "Liste der erweiterten Statistiken" -#: describe.c:4802 +#: describe.c:4966 msgid "Source type" msgstr "Quelltyp" -#: describe.c:4803 +#: describe.c:4967 msgid "Target type" msgstr "Zieltyp" -#: describe.c:4827 +#: describe.c:4991 msgid "in assignment" msgstr "in Zuweisung" -#: describe.c:4829 +#: describe.c:4993 msgid "Implicit?" msgstr "Implizit?" -#: describe.c:4887 +#: describe.c:5057 msgid "List of casts" msgstr "Liste der Typumwandlungen" -#: describe.c:4927 describe.c:4931 +#: describe.c:5102 describe.c:5106 msgid "Provider" msgstr "Provider" -#: describe.c:4965 describe.c:4970 +#: describe.c:5140 describe.c:5145 msgid "Deterministic?" msgstr "Deterministisch?" -#: describe.c:5009 +#: describe.c:5184 msgid "List of collations" msgstr "Liste der Sortierfolgen" -#: describe.c:5070 +#: describe.c:5245 msgid "List of schemas" msgstr "Liste der Schemas" -#: describe.c:5186 +#: describe.c:5361 msgid "List of text search parsers" msgstr "Liste der Textsucheparser" -#: describe.c:5236 +#: describe.c:5411 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "Kein Textsucheparser namens »%s« gefunden" -#: describe.c:5239 +#: describe.c:5414 #, c-format msgid "Did not find any text search parsers." msgstr "Keine Textsucheparser gefunden" -#: describe.c:5314 +#: describe.c:5489 msgid "Start parse" msgstr "Parsen starten" -#: describe.c:5315 +#: describe.c:5490 msgid "Method" msgstr "Methode" -#: describe.c:5319 +#: describe.c:5494 msgid "Get next token" msgstr "Nächstes Token lesen" -#: describe.c:5321 +#: describe.c:5496 msgid "End parse" msgstr "Parsen beenden" -#: describe.c:5323 +#: describe.c:5498 msgid "Get headline" msgstr "Überschrift ermitteln" -#: describe.c:5325 +#: describe.c:5500 msgid "Get token types" msgstr "Tokentypen ermitteln" -#: describe.c:5335 +#: describe.c:5510 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Textsucheparser »%s.%s«" -#: describe.c:5338 +#: describe.c:5513 #, c-format msgid "Text search parser \"%s\"" msgstr "Textsucheparser »%s«" -#: describe.c:5357 +#: describe.c:5532 msgid "Token name" msgstr "Tokenname" -#: describe.c:5370 +#: describe.c:5545 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Tokentypen für Parser »%s.%s«" -#: describe.c:5373 +#: describe.c:5548 #, c-format msgid "Token types for parser \"%s\"" msgstr "Tokentypen für Parser »%s«" -#: describe.c:5417 +#: describe.c:5592 msgid "Template" msgstr "Vorlage" -#: describe.c:5418 +#: describe.c:5593 msgid "Init options" msgstr "Initialisierungsoptionen" -#: describe.c:5444 +#: describe.c:5619 msgid "List of text search dictionaries" msgstr "Liste der Textsuchewörterbücher" -#: describe.c:5477 +#: describe.c:5652 msgid "Init" msgstr "Init" -#: describe.c:5478 +#: describe.c:5653 msgid "Lexize" msgstr "Lexize" -#: describe.c:5509 +#: describe.c:5684 msgid "List of text search templates" msgstr "Liste der Textsuchevorlagen" -#: describe.c:5563 +#: describe.c:5738 msgid "List of text search configurations" msgstr "Liste der Textsuchekonfigurationen" -#: describe.c:5614 +#: describe.c:5789 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "Keine Textsuchekonfiguration namens »%s« gefunden" -#: describe.c:5617 +#: describe.c:5792 #, c-format msgid "Did not find any text search configurations." msgstr "Keine Textsuchekonfigurationen gefunden" -#: describe.c:5683 +#: describe.c:5858 msgid "Token" msgstr "Token" -#: describe.c:5684 +#: describe.c:5859 msgid "Dictionaries" msgstr "Wörterbücher" -#: describe.c:5695 +#: describe.c:5870 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Textsuchekonfiguration »%s.%s«" -#: describe.c:5698 +#: describe.c:5873 #, c-format msgid "Text search configuration \"%s\"" msgstr "Textsuchekonfiguration »%s«" -#: describe.c:5702 +#: describe.c:5877 #, c-format msgid "" "\n" @@ -2237,7 +2442,7 @@ msgstr "" "\n" "Parser: »%s.%s«" -#: describe.c:5705 +#: describe.c:5880 #, c-format msgid "" "\n" @@ -2246,273 +2451,279 @@ msgstr "" "\n" "Parser: »%s«" -#: describe.c:5784 +#: describe.c:5959 msgid "List of foreign-data wrappers" msgstr "Liste der Fremddaten-Wrapper" -#: describe.c:5812 +#: describe.c:5987 msgid "Foreign-data wrapper" msgstr "Fremddaten-Wrapper" -#: describe.c:5830 describe.c:6017 +#: describe.c:6005 describe.c:6194 msgid "Version" msgstr "Version" -#: describe.c:5860 +#: describe.c:6035 msgid "List of foreign servers" msgstr "Liste der Fremdserver" -#: describe.c:5885 describe.c:5943 +#: describe.c:6060 describe.c:6118 msgid "Server" msgstr "Server" -#: describe.c:5886 +#: describe.c:6061 msgid "User name" msgstr "Benutzername" -#: describe.c:5915 +#: describe.c:6090 msgid "List of user mappings" msgstr "Liste der Benutzerabbildungen" -#: describe.c:5987 -msgid "List of foreign tables" -msgstr "Liste der Fremdtabellen" +#: describe.c:6195 +#, fuzzy +#| msgid "Default footer is on.\n" +msgid "Default version" +msgstr "Standardfußzeile ist an.\n" -#: describe.c:6038 +#: describe.c:6216 msgid "List of installed extensions" msgstr "Liste der installierten Erweiterungen" -#: describe.c:6086 +#: describe.c:6264 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "Keine Erweiterung namens »%s« gefunden" -#: describe.c:6089 +#: describe.c:6267 #, c-format msgid "Did not find any extensions." msgstr "Keine Erweiterungen gefunden" -#: describe.c:6133 +#: describe.c:6311 msgid "Object description" msgstr "Objektbeschreibung" -#: describe.c:6142 +#: describe.c:6320 #, c-format msgid "Objects in extension \"%s\"" msgstr "Objekte in Erweiterung »%s«" -#: describe.c:6183 +#: describe.c:6361 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "falscher qualifizierter Name (zu viele Namensteile): %s" -#: describe.c:6197 +#: describe.c:6375 #, c-format msgid "cross-database references are not implemented: %s" msgstr "Verweise auf andere Datenbanken sind nicht implementiert: %s" -#: describe.c:6228 describe.c:6354 +#: describe.c:6406 describe.c:6542 #, c-format msgid "The server (version %s) does not support publications." msgstr "Der Server (Version %s) unterstützt keine Publikationen." -#: describe.c:6245 describe.c:6432 +#: describe.c:6423 describe.c:6644 msgid "All tables" msgstr "Alle Tabellen" -#: describe.c:6246 describe.c:6433 +#: describe.c:6424 describe.c:6645 msgid "Inserts" msgstr "Inserts" -#: describe.c:6247 describe.c:6434 +#: describe.c:6425 describe.c:6646 msgid "Updates" msgstr "Updates" -#: describe.c:6248 describe.c:6435 +#: describe.c:6426 describe.c:6647 msgid "Deletes" msgstr "Deletes" -#: describe.c:6252 describe.c:6437 +#: describe.c:6430 describe.c:6649 msgid "Truncates" msgstr "Truncates" -#: describe.c:6256 describe.c:6439 +#: describe.c:6439 describe.c:6573 describe.c:6651 +msgid "Generated columns" +msgstr "Generierte Spalten" + +#: describe.c:6443 describe.c:6653 msgid "Via root" msgstr "Über Wurzel" -#: describe.c:6277 +#: describe.c:6464 msgid "List of publications" msgstr "Liste der Publikationen" -#: describe.c:6401 +#: describe.c:6611 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "Keine Publikation namens »%s« gefunden" -#: describe.c:6404 +#: describe.c:6614 #, c-format msgid "Did not find any publications." msgstr "Keine Publikationen gefunden" -#: describe.c:6428 +#: describe.c:6640 #, c-format msgid "Publication %s" msgstr "Publikation %s" -#: describe.c:6481 +#: describe.c:6697 msgid "Tables:" msgstr "Tabellen:" -#: describe.c:6493 +#: describe.c:6709 msgid "Tables from schemas:" msgstr "Tabellen aus Schemas:" -#: describe.c:6538 +#: describe.c:6754 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "Der Server (Version %s) unterstützt keine Subskriptionen." -#: describe.c:6554 +#: describe.c:6770 msgid "Publication" msgstr "Publikation" -#: describe.c:6563 +#: describe.c:6779 msgid "Binary" msgstr "Binär" -#: describe.c:6572 describe.c:6576 +#: describe.c:6788 describe.c:6792 msgid "Streaming" msgstr "Streaming" -#: describe.c:6584 +#: describe.c:6800 msgid "Two-phase commit" msgstr "Two-Phase-Commit" -#: describe.c:6585 +#: describe.c:6801 msgid "Disable on error" msgstr "Bei Fehler abschalten" -#: describe.c:6592 +#: describe.c:6808 msgid "Origin" msgstr "Herkunft" -#: describe.c:6593 +#: describe.c:6809 msgid "Password required" msgstr "Passwort nötig" -#: describe.c:6594 +#: describe.c:6810 msgid "Run as owner?" msgstr "Als Eigentümer ausführen?" -#: describe.c:6599 +#: describe.c:6815 msgid "Failover" msgstr "Failover" -#: describe.c:6604 +#: describe.c:6820 msgid "Synchronous commit" msgstr "Synchroner Commit" -#: describe.c:6605 +#: describe.c:6821 msgid "Conninfo" msgstr "Verbindungsinfo" -#: describe.c:6611 +#: describe.c:6827 msgid "Skip LSN" msgstr "Skip-LSN" -#: describe.c:6637 +#: describe.c:6853 msgid "List of subscriptions" msgstr "Liste der Subskriptionen" -#: describe.c:6666 +#: describe.c:6882 msgid "(none)" msgstr "(keine)" -#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 +#: describe.c:6922 describe.c:7017 describe.c:7109 describe.c:7212 msgid "AM" msgstr "AM" -#: describe.c:6707 +#: describe.c:6923 msgid "Input type" msgstr "Eingabetyp" -#: describe.c:6708 +#: describe.c:6924 msgid "Storage type" msgstr "Storage-Typ" -#: describe.c:6709 +#: describe.c:6925 msgid "Operator class" msgstr "Operatorklasse" -#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 +#: describe.c:6937 describe.c:7018 describe.c:7110 describe.c:7213 msgid "Operator family" msgstr "Operatorfamilie" -#: describe.c:6756 +#: describe.c:6972 msgid "List of operator classes" msgstr "Liste der Operatorklassen" -#: describe.c:6803 +#: describe.c:7019 msgid "Applicable types" msgstr "Passende Typen" -#: describe.c:6844 +#: describe.c:7060 msgid "List of operator families" msgstr "Liste der Operatorfamilien" -#: describe.c:6895 +#: describe.c:7111 msgid "Operator" msgstr "Operator" -#: describe.c:6896 +#: describe.c:7112 msgid "Strategy" msgstr "Strategie" -#: describe.c:6897 +#: describe.c:7113 msgid "ordering" msgstr "Sortieren" -#: describe.c:6898 +#: describe.c:7114 msgid "search" msgstr "Suchen" -#: describe.c:6899 +#: describe.c:7115 msgid "Purpose" msgstr "Zweck" -#: describe.c:6904 +#: describe.c:7124 msgid "Sort opfamily" msgstr "Sortier-Opfamilie" -#: describe.c:6942 +#: describe.c:7167 msgid "List of operators of operator families" msgstr "Liste der Operatoren in Operatorfamilien" -#: describe.c:6989 +#: describe.c:7214 msgid "Registered left type" msgstr "Registrierter linker Typ" -#: describe.c:6990 +#: describe.c:7215 msgid "Registered right type" msgstr "Registrierter rechter Typ" -#: describe.c:6991 +#: describe.c:7216 msgid "Number" msgstr "Nummer" -#: describe.c:7034 +#: describe.c:7259 msgid "List of support functions of operator families" msgstr "Liste der Unterstützungsfunktionen in Operatorfamilien" -#: describe.c:7065 +#: describe.c:7290 msgid "ID" msgstr "ID" -#: describe.c:7085 +#: describe.c:7310 msgid "Large objects" msgstr "Large Objects" -#: help.c:63 +#: help.c:60 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2520,11 +2731,11 @@ msgstr "" "psql ist das interaktive PostgreSQL-Terminal.\n" "\n" -#: help.c:64 help.c:372 help.c:456 help.c:499 +#: help.c:61 help.c:384 help.c:470 help.c:516 msgid "Usage:\n" msgstr "Aufruf:\n" -#: help.c:65 +#: help.c:62 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2532,27 +2743,27 @@ msgstr "" " psql [OPTION]... [DBNAME [BENUTZERNAME]]\n" "\n" -#: help.c:67 +#: help.c:64 msgid "General options:\n" msgstr "Allgemeine Optionen:\n" -#: help.c:68 +#: help.c:65 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr " -c, --command=ANWEISUNG einzelne Anweisung ausführen und beenden\n" -#: help.c:69 +#: help.c:66 msgid " -d, --dbname=DBNAME database name to connect to\n" msgstr " -d, --dbname=DBNAME Datenbank, mit der verbunden werden soll\n" -#: help.c:70 +#: help.c:67 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=DATEINAME Anweisungen aus Datei ausführen und danach beenden\n" -#: help.c:71 +#: help.c:68 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list verfügbare Datenbanken auflisten und beenden\n" -#: help.c:72 +#: help.c:69 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2562,15 +2773,15 @@ msgstr "" " psql-Variable NAME auf WERT setzen\n" " (z.B. -v ON_ERROR_STOP=1)\n" -#: help.c:75 +#: help.c:72 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: help.c:76 +#: help.c:73 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc Startdatei (~/.psqlrc) nicht lesen\n" -#: help.c:77 +#: help.c:74 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" @@ -2579,19 +2790,19 @@ msgstr "" " als eine einzige Transaktion ausführen (wenn nicht\n" " interaktiv)\n" -#: help.c:79 +#: help.c:76 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=options] diese Hilfe anzeigen, dann beenden\n" -#: help.c:80 +#: help.c:77 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands Backslash-Befehle auflisten, dann beenden\n" -#: help.c:81 +#: help.c:78 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables besondere Variablen auflisten, dann beenden\n" -#: help.c:83 +#: help.c:80 msgid "" "\n" "Input and output options:\n" @@ -2599,51 +2810,51 @@ msgstr "" "\n" "Eingabe- und Ausgabeoptionen:\n" -#: help.c:84 +#: help.c:81 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all Skript-Inhalt wiedergeben\n" -#: help.c:85 +#: help.c:82 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors fehlgeschlagene Anweisungen wiedergeben\n" -#: help.c:86 +#: help.c:83 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries an den Server geschickte Anweisungen zeigen\n" -#: help.c:87 +#: help.c:84 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden von internen Anweisungen erzeugte Anfragen zeigen\n" -#: help.c:88 +#: help.c:85 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr "" " -L, --log-file=DATEINAME\n" " Sitzungslog in Datei senden\n" -#: help.c:89 +#: help.c:86 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr " -n, --no-readline erweiterte Zeilenbearbeitung (Readline) ausschalten\n" -#: help.c:90 +#: help.c:87 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=DATEINAME Anfrageergebnisse in Datei (oder |Pipe) senden\n" -#: help.c:91 +#: help.c:88 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr "" " -q, --quiet stille Ausführung (keine Mitteilungen, nur\n" " Anfrageergebnisse)\n" -#: help.c:92 +#: help.c:89 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step Einzelschrittmodus (jede Anfrage bestätigen)\n" -#: help.c:93 +#: help.c:90 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr " -S, --single-line Einzelzeilenmodus (Zeilenende beendet SQL-Anweisung)\n" -#: help.c:95 +#: help.c:92 msgid "" "\n" "Output format options:\n" @@ -2651,15 +2862,15 @@ msgstr "" "\n" "Ausgabeformatoptionen:\n" -#: help.c:96 +#: help.c:93 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align unausgerichteter Tabellenausgabemodus\n" -#: help.c:97 +#: help.c:94 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv Tabellenausgabemodus CSV (Comma-Separated Values)\n" -#: help.c:98 +#: help.c:95 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2669,17 +2880,17 @@ msgstr "" " Feldtrennzeichen für unausgerichteten Ausgabemodus\n" " (Standard: »%s«)\n" -#: help.c:101 +#: help.c:98 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html HTML-Tabellenausgabemodus\n" -#: help.c:102 +#: help.c:99 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr "" " -P, --pset=VAR[=ARG] Ausgabeoption VAR auf ARG setzen (siehe\n" " \\pset-Anweisung)\n" -#: help.c:103 +#: help.c:100 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" @@ -2688,19 +2899,19 @@ msgstr "" " Satztrennzeichen für unausgerichteten Ausgabemodus\n" " (Standard: Newline)\n" -#: help.c:105 +#: help.c:102 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only nur Datenzeilen ausgeben\n" -#: help.c:106 +#: help.c:103 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr " -T, --table-attr=TEXT HTML »table«-Tag-Attribute setzen (z.B. width, border)\n" -#: help.c:107 +#: help.c:104 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded erweiterte Tabellenausgabe einschalten\n" -#: help.c:108 +#: help.c:105 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" @@ -2709,7 +2920,7 @@ msgstr "" " Feldtrennzeichen für unausgerichteten Ausgabemodus auf\n" " Null-Byte setzen\n" -#: help.c:110 +#: help.c:107 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" @@ -2718,7 +2929,7 @@ msgstr "" " Satztrennzeichen für unausgerichteten Ausgabemodus auf\n" " Null-Byte setzen\n" -#: help.c:113 +#: help.c:110 msgid "" "\n" "Connection options:\n" @@ -2726,27 +2937,27 @@ msgstr "" "\n" "Verbindungsoptionen:\n" -#: help.c:114 +#: help.c:111 msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" -#: help.c:115 +#: help.c:112 msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT Port des Datenbankservers\n" -#: help.c:116 +#: help.c:113 msgid " -U, --username=USERNAME database user name\n" msgstr " -U, --username=NAME Datenbank-Benutzername\n" -#: help.c:117 +#: help.c:114 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password niemals nach Passwort fragen\n" -#: help.c:118 +#: help.c:115 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password nach Passwort fragen (sollte automatisch geschehen)\n" -#: help.c:120 +#: help.c:117 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" @@ -2760,39 +2971,35 @@ msgstr "" "Abschnitt der PostgreSQL-Dokumentation.\n" "\n" -#: help.c:123 +#: help.c:120 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Berichten Sie Fehler an <%s>.\n" -#: help.c:124 +#: help.c:121 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: help.c:166 +#: help.c:163 msgid "General\n" msgstr "Allgemein\n" -#: help.c:167 -msgid " \\bind [PARAM]... set query parameters\n" -msgstr " \\bind [PARAM]... Anfrageparameter setzen\n" - -#: help.c:168 +#: help.c:164 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright PostgreSQL-Urheberrechtsinformationen zeigen\n" -#: help.c:169 +#: help.c:165 msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr "" " \\crosstabview [SPALTEN] Anfrage ausführen und Ergebnis als Kreuztabelle\n" " anzeigen\n" -#: help.c:170 +#: help.c:166 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose letzte Fehlermeldung mit vollen Details anzeigen\n" -#: help.c:171 +#: help.c:167 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2800,31 +3007,31 @@ msgstr "" " \\g [(OPT)] [DATEI] SQL-Anweisung ausführen (und Ergebnis in Datei oder\n" " |Pipe schreiben); \\g ohne Argumente entspricht Semikolon\n" -#: help.c:173 +#: help.c:169 msgid " \\gdesc describe result of query, without executing it\n" msgstr " \\gdesc Ergebnis der Anfrage beschreiben ohne sie auszuführen\n" -#: help.c:174 +#: help.c:170 msgid " \\gexec execute query, then execute each value in its result\n" msgstr "" " \\gexec Anfrage ausführen, dann jeden Ergebniswert als\n" " Anweisung ausführen\n" -#: help.c:175 +#: help.c:171 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr "" " \\gset [PREFIX] SQL-Anweisung ausführen und Ergebnis in psql-Variablen\n" " ablegen\n" -#: help.c:176 +#: help.c:172 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr " \\gx [(OPT)] [DATEI] wie \\g, aber mit erweitertem Ausgabemodus\n" -#: help.c:177 +#: help.c:173 msgid " \\q quit psql\n" msgstr " \\q psql beenden\n" -#: help.c:178 +#: help.c:174 msgid "" " \\watch [[i=]SEC] [c=N] [m=MIN]\n" " execute query every SEC seconds, up to N times,\n" @@ -2834,356 +3041,358 @@ msgstr "" " Anfrage alle SEK Sekunden ausführen, bis zu N Mal,\n" " aufhören wenn weniger als MIN Zeilen zurückgegeben werden\n" -#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 -#: help.c:303 help.c:316 help.c:325 +#: help.c:177 help.c:185 help.c:197 help.c:207 help.c:214 help.c:271 help.c:279 +#: help.c:299 help.c:312 help.c:321 help.c:327 msgid "\n" msgstr "\n" -#: help.c:183 +#: help.c:179 msgid "Help\n" msgstr "Hilfe\n" -#: help.c:185 +#: help.c:181 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commands] Hilfe über Backslash-Befehle anzeigen\n" -#: help.c:186 +#: help.c:182 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options Hilfe über psql-Kommandozeilenoptionen anzeigen\n" -#: help.c:187 +#: help.c:183 msgid " \\? variables show help on special variables\n" msgstr " \\? variables Hilfe über besondere Variablen anzeigen\n" -#: help.c:188 +#: help.c:184 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr " \\h [NAME] Syntaxhilfe über SQL-Anweisung, * für alle Anweisungen\n" -#: help.c:191 +#: help.c:187 msgid "Query Buffer\n" msgstr "Anfragepuffer\n" -#: help.c:192 +#: help.c:188 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr " \\e [DATEI] [ZEILE] Anfragepuffer (oder Datei) mit externem Editor bearbeiten\n" -#: help.c:193 +#: help.c:189 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr " \\ef [FUNKNAME [ZEILE]] Funktionsdefinition mit externem Editor bearbeiten\n" -#: help.c:194 +#: help.c:190 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr " \\ev [SICHTNAME [ZEILE]] Sichtdefinition mit externem Editor bearbeiten\n" -#: help.c:195 +#: help.c:191 msgid " \\p show the contents of the query buffer\n" msgstr " \\p aktuellen Inhalt der Anfragepuffers zeigen\n" -#: help.c:196 +#: help.c:192 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r Anfragepuffer löschen\n" -#: help.c:198 +#: help.c:194 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [DATEI] Befehlsgeschichte ausgeben oder in Datei schreiben\n" -#: help.c:200 +#: help.c:196 msgid " \\w FILE write query buffer to file\n" msgstr " \\w DATEI Anfragepuffer in Datei schreiben\n" -#: help.c:203 +#: help.c:199 msgid "Input/Output\n" msgstr "Eingabe/Ausgabe\n" -#: help.c:204 +#: help.c:200 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr " \\copy ... SQL COPY mit Datenstrom auf Client-Host ausführen\n" -#: help.c:205 +#: help.c:201 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [TEXT] Text auf Standardausgabe schreiben (-n für ohne Newline)\n" -#: help.c:206 +#: help.c:202 msgid " \\i FILE execute commands from file\n" msgstr " \\i DATEI Befehle aus Datei ausführen\n" -#: help.c:207 +#: help.c:203 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr " \\ir DATEI wie \\i, aber relativ zum Ort des aktuellen Skripts\n" -#: help.c:208 +#: help.c:204 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [DATEI] alle Anfrageergebnisse in Datei oder |Pipe schreiben\n" -#: help.c:209 +#: help.c:205 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr "" " \\qecho [-n] [TEXT] Text auf Ausgabestrom für \\o schreiben (-n für ohne\n" " Newline)\n" -#: help.c:210 +#: help.c:206 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr "" " \\warn [-n] [TEXT] Text auf Standardfehlerausgabe schreiben (-n für ohne\n" " Newline)\n" -#: help.c:213 +#: help.c:209 msgid "Conditional\n" msgstr "Bedingte Anweisungen\n" -#: help.c:214 +#: help.c:210 msgid " \\if EXPR begin conditional block\n" msgstr " \\if AUSDRUCK Beginn einer bedingten Anweisung\n" -#: help.c:215 +#: help.c:211 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif AUSDRUCK Alternative in aktueller bedingter Anweisung\n" -#: help.c:216 +#: help.c:212 msgid " \\else final alternative within current conditional block\n" msgstr " \\else letzte Alternative in aktueller bedingter Anweisung\n" -#: help.c:217 +#: help.c:213 msgid " \\endif end conditional block\n" msgstr " \\endif Ende einer bedingten Anweisung\n" -#: help.c:220 +#: help.c:216 msgid "Informational\n" msgstr "Informationen\n" +#: help.c:217 +msgid " (options: S = show system objects, x = expanded mode, + = additional detail)\n" +msgstr " (Optionen: S = Systemobjekte zeigen, x = erweiterte Ausgabe, + = mehr Details)\n" + +#: help.c:218 +msgid " \\d[Sx+] list tables, views, and sequences\n" +msgstr " \\d[Sx+] Tabellen, Sichten und Sequenzen auflisten\n" + +#: help.c:219 +msgid " \\d[S+] NAME describe table, view, sequence, or index\n" +msgstr " \\d[S+] NAME Tabelle, Sicht, Sequenz oder Index beschreiben\n" + +#: help.c:220 +msgid " \\da[Sx] [PATTERN] list aggregates\n" +msgstr " \\da[Sx] [MUSTER] Aggregatfunktionen auflisten\n" + #: help.c:221 -msgid " (options: S = show system objects, + = additional detail)\n" -msgstr " (Optionen: S = Systemobjekte zeigen, + = zusätzliche Details zeigen)\n" +msgid " \\dA[x+] [PATTERN] list access methods\n" +msgstr " \\dA[x+] [MUSTER] Zugriffsmethoden auflisten\n" #: help.c:222 -msgid " \\d[S+] list tables, views, and sequences\n" -msgstr " \\d[S+] Tabellen, Sichten und Sequenzen auflisten\n" +msgid " \\dAc[x+] [AMPTRN [TYPEPTRN]] list operator classes\n" +msgstr " \\dAc[x+] [AMMUST [TYPMUST]] Operatorklassen auflisten\n" #: help.c:223 -msgid " \\d[S+] NAME describe table, view, sequence, or index\n" -msgstr " \\d[S+] NAME Tabelle, Sicht, Sequenz oder Index beschreiben\n" +msgid " \\dAf[x+] [AMPTRN [TYPEPTRN]] list operator families\n" +msgstr " \\dAf[x+] [AMMUST [TYPMUST]] Operatorfamilien auflisten\n" #: help.c:224 -msgid " \\da[S] [PATTERN] list aggregates\n" -msgstr " \\da[S] [MUSTER] Aggregatfunktionen auflisten\n" +msgid " \\dAo[x+] [AMPTRN [OPFPTRN]] list operators of operator families\n" +msgstr " \\dAo[x+] [AMMUST [OPFMUST]] Operatoren in Operatorfamilien auflisten\n" #: help.c:225 -msgid " \\dA[+] [PATTERN] list access methods\n" -msgstr " \\dA[+] [MUSTER] Zugriffsmethoden auflisten\n" +msgid " \\dAp[x+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" +msgstr " \\dAp[x+] [AMMUST [OPFMUST]] Unterst.funktionen in Operatorfamilien auflisten\n" #: help.c:226 -msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" -msgstr " \\dAc[+] [AMMUST [TYPMUST]] Operatorklassen auflisten\n" +msgid " \\db[x+] [PATTERN] list tablespaces\n" +msgstr " \\db[x+] [MUSTER] Tablespaces auflisten\n" #: help.c:227 -msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" -msgstr " \\dAf[+] [AMMUST [TYPMUST]] Operatorfamilien auflisten\n" +msgid " \\dc[Sx+] [PATTERN] list conversions\n" +msgstr " \\dc[Sx+] [MUSTER] Konversionen auflisten\n" #: help.c:228 -msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" -msgstr " \\dAo[+] [AMMUST [OPFMUST]] Operatoren in Operatorfamilien auflisten\n" +msgid " \\dconfig[x+] [PATTERN] list configuration parameters\n" +msgstr " \\dconfig[x+] [MUSTER] Konfigurationsparameter auflisten\n" #: help.c:229 -msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" -msgstr " \\dAp[+] [AMMUST [OPFMUST]] Unterst.funktionen in Operatorfamilien auflisten\n" +msgid " \\dC[x+] [PATTERN] list casts\n" +msgstr " \\dC[x+] [MUSTER] Typumwandlungen (Casts) auflisten\n" #: help.c:230 -msgid " \\db[+] [PATTERN] list tablespaces\n" -msgstr " \\db[+] [MUSTER] Tablespaces auflisten\n" +msgid " \\dd[Sx] [PATTERN] show object descriptions not displayed elsewhere\n" +msgstr "" +" \\dd[Sx] [MUSTER] Objektbeschreibungen zeigen, die nirgendwo anders\n" +" erscheinen\n" #: help.c:231 -msgid " \\dc[S+] [PATTERN] list conversions\n" -msgstr " \\dc[S+] [MUSTER] Konversionen auflisten\n" +msgid " \\dD[Sx+] [PATTERN] list domains\n" +msgstr " \\dD[Sx+] [MUSTER] Domänen auflisten\n" #: help.c:232 -msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" -msgstr " \\dconfig[+] [MUSTER] Konfigurationsparameter auflisten\n" +msgid " \\ddp[x] [PATTERN] list default privileges\n" +msgstr " \\ddp[x] [MUSTER] Vorgabeprivilegien auflisten\n" #: help.c:233 -msgid " \\dC[+] [PATTERN] list casts\n" -msgstr " \\dC[+] [MUSTER] Typumwandlungen (Casts) auflisten\n" +msgid " \\dE[Sx+] [PATTERN] list foreign tables\n" +msgstr " \\dE[Sx+] [MUSTER] Fremdtabellen auflisten\n" #: help.c:234 -msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" -msgstr "" -" \\dd[S] [MUSTER] Objektbeschreibungen zeigen, die nirgendwo anders\n" -" erscheinen\n" +msgid " \\des[x+] [PATTERN] list foreign servers\n" +msgstr " \\des[x+] [MUSTER] Fremdserver auflisten\n" #: help.c:235 -msgid " \\dD[S+] [PATTERN] list domains\n" -msgstr " \\dD[S+] [MUSTER] Domänen auflisten\n" +msgid " \\det[x+] [PATTERN] list foreign tables\n" +msgstr " \\det[x+] [MUSTER] Fremdtabellen auflisten\n" #: help.c:236 -msgid " \\ddp [PATTERN] list default privileges\n" -msgstr " \\ddp [MUSTER] Vorgabeprivilegien auflisten\n" +msgid " \\deu[x+] [PATTERN] list user mappings\n" +msgstr " \\deu[x+] [MUSTER] Benutzerabbildungen auflisten\n" #: help.c:237 -msgid " \\dE[S+] [PATTERN] list foreign tables\n" -msgstr " \\dE[S+] [MUSTER] Fremdtabellen auflisten\n" +msgid " \\dew[x+] [PATTERN] list foreign-data wrappers\n" +msgstr " \\dew[x+] [MUSTER] Fremddaten-Wrapper auflisten\n" #: help.c:238 -msgid " \\des[+] [PATTERN] list foreign servers\n" -msgstr " \\des[+] [MUSTER] Fremdserver auflisten\n" - -#: help.c:239 -msgid " \\det[+] [PATTERN] list foreign tables\n" -msgstr " \\det[+] [MUSTER] Fremdtabellen auflisten\n" +msgid "" +" \\df[anptw][Sx+] [FUNCPTRN [TYPEPTRN ...]]\n" +" list [only agg/normal/procedure/trigger/window] functions\n" +msgstr "" +" \\df[anptw][Sx+] [FUNKMUSTR [TYPMUSTR ...]]\n" +" Funktionen [nur Agg/normale/Proz/Trigger/Fenster] auflisten\n" #: help.c:240 -msgid " \\deu[+] [PATTERN] list user mappings\n" -msgstr " \\deu[+] [MUSTER] Benutzerabbildungen auflisten\n" +msgid " \\dF[x+] [PATTERN] list text search configurations\n" +msgstr " \\dF[x+] [MUSTER] Textsuchekonfigurationen auflisten\n" #: help.c:241 -msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" -msgstr " \\dew[+] [MUSTER] Fremddaten-Wrapper auflisten\n" +msgid " \\dFd[x+] [PATTERN] list text search dictionaries\n" +msgstr " \\dFd[x+] [MUSTER] Textsuchewörterbücher auflisten\n" #: help.c:242 -msgid "" -" \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" -" list [only agg/normal/procedure/trigger/window] functions\n" -msgstr "" -" \\df[anptw][S+] [FUNKMUSTR [TYPMUSTR ...]]\n" -" Funktionen [nur Agg/normale/Proz/Trigger/Fenster] auflisten\n" +msgid " \\dFp[x+] [PATTERN] list text search parsers\n" +msgstr " \\dFp[x+] [MUSTER] Textsucheparser auflisten\n" + +#: help.c:243 +msgid " \\dFt[x+] [PATTERN] list text search templates\n" +msgstr " \\dFt[x+] [MUSTER] Textsuchevorlagen auflisten\n" #: help.c:244 -msgid " \\dF[+] [PATTERN] list text search configurations\n" -msgstr " \\dF[+] [MUSTER] Textsuchekonfigurationen auflisten\n" +msgid " \\dg[Sx+] [PATTERN] list roles\n" +msgstr " \\dg[Sx+] [MUSTER] Rollen auflisten\n" #: help.c:245 -msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" -msgstr " \\dFd[+] [MUSTER] Textsuchewörterbücher auflisten\n" +msgid " \\di[Sx+] [PATTERN] list indexes\n" +msgstr " \\di[Sx+] [MUSTER] Indexe auflisten\n" #: help.c:246 -msgid " \\dFp[+] [PATTERN] list text search parsers\n" -msgstr " \\dFp[+] [MUSTER] Textsucheparser auflisten\n" +msgid " \\dl[x+] list large objects, same as \\lo_list\n" +msgstr " \\dl[x+] Large Objects auflisten, wie \\lo_list\n" #: help.c:247 -msgid " \\dFt[+] [PATTERN] list text search templates\n" -msgstr " \\dFt[+] [MUSTER] Textsuchevorlagen auflisten\n" +msgid " \\dL[Sx+] [PATTERN] list procedural languages\n" +msgstr " \\dL[Sx+] [MUSTER] prozedurale Sprachen auflisten\n" #: help.c:248 -msgid " \\dg[S+] [PATTERN] list roles\n" -msgstr " \\dg[S+] [MUSTER] Rollen auflisten\n" +msgid " \\dm[Sx+] [PATTERN] list materialized views\n" +msgstr " \\dm[Sx+] [MUSTER] materialisierte Sichten auflisten\n" #: help.c:249 -msgid " \\di[S+] [PATTERN] list indexes\n" -msgstr " \\di[S+] [MUSTER] Indexe auflisten\n" +msgid " \\dn[Sx+] [PATTERN] list schemas\n" +msgstr " \\dn[Sx+] [MUSTER] Schemas auflisten\n" #: help.c:250 -msgid " \\dl[+] list large objects, same as \\lo_list\n" -msgstr " \\dl[+] Large Objects auflisten, wie \\lo_list\n" - -#: help.c:251 -msgid " \\dL[S+] [PATTERN] list procedural languages\n" -msgstr " \\dL[S+] [MUSTER] prozedurale Sprachen auflisten\n" +msgid "" +" \\do[Sx+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" +" list operators\n" +msgstr "" +" \\do[Sx+] [OPMUST [TYPMUST [TYPMUST]]]\n" +" Operatoren auflisten\n" #: help.c:252 -msgid " \\dm[S+] [PATTERN] list materialized views\n" -msgstr " \\dm[S+] [MUSTER] materialisierte Sichten auflisten\n" +msgid " \\dO[Sx+] [PATTERN] list collations\n" +msgstr " \\dO[Sx+] [MUSTER] Sortierfolgen auflisten\n" #: help.c:253 -msgid " \\dn[S+] [PATTERN] list schemas\n" -msgstr " \\dn[S+] [MUSTER] Schemas auflisten\n" +msgid " \\dp[Sx] [PATTERN] list table, view, and sequence access privileges\n" +msgstr "" +" \\dp[Sx] [MUSTER] Zugriffsprivilegien für Tabellen, Sichten und\n" +" Sequenzen auflisten\n" #: help.c:254 -msgid "" -" \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" -" list operators\n" +msgid " \\dP[itnx+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" msgstr "" -" \\do[S+] [OPMUST [TYPMUST [TYPMUST]]]\n" -" Operatoren auflisten\n" +" \\dP[itnx+] [MUSTER] partitionierte Relationen [nur Indexe/Tabellen]\n" +" auflisten [n=geschachtelt]\n" + +#: help.c:255 +msgid " \\drds[x] [ROLEPTRN [DBPTRN]] list per-database role settings\n" +msgstr "" +" \\drds[x] [ROLLMUST [DBMUST]]\n" +" datenbankspezifische Rolleneinstellungen auflisten\n" #: help.c:256 -msgid " \\dO[S+] [PATTERN] list collations\n" -msgstr " \\dO[S+] [MUSTER] Sortierfolgen auflisten\n" +msgid " \\drg[Sx] [PATTERN] list role grants\n" +msgstr " \\drg[Sx] [MUSTER] Rollen-Grants auflisten\n" #: help.c:257 -msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" -msgstr "" -" \\dp[S] [MUSTER] Zugriffsprivilegien für Tabellen, Sichten und\n" -" Sequenzen auflisten\n" +msgid " \\dRp[x+] [PATTERN] list replication publications\n" +msgstr " \\dRp[x+] [MUSTER] Replikationspublikationen auflisten\n" #: help.c:258 -msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" -msgstr "" -" \\dP[itn+] [MUSTER] partitionierte Relationen [nur Indexe/Tabellen]\n" -" auflisten [n=geschachtelt]\n" +msgid " \\dRs[x+] [PATTERN] list replication subscriptions\n" +msgstr " \\dRs[x+] [MUSTER] Replikationssubskriptionen auflisten\n" #: help.c:259 -msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" -msgstr " \\drds [ROLLMUST [DBMUST]] datenbankspezifische Rolleneinstellungen auflisten\n" +msgid " \\ds[Sx+] [PATTERN] list sequences\n" +msgstr " \\ds[Sx+] [MUSTER] Sequenzen auflisten\n" #: help.c:260 -msgid " \\drg[S] [PATTERN] list role grants\n" -msgstr " \\drg[S] [MUSTER] Rollen-Grants auflisten\n" +msgid " \\dt[Sx+] [PATTERN] list tables\n" +msgstr " \\dt[Sx+] [MUSTER] Tabellen auflisten\n" #: help.c:261 -msgid " \\dRp[+] [PATTERN] list replication publications\n" -msgstr " \\dRp[+] [MUSTER] Replikationspublikationen auflisten\n" +msgid " \\dT[Sx+] [PATTERN] list data types\n" +msgstr " \\dT[Sx+] [MUSTER] Datentypen auflisten\n" #: help.c:262 -msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" -msgstr " \\dRs[+] [MUSTER] Replikationssubskriptionen auflisten\n" +msgid " \\du[Sx+] [PATTERN] list roles\n" +msgstr " \\du[Sx+] [MUSTER] Rollen auflisten\n" #: help.c:263 -msgid " \\ds[S+] [PATTERN] list sequences\n" -msgstr " \\ds[S+] [MUSTER] Sequenzen auflisten\n" +msgid " \\dv[Sx+] [PATTERN] list views\n" +msgstr " \\dv[Sx+] [MUSTER] Sichten auflisten\n" #: help.c:264 -msgid " \\dt[S+] [PATTERN] list tables\n" -msgstr " \\dt[S+] [MUSTER] Tabellen auflisten\n" +msgid " \\dx[x+] [PATTERN] list extensions\n" +msgstr " \\dx[x+] [MUSTER] Erweiterungen auflisten\n" #: help.c:265 -msgid " \\dT[S+] [PATTERN] list data types\n" -msgstr " \\dT[S+] [MUSTER] Datentypen auflisten\n" +msgid " \\dX[x] [PATTERN] list extended statistics\n" +msgstr " \\dX[x] [MUSTER] erweiterte Statistiken auflisten\n" #: help.c:266 -msgid " \\du[S+] [PATTERN] list roles\n" -msgstr " \\du[S+] [MUSTER] Rollen auflisten\n" +msgid " \\dy[x+] [PATTERN] list event triggers\n" +msgstr " \\dy[x+] [MUSTER] Ereignistrigger auflisten\n" #: help.c:267 -msgid " \\dv[S+] [PATTERN] list views\n" -msgstr " \\dv[S+] [MUSTER] Sichten auflisten\n" +msgid " \\l[x+] [PATTERN] list databases\n" +msgstr " \\l[x+] [MUSTER] Datenbanken auflisten\n" #: help.c:268 -msgid " \\dx[+] [PATTERN] list extensions\n" -msgstr " \\dx[+] [MUSTER] Erweiterungen auflisten\n" +msgid " \\sf[+] FUNCNAME show a function's definition\n" +msgstr " \\sf[+] FUNKNAME Funktionsdefinition zeigen\n" #: help.c:269 -msgid " \\dX [PATTERN] list extended statistics\n" -msgstr " \\dX [MUSTER] erweiterte Statistiken auflisten\n" +msgid " \\sv[+] VIEWNAME show a view's definition\n" +msgstr " \\sv[+] SICHTNAME Sichtdefinition zeigen\n" #: help.c:270 -msgid " \\dy[+] [PATTERN] list event triggers\n" -msgstr " \\dy[+] [MUSTER] Ereignistrigger auflisten\n" - -#: help.c:271 -msgid " \\l[+] [PATTERN] list databases\n" -msgstr " \\l[+] [MUSTER] Datenbanken auflisten\n" - -#: help.c:272 -msgid " \\sf[+] FUNCNAME show a function's definition\n" -msgstr " \\sf[+] FUNKNAME Funktionsdefinition zeigen\n" +msgid " \\z[Sx] [PATTERN] same as \\dp\n" +msgstr " \\z[Sx] [MUSTER] äquivalent zu \\dp\n" #: help.c:273 -msgid " \\sv[+] VIEWNAME show a view's definition\n" -msgstr " \\sv[+] SICHTNAME Sichtdefinition zeigen\n" - -#: help.c:274 -msgid " \\z[S] [PATTERN] same as \\dp\n" -msgstr " \\z[S] [MUSTER] äquivalent zu \\dp\n" - -#: help.c:277 msgid "Large Objects\n" msgstr "Large Objects\n" -#: help.c:278 +#: help.c:274 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr "" " \\lo_export LOBOID DATEI\n" " Large Object in Datei schreiben\n" -#: help.c:279 +#: help.c:275 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3191,38 +3400,38 @@ msgstr "" " \\lo_import DATEI [KOMMENTAR]\n" " Large Object aus Datei lesen\n" -#: help.c:281 -msgid " \\lo_list[+] list large objects\n" -msgstr " \\lo_list[+] Large Objects auflisten\n" +#: help.c:277 +msgid " \\lo_list[x+] list large objects\n" +msgstr " \\lo_list[x+] Large Objects auflisten\n" -#: help.c:282 +#: help.c:278 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID Large Object löschen\n" -#: help.c:285 +#: help.c:281 msgid "Formatting\n" msgstr "Formatierung\n" -#: help.c:286 +#: help.c:282 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr "" " \\a zwischen unausgerichtetem und ausgerichtetem Ausgabemodus\n" " umschalten\n" -#: help.c:287 +#: help.c:283 msgid " \\C [STRING] set table title, or unset if none\n" msgstr " \\C [TEXT] Tabellentitel setzen oder löschen\n" -#: help.c:288 +#: help.c:284 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr " \\f [ZEICHEN] Feldtrennzeichen zeigen oder setzen\n" -#: help.c:289 +#: help.c:285 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H HTML-Ausgabemodus umschalten (gegenwärtig %s)\n" -#: help.c:291 +#: help.c:287 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3230,7 +3439,7 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [NAME [WERT]] Tabellenausgabeoption setzen\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3238,31 +3447,31 @@ msgstr "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:298 +#: help.c:294 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] nur Datenzeilen zeigen (gegenwärtig %s)\n" -#: help.c:300 +#: help.c:296 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr " \\T [TEXT] HTML
-Tag-Attribute setzen oder löschen\n" -#: help.c:301 +#: help.c:297 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] erweiterte Ausgabe umschalten (gegenwärtig %s)\n" -#: help.c:302 +#: help.c:298 msgid "auto" msgstr "auto" -#: help.c:305 +#: help.c:301 msgid "Connection\n" msgstr "Verbindung\n" -#: help.c:307 +#: help.c:303 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3271,7 +3480,7 @@ msgstr "" " \\c[onnect] {[DBNAME|- BENUTZER|- HOST|- PORT|-] | conninfo}\n" " mit neuer Datenbank verbinden (aktuell »%s«)\n" -#: help.c:311 +#: help.c:307 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3279,62 +3488,120 @@ msgstr "" " \\c[onnect] {[DBNAME|- BENUTZER|- HOST|- PORT|-] | conninfo}\n" " mit neuer Datenbank verbinden (aktuell keine Verbindung)\n" -#: help.c:313 +#: help.c:309 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo Informationen über aktuelle Verbindung anzeigen\n" -#: help.c:314 +#: help.c:310 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [KODIERUNG] Client-Kodierung zeigen oder setzen\n" -#: help.c:315 +#: help.c:311 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr "" " \\password [BENUTZERNAME]\n" " sicheres Ändern eines Benutzerpasswortes\n" -#: help.c:318 +#: help.c:314 msgid "Operating System\n" msgstr "Betriebssystem\n" -#: help.c:319 +#: help.c:315 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [VERZ] Arbeitsverzeichnis wechseln\n" -#: help.c:320 +#: help.c:316 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVVAR Umgebungsvariable auslesen\n" -#: help.c:321 +#: help.c:317 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv NAME [WERT] Umgebungsvariable setzen oder löschen\n" -#: help.c:322 +#: help.c:318 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] Zeitmessung umschalten (gegenwärtig %s)\n" -#: help.c:324 +#: help.c:320 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr " \\! [BEFEHL] Befehl in Shell ausführen oder interaktive Shell starten\n" -#: help.c:327 +#: help.c:323 msgid "Variables\n" msgstr "Variablen\n" -#: help.c:328 +#: help.c:324 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr " \\prompt [TEXT] NAME interne Variable vom Benutzer abfragen\n" -#: help.c:329 +#: help.c:325 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr " \\set [NAME [WERT]] interne Variable setzen, oder alle anzeigen\n" -#: help.c:330 +#: help.c:326 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NAME interne Variable löschen\n" -#: help.c:369 +#: help.c:329 +msgid "Extended Query Protocol\n" +msgstr "" + +#: help.c:330 +msgid " \\bind [PARAM]... set query parameters\n" +msgstr " \\bind [PARAM]... Anfrageparameter setzen\n" + +#: help.c:331 +msgid "" +" \\bind_named STMT_NAME [PARAM]...\n" +" set query parameters for an existing prepared statement\n" +msgstr "" + +#: help.c:333 +msgid " \\close STMT_NAME close an existing prepared statement\n" +msgstr "" + +#: help.c:334 +msgid " \\endpipeline exit pipeline mode\n" +msgstr " \\endpipeline Pipeline-Modus beenden\n" + +#: help.c:335 +#, fuzzy +#| msgid " -e, --echo show the commands being sent to the server\n" +msgid " \\flush flush output data to the server\n" +msgstr "" +" -e, --echo zeige die Befehle, die an den Server\n" +" gesendet werden\n" + +#: help.c:336 +msgid " \\flushrequest send request to the server to flush its output buffer\n" +msgstr "" + +#: help.c:337 +msgid "" +" \\getresults [NUM_RES] read NUM_RES pending results. All pending results are\n" +" read if no argument is provided\n" +msgstr "" + +#: help.c:339 +#, fuzzy +#| msgid "deallocate a prepared statement" +msgid " \\parse STMT_NAME create a prepared statement\n" +msgstr "gibt einen vorbereiteten Befehl frei" + +#: help.c:340 +msgid " \\sendpipeline send an extended query to an ongoing pipeline\n" +msgstr "" + +#: help.c:341 +msgid " \\startpipeline enter pipeline mode\n" +msgstr " \\startpipeline Pipeline-Modus beginnen\n" + +#: help.c:342 +msgid " \\syncpipeline add a synchronisation point to an ongoing pipeline\n" +msgstr "" + +#: help.c:381 msgid "" "List of specially treated variables\n" "\n" @@ -3342,11 +3609,11 @@ msgstr "" "Liste besonderer Variablen\n" "\n" -#: help.c:371 +#: help.c:383 msgid "psql variables:\n" msgstr "psql-Variablen:\n" -#: help.c:373 +#: help.c:385 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3356,7 +3623,7 @@ msgstr "" " oder \\set NAME WERT innerhalb von psql\n" "\n" -#: help.c:375 +#: help.c:387 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3364,7 +3631,7 @@ msgstr "" " AUTOCOMMIT\n" " wenn gesetzt werden alle erfolgreichen SQL-Befehle automatisch committet\n" -#: help.c:377 +#: help.c:389 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3374,7 +3641,7 @@ msgstr "" " bestimmt, ob SQL-Schlüsselwörter in Groß- oder Kleinschreibung\n" " vervollständigt werden [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:380 +#: help.c:392 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3382,7 +3649,7 @@ msgstr "" " DBNAME\n" " Name der aktuellen Datenbank\n" -#: help.c:382 +#: help.c:394 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3392,7 +3659,7 @@ msgstr "" " kontrolliert, welche Eingaben auf die Standardausgabe geschrieben werden\n" " [all, errors, none, queries]\n" -#: help.c:385 +#: help.c:397 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3402,7 +3669,7 @@ msgstr "" " wenn gesetzt, interne Anfragen, die von Backslash-Befehlen ausgeführt werden,\n" " anzeigen; wenn auf »noexec« gesetzt, nur anzeigen, nicht ausführen\n" -#: help.c:388 +#: help.c:400 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3410,7 +3677,7 @@ msgstr "" " ENCODING\n" " aktuelle Zeichensatzkodierung des Clients\n" -#: help.c:390 +#: help.c:402 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3418,7 +3685,7 @@ msgstr "" " ERROR\n" " »true« wenn die letzte Anfrage fehlgeschlagen ist, sonst »false«\n" -#: help.c:392 +#: help.c:404 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" @@ -3426,7 +3693,7 @@ msgstr "" " FETCH_COUNT\n" " Anzahl auf einmal zu holender und anzuzeigender Zeilen (0 = unbegrenzt)\n" -#: help.c:394 +#: help.c:406 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3434,7 +3701,7 @@ msgstr "" " HIDE_TABLEAM\n" " wenn gesetzt werden Tabellenzugriffsmethoden nicht angezeigt\n" -#: help.c:396 +#: help.c:408 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3442,7 +3709,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " wenn gesetzt werden Kompressionsmethoden nicht angezeigt\n" -#: help.c:398 +#: help.c:410 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3450,7 +3717,7 @@ msgstr "" " HISTCONTROL\n" " kontrolliert Befehlsgeschichte [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:400 +#: help.c:412 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3458,7 +3725,7 @@ msgstr "" " HISTFILE\n" " Dateiname für die Befehlsgeschichte\n" -#: help.c:402 +#: help.c:414 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3466,7 +3733,7 @@ msgstr "" " HISTSIZE\n" " maximale Anzahl der in der Befehlsgeschichte zu speichernden Befehle\n" -#: help.c:404 +#: help.c:416 msgid "" " HOST\n" " the currently connected database server host\n" @@ -3474,7 +3741,7 @@ msgstr "" " HOST\n" " der aktuell verbundene Datenbankserverhost\n" -#: help.c:406 +#: help.c:418 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3482,7 +3749,7 @@ msgstr "" " IGNOREEOF\n" " Anzahl benötigter EOFs um eine interaktive Sitzung zu beenden\n" -#: help.c:408 +#: help.c:420 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3490,7 +3757,7 @@ msgstr "" " LASTOID\n" " Wert der zuletzt beinträchtigten OID\n" -#: help.c:410 +#: help.c:422 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3501,7 +3768,7 @@ msgstr "" " Fehlermeldung und SQLSTATE des letzten Fehlers, oder leer und »000000« wenn\n" " kein Fehler\n" -#: help.c:413 +#: help.c:425 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3510,7 +3777,7 @@ msgstr "" " wenn gesetzt beendet ein Fehler die Transaktion nicht (verwendet implizite\n" " Sicherungspunkte)\n" -#: help.c:415 +#: help.c:427 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3518,7 +3785,7 @@ msgstr "" " ON_ERROR_STOP\n" " Skriptausführung bei Fehler beenden\n" -#: help.c:417 +#: help.c:429 msgid "" " PORT\n" " server port of the current connection\n" @@ -3526,7 +3793,7 @@ msgstr "" " PORT\n" " Serverport der aktuellen Verbindung\n" -#: help.c:419 +#: help.c:431 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3534,7 +3801,7 @@ msgstr "" " PROMPT1\n" " der normale psql-Prompt\n" -#: help.c:421 +#: help.c:433 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" @@ -3542,7 +3809,7 @@ msgstr "" " PROMPT2\n" " der Prompt, wenn eine Anweisung von der vorherigen Zeile fortgesetzt wird\n" -#: help.c:423 +#: help.c:435 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3550,7 +3817,7 @@ msgstr "" " PROMPT3\n" " der Prompt während COPY ... FROM STDIN\n" -#: help.c:425 +#: help.c:437 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3558,7 +3825,7 @@ msgstr "" " QUIET\n" " stille Ausführung (wie Option -q)\n" -#: help.c:427 +#: help.c:439 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3566,7 +3833,7 @@ msgstr "" " ROW_COUNT\n" " Anzahl der von der letzten Anfrage beeinträchtigten Zeilen, oder 0\n" -#: help.c:429 +#: help.c:441 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3576,7 +3843,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " Serverversion (kurze Zeichenkette oder numerisches Format)\n" -#: help.c:432 +#: help.c:444 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3584,7 +3851,7 @@ msgstr "" " SHELL_ERROR\n" " »true« wenn der letzte Shell-Befehl fehlgeschlagen ist, sonst »false«\n" -#: help.c:434 +#: help.c:446 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3592,7 +3859,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " Statuscode des letzten Shell-Befehls\n" -#: help.c:436 +#: help.c:448 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3600,7 +3867,7 @@ msgstr "" " SHOW_ALL_RESULTS\n" " alle Ergebnisse einer kombinierten Anfrage (\\;) anzeigen statt nur das letzte\n" -#: help.c:438 +#: help.c:450 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3609,7 +3876,7 @@ msgstr "" " kontrolliert die Anzeige von Kontextinformationen in Meldungen\n" " [never, errors, always]\n" -#: help.c:440 +#: help.c:452 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3617,7 +3884,7 @@ msgstr "" " SINGLELINE\n" " wenn gesetzt beendet Zeilenende die SQL-Anweisung (wie Option -S)\n" -#: help.c:442 +#: help.c:454 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3625,7 +3892,7 @@ msgstr "" " SINGLESTEP\n" " Einzelschrittmodus (wie Option -s)\n" -#: help.c:444 +#: help.c:456 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3633,7 +3900,7 @@ msgstr "" " SQLSTATE\n" " SQLSTATE der letzten Anfrage, oder »00000« wenn kein Fehler\n" -#: help.c:446 +#: help.c:458 msgid "" " USER\n" " the currently connected database user\n" @@ -3641,7 +3908,7 @@ msgstr "" " USER\n" " der aktuell verbundene Datenbankbenutzer\n" -#: help.c:448 +#: help.c:460 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3650,7 +3917,7 @@ msgstr "" " kontrolliert wieviele Details in Fehlermeldungen enthalten sind\n" " [default, verbose, terse, sqlstate]\n" -#: help.c:450 +#: help.c:462 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3662,7 +3929,13 @@ msgstr "" " VERSION_NUM\n" " Version von psql (lange Zeichenkette, kurze Zeichenkette oder numerisch)\n" -#: help.c:455 +#: help.c:466 +msgid "" +" WATCH_INTERVAL\n" +" if set to a number, overrides the default two second \\watch interval\n" +msgstr "" + +#: help.c:469 msgid "" "\n" "Display settings:\n" @@ -3670,7 +3943,7 @@ msgstr "" "\n" "Anzeigeeinstellungen:\n" -#: help.c:457 +#: help.c:471 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3680,7 +3953,7 @@ msgstr "" " oder \\pset NAME [WERT] innerhalb von psql\n" "\n" -#: help.c:459 +#: help.c:473 msgid "" " border\n" " border style (number)\n" @@ -3688,7 +3961,7 @@ msgstr "" " border\n" " Rahmenstil (Zahl)\n" -#: help.c:461 +#: help.c:475 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3696,7 +3969,7 @@ msgstr "" " columns\n" " Zielbreite für das Format »wrapped«\n" -#: help.c:463 +#: help.c:477 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" @@ -3704,7 +3977,7 @@ msgstr "" " expanded (oder x)\n" " erweiterte Ausgabe [on, off, auto]\n" -#: help.c:465 +#: help.c:479 #, c-format msgid "" " fieldsep\n" @@ -3713,7 +3986,7 @@ msgstr "" " fieldsep\n" " Feldtrennzeichen für unausgerichteten Ausgabemodus (Standard »%s«)\n" -#: help.c:468 +#: help.c:482 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3721,7 +3994,7 @@ msgstr "" " fieldsep_zero\n" " Feldtrennzeichen für unausgerichteten Ausgabemodus auf Null-Byte setzen\n" -#: help.c:470 +#: help.c:484 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3729,7 +4002,7 @@ msgstr "" " footer\n" " Tabellenfußzeile ein- oder auschalten [on, off]\n" -#: help.c:472 +#: help.c:486 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3737,7 +4010,7 @@ msgstr "" " format\n" " Ausgabeformat setzen [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:474 +#: help.c:488 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3745,7 +4018,7 @@ msgstr "" " linestyle\n" " Rahmenlinienstil setzen [ascii, old-ascii, unicode]\n" -#: help.c:476 +#: help.c:490 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3753,7 +4026,7 @@ msgstr "" " null\n" " setzt die Zeichenkette, die anstelle eines NULL-Wertes ausgegeben wird\n" -#: help.c:478 +#: help.c:492 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" @@ -3762,7 +4035,7 @@ msgstr "" " Verwendung eines Locale-spezifischen Zeichens zur Trennung von Zifferngruppen\n" " einschalten [on, off]\n" -#: help.c:480 +#: help.c:494 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3770,7 +4043,7 @@ msgstr "" " pager\n" " kontrolliert Verwendung eines externen Pager-Programms [yes, no, always]\n" -#: help.c:482 +#: help.c:496 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3778,7 +4051,7 @@ msgstr "" " recordsep\n" " Satztrennzeichen für unausgerichteten Ausgabemodus\n" -#: help.c:484 +#: help.c:498 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3786,7 +4059,7 @@ msgstr "" " recordsep_zero\n" " Satztrennzeichen für unausgerichteten Ausgabemodus auf Null-Byte setzen\n" -#: help.c:486 +#: help.c:500 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3796,7 +4069,7 @@ msgstr "" " Attribute für das »table«-Tag im Format »html« oder proportionale\n" " Spaltenbreite für links ausgerichtete Datentypen im Format »latex-longtable«\n" -#: help.c:489 +#: help.c:503 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -3804,7 +4077,7 @@ msgstr "" " title\n" " setzt den Titel darauffolgend ausgegebener Tabellen\n" -#: help.c:491 +#: help.c:505 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -3812,7 +4085,7 @@ msgstr "" " tuples_only\n" " wenn gesetzt werden nur die eigentlichen Tabellendaten gezeigt\n" -#: help.c:493 +#: help.c:507 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3824,7 +4097,17 @@ msgstr "" " unicode_header_linestyle\n" " setzt den Stil für Unicode-Linien [single, double]\n" -#: help.c:498 +#: help.c:511 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" setzt die maximale Breite der Kopfzeile für die erweiterte Ausgabe\n" +" [full, column, page, ganze Zahl]\n" + +#: help.c:515 msgid "" "\n" "Environment variables:\n" @@ -3832,7 +4115,7 @@ msgstr "" "\n" "Umgebungsvariablen:\n" -#: help.c:502 +#: help.c:519 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3842,7 +4125,7 @@ msgstr "" " oder \\setenv NAME [WERT] innerhalb von psql\n" "\n" -#: help.c:504 +#: help.c:521 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3854,7 +4137,7 @@ msgstr "" " oder \\setenv NAME [WERT] innerhalb von psql\n" "\n" -#: help.c:507 +#: help.c:524 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -3862,7 +4145,7 @@ msgstr "" " COLUMNS\n" " Anzahl Spalten im Format »wrapped«\n" -#: help.c:509 +#: help.c:526 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -3870,7 +4153,7 @@ msgstr "" " PGAPPNAME\n" " wie Verbindungsparameter »application_name«\n" -#: help.c:511 +#: help.c:528 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -3878,7 +4161,7 @@ msgstr "" " PGDATABASE\n" " wie Verbindungsparameter »dbname«\n" -#: help.c:513 +#: help.c:530 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -3886,7 +4169,7 @@ msgstr "" " PGHOST\n" " wie Verbindungsparameter »host«\n" -#: help.c:515 +#: help.c:532 msgid "" " PGPASSFILE\n" " password file name\n" @@ -3894,7 +4177,7 @@ msgstr "" " PGPASSFILE\n" " Name der Passwortdatei\n" -#: help.c:517 +#: help.c:534 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -3902,7 +4185,7 @@ msgstr "" " PGPASSWORD\n" " Verbindungspasswort (nicht empfohlen)\n" -#: help.c:519 +#: help.c:536 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -3910,7 +4193,7 @@ msgstr "" " PGPORT\n" " wie Verbindungsparameter »port«\n" -#: help.c:521 +#: help.c:538 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -3918,7 +4201,7 @@ msgstr "" " PGUSER\n" " wie Verbindungsparameter »user«\n" -#: help.c:523 +#: help.c:540 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3926,7 +4209,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " Editor für Befehle \\e, \\ef und \\ev\n" -#: help.c:525 +#: help.c:542 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -3934,7 +4217,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " wie die Zeilennummer beim Aufruf des Editors angegeben wird\n" -#: help.c:527 +#: help.c:544 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -3942,7 +4225,7 @@ msgstr "" " PSQL_HISTORY\n" " alternativer Pfad für History-Datei\n" -#: help.c:529 +#: help.c:546 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -3950,7 +4233,7 @@ msgstr "" " PSQL_PAGER, PAGER\n" " Name des externen Pager-Programms\n" -#: help.c:532 +#: help.c:549 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -3958,7 +4241,7 @@ msgstr "" " PSQL_WATCH_PAGER\n" " Name des externen Pager-Programms für \\watch\n" -#: help.c:535 +#: help.c:552 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -3966,7 +4249,7 @@ msgstr "" " PSQLRC\n" " alternativer Pfad für .psqlrc-Datei des Benutzers\n" -#: help.c:537 +#: help.c:554 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -3974,7 +4257,7 @@ msgstr "" " SHELL\n" " Shell für den Befehl \\!\n" -#: help.c:539 +#: help.c:556 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -3982,11 +4265,11 @@ msgstr "" " TMPDIR\n" " Verzeichnis für temporäre Dateien\n" -#: help.c:599 +#: help.c:616 msgid "Available help:\n" msgstr "Verfügbare Hilfe:\n" -#: help.c:694 +#: help.c:711 #, c-format msgid "" "Command: %s\n" @@ -4005,7 +4288,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:717 +#: help.c:734 #, c-format msgid "" "No help available for \"%s\".\n" @@ -4112,12 +4395,12 @@ msgstr "Anfrage ignoriert; verwenden Sie \\endif oder Strg-C um den aktuellen \\ msgid "reached EOF without finding closing \\endif(s)" msgstr "Dateiende erreicht, aber schließendes \\endif fehlt" -#: psqlscanslash.l:642 +#: psqlscanslash.l:633 #, c-format msgid "unterminated quoted string" msgstr "Zeichenkette in Anführungszeichen nicht abgeschlossen" -#: psqlscanslash.l:842 +#: psqlscanslash.l:834 #, c-format msgid "%s: out of memory" msgstr "%s: Speicher aufgebraucht" @@ -4125,2470 +4408,2477 @@ msgstr "%s: Speicher aufgebraucht" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:240 -#: sql_help.c:242 sql_help.c:243 sql_help.c:245 sql_help.c:247 sql_help.c:250 -#: sql_help.c:252 sql_help.c:254 sql_help.c:256 sql_help.c:268 sql_help.c:269 -#: sql_help.c:270 sql_help.c:272 sql_help.c:321 sql_help.c:323 sql_help.c:325 -#: sql_help.c:327 sql_help.c:396 sql_help.c:401 sql_help.c:403 sql_help.c:445 -#: sql_help.c:447 sql_help.c:450 sql_help.c:452 sql_help.c:521 sql_help.c:526 -#: sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:595 sql_help.c:597 -#: sql_help.c:599 sql_help.c:601 sql_help.c:603 sql_help.c:606 sql_help.c:608 -#: sql_help.c:611 sql_help.c:622 sql_help.c:624 sql_help.c:668 sql_help.c:670 -#: sql_help.c:672 sql_help.c:675 sql_help.c:677 sql_help.c:679 sql_help.c:720 -#: sql_help.c:724 sql_help.c:728 sql_help.c:749 sql_help.c:752 sql_help.c:755 -#: sql_help.c:784 sql_help.c:796 sql_help.c:804 sql_help.c:807 sql_help.c:810 -#: sql_help.c:825 sql_help.c:828 sql_help.c:857 sql_help.c:862 sql_help.c:867 -#: sql_help.c:872 sql_help.c:877 sql_help.c:904 sql_help.c:906 sql_help.c:908 -#: sql_help.c:910 sql_help.c:913 sql_help.c:915 sql_help.c:962 sql_help.c:1007 -#: sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 sql_help.c:1027 -#: sql_help.c:1046 sql_help.c:1057 sql_help.c:1059 sql_help.c:1079 -#: sql_help.c:1089 sql_help.c:1090 sql_help.c:1092 sql_help.c:1094 -#: sql_help.c:1106 sql_help.c:1110 sql_help.c:1112 sql_help.c:1124 -#: sql_help.c:1126 sql_help.c:1128 sql_help.c:1130 sql_help.c:1149 -#: sql_help.c:1151 sql_help.c:1155 sql_help.c:1159 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1167 sql_help.c:1168 sql_help.c:1171 -#: sql_help.c:1174 sql_help.c:1176 sql_help.c:1323 sql_help.c:1325 -#: sql_help.c:1328 sql_help.c:1331 sql_help.c:1333 sql_help.c:1335 -#: sql_help.c:1338 sql_help.c:1341 sql_help.c:1343 sql_help.c:1349 -#: sql_help.c:1473 sql_help.c:1475 sql_help.c:1477 sql_help.c:1480 -#: sql_help.c:1501 sql_help.c:1504 sql_help.c:1507 sql_help.c:1510 -#: sql_help.c:1514 sql_help.c:1516 sql_help.c:1518 sql_help.c:1520 -#: sql_help.c:1534 sql_help.c:1537 sql_help.c:1539 sql_help.c:1541 -#: sql_help.c:1551 sql_help.c:1553 sql_help.c:1563 sql_help.c:1565 -#: sql_help.c:1575 sql_help.c:1578 sql_help.c:1601 sql_help.c:1603 -#: sql_help.c:1605 sql_help.c:1607 sql_help.c:1610 sql_help.c:1612 -#: sql_help.c:1615 sql_help.c:1618 sql_help.c:1669 sql_help.c:1712 -#: sql_help.c:1715 sql_help.c:1717 sql_help.c:1719 sql_help.c:1722 -#: sql_help.c:1724 sql_help.c:1726 sql_help.c:1729 sql_help.c:1779 -#: sql_help.c:1795 sql_help.c:2028 sql_help.c:2097 sql_help.c:2116 -#: sql_help.c:2129 sql_help.c:2187 sql_help.c:2195 sql_help.c:2205 -#: sql_help.c:2233 sql_help.c:2266 sql_help.c:2284 sql_help.c:2312 -#: sql_help.c:2423 sql_help.c:2469 sql_help.c:2494 sql_help.c:2517 -#: sql_help.c:2521 sql_help.c:2555 sql_help.c:2575 sql_help.c:2597 -#: sql_help.c:2611 sql_help.c:2632 sql_help.c:2661 sql_help.c:2694 -#: sql_help.c:2717 sql_help.c:2764 sql_help.c:3062 sql_help.c:3075 -#: sql_help.c:3092 sql_help.c:3108 sql_help.c:3148 sql_help.c:3202 -#: sql_help.c:3206 sql_help.c:3208 sql_help.c:3215 sql_help.c:3234 -#: sql_help.c:3261 sql_help.c:3296 sql_help.c:3308 sql_help.c:3317 -#: sql_help.c:3361 sql_help.c:3375 sql_help.c:3403 sql_help.c:3411 -#: sql_help.c:3423 sql_help.c:3433 sql_help.c:3441 sql_help.c:3449 -#: sql_help.c:3457 sql_help.c:3465 sql_help.c:3474 sql_help.c:3485 -#: sql_help.c:3493 sql_help.c:3501 sql_help.c:3509 sql_help.c:3517 -#: sql_help.c:3527 sql_help.c:3536 sql_help.c:3545 sql_help.c:3553 -#: sql_help.c:3563 sql_help.c:3574 sql_help.c:3582 sql_help.c:3591 -#: sql_help.c:3602 sql_help.c:3611 sql_help.c:3619 sql_help.c:3627 -#: sql_help.c:3635 sql_help.c:3643 sql_help.c:3651 sql_help.c:3659 -#: sql_help.c:3667 sql_help.c:3675 sql_help.c:3683 sql_help.c:3691 -#: sql_help.c:3708 sql_help.c:3717 sql_help.c:3725 sql_help.c:3742 -#: sql_help.c:3757 sql_help.c:4070 sql_help.c:4191 sql_help.c:4220 -#: sql_help.c:4236 sql_help.c:4238 sql_help.c:4742 sql_help.c:4790 -#: sql_help.c:4949 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:259 +#: sql_help.c:261 sql_help.c:262 sql_help.c:264 sql_help.c:266 sql_help.c:269 +#: sql_help.c:271 sql_help.c:273 sql_help.c:275 sql_help.c:290 sql_help.c:291 +#: sql_help.c:292 sql_help.c:294 sql_help.c:343 sql_help.c:345 sql_help.c:347 +#: sql_help.c:349 sql_help.c:418 sql_help.c:423 sql_help.c:425 sql_help.c:467 +#: sql_help.c:469 sql_help.c:472 sql_help.c:474 sql_help.c:543 sql_help.c:548 +#: sql_help.c:553 sql_help.c:558 sql_help.c:563 sql_help.c:617 sql_help.c:619 +#: sql_help.c:621 sql_help.c:623 sql_help.c:625 sql_help.c:628 sql_help.c:630 +#: sql_help.c:633 sql_help.c:644 sql_help.c:646 sql_help.c:690 sql_help.c:692 +#: sql_help.c:694 sql_help.c:697 sql_help.c:699 sql_help.c:701 sql_help.c:742 +#: sql_help.c:746 sql_help.c:750 sql_help.c:771 sql_help.c:774 sql_help.c:777 +#: sql_help.c:806 sql_help.c:818 sql_help.c:826 sql_help.c:829 sql_help.c:832 +#: sql_help.c:847 sql_help.c:850 sql_help.c:879 sql_help.c:884 sql_help.c:889 +#: sql_help.c:894 sql_help.c:899 sql_help.c:926 sql_help.c:928 sql_help.c:930 +#: sql_help.c:932 sql_help.c:935 sql_help.c:937 sql_help.c:984 sql_help.c:1029 +#: sql_help.c:1034 sql_help.c:1039 sql_help.c:1044 sql_help.c:1049 +#: sql_help.c:1068 sql_help.c:1079 sql_help.c:1081 sql_help.c:1102 +#: sql_help.c:1112 sql_help.c:1113 sql_help.c:1115 sql_help.c:1117 +#: sql_help.c:1129 sql_help.c:1133 sql_help.c:1135 sql_help.c:1147 +#: sql_help.c:1149 sql_help.c:1151 sql_help.c:1153 sql_help.c:1172 +#: sql_help.c:1174 sql_help.c:1178 sql_help.c:1182 sql_help.c:1186 +#: sql_help.c:1189 sql_help.c:1190 sql_help.c:1191 sql_help.c:1194 +#: sql_help.c:1197 sql_help.c:1199 sql_help.c:1341 sql_help.c:1343 +#: sql_help.c:1346 sql_help.c:1349 sql_help.c:1351 sql_help.c:1353 +#: sql_help.c:1356 sql_help.c:1359 sql_help.c:1487 sql_help.c:1489 +#: sql_help.c:1491 sql_help.c:1494 sql_help.c:1515 sql_help.c:1518 +#: sql_help.c:1521 sql_help.c:1524 sql_help.c:1528 sql_help.c:1530 +#: sql_help.c:1532 sql_help.c:1534 sql_help.c:1548 sql_help.c:1551 +#: sql_help.c:1553 sql_help.c:1555 sql_help.c:1565 sql_help.c:1567 +#: sql_help.c:1577 sql_help.c:1579 sql_help.c:1589 sql_help.c:1592 +#: sql_help.c:1615 sql_help.c:1617 sql_help.c:1619 sql_help.c:1621 +#: sql_help.c:1624 sql_help.c:1626 sql_help.c:1629 sql_help.c:1632 +#: sql_help.c:1683 sql_help.c:1726 sql_help.c:1729 sql_help.c:1731 +#: sql_help.c:1733 sql_help.c:1736 sql_help.c:1738 sql_help.c:1740 +#: sql_help.c:1743 sql_help.c:1793 sql_help.c:1809 sql_help.c:2044 +#: sql_help.c:2113 sql_help.c:2132 sql_help.c:2145 sql_help.c:2203 +#: sql_help.c:2211 sql_help.c:2221 sql_help.c:2249 sql_help.c:2282 +#: sql_help.c:2300 sql_help.c:2328 sql_help.c:2451 sql_help.c:2497 +#: sql_help.c:2522 sql_help.c:2545 sql_help.c:2549 sql_help.c:2583 +#: sql_help.c:2603 sql_help.c:2625 sql_help.c:2639 sql_help.c:2660 +#: sql_help.c:2689 sql_help.c:2722 sql_help.c:2745 sql_help.c:2794 +#: sql_help.c:3098 sql_help.c:3111 sql_help.c:3128 sql_help.c:3144 +#: sql_help.c:3184 sql_help.c:3238 sql_help.c:3242 sql_help.c:3244 +#: sql_help.c:3251 sql_help.c:3270 sql_help.c:3297 sql_help.c:3332 +#: sql_help.c:3344 sql_help.c:3353 sql_help.c:3399 sql_help.c:3413 +#: sql_help.c:3441 sql_help.c:3449 sql_help.c:3461 sql_help.c:3471 +#: sql_help.c:3479 sql_help.c:3487 sql_help.c:3495 sql_help.c:3503 +#: sql_help.c:3512 sql_help.c:3523 sql_help.c:3531 sql_help.c:3539 +#: sql_help.c:3547 sql_help.c:3555 sql_help.c:3565 sql_help.c:3574 +#: sql_help.c:3583 sql_help.c:3591 sql_help.c:3601 sql_help.c:3612 +#: sql_help.c:3620 sql_help.c:3629 sql_help.c:3640 sql_help.c:3649 +#: sql_help.c:3657 sql_help.c:3665 sql_help.c:3673 sql_help.c:3681 +#: sql_help.c:3689 sql_help.c:3697 sql_help.c:3705 sql_help.c:3713 +#: sql_help.c:3721 sql_help.c:3729 sql_help.c:3746 sql_help.c:3755 +#: sql_help.c:3763 sql_help.c:3780 sql_help.c:3795 sql_help.c:4110 +#: sql_help.c:4233 sql_help.c:4262 sql_help.c:4278 sql_help.c:4280 +#: sql_help.c:4784 sql_help.c:4832 sql_help.c:4991 msgid "name" msgstr "Name" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:332 sql_help.c:1872 -#: sql_help.c:3376 sql_help.c:4509 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:354 sql_help.c:1886 +#: sql_help.c:3414 sql_help.c:4551 msgid "aggregate_signature" msgstr "Aggregatsignatur" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:255 -#: sql_help.c:273 sql_help.c:404 sql_help.c:451 sql_help.c:530 sql_help.c:578 -#: sql_help.c:596 sql_help.c:623 sql_help.c:676 sql_help.c:751 sql_help.c:806 -#: sql_help.c:827 sql_help.c:866 sql_help.c:916 sql_help.c:963 sql_help.c:1016 -#: sql_help.c:1048 sql_help.c:1058 sql_help.c:1093 sql_help.c:1113 -#: sql_help.c:1127 sql_help.c:1177 sql_help.c:1332 sql_help.c:1474 -#: sql_help.c:1517 sql_help.c:1538 sql_help.c:1552 sql_help.c:1564 -#: sql_help.c:1577 sql_help.c:1604 sql_help.c:1670 sql_help.c:1723 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:274 +#: sql_help.c:295 sql_help.c:426 sql_help.c:473 sql_help.c:552 sql_help.c:600 +#: sql_help.c:618 sql_help.c:645 sql_help.c:698 sql_help.c:773 sql_help.c:828 +#: sql_help.c:849 sql_help.c:888 sql_help.c:938 sql_help.c:985 sql_help.c:1038 +#: sql_help.c:1070 sql_help.c:1080 sql_help.c:1116 sql_help.c:1136 +#: sql_help.c:1150 sql_help.c:1200 sql_help.c:1350 sql_help.c:1488 +#: sql_help.c:1531 sql_help.c:1552 sql_help.c:1566 sql_help.c:1578 +#: sql_help.c:1591 sql_help.c:1618 sql_help.c:1684 sql_help.c:1737 msgid "new_name" msgstr "neuer_Name" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:487 sql_help.c:535 sql_help.c:625 -#: sql_help.c:634 sql_help.c:699 sql_help.c:723 sql_help.c:754 sql_help.c:809 -#: sql_help.c:871 sql_help.c:914 sql_help.c:1021 sql_help.c:1060 -#: sql_help.c:1091 sql_help.c:1111 sql_help.c:1125 sql_help.c:1175 -#: sql_help.c:1408 sql_help.c:1476 sql_help.c:1519 sql_help.c:1540 -#: sql_help.c:1602 sql_help.c:1718 sql_help.c:3048 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:272 +#: sql_help.c:293 sql_help.c:424 sql_help.c:509 sql_help.c:557 sql_help.c:647 +#: sql_help.c:656 sql_help.c:721 sql_help.c:745 sql_help.c:776 sql_help.c:831 +#: sql_help.c:893 sql_help.c:936 sql_help.c:1043 sql_help.c:1082 +#: sql_help.c:1114 sql_help.c:1134 sql_help.c:1148 sql_help.c:1198 +#: sql_help.c:1417 sql_help.c:1490 sql_help.c:1533 sql_help.c:1554 +#: sql_help.c:1616 sql_help.c:1732 sql_help.c:3084 msgid "new_owner" msgstr "neuer_Eigentümer" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:257 sql_help.c:324 -#: sql_help.c:453 sql_help.c:540 sql_help.c:678 sql_help.c:727 sql_help.c:757 -#: sql_help.c:812 sql_help.c:876 sql_help.c:1026 sql_help.c:1095 -#: sql_help.c:1129 sql_help.c:1334 sql_help.c:1521 sql_help.c:1542 -#: sql_help.c:1554 sql_help.c:1566 sql_help.c:1606 sql_help.c:1725 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:276 sql_help.c:346 +#: sql_help.c:475 sql_help.c:562 sql_help.c:700 sql_help.c:749 sql_help.c:779 +#: sql_help.c:834 sql_help.c:898 sql_help.c:1048 sql_help.c:1118 +#: sql_help.c:1152 sql_help.c:1352 sql_help.c:1535 sql_help.c:1556 +#: sql_help.c:1568 sql_help.c:1580 sql_help.c:1620 sql_help.c:1739 msgid "new_schema" msgstr "neues_Schema" -#: sql_help.c:44 sql_help.c:1936 sql_help.c:3377 sql_help.c:4538 +#: sql_help.c:44 sql_help.c:1950 sql_help.c:3415 sql_help.c:4580 msgid "where aggregate_signature is:" msgstr "wobei Aggregatsignatur Folgendes ist:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:858 -#: sql_help.c:863 sql_help.c:868 sql_help.c:873 sql_help.c:878 sql_help.c:1008 -#: sql_help.c:1013 sql_help.c:1018 sql_help.c:1023 sql_help.c:1028 -#: sql_help.c:1890 sql_help.c:1907 sql_help.c:1913 sql_help.c:1937 -#: sql_help.c:1940 sql_help.c:1943 sql_help.c:2098 sql_help.c:2117 -#: sql_help.c:2120 sql_help.c:2424 sql_help.c:2633 sql_help.c:3378 -#: sql_help.c:3381 sql_help.c:3384 sql_help.c:3475 sql_help.c:3564 -#: sql_help.c:3592 sql_help.c:3945 sql_help.c:4408 sql_help.c:4515 -#: sql_help.c:4522 sql_help.c:4528 sql_help.c:4539 sql_help.c:4542 -#: sql_help.c:4545 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:364 sql_help.c:377 +#: sql_help.c:381 sql_help.c:397 sql_help.c:400 sql_help.c:403 sql_help.c:544 +#: sql_help.c:549 sql_help.c:554 sql_help.c:559 sql_help.c:564 sql_help.c:880 +#: sql_help.c:885 sql_help.c:890 sql_help.c:895 sql_help.c:900 sql_help.c:1030 +#: sql_help.c:1035 sql_help.c:1040 sql_help.c:1045 sql_help.c:1050 +#: sql_help.c:1904 sql_help.c:1921 sql_help.c:1927 sql_help.c:1951 +#: sql_help.c:1954 sql_help.c:1957 sql_help.c:2114 sql_help.c:2133 +#: sql_help.c:2136 sql_help.c:2452 sql_help.c:2661 sql_help.c:3416 +#: sql_help.c:3419 sql_help.c:3422 sql_help.c:3513 sql_help.c:3602 +#: sql_help.c:3630 sql_help.c:3983 sql_help.c:4450 sql_help.c:4557 +#: sql_help.c:4564 sql_help.c:4570 sql_help.c:4581 sql_help.c:4584 +#: sql_help.c:4587 msgid "argmode" msgstr "Argmodus" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:343 sql_help.c:356 -#: sql_help.c:360 sql_help.c:376 sql_help.c:379 sql_help.c:382 sql_help.c:523 -#: sql_help.c:528 sql_help.c:533 sql_help.c:538 sql_help.c:543 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:874 sql_help.c:879 sql_help.c:1009 -#: sql_help.c:1014 sql_help.c:1019 sql_help.c:1024 sql_help.c:1029 -#: sql_help.c:1891 sql_help.c:1908 sql_help.c:1914 sql_help.c:1938 -#: sql_help.c:1941 sql_help.c:1944 sql_help.c:2099 sql_help.c:2118 -#: sql_help.c:2121 sql_help.c:2425 sql_help.c:2634 sql_help.c:3379 -#: sql_help.c:3382 sql_help.c:3385 sql_help.c:3476 sql_help.c:3565 -#: sql_help.c:3593 sql_help.c:4516 sql_help.c:4523 sql_help.c:4529 -#: sql_help.c:4540 sql_help.c:4543 sql_help.c:4546 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:365 sql_help.c:378 +#: sql_help.c:382 sql_help.c:398 sql_help.c:401 sql_help.c:404 sql_help.c:545 +#: sql_help.c:550 sql_help.c:555 sql_help.c:560 sql_help.c:565 sql_help.c:881 +#: sql_help.c:886 sql_help.c:891 sql_help.c:896 sql_help.c:901 sql_help.c:1031 +#: sql_help.c:1036 sql_help.c:1041 sql_help.c:1046 sql_help.c:1051 +#: sql_help.c:1905 sql_help.c:1922 sql_help.c:1928 sql_help.c:1952 +#: sql_help.c:1955 sql_help.c:1958 sql_help.c:2115 sql_help.c:2134 +#: sql_help.c:2137 sql_help.c:2453 sql_help.c:2662 sql_help.c:3417 +#: sql_help.c:3420 sql_help.c:3423 sql_help.c:3514 sql_help.c:3603 +#: sql_help.c:3631 sql_help.c:4558 sql_help.c:4565 sql_help.c:4571 +#: sql_help.c:4582 sql_help.c:4585 sql_help.c:4588 msgid "argname" msgstr "Argname" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:344 sql_help.c:357 -#: sql_help.c:361 sql_help.c:377 sql_help.c:380 sql_help.c:383 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:544 sql_help.c:860 -#: sql_help.c:865 sql_help.c:870 sql_help.c:875 sql_help.c:880 sql_help.c:1010 -#: sql_help.c:1015 sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 -#: sql_help.c:1892 sql_help.c:1909 sql_help.c:1915 sql_help.c:1939 -#: sql_help.c:1942 sql_help.c:1945 sql_help.c:2426 sql_help.c:2635 -#: sql_help.c:3380 sql_help.c:3383 sql_help.c:3386 sql_help.c:3477 -#: sql_help.c:3566 sql_help.c:3594 sql_help.c:4517 sql_help.c:4524 -#: sql_help.c:4530 sql_help.c:4541 sql_help.c:4544 sql_help.c:4547 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:366 sql_help.c:379 +#: sql_help.c:383 sql_help.c:399 sql_help.c:402 sql_help.c:405 sql_help.c:546 +#: sql_help.c:551 sql_help.c:556 sql_help.c:561 sql_help.c:566 sql_help.c:882 +#: sql_help.c:887 sql_help.c:892 sql_help.c:897 sql_help.c:902 sql_help.c:1032 +#: sql_help.c:1037 sql_help.c:1042 sql_help.c:1047 sql_help.c:1052 +#: sql_help.c:1906 sql_help.c:1923 sql_help.c:1929 sql_help.c:1953 +#: sql_help.c:1956 sql_help.c:1959 sql_help.c:2454 sql_help.c:2663 +#: sql_help.c:3418 sql_help.c:3421 sql_help.c:3424 sql_help.c:3515 +#: sql_help.c:3604 sql_help.c:3632 sql_help.c:4559 sql_help.c:4566 +#: sql_help.c:4572 sql_help.c:4583 sql_help.c:4586 sql_help.c:4589 msgid "argtype" msgstr "Argtyp" -#: sql_help.c:114 sql_help.c:399 sql_help.c:476 sql_help.c:488 sql_help.c:957 -#: sql_help.c:1108 sql_help.c:1535 sql_help.c:1664 sql_help.c:1696 -#: sql_help.c:1748 sql_help.c:1807 sql_help.c:1996 sql_help.c:2003 -#: sql_help.c:2315 sql_help.c:2365 sql_help.c:2372 sql_help.c:2381 -#: sql_help.c:2470 sql_help.c:2695 sql_help.c:2786 sql_help.c:3077 -#: sql_help.c:3262 sql_help.c:3284 sql_help.c:3424 sql_help.c:3781 -#: sql_help.c:3989 sql_help.c:4235 sql_help.c:4237 sql_help.c:5015 +#: sql_help.c:114 sql_help.c:421 sql_help.c:498 sql_help.c:510 sql_help.c:979 +#: sql_help.c:1131 sql_help.c:1549 sql_help.c:1678 sql_help.c:1710 +#: sql_help.c:1762 sql_help.c:1821 sql_help.c:2011 sql_help.c:2018 +#: sql_help.c:2331 sql_help.c:2389 sql_help.c:2398 sql_help.c:2407 +#: sql_help.c:2498 sql_help.c:2723 sql_help.c:2816 sql_help.c:3113 +#: sql_help.c:3298 sql_help.c:3320 sql_help.c:3462 sql_help.c:3819 +#: sql_help.c:4027 sql_help.c:4277 sql_help.c:4279 sql_help.c:5059 msgid "option" msgstr "Option" -#: sql_help.c:115 sql_help.c:958 sql_help.c:1665 sql_help.c:2471 -#: sql_help.c:2696 sql_help.c:3263 sql_help.c:3425 +#: sql_help.c:115 sql_help.c:980 sql_help.c:1679 sql_help.c:2499 +#: sql_help.c:2724 sql_help.c:3299 sql_help.c:3463 msgid "where option can be:" msgstr "wobei Option Folgendes sein kann:" -#: sql_help.c:116 sql_help.c:2247 +#: sql_help.c:116 sql_help.c:2263 msgid "allowconn" msgstr "allowconn" -#: sql_help.c:117 sql_help.c:959 sql_help.c:1666 sql_help.c:2248 -#: sql_help.c:2472 sql_help.c:2697 sql_help.c:3264 +#: sql_help.c:117 sql_help.c:981 sql_help.c:1680 sql_help.c:2264 +#: sql_help.c:2500 sql_help.c:2725 sql_help.c:3300 msgid "connlimit" msgstr "Verbindungslimit" -#: sql_help.c:118 sql_help.c:2249 +#: sql_help.c:118 sql_help.c:2265 msgid "istemplate" msgstr "istemplate" -#: sql_help.c:124 sql_help.c:613 sql_help.c:681 sql_help.c:695 sql_help.c:1337 -#: sql_help.c:1401 sql_help.c:4241 +#: sql_help.c:124 sql_help.c:635 sql_help.c:703 sql_help.c:717 sql_help.c:1355 +#: sql_help.c:1410 sql_help.c:4283 msgid "new_tablespace" msgstr "neuer_Tablespace" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:550 sql_help.c:552 -#: sql_help.c:553 sql_help.c:883 sql_help.c:885 sql_help.c:886 sql_help.c:966 -#: sql_help.c:970 sql_help.c:973 sql_help.c:1035 sql_help.c:1037 -#: sql_help.c:1038 sql_help.c:1188 sql_help.c:1190 sql_help.c:1673 -#: sql_help.c:1677 sql_help.c:1680 sql_help.c:2436 sql_help.c:2639 -#: sql_help.c:3957 sql_help.c:4259 sql_help.c:4420 sql_help.c:4730 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:572 sql_help.c:574 +#: sql_help.c:575 sql_help.c:905 sql_help.c:907 sql_help.c:908 sql_help.c:988 +#: sql_help.c:992 sql_help.c:995 sql_help.c:1057 sql_help.c:1059 +#: sql_help.c:1060 sql_help.c:1211 sql_help.c:1213 sql_help.c:1687 +#: sql_help.c:1691 sql_help.c:1694 sql_help.c:2464 sql_help.c:2667 +#: sql_help.c:3995 sql_help.c:4301 sql_help.c:4462 sql_help.c:4772 msgid "configuration_parameter" msgstr "Konfigurationsparameter" -#: sql_help.c:128 sql_help.c:400 sql_help.c:471 sql_help.c:477 sql_help.c:489 -#: sql_help.c:551 sql_help.c:605 sql_help.c:687 sql_help.c:697 sql_help.c:884 -#: sql_help.c:912 sql_help.c:967 sql_help.c:1036 sql_help.c:1109 -#: sql_help.c:1154 sql_help.c:1158 sql_help.c:1162 sql_help.c:1165 -#: sql_help.c:1170 sql_help.c:1173 sql_help.c:1189 sql_help.c:1380 -#: sql_help.c:1403 sql_help.c:1451 sql_help.c:1459 sql_help.c:1479 -#: sql_help.c:1536 sql_help.c:1620 sql_help.c:1674 sql_help.c:1697 -#: sql_help.c:2316 sql_help.c:2366 sql_help.c:2373 sql_help.c:2382 -#: sql_help.c:2437 sql_help.c:2438 sql_help.c:2502 sql_help.c:2505 -#: sql_help.c:2539 sql_help.c:2640 sql_help.c:2641 sql_help.c:2664 -#: sql_help.c:2787 sql_help.c:2826 sql_help.c:2936 sql_help.c:2949 -#: sql_help.c:2963 sql_help.c:3004 sql_help.c:3012 sql_help.c:3034 -#: sql_help.c:3051 sql_help.c:3078 sql_help.c:3285 sql_help.c:3990 -#: sql_help.c:4731 sql_help.c:4732 sql_help.c:4733 sql_help.c:4734 +#: sql_help.c:128 sql_help.c:422 sql_help.c:493 sql_help.c:499 sql_help.c:511 +#: sql_help.c:573 sql_help.c:627 sql_help.c:709 sql_help.c:719 sql_help.c:906 +#: sql_help.c:934 sql_help.c:989 sql_help.c:1058 sql_help.c:1132 +#: sql_help.c:1177 sql_help.c:1181 sql_help.c:1185 sql_help.c:1188 +#: sql_help.c:1193 sql_help.c:1196 sql_help.c:1212 sql_help.c:1388 +#: sql_help.c:1412 sql_help.c:1465 sql_help.c:1473 sql_help.c:1493 +#: sql_help.c:1550 sql_help.c:1634 sql_help.c:1688 sql_help.c:1711 +#: sql_help.c:2332 sql_help.c:2390 sql_help.c:2399 sql_help.c:2408 +#: sql_help.c:2465 sql_help.c:2466 sql_help.c:2530 sql_help.c:2533 +#: sql_help.c:2567 sql_help.c:2668 sql_help.c:2669 sql_help.c:2692 +#: sql_help.c:2817 sql_help.c:2856 sql_help.c:2967 sql_help.c:2980 +#: sql_help.c:2994 sql_help.c:3040 sql_help.c:3048 sql_help.c:3070 +#: sql_help.c:3087 sql_help.c:3114 sql_help.c:3321 sql_help.c:4028 +#: sql_help.c:4773 sql_help.c:4774 sql_help.c:4775 sql_help.c:4776 msgid "value" msgstr "Wert" -#: sql_help.c:202 +#: sql_help.c:214 msgid "target_role" msgstr "Zielrolle" -#: sql_help.c:203 sql_help.c:921 sql_help.c:2300 sql_help.c:2669 -#: sql_help.c:2742 sql_help.c:2747 sql_help.c:3920 sql_help.c:3929 -#: sql_help.c:3948 sql_help.c:3960 sql_help.c:4383 sql_help.c:4392 -#: sql_help.c:4411 sql_help.c:4423 +#: sql_help.c:215 sql_help.c:943 sql_help.c:2316 sql_help.c:2697 +#: sql_help.c:2770 sql_help.c:2775 sql_help.c:3958 sql_help.c:3967 +#: sql_help.c:3986 sql_help.c:3998 sql_help.c:4425 sql_help.c:4434 +#: sql_help.c:4453 sql_help.c:4465 msgid "schema_name" msgstr "Schemaname" -#: sql_help.c:204 +#: sql_help.c:216 msgid "abbreviated_grant_or_revoke" msgstr "abgekürztes_Grant_oder_Revoke" -#: sql_help.c:205 +#: sql_help.c:217 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "wobei abgekürztes_Grant_oder_Revoke Folgendes sein kann:" -#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 -#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 -#: sql_help.c:576 sql_help.c:612 sql_help.c:680 sql_help.c:830 sql_help.c:977 -#: sql_help.c:1336 sql_help.c:1684 sql_help.c:2475 sql_help.c:2476 -#: sql_help.c:2477 sql_help.c:2478 sql_help.c:2479 sql_help.c:2613 -#: sql_help.c:2700 sql_help.c:2701 sql_help.c:2702 sql_help.c:3267 -#: sql_help.c:3268 sql_help.c:3269 sql_help.c:3270 sql_help.c:3271 -#: sql_help.c:3969 sql_help.c:3973 sql_help.c:4432 sql_help.c:4436 -#: sql_help.c:4752 +#: sql_help.c:218 sql_help.c:219 sql_help.c:220 sql_help.c:221 sql_help.c:222 +#: sql_help.c:223 sql_help.c:224 sql_help.c:225 sql_help.c:226 sql_help.c:227 +#: sql_help.c:228 sql_help.c:229 sql_help.c:598 sql_help.c:634 sql_help.c:702 +#: sql_help.c:852 sql_help.c:999 sql_help.c:1354 sql_help.c:1698 +#: sql_help.c:2503 sql_help.c:2504 sql_help.c:2505 sql_help.c:2506 +#: sql_help.c:2507 sql_help.c:2641 sql_help.c:2728 sql_help.c:2729 +#: sql_help.c:2730 sql_help.c:3303 sql_help.c:3304 sql_help.c:3305 +#: sql_help.c:3306 sql_help.c:3307 sql_help.c:4007 sql_help.c:4011 +#: sql_help.c:4474 sql_help.c:4478 sql_help.c:4794 msgid "role_name" msgstr "Rollenname" -#: sql_help.c:241 sql_help.c:464 sql_help.c:920 sql_help.c:1362 sql_help.c:1364 -#: sql_help.c:1368 sql_help.c:1418 sql_help.c:1430 sql_help.c:1455 -#: sql_help.c:1714 sql_help.c:2269 sql_help.c:2273 sql_help.c:2385 -#: sql_help.c:2390 sql_help.c:2498 sql_help.c:2668 sql_help.c:2803 -#: sql_help.c:2808 sql_help.c:2810 sql_help.c:2931 sql_help.c:2944 -#: sql_help.c:2958 sql_help.c:2967 sql_help.c:2979 sql_help.c:3008 -#: sql_help.c:4021 sql_help.c:4036 sql_help.c:4038 sql_help.c:4134 -#: sql_help.c:4137 sql_help.c:4139 sql_help.c:4602 sql_help.c:4603 -#: sql_help.c:4612 sql_help.c:4659 sql_help.c:4660 sql_help.c:4661 -#: sql_help.c:4662 sql_help.c:4663 sql_help.c:4664 sql_help.c:4705 -#: sql_help.c:4706 sql_help.c:4711 sql_help.c:4716 sql_help.c:4860 -#: sql_help.c:4861 sql_help.c:4870 sql_help.c:4917 sql_help.c:4918 -#: sql_help.c:4919 sql_help.c:4920 sql_help.c:4921 sql_help.c:4922 -#: sql_help.c:4977 sql_help.c:4979 sql_help.c:5045 sql_help.c:5105 -#: sql_help.c:5106 sql_help.c:5115 sql_help.c:5162 sql_help.c:5163 -#: sql_help.c:5164 sql_help.c:5165 sql_help.c:5166 sql_help.c:5167 +#: sql_help.c:260 sql_help.c:279 sql_help.c:486 sql_help.c:942 sql_help.c:1370 +#: sql_help.c:1372 sql_help.c:1376 sql_help.c:1427 sql_help.c:1439 +#: sql_help.c:1469 sql_help.c:1728 sql_help.c:2285 sql_help.c:2289 +#: sql_help.c:2411 sql_help.c:2417 sql_help.c:2526 sql_help.c:2696 +#: sql_help.c:2833 sql_help.c:2838 sql_help.c:2840 sql_help.c:2962 +#: sql_help.c:2975 sql_help.c:2989 sql_help.c:2998 sql_help.c:3010 +#: sql_help.c:3044 sql_help.c:4060 sql_help.c:4076 sql_help.c:4078 +#: sql_help.c:4176 sql_help.c:4179 sql_help.c:4181 sql_help.c:4644 +#: sql_help.c:4645 sql_help.c:4654 sql_help.c:4701 sql_help.c:4702 +#: sql_help.c:4703 sql_help.c:4704 sql_help.c:4705 sql_help.c:4706 +#: sql_help.c:4747 sql_help.c:4748 sql_help.c:4753 sql_help.c:4758 +#: sql_help.c:4902 sql_help.c:4903 sql_help.c:4912 sql_help.c:4959 +#: sql_help.c:4960 sql_help.c:4961 sql_help.c:4962 sql_help.c:4963 +#: sql_help.c:4964 sql_help.c:5020 sql_help.c:5022 sql_help.c:5089 +#: sql_help.c:5149 sql_help.c:5150 sql_help.c:5159 sql_help.c:5206 +#: sql_help.c:5207 sql_help.c:5208 sql_help.c:5209 sql_help.c:5210 +#: sql_help.c:5211 msgid "expression" msgstr "Ausdruck" -#: sql_help.c:244 sql_help.c:2270 +#: sql_help.c:263 sql_help.c:2286 msgid "domain_constraint" msgstr "Domänen-Constraint" -#: sql_help.c:246 sql_help.c:248 sql_help.c:251 sql_help.c:479 sql_help.c:480 -#: sql_help.c:1329 sql_help.c:1388 sql_help.c:1389 sql_help.c:1390 -#: sql_help.c:1417 sql_help.c:1429 sql_help.c:1446 sql_help.c:1878 -#: sql_help.c:1880 sql_help.c:2272 sql_help.c:2384 sql_help.c:2389 -#: sql_help.c:2966 sql_help.c:2978 sql_help.c:4033 +#: sql_help.c:265 sql_help.c:267 sql_help.c:270 sql_help.c:278 sql_help.c:501 +#: sql_help.c:502 sql_help.c:1347 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:1398 sql_help.c:1399 sql_help.c:1426 sql_help.c:1438 +#: sql_help.c:1460 sql_help.c:1892 sql_help.c:1894 sql_help.c:2288 +#: sql_help.c:2410 sql_help.c:2415 sql_help.c:2997 sql_help.c:3009 +#: sql_help.c:4073 msgid "constraint_name" msgstr "Constraint-Name" -#: sql_help.c:249 sql_help.c:1330 +#: sql_help.c:268 sql_help.c:1348 msgid "new_constraint_name" msgstr "neuer_Constraint-Name" -#: sql_help.c:322 sql_help.c:1107 +#: sql_help.c:277 sql_help.c:2287 +msgid "where domain_constraint is:" +msgstr "wobei Domänen-Constraint Folgendes ist:" + +#: sql_help.c:344 sql_help.c:1130 msgid "new_version" msgstr "neue_Version" -#: sql_help.c:326 sql_help.c:328 +#: sql_help.c:348 sql_help.c:350 msgid "member_object" msgstr "Elementobjekt" -#: sql_help.c:329 +#: sql_help.c:351 msgid "where member_object is:" msgstr "wobei Elementobjekt Folgendes ist:" -#: sql_help.c:330 sql_help.c:335 sql_help.c:336 sql_help.c:337 sql_help.c:338 -#: sql_help.c:339 sql_help.c:340 sql_help.c:345 sql_help.c:349 sql_help.c:351 -#: sql_help.c:353 sql_help.c:362 sql_help.c:363 sql_help.c:364 sql_help.c:365 -#: sql_help.c:366 sql_help.c:367 sql_help.c:368 sql_help.c:369 sql_help.c:372 -#: sql_help.c:373 sql_help.c:1870 sql_help.c:1875 sql_help.c:1882 -#: sql_help.c:1883 sql_help.c:1884 sql_help.c:1885 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1888 sql_help.c:1893 sql_help.c:1895 -#: sql_help.c:1899 sql_help.c:1901 sql_help.c:1905 sql_help.c:1910 -#: sql_help.c:1911 sql_help.c:1918 sql_help.c:1919 sql_help.c:1920 -#: sql_help.c:1921 sql_help.c:1922 sql_help.c:1923 sql_help.c:1924 -#: sql_help.c:1925 sql_help.c:1926 sql_help.c:1927 sql_help.c:1928 -#: sql_help.c:1933 sql_help.c:1934 sql_help.c:4505 sql_help.c:4510 -#: sql_help.c:4511 sql_help.c:4512 sql_help.c:4513 sql_help.c:4519 -#: sql_help.c:4520 sql_help.c:4525 sql_help.c:4526 sql_help.c:4531 -#: sql_help.c:4532 sql_help.c:4533 sql_help.c:4534 sql_help.c:4535 -#: sql_help.c:4536 +#: sql_help.c:352 sql_help.c:357 sql_help.c:358 sql_help.c:359 sql_help.c:360 +#: sql_help.c:361 sql_help.c:362 sql_help.c:367 sql_help.c:371 sql_help.c:373 +#: sql_help.c:375 sql_help.c:384 sql_help.c:385 sql_help.c:386 sql_help.c:387 +#: sql_help.c:388 sql_help.c:389 sql_help.c:390 sql_help.c:391 sql_help.c:394 +#: sql_help.c:395 sql_help.c:1884 sql_help.c:1889 sql_help.c:1896 +#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 +#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1907 sql_help.c:1909 +#: sql_help.c:1913 sql_help.c:1915 sql_help.c:1919 sql_help.c:1924 +#: sql_help.c:1925 sql_help.c:1932 sql_help.c:1933 sql_help.c:1934 +#: sql_help.c:1935 sql_help.c:1936 sql_help.c:1937 sql_help.c:1938 +#: sql_help.c:1939 sql_help.c:1940 sql_help.c:1941 sql_help.c:1942 +#: sql_help.c:1947 sql_help.c:1948 sql_help.c:4547 sql_help.c:4552 +#: sql_help.c:4553 sql_help.c:4554 sql_help.c:4555 sql_help.c:4561 +#: sql_help.c:4562 sql_help.c:4567 sql_help.c:4568 sql_help.c:4573 +#: sql_help.c:4574 sql_help.c:4575 sql_help.c:4576 sql_help.c:4577 +#: sql_help.c:4578 msgid "object_name" msgstr "Objektname" -#: sql_help.c:331 sql_help.c:1871 sql_help.c:4508 +#: sql_help.c:353 sql_help.c:1885 sql_help.c:4550 msgid "aggregate_name" msgstr "Aggregatname" -#: sql_help.c:333 sql_help.c:1873 sql_help.c:2163 sql_help.c:2167 -#: sql_help.c:2169 sql_help.c:3394 +#: sql_help.c:355 sql_help.c:1887 sql_help.c:2179 sql_help.c:2183 +#: sql_help.c:2185 sql_help.c:3432 msgid "source_type" msgstr "Quelltyp" -#: sql_help.c:334 sql_help.c:1874 sql_help.c:2164 sql_help.c:2168 -#: sql_help.c:2170 sql_help.c:3395 +#: sql_help.c:356 sql_help.c:1888 sql_help.c:2180 sql_help.c:2184 +#: sql_help.c:2186 sql_help.c:3433 msgid "target_type" msgstr "Zieltyp" -#: sql_help.c:341 sql_help.c:794 sql_help.c:1889 sql_help.c:2165 -#: sql_help.c:2208 sql_help.c:2288 sql_help.c:2556 sql_help.c:2587 -#: sql_help.c:3154 sql_help.c:4407 sql_help.c:4514 sql_help.c:4631 -#: sql_help.c:4635 sql_help.c:4639 sql_help.c:4642 sql_help.c:4889 -#: sql_help.c:4893 sql_help.c:4897 sql_help.c:4900 sql_help.c:5134 -#: sql_help.c:5138 sql_help.c:5142 sql_help.c:5145 +#: sql_help.c:363 sql_help.c:816 sql_help.c:1903 sql_help.c:2181 +#: sql_help.c:2224 sql_help.c:2304 sql_help.c:2584 sql_help.c:2615 +#: sql_help.c:3190 sql_help.c:4449 sql_help.c:4556 sql_help.c:4673 +#: sql_help.c:4677 sql_help.c:4681 sql_help.c:4684 sql_help.c:4931 +#: sql_help.c:4935 sql_help.c:4939 sql_help.c:4942 sql_help.c:5178 +#: sql_help.c:5182 sql_help.c:5186 sql_help.c:5189 msgid "function_name" msgstr "Funktionsname" -#: sql_help.c:346 sql_help.c:787 sql_help.c:1896 sql_help.c:2580 +#: sql_help.c:368 sql_help.c:809 sql_help.c:1910 sql_help.c:2608 msgid "operator_name" msgstr "Operatorname" -#: sql_help.c:347 sql_help.c:721 sql_help.c:725 sql_help.c:729 sql_help.c:1897 -#: sql_help.c:2557 sql_help.c:3518 +#: sql_help.c:369 sql_help.c:743 sql_help.c:747 sql_help.c:751 sql_help.c:1911 +#: sql_help.c:2585 sql_help.c:3556 msgid "left_type" msgstr "linker_Typ" -#: sql_help.c:348 sql_help.c:722 sql_help.c:726 sql_help.c:730 sql_help.c:1898 -#: sql_help.c:2558 sql_help.c:3519 +#: sql_help.c:370 sql_help.c:744 sql_help.c:748 sql_help.c:752 sql_help.c:1912 +#: sql_help.c:2586 sql_help.c:3557 msgid "right_type" msgstr "rechter_Typ" -#: sql_help.c:350 sql_help.c:352 sql_help.c:750 sql_help.c:753 sql_help.c:756 -#: sql_help.c:785 sql_help.c:797 sql_help.c:805 sql_help.c:808 sql_help.c:811 -#: sql_help.c:1435 sql_help.c:1900 sql_help.c:1902 sql_help.c:2577 -#: sql_help.c:2598 sql_help.c:2984 sql_help.c:3528 sql_help.c:3537 +#: sql_help.c:372 sql_help.c:374 sql_help.c:772 sql_help.c:775 sql_help.c:778 +#: sql_help.c:807 sql_help.c:819 sql_help.c:827 sql_help.c:830 sql_help.c:833 +#: sql_help.c:1447 sql_help.c:1914 sql_help.c:1916 sql_help.c:2605 +#: sql_help.c:2626 sql_help.c:3018 sql_help.c:3566 sql_help.c:3575 msgid "index_method" msgstr "Indexmethode" -#: sql_help.c:354 sql_help.c:1906 sql_help.c:4521 +#: sql_help.c:376 sql_help.c:1920 sql_help.c:4563 msgid "procedure_name" msgstr "Prozedurname" -#: sql_help.c:358 sql_help.c:1912 sql_help.c:3944 sql_help.c:4527 +#: sql_help.c:380 sql_help.c:1926 sql_help.c:3982 sql_help.c:4569 msgid "routine_name" msgstr "Routinenname" -#: sql_help.c:370 sql_help.c:1407 sql_help.c:1929 sql_help.c:2432 -#: sql_help.c:2638 sql_help.c:2939 sql_help.c:3121 sql_help.c:3699 -#: sql_help.c:3966 sql_help.c:4429 +#: sql_help.c:392 sql_help.c:1416 sql_help.c:1943 sql_help.c:2460 +#: sql_help.c:2666 sql_help.c:2970 sql_help.c:3157 sql_help.c:3737 +#: sql_help.c:4004 sql_help.c:4471 msgid "type_name" msgstr "Typname" -#: sql_help.c:371 sql_help.c:1930 sql_help.c:2431 sql_help.c:2637 -#: sql_help.c:3122 sql_help.c:3352 sql_help.c:3700 sql_help.c:3951 -#: sql_help.c:4414 +#: sql_help.c:393 sql_help.c:1944 sql_help.c:2459 sql_help.c:2665 +#: sql_help.c:3158 sql_help.c:3390 sql_help.c:3738 sql_help.c:3989 +#: sql_help.c:4456 msgid "lang_name" msgstr "Sprachname" -#: sql_help.c:374 +#: sql_help.c:396 msgid "and aggregate_signature is:" msgstr "und Aggregatsignatur Folgendes ist:" -#: sql_help.c:397 sql_help.c:2030 sql_help.c:2313 +#: sql_help.c:419 sql_help.c:2046 sql_help.c:2329 msgid "handler_function" msgstr "Handler-Funktion" -#: sql_help.c:398 sql_help.c:2314 +#: sql_help.c:420 sql_help.c:2330 msgid "validator_function" msgstr "Validator-Funktion" -#: sql_help.c:446 sql_help.c:525 sql_help.c:669 sql_help.c:861 sql_help.c:1011 -#: sql_help.c:1324 sql_help.c:1611 +#: sql_help.c:468 sql_help.c:547 sql_help.c:691 sql_help.c:883 sql_help.c:1033 +#: sql_help.c:1342 sql_help.c:1625 msgid "action" msgstr "Aktion" -#: sql_help.c:448 sql_help.c:455 sql_help.c:459 sql_help.c:460 sql_help.c:463 -#: sql_help.c:465 sql_help.c:466 sql_help.c:467 sql_help.c:469 sql_help.c:472 -#: sql_help.c:474 sql_help.c:475 sql_help.c:673 sql_help.c:683 sql_help.c:685 -#: sql_help.c:688 sql_help.c:690 sql_help.c:691 sql_help.c:919 sql_help.c:1088 -#: sql_help.c:1326 sql_help.c:1354 sql_help.c:1358 sql_help.c:1359 -#: sql_help.c:1363 sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 -#: sql_help.c:1369 sql_help.c:1370 sql_help.c:1372 sql_help.c:1375 -#: sql_help.c:1376 sql_help.c:1378 sql_help.c:1381 sql_help.c:1383 -#: sql_help.c:1384 sql_help.c:1431 sql_help.c:1433 sql_help.c:1440 -#: sql_help.c:1449 sql_help.c:1454 sql_help.c:1461 sql_help.c:1462 -#: sql_help.c:1713 sql_help.c:1716 sql_help.c:1720 sql_help.c:1756 -#: sql_help.c:1877 sql_help.c:1993 sql_help.c:1999 sql_help.c:2013 -#: sql_help.c:2014 sql_help.c:2015 sql_help.c:2363 sql_help.c:2376 -#: sql_help.c:2429 sql_help.c:2497 sql_help.c:2503 sql_help.c:2536 -#: sql_help.c:2667 sql_help.c:2772 sql_help.c:2807 sql_help.c:2809 -#: sql_help.c:2921 sql_help.c:2930 sql_help.c:2940 sql_help.c:2943 -#: sql_help.c:2953 sql_help.c:2957 sql_help.c:2980 sql_help.c:2982 -#: sql_help.c:2989 sql_help.c:3002 sql_help.c:3007 sql_help.c:3014 -#: sql_help.c:3015 sql_help.c:3031 sql_help.c:3157 sql_help.c:3297 -#: sql_help.c:3923 sql_help.c:3924 sql_help.c:4020 sql_help.c:4035 -#: sql_help.c:4037 sql_help.c:4039 sql_help.c:4133 sql_help.c:4136 -#: sql_help.c:4138 sql_help.c:4140 sql_help.c:4386 sql_help.c:4387 -#: sql_help.c:4507 sql_help.c:4668 sql_help.c:4675 sql_help.c:4677 -#: sql_help.c:4926 sql_help.c:4933 sql_help.c:4935 sql_help.c:4976 -#: sql_help.c:4978 sql_help.c:4980 sql_help.c:5033 sql_help.c:5171 -#: sql_help.c:5178 sql_help.c:5180 +#: sql_help.c:470 sql_help.c:477 sql_help.c:481 sql_help.c:482 sql_help.c:485 +#: sql_help.c:487 sql_help.c:488 sql_help.c:489 sql_help.c:491 sql_help.c:494 +#: sql_help.c:496 sql_help.c:497 sql_help.c:695 sql_help.c:705 sql_help.c:707 +#: sql_help.c:710 sql_help.c:712 sql_help.c:713 sql_help.c:941 sql_help.c:1111 +#: sql_help.c:1344 sql_help.c:1362 sql_help.c:1366 sql_help.c:1367 +#: sql_help.c:1371 sql_help.c:1373 sql_help.c:1374 sql_help.c:1375 +#: sql_help.c:1377 sql_help.c:1378 sql_help.c:1380 sql_help.c:1383 +#: sql_help.c:1384 sql_help.c:1386 sql_help.c:1389 sql_help.c:1391 +#: sql_help.c:1392 sql_help.c:1440 sql_help.c:1441 sql_help.c:1442 +#: sql_help.c:1444 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1463 sql_help.c:1468 sql_help.c:1475 sql_help.c:1476 +#: sql_help.c:1727 sql_help.c:1730 sql_help.c:1734 sql_help.c:1770 +#: sql_help.c:1891 sql_help.c:2008 sql_help.c:2014 sql_help.c:2028 +#: sql_help.c:2029 sql_help.c:2030 sql_help.c:2387 sql_help.c:2402 +#: sql_help.c:2416 sql_help.c:2457 sql_help.c:2525 sql_help.c:2531 +#: sql_help.c:2564 sql_help.c:2695 sql_help.c:2802 sql_help.c:2837 +#: sql_help.c:2839 sql_help.c:2952 sql_help.c:2961 sql_help.c:2971 +#: sql_help.c:2974 sql_help.c:2984 sql_help.c:2988 sql_help.c:3011 +#: sql_help.c:3012 sql_help.c:3013 sql_help.c:3015 sql_help.c:3016 +#: sql_help.c:3023 sql_help.c:3024 sql_help.c:3038 sql_help.c:3043 +#: sql_help.c:3050 sql_help.c:3051 sql_help.c:3067 sql_help.c:3193 +#: sql_help.c:3333 sql_help.c:3961 sql_help.c:3962 sql_help.c:4059 +#: sql_help.c:4075 sql_help.c:4077 sql_help.c:4079 sql_help.c:4175 +#: sql_help.c:4178 sql_help.c:4180 sql_help.c:4182 sql_help.c:4428 +#: sql_help.c:4429 sql_help.c:4549 sql_help.c:4710 sql_help.c:4717 +#: sql_help.c:4719 sql_help.c:4968 sql_help.c:4975 sql_help.c:4977 +#: sql_help.c:5019 sql_help.c:5021 sql_help.c:5023 sql_help.c:5077 +#: sql_help.c:5215 sql_help.c:5222 sql_help.c:5224 msgid "column_name" msgstr "Spaltenname" -#: sql_help.c:449 sql_help.c:674 sql_help.c:1327 sql_help.c:1721 +#: sql_help.c:471 sql_help.c:696 sql_help.c:1345 sql_help.c:1735 msgid "new_column_name" msgstr "neuer_Spaltenname" -#: sql_help.c:454 sql_help.c:546 sql_help.c:682 sql_help.c:882 sql_help.c:1032 -#: sql_help.c:1353 sql_help.c:1621 +#: sql_help.c:476 sql_help.c:568 sql_help.c:704 sql_help.c:904 sql_help.c:1054 +#: sql_help.c:1361 sql_help.c:1635 msgid "where action is one of:" msgstr "wobei Aktion Folgendes sein kann:" -#: sql_help.c:456 sql_help.c:461 sql_help.c:1080 sql_help.c:1355 -#: sql_help.c:1360 sql_help.c:1623 sql_help.c:1627 sql_help.c:2267 -#: sql_help.c:2364 sql_help.c:2576 sql_help.c:2765 sql_help.c:2922 -#: sql_help.c:3204 sql_help.c:4192 +#: sql_help.c:478 sql_help.c:483 sql_help.c:1103 sql_help.c:1363 +#: sql_help.c:1368 sql_help.c:1637 sql_help.c:1641 sql_help.c:2283 +#: sql_help.c:2388 sql_help.c:2604 sql_help.c:2795 sql_help.c:2953 +#: sql_help.c:3240 sql_help.c:4234 msgid "data_type" msgstr "Datentyp" -#: sql_help.c:457 sql_help.c:462 sql_help.c:1356 sql_help.c:1361 -#: sql_help.c:1456 sql_help.c:1624 sql_help.c:1628 sql_help.c:2268 -#: sql_help.c:2367 sql_help.c:2499 sql_help.c:2924 sql_help.c:2932 -#: sql_help.c:2945 sql_help.c:2959 sql_help.c:3009 sql_help.c:3205 -#: sql_help.c:3211 sql_help.c:4030 +#: sql_help.c:479 sql_help.c:484 sql_help.c:1364 sql_help.c:1369 +#: sql_help.c:1470 sql_help.c:1638 sql_help.c:1642 sql_help.c:2284 +#: sql_help.c:2391 sql_help.c:2527 sql_help.c:2955 sql_help.c:2963 +#: sql_help.c:2976 sql_help.c:2990 sql_help.c:3045 sql_help.c:3241 +#: sql_help.c:3247 sql_help.c:4070 msgid "collation" msgstr "Sortierfolge" -#: sql_help.c:458 sql_help.c:1357 sql_help.c:2368 sql_help.c:2377 -#: sql_help.c:2925 sql_help.c:2941 sql_help.c:2954 +#: sql_help.c:480 sql_help.c:1365 sql_help.c:2392 sql_help.c:2403 +#: sql_help.c:2956 sql_help.c:2972 sql_help.c:2985 msgid "column_constraint" msgstr "Spalten-Constraint" -#: sql_help.c:468 sql_help.c:610 sql_help.c:684 sql_help.c:1377 sql_help.c:5027 +#: sql_help.c:490 sql_help.c:632 sql_help.c:706 sql_help.c:1385 sql_help.c:5071 msgid "integer" msgstr "ganze_Zahl" -#: sql_help.c:470 sql_help.c:473 sql_help.c:686 sql_help.c:689 sql_help.c:1379 -#: sql_help.c:1382 +#: sql_help.c:492 sql_help.c:495 sql_help.c:708 sql_help.c:711 sql_help.c:1387 +#: sql_help.c:1390 msgid "attribute_option" msgstr "Attributoption" -#: sql_help.c:478 sql_help.c:1386 sql_help.c:2369 sql_help.c:2378 -#: sql_help.c:2926 sql_help.c:2942 sql_help.c:2955 +#: sql_help.c:500 sql_help.c:1394 sql_help.c:2393 sql_help.c:2404 +#: sql_help.c:2957 sql_help.c:2973 sql_help.c:2986 msgid "table_constraint" msgstr "Tabellen-Constraint" -#: sql_help.c:481 sql_help.c:482 sql_help.c:483 sql_help.c:484 sql_help.c:1391 -#: sql_help.c:1392 sql_help.c:1393 sql_help.c:1394 sql_help.c:1931 +#: sql_help.c:503 sql_help.c:504 sql_help.c:505 sql_help.c:506 sql_help.c:1400 +#: sql_help.c:1401 sql_help.c:1402 sql_help.c:1403 sql_help.c:1945 msgid "trigger_name" msgstr "Triggername" -#: sql_help.c:485 sql_help.c:486 sql_help.c:1405 sql_help.c:1406 -#: sql_help.c:2370 sql_help.c:2375 sql_help.c:2929 sql_help.c:2952 +#: sql_help.c:507 sql_help.c:508 sql_help.c:1414 sql_help.c:1415 +#: sql_help.c:2396 sql_help.c:2401 sql_help.c:2960 sql_help.c:2983 msgid "parent_table" msgstr "Elterntabelle" -#: sql_help.c:545 sql_help.c:602 sql_help.c:671 sql_help.c:881 sql_help.c:1031 -#: sql_help.c:1580 sql_help.c:2299 +#: sql_help.c:567 sql_help.c:624 sql_help.c:693 sql_help.c:903 sql_help.c:1053 +#: sql_help.c:1594 sql_help.c:2315 msgid "extension_name" msgstr "Erweiterungsname" -#: sql_help.c:547 sql_help.c:1033 sql_help.c:2433 +#: sql_help.c:569 sql_help.c:1055 sql_help.c:2461 msgid "execution_cost" msgstr "Ausführungskosten" -#: sql_help.c:548 sql_help.c:1034 sql_help.c:2434 +#: sql_help.c:570 sql_help.c:1056 sql_help.c:2462 msgid "result_rows" msgstr "Ergebniszeilen" -#: sql_help.c:549 sql_help.c:2435 +#: sql_help.c:571 sql_help.c:2463 msgid "support_function" msgstr "Support-Funktion" -#: sql_help.c:571 sql_help.c:573 sql_help.c:956 sql_help.c:964 sql_help.c:968 -#: sql_help.c:971 sql_help.c:974 sql_help.c:1663 sql_help.c:1671 -#: sql_help.c:1675 sql_help.c:1678 sql_help.c:1681 sql_help.c:2743 -#: sql_help.c:2745 sql_help.c:2748 sql_help.c:2749 sql_help.c:3921 -#: sql_help.c:3922 sql_help.c:3926 sql_help.c:3927 sql_help.c:3930 -#: sql_help.c:3931 sql_help.c:3933 sql_help.c:3934 sql_help.c:3936 -#: sql_help.c:3937 sql_help.c:3939 sql_help.c:3940 sql_help.c:3942 -#: sql_help.c:3943 sql_help.c:3949 sql_help.c:3950 sql_help.c:3952 -#: sql_help.c:3953 sql_help.c:3955 sql_help.c:3956 sql_help.c:3958 -#: sql_help.c:3959 sql_help.c:3961 sql_help.c:3962 sql_help.c:3964 -#: sql_help.c:3965 sql_help.c:3967 sql_help.c:3968 sql_help.c:3970 -#: sql_help.c:3971 sql_help.c:4384 sql_help.c:4385 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4393 sql_help.c:4394 sql_help.c:4396 -#: sql_help.c:4397 sql_help.c:4399 sql_help.c:4400 sql_help.c:4402 -#: sql_help.c:4403 sql_help.c:4405 sql_help.c:4406 sql_help.c:4412 -#: sql_help.c:4413 sql_help.c:4415 sql_help.c:4416 sql_help.c:4418 -#: sql_help.c:4419 sql_help.c:4421 sql_help.c:4422 sql_help.c:4424 -#: sql_help.c:4425 sql_help.c:4427 sql_help.c:4428 sql_help.c:4430 -#: sql_help.c:4431 sql_help.c:4433 sql_help.c:4434 +#: sql_help.c:593 sql_help.c:595 sql_help.c:978 sql_help.c:986 sql_help.c:990 +#: sql_help.c:993 sql_help.c:996 sql_help.c:1677 sql_help.c:1685 +#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1695 sql_help.c:2771 +#: sql_help.c:2773 sql_help.c:2776 sql_help.c:2777 sql_help.c:3959 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:3965 sql_help.c:3968 +#: sql_help.c:3969 sql_help.c:3971 sql_help.c:3972 sql_help.c:3974 +#: sql_help.c:3975 sql_help.c:3977 sql_help.c:3978 sql_help.c:3980 +#: sql_help.c:3981 sql_help.c:3987 sql_help.c:3988 sql_help.c:3990 +#: sql_help.c:3991 sql_help.c:3993 sql_help.c:3994 sql_help.c:3996 +#: sql_help.c:3997 sql_help.c:3999 sql_help.c:4000 sql_help.c:4002 +#: sql_help.c:4003 sql_help.c:4005 sql_help.c:4006 sql_help.c:4008 +#: sql_help.c:4009 sql_help.c:4426 sql_help.c:4427 sql_help.c:4431 +#: sql_help.c:4432 sql_help.c:4435 sql_help.c:4436 sql_help.c:4438 +#: sql_help.c:4439 sql_help.c:4441 sql_help.c:4442 sql_help.c:4444 +#: sql_help.c:4445 sql_help.c:4447 sql_help.c:4448 sql_help.c:4454 +#: sql_help.c:4455 sql_help.c:4457 sql_help.c:4458 sql_help.c:4460 +#: sql_help.c:4461 sql_help.c:4463 sql_help.c:4464 sql_help.c:4466 +#: sql_help.c:4467 sql_help.c:4469 sql_help.c:4470 sql_help.c:4472 +#: sql_help.c:4473 sql_help.c:4475 sql_help.c:4476 msgid "role_specification" msgstr "Rollenangabe" -#: sql_help.c:572 sql_help.c:574 sql_help.c:1694 sql_help.c:2234 -#: sql_help.c:2751 sql_help.c:3282 sql_help.c:3733 sql_help.c:4762 +#: sql_help.c:594 sql_help.c:596 sql_help.c:1708 sql_help.c:2250 +#: sql_help.c:2779 sql_help.c:3318 sql_help.c:3771 sql_help.c:4804 msgid "user_name" msgstr "Benutzername" -#: sql_help.c:575 sql_help.c:976 sql_help.c:1683 sql_help.c:2750 -#: sql_help.c:3972 sql_help.c:4435 +#: sql_help.c:597 sql_help.c:998 sql_help.c:1697 sql_help.c:2778 +#: sql_help.c:4010 sql_help.c:4477 msgid "where role_specification can be:" msgstr "wobei Rollenangabe Folgendes sein kann:" -#: sql_help.c:577 +#: sql_help.c:599 msgid "group_name" msgstr "Gruppenname" -#: sql_help.c:598 sql_help.c:1452 sql_help.c:2246 sql_help.c:2506 -#: sql_help.c:2540 sql_help.c:2937 sql_help.c:2950 sql_help.c:2964 -#: sql_help.c:3005 sql_help.c:3035 sql_help.c:3047 sql_help.c:3963 -#: sql_help.c:4426 +#: sql_help.c:620 sql_help.c:1466 sql_help.c:2262 sql_help.c:2534 +#: sql_help.c:2568 sql_help.c:2968 sql_help.c:2981 sql_help.c:2995 +#: sql_help.c:3041 sql_help.c:3071 sql_help.c:3083 sql_help.c:4001 +#: sql_help.c:4468 msgid "tablespace_name" msgstr "Tablespace-Name" -#: sql_help.c:600 sql_help.c:693 sql_help.c:1399 sql_help.c:1409 -#: sql_help.c:1447 sql_help.c:1809 +#: sql_help.c:622 sql_help.c:715 sql_help.c:1408 sql_help.c:1418 +#: sql_help.c:1461 sql_help.c:1823 msgid "index_name" msgstr "Indexname" -#: sql_help.c:604 sql_help.c:607 sql_help.c:696 sql_help.c:698 sql_help.c:1402 -#: sql_help.c:1404 sql_help.c:1450 sql_help.c:2504 sql_help.c:2538 -#: sql_help.c:2935 sql_help.c:2948 sql_help.c:2962 sql_help.c:3003 -#: sql_help.c:3033 +#: sql_help.c:626 sql_help.c:629 sql_help.c:718 sql_help.c:720 sql_help.c:1411 +#: sql_help.c:1413 sql_help.c:1464 sql_help.c:2532 sql_help.c:2566 +#: sql_help.c:2966 sql_help.c:2979 sql_help.c:2993 sql_help.c:3039 +#: sql_help.c:3069 msgid "storage_parameter" msgstr "Storage-Parameter" -#: sql_help.c:609 +#: sql_help.c:631 msgid "column_number" msgstr "Spaltennummer" -#: sql_help.c:633 sql_help.c:1894 sql_help.c:4518 +#: sql_help.c:655 sql_help.c:1908 sql_help.c:4560 msgid "large_object_oid" msgstr "Large-Object-OID" -#: sql_help.c:692 sql_help.c:1385 sql_help.c:2923 +#: sql_help.c:714 sql_help.c:1393 sql_help.c:2954 msgid "compression_method" msgstr "Kompressionsmethode" -#: sql_help.c:694 sql_help.c:1400 +#: sql_help.c:716 sql_help.c:1409 msgid "new_access_method" msgstr "neue_Zugriffsmethode" -#: sql_help.c:731 sql_help.c:2561 +#: sql_help.c:753 sql_help.c:2589 msgid "res_proc" msgstr "Res-Funktion" -#: sql_help.c:732 sql_help.c:2562 +#: sql_help.c:754 sql_help.c:2590 msgid "join_proc" msgstr "Join-Funktion" -#: sql_help.c:733 sql_help.c:2559 +#: sql_help.c:755 sql_help.c:2587 msgid "com_op" msgstr "Kommutator-Op" -#: sql_help.c:734 sql_help.c:2560 +#: sql_help.c:756 sql_help.c:2588 msgid "neg_op" msgstr "Umkehrungs-Op" -#: sql_help.c:786 sql_help.c:798 sql_help.c:2579 +#: sql_help.c:808 sql_help.c:820 sql_help.c:2607 msgid "strategy_number" msgstr "Strategienummer" -#: sql_help.c:788 sql_help.c:789 sql_help.c:792 sql_help.c:793 sql_help.c:799 -#: sql_help.c:800 sql_help.c:802 sql_help.c:803 sql_help.c:2581 sql_help.c:2582 -#: sql_help.c:2585 sql_help.c:2586 +#: sql_help.c:810 sql_help.c:811 sql_help.c:814 sql_help.c:815 sql_help.c:821 +#: sql_help.c:822 sql_help.c:824 sql_help.c:825 sql_help.c:2609 sql_help.c:2610 +#: sql_help.c:2613 sql_help.c:2614 msgid "op_type" msgstr "Optyp" -#: sql_help.c:790 sql_help.c:2583 +#: sql_help.c:812 sql_help.c:2611 msgid "sort_family_name" msgstr "Sortierfamilienname" -#: sql_help.c:791 sql_help.c:801 sql_help.c:2584 +#: sql_help.c:813 sql_help.c:823 sql_help.c:2612 msgid "support_number" msgstr "Unterst-Nummer" -#: sql_help.c:795 sql_help.c:2166 sql_help.c:2588 sql_help.c:3124 -#: sql_help.c:3126 +#: sql_help.c:817 sql_help.c:2182 sql_help.c:2616 sql_help.c:3160 +#: sql_help.c:3162 msgid "argument_type" msgstr "Argumenttyp" -#: sql_help.c:826 sql_help.c:829 sql_help.c:918 sql_help.c:1047 sql_help.c:1087 -#: sql_help.c:1576 sql_help.c:1579 sql_help.c:1755 sql_help.c:1808 -#: sql_help.c:1879 sql_help.c:1904 sql_help.c:1917 sql_help.c:1932 -#: sql_help.c:1992 sql_help.c:1998 sql_help.c:2362 sql_help.c:2374 -#: sql_help.c:2495 sql_help.c:2535 sql_help.c:2612 sql_help.c:2666 -#: sql_help.c:2719 sql_help.c:2771 sql_help.c:2804 sql_help.c:2811 -#: sql_help.c:2920 sql_help.c:2938 sql_help.c:2951 sql_help.c:3030 -#: sql_help.c:3150 sql_help.c:3331 sql_help.c:3554 sql_help.c:3603 -#: sql_help.c:3709 sql_help.c:3919 sql_help.c:3925 sql_help.c:3986 -#: sql_help.c:4018 sql_help.c:4382 sql_help.c:4388 sql_help.c:4506 -#: sql_help.c:4619 sql_help.c:4682 sql_help.c:4721 sql_help.c:4877 -#: sql_help.c:4940 sql_help.c:4974 sql_help.c:5032 sql_help.c:5122 -#: sql_help.c:5185 +#: sql_help.c:848 sql_help.c:851 sql_help.c:940 sql_help.c:1069 sql_help.c:1110 +#: sql_help.c:1590 sql_help.c:1593 sql_help.c:1769 sql_help.c:1822 +#: sql_help.c:1893 sql_help.c:1918 sql_help.c:1931 sql_help.c:1946 +#: sql_help.c:2007 sql_help.c:2013 sql_help.c:2386 sql_help.c:2400 +#: sql_help.c:2523 sql_help.c:2563 sql_help.c:2640 sql_help.c:2694 +#: sql_help.c:2747 sql_help.c:2801 sql_help.c:2834 sql_help.c:2841 +#: sql_help.c:2951 sql_help.c:2969 sql_help.c:2982 sql_help.c:3066 +#: sql_help.c:3186 sql_help.c:3368 sql_help.c:3592 sql_help.c:3641 +#: sql_help.c:3747 sql_help.c:3957 sql_help.c:3963 sql_help.c:4024 +#: sql_help.c:4057 sql_help.c:4424 sql_help.c:4430 sql_help.c:4548 +#: sql_help.c:4661 sql_help.c:4724 sql_help.c:4763 sql_help.c:4919 +#: sql_help.c:4982 sql_help.c:5017 sql_help.c:5076 sql_help.c:5166 +#: sql_help.c:5229 msgid "table_name" msgstr "Tabellenname" -#: sql_help.c:831 sql_help.c:2614 +#: sql_help.c:853 sql_help.c:2642 msgid "using_expression" msgstr "Using-Ausdruck" -#: sql_help.c:832 sql_help.c:2615 +#: sql_help.c:854 sql_help.c:2643 msgid "check_expression" msgstr "Check-Ausdruck" -#: sql_help.c:905 sql_help.c:907 sql_help.c:909 sql_help.c:2662 +#: sql_help.c:927 sql_help.c:929 sql_help.c:931 sql_help.c:2690 msgid "publication_object" msgstr "Publikationsobjekt" -#: sql_help.c:911 sql_help.c:2663 +#: sql_help.c:933 sql_help.c:2691 msgid "publication_parameter" msgstr "Publikationsparameter" -#: sql_help.c:917 sql_help.c:2665 +#: sql_help.c:939 sql_help.c:2693 msgid "where publication_object is one of:" msgstr "wobei Publikationsobjekt Folgendes sein kann:" -#: sql_help.c:960 sql_help.c:1667 sql_help.c:2473 sql_help.c:2698 -#: sql_help.c:3265 +#: sql_help.c:982 sql_help.c:1681 sql_help.c:2501 sql_help.c:2726 +#: sql_help.c:3301 msgid "password" msgstr "Passwort" -#: sql_help.c:961 sql_help.c:1668 sql_help.c:2474 sql_help.c:2699 -#: sql_help.c:3266 +#: sql_help.c:983 sql_help.c:1682 sql_help.c:2502 sql_help.c:2727 +#: sql_help.c:3302 msgid "timestamp" msgstr "Zeit" -#: sql_help.c:965 sql_help.c:969 sql_help.c:972 sql_help.c:975 sql_help.c:1672 -#: sql_help.c:1676 sql_help.c:1679 sql_help.c:1682 sql_help.c:3932 -#: sql_help.c:4395 +#: sql_help.c:987 sql_help.c:991 sql_help.c:994 sql_help.c:997 sql_help.c:1686 +#: sql_help.c:1690 sql_help.c:1693 sql_help.c:1696 sql_help.c:3970 +#: sql_help.c:4437 msgid "database_name" msgstr "Datenbankname" -#: sql_help.c:1081 sql_help.c:2766 +#: sql_help.c:1104 sql_help.c:2796 msgid "increment" msgstr "Inkrement" -#: sql_help.c:1082 sql_help.c:2767 +#: sql_help.c:1105 sql_help.c:2797 msgid "minvalue" msgstr "Minwert" -#: sql_help.c:1083 sql_help.c:2768 +#: sql_help.c:1106 sql_help.c:2798 msgid "maxvalue" msgstr "Maxwert" -#: sql_help.c:1084 sql_help.c:2769 sql_help.c:4615 sql_help.c:4719 -#: sql_help.c:4873 sql_help.c:5049 sql_help.c:5118 +#: sql_help.c:1107 sql_help.c:2799 sql_help.c:4657 sql_help.c:4761 +#: sql_help.c:4915 sql_help.c:5093 sql_help.c:5162 msgid "start" msgstr "Start" -#: sql_help.c:1085 sql_help.c:1374 +#: sql_help.c:1108 sql_help.c:1382 msgid "restart" msgstr "Restart" -#: sql_help.c:1086 sql_help.c:2770 +#: sql_help.c:1109 sql_help.c:2800 msgid "cache" msgstr "Cache" -#: sql_help.c:1131 +#: sql_help.c:1154 msgid "new_target" msgstr "neues_Ziel" -#: sql_help.c:1150 sql_help.c:2823 +#: sql_help.c:1173 sql_help.c:2853 msgid "conninfo" msgstr "Verbindungsinfo" -#: sql_help.c:1152 sql_help.c:1156 sql_help.c:1160 sql_help.c:2824 +#: sql_help.c:1175 sql_help.c:1179 sql_help.c:1183 sql_help.c:2854 msgid "publication_name" msgstr "Publikationsname" -#: sql_help.c:1153 sql_help.c:1157 sql_help.c:1161 +#: sql_help.c:1176 sql_help.c:1180 sql_help.c:1184 msgid "publication_option" msgstr "Publikationsoption" -#: sql_help.c:1164 +#: sql_help.c:1187 msgid "refresh_option" msgstr "Refresh-Option" -#: sql_help.c:1169 sql_help.c:2825 +#: sql_help.c:1192 sql_help.c:2855 msgid "subscription_parameter" msgstr "Subskriptionsparameter" -#: sql_help.c:1172 +#: sql_help.c:1195 msgid "skip_option" msgstr "Skip-Option" -#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1344 sql_help.c:1352 +#: sql_help.c:1357 sql_help.c:1360 msgid "partition_name" msgstr "Partitionsname" -#: sql_help.c:1340 sql_help.c:1346 sql_help.c:1348 sql_help.c:2379 -#: sql_help.c:2956 +#: sql_help.c:1358 sql_help.c:2405 sql_help.c:2987 msgid "partition_bound_spec" msgstr "Partitionsbegrenzungsangabe" -#: sql_help.c:1345 sql_help.c:1350 -msgid "partition_name1" -msgstr "Partitionsname1" - -#: sql_help.c:1347 sql_help.c:1351 -msgid "partition_name2" -msgstr "Partitionsname2" - -#: sql_help.c:1371 sql_help.c:1421 sql_help.c:2970 +#: sql_help.c:1379 sql_help.c:1430 sql_help.c:3001 msgid "sequence_options" msgstr "Sequenzoptionen" -#: sql_help.c:1373 +#: sql_help.c:1381 msgid "sequence_option" msgstr "Sequenzoption" -#: sql_help.c:1387 +#: sql_help.c:1395 msgid "table_constraint_using_index" msgstr "Tabellen-Constraint-für-Index" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1397 sql_help.c:1398 +#: sql_help.c:1404 sql_help.c:1405 sql_help.c:1406 sql_help.c:1407 msgid "rewrite_rule_name" msgstr "Regelname" -#: sql_help.c:1410 sql_help.c:2391 sql_help.c:2995 +#: sql_help.c:1419 sql_help.c:2419 sql_help.c:3031 msgid "and partition_bound_spec is:" msgstr "und Partitionsbegrenzungsangabe Folgendes ist:" -#: sql_help.c:1411 sql_help.c:1412 sql_help.c:1413 sql_help.c:2392 -#: sql_help.c:2393 sql_help.c:2394 sql_help.c:2996 sql_help.c:2997 -#: sql_help.c:2998 +#: sql_help.c:1420 sql_help.c:1421 sql_help.c:1422 sql_help.c:2420 +#: sql_help.c:2421 sql_help.c:2422 sql_help.c:3032 sql_help.c:3033 +#: sql_help.c:3034 msgid "partition_bound_expr" msgstr "Partitionsbegrenzungsausdruck" -#: sql_help.c:1414 sql_help.c:1415 sql_help.c:2395 sql_help.c:2396 -#: sql_help.c:2999 sql_help.c:3000 +#: sql_help.c:1423 sql_help.c:1424 sql_help.c:2423 sql_help.c:2424 +#: sql_help.c:3035 sql_help.c:3036 msgid "numeric_literal" msgstr "numerische_Konstante" -#: sql_help.c:1416 +#: sql_help.c:1425 msgid "and column_constraint is:" msgstr "und Spalten-Constraint Folgendes ist:" -#: sql_help.c:1419 sql_help.c:2386 sql_help.c:2427 sql_help.c:2636 -#: sql_help.c:2968 +#: sql_help.c:1428 sql_help.c:2412 sql_help.c:2455 sql_help.c:2664 +#: sql_help.c:2999 msgid "default_expr" msgstr "Vorgabeausdruck" -#: sql_help.c:1420 sql_help.c:2387 sql_help.c:2969 +#: sql_help.c:1429 sql_help.c:2413 sql_help.c:3000 msgid "generation_expr" msgstr "Generierungsausdruck" -#: sql_help.c:1422 sql_help.c:1423 sql_help.c:1432 sql_help.c:1434 -#: sql_help.c:1438 sql_help.c:2971 sql_help.c:2972 sql_help.c:2981 -#: sql_help.c:2983 sql_help.c:2987 +#: sql_help.c:1431 sql_help.c:1432 sql_help.c:1443 sql_help.c:1446 +#: sql_help.c:1450 sql_help.c:3002 sql_help.c:3003 sql_help.c:3014 +#: sql_help.c:3017 sql_help.c:3021 msgid "index_parameters" msgstr "Indexparameter" -#: sql_help.c:1424 sql_help.c:1441 sql_help.c:2973 sql_help.c:2990 +#: sql_help.c:1433 sql_help.c:1454 sql_help.c:3004 sql_help.c:3025 msgid "reftable" msgstr "Reftabelle" -#: sql_help.c:1425 sql_help.c:1442 sql_help.c:2974 sql_help.c:2991 +#: sql_help.c:1434 sql_help.c:1455 sql_help.c:1456 sql_help.c:3005 +#: sql_help.c:3026 sql_help.c:3027 msgid "refcolumn" msgstr "Refspalte" -#: sql_help.c:1426 sql_help.c:1427 sql_help.c:1443 sql_help.c:1444 -#: sql_help.c:2975 sql_help.c:2976 sql_help.c:2992 sql_help.c:2993 +#: sql_help.c:1435 sql_help.c:1436 sql_help.c:1457 sql_help.c:1458 +#: sql_help.c:3006 sql_help.c:3007 sql_help.c:3028 sql_help.c:3029 msgid "referential_action" msgstr "Fremdschlüsselaktion" -#: sql_help.c:1428 sql_help.c:2388 sql_help.c:2977 +#: sql_help.c:1437 sql_help.c:2414 sql_help.c:3008 msgid "and table_constraint is:" msgstr "und Tabellen-Constraint Folgendes ist:" -#: sql_help.c:1436 sql_help.c:2985 +#: sql_help.c:1448 sql_help.c:3019 msgid "exclude_element" msgstr "Exclude-Element" -#: sql_help.c:1437 sql_help.c:2986 sql_help.c:4613 sql_help.c:4717 -#: sql_help.c:4871 sql_help.c:5047 sql_help.c:5116 +#: sql_help.c:1449 sql_help.c:3020 sql_help.c:4655 sql_help.c:4759 +#: sql_help.c:4913 sql_help.c:5091 sql_help.c:5160 msgid "operator" msgstr "Operator" -#: sql_help.c:1439 sql_help.c:2507 sql_help.c:2988 +#: sql_help.c:1451 sql_help.c:2535 sql_help.c:3022 msgid "predicate" msgstr "Prädikat" -#: sql_help.c:1445 +#: sql_help.c:1459 msgid "and table_constraint_using_index is:" msgstr "und Tabellen-Constraint-für-Index Folgendes ist:" -#: sql_help.c:1448 sql_help.c:3001 +#: sql_help.c:1462 sql_help.c:3037 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "Indexparameter bei UNIQUE-, PRIMARY KEY- und EXCLUDE-Constraints sind:" -#: sql_help.c:1453 sql_help.c:3006 +#: sql_help.c:1467 sql_help.c:3042 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "Exclude-Element in einem EXCLUDE-Constraint ist:" -#: sql_help.c:1457 sql_help.c:2500 sql_help.c:2933 sql_help.c:2946 -#: sql_help.c:2960 sql_help.c:3010 sql_help.c:4031 +#: sql_help.c:1471 sql_help.c:2528 sql_help.c:2964 sql_help.c:2977 +#: sql_help.c:2991 sql_help.c:3046 sql_help.c:4071 msgid "opclass" msgstr "Opklasse" -#: sql_help.c:1458 sql_help.c:2501 sql_help.c:3011 +#: sql_help.c:1472 sql_help.c:2529 sql_help.c:3047 msgid "opclass_parameter" msgstr "Opklassen-Parameter" -#: sql_help.c:1460 sql_help.c:3013 +#: sql_help.c:1474 sql_help.c:3049 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "Fremdschlüsselaktion in FOREIGN KEY/REFERENCES ist:" -#: sql_help.c:1478 sql_help.c:1481 sql_help.c:3050 +#: sql_help.c:1492 sql_help.c:1495 sql_help.c:3086 msgid "tablespace_option" msgstr "Tablespace-Option" -#: sql_help.c:1502 sql_help.c:1505 sql_help.c:1511 sql_help.c:1515 +#: sql_help.c:1516 sql_help.c:1519 sql_help.c:1525 sql_help.c:1529 msgid "token_type" msgstr "Tokentyp" -#: sql_help.c:1503 sql_help.c:1506 +#: sql_help.c:1517 sql_help.c:1520 msgid "dictionary_name" msgstr "Wörterbuchname" -#: sql_help.c:1508 sql_help.c:1512 +#: sql_help.c:1522 sql_help.c:1526 msgid "old_dictionary" msgstr "altes_Wörterbuch" -#: sql_help.c:1509 sql_help.c:1513 +#: sql_help.c:1523 sql_help.c:1527 msgid "new_dictionary" msgstr "neues_Wörterbuch" -#: sql_help.c:1608 sql_help.c:1622 sql_help.c:1625 sql_help.c:1626 -#: sql_help.c:3203 +#: sql_help.c:1622 sql_help.c:1636 sql_help.c:1639 sql_help.c:1640 +#: sql_help.c:3239 msgid "attribute_name" msgstr "Attributname" -#: sql_help.c:1609 +#: sql_help.c:1623 msgid "new_attribute_name" msgstr "neuer_Attributname" -#: sql_help.c:1613 sql_help.c:1617 +#: sql_help.c:1627 sql_help.c:1631 msgid "new_enum_value" msgstr "neuer_Enum-Wert" -#: sql_help.c:1614 +#: sql_help.c:1628 msgid "neighbor_enum_value" msgstr "Nachbar-Enum-Wert" -#: sql_help.c:1616 +#: sql_help.c:1630 msgid "existing_enum_value" msgstr "existierender_Enum-Wert" -#: sql_help.c:1619 +#: sql_help.c:1633 msgid "property" msgstr "Eigenschaft" -#: sql_help.c:1695 sql_help.c:2371 sql_help.c:2380 sql_help.c:2782 -#: sql_help.c:3283 sql_help.c:3734 sql_help.c:3941 sql_help.c:3987 -#: sql_help.c:4404 +#: sql_help.c:1709 sql_help.c:2397 sql_help.c:2406 sql_help.c:2812 +#: sql_help.c:3319 sql_help.c:3772 sql_help.c:3979 sql_help.c:4025 +#: sql_help.c:4446 msgid "server_name" msgstr "Servername" -#: sql_help.c:1727 sql_help.c:1730 sql_help.c:3298 +#: sql_help.c:1741 sql_help.c:1744 sql_help.c:3334 msgid "view_option_name" msgstr "Sichtoptionsname" -#: sql_help.c:1728 sql_help.c:3299 +#: sql_help.c:1742 sql_help.c:3335 msgid "view_option_value" msgstr "Sichtoptionswert" -#: sql_help.c:1749 sql_help.c:5016 +#: sql_help.c:1763 sql_help.c:5060 msgid "table_and_columns" msgstr "Tabelle-und-Spalten" -#: sql_help.c:1750 sql_help.c:1810 sql_help.c:2004 sql_help.c:3783 -#: sql_help.c:4239 sql_help.c:5017 +#: sql_help.c:1764 sql_help.c:1824 sql_help.c:2019 sql_help.c:3821 +#: sql_help.c:4281 sql_help.c:5061 msgid "where option can be one of:" msgstr "wobei Option eine der folgenden sein kann:" -#: sql_help.c:1751 sql_help.c:1752 sql_help.c:1811 sql_help.c:2006 -#: sql_help.c:2010 sql_help.c:2192 sql_help.c:3784 sql_help.c:3785 -#: sql_help.c:3786 sql_help.c:3787 sql_help.c:3788 sql_help.c:3789 -#: sql_help.c:3790 sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 -#: sql_help.c:4240 sql_help.c:4242 sql_help.c:5018 sql_help.c:5019 -#: sql_help.c:5020 sql_help.c:5021 sql_help.c:5022 sql_help.c:5023 -#: sql_help.c:5024 sql_help.c:5025 sql_help.c:5026 sql_help.c:5028 -#: sql_help.c:5029 +#: sql_help.c:1765 sql_help.c:1766 sql_help.c:1825 sql_help.c:2021 +#: sql_help.c:2025 sql_help.c:2208 sql_help.c:3822 sql_help.c:3823 +#: sql_help.c:3824 sql_help.c:3825 sql_help.c:3826 sql_help.c:3827 +#: sql_help.c:3828 sql_help.c:3829 sql_help.c:3830 sql_help.c:3831 +#: sql_help.c:4282 sql_help.c:4284 sql_help.c:5062 sql_help.c:5063 +#: sql_help.c:5064 sql_help.c:5065 sql_help.c:5066 sql_help.c:5067 +#: sql_help.c:5068 sql_help.c:5069 sql_help.c:5070 sql_help.c:5072 +#: sql_help.c:5073 msgid "boolean" msgstr "boolean" -#: sql_help.c:1753 sql_help.c:5030 +#: sql_help.c:1767 sql_help.c:5074 msgid "size" msgstr "Größe" -#: sql_help.c:1754 sql_help.c:5031 +#: sql_help.c:1768 sql_help.c:5075 msgid "and table_and_columns is:" msgstr "und Tabelle-und-Spalten Folgendes ist:" -#: sql_help.c:1770 sql_help.c:4778 sql_help.c:4780 sql_help.c:4804 +#: sql_help.c:1784 sql_help.c:4820 sql_help.c:4822 sql_help.c:4846 msgid "transaction_mode" msgstr "Transaktionsmodus" -#: sql_help.c:1771 sql_help.c:4781 sql_help.c:4805 +#: sql_help.c:1785 sql_help.c:4823 sql_help.c:4847 msgid "where transaction_mode is one of:" msgstr "wobei Transaktionsmodus Folgendes sein kann:" -#: sql_help.c:1780 sql_help.c:4623 sql_help.c:4632 sql_help.c:4636 -#: sql_help.c:4640 sql_help.c:4643 sql_help.c:4881 sql_help.c:4890 -#: sql_help.c:4894 sql_help.c:4898 sql_help.c:4901 sql_help.c:5126 -#: sql_help.c:5135 sql_help.c:5139 sql_help.c:5143 sql_help.c:5146 +#: sql_help.c:1794 sql_help.c:4665 sql_help.c:4674 sql_help.c:4678 +#: sql_help.c:4682 sql_help.c:4685 sql_help.c:4923 sql_help.c:4932 +#: sql_help.c:4936 sql_help.c:4940 sql_help.c:4943 sql_help.c:5170 +#: sql_help.c:5179 sql_help.c:5183 sql_help.c:5187 sql_help.c:5190 msgid "argument" msgstr "Argument" -#: sql_help.c:1876 +#: sql_help.c:1890 msgid "relation_name" msgstr "Relationsname" -#: sql_help.c:1881 sql_help.c:3935 sql_help.c:4398 +#: sql_help.c:1895 sql_help.c:3973 sql_help.c:4440 msgid "domain_name" msgstr "Domänenname" -#: sql_help.c:1903 +#: sql_help.c:1917 msgid "policy_name" msgstr "Policy-Name" -#: sql_help.c:1916 +#: sql_help.c:1930 msgid "rule_name" msgstr "Regelname" -#: sql_help.c:1935 sql_help.c:4537 +#: sql_help.c:1949 sql_help.c:4579 msgid "string_literal" msgstr "Zeichenkettenkonstante" -#: sql_help.c:1960 sql_help.c:4201 sql_help.c:4451 +#: sql_help.c:1974 sql_help.c:4243 sql_help.c:4493 msgid "transaction_id" msgstr "Transaktions-ID" -#: sql_help.c:1994 sql_help.c:2001 sql_help.c:4057 +#: sql_help.c:2009 sql_help.c:2016 sql_help.c:4097 msgid "filename" msgstr "Dateiname" -#: sql_help.c:1995 sql_help.c:2002 sql_help.c:2721 sql_help.c:2722 -#: sql_help.c:2723 +#: sql_help.c:2010 sql_help.c:2017 sql_help.c:2749 sql_help.c:2750 +#: sql_help.c:2751 msgid "command" msgstr "Befehl" -#: sql_help.c:1997 sql_help.c:2720 sql_help.c:3153 sql_help.c:3334 -#: sql_help.c:4041 sql_help.c:4124 sql_help.c:4127 sql_help.c:4130 -#: sql_help.c:4606 sql_help.c:4608 sql_help.c:4710 sql_help.c:4712 -#: sql_help.c:4864 sql_help.c:4866 sql_help.c:4983 sql_help.c:5109 -#: sql_help.c:5111 +#: sql_help.c:2012 sql_help.c:2748 sql_help.c:3189 sql_help.c:3371 +#: sql_help.c:4081 sql_help.c:4166 sql_help.c:4169 sql_help.c:4172 +#: sql_help.c:4648 sql_help.c:4650 sql_help.c:4752 sql_help.c:4754 +#: sql_help.c:4906 sql_help.c:4908 sql_help.c:5026 sql_help.c:5153 +#: sql_help.c:5155 msgid "condition" msgstr "Bedingung" -#: sql_help.c:2000 sql_help.c:2541 sql_help.c:3036 sql_help.c:3300 -#: sql_help.c:3318 sql_help.c:4022 +#: sql_help.c:2015 sql_help.c:2569 sql_help.c:3072 sql_help.c:3336 +#: sql_help.c:3354 sql_help.c:4061 msgid "query" msgstr "Anfrage" -#: sql_help.c:2005 +#: sql_help.c:2020 msgid "format_name" msgstr "Formatname" -#: sql_help.c:2007 +#: sql_help.c:2022 msgid "delimiter_character" msgstr "Trennzeichen" -#: sql_help.c:2008 +#: sql_help.c:2023 msgid "null_string" msgstr "Null-Zeichenkette" -#: sql_help.c:2009 +#: sql_help.c:2024 msgid "default_string" msgstr "Vorgabewert-Zeichenkette" -#: sql_help.c:2011 +#: sql_help.c:2026 msgid "quote_character" msgstr "Quote-Zeichen" -#: sql_help.c:2012 +#: sql_help.c:2027 msgid "escape_character" msgstr "Escape-Zeichen" -#: sql_help.c:2016 +#: sql_help.c:2031 msgid "error_action" msgstr "Fehleraktion" -#: sql_help.c:2017 +#: sql_help.c:2032 +#, fuzzy +#| msgid "syntax error" +msgid "maxerror" +msgstr "Syntaxfehler" + +#: sql_help.c:2033 msgid "encoding_name" msgstr "Kodierungsname" -#: sql_help.c:2018 +#: sql_help.c:2034 msgid "verbosity" msgstr "Verbose-Modus" -#: sql_help.c:2029 +#: sql_help.c:2045 msgid "access_method_type" msgstr "Zugriffsmethodentyp" -#: sql_help.c:2100 sql_help.c:2119 sql_help.c:2122 +#: sql_help.c:2116 sql_help.c:2135 sql_help.c:2138 msgid "arg_data_type" msgstr "Arg-Datentyp" -#: sql_help.c:2101 sql_help.c:2123 sql_help.c:2131 +#: sql_help.c:2117 sql_help.c:2139 sql_help.c:2147 msgid "sfunc" msgstr "Übergangsfunktion" -#: sql_help.c:2102 sql_help.c:2124 sql_help.c:2132 +#: sql_help.c:2118 sql_help.c:2140 sql_help.c:2148 msgid "state_data_type" msgstr "Zustandsdatentyp" -#: sql_help.c:2103 sql_help.c:2125 sql_help.c:2133 +#: sql_help.c:2119 sql_help.c:2141 sql_help.c:2149 msgid "state_data_size" msgstr "Zustandsdatengröße" -#: sql_help.c:2104 sql_help.c:2126 sql_help.c:2134 +#: sql_help.c:2120 sql_help.c:2142 sql_help.c:2150 msgid "ffunc" msgstr "Abschlussfunktion" -#: sql_help.c:2105 sql_help.c:2135 +#: sql_help.c:2121 sql_help.c:2151 msgid "combinefunc" msgstr "Combine-Funktion" -#: sql_help.c:2106 sql_help.c:2136 +#: sql_help.c:2122 sql_help.c:2152 msgid "serialfunc" msgstr "Serialisierungsfunktion" -#: sql_help.c:2107 sql_help.c:2137 +#: sql_help.c:2123 sql_help.c:2153 msgid "deserialfunc" msgstr "Deserialisierungsfunktion" -#: sql_help.c:2108 sql_help.c:2127 sql_help.c:2138 +#: sql_help.c:2124 sql_help.c:2143 sql_help.c:2154 msgid "initial_condition" msgstr "Anfangswert" -#: sql_help.c:2109 sql_help.c:2139 +#: sql_help.c:2125 sql_help.c:2155 msgid "msfunc" msgstr "Moving-Übergangsfunktion" -#: sql_help.c:2110 sql_help.c:2140 +#: sql_help.c:2126 sql_help.c:2156 msgid "minvfunc" msgstr "Moving-Inversfunktion" -#: sql_help.c:2111 sql_help.c:2141 +#: sql_help.c:2127 sql_help.c:2157 msgid "mstate_data_type" msgstr "Moving-Zustandsdatentyp" -#: sql_help.c:2112 sql_help.c:2142 +#: sql_help.c:2128 sql_help.c:2158 msgid "mstate_data_size" msgstr "Moving-Zustandsdatengröße" -#: sql_help.c:2113 sql_help.c:2143 +#: sql_help.c:2129 sql_help.c:2159 msgid "mffunc" msgstr "Moving-Abschlussfunktion" -#: sql_help.c:2114 sql_help.c:2144 +#: sql_help.c:2130 sql_help.c:2160 msgid "minitial_condition" msgstr "Moving-Anfangswert" -#: sql_help.c:2115 sql_help.c:2145 +#: sql_help.c:2131 sql_help.c:2161 msgid "sort_operator" msgstr "Sortieroperator" -#: sql_help.c:2128 +#: sql_help.c:2144 msgid "or the old syntax" msgstr "oder die alte Syntax" -#: sql_help.c:2130 +#: sql_help.c:2146 msgid "base_type" msgstr "Basistyp" -#: sql_help.c:2188 sql_help.c:2238 +#: sql_help.c:2204 sql_help.c:2254 msgid "locale" msgstr "Locale" -#: sql_help.c:2189 sql_help.c:2239 +#: sql_help.c:2205 sql_help.c:2255 msgid "lc_collate" msgstr "lc_collate" -#: sql_help.c:2190 sql_help.c:2240 +#: sql_help.c:2206 sql_help.c:2256 msgid "lc_ctype" msgstr "lc_ctype" -#: sql_help.c:2191 sql_help.c:4504 +#: sql_help.c:2207 sql_help.c:4546 msgid "provider" msgstr "Provider" -#: sql_help.c:2193 +#: sql_help.c:2209 msgid "rules" msgstr "Regeln" -#: sql_help.c:2194 sql_help.c:2301 +#: sql_help.c:2210 sql_help.c:2317 msgid "version" msgstr "Version" -#: sql_help.c:2196 +#: sql_help.c:2212 msgid "existing_collation" msgstr "existierende_Sortierfolge" -#: sql_help.c:2206 +#: sql_help.c:2222 msgid "source_encoding" msgstr "Quellkodierung" -#: sql_help.c:2207 +#: sql_help.c:2223 msgid "dest_encoding" msgstr "Zielkodierung" -#: sql_help.c:2235 sql_help.c:3076 +#: sql_help.c:2251 sql_help.c:3112 msgid "template" msgstr "Vorlage" -#: sql_help.c:2236 +#: sql_help.c:2252 msgid "encoding" msgstr "Kodierung" -#: sql_help.c:2237 +#: sql_help.c:2253 msgid "strategy" msgstr "Strategie" -#: sql_help.c:2241 +#: sql_help.c:2257 msgid "builtin_locale" msgstr "Builtin-Locale" -#: sql_help.c:2242 +#: sql_help.c:2258 msgid "icu_locale" msgstr "ICU-Locale" -#: sql_help.c:2243 +#: sql_help.c:2259 msgid "icu_rules" msgstr "ICU-Regeln" -#: sql_help.c:2244 +#: sql_help.c:2260 msgid "locale_provider" msgstr "Locale-Provider" -#: sql_help.c:2245 +#: sql_help.c:2261 msgid "collation_version" msgstr "Sortierfolgenversion" -#: sql_help.c:2250 +#: sql_help.c:2266 msgid "oid" msgstr "OID" -#: sql_help.c:2271 -msgid "where domain_constraint is:" -msgstr "wobei Domänen-Constraint Folgendes ist:" - -#: sql_help.c:2285 sql_help.c:2718 sql_help.c:3149 +#: sql_help.c:2301 sql_help.c:2746 sql_help.c:3185 msgid "event" msgstr "Ereignis" -#: sql_help.c:2286 +#: sql_help.c:2302 msgid "filter_variable" msgstr "Filtervariable" -#: sql_help.c:2287 +#: sql_help.c:2303 msgid "filter_value" msgstr "Filterwert" -#: sql_help.c:2383 sql_help.c:2965 +#: sql_help.c:2394 sql_help.c:2958 +msgid "source_table" +msgstr "Quelltabelle" + +#: sql_help.c:2395 sql_help.c:2959 +msgid "like_option" +msgstr "Like-Option" + +#: sql_help.c:2409 sql_help.c:2996 msgid "where column_constraint is:" msgstr "wobei Spalten-Constraint Folgendes ist:" -#: sql_help.c:2428 +#: sql_help.c:2418 sql_help.c:3030 +msgid "and like_option is:" +msgstr "und Like-Option Folgendes ist:" + +#: sql_help.c:2456 msgid "rettype" msgstr "Rückgabetyp" -#: sql_help.c:2430 +#: sql_help.c:2458 msgid "column_type" msgstr "Spaltentyp" -#: sql_help.c:2439 sql_help.c:2642 +#: sql_help.c:2467 sql_help.c:2670 msgid "definition" msgstr "Definition" -#: sql_help.c:2440 sql_help.c:2643 +#: sql_help.c:2468 sql_help.c:2671 msgid "obj_file" msgstr "Objektdatei" -#: sql_help.c:2441 sql_help.c:2644 +#: sql_help.c:2469 sql_help.c:2672 msgid "link_symbol" msgstr "Linksymbol" -#: sql_help.c:2442 sql_help.c:2645 +#: sql_help.c:2470 sql_help.c:2673 msgid "sql_body" msgstr "SQL-Rumpf" -#: sql_help.c:2480 sql_help.c:2703 sql_help.c:3272 +#: sql_help.c:2508 sql_help.c:2731 sql_help.c:3308 msgid "uid" msgstr "Uid" -#: sql_help.c:2496 sql_help.c:2537 sql_help.c:2934 sql_help.c:2947 -#: sql_help.c:2961 sql_help.c:3032 +#: sql_help.c:2524 sql_help.c:2565 sql_help.c:2965 sql_help.c:2978 +#: sql_help.c:2992 sql_help.c:3068 msgid "method" msgstr "Methode" -#: sql_help.c:2518 +#: sql_help.c:2546 msgid "call_handler" msgstr "Handler" -#: sql_help.c:2519 +#: sql_help.c:2547 msgid "inline_handler" msgstr "Inline-Handler" -#: sql_help.c:2520 +#: sql_help.c:2548 msgid "valfunction" msgstr "Valfunktion" -#: sql_help.c:2578 +#: sql_help.c:2606 msgid "family_name" msgstr "Familienname" -#: sql_help.c:2589 +#: sql_help.c:2617 msgid "storage_type" msgstr "Storage-Typ" -#: sql_help.c:2724 sql_help.c:3156 +#: sql_help.c:2752 sql_help.c:3192 msgid "where event can be one of:" msgstr "wobei Ereignis eins der folgenden sein kann:" -#: sql_help.c:2744 sql_help.c:2746 +#: sql_help.c:2772 sql_help.c:2774 msgid "schema_element" msgstr "Schemaelement" -#: sql_help.c:2783 +#: sql_help.c:2813 msgid "server_type" msgstr "Servertyp" -#: sql_help.c:2784 +#: sql_help.c:2814 msgid "server_version" msgstr "Serverversion" -#: sql_help.c:2785 sql_help.c:3938 sql_help.c:4401 +#: sql_help.c:2815 sql_help.c:3976 sql_help.c:4443 msgid "fdw_name" msgstr "FDW-Name" -#: sql_help.c:2802 sql_help.c:2805 +#: sql_help.c:2832 sql_help.c:2835 msgid "statistics_name" msgstr "Statistikname" -#: sql_help.c:2806 +#: sql_help.c:2836 msgid "statistics_kind" msgstr "Statistikart" -#: sql_help.c:2822 +#: sql_help.c:2852 msgid "subscription_name" msgstr "Subskriptionsname" -#: sql_help.c:2927 -msgid "source_table" -msgstr "Quelltabelle" - -#: sql_help.c:2928 -msgid "like_option" -msgstr "Like-Option" - -#: sql_help.c:2994 -msgid "and like_option is:" -msgstr "und Like-Option Folgendes ist:" - -#: sql_help.c:3049 +#: sql_help.c:3085 msgid "directory" msgstr "Verzeichnis" -#: sql_help.c:3063 +#: sql_help.c:3099 msgid "parser_name" msgstr "Parser-Name" -#: sql_help.c:3064 +#: sql_help.c:3100 msgid "source_config" msgstr "Quellkonfig" -#: sql_help.c:3093 +#: sql_help.c:3129 msgid "start_function" msgstr "Startfunktion" -#: sql_help.c:3094 +#: sql_help.c:3130 msgid "gettoken_function" msgstr "Gettext-Funktion" -#: sql_help.c:3095 +#: sql_help.c:3131 msgid "end_function" msgstr "Endfunktion" -#: sql_help.c:3096 +#: sql_help.c:3132 msgid "lextypes_function" msgstr "Lextypenfunktion" -#: sql_help.c:3097 +#: sql_help.c:3133 msgid "headline_function" msgstr "Headline-Funktion" -#: sql_help.c:3109 +#: sql_help.c:3145 msgid "init_function" msgstr "Init-Funktion" -#: sql_help.c:3110 +#: sql_help.c:3146 msgid "lexize_function" msgstr "Lexize-Funktion" -#: sql_help.c:3123 +#: sql_help.c:3159 msgid "from_sql_function_name" msgstr "From-SQL-Funktionsname" -#: sql_help.c:3125 +#: sql_help.c:3161 msgid "to_sql_function_name" msgstr "To-SQL-Funktionsname" -#: sql_help.c:3151 +#: sql_help.c:3187 msgid "referenced_table_name" msgstr "verwiesener_Tabellenname" -#: sql_help.c:3152 +#: sql_help.c:3188 msgid "transition_relation_name" msgstr "Übergangsrelationsname" -#: sql_help.c:3155 +#: sql_help.c:3191 msgid "arguments" msgstr "Argumente" -#: sql_help.c:3207 +#: sql_help.c:3243 msgid "label" msgstr "Label" -#: sql_help.c:3209 +#: sql_help.c:3245 msgid "subtype" msgstr "Untertyp" -#: sql_help.c:3210 +#: sql_help.c:3246 msgid "subtype_operator_class" msgstr "Untertyp-Operatorklasse" -#: sql_help.c:3212 +#: sql_help.c:3248 msgid "canonical_function" msgstr "Canonical-Funktion" -#: sql_help.c:3213 +#: sql_help.c:3249 msgid "subtype_diff_function" msgstr "Untertyp-Diff-Funktion" -#: sql_help.c:3214 +#: sql_help.c:3250 msgid "multirange_type_name" msgstr "Multirange-Typname" -#: sql_help.c:3216 +#: sql_help.c:3252 msgid "input_function" msgstr "Eingabefunktion" -#: sql_help.c:3217 +#: sql_help.c:3253 msgid "output_function" msgstr "Ausgabefunktion" -#: sql_help.c:3218 +#: sql_help.c:3254 msgid "receive_function" msgstr "Empfangsfunktion" -#: sql_help.c:3219 +#: sql_help.c:3255 msgid "send_function" msgstr "Sendefunktion" -#: sql_help.c:3220 +#: sql_help.c:3256 msgid "type_modifier_input_function" msgstr "Typmod-Eingabefunktion" -#: sql_help.c:3221 +#: sql_help.c:3257 msgid "type_modifier_output_function" msgstr "Typmod-Ausgabefunktion" -#: sql_help.c:3222 +#: sql_help.c:3258 msgid "analyze_function" msgstr "Analyze-Funktion" -#: sql_help.c:3223 +#: sql_help.c:3259 msgid "subscript_function" msgstr "Subscript-Funktion" -#: sql_help.c:3224 +#: sql_help.c:3260 msgid "internallength" msgstr "interne_Länge" -#: sql_help.c:3225 +#: sql_help.c:3261 msgid "alignment" msgstr "Ausrichtung" -#: sql_help.c:3226 +#: sql_help.c:3262 msgid "storage" msgstr "Speicherung" -#: sql_help.c:3227 +#: sql_help.c:3263 msgid "like_type" msgstr "wie_Typ" -#: sql_help.c:3228 +#: sql_help.c:3264 msgid "category" msgstr "Kategorie" -#: sql_help.c:3229 +#: sql_help.c:3265 msgid "preferred" msgstr "bevorzugt" -#: sql_help.c:3230 +#: sql_help.c:3266 msgid "default" msgstr "Vorgabewert" -#: sql_help.c:3231 +#: sql_help.c:3267 msgid "element" msgstr "Element" -#: sql_help.c:3232 +#: sql_help.c:3268 msgid "delimiter" msgstr "Trennzeichen" -#: sql_help.c:3233 +#: sql_help.c:3269 msgid "collatable" msgstr "sortierbar" -#: sql_help.c:3330 sql_help.c:4017 sql_help.c:4111 sql_help.c:4601 -#: sql_help.c:4704 sql_help.c:4859 sql_help.c:4973 sql_help.c:5104 +#: sql_help.c:3367 sql_help.c:4056 sql_help.c:4152 sql_help.c:4643 +#: sql_help.c:4746 sql_help.c:4901 sql_help.c:5016 sql_help.c:5148 msgid "with_query" msgstr "With-Anfrage" -#: sql_help.c:3332 sql_help.c:4019 sql_help.c:4620 sql_help.c:4626 -#: sql_help.c:4629 sql_help.c:4633 sql_help.c:4637 sql_help.c:4645 -#: sql_help.c:4878 sql_help.c:4884 sql_help.c:4887 sql_help.c:4891 -#: sql_help.c:4895 sql_help.c:4903 sql_help.c:4975 sql_help.c:5123 -#: sql_help.c:5129 sql_help.c:5132 sql_help.c:5136 sql_help.c:5140 -#: sql_help.c:5148 +#: sql_help.c:3369 sql_help.c:4058 sql_help.c:4662 sql_help.c:4668 +#: sql_help.c:4671 sql_help.c:4675 sql_help.c:4679 sql_help.c:4687 +#: sql_help.c:4920 sql_help.c:4926 sql_help.c:4929 sql_help.c:4933 +#: sql_help.c:4937 sql_help.c:4945 sql_help.c:5018 sql_help.c:5167 +#: sql_help.c:5173 sql_help.c:5176 sql_help.c:5180 sql_help.c:5184 +#: sql_help.c:5192 msgid "alias" msgstr "Alias" -#: sql_help.c:3333 sql_help.c:4605 sql_help.c:4647 sql_help.c:4649 -#: sql_help.c:4653 sql_help.c:4655 sql_help.c:4656 sql_help.c:4657 -#: sql_help.c:4709 sql_help.c:4863 sql_help.c:4905 sql_help.c:4907 -#: sql_help.c:4911 sql_help.c:4913 sql_help.c:4914 sql_help.c:4915 -#: sql_help.c:4982 sql_help.c:5108 sql_help.c:5150 sql_help.c:5152 -#: sql_help.c:5156 sql_help.c:5158 sql_help.c:5159 sql_help.c:5160 +#: sql_help.c:3370 sql_help.c:4647 sql_help.c:4689 sql_help.c:4691 +#: sql_help.c:4695 sql_help.c:4697 sql_help.c:4698 sql_help.c:4699 +#: sql_help.c:4751 sql_help.c:4905 sql_help.c:4947 sql_help.c:4949 +#: sql_help.c:4953 sql_help.c:4955 sql_help.c:4956 sql_help.c:4957 +#: sql_help.c:5025 sql_help.c:5152 sql_help.c:5194 sql_help.c:5196 +#: sql_help.c:5200 sql_help.c:5202 sql_help.c:5203 sql_help.c:5204 msgid "from_item" msgstr "From-Element" -#: sql_help.c:3335 sql_help.c:3819 sql_help.c:4168 sql_help.c:4984 +#: sql_help.c:3372 sql_help.c:3857 sql_help.c:4210 sql_help.c:5027 msgid "cursor_name" msgstr "Cursor-Name" -#: sql_help.c:3336 sql_help.c:4025 sql_help.c:4117 sql_help.c:4985 +#: sql_help.c:3373 sql_help.c:4064 sql_help.c:4158 sql_help.c:5028 +#, fuzzy +#| msgid "output_name" +msgid "output_alias" +msgstr "Ausgabename" + +#: sql_help.c:3374 sql_help.c:4065 sql_help.c:4159 sql_help.c:5029 msgid "output_expression" msgstr "Ausgabeausdruck" -#: sql_help.c:3337 sql_help.c:4026 sql_help.c:4118 sql_help.c:4604 -#: sql_help.c:4707 sql_help.c:4862 sql_help.c:4986 sql_help.c:5107 +#: sql_help.c:3375 sql_help.c:4066 sql_help.c:4160 sql_help.c:4646 +#: sql_help.c:4749 sql_help.c:4904 sql_help.c:5030 sql_help.c:5151 msgid "output_name" msgstr "Ausgabename" -#: sql_help.c:3353 +#: sql_help.c:3391 msgid "code" msgstr "Code" -#: sql_help.c:3758 +#: sql_help.c:3796 msgid "parameter" msgstr "Parameter" -#: sql_help.c:3782 sql_help.c:4193 +#: sql_help.c:3820 sql_help.c:4235 msgid "statement" msgstr "Anweisung" -#: sql_help.c:3818 sql_help.c:4167 +#: sql_help.c:3856 sql_help.c:4209 msgid "direction" msgstr "Richtung" -#: sql_help.c:3820 sql_help.c:4169 +#: sql_help.c:3858 sql_help.c:4211 msgid "where direction can be one of:" msgstr "wobei Richtung eine der folgenden sein kann:" -#: sql_help.c:3821 sql_help.c:3822 sql_help.c:3823 sql_help.c:3824 -#: sql_help.c:3825 sql_help.c:4170 sql_help.c:4171 sql_help.c:4172 -#: sql_help.c:4173 sql_help.c:4174 sql_help.c:4614 sql_help.c:4616 -#: sql_help.c:4718 sql_help.c:4720 sql_help.c:4872 sql_help.c:4874 -#: sql_help.c:5048 sql_help.c:5050 sql_help.c:5117 sql_help.c:5119 +#: sql_help.c:3859 sql_help.c:3860 sql_help.c:3861 sql_help.c:3862 +#: sql_help.c:3863 sql_help.c:4212 sql_help.c:4213 sql_help.c:4214 +#: sql_help.c:4215 sql_help.c:4216 sql_help.c:4656 sql_help.c:4658 +#: sql_help.c:4760 sql_help.c:4762 sql_help.c:4914 sql_help.c:4916 +#: sql_help.c:5092 sql_help.c:5094 sql_help.c:5161 sql_help.c:5163 msgid "count" msgstr "Anzahl" -#: sql_help.c:3928 sql_help.c:4391 +#: sql_help.c:3966 sql_help.c:4433 msgid "sequence_name" msgstr "Sequenzname" -#: sql_help.c:3946 sql_help.c:4409 +#: sql_help.c:3984 sql_help.c:4451 msgid "arg_name" msgstr "Argname" -#: sql_help.c:3947 sql_help.c:4410 +#: sql_help.c:3985 sql_help.c:4452 msgid "arg_type" msgstr "Argtyp" -#: sql_help.c:3954 sql_help.c:4417 +#: sql_help.c:3992 sql_help.c:4459 msgid "loid" msgstr "Large-Object-OID" -#: sql_help.c:3985 +#: sql_help.c:4023 msgid "remote_schema" msgstr "fernes_Schema" -#: sql_help.c:3988 +#: sql_help.c:4026 msgid "local_schema" msgstr "lokales_Schema" -#: sql_help.c:4023 +#: sql_help.c:4062 msgid "conflict_target" msgstr "Konfliktziel" -#: sql_help.c:4024 +#: sql_help.c:4063 msgid "conflict_action" msgstr "Konfliktaktion" -#: sql_help.c:4027 +#: sql_help.c:4067 msgid "where conflict_target can be one of:" msgstr "wobei Konfliktziel Folgendes sein kann:" -#: sql_help.c:4028 +#: sql_help.c:4068 msgid "index_column_name" msgstr "Indexspaltenname" -#: sql_help.c:4029 +#: sql_help.c:4069 msgid "index_expression" msgstr "Indexausdruck" -#: sql_help.c:4032 +#: sql_help.c:4072 msgid "index_predicate" msgstr "Indexprädikat" -#: sql_help.c:4034 +#: sql_help.c:4074 msgid "and conflict_action is one of:" msgstr "und Konfliktaktion Folgendes sein kann:" -#: sql_help.c:4040 sql_help.c:4141 sql_help.c:4981 +#: sql_help.c:4080 sql_help.c:4183 sql_help.c:5024 msgid "sub-SELECT" msgstr "Sub-SELECT" -#: sql_help.c:4049 sql_help.c:4182 sql_help.c:4957 +#: sql_help.c:4089 sql_help.c:4224 sql_help.c:4999 msgid "channel" msgstr "Kanal" -#: sql_help.c:4071 +#: sql_help.c:4111 msgid "lockmode" msgstr "Sperrmodus" -#: sql_help.c:4072 +#: sql_help.c:4112 msgid "where lockmode is one of:" msgstr "wobei Sperrmodus Folgendes sein kann:" -#: sql_help.c:4112 +#: sql_help.c:4153 msgid "target_table_name" msgstr "Zieltabellenname" -#: sql_help.c:4113 +#: sql_help.c:4154 msgid "target_alias" msgstr "Zielalias" -#: sql_help.c:4114 +#: sql_help.c:4155 msgid "data_source" msgstr "Datenquelle" -#: sql_help.c:4115 sql_help.c:4650 sql_help.c:4908 sql_help.c:5153 +#: sql_help.c:4156 sql_help.c:4692 sql_help.c:4950 sql_help.c:5197 msgid "join_condition" msgstr "Verbundbedingung" -#: sql_help.c:4116 +#: sql_help.c:4157 msgid "when_clause" msgstr "When-Klausel" -#: sql_help.c:4119 +#: sql_help.c:4161 msgid "where data_source is:" msgstr "wobei Datenquelle Folgendes ist:" -#: sql_help.c:4120 +#: sql_help.c:4162 msgid "source_table_name" msgstr "Quelltabellenname" -#: sql_help.c:4121 +#: sql_help.c:4163 msgid "source_query" msgstr "Quellanfrage" -#: sql_help.c:4122 +#: sql_help.c:4164 msgid "source_alias" msgstr "Quellalias" -#: sql_help.c:4123 +#: sql_help.c:4165 msgid "and when_clause is:" msgstr "und When-Klausel Folgendes ist:" -#: sql_help.c:4125 sql_help.c:4128 +#: sql_help.c:4167 sql_help.c:4170 msgid "merge_update" msgstr "Merge-Update" -#: sql_help.c:4126 sql_help.c:4129 +#: sql_help.c:4168 sql_help.c:4171 msgid "merge_delete" msgstr "Merge-Delete" -#: sql_help.c:4131 +#: sql_help.c:4173 msgid "merge_insert" msgstr "Merge-Insert" -#: sql_help.c:4132 +#: sql_help.c:4174 msgid "and merge_insert is:" msgstr "und Merge-Insert Folgendes ist:" -#: sql_help.c:4135 +#: sql_help.c:4177 msgid "and merge_update is:" msgstr "und Merge-Update Folgendes ist:" -#: sql_help.c:4142 +#: sql_help.c:4184 msgid "and merge_delete is:" msgstr "und Merge-Delete Folgendes ist:" -#: sql_help.c:4183 +#: sql_help.c:4225 msgid "payload" msgstr "Payload" -#: sql_help.c:4210 +#: sql_help.c:4252 msgid "old_role" msgstr "alte_Rolle" -#: sql_help.c:4211 +#: sql_help.c:4253 msgid "new_role" msgstr "neue_Rolle" -#: sql_help.c:4250 sql_help.c:4459 sql_help.c:4467 +#: sql_help.c:4292 sql_help.c:4501 sql_help.c:4509 msgid "savepoint_name" msgstr "Sicherungspunktsname" -#: sql_help.c:4607 sql_help.c:4665 sql_help.c:4865 sql_help.c:4923 -#: sql_help.c:5110 sql_help.c:5168 +#: sql_help.c:4649 sql_help.c:4707 sql_help.c:4907 sql_help.c:4965 +#: sql_help.c:5154 sql_help.c:5212 msgid "grouping_element" msgstr "Gruppierelement" -#: sql_help.c:4609 sql_help.c:4713 sql_help.c:4867 sql_help.c:5112 +#: sql_help.c:4651 sql_help.c:4755 sql_help.c:4909 sql_help.c:5156 msgid "window_name" msgstr "Fenstername" -#: sql_help.c:4610 sql_help.c:4714 sql_help.c:4868 sql_help.c:5113 +#: sql_help.c:4652 sql_help.c:4756 sql_help.c:4910 sql_help.c:5157 msgid "window_definition" msgstr "Fensterdefinition" -#: sql_help.c:4611 sql_help.c:4625 sql_help.c:4669 sql_help.c:4715 -#: sql_help.c:4869 sql_help.c:4883 sql_help.c:4927 sql_help.c:5114 -#: sql_help.c:5128 sql_help.c:5172 +#: sql_help.c:4653 sql_help.c:4667 sql_help.c:4711 sql_help.c:4757 +#: sql_help.c:4911 sql_help.c:4925 sql_help.c:4969 sql_help.c:5158 +#: sql_help.c:5172 sql_help.c:5216 msgid "select" msgstr "Select" -#: sql_help.c:4617 sql_help.c:4875 sql_help.c:5120 +#: sql_help.c:4659 sql_help.c:4917 sql_help.c:5164 msgid "from_reference" msgstr "From-Referenz" -#: sql_help.c:4618 sql_help.c:4876 sql_help.c:5121 +#: sql_help.c:4660 sql_help.c:4918 sql_help.c:5165 msgid "where from_item can be one of:" msgstr "wobei From-Element Folgendes sein kann:" -#: sql_help.c:4621 sql_help.c:4627 sql_help.c:4630 sql_help.c:4634 -#: sql_help.c:4646 sql_help.c:4879 sql_help.c:4885 sql_help.c:4888 -#: sql_help.c:4892 sql_help.c:4904 sql_help.c:5124 sql_help.c:5130 -#: sql_help.c:5133 sql_help.c:5137 sql_help.c:5149 +#: sql_help.c:4663 sql_help.c:4669 sql_help.c:4672 sql_help.c:4676 +#: sql_help.c:4688 sql_help.c:4921 sql_help.c:4927 sql_help.c:4930 +#: sql_help.c:4934 sql_help.c:4946 sql_help.c:5168 sql_help.c:5174 +#: sql_help.c:5177 sql_help.c:5181 sql_help.c:5193 msgid "column_alias" msgstr "Spaltenalias" -#: sql_help.c:4622 sql_help.c:4880 sql_help.c:5125 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5169 msgid "sampling_method" msgstr "Stichprobenmethode" -#: sql_help.c:4624 sql_help.c:4882 sql_help.c:5127 +#: sql_help.c:4666 sql_help.c:4924 sql_help.c:5171 msgid "seed" msgstr "Startwert" -#: sql_help.c:4628 sql_help.c:4667 sql_help.c:4886 sql_help.c:4925 -#: sql_help.c:5131 sql_help.c:5170 +#: sql_help.c:4670 sql_help.c:4709 sql_help.c:4928 sql_help.c:4967 +#: sql_help.c:5175 sql_help.c:5214 msgid "with_query_name" msgstr "With-Anfragename" -#: sql_help.c:4638 sql_help.c:4641 sql_help.c:4644 sql_help.c:4896 -#: sql_help.c:4899 sql_help.c:4902 sql_help.c:5141 sql_help.c:5144 -#: sql_help.c:5147 +#: sql_help.c:4680 sql_help.c:4683 sql_help.c:4686 sql_help.c:4938 +#: sql_help.c:4941 sql_help.c:4944 sql_help.c:5185 sql_help.c:5188 +#: sql_help.c:5191 msgid "column_definition" msgstr "Spaltendefinition" -#: sql_help.c:4648 sql_help.c:4654 sql_help.c:4906 sql_help.c:4912 -#: sql_help.c:5151 sql_help.c:5157 +#: sql_help.c:4690 sql_help.c:4696 sql_help.c:4948 sql_help.c:4954 +#: sql_help.c:5195 sql_help.c:5201 msgid "join_type" msgstr "Verbundtyp" -#: sql_help.c:4651 sql_help.c:4909 sql_help.c:5154 +#: sql_help.c:4693 sql_help.c:4951 sql_help.c:5198 msgid "join_column" msgstr "Verbundspalte" -#: sql_help.c:4652 sql_help.c:4910 sql_help.c:5155 +#: sql_help.c:4694 sql_help.c:4952 sql_help.c:5199 msgid "join_using_alias" msgstr "Join-Using-Alias" -#: sql_help.c:4658 sql_help.c:4916 sql_help.c:5161 +#: sql_help.c:4700 sql_help.c:4958 sql_help.c:5205 msgid "and grouping_element can be one of:" msgstr "und Gruppierelement eins der folgenden sein kann:" -#: sql_help.c:4666 sql_help.c:4924 sql_help.c:5169 +#: sql_help.c:4708 sql_help.c:4966 sql_help.c:5213 msgid "and with_query is:" msgstr "und With-Anfrage ist:" -#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 +#: sql_help.c:4712 sql_help.c:4970 sql_help.c:5217 msgid "values" msgstr "values" -#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 +#: sql_help.c:4713 sql_help.c:4971 sql_help.c:5218 msgid "insert" msgstr "insert" -#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 +#: sql_help.c:4714 sql_help.c:4972 sql_help.c:5219 msgid "update" msgstr "update" -#: sql_help.c:4673 sql_help.c:4931 sql_help.c:5176 +#: sql_help.c:4715 sql_help.c:4973 sql_help.c:5220 msgid "delete" msgstr "delete" -#: sql_help.c:4674 sql_help.c:4932 sql_help.c:5177 +#: sql_help.c:4716 sql_help.c:4974 sql_help.c:5221 msgid "merge" msgstr "merge" -#: sql_help.c:4676 sql_help.c:4934 sql_help.c:5179 +#: sql_help.c:4718 sql_help.c:4976 sql_help.c:5223 msgid "search_seq_col_name" msgstr "Search-Seq-Spaltenname" -#: sql_help.c:4678 sql_help.c:4936 sql_help.c:5181 +#: sql_help.c:4720 sql_help.c:4978 sql_help.c:5225 msgid "cycle_mark_col_name" msgstr "Cycle-Mark-Spaltenname" -#: sql_help.c:4679 sql_help.c:4937 sql_help.c:5182 +#: sql_help.c:4721 sql_help.c:4979 sql_help.c:5226 msgid "cycle_mark_value" msgstr "Cycle-Mark-Wert" -#: sql_help.c:4680 sql_help.c:4938 sql_help.c:5183 +#: sql_help.c:4722 sql_help.c:4980 sql_help.c:5227 msgid "cycle_mark_default" msgstr "Cycle-Mark-Standard" -#: sql_help.c:4681 sql_help.c:4939 sql_help.c:5184 +#: sql_help.c:4723 sql_help.c:4981 sql_help.c:5228 msgid "cycle_path_col_name" msgstr "Cycle-Pfad-Spaltenname" -#: sql_help.c:4708 +#: sql_help.c:4750 msgid "new_table" msgstr "neue_Tabelle" -#: sql_help.c:4779 +#: sql_help.c:4821 msgid "snapshot_id" msgstr "Snapshot-ID" -#: sql_help.c:5046 +#: sql_help.c:5090 msgid "sort_expression" msgstr "Sortierausdruck" -#: sql_help.c:5191 sql_help.c:6175 +#: sql_help.c:5235 sql_help.c:6219 msgid "abort the current transaction" msgstr "bricht die aktuelle Transaktion ab" -#: sql_help.c:5197 +#: sql_help.c:5241 msgid "change the definition of an aggregate function" msgstr "ändert die Definition einer Aggregatfunktion" -#: sql_help.c:5203 +#: sql_help.c:5247 msgid "change the definition of a collation" msgstr "ändert die Definition einer Sortierfolge" -#: sql_help.c:5209 +#: sql_help.c:5253 msgid "change the definition of a conversion" msgstr "ändert die Definition einer Zeichensatzkonversion" -#: sql_help.c:5215 +#: sql_help.c:5259 msgid "change a database" msgstr "ändert eine Datenbank" -#: sql_help.c:5221 +#: sql_help.c:5265 msgid "define default access privileges" msgstr "definiert vorgegebene Zugriffsprivilegien" -#: sql_help.c:5227 +#: sql_help.c:5271 msgid "change the definition of a domain" msgstr "ändert die Definition einer Domäne" -#: sql_help.c:5233 +#: sql_help.c:5277 msgid "change the definition of an event trigger" msgstr "ändert die Definition eines Ereignistriggers" -#: sql_help.c:5239 +#: sql_help.c:5283 msgid "change the definition of an extension" msgstr "ändert die Definition einer Erweiterung" -#: sql_help.c:5245 +#: sql_help.c:5289 msgid "change the definition of a foreign-data wrapper" msgstr "ändert die Definition eines Fremddaten-Wrappers" -#: sql_help.c:5251 +#: sql_help.c:5295 msgid "change the definition of a foreign table" msgstr "ändert die Definition einer Fremdtabelle" -#: sql_help.c:5257 +#: sql_help.c:5301 msgid "change the definition of a function" msgstr "ändert die Definition einer Funktion" -#: sql_help.c:5263 +#: sql_help.c:5307 msgid "change role name or membership" msgstr "ändert Rollenname oder -mitglieder" -#: sql_help.c:5269 +#: sql_help.c:5313 msgid "change the definition of an index" msgstr "ändert die Definition eines Index" -#: sql_help.c:5275 +#: sql_help.c:5319 msgid "change the definition of a procedural language" msgstr "ändert die Definition einer prozeduralen Sprache" -#: sql_help.c:5281 +#: sql_help.c:5325 msgid "change the definition of a large object" msgstr "ändert die Definition eines Large Object" -#: sql_help.c:5287 +#: sql_help.c:5331 msgid "change the definition of a materialized view" msgstr "ändert die Definition einer materialisierten Sicht" -#: sql_help.c:5293 +#: sql_help.c:5337 msgid "change the definition of an operator" msgstr "ändert die Definition eines Operators" -#: sql_help.c:5299 +#: sql_help.c:5343 msgid "change the definition of an operator class" msgstr "ändert die Definition einer Operatorklasse" -#: sql_help.c:5305 +#: sql_help.c:5349 msgid "change the definition of an operator family" msgstr "ändert die Definition einer Operatorfamilie" -#: sql_help.c:5311 +#: sql_help.c:5355 msgid "change the definition of a row-level security policy" msgstr "ändert die Definition einer Policy für Sicherheit auf Zeilenebene" -#: sql_help.c:5317 +#: sql_help.c:5361 msgid "change the definition of a procedure" msgstr "ändert die Definition einer Prozedur" -#: sql_help.c:5323 +#: sql_help.c:5367 msgid "change the definition of a publication" msgstr "ändert die Definition einer Publikation" -#: sql_help.c:5329 sql_help.c:5431 +#: sql_help.c:5373 sql_help.c:5475 msgid "change a database role" msgstr "ändert eine Datenbankrolle" -#: sql_help.c:5335 +#: sql_help.c:5379 msgid "change the definition of a routine" msgstr "ändert die Definition einer Routine" -#: sql_help.c:5341 +#: sql_help.c:5385 msgid "change the definition of a rule" msgstr "ändert die Definition einer Regel" -#: sql_help.c:5347 +#: sql_help.c:5391 msgid "change the definition of a schema" msgstr "ändert die Definition eines Schemas" -#: sql_help.c:5353 +#: sql_help.c:5397 msgid "change the definition of a sequence generator" msgstr "ändert die Definition eines Sequenzgenerators" -#: sql_help.c:5359 +#: sql_help.c:5403 msgid "change the definition of a foreign server" msgstr "ändert die Definition eines Fremdservers" -#: sql_help.c:5365 +#: sql_help.c:5409 msgid "change the definition of an extended statistics object" msgstr "ändert die Definition eines erweiterten Statistikobjekts" -#: sql_help.c:5371 +#: sql_help.c:5415 msgid "change the definition of a subscription" msgstr "ändert die Definition einer Subskription" -#: sql_help.c:5377 +#: sql_help.c:5421 msgid "change a server configuration parameter" msgstr "ändert einen Server-Konfigurationsparameter" -#: sql_help.c:5383 +#: sql_help.c:5427 msgid "change the definition of a table" msgstr "ändert die Definition einer Tabelle" -#: sql_help.c:5389 +#: sql_help.c:5433 msgid "change the definition of a tablespace" msgstr "ändert die Definition eines Tablespace" -#: sql_help.c:5395 +#: sql_help.c:5439 msgid "change the definition of a text search configuration" msgstr "ändert die Definition einer Textsuchekonfiguration" -#: sql_help.c:5401 +#: sql_help.c:5445 msgid "change the definition of a text search dictionary" msgstr "ändert die Definition eines Textsuchewörterbuchs" -#: sql_help.c:5407 +#: sql_help.c:5451 msgid "change the definition of a text search parser" msgstr "ändert die Definition eines Textsucheparsers" -#: sql_help.c:5413 +#: sql_help.c:5457 msgid "change the definition of a text search template" msgstr "ändert die Definition einer Textsuchevorlage" -#: sql_help.c:5419 +#: sql_help.c:5463 msgid "change the definition of a trigger" msgstr "ändert die Definition eines Triggers" -#: sql_help.c:5425 +#: sql_help.c:5469 msgid "change the definition of a type" msgstr "ändert die Definition eines Typs" -#: sql_help.c:5437 +#: sql_help.c:5481 msgid "change the definition of a user mapping" msgstr "ändert die Definition einer Benutzerabbildung" -#: sql_help.c:5443 +#: sql_help.c:5487 msgid "change the definition of a view" msgstr "ändert die Definition einer Sicht" -#: sql_help.c:5449 +#: sql_help.c:5493 msgid "collect statistics about a database" msgstr "sammelt Statistiken über eine Datenbank" -#: sql_help.c:5455 sql_help.c:6253 +#: sql_help.c:5499 sql_help.c:6297 msgid "start a transaction block" msgstr "startet einen Transaktionsblock" -#: sql_help.c:5461 +#: sql_help.c:5505 msgid "invoke a procedure" msgstr "ruft eine Prozedur auf" -#: sql_help.c:5467 +#: sql_help.c:5511 msgid "force a write-ahead log checkpoint" msgstr "erzwingt einen Checkpoint im Write-Ahead-Log" -#: sql_help.c:5473 +#: sql_help.c:5517 msgid "close a cursor" msgstr "schließt einen Cursor" -#: sql_help.c:5479 +#: sql_help.c:5523 msgid "cluster a table according to an index" msgstr "clustert eine Tabelle nach einem Index" -#: sql_help.c:5485 +#: sql_help.c:5529 msgid "define or change the comment of an object" msgstr "definiert oder ändert den Kommentar eines Objektes" -#: sql_help.c:5491 sql_help.c:6049 +#: sql_help.c:5535 sql_help.c:6093 msgid "commit the current transaction" msgstr "schließt die aktuelle Transaktion ab" -#: sql_help.c:5497 +#: sql_help.c:5541 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "schließt eine Transaktion ab, die vorher für Two-Phase-Commit vorbereitet worden war" -#: sql_help.c:5503 +#: sql_help.c:5547 msgid "copy data between a file and a table" msgstr "kopiert Daten zwischen einer Datei und einer Tabelle" -#: sql_help.c:5509 +#: sql_help.c:5553 msgid "define a new access method" msgstr "definiert eine neue Zugriffsmethode" -#: sql_help.c:5515 +#: sql_help.c:5559 msgid "define a new aggregate function" msgstr "definiert eine neue Aggregatfunktion" -#: sql_help.c:5521 +#: sql_help.c:5565 msgid "define a new cast" msgstr "definiert eine neue Typumwandlung" -#: sql_help.c:5527 +#: sql_help.c:5571 msgid "define a new collation" msgstr "definiert eine neue Sortierfolge" -#: sql_help.c:5533 +#: sql_help.c:5577 msgid "define a new encoding conversion" msgstr "definiert eine neue Kodierungskonversion" -#: sql_help.c:5539 +#: sql_help.c:5583 msgid "create a new database" msgstr "erzeugt eine neue Datenbank" -#: sql_help.c:5545 +#: sql_help.c:5589 msgid "define a new domain" msgstr "definiert eine neue Domäne" -#: sql_help.c:5551 +#: sql_help.c:5595 msgid "define a new event trigger" msgstr "definiert einen neuen Ereignistrigger" -#: sql_help.c:5557 +#: sql_help.c:5601 msgid "install an extension" msgstr "installiert eine Erweiterung" -#: sql_help.c:5563 +#: sql_help.c:5607 msgid "define a new foreign-data wrapper" msgstr "definiert einen neuen Fremddaten-Wrapper" -#: sql_help.c:5569 +#: sql_help.c:5613 msgid "define a new foreign table" msgstr "definiert eine neue Fremdtabelle" -#: sql_help.c:5575 +#: sql_help.c:5619 msgid "define a new function" msgstr "definiert eine neue Funktion" -#: sql_help.c:5581 sql_help.c:5641 sql_help.c:5743 +#: sql_help.c:5625 sql_help.c:5685 sql_help.c:5787 msgid "define a new database role" msgstr "definiert eine neue Datenbankrolle" -#: sql_help.c:5587 +#: sql_help.c:5631 msgid "define a new index" msgstr "definiert einen neuen Index" -#: sql_help.c:5593 +#: sql_help.c:5637 msgid "define a new procedural language" msgstr "definiert eine neue prozedurale Sprache" -#: sql_help.c:5599 +#: sql_help.c:5643 msgid "define a new materialized view" msgstr "definiert eine neue materialisierte Sicht" -#: sql_help.c:5605 +#: sql_help.c:5649 msgid "define a new operator" msgstr "definiert einen neuen Operator" -#: sql_help.c:5611 +#: sql_help.c:5655 msgid "define a new operator class" msgstr "definiert eine neue Operatorklasse" -#: sql_help.c:5617 +#: sql_help.c:5661 msgid "define a new operator family" msgstr "definiert eine neue Operatorfamilie" -#: sql_help.c:5623 +#: sql_help.c:5667 msgid "define a new row-level security policy for a table" msgstr "definiert eine neue Policy für Sicherheit auf Zeilenebene für eine Tabelle" -#: sql_help.c:5629 +#: sql_help.c:5673 msgid "define a new procedure" msgstr "definiert eine neue Prozedur" -#: sql_help.c:5635 +#: sql_help.c:5679 msgid "define a new publication" msgstr "definiert eine neue Publikation" -#: sql_help.c:5647 +#: sql_help.c:5691 msgid "define a new rewrite rule" msgstr "definiert eine neue Umschreiberegel" -#: sql_help.c:5653 +#: sql_help.c:5697 msgid "define a new schema" msgstr "definiert ein neues Schema" -#: sql_help.c:5659 +#: sql_help.c:5703 msgid "define a new sequence generator" msgstr "definiert einen neuen Sequenzgenerator" -#: sql_help.c:5665 +#: sql_help.c:5709 msgid "define a new foreign server" msgstr "definiert einen neuen Fremdserver" -#: sql_help.c:5671 +#: sql_help.c:5715 msgid "define extended statistics" msgstr "definiert erweiterte Statistiken" -#: sql_help.c:5677 +#: sql_help.c:5721 msgid "define a new subscription" msgstr "definiert eine neue Subskription" -#: sql_help.c:5683 +#: sql_help.c:5727 msgid "define a new table" msgstr "definiert eine neue Tabelle" -#: sql_help.c:5689 sql_help.c:6211 +#: sql_help.c:5733 sql_help.c:6255 msgid "define a new table from the results of a query" msgstr "definiert eine neue Tabelle aus den Ergebnissen einer Anfrage" -#: sql_help.c:5695 +#: sql_help.c:5739 msgid "define a new tablespace" msgstr "definiert einen neuen Tablespace" -#: sql_help.c:5701 +#: sql_help.c:5745 msgid "define a new text search configuration" msgstr "definiert eine neue Textsuchekonfiguration" -#: sql_help.c:5707 +#: sql_help.c:5751 msgid "define a new text search dictionary" msgstr "definiert ein neues Textsuchewörterbuch" -#: sql_help.c:5713 +#: sql_help.c:5757 msgid "define a new text search parser" msgstr "definiert einen neuen Textsucheparser" -#: sql_help.c:5719 +#: sql_help.c:5763 msgid "define a new text search template" msgstr "definiert eine neue Textsuchevorlage" -#: sql_help.c:5725 +#: sql_help.c:5769 msgid "define a new transform" msgstr "definiert eine neue Transformation" -#: sql_help.c:5731 +#: sql_help.c:5775 msgid "define a new trigger" msgstr "definiert einen neuen Trigger" -#: sql_help.c:5737 +#: sql_help.c:5781 msgid "define a new data type" msgstr "definiert einen neuen Datentyp" -#: sql_help.c:5749 +#: sql_help.c:5793 msgid "define a new mapping of a user to a foreign server" msgstr "definiert eine neue Abbildung eines Benutzers auf einen Fremdserver" -#: sql_help.c:5755 +#: sql_help.c:5799 msgid "define a new view" msgstr "definiert eine neue Sicht" -#: sql_help.c:5761 +#: sql_help.c:5805 msgid "deallocate a prepared statement" msgstr "gibt einen vorbereiteten Befehl frei" -#: sql_help.c:5767 +#: sql_help.c:5811 msgid "define a cursor" msgstr "definiert einen Cursor" -#: sql_help.c:5773 +#: sql_help.c:5817 msgid "delete rows of a table" msgstr "löscht Zeilen einer Tabelle" -#: sql_help.c:5779 +#: sql_help.c:5823 msgid "discard session state" msgstr "verwirft den Sitzungszustand" -#: sql_help.c:5785 +#: sql_help.c:5829 msgid "execute an anonymous code block" msgstr "führt einen anonymen Codeblock aus" -#: sql_help.c:5791 +#: sql_help.c:5835 msgid "remove an access method" msgstr "entfernt eine Zugriffsmethode" -#: sql_help.c:5797 +#: sql_help.c:5841 msgid "remove an aggregate function" msgstr "entfernt eine Aggregatfunktion" -#: sql_help.c:5803 +#: sql_help.c:5847 msgid "remove a cast" msgstr "entfernt eine Typumwandlung" -#: sql_help.c:5809 +#: sql_help.c:5853 msgid "remove a collation" msgstr "entfernt eine Sortierfolge" -#: sql_help.c:5815 +#: sql_help.c:5859 msgid "remove a conversion" msgstr "entfernt eine Zeichensatzkonversion" -#: sql_help.c:5821 +#: sql_help.c:5865 msgid "remove a database" msgstr "entfernt eine Datenbank" -#: sql_help.c:5827 +#: sql_help.c:5871 msgid "remove a domain" msgstr "entfernt eine Domäne" -#: sql_help.c:5833 +#: sql_help.c:5877 msgid "remove an event trigger" msgstr "entfernt einen Ereignistrigger" -#: sql_help.c:5839 +#: sql_help.c:5883 msgid "remove an extension" msgstr "entfernt eine Erweiterung" -#: sql_help.c:5845 +#: sql_help.c:5889 msgid "remove a foreign-data wrapper" msgstr "entfernt einen Fremddaten-Wrapper" -#: sql_help.c:5851 +#: sql_help.c:5895 msgid "remove a foreign table" msgstr "entfernt eine Fremdtabelle" -#: sql_help.c:5857 +#: sql_help.c:5901 msgid "remove a function" msgstr "entfernt eine Funktion" -#: sql_help.c:5863 sql_help.c:5929 sql_help.c:6031 +#: sql_help.c:5907 sql_help.c:5973 sql_help.c:6075 msgid "remove a database role" msgstr "entfernt eine Datenbankrolle" -#: sql_help.c:5869 +#: sql_help.c:5913 msgid "remove an index" msgstr "entfernt einen Index" -#: sql_help.c:5875 +#: sql_help.c:5919 msgid "remove a procedural language" msgstr "entfernt eine prozedurale Sprache" -#: sql_help.c:5881 +#: sql_help.c:5925 msgid "remove a materialized view" msgstr "entfernt eine materialisierte Sicht" -#: sql_help.c:5887 +#: sql_help.c:5931 msgid "remove an operator" msgstr "entfernt einen Operator" -#: sql_help.c:5893 +#: sql_help.c:5937 msgid "remove an operator class" msgstr "entfernt eine Operatorklasse" -#: sql_help.c:5899 +#: sql_help.c:5943 msgid "remove an operator family" msgstr "entfernt eine Operatorfamilie" -#: sql_help.c:5905 +#: sql_help.c:5949 msgid "remove database objects owned by a database role" msgstr "entfernt die einer Datenbankrolle gehörenden Datenbankobjekte" -#: sql_help.c:5911 +#: sql_help.c:5955 msgid "remove a row-level security policy from a table" msgstr "entfernt eine Policy für Sicherheit auf Zeilenebene von einer Tabelle" -#: sql_help.c:5917 +#: sql_help.c:5961 msgid "remove a procedure" msgstr "entfernt eine Prozedur" -#: sql_help.c:5923 +#: sql_help.c:5967 msgid "remove a publication" msgstr "entfernt eine Publikation" -#: sql_help.c:5935 +#: sql_help.c:5979 msgid "remove a routine" msgstr "entfernt eine Routine" -#: sql_help.c:5941 +#: sql_help.c:5985 msgid "remove a rewrite rule" msgstr "entfernt eine Umschreiberegel" -#: sql_help.c:5947 +#: sql_help.c:5991 msgid "remove a schema" msgstr "entfernt ein Schema" -#: sql_help.c:5953 +#: sql_help.c:5997 msgid "remove a sequence" msgstr "entfernt eine Sequenz" -#: sql_help.c:5959 +#: sql_help.c:6003 msgid "remove a foreign server descriptor" msgstr "entfernt einen Fremdserverdeskriptor" -#: sql_help.c:5965 +#: sql_help.c:6009 msgid "remove extended statistics" msgstr "entfernt erweiterte Statistiken" -#: sql_help.c:5971 +#: sql_help.c:6015 msgid "remove a subscription" msgstr "entfernt eine Subskription" -#: sql_help.c:5977 +#: sql_help.c:6021 msgid "remove a table" msgstr "entfernt eine Tabelle" -#: sql_help.c:5983 +#: sql_help.c:6027 msgid "remove a tablespace" msgstr "entfernt einen Tablespace" -#: sql_help.c:5989 +#: sql_help.c:6033 msgid "remove a text search configuration" msgstr "entfernt eine Textsuchekonfiguration" -#: sql_help.c:5995 +#: sql_help.c:6039 msgid "remove a text search dictionary" msgstr "entfernt ein Textsuchewörterbuch" -#: sql_help.c:6001 +#: sql_help.c:6045 msgid "remove a text search parser" msgstr "entfernt einen Textsucheparser" -#: sql_help.c:6007 +#: sql_help.c:6051 msgid "remove a text search template" msgstr "entfernt eine Textsuchevorlage" -#: sql_help.c:6013 +#: sql_help.c:6057 msgid "remove a transform" msgstr "entfernt eine Transformation" -#: sql_help.c:6019 +#: sql_help.c:6063 msgid "remove a trigger" msgstr "entfernt einen Trigger" -#: sql_help.c:6025 +#: sql_help.c:6069 msgid "remove a data type" msgstr "entfernt einen Datentyp" -#: sql_help.c:6037 +#: sql_help.c:6081 msgid "remove a user mapping for a foreign server" msgstr "entfernt eine Benutzerabbildung für einen Fremdserver" -#: sql_help.c:6043 +#: sql_help.c:6087 msgid "remove a view" msgstr "entfernt eine Sicht" -#: sql_help.c:6055 +#: sql_help.c:6099 msgid "execute a prepared statement" msgstr "führt einen vorbereiteten Befehl aus" -#: sql_help.c:6061 +#: sql_help.c:6105 msgid "show the execution plan of a statement" msgstr "zeigt den Ausführungsplan eines Befehls" -#: sql_help.c:6067 +#: sql_help.c:6111 msgid "retrieve rows from a query using a cursor" msgstr "liest Zeilen aus einer Anfrage mit einem Cursor" -#: sql_help.c:6073 +#: sql_help.c:6117 msgid "define access privileges" msgstr "definiert Zugriffsprivilegien" -#: sql_help.c:6079 +#: sql_help.c:6123 msgid "import table definitions from a foreign server" msgstr "importiert Tabellendefinitionen von einem Fremdserver" -#: sql_help.c:6085 +#: sql_help.c:6129 msgid "create new rows in a table" msgstr "erzeugt neue Zeilen in einer Tabelle" -#: sql_help.c:6091 +#: sql_help.c:6135 msgid "listen for a notification" msgstr "hört auf eine Benachrichtigung" -#: sql_help.c:6097 +#: sql_help.c:6141 msgid "load a shared library file" msgstr "lädt eine dynamische Bibliotheksdatei" -#: sql_help.c:6103 +#: sql_help.c:6147 msgid "lock a table" msgstr "sperrt eine Tabelle" -#: sql_help.c:6109 +#: sql_help.c:6153 msgid "conditionally insert, update, or delete rows of a table" msgstr "fügt Zeilen in eine Tabelle ein oder ändert oder löscht Zeilen einer Tabelle, abhängig von Bedingungen" -#: sql_help.c:6115 +#: sql_help.c:6159 msgid "position a cursor" msgstr "positioniert einen Cursor" -#: sql_help.c:6121 +#: sql_help.c:6165 msgid "generate a notification" msgstr "erzeugt eine Benachrichtigung" -#: sql_help.c:6127 +#: sql_help.c:6171 msgid "prepare a statement for execution" msgstr "bereitet einen Befehl zur Ausführung vor" -#: sql_help.c:6133 +#: sql_help.c:6177 msgid "prepare the current transaction for two-phase commit" msgstr "bereitet die aktuelle Transaktion für Two-Phase-Commit vor" -#: sql_help.c:6139 +#: sql_help.c:6183 msgid "change the ownership of database objects owned by a database role" msgstr "ändert den Eigentümer der der Rolle gehörenden Datenbankobjekte" -#: sql_help.c:6145 +#: sql_help.c:6189 msgid "replace the contents of a materialized view" msgstr "ersetzt den Inhalt einer materialisierten Sicht" -#: sql_help.c:6151 +#: sql_help.c:6195 msgid "rebuild indexes" msgstr "baut Indexe neu" -#: sql_help.c:6157 +#: sql_help.c:6201 msgid "release a previously defined savepoint" msgstr "gibt einen zuvor definierten Sicherungspunkt frei" -#: sql_help.c:6163 +#: sql_help.c:6207 msgid "restore the value of a run-time parameter to the default value" msgstr "setzt einen Konfigurationsparameter auf die Voreinstellung zurück" -#: sql_help.c:6169 +#: sql_help.c:6213 msgid "remove access privileges" msgstr "entfernt Zugriffsprivilegien" -#: sql_help.c:6181 +#: sql_help.c:6225 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "storniert eine Transaktion, die vorher für Two-Phase-Commit vorbereitet worden war" -#: sql_help.c:6187 +#: sql_help.c:6231 msgid "roll back to a savepoint" msgstr "rollt eine Transaktion bis zu einem Sicherungspunkt zurück" -#: sql_help.c:6193 +#: sql_help.c:6237 msgid "define a new savepoint within the current transaction" msgstr "definiert einen neuen Sicherungspunkt in der aktuellen Transaktion" -#: sql_help.c:6199 +#: sql_help.c:6243 msgid "define or change a security label applied to an object" msgstr "definiert oder ändert ein Security-Label eines Objektes" -#: sql_help.c:6205 sql_help.c:6259 sql_help.c:6295 +#: sql_help.c:6249 sql_help.c:6303 sql_help.c:6339 msgid "retrieve rows from a table or view" msgstr "liest Zeilen aus einer Tabelle oder Sicht" -#: sql_help.c:6217 +#: sql_help.c:6261 msgid "change a run-time parameter" msgstr "ändert einen Konfigurationsparameter" -#: sql_help.c:6223 +#: sql_help.c:6267 msgid "set constraint check timing for the current transaction" msgstr "setzt die Zeitsteuerung für Check-Constraints in der aktuellen Transaktion" -#: sql_help.c:6229 +#: sql_help.c:6273 msgid "set the current user identifier of the current session" msgstr "setzt den aktuellen Benutzernamen der aktuellen Sitzung" -#: sql_help.c:6235 +#: sql_help.c:6279 msgid "set the session user identifier and the current user identifier of the current session" msgstr "setzt den Sitzungsbenutzernamen und den aktuellen Benutzernamen der aktuellen Sitzung" -#: sql_help.c:6241 +#: sql_help.c:6285 msgid "set the characteristics of the current transaction" msgstr "setzt die Charakteristika der aktuellen Transaktion" -#: sql_help.c:6247 +#: sql_help.c:6291 msgid "show the value of a run-time parameter" msgstr "zeigt den Wert eines Konfigurationsparameters" -#: sql_help.c:6265 +#: sql_help.c:6309 msgid "empty a table or set of tables" msgstr "leert eine oder mehrere Tabellen" -#: sql_help.c:6271 +#: sql_help.c:6315 msgid "stop listening for a notification" msgstr "beendet das Hören auf eine Benachrichtigung" -#: sql_help.c:6277 +#: sql_help.c:6321 msgid "update rows of a table" msgstr "aktualisiert Zeilen einer Tabelle" -#: sql_help.c:6283 +#: sql_help.c:6327 msgid "garbage-collect and optionally analyze a database" msgstr "säubert und analysiert eine Datenbank" -#: sql_help.c:6289 +#: sql_help.c:6333 msgid "compute a set of rows" msgstr "berechnet eine Zeilenmenge" -#: startup.c:220 +#: startup.c:225 #, c-format msgid "-1 can only be used in non-interactive mode" msgstr "-1 kann nur im nicht interaktiven Modus verwendet werden" -#: startup.c:343 +#: startup.c:348 #, c-format msgid "could not open log file \"%s\": %m" msgstr "konnte Logdatei »%s« nicht öffnen: %m" -#: startup.c:460 +#: startup.c:465 #, c-format msgid "" "Type \"help\" for help.\n" @@ -6597,27 +6887,27 @@ msgstr "" "Geben Sie »help« für Hilfe ein.\n" "\n" -#: startup.c:612 +#: startup.c:617 #, c-format msgid "could not set printing parameter \"%s\"" msgstr "konnte Ausgabeparameter »%s« nicht setzen" -#: startup.c:719 +#: startup.c:724 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: startup.c:735 +#: startup.c:740 #, c-format msgid "extra command-line argument \"%s\" ignored" msgstr "überflüssiges Kommandozeilenargument »%s« ignoriert" -#: startup.c:783 +#: startup.c:788 #, c-format msgid "could not find own program executable" msgstr "konnte eigene Programmdatei nicht finden" -#: tab-complete.c:6230 +#: tab-complete.in.c:6606 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6628,22 +6918,47 @@ msgstr "" "Anfrage war:\n" "%s" -#: variables.c:139 +#: variables.c:141 #, c-format msgid "unrecognized value \"%s\" for \"%s\": Boolean expected" msgstr "unbekannter Wert »%s« für »%s«: Boole'scher Wert erwartet" -#: variables.c:176 +#: variables.c:178 #, c-format msgid "invalid value \"%s\" for \"%s\": integer expected" msgstr "ungültiger Wert »%s« für »%s«: ganze Zahl erwartet" -#: variables.c:224 +#: variables.c:207 +#, c-format +msgid "invalid input syntax for \"%s\"" +msgstr "ungültige Eingabesyntax für »%s«" + +#: variables.c:218 +#, c-format +msgid "invalid value \"%s\" for \"%s\": must be greater than %.2f" +msgstr "ungültiger Wert »%s« für »%s«: muss größer als %.2f sein" + +#: variables.c:225 +#, c-format +msgid "invalid value \"%s\" for \"%s\": must be less than %.2f" +msgstr "ungültiger Wert »%s« für »%s«: muss kleiner als %.2f sein" + +#: variables.c:241 +#, c-format +msgid "\"%s\" is out of range for \"%s\"" +msgstr "»%s« ist außerhalb des gültigen Bereichs für »%s«" + +#: variables.c:247 +#, c-format +msgid "invalid value \"%s\" for \"%s\"" +msgstr "ungültiger Wert »%s« für »%s«" + +#: variables.c:294 #, c-format msgid "invalid variable name: \"%s\"" msgstr "ungültiger Variablenname: »%s«" -#: variables.c:418 +#: variables.c:488 #, c-format msgid "" "unrecognized value \"%s\" for \"%s\"\n" diff --git a/src/bin/psql/po/el.po b/src/bin/psql/po/el.po index 9e4179afa6640..2fe4db9eec06b 100644 --- a/src/bin/psql/po/el.po +++ b/src/bin/psql/po/el.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: psql (PostgreSQL) 15\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2023-08-15 13:47+0000\n" -"PO-Revision-Date: 2023-08-16 11:55+0200\n" +"PO-Revision-Date: 2024-06-26 08:48+0200\n" "Last-Translator: Georgios Kokolatos \n" "Language-Team: \n" "Language: el\n" @@ -3312,7 +3312,6 @@ msgstr "" " ECHO\n" " ελέγχει ποία είσοδος γράφεται στην τυπική έξοδο\n" " [all, errors, none, queries]\n" -"\n" #: help.c:408 msgid "" @@ -3494,7 +3493,7 @@ msgid "" msgstr "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" -" έκδοση διακομιστή (σε σύντομη συμβολοσειρά ή αριθμητική μορφή)\n" +" έκδοση διακομιστή (σε σύντομη συμβολοσειρά ή αριθμητική μορφή)\n" #: help.c:455 msgid "" @@ -3542,7 +3541,7 @@ msgid "" " single-step mode (same as -s option)\n" msgstr "" " SINGLESTEP\n" -" λειτουργία μονού-βήματος(όμοια με την επιλογή -s)\n" +" λειτουργία μονού-βήματος(όμοια με την επιλογή -s)\n" #: help.c:467 msgid "" diff --git a/src/bin/psql/po/es.po b/src/bin/psql/po/es.po index 9070c6c90b124..bc110c4dcad6f 100644 --- a/src/bin/psql/po/es.po +++ b/src/bin/psql/po/es.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: psql (PostgreSQL) 16\n" +"Project-Id-Version: psql (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-03 07:17+0000\n" -"PO-Revision-Date: 2023-10-04 11:48+0200\n" +"POT-Creation-Date: 2025-02-16 19:47+0000\n" +"PO-Revision-Date: 2024-12-07 09:06+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -43,33 +43,48 @@ msgstr "detalle: " msgid "hint: " msgstr "consejo: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binario «%s» no válido: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "no se pudo leer el binario «%s»: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "no se pudo encontrar un «%s» para ejecutar" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "no se pudo resolver la ruta «%s» a forma absoluta: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "no se pudo ejecutar la orden «%s»: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "no se pudo leer desde la orden «%s»: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "la orden «%s» no retornó datos" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() falló: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1373 command.c:3459 command.c:3508 command.c:3633 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -91,7 +106,7 @@ msgstr "no se puede duplicar un puntero nulo (error interno)\n" msgid "could not look up effective user ID %ld: %s" msgstr "no se pudo buscar el ID de usuario efectivo %ld: %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "el usuario no existe" @@ -130,11 +145,11 @@ msgstr "el proceso hijo fue terminado por una señal %d: %s" msgid "child process exited with unrecognized status %d" msgstr "el proceso hijo terminó con código no reconocido %d" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Petición de cancelación enviada\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "No se pudo enviar la petición de cancelación: %s" @@ -150,312 +165,337 @@ msgstr[1] "(%lu filas)" msgid "Interrupted\n" msgstr "Interrumpido\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "No se puede imprimir el contenido de la tabla: el número de celdas %lld es igual o mayor al máximo %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "No se puede agregar un encabezado al contenido de la tabla: la cantidad de columnas de %d ha sido excedida.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "No se puede agregar una celda al contenido de la tabla: la cantidad de celdas de %d ha sido excedida.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "No se puede agregar una celda al contenido de la tabla: la cantidad de celdas de %lld ha sido excedida.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "formato de salida no válido (error interno): %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "saltando expansión recursiva de la variable «%s»" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "no se pudo buscar el usuario local de ID %d: %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "no existe un usuario local con ID %d" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "orden \\%s no válida" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "Digite \\? para obtener ayuda." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: argumento extra «%s» ignorado" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "orden \\%s ignorada: use \\endif o Ctrl-C para salir del bloque \\if actual" -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "no se pudo obtener directorio home para el usuario de ID %ld: %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: no se pudo cambiar directorio a «%s»: %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "No está conectado a una base de datos.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Está conectado a la base de datos «%s» como el usuario «%s» en la dirección «%s» port «%s».\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Está conectado a la base de datos «%s» como el usuario «%s» a través del socket en «%s» port «%s».\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Está conectado a la base de datos «%s» como el usuario «%s» en el servidor «%s» (dirección «%s») port «%s».\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Está conectado a la base de datos «%s» como el usuario «%s» en el servidor «%s» port «%s».\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2676 #, c-format msgid "no query buffer" msgstr "no hay búfer de consulta" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5779 #, c-format msgid "invalid line number: %s" msgstr "número de línea no válido: %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "Sin cambios" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: nombre de codificación no válido o procedimiento de conversión no encontrado" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:720 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1369 command.c:2158 command.c:3455 command.c:3653 command.c:5885 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1376 msgid "There is no previous error." msgstr "No hay error anterior." -#: command.c:1470 +#: command.c:1489 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: falta el paréntesis derecho" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1573 command.c:1692 command.c:1996 command.c:2010 command.c:2029 +#: command.c:2197 command.c:2438 command.c:2643 command.c:2683 #, c-format msgid "\\%s: missing required argument" msgstr "\\%s: falta argumento requerido" -#: command.c:1815 +#: command.c:1823 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: no puede ocurrir después de \\else" -#: command.c:1820 +#: command.c:1828 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: no hay un \\if coincidente" -#: command.c:1884 +#: command.c:1892 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: no puede ocurrir después de \\else" -#: command.c:1889 +#: command.c:1897 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: no hay un \\if coincidente" -#: command.c:1929 +#: command.c:1937 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: no hay un \\if coincidente" -#: command.c:2085 +#: command.c:2093 msgid "Query buffer is empty." msgstr "El búfer de consulta está vacío." -#: command.c:2128 +#: command.c:2136 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Ingrese nueva contraseña para usuario «%s»: " -#: command.c:2132 +#: command.c:2140 msgid "Enter it again: " msgstr "Ingrésela nuevamente: " -#: command.c:2141 +#: command.c:2149 #, c-format msgid "Passwords didn't match." msgstr "Las contraseñas no coinciden." -#: command.c:2238 +#: command.c:2232 #, c-format msgid "\\%s: could not read value for variable" msgstr "%s: no se pudo leer el valor para la variable" -#: command.c:2340 +#: command.c:2334 msgid "Query buffer reset (cleared)." msgstr "El búfer de consulta ha sido reiniciado (limpiado)." -#: command.c:2362 +#: command.c:2356 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "Se escribió la historia en el archivo «%s».\n" -#: command.c:2449 +#: command.c:2443 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: el nombre de variable de ambiente no debe contener «=»" -#: command.c:2497 +#: command.c:2491 #, c-format msgid "function name is required" msgstr "el nombre de la función es requerido" -#: command.c:2499 +#: command.c:2493 #, c-format msgid "view name is required" msgstr "el nombre de la vista es requerido" -#: command.c:2621 +#: command.c:2615 msgid "Timing is on." msgstr "El despliegue de duración está activado." -#: command.c:2623 +#: command.c:2617 msgid "Timing is off." msgstr "El despliegue de duración está desactivado." -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2703 command.c:2741 command.c:4166 command.c:4169 command.c:4172 +#: command.c:4178 command.c:4180 command.c:4206 command.c:4216 command.c:4228 +#: command.c:4242 command.c:4269 command.c:4327 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2736 copy.c:388 +#: command.c:2730 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2806 command.c:2852 +#: command.c:2802 command.c:2868 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: valor de intervalo ese especifica más de una vez" -#: command.c:2816 command.c:2862 +#: command.c:2812 command.c:2878 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: valor de intervalo incorrecto «%s»" -#: command.c:2826 +#: command.c:2822 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: cantidad de iteraciones se especifica más de una vez" -#: command.c:2836 +#: command.c:2832 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: cantidad de iteraciones incorrecta «%s»" -#: command.c:2843 +#: command.c:2842 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: mínima cantidad de filas se especifica más de una vez" + +#: command.c:2852 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch: cantidad mínima de filas incorrecta «%s»" + +#: command.c:2859 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: parámetro «%s» no reconocido" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3256 startup.c:243 startup.c:293 msgid "Password: " msgstr "Contraseña: " -#: command.c:3241 startup.c:290 +#: command.c:3261 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "Contraseña para usuario %s: " -#: command.c:3297 +#: command.c:3317 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "No proporcione usuario, host o puerto de forma separada al usar una cadena de conexión" -#: command.c:3332 +#: command.c:3352 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "No existe una conexión de base de datos para poder reusar sus parámetros" -#: command.c:3638 +#: command.c:3659 #, c-format msgid "Previous connection kept" msgstr "Se ha mantenido la conexión anterior" -#: command.c:3644 +#: command.c:3665 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3700 +#: command.c:3721 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Ahora está conectado a la base de datos «%s» como el usuario «%s» en la dirección «%s» port «%s».\n" -#: command.c:3703 +#: command.c:3724 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Ahora está conectado a la base de datos «%s» como el usuario «%s» a través del socket en «%s» port «%s».\n" -#: command.c:3709 +#: command.c:3730 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Ahora está conectado a la base de datos «%s» como el usuario «%s» en el servidor «%s» (dirección «%s») port «%s».\n" -#: command.c:3712 +#: command.c:3733 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Ahora está conectado a la base de datos «%s» como el usuario «%s» en el servidor «%s» port «%s».\n" -#: command.c:3717 +#: command.c:3738 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Ahora está conectado a la base de datos «%s» con el usuario «%s».\n" -#: command.c:3757 +#: command.c:3844 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, servidor %s)\n" -#: command.c:3770 +#: command.c:3857 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -464,29 +504,33 @@ msgstr "" "ADVERTENCIA: %s versión mayor %s, servidor versión mayor %s.\n" " Algunas características de psql podrían no funcionar.\n" -#: command.c:3807 +#: command.c:3896 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "Conexión SSL (protocolo: %s, cifrado: %s, compresión: %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "Conexión SSL (protocolo: %s, cifrado: %s, compresión: %s, ALPN: %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3897 command.c:3898 msgid "unknown" msgstr "desconocido" -#: command.c:3810 help.c:42 +#: command.c:3899 help.c:42 msgid "off" msgstr "desactivado" -#: command.c:3810 help.c:42 +#: command.c:3899 help.c:42 msgid "on" msgstr "activado" -#: command.c:3824 +#: command.c:3900 +msgid "none" +msgstr "ninguno" + +#: command.c:3914 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "Conexión Cifrada GSSAPI\n" -#: command.c:3844 +#: command.c:3934 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -499,433 +543,438 @@ msgstr "" " Vea la página de referencia de psql «Notes for Windows users»\n" " para obtener más detalles.\n" -#: command.c:3949 +#: command.c:4041 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "la variable de ambiente PSQL_EDITOR_LINENUMBER_SWITCH debe estar definida para poder especificar un número de línea" -#: command.c:3979 +#: command.c:4071 #, c-format msgid "could not start editor \"%s\"" msgstr "no se pudo iniciar el editor «%s»" -#: command.c:3981 +#: command.c:4073 #, c-format msgid "could not start /bin/sh" msgstr "no se pudo iniciar /bin/sh" -#: command.c:4031 +#: command.c:4123 #, c-format msgid "could not locate temporary directory: %s" msgstr "no se pudo ubicar el directorio temporal: %s" -#: command.c:4058 +#: command.c:4150 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "no se pudo abrir archivo temporal «%s»: %m" -#: command.c:4394 +#: command.c:4486 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: abreviación ambigua «%s» coincide tanto con «%s» como con «%s»" -#: command.c:4414 +#: command.c:4506 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset: formatos permitidos son aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4525 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: estilos de línea permitidos son ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4540 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: estilos de línea Unicode de borde permitidos son single, double" -#: command.c:4463 +#: command.c:4555 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: estilos de línea Unicode de columna permitidos son single, double" -#: command.c:4478 +#: command.c:4570 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: estilos de línea Unicode de encabezado permitidos son single, double" -#: command.c:4530 +#: command.c:4622 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: los valores permitidos de xheader_width son «%s» (por omisión), «%s», «%s», o un número que indica el ancho exacto" -#: command.c:4547 +#: command.c:4639 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep debe ser un carácter de un solo byte" -#: command.c:4552 +#: command.c:4644 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldset ni puede ser una comilla doble, un salto de línea, o un retorno de carro" -#: command.c:4690 command.c:4891 +#: command.c:4782 command.c:4983 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: opción desconocida: %s" -#: command.c:4710 +#: command.c:4802 #, c-format msgid "Border style is %d.\n" msgstr "El estilo de borde es %d.\n" -#: command.c:4716 +#: command.c:4808 #, c-format msgid "Target width is unset.\n" msgstr "El ancho no está definido.\n" -#: command.c:4718 +#: command.c:4810 #, c-format msgid "Target width is %d.\n" msgstr "El ancho es %d.\n" -#: command.c:4725 +#: command.c:4817 #, c-format msgid "Expanded display is on.\n" msgstr "Se ha activado el despliegue expandido.\n" -#: command.c:4727 +#: command.c:4819 #, c-format msgid "Expanded display is used automatically.\n" msgstr "El despliegue expandido se usa automáticamente.\n" -#: command.c:4729 +#: command.c:4821 #, c-format msgid "Expanded display is off.\n" msgstr "Se ha desactivado el despliegue expandido.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4828 command.c:4830 command.c:4832 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "El ancho del encabezado expandido es '%s'.\n" -#: command.c:4742 +#: command.c:4834 #, c-format msgid "Expanded header width is %d.\n" msgstr "El ancho de encabezado expandido es %d.\n" -#: command.c:4748 +#: command.c:4840 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "El separador de campos para CSV es «%s».\n" -#: command.c:4756 command.c:4764 +#: command.c:4848 command.c:4856 #, c-format msgid "Field separator is zero byte.\n" msgstr "El separador de campos es el byte cero.\n" -#: command.c:4758 +#: command.c:4850 #, c-format msgid "Field separator is \"%s\".\n" msgstr "El separador de campos es «%s».\n" -#: command.c:4771 +#: command.c:4863 #, c-format msgid "Default footer is on.\n" msgstr "El pie por omisión está activo.\n" -#: command.c:4773 +#: command.c:4865 #, c-format msgid "Default footer is off.\n" msgstr "El pie de página por omisión está desactivado.\n" -#: command.c:4779 +#: command.c:4871 #, c-format msgid "Output format is %s.\n" msgstr "El formato de salida es %s.\n" -#: command.c:4785 +#: command.c:4877 #, c-format msgid "Line style is %s.\n" msgstr "El estilo de línea es %s.\n" -#: command.c:4792 +#: command.c:4884 #, c-format msgid "Null display is \"%s\".\n" msgstr "Despliegue de nulos es «%s».\n" -#: command.c:4800 +#: command.c:4892 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "La salida numérica ajustada localmente está habilitada.\n" -#: command.c:4802 +#: command.c:4894 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "La salida numérica ajustada localmente está deshabilitada.\n" -#: command.c:4809 +#: command.c:4901 #, c-format msgid "Pager is used for long output.\n" msgstr "El paginador se usará para salida larga.\n" -#: command.c:4811 +#: command.c:4903 #, c-format msgid "Pager is always used.\n" msgstr "El paginador se usará siempre.\n" -#: command.c:4813 +#: command.c:4905 #, c-format msgid "Pager usage is off.\n" msgstr "El paginador no se usará.\n" -#: command.c:4819 +#: command.c:4911 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "El paginador no se usará para menos de %d línea.\n" msgstr[1] "El paginador no se usará para menos de %d líneas.\n" -#: command.c:4829 command.c:4839 +#: command.c:4921 command.c:4931 #, c-format msgid "Record separator is zero byte.\n" msgstr "El separador de filas es el byte cero.\n" -#: command.c:4831 +#: command.c:4923 #, c-format msgid "Record separator is .\n" msgstr "El separador de filas es .\n" -#: command.c:4833 +#: command.c:4925 #, c-format msgid "Record separator is \"%s\".\n" msgstr "El separador de filas es «%s».\n" -#: command.c:4846 +#: command.c:4938 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Los atributos de tabla son «%s».\n" -#: command.c:4849 +#: command.c:4941 #, c-format msgid "Table attributes unset.\n" msgstr "Los atributos de tabla han sido indefinidos.\n" -#: command.c:4856 +#: command.c:4948 #, c-format msgid "Title is \"%s\".\n" msgstr "El título es «%s».\n" -#: command.c:4858 +#: command.c:4950 #, c-format msgid "Title is unset.\n" msgstr "El título ha sido indefinido.\n" -#: command.c:4865 +#: command.c:4957 #, c-format msgid "Tuples only is on.\n" msgstr "Mostrar sólo filas está activado.\n" -#: command.c:4867 +#: command.c:4959 #, c-format msgid "Tuples only is off.\n" msgstr "Mostrar sólo filas está desactivado.\n" -#: command.c:4873 +#: command.c:4965 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "El estilo Unicode de borde es «%s».\n" -#: command.c:4879 +#: command.c:4971 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "El estilo de línea Unicode de columna es «%s».\n" -#: command.c:4885 +#: command.c:4977 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "El estilo de línea Unicode de encabezado es «%s».\n" -#: command.c:5134 +#: command.c:5226 #, c-format msgid "\\!: failed" msgstr "\\!: falló" -#: command.c:5168 +#: command.c:5264 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch no puede ser usado con una consulta vacía" -#: command.c:5200 +#: command.c:5296 #, c-format msgid "could not set timer: %m" msgstr "no se pudo establecer un temporizador: %m" -#: command.c:5269 +#: command.c:5365 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (cada %gs)\n" -#: command.c:5272 +#: command.c:5368 #, c-format msgid "%s (every %gs)\n" msgstr "%s (cada %gs)\n" -#: command.c:5340 +#: command.c:5432 #, c-format msgid "could not wait for signals: %m" msgstr "no se pudo esperar señales: %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5488 command.c:5495 common.c:632 common.c:639 common.c:1123 #, c-format msgid "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" msgstr "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" -#: command.c:5584 +#: command.c:5674 #, c-format msgid "\"%s.%s\" is not a view" msgstr "«%s.%s» no es una vista" -#: command.c:5600 +#: command.c:5690 #, c-format msgid "could not parse reloptions array" msgstr "no se pudo interpretar el array reloptions" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "no se puede escapar sin una conexión activa" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "se ha perdido la conexión al servidor" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "La conexión al servidor se ha perdido. Intentando reiniciar: " -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "Falló.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "Con éxito.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "PQresultStatus no esperado: %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "Duración: %.3f ms\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Duración: %.3f ms (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Duración: %.3f ms (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Duración: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "No está conectado a una base de datos." -#: common.c:674 +#: common.c:714 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "Notificación asíncrona «%s» con carga «%s» recibida del proceso de servidor con PID %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "Notificación asíncrona «%s» recibida del proceso de servidor con PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "no se pudo mostrar la tabla de resultados: %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "\\gset no retornó renglón alguno" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "\\gset retornó más de un renglón" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "se ignoró intentó de hacer \\gset a variable con tratamiento especial «%s»" -#: common.c:1063 +#: common.c:1103 #, c-format msgid "" -"***(Single step mode: verify command)*******************************************\n" +"/**(Single step mode: verify command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to cancel)********************\n" +"/**(press return to proceed or enter x and return to cancel)*******************/\n" msgstr "" -"***(Modo paso a paso: verifique la orden)****************************************\n" +"/**(Modo paso a paso: verifique la orden)**************************************/\n" "%s\n" -"***(presione enter para continuar, o x y enter para cancelar)*******************\n" +"/**(presione enter para continuar, o x y enter para cancelar)******************/\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "SENTENCIA: %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "estado de transacción inesperado (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "Columna" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "Tipo" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "La orden no tiene resultado, o el resultado no tiene columnas.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "la obtención de resultados en modo trozado falló" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -941,11 +990,6 @@ msgstr "\\copy: error de procesamiento en «%s»" msgid "\\copy: parse error at end of line" msgstr "\\copy: error de procesamiento al final de la línea" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "no se pudo ejecutar la orden «%s»: %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -983,338 +1027,339 @@ msgstr "" "Ingrese los datos a ser copiados seguidos de un fin de línea.\n" "Termine con un backslash y un punto, o una señal EOF." -#: copy.c:682 +#: copy.c:684 msgid "aborted because of read failure" msgstr "se abortó por un error de lectura" -#: copy.c:716 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "tratando de salir del modo copy" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview: la sentencia no produjo un conjunto de resultados" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview: la consulta debe retornar al menos tres columnas" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "\\crosstabview: vertical and horizontal headers must be different columns" msgstr "\\crosstabview: los encabezados verticales y horizontales deben ser columnas distintas" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "\\crosstabview: data column must be specified when query returns more than three columns" msgstr "\\crosstabview: la columna de datos debe ser especificada cuando la consulta retorna más de tres columnas" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview: se superó el número máximo de columnas (%d)" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"" msgstr "\\crosstabview: el resultado de la consulta contiene múltiples valores para la fila «%s», columna «%s»" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview: el número de columna %d está fuera del rango 1..%d" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview: nombre de columna «%s» ambiguo" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: nombre de columna «%s» no encontrado" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "Esquema" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "Nombre" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "Tipo de dato de salida" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "Tipos de datos de argumentos" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "Descripción" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "Listado de funciones de agregación" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "El servidor (versión %s) no soporta métodos de acceso." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "Indice" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "Tabla" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "Manejador" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "Lista de métodos de acceso" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "Dueño" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "Ubicación" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "Opciones" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "Tamaño" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "Listado de tablespaces" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df sólo acepta las opciones [antpwS+]" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df no acepta la opción «%c» en un servidor versión %s" #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "agg" -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "ventana" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "proc" -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "func" -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "disparador" -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "inmutable" -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "estable" -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "volátil" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "Volatilidad" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "restringida" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "segura" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "insegura" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "Paralelismo" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "definidor" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "invocador" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "Seguridad" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "Lenguaje" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "Nombre interno" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "Listado de funciones" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "Elementos" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "Listado de tipos de dato" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "Tipo arg izq" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "Tipo arg der" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "Tipo resultado" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "Función" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "Listado de operadores" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "Codificación" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "Proveedor de locale" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "Collate" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "Ctype" -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "configuración ICU" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "Configuración regional" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "Reglas ICU:" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "Tablespace" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "Listado de base de datos" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "tabla" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "vista" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "vista materializada" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "secuencia" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "tabla foránea" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "tabla particionada" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "Privilegios de acceso a columnas" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "Políticas" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "Privilegios" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "función" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "tipo" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "esquema" @@ -1346,293 +1391,293 @@ msgstr "familia de operadores" msgid "rule" msgstr "regla" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "Descripciones de objetos" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "No se encontró relación llamada «%s»." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "No se encontró ninguna relación." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "No se encontró relación con OID %s." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "Inicio" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "Mínimo" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "Máximo" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "Incremento" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "sí" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "no" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "¿Cicla?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "Cache" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "Asociada a: %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "Secuencia para columna identidad: %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Secuencia unlogged «%s.%s»" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Secuencia «%s.%s»" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Tabla unlogged «%s.%s»" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "Tabla «%s.%s»" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "Vista «%s.%s»" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "Vista materializada unlogged «%s.%s»" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Vista materializada \"%s.%s\"" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Índice unlogged «%s.%s»" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "Índice «%s.%s»" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Índice particionado unlogged «%s.%s»" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Índice particionado «%s.%s»" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "Tabla TOAST «%s.%s»" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Tipo compuesto «%s.%s»" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Tabla foránea «%s.%s»" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Tabla unlogged particionada «%s.%s»" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Tabla particionada «%s.%s»" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "Ordenamiento" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "Nulable" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "Por omisión" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "¿Llave?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "Definición" -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "Opciones de FDW" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "Almacenamiento" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "Compresión" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "Estadísticas" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "Partición de: %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "Sin restricción de partición" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "Restricción de partición: %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "Llave de partición: %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Tabla dueña: «%s.%s»" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "llave primaria, " -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "único" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " nulls no distintos" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr ", " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "de tabla «%s.%s»" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", predicado (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", clustered" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", no válido" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", postergable" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", inicialmente postergada" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", identidad de replicación" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "Índices:" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "Restricciones CHECK:" -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "Restricciones de llave foránea:" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "Referenciada por:" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "Políticas:" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "Políticas (seguridad de registros forzada):" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "Políticas (seguridad de filas activa): (ninguna)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "Políticas (seguridad de filas forzada): (ninguna)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "Políticas (seguridad de filas inactiva):" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "Objetos de estadísticas:" @@ -1652,7 +1697,7 @@ msgstr "Reglas que se activan siempre:" msgid "Rules firing on replica only:" msgstr "Reglas que se activan sólo en las réplicas:" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "Publicaciones:" @@ -1751,7 +1796,7 @@ msgstr ", tablespace «%s»" msgid "List of roles" msgstr "Lista de roles" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "Nombre de rol" @@ -1829,368 +1874,368 @@ msgstr "No se encontró ningún parámetro para el rol «%s»." msgid "Did not find any settings." msgstr "No se encontró ningún parámetro." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "Listado de parámetros" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "Miembro de" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "Otorgador" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "Lista de roles otorgados" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "índice" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "Tabla TOAST" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "índice particionado" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "permanente" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "temporal" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "unlogged" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "Persistencia" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "Método de acceso" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "Listado de relaciones" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "El servidor (versión %s) no soporta particionamiento declarativo de tablas." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "Listado de índices particionados" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "Listado de tablas particionadas" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "Listado de relaciones particionadas" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "Nombre del padre" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "Tamaño de particiones hoja" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "Tamaño total" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "Confiable" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "Lenguaje interno" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "Manejador de llamada" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "Validador" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "Manejador en línea" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "Lista de lenguajes" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "Check" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "Listado de dominios" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "Fuente" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "Destino" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "Por omisión?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "Listado de conversiones" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "Parámetro" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "Valor" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "Contexto" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "Listado de parámetro de configuración" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "Listado de parámetros de configuración no-default" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "El servidor (versión %s) no soporta triggers por eventos." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "Evento" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "activo" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "réplica" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "siempre" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "inactivo" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "Activo" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "Etiquetas" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "Listado de disparadores por eventos" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "El servidor (versión %s) no soporta estadísticas extendidas." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Dependencias" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "Lista de estadísticas extendidas" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Tipo fuente" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Tipo destino" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "en asignación" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Implícito?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "Listado de conversiones de tipo (casts)" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "Proveedor" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "¿Determinístico?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "Listado de ordenamientos" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "Listado de esquemas" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "Listado de analizadores de búsqueda en texto" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "No se encontró ningún analizador de búsqueda en texto llamado «%s»." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "No se encontró ningún analizador de búsqueda en texto." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "Inicio de parse" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "Método" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "Obtener siguiente elemento" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "Fin de parse" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "Obtener encabezado" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "Obtener tipos de elemento" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Analizador de búsqueda en texto «%s.%s»" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "Analizador de búsqueda en texto «%s»" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "Nombre de elemento" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Tipos de elemento para el analizador «%s.%s»" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "Tipos de elemento para el analizador «%s»" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "Plantilla" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "Opciones de inicialización" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "Listado de diccionarios de búsqueda en texto" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "Inicializador" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Fn. análisis léx." -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "Listado de plantillas de búsqueda en texto" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "Listado de configuraciones de búsqueda en texto" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "No se encontró una configuración de búsqueda en texto llamada «%s»." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "No se encontró una configuración de búsqueda en texto." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "Elemento" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "Diccionarios" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Configuración de búsqueda en texto «%s.%s»" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "Configuración de búsqueda en texto «%s»" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "" "\n" @@ -2199,7 +2244,7 @@ msgstr "" "\n" "Analizador: «%s.%s»" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "" "\n" @@ -2208,265 +2253,273 @@ msgstr "" "\n" "Analizador: «%s»" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "Listado de conectores de datos externos" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "Conectores de datos externos" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "Versión" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "Listado de servidores foráneos" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "Servidor" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "Nombre de usuario" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "Listado de mapeos de usuario" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "Listado de tablas foráneas" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "Listado de extensiones instaladas" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "No se encontró extensión llamada «%s»." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "No se encontró ninguna extensión." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "Descripción de objeto" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "Objetos en extensión «%s»" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "el nombre no es válido (demasiados puntos): %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "no están implementadas las referencias entre bases de datos: %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "El servidor (versión %s) no soporta publicaciones." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "Todas las tablas" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Inserts" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Updates" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Deletes" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Truncates" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Via root" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "Listado de publicaciones" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "No se encontró publicación llamada «%s»." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "No se encontró ninguna publicación." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "Publicación %s" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "Tablas:" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "Tablas de esquemas:" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "El servidor (versión %s) no soporta suscripciones." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "Publicación" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "Binario" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "De flujo" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "Commit 2-fases" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "Desactivar en error" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "Origen" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "Contraseña requerida" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "¿Ejec. como dueño?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "“Failover”" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "Commit síncrono" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "Conninfo" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "Saltar LSN" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "Listado de suscripciones" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(ninguno)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "AM" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "Tipo de entrada" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "Tipo de almacenamiento" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "Clase de operador" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "Familia de operadores" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "Listado de clases de operador" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Tipos aplicables" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "Listado de familias de operadores" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "Operador" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "Estrategia" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "ordenamiento" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "búsqueda" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "Propósito" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "familia de ops de ordenamiento" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "Lista de operadores de familias de operadores" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "Tipo de dato izquierdo registrado" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "Tipo de dato derecho registrado" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "Número" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "Listado de funciones de la familia de operadores %s" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "Objetos grandes" -#: help.c:75 +#: help.c:63 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2474,11 +2527,11 @@ msgstr "" "psql es el terminal interactivo de PostgreSQL.\n" "\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:502 msgid "Usage:\n" msgstr "Empleo:\n" -#: help.c:77 +#: help.c:65 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2486,30 +2539,27 @@ msgstr "" " psql [OPCIONES]... [BASE-DE-DATOS [USUARIO]]\n" "\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "Opciones generales:\n" -#: help.c:84 +#: help.c:68 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr " -c, --command=ORDEN ejecutar sólo una orden (SQL o interna) y salir\n" -#: help.c:85 -#, c-format -msgid " -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr "" -" -d, --dbname=NOMBRE nombre de base de datos a conectarse\n" -" (por omisión: «%s»)\n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=BASE base de datos a la cual conectarse\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=ARCHIVO ejecutar órdenes desde archivo, luego salir\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list listar bases de datos, luego salir\n" -#: help.c:89 +#: help.c:72 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2519,15 +2569,15 @@ msgstr "" " definir variable de psql NOMBRE a VALOR\n" " (p.ej. -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión, luego salir\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc no leer archivo de configuración (~/.psqlrc)\n" -#: help.c:94 +#: help.c:77 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" @@ -2535,19 +2585,19 @@ msgstr "" " -1 («uno»), --single-transaction\n" " ejecuta órdenes en una única transacción\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=opcs] mostrar esta ayuda, luego salir\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands listar órdenes backslash, luego salir\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables listar variables especiales, luego salir\n" -#: help.c:100 +#: help.c:83 msgid "" "\n" "Input and output options:\n" @@ -2555,47 +2605,47 @@ msgstr "" "\n" "Opciones de entrada y salida:\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all mostrar las órdenes del script\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors mostrar órdenes fallidas\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries mostrar órdenes enviadas al servidor\n" -#: help.c:104 +#: help.c:87 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden mostrar consultas generadas por órdenes internas\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=ARCH envía el registro de la sesión a un archivo\n" -#: help.c:106 +#: help.c:89 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr " -n, --no-readline deshabilitar edición de línea de órdenes (readline)\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=ARCHIVO enviar resultados de consultas a archivo (u |orden)\n" -#: help.c:108 +#: help.c:91 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr " -q, --quiet modo silencioso (sin mensajes, sólo resultados)\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step modo paso a paso (confirmar cada consulta)\n" -#: help.c:110 +#: help.c:93 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr " -S, --single-line modo de líneas (fin de línea termina la orden SQL)\n" -#: help.c:112 +#: help.c:95 msgid "" "\n" "Output format options:\n" @@ -2603,15 +2653,15 @@ msgstr "" "\n" "Opciones de formato de salida:\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align modo de salida desalineado\n" -#: help.c:114 +#: help.c:97 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv modo de salida de tabla CSV (valores separados por comas)\n" -#: help.c:115 +#: help.c:98 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2620,15 +2670,15 @@ msgstr "" " -F, --field-separator=CADENA separador de campos para salida desalineada\n" " (por omisión: «%s»)\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html modo de salida en tablas HTML\n" -#: help.c:119 +#: help.c:102 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr " -P, --pset=VAR[=ARG] definir opción de impresión VAR en ARG (ver orden \\pset)\n" -#: help.c:120 +#: help.c:103 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" @@ -2636,21 +2686,21 @@ msgstr "" " -R, --record-separator=CADENA separador de registros para salida desalineada\n" " (por omisión: salto de línea)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only sólo muestra registros\n" -#: help.c:123 +#: help.c:106 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr "" " -T, --table-attr=TEXTO\n" " definir atributos de marcas de tabla HTML (ancho, borde)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded activar modo expandido de salida de tablas\n" -#: help.c:125 +#: help.c:108 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" @@ -2658,7 +2708,7 @@ msgstr "" " -z, --field-separator-zero\n" " definir separador de campos para salida desalineada al byte cero\n" -#: help.c:127 +#: help.c:110 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" @@ -2666,7 +2716,7 @@ msgstr "" " -0, --record-separator-zero\n" " definir separador de filas para salida desalineada al byte cero\n" -#: help.c:130 +#: help.c:113 msgid "" "\n" "Connection options:\n" @@ -2674,40 +2724,31 @@ msgstr "" "\n" "Opciones de conexión:\n" -#: help.c:133 -#, c-format -msgid " -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=NOMBRE nombre del anfitrión o directorio de socket\n" -" (por omisión: «%s»)\n" - -#: help.c:134 -msgid "local socket" -msgstr "socket local" +" -h, --host=ANFITRIÓN anfitrión de la base de datos o\n" +" directorio del enchufe (socket)\n" -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr " -p, --port=PUERTO puerto del servidor (por omisión: «%s»)\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PUERTO puerto del servidor\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr "" -" -U, --username=NOMBRE\n" -" nombre de usuario (por omisión: «%s»)\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=USUARIO nombre usuario de la base de datos\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir contraseña\n" -#: help.c:143 +#: help.c:118 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password forzar petición de contraseña\n" " (debería ser automático)\n" -#: help.c:145 +#: help.c:120 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" @@ -2721,41 +2762,41 @@ msgstr "" "en la documentación de PostgreSQL.\n" "\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Reporte de errores a <%s>.\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "General\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr "" " \\bind [PARAM]...\n" " definir parámetros de consulta\n" -#: help.c:193 +#: help.c:168 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright mostrar términos de uso y distribución de PostgreSQL\n" -#: help.c:194 +#: help.c:169 msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr "" " \\crosstabview [COLUMNAS]\n" " ejecutar la consulta y desplegar en «crosstab»\n" -#: help.c:195 +#: help.c:170 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose mostrar error más reciente en máxima verbosidad\n" -#: help.c:196 +#: help.c:171 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2764,242 +2805,248 @@ msgstr "" " ejecuta la consulta (y envía el resultado a un fichero o |pipe);\n" " \\g sin argumentos es equivalente a un punto y coma\n" -#: help.c:198 +#: help.c:173 msgid " \\gdesc describe result of query, without executing it\n" msgstr " \\gdesc describir resultado de la consulta, sin ejecutarla\n" -#: help.c:199 +#: help.c:174 msgid " \\gexec execute query, then execute each value in its result\n" msgstr " \\gexec ejecutar la consulta, luego ejecuta cada valor del resultado\n" -#: help.c:200 +#: help.c:175 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr "" " \\gset [PREFIJO] ejecutar la consulta y almacenar el resultado en variables\n" " de psql\n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr "" " \\gx [(OPTIONS)] [FILE]\n" " como \\g, pero fuerza el modo de salida expandido\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q salir de psql\n" -#: help.c:203 -msgid " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" -msgstr " \\watch [[i=]SEG] [c=N] ejecute consulta cada SEG segundos, hasta N veces\n" +#: help.c:178 +msgid "" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" +msgstr "" +" \\watch [[i=]SEG] [c=N] [m=MIN]\n" +" ejecutar consulta cada SEG segundos, hasta N veces,\n" +" deteniéndose si menos de MIN registros son devueltos\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "Ayuda\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commands] desplegar ayuda sobre las órdenes backslash\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options desplegar ayuda sobre opciones de línea de órdenes\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables desplegar ayuda sobre variables especiales\n" -#: help.c:211 +#: help.c:188 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr "" " \\h [NOMBRE] mostrar ayuda de sintaxis de órdenes SQL;\n" " use «*» para todas las órdenes\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "Búfer de consulta\n" -#: help.c:215 +#: help.c:192 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr "" " \\e [ARCHIVO] [LÍNEA]\n" " editar el búfer de consulta (o archivo) con editor externo\n" -#: help.c:216 +#: help.c:193 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr "" " \\ef [NOMBRE-FUNCIÓN [LÍNEA]]\n" " editar una función con editor externo\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr "" " \\ev [NOMBRE-VISTA [LÍNEA]]\n" " editar definición de una vista con editor externo\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p mostrar el contenido del búfer de consulta\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r reiniciar (limpiar) el búfer de consulta\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [ARCHIVO] mostrar historial de órdenes o guardarlo en archivo\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr " \\w ARCHIVO escribir búfer de consulta a archivo\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "" "Entrada/Salida\n" " (con -n, donde existe, se omite el salto de línea final)\n" -#: help.c:227 +#: help.c:204 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr " \\copy ... ejecutar orden SQL COPY con flujo de datos al cliente\n" -#: help.c:228 +#: help.c:205 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [STRING] escribe la cadena en la salida estándar\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i ARCHIVO ejecutar órdenes desde archivo\n" -#: help.c:230 +#: help.c:207 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr " \\ir ARCHIVO como \\i, pero relativo a la ubicación del script actual\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [ARCHIVO] enviar resultados de consultas a archivo u |orden\n" -#: help.c:232 +#: help.c:209 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr " \\qecho [-n] [STRING] escribe la cadena hacia flujo de salida \\o\n" -#: help.c:233 +#: help.c:210 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr " \\warn [-n] [STRING] escribe la cadena a la salida de error estándar\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "Condicional\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPRESIÓN inicia bloque condicional\n" -#: help.c:238 +#: help.c:215 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif EXPR alternativa dentro del bloque condicional actual\n" -#: help.c:239 +#: help.c:216 msgid " \\else final alternative within current conditional block\n" msgstr " \\else alternativa final dentro del bloque condicional actual\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif termina el bloque condicional\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "Informativo\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr " (opciones: S = desplegar objetos de sistema, + = agregar más detalle)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr " \\d[S+] listar tablas, vistas y secuencias\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr " \\d[S+] NOMBRE describir tabla, índice, secuencia o vista\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" msgstr " \\da[S] [PATRÓN] listar funciones de agregación\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [PATRÓN] listar métodos de acceso\n" -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] listar las clases de operadores\n" -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] listar las familias de operadores\n" -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] listar los operadores de la familia de operadores\n" -#: help.c:252 +#: help.c:229 msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] enumera las funciones de la familia de operadores\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [PATRÓN] listar tablespaces\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [PATRÓN] listar conversiones\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [PATRÓN] listar parámetros de configuración\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [PATRÓN] listar conversiones de tipo (casts)\n" -#: help.c:257 +#: help.c:234 msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr " \\dd[S] [PATRÓN] listar comentarios de objetos que no aparecen en otra parte\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [PATRÓN] listar dominios\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [PATRÓN] listar privilegios por omisión\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [PATRÓN] listar tablas foráneas\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [PATRÓN] listar servidores foráneos\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\det[+] [PATRÓN] listar tablas foráneas\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [PATRÓN] listar mapeos de usuario\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [PATRÓN] listar conectores de datos externos\n" -#: help.c:265 +#: help.c:242 msgid "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] functions\n" @@ -3007,47 +3054,47 @@ msgstr "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " listar funciones [sólo ag./normal/proc./trigger/ventana]\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr " \\dF[+] [PATRÓN] listar configuraciones de búsqueda en texto\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr " \\dFd[+] [PATRÓN] listar diccionarios de búsqueda en texto\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr " \\dFp[+] [PATRÓN] listar analizadores (parsers) de búsq. en texto\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr " \\dFt[+] [PATRÓN] listar plantillas de búsqueda en texto\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [PATRÓN] listar roles\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [PATRÓN] listar índices\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr " \\dl[+] listar objetos grandes, lo mismo que \\lo_list\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [PATRÓN] listar lenguajes procedurales\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [PATRÓN] listar vistas materializadas\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [PATRÓN] listar esquemas\n" -#: help.c:277 +#: help.c:254 msgid "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" @@ -3055,93 +3102,93 @@ msgstr "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " listar operadores\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S] [PATRÓN] listar ordenamientos (collations)\n" -#: help.c:280 +#: help.c:257 msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr " \\dp[S] [PATRÓN] listar privilegios de acceso a tablas, vistas y secuencias\n" -#: help.c:281 +#: help.c:258 msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" msgstr " \\dP[tin+] [PATRÓN] listar relaciones particionadas (sólo tablas/índices) [n=anidadas]\n" -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr "" " \\drds [PATRÓN_ROL [PATRÓN_BASE]]\n" " listar parámetros de rol por base de datos\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\drg[S] [PATRÓN] listar roles\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[+] [PATRÓN] listar publicaciones de replicación\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [PATRÓN] listar suscripciones de replicación\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [PATRÓN] listar secuencias\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [PATRÓN] listar tablas\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [PATRÓN] listar tipos de dato\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [PATRÓN] listar roles\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [PATRÓN] listar vistas\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [PATRÓN] listar extensiones\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [PATRÓN] listar estadísticas extendidas\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [PATRÓN] listar disparadores por eventos\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [PATRÓN] listar bases de datos\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] FUNCIÓN mostrar la definición de una función\n" -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv[+] VISTA mostrar la definición de una vista\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [PATRÓN] lo mismo que \\dp\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "Objetos Grandes\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr " \\lo_export LOBOID ARCHIVO escribir objeto grande a archivo\n" -#: help.c:302 +#: help.c:279 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3149,38 +3196,38 @@ msgstr "" " \\lo_import ARCHIVO [COMENTARIO]\n" " leer objeto grande desde archivo\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\lo_list[+] listar objetos grandes\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID borrar un objeto grande\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "Formato\n" -#: help.c:309 +#: help.c:286 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr " \\a cambiar entre modo de salida alineado y sin alinear\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr " \\C [CADENA] definir título de tabla, o indefinir si es vacío\n" -#: help.c:311 +#: help.c:288 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr "" " \\f [CADENA] mostrar o definir separador de campos para\n" " modo de salida sin alinear\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H cambiar modo de salida HTML (actualmente %s)\n" -#: help.c:314 +#: help.c:291 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3188,38 +3235,38 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [NOMBRE [VALOR]] define opción de tabla de salida\n" " (border|columns|csv_fieldsep|expanded|fieldsep|fieldsep_zero|\n" " footer|format|linestyle|null|numericlocale|pager|\n" " pager_min_lines|recordsep|recordsep_zero|tableattr|title|\n" " tuples_only|unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] mostrar sólo filas (actualmente %s)\n" -#: help.c:323 +#: help.c:300 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr " \\T [CADENA] definir atributos HTML de
, o indefinir si es vacío\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] cambiar modo expandido (actualmente %s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "auto" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "Conexiones\n" -#: help.c:330 +#: help.c:307 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3228,7 +3275,7 @@ msgstr "" " \\c[onnect] [BASE-DE-DATOS|- USUARIO|- ANFITRIÓN|- PUERTO|- | conninfo]\n" " conectar a una nueva base de datos (actual: «%s»)\n" -#: help.c:334 +#: help.c:311 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3236,72 +3283,72 @@ msgstr "" " \\c[onnect] [BASE-DE-DATOS|- USUARIO|- ANFITRIÓN|- PUERTO|- | conninfo]\n" " conectar a una nueva base de datos (no hay conexión actual)\n" -#: help.c:336 +#: help.c:313 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo despliega la información sobre la conexión actual\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr "" " \\encoding [CODIFICACIÓN]\n" " mostrar o definir codificación del cliente\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr "" " \\password [USUARIO]\n" " cambiar la contraseña para un usuario en forma segura\n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "Sistema Operativo\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [DIR] cambiar el directorio de trabajo actual\n" -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVVAR obtener variable de ambiente\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr "" " \\setenv NOMBRE [VALOR]\n" " definir o indefinir variable de ambiente\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr "" " \\timing [on|off] mostrar tiempo de ejecución de órdenes\n" " (actualmente %s)\n" -#: help.c:347 +#: help.c:324 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr "" " \\! [ORDEN] ejecutar orden en intérprete de órdenes (shell),\n" " o iniciar intérprete interactivo\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "Variables\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr " \\prompt [TEXTO] NOMBRE preguntar al usuario el valor de la variable\n" -#: help.c:352 +#: help.c:329 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr "" " \\set [NOMBRE [VALOR]] definir variables internas,\n" " listar todas si no se dan parámetros\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NOMBRE indefinir (eliminar) variable interna\n" -#: help.c:392 +#: help.c:369 msgid "" "List of specially treated variables\n" "\n" @@ -3309,11 +3356,11 @@ msgstr "" "Lista de variables con tratamiento especial\n" "\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "variables psql:\n" -#: help.c:396 +#: help.c:373 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3322,7 +3369,7 @@ msgstr "" " psql --set=NOMBRE=VALOR\n" " o \\set NOMBRE VALOR dentro de psql\n" -#: help.c:398 +#: help.c:375 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3330,7 +3377,7 @@ msgstr "" " AUTOCOMMIT si está definida, órdenes SQL exitosas se comprometen\n" " automáticamente\n" -#: help.c:400 +#: help.c:377 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3339,13 +3386,13 @@ msgstr "" " COMP_KEYWORD_CASE determina si usar mayúsculas al completar palabras SQL\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:403 +#: help.c:380 msgid "" " DBNAME\n" " the currently connected database name\n" msgstr " DBNAME la base de datos actualmente conectada\n" -#: help.c:405 +#: help.c:382 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3354,7 +3401,7 @@ msgstr "" " ECHO controla qué entrada se escribe a la salida estándar\n" " [all, errors, none, queries]\n" -#: help.c:408 +#: help.c:385 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3363,13 +3410,13 @@ msgstr "" " ECHO_HIDDEN muestra consultas internas usadas por órdenes backslash\n" " con «noexec» sólo las muestra sin ejecutarlas\n" -#: help.c:411 +#: help.c:388 msgid "" " ENCODING\n" " current client character set encoding\n" msgstr " ENCODING codificación actual del cliente\n" -#: help.c:413 +#: help.c:390 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3377,7 +3424,7 @@ msgstr "" " ERROR\n" " «true» si la última consulta falló; si no, «false»\n" -#: help.c:415 +#: help.c:392 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" @@ -3385,7 +3432,7 @@ msgstr "" " FETCH_COUNT número de filas del resultado que extraer y mostrar cada vez\n" " (por omisión: 0=sin límite)\n" -#: help.c:417 +#: help.c:394 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3393,7 +3440,7 @@ msgstr "" " HIDE_TABLEAM\n" " ocultar métodos de acceso de tabla\n" -#: help.c:419 +#: help.c:396 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3401,7 +3448,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " ocultar métodos de compresión\n" -#: help.c:421 +#: help.c:398 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3409,25 +3456,25 @@ msgstr "" " HISTCONTROL controla la lista de historia de órdenes\n" " [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:423 +#: help.c:400 msgid "" " HISTFILE\n" " file name used to store the command history\n" msgstr " HISTFILE nombre de archivo para almacenar historia de órdenes\n" -#: help.c:425 +#: help.c:402 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" msgstr " HISTSIZE número de órdenes a guardar en la historia de órdenes\n" -#: help.c:427 +#: help.c:404 msgid "" " HOST\n" " the currently connected database server host\n" msgstr " HOST el servidor actualmente conectado\n" -#: help.c:429 +#: help.c:406 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3435,13 +3482,13 @@ msgstr "" " IGNOREEOF si no está definida, enviar un EOF a sesión interactiva\n" " termina la aplicación\n" -#: help.c:431 +#: help.c:408 msgid "" " LASTOID\n" " value of the last affected OID\n" msgstr " LASTOID el valor del último OID afectado\n" -#: help.c:433 +#: help.c:410 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3452,7 +3499,7 @@ msgstr "" " mensaje y SQLSTATE del último error, o cadena vacía y\n" " «00000» si no hubo\n" -#: help.c:436 +#: help.c:413 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3460,25 +3507,25 @@ msgstr "" " ON_ERROR_ROLLBACK si está definido, un error no aborta la transacción\n" " (usa «savepoints» implícitos)\n" -#: help.c:438 +#: help.c:415 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" msgstr " ON_ERROR_STOP detiene ejecución por lotes al ocurrir un error\n" -#: help.c:440 +#: help.c:417 msgid "" " PORT\n" " server port of the current connection\n" msgstr " PORT puerto del servidor de la conexión actual\n" -#: help.c:442 +#: help.c:419 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" msgstr " PROMPT1 especifica el prompt estándar de psql\n" -#: help.c:444 +#: help.c:421 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" @@ -3486,19 +3533,19 @@ msgstr "" " PROMPT2 especifica el prompt usado cuando una sentencia continúa\n" " de una línea anterior\n" -#: help.c:446 +#: help.c:423 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" msgstr " PROMPT3 especifica el prompt usado durante COPY ... FROM STDIN\n" -#: help.c:448 +#: help.c:425 msgid "" " QUIET\n" " run quietly (same as -q option)\n" msgstr " QUIET ejecuta silenciosamente (igual que -q)\n" -#: help.c:450 +#: help.c:427 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3506,7 +3553,7 @@ msgstr "" " ROW_COUNT número de tuplas retornadas o afectadas por última\n" " consulta, o 0\n" -#: help.c:452 +#: help.c:429 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3516,7 +3563,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " versión del servidor (cadena corta o numérica)\n" -#: help.c:455 +#: help.c:432 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3524,7 +3571,7 @@ msgstr "" " SHELL_ERROR\n" " «true» si la última orden de shell falló, «false» si tuvo éxito\n" -#: help.c:457 +#: help.c:434 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3532,7 +3579,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " estado de salida de la última orden de shell\n" -#: help.c:459 +#: help.c:436 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3541,7 +3588,7 @@ msgstr "" " mostrar todos los resultados de una consulta combinada (\\;) en lugar\n" " de sólo mostrar el último\n" -#: help.c:461 +#: help.c:438 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3549,31 +3596,31 @@ msgstr "" " SHOW_CONTEXT controla el despliegue de campos de contexto de mensaje\n" " [never, errors, always]\n" -#: help.c:463 +#: help.c:440 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" msgstr " SINGLELINE fin de línea termina modo de órdenes SQL (igual que -S)\n" -#: help.c:465 +#: help.c:442 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" msgstr " SINGLESTEP modo paso a paso (igual que -s)\n" -#: help.c:467 +#: help.c:444 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" msgstr " SQLSTATE SQLSTATE de la última consulta, o «00000» si no hubo error\n" -#: help.c:469 +#: help.c:446 msgid "" " USER\n" " the currently connected database user\n" msgstr " USER el usuario actualmente conectado\n" -#: help.c:471 +#: help.c:448 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3581,7 +3628,7 @@ msgstr "" " VERBOSITY controla la verbosidad de errores [default, verbose,\n" " terse, sqlstate]\n" -#: help.c:473 +#: help.c:450 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3593,7 +3640,7 @@ msgstr "" " VERSION_NUM\n" " versión de psql (cadena verbosa, corta o numérica)\n" -#: help.c:478 +#: help.c:455 msgid "" "\n" "Display settings:\n" @@ -3601,7 +3648,7 @@ msgstr "" "\n" "Parámetros de despliegue:\n" -#: help.c:480 +#: help.c:457 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3611,25 +3658,25 @@ msgstr "" " o \\pset NOMBRE [VALOR] dentro de psql\n" "\n" -#: help.c:482 +#: help.c:459 msgid "" " border\n" " border style (number)\n" msgstr " border estilo de borde (número)\n" -#: help.c:484 +#: help.c:461 msgid "" " columns\n" " target width for the wrapped format\n" msgstr " columns define el ancho para formato «wrapped»\n" -#: help.c:486 +#: help.c:463 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" msgstr " expanded (o x) salida expandida [on, off, auto]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid "" " fieldsep\n" @@ -3638,37 +3685,37 @@ msgstr "" " fieldsep separador de campos para formato «unaligned»\n" " (por omisión: «%s»)\n" -#: help.c:491 +#: help.c:468 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" msgstr " fieldsep_zero separador de campos en «unaligned» es byte cero\n" -#: help.c:493 +#: help.c:470 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" msgstr " footer activa o desactiva el pie de tabla [on, off]\n" -#: help.c:495 +#: help.c:472 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" msgstr " format define el formato de salida [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" msgstr " linestyle define el estilo de dibujo de líneas [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid "" " null\n" " set the string to be printed in place of a null value\n" msgstr " null define la cadena a imprimirse para valores null\n" -#: help.c:501 +#: help.c:478 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" @@ -3676,26 +3723,26 @@ msgstr "" " numericlocale activa despliegue de carácter específico del lenguaje para\n" " separar grupos de dígitos\n" -#: help.c:503 +#: help.c:480 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" msgstr " pager controla cuándo se usará un paginador externo [yes, no, always]\n" -#: help.c:505 +#: help.c:482 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" msgstr " recordsep separador de registros (líneas) para formato «unaligned»\n" -#: help.c:507 +#: help.c:484 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" msgstr " recordsep_zero separador de registros en «unaligned» es byte cero\n" # XXX WTF does this mean? -#: help.c:509 +#: help.c:486 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3705,19 +3752,19 @@ msgstr "" " o ancho proporcional de columnas alineadas a la izquierda\n" " en formato «latex-longtable»\n" -#: help.c:512 +#: help.c:489 msgid "" " title\n" " set the table title for subsequently printed tables\n" msgstr " title define el título de tablas\n" -#: help.c:514 +#: help.c:491 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" msgstr " tuples_only si está definido, sólo los datos de la tabla se muestran\n" -#: help.c:516 +#: help.c:493 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3729,7 +3776,17 @@ msgstr "" " unicode_header_linestyle\n" " define el estilo de líneas Unicode [single, double]\n" -#: help.c:521 +#: help.c:497 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" define el ancho máximo del encabezado para el formato expandido\n" +" [full, column, page, valor entero]\n" + +#: help.c:501 msgid "" "\n" "Environment variables:\n" @@ -3737,7 +3794,7 @@ msgstr "" "\n" "Variables de ambiente:\n" -#: help.c:525 +#: help.c:505 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3746,7 +3803,7 @@ msgstr "" " NOMBRE=VALOR [NOMBRE=VALOR] psql ...\n" " o \\setenv NOMBRE [VALOR] dentro de psql\n" -#: help.c:527 +#: help.c:507 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3757,55 +3814,55 @@ msgstr "" " psql ...\n" " o \\setenv NOMBRE [VALOR] dentro de psql\n" -#: help.c:530 +#: help.c:510 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" msgstr " COLUMNS número de columnas para formato «wrapped»\n" -#: help.c:532 +#: help.c:512 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" msgstr " PGAPPNAME igual que el parámetro de conexión application_name\n" -#: help.c:534 +#: help.c:514 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" msgstr " PGDATABASE igual que el parámetro de conexión dbname\n" -#: help.c:536 +#: help.c:516 msgid "" " PGHOST\n" " same as the host connection parameter\n" msgstr " PGHOST igual que el parámetro de conexión host\n" -#: help.c:538 +#: help.c:518 msgid "" " PGPASSFILE\n" " password file name\n" msgstr " PGPASSFILE nombre de archivo de contraseñas\n" -#: help.c:540 +#: help.c:520 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" msgstr " PGPASSWORD contraseña de la conexión (no recomendado)\n" -#: help.c:542 +#: help.c:522 msgid "" " PGPORT\n" " same as the port connection parameter\n" msgstr " PGPORT igual que el parámetro de conexión port\n" -#: help.c:544 +#: help.c:524 msgid "" " PGUSER\n" " same as the user connection parameter\n" msgstr " PGUSER igual que el parámetro de conexión user\n" -#: help.c:546 +#: help.c:526 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3813,7 +3870,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor usado por órdenes \\e, \\ef, y \\ev\n" -#: help.c:548 +#: help.c:528 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -3821,47 +3878,47 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARGS\n" " cómo especificar número de línea al invocar al editor\n" -#: help.c:550 +#: help.c:530 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" msgstr " PSQL_HISTORY ubicación alternativa del archivo de historia de órdenes\n" -#: help.c:552 +#: help.c:532 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" msgstr " PSQL_PAGER, PAGER nombre de programa paginador externo\n" -#: help.c:555 +#: help.c:535 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" msgstr " PSQL_WATCH_PAGER paginador externo para usar con \\watch\n" -#: help.c:558 +#: help.c:538 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" msgstr " PSQLRC ubicación alternativa para el archivo .psqlrc del usuario\n" -#: help.c:560 +#: help.c:540 msgid "" " SHELL\n" " shell used by the \\! command\n" msgstr " SHELL intérprete usado por la orden \\!\n" -#: help.c:562 +#: help.c:542 msgid "" " TMPDIR\n" " directory for temporary files\n" msgstr " TMPDIR directorio para archivos temporales\n" -#: help.c:622 +#: help.c:602 msgid "Available help:\n" msgstr "Ayuda disponible:\n" -#: help.c:717 +#: help.c:697 #, c-format msgid "" "Command: %s\n" @@ -3880,7 +3937,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:740 +#: help.c:720 #, c-format msgid "" "No help available for \"%s\".\n" @@ -3889,17 +3946,17 @@ msgstr "" "No hay ayuda disponible para «%s».\n" "Pruebe \\h sin argumentos para mostrar los elementos de ayuda disponibles.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "no se pudo leer el archivo de entrada: %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "no se pudo guardar historial a archivo «%s»: %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "el historial de órdenes no está soportado en esta instalación" @@ -3986,12 +4043,12 @@ msgstr "consulta ignorada; use \\endif o Ctrl-C para salir del bloque \\if actua msgid "reached EOF without finding closing \\endif(s)" msgstr "se alcanzó EOF sin encontrar el/los \\endif de cierre" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "una cadena de caracteres entre comillas está inconclusa" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s: memoria agotada" @@ -3999,2429 +4056,2449 @@ msgstr "%s: memoria agotada" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:238 -#: sql_help.c:240 sql_help.c:241 sql_help.c:243 sql_help.c:245 sql_help.c:248 -#: sql_help.c:250 sql_help.c:252 sql_help.c:254 sql_help.c:266 sql_help.c:267 -#: sql_help.c:268 sql_help.c:270 sql_help.c:319 sql_help.c:321 sql_help.c:323 -#: sql_help.c:325 sql_help.c:394 sql_help.c:399 sql_help.c:401 sql_help.c:443 -#: sql_help.c:445 sql_help.c:448 sql_help.c:450 sql_help.c:519 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:593 sql_help.c:595 -#: sql_help.c:597 sql_help.c:599 sql_help.c:601 sql_help.c:604 sql_help.c:606 -#: sql_help.c:609 sql_help.c:620 sql_help.c:622 sql_help.c:666 sql_help.c:668 -#: sql_help.c:670 sql_help.c:673 sql_help.c:675 sql_help.c:677 sql_help.c:714 -#: sql_help.c:718 sql_help.c:722 sql_help.c:741 sql_help.c:744 sql_help.c:747 -#: sql_help.c:776 sql_help.c:788 sql_help.c:796 sql_help.c:799 sql_help.c:802 -#: sql_help.c:817 sql_help.c:820 sql_help.c:849 sql_help.c:854 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:896 sql_help.c:898 sql_help.c:900 -#: sql_help.c:902 sql_help.c:905 sql_help.c:907 sql_help.c:954 sql_help.c:999 -#: sql_help.c:1004 sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 -#: sql_help.c:1038 sql_help.c:1049 sql_help.c:1051 sql_help.c:1071 -#: sql_help.c:1081 sql_help.c:1082 sql_help.c:1084 sql_help.c:1086 -#: sql_help.c:1098 sql_help.c:1102 sql_help.c:1104 sql_help.c:1116 -#: sql_help.c:1118 sql_help.c:1120 sql_help.c:1122 sql_help.c:1141 -#: sql_help.c:1143 sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 -#: sql_help.c:1158 sql_help.c:1159 sql_help.c:1160 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1168 sql_help.c:1308 sql_help.c:1310 -#: sql_help.c:1313 sql_help.c:1316 sql_help.c:1318 sql_help.c:1320 -#: sql_help.c:1323 sql_help.c:1326 sql_help.c:1443 sql_help.c:1445 -#: sql_help.c:1447 sql_help.c:1450 sql_help.c:1471 sql_help.c:1474 -#: sql_help.c:1477 sql_help.c:1480 sql_help.c:1484 sql_help.c:1486 -#: sql_help.c:1488 sql_help.c:1490 sql_help.c:1504 sql_help.c:1507 -#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1521 sql_help.c:1523 -#: sql_help.c:1533 sql_help.c:1535 sql_help.c:1545 sql_help.c:1548 -#: sql_help.c:1571 sql_help.c:1573 sql_help.c:1575 sql_help.c:1577 -#: sql_help.c:1580 sql_help.c:1582 sql_help.c:1585 sql_help.c:1588 -#: sql_help.c:1639 sql_help.c:1682 sql_help.c:1685 sql_help.c:1687 -#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1694 sql_help.c:1696 -#: sql_help.c:1699 sql_help.c:1751 sql_help.c:1767 sql_help.c:2000 -#: sql_help.c:2069 sql_help.c:2088 sql_help.c:2101 sql_help.c:2159 -#: sql_help.c:2167 sql_help.c:2177 sql_help.c:2204 sql_help.c:2236 -#: sql_help.c:2254 sql_help.c:2282 sql_help.c:2393 sql_help.c:2439 -#: sql_help.c:2464 sql_help.c:2487 sql_help.c:2491 sql_help.c:2525 -#: sql_help.c:2545 sql_help.c:2567 sql_help.c:2581 sql_help.c:2602 -#: sql_help.c:2631 sql_help.c:2666 sql_help.c:2691 sql_help.c:2738 -#: sql_help.c:3033 sql_help.c:3046 sql_help.c:3063 sql_help.c:3079 -#: sql_help.c:3119 sql_help.c:3173 sql_help.c:3177 sql_help.c:3179 -#: sql_help.c:3186 sql_help.c:3205 sql_help.c:3232 sql_help.c:3267 -#: sql_help.c:3279 sql_help.c:3288 sql_help.c:3332 sql_help.c:3346 -#: sql_help.c:3374 sql_help.c:3382 sql_help.c:3394 sql_help.c:3404 -#: sql_help.c:3412 sql_help.c:3420 sql_help.c:3428 sql_help.c:3436 -#: sql_help.c:3445 sql_help.c:3456 sql_help.c:3464 sql_help.c:3472 -#: sql_help.c:3480 sql_help.c:3488 sql_help.c:3498 sql_help.c:3507 -#: sql_help.c:3516 sql_help.c:3524 sql_help.c:3534 sql_help.c:3545 -#: sql_help.c:3553 sql_help.c:3562 sql_help.c:3573 sql_help.c:3582 -#: sql_help.c:3590 sql_help.c:3598 sql_help.c:3606 sql_help.c:3614 -#: sql_help.c:3622 sql_help.c:3630 sql_help.c:3638 sql_help.c:3646 -#: sql_help.c:3654 sql_help.c:3662 sql_help.c:3679 sql_help.c:3688 -#: sql_help.c:3696 sql_help.c:3713 sql_help.c:3728 sql_help.c:4040 -#: sql_help.c:4150 sql_help.c:4179 sql_help.c:4195 sql_help.c:4197 -#: sql_help.c:4700 sql_help.c:4748 sql_help.c:4906 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:245 +#: sql_help.c:247 sql_help.c:248 sql_help.c:250 sql_help.c:252 sql_help.c:255 +#: sql_help.c:257 sql_help.c:259 sql_help.c:261 sql_help.c:276 sql_help.c:277 +#: sql_help.c:278 sql_help.c:280 sql_help.c:329 sql_help.c:331 sql_help.c:333 +#: sql_help.c:335 sql_help.c:404 sql_help.c:409 sql_help.c:411 sql_help.c:453 +#: sql_help.c:455 sql_help.c:458 sql_help.c:460 sql_help.c:529 sql_help.c:534 +#: sql_help.c:539 sql_help.c:544 sql_help.c:549 sql_help.c:603 sql_help.c:605 +#: sql_help.c:607 sql_help.c:609 sql_help.c:611 sql_help.c:614 sql_help.c:616 +#: sql_help.c:619 sql_help.c:630 sql_help.c:632 sql_help.c:676 sql_help.c:678 +#: sql_help.c:680 sql_help.c:683 sql_help.c:685 sql_help.c:687 sql_help.c:728 +#: sql_help.c:732 sql_help.c:736 sql_help.c:757 sql_help.c:760 sql_help.c:763 +#: sql_help.c:792 sql_help.c:804 sql_help.c:812 sql_help.c:815 sql_help.c:818 +#: sql_help.c:833 sql_help.c:836 sql_help.c:865 sql_help.c:870 sql_help.c:875 +#: sql_help.c:880 sql_help.c:885 sql_help.c:912 sql_help.c:914 sql_help.c:916 +#: sql_help.c:918 sql_help.c:921 sql_help.c:923 sql_help.c:970 sql_help.c:1015 +#: sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 sql_help.c:1035 +#: sql_help.c:1054 sql_help.c:1065 sql_help.c:1067 sql_help.c:1087 +#: sql_help.c:1097 sql_help.c:1098 sql_help.c:1100 sql_help.c:1102 +#: sql_help.c:1114 sql_help.c:1118 sql_help.c:1120 sql_help.c:1132 +#: sql_help.c:1134 sql_help.c:1136 sql_help.c:1138 sql_help.c:1157 +#: sql_help.c:1159 sql_help.c:1163 sql_help.c:1167 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1175 sql_help.c:1176 sql_help.c:1179 +#: sql_help.c:1182 sql_help.c:1184 sql_help.c:1324 sql_help.c:1326 +#: sql_help.c:1329 sql_help.c:1332 sql_help.c:1334 sql_help.c:1336 +#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1464 sql_help.c:1466 +#: sql_help.c:1468 sql_help.c:1471 sql_help.c:1492 sql_help.c:1495 +#: sql_help.c:1498 sql_help.c:1501 sql_help.c:1505 sql_help.c:1507 +#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1525 sql_help.c:1528 +#: sql_help.c:1530 sql_help.c:1532 sql_help.c:1542 sql_help.c:1544 +#: sql_help.c:1554 sql_help.c:1556 sql_help.c:1566 sql_help.c:1569 +#: sql_help.c:1592 sql_help.c:1594 sql_help.c:1596 sql_help.c:1598 +#: sql_help.c:1601 sql_help.c:1603 sql_help.c:1606 sql_help.c:1609 +#: sql_help.c:1660 sql_help.c:1703 sql_help.c:1706 sql_help.c:1708 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:1715 sql_help.c:1717 +#: sql_help.c:1720 sql_help.c:1770 sql_help.c:1786 sql_help.c:2019 +#: sql_help.c:2088 sql_help.c:2107 sql_help.c:2120 sql_help.c:2178 +#: sql_help.c:2186 sql_help.c:2196 sql_help.c:2224 sql_help.c:2257 +#: sql_help.c:2275 sql_help.c:2303 sql_help.c:2414 sql_help.c:2460 +#: sql_help.c:2485 sql_help.c:2508 sql_help.c:2512 sql_help.c:2546 +#: sql_help.c:2566 sql_help.c:2588 sql_help.c:2602 sql_help.c:2623 +#: sql_help.c:2652 sql_help.c:2685 sql_help.c:2708 sql_help.c:2755 +#: sql_help.c:3053 sql_help.c:3066 sql_help.c:3083 sql_help.c:3099 +#: sql_help.c:3139 sql_help.c:3193 sql_help.c:3197 sql_help.c:3199 +#: sql_help.c:3206 sql_help.c:3225 sql_help.c:3252 sql_help.c:3287 +#: sql_help.c:3299 sql_help.c:3308 sql_help.c:3352 sql_help.c:3366 +#: sql_help.c:3394 sql_help.c:3402 sql_help.c:3414 sql_help.c:3424 +#: sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 sql_help.c:3456 +#: sql_help.c:3465 sql_help.c:3476 sql_help.c:3484 sql_help.c:3492 +#: sql_help.c:3500 sql_help.c:3508 sql_help.c:3518 sql_help.c:3527 +#: sql_help.c:3536 sql_help.c:3544 sql_help.c:3554 sql_help.c:3565 +#: sql_help.c:3573 sql_help.c:3582 sql_help.c:3593 sql_help.c:3602 +#: sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 sql_help.c:3634 +#: sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 sql_help.c:3666 +#: sql_help.c:3674 sql_help.c:3682 sql_help.c:3699 sql_help.c:3708 +#: sql_help.c:3716 sql_help.c:3733 sql_help.c:3748 sql_help.c:4061 +#: sql_help.c:4182 sql_help.c:4211 sql_help.c:4227 sql_help.c:4229 +#: sql_help.c:4733 sql_help.c:4781 sql_help.c:4940 msgid "name" msgstr "nombre" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:330 sql_help.c:1848 -#: sql_help.c:3347 sql_help.c:4468 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:340 sql_help.c:1863 +#: sql_help.c:3367 sql_help.c:4500 msgid "aggregate_signature" msgstr "signatura_func_agregación" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:449 sql_help.c:528 sql_help.c:576 -#: sql_help.c:594 sql_help.c:621 sql_help.c:674 sql_help.c:743 sql_help.c:798 -#: sql_help.c:819 sql_help.c:858 sql_help.c:908 sql_help.c:955 sql_help.c:1008 -#: sql_help.c:1040 sql_help.c:1050 sql_help.c:1085 sql_help.c:1105 -#: sql_help.c:1119 sql_help.c:1169 sql_help.c:1317 sql_help.c:1444 -#: sql_help.c:1487 sql_help.c:1508 sql_help.c:1522 sql_help.c:1534 -#: sql_help.c:1547 sql_help.c:1574 sql_help.c:1640 sql_help.c:1693 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:260 +#: sql_help.c:281 sql_help.c:412 sql_help.c:459 sql_help.c:538 sql_help.c:586 +#: sql_help.c:604 sql_help.c:631 sql_help.c:684 sql_help.c:759 sql_help.c:814 +#: sql_help.c:835 sql_help.c:874 sql_help.c:924 sql_help.c:971 sql_help.c:1024 +#: sql_help.c:1056 sql_help.c:1066 sql_help.c:1101 sql_help.c:1121 +#: sql_help.c:1135 sql_help.c:1185 sql_help.c:1333 sql_help.c:1465 +#: sql_help.c:1508 sql_help.c:1529 sql_help.c:1543 sql_help.c:1555 +#: sql_help.c:1568 sql_help.c:1595 sql_help.c:1661 sql_help.c:1714 msgid "new_name" msgstr "nuevo_nombre" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:251 -#: sql_help.c:269 sql_help.c:400 sql_help.c:485 sql_help.c:533 sql_help.c:623 -#: sql_help.c:632 sql_help.c:697 sql_help.c:717 sql_help.c:746 sql_help.c:801 -#: sql_help.c:863 sql_help.c:906 sql_help.c:1013 sql_help.c:1052 -#: sql_help.c:1083 sql_help.c:1103 sql_help.c:1117 sql_help.c:1167 -#: sql_help.c:1381 sql_help.c:1446 sql_help.c:1489 sql_help.c:1510 -#: sql_help.c:1572 sql_help.c:1688 sql_help.c:3019 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:258 +#: sql_help.c:279 sql_help.c:410 sql_help.c:495 sql_help.c:543 sql_help.c:633 +#: sql_help.c:642 sql_help.c:707 sql_help.c:731 sql_help.c:762 sql_help.c:817 +#: sql_help.c:879 sql_help.c:922 sql_help.c:1029 sql_help.c:1068 +#: sql_help.c:1099 sql_help.c:1119 sql_help.c:1133 sql_help.c:1183 +#: sql_help.c:1399 sql_help.c:1467 sql_help.c:1510 sql_help.c:1531 +#: sql_help.c:1593 sql_help.c:1709 sql_help.c:3039 msgid "new_owner" msgstr "nuevo_dueño" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:255 sql_help.c:322 -#: sql_help.c:451 sql_help.c:538 sql_help.c:676 sql_help.c:721 sql_help.c:749 -#: sql_help.c:804 sql_help.c:868 sql_help.c:1018 sql_help.c:1087 -#: sql_help.c:1121 sql_help.c:1319 sql_help.c:1491 sql_help.c:1512 -#: sql_help.c:1524 sql_help.c:1536 sql_help.c:1576 sql_help.c:1695 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:262 sql_help.c:332 +#: sql_help.c:461 sql_help.c:548 sql_help.c:686 sql_help.c:735 sql_help.c:765 +#: sql_help.c:820 sql_help.c:884 sql_help.c:1034 sql_help.c:1103 +#: sql_help.c:1137 sql_help.c:1335 sql_help.c:1512 sql_help.c:1533 +#: sql_help.c:1545 sql_help.c:1557 sql_help.c:1597 sql_help.c:1716 msgid "new_schema" msgstr "nuevo_esquema" -#: sql_help.c:44 sql_help.c:1912 sql_help.c:3348 sql_help.c:4497 +#: sql_help.c:44 sql_help.c:1927 sql_help.c:3368 sql_help.c:4529 msgid "where aggregate_signature is:" msgstr "donde signatura_func_agregación es:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:340 sql_help.c:353 -#: sql_help.c:357 sql_help.c:373 sql_help.c:376 sql_help.c:379 sql_help.c:520 -#: sql_help.c:525 sql_help.c:530 sql_help.c:535 sql_help.c:540 sql_help.c:850 -#: sql_help.c:855 sql_help.c:860 sql_help.c:865 sql_help.c:870 sql_help.c:1000 -#: sql_help.c:1005 sql_help.c:1010 sql_help.c:1015 sql_help.c:1020 -#: sql_help.c:1866 sql_help.c:1883 sql_help.c:1889 sql_help.c:1913 -#: sql_help.c:1916 sql_help.c:1919 sql_help.c:2070 sql_help.c:2089 -#: sql_help.c:2092 sql_help.c:2394 sql_help.c:2603 sql_help.c:3349 -#: sql_help.c:3352 sql_help.c:3355 sql_help.c:3446 sql_help.c:3535 -#: sql_help.c:3563 sql_help.c:3915 sql_help.c:4367 sql_help.c:4474 -#: sql_help.c:4481 sql_help.c:4487 sql_help.c:4498 sql_help.c:4501 -#: sql_help.c:4504 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:350 sql_help.c:363 +#: sql_help.c:367 sql_help.c:383 sql_help.c:386 sql_help.c:389 sql_help.c:530 +#: sql_help.c:535 sql_help.c:540 sql_help.c:545 sql_help.c:550 sql_help.c:866 +#: sql_help.c:871 sql_help.c:876 sql_help.c:881 sql_help.c:886 sql_help.c:1016 +#: sql_help.c:1021 sql_help.c:1026 sql_help.c:1031 sql_help.c:1036 +#: sql_help.c:1881 sql_help.c:1898 sql_help.c:1904 sql_help.c:1928 +#: sql_help.c:1931 sql_help.c:1934 sql_help.c:2089 sql_help.c:2108 +#: sql_help.c:2111 sql_help.c:2415 sql_help.c:2624 sql_help.c:3369 +#: sql_help.c:3372 sql_help.c:3375 sql_help.c:3466 sql_help.c:3555 +#: sql_help.c:3583 sql_help.c:3936 sql_help.c:4399 sql_help.c:4506 +#: sql_help.c:4513 sql_help.c:4519 sql_help.c:4530 sql_help.c:4533 +#: sql_help.c:4536 msgid "argmode" msgstr "modo_arg" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:341 sql_help.c:354 -#: sql_help.c:358 sql_help.c:374 sql_help.c:377 sql_help.c:380 sql_help.c:521 -#: sql_help.c:526 sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:851 -#: sql_help.c:856 sql_help.c:861 sql_help.c:866 sql_help.c:871 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1867 sql_help.c:1884 sql_help.c:1890 sql_help.c:1914 -#: sql_help.c:1917 sql_help.c:1920 sql_help.c:2071 sql_help.c:2090 -#: sql_help.c:2093 sql_help.c:2395 sql_help.c:2604 sql_help.c:3350 -#: sql_help.c:3353 sql_help.c:3356 sql_help.c:3447 sql_help.c:3536 -#: sql_help.c:3564 sql_help.c:4475 sql_help.c:4482 sql_help.c:4488 -#: sql_help.c:4499 sql_help.c:4502 sql_help.c:4505 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:351 sql_help.c:364 +#: sql_help.c:368 sql_help.c:384 sql_help.c:387 sql_help.c:390 sql_help.c:531 +#: sql_help.c:536 sql_help.c:541 sql_help.c:546 sql_help.c:551 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:882 sql_help.c:887 sql_help.c:1017 +#: sql_help.c:1022 sql_help.c:1027 sql_help.c:1032 sql_help.c:1037 +#: sql_help.c:1882 sql_help.c:1899 sql_help.c:1905 sql_help.c:1929 +#: sql_help.c:1932 sql_help.c:1935 sql_help.c:2090 sql_help.c:2109 +#: sql_help.c:2112 sql_help.c:2416 sql_help.c:2625 sql_help.c:3370 +#: sql_help.c:3373 sql_help.c:3376 sql_help.c:3467 sql_help.c:3556 +#: sql_help.c:3584 sql_help.c:4507 sql_help.c:4514 sql_help.c:4520 +#: sql_help.c:4531 sql_help.c:4534 sql_help.c:4537 msgid "argname" msgstr "nombre_arg" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1868 sql_help.c:1885 sql_help.c:1891 sql_help.c:1915 -#: sql_help.c:1918 sql_help.c:1921 sql_help.c:2396 sql_help.c:2605 -#: sql_help.c:3351 sql_help.c:3354 sql_help.c:3357 sql_help.c:3448 -#: sql_help.c:3537 sql_help.c:3565 sql_help.c:4476 sql_help.c:4483 -#: sql_help.c:4489 sql_help.c:4500 sql_help.c:4503 sql_help.c:4506 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:352 sql_help.c:365 +#: sql_help.c:369 sql_help.c:385 sql_help.c:388 sql_help.c:391 sql_help.c:532 +#: sql_help.c:537 sql_help.c:542 sql_help.c:547 sql_help.c:552 sql_help.c:868 +#: sql_help.c:873 sql_help.c:878 sql_help.c:883 sql_help.c:888 sql_help.c:1018 +#: sql_help.c:1023 sql_help.c:1028 sql_help.c:1033 sql_help.c:1038 +#: sql_help.c:1883 sql_help.c:1900 sql_help.c:1906 sql_help.c:1930 +#: sql_help.c:1933 sql_help.c:1936 sql_help.c:2417 sql_help.c:2626 +#: sql_help.c:3371 sql_help.c:3374 sql_help.c:3377 sql_help.c:3468 +#: sql_help.c:3557 sql_help.c:3585 sql_help.c:4508 sql_help.c:4515 +#: sql_help.c:4521 sql_help.c:4532 sql_help.c:4535 sql_help.c:4538 msgid "argtype" msgstr "tipo_arg" -#: sql_help.c:114 sql_help.c:397 sql_help.c:474 sql_help.c:486 sql_help.c:949 -#: sql_help.c:1100 sql_help.c:1505 sql_help.c:1634 sql_help.c:1666 -#: sql_help.c:1719 sql_help.c:1783 sql_help.c:1970 sql_help.c:1977 -#: sql_help.c:2285 sql_help.c:2335 sql_help.c:2342 sql_help.c:2351 -#: sql_help.c:2440 sql_help.c:2667 sql_help.c:2760 sql_help.c:3048 -#: sql_help.c:3233 sql_help.c:3255 sql_help.c:3395 sql_help.c:3751 -#: sql_help.c:3959 sql_help.c:4194 sql_help.c:4196 sql_help.c:4973 +#: sql_help.c:114 sql_help.c:407 sql_help.c:484 sql_help.c:496 sql_help.c:965 +#: sql_help.c:1116 sql_help.c:1526 sql_help.c:1655 sql_help.c:1687 +#: sql_help.c:1739 sql_help.c:1798 sql_help.c:1987 sql_help.c:1994 +#: sql_help.c:2306 sql_help.c:2356 sql_help.c:2363 sql_help.c:2372 +#: sql_help.c:2461 sql_help.c:2686 sql_help.c:2777 sql_help.c:3068 +#: sql_help.c:3253 sql_help.c:3275 sql_help.c:3415 sql_help.c:3772 +#: sql_help.c:3980 sql_help.c:4226 sql_help.c:4228 sql_help.c:5006 msgid "option" msgstr "opción" -#: sql_help.c:115 sql_help.c:950 sql_help.c:1635 sql_help.c:2441 -#: sql_help.c:2668 sql_help.c:3234 sql_help.c:3396 +#: sql_help.c:115 sql_help.c:966 sql_help.c:1656 sql_help.c:2462 +#: sql_help.c:2687 sql_help.c:3254 sql_help.c:3416 msgid "where option can be:" msgstr "donde opción puede ser:" -#: sql_help.c:116 sql_help.c:2217 +#: sql_help.c:116 sql_help.c:2238 msgid "allowconn" msgstr "allowconn" -#: sql_help.c:117 sql_help.c:951 sql_help.c:1636 sql_help.c:2218 -#: sql_help.c:2442 sql_help.c:2669 sql_help.c:3235 +#: sql_help.c:117 sql_help.c:967 sql_help.c:1657 sql_help.c:2239 +#: sql_help.c:2463 sql_help.c:2688 sql_help.c:3255 msgid "connlimit" msgstr "límite_conexiones" -#: sql_help.c:118 sql_help.c:2219 +#: sql_help.c:118 sql_help.c:2240 msgid "istemplate" msgstr "esplantilla" -#: sql_help.c:124 sql_help.c:611 sql_help.c:679 sql_help.c:693 sql_help.c:1322 -#: sql_help.c:1374 sql_help.c:4200 +#: sql_help.c:124 sql_help.c:621 sql_help.c:689 sql_help.c:703 sql_help.c:1338 +#: sql_help.c:1392 sql_help.c:4232 msgid "new_tablespace" msgstr "nuevo_tablespace" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:548 sql_help.c:550 -#: sql_help.c:551 sql_help.c:875 sql_help.c:877 sql_help.c:878 sql_help.c:958 -#: sql_help.c:962 sql_help.c:965 sql_help.c:1027 sql_help.c:1029 -#: sql_help.c:1030 sql_help.c:1180 sql_help.c:1183 sql_help.c:1643 -#: sql_help.c:1647 sql_help.c:1650 sql_help.c:2406 sql_help.c:2609 -#: sql_help.c:3927 sql_help.c:4218 sql_help.c:4379 sql_help.c:4688 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:558 sql_help.c:560 +#: sql_help.c:561 sql_help.c:891 sql_help.c:893 sql_help.c:894 sql_help.c:974 +#: sql_help.c:978 sql_help.c:981 sql_help.c:1043 sql_help.c:1045 +#: sql_help.c:1046 sql_help.c:1196 sql_help.c:1198 sql_help.c:1664 +#: sql_help.c:1668 sql_help.c:1671 sql_help.c:2427 sql_help.c:2630 +#: sql_help.c:3948 sql_help.c:4250 sql_help.c:4411 sql_help.c:4721 msgid "configuration_parameter" msgstr "parámetro_de_configuración" -#: sql_help.c:128 sql_help.c:398 sql_help.c:469 sql_help.c:475 sql_help.c:487 -#: sql_help.c:549 sql_help.c:603 sql_help.c:685 sql_help.c:695 sql_help.c:876 -#: sql_help.c:904 sql_help.c:959 sql_help.c:1028 sql_help.c:1101 -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:1157 -#: sql_help.c:1162 sql_help.c:1165 sql_help.c:1181 sql_help.c:1182 -#: sql_help.c:1353 sql_help.c:1376 sql_help.c:1424 sql_help.c:1449 -#: sql_help.c:1506 sql_help.c:1590 sql_help.c:1644 sql_help.c:1667 -#: sql_help.c:2286 sql_help.c:2336 sql_help.c:2343 sql_help.c:2352 -#: sql_help.c:2407 sql_help.c:2408 sql_help.c:2472 sql_help.c:2475 -#: sql_help.c:2509 sql_help.c:2610 sql_help.c:2611 sql_help.c:2634 -#: sql_help.c:2761 sql_help.c:2800 sql_help.c:2910 sql_help.c:2923 -#: sql_help.c:2937 sql_help.c:2978 sql_help.c:3005 sql_help.c:3022 -#: sql_help.c:3049 sql_help.c:3256 sql_help.c:3960 sql_help.c:4689 -#: sql_help.c:4690 sql_help.c:4691 sql_help.c:4692 +#: sql_help.c:128 sql_help.c:408 sql_help.c:479 sql_help.c:485 sql_help.c:497 +#: sql_help.c:559 sql_help.c:613 sql_help.c:695 sql_help.c:705 sql_help.c:892 +#: sql_help.c:920 sql_help.c:975 sql_help.c:1044 sql_help.c:1117 +#: sql_help.c:1162 sql_help.c:1166 sql_help.c:1170 sql_help.c:1173 +#: sql_help.c:1178 sql_help.c:1181 sql_help.c:1197 sql_help.c:1371 +#: sql_help.c:1394 sql_help.c:1442 sql_help.c:1450 sql_help.c:1470 +#: sql_help.c:1527 sql_help.c:1611 sql_help.c:1665 sql_help.c:1688 +#: sql_help.c:2307 sql_help.c:2357 sql_help.c:2364 sql_help.c:2373 +#: sql_help.c:2428 sql_help.c:2429 sql_help.c:2493 sql_help.c:2496 +#: sql_help.c:2530 sql_help.c:2631 sql_help.c:2632 sql_help.c:2655 +#: sql_help.c:2778 sql_help.c:2817 sql_help.c:2927 sql_help.c:2940 +#: sql_help.c:2954 sql_help.c:2995 sql_help.c:3003 sql_help.c:3025 +#: sql_help.c:3042 sql_help.c:3069 sql_help.c:3276 sql_help.c:3981 +#: sql_help.c:4722 sql_help.c:4723 sql_help.c:4724 sql_help.c:4725 msgid "value" msgstr "valor" -#: sql_help.c:200 +#: sql_help.c:202 msgid "target_role" msgstr "rol_destino" -#: sql_help.c:201 sql_help.c:913 sql_help.c:2270 sql_help.c:2639 -#: sql_help.c:2716 sql_help.c:2721 sql_help.c:3890 sql_help.c:3899 -#: sql_help.c:3918 sql_help.c:3930 sql_help.c:4342 sql_help.c:4351 -#: sql_help.c:4370 sql_help.c:4382 +#: sql_help.c:203 sql_help.c:929 sql_help.c:2291 sql_help.c:2660 +#: sql_help.c:2733 sql_help.c:2738 sql_help.c:3911 sql_help.c:3920 +#: sql_help.c:3939 sql_help.c:3951 sql_help.c:4374 sql_help.c:4383 +#: sql_help.c:4402 sql_help.c:4414 msgid "schema_name" msgstr "nombre_de_esquema" -#: sql_help.c:202 +#: sql_help.c:204 msgid "abbreviated_grant_or_revoke" msgstr "grant_o_revoke_abreviado" -#: sql_help.c:203 +#: sql_help.c:205 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "donde grant_o_revoke_abreviado es uno de:" -#: sql_help.c:204 sql_help.c:205 sql_help.c:206 sql_help.c:207 sql_help.c:208 -#: sql_help.c:209 sql_help.c:210 sql_help.c:211 sql_help.c:212 sql_help.c:213 -#: sql_help.c:574 sql_help.c:610 sql_help.c:678 sql_help.c:822 sql_help.c:969 -#: sql_help.c:1321 sql_help.c:1654 sql_help.c:2445 sql_help.c:2446 -#: sql_help.c:2447 sql_help.c:2448 sql_help.c:2449 sql_help.c:2583 -#: sql_help.c:2672 sql_help.c:2673 sql_help.c:2674 sql_help.c:2675 -#: sql_help.c:2676 sql_help.c:3238 sql_help.c:3239 sql_help.c:3240 -#: sql_help.c:3241 sql_help.c:3242 sql_help.c:3939 sql_help.c:3943 -#: sql_help.c:4391 sql_help.c:4395 sql_help.c:4710 +#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 +#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 +#: sql_help.c:584 sql_help.c:620 sql_help.c:688 sql_help.c:838 sql_help.c:985 +#: sql_help.c:1337 sql_help.c:1675 sql_help.c:2466 sql_help.c:2467 +#: sql_help.c:2468 sql_help.c:2469 sql_help.c:2470 sql_help.c:2604 +#: sql_help.c:2691 sql_help.c:2692 sql_help.c:2693 sql_help.c:3258 +#: sql_help.c:3259 sql_help.c:3260 sql_help.c:3261 sql_help.c:3262 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:4423 sql_help.c:4427 +#: sql_help.c:4743 msgid "role_name" msgstr "nombre_de_rol" -#: sql_help.c:239 sql_help.c:462 sql_help.c:912 sql_help.c:1337 sql_help.c:1339 -#: sql_help.c:1391 sql_help.c:1403 sql_help.c:1428 sql_help.c:1684 -#: sql_help.c:2239 sql_help.c:2243 sql_help.c:2355 sql_help.c:2360 -#: sql_help.c:2468 sql_help.c:2638 sql_help.c:2777 sql_help.c:2782 -#: sql_help.c:2784 sql_help.c:2905 sql_help.c:2918 sql_help.c:2932 -#: sql_help.c:2941 sql_help.c:2953 sql_help.c:2982 sql_help.c:3991 -#: sql_help.c:4006 sql_help.c:4008 sql_help.c:4095 sql_help.c:4098 -#: sql_help.c:4100 sql_help.c:4561 sql_help.c:4562 sql_help.c:4571 -#: sql_help.c:4618 sql_help.c:4619 sql_help.c:4620 sql_help.c:4621 -#: sql_help.c:4622 sql_help.c:4623 sql_help.c:4663 sql_help.c:4664 -#: sql_help.c:4669 sql_help.c:4674 sql_help.c:4818 sql_help.c:4819 -#: sql_help.c:4828 sql_help.c:4875 sql_help.c:4876 sql_help.c:4877 -#: sql_help.c:4878 sql_help.c:4879 sql_help.c:4880 sql_help.c:4934 -#: sql_help.c:4936 sql_help.c:5004 sql_help.c:5064 sql_help.c:5065 -#: sql_help.c:5074 sql_help.c:5121 sql_help.c:5122 sql_help.c:5123 -#: sql_help.c:5124 sql_help.c:5125 sql_help.c:5126 +#: sql_help.c:246 sql_help.c:265 sql_help.c:472 sql_help.c:928 sql_help.c:1353 +#: sql_help.c:1355 sql_help.c:1359 sql_help.c:1409 sql_help.c:1421 +#: sql_help.c:1446 sql_help.c:1705 sql_help.c:2260 sql_help.c:2264 +#: sql_help.c:2376 sql_help.c:2381 sql_help.c:2489 sql_help.c:2659 +#: sql_help.c:2794 sql_help.c:2799 sql_help.c:2801 sql_help.c:2922 +#: sql_help.c:2935 sql_help.c:2949 sql_help.c:2958 sql_help.c:2970 +#: sql_help.c:2999 sql_help.c:4012 sql_help.c:4027 sql_help.c:4029 +#: sql_help.c:4125 sql_help.c:4128 sql_help.c:4130 sql_help.c:4593 +#: sql_help.c:4594 sql_help.c:4603 sql_help.c:4650 sql_help.c:4651 +#: sql_help.c:4652 sql_help.c:4653 sql_help.c:4654 sql_help.c:4655 +#: sql_help.c:4696 sql_help.c:4697 sql_help.c:4702 sql_help.c:4707 +#: sql_help.c:4851 sql_help.c:4852 sql_help.c:4861 sql_help.c:4908 +#: sql_help.c:4909 sql_help.c:4910 sql_help.c:4911 sql_help.c:4912 +#: sql_help.c:4913 sql_help.c:4968 sql_help.c:4970 sql_help.c:5036 +#: sql_help.c:5096 sql_help.c:5097 sql_help.c:5106 sql_help.c:5153 +#: sql_help.c:5154 sql_help.c:5155 sql_help.c:5156 sql_help.c:5157 +#: sql_help.c:5158 msgid "expression" msgstr "expresión" -#: sql_help.c:242 +#: sql_help.c:249 sql_help.c:2261 msgid "domain_constraint" msgstr "restricción_de_dominio" -#: sql_help.c:244 sql_help.c:246 sql_help.c:249 sql_help.c:477 sql_help.c:478 -#: sql_help.c:1314 sql_help.c:1361 sql_help.c:1362 sql_help.c:1363 -#: sql_help.c:1390 sql_help.c:1402 sql_help.c:1419 sql_help.c:1854 -#: sql_help.c:1856 sql_help.c:2242 sql_help.c:2354 sql_help.c:2359 -#: sql_help.c:2940 sql_help.c:2952 sql_help.c:4003 +#: sql_help.c:251 sql_help.c:253 sql_help.c:256 sql_help.c:264 sql_help.c:487 +#: sql_help.c:488 sql_help.c:1330 sql_help.c:1379 sql_help.c:1380 +#: sql_help.c:1381 sql_help.c:1408 sql_help.c:1420 sql_help.c:1437 +#: sql_help.c:1869 sql_help.c:1871 sql_help.c:2263 sql_help.c:2375 +#: sql_help.c:2380 sql_help.c:2957 sql_help.c:2969 sql_help.c:4024 msgid "constraint_name" msgstr "nombre_restricción" -#: sql_help.c:247 sql_help.c:1315 +#: sql_help.c:254 sql_help.c:1331 msgid "new_constraint_name" msgstr "nuevo_nombre_restricción" -#: sql_help.c:320 sql_help.c:1099 +#: sql_help.c:263 sql_help.c:2262 +msgid "where domain_constraint is:" +msgstr "donde restricción_de_dominio es:" + +#: sql_help.c:330 sql_help.c:1115 msgid "new_version" msgstr "nueva_versión" -#: sql_help.c:324 sql_help.c:326 +#: sql_help.c:334 sql_help.c:336 msgid "member_object" msgstr "objeto_miembro" -#: sql_help.c:327 +#: sql_help.c:337 msgid "where member_object is:" msgstr "dondo objeto_miembro es:" -#: sql_help.c:328 sql_help.c:333 sql_help.c:334 sql_help.c:335 sql_help.c:336 -#: sql_help.c:337 sql_help.c:338 sql_help.c:343 sql_help.c:347 sql_help.c:349 -#: sql_help.c:351 sql_help.c:360 sql_help.c:361 sql_help.c:362 sql_help.c:363 -#: sql_help.c:364 sql_help.c:365 sql_help.c:366 sql_help.c:367 sql_help.c:370 -#: sql_help.c:371 sql_help.c:1846 sql_help.c:1851 sql_help.c:1858 -#: sql_help.c:1859 sql_help.c:1860 sql_help.c:1861 sql_help.c:1862 -#: sql_help.c:1863 sql_help.c:1864 sql_help.c:1869 sql_help.c:1871 -#: sql_help.c:1875 sql_help.c:1877 sql_help.c:1881 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1894 sql_help.c:1895 sql_help.c:1896 -#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 -#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 sql_help.c:1904 -#: sql_help.c:1909 sql_help.c:1910 sql_help.c:4464 sql_help.c:4469 -#: sql_help.c:4470 sql_help.c:4471 sql_help.c:4472 sql_help.c:4478 -#: sql_help.c:4479 sql_help.c:4484 sql_help.c:4485 sql_help.c:4490 -#: sql_help.c:4491 sql_help.c:4492 sql_help.c:4493 sql_help.c:4494 -#: sql_help.c:4495 +#: sql_help.c:338 sql_help.c:343 sql_help.c:344 sql_help.c:345 sql_help.c:346 +#: sql_help.c:347 sql_help.c:348 sql_help.c:353 sql_help.c:357 sql_help.c:359 +#: sql_help.c:361 sql_help.c:370 sql_help.c:371 sql_help.c:372 sql_help.c:373 +#: sql_help.c:374 sql_help.c:375 sql_help.c:376 sql_help.c:377 sql_help.c:380 +#: sql_help.c:381 sql_help.c:1861 sql_help.c:1866 sql_help.c:1873 +#: sql_help.c:1874 sql_help.c:1875 sql_help.c:1876 sql_help.c:1877 +#: sql_help.c:1878 sql_help.c:1879 sql_help.c:1884 sql_help.c:1886 +#: sql_help.c:1890 sql_help.c:1892 sql_help.c:1896 sql_help.c:1901 +#: sql_help.c:1902 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1912 sql_help.c:1913 sql_help.c:1914 sql_help.c:1915 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:1918 sql_help.c:1919 +#: sql_help.c:1924 sql_help.c:1925 sql_help.c:4496 sql_help.c:4501 +#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4510 +#: sql_help.c:4511 sql_help.c:4516 sql_help.c:4517 sql_help.c:4522 +#: sql_help.c:4523 sql_help.c:4524 sql_help.c:4525 sql_help.c:4526 +#: sql_help.c:4527 msgid "object_name" msgstr "nombre_de_objeto" -#: sql_help.c:329 sql_help.c:1847 sql_help.c:4467 +#: sql_help.c:339 sql_help.c:1862 sql_help.c:4499 msgid "aggregate_name" msgstr "nombre_función_agregación" -#: sql_help.c:331 sql_help.c:1849 sql_help.c:2135 sql_help.c:2139 -#: sql_help.c:2141 sql_help.c:3365 +#: sql_help.c:341 sql_help.c:1864 sql_help.c:2154 sql_help.c:2158 +#: sql_help.c:2160 sql_help.c:3385 msgid "source_type" msgstr "tipo_fuente" -#: sql_help.c:332 sql_help.c:1850 sql_help.c:2136 sql_help.c:2140 -#: sql_help.c:2142 sql_help.c:3366 +#: sql_help.c:342 sql_help.c:1865 sql_help.c:2155 sql_help.c:2159 +#: sql_help.c:2161 sql_help.c:3386 msgid "target_type" msgstr "tipo_destino" -#: sql_help.c:339 sql_help.c:786 sql_help.c:1865 sql_help.c:2137 -#: sql_help.c:2180 sql_help.c:2258 sql_help.c:2526 sql_help.c:2557 -#: sql_help.c:3125 sql_help.c:4366 sql_help.c:4473 sql_help.c:4590 -#: sql_help.c:4594 sql_help.c:4598 sql_help.c:4601 sql_help.c:4847 -#: sql_help.c:4851 sql_help.c:4855 sql_help.c:4858 sql_help.c:5093 -#: sql_help.c:5097 sql_help.c:5101 sql_help.c:5104 +#: sql_help.c:349 sql_help.c:802 sql_help.c:1880 sql_help.c:2156 +#: sql_help.c:2199 sql_help.c:2279 sql_help.c:2547 sql_help.c:2578 +#: sql_help.c:3145 sql_help.c:4398 sql_help.c:4505 sql_help.c:4622 +#: sql_help.c:4626 sql_help.c:4630 sql_help.c:4633 sql_help.c:4880 +#: sql_help.c:4884 sql_help.c:4888 sql_help.c:4891 sql_help.c:5125 +#: sql_help.c:5129 sql_help.c:5133 sql_help.c:5136 msgid "function_name" msgstr "nombre_de_función" -#: sql_help.c:344 sql_help.c:779 sql_help.c:1872 sql_help.c:2550 +#: sql_help.c:354 sql_help.c:795 sql_help.c:1887 sql_help.c:2571 msgid "operator_name" msgstr "nombre_operador" -#: sql_help.c:345 sql_help.c:715 sql_help.c:719 sql_help.c:723 sql_help.c:1873 -#: sql_help.c:2527 sql_help.c:3489 +#: sql_help.c:355 sql_help.c:729 sql_help.c:733 sql_help.c:737 sql_help.c:1888 +#: sql_help.c:2548 sql_help.c:3509 msgid "left_type" msgstr "tipo_izq" -#: sql_help.c:346 sql_help.c:716 sql_help.c:720 sql_help.c:724 sql_help.c:1874 -#: sql_help.c:2528 sql_help.c:3490 +#: sql_help.c:356 sql_help.c:730 sql_help.c:734 sql_help.c:738 sql_help.c:1889 +#: sql_help.c:2549 sql_help.c:3510 msgid "right_type" msgstr "tipo_der" -#: sql_help.c:348 sql_help.c:350 sql_help.c:742 sql_help.c:745 sql_help.c:748 -#: sql_help.c:777 sql_help.c:789 sql_help.c:797 sql_help.c:800 sql_help.c:803 -#: sql_help.c:1408 sql_help.c:1876 sql_help.c:1878 sql_help.c:2547 -#: sql_help.c:2568 sql_help.c:2958 sql_help.c:3499 sql_help.c:3508 +#: sql_help.c:358 sql_help.c:360 sql_help.c:758 sql_help.c:761 sql_help.c:764 +#: sql_help.c:793 sql_help.c:805 sql_help.c:813 sql_help.c:816 sql_help.c:819 +#: sql_help.c:1426 sql_help.c:1891 sql_help.c:1893 sql_help.c:2568 +#: sql_help.c:2589 sql_help.c:2975 sql_help.c:3519 sql_help.c:3528 msgid "index_method" msgstr "método_de_índice" -#: sql_help.c:352 sql_help.c:1882 sql_help.c:4480 +#: sql_help.c:362 sql_help.c:1897 sql_help.c:4512 msgid "procedure_name" msgstr "nombre_de_procedimiento" -#: sql_help.c:356 sql_help.c:1888 sql_help.c:3914 sql_help.c:4486 +#: sql_help.c:366 sql_help.c:1903 sql_help.c:3935 sql_help.c:4518 msgid "routine_name" msgstr "nombre_de_rutina" -#: sql_help.c:368 sql_help.c:1380 sql_help.c:1905 sql_help.c:2402 -#: sql_help.c:2608 sql_help.c:2913 sql_help.c:3092 sql_help.c:3670 -#: sql_help.c:3936 sql_help.c:4388 +#: sql_help.c:378 sql_help.c:1398 sql_help.c:1920 sql_help.c:2423 +#: sql_help.c:2629 sql_help.c:2930 sql_help.c:3112 sql_help.c:3690 +#: sql_help.c:3957 sql_help.c:4420 msgid "type_name" msgstr "nombre_de_tipo" -#: sql_help.c:369 sql_help.c:1906 sql_help.c:2401 sql_help.c:2607 -#: sql_help.c:3093 sql_help.c:3323 sql_help.c:3671 sql_help.c:3921 -#: sql_help.c:4373 +#: sql_help.c:379 sql_help.c:1921 sql_help.c:2422 sql_help.c:2628 +#: sql_help.c:3113 sql_help.c:3343 sql_help.c:3691 sql_help.c:3942 +#: sql_help.c:4405 msgid "lang_name" msgstr "nombre_lenguaje" -#: sql_help.c:372 +#: sql_help.c:382 msgid "and aggregate_signature is:" msgstr "y signatura_func_agregación es:" -#: sql_help.c:395 sql_help.c:2002 sql_help.c:2283 +#: sql_help.c:405 sql_help.c:2021 sql_help.c:2304 msgid "handler_function" msgstr "función_manejadora" -#: sql_help.c:396 sql_help.c:2284 +#: sql_help.c:406 sql_help.c:2305 msgid "validator_function" msgstr "función_validadora" -#: sql_help.c:444 sql_help.c:523 sql_help.c:667 sql_help.c:853 sql_help.c:1003 -#: sql_help.c:1309 sql_help.c:1581 +#: sql_help.c:454 sql_help.c:533 sql_help.c:677 sql_help.c:869 sql_help.c:1019 +#: sql_help.c:1325 sql_help.c:1602 msgid "action" msgstr "acción" -#: sql_help.c:446 sql_help.c:453 sql_help.c:457 sql_help.c:458 sql_help.c:461 -#: sql_help.c:463 sql_help.c:464 sql_help.c:465 sql_help.c:467 sql_help.c:470 -#: sql_help.c:472 sql_help.c:473 sql_help.c:671 sql_help.c:681 sql_help.c:683 -#: sql_help.c:686 sql_help.c:688 sql_help.c:689 sql_help.c:911 sql_help.c:1080 -#: sql_help.c:1311 sql_help.c:1329 sql_help.c:1333 sql_help.c:1334 -#: sql_help.c:1338 sql_help.c:1340 sql_help.c:1341 sql_help.c:1342 -#: sql_help.c:1343 sql_help.c:1345 sql_help.c:1348 sql_help.c:1349 -#: sql_help.c:1351 sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 -#: sql_help.c:1404 sql_help.c:1406 sql_help.c:1413 sql_help.c:1422 -#: sql_help.c:1427 sql_help.c:1431 sql_help.c:1432 sql_help.c:1683 -#: sql_help.c:1686 sql_help.c:1690 sql_help.c:1728 sql_help.c:1853 -#: sql_help.c:1967 sql_help.c:1973 sql_help.c:1987 sql_help.c:1988 -#: sql_help.c:1989 sql_help.c:2333 sql_help.c:2346 sql_help.c:2399 -#: sql_help.c:2467 sql_help.c:2473 sql_help.c:2506 sql_help.c:2637 -#: sql_help.c:2746 sql_help.c:2781 sql_help.c:2783 sql_help.c:2895 -#: sql_help.c:2904 sql_help.c:2914 sql_help.c:2917 sql_help.c:2927 -#: sql_help.c:2931 sql_help.c:2954 sql_help.c:2956 sql_help.c:2963 -#: sql_help.c:2976 sql_help.c:2981 sql_help.c:2985 sql_help.c:2986 -#: sql_help.c:3002 sql_help.c:3128 sql_help.c:3268 sql_help.c:3893 -#: sql_help.c:3894 sql_help.c:3990 sql_help.c:4005 sql_help.c:4007 -#: sql_help.c:4009 sql_help.c:4094 sql_help.c:4097 sql_help.c:4099 -#: sql_help.c:4345 sql_help.c:4346 sql_help.c:4466 sql_help.c:4627 -#: sql_help.c:4633 sql_help.c:4635 sql_help.c:4884 sql_help.c:4890 -#: sql_help.c:4892 sql_help.c:4933 sql_help.c:4935 sql_help.c:4937 -#: sql_help.c:4992 sql_help.c:5130 sql_help.c:5136 sql_help.c:5138 +#: sql_help.c:456 sql_help.c:463 sql_help.c:467 sql_help.c:468 sql_help.c:471 +#: sql_help.c:473 sql_help.c:474 sql_help.c:475 sql_help.c:477 sql_help.c:480 +#: sql_help.c:482 sql_help.c:483 sql_help.c:681 sql_help.c:691 sql_help.c:693 +#: sql_help.c:696 sql_help.c:698 sql_help.c:699 sql_help.c:927 sql_help.c:1096 +#: sql_help.c:1327 sql_help.c:1345 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 sql_help.c:1358 +#: sql_help.c:1360 sql_help.c:1361 sql_help.c:1363 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1369 sql_help.c:1372 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1422 sql_help.c:1424 sql_help.c:1431 +#: sql_help.c:1440 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1704 sql_help.c:1707 sql_help.c:1711 sql_help.c:1747 +#: sql_help.c:1868 sql_help.c:1984 sql_help.c:1990 sql_help.c:2004 +#: sql_help.c:2005 sql_help.c:2006 sql_help.c:2354 sql_help.c:2367 +#: sql_help.c:2420 sql_help.c:2488 sql_help.c:2494 sql_help.c:2527 +#: sql_help.c:2658 sql_help.c:2763 sql_help.c:2798 sql_help.c:2800 +#: sql_help.c:2912 sql_help.c:2921 sql_help.c:2931 sql_help.c:2934 +#: sql_help.c:2944 sql_help.c:2948 sql_help.c:2971 sql_help.c:2973 +#: sql_help.c:2980 sql_help.c:2993 sql_help.c:2998 sql_help.c:3005 +#: sql_help.c:3006 sql_help.c:3022 sql_help.c:3148 sql_help.c:3288 +#: sql_help.c:3914 sql_help.c:3915 sql_help.c:4011 sql_help.c:4026 +#: sql_help.c:4028 sql_help.c:4030 sql_help.c:4124 sql_help.c:4127 +#: sql_help.c:4129 sql_help.c:4131 sql_help.c:4377 sql_help.c:4378 +#: sql_help.c:4498 sql_help.c:4659 sql_help.c:4666 sql_help.c:4668 +#: sql_help.c:4917 sql_help.c:4924 sql_help.c:4926 sql_help.c:4967 +#: sql_help.c:4969 sql_help.c:4971 sql_help.c:5024 sql_help.c:5162 +#: sql_help.c:5169 sql_help.c:5171 msgid "column_name" msgstr "nombre_de_columna" -#: sql_help.c:447 sql_help.c:672 sql_help.c:1312 sql_help.c:1691 +#: sql_help.c:457 sql_help.c:682 sql_help.c:1328 sql_help.c:1712 msgid "new_column_name" msgstr "nuevo_nombre_de_columna" -#: sql_help.c:452 sql_help.c:544 sql_help.c:680 sql_help.c:874 sql_help.c:1024 -#: sql_help.c:1328 sql_help.c:1591 +#: sql_help.c:462 sql_help.c:554 sql_help.c:690 sql_help.c:890 sql_help.c:1040 +#: sql_help.c:1344 sql_help.c:1612 msgid "where action is one of:" msgstr "donde acción es una de:" -#: sql_help.c:454 sql_help.c:459 sql_help.c:1072 sql_help.c:1330 -#: sql_help.c:1335 sql_help.c:1593 sql_help.c:1597 sql_help.c:2237 -#: sql_help.c:2334 sql_help.c:2546 sql_help.c:2739 sql_help.c:2896 -#: sql_help.c:3175 sql_help.c:4151 +#: sql_help.c:464 sql_help.c:469 sql_help.c:1088 sql_help.c:1346 +#: sql_help.c:1351 sql_help.c:1614 sql_help.c:1618 sql_help.c:2258 +#: sql_help.c:2355 sql_help.c:2567 sql_help.c:2756 sql_help.c:2913 +#: sql_help.c:3195 sql_help.c:4183 msgid "data_type" msgstr "tipo_de_dato" -#: sql_help.c:455 sql_help.c:460 sql_help.c:1331 sql_help.c:1336 -#: sql_help.c:1594 sql_help.c:1598 sql_help.c:2238 sql_help.c:2337 -#: sql_help.c:2469 sql_help.c:2898 sql_help.c:2906 sql_help.c:2919 -#: sql_help.c:2933 sql_help.c:3176 sql_help.c:3182 sql_help.c:4000 +#: sql_help.c:465 sql_help.c:470 sql_help.c:1347 sql_help.c:1352 +#: sql_help.c:1447 sql_help.c:1615 sql_help.c:1619 sql_help.c:2259 +#: sql_help.c:2358 sql_help.c:2490 sql_help.c:2915 sql_help.c:2923 +#: sql_help.c:2936 sql_help.c:2950 sql_help.c:3000 sql_help.c:3196 +#: sql_help.c:3202 sql_help.c:4021 msgid "collation" msgstr "ordenamiento" -#: sql_help.c:456 sql_help.c:1332 sql_help.c:2338 sql_help.c:2347 -#: sql_help.c:2899 sql_help.c:2915 sql_help.c:2928 +#: sql_help.c:466 sql_help.c:1348 sql_help.c:2359 sql_help.c:2368 +#: sql_help.c:2916 sql_help.c:2932 sql_help.c:2945 msgid "column_constraint" msgstr "restricción_de_columna" -#: sql_help.c:466 sql_help.c:608 sql_help.c:682 sql_help.c:1350 sql_help.c:4986 +#: sql_help.c:476 sql_help.c:618 sql_help.c:692 sql_help.c:1368 sql_help.c:5018 msgid "integer" msgstr "entero" -#: sql_help.c:468 sql_help.c:471 sql_help.c:684 sql_help.c:687 sql_help.c:1352 -#: sql_help.c:1355 +#: sql_help.c:478 sql_help.c:481 sql_help.c:694 sql_help.c:697 sql_help.c:1370 +#: sql_help.c:1373 msgid "attribute_option" msgstr "opción_de_atributo" -#: sql_help.c:476 sql_help.c:1359 sql_help.c:2339 sql_help.c:2348 -#: sql_help.c:2900 sql_help.c:2916 sql_help.c:2929 +#: sql_help.c:486 sql_help.c:1377 sql_help.c:2360 sql_help.c:2369 +#: sql_help.c:2917 sql_help.c:2933 sql_help.c:2946 msgid "table_constraint" msgstr "restricción_de_tabla" -#: sql_help.c:479 sql_help.c:480 sql_help.c:481 sql_help.c:482 sql_help.c:1364 -#: sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 sql_help.c:1907 +#: sql_help.c:489 sql_help.c:490 sql_help.c:491 sql_help.c:492 sql_help.c:1382 +#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:1922 msgid "trigger_name" msgstr "nombre_disparador" -#: sql_help.c:483 sql_help.c:484 sql_help.c:1378 sql_help.c:1379 -#: sql_help.c:2340 sql_help.c:2345 sql_help.c:2903 sql_help.c:2926 +#: sql_help.c:493 sql_help.c:494 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:2361 sql_help.c:2366 sql_help.c:2920 sql_help.c:2943 msgid "parent_table" msgstr "tabla_padre" -#: sql_help.c:543 sql_help.c:600 sql_help.c:669 sql_help.c:873 sql_help.c:1023 -#: sql_help.c:1550 sql_help.c:2269 +#: sql_help.c:553 sql_help.c:610 sql_help.c:679 sql_help.c:889 sql_help.c:1039 +#: sql_help.c:1571 sql_help.c:2290 msgid "extension_name" msgstr "nombre_de_extensión" -#: sql_help.c:545 sql_help.c:1025 sql_help.c:2403 +#: sql_help.c:555 sql_help.c:1041 sql_help.c:2424 msgid "execution_cost" msgstr "costo_de_ejecución" -#: sql_help.c:546 sql_help.c:1026 sql_help.c:2404 +#: sql_help.c:556 sql_help.c:1042 sql_help.c:2425 msgid "result_rows" msgstr "núm_de_filas" -#: sql_help.c:547 sql_help.c:2405 +#: sql_help.c:557 sql_help.c:2426 msgid "support_function" msgstr "función_de_soporte" -#: sql_help.c:569 sql_help.c:571 sql_help.c:948 sql_help.c:956 sql_help.c:960 -#: sql_help.c:963 sql_help.c:966 sql_help.c:1633 sql_help.c:1641 -#: sql_help.c:1645 sql_help.c:1648 sql_help.c:1651 sql_help.c:2717 -#: sql_help.c:2719 sql_help.c:2722 sql_help.c:2723 sql_help.c:3891 -#: sql_help.c:3892 sql_help.c:3896 sql_help.c:3897 sql_help.c:3900 -#: sql_help.c:3901 sql_help.c:3903 sql_help.c:3904 sql_help.c:3906 -#: sql_help.c:3907 sql_help.c:3909 sql_help.c:3910 sql_help.c:3912 -#: sql_help.c:3913 sql_help.c:3919 sql_help.c:3920 sql_help.c:3922 -#: sql_help.c:3923 sql_help.c:3925 sql_help.c:3926 sql_help.c:3928 -#: sql_help.c:3929 sql_help.c:3931 sql_help.c:3932 sql_help.c:3934 -#: sql_help.c:3935 sql_help.c:3937 sql_help.c:3938 sql_help.c:3940 -#: sql_help.c:3941 sql_help.c:4343 sql_help.c:4344 sql_help.c:4348 -#: sql_help.c:4349 sql_help.c:4352 sql_help.c:4353 sql_help.c:4355 -#: sql_help.c:4356 sql_help.c:4358 sql_help.c:4359 sql_help.c:4361 -#: sql_help.c:4362 sql_help.c:4364 sql_help.c:4365 sql_help.c:4371 -#: sql_help.c:4372 sql_help.c:4374 sql_help.c:4375 sql_help.c:4377 -#: sql_help.c:4378 sql_help.c:4380 sql_help.c:4381 sql_help.c:4383 -#: sql_help.c:4384 sql_help.c:4386 sql_help.c:4387 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4392 sql_help.c:4393 +#: sql_help.c:579 sql_help.c:581 sql_help.c:964 sql_help.c:972 sql_help.c:976 +#: sql_help.c:979 sql_help.c:982 sql_help.c:1654 sql_help.c:1662 +#: sql_help.c:1666 sql_help.c:1669 sql_help.c:1672 sql_help.c:2734 +#: sql_help.c:2736 sql_help.c:2739 sql_help.c:2740 sql_help.c:3912 +#: sql_help.c:3913 sql_help.c:3917 sql_help.c:3918 sql_help.c:3921 +#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 +#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 +#: sql_help.c:3934 sql_help.c:3940 sql_help.c:3941 sql_help.c:3943 +#: sql_help.c:3944 sql_help.c:3946 sql_help.c:3947 sql_help.c:3949 +#: sql_help.c:3950 sql_help.c:3952 sql_help.c:3953 sql_help.c:3955 +#: sql_help.c:3956 sql_help.c:3958 sql_help.c:3959 sql_help.c:3961 +#: sql_help.c:3962 sql_help.c:4375 sql_help.c:4376 sql_help.c:4380 +#: sql_help.c:4381 sql_help.c:4384 sql_help.c:4385 sql_help.c:4387 +#: sql_help.c:4388 sql_help.c:4390 sql_help.c:4391 sql_help.c:4393 +#: sql_help.c:4394 sql_help.c:4396 sql_help.c:4397 sql_help.c:4403 +#: sql_help.c:4404 sql_help.c:4406 sql_help.c:4407 sql_help.c:4409 +#: sql_help.c:4410 sql_help.c:4412 sql_help.c:4413 sql_help.c:4415 +#: sql_help.c:4416 sql_help.c:4418 sql_help.c:4419 sql_help.c:4421 +#: sql_help.c:4422 sql_help.c:4424 sql_help.c:4425 msgid "role_specification" msgstr "especificación_de_rol" -#: sql_help.c:570 sql_help.c:572 sql_help.c:1664 sql_help.c:2205 -#: sql_help.c:2725 sql_help.c:3253 sql_help.c:3704 sql_help.c:4720 +#: sql_help.c:580 sql_help.c:582 sql_help.c:1685 sql_help.c:2225 +#: sql_help.c:2742 sql_help.c:3273 sql_help.c:3724 sql_help.c:4753 msgid "user_name" msgstr "nombre_de_usuario" -#: sql_help.c:573 sql_help.c:968 sql_help.c:1653 sql_help.c:2724 -#: sql_help.c:3942 sql_help.c:4394 +#: sql_help.c:583 sql_help.c:984 sql_help.c:1674 sql_help.c:2741 +#: sql_help.c:3963 sql_help.c:4426 msgid "where role_specification can be:" msgstr "donde especificación_de_rol puede ser:" -#: sql_help.c:575 +#: sql_help.c:585 msgid "group_name" msgstr "nombre_de_grupo" -#: sql_help.c:596 sql_help.c:1425 sql_help.c:2216 sql_help.c:2476 -#: sql_help.c:2510 sql_help.c:2911 sql_help.c:2924 sql_help.c:2938 -#: sql_help.c:2979 sql_help.c:3006 sql_help.c:3018 sql_help.c:3933 -#: sql_help.c:4385 +#: sql_help.c:606 sql_help.c:1443 sql_help.c:2237 sql_help.c:2497 +#: sql_help.c:2531 sql_help.c:2928 sql_help.c:2941 sql_help.c:2955 +#: sql_help.c:2996 sql_help.c:3026 sql_help.c:3038 sql_help.c:3954 +#: sql_help.c:4417 msgid "tablespace_name" msgstr "nombre_de_tablespace" -#: sql_help.c:598 sql_help.c:691 sql_help.c:1372 sql_help.c:1382 -#: sql_help.c:1420 sql_help.c:1782 sql_help.c:1785 +#: sql_help.c:608 sql_help.c:701 sql_help.c:1390 sql_help.c:1400 +#: sql_help.c:1438 sql_help.c:1800 msgid "index_name" msgstr "nombre_índice" -#: sql_help.c:602 sql_help.c:605 sql_help.c:694 sql_help.c:696 sql_help.c:1375 -#: sql_help.c:1377 sql_help.c:1423 sql_help.c:2474 sql_help.c:2508 -#: sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 sql_help.c:2977 -#: sql_help.c:3004 +#: sql_help.c:612 sql_help.c:615 sql_help.c:704 sql_help.c:706 sql_help.c:1393 +#: sql_help.c:1395 sql_help.c:1441 sql_help.c:2495 sql_help.c:2529 +#: sql_help.c:2926 sql_help.c:2939 sql_help.c:2953 sql_help.c:2994 +#: sql_help.c:3024 msgid "storage_parameter" msgstr "parámetro_de_almacenamiento" -#: sql_help.c:607 +#: sql_help.c:617 msgid "column_number" msgstr "número_de_columna" -#: sql_help.c:631 sql_help.c:1870 sql_help.c:4477 +#: sql_help.c:641 sql_help.c:1885 sql_help.c:4509 msgid "large_object_oid" msgstr "oid_de_objeto_grande" -#: sql_help.c:690 sql_help.c:1358 sql_help.c:2897 +#: sql_help.c:700 sql_help.c:1376 sql_help.c:2914 msgid "compression_method" msgstr "método_de_compresión" -#: sql_help.c:692 sql_help.c:1373 +#: sql_help.c:702 sql_help.c:1391 msgid "new_access_method" msgstr "nuevo_método_de_acceso" -#: sql_help.c:725 sql_help.c:2531 +#: sql_help.c:739 sql_help.c:2552 msgid "res_proc" msgstr "proc_res" -#: sql_help.c:726 sql_help.c:2532 +#: sql_help.c:740 sql_help.c:2553 msgid "join_proc" msgstr "proc_join" -#: sql_help.c:778 sql_help.c:790 sql_help.c:2549 +#: sql_help.c:741 sql_help.c:2550 +msgid "com_op" +msgstr "op_conm" + +#: sql_help.c:742 sql_help.c:2551 +msgid "neg_op" +msgstr "op_neg" + +#: sql_help.c:794 sql_help.c:806 sql_help.c:2570 msgid "strategy_number" msgstr "número_de_estrategia" -#: sql_help.c:780 sql_help.c:781 sql_help.c:784 sql_help.c:785 sql_help.c:791 -#: sql_help.c:792 sql_help.c:794 sql_help.c:795 sql_help.c:2551 sql_help.c:2552 -#: sql_help.c:2555 sql_help.c:2556 +#: sql_help.c:796 sql_help.c:797 sql_help.c:800 sql_help.c:801 sql_help.c:807 +#: sql_help.c:808 sql_help.c:810 sql_help.c:811 sql_help.c:2572 sql_help.c:2573 +#: sql_help.c:2576 sql_help.c:2577 msgid "op_type" msgstr "tipo_op" -#: sql_help.c:782 sql_help.c:2553 +#: sql_help.c:798 sql_help.c:2574 msgid "sort_family_name" msgstr "nombre_familia_ordenamiento" -#: sql_help.c:783 sql_help.c:793 sql_help.c:2554 +#: sql_help.c:799 sql_help.c:809 sql_help.c:2575 msgid "support_number" msgstr "número_de_soporte" -#: sql_help.c:787 sql_help.c:2138 sql_help.c:2558 sql_help.c:3095 -#: sql_help.c:3097 +#: sql_help.c:803 sql_help.c:2157 sql_help.c:2579 sql_help.c:3115 +#: sql_help.c:3117 msgid "argument_type" msgstr "tipo_argumento" -#: sql_help.c:818 sql_help.c:821 sql_help.c:910 sql_help.c:1039 sql_help.c:1079 -#: sql_help.c:1546 sql_help.c:1549 sql_help.c:1727 sql_help.c:1781 -#: sql_help.c:1784 sql_help.c:1855 sql_help.c:1880 sql_help.c:1893 -#: sql_help.c:1908 sql_help.c:1966 sql_help.c:1972 sql_help.c:2332 -#: sql_help.c:2344 sql_help.c:2465 sql_help.c:2505 sql_help.c:2582 -#: sql_help.c:2636 sql_help.c:2693 sql_help.c:2745 sql_help.c:2778 -#: sql_help.c:2785 sql_help.c:2894 sql_help.c:2912 sql_help.c:2925 -#: sql_help.c:3001 sql_help.c:3121 sql_help.c:3302 sql_help.c:3525 -#: sql_help.c:3574 sql_help.c:3680 sql_help.c:3889 sql_help.c:3895 -#: sql_help.c:3956 sql_help.c:3988 sql_help.c:4341 sql_help.c:4347 -#: sql_help.c:4465 sql_help.c:4576 sql_help.c:4578 sql_help.c:4640 -#: sql_help.c:4679 sql_help.c:4833 sql_help.c:4835 sql_help.c:4897 -#: sql_help.c:4931 sql_help.c:4991 sql_help.c:5079 sql_help.c:5081 -#: sql_help.c:5143 +#: sql_help.c:834 sql_help.c:837 sql_help.c:926 sql_help.c:1055 sql_help.c:1095 +#: sql_help.c:1567 sql_help.c:1570 sql_help.c:1746 sql_help.c:1799 +#: sql_help.c:1870 sql_help.c:1895 sql_help.c:1908 sql_help.c:1923 +#: sql_help.c:1983 sql_help.c:1989 sql_help.c:2353 sql_help.c:2365 +#: sql_help.c:2486 sql_help.c:2526 sql_help.c:2603 sql_help.c:2657 +#: sql_help.c:2710 sql_help.c:2762 sql_help.c:2795 sql_help.c:2802 +#: sql_help.c:2911 sql_help.c:2929 sql_help.c:2942 sql_help.c:3021 +#: sql_help.c:3141 sql_help.c:3322 sql_help.c:3545 sql_help.c:3594 +#: sql_help.c:3700 sql_help.c:3910 sql_help.c:3916 sql_help.c:3977 +#: sql_help.c:4009 sql_help.c:4373 sql_help.c:4379 sql_help.c:4497 +#: sql_help.c:4610 sql_help.c:4673 sql_help.c:4712 sql_help.c:4868 +#: sql_help.c:4931 sql_help.c:4965 sql_help.c:5023 sql_help.c:5113 +#: sql_help.c:5176 msgid "table_name" msgstr "nombre_de_tabla" -#: sql_help.c:823 sql_help.c:2584 +#: sql_help.c:839 sql_help.c:2605 msgid "using_expression" msgstr "expresión_using" -#: sql_help.c:824 sql_help.c:2585 +#: sql_help.c:840 sql_help.c:2606 msgid "check_expression" msgstr "expresión_check" -#: sql_help.c:897 sql_help.c:899 sql_help.c:901 sql_help.c:2632 +#: sql_help.c:913 sql_help.c:915 sql_help.c:917 sql_help.c:2653 msgid "publication_object" msgstr "objeto_de_publicación" -#: sql_help.c:903 sql_help.c:2633 +#: sql_help.c:919 sql_help.c:2654 msgid "publication_parameter" msgstr "parámetro_de_publicación" -#: sql_help.c:909 sql_help.c:2635 +#: sql_help.c:925 sql_help.c:2656 msgid "where publication_object is one of:" msgstr "donde objeto_de_publicación es uno de:" -#: sql_help.c:952 sql_help.c:1637 sql_help.c:2443 sql_help.c:2670 -#: sql_help.c:3236 +#: sql_help.c:968 sql_help.c:1658 sql_help.c:2464 sql_help.c:2689 +#: sql_help.c:3256 msgid "password" msgstr "contraseña" -#: sql_help.c:953 sql_help.c:1638 sql_help.c:2444 sql_help.c:2671 -#: sql_help.c:3237 +#: sql_help.c:969 sql_help.c:1659 sql_help.c:2465 sql_help.c:2690 +#: sql_help.c:3257 msgid "timestamp" msgstr "fecha_hora" -#: sql_help.c:957 sql_help.c:961 sql_help.c:964 sql_help.c:967 sql_help.c:1642 -#: sql_help.c:1646 sql_help.c:1649 sql_help.c:1652 sql_help.c:3902 -#: sql_help.c:4354 +#: sql_help.c:973 sql_help.c:977 sql_help.c:980 sql_help.c:983 sql_help.c:1663 +#: sql_help.c:1667 sql_help.c:1670 sql_help.c:1673 sql_help.c:3923 +#: sql_help.c:4386 msgid "database_name" msgstr "nombre_de_base_de_datos" -#: sql_help.c:1073 sql_help.c:2740 +#: sql_help.c:1089 sql_help.c:2757 msgid "increment" msgstr "incremento" -#: sql_help.c:1074 sql_help.c:2741 +#: sql_help.c:1090 sql_help.c:2758 msgid "minvalue" msgstr "valormin" -#: sql_help.c:1075 sql_help.c:2742 +#: sql_help.c:1091 sql_help.c:2759 msgid "maxvalue" msgstr "valormax" -#: sql_help.c:1076 sql_help.c:2743 sql_help.c:4574 sql_help.c:4677 -#: sql_help.c:4831 sql_help.c:5008 sql_help.c:5077 +#: sql_help.c:1092 sql_help.c:2760 sql_help.c:4606 sql_help.c:4710 +#: sql_help.c:4864 sql_help.c:5040 sql_help.c:5109 msgid "start" msgstr "inicio" -#: sql_help.c:1077 sql_help.c:1347 +#: sql_help.c:1093 sql_help.c:1365 msgid "restart" msgstr "reinicio" -#: sql_help.c:1078 sql_help.c:2744 +#: sql_help.c:1094 sql_help.c:2761 msgid "cache" msgstr "cache" -#: sql_help.c:1123 +#: sql_help.c:1139 msgid "new_target" msgstr "nuevo_valor" -#: sql_help.c:1142 sql_help.c:2797 +#: sql_help.c:1158 sql_help.c:2814 msgid "conninfo" msgstr "conninfo" -#: sql_help.c:1144 sql_help.c:1148 sql_help.c:1152 sql_help.c:2798 +#: sql_help.c:1160 sql_help.c:1164 sql_help.c:1168 sql_help.c:2815 msgid "publication_name" msgstr "nombre_de_publicación" -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 +#: sql_help.c:1161 sql_help.c:1165 sql_help.c:1169 msgid "publication_option" msgstr "opción_de_publicación" -#: sql_help.c:1156 +#: sql_help.c:1172 msgid "refresh_option" msgstr "opción_refresh" -#: sql_help.c:1161 sql_help.c:2799 +#: sql_help.c:1177 sql_help.c:2816 msgid "subscription_parameter" msgstr "parámetro_de_suscripción" -#: sql_help.c:1164 +#: sql_help.c:1180 msgid "skip_option" msgstr "opción_skip" -#: sql_help.c:1324 sql_help.c:1327 +#: sql_help.c:1340 sql_help.c:1343 msgid "partition_name" msgstr "nombre_de_partición" -#: sql_help.c:1325 sql_help.c:2349 sql_help.c:2930 +#: sql_help.c:1341 sql_help.c:2370 sql_help.c:2947 msgid "partition_bound_spec" msgstr "borde_de_partición" -#: sql_help.c:1344 sql_help.c:1394 sql_help.c:2944 +#: sql_help.c:1362 sql_help.c:1412 sql_help.c:2961 msgid "sequence_options" msgstr "opciones_de_secuencia" -#: sql_help.c:1346 +#: sql_help.c:1364 msgid "sequence_option" msgstr "opción_de_secuencia" -#: sql_help.c:1360 +#: sql_help.c:1378 msgid "table_constraint_using_index" msgstr "restricción_de_tabla_con_índice" -#: sql_help.c:1368 sql_help.c:1369 sql_help.c:1370 sql_help.c:1371 +#: sql_help.c:1386 sql_help.c:1387 sql_help.c:1388 sql_help.c:1389 msgid "rewrite_rule_name" msgstr "nombre_regla_de_reescritura" -#: sql_help.c:1383 sql_help.c:2361 sql_help.c:2969 +#: sql_help.c:1401 sql_help.c:2382 sql_help.c:2986 msgid "and partition_bound_spec is:" msgstr "y borde_de_partición es:" -#: sql_help.c:1384 sql_help.c:1385 sql_help.c:1386 sql_help.c:2362 -#: sql_help.c:2363 sql_help.c:2364 sql_help.c:2970 sql_help.c:2971 -#: sql_help.c:2972 +#: sql_help.c:1402 sql_help.c:1403 sql_help.c:1404 sql_help.c:2383 +#: sql_help.c:2384 sql_help.c:2385 sql_help.c:2987 sql_help.c:2988 +#: sql_help.c:2989 msgid "partition_bound_expr" msgstr "expresión_de_borde_de_partición" -#: sql_help.c:1387 sql_help.c:1388 sql_help.c:2365 sql_help.c:2366 -#: sql_help.c:2973 sql_help.c:2974 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:2386 sql_help.c:2387 +#: sql_help.c:2990 sql_help.c:2991 msgid "numeric_literal" msgstr "literal_numérico" -#: sql_help.c:1389 +#: sql_help.c:1407 msgid "and column_constraint is:" msgstr "donde restricción_de_columna es:" -#: sql_help.c:1392 sql_help.c:2356 sql_help.c:2397 sql_help.c:2606 -#: sql_help.c:2942 +#: sql_help.c:1410 sql_help.c:2377 sql_help.c:2418 sql_help.c:2627 +#: sql_help.c:2959 msgid "default_expr" msgstr "expr_por_omisión" -#: sql_help.c:1393 sql_help.c:2357 sql_help.c:2943 +#: sql_help.c:1411 sql_help.c:2378 sql_help.c:2960 msgid "generation_expr" msgstr "expr_de_generación" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1405 sql_help.c:1407 -#: sql_help.c:1411 sql_help.c:2945 sql_help.c:2946 sql_help.c:2955 -#: sql_help.c:2957 sql_help.c:2961 +#: sql_help.c:1413 sql_help.c:1414 sql_help.c:1423 sql_help.c:1425 +#: sql_help.c:1429 sql_help.c:2962 sql_help.c:2963 sql_help.c:2972 +#: sql_help.c:2974 sql_help.c:2978 msgid "index_parameters" msgstr "parámetros_de_índice" -#: sql_help.c:1397 sql_help.c:1414 sql_help.c:2947 sql_help.c:2964 +#: sql_help.c:1415 sql_help.c:1432 sql_help.c:2964 sql_help.c:2981 msgid "reftable" msgstr "tabla_ref" -#: sql_help.c:1398 sql_help.c:1415 sql_help.c:2948 sql_help.c:2965 +#: sql_help.c:1416 sql_help.c:1433 sql_help.c:2965 sql_help.c:2982 msgid "refcolumn" msgstr "columna_ref" -#: sql_help.c:1399 sql_help.c:1400 sql_help.c:1416 sql_help.c:1417 -#: sql_help.c:2949 sql_help.c:2950 sql_help.c:2966 sql_help.c:2967 +#: sql_help.c:1417 sql_help.c:1418 sql_help.c:1434 sql_help.c:1435 +#: sql_help.c:2966 sql_help.c:2967 sql_help.c:2983 sql_help.c:2984 msgid "referential_action" msgstr "acción_referencial" -#: sql_help.c:1401 sql_help.c:2358 sql_help.c:2951 +#: sql_help.c:1419 sql_help.c:2379 sql_help.c:2968 msgid "and table_constraint is:" msgstr "y restricción_de_tabla es:" -#: sql_help.c:1409 sql_help.c:2959 +#: sql_help.c:1427 sql_help.c:2976 msgid "exclude_element" msgstr "elemento_de_exclusión" -#: sql_help.c:1410 sql_help.c:2960 sql_help.c:4572 sql_help.c:4675 -#: sql_help.c:4829 sql_help.c:5006 sql_help.c:5075 +#: sql_help.c:1428 sql_help.c:2977 sql_help.c:4604 sql_help.c:4708 +#: sql_help.c:4862 sql_help.c:5038 sql_help.c:5107 msgid "operator" msgstr "operador" -#: sql_help.c:1412 sql_help.c:2477 sql_help.c:2962 +#: sql_help.c:1430 sql_help.c:2498 sql_help.c:2979 msgid "predicate" msgstr "predicado" -#: sql_help.c:1418 +#: sql_help.c:1436 msgid "and table_constraint_using_index is:" msgstr "y restricción_de_tabla_con_índice es:" -#: sql_help.c:1421 sql_help.c:2975 +#: sql_help.c:1439 sql_help.c:2992 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "parámetros_de_índice en UNIQUE, PRIMARY KEY y EXCLUDE son:" -#: sql_help.c:1426 sql_help.c:2980 +#: sql_help.c:1444 sql_help.c:2997 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "elemento_de_exclusión en una restricción EXCLUDE es:" -#: sql_help.c:1429 sql_help.c:2470 sql_help.c:2907 sql_help.c:2920 -#: sql_help.c:2934 sql_help.c:2983 sql_help.c:4001 +#: sql_help.c:1448 sql_help.c:2491 sql_help.c:2924 sql_help.c:2937 +#: sql_help.c:2951 sql_help.c:3001 sql_help.c:4022 msgid "opclass" msgstr "clase_de_ops" -#: sql_help.c:1430 sql_help.c:2984 +#: sql_help.c:1449 sql_help.c:2492 sql_help.c:3002 +msgid "opclass_parameter" +msgstr "parámetro_opclass" + +#: sql_help.c:1451 sql_help.c:3004 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "acción_referencial en una restricción FOREIGN KEY/REFERENCES es:" -#: sql_help.c:1448 sql_help.c:1451 sql_help.c:3021 +#: sql_help.c:1469 sql_help.c:1472 sql_help.c:3041 msgid "tablespace_option" msgstr "opción_de_tablespace" -#: sql_help.c:1472 sql_help.c:1475 sql_help.c:1481 sql_help.c:1485 +#: sql_help.c:1493 sql_help.c:1496 sql_help.c:1502 sql_help.c:1506 msgid "token_type" msgstr "tipo_de_token" -#: sql_help.c:1473 sql_help.c:1476 +#: sql_help.c:1494 sql_help.c:1497 msgid "dictionary_name" msgstr "nombre_diccionario" -#: sql_help.c:1478 sql_help.c:1482 +#: sql_help.c:1499 sql_help.c:1503 msgid "old_dictionary" msgstr "diccionario_antiguo" -#: sql_help.c:1479 sql_help.c:1483 +#: sql_help.c:1500 sql_help.c:1504 msgid "new_dictionary" msgstr "diccionario_nuevo" -#: sql_help.c:1578 sql_help.c:1592 sql_help.c:1595 sql_help.c:1596 -#: sql_help.c:3174 +#: sql_help.c:1599 sql_help.c:1613 sql_help.c:1616 sql_help.c:1617 +#: sql_help.c:3194 msgid "attribute_name" msgstr "nombre_atributo" -#: sql_help.c:1579 +#: sql_help.c:1600 msgid "new_attribute_name" msgstr "nuevo_nombre_atributo" -#: sql_help.c:1583 sql_help.c:1587 +#: sql_help.c:1604 sql_help.c:1608 msgid "new_enum_value" msgstr "nuevo_valor_enum" -#: sql_help.c:1584 +#: sql_help.c:1605 msgid "neighbor_enum_value" msgstr "valor_enum_vecino" -#: sql_help.c:1586 +#: sql_help.c:1607 msgid "existing_enum_value" msgstr "valor_enum_existente" -#: sql_help.c:1589 +#: sql_help.c:1610 msgid "property" msgstr "propiedad" -#: sql_help.c:1665 sql_help.c:2341 sql_help.c:2350 sql_help.c:2756 -#: sql_help.c:3254 sql_help.c:3705 sql_help.c:3911 sql_help.c:3957 -#: sql_help.c:4363 +#: sql_help.c:1686 sql_help.c:2362 sql_help.c:2371 sql_help.c:2773 +#: sql_help.c:3274 sql_help.c:3725 sql_help.c:3932 sql_help.c:3978 +#: sql_help.c:4395 msgid "server_name" msgstr "nombre_de_servidor" -#: sql_help.c:1697 sql_help.c:1700 sql_help.c:3269 +#: sql_help.c:1718 sql_help.c:1721 sql_help.c:3289 msgid "view_option_name" msgstr "nombre_opción_de_vista" -#: sql_help.c:1698 sql_help.c:3270 +#: sql_help.c:1719 sql_help.c:3290 msgid "view_option_value" msgstr "valor_opción_de_vista" -#: sql_help.c:1720 sql_help.c:1721 sql_help.c:4974 sql_help.c:4975 +#: sql_help.c:1740 sql_help.c:5007 msgid "table_and_columns" msgstr "tabla_y_columnas" -#: sql_help.c:1722 sql_help.c:1786 sql_help.c:1978 sql_help.c:3754 -#: sql_help.c:4198 sql_help.c:4976 +#: sql_help.c:1741 sql_help.c:1801 sql_help.c:1995 sql_help.c:3774 +#: sql_help.c:4230 sql_help.c:5008 msgid "where option can be one of:" msgstr "donde opción puede ser una de:" -#: sql_help.c:1723 sql_help.c:1724 sql_help.c:1787 sql_help.c:1980 -#: sql_help.c:1984 sql_help.c:2164 sql_help.c:3755 sql_help.c:3756 -#: sql_help.c:3757 sql_help.c:3758 sql_help.c:3759 sql_help.c:3760 -#: sql_help.c:3761 sql_help.c:3762 sql_help.c:3763 sql_help.c:4199 -#: sql_help.c:4201 sql_help.c:4977 sql_help.c:4978 sql_help.c:4979 -#: sql_help.c:4980 sql_help.c:4981 sql_help.c:4982 sql_help.c:4983 -#: sql_help.c:4984 sql_help.c:4985 sql_help.c:4987 sql_help.c:4988 +#: sql_help.c:1742 sql_help.c:1743 sql_help.c:1802 sql_help.c:1997 +#: sql_help.c:2001 sql_help.c:2183 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:3777 sql_help.c:3778 sql_help.c:3779 sql_help.c:3780 +#: sql_help.c:3781 sql_help.c:3782 sql_help.c:3783 sql_help.c:3784 +#: sql_help.c:4231 sql_help.c:4233 sql_help.c:5009 sql_help.c:5010 +#: sql_help.c:5011 sql_help.c:5012 sql_help.c:5013 sql_help.c:5014 +#: sql_help.c:5015 sql_help.c:5016 sql_help.c:5017 sql_help.c:5019 +#: sql_help.c:5020 msgid "boolean" msgstr "booleano" -#: sql_help.c:1725 sql_help.c:4989 +#: sql_help.c:1744 sql_help.c:5021 msgid "size" msgstr "tamaño" -#: sql_help.c:1726 sql_help.c:4990 +#: sql_help.c:1745 sql_help.c:5022 msgid "and table_and_columns is:" msgstr "y tabla_y_columnas es:" -#: sql_help.c:1742 sql_help.c:4736 sql_help.c:4738 sql_help.c:4762 +#: sql_help.c:1761 sql_help.c:4769 sql_help.c:4771 sql_help.c:4795 msgid "transaction_mode" msgstr "modo_de_transacción" -#: sql_help.c:1743 sql_help.c:4739 sql_help.c:4763 +#: sql_help.c:1762 sql_help.c:4772 sql_help.c:4796 msgid "where transaction_mode is one of:" msgstr "donde modo_de_transacción es uno de:" -#: sql_help.c:1752 sql_help.c:4582 sql_help.c:4591 sql_help.c:4595 -#: sql_help.c:4599 sql_help.c:4602 sql_help.c:4839 sql_help.c:4848 -#: sql_help.c:4852 sql_help.c:4856 sql_help.c:4859 sql_help.c:5085 -#: sql_help.c:5094 sql_help.c:5098 sql_help.c:5102 sql_help.c:5105 +#: sql_help.c:1771 sql_help.c:4614 sql_help.c:4623 sql_help.c:4627 +#: sql_help.c:4631 sql_help.c:4634 sql_help.c:4872 sql_help.c:4881 +#: sql_help.c:4885 sql_help.c:4889 sql_help.c:4892 sql_help.c:5117 +#: sql_help.c:5126 sql_help.c:5130 sql_help.c:5134 sql_help.c:5137 msgid "argument" msgstr "argumento" -#: sql_help.c:1852 +#: sql_help.c:1867 msgid "relation_name" msgstr "nombre_relación" -#: sql_help.c:1857 sql_help.c:3905 sql_help.c:4357 +#: sql_help.c:1872 sql_help.c:3926 sql_help.c:4389 msgid "domain_name" msgstr "nombre_de_dominio" -#: sql_help.c:1879 +#: sql_help.c:1894 msgid "policy_name" msgstr "nombre_de_política" -#: sql_help.c:1892 +#: sql_help.c:1907 msgid "rule_name" msgstr "nombre_regla" -#: sql_help.c:1911 sql_help.c:4496 +#: sql_help.c:1926 sql_help.c:4528 msgid "string_literal" msgstr "literal_de_cadena" -#: sql_help.c:1936 sql_help.c:4160 sql_help.c:4410 +#: sql_help.c:1951 sql_help.c:4192 sql_help.c:4442 msgid "transaction_id" msgstr "id_de_transacción" -#: sql_help.c:1968 sql_help.c:1975 sql_help.c:4027 +#: sql_help.c:1985 sql_help.c:1992 sql_help.c:4048 msgid "filename" msgstr "nombre_de_archivo" -#: sql_help.c:1969 sql_help.c:1976 sql_help.c:2695 sql_help.c:2696 -#: sql_help.c:2697 +#: sql_help.c:1986 sql_help.c:1993 sql_help.c:2712 sql_help.c:2713 +#: sql_help.c:2714 msgid "command" msgstr "orden" -#: sql_help.c:1971 sql_help.c:2694 sql_help.c:3124 sql_help.c:3305 -#: sql_help.c:4011 sql_help.c:4088 sql_help.c:4091 sql_help.c:4565 -#: sql_help.c:4567 sql_help.c:4668 sql_help.c:4670 sql_help.c:4822 -#: sql_help.c:4824 sql_help.c:4940 sql_help.c:5068 sql_help.c:5070 +#: sql_help.c:1988 sql_help.c:2711 sql_help.c:3144 sql_help.c:3325 +#: sql_help.c:4032 sql_help.c:4115 sql_help.c:4118 sql_help.c:4121 +#: sql_help.c:4597 sql_help.c:4599 sql_help.c:4701 sql_help.c:4703 +#: sql_help.c:4855 sql_help.c:4857 sql_help.c:4974 sql_help.c:5100 +#: sql_help.c:5102 msgid "condition" msgstr "condición" -#: sql_help.c:1974 sql_help.c:2511 sql_help.c:3007 sql_help.c:3271 -#: sql_help.c:3289 sql_help.c:3992 +#: sql_help.c:1991 sql_help.c:2532 sql_help.c:3027 sql_help.c:3291 +#: sql_help.c:3309 sql_help.c:4013 msgid "query" msgstr "consulta" -#: sql_help.c:1979 +#: sql_help.c:1996 msgid "format_name" msgstr "nombre_de_formato" -#: sql_help.c:1981 +#: sql_help.c:1998 msgid "delimiter_character" msgstr "carácter_delimitador" -#: sql_help.c:1982 +#: sql_help.c:1999 msgid "null_string" msgstr "cadena_null" -#: sql_help.c:1983 +#: sql_help.c:2000 msgid "default_string" msgstr "cadena_por_omisión" -#: sql_help.c:1985 +#: sql_help.c:2002 msgid "quote_character" msgstr "carácter_de_comilla" -#: sql_help.c:1986 +#: sql_help.c:2003 msgid "escape_character" msgstr "carácter_de_escape" -#: sql_help.c:1990 +#: sql_help.c:2007 +msgid "error_action" +msgstr "acción_en_error" + +#: sql_help.c:2008 msgid "encoding_name" msgstr "nombre_codificación" -#: sql_help.c:2001 +#: sql_help.c:2009 +msgid "verbosity" +msgstr "verbosidad" + +#: sql_help.c:2020 msgid "access_method_type" msgstr "tipo_de_método_de_acceso" -#: sql_help.c:2072 sql_help.c:2091 sql_help.c:2094 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2113 msgid "arg_data_type" msgstr "tipo_de_dato_arg" -#: sql_help.c:2073 sql_help.c:2095 sql_help.c:2103 +#: sql_help.c:2092 sql_help.c:2114 sql_help.c:2122 msgid "sfunc" msgstr "func_transición" -#: sql_help.c:2074 sql_help.c:2096 sql_help.c:2104 +#: sql_help.c:2093 sql_help.c:2115 sql_help.c:2123 msgid "state_data_type" msgstr "tipo_de_dato_de_estado" -#: sql_help.c:2075 sql_help.c:2097 sql_help.c:2105 +#: sql_help.c:2094 sql_help.c:2116 sql_help.c:2124 msgid "state_data_size" msgstr "tamaño_de_dato_de_estado" -#: sql_help.c:2076 sql_help.c:2098 sql_help.c:2106 +#: sql_help.c:2095 sql_help.c:2117 sql_help.c:2125 msgid "ffunc" msgstr "func_final" -#: sql_help.c:2077 sql_help.c:2107 +#: sql_help.c:2096 sql_help.c:2126 msgid "combinefunc" msgstr "func_combinación" -#: sql_help.c:2078 sql_help.c:2108 +#: sql_help.c:2097 sql_help.c:2127 msgid "serialfunc" msgstr "func_serial" -#: sql_help.c:2079 sql_help.c:2109 +#: sql_help.c:2098 sql_help.c:2128 msgid "deserialfunc" msgstr "func_deserial" -#: sql_help.c:2080 sql_help.c:2099 sql_help.c:2110 +#: sql_help.c:2099 sql_help.c:2118 sql_help.c:2129 msgid "initial_condition" msgstr "condición_inicial" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2100 sql_help.c:2130 msgid "msfunc" msgstr "func_transición_m" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2101 sql_help.c:2131 msgid "minvfunc" msgstr "func_inv_m" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2102 sql_help.c:2132 msgid "mstate_data_type" msgstr "tipo_de_dato_de_estado_m" -#: sql_help.c:2084 sql_help.c:2114 +#: sql_help.c:2103 sql_help.c:2133 msgid "mstate_data_size" msgstr "tamaño_de_dato_de_estado_m" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2104 sql_help.c:2134 msgid "mffunc" msgstr "func_final_m" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2105 sql_help.c:2135 msgid "minitial_condition" msgstr "condición_inicial_m" -#: sql_help.c:2087 sql_help.c:2117 +#: sql_help.c:2106 sql_help.c:2136 msgid "sort_operator" msgstr "operador_de_ordenamiento" -#: sql_help.c:2100 +#: sql_help.c:2119 msgid "or the old syntax" msgstr "o la sintaxis antigua" -#: sql_help.c:2102 +#: sql_help.c:2121 msgid "base_type" msgstr "tipo_base" -#: sql_help.c:2160 sql_help.c:2209 +#: sql_help.c:2179 sql_help.c:2229 msgid "locale" msgstr "configuración regional" -#: sql_help.c:2161 sql_help.c:2210 +#: sql_help.c:2180 sql_help.c:2230 msgid "lc_collate" msgstr "lc_collate" -#: sql_help.c:2162 sql_help.c:2211 +#: sql_help.c:2181 sql_help.c:2231 msgid "lc_ctype" msgstr "lc_ctype" -#: sql_help.c:2163 sql_help.c:4463 +#: sql_help.c:2182 sql_help.c:4495 msgid "provider" msgstr "proveedor" -#: sql_help.c:2165 +#: sql_help.c:2184 msgid "rules" msgstr "reglas" -#: sql_help.c:2166 sql_help.c:2271 +#: sql_help.c:2185 sql_help.c:2292 msgid "version" msgstr "versión" -#: sql_help.c:2168 +#: sql_help.c:2187 msgid "existing_collation" msgstr "ordenamiento_existente" -#: sql_help.c:2178 +#: sql_help.c:2197 msgid "source_encoding" msgstr "codificación_origen" -#: sql_help.c:2179 +#: sql_help.c:2198 msgid "dest_encoding" msgstr "codificación_destino" -#: sql_help.c:2206 sql_help.c:3047 +#: sql_help.c:2226 sql_help.c:3067 msgid "template" msgstr "plantilla" -#: sql_help.c:2207 +#: sql_help.c:2227 msgid "encoding" msgstr "codificación" -#: sql_help.c:2208 +#: sql_help.c:2228 msgid "strategy" msgstr "estrategia" -#: sql_help.c:2212 +#: sql_help.c:2232 +msgid "builtin_locale" +msgstr "locale_builtin" + +#: sql_help.c:2233 msgid "icu_locale" msgstr "locale_icu" -#: sql_help.c:2213 +#: sql_help.c:2234 msgid "icu_rules" msgstr "reglas_icu" -#: sql_help.c:2214 +#: sql_help.c:2235 msgid "locale_provider" msgstr "proveedor_locale" -#: sql_help.c:2215 +#: sql_help.c:2236 msgid "collation_version" msgstr "versión_ordenamiento" -#: sql_help.c:2220 +#: sql_help.c:2241 msgid "oid" msgstr "oid" -#: sql_help.c:2240 -msgid "constraint" -msgstr "restricción" - -#: sql_help.c:2241 -msgid "where constraint is:" -msgstr "donde restricción es:" - -#: sql_help.c:2255 sql_help.c:2692 sql_help.c:3120 +#: sql_help.c:2276 sql_help.c:2709 sql_help.c:3140 msgid "event" msgstr "evento" -#: sql_help.c:2256 +#: sql_help.c:2277 msgid "filter_variable" msgstr "variable_de_filtrado" -#: sql_help.c:2257 +#: sql_help.c:2278 msgid "filter_value" msgstr "valor_de_filtrado" -#: sql_help.c:2353 sql_help.c:2939 +#: sql_help.c:2374 sql_help.c:2956 msgid "where column_constraint is:" msgstr "donde restricción_de_columna es:" -#: sql_help.c:2398 +#: sql_help.c:2419 msgid "rettype" msgstr "tipo_ret" -#: sql_help.c:2400 +#: sql_help.c:2421 msgid "column_type" msgstr "tipo_columna" -#: sql_help.c:2409 sql_help.c:2612 +#: sql_help.c:2430 sql_help.c:2633 msgid "definition" msgstr "definición" -#: sql_help.c:2410 sql_help.c:2613 +#: sql_help.c:2431 sql_help.c:2634 msgid "obj_file" msgstr "archivo_obj" -#: sql_help.c:2411 sql_help.c:2614 +#: sql_help.c:2432 sql_help.c:2635 msgid "link_symbol" msgstr "símbolo_enlace" -#: sql_help.c:2412 sql_help.c:2615 +#: sql_help.c:2433 sql_help.c:2636 msgid "sql_body" msgstr "contenido_sql" -#: sql_help.c:2450 sql_help.c:2677 sql_help.c:3243 +#: sql_help.c:2471 sql_help.c:2694 sql_help.c:3263 msgid "uid" msgstr "uid" -#: sql_help.c:2466 sql_help.c:2507 sql_help.c:2908 sql_help.c:2921 -#: sql_help.c:2935 sql_help.c:3003 +#: sql_help.c:2487 sql_help.c:2528 sql_help.c:2925 sql_help.c:2938 +#: sql_help.c:2952 sql_help.c:3023 msgid "method" msgstr "método" -#: sql_help.c:2471 -msgid "opclass_parameter" -msgstr "parámetro_opclass" - -#: sql_help.c:2488 +#: sql_help.c:2509 msgid "call_handler" msgstr "manejador_de_llamada" -#: sql_help.c:2489 +#: sql_help.c:2510 msgid "inline_handler" msgstr "manejador_en_línea" -#: sql_help.c:2490 +#: sql_help.c:2511 msgid "valfunction" msgstr "función_val" -#: sql_help.c:2529 -msgid "com_op" -msgstr "op_conm" - -#: sql_help.c:2530 -msgid "neg_op" -msgstr "op_neg" - -#: sql_help.c:2548 +#: sql_help.c:2569 msgid "family_name" msgstr "nombre_familia" -#: sql_help.c:2559 +#: sql_help.c:2580 msgid "storage_type" msgstr "tipo_almacenamiento" -#: sql_help.c:2698 sql_help.c:3127 +#: sql_help.c:2715 sql_help.c:3147 msgid "where event can be one of:" msgstr "donde evento puede ser una de:" -#: sql_help.c:2718 sql_help.c:2720 +#: sql_help.c:2735 sql_help.c:2737 msgid "schema_element" msgstr "elemento_de_esquema" -#: sql_help.c:2757 +#: sql_help.c:2774 msgid "server_type" msgstr "tipo_de_servidor" -#: sql_help.c:2758 +#: sql_help.c:2775 msgid "server_version" msgstr "versión_de_servidor" -#: sql_help.c:2759 sql_help.c:3908 sql_help.c:4360 +#: sql_help.c:2776 sql_help.c:3929 sql_help.c:4392 msgid "fdw_name" msgstr "nombre_fdw" -#: sql_help.c:2776 sql_help.c:2779 +#: sql_help.c:2793 sql_help.c:2796 msgid "statistics_name" msgstr "nombre_de_estadística" -#: sql_help.c:2780 +#: sql_help.c:2797 msgid "statistics_kind" msgstr "tipo_de_estadística" -#: sql_help.c:2796 +#: sql_help.c:2813 msgid "subscription_name" msgstr "nombre_de_suscripción" -#: sql_help.c:2901 +#: sql_help.c:2918 msgid "source_table" msgstr "tabla_origen" -#: sql_help.c:2902 +#: sql_help.c:2919 msgid "like_option" msgstr "opción_de_like" -#: sql_help.c:2968 +#: sql_help.c:2985 msgid "and like_option is:" msgstr "y opción_de_like es:" -#: sql_help.c:3020 +#: sql_help.c:3040 msgid "directory" msgstr "directorio" -#: sql_help.c:3034 +#: sql_help.c:3054 msgid "parser_name" msgstr "nombre_de_parser" -#: sql_help.c:3035 +#: sql_help.c:3055 msgid "source_config" msgstr "config_origen" -#: sql_help.c:3064 +#: sql_help.c:3084 msgid "start_function" msgstr "función_inicio" -#: sql_help.c:3065 +#: sql_help.c:3085 msgid "gettoken_function" msgstr "función_gettoken" -#: sql_help.c:3066 +#: sql_help.c:3086 msgid "end_function" msgstr "función_fin" -#: sql_help.c:3067 +#: sql_help.c:3087 msgid "lextypes_function" msgstr "función_lextypes" -#: sql_help.c:3068 +#: sql_help.c:3088 msgid "headline_function" msgstr "función_headline" -#: sql_help.c:3080 +#: sql_help.c:3100 msgid "init_function" msgstr "función_init" -#: sql_help.c:3081 +#: sql_help.c:3101 msgid "lexize_function" msgstr "función_lexize" -#: sql_help.c:3094 +#: sql_help.c:3114 msgid "from_sql_function_name" msgstr "nombre_de_función_from" -#: sql_help.c:3096 +#: sql_help.c:3116 msgid "to_sql_function_name" msgstr "nombre_de_función_to" -#: sql_help.c:3122 +#: sql_help.c:3142 msgid "referenced_table_name" msgstr "nombre_tabla_referenciada" -#: sql_help.c:3123 +#: sql_help.c:3143 msgid "transition_relation_name" msgstr "nombre_de_relación_de_transición" -#: sql_help.c:3126 +#: sql_help.c:3146 msgid "arguments" msgstr "argumentos" -#: sql_help.c:3178 +#: sql_help.c:3198 msgid "label" msgstr "etiqueta" -#: sql_help.c:3180 +#: sql_help.c:3200 msgid "subtype" msgstr "subtipo" -#: sql_help.c:3181 +#: sql_help.c:3201 msgid "subtype_operator_class" msgstr "clase_de_operador_del_subtipo" -#: sql_help.c:3183 +#: sql_help.c:3203 msgid "canonical_function" msgstr "función_canónica" -#: sql_help.c:3184 +#: sql_help.c:3204 msgid "subtype_diff_function" msgstr "función_diff_del_subtipo" -#: sql_help.c:3185 +#: sql_help.c:3205 msgid "multirange_type_name" msgstr "nombre_de_tipo_de_multirango" -#: sql_help.c:3187 +#: sql_help.c:3207 msgid "input_function" msgstr "función_entrada" -#: sql_help.c:3188 +#: sql_help.c:3208 msgid "output_function" msgstr "función_salida" -#: sql_help.c:3189 +#: sql_help.c:3209 msgid "receive_function" msgstr "función_receive" -#: sql_help.c:3190 +#: sql_help.c:3210 msgid "send_function" msgstr "función_send" -#: sql_help.c:3191 +#: sql_help.c:3211 msgid "type_modifier_input_function" msgstr "función_entrada_del_modificador_de_tipo" -#: sql_help.c:3192 +#: sql_help.c:3212 msgid "type_modifier_output_function" msgstr "función_salida_del_modificador_de_tipo" -#: sql_help.c:3193 +#: sql_help.c:3213 msgid "analyze_function" msgstr "función_analyze" -#: sql_help.c:3194 +#: sql_help.c:3214 msgid "subscript_function" msgstr "función_de_subíndice" -#: sql_help.c:3195 +#: sql_help.c:3215 msgid "internallength" msgstr "largo_interno" -#: sql_help.c:3196 +#: sql_help.c:3216 msgid "alignment" msgstr "alineamiento" -#: sql_help.c:3197 +#: sql_help.c:3217 msgid "storage" msgstr "almacenamiento" -#: sql_help.c:3198 +#: sql_help.c:3218 msgid "like_type" msgstr "como_tipo" -#: sql_help.c:3199 +#: sql_help.c:3219 msgid "category" msgstr "categoría" -#: sql_help.c:3200 +#: sql_help.c:3220 msgid "preferred" msgstr "preferido" -#: sql_help.c:3201 +#: sql_help.c:3221 msgid "default" msgstr "valor_por_omisión" -#: sql_help.c:3202 +#: sql_help.c:3222 msgid "element" msgstr "elemento" -#: sql_help.c:3203 +#: sql_help.c:3223 msgid "delimiter" msgstr "delimitador" -#: sql_help.c:3204 +#: sql_help.c:3224 msgid "collatable" msgstr "ordenable" -#: sql_help.c:3301 sql_help.c:3987 sql_help.c:4077 sql_help.c:4560 -#: sql_help.c:4662 sql_help.c:4817 sql_help.c:4930 sql_help.c:5063 +#: sql_help.c:3321 sql_help.c:4008 sql_help.c:4102 sql_help.c:4592 +#: sql_help.c:4695 sql_help.c:4850 sql_help.c:4964 sql_help.c:5095 msgid "with_query" msgstr "consulta_with" -#: sql_help.c:3303 sql_help.c:3989 sql_help.c:4579 sql_help.c:4585 -#: sql_help.c:4588 sql_help.c:4592 sql_help.c:4596 sql_help.c:4604 -#: sql_help.c:4836 sql_help.c:4842 sql_help.c:4845 sql_help.c:4849 -#: sql_help.c:4853 sql_help.c:4861 sql_help.c:4932 sql_help.c:5082 -#: sql_help.c:5088 sql_help.c:5091 sql_help.c:5095 sql_help.c:5099 -#: sql_help.c:5107 +#: sql_help.c:3323 sql_help.c:4010 sql_help.c:4611 sql_help.c:4617 +#: sql_help.c:4620 sql_help.c:4624 sql_help.c:4628 sql_help.c:4636 +#: sql_help.c:4869 sql_help.c:4875 sql_help.c:4878 sql_help.c:4882 +#: sql_help.c:4886 sql_help.c:4894 sql_help.c:4966 sql_help.c:5114 +#: sql_help.c:5120 sql_help.c:5123 sql_help.c:5127 sql_help.c:5131 +#: sql_help.c:5139 msgid "alias" msgstr "alias" -#: sql_help.c:3304 sql_help.c:4564 sql_help.c:4606 sql_help.c:4608 -#: sql_help.c:4612 sql_help.c:4614 sql_help.c:4615 sql_help.c:4616 -#: sql_help.c:4667 sql_help.c:4821 sql_help.c:4863 sql_help.c:4865 -#: sql_help.c:4869 sql_help.c:4871 sql_help.c:4872 sql_help.c:4873 -#: sql_help.c:4939 sql_help.c:5067 sql_help.c:5109 sql_help.c:5111 -#: sql_help.c:5115 sql_help.c:5117 sql_help.c:5118 sql_help.c:5119 +#: sql_help.c:3324 sql_help.c:4596 sql_help.c:4638 sql_help.c:4640 +#: sql_help.c:4644 sql_help.c:4646 sql_help.c:4647 sql_help.c:4648 +#: sql_help.c:4700 sql_help.c:4854 sql_help.c:4896 sql_help.c:4898 +#: sql_help.c:4902 sql_help.c:4904 sql_help.c:4905 sql_help.c:4906 +#: sql_help.c:4973 sql_help.c:5099 sql_help.c:5141 sql_help.c:5143 +#: sql_help.c:5147 sql_help.c:5149 sql_help.c:5150 sql_help.c:5151 msgid "from_item" msgstr "item_de_from" -#: sql_help.c:3306 sql_help.c:3789 sql_help.c:4127 sql_help.c:4941 +#: sql_help.c:3326 sql_help.c:3810 sql_help.c:4159 sql_help.c:4975 msgid "cursor_name" msgstr "nombre_de_cursor" -#: sql_help.c:3307 sql_help.c:3995 sql_help.c:4942 +#: sql_help.c:3327 sql_help.c:4016 sql_help.c:4108 sql_help.c:4976 msgid "output_expression" msgstr "expresión_de_salida" -#: sql_help.c:3308 sql_help.c:3996 sql_help.c:4563 sql_help.c:4665 -#: sql_help.c:4820 sql_help.c:4943 sql_help.c:5066 +#: sql_help.c:3328 sql_help.c:4017 sql_help.c:4109 sql_help.c:4595 +#: sql_help.c:4698 sql_help.c:4853 sql_help.c:4977 sql_help.c:5098 msgid "output_name" msgstr "nombre_de_salida" -#: sql_help.c:3324 +#: sql_help.c:3344 msgid "code" msgstr "código" -#: sql_help.c:3729 +#: sql_help.c:3749 msgid "parameter" msgstr "parámetro" -#: sql_help.c:3752 sql_help.c:3753 sql_help.c:4152 +#: sql_help.c:3773 sql_help.c:4184 msgid "statement" msgstr "sentencia" -#: sql_help.c:3788 sql_help.c:4126 +#: sql_help.c:3809 sql_help.c:4158 msgid "direction" msgstr "dirección" -#: sql_help.c:3790 sql_help.c:4128 +#: sql_help.c:3811 sql_help.c:4160 msgid "where direction can be one of:" msgstr "donde dirección puede ser una de:" -#: sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 sql_help.c:3794 -#: sql_help.c:3795 sql_help.c:4129 sql_help.c:4130 sql_help.c:4131 -#: sql_help.c:4132 sql_help.c:4133 sql_help.c:4573 sql_help.c:4575 -#: sql_help.c:4676 sql_help.c:4678 sql_help.c:4830 sql_help.c:4832 -#: sql_help.c:5007 sql_help.c:5009 sql_help.c:5076 sql_help.c:5078 +#: sql_help.c:3812 sql_help.c:3813 sql_help.c:3814 sql_help.c:3815 +#: sql_help.c:3816 sql_help.c:4161 sql_help.c:4162 sql_help.c:4163 +#: sql_help.c:4164 sql_help.c:4165 sql_help.c:4605 sql_help.c:4607 +#: sql_help.c:4709 sql_help.c:4711 sql_help.c:4863 sql_help.c:4865 +#: sql_help.c:5039 sql_help.c:5041 sql_help.c:5108 sql_help.c:5110 msgid "count" msgstr "cantidad" -#: sql_help.c:3898 sql_help.c:4350 +#: sql_help.c:3919 sql_help.c:4382 msgid "sequence_name" msgstr "nombre_secuencia" -#: sql_help.c:3916 sql_help.c:4368 +#: sql_help.c:3937 sql_help.c:4400 msgid "arg_name" msgstr "nombre_arg" -#: sql_help.c:3917 sql_help.c:4369 +#: sql_help.c:3938 sql_help.c:4401 msgid "arg_type" msgstr "tipo_arg" -#: sql_help.c:3924 sql_help.c:4376 +#: sql_help.c:3945 sql_help.c:4408 msgid "loid" msgstr "loid" -#: sql_help.c:3955 +#: sql_help.c:3976 msgid "remote_schema" msgstr "esquema_remoto" -#: sql_help.c:3958 +#: sql_help.c:3979 msgid "local_schema" msgstr "esquema_local" -#: sql_help.c:3993 +#: sql_help.c:4014 msgid "conflict_target" msgstr "destino_de_conflict" -#: sql_help.c:3994 +#: sql_help.c:4015 msgid "conflict_action" msgstr "acción_de_conflict" -#: sql_help.c:3997 +#: sql_help.c:4018 msgid "where conflict_target can be one of:" msgstr "donde destino_de_conflict puede ser uno de:" -#: sql_help.c:3998 +#: sql_help.c:4019 msgid "index_column_name" msgstr "nombre_de_columna_de_índice" -#: sql_help.c:3999 +#: sql_help.c:4020 msgid "index_expression" msgstr "expresión_de_índice" -#: sql_help.c:4002 +#: sql_help.c:4023 msgid "index_predicate" msgstr "predicado_de_índice" -#: sql_help.c:4004 +#: sql_help.c:4025 msgid "and conflict_action is one of:" msgstr "donde acción_de_conflict es una de:" -#: sql_help.c:4010 sql_help.c:4938 +#: sql_help.c:4031 sql_help.c:4132 sql_help.c:4972 msgid "sub-SELECT" msgstr "sub-SELECT" -#: sql_help.c:4019 sql_help.c:4141 sql_help.c:4914 +#: sql_help.c:4040 sql_help.c:4173 sql_help.c:4948 msgid "channel" msgstr "canal" -#: sql_help.c:4041 +#: sql_help.c:4062 msgid "lockmode" msgstr "modo_bloqueo" -#: sql_help.c:4042 +#: sql_help.c:4063 msgid "where lockmode is one of:" msgstr "donde modo_bloqueo es uno de:" -#: sql_help.c:4078 +#: sql_help.c:4103 msgid "target_table_name" msgstr "nombre_de_tabla_destino" -#: sql_help.c:4079 +#: sql_help.c:4104 msgid "target_alias" msgstr "alias_de_destino" -#: sql_help.c:4080 +#: sql_help.c:4105 msgid "data_source" msgstr "origin_de_datos" -#: sql_help.c:4081 sql_help.c:4609 sql_help.c:4866 sql_help.c:5112 +#: sql_help.c:4106 sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "join_condition" msgstr "condición_de_join" -#: sql_help.c:4082 +#: sql_help.c:4107 msgid "when_clause" msgstr "cláusula_when" -#: sql_help.c:4083 +#: sql_help.c:4110 msgid "where data_source is:" msgstr "donde origen_de_datos es:" -#: sql_help.c:4084 +#: sql_help.c:4111 msgid "source_table_name" msgstr "nombre_tabla_origen" -#: sql_help.c:4085 +#: sql_help.c:4112 msgid "source_query" msgstr "consulta_origen" -#: sql_help.c:4086 +#: sql_help.c:4113 msgid "source_alias" msgstr "alias_origen" -#: sql_help.c:4087 +#: sql_help.c:4114 msgid "and when_clause is:" msgstr "y cláusula_when es:" -#: sql_help.c:4089 +#: sql_help.c:4116 sql_help.c:4119 msgid "merge_update" msgstr "update_de_merge" -#: sql_help.c:4090 +#: sql_help.c:4117 sql_help.c:4120 msgid "merge_delete" msgstr "delete_de_merge" -#: sql_help.c:4092 +#: sql_help.c:4122 msgid "merge_insert" msgstr "insert_de_merge" -#: sql_help.c:4093 +#: sql_help.c:4123 msgid "and merge_insert is:" msgstr "y insert_de_merge es:" -#: sql_help.c:4096 +#: sql_help.c:4126 msgid "and merge_update is:" msgstr "y update_de_merge es:" -#: sql_help.c:4101 +#: sql_help.c:4133 msgid "and merge_delete is:" msgstr "y delete_de_merge es:" -#: sql_help.c:4142 +#: sql_help.c:4174 msgid "payload" msgstr "carga" -#: sql_help.c:4169 +#: sql_help.c:4201 msgid "old_role" msgstr "rol_antiguo" -#: sql_help.c:4170 +#: sql_help.c:4202 msgid "new_role" msgstr "rol_nuevo" -#: sql_help.c:4209 sql_help.c:4418 sql_help.c:4426 +#: sql_help.c:4241 sql_help.c:4450 sql_help.c:4458 msgid "savepoint_name" msgstr "nombre_de_savepoint" -#: sql_help.c:4566 sql_help.c:4624 sql_help.c:4823 sql_help.c:4881 -#: sql_help.c:5069 sql_help.c:5127 +#: sql_help.c:4598 sql_help.c:4656 sql_help.c:4856 sql_help.c:4914 +#: sql_help.c:5101 sql_help.c:5159 msgid "grouping_element" msgstr "elemento_agrupante" -#: sql_help.c:4568 sql_help.c:4671 sql_help.c:4825 sql_help.c:5071 +#: sql_help.c:4600 sql_help.c:4704 sql_help.c:4858 sql_help.c:5103 msgid "window_name" msgstr "nombre_de_ventana" -#: sql_help.c:4569 sql_help.c:4672 sql_help.c:4826 sql_help.c:5072 +#: sql_help.c:4601 sql_help.c:4705 sql_help.c:4859 sql_help.c:5104 msgid "window_definition" msgstr "definición_de_ventana" -#: sql_help.c:4570 sql_help.c:4584 sql_help.c:4628 sql_help.c:4673 -#: sql_help.c:4827 sql_help.c:4841 sql_help.c:4885 sql_help.c:5073 -#: sql_help.c:5087 sql_help.c:5131 +#: sql_help.c:4602 sql_help.c:4616 sql_help.c:4660 sql_help.c:4706 +#: sql_help.c:4860 sql_help.c:4874 sql_help.c:4918 sql_help.c:5105 +#: sql_help.c:5119 sql_help.c:5163 msgid "select" msgstr "select" -#: sql_help.c:4577 sql_help.c:4834 sql_help.c:5080 +#: sql_help.c:4608 sql_help.c:4866 sql_help.c:5111 +msgid "from_reference" +msgstr "referencia_en_from" + +#: sql_help.c:4609 sql_help.c:4867 sql_help.c:5112 msgid "where from_item can be one of:" msgstr "donde item_de_from puede ser uno de:" -#: sql_help.c:4580 sql_help.c:4586 sql_help.c:4589 sql_help.c:4593 -#: sql_help.c:4605 sql_help.c:4837 sql_help.c:4843 sql_help.c:4846 -#: sql_help.c:4850 sql_help.c:4862 sql_help.c:5083 sql_help.c:5089 -#: sql_help.c:5092 sql_help.c:5096 sql_help.c:5108 +#: sql_help.c:4612 sql_help.c:4618 sql_help.c:4621 sql_help.c:4625 +#: sql_help.c:4637 sql_help.c:4870 sql_help.c:4876 sql_help.c:4879 +#: sql_help.c:4883 sql_help.c:4895 sql_help.c:5115 sql_help.c:5121 +#: sql_help.c:5124 sql_help.c:5128 sql_help.c:5140 msgid "column_alias" msgstr "alias_de_columna" -#: sql_help.c:4581 sql_help.c:4838 sql_help.c:5084 +#: sql_help.c:4613 sql_help.c:4871 sql_help.c:5116 msgid "sampling_method" msgstr "método_de_sampleo" -#: sql_help.c:4583 sql_help.c:4840 sql_help.c:5086 +#: sql_help.c:4615 sql_help.c:4873 sql_help.c:5118 msgid "seed" msgstr "semilla" -#: sql_help.c:4587 sql_help.c:4626 sql_help.c:4844 sql_help.c:4883 -#: sql_help.c:5090 sql_help.c:5129 +#: sql_help.c:4619 sql_help.c:4658 sql_help.c:4877 sql_help.c:4916 +#: sql_help.c:5122 sql_help.c:5161 msgid "with_query_name" msgstr "nombre_consulta_with" -#: sql_help.c:4597 sql_help.c:4600 sql_help.c:4603 sql_help.c:4854 -#: sql_help.c:4857 sql_help.c:4860 sql_help.c:5100 sql_help.c:5103 -#: sql_help.c:5106 +#: sql_help.c:4629 sql_help.c:4632 sql_help.c:4635 sql_help.c:4887 +#: sql_help.c:4890 sql_help.c:4893 sql_help.c:5132 sql_help.c:5135 +#: sql_help.c:5138 msgid "column_definition" msgstr "definición_de_columna" -#: sql_help.c:4607 sql_help.c:4613 sql_help.c:4864 sql_help.c:4870 -#: sql_help.c:5110 sql_help.c:5116 +#: sql_help.c:4639 sql_help.c:4645 sql_help.c:4897 sql_help.c:4903 +#: sql_help.c:5142 sql_help.c:5148 msgid "join_type" msgstr "tipo_de_join" -#: sql_help.c:4610 sql_help.c:4867 sql_help.c:5113 +#: sql_help.c:4642 sql_help.c:4900 sql_help.c:5145 msgid "join_column" msgstr "columna_de_join" -#: sql_help.c:4611 sql_help.c:4868 sql_help.c:5114 +#: sql_help.c:4643 sql_help.c:4901 sql_help.c:5146 msgid "join_using_alias" msgstr "join_con_alias" -#: sql_help.c:4617 sql_help.c:4874 sql_help.c:5120 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and grouping_element can be one of:" msgstr "donde elemento_agrupante puede ser una de:" -#: sql_help.c:4625 sql_help.c:4882 sql_help.c:5128 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 msgid "and with_query is:" msgstr "y consulta_with es:" -#: sql_help.c:4629 sql_help.c:4886 sql_help.c:5132 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "values" msgstr "valores" -#: sql_help.c:4630 sql_help.c:4887 sql_help.c:5133 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "insert" msgstr "insert" -#: sql_help.c:4631 sql_help.c:4888 sql_help.c:5134 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "update" msgstr "update" -#: sql_help.c:4632 sql_help.c:4889 sql_help.c:5135 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "delete" msgstr "delete" -#: sql_help.c:4634 sql_help.c:4891 sql_help.c:5137 +#: sql_help.c:4665 sql_help.c:4923 sql_help.c:5168 +msgid "merge" +msgstr "merge" + +#: sql_help.c:4667 sql_help.c:4925 sql_help.c:5170 msgid "search_seq_col_name" msgstr "nombre_col_para_sec_de_búsqueda" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4669 sql_help.c:4927 sql_help.c:5172 msgid "cycle_mark_col_name" msgstr "nombre_col_para_marca_de_ciclo" -#: sql_help.c:4637 sql_help.c:4894 sql_help.c:5140 +#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 msgid "cycle_mark_value" msgstr "valor_marca_de_ciclo" -#: sql_help.c:4638 sql_help.c:4895 sql_help.c:5141 +#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 msgid "cycle_mark_default" msgstr "valor_predet_marca_de_ciclo" -#: sql_help.c:4639 sql_help.c:4896 sql_help.c:5142 +#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 msgid "cycle_path_col_name" msgstr "nombre_col_para_ruta_de_ciclo" -#: sql_help.c:4666 +#: sql_help.c:4699 msgid "new_table" msgstr "nueva_tabla" -#: sql_help.c:4737 +#: sql_help.c:4770 msgid "snapshot_id" msgstr "id_de_snapshot" -#: sql_help.c:5005 +#: sql_help.c:5037 msgid "sort_expression" msgstr "expresión_orden" -#: sql_help.c:5149 sql_help.c:6133 +#: sql_help.c:5182 sql_help.c:6166 msgid "abort the current transaction" msgstr "aborta la transacción en curso" -#: sql_help.c:5155 +#: sql_help.c:5188 msgid "change the definition of an aggregate function" msgstr "cambia la definición de una función de agregación" -#: sql_help.c:5161 +#: sql_help.c:5194 msgid "change the definition of a collation" msgstr "cambia la definición de un ordenamiento" -#: sql_help.c:5167 +#: sql_help.c:5200 msgid "change the definition of a conversion" msgstr "cambia la definición de una conversión" -#: sql_help.c:5173 +#: sql_help.c:5206 msgid "change a database" msgstr "cambia una base de datos" -#: sql_help.c:5179 +#: sql_help.c:5212 msgid "define default access privileges" msgstr "define privilegios de acceso por omisión" -#: sql_help.c:5185 +#: sql_help.c:5218 msgid "change the definition of a domain" msgstr "cambia la definición de un dominio" -#: sql_help.c:5191 +#: sql_help.c:5224 msgid "change the definition of an event trigger" msgstr "cambia la definición de un disparador por evento" -#: sql_help.c:5197 +#: sql_help.c:5230 msgid "change the definition of an extension" msgstr "cambia la definición de una extensión" -#: sql_help.c:5203 +#: sql_help.c:5236 msgid "change the definition of a foreign-data wrapper" msgstr "cambia la definición de un conector de datos externos" -#: sql_help.c:5209 +#: sql_help.c:5242 msgid "change the definition of a foreign table" msgstr "cambia la definición de una tabla foránea" -#: sql_help.c:5215 +#: sql_help.c:5248 msgid "change the definition of a function" msgstr "cambia la definición de una función" -#: sql_help.c:5221 +#: sql_help.c:5254 msgid "change role name or membership" msgstr "cambiar nombre del rol o membresía" -#: sql_help.c:5227 +#: sql_help.c:5260 msgid "change the definition of an index" msgstr "cambia la definición de un índice" -#: sql_help.c:5233 +#: sql_help.c:5266 msgid "change the definition of a procedural language" msgstr "cambia la definición de un lenguaje procedural" -#: sql_help.c:5239 +#: sql_help.c:5272 msgid "change the definition of a large object" msgstr "cambia la definición de un objeto grande" -#: sql_help.c:5245 +#: sql_help.c:5278 msgid "change the definition of a materialized view" msgstr "cambia la definición de una vista materializada" -#: sql_help.c:5251 +#: sql_help.c:5284 msgid "change the definition of an operator" msgstr "cambia la definición de un operador" -#: sql_help.c:5257 +#: sql_help.c:5290 msgid "change the definition of an operator class" msgstr "cambia la definición de una clase de operadores" -#: sql_help.c:5263 +#: sql_help.c:5296 msgid "change the definition of an operator family" msgstr "cambia la definición de una familia de operadores" -#: sql_help.c:5269 +#: sql_help.c:5302 msgid "change the definition of a row-level security policy" msgstr "cambia la definición de una política de seguridad a nivel de registros" -#: sql_help.c:5275 +#: sql_help.c:5308 msgid "change the definition of a procedure" msgstr "cambia la definición de un procedimiento" -#: sql_help.c:5281 +#: sql_help.c:5314 msgid "change the definition of a publication" msgstr "cambia la definición de una publicación" -#: sql_help.c:5287 sql_help.c:5389 +#: sql_help.c:5320 sql_help.c:5422 msgid "change a database role" msgstr "cambia un rol de la base de datos" -#: sql_help.c:5293 +#: sql_help.c:5326 msgid "change the definition of a routine" msgstr "cambia la definición de una rutina" -#: sql_help.c:5299 +#: sql_help.c:5332 msgid "change the definition of a rule" msgstr "cambia la definición de una regla" -#: sql_help.c:5305 +#: sql_help.c:5338 msgid "change the definition of a schema" msgstr "cambia la definición de un esquema" -#: sql_help.c:5311 +#: sql_help.c:5344 msgid "change the definition of a sequence generator" msgstr "cambia la definición de un generador secuencial" -#: sql_help.c:5317 +#: sql_help.c:5350 msgid "change the definition of a foreign server" msgstr "cambia la definición de un servidor foráneo" -#: sql_help.c:5323 +#: sql_help.c:5356 msgid "change the definition of an extended statistics object" msgstr "cambia la definición de un objeto de estadísticas extendidas" -#: sql_help.c:5329 +#: sql_help.c:5362 msgid "change the definition of a subscription" msgstr "cambia la definición de una suscripción" -#: sql_help.c:5335 +#: sql_help.c:5368 msgid "change a server configuration parameter" msgstr "cambia un parámetro de configuración del servidor" -#: sql_help.c:5341 +#: sql_help.c:5374 msgid "change the definition of a table" msgstr "cambia la definición de una tabla" -#: sql_help.c:5347 +#: sql_help.c:5380 msgid "change the definition of a tablespace" msgstr "cambia la definición de un tablespace" -#: sql_help.c:5353 +#: sql_help.c:5386 msgid "change the definition of a text search configuration" msgstr "cambia la definición de una configuración de búsqueda en texto" -#: sql_help.c:5359 +#: sql_help.c:5392 msgid "change the definition of a text search dictionary" msgstr "cambia la definición de un diccionario de búsqueda en texto" -#: sql_help.c:5365 +#: sql_help.c:5398 msgid "change the definition of a text search parser" msgstr "cambia la definición de un analizador de búsqueda en texto" -#: sql_help.c:5371 +#: sql_help.c:5404 msgid "change the definition of a text search template" msgstr "cambia la definición de una plantilla de búsqueda en texto" -#: sql_help.c:5377 +#: sql_help.c:5410 msgid "change the definition of a trigger" msgstr "cambia la definición de un disparador" -#: sql_help.c:5383 +#: sql_help.c:5416 msgid "change the definition of a type" msgstr "cambia la definición de un tipo" -#: sql_help.c:5395 +#: sql_help.c:5428 msgid "change the definition of a user mapping" msgstr "cambia la definición de un mapeo de usuario" -#: sql_help.c:5401 +#: sql_help.c:5434 msgid "change the definition of a view" msgstr "cambia la definición de una vista" -#: sql_help.c:5407 +#: sql_help.c:5440 msgid "collect statistics about a database" msgstr "recolecta estadísticas sobre una base de datos" -#: sql_help.c:5413 sql_help.c:6211 +#: sql_help.c:5446 sql_help.c:6244 msgid "start a transaction block" msgstr "inicia un bloque de transacción" -#: sql_help.c:5419 +#: sql_help.c:5452 msgid "invoke a procedure" msgstr "invocar un procedimiento" -#: sql_help.c:5425 +#: sql_help.c:5458 msgid "force a write-ahead log checkpoint" msgstr "fuerza un checkpoint de wal" -#: sql_help.c:5431 +#: sql_help.c:5464 msgid "close a cursor" msgstr "cierra un cursor" -#: sql_help.c:5437 +#: sql_help.c:5470 msgid "cluster a table according to an index" msgstr "reordena una tabla siguiendo un índice" -#: sql_help.c:5443 +#: sql_help.c:5476 msgid "define or change the comment of an object" msgstr "define o cambia un comentario sobre un objeto" -#: sql_help.c:5449 sql_help.c:6007 +#: sql_help.c:5482 sql_help.c:6040 msgid "commit the current transaction" msgstr "compromete la transacción en curso" -#: sql_help.c:5455 +#: sql_help.c:5488 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "confirma una transacción que fue preparada para two-phase commit" -#: sql_help.c:5461 +#: sql_help.c:5494 msgid "copy data between a file and a table" msgstr "copia datos entre un archivo y una tabla" -#: sql_help.c:5467 +#: sql_help.c:5500 msgid "define a new access method" msgstr "define un nuevo método de acceso" -#: sql_help.c:5473 +#: sql_help.c:5506 msgid "define a new aggregate function" msgstr "define una nueva función de agregación" -#: sql_help.c:5479 +#: sql_help.c:5512 msgid "define a new cast" msgstr "define una nueva conversión de tipo" -#: sql_help.c:5485 +#: sql_help.c:5518 msgid "define a new collation" msgstr "define un nuevo ordenamiento" -#: sql_help.c:5491 +#: sql_help.c:5524 msgid "define a new encoding conversion" msgstr "define una nueva conversión de codificación" -#: sql_help.c:5497 +#: sql_help.c:5530 msgid "create a new database" msgstr "crea una nueva base de datos" -#: sql_help.c:5503 +#: sql_help.c:5536 msgid "define a new domain" msgstr "define un nuevo dominio" -#: sql_help.c:5509 +#: sql_help.c:5542 msgid "define a new event trigger" msgstr "define un nuevo disparador por evento" -#: sql_help.c:5515 +#: sql_help.c:5548 msgid "install an extension" msgstr "instala una extensión" -#: sql_help.c:5521 +#: sql_help.c:5554 msgid "define a new foreign-data wrapper" msgstr "define un nuevo conector de datos externos" -#: sql_help.c:5527 +#: sql_help.c:5560 msgid "define a new foreign table" msgstr "define una nueva tabla foránea" -#: sql_help.c:5533 +#: sql_help.c:5566 msgid "define a new function" msgstr "define una nueva función" -#: sql_help.c:5539 sql_help.c:5599 sql_help.c:5701 +#: sql_help.c:5572 sql_help.c:5632 sql_help.c:5734 msgid "define a new database role" msgstr "define un nuevo rol de la base de datos" -#: sql_help.c:5545 +#: sql_help.c:5578 msgid "define a new index" msgstr "define un nuevo índice" -#: sql_help.c:5551 +#: sql_help.c:5584 msgid "define a new procedural language" msgstr "define un nuevo lenguaje procedural" -#: sql_help.c:5557 +#: sql_help.c:5590 msgid "define a new materialized view" msgstr "define una nueva vista materializada" -#: sql_help.c:5563 +#: sql_help.c:5596 msgid "define a new operator" msgstr "define un nuevo operador" -#: sql_help.c:5569 +#: sql_help.c:5602 msgid "define a new operator class" msgstr "define una nueva clase de operadores" -#: sql_help.c:5575 +#: sql_help.c:5608 msgid "define a new operator family" msgstr "define una nueva familia de operadores" -#: sql_help.c:5581 +#: sql_help.c:5614 msgid "define a new row-level security policy for a table" msgstr "define una nueva política de seguridad a nivel de registros para una tabla" -#: sql_help.c:5587 +#: sql_help.c:5620 msgid "define a new procedure" msgstr "define un nuevo procedimiento" -#: sql_help.c:5593 +#: sql_help.c:5626 msgid "define a new publication" msgstr "define una nueva publicación" -#: sql_help.c:5605 +#: sql_help.c:5638 msgid "define a new rewrite rule" msgstr "define una nueva regla de reescritura" -#: sql_help.c:5611 +#: sql_help.c:5644 msgid "define a new schema" msgstr "define un nuevo esquema" -#: sql_help.c:5617 +#: sql_help.c:5650 msgid "define a new sequence generator" msgstr "define un nuevo generador secuencial" -#: sql_help.c:5623 +#: sql_help.c:5656 msgid "define a new foreign server" msgstr "define un nuevo servidor foráneo" -#: sql_help.c:5629 +#: sql_help.c:5662 msgid "define extended statistics" msgstr "define estadísticas extendidas" -#: sql_help.c:5635 +#: sql_help.c:5668 msgid "define a new subscription" msgstr "define una nueva suscripción" -#: sql_help.c:5641 +#: sql_help.c:5674 msgid "define a new table" msgstr "define una nueva tabla" -#: sql_help.c:5647 sql_help.c:6169 +#: sql_help.c:5680 sql_help.c:6202 msgid "define a new table from the results of a query" msgstr "crea una nueva tabla usando los resultados de una consulta" -#: sql_help.c:5653 +#: sql_help.c:5686 msgid "define a new tablespace" msgstr "define un nuevo tablespace" -#: sql_help.c:5659 +#: sql_help.c:5692 msgid "define a new text search configuration" msgstr "define una nueva configuración de búsqueda en texto" -#: sql_help.c:5665 +#: sql_help.c:5698 msgid "define a new text search dictionary" msgstr "define un nuevo diccionario de búsqueda en texto" -#: sql_help.c:5671 +#: sql_help.c:5704 msgid "define a new text search parser" msgstr "define un nuevo analizador de búsqueda en texto" -#: sql_help.c:5677 +#: sql_help.c:5710 msgid "define a new text search template" msgstr "define una nueva plantilla de búsqueda en texto" -#: sql_help.c:5683 +#: sql_help.c:5716 msgid "define a new transform" msgstr "define una nueva transformación" -#: sql_help.c:5689 +#: sql_help.c:5722 msgid "define a new trigger" msgstr "define un nuevo disparador" -#: sql_help.c:5695 +#: sql_help.c:5728 msgid "define a new data type" msgstr "define un nuevo tipo de datos" -#: sql_help.c:5707 +#: sql_help.c:5740 msgid "define a new mapping of a user to a foreign server" msgstr "define un nuevo mapa de usuario a servidor foráneo" -#: sql_help.c:5713 +#: sql_help.c:5746 msgid "define a new view" msgstr "define una nueva vista" -#: sql_help.c:5719 +#: sql_help.c:5752 msgid "deallocate a prepared statement" msgstr "elimina una sentencia preparada" -#: sql_help.c:5725 +#: sql_help.c:5758 msgid "define a cursor" msgstr "define un nuevo cursor" -#: sql_help.c:5731 +#: sql_help.c:5764 msgid "delete rows of a table" msgstr "elimina filas de una tabla" -#: sql_help.c:5737 +#: sql_help.c:5770 msgid "discard session state" msgstr "descartar datos de la sesión" -#: sql_help.c:5743 +#: sql_help.c:5776 msgid "execute an anonymous code block" msgstr "ejecutar un bloque anónimo de código" -#: sql_help.c:5749 +#: sql_help.c:5782 msgid "remove an access method" msgstr "elimina un método de acceso" -#: sql_help.c:5755 +#: sql_help.c:5788 msgid "remove an aggregate function" msgstr "elimina una función de agregación" -#: sql_help.c:5761 +#: sql_help.c:5794 msgid "remove a cast" msgstr "elimina una conversión de tipo" -#: sql_help.c:5767 +#: sql_help.c:5800 msgid "remove a collation" msgstr "elimina un ordenamiento" -#: sql_help.c:5773 +#: sql_help.c:5806 msgid "remove a conversion" msgstr "elimina una conversión de codificación" -#: sql_help.c:5779 +#: sql_help.c:5812 msgid "remove a database" msgstr "elimina una base de datos" -#: sql_help.c:5785 +#: sql_help.c:5818 msgid "remove a domain" msgstr "elimina un dominio" -#: sql_help.c:5791 +#: sql_help.c:5824 msgid "remove an event trigger" msgstr "elimina un disparador por evento" -#: sql_help.c:5797 +#: sql_help.c:5830 msgid "remove an extension" msgstr "elimina una extensión" -#: sql_help.c:5803 +#: sql_help.c:5836 msgid "remove a foreign-data wrapper" msgstr "elimina un conector de datos externos" -#: sql_help.c:5809 +#: sql_help.c:5842 msgid "remove a foreign table" msgstr "elimina una tabla foránea" -#: sql_help.c:5815 +#: sql_help.c:5848 msgid "remove a function" msgstr "elimina una función" -#: sql_help.c:5821 sql_help.c:5887 sql_help.c:5989 +#: sql_help.c:5854 sql_help.c:5920 sql_help.c:6022 msgid "remove a database role" msgstr "elimina un rol de base de datos" -#: sql_help.c:5827 +#: sql_help.c:5860 msgid "remove an index" msgstr "elimina un índice" -#: sql_help.c:5833 +#: sql_help.c:5866 msgid "remove a procedural language" msgstr "elimina un lenguaje procedural" -#: sql_help.c:5839 +#: sql_help.c:5872 msgid "remove a materialized view" msgstr "elimina una vista materializada" -#: sql_help.c:5845 +#: sql_help.c:5878 msgid "remove an operator" msgstr "elimina un operador" -#: sql_help.c:5851 +#: sql_help.c:5884 msgid "remove an operator class" msgstr "elimina una clase de operadores" -#: sql_help.c:5857 +#: sql_help.c:5890 msgid "remove an operator family" msgstr "elimina una familia de operadores" -#: sql_help.c:5863 +#: sql_help.c:5896 msgid "remove database objects owned by a database role" msgstr "elimina objetos de propiedad de un rol de la base de datos" -#: sql_help.c:5869 +#: sql_help.c:5902 msgid "remove a row-level security policy from a table" msgstr "elimina una política de seguridad a nivel de registros de una tabla" -#: sql_help.c:5875 +#: sql_help.c:5908 msgid "remove a procedure" msgstr "elimina un procedimiento" -#: sql_help.c:5881 +#: sql_help.c:5914 msgid "remove a publication" msgstr "elimina una publicación" -#: sql_help.c:5893 +#: sql_help.c:5926 msgid "remove a routine" msgstr "elimina una rutina" -#: sql_help.c:5899 +#: sql_help.c:5932 msgid "remove a rewrite rule" msgstr "elimina una regla de reescritura" -#: sql_help.c:5905 +#: sql_help.c:5938 msgid "remove a schema" msgstr "elimina un esquema" -#: sql_help.c:5911 +#: sql_help.c:5944 msgid "remove a sequence" msgstr "elimina un generador secuencial" -#: sql_help.c:5917 +#: sql_help.c:5950 msgid "remove a foreign server descriptor" msgstr "elimina un descriptor de servidor foráneo" -#: sql_help.c:5923 +#: sql_help.c:5956 msgid "remove extended statistics" msgstr "elimina estadísticas extendidas" -#: sql_help.c:5929 +#: sql_help.c:5962 msgid "remove a subscription" msgstr "elimina una suscripción" -#: sql_help.c:5935 +#: sql_help.c:5968 msgid "remove a table" msgstr "elimina una tabla" -#: sql_help.c:5941 +#: sql_help.c:5974 msgid "remove a tablespace" msgstr "elimina un tablespace" -#: sql_help.c:5947 +#: sql_help.c:5980 msgid "remove a text search configuration" msgstr "elimina una configuración de búsqueda en texto" -#: sql_help.c:5953 +#: sql_help.c:5986 msgid "remove a text search dictionary" msgstr "elimina un diccionario de búsqueda en texto" -#: sql_help.c:5959 +#: sql_help.c:5992 msgid "remove a text search parser" msgstr "elimina un analizador de búsqueda en texto" -#: sql_help.c:5965 +#: sql_help.c:5998 msgid "remove a text search template" msgstr "elimina una plantilla de búsqueda en texto" -#: sql_help.c:5971 +#: sql_help.c:6004 msgid "remove a transform" msgstr "elimina una transformación" -#: sql_help.c:5977 +#: sql_help.c:6010 msgid "remove a trigger" msgstr "elimina un disparador" -#: sql_help.c:5983 +#: sql_help.c:6016 msgid "remove a data type" msgstr "elimina un tipo de datos" -#: sql_help.c:5995 +#: sql_help.c:6028 msgid "remove a user mapping for a foreign server" msgstr "elimina un mapeo de usuario para un servidor remoto" -#: sql_help.c:6001 +#: sql_help.c:6034 msgid "remove a view" msgstr "elimina una vista" -#: sql_help.c:6013 +#: sql_help.c:6046 msgid "execute a prepared statement" msgstr "ejecuta una sentencia preparada" -#: sql_help.c:6019 +#: sql_help.c:6052 msgid "show the execution plan of a statement" msgstr "muestra el plan de ejecución de una sentencia" -#: sql_help.c:6025 +#: sql_help.c:6058 msgid "retrieve rows from a query using a cursor" msgstr "recupera filas de una consulta usando un cursor" -#: sql_help.c:6031 +#: sql_help.c:6064 msgid "define access privileges" msgstr "define privilegios de acceso" -#: sql_help.c:6037 +#: sql_help.c:6070 msgid "import table definitions from a foreign server" msgstr "importa definiciones de tablas desde un servidor foráneo" -#: sql_help.c:6043 +#: sql_help.c:6076 msgid "create new rows in a table" msgstr "crea nuevas filas en una tabla" -#: sql_help.c:6049 +#: sql_help.c:6082 msgid "listen for a notification" msgstr "escucha notificaciones" -#: sql_help.c:6055 +#: sql_help.c:6088 msgid "load a shared library file" msgstr "carga un archivo de biblioteca compartida" -#: sql_help.c:6061 +#: sql_help.c:6094 msgid "lock a table" msgstr "bloquea una tabla" -#: sql_help.c:6067 +#: sql_help.c:6100 msgid "conditionally insert, update, or delete rows of a table" msgstr "condicionalmente inserta, actualiza o elimina filas de una tabla" -#: sql_help.c:6073 +#: sql_help.c:6106 msgid "position a cursor" msgstr "reposiciona un cursor" -#: sql_help.c:6079 +#: sql_help.c:6112 msgid "generate a notification" msgstr "genera una notificación" -#: sql_help.c:6085 +#: sql_help.c:6118 msgid "prepare a statement for execution" msgstr "prepara una sentencia para ejecución" -#: sql_help.c:6091 +#: sql_help.c:6124 msgid "prepare the current transaction for two-phase commit" msgstr "prepara la transacción actual para two-phase commit" -#: sql_help.c:6097 +#: sql_help.c:6130 msgid "change the ownership of database objects owned by a database role" msgstr "cambia de dueño a los objetos de propiedad de un rol de la base de datos" -#: sql_help.c:6103 +#: sql_help.c:6136 msgid "replace the contents of a materialized view" msgstr "reemplaza los contenidos de una vista materializada" -#: sql_help.c:6109 +#: sql_help.c:6142 msgid "rebuild indexes" msgstr "reconstruye índices" -#: sql_help.c:6115 +#: sql_help.c:6148 msgid "release a previously defined savepoint" msgstr "libera un “savepoint” definido previamente" -#: sql_help.c:6121 +#: sql_help.c:6154 msgid "restore the value of a run-time parameter to the default value" msgstr "restaura el valor de un parámetro de configuración al valor inicial" -#: sql_help.c:6127 +#: sql_help.c:6160 msgid "remove access privileges" msgstr "revoca privilegios de acceso" -#: sql_help.c:6139 +#: sql_help.c:6172 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "cancela una transacción que fue previamente preparada para two-phase commit" -#: sql_help.c:6145 +#: sql_help.c:6178 msgid "roll back to a savepoint" msgstr "descartar hacia un “savepoint”" -#: sql_help.c:6151 +#: sql_help.c:6184 msgid "define a new savepoint within the current transaction" msgstr "define un nuevo ”savepoint” en la transacción en curso" -#: sql_help.c:6157 +#: sql_help.c:6190 msgid "define or change a security label applied to an object" msgstr "define o cambia una etiqueta de seguridad sobre un objeto" -#: sql_help.c:6163 sql_help.c:6217 sql_help.c:6253 +#: sql_help.c:6196 sql_help.c:6250 sql_help.c:6286 msgid "retrieve rows from a table or view" msgstr "recupera filas desde una tabla o vista" -#: sql_help.c:6175 +#: sql_help.c:6208 msgid "change a run-time parameter" msgstr "cambia un parámetro de configuración" -#: sql_help.c:6181 +#: sql_help.c:6214 msgid "set constraint check timing for the current transaction" msgstr "define el modo de verificación de las restricciones de la transacción en curso" -#: sql_help.c:6187 +#: sql_help.c:6220 msgid "set the current user identifier of the current session" msgstr "define el identificador de usuario actual de la sesión actual" -#: sql_help.c:6193 +#: sql_help.c:6226 msgid "set the session user identifier and the current user identifier of the current session" msgstr "" "define el identificador del usuario de sesión y el identificador\n" "del usuario actual de la sesión en curso" -#: sql_help.c:6199 +#: sql_help.c:6232 msgid "set the characteristics of the current transaction" msgstr "define las características de la transacción en curso" -#: sql_help.c:6205 +#: sql_help.c:6238 msgid "show the value of a run-time parameter" msgstr "muestra el valor de un parámetro de configuración" -#: sql_help.c:6223 +#: sql_help.c:6256 msgid "empty a table or set of tables" msgstr "vacía una tabla o conjunto de tablas" -#: sql_help.c:6229 +#: sql_help.c:6262 msgid "stop listening for a notification" msgstr "deja de escuchar una notificación" -#: sql_help.c:6235 +#: sql_help.c:6268 msgid "update rows of a table" msgstr "actualiza filas de una tabla" -#: sql_help.c:6241 +#: sql_help.c:6274 msgid "garbage-collect and optionally analyze a database" msgstr "recolecta basura y opcionalmente estadísticas sobre una base de datos" -#: sql_help.c:6247 +#: sql_help.c:6280 msgid "compute a set of rows" msgstr "calcula un conjunto de registros" @@ -6464,7 +6541,7 @@ msgstr "se ignoró argumento extra «%s» en línea de órdenes" msgid "could not find own program executable" msgstr "no se pudo encontrar el ejecutable propio" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "" "tab completion query failed: %s\n" diff --git a/src/bin/psql/po/fr.po b/src/bin/psql/po/fr.po index 676d05a031a0f..1d5fb8c7b6ccc 100644 --- a/src/bin/psql/po/fr.po +++ b/src/bin/psql/po/fr.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-07-29 09:17+0000\n" -"PO-Revision-Date: 2023-09-05 09:52+0200\n" +"POT-Creation-Date: 2025-02-05 00:48+0000\n" +"PO-Revision-Date: 2025-02-05 09:06+0100\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -42,33 +42,48 @@ msgstr "détail : " msgid "hint: " msgstr "astuce : " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "binaire « %s » invalide : %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "n'a pas pu lire le binaire « %s » : %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "n'a pas pu trouver un « %s » à exécuter" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "n'a pas pu résoudre le chemin « %s » en sa forme absolue : %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "n'a pas pu exécuter la commande « %s » : %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "n'a pas pu lire à partir de la commande « %s » : %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "aucune donnée n'a été renvoyée par la commande « %s »" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "échec de %s() : %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -90,7 +105,7 @@ msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" msgid "could not look up effective user ID %ld: %s" msgstr "n'a pas pu trouver l'identifiant réel %ld de l'utilisateur : %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "l'utilisateur n'existe pas" @@ -129,11 +144,11 @@ msgstr "le processus fils a été terminé par le signal %d : %s" msgid "child process exited with unrecognized status %d" msgstr "le processus fils a quitté avec un statut %d non reconnu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Requête d'annulation envoyée\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "N'a pas pu envoyer la requête d'annulation : " @@ -149,316 +164,341 @@ msgstr[1] "(%lu lignes)" msgid "Interrupted\n" msgstr "Interrompu\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Ne peut pas afficher le contenu de la table : le nombre de cellules %lld est égal à ou dépasse le maximum %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "" "Ne peut pas ajouter l'en-tête au contenu de la table : le nombre de colonnes\n" "%d est dépassé.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" msgstr "" "Ne peut pas ajouter une cellule au contenu de la table : le nombre total des\n" -"cellules %d est dépassé.\n" +"cellules %lld est dépassé.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "format de sortie invalide (erreur interne) : %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "ignore l'expansion récursive de la variable « %s »" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "n'a pas pu rechercher l'identifiant de l'utilisateur local %d : %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "l'utilisateur local dont l'identifiant est %d n'existe pas" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "commande \\%s invalide" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "Essayez \\? pour l'aide." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s : argument « %s » supplémentaire ignoré" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "commande \\%s ignorée ; utilisez \\endif ou Ctrl-C pour quitter le bloc \\if courant" -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "n'a pas pu obtenir le répertoire principal pour l'identifiant d'utilisateur %ld : %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s : n'a pas pu accéder au répertoire « %s » : %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "Vous n'êtes pas connecté à une base de données.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Vous êtes connecté à la base de données « %s » en tant qu'utilisateur « %s » à l'adresse « %s » via le port « %s ».\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Vous êtes connecté à la base de données « %s » en tant qu'utilisateur « %s » via le socket dans « %s » via le port « %s ».\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Vous êtes connecté à la base de données « %s » en tant qu'utilisateur « %s » sur l'hôte « %s » (adresse « %s ») via le port « %s ».\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Vous êtes connecté à la base de données « %s » en tant qu'utilisateur « %s » sur l'hôte « %s » via le port « %s ».\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2675 #, c-format msgid "no query buffer" msgstr "aucun tampon de requête" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5776 #, c-format msgid "invalid line number: %s" msgstr "numéro de ligne invalide : %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "Aucun changement" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s : nom d'encodage invalide ou procédure de conversion introuvable" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:720 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5882 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1375 msgid "There is no previous error." msgstr "Il n'y a pas d'erreur précédente." -#: command.c:1470 +#: command.c:1488 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: parenthèse droite manquante" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 +#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 #, c-format msgid "\\%s: missing required argument" msgstr "\\%s : argument requis manquant" -#: command.c:1815 +#: command.c:1822 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif : ne peut pas survenir après \\else" -#: command.c:1820 +#: command.c:1827 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif : pas de \\if correspondant" -#: command.c:1884 +#: command.c:1891 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else : ne peut pas survenir après \\else" -#: command.c:1889 +#: command.c:1896 #, c-format msgid "\\else: no matching \\if" msgstr "\\else : pas de \\if correspondant" -#: command.c:1929 +#: command.c:1936 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif : pas de \\if correspondant" -#: command.c:2085 +#: command.c:2092 msgid "Query buffer is empty." msgstr "Le tampon de requête est vide." -#: command.c:2128 +#: command.c:2135 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Saisir le nouveau mot de passe de l'utilisateur « %s » : " -#: command.c:2132 +#: command.c:2139 msgid "Enter it again: " msgstr "Saisir le mot de passe à nouveau : " -#: command.c:2141 +#: command.c:2148 #, c-format msgid "Passwords didn't match." msgstr "Les mots de passe ne sont pas identiques." -#: command.c:2238 +#: command.c:2231 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s : n'a pas pu lire la valeur pour la variable" -#: command.c:2340 +#: command.c:2333 msgid "Query buffer reset (cleared)." msgstr "Le tampon de requête a été effacé." -#: command.c:2362 +#: command.c:2355 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "Historique sauvegardé dans le fichier « %s ».\n" -#: command.c:2449 +#: command.c:2442 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s : le nom de la variable d'environnement ne doit pas contenir « = »" -#: command.c:2497 +#: command.c:2490 #, c-format msgid "function name is required" msgstr "le nom de la fonction est requis" -#: command.c:2499 +#: command.c:2492 #, c-format msgid "view name is required" msgstr "le nom de la vue est requis" -#: command.c:2621 +#: command.c:2614 msgid "Timing is on." msgstr "Chronométrage activé." -#: command.c:2623 +#: command.c:2616 msgid "Timing is off." msgstr "Chronométrage désactivé." -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 +#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 +#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s : %m" -#: command.c:2736 copy.c:388 +#: command.c:2729 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s : %s" -#: command.c:2806 command.c:2852 +#: command.c:2801 command.c:2867 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch : la valeur d'intervalle est spécifiée plus d'une fois" -#: command.c:2816 command.c:2862 +#: command.c:2811 command.c:2877 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch : valeur d'intervalle incorrecte « %s »" -#: command.c:2826 +#: command.c:2821 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: le nombre d'itération est spécifié plus d'une fois" -#: command.c:2836 +#: command.c:2831 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch : nombre d'itération incorrect « %s »" -#: command.c:2843 +#: command.c:2841 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: nombre de lignes minimum spécifié plus d'une fois" + +#: command.c:2851 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch : nombre de lignes minimum incorrect « %s »" + +#: command.c:2858 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch : paramètre « %s » non reconnu" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3255 startup.c:243 startup.c:293 msgid "Password: " msgstr "Mot de passe : " -#: command.c:3241 startup.c:290 +#: command.c:3260 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "Mot de passe pour l'utilisateur %s : " -#: command.c:3297 +#: command.c:3316 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "Ne pas donner utilisateur, hôte ou port lors de l'utilisation d'une chaîne de connexion" -#: command.c:3332 +#: command.c:3351 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "Aucune connexion de base existante pour réutiliser ses paramètres" -#: command.c:3638 +#: command.c:3658 #, c-format msgid "Previous connection kept" msgstr "Connexion précédente conservée" -#: command.c:3644 +#: command.c:3664 #, c-format msgid "\\connect: %s" msgstr "\\connect : %s" -#: command.c:3700 +#: command.c:3720 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Vous êtes maintenant connecté à la base de données « %s » en tant qu'utilisateur « %s » à l'adresse « %s » via le port « %s ».\n" -#: command.c:3703 +#: command.c:3723 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Vous êtes maintenant connecté à la base de données « %s » en tant qu'utilisateur « %s » via le socket dans « %s » via le port « %s ».\n" -#: command.c:3709 +#: command.c:3729 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Vous êtes maintenant connecté à la base de données « %s » en tant qu'utilisateur « %s » sur l'hôte « %s » (adresse « %s » ) via le port « %s ».\n" -#: command.c:3712 +#: command.c:3732 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Vous êtes maintenant connecté à la base de données « %s » en tant qu'utilisateur « %s » sur l'hôte « %s » via le port « %s ».\n" -#: command.c:3717 +#: command.c:3737 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Vous êtes maintenant connecté à la base de données « %s » en tant qu'utilisateur « %s ».\n" -#: command.c:3757 +#: command.c:3843 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, serveur %s)\n" -#: command.c:3770 +#: command.c:3856 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -467,29 +507,33 @@ msgstr "" "ATTENTION : %s version majeure %s, version majeure du serveur %s.\n" " Certaines fonctionnalités de psql pourraient ne pas fonctionner.\n" -#: command.c:3807 +#: command.c:3895 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "Connexion SSL (protocole : %s, chiffrement : %s, compression : %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "Connexion SSL (protocole : %s, chiffrement : %s, compression : %s, ALPN : %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3896 command.c:3897 msgid "unknown" msgstr "inconnu" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "off" msgstr "désactivé" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "on" msgstr "activé" -#: command.c:3824 +#: command.c:3899 +msgid "none" +msgstr "aucun" + +#: command.c:3913 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "connexion chiffrée avec GSSAPI\n" -#: command.c:3844 +#: command.c:3933 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -501,289 +545,289 @@ msgstr "" " Voir la section « Notes aux utilisateurs de Windows » de la page\n" " référence de psql pour les détails.\n" -#: command.c:3949 +#: command.c:4038 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "la variable d'environnement PSQL_EDITOR_LINENUMBER_ARG doit être définie avec un numéro de ligne" -#: command.c:3979 +#: command.c:4068 #, c-format msgid "could not start editor \"%s\"" msgstr "n'a pas pu exécuter l'éditeur « %s »" -#: command.c:3981 +#: command.c:4070 #, c-format msgid "could not start /bin/sh" msgstr "n'a pas pu exécuter /bin/sh" -#: command.c:4031 +#: command.c:4120 #, c-format msgid "could not locate temporary directory: %s" msgstr "n'a pas pu localiser le répertoire temporaire : %s" -#: command.c:4058 +#: command.c:4147 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "n'a pas pu ouvrir le fichier temporaire « %s » : %m" -#: command.c:4394 +#: command.c:4483 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" -msgstr "\\pset: abréviation ambigüe : « %s » correspond à « %s » comme à « %s »" +msgstr "\\pset: abréviation ambiguë : « %s » correspond à « %s » comme à « %s »" -#: command.c:4414 +#: command.c:4503 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset : les formats autorisés sont aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4522 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: les styles de lignes autorisés sont ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4537 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset : les styles autorisés de ligne de bordure Unicode sont single, double" -#: command.c:4463 +#: command.c:4552 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset : les styles autorisés pour la ligne de colonne Unicode sont single, double" -#: command.c:4478 +#: command.c:4567 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset : les styles autorisés pour la ligne d'en-tête Unicode sont single, double" -#: command.c:4530 +#: command.c:4619 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: les valeurs acceptées pour xheader_width sont « %s » (par défaut), « %s », « %s » ou un nombre indiquant la largeur exacte" -#: command.c:4547 +#: command.c:4636 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep doit être un unique caractère d'un octet" -#: command.c:4552 +#: command.c:4641 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldsep ne peut pas être un guillemet, un retour à la ligne ou un retour chariot" -#: command.c:4690 command.c:4891 +#: command.c:4779 command.c:4980 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset : option inconnue : %s" -#: command.c:4710 +#: command.c:4799 #, c-format msgid "Border style is %d.\n" msgstr "Le style de bordure est %d.\n" -#: command.c:4716 +#: command.c:4805 #, c-format msgid "Target width is unset.\n" msgstr "La largeur cible n'est pas configuré.\n" -#: command.c:4718 +#: command.c:4807 #, c-format msgid "Target width is %d.\n" msgstr "La largeur cible est %d.\n" -#: command.c:4725 +#: command.c:4814 #, c-format msgid "Expanded display is on.\n" msgstr "Affichage étendu activé.\n" -#: command.c:4727 +#: command.c:4816 #, c-format msgid "Expanded display is used automatically.\n" msgstr "L'affichage étendu est utilisé automatiquement.\n" -#: command.c:4729 +#: command.c:4818 #, c-format msgid "Expanded display is off.\n" msgstr "Affichage étendu désactivé.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4825 command.c:4827 command.c:4829 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "La largeur étendue de l'entête est « %s ».\n" -#: command.c:4742 +#: command.c:4831 #, c-format msgid "Expanded header width is %d.\n" msgstr "La largeur étendue de l'entête est %d.\n" -#: command.c:4748 +#: command.c:4837 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "Le séparateur de champs pour un CSV est « %s ».\n" -#: command.c:4756 command.c:4764 +#: command.c:4845 command.c:4853 #, c-format msgid "Field separator is zero byte.\n" msgstr "Le séparateur de champs est l'octet zéro.\n" -#: command.c:4758 +#: command.c:4847 #, c-format msgid "Field separator is \"%s\".\n" msgstr "Le séparateur de champs est « %s ».\n" -#: command.c:4771 +#: command.c:4860 #, c-format msgid "Default footer is on.\n" msgstr "Le bas de page pas défaut est activé.\n" -#: command.c:4773 +#: command.c:4862 #, c-format msgid "Default footer is off.\n" msgstr "Le bas de page par défaut est désactivé.\n" -#: command.c:4779 +#: command.c:4868 #, c-format msgid "Output format is %s.\n" msgstr "Le format de sortie est %s.\n" -#: command.c:4785 +#: command.c:4874 #, c-format msgid "Line style is %s.\n" msgstr "Le style de ligne est %s.\n" -#: command.c:4792 +#: command.c:4881 #, c-format msgid "Null display is \"%s\".\n" msgstr "L'affichage de null est « %s ».\n" -#: command.c:4800 +#: command.c:4889 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "L'affichage de la sortie numérique adaptée à la locale est activé.\n" -#: command.c:4802 +#: command.c:4891 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "L'affichage de la sortie numérique adaptée à la locale est désactivé.\n" -#: command.c:4809 +#: command.c:4898 #, c-format msgid "Pager is used for long output.\n" msgstr "Le paginateur est utilisé pour les affichages longs.\n" -#: command.c:4811 +#: command.c:4900 #, c-format msgid "Pager is always used.\n" msgstr "Le paginateur est toujours utilisé.\n" -#: command.c:4813 +#: command.c:4902 #, c-format msgid "Pager usage is off.\n" msgstr "L'utilisation du paginateur est désactivé.\n" -#: command.c:4819 +#: command.c:4908 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "Le paginateur ne sera pas utilisé pour moins que %d ligne.\n" msgstr[1] "Le paginateur ne sera pas utilisé pour moins que %d lignes.\n" -#: command.c:4829 command.c:4839 +#: command.c:4918 command.c:4928 #, c-format msgid "Record separator is zero byte.\n" msgstr "Le séparateur d'enregistrements est l'octet zéro.\n" -#: command.c:4831 +#: command.c:4920 #, c-format msgid "Record separator is .\n" msgstr "Le séparateur d'enregistrement est .\n" -#: command.c:4833 +#: command.c:4922 #, c-format msgid "Record separator is \"%s\".\n" msgstr "Le séparateur d'enregistrements est « %s ».\n" -#: command.c:4846 +#: command.c:4935 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Les attributs de la table sont « %s ».\n" -#: command.c:4849 +#: command.c:4938 #, c-format msgid "Table attributes unset.\n" msgstr "Les attributs de la table ne sont pas définis.\n" -#: command.c:4856 +#: command.c:4945 #, c-format msgid "Title is \"%s\".\n" msgstr "Le titre est « %s ».\n" -#: command.c:4858 +#: command.c:4947 #, c-format msgid "Title is unset.\n" msgstr "Le titre n'est pas défini.\n" -#: command.c:4865 +#: command.c:4954 #, c-format msgid "Tuples only is on.\n" msgstr "L'affichage des tuples seuls est activé.\n" -#: command.c:4867 +#: command.c:4956 #, c-format msgid "Tuples only is off.\n" msgstr "L'affichage des tuples seuls est désactivé.\n" -#: command.c:4873 +#: command.c:4962 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Le style de bordure Unicode est « %s ».\n" -#: command.c:4879 +#: command.c:4968 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Le style de ligne Unicode est « %s ».\n" -#: command.c:4885 +#: command.c:4974 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Le style d'en-tête Unicode est « %s ».\n" -#: command.c:5134 +#: command.c:5223 #, c-format msgid "\\!: failed" msgstr "\\! : échec" -#: command.c:5168 +#: command.c:5261 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch ne peut pas être utilisé avec une requête vide" -#: command.c:5200 +#: command.c:5293 #, c-format msgid "could not set timer: %m" msgstr "n'a pas pu configurer le chronomètre : %m" -#: command.c:5269 +#: command.c:5362 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (chaque %gs)\n" -#: command.c:5272 +#: command.c:5365 #, c-format msgid "%s (every %gs)\n" msgstr "%s (chaque %gs)\n" -#: command.c:5340 +#: command.c:5429 #, c-format msgid "could not wait for signals: %m" msgstr "n'a pas pu attendre le signal : %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5485 command.c:5492 common.c:632 common.c:639 common.c:1123 #, c-format msgid "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" msgstr "" "******** REQUÊTE *********\n" @@ -791,147 +835,152 @@ msgstr "" "**************************\n" "\n" -#: command.c:5584 +#: command.c:5671 #, c-format msgid "\"%s.%s\" is not a view" msgstr "« %s.%s » n'est pas une vue" -#: command.c:5600 +#: command.c:5687 #, c-format msgid "could not parse reloptions array" msgstr "n'a pas pu analyser le tableau reloptions" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "ne peut mettre entre guillemets sans connexion active" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "la connexion au serveur a été perdue" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "La connexion au serveur a été perdue. Tentative de réinitialisation : " -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "Échec.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "Succès.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "PQresultStatus inattendu : %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "Temps : %.3f ms\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Durée : %.3f ms (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Durée : %.3f ms (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Durée : %.3f ms (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "Vous n'êtes pas connecté à une base de données." -#: common.c:674 +#: common.c:714 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "" "Notification asynchrone « %s » reçue avec le contenu « %s » en provenance du\n" "processus serveur de PID %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "" "Notification asynchrone « %s » reçue en provenance du processus serveur de\n" "PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "n'a pas pu imprimer la table résultante : %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "aucune ligne retournée pour \\gset" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "plus d'une ligne retournée pour \\gset" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "tentative ignorée d'utilisation de \\gset dans une variable traitée spécialement « %s »" -#: common.c:1063 +#: common.c:1103 #, c-format msgid "" -"***(Single step mode: verify command)*******************************************\n" +"/**(Single step mode: verify command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to cancel)********************\n" +"/**(press return to proceed or enter x and return to cancel)*******************/\n" msgstr "" "***(Mode étape par étape: vérifiez la commande)*********************************\n" "%s\n" "***(appuyez sur entrée pour l'exécuter ou tapez x puis entrée pour annuler)***\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "INSTRUCTION : %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "état de la transaction inattendu (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "Colonne" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "Type" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "La commande n'a pas de résultats ou le résultat n'a pas de colonnes.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "échec de la récupération des résultats en mode par morceau" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -947,11 +996,6 @@ msgstr "\\copy : erreur d'analyse sur « %s »" msgid "\\copy: parse error at end of line" msgstr "\\copy : erreur d'analyse à la fin de la ligne" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "n'a pas pu exécuter la commande « %s » : %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -989,338 +1033,339 @@ msgstr "" "Saisissez les données à copier suivies d'un saut de ligne.\n" "Terminez avec un antislash et un point seuls sur une ligne ou un signal EOF." -#: copy.c:682 +#: copy.c:684 msgid "aborted because of read failure" msgstr "annulé du fait d'une erreur de lecture" -#: copy.c:716 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "tente de sortir du mode copy" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview : la commande n'a pas retourné d'ensemble de résultats" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview : la requête doit renvoyer au moins trois colonnes" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "\\crosstabview: vertical and horizontal headers must be different columns" msgstr "\\crosstabview : les en-têtes horizontales et verticales doivent être des colonnes différentes" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "\\crosstabview: data column must be specified when query returns more than three columns" msgstr "\\crosstabview : la colonne de données doit être spécifiée quand la requête retourne plus de trois colonnes" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview : nombre maximum de colonnes (%d) dépassé" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"" msgstr "\\crosstabview : le résultat de la requête contient plusieurs valeurs de données pour la ligne « %s », colonne « %s »" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview : le numéro de colonne %d est en dehors des limites 1..%d" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview : nom de colonne ambigu : « %s »" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview : nom de colonne non trouvé : « %s »" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "Schéma" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "Nom" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "Type de données du résultat" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "Type de données des paramètres" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "Description" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "Liste des fonctions d'agrégation" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "Le serveur (version %s) ne supporte pas les méthodes d'accès." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "Index" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "Table" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "Gestionnaire" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "Liste des méthodes d'accès" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "Propriétaire" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "Emplacement" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "Options" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "Taille" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "Liste des tablespaces" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df ne prend que [anptwS+] comme options" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df ne prend pas d'option « %c » pour un serveur en version %s" #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "agg" -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "window" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "proc" -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "func" -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "trigger" -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "immutable" -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "stable" -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "volatile" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "Volatibilité" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "restricted" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "safe" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "unsafe" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "Parallèle" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "definer" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "invoker" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "Sécurité" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "Langage" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "Nom interne" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "Liste des fonctions" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "Éléments" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "Liste des types de données" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "Type de l'arg. gauche" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "Type de l'arg. droit" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "Type du résultat" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "Fonction" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "Liste des opérateurs" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "Encodage" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "Fournisseur de locale" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "Collationnement" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "Type caract." -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "Locale ICU" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "Locale" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "Règles ICU :" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "Tablespace" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "Liste des bases de données" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "table" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "vue" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "vue matérialisée" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "séquence" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "table distante" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "table partitionnée" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "Droits d'accès à la colonne" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "Politiques" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "Droits d'accès" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "fonction" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "type" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "schéma" @@ -1352,293 +1397,293 @@ msgstr "famille d'opérateur" msgid "rule" msgstr "règle" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "Descriptions des objets" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "Aucune relation nommée « %s » n'a été trouvée." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "Aucune relation n'a été trouvée." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "Aucune relation avec l'OID « %s » n'a été trouvée." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "Début" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "Minimum" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "Maximum" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "Incrément" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "oui" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "non" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "Cycles ?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "Cache" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "Propriétaire : %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "Séquence pour la colonne d'identité : %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Séquence non journalisée « %s.%s »" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Séquence « %s.%s »" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Table non tracée « %s.%s »" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "Table « %s.%s »" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "Vue « %s.%s »" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "Vue matérialisée non journalisée « %s.%s »" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Vue matérialisée « %s.%s »" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Index non tracé « %s.%s »" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "Index « %s.%s »" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Index partitionné non journalisé « %s.%s »" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Index partitionné « %s.%s »" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "Table TOAST « %s.%s »" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Type composé « %s.%s »" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Table distante « %s.%s »" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Table non journalisée « %s.%s »" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Table partitionnée « %s.%s »" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "Collationnement" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "NULL-able" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "Par défaut" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "Clé ?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "Définition" -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "Options FDW" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "Stockage" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "Compression" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "Cible de statistiques" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "Partition de : %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "Aucune contrainte de partition" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "Contrainte de partition : %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "Clé de partition : %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Table propriétaire : « %s.%s »" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "clé primaire, " -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "unique" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " nulls non distincts" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr " , " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "pour la table « %s.%s »" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", prédicat (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", en cluster" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", invalide" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", déferrable" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", initialement déferré" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", identité réplica" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "Index :" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "Contraintes de vérification :" -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "Contraintes de clés étrangères :" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "Référencé par :" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "Politiques :" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "Politiques (mode sécurité de ligne activé en forcé) :" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "Politiques (mode sécurité de ligne activé) : (aucune)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "Politiques (mode sécurité de ligne activé en forcé) : (aucune)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "Politiques (mode sécurité de ligne désactivé) :" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "Objets statistiques :" @@ -1652,13 +1697,13 @@ msgstr "Règles désactivées :" #: describe.c:2949 msgid "Rules firing always:" -msgstr "Règles toujous activées :" +msgstr "Règles toujours activées :" #: describe.c:2952 msgid "Rules firing on replica only:" msgstr "Règles activées uniquement sur le réplica :" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "Publications :" @@ -1757,7 +1802,7 @@ msgstr ", tablespace « %s »" msgid "List of roles" msgstr "Liste des rôles" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "Nom du rôle" @@ -1835,368 +1880,368 @@ msgstr "Aucune configuration pour le rôle « %s » n'a été trouvée." msgid "Did not find any settings." msgstr "Aucune configuration n'a été trouvée." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "Liste des paramètres" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "Membre de" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "Donneur de droits" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "Liste des droits de rôles" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "index" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "Table TOAST" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "index partitionné" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "permanent" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "temporaire" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "non journalisé" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "Persistence" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "Méthode d'accès" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "Liste des relations" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "Le serveur (version %s) ne supporte pas le partitionnement déclaratif des tables." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "Liste des index partitionnés" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "Liste des tables partitionnées" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "Liste des relations partitionnées" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "Nom du parent" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "Taille de la partition de dernier niveau" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "Taille totale" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "De confiance" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "Langage interne" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "Gestionnaire d'appel" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "Validateur" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "Gestionnaire en ligne" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "Liste des langages" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "Vérification" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "Liste des domaines" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "Source" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "Destination" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "Par défaut ?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "Liste des conversions" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "Paramètre" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "Valeur" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "Contexte" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "Liste des paramètres de configuration" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "Liste des paramètres de configuration à valeur personnalisée" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "Le serveur (version %s) ne supporte pas les triggers d'événement." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "Événement" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "activé" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "réplicat" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "toujours" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "désactivé" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "Activé" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "Tags" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "Liste des triggers sur évènement" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "Le serveur (version %s) ne supporte pas les statistiques étendues." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Dépendances" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "Liste des statistiques étendues" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Type source" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Type cible" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "assigné" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Implicite ?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "Liste des conversions explicites" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "Fournisseur" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "Déterministe ?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "Liste des collationnements" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "Liste des schémas" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "Liste des analyseurs de la recherche de texte" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "Aucun analyseur de la recherche de texte nommé « %s » n'a été trouvé." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "Aucun analyseur de recherche de texte n'a été trouvé." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "Début de l'analyse" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "Méthode" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "Obtenir le prochain jeton" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "Fin de l'analyse" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "Obtenir l'en-tête" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "Obtenir les types de jeton" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Analyseur « %s.%s » de la recherche de texte" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "Analyseur « %s » de la recherche de texte" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "Nom du jeton" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Types de jeton pour l'analyseur « %s.%s »" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "Types de jeton pour l'analyseur « %s »" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "Modèle" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "Options d'initialisation" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "Liste des dictionnaires de la recherche de texte" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "Initialisation" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Lexize" -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "Liste des modèles de la recherche de texte" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "Liste des configurations de la recherche de texte" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "Aucune configuration de la recherche de texte nommée « %s » n'a été trouvée." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "Aucune configuration de recherche de texte n'a été trouvée." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "Jeton" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "Dictionnaires" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Configuration « %s.%s » de la recherche de texte" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "Configuration « %s » de la recherche de texte" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "" "\n" @@ -2205,7 +2250,7 @@ msgstr "" "\n" "Analyseur : « %s.%s »" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "" "\n" @@ -2214,265 +2259,273 @@ msgstr "" "\n" "Analyseur : « %s »" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "Liste des wrappers de données distantes" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "Wrapper des données distantes" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "Version" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "Liste des serveurs distants" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "Serveur" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "Nom de l'utilisateur" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "Liste des correspondances utilisateurs" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "Liste des tables distantes" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "Liste des extensions installées" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "Aucune extension nommée « %s » n'a été trouvée." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "Aucune extension n'a été trouvée." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "Description d'objet" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "Objets dans l'extension « %s »" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "mauvaise qualification du nom (trop de points entre les noms) : %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "les références entre bases de données ne sont pas implémentées : %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "Le serveur (version %s) ne supporte pas les publications." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "Toutes les tables" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Insertions" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Mises à jour" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Suppressions" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Tronque" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Via la racine" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "Liste des publications" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "Aucune publication nommée « %s » n'a été trouvée." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "Aucune publication n'a été trouvée." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "Publication %s" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "Tables :" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "Tables des schémas :" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "Le serveur (version %s) ne supporte pas les souscriptions." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "Publication" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "Binaire" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "Flux" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "Commit en deux phases" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "Désactiver en cas d'erreur" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "Origine" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "Mot de passe requis" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "Exécuté en tant que propriétaire ?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "Failover" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "Validation synchrone" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "Informations de connexion" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "Ignore LSN" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "Liste des souscriptions" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(aucun)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "AM" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "Type en entrée" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "Type de stockage" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "Classe d'opérateur" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "Famille d'opérateur" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "Liste des classes d'opérateurs" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Types applicables" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "Liste des familles d'opérateurs" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "Opérateur" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "Stratégie" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "ordre" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "recherche" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "But" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "Tri famille d'opérateur" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "Liste d'opérateurs des familles d'opérateurs" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "Type de l'arg. gauche enregistré" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "Type de l'arg. droit enregistré" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "Numéro" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "Liste des fonctions de support des familles d'opérateurs" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "« Large objects »" -#: help.c:75 +#: help.c:63 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2480,11 +2533,11 @@ msgstr "" "psql est l'interface interactive de PostgreSQL.\n" "\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:502 msgid "Usage:\n" msgstr "Usage :\n" -#: help.c:77 +#: help.c:65 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2492,32 +2545,29 @@ msgstr "" " psql [OPTIONS]... [BASE [UTILISATEUR]]\n" "\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "Options générales :\n" -#: help.c:84 +#: help.c:68 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr "" " -c, --command=COMMANDE exécute une commande unique (SQL ou interne), puis\n" " quitte\n" -#: help.c:85 -#, c-format -msgid " -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr "" -" -d, --dbname=BASE indique le nom de la base de données à laquelle se\n" -" connecter (par défaut : « %s »)\n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=BASE base de données de connexion\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=FICHIER exécute les commandes du fichier, puis quitte\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list affiche les bases de données disponibles, puis quitte\n" -#: help.c:89 +#: help.c:72 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2527,15 +2577,15 @@ msgstr "" " configure la variable psql NOM en VALEUR\n" " (par exemple : -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc ne lit pas le fichier de démarrage (~/.psqlrc)\n" -#: help.c:94 +#: help.c:77 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" @@ -2544,19 +2594,19 @@ msgstr "" " exécute dans une transaction unique (si non\n" " interactif)\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=options] affiche cette aide et quitte\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commandes liste les méta-commandes, puis quitte\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables liste les variables spéciales, puis quitte\n" -#: help.c:100 +#: help.c:83 msgid "" "\n" "Input and output options:\n" @@ -2564,79 +2614,79 @@ msgstr "" "\n" "Options d'entrée/sortie :\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all affiche les lignes du script\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors affiche les commandes échouées\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries affiche les commandes envoyées au serveur\n" -#: help.c:104 +#: help.c:87 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr "" " -E, --echo-hidden affiche les requêtes engendrées par les commandes\n" " internes\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=FICHIER envoie les traces dans le fichier\n" -#: help.c:106 +#: help.c:89 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr "" " -n, --no-readline désactive l'édition avancée de la ligne de commande\n" " (readline)\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr "" " -o, --output=FICHIER écrit les résultats des requêtes dans un fichier (ou\n" " |tube)\n" -#: help.c:108 +#: help.c:91 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr "" " -q, --quiet s'exécute silencieusement (pas de messages, uniquement\n" " le résultat des requêtes)\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr "" " -s, --single-step active le mode étape par étape (confirmation pour\n" " chaque requête)\n" -#: help.c:110 +#: help.c:93 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr "" " -S, --single-line active le mode ligne par ligne (EOL termine la\n" " commande SQL)\n" -#: help.c:112 +#: help.c:95 msgid "" "\n" "Output format options:\n" msgstr "" "\n" -"Options de formattage de la sortie :\n" +"Options de formatage de la sortie :\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr "" " -A, --no-align active le mode d'affichage non aligné des tables\n" " (-P format=unaligned)\n" -#: help.c:114 +#: help.c:97 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr "" " --csv mode d'affichage CSV (valeurs séparées par des\n" " virgules)\n" -#: help.c:115 +#: help.c:98 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2646,19 +2696,19 @@ msgstr "" " séparateur de champs pour un affichage non aligné\n" " (par défaut : « %s »)\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr "" " -H, --html active le mode d'affichage HTML des tables\n" " (-P format=html)\n" -#: help.c:119 +#: help.c:102 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr "" " -P, --pset=VAR[=ARG] initialise l'option d'impression VAR à ARG (voir la\n" " commande \\pset)\n" -#: help.c:120 +#: help.c:103 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" @@ -2667,21 +2717,21 @@ msgstr "" " séparateur d'enregistrements pour un affichage non\n" " aligné (par défaut : saut de ligne)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only affiche seulement les lignes (-P tuples_only)\n" -#: help.c:123 +#: help.c:106 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr "" " -T, --table-attr=TEXTE initialise les attributs des balises HTML de tableau\n" " (largeur, bordure)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded active l'affichage étendu des tables (-P expanded)\n" -#: help.c:125 +#: help.c:108 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" @@ -2690,7 +2740,7 @@ msgstr "" " initialise le séparateur de champs pour un affichage\n" " non aligné à l'octet zéro\n" -#: help.c:127 +#: help.c:110 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" @@ -2699,7 +2749,7 @@ msgstr "" " initialise le séparateur d'enregistrements pour un\n" " affichage non aligné à l'octet zéro\n" -#: help.c:130 +#: help.c:113 msgid "" "\n" "Connection options:\n" @@ -2707,43 +2757,31 @@ msgstr "" "\n" "Options de connexion :\n" -#: help.c:133 -#, c-format -msgid " -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=HÔTE nom d'hôte du serveur de la base de données ou\n" -" répertoire de la socket (par défaut : %s)\n" +" -h, --host=HÔTE hôte du serveur de bases de données ou\n" +" répertoire des sockets\n" -#: help.c:134 -msgid "local socket" -msgstr "socket locale" - -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr "" -" -p, --port=PORT port du serveur de la base de données (par défaut :\n" -" « %s »)\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PORT port du serveur de bases de données\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr "" -" -U, --username=UTILISATEUR\n" -" nom d'utilisateur de la base de données (par\n" -" défaut : « %s »)\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=NOM nom de l'utilisateur de la base de données\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ne demande jamais un mot de passe\n" -#: help.c:143 +#: help.c:118 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr "" " -W, --password force la demande du mot de passe (devrait survenir\n" " automatiquement)\n" -#: help.c:145 +#: help.c:120 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" @@ -2757,39 +2795,39 @@ msgstr "" "la documentation de PostgreSQL.\n" "\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapporter les bogues à <%s>.\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "Général\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [PARAM]... configure les paramètres de la requête\n" -#: help.c:193 +#: help.c:168 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr "" " \\copyright affiche les conditions d'utilisation et de\n" " distribution de PostgreSQL\n" -#: help.c:194 +#: help.c:169 msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr " \\crosstabview [COLONNES] exécute la requête et affiche le résultat dans un tableau croisé\n" -#: help.c:195 +#: help.c:170 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose affiche le message d'erreur le plus récent avec une verbosité maximale\n" -#: help.c:196 +#: help.c:171 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2797,252 +2835,258 @@ msgstr "" " \\g [(OPTIONS)] [FICHIER] exécute la requête (et envoie les résultats à un fichier ou à |pipe);\n" " \\g sans arguments est équivalent à un point-virgule\n" -#: help.c:198 +#: help.c:173 msgid " \\gdesc describe result of query, without executing it\n" msgstr " \\gdesc décrit le résultat de la requête sans l'exécuter\n" -#: help.c:199 +#: help.c:174 msgid " \\gexec execute query, then execute each value in its result\n" msgstr " \\gexec exécute la requête et exécute chaque valeur du résultat\n" -#: help.c:200 +#: help.c:175 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr " \\gset [PRÉFIXE] exécute la requête et enregistre le résultat dans des variables psql\n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr " \\gx [(OPTIONS)] [FICHIER] comme \\g, mais force le mode de sortie étendu\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q quitte psql\n" -#: help.c:203 -msgid " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" -msgstr " \\watch [[i=]SEC] [c=N] exécute la requête toutes les SEC secondes, jusqu'à N fois\n" +#: help.c:178 +msgid "" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" +msgstr "" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" exécute la requête chaque SEC secondes, jusqu'à N fois,\n" +" s'arrête si moins de MIN lignes sont renvoyés\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "Aide\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commandes] affiche l'aide sur les métacommandes\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options affiche l'aide sur les options en ligne de commande de psql\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables affiche l'aide sur les variables spéciales\n" -#: help.c:211 +#: help.c:188 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr "" " \\h [NOM] aide-mémoire pour les commandes SQL, * pour toutes\n" " les commandes\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "Tampon de requête\n" -#: help.c:215 +#: help.c:192 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr "" " \\e [FICHIER] [LIGNE] édite le tampon de requête ou le fichier avec un\n" " éditeur externe\n" -#: help.c:216 +#: help.c:193 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr "" " \\ef [FONCTION [LIGNE]] édite la définition de fonction avec un éditeur\n" " externe\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr "" " \\ev [VUE [LIGNE]] édite la définition de vue avec un éditeur\n" " externe\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p affiche le contenu du tampon de requête\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r efface le tampon de requêtes\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr "" " \\s [FICHIER] affiche l'historique ou le sauvegarde dans un\n" " fichier\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr "" " \\w [FICHIER] écrit le contenu du tampon de requêtes dans un\n" " fichier\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "Entrée/Sortie\n" -#: help.c:227 +#: help.c:204 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr "" " \\copy ... exécute SQL COPY avec le flux de données dirigé vers\n" " l'hôte client\n" -#: help.c:228 +#: help.c:205 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [TEXTE] écrit le texte sur la sortie standard (-n pour supprimer le retour à la ligne)\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i FICHIER exécute les commandes du fichier\n" -#: help.c:230 +#: help.c:207 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr "" " \\ir FICHIER identique à \\i, mais relatif à l'emplacement du script\n" " ou un |tube\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr "" " \\o [FICHIER] envoie les résultats de la requête vers un fichier\n" " ou un |tube\n" -#: help.c:232 +#: help.c:209 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr "" " \\qecho [-n] [TEXTE] écrit un texte sur la sortie des résultats des\n" " requêtes (\\o) (-n pour supprimer le retour à la ligne)\n" -#: help.c:233 +#: help.c:210 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr " \\warn [-n] [TEXTE] écrit le texte sur la sortie des erreurs (-n pour supprimer le retour à la ligne)\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "Conditionnel\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPR début du bloc conditionnel\n" -#: help.c:238 +#: help.c:215 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif alternative à l'intérieur du bloc conditionnel courant\n" -#: help.c:239 +#: help.c:216 msgid " \\else final alternative within current conditional block\n" msgstr " \\else alternative finale à l'intérieur du bloc conditionnel courant\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif bloc conditionnel de fin\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "Informations\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr " (options : S = affiche les objets systèmes, + = informations supplémentaires)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr " \\d[S+] affiche la liste des tables, vues et séquences\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr "" " \\d[S+] NOM affiche la description de la table, de la vue,\n" " de la séquence ou de l'index\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" -msgstr " \\da[S] [MODÈLE] affiche les aggrégats\n" +msgstr " \\da[S] [MODÈLE] affiche les agrégats\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [MODÈLE] affiche la liste des méthodes d'accès\n" -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] affiche les classes d'opérateurs\n" -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] affiche les familles d'opérateur\n" -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] affiche les opérateurs des familles d'opérateur\n" -#: help.c:252 +#: help.c:229 msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] liste les fonctions de support des familles d'opérateur\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [MODÈLE] affiche la liste des tablespaces\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [MODÈLE] affiche la liste des conversions\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [MODÈLE] affiche les paramètres de configuration\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [MODÈLE] affiche la liste des transtypages\n" -#: help.c:257 +#: help.c:234 msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr "" " \\dd[S] [MODÈLE] affiche les commentaires des objets dont le commentaire\n" " n'est affiché nul part ailleurs\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [MODÈLE] affiche la liste des domaines\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [MODÈLE] affiche les droits par défaut\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [MODÈLE] affiche la liste des tables distantes\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [MODÈLE] affiche la liste des serveurs distants\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\det[+] [MODÈLE] affiche la liste des tables distantes\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [MODÈLE] affiche la liste des correspondances utilisateurs\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [MODÈLE] affiche la liste des wrappers de données distantes\n" -#: help.c:265 +#: help.c:242 msgid "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] functions\n" @@ -3050,55 +3094,55 @@ msgstr "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " affiche la liste des fonctions [seulement agrégat/normal/procédure/trigger/window]\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr "" " \\dF[+] [MODÈLE] affiche la liste des configurations de la recherche\n" " plein texte\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr "" " \\dFd[+] [MODÈLE] affiche la liste des dictionnaires de la recherche de\n" " texte\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr "" " \\dFp[+] [MODÈLE] affiche la liste des analyseurs de la recherche de\n" " texte\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr "" " \\dFt[+] [MODÈLE] affiche la liste des modèles de la recherche de\n" " texte\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [MODÈLE] affiche la liste des rôles (utilisateurs)\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [MODÈLE] affiche la liste des index\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr " \\dl[+] liste des « Large Objects », identique à \\lo_list\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [MODÈLE] affiche la liste des langages procéduraux\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [MODÈLE] affiche la liste des vues matérialisées\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [MODÈLE] affiche la liste des schémas\n" -#: help.c:277 +#: help.c:254 msgid "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" @@ -3106,97 +3150,97 @@ msgstr "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " affiche la liste des opérateurs\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S+] [MODÈLE] affiche la liste des collationnements\n" -#: help.c:280 +#: help.c:257 msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr "" " \\dp[S] [MODÈLE] affiche la liste des droits d'accès aux tables,\n" " vues, séquences\n" -#: help.c:281 +#: help.c:258 msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" msgstr " \\dP[itn+] [PATTERN] affiche les relations partitionnées [seulement index/table] [n=imbriquées]\n" -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr "" " \\drds [ROLEPTRN [DBPTRN]] liste la configuration utilisateur par base de données\n" "\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\dg[S] [MODÈLE] affiche la liste des droits des rôles\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[S+] [MODÈLE] affiche la liste des publications de réplication\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [MODÈLE] affiche la liste des souscriptions de réplication\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [MODÈLE] affiche la liste des séquences\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [MODÈLE] affiche la liste des tables\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [MODÈLE] affiche la liste des types de données\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [MODÈLE] affiche la liste des rôles (utilisateurs)\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [MODÈLE] affiche la liste des vues\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [MODÈLE] affiche la liste des extensions\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [MODÈLE] affiche les statistiques étendues\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [MODÈLE] affiche les triggers sur évènement\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [MODÈLE] affiche la liste des bases de données\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] [FONCTION] édite la définition d'une fonction\n" -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv [FONCTION] édite la définition d'une vue\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [MODÈLE] identique à \\dp\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "« Large objects »\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr "" " \\lo_export LOBOID FICHIER\n" " écrit un « Large Object » dans le fichier\n" -#: help.c:302 +#: help.c:279 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3204,42 +3248,42 @@ msgstr "" " \\lo_import FICHIER [COMMENTAIRE]\n" " lit un « Large Object » à partir du fichier\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\dl[+] liste des « Large Objects »\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID supprime un « Large Object »\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "Formatage\n" -#: help.c:309 +#: help.c:286 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr "" " \\a bascule entre les modes de sortie alignée et non\n" " alignée\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr "" " \\C [CHAÎNE] initialise le titre d'une table, ou le désactive en\n" " l'absence d'argument\n" -#: help.c:311 +#: help.c:288 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr "" " \\f [CHAÎNE] affiche ou initialise le séparateur de champ pour\n" " une sortie non alignée des requêtes\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H bascule le mode de sortie HTML (actuellement %s)\n" -#: help.c:314 +#: help.c:291 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3247,7 +3291,7 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [NOM [VALEUR]] règle l'affichage de la table\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3255,33 +3299,33 @@ msgstr "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t affiche uniquement les lignes (actuellement %s)\n" -#: help.c:323 +#: help.c:300 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr "" " \\T [CHAÎNE] initialise les attributs HTML de la balise
,\n" " ou l'annule en l'absence d'argument\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] bascule l'affichage étendu (actuellement %s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "auto" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "Connexions\n" -#: help.c:330 +#: help.c:307 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3291,7 +3335,7 @@ msgstr "" " se connecte à une autre base de données\n" " (actuellement « %s »)\n" -#: help.c:334 +#: help.c:311 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3300,71 +3344,71 @@ msgstr "" " se connecte à une nouvelle base de données\n" " (aucune connexion actuellement)\n" -#: help.c:336 +#: help.c:313 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo affiche des informations sur la connexion en cours\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [ENCODAGE] affiche ou initialise l'encodage du client\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr "" " \\password [UTILISATEUR]\n" " modifie de façon sécurisé le mot de passe d'un\n" " utilisateur\n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "Système d'exploitation\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [RÉPERTOIRE] change de répertoire de travail\n" -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVVAR récupère une variable d'environnement\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv NOM [VALEUR] (dés)initialise une variable d'environnement\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr "" " \\timing [on|off] bascule l'activation du chronométrage des commandes\n" " (actuellement %s)\n" -#: help.c:347 +#: help.c:324 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr "" " \\! [COMMANDE] exécute la commande dans un shell ou exécute un\n" " shell interactif\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "Variables\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr "" " \\prompt [TEXTE] NOM demande à l'utilisateur de configurer la variable\n" " interne\n" -#: help.c:352 +#: help.c:329 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr "" " \\set [NOM [VALEUR]] initialise une variable interne ou les affiche\n" " toutes en l'absence de paramètre\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NOM désactive (supprime) la variable interne\n" -#: help.c:392 +#: help.c:369 msgid "" "List of specially treated variables\n" "\n" @@ -3372,11 +3416,11 @@ msgstr "" "Liste des variables traitées spécialement\n" "\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "variables psql :\n" -#: help.c:396 +#: help.c:373 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3386,7 +3430,7 @@ msgstr "" " ou \\set NOM VALEUR dans psql\n" "\n" -#: help.c:398 +#: help.c:375 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3394,7 +3438,7 @@ msgstr "" " AUTOCOMMIT\n" " si activé, les commandes SQL réussies sont automatiquement validées\n" -#: help.c:400 +#: help.c:377 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3404,7 +3448,7 @@ msgstr "" " détermine la casse utilisée pour compléter les mots clés SQL\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:403 +#: help.c:380 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3412,7 +3456,7 @@ msgstr "" " DBNAME\n" " le nom de base de données actuel\n" -#: help.c:405 +#: help.c:382 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3422,7 +3466,7 @@ msgstr "" " contrôle ce qui est envoyé sur la sortie standard\n" " [all, errors, none, queries]\n" -#: help.c:408 +#: help.c:385 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3432,7 +3476,7 @@ msgstr "" " si activé, affiche les requêtes internes exécutées par les méta-commandes ;\n" " si configuré à « noexec », affiche les requêtes sans les exécuter\n" -#: help.c:411 +#: help.c:388 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3440,7 +3484,7 @@ msgstr "" " ENCODING\n" " encodage du jeu de caractères client\n" -#: help.c:413 +#: help.c:390 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3448,7 +3492,7 @@ msgstr "" " ERROR\n" " true si la dernière requête a échoué, sinon false\n" -#: help.c:415 +#: help.c:392 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" @@ -3457,7 +3501,7 @@ msgstr "" " le nombre de lignes résultats à récupérer et à afficher à la fois\n" " (0 pour illimité)\n" -#: help.c:417 +#: help.c:394 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3465,7 +3509,7 @@ msgstr "" " HIDE_TABLEAM\n" " si activé, les méthodes d'accès ne sont pas affichées\n" -#: help.c:419 +#: help.c:396 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3473,7 +3517,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " si activé, les méthodes de compression methods ne sont pas affichées\n" -#: help.c:421 +#: help.c:398 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3481,7 +3525,7 @@ msgstr "" " HISTCONTROL\n" " contrôle l'historique des commandes [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:423 +#: help.c:400 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3489,7 +3533,7 @@ msgstr "" " HISTFILE\n" " nom du fichier utilisé pour stocker l'historique des commandes\n" -#: help.c:425 +#: help.c:402 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3497,7 +3541,7 @@ msgstr "" " HISTSIZE\n" " nombre maximum de commandes à stocker dans l'historique de commandes\n" -#: help.c:427 +#: help.c:404 msgid "" " HOST\n" " the currently connected database server host\n" @@ -3505,7 +3549,7 @@ msgstr "" " HOST\n" " l'hôte de la base de données\n" -#: help.c:429 +#: help.c:406 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3513,7 +3557,7 @@ msgstr "" " IGNOREEOF\n" " nombre d'EOF nécessaire pour terminer une session interactive\n" -#: help.c:431 +#: help.c:408 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3521,7 +3565,7 @@ msgstr "" " LASTOID\n" " valeur du dernier OID affecté\n" -#: help.c:433 +#: help.c:410 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3531,7 +3575,7 @@ msgstr "" " LAST_ERROR_SQLSTATE\n" " message et SQLSTATE de la dernière erreur ou une chaîne vide et \"00000\" if si aucune erreur\n" -#: help.c:436 +#: help.c:413 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3539,7 +3583,7 @@ msgstr "" " ON_ERROR_ROLLBACK\n" " si activé, une erreur n'arrête pas une transaction (utilise des savepoints implicites)\n" -#: help.c:438 +#: help.c:415 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3547,7 +3591,7 @@ msgstr "" " ON_ERROR_STOP\n" " arrête l'exécution d'un batch après une erreur\n" -#: help.c:440 +#: help.c:417 msgid "" " PORT\n" " server port of the current connection\n" @@ -3555,7 +3599,7 @@ msgstr "" " PORT\n" " port du serveur pour la connexion actuelle\n" -#: help.c:442 +#: help.c:419 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3563,7 +3607,7 @@ msgstr "" " PROMPT1\n" " spécifie l'invite standard de psql\n" -#: help.c:444 +#: help.c:421 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" @@ -3571,7 +3615,7 @@ msgstr "" " PROMPT2\n" " spécifie l'invite utilisé quand une requête continue après la ligne courante\n" -#: help.c:446 +#: help.c:423 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3579,7 +3623,7 @@ msgstr "" " PROMPT3\n" " spécifie l'invite utilisée lors d'un COPY ... FROM STDIN\n" -#: help.c:448 +#: help.c:425 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3587,7 +3631,7 @@ msgstr "" " QUIET\n" " s'exécute en silence (identique à l'option -q)\n" -#: help.c:450 +#: help.c:427 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3595,7 +3639,7 @@ msgstr "" " ROW_COUNT\n" " nombre de lignes renvoyées ou affectées par la dernière requête, ou 0\n" -#: help.c:452 +#: help.c:429 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3605,7 +3649,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " version du serveur (chaîne courte ou format numérique)\n" -#: help.c:455 +#: help.c:432 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3613,7 +3657,7 @@ msgstr "" " SHELL_ERROR\n" " true si la dernière requête a échoué, sinon false\n" -#: help.c:457 +#: help.c:434 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3621,7 +3665,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " code de sortie de la dernière commande shell\n" -#: help.c:459 +#: help.c:436 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3629,7 +3673,7 @@ msgstr "" " SHOW_ALL_RESULTS\n" " affiche tous les résultats d'une requête combinée (\\;) au lieu du dernier uniquement\n" -#: help.c:461 +#: help.c:438 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3637,7 +3681,7 @@ msgstr "" " SHOW_CONTEXT\n" " contrôle l'affichage des champs de contexte du message [never, errors, always]\n" -#: help.c:463 +#: help.c:440 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3645,7 +3689,7 @@ msgstr "" " SINGLELINE\n" " une fin de ligne termine le mode de commande SQL (identique à l'option -S)\n" -#: help.c:465 +#: help.c:442 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3653,7 +3697,7 @@ msgstr "" " SINGLESTEP\n" " mode pas à pas (identique à l'option -s)\n" -#: help.c:467 +#: help.c:444 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3661,7 +3705,7 @@ msgstr "" " SQLSTATE\n" " SQLSTATE de la dernière requête, ou \"00000\" si aucune erreur\n" -#: help.c:469 +#: help.c:446 msgid "" " USER\n" " the currently connected database user\n" @@ -3669,7 +3713,7 @@ msgstr "" " USER\n" " l'utilisateur actuellement connecté\n" -#: help.c:471 +#: help.c:448 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3677,7 +3721,7 @@ msgstr "" " VERBOSITY\n" " contrôle la verbosité des rapports d'erreurs [default, verbose, terse, sqlstate]\n" -#: help.c:473 +#: help.c:450 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3689,7 +3733,7 @@ msgstr "" " VERSION_NUM\n" " version de psql (chaîne longue, chaîne courte, ou format numérique)\n" -#: help.c:478 +#: help.c:455 msgid "" "\n" "Display settings:\n" @@ -3697,7 +3741,7 @@ msgstr "" "\n" "Paramètres d'affichage :\n" -#: help.c:480 +#: help.c:457 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3707,7 +3751,7 @@ msgstr "" " ou \\pset NOM [VALEUR] dans psql\n" "\n" -#: help.c:482 +#: help.c:459 msgid "" " border\n" " border style (number)\n" @@ -3715,7 +3759,7 @@ msgstr "" " border\n" " style de bordure (nombre)\n" -#: help.c:484 +#: help.c:461 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3723,7 +3767,7 @@ msgstr "" " columns\n" " largeur cible pour le format encadré\n" -#: help.c:486 +#: help.c:463 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" @@ -3731,7 +3775,7 @@ msgstr "" " expanded (ou x)\n" " sortie étendue [on, off, auto]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid "" " fieldsep\n" @@ -3740,7 +3784,7 @@ msgstr "" " fieldsep\n" " champ séparateur pour l'affichage non aligné (par défaut « %s »)\n" -#: help.c:491 +#: help.c:468 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3748,7 +3792,7 @@ msgstr "" " fieldsep_zero\n" " configure le séparateur de champ pour l'affichage non alignée à l'octet zéro\n" -#: help.c:493 +#: help.c:470 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3756,7 +3800,7 @@ msgstr "" " footer\n" " active ou désactive l'affiche du bas de tableau [on, off]\n" -#: help.c:495 +#: help.c:472 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3764,7 +3808,7 @@ msgstr "" " format\n" " active le format de sortie [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3772,7 +3816,7 @@ msgstr "" " linestyle\n" " configure l'affichage des lignes de bordure [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3780,7 +3824,7 @@ msgstr "" " null\n" " configure la chaîne à afficher à la place d'une valeur NULL\n" -#: help.c:501 +#: help.c:478 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" @@ -3789,7 +3833,7 @@ msgstr "" " active ou désactive l'affichage d'un caractère spécifique à la locale pour séparer\n" " des groupes de chiffres [on, off]\n" -#: help.c:503 +#: help.c:480 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3797,7 +3841,7 @@ msgstr "" " pager\n" " contrôle quand un paginateur externe est utilisé [yes, no, always]\n" -#: help.c:505 +#: help.c:482 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3805,7 +3849,7 @@ msgstr "" " recordsep\n" " enregistre le séparateur de ligne pour les affichages non alignés\n" -#: help.c:507 +#: help.c:484 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3814,7 +3858,7 @@ msgstr "" " initialise le séparateur d'enregistrements pour un affichage\n" " non aligné à l'octet zéro\n" -#: help.c:509 +#: help.c:486 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3825,7 +3869,7 @@ msgstr "" " proportionnelles de colonnes pour les types de données alignés à gauche dans le\n" " format latex-longtable\n" -#: help.c:512 +#: help.c:489 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -3833,7 +3877,7 @@ msgstr "" " title\n" " configure le titre de la table pour toute table affichée\n" -#: help.c:514 +#: help.c:491 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -3841,7 +3885,7 @@ msgstr "" " tuples_only\n" " si activé, seules les données de la table sont affichées\n" -#: help.c:516 +#: help.c:493 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3853,7 +3897,17 @@ msgstr "" " unicode_header_linestyle\n" " configure le style d'affichage de ligne Unicode [single, double]\n" -#: help.c:521 +#: help.c:497 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" configure la largeur maximale de l'entête dans le format étendu\n" +" [full, column, page, valeur entière]\n" + +#: help.c:501 msgid "" "\n" "Environment variables:\n" @@ -3861,7 +3915,7 @@ msgstr "" "\n" "Variables d'environnement :\n" -#: help.c:525 +#: help.c:505 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3871,7 +3925,7 @@ msgstr "" " ou \\setenv NOM [VALEUR] dans psql\n" "\n" -#: help.c:527 +#: help.c:507 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3883,7 +3937,7 @@ msgstr "" " ou \\setenv NOM [VALEUR] dans psql\n" "\n" -#: help.c:530 +#: help.c:510 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -3891,7 +3945,7 @@ msgstr "" " COLUMNS\n" " nombre de colonnes pour le format encadré\n" -#: help.c:532 +#: help.c:512 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -3899,7 +3953,7 @@ msgstr "" " PGAPPNAME\n" " identique au paramètre de connexion application_name\n" -#: help.c:534 +#: help.c:514 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -3907,7 +3961,7 @@ msgstr "" " PGDATABASE\n" " identique au paramètre de connexion dbname\n" -#: help.c:536 +#: help.c:516 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -3915,7 +3969,7 @@ msgstr "" " PGHOST\n" " identique au paramètre de connexion host\n" -#: help.c:538 +#: help.c:518 msgid "" " PGPASSFILE\n" " password file name\n" @@ -3923,7 +3977,7 @@ msgstr "" " PGPASSFILE\n" " nom du fichier de mot de passe\n" -#: help.c:540 +#: help.c:520 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -3931,7 +3985,7 @@ msgstr "" " PGPASSWORD\n" " mot de passe de connexion (non recommendé)\n" -#: help.c:542 +#: help.c:522 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -3939,7 +3993,7 @@ msgstr "" " PGPORT\n" " identique au paramètre de connexion port\n" -#: help.c:544 +#: help.c:524 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -3947,7 +4001,7 @@ msgstr "" " PGUSER\n" " identique au paramètre de connexion user\n" -#: help.c:546 +#: help.c:526 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3955,7 +4009,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " éditeur utilisé par les commandes \\e, \\ef et \\ev\n" -#: help.c:548 +#: help.c:528 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -3963,7 +4017,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " comment spécifier un numéro de ligne lors de l'appel de l'éditeur\n" -#: help.c:550 +#: help.c:530 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -3971,7 +4025,7 @@ msgstr "" " PSQL_HISTORY\n" " autre emplacement pour le fichier d'historique des commandes\n" -#: help.c:552 +#: help.c:532 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -3979,7 +4033,7 @@ msgstr "" " PSQL_PAGER, PAGER\n" " nom du paginateur externe\n" -#: help.c:555 +#: help.c:535 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -3987,7 +4041,7 @@ msgstr "" " PSQL_WATCH_PAGER\n" " nom du paginateur externe utilisé pour \\watch\n" -#: help.c:558 +#: help.c:538 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -3995,7 +4049,7 @@ msgstr "" " PSQLRC\n" " autre emplacement pour le fichier .psqlrc de l'utilisateur\n" -#: help.c:560 +#: help.c:540 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -4003,7 +4057,7 @@ msgstr "" " SHELL\n" " shell utilisé par la commande \\!\n" -#: help.c:562 +#: help.c:542 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -4011,11 +4065,11 @@ msgstr "" " TMPDIR\n" " répertoire pour les fichiers temporaires\n" -#: help.c:622 +#: help.c:602 msgid "Available help:\n" msgstr "Aide-mémoire disponible :\n" -#: help.c:717 +#: help.c:697 #, c-format msgid "" "Command: %s\n" @@ -4034,7 +4088,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:740 +#: help.c:720 #, c-format msgid "" "No help available for \"%s\".\n" @@ -4043,17 +4097,17 @@ msgstr "" "Aucun aide-mémoire disponible pour « %s ».\n" "Essayez \\h sans arguments pour afficher les aide-mémoires disponibles.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "n'a pas pu lire à partir du fichier en entrée : %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "n'a pas pu sauvegarder l'historique dans le fichier « %s » : %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "l'historique n'est pas supportée par cette installation" @@ -4141,12 +4195,12 @@ msgstr "requête ignorée ; utilisez \\endif ou Ctrl-C pour quitter le bloc \\if msgid "reached EOF without finding closing \\endif(s)" msgstr "a atteint EOF sans trouver le(s) \\endif fermant" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "chaîne entre guillemets non terminée" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s : mémoire épuisée" @@ -4154,2433 +4208,2453 @@ msgstr "%s : mémoire épuisée" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:238 -#: sql_help.c:240 sql_help.c:241 sql_help.c:243 sql_help.c:245 sql_help.c:248 -#: sql_help.c:250 sql_help.c:252 sql_help.c:254 sql_help.c:266 sql_help.c:267 -#: sql_help.c:268 sql_help.c:270 sql_help.c:319 sql_help.c:321 sql_help.c:323 -#: sql_help.c:325 sql_help.c:394 sql_help.c:399 sql_help.c:401 sql_help.c:443 -#: sql_help.c:445 sql_help.c:448 sql_help.c:450 sql_help.c:519 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:593 sql_help.c:595 -#: sql_help.c:597 sql_help.c:599 sql_help.c:601 sql_help.c:604 sql_help.c:606 -#: sql_help.c:609 sql_help.c:620 sql_help.c:622 sql_help.c:666 sql_help.c:668 -#: sql_help.c:670 sql_help.c:673 sql_help.c:675 sql_help.c:677 sql_help.c:714 -#: sql_help.c:718 sql_help.c:722 sql_help.c:741 sql_help.c:744 sql_help.c:747 -#: sql_help.c:776 sql_help.c:788 sql_help.c:796 sql_help.c:799 sql_help.c:802 -#: sql_help.c:817 sql_help.c:820 sql_help.c:849 sql_help.c:854 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:896 sql_help.c:898 sql_help.c:900 -#: sql_help.c:902 sql_help.c:905 sql_help.c:907 sql_help.c:954 sql_help.c:999 -#: sql_help.c:1004 sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 -#: sql_help.c:1038 sql_help.c:1049 sql_help.c:1051 sql_help.c:1071 -#: sql_help.c:1081 sql_help.c:1082 sql_help.c:1084 sql_help.c:1086 -#: sql_help.c:1098 sql_help.c:1102 sql_help.c:1104 sql_help.c:1116 -#: sql_help.c:1118 sql_help.c:1120 sql_help.c:1122 sql_help.c:1141 -#: sql_help.c:1143 sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 -#: sql_help.c:1158 sql_help.c:1159 sql_help.c:1160 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1168 sql_help.c:1308 sql_help.c:1310 -#: sql_help.c:1313 sql_help.c:1316 sql_help.c:1318 sql_help.c:1320 -#: sql_help.c:1323 sql_help.c:1326 sql_help.c:1443 sql_help.c:1445 -#: sql_help.c:1447 sql_help.c:1450 sql_help.c:1471 sql_help.c:1474 -#: sql_help.c:1477 sql_help.c:1480 sql_help.c:1484 sql_help.c:1486 -#: sql_help.c:1488 sql_help.c:1490 sql_help.c:1504 sql_help.c:1507 -#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1521 sql_help.c:1523 -#: sql_help.c:1533 sql_help.c:1535 sql_help.c:1545 sql_help.c:1548 -#: sql_help.c:1571 sql_help.c:1573 sql_help.c:1575 sql_help.c:1577 -#: sql_help.c:1580 sql_help.c:1582 sql_help.c:1585 sql_help.c:1588 -#: sql_help.c:1639 sql_help.c:1682 sql_help.c:1685 sql_help.c:1687 -#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1694 sql_help.c:1696 -#: sql_help.c:1699 sql_help.c:1751 sql_help.c:1767 sql_help.c:2000 -#: sql_help.c:2069 sql_help.c:2088 sql_help.c:2101 sql_help.c:2159 -#: sql_help.c:2167 sql_help.c:2177 sql_help.c:2204 sql_help.c:2236 -#: sql_help.c:2254 sql_help.c:2282 sql_help.c:2393 sql_help.c:2439 -#: sql_help.c:2464 sql_help.c:2487 sql_help.c:2491 sql_help.c:2525 -#: sql_help.c:2545 sql_help.c:2567 sql_help.c:2581 sql_help.c:2602 -#: sql_help.c:2631 sql_help.c:2666 sql_help.c:2691 sql_help.c:2738 -#: sql_help.c:3033 sql_help.c:3046 sql_help.c:3063 sql_help.c:3079 -#: sql_help.c:3119 sql_help.c:3173 sql_help.c:3177 sql_help.c:3179 -#: sql_help.c:3186 sql_help.c:3205 sql_help.c:3232 sql_help.c:3267 -#: sql_help.c:3279 sql_help.c:3288 sql_help.c:3332 sql_help.c:3346 -#: sql_help.c:3374 sql_help.c:3382 sql_help.c:3394 sql_help.c:3404 -#: sql_help.c:3412 sql_help.c:3420 sql_help.c:3428 sql_help.c:3436 -#: sql_help.c:3445 sql_help.c:3456 sql_help.c:3464 sql_help.c:3472 -#: sql_help.c:3480 sql_help.c:3488 sql_help.c:3498 sql_help.c:3507 -#: sql_help.c:3516 sql_help.c:3524 sql_help.c:3534 sql_help.c:3545 -#: sql_help.c:3553 sql_help.c:3562 sql_help.c:3573 sql_help.c:3582 -#: sql_help.c:3590 sql_help.c:3598 sql_help.c:3606 sql_help.c:3614 -#: sql_help.c:3622 sql_help.c:3630 sql_help.c:3638 sql_help.c:3646 -#: sql_help.c:3654 sql_help.c:3662 sql_help.c:3679 sql_help.c:3688 -#: sql_help.c:3696 sql_help.c:3713 sql_help.c:3728 sql_help.c:4040 -#: sql_help.c:4150 sql_help.c:4179 sql_help.c:4195 sql_help.c:4197 -#: sql_help.c:4700 sql_help.c:4748 sql_help.c:4906 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:245 +#: sql_help.c:247 sql_help.c:248 sql_help.c:250 sql_help.c:252 sql_help.c:255 +#: sql_help.c:257 sql_help.c:259 sql_help.c:261 sql_help.c:276 sql_help.c:277 +#: sql_help.c:278 sql_help.c:280 sql_help.c:329 sql_help.c:331 sql_help.c:333 +#: sql_help.c:335 sql_help.c:404 sql_help.c:409 sql_help.c:411 sql_help.c:453 +#: sql_help.c:455 sql_help.c:458 sql_help.c:460 sql_help.c:529 sql_help.c:534 +#: sql_help.c:539 sql_help.c:544 sql_help.c:549 sql_help.c:603 sql_help.c:605 +#: sql_help.c:607 sql_help.c:609 sql_help.c:611 sql_help.c:614 sql_help.c:616 +#: sql_help.c:619 sql_help.c:630 sql_help.c:632 sql_help.c:676 sql_help.c:678 +#: sql_help.c:680 sql_help.c:683 sql_help.c:685 sql_help.c:687 sql_help.c:728 +#: sql_help.c:732 sql_help.c:736 sql_help.c:757 sql_help.c:760 sql_help.c:763 +#: sql_help.c:792 sql_help.c:804 sql_help.c:812 sql_help.c:815 sql_help.c:818 +#: sql_help.c:833 sql_help.c:836 sql_help.c:865 sql_help.c:870 sql_help.c:875 +#: sql_help.c:880 sql_help.c:885 sql_help.c:912 sql_help.c:914 sql_help.c:916 +#: sql_help.c:918 sql_help.c:921 sql_help.c:923 sql_help.c:970 sql_help.c:1015 +#: sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 sql_help.c:1035 +#: sql_help.c:1054 sql_help.c:1065 sql_help.c:1067 sql_help.c:1087 +#: sql_help.c:1097 sql_help.c:1098 sql_help.c:1100 sql_help.c:1102 +#: sql_help.c:1114 sql_help.c:1118 sql_help.c:1120 sql_help.c:1132 +#: sql_help.c:1134 sql_help.c:1136 sql_help.c:1138 sql_help.c:1157 +#: sql_help.c:1159 sql_help.c:1163 sql_help.c:1167 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1175 sql_help.c:1176 sql_help.c:1179 +#: sql_help.c:1182 sql_help.c:1184 sql_help.c:1324 sql_help.c:1326 +#: sql_help.c:1329 sql_help.c:1332 sql_help.c:1334 sql_help.c:1336 +#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1464 sql_help.c:1466 +#: sql_help.c:1468 sql_help.c:1471 sql_help.c:1492 sql_help.c:1495 +#: sql_help.c:1498 sql_help.c:1501 sql_help.c:1505 sql_help.c:1507 +#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1525 sql_help.c:1528 +#: sql_help.c:1530 sql_help.c:1532 sql_help.c:1542 sql_help.c:1544 +#: sql_help.c:1554 sql_help.c:1556 sql_help.c:1566 sql_help.c:1569 +#: sql_help.c:1592 sql_help.c:1594 sql_help.c:1596 sql_help.c:1598 +#: sql_help.c:1601 sql_help.c:1603 sql_help.c:1606 sql_help.c:1609 +#: sql_help.c:1660 sql_help.c:1703 sql_help.c:1706 sql_help.c:1708 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:1715 sql_help.c:1717 +#: sql_help.c:1720 sql_help.c:1770 sql_help.c:1786 sql_help.c:2019 +#: sql_help.c:2088 sql_help.c:2107 sql_help.c:2120 sql_help.c:2178 +#: sql_help.c:2186 sql_help.c:2196 sql_help.c:2224 sql_help.c:2257 +#: sql_help.c:2275 sql_help.c:2303 sql_help.c:2414 sql_help.c:2460 +#: sql_help.c:2485 sql_help.c:2508 sql_help.c:2512 sql_help.c:2546 +#: sql_help.c:2566 sql_help.c:2588 sql_help.c:2602 sql_help.c:2623 +#: sql_help.c:2652 sql_help.c:2685 sql_help.c:2708 sql_help.c:2755 +#: sql_help.c:3053 sql_help.c:3066 sql_help.c:3083 sql_help.c:3099 +#: sql_help.c:3139 sql_help.c:3193 sql_help.c:3197 sql_help.c:3199 +#: sql_help.c:3206 sql_help.c:3225 sql_help.c:3252 sql_help.c:3287 +#: sql_help.c:3299 sql_help.c:3308 sql_help.c:3352 sql_help.c:3366 +#: sql_help.c:3394 sql_help.c:3402 sql_help.c:3414 sql_help.c:3424 +#: sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 sql_help.c:3456 +#: sql_help.c:3465 sql_help.c:3476 sql_help.c:3484 sql_help.c:3492 +#: sql_help.c:3500 sql_help.c:3508 sql_help.c:3518 sql_help.c:3527 +#: sql_help.c:3536 sql_help.c:3544 sql_help.c:3554 sql_help.c:3565 +#: sql_help.c:3573 sql_help.c:3582 sql_help.c:3593 sql_help.c:3602 +#: sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 sql_help.c:3634 +#: sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 sql_help.c:3666 +#: sql_help.c:3674 sql_help.c:3682 sql_help.c:3699 sql_help.c:3708 +#: sql_help.c:3716 sql_help.c:3733 sql_help.c:3748 sql_help.c:4061 +#: sql_help.c:4182 sql_help.c:4211 sql_help.c:4227 sql_help.c:4229 +#: sql_help.c:4733 sql_help.c:4781 sql_help.c:4940 msgid "name" msgstr "nom" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:330 sql_help.c:1848 -#: sql_help.c:3347 sql_help.c:4468 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:340 sql_help.c:1863 +#: sql_help.c:3367 sql_help.c:4500 msgid "aggregate_signature" msgstr "signature_agrégat" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:449 sql_help.c:528 sql_help.c:576 -#: sql_help.c:594 sql_help.c:621 sql_help.c:674 sql_help.c:743 sql_help.c:798 -#: sql_help.c:819 sql_help.c:858 sql_help.c:908 sql_help.c:955 sql_help.c:1008 -#: sql_help.c:1040 sql_help.c:1050 sql_help.c:1085 sql_help.c:1105 -#: sql_help.c:1119 sql_help.c:1169 sql_help.c:1317 sql_help.c:1444 -#: sql_help.c:1487 sql_help.c:1508 sql_help.c:1522 sql_help.c:1534 -#: sql_help.c:1547 sql_help.c:1574 sql_help.c:1640 sql_help.c:1693 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:260 +#: sql_help.c:281 sql_help.c:412 sql_help.c:459 sql_help.c:538 sql_help.c:586 +#: sql_help.c:604 sql_help.c:631 sql_help.c:684 sql_help.c:759 sql_help.c:814 +#: sql_help.c:835 sql_help.c:874 sql_help.c:924 sql_help.c:971 sql_help.c:1024 +#: sql_help.c:1056 sql_help.c:1066 sql_help.c:1101 sql_help.c:1121 +#: sql_help.c:1135 sql_help.c:1185 sql_help.c:1333 sql_help.c:1465 +#: sql_help.c:1508 sql_help.c:1529 sql_help.c:1543 sql_help.c:1555 +#: sql_help.c:1568 sql_help.c:1595 sql_help.c:1661 sql_help.c:1714 msgid "new_name" msgstr "nouveau_nom" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:251 -#: sql_help.c:269 sql_help.c:400 sql_help.c:485 sql_help.c:533 sql_help.c:623 -#: sql_help.c:632 sql_help.c:697 sql_help.c:717 sql_help.c:746 sql_help.c:801 -#: sql_help.c:863 sql_help.c:906 sql_help.c:1013 sql_help.c:1052 -#: sql_help.c:1083 sql_help.c:1103 sql_help.c:1117 sql_help.c:1167 -#: sql_help.c:1381 sql_help.c:1446 sql_help.c:1489 sql_help.c:1510 -#: sql_help.c:1572 sql_help.c:1688 sql_help.c:3019 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:258 +#: sql_help.c:279 sql_help.c:410 sql_help.c:495 sql_help.c:543 sql_help.c:633 +#: sql_help.c:642 sql_help.c:707 sql_help.c:731 sql_help.c:762 sql_help.c:817 +#: sql_help.c:879 sql_help.c:922 sql_help.c:1029 sql_help.c:1068 +#: sql_help.c:1099 sql_help.c:1119 sql_help.c:1133 sql_help.c:1183 +#: sql_help.c:1399 sql_help.c:1467 sql_help.c:1510 sql_help.c:1531 +#: sql_help.c:1593 sql_help.c:1709 sql_help.c:3039 msgid "new_owner" msgstr "nouveau_propriétaire" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:255 sql_help.c:322 -#: sql_help.c:451 sql_help.c:538 sql_help.c:676 sql_help.c:721 sql_help.c:749 -#: sql_help.c:804 sql_help.c:868 sql_help.c:1018 sql_help.c:1087 -#: sql_help.c:1121 sql_help.c:1319 sql_help.c:1491 sql_help.c:1512 -#: sql_help.c:1524 sql_help.c:1536 sql_help.c:1576 sql_help.c:1695 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:262 sql_help.c:332 +#: sql_help.c:461 sql_help.c:548 sql_help.c:686 sql_help.c:735 sql_help.c:765 +#: sql_help.c:820 sql_help.c:884 sql_help.c:1034 sql_help.c:1103 +#: sql_help.c:1137 sql_help.c:1335 sql_help.c:1512 sql_help.c:1533 +#: sql_help.c:1545 sql_help.c:1557 sql_help.c:1597 sql_help.c:1716 msgid "new_schema" msgstr "nouveau_schéma" -#: sql_help.c:44 sql_help.c:1912 sql_help.c:3348 sql_help.c:4497 +#: sql_help.c:44 sql_help.c:1927 sql_help.c:3368 sql_help.c:4529 msgid "where aggregate_signature is:" msgstr "où signature_agrégat est :" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:340 sql_help.c:353 -#: sql_help.c:357 sql_help.c:373 sql_help.c:376 sql_help.c:379 sql_help.c:520 -#: sql_help.c:525 sql_help.c:530 sql_help.c:535 sql_help.c:540 sql_help.c:850 -#: sql_help.c:855 sql_help.c:860 sql_help.c:865 sql_help.c:870 sql_help.c:1000 -#: sql_help.c:1005 sql_help.c:1010 sql_help.c:1015 sql_help.c:1020 -#: sql_help.c:1866 sql_help.c:1883 sql_help.c:1889 sql_help.c:1913 -#: sql_help.c:1916 sql_help.c:1919 sql_help.c:2070 sql_help.c:2089 -#: sql_help.c:2092 sql_help.c:2394 sql_help.c:2603 sql_help.c:3349 -#: sql_help.c:3352 sql_help.c:3355 sql_help.c:3446 sql_help.c:3535 -#: sql_help.c:3563 sql_help.c:3915 sql_help.c:4367 sql_help.c:4474 -#: sql_help.c:4481 sql_help.c:4487 sql_help.c:4498 sql_help.c:4501 -#: sql_help.c:4504 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:350 sql_help.c:363 +#: sql_help.c:367 sql_help.c:383 sql_help.c:386 sql_help.c:389 sql_help.c:530 +#: sql_help.c:535 sql_help.c:540 sql_help.c:545 sql_help.c:550 sql_help.c:866 +#: sql_help.c:871 sql_help.c:876 sql_help.c:881 sql_help.c:886 sql_help.c:1016 +#: sql_help.c:1021 sql_help.c:1026 sql_help.c:1031 sql_help.c:1036 +#: sql_help.c:1881 sql_help.c:1898 sql_help.c:1904 sql_help.c:1928 +#: sql_help.c:1931 sql_help.c:1934 sql_help.c:2089 sql_help.c:2108 +#: sql_help.c:2111 sql_help.c:2415 sql_help.c:2624 sql_help.c:3369 +#: sql_help.c:3372 sql_help.c:3375 sql_help.c:3466 sql_help.c:3555 +#: sql_help.c:3583 sql_help.c:3936 sql_help.c:4399 sql_help.c:4506 +#: sql_help.c:4513 sql_help.c:4519 sql_help.c:4530 sql_help.c:4533 +#: sql_help.c:4536 msgid "argmode" msgstr "mode_argument" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:341 sql_help.c:354 -#: sql_help.c:358 sql_help.c:374 sql_help.c:377 sql_help.c:380 sql_help.c:521 -#: sql_help.c:526 sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:851 -#: sql_help.c:856 sql_help.c:861 sql_help.c:866 sql_help.c:871 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1867 sql_help.c:1884 sql_help.c:1890 sql_help.c:1914 -#: sql_help.c:1917 sql_help.c:1920 sql_help.c:2071 sql_help.c:2090 -#: sql_help.c:2093 sql_help.c:2395 sql_help.c:2604 sql_help.c:3350 -#: sql_help.c:3353 sql_help.c:3356 sql_help.c:3447 sql_help.c:3536 -#: sql_help.c:3564 sql_help.c:4475 sql_help.c:4482 sql_help.c:4488 -#: sql_help.c:4499 sql_help.c:4502 sql_help.c:4505 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:351 sql_help.c:364 +#: sql_help.c:368 sql_help.c:384 sql_help.c:387 sql_help.c:390 sql_help.c:531 +#: sql_help.c:536 sql_help.c:541 sql_help.c:546 sql_help.c:551 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:882 sql_help.c:887 sql_help.c:1017 +#: sql_help.c:1022 sql_help.c:1027 sql_help.c:1032 sql_help.c:1037 +#: sql_help.c:1882 sql_help.c:1899 sql_help.c:1905 sql_help.c:1929 +#: sql_help.c:1932 sql_help.c:1935 sql_help.c:2090 sql_help.c:2109 +#: sql_help.c:2112 sql_help.c:2416 sql_help.c:2625 sql_help.c:3370 +#: sql_help.c:3373 sql_help.c:3376 sql_help.c:3467 sql_help.c:3556 +#: sql_help.c:3584 sql_help.c:4507 sql_help.c:4514 sql_help.c:4520 +#: sql_help.c:4531 sql_help.c:4534 sql_help.c:4537 msgid "argname" msgstr "nom_agrégat" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1868 sql_help.c:1885 sql_help.c:1891 sql_help.c:1915 -#: sql_help.c:1918 sql_help.c:1921 sql_help.c:2396 sql_help.c:2605 -#: sql_help.c:3351 sql_help.c:3354 sql_help.c:3357 sql_help.c:3448 -#: sql_help.c:3537 sql_help.c:3565 sql_help.c:4476 sql_help.c:4483 -#: sql_help.c:4489 sql_help.c:4500 sql_help.c:4503 sql_help.c:4506 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:352 sql_help.c:365 +#: sql_help.c:369 sql_help.c:385 sql_help.c:388 sql_help.c:391 sql_help.c:532 +#: sql_help.c:537 sql_help.c:542 sql_help.c:547 sql_help.c:552 sql_help.c:868 +#: sql_help.c:873 sql_help.c:878 sql_help.c:883 sql_help.c:888 sql_help.c:1018 +#: sql_help.c:1023 sql_help.c:1028 sql_help.c:1033 sql_help.c:1038 +#: sql_help.c:1883 sql_help.c:1900 sql_help.c:1906 sql_help.c:1930 +#: sql_help.c:1933 sql_help.c:1936 sql_help.c:2417 sql_help.c:2626 +#: sql_help.c:3371 sql_help.c:3374 sql_help.c:3377 sql_help.c:3468 +#: sql_help.c:3557 sql_help.c:3585 sql_help.c:4508 sql_help.c:4515 +#: sql_help.c:4521 sql_help.c:4532 sql_help.c:4535 sql_help.c:4538 msgid "argtype" msgstr "type_argument" -#: sql_help.c:114 sql_help.c:397 sql_help.c:474 sql_help.c:486 sql_help.c:949 -#: sql_help.c:1100 sql_help.c:1505 sql_help.c:1634 sql_help.c:1666 -#: sql_help.c:1719 sql_help.c:1783 sql_help.c:1970 sql_help.c:1977 -#: sql_help.c:2285 sql_help.c:2335 sql_help.c:2342 sql_help.c:2351 -#: sql_help.c:2440 sql_help.c:2667 sql_help.c:2760 sql_help.c:3048 -#: sql_help.c:3233 sql_help.c:3255 sql_help.c:3395 sql_help.c:3751 -#: sql_help.c:3959 sql_help.c:4194 sql_help.c:4196 sql_help.c:4973 +#: sql_help.c:114 sql_help.c:407 sql_help.c:484 sql_help.c:496 sql_help.c:965 +#: sql_help.c:1116 sql_help.c:1526 sql_help.c:1655 sql_help.c:1687 +#: sql_help.c:1739 sql_help.c:1798 sql_help.c:1987 sql_help.c:1994 +#: sql_help.c:2306 sql_help.c:2356 sql_help.c:2363 sql_help.c:2372 +#: sql_help.c:2461 sql_help.c:2686 sql_help.c:2777 sql_help.c:3068 +#: sql_help.c:3253 sql_help.c:3275 sql_help.c:3415 sql_help.c:3772 +#: sql_help.c:3980 sql_help.c:4226 sql_help.c:4228 sql_help.c:5006 msgid "option" msgstr "option" -#: sql_help.c:115 sql_help.c:950 sql_help.c:1635 sql_help.c:2441 -#: sql_help.c:2668 sql_help.c:3234 sql_help.c:3396 +#: sql_help.c:115 sql_help.c:966 sql_help.c:1656 sql_help.c:2462 +#: sql_help.c:2687 sql_help.c:3254 sql_help.c:3416 msgid "where option can be:" msgstr "où option peut être :" -#: sql_help.c:116 sql_help.c:2217 +#: sql_help.c:116 sql_help.c:2238 msgid "allowconn" msgstr "allowconn" -#: sql_help.c:117 sql_help.c:951 sql_help.c:1636 sql_help.c:2218 -#: sql_help.c:2442 sql_help.c:2669 sql_help.c:3235 +#: sql_help.c:117 sql_help.c:967 sql_help.c:1657 sql_help.c:2239 +#: sql_help.c:2463 sql_help.c:2688 sql_help.c:3255 msgid "connlimit" msgstr "limite_de_connexion" -#: sql_help.c:118 sql_help.c:2219 +#: sql_help.c:118 sql_help.c:2240 msgid "istemplate" msgstr "istemplate" -#: sql_help.c:124 sql_help.c:611 sql_help.c:679 sql_help.c:693 sql_help.c:1322 -#: sql_help.c:1374 sql_help.c:4200 +#: sql_help.c:124 sql_help.c:621 sql_help.c:689 sql_help.c:703 sql_help.c:1338 +#: sql_help.c:1392 sql_help.c:4232 msgid "new_tablespace" msgstr "nouveau_tablespace" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:548 sql_help.c:550 -#: sql_help.c:551 sql_help.c:875 sql_help.c:877 sql_help.c:878 sql_help.c:958 -#: sql_help.c:962 sql_help.c:965 sql_help.c:1027 sql_help.c:1029 -#: sql_help.c:1030 sql_help.c:1180 sql_help.c:1183 sql_help.c:1643 -#: sql_help.c:1647 sql_help.c:1650 sql_help.c:2406 sql_help.c:2609 -#: sql_help.c:3927 sql_help.c:4218 sql_help.c:4379 sql_help.c:4688 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:558 sql_help.c:560 +#: sql_help.c:561 sql_help.c:891 sql_help.c:893 sql_help.c:894 sql_help.c:974 +#: sql_help.c:978 sql_help.c:981 sql_help.c:1043 sql_help.c:1045 +#: sql_help.c:1046 sql_help.c:1196 sql_help.c:1198 sql_help.c:1664 +#: sql_help.c:1668 sql_help.c:1671 sql_help.c:2427 sql_help.c:2630 +#: sql_help.c:3948 sql_help.c:4250 sql_help.c:4411 sql_help.c:4721 msgid "configuration_parameter" msgstr "paramètre_configuration" -#: sql_help.c:128 sql_help.c:398 sql_help.c:469 sql_help.c:475 sql_help.c:487 -#: sql_help.c:549 sql_help.c:603 sql_help.c:685 sql_help.c:695 sql_help.c:876 -#: sql_help.c:904 sql_help.c:959 sql_help.c:1028 sql_help.c:1101 -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:1157 -#: sql_help.c:1162 sql_help.c:1165 sql_help.c:1181 sql_help.c:1182 -#: sql_help.c:1353 sql_help.c:1376 sql_help.c:1424 sql_help.c:1449 -#: sql_help.c:1506 sql_help.c:1590 sql_help.c:1644 sql_help.c:1667 -#: sql_help.c:2286 sql_help.c:2336 sql_help.c:2343 sql_help.c:2352 -#: sql_help.c:2407 sql_help.c:2408 sql_help.c:2472 sql_help.c:2475 -#: sql_help.c:2509 sql_help.c:2610 sql_help.c:2611 sql_help.c:2634 -#: sql_help.c:2761 sql_help.c:2800 sql_help.c:2910 sql_help.c:2923 -#: sql_help.c:2937 sql_help.c:2978 sql_help.c:3005 sql_help.c:3022 -#: sql_help.c:3049 sql_help.c:3256 sql_help.c:3960 sql_help.c:4689 -#: sql_help.c:4690 sql_help.c:4691 sql_help.c:4692 +#: sql_help.c:128 sql_help.c:408 sql_help.c:479 sql_help.c:485 sql_help.c:497 +#: sql_help.c:559 sql_help.c:613 sql_help.c:695 sql_help.c:705 sql_help.c:892 +#: sql_help.c:920 sql_help.c:975 sql_help.c:1044 sql_help.c:1117 +#: sql_help.c:1162 sql_help.c:1166 sql_help.c:1170 sql_help.c:1173 +#: sql_help.c:1178 sql_help.c:1181 sql_help.c:1197 sql_help.c:1371 +#: sql_help.c:1394 sql_help.c:1442 sql_help.c:1450 sql_help.c:1470 +#: sql_help.c:1527 sql_help.c:1611 sql_help.c:1665 sql_help.c:1688 +#: sql_help.c:2307 sql_help.c:2357 sql_help.c:2364 sql_help.c:2373 +#: sql_help.c:2428 sql_help.c:2429 sql_help.c:2493 sql_help.c:2496 +#: sql_help.c:2530 sql_help.c:2631 sql_help.c:2632 sql_help.c:2655 +#: sql_help.c:2778 sql_help.c:2817 sql_help.c:2927 sql_help.c:2940 +#: sql_help.c:2954 sql_help.c:2995 sql_help.c:3003 sql_help.c:3025 +#: sql_help.c:3042 sql_help.c:3069 sql_help.c:3276 sql_help.c:3981 +#: sql_help.c:4722 sql_help.c:4723 sql_help.c:4724 sql_help.c:4725 msgid "value" msgstr "valeur" -#: sql_help.c:200 +#: sql_help.c:202 msgid "target_role" msgstr "rôle_cible" -#: sql_help.c:201 sql_help.c:913 sql_help.c:2270 sql_help.c:2639 -#: sql_help.c:2716 sql_help.c:2721 sql_help.c:3890 sql_help.c:3899 -#: sql_help.c:3918 sql_help.c:3930 sql_help.c:4342 sql_help.c:4351 -#: sql_help.c:4370 sql_help.c:4382 +#: sql_help.c:203 sql_help.c:929 sql_help.c:2291 sql_help.c:2660 +#: sql_help.c:2733 sql_help.c:2738 sql_help.c:3911 sql_help.c:3920 +#: sql_help.c:3939 sql_help.c:3951 sql_help.c:4374 sql_help.c:4383 +#: sql_help.c:4402 sql_help.c:4414 msgid "schema_name" msgstr "nom_schéma" -#: sql_help.c:202 +#: sql_help.c:204 msgid "abbreviated_grant_or_revoke" msgstr "grant_ou_revoke_raccourci" -#: sql_help.c:203 +#: sql_help.c:205 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "où abbreviated_grant_or_revoke fait partie de :" -#: sql_help.c:204 sql_help.c:205 sql_help.c:206 sql_help.c:207 sql_help.c:208 -#: sql_help.c:209 sql_help.c:210 sql_help.c:211 sql_help.c:212 sql_help.c:213 -#: sql_help.c:574 sql_help.c:610 sql_help.c:678 sql_help.c:822 sql_help.c:969 -#: sql_help.c:1321 sql_help.c:1654 sql_help.c:2445 sql_help.c:2446 -#: sql_help.c:2447 sql_help.c:2448 sql_help.c:2449 sql_help.c:2583 -#: sql_help.c:2672 sql_help.c:2673 sql_help.c:2674 sql_help.c:2675 -#: sql_help.c:2676 sql_help.c:3238 sql_help.c:3239 sql_help.c:3240 -#: sql_help.c:3241 sql_help.c:3242 sql_help.c:3939 sql_help.c:3943 -#: sql_help.c:4391 sql_help.c:4395 sql_help.c:4710 +#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 +#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 +#: sql_help.c:584 sql_help.c:620 sql_help.c:688 sql_help.c:838 sql_help.c:985 +#: sql_help.c:1337 sql_help.c:1675 sql_help.c:2466 sql_help.c:2467 +#: sql_help.c:2468 sql_help.c:2469 sql_help.c:2470 sql_help.c:2604 +#: sql_help.c:2691 sql_help.c:2692 sql_help.c:2693 sql_help.c:3258 +#: sql_help.c:3259 sql_help.c:3260 sql_help.c:3261 sql_help.c:3262 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:4423 sql_help.c:4427 +#: sql_help.c:4743 msgid "role_name" msgstr "nom_rôle" -#: sql_help.c:239 sql_help.c:462 sql_help.c:912 sql_help.c:1337 sql_help.c:1339 -#: sql_help.c:1391 sql_help.c:1403 sql_help.c:1428 sql_help.c:1684 -#: sql_help.c:2239 sql_help.c:2243 sql_help.c:2355 sql_help.c:2360 -#: sql_help.c:2468 sql_help.c:2638 sql_help.c:2777 sql_help.c:2782 -#: sql_help.c:2784 sql_help.c:2905 sql_help.c:2918 sql_help.c:2932 -#: sql_help.c:2941 sql_help.c:2953 sql_help.c:2982 sql_help.c:3991 -#: sql_help.c:4006 sql_help.c:4008 sql_help.c:4095 sql_help.c:4098 -#: sql_help.c:4100 sql_help.c:4561 sql_help.c:4562 sql_help.c:4571 -#: sql_help.c:4618 sql_help.c:4619 sql_help.c:4620 sql_help.c:4621 -#: sql_help.c:4622 sql_help.c:4623 sql_help.c:4663 sql_help.c:4664 -#: sql_help.c:4669 sql_help.c:4674 sql_help.c:4818 sql_help.c:4819 -#: sql_help.c:4828 sql_help.c:4875 sql_help.c:4876 sql_help.c:4877 -#: sql_help.c:4878 sql_help.c:4879 sql_help.c:4880 sql_help.c:4934 -#: sql_help.c:4936 sql_help.c:5004 sql_help.c:5064 sql_help.c:5065 -#: sql_help.c:5074 sql_help.c:5121 sql_help.c:5122 sql_help.c:5123 -#: sql_help.c:5124 sql_help.c:5125 sql_help.c:5126 +#: sql_help.c:246 sql_help.c:265 sql_help.c:472 sql_help.c:928 sql_help.c:1353 +#: sql_help.c:1355 sql_help.c:1359 sql_help.c:1409 sql_help.c:1421 +#: sql_help.c:1446 sql_help.c:1705 sql_help.c:2260 sql_help.c:2264 +#: sql_help.c:2376 sql_help.c:2381 sql_help.c:2489 sql_help.c:2659 +#: sql_help.c:2794 sql_help.c:2799 sql_help.c:2801 sql_help.c:2922 +#: sql_help.c:2935 sql_help.c:2949 sql_help.c:2958 sql_help.c:2970 +#: sql_help.c:2999 sql_help.c:4012 sql_help.c:4027 sql_help.c:4029 +#: sql_help.c:4125 sql_help.c:4128 sql_help.c:4130 sql_help.c:4593 +#: sql_help.c:4594 sql_help.c:4603 sql_help.c:4650 sql_help.c:4651 +#: sql_help.c:4652 sql_help.c:4653 sql_help.c:4654 sql_help.c:4655 +#: sql_help.c:4696 sql_help.c:4697 sql_help.c:4702 sql_help.c:4707 +#: sql_help.c:4851 sql_help.c:4852 sql_help.c:4861 sql_help.c:4908 +#: sql_help.c:4909 sql_help.c:4910 sql_help.c:4911 sql_help.c:4912 +#: sql_help.c:4913 sql_help.c:4968 sql_help.c:4970 sql_help.c:5036 +#: sql_help.c:5096 sql_help.c:5097 sql_help.c:5106 sql_help.c:5153 +#: sql_help.c:5154 sql_help.c:5155 sql_help.c:5156 sql_help.c:5157 +#: sql_help.c:5158 msgid "expression" msgstr "expression" -#: sql_help.c:242 +#: sql_help.c:249 sql_help.c:2261 msgid "domain_constraint" msgstr "contrainte_domaine" -#: sql_help.c:244 sql_help.c:246 sql_help.c:249 sql_help.c:477 sql_help.c:478 -#: sql_help.c:1314 sql_help.c:1361 sql_help.c:1362 sql_help.c:1363 -#: sql_help.c:1390 sql_help.c:1402 sql_help.c:1419 sql_help.c:1854 -#: sql_help.c:1856 sql_help.c:2242 sql_help.c:2354 sql_help.c:2359 -#: sql_help.c:2940 sql_help.c:2952 sql_help.c:4003 +#: sql_help.c:251 sql_help.c:253 sql_help.c:256 sql_help.c:264 sql_help.c:487 +#: sql_help.c:488 sql_help.c:1330 sql_help.c:1379 sql_help.c:1380 +#: sql_help.c:1381 sql_help.c:1408 sql_help.c:1420 sql_help.c:1437 +#: sql_help.c:1869 sql_help.c:1871 sql_help.c:2263 sql_help.c:2375 +#: sql_help.c:2380 sql_help.c:2957 sql_help.c:2969 sql_help.c:4024 msgid "constraint_name" msgstr "nom_contrainte" -#: sql_help.c:247 sql_help.c:1315 +#: sql_help.c:254 sql_help.c:1331 msgid "new_constraint_name" msgstr "nouvelle_nom_contrainte" -#: sql_help.c:320 sql_help.c:1099 +#: sql_help.c:263 sql_help.c:2262 +msgid "where domain_constraint is:" +msgstr "où contrainte_domaine est :" + +#: sql_help.c:330 sql_help.c:1115 msgid "new_version" msgstr "nouvelle_version" -#: sql_help.c:324 sql_help.c:326 +#: sql_help.c:334 sql_help.c:336 msgid "member_object" msgstr "objet_membre" -#: sql_help.c:327 +#: sql_help.c:337 msgid "where member_object is:" msgstr "où objet_membre fait partie de :" -#: sql_help.c:328 sql_help.c:333 sql_help.c:334 sql_help.c:335 sql_help.c:336 -#: sql_help.c:337 sql_help.c:338 sql_help.c:343 sql_help.c:347 sql_help.c:349 -#: sql_help.c:351 sql_help.c:360 sql_help.c:361 sql_help.c:362 sql_help.c:363 -#: sql_help.c:364 sql_help.c:365 sql_help.c:366 sql_help.c:367 sql_help.c:370 -#: sql_help.c:371 sql_help.c:1846 sql_help.c:1851 sql_help.c:1858 -#: sql_help.c:1859 sql_help.c:1860 sql_help.c:1861 sql_help.c:1862 -#: sql_help.c:1863 sql_help.c:1864 sql_help.c:1869 sql_help.c:1871 -#: sql_help.c:1875 sql_help.c:1877 sql_help.c:1881 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1894 sql_help.c:1895 sql_help.c:1896 -#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 -#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 sql_help.c:1904 -#: sql_help.c:1909 sql_help.c:1910 sql_help.c:4464 sql_help.c:4469 -#: sql_help.c:4470 sql_help.c:4471 sql_help.c:4472 sql_help.c:4478 -#: sql_help.c:4479 sql_help.c:4484 sql_help.c:4485 sql_help.c:4490 -#: sql_help.c:4491 sql_help.c:4492 sql_help.c:4493 sql_help.c:4494 -#: sql_help.c:4495 +#: sql_help.c:338 sql_help.c:343 sql_help.c:344 sql_help.c:345 sql_help.c:346 +#: sql_help.c:347 sql_help.c:348 sql_help.c:353 sql_help.c:357 sql_help.c:359 +#: sql_help.c:361 sql_help.c:370 sql_help.c:371 sql_help.c:372 sql_help.c:373 +#: sql_help.c:374 sql_help.c:375 sql_help.c:376 sql_help.c:377 sql_help.c:380 +#: sql_help.c:381 sql_help.c:1861 sql_help.c:1866 sql_help.c:1873 +#: sql_help.c:1874 sql_help.c:1875 sql_help.c:1876 sql_help.c:1877 +#: sql_help.c:1878 sql_help.c:1879 sql_help.c:1884 sql_help.c:1886 +#: sql_help.c:1890 sql_help.c:1892 sql_help.c:1896 sql_help.c:1901 +#: sql_help.c:1902 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1912 sql_help.c:1913 sql_help.c:1914 sql_help.c:1915 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:1918 sql_help.c:1919 +#: sql_help.c:1924 sql_help.c:1925 sql_help.c:4496 sql_help.c:4501 +#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4510 +#: sql_help.c:4511 sql_help.c:4516 sql_help.c:4517 sql_help.c:4522 +#: sql_help.c:4523 sql_help.c:4524 sql_help.c:4525 sql_help.c:4526 +#: sql_help.c:4527 msgid "object_name" msgstr "nom_objet" -#: sql_help.c:329 sql_help.c:1847 sql_help.c:4467 +#: sql_help.c:339 sql_help.c:1862 sql_help.c:4499 msgid "aggregate_name" msgstr "nom_agrégat" -#: sql_help.c:331 sql_help.c:1849 sql_help.c:2135 sql_help.c:2139 -#: sql_help.c:2141 sql_help.c:3365 +#: sql_help.c:341 sql_help.c:1864 sql_help.c:2154 sql_help.c:2158 +#: sql_help.c:2160 sql_help.c:3385 msgid "source_type" msgstr "type_source" -#: sql_help.c:332 sql_help.c:1850 sql_help.c:2136 sql_help.c:2140 -#: sql_help.c:2142 sql_help.c:3366 +#: sql_help.c:342 sql_help.c:1865 sql_help.c:2155 sql_help.c:2159 +#: sql_help.c:2161 sql_help.c:3386 msgid "target_type" msgstr "type_cible" -#: sql_help.c:339 sql_help.c:786 sql_help.c:1865 sql_help.c:2137 -#: sql_help.c:2180 sql_help.c:2258 sql_help.c:2526 sql_help.c:2557 -#: sql_help.c:3125 sql_help.c:4366 sql_help.c:4473 sql_help.c:4590 -#: sql_help.c:4594 sql_help.c:4598 sql_help.c:4601 sql_help.c:4847 -#: sql_help.c:4851 sql_help.c:4855 sql_help.c:4858 sql_help.c:5093 -#: sql_help.c:5097 sql_help.c:5101 sql_help.c:5104 +#: sql_help.c:349 sql_help.c:802 sql_help.c:1880 sql_help.c:2156 +#: sql_help.c:2199 sql_help.c:2279 sql_help.c:2547 sql_help.c:2578 +#: sql_help.c:3145 sql_help.c:4398 sql_help.c:4505 sql_help.c:4622 +#: sql_help.c:4626 sql_help.c:4630 sql_help.c:4633 sql_help.c:4880 +#: sql_help.c:4884 sql_help.c:4888 sql_help.c:4891 sql_help.c:5125 +#: sql_help.c:5129 sql_help.c:5133 sql_help.c:5136 msgid "function_name" msgstr "nom_fonction" -#: sql_help.c:344 sql_help.c:779 sql_help.c:1872 sql_help.c:2550 +#: sql_help.c:354 sql_help.c:795 sql_help.c:1887 sql_help.c:2571 msgid "operator_name" msgstr "nom_opérateur" -#: sql_help.c:345 sql_help.c:715 sql_help.c:719 sql_help.c:723 sql_help.c:1873 -#: sql_help.c:2527 sql_help.c:3489 +#: sql_help.c:355 sql_help.c:729 sql_help.c:733 sql_help.c:737 sql_help.c:1888 +#: sql_help.c:2548 sql_help.c:3509 msgid "left_type" msgstr "type_argument_gauche" -#: sql_help.c:346 sql_help.c:716 sql_help.c:720 sql_help.c:724 sql_help.c:1874 -#: sql_help.c:2528 sql_help.c:3490 +#: sql_help.c:356 sql_help.c:730 sql_help.c:734 sql_help.c:738 sql_help.c:1889 +#: sql_help.c:2549 sql_help.c:3510 msgid "right_type" msgstr "type_argument_droit" -#: sql_help.c:348 sql_help.c:350 sql_help.c:742 sql_help.c:745 sql_help.c:748 -#: sql_help.c:777 sql_help.c:789 sql_help.c:797 sql_help.c:800 sql_help.c:803 -#: sql_help.c:1408 sql_help.c:1876 sql_help.c:1878 sql_help.c:2547 -#: sql_help.c:2568 sql_help.c:2958 sql_help.c:3499 sql_help.c:3508 +#: sql_help.c:358 sql_help.c:360 sql_help.c:758 sql_help.c:761 sql_help.c:764 +#: sql_help.c:793 sql_help.c:805 sql_help.c:813 sql_help.c:816 sql_help.c:819 +#: sql_help.c:1426 sql_help.c:1891 sql_help.c:1893 sql_help.c:2568 +#: sql_help.c:2589 sql_help.c:2975 sql_help.c:3519 sql_help.c:3528 msgid "index_method" msgstr "méthode_indexage" -#: sql_help.c:352 sql_help.c:1882 sql_help.c:4480 +#: sql_help.c:362 sql_help.c:1897 sql_help.c:4512 msgid "procedure_name" msgstr "nom_procédure" -#: sql_help.c:356 sql_help.c:1888 sql_help.c:3914 sql_help.c:4486 +#: sql_help.c:366 sql_help.c:1903 sql_help.c:3935 sql_help.c:4518 msgid "routine_name" msgstr "nom_routine" -#: sql_help.c:368 sql_help.c:1380 sql_help.c:1905 sql_help.c:2402 -#: sql_help.c:2608 sql_help.c:2913 sql_help.c:3092 sql_help.c:3670 -#: sql_help.c:3936 sql_help.c:4388 +#: sql_help.c:378 sql_help.c:1398 sql_help.c:1920 sql_help.c:2423 +#: sql_help.c:2629 sql_help.c:2930 sql_help.c:3112 sql_help.c:3690 +#: sql_help.c:3957 sql_help.c:4420 msgid "type_name" msgstr "nom_type" -#: sql_help.c:369 sql_help.c:1906 sql_help.c:2401 sql_help.c:2607 -#: sql_help.c:3093 sql_help.c:3323 sql_help.c:3671 sql_help.c:3921 -#: sql_help.c:4373 +#: sql_help.c:379 sql_help.c:1921 sql_help.c:2422 sql_help.c:2628 +#: sql_help.c:3113 sql_help.c:3343 sql_help.c:3691 sql_help.c:3942 +#: sql_help.c:4405 msgid "lang_name" msgstr "nom_langage" -#: sql_help.c:372 +#: sql_help.c:382 msgid "and aggregate_signature is:" msgstr "et signature_agrégat est :" -#: sql_help.c:395 sql_help.c:2002 sql_help.c:2283 +#: sql_help.c:405 sql_help.c:2021 sql_help.c:2304 msgid "handler_function" msgstr "fonction_gestionnaire" -#: sql_help.c:396 sql_help.c:2284 +#: sql_help.c:406 sql_help.c:2305 msgid "validator_function" msgstr "fonction_validateur" -#: sql_help.c:444 sql_help.c:523 sql_help.c:667 sql_help.c:853 sql_help.c:1003 -#: sql_help.c:1309 sql_help.c:1581 +#: sql_help.c:454 sql_help.c:533 sql_help.c:677 sql_help.c:869 sql_help.c:1019 +#: sql_help.c:1325 sql_help.c:1602 msgid "action" msgstr "action" -#: sql_help.c:446 sql_help.c:453 sql_help.c:457 sql_help.c:458 sql_help.c:461 -#: sql_help.c:463 sql_help.c:464 sql_help.c:465 sql_help.c:467 sql_help.c:470 -#: sql_help.c:472 sql_help.c:473 sql_help.c:671 sql_help.c:681 sql_help.c:683 -#: sql_help.c:686 sql_help.c:688 sql_help.c:689 sql_help.c:911 sql_help.c:1080 -#: sql_help.c:1311 sql_help.c:1329 sql_help.c:1333 sql_help.c:1334 -#: sql_help.c:1338 sql_help.c:1340 sql_help.c:1341 sql_help.c:1342 -#: sql_help.c:1343 sql_help.c:1345 sql_help.c:1348 sql_help.c:1349 -#: sql_help.c:1351 sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 -#: sql_help.c:1404 sql_help.c:1406 sql_help.c:1413 sql_help.c:1422 -#: sql_help.c:1427 sql_help.c:1431 sql_help.c:1432 sql_help.c:1683 -#: sql_help.c:1686 sql_help.c:1690 sql_help.c:1728 sql_help.c:1853 -#: sql_help.c:1967 sql_help.c:1973 sql_help.c:1987 sql_help.c:1988 -#: sql_help.c:1989 sql_help.c:2333 sql_help.c:2346 sql_help.c:2399 -#: sql_help.c:2467 sql_help.c:2473 sql_help.c:2506 sql_help.c:2637 -#: sql_help.c:2746 sql_help.c:2781 sql_help.c:2783 sql_help.c:2895 -#: sql_help.c:2904 sql_help.c:2914 sql_help.c:2917 sql_help.c:2927 -#: sql_help.c:2931 sql_help.c:2954 sql_help.c:2956 sql_help.c:2963 -#: sql_help.c:2976 sql_help.c:2981 sql_help.c:2985 sql_help.c:2986 -#: sql_help.c:3002 sql_help.c:3128 sql_help.c:3268 sql_help.c:3893 -#: sql_help.c:3894 sql_help.c:3990 sql_help.c:4005 sql_help.c:4007 -#: sql_help.c:4009 sql_help.c:4094 sql_help.c:4097 sql_help.c:4099 -#: sql_help.c:4345 sql_help.c:4346 sql_help.c:4466 sql_help.c:4627 -#: sql_help.c:4633 sql_help.c:4635 sql_help.c:4884 sql_help.c:4890 -#: sql_help.c:4892 sql_help.c:4933 sql_help.c:4935 sql_help.c:4937 -#: sql_help.c:4992 sql_help.c:5130 sql_help.c:5136 sql_help.c:5138 +#: sql_help.c:456 sql_help.c:463 sql_help.c:467 sql_help.c:468 sql_help.c:471 +#: sql_help.c:473 sql_help.c:474 sql_help.c:475 sql_help.c:477 sql_help.c:480 +#: sql_help.c:482 sql_help.c:483 sql_help.c:681 sql_help.c:691 sql_help.c:693 +#: sql_help.c:696 sql_help.c:698 sql_help.c:699 sql_help.c:927 sql_help.c:1096 +#: sql_help.c:1327 sql_help.c:1345 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 sql_help.c:1358 +#: sql_help.c:1360 sql_help.c:1361 sql_help.c:1363 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1369 sql_help.c:1372 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1422 sql_help.c:1424 sql_help.c:1431 +#: sql_help.c:1440 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1704 sql_help.c:1707 sql_help.c:1711 sql_help.c:1747 +#: sql_help.c:1868 sql_help.c:1984 sql_help.c:1990 sql_help.c:2004 +#: sql_help.c:2005 sql_help.c:2006 sql_help.c:2354 sql_help.c:2367 +#: sql_help.c:2420 sql_help.c:2488 sql_help.c:2494 sql_help.c:2527 +#: sql_help.c:2658 sql_help.c:2763 sql_help.c:2798 sql_help.c:2800 +#: sql_help.c:2912 sql_help.c:2921 sql_help.c:2931 sql_help.c:2934 +#: sql_help.c:2944 sql_help.c:2948 sql_help.c:2971 sql_help.c:2973 +#: sql_help.c:2980 sql_help.c:2993 sql_help.c:2998 sql_help.c:3005 +#: sql_help.c:3006 sql_help.c:3022 sql_help.c:3148 sql_help.c:3288 +#: sql_help.c:3914 sql_help.c:3915 sql_help.c:4011 sql_help.c:4026 +#: sql_help.c:4028 sql_help.c:4030 sql_help.c:4124 sql_help.c:4127 +#: sql_help.c:4129 sql_help.c:4131 sql_help.c:4377 sql_help.c:4378 +#: sql_help.c:4498 sql_help.c:4659 sql_help.c:4666 sql_help.c:4668 +#: sql_help.c:4917 sql_help.c:4924 sql_help.c:4926 sql_help.c:4967 +#: sql_help.c:4969 sql_help.c:4971 sql_help.c:5024 sql_help.c:5162 +#: sql_help.c:5169 sql_help.c:5171 msgid "column_name" msgstr "nom_colonne" -#: sql_help.c:447 sql_help.c:672 sql_help.c:1312 sql_help.c:1691 +#: sql_help.c:457 sql_help.c:682 sql_help.c:1328 sql_help.c:1712 msgid "new_column_name" msgstr "nouvelle_nom_colonne" -#: sql_help.c:452 sql_help.c:544 sql_help.c:680 sql_help.c:874 sql_help.c:1024 -#: sql_help.c:1328 sql_help.c:1591 +#: sql_help.c:462 sql_help.c:554 sql_help.c:690 sql_help.c:890 sql_help.c:1040 +#: sql_help.c:1344 sql_help.c:1612 msgid "where action is one of:" msgstr "où action fait partie de :" -#: sql_help.c:454 sql_help.c:459 sql_help.c:1072 sql_help.c:1330 -#: sql_help.c:1335 sql_help.c:1593 sql_help.c:1597 sql_help.c:2237 -#: sql_help.c:2334 sql_help.c:2546 sql_help.c:2739 sql_help.c:2896 -#: sql_help.c:3175 sql_help.c:4151 +#: sql_help.c:464 sql_help.c:469 sql_help.c:1088 sql_help.c:1346 +#: sql_help.c:1351 sql_help.c:1614 sql_help.c:1618 sql_help.c:2258 +#: sql_help.c:2355 sql_help.c:2567 sql_help.c:2756 sql_help.c:2913 +#: sql_help.c:3195 sql_help.c:4183 msgid "data_type" msgstr "type_données" -#: sql_help.c:455 sql_help.c:460 sql_help.c:1331 sql_help.c:1336 -#: sql_help.c:1594 sql_help.c:1598 sql_help.c:2238 sql_help.c:2337 -#: sql_help.c:2469 sql_help.c:2898 sql_help.c:2906 sql_help.c:2919 -#: sql_help.c:2933 sql_help.c:3176 sql_help.c:3182 sql_help.c:4000 +#: sql_help.c:465 sql_help.c:470 sql_help.c:1347 sql_help.c:1352 +#: sql_help.c:1447 sql_help.c:1615 sql_help.c:1619 sql_help.c:2259 +#: sql_help.c:2358 sql_help.c:2490 sql_help.c:2915 sql_help.c:2923 +#: sql_help.c:2936 sql_help.c:2950 sql_help.c:3000 sql_help.c:3196 +#: sql_help.c:3202 sql_help.c:4021 msgid "collation" msgstr "collationnement" -#: sql_help.c:456 sql_help.c:1332 sql_help.c:2338 sql_help.c:2347 -#: sql_help.c:2899 sql_help.c:2915 sql_help.c:2928 +#: sql_help.c:466 sql_help.c:1348 sql_help.c:2359 sql_help.c:2368 +#: sql_help.c:2916 sql_help.c:2932 sql_help.c:2945 msgid "column_constraint" msgstr "contrainte_colonne" -#: sql_help.c:466 sql_help.c:608 sql_help.c:682 sql_help.c:1350 sql_help.c:4986 +#: sql_help.c:476 sql_help.c:618 sql_help.c:692 sql_help.c:1368 sql_help.c:5018 msgid "integer" msgstr "entier" -#: sql_help.c:468 sql_help.c:471 sql_help.c:684 sql_help.c:687 sql_help.c:1352 -#: sql_help.c:1355 +#: sql_help.c:478 sql_help.c:481 sql_help.c:694 sql_help.c:697 sql_help.c:1370 +#: sql_help.c:1373 msgid "attribute_option" msgstr "option_attribut" -#: sql_help.c:476 sql_help.c:1359 sql_help.c:2339 sql_help.c:2348 -#: sql_help.c:2900 sql_help.c:2916 sql_help.c:2929 +#: sql_help.c:486 sql_help.c:1377 sql_help.c:2360 sql_help.c:2369 +#: sql_help.c:2917 sql_help.c:2933 sql_help.c:2946 msgid "table_constraint" msgstr "contrainte_table" -#: sql_help.c:479 sql_help.c:480 sql_help.c:481 sql_help.c:482 sql_help.c:1364 -#: sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 sql_help.c:1907 +#: sql_help.c:489 sql_help.c:490 sql_help.c:491 sql_help.c:492 sql_help.c:1382 +#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:1922 msgid "trigger_name" msgstr "nom_trigger" -#: sql_help.c:483 sql_help.c:484 sql_help.c:1378 sql_help.c:1379 -#: sql_help.c:2340 sql_help.c:2345 sql_help.c:2903 sql_help.c:2926 +#: sql_help.c:493 sql_help.c:494 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:2361 sql_help.c:2366 sql_help.c:2920 sql_help.c:2943 msgid "parent_table" msgstr "table_parent" -#: sql_help.c:543 sql_help.c:600 sql_help.c:669 sql_help.c:873 sql_help.c:1023 -#: sql_help.c:1550 sql_help.c:2269 +#: sql_help.c:553 sql_help.c:610 sql_help.c:679 sql_help.c:889 sql_help.c:1039 +#: sql_help.c:1571 sql_help.c:2290 msgid "extension_name" msgstr "nom_extension" -#: sql_help.c:545 sql_help.c:1025 sql_help.c:2403 +#: sql_help.c:555 sql_help.c:1041 sql_help.c:2424 msgid "execution_cost" msgstr "coût_exécution" -#: sql_help.c:546 sql_help.c:1026 sql_help.c:2404 +#: sql_help.c:556 sql_help.c:1042 sql_help.c:2425 msgid "result_rows" msgstr "lignes_de_résultat" -#: sql_help.c:547 sql_help.c:2405 +#: sql_help.c:557 sql_help.c:2426 msgid "support_function" msgstr "fonction_support" -#: sql_help.c:569 sql_help.c:571 sql_help.c:948 sql_help.c:956 sql_help.c:960 -#: sql_help.c:963 sql_help.c:966 sql_help.c:1633 sql_help.c:1641 -#: sql_help.c:1645 sql_help.c:1648 sql_help.c:1651 sql_help.c:2717 -#: sql_help.c:2719 sql_help.c:2722 sql_help.c:2723 sql_help.c:3891 -#: sql_help.c:3892 sql_help.c:3896 sql_help.c:3897 sql_help.c:3900 -#: sql_help.c:3901 sql_help.c:3903 sql_help.c:3904 sql_help.c:3906 -#: sql_help.c:3907 sql_help.c:3909 sql_help.c:3910 sql_help.c:3912 -#: sql_help.c:3913 sql_help.c:3919 sql_help.c:3920 sql_help.c:3922 -#: sql_help.c:3923 sql_help.c:3925 sql_help.c:3926 sql_help.c:3928 -#: sql_help.c:3929 sql_help.c:3931 sql_help.c:3932 sql_help.c:3934 -#: sql_help.c:3935 sql_help.c:3937 sql_help.c:3938 sql_help.c:3940 -#: sql_help.c:3941 sql_help.c:4343 sql_help.c:4344 sql_help.c:4348 -#: sql_help.c:4349 sql_help.c:4352 sql_help.c:4353 sql_help.c:4355 -#: sql_help.c:4356 sql_help.c:4358 sql_help.c:4359 sql_help.c:4361 -#: sql_help.c:4362 sql_help.c:4364 sql_help.c:4365 sql_help.c:4371 -#: sql_help.c:4372 sql_help.c:4374 sql_help.c:4375 sql_help.c:4377 -#: sql_help.c:4378 sql_help.c:4380 sql_help.c:4381 sql_help.c:4383 -#: sql_help.c:4384 sql_help.c:4386 sql_help.c:4387 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4392 sql_help.c:4393 +#: sql_help.c:579 sql_help.c:581 sql_help.c:964 sql_help.c:972 sql_help.c:976 +#: sql_help.c:979 sql_help.c:982 sql_help.c:1654 sql_help.c:1662 +#: sql_help.c:1666 sql_help.c:1669 sql_help.c:1672 sql_help.c:2734 +#: sql_help.c:2736 sql_help.c:2739 sql_help.c:2740 sql_help.c:3912 +#: sql_help.c:3913 sql_help.c:3917 sql_help.c:3918 sql_help.c:3921 +#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 +#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 +#: sql_help.c:3934 sql_help.c:3940 sql_help.c:3941 sql_help.c:3943 +#: sql_help.c:3944 sql_help.c:3946 sql_help.c:3947 sql_help.c:3949 +#: sql_help.c:3950 sql_help.c:3952 sql_help.c:3953 sql_help.c:3955 +#: sql_help.c:3956 sql_help.c:3958 sql_help.c:3959 sql_help.c:3961 +#: sql_help.c:3962 sql_help.c:4375 sql_help.c:4376 sql_help.c:4380 +#: sql_help.c:4381 sql_help.c:4384 sql_help.c:4385 sql_help.c:4387 +#: sql_help.c:4388 sql_help.c:4390 sql_help.c:4391 sql_help.c:4393 +#: sql_help.c:4394 sql_help.c:4396 sql_help.c:4397 sql_help.c:4403 +#: sql_help.c:4404 sql_help.c:4406 sql_help.c:4407 sql_help.c:4409 +#: sql_help.c:4410 sql_help.c:4412 sql_help.c:4413 sql_help.c:4415 +#: sql_help.c:4416 sql_help.c:4418 sql_help.c:4419 sql_help.c:4421 +#: sql_help.c:4422 sql_help.c:4424 sql_help.c:4425 msgid "role_specification" msgstr "specification_role" -#: sql_help.c:570 sql_help.c:572 sql_help.c:1664 sql_help.c:2205 -#: sql_help.c:2725 sql_help.c:3253 sql_help.c:3704 sql_help.c:4720 +#: sql_help.c:580 sql_help.c:582 sql_help.c:1685 sql_help.c:2225 +#: sql_help.c:2742 sql_help.c:3273 sql_help.c:3724 sql_help.c:4753 msgid "user_name" msgstr "nom_utilisateur" -#: sql_help.c:573 sql_help.c:968 sql_help.c:1653 sql_help.c:2724 -#: sql_help.c:3942 sql_help.c:4394 +#: sql_help.c:583 sql_help.c:984 sql_help.c:1674 sql_help.c:2741 +#: sql_help.c:3963 sql_help.c:4426 msgid "where role_specification can be:" msgstr "où specification_role peut être :" -#: sql_help.c:575 +#: sql_help.c:585 msgid "group_name" msgstr "nom_groupe" -#: sql_help.c:596 sql_help.c:1425 sql_help.c:2216 sql_help.c:2476 -#: sql_help.c:2510 sql_help.c:2911 sql_help.c:2924 sql_help.c:2938 -#: sql_help.c:2979 sql_help.c:3006 sql_help.c:3018 sql_help.c:3933 -#: sql_help.c:4385 +#: sql_help.c:606 sql_help.c:1443 sql_help.c:2237 sql_help.c:2497 +#: sql_help.c:2531 sql_help.c:2928 sql_help.c:2941 sql_help.c:2955 +#: sql_help.c:2996 sql_help.c:3026 sql_help.c:3038 sql_help.c:3954 +#: sql_help.c:4417 msgid "tablespace_name" msgstr "nom_tablespace" -#: sql_help.c:598 sql_help.c:691 sql_help.c:1372 sql_help.c:1382 -#: sql_help.c:1420 sql_help.c:1782 sql_help.c:1785 +#: sql_help.c:608 sql_help.c:701 sql_help.c:1390 sql_help.c:1400 +#: sql_help.c:1438 sql_help.c:1800 msgid "index_name" msgstr "nom_index" -#: sql_help.c:602 sql_help.c:605 sql_help.c:694 sql_help.c:696 sql_help.c:1375 -#: sql_help.c:1377 sql_help.c:1423 sql_help.c:2474 sql_help.c:2508 -#: sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 sql_help.c:2977 -#: sql_help.c:3004 +#: sql_help.c:612 sql_help.c:615 sql_help.c:704 sql_help.c:706 sql_help.c:1393 +#: sql_help.c:1395 sql_help.c:1441 sql_help.c:2495 sql_help.c:2529 +#: sql_help.c:2926 sql_help.c:2939 sql_help.c:2953 sql_help.c:2994 +#: sql_help.c:3024 msgid "storage_parameter" msgstr "paramètre_stockage" -#: sql_help.c:607 +#: sql_help.c:617 msgid "column_number" msgstr "numéro_colonne" -#: sql_help.c:631 sql_help.c:1870 sql_help.c:4477 +#: sql_help.c:641 sql_help.c:1885 sql_help.c:4509 msgid "large_object_oid" msgstr "oid_large_object" -#: sql_help.c:690 sql_help.c:1358 sql_help.c:2897 +#: sql_help.c:700 sql_help.c:1376 sql_help.c:2914 msgid "compression_method" msgstr "méthode_compression" -#: sql_help.c:692 sql_help.c:1373 +#: sql_help.c:702 sql_help.c:1391 msgid "new_access_method" msgstr "new_access_method" -#: sql_help.c:725 sql_help.c:2531 +#: sql_help.c:739 sql_help.c:2552 msgid "res_proc" msgstr "res_proc" -#: sql_help.c:726 sql_help.c:2532 +#: sql_help.c:740 sql_help.c:2553 msgid "join_proc" msgstr "join_proc" -#: sql_help.c:778 sql_help.c:790 sql_help.c:2549 +#: sql_help.c:741 sql_help.c:2550 +msgid "com_op" +msgstr "com_op" + +#: sql_help.c:742 sql_help.c:2551 +msgid "neg_op" +msgstr "neg_op" + +#: sql_help.c:794 sql_help.c:806 sql_help.c:2570 msgid "strategy_number" msgstr "numéro_de_stratégie" -#: sql_help.c:780 sql_help.c:781 sql_help.c:784 sql_help.c:785 sql_help.c:791 -#: sql_help.c:792 sql_help.c:794 sql_help.c:795 sql_help.c:2551 sql_help.c:2552 -#: sql_help.c:2555 sql_help.c:2556 +#: sql_help.c:796 sql_help.c:797 sql_help.c:800 sql_help.c:801 sql_help.c:807 +#: sql_help.c:808 sql_help.c:810 sql_help.c:811 sql_help.c:2572 sql_help.c:2573 +#: sql_help.c:2576 sql_help.c:2577 msgid "op_type" msgstr "type_op" -#: sql_help.c:782 sql_help.c:2553 +#: sql_help.c:798 sql_help.c:2574 msgid "sort_family_name" msgstr "nom_famille_tri" -#: sql_help.c:783 sql_help.c:793 sql_help.c:2554 +#: sql_help.c:799 sql_help.c:809 sql_help.c:2575 msgid "support_number" msgstr "numéro_de_support" -#: sql_help.c:787 sql_help.c:2138 sql_help.c:2558 sql_help.c:3095 -#: sql_help.c:3097 +#: sql_help.c:803 sql_help.c:2157 sql_help.c:2579 sql_help.c:3115 +#: sql_help.c:3117 msgid "argument_type" msgstr "type_argument" -#: sql_help.c:818 sql_help.c:821 sql_help.c:910 sql_help.c:1039 sql_help.c:1079 -#: sql_help.c:1546 sql_help.c:1549 sql_help.c:1727 sql_help.c:1781 -#: sql_help.c:1784 sql_help.c:1855 sql_help.c:1880 sql_help.c:1893 -#: sql_help.c:1908 sql_help.c:1966 sql_help.c:1972 sql_help.c:2332 -#: sql_help.c:2344 sql_help.c:2465 sql_help.c:2505 sql_help.c:2582 -#: sql_help.c:2636 sql_help.c:2693 sql_help.c:2745 sql_help.c:2778 -#: sql_help.c:2785 sql_help.c:2894 sql_help.c:2912 sql_help.c:2925 -#: sql_help.c:3001 sql_help.c:3121 sql_help.c:3302 sql_help.c:3525 -#: sql_help.c:3574 sql_help.c:3680 sql_help.c:3889 sql_help.c:3895 -#: sql_help.c:3956 sql_help.c:3988 sql_help.c:4341 sql_help.c:4347 -#: sql_help.c:4465 sql_help.c:4576 sql_help.c:4578 sql_help.c:4640 -#: sql_help.c:4679 sql_help.c:4833 sql_help.c:4835 sql_help.c:4897 -#: sql_help.c:4931 sql_help.c:4991 sql_help.c:5079 sql_help.c:5081 -#: sql_help.c:5143 +#: sql_help.c:834 sql_help.c:837 sql_help.c:926 sql_help.c:1055 sql_help.c:1095 +#: sql_help.c:1567 sql_help.c:1570 sql_help.c:1746 sql_help.c:1799 +#: sql_help.c:1870 sql_help.c:1895 sql_help.c:1908 sql_help.c:1923 +#: sql_help.c:1983 sql_help.c:1989 sql_help.c:2353 sql_help.c:2365 +#: sql_help.c:2486 sql_help.c:2526 sql_help.c:2603 sql_help.c:2657 +#: sql_help.c:2710 sql_help.c:2762 sql_help.c:2795 sql_help.c:2802 +#: sql_help.c:2911 sql_help.c:2929 sql_help.c:2942 sql_help.c:3021 +#: sql_help.c:3141 sql_help.c:3322 sql_help.c:3545 sql_help.c:3594 +#: sql_help.c:3700 sql_help.c:3910 sql_help.c:3916 sql_help.c:3977 +#: sql_help.c:4009 sql_help.c:4373 sql_help.c:4379 sql_help.c:4497 +#: sql_help.c:4610 sql_help.c:4673 sql_help.c:4712 sql_help.c:4868 +#: sql_help.c:4931 sql_help.c:4965 sql_help.c:5023 sql_help.c:5113 +#: sql_help.c:5176 msgid "table_name" msgstr "nom_table" -#: sql_help.c:823 sql_help.c:2584 +#: sql_help.c:839 sql_help.c:2605 msgid "using_expression" msgstr "expression_using" -#: sql_help.c:824 sql_help.c:2585 +#: sql_help.c:840 sql_help.c:2606 msgid "check_expression" msgstr "expression_check" -#: sql_help.c:897 sql_help.c:899 sql_help.c:901 sql_help.c:2632 +#: sql_help.c:913 sql_help.c:915 sql_help.c:917 sql_help.c:2653 msgid "publication_object" msgstr "objet_publication" -#: sql_help.c:903 sql_help.c:2633 +#: sql_help.c:919 sql_help.c:2654 msgid "publication_parameter" msgstr "paramètre_publication" -#: sql_help.c:909 sql_help.c:2635 +#: sql_help.c:925 sql_help.c:2656 msgid "where publication_object is one of:" msgstr "où publication_object fait partie de :" -#: sql_help.c:952 sql_help.c:1637 sql_help.c:2443 sql_help.c:2670 -#: sql_help.c:3236 +#: sql_help.c:968 sql_help.c:1658 sql_help.c:2464 sql_help.c:2689 +#: sql_help.c:3256 msgid "password" msgstr "mot_de_passe" -#: sql_help.c:953 sql_help.c:1638 sql_help.c:2444 sql_help.c:2671 -#: sql_help.c:3237 +#: sql_help.c:969 sql_help.c:1659 sql_help.c:2465 sql_help.c:2690 +#: sql_help.c:3257 msgid "timestamp" msgstr "horodatage" -#: sql_help.c:957 sql_help.c:961 sql_help.c:964 sql_help.c:967 sql_help.c:1642 -#: sql_help.c:1646 sql_help.c:1649 sql_help.c:1652 sql_help.c:3902 -#: sql_help.c:4354 +#: sql_help.c:973 sql_help.c:977 sql_help.c:980 sql_help.c:983 sql_help.c:1663 +#: sql_help.c:1667 sql_help.c:1670 sql_help.c:1673 sql_help.c:3923 +#: sql_help.c:4386 msgid "database_name" msgstr "nom_base_de_donnée" -#: sql_help.c:1073 sql_help.c:2740 +#: sql_help.c:1089 sql_help.c:2757 msgid "increment" msgstr "incrément" -#: sql_help.c:1074 sql_help.c:2741 +#: sql_help.c:1090 sql_help.c:2758 msgid "minvalue" msgstr "valeur_min" -#: sql_help.c:1075 sql_help.c:2742 +#: sql_help.c:1091 sql_help.c:2759 msgid "maxvalue" msgstr "valeur_max" -#: sql_help.c:1076 sql_help.c:2743 sql_help.c:4574 sql_help.c:4677 -#: sql_help.c:4831 sql_help.c:5008 sql_help.c:5077 +#: sql_help.c:1092 sql_help.c:2760 sql_help.c:4606 sql_help.c:4710 +#: sql_help.c:4864 sql_help.c:5040 sql_help.c:5109 msgid "start" msgstr "début" -#: sql_help.c:1077 sql_help.c:1347 +#: sql_help.c:1093 sql_help.c:1365 msgid "restart" msgstr "nouveau_début" -#: sql_help.c:1078 sql_help.c:2744 +#: sql_help.c:1094 sql_help.c:2761 msgid "cache" msgstr "cache" -#: sql_help.c:1123 +#: sql_help.c:1139 msgid "new_target" msgstr "nouvelle_cible" -#: sql_help.c:1142 sql_help.c:2797 +#: sql_help.c:1158 sql_help.c:2814 msgid "conninfo" msgstr "conninfo" -#: sql_help.c:1144 sql_help.c:1148 sql_help.c:1152 sql_help.c:2798 +#: sql_help.c:1160 sql_help.c:1164 sql_help.c:1168 sql_help.c:2815 msgid "publication_name" msgstr "nom_publication" -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 +#: sql_help.c:1161 sql_help.c:1165 sql_help.c:1169 msgid "publication_option" msgstr "option_publication" -#: sql_help.c:1156 +#: sql_help.c:1172 msgid "refresh_option" msgstr "option_rafraichissement" -#: sql_help.c:1161 sql_help.c:2799 +#: sql_help.c:1177 sql_help.c:2816 msgid "subscription_parameter" msgstr "paramètre_souscription" -#: sql_help.c:1164 +#: sql_help.c:1180 msgid "skip_option" msgstr "option_skip" -#: sql_help.c:1324 sql_help.c:1327 +#: sql_help.c:1340 sql_help.c:1343 msgid "partition_name" msgstr "nom_partition" -#: sql_help.c:1325 sql_help.c:2349 sql_help.c:2930 +#: sql_help.c:1341 sql_help.c:2370 sql_help.c:2947 msgid "partition_bound_spec" msgstr "spec_limite_partition" -#: sql_help.c:1344 sql_help.c:1394 sql_help.c:2944 +#: sql_help.c:1362 sql_help.c:1412 sql_help.c:2961 msgid "sequence_options" msgstr "options_séquence" -#: sql_help.c:1346 +#: sql_help.c:1364 msgid "sequence_option" msgstr "option_séquence" -#: sql_help.c:1360 +#: sql_help.c:1378 msgid "table_constraint_using_index" msgstr "contrainte_table_utilisant_index" -#: sql_help.c:1368 sql_help.c:1369 sql_help.c:1370 sql_help.c:1371 +#: sql_help.c:1386 sql_help.c:1387 sql_help.c:1388 sql_help.c:1389 msgid "rewrite_rule_name" msgstr "nom_règle_réécriture" -#: sql_help.c:1383 sql_help.c:2361 sql_help.c:2969 +#: sql_help.c:1401 sql_help.c:2382 sql_help.c:2986 msgid "and partition_bound_spec is:" msgstr "et partition_bound_spec est :" -#: sql_help.c:1384 sql_help.c:1385 sql_help.c:1386 sql_help.c:2362 -#: sql_help.c:2363 sql_help.c:2364 sql_help.c:2970 sql_help.c:2971 -#: sql_help.c:2972 +#: sql_help.c:1402 sql_help.c:1403 sql_help.c:1404 sql_help.c:2383 +#: sql_help.c:2384 sql_help.c:2385 sql_help.c:2987 sql_help.c:2988 +#: sql_help.c:2989 msgid "partition_bound_expr" msgstr "expr_limite_partition" -#: sql_help.c:1387 sql_help.c:1388 sql_help.c:2365 sql_help.c:2366 -#: sql_help.c:2973 sql_help.c:2974 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:2386 sql_help.c:2387 +#: sql_help.c:2990 sql_help.c:2991 msgid "numeric_literal" msgstr "numeric_literal" -#: sql_help.c:1389 +#: sql_help.c:1407 msgid "and column_constraint is:" msgstr "et contrainte_colonne est :" -#: sql_help.c:1392 sql_help.c:2356 sql_help.c:2397 sql_help.c:2606 -#: sql_help.c:2942 +#: sql_help.c:1410 sql_help.c:2377 sql_help.c:2418 sql_help.c:2627 +#: sql_help.c:2959 msgid "default_expr" msgstr "expression_par_défaut" -#: sql_help.c:1393 sql_help.c:2357 sql_help.c:2943 +#: sql_help.c:1411 sql_help.c:2378 sql_help.c:2960 msgid "generation_expr" msgstr "expression_génération" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1405 sql_help.c:1407 -#: sql_help.c:1411 sql_help.c:2945 sql_help.c:2946 sql_help.c:2955 -#: sql_help.c:2957 sql_help.c:2961 +#: sql_help.c:1413 sql_help.c:1414 sql_help.c:1423 sql_help.c:1425 +#: sql_help.c:1429 sql_help.c:2962 sql_help.c:2963 sql_help.c:2972 +#: sql_help.c:2974 sql_help.c:2978 msgid "index_parameters" msgstr "paramètres_index" -#: sql_help.c:1397 sql_help.c:1414 sql_help.c:2947 sql_help.c:2964 +#: sql_help.c:1415 sql_help.c:1432 sql_help.c:2964 sql_help.c:2981 msgid "reftable" msgstr "table_référence" -#: sql_help.c:1398 sql_help.c:1415 sql_help.c:2948 sql_help.c:2965 +#: sql_help.c:1416 sql_help.c:1433 sql_help.c:2965 sql_help.c:2982 msgid "refcolumn" msgstr "colonne_référence" -#: sql_help.c:1399 sql_help.c:1400 sql_help.c:1416 sql_help.c:1417 -#: sql_help.c:2949 sql_help.c:2950 sql_help.c:2966 sql_help.c:2967 +#: sql_help.c:1417 sql_help.c:1418 sql_help.c:1434 sql_help.c:1435 +#: sql_help.c:2966 sql_help.c:2967 sql_help.c:2983 sql_help.c:2984 msgid "referential_action" msgstr "action" -#: sql_help.c:1401 sql_help.c:2358 sql_help.c:2951 +#: sql_help.c:1419 sql_help.c:2379 sql_help.c:2968 msgid "and table_constraint is:" msgstr "et contrainte_table est :" -#: sql_help.c:1409 sql_help.c:2959 +#: sql_help.c:1427 sql_help.c:2976 msgid "exclude_element" msgstr "élément_exclusion" -#: sql_help.c:1410 sql_help.c:2960 sql_help.c:4572 sql_help.c:4675 -#: sql_help.c:4829 sql_help.c:5006 sql_help.c:5075 +#: sql_help.c:1428 sql_help.c:2977 sql_help.c:4604 sql_help.c:4708 +#: sql_help.c:4862 sql_help.c:5038 sql_help.c:5107 msgid "operator" msgstr "opérateur" -#: sql_help.c:1412 sql_help.c:2477 sql_help.c:2962 +#: sql_help.c:1430 sql_help.c:2498 sql_help.c:2979 msgid "predicate" msgstr "prédicat" -#: sql_help.c:1418 +#: sql_help.c:1436 msgid "and table_constraint_using_index is:" msgstr "et contrainte_table_utilisant_index est :" -#: sql_help.c:1421 sql_help.c:2975 +#: sql_help.c:1439 sql_help.c:2992 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "dans les contraintes UNIQUE, PRIMARY KEY et EXCLUDE, les paramètres_index sont :" -#: sql_help.c:1426 sql_help.c:2980 +#: sql_help.c:1444 sql_help.c:2997 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "élément_exclusion dans une contrainte EXCLUDE est :" -#: sql_help.c:1429 sql_help.c:2470 sql_help.c:2907 sql_help.c:2920 -#: sql_help.c:2934 sql_help.c:2983 sql_help.c:4001 +#: sql_help.c:1448 sql_help.c:2491 sql_help.c:2924 sql_help.c:2937 +#: sql_help.c:2951 sql_help.c:3001 sql_help.c:4022 msgid "opclass" msgstr "classe_d_opérateur" -#: sql_help.c:1430 sql_help.c:2984 +#: sql_help.c:1449 sql_help.c:2492 sql_help.c:3002 +msgid "opclass_parameter" +msgstr "paramètre_opclass" + +#: sql_help.c:1451 sql_help.c:3004 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "referential_action dans une contrainte FOREIGN KEY/REFERENCES est :" -#: sql_help.c:1448 sql_help.c:1451 sql_help.c:3021 +#: sql_help.c:1469 sql_help.c:1472 sql_help.c:3041 msgid "tablespace_option" msgstr "option_tablespace" -#: sql_help.c:1472 sql_help.c:1475 sql_help.c:1481 sql_help.c:1485 +#: sql_help.c:1493 sql_help.c:1496 sql_help.c:1502 sql_help.c:1506 msgid "token_type" msgstr "type_jeton" -#: sql_help.c:1473 sql_help.c:1476 +#: sql_help.c:1494 sql_help.c:1497 msgid "dictionary_name" msgstr "nom_dictionnaire" -#: sql_help.c:1478 sql_help.c:1482 +#: sql_help.c:1499 sql_help.c:1503 msgid "old_dictionary" msgstr "ancien_dictionnaire" -#: sql_help.c:1479 sql_help.c:1483 +#: sql_help.c:1500 sql_help.c:1504 msgid "new_dictionary" msgstr "nouveau_dictionnaire" -#: sql_help.c:1578 sql_help.c:1592 sql_help.c:1595 sql_help.c:1596 -#: sql_help.c:3174 +#: sql_help.c:1599 sql_help.c:1613 sql_help.c:1616 sql_help.c:1617 +#: sql_help.c:3194 msgid "attribute_name" msgstr "nom_attribut" -#: sql_help.c:1579 +#: sql_help.c:1600 msgid "new_attribute_name" msgstr "nouveau_nom_attribut" -#: sql_help.c:1583 sql_help.c:1587 +#: sql_help.c:1604 sql_help.c:1608 msgid "new_enum_value" msgstr "nouvelle_valeur_enum" -#: sql_help.c:1584 +#: sql_help.c:1605 msgid "neighbor_enum_value" msgstr "valeur_enum_voisine" -#: sql_help.c:1586 +#: sql_help.c:1607 msgid "existing_enum_value" msgstr "valeur_enum_existante" -#: sql_help.c:1589 +#: sql_help.c:1610 msgid "property" msgstr "propriété" -#: sql_help.c:1665 sql_help.c:2341 sql_help.c:2350 sql_help.c:2756 -#: sql_help.c:3254 sql_help.c:3705 sql_help.c:3911 sql_help.c:3957 -#: sql_help.c:4363 +#: sql_help.c:1686 sql_help.c:2362 sql_help.c:2371 sql_help.c:2773 +#: sql_help.c:3274 sql_help.c:3725 sql_help.c:3932 sql_help.c:3978 +#: sql_help.c:4395 msgid "server_name" msgstr "nom_serveur" -#: sql_help.c:1697 sql_help.c:1700 sql_help.c:3269 +#: sql_help.c:1718 sql_help.c:1721 sql_help.c:3289 msgid "view_option_name" msgstr "nom_option_vue" -#: sql_help.c:1698 sql_help.c:3270 +#: sql_help.c:1719 sql_help.c:3290 msgid "view_option_value" msgstr "valeur_option_vue" -#: sql_help.c:1720 sql_help.c:1721 sql_help.c:4974 sql_help.c:4975 +#: sql_help.c:1740 sql_help.c:5007 msgid "table_and_columns" msgstr "table_et_colonnes" -#: sql_help.c:1722 sql_help.c:1786 sql_help.c:1978 sql_help.c:3754 -#: sql_help.c:4198 sql_help.c:4976 +#: sql_help.c:1741 sql_help.c:1801 sql_help.c:1995 sql_help.c:3774 +#: sql_help.c:4230 sql_help.c:5008 msgid "where option can be one of:" msgstr "où option fait partie de :" -#: sql_help.c:1723 sql_help.c:1724 sql_help.c:1787 sql_help.c:1980 -#: sql_help.c:1984 sql_help.c:2164 sql_help.c:3755 sql_help.c:3756 -#: sql_help.c:3757 sql_help.c:3758 sql_help.c:3759 sql_help.c:3760 -#: sql_help.c:3761 sql_help.c:3762 sql_help.c:3763 sql_help.c:4199 -#: sql_help.c:4201 sql_help.c:4977 sql_help.c:4978 sql_help.c:4979 -#: sql_help.c:4980 sql_help.c:4981 sql_help.c:4982 sql_help.c:4983 -#: sql_help.c:4984 sql_help.c:4985 sql_help.c:4987 sql_help.c:4988 +#: sql_help.c:1742 sql_help.c:1743 sql_help.c:1802 sql_help.c:1997 +#: sql_help.c:2001 sql_help.c:2183 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:3777 sql_help.c:3778 sql_help.c:3779 sql_help.c:3780 +#: sql_help.c:3781 sql_help.c:3782 sql_help.c:3783 sql_help.c:3784 +#: sql_help.c:4231 sql_help.c:4233 sql_help.c:5009 sql_help.c:5010 +#: sql_help.c:5011 sql_help.c:5012 sql_help.c:5013 sql_help.c:5014 +#: sql_help.c:5015 sql_help.c:5016 sql_help.c:5017 sql_help.c:5019 +#: sql_help.c:5020 msgid "boolean" msgstr "boolean" -#: sql_help.c:1725 sql_help.c:4989 +#: sql_help.c:1744 sql_help.c:5021 msgid "size" msgstr "taille" -#: sql_help.c:1726 sql_help.c:4990 +#: sql_help.c:1745 sql_help.c:5022 msgid "and table_and_columns is:" msgstr "et table_et_colonnes est :" -#: sql_help.c:1742 sql_help.c:4736 sql_help.c:4738 sql_help.c:4762 +#: sql_help.c:1761 sql_help.c:4769 sql_help.c:4771 sql_help.c:4795 msgid "transaction_mode" msgstr "mode_transaction" -#: sql_help.c:1743 sql_help.c:4739 sql_help.c:4763 +#: sql_help.c:1762 sql_help.c:4772 sql_help.c:4796 msgid "where transaction_mode is one of:" msgstr "où mode_transaction fait partie de :" -#: sql_help.c:1752 sql_help.c:4582 sql_help.c:4591 sql_help.c:4595 -#: sql_help.c:4599 sql_help.c:4602 sql_help.c:4839 sql_help.c:4848 -#: sql_help.c:4852 sql_help.c:4856 sql_help.c:4859 sql_help.c:5085 -#: sql_help.c:5094 sql_help.c:5098 sql_help.c:5102 sql_help.c:5105 +#: sql_help.c:1771 sql_help.c:4614 sql_help.c:4623 sql_help.c:4627 +#: sql_help.c:4631 sql_help.c:4634 sql_help.c:4872 sql_help.c:4881 +#: sql_help.c:4885 sql_help.c:4889 sql_help.c:4892 sql_help.c:5117 +#: sql_help.c:5126 sql_help.c:5130 sql_help.c:5134 sql_help.c:5137 msgid "argument" msgstr "argument" -#: sql_help.c:1852 +#: sql_help.c:1867 msgid "relation_name" msgstr "nom_relation" -#: sql_help.c:1857 sql_help.c:3905 sql_help.c:4357 +#: sql_help.c:1872 sql_help.c:3926 sql_help.c:4389 msgid "domain_name" msgstr "nom_domaine" -#: sql_help.c:1879 +#: sql_help.c:1894 msgid "policy_name" msgstr "nom_politique" -#: sql_help.c:1892 +#: sql_help.c:1907 msgid "rule_name" msgstr "nom_règle" -#: sql_help.c:1911 sql_help.c:4496 +#: sql_help.c:1926 sql_help.c:4528 msgid "string_literal" msgstr "littéral_chaîne" -#: sql_help.c:1936 sql_help.c:4160 sql_help.c:4410 +#: sql_help.c:1951 sql_help.c:4192 sql_help.c:4442 msgid "transaction_id" msgstr "id_transaction" -#: sql_help.c:1968 sql_help.c:1975 sql_help.c:4027 +#: sql_help.c:1985 sql_help.c:1992 sql_help.c:4048 msgid "filename" msgstr "nom_fichier" -#: sql_help.c:1969 sql_help.c:1976 sql_help.c:2695 sql_help.c:2696 -#: sql_help.c:2697 +#: sql_help.c:1986 sql_help.c:1993 sql_help.c:2712 sql_help.c:2713 +#: sql_help.c:2714 msgid "command" msgstr "commande" -#: sql_help.c:1971 sql_help.c:2694 sql_help.c:3124 sql_help.c:3305 -#: sql_help.c:4011 sql_help.c:4088 sql_help.c:4091 sql_help.c:4565 -#: sql_help.c:4567 sql_help.c:4668 sql_help.c:4670 sql_help.c:4822 -#: sql_help.c:4824 sql_help.c:4940 sql_help.c:5068 sql_help.c:5070 +#: sql_help.c:1988 sql_help.c:2711 sql_help.c:3144 sql_help.c:3325 +#: sql_help.c:4032 sql_help.c:4115 sql_help.c:4118 sql_help.c:4121 +#: sql_help.c:4597 sql_help.c:4599 sql_help.c:4701 sql_help.c:4703 +#: sql_help.c:4855 sql_help.c:4857 sql_help.c:4974 sql_help.c:5100 +#: sql_help.c:5102 msgid "condition" msgstr "condition" -#: sql_help.c:1974 sql_help.c:2511 sql_help.c:3007 sql_help.c:3271 -#: sql_help.c:3289 sql_help.c:3992 +#: sql_help.c:1991 sql_help.c:2532 sql_help.c:3027 sql_help.c:3291 +#: sql_help.c:3309 sql_help.c:4013 msgid "query" msgstr "requête" -#: sql_help.c:1979 +#: sql_help.c:1996 msgid "format_name" msgstr "nom_format" -#: sql_help.c:1981 +#: sql_help.c:1998 msgid "delimiter_character" msgstr "caractère_délimiteur" -#: sql_help.c:1982 +#: sql_help.c:1999 msgid "null_string" msgstr "chaîne_null" -#: sql_help.c:1983 +#: sql_help.c:2000 msgid "default_string" msgstr "chaîne_par_défaut" -#: sql_help.c:1985 +#: sql_help.c:2002 msgid "quote_character" msgstr "caractère_guillemet" -#: sql_help.c:1986 +#: sql_help.c:2003 msgid "escape_character" msgstr "chaîne_d_échappement" -#: sql_help.c:1990 +#: sql_help.c:2007 +msgid "error_action" +msgstr "action_erreur" + +#: sql_help.c:2008 msgid "encoding_name" msgstr "nom_encodage" -#: sql_help.c:2001 +#: sql_help.c:2009 +msgid "verbosity" +msgstr "verbosité" + +#: sql_help.c:2020 msgid "access_method_type" msgstr "access_method_type" -#: sql_help.c:2072 sql_help.c:2091 sql_help.c:2094 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2113 msgid "arg_data_type" msgstr "type_données_arg" -#: sql_help.c:2073 sql_help.c:2095 sql_help.c:2103 +#: sql_help.c:2092 sql_help.c:2114 sql_help.c:2122 msgid "sfunc" msgstr "sfunc" -#: sql_help.c:2074 sql_help.c:2096 sql_help.c:2104 +#: sql_help.c:2093 sql_help.c:2115 sql_help.c:2123 msgid "state_data_type" msgstr "type_de_données_statut" -#: sql_help.c:2075 sql_help.c:2097 sql_help.c:2105 +#: sql_help.c:2094 sql_help.c:2116 sql_help.c:2124 msgid "state_data_size" msgstr "taille_de_données_statut" -#: sql_help.c:2076 sql_help.c:2098 sql_help.c:2106 +#: sql_help.c:2095 sql_help.c:2117 sql_help.c:2125 msgid "ffunc" msgstr "ffunc" -#: sql_help.c:2077 sql_help.c:2107 +#: sql_help.c:2096 sql_help.c:2126 msgid "combinefunc" msgstr "combinefunc" -#: sql_help.c:2078 sql_help.c:2108 +#: sql_help.c:2097 sql_help.c:2127 msgid "serialfunc" msgstr "serialfunc" -#: sql_help.c:2079 sql_help.c:2109 +#: sql_help.c:2098 sql_help.c:2128 msgid "deserialfunc" msgstr "deserialfunc" -#: sql_help.c:2080 sql_help.c:2099 sql_help.c:2110 +#: sql_help.c:2099 sql_help.c:2118 sql_help.c:2129 msgid "initial_condition" msgstr "condition_initiale" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2100 sql_help.c:2130 msgid "msfunc" msgstr "msfunc" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2101 sql_help.c:2131 msgid "minvfunc" msgstr "minvfunc" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2102 sql_help.c:2132 msgid "mstate_data_type" msgstr "m_type_de_données_statut" -#: sql_help.c:2084 sql_help.c:2114 +#: sql_help.c:2103 sql_help.c:2133 msgid "mstate_data_size" msgstr "m_taille_de_données_statut" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2104 sql_help.c:2134 msgid "mffunc" msgstr "mffunc" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2105 sql_help.c:2135 msgid "minitial_condition" msgstr "m_condition_initiale" -#: sql_help.c:2087 sql_help.c:2117 +#: sql_help.c:2106 sql_help.c:2136 msgid "sort_operator" msgstr "opérateur_de_tri" -#: sql_help.c:2100 +#: sql_help.c:2119 msgid "or the old syntax" msgstr "ou l'ancienne syntaxe" -#: sql_help.c:2102 +#: sql_help.c:2121 msgid "base_type" msgstr "type_base" -#: sql_help.c:2160 sql_help.c:2209 +#: sql_help.c:2179 sql_help.c:2229 msgid "locale" msgstr "locale" -#: sql_help.c:2161 sql_help.c:2210 +#: sql_help.c:2180 sql_help.c:2230 msgid "lc_collate" msgstr "lc_collate" -#: sql_help.c:2162 sql_help.c:2211 +#: sql_help.c:2181 sql_help.c:2231 msgid "lc_ctype" msgstr "lc_ctype" -#: sql_help.c:2163 sql_help.c:4463 +#: sql_help.c:2182 sql_help.c:4495 msgid "provider" msgstr "fournisseur" -#: sql_help.c:2165 +#: sql_help.c:2184 msgid "rules" msgstr "règles" -#: sql_help.c:2166 sql_help.c:2271 +#: sql_help.c:2185 sql_help.c:2292 msgid "version" msgstr "version" -#: sql_help.c:2168 +#: sql_help.c:2187 msgid "existing_collation" msgstr "collationnement_existant" -#: sql_help.c:2178 +#: sql_help.c:2197 msgid "source_encoding" msgstr "encodage_source" -#: sql_help.c:2179 +#: sql_help.c:2198 msgid "dest_encoding" msgstr "encodage_destination" -#: sql_help.c:2206 sql_help.c:3047 +#: sql_help.c:2226 sql_help.c:3067 msgid "template" msgstr "modèle" -#: sql_help.c:2207 +#: sql_help.c:2227 msgid "encoding" msgstr "encodage" -#: sql_help.c:2208 +#: sql_help.c:2228 msgid "strategy" msgstr "stratégie" -#: sql_help.c:2212 +#: sql_help.c:2232 +msgid "builtin_locale" +msgstr "builtin_locale" + +#: sql_help.c:2233 msgid "icu_locale" msgstr "icu_locale" -#: sql_help.c:2213 +#: sql_help.c:2234 msgid "icu_rules" msgstr "règles_icu" -#: sql_help.c:2214 +#: sql_help.c:2235 msgid "locale_provider" msgstr "locale_provider" -#: sql_help.c:2215 +#: sql_help.c:2236 msgid "collation_version" msgstr "collation_version" -#: sql_help.c:2220 +#: sql_help.c:2241 msgid "oid" msgstr "oid" -#: sql_help.c:2240 -msgid "constraint" -msgstr "contrainte" - -#: sql_help.c:2241 -msgid "where constraint is:" -msgstr "où la contrainte est :" - -#: sql_help.c:2255 sql_help.c:2692 sql_help.c:3120 +#: sql_help.c:2276 sql_help.c:2709 sql_help.c:3140 msgid "event" msgstr "événement" -#: sql_help.c:2256 +#: sql_help.c:2277 msgid "filter_variable" msgstr "filter_variable" -#: sql_help.c:2257 +#: sql_help.c:2278 msgid "filter_value" msgstr "filtre_valeur" -#: sql_help.c:2353 sql_help.c:2939 +#: sql_help.c:2374 sql_help.c:2956 msgid "where column_constraint is:" msgstr "où contrainte_colonne est :" -#: sql_help.c:2398 +#: sql_help.c:2419 msgid "rettype" msgstr "type_en_retour" -#: sql_help.c:2400 +#: sql_help.c:2421 msgid "column_type" msgstr "type_colonne" -#: sql_help.c:2409 sql_help.c:2612 +#: sql_help.c:2430 sql_help.c:2633 msgid "definition" msgstr "définition" -#: sql_help.c:2410 sql_help.c:2613 +#: sql_help.c:2431 sql_help.c:2634 msgid "obj_file" msgstr "fichier_objet" -#: sql_help.c:2411 sql_help.c:2614 +#: sql_help.c:2432 sql_help.c:2635 msgid "link_symbol" msgstr "symbole_link" -#: sql_help.c:2412 sql_help.c:2615 +#: sql_help.c:2433 sql_help.c:2636 msgid "sql_body" msgstr "corps_sql" -#: sql_help.c:2450 sql_help.c:2677 sql_help.c:3243 +#: sql_help.c:2471 sql_help.c:2694 sql_help.c:3263 msgid "uid" msgstr "uid" -#: sql_help.c:2466 sql_help.c:2507 sql_help.c:2908 sql_help.c:2921 -#: sql_help.c:2935 sql_help.c:3003 +#: sql_help.c:2487 sql_help.c:2528 sql_help.c:2925 sql_help.c:2938 +#: sql_help.c:2952 sql_help.c:3023 msgid "method" msgstr "méthode" -#: sql_help.c:2471 -msgid "opclass_parameter" -msgstr "paramètre_opclass" - -#: sql_help.c:2488 +#: sql_help.c:2509 msgid "call_handler" msgstr "gestionnaire_d_appel" -#: sql_help.c:2489 +#: sql_help.c:2510 msgid "inline_handler" msgstr "gestionnaire_en_ligne" -#: sql_help.c:2490 +#: sql_help.c:2511 msgid "valfunction" msgstr "fonction_val" -#: sql_help.c:2529 -msgid "com_op" -msgstr "com_op" - -#: sql_help.c:2530 -msgid "neg_op" -msgstr "neg_op" - -#: sql_help.c:2548 +#: sql_help.c:2569 msgid "family_name" msgstr "nom_famille" -#: sql_help.c:2559 +#: sql_help.c:2580 msgid "storage_type" msgstr "type_stockage" -#: sql_help.c:2698 sql_help.c:3127 +#: sql_help.c:2715 sql_help.c:3147 msgid "where event can be one of:" msgstr "où événement fait partie de :" -#: sql_help.c:2718 sql_help.c:2720 +#: sql_help.c:2735 sql_help.c:2737 msgid "schema_element" msgstr "élément_schéma" -#: sql_help.c:2757 +#: sql_help.c:2774 msgid "server_type" msgstr "type_serveur" -#: sql_help.c:2758 +#: sql_help.c:2775 msgid "server_version" msgstr "version_serveur" -#: sql_help.c:2759 sql_help.c:3908 sql_help.c:4360 +#: sql_help.c:2776 sql_help.c:3929 sql_help.c:4392 msgid "fdw_name" msgstr "nom_fdw" -#: sql_help.c:2776 sql_help.c:2779 +#: sql_help.c:2793 sql_help.c:2796 msgid "statistics_name" msgstr "nom_statistique" -#: sql_help.c:2780 +#: sql_help.c:2797 msgid "statistics_kind" msgstr "statistics_kind" -#: sql_help.c:2796 +#: sql_help.c:2813 msgid "subscription_name" msgstr "nom_souscription" -#: sql_help.c:2901 +#: sql_help.c:2918 msgid "source_table" msgstr "table_source" -#: sql_help.c:2902 +#: sql_help.c:2919 msgid "like_option" msgstr "option_like" -#: sql_help.c:2968 +#: sql_help.c:2985 msgid "and like_option is:" msgstr "et option_like est :" -#: sql_help.c:3020 +#: sql_help.c:3040 msgid "directory" msgstr "répertoire" -#: sql_help.c:3034 +#: sql_help.c:3054 msgid "parser_name" msgstr "nom_analyseur" -#: sql_help.c:3035 +#: sql_help.c:3055 msgid "source_config" msgstr "configuration_source" -#: sql_help.c:3064 +#: sql_help.c:3084 msgid "start_function" msgstr "fonction_start" -#: sql_help.c:3065 +#: sql_help.c:3085 msgid "gettoken_function" msgstr "fonction_gettoken" -#: sql_help.c:3066 +#: sql_help.c:3086 msgid "end_function" msgstr "fonction_end" -#: sql_help.c:3067 +#: sql_help.c:3087 msgid "lextypes_function" msgstr "fonction_lextypes" -#: sql_help.c:3068 +#: sql_help.c:3088 msgid "headline_function" msgstr "fonction_headline" -#: sql_help.c:3080 +#: sql_help.c:3100 msgid "init_function" msgstr "fonction_init" -#: sql_help.c:3081 +#: sql_help.c:3101 msgid "lexize_function" msgstr "fonction_lexize" -#: sql_help.c:3094 +#: sql_help.c:3114 msgid "from_sql_function_name" msgstr "nom_fonction_from_sql" -#: sql_help.c:3096 +#: sql_help.c:3116 msgid "to_sql_function_name" msgstr "nom_fonction_to_sql" -#: sql_help.c:3122 +#: sql_help.c:3142 msgid "referenced_table_name" msgstr "nom_table_référencée" -#: sql_help.c:3123 +#: sql_help.c:3143 msgid "transition_relation_name" msgstr "nom_relation_transition" -#: sql_help.c:3126 +#: sql_help.c:3146 msgid "arguments" msgstr "arguments" -#: sql_help.c:3178 +#: sql_help.c:3198 msgid "label" msgstr "label" -#: sql_help.c:3180 +#: sql_help.c:3200 msgid "subtype" msgstr "sous_type" -#: sql_help.c:3181 +#: sql_help.c:3201 msgid "subtype_operator_class" msgstr "classe_opérateur_sous_type" -#: sql_help.c:3183 +#: sql_help.c:3203 msgid "canonical_function" msgstr "fonction_canonique" -#: sql_help.c:3184 +#: sql_help.c:3204 msgid "subtype_diff_function" msgstr "fonction_diff_sous_type" -#: sql_help.c:3185 +#: sql_help.c:3205 msgid "multirange_type_name" msgstr "nom_type_multirange" -#: sql_help.c:3187 +#: sql_help.c:3207 msgid "input_function" msgstr "fonction_en_sortie" -#: sql_help.c:3188 +#: sql_help.c:3208 msgid "output_function" msgstr "fonction_en_sortie" -#: sql_help.c:3189 +#: sql_help.c:3209 msgid "receive_function" msgstr "fonction_receive" -#: sql_help.c:3190 +#: sql_help.c:3210 msgid "send_function" msgstr "fonction_send" -#: sql_help.c:3191 +#: sql_help.c:3211 msgid "type_modifier_input_function" msgstr "fonction_en_entrée_modificateur_type" -#: sql_help.c:3192 +#: sql_help.c:3212 msgid "type_modifier_output_function" msgstr "fonction_en_sortie_modificateur_type" -#: sql_help.c:3193 +#: sql_help.c:3213 msgid "analyze_function" msgstr "fonction_analyze" -#: sql_help.c:3194 +#: sql_help.c:3214 msgid "subscript_function" msgstr "fonction_indice" -#: sql_help.c:3195 +#: sql_help.c:3215 msgid "internallength" msgstr "longueur_interne" -#: sql_help.c:3196 +#: sql_help.c:3216 msgid "alignment" msgstr "alignement" -#: sql_help.c:3197 +#: sql_help.c:3217 msgid "storage" msgstr "stockage" -#: sql_help.c:3198 +#: sql_help.c:3218 msgid "like_type" msgstr "type_like" -#: sql_help.c:3199 +#: sql_help.c:3219 msgid "category" msgstr "catégorie" -#: sql_help.c:3200 +#: sql_help.c:3220 msgid "preferred" msgstr "préféré" -#: sql_help.c:3201 +#: sql_help.c:3221 msgid "default" msgstr "par défaut" -#: sql_help.c:3202 +#: sql_help.c:3222 msgid "element" msgstr "élément" -#: sql_help.c:3203 +#: sql_help.c:3223 msgid "delimiter" msgstr "délimiteur" -#: sql_help.c:3204 +#: sql_help.c:3224 msgid "collatable" msgstr "collationnable" -#: sql_help.c:3301 sql_help.c:3987 sql_help.c:4077 sql_help.c:4560 -#: sql_help.c:4662 sql_help.c:4817 sql_help.c:4930 sql_help.c:5063 +#: sql_help.c:3321 sql_help.c:4008 sql_help.c:4102 sql_help.c:4592 +#: sql_help.c:4695 sql_help.c:4850 sql_help.c:4964 sql_help.c:5095 msgid "with_query" msgstr "requête_with" -#: sql_help.c:3303 sql_help.c:3989 sql_help.c:4579 sql_help.c:4585 -#: sql_help.c:4588 sql_help.c:4592 sql_help.c:4596 sql_help.c:4604 -#: sql_help.c:4836 sql_help.c:4842 sql_help.c:4845 sql_help.c:4849 -#: sql_help.c:4853 sql_help.c:4861 sql_help.c:4932 sql_help.c:5082 -#: sql_help.c:5088 sql_help.c:5091 sql_help.c:5095 sql_help.c:5099 -#: sql_help.c:5107 +#: sql_help.c:3323 sql_help.c:4010 sql_help.c:4611 sql_help.c:4617 +#: sql_help.c:4620 sql_help.c:4624 sql_help.c:4628 sql_help.c:4636 +#: sql_help.c:4869 sql_help.c:4875 sql_help.c:4878 sql_help.c:4882 +#: sql_help.c:4886 sql_help.c:4894 sql_help.c:4966 sql_help.c:5114 +#: sql_help.c:5120 sql_help.c:5123 sql_help.c:5127 sql_help.c:5131 +#: sql_help.c:5139 msgid "alias" msgstr "alias" -#: sql_help.c:3304 sql_help.c:4564 sql_help.c:4606 sql_help.c:4608 -#: sql_help.c:4612 sql_help.c:4614 sql_help.c:4615 sql_help.c:4616 -#: sql_help.c:4667 sql_help.c:4821 sql_help.c:4863 sql_help.c:4865 -#: sql_help.c:4869 sql_help.c:4871 sql_help.c:4872 sql_help.c:4873 -#: sql_help.c:4939 sql_help.c:5067 sql_help.c:5109 sql_help.c:5111 -#: sql_help.c:5115 sql_help.c:5117 sql_help.c:5118 sql_help.c:5119 +#: sql_help.c:3324 sql_help.c:4596 sql_help.c:4638 sql_help.c:4640 +#: sql_help.c:4644 sql_help.c:4646 sql_help.c:4647 sql_help.c:4648 +#: sql_help.c:4700 sql_help.c:4854 sql_help.c:4896 sql_help.c:4898 +#: sql_help.c:4902 sql_help.c:4904 sql_help.c:4905 sql_help.c:4906 +#: sql_help.c:4973 sql_help.c:5099 sql_help.c:5141 sql_help.c:5143 +#: sql_help.c:5147 sql_help.c:5149 sql_help.c:5150 sql_help.c:5151 msgid "from_item" msgstr "élément_from" -#: sql_help.c:3306 sql_help.c:3789 sql_help.c:4127 sql_help.c:4941 +#: sql_help.c:3326 sql_help.c:3810 sql_help.c:4159 sql_help.c:4975 msgid "cursor_name" msgstr "nom_curseur" -#: sql_help.c:3307 sql_help.c:3995 sql_help.c:4942 +#: sql_help.c:3327 sql_help.c:4016 sql_help.c:4108 sql_help.c:4976 msgid "output_expression" msgstr "expression_en_sortie" -#: sql_help.c:3308 sql_help.c:3996 sql_help.c:4563 sql_help.c:4665 -#: sql_help.c:4820 sql_help.c:4943 sql_help.c:5066 +#: sql_help.c:3328 sql_help.c:4017 sql_help.c:4109 sql_help.c:4595 +#: sql_help.c:4698 sql_help.c:4853 sql_help.c:4977 sql_help.c:5098 msgid "output_name" msgstr "nom_en_sortie" -#: sql_help.c:3324 +#: sql_help.c:3344 msgid "code" msgstr "code" -#: sql_help.c:3729 +#: sql_help.c:3749 msgid "parameter" msgstr "paramètre" -#: sql_help.c:3752 sql_help.c:3753 sql_help.c:4152 +#: sql_help.c:3773 sql_help.c:4184 msgid "statement" msgstr "instruction" -#: sql_help.c:3788 sql_help.c:4126 +#: sql_help.c:3809 sql_help.c:4158 msgid "direction" msgstr "direction" -#: sql_help.c:3790 sql_help.c:4128 +#: sql_help.c:3811 sql_help.c:4160 msgid "where direction can be one of:" msgstr "où direction fait partie de :" -#: sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 sql_help.c:3794 -#: sql_help.c:3795 sql_help.c:4129 sql_help.c:4130 sql_help.c:4131 -#: sql_help.c:4132 sql_help.c:4133 sql_help.c:4573 sql_help.c:4575 -#: sql_help.c:4676 sql_help.c:4678 sql_help.c:4830 sql_help.c:4832 -#: sql_help.c:5007 sql_help.c:5009 sql_help.c:5076 sql_help.c:5078 +#: sql_help.c:3812 sql_help.c:3813 sql_help.c:3814 sql_help.c:3815 +#: sql_help.c:3816 sql_help.c:4161 sql_help.c:4162 sql_help.c:4163 +#: sql_help.c:4164 sql_help.c:4165 sql_help.c:4605 sql_help.c:4607 +#: sql_help.c:4709 sql_help.c:4711 sql_help.c:4863 sql_help.c:4865 +#: sql_help.c:5039 sql_help.c:5041 sql_help.c:5108 sql_help.c:5110 msgid "count" msgstr "nombre" -#: sql_help.c:3898 sql_help.c:4350 +#: sql_help.c:3919 sql_help.c:4382 msgid "sequence_name" msgstr "nom_séquence" -#: sql_help.c:3916 sql_help.c:4368 +#: sql_help.c:3937 sql_help.c:4400 msgid "arg_name" msgstr "nom_argument" -#: sql_help.c:3917 sql_help.c:4369 +#: sql_help.c:3938 sql_help.c:4401 msgid "arg_type" msgstr "type_arg" -#: sql_help.c:3924 sql_help.c:4376 +#: sql_help.c:3945 sql_help.c:4408 msgid "loid" msgstr "loid" -#: sql_help.c:3955 +#: sql_help.c:3976 msgid "remote_schema" msgstr "schema_distant" -#: sql_help.c:3958 +#: sql_help.c:3979 msgid "local_schema" msgstr "schéma_local" -#: sql_help.c:3993 +#: sql_help.c:4014 msgid "conflict_target" msgstr "cible_conflit" -#: sql_help.c:3994 +#: sql_help.c:4015 msgid "conflict_action" msgstr "action_conflit" -#: sql_help.c:3997 +#: sql_help.c:4018 msgid "where conflict_target can be one of:" msgstr "où cible_conflit fait partie de :" -#: sql_help.c:3998 +#: sql_help.c:4019 msgid "index_column_name" msgstr "index_nom_colonne" -#: sql_help.c:3999 +#: sql_help.c:4020 msgid "index_expression" msgstr "index_expression" -#: sql_help.c:4002 +#: sql_help.c:4023 msgid "index_predicate" msgstr "index_prédicat" -#: sql_help.c:4004 +#: sql_help.c:4025 msgid "and conflict_action is one of:" msgstr "où action_conflit fait partie de :" -#: sql_help.c:4010 sql_help.c:4938 +#: sql_help.c:4031 sql_help.c:4132 sql_help.c:4972 msgid "sub-SELECT" msgstr "sous-SELECT" -#: sql_help.c:4019 sql_help.c:4141 sql_help.c:4914 +#: sql_help.c:4040 sql_help.c:4173 sql_help.c:4948 msgid "channel" msgstr "canal" -#: sql_help.c:4041 +#: sql_help.c:4062 msgid "lockmode" msgstr "mode_de_verrou" -#: sql_help.c:4042 +#: sql_help.c:4063 msgid "where lockmode is one of:" msgstr "où mode_de_verrou fait partie de :" -#: sql_help.c:4078 +#: sql_help.c:4103 msgid "target_table_name" msgstr "target_table_name" -#: sql_help.c:4079 +#: sql_help.c:4104 msgid "target_alias" msgstr "target_alias" -#: sql_help.c:4080 +#: sql_help.c:4105 msgid "data_source" msgstr "data_source" -#: sql_help.c:4081 sql_help.c:4609 sql_help.c:4866 sql_help.c:5112 +#: sql_help.c:4106 sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "join_condition" msgstr "condition_de_jointure" -#: sql_help.c:4082 +#: sql_help.c:4107 msgid "when_clause" msgstr "when_clause" -#: sql_help.c:4083 +#: sql_help.c:4110 msgid "where data_source is:" msgstr "où data_source est :" -#: sql_help.c:4084 +#: sql_help.c:4111 msgid "source_table_name" msgstr "source_table_name" -#: sql_help.c:4085 +#: sql_help.c:4112 msgid "source_query" msgstr "source_query" -#: sql_help.c:4086 +#: sql_help.c:4113 msgid "source_alias" msgstr "source_alias" -#: sql_help.c:4087 +#: sql_help.c:4114 msgid "and when_clause is:" msgstr "et when_clause est :" -#: sql_help.c:4089 +#: sql_help.c:4116 sql_help.c:4119 msgid "merge_update" msgstr "merge_delete" -#: sql_help.c:4090 +#: sql_help.c:4117 sql_help.c:4120 msgid "merge_delete" msgstr "merge_delete" -#: sql_help.c:4092 +#: sql_help.c:4122 msgid "merge_insert" msgstr "merge_insert" -#: sql_help.c:4093 +#: sql_help.c:4123 msgid "and merge_insert is:" msgstr "et merge_insert est :" -#: sql_help.c:4096 +#: sql_help.c:4126 msgid "and merge_update is:" msgstr "et merge_update est :" -#: sql_help.c:4101 +#: sql_help.c:4133 msgid "and merge_delete is:" msgstr "et merge_delete est :" -#: sql_help.c:4142 +#: sql_help.c:4174 msgid "payload" msgstr "contenu" -#: sql_help.c:4169 +#: sql_help.c:4201 msgid "old_role" msgstr "ancien_rôle" -#: sql_help.c:4170 +#: sql_help.c:4202 msgid "new_role" msgstr "nouveau_rôle" -#: sql_help.c:4209 sql_help.c:4418 sql_help.c:4426 +#: sql_help.c:4241 sql_help.c:4450 sql_help.c:4458 msgid "savepoint_name" msgstr "nom_savepoint" -#: sql_help.c:4566 sql_help.c:4624 sql_help.c:4823 sql_help.c:4881 -#: sql_help.c:5069 sql_help.c:5127 +#: sql_help.c:4598 sql_help.c:4656 sql_help.c:4856 sql_help.c:4914 +#: sql_help.c:5101 sql_help.c:5159 msgid "grouping_element" msgstr "element_regroupement" -#: sql_help.c:4568 sql_help.c:4671 sql_help.c:4825 sql_help.c:5071 +#: sql_help.c:4600 sql_help.c:4704 sql_help.c:4858 sql_help.c:5103 msgid "window_name" msgstr "nom_window" -#: sql_help.c:4569 sql_help.c:4672 sql_help.c:4826 sql_help.c:5072 +#: sql_help.c:4601 sql_help.c:4705 sql_help.c:4859 sql_help.c:5104 msgid "window_definition" msgstr "définition_window" -#: sql_help.c:4570 sql_help.c:4584 sql_help.c:4628 sql_help.c:4673 -#: sql_help.c:4827 sql_help.c:4841 sql_help.c:4885 sql_help.c:5073 -#: sql_help.c:5087 sql_help.c:5131 +#: sql_help.c:4602 sql_help.c:4616 sql_help.c:4660 sql_help.c:4706 +#: sql_help.c:4860 sql_help.c:4874 sql_help.c:4918 sql_help.c:5105 +#: sql_help.c:5119 sql_help.c:5163 msgid "select" msgstr "sélection" -#: sql_help.c:4577 sql_help.c:4834 sql_help.c:5080 +#: sql_help.c:4608 sql_help.c:4866 sql_help.c:5111 +msgid "from_reference" +msgstr "reference_from" + +#: sql_help.c:4609 sql_help.c:4867 sql_help.c:5112 msgid "where from_item can be one of:" msgstr "où élément_from fait partie de :" -#: sql_help.c:4580 sql_help.c:4586 sql_help.c:4589 sql_help.c:4593 -#: sql_help.c:4605 sql_help.c:4837 sql_help.c:4843 sql_help.c:4846 -#: sql_help.c:4850 sql_help.c:4862 sql_help.c:5083 sql_help.c:5089 -#: sql_help.c:5092 sql_help.c:5096 sql_help.c:5108 +#: sql_help.c:4612 sql_help.c:4618 sql_help.c:4621 sql_help.c:4625 +#: sql_help.c:4637 sql_help.c:4870 sql_help.c:4876 sql_help.c:4879 +#: sql_help.c:4883 sql_help.c:4895 sql_help.c:5115 sql_help.c:5121 +#: sql_help.c:5124 sql_help.c:5128 sql_help.c:5140 msgid "column_alias" msgstr "alias_colonne" -#: sql_help.c:4581 sql_help.c:4838 sql_help.c:5084 +#: sql_help.c:4613 sql_help.c:4871 sql_help.c:5116 msgid "sampling_method" msgstr "méthode_echantillonnage" -#: sql_help.c:4583 sql_help.c:4840 sql_help.c:5086 +#: sql_help.c:4615 sql_help.c:4873 sql_help.c:5118 msgid "seed" msgstr "graine" -#: sql_help.c:4587 sql_help.c:4626 sql_help.c:4844 sql_help.c:4883 -#: sql_help.c:5090 sql_help.c:5129 +#: sql_help.c:4619 sql_help.c:4658 sql_help.c:4877 sql_help.c:4916 +#: sql_help.c:5122 sql_help.c:5161 msgid "with_query_name" msgstr "nom_requête_with" -#: sql_help.c:4597 sql_help.c:4600 sql_help.c:4603 sql_help.c:4854 -#: sql_help.c:4857 sql_help.c:4860 sql_help.c:5100 sql_help.c:5103 -#: sql_help.c:5106 +#: sql_help.c:4629 sql_help.c:4632 sql_help.c:4635 sql_help.c:4887 +#: sql_help.c:4890 sql_help.c:4893 sql_help.c:5132 sql_help.c:5135 +#: sql_help.c:5138 msgid "column_definition" msgstr "définition_colonne" -#: sql_help.c:4607 sql_help.c:4613 sql_help.c:4864 sql_help.c:4870 -#: sql_help.c:5110 sql_help.c:5116 +#: sql_help.c:4639 sql_help.c:4645 sql_help.c:4897 sql_help.c:4903 +#: sql_help.c:5142 sql_help.c:5148 msgid "join_type" msgstr "type_de_jointure" -#: sql_help.c:4610 sql_help.c:4867 sql_help.c:5113 +#: sql_help.c:4642 sql_help.c:4900 sql_help.c:5145 msgid "join_column" msgstr "colonne_de_jointure" -#: sql_help.c:4611 sql_help.c:4868 sql_help.c:5114 +#: sql_help.c:4643 sql_help.c:4901 sql_help.c:5146 msgid "join_using_alias" msgstr "join_utilisant_alias" -#: sql_help.c:4617 sql_help.c:4874 sql_help.c:5120 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and grouping_element can be one of:" msgstr "où element_regroupement fait partie de :" -#: sql_help.c:4625 sql_help.c:4882 sql_help.c:5128 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 msgid "and with_query is:" msgstr "et requête_with est :" -#: sql_help.c:4629 sql_help.c:4886 sql_help.c:5132 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "values" msgstr "valeurs" -#: sql_help.c:4630 sql_help.c:4887 sql_help.c:5133 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "insert" msgstr "insert" -#: sql_help.c:4631 sql_help.c:4888 sql_help.c:5134 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "update" msgstr "update" -#: sql_help.c:4632 sql_help.c:4889 sql_help.c:5135 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "delete" msgstr "delete" -#: sql_help.c:4634 sql_help.c:4891 sql_help.c:5137 +#: sql_help.c:4665 sql_help.c:4923 sql_help.c:5168 +msgid "merge" +msgstr "merge" + +#: sql_help.c:4667 sql_help.c:4925 sql_help.c:5170 msgid "search_seq_col_name" msgstr "nom_colonne_seq_recherche" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4669 sql_help.c:4927 sql_help.c:5172 msgid "cycle_mark_col_name" msgstr "nom_colonne_marque_cycle" -#: sql_help.c:4637 sql_help.c:4894 sql_help.c:5140 +#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 msgid "cycle_mark_value" msgstr "valeur_marque_cycle" -#: sql_help.c:4638 sql_help.c:4895 sql_help.c:5141 +#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 msgid "cycle_mark_default" msgstr "défaut_marque_cyle" -#: sql_help.c:4639 sql_help.c:4896 sql_help.c:5142 +#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 msgid "cycle_path_col_name" msgstr "nom_colonne_chemin_cycle" -#: sql_help.c:4666 +#: sql_help.c:4699 msgid "new_table" msgstr "nouvelle_table" -#: sql_help.c:4737 +#: sql_help.c:4770 msgid "snapshot_id" msgstr "id_snapshot" -#: sql_help.c:5005 +#: sql_help.c:5037 msgid "sort_expression" msgstr "expression_de_tri" -#: sql_help.c:5149 sql_help.c:6133 +#: sql_help.c:5182 sql_help.c:6166 msgid "abort the current transaction" msgstr "abandonner la transaction en cours" -#: sql_help.c:5155 +#: sql_help.c:5188 msgid "change the definition of an aggregate function" msgstr "modifier la définition d'une fonction d'agrégation" -#: sql_help.c:5161 +#: sql_help.c:5194 msgid "change the definition of a collation" msgstr "modifier la définition d'un collationnement" -#: sql_help.c:5167 +#: sql_help.c:5200 msgid "change the definition of a conversion" msgstr "modifier la définition d'une conversion" -#: sql_help.c:5173 +#: sql_help.c:5206 msgid "change a database" msgstr "modifier une base de données" -#: sql_help.c:5179 +#: sql_help.c:5212 msgid "define default access privileges" msgstr "définir les droits d'accès par défaut" -#: sql_help.c:5185 +#: sql_help.c:5218 msgid "change the definition of a domain" msgstr "modifier la définition d'un domaine" -#: sql_help.c:5191 +#: sql_help.c:5224 msgid "change the definition of an event trigger" msgstr "modifier la définition d'un trigger sur évènement" -#: sql_help.c:5197 +#: sql_help.c:5230 msgid "change the definition of an extension" msgstr "modifier la définition d'une extension" -#: sql_help.c:5203 +#: sql_help.c:5236 msgid "change the definition of a foreign-data wrapper" msgstr "modifier la définition d'un wrapper de données distantes" -#: sql_help.c:5209 +#: sql_help.c:5242 msgid "change the definition of a foreign table" msgstr "modifier la définition d'une table distante" -#: sql_help.c:5215 +#: sql_help.c:5248 msgid "change the definition of a function" msgstr "modifier la définition d'une fonction" -#: sql_help.c:5221 +#: sql_help.c:5254 msgid "change role name or membership" msgstr "modifier le nom d'un groupe ou la liste des ses membres" -#: sql_help.c:5227 +#: sql_help.c:5260 msgid "change the definition of an index" msgstr "modifier la définition d'un index" -#: sql_help.c:5233 +#: sql_help.c:5266 msgid "change the definition of a procedural language" msgstr "modifier la définition d'un langage procédural" -#: sql_help.c:5239 +#: sql_help.c:5272 msgid "change the definition of a large object" msgstr "modifier la définition d'un « Large Object »" -#: sql_help.c:5245 +#: sql_help.c:5278 msgid "change the definition of a materialized view" msgstr "modifier la définition d'une vue matérialisée" -#: sql_help.c:5251 +#: sql_help.c:5284 msgid "change the definition of an operator" msgstr "modifier la définition d'un opérateur" -#: sql_help.c:5257 +#: sql_help.c:5290 msgid "change the definition of an operator class" msgstr "modifier la définition d'une classe d'opérateurs" -#: sql_help.c:5263 +#: sql_help.c:5296 msgid "change the definition of an operator family" msgstr "modifier la définition d'une famille d'opérateur" -#: sql_help.c:5269 +#: sql_help.c:5302 msgid "change the definition of a row-level security policy" msgstr "modifier la définition d'une politique de sécurité au niveau ligne" -#: sql_help.c:5275 +#: sql_help.c:5308 msgid "change the definition of a procedure" msgstr "modifier la définition d'une procédure" -#: sql_help.c:5281 +#: sql_help.c:5314 msgid "change the definition of a publication" msgstr "modifier la définition d'une publication" -#: sql_help.c:5287 sql_help.c:5389 +#: sql_help.c:5320 sql_help.c:5422 msgid "change a database role" msgstr "modifier un rôle" -#: sql_help.c:5293 +#: sql_help.c:5326 msgid "change the definition of a routine" msgstr "modifier la définition d'une routine" -#: sql_help.c:5299 +#: sql_help.c:5332 msgid "change the definition of a rule" msgstr "modifier la définition d'une règle" -#: sql_help.c:5305 +#: sql_help.c:5338 msgid "change the definition of a schema" msgstr "modifier la définition d'un schéma" -#: sql_help.c:5311 +#: sql_help.c:5344 msgid "change the definition of a sequence generator" msgstr "modifier la définition d'un générateur de séquence" -#: sql_help.c:5317 +#: sql_help.c:5350 msgid "change the definition of a foreign server" msgstr "modifier la définition d'un serveur distant" -#: sql_help.c:5323 +#: sql_help.c:5356 msgid "change the definition of an extended statistics object" msgstr "modifier la définition d'un objet de statistiques étendues" -#: sql_help.c:5329 +#: sql_help.c:5362 msgid "change the definition of a subscription" msgstr "modifier la définition d'une souscription" -#: sql_help.c:5335 +#: sql_help.c:5368 msgid "change a server configuration parameter" msgstr "modifie un paramètre de configuration du serveur" -#: sql_help.c:5341 +#: sql_help.c:5374 msgid "change the definition of a table" msgstr "modifier la définition d'une table" -#: sql_help.c:5347 +#: sql_help.c:5380 msgid "change the definition of a tablespace" msgstr "modifier la définition d'un tablespace" -#: sql_help.c:5353 +#: sql_help.c:5386 msgid "change the definition of a text search configuration" msgstr "modifier la définition d'une configuration de la recherche de texte" -#: sql_help.c:5359 +#: sql_help.c:5392 msgid "change the definition of a text search dictionary" msgstr "modifier la définition d'un dictionnaire de la recherche de texte" -#: sql_help.c:5365 +#: sql_help.c:5398 msgid "change the definition of a text search parser" msgstr "modifier la définition d'un analyseur de la recherche de texte" -#: sql_help.c:5371 +#: sql_help.c:5404 msgid "change the definition of a text search template" msgstr "modifier la définition d'un modèle de la recherche de texte" -#: sql_help.c:5377 +#: sql_help.c:5410 msgid "change the definition of a trigger" msgstr "modifier la définition d'un trigger" -#: sql_help.c:5383 +#: sql_help.c:5416 msgid "change the definition of a type" msgstr "modifier la définition d'un type" -#: sql_help.c:5395 +#: sql_help.c:5428 msgid "change the definition of a user mapping" msgstr "modifier la définition d'une correspondance d'utilisateur" -#: sql_help.c:5401 +#: sql_help.c:5434 msgid "change the definition of a view" msgstr "modifier la définition d'une vue" -#: sql_help.c:5407 +#: sql_help.c:5440 msgid "collect statistics about a database" msgstr "acquérir des statistiques concernant la base de données" -#: sql_help.c:5413 sql_help.c:6211 +#: sql_help.c:5446 sql_help.c:6244 msgid "start a transaction block" msgstr "débuter un bloc de transaction" -#: sql_help.c:5419 +#: sql_help.c:5452 msgid "invoke a procedure" msgstr "appeler une procédure" -#: sql_help.c:5425 +#: sql_help.c:5458 msgid "force a write-ahead log checkpoint" msgstr "forcer un point de vérification des journaux de transactions" -#: sql_help.c:5431 +#: sql_help.c:5464 msgid "close a cursor" msgstr "fermer un curseur" -#: sql_help.c:5437 +#: sql_help.c:5470 msgid "cluster a table according to an index" msgstr "réorganiser (cluster) une table en fonction d'un index" -#: sql_help.c:5443 +#: sql_help.c:5476 msgid "define or change the comment of an object" msgstr "définir ou modifier les commentaires d'un objet" -#: sql_help.c:5449 sql_help.c:6007 +#: sql_help.c:5482 sql_help.c:6040 msgid "commit the current transaction" msgstr "valider la transaction en cours" -#: sql_help.c:5455 +#: sql_help.c:5488 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "" "valider une transaction précédemment préparée pour une validation en deux\n" "phases" -#: sql_help.c:5461 +#: sql_help.c:5494 msgid "copy data between a file and a table" msgstr "copier des données entre un fichier et une table" -#: sql_help.c:5467 +#: sql_help.c:5500 msgid "define a new access method" msgstr "définir une nouvelle méthode d'accès" -#: sql_help.c:5473 +#: sql_help.c:5506 msgid "define a new aggregate function" msgstr "définir une nouvelle fonction d'agrégation" -#: sql_help.c:5479 +#: sql_help.c:5512 msgid "define a new cast" msgstr "définir un nouveau transtypage" -#: sql_help.c:5485 +#: sql_help.c:5518 msgid "define a new collation" msgstr "définir un nouveau collationnement" -#: sql_help.c:5491 +#: sql_help.c:5524 msgid "define a new encoding conversion" msgstr "définir une nouvelle conversion d'encodage" -#: sql_help.c:5497 +#: sql_help.c:5530 msgid "create a new database" msgstr "créer une nouvelle base de données" -#: sql_help.c:5503 +#: sql_help.c:5536 msgid "define a new domain" msgstr "définir un nouveau domaine" -#: sql_help.c:5509 +#: sql_help.c:5542 msgid "define a new event trigger" msgstr "définir un nouveau trigger sur évènement" -#: sql_help.c:5515 +#: sql_help.c:5548 msgid "install an extension" msgstr "installer une extension" -#: sql_help.c:5521 +#: sql_help.c:5554 msgid "define a new foreign-data wrapper" msgstr "définir un nouveau wrapper de données distantes" -#: sql_help.c:5527 +#: sql_help.c:5560 msgid "define a new foreign table" msgstr "définir une nouvelle table distante" -#: sql_help.c:5533 +#: sql_help.c:5566 msgid "define a new function" msgstr "définir une nouvelle fonction" -#: sql_help.c:5539 sql_help.c:5599 sql_help.c:5701 +#: sql_help.c:5572 sql_help.c:5632 sql_help.c:5734 msgid "define a new database role" msgstr "définir un nouveau rôle" -#: sql_help.c:5545 +#: sql_help.c:5578 msgid "define a new index" msgstr "définir un nouvel index" -#: sql_help.c:5551 +#: sql_help.c:5584 msgid "define a new procedural language" msgstr "définir un nouveau langage de procédures" -#: sql_help.c:5557 +#: sql_help.c:5590 msgid "define a new materialized view" msgstr "définir une nouvelle vue matérialisée" -#: sql_help.c:5563 +#: sql_help.c:5596 msgid "define a new operator" msgstr "définir un nouvel opérateur" -#: sql_help.c:5569 +#: sql_help.c:5602 msgid "define a new operator class" msgstr "définir une nouvelle classe d'opérateur" -#: sql_help.c:5575 +#: sql_help.c:5608 msgid "define a new operator family" msgstr "définir une nouvelle famille d'opérateur" -#: sql_help.c:5581 +#: sql_help.c:5614 msgid "define a new row-level security policy for a table" msgstr "définir une nouvelle politique de sécurité au niveau ligne pour une table" -#: sql_help.c:5587 +#: sql_help.c:5620 msgid "define a new procedure" msgstr "définir une nouvelle procédure" -#: sql_help.c:5593 +#: sql_help.c:5626 msgid "define a new publication" msgstr "définir une nouvelle publication" -#: sql_help.c:5605 +#: sql_help.c:5638 msgid "define a new rewrite rule" msgstr "définir une nouvelle règle de réécriture" -#: sql_help.c:5611 +#: sql_help.c:5644 msgid "define a new schema" msgstr "définir un nouveau schéma" -#: sql_help.c:5617 +#: sql_help.c:5650 msgid "define a new sequence generator" msgstr "définir un nouveau générateur de séquence" -#: sql_help.c:5623 +#: sql_help.c:5656 msgid "define a new foreign server" msgstr "définir un nouveau serveur distant" -#: sql_help.c:5629 +#: sql_help.c:5662 msgid "define extended statistics" msgstr "définir des statistiques étendues" -#: sql_help.c:5635 +#: sql_help.c:5668 msgid "define a new subscription" msgstr "définir une nouvelle souscription" -#: sql_help.c:5641 +#: sql_help.c:5674 msgid "define a new table" msgstr "définir une nouvelle table" -#: sql_help.c:5647 sql_help.c:6169 +#: sql_help.c:5680 sql_help.c:6202 msgid "define a new table from the results of a query" msgstr "définir une nouvelle table à partir des résultats d'une requête" -#: sql_help.c:5653 +#: sql_help.c:5686 msgid "define a new tablespace" msgstr "définir un nouveau tablespace" -#: sql_help.c:5659 +#: sql_help.c:5692 msgid "define a new text search configuration" msgstr "définir une nouvelle configuration de la recherche de texte" -#: sql_help.c:5665 +#: sql_help.c:5698 msgid "define a new text search dictionary" msgstr "définir un nouveau dictionnaire de la recherche de texte" -#: sql_help.c:5671 +#: sql_help.c:5704 msgid "define a new text search parser" msgstr "définir un nouvel analyseur de la recherche de texte" -#: sql_help.c:5677 +#: sql_help.c:5710 msgid "define a new text search template" msgstr "définir un nouveau modèle de la recherche de texte" -#: sql_help.c:5683 +#: sql_help.c:5716 msgid "define a new transform" msgstr "définir une nouvelle transformation" -#: sql_help.c:5689 +#: sql_help.c:5722 msgid "define a new trigger" msgstr "définir un nouveau trigger" -#: sql_help.c:5695 +#: sql_help.c:5728 msgid "define a new data type" msgstr "définir un nouveau type de données" -#: sql_help.c:5707 +#: sql_help.c:5740 msgid "define a new mapping of a user to a foreign server" msgstr "définit une nouvelle correspondance d'un utilisateur vers un serveur distant" -#: sql_help.c:5713 +#: sql_help.c:5746 msgid "define a new view" msgstr "définir une nouvelle vue" -#: sql_help.c:5719 +#: sql_help.c:5752 msgid "deallocate a prepared statement" msgstr "désallouer une instruction préparée" -#: sql_help.c:5725 +#: sql_help.c:5758 msgid "define a cursor" msgstr "définir un curseur" -#: sql_help.c:5731 +#: sql_help.c:5764 msgid "delete rows of a table" msgstr "supprimer des lignes d'une table" -#: sql_help.c:5737 +#: sql_help.c:5770 msgid "discard session state" msgstr "annuler l'état de la session" -#: sql_help.c:5743 +#: sql_help.c:5776 msgid "execute an anonymous code block" msgstr "exécute un bloc de code anonyme" -#: sql_help.c:5749 +#: sql_help.c:5782 msgid "remove an access method" msgstr "supprimer une méthode d'accès" -#: sql_help.c:5755 +#: sql_help.c:5788 msgid "remove an aggregate function" msgstr "supprimer une fonction d'agrégation" -#: sql_help.c:5761 +#: sql_help.c:5794 msgid "remove a cast" msgstr "supprimer un transtypage" -#: sql_help.c:5767 +#: sql_help.c:5800 msgid "remove a collation" msgstr "supprimer un collationnement" -#: sql_help.c:5773 +#: sql_help.c:5806 msgid "remove a conversion" msgstr "supprimer une conversion" -#: sql_help.c:5779 +#: sql_help.c:5812 msgid "remove a database" msgstr "supprimer une base de données" -#: sql_help.c:5785 +#: sql_help.c:5818 msgid "remove a domain" msgstr "supprimer un domaine" -#: sql_help.c:5791 +#: sql_help.c:5824 msgid "remove an event trigger" msgstr "supprimer un trigger sur évènement" -#: sql_help.c:5797 +#: sql_help.c:5830 msgid "remove an extension" msgstr "supprimer une extension" -#: sql_help.c:5803 +#: sql_help.c:5836 msgid "remove a foreign-data wrapper" msgstr "supprimer un wrapper de données distantes" -#: sql_help.c:5809 +#: sql_help.c:5842 msgid "remove a foreign table" msgstr "supprimer une table distante" -#: sql_help.c:5815 +#: sql_help.c:5848 msgid "remove a function" msgstr "supprimer une fonction" -#: sql_help.c:5821 sql_help.c:5887 sql_help.c:5989 +#: sql_help.c:5854 sql_help.c:5920 sql_help.c:6022 msgid "remove a database role" msgstr "supprimer un rôle de la base de données" -#: sql_help.c:5827 +#: sql_help.c:5860 msgid "remove an index" msgstr "supprimer un index" -#: sql_help.c:5833 +#: sql_help.c:5866 msgid "remove a procedural language" msgstr "supprimer un langage procédural" -#: sql_help.c:5839 +#: sql_help.c:5872 msgid "remove a materialized view" msgstr "supprimer une vue matérialisée" -#: sql_help.c:5845 +#: sql_help.c:5878 msgid "remove an operator" msgstr "supprimer un opérateur" -#: sql_help.c:5851 +#: sql_help.c:5884 msgid "remove an operator class" msgstr "supprimer une classe d'opérateur" -#: sql_help.c:5857 +#: sql_help.c:5890 msgid "remove an operator family" msgstr "supprimer une famille d'opérateur" -#: sql_help.c:5863 +#: sql_help.c:5896 msgid "remove database objects owned by a database role" msgstr "supprimer les objets appartenant à un rôle" -#: sql_help.c:5869 +#: sql_help.c:5902 msgid "remove a row-level security policy from a table" msgstr "supprimer une politique de sécurité au niveau ligne pour une table" -#: sql_help.c:5875 +#: sql_help.c:5908 msgid "remove a procedure" msgstr "supprimer une procédure" -#: sql_help.c:5881 +#: sql_help.c:5914 msgid "remove a publication" msgstr "supprimer une publication" -#: sql_help.c:5893 +#: sql_help.c:5926 msgid "remove a routine" msgstr "supprimer une routine" -#: sql_help.c:5899 +#: sql_help.c:5932 msgid "remove a rewrite rule" msgstr "supprimer une règle de réécriture" -#: sql_help.c:5905 +#: sql_help.c:5938 msgid "remove a schema" msgstr "supprimer un schéma" -#: sql_help.c:5911 +#: sql_help.c:5944 msgid "remove a sequence" msgstr "supprimer une séquence" -#: sql_help.c:5917 +#: sql_help.c:5950 msgid "remove a foreign server descriptor" msgstr "supprimer un descripteur de serveur distant" -#: sql_help.c:5923 +#: sql_help.c:5956 msgid "remove extended statistics" msgstr "supprimer des statistiques étendues" -#: sql_help.c:5929 +#: sql_help.c:5962 msgid "remove a subscription" msgstr "supprimer une souscription" -#: sql_help.c:5935 +#: sql_help.c:5968 msgid "remove a table" msgstr "supprimer une table" -#: sql_help.c:5941 +#: sql_help.c:5974 msgid "remove a tablespace" msgstr "supprimer un tablespace" -#: sql_help.c:5947 +#: sql_help.c:5980 msgid "remove a text search configuration" msgstr "supprimer une configuration de la recherche de texte" -#: sql_help.c:5953 +#: sql_help.c:5986 msgid "remove a text search dictionary" msgstr "supprimer un dictionnaire de la recherche de texte" -#: sql_help.c:5959 +#: sql_help.c:5992 msgid "remove a text search parser" msgstr "supprimer un analyseur de la recherche de texte" -#: sql_help.c:5965 +#: sql_help.c:5998 msgid "remove a text search template" msgstr "supprimer un modèle de la recherche de texte" -#: sql_help.c:5971 +#: sql_help.c:6004 msgid "remove a transform" msgstr "supprimer une transformation" -#: sql_help.c:5977 +#: sql_help.c:6010 msgid "remove a trigger" msgstr "supprimer un trigger" -#: sql_help.c:5983 +#: sql_help.c:6016 msgid "remove a data type" msgstr "supprimer un type de données" -#: sql_help.c:5995 +#: sql_help.c:6028 msgid "remove a user mapping for a foreign server" msgstr "supprime une correspondance utilisateur pour un serveur distant" -#: sql_help.c:6001 +#: sql_help.c:6034 msgid "remove a view" msgstr "supprimer une vue" -#: sql_help.c:6013 +#: sql_help.c:6046 msgid "execute a prepared statement" msgstr "exécuter une instruction préparée" -#: sql_help.c:6019 +#: sql_help.c:6052 msgid "show the execution plan of a statement" msgstr "afficher le plan d'exécution d'une instruction" -#: sql_help.c:6025 +#: sql_help.c:6058 msgid "retrieve rows from a query using a cursor" msgstr "extraire certaines lignes d'une requête à l'aide d'un curseur" -#: sql_help.c:6031 +#: sql_help.c:6064 msgid "define access privileges" msgstr "définir des privilèges d'accès" -#: sql_help.c:6037 +#: sql_help.c:6070 msgid "import table definitions from a foreign server" msgstr "importer la définition d'une table à partir d'un serveur distant" -#: sql_help.c:6043 +#: sql_help.c:6076 msgid "create new rows in a table" msgstr "créer de nouvelles lignes dans une table" -#: sql_help.c:6049 +#: sql_help.c:6082 msgid "listen for a notification" msgstr "se mettre à l'écoute d'une notification" -#: sql_help.c:6055 +#: sql_help.c:6088 msgid "load a shared library file" msgstr "charger un fichier de bibliothèque partagée" -#: sql_help.c:6061 +#: sql_help.c:6094 msgid "lock a table" msgstr "verrouiller une table" -#: sql_help.c:6067 +#: sql_help.c:6100 msgid "conditionally insert, update, or delete rows of a table" msgstr "insère, modifie ou supprime des lignes d'une table de façon conditionnelle" -#: sql_help.c:6073 +#: sql_help.c:6106 msgid "position a cursor" msgstr "positionner un curseur" -#: sql_help.c:6079 +#: sql_help.c:6112 msgid "generate a notification" msgstr "engendrer une notification" -#: sql_help.c:6085 +#: sql_help.c:6118 msgid "prepare a statement for execution" msgstr "préparer une instruction pour exécution" -#: sql_help.c:6091 +#: sql_help.c:6124 msgid "prepare the current transaction for two-phase commit" msgstr "préparer la transaction en cours pour une validation en deux phases" -#: sql_help.c:6097 +#: sql_help.c:6130 msgid "change the ownership of database objects owned by a database role" msgstr "changer le propriétaire des objets d'un rôle" -#: sql_help.c:6103 +#: sql_help.c:6136 msgid "replace the contents of a materialized view" msgstr "remplacer le contenu d'une vue matérialisée" -#: sql_help.c:6109 +#: sql_help.c:6142 msgid "rebuild indexes" msgstr "reconstruire des index" -#: sql_help.c:6115 +#: sql_help.c:6148 msgid "release a previously defined savepoint" msgstr "détruire un savepoint précédemment défini" -#: sql_help.c:6121 +#: sql_help.c:6154 msgid "restore the value of a run-time parameter to the default value" msgstr "réinitialiser un paramètre d'exécution à sa valeur par défaut" -#: sql_help.c:6127 +#: sql_help.c:6160 msgid "remove access privileges" msgstr "supprimer des privilèges d'accès" -#: sql_help.c:6139 +#: sql_help.c:6172 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "" "annuler une transaction précédemment préparée pour une validation en deux\n" "phases" -#: sql_help.c:6145 +#: sql_help.c:6178 msgid "roll back to a savepoint" msgstr "annuler jusqu'au point de retournement" -#: sql_help.c:6151 +#: sql_help.c:6184 msgid "define a new savepoint within the current transaction" msgstr "définir un nouveau point de retournement pour la transaction en cours" -#: sql_help.c:6157 +#: sql_help.c:6190 msgid "define or change a security label applied to an object" msgstr "définir ou modifier un label de sécurité à un objet" -#: sql_help.c:6163 sql_help.c:6217 sql_help.c:6253 +#: sql_help.c:6196 sql_help.c:6250 sql_help.c:6286 msgid "retrieve rows from a table or view" msgstr "extraire des lignes d'une table ou d'une vue" -#: sql_help.c:6175 +#: sql_help.c:6208 msgid "change a run-time parameter" msgstr "modifier un paramètre d'exécution" -#: sql_help.c:6181 +#: sql_help.c:6214 msgid "set constraint check timing for the current transaction" msgstr "définir le moment de la vérification des contraintes pour la transaction en cours" -#: sql_help.c:6187 +#: sql_help.c:6220 msgid "set the current user identifier of the current session" msgstr "définir l'identifiant actuel de l'utilisateur de la session courante" -#: sql_help.c:6193 +#: sql_help.c:6226 msgid "set the session user identifier and the current user identifier of the current session" msgstr "" "définir l'identifiant de l'utilisateur de session et l'identifiant actuel de\n" "l'utilisateur de la session courante" -#: sql_help.c:6199 +#: sql_help.c:6232 msgid "set the characteristics of the current transaction" msgstr "définir les caractéristiques de la transaction en cours" -#: sql_help.c:6205 +#: sql_help.c:6238 msgid "show the value of a run-time parameter" msgstr "afficher la valeur d'un paramètre d'exécution" -#: sql_help.c:6223 +#: sql_help.c:6256 msgid "empty a table or set of tables" msgstr "vider une table ou un ensemble de tables" -#: sql_help.c:6229 +#: sql_help.c:6262 msgid "stop listening for a notification" msgstr "arrêter l'écoute d'une notification" -#: sql_help.c:6235 +#: sql_help.c:6268 msgid "update rows of a table" msgstr "actualiser les lignes d'une table" -#: sql_help.c:6241 +#: sql_help.c:6274 msgid "garbage-collect and optionally analyze a database" msgstr "compacter et optionnellement analyser une base de données" -#: sql_help.c:6247 +#: sql_help.c:6280 msgid "compute a set of rows" msgstr "calculer un ensemble de lignes" @@ -6623,7 +6697,7 @@ msgstr "option supplémentaire « %s » ignorée" msgid "could not find own program executable" msgstr "n'a pas pu trouver son propre exécutable" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6658,467 +6732,8 @@ msgstr "" "valeur « %s » non reconnue pour « %s »\n" "Les valeurs disponibles sont : %s." -#~ msgid " \"%s\"" -#~ msgstr " « %s »" - -#~ msgid " \"%s\" IN %s %s" -#~ msgstr " \"%s\" DANS %s %s" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide, puis quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version, puis quitte\n" - -#~ msgid " -?, --help show this help, then exit\n" -#~ msgstr " -?, --help affiche cette aide puis quitte\n" - -#~ msgid " SERVER_VERSION_NAME server's version (short string)\n" -#~ msgstr " SERVER_VERSION_NAME version du serveur (chaîne courte)\n" - -#~ msgid " VERSION psql's version (verbose string)\n" -#~ msgstr " VERSION version de psql (chaîne verbeuse)\n" - -#~ msgid " VERSION_NAME psql's version (short string)\n" -#~ msgstr " VERSION_NAME version de psql (chaîne courte)\n" - -#~ msgid " VERSION_NUM psql's version (numeric format)\n" -#~ msgstr " VERSION_NUM version de psql (format numérique)\n" - -#~ msgid " \\dFd [PATTERN] list text search dictionaries (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\dFd [MODÈLE] affiche la liste des dictionnaires de la recherche\n" -#~ " de texte (ajouter « + » pour plus de détails)\n" - -#~ msgid " \\dFp [PATTERN] list text search parsers (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\dFp [MODÈLE] affiche la liste des analyseurs de la recherche de\n" -#~ " texte (ajouter « + » pour plus de détails)\n" - -#~ msgid " \\dT [PATTERN] list data types (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\dT [MODÈLE] affiche la liste des types de données (ajouter « + »\n" -#~ " pour plus de détails)\n" - -#~ msgid " \\db [PATTERN] list tablespaces (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\db [MODÈLE] affiche la liste des tablespaces (ajouter « + » pour\n" -#~ " plus de détails)\n" - -#~ msgid " \\df [PATTERN] list functions (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\df [MODÈLE] affiche la liste des fonctions (ajouter « + » pour\n" -#~ " plus de détails)\n" - -#~ msgid " \\dn [PATTERN] list schemas (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\dn [MODÈLE] affiche la liste des schémas (ajouter « + » pour\n" -#~ " plus de détails)\n" - -#~ msgid "" -#~ " \\d{t|i|s|v|S} [PATTERN] (add \"+\" for more detail)\n" -#~ " list tables/indexes/sequences/views/system tables\n" -#~ msgstr "" -#~ " \\d{t|i|s|v|S} [MODÈLE] (ajouter « + » pour plus de détails)\n" -#~ " affiche la liste des\n" -#~ " tables/index/séquences/vues/tables système\n" - -#~ msgid " \\g [FILE] or ; execute query (and send results to file or |pipe)\n" -#~ msgstr "" -#~ " \\g [FICHIER] ou ; envoie le tampon de requêtes au serveur (et les\n" -#~ " résultats au fichier ou |tube)\n" - -#~ msgid " \\l list all databases (add \"+\" for more detail)\n" -#~ msgstr "" -#~ " \\l affiche la liste des bases de données (ajouter « + »\n" -#~ " pour plus de détails)\n" - -#~ msgid " \\l[+] list all databases\n" -#~ msgstr " \\l[+] affiche la liste des bases de données\n" - -#, c-format -#~ msgid "" -#~ " \\lo_export LOBOID FILE\n" -#~ " \\lo_import FILE [COMMENT]\n" -#~ " \\lo_list[+]\n" -#~ " \\lo_unlink LOBOID large object operations\n" -#~ msgstr "" -#~ " \\lo_export OIDLOB FICHIER\n" -#~ " \\lo_import FICHIER [COMMENTAIRE]\n" -#~ " \\lo_list[+]\n" -#~ " \\lo_unlink OIDLOB opérations sur les « Large Objects »\n" - -#~ msgid " \\z [PATTERN] list table, view, and sequence access privileges (same as \\dp)\n" -#~ msgstr "" -#~ " \\z [MODÈLE] affiche la liste des privilèges d'accès aux tables,\n" -#~ " vues et séquences (identique à \\dp)\n" - -#~ msgid " as user \"%s\"" -#~ msgstr " comme utilisateur « %s »" - -#~ msgid " at port \"%s\"" -#~ msgstr " sur le port « %s »" - -#~ msgid " on host \"%s\"" -#~ msgstr " sur l'hôte « %s »" - -#~ msgid "%s\n" -#~ msgstr "%s\n" - -#~ msgid "%s: %s\n" -#~ msgstr "%s : %s\n" - -#~ msgid "%s: could not open log file \"%s\": %s\n" -#~ msgstr "%s : n'a pas pu ouvrir le journal applicatif « %s » : %s\n" - -#~ msgid "%s: could not set variable \"%s\"\n" -#~ msgstr "%s : n'a pas pu initialiser la variable « %s »\n" - -#~ msgid "%s: pg_strdup: cannot duplicate null pointer (internal error)\n" -#~ msgstr "%s : pg_strdup : ne peut pas dupliquer le pointeur null (erreur interne)\n" - -#~ msgid "(1 row)" -#~ msgid_plural "(%lu rows)" -#~ msgstr[0] "(1 ligne)" -#~ msgstr[1] "(%lu lignes)" - -#~ msgid "(No rows)\n" -#~ msgstr "(Aucune ligne)\n" - -#~ msgid "+ opt(%d) = |%s|\n" -#~ msgstr "+ opt(%d) = |%s|\n" - -#~ msgid "?%c? \"%s.%s\"" -#~ msgstr "?%c? « %s.%s »" - -#~ msgid "Access privileges for database \"%s\"" -#~ msgstr "Droits d'accès pour la base de données « %s »" - -#~ msgid "All connection parameters must be supplied because no database connection exists" -#~ msgstr "Tous les paramètres de connexion doivent être fournis car il n'existe pas de connexion à une base de données" - -#~ msgid "Copy, Large Object\n" -#~ msgstr "Copie, « Large Object »\n" - -#~ msgid "Could not send cancel request: %s" -#~ msgstr "N'a pas pu envoyer la requête d'annulation : %s" - -#~ msgid "Disabled triggers:" -#~ msgstr "Triggers désactivés :" - -#~ msgid "Enter new password: " -#~ msgstr "Saisir le nouveau mot de passe : " - -#~ msgid "Exclusion constraints:" -#~ msgstr "Contraintes d'exclusion :" - -#~ msgid "Invalid command \\%s. Try \\? for help.\n" -#~ msgstr "Commande \\%s invalide. Essayez \\? pour l'aide-mémoire.\n" - -#~ msgid "Modifier" -#~ msgstr "Modificateur" - -#~ msgid "Modifiers" -#~ msgstr "Modificateurs" - -#~ msgid "No matching relations found.\n" -#~ msgstr "Aucune relation correspondante trouvée.\n" - -#~ msgid "No matching settings found.\n" -#~ msgstr "Aucun paramètre correspondant trouvé.\n" - -#~ msgid "No per-database role settings support in this server version.\n" -#~ msgstr "Pas de supprot des paramètres rôle par base de données pour la version de ce serveur.\n" - -#~ msgid "No relations found.\n" -#~ msgstr "Aucune relation trouvée.\n" - -#~ msgid "No settings found.\n" -#~ msgstr "Aucun paramètre trouvé.\n" - -#~ msgid "Object Description" -#~ msgstr "Description d'un objet" - -#~ msgid "Password encryption failed.\n" -#~ msgstr "Échec du chiffrement du mot de passe.\n" - -#~ msgid "Procedure" -#~ msgstr "Procédure" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapporter les bogues à .\n" - -#~ msgid "Report bugs to .\n" -#~ msgstr "Rapportez les bogues à .\n" - -#~ msgid "SSL connection (unknown cipher)\n" -#~ msgstr "Connexion SSL (chiffrement inconnu)\n" - -#~ msgid "Showing locale-adjusted numeric output." -#~ msgstr "Affichage de la sortie numérique adaptée à la locale." - -#~ msgid "Showing only tuples." -#~ msgstr "Affichage des tuples seuls." - -#~ msgid "Source code" -#~ msgstr "Code source" - -#, c-format -#~ msgid "Special relation \"%s.%s\"" -#~ msgstr "Relation spéciale « %s.%s »" - -#, c-format -#~ msgid "The server (version %s) does not support altering default privileges." -#~ msgstr "Le serveur (version %s) ne supporte pas la modification des droits par défaut." - -#, c-format -#~ msgid "The server (version %s) does not support collations." -#~ msgstr "Le serveur (version %s) ne supporte pas les collationnements." - -#, c-format -#~ msgid "The server (version %s) does not support editing function source." -#~ msgstr "Le serveur (version %s) ne supporte pas l'édition du code de la fonction." - -#, c-format -#~ msgid "The server (version %s) does not support editing view definitions." -#~ msgstr "Le serveur (version %s) ne supporte pas l'édition des définitions de vue." - -#, c-format -#~ msgid "The server (version %s) does not support foreign servers." -#~ msgstr "Le serveur (version %s) ne supporte pas les serveurs distants." - -#, c-format -#~ msgid "The server (version %s) does not support foreign tables." -#~ msgstr "Le serveur (version %s) ne supporte pas les tables distantes." - -#, c-format -#~ msgid "The server (version %s) does not support foreign-data wrappers." -#~ msgstr "Le serveur (version %s) ne supporte pas les wrappers de données distantes." - -#, c-format -#~ msgid "The server (version %s) does not support full text search." -#~ msgstr "Le serveur (version %s) ne supporte pas la recherche plein texte." - -#, c-format -#~ msgid "The server (version %s) does not support per-database role settings." -#~ msgstr "Le serveur (version %s) ne supporte pas les paramètres de rôles par bases de données." - -#, c-format -#~ msgid "The server (version %s) does not support savepoints for ON_ERROR_ROLLBACK." -#~ msgstr "Le serveur (version %s) ne supporte pas les points de sauvegarde pour ON_ERROR_ROLLBACK." - -#, c-format -#~ msgid "The server (version %s) does not support showing function source." -#~ msgstr "Le serveur (version %s) ne supporte pas l'affichage du code de la fonction." - -#, c-format -#~ msgid "The server (version %s) does not support showing view definitions." -#~ msgstr "Le serveur (version %s) ne supporte pas l'affichage des définitions de vues." - -#, c-format -#~ msgid "The server (version %s) does not support tablespaces." -#~ msgstr "Le serveur (version %s) ne supporte pas les tablespaces." - -#, c-format -#~ msgid "The server (version %s) does not support user mappings." -#~ msgstr "Le serveur (version %s) ne supporte pas les correspondances d'utilisateurs." - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayez « %s --help » pour plus d'informations.\n" - -#~ msgid "" -#~ "WARNING: You are connected to a server with major version %d.%d,\n" -#~ "but your %s client is major version %d.%d. Some backslash commands,\n" -#~ "such as \\d, might not work properly.\n" -#~ "\n" -#~ msgstr "" -#~ "ATTENTION : vous êtes connecté sur un serveur dont la version majeure est\n" -#~ "%d.%d alors que votre client %s est en version majeure %d.%d. Certaines\n" -#~ "commandes avec antislashs, comme \\d, peuvent ne pas fonctionner\n" -#~ "correctement.\n" -#~ "\n" - -#~ msgid "Watch every %lds\t%s" -#~ msgstr "Vérifier chaque %lds\t%s" - -#~ msgid "" -#~ "Welcome to %s %s (server %s), the PostgreSQL interactive terminal.\n" -#~ "\n" -#~ msgstr "" -#~ "Bienvenue dans %s %s (serveur %s), l'interface interactive de PostgreSQL.\n" -#~ "\n" - -#~ msgid "" -#~ "Welcome to %s %s, the PostgreSQL interactive terminal.\n" -#~ "\n" -#~ msgstr "" -#~ "Bienvenue dans %s %s, l'interface interactive de PostgreSQL.\n" -#~ "\n" - -#~ msgid "\\%s: error\n" -#~ msgstr "\\%s : erreur\n" - -#~ msgid "\\%s: error while setting variable\n" -#~ msgstr "\\%s : erreur lors de l'initialisation de la variable\n" - -#~ msgid "\\copy: %s" -#~ msgstr "\\copy : %s" - -#~ msgid "\\copy: unexpected response (%d)\n" -#~ msgstr "\\copy : réponse inattendue (%d)\n" - -#, c-format -#~ msgid "\\watch cannot be used with COPY" -#~ msgstr "\\watch ne peut pas être utilisé avec COPY" - -#~ msgid "agg_name" -#~ msgstr "nom_d_agrégat" - -#~ msgid "agg_type" -#~ msgstr "type_aggrégat" - -#~ msgid "attribute" -#~ msgstr "attribut" - -#~ msgid "child process was terminated by signal %d" -#~ msgstr "le processus fils a été terminé par le signal %d" - -#~ msgid "child process was terminated by signal %s" -#~ msgstr "le processus fils a été terminé par le signal %s" - -#~ msgid "collate %s" -#~ msgstr "collationnement %s" - -#~ msgid "collation_name" -#~ msgstr "nom_collation" - -#~ msgid "column" -#~ msgstr "colonne" - -#~ msgid "contains support for command-line editing" -#~ msgstr "contient une gestion avancée de la ligne de commande" - -#~ msgid "could not change directory to \"%s\"" -#~ msgstr "n'a pas pu accéder au répertoire « %s »" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "n'a pas pu modifier le répertoire par « %s » : %m" - -#~ msgid "could not change directory to \"%s\": %s" -#~ msgstr "n'a pas pu changer le répertoire par « %s » : %s" - -#~ msgid "could not close pipe to external command: %s\n" -#~ msgstr "n'a pas pu fermer le fichier pipe vers la commande externe : %s\n" - -#~ msgid "could not connect to server: %s" -#~ msgstr "n'a pas pu se connecter au serveur : %s" - -#~ msgid "could not execute command \"%s\": %s\n" -#~ msgstr "n'a pas pu exécuter la commande « %s » : %s\n" - -#~ msgid "could not get current user name: %s\n" -#~ msgstr "n'a pas pu obtenir le nom d'utilisateur courant : %s\n" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "n'a pas pu identifier le répertoire courant : %m" - -#~ msgid "could not identify current directory: %s" -#~ msgstr "n'a pas pu identifier le répertoire courant : %s" - -#~ msgid "could not open temporary file \"%s\": %s\n" -#~ msgstr "n'a pas pu ouvrir le fichier temporaire « %s » : %s\n" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "n'a pas pu lire le binaire « %s »" - -#~ msgid "could not read symbolic link \"%s\"" -#~ msgstr "n'a pas pu lire le lien symbolique « %s »" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %m" - -#~ msgid "could not set variable \"%s\"\n" -#~ msgstr "n'a pas pu initialiser la variable « %s »\n" - -#~ msgid "could not stat file \"%s\": %s\n" -#~ msgstr "n'a pas pu tester le fichier « %s » : %s\n" - -#~ msgid "data type" -#~ msgstr "type de données" - -#~ msgid "default %s" -#~ msgstr "Par défaut, %s" - -#~ msgid "define a new constraint trigger" -#~ msgstr "définir une nouvelle contrainte de déclenchement" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#~ msgid "from_list" -#~ msgstr "liste_from" - -#~ msgid "input_data_type" -#~ msgstr "type_de_données_en_entrée" - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "binaire « %s » invalide" - -#~ msgid "lock a named relation (table, etc)" -#~ msgstr "verrouille une relation nommée (table, etc)" - -#~ msgid "match" -#~ msgstr "match" - -#~ msgid "new_column" -#~ msgstr "nouvelle_colonne" - -#~ msgid "normal" -#~ msgstr "normal" - -#~ msgid "not null" -#~ msgstr "non NULL" - -#~ msgid "pclose failed: %m" -#~ msgstr "échec de pclose : %m" - -#~ msgid "pclose failed: %s" -#~ msgstr "échec de pclose : %s" - -#~ msgid "rolename" -#~ msgstr "nom_rôle" - -#~ msgid "serialtype" -#~ msgstr "serialtype" - -#~ msgid "special" -#~ msgstr "spécial" - -#~ msgid "statistic_type" -#~ msgstr "type_statistique" - -#~ msgid "tablespace" -#~ msgstr "tablespace" - -#~ msgid "text" -#~ msgstr "texte" - -#~ msgid "timezone" -#~ msgstr "fuseau_horaire" - -#, c-format -#~ msgid "unexpected result status for \\watch" -#~ msgstr "statut résultat inattendu pour \\watch" - -#~ msgid "unterminated quoted string\n" -#~ msgstr "chaîne entre guillemets non terminée\n" +#~ msgid "partition_name1" +#~ msgstr "nom_partition1" -#~ msgid "where direction can be empty or one of:" -#~ msgstr "où direction peut être vide ou faire partie de :" +#~ msgid "partition_name2" +#~ msgstr "nom_partition2" diff --git a/src/bin/psql/po/it.po b/src/bin/psql/po/it.po index 7f071c3afe3c4..aee5e3b405e13 100644 --- a/src/bin/psql/po/it.po +++ b/src/bin/psql/po/it.po @@ -21,7 +21,7 @@ msgstr "" "Project-Id-Version: psql (PostgreSQL) 11\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2022-09-26 08:16+0000\n" -"PO-Revision-Date: 2023-09-05 09:53+0200\n" +"PO-Revision-Date: 2024-06-26 09:10+0200\n" "Last-Translator: Daniele Varrazzo \n" "Language-Team: https://github.com/dvarrazzo/postgresql-it\n" "Language: it\n" @@ -2829,7 +2829,7 @@ msgstr " \\copy ... esegui una SQL COPY con flusso di dati dal cli #: help.c:227 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" -msgstr " \\echo [-n] [STRING] scrive la stringa nello standard output (-n per nessuna nuova riga)\n" +msgstr " \\echo [-n] [STRING] scrive la stringa nello standard output (-n per nessuna nuova riga)\n" #: help.c:228 msgid " \\i FILE execute commands from file\n" diff --git a/src/bin/psql/po/ja.po b/src/bin/psql/po/ja.po index 56cbe4ea2e67d..25c0e2e0e74ff 100644 --- a/src/bin/psql/po/ja.po +++ b/src/bin/psql/po/ja.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: psql (PostgreSQL 17)\n" +"Project-Id-Version: psql (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:24+0900\n" -"PO-Revision-Date: 2024-06-14 11:30+0900\n" +"POT-Creation-Date: 2025-04-08 10:37+0900\n" +"PO-Revision-Date: 2025-04-08 11:22+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -22,22 +22,22 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " @@ -62,28 +62,28 @@ msgstr "実行対象の\"%s\"が見つかりませんでした" msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "パス\"%s\"を絶対パス形式に変換できませんでした: %m" -#: ../../common/exec.c:382 copy.c:326 +#: ../../common/exec.c:363 copy.c:326 #, c-format msgid "could not execute command \"%s\": %m" msgstr "コマンド\"%s\"を実行できませんでした: %m" -#: ../../common/exec.c:394 +#: ../../common/exec.c:375 #, c-format msgid "could not read from command \"%s\": %m" msgstr "コマンド\"%s\"から読み取れませんでした: %m" -#: ../../common/exec.c:397 +#: ../../common/exec.c:378 #, c-format msgid "no data was returned by command \"%s\"" msgstr "コマンド\"%s\"がデータを返却しませんでした" -#: ../../common/exec.c:424 +#: ../../common/exec.c:405 #, c-format msgid "%s() failed: %m" msgstr "%s() が失敗しました: %m" -#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 -#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 +#: ../../common/exec.c:543 ../../common/exec.c:588 ../../common/exec.c:680 +#: command.c:1636 command.c:3985 command.c:4034 command.c:4159 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -105,7 +105,7 @@ msgstr "null ポインターを複製することはできません(内部エラ msgid "could not look up effective user ID %ld: %s" msgstr "実効ユーザーID %ld が見つかりませんでした: %s" -#: ../../common/username.c:45 command.c:616 +#: ../../common/username.c:45 command.c:700 msgid "user does not exist" msgstr "ユーザーが存在しません" @@ -165,8 +165,8 @@ msgstr "割り込み\n" #: ../../fe_utils/print.c:3188 #, c-format -msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" -msgstr "テーブルの内容を表示できません: セル数%lldが上限値%lld以上です。\n" +msgid "Cannot print table contents: number of cells % is equal to or exceeds maximum %zu.\n" +msgstr "テーブルの内容を表示できません: セル数%が上限値%zu以上です。\n" #: ../../fe_utils/print.c:3229 #, c-format @@ -175,325 +175,432 @@ msgstr "テーブルの内容にヘッダーを追加できません: 列数の #: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" -msgstr "テーブルの内容にセルを追加できません: セルの総数%lldを超過しています。\n" +msgid "Cannot add cell to table content: total cell count of % exceeded.\n" +msgstr "テーブルの内容にセルを追加できません: セルの総数%を超過しています。\n" #: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "出力フォーマットが無効(内部エラー):%d" -#: ../../fe_utils/psqlscan.l:718 +#: ../../fe_utils/psqlscan.l:723 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "変数\"%s\"の再帰展開をスキップしています" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../port/user.c:43 ../../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "ローカルユーザーID %dの参照に失敗しました: %s" - -#: ../../port/user.c:48 ../../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "ID %d を持つローカルユーザーは存在しません" - -#: command.c:235 +#: command.c:245 #, c-format msgid "invalid command \\%s" msgstr "不正なコマンド \\%s " -#: command.c:237 +#: command.c:247 #, c-format msgid "Try \\? for help." msgstr " \\? でヘルプを表示します。" -#: command.c:255 +#: command.c:265 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: 余分な引数\"%s\"は無視されました" -#: command.c:307 +#: command.c:317 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "\\%s コマンドは無視されます; 現在の\\ifブロックを抜けるには\\endifまたはCtrl-Cを使用します" -#: command.c:614 +#: command.c:552 command.c:747 command.c:1882 command.c:2050 command.c:2363 +#: command.c:2377 command.c:2409 command.c:2498 command.c:2611 command.c:2889 +#: command.c:3151 command.c:3191 +#, c-format +msgid "\\%s: missing required argument" +msgstr "\\%s: 必要な引数がありません" + +#: command.c:698 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "ユーザーID %ldのホームディレクトリを取得できませんでした : %s" -#: command.c:633 +#: command.c:717 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: ディレクトリを\"%s\"に変更できませんでした: %m" -#: command.c:657 +#: command.c:789 #, c-format msgid "You are currently not connected to a database.\n" msgstr "現在データベースに接続していません。\n" -#: command.c:667 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" -msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"上のポート\"%s\"で接続しています。\n" +#: command.c:815 +msgid "Connection Information" +msgstr "接続情報" -#: command.c:670 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" -msgstr "データベース\"%s\"にユーザー\"%s\"として、\"%s\"のソケットを介してポート\"%s\"で接続しています。\n" +#: command.c:816 describe.c:4721 +msgid "Parameter" +msgstr "パラメータ" -#: command.c:676 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" -msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"(アドレス\"%s\")上のポート\"%s\"で接続しています。\n" +#: command.c:817 describe.c:4722 +msgid "Value" +msgstr "値" -#: command.c:679 -#, c-format -msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" -msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"上のポート\"%s\"で接続しています。\n" +#: command.c:820 describe.c:3873 +msgid "Database" +msgstr "データベース" + +#: command.c:824 +msgid "Client User" +msgstr "クライアントユーザー" + +#: command.c:833 command.c:848 +msgid "Host Address" +msgstr "ソケットディレクトリ" + +#: command.c:838 +msgid "Socket Directory" +msgstr "ソケットディレクトリ" + +#: command.c:844 +msgid "Host" +msgstr "ホスト" + +#: command.c:854 +msgid "Server Port" +msgstr "サーバーポート" + +#: command.c:858 describe.c:246 describe.c:3614 describe.c:3954 +msgid "Options" +msgstr "オプション" + +#: command.c:862 +msgid "Protocol Version" +msgstr "プロトコルバージョン" + +#: command.c:866 +msgid "Password Used" +msgstr "パスワード使用" + +#: command.c:867 command.c:871 command.c:879 command.c:912 +msgid "false" +msgstr "false" + +#: command.c:867 command.c:871 command.c:879 command.c:912 +msgid "true" +msgstr "true" + +#: command.c:870 +msgid "GSSAPI Authenticated" +msgstr "GSSAPI認証" + +#: command.c:874 +msgid "Backend PID" +msgstr "バックエンドPID" + +#: command.c:878 +msgid "TLS Connection" +msgstr "TLS接続" -#: command.c:1069 command.c:1170 command.c:2675 +#: command.c:898 +msgid "TLS Library" +msgstr "TLSライブラリ" + +#: command.c:899 command.c:902 command.c:905 command.c:908 command.c:920 +#: command.c:924 command.c:4423 command.c:4424 +msgid "unknown" +msgstr "不明" + +#: command.c:901 +msgid "TLS Protocol" +msgstr "TLSプロトコル" + +#: command.c:904 +msgid "TLS Key Bits" +msgstr "TKSキービット数" + +#: command.c:907 +msgid "TLS Cipher" +msgstr "TLS暗号化方式" + +#: command.c:910 +msgid "TLS Compression" +msgstr "TLS圧縮" + +#: command.c:914 +msgid "ALPN" +msgstr "ALPN" + +#: command.c:915 command.c:4426 +msgid "none" +msgstr "なし" + +#: command.c:1332 command.c:1433 command.c:3184 #, c-format msgid "no query buffer" msgstr "問い合わせバッファがありません" -#: command.c:1102 command.c:5771 +#: command.c:1365 command.c:6307 #, c-format msgid "invalid line number: %s" msgstr "不正な行番号です: %s" -#: command.c:1248 +#: command.c:1511 msgid "No changes" msgstr "変更されていません" -#: command.c:1333 +#: command.c:1596 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: エンコーディング名が不正であるか、または変換プロシージャが見つかりません。" -#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5877 -#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 -#: common.c:1228 common.c:1347 common.c:1385 common.c:1482 common.c:1548 -#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 -#: startup.c:304 +#: command.c:1632 command.c:2572 command.c:3981 command.c:4179 command.c:6413 +#: common.c:233 common.c:282 common.c:455 common.c:1178 common.c:1196 +#: common.c:1264 common.c:1376 common.c:1414 common.c:1688 common.c:1768 +#: copy.c:486 copy.c:731 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:309 #, c-format msgid "%s" msgstr "%s" -#: command.c:1375 +#: command.c:1639 msgid "There is no previous error." msgstr "直前のエラーはありません。" -#: command.c:1488 +#: command.c:1742 +#, c-format +msgid "\\%s not allowed in pipeline mode" +msgstr "\\%s はパイプラインモードでは使用できません" + +#: command.c:1798 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: 右括弧がありません" -#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 -#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 +#: command.c:1924 #, c-format -msgid "\\%s: missing required argument" -msgstr "\\%s: 必要な引数がありません" +msgid "\\getresults: invalid number of requested results" +msgstr "\\getresults: 要求された結果の数が不正" -#: command.c:1822 +#: command.c:1949 +#, c-format +msgid "\\gexec not allowed in pipeline mode" +msgstr "\\gexec はパイプラインモードでは使用できません" + +#: command.c:1975 +#, c-format +msgid "\\gset not allowed in pipeline mode" +msgstr "\\gset はパイプラインモードでは使用できません" + +#: command.c:2181 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: \\else の後には置けません" -#: command.c:1827 +#: command.c:2186 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: 対応する \\if がありません" -#: command.c:1891 +#: command.c:2250 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: \\else の後には置けません" -#: command.c:1896 +#: command.c:2255 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: 対応する \\if がありません" -#: command.c:1936 +#: command.c:2295 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: 対応する \\if がありません" -#: command.c:2092 +#: command.c:2473 msgid "Query buffer is empty." msgstr "問い合わせバッファは空です。" -#: command.c:2135 +#: command.c:2550 #, c-format msgid "Enter new password for user \"%s\": " msgstr "ユーザー\"%s\"の新しいパスワードを入力してください: " -#: command.c:2139 +#: command.c:2554 msgid "Enter it again: " msgstr "もう一度入力してください: " -#: command.c:2148 +#: command.c:2563 #, c-format msgid "Passwords didn't match." msgstr "パスワードが一致しませんでした。" -#: command.c:2231 +#: command.c:2646 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: 変数の値を読み取ることができませんでした" -#: command.c:2333 +#: command.c:2748 msgid "Query buffer reset (cleared)." msgstr "問い合わせバッファがリセット(クリア)されました。" -#: command.c:2355 +#: command.c:2770 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "ファイル\"%s\"にヒストリーを出力しました。\n" -#: command.c:2442 +#: command.c:2800 +#, c-format +msgid "\\sendpipeline must be used after \\bind or \\bind_named" +msgstr "\\sendpipeline は \\bind または \\bind_named の後で使用する必要があります" + +#: command.c:2807 +#, c-format +msgid "\\sendpipeline not allowed outside of pipeline mode" +msgstr "\\sendpipeline はパイプラインモード以外では使用できません" + +#: command.c:2894 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: 環境変数名に\"=\"を含めることはできません" -#: command.c:2490 +#: command.c:2942 #, c-format msgid "function name is required" msgstr "関数名が必要です" -#: command.c:2492 +#: command.c:2944 #, c-format msgid "view name is required" msgstr "ビュー名が必要です" -#: command.c:2614 +#: command.c:3123 msgid "Timing is on." msgstr "タイミングは on です。" -#: command.c:2616 +#: command.c:3125 msgid "Timing is off." msgstr "タイミングは off です。" -#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 -#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 -#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 -#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 +#: command.c:3211 command.c:3249 command.c:4694 command.c:4697 command.c:4700 +#: command.c:4706 command.c:4708 command.c:4734 command.c:4744 command.c:4756 +#: command.c:4770 command.c:4797 command.c:4855 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:797 psqlscanslash.l:809 psqlscanslash.l:827 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2729 copy.c:388 +#: command.c:3238 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2801 command.c:2867 +#: command.c:3287 +#, c-format +msgid "\\watch not allowed in pipeline mode" +msgstr "\\watch はパイプラインモードでは使用できません" + +#: command.c:3319 command.c:3385 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: インターバル値が2回以上指定されました" -#: command.c:2811 command.c:2877 +#: command.c:3329 command.c:3395 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: 不正なインターバル値 \"%s\"" -#: command.c:2821 +#: command.c:3339 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: 反復回数が2回以上指定されました" -#: command.c:2831 +#: command.c:3349 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: 不正な反復回数 '%s'" -#: command.c:2841 +#: command.c:3359 #, c-format msgid "\\watch: minimum row count specified more than once" msgstr "\\watch: 詐称行数が2回以上指定されました" -#: command.c:2851 +#: command.c:3369 #, c-format msgid "\\watch: incorrect minimum row count \"%s\"" msgstr "\\watch: 不正な最小行数 \"%s\"" -#: command.c:2858 +#: command.c:3376 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: 認識できないパラーメータ \"%s\"" -#: command.c:3255 startup.c:243 startup.c:293 +#: command.c:3782 startup.c:248 startup.c:298 msgid "Password: " msgstr "パスワード: " -#: command.c:3260 startup.c:290 +#: command.c:3787 startup.c:295 #, c-format msgid "Password for user %s: " msgstr "ユーザー %s のパスワード: " -#: command.c:3316 +#: command.c:3843 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "接続文字列使用時はユーザー、ホストおよびポートは個別に指定しないでください" -#: command.c:3351 +#: command.c:3878 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "パラメータ再利用に使用可能なデータベース接続がありません" -#: command.c:3658 +#: command.c:4185 #, c-format msgid "Previous connection kept" msgstr "以前の接続は保持されています" -#: command.c:3664 +#: command.c:4191 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3720 +#: command.c:4247 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"のポート\"%s\"で接続しました。\n" -#: command.c:3723 +#: command.c:4250 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "データベース\"%s\"にユーザー\"%s\"として、ソケット\"%s\"のポート\"%s\"を介して接続しました。\n" -#: command.c:3729 +#: command.c:4256 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"(アドレス\"%s\")のポート\"%s\"で接続しました。\n" -#: command.c:3732 +#: command.c:4259 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "データベース\"%s\"にユーザー\"%s\"として、ホスト\"%s\"のポート\"%s\"を介して接続しました。\n" -#: command.c:3737 +#: command.c:4264 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "データベース\"%s\"にユーザー\"%s\"として接続しました。\n" -#: command.c:3843 +#: command.c:4370 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s、サーバー %s)\n" -#: command.c:3856 +#: command.c:4383 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -502,33 +609,25 @@ msgstr "" "警告: %s のメジャーバージョンは %s ですが、サーバーのメジャーバージョンは %s です。\n" " psql の機能の中で、動作しないものがあるかもしれません。\n" -#: command.c:3895 +#: command.c:4422 #, c-format msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" msgstr "SSL接続(プロトコル: %s、暗号化方式: %s、圧縮: %s、ALPN: %s)\n" -#: command.c:3896 command.c:3897 -msgid "unknown" -msgstr "不明" - -#: command.c:3898 help.c:42 +#: command.c:4425 help.c:39 msgid "off" msgstr "オフ" -#: command.c:3898 help.c:42 +#: command.c:4425 help.c:39 msgid "on" msgstr "オン" -#: command.c:3899 -msgid "none" -msgstr "なし" - -#: command.c:3913 +#: command.c:4440 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "GSSAPI暗号化接続\n" -#: command.c:3933 +#: command.c:4460 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -539,283 +638,283 @@ msgstr "" " 8ビット文字が正しく表示されない可能性があります。詳細はpsqlリファレンスマニュアルの\n" " \"Windowsユーザー向けの注意\" (Notes for Windows users)を参照してください。\n" -#: command.c:4038 +#: command.c:4569 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "環境変数PSQL_EDITOR_LINENUMBER_ARGで行番号を指定する必要があります" -#: command.c:4068 +#: command.c:4599 #, c-format msgid "could not start editor \"%s\"" msgstr "エディタ\"%s\"を起動できませんでした" -#: command.c:4070 +#: command.c:4601 #, c-format msgid "could not start /bin/sh" msgstr "/bin/shを起動できませんでした" -#: command.c:4120 +#: command.c:4651 #, c-format msgid "could not locate temporary directory: %s" msgstr "一時ディレクトリが見つかりませんでした: %s" -#: command.c:4147 +#: command.c:4678 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "一時ファイル\"%s\"をオープンできませんでした: %m" -#: command.c:4483 +#: command.c:5014 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: 曖昧な短縮形\"%s\"が\"%s\"と\"%s\"のどちらにも合致します" -#: command.c:4503 +#: command.c:5034 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset: 有効なフォーマットはaligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4522 +#: command.c:5053 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: 有効な線のスタイルは ascii, old-ascii, unicode" -#: command.c:4537 +#: command.c:5068 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: 有効な Unicode 罫線のスタイルは single, double" -#: command.c:4552 +#: command.c:5083 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: 有効な Unicode 列罫線のスタイルは single, double" -#: command.c:4567 +#: command.c:5098 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: 有効な Unicode ヘッダー罫線のスタイルは single, double" -#: command.c:4619 +#: command.c:5150 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: xheader_widthに指定可能な値は、\"%s\" (default)、\"%s\"、\"%s\"、または幅そのものを指定する数値です" -#: command.c:4636 +#: command.c:5167 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsepは単一の1バイト文字でなければなりません" -#: command.c:4641 +#: command.c:5172 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldsepはダブルクォート、改行(LF)または復帰(CR)にはできません" -#: command.c:4779 command.c:4980 +#: command.c:5310 command.c:5511 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: 未定義のオプション:%s" -#: command.c:4799 +#: command.c:5330 #, c-format msgid "Border style is %d.\n" msgstr "罫線スタイルは %d です。\n" -#: command.c:4805 +#: command.c:5336 #, c-format msgid "Target width is unset.\n" msgstr "ターゲットの幅が設定されていません。\n" -#: command.c:4807 +#: command.c:5338 #, c-format msgid "Target width is %d.\n" msgstr "ターゲットの幅は %d です。\n" -#: command.c:4814 +#: command.c:5345 #, c-format msgid "Expanded display is on.\n" msgstr "拡張表示は on です。\n" -#: command.c:4816 +#: command.c:5347 #, c-format msgid "Expanded display is used automatically.\n" msgstr "拡張表示が自動的に使われます。\n" -#: command.c:4818 +#: command.c:5349 #, c-format msgid "Expanded display is off.\n" msgstr "拡張表示は off です。\n" -#: command.c:4825 command.c:4827 command.c:4829 +#: command.c:5356 command.c:5358 command.c:5360 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "拡張表示ヘッダ幅は\"%s\"です。\n" -#: command.c:4831 +#: command.c:5362 #, c-format msgid "Expanded header width is %d.\n" msgstr "拡張表示ヘッダ幅は%dです。\n" -#: command.c:4837 +#: command.c:5368 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "CSVのフィールド区切り文字は\"%s\"です。\n" -#: command.c:4845 command.c:4853 +#: command.c:5376 command.c:5384 #, c-format msgid "Field separator is zero byte.\n" msgstr "フィールド区切り文字はゼロバイトです。\n" -#: command.c:4847 +#: command.c:5378 #, c-format msgid "Field separator is \"%s\".\n" msgstr "フィールド区切り文字は\"%s\"です。\n" -#: command.c:4860 +#: command.c:5391 #, c-format msgid "Default footer is on.\n" msgstr "デフォルトフッター(行数の表示)は on です。\n" -#: command.c:4862 +#: command.c:5393 #, c-format msgid "Default footer is off.\n" msgstr "デフォルトフッター(行数の表示)は off です。\n" -#: command.c:4868 +#: command.c:5399 #, c-format msgid "Output format is %s.\n" msgstr "出力形式は %s です。\n" -#: command.c:4874 +#: command.c:5405 #, c-format msgid "Line style is %s.\n" msgstr "線のスタイルは %s です。\n" -#: command.c:4881 +#: command.c:5412 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null表示は\"%s\"です。\n" -#: command.c:4889 +#: command.c:5420 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "『数値出力時のロケール調整』は on です。\n" -#: command.c:4891 +#: command.c:5422 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "『数値出力時のロケール調整』は off です。\n" -#: command.c:4898 +#: command.c:5429 #, c-format msgid "Pager is used for long output.\n" msgstr "表示が縦に長くなる場合はページャーを使います。\n" -#: command.c:4900 +#: command.c:5431 #, c-format msgid "Pager is always used.\n" msgstr "常にページャーを使います。\n" -#: command.c:4902 +#: command.c:5433 #, c-format msgid "Pager usage is off.\n" msgstr "「ページャーを使う」は off です。\n" -#: command.c:4908 +#: command.c:5439 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "%d 行未満の場合、ページャーは使われません。\n" -#: command.c:4918 command.c:4928 +#: command.c:5449 command.c:5459 #, c-format msgid "Record separator is zero byte.\n" msgstr "レコードの区切り文字はゼロバイトです\n" -#: command.c:4920 +#: command.c:5451 #, c-format msgid "Record separator is .\n" msgstr "レコード区切り文字はです。\n" -#: command.c:4922 +#: command.c:5453 #, c-format msgid "Record separator is \"%s\".\n" msgstr "レコード区切り記号は\"%s\"です。\n" -#: command.c:4935 +#: command.c:5466 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "テーブル属性は\"%s\"です。\n" -#: command.c:4938 +#: command.c:5469 #, c-format msgid "Table attributes unset.\n" msgstr "テーブル属性は設定されていません。\n" -#: command.c:4945 +#: command.c:5476 #, c-format msgid "Title is \"%s\".\n" msgstr "タイトルは\"%s\"です。\n" -#: command.c:4947 +#: command.c:5478 #, c-format msgid "Title is unset.\n" msgstr "タイトルは設定されていません。\n" -#: command.c:4954 +#: command.c:5485 #, c-format msgid "Tuples only is on.\n" msgstr "「タプルのみ表示」は on です。\n" -#: command.c:4956 +#: command.c:5487 #, c-format msgid "Tuples only is off.\n" msgstr "「タプルのみ表示」は off です。\n" -#: command.c:4962 +#: command.c:5493 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Unicode の罫線スタイルは\"%s\"です。\n" -#: command.c:4968 +#: command.c:5499 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Unicode 行罫線のスタイルは\"%s\"です。\n" -#: command.c:4974 +#: command.c:5505 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Unicodeヘッダー行のスタイルは\"%s\"です。\n" -#: command.c:5223 +#: command.c:5754 #, c-format msgid "\\!: failed" msgstr "\\!: 失敗" -#: command.c:5257 +#: command.c:5792 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watchは空の問い合わせでは使えません" -#: command.c:5289 +#: command.c:5824 #, c-format msgid "could not set timer: %m" msgstr "タイマーを設定できません: %m" -#: command.c:5358 +#: command.c:5893 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (%g 秒毎)\n" -#: command.c:5361 +#: command.c:5896 #, c-format msgid "%s (every %gs)\n" msgstr "%s (%g 秒毎)\n" -#: command.c:5424 +#: command.c:5960 #, c-format msgid "could not wait for signals: %m" msgstr "シグナルを待機できませんでした: %m" -#: command.c:5480 command.c:5487 common.c:632 common.c:639 common.c:1123 +#: command.c:6016 command.c:6023 common.c:667 common.c:674 common.c:1159 #, c-format msgid "" "/******** QUERY *********/\n" @@ -828,107 +927,107 @@ msgstr "" "/************************/\n" "\n" -#: command.c:5666 +#: command.c:6202 #, c-format msgid "\"%s.%s\" is not a view" msgstr "\"%s.%s\"はビューではありません" -#: command.c:5682 +#: command.c:6218 #, c-format msgid "could not parse reloptions array" msgstr "reloptions配列をパースできませんでした" -#: common.c:206 +#: common.c:218 #, c-format msgid "cannot escape without active connection" msgstr "有効な接続がないのでエスケープできません" -#: common.c:247 +#: common.c:259 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"" -#: common.c:351 +#: common.c:363 #, c-format msgid "connection to server was lost" msgstr "サーバーへの接続が失われました" -#: common.c:355 +#: common.c:367 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "サーバーへの接続が失われました。リセットしています: " -#: common.c:360 +#: common.c:373 #, c-format msgid "Failed.\n" msgstr "失敗。\n" -#: common.c:377 +#: common.c:390 #, c-format msgid "Succeeded.\n" msgstr "成功。\n" -#: common.c:430 common.c:1061 +#: common.c:445 common.c:1097 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "想定外のPQresultStatus: %d" -#: common.c:571 +#: common.c:606 #, c-format msgid "Time: %.3f ms\n" msgstr "時間: %.3f ミリ秒\n" -#: common.c:586 +#: common.c:621 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "時間: %.3f ミリ秒(%02d:%06.3f)\n" -#: common.c:595 +#: common.c:630 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "時間: %.3f ミリ秒 (%02d:%02d:%06.3f)\n" -#: common.c:602 +#: common.c:637 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "時間: %.3f ミリ秒 (%.0f 日 %02d:%02d:%06.3f)\n" -#: common.c:626 common.c:683 common.c:1094 describe.c:6192 +#: common.c:661 common.c:718 common.c:1130 describe.c:6370 #, c-format msgid "You are currently not connected to a database." msgstr "現在データベースに接続していません。" -#: common.c:714 +#: common.c:749 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "PID %3$dのサーバープロセスから、ペイロード\"%2$s\"を持つ非同期通知\"%1$s\"を受信しました。\n" -#: common.c:717 +#: common.c:752 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "PID %2$dのサーバープロセスから非同期通知\"%1$s\"を受信しました。\n" -#: common.c:748 +#: common.c:783 #, c-format msgid "could not print result table: %m" msgstr "結果テーブルを表示できませんでした: %m" -#: common.c:768 +#: common.c:803 #, c-format msgid "no rows returned for \\gset" msgstr "\\gset に対して返すべき行がありません" -#: common.c:773 +#: common.c:808 #, c-format msgid "more than one row returned for \\gset" msgstr "\\gset に対して複数の行が返されました" -#: common.c:791 +#: common.c:826 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "特殊変数\"%s\"への\\gsetは無視されました" -#: common.c:1103 +#: common.c:1139 #, c-format msgid "" "/**(Single step mode: verify command)******************************************/\n" @@ -939,37 +1038,47 @@ msgstr "" "%s\n" "/**([Enter] を押して進むか、x [Enter] でキャンセル)****************************/\n" -#: common.c:1180 +#: common.c:1216 #, c-format msgid "STATEMENT: %s" msgstr "文: %s" -#: common.c:1216 +#: common.c:1252 #, c-format msgid "unexpected transaction status (%d)" msgstr "想定外のトランザクション状態(%d)" -#: common.c:1369 describe.c:2025 +#: common.c:1398 describe.c:2063 msgid "Column" msgstr "列" -#: common.c:1370 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 -#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 -#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 -#: describe.c:5829 +#: common.c:1399 describe.c:176 describe.c:362 describe.c:380 describe.c:1081 +#: describe.c:1243 describe.c:1773 describe.c:1797 describe.c:2064 +#: describe.c:4057 describe.c:4321 describe.c:4568 describe.c:4728 +#: describe.c:6004 msgid "Type" msgstr "タイプ" -#: common.c:1419 +#: common.c:1448 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "このコマンドは結果を返却しないか、結果にカラムが含まれません。\n" -#: common.c:1511 +#: common.c:1653 +#, c-format +msgid "No pending results to get" +msgstr "取得すべき保留中の結果はありません" + +#: common.c:1731 #, c-format msgid "fetching results in chunked mode failed" msgstr "チャンクモードでの結果の取得に失敗しました" +#: common.c:1780 +#, c-format +msgid "Pipeline aborted, command did not run" +msgstr "パイプラインが中断され、コマンドは実行されませんでした" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -1022,11 +1131,11 @@ msgstr "" "コピーするデータに続いて改行を入力してください。\n" "バックスラッシュとピリオドだけの行、もしくは EOF シグナルで終了します。" -#: copy.c:684 +#: copy.c:693 msgid "aborted because of read failure" msgstr "読み取りエラーのため中止" -#: copy.c:718 +#: copy.c:727 msgid "trying to exit copy mode" msgstr "コピーモードを終了しようとしています。" @@ -1075,1161 +1184,1251 @@ msgstr "\\crosstabview: 列名があいまいです: \"%s\"" msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: 列名が見つかりませんでした: \"%s\"" -#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 -#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 -#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 -#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 -#: describe.c:5542 describe.c:5941 describe.c:6018 +#: describe.c:94 describe.c:342 describe.c:649 describe.c:826 describe.c:1073 +#: describe.c:1230 describe.c:1306 describe.c:4046 describe.c:4308 +#: describe.c:4566 describe.c:4647 describe.c:4879 describe.c:5091 +#: describe.c:5340 describe.c:5581 describe.c:5650 describe.c:5661 +#: describe.c:5717 describe.c:6116 describe.c:6196 msgid "Schema" msgstr "スキーマ" -#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 -#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 -#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 -#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 -#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 -#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 -#: describe.c:6016 describe.c:6243 describe.c:6551 +#: describe.c:95 describe.c:173 describe.c:234 describe.c:343 describe.c:650 +#: describe.c:827 describe.c:958 describe.c:1074 describe.c:1307 +#: describe.c:4047 describe.c:4309 describe.c:4483 describe.c:4567 +#: describe.c:4648 describe.c:4809 describe.c:4880 describe.c:5092 +#: describe.c:5213 describe.c:5341 describe.c:5582 describe.c:5651 +#: describe.c:5662 describe.c:5718 describe.c:5915 describe.c:5985 +#: describe.c:6193 describe.c:6421 describe.c:6767 msgid "Name" msgstr "名前" -#: describe.c:89 describe.c:348 describe.c:366 +#: describe.c:96 describe.c:355 describe.c:373 msgid "Result data type" msgstr "結果のデータ型" -#: describe.c:90 describe.c:349 describe.c:367 +#: describe.c:97 describe.c:356 describe.c:374 msgid "Argument data types" msgstr "引数のデータ型" -#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 -#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 -#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 -#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 -#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 -#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 -#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 -#: describe.c:6019 describe.c:7078 +#: describe.c:105 describe.c:112 describe.c:184 describe.c:248 describe.c:432 +#: describe.c:681 describe.c:846 describe.c:1010 describe.c:1309 +#: describe.c:2084 describe.c:3773 describe.c:4105 describe.c:4362 +#: describe.c:4507 describe.c:4580 describe.c:4657 describe.c:4822 +#: describe.c:5004 describe.c:5150 describe.c:5222 describe.c:5342 +#: describe.c:5492 describe.c:5533 describe.c:5598 describe.c:5654 +#: describe.c:5663 describe.c:5719 describe.c:5933 describe.c:6007 +#: describe.c:6130 describe.c:6197 describe.c:7303 msgid "Description" msgstr "説明" -#: describe.c:127 +#: describe.c:134 msgid "List of aggregate functions" msgstr "集約関数一覧" -#: describe.c:152 +#: describe.c:159 #, c-format msgid "The server (version %s) does not support access methods." msgstr "このサーバー(バージョン%s)はアクセスメソッドをサポートしていません。" -#: describe.c:167 +#: describe.c:174 msgid "Index" msgstr "インデックス" -#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 +#: describe.c:175 describe.c:4065 describe.c:4334 describe.c:6117 msgid "Table" msgstr "テーブル" -#: describe.c:176 describe.c:5742 +#: describe.c:183 describe.c:5917 msgid "Handler" msgstr "ハンドラ" -#: describe.c:199 +#: describe.c:206 msgid "List of access methods" msgstr "アクセスメソッド一覧" -#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 -#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 -#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 -#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 -#: describe.c:7066 +#: describe.c:235 describe.c:415 describe.c:674 describe.c:959 describe.c:1229 +#: describe.c:4058 describe.c:4310 describe.c:4484 describe.c:4811 +#: describe.c:5214 describe.c:5916 describe.c:5986 describe.c:6422 +#: describe.c:6643 describe.c:6768 describe.c:6938 describe.c:7023 +#: describe.c:7291 msgid "Owner" msgstr "所有者" -#: describe.c:229 +#: describe.c:236 msgid "Location" msgstr "場所" -#: describe.c:239 describe.c:3517 describe.c:3857 -msgid "Options" -msgstr "オプション" - -#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 +#: describe.c:247 describe.c:672 describe.c:1008 describe.c:4104 msgid "Size" msgstr "サイズ" -#: describe.c:263 +#: describe.c:270 msgid "List of tablespaces" msgstr "テーブル空間一覧" -#: describe.c:308 +#: describe.c:315 #, c-format -msgid "\\df only takes [anptwS+] as options" -msgstr "\\dfで指定できるオプションは [anptwS+] のみです" +msgid "\\df only takes [anptwSx+] as options" +msgstr "\\dfで指定できるオプションは [anptwSx+] のみです" -#: describe.c:316 +#: describe.c:323 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\dfはこのサーバーバージョン%2$sでは\"%1$c\"オプションは指定できません" #. translator: "agg" is short for "aggregate" -#: describe.c:351 describe.c:369 +#: describe.c:358 describe.c:376 msgid "agg" msgstr "集約" -#: describe.c:352 describe.c:370 +#: describe.c:359 describe.c:377 msgid "window" msgstr "ウィンドウ" -#: describe.c:353 +#: describe.c:360 msgid "proc" msgstr "プロシージャ" -#: describe.c:354 describe.c:372 +#: describe.c:361 describe.c:379 msgid "func" msgstr "関数" -#: describe.c:371 describe.c:1397 +#: describe.c:378 describe.c:1439 msgid "trigger" msgstr "トリガー" -#: describe.c:383 +#: describe.c:393 msgid "immutable" msgstr "IMMUTABLE" -#: describe.c:384 +#: describe.c:394 msgid "stable" msgstr "STABLE" -#: describe.c:385 +#: describe.c:395 msgid "volatile" msgstr "VOLATILE" -#: describe.c:386 +#: describe.c:396 msgid "Volatility" msgstr "関数の変動性分類" -#: describe.c:394 +#: describe.c:407 msgid "restricted" msgstr "制限付き" -#: describe.c:395 +#: describe.c:408 msgid "safe" msgstr "安全" -#: describe.c:396 +#: describe.c:409 msgid "unsafe" msgstr "危険" -#: describe.c:397 +#: describe.c:410 msgid "Parallel" msgstr "並列実行" -#: describe.c:402 +#: describe.c:416 msgid "definer" msgstr "定義ロール" -#: describe.c:403 +#: describe.c:417 msgid "invoker" msgstr "起動ロール" -#: describe.c:404 +#: describe.c:418 msgid "Security" msgstr "セキュリティ" -#: describe.c:409 +#: describe.c:419 describe.c:837 describe.c:1778 describe.c:1802 +#: describe.c:1931 describe.c:4651 describe.c:4992 describe.c:5001 +#: describe.c:5139 describe.c:5144 describe.c:6926 describe.c:7125 +msgid "yes" +msgstr "はい" + +#: describe.c:420 describe.c:838 describe.c:1779 describe.c:1803 +#: describe.c:1932 describe.c:4651 describe.c:4989 describe.c:5002 +#: describe.c:5139 describe.c:6927 describe.c:7126 +msgid "no" +msgstr "いいえ" + +#: describe.c:421 describe.c:839 describe.c:5003 describe.c:7127 +msgid "Leakproof?" +msgstr "無漏洩?" + +#: describe.c:426 msgid "Language" msgstr "手続き言語" -#: describe.c:412 describe.c:648 +#: describe.c:429 describe.c:671 msgid "Internal name" msgstr "内部名" -#: describe.c:585 +#: describe.c:608 msgid "List of functions" msgstr "関数一覧" -#: describe.c:650 +#: describe.c:673 msgid "Elements" msgstr "構成要素" -#: describe.c:701 +#: describe.c:724 msgid "List of data types" msgstr "データ型一覧" -#: describe.c:804 +#: describe.c:828 msgid "Left arg type" msgstr "左辺の型" -#: describe.c:805 +#: describe.c:829 msgid "Right arg type" msgstr "右辺の型" -#: describe.c:806 +#: describe.c:830 msgid "Result type" msgstr "結果の型" -#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 -#: describe.c:6996 describe.c:7000 +#: describe.c:836 describe.c:4817 describe.c:4981 describe.c:5491 +#: describe.c:7221 describe.c:7225 msgid "Function" msgstr "関数" -#: describe.c:891 +#: describe.c:923 msgid "List of operators" msgstr "演算子一覧" -#: describe.c:926 +#: describe.c:960 msgid "Encoding" msgstr "エンコーディング" -#: describe.c:930 describe.c:934 +#: describe.c:968 describe.c:972 msgid "Locale Provider" msgstr "ロケールプロバイダー" -#: describe.c:938 describe.c:4936 +#: describe.c:976 describe.c:5111 msgid "Collate" msgstr "照合順序" -#: describe.c:939 describe.c:4937 +#: describe.c:977 describe.c:5112 msgid "Ctype" msgstr "Ctype(変換演算子)" -#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 -#: describe.c:4950 +#: describe.c:981 describe.c:985 describe.c:989 describe.c:5117 describe.c:5121 +#: describe.c:5125 msgid "Locale" msgstr "ロケール" -#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 +#: describe.c:993 describe.c:997 describe.c:5130 describe.c:5134 msgid "ICU Rules" msgstr "ICUルール:" -#: describe.c:971 +#: describe.c:1009 msgid "Tablespace" msgstr "テーブル空間" -#: describe.c:996 +#: describe.c:1034 msgid "List of databases" msgstr "データベース一覧" -#: describe.c:1037 describe.c:1192 describe.c:3947 +#: describe.c:1075 describe.c:1232 describe.c:4048 msgid "table" msgstr "テーブル" -#: describe.c:1038 describe.c:3948 +#: describe.c:1076 describe.c:4049 msgid "view" msgstr "ビュー" -#: describe.c:1039 describe.c:3949 +#: describe.c:1077 describe.c:4050 msgid "materialized view" msgstr "実体化ビュー" -#: describe.c:1040 describe.c:1194 describe.c:3951 +#: describe.c:1078 describe.c:1234 describe.c:4052 msgid "sequence" msgstr "シーケンス" -#: describe.c:1041 describe.c:3953 +#: describe.c:1079 describe.c:4054 msgid "foreign table" msgstr "外部テーブル" -#: describe.c:1042 describe.c:3954 describe.c:4165 +#: describe.c:1080 describe.c:4055 describe.c:4319 msgid "partitioned table" msgstr "パーティションテーブル" -#: describe.c:1058 +#: describe.c:1096 msgid "Column privileges" msgstr "列の権限" -#: describe.c:1089 describe.c:1123 +#: describe.c:1127 describe.c:1161 msgid "Policies" msgstr "ポリシー" -#: describe.c:1151 describe.c:4570 describe.c:6667 +#: describe.c:1189 describe.c:4734 describe.c:6883 msgid "Access privileges" msgstr "アクセス権限" -#: describe.c:1196 +#: describe.c:1236 msgid "function" msgstr "関数" -#: describe.c:1198 +#: describe.c:1238 msgid "type" msgstr "型" -#: describe.c:1200 +#: describe.c:1240 msgid "schema" msgstr "スキーマ" -#: describe.c:1222 +#: describe.c:1242 +msgid "large object" +msgstr "ラージオブジェクト" + +#: describe.c:1264 msgid "Default access privileges" msgstr "デフォルトのアクセス権限" -#: describe.c:1266 +#: describe.c:1308 msgid "Object" msgstr "オブジェクト" -#: describe.c:1280 +#: describe.c:1322 msgid "table constraint" msgstr "テーブル制約" -#: describe.c:1304 +#: describe.c:1346 msgid "domain constraint" msgstr "ドメイン制約" -#: describe.c:1328 +#: describe.c:1370 msgid "operator class" msgstr "演算子クラス" -#: describe.c:1352 +#: describe.c:1394 msgid "operator family" msgstr "演算子族" -#: describe.c:1375 +#: describe.c:1417 msgid "rule" msgstr "ルール" -#: describe.c:1420 +#: describe.c:1462 msgid "Object descriptions" msgstr "オブジェクトの説明" -#: describe.c:1485 describe.c:4072 +#: describe.c:1527 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "\"%s\"という名前のリレーションは見つかりませんでした。" -#: describe.c:1488 describe.c:4075 +#: describe.c:1530 describe.c:4206 #, c-format msgid "Did not find any relations." msgstr "リレーションが見つかりませんでした。" -#: describe.c:1684 +#: describe.c:1726 #, c-format msgid "Did not find any relation with OID %s." msgstr "OID %sを持つリレーションが見つかりませんでした。" -#: describe.c:1732 describe.c:1756 +#: describe.c:1774 describe.c:1798 msgid "Start" msgstr "開始" -#: describe.c:1733 describe.c:1757 +#: describe.c:1775 describe.c:1799 msgid "Minimum" msgstr "最小" -#: describe.c:1734 describe.c:1758 +#: describe.c:1776 describe.c:1800 msgid "Maximum" msgstr "最大" -#: describe.c:1735 describe.c:1759 +#: describe.c:1777 describe.c:1801 msgid "Increment" msgstr "増分" -#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 -#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 -msgid "yes" -msgstr "はい" - -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 -#: describe.c:4825 describe.c:4964 describe.c:6711 -msgid "no" -msgstr "いいえ" - -#: describe.c:1738 describe.c:1762 +#: describe.c:1780 describe.c:1804 msgid "Cycles?" msgstr "循環?" -#: describe.c:1739 describe.c:1763 +#: describe.c:1781 describe.c:1805 msgid "Cache" msgstr "キャッシュ" -#: describe.c:1804 +#: describe.c:1846 #, c-format msgid "Owned by: %s" msgstr "所有者: %s" -#: describe.c:1808 +#: describe.c:1850 #, c-format msgid "Sequence for identity column: %s" msgstr "識別列のシーケンス: %s" -#: describe.c:1816 +#: describe.c:1858 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "ログ出力なしのシーケンス\"%s.%s\"" -#: describe.c:1819 +#: describe.c:1861 #, c-format msgid "Sequence \"%s.%s\"" msgstr "シーケンス \"%s.%s\"" -#: describe.c:1962 +#: describe.c:2004 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "ログ出力なしのテーブル\"%s.%s\"" -#: describe.c:1965 +#: describe.c:2007 #, c-format msgid "Table \"%s.%s\"" msgstr "テーブル\"%s.%s\"" -#: describe.c:1969 +#: describe.c:2011 #, c-format msgid "View \"%s.%s\"" msgstr "ビュー\"%s.%s\"" -#: describe.c:1974 -#, c-format -msgid "Unlogged materialized view \"%s.%s\"" -msgstr "ログ出力なしの実体化ビュー\"%s.%s\"" - -#: describe.c:1977 +#: describe.c:2015 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "実体化ビュー\"%s.%s\"" -#: describe.c:1982 +#: describe.c:2020 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "ログ出力なしのインデックス\"%s.%s\"" -#: describe.c:1985 +#: describe.c:2023 #, c-format msgid "Index \"%s.%s\"" msgstr "インデックス\"%s.%s\"" -#: describe.c:1990 +#: describe.c:2028 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "ログ出力なしのパーティション親インデックス\"%s.%s\"" -#: describe.c:1993 +#: describe.c:2031 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "パーティションインデックス\"%s.%s\"" -#: describe.c:1997 +#: describe.c:2035 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "TOAST テーブル\"%s.%s\"" -#: describe.c:2001 +#: describe.c:2039 #, c-format msgid "Composite type \"%s.%s\"" msgstr "複合型\"%s.%s\"" -#: describe.c:2005 +#: describe.c:2043 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "外部テーブル\"%s.%s\"" -#: describe.c:2010 +#: describe.c:2048 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "ログ出力なしのパーティション親テーブル\"%s.%s\"" -#: describe.c:2013 +#: describe.c:2051 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "パーティションテーブル\"%s.%s\"" -#: describe.c:2029 describe.c:4405 +#: describe.c:2067 describe.c:4569 msgid "Collation" msgstr "照合順序" -#: describe.c:2030 describe.c:4406 +#: describe.c:2068 describe.c:4570 msgid "Nullable" msgstr "Null 値を許容" -#: describe.c:2031 describe.c:4407 +#: describe.c:2069 describe.c:4571 msgid "Default" msgstr "デフォルト" -#: describe.c:2034 +#: describe.c:2072 msgid "Key?" msgstr "キー?" -#: describe.c:2036 describe.c:4723 describe.c:4734 +#: describe.c:2074 describe.c:4887 describe.c:4898 msgid "Definition" msgstr "定義" -#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 -#: describe.c:5954 +#: describe.c:2076 describe.c:5932 describe.c:6006 describe.c:6071 +#: describe.c:6129 msgid "FDW options" msgstr "FDW オプション" -#: describe.c:2040 +#: describe.c:2078 msgid "Storage" msgstr "ストレージ" -#: describe.c:2042 +#: describe.c:2080 msgid "Compression" msgstr "圧縮" -#: describe.c:2044 +#: describe.c:2082 msgid "Stats target" msgstr "統計目標" -#: describe.c:2180 +#: describe.c:2224 #, c-format msgid "Partition of: %s %s%s" msgstr "親パーティション: %s %s%s" -#: describe.c:2193 +#: describe.c:2237 msgid "No partition constraint" msgstr "パーティション制約なし" -#: describe.c:2195 +#: describe.c:2239 #, c-format msgid "Partition constraint: %s" msgstr "パーティションの制約: %s" -#: describe.c:2219 +#: describe.c:2263 #, c-format msgid "Partition key: %s" msgstr "パーティションキー: %s" -#: describe.c:2245 +#: describe.c:2289 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "所属先テーブル\"%s.%s\"" -#: describe.c:2314 +#: describe.c:2362 msgid "primary key, " msgstr "プライマリキー, " -#: describe.c:2317 +#: describe.c:2365 msgid "unique" msgstr "ユニーク" -#: describe.c:2319 +#: describe.c:2367 msgid " nulls not distinct" msgstr " nulls not distinct" -#: describe.c:2320 +#: describe.c:2368 msgid ", " msgstr ", " -#: describe.c:2327 +#: describe.c:2375 #, c-format msgid "for table \"%s.%s\"" msgstr "テーブル\"%s.%s\"用" -#: describe.c:2331 +#: describe.c:2379 #, c-format msgid ", predicate (%s)" msgstr "、述語 (%s)" -#: describe.c:2334 +#: describe.c:2382 msgid ", clustered" msgstr "、クラスター化" -#: describe.c:2337 +#: describe.c:2385 msgid ", invalid" msgstr "無効" -#: describe.c:2340 +#: describe.c:2388 msgid ", deferrable" msgstr "、遅延可能" -#: describe.c:2343 +#: describe.c:2391 msgid ", initially deferred" msgstr "、最初から遅延中" -#: describe.c:2346 +#: describe.c:2394 msgid ", replica identity" msgstr "、レプリカの id" -#: describe.c:2400 +#: describe.c:2455 msgid "Indexes:" msgstr "インデックス:" -#: describe.c:2483 +#: describe.c:2543 msgid "Check constraints:" msgstr "Check 制約:" -#: describe.c:2551 +#: describe.c:2604 msgid "Foreign-key constraints:" msgstr "外部キー制約:" -#: describe.c:2614 +#: describe.c:2663 msgid "Referenced by:" msgstr "参照元:" -#: describe.c:2664 +#: describe.c:2712 msgid "Policies:" msgstr "ポリシー:" -#: describe.c:2667 +#: describe.c:2715 msgid "Policies (forced row security enabled):" msgstr "ポリシー(行セキュリティを強制的に有効化):" -#: describe.c:2670 +#: describe.c:2718 msgid "Policies (row security enabled): (none)" msgstr "ポリシー(行セキュリティ有効化): (なし)" -#: describe.c:2673 +#: describe.c:2721 msgid "Policies (forced row security enabled): (none)" msgstr "ポリシー(行セキュリティを強制的に有効化): (なし)" -#: describe.c:2676 +#: describe.c:2724 msgid "Policies (row security disabled):" msgstr "ポリシー(行セキュリティを無効化):" -#: describe.c:2736 describe.c:2841 +#: describe.c:2784 describe.c:2889 msgid "Statistics objects:" msgstr "統計オブジェクト:" -#: describe.c:2943 describe.c:3096 +#: describe.c:2991 describe.c:3191 msgid "Rules:" msgstr "ルール:" -#: describe.c:2946 +#: describe.c:2994 msgid "Disabled rules:" msgstr "無効化されたルール:" -#: describe.c:2949 +#: describe.c:2997 msgid "Rules firing always:" msgstr "常に適用するルール:" -#: describe.c:2952 +#: describe.c:3000 msgid "Rules firing on replica only:" msgstr "レプリカ上でのみ適用するルール:" -#: describe.c:3031 describe.c:5100 +#: describe.c:3079 describe.c:5275 msgid "Publications:" msgstr "パブリケーション:" -#: describe.c:3079 +#: describe.c:3126 +msgid "Not-null constraints:" +msgstr "非NULL制約:" + +#: describe.c:3140 +msgid " (local, inherited)" +msgstr "(ローカル、継承)" + +#: describe.c:3141 +msgid " (inherited)" +msgstr "(継承)" + +#: describe.c:3174 msgid "View definition:" msgstr "ビューの定義:" -#: describe.c:3242 +#: describe.c:3337 msgid "Triggers:" msgstr "トリガー:" -#: describe.c:3245 +#: describe.c:3340 msgid "Disabled user triggers:" msgstr "無効化されたユーザートリガ:" -#: describe.c:3248 +#: describe.c:3343 msgid "Disabled internal triggers:" msgstr "無効化された内部トリガー:" -#: describe.c:3251 +#: describe.c:3346 msgid "Triggers firing always:" msgstr "常に適用するするトリガー:" -#: describe.c:3254 +#: describe.c:3349 msgid "Triggers firing on replica only:" msgstr "レプリカ上でのみ適用するトリガー:" -#: describe.c:3325 +#: describe.c:3420 #, c-format msgid "Server: %s" msgstr "サーバー: %s" -#: describe.c:3333 +#: describe.c:3428 #, c-format msgid "FDW options: (%s)" msgstr "FDW オプション: (%s)" -#: describe.c:3354 +#: describe.c:3449 msgid "Inherits" msgstr "継承元" -#: describe.c:3419 +#: describe.c:3514 #, c-format msgid "Number of partitions: %d" msgstr "パーティション数: %d" -#: describe.c:3428 +#: describe.c:3523 #, c-format msgid "Number of partitions: %d (Use \\d+ to list them.)" msgstr "パーティション数: %d (\\d+ で一覧を表示)。" -#: describe.c:3430 +#: describe.c:3525 #, c-format msgid "Number of child tables: %d (Use \\d+ to list them.)" msgstr "子テーブル数: %d (\\d+ で一覧を表示)" -#: describe.c:3437 +#: describe.c:3532 msgid "Child tables" msgstr "子テーブル" -#: describe.c:3437 +#: describe.c:3532 msgid "Partitions" msgstr "パーティション" -#: describe.c:3470 +#: describe.c:3565 #, c-format msgid "Typed table of type: %s" msgstr "%s 型の型付きテーブル" -#: describe.c:3486 +#: describe.c:3583 msgid "Replica Identity" msgstr "レプリカ識別" -#: describe.c:3499 +#: describe.c:3596 msgid "Has OIDs: yes" msgstr "OID あり: はい" -#: describe.c:3508 +#: describe.c:3605 #, c-format msgid "Access method: %s" msgstr "アクセスメソッド: %s" -#: describe.c:3585 +#: describe.c:3682 #, c-format msgid "Tablespace: \"%s\"" msgstr "テーブル空間: \"%s\"" #. translator: before this string there's an index description like #. '"foo_pkey" PRIMARY KEY, btree (a)' -#: describe.c:3597 +#: describe.c:3694 #, c-format msgid ", tablespace \"%s\"" msgstr "、テーブル空間\"%s\"" -#: describe.c:3670 +#: describe.c:3767 msgid "List of roles" msgstr "ロール一覧" -#: describe.c:3672 describe.c:3840 +#: describe.c:3769 describe.c:3937 msgid "Role name" msgstr "ロール名" -#: describe.c:3673 +#: describe.c:3770 msgid "Attributes" msgstr "属性" -#: describe.c:3684 +#: describe.c:3781 msgid "Superuser" msgstr "スーパーユーザー" -#: describe.c:3687 +#: describe.c:3784 msgid "No inheritance" msgstr "継承なし" -#: describe.c:3690 +#: describe.c:3787 msgid "Create role" msgstr "ロール作成可" -#: describe.c:3693 +#: describe.c:3790 msgid "Create DB" msgstr "DB作成可" -#: describe.c:3696 +#: describe.c:3793 msgid "Cannot login" msgstr "ログインできません" -#: describe.c:3699 +#: describe.c:3796 msgid "Replication" msgstr "レプリケーション可" -#: describe.c:3703 +#: describe.c:3800 msgid "Bypass RLS" msgstr "RLS のバイパス" -#: describe.c:3712 +#: describe.c:3809 msgid "No connections" msgstr "接続なし" -#: describe.c:3714 +#: describe.c:3811 #, c-format msgid "%d connection" msgid_plural "%d connections" msgstr[0] "%d 個の接続" -#: describe.c:3724 +#: describe.c:3821 msgid "Password valid until " msgstr "パスワードの有効期限 " -#: describe.c:3775 +#: describe.c:3872 msgid "Role" msgstr "ロール" -#: describe.c:3776 -msgid "Database" -msgstr "データベース" - -#: describe.c:3777 +#: describe.c:3874 msgid "Settings" msgstr "設定" -#: describe.c:3801 +#: describe.c:3898 #, c-format msgid "Did not find any settings for role \"%s\" and database \"%s\"." msgstr "ロール\"%s\"とデータベース\"%s\"の設定が見つかりませんでした。" -#: describe.c:3804 +#: describe.c:3901 #, c-format msgid "Did not find any settings for role \"%s\"." msgstr "ロール\"%s\"の設定が見つかりませんでした。" -#: describe.c:3807 +#: describe.c:3904 #, c-format msgid "Did not find any settings." msgstr "設定が見つかりませんでした。" -#: describe.c:3811 +#: describe.c:3908 msgid "List of settings" msgstr "設定一覧" -#: describe.c:3841 +#: describe.c:3938 msgid "Member of" msgstr "所属グループ" -#: describe.c:3858 +#: describe.c:3955 msgid "Grantor" msgstr "付与者" -#: describe.c:3884 +#: describe.c:3981 msgid "List of role grants" msgstr "ロール権限付与一覧" -#: describe.c:3950 +#: describe.c:4051 msgid "index" msgstr "インデックス" -#: describe.c:3952 +#: describe.c:4053 msgid "TOAST table" msgstr "TOAST テーブル" -#: describe.c:3955 describe.c:4166 +#: describe.c:4056 describe.c:4320 msgid "partitioned index" msgstr "パーティションインデックス" -#: describe.c:3975 +#: describe.c:4080 msgid "permanent" msgstr "永続" -#: describe.c:3976 +#: describe.c:4081 msgid "temporary" msgstr "一時" -#: describe.c:3977 +#: describe.c:4082 msgid "unlogged" msgstr "ログなし" -#: describe.c:3978 +#: describe.c:4083 msgid "Persistence" msgstr "永続性" -#: describe.c:3994 +#: describe.c:4099 describe.c:4343 msgid "Access method" msgstr "アクセスメソッド" -#: describe.c:4079 +#: describe.c:4179 +#, c-format +msgid "Did not find any relations named \"%s\"." +msgstr "\"%s\"という名前のリレーションは見つかりませんでした。" + +#: describe.c:4182 +#, c-format +msgid "Did not find any tables named \"%s\"." +msgstr "\"%s\"という名前のテーブルは見つかりませんでした。" + +#: describe.c:4185 +#, c-format +msgid "Did not find any indexes named \"%s\"." +msgstr "\"%s\"という名前のインデックスは見つかりませんでした。" + +#: describe.c:4188 +#, c-format +msgid "Did not find any views named \"%s\"." +msgstr "\"%s\"という名前のビューは見つかりませんでした。" + +#: describe.c:4191 +#, c-format +msgid "Did not find any materialized views named \"%s\"." +msgstr "\"%s\"という名前の実体化ビューは見つかりませんでした。" + +#: describe.c:4194 +#, c-format +msgid "Did not find any sequences named \"%s\"." +msgstr "\"%s\"という名前のシーケンスは見つかりませんでした。" + +#: describe.c:4197 +#, c-format +msgid "Did not find any foreign tables named \"%s\"." +msgstr "\"%s\"という名前の外部テーブルは見つかりませんでした。" + +#: describe.c:4208 +#, c-format +msgid "Did not find any tables." +msgstr "テーブルが見つかりませんでした。" + +#: describe.c:4210 +#, c-format +msgid "Did not find any indexes." +msgstr "インデックスが見つかりませんでした。" + +#: describe.c:4212 +#, c-format +msgid "Did not find any views." +msgstr "ビューが見つかりませんでした。" + +#: describe.c:4214 +#, c-format +msgid "Did not find any materialized views." +msgstr "実体化ビューが見つかりませんでした。" + +#: describe.c:4216 +#, c-format +msgid "Did not find any sequences." +msgstr "シーケンスが見つかりませんでした。" + +#: describe.c:4218 +#, c-format +msgid "Did not find any foreign tables." +msgstr "外部テーブルが見つかりませんでした。" + +#: describe.c:4226 msgid "List of relations" msgstr "リレーション一覧" -#: describe.c:4127 +#: describe.c:4227 +msgid "List of tables" +msgstr "テーブル一覧" + +#: describe.c:4228 +msgid "List of indexes" +msgstr "インデックス一覧" + +#: describe.c:4229 +msgid "List of views" +msgstr "ビュー一覧" + +#: describe.c:4230 +msgid "List of materialized views" +msgstr "実体化ビュー一覧" + +#: describe.c:4231 +msgid "List of sequences" +msgstr "シーケンス一覧" + +#: describe.c:4232 describe.c:6162 +msgid "List of foreign tables" +msgstr "外部テーブル一覧" + +#: describe.c:4281 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "このサーバー(バージョン%s)は宣言的テーブルパーティショニングをサポートしていません。" -#: describe.c:4138 +#: describe.c:4292 msgid "List of partitioned indexes" msgstr "パーティションインデックスの一覧" -#: describe.c:4140 +#: describe.c:4294 msgid "List of partitioned tables" msgstr "パーティションテーブルの一覧" -#: describe.c:4144 +#: describe.c:4298 msgid "List of partitioned relations" msgstr "パーティションリレーションの一覧" -#: describe.c:4175 +#: describe.c:4329 msgid "Parent name" msgstr "親の名前" -#: describe.c:4188 +#: describe.c:4349 msgid "Leaf partition size" msgstr "末端パーティションのサイズ" -#: describe.c:4191 describe.c:4197 +#: describe.c:4352 describe.c:4358 msgid "Total size" msgstr "トータルサイズ" -#: describe.c:4321 +#: describe.c:4485 msgid "Trusted" msgstr "信頼済み" -#: describe.c:4330 +#: describe.c:4494 msgid "Internal language" msgstr "内部言語" -#: describe.c:4331 +#: describe.c:4495 msgid "Call handler" msgstr "呼び出しハンドラー" -#: describe.c:4332 describe.c:5743 +#: describe.c:4496 describe.c:5918 msgid "Validator" msgstr "バリデーター" -#: describe.c:4333 +#: describe.c:4497 msgid "Inline handler" msgstr "インラインハンドラー" -#: describe.c:4367 +#: describe.c:4531 msgid "List of languages" msgstr "手続き言語一覧" -#: describe.c:4408 +#: describe.c:4572 msgid "Check" msgstr "CHECK制約" -#: describe.c:4451 +#: describe.c:4615 msgid "List of domains" msgstr "ドメイン一覧" -#: describe.c:4485 +#: describe.c:4649 msgid "Source" msgstr "変換元" -#: describe.c:4486 +#: describe.c:4650 msgid "Destination" msgstr "変換先" -#: describe.c:4488 describe.c:6712 +#: describe.c:4652 describe.c:6928 msgid "Default?" msgstr "デフォルト?" -#: describe.c:4529 +#: describe.c:4693 msgid "List of conversions" msgstr "符号化方式一覧" -#: describe.c:4557 -msgid "Parameter" -msgstr "パラメータ" - -#: describe.c:4558 -msgid "Value" -msgstr "値" - -#: describe.c:4565 +#: describe.c:4729 msgid "Context" msgstr "コンテクスト" -#: describe.c:4597 +#: describe.c:4761 msgid "List of configuration parameters" msgstr "設定パラメータの一覧" -#: describe.c:4599 +#: describe.c:4763 msgid "List of non-default configuration parameters" msgstr "非デフォルトの設定パラメータの一覧" -#: describe.c:4626 +#: describe.c:4790 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "このサーバー(バージョン%s)はイベントトリガーをサポートしていません。" -#: describe.c:4646 +#: describe.c:4810 msgid "Event" msgstr "イベント" -#: describe.c:4648 +#: describe.c:4812 msgid "enabled" msgstr "有効" -#: describe.c:4649 +#: describe.c:4813 msgid "replica" msgstr "レプリカ" -#: describe.c:4650 +#: describe.c:4814 msgid "always" msgstr "常時" -#: describe.c:4651 +#: describe.c:4815 msgid "disabled" msgstr "無効" -#: describe.c:4652 describe.c:6553 +#: describe.c:4816 describe.c:6769 msgid "Enabled" msgstr "有効状態" -#: describe.c:4654 +#: describe.c:4818 msgid "Tags" msgstr "タグ" -#: describe.c:4677 +#: describe.c:4841 msgid "List of event triggers" msgstr "イベントトリガー一覧" -#: describe.c:4704 +#: describe.c:4868 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "このサーバー(バージョン%s)は拡張統計情報をサポートしていません。" -#: describe.c:4741 +#: describe.c:4905 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4742 +#: describe.c:4906 msgid "Dependencies" msgstr "Dependencies" -#: describe.c:4752 +#: describe.c:4916 msgid "MCV" msgstr "MCV" -#: describe.c:4775 +#: describe.c:4939 msgid "List of extended statistics" msgstr "拡張統計情報の一覧" -#: describe.c:4802 +#: describe.c:4966 msgid "Source type" msgstr "変換元の型" -#: describe.c:4803 +#: describe.c:4967 msgid "Target type" msgstr "変換先の型" -#: describe.c:4827 +#: describe.c:4991 msgid "in assignment" msgstr "代入時のみ" -#: describe.c:4829 +#: describe.c:4993 msgid "Implicit?" msgstr "暗黙的に適用 ?" -#: describe.c:4887 +#: describe.c:5057 msgid "List of casts" msgstr "キャスト一覧" -#: describe.c:4927 describe.c:4931 +#: describe.c:5102 describe.c:5106 msgid "Provider" msgstr "プロバイダー" -#: describe.c:4965 describe.c:4970 +#: describe.c:5140 describe.c:5145 msgid "Deterministic?" msgstr "確定的?" -#: describe.c:5009 +#: describe.c:5184 msgid "List of collations" msgstr "照合順序一覧" -#: describe.c:5070 +#: describe.c:5245 msgid "List of schemas" msgstr "スキーマ一覧" -#: describe.c:5186 +#: describe.c:5361 msgid "List of text search parsers" msgstr "テキスト検索用パーサ一覧" -#: describe.c:5236 +#: describe.c:5411 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "テキスト検索用パーサ\"%s\"が見つかりませんでした。" -#: describe.c:5239 +#: describe.c:5414 #, c-format msgid "Did not find any text search parsers." msgstr "テキスト検索パーサが見つかりませんでした。" -#: describe.c:5314 +#: describe.c:5489 msgid "Start parse" msgstr "パース開始" -#: describe.c:5315 +#: describe.c:5490 msgid "Method" msgstr "メソッド" -#: describe.c:5319 +#: describe.c:5494 msgid "Get next token" msgstr "次のトークンを取得" -#: describe.c:5321 +#: describe.c:5496 msgid "End parse" msgstr "パース終了" -#: describe.c:5323 +#: describe.c:5498 msgid "Get headline" msgstr "見出しを取得" -#: describe.c:5325 +#: describe.c:5500 msgid "Get token types" msgstr "トークンタイプを取得" -#: describe.c:5335 +#: describe.c:5510 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "テキスト検索パーサ\"%s.%s\"" -#: describe.c:5338 +#: describe.c:5513 #, c-format msgid "Text search parser \"%s\"" msgstr "テキスト検索パーサ\"%s\"" -#: describe.c:5357 +#: describe.c:5532 msgid "Token name" msgstr "トークン名" -#: describe.c:5370 +#: describe.c:5545 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "パーサ\"%s.%s\"のトークンタイプ" -#: describe.c:5373 +#: describe.c:5548 #, c-format msgid "Token types for parser \"%s\"" msgstr "パーサ\"%s\"のトークンタイプ" -#: describe.c:5417 +#: describe.c:5592 msgid "Template" msgstr "テンプレート" -#: describe.c:5418 +#: describe.c:5593 msgid "Init options" msgstr "初期化オプション" -#: describe.c:5444 +#: describe.c:5619 msgid "List of text search dictionaries" msgstr "テキスト検索用辞書一覧" -#: describe.c:5477 +#: describe.c:5652 msgid "Init" msgstr "初期化" -#: describe.c:5478 +#: describe.c:5653 msgid "Lexize" msgstr "Lex 処理" -#: describe.c:5509 +#: describe.c:5684 msgid "List of text search templates" msgstr "テキスト検索テンプレート一覧" -#: describe.c:5563 +#: describe.c:5738 msgid "List of text search configurations" msgstr "テキスト検索設定一覧" -#: describe.c:5614 +#: describe.c:5789 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "テキスト検索用設定\"%s\"が見つかりませんでした。" -#: describe.c:5617 +#: describe.c:5792 #, c-format msgid "Did not find any text search configurations." msgstr "テキスト検索設定が見つかりませんでした。" -#: describe.c:5683 +#: describe.c:5858 msgid "Token" msgstr "トークン" -#: describe.c:5684 +#: describe.c:5859 msgid "Dictionaries" msgstr "辞書" -#: describe.c:5695 +#: describe.c:5870 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "テキスト検索設定\"%s.%s\"" -#: describe.c:5698 +#: describe.c:5873 #, c-format msgid "Text search configuration \"%s\"" msgstr "テキスト検索設定\"%s\"" -#: describe.c:5702 +#: describe.c:5877 #, c-format msgid "" "\n" @@ -2238,7 +2437,7 @@ msgstr "" "\n" "パーサ: \"%s.%s\"" -#: describe.c:5705 +#: describe.c:5880 #, c-format msgid "" "\n" @@ -2247,273 +2446,277 @@ msgstr "" "\n" "パーサ: \"%s\"" -#: describe.c:5784 +#: describe.c:5959 msgid "List of foreign-data wrappers" msgstr "外部データラッパ一覧" -#: describe.c:5812 +#: describe.c:5987 msgid "Foreign-data wrapper" msgstr "外部データラッパ" -#: describe.c:5830 describe.c:6017 +#: describe.c:6005 describe.c:6194 msgid "Version" msgstr "バージョン" -#: describe.c:5860 +#: describe.c:6035 msgid "List of foreign servers" msgstr "外部サーバー一覧" -#: describe.c:5885 describe.c:5943 +#: describe.c:6060 describe.c:6118 msgid "Server" msgstr "サーバー" -#: describe.c:5886 +#: describe.c:6061 msgid "User name" msgstr "ユーザー名" -#: describe.c:5915 +#: describe.c:6090 msgid "List of user mappings" msgstr "ユーザーマッピング一覧" -#: describe.c:5987 -msgid "List of foreign tables" -msgstr "外部テーブル一覧" +#: describe.c:6195 +msgid "Default version" +msgstr "デフォルトバージョン" -#: describe.c:6038 +#: describe.c:6216 msgid "List of installed extensions" msgstr "インストール済みの拡張一覧" -#: describe.c:6086 +#: describe.c:6264 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "\"%s\"という名前の機能拡張が見つかりませんでした。" -#: describe.c:6089 +#: describe.c:6267 #, c-format msgid "Did not find any extensions." msgstr "機能拡張が見つかりませんでした。" -#: describe.c:6133 +#: describe.c:6311 msgid "Object description" msgstr "オブジェクトの説明" -#: describe.c:6142 +#: describe.c:6320 #, c-format msgid "Objects in extension \"%s\"" msgstr "機能拡張\"%s\"内のオブジェクト" -#: describe.c:6183 +#: describe.c:6361 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "修飾名が不適切です(ドット区切りの名前が多すぎます): %s" -#: describe.c:6197 +#: describe.c:6375 #, c-format msgid "cross-database references are not implemented: %s" msgstr "データベース間の参照は実装されていません: %s" -#: describe.c:6228 describe.c:6354 +#: describe.c:6406 describe.c:6542 #, c-format msgid "The server (version %s) does not support publications." msgstr "このサーバー(バージョン%s)はパブリケーションをサポートしていません。" -#: describe.c:6245 describe.c:6432 +#: describe.c:6423 describe.c:6644 msgid "All tables" msgstr "全テーブル" -#: describe.c:6246 describe.c:6433 +#: describe.c:6424 describe.c:6645 msgid "Inserts" msgstr "Insert文" -#: describe.c:6247 describe.c:6434 +#: describe.c:6425 describe.c:6646 msgid "Updates" msgstr "Update文" -#: describe.c:6248 describe.c:6435 +#: describe.c:6426 describe.c:6647 msgid "Deletes" msgstr "Delete文" -#: describe.c:6252 describe.c:6437 +#: describe.c:6430 describe.c:6649 msgid "Truncates" msgstr "Truncate文" -#: describe.c:6256 describe.c:6439 +#: describe.c:6439 describe.c:6573 describe.c:6651 +msgid "Generated columns" +msgstr "生成列" + +#: describe.c:6443 describe.c:6653 msgid "Via root" msgstr "最上位パーティションテーブル経由" -#: describe.c:6277 +#: describe.c:6464 msgid "List of publications" msgstr "パブリケーション一覧" -#: describe.c:6401 +#: describe.c:6611 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "\"%s\"という名前のパブリケーションが見つかりませんでした。" -#: describe.c:6404 +#: describe.c:6614 #, c-format msgid "Did not find any publications." msgstr "パブリケーションが見つかりませんでした。" -#: describe.c:6428 +#: describe.c:6640 #, c-format msgid "Publication %s" msgstr "パブリケーション %s" -#: describe.c:6481 +#: describe.c:6697 msgid "Tables:" msgstr "テーブル:" -#: describe.c:6493 +#: describe.c:6709 msgid "Tables from schemas:" msgstr "以下のスキーマ内のテーブル:" -#: describe.c:6538 +#: describe.c:6754 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "このサーバー(バージョン%s)はサブスクリプションをサポートしていません。" -#: describe.c:6554 +#: describe.c:6770 msgid "Publication" msgstr "パブリケーション" -#: describe.c:6563 +#: describe.c:6779 msgid "Binary" msgstr "バイナリ" -#: describe.c:6572 describe.c:6576 +#: describe.c:6788 describe.c:6792 msgid "Streaming" msgstr "ストリーミング" -#: describe.c:6584 +#: describe.c:6800 msgid "Two-phase commit" msgstr "2相コミット" -#: describe.c:6585 +#: describe.c:6801 msgid "Disable on error" msgstr "エラー時無効化" -#: describe.c:6592 +#: describe.c:6808 msgid "Origin" msgstr "起点" -#: describe.c:6593 +#: describe.c:6809 msgid "Password required" msgstr "パスワード必須" -#: describe.c:6594 +#: describe.c:6810 msgid "Run as owner?" msgstr "所有者として実行?" -#: describe.c:6599 +#: describe.c:6815 msgid "Failover" msgstr "フェイルオーバー" -#: describe.c:6604 +#: describe.c:6820 msgid "Synchronous commit" msgstr "同期コミット" -#: describe.c:6605 +#: describe.c:6821 msgid "Conninfo" msgstr "接続情報" -#: describe.c:6611 +#: describe.c:6827 msgid "Skip LSN" msgstr "スキップLSN" -#: describe.c:6637 +#: describe.c:6853 msgid "List of subscriptions" msgstr "サブスクリプション一覧" -#: describe.c:6666 +#: describe.c:6882 msgid "(none)" msgstr "(権限なし)" -#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 +#: describe.c:6922 describe.c:7017 describe.c:7109 describe.c:7212 msgid "AM" msgstr "AM" -#: describe.c:6707 +#: describe.c:6923 msgid "Input type" msgstr "入力の型" -#: describe.c:6708 +#: describe.c:6924 msgid "Storage type" msgstr "ストレージタイプ" -#: describe.c:6709 +#: describe.c:6925 msgid "Operator class" msgstr "演算子クラス" -#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 +#: describe.c:6937 describe.c:7018 describe.c:7110 describe.c:7213 msgid "Operator family" msgstr "演算子族" -#: describe.c:6756 +#: describe.c:6972 msgid "List of operator classes" msgstr "演算子クラス一覧" -#: describe.c:6803 +#: describe.c:7019 msgid "Applicable types" msgstr "適用可能型" -#: describe.c:6844 +#: describe.c:7060 msgid "List of operator families" msgstr "演算子族一覧" -#: describe.c:6895 +#: describe.c:7111 msgid "Operator" msgstr "演算子" -#: describe.c:6896 +#: describe.c:7112 msgid "Strategy" msgstr "ストラテジ" -#: describe.c:6897 +#: describe.c:7113 msgid "ordering" msgstr "順序付け" -#: describe.c:6898 +#: describe.c:7114 msgid "search" msgstr "検索" -#: describe.c:6899 +#: describe.c:7115 msgid "Purpose" msgstr "目的" -#: describe.c:6904 +#: describe.c:7124 msgid "Sort opfamily" msgstr "ソート演算子族" -#: describe.c:6942 +#: describe.c:7167 msgid "List of operators of operator families" msgstr "演算子族の演算子一覧" -#: describe.c:6989 +#: describe.c:7214 msgid "Registered left type" msgstr "登録左辺型" -#: describe.c:6990 +#: describe.c:7215 msgid "Registered right type" msgstr "登録右辺型" -#: describe.c:6991 +#: describe.c:7216 msgid "Number" msgstr "番号" -#: describe.c:7034 +#: describe.c:7259 msgid "List of support functions of operator families" msgstr "演算子族のサポート関数一覧" -#: describe.c:7065 +#: describe.c:7290 msgid "ID" msgstr "ID" -#: describe.c:7085 +#: describe.c:7310 msgid "Large objects" msgstr "ラージ オブジェクト" -#: help.c:63 +#: help.c:60 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2521,11 +2724,11 @@ msgstr "" "psql は PostgreSQL の対話型ターミナルです。\n" "\n" -#: help.c:64 help.c:372 help.c:456 help.c:499 +#: help.c:61 help.c:381 help.c:467 help.c:513 msgid "Usage:\n" msgstr "使い方:\n" -#: help.c:65 +#: help.c:62 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2533,27 +2736,27 @@ msgstr "" " psql [オプション]... [データベース名 [ユーザー名]]\n" "\n" -#: help.c:67 +#: help.c:64 msgid "General options:\n" msgstr "一般的なオプション:\n" -#: help.c:68 +#: help.c:65 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr " -c, --command=コマンド 単一の(SQLまたは内部)コマンドを一つだけ実行して終了\n" -#: help.c:69 +#: help.c:66 msgid " -d, --dbname=DBNAME database name to connect to\n" -msgstr " -d, --dbname=DBNAME 接続先データベース名\n" +msgstr " -d, --dbname=DBNAME 接続先データベース名\n" -#: help.c:70 +#: help.c:67 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=FILENAME ファイルからコマンドを読み込んで実行後、終了\n" -#: help.c:71 +#: help.c:68 msgid " -l, --list list available databases, then exit\n" msgstr " -l(エル), --list 使用可能なデータベース一覧を表示して終了\n" -#: help.c:72 +#: help.c:69 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2563,15 +2766,15 @@ msgstr "" " psql 変数 '名前' に '値' をセット\n" " (例: -v ON_ERROR_STOP=1)\n" -#: help.c:75 +#: help.c:72 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: help.c:76 +#: help.c:73 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc 初期化ファイル (~/.psqlrc) を読み込まない\n" -#: help.c:77 +#: help.c:74 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" @@ -2579,19 +2782,19 @@ msgstr "" " -1 (数字の1), --single-transaction\n" " (対話形式でない場合)単一のトランザクションとして実行\n" -#: help.c:79 +#: help.c:76 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=options] このヘルプを表示して終了\n" -#: help.c:80 +#: help.c:77 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands バックスラッシュコマンドの一覧を表示して終了\n" -#: help.c:81 +#: help.c:78 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables 特殊変数の一覧を表示して終了\n" -#: help.c:83 +#: help.c:80 msgid "" "\n" "Input and output options:\n" @@ -2599,47 +2802,47 @@ msgstr "" "\n" "入出力オプション:\n" -#: help.c:84 +#: help.c:81 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all スクリプトから読み込んだ入力をすべて表示\n" -#: help.c:85 +#: help.c:82 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors 失敗したコマンドを表示\n" -#: help.c:86 +#: help.c:83 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries サーバーへ送信したコマンドを表示\n" -#: help.c:87 +#: help.c:84 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden 内部コマンドが生成した問い合わせを表示\n" -#: help.c:88 +#: help.c:85 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=FILENAME セッションログをファイルに書き込む\n" -#: help.c:89 +#: help.c:86 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr " -n, --no-readline 拡張コマンドライン編集機能(readline)を無効にする\n" -#: help.c:90 +#: help.c:87 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=FILENAME 問い合わせの結果をファイル (または |パイプ)に送る\n" -#: help.c:91 +#: help.c:88 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr " -q, --quiet 静かに実行 (メッセージなしで、問い合わせの出力のみ)\n" -#: help.c:92 +#: help.c:89 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step シングルステップモード (各問い合わせごとに確認)\n" -#: help.c:93 +#: help.c:90 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr " -S, --single-line 単一行モード (行末でSQLコマンドを終端)\n" -#: help.c:95 +#: help.c:92 msgid "" "\n" "Output format options:\n" @@ -2647,15 +2850,15 @@ msgstr "" "\n" "出力フォーマットのオプション\n" -#: help.c:96 +#: help.c:93 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align 桁揃えなしのテーブル出力モード\n" -#: help.c:97 +#: help.c:94 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv CSV(カンマ区切り)テーブル出力モード\n" -#: help.c:98 +#: help.c:95 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2665,17 +2868,17 @@ msgstr "" " 桁揃えなし出力時のフィールド区切り文字\n" " (デフォルト: \"%s\")\n" -#: help.c:101 +#: help.c:98 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html HTML テーブル出力モード\n" -#: help.c:102 +#: help.c:99 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr "" " -P, --pset=変数[=値] 表示オプション '変数' を '値' にセット\n" " (\\pset コマンドを参照)\n" -#: help.c:103 +#: help.c:100 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" @@ -2684,19 +2887,19 @@ msgstr "" " 桁揃えなし出力におけるレコード区切り文字\n" " (デフォルト: 改行)\n" -#: help.c:105 +#: help.c:102 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only 行のみを表示\n" -#: help.c:106 +#: help.c:103 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr " -T, --table-attr=TEXT HTMLテーブルのタグ属性をセット (width, border等)\n" -#: help.c:107 +#: help.c:104 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded 拡張テーブル出力に切り替える\n" -#: help.c:108 +#: help.c:105 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" @@ -2704,7 +2907,7 @@ msgstr "" " -z, --field-separator-zero\n" " 桁揃えなし出力のフィールド区切りをバイト値の0に設定\n" -#: help.c:110 +#: help.c:107 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" @@ -2712,7 +2915,7 @@ msgstr "" " -0, --record-separator-zero\n" " 桁揃えなし出力のレコード区切りをバイト値の0に設定\n" -#: help.c:113 +#: help.c:110 msgid "" "\n" "Connection options:\n" @@ -2720,29 +2923,29 @@ msgstr "" "\n" "接続オプション:\n" -#: help.c:114 +#: help.c:111 msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME データベースサーバーのホストまたはソケット\n" " ディレクトリ\n" -#: help.c:115 +#: help.c:112 msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT データベースサーバーのポート番号\n" -#: help.c:116 +#: help.c:113 msgid " -U, --username=USERNAME database user name\n" msgstr " -U, --username=USERNAME データベースのユーザー名\n" -#: help.c:117 +#: help.c:114 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password パスワード入力を要求しない\n" -#: help.c:118 +#: help.c:115 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password パスワードプロンプトの強制表示(本来は自動的に表示)\n" -#: help.c:120 +#: help.c:117 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" @@ -2755,24 +2958,36 @@ msgstr "" "をタイプするか、PostgreSQLドキュメント中のpsqlのセクションを参照してください。\n" "\n" -#: help.c:123 +#: help.c:120 #, c-format msgid "Report bugs to <%s>.\n" msgstr "バグは<%s>に報告してください。\n" -#: help.c:124 +#: help.c:121 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: help.c:166 +#: help.c:163 msgid "General\n" msgstr "一般\n" -#: help.c:167 +#: help.c:164 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [PARAM]... 問い合わせパラメータを設定\n" +#: help.c:165 +msgid "" +" \\bind_named STMT_NAME [PARAM]...\n" +" set query parameters for an existing prepared statement\n" +msgstr "" +" \\bind_named STMT_NAME [PARAM]...\n" +" 既存の準備済みの文にパラメータを設定する\n" + +#: help.c:167 +msgid " \\close STMT_NAME close an existing prepared statement\n" +msgstr " \\close STMT_NAME 準備済みの文をクローズする\n" + #: help.c:168 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright PostgreSQL の使い方と配布条件を表示\n" @@ -2782,10 +2997,22 @@ msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n msgstr " \\crosstabview [列リスト] 問い合わせを実行し、結果をクロス表形式で出力\n" #: help.c:170 +msgid " \\endpipeline exit pipeline mode\n" +msgstr " \\endpipeline パイプラインモードを終了\n" + +#: help.c:171 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose 最後のエラーメッセージを最大の冗長性で表示\n" -#: help.c:171 +#: help.c:172 +msgid " \\flush push unsent data to the server\n" +msgstr " \\flush 未送信のデータをサーバーへ送信\n" + +#: help.c:173 +msgid " \\flushrequest send a flushrequest command\n" +msgstr " \\flushrequest flushrequestコマンドを送信\n" + +#: help.c:174 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2793,393 +3020,416 @@ msgstr "" " \\g [(OPTIONS)] [FILE] 問い合わせ実行 (結果はファイルまたは |パイプへ出力);\n" " 引数なしの\\gはセミコロンと同義\n" -#: help.c:173 +#: help.c:176 msgid " \\gdesc describe result of query, without executing it\n" -msgstr " \\gdesc 問い合わせを実行せずに結果の説明を行う\n" +msgstr " \\gdesc 問い合わせを実行せずに結果の形式を出力する\n" -#: help.c:174 +#: help.c:177 +msgid "" +" \\getresults [NUM_RES] read NUM_RES pending results. All pending results are\n" +" read if no argument is provided\n" +msgstr "" +" \\getresults [結果数] 指定した \"結果数\" 分の未取得の結果を読み取る。\n" +" 引数なしの場合、すべての未取得の結果を読み取る\n" + +#: help.c:179 msgid " \\gexec execute query, then execute each value in its result\n" msgstr " \\gexec 問い合わせを実行し、結果の中の個々の値を実行\n" -#: help.c:175 +#: help.c:180 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr " \\gset [PREFIX] 問い合わせを実行して結果を psql 変数に格納\n" -#: help.c:176 +#: help.c:181 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr " \\gx [ファイル名] \\g と同じ、ただし拡張出力モードを強制\n" -#: help.c:177 +#: help.c:182 +msgid " \\parse STMT_NAME create a prepared statement\n" +msgstr " \\parse STMT_NAME 準備済みの文を作成\n" + +#: help.c:183 msgid " \\q quit psql\n" msgstr " \\q psql を終了する\n" -#: help.c:178 +#: help.c:184 +msgid " \\sendpipeline send an extended query to an ongoing pipeline\n" +msgstr " \\sendpipeline 実行中のパイプラインに拡張問い合わせを送出\n" + +#: help.c:185 +msgid " \\startpipeline enter pipeline mode\n" +msgstr " \\startpipeline パイプラインモードを開始\n" + +#: help.c:186 +msgid " \\syncpipeline add a synchronisation point to an ongoing pipeline\n" +msgstr " \\syncpipeline 実行中のパイプラインに同期ポイントを追加\n" + +#: help.c:187 msgid "" " \\watch [[i=]SEC] [c=N] [m=MIN]\n" " execute query every SEC seconds, up to N times,\n" " stop if less than MIN rows are returned\n" msgstr "" " \\watch [[i=]SEC] [c=N] [m=MIN]\n" -" SEC秒ごとに最大N回まで分を実行する\n" -" 返却行数がMIN行より少ない場合には停止する\n" +" SEC秒ごとに最大N回まで分を実行。返却行数がMIN行より\n" +" 少ない場合には停止する\n" -#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 -#: help.c:303 help.c:316 help.c:325 +#: help.c:190 help.c:198 help.c:210 help.c:220 help.c:227 help.c:284 help.c:292 +#: help.c:312 help.c:325 help.c:334 msgid "\n" msgstr "\n" -#: help.c:183 +#: help.c:192 msgid "Help\n" msgstr "ヘルプ\n" -#: help.c:185 +#: help.c:194 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [コマンド] バックスラッシュコマンドのヘルプを表示\n" -#: help.c:186 +#: help.c:195 msgid " \\? options show help on psql command-line options\n" msgstr " \\? オプション psql のコマンドライン・オプションのヘルプを表示\n" -#: help.c:187 +#: help.c:196 msgid " \\? variables show help on special variables\n" msgstr " \\? 変数名 特殊変数のヘルプを表示\n" -#: help.c:188 +#: help.c:197 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr " \\h [名前] SQLコマンドの文法ヘルプの表示。* で全コマンドを表示\n" -#: help.c:191 +#: help.c:200 msgid "Query Buffer\n" msgstr "問い合わせバッファ\n" -#: help.c:192 +#: help.c:201 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr "" " \\e [ファイル] [行番号] 現在の問い合わせバッファ(やファイル)を外部エディタで\n" " 編集\n" -#: help.c:193 +#: help.c:202 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr " \\ef [関数名 [行番号]] 関数定義を外部エディタで編集\n" -#: help.c:194 +#: help.c:203 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr " \\ev [ビュー名 [行番号]] ビュー定義を外部エディタで編集\n" -#: help.c:195 +#: help.c:204 msgid " \\p show the contents of the query buffer\n" msgstr " \\p 問い合わせバッファの内容を表示\n" -#: help.c:196 +#: help.c:205 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r 問い合わせバッファをリセット(クリア)\n" -#: help.c:198 +#: help.c:207 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [ファイル] ヒストリを表示またはファイルに保存\n" -#: help.c:200 +#: help.c:209 msgid " \\w FILE write query buffer to file\n" msgstr " \\w ファイル 問い合わせバッファの内容をファイルに保存\n" -#: help.c:203 +#: help.c:212 msgid "Input/Output\n" msgstr "入出力\n" -#: help.c:204 +#: help.c:213 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr "" " \\copy ... クライアントホストに対し、データストリームを使って\n" " SQL COPYを実行\n" -#: help.c:205 +#: help.c:214 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [文字列] 文字列を標準出力に書き込む (-n で改行しない)\n" -#: help.c:206 +#: help.c:215 msgid " \\i FILE execute commands from file\n" msgstr " \\i ファイル ファイルからコマンドを読み込んで実行\n" -#: help.c:207 +#: help.c:216 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr "" " \\ir ファイル \\i と同じ。ただし現在のスクリプトの場所からの相対パス\n" " で指定\n" -#: help.c:208 +#: help.c:217 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [ファイル] 問い合わせ結果をすべてファイルまたは |パイプ へ送出\n" -#: help.c:209 +#: help.c:218 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr "" " \\qecho [-n] [文字列] 文字列を\\oで指定した出力ストリームに書き込む(-n で改行\n" " しない)\n" -#: help.c:210 +#: help.c:219 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr " \\warn [-n] [文字列] 文字列を標準エラー出力に書き込む (-n で改行しない)\n" -#: help.c:213 +#: help.c:222 msgid "Conditional\n" msgstr "条件分岐\n" -#: help.c:214 +#: help.c:223 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPR 条件分岐ブロックの開始\n" -#: help.c:215 +#: help.c:224 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif EXPR 現在の条件分岐ブロック内の選択肢\n" -#: help.c:216 +#: help.c:225 msgid " \\else final alternative within current conditional block\n" msgstr " \\else 現在の条件分岐ブロックにおける最後の選択肢\n" -#: help.c:217 +#: help.c:226 msgid " \\endif end conditional block\n" msgstr " \\endif 条件分岐ブロックの終了\n" -#: help.c:220 +#: help.c:229 msgid "Informational\n" msgstr "情報表示\n" -#: help.c:221 -msgid " (options: S = show system objects, + = additional detail)\n" -msgstr " (オプション:S = システムオブジェクトを表示, + = 詳細表示)\n" - -#: help.c:222 -msgid " \\d[S+] list tables, views, and sequences\n" -msgstr " \\d[S+] テーブル、ビュー、およびシーケンスの一覧を表示\n" - -#: help.c:223 -msgid " \\d[S+] NAME describe table, view, sequence, or index\n" -msgstr "" -" \\d[S+] 名前 テーブル、ビュー、シーケンス、またはインデックスの\n" -" 説明を表示\n" - -#: help.c:224 -msgid " \\da[S] [PATTERN] list aggregates\n" -msgstr " \\da[S] [パターン] 集約関数の一覧を表示\n" - -#: help.c:225 -msgid " \\dA[+] [PATTERN] list access methods\n" -msgstr " \\dA[+] [パターン] アクセスメソッドの一覧を表示\n" - -#: help.c:226 -msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" -msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] 演算子クラスの一覧を表示\n" - -#: help.c:227 -msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" -msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] 演算子族の一覧を表示\n" - -#: help.c:228 -msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" -msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] 演算子族の演算子の一覧を表示\n" - -#: help.c:229 -msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" -msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] 演算子族のサポート関数の一覧を表示\n" - #: help.c:230 -msgid " \\db[+] [PATTERN] list tablespaces\n" -msgstr " \\db[+] [パターン] テーブル空間の一覧を表示\n" +msgid " (options: S = show system objects, x = expanded mode, + = additional detail)\n" +msgstr " (オプション:S = システムオブジェクトを表示、x = 拡張モード、+ = 詳細表示)\n" #: help.c:231 -msgid " \\dc[S+] [PATTERN] list conversions\n" -msgstr " \\dc[S+] [パターン] 符号化方式間の変換の一覧を表示\n" +msgid " \\d[Sx+] list tables, views, and sequences\n" +msgstr " \\d[Sx+] テーブル、ビュー、およびシーケンスの一覧を表示\n" #: help.c:232 -msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" -msgstr " \\dconfig[+] [PATTERN] 設定パラメータの一覧を表示\n" +msgid " \\d[S+] NAME describe table, view, sequence, or index\n" +msgstr "" +" \\d[S+] 名前 テーブル、ビュー、シーケンス、またはインデックスの\n" +" 説明を表示\n" #: help.c:233 -msgid " \\dC[+] [PATTERN] list casts\n" -msgstr " \\dC[+] [パターン] キャストの一覧を表示します。\n" +msgid " \\da[Sx] [PATTERN] list aggregates\n" +msgstr " \\da[Sx] [パターン] 集約関数の一覧を表示\n" #: help.c:234 -msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" -msgstr " \\dd[S] [パターン] 他では表示されないオブジェクトの説明を表示\n" +msgid " \\dA[x+] [PATTERN] list access methods\n" +msgstr " \\dA[x+] [パターン] アクセスメソッドの一覧を表示\n" #: help.c:235 -msgid " \\dD[S+] [PATTERN] list domains\n" -msgstr " \\dD[S+] [パターン] ドメインの一覧を表示\n" +msgid " \\dAc[x+] [AMPTRN [TYPEPTRN]] list operator classes\n" +msgstr " \\dAc[x+] [AMパターン [型パターン]] 演算子クラスの一覧を表示\n" #: help.c:236 -msgid " \\ddp [PATTERN] list default privileges\n" -msgstr " \\ddp [パターン] デフォルト権限の一覧を表示\n" +msgid " \\dAf[x+] [AMPTRN [TYPEPTRN]] list operator families\n" +msgstr " \\dAf[x+] [AMパターン [型パターン]] 演算子族の一覧を表示\n" #: help.c:237 -msgid " \\dE[S+] [PATTERN] list foreign tables\n" -msgstr " \\dE[S+] [パターン] 外部テーブルの一覧を表示\n" +msgid " \\dAo[x+] [AMPTRN [OPFPTRN]] list operators of operator families\n" +msgstr " \\dAo[x+] [AMパターン [型パターン]] 演算子族の演算子の一覧を表示\n" #: help.c:238 -msgid " \\des[+] [PATTERN] list foreign servers\n" -msgstr " \\des[+] [パターン] 外部サーバーの一覧を表示\n" +msgid " \\dAp[x+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" +msgstr " \\dAp[x+] [AMパターン [型パターン]] 演算子族のサポート関数の一覧を表示\n" #: help.c:239 -msgid " \\det[+] [PATTERN] list foreign tables\n" -msgstr " \\det[+] [パターン] 外部テーブルの一覧を表示\n" +msgid " \\db[x+] [PATTERN] list tablespaces\n" +msgstr " \\db[x+] [パターン] テーブル空間の一覧を表示\n" #: help.c:240 -msgid " \\deu[+] [PATTERN] list user mappings\n" -msgstr " \\deu[+] [パターン] ユーザーマッピングの一覧を表示\n" +msgid " \\dc[Sx+] [PATTERN] list conversions\n" +msgstr " \\dc[Sx+] [パターン] 符号化方式間の変換の一覧を表示\n" #: help.c:241 -msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" -msgstr " \\dew[+] [パターン] 外部データラッパの一覧を表示\n" +msgid " \\dconfig[x+] [PATTERN] list configuration parameters\n" +msgstr " \\dconfig[x+] [パターン] 設定パラメータの一覧を表示\n" #: help.c:242 -msgid "" -" \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" -" list [only agg/normal/procedure/trigger/window] functions\n" -msgstr "" -" \\df[anptw][S+] [関数パターン [型パターン ...]]\n" -" [集約/通常/プロシージャ/トリガー/ウィンドウ]\n" -" 関数のみの一覧を表示\n" +msgid " \\dC[x+] [PATTERN] list casts\n" +msgstr " \\dC[x+] [パターン] キャストの一覧を表示します。\n" + +#: help.c:243 +msgid " \\dd[Sx] [PATTERN] show object descriptions not displayed elsewhere\n" +msgstr " \\dd[Sx] [パターン] 他では表示されないオブジェクトの説明を表示\n" #: help.c:244 -msgid " \\dF[+] [PATTERN] list text search configurations\n" -msgstr " \\dF[+] [パターン] テキスト検索設定の一覧を表示\n" +msgid " \\dD[Sx+] [PATTERN] list domains\n" +msgstr " \\dD[Sx+] [パターン] ドメインの一覧を表示\n" #: help.c:245 -msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" -msgstr " \\dFd[+] [パターン] テキスト検索辞書の一覧を表示\n" +msgid " \\ddp[x] [PATTERN] list default privileges\n" +msgstr " \\ddp[x] [パターン] デフォルト権限の一覧を表示\n" #: help.c:246 -msgid " \\dFp[+] [PATTERN] list text search parsers\n" -msgstr " \\dFp[+] [パターン] テキスト検索パーサの一覧を表示\n" +msgid " \\dE[Sx+] [PATTERN] list foreign tables\n" +msgstr " \\dE[Sx+] [パターン] 外部テーブルの一覧を表示\n" #: help.c:247 -msgid " \\dFt[+] [PATTERN] list text search templates\n" -msgstr " \\dFt[+] [パターン] テキスト検索テンプレートの一覧を表示\n" +msgid " \\des[x+] [PATTERN] list foreign servers\n" +msgstr " \\des[x+] [パターン] 外部サーバーの一覧を表示\n" #: help.c:248 -msgid " \\dg[S+] [PATTERN] list roles\n" -msgstr " \\dg[S+] [パターン] ロールの一覧を表示\n" +msgid " \\det[x+] [PATTERN] list foreign tables\n" +msgstr " \\det[x+] [パターン] 外部テーブルの一覧を表示\n" #: help.c:249 -msgid " \\di[S+] [PATTERN] list indexes\n" -msgstr " \\di[S+] [パターン] インデックスの一覧を表示\n" +msgid " \\deu[x+] [PATTERN] list user mappings\n" +msgstr " \\deu[x+] [パターン] ユーザーマッピングの一覧を表示\n" #: help.c:250 -msgid " \\dl[+] list large objects, same as \\lo_list\n" -msgstr " \\dl[+] ラージオブジェクトの一覧を表示、\\lo_list と同じ\n" +msgid " \\dew[x+] [PATTERN] list foreign-data wrappers\n" +msgstr " \\dew[x+] [パターン] 外部データラッパの一覧を表示\n" #: help.c:251 -msgid " \\dL[S+] [PATTERN] list procedural languages\n" -msgstr " \\dL[S+] [パターン] 手続き言語の一覧を表示\n" - -#: help.c:252 -msgid " \\dm[S+] [PATTERN] list materialized views\n" -msgstr " \\dm[S+] [パターン] 実体化ビューの一覧を表示\n" +msgid "" +" \\df[anptw][Sx+] [FUNCPTRN [TYPEPTRN ...]]\n" +" list [only agg/normal/procedure/trigger/window] functions\n" +msgstr "" +" \\df[anptw][Sx+] [関数パターン [型パターン ...]]\n" +" [集約/通常/プロシージャ/トリガー/ウィンドウ]\n" +" 関数のみの一覧を表示\n" #: help.c:253 -msgid " \\dn[S+] [PATTERN] list schemas\n" -msgstr " \\dn[S+] [パターン] スキーマの一覧を表示\n" +msgid " \\dF[x+] [PATTERN] list text search configurations\n" +msgstr " \\dF[x+] [パターン] テキスト検索設定の一覧を表示\n" #: help.c:254 -msgid "" -" \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" -" list operators\n" -msgstr "" -" \\do[S+] [演算子パターン [型パターン [型パターン]]]\n" -" 演算子の一覧を表示\n" +msgid " \\dFd[x+] [PATTERN] list text search dictionaries\n" +msgstr " \\dFd[x+] [パターン] テキスト検索辞書の一覧を表示\n" + +#: help.c:255 +msgid " \\dFp[x+] [PATTERN] list text search parsers\n" +msgstr " \\dFp[x+] [パターン] テキスト検索パーサの一覧を表示\n" #: help.c:256 -msgid " \\dO[S+] [PATTERN] list collations\n" -msgstr " \\dO[S+] [パターン] 照合順序の一覧を表示\n" +msgid " \\dFt[x+] [PATTERN] list text search templates\n" +msgstr " \\dFt[x+] [パターン] テキスト検索テンプレートの一覧を表示\n" #: help.c:257 -msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" -msgstr " \\dp[S] [パターン] テーブル、ビュー、シーケンスのアクセス権の一覧を表示\n" +msgid " \\dg[Sx+] [PATTERN] list roles\n" +msgstr " \\dg[Sx+] [パターン] ロールの一覧を表示\n" #: help.c:258 -msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" -msgstr "" -" \\dP[itn+] [パターン] パーティションリレーション[テーブル/インデックスのみ]\n" -" の一覧を表示 [n=入れ子]\n" +msgid " \\di[Sx+] [PATTERN] list indexes\n" +msgstr " \\di[Sx+] [パターン] インデックスの一覧を表示\n" #: help.c:259 -msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" -msgstr "" -" \\drds [ロールパターン [DBパターン]]\n" -" データベース毎のロール設定の一覧を表示\n" +msgid " \\dl[x+] list large objects, same as \\lo_list\n" +msgstr " \\dl[x+] ラージオブジェクトの一覧を表示、\\lo_list と同じ\n" #: help.c:260 -msgid " \\drg[S] [PATTERN] list role grants\n" -msgstr "" -" \\drg[S] [PATTERN] ロール権限付与の一覧を表示\n" -"\n" +msgid " \\dL[Sx+] [PATTERN] list procedural languages\n" +msgstr " \\dL[Sx+] [パターン] 手続き言語の一覧を表示\n" #: help.c:261 -msgid " \\dRp[+] [PATTERN] list replication publications\n" -msgstr " \\dRp[+] [パターン] レプリケーションのパブリケーションの一覧を表示\n" +msgid " \\dm[Sx+] [PATTERN] list materialized views\n" +msgstr " \\dm[Sx+] [パターン] 実体化ビューの一覧を表示\n" #: help.c:262 -msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" -msgstr " \\dRs[+] [パターン] レプリケーションのサブスクリプションの一覧を表示\n" +msgid " \\dn[Sx+] [PATTERN] list schemas\n" +msgstr " \\dn[Sx+] [パターン] スキーマの一覧を表示\n" #: help.c:263 -msgid " \\ds[S+] [PATTERN] list sequences\n" -msgstr " \\ds[S+] [パターン] シーケンスの一覧を表示\n" - -#: help.c:264 -msgid " \\dt[S+] [PATTERN] list tables\n" -msgstr " \\dt[S+] [パターン] テーブルの一覧を表示\n" +msgid "" +" \\do[Sx+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" +" list operators\n" +msgstr "" +" \\do[Sx+] [演算子パターン [型パターン [型パターン]]]\n" +" 演算子の一覧を表示\n" #: help.c:265 -msgid " \\dT[S+] [PATTERN] list data types\n" -msgstr " \\dT[S+] [パターン] データ型の一覧を表示\n" +msgid " \\dO[Sx+] [PATTERN] list collations\n" +msgstr " \\dO[Sx+] [パターン] 照合順序の一覧を表示\n" #: help.c:266 -msgid " \\du[S+] [PATTERN] list roles\n" -msgstr " \\du[S+] [パターン] ロールの一覧を表示\n" +msgid " \\dp[Sx] [PATTERN] list table, view, and sequence access privileges\n" +msgstr " \\dp[Sx] [パターン] テーブル、ビュー、シーケンスのアクセス権の一覧を表示\n" #: help.c:267 -msgid " \\dv[S+] [PATTERN] list views\n" -msgstr " \\dv[S+] [パターン] ビューの一覧を表示\n" +msgid " \\dP[itnx+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" +msgstr "" +" \\dP[itnx+] [パターン] パーティションリレーション[テーブル/インデックスのみ]\n" +" の一覧を表示 [n=入れ子]\n" +" \n" #: help.c:268 -msgid " \\dx[+] [PATTERN] list extensions\n" -msgstr " \\dx[+] [パターン] 機能拡張の一覧を表示\n" +msgid " \\drds[x] [ROLEPTRN [DBPTRN]] list per-database role settings\n" +msgstr "" +" \\drds[x] [ロールパターン [DBパターン]]\n" +" データベース毎のロール設定の一覧を表示\n" #: help.c:269 -msgid " \\dX [PATTERN] list extended statistics\n" -msgstr " \\dX [パターン] 拡張統計情報の一覧を表示\n" +msgid " \\drg[Sx] [PATTERN] list role grants\n" +msgstr " \\drg[Sx] [パターン] ロール権限付与の一覧を表示\n" #: help.c:270 -msgid " \\dy[+] [PATTERN] list event triggers\n" -msgstr " \\dy[+] [パターン] イベントトリガーの一覧を表示\n" +msgid " \\dRp[x+] [PATTERN] list replication publications\n" +msgstr " \\dRp[x+] [パターン] レプリケーションのパブリケーションの一覧を表示\n" #: help.c:271 -msgid " \\l[+] [PATTERN] list databases\n" -msgstr " \\l[+] [パターン] データベースの一覧を表示\n" +msgid " \\dRs[x+] [PATTERN] list replication subscriptions\n" +msgstr " \\dRs[x+] [パターン] レプリケーションのサブスクリプションの一覧を表示\n" #: help.c:272 -msgid " \\sf[+] FUNCNAME show a function's definition\n" -msgstr " \\sf[+] 関数名 関数の定義を表示\n" +msgid " \\ds[Sx+] [PATTERN] list sequences\n" +msgstr " \\ds[Sx+] [パターン] シーケンスの一覧を表示\n" #: help.c:273 -msgid " \\sv[+] VIEWNAME show a view's definition\n" -msgstr " \\sv[+] ビュー名 ビューの定義を表示\n" +msgid " \\dt[Sx+] [PATTERN] list tables\n" +msgstr " \\dt[Sx+] [パターン] テーブルの一覧を表示\n" #: help.c:274 -msgid " \\z[S] [PATTERN] same as \\dp\n" -msgstr " \\z[S] [パターン] \\dp と同じ\n" +msgid " \\dT[Sx+] [PATTERN] list data types\n" +msgstr " \\dT[Sx+] [パターン] データ型の一覧を表示\n" + +#: help.c:275 +msgid " \\du[Sx+] [PATTERN] list roles\n" +msgstr " \\du[Sx+] [パターン] ロールの一覧を表示\n" + +#: help.c:276 +msgid " \\dv[Sx+] [PATTERN] list views\n" +msgstr " \\dv[Sx+] [パターン] ビューの一覧を表示\n" #: help.c:277 +msgid " \\dx[x+] [PATTERN] list extensions\n" +msgstr " \\dx[x+] [パターン] 機能拡張の一覧を表示\n" + +#: help.c:278 +msgid " \\dX[x] [PATTERN] list extended statistics\n" +msgstr " \\dX[x] [パターン] 拡張統計情報の一覧を表示\n" + +#: help.c:279 +msgid " \\dy[x+] [PATTERN] list event triggers\n" +msgstr " \\dy[x+] [パターン] イベントトリガーの一覧を表示\n" + +#: help.c:280 +msgid " \\l[x+] [PATTERN] list databases\n" +msgstr " \\l[x+] [パターン] データベースの一覧を表示\n" + +#: help.c:281 +msgid " \\sf[+] FUNCNAME show a function's definition\n" +msgstr " \\sf[+] 関数名 関数の定義を表示\n" + +#: help.c:282 +msgid " \\sv[+] VIEWNAME show a view's definition\n" +msgstr " \\sv[+] ビュー名 ビューの定義を表示\n" + +#: help.c:283 +msgid " \\z[Sx] [PATTERN] same as \\dp\n" +msgstr " \\z[Sx] [パターン] \\dp と同じ\n" + +#: help.c:286 msgid "Large Objects\n" msgstr "ラージ・オブジェクト\n" -#: help.c:278 +#: help.c:287 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr "" " \\lo_export LOBOID ファイル名\n" " ラージ・オブエジェクトをファイルに書き込む\n" -#: help.c:279 +#: help.c:288 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3187,38 +3437,38 @@ msgstr "" " \\lo_import ファイル名 [コメント]\n" " ラージ・オブジェクトをファイルから読み込む\n" -#: help.c:281 -msgid " \\lo_list[+] list large objects\n" -msgstr " \\lo_list[+] ラージ・オブジェクトの一覧を表示\n" +#: help.c:290 +msgid " \\lo_list[x+] list large objects\n" +msgstr " \\lo_list[x+] ラージ・オブジェクトの一覧を表示\n" -#: help.c:282 +#: help.c:291 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID ラージ・オブジェクトを削除\n" -#: help.c:285 +#: help.c:294 msgid "Formatting\n" msgstr "書式設定\n" -#: help.c:286 +#: help.c:295 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr " \\a 非整列と整列間の出力モードの切り替え\n" -#: help.c:287 +#: help.c:296 msgid " \\C [STRING] set table title, or unset if none\n" msgstr " \\C [文字列] テーブルのタイトルを設定、値がなければ削除\n" -#: help.c:288 +#: help.c:297 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr "" " \\f [文字列] 問い合わせ結果の非整列出力時のフィールド区切り文字を\n" " 表示または設定\n" -#: help.c:289 +#: help.c:298 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H HTML出力モードの切り替え (現在値: %s)\n" -#: help.c:291 +#: help.c:300 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3226,39 +3476,39 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" -" \\pset [名前 [値]] テーブル出力のオプション設定\n" -" (border|columns|csv_fieldsep|expanded|fieldsep|\n" +" \\pset [名前 [値]] テーブル出力のオプションを指定します\n" +" (border|columns|csv_fieldsep|expanded|fieldsep|\n" " fieldsep_zero|footer|format|linestyle|null|\n" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:298 +#: help.c:307 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] 結果行のみ表示 (現在値: %s)\n" -#: help.c:300 +#: help.c:309 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr " \\T [文字列] HTMLの
タグ属性の設定、値がなければ解除\n" -#: help.c:301 +#: help.c:310 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] 拡張出力の切り替え (現在値: %s)\n" -#: help.c:302 +#: help.c:311 msgid "auto" msgstr "自動(auto)" -#: help.c:305 +#: help.c:314 msgid "Connection\n" msgstr "接続\n" -#: help.c:307 +#: help.c:316 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3267,7 +3517,7 @@ msgstr "" " \\c[onnect] {[DB名|- ユーザー名|- ホスト名|- ポート番号|-] | 接続文字列}\n" " 新しいデータベースに接続 (現在: \"%s\")\n" -#: help.c:311 +#: help.c:320 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3275,64 +3525,64 @@ msgstr "" " \\c[onnect] {[DB名|- ユーザー名|- ホスト名|- ポート番号|-] | 接続文字列}\n" " 新しいデータベースに接続 (現在: 未接続)\n" -#: help.c:313 +#: help.c:322 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo 現在の接続に関する情報を表示\n" -#: help.c:314 +#: help.c:323 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [エンコーディング] クライアントのエンコーディングを表示または設定\n" -#: help.c:315 +#: help.c:324 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr " \\password [ユーザー名] ユーザーのパスワードを安全に変更\n" -#: help.c:318 +#: help.c:327 msgid "Operating System\n" msgstr "オペレーティングシステム\n" -#: help.c:319 +#: help.c:328 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [DIR] カレントディレクトリを変更\n" -#: help.c:320 +#: help.c:329 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr "" " \\getenv psql変数 環境変数\n" " 環境変数を取得\n" -#: help.c:321 +#: help.c:330 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv 名前 [値] 環境変数を設定または解除\n" -#: help.c:322 +#: help.c:331 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] コマンドの実行時間表示の切り替え (現在値: %s)\n" -#: help.c:324 +#: help.c:333 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr "" " \\! [コマンド] シェルでコマンドを実行するか、もしくは対話型シェルを\n" " 起動します。\n" -#: help.c:327 +#: help.c:336 msgid "Variables\n" msgstr "変数\n" -#: help.c:328 +#: help.c:337 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr " \\prompt [テキスト] 変数名 ユーザーに対して内部変数の設定を要求します\n" -#: help.c:329 +#: help.c:338 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr " \\set [変数名 [値]] 内部変数の値を設定、パラメータがなければ一覧を表示\n" -#: help.c:330 +#: help.c:339 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset 変数名 内部変数を削除\n" -#: help.c:369 +#: help.c:378 msgid "" "List of specially treated variables\n" "\n" @@ -3340,11 +3590,11 @@ msgstr "" "特別に扱われる変数の一覧\n" "\n" -#: help.c:371 +#: help.c:380 msgid "psql variables:\n" msgstr "psql変数:\n" -#: help.c:373 +#: help.c:382 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3354,7 +3604,7 @@ msgstr "" " またはpsql内で \\set 名前 値\n" "\n" -#: help.c:375 +#: help.c:384 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3362,7 +3612,7 @@ msgstr "" " AUTOCOMMIT\n" " セットされている場合、SQLコマンドが成功した際に自動的にコミット\n" -#: help.c:377 +#: help.c:386 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3372,7 +3622,7 @@ msgstr "" " SQLキーワードの補完に使う文字ケースを指定\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:380 +#: help.c:389 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3380,7 +3630,7 @@ msgstr "" " DBNAME\n" " 現在接続中のデータベース名\n" -#: help.c:382 +#: help.c:391 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3390,7 +3640,7 @@ msgstr "" " どの入力を標準出力への出力対象とするかを設定\n" " [all, errors, none, queries]\n" -#: help.c:385 +#: help.c:394 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3400,7 +3650,7 @@ msgstr "" " セットされていれば、バックスラッシュコマンドで実行される内部問い合わせを\n" " 表示; \"noexec\"を設定した場合は実行せずに表示のみ\n" -#: help.c:388 +#: help.c:397 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3408,7 +3658,7 @@ msgstr "" " ENCODING\n" " 現在のクライアント側の文字セットのエンコーディング\n" -#: help.c:390 +#: help.c:399 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3416,7 +3666,7 @@ msgstr "" " ERROR\n" " 最後の問い合わせが失敗であれば\"true\"、そうでなければ\"false\"\n" -#: help.c:392 +#: help.c:401 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" @@ -3424,7 +3674,7 @@ msgstr "" " FETCH_COUNT\n" " 一度に取得および表示する結果の行数 (0 = 無制限)\n" -#: help.c:394 +#: help.c:403 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3432,7 +3682,7 @@ msgstr "" " HIDE_TABLEAM\n" " 設定すると、テーブルアクセスメソッドは表示されない\n" -#: help.c:396 +#: help.c:405 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3440,7 +3690,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " 設定すると、圧縮方式は表示されない\n" -#: help.c:398 +#: help.c:407 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3448,7 +3698,7 @@ msgstr "" " HISTCONTROL\n" " コマンド履歴の制御 [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:400 +#: help.c:409 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3456,7 +3706,7 @@ msgstr "" " HISTFILE\n" " コマンド履歴を保存するファイルの名前\n" -#: help.c:402 +#: help.c:411 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3464,7 +3714,7 @@ msgstr "" " HISTSIZE\n" " コマンド履歴で保存するコマンド数の上限\n" -#: help.c:404 +#: help.c:413 msgid "" " HOST\n" " the currently connected database server host\n" @@ -3472,7 +3722,7 @@ msgstr "" " HOST\n" " 現在接続中のデータベースサーバーホスト\n" -#: help.c:406 +#: help.c:415 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3480,7 +3730,7 @@ msgstr "" " IGNOREEOF\n" " 対話形セッションを終わらせるのに必要なEOFの数\n" -#: help.c:408 +#: help.c:417 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3488,7 +3738,7 @@ msgstr "" " LASTOID\n" " 最後の変更の影響を受けたOID\n" -#: help.c:410 +#: help.c:419 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3499,7 +3749,7 @@ msgstr "" " 最後のエラーのメッセージおよび SQLSTATE、\n" " なにもなければ空の文字列および\"00000\"\n" -#: help.c:413 +#: help.c:422 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3508,7 +3758,7 @@ msgstr "" " セットされている場合、エラーでトランザクションを停止しない (暗黙のセーブ\n" " ポイントを使用)\n" -#: help.c:415 +#: help.c:424 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3516,7 +3766,7 @@ msgstr "" " ON_ERROR_STOP\n" " エラー発生後にバッチ実行を停止\n" -#: help.c:417 +#: help.c:426 msgid "" " PORT\n" " server port of the current connection\n" @@ -3524,7 +3774,7 @@ msgstr "" " PORT\n" " 現在の接続のサーバーポート\n" -#: help.c:419 +#: help.c:428 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3532,7 +3782,7 @@ msgstr "" " PROMPT1\n" " psql の標準のプロンプトを指定\n" -#: help.c:421 +#: help.c:430 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" @@ -3540,7 +3790,7 @@ msgstr "" " PROMPT2\n" " 文が前行から継続する場合のプロンプトを指定\n" -#: help.c:423 +#: help.c:432 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3548,7 +3798,7 @@ msgstr "" " PROMPT3\n" " COPY ... FROM STDIN の最中に使われるプロンプトを指定\n" -#: help.c:425 +#: help.c:434 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3556,7 +3806,7 @@ msgstr "" " QUIET\n" " メッセージを表示しない (-q オプションと同じ)\n" -#: help.c:427 +#: help.c:436 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3564,7 +3814,7 @@ msgstr "" " ROW_COUNT\n" " 最後の問い合わせで返却した、または影響を与えた行の数、または0\n" -#: help.c:429 +#: help.c:438 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3574,7 +3824,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " サーバーのバージョン(短い文字列または数値)\n" -#: help.c:432 +#: help.c:441 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3582,7 +3832,7 @@ msgstr "" " SHELL_ERROR\n" " 最後のシェルコマンドが失敗であれば\"true\"、成功であれば\"false\"\n" -#: help.c:434 +#: help.c:443 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3590,7 +3840,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " 最後に実行したシェルコマンドの終了ステータス\n" -#: help.c:436 +#: help.c:445 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3598,7 +3848,7 @@ msgstr "" " SHOW_ALL_RESULTS\n" " 複合問い合わせ(\\;)の最後の結果のみではなくすべてを表示する\n" -#: help.c:438 +#: help.c:447 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3606,7 +3856,7 @@ msgstr "" " SHOW_CONTEXT\n" " メッセージコンテキストフィールドの表示を制御 [never, errors, always]\n" -#: help.c:440 +#: help.c:449 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3614,7 +3864,7 @@ msgstr "" " SINGLELINE\n" " セットした場合、改行はSQLコマンドを終端する (-S オプションと同じ)\n" -#: help.c:442 +#: help.c:451 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3622,7 +3872,7 @@ msgstr "" " SINGLESTEP\n" " シングルステップモード (-s オプションと同じ)\n" -#: help.c:444 +#: help.c:453 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3630,7 +3880,7 @@ msgstr "" " SQLSTATE\n" " 最後の問い合わせの SQLSTATE、またはエラーでなければ\"00000\"\n" -#: help.c:446 +#: help.c:455 msgid "" " USER\n" " the currently connected database user\n" @@ -3638,7 +3888,7 @@ msgstr "" " USER\n" " 現在接続中のデータベースユーザー\n" -#: help.c:448 +#: help.c:457 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3646,7 +3896,7 @@ msgstr "" " VERBOSITY\n" " エラー報告の詳細度を制御 [default, verbose, terse, sqlstate]\n" -#: help.c:450 +#: help.c:459 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3658,7 +3908,15 @@ msgstr "" " VERSION_NUM\n" " psql のバージョン(長い文字列、短い文字列または数値)\n" -#: help.c:455 +#: help.c:463 +msgid "" +" WATCH_INTERVAL\n" +" if set to a number, overrides the default two second \\watch interval\n" +msgstr "" +" WATCH_INTERVAL\n" +" 数値の場合、\\watch間隔のデフォルトである2秒を変更します\n" + +#: help.c:466 msgid "" "\n" "Display settings:\n" @@ -3666,7 +3924,7 @@ msgstr "" "\n" "表示設定:\n" -#: help.c:457 +#: help.c:468 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3676,7 +3934,7 @@ msgstr "" " またはpsql内で \\pset 名前 [値]\n" "\n" -#: help.c:459 +#: help.c:470 msgid "" " border\n" " border style (number)\n" @@ -3684,7 +3942,7 @@ msgstr "" " border\n" " 境界線のスタイル (番号)\n" -#: help.c:461 +#: help.c:472 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3692,7 +3950,7 @@ msgstr "" " columns\n" " 折り返し形式で目標とする横幅\n" -#: help.c:463 +#: help.c:474 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" @@ -3700,7 +3958,7 @@ msgstr "" " expanded (or x)\n" " 拡張出力 [on, off, auto]\n" -#: help.c:465 +#: help.c:476 #, c-format msgid "" " fieldsep\n" @@ -3709,7 +3967,7 @@ msgstr "" " fieldsep\n" " 非整列出力でのフィールド区切り文字(デフォルトは \"%s\")\n" -#: help.c:468 +#: help.c:479 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3717,7 +3975,7 @@ msgstr "" " fieldsep_zero\n" " 非整列出力でのフィールド区切り文字をバイト値の0に設定\n" -#: help.c:470 +#: help.c:481 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3725,7 +3983,7 @@ msgstr "" " footer\n" " テーブルフッター出力の要否を設定 [on, off]\n" -#: help.c:472 +#: help.c:483 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3733,7 +3991,7 @@ msgstr "" " format\n" " 出力フォーマットを設定 [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:474 +#: help.c:485 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3741,7 +3999,7 @@ msgstr "" " linestyle\n" " 境界線の描画スタイルを設定 [ascii, old-ascii, unicode]\n" -#: help.c:476 +#: help.c:487 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3749,7 +4007,7 @@ msgstr "" " null\n" " null 値の代わりに表示する文字列を設定\n" -#: help.c:478 +#: help.c:489 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" @@ -3757,7 +4015,7 @@ msgstr "" " numericlocale\n" " ロケール固有文字での桁区切りを表示するかどうかを指定\n" -#: help.c:480 +#: help.c:491 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3765,7 +4023,7 @@ msgstr "" " pager\n" " いつ外部ページャーを使うかを制御 [yes, no, always]\n" -#: help.c:482 +#: help.c:493 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3773,7 +4031,7 @@ msgstr "" " recordsep\n" " 非整列出力でのレコード(行)区切り\n" -#: help.c:484 +#: help.c:495 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3781,7 +4039,7 @@ msgstr "" " recordsep_zero\n" " 非整列出力でレコード区切りにバイト値の0に設定\n" -#: help.c:486 +#: help.c:497 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3791,7 +4049,7 @@ msgstr "" " HTMLフォーマット時のtableタグの属性、もしくは latex-longtable\n" " フォーマット時に左寄せするデータ型の相対カラム幅を指定\n" -#: help.c:489 +#: help.c:500 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -3799,7 +4057,7 @@ msgstr "" " title\n" " 以降に表示される表のタイトルを設定\n" -#: help.c:491 +#: help.c:502 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -3807,7 +4065,7 @@ msgstr "" " tuples_only\n" " セットされた場合、実際のテーブルデータのみを表示\n" -#: help.c:493 +#: help.c:504 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3819,7 +4077,17 @@ msgstr "" " unicode_header_linestyle\n" " Unicode による線描画時のスタイルを設定 [single, double]\n" -#: help.c:498 +#: help.c:508 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" 拡張出力のヘッダの最大幅を指定します\n" +" [full, column, page, 整数値]\n" + +#: help.c:512 msgid "" "\n" "Environment variables:\n" @@ -3827,7 +4095,7 @@ msgstr "" "\n" "環境変数:\n" -#: help.c:502 +#: help.c:516 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3837,7 +4105,7 @@ msgstr "" " またはpsql内で \\setenv 名前 [値]\n" "\n" -#: help.c:504 +#: help.c:518 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3849,7 +4117,7 @@ msgstr "" " またはpsq内で \\setenv 名前 [値]\n" "\n" -#: help.c:507 +#: help.c:521 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -3857,7 +4125,7 @@ msgstr "" " COLUMNS\n" " 折り返し書式におけるカラム数\n" -#: help.c:509 +#: help.c:523 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -3865,7 +4133,7 @@ msgstr "" " PGAPPNAME\n" " application_name 接続パラメータと同じ\n" -#: help.c:511 +#: help.c:525 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -3873,7 +4141,7 @@ msgstr "" " PGDATABASE\n" " dbname 接続パラメータと同じ\n" -#: help.c:513 +#: help.c:527 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -3881,7 +4149,7 @@ msgstr "" " PGHOST\n" " host 接続パラメータと同じ\n" -#: help.c:515 +#: help.c:529 msgid "" " PGPASSFILE\n" " password file name\n" @@ -3889,7 +4157,7 @@ msgstr "" " PGPASSFILE\n" " パスワードファイル名\n" -#: help.c:517 +#: help.c:531 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -3897,7 +4165,7 @@ msgstr "" " PGPASSWORD\n" " 接続用パスワード (推奨されません)\n" -#: help.c:519 +#: help.c:533 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -3905,7 +4173,7 @@ msgstr "" " PGPORT\n" " port 接続パラメータと同じ\n" -#: help.c:521 +#: help.c:535 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -3913,7 +4181,7 @@ msgstr "" " PGUSER\n" " user 接続パラメータと同じ\n" -#: help.c:523 +#: help.c:537 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3921,7 +4189,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " \\e, \\ef, \\ev コマンドで使われるエディタ\n" -#: help.c:525 +#: help.c:539 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -3929,7 +4197,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " エディタの起動時に行番号を指定する方法\n" -#: help.c:527 +#: help.c:541 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -3937,7 +4205,7 @@ msgstr "" " PSQL_HISTORY\n" " コマンドライン履歴ファイルの代替の場所\n" -#: help.c:529 +#: help.c:543 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -3945,7 +4213,7 @@ msgstr "" " PSQL_PAGER, PAGER\n" " 外部ページャープログラムの名前\n" -#: help.c:532 +#: help.c:546 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -3953,7 +4221,7 @@ msgstr "" " PSQL_PAGER, PAGER\n" " \\watchで使用する外部ページャープログラムの名前\n" -#: help.c:535 +#: help.c:549 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -3961,7 +4229,7 @@ msgstr "" " PSQLRC\n" " ユーザーの .psqlrc ファイルの代替の場所\n" -#: help.c:537 +#: help.c:551 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -3969,7 +4237,7 @@ msgstr "" " SHELL\n" " \\! コマンドで使われるシェル\n" -#: help.c:539 +#: help.c:553 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -3977,11 +4245,11 @@ msgstr "" " TMPDIR\n" " テンポラリファイル用ディレクトリ\n" -#: help.c:599 +#: help.c:613 msgid "Available help:\n" msgstr "利用可能なヘルプ:\n" -#: help.c:694 +#: help.c:708 #, c-format msgid "" "Command: %s\n" @@ -4000,7 +4268,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:717 +#: help.c:731 #, c-format msgid "" "No help available for \"%s\".\n" @@ -4106,12 +4374,12 @@ msgstr "問い合わせは無視されました; \\endifかCtrl-Cで現在の\\i msgid "reached EOF without finding closing \\endif(s)" msgstr "ブロックを閉じる\\endifを検出中に、ファイルの終端(EOF)に達しました" -#: psqlscanslash.l:642 +#: psqlscanslash.l:633 #, c-format msgid "unterminated quoted string" msgstr "文字列の引用符が閉じていません" -#: psqlscanslash.l:842 +#: psqlscanslash.l:834 #, c-format msgid "%s: out of memory" msgstr "%s: メモリ不足です" @@ -4119,2470 +4387,2473 @@ msgstr "%s: メモリ不足です" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:240 -#: sql_help.c:242 sql_help.c:243 sql_help.c:245 sql_help.c:247 sql_help.c:250 -#: sql_help.c:252 sql_help.c:254 sql_help.c:256 sql_help.c:268 sql_help.c:269 -#: sql_help.c:270 sql_help.c:272 sql_help.c:321 sql_help.c:323 sql_help.c:325 -#: sql_help.c:327 sql_help.c:396 sql_help.c:401 sql_help.c:403 sql_help.c:445 -#: sql_help.c:447 sql_help.c:450 sql_help.c:452 sql_help.c:521 sql_help.c:526 -#: sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:595 sql_help.c:597 -#: sql_help.c:599 sql_help.c:601 sql_help.c:603 sql_help.c:606 sql_help.c:608 -#: sql_help.c:611 sql_help.c:622 sql_help.c:624 sql_help.c:668 sql_help.c:670 -#: sql_help.c:672 sql_help.c:675 sql_help.c:677 sql_help.c:679 sql_help.c:720 -#: sql_help.c:724 sql_help.c:728 sql_help.c:749 sql_help.c:752 sql_help.c:755 -#: sql_help.c:784 sql_help.c:796 sql_help.c:804 sql_help.c:807 sql_help.c:810 -#: sql_help.c:825 sql_help.c:828 sql_help.c:857 sql_help.c:862 sql_help.c:867 -#: sql_help.c:872 sql_help.c:877 sql_help.c:904 sql_help.c:906 sql_help.c:908 -#: sql_help.c:910 sql_help.c:913 sql_help.c:915 sql_help.c:962 sql_help.c:1007 -#: sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 sql_help.c:1027 -#: sql_help.c:1046 sql_help.c:1057 sql_help.c:1059 sql_help.c:1079 -#: sql_help.c:1089 sql_help.c:1090 sql_help.c:1092 sql_help.c:1094 -#: sql_help.c:1106 sql_help.c:1110 sql_help.c:1112 sql_help.c:1124 -#: sql_help.c:1126 sql_help.c:1128 sql_help.c:1130 sql_help.c:1149 -#: sql_help.c:1151 sql_help.c:1155 sql_help.c:1159 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1167 sql_help.c:1168 sql_help.c:1171 -#: sql_help.c:1174 sql_help.c:1176 sql_help.c:1323 sql_help.c:1325 -#: sql_help.c:1328 sql_help.c:1331 sql_help.c:1333 sql_help.c:1335 -#: sql_help.c:1338 sql_help.c:1341 sql_help.c:1343 sql_help.c:1349 -#: sql_help.c:1473 sql_help.c:1475 sql_help.c:1477 sql_help.c:1480 -#: sql_help.c:1501 sql_help.c:1504 sql_help.c:1507 sql_help.c:1510 -#: sql_help.c:1514 sql_help.c:1516 sql_help.c:1518 sql_help.c:1520 -#: sql_help.c:1534 sql_help.c:1537 sql_help.c:1539 sql_help.c:1541 -#: sql_help.c:1551 sql_help.c:1553 sql_help.c:1563 sql_help.c:1565 -#: sql_help.c:1575 sql_help.c:1578 sql_help.c:1601 sql_help.c:1603 -#: sql_help.c:1605 sql_help.c:1607 sql_help.c:1610 sql_help.c:1612 -#: sql_help.c:1615 sql_help.c:1618 sql_help.c:1669 sql_help.c:1712 -#: sql_help.c:1715 sql_help.c:1717 sql_help.c:1719 sql_help.c:1722 -#: sql_help.c:1724 sql_help.c:1726 sql_help.c:1729 sql_help.c:1779 -#: sql_help.c:1795 sql_help.c:2028 sql_help.c:2097 sql_help.c:2116 -#: sql_help.c:2129 sql_help.c:2187 sql_help.c:2195 sql_help.c:2205 -#: sql_help.c:2233 sql_help.c:2266 sql_help.c:2284 sql_help.c:2312 -#: sql_help.c:2423 sql_help.c:2469 sql_help.c:2494 sql_help.c:2517 -#: sql_help.c:2521 sql_help.c:2555 sql_help.c:2575 sql_help.c:2597 -#: sql_help.c:2611 sql_help.c:2632 sql_help.c:2661 sql_help.c:2694 -#: sql_help.c:2717 sql_help.c:2764 sql_help.c:3062 sql_help.c:3075 -#: sql_help.c:3092 sql_help.c:3108 sql_help.c:3148 sql_help.c:3202 -#: sql_help.c:3206 sql_help.c:3208 sql_help.c:3215 sql_help.c:3234 -#: sql_help.c:3261 sql_help.c:3296 sql_help.c:3308 sql_help.c:3317 -#: sql_help.c:3361 sql_help.c:3375 sql_help.c:3403 sql_help.c:3411 -#: sql_help.c:3423 sql_help.c:3433 sql_help.c:3441 sql_help.c:3449 -#: sql_help.c:3457 sql_help.c:3465 sql_help.c:3474 sql_help.c:3485 -#: sql_help.c:3493 sql_help.c:3501 sql_help.c:3509 sql_help.c:3517 -#: sql_help.c:3527 sql_help.c:3536 sql_help.c:3545 sql_help.c:3553 -#: sql_help.c:3563 sql_help.c:3574 sql_help.c:3582 sql_help.c:3591 -#: sql_help.c:3602 sql_help.c:3611 sql_help.c:3619 sql_help.c:3627 -#: sql_help.c:3635 sql_help.c:3643 sql_help.c:3651 sql_help.c:3659 -#: sql_help.c:3667 sql_help.c:3675 sql_help.c:3683 sql_help.c:3691 -#: sql_help.c:3708 sql_help.c:3717 sql_help.c:3725 sql_help.c:3742 -#: sql_help.c:3757 sql_help.c:4070 sql_help.c:4191 sql_help.c:4220 -#: sql_help.c:4236 sql_help.c:4238 sql_help.c:4742 sql_help.c:4790 -#: sql_help.c:4949 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:259 +#: sql_help.c:261 sql_help.c:262 sql_help.c:264 sql_help.c:266 sql_help.c:269 +#: sql_help.c:271 sql_help.c:273 sql_help.c:275 sql_help.c:290 sql_help.c:291 +#: sql_help.c:292 sql_help.c:294 sql_help.c:343 sql_help.c:345 sql_help.c:347 +#: sql_help.c:349 sql_help.c:418 sql_help.c:423 sql_help.c:425 sql_help.c:467 +#: sql_help.c:469 sql_help.c:472 sql_help.c:474 sql_help.c:543 sql_help.c:548 +#: sql_help.c:553 sql_help.c:558 sql_help.c:563 sql_help.c:617 sql_help.c:619 +#: sql_help.c:621 sql_help.c:623 sql_help.c:625 sql_help.c:628 sql_help.c:630 +#: sql_help.c:633 sql_help.c:644 sql_help.c:646 sql_help.c:690 sql_help.c:692 +#: sql_help.c:694 sql_help.c:697 sql_help.c:699 sql_help.c:701 sql_help.c:742 +#: sql_help.c:746 sql_help.c:750 sql_help.c:771 sql_help.c:774 sql_help.c:777 +#: sql_help.c:806 sql_help.c:818 sql_help.c:826 sql_help.c:829 sql_help.c:832 +#: sql_help.c:847 sql_help.c:850 sql_help.c:879 sql_help.c:884 sql_help.c:889 +#: sql_help.c:894 sql_help.c:899 sql_help.c:926 sql_help.c:928 sql_help.c:930 +#: sql_help.c:932 sql_help.c:935 sql_help.c:937 sql_help.c:984 sql_help.c:1029 +#: sql_help.c:1034 sql_help.c:1039 sql_help.c:1044 sql_help.c:1049 +#: sql_help.c:1068 sql_help.c:1079 sql_help.c:1081 sql_help.c:1102 +#: sql_help.c:1112 sql_help.c:1113 sql_help.c:1115 sql_help.c:1117 +#: sql_help.c:1129 sql_help.c:1133 sql_help.c:1135 sql_help.c:1147 +#: sql_help.c:1149 sql_help.c:1151 sql_help.c:1153 sql_help.c:1172 +#: sql_help.c:1174 sql_help.c:1178 sql_help.c:1182 sql_help.c:1186 +#: sql_help.c:1189 sql_help.c:1190 sql_help.c:1191 sql_help.c:1194 +#: sql_help.c:1197 sql_help.c:1199 sql_help.c:1341 sql_help.c:1343 +#: sql_help.c:1346 sql_help.c:1349 sql_help.c:1351 sql_help.c:1353 +#: sql_help.c:1356 sql_help.c:1359 sql_help.c:1487 sql_help.c:1489 +#: sql_help.c:1491 sql_help.c:1494 sql_help.c:1515 sql_help.c:1518 +#: sql_help.c:1521 sql_help.c:1524 sql_help.c:1528 sql_help.c:1530 +#: sql_help.c:1532 sql_help.c:1534 sql_help.c:1548 sql_help.c:1551 +#: sql_help.c:1553 sql_help.c:1555 sql_help.c:1565 sql_help.c:1567 +#: sql_help.c:1577 sql_help.c:1579 sql_help.c:1589 sql_help.c:1592 +#: sql_help.c:1615 sql_help.c:1617 sql_help.c:1619 sql_help.c:1621 +#: sql_help.c:1624 sql_help.c:1626 sql_help.c:1629 sql_help.c:1632 +#: sql_help.c:1683 sql_help.c:1726 sql_help.c:1729 sql_help.c:1731 +#: sql_help.c:1733 sql_help.c:1736 sql_help.c:1738 sql_help.c:1740 +#: sql_help.c:1743 sql_help.c:1793 sql_help.c:1809 sql_help.c:2044 +#: sql_help.c:2113 sql_help.c:2132 sql_help.c:2145 sql_help.c:2203 +#: sql_help.c:2211 sql_help.c:2221 sql_help.c:2249 sql_help.c:2282 +#: sql_help.c:2300 sql_help.c:2328 sql_help.c:2451 sql_help.c:2497 +#: sql_help.c:2522 sql_help.c:2545 sql_help.c:2549 sql_help.c:2583 +#: sql_help.c:2603 sql_help.c:2625 sql_help.c:2639 sql_help.c:2660 +#: sql_help.c:2689 sql_help.c:2722 sql_help.c:2745 sql_help.c:2794 +#: sql_help.c:3098 sql_help.c:3111 sql_help.c:3128 sql_help.c:3144 +#: sql_help.c:3184 sql_help.c:3238 sql_help.c:3242 sql_help.c:3244 +#: sql_help.c:3251 sql_help.c:3270 sql_help.c:3297 sql_help.c:3332 +#: sql_help.c:3344 sql_help.c:3353 sql_help.c:3399 sql_help.c:3413 +#: sql_help.c:3441 sql_help.c:3449 sql_help.c:3461 sql_help.c:3471 +#: sql_help.c:3479 sql_help.c:3487 sql_help.c:3495 sql_help.c:3503 +#: sql_help.c:3512 sql_help.c:3523 sql_help.c:3531 sql_help.c:3539 +#: sql_help.c:3547 sql_help.c:3555 sql_help.c:3565 sql_help.c:3574 +#: sql_help.c:3583 sql_help.c:3591 sql_help.c:3601 sql_help.c:3612 +#: sql_help.c:3620 sql_help.c:3629 sql_help.c:3640 sql_help.c:3649 +#: sql_help.c:3657 sql_help.c:3665 sql_help.c:3673 sql_help.c:3681 +#: sql_help.c:3689 sql_help.c:3697 sql_help.c:3705 sql_help.c:3713 +#: sql_help.c:3721 sql_help.c:3729 sql_help.c:3746 sql_help.c:3755 +#: sql_help.c:3763 sql_help.c:3780 sql_help.c:3795 sql_help.c:4110 +#: sql_help.c:4233 sql_help.c:4262 sql_help.c:4278 sql_help.c:4280 +#: sql_help.c:4784 sql_help.c:4832 sql_help.c:4991 msgid "name" msgstr "名前" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:332 sql_help.c:1872 -#: sql_help.c:3376 sql_help.c:4509 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:354 sql_help.c:1886 +#: sql_help.c:3414 sql_help.c:4551 msgid "aggregate_signature" msgstr "集約関数のシグニチャー" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:255 -#: sql_help.c:273 sql_help.c:404 sql_help.c:451 sql_help.c:530 sql_help.c:578 -#: sql_help.c:596 sql_help.c:623 sql_help.c:676 sql_help.c:751 sql_help.c:806 -#: sql_help.c:827 sql_help.c:866 sql_help.c:916 sql_help.c:963 sql_help.c:1016 -#: sql_help.c:1048 sql_help.c:1058 sql_help.c:1093 sql_help.c:1113 -#: sql_help.c:1127 sql_help.c:1177 sql_help.c:1332 sql_help.c:1474 -#: sql_help.c:1517 sql_help.c:1538 sql_help.c:1552 sql_help.c:1564 -#: sql_help.c:1577 sql_help.c:1604 sql_help.c:1670 sql_help.c:1723 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:274 +#: sql_help.c:295 sql_help.c:426 sql_help.c:473 sql_help.c:552 sql_help.c:600 +#: sql_help.c:618 sql_help.c:645 sql_help.c:698 sql_help.c:773 sql_help.c:828 +#: sql_help.c:849 sql_help.c:888 sql_help.c:938 sql_help.c:985 sql_help.c:1038 +#: sql_help.c:1070 sql_help.c:1080 sql_help.c:1116 sql_help.c:1136 +#: sql_help.c:1150 sql_help.c:1200 sql_help.c:1350 sql_help.c:1488 +#: sql_help.c:1531 sql_help.c:1552 sql_help.c:1566 sql_help.c:1578 +#: sql_help.c:1591 sql_help.c:1618 sql_help.c:1684 sql_help.c:1737 msgid "new_name" msgstr "新しい名前" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:487 sql_help.c:535 sql_help.c:625 -#: sql_help.c:634 sql_help.c:699 sql_help.c:723 sql_help.c:754 sql_help.c:809 -#: sql_help.c:871 sql_help.c:914 sql_help.c:1021 sql_help.c:1060 -#: sql_help.c:1091 sql_help.c:1111 sql_help.c:1125 sql_help.c:1175 -#: sql_help.c:1408 sql_help.c:1476 sql_help.c:1519 sql_help.c:1540 -#: sql_help.c:1602 sql_help.c:1718 sql_help.c:3048 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:272 +#: sql_help.c:293 sql_help.c:424 sql_help.c:509 sql_help.c:557 sql_help.c:647 +#: sql_help.c:656 sql_help.c:721 sql_help.c:745 sql_help.c:776 sql_help.c:831 +#: sql_help.c:893 sql_help.c:936 sql_help.c:1043 sql_help.c:1082 +#: sql_help.c:1114 sql_help.c:1134 sql_help.c:1148 sql_help.c:1198 +#: sql_help.c:1417 sql_help.c:1490 sql_help.c:1533 sql_help.c:1554 +#: sql_help.c:1616 sql_help.c:1732 sql_help.c:3084 msgid "new_owner" msgstr "新しい所有者" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:257 sql_help.c:324 -#: sql_help.c:453 sql_help.c:540 sql_help.c:678 sql_help.c:727 sql_help.c:757 -#: sql_help.c:812 sql_help.c:876 sql_help.c:1026 sql_help.c:1095 -#: sql_help.c:1129 sql_help.c:1334 sql_help.c:1521 sql_help.c:1542 -#: sql_help.c:1554 sql_help.c:1566 sql_help.c:1606 sql_help.c:1725 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:276 sql_help.c:346 +#: sql_help.c:475 sql_help.c:562 sql_help.c:700 sql_help.c:749 sql_help.c:779 +#: sql_help.c:834 sql_help.c:898 sql_help.c:1048 sql_help.c:1118 +#: sql_help.c:1152 sql_help.c:1352 sql_help.c:1535 sql_help.c:1556 +#: sql_help.c:1568 sql_help.c:1580 sql_help.c:1620 sql_help.c:1739 msgid "new_schema" msgstr "新しいスキーマ" -#: sql_help.c:44 sql_help.c:1936 sql_help.c:3377 sql_help.c:4538 +#: sql_help.c:44 sql_help.c:1950 sql_help.c:3415 sql_help.c:4580 msgid "where aggregate_signature is:" msgstr "集約関数のシグニチャーには以下のものがあります:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:858 -#: sql_help.c:863 sql_help.c:868 sql_help.c:873 sql_help.c:878 sql_help.c:1008 -#: sql_help.c:1013 sql_help.c:1018 sql_help.c:1023 sql_help.c:1028 -#: sql_help.c:1890 sql_help.c:1907 sql_help.c:1913 sql_help.c:1937 -#: sql_help.c:1940 sql_help.c:1943 sql_help.c:2098 sql_help.c:2117 -#: sql_help.c:2120 sql_help.c:2424 sql_help.c:2633 sql_help.c:3378 -#: sql_help.c:3381 sql_help.c:3384 sql_help.c:3475 sql_help.c:3564 -#: sql_help.c:3592 sql_help.c:3945 sql_help.c:4408 sql_help.c:4515 -#: sql_help.c:4522 sql_help.c:4528 sql_help.c:4539 sql_help.c:4542 -#: sql_help.c:4545 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:364 sql_help.c:377 +#: sql_help.c:381 sql_help.c:397 sql_help.c:400 sql_help.c:403 sql_help.c:544 +#: sql_help.c:549 sql_help.c:554 sql_help.c:559 sql_help.c:564 sql_help.c:880 +#: sql_help.c:885 sql_help.c:890 sql_help.c:895 sql_help.c:900 sql_help.c:1030 +#: sql_help.c:1035 sql_help.c:1040 sql_help.c:1045 sql_help.c:1050 +#: sql_help.c:1904 sql_help.c:1921 sql_help.c:1927 sql_help.c:1951 +#: sql_help.c:1954 sql_help.c:1957 sql_help.c:2114 sql_help.c:2133 +#: sql_help.c:2136 sql_help.c:2452 sql_help.c:2661 sql_help.c:3416 +#: sql_help.c:3419 sql_help.c:3422 sql_help.c:3513 sql_help.c:3602 +#: sql_help.c:3630 sql_help.c:3983 sql_help.c:4450 sql_help.c:4557 +#: sql_help.c:4564 sql_help.c:4570 sql_help.c:4581 sql_help.c:4584 +#: sql_help.c:4587 msgid "argmode" msgstr "引数のモード" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:343 sql_help.c:356 -#: sql_help.c:360 sql_help.c:376 sql_help.c:379 sql_help.c:382 sql_help.c:523 -#: sql_help.c:528 sql_help.c:533 sql_help.c:538 sql_help.c:543 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:874 sql_help.c:879 sql_help.c:1009 -#: sql_help.c:1014 sql_help.c:1019 sql_help.c:1024 sql_help.c:1029 -#: sql_help.c:1891 sql_help.c:1908 sql_help.c:1914 sql_help.c:1938 -#: sql_help.c:1941 sql_help.c:1944 sql_help.c:2099 sql_help.c:2118 -#: sql_help.c:2121 sql_help.c:2425 sql_help.c:2634 sql_help.c:3379 -#: sql_help.c:3382 sql_help.c:3385 sql_help.c:3476 sql_help.c:3565 -#: sql_help.c:3593 sql_help.c:4516 sql_help.c:4523 sql_help.c:4529 -#: sql_help.c:4540 sql_help.c:4543 sql_help.c:4546 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:365 sql_help.c:378 +#: sql_help.c:382 sql_help.c:398 sql_help.c:401 sql_help.c:404 sql_help.c:545 +#: sql_help.c:550 sql_help.c:555 sql_help.c:560 sql_help.c:565 sql_help.c:881 +#: sql_help.c:886 sql_help.c:891 sql_help.c:896 sql_help.c:901 sql_help.c:1031 +#: sql_help.c:1036 sql_help.c:1041 sql_help.c:1046 sql_help.c:1051 +#: sql_help.c:1905 sql_help.c:1922 sql_help.c:1928 sql_help.c:1952 +#: sql_help.c:1955 sql_help.c:1958 sql_help.c:2115 sql_help.c:2134 +#: sql_help.c:2137 sql_help.c:2453 sql_help.c:2662 sql_help.c:3417 +#: sql_help.c:3420 sql_help.c:3423 sql_help.c:3514 sql_help.c:3603 +#: sql_help.c:3631 sql_help.c:4558 sql_help.c:4565 sql_help.c:4571 +#: sql_help.c:4582 sql_help.c:4585 sql_help.c:4588 msgid "argname" msgstr "引数の名前" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:344 sql_help.c:357 -#: sql_help.c:361 sql_help.c:377 sql_help.c:380 sql_help.c:383 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:544 sql_help.c:860 -#: sql_help.c:865 sql_help.c:870 sql_help.c:875 sql_help.c:880 sql_help.c:1010 -#: sql_help.c:1015 sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 -#: sql_help.c:1892 sql_help.c:1909 sql_help.c:1915 sql_help.c:1939 -#: sql_help.c:1942 sql_help.c:1945 sql_help.c:2426 sql_help.c:2635 -#: sql_help.c:3380 sql_help.c:3383 sql_help.c:3386 sql_help.c:3477 -#: sql_help.c:3566 sql_help.c:3594 sql_help.c:4517 sql_help.c:4524 -#: sql_help.c:4530 sql_help.c:4541 sql_help.c:4544 sql_help.c:4547 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:366 sql_help.c:379 +#: sql_help.c:383 sql_help.c:399 sql_help.c:402 sql_help.c:405 sql_help.c:546 +#: sql_help.c:551 sql_help.c:556 sql_help.c:561 sql_help.c:566 sql_help.c:882 +#: sql_help.c:887 sql_help.c:892 sql_help.c:897 sql_help.c:902 sql_help.c:1032 +#: sql_help.c:1037 sql_help.c:1042 sql_help.c:1047 sql_help.c:1052 +#: sql_help.c:1906 sql_help.c:1923 sql_help.c:1929 sql_help.c:1953 +#: sql_help.c:1956 sql_help.c:1959 sql_help.c:2454 sql_help.c:2663 +#: sql_help.c:3418 sql_help.c:3421 sql_help.c:3424 sql_help.c:3515 +#: sql_help.c:3604 sql_help.c:3632 sql_help.c:4559 sql_help.c:4566 +#: sql_help.c:4572 sql_help.c:4583 sql_help.c:4586 sql_help.c:4589 msgid "argtype" msgstr "引数の型" -#: sql_help.c:114 sql_help.c:399 sql_help.c:476 sql_help.c:488 sql_help.c:957 -#: sql_help.c:1108 sql_help.c:1535 sql_help.c:1664 sql_help.c:1696 -#: sql_help.c:1748 sql_help.c:1807 sql_help.c:1996 sql_help.c:2003 -#: sql_help.c:2315 sql_help.c:2365 sql_help.c:2372 sql_help.c:2381 -#: sql_help.c:2470 sql_help.c:2695 sql_help.c:2786 sql_help.c:3077 -#: sql_help.c:3262 sql_help.c:3284 sql_help.c:3424 sql_help.c:3781 -#: sql_help.c:3989 sql_help.c:4235 sql_help.c:4237 sql_help.c:5015 +#: sql_help.c:114 sql_help.c:421 sql_help.c:498 sql_help.c:510 sql_help.c:979 +#: sql_help.c:1131 sql_help.c:1549 sql_help.c:1678 sql_help.c:1710 +#: sql_help.c:1762 sql_help.c:1821 sql_help.c:2011 sql_help.c:2018 +#: sql_help.c:2331 sql_help.c:2389 sql_help.c:2398 sql_help.c:2407 +#: sql_help.c:2498 sql_help.c:2723 sql_help.c:2816 sql_help.c:3113 +#: sql_help.c:3298 sql_help.c:3320 sql_help.c:3462 sql_help.c:3819 +#: sql_help.c:4027 sql_help.c:4277 sql_help.c:4279 sql_help.c:5059 msgid "option" msgstr "オプション" -#: sql_help.c:115 sql_help.c:958 sql_help.c:1665 sql_help.c:2471 -#: sql_help.c:2696 sql_help.c:3263 sql_help.c:3425 +#: sql_help.c:115 sql_help.c:980 sql_help.c:1679 sql_help.c:2499 +#: sql_help.c:2724 sql_help.c:3299 sql_help.c:3463 msgid "where option can be:" msgstr "オプションには以下のものがあります:" -#: sql_help.c:116 sql_help.c:2247 +#: sql_help.c:116 sql_help.c:2263 msgid "allowconn" msgstr "接続の可否(真偽値)" -#: sql_help.c:117 sql_help.c:959 sql_help.c:1666 sql_help.c:2248 -#: sql_help.c:2472 sql_help.c:2697 sql_help.c:3264 +#: sql_help.c:117 sql_help.c:981 sql_help.c:1680 sql_help.c:2264 +#: sql_help.c:2500 sql_help.c:2725 sql_help.c:3300 msgid "connlimit" msgstr "最大同時接続数" -#: sql_help.c:118 sql_help.c:2249 +#: sql_help.c:118 sql_help.c:2265 msgid "istemplate" msgstr "テンプレートかどうか(真偽値)" -#: sql_help.c:124 sql_help.c:613 sql_help.c:681 sql_help.c:695 sql_help.c:1337 -#: sql_help.c:1401 sql_help.c:4241 +#: sql_help.c:124 sql_help.c:635 sql_help.c:703 sql_help.c:717 sql_help.c:1355 +#: sql_help.c:1410 sql_help.c:4283 msgid "new_tablespace" msgstr "新しいテーブル空間名" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:550 sql_help.c:552 -#: sql_help.c:553 sql_help.c:883 sql_help.c:885 sql_help.c:886 sql_help.c:966 -#: sql_help.c:970 sql_help.c:973 sql_help.c:1035 sql_help.c:1037 -#: sql_help.c:1038 sql_help.c:1188 sql_help.c:1190 sql_help.c:1673 -#: sql_help.c:1677 sql_help.c:1680 sql_help.c:2436 sql_help.c:2639 -#: sql_help.c:3957 sql_help.c:4259 sql_help.c:4420 sql_help.c:4730 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:572 sql_help.c:574 +#: sql_help.c:575 sql_help.c:905 sql_help.c:907 sql_help.c:908 sql_help.c:988 +#: sql_help.c:992 sql_help.c:995 sql_help.c:1057 sql_help.c:1059 +#: sql_help.c:1060 sql_help.c:1211 sql_help.c:1213 sql_help.c:1687 +#: sql_help.c:1691 sql_help.c:1694 sql_help.c:2464 sql_help.c:2667 +#: sql_help.c:3995 sql_help.c:4301 sql_help.c:4462 sql_help.c:4772 msgid "configuration_parameter" msgstr "設定パラメータ" -#: sql_help.c:128 sql_help.c:400 sql_help.c:471 sql_help.c:477 sql_help.c:489 -#: sql_help.c:551 sql_help.c:605 sql_help.c:687 sql_help.c:697 sql_help.c:884 -#: sql_help.c:912 sql_help.c:967 sql_help.c:1036 sql_help.c:1109 -#: sql_help.c:1154 sql_help.c:1158 sql_help.c:1162 sql_help.c:1165 -#: sql_help.c:1170 sql_help.c:1173 sql_help.c:1189 sql_help.c:1380 -#: sql_help.c:1403 sql_help.c:1451 sql_help.c:1459 sql_help.c:1479 -#: sql_help.c:1536 sql_help.c:1620 sql_help.c:1674 sql_help.c:1697 -#: sql_help.c:2316 sql_help.c:2366 sql_help.c:2373 sql_help.c:2382 -#: sql_help.c:2437 sql_help.c:2438 sql_help.c:2502 sql_help.c:2505 -#: sql_help.c:2539 sql_help.c:2640 sql_help.c:2641 sql_help.c:2664 -#: sql_help.c:2787 sql_help.c:2826 sql_help.c:2936 sql_help.c:2949 -#: sql_help.c:2963 sql_help.c:3004 sql_help.c:3012 sql_help.c:3034 -#: sql_help.c:3051 sql_help.c:3078 sql_help.c:3285 sql_help.c:3990 -#: sql_help.c:4731 sql_help.c:4732 sql_help.c:4733 sql_help.c:4734 +#: sql_help.c:128 sql_help.c:422 sql_help.c:493 sql_help.c:499 sql_help.c:511 +#: sql_help.c:573 sql_help.c:627 sql_help.c:709 sql_help.c:719 sql_help.c:906 +#: sql_help.c:934 sql_help.c:989 sql_help.c:1058 sql_help.c:1132 +#: sql_help.c:1177 sql_help.c:1181 sql_help.c:1185 sql_help.c:1188 +#: sql_help.c:1193 sql_help.c:1196 sql_help.c:1212 sql_help.c:1388 +#: sql_help.c:1412 sql_help.c:1465 sql_help.c:1473 sql_help.c:1493 +#: sql_help.c:1550 sql_help.c:1634 sql_help.c:1688 sql_help.c:1711 +#: sql_help.c:2332 sql_help.c:2390 sql_help.c:2399 sql_help.c:2408 +#: sql_help.c:2465 sql_help.c:2466 sql_help.c:2530 sql_help.c:2533 +#: sql_help.c:2567 sql_help.c:2668 sql_help.c:2669 sql_help.c:2692 +#: sql_help.c:2817 sql_help.c:2856 sql_help.c:2967 sql_help.c:2980 +#: sql_help.c:2994 sql_help.c:3040 sql_help.c:3048 sql_help.c:3070 +#: sql_help.c:3087 sql_help.c:3114 sql_help.c:3321 sql_help.c:4028 +#: sql_help.c:4773 sql_help.c:4774 sql_help.c:4775 sql_help.c:4776 msgid "value" msgstr "値" -#: sql_help.c:202 +#: sql_help.c:214 msgid "target_role" msgstr "対象のロール" -#: sql_help.c:203 sql_help.c:921 sql_help.c:2300 sql_help.c:2669 -#: sql_help.c:2742 sql_help.c:2747 sql_help.c:3920 sql_help.c:3929 -#: sql_help.c:3948 sql_help.c:3960 sql_help.c:4383 sql_help.c:4392 -#: sql_help.c:4411 sql_help.c:4423 +#: sql_help.c:215 sql_help.c:943 sql_help.c:2316 sql_help.c:2697 +#: sql_help.c:2770 sql_help.c:2775 sql_help.c:3958 sql_help.c:3967 +#: sql_help.c:3986 sql_help.c:3998 sql_help.c:4425 sql_help.c:4434 +#: sql_help.c:4453 sql_help.c:4465 msgid "schema_name" msgstr "スキーマ名" -#: sql_help.c:204 +#: sql_help.c:216 msgid "abbreviated_grant_or_revoke" msgstr "GRANT/REVOKEの省略形" -#: sql_help.c:205 +#: sql_help.c:217 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "GRANT/REVOKEの省略形は以下のいずれかです:" -#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 -#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 -#: sql_help.c:576 sql_help.c:612 sql_help.c:680 sql_help.c:830 sql_help.c:977 -#: sql_help.c:1336 sql_help.c:1684 sql_help.c:2475 sql_help.c:2476 -#: sql_help.c:2477 sql_help.c:2478 sql_help.c:2479 sql_help.c:2613 -#: sql_help.c:2700 sql_help.c:2701 sql_help.c:2702 sql_help.c:3267 -#: sql_help.c:3268 sql_help.c:3269 sql_help.c:3270 sql_help.c:3271 -#: sql_help.c:3969 sql_help.c:3973 sql_help.c:4432 sql_help.c:4436 -#: sql_help.c:4752 +#: sql_help.c:218 sql_help.c:219 sql_help.c:220 sql_help.c:221 sql_help.c:222 +#: sql_help.c:223 sql_help.c:224 sql_help.c:225 sql_help.c:226 sql_help.c:227 +#: sql_help.c:228 sql_help.c:229 sql_help.c:598 sql_help.c:634 sql_help.c:702 +#: sql_help.c:852 sql_help.c:999 sql_help.c:1354 sql_help.c:1698 +#: sql_help.c:2503 sql_help.c:2504 sql_help.c:2505 sql_help.c:2506 +#: sql_help.c:2507 sql_help.c:2641 sql_help.c:2728 sql_help.c:2729 +#: sql_help.c:2730 sql_help.c:3303 sql_help.c:3304 sql_help.c:3305 +#: sql_help.c:3306 sql_help.c:3307 sql_help.c:4007 sql_help.c:4011 +#: sql_help.c:4474 sql_help.c:4478 sql_help.c:4794 msgid "role_name" msgstr "ロール名" -#: sql_help.c:241 sql_help.c:464 sql_help.c:920 sql_help.c:1362 sql_help.c:1364 -#: sql_help.c:1368 sql_help.c:1418 sql_help.c:1430 sql_help.c:1455 -#: sql_help.c:1714 sql_help.c:2269 sql_help.c:2273 sql_help.c:2385 -#: sql_help.c:2390 sql_help.c:2498 sql_help.c:2668 sql_help.c:2803 -#: sql_help.c:2808 sql_help.c:2810 sql_help.c:2931 sql_help.c:2944 -#: sql_help.c:2958 sql_help.c:2967 sql_help.c:2979 sql_help.c:3008 -#: sql_help.c:4021 sql_help.c:4036 sql_help.c:4038 sql_help.c:4134 -#: sql_help.c:4137 sql_help.c:4139 sql_help.c:4602 sql_help.c:4603 -#: sql_help.c:4612 sql_help.c:4659 sql_help.c:4660 sql_help.c:4661 -#: sql_help.c:4662 sql_help.c:4663 sql_help.c:4664 sql_help.c:4705 -#: sql_help.c:4706 sql_help.c:4711 sql_help.c:4716 sql_help.c:4860 -#: sql_help.c:4861 sql_help.c:4870 sql_help.c:4917 sql_help.c:4918 -#: sql_help.c:4919 sql_help.c:4920 sql_help.c:4921 sql_help.c:4922 -#: sql_help.c:4977 sql_help.c:4979 sql_help.c:5045 sql_help.c:5105 -#: sql_help.c:5106 sql_help.c:5115 sql_help.c:5162 sql_help.c:5163 -#: sql_help.c:5164 sql_help.c:5165 sql_help.c:5166 sql_help.c:5167 +#: sql_help.c:260 sql_help.c:279 sql_help.c:486 sql_help.c:942 sql_help.c:1370 +#: sql_help.c:1372 sql_help.c:1376 sql_help.c:1427 sql_help.c:1439 +#: sql_help.c:1469 sql_help.c:1728 sql_help.c:2285 sql_help.c:2289 +#: sql_help.c:2411 sql_help.c:2417 sql_help.c:2526 sql_help.c:2696 +#: sql_help.c:2833 sql_help.c:2838 sql_help.c:2840 sql_help.c:2962 +#: sql_help.c:2975 sql_help.c:2989 sql_help.c:2998 sql_help.c:3010 +#: sql_help.c:3044 sql_help.c:4060 sql_help.c:4076 sql_help.c:4078 +#: sql_help.c:4176 sql_help.c:4179 sql_help.c:4181 sql_help.c:4644 +#: sql_help.c:4645 sql_help.c:4654 sql_help.c:4701 sql_help.c:4702 +#: sql_help.c:4703 sql_help.c:4704 sql_help.c:4705 sql_help.c:4706 +#: sql_help.c:4747 sql_help.c:4748 sql_help.c:4753 sql_help.c:4758 +#: sql_help.c:4902 sql_help.c:4903 sql_help.c:4912 sql_help.c:4959 +#: sql_help.c:4960 sql_help.c:4961 sql_help.c:4962 sql_help.c:4963 +#: sql_help.c:4964 sql_help.c:5020 sql_help.c:5022 sql_help.c:5089 +#: sql_help.c:5149 sql_help.c:5150 sql_help.c:5159 sql_help.c:5206 +#: sql_help.c:5207 sql_help.c:5208 sql_help.c:5209 sql_help.c:5210 +#: sql_help.c:5211 msgid "expression" msgstr "評価式" -#: sql_help.c:244 sql_help.c:2270 +#: sql_help.c:263 sql_help.c:2286 msgid "domain_constraint" msgstr "ドメイン制約" -#: sql_help.c:246 sql_help.c:248 sql_help.c:251 sql_help.c:479 sql_help.c:480 -#: sql_help.c:1329 sql_help.c:1388 sql_help.c:1389 sql_help.c:1390 -#: sql_help.c:1417 sql_help.c:1429 sql_help.c:1446 sql_help.c:1878 -#: sql_help.c:1880 sql_help.c:2272 sql_help.c:2384 sql_help.c:2389 -#: sql_help.c:2966 sql_help.c:2978 sql_help.c:4033 +#: sql_help.c:265 sql_help.c:267 sql_help.c:270 sql_help.c:278 sql_help.c:501 +#: sql_help.c:502 sql_help.c:1347 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:1398 sql_help.c:1399 sql_help.c:1426 sql_help.c:1438 +#: sql_help.c:1460 sql_help.c:1892 sql_help.c:1894 sql_help.c:2288 +#: sql_help.c:2410 sql_help.c:2415 sql_help.c:2997 sql_help.c:3009 +#: sql_help.c:4073 msgid "constraint_name" msgstr "制約名" -#: sql_help.c:249 sql_help.c:1330 +#: sql_help.c:268 sql_help.c:1348 msgid "new_constraint_name" msgstr "新しい制約名" -#: sql_help.c:322 sql_help.c:1107 +#: sql_help.c:277 sql_help.c:2287 +msgid "where domain_constraint is:" +msgstr "ドメイン制約は以下の通りです:" + +#: sql_help.c:344 sql_help.c:1130 msgid "new_version" msgstr "新しいバージョン" -#: sql_help.c:326 sql_help.c:328 +#: sql_help.c:348 sql_help.c:350 msgid "member_object" msgstr "メンバーオブジェクト" -#: sql_help.c:329 +#: sql_help.c:351 msgid "where member_object is:" msgstr "メンバーオブジェクトは以下の通りです:" -#: sql_help.c:330 sql_help.c:335 sql_help.c:336 sql_help.c:337 sql_help.c:338 -#: sql_help.c:339 sql_help.c:340 sql_help.c:345 sql_help.c:349 sql_help.c:351 -#: sql_help.c:353 sql_help.c:362 sql_help.c:363 sql_help.c:364 sql_help.c:365 -#: sql_help.c:366 sql_help.c:367 sql_help.c:368 sql_help.c:369 sql_help.c:372 -#: sql_help.c:373 sql_help.c:1870 sql_help.c:1875 sql_help.c:1882 -#: sql_help.c:1883 sql_help.c:1884 sql_help.c:1885 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1888 sql_help.c:1893 sql_help.c:1895 -#: sql_help.c:1899 sql_help.c:1901 sql_help.c:1905 sql_help.c:1910 -#: sql_help.c:1911 sql_help.c:1918 sql_help.c:1919 sql_help.c:1920 -#: sql_help.c:1921 sql_help.c:1922 sql_help.c:1923 sql_help.c:1924 -#: sql_help.c:1925 sql_help.c:1926 sql_help.c:1927 sql_help.c:1928 -#: sql_help.c:1933 sql_help.c:1934 sql_help.c:4505 sql_help.c:4510 -#: sql_help.c:4511 sql_help.c:4512 sql_help.c:4513 sql_help.c:4519 -#: sql_help.c:4520 sql_help.c:4525 sql_help.c:4526 sql_help.c:4531 -#: sql_help.c:4532 sql_help.c:4533 sql_help.c:4534 sql_help.c:4535 -#: sql_help.c:4536 +#: sql_help.c:352 sql_help.c:357 sql_help.c:358 sql_help.c:359 sql_help.c:360 +#: sql_help.c:361 sql_help.c:362 sql_help.c:367 sql_help.c:371 sql_help.c:373 +#: sql_help.c:375 sql_help.c:384 sql_help.c:385 sql_help.c:386 sql_help.c:387 +#: sql_help.c:388 sql_help.c:389 sql_help.c:390 sql_help.c:391 sql_help.c:394 +#: sql_help.c:395 sql_help.c:1884 sql_help.c:1889 sql_help.c:1896 +#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 +#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1907 sql_help.c:1909 +#: sql_help.c:1913 sql_help.c:1915 sql_help.c:1919 sql_help.c:1924 +#: sql_help.c:1925 sql_help.c:1932 sql_help.c:1933 sql_help.c:1934 +#: sql_help.c:1935 sql_help.c:1936 sql_help.c:1937 sql_help.c:1938 +#: sql_help.c:1939 sql_help.c:1940 sql_help.c:1941 sql_help.c:1942 +#: sql_help.c:1947 sql_help.c:1948 sql_help.c:4547 sql_help.c:4552 +#: sql_help.c:4553 sql_help.c:4554 sql_help.c:4555 sql_help.c:4561 +#: sql_help.c:4562 sql_help.c:4567 sql_help.c:4568 sql_help.c:4573 +#: sql_help.c:4574 sql_help.c:4575 sql_help.c:4576 sql_help.c:4577 +#: sql_help.c:4578 msgid "object_name" msgstr "オブジェクト名" -#: sql_help.c:331 sql_help.c:1871 sql_help.c:4508 +#: sql_help.c:353 sql_help.c:1885 sql_help.c:4550 msgid "aggregate_name" msgstr "集約関数名" -#: sql_help.c:333 sql_help.c:1873 sql_help.c:2163 sql_help.c:2167 -#: sql_help.c:2169 sql_help.c:3394 +#: sql_help.c:355 sql_help.c:1887 sql_help.c:2179 sql_help.c:2183 +#: sql_help.c:2185 sql_help.c:3432 msgid "source_type" msgstr "変換前の型" -#: sql_help.c:334 sql_help.c:1874 sql_help.c:2164 sql_help.c:2168 -#: sql_help.c:2170 sql_help.c:3395 +#: sql_help.c:356 sql_help.c:1888 sql_help.c:2180 sql_help.c:2184 +#: sql_help.c:2186 sql_help.c:3433 msgid "target_type" msgstr "変換後の型" -#: sql_help.c:341 sql_help.c:794 sql_help.c:1889 sql_help.c:2165 -#: sql_help.c:2208 sql_help.c:2288 sql_help.c:2556 sql_help.c:2587 -#: sql_help.c:3154 sql_help.c:4407 sql_help.c:4514 sql_help.c:4631 -#: sql_help.c:4635 sql_help.c:4639 sql_help.c:4642 sql_help.c:4889 -#: sql_help.c:4893 sql_help.c:4897 sql_help.c:4900 sql_help.c:5134 -#: sql_help.c:5138 sql_help.c:5142 sql_help.c:5145 +#: sql_help.c:363 sql_help.c:816 sql_help.c:1903 sql_help.c:2181 +#: sql_help.c:2224 sql_help.c:2304 sql_help.c:2584 sql_help.c:2615 +#: sql_help.c:3190 sql_help.c:4449 sql_help.c:4556 sql_help.c:4673 +#: sql_help.c:4677 sql_help.c:4681 sql_help.c:4684 sql_help.c:4931 +#: sql_help.c:4935 sql_help.c:4939 sql_help.c:4942 sql_help.c:5178 +#: sql_help.c:5182 sql_help.c:5186 sql_help.c:5189 msgid "function_name" msgstr "関数名" -#: sql_help.c:346 sql_help.c:787 sql_help.c:1896 sql_help.c:2580 +#: sql_help.c:368 sql_help.c:809 sql_help.c:1910 sql_help.c:2608 msgid "operator_name" msgstr "演算子名" -#: sql_help.c:347 sql_help.c:721 sql_help.c:725 sql_help.c:729 sql_help.c:1897 -#: sql_help.c:2557 sql_help.c:3518 +#: sql_help.c:369 sql_help.c:743 sql_help.c:747 sql_help.c:751 sql_help.c:1911 +#: sql_help.c:2585 sql_help.c:3556 msgid "left_type" msgstr "左辺の型" -#: sql_help.c:348 sql_help.c:722 sql_help.c:726 sql_help.c:730 sql_help.c:1898 -#: sql_help.c:2558 sql_help.c:3519 +#: sql_help.c:370 sql_help.c:744 sql_help.c:748 sql_help.c:752 sql_help.c:1912 +#: sql_help.c:2586 sql_help.c:3557 msgid "right_type" msgstr "右辺の型" -#: sql_help.c:350 sql_help.c:352 sql_help.c:750 sql_help.c:753 sql_help.c:756 -#: sql_help.c:785 sql_help.c:797 sql_help.c:805 sql_help.c:808 sql_help.c:811 -#: sql_help.c:1435 sql_help.c:1900 sql_help.c:1902 sql_help.c:2577 -#: sql_help.c:2598 sql_help.c:2984 sql_help.c:3528 sql_help.c:3537 +#: sql_help.c:372 sql_help.c:374 sql_help.c:772 sql_help.c:775 sql_help.c:778 +#: sql_help.c:807 sql_help.c:819 sql_help.c:827 sql_help.c:830 sql_help.c:833 +#: sql_help.c:1447 sql_help.c:1914 sql_help.c:1916 sql_help.c:2605 +#: sql_help.c:2626 sql_help.c:3018 sql_help.c:3566 sql_help.c:3575 msgid "index_method" msgstr "インデックスメソッド" -#: sql_help.c:354 sql_help.c:1906 sql_help.c:4521 +#: sql_help.c:376 sql_help.c:1920 sql_help.c:4563 msgid "procedure_name" msgstr "プロシージャ名" -#: sql_help.c:358 sql_help.c:1912 sql_help.c:3944 sql_help.c:4527 +#: sql_help.c:380 sql_help.c:1926 sql_help.c:3982 sql_help.c:4569 msgid "routine_name" msgstr "ルーチン名" -#: sql_help.c:370 sql_help.c:1407 sql_help.c:1929 sql_help.c:2432 -#: sql_help.c:2638 sql_help.c:2939 sql_help.c:3121 sql_help.c:3699 -#: sql_help.c:3966 sql_help.c:4429 +#: sql_help.c:392 sql_help.c:1416 sql_help.c:1943 sql_help.c:2460 +#: sql_help.c:2666 sql_help.c:2970 sql_help.c:3157 sql_help.c:3737 +#: sql_help.c:4004 sql_help.c:4471 msgid "type_name" msgstr "型名" -#: sql_help.c:371 sql_help.c:1930 sql_help.c:2431 sql_help.c:2637 -#: sql_help.c:3122 sql_help.c:3352 sql_help.c:3700 sql_help.c:3951 -#: sql_help.c:4414 +#: sql_help.c:393 sql_help.c:1944 sql_help.c:2459 sql_help.c:2665 +#: sql_help.c:3158 sql_help.c:3390 sql_help.c:3738 sql_help.c:3989 +#: sql_help.c:4456 msgid "lang_name" msgstr "言語名" -#: sql_help.c:374 +#: sql_help.c:396 msgid "and aggregate_signature is:" msgstr "集約関数のシグニチャーは以下の通りです:" -#: sql_help.c:397 sql_help.c:2030 sql_help.c:2313 +#: sql_help.c:419 sql_help.c:2046 sql_help.c:2329 msgid "handler_function" msgstr "ハンドラー関数" -#: sql_help.c:398 sql_help.c:2314 +#: sql_help.c:420 sql_help.c:2330 msgid "validator_function" msgstr "バリデーター関数" -#: sql_help.c:446 sql_help.c:525 sql_help.c:669 sql_help.c:861 sql_help.c:1011 -#: sql_help.c:1324 sql_help.c:1611 +#: sql_help.c:468 sql_help.c:547 sql_help.c:691 sql_help.c:883 sql_help.c:1033 +#: sql_help.c:1342 sql_help.c:1625 msgid "action" msgstr "アクション" -#: sql_help.c:448 sql_help.c:455 sql_help.c:459 sql_help.c:460 sql_help.c:463 -#: sql_help.c:465 sql_help.c:466 sql_help.c:467 sql_help.c:469 sql_help.c:472 -#: sql_help.c:474 sql_help.c:475 sql_help.c:673 sql_help.c:683 sql_help.c:685 -#: sql_help.c:688 sql_help.c:690 sql_help.c:691 sql_help.c:919 sql_help.c:1088 -#: sql_help.c:1326 sql_help.c:1354 sql_help.c:1358 sql_help.c:1359 -#: sql_help.c:1363 sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 -#: sql_help.c:1369 sql_help.c:1370 sql_help.c:1372 sql_help.c:1375 -#: sql_help.c:1376 sql_help.c:1378 sql_help.c:1381 sql_help.c:1383 -#: sql_help.c:1384 sql_help.c:1431 sql_help.c:1433 sql_help.c:1440 -#: sql_help.c:1449 sql_help.c:1454 sql_help.c:1461 sql_help.c:1462 -#: sql_help.c:1713 sql_help.c:1716 sql_help.c:1720 sql_help.c:1756 -#: sql_help.c:1877 sql_help.c:1993 sql_help.c:1999 sql_help.c:2013 -#: sql_help.c:2014 sql_help.c:2015 sql_help.c:2363 sql_help.c:2376 -#: sql_help.c:2429 sql_help.c:2497 sql_help.c:2503 sql_help.c:2536 -#: sql_help.c:2667 sql_help.c:2772 sql_help.c:2807 sql_help.c:2809 -#: sql_help.c:2921 sql_help.c:2930 sql_help.c:2940 sql_help.c:2943 -#: sql_help.c:2953 sql_help.c:2957 sql_help.c:2980 sql_help.c:2982 -#: sql_help.c:2989 sql_help.c:3002 sql_help.c:3007 sql_help.c:3014 -#: sql_help.c:3015 sql_help.c:3031 sql_help.c:3157 sql_help.c:3297 -#: sql_help.c:3923 sql_help.c:3924 sql_help.c:4020 sql_help.c:4035 -#: sql_help.c:4037 sql_help.c:4039 sql_help.c:4133 sql_help.c:4136 -#: sql_help.c:4138 sql_help.c:4140 sql_help.c:4386 sql_help.c:4387 -#: sql_help.c:4507 sql_help.c:4668 sql_help.c:4675 sql_help.c:4677 -#: sql_help.c:4926 sql_help.c:4933 sql_help.c:4935 sql_help.c:4976 -#: sql_help.c:4978 sql_help.c:4980 sql_help.c:5033 sql_help.c:5171 -#: sql_help.c:5178 sql_help.c:5180 +#: sql_help.c:470 sql_help.c:477 sql_help.c:481 sql_help.c:482 sql_help.c:485 +#: sql_help.c:487 sql_help.c:488 sql_help.c:489 sql_help.c:491 sql_help.c:494 +#: sql_help.c:496 sql_help.c:497 sql_help.c:695 sql_help.c:705 sql_help.c:707 +#: sql_help.c:710 sql_help.c:712 sql_help.c:713 sql_help.c:941 sql_help.c:1111 +#: sql_help.c:1344 sql_help.c:1362 sql_help.c:1366 sql_help.c:1367 +#: sql_help.c:1371 sql_help.c:1373 sql_help.c:1374 sql_help.c:1375 +#: sql_help.c:1377 sql_help.c:1378 sql_help.c:1380 sql_help.c:1383 +#: sql_help.c:1384 sql_help.c:1386 sql_help.c:1389 sql_help.c:1391 +#: sql_help.c:1392 sql_help.c:1440 sql_help.c:1441 sql_help.c:1442 +#: sql_help.c:1444 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1463 sql_help.c:1468 sql_help.c:1475 sql_help.c:1476 +#: sql_help.c:1727 sql_help.c:1730 sql_help.c:1734 sql_help.c:1770 +#: sql_help.c:1891 sql_help.c:2008 sql_help.c:2014 sql_help.c:2028 +#: sql_help.c:2029 sql_help.c:2030 sql_help.c:2387 sql_help.c:2402 +#: sql_help.c:2416 sql_help.c:2457 sql_help.c:2525 sql_help.c:2531 +#: sql_help.c:2564 sql_help.c:2695 sql_help.c:2802 sql_help.c:2837 +#: sql_help.c:2839 sql_help.c:2952 sql_help.c:2961 sql_help.c:2971 +#: sql_help.c:2974 sql_help.c:2984 sql_help.c:2988 sql_help.c:3011 +#: sql_help.c:3012 sql_help.c:3013 sql_help.c:3015 sql_help.c:3016 +#: sql_help.c:3023 sql_help.c:3024 sql_help.c:3038 sql_help.c:3043 +#: sql_help.c:3050 sql_help.c:3051 sql_help.c:3067 sql_help.c:3193 +#: sql_help.c:3333 sql_help.c:3961 sql_help.c:3962 sql_help.c:4059 +#: sql_help.c:4075 sql_help.c:4077 sql_help.c:4079 sql_help.c:4175 +#: sql_help.c:4178 sql_help.c:4180 sql_help.c:4182 sql_help.c:4428 +#: sql_help.c:4429 sql_help.c:4549 sql_help.c:4710 sql_help.c:4717 +#: sql_help.c:4719 sql_help.c:4968 sql_help.c:4975 sql_help.c:4977 +#: sql_help.c:5019 sql_help.c:5021 sql_help.c:5023 sql_help.c:5077 +#: sql_help.c:5215 sql_help.c:5222 sql_help.c:5224 msgid "column_name" msgstr "列名" -#: sql_help.c:449 sql_help.c:674 sql_help.c:1327 sql_help.c:1721 +#: sql_help.c:471 sql_help.c:696 sql_help.c:1345 sql_help.c:1735 msgid "new_column_name" msgstr "新しい列名" -#: sql_help.c:454 sql_help.c:546 sql_help.c:682 sql_help.c:882 sql_help.c:1032 -#: sql_help.c:1353 sql_help.c:1621 +#: sql_help.c:476 sql_help.c:568 sql_help.c:704 sql_help.c:904 sql_help.c:1054 +#: sql_help.c:1361 sql_help.c:1635 msgid "where action is one of:" msgstr "アクションは以下のいずれかです:" -#: sql_help.c:456 sql_help.c:461 sql_help.c:1080 sql_help.c:1355 -#: sql_help.c:1360 sql_help.c:1623 sql_help.c:1627 sql_help.c:2267 -#: sql_help.c:2364 sql_help.c:2576 sql_help.c:2765 sql_help.c:2922 -#: sql_help.c:3204 sql_help.c:4192 +#: sql_help.c:478 sql_help.c:483 sql_help.c:1103 sql_help.c:1363 +#: sql_help.c:1368 sql_help.c:1637 sql_help.c:1641 sql_help.c:2283 +#: sql_help.c:2388 sql_help.c:2604 sql_help.c:2795 sql_help.c:2953 +#: sql_help.c:3240 sql_help.c:4234 msgid "data_type" msgstr "データ型" -#: sql_help.c:457 sql_help.c:462 sql_help.c:1356 sql_help.c:1361 -#: sql_help.c:1456 sql_help.c:1624 sql_help.c:1628 sql_help.c:2268 -#: sql_help.c:2367 sql_help.c:2499 sql_help.c:2924 sql_help.c:2932 -#: sql_help.c:2945 sql_help.c:2959 sql_help.c:3009 sql_help.c:3205 -#: sql_help.c:3211 sql_help.c:4030 +#: sql_help.c:479 sql_help.c:484 sql_help.c:1364 sql_help.c:1369 +#: sql_help.c:1470 sql_help.c:1638 sql_help.c:1642 sql_help.c:2284 +#: sql_help.c:2391 sql_help.c:2527 sql_help.c:2955 sql_help.c:2963 +#: sql_help.c:2976 sql_help.c:2990 sql_help.c:3045 sql_help.c:3241 +#: sql_help.c:3247 sql_help.c:4070 msgid "collation" msgstr "照合順序" -#: sql_help.c:458 sql_help.c:1357 sql_help.c:2368 sql_help.c:2377 -#: sql_help.c:2925 sql_help.c:2941 sql_help.c:2954 +#: sql_help.c:480 sql_help.c:1365 sql_help.c:2392 sql_help.c:2403 +#: sql_help.c:2956 sql_help.c:2972 sql_help.c:2985 msgid "column_constraint" msgstr "カラム制約" -#: sql_help.c:468 sql_help.c:610 sql_help.c:684 sql_help.c:1377 sql_help.c:5027 +#: sql_help.c:490 sql_help.c:632 sql_help.c:706 sql_help.c:1385 sql_help.c:5071 msgid "integer" msgstr "整数" -#: sql_help.c:470 sql_help.c:473 sql_help.c:686 sql_help.c:689 sql_help.c:1379 -#: sql_help.c:1382 +#: sql_help.c:492 sql_help.c:495 sql_help.c:708 sql_help.c:711 sql_help.c:1387 +#: sql_help.c:1390 msgid "attribute_option" msgstr "属性オプション" -#: sql_help.c:478 sql_help.c:1386 sql_help.c:2369 sql_help.c:2378 -#: sql_help.c:2926 sql_help.c:2942 sql_help.c:2955 +#: sql_help.c:500 sql_help.c:1394 sql_help.c:2393 sql_help.c:2404 +#: sql_help.c:2957 sql_help.c:2973 sql_help.c:2986 msgid "table_constraint" msgstr "テーブル制約" -#: sql_help.c:481 sql_help.c:482 sql_help.c:483 sql_help.c:484 sql_help.c:1391 -#: sql_help.c:1392 sql_help.c:1393 sql_help.c:1394 sql_help.c:1931 +#: sql_help.c:503 sql_help.c:504 sql_help.c:505 sql_help.c:506 sql_help.c:1400 +#: sql_help.c:1401 sql_help.c:1402 sql_help.c:1403 sql_help.c:1945 msgid "trigger_name" msgstr "トリガー名" -#: sql_help.c:485 sql_help.c:486 sql_help.c:1405 sql_help.c:1406 -#: sql_help.c:2370 sql_help.c:2375 sql_help.c:2929 sql_help.c:2952 +#: sql_help.c:507 sql_help.c:508 sql_help.c:1414 sql_help.c:1415 +#: sql_help.c:2396 sql_help.c:2401 sql_help.c:2960 sql_help.c:2983 msgid "parent_table" msgstr "親テーブル" -#: sql_help.c:545 sql_help.c:602 sql_help.c:671 sql_help.c:881 sql_help.c:1031 -#: sql_help.c:1580 sql_help.c:2299 +#: sql_help.c:567 sql_help.c:624 sql_help.c:693 sql_help.c:903 sql_help.c:1053 +#: sql_help.c:1594 sql_help.c:2315 msgid "extension_name" msgstr "拡張名" -#: sql_help.c:547 sql_help.c:1033 sql_help.c:2433 +#: sql_help.c:569 sql_help.c:1055 sql_help.c:2461 msgid "execution_cost" msgstr "実行コスト" -#: sql_help.c:548 sql_help.c:1034 sql_help.c:2434 +#: sql_help.c:570 sql_help.c:1056 sql_help.c:2462 msgid "result_rows" msgstr "結果の行数" -#: sql_help.c:549 sql_help.c:2435 +#: sql_help.c:571 sql_help.c:2463 msgid "support_function" msgstr "サポート関数" -#: sql_help.c:571 sql_help.c:573 sql_help.c:956 sql_help.c:964 sql_help.c:968 -#: sql_help.c:971 sql_help.c:974 sql_help.c:1663 sql_help.c:1671 -#: sql_help.c:1675 sql_help.c:1678 sql_help.c:1681 sql_help.c:2743 -#: sql_help.c:2745 sql_help.c:2748 sql_help.c:2749 sql_help.c:3921 -#: sql_help.c:3922 sql_help.c:3926 sql_help.c:3927 sql_help.c:3930 -#: sql_help.c:3931 sql_help.c:3933 sql_help.c:3934 sql_help.c:3936 -#: sql_help.c:3937 sql_help.c:3939 sql_help.c:3940 sql_help.c:3942 -#: sql_help.c:3943 sql_help.c:3949 sql_help.c:3950 sql_help.c:3952 -#: sql_help.c:3953 sql_help.c:3955 sql_help.c:3956 sql_help.c:3958 -#: sql_help.c:3959 sql_help.c:3961 sql_help.c:3962 sql_help.c:3964 -#: sql_help.c:3965 sql_help.c:3967 sql_help.c:3968 sql_help.c:3970 -#: sql_help.c:3971 sql_help.c:4384 sql_help.c:4385 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4393 sql_help.c:4394 sql_help.c:4396 -#: sql_help.c:4397 sql_help.c:4399 sql_help.c:4400 sql_help.c:4402 -#: sql_help.c:4403 sql_help.c:4405 sql_help.c:4406 sql_help.c:4412 -#: sql_help.c:4413 sql_help.c:4415 sql_help.c:4416 sql_help.c:4418 -#: sql_help.c:4419 sql_help.c:4421 sql_help.c:4422 sql_help.c:4424 -#: sql_help.c:4425 sql_help.c:4427 sql_help.c:4428 sql_help.c:4430 -#: sql_help.c:4431 sql_help.c:4433 sql_help.c:4434 +#: sql_help.c:593 sql_help.c:595 sql_help.c:978 sql_help.c:986 sql_help.c:990 +#: sql_help.c:993 sql_help.c:996 sql_help.c:1677 sql_help.c:1685 +#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1695 sql_help.c:2771 +#: sql_help.c:2773 sql_help.c:2776 sql_help.c:2777 sql_help.c:3959 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:3965 sql_help.c:3968 +#: sql_help.c:3969 sql_help.c:3971 sql_help.c:3972 sql_help.c:3974 +#: sql_help.c:3975 sql_help.c:3977 sql_help.c:3978 sql_help.c:3980 +#: sql_help.c:3981 sql_help.c:3987 sql_help.c:3988 sql_help.c:3990 +#: sql_help.c:3991 sql_help.c:3993 sql_help.c:3994 sql_help.c:3996 +#: sql_help.c:3997 sql_help.c:3999 sql_help.c:4000 sql_help.c:4002 +#: sql_help.c:4003 sql_help.c:4005 sql_help.c:4006 sql_help.c:4008 +#: sql_help.c:4009 sql_help.c:4426 sql_help.c:4427 sql_help.c:4431 +#: sql_help.c:4432 sql_help.c:4435 sql_help.c:4436 sql_help.c:4438 +#: sql_help.c:4439 sql_help.c:4441 sql_help.c:4442 sql_help.c:4444 +#: sql_help.c:4445 sql_help.c:4447 sql_help.c:4448 sql_help.c:4454 +#: sql_help.c:4455 sql_help.c:4457 sql_help.c:4458 sql_help.c:4460 +#: sql_help.c:4461 sql_help.c:4463 sql_help.c:4464 sql_help.c:4466 +#: sql_help.c:4467 sql_help.c:4469 sql_help.c:4470 sql_help.c:4472 +#: sql_help.c:4473 sql_help.c:4475 sql_help.c:4476 msgid "role_specification" msgstr "ロールの指定" -#: sql_help.c:572 sql_help.c:574 sql_help.c:1694 sql_help.c:2234 -#: sql_help.c:2751 sql_help.c:3282 sql_help.c:3733 sql_help.c:4762 +#: sql_help.c:594 sql_help.c:596 sql_help.c:1708 sql_help.c:2250 +#: sql_help.c:2779 sql_help.c:3318 sql_help.c:3771 sql_help.c:4804 msgid "user_name" msgstr "ユーザー名" -#: sql_help.c:575 sql_help.c:976 sql_help.c:1683 sql_help.c:2750 -#: sql_help.c:3972 sql_help.c:4435 +#: sql_help.c:597 sql_help.c:998 sql_help.c:1697 sql_help.c:2778 +#: sql_help.c:4010 sql_help.c:4477 msgid "where role_specification can be:" msgstr "ロール指定は以下の通りです:" -#: sql_help.c:577 +#: sql_help.c:599 msgid "group_name" msgstr "グループ名" -#: sql_help.c:598 sql_help.c:1452 sql_help.c:2246 sql_help.c:2506 -#: sql_help.c:2540 sql_help.c:2937 sql_help.c:2950 sql_help.c:2964 -#: sql_help.c:3005 sql_help.c:3035 sql_help.c:3047 sql_help.c:3963 -#: sql_help.c:4426 +#: sql_help.c:620 sql_help.c:1466 sql_help.c:2262 sql_help.c:2534 +#: sql_help.c:2568 sql_help.c:2968 sql_help.c:2981 sql_help.c:2995 +#: sql_help.c:3041 sql_help.c:3071 sql_help.c:3083 sql_help.c:4001 +#: sql_help.c:4468 msgid "tablespace_name" msgstr "テーブル空間名" -#: sql_help.c:600 sql_help.c:693 sql_help.c:1399 sql_help.c:1409 -#: sql_help.c:1447 sql_help.c:1809 +#: sql_help.c:622 sql_help.c:715 sql_help.c:1408 sql_help.c:1418 +#: sql_help.c:1461 sql_help.c:1823 msgid "index_name" msgstr "インデックス名" -#: sql_help.c:604 sql_help.c:607 sql_help.c:696 sql_help.c:698 sql_help.c:1402 -#: sql_help.c:1404 sql_help.c:1450 sql_help.c:2504 sql_help.c:2538 -#: sql_help.c:2935 sql_help.c:2948 sql_help.c:2962 sql_help.c:3003 -#: sql_help.c:3033 +#: sql_help.c:626 sql_help.c:629 sql_help.c:718 sql_help.c:720 sql_help.c:1411 +#: sql_help.c:1413 sql_help.c:1464 sql_help.c:2532 sql_help.c:2566 +#: sql_help.c:2966 sql_help.c:2979 sql_help.c:2993 sql_help.c:3039 +#: sql_help.c:3069 msgid "storage_parameter" msgstr "ストレージパラメータ" -#: sql_help.c:609 +#: sql_help.c:631 msgid "column_number" msgstr "列番号" -#: sql_help.c:633 sql_help.c:1894 sql_help.c:4518 +#: sql_help.c:655 sql_help.c:1908 sql_help.c:4560 msgid "large_object_oid" msgstr "ラージオブジェクトのOID" -#: sql_help.c:692 sql_help.c:1385 sql_help.c:2923 +#: sql_help.c:714 sql_help.c:1393 sql_help.c:2954 msgid "compression_method" msgstr "圧縮方式" -#: sql_help.c:694 sql_help.c:1400 +#: sql_help.c:716 sql_help.c:1409 msgid "new_access_method" msgstr "新しいアクセスメソッド" -#: sql_help.c:731 sql_help.c:2561 +#: sql_help.c:753 sql_help.c:2589 msgid "res_proc" msgstr "制約選択評価関数" -#: sql_help.c:732 sql_help.c:2562 +#: sql_help.c:754 sql_help.c:2590 msgid "join_proc" msgstr "結合選択評価関数" -#: sql_help.c:733 sql_help.c:2559 +#: sql_help.c:755 sql_help.c:2587 msgid "com_op" msgstr "交代演算子" -#: sql_help.c:734 sql_help.c:2560 +#: sql_help.c:756 sql_help.c:2588 msgid "neg_op" msgstr "否定演算子" -#: sql_help.c:786 sql_help.c:798 sql_help.c:2579 +#: sql_help.c:808 sql_help.c:820 sql_help.c:2607 msgid "strategy_number" msgstr "戦略番号" -#: sql_help.c:788 sql_help.c:789 sql_help.c:792 sql_help.c:793 sql_help.c:799 -#: sql_help.c:800 sql_help.c:802 sql_help.c:803 sql_help.c:2581 sql_help.c:2582 -#: sql_help.c:2585 sql_help.c:2586 +#: sql_help.c:810 sql_help.c:811 sql_help.c:814 sql_help.c:815 sql_help.c:821 +#: sql_help.c:822 sql_help.c:824 sql_help.c:825 sql_help.c:2609 sql_help.c:2610 +#: sql_help.c:2613 sql_help.c:2614 msgid "op_type" msgstr "演算子の型" -#: sql_help.c:790 sql_help.c:2583 +#: sql_help.c:812 sql_help.c:2611 msgid "sort_family_name" msgstr "ソートファミリー名" -#: sql_help.c:791 sql_help.c:801 sql_help.c:2584 +#: sql_help.c:813 sql_help.c:823 sql_help.c:2612 msgid "support_number" msgstr "サポート番号" -#: sql_help.c:795 sql_help.c:2166 sql_help.c:2588 sql_help.c:3124 -#: sql_help.c:3126 +#: sql_help.c:817 sql_help.c:2182 sql_help.c:2616 sql_help.c:3160 +#: sql_help.c:3162 msgid "argument_type" msgstr "引数の型" -#: sql_help.c:826 sql_help.c:829 sql_help.c:918 sql_help.c:1047 sql_help.c:1087 -#: sql_help.c:1576 sql_help.c:1579 sql_help.c:1755 sql_help.c:1808 -#: sql_help.c:1879 sql_help.c:1904 sql_help.c:1917 sql_help.c:1932 -#: sql_help.c:1992 sql_help.c:1998 sql_help.c:2362 sql_help.c:2374 -#: sql_help.c:2495 sql_help.c:2535 sql_help.c:2612 sql_help.c:2666 -#: sql_help.c:2719 sql_help.c:2771 sql_help.c:2804 sql_help.c:2811 -#: sql_help.c:2920 sql_help.c:2938 sql_help.c:2951 sql_help.c:3030 -#: sql_help.c:3150 sql_help.c:3331 sql_help.c:3554 sql_help.c:3603 -#: sql_help.c:3709 sql_help.c:3919 sql_help.c:3925 sql_help.c:3986 -#: sql_help.c:4018 sql_help.c:4382 sql_help.c:4388 sql_help.c:4506 -#: sql_help.c:4619 sql_help.c:4682 sql_help.c:4721 sql_help.c:4877 -#: sql_help.c:4940 sql_help.c:4974 sql_help.c:5032 sql_help.c:5122 -#: sql_help.c:5185 +#: sql_help.c:848 sql_help.c:851 sql_help.c:940 sql_help.c:1069 sql_help.c:1110 +#: sql_help.c:1590 sql_help.c:1593 sql_help.c:1769 sql_help.c:1822 +#: sql_help.c:1893 sql_help.c:1918 sql_help.c:1931 sql_help.c:1946 +#: sql_help.c:2007 sql_help.c:2013 sql_help.c:2386 sql_help.c:2400 +#: sql_help.c:2523 sql_help.c:2563 sql_help.c:2640 sql_help.c:2694 +#: sql_help.c:2747 sql_help.c:2801 sql_help.c:2834 sql_help.c:2841 +#: sql_help.c:2951 sql_help.c:2969 sql_help.c:2982 sql_help.c:3066 +#: sql_help.c:3186 sql_help.c:3368 sql_help.c:3592 sql_help.c:3641 +#: sql_help.c:3747 sql_help.c:3957 sql_help.c:3963 sql_help.c:4024 +#: sql_help.c:4057 sql_help.c:4424 sql_help.c:4430 sql_help.c:4548 +#: sql_help.c:4661 sql_help.c:4724 sql_help.c:4763 sql_help.c:4919 +#: sql_help.c:4982 sql_help.c:5017 sql_help.c:5076 sql_help.c:5166 +#: sql_help.c:5229 msgid "table_name" msgstr "テーブル名" -#: sql_help.c:831 sql_help.c:2614 +#: sql_help.c:853 sql_help.c:2642 msgid "using_expression" msgstr "USING式" -#: sql_help.c:832 sql_help.c:2615 +#: sql_help.c:854 sql_help.c:2643 msgid "check_expression" msgstr "CHECK式" -#: sql_help.c:905 sql_help.c:907 sql_help.c:909 sql_help.c:2662 +#: sql_help.c:927 sql_help.c:929 sql_help.c:931 sql_help.c:2690 msgid "publication_object" msgstr "発行オブジェクト" -#: sql_help.c:911 sql_help.c:2663 +#: sql_help.c:933 sql_help.c:2691 msgid "publication_parameter" msgstr "パブリケーションパラメータ" -#: sql_help.c:917 sql_help.c:2665 +#: sql_help.c:939 sql_help.c:2693 msgid "where publication_object is one of:" msgstr "発行オブジェクトは以下のいずれかです:" -#: sql_help.c:960 sql_help.c:1667 sql_help.c:2473 sql_help.c:2698 -#: sql_help.c:3265 +#: sql_help.c:982 sql_help.c:1681 sql_help.c:2501 sql_help.c:2726 +#: sql_help.c:3301 msgid "password" msgstr "パスワード" -#: sql_help.c:961 sql_help.c:1668 sql_help.c:2474 sql_help.c:2699 -#: sql_help.c:3266 +#: sql_help.c:983 sql_help.c:1682 sql_help.c:2502 sql_help.c:2727 +#: sql_help.c:3302 msgid "timestamp" msgstr "タイムスタンプ" -#: sql_help.c:965 sql_help.c:969 sql_help.c:972 sql_help.c:975 sql_help.c:1672 -#: sql_help.c:1676 sql_help.c:1679 sql_help.c:1682 sql_help.c:3932 -#: sql_help.c:4395 +#: sql_help.c:987 sql_help.c:991 sql_help.c:994 sql_help.c:997 sql_help.c:1686 +#: sql_help.c:1690 sql_help.c:1693 sql_help.c:1696 sql_help.c:3970 +#: sql_help.c:4437 msgid "database_name" msgstr "データベース名" -#: sql_help.c:1081 sql_help.c:2766 +#: sql_help.c:1104 sql_help.c:2796 msgid "increment" msgstr "増分値" -#: sql_help.c:1082 sql_help.c:2767 +#: sql_help.c:1105 sql_help.c:2797 msgid "minvalue" msgstr "最小値" -#: sql_help.c:1083 sql_help.c:2768 +#: sql_help.c:1106 sql_help.c:2798 msgid "maxvalue" msgstr "最大値" -#: sql_help.c:1084 sql_help.c:2769 sql_help.c:4615 sql_help.c:4719 -#: sql_help.c:4873 sql_help.c:5049 sql_help.c:5118 +#: sql_help.c:1107 sql_help.c:2799 sql_help.c:4657 sql_help.c:4761 +#: sql_help.c:4915 sql_help.c:5093 sql_help.c:5162 msgid "start" msgstr "開始番号" -#: sql_help.c:1085 sql_help.c:1374 +#: sql_help.c:1108 sql_help.c:1382 msgid "restart" msgstr "再開始番号" -#: sql_help.c:1086 sql_help.c:2770 +#: sql_help.c:1109 sql_help.c:2800 msgid "cache" msgstr "キャッシュ割り当て数" -#: sql_help.c:1131 +#: sql_help.c:1154 msgid "new_target" msgstr "新しいターゲット" -#: sql_help.c:1150 sql_help.c:2823 +#: sql_help.c:1173 sql_help.c:2853 msgid "conninfo" msgstr "接続文字列" -#: sql_help.c:1152 sql_help.c:1156 sql_help.c:1160 sql_help.c:2824 +#: sql_help.c:1175 sql_help.c:1179 sql_help.c:1183 sql_help.c:2854 msgid "publication_name" msgstr "パブリケーション名" -#: sql_help.c:1153 sql_help.c:1157 sql_help.c:1161 +#: sql_help.c:1176 sql_help.c:1180 sql_help.c:1184 msgid "publication_option" msgstr "パブリケーション・オプション" -#: sql_help.c:1164 +#: sql_help.c:1187 msgid "refresh_option" msgstr "{REFRESH PUBLICATION の追加オプション}" -#: sql_help.c:1169 sql_help.c:2825 +#: sql_help.c:1192 sql_help.c:2855 msgid "subscription_parameter" msgstr "{SUBSCRIPTION パラメータ名}" -#: sql_help.c:1172 +#: sql_help.c:1195 msgid "skip_option" msgstr "スキップオプション" -#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1344 sql_help.c:1352 +#: sql_help.c:1357 sql_help.c:1360 msgid "partition_name" msgstr "パーティション名" -#: sql_help.c:1340 sql_help.c:1346 sql_help.c:1348 sql_help.c:2379 -#: sql_help.c:2956 +#: sql_help.c:1358 sql_help.c:2405 sql_help.c:2987 msgid "partition_bound_spec" msgstr "パーティション境界の仕様" -#: sql_help.c:1345 sql_help.c:1350 -msgid "partition_name1" -msgstr "パーティション名1" - -#: sql_help.c:1347 sql_help.c:1351 -msgid "partition_name2" -msgstr "パーティション名2" - -#: sql_help.c:1371 sql_help.c:1421 sql_help.c:2970 +#: sql_help.c:1379 sql_help.c:1430 sql_help.c:3001 msgid "sequence_options" msgstr "シーケンスオプション" -#: sql_help.c:1373 +#: sql_help.c:1381 msgid "sequence_option" msgstr "シーケンスオプション" -#: sql_help.c:1387 +#: sql_help.c:1395 msgid "table_constraint_using_index" msgstr "インデックスを使うテーブルの制約" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1397 sql_help.c:1398 +#: sql_help.c:1404 sql_help.c:1405 sql_help.c:1406 sql_help.c:1407 msgid "rewrite_rule_name" msgstr "書き換えルール名" -#: sql_help.c:1410 sql_help.c:2391 sql_help.c:2995 +#: sql_help.c:1419 sql_help.c:2419 sql_help.c:3031 msgid "and partition_bound_spec is:" msgstr "パーティション境界の仕様は以下の通りです:" -#: sql_help.c:1411 sql_help.c:1412 sql_help.c:1413 sql_help.c:2392 -#: sql_help.c:2393 sql_help.c:2394 sql_help.c:2996 sql_help.c:2997 -#: sql_help.c:2998 +#: sql_help.c:1420 sql_help.c:1421 sql_help.c:1422 sql_help.c:2420 +#: sql_help.c:2421 sql_help.c:2422 sql_help.c:3032 sql_help.c:3033 +#: sql_help.c:3034 msgid "partition_bound_expr" msgstr "パーティション境界式" -#: sql_help.c:1414 sql_help.c:1415 sql_help.c:2395 sql_help.c:2396 -#: sql_help.c:2999 sql_help.c:3000 +#: sql_help.c:1423 sql_help.c:1424 sql_help.c:2423 sql_help.c:2424 +#: sql_help.c:3035 sql_help.c:3036 msgid "numeric_literal" msgstr "numericリテラル" -#: sql_help.c:1416 +#: sql_help.c:1425 msgid "and column_constraint is:" msgstr "そしてカラム制約は以下の通りです:" -#: sql_help.c:1419 sql_help.c:2386 sql_help.c:2427 sql_help.c:2636 -#: sql_help.c:2968 +#: sql_help.c:1428 sql_help.c:2412 sql_help.c:2455 sql_help.c:2664 +#: sql_help.c:2999 msgid "default_expr" msgstr "デフォルト表現" -#: sql_help.c:1420 sql_help.c:2387 sql_help.c:2969 +#: sql_help.c:1429 sql_help.c:2413 sql_help.c:3000 msgid "generation_expr" msgstr "生成式" -#: sql_help.c:1422 sql_help.c:1423 sql_help.c:1432 sql_help.c:1434 -#: sql_help.c:1438 sql_help.c:2971 sql_help.c:2972 sql_help.c:2981 -#: sql_help.c:2983 sql_help.c:2987 +#: sql_help.c:1431 sql_help.c:1432 sql_help.c:1443 sql_help.c:1446 +#: sql_help.c:1450 sql_help.c:3002 sql_help.c:3003 sql_help.c:3014 +#: sql_help.c:3017 sql_help.c:3021 msgid "index_parameters" msgstr "インデックスパラメータ" -#: sql_help.c:1424 sql_help.c:1441 sql_help.c:2973 sql_help.c:2990 +#: sql_help.c:1433 sql_help.c:1454 sql_help.c:3004 sql_help.c:3025 msgid "reftable" msgstr "参照テーブル" -#: sql_help.c:1425 sql_help.c:1442 sql_help.c:2974 sql_help.c:2991 +#: sql_help.c:1434 sql_help.c:1455 sql_help.c:1456 sql_help.c:3005 +#: sql_help.c:3026 sql_help.c:3027 msgid "refcolumn" msgstr "参照列" -#: sql_help.c:1426 sql_help.c:1427 sql_help.c:1443 sql_help.c:1444 -#: sql_help.c:2975 sql_help.c:2976 sql_help.c:2992 sql_help.c:2993 +#: sql_help.c:1435 sql_help.c:1436 sql_help.c:1457 sql_help.c:1458 +#: sql_help.c:3006 sql_help.c:3007 sql_help.c:3028 sql_help.c:3029 msgid "referential_action" msgstr "参照動作" -#: sql_help.c:1428 sql_help.c:2388 sql_help.c:2977 +#: sql_help.c:1437 sql_help.c:2414 sql_help.c:3008 msgid "and table_constraint is:" msgstr "テーブル制約は以下の通りです:" -#: sql_help.c:1436 sql_help.c:2985 +#: sql_help.c:1448 sql_help.c:3019 msgid "exclude_element" msgstr "除外対象要素" -#: sql_help.c:1437 sql_help.c:2986 sql_help.c:4613 sql_help.c:4717 -#: sql_help.c:4871 sql_help.c:5047 sql_help.c:5116 +#: sql_help.c:1449 sql_help.c:3020 sql_help.c:4655 sql_help.c:4759 +#: sql_help.c:4913 sql_help.c:5091 sql_help.c:5160 msgid "operator" msgstr "演算子" -#: sql_help.c:1439 sql_help.c:2507 sql_help.c:2988 +#: sql_help.c:1451 sql_help.c:2535 sql_help.c:3022 msgid "predicate" msgstr "インデックスの述語" -#: sql_help.c:1445 +#: sql_help.c:1459 msgid "and table_constraint_using_index is:" msgstr "テーブル制約は以下の通りです:" -#: sql_help.c:1448 sql_help.c:3001 +#: sql_help.c:1462 sql_help.c:3037 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "UNIQUE, PRIMARY KEY, EXCLUDE 制約のインデックスパラメータは以下の通りです:" -#: sql_help.c:1453 sql_help.c:3006 +#: sql_help.c:1467 sql_help.c:3042 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "EXCLUDE 制約の除外対象要素は以下の通りです:" -#: sql_help.c:1457 sql_help.c:2500 sql_help.c:2933 sql_help.c:2946 -#: sql_help.c:2960 sql_help.c:3010 sql_help.c:4031 +#: sql_help.c:1471 sql_help.c:2528 sql_help.c:2964 sql_help.c:2977 +#: sql_help.c:2991 sql_help.c:3046 sql_help.c:4071 msgid "opclass" msgstr "演算子クラス" -#: sql_help.c:1458 sql_help.c:2501 sql_help.c:3011 +#: sql_help.c:1472 sql_help.c:2529 sql_help.c:3047 msgid "opclass_parameter" msgstr "演算子クラスパラメータ" -#: sql_help.c:1460 sql_help.c:3013 +#: sql_help.c:1474 sql_help.c:3049 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "FOREIGN KEY/REFERENCES制約の参照動作は以下の通り:" -#: sql_help.c:1478 sql_help.c:1481 sql_help.c:3050 +#: sql_help.c:1492 sql_help.c:1495 sql_help.c:3086 msgid "tablespace_option" msgstr "テーブル空間のオプション" -#: sql_help.c:1502 sql_help.c:1505 sql_help.c:1511 sql_help.c:1515 +#: sql_help.c:1516 sql_help.c:1519 sql_help.c:1525 sql_help.c:1529 msgid "token_type" msgstr "トークンの型" -#: sql_help.c:1503 sql_help.c:1506 +#: sql_help.c:1517 sql_help.c:1520 msgid "dictionary_name" msgstr "辞書名" -#: sql_help.c:1508 sql_help.c:1512 +#: sql_help.c:1522 sql_help.c:1526 msgid "old_dictionary" msgstr "元の辞書" -#: sql_help.c:1509 sql_help.c:1513 +#: sql_help.c:1523 sql_help.c:1527 msgid "new_dictionary" msgstr "新しい辞書" -#: sql_help.c:1608 sql_help.c:1622 sql_help.c:1625 sql_help.c:1626 -#: sql_help.c:3203 +#: sql_help.c:1622 sql_help.c:1636 sql_help.c:1639 sql_help.c:1640 +#: sql_help.c:3239 msgid "attribute_name" msgstr "属性名" -#: sql_help.c:1609 +#: sql_help.c:1623 msgid "new_attribute_name" msgstr "新しい属性名" -#: sql_help.c:1613 sql_help.c:1617 +#: sql_help.c:1627 sql_help.c:1631 msgid "new_enum_value" msgstr "新しい列挙値" -#: sql_help.c:1614 +#: sql_help.c:1628 msgid "neighbor_enum_value" msgstr "隣接した列挙値" -#: sql_help.c:1616 +#: sql_help.c:1630 msgid "existing_enum_value" msgstr "既存の列挙値" -#: sql_help.c:1619 +#: sql_help.c:1633 msgid "property" msgstr "プロパティ" -#: sql_help.c:1695 sql_help.c:2371 sql_help.c:2380 sql_help.c:2782 -#: sql_help.c:3283 sql_help.c:3734 sql_help.c:3941 sql_help.c:3987 -#: sql_help.c:4404 +#: sql_help.c:1709 sql_help.c:2397 sql_help.c:2406 sql_help.c:2812 +#: sql_help.c:3319 sql_help.c:3772 sql_help.c:3979 sql_help.c:4025 +#: sql_help.c:4446 msgid "server_name" msgstr "サーバー名" -#: sql_help.c:1727 sql_help.c:1730 sql_help.c:3298 +#: sql_help.c:1741 sql_help.c:1744 sql_help.c:3334 msgid "view_option_name" msgstr "ビューのオプション名" -#: sql_help.c:1728 sql_help.c:3299 +#: sql_help.c:1742 sql_help.c:3335 msgid "view_option_value" msgstr "ビューオプションの値" -#: sql_help.c:1749 sql_help.c:5016 +#: sql_help.c:1763 sql_help.c:5060 msgid "table_and_columns" msgstr "テーブルおよび列" -#: sql_help.c:1750 sql_help.c:1810 sql_help.c:2004 sql_help.c:3783 -#: sql_help.c:4239 sql_help.c:5017 +#: sql_help.c:1764 sql_help.c:1824 sql_help.c:2019 sql_help.c:3821 +#: sql_help.c:4281 sql_help.c:5061 msgid "where option can be one of:" msgstr "オプションには以下のうちのいずれかを指定します:" -#: sql_help.c:1751 sql_help.c:1752 sql_help.c:1811 sql_help.c:2006 -#: sql_help.c:2010 sql_help.c:2192 sql_help.c:3784 sql_help.c:3785 -#: sql_help.c:3786 sql_help.c:3787 sql_help.c:3788 sql_help.c:3789 -#: sql_help.c:3790 sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 -#: sql_help.c:4240 sql_help.c:4242 sql_help.c:5018 sql_help.c:5019 -#: sql_help.c:5020 sql_help.c:5021 sql_help.c:5022 sql_help.c:5023 -#: sql_help.c:5024 sql_help.c:5025 sql_help.c:5026 sql_help.c:5028 -#: sql_help.c:5029 +#: sql_help.c:1765 sql_help.c:1766 sql_help.c:1825 sql_help.c:2021 +#: sql_help.c:2025 sql_help.c:2208 sql_help.c:3822 sql_help.c:3823 +#: sql_help.c:3824 sql_help.c:3825 sql_help.c:3826 sql_help.c:3827 +#: sql_help.c:3828 sql_help.c:3829 sql_help.c:3830 sql_help.c:3831 +#: sql_help.c:4282 sql_help.c:4284 sql_help.c:5062 sql_help.c:5063 +#: sql_help.c:5064 sql_help.c:5065 sql_help.c:5066 sql_help.c:5067 +#: sql_help.c:5068 sql_help.c:5069 sql_help.c:5070 sql_help.c:5072 +#: sql_help.c:5073 msgid "boolean" msgstr "真偽値" -#: sql_help.c:1753 sql_help.c:5030 +#: sql_help.c:1767 sql_help.c:5074 msgid "size" msgstr "サイズ" -#: sql_help.c:1754 sql_help.c:5031 +#: sql_help.c:1768 sql_help.c:5075 msgid "and table_and_columns is:" msgstr "そしてテーブルと列の指定は以下の通りです:" -#: sql_help.c:1770 sql_help.c:4778 sql_help.c:4780 sql_help.c:4804 +#: sql_help.c:1784 sql_help.c:4820 sql_help.c:4822 sql_help.c:4846 msgid "transaction_mode" msgstr "トランザクションのモード" -#: sql_help.c:1771 sql_help.c:4781 sql_help.c:4805 +#: sql_help.c:1785 sql_help.c:4823 sql_help.c:4847 msgid "where transaction_mode is one of:" msgstr "トランザクションのモードは以下の通りです:" -#: sql_help.c:1780 sql_help.c:4623 sql_help.c:4632 sql_help.c:4636 -#: sql_help.c:4640 sql_help.c:4643 sql_help.c:4881 sql_help.c:4890 -#: sql_help.c:4894 sql_help.c:4898 sql_help.c:4901 sql_help.c:5126 -#: sql_help.c:5135 sql_help.c:5139 sql_help.c:5143 sql_help.c:5146 +#: sql_help.c:1794 sql_help.c:4665 sql_help.c:4674 sql_help.c:4678 +#: sql_help.c:4682 sql_help.c:4685 sql_help.c:4923 sql_help.c:4932 +#: sql_help.c:4936 sql_help.c:4940 sql_help.c:4943 sql_help.c:5170 +#: sql_help.c:5179 sql_help.c:5183 sql_help.c:5187 sql_help.c:5190 msgid "argument" msgstr "引数" -#: sql_help.c:1876 +#: sql_help.c:1890 msgid "relation_name" msgstr "リレーション名" -#: sql_help.c:1881 sql_help.c:3935 sql_help.c:4398 +#: sql_help.c:1895 sql_help.c:3973 sql_help.c:4440 msgid "domain_name" msgstr "ドメイン名" -#: sql_help.c:1903 +#: sql_help.c:1917 msgid "policy_name" msgstr "ポリシー名" -#: sql_help.c:1916 +#: sql_help.c:1930 msgid "rule_name" msgstr "ルール名" -#: sql_help.c:1935 sql_help.c:4537 +#: sql_help.c:1949 sql_help.c:4579 msgid "string_literal" msgstr "文字列リテラル" -#: sql_help.c:1960 sql_help.c:4201 sql_help.c:4451 +#: sql_help.c:1974 sql_help.c:4243 sql_help.c:4493 msgid "transaction_id" msgstr "トランザクションID" -#: sql_help.c:1994 sql_help.c:2001 sql_help.c:4057 +#: sql_help.c:2009 sql_help.c:2016 sql_help.c:4097 msgid "filename" msgstr "ファイル名" -#: sql_help.c:1995 sql_help.c:2002 sql_help.c:2721 sql_help.c:2722 -#: sql_help.c:2723 +#: sql_help.c:2010 sql_help.c:2017 sql_help.c:2749 sql_help.c:2750 +#: sql_help.c:2751 msgid "command" msgstr "コマンド" -#: sql_help.c:1997 sql_help.c:2720 sql_help.c:3153 sql_help.c:3334 -#: sql_help.c:4041 sql_help.c:4124 sql_help.c:4127 sql_help.c:4130 -#: sql_help.c:4606 sql_help.c:4608 sql_help.c:4710 sql_help.c:4712 -#: sql_help.c:4864 sql_help.c:4866 sql_help.c:4983 sql_help.c:5109 -#: sql_help.c:5111 +#: sql_help.c:2012 sql_help.c:2748 sql_help.c:3189 sql_help.c:3371 +#: sql_help.c:4081 sql_help.c:4166 sql_help.c:4169 sql_help.c:4172 +#: sql_help.c:4648 sql_help.c:4650 sql_help.c:4752 sql_help.c:4754 +#: sql_help.c:4906 sql_help.c:4908 sql_help.c:5026 sql_help.c:5153 +#: sql_help.c:5155 msgid "condition" msgstr "条件" -#: sql_help.c:2000 sql_help.c:2541 sql_help.c:3036 sql_help.c:3300 -#: sql_help.c:3318 sql_help.c:4022 +#: sql_help.c:2015 sql_help.c:2569 sql_help.c:3072 sql_help.c:3336 +#: sql_help.c:3354 sql_help.c:4061 msgid "query" msgstr "問い合わせ" -#: sql_help.c:2005 +#: sql_help.c:2020 msgid "format_name" msgstr "フォーマット名" -#: sql_help.c:2007 +#: sql_help.c:2022 msgid "delimiter_character" msgstr "区切り文字" -#: sql_help.c:2008 +#: sql_help.c:2023 msgid "null_string" msgstr "NULL文字列" -#: sql_help.c:2009 +#: sql_help.c:2024 msgid "default_string" msgstr "デフォルト文字列" -#: sql_help.c:2011 +#: sql_help.c:2026 msgid "quote_character" msgstr "引用符文字" -#: sql_help.c:2012 +#: sql_help.c:2027 msgid "escape_character" msgstr "エスケープ文字" -#: sql_help.c:2016 +#: sql_help.c:2031 msgid "error_action" msgstr "エラー処理" -#: sql_help.c:2017 +#: sql_help.c:2032 +msgid "maxerror" +msgstr "許容エラー数" + +#: sql_help.c:2033 msgid "encoding_name" msgstr "エンコーディング名" -#: sql_help.c:2018 +#: sql_help.c:2034 msgid "verbosity" msgstr "詳細度" -#: sql_help.c:2029 +#: sql_help.c:2045 msgid "access_method_type" msgstr "アクセスメソッドの型" -#: sql_help.c:2100 sql_help.c:2119 sql_help.c:2122 +#: sql_help.c:2116 sql_help.c:2135 sql_help.c:2138 msgid "arg_data_type" msgstr "入力データ型" -#: sql_help.c:2101 sql_help.c:2123 sql_help.c:2131 +#: sql_help.c:2117 sql_help.c:2139 sql_help.c:2147 msgid "sfunc" msgstr "状態遷移関数" -#: sql_help.c:2102 sql_help.c:2124 sql_help.c:2132 +#: sql_help.c:2118 sql_help.c:2140 sql_help.c:2148 msgid "state_data_type" msgstr "状態データの型" -#: sql_help.c:2103 sql_help.c:2125 sql_help.c:2133 +#: sql_help.c:2119 sql_help.c:2141 sql_help.c:2149 msgid "state_data_size" msgstr "状態データのサイズ" -#: sql_help.c:2104 sql_help.c:2126 sql_help.c:2134 +#: sql_help.c:2120 sql_help.c:2142 sql_help.c:2150 msgid "ffunc" msgstr "終了関数" -#: sql_help.c:2105 sql_help.c:2135 +#: sql_help.c:2121 sql_help.c:2151 msgid "combinefunc" msgstr "結合関数" -#: sql_help.c:2106 sql_help.c:2136 +#: sql_help.c:2122 sql_help.c:2152 msgid "serialfunc" msgstr "シリアライズ関数" -#: sql_help.c:2107 sql_help.c:2137 +#: sql_help.c:2123 sql_help.c:2153 msgid "deserialfunc" msgstr "デシリアライズ関数" -#: sql_help.c:2108 sql_help.c:2127 sql_help.c:2138 +#: sql_help.c:2124 sql_help.c:2143 sql_help.c:2154 msgid "initial_condition" msgstr "初期条件" -#: sql_help.c:2109 sql_help.c:2139 +#: sql_help.c:2125 sql_help.c:2155 msgid "msfunc" msgstr "前方状態遷移関数" -#: sql_help.c:2110 sql_help.c:2140 +#: sql_help.c:2126 sql_help.c:2156 msgid "minvfunc" msgstr "逆状態遷移関数" -#: sql_help.c:2111 sql_help.c:2141 +#: sql_help.c:2127 sql_help.c:2157 msgid "mstate_data_type" msgstr "移動集約モード時の状態値のデータ型" -#: sql_help.c:2112 sql_help.c:2142 +#: sql_help.c:2128 sql_help.c:2158 msgid "mstate_data_size" msgstr "移動集約モード時の状態値のデータサイズ" -#: sql_help.c:2113 sql_help.c:2143 +#: sql_help.c:2129 sql_help.c:2159 msgid "mffunc" msgstr "移動集約モード時の終了関数" -#: sql_help.c:2114 sql_help.c:2144 +#: sql_help.c:2130 sql_help.c:2160 msgid "minitial_condition" msgstr "移動集約モード時の初期条件" -#: sql_help.c:2115 sql_help.c:2145 +#: sql_help.c:2131 sql_help.c:2161 msgid "sort_operator" msgstr "ソート演算子" -#: sql_help.c:2128 +#: sql_help.c:2144 msgid "or the old syntax" msgstr "または古い構文" -#: sql_help.c:2130 +#: sql_help.c:2146 msgid "base_type" msgstr "基本の型" -#: sql_help.c:2188 sql_help.c:2238 +#: sql_help.c:2204 sql_help.c:2254 msgid "locale" msgstr "ロケール" -#: sql_help.c:2189 sql_help.c:2239 +#: sql_help.c:2205 sql_help.c:2255 msgid "lc_collate" msgstr "照合順序" -#: sql_help.c:2190 sql_help.c:2240 +#: sql_help.c:2206 sql_help.c:2256 msgid "lc_ctype" msgstr "Ctype(変換演算子)" -#: sql_help.c:2191 sql_help.c:4504 +#: sql_help.c:2207 sql_help.c:4546 msgid "provider" msgstr "プロバイダ" -#: sql_help.c:2193 +#: sql_help.c:2209 msgid "rules" msgstr "ルール" -#: sql_help.c:2194 sql_help.c:2301 +#: sql_help.c:2210 sql_help.c:2317 msgid "version" msgstr "バージョン" -#: sql_help.c:2196 +#: sql_help.c:2212 msgid "existing_collation" msgstr "既存の照合順序" -#: sql_help.c:2206 +#: sql_help.c:2222 msgid "source_encoding" msgstr "変換元のエンコーディング" -#: sql_help.c:2207 +#: sql_help.c:2223 msgid "dest_encoding" msgstr "変換先のエンコーディング" -#: sql_help.c:2235 sql_help.c:3076 +#: sql_help.c:2251 sql_help.c:3112 msgid "template" msgstr "テンプレート" -#: sql_help.c:2236 +#: sql_help.c:2252 msgid "encoding" msgstr "エンコード" -#: sql_help.c:2237 +#: sql_help.c:2253 msgid "strategy" msgstr "ストラテジ" -#: sql_help.c:2241 +#: sql_help.c:2257 msgid "builtin_locale" msgstr "組み込みロケール" -#: sql_help.c:2242 +#: sql_help.c:2258 msgid "icu_locale" msgstr "ICUロケール" -#: sql_help.c:2243 +#: sql_help.c:2259 msgid "icu_rules" msgstr "ICUルール(群)" -#: sql_help.c:2244 +#: sql_help.c:2260 msgid "locale_provider" msgstr "ロケールプロバイダ" -#: sql_help.c:2245 +#: sql_help.c:2261 msgid "collation_version" msgstr "照合順序バージョン" -#: sql_help.c:2250 +#: sql_help.c:2266 msgid "oid" msgstr "オブジェクトID" -#: sql_help.c:2271 -msgid "where domain_constraint is:" -msgstr "ドメイン制約は以下の通りです:" - -#: sql_help.c:2285 sql_help.c:2718 sql_help.c:3149 +#: sql_help.c:2301 sql_help.c:2746 sql_help.c:3185 msgid "event" msgstr "イベント" -#: sql_help.c:2286 +#: sql_help.c:2302 msgid "filter_variable" msgstr "フィルター変数" -#: sql_help.c:2287 +#: sql_help.c:2303 msgid "filter_value" msgstr "フィルター値" -#: sql_help.c:2383 sql_help.c:2965 +#: sql_help.c:2394 sql_help.c:2958 +msgid "source_table" +msgstr "コピー元のテーブル" + +#: sql_help.c:2395 sql_help.c:2959 +msgid "like_option" +msgstr "LIKEオプション" + +#: sql_help.c:2409 sql_help.c:2996 msgid "where column_constraint is:" msgstr "カラム制約は以下の通りです:" -#: sql_help.c:2428 +#: sql_help.c:2418 sql_help.c:3030 +msgid "and like_option is:" +msgstr "LIKE オプションは以下の通りです:" + +#: sql_help.c:2456 msgid "rettype" msgstr "戻り値の型" -#: sql_help.c:2430 +#: sql_help.c:2458 msgid "column_type" msgstr "列の型" -#: sql_help.c:2439 sql_help.c:2642 +#: sql_help.c:2467 sql_help.c:2670 msgid "definition" msgstr "定義" -#: sql_help.c:2440 sql_help.c:2643 +#: sql_help.c:2468 sql_help.c:2671 msgid "obj_file" msgstr "オブジェクトファイル名" -#: sql_help.c:2441 sql_help.c:2644 +#: sql_help.c:2469 sql_help.c:2672 msgid "link_symbol" msgstr "リンクシンボル" -#: sql_help.c:2442 sql_help.c:2645 +#: sql_help.c:2470 sql_help.c:2673 msgid "sql_body" msgstr "SQL本体" -#: sql_help.c:2480 sql_help.c:2703 sql_help.c:3272 +#: sql_help.c:2508 sql_help.c:2731 sql_help.c:3308 msgid "uid" msgstr "UID" -#: sql_help.c:2496 sql_help.c:2537 sql_help.c:2934 sql_help.c:2947 -#: sql_help.c:2961 sql_help.c:3032 +#: sql_help.c:2524 sql_help.c:2565 sql_help.c:2965 sql_help.c:2978 +#: sql_help.c:2992 sql_help.c:3068 msgid "method" msgstr "インデックスメソッド" -#: sql_help.c:2518 +#: sql_help.c:2546 msgid "call_handler" msgstr "呼び出しハンドラー" -#: sql_help.c:2519 +#: sql_help.c:2547 msgid "inline_handler" msgstr "インラインハンドラー" -#: sql_help.c:2520 +#: sql_help.c:2548 msgid "valfunction" msgstr "バリデーション関数" -#: sql_help.c:2578 +#: sql_help.c:2606 msgid "family_name" msgstr "演算子族の名前" -#: sql_help.c:2589 +#: sql_help.c:2617 msgid "storage_type" msgstr "ストレージタイプ" -#: sql_help.c:2724 sql_help.c:3156 +#: sql_help.c:2752 sql_help.c:3192 msgid "where event can be one of:" msgstr "イベントは以下のいずれかです:" -#: sql_help.c:2744 sql_help.c:2746 +#: sql_help.c:2772 sql_help.c:2774 msgid "schema_element" msgstr "スキーマ要素" -#: sql_help.c:2783 +#: sql_help.c:2813 msgid "server_type" msgstr "サーバーのタイプ" -#: sql_help.c:2784 +#: sql_help.c:2814 msgid "server_version" msgstr "サーバーのバージョン" -#: sql_help.c:2785 sql_help.c:3938 sql_help.c:4401 +#: sql_help.c:2815 sql_help.c:3976 sql_help.c:4443 msgid "fdw_name" msgstr "外部データラッパ名" -#: sql_help.c:2802 sql_help.c:2805 +#: sql_help.c:2832 sql_help.c:2835 msgid "statistics_name" msgstr "統計オブジェクト名" -#: sql_help.c:2806 +#: sql_help.c:2836 msgid "statistics_kind" msgstr "統計種別" -#: sql_help.c:2822 +#: sql_help.c:2852 msgid "subscription_name" msgstr "サブスクリプション名" -#: sql_help.c:2927 -msgid "source_table" -msgstr "コピー元のテーブル" - -#: sql_help.c:2928 -msgid "like_option" -msgstr "LIKEオプション" - -#: sql_help.c:2994 -msgid "and like_option is:" -msgstr "LIKE オプションは以下の通りです:" - -#: sql_help.c:3049 +#: sql_help.c:3085 msgid "directory" msgstr "ディレクトリ" -#: sql_help.c:3063 +#: sql_help.c:3099 msgid "parser_name" msgstr "パーサ名" -#: sql_help.c:3064 +#: sql_help.c:3100 msgid "source_config" msgstr "複製元の設定" -#: sql_help.c:3093 +#: sql_help.c:3129 msgid "start_function" msgstr "開始関数" -#: sql_help.c:3094 +#: sql_help.c:3130 msgid "gettoken_function" msgstr "トークン取得関数" -#: sql_help.c:3095 +#: sql_help.c:3131 msgid "end_function" msgstr "終了関数" -#: sql_help.c:3096 +#: sql_help.c:3132 msgid "lextypes_function" msgstr "LEXTYPE関数" -#: sql_help.c:3097 +#: sql_help.c:3133 msgid "headline_function" msgstr "見出し関数" -#: sql_help.c:3109 +#: sql_help.c:3145 msgid "init_function" msgstr "初期処理関数" -#: sql_help.c:3110 +#: sql_help.c:3146 msgid "lexize_function" msgstr "LEXIZE関数" -#: sql_help.c:3123 +#: sql_help.c:3159 msgid "from_sql_function_name" msgstr "{FROM SQL 関数名}" -#: sql_help.c:3125 +#: sql_help.c:3161 msgid "to_sql_function_name" msgstr "{TO SQL 関数名}" -#: sql_help.c:3151 +#: sql_help.c:3187 msgid "referenced_table_name" msgstr "被参照テーブル名" -#: sql_help.c:3152 +#: sql_help.c:3188 msgid "transition_relation_name" msgstr "移行用リレーション名" -#: sql_help.c:3155 +#: sql_help.c:3191 msgid "arguments" msgstr "引数" -#: sql_help.c:3207 +#: sql_help.c:3243 msgid "label" msgstr "ラベル" -#: sql_help.c:3209 +#: sql_help.c:3245 msgid "subtype" msgstr "当該範囲のデータ型" -#: sql_help.c:3210 +#: sql_help.c:3246 msgid "subtype_operator_class" msgstr "当該範囲のデータ型の演算子クラス" -#: sql_help.c:3212 +#: sql_help.c:3248 msgid "canonical_function" msgstr "正規化関数" -#: sql_help.c:3213 +#: sql_help.c:3249 msgid "subtype_diff_function" msgstr "当該範囲のデータ型の差分抽出関数" -#: sql_help.c:3214 +#: sql_help.c:3250 msgid "multirange_type_name" msgstr "複範囲型名" -#: sql_help.c:3216 +#: sql_help.c:3252 msgid "input_function" msgstr "入力関数" -#: sql_help.c:3217 +#: sql_help.c:3253 msgid "output_function" msgstr "出力関数" -#: sql_help.c:3218 +#: sql_help.c:3254 msgid "receive_function" msgstr "受信関数" -#: sql_help.c:3219 +#: sql_help.c:3255 msgid "send_function" msgstr "送信関数" -#: sql_help.c:3220 +#: sql_help.c:3256 msgid "type_modifier_input_function" msgstr "型修飾子の入力関数" -#: sql_help.c:3221 +#: sql_help.c:3257 msgid "type_modifier_output_function" msgstr "型修飾子の出力関数" -#: sql_help.c:3222 +#: sql_help.c:3258 msgid "analyze_function" msgstr "分析関数" -#: sql_help.c:3223 +#: sql_help.c:3259 msgid "subscript_function" msgstr "添字関数" -#: sql_help.c:3224 +#: sql_help.c:3260 msgid "internallength" msgstr "内部長" -#: sql_help.c:3225 +#: sql_help.c:3261 msgid "alignment" msgstr "バイト境界" -#: sql_help.c:3226 +#: sql_help.c:3262 msgid "storage" msgstr "ストレージ" -#: sql_help.c:3227 +#: sql_help.c:3263 msgid "like_type" msgstr "LIKEの型" -#: sql_help.c:3228 +#: sql_help.c:3264 msgid "category" msgstr "カテゴリー" -#: sql_help.c:3229 +#: sql_help.c:3265 msgid "preferred" msgstr "優先データ型かどうか(真偽値)" -#: sql_help.c:3230 +#: sql_help.c:3266 msgid "default" msgstr "デフォルト" -#: sql_help.c:3231 +#: sql_help.c:3267 msgid "element" msgstr "要素のデータ型" -#: sql_help.c:3232 +#: sql_help.c:3268 msgid "delimiter" msgstr "区切り記号" -#: sql_help.c:3233 +#: sql_help.c:3269 msgid "collatable" msgstr "照合可能" -#: sql_help.c:3330 sql_help.c:4017 sql_help.c:4111 sql_help.c:4601 -#: sql_help.c:4704 sql_help.c:4859 sql_help.c:4973 sql_help.c:5104 +#: sql_help.c:3367 sql_help.c:4056 sql_help.c:4152 sql_help.c:4643 +#: sql_help.c:4746 sql_help.c:4901 sql_help.c:5016 sql_help.c:5148 msgid "with_query" msgstr "WITH問い合わせ" -#: sql_help.c:3332 sql_help.c:4019 sql_help.c:4620 sql_help.c:4626 -#: sql_help.c:4629 sql_help.c:4633 sql_help.c:4637 sql_help.c:4645 -#: sql_help.c:4878 sql_help.c:4884 sql_help.c:4887 sql_help.c:4891 -#: sql_help.c:4895 sql_help.c:4903 sql_help.c:4975 sql_help.c:5123 -#: sql_help.c:5129 sql_help.c:5132 sql_help.c:5136 sql_help.c:5140 -#: sql_help.c:5148 +#: sql_help.c:3369 sql_help.c:4058 sql_help.c:4662 sql_help.c:4668 +#: sql_help.c:4671 sql_help.c:4675 sql_help.c:4679 sql_help.c:4687 +#: sql_help.c:4920 sql_help.c:4926 sql_help.c:4929 sql_help.c:4933 +#: sql_help.c:4937 sql_help.c:4945 sql_help.c:5018 sql_help.c:5167 +#: sql_help.c:5173 sql_help.c:5176 sql_help.c:5180 sql_help.c:5184 +#: sql_help.c:5192 msgid "alias" msgstr "別名" -#: sql_help.c:3333 sql_help.c:4605 sql_help.c:4647 sql_help.c:4649 -#: sql_help.c:4653 sql_help.c:4655 sql_help.c:4656 sql_help.c:4657 -#: sql_help.c:4709 sql_help.c:4863 sql_help.c:4905 sql_help.c:4907 -#: sql_help.c:4911 sql_help.c:4913 sql_help.c:4914 sql_help.c:4915 -#: sql_help.c:4982 sql_help.c:5108 sql_help.c:5150 sql_help.c:5152 -#: sql_help.c:5156 sql_help.c:5158 sql_help.c:5159 sql_help.c:5160 +#: sql_help.c:3370 sql_help.c:4647 sql_help.c:4689 sql_help.c:4691 +#: sql_help.c:4695 sql_help.c:4697 sql_help.c:4698 sql_help.c:4699 +#: sql_help.c:4751 sql_help.c:4905 sql_help.c:4947 sql_help.c:4949 +#: sql_help.c:4953 sql_help.c:4955 sql_help.c:4956 sql_help.c:4957 +#: sql_help.c:5025 sql_help.c:5152 sql_help.c:5194 sql_help.c:5196 +#: sql_help.c:5200 sql_help.c:5202 sql_help.c:5203 sql_help.c:5204 msgid "from_item" msgstr "FROM項目" -#: sql_help.c:3335 sql_help.c:3819 sql_help.c:4168 sql_help.c:4984 +#: sql_help.c:3372 sql_help.c:3857 sql_help.c:4210 sql_help.c:5027 msgid "cursor_name" msgstr "カーソル名" -#: sql_help.c:3336 sql_help.c:4025 sql_help.c:4117 sql_help.c:4985 +#: sql_help.c:3373 sql_help.c:4064 sql_help.c:4158 sql_help.c:5028 +msgid "output_alias" +msgstr "出力別名" + +#: sql_help.c:3374 sql_help.c:4065 sql_help.c:4159 sql_help.c:5029 msgid "output_expression" msgstr "出力表現" -#: sql_help.c:3337 sql_help.c:4026 sql_help.c:4118 sql_help.c:4604 -#: sql_help.c:4707 sql_help.c:4862 sql_help.c:4986 sql_help.c:5107 +#: sql_help.c:3375 sql_help.c:4066 sql_help.c:4160 sql_help.c:4646 +#: sql_help.c:4749 sql_help.c:4904 sql_help.c:5030 sql_help.c:5151 msgid "output_name" msgstr "出力名" -#: sql_help.c:3353 +#: sql_help.c:3391 msgid "code" msgstr "コードブロック" -#: sql_help.c:3758 +#: sql_help.c:3796 msgid "parameter" msgstr "パラメータ" -#: sql_help.c:3782 sql_help.c:4193 +#: sql_help.c:3820 sql_help.c:4235 msgid "statement" msgstr "文" -#: sql_help.c:3818 sql_help.c:4167 +#: sql_help.c:3856 sql_help.c:4209 msgid "direction" msgstr "方向" -#: sql_help.c:3820 sql_help.c:4169 +#: sql_help.c:3858 sql_help.c:4211 msgid "where direction can be one of:" msgstr "方向 は以下のうちのいずれか:" -#: sql_help.c:3821 sql_help.c:3822 sql_help.c:3823 sql_help.c:3824 -#: sql_help.c:3825 sql_help.c:4170 sql_help.c:4171 sql_help.c:4172 -#: sql_help.c:4173 sql_help.c:4174 sql_help.c:4614 sql_help.c:4616 -#: sql_help.c:4718 sql_help.c:4720 sql_help.c:4872 sql_help.c:4874 -#: sql_help.c:5048 sql_help.c:5050 sql_help.c:5117 sql_help.c:5119 +#: sql_help.c:3859 sql_help.c:3860 sql_help.c:3861 sql_help.c:3862 +#: sql_help.c:3863 sql_help.c:4212 sql_help.c:4213 sql_help.c:4214 +#: sql_help.c:4215 sql_help.c:4216 sql_help.c:4656 sql_help.c:4658 +#: sql_help.c:4760 sql_help.c:4762 sql_help.c:4914 sql_help.c:4916 +#: sql_help.c:5092 sql_help.c:5094 sql_help.c:5161 sql_help.c:5163 msgid "count" msgstr "取り出す位置や行数" -#: sql_help.c:3928 sql_help.c:4391 +#: sql_help.c:3966 sql_help.c:4433 msgid "sequence_name" msgstr "シーケンス名" -#: sql_help.c:3946 sql_help.c:4409 +#: sql_help.c:3984 sql_help.c:4451 msgid "arg_name" msgstr "引数名" -#: sql_help.c:3947 sql_help.c:4410 +#: sql_help.c:3985 sql_help.c:4452 msgid "arg_type" msgstr "引数の型" -#: sql_help.c:3954 sql_help.c:4417 +#: sql_help.c:3992 sql_help.c:4459 msgid "loid" msgstr "ラージオブジェクトid" -#: sql_help.c:3985 +#: sql_help.c:4023 msgid "remote_schema" msgstr "リモートスキーマ" -#: sql_help.c:3988 +#: sql_help.c:4026 msgid "local_schema" msgstr "ローカルスキーマ" -#: sql_help.c:4023 +#: sql_help.c:4062 msgid "conflict_target" msgstr "競合ターゲット" -#: sql_help.c:4024 +#: sql_help.c:4063 msgid "conflict_action" msgstr "競合時アクション" -#: sql_help.c:4027 +#: sql_help.c:4067 msgid "where conflict_target can be one of:" msgstr "競合ターゲットは以下のいずれかです:" -#: sql_help.c:4028 +#: sql_help.c:4068 msgid "index_column_name" msgstr "インデックスのカラム名" -#: sql_help.c:4029 +#: sql_help.c:4069 msgid "index_expression" msgstr "インデックス表現" -#: sql_help.c:4032 +#: sql_help.c:4072 msgid "index_predicate" msgstr "インデックスの述語" -#: sql_help.c:4034 +#: sql_help.c:4074 msgid "and conflict_action is one of:" msgstr "競合時アクションは以下のいずれかです:" -#: sql_help.c:4040 sql_help.c:4141 sql_help.c:4981 +#: sql_help.c:4080 sql_help.c:4183 sql_help.c:5024 msgid "sub-SELECT" msgstr "副問い合わせ句" -#: sql_help.c:4049 sql_help.c:4182 sql_help.c:4957 +#: sql_help.c:4089 sql_help.c:4224 sql_help.c:4999 msgid "channel" msgstr "チャネル" -#: sql_help.c:4071 +#: sql_help.c:4111 msgid "lockmode" msgstr "ロックモード" -#: sql_help.c:4072 +#: sql_help.c:4112 msgid "where lockmode is one of:" msgstr "ロックモードは以下のいずれかです:" -#: sql_help.c:4112 +#: sql_help.c:4153 msgid "target_table_name" msgstr "ターゲットテーブル名" -#: sql_help.c:4113 +#: sql_help.c:4154 msgid "target_alias" msgstr "ターゲット別名" -#: sql_help.c:4114 +#: sql_help.c:4155 msgid "data_source" msgstr "データ源" -#: sql_help.c:4115 sql_help.c:4650 sql_help.c:4908 sql_help.c:5153 +#: sql_help.c:4156 sql_help.c:4692 sql_help.c:4950 sql_help.c:5197 msgid "join_condition" msgstr "JOIN条件" -#: sql_help.c:4116 +#: sql_help.c:4157 msgid "when_clause" msgstr "WHEN句" -#: sql_help.c:4119 +#: sql_help.c:4161 msgid "where data_source is:" msgstr "ここで\"データ源\"は以下の通り:" -#: sql_help.c:4120 +#: sql_help.c:4162 msgid "source_table_name" msgstr "データ源テーブル名" -#: sql_help.c:4121 +#: sql_help.c:4163 msgid "source_query" msgstr "データ源問い合わせ" -#: sql_help.c:4122 +#: sql_help.c:4164 msgid "source_alias" msgstr "データ源別名" -#: sql_help.c:4123 +#: sql_help.c:4165 msgid "and when_clause is:" msgstr "WHEN句は以下の通り:" -#: sql_help.c:4125 sql_help.c:4128 +#: sql_help.c:4167 sql_help.c:4170 msgid "merge_update" msgstr "マージ更新" -#: sql_help.c:4126 sql_help.c:4129 +#: sql_help.c:4168 sql_help.c:4171 msgid "merge_delete" msgstr "マージ削除" -#: sql_help.c:4131 +#: sql_help.c:4173 msgid "merge_insert" msgstr "マージ挿入" -#: sql_help.c:4132 +#: sql_help.c:4174 msgid "and merge_insert is:" msgstr "そして\"マージ挿入\"は以下の通り:" -#: sql_help.c:4135 +#: sql_help.c:4177 msgid "and merge_update is:" msgstr "そして\"マージ更新\"は以下の通り:" -#: sql_help.c:4142 +#: sql_help.c:4184 msgid "and merge_delete is:" msgstr "そして\"マージ削除\"は以下の通り:" -#: sql_help.c:4183 +#: sql_help.c:4225 msgid "payload" msgstr "ペイロード" -#: sql_help.c:4210 +#: sql_help.c:4252 msgid "old_role" msgstr "元のロール" -#: sql_help.c:4211 +#: sql_help.c:4253 msgid "new_role" msgstr "新しいロール" -#: sql_help.c:4250 sql_help.c:4459 sql_help.c:4467 +#: sql_help.c:4292 sql_help.c:4501 sql_help.c:4509 msgid "savepoint_name" msgstr "セーブポイント名" -#: sql_help.c:4607 sql_help.c:4665 sql_help.c:4865 sql_help.c:4923 -#: sql_help.c:5110 sql_help.c:5168 +#: sql_help.c:4649 sql_help.c:4707 sql_help.c:4907 sql_help.c:4965 +#: sql_help.c:5154 sql_help.c:5212 msgid "grouping_element" msgstr "グルーピング要素" -#: sql_help.c:4609 sql_help.c:4713 sql_help.c:4867 sql_help.c:5112 +#: sql_help.c:4651 sql_help.c:4755 sql_help.c:4909 sql_help.c:5156 msgid "window_name" msgstr "ウィンドウ名" -#: sql_help.c:4610 sql_help.c:4714 sql_help.c:4868 sql_help.c:5113 +#: sql_help.c:4652 sql_help.c:4756 sql_help.c:4910 sql_help.c:5157 msgid "window_definition" msgstr "ウィンドウ定義" -#: sql_help.c:4611 sql_help.c:4625 sql_help.c:4669 sql_help.c:4715 -#: sql_help.c:4869 sql_help.c:4883 sql_help.c:4927 sql_help.c:5114 -#: sql_help.c:5128 sql_help.c:5172 +#: sql_help.c:4653 sql_help.c:4667 sql_help.c:4711 sql_help.c:4757 +#: sql_help.c:4911 sql_help.c:4925 sql_help.c:4969 sql_help.c:5158 +#: sql_help.c:5172 sql_help.c:5216 msgid "select" msgstr "SELECT句" -#: sql_help.c:4617 sql_help.c:4875 sql_help.c:5120 +#: sql_help.c:4659 sql_help.c:4917 sql_help.c:5164 msgid "from_reference" msgstr "FROM参照" -#: sql_help.c:4618 sql_help.c:4876 sql_help.c:5121 +#: sql_help.c:4660 sql_help.c:4918 sql_help.c:5165 msgid "where from_item can be one of:" msgstr "FROM項目は以下のいずれかです:" -#: sql_help.c:4621 sql_help.c:4627 sql_help.c:4630 sql_help.c:4634 -#: sql_help.c:4646 sql_help.c:4879 sql_help.c:4885 sql_help.c:4888 -#: sql_help.c:4892 sql_help.c:4904 sql_help.c:5124 sql_help.c:5130 -#: sql_help.c:5133 sql_help.c:5137 sql_help.c:5149 +#: sql_help.c:4663 sql_help.c:4669 sql_help.c:4672 sql_help.c:4676 +#: sql_help.c:4688 sql_help.c:4921 sql_help.c:4927 sql_help.c:4930 +#: sql_help.c:4934 sql_help.c:4946 sql_help.c:5168 sql_help.c:5174 +#: sql_help.c:5177 sql_help.c:5181 sql_help.c:5193 msgid "column_alias" msgstr "列別名" -#: sql_help.c:4622 sql_help.c:4880 sql_help.c:5125 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5169 msgid "sampling_method" msgstr "サンプリングメソッド" -#: sql_help.c:4624 sql_help.c:4882 sql_help.c:5127 +#: sql_help.c:4666 sql_help.c:4924 sql_help.c:5171 msgid "seed" msgstr "乱数シード" -#: sql_help.c:4628 sql_help.c:4667 sql_help.c:4886 sql_help.c:4925 -#: sql_help.c:5131 sql_help.c:5170 +#: sql_help.c:4670 sql_help.c:4709 sql_help.c:4928 sql_help.c:4967 +#: sql_help.c:5175 sql_help.c:5214 msgid "with_query_name" msgstr "WITH問い合わせ名" -#: sql_help.c:4638 sql_help.c:4641 sql_help.c:4644 sql_help.c:4896 -#: sql_help.c:4899 sql_help.c:4902 sql_help.c:5141 sql_help.c:5144 -#: sql_help.c:5147 +#: sql_help.c:4680 sql_help.c:4683 sql_help.c:4686 sql_help.c:4938 +#: sql_help.c:4941 sql_help.c:4944 sql_help.c:5185 sql_help.c:5188 +#: sql_help.c:5191 msgid "column_definition" msgstr "カラム定義" -#: sql_help.c:4648 sql_help.c:4654 sql_help.c:4906 sql_help.c:4912 -#: sql_help.c:5151 sql_help.c:5157 +#: sql_help.c:4690 sql_help.c:4696 sql_help.c:4948 sql_help.c:4954 +#: sql_help.c:5195 sql_help.c:5201 msgid "join_type" msgstr "JOINタイプ" -#: sql_help.c:4651 sql_help.c:4909 sql_help.c:5154 +#: sql_help.c:4693 sql_help.c:4951 sql_help.c:5198 msgid "join_column" msgstr "JOINカラム" -#: sql_help.c:4652 sql_help.c:4910 sql_help.c:5155 +#: sql_help.c:4694 sql_help.c:4952 sql_help.c:5199 msgid "join_using_alias" msgstr "JOIN用別名" -#: sql_help.c:4658 sql_help.c:4916 sql_help.c:5161 +#: sql_help.c:4700 sql_help.c:4958 sql_help.c:5205 msgid "and grouping_element can be one of:" msgstr "グルーピング要素は以下のいずれかです:" -#: sql_help.c:4666 sql_help.c:4924 sql_help.c:5169 +#: sql_help.c:4708 sql_help.c:4966 sql_help.c:5213 msgid "and with_query is:" msgstr "WITH問い合わせは以下のいずれかです:" -#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 +#: sql_help.c:4712 sql_help.c:4970 sql_help.c:5217 msgid "values" msgstr "VALUES句" -#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 +#: sql_help.c:4713 sql_help.c:4971 sql_help.c:5218 msgid "insert" msgstr "INSERT句" -#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 +#: sql_help.c:4714 sql_help.c:4972 sql_help.c:5219 msgid "update" msgstr "UPDATE句" -#: sql_help.c:4673 sql_help.c:4931 sql_help.c:5176 +#: sql_help.c:4715 sql_help.c:4973 sql_help.c:5220 msgid "delete" msgstr "DELETE句" -#: sql_help.c:4674 sql_help.c:4932 sql_help.c:5177 +#: sql_help.c:4716 sql_help.c:4974 sql_help.c:5221 msgid "merge" msgstr "MERGE句" -#: sql_help.c:4676 sql_help.c:4934 sql_help.c:5179 +#: sql_help.c:4718 sql_help.c:4976 sql_help.c:5223 msgid "search_seq_col_name" msgstr "SEARCH順序列名" -#: sql_help.c:4678 sql_help.c:4936 sql_help.c:5181 +#: sql_help.c:4720 sql_help.c:4978 sql_help.c:5225 msgid "cycle_mark_col_name" msgstr "循環識別列名" -#: sql_help.c:4679 sql_help.c:4937 sql_help.c:5182 +#: sql_help.c:4721 sql_help.c:4979 sql_help.c:5226 msgid "cycle_mark_value" msgstr "循環識別値" -#: sql_help.c:4680 sql_help.c:4938 sql_help.c:5183 +#: sql_help.c:4722 sql_help.c:4980 sql_help.c:5227 msgid "cycle_mark_default" msgstr "循環識別デフォルト" -#: sql_help.c:4681 sql_help.c:4939 sql_help.c:5184 +#: sql_help.c:4723 sql_help.c:4981 sql_help.c:5228 msgid "cycle_path_col_name" msgstr "循環パス列名" -#: sql_help.c:4708 +#: sql_help.c:4750 msgid "new_table" msgstr "新しいテーブル" -#: sql_help.c:4779 +#: sql_help.c:4821 msgid "snapshot_id" msgstr "スナップショットID" -#: sql_help.c:5046 +#: sql_help.c:5090 msgid "sort_expression" msgstr "ソート表現" -#: sql_help.c:5191 sql_help.c:6175 +#: sql_help.c:5235 sql_help.c:6219 msgid "abort the current transaction" msgstr "現在のトランザクションを中止します" -#: sql_help.c:5197 +#: sql_help.c:5241 msgid "change the definition of an aggregate function" msgstr "集約関数の定義を変更します" -#: sql_help.c:5203 +#: sql_help.c:5247 msgid "change the definition of a collation" msgstr "照合順序の定義を変更します" -#: sql_help.c:5209 +#: sql_help.c:5253 msgid "change the definition of a conversion" msgstr "エンコーディング変換ルールの定義を変更します" -#: sql_help.c:5215 +#: sql_help.c:5259 msgid "change a database" msgstr "データベースを変更します" -#: sql_help.c:5221 +#: sql_help.c:5265 msgid "define default access privileges" msgstr "デフォルトのアクセス権限を定義します" -#: sql_help.c:5227 +#: sql_help.c:5271 msgid "change the definition of a domain" msgstr "ドメインの定義を変更します" -#: sql_help.c:5233 +#: sql_help.c:5277 msgid "change the definition of an event trigger" msgstr "イベントトリガーの定義を変更します" -#: sql_help.c:5239 +#: sql_help.c:5283 msgid "change the definition of an extension" msgstr "機能拡張の定義を変更します" -#: sql_help.c:5245 +#: sql_help.c:5289 msgid "change the definition of a foreign-data wrapper" msgstr "外部データラッパの定義を変更します" -#: sql_help.c:5251 +#: sql_help.c:5295 msgid "change the definition of a foreign table" msgstr "外部テーブルの定義を変更します" -#: sql_help.c:5257 +#: sql_help.c:5301 msgid "change the definition of a function" msgstr "関数の定義を変更します" -#: sql_help.c:5263 +#: sql_help.c:5307 msgid "change role name or membership" msgstr "ロール名またはメンバーシップを変更します" -#: sql_help.c:5269 +#: sql_help.c:5313 msgid "change the definition of an index" msgstr "インデックスの定義を変更します" -#: sql_help.c:5275 +#: sql_help.c:5319 msgid "change the definition of a procedural language" msgstr "手続き言語の定義を変更します" -#: sql_help.c:5281 +#: sql_help.c:5325 msgid "change the definition of a large object" msgstr "ラージオブジェクトの定義を変更します" -#: sql_help.c:5287 +#: sql_help.c:5331 msgid "change the definition of a materialized view" msgstr "実体化ビューの定義を変更します" -#: sql_help.c:5293 +#: sql_help.c:5337 msgid "change the definition of an operator" msgstr "演算子の定義を変更します" -#: sql_help.c:5299 +#: sql_help.c:5343 msgid "change the definition of an operator class" msgstr "演算子クラスの定義を変更します" -#: sql_help.c:5305 +#: sql_help.c:5349 msgid "change the definition of an operator family" msgstr "演算子族の定義を変更します" -#: sql_help.c:5311 +#: sql_help.c:5355 msgid "change the definition of a row-level security policy" msgstr "行レベルのセキュリティ ポリシーの定義を変更します" -#: sql_help.c:5317 +#: sql_help.c:5361 msgid "change the definition of a procedure" msgstr "プロシージャの定義を変更します" -#: sql_help.c:5323 +#: sql_help.c:5367 msgid "change the definition of a publication" msgstr "パブリケーションの定義を変更します" -#: sql_help.c:5329 sql_help.c:5431 +#: sql_help.c:5373 sql_help.c:5475 msgid "change a database role" msgstr "データベースロールを変更します" -#: sql_help.c:5335 +#: sql_help.c:5379 msgid "change the definition of a routine" msgstr "ルーチンの定義を変更します" -#: sql_help.c:5341 +#: sql_help.c:5385 msgid "change the definition of a rule" msgstr "ルールの定義を変更します" -#: sql_help.c:5347 +#: sql_help.c:5391 msgid "change the definition of a schema" msgstr "スキーマの定義を変更します" -#: sql_help.c:5353 +#: sql_help.c:5397 msgid "change the definition of a sequence generator" msgstr "シーケンス生成器の定義を変更します" -#: sql_help.c:5359 +#: sql_help.c:5403 msgid "change the definition of a foreign server" msgstr "外部サーバーの定義を変更します" -#: sql_help.c:5365 +#: sql_help.c:5409 msgid "change the definition of an extended statistics object" msgstr "拡張統計情報オブジェクトの定義を変更します" -#: sql_help.c:5371 +#: sql_help.c:5415 msgid "change the definition of a subscription" msgstr "サブスクリプションの定義を変更します" -#: sql_help.c:5377 +#: sql_help.c:5421 msgid "change a server configuration parameter" msgstr "サーバーの設定パラメータを変更します" -#: sql_help.c:5383 +#: sql_help.c:5427 msgid "change the definition of a table" msgstr "テーブルの定義を変更します。" -#: sql_help.c:5389 +#: sql_help.c:5433 msgid "change the definition of a tablespace" msgstr "テーブル空間の定義を変更します" -#: sql_help.c:5395 +#: sql_help.c:5439 msgid "change the definition of a text search configuration" msgstr "テキスト検索設定の定義を変更します" -#: sql_help.c:5401 +#: sql_help.c:5445 msgid "change the definition of a text search dictionary" msgstr "テキスト検索辞書の定義を変更します" -#: sql_help.c:5407 +#: sql_help.c:5451 msgid "change the definition of a text search parser" msgstr "テキスト検索パーサーの定義を変更します" -#: sql_help.c:5413 +#: sql_help.c:5457 msgid "change the definition of a text search template" msgstr "テキスト検索テンプレートの定義を変更します" -#: sql_help.c:5419 +#: sql_help.c:5463 msgid "change the definition of a trigger" msgstr "トリガーの定義を変更します" -#: sql_help.c:5425 +#: sql_help.c:5469 msgid "change the definition of a type" msgstr "型の定義を変更します" -#: sql_help.c:5437 +#: sql_help.c:5481 msgid "change the definition of a user mapping" msgstr "ユーザーマッピングの定義を変更します" -#: sql_help.c:5443 +#: sql_help.c:5487 msgid "change the definition of a view" msgstr "ビューの定義を変更します" -#: sql_help.c:5449 +#: sql_help.c:5493 msgid "collect statistics about a database" msgstr "データベースの統計情報を収集します" -#: sql_help.c:5455 sql_help.c:6253 +#: sql_help.c:5499 sql_help.c:6297 msgid "start a transaction block" msgstr "トランザクション区間を開始します" -#: sql_help.c:5461 +#: sql_help.c:5505 msgid "invoke a procedure" msgstr "プロシージャを実行します" -#: sql_help.c:5467 +#: sql_help.c:5511 msgid "force a write-ahead log checkpoint" msgstr "先行書き込みログのチェックポイントを強制的に実行します" -#: sql_help.c:5473 +#: sql_help.c:5517 msgid "close a cursor" msgstr "カーソルを閉じます" -#: sql_help.c:5479 +#: sql_help.c:5523 msgid "cluster a table according to an index" msgstr "インデックスに従ってテーブルをクラスタ化します" -#: sql_help.c:5485 +#: sql_help.c:5529 msgid "define or change the comment of an object" msgstr "オブジェクトのコメントを定義または変更します" -#: sql_help.c:5491 sql_help.c:6049 +#: sql_help.c:5535 sql_help.c:6093 msgid "commit the current transaction" msgstr "現在のトランザクションをコミットします" -#: sql_help.c:5497 +#: sql_help.c:5541 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "二相コミットのために事前に準備されたトランザクションをコミットします" -#: sql_help.c:5503 +#: sql_help.c:5547 msgid "copy data between a file and a table" msgstr "ファイルとテーブルとの間でデータをコピーします" -#: sql_help.c:5509 +#: sql_help.c:5553 msgid "define a new access method" msgstr "新しいアクセスメソッドを定義します" -#: sql_help.c:5515 +#: sql_help.c:5559 msgid "define a new aggregate function" msgstr "新しい集約関数を定義します" -#: sql_help.c:5521 +#: sql_help.c:5565 msgid "define a new cast" msgstr "新しい型変換を定義します" -#: sql_help.c:5527 +#: sql_help.c:5571 msgid "define a new collation" msgstr "新しい照合順序を定義します" -#: sql_help.c:5533 +#: sql_help.c:5577 msgid "define a new encoding conversion" msgstr "新しいエンコーディング変換を定義します" -#: sql_help.c:5539 +#: sql_help.c:5583 msgid "create a new database" msgstr "新しいデータベースを作成します" -#: sql_help.c:5545 +#: sql_help.c:5589 msgid "define a new domain" msgstr "新しいドメインを定義します" -#: sql_help.c:5551 +#: sql_help.c:5595 msgid "define a new event trigger" msgstr "新しいイベントトリガーを定義します" -#: sql_help.c:5557 +#: sql_help.c:5601 msgid "install an extension" msgstr "機能拡張をインストールします" -#: sql_help.c:5563 +#: sql_help.c:5607 msgid "define a new foreign-data wrapper" msgstr "新しい外部データラッパを定義します" -#: sql_help.c:5569 +#: sql_help.c:5613 msgid "define a new foreign table" msgstr "新しい外部テーブルを定義します" -#: sql_help.c:5575 +#: sql_help.c:5619 msgid "define a new function" msgstr "新しい関数を定義します" -#: sql_help.c:5581 sql_help.c:5641 sql_help.c:5743 +#: sql_help.c:5625 sql_help.c:5685 sql_help.c:5787 msgid "define a new database role" msgstr "新しいデータベースロールを定義します" -#: sql_help.c:5587 +#: sql_help.c:5631 msgid "define a new index" msgstr "新しいインデックスを定義します" -#: sql_help.c:5593 +#: sql_help.c:5637 msgid "define a new procedural language" msgstr "新しい手続き言語を定義します" -#: sql_help.c:5599 +#: sql_help.c:5643 msgid "define a new materialized view" msgstr "新しい実体化ビューを定義します" -#: sql_help.c:5605 +#: sql_help.c:5649 msgid "define a new operator" msgstr "新しい演算子を定義します" -#: sql_help.c:5611 +#: sql_help.c:5655 msgid "define a new operator class" msgstr "新しい演算子クラスを定義します" -#: sql_help.c:5617 +#: sql_help.c:5661 msgid "define a new operator family" msgstr "新しい演算子族を定義します" -#: sql_help.c:5623 +#: sql_help.c:5667 msgid "define a new row-level security policy for a table" msgstr "テーブルに対して新しい行レベルセキュリティポリシーを定義します" -#: sql_help.c:5629 +#: sql_help.c:5673 msgid "define a new procedure" msgstr "新しいプロシージャを定義します" -#: sql_help.c:5635 +#: sql_help.c:5679 msgid "define a new publication" msgstr "新しいパブリケーションを定義します" -#: sql_help.c:5647 +#: sql_help.c:5691 msgid "define a new rewrite rule" msgstr "新しい書き換えルールを定義します" -#: sql_help.c:5653 +#: sql_help.c:5697 msgid "define a new schema" msgstr "新しいスキーマを定義します" -#: sql_help.c:5659 +#: sql_help.c:5703 msgid "define a new sequence generator" msgstr "新しいシーケンス生成器を定義します。" -#: sql_help.c:5665 +#: sql_help.c:5709 msgid "define a new foreign server" msgstr "新しい外部サーバーを定義します" -#: sql_help.c:5671 +#: sql_help.c:5715 msgid "define extended statistics" msgstr "拡張統計情報を定義します" -#: sql_help.c:5677 +#: sql_help.c:5721 msgid "define a new subscription" msgstr "新しいサブスクリプションを定義します" -#: sql_help.c:5683 +#: sql_help.c:5727 msgid "define a new table" msgstr "新しいテーブルを定義します" -#: sql_help.c:5689 sql_help.c:6211 +#: sql_help.c:5733 sql_help.c:6255 msgid "define a new table from the results of a query" msgstr "問い合わせの結果から新しいテーブルを定義します" -#: sql_help.c:5695 +#: sql_help.c:5739 msgid "define a new tablespace" msgstr "新しいテーブル空間を定義します" -#: sql_help.c:5701 +#: sql_help.c:5745 msgid "define a new text search configuration" msgstr "新しいテキスト検索設定を定義します" -#: sql_help.c:5707 +#: sql_help.c:5751 msgid "define a new text search dictionary" msgstr "新しいテキスト検索辞書を定義します" -#: sql_help.c:5713 +#: sql_help.c:5757 msgid "define a new text search parser" msgstr "新しいテキスト検索パーサーを定義します" -#: sql_help.c:5719 +#: sql_help.c:5763 msgid "define a new text search template" msgstr "新しいテキスト検索テンプレートを定義します" -#: sql_help.c:5725 +#: sql_help.c:5769 msgid "define a new transform" msgstr "新しいデータ変換を定義します" -#: sql_help.c:5731 +#: sql_help.c:5775 msgid "define a new trigger" msgstr "新しいトリガーを定義します" -#: sql_help.c:5737 +#: sql_help.c:5781 msgid "define a new data type" msgstr "新しいデータ型を定義します" -#: sql_help.c:5749 +#: sql_help.c:5793 msgid "define a new mapping of a user to a foreign server" msgstr "外部サーバーに対するユーザーの新しいマッピングを定義します。" -#: sql_help.c:5755 +#: sql_help.c:5799 msgid "define a new view" msgstr "新しいビューを定義します" -#: sql_help.c:5761 +#: sql_help.c:5805 msgid "deallocate a prepared statement" msgstr "準備した文を解放します" -#: sql_help.c:5767 +#: sql_help.c:5811 msgid "define a cursor" msgstr "カーソルを定義します" -#: sql_help.c:5773 +#: sql_help.c:5817 msgid "delete rows of a table" msgstr "テーブルの行を削除します" -#: sql_help.c:5779 +#: sql_help.c:5823 msgid "discard session state" msgstr "セッション状態を破棄します" -#: sql_help.c:5785 +#: sql_help.c:5829 msgid "execute an anonymous code block" msgstr "無名コードブロックを実行します" -#: sql_help.c:5791 +#: sql_help.c:5835 msgid "remove an access method" msgstr "アクセスメソッドを削除します" -#: sql_help.c:5797 +#: sql_help.c:5841 msgid "remove an aggregate function" msgstr "集約関数を削除します" -#: sql_help.c:5803 +#: sql_help.c:5847 msgid "remove a cast" msgstr "型変換を削除します" -#: sql_help.c:5809 +#: sql_help.c:5853 msgid "remove a collation" msgstr "照合順序を削除します" -#: sql_help.c:5815 +#: sql_help.c:5859 msgid "remove a conversion" msgstr "符号化方式変換を削除します" -#: sql_help.c:5821 +#: sql_help.c:5865 msgid "remove a database" msgstr "データベースを削除します" -#: sql_help.c:5827 +#: sql_help.c:5871 msgid "remove a domain" msgstr "ドメインを削除します" -#: sql_help.c:5833 +#: sql_help.c:5877 msgid "remove an event trigger" msgstr "イベントトリガーを削除します" -#: sql_help.c:5839 +#: sql_help.c:5883 msgid "remove an extension" msgstr "機能拡張を削除します" -#: sql_help.c:5845 +#: sql_help.c:5889 msgid "remove a foreign-data wrapper" msgstr "外部データラッパを削除します" -#: sql_help.c:5851 +#: sql_help.c:5895 msgid "remove a foreign table" msgstr "外部テーブルを削除します" -#: sql_help.c:5857 +#: sql_help.c:5901 msgid "remove a function" msgstr "関数を削除します" -#: sql_help.c:5863 sql_help.c:5929 sql_help.c:6031 +#: sql_help.c:5907 sql_help.c:5973 sql_help.c:6075 msgid "remove a database role" msgstr "データベースロールを削除します" -#: sql_help.c:5869 +#: sql_help.c:5913 msgid "remove an index" msgstr "インデックスを削除します" -#: sql_help.c:5875 +#: sql_help.c:5919 msgid "remove a procedural language" msgstr "手続き言語を削除します" -#: sql_help.c:5881 +#: sql_help.c:5925 msgid "remove a materialized view" msgstr "実体化ビューを削除します" -#: sql_help.c:5887 +#: sql_help.c:5931 msgid "remove an operator" msgstr "演算子を削除します" -#: sql_help.c:5893 +#: sql_help.c:5937 msgid "remove an operator class" msgstr "演算子クラスを削除します" -#: sql_help.c:5899 +#: sql_help.c:5943 msgid "remove an operator family" msgstr "演算子族を削除します" -#: sql_help.c:5905 +#: sql_help.c:5949 msgid "remove database objects owned by a database role" msgstr "データベースロールが所有するデータベースオブジェクトを削除します" -#: sql_help.c:5911 +#: sql_help.c:5955 msgid "remove a row-level security policy from a table" msgstr "テーブルから行レベルのセキュリティポリシーを削除します" -#: sql_help.c:5917 +#: sql_help.c:5961 msgid "remove a procedure" msgstr "プロシージャを削除します" -#: sql_help.c:5923 +#: sql_help.c:5967 msgid "remove a publication" msgstr "パブリケーションを削除します" -#: sql_help.c:5935 +#: sql_help.c:5979 msgid "remove a routine" msgstr "ルーチンを削除します" -#: sql_help.c:5941 +#: sql_help.c:5985 msgid "remove a rewrite rule" msgstr "書き換えルールを削除します" -#: sql_help.c:5947 +#: sql_help.c:5991 msgid "remove a schema" msgstr "スキーマを削除します" -#: sql_help.c:5953 +#: sql_help.c:5997 msgid "remove a sequence" msgstr "シーケンスを削除します" -#: sql_help.c:5959 +#: sql_help.c:6003 msgid "remove a foreign server descriptor" msgstr "外部サーバー記述子を削除します" -#: sql_help.c:5965 +#: sql_help.c:6009 msgid "remove extended statistics" msgstr "拡張統計情報を削除します" -#: sql_help.c:5971 +#: sql_help.c:6015 msgid "remove a subscription" msgstr "サブスクリプションを削除します" -#: sql_help.c:5977 +#: sql_help.c:6021 msgid "remove a table" msgstr "テーブルを削除します" -#: sql_help.c:5983 +#: sql_help.c:6027 msgid "remove a tablespace" msgstr "テーブル空間を削除します" -#: sql_help.c:5989 +#: sql_help.c:6033 msgid "remove a text search configuration" msgstr "テキスト検索設定を削除します" -#: sql_help.c:5995 +#: sql_help.c:6039 msgid "remove a text search dictionary" msgstr "テキスト検索辞書を削除します" -#: sql_help.c:6001 +#: sql_help.c:6045 msgid "remove a text search parser" msgstr "テキスト検索パーサーを削除します" -#: sql_help.c:6007 +#: sql_help.c:6051 msgid "remove a text search template" msgstr "テキスト検索テンプレートを削除します" -#: sql_help.c:6013 +#: sql_help.c:6057 msgid "remove a transform" msgstr "データ変換を削除します" -#: sql_help.c:6019 +#: sql_help.c:6063 msgid "remove a trigger" msgstr "トリガーを削除します" -#: sql_help.c:6025 +#: sql_help.c:6069 msgid "remove a data type" msgstr "データ型を削除します" -#: sql_help.c:6037 +#: sql_help.c:6081 msgid "remove a user mapping for a foreign server" msgstr "外部サーバーのユーザーマッピングを削除します" -#: sql_help.c:6043 +#: sql_help.c:6087 msgid "remove a view" msgstr "ビューを削除します" -#: sql_help.c:6055 +#: sql_help.c:6099 msgid "execute a prepared statement" msgstr "準備した文を実行します" -#: sql_help.c:6061 +#: sql_help.c:6105 msgid "show the execution plan of a statement" msgstr "文の実行計画を表示します" -#: sql_help.c:6067 +#: sql_help.c:6111 msgid "retrieve rows from a query using a cursor" msgstr "カーソルを使って問い合わせから行を取り出します" -#: sql_help.c:6073 +#: sql_help.c:6117 msgid "define access privileges" msgstr "アクセス権限を定義します" -#: sql_help.c:6079 +#: sql_help.c:6123 msgid "import table definitions from a foreign server" msgstr "外部サーバーからテーブル定義をインポートします" -#: sql_help.c:6085 +#: sql_help.c:6129 msgid "create new rows in a table" msgstr "テーブルに新しい行を作成します" -#: sql_help.c:6091 +#: sql_help.c:6135 msgid "listen for a notification" msgstr "通知メッセージを監視します" -#: sql_help.c:6097 +#: sql_help.c:6141 msgid "load a shared library file" msgstr "共有ライブラリファイルをロードします" -#: sql_help.c:6103 +#: sql_help.c:6147 msgid "lock a table" msgstr "テーブルをロックします" -#: sql_help.c:6109 +#: sql_help.c:6153 msgid "conditionally insert, update, or delete rows of a table" msgstr "条件によってテーブルの行を挿入、更新または削除する" -#: sql_help.c:6115 +#: sql_help.c:6159 msgid "position a cursor" msgstr "カーソルを位置づけます" -#: sql_help.c:6121 +#: sql_help.c:6165 msgid "generate a notification" msgstr "通知を生成します" -#: sql_help.c:6127 +#: sql_help.c:6171 msgid "prepare a statement for execution" msgstr "実行に備えて文を準備します" -#: sql_help.c:6133 +#: sql_help.c:6177 msgid "prepare the current transaction for two-phase commit" msgstr "二相コミットに備えて現在のトランザクションを準備します" -#: sql_help.c:6139 +#: sql_help.c:6183 msgid "change the ownership of database objects owned by a database role" msgstr "データベースロールが所有するデータベースオブジェクトの所有権を変更します" -#: sql_help.c:6145 +#: sql_help.c:6189 msgid "replace the contents of a materialized view" msgstr "実体化ビューの内容を置き換えます" -#: sql_help.c:6151 +#: sql_help.c:6195 msgid "rebuild indexes" msgstr "インデックスを再構築します" -#: sql_help.c:6157 +#: sql_help.c:6201 msgid "release a previously defined savepoint" msgstr "以前に定義されたセーブポイントを解放します" -#: sql_help.c:6163 +#: sql_help.c:6207 msgid "restore the value of a run-time parameter to the default value" msgstr "実行時パラメータの値をデフォルト値に戻します" -#: sql_help.c:6169 +#: sql_help.c:6213 msgid "remove access privileges" msgstr "アクセス権限を削除します" -#: sql_help.c:6181 +#: sql_help.c:6225 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "二相コミットのために事前に準備されたトランザクションをキャンセルします" -#: sql_help.c:6187 +#: sql_help.c:6231 msgid "roll back to a savepoint" msgstr "セーブポイントまでロールバックします" -#: sql_help.c:6193 +#: sql_help.c:6237 msgid "define a new savepoint within the current transaction" msgstr "現在のトランザクション内で新しいセーブポイントを定義します" -#: sql_help.c:6199 +#: sql_help.c:6243 msgid "define or change a security label applied to an object" msgstr "オブジェクトに適用されるセキュリティラベルを定義または変更します" -#: sql_help.c:6205 sql_help.c:6259 sql_help.c:6295 +#: sql_help.c:6249 sql_help.c:6303 sql_help.c:6339 msgid "retrieve rows from a table or view" msgstr "テーブルまたはビューから行を取得します" -#: sql_help.c:6217 +#: sql_help.c:6261 msgid "change a run-time parameter" msgstr "実行時パラメータを変更します" -#: sql_help.c:6223 +#: sql_help.c:6267 msgid "set constraint check timing for the current transaction" msgstr "現在のトランザクションについて、制約チェックのタイミングを設定します" -#: sql_help.c:6229 +#: sql_help.c:6273 msgid "set the current user identifier of the current session" msgstr "現在のセッションの現在のユーザー識別子を設定します" -#: sql_help.c:6235 +#: sql_help.c:6279 msgid "set the session user identifier and the current user identifier of the current session" msgstr "セッションのユーザー識別子および現在のセッションの現在のユーザー識別子を設定します" -#: sql_help.c:6241 +#: sql_help.c:6285 msgid "set the characteristics of the current transaction" msgstr "現在のトランザクションの特性を設定します" -#: sql_help.c:6247 +#: sql_help.c:6291 msgid "show the value of a run-time parameter" msgstr "実行時パラメータの値を表示します" -#: sql_help.c:6265 +#: sql_help.c:6309 msgid "empty a table or set of tables" msgstr "一つの、または複数のテーブルを空にします" -#: sql_help.c:6271 +#: sql_help.c:6315 msgid "stop listening for a notification" msgstr "通知メッセージの監視を中止します" -#: sql_help.c:6277 +#: sql_help.c:6321 msgid "update rows of a table" msgstr "テーブルの行を更新します" -#: sql_help.c:6283 +#: sql_help.c:6327 msgid "garbage-collect and optionally analyze a database" msgstr "ガーベッジコレクションを行い、また必要に応じてデータベースを分析します" -#: sql_help.c:6289 +#: sql_help.c:6333 msgid "compute a set of rows" msgstr "行セットを計算します" -#: startup.c:220 +#: startup.c:225 #, c-format msgid "-1 can only be used in non-interactive mode" msgstr "-1 は非対話モード時でのみ使用可能です" -#: startup.c:343 +#: startup.c:348 #, c-format msgid "could not open log file \"%s\": %m" msgstr "ロックファイル\"%s\"をオープンできませんでした: %m" -#: startup.c:460 +#: startup.c:465 #, c-format msgid "" "Type \"help\" for help.\n" @@ -6591,27 +6862,27 @@ msgstr "" "\"help\"でヘルプを表示します。\n" "\n" -#: startup.c:612 +#: startup.c:617 #, c-format msgid "could not set printing parameter \"%s\"" msgstr "表示パラメータ\"%s\"を設定できませんでした" -#: startup.c:719 +#: startup.c:724 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: startup.c:735 +#: startup.c:740 #, c-format msgid "extra command-line argument \"%s\" ignored" msgstr "余分なコマンドライン引数\"%s\"は無視されました" -#: startup.c:783 +#: startup.c:788 #, c-format msgid "could not find own program executable" msgstr "実行可能ファイルが見つかりませんでした" -#: tab-complete.c:6230 +#: tab-complete.in.c:6606 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6622,22 +6893,47 @@ msgstr "" "問い合わせ:\n" "%s" -#: variables.c:139 +#: variables.c:141 #, c-format msgid "unrecognized value \"%s\" for \"%s\": Boolean expected" msgstr "\"%2$s\"の値\"%1$s\"が認識できません: 真偽値を指定してください" -#: variables.c:176 +#: variables.c:178 #, c-format msgid "invalid value \"%s\" for \"%s\": integer expected" msgstr "\"%2$s\"の値\"%1$s\"が不正です: 整数を指定してください" -#: variables.c:224 +#: variables.c:207 +#, c-format +msgid "invalid input syntax for \"%s\"" +msgstr "\"%s\"に対する不正な入力構文" + +#: variables.c:218 +#, c-format +msgid "invalid value \"%s\" for \"%s\": must be greater than %.2f" +msgstr "\"%2$s\"の値\"%1$s\"が不正です: %3$.2f より大きい必要があります" + +#: variables.c:225 +#, c-format +msgid "invalid value \"%s\" for \"%s\": must be less than %.2f" +msgstr "\"%2$s\"の値\"%1$s\"が不正です: %3$.2f より小さい必要があります" + +#: variables.c:241 +#, c-format +msgid "\"%s\" is out of range for \"%s\"" +msgstr "\"%s\"は\"%s\"の範囲外です" + +#: variables.c:247 +#, c-format +msgid "invalid value \"%s\" for \"%s\"" +msgstr "\"%2$s\"に対する不正な値\"%1$s\"" + +#: variables.c:294 #, c-format msgid "invalid variable name: \"%s\"" msgstr "変数名が不正です: \"%s\"" -#: variables.c:418 +#: variables.c:488 #, c-format msgid "" "unrecognized value \"%s\" for \"%s\"\n" diff --git a/src/bin/psql/po/ko.po b/src/bin/psql/po/ko.po index 4f3c2db3bb6c8..6afbc04dd1dd5 100644 --- a/src/bin/psql/po/ko.po +++ b/src/bin/psql/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: psql (PostgreSQL) 16\n" +"Project-Id-Version: psql (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:48+0000\n" -"PO-Revision-Date: 2023-07-20 15:50+0900\n" +"POT-Creation-Date: 2025-01-17 04:48+0000\n" +"PO-Revision-Date: 2025-01-16 17:32+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -35,33 +35,48 @@ msgstr "상세정보: " msgid "hint: " msgstr "힌트: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "\"%s\" 파일은 잘못된 바이너리 파일: %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "\"%s\" 바이너리 파일을 읽을 수 없음: %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "실행할 \"%s\" 파일 찾을 수 없음" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "\"%s\" 경로를 절대경로로 바꿀 수 없음: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "\"%s\" 명령을 실행할 수 없음: %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "\"%s\" 명령으로부터 읽을 수 없음: %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "\"%s\" 명령에서 아무 데이터도 반환하지 않음" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() 실패: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -83,7 +98,7 @@ msgstr "null 포인터를 복제할 수 없음(내부 오류)\n" msgid "could not look up effective user ID %ld: %s" msgstr "UID %ld 해당하는 사용자를 찾을 수 없음: %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "사용자 없음" @@ -122,11 +137,11 @@ msgstr "하위 프로세스가 %d 신호를 받고 종료되었음: %s" msgid "child process exited with unrecognized status %d" msgstr "하위 프로세스가 알 수 없는 상태(%d)로 종료되었음" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "취소 요청 보냄\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "취소 요청 보내기 실패: " @@ -141,74 +156,91 @@ msgstr[0] "(%lu개 행)" msgid "Interrupted\n" msgstr "인트럽트발생\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "" +"Cannot print table contents: number of cells %lld is equal to or exceeds " +"maximum %lld.\n" +msgstr "테이블 내용을 출력할 수 없음: %lld개 셀 수가 최대값인 %lld개 이상임\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "테이블 내용에 헤더를 추가할 수 없음: 열 수가 %d개를 초과했습니다.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "테이블 내용에 셀을 추가할 수 없음: 총 셀 수가 %d개를 초과했습니다.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "테이블 내용에 셀을 추가할 수 없음: 총 셀 수가 %lld개를 초과했습니다.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "잘못된 출력 형식 (내부 오류): %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "\"%s\" 변수의 재귀적 확장을 건너뛰는 중" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령의 인자에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 있음: \"%s\"\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "UID %d 해당하는 로컬 사용자를 찾을 수 없음: %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "ID %d 로컬 사용자 없음" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "잘못된 명령: \\%s" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "도움말을 보려면 \\?를 입력하십시오." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: \"%s\" 추가 인자가 무시되었음" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "" "\\%s 명령은 무시함; 현재 \\if 블록을 중지하려면, \\endif 명령이나 Ctrl-C 키" "를 사용하세요." -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "UID %ld 사용자의 홈 디렉터리를 찾을 수 없음: %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: \"%s\" 디렉터리로 이동할 수 없음: %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "현재 데이터베이스에 연결되어있지 않습니다.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at " @@ -216,7 +248,7 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 주소=\"%s\", 포트=\"%s\".\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at " @@ -224,7 +256,7 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 소켓=\"%s\", 포트=\"%s\".\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address " @@ -233,7 +265,7 @@ msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 호스트=\"%s\" (주소=\"%s\"), 포" "트=\"%s\".\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port " @@ -241,199 +273,209 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 호스트=\"%s\", 포트=\"%s\".\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2675 #, c-format msgid "no query buffer" msgstr "쿼리 버퍼가 없음" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5776 #, c-format msgid "invalid line number: %s" msgstr "잘못된 줄 번호: %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "변경 내용 없음" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: 잘못된 인코딩 이름 또는 문자셋 변환 프로시저 없음" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:720 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5882 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1375 msgid "There is no previous error." msgstr "이전 오류가 없습니다." -#: command.c:1470 +#: command.c:1488 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: 오른쪽 괄호 빠졌음" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 +#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 #, c-format msgid "\\%s: missing required argument" msgstr "\\%s: 필요한 인자가 빠졌음" -#: command.c:1815 +#: command.c:1822 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: \\else 구문 뒤에 올 수 없음" -#: command.c:1820 +#: command.c:1827 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: \\if 명령과 짝이 안맞음" -#: command.c:1884 +#: command.c:1891 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: \\else 명령 뒤에 올 수 없음" -#: command.c:1889 +#: command.c:1896 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: \\if 명령과 짝이 안맞음" -#: command.c:1929 +#: command.c:1936 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: \\if 명령과 짝이 안맞음" -#: command.c:2085 +#: command.c:2092 msgid "Query buffer is empty." msgstr "쿼리 버퍼가 비었음." -#: command.c:2128 +#: command.c:2135 #, c-format msgid "Enter new password for user \"%s\": " msgstr "\"%s\" 사용자의 새 암호: " -#: command.c:2132 +#: command.c:2139 msgid "Enter it again: " msgstr "다시 입력해 주세요:" -#: command.c:2141 +#: command.c:2148 #, c-format msgid "Passwords didn't match." msgstr "암호가 서로 틀립니다." -#: command.c:2238 +#: command.c:2231 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: 변수 값을 읽을 수 없음" -#: command.c:2340 +#: command.c:2333 msgid "Query buffer reset (cleared)." msgstr "쿼리 버퍼 초기화 (비웠음)." -#: command.c:2362 +#: command.c:2355 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "명령내역(history)을 \"%s\" 파일에 기록했습니다.\n" -#: command.c:2449 +#: command.c:2442 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: OS 환경 변수 이름에는 \"=\" 문자가 없어야 함" -#: command.c:2497 +#: command.c:2490 #, c-format msgid "function name is required" msgstr "함수 이름이 필요함" -#: command.c:2499 +#: command.c:2492 #, c-format msgid "view name is required" msgstr "뷰 이름이 필요함" -#: command.c:2621 +#: command.c:2614 msgid "Timing is on." msgstr "작업수행시간 보임" -#: command.c:2623 +#: command.c:2616 msgid "Timing is off." msgstr "작업수행시간 숨김" -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 +#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 +#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2736 copy.c:388 +#: command.c:2729 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2806 command.c:2852 +#: command.c:2801 command.c:2867 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: 반복 간격 값은 하나만 지정해야 합니다" -#: command.c:2816 command.c:2862 +#: command.c:2811 command.c:2877 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: 잘못된 반복 간격 값 \"%s\"" -#: command.c:2826 +#: command.c:2821 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: 최대 반복 회수는 하나만 지정해야 합니다" -#: command.c:2836 +#: command.c:2831 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: 잘못된 최대 반복 회수 \"%s\"" -#: command.c:2843 +#: command.c:2841 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: 최소 row 수 지정을 중복 지정했음" + +#: command.c:2851 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch: 최소 row 수 값 잘못됨 \"%s\"" + +#: command.c:2858 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: 알수 없는 매개 변수 \"%s\"" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3255 startup.c:243 startup.c:293 msgid "Password: " msgstr "암호: " -#: command.c:3241 startup.c:290 +#: command.c:3260 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "%s 사용자의 암호: " -#: command.c:3297 +#: command.c:3316 #, c-format msgid "" "Do not give user, host, or port separately when using a connection string" msgstr "" "연결 문자열을 사용할 때는 user, host, port 를 따로 따로 지정하지 마세요." -#: command.c:3332 +#: command.c:3351 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "재접속할 데이터베이스 연결 정보가 없음" -#: command.c:3638 +#: command.c:3658 #, c-format msgid "Previous connection kept" msgstr "이전 연결이 유지되었음" -#: command.c:3644 +#: command.c:3664 #, c-format msgid "\\connect: %s" msgstr "\\연결: %s" -#: command.c:3700 +#: command.c:3720 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at " @@ -441,7 +483,7 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 주소=\"%s\", 포트=\"%s\".\n" -#: command.c:3703 +#: command.c:3723 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" " @@ -449,16 +491,16 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 소켓=\"%s\", 포트=\"%s\".\n" -#: command.c:3709 +#: command.c:3729 #, c-format msgid "" -"You are now connected to database \"%s\" as user \"%s\" on host \"%s" -"\" (address \"%s\") at port \"%s\".\n" +"You are now connected to database \"%s\" as user \"%s\" on host \"%s\" " +"(address \"%s\") at port \"%s\".\n" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 호스트=\"%s\" (주소 \"%s\"), 포" "트=\"%s\".\n" -#: command.c:3712 +#: command.c:3732 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at " @@ -466,17 +508,17 @@ msgid "" msgstr "" "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\", 호스트=\"%s\", 포트=\"%s\".\n" -#: command.c:3717 +#: command.c:3737 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "접속정보: 데이터베이스=\"%s\", 사용자=\"%s\".\n" -#: command.c:3757 +#: command.c:3843 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s(%s, %s 서버)\n" -#: command.c:3770 +#: command.c:3856 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -485,29 +527,33 @@ msgstr "" "경고: %s 메이저 버전 %s, 서버 메이저 버전 %s.\n" " 일부 psql 기능이 작동하지 않을 수도 있습니다.\n" -#: command.c:3807 +#: command.c:3895 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "SSL 연결정보 (프로토콜: %s, 암호화기법: %s, 압축: %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "SSL 연결정보 (프로토콜: %s, 암호화기법: %s, 압축: %s, ALPN: %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3896 command.c:3897 msgid "unknown" msgstr "알수없음" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "off" msgstr "off" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "on" msgstr "on" -#: command.c:3824 +#: command.c:3899 +msgid "none" +msgstr "none" + +#: command.c:3913 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "암호화된 GSSAPI 연결\n" -#: command.c:3844 +#: command.c:3933 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -519,7 +565,7 @@ msgstr "" "참조\n" " 페이지 \"Notes for Windows users\"를 참조하십시오.\n" -#: command.c:3949 +#: command.c:4038 #, c-format msgid "" "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a " @@ -528,32 +574,32 @@ msgstr "" "지정한 줄번호를 사용하기 위해서는 PSQL_EDITOR_LINENUMBER_ARG 이름의 OS 환경변" "수가 설정되어 있어야 합니다." -#: command.c:3979 +#: command.c:4068 #, c-format msgid "could not start editor \"%s\"" msgstr "\"%s\" 문서 편집기를 실행시킬 수 없음" -#: command.c:3981 +#: command.c:4070 #, c-format msgid "could not start /bin/sh" msgstr "/bin/sh 명령을 실행할 수 없음" -#: command.c:4031 +#: command.c:4120 #, c-format msgid "could not locate temporary directory: %s" msgstr "임시 디렉터리 경로를 알 수 없음: %s" -#: command.c:4058 +#: command.c:4147 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "\"%s\" 임시 파일을 열 수 없음: %m" -#: command.c:4394 +#: command.c:4483 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: \"%s\" 생략형이 \"%s\" 또는 \"%s\" 값 모두 선택가능해서 모호함" -#: command.c:4414 +#: command.c:4503 #, c-format msgid "" "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-" @@ -562,27 +608,27 @@ msgstr "" "\\pset: 허용되는 출력 형식: aligned, asciidoc, csv, html, latex, latex-" "longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4522 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: 사용할 수 있는 선 모양은 ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4537 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: 사용할 수 있는 유니코드 테두리 모양은 single, double" -#: command.c:4463 +#: command.c:4552 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: 사용할 수 있는 유니코드 칼럼 선 모양은 single, double" -#: command.c:4478 +#: command.c:4567 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: 사용할 수 있는 유니코드 헤더 선 모양은 single, double" -#: command.c:4530 +#: command.c:4619 #, c-format msgid "" "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", " @@ -591,12 +637,12 @@ msgstr "" "\\pset: xheader_width 값은 \"%s\" (기본값), \"%s\", \"%s\", 또는 정확한 너비 " "숫자 입니다." -#: command.c:4547 +#: command.c:4636 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep 문자는 1바이트의 단일 문자여야 함" -#: command.c:4552 +#: command.c:4641 #, c-format msgid "" "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage " @@ -604,218 +650,218 @@ msgid "" msgstr "" "\\pset: csv_fieldsep 문자로 따옴표, 줄바꿈(\\n, \\r) 문자는 사용할 수 없음" -#: command.c:4690 command.c:4891 +#: command.c:4779 command.c:4980 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: 알 수 없는 옵션: %s" -#: command.c:4710 +#: command.c:4799 #, c-format msgid "Border style is %d.\n" msgstr "html 테이블의 테두리를 %d로 지정했습니다.\n" -#: command.c:4716 +#: command.c:4805 #, c-format msgid "Target width is unset.\n" msgstr "대상 너비 미지정.\n" -#: command.c:4718 +#: command.c:4807 #, c-format msgid "Target width is %d.\n" msgstr "대상 너비는 %d입니다.\n" -#: command.c:4725 +#: command.c:4814 #, c-format msgid "Expanded display is on.\n" msgstr "칼럼 단위 보기 기능 켬.\n" -#: command.c:4727 +#: command.c:4816 #, c-format msgid "Expanded display is used automatically.\n" msgstr "칼럼 단위 보기 기능을 자동으로 지정 함.\n" -#: command.c:4729 +#: command.c:4818 #, c-format msgid "Expanded display is off.\n" msgstr "칼럼 단위 보기 기능 끔.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4825 command.c:4827 command.c:4829 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "확장된 헤더 너비 = \"%s\".\n" -#: command.c:4742 +#: command.c:4831 #, c-format msgid "Expanded header width is %d.\n" msgstr "확장된 헤더 너비는 %d입니다.\n" -#: command.c:4748 +#: command.c:4837 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "CSV용 필드 구분자: \"%s\".\n" -#: command.c:4756 command.c:4764 +#: command.c:4845 command.c:4853 #, c-format msgid "Field separator is zero byte.\n" msgstr "필드 구분자가 0 바이트입니다.\n" -#: command.c:4758 +#: command.c:4847 #, c-format msgid "Field separator is \"%s\".\n" msgstr "필드 구분자 \"%s\".\n" -#: command.c:4771 +#: command.c:4860 #, c-format msgid "Default footer is on.\n" msgstr "기본 꼬릿말 보기 기능 켬.\n" -#: command.c:4773 +#: command.c:4862 #, c-format msgid "Default footer is off.\n" msgstr "기본 꼬릿말 보기 기능 끔.\n" -#: command.c:4779 +#: command.c:4868 #, c-format msgid "Output format is %s.\n" msgstr "현재 출력 형식: %s.\n" -#: command.c:4785 +#: command.c:4874 #, c-format msgid "Line style is %s.\n" msgstr "선 모양: %s.\n" -#: command.c:4792 +#: command.c:4881 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null 값은 \"%s\" 문자로 보여짐.\n" -#: command.c:4800 +#: command.c:4889 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "로케일 맞춤 숫자 표기 기능 켬.\n" -#: command.c:4802 +#: command.c:4891 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "로케일 맞춤 숫자 표기 기능 끔.\n" -#: command.c:4809 +#: command.c:4898 #, c-format msgid "Pager is used for long output.\n" msgstr "긴 출력을 위해 페이저가 사용됨.\n" -#: command.c:4811 +#: command.c:4900 #, c-format msgid "Pager is always used.\n" msgstr "항상 페이저가 사용됨.\n" -#: command.c:4813 +#: command.c:4902 #, c-format msgid "Pager usage is off.\n" msgstr "화면단위 보기 기능 끔(전체 자료 모두 보여줌).\n" -#: command.c:4819 +#: command.c:4908 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "%d 줄보다 적은 경우는 페이지 단위 보기가 사용되지 않음\n" -#: command.c:4829 command.c:4839 +#: command.c:4918 command.c:4928 #, c-format msgid "Record separator is zero byte.\n" msgstr "레코드 구분자가 0 바이트임.\n" -#: command.c:4831 +#: command.c:4920 #, c-format msgid "Record separator is .\n" msgstr "레코드 구분자는 줄바꿈 문자입니다.\n" -#: command.c:4833 +#: command.c:4922 #, c-format msgid "Record separator is \"%s\".\n" msgstr "레코드 구분자 \"%s\".\n" -#: command.c:4846 +#: command.c:4935 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "테이블 속성: \"%s\".\n" -#: command.c:4849 +#: command.c:4938 #, c-format msgid "Table attributes unset.\n" msgstr "테이블 속성 모두 지움.\n" -#: command.c:4856 +#: command.c:4945 #, c-format msgid "Title is \"%s\".\n" msgstr "출력 테이블의 제목: \"%s\"\n" -#: command.c:4858 +#: command.c:4947 #, c-format msgid "Title is unset.\n" msgstr "출력 테이블의 제목을 지정하지 않았습니다.\n" -#: command.c:4865 +#: command.c:4954 #, c-format msgid "Tuples only is on.\n" msgstr "자료만 보기 기능 켬.\n" -#: command.c:4867 +#: command.c:4956 #, c-format msgid "Tuples only is off.\n" msgstr "자료만 보기 기능 끔.\n" -#: command.c:4873 +#: command.c:4962 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "유니코드 테두리 선문자: \"%s\".\n" -#: command.c:4879 +#: command.c:4968 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "유니코드 칼럼 선문자: \"%s\".\n" -#: command.c:4885 +#: command.c:4974 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "유니코드 헤더 선문자: \"%s\".\n" -#: command.c:5134 +#: command.c:5223 #, c-format msgid "\\!: failed" msgstr "\\!: 실패" -#: command.c:5168 +#: command.c:5261 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch 명령으로 수행할 쿼리가 없습니다." -#: command.c:5200 +#: command.c:5293 #, c-format msgid "could not set timer: %m" msgstr "타이머 설정 실패: %m" -#: command.c:5269 +#: command.c:5362 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (%g초 간격)\n" -#: command.c:5272 +#: command.c:5365 #, c-format msgid "%s (every %gs)\n" msgstr "%s (%g초 간격)\n" -#: command.c:5340 +#: command.c:5429 #, c-format msgid "could not wait for signals: %m" msgstr "신호를 기다릴 수 없었음: %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5485 command.c:5492 common.c:632 common.c:639 common.c:1123 #, c-format msgid "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" msgstr "" "********** 쿼리 **********\n" @@ -823,149 +869,154 @@ msgstr "" "**************************\n" "\n" -#: command.c:5584 +#: command.c:5671 #, c-format msgid "\"%s.%s\" is not a view" msgstr "\"%s.%s\" 뷰(view)가 아님" -#: command.c:5600 +#: command.c:5687 #, c-format msgid "could not parse reloptions array" msgstr "reloptions 배열을 분석할 수 없음" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "현재 접속한 연결 없이는 특수문자처리를 할 수 없음" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "쉘 명령의 인자에 줄바꿈 문자가 있음: \"%s\"" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "서버 접속 끊김" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "서버로부터 연결이 끊어졌습니다. 다시 연결을 시도합니다: " -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "실패.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "성공.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "PQresultStatus 반환값이 잘못됨: %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "작업시간: %.3f ms\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "작업시간: %.3f ms (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "작업시간: %.3f ms (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "작업시간: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "현재 데이터베이스에 연결되어있지 않습니다." -#: common.c:674 +#: common.c:714 #, c-format msgid "" "Asynchronous notification \"%s\" with payload \"%s\" received from server " "process with PID %d.\n" msgstr "\"%s\" 비동기 통지를 받음, 부가정보: \"%s\", 보낸 프로세스: %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "" "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "동기화 신호 \"%s\" 받음, 해당 서버 프로세스 PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "결과 테이블을 출력할 수 없음: %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "\\gset 해당 자료 없음" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "\\gset 실행 결과가 단일 자료가 아님" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "" "\\gset 작업으로 특수하게 처리되는 변수인 \"%s\" 변수값을 바꿀 수 있어 무시함" -#: common.c:1063 +#: common.c:1103 #, c-format msgid "" -"***(Single step mode: verify " -"command)*******************************************\n" +"/**(Single step mode: verify " +"command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to " -"cancel)********************\n" +"/**(press return to proceed or enter x and return to " +"cancel)*******************/\n" msgstr "" "***(단독 순차 모드: 쿼리 확인)*********************************************\n" "%s\n" "***(Enter: 계속 진행, x Enter: 중지)********************\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "명령구문: %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "알 수 없는 트랜잭션 상태 (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "필드명" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "형태" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "해당 명령 결과가 없거나, 그 결과에는 칼럼이 없습니다.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "청크된 모드에서 결과값 추출 실패" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -981,11 +1032,6 @@ msgstr "\\copy: 구문 오류: \"%s\"" msgid "\\copy: parse error at end of line" msgstr "\\copy: 줄 끝에 구문 오류" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "\"%s\" 명령을 실행할 수 없음: %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -1024,31 +1070,31 @@ msgstr "" "자료입력이 끝나면 backslash 점 (\\.) 마지막 줄 처음에 입력하는 EOF 시그널을 " "보내세요." -#: copy.c:682 +#: copy.c:684 msgid "aborted because of read failure" msgstr "읽기 실패로 중지됨" -#: copy.c:716 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "복사 모드를 종료하는 중" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview: 구문 결과가 집합을 반환하지 않았음" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview: 쿼리 결과는 적어도 세 개의 칼럼은 반환 해야 함" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "" "\\crosstabview: vertical and horizontal headers must be different columns" msgstr "\\crosstabview: 행과 열의 칼럼이 각각 다른 칼럼이어야 함" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "" "\\crosstabview: data column must be specified when query returns more than " @@ -1057,12 +1103,12 @@ msgstr "" "\\crosstabview: 처리할 칼럼이 세개보다 많을 때는 자료로 사용할 칼럼을 지정해" "야 함" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview: 최대 칼럼 수 (%d) 초과" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "" "\\crosstabview: query result contains multiple data values for row \"%s\", " @@ -1070,300 +1116,301 @@ msgid "" msgstr "" "\\crosstabview: \"%s\" 로우, \"%s\" 칼럼에 대해 쿼리 결과는 다중값이어야 함" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview: %d 번째 열은 1..%d 범위를 벗어났음" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview: 칼럼 이름이 모호함: \"%s\"" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: 칼럼 이름 없음: \"%s\"" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "스키마" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "이름" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "반환 자료형" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "인자 자료형" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "설명" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "통계 함수 목록" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "서버(%s 버전)에서 접근 방법을 지원하지 않습니다." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "인덱스" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "테이블" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "핸들러" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "접근 방법 목록" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "소유주" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "위치" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "옵션" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "크기" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "테이블스페이스 목록" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df 명령은 [anptwS+]만 추가로 사용함" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df 명령은 \"%c\" 옵션을 %s 버전 서버에서는 사용할 수 없음" #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "집계" -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "창" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "proc" -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "함수" -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "트리거" -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "immutable" -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "stable" -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "volatile" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "휘발성" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "엄격함" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "safe" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "unsafe" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "병렬처리" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "definer" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "invoker" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "보안" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "언어" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "내부 이름" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "함수 목록" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "요소" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "자료형 목록" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "왼쪽 인수 자료형" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "오른쪽 인수 자료형" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "반환 자료형" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "함수" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "연산자 목록" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "인코딩" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "로케일 제공자" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "Collate" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "Ctype" -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "ICU 로케일" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "로케일" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "ICU 룰" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "테이블스페이스" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "데이터베이스 목록" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "테이블" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "뷰(view)" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "구체화된 뷰" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "시퀀스" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "외부 테이블" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "파티션 테이블" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "칼럼 접근권한" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "정책" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "액세스 권한" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "함수" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "type" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "스키마" @@ -1395,293 +1442,293 @@ msgstr "연산자 부류" msgid "rule" msgstr "룰(rule)" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "개체 설명" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "\"%s\" 이름을 릴레이션(relation) 없음." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "관련 릴레이션 찾을 수 없음." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "%s oid의 어떤 릴레이션(relation)도 찾을 수 없음." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "시작" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "최소값" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "최대값" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "증가값" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "예" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "아니오" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "순환?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "캐쉬" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "소유주: %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "식별 칼럼용 시퀀스: %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "\"%s.%s\" 로그 미사용 시퀀스" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "\"%s.%s\" 시퀀스" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "로그 미사용 테이블 \"%s.%s\"" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "\"%s.%s\" 테이블" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "\"%s.%s\" 뷰(view)" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "트랜잭션 로그를 남기지 않은 구체화된 뷰 \"%s.%s\"" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Materialized 뷰 \"%s.%s\"" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "\"%s.%s\" 로그 미사용 인덱스" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "\"%s.%s\" 인덱스" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "\"%s.%s\" 로그 미사용 파티션 인덱스" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "\"%s.%s\" 파티션 인덱스" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "\"%s.%s\" TOAST 테이블" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "\"%s.%s\" 복합자료형" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "\"%s.%s\" 외부 테이블" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "로그 미사용 파티션 테이블 \"%s.%s\"" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "\"%s.%s\" 파티션 테이블" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "정렬규칙" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "NULL허용" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "초기값" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "Key?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "정의" -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "FDW 옵션" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "스토리지" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "압축" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "통계수집량" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "소속 파티션: %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "파티션 제약 조건 없음" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "파티션 제약조건: %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "파티션 키: %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "소속 테이블: \"%s.%s\"" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "기본키, " -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "고유" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " nulls not distinct" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr ", " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "적용테이블: \"%s.%s\"" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", predicate (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", 클러스됨" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", 잘못됨" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", 지연가능" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", 트랜잭션단위지연" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", 복제 식별자" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "인덱스들:" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "체크 제약 조건:" -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "참조키 제약 조건:" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "다음에서 참조됨:" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "정책:" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "정책 (로우단위 보안정책 강제 활성화):" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "정책 (로우단위 보안정책 활성화): (없음)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "정책 (로우단위 보안정책 강제 활성화): (없음)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "정책 (로우단위 보안정책 비활성화):" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "통계정보 객체:" @@ -1701,7 +1748,7 @@ msgstr "항상 발생하는 규칙:" msgid "Rules firing on replica only:" msgstr "복제본에서만 발생하는 규칙:" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "발행자:" @@ -1800,7 +1847,7 @@ msgstr ", \"%s\" 테이블스페이스" msgid "List of roles" msgstr "롤 목록" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "롤 이름" @@ -1877,369 +1924,369 @@ msgstr "\"%s\" 롤용 특정 설정이 없음." msgid "Did not find any settings." msgstr "추가 설정 없음." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "설정 목록" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "소속 그룹" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "부여자" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "롤 부여 목록" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "인덱스" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "TOAST 테이블" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "파티션_인덱스" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "영구" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "임시" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "로깅안함" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "지속성" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "접근 방법" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "릴레이션 목록" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "" "The server (version %s) does not support declarative table partitioning." msgstr "이 서버(%s 버전)는 파티션 테이블 기능을 지원하지 않습니다." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "파티션 인덱스 목록" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "파티션 테이블 목록" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "파티션 릴레이션(relation) 목록" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "상위 이름" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "하위 파티션 크기" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "전체 크기" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "신뢰됨" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "내부 언어" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "호출 핸들러" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "유효성 검사기" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "인라인 핸들러" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "언어 목록" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "체크" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "도메인(domain) 목록" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "소스" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "설명" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "초기값?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "문자코드변환규칙(conversion) 목록" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "매개변수" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "값" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "컨텍스트" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "환경설정 매개변수 목록" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "기본값이 아닌 값으로 지정된 환경설정 매개변수 목록" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "이 서버(%s 버전)는 이벤트 트리거를 지원하지 않습니다." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "이벤트" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "활성화" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "replica" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "항상" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "비활성화" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "활성화" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "태그" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "이벤트 트리거 목록" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "이 서버(%s 버전)에서 확장 통계정보를 지원하지 않습니다." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Dependencies" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "확장 통계정보 목록" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Source 자료형" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Target 자료형" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "in assignment" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Implicit?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "형변환자 목록" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "제공자" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "Deterministic?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "문자 정렬 목록" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "스키마 목록" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "텍스트 검색 파서 목록" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "\"%s\"(이)라는 전문 검색 분석기를 찾지 못했습니다." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "특정 전문 검색 분석기를 찾지 못했습니다." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "구문 분석 시작" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "방법" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "다음 토큰 가져오기" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "구문 분석 종료" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "헤드라인 가져오기" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "토큰 형식 가져오기" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "\"%s.%s\" 텍스트 검색 파서" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "\"%s\" 텍스트 검색 파서" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "토큰 이름" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "\"%s.%s\" 파서의 토큰 형식" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "\"%s\" 파서의 토큰 형식" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "템플릿" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "초기화 옵션" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "텍스트 검색 사전 목록" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "초기화" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Lexize" -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "텍스트 검색 템플릿 목록" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "텍스트 검색 구성 목록" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "\"%s\"(이)라는 텍스트 검색 구성을 찾지 못했습니다." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "특정 텍스트 검색 구성을 찾지 못했습니다." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "토큰" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "사전" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "텍스트 검색 구성 \"%s.%s\"" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "텍스트 검색 구성 \"%s\"" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "" "\n" @@ -2248,7 +2295,7 @@ msgstr "" "\n" "파서: \"%s.%s\"" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "" "\n" @@ -2257,265 +2304,273 @@ msgstr "" "\n" "파서: \"%s\"" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "외부 데이터 래퍼 목록" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "외부 데이터 래퍼" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "버전" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "외부 서버 목록" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "서버" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "사용자 이름" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "사용자 매핑 목록" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "외부 테이블 목록" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "설치된 확장기능 목록" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "\"%s\" 이름의 확장 기능 모듈을 찾을 수 없습니다." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "추가할 확장 기능 모듈이 없음." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "개체 설명" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "\"%s\" 확장 기능 안에 포함된 객체들" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "적당하지 않은 qualified 이름 입니다 (너무 많은 점이 있네요): %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "서로 다른 데이터베이스간의 참조는 구현되어있지 않습니다: %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "이 서버(%s 버전)는 논리 복제 발행 기능을 지원하지 않습니다." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "모든 테이블" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Inserts" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Updates" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Deletes" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Truncates" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Via root" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "발행 목록" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "\"%s\" 이름의 발행 없음." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "발행 없음." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "%s 발행" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "테이블들:" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "다음 스키마의 모든 테이블:" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "이 서버(%s 버전)는 구독 기능을 지원하지 않습니다." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "발행" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "바이너리" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "스트리밍" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "2단계 커밋" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "오류가 생기면 비활성" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "오리진" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "비밀번호 필요함" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "소유주 권한으로 실행?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "Failover" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "동기식 커밋" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "연결정보" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "LSN 건너뜀" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "구독 목록" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(none)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "AM" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "입력 자료형" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "스토리지 유형" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "연산자 클래스" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "연산자 부류" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "연산자 클래스 목록" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Applicable types" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "연산자 부류 목록" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "연산자" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "전략번호" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "ordering" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "search" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "Purpose" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "정렬 연산자 부류" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "연산자 부류 소속 연산자 목록" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "등록된 왼쪽 자료형" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "등록된 오른쪽 자료형" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "번호" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "연산자 부류 소속 지원 함수 목록" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "대형 객체들" -#: help.c:75 +#: help.c:63 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2523,11 +2578,11 @@ msgstr "" "psql은 PostgreSQL 대화식 터미널입니다.\n" "\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:502 msgid "Usage:\n" msgstr "사용법:\n" -#: help.c:77 +#: help.c:65 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2535,33 +2590,31 @@ msgstr "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "일반 옵션:\n" -#: help.c:84 +#: help.c:68 msgid "" " -c, --command=COMMAND run only single command (SQL or internal) and " "exit\n" msgstr "" " -c, --command=COMMAND 하나의 명령(SQL 또는 내부 명령)만 실행하고 끝냄\n" -#: help.c:85 -#, c-format -msgid "" -" -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr " -d, --dbname=DBNAME 연결할 데이터베이스 이름(기본 값: \"%s\")\n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=DBNAME 연결할 데이터베이스 이름\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=FILENAME 파일 안에 지정한 명령을 실행하고 끝냄\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr "" " -l, --list 사용 가능한 데이터베이스 목록을 표시하고 끝냄\n" -#: help.c:89 +#: help.c:72 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2571,15 +2624,15 @@ msgstr "" " psql 변수 NAME을 VALUE로 설정\n" " (예, -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc 시작 파일(~/.psqlrc)을 읽지 않음\n" -#: help.c:94 +#: help.c:77 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-" @@ -2588,21 +2641,21 @@ msgstr "" " -1 (\"one\"), --single-transaction\n" " 명령 파일을 하나의 트랜잭션으로 실행\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=options] 이 도움말을 표시하고 종료\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr "" " --help=commands psql 내장명령어(\\문자로 시작하는)를 표시하고 종" "료\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables 특별 변수들 보여주고, 종료\n" -#: help.c:100 +#: help.c:83 msgid "" "\n" "Input and output options:\n" @@ -2610,53 +2663,53 @@ msgstr "" "\n" "입출력 옵션:\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all 스크립트의 모든 입력 표시\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors 실패한 명령들 출력\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries 서버로 보낸 명령 표시\n" -#: help.c:104 +#: help.c:87 msgid "" " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden 내부 명령이 생성하는 쿼리 표시\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=FILENAME 세션 로그를 파일로 보냄\n" -#: help.c:106 +#: help.c:89 msgid "" " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr "" " -n, --no-readline 확장된 명령행 편집 기능을 사용중지함(readline)\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=FILENAME 쿼리 결과를 파일(또는 |파이프)로 보냄\n" -#: help.c:108 +#: help.c:91 msgid "" " -q, --quiet run quietly (no messages, only query output)\n" msgstr " -q, --quiet 자동 실행(메시지 없이 쿼리 결과만 표시)\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step 단독 순차 모드(각 쿼리 확인)\n" -#: help.c:110 +#: help.c:93 msgid "" " -S, --single-line single-line mode (end of line terminates SQL " "command)\n" msgstr " -S, --single-line 한 줄 모드(줄 끝에서 SQL 명령이 종료됨)\n" -#: help.c:112 +#: help.c:95 msgid "" "\n" "Output format options:\n" @@ -2664,16 +2717,16 @@ msgstr "" "\n" "출력 형식 옵션:\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align 정렬되지 않은 표 형태의 출력 모드\n" -#: help.c:114 +#: help.c:97 msgid "" " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv CSV (쉼표-분리 자료) 테이블 출력 모드\n" -#: help.c:115 +#: help.c:98 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2681,21 +2734,21 @@ msgid "" "\"%s\")\n" msgstr "" " -F, --field-separator=STRING\n" -" unaligned 출력용 필드 구분자 설정(기본 값: \"%s" -"\")\n" +" unaligned 출력용 필드 구분자 설정(기본 값: " +"\"%s\")\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html HTML 표 형태 출력 모드\n" -#: help.c:119 +#: help.c:102 msgid "" " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset " "command)\n" msgstr "" " -P, --pset=VAR[=ARG] 인쇄 옵션 VAR을 ARG로 설정(\\pset 명령 참조)\n" -#: help.c:120 +#: help.c:103 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: " @@ -2705,22 +2758,22 @@ msgstr "" " unaligned 출력용 레코드 구분자 설정\n" " (기본 값: 줄바꿈 문자)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only 행만 인쇄\n" -#: help.c:123 +#: help.c:106 msgid "" " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, " "border)\n" msgstr "" " -T, --table-attr=TEXT HTML table 태그 속성 설정(예: width, border)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded 확장된 표 형태로 출력\n" -#: help.c:125 +#: help.c:108 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero " @@ -2729,7 +2782,7 @@ msgstr "" " -z, --field-separator-zero\n" " unaligned 출력용 필드 구분자를 0 바이트로 지정\n" -#: help.c:127 +#: help.c:110 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero " @@ -2738,7 +2791,7 @@ msgstr "" " -0, --record-separator-zero\n" " unaligned 출력용 레코드 구분자를 0 바이트로 지정\n" -#: help.c:130 +#: help.c:113 msgid "" "\n" "Connection options:\n" @@ -2746,44 +2799,34 @@ msgstr "" "\n" "연결 옵션들:\n" -#: help.c:133 -#, c-format -msgid "" -" -h, --host=HOSTNAME database server host or socket directory " -"(default: \"%s\")\n" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME 데이터베이스 서버 호스트 또는 소켓 디렉터리\n" -" (기본값: \"%s\")\n" -#: help.c:134 -msgid "local socket" -msgstr "로컬 소켓" - -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr " -p, --port=PORT 데이터베이스 서버 포트(기본 값: \"%s\")\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PORT 데이터베이스 서버 포트\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr " -U, --username=USERNAME 데이터베이스 사용자 이름(기본 값: \"%s\")\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=USERNAME 데이터베이스 사용자 이름\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password 암호 프롬프트 표시 안 함\n" -#: help.c:143 +#: help.c:118 msgid "" " -W, --password force password prompt (should happen " "automatically)\n" msgstr " -W, --password 암호 입력 프롬프트 보임(자동으로 처리함)\n" -#: help.c:145 +#: help.c:120 msgid "" "\n" -"For more information, type \"\\?\" (for internal commands) or \"\\help" -"\" (for SQL\n" +"For more information, type \"\\?\" (for internal commands) or \"\\help\" " +"(for SQL\n" "commands) from within psql, or consult the psql section in the PostgreSQL\n" "documentation.\n" "\n" @@ -2794,43 +2837,43 @@ msgstr "" "설명서에서 psql 섹션을 참조하십시오.\n" "\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "문제점 보고 주소: <%s>\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "일반\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [PARAM]... 쿼리 매개 변수 지정\n" -#: help.c:193 +#: help.c:168 msgid "" " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright PostgreSQL 사용법 및 저작권 정보 표시\n" -#: help.c:194 +#: help.c:169 msgid "" " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr "" " \\crosstabview [칼럼들] 쿼리를 실행하고, 피봇 테이블 형태로 자료를 보여줌\n" -#: help.c:195 +#: help.c:170 msgid "" " \\errverbose show most recent error message at maximum " "verbosity\n" msgstr "" " \\errverbose 최대 자세히 보기 상태에서 최근 오류를 다 보여줌\n" -#: help.c:196 +#: help.c:171 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2838,59 +2881,64 @@ msgstr "" " \\g [(OPTIONS)] [FILE] 쿼리 실행 (결과는 지정한 파일로, 또는 |파이프로);\n" " \\g 명령에서 인자가 없으면 세미콜론과 같음\n" -#: help.c:198 +#: help.c:173 msgid "" " \\gdesc describe result of query, without executing it\n" msgstr "" " \\gdesc 쿼리를 실행하지 않고 그 결과 칼럼과 자료형을 출력\n" -#: help.c:199 +#: help.c:174 msgid "" " \\gexec execute query, then execute each value in its " "result\n" msgstr " \\gexec 쿼리를 실행하고, 그 결과를 각각 실행 함\n" -#: help.c:200 +#: help.c:175 msgid "" " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr " \\gset [PREFIX] 쿼리 실행 뒤 그 결과를 psql 변수로 저장\n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr "" " \\gx [(OPTIONS)] [FILE] \\g 명령과 같으나, 출력을 확장 모드로 강제함\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q psql 종료\n" -#: help.c:203 +#: help.c:178 msgid "" -" \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" -msgstr " \\watch [[i=]SEC] [c=N] SEC초 간격, N번 반복\n" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" +msgstr "" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" SEC 초 마다 쿼리 반복, N 회만 실행,\n" +" MIN 로우 보다 적게 출력하면 중지\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "도움말\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commands] psql 역슬래시 명령어 설명\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options psql 명령행 옵션 도움말 보기\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables psql 환경 설정 변수들에 설명 보기\n" -#: help.c:211 +#: help.c:188 msgid "" " \\h [NAME] help on syntax of SQL commands, * for all " "commands\n" @@ -2898,46 +2946,46 @@ msgstr "" " \\h [NAME] SQL 명령 구문 도움말, 모든 명령을 표시하려면 * 입" "력\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "쿼리 버퍼\n" -#: help.c:215 +#: help.c:192 msgid "" " \\e [FILE] [LINE] edit the query buffer (or file) with external " "editor\n" msgstr " \\e [FILE] [LINE] 외부 편집기로 쿼리 버퍼(또는 파일) 편집\n" -#: help.c:216 +#: help.c:193 msgid "" " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr " \\ef [FUNCNAME [LINE]] 외부 편집기로 해당 함수 내용 편집\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr " \\ev [VIEWNAME [LINE]] 외부 편집기로 해당 뷰 정의 편집\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p 쿼리 버퍼의 내용 표시\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r 쿼리 버퍼 초기화(모두 지움)\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [FILE] 기록 표시 또는 파일에 저장\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr " \\w FILE 쿼리 버퍼를 파일에 기록\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "입력/출력\n" -#: help.c:227 +#: help.c:204 msgid "" " \\copy ... perform SQL COPY with data stream to the client " "host\n" @@ -2945,155 +2993,155 @@ msgstr "" " \\copy ... 클라이언트 호스트에 있는 자료를 SQL COPY 명령 실" "행\n" -#: help.c:228 +#: help.c:205 msgid "" " \\echo [-n] [STRING] write string to standard output (-n for no " "newline)\n" msgstr " \\echo [-n] [STRING] 문자열을 표준 출력에 기록 (-n 줄바꿈 없음)\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i FILE 파일에서 명령 실행\n" -#: help.c:230 +#: help.c:207 msgid "" " \\ir FILE as \\i, but relative to location of current " "script\n" msgstr "" " \\ir FILE \\i 명령과 같으나, 경로가 현재 위치 기준 상대적\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [FILE] 모든 쿼리 결과를 파일 또는 |파이프로 보냄\n" -#: help.c:232 +#: help.c:209 msgid "" " \\qecho [-n] [STRING] write string to \\o output stream (-n for no " "newline)\n" msgstr "" " \\qecho [-n] [STRING] 문자열을 \\o 출력 스트림에 기록 (-n 줄바꿈 없음)\n" -#: help.c:233 +#: help.c:210 msgid "" " \\warn [-n] [STRING] write string to standard error (-n for no " "newline)\n" msgstr " \\warn [-n] [STRING] 문자열을 stderr에 기록 (-n 줄바꿈 없음)\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "조건문\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPR 조건문 시작\n" -#: help.c:238 +#: help.c:215 msgid "" " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif EXPR else if 구문 시작\n" -#: help.c:239 +#: help.c:216 msgid "" " \\else final alternative within current conditional " "block\n" msgstr " \\else 조건문의 그 외 조건\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif 조건문 끝\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "정보보기\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr " (옵션: S = 시스템 개체 표시, + = 추가 상세 정보)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr " \\d[S+] 테이블, 뷰 및 시퀀스 목록\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr " \\d[S+] NAME 테이블, 뷰, 시퀀스 또는 인덱스 설명\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" msgstr " \\da[S] [PATTERN] 집계 함수 목록\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [PATTERN] 접근 방법 목록\n" -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] 연산자 클래스 목록\n" -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] 연산자 부류 목록\n" -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] 연산자 부류 소속 연산자 목록\n" -#: help.c:252 +#: help.c:229 msgid "" " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] 연산자 가족에 포함된 지원 함수 목록\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [PATTERN] 테이블스페이스 목록\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [PATTERN] 문자셋 변환자 목록\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [PATTERN] 환경설정 매개변수 목록\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [PATTERN] 자료형 변환자 목록\n" -#: help.c:257 +#: help.c:234 msgid "" " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr "" " \\dd[S] [PATTERN] 다른 곳에서는 볼 수 없는 객체 설명을 보여줌\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [PATTERN] 도메인 목록\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [PATTERN] 기본 접근권한 목록\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [PATTERN] 외부 테이블 목록\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [PATTERN] 외부 서버 목록\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\det[+] [PATTERN] 외부 테이블 목록\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [PATTERN] 사용자 매핑 목록\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [PATTERN] 외부 데이터 래퍼 목록\n" -#: help.c:265 +#: help.c:242 msgid "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] " @@ -3103,47 +3151,47 @@ msgstr "" " [agg/normal/procedure/trigger/window 단일] 함수 목" "록\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr " \\dF[+] [PATTERN] 텍스트 검색 구성 목록\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr " \\dFd[+] [PATTERN] 텍스트 검색 사전 목록\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr " \\dFp[+] [PATTERN] 텍스트 검색 파서 목록\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr " \\dFt[+] [PATTERN] 텍스트 검색 템플릿 목록\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [PATTERN] 롤 목록\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [PATTERN] 인덱스 목록\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr " \\dl[+] 큰 개체 목록, \\lo_list 명령과 같음\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [PATTERN] 프로시져 언어 목록\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [PATTERN] materialized 뷰 목록\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [PATTERN] 스키마 목록\n" -#: help.c:277 +#: help.c:254 msgid "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" @@ -3151,95 +3199,95 @@ msgstr "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " 연산자 목록\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S+] [PATTERN] collation 목록\n" -#: help.c:280 +#: help.c:257 msgid "" " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr " \\dp[S] [PATTERN] 테이블, 뷰 및 시퀀스 액세스 권한 목록\n" -#: help.c:281 +#: help.c:258 msgid "" " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations " "[n=nested]\n" msgstr "" " \\dP[itn+] [PATTERN] 파티션 릴레이션 목록 [인덱스/테이블만] [n=nested]\n" -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr " \\drds [ROLEPTRN [DBPTRN]] per-database 롤 설정 목록\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\drg[S] [PATTERN] 롤 부여 목록\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[+] [PATTERN] 복제 발행 목록\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [PATTERN] 복제 구독 목록\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [PATTERN] 시퀀스 목록\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [PATTERN] 테이블 목록\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [PATTERN] 데이터 형식 목록\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [PATTERN] 롤 목록\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [PATTERN] 뷰 목록\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [PATTERN] 확장 모듈 목록\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [PATTERN] 확장 통계 정보 목록\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [PATTERN] 이벤트 트리거 목록\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [PATTERN] 데이터베이스 목록\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] 함수이름 함수 정의 보기\n" -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv[+] 뷰이름 뷰 정의 보기\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [PATTERN] \\dp 와 같음\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "큰 개체\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr " \\lo_export LOBOID FILE 큰 개체를 파일로 저장\n" -#: help.c:302 +#: help.c:279 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3247,42 +3295,42 @@ msgstr "" " \\lo_import FILE [COMMENT]\n" " 파일에서 큰 개체 가져오기\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\lo_list[+] 큰 개체 목록\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID 큰 개체 삭제\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "출력 형식\n" -#: help.c:309 +#: help.c:286 msgid "" " \\a toggle between unaligned and aligned output mode\n" msgstr "" " \\a 정렬되지 않은 출력 모드와 정렬된 출력 모드 전환\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr "" " \\C [STRING] 테이블 제목 설정 또는 값이 없는 경우 설정 안 함\n" -#: help.c:311 +#: help.c:288 msgid "" " \\f [STRING] show or set field separator for unaligned query " "output\n" msgstr "" " \\f [STRING] unaligned 출력에 대해 필드 구분자 표시 또는 설정\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H HTML 출력 모드 전환(현재 %s)\n" -#: help.c:314 +#: help.c:291 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3290,7 +3338,7 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [이름 [값]] 테이블 출력 옵션 설정\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3298,34 +3346,34 @@ msgstr "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] 행만 표시(현재 %s)\n" -#: help.c:323 +#: help.c:300 msgid "" " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr "" " \\T [STRING] HTML
태그 속성 설정 또는 비었는 경우 설정 " "안 함\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] 확장된 출력 전환 (현재 %s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "자동" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "연결\n" -#: help.c:330 +#: help.c:307 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3334,7 +3382,7 @@ msgstr "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " 새 데이터베이스에 접속 (현재 \"%s\")\n" -#: help.c:334 +#: help.c:311 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3342,56 +3390,56 @@ msgstr "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " 새 데이터베이스에 접속 (현재 접속해 있지 않음)\n" -#: help.c:336 +#: help.c:313 msgid "" " \\conninfo display information about current connection\n" msgstr " \\conninfo 현재 데이터베이스 접속 정보 보기\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [ENCODING] 클라이언트 인코딩 표시 또는 설정\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr " \\password [USERNAME] 사용자 암호를 안전하게 변경\n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "운영 체제\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [DIR] 현재 작업 디렉터리 변경\n" -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVVAR 환경 변수값을 psql 변수값으로\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv NAME [VALUE] 환경 변수 지정 및 해제\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] 명령 실행 시간 전환(현재 %s)\n" -#: help.c:347 +#: help.c:324 msgid "" " \\! [COMMAND] execute command in shell or start interactive " "shell\n" msgstr " \\! [COMMAND] 셸 명령 실행 또는 대화식 셸 시작\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "변수\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr "" " \\prompt [TEXT] NAME 사용자에게 내부 변수를 설정하라는 메시지 표시\n" -#: help.c:352 +#: help.c:329 msgid "" " \\set [NAME [VALUE]] set internal variable, or list all if no " "parameters\n" @@ -3399,21 +3447,21 @@ msgstr "" " \\set [NAME [VALUE]] 내부 변수 설정 또는 미지정 경우 모든 변수 목록 표" "시\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NAME 내부 변수 설정 해제(삭제)\n" -#: help.c:392 +#: help.c:369 msgid "" "List of specially treated variables\n" "\n" msgstr "특별한 기능 설정 변수 목록\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "psql 변수들:\n" -#: help.c:396 +#: help.c:373 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3423,7 +3471,7 @@ msgstr "" " 또는 psql 명령 모드에서는 \\set NAME VALUE\n" "\n" -#: help.c:398 +#: help.c:375 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3431,7 +3479,7 @@ msgstr "" " AUTOCOMMIT\n" " 설정 되면, SQL 명령이 정상 실행 되면 자동 커밋 함\n" -#: help.c:400 +#: help.c:377 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3441,7 +3489,7 @@ msgstr "" " SQL 키워드 자동완성에서 대소문자 처리\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:403 +#: help.c:380 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3449,7 +3497,7 @@ msgstr "" " DBNAME\n" " 현재 접속한 데이터베이스 이름\n" -#: help.c:405 +#: help.c:382 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3459,7 +3507,7 @@ msgstr "" " 입력을 표준 출력으로 보낼 종류\n" " [all, errors, none, queries]\n" -#: help.c:408 +#: help.c:385 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3469,7 +3517,7 @@ msgstr "" " 지정 되면 psql 내장 명령어의 내부 쿼리를 출력함;\n" " \"noexec\" 값으로 설정하면, 실행되지 않고 쿼리만 보여줌\n" -#: help.c:411 +#: help.c:388 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3477,7 +3525,7 @@ msgstr "" " ENCODING\n" " 현재 클라이언트 인코딩 지정\n" -#: help.c:413 +#: help.c:390 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3485,7 +3533,7 @@ msgstr "" " ERROR\n" " 마지막 쿼리가 실패했으면 \"true\", 아니면 \"false\"\n" -#: help.c:415 +#: help.c:392 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = " @@ -3494,7 +3542,7 @@ msgstr "" " FETCH_COUNT\n" " 쿼리 결과에 대해서 출력할 최대 로우 개수 (0=제한없음)\n" -#: help.c:417 +#: help.c:394 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3502,7 +3550,7 @@ msgstr "" " HIDE_TABLEAM\n" " 지정하면 테이블 접근 방법을 보여주지 않음\n" -#: help.c:419 +#: help.c:396 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3510,7 +3558,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " 지정하면 TOAST 압축 종류 보여주지 않음\n" -#: help.c:421 +#: help.c:398 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3518,7 +3566,7 @@ msgstr "" " HISTCONTROL\n" " 명령 내역 처리 방법 [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:423 +#: help.c:400 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3526,7 +3574,7 @@ msgstr "" " HISTFILE\n" " 명령 내역을 저장할 파일 이름\n" -#: help.c:425 +#: help.c:402 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3534,7 +3582,7 @@ msgstr "" " HISTSIZE\n" " 명령 내역 최대 보관 개수\n" -#: help.c:427 +#: help.c:404 msgid "" " HOST\n" " the currently connected database server host\n" @@ -3542,7 +3590,7 @@ msgstr "" " HOST\n" " 현재 접속한 데이터베이스 서버 호스트\n" -#: help.c:429 +#: help.c:406 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3550,7 +3598,7 @@ msgstr "" " IGNOREEOF\n" " 대화형 세션 종료를 위한 EOF 개수\n" -#: help.c:431 +#: help.c:408 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3558,7 +3606,7 @@ msgstr "" " LASTOID\n" " 마지막 영향 받은 OID 값\n" -#: help.c:433 +#: help.c:410 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3569,7 +3617,7 @@ msgstr "" " LAST_ERROR_SQLSTATE\n" " 마지막 오류 메시지와 SQLSTATE, 정상이면, 빈 문자열과 \"00000\"\n" -#: help.c:436 +#: help.c:413 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3577,7 +3625,7 @@ msgstr "" " ON_ERROR_ROLLBACK\n" " 설정하면 오류 발생시에도 트랜잭션 중지 안함 (savepoint 암묵적 사용)\n" -#: help.c:438 +#: help.c:415 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3585,7 +3633,7 @@ msgstr "" " ON_ERROR_STOP\n" " 배치 작업 시 오류가 발생하면 중지함\n" -#: help.c:440 +#: help.c:417 msgid "" " PORT\n" " server port of the current connection\n" @@ -3593,7 +3641,7 @@ msgstr "" " PORT\n" " 현재 접속한 서버 포트\n" -#: help.c:442 +#: help.c:419 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3601,7 +3649,7 @@ msgstr "" " PROMPT1\n" " 기본 psql 프롬프트 정의\n" -#: help.c:444 +#: help.c:421 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous " @@ -3610,7 +3658,7 @@ msgstr "" " PROMPT2\n" " 아직 구문이 덜 끝난 명령행의 프롬프트\n" -#: help.c:446 +#: help.c:423 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3618,7 +3666,7 @@ msgstr "" " PROMPT3\n" " COPY ... FROM STDIN 작업시 보일 프롬프트\n" -#: help.c:448 +#: help.c:425 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3626,7 +3674,7 @@ msgstr "" " QUIET\n" " 조용히 실행 (-q 옵션과 같음)\n" -#: help.c:450 +#: help.c:427 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3634,7 +3682,7 @@ msgstr "" " ROW_COUNT\n" " 마지막 쿼리 작업 대상 로우 수, 또는 0\n" -#: help.c:452 +#: help.c:429 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3644,7 +3692,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " 문자열 버전 정보나, 숫자 형식 버전 정보\n" -#: help.c:455 +#: help.c:432 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3652,7 +3700,7 @@ msgstr "" " SHELL_ERROR\n" " 마지막 쉘 명령이 실패했으면 \"true\", 아니면 \"false\"\n" -#: help.c:457 +#: help.c:434 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3660,7 +3708,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " 마지막 쉘 명령의 종료 코드\n" -#: help.c:459 +#: help.c:436 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3669,7 +3717,7 @@ msgstr "" " 여러 쿼리가 연속하는 경우(\\;) 모든 쿼리 결과를 출력, off면 마지막 결과" "만\n" -#: help.c:461 +#: help.c:438 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3677,7 +3725,7 @@ msgstr "" " SHOW_CONTEXT\n" " 상황별 자세한 메시지 내용 출력 제어 [never, errors, always]\n" -#: help.c:463 +#: help.c:440 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3685,7 +3733,7 @@ msgstr "" " SINGLELINE\n" " 한 줄에 하나의 SQL 명령 실행 (-S 옵션과 같음)\n" -#: help.c:465 +#: help.c:442 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3693,7 +3741,7 @@ msgstr "" " SINGLESTEP\n" " 각 명령을 확인하며 실행 (-s 옵션과 같음)\n" -#: help.c:467 +#: help.c:444 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3701,7 +3749,7 @@ msgstr "" " SQLSTATE\n" " 마지막 쿼리의 SQLSTATE 값, 오류가 없으면 \"00000\"\n" -#: help.c:469 +#: help.c:446 msgid "" " USER\n" " the currently connected database user\n" @@ -3709,7 +3757,7 @@ msgstr "" " USER\n" " 현재 접속한 데이터베이스 사용자\n" -#: help.c:471 +#: help.c:448 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3717,7 +3765,7 @@ msgstr "" " VERBOSITY\n" " 오류 출력시 자세히 볼 내용 범위 [default, verbose, terse, sqlstate]\n" -#: help.c:473 +#: help.c:450 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3729,7 +3777,7 @@ msgstr "" " VERSION_NUM\n" " psql 버전 (자세한 버전, 단순한 버전, 숫자형 버전)\n" -#: help.c:478 +#: help.c:455 msgid "" "\n" "Display settings:\n" @@ -3737,7 +3785,7 @@ msgstr "" "\n" "출력 설정들:\n" -#: help.c:480 +#: help.c:457 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3747,7 +3795,7 @@ msgstr "" " 또는 psql 명령 모드에서는 \\pset NAME [VALUE]\n" "\n" -#: help.c:482 +#: help.c:459 msgid "" " border\n" " border style (number)\n" @@ -3755,7 +3803,7 @@ msgstr "" " border\n" " 테두리 모양 (숫자)\n" -#: help.c:484 +#: help.c:461 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3763,7 +3811,7 @@ msgstr "" " columns\n" " 줄바꿈을 위한 너비 지정\n" -#: help.c:486 +#: help.c:463 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" @@ -3771,7 +3819,7 @@ msgstr "" " expanded (또는 x)\n" " 확장된 출력 전환 [on, off, auto]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid "" " fieldsep\n" @@ -3780,7 +3828,7 @@ msgstr "" " fieldsep\n" " unaligned 출력용 필드 구분자 (초기값 \"%s\"')\n" -#: help.c:491 +#: help.c:468 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3788,7 +3836,7 @@ msgstr "" " fieldsep_zero\n" " unaligned 출력용 필드 구분자를 0 바이트로 지정\n" -#: help.c:493 +#: help.c:470 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3796,7 +3844,7 @@ msgstr "" " footer\n" " 테이블 꼬리말 보이기 전환 [on, off]\n" -#: help.c:495 +#: help.c:472 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3804,7 +3852,7 @@ msgstr "" " format\n" " 출력 양식 지정 [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3812,7 +3860,7 @@ msgstr "" " linestyle\n" " 테두리 선 모양 지정 [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3820,7 +3868,7 @@ msgstr "" " null\n" " null 값 출력 방법\n" -#: help.c:501 +#: help.c:478 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of " @@ -3829,7 +3877,7 @@ msgstr "" " numericlocale\n" " 숫자 출력에서 로케일 기반 천자리 분리 문자 활성화 [on, off]\n" -#: help.c:503 +#: help.c:480 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3837,7 +3885,7 @@ msgstr "" " pager\n" " 외부 페이지 단위 보기 도구 사용 여부 [yes, no, always]\n" -#: help.c:505 +#: help.c:482 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3845,7 +3893,7 @@ msgstr "" " recordsep\n" " unaligned 출력용 레코드(줄) 구분자\n" -#: help.c:507 +#: help.c:484 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3853,7 +3901,7 @@ msgstr "" " recordsep_zero\n" " unaligned 출력용 레코드 구분자를 0 바이트로 지정\n" -#: help.c:509 +#: help.c:486 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3863,7 +3911,7 @@ msgstr "" " html 테이블 태그에 대한 속성이나,\n" " latex-longtable 양식에서 왼쪽 정렬 자료용 칼럼 너비 지정\n" -#: help.c:512 +#: help.c:489 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -3871,7 +3919,7 @@ msgstr "" " title\n" " 테이블 제목 지정\n" -#: help.c:514 +#: help.c:491 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -3879,7 +3927,7 @@ msgstr "" " tuples_only\n" " 지정되면, 자료만 보임\n" -#: help.c:516 +#: help.c:493 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3891,7 +3939,17 @@ msgstr "" " unicode_header_linestyle\n" " 유니코드 선 종류 [single, double]\n" -#: help.c:521 +#: help.c:497 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" 확장된 출력 화면에서 헤더의 최대 너비 지정\n" +" [full, column, page, integer value]\n" + +#: help.c:501 msgid "" "\n" "Environment variables:\n" @@ -3899,7 +3957,7 @@ msgstr "" "\n" "OS 환경 변수들:\n" -#: help.c:525 +#: help.c:505 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3909,7 +3967,7 @@ msgstr "" " 또는 psql 명령 모드에서는 \\setenv NAME [VALUE]\n" "\n" -#: help.c:527 +#: help.c:507 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3921,7 +3979,7 @@ msgstr "" " 또는 psql 명령 모드에서는 \\setenv NAME [VALUE]\n" "\n" -#: help.c:530 +#: help.c:510 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -3929,7 +3987,7 @@ msgstr "" " COLUMNS\n" " 다음 줄로 넘어갈 칼럼 수\n" -#: help.c:532 +#: help.c:512 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -3937,7 +3995,7 @@ msgstr "" " PGAPPNAME\n" " application_name 변수값으로 사용됨\n" -#: help.c:534 +#: help.c:514 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -3945,7 +4003,7 @@ msgstr "" " PGDATABASE\n" " 접속할 데이터베이스 이름\n" -#: help.c:536 +#: help.c:516 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -3953,7 +4011,7 @@ msgstr "" " PGHOST\n" " 서버 접속용 호스트 이름\n" -#: help.c:538 +#: help.c:518 msgid "" " PGPASSFILE\n" " password file name\n" @@ -3961,7 +4019,7 @@ msgstr "" " PGPASSFILE\n" " 서버 접속용 비밀번호가 저장된 파일 이름\n" -#: help.c:540 +#: help.c:520 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -3969,7 +4027,7 @@ msgstr "" " PGPASSWORD\n" " 서버 접속 비밀번호 (보안에 취약함)\n" -#: help.c:542 +#: help.c:522 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -3977,7 +4035,7 @@ msgstr "" " PGPORT\n" " 서버 접속용 포트\n" -#: help.c:544 +#: help.c:524 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -3985,7 +4043,7 @@ msgstr "" " PGUSER\n" " 서버 접속용 데이터베이스 사용자 이름\n" -#: help.c:546 +#: help.c:526 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3993,7 +4051,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " \\e, \\ef, \\ev 명령에서 사용할 외부 편집기 경로\n" -#: help.c:548 +#: help.c:528 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -4001,7 +4059,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " 외부 편집기 호출 시 사용할 줄번호 선택 옵션\n" -#: help.c:550 +#: help.c:530 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -4009,7 +4067,7 @@ msgstr "" " PSQL_HISTORY\n" " 사용자 .psql_history 파일 임의 지정\n" -#: help.c:552 +#: help.c:532 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -4017,7 +4075,7 @@ msgstr "" " PAGER\n" " 페이지 단위 보기에서 사용할 프로그램\n" -#: help.c:555 +#: help.c:535 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -4025,7 +4083,7 @@ msgstr "" " PSQL_WATCH_PAGER\n" " \\watch 명령에서 사용할 외장 페이저 프로그램 이름\n" -#: help.c:558 +#: help.c:538 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -4033,7 +4091,7 @@ msgstr "" " PSQLRC\n" " 사용자 .psqlrc 파일의 임의 지정\n" -#: help.c:560 +#: help.c:540 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -4041,7 +4099,7 @@ msgstr "" " SHELL\n" " \\! 명령에서 사용할 쉘\n" -#: help.c:562 +#: help.c:542 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -4049,11 +4107,11 @@ msgstr "" " TMPDIR\n" " 임시 파일을 사용할 디렉터리\n" -#: help.c:622 +#: help.c:602 msgid "Available help:\n" msgstr "사용 가능한 도움말:\n" -#: help.c:717 +#: help.c:697 #, c-format msgid "" "Command: %s\n" @@ -4071,7 +4129,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:740 +#: help.c:720 #, c-format msgid "" "No help available for \"%s\".\n" @@ -4080,17 +4138,17 @@ msgstr "" "\"%s\" 명령에 대한 도움말 없음.\n" "\\h 명령을 인자 없이 호출 하면 사용 가능한 모든 명령 보여줌.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "입력 파일을 읽을 수 없음: %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "history를 \"%s\" 파일로 저장할 수 없음: %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "히스토리 기능은 이 설치본에서는 지원하지 않음" @@ -4179,12 +4237,12 @@ msgstr "" msgid "reached EOF without finding closing \\endif(s)" msgstr "\\endif 없이 EOF 도달" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "마무리 안된 따옴표 안의 문자열" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s: 메모리 부족" @@ -4192,2429 +4250,2449 @@ msgstr "%s: 메모리 부족" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:238 -#: sql_help.c:240 sql_help.c:241 sql_help.c:243 sql_help.c:245 sql_help.c:248 -#: sql_help.c:250 sql_help.c:252 sql_help.c:254 sql_help.c:266 sql_help.c:267 -#: sql_help.c:268 sql_help.c:270 sql_help.c:319 sql_help.c:321 sql_help.c:323 -#: sql_help.c:325 sql_help.c:394 sql_help.c:399 sql_help.c:401 sql_help.c:443 -#: sql_help.c:445 sql_help.c:448 sql_help.c:450 sql_help.c:519 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:593 sql_help.c:595 -#: sql_help.c:597 sql_help.c:599 sql_help.c:601 sql_help.c:604 sql_help.c:606 -#: sql_help.c:609 sql_help.c:620 sql_help.c:622 sql_help.c:666 sql_help.c:668 -#: sql_help.c:670 sql_help.c:673 sql_help.c:675 sql_help.c:677 sql_help.c:714 -#: sql_help.c:718 sql_help.c:722 sql_help.c:741 sql_help.c:744 sql_help.c:747 -#: sql_help.c:776 sql_help.c:788 sql_help.c:796 sql_help.c:799 sql_help.c:802 -#: sql_help.c:817 sql_help.c:820 sql_help.c:849 sql_help.c:854 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:896 sql_help.c:898 sql_help.c:900 -#: sql_help.c:902 sql_help.c:905 sql_help.c:907 sql_help.c:954 sql_help.c:999 -#: sql_help.c:1004 sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 -#: sql_help.c:1038 sql_help.c:1049 sql_help.c:1051 sql_help.c:1071 -#: sql_help.c:1081 sql_help.c:1082 sql_help.c:1084 sql_help.c:1086 -#: sql_help.c:1098 sql_help.c:1102 sql_help.c:1104 sql_help.c:1116 -#: sql_help.c:1118 sql_help.c:1120 sql_help.c:1122 sql_help.c:1141 -#: sql_help.c:1143 sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 -#: sql_help.c:1158 sql_help.c:1159 sql_help.c:1160 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1168 sql_help.c:1308 sql_help.c:1310 -#: sql_help.c:1313 sql_help.c:1316 sql_help.c:1318 sql_help.c:1320 -#: sql_help.c:1323 sql_help.c:1326 sql_help.c:1443 sql_help.c:1445 -#: sql_help.c:1447 sql_help.c:1450 sql_help.c:1471 sql_help.c:1474 -#: sql_help.c:1477 sql_help.c:1480 sql_help.c:1484 sql_help.c:1486 -#: sql_help.c:1488 sql_help.c:1490 sql_help.c:1504 sql_help.c:1507 -#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1521 sql_help.c:1523 -#: sql_help.c:1533 sql_help.c:1535 sql_help.c:1545 sql_help.c:1548 -#: sql_help.c:1571 sql_help.c:1573 sql_help.c:1575 sql_help.c:1577 -#: sql_help.c:1580 sql_help.c:1582 sql_help.c:1585 sql_help.c:1588 -#: sql_help.c:1639 sql_help.c:1682 sql_help.c:1685 sql_help.c:1687 -#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1694 sql_help.c:1696 -#: sql_help.c:1699 sql_help.c:1751 sql_help.c:1767 sql_help.c:2000 -#: sql_help.c:2069 sql_help.c:2088 sql_help.c:2101 sql_help.c:2159 -#: sql_help.c:2167 sql_help.c:2177 sql_help.c:2204 sql_help.c:2236 -#: sql_help.c:2254 sql_help.c:2282 sql_help.c:2393 sql_help.c:2439 -#: sql_help.c:2464 sql_help.c:2487 sql_help.c:2491 sql_help.c:2525 -#: sql_help.c:2545 sql_help.c:2567 sql_help.c:2581 sql_help.c:2602 -#: sql_help.c:2631 sql_help.c:2666 sql_help.c:2691 sql_help.c:2738 -#: sql_help.c:3033 sql_help.c:3046 sql_help.c:3063 sql_help.c:3079 -#: sql_help.c:3119 sql_help.c:3173 sql_help.c:3177 sql_help.c:3179 -#: sql_help.c:3186 sql_help.c:3205 sql_help.c:3232 sql_help.c:3267 -#: sql_help.c:3279 sql_help.c:3288 sql_help.c:3332 sql_help.c:3346 -#: sql_help.c:3374 sql_help.c:3382 sql_help.c:3394 sql_help.c:3404 -#: sql_help.c:3412 sql_help.c:3420 sql_help.c:3428 sql_help.c:3436 -#: sql_help.c:3445 sql_help.c:3456 sql_help.c:3464 sql_help.c:3472 -#: sql_help.c:3480 sql_help.c:3488 sql_help.c:3498 sql_help.c:3507 -#: sql_help.c:3516 sql_help.c:3524 sql_help.c:3534 sql_help.c:3545 -#: sql_help.c:3553 sql_help.c:3562 sql_help.c:3573 sql_help.c:3582 -#: sql_help.c:3590 sql_help.c:3598 sql_help.c:3606 sql_help.c:3614 -#: sql_help.c:3622 sql_help.c:3630 sql_help.c:3638 sql_help.c:3646 -#: sql_help.c:3654 sql_help.c:3662 sql_help.c:3679 sql_help.c:3688 -#: sql_help.c:3696 sql_help.c:3713 sql_help.c:3728 sql_help.c:4040 -#: sql_help.c:4150 sql_help.c:4179 sql_help.c:4195 sql_help.c:4197 -#: sql_help.c:4700 sql_help.c:4748 sql_help.c:4906 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:245 +#: sql_help.c:247 sql_help.c:248 sql_help.c:250 sql_help.c:252 sql_help.c:255 +#: sql_help.c:257 sql_help.c:259 sql_help.c:261 sql_help.c:276 sql_help.c:277 +#: sql_help.c:278 sql_help.c:280 sql_help.c:329 sql_help.c:331 sql_help.c:333 +#: sql_help.c:335 sql_help.c:404 sql_help.c:409 sql_help.c:411 sql_help.c:453 +#: sql_help.c:455 sql_help.c:458 sql_help.c:460 sql_help.c:529 sql_help.c:534 +#: sql_help.c:539 sql_help.c:544 sql_help.c:549 sql_help.c:603 sql_help.c:605 +#: sql_help.c:607 sql_help.c:609 sql_help.c:611 sql_help.c:614 sql_help.c:616 +#: sql_help.c:619 sql_help.c:630 sql_help.c:632 sql_help.c:676 sql_help.c:678 +#: sql_help.c:680 sql_help.c:683 sql_help.c:685 sql_help.c:687 sql_help.c:728 +#: sql_help.c:732 sql_help.c:736 sql_help.c:757 sql_help.c:760 sql_help.c:763 +#: sql_help.c:792 sql_help.c:804 sql_help.c:812 sql_help.c:815 sql_help.c:818 +#: sql_help.c:833 sql_help.c:836 sql_help.c:865 sql_help.c:870 sql_help.c:875 +#: sql_help.c:880 sql_help.c:885 sql_help.c:912 sql_help.c:914 sql_help.c:916 +#: sql_help.c:918 sql_help.c:921 sql_help.c:923 sql_help.c:970 sql_help.c:1015 +#: sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 sql_help.c:1035 +#: sql_help.c:1054 sql_help.c:1065 sql_help.c:1067 sql_help.c:1087 +#: sql_help.c:1097 sql_help.c:1098 sql_help.c:1100 sql_help.c:1102 +#: sql_help.c:1114 sql_help.c:1118 sql_help.c:1120 sql_help.c:1132 +#: sql_help.c:1134 sql_help.c:1136 sql_help.c:1138 sql_help.c:1157 +#: sql_help.c:1159 sql_help.c:1163 sql_help.c:1167 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1175 sql_help.c:1176 sql_help.c:1179 +#: sql_help.c:1182 sql_help.c:1184 sql_help.c:1324 sql_help.c:1326 +#: sql_help.c:1329 sql_help.c:1332 sql_help.c:1334 sql_help.c:1336 +#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1464 sql_help.c:1466 +#: sql_help.c:1468 sql_help.c:1471 sql_help.c:1492 sql_help.c:1495 +#: sql_help.c:1498 sql_help.c:1501 sql_help.c:1505 sql_help.c:1507 +#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1525 sql_help.c:1528 +#: sql_help.c:1530 sql_help.c:1532 sql_help.c:1542 sql_help.c:1544 +#: sql_help.c:1554 sql_help.c:1556 sql_help.c:1566 sql_help.c:1569 +#: sql_help.c:1592 sql_help.c:1594 sql_help.c:1596 sql_help.c:1598 +#: sql_help.c:1601 sql_help.c:1603 sql_help.c:1606 sql_help.c:1609 +#: sql_help.c:1660 sql_help.c:1703 sql_help.c:1706 sql_help.c:1708 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:1715 sql_help.c:1717 +#: sql_help.c:1720 sql_help.c:1770 sql_help.c:1786 sql_help.c:2019 +#: sql_help.c:2088 sql_help.c:2107 sql_help.c:2120 sql_help.c:2178 +#: sql_help.c:2186 sql_help.c:2196 sql_help.c:2224 sql_help.c:2257 +#: sql_help.c:2275 sql_help.c:2303 sql_help.c:2414 sql_help.c:2460 +#: sql_help.c:2485 sql_help.c:2508 sql_help.c:2512 sql_help.c:2546 +#: sql_help.c:2566 sql_help.c:2588 sql_help.c:2602 sql_help.c:2623 +#: sql_help.c:2652 sql_help.c:2685 sql_help.c:2708 sql_help.c:2755 +#: sql_help.c:3053 sql_help.c:3066 sql_help.c:3083 sql_help.c:3099 +#: sql_help.c:3139 sql_help.c:3193 sql_help.c:3197 sql_help.c:3199 +#: sql_help.c:3206 sql_help.c:3225 sql_help.c:3252 sql_help.c:3287 +#: sql_help.c:3299 sql_help.c:3308 sql_help.c:3352 sql_help.c:3366 +#: sql_help.c:3394 sql_help.c:3402 sql_help.c:3414 sql_help.c:3424 +#: sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 sql_help.c:3456 +#: sql_help.c:3465 sql_help.c:3476 sql_help.c:3484 sql_help.c:3492 +#: sql_help.c:3500 sql_help.c:3508 sql_help.c:3518 sql_help.c:3527 +#: sql_help.c:3536 sql_help.c:3544 sql_help.c:3554 sql_help.c:3565 +#: sql_help.c:3573 sql_help.c:3582 sql_help.c:3593 sql_help.c:3602 +#: sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 sql_help.c:3634 +#: sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 sql_help.c:3666 +#: sql_help.c:3674 sql_help.c:3682 sql_help.c:3699 sql_help.c:3708 +#: sql_help.c:3716 sql_help.c:3733 sql_help.c:3748 sql_help.c:4061 +#: sql_help.c:4182 sql_help.c:4211 sql_help.c:4227 sql_help.c:4229 +#: sql_help.c:4733 sql_help.c:4781 sql_help.c:4940 msgid "name" msgstr "이름" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:330 sql_help.c:1848 -#: sql_help.c:3347 sql_help.c:4468 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:340 sql_help.c:1863 +#: sql_help.c:3367 sql_help.c:4500 msgid "aggregate_signature" msgstr "집계함수_식별구문" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:449 sql_help.c:528 sql_help.c:576 -#: sql_help.c:594 sql_help.c:621 sql_help.c:674 sql_help.c:743 sql_help.c:798 -#: sql_help.c:819 sql_help.c:858 sql_help.c:908 sql_help.c:955 sql_help.c:1008 -#: sql_help.c:1040 sql_help.c:1050 sql_help.c:1085 sql_help.c:1105 -#: sql_help.c:1119 sql_help.c:1169 sql_help.c:1317 sql_help.c:1444 -#: sql_help.c:1487 sql_help.c:1508 sql_help.c:1522 sql_help.c:1534 -#: sql_help.c:1547 sql_help.c:1574 sql_help.c:1640 sql_help.c:1693 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:260 +#: sql_help.c:281 sql_help.c:412 sql_help.c:459 sql_help.c:538 sql_help.c:586 +#: sql_help.c:604 sql_help.c:631 sql_help.c:684 sql_help.c:759 sql_help.c:814 +#: sql_help.c:835 sql_help.c:874 sql_help.c:924 sql_help.c:971 sql_help.c:1024 +#: sql_help.c:1056 sql_help.c:1066 sql_help.c:1101 sql_help.c:1121 +#: sql_help.c:1135 sql_help.c:1185 sql_help.c:1333 sql_help.c:1465 +#: sql_help.c:1508 sql_help.c:1529 sql_help.c:1543 sql_help.c:1555 +#: sql_help.c:1568 sql_help.c:1595 sql_help.c:1661 sql_help.c:1714 msgid "new_name" msgstr "새이름" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:251 -#: sql_help.c:269 sql_help.c:400 sql_help.c:485 sql_help.c:533 sql_help.c:623 -#: sql_help.c:632 sql_help.c:697 sql_help.c:717 sql_help.c:746 sql_help.c:801 -#: sql_help.c:863 sql_help.c:906 sql_help.c:1013 sql_help.c:1052 -#: sql_help.c:1083 sql_help.c:1103 sql_help.c:1117 sql_help.c:1167 -#: sql_help.c:1381 sql_help.c:1446 sql_help.c:1489 sql_help.c:1510 -#: sql_help.c:1572 sql_help.c:1688 sql_help.c:3019 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:258 +#: sql_help.c:279 sql_help.c:410 sql_help.c:495 sql_help.c:543 sql_help.c:633 +#: sql_help.c:642 sql_help.c:707 sql_help.c:731 sql_help.c:762 sql_help.c:817 +#: sql_help.c:879 sql_help.c:922 sql_help.c:1029 sql_help.c:1068 +#: sql_help.c:1099 sql_help.c:1119 sql_help.c:1133 sql_help.c:1183 +#: sql_help.c:1399 sql_help.c:1467 sql_help.c:1510 sql_help.c:1531 +#: sql_help.c:1593 sql_help.c:1709 sql_help.c:3039 msgid "new_owner" msgstr "새사용자" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:255 sql_help.c:322 -#: sql_help.c:451 sql_help.c:538 sql_help.c:676 sql_help.c:721 sql_help.c:749 -#: sql_help.c:804 sql_help.c:868 sql_help.c:1018 sql_help.c:1087 -#: sql_help.c:1121 sql_help.c:1319 sql_help.c:1491 sql_help.c:1512 -#: sql_help.c:1524 sql_help.c:1536 sql_help.c:1576 sql_help.c:1695 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:262 sql_help.c:332 +#: sql_help.c:461 sql_help.c:548 sql_help.c:686 sql_help.c:735 sql_help.c:765 +#: sql_help.c:820 sql_help.c:884 sql_help.c:1034 sql_help.c:1103 +#: sql_help.c:1137 sql_help.c:1335 sql_help.c:1512 sql_help.c:1533 +#: sql_help.c:1545 sql_help.c:1557 sql_help.c:1597 sql_help.c:1716 msgid "new_schema" msgstr "새스키마" -#: sql_help.c:44 sql_help.c:1912 sql_help.c:3348 sql_help.c:4497 +#: sql_help.c:44 sql_help.c:1927 sql_help.c:3368 sql_help.c:4529 msgid "where aggregate_signature is:" msgstr "집계함수_식별구문 사용법:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:340 sql_help.c:353 -#: sql_help.c:357 sql_help.c:373 sql_help.c:376 sql_help.c:379 sql_help.c:520 -#: sql_help.c:525 sql_help.c:530 sql_help.c:535 sql_help.c:540 sql_help.c:850 -#: sql_help.c:855 sql_help.c:860 sql_help.c:865 sql_help.c:870 sql_help.c:1000 -#: sql_help.c:1005 sql_help.c:1010 sql_help.c:1015 sql_help.c:1020 -#: sql_help.c:1866 sql_help.c:1883 sql_help.c:1889 sql_help.c:1913 -#: sql_help.c:1916 sql_help.c:1919 sql_help.c:2070 sql_help.c:2089 -#: sql_help.c:2092 sql_help.c:2394 sql_help.c:2603 sql_help.c:3349 -#: sql_help.c:3352 sql_help.c:3355 sql_help.c:3446 sql_help.c:3535 -#: sql_help.c:3563 sql_help.c:3915 sql_help.c:4367 sql_help.c:4474 -#: sql_help.c:4481 sql_help.c:4487 sql_help.c:4498 sql_help.c:4501 -#: sql_help.c:4504 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:350 sql_help.c:363 +#: sql_help.c:367 sql_help.c:383 sql_help.c:386 sql_help.c:389 sql_help.c:530 +#: sql_help.c:535 sql_help.c:540 sql_help.c:545 sql_help.c:550 sql_help.c:866 +#: sql_help.c:871 sql_help.c:876 sql_help.c:881 sql_help.c:886 sql_help.c:1016 +#: sql_help.c:1021 sql_help.c:1026 sql_help.c:1031 sql_help.c:1036 +#: sql_help.c:1881 sql_help.c:1898 sql_help.c:1904 sql_help.c:1928 +#: sql_help.c:1931 sql_help.c:1934 sql_help.c:2089 sql_help.c:2108 +#: sql_help.c:2111 sql_help.c:2415 sql_help.c:2624 sql_help.c:3369 +#: sql_help.c:3372 sql_help.c:3375 sql_help.c:3466 sql_help.c:3555 +#: sql_help.c:3583 sql_help.c:3936 sql_help.c:4399 sql_help.c:4506 +#: sql_help.c:4513 sql_help.c:4519 sql_help.c:4530 sql_help.c:4533 +#: sql_help.c:4536 msgid "argmode" msgstr "인자모드" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:341 sql_help.c:354 -#: sql_help.c:358 sql_help.c:374 sql_help.c:377 sql_help.c:380 sql_help.c:521 -#: sql_help.c:526 sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:851 -#: sql_help.c:856 sql_help.c:861 sql_help.c:866 sql_help.c:871 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1867 sql_help.c:1884 sql_help.c:1890 sql_help.c:1914 -#: sql_help.c:1917 sql_help.c:1920 sql_help.c:2071 sql_help.c:2090 -#: sql_help.c:2093 sql_help.c:2395 sql_help.c:2604 sql_help.c:3350 -#: sql_help.c:3353 sql_help.c:3356 sql_help.c:3447 sql_help.c:3536 -#: sql_help.c:3564 sql_help.c:4475 sql_help.c:4482 sql_help.c:4488 -#: sql_help.c:4499 sql_help.c:4502 sql_help.c:4505 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:351 sql_help.c:364 +#: sql_help.c:368 sql_help.c:384 sql_help.c:387 sql_help.c:390 sql_help.c:531 +#: sql_help.c:536 sql_help.c:541 sql_help.c:546 sql_help.c:551 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:882 sql_help.c:887 sql_help.c:1017 +#: sql_help.c:1022 sql_help.c:1027 sql_help.c:1032 sql_help.c:1037 +#: sql_help.c:1882 sql_help.c:1899 sql_help.c:1905 sql_help.c:1929 +#: sql_help.c:1932 sql_help.c:1935 sql_help.c:2090 sql_help.c:2109 +#: sql_help.c:2112 sql_help.c:2416 sql_help.c:2625 sql_help.c:3370 +#: sql_help.c:3373 sql_help.c:3376 sql_help.c:3467 sql_help.c:3556 +#: sql_help.c:3584 sql_help.c:4507 sql_help.c:4514 sql_help.c:4520 +#: sql_help.c:4531 sql_help.c:4534 sql_help.c:4537 msgid "argname" msgstr "인자이름" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1868 sql_help.c:1885 sql_help.c:1891 sql_help.c:1915 -#: sql_help.c:1918 sql_help.c:1921 sql_help.c:2396 sql_help.c:2605 -#: sql_help.c:3351 sql_help.c:3354 sql_help.c:3357 sql_help.c:3448 -#: sql_help.c:3537 sql_help.c:3565 sql_help.c:4476 sql_help.c:4483 -#: sql_help.c:4489 sql_help.c:4500 sql_help.c:4503 sql_help.c:4506 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:352 sql_help.c:365 +#: sql_help.c:369 sql_help.c:385 sql_help.c:388 sql_help.c:391 sql_help.c:532 +#: sql_help.c:537 sql_help.c:542 sql_help.c:547 sql_help.c:552 sql_help.c:868 +#: sql_help.c:873 sql_help.c:878 sql_help.c:883 sql_help.c:888 sql_help.c:1018 +#: sql_help.c:1023 sql_help.c:1028 sql_help.c:1033 sql_help.c:1038 +#: sql_help.c:1883 sql_help.c:1900 sql_help.c:1906 sql_help.c:1930 +#: sql_help.c:1933 sql_help.c:1936 sql_help.c:2417 sql_help.c:2626 +#: sql_help.c:3371 sql_help.c:3374 sql_help.c:3377 sql_help.c:3468 +#: sql_help.c:3557 sql_help.c:3585 sql_help.c:4508 sql_help.c:4515 +#: sql_help.c:4521 sql_help.c:4532 sql_help.c:4535 sql_help.c:4538 msgid "argtype" msgstr "인자자료형" -#: sql_help.c:114 sql_help.c:397 sql_help.c:474 sql_help.c:486 sql_help.c:949 -#: sql_help.c:1100 sql_help.c:1505 sql_help.c:1634 sql_help.c:1666 -#: sql_help.c:1719 sql_help.c:1783 sql_help.c:1970 sql_help.c:1977 -#: sql_help.c:2285 sql_help.c:2335 sql_help.c:2342 sql_help.c:2351 -#: sql_help.c:2440 sql_help.c:2667 sql_help.c:2760 sql_help.c:3048 -#: sql_help.c:3233 sql_help.c:3255 sql_help.c:3395 sql_help.c:3751 -#: sql_help.c:3959 sql_help.c:4194 sql_help.c:4196 sql_help.c:4973 +#: sql_help.c:114 sql_help.c:407 sql_help.c:484 sql_help.c:496 sql_help.c:965 +#: sql_help.c:1116 sql_help.c:1526 sql_help.c:1655 sql_help.c:1687 +#: sql_help.c:1739 sql_help.c:1798 sql_help.c:1987 sql_help.c:1994 +#: sql_help.c:2306 sql_help.c:2356 sql_help.c:2363 sql_help.c:2372 +#: sql_help.c:2461 sql_help.c:2686 sql_help.c:2777 sql_help.c:3068 +#: sql_help.c:3253 sql_help.c:3275 sql_help.c:3415 sql_help.c:3772 +#: sql_help.c:3980 sql_help.c:4226 sql_help.c:4228 sql_help.c:5006 msgid "option" msgstr "옵션" -#: sql_help.c:115 sql_help.c:950 sql_help.c:1635 sql_help.c:2441 -#: sql_help.c:2668 sql_help.c:3234 sql_help.c:3396 +#: sql_help.c:115 sql_help.c:966 sql_help.c:1656 sql_help.c:2462 +#: sql_help.c:2687 sql_help.c:3254 sql_help.c:3416 msgid "where option can be:" msgstr "옵션 사용법:" -#: sql_help.c:116 sql_help.c:2217 +#: sql_help.c:116 sql_help.c:2238 msgid "allowconn" msgstr "접속허용" -#: sql_help.c:117 sql_help.c:951 sql_help.c:1636 sql_help.c:2218 -#: sql_help.c:2442 sql_help.c:2669 sql_help.c:3235 +#: sql_help.c:117 sql_help.c:967 sql_help.c:1657 sql_help.c:2239 +#: sql_help.c:2463 sql_help.c:2688 sql_help.c:3255 msgid "connlimit" msgstr "접속제한" -#: sql_help.c:118 sql_help.c:2219 +#: sql_help.c:118 sql_help.c:2240 msgid "istemplate" msgstr "템플릿?" -#: sql_help.c:124 sql_help.c:611 sql_help.c:679 sql_help.c:693 sql_help.c:1322 -#: sql_help.c:1374 sql_help.c:4200 +#: sql_help.c:124 sql_help.c:621 sql_help.c:689 sql_help.c:703 sql_help.c:1338 +#: sql_help.c:1392 sql_help.c:4232 msgid "new_tablespace" msgstr "새테이블스페이스" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:548 sql_help.c:550 -#: sql_help.c:551 sql_help.c:875 sql_help.c:877 sql_help.c:878 sql_help.c:958 -#: sql_help.c:962 sql_help.c:965 sql_help.c:1027 sql_help.c:1029 -#: sql_help.c:1030 sql_help.c:1180 sql_help.c:1183 sql_help.c:1643 -#: sql_help.c:1647 sql_help.c:1650 sql_help.c:2406 sql_help.c:2609 -#: sql_help.c:3927 sql_help.c:4218 sql_help.c:4379 sql_help.c:4688 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:558 sql_help.c:560 +#: sql_help.c:561 sql_help.c:891 sql_help.c:893 sql_help.c:894 sql_help.c:974 +#: sql_help.c:978 sql_help.c:981 sql_help.c:1043 sql_help.c:1045 +#: sql_help.c:1046 sql_help.c:1196 sql_help.c:1198 sql_help.c:1664 +#: sql_help.c:1668 sql_help.c:1671 sql_help.c:2427 sql_help.c:2630 +#: sql_help.c:3948 sql_help.c:4250 sql_help.c:4411 sql_help.c:4721 msgid "configuration_parameter" msgstr "환경설정_매개변수" -#: sql_help.c:128 sql_help.c:398 sql_help.c:469 sql_help.c:475 sql_help.c:487 -#: sql_help.c:549 sql_help.c:603 sql_help.c:685 sql_help.c:695 sql_help.c:876 -#: sql_help.c:904 sql_help.c:959 sql_help.c:1028 sql_help.c:1101 -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:1157 -#: sql_help.c:1162 sql_help.c:1165 sql_help.c:1181 sql_help.c:1182 -#: sql_help.c:1353 sql_help.c:1376 sql_help.c:1424 sql_help.c:1449 -#: sql_help.c:1506 sql_help.c:1590 sql_help.c:1644 sql_help.c:1667 -#: sql_help.c:2286 sql_help.c:2336 sql_help.c:2343 sql_help.c:2352 -#: sql_help.c:2407 sql_help.c:2408 sql_help.c:2472 sql_help.c:2475 -#: sql_help.c:2509 sql_help.c:2610 sql_help.c:2611 sql_help.c:2634 -#: sql_help.c:2761 sql_help.c:2800 sql_help.c:2910 sql_help.c:2923 -#: sql_help.c:2937 sql_help.c:2978 sql_help.c:3005 sql_help.c:3022 -#: sql_help.c:3049 sql_help.c:3256 sql_help.c:3960 sql_help.c:4689 -#: sql_help.c:4690 sql_help.c:4691 sql_help.c:4692 +#: sql_help.c:128 sql_help.c:408 sql_help.c:479 sql_help.c:485 sql_help.c:497 +#: sql_help.c:559 sql_help.c:613 sql_help.c:695 sql_help.c:705 sql_help.c:892 +#: sql_help.c:920 sql_help.c:975 sql_help.c:1044 sql_help.c:1117 +#: sql_help.c:1162 sql_help.c:1166 sql_help.c:1170 sql_help.c:1173 +#: sql_help.c:1178 sql_help.c:1181 sql_help.c:1197 sql_help.c:1371 +#: sql_help.c:1394 sql_help.c:1442 sql_help.c:1450 sql_help.c:1470 +#: sql_help.c:1527 sql_help.c:1611 sql_help.c:1665 sql_help.c:1688 +#: sql_help.c:2307 sql_help.c:2357 sql_help.c:2364 sql_help.c:2373 +#: sql_help.c:2428 sql_help.c:2429 sql_help.c:2493 sql_help.c:2496 +#: sql_help.c:2530 sql_help.c:2631 sql_help.c:2632 sql_help.c:2655 +#: sql_help.c:2778 sql_help.c:2817 sql_help.c:2927 sql_help.c:2940 +#: sql_help.c:2954 sql_help.c:2995 sql_help.c:3003 sql_help.c:3025 +#: sql_help.c:3042 sql_help.c:3069 sql_help.c:3276 sql_help.c:3981 +#: sql_help.c:4722 sql_help.c:4723 sql_help.c:4724 sql_help.c:4725 msgid "value" msgstr "값" -#: sql_help.c:200 +#: sql_help.c:202 msgid "target_role" msgstr "대상롤" -#: sql_help.c:201 sql_help.c:913 sql_help.c:2270 sql_help.c:2639 -#: sql_help.c:2716 sql_help.c:2721 sql_help.c:3890 sql_help.c:3899 -#: sql_help.c:3918 sql_help.c:3930 sql_help.c:4342 sql_help.c:4351 -#: sql_help.c:4370 sql_help.c:4382 +#: sql_help.c:203 sql_help.c:929 sql_help.c:2291 sql_help.c:2660 +#: sql_help.c:2733 sql_help.c:2738 sql_help.c:3911 sql_help.c:3920 +#: sql_help.c:3939 sql_help.c:3951 sql_help.c:4374 sql_help.c:4383 +#: sql_help.c:4402 sql_help.c:4414 msgid "schema_name" msgstr "스키마이름" -#: sql_help.c:202 +#: sql_help.c:204 msgid "abbreviated_grant_or_revoke" msgstr "grant_또는_revoke_내용" -#: sql_help.c:203 +#: sql_help.c:205 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "grant_또는_revoke_내용에 사용되는 구문:" -#: sql_help.c:204 sql_help.c:205 sql_help.c:206 sql_help.c:207 sql_help.c:208 -#: sql_help.c:209 sql_help.c:210 sql_help.c:211 sql_help.c:212 sql_help.c:213 -#: sql_help.c:574 sql_help.c:610 sql_help.c:678 sql_help.c:822 sql_help.c:969 -#: sql_help.c:1321 sql_help.c:1654 sql_help.c:2445 sql_help.c:2446 -#: sql_help.c:2447 sql_help.c:2448 sql_help.c:2449 sql_help.c:2583 -#: sql_help.c:2672 sql_help.c:2673 sql_help.c:2674 sql_help.c:2675 -#: sql_help.c:2676 sql_help.c:3238 sql_help.c:3239 sql_help.c:3240 -#: sql_help.c:3241 sql_help.c:3242 sql_help.c:3939 sql_help.c:3943 -#: sql_help.c:4391 sql_help.c:4395 sql_help.c:4710 +#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 +#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 +#: sql_help.c:584 sql_help.c:620 sql_help.c:688 sql_help.c:838 sql_help.c:985 +#: sql_help.c:1337 sql_help.c:1675 sql_help.c:2466 sql_help.c:2467 +#: sql_help.c:2468 sql_help.c:2469 sql_help.c:2470 sql_help.c:2604 +#: sql_help.c:2691 sql_help.c:2692 sql_help.c:2693 sql_help.c:3258 +#: sql_help.c:3259 sql_help.c:3260 sql_help.c:3261 sql_help.c:3262 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:4423 sql_help.c:4427 +#: sql_help.c:4743 msgid "role_name" msgstr "롤이름" -#: sql_help.c:239 sql_help.c:462 sql_help.c:912 sql_help.c:1337 sql_help.c:1339 -#: sql_help.c:1391 sql_help.c:1403 sql_help.c:1428 sql_help.c:1684 -#: sql_help.c:2239 sql_help.c:2243 sql_help.c:2355 sql_help.c:2360 -#: sql_help.c:2468 sql_help.c:2638 sql_help.c:2777 sql_help.c:2782 -#: sql_help.c:2784 sql_help.c:2905 sql_help.c:2918 sql_help.c:2932 -#: sql_help.c:2941 sql_help.c:2953 sql_help.c:2982 sql_help.c:3991 -#: sql_help.c:4006 sql_help.c:4008 sql_help.c:4095 sql_help.c:4098 -#: sql_help.c:4100 sql_help.c:4561 sql_help.c:4562 sql_help.c:4571 -#: sql_help.c:4618 sql_help.c:4619 sql_help.c:4620 sql_help.c:4621 -#: sql_help.c:4622 sql_help.c:4623 sql_help.c:4663 sql_help.c:4664 -#: sql_help.c:4669 sql_help.c:4674 sql_help.c:4818 sql_help.c:4819 -#: sql_help.c:4828 sql_help.c:4875 sql_help.c:4876 sql_help.c:4877 -#: sql_help.c:4878 sql_help.c:4879 sql_help.c:4880 sql_help.c:4934 -#: sql_help.c:4936 sql_help.c:5004 sql_help.c:5064 sql_help.c:5065 -#: sql_help.c:5074 sql_help.c:5121 sql_help.c:5122 sql_help.c:5123 -#: sql_help.c:5124 sql_help.c:5125 sql_help.c:5126 +#: sql_help.c:246 sql_help.c:265 sql_help.c:472 sql_help.c:928 sql_help.c:1353 +#: sql_help.c:1355 sql_help.c:1359 sql_help.c:1409 sql_help.c:1421 +#: sql_help.c:1446 sql_help.c:1705 sql_help.c:2260 sql_help.c:2264 +#: sql_help.c:2376 sql_help.c:2381 sql_help.c:2489 sql_help.c:2659 +#: sql_help.c:2794 sql_help.c:2799 sql_help.c:2801 sql_help.c:2922 +#: sql_help.c:2935 sql_help.c:2949 sql_help.c:2958 sql_help.c:2970 +#: sql_help.c:2999 sql_help.c:4012 sql_help.c:4027 sql_help.c:4029 +#: sql_help.c:4125 sql_help.c:4128 sql_help.c:4130 sql_help.c:4593 +#: sql_help.c:4594 sql_help.c:4603 sql_help.c:4650 sql_help.c:4651 +#: sql_help.c:4652 sql_help.c:4653 sql_help.c:4654 sql_help.c:4655 +#: sql_help.c:4696 sql_help.c:4697 sql_help.c:4702 sql_help.c:4707 +#: sql_help.c:4851 sql_help.c:4852 sql_help.c:4861 sql_help.c:4908 +#: sql_help.c:4909 sql_help.c:4910 sql_help.c:4911 sql_help.c:4912 +#: sql_help.c:4913 sql_help.c:4968 sql_help.c:4970 sql_help.c:5036 +#: sql_help.c:5096 sql_help.c:5097 sql_help.c:5106 sql_help.c:5153 +#: sql_help.c:5154 sql_help.c:5155 sql_help.c:5156 sql_help.c:5157 +#: sql_help.c:5158 msgid "expression" msgstr "표현식" -#: sql_help.c:242 +#: sql_help.c:249 sql_help.c:2261 msgid "domain_constraint" msgstr "도메인_제약조건" -#: sql_help.c:244 sql_help.c:246 sql_help.c:249 sql_help.c:477 sql_help.c:478 -#: sql_help.c:1314 sql_help.c:1361 sql_help.c:1362 sql_help.c:1363 -#: sql_help.c:1390 sql_help.c:1402 sql_help.c:1419 sql_help.c:1854 -#: sql_help.c:1856 sql_help.c:2242 sql_help.c:2354 sql_help.c:2359 -#: sql_help.c:2940 sql_help.c:2952 sql_help.c:4003 +#: sql_help.c:251 sql_help.c:253 sql_help.c:256 sql_help.c:264 sql_help.c:487 +#: sql_help.c:488 sql_help.c:1330 sql_help.c:1379 sql_help.c:1380 +#: sql_help.c:1381 sql_help.c:1408 sql_help.c:1420 sql_help.c:1437 +#: sql_help.c:1869 sql_help.c:1871 sql_help.c:2263 sql_help.c:2375 +#: sql_help.c:2380 sql_help.c:2957 sql_help.c:2969 sql_help.c:4024 msgid "constraint_name" msgstr "제약조건_이름" -#: sql_help.c:247 sql_help.c:1315 +#: sql_help.c:254 sql_help.c:1331 msgid "new_constraint_name" msgstr "새제약조건_이름" -#: sql_help.c:320 sql_help.c:1099 +#: sql_help.c:263 sql_help.c:2262 +msgid "where domain_constraint is:" +msgstr "도메인_제약조건 사용법:" + +#: sql_help.c:330 sql_help.c:1115 msgid "new_version" msgstr "새버전" -#: sql_help.c:324 sql_help.c:326 +#: sql_help.c:334 sql_help.c:336 msgid "member_object" msgstr "맴버_객체" -#: sql_help.c:327 +#: sql_help.c:337 msgid "where member_object is:" msgstr "맴버_객체 사용법:" -#: sql_help.c:328 sql_help.c:333 sql_help.c:334 sql_help.c:335 sql_help.c:336 -#: sql_help.c:337 sql_help.c:338 sql_help.c:343 sql_help.c:347 sql_help.c:349 -#: sql_help.c:351 sql_help.c:360 sql_help.c:361 sql_help.c:362 sql_help.c:363 -#: sql_help.c:364 sql_help.c:365 sql_help.c:366 sql_help.c:367 sql_help.c:370 -#: sql_help.c:371 sql_help.c:1846 sql_help.c:1851 sql_help.c:1858 -#: sql_help.c:1859 sql_help.c:1860 sql_help.c:1861 sql_help.c:1862 -#: sql_help.c:1863 sql_help.c:1864 sql_help.c:1869 sql_help.c:1871 -#: sql_help.c:1875 sql_help.c:1877 sql_help.c:1881 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1894 sql_help.c:1895 sql_help.c:1896 -#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 -#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 sql_help.c:1904 -#: sql_help.c:1909 sql_help.c:1910 sql_help.c:4464 sql_help.c:4469 -#: sql_help.c:4470 sql_help.c:4471 sql_help.c:4472 sql_help.c:4478 -#: sql_help.c:4479 sql_help.c:4484 sql_help.c:4485 sql_help.c:4490 -#: sql_help.c:4491 sql_help.c:4492 sql_help.c:4493 sql_help.c:4494 -#: sql_help.c:4495 +#: sql_help.c:338 sql_help.c:343 sql_help.c:344 sql_help.c:345 sql_help.c:346 +#: sql_help.c:347 sql_help.c:348 sql_help.c:353 sql_help.c:357 sql_help.c:359 +#: sql_help.c:361 sql_help.c:370 sql_help.c:371 sql_help.c:372 sql_help.c:373 +#: sql_help.c:374 sql_help.c:375 sql_help.c:376 sql_help.c:377 sql_help.c:380 +#: sql_help.c:381 sql_help.c:1861 sql_help.c:1866 sql_help.c:1873 +#: sql_help.c:1874 sql_help.c:1875 sql_help.c:1876 sql_help.c:1877 +#: sql_help.c:1878 sql_help.c:1879 sql_help.c:1884 sql_help.c:1886 +#: sql_help.c:1890 sql_help.c:1892 sql_help.c:1896 sql_help.c:1901 +#: sql_help.c:1902 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1912 sql_help.c:1913 sql_help.c:1914 sql_help.c:1915 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:1918 sql_help.c:1919 +#: sql_help.c:1924 sql_help.c:1925 sql_help.c:4496 sql_help.c:4501 +#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4510 +#: sql_help.c:4511 sql_help.c:4516 sql_help.c:4517 sql_help.c:4522 +#: sql_help.c:4523 sql_help.c:4524 sql_help.c:4525 sql_help.c:4526 +#: sql_help.c:4527 msgid "object_name" msgstr "객체이름" -#: sql_help.c:329 sql_help.c:1847 sql_help.c:4467 +#: sql_help.c:339 sql_help.c:1862 sql_help.c:4499 msgid "aggregate_name" msgstr "집계함수이름" -#: sql_help.c:331 sql_help.c:1849 sql_help.c:2135 sql_help.c:2139 -#: sql_help.c:2141 sql_help.c:3365 +#: sql_help.c:341 sql_help.c:1864 sql_help.c:2154 sql_help.c:2158 +#: sql_help.c:2160 sql_help.c:3385 msgid "source_type" msgstr "기존자료형" -#: sql_help.c:332 sql_help.c:1850 sql_help.c:2136 sql_help.c:2140 -#: sql_help.c:2142 sql_help.c:3366 +#: sql_help.c:342 sql_help.c:1865 sql_help.c:2155 sql_help.c:2159 +#: sql_help.c:2161 sql_help.c:3386 msgid "target_type" msgstr "대상자료형" -#: sql_help.c:339 sql_help.c:786 sql_help.c:1865 sql_help.c:2137 -#: sql_help.c:2180 sql_help.c:2258 sql_help.c:2526 sql_help.c:2557 -#: sql_help.c:3125 sql_help.c:4366 sql_help.c:4473 sql_help.c:4590 -#: sql_help.c:4594 sql_help.c:4598 sql_help.c:4601 sql_help.c:4847 -#: sql_help.c:4851 sql_help.c:4855 sql_help.c:4858 sql_help.c:5093 -#: sql_help.c:5097 sql_help.c:5101 sql_help.c:5104 +#: sql_help.c:349 sql_help.c:802 sql_help.c:1880 sql_help.c:2156 +#: sql_help.c:2199 sql_help.c:2279 sql_help.c:2547 sql_help.c:2578 +#: sql_help.c:3145 sql_help.c:4398 sql_help.c:4505 sql_help.c:4622 +#: sql_help.c:4626 sql_help.c:4630 sql_help.c:4633 sql_help.c:4880 +#: sql_help.c:4884 sql_help.c:4888 sql_help.c:4891 sql_help.c:5125 +#: sql_help.c:5129 sql_help.c:5133 sql_help.c:5136 msgid "function_name" msgstr "함수이름" -#: sql_help.c:344 sql_help.c:779 sql_help.c:1872 sql_help.c:2550 +#: sql_help.c:354 sql_help.c:795 sql_help.c:1887 sql_help.c:2571 msgid "operator_name" msgstr "연산자이름" -#: sql_help.c:345 sql_help.c:715 sql_help.c:719 sql_help.c:723 sql_help.c:1873 -#: sql_help.c:2527 sql_help.c:3489 +#: sql_help.c:355 sql_help.c:729 sql_help.c:733 sql_help.c:737 sql_help.c:1888 +#: sql_help.c:2548 sql_help.c:3509 msgid "left_type" msgstr "왼쪽인자_자료형" -#: sql_help.c:346 sql_help.c:716 sql_help.c:720 sql_help.c:724 sql_help.c:1874 -#: sql_help.c:2528 sql_help.c:3490 +#: sql_help.c:356 sql_help.c:730 sql_help.c:734 sql_help.c:738 sql_help.c:1889 +#: sql_help.c:2549 sql_help.c:3510 msgid "right_type" msgstr "오른쪽인자_자료형" -#: sql_help.c:348 sql_help.c:350 sql_help.c:742 sql_help.c:745 sql_help.c:748 -#: sql_help.c:777 sql_help.c:789 sql_help.c:797 sql_help.c:800 sql_help.c:803 -#: sql_help.c:1408 sql_help.c:1876 sql_help.c:1878 sql_help.c:2547 -#: sql_help.c:2568 sql_help.c:2958 sql_help.c:3499 sql_help.c:3508 +#: sql_help.c:358 sql_help.c:360 sql_help.c:758 sql_help.c:761 sql_help.c:764 +#: sql_help.c:793 sql_help.c:805 sql_help.c:813 sql_help.c:816 sql_help.c:819 +#: sql_help.c:1426 sql_help.c:1891 sql_help.c:1893 sql_help.c:2568 +#: sql_help.c:2589 sql_help.c:2975 sql_help.c:3519 sql_help.c:3528 msgid "index_method" msgstr "색인방법" -#: sql_help.c:352 sql_help.c:1882 sql_help.c:4480 +#: sql_help.c:362 sql_help.c:1897 sql_help.c:4512 msgid "procedure_name" msgstr "프로시져_이름" -#: sql_help.c:356 sql_help.c:1888 sql_help.c:3914 sql_help.c:4486 +#: sql_help.c:366 sql_help.c:1903 sql_help.c:3935 sql_help.c:4518 msgid "routine_name" msgstr "루틴_이름" -#: sql_help.c:368 sql_help.c:1380 sql_help.c:1905 sql_help.c:2402 -#: sql_help.c:2608 sql_help.c:2913 sql_help.c:3092 sql_help.c:3670 -#: sql_help.c:3936 sql_help.c:4388 +#: sql_help.c:378 sql_help.c:1398 sql_help.c:1920 sql_help.c:2423 +#: sql_help.c:2629 sql_help.c:2930 sql_help.c:3112 sql_help.c:3690 +#: sql_help.c:3957 sql_help.c:4420 msgid "type_name" msgstr "자료형이름" -#: sql_help.c:369 sql_help.c:1906 sql_help.c:2401 sql_help.c:2607 -#: sql_help.c:3093 sql_help.c:3323 sql_help.c:3671 sql_help.c:3921 -#: sql_help.c:4373 +#: sql_help.c:379 sql_help.c:1921 sql_help.c:2422 sql_help.c:2628 +#: sql_help.c:3113 sql_help.c:3343 sql_help.c:3691 sql_help.c:3942 +#: sql_help.c:4405 msgid "lang_name" msgstr "언어_이름" -#: sql_help.c:372 +#: sql_help.c:382 msgid "and aggregate_signature is:" msgstr "집계함수_식별구문 사용법:" -#: sql_help.c:395 sql_help.c:2002 sql_help.c:2283 +#: sql_help.c:405 sql_help.c:2021 sql_help.c:2304 msgid "handler_function" msgstr "핸들러_함수" -#: sql_help.c:396 sql_help.c:2284 +#: sql_help.c:406 sql_help.c:2305 msgid "validator_function" msgstr "유효성검사_함수" -#: sql_help.c:444 sql_help.c:523 sql_help.c:667 sql_help.c:853 sql_help.c:1003 -#: sql_help.c:1309 sql_help.c:1581 +#: sql_help.c:454 sql_help.c:533 sql_help.c:677 sql_help.c:869 sql_help.c:1019 +#: sql_help.c:1325 sql_help.c:1602 msgid "action" msgstr "동작" -#: sql_help.c:446 sql_help.c:453 sql_help.c:457 sql_help.c:458 sql_help.c:461 -#: sql_help.c:463 sql_help.c:464 sql_help.c:465 sql_help.c:467 sql_help.c:470 -#: sql_help.c:472 sql_help.c:473 sql_help.c:671 sql_help.c:681 sql_help.c:683 -#: sql_help.c:686 sql_help.c:688 sql_help.c:689 sql_help.c:911 sql_help.c:1080 -#: sql_help.c:1311 sql_help.c:1329 sql_help.c:1333 sql_help.c:1334 -#: sql_help.c:1338 sql_help.c:1340 sql_help.c:1341 sql_help.c:1342 -#: sql_help.c:1343 sql_help.c:1345 sql_help.c:1348 sql_help.c:1349 -#: sql_help.c:1351 sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 -#: sql_help.c:1404 sql_help.c:1406 sql_help.c:1413 sql_help.c:1422 -#: sql_help.c:1427 sql_help.c:1431 sql_help.c:1432 sql_help.c:1683 -#: sql_help.c:1686 sql_help.c:1690 sql_help.c:1728 sql_help.c:1853 -#: sql_help.c:1967 sql_help.c:1973 sql_help.c:1987 sql_help.c:1988 -#: sql_help.c:1989 sql_help.c:2333 sql_help.c:2346 sql_help.c:2399 -#: sql_help.c:2467 sql_help.c:2473 sql_help.c:2506 sql_help.c:2637 -#: sql_help.c:2746 sql_help.c:2781 sql_help.c:2783 sql_help.c:2895 -#: sql_help.c:2904 sql_help.c:2914 sql_help.c:2917 sql_help.c:2927 -#: sql_help.c:2931 sql_help.c:2954 sql_help.c:2956 sql_help.c:2963 -#: sql_help.c:2976 sql_help.c:2981 sql_help.c:2985 sql_help.c:2986 -#: sql_help.c:3002 sql_help.c:3128 sql_help.c:3268 sql_help.c:3893 -#: sql_help.c:3894 sql_help.c:3990 sql_help.c:4005 sql_help.c:4007 -#: sql_help.c:4009 sql_help.c:4094 sql_help.c:4097 sql_help.c:4099 -#: sql_help.c:4345 sql_help.c:4346 sql_help.c:4466 sql_help.c:4627 -#: sql_help.c:4633 sql_help.c:4635 sql_help.c:4884 sql_help.c:4890 -#: sql_help.c:4892 sql_help.c:4933 sql_help.c:4935 sql_help.c:4937 -#: sql_help.c:4992 sql_help.c:5130 sql_help.c:5136 sql_help.c:5138 +#: sql_help.c:456 sql_help.c:463 sql_help.c:467 sql_help.c:468 sql_help.c:471 +#: sql_help.c:473 sql_help.c:474 sql_help.c:475 sql_help.c:477 sql_help.c:480 +#: sql_help.c:482 sql_help.c:483 sql_help.c:681 sql_help.c:691 sql_help.c:693 +#: sql_help.c:696 sql_help.c:698 sql_help.c:699 sql_help.c:927 sql_help.c:1096 +#: sql_help.c:1327 sql_help.c:1345 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 sql_help.c:1358 +#: sql_help.c:1360 sql_help.c:1361 sql_help.c:1363 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1369 sql_help.c:1372 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1422 sql_help.c:1424 sql_help.c:1431 +#: sql_help.c:1440 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1704 sql_help.c:1707 sql_help.c:1711 sql_help.c:1747 +#: sql_help.c:1868 sql_help.c:1984 sql_help.c:1990 sql_help.c:2004 +#: sql_help.c:2005 sql_help.c:2006 sql_help.c:2354 sql_help.c:2367 +#: sql_help.c:2420 sql_help.c:2488 sql_help.c:2494 sql_help.c:2527 +#: sql_help.c:2658 sql_help.c:2763 sql_help.c:2798 sql_help.c:2800 +#: sql_help.c:2912 sql_help.c:2921 sql_help.c:2931 sql_help.c:2934 +#: sql_help.c:2944 sql_help.c:2948 sql_help.c:2971 sql_help.c:2973 +#: sql_help.c:2980 sql_help.c:2993 sql_help.c:2998 sql_help.c:3005 +#: sql_help.c:3006 sql_help.c:3022 sql_help.c:3148 sql_help.c:3288 +#: sql_help.c:3914 sql_help.c:3915 sql_help.c:4011 sql_help.c:4026 +#: sql_help.c:4028 sql_help.c:4030 sql_help.c:4124 sql_help.c:4127 +#: sql_help.c:4129 sql_help.c:4131 sql_help.c:4377 sql_help.c:4378 +#: sql_help.c:4498 sql_help.c:4659 sql_help.c:4666 sql_help.c:4668 +#: sql_help.c:4917 sql_help.c:4924 sql_help.c:4926 sql_help.c:4967 +#: sql_help.c:4969 sql_help.c:4971 sql_help.c:5024 sql_help.c:5162 +#: sql_help.c:5169 sql_help.c:5171 msgid "column_name" msgstr "칼럼이름" -#: sql_help.c:447 sql_help.c:672 sql_help.c:1312 sql_help.c:1691 +#: sql_help.c:457 sql_help.c:682 sql_help.c:1328 sql_help.c:1712 msgid "new_column_name" msgstr "새칼럼이름" -#: sql_help.c:452 sql_help.c:544 sql_help.c:680 sql_help.c:874 sql_help.c:1024 -#: sql_help.c:1328 sql_help.c:1591 +#: sql_help.c:462 sql_help.c:554 sql_help.c:690 sql_help.c:890 sql_help.c:1040 +#: sql_help.c:1344 sql_help.c:1612 msgid "where action is one of:" msgstr "동작 사용법:" -#: sql_help.c:454 sql_help.c:459 sql_help.c:1072 sql_help.c:1330 -#: sql_help.c:1335 sql_help.c:1593 sql_help.c:1597 sql_help.c:2237 -#: sql_help.c:2334 sql_help.c:2546 sql_help.c:2739 sql_help.c:2896 -#: sql_help.c:3175 sql_help.c:4151 +#: sql_help.c:464 sql_help.c:469 sql_help.c:1088 sql_help.c:1346 +#: sql_help.c:1351 sql_help.c:1614 sql_help.c:1618 sql_help.c:2258 +#: sql_help.c:2355 sql_help.c:2567 sql_help.c:2756 sql_help.c:2913 +#: sql_help.c:3195 sql_help.c:4183 msgid "data_type" msgstr "자료형" -#: sql_help.c:455 sql_help.c:460 sql_help.c:1331 sql_help.c:1336 -#: sql_help.c:1594 sql_help.c:1598 sql_help.c:2238 sql_help.c:2337 -#: sql_help.c:2469 sql_help.c:2898 sql_help.c:2906 sql_help.c:2919 -#: sql_help.c:2933 sql_help.c:3176 sql_help.c:3182 sql_help.c:4000 +#: sql_help.c:465 sql_help.c:470 sql_help.c:1347 sql_help.c:1352 +#: sql_help.c:1447 sql_help.c:1615 sql_help.c:1619 sql_help.c:2259 +#: sql_help.c:2358 sql_help.c:2490 sql_help.c:2915 sql_help.c:2923 +#: sql_help.c:2936 sql_help.c:2950 sql_help.c:3000 sql_help.c:3196 +#: sql_help.c:3202 sql_help.c:4021 msgid "collation" msgstr "collation" -#: sql_help.c:456 sql_help.c:1332 sql_help.c:2338 sql_help.c:2347 -#: sql_help.c:2899 sql_help.c:2915 sql_help.c:2928 +#: sql_help.c:466 sql_help.c:1348 sql_help.c:2359 sql_help.c:2368 +#: sql_help.c:2916 sql_help.c:2932 sql_help.c:2945 msgid "column_constraint" msgstr "칼럼_제약조건" -#: sql_help.c:466 sql_help.c:608 sql_help.c:682 sql_help.c:1350 sql_help.c:4986 +#: sql_help.c:476 sql_help.c:618 sql_help.c:692 sql_help.c:1368 sql_help.c:5018 msgid "integer" msgstr "정수" -#: sql_help.c:468 sql_help.c:471 sql_help.c:684 sql_help.c:687 sql_help.c:1352 -#: sql_help.c:1355 +#: sql_help.c:478 sql_help.c:481 sql_help.c:694 sql_help.c:697 sql_help.c:1370 +#: sql_help.c:1373 msgid "attribute_option" msgstr "속성_옵션" -#: sql_help.c:476 sql_help.c:1359 sql_help.c:2339 sql_help.c:2348 -#: sql_help.c:2900 sql_help.c:2916 sql_help.c:2929 +#: sql_help.c:486 sql_help.c:1377 sql_help.c:2360 sql_help.c:2369 +#: sql_help.c:2917 sql_help.c:2933 sql_help.c:2946 msgid "table_constraint" msgstr "테이블_제약조건" -#: sql_help.c:479 sql_help.c:480 sql_help.c:481 sql_help.c:482 sql_help.c:1364 -#: sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 sql_help.c:1907 +#: sql_help.c:489 sql_help.c:490 sql_help.c:491 sql_help.c:492 sql_help.c:1382 +#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:1922 msgid "trigger_name" msgstr "트리거이름" -#: sql_help.c:483 sql_help.c:484 sql_help.c:1378 sql_help.c:1379 -#: sql_help.c:2340 sql_help.c:2345 sql_help.c:2903 sql_help.c:2926 +#: sql_help.c:493 sql_help.c:494 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:2361 sql_help.c:2366 sql_help.c:2920 sql_help.c:2943 msgid "parent_table" msgstr "상위_테이블" -#: sql_help.c:543 sql_help.c:600 sql_help.c:669 sql_help.c:873 sql_help.c:1023 -#: sql_help.c:1550 sql_help.c:2269 +#: sql_help.c:553 sql_help.c:610 sql_help.c:679 sql_help.c:889 sql_help.c:1039 +#: sql_help.c:1571 sql_help.c:2290 msgid "extension_name" msgstr "확장모듈이름" -#: sql_help.c:545 sql_help.c:1025 sql_help.c:2403 +#: sql_help.c:555 sql_help.c:1041 sql_help.c:2424 msgid "execution_cost" msgstr "실행비용" -#: sql_help.c:546 sql_help.c:1026 sql_help.c:2404 +#: sql_help.c:556 sql_help.c:1042 sql_help.c:2425 msgid "result_rows" msgstr "반환자료수" -#: sql_help.c:547 sql_help.c:2405 +#: sql_help.c:557 sql_help.c:2426 msgid "support_function" msgstr "지원_함수" -#: sql_help.c:569 sql_help.c:571 sql_help.c:948 sql_help.c:956 sql_help.c:960 -#: sql_help.c:963 sql_help.c:966 sql_help.c:1633 sql_help.c:1641 -#: sql_help.c:1645 sql_help.c:1648 sql_help.c:1651 sql_help.c:2717 -#: sql_help.c:2719 sql_help.c:2722 sql_help.c:2723 sql_help.c:3891 -#: sql_help.c:3892 sql_help.c:3896 sql_help.c:3897 sql_help.c:3900 -#: sql_help.c:3901 sql_help.c:3903 sql_help.c:3904 sql_help.c:3906 -#: sql_help.c:3907 sql_help.c:3909 sql_help.c:3910 sql_help.c:3912 -#: sql_help.c:3913 sql_help.c:3919 sql_help.c:3920 sql_help.c:3922 -#: sql_help.c:3923 sql_help.c:3925 sql_help.c:3926 sql_help.c:3928 -#: sql_help.c:3929 sql_help.c:3931 sql_help.c:3932 sql_help.c:3934 -#: sql_help.c:3935 sql_help.c:3937 sql_help.c:3938 sql_help.c:3940 -#: sql_help.c:3941 sql_help.c:4343 sql_help.c:4344 sql_help.c:4348 -#: sql_help.c:4349 sql_help.c:4352 sql_help.c:4353 sql_help.c:4355 -#: sql_help.c:4356 sql_help.c:4358 sql_help.c:4359 sql_help.c:4361 -#: sql_help.c:4362 sql_help.c:4364 sql_help.c:4365 sql_help.c:4371 -#: sql_help.c:4372 sql_help.c:4374 sql_help.c:4375 sql_help.c:4377 -#: sql_help.c:4378 sql_help.c:4380 sql_help.c:4381 sql_help.c:4383 -#: sql_help.c:4384 sql_help.c:4386 sql_help.c:4387 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4392 sql_help.c:4393 +#: sql_help.c:579 sql_help.c:581 sql_help.c:964 sql_help.c:972 sql_help.c:976 +#: sql_help.c:979 sql_help.c:982 sql_help.c:1654 sql_help.c:1662 +#: sql_help.c:1666 sql_help.c:1669 sql_help.c:1672 sql_help.c:2734 +#: sql_help.c:2736 sql_help.c:2739 sql_help.c:2740 sql_help.c:3912 +#: sql_help.c:3913 sql_help.c:3917 sql_help.c:3918 sql_help.c:3921 +#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 +#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 +#: sql_help.c:3934 sql_help.c:3940 sql_help.c:3941 sql_help.c:3943 +#: sql_help.c:3944 sql_help.c:3946 sql_help.c:3947 sql_help.c:3949 +#: sql_help.c:3950 sql_help.c:3952 sql_help.c:3953 sql_help.c:3955 +#: sql_help.c:3956 sql_help.c:3958 sql_help.c:3959 sql_help.c:3961 +#: sql_help.c:3962 sql_help.c:4375 sql_help.c:4376 sql_help.c:4380 +#: sql_help.c:4381 sql_help.c:4384 sql_help.c:4385 sql_help.c:4387 +#: sql_help.c:4388 sql_help.c:4390 sql_help.c:4391 sql_help.c:4393 +#: sql_help.c:4394 sql_help.c:4396 sql_help.c:4397 sql_help.c:4403 +#: sql_help.c:4404 sql_help.c:4406 sql_help.c:4407 sql_help.c:4409 +#: sql_help.c:4410 sql_help.c:4412 sql_help.c:4413 sql_help.c:4415 +#: sql_help.c:4416 sql_help.c:4418 sql_help.c:4419 sql_help.c:4421 +#: sql_help.c:4422 sql_help.c:4424 sql_help.c:4425 msgid "role_specification" msgstr "롤_명세" -#: sql_help.c:570 sql_help.c:572 sql_help.c:1664 sql_help.c:2205 -#: sql_help.c:2725 sql_help.c:3253 sql_help.c:3704 sql_help.c:4720 +#: sql_help.c:580 sql_help.c:582 sql_help.c:1685 sql_help.c:2225 +#: sql_help.c:2742 sql_help.c:3273 sql_help.c:3724 sql_help.c:4753 msgid "user_name" msgstr "사용자이름" -#: sql_help.c:573 sql_help.c:968 sql_help.c:1653 sql_help.c:2724 -#: sql_help.c:3942 sql_help.c:4394 +#: sql_help.c:583 sql_help.c:984 sql_help.c:1674 sql_help.c:2741 +#: sql_help.c:3963 sql_help.c:4426 msgid "where role_specification can be:" msgstr "롤_명세 사용법:" -#: sql_help.c:575 +#: sql_help.c:585 msgid "group_name" msgstr "그룹이름" -#: sql_help.c:596 sql_help.c:1425 sql_help.c:2216 sql_help.c:2476 -#: sql_help.c:2510 sql_help.c:2911 sql_help.c:2924 sql_help.c:2938 -#: sql_help.c:2979 sql_help.c:3006 sql_help.c:3018 sql_help.c:3933 -#: sql_help.c:4385 +#: sql_help.c:606 sql_help.c:1443 sql_help.c:2237 sql_help.c:2497 +#: sql_help.c:2531 sql_help.c:2928 sql_help.c:2941 sql_help.c:2955 +#: sql_help.c:2996 sql_help.c:3026 sql_help.c:3038 sql_help.c:3954 +#: sql_help.c:4417 msgid "tablespace_name" msgstr "테이블스페이스이름" -#: sql_help.c:598 sql_help.c:691 sql_help.c:1372 sql_help.c:1382 -#: sql_help.c:1420 sql_help.c:1782 sql_help.c:1785 +#: sql_help.c:608 sql_help.c:701 sql_help.c:1390 sql_help.c:1400 +#: sql_help.c:1438 sql_help.c:1800 msgid "index_name" msgstr "인덱스이름" -#: sql_help.c:602 sql_help.c:605 sql_help.c:694 sql_help.c:696 sql_help.c:1375 -#: sql_help.c:1377 sql_help.c:1423 sql_help.c:2474 sql_help.c:2508 -#: sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 sql_help.c:2977 -#: sql_help.c:3004 +#: sql_help.c:612 sql_help.c:615 sql_help.c:704 sql_help.c:706 sql_help.c:1393 +#: sql_help.c:1395 sql_help.c:1441 sql_help.c:2495 sql_help.c:2529 +#: sql_help.c:2926 sql_help.c:2939 sql_help.c:2953 sql_help.c:2994 +#: sql_help.c:3024 msgid "storage_parameter" msgstr "스토리지_매개변수" -#: sql_help.c:607 +#: sql_help.c:617 msgid "column_number" msgstr "칼럼번호" -#: sql_help.c:631 sql_help.c:1870 sql_help.c:4477 +#: sql_help.c:641 sql_help.c:1885 sql_help.c:4509 msgid "large_object_oid" msgstr "대형_객체_oid" -#: sql_help.c:690 sql_help.c:1358 sql_help.c:2897 +#: sql_help.c:700 sql_help.c:1376 sql_help.c:2914 msgid "compression_method" msgstr "압축_방법" -#: sql_help.c:692 sql_help.c:1373 +#: sql_help.c:702 sql_help.c:1391 msgid "new_access_method" msgstr "새_접근_방법" -#: sql_help.c:725 sql_help.c:2531 +#: sql_help.c:739 sql_help.c:2552 msgid "res_proc" msgstr "res_proc" -#: sql_help.c:726 sql_help.c:2532 +#: sql_help.c:740 sql_help.c:2553 msgid "join_proc" msgstr "join_proc" -#: sql_help.c:778 sql_help.c:790 sql_help.c:2549 +#: sql_help.c:741 sql_help.c:2550 +msgid "com_op" +msgstr "com_op" + +#: sql_help.c:742 sql_help.c:2551 +msgid "neg_op" +msgstr "neg_op" + +#: sql_help.c:794 sql_help.c:806 sql_help.c:2570 msgid "strategy_number" msgstr "전략_번호" -#: sql_help.c:780 sql_help.c:781 sql_help.c:784 sql_help.c:785 sql_help.c:791 -#: sql_help.c:792 sql_help.c:794 sql_help.c:795 sql_help.c:2551 sql_help.c:2552 -#: sql_help.c:2555 sql_help.c:2556 +#: sql_help.c:796 sql_help.c:797 sql_help.c:800 sql_help.c:801 sql_help.c:807 +#: sql_help.c:808 sql_help.c:810 sql_help.c:811 sql_help.c:2572 sql_help.c:2573 +#: sql_help.c:2576 sql_help.c:2577 msgid "op_type" msgstr "연산자자료형" -#: sql_help.c:782 sql_help.c:2553 +#: sql_help.c:798 sql_help.c:2574 msgid "sort_family_name" msgstr "정렬_가족_이름" -#: sql_help.c:783 sql_help.c:793 sql_help.c:2554 +#: sql_help.c:799 sql_help.c:809 sql_help.c:2575 msgid "support_number" msgstr "지원_번호" -#: sql_help.c:787 sql_help.c:2138 sql_help.c:2558 sql_help.c:3095 -#: sql_help.c:3097 +#: sql_help.c:803 sql_help.c:2157 sql_help.c:2579 sql_help.c:3115 +#: sql_help.c:3117 msgid "argument_type" msgstr "인자자료형" -#: sql_help.c:818 sql_help.c:821 sql_help.c:910 sql_help.c:1039 sql_help.c:1079 -#: sql_help.c:1546 sql_help.c:1549 sql_help.c:1727 sql_help.c:1781 -#: sql_help.c:1784 sql_help.c:1855 sql_help.c:1880 sql_help.c:1893 -#: sql_help.c:1908 sql_help.c:1966 sql_help.c:1972 sql_help.c:2332 -#: sql_help.c:2344 sql_help.c:2465 sql_help.c:2505 sql_help.c:2582 -#: sql_help.c:2636 sql_help.c:2693 sql_help.c:2745 sql_help.c:2778 -#: sql_help.c:2785 sql_help.c:2894 sql_help.c:2912 sql_help.c:2925 -#: sql_help.c:3001 sql_help.c:3121 sql_help.c:3302 sql_help.c:3525 -#: sql_help.c:3574 sql_help.c:3680 sql_help.c:3889 sql_help.c:3895 -#: sql_help.c:3956 sql_help.c:3988 sql_help.c:4341 sql_help.c:4347 -#: sql_help.c:4465 sql_help.c:4576 sql_help.c:4578 sql_help.c:4640 -#: sql_help.c:4679 sql_help.c:4833 sql_help.c:4835 sql_help.c:4897 -#: sql_help.c:4931 sql_help.c:4991 sql_help.c:5079 sql_help.c:5081 -#: sql_help.c:5143 +#: sql_help.c:834 sql_help.c:837 sql_help.c:926 sql_help.c:1055 sql_help.c:1095 +#: sql_help.c:1567 sql_help.c:1570 sql_help.c:1746 sql_help.c:1799 +#: sql_help.c:1870 sql_help.c:1895 sql_help.c:1908 sql_help.c:1923 +#: sql_help.c:1983 sql_help.c:1989 sql_help.c:2353 sql_help.c:2365 +#: sql_help.c:2486 sql_help.c:2526 sql_help.c:2603 sql_help.c:2657 +#: sql_help.c:2710 sql_help.c:2762 sql_help.c:2795 sql_help.c:2802 +#: sql_help.c:2911 sql_help.c:2929 sql_help.c:2942 sql_help.c:3021 +#: sql_help.c:3141 sql_help.c:3322 sql_help.c:3545 sql_help.c:3594 +#: sql_help.c:3700 sql_help.c:3910 sql_help.c:3916 sql_help.c:3977 +#: sql_help.c:4009 sql_help.c:4373 sql_help.c:4379 sql_help.c:4497 +#: sql_help.c:4610 sql_help.c:4673 sql_help.c:4712 sql_help.c:4868 +#: sql_help.c:4931 sql_help.c:4965 sql_help.c:5023 sql_help.c:5113 +#: sql_help.c:5176 msgid "table_name" msgstr "테이블_이름" -#: sql_help.c:823 sql_help.c:2584 +#: sql_help.c:839 sql_help.c:2605 msgid "using_expression" msgstr "using_expression" -#: sql_help.c:824 sql_help.c:2585 +#: sql_help.c:840 sql_help.c:2606 msgid "check_expression" msgstr "체크_표현식" -#: sql_help.c:897 sql_help.c:899 sql_help.c:901 sql_help.c:2632 +#: sql_help.c:913 sql_help.c:915 sql_help.c:917 sql_help.c:2653 msgid "publication_object" msgstr "발행_객체" -#: sql_help.c:903 sql_help.c:2633 +#: sql_help.c:919 sql_help.c:2654 msgid "publication_parameter" msgstr "발행_매개변수" -#: sql_help.c:909 sql_help.c:2635 +#: sql_help.c:925 sql_help.c:2656 msgid "where publication_object is one of:" msgstr "발행_객체 사용법:" -#: sql_help.c:952 sql_help.c:1637 sql_help.c:2443 sql_help.c:2670 -#: sql_help.c:3236 +#: sql_help.c:968 sql_help.c:1658 sql_help.c:2464 sql_help.c:2689 +#: sql_help.c:3256 msgid "password" msgstr "암호" -#: sql_help.c:953 sql_help.c:1638 sql_help.c:2444 sql_help.c:2671 -#: sql_help.c:3237 +#: sql_help.c:969 sql_help.c:1659 sql_help.c:2465 sql_help.c:2690 +#: sql_help.c:3257 msgid "timestamp" msgstr "타임스탬프" -#: sql_help.c:957 sql_help.c:961 sql_help.c:964 sql_help.c:967 sql_help.c:1642 -#: sql_help.c:1646 sql_help.c:1649 sql_help.c:1652 sql_help.c:3902 -#: sql_help.c:4354 +#: sql_help.c:973 sql_help.c:977 sql_help.c:980 sql_help.c:983 sql_help.c:1663 +#: sql_help.c:1667 sql_help.c:1670 sql_help.c:1673 sql_help.c:3923 +#: sql_help.c:4386 msgid "database_name" msgstr "데이터베이스_이름" -#: sql_help.c:1073 sql_help.c:2740 +#: sql_help.c:1089 sql_help.c:2757 msgid "increment" msgstr "증가값" -#: sql_help.c:1074 sql_help.c:2741 +#: sql_help.c:1090 sql_help.c:2758 msgid "minvalue" msgstr "최소값" -#: sql_help.c:1075 sql_help.c:2742 +#: sql_help.c:1091 sql_help.c:2759 msgid "maxvalue" msgstr "최대값" -#: sql_help.c:1076 sql_help.c:2743 sql_help.c:4574 sql_help.c:4677 -#: sql_help.c:4831 sql_help.c:5008 sql_help.c:5077 +#: sql_help.c:1092 sql_help.c:2760 sql_help.c:4606 sql_help.c:4710 +#: sql_help.c:4864 sql_help.c:5040 sql_help.c:5109 msgid "start" msgstr "시작" -#: sql_help.c:1077 sql_help.c:1347 +#: sql_help.c:1093 sql_help.c:1365 msgid "restart" msgstr "재시작" -#: sql_help.c:1078 sql_help.c:2744 +#: sql_help.c:1094 sql_help.c:2761 msgid "cache" msgstr "캐쉬" -#: sql_help.c:1123 +#: sql_help.c:1139 msgid "new_target" msgstr "새대상" -#: sql_help.c:1142 sql_help.c:2797 +#: sql_help.c:1158 sql_help.c:2814 msgid "conninfo" msgstr "접속정보" -#: sql_help.c:1144 sql_help.c:1148 sql_help.c:1152 sql_help.c:2798 +#: sql_help.c:1160 sql_help.c:1164 sql_help.c:1168 sql_help.c:2815 msgid "publication_name" msgstr "발행_이름" -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 +#: sql_help.c:1161 sql_help.c:1165 sql_help.c:1169 msgid "publication_option" msgstr "발행_옵션" -#: sql_help.c:1156 +#: sql_help.c:1172 msgid "refresh_option" msgstr "새로고침_옵션" -#: sql_help.c:1161 sql_help.c:2799 +#: sql_help.c:1177 sql_help.c:2816 msgid "subscription_parameter" msgstr "구독_매개변수" -#: sql_help.c:1164 +#: sql_help.c:1180 msgid "skip_option" msgstr "skip_option" -#: sql_help.c:1324 sql_help.c:1327 +#: sql_help.c:1340 sql_help.c:1343 msgid "partition_name" msgstr "파티션_이름" -#: sql_help.c:1325 sql_help.c:2349 sql_help.c:2930 +#: sql_help.c:1341 sql_help.c:2370 sql_help.c:2947 msgid "partition_bound_spec" msgstr "파티션_범위_정의" -#: sql_help.c:1344 sql_help.c:1394 sql_help.c:2944 +#: sql_help.c:1362 sql_help.c:1412 sql_help.c:2961 msgid "sequence_options" msgstr "시퀀스_옵션" -#: sql_help.c:1346 +#: sql_help.c:1364 msgid "sequence_option" msgstr "시퀀스_옵션" -#: sql_help.c:1360 +#: sql_help.c:1378 msgid "table_constraint_using_index" msgstr "색인을_사용하는_테이블_제약조건" -#: sql_help.c:1368 sql_help.c:1369 sql_help.c:1370 sql_help.c:1371 +#: sql_help.c:1386 sql_help.c:1387 sql_help.c:1388 sql_help.c:1389 msgid "rewrite_rule_name" msgstr "rewrite_룰_이름" -#: sql_help.c:1383 sql_help.c:2361 sql_help.c:2969 +#: sql_help.c:1401 sql_help.c:2382 sql_help.c:2986 msgid "and partition_bound_spec is:" msgstr "파티션_범위_정의 사용법:" -#: sql_help.c:1384 sql_help.c:1385 sql_help.c:1386 sql_help.c:2362 -#: sql_help.c:2363 sql_help.c:2364 sql_help.c:2970 sql_help.c:2971 -#: sql_help.c:2972 +#: sql_help.c:1402 sql_help.c:1403 sql_help.c:1404 sql_help.c:2383 +#: sql_help.c:2384 sql_help.c:2385 sql_help.c:2987 sql_help.c:2988 +#: sql_help.c:2989 msgid "partition_bound_expr" msgstr "파티션_범위_표현식" -#: sql_help.c:1387 sql_help.c:1388 sql_help.c:2365 sql_help.c:2366 -#: sql_help.c:2973 sql_help.c:2974 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:2386 sql_help.c:2387 +#: sql_help.c:2990 sql_help.c:2991 msgid "numeric_literal" msgstr "숫자" -#: sql_help.c:1389 +#: sql_help.c:1407 msgid "and column_constraint is:" msgstr "칼럼_제약조건 사용법:" -#: sql_help.c:1392 sql_help.c:2356 sql_help.c:2397 sql_help.c:2606 -#: sql_help.c:2942 +#: sql_help.c:1410 sql_help.c:2377 sql_help.c:2418 sql_help.c:2627 +#: sql_help.c:2959 msgid "default_expr" msgstr "초기값_표현식" -#: sql_help.c:1393 sql_help.c:2357 sql_help.c:2943 +#: sql_help.c:1411 sql_help.c:2378 sql_help.c:2960 msgid "generation_expr" msgstr "생성_표현식" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1405 sql_help.c:1407 -#: sql_help.c:1411 sql_help.c:2945 sql_help.c:2946 sql_help.c:2955 -#: sql_help.c:2957 sql_help.c:2961 +#: sql_help.c:1413 sql_help.c:1414 sql_help.c:1423 sql_help.c:1425 +#: sql_help.c:1429 sql_help.c:2962 sql_help.c:2963 sql_help.c:2972 +#: sql_help.c:2974 sql_help.c:2978 msgid "index_parameters" msgstr "색인_매개변수" -#: sql_help.c:1397 sql_help.c:1414 sql_help.c:2947 sql_help.c:2964 +#: sql_help.c:1415 sql_help.c:1432 sql_help.c:2964 sql_help.c:2981 msgid "reftable" msgstr "참조테이블" -#: sql_help.c:1398 sql_help.c:1415 sql_help.c:2948 sql_help.c:2965 +#: sql_help.c:1416 sql_help.c:1433 sql_help.c:2965 sql_help.c:2982 msgid "refcolumn" msgstr "참조칼럼" -#: sql_help.c:1399 sql_help.c:1400 sql_help.c:1416 sql_help.c:1417 -#: sql_help.c:2949 sql_help.c:2950 sql_help.c:2966 sql_help.c:2967 +#: sql_help.c:1417 sql_help.c:1418 sql_help.c:1434 sql_help.c:1435 +#: sql_help.c:2966 sql_help.c:2967 sql_help.c:2983 sql_help.c:2984 msgid "referential_action" msgstr "참조_방식" -#: sql_help.c:1401 sql_help.c:2358 sql_help.c:2951 +#: sql_help.c:1419 sql_help.c:2379 sql_help.c:2968 msgid "and table_constraint is:" msgstr "테이블_제약조건 사용법:" -#: sql_help.c:1409 sql_help.c:2959 +#: sql_help.c:1427 sql_help.c:2976 msgid "exclude_element" msgstr "exclude_요소" -#: sql_help.c:1410 sql_help.c:2960 sql_help.c:4572 sql_help.c:4675 -#: sql_help.c:4829 sql_help.c:5006 sql_help.c:5075 +#: sql_help.c:1428 sql_help.c:2977 sql_help.c:4604 sql_help.c:4708 +#: sql_help.c:4862 sql_help.c:5038 sql_help.c:5107 msgid "operator" msgstr "연산자" -#: sql_help.c:1412 sql_help.c:2477 sql_help.c:2962 +#: sql_help.c:1430 sql_help.c:2498 sql_help.c:2979 msgid "predicate" msgstr "범위한정구문" -#: sql_help.c:1418 +#: sql_help.c:1436 msgid "and table_constraint_using_index is:" msgstr "색인을_사용하는_테이블_제약조건 사용법:" -#: sql_help.c:1421 sql_help.c:2975 +#: sql_help.c:1439 sql_help.c:2992 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "UNIQUE, PRIMARY KEY, EXCLUDE 제약조건에서 쓰는 색인_매개변수 사용법:" -#: sql_help.c:1426 sql_help.c:2980 +#: sql_help.c:1444 sql_help.c:2997 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "EXCLUDE 제약조건에서 쓰는 exclude_요소 사용법:" -#: sql_help.c:1429 sql_help.c:2470 sql_help.c:2907 sql_help.c:2920 -#: sql_help.c:2934 sql_help.c:2983 sql_help.c:4001 +#: sql_help.c:1448 sql_help.c:2491 sql_help.c:2924 sql_help.c:2937 +#: sql_help.c:2951 sql_help.c:3001 sql_help.c:4022 msgid "opclass" msgstr "연산자클래스" -#: sql_help.c:1430 sql_help.c:2984 +#: sql_help.c:1449 sql_help.c:2492 sql_help.c:3002 +msgid "opclass_parameter" +msgstr "opclass_매개변수" + +#: sql_help.c:1451 sql_help.c:3004 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "FOREIGN KEY/REFERENCES 제약조건에서 쓰는 참조_방식 사용법:" -#: sql_help.c:1448 sql_help.c:1451 sql_help.c:3021 +#: sql_help.c:1469 sql_help.c:1472 sql_help.c:3041 msgid "tablespace_option" msgstr "테이블스페이스_옵션" -#: sql_help.c:1472 sql_help.c:1475 sql_help.c:1481 sql_help.c:1485 +#: sql_help.c:1493 sql_help.c:1496 sql_help.c:1502 sql_help.c:1506 msgid "token_type" msgstr "토큰_종류" -#: sql_help.c:1473 sql_help.c:1476 +#: sql_help.c:1494 sql_help.c:1497 msgid "dictionary_name" msgstr "사전이름" -#: sql_help.c:1478 sql_help.c:1482 +#: sql_help.c:1499 sql_help.c:1503 msgid "old_dictionary" msgstr "옛사전" -#: sql_help.c:1479 sql_help.c:1483 +#: sql_help.c:1500 sql_help.c:1504 msgid "new_dictionary" msgstr "새사전" -#: sql_help.c:1578 sql_help.c:1592 sql_help.c:1595 sql_help.c:1596 -#: sql_help.c:3174 +#: sql_help.c:1599 sql_help.c:1613 sql_help.c:1616 sql_help.c:1617 +#: sql_help.c:3194 msgid "attribute_name" msgstr "속성이름" -#: sql_help.c:1579 +#: sql_help.c:1600 msgid "new_attribute_name" msgstr "새속성이름" -#: sql_help.c:1583 sql_help.c:1587 +#: sql_help.c:1604 sql_help.c:1608 msgid "new_enum_value" msgstr "새_enum_값" -#: sql_help.c:1584 +#: sql_help.c:1605 msgid "neighbor_enum_value" msgstr "옆_enum_값" -#: sql_help.c:1586 +#: sql_help.c:1607 msgid "existing_enum_value" msgstr "기존_enum_값" -#: sql_help.c:1589 +#: sql_help.c:1610 msgid "property" msgstr "속성" -#: sql_help.c:1665 sql_help.c:2341 sql_help.c:2350 sql_help.c:2756 -#: sql_help.c:3254 sql_help.c:3705 sql_help.c:3911 sql_help.c:3957 -#: sql_help.c:4363 +#: sql_help.c:1686 sql_help.c:2362 sql_help.c:2371 sql_help.c:2773 +#: sql_help.c:3274 sql_help.c:3725 sql_help.c:3932 sql_help.c:3978 +#: sql_help.c:4395 msgid "server_name" msgstr "서버이름" -#: sql_help.c:1697 sql_help.c:1700 sql_help.c:3269 +#: sql_help.c:1718 sql_help.c:1721 sql_help.c:3289 msgid "view_option_name" msgstr "뷰_옵션이름" -#: sql_help.c:1698 sql_help.c:3270 +#: sql_help.c:1719 sql_help.c:3290 msgid "view_option_value" msgstr "뷰_옵션_값" -#: sql_help.c:1720 sql_help.c:1721 sql_help.c:4974 sql_help.c:4975 +#: sql_help.c:1740 sql_help.c:5007 msgid "table_and_columns" msgstr "테이블과_칼럼" -#: sql_help.c:1722 sql_help.c:1786 sql_help.c:1978 sql_help.c:3754 -#: sql_help.c:4198 sql_help.c:4976 +#: sql_help.c:1741 sql_help.c:1801 sql_help.c:1995 sql_help.c:3774 +#: sql_help.c:4230 sql_help.c:5008 msgid "where option can be one of:" msgstr "옵션 사용법:" -#: sql_help.c:1723 sql_help.c:1724 sql_help.c:1787 sql_help.c:1980 -#: sql_help.c:1984 sql_help.c:2164 sql_help.c:3755 sql_help.c:3756 -#: sql_help.c:3757 sql_help.c:3758 sql_help.c:3759 sql_help.c:3760 -#: sql_help.c:3761 sql_help.c:3762 sql_help.c:3763 sql_help.c:4199 -#: sql_help.c:4201 sql_help.c:4977 sql_help.c:4978 sql_help.c:4979 -#: sql_help.c:4980 sql_help.c:4981 sql_help.c:4982 sql_help.c:4983 -#: sql_help.c:4984 sql_help.c:4985 sql_help.c:4987 sql_help.c:4988 +#: sql_help.c:1742 sql_help.c:1743 sql_help.c:1802 sql_help.c:1997 +#: sql_help.c:2001 sql_help.c:2183 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:3777 sql_help.c:3778 sql_help.c:3779 sql_help.c:3780 +#: sql_help.c:3781 sql_help.c:3782 sql_help.c:3783 sql_help.c:3784 +#: sql_help.c:4231 sql_help.c:4233 sql_help.c:5009 sql_help.c:5010 +#: sql_help.c:5011 sql_help.c:5012 sql_help.c:5013 sql_help.c:5014 +#: sql_help.c:5015 sql_help.c:5016 sql_help.c:5017 sql_help.c:5019 +#: sql_help.c:5020 msgid "boolean" msgstr "불린" -#: sql_help.c:1725 sql_help.c:4989 +#: sql_help.c:1744 sql_help.c:5021 msgid "size" msgstr "크기" -#: sql_help.c:1726 sql_help.c:4990 +#: sql_help.c:1745 sql_help.c:5022 msgid "and table_and_columns is:" msgstr "테이블과_칼럼 사용법:" -#: sql_help.c:1742 sql_help.c:4736 sql_help.c:4738 sql_help.c:4762 +#: sql_help.c:1761 sql_help.c:4769 sql_help.c:4771 sql_help.c:4795 msgid "transaction_mode" msgstr "트랜잭션모드" -#: sql_help.c:1743 sql_help.c:4739 sql_help.c:4763 +#: sql_help.c:1762 sql_help.c:4772 sql_help.c:4796 msgid "where transaction_mode is one of:" msgstr "트랜잭션모드 사용법:" -#: sql_help.c:1752 sql_help.c:4582 sql_help.c:4591 sql_help.c:4595 -#: sql_help.c:4599 sql_help.c:4602 sql_help.c:4839 sql_help.c:4848 -#: sql_help.c:4852 sql_help.c:4856 sql_help.c:4859 sql_help.c:5085 -#: sql_help.c:5094 sql_help.c:5098 sql_help.c:5102 sql_help.c:5105 +#: sql_help.c:1771 sql_help.c:4614 sql_help.c:4623 sql_help.c:4627 +#: sql_help.c:4631 sql_help.c:4634 sql_help.c:4872 sql_help.c:4881 +#: sql_help.c:4885 sql_help.c:4889 sql_help.c:4892 sql_help.c:5117 +#: sql_help.c:5126 sql_help.c:5130 sql_help.c:5134 sql_help.c:5137 msgid "argument" msgstr "인자" -#: sql_help.c:1852 +#: sql_help.c:1867 msgid "relation_name" msgstr "릴레이션이름" -#: sql_help.c:1857 sql_help.c:3905 sql_help.c:4357 +#: sql_help.c:1872 sql_help.c:3926 sql_help.c:4389 msgid "domain_name" msgstr "도메인이름" -#: sql_help.c:1879 +#: sql_help.c:1894 msgid "policy_name" msgstr "정책이름" -#: sql_help.c:1892 +#: sql_help.c:1907 msgid "rule_name" msgstr "룰이름" -#: sql_help.c:1911 sql_help.c:4496 +#: sql_help.c:1926 sql_help.c:4528 msgid "string_literal" msgstr "문자열_리터럴" -#: sql_help.c:1936 sql_help.c:4160 sql_help.c:4410 +#: sql_help.c:1951 sql_help.c:4192 sql_help.c:4442 msgid "transaction_id" msgstr "트랜잭션_id" -#: sql_help.c:1968 sql_help.c:1975 sql_help.c:4027 +#: sql_help.c:1985 sql_help.c:1992 sql_help.c:4048 msgid "filename" msgstr "파일이름" -#: sql_help.c:1969 sql_help.c:1976 sql_help.c:2695 sql_help.c:2696 -#: sql_help.c:2697 +#: sql_help.c:1986 sql_help.c:1993 sql_help.c:2712 sql_help.c:2713 +#: sql_help.c:2714 msgid "command" msgstr "명령어" -#: sql_help.c:1971 sql_help.c:2694 sql_help.c:3124 sql_help.c:3305 -#: sql_help.c:4011 sql_help.c:4088 sql_help.c:4091 sql_help.c:4565 -#: sql_help.c:4567 sql_help.c:4668 sql_help.c:4670 sql_help.c:4822 -#: sql_help.c:4824 sql_help.c:4940 sql_help.c:5068 sql_help.c:5070 +#: sql_help.c:1988 sql_help.c:2711 sql_help.c:3144 sql_help.c:3325 +#: sql_help.c:4032 sql_help.c:4115 sql_help.c:4118 sql_help.c:4121 +#: sql_help.c:4597 sql_help.c:4599 sql_help.c:4701 sql_help.c:4703 +#: sql_help.c:4855 sql_help.c:4857 sql_help.c:4974 sql_help.c:5100 +#: sql_help.c:5102 msgid "condition" msgstr "조건" -#: sql_help.c:1974 sql_help.c:2511 sql_help.c:3007 sql_help.c:3271 -#: sql_help.c:3289 sql_help.c:3992 +#: sql_help.c:1991 sql_help.c:2532 sql_help.c:3027 sql_help.c:3291 +#: sql_help.c:3309 sql_help.c:4013 msgid "query" msgstr "쿼리문" -#: sql_help.c:1979 +#: sql_help.c:1996 msgid "format_name" msgstr "입출력양식이름" -#: sql_help.c:1981 +#: sql_help.c:1998 msgid "delimiter_character" msgstr "구분문자" -#: sql_help.c:1982 +#: sql_help.c:1999 msgid "null_string" msgstr "널문자열" -#: sql_help.c:1983 +#: sql_help.c:2000 msgid "default_string" msgstr "기본_문자열" -#: sql_help.c:1985 +#: sql_help.c:2002 msgid "quote_character" msgstr "인용부호" -#: sql_help.c:1986 +#: sql_help.c:2003 msgid "escape_character" msgstr "이스케이프 문자" -#: sql_help.c:1990 +#: sql_help.c:2007 +msgid "error_action" +msgstr "오류_동작" + +#: sql_help.c:2008 msgid "encoding_name" msgstr "인코딩이름" -#: sql_help.c:2001 +#: sql_help.c:2009 +msgid "verbosity" +msgstr "로그출력수준" + +#: sql_help.c:2020 msgid "access_method_type" msgstr "접근_방법_종류" -#: sql_help.c:2072 sql_help.c:2091 sql_help.c:2094 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2113 msgid "arg_data_type" msgstr "인자자료형" -#: sql_help.c:2073 sql_help.c:2095 sql_help.c:2103 +#: sql_help.c:2092 sql_help.c:2114 sql_help.c:2122 msgid "sfunc" msgstr "sfunc" -#: sql_help.c:2074 sql_help.c:2096 sql_help.c:2104 +#: sql_help.c:2093 sql_help.c:2115 sql_help.c:2123 msgid "state_data_type" msgstr "state_data_type" -#: sql_help.c:2075 sql_help.c:2097 sql_help.c:2105 +#: sql_help.c:2094 sql_help.c:2116 sql_help.c:2124 msgid "state_data_size" msgstr "state_data_size" -#: sql_help.c:2076 sql_help.c:2098 sql_help.c:2106 +#: sql_help.c:2095 sql_help.c:2117 sql_help.c:2125 msgid "ffunc" msgstr "ffunc" -#: sql_help.c:2077 sql_help.c:2107 +#: sql_help.c:2096 sql_help.c:2126 msgid "combinefunc" msgstr "combinefunc" -#: sql_help.c:2078 sql_help.c:2108 +#: sql_help.c:2097 sql_help.c:2127 msgid "serialfunc" msgstr "serialfunc" -#: sql_help.c:2079 sql_help.c:2109 +#: sql_help.c:2098 sql_help.c:2128 msgid "deserialfunc" msgstr "deserialfunc" -#: sql_help.c:2080 sql_help.c:2099 sql_help.c:2110 +#: sql_help.c:2099 sql_help.c:2118 sql_help.c:2129 msgid "initial_condition" msgstr "initial_condition" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2100 sql_help.c:2130 msgid "msfunc" msgstr "msfunc" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2101 sql_help.c:2131 msgid "minvfunc" msgstr "minvfunc" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2102 sql_help.c:2132 msgid "mstate_data_type" msgstr "mstate_data_type" -#: sql_help.c:2084 sql_help.c:2114 +#: sql_help.c:2103 sql_help.c:2133 msgid "mstate_data_size" msgstr "mstate_data_size" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2104 sql_help.c:2134 msgid "mffunc" msgstr "mffunc" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2105 sql_help.c:2135 msgid "minitial_condition" msgstr "minitial_condition" -#: sql_help.c:2087 sql_help.c:2117 +#: sql_help.c:2106 sql_help.c:2136 msgid "sort_operator" msgstr "정렬연산자" -#: sql_help.c:2100 +#: sql_help.c:2119 msgid "or the old syntax" msgstr "또는 옛날 구문" -#: sql_help.c:2102 +#: sql_help.c:2121 msgid "base_type" msgstr "기본자료형" -#: sql_help.c:2160 sql_help.c:2209 +#: sql_help.c:2179 sql_help.c:2229 msgid "locale" msgstr "로케일" -#: sql_help.c:2161 sql_help.c:2210 +#: sql_help.c:2180 sql_help.c:2230 msgid "lc_collate" msgstr "lc_collate" -#: sql_help.c:2162 sql_help.c:2211 +#: sql_help.c:2181 sql_help.c:2231 msgid "lc_ctype" msgstr "lc_ctype" -#: sql_help.c:2163 sql_help.c:4463 +#: sql_help.c:2182 sql_help.c:4495 msgid "provider" msgstr "제공자" -#: sql_help.c:2165 +#: sql_help.c:2184 msgid "rules" msgstr "룰" -#: sql_help.c:2166 sql_help.c:2271 +#: sql_help.c:2185 sql_help.c:2292 msgid "version" msgstr "버전" -#: sql_help.c:2168 +#: sql_help.c:2187 msgid "existing_collation" msgstr "기존_collation" -#: sql_help.c:2178 +#: sql_help.c:2197 msgid "source_encoding" msgstr "원래인코딩" -#: sql_help.c:2179 +#: sql_help.c:2198 msgid "dest_encoding" msgstr "대상인코딩" -#: sql_help.c:2206 sql_help.c:3047 +#: sql_help.c:2226 sql_help.c:3067 msgid "template" msgstr "템플릿" -#: sql_help.c:2207 +#: sql_help.c:2227 msgid "encoding" msgstr "인코딩" -#: sql_help.c:2208 +#: sql_help.c:2228 msgid "strategy" msgstr "전략번호" -#: sql_help.c:2212 +#: sql_help.c:2232 +msgid "builtin_locale" +msgstr "내장_로케일" + +#: sql_help.c:2233 msgid "icu_locale" msgstr "icu_로케일" -#: sql_help.c:2213 +#: sql_help.c:2234 msgid "icu_rules" msgstr "icu_룰" -#: sql_help.c:2214 +#: sql_help.c:2235 msgid "locale_provider" msgstr "로케일_제공자" -#: sql_help.c:2215 +#: sql_help.c:2236 msgid "collation_version" msgstr "collation_version" -#: sql_help.c:2220 +#: sql_help.c:2241 msgid "oid" msgstr "oid" -#: sql_help.c:2240 -msgid "constraint" -msgstr "제약조건" - -#: sql_help.c:2241 -msgid "where constraint is:" -msgstr "제약조건 사용법:" - -#: sql_help.c:2255 sql_help.c:2692 sql_help.c:3120 +#: sql_help.c:2276 sql_help.c:2709 sql_help.c:3140 msgid "event" msgstr "이벤트" -#: sql_help.c:2256 +#: sql_help.c:2277 msgid "filter_variable" msgstr "필터_변수" -#: sql_help.c:2257 +#: sql_help.c:2278 msgid "filter_value" msgstr "필터_값" -#: sql_help.c:2353 sql_help.c:2939 +#: sql_help.c:2374 sql_help.c:2956 msgid "where column_constraint is:" msgstr "칼럼_제약조건 사용법:" -#: sql_help.c:2398 +#: sql_help.c:2419 msgid "rettype" msgstr "rettype" -#: sql_help.c:2400 +#: sql_help.c:2421 msgid "column_type" msgstr "칼럼_자료형" -#: sql_help.c:2409 sql_help.c:2612 +#: sql_help.c:2430 sql_help.c:2633 msgid "definition" msgstr "함수정의" -#: sql_help.c:2410 sql_help.c:2613 +#: sql_help.c:2431 sql_help.c:2634 msgid "obj_file" msgstr "오브젝트파일" -#: sql_help.c:2411 sql_help.c:2614 +#: sql_help.c:2432 sql_help.c:2635 msgid "link_symbol" msgstr "연결할_함수명" -#: sql_help.c:2412 sql_help.c:2615 +#: sql_help.c:2433 sql_help.c:2636 msgid "sql_body" msgstr "sql_본문" -#: sql_help.c:2450 sql_help.c:2677 sql_help.c:3243 +#: sql_help.c:2471 sql_help.c:2694 sql_help.c:3263 msgid "uid" msgstr "uid" -#: sql_help.c:2466 sql_help.c:2507 sql_help.c:2908 sql_help.c:2921 -#: sql_help.c:2935 sql_help.c:3003 +#: sql_help.c:2487 sql_help.c:2528 sql_help.c:2925 sql_help.c:2938 +#: sql_help.c:2952 sql_help.c:3023 msgid "method" msgstr "색인방법" -#: sql_help.c:2471 -msgid "opclass_parameter" -msgstr "opclass_매개변수" - -#: sql_help.c:2488 +#: sql_help.c:2509 msgid "call_handler" msgstr "호출_핸들러" -#: sql_help.c:2489 +#: sql_help.c:2510 msgid "inline_handler" msgstr "인라인_핸들러" -#: sql_help.c:2490 +#: sql_help.c:2511 msgid "valfunction" msgstr "구문검사함수" -#: sql_help.c:2529 -msgid "com_op" -msgstr "com_op" - -#: sql_help.c:2530 -msgid "neg_op" -msgstr "neg_op" - -#: sql_help.c:2548 +#: sql_help.c:2569 msgid "family_name" msgstr "family_name" -#: sql_help.c:2559 +#: sql_help.c:2580 msgid "storage_type" msgstr "스토리지_유형" -#: sql_help.c:2698 sql_help.c:3127 +#: sql_help.c:2715 sql_help.c:3147 msgid "where event can be one of:" msgstr "이벤트 사용법:" -#: sql_help.c:2718 sql_help.c:2720 +#: sql_help.c:2735 sql_help.c:2737 msgid "schema_element" msgstr "스키마_요소" -#: sql_help.c:2757 +#: sql_help.c:2774 msgid "server_type" msgstr "서버_종류" -#: sql_help.c:2758 +#: sql_help.c:2775 msgid "server_version" msgstr "서버_버전" -#: sql_help.c:2759 sql_help.c:3908 sql_help.c:4360 +#: sql_help.c:2776 sql_help.c:3929 sql_help.c:4392 msgid "fdw_name" msgstr "fdw_이름" -#: sql_help.c:2776 sql_help.c:2779 +#: sql_help.c:2793 sql_help.c:2796 msgid "statistics_name" msgstr "통계정보_이름" -#: sql_help.c:2780 +#: sql_help.c:2797 msgid "statistics_kind" msgstr "통계정보_종류" -#: sql_help.c:2796 +#: sql_help.c:2813 msgid "subscription_name" msgstr "구독_이름" -#: sql_help.c:2901 +#: sql_help.c:2918 msgid "source_table" msgstr "원본테이블" -#: sql_help.c:2902 +#: sql_help.c:2919 msgid "like_option" msgstr "LIKE구문옵션" -#: sql_help.c:2968 +#: sql_help.c:2985 msgid "and like_option is:" msgstr "LIKE구문옵션 사용법:" -#: sql_help.c:3020 +#: sql_help.c:3040 msgid "directory" msgstr "디렉터리" -#: sql_help.c:3034 +#: sql_help.c:3054 msgid "parser_name" msgstr "구문분석기_이름" -#: sql_help.c:3035 +#: sql_help.c:3055 msgid "source_config" msgstr "원본_설정" -#: sql_help.c:3064 +#: sql_help.c:3084 msgid "start_function" msgstr "시작_함수" -#: sql_help.c:3065 +#: sql_help.c:3085 msgid "gettoken_function" msgstr "gettoken함수" -#: sql_help.c:3066 +#: sql_help.c:3086 msgid "end_function" msgstr "종료_함수" -#: sql_help.c:3067 +#: sql_help.c:3087 msgid "lextypes_function" msgstr "lextypes함수" -#: sql_help.c:3068 +#: sql_help.c:3088 msgid "headline_function" msgstr "headline함수" -#: sql_help.c:3080 +#: sql_help.c:3100 msgid "init_function" msgstr "init함수" -#: sql_help.c:3081 +#: sql_help.c:3101 msgid "lexize_function" msgstr "lexize함수" -#: sql_help.c:3094 +#: sql_help.c:3114 msgid "from_sql_function_name" msgstr "sql에서_언어로_바꿀때쓸_함수이름" -#: sql_help.c:3096 +#: sql_help.c:3116 msgid "to_sql_function_name" msgstr "언어에서_sql로_바꿀때쓸_함수이름" -#: sql_help.c:3122 +#: sql_help.c:3142 msgid "referenced_table_name" msgstr "참조된_테이블_이름" -#: sql_help.c:3123 +#: sql_help.c:3143 msgid "transition_relation_name" msgstr "전달_릴레이션_이름" -#: sql_help.c:3126 +#: sql_help.c:3146 msgid "arguments" msgstr "인자들" -#: sql_help.c:3178 +#: sql_help.c:3198 msgid "label" msgstr "enum요소" -#: sql_help.c:3180 +#: sql_help.c:3200 msgid "subtype" msgstr "subtype" -#: sql_help.c:3181 +#: sql_help.c:3201 msgid "subtype_operator_class" msgstr "subtype_operator_class" -#: sql_help.c:3183 +#: sql_help.c:3203 msgid "canonical_function" msgstr "canonical_function" -#: sql_help.c:3184 +#: sql_help.c:3204 msgid "subtype_diff_function" msgstr "subtype_diff_function" -#: sql_help.c:3185 +#: sql_help.c:3205 msgid "multirange_type_name" msgstr "다중범위_자료형_이름" -#: sql_help.c:3187 +#: sql_help.c:3207 msgid "input_function" msgstr "입력함수" -#: sql_help.c:3188 +#: sql_help.c:3208 msgid "output_function" msgstr "출력함수" -#: sql_help.c:3189 +#: sql_help.c:3209 msgid "receive_function" msgstr "받는함수" -#: sql_help.c:3190 +#: sql_help.c:3210 msgid "send_function" msgstr "주는함수" -#: sql_help.c:3191 +#: sql_help.c:3211 msgid "type_modifier_input_function" msgstr "type_modifier_input_function" -#: sql_help.c:3192 +#: sql_help.c:3212 msgid "type_modifier_output_function" msgstr "type_modifier_output_function" -#: sql_help.c:3193 +#: sql_help.c:3213 msgid "analyze_function" msgstr "분석함수" -#: sql_help.c:3194 +#: sql_help.c:3214 msgid "subscript_function" msgstr "구독_함수" -#: sql_help.c:3195 +#: sql_help.c:3215 msgid "internallength" msgstr "내부길이" -#: sql_help.c:3196 +#: sql_help.c:3216 msgid "alignment" msgstr "정렬" -#: sql_help.c:3197 +#: sql_help.c:3217 msgid "storage" msgstr "스토리지" -#: sql_help.c:3198 +#: sql_help.c:3218 msgid "like_type" msgstr "like_type" -#: sql_help.c:3199 +#: sql_help.c:3219 msgid "category" msgstr "category" -#: sql_help.c:3200 +#: sql_help.c:3220 msgid "preferred" msgstr "preferred" -#: sql_help.c:3201 +#: sql_help.c:3221 msgid "default" msgstr "기본값" -#: sql_help.c:3202 +#: sql_help.c:3222 msgid "element" msgstr "요소" -#: sql_help.c:3203 +#: sql_help.c:3223 msgid "delimiter" msgstr "구분자" -#: sql_help.c:3204 +#: sql_help.c:3224 msgid "collatable" msgstr "collatable" -#: sql_help.c:3301 sql_help.c:3987 sql_help.c:4077 sql_help.c:4560 -#: sql_help.c:4662 sql_help.c:4817 sql_help.c:4930 sql_help.c:5063 +#: sql_help.c:3321 sql_help.c:4008 sql_help.c:4102 sql_help.c:4592 +#: sql_help.c:4695 sql_help.c:4850 sql_help.c:4964 sql_help.c:5095 msgid "with_query" msgstr "with절_쿼리" -#: sql_help.c:3303 sql_help.c:3989 sql_help.c:4579 sql_help.c:4585 -#: sql_help.c:4588 sql_help.c:4592 sql_help.c:4596 sql_help.c:4604 -#: sql_help.c:4836 sql_help.c:4842 sql_help.c:4845 sql_help.c:4849 -#: sql_help.c:4853 sql_help.c:4861 sql_help.c:4932 sql_help.c:5082 -#: sql_help.c:5088 sql_help.c:5091 sql_help.c:5095 sql_help.c:5099 -#: sql_help.c:5107 +#: sql_help.c:3323 sql_help.c:4010 sql_help.c:4611 sql_help.c:4617 +#: sql_help.c:4620 sql_help.c:4624 sql_help.c:4628 sql_help.c:4636 +#: sql_help.c:4869 sql_help.c:4875 sql_help.c:4878 sql_help.c:4882 +#: sql_help.c:4886 sql_help.c:4894 sql_help.c:4966 sql_help.c:5114 +#: sql_help.c:5120 sql_help.c:5123 sql_help.c:5127 sql_help.c:5131 +#: sql_help.c:5139 msgid "alias" msgstr "별칭" -#: sql_help.c:3304 sql_help.c:4564 sql_help.c:4606 sql_help.c:4608 -#: sql_help.c:4612 sql_help.c:4614 sql_help.c:4615 sql_help.c:4616 -#: sql_help.c:4667 sql_help.c:4821 sql_help.c:4863 sql_help.c:4865 -#: sql_help.c:4869 sql_help.c:4871 sql_help.c:4872 sql_help.c:4873 -#: sql_help.c:4939 sql_help.c:5067 sql_help.c:5109 sql_help.c:5111 -#: sql_help.c:5115 sql_help.c:5117 sql_help.c:5118 sql_help.c:5119 +#: sql_help.c:3324 sql_help.c:4596 sql_help.c:4638 sql_help.c:4640 +#: sql_help.c:4644 sql_help.c:4646 sql_help.c:4647 sql_help.c:4648 +#: sql_help.c:4700 sql_help.c:4854 sql_help.c:4896 sql_help.c:4898 +#: sql_help.c:4902 sql_help.c:4904 sql_help.c:4905 sql_help.c:4906 +#: sql_help.c:4973 sql_help.c:5099 sql_help.c:5141 sql_help.c:5143 +#: sql_help.c:5147 sql_help.c:5149 sql_help.c:5150 sql_help.c:5151 msgid "from_item" msgstr "from절_항목" -#: sql_help.c:3306 sql_help.c:3789 sql_help.c:4127 sql_help.c:4941 +#: sql_help.c:3326 sql_help.c:3810 sql_help.c:4159 sql_help.c:4975 msgid "cursor_name" msgstr "커서이름" -#: sql_help.c:3307 sql_help.c:3995 sql_help.c:4942 +#: sql_help.c:3327 sql_help.c:4016 sql_help.c:4108 sql_help.c:4976 msgid "output_expression" msgstr "출력표현식" -#: sql_help.c:3308 sql_help.c:3996 sql_help.c:4563 sql_help.c:4665 -#: sql_help.c:4820 sql_help.c:4943 sql_help.c:5066 +#: sql_help.c:3328 sql_help.c:4017 sql_help.c:4109 sql_help.c:4595 +#: sql_help.c:4698 sql_help.c:4853 sql_help.c:4977 sql_help.c:5098 msgid "output_name" msgstr "출력_이름" -#: sql_help.c:3324 +#: sql_help.c:3344 msgid "code" msgstr "코드" -#: sql_help.c:3729 +#: sql_help.c:3749 msgid "parameter" msgstr "매개변수" -#: sql_help.c:3752 sql_help.c:3753 sql_help.c:4152 +#: sql_help.c:3773 sql_help.c:4184 msgid "statement" msgstr "명령구문" -#: sql_help.c:3788 sql_help.c:4126 +#: sql_help.c:3809 sql_help.c:4158 msgid "direction" msgstr "방향" -#: sql_help.c:3790 sql_help.c:4128 +#: sql_help.c:3811 sql_help.c:4160 msgid "where direction can be one of:" msgstr "방향 사용법:" -#: sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 sql_help.c:3794 -#: sql_help.c:3795 sql_help.c:4129 sql_help.c:4130 sql_help.c:4131 -#: sql_help.c:4132 sql_help.c:4133 sql_help.c:4573 sql_help.c:4575 -#: sql_help.c:4676 sql_help.c:4678 sql_help.c:4830 sql_help.c:4832 -#: sql_help.c:5007 sql_help.c:5009 sql_help.c:5076 sql_help.c:5078 +#: sql_help.c:3812 sql_help.c:3813 sql_help.c:3814 sql_help.c:3815 +#: sql_help.c:3816 sql_help.c:4161 sql_help.c:4162 sql_help.c:4163 +#: sql_help.c:4164 sql_help.c:4165 sql_help.c:4605 sql_help.c:4607 +#: sql_help.c:4709 sql_help.c:4711 sql_help.c:4863 sql_help.c:4865 +#: sql_help.c:5039 sql_help.c:5041 sql_help.c:5108 sql_help.c:5110 msgid "count" msgstr "출력개수" -#: sql_help.c:3898 sql_help.c:4350 +#: sql_help.c:3919 sql_help.c:4382 msgid "sequence_name" msgstr "시퀀스이름" -#: sql_help.c:3916 sql_help.c:4368 +#: sql_help.c:3937 sql_help.c:4400 msgid "arg_name" msgstr "인자이름" -#: sql_help.c:3917 sql_help.c:4369 +#: sql_help.c:3938 sql_help.c:4401 msgid "arg_type" msgstr "인자자료형" -#: sql_help.c:3924 sql_help.c:4376 +#: sql_help.c:3945 sql_help.c:4408 msgid "loid" msgstr "큰개체_oid" -#: sql_help.c:3955 +#: sql_help.c:3976 msgid "remote_schema" msgstr "원격_스키마" -#: sql_help.c:3958 +#: sql_help.c:3979 msgid "local_schema" msgstr "로컬_스키마" -#: sql_help.c:3993 +#: sql_help.c:4014 msgid "conflict_target" msgstr "충돌_대상" -#: sql_help.c:3994 +#: sql_help.c:4015 msgid "conflict_action" msgstr "충돌_작업" -#: sql_help.c:3997 +#: sql_help.c:4018 msgid "where conflict_target can be one of:" msgstr "충돌_대상 사용법:" -#: sql_help.c:3998 +#: sql_help.c:4019 msgid "index_column_name" msgstr "인덱스칼럼이름" -#: sql_help.c:3999 +#: sql_help.c:4020 msgid "index_expression" msgstr "인덱스표현식" -#: sql_help.c:4002 +#: sql_help.c:4023 msgid "index_predicate" msgstr "부분인덱스식" -#: sql_help.c:4004 +#: sql_help.c:4025 msgid "and conflict_action is one of:" msgstr "충돌_작업 사용법:" -#: sql_help.c:4010 sql_help.c:4938 +#: sql_help.c:4031 sql_help.c:4132 sql_help.c:4972 msgid "sub-SELECT" msgstr "서브셀렉트" -#: sql_help.c:4019 sql_help.c:4141 sql_help.c:4914 +#: sql_help.c:4040 sql_help.c:4173 sql_help.c:4948 msgid "channel" msgstr "채널" -#: sql_help.c:4041 +#: sql_help.c:4062 msgid "lockmode" msgstr "잠금모드" -#: sql_help.c:4042 +#: sql_help.c:4063 msgid "where lockmode is one of:" msgstr "잠금모드 사용법:" -#: sql_help.c:4078 +#: sql_help.c:4103 msgid "target_table_name" msgstr "대상_테이블_이름" -#: sql_help.c:4079 +#: sql_help.c:4104 msgid "target_alias" msgstr "대상_별칭" -#: sql_help.c:4080 +#: sql_help.c:4105 msgid "data_source" msgstr "데이터_소스" -#: sql_help.c:4081 sql_help.c:4609 sql_help.c:4866 sql_help.c:5112 +#: sql_help.c:4106 sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "join_condition" msgstr "조인_조건" -#: sql_help.c:4082 +#: sql_help.c:4107 msgid "when_clause" msgstr "when절" -#: sql_help.c:4083 +#: sql_help.c:4110 msgid "where data_source is:" msgstr "데이터_소스 사용법:" -#: sql_help.c:4084 +#: sql_help.c:4111 msgid "source_table_name" msgstr "원본_테이블_이름" -#: sql_help.c:4085 +#: sql_help.c:4112 msgid "source_query" msgstr "소스_쿼리" -#: sql_help.c:4086 +#: sql_help.c:4113 msgid "source_alias" msgstr "소스_별칭" -#: sql_help.c:4087 +#: sql_help.c:4114 msgid "and when_clause is:" msgstr "when절 사용법:" -#: sql_help.c:4089 +#: sql_help.c:4116 sql_help.c:4119 msgid "merge_update" msgstr "merge_update" -#: sql_help.c:4090 +#: sql_help.c:4117 sql_help.c:4120 msgid "merge_delete" msgstr "merge_delete" -#: sql_help.c:4092 +#: sql_help.c:4122 msgid "merge_insert" msgstr "merge_insert" -#: sql_help.c:4093 +#: sql_help.c:4123 msgid "and merge_insert is:" msgstr "merge_insert 사용법:" -#: sql_help.c:4096 +#: sql_help.c:4126 msgid "and merge_update is:" msgstr "merge_update 사용법:" -#: sql_help.c:4101 +#: sql_help.c:4133 msgid "and merge_delete is:" msgstr "merge_delete 사용법:" -#: sql_help.c:4142 +#: sql_help.c:4174 msgid "payload" msgstr "payload" -#: sql_help.c:4169 +#: sql_help.c:4201 msgid "old_role" msgstr "기존롤" -#: sql_help.c:4170 +#: sql_help.c:4202 msgid "new_role" msgstr "새롤" -#: sql_help.c:4209 sql_help.c:4418 sql_help.c:4426 +#: sql_help.c:4241 sql_help.c:4450 sql_help.c:4458 msgid "savepoint_name" msgstr "savepoint_name" -#: sql_help.c:4566 sql_help.c:4624 sql_help.c:4823 sql_help.c:4881 -#: sql_help.c:5069 sql_help.c:5127 +#: sql_help.c:4598 sql_help.c:4656 sql_help.c:4856 sql_help.c:4914 +#: sql_help.c:5101 sql_help.c:5159 msgid "grouping_element" msgstr "grouping_element" -#: sql_help.c:4568 sql_help.c:4671 sql_help.c:4825 sql_help.c:5071 +#: sql_help.c:4600 sql_help.c:4704 sql_help.c:4858 sql_help.c:5103 msgid "window_name" msgstr "윈도우이름" -#: sql_help.c:4569 sql_help.c:4672 sql_help.c:4826 sql_help.c:5072 +#: sql_help.c:4601 sql_help.c:4705 sql_help.c:4859 sql_help.c:5104 msgid "window_definition" msgstr "원도우정의" -#: sql_help.c:4570 sql_help.c:4584 sql_help.c:4628 sql_help.c:4673 -#: sql_help.c:4827 sql_help.c:4841 sql_help.c:4885 sql_help.c:5073 -#: sql_help.c:5087 sql_help.c:5131 +#: sql_help.c:4602 sql_help.c:4616 sql_help.c:4660 sql_help.c:4706 +#: sql_help.c:4860 sql_help.c:4874 sql_help.c:4918 sql_help.c:5105 +#: sql_help.c:5119 sql_help.c:5163 msgid "select" msgstr "select" -#: sql_help.c:4577 sql_help.c:4834 sql_help.c:5080 +#: sql_help.c:4608 sql_help.c:4866 sql_help.c:5111 +msgid "from_reference" +msgstr "from_reference" + +#: sql_help.c:4609 sql_help.c:4867 sql_help.c:5112 msgid "where from_item can be one of:" msgstr "from절_항목 사용법:" -#: sql_help.c:4580 sql_help.c:4586 sql_help.c:4589 sql_help.c:4593 -#: sql_help.c:4605 sql_help.c:4837 sql_help.c:4843 sql_help.c:4846 -#: sql_help.c:4850 sql_help.c:4862 sql_help.c:5083 sql_help.c:5089 -#: sql_help.c:5092 sql_help.c:5096 sql_help.c:5108 +#: sql_help.c:4612 sql_help.c:4618 sql_help.c:4621 sql_help.c:4625 +#: sql_help.c:4637 sql_help.c:4870 sql_help.c:4876 sql_help.c:4879 +#: sql_help.c:4883 sql_help.c:4895 sql_help.c:5115 sql_help.c:5121 +#: sql_help.c:5124 sql_help.c:5128 sql_help.c:5140 msgid "column_alias" msgstr "칼럼별칭" -#: sql_help.c:4581 sql_help.c:4838 sql_help.c:5084 +#: sql_help.c:4613 sql_help.c:4871 sql_help.c:5116 msgid "sampling_method" msgstr "표본추출방법" -#: sql_help.c:4583 sql_help.c:4840 sql_help.c:5086 +#: sql_help.c:4615 sql_help.c:4873 sql_help.c:5118 msgid "seed" msgstr "seed" -#: sql_help.c:4587 sql_help.c:4626 sql_help.c:4844 sql_help.c:4883 -#: sql_help.c:5090 sql_help.c:5129 +#: sql_help.c:4619 sql_help.c:4658 sql_help.c:4877 sql_help.c:4916 +#: sql_help.c:5122 sql_help.c:5161 msgid "with_query_name" msgstr "with절_쿼리_이름" -#: sql_help.c:4597 sql_help.c:4600 sql_help.c:4603 sql_help.c:4854 -#: sql_help.c:4857 sql_help.c:4860 sql_help.c:5100 sql_help.c:5103 -#: sql_help.c:5106 +#: sql_help.c:4629 sql_help.c:4632 sql_help.c:4635 sql_help.c:4887 +#: sql_help.c:4890 sql_help.c:4893 sql_help.c:5132 sql_help.c:5135 +#: sql_help.c:5138 msgid "column_definition" msgstr "칼럼정의" -#: sql_help.c:4607 sql_help.c:4613 sql_help.c:4864 sql_help.c:4870 -#: sql_help.c:5110 sql_help.c:5116 +#: sql_help.c:4639 sql_help.c:4645 sql_help.c:4897 sql_help.c:4903 +#: sql_help.c:5142 sql_help.c:5148 msgid "join_type" msgstr "조인_종류" -#: sql_help.c:4610 sql_help.c:4867 sql_help.c:5113 +#: sql_help.c:4642 sql_help.c:4900 sql_help.c:5145 msgid "join_column" msgstr "조인_칼럼" -#: sql_help.c:4611 sql_help.c:4868 sql_help.c:5114 +#: sql_help.c:4643 sql_help.c:4901 sql_help.c:5146 msgid "join_using_alias" msgstr "조인_별칭" -#: sql_help.c:4617 sql_help.c:4874 sql_help.c:5120 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and grouping_element can be one of:" msgstr "grouping_element 사용법:" -#: sql_help.c:4625 sql_help.c:4882 sql_help.c:5128 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 msgid "and with_query is:" msgstr "with절_쿼리 사용법:" -#: sql_help.c:4629 sql_help.c:4886 sql_help.c:5132 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "values" msgstr "값" -#: sql_help.c:4630 sql_help.c:4887 sql_help.c:5133 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "insert" msgstr "insert" -#: sql_help.c:4631 sql_help.c:4888 sql_help.c:5134 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "update" msgstr "update" -#: sql_help.c:4632 sql_help.c:4889 sql_help.c:5135 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "delete" msgstr "delete" -#: sql_help.c:4634 sql_help.c:4891 sql_help.c:5137 +#: sql_help.c:4665 sql_help.c:4923 sql_help.c:5168 +msgid "merge" +msgstr "merge" + +#: sql_help.c:4667 sql_help.c:4925 sql_help.c:5170 msgid "search_seq_col_name" msgstr "search_seq_col_name" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4669 sql_help.c:4927 sql_help.c:5172 msgid "cycle_mark_col_name" msgstr "cycle_mark_col_name" -#: sql_help.c:4637 sql_help.c:4894 sql_help.c:5140 +#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 msgid "cycle_mark_value" msgstr "cycle_mark_value" -#: sql_help.c:4638 sql_help.c:4895 sql_help.c:5141 +#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 msgid "cycle_mark_default" msgstr "cycle_mark_default" -#: sql_help.c:4639 sql_help.c:4896 sql_help.c:5142 +#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 msgid "cycle_path_col_name" msgstr "cycle_path_col_name" -#: sql_help.c:4666 +#: sql_help.c:4699 msgid "new_table" msgstr "새테이블" -#: sql_help.c:4737 +#: sql_help.c:4770 msgid "snapshot_id" msgstr "스냅샷_id" -#: sql_help.c:5005 +#: sql_help.c:5037 msgid "sort_expression" msgstr "정렬_표현식" -#: sql_help.c:5149 sql_help.c:6133 +#: sql_help.c:5182 sql_help.c:6166 msgid "abort the current transaction" msgstr "현재 트랜잭션 중지함" -#: sql_help.c:5155 +#: sql_help.c:5188 msgid "change the definition of an aggregate function" msgstr "집계함수 정보 바꾸기" -#: sql_help.c:5161 +#: sql_help.c:5194 msgid "change the definition of a collation" msgstr "collation 정의 바꾸기" -#: sql_help.c:5167 +#: sql_help.c:5200 msgid "change the definition of a conversion" msgstr "문자코드 변환규칙(conversion) 정보 바꾸기" -#: sql_help.c:5173 +#: sql_help.c:5206 msgid "change a database" msgstr "데이터베이스 변경" -#: sql_help.c:5179 +#: sql_help.c:5212 msgid "define default access privileges" msgstr "기본 접근 권한 정의" -#: sql_help.c:5185 +#: sql_help.c:5218 msgid "change the definition of a domain" msgstr "도메인 정보 바꾸기" -#: sql_help.c:5191 +#: sql_help.c:5224 msgid "change the definition of an event trigger" msgstr "트리거 정보 바꾸기" -#: sql_help.c:5197 +#: sql_help.c:5230 msgid "change the definition of an extension" msgstr "확장모듈 정의 바꾸기" -#: sql_help.c:5203 +#: sql_help.c:5236 msgid "change the definition of a foreign-data wrapper" msgstr "외부 데이터 래퍼 정의 바꾸기" -#: sql_help.c:5209 +#: sql_help.c:5242 msgid "change the definition of a foreign table" msgstr "외부 테이블 정의 바꾸기" -#: sql_help.c:5215 +#: sql_help.c:5248 msgid "change the definition of a function" msgstr "함수 정보 바꾸기" -#: sql_help.c:5221 +#: sql_help.c:5254 msgid "change role name or membership" msgstr "롤 이름이나 맴버쉽 바꾸기" -#: sql_help.c:5227 +#: sql_help.c:5260 msgid "change the definition of an index" msgstr "인덱스 정의 바꾸기" -#: sql_help.c:5233 +#: sql_help.c:5266 msgid "change the definition of a procedural language" msgstr "procedural language 정보 바꾸기" -#: sql_help.c:5239 +#: sql_help.c:5272 msgid "change the definition of a large object" msgstr "대형 객체 정의 바꾸기" -#: sql_help.c:5245 +#: sql_help.c:5278 msgid "change the definition of a materialized view" msgstr "materialized 뷰 정의 바꾸기" -#: sql_help.c:5251 +#: sql_help.c:5284 msgid "change the definition of an operator" msgstr "연산자 정의 바꾸기" -#: sql_help.c:5257 +#: sql_help.c:5290 msgid "change the definition of an operator class" msgstr "연산자 클래스 정보 바꾸기" -#: sql_help.c:5263 +#: sql_help.c:5296 msgid "change the definition of an operator family" msgstr "연산자 부류의 정의 바꾸기" -#: sql_help.c:5269 +#: sql_help.c:5302 msgid "change the definition of a row-level security policy" msgstr "로우 단위 보안 정책의 정의 바꾸기" -#: sql_help.c:5275 +#: sql_help.c:5308 msgid "change the definition of a procedure" msgstr "프로시져 정의 바꾸기" -#: sql_help.c:5281 +#: sql_help.c:5314 msgid "change the definition of a publication" msgstr "발행 정보 바꾸기" -#: sql_help.c:5287 sql_help.c:5389 +#: sql_help.c:5320 sql_help.c:5422 msgid "change a database role" msgstr "데이터베이스 롤 변경" -#: sql_help.c:5293 +#: sql_help.c:5326 msgid "change the definition of a routine" msgstr "루틴 정의 바꾸기" -#: sql_help.c:5299 +#: sql_help.c:5332 msgid "change the definition of a rule" msgstr "룰 정의 바꾸기" -#: sql_help.c:5305 +#: sql_help.c:5338 msgid "change the definition of a schema" msgstr "스키마 이름 바꾸기" -#: sql_help.c:5311 +#: sql_help.c:5344 msgid "change the definition of a sequence generator" msgstr "시퀀스 정보 바꾸기" -#: sql_help.c:5317 +#: sql_help.c:5350 msgid "change the definition of a foreign server" msgstr "외부 서버 정의 바꾸기" -#: sql_help.c:5323 +#: sql_help.c:5356 msgid "change the definition of an extended statistics object" msgstr "확장 통계정보 객체 정의 바꾸기" -#: sql_help.c:5329 +#: sql_help.c:5362 msgid "change the definition of a subscription" msgstr "구독 정보 바꾸기" -#: sql_help.c:5335 +#: sql_help.c:5368 msgid "change a server configuration parameter" msgstr "서버 환경 설정 매개 변수 바꾸기" -#: sql_help.c:5341 +#: sql_help.c:5374 msgid "change the definition of a table" msgstr "테이블 정보 바꾸기" -#: sql_help.c:5347 +#: sql_help.c:5380 msgid "change the definition of a tablespace" msgstr "테이블스페이스 정의 바꾸기" -#: sql_help.c:5353 +#: sql_help.c:5386 msgid "change the definition of a text search configuration" msgstr "텍스트 검색 구성 정의 바꾸기" -#: sql_help.c:5359 +#: sql_help.c:5392 msgid "change the definition of a text search dictionary" msgstr "텍스트 검색 사전 정의 바꾸기" -#: sql_help.c:5365 +#: sql_help.c:5398 msgid "change the definition of a text search parser" msgstr "텍스트 검색 파서 정의 바꾸기" -#: sql_help.c:5371 +#: sql_help.c:5404 msgid "change the definition of a text search template" msgstr "텍스트 검색 템플릿 정의 바꾸기" -#: sql_help.c:5377 +#: sql_help.c:5410 msgid "change the definition of a trigger" msgstr "트리거 정보 바꾸기" -#: sql_help.c:5383 +#: sql_help.c:5416 msgid "change the definition of a type" msgstr "자료형 정의 바꾸기" -#: sql_help.c:5395 +#: sql_help.c:5428 msgid "change the definition of a user mapping" msgstr "사용자 매핑 정의 바꾸기" -#: sql_help.c:5401 +#: sql_help.c:5434 msgid "change the definition of a view" msgstr "뷰 정의 바꾸기" -#: sql_help.c:5407 +#: sql_help.c:5440 msgid "collect statistics about a database" msgstr "데이터베이스 사용 통계 정보를 갱신함" -#: sql_help.c:5413 sql_help.c:6211 +#: sql_help.c:5446 sql_help.c:6244 msgid "start a transaction block" msgstr "트랜잭션 블럭을 시작함" -#: sql_help.c:5419 +#: sql_help.c:5452 msgid "invoke a procedure" msgstr "프로시져 호출" -#: sql_help.c:5425 +#: sql_help.c:5458 msgid "force a write-ahead log checkpoint" msgstr "트랜잭션 로그를 강제로 체크포인트 함" -#: sql_help.c:5431 +#: sql_help.c:5464 msgid "close a cursor" msgstr "커서 닫기" -#: sql_help.c:5437 +#: sql_help.c:5470 msgid "cluster a table according to an index" msgstr "지정한 인덱스 기준으로 테이블 자료를 다시 저장함" -#: sql_help.c:5443 +#: sql_help.c:5476 msgid "define or change the comment of an object" msgstr "해당 개체의 코멘트를 지정하거나 수정함" -#: sql_help.c:5449 sql_help.c:6007 +#: sql_help.c:5482 sql_help.c:6040 msgid "commit the current transaction" msgstr "현재 트랜잭션 commit" -#: sql_help.c:5455 +#: sql_help.c:5488 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "two-phase 커밋을 위해 먼저 준비된 트랜잭션을 커밋하세요." -#: sql_help.c:5461 +#: sql_help.c:5494 msgid "copy data between a file and a table" msgstr "테이블과 파일 사이 자료를 복사함" -#: sql_help.c:5467 +#: sql_help.c:5500 msgid "define a new access method" msgstr "새 접속 방법 정의" -#: sql_help.c:5473 +#: sql_help.c:5506 msgid "define a new aggregate function" msgstr "새 집계합수 만들기" -#: sql_help.c:5479 +#: sql_help.c:5512 msgid "define a new cast" msgstr "새 형변환자 만들기" -#: sql_help.c:5485 +#: sql_help.c:5518 msgid "define a new collation" msgstr "새 collation 만들기" -#: sql_help.c:5491 +#: sql_help.c:5524 msgid "define a new encoding conversion" msgstr "새 문자코드변환규칙(conversion) 만들기" -#: sql_help.c:5497 +#: sql_help.c:5530 msgid "create a new database" msgstr "데이터베이스 생성" -#: sql_help.c:5503 +#: sql_help.c:5536 msgid "define a new domain" msgstr "새 도메인 만들기" -#: sql_help.c:5509 +#: sql_help.c:5542 msgid "define a new event trigger" msgstr "새 이벤트 트리거 만들기" -#: sql_help.c:5515 +#: sql_help.c:5548 msgid "install an extension" msgstr "확장 모듈 설치" -#: sql_help.c:5521 +#: sql_help.c:5554 msgid "define a new foreign-data wrapper" msgstr "새 외부 데이터 래퍼 정의" -#: sql_help.c:5527 +#: sql_help.c:5560 msgid "define a new foreign table" msgstr "새 외부 테이블 정의" -#: sql_help.c:5533 +#: sql_help.c:5566 msgid "define a new function" msgstr "새 함수 만들기" -#: sql_help.c:5539 sql_help.c:5599 sql_help.c:5701 +#: sql_help.c:5572 sql_help.c:5632 sql_help.c:5734 msgid "define a new database role" msgstr "새 데이터베이스 롤 만들기" -#: sql_help.c:5545 +#: sql_help.c:5578 msgid "define a new index" msgstr "새 인덱스 만들기" -#: sql_help.c:5551 +#: sql_help.c:5584 msgid "define a new procedural language" msgstr "새 프로시주얼 언어 만들기" -#: sql_help.c:5557 +#: sql_help.c:5590 msgid "define a new materialized view" msgstr "새 materialized 뷰 만들기" -#: sql_help.c:5563 +#: sql_help.c:5596 msgid "define a new operator" msgstr "새 연산자 만들기" -#: sql_help.c:5569 +#: sql_help.c:5602 msgid "define a new operator class" msgstr "새 연잔자 클래스 만들기" -#: sql_help.c:5575 +#: sql_help.c:5608 msgid "define a new operator family" msgstr "새 연산자 부류 만들기" -#: sql_help.c:5581 +#: sql_help.c:5614 msgid "define a new row-level security policy for a table" msgstr "특정 테이블에 로우 단위 보안 정책 정의" -#: sql_help.c:5587 +#: sql_help.c:5620 msgid "define a new procedure" msgstr "새 프로시져 만들기" -#: sql_help.c:5593 +#: sql_help.c:5626 msgid "define a new publication" msgstr "새 발행 만들기" -#: sql_help.c:5605 +#: sql_help.c:5638 msgid "define a new rewrite rule" msgstr "새 룰(rule) 만들기" -#: sql_help.c:5611 +#: sql_help.c:5644 msgid "define a new schema" msgstr "새 스키마(schema) 만들기" -#: sql_help.c:5617 +#: sql_help.c:5650 msgid "define a new sequence generator" msgstr "새 시퀀스 만들기" -#: sql_help.c:5623 +#: sql_help.c:5656 msgid "define a new foreign server" msgstr "새 외부 서버 정의" -#: sql_help.c:5629 +#: sql_help.c:5662 msgid "define extended statistics" msgstr "새 확장 통계정보 만들기" -#: sql_help.c:5635 +#: sql_help.c:5668 msgid "define a new subscription" msgstr "새 구독 만들기" -#: sql_help.c:5641 +#: sql_help.c:5674 msgid "define a new table" msgstr "새 테이블 만들기" -#: sql_help.c:5647 sql_help.c:6169 +#: sql_help.c:5680 sql_help.c:6202 msgid "define a new table from the results of a query" msgstr "쿼리 결과를 새 테이블로 만들기" -#: sql_help.c:5653 +#: sql_help.c:5686 msgid "define a new tablespace" msgstr "새 테이블스페이스 만들기" -#: sql_help.c:5659 +#: sql_help.c:5692 msgid "define a new text search configuration" msgstr "새 텍스트 검색 구성 정의" -#: sql_help.c:5665 +#: sql_help.c:5698 msgid "define a new text search dictionary" msgstr "새 텍스트 검색 사전 정의" -#: sql_help.c:5671 +#: sql_help.c:5704 msgid "define a new text search parser" msgstr "새 텍스트 검색 파서 정의" -#: sql_help.c:5677 +#: sql_help.c:5710 msgid "define a new text search template" msgstr "새 텍스트 검색 템플릿 정의" -#: sql_help.c:5683 +#: sql_help.c:5716 msgid "define a new transform" msgstr "새 transform 만들기" -#: sql_help.c:5689 +#: sql_help.c:5722 msgid "define a new trigger" msgstr "새 트리거 만들기" -#: sql_help.c:5695 +#: sql_help.c:5728 msgid "define a new data type" msgstr "새 자료형 만들기" -#: sql_help.c:5707 +#: sql_help.c:5740 msgid "define a new mapping of a user to a foreign server" msgstr "사용자와 외부 서버 간의 새 매핑 정의" -#: sql_help.c:5713 +#: sql_help.c:5746 msgid "define a new view" msgstr "새 view 만들기" -#: sql_help.c:5719 +#: sql_help.c:5752 msgid "deallocate a prepared statement" msgstr "준비된 구문(prepared statement) 지우기" -#: sql_help.c:5725 +#: sql_help.c:5758 msgid "define a cursor" msgstr "커서 지정" -#: sql_help.c:5731 +#: sql_help.c:5764 msgid "delete rows of a table" msgstr "테이블의 자료 삭제" -#: sql_help.c:5737 +#: sql_help.c:5770 msgid "discard session state" msgstr "세션 상태 삭제" -#: sql_help.c:5743 +#: sql_help.c:5776 msgid "execute an anonymous code block" msgstr "임의 코드 블록 실행" -#: sql_help.c:5749 +#: sql_help.c:5782 msgid "remove an access method" msgstr "접근 방법 삭제" -#: sql_help.c:5755 +#: sql_help.c:5788 msgid "remove an aggregate function" msgstr "집계 함수 삭제" -#: sql_help.c:5761 +#: sql_help.c:5794 msgid "remove a cast" msgstr "형변환자 삭제" -#: sql_help.c:5767 +#: sql_help.c:5800 msgid "remove a collation" msgstr "collation 삭제" -#: sql_help.c:5773 +#: sql_help.c:5806 msgid "remove a conversion" msgstr "문자코드 변환규칙(conversion) 삭제" -#: sql_help.c:5779 +#: sql_help.c:5812 msgid "remove a database" msgstr "데이터베이스 삭제" -#: sql_help.c:5785 +#: sql_help.c:5818 msgid "remove a domain" msgstr "도메인 삭제" -#: sql_help.c:5791 +#: sql_help.c:5824 msgid "remove an event trigger" msgstr "이벤트 트리거 삭제" -#: sql_help.c:5797 +#: sql_help.c:5830 msgid "remove an extension" msgstr "확장 모듈 삭제" -#: sql_help.c:5803 +#: sql_help.c:5836 msgid "remove a foreign-data wrapper" msgstr "외부 데이터 래퍼 제거" -#: sql_help.c:5809 +#: sql_help.c:5842 msgid "remove a foreign table" msgstr "외부 테이블 삭제" -#: sql_help.c:5815 +#: sql_help.c:5848 msgid "remove a function" msgstr "함수 삭제" -#: sql_help.c:5821 sql_help.c:5887 sql_help.c:5989 +#: sql_help.c:5854 sql_help.c:5920 sql_help.c:6022 msgid "remove a database role" msgstr "데이터베이스 롤 삭제" -#: sql_help.c:5827 +#: sql_help.c:5860 msgid "remove an index" msgstr "인덱스 삭제" -#: sql_help.c:5833 +#: sql_help.c:5866 msgid "remove a procedural language" msgstr "프로시주얼 언어 삭제" -#: sql_help.c:5839 +#: sql_help.c:5872 msgid "remove a materialized view" msgstr "materialized 뷰 삭제" -#: sql_help.c:5845 +#: sql_help.c:5878 msgid "remove an operator" msgstr "연산자 삭제" -#: sql_help.c:5851 +#: sql_help.c:5884 msgid "remove an operator class" msgstr "연산자 클래스 삭제" -#: sql_help.c:5857 +#: sql_help.c:5890 msgid "remove an operator family" msgstr "연산자 부류 삭제" -#: sql_help.c:5863 +#: sql_help.c:5896 msgid "remove database objects owned by a database role" msgstr "데이터베이스 롤로 권한이 부여된 데이터베이스 개체들을 삭제하세요" -#: sql_help.c:5869 +#: sql_help.c:5902 msgid "remove a row-level security policy from a table" msgstr "해당 테이블에 정의된 로우 단위 보안 정책 삭제" -#: sql_help.c:5875 +#: sql_help.c:5908 msgid "remove a procedure" msgstr "프로시져 삭제" -#: sql_help.c:5881 +#: sql_help.c:5914 msgid "remove a publication" msgstr "발행 삭제" -#: sql_help.c:5893 +#: sql_help.c:5926 msgid "remove a routine" msgstr "루틴 삭제" -#: sql_help.c:5899 +#: sql_help.c:5932 msgid "remove a rewrite rule" msgstr "룰(rule) 삭제" -#: sql_help.c:5905 +#: sql_help.c:5938 msgid "remove a schema" msgstr "스키마(schema) 삭제" -#: sql_help.c:5911 +#: sql_help.c:5944 msgid "remove a sequence" msgstr "시퀀스 삭제" -#: sql_help.c:5917 +#: sql_help.c:5950 msgid "remove a foreign server descriptor" msgstr "외부 서버 설명자 제거" -#: sql_help.c:5923 +#: sql_help.c:5956 msgid "remove extended statistics" msgstr "확장 통계정보 삭제" -#: sql_help.c:5929 +#: sql_help.c:5962 msgid "remove a subscription" msgstr "구독 삭제" -#: sql_help.c:5935 +#: sql_help.c:5968 msgid "remove a table" msgstr "테이블 삭제" -#: sql_help.c:5941 +#: sql_help.c:5974 msgid "remove a tablespace" msgstr "테이블스페이스 삭제" -#: sql_help.c:5947 +#: sql_help.c:5980 msgid "remove a text search configuration" msgstr "텍스트 검색 구성 제거" -#: sql_help.c:5953 +#: sql_help.c:5986 msgid "remove a text search dictionary" msgstr "텍스트 검색 사전 제거" -#: sql_help.c:5959 +#: sql_help.c:5992 msgid "remove a text search parser" msgstr "텍스트 검색 파서 제거" -#: sql_help.c:5965 +#: sql_help.c:5998 msgid "remove a text search template" msgstr "텍스트 검색 템플릿 제거" -#: sql_help.c:5971 +#: sql_help.c:6004 msgid "remove a transform" msgstr "transform 삭제" -#: sql_help.c:5977 +#: sql_help.c:6010 msgid "remove a trigger" msgstr "트리거 삭제" -#: sql_help.c:5983 +#: sql_help.c:6016 msgid "remove a data type" msgstr "자료형 삭제" -#: sql_help.c:5995 +#: sql_help.c:6028 msgid "remove a user mapping for a foreign server" msgstr "외부 서버에 대한 사용자 매핑 제거" -#: sql_help.c:6001 +#: sql_help.c:6034 msgid "remove a view" msgstr "뷰(view) 삭제" -#: sql_help.c:6013 +#: sql_help.c:6046 msgid "execute a prepared statement" msgstr "준비된 구문(prepared statement) 실행" -#: sql_help.c:6019 +#: sql_help.c:6052 msgid "show the execution plan of a statement" msgstr "쿼리 실행계획 보기" -#: sql_help.c:6025 +#: sql_help.c:6058 msgid "retrieve rows from a query using a cursor" msgstr "해당 커서에서 자료 뽑기" -#: sql_help.c:6031 +#: sql_help.c:6064 msgid "define access privileges" msgstr "액세스 권한 지정하기" -#: sql_help.c:6037 +#: sql_help.c:6070 msgid "import table definitions from a foreign server" msgstr "외부 서버로부터 테이블 정의 가져오기" -#: sql_help.c:6043 +#: sql_help.c:6076 msgid "create new rows in a table" msgstr "테이블 자료 삽입" -#: sql_help.c:6049 +#: sql_help.c:6082 msgid "listen for a notification" msgstr "특정 서버 메시지 수신함" -#: sql_help.c:6055 +#: sql_help.c:6088 msgid "load a shared library file" msgstr "공유 라이브러리 파일 로드" -#: sql_help.c:6061 +#: sql_help.c:6094 msgid "lock a table" msgstr "테이블 잠금" -#: sql_help.c:6067 +#: sql_help.c:6100 msgid "conditionally insert, update, or delete rows of a table" msgstr "조건부 테이블 insert, update, delete" -#: sql_help.c:6073 +#: sql_help.c:6106 msgid "position a cursor" msgstr "커서 위치 옮기기" -#: sql_help.c:6079 +#: sql_help.c:6112 msgid "generate a notification" msgstr "특정 서버 메시지 발생" -#: sql_help.c:6085 +#: sql_help.c:6118 msgid "prepare a statement for execution" msgstr "준비된 구문(prepared statement) 만들기" -#: sql_help.c:6091 +#: sql_help.c:6124 msgid "prepare the current transaction for two-phase commit" msgstr "two-phase 커밋을 위해 현재 트랜잭션을 준비함" -#: sql_help.c:6097 +#: sql_help.c:6130 msgid "change the ownership of database objects owned by a database role" msgstr "데이터베이스 롤로 권한이 부여된 데이터베이스 개체들의 소유주 바꾸기" -#: sql_help.c:6103 +#: sql_help.c:6136 msgid "replace the contents of a materialized view" msgstr "구체화된 뷰의 내용 수정" -#: sql_help.c:6109 +#: sql_help.c:6142 msgid "rebuild indexes" msgstr "인덱스 다시 만들기" -#: sql_help.c:6115 +#: sql_help.c:6148 msgid "release a previously defined savepoint" msgstr "이전 정의된 savepoint를 지움" -#: sql_help.c:6121 +#: sql_help.c:6154 msgid "restore the value of a run-time parameter to the default value" msgstr "실시간 환경 변수값을 초기값으로 다시 지정" -#: sql_help.c:6127 +#: sql_help.c:6160 msgid "remove access privileges" msgstr "액세스 권한 해제하기" -#: sql_help.c:6139 +#: sql_help.c:6172 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "two-phase 커밋을 위해 먼저 준비되었던 트랜잭션 실행취소하기" -#: sql_help.c:6145 +#: sql_help.c:6178 msgid "roll back to a savepoint" msgstr "savepoint 파기하기" -#: sql_help.c:6151 +#: sql_help.c:6184 msgid "define a new savepoint within the current transaction" msgstr "현재 트랜잭션에서 새로운 savepoint 만들기" -#: sql_help.c:6157 +#: sql_help.c:6190 msgid "define or change a security label applied to an object" msgstr "해당 개체에 보안 라벨을 정의하거나 변경" -#: sql_help.c:6163 sql_help.c:6217 sql_help.c:6253 +#: sql_help.c:6196 sql_help.c:6250 sql_help.c:6286 msgid "retrieve rows from a table or view" msgstr "테이블이나 뷰의 자료를 출력" -#: sql_help.c:6175 +#: sql_help.c:6208 msgid "change a run-time parameter" msgstr "실시간 환경 변수값 바꾸기" -#: sql_help.c:6181 +#: sql_help.c:6214 msgid "set constraint check timing for the current transaction" msgstr "현재 트랜잭션에서 제약조건 설정" -#: sql_help.c:6187 +#: sql_help.c:6220 msgid "set the current user identifier of the current session" msgstr "현재 세션의 현재 사용자 식별자를 지정" -#: sql_help.c:6193 +#: sql_help.c:6226 msgid "" "set the session user identifier and the current user identifier of the " "current session" msgstr "현재 세션의 사용자 인증을 지정함 - 사용자 지정" -#: sql_help.c:6199 +#: sql_help.c:6232 msgid "set the characteristics of the current transaction" msgstr "현재 트랜잭션의 성질을 지정함" -#: sql_help.c:6205 +#: sql_help.c:6238 msgid "show the value of a run-time parameter" msgstr "실시간 환경 변수값들을 보여줌" -#: sql_help.c:6223 +#: sql_help.c:6256 msgid "empty a table or set of tables" msgstr "하나 또는 지정한 여러개의 테이블에서 모든 자료 지움" -#: sql_help.c:6229 +#: sql_help.c:6262 msgid "stop listening for a notification" msgstr "특정 서버 메시지 수신 기능 끔" -#: sql_help.c:6235 +#: sql_help.c:6268 msgid "update rows of a table" msgstr "테이블 자료 갱신" -#: sql_help.c:6241 +#: sql_help.c:6274 msgid "garbage-collect and optionally analyze a database" msgstr "물리적인 자료 정리 작업 - 쓰레기값 청소" -#: sql_help.c:6247 +#: sql_help.c:6280 msgid "compute a set of rows" msgstr "compute a set of rows" @@ -6657,7 +6735,7 @@ msgstr "추가 명령행 인자 \"%s\" 무시됨" msgid "could not find own program executable" msgstr "실행 가능한 프로그램을 찾을 수 없음" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6691,3 +6769,19 @@ msgid "" msgstr "" "\"%s\" 값은 \"%s\" 변수값으로 사용할 수 없음\n" "사용할 수 있는 변수값: %s" + +#~ msgid "ICU Locale" +#~ msgstr "ICU 로케일" + +#~ msgid "local socket" +#~ msgstr "로컬 소켓" + +#~ msgid "" +#~ " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" +#~ msgstr " \\watch [[i=]SEC] [c=N] SEC초 간격, N번 반복\n" + +#~ msgid "constraint" +#~ msgstr "제약조건" + +#~ msgid "where constraint is:" +#~ msgstr "제약조건 사용법:" diff --git a/src/bin/psql/po/meson.build b/src/bin/psql/po/meson.build index 4907d85080ac5..6b5abd0e49276 100644 --- a/src/bin/psql/po/meson.build +++ b/src/bin/psql/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('psql-' + pg_version_major.to_string())] diff --git a/src/bin/psql/po/ru.po b/src/bin/psql/po/ru.po index aa94fef05ef7a..9ffcab1d2b8e9 100644 --- a/src/bin/psql/po/ru.po +++ b/src/bin/psql/po/ru.po @@ -4,14 +4,14 @@ # Serguei A. Mokhov , 2001-2005. # Oleg Bartunov , 2004-2005. # Sergey Burladyan , 2012. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2025. # Maxim Yablokov , 2021. msgid "" msgstr "" "Project-Id-Version: psql (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2023-08-29 13:37+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2025-02-08 08:33+0200\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -41,33 +41,48 @@ msgstr "подробности: " msgid "hint: " msgstr "подсказка: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "неверный исполняемый файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не удалось прочитать исполняемый файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "не удалось найти запускаемый файл \"%s\"" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не удалось преобразовать относительный путь \"%s\" в абсолютный: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не удалось выполнить команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не удалось прочитать вывод команды \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не выдала данные" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "ошибка в %s(): %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -89,7 +104,7 @@ msgstr "попытка дублирования нулевого указате msgid "could not look up effective user ID %ld: %s" msgstr "выяснить эффективный идентификатор пользователя (%ld) не удалось: %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "пользователь не существует" @@ -126,13 +141,13 @@ msgstr "дочерний процесс завершён по сигналу %d: #: ../../common/wait_error.c:82 #, c-format msgid "child process exited with unrecognized status %d" -msgstr "дочерний процесс завершился с нераспознанным состоянием %d" +msgstr "дочерний процесс завершился с нераспознанным кодом состояния %d" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Сигнал отмены отправлен\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Отправить сигнал отмены не удалось: " @@ -149,76 +164,98 @@ msgstr[2] "(%lu строк)" msgid "Interrupted\n" msgstr "Прервано\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "" +"Cannot print table contents: number of cells %lld is equal to or exceeds " +"maximum %lld.\n" +msgstr "" +"Вывести содержимое таблицы нельзя: число ячеек %lld достигло максимума " +"%lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "" "Ошибка добавления заголовка таблицы: превышен предел числа столбцов (%d).\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" msgstr "" -"Ошибка добавления ячейки в таблицу: превышен предел числа ячеек (%d).\n" +"Ошибка добавления ячейки в таблицу: превышен предел числа ячеек (%lld).\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "неверный формат вывода (внутренняя ошибка): %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "рекурсивное расширение переменной \"%s\" пропускается" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "найти локального пользователя по идентификатору (%d) не удалось: %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "локальный пользователь с ID %d не существует" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "неверная команда \\%s" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "Введите \\? для получения справки." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: лишний аргумент \"%s\" пропущен" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "" "команда \\%s игнорируется; добавьте \\endif или нажмите Ctrl-C для " "завершения текущего блока \\if" -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "не удалось получить домашний каталог пользователя c ид. %ld: %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: не удалось перейти в каталог \"%s\": %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "В данный момент вы не подключены к базе данных.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at " @@ -227,7 +264,7 @@ msgstr "" "Вы подключены к базе данных \"%s\" как пользователь \"%s\" (адрес сервера " "\"%s\", порт \"%s\").\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at " @@ -236,221 +273,231 @@ msgstr "" "Вы подключены к базе данных \"%s\" как пользователь \"%s\" через сокет в " "\"%s\", порт \"%s\".\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address " "\"%s\") at port \"%s\".\n" msgstr "" -"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (сервер \"%s\": " -"адрес \"%s\", порт \"%s\").\n" +"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (компьютер " +"\"%s\": адрес \"%s\", порт \"%s\").\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "" "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port " "\"%s\".\n" msgstr "" -"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (сервер \"%s\", " -"порт \"%s\").\n" +"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (компьютер " +"\"%s\", порт \"%s\").\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2675 #, c-format msgid "no query buffer" msgstr "нет буфера запросов" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5776 #, c-format msgid "invalid line number: %s" msgstr "неверный номер строки: %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "Изменений нет" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "" "%s: неверное название кодировки символов или не найдена процедура " "перекодировки" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:721 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5882 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1375 msgid "There is no previous error." msgstr "Ошибки не было." -#: command.c:1470 +#: command.c:1488 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: отсутствует правая скобка" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 +#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 #, c-format msgid "\\%s: missing required argument" msgstr "отсутствует необходимый аргумент \\%s" -#: command.c:1815 +#: command.c:1822 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif не может находиться после \\else" -#: command.c:1820 +#: command.c:1827 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif без соответствующего \\if" -#: command.c:1884 +#: command.c:1891 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else не может находиться после \\else" -#: command.c:1889 +#: command.c:1896 #, c-format msgid "\\else: no matching \\if" msgstr "\\else без соответствующего \\if" -#: command.c:1929 +#: command.c:1936 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif без соответствующего \\if" -#: command.c:2085 +#: command.c:2092 msgid "Query buffer is empty." msgstr "Буфер запроса пуст." -#: command.c:2128 +#: command.c:2135 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Введите новый пароль для пользователя \"%s\": " -#: command.c:2132 +#: command.c:2139 msgid "Enter it again: " msgstr "Повторите его: " -#: command.c:2141 +#: command.c:2148 #, c-format msgid "Passwords didn't match." msgstr "Пароли не совпадают." -#: command.c:2238 +#: command.c:2231 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: не удалось прочитать значение переменной" -#: command.c:2340 +#: command.c:2333 msgid "Query buffer reset (cleared)." msgstr "Буфер запроса сброшен (очищен)." -#: command.c:2362 +#: command.c:2355 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "История записана в файл \"%s\".\n" -#: command.c:2449 +#: command.c:2442 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: имя переменной окружения не может содержать знак \"=\"" -#: command.c:2497 +#: command.c:2490 #, c-format msgid "function name is required" msgstr "требуется имя функции" -#: command.c:2499 +#: command.c:2492 #, c-format msgid "view name is required" msgstr "требуется имя представления" -#: command.c:2621 +#: command.c:2614 msgid "Timing is on." msgstr "Секундомер включён." -#: command.c:2623 +#: command.c:2616 msgid "Timing is off." msgstr "Секундомер выключен." -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 +#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 +#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2736 copy.c:388 +#: command.c:2729 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2806 command.c:2852 +#: command.c:2801 command.c:2867 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: длительность интервала указана неоднократно" -#: command.c:2816 command.c:2862 +#: command.c:2811 command.c:2877 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: некорректная длительность интервала \"%s\"" -#: command.c:2826 +#: command.c:2821 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: число итераций указано неоднократно" -#: command.c:2836 +#: command.c:2831 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: некорректное число итераций \"%s\"" -#: command.c:2843 +#: command.c:2841 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: минимальное число строк указано неоднократно" + +#: command.c:2851 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch: некорректное минимальное число строк \"%s\"" + +#: command.c:2858 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: нераспознанный параметр \"%s\"" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3255 startup.c:243 startup.c:293 msgid "Password: " msgstr "Пароль: " -#: command.c:3241 startup.c:290 +#: command.c:3260 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "Пароль пользователя %s: " -#: command.c:3297 +#: command.c:3316 #, c-format msgid "" "Do not give user, host, or port separately when using a connection string" msgstr "" -"Не указывайте пользователя, сервер или порт отдельно, когда используете " +"Не указывайте пользователя, компьютер или порт отдельно, когда используете " "строку подключения" -#: command.c:3332 +#: command.c:3351 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "" "Нет подключения к базе, из которого можно было бы использовать параметры" -#: command.c:3638 +#: command.c:3658 #, c-format msgid "Previous connection kept" msgstr "Сохранено предыдущее подключение" -#: command.c:3644 +#: command.c:3664 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3700 +#: command.c:3720 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at " @@ -459,7 +506,7 @@ msgstr "" "Сейчас вы подключены к базе данных \"%s\" как пользователь \"%s\" (адрес " "сервера \"%s\", порт \"%s\").\n" -#: command.c:3703 +#: command.c:3723 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" " @@ -468,35 +515,35 @@ msgstr "" "Вы подключены к базе данных \"%s\" как пользователь \"%s\" через сокет в " "\"%s\", порт \"%s\".\n" -#: command.c:3709 +#: command.c:3729 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" on host " "\"%s\" (address \"%s\") at port \"%s\".\n" msgstr "" -"Сейчас вы подключены к базе данных \"%s\" как пользователь \"%s\" (сервер " +"Сейчас вы подключены к базе данных \"%s\" как пользователь \"%s\" (компьютер " "\"%s\": адрес \"%s\", порт \"%s\").\n" -#: command.c:3712 +#: command.c:3732 #, c-format msgid "" "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at " "port \"%s\".\n" msgstr "" -"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (сервер \"%s\", " -"порт \"%s\").\n" +"Вы подключены к базе данных \"%s\" как пользователь \"%s\" (компьютер " +"\"%s\", порт \"%s\").\n" -#: command.c:3717 +#: command.c:3737 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Вы подключены к базе данных \"%s\" как пользователь \"%s\".\n" -#: command.c:3757 +#: command.c:3843 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, сервер %s)\n" -#: command.c:3770 +#: command.c:3856 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -505,29 +552,33 @@ msgstr "" "ПРЕДУПРЕЖДЕНИЕ: %s имеет базовую версию %s, а сервер - %s.\n" " Часть функций psql может не работать.\n" -#: command.c:3807 +#: command.c:3895 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "SSL-соединение (протокол: %s, шифр: %s, сжатие: %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "SSL-соединение (протокол: %s, шифр: %s, сжатие: %s, ALPN: %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3896 command.c:3897 msgid "unknown" msgstr "неизвестно" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "off" msgstr "выкл." -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "on" msgstr "вкл." -#: command.c:3824 +#: command.c:3899 +msgid "none" +msgstr "нет" + +#: command.c:3913 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "Соединение зашифровано GSSAPI\n" -#: command.c:3844 +#: command.c:3933 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -540,7 +591,7 @@ msgstr "" " Подробнее об этом смотрите документацию psql, раздел\n" " \"Notes for Windows users\".\n" -#: command.c:3949 +#: command.c:4038 #, c-format msgid "" "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a " @@ -549,33 +600,33 @@ msgstr "" "в переменной окружения PSQL_EDITOR_LINENUMBER_ARG должен быть указан номер " "строки" -#: command.c:3979 +#: command.c:4068 #, c-format msgid "could not start editor \"%s\"" msgstr "не удалось запустить редактор \"%s\"" -#: command.c:3981 +#: command.c:4070 #, c-format msgid "could not start /bin/sh" msgstr "не удалось запустить /bin/sh" -#: command.c:4031 +#: command.c:4120 #, c-format msgid "could not locate temporary directory: %s" msgstr "не удалось найти временный каталог: %s" -#: command.c:4058 +#: command.c:4147 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "не удалось открыть временный файл \"%s\": %m" -#: command.c:4394 +#: command.c:4483 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "" "\\pset: неоднозначному сокращению \"%s\" соответствует и \"%s\", и \"%s\"" -#: command.c:4414 +#: command.c:4503 #, c-format msgid "" "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-" @@ -584,27 +635,27 @@ msgstr "" "\\pset: допустимые форматы: aligned, asciidoc, csv, html, latex, latex-" "longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4522 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: допустимые стили линий: ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4537 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: допустимые стили Unicode-линий границ: single, double" -#: command.c:4463 +#: command.c:4552 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: допустимые стили Unicode-линий столбцов: single, double" -#: command.c:4478 +#: command.c:4567 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: допустимые стили Unicode-линий заголовков: single, double" -#: command.c:4530 +#: command.c:4619 #, c-format msgid "" "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", " @@ -613,12 +664,12 @@ msgstr "" "\\pset: допустимые значения xheader_width: \"%s\" (по умолчанию), \"%s\", " "\"%s\", а также число, задающее точную ширину" -#: command.c:4547 +#: command.c:4636 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: символ csv_fieldsep должен быть однобайтовым" -#: command.c:4552 +#: command.c:4641 #, c-format msgid "" "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage " @@ -627,117 +678,117 @@ msgstr "" "\\pset: в качестве csv_fieldsep нельзя выбрать символ кавычек, новой строки " "или возврата каретки" -#: command.c:4690 command.c:4891 +#: command.c:4779 command.c:4980 #, c-format msgid "\\pset: unknown option: %s" msgstr "неизвестный параметр \\pset: %s" -#: command.c:4710 +#: command.c:4799 #, c-format msgid "Border style is %d.\n" msgstr "Стиль границ: %d.\n" -#: command.c:4716 +#: command.c:4805 #, c-format msgid "Target width is unset.\n" msgstr "Ширина вывода сброшена.\n" -#: command.c:4718 +#: command.c:4807 #, c-format msgid "Target width is %d.\n" msgstr "Ширина вывода: %d.\n" -#: command.c:4725 +#: command.c:4814 #, c-format msgid "Expanded display is on.\n" msgstr "Расширенный вывод включён.\n" -#: command.c:4727 +#: command.c:4816 #, c-format msgid "Expanded display is used automatically.\n" msgstr "Расширенный вывод применяется автоматически.\n" -#: command.c:4729 +#: command.c:4818 #, c-format msgid "Expanded display is off.\n" msgstr "Расширенный вывод выключен.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4825 command.c:4827 command.c:4829 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "Ширина расширенного заголовка: \"%s\".\n" -#: command.c:4742 +#: command.c:4831 #, c-format msgid "Expanded header width is %d.\n" msgstr "Ширина расширенного заголовка: %d.\n" -#: command.c:4748 +#: command.c:4837 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "Разделитель полей для CSV: \"%s\".\n" -#: command.c:4756 command.c:4764 +#: command.c:4845 command.c:4853 #, c-format msgid "Field separator is zero byte.\n" msgstr "Разделитель полей - нулевой байт.\n" -#: command.c:4758 +#: command.c:4847 #, c-format msgid "Field separator is \"%s\".\n" msgstr "Разделитель полей: \"%s\".\n" -#: command.c:4771 +#: command.c:4860 #, c-format msgid "Default footer is on.\n" msgstr "Строка итогов включена.\n" -#: command.c:4773 +#: command.c:4862 #, c-format msgid "Default footer is off.\n" msgstr "Строка итогов выключена.\n" -#: command.c:4779 +#: command.c:4868 #, c-format msgid "Output format is %s.\n" msgstr "Формат вывода: %s.\n" -#: command.c:4785 +#: command.c:4874 #, c-format msgid "Line style is %s.\n" msgstr "Установлен стиль линий: %s.\n" -#: command.c:4792 +#: command.c:4881 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null выводится как: \"%s\".\n" -#: command.c:4800 +#: command.c:4889 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "Локализованный вывод чисел включён.\n" -#: command.c:4802 +#: command.c:4891 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "Локализованный вывод чисел выключен.\n" -#: command.c:4809 +#: command.c:4898 #, c-format msgid "Pager is used for long output.\n" msgstr "Постраничник используется для вывода длинного текста.\n" -#: command.c:4811 +#: command.c:4900 #, c-format msgid "Pager is always used.\n" msgstr "Постраничник используется всегда.\n" -#: command.c:4813 +#: command.c:4902 #, c-format msgid "Pager usage is off.\n" msgstr "Постраничник выключен.\n" -#: command.c:4819 +#: command.c:4908 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" @@ -745,182 +796,182 @@ msgstr[0] "Постраничник не будет использоваться msgstr[1] "Постраничник не будет использоваться, если строк меньше %d\n" msgstr[2] "Постраничник не будет использоваться, если строк меньше %d\n" -#: command.c:4829 command.c:4839 +#: command.c:4918 command.c:4928 #, c-format msgid "Record separator is zero byte.\n" msgstr "Разделитель записей - нулевой байт.\n" -#: command.c:4831 +#: command.c:4920 #, c-format msgid "Record separator is .\n" msgstr "Разделитель записей: <новая строка>.\n" -#: command.c:4833 +#: command.c:4922 #, c-format msgid "Record separator is \"%s\".\n" msgstr "Разделитель записей: \"%s\".\n" -#: command.c:4846 +#: command.c:4935 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Атрибуты HTML-таблицы: \"%s\".\n" -#: command.c:4849 +#: command.c:4938 #, c-format msgid "Table attributes unset.\n" msgstr "Атрибуты HTML-таблицы не заданы.\n" -#: command.c:4856 +#: command.c:4945 #, c-format msgid "Title is \"%s\".\n" msgstr "Заголовок: \"%s\".\n" -#: command.c:4858 +#: command.c:4947 #, c-format msgid "Title is unset.\n" msgstr "Заголовок не задан.\n" -#: command.c:4865 +#: command.c:4954 #, c-format msgid "Tuples only is on.\n" msgstr "Режим вывода только кортежей включён.\n" -#: command.c:4867 +#: command.c:4956 #, c-format msgid "Tuples only is off.\n" msgstr "Режим вывода только кортежей выключен.\n" -#: command.c:4873 +#: command.c:4962 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Стиль Unicode-линий границ: \"%s\".\n" -#: command.c:4879 +#: command.c:4968 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Стиль Unicode-линий столбцов: \"%s\".\n" -#: command.c:4885 +#: command.c:4974 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Стиль Unicode-линий границ: \"%s\".\n" -#: command.c:5134 +#: command.c:5223 #, c-format msgid "\\!: failed" msgstr "\\!: ошибка" -#: command.c:5168 +#: command.c:5261 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch нельзя использовать с пустым запросом" -#: command.c:5200 +#: command.c:5293 #, c-format msgid "could not set timer: %m" msgstr "не удалось установить таймер: %m" -#: command.c:5269 +#: command.c:5362 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (обновление: %g с)\n" -#: command.c:5272 +#: command.c:5365 #, c-format msgid "%s (every %gs)\n" msgstr "%s (обновление: %g с)\n" -#: command.c:5340 +#: command.c:5429 #, c-format msgid "could not wait for signals: %m" msgstr "сбой при ожидании сигналов: %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5485 command.c:5492 common.c:632 common.c:639 common.c:1123 #, c-format msgid "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" msgstr "" -"********* ЗАПРОС *********\n" +"/******** ЗАПРОС ********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" -#: command.c:5584 +#: command.c:5671 #, c-format msgid "\"%s.%s\" is not a view" msgstr "\"%s.%s\" — не представление" -#: command.c:5600 +#: command.c:5687 #, c-format msgid "could not parse reloptions array" msgstr "не удалось разобрать массив reloptions" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "экранирование строк не работает без подключения к БД" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "" "аргумент команды оболочки содержит символ новой строки или перевода каретки: " "\"%s\"" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "подключение к серверу было потеряно" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "Подключение к серверу потеряно. Попытка восстановления " -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "неудачна.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "удачна.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "неожиданное значение PQresultStatus: %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "Время: %.3f мс\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Время: %.3f мс (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Время: %.3f мс (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Время: %.3f мс (%.0f д. %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "В данный момент вы не подключены к базе данных." -#: common.c:674 +#: common.c:714 #, c-format msgid "" "Asynchronous notification \"%s\" with payload \"%s\" received from server " @@ -929,73 +980,79 @@ msgstr "" "Получено асинхронное уведомление \"%s\" с сообщением-нагрузкой \"%s\" от " "серверного процесса с PID %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "" "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "" "Получено асинхронное уведомление \"%s\" от серверного процесса с PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "не удалось вывести таблицу результатов: %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "сервер не возвратил строк для \\gset" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "сервер возвратил больше одной строки для \\gset" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "попытка выполнить \\gset со специальной переменной \"%s\" игнорируется" -#: common.c:1063 +#: common.c:1103 #, c-format msgid "" -"***(Single step mode: verify " -"command)*******************************************\n" +"/**(Single step mode: verify " +"command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to " -"cancel)********************\n" +"/**(press return to proceed or enter x and return to " +"cancel)*******************/\n" msgstr "" -"***(Пошаговый режим: проверка " -"команды)******************************************\n" +"/**(Пошаговый режим: проверка " +"команды)*****************************************/\n" "%s\n" -"***(Enter - выполнение; x и Enter - отмена)**************\n" +"/**(Enter - выполнение; x и Enter - " +"отмена)************************************/\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "ОПЕРАТОР: %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "неожиданное состояние транзакции (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "Столбец" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "Тип" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "Команда не выдала результат, либо в результате нет столбцов.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "получить результаты в блочном режиме не удалось" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -1011,11 +1068,6 @@ msgstr "\\copy: ошибка разбора аргумента \"%s\"" msgid "\\copy: parse error at end of line" msgstr "\\copy: ошибка разбора в конце строки" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не удалось выполнить команду \"%s\": %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -1053,25 +1105,25 @@ msgstr "" "Вводите данные для копирования, разделяя строки переводом строки.\n" "Закончите ввод строкой '\\.' или сигналом EOF." -#: copy.c:683 +#: copy.c:684 msgid "aborted because of read failure" msgstr "прерывание из-за ошибки чтения" -#: copy.c:717 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "попытка выйти из режима копирования" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview: оператор не возвратил результирующий набор" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview: запрос должен возвращать минимум три столбца" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "" "\\crosstabview: vertical and horizontal headers must be different columns" @@ -1079,7 +1131,7 @@ msgstr "" "\\crosstabview: для вертикальных и горизонтальных заголовков должны " "задаваться разные столбцы" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "" "\\crosstabview: data column must be specified when query returns more than " @@ -1088,12 +1140,12 @@ msgstr "" "\\crosstabview: когда запрос возвращает больше трёх столбцов, необходимо " "указать столбец данных" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview: превышен максимум числа столбцов (%d)" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "" "\\crosstabview: query result contains multiple data values for row \"%s\", " @@ -1102,302 +1154,303 @@ msgstr "" "\\crosstabview: в результатах запроса содержится несколько значений данных " "для строки \"%s\", столбца \"%s\"" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview: номер столбца %d выходит за рамки диапазона 1..%d" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview: неоднозначное имя столбца: \"%s\"" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: имя столбца не найдено: \"%s\"" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "Схема" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "Имя" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "Тип данных результата" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "Типы данных аргументов" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "Описание" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "Список агрегатных функций" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "Сервер (версия %s) не поддерживает методы доступа." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "Индекс" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "Таблица" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "Обработчик" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "Список методов доступа" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "Владелец" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "Расположение" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "Параметры" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "Размер" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "Список табличных пространств" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df принимает в качестве параметров только [anptwS+]" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df не поддерживает параметр \"%c\" с сервером версии %s" # well-spelled: агр #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "агр." -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "оконная" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "проц." # well-spelled: функ -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "функ." -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "триггерная" -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "постоянная" -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "стабильная" -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "изменчивая" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "Изменчивость" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "ограниченная" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "безопасная" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "небезопасная" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "Параллельность" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "определившего" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "вызывающего" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "Безопасность" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "Язык" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "Внутреннее имя" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "Список функций" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "Элементы" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "Список типов данных" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "Тип левого аргумента" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "Тип правого аргумента" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "Результирующий тип" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "Функция" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "Список операторов" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "Кодировка" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "Провайдер локали" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "LC_COLLATE" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "LC_CTYPE" -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "локаль ICU" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "Локаль" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "Правила ICU" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "Табл. пространство" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "Список баз данных" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "таблица" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "представление" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "материализованное представление" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "последовательность" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "сторонняя таблица" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "секционированная таблица" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "Права для столбцов" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "Политики" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "Права доступа" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "функция" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "тип" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "схема" @@ -1429,295 +1482,295 @@ msgstr "семейство операторов" msgid "rule" msgstr "правило" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "Описание объекта" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "Отношение \"%s\" не найдено." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "Отношения не найдены." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "Отношение с OID %s не найдено." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "Начальное_значение" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "Минимум" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "Максимум" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "Шаг" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "да" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "нет" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "Зацикливается?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "Кешируется" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "Владелец: %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "Последовательность для столбца идентификации: %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Нежурналируемая последовательность \"%s.%s\"" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Последовательность \"%s.%s\"" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Нежурналируемая таблица \"%s.%s\"" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "Таблица \"%s.%s\"" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "Представление \"%s.%s\"" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "Нежурналируемое материализованное представление \"%s.%s\"" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Материализованное представление \"%s.%s\"" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Нежурналируемый индекс \"%s.%s\"" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "Индекс \"%s.%s\"" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Нежурналируемый секционированный индекс \"%s.%s\"" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Секционированный индекс \"%s.%s\"" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "TOAST-таблица \"%s.%s\"" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Составной тип \"%s.%s\"" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Сторонняя таблица \"%s.%s\"" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Нежурналируемая секционированная таблица \"%s.%s\"" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Секционированная таблица \"%s.%s\"" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "Правило сортировки" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "Допустимость NULL" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "По умолчанию" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "Ключевой?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "Определение" # well-spelled: ОСД -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "Параметры ОСД" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "Хранилище" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "Сжатие" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "Цель для статистики" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "Секция: %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "Нет ограничения секции" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "Ограничение секции: %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "Ключ разбиения: %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Принадлежит таблице: \"%s.%s\"" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "первичный ключ, " -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "уникальный" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " null не различаются" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr ", " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "для таблицы \"%s.%s\"" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", предикат (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", кластеризованный" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", нерабочий" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", откладываемый" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", изначально отложенный" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", репликационный" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "Индексы:" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "Ограничения-проверки:" # TO REWVIEW -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "Ограничения внешнего ключа:" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "Ссылки извне:" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "Политики:" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "Политики (усиленная защита строк включена):" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "Политики (защита строк включена): (Нет)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "Политики (усиленная защита строк включена): (Нет)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "Политики (защита строк выключена):" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "Объекты статистики:" @@ -1737,7 +1790,7 @@ msgstr "Правила, срабатывающие всегда:" msgid "Rules firing on replica only:" msgstr "Правила, срабатывающие только в реплике:" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "Публикации:" @@ -1837,7 +1890,7 @@ msgstr ", табл. пространство \"%s\"" msgid "List of roles" msgstr "Список ролей" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "Имя роли" @@ -1916,370 +1969,370 @@ msgstr "Параметры для роли \"%s\" не найдены." msgid "Did not find any settings." msgstr "Никакие параметры не найдены." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "Список параметров" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "Член ролей" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "Праводатель" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "Список назначений ролей" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "индекс" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "TOAST-таблица" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "секционированный индекс" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "постоянное" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "временное" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "нежурналируемое" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "Хранение" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "Метод доступа" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "Список отношений" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "" "The server (version %s) does not support declarative table partitioning." msgstr "" "Сервер (версия %s) не поддерживает декларативное секционирование таблиц." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "Список секционированных индексов" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "Список секционированных таблиц" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "Список секционированных отношений" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "Имя родителя" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "Размер конечной секции" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "Общий размер" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "Доверенный" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "Внутренний язык" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "Обработчик вызова" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "Функция проверки" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "Обработчик внедрённого кода" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "Список языков" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "Проверка" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "Список доменов" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "Источник" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "Назначение" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "По умолчанию?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "Список преобразований" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "Параметр" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "Значение" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "Контекст" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "Список параметров конфигурации" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "Список изменённых параметров конфигурации" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "Сервер (версия %s) не поддерживает событийные триггеры." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "Событие" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "включён" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "реплика" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "всегда" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "отключён" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "Включён" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "Теги" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "Список событийных триггеров" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "Сервер (версия %s) не поддерживает расширенные статистики." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Зависимости" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "Список расширенных статистик" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Исходный тип" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Целевой тип" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "в присваивании" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Неявное?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "Список приведений типов" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "Провайдер" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "Детерминированное?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "Список правил сортировки" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "Список схем" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "Список анализаторов текстового поиска" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "Анализатор текстового поиска \"%s\" не найден." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "Никакие анализаторы текстового поиска не найдены." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "Начало разбора" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "Метод" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "Получение следующего фрагмента" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "Окончание разбора" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "Получение выдержки" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "Получение типов фрагментов" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Анализатор текстового поиска \"%s.%s\"" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "Анализатор текстового поиска \"%s\"" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "Имя фрагмента" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Типы фрагментов для анализатора \"%s.%s\"" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "Типы фрагментов для анализатора \"%s\"" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "Шаблон" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "Параметры инициализации" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "Список словарей текстового поиска" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "Инициализация" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Выделение лексем" -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "Список шаблонов текстового поиска" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "Список конфигураций текстового поиска" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "Конфигурация текстового поиска \"%s\" не найдена." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "Никакие конфигурации текстового поиска не найдены." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "Фрагмент" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "Словари" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Конфигурация текстового поиска \"%s.%s\"" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "Конфигурация текстового поиска \"%s\"" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "" "\n" @@ -2288,7 +2341,7 @@ msgstr "" "\n" "Анализатор: \"%s.%s\"" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "" "\n" @@ -2297,265 +2350,273 @@ msgstr "" "\n" "Анализатор: \"%s\"" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "Список обёрток сторонних данных" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "Обёртка сторонних данных" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "Версия" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "Список сторонних серверов" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "Сервер" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "Имя пользователя" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "Список сопоставлений пользователей" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "Список сторонних таблиц" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "Список установленных расширений" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "Расширение \"%s\" не найдено." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "Никакие расширения не найдены." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "Описание объекта" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "Объекты в расширении \"%s\"" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неверное полное имя (слишком много компонентов): %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "ссылки между базами не реализованы: %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "Сервер (версия %s) не поддерживает публикации." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "Все таблицы" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Добавления" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Изменения" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Удаления" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Опустошения" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Через корень" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "Список публикаций" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "Публикация \"%s\" не найдена." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "Никакие публикации не найдены." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "Публикация %s" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "Таблицы:" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "Таблицы из схем:" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "Сервер (версия %s) не поддерживает подписки." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "Публикация" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "Бинарная" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "Потоковая" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "Двухфазная фиксация" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "Отключается при ошибке" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "Источник" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "Требуется пароль" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "Использовать владельца?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "Переносимая" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "Синхронная фиксация" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "Строка подключения" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "Пропустить LSN" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "Список подписок" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(нет)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "МД" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "Входной тип" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "Тип хранения" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "Класс операторов" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "Семейство операторов" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "Список классов операторов" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Применимые типы" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "Список семейств операторов" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "Оператор" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "Стратегия" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "сортировка" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "поиск" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "Назначение" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "Семейство для сортировки" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "Список операторов из семейств операторов" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "Зарегистрированный левый тип" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "Зарегистрированный правый тип" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "Номер" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "Список опорных функций из семейств операторов" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "Большие объекты" -#: help.c:75 +#: help.c:63 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2563,11 +2624,11 @@ msgstr "" "psql - это интерактивный терминал PostgreSQL.\n" "\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:502 msgid "Usage:\n" msgstr "Использование:\n" -#: help.c:77 +#: help.c:65 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2575,11 +2636,11 @@ msgstr "" " psql [ПАРАМЕТР]... [БД [ПОЛЬЗОВАТЕЛЬ]]\n" "\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "Общие параметры:\n" -#: help.c:84 +#: help.c:68 msgid "" " -c, --command=COMMAND run only single command (SQL or internal) and " "exit\n" @@ -2587,23 +2648,19 @@ msgstr "" " -c, --command=КОМАНДА выполнить одну команду (SQL или внутреннюю) и " "выйти\n" -#: help.c:85 -#, c-format -msgid "" -" -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr "" -" -d, --dbname=БД имя подключаемой базы данных (по умолчанию " -"\"%s\")\n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=БД имя целевой базы данных\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=ИМЯ_ФАЙЛА выполнить команды из файла и выйти\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list вывести список баз данных и выйти\n" -#: help.c:89 +#: help.c:72 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2613,16 +2670,16 @@ msgstr "" " присвоить переменной psql ИМЯ заданное ЗНАЧЕНИЕ\n" " (например: -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr "" " -X, --no-psqlrc игнорировать файл параметров запуска (~/.psqlrc)\n" -#: help.c:94 +#: help.c:77 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-" @@ -2632,20 +2689,20 @@ msgstr "" " выполнить как одну транзакцию\n" " (в неинтерактивном режиме)\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=options] показать эту справку и выйти\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands перечислить команды с \\ и выйти\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr "" " --help=variables перечислить специальные переменные и выйти\n" -#: help.c:100 +#: help.c:83 msgid "" "\n" "Input and output options:\n" @@ -2653,54 +2710,54 @@ msgstr "" "\n" "Параметры ввода/вывода:\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all отображать все команды из скрипта\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors отображать команды с ошибками\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries отображать команды, отправляемые серверу\n" -#: help.c:104 +#: help.c:87 msgid "" " -E, --echo-hidden display queries that internal commands generate\n" msgstr "" " -E, --echo-hidden выводить запросы, порождённые внутренними " "командами\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=ИМЯ_ФАЙЛА сохранять протокол работы в файл\n" -#: help.c:106 +#: help.c:89 msgid "" " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr "" " -n, --no-readline отключить редактор командной строки readline\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr "" " -o, --output=ИМЯ_ФАЙЛА направить результаты запроса в файл (или канал " "|)\n" -#: help.c:108 +#: help.c:91 msgid "" " -q, --quiet run quietly (no messages, only query output)\n" msgstr "" " -q, --quiet показывать только результаты запросов, без " "сообщений\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr "" " -s, --single-step пошаговый режим (подтверждение каждого запроса)\n" -#: help.c:110 +#: help.c:93 msgid "" " -S, --single-line single-line mode (end of line terminates SQL " "command)\n" @@ -2708,7 +2765,7 @@ msgstr "" " -S, --single-line однострочный режим (конец строки завершает " "команду)\n" -#: help.c:112 +#: help.c:95 msgid "" "\n" "Output format options:\n" @@ -2716,11 +2773,11 @@ msgstr "" "\n" "Параметры вывода:\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align режим вывода невыровненной таблицы\n" -#: help.c:114 +#: help.c:97 msgid "" " --csv CSV (Comma-Separated Values) table output mode\n" msgstr "" @@ -2728,7 +2785,7 @@ msgstr "" "разделённые\n" " запятыми)\n" -#: help.c:115 +#: help.c:98 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2739,11 +2796,11 @@ msgstr "" " разделителей полей при невыровненном выводе\n" " (по умолчанию: \"%s\")\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html вывод таблицы в формате HTML\n" -#: help.c:119 +#: help.c:102 msgid "" " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset " "command)\n" @@ -2752,7 +2809,7 @@ msgstr "" "ЗНАЧЕНИЕМ)\n" " (см. описание \\pset)\n" -#: help.c:120 +#: help.c:103 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: " @@ -2762,22 +2819,22 @@ msgstr "" " разделитель записей при невыровненном выводе\n" " (по умолчанию: новая строка)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only выводить только кортежи\n" -#: help.c:123 +#: help.c:106 msgid "" " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, " "border)\n" msgstr "" " -T, --table-attr=ТЕКСТ установить атрибуты HTML-таблицы (width, border)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded включить развёрнутый вывод таблицы\n" -#: help.c:125 +#: help.c:108 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero " @@ -2787,7 +2844,7 @@ msgstr "" " сделать разделителем полей при невыровненном\n" " выводе нулевой байт\n" -#: help.c:127 +#: help.c:110 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero " @@ -2797,7 +2854,7 @@ msgstr "" " сделать разделителем записей при невыровненном\n" " нулевой байт\n" -#: help.c:130 +#: help.c:113 msgid "" "\n" "Connection options:\n" @@ -2805,42 +2862,32 @@ msgstr "" "\n" "Параметры подключения:\n" -#: help.c:133 -#, c-format -msgid "" -" -h, --host=HOSTNAME database server host or socket directory " -"(default: \"%s\")\n" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" -" (по умолчанию: \"%s\")\n" - -#: help.c:134 -msgid "local socket" -msgstr "локальный сокет" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr "" -" -p, --port=ПОРТ порт сервера баз данных (по умолчанию: \"%s\")\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=ПОРТ порт сервера баз данных\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr " -U, --username=ИМЯ имя пользователя (по умолчанию: \"%s\")\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=ИМЯ имя пользователя БД\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: help.c:143 +#: help.c:118 msgid "" " -W, --password force password prompt (should happen " "automatically)\n" msgstr "" " -W, --password запрашивать пароль всегда (обычно не требуется)\n" -#: help.c:145 +#: help.c:120 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or " @@ -2856,40 +2903,40 @@ msgstr "" "документации PostgreSQL.\n" "\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Об ошибках сообщайте по адресу <%s>.\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "Общие\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [ПАРАМЕТР]... задать параметры запроса\n" # skip-rule: copyright -#: help.c:193 +#: help.c:168 msgid "" " \\copyright show PostgreSQL usage and distribution terms\n" msgstr "" " \\copyright условия использования и распространения " "PostgreSQL\n" -#: help.c:194 +#: help.c:169 msgid "" " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr "" " \\crosstabview [СТОЛБЦЫ] выполнить запрос и вывести результат в " "перекрёстном виде\n" -#: help.c:195 +#: help.c:170 msgid "" " \\errverbose show most recent error message at maximum " "verbosity\n" @@ -2897,7 +2944,7 @@ msgstr "" " \\errverbose вывести максимально подробное сообщение о " "последней ошибке\n" -#: help.c:196 +#: help.c:171 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2906,13 +2953,13 @@ msgstr "" " или канал |); \\g без аргументов равнозначно \";" "\"\n" -#: help.c:198 +#: help.c:173 msgid "" " \\gdesc describe result of query, without executing it\n" msgstr "" " \\gdesc описать результат запроса, но не выполнять его\n" -#: help.c:199 +#: help.c:174 msgid "" " \\gexec execute query, then execute each value in its " "result\n" @@ -2920,7 +2967,7 @@ msgstr "" " \\gexec выполнить запрос, а затем выполнить каждую строку " "в результате\n" -#: help.c:200 +#: help.c:175 msgid "" " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr "" @@ -2928,56 +2975,60 @@ msgstr "" "переменных\n" " psql\n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr "" " \\gx [(ПАРАМЕТРЫ)] [ФАЙЛ] то же, что \\g, но в режиме развёрнутого вывода\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q выйти из psql\n" -#: help.c:203 +#: help.c:178 msgid "" -" \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" msgstr "" -" \\watch [[i=]СЕК] [c=N] повторять запрос через заданное число секунд, не\n" -" более N раз\n" +" \\watch [[i=]СЕК] [c=N] [m=MIN]\n" +" повторять запрос через заданное число секунд, не " +"более\n" +" N раз, остановиться, если получено менее MIN строк\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "Справка\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commands] справка по командам psql c \\\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr "" " \\? options справка по параметрам командной строки psql\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables справка по специальным переменным\n" -#: help.c:211 +#: help.c:188 msgid "" " \\h [NAME] help on syntax of SQL commands, * for all " "commands\n" msgstr "" " \\h [ИМЯ] справка по заданному SQL-оператору; * - по всем\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "Буфер запроса\n" -#: help.c:215 +#: help.c:192 msgid "" " \\e [FILE] [LINE] edit the query buffer (or file) with external " "editor\n" @@ -2985,45 +3036,45 @@ msgstr "" " \\e [ФАЙЛ] [СТРОКА] править буфер запроса (или файл) во внешнем " "редакторе\n" -#: help.c:216 +#: help.c:193 msgid "" " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr "" " \\ef [ФУНКЦИЯ [СТРОКА]] править определение функции во внешнем редакторе\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr "" " \\ev [VIEWNAME [LINE]] править определение представления во внешнем " "редакторе\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p вывести содержимое буфера запросов\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r очистить буфер запроса\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [ФАЙЛ] вывести историю или сохранить её в файл\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr " \\w ФАЙЛ записать буфер запроса в файл\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "Ввод/Вывод\n" -#: help.c:227 +#: help.c:204 msgid "" " \\copy ... perform SQL COPY with data stream to the client " "host\n" msgstr " \\copy ... выполнить SQL COPY на стороне клиента\n" -#: help.c:228 +#: help.c:205 msgid "" " \\echo [-n] [STRING] write string to standard output (-n for no " "newline)\n" @@ -3031,11 +3082,11 @@ msgstr "" " \\echo [-n] [СТРОКА] записать строку в поток стандартного вывода\n" " (-n отключает перевод строки)\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i ФАЙЛ выполнить команды из файла\n" -#: help.c:230 +#: help.c:207 msgid "" " \\ir FILE as \\i, but relative to location of current " "script\n" @@ -3043,13 +3094,13 @@ msgstr "" " \\ir ФАЙЛ подобно \\i, но путь задаётся относительно\n" " текущего скрипта\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr "" " \\o [ФАЙЛ] выводить все результаты запросов в файл или канал " "|\n" -#: help.c:232 +#: help.c:209 msgid "" " \\qecho [-n] [STRING] write string to \\o output stream (-n for no " "newline)\n" @@ -3057,7 +3108,7 @@ msgstr "" " \\qecho [-n] [СТРОКА] записать строку в выходной поток \\o\n" " (-n отключает перевод строки)\n" -#: help.c:233 +#: help.c:210 msgid "" " \\warn [-n] [STRING] write string to standard error (-n for no " "newline)\n" @@ -3065,136 +3116,136 @@ msgstr "" " \\warn [-n] [СТРОКА] записать строку в поток вывода ошибок\n" " (-n отключает перевод строки)\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "Условия\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if ВЫРАЖЕНИЕ начало блока условия\n" -#: help.c:238 +#: help.c:215 msgid "" " \\elif EXPR alternative within current conditional block\n" msgstr "" " \\elif ВЫРАЖЕНИЕ альтернативная ветвь в текущем блоке условия\n" -#: help.c:239 +#: help.c:216 msgid "" " \\else final alternative within current conditional " "block\n" msgstr "" " \\else окончательная ветвь в текущем блоке условия\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif конец блока условия\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "Информационные\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr "" " (дополнения: S = показывать системные объекты, + = дополнительные " "подробности)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr "" " \\d[S+] список таблиц, представлений и " "последовательностей\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr "" " \\d[S+] ИМЯ описание таблицы, представления, " "последовательности\n" " или индекса\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" msgstr " \\da[S] [МАСКА] список агрегатных функций\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [МАСКА] список методов доступа\n" # well-spelled: МСК -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [МСК_МД [МСК_ТИПА]] список классов операторов\n" # well-spelled: МСК -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [МСК_МД [МСК_ТИПА]] список семейств операторов\n" # well-spelled: МСК -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr "" " \\dAo[+] [МСК_МД [МСК_СОП]] список операторов из семейств операторов\n" # well-spelled: МСК -#: help.c:252 +#: help.c:229 msgid "" " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [МСК_МД [МСК_СОП]] список опорных функций из семейств\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [МАСКА] список табличных пространств\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [МАСКА] список преобразований\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [МАСКА] список параметров конфигурации\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [МАСКА] список приведений типов\n" -#: help.c:257 +#: help.c:234 msgid "" " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr "" " \\dd[S] [МАСКА] описания объектов, не выводимые в других режимах\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [МАСКА] список доменов\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [МАСКА] список прав по умолчанию\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [МАСКА] список сторонних таблиц\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [МАСКА] список сторонних серверов\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\det[+] [МАСКА] список сторонних таблиц\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [МАСКА] список сопоставлений пользователей\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [МАСКА] список обёрток сторонних данных\n" # well-spelled: МСК, ФУНК -#: help.c:265 +#: help.c:242 msgid "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] " @@ -3204,49 +3255,49 @@ msgstr "" " список функций [только агрегатных/обычных/процедур/" "триггеров/оконных]\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr " \\dF[+] [МАСКА] список конфигураций текстового поиска\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr " \\dFd[+] [МАСКА] список словарей текстового поиска\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr " \\dFp[+] [МАСКА] список анализаторов текстового поиска\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr " \\dFt[+] [МАСКА] список шаблонов текстового поиска\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [МАСКА] список ролей\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [МАСКА] список индексов\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr "" " \\dl[+] список больших объектов (то же, что и \\lo_list)\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [МАСКА] список языков процедур\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [МАСКА] список материализованных представлений\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [МАСКА] список схем\n" # well-spelled: МСК -#: help.c:277 +#: help.c:254 msgid "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" @@ -3254,18 +3305,18 @@ msgstr "" " \\do[S+] [МСК_ОП [МСК_ТИПА [МСК_ТИПА]]]\n" " список операторов\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S+] [МАСКА] список правил сортировки\n" -#: help.c:280 +#: help.c:257 msgid "" " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr "" " \\dp[S] [МАСКА] список прав доступа к таблицам, представлениям и\n" " последовательностям\n" -#: help.c:281 +#: help.c:258 msgid "" " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations " "[n=nested]\n" @@ -3275,80 +3326,80 @@ msgstr "" "(n)\n" # well-spelled: МСК -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr " \\drds [МСК_РОЛИ [МСК_БД]] список параметров роли на уровне БД\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\drg[S] [МАСКА] список назначений ролей\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[+] [МАСКА] список публикаций для репликации\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [МАСКА] список подписок на репликацию\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [МАСКА] список последовательностей\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [МАСКА] список таблиц\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [МАСКА] список типов данных\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [МАСКА] список ролей\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [МАСКА] список представлений\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [МАСКА] список расширений\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [МАСКА] список расширенных статистик\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [МАСКА] список событийных триггеров\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [МАСКА] список баз данных\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] ИМЯ_ФУНКЦИИ показать определение функции\n" # well-spelled: ПРЕДСТ -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv[+] ИМЯ_ПРЕДСТ показать определение представления\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [МАСКА] то же, что и \\dp\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "Большие объекты\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr " \\lo_export OID_БО ФАЙЛ записать большой объект в файл\n" -#: help.c:302 +#: help.c:279 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3356,32 +3407,32 @@ msgstr "" " \\lo_import ФАЙЛ [КОММЕНТАРИЙ]\n" " прочитать большой объект из файла\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\lo_list[+] список больших объектов\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink OID_БО удалить большой объект\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "Форматирование\n" -#: help.c:309 +#: help.c:286 msgid "" " \\a toggle between unaligned and aligned output mode\n" msgstr "" " \\a переключение режимов вывода:\n" " неформатированный/выровненный\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr "" " \\C [СТРОКА] задать заголовок таблицы или убрать, если не " "задан\n" -#: help.c:311 +#: help.c:288 msgid "" " \\f [STRING] show or set field separator for unaligned query " "output\n" @@ -3389,13 +3440,13 @@ msgstr "" " \\f [СТРОКА] показать или установить разделитель полей для\n" " неформатированного вывода\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr "" " \\H переключить режим вывода в HTML (текущий: %s)\n" -#: help.c:314 +#: help.c:291 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3403,7 +3454,7 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [ИМЯ [ЗНАЧЕНИЕ]] установить параметр вывода таблицы\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3411,91 +3462,91 @@ msgstr "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] режим вывода только строк (сейчас: %s)\n" -#: help.c:323 +#: help.c:300 msgid "" " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr "" " \\T [СТРОКА] задать атрибуты для
или убрать, если не " "заданы\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr "" -" \\x [on|off|auto] переключить режим расширенного вывода (сейчас: " +" \\x [on|off|auto] переключить режим развёрнутого вывода (сейчас: " "%s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "auto" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "Соединение\n" -#: help.c:330 +#: help.c:307 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently \"%s\")\n" msgstr "" -" \\c[onnect] {[БД|- ПОЛЬЗОВАТЕЛЬ|- СЕРВЕР|- ПОРТ|-] | conninfo}\n" +" \\c[onnect] {[БД|- ПОЛЬЗОВАТЕЛЬ|- КОМПЬЮТЕР|- ПОРТ|-] | conninfo}\n" " подключиться к другой базе данных\n" " (текущая: \"%s\")\n" -#: help.c:334 +#: help.c:311 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" msgstr "" -" \\c[onnect] {[БД|- ПОЛЬЗОВАТЕЛЬ|- СЕРВЕР|- ПОРТ|-] | conninfo}\n" +" \\c[onnect] {[БД|- ПОЛЬЗОВАТЕЛЬ|- КОМПЬЮТЕР|- ПОРТ|-] | conninfo}\n" " подключиться к другой базе данных\n" " (сейчас подключения нет)\n" -#: help.c:336 +#: help.c:313 msgid "" " \\conninfo display information about current connection\n" msgstr " \\conninfo информация о текущем соединении\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [КОДИРОВКА] показать/установить клиентскую кодировку\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr " \\password [ИМЯ] безопасно сменить пароль пользователя\n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "Операционная система\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [ПУТЬ] сменить текущий каталог\n" # well-spelled: ОКР -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv ПЕР_PSQL ПЕР_ОКР прочитать переменную окружения\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr "" " \\setenv ИМЯ [ЗНАЧЕНИЕ] установить или сбросить переменную окружения\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] включить/выключить секундомер (сейчас: %s)\n" -#: help.c:347 +#: help.c:324 msgid "" " \\! [COMMAND] execute command in shell or start interactive " "shell\n" @@ -3503,17 +3554,17 @@ msgstr "" " \\! [КОМАНДА] выполнить команду в командной оболочке\n" " или запустить интерактивную оболочку\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "Переменные\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr "" " \\prompt [ТЕКСТ] ИМЯ предложить пользователю задать внутреннюю " "переменную\n" -#: help.c:352 +#: help.c:329 msgid "" " \\set [NAME [VALUE]] set internal variable, or list all if no " "parameters\n" @@ -3521,11 +3572,11 @@ msgstr "" " \\set [ИМЯ [ЗНАЧЕНИЕ]] установить внутреннюю переменную или вывести все,\n" " если имя не задано\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset ИМЯ сбросить (удалить) внутреннюю переменную\n" -#: help.c:392 +#: help.c:369 msgid "" "List of specially treated variables\n" "\n" @@ -3533,11 +3584,11 @@ msgstr "" "Список специальных переменных\n" "\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "Переменные psql:\n" -#: help.c:396 +#: help.c:373 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3547,7 +3598,7 @@ msgstr "" " или \\set ИМЯ ЗНАЧЕНИЕ в приглашении psql\n" "\n" -#: help.c:398 +#: help.c:375 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3555,7 +3606,7 @@ msgstr "" " AUTOCOMMIT\n" " если установлен, успешные SQL-команды фиксируются автоматически\n" -#: help.c:400 +#: help.c:377 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3567,7 +3618,7 @@ msgstr "" " preserve-lower (сохранять нижний),\n" " preserve-upper (сохранять верхний)]\n" -#: help.c:403 +#: help.c:380 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3575,7 +3626,7 @@ msgstr "" " DBNAME\n" " имя текущей подключённой базы данных\n" -#: help.c:405 +#: help.c:382 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3586,7 +3637,7 @@ msgstr "" " [all (всё), errors (ошибки), none (ничего),\n" " queries (запросы)]\n" -#: help.c:408 +#: help.c:385 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3596,7 +3647,7 @@ msgstr "" " если включено, выводит внутренние запросы, порождаемые командами с \\;\n" " если установлено значение \"noexec\", они выводятся, но не выполняются\n" -#: help.c:411 +#: help.c:388 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3604,7 +3655,7 @@ msgstr "" " ENCODING\n" " текущая кодировка клиентского набора символов\n" -#: help.c:413 +#: help.c:390 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3612,7 +3663,7 @@ msgstr "" " ERROR\n" " \"true\" в случае ошибки в последнем запросе, иначе — \"false\"\n" -#: help.c:415 +#: help.c:392 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = " @@ -3622,7 +3673,7 @@ msgstr "" " число результирующих строк, извлекаемых и отображаемых за раз\n" " (0 = без ограничений)\n" -#: help.c:417 +#: help.c:394 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3630,7 +3681,7 @@ msgstr "" " HIDE_TABLEAM\n" " если установлено, табличные методы доступа не выводятся\n" -#: help.c:419 +#: help.c:396 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3638,7 +3689,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " если установлено, методы сжатия не выводятся\n" -#: help.c:421 +#: help.c:398 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3647,7 +3698,7 @@ msgstr "" " управляет историей команд [ignorespace (игнорировать пробелы),\n" " ignoredups (игнорировать дубли), ignoreboth (и то, и другое)]\n" -#: help.c:423 +#: help.c:400 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3655,7 +3706,7 @@ msgstr "" " HISTFILE\n" " имя файла, в котором будет сохраняться история команд\n" -#: help.c:425 +#: help.c:402 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3663,15 +3714,15 @@ msgstr "" " HISTSIZE\n" " максимальное число команд, сохраняемых в истории\n" -#: help.c:427 +#: help.c:404 msgid "" " HOST\n" " the currently connected database server host\n" msgstr "" " HOST\n" -" сервер баз данных, к которому установлено подключение\n" +" компьютер с сервером баз данных, к которому установлено подключение\n" -#: help.c:429 +#: help.c:406 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3679,7 +3730,7 @@ msgstr "" " IGNOREEOF\n" " количество EOF для завершения интерактивного сеанса\n" -#: help.c:431 +#: help.c:408 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3687,7 +3738,7 @@ msgstr "" " LASTOID\n" " значение последнего задействованного OID\n" -#: help.c:433 +#: help.c:410 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3700,7 +3751,7 @@ msgstr "" "\"00000\",\n" " если ошибки не было\n" -#: help.c:436 +#: help.c:413 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3709,7 +3760,7 @@ msgstr "" " если установлено, транзакция не прекращается при ошибке\n" " (используются неявные точки сохранения)\n" -#: help.c:438 +#: help.c:415 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3717,7 +3768,7 @@ msgstr "" " ON_ERROR_STOP\n" " останавливать выполнение пакета команд после ошибки\n" -#: help.c:440 +#: help.c:417 msgid "" " PORT\n" " server port of the current connection\n" @@ -3725,7 +3776,7 @@ msgstr "" " PORT\n" " порт сервера для текущего соединения\n" -#: help.c:442 +#: help.c:419 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3733,7 +3784,7 @@ msgstr "" " PROMPT1\n" " устанавливает стандартное приглашение psql\n" -#: help.c:444 +#: help.c:421 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous " @@ -3743,7 +3794,7 @@ msgstr "" " устанавливает приглашение, которое выводится при переносе оператора\n" " на новую строку\n" -#: help.c:446 +#: help.c:423 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3751,7 +3802,7 @@ msgstr "" " PROMPT3\n" " устанавливает приглашение для выполнения COPY ... FROM STDIN\n" -#: help.c:448 +#: help.c:425 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3759,7 +3810,7 @@ msgstr "" " QUIET\n" " выводить минимум сообщений (как и с параметром -q)\n" -#: help.c:450 +#: help.c:427 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3768,7 +3819,7 @@ msgstr "" " число строк, возвращённых или обработанных последним SQL-запросом, либо " "0\n" -#: help.c:452 +#: help.c:429 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3778,7 +3829,7 @@ msgstr "" " SERVER_VERSION_NUM\n" " версия сервера (в коротком текстовом и числовом формате)\n" -#: help.c:455 +#: help.c:432 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3787,7 +3838,7 @@ msgstr "" " \"true\" в случае ошибки последней команды оболочки, \"false\" в ином " "случае\n" -#: help.c:457 +#: help.c:434 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3795,7 +3846,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " код завершения последней команды оболочки\n" -#: help.c:459 +#: help.c:436 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3804,7 +3855,7 @@ msgstr "" " выводить все результаты объединённых запросов (\\;), а не только " "последнего\n" -#: help.c:461 +#: help.c:438 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3813,7 +3864,7 @@ msgstr "" " управляет отображением полей контекста сообщений\n" " [never (не отображать никогда), errors (ошибки), always (всегда]\n" -#: help.c:463 +#: help.c:440 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3822,7 +3873,7 @@ msgstr "" " если установлено, конец строки завершает режим ввода SQL-команды\n" " (как и с параметром -S)\n" -#: help.c:465 +#: help.c:442 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3830,7 +3881,7 @@ msgstr "" " SINGLESTEP\n" " пошаговый режим (как и с параметром -s)\n" -#: help.c:467 +#: help.c:444 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3839,7 +3890,7 @@ msgstr "" " SQLSTATE последнего запроса или \"00000\", если он выполнился без " "ошибок\n" -#: help.c:469 +#: help.c:446 msgid "" " USER\n" " the currently connected database user\n" @@ -3847,7 +3898,7 @@ msgstr "" " USER\n" " текущий пользователь, подключённый к БД\n" -#: help.c:471 +#: help.c:448 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3856,7 +3907,7 @@ msgstr "" " управляет детализацией отчётов об ошибках [default (по умолчанию),\n" " verbose (подробно), terse (кратко), sqlstate (код состояния)]\n" -#: help.c:473 +#: help.c:450 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3868,7 +3919,7 @@ msgstr "" " VERSION_NUM\n" " версия psql (в развёрнутом, в коротком текстовом и в числовом формате)\n" -#: help.c:478 +#: help.c:455 msgid "" "\n" "Display settings:\n" @@ -3876,7 +3927,7 @@ msgstr "" "\n" "Параметры отображения:\n" -#: help.c:480 +#: help.c:457 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3886,7 +3937,7 @@ msgstr "" " или \\pset ИМЯ [ЗНАЧЕНИЕ] в приглашении psql\n" "\n" -#: help.c:482 +#: help.c:459 msgid "" " border\n" " border style (number)\n" @@ -3894,7 +3945,7 @@ msgstr "" " border\n" " стиль границы (число)\n" -#: help.c:484 +#: help.c:461 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3902,15 +3953,15 @@ msgstr "" " columns\n" " целевая ширина для формата с переносом\n" -#: help.c:486 +#: help.c:463 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" msgstr "" " expanded (или x)\n" -" расширенный вывод [on (вкл.), off (выкл.), auto (авто)]\n" +" развёрнутый вывод [on (вкл.), off (выкл.), auto (авто)]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid "" " fieldsep\n" @@ -3919,7 +3970,7 @@ msgstr "" " fieldsep\n" " разделитель полей для неформатированного вывода (по умолчанию \"%s\")\n" -#: help.c:491 +#: help.c:468 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3927,7 +3978,7 @@ msgstr "" " fieldsep_zero\n" " устанавливает ноль разделителем полей при неформатированном выводе\n" -#: help.c:493 +#: help.c:470 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3935,7 +3986,7 @@ msgstr "" " footer\n" " включает или выключает вывод подписей таблицы [on (вкл.), off (выкл.)]\n" -#: help.c:495 +#: help.c:472 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3945,7 +3996,7 @@ msgstr "" "\n" " aligned (выровненный), wrapped (с переносом), html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3953,7 +4004,7 @@ msgstr "" " linestyle\n" " задаёт стиль рисования линий границы [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3961,7 +4012,7 @@ msgstr "" " null\n" " устанавливает строку, выводимую вместо значения NULL\n" -#: help.c:501 +#: help.c:478 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of " @@ -3970,7 +4021,7 @@ msgstr "" " numericlocale\n" " отключает вывод заданного локалью разделителя группы цифр\n" -#: help.c:503 +#: help.c:480 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3979,7 +4030,7 @@ msgstr "" " определяет, используется ли внешний постраничник\n" " [yes (да), no (нет), always (всегда)]\n" -#: help.c:505 +#: help.c:482 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3987,7 +4038,7 @@ msgstr "" " recordsep\n" " разделитель записей (строк) при неформатированном выводе\n" -#: help.c:507 +#: help.c:484 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3995,7 +4046,7 @@ msgstr "" " recordsep_zero\n" " устанавливает ноль разделителем записей при неформатированном выводе\n" -#: help.c:509 +#: help.c:486 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -4005,7 +4056,7 @@ msgstr "" " задаёт атрибуты для тега table в формате html или пропорциональные\n" " ширины столбцов для выровненных влево данных, в формате latex-longtable\n" -#: help.c:512 +#: help.c:489 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -4013,7 +4064,7 @@ msgstr "" " title\n" " задаёт заголовок таблицы для последовательно печатаемых таблиц\n" -#: help.c:514 +#: help.c:491 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -4021,7 +4072,7 @@ msgstr "" " tuples_only\n" " если установлено, выводятся только непосредственно табличные данные\n" -#: help.c:516 +#: help.c:493 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -4034,7 +4085,17 @@ msgstr "" " задаёт стиль рисуемых линий Unicode [single (одинарные), double " "(двойные)]\n" -#: help.c:521 +#: help.c:497 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" задаёт максимальную ширину заголовка для развёрнутого вывода\n" +" [full (полностью), column (столбец), page (страница), целое значение]\n" + +#: help.c:501 msgid "" "\n" "Environment variables:\n" @@ -4042,7 +4103,7 @@ msgstr "" "\n" "Переменные окружения:\n" -#: help.c:525 +#: help.c:505 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -4052,7 +4113,7 @@ msgstr "" " или \\setenv ИМЯ [ЗНАЧЕНИЕ] в приглашении psql\n" "\n" -#: help.c:527 +#: help.c:507 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -4064,7 +4125,7 @@ msgstr "" " или \\setenv ИМЯ ЗНАЧЕНИЕ в приглашении psql\n" "\n" -#: help.c:530 +#: help.c:510 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -4072,7 +4133,7 @@ msgstr "" " COLUMNS\n" " число столбцов для форматирования с переносом\n" -#: help.c:532 +#: help.c:512 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -4080,7 +4141,7 @@ msgstr "" " PGAPPNAME\n" " синоним параметра подключения application_name\n" -#: help.c:534 +#: help.c:514 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -4088,7 +4149,7 @@ msgstr "" " PGDATABASE\n" " синоним параметра подключения dbname\n" -#: help.c:536 +#: help.c:516 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -4096,7 +4157,7 @@ msgstr "" " PGHOST\n" " синоним параметра подключения host\n" -#: help.c:538 +#: help.c:518 msgid "" " PGPASSFILE\n" " password file name\n" @@ -4104,7 +4165,7 @@ msgstr "" " PGPASSFILE\n" " имя файла с паролем\n" -#: help.c:540 +#: help.c:520 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -4112,7 +4173,7 @@ msgstr "" " PGPASSWORD\n" " пароль для подключения (использовать не рекомендуется)\n" -#: help.c:542 +#: help.c:522 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -4120,7 +4181,7 @@ msgstr "" " PGPORT\n" " синоним параметра подключения port\n" -#: help.c:544 +#: help.c:524 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -4128,7 +4189,7 @@ msgstr "" " PGUSER\n" " синоним параметра подключения user\n" -#: help.c:546 +#: help.c:526 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -4136,7 +4197,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " редактор, вызываемый командами \\e, \\ef и \\ev\n" -#: help.c:548 +#: help.c:528 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -4144,7 +4205,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " определяет способ передачи номера строки при вызове редактора\n" -#: help.c:550 +#: help.c:530 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -4152,7 +4213,7 @@ msgstr "" " PSQL_HISTORY\n" " альтернативное размещение файла с историей команд\n" -#: help.c:552 +#: help.c:532 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -4160,7 +4221,7 @@ msgstr "" " PSQL_PAGER, PAGER\n" " имя программы внешнего постраничника\n" -#: help.c:555 +#: help.c:535 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -4168,7 +4229,7 @@ msgstr "" " PSQL_WATCH_PAGER\n" " имя программы внешнего постраничника для \\watch\n" -#: help.c:558 +#: help.c:538 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -4176,7 +4237,7 @@ msgstr "" " PSQLRC\n" " альтернативное размещение пользовательского файла .psqlrc\n" -#: help.c:560 +#: help.c:540 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -4184,7 +4245,7 @@ msgstr "" " SHELL\n" " оболочка, вызываемая командой \\!\n" -#: help.c:562 +#: help.c:542 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -4192,11 +4253,11 @@ msgstr "" " TMPDIR\n" " каталог для временных файлов\n" -#: help.c:622 +#: help.c:602 msgid "Available help:\n" msgstr "Имеющаяся справка:\n" -#: help.c:717 +#: help.c:697 #, c-format msgid "" "Command: %s\n" @@ -4215,7 +4276,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:740 +#: help.c:720 #, c-format msgid "" "No help available for \"%s\".\n" @@ -4224,17 +4285,17 @@ msgstr "" "Нет справки по команде \"%s\".\n" "Попробуйте \\h без аргументов и посмотрите, что есть.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "не удалось прочитать входной файл: %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "не удалось сохранить историю в файле \"%s\": %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "в данной среде история не поддерживается" @@ -4327,12 +4388,12 @@ msgstr "" msgid "reached EOF without finding closing \\endif(s)" msgstr "в закончившемся потоке команд не хватает \\endif" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "незавершённая строка в кавычках" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s: нехватка памяти" @@ -4340,202 +4401,202 @@ msgstr "%s: нехватка памяти" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:240 -#: sql_help.c:242 sql_help.c:243 sql_help.c:245 sql_help.c:247 sql_help.c:250 -#: sql_help.c:252 sql_help.c:254 sql_help.c:256 sql_help.c:268 sql_help.c:269 -#: sql_help.c:270 sql_help.c:272 sql_help.c:321 sql_help.c:323 sql_help.c:325 -#: sql_help.c:327 sql_help.c:396 sql_help.c:401 sql_help.c:403 sql_help.c:445 -#: sql_help.c:447 sql_help.c:450 sql_help.c:452 sql_help.c:521 sql_help.c:526 -#: sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:595 sql_help.c:597 -#: sql_help.c:599 sql_help.c:601 sql_help.c:603 sql_help.c:606 sql_help.c:608 -#: sql_help.c:611 sql_help.c:622 sql_help.c:624 sql_help.c:668 sql_help.c:670 -#: sql_help.c:672 sql_help.c:675 sql_help.c:677 sql_help.c:679 sql_help.c:716 -#: sql_help.c:720 sql_help.c:724 sql_help.c:743 sql_help.c:746 sql_help.c:749 -#: sql_help.c:778 sql_help.c:790 sql_help.c:798 sql_help.c:801 sql_help.c:804 -#: sql_help.c:819 sql_help.c:822 sql_help.c:851 sql_help.c:856 sql_help.c:861 -#: sql_help.c:866 sql_help.c:871 sql_help.c:898 sql_help.c:900 sql_help.c:902 -#: sql_help.c:904 sql_help.c:907 sql_help.c:909 sql_help.c:956 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1040 sql_help.c:1051 sql_help.c:1053 sql_help.c:1073 -#: sql_help.c:1083 sql_help.c:1084 sql_help.c:1086 sql_help.c:1088 -#: sql_help.c:1100 sql_help.c:1104 sql_help.c:1106 sql_help.c:1118 -#: sql_help.c:1120 sql_help.c:1122 sql_help.c:1124 sql_help.c:1143 -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 sql_help.c:1157 -#: sql_help.c:1160 sql_help.c:1161 sql_help.c:1162 sql_help.c:1165 -#: sql_help.c:1168 sql_help.c:1170 sql_help.c:1309 sql_help.c:1311 -#: sql_help.c:1314 sql_help.c:1317 sql_help.c:1319 sql_help.c:1321 -#: sql_help.c:1324 sql_help.c:1327 sql_help.c:1447 sql_help.c:1449 -#: sql_help.c:1451 sql_help.c:1454 sql_help.c:1475 sql_help.c:1478 -#: sql_help.c:1481 sql_help.c:1484 sql_help.c:1488 sql_help.c:1490 -#: sql_help.c:1492 sql_help.c:1494 sql_help.c:1508 sql_help.c:1511 -#: sql_help.c:1513 sql_help.c:1515 sql_help.c:1525 sql_help.c:1527 -#: sql_help.c:1537 sql_help.c:1539 sql_help.c:1549 sql_help.c:1552 -#: sql_help.c:1575 sql_help.c:1577 sql_help.c:1579 sql_help.c:1581 -#: sql_help.c:1584 sql_help.c:1586 sql_help.c:1589 sql_help.c:1592 -#: sql_help.c:1643 sql_help.c:1686 sql_help.c:1689 sql_help.c:1691 -#: sql_help.c:1693 sql_help.c:1696 sql_help.c:1698 sql_help.c:1700 -#: sql_help.c:1703 sql_help.c:1755 sql_help.c:1771 sql_help.c:2004 -#: sql_help.c:2073 sql_help.c:2092 sql_help.c:2105 sql_help.c:2163 -#: sql_help.c:2171 sql_help.c:2181 sql_help.c:2208 sql_help.c:2240 -#: sql_help.c:2258 sql_help.c:2286 sql_help.c:2397 sql_help.c:2443 -#: sql_help.c:2468 sql_help.c:2491 sql_help.c:2495 sql_help.c:2529 -#: sql_help.c:2549 sql_help.c:2571 sql_help.c:2585 sql_help.c:2606 -#: sql_help.c:2635 sql_help.c:2670 sql_help.c:2695 sql_help.c:2742 -#: sql_help.c:3040 sql_help.c:3053 sql_help.c:3070 sql_help.c:3086 -#: sql_help.c:3126 sql_help.c:3180 sql_help.c:3184 sql_help.c:3186 -#: sql_help.c:3193 sql_help.c:3212 sql_help.c:3239 sql_help.c:3274 -#: sql_help.c:3286 sql_help.c:3295 sql_help.c:3339 sql_help.c:3353 -#: sql_help.c:3381 sql_help.c:3389 sql_help.c:3401 sql_help.c:3411 -#: sql_help.c:3419 sql_help.c:3427 sql_help.c:3435 sql_help.c:3443 -#: sql_help.c:3452 sql_help.c:3463 sql_help.c:3471 sql_help.c:3479 -#: sql_help.c:3487 sql_help.c:3495 sql_help.c:3505 sql_help.c:3514 -#: sql_help.c:3523 sql_help.c:3531 sql_help.c:3541 sql_help.c:3552 -#: sql_help.c:3560 sql_help.c:3569 sql_help.c:3580 sql_help.c:3589 -#: sql_help.c:3597 sql_help.c:3605 sql_help.c:3613 sql_help.c:3621 -#: sql_help.c:3629 sql_help.c:3637 sql_help.c:3645 sql_help.c:3653 -#: sql_help.c:3661 sql_help.c:3669 sql_help.c:3686 sql_help.c:3695 -#: sql_help.c:3703 sql_help.c:3720 sql_help.c:3735 sql_help.c:4047 -#: sql_help.c:4161 sql_help.c:4190 sql_help.c:4206 sql_help.c:4208 -#: sql_help.c:4711 sql_help.c:4759 sql_help.c:4917 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:245 +#: sql_help.c:247 sql_help.c:248 sql_help.c:250 sql_help.c:252 sql_help.c:255 +#: sql_help.c:257 sql_help.c:259 sql_help.c:261 sql_help.c:276 sql_help.c:277 +#: sql_help.c:278 sql_help.c:280 sql_help.c:329 sql_help.c:331 sql_help.c:333 +#: sql_help.c:335 sql_help.c:404 sql_help.c:409 sql_help.c:411 sql_help.c:453 +#: sql_help.c:455 sql_help.c:458 sql_help.c:460 sql_help.c:529 sql_help.c:534 +#: sql_help.c:539 sql_help.c:544 sql_help.c:549 sql_help.c:603 sql_help.c:605 +#: sql_help.c:607 sql_help.c:609 sql_help.c:611 sql_help.c:614 sql_help.c:616 +#: sql_help.c:619 sql_help.c:630 sql_help.c:632 sql_help.c:676 sql_help.c:678 +#: sql_help.c:680 sql_help.c:683 sql_help.c:685 sql_help.c:687 sql_help.c:728 +#: sql_help.c:732 sql_help.c:736 sql_help.c:757 sql_help.c:760 sql_help.c:763 +#: sql_help.c:792 sql_help.c:804 sql_help.c:812 sql_help.c:815 sql_help.c:818 +#: sql_help.c:833 sql_help.c:836 sql_help.c:865 sql_help.c:870 sql_help.c:875 +#: sql_help.c:880 sql_help.c:885 sql_help.c:912 sql_help.c:914 sql_help.c:916 +#: sql_help.c:918 sql_help.c:921 sql_help.c:923 sql_help.c:970 sql_help.c:1015 +#: sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 sql_help.c:1035 +#: sql_help.c:1054 sql_help.c:1065 sql_help.c:1067 sql_help.c:1087 +#: sql_help.c:1097 sql_help.c:1098 sql_help.c:1100 sql_help.c:1102 +#: sql_help.c:1114 sql_help.c:1118 sql_help.c:1120 sql_help.c:1132 +#: sql_help.c:1134 sql_help.c:1136 sql_help.c:1138 sql_help.c:1157 +#: sql_help.c:1159 sql_help.c:1163 sql_help.c:1167 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1175 sql_help.c:1176 sql_help.c:1179 +#: sql_help.c:1182 sql_help.c:1184 sql_help.c:1324 sql_help.c:1326 +#: sql_help.c:1329 sql_help.c:1332 sql_help.c:1334 sql_help.c:1336 +#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1464 sql_help.c:1466 +#: sql_help.c:1468 sql_help.c:1471 sql_help.c:1492 sql_help.c:1495 +#: sql_help.c:1498 sql_help.c:1501 sql_help.c:1505 sql_help.c:1507 +#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1525 sql_help.c:1528 +#: sql_help.c:1530 sql_help.c:1532 sql_help.c:1542 sql_help.c:1544 +#: sql_help.c:1554 sql_help.c:1556 sql_help.c:1566 sql_help.c:1569 +#: sql_help.c:1592 sql_help.c:1594 sql_help.c:1596 sql_help.c:1598 +#: sql_help.c:1601 sql_help.c:1603 sql_help.c:1606 sql_help.c:1609 +#: sql_help.c:1660 sql_help.c:1703 sql_help.c:1706 sql_help.c:1708 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:1715 sql_help.c:1717 +#: sql_help.c:1720 sql_help.c:1770 sql_help.c:1786 sql_help.c:2019 +#: sql_help.c:2088 sql_help.c:2107 sql_help.c:2120 sql_help.c:2178 +#: sql_help.c:2186 sql_help.c:2196 sql_help.c:2224 sql_help.c:2257 +#: sql_help.c:2275 sql_help.c:2303 sql_help.c:2414 sql_help.c:2460 +#: sql_help.c:2485 sql_help.c:2508 sql_help.c:2512 sql_help.c:2546 +#: sql_help.c:2566 sql_help.c:2588 sql_help.c:2602 sql_help.c:2623 +#: sql_help.c:2652 sql_help.c:2685 sql_help.c:2708 sql_help.c:2755 +#: sql_help.c:3053 sql_help.c:3066 sql_help.c:3083 sql_help.c:3099 +#: sql_help.c:3139 sql_help.c:3193 sql_help.c:3197 sql_help.c:3199 +#: sql_help.c:3206 sql_help.c:3225 sql_help.c:3252 sql_help.c:3287 +#: sql_help.c:3299 sql_help.c:3308 sql_help.c:3352 sql_help.c:3366 +#: sql_help.c:3394 sql_help.c:3402 sql_help.c:3414 sql_help.c:3424 +#: sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 sql_help.c:3456 +#: sql_help.c:3465 sql_help.c:3476 sql_help.c:3484 sql_help.c:3492 +#: sql_help.c:3500 sql_help.c:3508 sql_help.c:3518 sql_help.c:3527 +#: sql_help.c:3536 sql_help.c:3544 sql_help.c:3554 sql_help.c:3565 +#: sql_help.c:3573 sql_help.c:3582 sql_help.c:3593 sql_help.c:3602 +#: sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 sql_help.c:3634 +#: sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 sql_help.c:3666 +#: sql_help.c:3674 sql_help.c:3682 sql_help.c:3699 sql_help.c:3708 +#: sql_help.c:3716 sql_help.c:3733 sql_help.c:3748 sql_help.c:4061 +#: sql_help.c:4182 sql_help.c:4211 sql_help.c:4227 sql_help.c:4229 +#: sql_help.c:4733 sql_help.c:4781 sql_help.c:4940 msgid "name" msgstr "имя" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:332 sql_help.c:1852 -#: sql_help.c:3354 sql_help.c:4479 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:340 sql_help.c:1863 +#: sql_help.c:3367 sql_help.c:4500 msgid "aggregate_signature" msgstr "сигнатура_агр_функции" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:255 -#: sql_help.c:273 sql_help.c:404 sql_help.c:451 sql_help.c:530 sql_help.c:578 -#: sql_help.c:596 sql_help.c:623 sql_help.c:676 sql_help.c:745 sql_help.c:800 -#: sql_help.c:821 sql_help.c:860 sql_help.c:910 sql_help.c:957 sql_help.c:1010 -#: sql_help.c:1042 sql_help.c:1052 sql_help.c:1087 sql_help.c:1107 -#: sql_help.c:1121 sql_help.c:1171 sql_help.c:1318 sql_help.c:1448 -#: sql_help.c:1491 sql_help.c:1512 sql_help.c:1526 sql_help.c:1538 -#: sql_help.c:1551 sql_help.c:1578 sql_help.c:1644 sql_help.c:1697 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:260 +#: sql_help.c:281 sql_help.c:412 sql_help.c:459 sql_help.c:538 sql_help.c:586 +#: sql_help.c:604 sql_help.c:631 sql_help.c:684 sql_help.c:759 sql_help.c:814 +#: sql_help.c:835 sql_help.c:874 sql_help.c:924 sql_help.c:971 sql_help.c:1024 +#: sql_help.c:1056 sql_help.c:1066 sql_help.c:1101 sql_help.c:1121 +#: sql_help.c:1135 sql_help.c:1185 sql_help.c:1333 sql_help.c:1465 +#: sql_help.c:1508 sql_help.c:1529 sql_help.c:1543 sql_help.c:1555 +#: sql_help.c:1568 sql_help.c:1595 sql_help.c:1661 sql_help.c:1714 msgid "new_name" msgstr "новое_имя" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:487 sql_help.c:535 sql_help.c:625 -#: sql_help.c:634 sql_help.c:699 sql_help.c:719 sql_help.c:748 sql_help.c:803 -#: sql_help.c:865 sql_help.c:908 sql_help.c:1015 sql_help.c:1054 -#: sql_help.c:1085 sql_help.c:1105 sql_help.c:1119 sql_help.c:1169 -#: sql_help.c:1382 sql_help.c:1450 sql_help.c:1493 sql_help.c:1514 -#: sql_help.c:1576 sql_help.c:1692 sql_help.c:3026 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:258 +#: sql_help.c:279 sql_help.c:410 sql_help.c:495 sql_help.c:543 sql_help.c:633 +#: sql_help.c:642 sql_help.c:707 sql_help.c:731 sql_help.c:762 sql_help.c:817 +#: sql_help.c:879 sql_help.c:922 sql_help.c:1029 sql_help.c:1068 +#: sql_help.c:1099 sql_help.c:1119 sql_help.c:1133 sql_help.c:1183 +#: sql_help.c:1399 sql_help.c:1467 sql_help.c:1510 sql_help.c:1531 +#: sql_help.c:1593 sql_help.c:1709 sql_help.c:3039 msgid "new_owner" msgstr "новый_владелец" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:257 sql_help.c:324 -#: sql_help.c:453 sql_help.c:540 sql_help.c:678 sql_help.c:723 sql_help.c:751 -#: sql_help.c:806 sql_help.c:870 sql_help.c:1020 sql_help.c:1089 -#: sql_help.c:1123 sql_help.c:1320 sql_help.c:1495 sql_help.c:1516 -#: sql_help.c:1528 sql_help.c:1540 sql_help.c:1580 sql_help.c:1699 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:262 sql_help.c:332 +#: sql_help.c:461 sql_help.c:548 sql_help.c:686 sql_help.c:735 sql_help.c:765 +#: sql_help.c:820 sql_help.c:884 sql_help.c:1034 sql_help.c:1103 +#: sql_help.c:1137 sql_help.c:1335 sql_help.c:1512 sql_help.c:1533 +#: sql_help.c:1545 sql_help.c:1557 sql_help.c:1597 sql_help.c:1716 msgid "new_schema" msgstr "новая_схема" -#: sql_help.c:44 sql_help.c:1916 sql_help.c:3355 sql_help.c:4508 +#: sql_help.c:44 sql_help.c:1927 sql_help.c:3368 sql_help.c:4529 msgid "where aggregate_signature is:" msgstr "где сигнатура_агр_функции:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1870 sql_help.c:1887 sql_help.c:1893 sql_help.c:1917 -#: sql_help.c:1920 sql_help.c:1923 sql_help.c:2074 sql_help.c:2093 -#: sql_help.c:2096 sql_help.c:2398 sql_help.c:2607 sql_help.c:3356 -#: sql_help.c:3359 sql_help.c:3362 sql_help.c:3453 sql_help.c:3542 -#: sql_help.c:3570 sql_help.c:3922 sql_help.c:4378 sql_help.c:4485 -#: sql_help.c:4492 sql_help.c:4498 sql_help.c:4509 sql_help.c:4512 -#: sql_help.c:4515 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:350 sql_help.c:363 +#: sql_help.c:367 sql_help.c:383 sql_help.c:386 sql_help.c:389 sql_help.c:530 +#: sql_help.c:535 sql_help.c:540 sql_help.c:545 sql_help.c:550 sql_help.c:866 +#: sql_help.c:871 sql_help.c:876 sql_help.c:881 sql_help.c:886 sql_help.c:1016 +#: sql_help.c:1021 sql_help.c:1026 sql_help.c:1031 sql_help.c:1036 +#: sql_help.c:1881 sql_help.c:1898 sql_help.c:1904 sql_help.c:1928 +#: sql_help.c:1931 sql_help.c:1934 sql_help.c:2089 sql_help.c:2108 +#: sql_help.c:2111 sql_help.c:2415 sql_help.c:2624 sql_help.c:3369 +#: sql_help.c:3372 sql_help.c:3375 sql_help.c:3466 sql_help.c:3555 +#: sql_help.c:3583 sql_help.c:3936 sql_help.c:4399 sql_help.c:4506 +#: sql_help.c:4513 sql_help.c:4519 sql_help.c:4530 sql_help.c:4533 +#: sql_help.c:4536 msgid "argmode" msgstr "режим_аргумента" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:343 sql_help.c:356 -#: sql_help.c:360 sql_help.c:376 sql_help.c:379 sql_help.c:382 sql_help.c:523 -#: sql_help.c:528 sql_help.c:533 sql_help.c:538 sql_help.c:543 sql_help.c:853 -#: sql_help.c:858 sql_help.c:863 sql_help.c:868 sql_help.c:873 sql_help.c:1003 -#: sql_help.c:1008 sql_help.c:1013 sql_help.c:1018 sql_help.c:1023 -#: sql_help.c:1871 sql_help.c:1888 sql_help.c:1894 sql_help.c:1918 -#: sql_help.c:1921 sql_help.c:1924 sql_help.c:2075 sql_help.c:2094 -#: sql_help.c:2097 sql_help.c:2399 sql_help.c:2608 sql_help.c:3357 -#: sql_help.c:3360 sql_help.c:3363 sql_help.c:3454 sql_help.c:3543 -#: sql_help.c:3571 sql_help.c:4486 sql_help.c:4493 sql_help.c:4499 -#: sql_help.c:4510 sql_help.c:4513 sql_help.c:4516 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:351 sql_help.c:364 +#: sql_help.c:368 sql_help.c:384 sql_help.c:387 sql_help.c:390 sql_help.c:531 +#: sql_help.c:536 sql_help.c:541 sql_help.c:546 sql_help.c:551 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:882 sql_help.c:887 sql_help.c:1017 +#: sql_help.c:1022 sql_help.c:1027 sql_help.c:1032 sql_help.c:1037 +#: sql_help.c:1882 sql_help.c:1899 sql_help.c:1905 sql_help.c:1929 +#: sql_help.c:1932 sql_help.c:1935 sql_help.c:2090 sql_help.c:2109 +#: sql_help.c:2112 sql_help.c:2416 sql_help.c:2625 sql_help.c:3370 +#: sql_help.c:3373 sql_help.c:3376 sql_help.c:3467 sql_help.c:3556 +#: sql_help.c:3584 sql_help.c:4507 sql_help.c:4514 sql_help.c:4520 +#: sql_help.c:4531 sql_help.c:4534 sql_help.c:4537 msgid "argname" msgstr "имя_аргумента" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:344 sql_help.c:357 -#: sql_help.c:361 sql_help.c:377 sql_help.c:380 sql_help.c:383 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:544 sql_help.c:854 -#: sql_help.c:859 sql_help.c:864 sql_help.c:869 sql_help.c:874 sql_help.c:1004 -#: sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 sql_help.c:1024 -#: sql_help.c:1872 sql_help.c:1889 sql_help.c:1895 sql_help.c:1919 -#: sql_help.c:1922 sql_help.c:1925 sql_help.c:2400 sql_help.c:2609 -#: sql_help.c:3358 sql_help.c:3361 sql_help.c:3364 sql_help.c:3455 -#: sql_help.c:3544 sql_help.c:3572 sql_help.c:4487 sql_help.c:4494 -#: sql_help.c:4500 sql_help.c:4511 sql_help.c:4514 sql_help.c:4517 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:352 sql_help.c:365 +#: sql_help.c:369 sql_help.c:385 sql_help.c:388 sql_help.c:391 sql_help.c:532 +#: sql_help.c:537 sql_help.c:542 sql_help.c:547 sql_help.c:552 sql_help.c:868 +#: sql_help.c:873 sql_help.c:878 sql_help.c:883 sql_help.c:888 sql_help.c:1018 +#: sql_help.c:1023 sql_help.c:1028 sql_help.c:1033 sql_help.c:1038 +#: sql_help.c:1883 sql_help.c:1900 sql_help.c:1906 sql_help.c:1930 +#: sql_help.c:1933 sql_help.c:1936 sql_help.c:2417 sql_help.c:2626 +#: sql_help.c:3371 sql_help.c:3374 sql_help.c:3377 sql_help.c:3468 +#: sql_help.c:3557 sql_help.c:3585 sql_help.c:4508 sql_help.c:4515 +#: sql_help.c:4521 sql_help.c:4532 sql_help.c:4535 sql_help.c:4538 msgid "argtype" msgstr "тип_аргумента" -#: sql_help.c:114 sql_help.c:399 sql_help.c:476 sql_help.c:488 sql_help.c:951 -#: sql_help.c:1102 sql_help.c:1509 sql_help.c:1638 sql_help.c:1670 -#: sql_help.c:1723 sql_help.c:1787 sql_help.c:1974 sql_help.c:1981 -#: sql_help.c:2289 sql_help.c:2339 sql_help.c:2346 sql_help.c:2355 -#: sql_help.c:2444 sql_help.c:2671 sql_help.c:2764 sql_help.c:3055 -#: sql_help.c:3240 sql_help.c:3262 sql_help.c:3402 sql_help.c:3758 -#: sql_help.c:3966 sql_help.c:4205 sql_help.c:4207 sql_help.c:4984 +#: sql_help.c:114 sql_help.c:407 sql_help.c:484 sql_help.c:496 sql_help.c:965 +#: sql_help.c:1116 sql_help.c:1526 sql_help.c:1655 sql_help.c:1687 +#: sql_help.c:1739 sql_help.c:1798 sql_help.c:1987 sql_help.c:1994 +#: sql_help.c:2306 sql_help.c:2356 sql_help.c:2363 sql_help.c:2372 +#: sql_help.c:2461 sql_help.c:2686 sql_help.c:2777 sql_help.c:3068 +#: sql_help.c:3253 sql_help.c:3275 sql_help.c:3415 sql_help.c:3772 +#: sql_help.c:3980 sql_help.c:4226 sql_help.c:4228 sql_help.c:5006 msgid "option" msgstr "параметр" -#: sql_help.c:115 sql_help.c:952 sql_help.c:1639 sql_help.c:2445 -#: sql_help.c:2672 sql_help.c:3241 sql_help.c:3403 +#: sql_help.c:115 sql_help.c:966 sql_help.c:1656 sql_help.c:2462 +#: sql_help.c:2687 sql_help.c:3254 sql_help.c:3416 msgid "where option can be:" msgstr "где допустимые параметры:" -#: sql_help.c:116 sql_help.c:2221 +#: sql_help.c:116 sql_help.c:2238 msgid "allowconn" msgstr "разр_подключения" -#: sql_help.c:117 sql_help.c:953 sql_help.c:1640 sql_help.c:2222 -#: sql_help.c:2446 sql_help.c:2673 sql_help.c:3242 +#: sql_help.c:117 sql_help.c:967 sql_help.c:1657 sql_help.c:2239 +#: sql_help.c:2463 sql_help.c:2688 sql_help.c:3255 msgid "connlimit" msgstr "предел_подключений" -#: sql_help.c:118 sql_help.c:2223 +#: sql_help.c:118 sql_help.c:2240 msgid "istemplate" msgstr "это_шаблон" -#: sql_help.c:124 sql_help.c:613 sql_help.c:681 sql_help.c:695 sql_help.c:1323 -#: sql_help.c:1375 sql_help.c:4211 +#: sql_help.c:124 sql_help.c:621 sql_help.c:689 sql_help.c:703 sql_help.c:1338 +#: sql_help.c:1392 sql_help.c:4232 msgid "new_tablespace" msgstr "новое_табл_пространство" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:550 sql_help.c:552 -#: sql_help.c:553 sql_help.c:877 sql_help.c:879 sql_help.c:880 sql_help.c:960 -#: sql_help.c:964 sql_help.c:967 sql_help.c:1029 sql_help.c:1031 -#: sql_help.c:1032 sql_help.c:1182 sql_help.c:1184 sql_help.c:1647 -#: sql_help.c:1651 sql_help.c:1654 sql_help.c:2410 sql_help.c:2613 -#: sql_help.c:3934 sql_help.c:4229 sql_help.c:4390 sql_help.c:4699 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:558 sql_help.c:560 +#: sql_help.c:561 sql_help.c:891 sql_help.c:893 sql_help.c:894 sql_help.c:974 +#: sql_help.c:978 sql_help.c:981 sql_help.c:1043 sql_help.c:1045 +#: sql_help.c:1046 sql_help.c:1196 sql_help.c:1198 sql_help.c:1664 +#: sql_help.c:1668 sql_help.c:1671 sql_help.c:2427 sql_help.c:2630 +#: sql_help.c:3948 sql_help.c:4250 sql_help.c:4411 sql_help.c:4721 msgid "configuration_parameter" msgstr "параметр_конфигурации" -#: sql_help.c:128 sql_help.c:400 sql_help.c:471 sql_help.c:477 sql_help.c:489 -#: sql_help.c:551 sql_help.c:605 sql_help.c:687 sql_help.c:697 sql_help.c:878 -#: sql_help.c:906 sql_help.c:961 sql_help.c:1030 sql_help.c:1103 -#: sql_help.c:1148 sql_help.c:1152 sql_help.c:1156 sql_help.c:1159 -#: sql_help.c:1164 sql_help.c:1167 sql_help.c:1183 sql_help.c:1354 -#: sql_help.c:1377 sql_help.c:1425 sql_help.c:1433 sql_help.c:1453 -#: sql_help.c:1510 sql_help.c:1594 sql_help.c:1648 sql_help.c:1671 -#: sql_help.c:2290 sql_help.c:2340 sql_help.c:2347 sql_help.c:2356 -#: sql_help.c:2411 sql_help.c:2412 sql_help.c:2476 sql_help.c:2479 -#: sql_help.c:2513 sql_help.c:2614 sql_help.c:2615 sql_help.c:2638 -#: sql_help.c:2765 sql_help.c:2804 sql_help.c:2914 sql_help.c:2927 -#: sql_help.c:2941 sql_help.c:2982 sql_help.c:2990 sql_help.c:3012 -#: sql_help.c:3029 sql_help.c:3056 sql_help.c:3263 sql_help.c:3967 -#: sql_help.c:4700 sql_help.c:4701 sql_help.c:4702 sql_help.c:4703 +#: sql_help.c:128 sql_help.c:408 sql_help.c:479 sql_help.c:485 sql_help.c:497 +#: sql_help.c:559 sql_help.c:613 sql_help.c:695 sql_help.c:705 sql_help.c:892 +#: sql_help.c:920 sql_help.c:975 sql_help.c:1044 sql_help.c:1117 +#: sql_help.c:1162 sql_help.c:1166 sql_help.c:1170 sql_help.c:1173 +#: sql_help.c:1178 sql_help.c:1181 sql_help.c:1197 sql_help.c:1371 +#: sql_help.c:1394 sql_help.c:1442 sql_help.c:1450 sql_help.c:1470 +#: sql_help.c:1527 sql_help.c:1611 sql_help.c:1665 sql_help.c:1688 +#: sql_help.c:2307 sql_help.c:2357 sql_help.c:2364 sql_help.c:2373 +#: sql_help.c:2428 sql_help.c:2429 sql_help.c:2493 sql_help.c:2496 +#: sql_help.c:2530 sql_help.c:2631 sql_help.c:2632 sql_help.c:2655 +#: sql_help.c:2778 sql_help.c:2817 sql_help.c:2927 sql_help.c:2940 +#: sql_help.c:2954 sql_help.c:2995 sql_help.c:3003 sql_help.c:3025 +#: sql_help.c:3042 sql_help.c:3069 sql_help.c:3276 sql_help.c:3981 +#: sql_help.c:4722 sql_help.c:4723 sql_help.c:4724 sql_help.c:4725 msgid "value" msgstr "значение" @@ -4543,10 +4604,10 @@ msgstr "значение" msgid "target_role" msgstr "целевая_роль" -#: sql_help.c:203 sql_help.c:915 sql_help.c:2274 sql_help.c:2643 -#: sql_help.c:2720 sql_help.c:2725 sql_help.c:3897 sql_help.c:3906 -#: sql_help.c:3925 sql_help.c:3937 sql_help.c:4353 sql_help.c:4362 -#: sql_help.c:4381 sql_help.c:4393 +#: sql_help.c:203 sql_help.c:929 sql_help.c:2291 sql_help.c:2660 +#: sql_help.c:2733 sql_help.c:2738 sql_help.c:3911 sql_help.c:3920 +#: sql_help.c:3939 sql_help.c:3951 sql_help.c:4374 sql_help.c:4383 +#: sql_help.c:4402 sql_help.c:4414 msgid "schema_name" msgstr "имя_схемы" @@ -4560,2182 +4621,2200 @@ msgstr "где допустимое предложение_GRANT_или_REVOKE:" #: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 #: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 -#: sql_help.c:576 sql_help.c:612 sql_help.c:680 sql_help.c:824 sql_help.c:971 -#: sql_help.c:1322 sql_help.c:1658 sql_help.c:2449 sql_help.c:2450 -#: sql_help.c:2451 sql_help.c:2452 sql_help.c:2453 sql_help.c:2587 -#: sql_help.c:2676 sql_help.c:2677 sql_help.c:2678 sql_help.c:2679 -#: sql_help.c:2680 sql_help.c:3245 sql_help.c:3246 sql_help.c:3247 -#: sql_help.c:3248 sql_help.c:3249 sql_help.c:3946 sql_help.c:3950 -#: sql_help.c:4402 sql_help.c:4406 sql_help.c:4721 +#: sql_help.c:584 sql_help.c:620 sql_help.c:688 sql_help.c:838 sql_help.c:985 +#: sql_help.c:1337 sql_help.c:1675 sql_help.c:2466 sql_help.c:2467 +#: sql_help.c:2468 sql_help.c:2469 sql_help.c:2470 sql_help.c:2604 +#: sql_help.c:2691 sql_help.c:2692 sql_help.c:2693 sql_help.c:3258 +#: sql_help.c:3259 sql_help.c:3260 sql_help.c:3261 sql_help.c:3262 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:4423 sql_help.c:4427 +#: sql_help.c:4743 msgid "role_name" msgstr "имя_роли" -#: sql_help.c:241 sql_help.c:464 sql_help.c:914 sql_help.c:1338 sql_help.c:1340 -#: sql_help.c:1392 sql_help.c:1404 sql_help.c:1429 sql_help.c:1688 -#: sql_help.c:2243 sql_help.c:2247 sql_help.c:2359 sql_help.c:2364 -#: sql_help.c:2472 sql_help.c:2642 sql_help.c:2781 sql_help.c:2786 -#: sql_help.c:2788 sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 -#: sql_help.c:2945 sql_help.c:2957 sql_help.c:2986 sql_help.c:3998 -#: sql_help.c:4013 sql_help.c:4015 sql_help.c:4104 sql_help.c:4107 -#: sql_help.c:4109 sql_help.c:4572 sql_help.c:4573 sql_help.c:4582 -#: sql_help.c:4629 sql_help.c:4630 sql_help.c:4631 sql_help.c:4632 -#: sql_help.c:4633 sql_help.c:4634 sql_help.c:4674 sql_help.c:4675 -#: sql_help.c:4680 sql_help.c:4685 sql_help.c:4829 sql_help.c:4830 -#: sql_help.c:4839 sql_help.c:4886 sql_help.c:4887 sql_help.c:4888 -#: sql_help.c:4889 sql_help.c:4890 sql_help.c:4891 sql_help.c:4945 -#: sql_help.c:4947 sql_help.c:5015 sql_help.c:5075 sql_help.c:5076 -#: sql_help.c:5085 sql_help.c:5132 sql_help.c:5133 sql_help.c:5134 -#: sql_help.c:5135 sql_help.c:5136 sql_help.c:5137 +#: sql_help.c:246 sql_help.c:265 sql_help.c:472 sql_help.c:928 sql_help.c:1353 +#: sql_help.c:1355 sql_help.c:1359 sql_help.c:1409 sql_help.c:1421 +#: sql_help.c:1446 sql_help.c:1705 sql_help.c:2260 sql_help.c:2264 +#: sql_help.c:2376 sql_help.c:2381 sql_help.c:2489 sql_help.c:2659 +#: sql_help.c:2794 sql_help.c:2799 sql_help.c:2801 sql_help.c:2922 +#: sql_help.c:2935 sql_help.c:2949 sql_help.c:2958 sql_help.c:2970 +#: sql_help.c:2999 sql_help.c:4012 sql_help.c:4027 sql_help.c:4029 +#: sql_help.c:4125 sql_help.c:4128 sql_help.c:4130 sql_help.c:4593 +#: sql_help.c:4594 sql_help.c:4603 sql_help.c:4650 sql_help.c:4651 +#: sql_help.c:4652 sql_help.c:4653 sql_help.c:4654 sql_help.c:4655 +#: sql_help.c:4696 sql_help.c:4697 sql_help.c:4702 sql_help.c:4707 +#: sql_help.c:4851 sql_help.c:4852 sql_help.c:4861 sql_help.c:4908 +#: sql_help.c:4909 sql_help.c:4910 sql_help.c:4911 sql_help.c:4912 +#: sql_help.c:4913 sql_help.c:4968 sql_help.c:4970 sql_help.c:5036 +#: sql_help.c:5096 sql_help.c:5097 sql_help.c:5106 sql_help.c:5153 +#: sql_help.c:5154 sql_help.c:5155 sql_help.c:5156 sql_help.c:5157 +#: sql_help.c:5158 msgid "expression" msgstr "выражение" -#: sql_help.c:244 +#: sql_help.c:249 sql_help.c:2261 msgid "domain_constraint" msgstr "ограничение_домена" -#: sql_help.c:246 sql_help.c:248 sql_help.c:251 sql_help.c:479 sql_help.c:480 -#: sql_help.c:1315 sql_help.c:1362 sql_help.c:1363 sql_help.c:1364 -#: sql_help.c:1391 sql_help.c:1403 sql_help.c:1420 sql_help.c:1858 -#: sql_help.c:1860 sql_help.c:2246 sql_help.c:2358 sql_help.c:2363 -#: sql_help.c:2944 sql_help.c:2956 sql_help.c:4010 +#: sql_help.c:251 sql_help.c:253 sql_help.c:256 sql_help.c:264 sql_help.c:487 +#: sql_help.c:488 sql_help.c:1330 sql_help.c:1379 sql_help.c:1380 +#: sql_help.c:1381 sql_help.c:1408 sql_help.c:1420 sql_help.c:1437 +#: sql_help.c:1869 sql_help.c:1871 sql_help.c:2263 sql_help.c:2375 +#: sql_help.c:2380 sql_help.c:2957 sql_help.c:2969 sql_help.c:4024 msgid "constraint_name" msgstr "имя_ограничения" -#: sql_help.c:249 sql_help.c:1316 +#: sql_help.c:254 sql_help.c:1331 msgid "new_constraint_name" msgstr "имя_нового_ограничения" -#: sql_help.c:322 sql_help.c:1101 +#: sql_help.c:263 sql_help.c:2262 +msgid "where domain_constraint is:" +msgstr "где ограничение_домена может быть следующим:" + +#: sql_help.c:330 sql_help.c:1115 msgid "new_version" msgstr "новая_версия" -#: sql_help.c:326 sql_help.c:328 +#: sql_help.c:334 sql_help.c:336 msgid "member_object" msgstr "элемент_объект" -#: sql_help.c:329 +#: sql_help.c:337 msgid "where member_object is:" msgstr "где элемент_объект:" -#: sql_help.c:330 sql_help.c:335 sql_help.c:336 sql_help.c:337 sql_help.c:338 -#: sql_help.c:339 sql_help.c:340 sql_help.c:345 sql_help.c:349 sql_help.c:351 -#: sql_help.c:353 sql_help.c:362 sql_help.c:363 sql_help.c:364 sql_help.c:365 -#: sql_help.c:366 sql_help.c:367 sql_help.c:368 sql_help.c:369 sql_help.c:372 -#: sql_help.c:373 sql_help.c:1850 sql_help.c:1855 sql_help.c:1862 -#: sql_help.c:1863 sql_help.c:1864 sql_help.c:1865 sql_help.c:1866 -#: sql_help.c:1867 sql_help.c:1868 sql_help.c:1873 sql_help.c:1875 -#: sql_help.c:1879 sql_help.c:1881 sql_help.c:1885 sql_help.c:1890 -#: sql_help.c:1891 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 -#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 sql_help.c:1904 -#: sql_help.c:1905 sql_help.c:1906 sql_help.c:1907 sql_help.c:1908 -#: sql_help.c:1913 sql_help.c:1914 sql_help.c:4475 sql_help.c:4480 -#: sql_help.c:4481 sql_help.c:4482 sql_help.c:4483 sql_help.c:4489 -#: sql_help.c:4490 sql_help.c:4495 sql_help.c:4496 sql_help.c:4501 -#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4505 -#: sql_help.c:4506 +#: sql_help.c:338 sql_help.c:343 sql_help.c:344 sql_help.c:345 sql_help.c:346 +#: sql_help.c:347 sql_help.c:348 sql_help.c:353 sql_help.c:357 sql_help.c:359 +#: sql_help.c:361 sql_help.c:370 sql_help.c:371 sql_help.c:372 sql_help.c:373 +#: sql_help.c:374 sql_help.c:375 sql_help.c:376 sql_help.c:377 sql_help.c:380 +#: sql_help.c:381 sql_help.c:1861 sql_help.c:1866 sql_help.c:1873 +#: sql_help.c:1874 sql_help.c:1875 sql_help.c:1876 sql_help.c:1877 +#: sql_help.c:1878 sql_help.c:1879 sql_help.c:1884 sql_help.c:1886 +#: sql_help.c:1890 sql_help.c:1892 sql_help.c:1896 sql_help.c:1901 +#: sql_help.c:1902 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1912 sql_help.c:1913 sql_help.c:1914 sql_help.c:1915 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:1918 sql_help.c:1919 +#: sql_help.c:1924 sql_help.c:1925 sql_help.c:4496 sql_help.c:4501 +#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4510 +#: sql_help.c:4511 sql_help.c:4516 sql_help.c:4517 sql_help.c:4522 +#: sql_help.c:4523 sql_help.c:4524 sql_help.c:4525 sql_help.c:4526 +#: sql_help.c:4527 msgid "object_name" msgstr "имя_объекта" # well-spelled: агр -#: sql_help.c:331 sql_help.c:1851 sql_help.c:4478 +#: sql_help.c:339 sql_help.c:1862 sql_help.c:4499 msgid "aggregate_name" msgstr "имя_агр_функции" -#: sql_help.c:333 sql_help.c:1853 sql_help.c:2139 sql_help.c:2143 -#: sql_help.c:2145 sql_help.c:3372 +#: sql_help.c:341 sql_help.c:1864 sql_help.c:2154 sql_help.c:2158 +#: sql_help.c:2160 sql_help.c:3385 msgid "source_type" msgstr "исходный_тип" -#: sql_help.c:334 sql_help.c:1854 sql_help.c:2140 sql_help.c:2144 -#: sql_help.c:2146 sql_help.c:3373 +#: sql_help.c:342 sql_help.c:1865 sql_help.c:2155 sql_help.c:2159 +#: sql_help.c:2161 sql_help.c:3386 msgid "target_type" msgstr "целевой_тип" -#: sql_help.c:341 sql_help.c:788 sql_help.c:1869 sql_help.c:2141 -#: sql_help.c:2184 sql_help.c:2262 sql_help.c:2530 sql_help.c:2561 -#: sql_help.c:3132 sql_help.c:4377 sql_help.c:4484 sql_help.c:4601 -#: sql_help.c:4605 sql_help.c:4609 sql_help.c:4612 sql_help.c:4858 -#: sql_help.c:4862 sql_help.c:4866 sql_help.c:4869 sql_help.c:5104 -#: sql_help.c:5108 sql_help.c:5112 sql_help.c:5115 +#: sql_help.c:349 sql_help.c:802 sql_help.c:1880 sql_help.c:2156 +#: sql_help.c:2199 sql_help.c:2279 sql_help.c:2547 sql_help.c:2578 +#: sql_help.c:3145 sql_help.c:4398 sql_help.c:4505 sql_help.c:4622 +#: sql_help.c:4626 sql_help.c:4630 sql_help.c:4633 sql_help.c:4880 +#: sql_help.c:4884 sql_help.c:4888 sql_help.c:4891 sql_help.c:5125 +#: sql_help.c:5129 sql_help.c:5133 sql_help.c:5136 msgid "function_name" msgstr "имя_функции" -#: sql_help.c:346 sql_help.c:781 sql_help.c:1876 sql_help.c:2554 +#: sql_help.c:354 sql_help.c:795 sql_help.c:1887 sql_help.c:2571 msgid "operator_name" msgstr "имя_оператора" -#: sql_help.c:347 sql_help.c:717 sql_help.c:721 sql_help.c:725 sql_help.c:1877 -#: sql_help.c:2531 sql_help.c:3496 +#: sql_help.c:355 sql_help.c:729 sql_help.c:733 sql_help.c:737 sql_help.c:1888 +#: sql_help.c:2548 sql_help.c:3509 msgid "left_type" msgstr "тип_слева" -#: sql_help.c:348 sql_help.c:718 sql_help.c:722 sql_help.c:726 sql_help.c:1878 -#: sql_help.c:2532 sql_help.c:3497 +#: sql_help.c:356 sql_help.c:730 sql_help.c:734 sql_help.c:738 sql_help.c:1889 +#: sql_help.c:2549 sql_help.c:3510 msgid "right_type" msgstr "тип_справа" -#: sql_help.c:350 sql_help.c:352 sql_help.c:744 sql_help.c:747 sql_help.c:750 -#: sql_help.c:779 sql_help.c:791 sql_help.c:799 sql_help.c:802 sql_help.c:805 -#: sql_help.c:1409 sql_help.c:1880 sql_help.c:1882 sql_help.c:2551 -#: sql_help.c:2572 sql_help.c:2962 sql_help.c:3506 sql_help.c:3515 +#: sql_help.c:358 sql_help.c:360 sql_help.c:758 sql_help.c:761 sql_help.c:764 +#: sql_help.c:793 sql_help.c:805 sql_help.c:813 sql_help.c:816 sql_help.c:819 +#: sql_help.c:1426 sql_help.c:1891 sql_help.c:1893 sql_help.c:2568 +#: sql_help.c:2589 sql_help.c:2975 sql_help.c:3519 sql_help.c:3528 msgid "index_method" msgstr "метод_индекса" -#: sql_help.c:354 sql_help.c:1886 sql_help.c:4491 +#: sql_help.c:362 sql_help.c:1897 sql_help.c:4512 msgid "procedure_name" msgstr "имя_процедуры" -#: sql_help.c:358 sql_help.c:1892 sql_help.c:3921 sql_help.c:4497 +#: sql_help.c:366 sql_help.c:1903 sql_help.c:3935 sql_help.c:4518 msgid "routine_name" msgstr "имя_подпрограммы" -#: sql_help.c:370 sql_help.c:1381 sql_help.c:1909 sql_help.c:2406 -#: sql_help.c:2612 sql_help.c:2917 sql_help.c:3099 sql_help.c:3677 -#: sql_help.c:3943 sql_help.c:4399 +#: sql_help.c:378 sql_help.c:1398 sql_help.c:1920 sql_help.c:2423 +#: sql_help.c:2629 sql_help.c:2930 sql_help.c:3112 sql_help.c:3690 +#: sql_help.c:3957 sql_help.c:4420 msgid "type_name" msgstr "имя_типа" -#: sql_help.c:371 sql_help.c:1910 sql_help.c:2405 sql_help.c:2611 -#: sql_help.c:3100 sql_help.c:3330 sql_help.c:3678 sql_help.c:3928 -#: sql_help.c:4384 +#: sql_help.c:379 sql_help.c:1921 sql_help.c:2422 sql_help.c:2628 +#: sql_help.c:3113 sql_help.c:3343 sql_help.c:3691 sql_help.c:3942 +#: sql_help.c:4405 msgid "lang_name" msgstr "имя_языка" -#: sql_help.c:374 +#: sql_help.c:382 msgid "and aggregate_signature is:" msgstr "и сигнатура_агр_функции:" -#: sql_help.c:397 sql_help.c:2006 sql_help.c:2287 +#: sql_help.c:405 sql_help.c:2021 sql_help.c:2304 msgid "handler_function" msgstr "функция_обработчик" -#: sql_help.c:398 sql_help.c:2288 +#: sql_help.c:406 sql_help.c:2305 msgid "validator_function" msgstr "функция_проверки" -#: sql_help.c:446 sql_help.c:525 sql_help.c:669 sql_help.c:855 sql_help.c:1005 -#: sql_help.c:1310 sql_help.c:1585 +#: sql_help.c:454 sql_help.c:533 sql_help.c:677 sql_help.c:869 sql_help.c:1019 +#: sql_help.c:1325 sql_help.c:1602 msgid "action" msgstr "действие" -#: sql_help.c:448 sql_help.c:455 sql_help.c:459 sql_help.c:460 sql_help.c:463 -#: sql_help.c:465 sql_help.c:466 sql_help.c:467 sql_help.c:469 sql_help.c:472 -#: sql_help.c:474 sql_help.c:475 sql_help.c:673 sql_help.c:683 sql_help.c:685 -#: sql_help.c:688 sql_help.c:690 sql_help.c:691 sql_help.c:913 sql_help.c:1082 -#: sql_help.c:1312 sql_help.c:1330 sql_help.c:1334 sql_help.c:1335 -#: sql_help.c:1339 sql_help.c:1341 sql_help.c:1342 sql_help.c:1343 -#: sql_help.c:1344 sql_help.c:1346 sql_help.c:1349 sql_help.c:1350 -#: sql_help.c:1352 sql_help.c:1355 sql_help.c:1357 sql_help.c:1358 -#: sql_help.c:1405 sql_help.c:1407 sql_help.c:1414 sql_help.c:1423 -#: sql_help.c:1428 sql_help.c:1435 sql_help.c:1436 sql_help.c:1687 -#: sql_help.c:1690 sql_help.c:1694 sql_help.c:1732 sql_help.c:1857 -#: sql_help.c:1971 sql_help.c:1977 sql_help.c:1991 sql_help.c:1992 -#: sql_help.c:1993 sql_help.c:2337 sql_help.c:2350 sql_help.c:2403 -#: sql_help.c:2471 sql_help.c:2477 sql_help.c:2510 sql_help.c:2641 -#: sql_help.c:2750 sql_help.c:2785 sql_help.c:2787 sql_help.c:2899 -#: sql_help.c:2908 sql_help.c:2918 sql_help.c:2921 sql_help.c:2931 -#: sql_help.c:2935 sql_help.c:2958 sql_help.c:2960 sql_help.c:2967 -#: sql_help.c:2980 sql_help.c:2985 sql_help.c:2992 sql_help.c:2993 -#: sql_help.c:3009 sql_help.c:3135 sql_help.c:3275 sql_help.c:3900 -#: sql_help.c:3901 sql_help.c:3997 sql_help.c:4012 sql_help.c:4014 -#: sql_help.c:4016 sql_help.c:4103 sql_help.c:4106 sql_help.c:4108 -#: sql_help.c:4110 sql_help.c:4356 sql_help.c:4357 sql_help.c:4477 -#: sql_help.c:4638 sql_help.c:4644 sql_help.c:4646 sql_help.c:4895 -#: sql_help.c:4901 sql_help.c:4903 sql_help.c:4944 sql_help.c:4946 -#: sql_help.c:4948 sql_help.c:5003 sql_help.c:5141 sql_help.c:5147 -#: sql_help.c:5149 +#: sql_help.c:456 sql_help.c:463 sql_help.c:467 sql_help.c:468 sql_help.c:471 +#: sql_help.c:473 sql_help.c:474 sql_help.c:475 sql_help.c:477 sql_help.c:480 +#: sql_help.c:482 sql_help.c:483 sql_help.c:681 sql_help.c:691 sql_help.c:693 +#: sql_help.c:696 sql_help.c:698 sql_help.c:699 sql_help.c:927 sql_help.c:1096 +#: sql_help.c:1327 sql_help.c:1345 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 sql_help.c:1358 +#: sql_help.c:1360 sql_help.c:1361 sql_help.c:1363 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1369 sql_help.c:1372 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1422 sql_help.c:1424 sql_help.c:1431 +#: sql_help.c:1440 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1704 sql_help.c:1707 sql_help.c:1711 sql_help.c:1747 +#: sql_help.c:1868 sql_help.c:1984 sql_help.c:1990 sql_help.c:2004 +#: sql_help.c:2005 sql_help.c:2006 sql_help.c:2354 sql_help.c:2367 +#: sql_help.c:2420 sql_help.c:2488 sql_help.c:2494 sql_help.c:2527 +#: sql_help.c:2658 sql_help.c:2763 sql_help.c:2798 sql_help.c:2800 +#: sql_help.c:2912 sql_help.c:2921 sql_help.c:2931 sql_help.c:2934 +#: sql_help.c:2944 sql_help.c:2948 sql_help.c:2971 sql_help.c:2973 +#: sql_help.c:2980 sql_help.c:2993 sql_help.c:2998 sql_help.c:3005 +#: sql_help.c:3006 sql_help.c:3022 sql_help.c:3148 sql_help.c:3288 +#: sql_help.c:3914 sql_help.c:3915 sql_help.c:4011 sql_help.c:4026 +#: sql_help.c:4028 sql_help.c:4030 sql_help.c:4124 sql_help.c:4127 +#: sql_help.c:4129 sql_help.c:4131 sql_help.c:4377 sql_help.c:4378 +#: sql_help.c:4498 sql_help.c:4659 sql_help.c:4666 sql_help.c:4668 +#: sql_help.c:4917 sql_help.c:4924 sql_help.c:4926 sql_help.c:4967 +#: sql_help.c:4969 sql_help.c:4971 sql_help.c:5024 sql_help.c:5162 +#: sql_help.c:5169 sql_help.c:5171 msgid "column_name" msgstr "имя_столбца" -#: sql_help.c:449 sql_help.c:674 sql_help.c:1313 sql_help.c:1695 +#: sql_help.c:457 sql_help.c:682 sql_help.c:1328 sql_help.c:1712 msgid "new_column_name" msgstr "новое_имя_столбца" -#: sql_help.c:454 sql_help.c:546 sql_help.c:682 sql_help.c:876 sql_help.c:1026 -#: sql_help.c:1329 sql_help.c:1595 +#: sql_help.c:462 sql_help.c:554 sql_help.c:690 sql_help.c:890 sql_help.c:1040 +#: sql_help.c:1344 sql_help.c:1612 msgid "where action is one of:" msgstr "где допустимое действие:" -#: sql_help.c:456 sql_help.c:461 sql_help.c:1074 sql_help.c:1331 -#: sql_help.c:1336 sql_help.c:1597 sql_help.c:1601 sql_help.c:2241 -#: sql_help.c:2338 sql_help.c:2550 sql_help.c:2743 sql_help.c:2900 -#: sql_help.c:3182 sql_help.c:4162 +#: sql_help.c:464 sql_help.c:469 sql_help.c:1088 sql_help.c:1346 +#: sql_help.c:1351 sql_help.c:1614 sql_help.c:1618 sql_help.c:2258 +#: sql_help.c:2355 sql_help.c:2567 sql_help.c:2756 sql_help.c:2913 +#: sql_help.c:3195 sql_help.c:4183 msgid "data_type" msgstr "тип_данных" -#: sql_help.c:457 sql_help.c:462 sql_help.c:1332 sql_help.c:1337 -#: sql_help.c:1430 sql_help.c:1598 sql_help.c:1602 sql_help.c:2242 -#: sql_help.c:2341 sql_help.c:2473 sql_help.c:2902 sql_help.c:2910 -#: sql_help.c:2923 sql_help.c:2937 sql_help.c:2987 sql_help.c:3183 -#: sql_help.c:3189 sql_help.c:4007 +#: sql_help.c:465 sql_help.c:470 sql_help.c:1347 sql_help.c:1352 +#: sql_help.c:1447 sql_help.c:1615 sql_help.c:1619 sql_help.c:2259 +#: sql_help.c:2358 sql_help.c:2490 sql_help.c:2915 sql_help.c:2923 +#: sql_help.c:2936 sql_help.c:2950 sql_help.c:3000 sql_help.c:3196 +#: sql_help.c:3202 sql_help.c:4021 msgid "collation" msgstr "правило_сортировки" -#: sql_help.c:458 sql_help.c:1333 sql_help.c:2342 sql_help.c:2351 -#: sql_help.c:2903 sql_help.c:2919 sql_help.c:2932 +#: sql_help.c:466 sql_help.c:1348 sql_help.c:2359 sql_help.c:2368 +#: sql_help.c:2916 sql_help.c:2932 sql_help.c:2945 msgid "column_constraint" msgstr "ограничение_столбца" -#: sql_help.c:468 sql_help.c:610 sql_help.c:684 sql_help.c:1351 sql_help.c:4997 +#: sql_help.c:476 sql_help.c:618 sql_help.c:692 sql_help.c:1368 sql_help.c:5018 msgid "integer" msgstr "целое" -#: sql_help.c:470 sql_help.c:473 sql_help.c:686 sql_help.c:689 sql_help.c:1353 -#: sql_help.c:1356 +#: sql_help.c:478 sql_help.c:481 sql_help.c:694 sql_help.c:697 sql_help.c:1370 +#: sql_help.c:1373 msgid "attribute_option" msgstr "атрибут" -#: sql_help.c:478 sql_help.c:1360 sql_help.c:2343 sql_help.c:2352 -#: sql_help.c:2904 sql_help.c:2920 sql_help.c:2933 +#: sql_help.c:486 sql_help.c:1377 sql_help.c:2360 sql_help.c:2369 +#: sql_help.c:2917 sql_help.c:2933 sql_help.c:2946 msgid "table_constraint" msgstr "ограничение_таблицы" -#: sql_help.c:481 sql_help.c:482 sql_help.c:483 sql_help.c:484 sql_help.c:1365 -#: sql_help.c:1366 sql_help.c:1367 sql_help.c:1368 sql_help.c:1911 +#: sql_help.c:489 sql_help.c:490 sql_help.c:491 sql_help.c:492 sql_help.c:1382 +#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:1922 msgid "trigger_name" msgstr "имя_триггера" -#: sql_help.c:485 sql_help.c:486 sql_help.c:1379 sql_help.c:1380 -#: sql_help.c:2344 sql_help.c:2349 sql_help.c:2907 sql_help.c:2930 +#: sql_help.c:493 sql_help.c:494 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:2361 sql_help.c:2366 sql_help.c:2920 sql_help.c:2943 msgid "parent_table" msgstr "таблица_родитель" -#: sql_help.c:545 sql_help.c:602 sql_help.c:671 sql_help.c:875 sql_help.c:1025 -#: sql_help.c:1554 sql_help.c:2273 +#: sql_help.c:553 sql_help.c:610 sql_help.c:679 sql_help.c:889 sql_help.c:1039 +#: sql_help.c:1571 sql_help.c:2290 msgid "extension_name" msgstr "имя_расширения" -#: sql_help.c:547 sql_help.c:1027 sql_help.c:2407 +#: sql_help.c:555 sql_help.c:1041 sql_help.c:2424 msgid "execution_cost" msgstr "стоимость_выполнения" -#: sql_help.c:548 sql_help.c:1028 sql_help.c:2408 +#: sql_help.c:556 sql_help.c:1042 sql_help.c:2425 msgid "result_rows" msgstr "строк_в_результате" -#: sql_help.c:549 sql_help.c:2409 +#: sql_help.c:557 sql_help.c:2426 msgid "support_function" msgstr "вспомогательная_функция" -#: sql_help.c:571 sql_help.c:573 sql_help.c:950 sql_help.c:958 sql_help.c:962 -#: sql_help.c:965 sql_help.c:968 sql_help.c:1637 sql_help.c:1645 -#: sql_help.c:1649 sql_help.c:1652 sql_help.c:1655 sql_help.c:2721 -#: sql_help.c:2723 sql_help.c:2726 sql_help.c:2727 sql_help.c:3898 -#: sql_help.c:3899 sql_help.c:3903 sql_help.c:3904 sql_help.c:3907 -#: sql_help.c:3908 sql_help.c:3910 sql_help.c:3911 sql_help.c:3913 -#: sql_help.c:3914 sql_help.c:3916 sql_help.c:3917 sql_help.c:3919 -#: sql_help.c:3920 sql_help.c:3926 sql_help.c:3927 sql_help.c:3929 -#: sql_help.c:3930 sql_help.c:3932 sql_help.c:3933 sql_help.c:3935 -#: sql_help.c:3936 sql_help.c:3938 sql_help.c:3939 sql_help.c:3941 -#: sql_help.c:3942 sql_help.c:3944 sql_help.c:3945 sql_help.c:3947 -#: sql_help.c:3948 sql_help.c:4354 sql_help.c:4355 sql_help.c:4359 -#: sql_help.c:4360 sql_help.c:4363 sql_help.c:4364 sql_help.c:4366 -#: sql_help.c:4367 sql_help.c:4369 sql_help.c:4370 sql_help.c:4372 -#: sql_help.c:4373 sql_help.c:4375 sql_help.c:4376 sql_help.c:4382 -#: sql_help.c:4383 sql_help.c:4385 sql_help.c:4386 sql_help.c:4388 -#: sql_help.c:4389 sql_help.c:4391 sql_help.c:4392 sql_help.c:4394 -#: sql_help.c:4395 sql_help.c:4397 sql_help.c:4398 sql_help.c:4400 -#: sql_help.c:4401 sql_help.c:4403 sql_help.c:4404 +#: sql_help.c:579 sql_help.c:581 sql_help.c:964 sql_help.c:972 sql_help.c:976 +#: sql_help.c:979 sql_help.c:982 sql_help.c:1654 sql_help.c:1662 +#: sql_help.c:1666 sql_help.c:1669 sql_help.c:1672 sql_help.c:2734 +#: sql_help.c:2736 sql_help.c:2739 sql_help.c:2740 sql_help.c:3912 +#: sql_help.c:3913 sql_help.c:3917 sql_help.c:3918 sql_help.c:3921 +#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 +#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 +#: sql_help.c:3934 sql_help.c:3940 sql_help.c:3941 sql_help.c:3943 +#: sql_help.c:3944 sql_help.c:3946 sql_help.c:3947 sql_help.c:3949 +#: sql_help.c:3950 sql_help.c:3952 sql_help.c:3953 sql_help.c:3955 +#: sql_help.c:3956 sql_help.c:3958 sql_help.c:3959 sql_help.c:3961 +#: sql_help.c:3962 sql_help.c:4375 sql_help.c:4376 sql_help.c:4380 +#: sql_help.c:4381 sql_help.c:4384 sql_help.c:4385 sql_help.c:4387 +#: sql_help.c:4388 sql_help.c:4390 sql_help.c:4391 sql_help.c:4393 +#: sql_help.c:4394 sql_help.c:4396 sql_help.c:4397 sql_help.c:4403 +#: sql_help.c:4404 sql_help.c:4406 sql_help.c:4407 sql_help.c:4409 +#: sql_help.c:4410 sql_help.c:4412 sql_help.c:4413 sql_help.c:4415 +#: sql_help.c:4416 sql_help.c:4418 sql_help.c:4419 sql_help.c:4421 +#: sql_help.c:4422 sql_help.c:4424 sql_help.c:4425 msgid "role_specification" msgstr "указание_роли" -#: sql_help.c:572 sql_help.c:574 sql_help.c:1668 sql_help.c:2209 -#: sql_help.c:2729 sql_help.c:3260 sql_help.c:3711 sql_help.c:4731 +#: sql_help.c:580 sql_help.c:582 sql_help.c:1685 sql_help.c:2225 +#: sql_help.c:2742 sql_help.c:3273 sql_help.c:3724 sql_help.c:4753 msgid "user_name" msgstr "имя_пользователя" -#: sql_help.c:575 sql_help.c:970 sql_help.c:1657 sql_help.c:2728 -#: sql_help.c:3949 sql_help.c:4405 +#: sql_help.c:583 sql_help.c:984 sql_help.c:1674 sql_help.c:2741 +#: sql_help.c:3963 sql_help.c:4426 msgid "where role_specification can be:" msgstr "где допустимое указание_роли:" -#: sql_help.c:577 +#: sql_help.c:585 msgid "group_name" msgstr "имя_группы" -#: sql_help.c:598 sql_help.c:1426 sql_help.c:2220 sql_help.c:2480 -#: sql_help.c:2514 sql_help.c:2915 sql_help.c:2928 sql_help.c:2942 -#: sql_help.c:2983 sql_help.c:3013 sql_help.c:3025 sql_help.c:3940 -#: sql_help.c:4396 +#: sql_help.c:606 sql_help.c:1443 sql_help.c:2237 sql_help.c:2497 +#: sql_help.c:2531 sql_help.c:2928 sql_help.c:2941 sql_help.c:2955 +#: sql_help.c:2996 sql_help.c:3026 sql_help.c:3038 sql_help.c:3954 +#: sql_help.c:4417 msgid "tablespace_name" msgstr "табл_пространство" -#: sql_help.c:600 sql_help.c:693 sql_help.c:1373 sql_help.c:1383 -#: sql_help.c:1421 sql_help.c:1786 sql_help.c:1789 +#: sql_help.c:608 sql_help.c:701 sql_help.c:1390 sql_help.c:1400 +#: sql_help.c:1438 sql_help.c:1800 msgid "index_name" msgstr "имя_индекса" -#: sql_help.c:604 sql_help.c:607 sql_help.c:696 sql_help.c:698 sql_help.c:1376 -#: sql_help.c:1378 sql_help.c:1424 sql_help.c:2478 sql_help.c:2512 -#: sql_help.c:2913 sql_help.c:2926 sql_help.c:2940 sql_help.c:2981 -#: sql_help.c:3011 +#: sql_help.c:612 sql_help.c:615 sql_help.c:704 sql_help.c:706 sql_help.c:1393 +#: sql_help.c:1395 sql_help.c:1441 sql_help.c:2495 sql_help.c:2529 +#: sql_help.c:2926 sql_help.c:2939 sql_help.c:2953 sql_help.c:2994 +#: sql_help.c:3024 msgid "storage_parameter" msgstr "параметр_хранения" -#: sql_help.c:609 +#: sql_help.c:617 msgid "column_number" msgstr "номер_столбца" -#: sql_help.c:633 sql_help.c:1874 sql_help.c:4488 +#: sql_help.c:641 sql_help.c:1885 sql_help.c:4509 msgid "large_object_oid" msgstr "oid_большого_объекта" -#: sql_help.c:692 sql_help.c:1359 sql_help.c:2901 +#: sql_help.c:700 sql_help.c:1376 sql_help.c:2914 msgid "compression_method" msgstr "метод_сжатия" -#: sql_help.c:694 sql_help.c:1374 +#: sql_help.c:702 sql_help.c:1391 msgid "new_access_method" msgstr "новый_метод_доступа" -#: sql_help.c:727 sql_help.c:2535 +#: sql_help.c:739 sql_help.c:2552 msgid "res_proc" msgstr "процедура_ограничения" -#: sql_help.c:728 sql_help.c:2536 +#: sql_help.c:740 sql_help.c:2553 msgid "join_proc" msgstr "процедура_соединения" -#: sql_help.c:780 sql_help.c:792 sql_help.c:2553 +#: sql_help.c:741 sql_help.c:2550 +msgid "com_op" +msgstr "коммут_оператор" + +#: sql_help.c:742 sql_help.c:2551 +msgid "neg_op" +msgstr "обратный_оператор" + +#: sql_help.c:794 sql_help.c:806 sql_help.c:2570 msgid "strategy_number" msgstr "номер_стратегии" -#: sql_help.c:782 sql_help.c:783 sql_help.c:786 sql_help.c:787 sql_help.c:793 -#: sql_help.c:794 sql_help.c:796 sql_help.c:797 sql_help.c:2555 sql_help.c:2556 -#: sql_help.c:2559 sql_help.c:2560 +#: sql_help.c:796 sql_help.c:797 sql_help.c:800 sql_help.c:801 sql_help.c:807 +#: sql_help.c:808 sql_help.c:810 sql_help.c:811 sql_help.c:2572 sql_help.c:2573 +#: sql_help.c:2576 sql_help.c:2577 msgid "op_type" msgstr "тип_операции" -#: sql_help.c:784 sql_help.c:2557 +#: sql_help.c:798 sql_help.c:2574 msgid "sort_family_name" msgstr "семейство_сортировки" -#: sql_help.c:785 sql_help.c:795 sql_help.c:2558 +#: sql_help.c:799 sql_help.c:809 sql_help.c:2575 msgid "support_number" msgstr "номер_опорной_процедуры" -#: sql_help.c:789 sql_help.c:2142 sql_help.c:2562 sql_help.c:3102 -#: sql_help.c:3104 +#: sql_help.c:803 sql_help.c:2157 sql_help.c:2579 sql_help.c:3115 +#: sql_help.c:3117 msgid "argument_type" msgstr "тип_аргумента" -#: sql_help.c:820 sql_help.c:823 sql_help.c:912 sql_help.c:1041 sql_help.c:1081 -#: sql_help.c:1550 sql_help.c:1553 sql_help.c:1731 sql_help.c:1785 -#: sql_help.c:1788 sql_help.c:1859 sql_help.c:1884 sql_help.c:1897 -#: sql_help.c:1912 sql_help.c:1970 sql_help.c:1976 sql_help.c:2336 -#: sql_help.c:2348 sql_help.c:2469 sql_help.c:2509 sql_help.c:2586 -#: sql_help.c:2640 sql_help.c:2697 sql_help.c:2749 sql_help.c:2782 -#: sql_help.c:2789 sql_help.c:2898 sql_help.c:2916 sql_help.c:2929 -#: sql_help.c:3008 sql_help.c:3128 sql_help.c:3309 sql_help.c:3532 -#: sql_help.c:3581 sql_help.c:3687 sql_help.c:3896 sql_help.c:3902 -#: sql_help.c:3963 sql_help.c:3995 sql_help.c:4352 sql_help.c:4358 -#: sql_help.c:4476 sql_help.c:4587 sql_help.c:4589 sql_help.c:4651 -#: sql_help.c:4690 sql_help.c:4844 sql_help.c:4846 sql_help.c:4908 -#: sql_help.c:4942 sql_help.c:5002 sql_help.c:5090 sql_help.c:5092 -#: sql_help.c:5154 +#: sql_help.c:834 sql_help.c:837 sql_help.c:926 sql_help.c:1055 sql_help.c:1095 +#: sql_help.c:1567 sql_help.c:1570 sql_help.c:1746 sql_help.c:1799 +#: sql_help.c:1870 sql_help.c:1895 sql_help.c:1908 sql_help.c:1923 +#: sql_help.c:1983 sql_help.c:1989 sql_help.c:2353 sql_help.c:2365 +#: sql_help.c:2486 sql_help.c:2526 sql_help.c:2603 sql_help.c:2657 +#: sql_help.c:2710 sql_help.c:2762 sql_help.c:2795 sql_help.c:2802 +#: sql_help.c:2911 sql_help.c:2929 sql_help.c:2942 sql_help.c:3021 +#: sql_help.c:3141 sql_help.c:3322 sql_help.c:3545 sql_help.c:3594 +#: sql_help.c:3700 sql_help.c:3910 sql_help.c:3916 sql_help.c:3977 +#: sql_help.c:4009 sql_help.c:4373 sql_help.c:4379 sql_help.c:4497 +#: sql_help.c:4610 sql_help.c:4673 sql_help.c:4712 sql_help.c:4868 +#: sql_help.c:4931 sql_help.c:4965 sql_help.c:5023 sql_help.c:5113 +#: sql_help.c:5176 msgid "table_name" msgstr "имя_таблицы" -#: sql_help.c:825 sql_help.c:2588 +#: sql_help.c:839 sql_help.c:2605 msgid "using_expression" msgstr "выражение_использования" -#: sql_help.c:826 sql_help.c:2589 +#: sql_help.c:840 sql_help.c:2606 msgid "check_expression" msgstr "выражение_проверки" -#: sql_help.c:899 sql_help.c:901 sql_help.c:903 sql_help.c:2636 +#: sql_help.c:913 sql_help.c:915 sql_help.c:917 sql_help.c:2653 msgid "publication_object" msgstr "объект_публикации" -#: sql_help.c:905 sql_help.c:2637 +#: sql_help.c:919 sql_help.c:2654 msgid "publication_parameter" msgstr "параметр_публикации" -#: sql_help.c:911 sql_help.c:2639 +#: sql_help.c:925 sql_help.c:2656 msgid "where publication_object is one of:" msgstr "где объект_публикации:" -#: sql_help.c:954 sql_help.c:1641 sql_help.c:2447 sql_help.c:2674 -#: sql_help.c:3243 +#: sql_help.c:968 sql_help.c:1658 sql_help.c:2464 sql_help.c:2689 +#: sql_help.c:3256 msgid "password" msgstr "пароль" -#: sql_help.c:955 sql_help.c:1642 sql_help.c:2448 sql_help.c:2675 -#: sql_help.c:3244 +#: sql_help.c:969 sql_help.c:1659 sql_help.c:2465 sql_help.c:2690 +#: sql_help.c:3257 msgid "timestamp" msgstr "timestamp" -#: sql_help.c:959 sql_help.c:963 sql_help.c:966 sql_help.c:969 sql_help.c:1646 -#: sql_help.c:1650 sql_help.c:1653 sql_help.c:1656 sql_help.c:3909 -#: sql_help.c:4365 +#: sql_help.c:973 sql_help.c:977 sql_help.c:980 sql_help.c:983 sql_help.c:1663 +#: sql_help.c:1667 sql_help.c:1670 sql_help.c:1673 sql_help.c:3923 +#: sql_help.c:4386 msgid "database_name" msgstr "имя_БД" -#: sql_help.c:1075 sql_help.c:2744 +#: sql_help.c:1089 sql_help.c:2757 msgid "increment" msgstr "шаг" -#: sql_help.c:1076 sql_help.c:2745 +#: sql_help.c:1090 sql_help.c:2758 msgid "minvalue" msgstr "мин_значение" -#: sql_help.c:1077 sql_help.c:2746 +#: sql_help.c:1091 sql_help.c:2759 msgid "maxvalue" msgstr "макс_значение" -#: sql_help.c:1078 sql_help.c:2747 sql_help.c:4585 sql_help.c:4688 -#: sql_help.c:4842 sql_help.c:5019 sql_help.c:5088 +#: sql_help.c:1092 sql_help.c:2760 sql_help.c:4606 sql_help.c:4710 +#: sql_help.c:4864 sql_help.c:5040 sql_help.c:5109 msgid "start" msgstr "начальное_значение" -#: sql_help.c:1079 sql_help.c:1348 +#: sql_help.c:1093 sql_help.c:1365 msgid "restart" msgstr "значение_перезапуска" -#: sql_help.c:1080 sql_help.c:2748 +#: sql_help.c:1094 sql_help.c:2761 msgid "cache" msgstr "кеш" -#: sql_help.c:1125 +#: sql_help.c:1139 msgid "new_target" msgstr "новое_имя" -#: sql_help.c:1144 sql_help.c:2801 +#: sql_help.c:1158 sql_help.c:2814 msgid "conninfo" msgstr "строка_подключения" -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:2802 +#: sql_help.c:1160 sql_help.c:1164 sql_help.c:1168 sql_help.c:2815 msgid "publication_name" msgstr "имя_публикации" -#: sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 +#: sql_help.c:1161 sql_help.c:1165 sql_help.c:1169 msgid "publication_option" msgstr "параметр_публикации" -#: sql_help.c:1158 +#: sql_help.c:1172 msgid "refresh_option" msgstr "параметр_обновления" -#: sql_help.c:1163 sql_help.c:2803 +#: sql_help.c:1177 sql_help.c:2816 msgid "subscription_parameter" msgstr "параметр_подписки" -#: sql_help.c:1166 +#: sql_help.c:1180 msgid "skip_option" msgstr "параметр_пропуска" -#: sql_help.c:1325 sql_help.c:1328 +#: sql_help.c:1340 sql_help.c:1343 msgid "partition_name" msgstr "имя_секции" -#: sql_help.c:1326 sql_help.c:2353 sql_help.c:2934 +#: sql_help.c:1341 sql_help.c:2370 sql_help.c:2947 msgid "partition_bound_spec" msgstr "указание_границ_секции" -#: sql_help.c:1345 sql_help.c:1395 sql_help.c:2948 +#: sql_help.c:1362 sql_help.c:1412 sql_help.c:2961 msgid "sequence_options" msgstr "параметры_последовательности" -#: sql_help.c:1347 +#: sql_help.c:1364 msgid "sequence_option" msgstr "параметр_последовательности" -#: sql_help.c:1361 +#: sql_help.c:1378 msgid "table_constraint_using_index" msgstr "ограничение_таблицы_с_индексом" -#: sql_help.c:1369 sql_help.c:1370 sql_help.c:1371 sql_help.c:1372 +#: sql_help.c:1386 sql_help.c:1387 sql_help.c:1388 sql_help.c:1389 msgid "rewrite_rule_name" msgstr "имя_правила_перезаписи" -#: sql_help.c:1384 sql_help.c:2365 sql_help.c:2973 +#: sql_help.c:1401 sql_help.c:2382 sql_help.c:2986 msgid "and partition_bound_spec is:" msgstr "и указание_границ_секции:" -#: sql_help.c:1385 sql_help.c:1386 sql_help.c:1387 sql_help.c:2366 -#: sql_help.c:2367 sql_help.c:2368 sql_help.c:2974 sql_help.c:2975 -#: sql_help.c:2976 +#: sql_help.c:1402 sql_help.c:1403 sql_help.c:1404 sql_help.c:2383 +#: sql_help.c:2384 sql_help.c:2385 sql_help.c:2987 sql_help.c:2988 +#: sql_help.c:2989 msgid "partition_bound_expr" msgstr "выражение_границ_секции" -#: sql_help.c:1388 sql_help.c:1389 sql_help.c:2369 sql_help.c:2370 -#: sql_help.c:2977 sql_help.c:2978 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:2386 sql_help.c:2387 +#: sql_help.c:2990 sql_help.c:2991 msgid "numeric_literal" msgstr "числовая_константа" -#: sql_help.c:1390 +#: sql_help.c:1407 msgid "and column_constraint is:" msgstr "и ограничение_столбца:" -#: sql_help.c:1393 sql_help.c:2360 sql_help.c:2401 sql_help.c:2610 -#: sql_help.c:2946 +#: sql_help.c:1410 sql_help.c:2377 sql_help.c:2418 sql_help.c:2627 +#: sql_help.c:2959 msgid "default_expr" msgstr "выражение_по_умолчанию" -#: sql_help.c:1394 sql_help.c:2361 sql_help.c:2947 +#: sql_help.c:1411 sql_help.c:2378 sql_help.c:2960 msgid "generation_expr" msgstr "генерирующее_выражение" -#: sql_help.c:1396 sql_help.c:1397 sql_help.c:1406 sql_help.c:1408 -#: sql_help.c:1412 sql_help.c:2949 sql_help.c:2950 sql_help.c:2959 -#: sql_help.c:2961 sql_help.c:2965 +#: sql_help.c:1413 sql_help.c:1414 sql_help.c:1423 sql_help.c:1425 +#: sql_help.c:1429 sql_help.c:2962 sql_help.c:2963 sql_help.c:2972 +#: sql_help.c:2974 sql_help.c:2978 msgid "index_parameters" msgstr "параметры_индекса" -#: sql_help.c:1398 sql_help.c:1415 sql_help.c:2951 sql_help.c:2968 +#: sql_help.c:1415 sql_help.c:1432 sql_help.c:2964 sql_help.c:2981 msgid "reftable" msgstr "целевая_таблица" -#: sql_help.c:1399 sql_help.c:1416 sql_help.c:2952 sql_help.c:2969 +#: sql_help.c:1416 sql_help.c:1433 sql_help.c:2965 sql_help.c:2982 msgid "refcolumn" msgstr "целевой_столбец" -#: sql_help.c:1400 sql_help.c:1401 sql_help.c:1417 sql_help.c:1418 -#: sql_help.c:2953 sql_help.c:2954 sql_help.c:2970 sql_help.c:2971 +#: sql_help.c:1417 sql_help.c:1418 sql_help.c:1434 sql_help.c:1435 +#: sql_help.c:2966 sql_help.c:2967 sql_help.c:2983 sql_help.c:2984 msgid "referential_action" msgstr "ссылочное_действие" -#: sql_help.c:1402 sql_help.c:2362 sql_help.c:2955 +#: sql_help.c:1419 sql_help.c:2379 sql_help.c:2968 msgid "and table_constraint is:" msgstr "и ограничение_таблицы:" -#: sql_help.c:1410 sql_help.c:2963 +#: sql_help.c:1427 sql_help.c:2976 msgid "exclude_element" msgstr "объект_исключения" -#: sql_help.c:1411 sql_help.c:2964 sql_help.c:4583 sql_help.c:4686 -#: sql_help.c:4840 sql_help.c:5017 sql_help.c:5086 +#: sql_help.c:1428 sql_help.c:2977 sql_help.c:4604 sql_help.c:4708 +#: sql_help.c:4862 sql_help.c:5038 sql_help.c:5107 msgid "operator" msgstr "оператор" -#: sql_help.c:1413 sql_help.c:2481 sql_help.c:2966 +#: sql_help.c:1430 sql_help.c:2498 sql_help.c:2979 msgid "predicate" msgstr "предикат" -#: sql_help.c:1419 +#: sql_help.c:1436 msgid "and table_constraint_using_index is:" msgstr "и ограничение_таблицы_с_индексом:" -#: sql_help.c:1422 sql_help.c:2979 +#: sql_help.c:1439 sql_help.c:2992 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "параметры_индекса в ограничениях UNIQUE, PRIMARY KEY и EXCLUDE:" -#: sql_help.c:1427 sql_help.c:2984 +#: sql_help.c:1444 sql_help.c:2997 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "объект_исключения в ограничении EXCLUDE:" -#: sql_help.c:1431 sql_help.c:2474 sql_help.c:2911 sql_help.c:2924 -#: sql_help.c:2938 sql_help.c:2988 sql_help.c:4008 +#: sql_help.c:1448 sql_help.c:2491 sql_help.c:2924 sql_help.c:2937 +#: sql_help.c:2951 sql_help.c:3001 sql_help.c:4022 msgid "opclass" msgstr "класс_оператора" -#: sql_help.c:1432 sql_help.c:2475 sql_help.c:2989 +#: sql_help.c:1449 sql_help.c:2492 sql_help.c:3002 msgid "opclass_parameter" msgstr "параметр_класса_оп" -#: sql_help.c:1434 sql_help.c:2991 +#: sql_help.c:1451 sql_help.c:3004 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "ссылочное действие в ограничении FOREIGN KEY/REFERENCES:" -#: sql_help.c:1452 sql_help.c:1455 sql_help.c:3028 +#: sql_help.c:1469 sql_help.c:1472 sql_help.c:3041 msgid "tablespace_option" msgstr "параметр_табл_пространства" -#: sql_help.c:1476 sql_help.c:1479 sql_help.c:1485 sql_help.c:1489 +#: sql_help.c:1493 sql_help.c:1496 sql_help.c:1502 sql_help.c:1506 msgid "token_type" msgstr "тип_фрагмента" -#: sql_help.c:1477 sql_help.c:1480 +#: sql_help.c:1494 sql_help.c:1497 msgid "dictionary_name" msgstr "имя_словаря" -#: sql_help.c:1482 sql_help.c:1486 +#: sql_help.c:1499 sql_help.c:1503 msgid "old_dictionary" msgstr "старый_словарь" -#: sql_help.c:1483 sql_help.c:1487 +#: sql_help.c:1500 sql_help.c:1504 msgid "new_dictionary" msgstr "новый_словарь" -#: sql_help.c:1582 sql_help.c:1596 sql_help.c:1599 sql_help.c:1600 -#: sql_help.c:3181 +#: sql_help.c:1599 sql_help.c:1613 sql_help.c:1616 sql_help.c:1617 +#: sql_help.c:3194 msgid "attribute_name" msgstr "имя_атрибута" -#: sql_help.c:1583 +#: sql_help.c:1600 msgid "new_attribute_name" msgstr "новое_имя_атрибута" -#: sql_help.c:1587 sql_help.c:1591 +#: sql_help.c:1604 sql_help.c:1608 msgid "new_enum_value" msgstr "новое_значение_перечисления" -#: sql_help.c:1588 +#: sql_help.c:1605 msgid "neighbor_enum_value" msgstr "соседнее_значение_перечисления" -#: sql_help.c:1590 +#: sql_help.c:1607 msgid "existing_enum_value" msgstr "существующее_значение_перечисления" -#: sql_help.c:1593 +#: sql_help.c:1610 msgid "property" msgstr "свойство" -#: sql_help.c:1669 sql_help.c:2345 sql_help.c:2354 sql_help.c:2760 -#: sql_help.c:3261 sql_help.c:3712 sql_help.c:3918 sql_help.c:3964 -#: sql_help.c:4374 +#: sql_help.c:1686 sql_help.c:2362 sql_help.c:2371 sql_help.c:2773 +#: sql_help.c:3274 sql_help.c:3725 sql_help.c:3932 sql_help.c:3978 +#: sql_help.c:4395 msgid "server_name" msgstr "имя_сервера" -#: sql_help.c:1701 sql_help.c:1704 sql_help.c:3276 +#: sql_help.c:1718 sql_help.c:1721 sql_help.c:3289 msgid "view_option_name" msgstr "имя_параметра_представления" -#: sql_help.c:1702 sql_help.c:3277 +#: sql_help.c:1719 sql_help.c:3290 msgid "view_option_value" msgstr "значение_параметра_представления" -#: sql_help.c:1724 sql_help.c:1725 sql_help.c:4985 sql_help.c:4986 +#: sql_help.c:1740 sql_help.c:5007 msgid "table_and_columns" msgstr "таблица_и_столбцы" -#: sql_help.c:1726 sql_help.c:1790 sql_help.c:1982 sql_help.c:3761 -#: sql_help.c:4209 sql_help.c:4987 +#: sql_help.c:1741 sql_help.c:1801 sql_help.c:1995 sql_help.c:3774 +#: sql_help.c:4230 sql_help.c:5008 msgid "where option can be one of:" msgstr "где допустимый параметр:" -#: sql_help.c:1727 sql_help.c:1728 sql_help.c:1791 sql_help.c:1984 -#: sql_help.c:1988 sql_help.c:2168 sql_help.c:3762 sql_help.c:3763 -#: sql_help.c:3764 sql_help.c:3765 sql_help.c:3766 sql_help.c:3767 -#: sql_help.c:3768 sql_help.c:3769 sql_help.c:3770 sql_help.c:4210 -#: sql_help.c:4212 sql_help.c:4988 sql_help.c:4989 sql_help.c:4990 -#: sql_help.c:4991 sql_help.c:4992 sql_help.c:4993 sql_help.c:4994 -#: sql_help.c:4995 sql_help.c:4996 sql_help.c:4998 sql_help.c:4999 +#: sql_help.c:1742 sql_help.c:1743 sql_help.c:1802 sql_help.c:1997 +#: sql_help.c:2001 sql_help.c:2183 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:3777 sql_help.c:3778 sql_help.c:3779 sql_help.c:3780 +#: sql_help.c:3781 sql_help.c:3782 sql_help.c:3783 sql_help.c:3784 +#: sql_help.c:4231 sql_help.c:4233 sql_help.c:5009 sql_help.c:5010 +#: sql_help.c:5011 sql_help.c:5012 sql_help.c:5013 sql_help.c:5014 +#: sql_help.c:5015 sql_help.c:5016 sql_help.c:5017 sql_help.c:5019 +#: sql_help.c:5020 msgid "boolean" msgstr "логическое_значение" -#: sql_help.c:1729 sql_help.c:5000 +#: sql_help.c:1744 sql_help.c:5021 msgid "size" msgstr "размер" -#: sql_help.c:1730 sql_help.c:5001 +#: sql_help.c:1745 sql_help.c:5022 msgid "and table_and_columns is:" msgstr "и таблица_и_столбцы:" -#: sql_help.c:1746 sql_help.c:4747 sql_help.c:4749 sql_help.c:4773 +#: sql_help.c:1761 sql_help.c:4769 sql_help.c:4771 sql_help.c:4795 msgid "transaction_mode" msgstr "режим_транзакции" -#: sql_help.c:1747 sql_help.c:4750 sql_help.c:4774 +#: sql_help.c:1762 sql_help.c:4772 sql_help.c:4796 msgid "where transaction_mode is one of:" msgstr "где допустимый режим_транзакции:" -#: sql_help.c:1756 sql_help.c:4593 sql_help.c:4602 sql_help.c:4606 -#: sql_help.c:4610 sql_help.c:4613 sql_help.c:4850 sql_help.c:4859 -#: sql_help.c:4863 sql_help.c:4867 sql_help.c:4870 sql_help.c:5096 -#: sql_help.c:5105 sql_help.c:5109 sql_help.c:5113 sql_help.c:5116 +#: sql_help.c:1771 sql_help.c:4614 sql_help.c:4623 sql_help.c:4627 +#: sql_help.c:4631 sql_help.c:4634 sql_help.c:4872 sql_help.c:4881 +#: sql_help.c:4885 sql_help.c:4889 sql_help.c:4892 sql_help.c:5117 +#: sql_help.c:5126 sql_help.c:5130 sql_help.c:5134 sql_help.c:5137 msgid "argument" msgstr "аргумент" -#: sql_help.c:1856 +#: sql_help.c:1867 msgid "relation_name" msgstr "имя_отношения" -#: sql_help.c:1861 sql_help.c:3912 sql_help.c:4368 +#: sql_help.c:1872 sql_help.c:3926 sql_help.c:4389 msgid "domain_name" msgstr "имя_домена" -#: sql_help.c:1883 +#: sql_help.c:1894 msgid "policy_name" msgstr "имя_политики" -#: sql_help.c:1896 +#: sql_help.c:1907 msgid "rule_name" msgstr "имя_правила" -#: sql_help.c:1915 sql_help.c:4507 +#: sql_help.c:1926 sql_help.c:4528 msgid "string_literal" msgstr "строковая_константа" -#: sql_help.c:1940 sql_help.c:4171 sql_help.c:4421 +#: sql_help.c:1951 sql_help.c:4192 sql_help.c:4442 msgid "transaction_id" msgstr "код_транзакции" -#: sql_help.c:1972 sql_help.c:1979 sql_help.c:4034 +#: sql_help.c:1985 sql_help.c:1992 sql_help.c:4048 msgid "filename" msgstr "имя_файла" -#: sql_help.c:1973 sql_help.c:1980 sql_help.c:2699 sql_help.c:2700 -#: sql_help.c:2701 +#: sql_help.c:1986 sql_help.c:1993 sql_help.c:2712 sql_help.c:2713 +#: sql_help.c:2714 msgid "command" msgstr "команда" -#: sql_help.c:1975 sql_help.c:2698 sql_help.c:3131 sql_help.c:3312 -#: sql_help.c:4018 sql_help.c:4097 sql_help.c:4100 sql_help.c:4576 -#: sql_help.c:4578 sql_help.c:4679 sql_help.c:4681 sql_help.c:4833 -#: sql_help.c:4835 sql_help.c:4951 sql_help.c:5079 sql_help.c:5081 +#: sql_help.c:1988 sql_help.c:2711 sql_help.c:3144 sql_help.c:3325 +#: sql_help.c:4032 sql_help.c:4115 sql_help.c:4118 sql_help.c:4121 +#: sql_help.c:4597 sql_help.c:4599 sql_help.c:4701 sql_help.c:4703 +#: sql_help.c:4855 sql_help.c:4857 sql_help.c:4974 sql_help.c:5100 +#: sql_help.c:5102 msgid "condition" msgstr "условие" -#: sql_help.c:1978 sql_help.c:2515 sql_help.c:3014 sql_help.c:3278 -#: sql_help.c:3296 sql_help.c:3999 +#: sql_help.c:1991 sql_help.c:2532 sql_help.c:3027 sql_help.c:3291 +#: sql_help.c:3309 sql_help.c:4013 msgid "query" msgstr "запрос" -#: sql_help.c:1983 +#: sql_help.c:1996 msgid "format_name" msgstr "имя_формата" -#: sql_help.c:1985 +#: sql_help.c:1998 msgid "delimiter_character" msgstr "символ_разделитель" -#: sql_help.c:1986 +#: sql_help.c:1999 msgid "null_string" msgstr "представление_NULL" -#: sql_help.c:1987 +#: sql_help.c:2000 msgid "default_string" msgstr "представление_DEFAULT" -#: sql_help.c:1989 +#: sql_help.c:2002 msgid "quote_character" msgstr "символ_кавычек" -#: sql_help.c:1990 +#: sql_help.c:2003 msgid "escape_character" msgstr "спецсимвол" -#: sql_help.c:1994 +#: sql_help.c:2007 +msgid "error_action" +msgstr "действие_при_ошибке" + +#: sql_help.c:2008 msgid "encoding_name" msgstr "имя_кодировки" -#: sql_help.c:2005 +#: sql_help.c:2009 +msgid "verbosity" +msgstr "детализация" + +#: sql_help.c:2020 msgid "access_method_type" msgstr "тип_метода_доступа" -#: sql_help.c:2076 sql_help.c:2095 sql_help.c:2098 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2113 msgid "arg_data_type" msgstr "тип_данных_аргумента" -#: sql_help.c:2077 sql_help.c:2099 sql_help.c:2107 +#: sql_help.c:2092 sql_help.c:2114 sql_help.c:2122 msgid "sfunc" msgstr "функция_состояния" -#: sql_help.c:2078 sql_help.c:2100 sql_help.c:2108 +#: sql_help.c:2093 sql_help.c:2115 sql_help.c:2123 msgid "state_data_type" msgstr "тип_данных_состояния" -#: sql_help.c:2079 sql_help.c:2101 sql_help.c:2109 +#: sql_help.c:2094 sql_help.c:2116 sql_help.c:2124 msgid "state_data_size" msgstr "размер_данных_состояния" -#: sql_help.c:2080 sql_help.c:2102 sql_help.c:2110 +#: sql_help.c:2095 sql_help.c:2117 sql_help.c:2125 msgid "ffunc" msgstr "функция_завершения" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2096 sql_help.c:2126 msgid "combinefunc" msgstr "комбинирующая_функция" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2097 sql_help.c:2127 msgid "serialfunc" msgstr "функция_сериализации" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2098 sql_help.c:2128 msgid "deserialfunc" msgstr "функция_десериализации" -#: sql_help.c:2084 sql_help.c:2103 sql_help.c:2114 +#: sql_help.c:2099 sql_help.c:2118 sql_help.c:2129 msgid "initial_condition" msgstr "начальное_условие" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2100 sql_help.c:2130 msgid "msfunc" msgstr "функция_состояния_движ" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2101 sql_help.c:2131 msgid "minvfunc" msgstr "обратная_функция_движ" -#: sql_help.c:2087 sql_help.c:2117 +#: sql_help.c:2102 sql_help.c:2132 msgid "mstate_data_type" msgstr "тип_данных_состояния_движ" -#: sql_help.c:2088 sql_help.c:2118 +#: sql_help.c:2103 sql_help.c:2133 msgid "mstate_data_size" msgstr "размер_данных_состояния_движ" -#: sql_help.c:2089 sql_help.c:2119 +#: sql_help.c:2104 sql_help.c:2134 msgid "mffunc" msgstr "функция_завершения_движ" -#: sql_help.c:2090 sql_help.c:2120 +#: sql_help.c:2105 sql_help.c:2135 msgid "minitial_condition" msgstr "начальное_условие_движ" -#: sql_help.c:2091 sql_help.c:2121 +#: sql_help.c:2106 sql_help.c:2136 msgid "sort_operator" msgstr "оператор_сортировки" -#: sql_help.c:2104 +#: sql_help.c:2119 msgid "or the old syntax" msgstr "или старый синтаксис" -#: sql_help.c:2106 +#: sql_help.c:2121 msgid "base_type" msgstr "базовый_тип" -#: sql_help.c:2164 sql_help.c:2213 +#: sql_help.c:2179 sql_help.c:2229 msgid "locale" msgstr "код_локали" -#: sql_help.c:2165 sql_help.c:2214 +#: sql_help.c:2180 sql_help.c:2230 msgid "lc_collate" msgstr "код_правила_сортировки" -#: sql_help.c:2166 sql_help.c:2215 +#: sql_help.c:2181 sql_help.c:2231 msgid "lc_ctype" msgstr "код_классификации_символов" -#: sql_help.c:2167 sql_help.c:4474 +#: sql_help.c:2182 sql_help.c:4495 msgid "provider" msgstr "провайдер" -#: sql_help.c:2169 +#: sql_help.c:2184 msgid "rules" msgstr "правила" -#: sql_help.c:2170 sql_help.c:2275 +#: sql_help.c:2185 sql_help.c:2292 msgid "version" msgstr "версия" -#: sql_help.c:2172 +#: sql_help.c:2187 msgid "existing_collation" msgstr "существующее_правило_сортировки" -#: sql_help.c:2182 +#: sql_help.c:2197 msgid "source_encoding" msgstr "исходная_кодировка" -#: sql_help.c:2183 +#: sql_help.c:2198 msgid "dest_encoding" msgstr "целевая_кодировка" -#: sql_help.c:2210 sql_help.c:3054 +#: sql_help.c:2226 sql_help.c:3067 msgid "template" msgstr "шаблон" -#: sql_help.c:2211 +#: sql_help.c:2227 msgid "encoding" msgstr "кодировка" -#: sql_help.c:2212 +#: sql_help.c:2228 msgid "strategy" msgstr "стратегия" -#: sql_help.c:2216 +#: sql_help.c:2232 +msgid "builtin_locale" +msgstr "встроенная_локаль" + +#: sql_help.c:2233 msgid "icu_locale" msgstr "локаль_icu" -#: sql_help.c:2217 +#: sql_help.c:2234 msgid "icu_rules" msgstr "правила_icu" -#: sql_help.c:2218 +#: sql_help.c:2235 msgid "locale_provider" msgstr "провайдер_локали" -#: sql_help.c:2219 +#: sql_help.c:2236 msgid "collation_version" msgstr "версия_правила_сортировки" -#: sql_help.c:2224 +#: sql_help.c:2241 msgid "oid" msgstr "oid" -#: sql_help.c:2244 -msgid "constraint" -msgstr "ограничение" - -#: sql_help.c:2245 -msgid "where constraint is:" -msgstr "где ограничение:" - -#: sql_help.c:2259 sql_help.c:2696 sql_help.c:3127 +#: sql_help.c:2276 sql_help.c:2709 sql_help.c:3140 msgid "event" msgstr "событие" -#: sql_help.c:2260 +#: sql_help.c:2277 msgid "filter_variable" msgstr "переменная_фильтра" -#: sql_help.c:2261 +#: sql_help.c:2278 msgid "filter_value" msgstr "значение_фильтра" -#: sql_help.c:2357 sql_help.c:2943 +#: sql_help.c:2374 sql_help.c:2956 msgid "where column_constraint is:" msgstr "где ограничение_столбца:" -#: sql_help.c:2402 +#: sql_help.c:2419 msgid "rettype" msgstr "тип_возврата" -#: sql_help.c:2404 +#: sql_help.c:2421 msgid "column_type" msgstr "тип_столбца" -#: sql_help.c:2413 sql_help.c:2616 +#: sql_help.c:2430 sql_help.c:2633 msgid "definition" msgstr "определение" -#: sql_help.c:2414 sql_help.c:2617 +#: sql_help.c:2431 sql_help.c:2634 msgid "obj_file" msgstr "объектный_файл" -#: sql_help.c:2415 sql_help.c:2618 +#: sql_help.c:2432 sql_help.c:2635 msgid "link_symbol" msgstr "символ_в_экспорте" -#: sql_help.c:2416 sql_help.c:2619 +#: sql_help.c:2433 sql_help.c:2636 msgid "sql_body" msgstr "тело_sql" -#: sql_help.c:2454 sql_help.c:2681 sql_help.c:3250 +#: sql_help.c:2471 sql_help.c:2694 sql_help.c:3263 msgid "uid" msgstr "uid" -#: sql_help.c:2470 sql_help.c:2511 sql_help.c:2912 sql_help.c:2925 -#: sql_help.c:2939 sql_help.c:3010 +#: sql_help.c:2487 sql_help.c:2528 sql_help.c:2925 sql_help.c:2938 +#: sql_help.c:2952 sql_help.c:3023 msgid "method" msgstr "метод" -#: sql_help.c:2492 +#: sql_help.c:2509 msgid "call_handler" msgstr "обработчик_вызова" -#: sql_help.c:2493 +#: sql_help.c:2510 msgid "inline_handler" msgstr "обработчик_внедрённого_кода" -#: sql_help.c:2494 +#: sql_help.c:2511 msgid "valfunction" msgstr "функция_проверки" -#: sql_help.c:2533 -msgid "com_op" -msgstr "коммут_оператор" - -#: sql_help.c:2534 -msgid "neg_op" -msgstr "обратный_оператор" - -#: sql_help.c:2552 +#: sql_help.c:2569 msgid "family_name" msgstr "имя_семейства" -#: sql_help.c:2563 +#: sql_help.c:2580 msgid "storage_type" msgstr "тип_хранения" -#: sql_help.c:2702 sql_help.c:3134 +#: sql_help.c:2715 sql_help.c:3147 msgid "where event can be one of:" msgstr "где допустимое событие:" -#: sql_help.c:2722 sql_help.c:2724 +#: sql_help.c:2735 sql_help.c:2737 msgid "schema_element" msgstr "элемент_схемы" -#: sql_help.c:2761 +#: sql_help.c:2774 msgid "server_type" msgstr "тип_сервера" -#: sql_help.c:2762 +#: sql_help.c:2775 msgid "server_version" msgstr "версия_сервера" -#: sql_help.c:2763 sql_help.c:3915 sql_help.c:4371 +#: sql_help.c:2776 sql_help.c:3929 sql_help.c:4392 msgid "fdw_name" msgstr "имя_обёртки_сторонних_данных" -#: sql_help.c:2780 sql_help.c:2783 +#: sql_help.c:2793 sql_help.c:2796 msgid "statistics_name" msgstr "имя_статистики" -#: sql_help.c:2784 +#: sql_help.c:2797 msgid "statistics_kind" msgstr "вид_статистики" -#: sql_help.c:2800 +#: sql_help.c:2813 msgid "subscription_name" msgstr "имя_подписки" -#: sql_help.c:2905 +#: sql_help.c:2918 msgid "source_table" msgstr "исходная_таблица" -#: sql_help.c:2906 +#: sql_help.c:2919 msgid "like_option" msgstr "параметр_порождения" -#: sql_help.c:2972 +#: sql_help.c:2985 msgid "and like_option is:" msgstr "и параметр_порождения:" -#: sql_help.c:3027 +#: sql_help.c:3040 msgid "directory" msgstr "каталог" -#: sql_help.c:3041 +#: sql_help.c:3054 msgid "parser_name" msgstr "имя_анализатора" -#: sql_help.c:3042 +#: sql_help.c:3055 msgid "source_config" msgstr "исходная_конфигурация" -#: sql_help.c:3071 +#: sql_help.c:3084 msgid "start_function" msgstr "функция_начала" -#: sql_help.c:3072 +#: sql_help.c:3085 msgid "gettoken_function" msgstr "функция_выдачи_фрагмента" -#: sql_help.c:3073 +#: sql_help.c:3086 msgid "end_function" msgstr "функция_окончания" -#: sql_help.c:3074 +#: sql_help.c:3087 msgid "lextypes_function" msgstr "функция_лекс_типов" -#: sql_help.c:3075 +#: sql_help.c:3088 msgid "headline_function" msgstr "функция_создания_выдержек" -#: sql_help.c:3087 +#: sql_help.c:3100 msgid "init_function" msgstr "функция_инициализации" -#: sql_help.c:3088 +#: sql_help.c:3101 msgid "lexize_function" msgstr "функция_выделения_лексем" -#: sql_help.c:3101 +#: sql_help.c:3114 msgid "from_sql_function_name" msgstr "имя_функции_из_sql" -#: sql_help.c:3103 +#: sql_help.c:3116 msgid "to_sql_function_name" msgstr "имя_функции_в_sql" -#: sql_help.c:3129 +#: sql_help.c:3142 msgid "referenced_table_name" msgstr "ссылающаяся_таблица" -#: sql_help.c:3130 +#: sql_help.c:3143 msgid "transition_relation_name" msgstr "имя_переходного_отношения" -#: sql_help.c:3133 +#: sql_help.c:3146 msgid "arguments" msgstr "аргументы" -#: sql_help.c:3185 +#: sql_help.c:3198 msgid "label" msgstr "метка" -#: sql_help.c:3187 +#: sql_help.c:3200 msgid "subtype" msgstr "подтип" -#: sql_help.c:3188 +#: sql_help.c:3201 msgid "subtype_operator_class" msgstr "класс_оператора_подтипа" -#: sql_help.c:3190 +#: sql_help.c:3203 msgid "canonical_function" msgstr "каноническая_функция" -#: sql_help.c:3191 +#: sql_help.c:3204 msgid "subtype_diff_function" msgstr "функция_различий_подтипа" -#: sql_help.c:3192 +#: sql_help.c:3205 msgid "multirange_type_name" msgstr "имя_мультидиапазонного_типа" -#: sql_help.c:3194 +#: sql_help.c:3207 msgid "input_function" msgstr "функция_ввода" -#: sql_help.c:3195 +#: sql_help.c:3208 msgid "output_function" msgstr "функция_вывода" -#: sql_help.c:3196 +#: sql_help.c:3209 msgid "receive_function" msgstr "функция_получения" -#: sql_help.c:3197 +#: sql_help.c:3210 msgid "send_function" msgstr "функция_отправки" -#: sql_help.c:3198 +#: sql_help.c:3211 msgid "type_modifier_input_function" msgstr "функция_ввода_модификатора_типа" -#: sql_help.c:3199 +#: sql_help.c:3212 msgid "type_modifier_output_function" msgstr "функция_вывода_модификатора_типа" -#: sql_help.c:3200 +#: sql_help.c:3213 msgid "analyze_function" msgstr "функция_анализа" -#: sql_help.c:3201 +#: sql_help.c:3214 msgid "subscript_function" msgstr "функция_обращения_по_индексу" -#: sql_help.c:3202 +#: sql_help.c:3215 msgid "internallength" msgstr "внутр_длина" -#: sql_help.c:3203 +#: sql_help.c:3216 msgid "alignment" msgstr "выравнивание" -#: sql_help.c:3204 +#: sql_help.c:3217 msgid "storage" msgstr "хранение" -#: sql_help.c:3205 +#: sql_help.c:3218 msgid "like_type" msgstr "тип_образец" -#: sql_help.c:3206 +#: sql_help.c:3219 msgid "category" msgstr "категория" -#: sql_help.c:3207 +#: sql_help.c:3220 msgid "preferred" msgstr "предпочитаемый" -#: sql_help.c:3208 +#: sql_help.c:3221 msgid "default" msgstr "по_умолчанию" -#: sql_help.c:3209 +#: sql_help.c:3222 msgid "element" msgstr "элемент" -#: sql_help.c:3210 +#: sql_help.c:3223 msgid "delimiter" msgstr "разделитель" -#: sql_help.c:3211 +#: sql_help.c:3224 msgid "collatable" msgstr "сортируемый" -#: sql_help.c:3308 sql_help.c:3994 sql_help.c:4086 sql_help.c:4571 -#: sql_help.c:4673 sql_help.c:4828 sql_help.c:4941 sql_help.c:5074 +#: sql_help.c:3321 sql_help.c:4008 sql_help.c:4102 sql_help.c:4592 +#: sql_help.c:4695 sql_help.c:4850 sql_help.c:4964 sql_help.c:5095 msgid "with_query" msgstr "запрос_WITH" -#: sql_help.c:3310 sql_help.c:3996 sql_help.c:4590 sql_help.c:4596 -#: sql_help.c:4599 sql_help.c:4603 sql_help.c:4607 sql_help.c:4615 -#: sql_help.c:4847 sql_help.c:4853 sql_help.c:4856 sql_help.c:4860 -#: sql_help.c:4864 sql_help.c:4872 sql_help.c:4943 sql_help.c:5093 -#: sql_help.c:5099 sql_help.c:5102 sql_help.c:5106 sql_help.c:5110 -#: sql_help.c:5118 +#: sql_help.c:3323 sql_help.c:4010 sql_help.c:4611 sql_help.c:4617 +#: sql_help.c:4620 sql_help.c:4624 sql_help.c:4628 sql_help.c:4636 +#: sql_help.c:4869 sql_help.c:4875 sql_help.c:4878 sql_help.c:4882 +#: sql_help.c:4886 sql_help.c:4894 sql_help.c:4966 sql_help.c:5114 +#: sql_help.c:5120 sql_help.c:5123 sql_help.c:5127 sql_help.c:5131 +#: sql_help.c:5139 msgid "alias" msgstr "псевдоним" -#: sql_help.c:3311 sql_help.c:4575 sql_help.c:4617 sql_help.c:4619 -#: sql_help.c:4623 sql_help.c:4625 sql_help.c:4626 sql_help.c:4627 -#: sql_help.c:4678 sql_help.c:4832 sql_help.c:4874 sql_help.c:4876 -#: sql_help.c:4880 sql_help.c:4882 sql_help.c:4883 sql_help.c:4884 -#: sql_help.c:4950 sql_help.c:5078 sql_help.c:5120 sql_help.c:5122 -#: sql_help.c:5126 sql_help.c:5128 sql_help.c:5129 sql_help.c:5130 +#: sql_help.c:3324 sql_help.c:4596 sql_help.c:4638 sql_help.c:4640 +#: sql_help.c:4644 sql_help.c:4646 sql_help.c:4647 sql_help.c:4648 +#: sql_help.c:4700 sql_help.c:4854 sql_help.c:4896 sql_help.c:4898 +#: sql_help.c:4902 sql_help.c:4904 sql_help.c:4905 sql_help.c:4906 +#: sql_help.c:4973 sql_help.c:5099 sql_help.c:5141 sql_help.c:5143 +#: sql_help.c:5147 sql_help.c:5149 sql_help.c:5150 sql_help.c:5151 msgid "from_item" msgstr "источник_данных" -#: sql_help.c:3313 sql_help.c:3796 sql_help.c:4138 sql_help.c:4952 +#: sql_help.c:3326 sql_help.c:3810 sql_help.c:4159 sql_help.c:4975 msgid "cursor_name" msgstr "имя_курсора" -#: sql_help.c:3314 sql_help.c:4002 sql_help.c:4953 +#: sql_help.c:3327 sql_help.c:4016 sql_help.c:4108 sql_help.c:4976 msgid "output_expression" msgstr "выражение_результата" -#: sql_help.c:3315 sql_help.c:4003 sql_help.c:4574 sql_help.c:4676 -#: sql_help.c:4831 sql_help.c:4954 sql_help.c:5077 +#: sql_help.c:3328 sql_help.c:4017 sql_help.c:4109 sql_help.c:4595 +#: sql_help.c:4698 sql_help.c:4853 sql_help.c:4977 sql_help.c:5098 msgid "output_name" msgstr "имя_результата" -#: sql_help.c:3331 +#: sql_help.c:3344 msgid "code" msgstr "внедрённый_код" -#: sql_help.c:3736 +#: sql_help.c:3749 msgid "parameter" msgstr "параметр" -#: sql_help.c:3759 sql_help.c:3760 sql_help.c:4163 +#: sql_help.c:3773 sql_help.c:4184 msgid "statement" msgstr "оператор" -#: sql_help.c:3795 sql_help.c:4137 +#: sql_help.c:3809 sql_help.c:4158 msgid "direction" msgstr "направление" -#: sql_help.c:3797 sql_help.c:4139 +#: sql_help.c:3811 sql_help.c:4160 msgid "where direction can be one of:" msgstr "где допустимое направление:" -#: sql_help.c:3798 sql_help.c:3799 sql_help.c:3800 sql_help.c:3801 -#: sql_help.c:3802 sql_help.c:4140 sql_help.c:4141 sql_help.c:4142 -#: sql_help.c:4143 sql_help.c:4144 sql_help.c:4584 sql_help.c:4586 -#: sql_help.c:4687 sql_help.c:4689 sql_help.c:4841 sql_help.c:4843 -#: sql_help.c:5018 sql_help.c:5020 sql_help.c:5087 sql_help.c:5089 +#: sql_help.c:3812 sql_help.c:3813 sql_help.c:3814 sql_help.c:3815 +#: sql_help.c:3816 sql_help.c:4161 sql_help.c:4162 sql_help.c:4163 +#: sql_help.c:4164 sql_help.c:4165 sql_help.c:4605 sql_help.c:4607 +#: sql_help.c:4709 sql_help.c:4711 sql_help.c:4863 sql_help.c:4865 +#: sql_help.c:5039 sql_help.c:5041 sql_help.c:5108 sql_help.c:5110 msgid "count" msgstr "число" -#: sql_help.c:3905 sql_help.c:4361 +#: sql_help.c:3919 sql_help.c:4382 msgid "sequence_name" msgstr "имя_последовательности" -#: sql_help.c:3923 sql_help.c:4379 +#: sql_help.c:3937 sql_help.c:4400 msgid "arg_name" msgstr "имя_аргумента" -#: sql_help.c:3924 sql_help.c:4380 +#: sql_help.c:3938 sql_help.c:4401 msgid "arg_type" msgstr "тип_аргумента" -#: sql_help.c:3931 sql_help.c:4387 +#: sql_help.c:3945 sql_help.c:4408 msgid "loid" msgstr "код_БО" -#: sql_help.c:3962 +#: sql_help.c:3976 msgid "remote_schema" msgstr "удалённая_схема" -#: sql_help.c:3965 +#: sql_help.c:3979 msgid "local_schema" msgstr "локальная_схема" -#: sql_help.c:4000 +#: sql_help.c:4014 msgid "conflict_target" msgstr "объект_конфликта" -#: sql_help.c:4001 +#: sql_help.c:4015 msgid "conflict_action" msgstr "действие_при_конфликте" -#: sql_help.c:4004 +#: sql_help.c:4018 msgid "where conflict_target can be one of:" msgstr "где допустимый объект_конфликта:" -#: sql_help.c:4005 +#: sql_help.c:4019 msgid "index_column_name" msgstr "имя_столбца_индекса" -#: sql_help.c:4006 +#: sql_help.c:4020 msgid "index_expression" msgstr "выражение_индекса" -#: sql_help.c:4009 +#: sql_help.c:4023 msgid "index_predicate" msgstr "предикат_индекса" -#: sql_help.c:4011 +#: sql_help.c:4025 msgid "and conflict_action is one of:" msgstr "а допустимое действие_при_конфликте:" -#: sql_help.c:4017 sql_help.c:4111 sql_help.c:4949 +#: sql_help.c:4031 sql_help.c:4132 sql_help.c:4972 msgid "sub-SELECT" msgstr "вложенный_SELECT" -#: sql_help.c:4026 sql_help.c:4152 sql_help.c:4925 +#: sql_help.c:4040 sql_help.c:4173 sql_help.c:4948 msgid "channel" msgstr "канал" -#: sql_help.c:4048 +#: sql_help.c:4062 msgid "lockmode" msgstr "режим_блокировки" -#: sql_help.c:4049 +#: sql_help.c:4063 msgid "where lockmode is one of:" msgstr "где допустимый режим_блокировки:" -#: sql_help.c:4087 +#: sql_help.c:4103 msgid "target_table_name" msgstr "имя_целевой_таблицы" -#: sql_help.c:4088 +#: sql_help.c:4104 msgid "target_alias" msgstr "псевдоним_назначения" -#: sql_help.c:4089 +#: sql_help.c:4105 msgid "data_source" msgstr "источник_данных" -#: sql_help.c:4090 sql_help.c:4620 sql_help.c:4877 sql_help.c:5123 +#: sql_help.c:4106 sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "join_condition" msgstr "условие_соединения" -#: sql_help.c:4091 +#: sql_help.c:4107 msgid "when_clause" msgstr "предложение_when" -#: sql_help.c:4092 +#: sql_help.c:4110 msgid "where data_source is:" msgstr "где источник_данных:" -#: sql_help.c:4093 +#: sql_help.c:4111 msgid "source_table_name" msgstr "имя_исходной_таблицы" -#: sql_help.c:4094 +#: sql_help.c:4112 msgid "source_query" msgstr "исходный_запрос" -#: sql_help.c:4095 +#: sql_help.c:4113 msgid "source_alias" msgstr "псевдоним_источника" -#: sql_help.c:4096 +#: sql_help.c:4114 msgid "and when_clause is:" msgstr "и предложение_when:" -#: sql_help.c:4098 +#: sql_help.c:4116 sql_help.c:4119 msgid "merge_update" msgstr "merge_update" -#: sql_help.c:4099 +#: sql_help.c:4117 sql_help.c:4120 msgid "merge_delete" msgstr "merge_delete" -#: sql_help.c:4101 +#: sql_help.c:4122 msgid "merge_insert" msgstr "merge_insert" -#: sql_help.c:4102 +#: sql_help.c:4123 msgid "and merge_insert is:" msgstr "и merge_insert:" -#: sql_help.c:4105 +#: sql_help.c:4126 msgid "and merge_update is:" msgstr "и merge_update:" -#: sql_help.c:4112 +#: sql_help.c:4133 msgid "and merge_delete is:" msgstr "и merge_delete:" -#: sql_help.c:4153 +#: sql_help.c:4174 msgid "payload" msgstr "сообщение_нагрузка" -#: sql_help.c:4180 +#: sql_help.c:4201 msgid "old_role" msgstr "старая_роль" -#: sql_help.c:4181 +#: sql_help.c:4202 msgid "new_role" msgstr "новая_роль" -#: sql_help.c:4220 sql_help.c:4429 sql_help.c:4437 +#: sql_help.c:4241 sql_help.c:4450 sql_help.c:4458 msgid "savepoint_name" msgstr "имя_точки_сохранения" -#: sql_help.c:4577 sql_help.c:4635 sql_help.c:4834 sql_help.c:4892 -#: sql_help.c:5080 sql_help.c:5138 +#: sql_help.c:4598 sql_help.c:4656 sql_help.c:4856 sql_help.c:4914 +#: sql_help.c:5101 sql_help.c:5159 msgid "grouping_element" msgstr "элемент_группирования" -#: sql_help.c:4579 sql_help.c:4682 sql_help.c:4836 sql_help.c:5082 +#: sql_help.c:4600 sql_help.c:4704 sql_help.c:4858 sql_help.c:5103 msgid "window_name" msgstr "имя_окна" -#: sql_help.c:4580 sql_help.c:4683 sql_help.c:4837 sql_help.c:5083 +#: sql_help.c:4601 sql_help.c:4705 sql_help.c:4859 sql_help.c:5104 msgid "window_definition" msgstr "определение_окна" -#: sql_help.c:4581 sql_help.c:4595 sql_help.c:4639 sql_help.c:4684 -#: sql_help.c:4838 sql_help.c:4852 sql_help.c:4896 sql_help.c:5084 -#: sql_help.c:5098 sql_help.c:5142 +#: sql_help.c:4602 sql_help.c:4616 sql_help.c:4660 sql_help.c:4706 +#: sql_help.c:4860 sql_help.c:4874 sql_help.c:4918 sql_help.c:5105 +#: sql_help.c:5119 sql_help.c:5163 msgid "select" msgstr "select" -#: sql_help.c:4588 sql_help.c:4845 sql_help.c:5091 +#: sql_help.c:4608 sql_help.c:4866 sql_help.c:5111 +msgid "from_reference" +msgstr "ссылка_FROM" + +#: sql_help.c:4609 sql_help.c:4867 sql_help.c:5112 msgid "where from_item can be one of:" msgstr "где допустимый источник_данных:" -#: sql_help.c:4591 sql_help.c:4597 sql_help.c:4600 sql_help.c:4604 -#: sql_help.c:4616 sql_help.c:4848 sql_help.c:4854 sql_help.c:4857 -#: sql_help.c:4861 sql_help.c:4873 sql_help.c:5094 sql_help.c:5100 -#: sql_help.c:5103 sql_help.c:5107 sql_help.c:5119 +#: sql_help.c:4612 sql_help.c:4618 sql_help.c:4621 sql_help.c:4625 +#: sql_help.c:4637 sql_help.c:4870 sql_help.c:4876 sql_help.c:4879 +#: sql_help.c:4883 sql_help.c:4895 sql_help.c:5115 sql_help.c:5121 +#: sql_help.c:5124 sql_help.c:5128 sql_help.c:5140 msgid "column_alias" msgstr "псевдоним_столбца" -#: sql_help.c:4592 sql_help.c:4849 sql_help.c:5095 +#: sql_help.c:4613 sql_help.c:4871 sql_help.c:5116 msgid "sampling_method" msgstr "метод_выборки" -#: sql_help.c:4594 sql_help.c:4851 sql_help.c:5097 +#: sql_help.c:4615 sql_help.c:4873 sql_help.c:5118 msgid "seed" msgstr "начальное_число" -#: sql_help.c:4598 sql_help.c:4637 sql_help.c:4855 sql_help.c:4894 -#: sql_help.c:5101 sql_help.c:5140 +#: sql_help.c:4619 sql_help.c:4658 sql_help.c:4877 sql_help.c:4916 +#: sql_help.c:5122 sql_help.c:5161 msgid "with_query_name" msgstr "имя_запроса_WITH" -#: sql_help.c:4608 sql_help.c:4611 sql_help.c:4614 sql_help.c:4865 -#: sql_help.c:4868 sql_help.c:4871 sql_help.c:5111 sql_help.c:5114 -#: sql_help.c:5117 +#: sql_help.c:4629 sql_help.c:4632 sql_help.c:4635 sql_help.c:4887 +#: sql_help.c:4890 sql_help.c:4893 sql_help.c:5132 sql_help.c:5135 +#: sql_help.c:5138 msgid "column_definition" msgstr "определение_столбца" -#: sql_help.c:4618 sql_help.c:4624 sql_help.c:4875 sql_help.c:4881 -#: sql_help.c:5121 sql_help.c:5127 +#: sql_help.c:4639 sql_help.c:4645 sql_help.c:4897 sql_help.c:4903 +#: sql_help.c:5142 sql_help.c:5148 msgid "join_type" msgstr "тип_соединения" -#: sql_help.c:4621 sql_help.c:4878 sql_help.c:5124 +#: sql_help.c:4642 sql_help.c:4900 sql_help.c:5145 msgid "join_column" msgstr "столбец_соединения" -#: sql_help.c:4622 sql_help.c:4879 sql_help.c:5125 +#: sql_help.c:4643 sql_help.c:4901 sql_help.c:5146 msgid "join_using_alias" msgstr "псевдоним_использования_соединения" -#: sql_help.c:4628 sql_help.c:4885 sql_help.c:5131 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and grouping_element can be one of:" msgstr "где допустимый элемент_группирования:" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 msgid "and with_query is:" msgstr "и запрос_WITH:" -#: sql_help.c:4640 sql_help.c:4897 sql_help.c:5143 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "values" msgstr "значения" -#: sql_help.c:4641 sql_help.c:4898 sql_help.c:5144 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "insert" msgstr "insert" -#: sql_help.c:4642 sql_help.c:4899 sql_help.c:5145 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "update" msgstr "update" -#: sql_help.c:4643 sql_help.c:4900 sql_help.c:5146 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "delete" msgstr "delete" -#: sql_help.c:4645 sql_help.c:4902 sql_help.c:5148 +#: sql_help.c:4665 sql_help.c:4923 sql_help.c:5168 +msgid "merge" +msgstr "merge" + +#: sql_help.c:4667 sql_help.c:4925 sql_help.c:5170 msgid "search_seq_col_name" msgstr "имя_столбца_послед_поиска" -#: sql_help.c:4647 sql_help.c:4904 sql_help.c:5150 +#: sql_help.c:4669 sql_help.c:4927 sql_help.c:5172 msgid "cycle_mark_col_name" msgstr "имя_столбца_пометки_цикла" -#: sql_help.c:4648 sql_help.c:4905 sql_help.c:5151 +#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 msgid "cycle_mark_value" msgstr "значение_пометки_цикла" -#: sql_help.c:4649 sql_help.c:4906 sql_help.c:5152 +#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 msgid "cycle_mark_default" msgstr "пометка_цикла_по_умолчанию" -#: sql_help.c:4650 sql_help.c:4907 sql_help.c:5153 +#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 msgid "cycle_path_col_name" msgstr "имя_столбца_пути_цикла" -#: sql_help.c:4677 +#: sql_help.c:4699 msgid "new_table" msgstr "новая_таблица" -#: sql_help.c:4748 +#: sql_help.c:4770 msgid "snapshot_id" msgstr "код_снимка" -#: sql_help.c:5016 +#: sql_help.c:5037 msgid "sort_expression" msgstr "выражение_сортировки" -#: sql_help.c:5160 sql_help.c:6144 +#: sql_help.c:5182 sql_help.c:6166 msgid "abort the current transaction" msgstr "прервать текущую транзакцию" -#: sql_help.c:5166 +#: sql_help.c:5188 msgid "change the definition of an aggregate function" msgstr "изменить определение агрегатной функции" -#: sql_help.c:5172 +#: sql_help.c:5194 msgid "change the definition of a collation" msgstr "изменить определение правила сортировки" -#: sql_help.c:5178 +#: sql_help.c:5200 msgid "change the definition of a conversion" msgstr "изменить определение преобразования" -#: sql_help.c:5184 +#: sql_help.c:5206 msgid "change a database" msgstr "изменить атрибуты базы данных" -#: sql_help.c:5190 +#: sql_help.c:5212 msgid "define default access privileges" msgstr "определить права доступа по умолчанию" -#: sql_help.c:5196 +#: sql_help.c:5218 msgid "change the definition of a domain" msgstr "изменить определение домена" -#: sql_help.c:5202 +#: sql_help.c:5224 msgid "change the definition of an event trigger" msgstr "изменить определение событийного триггера" -#: sql_help.c:5208 +#: sql_help.c:5230 msgid "change the definition of an extension" msgstr "изменить определение расширения" -#: sql_help.c:5214 +#: sql_help.c:5236 msgid "change the definition of a foreign-data wrapper" msgstr "изменить определение обёртки сторонних данных" -#: sql_help.c:5220 +#: sql_help.c:5242 msgid "change the definition of a foreign table" msgstr "изменить определение сторонней таблицы" -#: sql_help.c:5226 +#: sql_help.c:5248 msgid "change the definition of a function" msgstr "изменить определение функции" -#: sql_help.c:5232 +#: sql_help.c:5254 msgid "change role name or membership" msgstr "изменить имя роли или членство" -#: sql_help.c:5238 +#: sql_help.c:5260 msgid "change the definition of an index" msgstr "изменить определение индекса" -#: sql_help.c:5244 +#: sql_help.c:5266 msgid "change the definition of a procedural language" msgstr "изменить определение процедурного языка" -#: sql_help.c:5250 +#: sql_help.c:5272 msgid "change the definition of a large object" msgstr "изменить определение большого объекта" -#: sql_help.c:5256 +#: sql_help.c:5278 msgid "change the definition of a materialized view" msgstr "изменить определение материализованного представления" -#: sql_help.c:5262 +#: sql_help.c:5284 msgid "change the definition of an operator" msgstr "изменить определение оператора" -#: sql_help.c:5268 +#: sql_help.c:5290 msgid "change the definition of an operator class" msgstr "изменить определение класса операторов" -#: sql_help.c:5274 +#: sql_help.c:5296 msgid "change the definition of an operator family" msgstr "изменить определение семейства операторов" -#: sql_help.c:5280 +#: sql_help.c:5302 msgid "change the definition of a row-level security policy" msgstr "изменить определение политики защиты на уровне строк" -#: sql_help.c:5286 +#: sql_help.c:5308 msgid "change the definition of a procedure" msgstr "изменить определение процедуры" -#: sql_help.c:5292 +#: sql_help.c:5314 msgid "change the definition of a publication" msgstr "изменить определение публикации" -#: sql_help.c:5298 sql_help.c:5400 +#: sql_help.c:5320 sql_help.c:5422 msgid "change a database role" msgstr "изменить роль пользователя БД" -#: sql_help.c:5304 +#: sql_help.c:5326 msgid "change the definition of a routine" msgstr "изменить определение подпрограммы" -#: sql_help.c:5310 +#: sql_help.c:5332 msgid "change the definition of a rule" msgstr "изменить определение правила" -#: sql_help.c:5316 +#: sql_help.c:5338 msgid "change the definition of a schema" msgstr "изменить определение схемы" -#: sql_help.c:5322 +#: sql_help.c:5344 msgid "change the definition of a sequence generator" msgstr "изменить определение генератора последовательности" -#: sql_help.c:5328 +#: sql_help.c:5350 msgid "change the definition of a foreign server" msgstr "изменить определение стороннего сервера" -#: sql_help.c:5334 +#: sql_help.c:5356 msgid "change the definition of an extended statistics object" msgstr "изменить определение объекта расширенной статистики" -#: sql_help.c:5340 +#: sql_help.c:5362 msgid "change the definition of a subscription" msgstr "изменить определение подписки" -#: sql_help.c:5346 +#: sql_help.c:5368 msgid "change a server configuration parameter" msgstr "изменить параметр конфигурации сервера" -#: sql_help.c:5352 +#: sql_help.c:5374 msgid "change the definition of a table" msgstr "изменить определение таблицы" -#: sql_help.c:5358 +#: sql_help.c:5380 msgid "change the definition of a tablespace" msgstr "изменить определение табличного пространства" -#: sql_help.c:5364 +#: sql_help.c:5386 msgid "change the definition of a text search configuration" msgstr "изменить определение конфигурации текстового поиска" -#: sql_help.c:5370 +#: sql_help.c:5392 msgid "change the definition of a text search dictionary" msgstr "изменить определение словаря текстового поиска" -#: sql_help.c:5376 +#: sql_help.c:5398 msgid "change the definition of a text search parser" msgstr "изменить определение анализатора текстового поиска" -#: sql_help.c:5382 +#: sql_help.c:5404 msgid "change the definition of a text search template" msgstr "изменить определение шаблона текстового поиска" -#: sql_help.c:5388 +#: sql_help.c:5410 msgid "change the definition of a trigger" msgstr "изменить определение триггера" -#: sql_help.c:5394 +#: sql_help.c:5416 msgid "change the definition of a type" msgstr "изменить определение типа" -#: sql_help.c:5406 +#: sql_help.c:5428 msgid "change the definition of a user mapping" msgstr "изменить сопоставление пользователей" -#: sql_help.c:5412 +#: sql_help.c:5434 msgid "change the definition of a view" msgstr "изменить определение представления" -#: sql_help.c:5418 +#: sql_help.c:5440 msgid "collect statistics about a database" msgstr "собрать статистику о базе данных" -#: sql_help.c:5424 sql_help.c:6222 +#: sql_help.c:5446 sql_help.c:6244 msgid "start a transaction block" msgstr "начать транзакцию" -#: sql_help.c:5430 +#: sql_help.c:5452 msgid "invoke a procedure" msgstr "вызвать процедуру" -#: sql_help.c:5436 +#: sql_help.c:5458 msgid "force a write-ahead log checkpoint" msgstr "произвести контрольную точку в журнале предзаписи" -#: sql_help.c:5442 +#: sql_help.c:5464 msgid "close a cursor" msgstr "закрыть курсор" -#: sql_help.c:5448 +#: sql_help.c:5470 msgid "cluster a table according to an index" msgstr "перегруппировать таблицу по индексу" -#: sql_help.c:5454 +#: sql_help.c:5476 msgid "define or change the comment of an object" msgstr "задать или изменить комментарий объекта" -#: sql_help.c:5460 sql_help.c:6018 +#: sql_help.c:5482 sql_help.c:6040 msgid "commit the current transaction" msgstr "зафиксировать текущую транзакцию" -#: sql_help.c:5466 +#: sql_help.c:5488 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "зафиксировать транзакцию, ранее подготовленную для двухфазной фиксации" -#: sql_help.c:5472 +#: sql_help.c:5494 msgid "copy data between a file and a table" msgstr "импорт/экспорт данных в файл" -#: sql_help.c:5478 +#: sql_help.c:5500 msgid "define a new access method" msgstr "создать новый метод доступа" -#: sql_help.c:5484 +#: sql_help.c:5506 msgid "define a new aggregate function" msgstr "создать агрегатную функцию" -#: sql_help.c:5490 +#: sql_help.c:5512 msgid "define a new cast" msgstr "создать приведение типов" -#: sql_help.c:5496 +#: sql_help.c:5518 msgid "define a new collation" msgstr "создать правило сортировки" -#: sql_help.c:5502 +#: sql_help.c:5524 msgid "define a new encoding conversion" msgstr "создать преобразование кодировки" -#: sql_help.c:5508 +#: sql_help.c:5530 msgid "create a new database" msgstr "создать базу данных" -#: sql_help.c:5514 +#: sql_help.c:5536 msgid "define a new domain" msgstr "создать домен" -#: sql_help.c:5520 +#: sql_help.c:5542 msgid "define a new event trigger" msgstr "создать событийный триггер" -#: sql_help.c:5526 +#: sql_help.c:5548 msgid "install an extension" msgstr "установить расширение" -#: sql_help.c:5532 +#: sql_help.c:5554 msgid "define a new foreign-data wrapper" msgstr "создать обёртку сторонних данных" -#: sql_help.c:5538 +#: sql_help.c:5560 msgid "define a new foreign table" msgstr "создать стороннюю таблицу" -#: sql_help.c:5544 +#: sql_help.c:5566 msgid "define a new function" msgstr "создать функцию" -#: sql_help.c:5550 sql_help.c:5610 sql_help.c:5712 +#: sql_help.c:5572 sql_help.c:5632 sql_help.c:5734 msgid "define a new database role" msgstr "создать роль пользователя БД" -#: sql_help.c:5556 +#: sql_help.c:5578 msgid "define a new index" msgstr "создать индекс" -#: sql_help.c:5562 +#: sql_help.c:5584 msgid "define a new procedural language" msgstr "создать процедурный язык" -#: sql_help.c:5568 +#: sql_help.c:5590 msgid "define a new materialized view" msgstr "создать материализованное представление" -#: sql_help.c:5574 +#: sql_help.c:5596 msgid "define a new operator" msgstr "создать оператор" -#: sql_help.c:5580 +#: sql_help.c:5602 msgid "define a new operator class" msgstr "создать класс операторов" -#: sql_help.c:5586 +#: sql_help.c:5608 msgid "define a new operator family" msgstr "создать семейство операторов" -#: sql_help.c:5592 +#: sql_help.c:5614 msgid "define a new row-level security policy for a table" msgstr "создать новую политику защиты на уровне строк для таблицы" -#: sql_help.c:5598 +#: sql_help.c:5620 msgid "define a new procedure" msgstr "создать процедуру" -#: sql_help.c:5604 +#: sql_help.c:5626 msgid "define a new publication" msgstr "создать публикацию" -#: sql_help.c:5616 +#: sql_help.c:5638 msgid "define a new rewrite rule" msgstr "создать правило перезаписи" -#: sql_help.c:5622 +#: sql_help.c:5644 msgid "define a new schema" msgstr "создать схему" -#: sql_help.c:5628 +#: sql_help.c:5650 msgid "define a new sequence generator" msgstr "создать генератор последовательностей" -#: sql_help.c:5634 +#: sql_help.c:5656 msgid "define a new foreign server" msgstr "создать сторонний сервер" -#: sql_help.c:5640 +#: sql_help.c:5662 msgid "define extended statistics" msgstr "создать расширенную статистику" -#: sql_help.c:5646 +#: sql_help.c:5668 msgid "define a new subscription" msgstr "создать подписку" -#: sql_help.c:5652 +#: sql_help.c:5674 msgid "define a new table" msgstr "создать таблицу" -#: sql_help.c:5658 sql_help.c:6180 +#: sql_help.c:5680 sql_help.c:6202 msgid "define a new table from the results of a query" msgstr "создать таблицу из результатов запроса" -#: sql_help.c:5664 +#: sql_help.c:5686 msgid "define a new tablespace" msgstr "создать табличное пространство" -#: sql_help.c:5670 +#: sql_help.c:5692 msgid "define a new text search configuration" msgstr "создать конфигурацию текстового поиска" -#: sql_help.c:5676 +#: sql_help.c:5698 msgid "define a new text search dictionary" msgstr "создать словарь текстового поиска" -#: sql_help.c:5682 +#: sql_help.c:5704 msgid "define a new text search parser" msgstr "создать анализатор текстового поиска" -#: sql_help.c:5688 +#: sql_help.c:5710 msgid "define a new text search template" msgstr "создать шаблон текстового поиска" -#: sql_help.c:5694 +#: sql_help.c:5716 msgid "define a new transform" msgstr "создать преобразование" -#: sql_help.c:5700 +#: sql_help.c:5722 msgid "define a new trigger" msgstr "создать триггер" -#: sql_help.c:5706 +#: sql_help.c:5728 msgid "define a new data type" msgstr "создать тип данных" -#: sql_help.c:5718 +#: sql_help.c:5740 msgid "define a new mapping of a user to a foreign server" msgstr "создать сопоставление пользователя для стороннего сервера" -#: sql_help.c:5724 +#: sql_help.c:5746 msgid "define a new view" msgstr "создать представление" -#: sql_help.c:5730 +#: sql_help.c:5752 msgid "deallocate a prepared statement" msgstr "освободить подготовленный оператор" -#: sql_help.c:5736 +#: sql_help.c:5758 msgid "define a cursor" msgstr "создать курсор" -#: sql_help.c:5742 +#: sql_help.c:5764 msgid "delete rows of a table" msgstr "удалить записи таблицы" -#: sql_help.c:5748 +#: sql_help.c:5770 msgid "discard session state" msgstr "очистить состояние сеанса" -#: sql_help.c:5754 +#: sql_help.c:5776 msgid "execute an anonymous code block" msgstr "выполнить анонимный блок кода" -#: sql_help.c:5760 +#: sql_help.c:5782 msgid "remove an access method" msgstr "удалить метод доступа" -#: sql_help.c:5766 +#: sql_help.c:5788 msgid "remove an aggregate function" msgstr "удалить агрегатную функцию" -#: sql_help.c:5772 +#: sql_help.c:5794 msgid "remove a cast" msgstr "удалить приведение типа" -#: sql_help.c:5778 +#: sql_help.c:5800 msgid "remove a collation" msgstr "удалить правило сортировки" -#: sql_help.c:5784 +#: sql_help.c:5806 msgid "remove a conversion" msgstr "удалить преобразование" -#: sql_help.c:5790 +#: sql_help.c:5812 msgid "remove a database" msgstr "удалить базу данных" -#: sql_help.c:5796 +#: sql_help.c:5818 msgid "remove a domain" msgstr "удалить домен" -#: sql_help.c:5802 +#: sql_help.c:5824 msgid "remove an event trigger" msgstr "удалить событийный триггер" -#: sql_help.c:5808 +#: sql_help.c:5830 msgid "remove an extension" msgstr "удалить расширение" -#: sql_help.c:5814 +#: sql_help.c:5836 msgid "remove a foreign-data wrapper" msgstr "удалить обёртку сторонних данных" -#: sql_help.c:5820 +#: sql_help.c:5842 msgid "remove a foreign table" msgstr "удалить стороннюю таблицу" -#: sql_help.c:5826 +#: sql_help.c:5848 msgid "remove a function" msgstr "удалить функцию" -#: sql_help.c:5832 sql_help.c:5898 sql_help.c:6000 +#: sql_help.c:5854 sql_help.c:5920 sql_help.c:6022 msgid "remove a database role" msgstr "удалить роль пользователя БД" -#: sql_help.c:5838 +#: sql_help.c:5860 msgid "remove an index" msgstr "удалить индекс" -#: sql_help.c:5844 +#: sql_help.c:5866 msgid "remove a procedural language" msgstr "удалить процедурный язык" -#: sql_help.c:5850 +#: sql_help.c:5872 msgid "remove a materialized view" msgstr "удалить материализованное представление" -#: sql_help.c:5856 +#: sql_help.c:5878 msgid "remove an operator" msgstr "удалить оператор" -#: sql_help.c:5862 +#: sql_help.c:5884 msgid "remove an operator class" msgstr "удалить класс операторов" -#: sql_help.c:5868 +#: sql_help.c:5890 msgid "remove an operator family" msgstr "удалить семейство операторов" -#: sql_help.c:5874 +#: sql_help.c:5896 msgid "remove database objects owned by a database role" msgstr "удалить объекты базы данных, принадлежащие роли" -#: sql_help.c:5880 +#: sql_help.c:5902 msgid "remove a row-level security policy from a table" msgstr "удалить из таблицы политику защиты на уровне строк" -#: sql_help.c:5886 +#: sql_help.c:5908 msgid "remove a procedure" msgstr "удалить процедуру" -#: sql_help.c:5892 +#: sql_help.c:5914 msgid "remove a publication" msgstr "удалить публикацию" -#: sql_help.c:5904 +#: sql_help.c:5926 msgid "remove a routine" msgstr "удалить подпрограмму" -#: sql_help.c:5910 +#: sql_help.c:5932 msgid "remove a rewrite rule" msgstr "удалить правило перезаписи" -#: sql_help.c:5916 +#: sql_help.c:5938 msgid "remove a schema" msgstr "удалить схему" -#: sql_help.c:5922 +#: sql_help.c:5944 msgid "remove a sequence" msgstr "удалить последовательность" -#: sql_help.c:5928 +#: sql_help.c:5950 msgid "remove a foreign server descriptor" msgstr "удалить описание стороннего сервера" -#: sql_help.c:5934 +#: sql_help.c:5956 msgid "remove extended statistics" msgstr "удалить расширенную статистику" -#: sql_help.c:5940 +#: sql_help.c:5962 msgid "remove a subscription" msgstr "удалить подписку" -#: sql_help.c:5946 +#: sql_help.c:5968 msgid "remove a table" msgstr "удалить таблицу" -#: sql_help.c:5952 +#: sql_help.c:5974 msgid "remove a tablespace" msgstr "удалить табличное пространство" -#: sql_help.c:5958 +#: sql_help.c:5980 msgid "remove a text search configuration" msgstr "удалить конфигурацию текстового поиска" -#: sql_help.c:5964 +#: sql_help.c:5986 msgid "remove a text search dictionary" msgstr "удалить словарь текстового поиска" -#: sql_help.c:5970 +#: sql_help.c:5992 msgid "remove a text search parser" msgstr "удалить анализатор текстового поиска" -#: sql_help.c:5976 +#: sql_help.c:5998 msgid "remove a text search template" msgstr "удалить шаблон текстового поиска" -#: sql_help.c:5982 +#: sql_help.c:6004 msgid "remove a transform" msgstr "удалить преобразование" -#: sql_help.c:5988 +#: sql_help.c:6010 msgid "remove a trigger" msgstr "удалить триггер" -#: sql_help.c:5994 +#: sql_help.c:6016 msgid "remove a data type" msgstr "удалить тип данных" -#: sql_help.c:6006 +#: sql_help.c:6028 msgid "remove a user mapping for a foreign server" msgstr "удалить сопоставление пользователя для стороннего сервера" -#: sql_help.c:6012 +#: sql_help.c:6034 msgid "remove a view" msgstr "удалить представление" -#: sql_help.c:6024 +#: sql_help.c:6046 msgid "execute a prepared statement" msgstr "выполнить подготовленный оператор" -#: sql_help.c:6030 +#: sql_help.c:6052 msgid "show the execution plan of a statement" msgstr "показать план выполнения оператора" -#: sql_help.c:6036 +#: sql_help.c:6058 msgid "retrieve rows from a query using a cursor" msgstr "получить результат запроса через курсор" -#: sql_help.c:6042 +#: sql_help.c:6064 msgid "define access privileges" msgstr "определить права доступа" -#: sql_help.c:6048 +#: sql_help.c:6070 msgid "import table definitions from a foreign server" msgstr "импортировать определения таблиц со стороннего сервера" -#: sql_help.c:6054 +#: sql_help.c:6076 msgid "create new rows in a table" msgstr "добавить строки в таблицу" -#: sql_help.c:6060 +#: sql_help.c:6082 msgid "listen for a notification" msgstr "ожидать уведомления" -#: sql_help.c:6066 +#: sql_help.c:6088 msgid "load a shared library file" msgstr "загрузить файл разделяемой библиотеки" -#: sql_help.c:6072 +#: sql_help.c:6094 msgid "lock a table" msgstr "заблокировать таблицу" -#: sql_help.c:6078 +#: sql_help.c:6100 msgid "conditionally insert, update, or delete rows of a table" msgstr "добавление, изменение или удаление строк таблицы по условию" -#: sql_help.c:6084 +#: sql_help.c:6106 msgid "position a cursor" msgstr "установить курсор" -#: sql_help.c:6090 +#: sql_help.c:6112 msgid "generate a notification" msgstr "сгенерировать уведомление" -#: sql_help.c:6096 +#: sql_help.c:6118 msgid "prepare a statement for execution" msgstr "подготовить оператор для выполнения" -#: sql_help.c:6102 +#: sql_help.c:6124 msgid "prepare the current transaction for two-phase commit" msgstr "подготовить текущую транзакцию для двухфазной фиксации" -#: sql_help.c:6108 +#: sql_help.c:6130 msgid "change the ownership of database objects owned by a database role" msgstr "изменить владельца объектов БД, принадлежащих заданной роли" -#: sql_help.c:6114 +#: sql_help.c:6136 msgid "replace the contents of a materialized view" msgstr "заменить содержимое материализованного представления" -#: sql_help.c:6120 +#: sql_help.c:6142 msgid "rebuild indexes" msgstr "перестроить индексы" -#: sql_help.c:6126 +#: sql_help.c:6148 msgid "release a previously defined savepoint" msgstr "освободить ранее определённую точку сохранения" -#: sql_help.c:6132 +#: sql_help.c:6154 msgid "restore the value of a run-time parameter to the default value" msgstr "восстановить исходное значение параметра выполнения" -#: sql_help.c:6138 +#: sql_help.c:6160 msgid "remove access privileges" msgstr "удалить права доступа" -#: sql_help.c:6150 +#: sql_help.c:6172 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "отменить транзакцию, подготовленную ранее для двухфазной фиксации" -#: sql_help.c:6156 +#: sql_help.c:6178 msgid "roll back to a savepoint" msgstr "откатиться к точке сохранения" -#: sql_help.c:6162 +#: sql_help.c:6184 msgid "define a new savepoint within the current transaction" msgstr "определить новую точку сохранения в текущей транзакции" -#: sql_help.c:6168 +#: sql_help.c:6190 msgid "define or change a security label applied to an object" msgstr "задать или изменить метку безопасности, применённую к объекту" -#: sql_help.c:6174 sql_help.c:6228 sql_help.c:6264 +#: sql_help.c:6196 sql_help.c:6250 sql_help.c:6286 msgid "retrieve rows from a table or view" msgstr "выбрать строки из таблицы или представления" -#: sql_help.c:6186 +#: sql_help.c:6208 msgid "change a run-time parameter" msgstr "изменить параметр выполнения" -#: sql_help.c:6192 +#: sql_help.c:6214 msgid "set constraint check timing for the current transaction" msgstr "установить время проверки ограничений для текущей транзакции" -#: sql_help.c:6198 +#: sql_help.c:6220 msgid "set the current user identifier of the current session" msgstr "задать идентификатор текущего пользователя в текущем сеансе" -#: sql_help.c:6204 +#: sql_help.c:6226 msgid "" "set the session user identifier and the current user identifier of the " "current session" @@ -6743,31 +6822,31 @@ msgstr "" "задать идентификатор пользователя сеанса и идентификатор текущего " "пользователя в текущем сеансе" -#: sql_help.c:6210 +#: sql_help.c:6232 msgid "set the characteristics of the current transaction" msgstr "задать свойства текущей транзакции" -#: sql_help.c:6216 +#: sql_help.c:6238 msgid "show the value of a run-time parameter" msgstr "показать значение параметра выполнения" -#: sql_help.c:6234 +#: sql_help.c:6256 msgid "empty a table or set of tables" msgstr "опустошить таблицу или набор таблиц" -#: sql_help.c:6240 +#: sql_help.c:6262 msgid "stop listening for a notification" msgstr "прекратить ожидание уведомлений" -#: sql_help.c:6246 +#: sql_help.c:6268 msgid "update rows of a table" msgstr "изменить строки таблицы" -#: sql_help.c:6252 +#: sql_help.c:6274 msgid "garbage-collect and optionally analyze a database" msgstr "произвести сборку мусора и проанализировать базу данных" -#: sql_help.c:6258 +#: sql_help.c:6280 msgid "compute a set of rows" msgstr "получить набор строк" @@ -6810,7 +6889,7 @@ msgstr "лишний аргумент \"%s\" проигнорирован" msgid "could not find own program executable" msgstr "не удалось найти свой исполняемый файл" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6846,6 +6925,25 @@ msgstr "" "нераспознанное значение \"%s\" для \"%s\"\n" "Допустимые значения: %s." +#~ msgid "ICU Locale" +#~ msgstr "локаль ICU" + +#~ msgid "local socket" +#~ msgstr "локальный сокет" + +#~ msgid "" +#~ " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" +#~ msgstr "" +#~ " \\watch [[i=]СЕК] [c=N] повторять запрос через заданное число секунд, " +#~ "не\n" +#~ " более N раз\n" + +#~ msgid "constraint" +#~ msgstr "ограничение" + +#~ msgid "where constraint is:" +#~ msgstr "где ограничение:" + #, c-format #~ msgid "could not identify current directory: %m" #~ msgstr "не удалось определить текущий каталог: %m" diff --git a/src/bin/psql/po/sv.po b/src/bin/psql/po/sv.po index 2293529e4fe75..38ef29bff556a 100644 --- a/src/bin/psql/po/sv.po +++ b/src/bin/psql/po/sv.po @@ -1,15 +1,15 @@ # Swedish message translation file for psql # Peter Eisentraut , 2001, 2009, 2010. -# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2002, 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025. # # Use these quotes: "%s" # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-02 08:16+0000\n" -"PO-Revision-Date: 2023-08-02 12:20+0200\n" +"POT-Creation-Date: 2025-02-12 13:48+0000\n" +"PO-Revision-Date: 2025-02-12 20:57+0100\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -38,33 +38,48 @@ msgstr "detalj: " msgid "hint: " msgstr "tips: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "ogiltig binär \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "kunde inte läsa binär \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "kunde inte hitta en \"%s\" att köra" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "kunde inte konvertera sökvägen \"%s\" till en absolut sökväg: %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "kunde inte köra kommandot \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "kunde inte läsa från kommando \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "ingen data returnerades från kommandot \"%s\"" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() misslyckades: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1373 command.c:3459 command.c:3508 command.c:3633 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -86,7 +101,7 @@ msgstr "kan inte duplicera null-pekare (internt fel)\n" msgid "could not look up effective user ID %ld: %s" msgstr "kunde inte slå upp effektivt användar-id %ld: %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "användaren finns inte" @@ -125,11 +140,11 @@ msgstr "barnprocess terminerades av signal %d: %s" msgid "child process exited with unrecognized status %d" msgstr "barnprocess avslutade med okänd statuskod %d" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Förfrågan om avbrytning skickad\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Kunde inte skicka förfrågan om avbrytning: " @@ -145,312 +160,337 @@ msgstr[1] "(%lu rader)" msgid "Interrupted\n" msgstr "Avbruten\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Kan inte skriva ut tabellinnehåll: antal celler %lld är lika med eller fler än maximala %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "Kan inte lägga till rubrik till tabellinnehåll: antal kolumner (%d) överskridet.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "Kan inte lägga till cell till tabellinnehåll: totala cellantalet (%d) överskridet.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "Kan inte lägga till cell till tabellinnehåll: totala cellantalet %lld är överskridet.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "ogiltigt utdataformat (internt fel): %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "hoppar över rekursiv expandering av variabeln \"%s\"" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:608 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:781 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "kunde inte slå upp lokalt användar-id %d: %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "lokal användare med ID %d existerar inte" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "ogiltigt kommando \\%s" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "Försök med \\? för hjälp." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: extra argument \"%s\" ignorerat" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "kommandot \\%s ignorerat; använd \\endif eller Ctrl-C för att avsluta nuvarande \\if-block" -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "kunde inte hämta hemkatalog för användar-ID %ld: %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: kunde inte byta katalog till \"%s\": %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "Du är för närvarande inte uppkopplad mot en databas.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Du är uppkopplad upp mot databas \"%s\" som användare \"%s\" på adress \"%s\" på port \"%s\".\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Du är uppkopplad mot databas \"%s\" som användare \"%s\" via uttag i \"%s\" på port \"%s\".\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Du är uppkopplad upp mot databas \"%s\" som användare \"%s\" på värd \"%s\" (adress \"%s\") på port \"%s\".\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Du är uppkopplad upp mot databas \"%s\" som användare \"%s\" på värd \"%s\" på port \"%s\".\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2676 #, c-format msgid "no query buffer" msgstr "ingen frågebuffert" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5779 #, c-format msgid "invalid line number: %s" msgstr "ogiltigt radnummer: %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "Inga ändringar" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: ogiltigt kodningsnamn eller konverteringsprocedur hittades inte" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:720 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1369 command.c:2158 command.c:3455 command.c:3653 command.c:5885 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1376 msgid "There is no previous error." msgstr "Det finns inget tidigare fel." -#: command.c:1470 +#: command.c:1489 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: saknar höger parentes" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1573 command.c:1692 command.c:1996 command.c:2010 command.c:2029 +#: command.c:2197 command.c:2438 command.c:2643 command.c:2683 #, c-format msgid "\\%s: missing required argument" msgstr "\\%s: obligatoriskt argument saknas" -#: command.c:1815 +#: command.c:1823 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: kan inte komma efter \\else" -#: command.c:1820 +#: command.c:1828 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: ingen matchande \\if" -#: command.c:1884 +#: command.c:1892 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: kan inte komma efter \\else" -#: command.c:1889 +#: command.c:1897 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: ingen matchande \\if" -#: command.c:1929 +#: command.c:1937 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: ingen matchande \\if" -#: command.c:2085 +#: command.c:2093 msgid "Query buffer is empty." msgstr "Frågebufferten är tom." -#: command.c:2128 +#: command.c:2136 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Mata in nytt lösenord för användare \"%s\": " -#: command.c:2132 +#: command.c:2140 msgid "Enter it again: " msgstr "Mata in det igen: " -#: command.c:2141 +#: command.c:2149 #, c-format msgid "Passwords didn't match." msgstr "Lösenorden stämde inte överens." -#: command.c:2238 +#: command.c:2232 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: kunde inte läsa värde på varibeln" -#: command.c:2340 +#: command.c:2334 msgid "Query buffer reset (cleared)." msgstr "Frågebufferten har blivit borttagen." -#: command.c:2362 +#: command.c:2356 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "Skrev historiken till fil \"%s\".\n" -#: command.c:2449 +#: command.c:2443 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: omgivningsvariabelnamn får ej innehålla \"=\"" -#: command.c:2497 +#: command.c:2491 #, c-format msgid "function name is required" msgstr "funktionsnamn krävs" -#: command.c:2499 +#: command.c:2493 #, c-format msgid "view name is required" msgstr "vynamn krävs" -#: command.c:2621 +#: command.c:2615 msgid "Timing is on." msgstr "Tidtagning är på." -#: command.c:2623 +#: command.c:2617 msgid "Timing is off." msgstr "Tidtagning är av." -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2703 command.c:2741 command.c:4166 command.c:4169 command.c:4172 +#: command.c:4178 command.c:4180 command.c:4206 command.c:4216 command.c:4228 +#: command.c:4242 command.c:4269 command.c:4327 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2736 copy.c:388 +#: command.c:2730 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2806 command.c:2852 +#: command.c:2802 command.c:2868 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: värde på intervall angivet mer än en gång" -#: command.c:2816 command.c:2862 +#: command.c:2812 command.c:2878 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: inkorrekt intervallvärde \"%s\"" -#: command.c:2826 +#: command.c:2822 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: iterationsantal angivet mer än en gång" -#: command.c:2836 +#: command.c:2832 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: inkorrekt iterationsantal \"%s\"" -#: command.c:2843 +#: command.c:2842 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: minsta radantal angivet mer än en gång" + +#: command.c:2852 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch: inkorrekt minsta radantal \"%s\"" + +#: command.c:2859 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: okänd parameter \"%s\"" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3256 startup.c:243 startup.c:293 msgid "Password: " msgstr "Lösenord: " -#: command.c:3241 startup.c:290 +#: command.c:3261 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "Lösenord för användare %s: " -#: command.c:3297 +#: command.c:3317 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "Ange inte användare, värd eller port separat tillsammans med en anslutningssträng" -#: command.c:3332 +#: command.c:3352 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "Det finns ingen anslutning att återanvända parametrar från" -#: command.c:3638 +#: command.c:3659 #, c-format msgid "Previous connection kept" msgstr "Föregående anslutning bevarad" -#: command.c:3644 +#: command.c:3665 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3700 +#: command.c:3721 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Du är nu uppkopplad mot databasen \"%s\" som användare \"%s\" på adress \"%s\" på port \"%s\".\n" -#: command.c:3703 +#: command.c:3724 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Du är nu uppkopplad mot databasen \"%s\" som användare \"%s\" via uttag i \"%s\" på port \"%s\".\n" -#: command.c:3709 +#: command.c:3730 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Du är nu uppkopplad mot databasen \"%s\" som användare \"%s\" på värd \"%s\" (adress \"%s\") på port \"%s\".\n" -#: command.c:3712 +#: command.c:3733 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Du är nu uppkopplad mot databasen \"%s\" som användare \"%s\" på värd \"%s\" på port \"%s\".\n" -#: command.c:3717 +#: command.c:3738 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Du är nu uppkopplad mot databasen \"%s\" som användare \"%s\".\n" -#: command.c:3757 +#: command.c:3844 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, server %s)\n" -#: command.c:3770 +#: command.c:3857 #, c-format msgid "" "WARNING: %s major version %s, server major version %s.\n" @@ -459,29 +499,33 @@ msgstr "" "VARNING: %s huvudversion %s, server huvudversion %s.\n" " En del psql-finesser kommer kanske inte fungera.\n" -#: command.c:3807 +#: command.c:3896 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "SSL-anslutning (protokoll: %s, krypto: %s, komprimering: %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "SSL-anslutning (protokoll: %s, krypto: %s, komprimering: %s, ALPN: %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3897 command.c:3898 msgid "unknown" msgstr "okänd" -#: command.c:3810 help.c:42 +#: command.c:3899 help.c:42 msgid "off" msgstr "av" -#: command.c:3810 help.c:42 +#: command.c:3899 help.c:42 msgid "on" msgstr "på" -#: command.c:3824 +#: command.c:3900 +msgid "none" +msgstr "ingen" + +#: command.c:3914 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "GSSAPI-krypterad anslutning\n" -#: command.c:3844 +#: command.c:3934 #, c-format msgid "" "WARNING: Console code page (%u) differs from Windows code page (%u)\n" @@ -492,433 +536,438 @@ msgstr "" " 8-bitars tecken kommer troligen inte fungera korrekt. Se psql:s\n" " referensmanual i sektionen \"Notes for Windows users\" för mer detaljer.\n" -#: command.c:3949 +#: command.c:4041 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "omgivningsvariabeln PSQL_EDITOR_LINENUMBER_ARG måste ange ett radnummer" -#: command.c:3979 +#: command.c:4071 #, c-format msgid "could not start editor \"%s\"" msgstr "kunde inte starta editorn \"%s\"" -#: command.c:3981 +#: command.c:4073 #, c-format msgid "could not start /bin/sh" msgstr "kunde inte starta /bin/sh" -#: command.c:4031 +#: command.c:4123 #, c-format msgid "could not locate temporary directory: %s" msgstr "kunde inte hitta temp-katalog: %s" -#: command.c:4058 +#: command.c:4150 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "kunde inte öppna temporär fil \"%s\": %m" -#: command.c:4394 +#: command.c:4486 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: tvetydig förkortning \"%s\" matchar både \"%s\" och \"%s\"" -#: command.c:4414 +#: command.c:4506 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset: tillåtna format är aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4525 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: tillåtna linjestilar är ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4540 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: tillåtna Unicode-ramstilar är single, double" -#: command.c:4463 +#: command.c:4555 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: tillåtna Unicode-kolumnlinjestilar ärsingle, double" -#: command.c:4478 +#: command.c:4570 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: tillåtna Unicode-rubriklinjestilar är single, double" -#: command.c:4530 +#: command.c:4622 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: tillåtna värden på xheader_width är \"%s\" (standard), \"%s\", \"%s\" eller ett tal som anger exakt vidd" -#: command.c:4547 +#: command.c:4639 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep måste vara ett ensamt en-byte-tecken" -#: command.c:4552 +#: command.c:4644 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldset kan inte vara dubbelcitat, nyrad eller vagnretur" -#: command.c:4690 command.c:4891 +#: command.c:4782 command.c:4983 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: okänd parameter: %s" -#: command.c:4710 +#: command.c:4802 #, c-format msgid "Border style is %d.\n" msgstr "Ramstil är %d.\n" -#: command.c:4716 +#: command.c:4808 #, c-format msgid "Target width is unset.\n" msgstr "Målvidd är inte satt.\n" -#: command.c:4718 +#: command.c:4810 #, c-format msgid "Target width is %d.\n" msgstr "Målvidd är %d.\n" -#: command.c:4725 +#: command.c:4817 #, c-format msgid "Expanded display is on.\n" msgstr "Utökad visning är på.\n" -#: command.c:4727 +#: command.c:4819 #, c-format msgid "Expanded display is used automatically.\n" msgstr "Utökad visning används automatiskt.\n" -#: command.c:4729 +#: command.c:4821 #, c-format msgid "Expanded display is off.\n" msgstr "Utökad visning är av.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4828 command.c:4830 command.c:4832 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "Expanderad rubrikvidd är \"%s\".\n" -#: command.c:4742 +#: command.c:4834 #, c-format msgid "Expanded header width is %d.\n" msgstr "Expanderad rubrikvidd är %d.\n" -#: command.c:4748 +#: command.c:4840 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "Fältseparatorn för CSV är \"%s\".\n" -#: command.c:4756 command.c:4764 +#: command.c:4848 command.c:4856 #, c-format msgid "Field separator is zero byte.\n" msgstr "Fältseparatorn är noll-byte.\n" -#: command.c:4758 +#: command.c:4850 #, c-format msgid "Field separator is \"%s\".\n" msgstr "Fältseparatorn är \"%s\".\n" -#: command.c:4771 +#: command.c:4863 #, c-format msgid "Default footer is on.\n" msgstr "Standard sidfot är på.\n" -#: command.c:4773 +#: command.c:4865 #, c-format msgid "Default footer is off.\n" msgstr "Standard sidfot är av.\n" -#: command.c:4779 +#: command.c:4871 #, c-format msgid "Output format is %s.\n" msgstr "Utdataformatet är \"%s\".\n" -#: command.c:4785 +#: command.c:4877 #, c-format msgid "Line style is %s.\n" msgstr "Linjestil är %s.\n" -#: command.c:4792 +#: command.c:4884 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null-visare är \"%s\".\n" -#: command.c:4800 +#: command.c:4892 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "Lokal-anpassad numerisk utdata är på.\n" -#: command.c:4802 +#: command.c:4894 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "Lokal-anpassad numerisk utdata är av.\n" -#: command.c:4809 +#: command.c:4901 #, c-format msgid "Pager is used for long output.\n" msgstr "Siduppdelare är på för lång utdata.\n" -#: command.c:4811 +#: command.c:4903 #, c-format msgid "Pager is always used.\n" msgstr "Siduppdelare används alltid.\n" -#: command.c:4813 +#: command.c:4905 #, c-format msgid "Pager usage is off.\n" msgstr "Siduppdelare är av.\n" -#: command.c:4819 +#: command.c:4911 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" msgstr[0] "Siduppdelare kommer inte användas för färre än %d linje.\n" msgstr[1] "Siduppdelare kommer inte användas för färre än %d linjer.\n" -#: command.c:4829 command.c:4839 +#: command.c:4921 command.c:4931 #, c-format msgid "Record separator is zero byte.\n" msgstr "Postseparatorn är noll-byte.\n" -#: command.c:4831 +#: command.c:4923 #, c-format msgid "Record separator is .\n" msgstr "Postseparatorn är .\n" -#: command.c:4833 +#: command.c:4925 #, c-format msgid "Record separator is \"%s\".\n" msgstr "Postseparatorn är \"%s\".\n" -#: command.c:4846 +#: command.c:4938 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Tabellattributen är \"%s\".\n" -#: command.c:4849 +#: command.c:4941 #, c-format msgid "Table attributes unset.\n" msgstr "Tabellattributen är ej satta.\n" -#: command.c:4856 +#: command.c:4948 #, c-format msgid "Title is \"%s\".\n" msgstr "Titeln är \"%s\".\n" -#: command.c:4858 +#: command.c:4950 #, c-format msgid "Title is unset.\n" msgstr "Titeln är inte satt.\n" -#: command.c:4865 +#: command.c:4957 #, c-format msgid "Tuples only is on.\n" msgstr "Visa bara tupler är på.\n" -#: command.c:4867 +#: command.c:4959 #, c-format msgid "Tuples only is off.\n" msgstr "Visa bara tupler är av.\n" -#: command.c:4873 +#: command.c:4965 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Unicode-ramstil är \"%s\".\n" -#: command.c:4879 +#: command.c:4971 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Unicode-kolumnLinjestil är \"%s\".\n" -#: command.c:4885 +#: command.c:4977 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Unicode-rubriklinjestil är \"%s\".\n" -#: command.c:5134 +#: command.c:5226 #, c-format msgid "\\!: failed" msgstr "\\!: misslyckades" -#: command.c:5168 +#: command.c:5264 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch kan inte användas på en tom fråga" -#: command.c:5200 +#: command.c:5296 #, c-format msgid "could not set timer: %m" msgstr "kunde inte sätta timer: %m" -#: command.c:5269 +#: command.c:5365 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (varje %gs)\n" -#: command.c:5272 +#: command.c:5368 #, c-format msgid "%s (every %gs)\n" msgstr "%s (varje %gs)\n" -#: command.c:5340 +#: command.c:5432 #, c-format msgid "could not wait for signals: %m" msgstr "kunde inte vänta på signaler: %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5488 command.c:5495 common.c:632 common.c:639 common.c:1123 #, c-format msgid "" -"********* QUERY **********\n" +"/******** QUERY *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" msgstr "" -"********* FRÅGA **********\n" +"/******** FRÅGA *********/\n" "%s\n" -"**************************\n" +"/************************/\n" "\n" -#: command.c:5584 +#: command.c:5674 #, c-format msgid "\"%s.%s\" is not a view" msgstr "\"%s.%s\" är inte en vy" -#: command.c:5600 +#: command.c:5690 #, c-format msgid "could not parse reloptions array" msgstr "kunde inte parsa arrayen reloptions" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "kan inte escape:a utan en aktiv uppkoppling" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "uppkopplingen till servern har brutits" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "Anslutningen till servern har brutits. Försöker starta om: " -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "Misslyckades.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "Lyckades.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "oväntad PQresultStatus: %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "Tid: %.3f ms\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Tid: %.3f ms (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Tid: %.3f ms (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Tid: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "Du är för närvarande inte uppkopplad mot en databas." -#: common.c:674 +#: common.c:714 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "Asynkron notificering \"%s\" mottagen med innehåll \"%s\" från serverprocess med PID %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "Asynkron notificering \"%s\" mottagen från serverprocess med PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "kunde inte visa resultatabell: %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "inga rader returnerades för \\gset" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "mer än en rad returnerades för \\gset" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "försök att utföra \\gset in i en speciellt hanterad variabel \"%s\" hoppas över" -#: common.c:1063 +#: common.c:1103 #, c-format msgid "" -"***(Single step mode: verify command)*******************************************\n" +"/**(Single step mode: verify command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to cancel)********************\n" +"/**(press return to proceed or enter x and return to cancel)*******************/\n" msgstr "" -"***(Stegningsläge: Verifiera kommando)*******************************************\n" +"/**(Stegningsläge: verifiera kommando)*****************************************/\n" "%s\n" -"***(tryck return för att fortsätta eller skriv x och return för att avbryta)*****\n" +"/**(tryck return för att fortsätta eller skriv x och return för att avbryta)***/\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "SATS: %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "oväntad transaktionsstatus (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "Kolumn" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "Typ" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "Kommandot hade inget resultat eller så hade resultatet inga kolumner.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "hämta resultat i chunk-läge misslyckades" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -934,11 +983,6 @@ msgstr "\\copy: parsfel vid \"%s\"" msgid "\\copy: parse error at end of line" msgstr "\\copy: parsfel vid radslutet" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "kunde inte köra kommandot \"%s\": %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -976,343 +1020,344 @@ msgstr "" "Mata in data som skall kopieras följt av en nyrad.\n" "Avsluta med bakstreck och en punkt ensamma på en rad eller av en EOF." -#: copy.c:682 +#: copy.c:684 msgid "aborted because of read failure" msgstr "avbruten på grund av läsfel" -#: copy.c:716 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "försöker avsluta kopieringsläge" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview: satsen returnerade ingen resultatmängd" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview: frågan måste returnera minst tre kolumner" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "\\crosstabview: vertical and horizontal headers must be different columns" msgstr "\\crosstabview: vertikala och horisontala rubriker måste vara olika kolumner" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "\\crosstabview: data column must be specified when query returns more than three columns" msgstr "\\crosstabview: datakolumn måste anges när frågan returnerar mer än tre kolumner" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview: maximalt antal kolumner (%d) överskridet" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"" msgstr "\\crosstabview: frågeresultatet innehåller multipla värden för rad \"%s\", kolumn \"%s\"" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview: kolumnnummer %d är utanför giltigt intervall 1..%d" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview: tvetydigt kolumnnamn: \"%s\"" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: hittar ej kolumnnamn: \"%s\"" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "Schema" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "Namn" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "Resultatdatatyp" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "Argumentdatatyp" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "Beskrivning" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "Lista med aggregatfunktioner" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "Servern (version %s) stöder inte accessmetoder." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "Index" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "Tabell" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "Hanterare" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "Lista med accessmetoder" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "Ägare" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "Plats" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "Alternativ" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "Storlek" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "Lista med tabellutrymmen" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df tar bara [anptwS+] som flaggor" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df tar inte en \"%c\"-flagga med serverversion %s" #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "agg" -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "fönster" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "proc" -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "funk" # Vi väljer att bevara den engelska termen då det dels refererar till kommandot CREATE TRIGGER # och dels för att detta begreppet normalt benäms som triggers i dagligt tal i Sverige. -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "trigger" # Vi väljer att bevara den engelska termen då det refererar till en del av CREATE FUNCTION-syntaxen -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "immutable" # Vi väljer att bevara den engelska termen då det refererar till en del av CREATE FUNCTION-syntaxen -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "stable" # Vi väljer att bevara den engelska termen då det refererar till en del av CREATE FUNCTION-syntaxen -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "volatile" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "Flyktighet" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "begränsad" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "säker" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "osäker" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "Parallell" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "definierare" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "anropare" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "Säkerhet" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "Språk" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "Internt namn" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "Lista med funktioner" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "Element" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "Lista med datatyper" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "Vänster argumenttyp" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "Höger argumenttyp" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "Resultattyp" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "Funktion" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "Lista med operatorer" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "Kodning" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "Lokalleverantör" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "Jämförelse" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "Ctype" -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "ICU-lokal" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "Lokal" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "ICU-regler" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "Tabellutrymme" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "Lista med databaser" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "tabell" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "vy" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "materialiserad vy" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "sekvens" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "främmande tabell" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "partitionerad tabell" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "Kolumnrättigheter" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "Policys" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "Åtkomsträttigheter" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "funktion" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "typ" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "schema" @@ -1344,293 +1389,293 @@ msgstr "operatorfamilj" msgid "rule" msgstr "rule" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "Objektbeskrivningar" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "Kunde inte hitta en relation med namn \"%s\"." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "Kunde inte hitta några relationer." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "Kunde inte hitta en relation med OID %s." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "Start" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "Minimum" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "Maximum" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "Ökning" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "ja" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "nej" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "Cyklisk?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "Cache" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "Ägd av: %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "Sekvens för identitetskolumn: %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Ologgat sekvens \"%s.%s\"" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Sekvens \"%s.%s\"" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Ologgad tabell \"%s.%s\"" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "Tabell \"%s.%s\"" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "Vy \"%s.%s\"" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "Ologgad materialiserad vy \"%s.%s\"" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Materialiserad vy \"%s.%s\"" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Ologgat index \"%s.%s\"" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "Index \"%s.%s\"" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Ologgat partitionerat index \"%s.%s\"" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Partitionerat index \"%s.%s\"" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "TOAST-tabell \"%s.%s\"" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Sammansatt typ \"%s.%s\"" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Främmande tabell \"%s.%s\"" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Ologgad partitionerad tabell \"%s.%s\"" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Partitionerad tabell \"%s.%s\"" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "Jämförelse" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "Nullbar" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "Standard" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "Nyckel?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "Definition" -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "FDW-alternativ" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "Lagring" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "Komprimering" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "Statistikmål" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "Partition av: %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "Inget partitioneringsvillkor" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "Partitioneringsvillkor: %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "Partitioneringsnyckel: %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Ägande tabell \"%s.%s\"" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "primärnyckel, " -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "unik" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " null-värden ej distinkta" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr ", " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "för tabell \"%s.%s\"" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", predikat (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", klustrad" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", ogiltig" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", uppskjutbar" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", initialt uppskjuten" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", replikaidentitet" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "Index:" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "Kontrollvillkor:" -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "Främmande nyckel-villkor:" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "Refererad av:" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "Policys:" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "Policys (tvingad radsäkerhet påslagen):" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "Policys (radsäkerhet påslagna): (ingen)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "Policys (tvingad radsäkerhet påslagen): (ingen)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "Policys (radsäkerhet avstängd):" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "Statistikobjekt:" @@ -1650,7 +1695,7 @@ msgstr "Regler som alltid utförs:" msgid "Rules firing on replica only:" msgstr "Regler som utförs enbart på replika:" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "Publiceringar:" @@ -1749,7 +1794,7 @@ msgstr ", tabellutrymme: \"%s\"" msgid "List of roles" msgstr "Lista med roller" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "Rollnamn" @@ -1827,368 +1872,368 @@ msgstr "Kunde inte hitta några inställningar för roll \"%s\"." msgid "Did not find any settings." msgstr "Kunde inte hitta några inställningar." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "Lista med inställningar" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "Medlem av" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "Rättighetsutdelare" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "Lista med roll-rättigheter" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "index" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "TOAST-tabell" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "partitionerat index" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "permanent" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "temporär" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "ologgad" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "Persistens" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "Accessmetod" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "Lista med relationer" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "Servern (version %s) stöder inte deklarativ tabellpartitionering." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "Lista med partitionerade index" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "Lista med partitionerade tabeller" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "Lista med partitionerade relationer" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "Föräldranamn" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "Partitionsstorlek av löv" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "Total storlek" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "Tillförlitlig" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "Internt språk" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "Anropshanterare" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "Validerare" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "Inline-hanterare" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "Lista med språk" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "Check" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "Lista med domäner" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "Källa" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "Mål" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "Standard?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "Lista med konverteringar" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "Parameter" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "Värde" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "Kontext" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "Lista med konfigurationsparametrar" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "Lista med icke-defaulta konfigurationsparametrar" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "Servern (version %s) stöder inte händelsetriggrar." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "Händelse" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "påslagen" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "replika" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "alltid" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "avstängd" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "Påslagen" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "Etiketter" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "Lista med händelsetriggrar" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "Servern (version %s) stöder inte utökad statistik." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Nunika" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Beroenden" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "Lista med utökad statistik" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Källtyp" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Måltyp" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "i tilldelning" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Implicit?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "Lista med typomvandlingar" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "Leverantör" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "Deterministisk?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "Lista med jämförelser (collations)" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "Lista med scheman" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "Lista med textsökparsrar" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "Kunde inte hitta en textsökparser med namn \"%s\"." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "Kunde inte hitta några textsökparsrar." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "Starta parsning" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "Metod" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "Hämta nästa symbol" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "Avsluta parsning" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "Hämta rubrik" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "Hämta symboltyper" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Textsökparser \"%s.%s\"" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "Textsökparser \"%s\"" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "Symbolnamn" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Symboltyper för parser \"%s.%s\"" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "Symboltyper för parser \"%s\"" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "Mall" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "Initieringsalternativ" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "Lista med textsökordlistor" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "Init" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Symboluppdelning" -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "Lista med textsökmallar" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "Lista med textsökkonfigurationer" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "Kunde inte hitta en textsökkonfiguration med namn \"%s\"." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "Kunde inte hitta några textsökkonfigurationer." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "Symbol" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "Ordlistor" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Textsökkonfiguration \"%s.%s\"" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "Textsökkonfiguration \"%s\"" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "" "\n" @@ -2197,7 +2242,7 @@ msgstr "" "\n" "Parser: \"%s.%s\"" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "" "\n" @@ -2206,265 +2251,273 @@ msgstr "" "\n" "Parser: \"%s\"" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "Lista med främmande data-omvandlare" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "Främmande data-omvandlare" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "Version" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "Lista med främmande servrar" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "Server" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "Användarnamn" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "Lista av användarmappningar" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "Lista med främmande tabeller" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "Lista med installerade utökningar" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "Kunde inte hitta en utökning med namn \"%s\"." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "Kunde inte hitta några utökningar." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "Objektbeskrivning" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "Objekt i utökning \"%s\"" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "ej korrekt kvalificerat namn (för många namn med punkt): %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "referenser till andra databaser är inte implementerat: %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "Servern (version %s) stöder inte publiceringar." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "Alla tabeller" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Insättningar" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Uppdateringar" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Borttagningar" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Trunkeringar" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Via root" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "Lista med publiceringar" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "Kunde inte hitta någon publicering med namn \"%s\"." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "Kunde inte hitta några publiceringar." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "Publicering %s" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "Tabeller:" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "Tabeller från scheman:" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "Denna server (version %s) stöder inte prenumerationer." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "Publicering" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "Binär" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "Strömmande" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "Tvåfas-commit" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "Stäng av vid fel" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "Ursprung" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "Lösenord krävs" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "Kör som ägare?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "Failover" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "Synkron commit" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "Anslutningsinfo" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "Skippa LSN" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "Lista med prenumerationer" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(ingen)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "AM" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "Indatatyp" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "Lagringstyp" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "Operatorklass" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "Operatorfamilj" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "Lista med operatorklasser" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Applicerbara typer" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "Lista med operatorfamiljer" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "Operator" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "Strategi" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "ordning" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "sök" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "Ändamål" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "Sortering-opfamilj" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "Lista med operatorer i operatorfamiljer" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "Registrerad vänstertyp" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "Registrerad högertyp" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "Nummer" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "Lista med supportfunktioner i operatorfamiljer" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "Stora objekt" -#: help.c:75 +#: help.c:63 msgid "" "psql is the PostgreSQL interactive terminal.\n" "\n" @@ -2472,11 +2525,11 @@ msgstr "" "psql är den interaktiva PostgreSQL-terminalen.\n" "\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:502 msgid "Usage:\n" msgstr "Användning:\n" -#: help.c:77 +#: help.c:65 msgid "" " psql [OPTION]... [DBNAME [USERNAME]]\n" "\n" @@ -2484,28 +2537,27 @@ msgstr "" " psql [FLAGGA]... [DBNAMN [ANVÄNDARNAMN]]\n" "\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "Allmänna flaggor:\n" -#: help.c:84 +#: help.c:68 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr " -c, --command=KOMMANDO kör ett kommando (SQL eller internt) och avsluta sedan\n" -#: help.c:85 -#, c-format -msgid " -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr " -d, --dbname=DBNAMN databasnamn att koppla upp mot (standard: \"%s\")\n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=DBNAMN namn på databas att ansluta till\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=FILNAMN kör kommandon från fil och avsluta sedan\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list lista befintliga databaser och avsluta sedan\n" -#: help.c:89 +#: help.c:72 msgid "" " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" @@ -2515,15 +2567,15 @@ msgstr "" " sätt psql-variabel NAMN till VÄRDE\n" " (t.ex. -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc läs inte startfilen (~/.psqlrc)\n" -#: help.c:94 +#: help.c:77 msgid "" " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" @@ -2531,19 +2583,19 @@ msgstr "" " -1 (\"ett\"), --single-transaction\n" " kör kommandofilen som en transaktion (om icke-interaktiv)\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help[=alternativ] visa denna hjälp, avsluta sedan\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands lista bakstreck-kommandon, avsluta sedan\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variabler lista speciella variabler, avsluta sedan\n" -#: help.c:100 +#: help.c:83 msgid "" "\n" "Input and output options:\n" @@ -2551,47 +2603,47 @@ msgstr "" "\n" "Flaggor för in-/utmatning:\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all visa all indata från skript\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors visa misslyckade kommandon\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries visa kommandon som skickas till servern\n" -#: help.c:104 +#: help.c:87 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden visa frågor som interna kommandon skapar\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=FILENAME skicka sessions-logg till fil\n" -#: help.c:106 +#: help.c:89 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr " -n, --no-readline slå av förbättrad kommandoradsredigering (readline)\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=FILNAMN skriv frågeresultat till fil (eller |rör)\n" -#: help.c:108 +#: help.c:91 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr " -q, --quiet kör tyst (inga meddelanden, endast frågeutdata)\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step stegningsläge (bekräfta varje fråga)\n" -#: help.c:110 +#: help.c:93 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr " -S, --single-line enradsläge (slutet på raden avslutar SQL-kommando)\n" -#: help.c:112 +#: help.c:95 msgid "" "\n" "Output format options:\n" @@ -2599,15 +2651,15 @@ msgstr "" "\n" "Flaggor för utdataformat:\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align ojusterad utskrift av tabeller\n" -#: help.c:114 +#: help.c:97 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv CSV-utmarningsläge (kommaseparerade värden)\n" -#: help.c:115 +#: help.c:98 #, c-format msgid "" " -F, --field-separator=STRING\n" @@ -2616,15 +2668,15 @@ msgstr "" " -F, --field-separator=STRÄNG\n" " fältseparator för icke justerad utdata (standard: \"%s\")\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html HTML-utskrift av tabeller\n" -#: help.c:119 +#: help.c:102 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr " -P, --pset=VAR[=ARG] sätt utskriftsvariabel VAR till ARG (se kommando \\pset)\n" -#: help.c:120 +#: help.c:103 msgid "" " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" @@ -2632,19 +2684,19 @@ msgstr "" " -R, --record-separator=STRÄNG\n" " sätt postseparator för icke justerad utdata (standard: newline)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only visa endast rader\n" -#: help.c:123 +#: help.c:106 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr " -T, --table-attr=TEXT sätt HTML-tabellers flaggor (t.ex. width, border)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded slå på utökad utsrift av tabeller\n" -#: help.c:125 +#: help.c:108 msgid "" " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" @@ -2652,7 +2704,7 @@ msgstr "" " -z, --field-separator-zero\n" " sätt fältseparator för icke justerad utdata till noll-byte\n" -#: help.c:127 +#: help.c:110 msgid "" " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" @@ -2660,7 +2712,7 @@ msgstr "" " -0, --record-separator=zero\n" " sätt postseparator för icke justerad utdata till noll-byte\n" -#: help.c:130 +#: help.c:113 msgid "" "\n" "Connection options:\n" @@ -2668,36 +2720,27 @@ msgstr "" "\n" "Flaggor för anslutning:\n" -#: help.c:133 -#, c-format -msgid " -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n" -msgstr "" -" -h, --host=VÄRDNAMN databasens värdnamn eller uttagkatalog (socket)\n" -" (standard: \"%s\")\n" - -#: help.c:134 -msgid "local socket" -msgstr "lokalt uttag (socket)" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr " -p, --port=PORT databasens serverport (standard: \"%s\")\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=PORT databasserverns port\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr " -U, --username=ANVNAMN användarnamn för databasen (standard: \"%s\")\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=ANVNAMN namn på databasens användare\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga aldrig efter lösenord\n" -#: help.c:143 +#: help.c:118 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password fråga om lösenord (borde ske automatiskt)\n" -#: help.c:145 +#: help.c:120 msgid "" "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" @@ -2711,37 +2754,37 @@ msgstr "" "i PostgreSQL-dokumentationen.\n" "\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Rapportera fel till <%s>.\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "Allmänna\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [PARAM]... sätt frågeparameter\n" -#: help.c:193 +#: help.c:168 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright visa PostgreSQL-upphovsrättsinformation\n" -#: help.c:194 +#: help.c:169 msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr " \\crosstabview [KOLUMNER] kör fråga och visa resultatet i en korstabell\n" -#: help.c:195 +#: help.c:170 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose visa senste felmeddelande vid maximal verbositet\n" -#: help.c:196 +#: help.c:171 msgid "" " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" @@ -2749,228 +2792,234 @@ msgstr "" " \\g [(FLAGGOR)] [FIL] kör frågan (och skicka resultatet till fil eller |rör);\n" " \\g utan argument är samma som ett semikolon\n" -#: help.c:198 +#: help.c:173 msgid " \\gdesc describe result of query, without executing it\n" msgstr " \\gdesc beskriv resultatet av fråga utan att köra den\n" -#: help.c:199 +#: help.c:174 msgid " \\gexec execute query, then execute each value in its result\n" msgstr " \\gexec kör fråga, kör sen varje värde i resultatet\n" -#: help.c:200 +#: help.c:175 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr " \\gset [PREFIX] kör frågan och spara resultatet i psql-variabler\n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr " \\gx [(FLAGGOR)] [FIL] som \\g, men tvinga expanderat utmatningsläge\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q avsluta psql\n" -#: help.c:203 -msgid " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" -msgstr " \\watch [[i=]SEK] [c=N] kör fråga var SEK sekund, upp till N gånger\n" +#: help.c:178 +msgid "" +" \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" +msgstr "" +" \\watch [[i=]SEK] [c=N] [m=MIN]\n" +" kör fråga var SEK sekund, upp till N gånger,\n" +" stoppa om färre än MIN rader returneras\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "Hjälp\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [kommandon] visa hjälp om backstreckkommandon\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options visa hjälp för psqls kommandoradflaggor\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables visa hjälp om speciella variabler\n" -#: help.c:211 +#: help.c:188 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr " \\h [NAMN] hjälp med syntaxen för SQL-kommandon, * för alla kommandon\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "Frågebuffert\n" -#: help.c:215 +#: help.c:192 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr " \\e [FIL] [RAD] redigera frågebufferten (eller filen) med extern redigerare\n" -#: help.c:216 +#: help.c:193 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr " \\ef [FUNKNAMN [RAD]] redigera funktionsdefinition med extern redigerare\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr " \\ev [FUNKNAMN [RAD]] redigera vydefinition med extern redigerare\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p visa innehållet i frågebufferten\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r nollställ (radera) frågebufferten\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [FILNAMN] visa kommandohistorien eller spara den i fil\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr " \\w FILNAMN skriv frågebuffert till fil\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "In-/Utmatning\n" -#: help.c:227 +#: help.c:204 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr " \\copy ... utför SQL COPY med dataström till klientvärden\n" -#: help.c:228 +#: help.c:205 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [TEXT] skriv text till standard ut (-n för ingen nyrad)\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i FILNAMN kör kommandon från fil\n" -#: help.c:230 +#: help.c:207 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr " \\ir FIL som \\i, men relativt platsen för aktuellt script\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [FIL] skicka frågeresultat till fil eller |rör\n" -#: help.c:232 +#: help.c:209 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr " \\qecho [-n] [TEXT] skriv text till \\o-utdataströmmen (-n för ingen nyrad)\n" -#: help.c:233 +#: help.c:210 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr " \\warn [-n] [TEXT] skriv text till standard error (-n för ingen nyrad)\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "Villkor\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPR starta villkorsblock\n" -#: help.c:238 +#: help.c:215 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif EXPR alternativ inom aktuellt villkorsblock\n" -#: help.c:239 +#: help.c:216 msgid " \\else final alternative within current conditional block\n" msgstr " \\else avslutningsalternativ inom aktuellt villkorsblock\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif avsluta villkorsblock\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "Information\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr " (flaggor: S = lista systemobjekt, + = mer detaljer)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr " \\d[S+] lista tabeller, vyer och sekvenser\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr " \\d[S+] NAMN beskriv tabell, vy, sekvens eller index\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" msgstr " \\da[S] [MALL] lista aggregatfunktioner\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [MALL] lista accessmetoder\n" -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] lista operatorklasser\n" -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] lista operatorfamiljer\n" -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] lista operatorer i operatorfamiljer\n" -#: help.c:252 +#: help.c:229 msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] lista supportfunktioner i operatorfamiljer\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [MALL] lista tabellutrymmen\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [MALL] lista konverteringar\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [MALL] lista konfigurationsparametrar\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [MALL] lista typomvandlingar\n" -#: help.c:257 +#: help.c:234 msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr " \\dd[S] [MALL] visa objektbeskrivning som inte visas på andra ställen\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [MALL] lista domäner\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [MALL] lista standardrättigheter\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [MALL] lista främmande tabeller\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [MALL] lista främmande servrar\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\det[+] [MALL] lista främmande tabeller\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [MALL] lista användarmappning\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [MALL] lista främmande data-omvandlare\n" -#: help.c:265 +#: help.c:242 msgid "" " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] functions\n" @@ -2978,47 +3027,47 @@ msgstr "" " \\df[anptw][S+] [FUNKMALL [TYPMALL ...]]\n" " lista [endast agg/normala/procedur/trigger/window] funktioner\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr " \\dF[+] [MALL] lista textsökkonfigurationer\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr " \\dFd[+] [MALL] lista textsökordlistor\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr " \\dFp[+] [MALL] lista textsökparsrar\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr " \\dFt[+] [MALL] lista textsökmallar\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [MALL] lista roller\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [MALL] lista index\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr " \\dl[+] lista stora objekt, samma som \\lo_list\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [MALL] lista procedurspråk\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [MALL] lista materialiserade vyer\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [MALL] lista scheman\n" -#: help.c:277 +#: help.c:254 msgid "" " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" @@ -3026,93 +3075,93 @@ msgstr "" " \\do[S+] [OPMALL [TYPMALL [TYPMALL]]]\n" " lista operatorer\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S+] [MALL] lista jämförelser (collation)\n" -#: help.c:280 +#: help.c:257 msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr " \\dp[S] [MALL] lista åtkomsträttigheter för tabeller, vyer och sekvenser\n" -#: help.c:281 +#: help.c:258 msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" msgstr " \\dP[tin+] [MALL] lista [bara tabell/index] partitionerade relationer [n=nästlad]\n" -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr "" " \\drds [ROLLMALL1 [DBMALL2]]\n" " lista rollinställningar per databas\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\drg[S] [MALL] lista roll-rättigheter\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[+] [MALL] lista replikeringspubliceringar\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [MALL] lista replikeringsprenumerationer\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [MALL] lista sekvenser\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [MALL] lista tabeller\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [MALL] lista datatyper\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [MALL] lista roller\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [MALL] lista vyer\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [MALL] lista utökningar\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [MALL] lista utökad statistik\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [MALL] lista händelsetriggrar\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [MALL] lista databaser\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] FUNKNAMN visa en funktions definition\n" -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv[+] VYNAMN visa en vys definition\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [MALL] samma som \\dp\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "Stora objekt\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr " \\lo_export LOBOID FIL skriv stort objekt till fil\n" -#: help.c:302 +#: help.c:279 msgid "" " \\lo_import FILE [COMMENT]\n" " read large object from file\n" @@ -3120,36 +3169,36 @@ msgstr "" " \\lo_import FIL [KOMMENTAR]\n" " läs stort objekt från fil\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\lo_list[+] lista stora objekt\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID ta bort stort objekt\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "Formatering\n" -#: help.c:309 +#: help.c:286 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr " \\a byt mellan ojusterat och justerat utdataformat\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr " \\C [TEXT] sätt tabelltitel, eller nollställ\n" -#: help.c:311 +#: help.c:288 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr " \\f [TEXT] visa eller sätt fältseparatorn för ojusterad utmatning\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H slå på/av HTML-utskriftsläge (för närvarande: %s)\n" -#: help.c:314 +#: help.c:291 msgid "" " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3157,7 +3206,7 @@ msgid "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" msgstr "" " \\pset [NAMN [VÄRDE]] sätt utmatningsalternativ för tabeller\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" @@ -3165,31 +3214,31 @@ msgstr "" " numericlocale|pager|pager_min_lines|recordsep|\n" " recordsep_zero|tableattr|title|tuples_only|\n" " unicode_border_linestyle|unicode_column_linestyle|\n" -" unicode_header_linestyle)\n" +" unicode_header_linestyle|xheader_width)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] visa endast rader (för närvarande: %s)\n" -#: help.c:323 +#: help.c:300 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr " \\T [TEXT] sätt HTML-tabellens
-attribut, eller nollställ\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" -msgstr " \\x [on|off|auto] slå på/av utökad utskrift (för närvarande: %s)\n" +msgstr " \\x [on|off|auto] slå på/av expanderat utmatningsläge (för närvarande: %s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "auto" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "Anslutning\n" -#: help.c:330 +#: help.c:307 #, c-format msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" @@ -3198,7 +3247,7 @@ msgstr "" " \\c[onnect] {[DBNAMN|- ANVÄNDARE|- VÄRD|- PORT|-] | conninfo}\n" " koppla upp mot ny databas (för närvarande \"%s\")\n" -#: help.c:334 +#: help.c:311 msgid "" " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" @@ -3206,70 +3255,70 @@ msgstr "" " \\c[onnect] {[DBNAMN|- ANVÄNDARE|- VÄRD|- PORT|-] | conninfo}\n" " koppla upp mot ny databas (för närvarande ingen uppkoppling)\n" -#: help.c:336 +#: help.c:313 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo visa information om aktuell uppkoppling\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [KODNING] visa eller sätt klientens teckenkodning\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr " \\password [ANVÄNDARNAMN] byt användares lösenord på ett säkert sätt\n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "Operativsystem\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [KATALOG] byt den aktuella katalogen\n" -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVVAR hämta omgivningsvariabel\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv NAMN [VÄRDE] sätt eller nollställ omgivningsvariabel\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] slå på/av tidstagning av kommandon (för närvarande: %s)\n" -#: help.c:347 +#: help.c:324 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr " \\! [KOMMANDO] kör kommando i skal eller starta interaktivt skal\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "Variabler\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr " \\prompt [TEXT] NAMN be användaren att sätta en intern variabel\n" -#: help.c:352 +#: help.c:329 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr " \\set [NAMN [VÄRDE]] sätt intern variabel, eller lista alla om ingen param\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NAME ta bort intern variabel\n" -#: help.c:392 +#: help.c:369 msgid "" "List of specially treated variables\n" "\n" msgstr "Lista av variabler som hanteras speciellt\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "psql-variabler:\n" -#: help.c:396 +#: help.c:373 msgid "" " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n" @@ -3279,7 +3328,7 @@ msgstr "" " eller \\set NAMN VÄRDE inne i psql\n" "\n" -#: help.c:398 +#: help.c:375 msgid "" " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" @@ -3287,7 +3336,7 @@ msgstr "" " AUTOCOMMIT\n" " om satt så kommer efterföljande SQL-kommandon commit:as automatiskt\n" -#: help.c:400 +#: help.c:377 msgid "" " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" @@ -3297,7 +3346,7 @@ msgstr "" " bestämmer skiftläge för att komplettera SQL-nyckelord\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:403 +#: help.c:380 msgid "" " DBNAME\n" " the currently connected database name\n" @@ -3305,7 +3354,7 @@ msgstr "" " DBNAME\n" " den uppkopplade databasens namn\n" -#: help.c:405 +#: help.c:382 msgid "" " ECHO\n" " controls what input is written to standard output\n" @@ -3315,7 +3364,7 @@ msgstr "" " bestämmer vilken indata som skrivs till standard ut\n" " [all, errors, none, queries]\n" -#: help.c:408 +#: help.c:385 msgid "" " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" @@ -3325,7 +3374,7 @@ msgstr "" " om satt, visa interna frågor som körs av backåtstreckkommandon:\n" " om satt till \"noexec\", bara visa dem utan att köra\n" -#: help.c:411 +#: help.c:388 msgid "" " ENCODING\n" " current client character set encoding\n" @@ -3333,7 +3382,7 @@ msgstr "" " ENCODING\n" " aktuell teckenkodning för klient\n" -#: help.c:413 +#: help.c:390 msgid "" " ERROR\n" " \"true\" if last query failed, else \"false\"\n" @@ -3341,7 +3390,7 @@ msgstr "" " ERROR\n" " \"true\" om sista frågan misslyckades, \"false\" annars\n" -#: help.c:415 +#: help.c:392 msgid "" " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" @@ -3349,7 +3398,7 @@ msgstr "" " FETCH_COUNT\n" " antal resultatrader som hämtas och visas åt gången (0=obegränsat)\n" -#: help.c:417 +#: help.c:394 msgid "" " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" @@ -3357,7 +3406,7 @@ msgstr "" " HIDE_TABLEAM\n" " om satt så visas inte accessmetoder\n" -#: help.c:419 +#: help.c:396 msgid "" " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" @@ -3365,7 +3414,7 @@ msgstr "" " HIDE_TOAST_COMPRESSION\n" " om satt så visas inte komprimeringsmetoder\n" -#: help.c:421 +#: help.c:398 msgid "" " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" @@ -3373,7 +3422,7 @@ msgstr "" " HISTCONTROL\n" " styr kommandohistoriken [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:423 +#: help.c:400 msgid "" " HISTFILE\n" " file name used to store the command history\n" @@ -3381,7 +3430,7 @@ msgstr "" " HISTFILE\n" " filnamn för att spara kommandohistoriken i\n" -#: help.c:425 +#: help.c:402 msgid "" " HISTSIZE\n" " maximum number of commands to store in the command history\n" @@ -3389,7 +3438,7 @@ msgstr "" " HISTSIZE\n" " maximalt antal kommandon som sparas i kommandohistoriken\n" -#: help.c:427 +#: help.c:404 msgid "" " HOST\n" " the currently connected database server host\n" @@ -3397,7 +3446,7 @@ msgstr "" " HOST\n" " den uppkopplade databasens värd\n" -#: help.c:429 +#: help.c:406 msgid "" " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" @@ -3405,7 +3454,7 @@ msgstr "" " IGNOREEOF\n" " antal EOF som behövs för att avsluta en interaktiv session\n" -#: help.c:431 +#: help.c:408 msgid "" " LASTOID\n" " value of the last affected OID\n" @@ -3413,7 +3462,7 @@ msgstr "" " LASTOID\n" " värdet av den senast påverkade OID:en\n" -#: help.c:433 +#: help.c:410 msgid "" " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" @@ -3423,7 +3472,7 @@ msgstr "" " LAST_ERROR_SQLSTATE\n" " meddelande och SQLSTATE för sista felet eller en tom sträng och \"00000\" om det inte varit fel\n" -#: help.c:436 +#: help.c:413 msgid "" " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" @@ -3431,7 +3480,7 @@ msgstr "" " ON_ERROR_ROLLBACK\n" " om satt, ett fel stoppar inte en transaktion (använder implicita sparpunkter)\n" -#: help.c:438 +#: help.c:415 msgid "" " ON_ERROR_STOP\n" " stop batch execution after error\n" @@ -3439,7 +3488,7 @@ msgstr "" " ON_ERROR_STOP\n" " avsluta batchkörning vid fel\n" -#: help.c:440 +#: help.c:417 msgid "" " PORT\n" " server port of the current connection\n" @@ -3447,7 +3496,7 @@ msgstr "" " PORT\n" " värdport för den aktuella uppkopplingen\n" -#: help.c:442 +#: help.c:419 msgid "" " PROMPT1\n" " specifies the standard psql prompt\n" @@ -3455,7 +3504,7 @@ msgstr "" " PROMPT1\n" " anger standardprompten för psql\n" -#: help.c:444 +#: help.c:421 msgid "" " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" @@ -3463,7 +3512,7 @@ msgstr "" " PROMPT2\n" " anger den prompt som används om en sats forsätter på efterföljande rad\n" -#: help.c:446 +#: help.c:423 msgid "" " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" @@ -3471,7 +3520,7 @@ msgstr "" " PROMPT3\n" " anger den prompt som används för COPY ... FROM STDIN\n" -#: help.c:448 +#: help.c:425 msgid "" " QUIET\n" " run quietly (same as -q option)\n" @@ -3479,7 +3528,7 @@ msgstr "" " QUIET\n" " kör tyst (samma som flaggan -q)\n" -#: help.c:450 +#: help.c:427 msgid "" " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" @@ -3487,7 +3536,7 @@ msgstr "" " ROW_COUNT\n" " antal rader som returnerades eller påverkades av senaste frågan alternativt 0\n" -#: help.c:452 +#: help.c:429 msgid "" " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" @@ -3497,7 +3546,7 @@ msgstr "" " SERVER_VERSION_NAME\n" " serverns version (i kort sträng eller numeriskt format)\n" -#: help.c:455 +#: help.c:432 msgid "" " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" @@ -3505,7 +3554,7 @@ msgstr "" " ERROR\n" " \"true\" om sista frågan misslyckades, \"false\" annars\n" -#: help.c:457 +#: help.c:434 msgid "" " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" @@ -3513,7 +3562,7 @@ msgstr "" " SHELL_EXIT_CODE\n" " exit-kod för senaste skalkommandot\n" -#: help.c:459 +#: help.c:436 msgid "" " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" @@ -3522,7 +3571,7 @@ msgstr "" " visa alla resultat från en kombinerad fråga (\\;) istället för bara\n" " det sista\n" -#: help.c:461 +#: help.c:438 msgid "" " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" @@ -3530,7 +3579,7 @@ msgstr "" " SHOW_CONTEXT\n" " styr visning av meddelandekontextfält [never, errors, always]\n" -#: help.c:463 +#: help.c:440 msgid "" " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" @@ -3538,7 +3587,7 @@ msgstr "" " SINGLELINE\n" " om satt, slut på raden avslutar SQL-kommandon (samma som flaggan -S )\n" -#: help.c:465 +#: help.c:442 msgid "" " SINGLESTEP\n" " single-step mode (same as -s option)\n" @@ -3546,7 +3595,7 @@ msgstr "" " SINGLESTEP\n" " stegningsläge (samma som flaggan -s)\n" -#: help.c:467 +#: help.c:444 msgid "" " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" @@ -3554,7 +3603,7 @@ msgstr "" " SQLSTATE\n" " SQLSTATE för sista frågan eller \"00000\" om det inte varit fel\n" -#: help.c:469 +#: help.c:446 msgid "" " USER\n" " the currently connected database user\n" @@ -3562,7 +3611,7 @@ msgstr "" " USER\n" " den uppkopplade databasanvändaren\n" -#: help.c:471 +#: help.c:448 msgid "" " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" @@ -3570,7 +3619,7 @@ msgstr "" " VERBOSITY\n" " styr verbositet för felrapporter [default, verbose, terse, sqlstate]\n" -#: help.c:473 +#: help.c:450 msgid "" " VERSION\n" " VERSION_NAME\n" @@ -3582,7 +3631,7 @@ msgstr "" " VERSION_NUM\n" " psql:s version (i lång sträng, kort sträng eller numeriskt format)\n" -#: help.c:478 +#: help.c:455 msgid "" "\n" "Display settings:\n" @@ -3590,7 +3639,7 @@ msgstr "" "\n" "Visningsinställningar:\n" -#: help.c:480 +#: help.c:457 msgid "" " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n" @@ -3600,7 +3649,7 @@ msgstr "" " eller \\pset NAMN [VÄRDE] inne i psql\n" "\n" -#: help.c:482 +#: help.c:459 msgid "" " border\n" " border style (number)\n" @@ -3608,7 +3657,7 @@ msgstr "" " border\n" " ramstil (nummer)\n" -#: help.c:484 +#: help.c:461 msgid "" " columns\n" " target width for the wrapped format\n" @@ -3616,15 +3665,15 @@ msgstr "" " columns\n" " målvidd för wrappade format\n" -#: help.c:486 +#: help.c:463 msgid "" " expanded (or x)\n" " expanded output [on, off, auto]\n" msgstr "" " expanded (eller x)\n" -" expanderad utdata [on, off, auto]\n" +" expanderat utmatningsläge [on, off, auto]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid "" " fieldsep\n" @@ -3633,7 +3682,7 @@ msgstr "" " fieldsep\n" " fältseparator för ej justerad utdata (standard \"%s\")\n" -#: help.c:491 +#: help.c:468 msgid "" " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" @@ -3641,7 +3690,7 @@ msgstr "" " fieldsep_zero\n" " sätt fältseparator för ej justerad utdata till noll-byte\n" -#: help.c:493 +#: help.c:470 msgid "" " footer\n" " enable or disable display of the table footer [on, off]\n" @@ -3649,7 +3698,7 @@ msgstr "" " footer\n" " slå på/av visning av tabellfot [on, off]\n" -#: help.c:495 +#: help.c:472 msgid "" " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" @@ -3657,7 +3706,7 @@ msgstr "" " format\n" " sätt utdataformat [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid "" " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" @@ -3665,7 +3714,7 @@ msgstr "" " linestyle\n" " sätt ramlinjestil [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid "" " null\n" " set the string to be printed in place of a null value\n" @@ -3673,7 +3722,7 @@ msgstr "" " null\n" " sätt sträng som visas istället för null-värden\n" -#: help.c:501 +#: help.c:478 msgid "" " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" @@ -3681,7 +3730,7 @@ msgstr "" " numericlocale\n" " slå på visning av lokalspecifika tecken för gruppering av siffror\n" -#: help.c:503 +#: help.c:480 msgid "" " pager\n" " control when an external pager is used [yes, no, always]\n" @@ -3689,7 +3738,7 @@ msgstr "" " pager\n" " styr när en extern pagenerare används [yes, no, always]\n" -#: help.c:505 +#: help.c:482 msgid "" " recordsep\n" " record (line) separator for unaligned output\n" @@ -3697,7 +3746,7 @@ msgstr "" " recordsep\n" " post (rad) separator för ej justerad utdata\n" -#: help.c:507 +#: help.c:484 msgid "" " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" @@ -3705,7 +3754,7 @@ msgstr "" " recordsep_zero\n" " sätt postseparator för ej justerad utdata till noll-byte\n" -#: help.c:509 +#: help.c:486 msgid "" " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" @@ -3715,7 +3764,7 @@ msgstr "" " ange attribut för tabelltaggen i html-format eller proportionella\n" " kolumnvidder för vänsterjusterade datatypet i latex-longtable-format\n" -#: help.c:512 +#: help.c:489 msgid "" " title\n" " set the table title for subsequently printed tables\n" @@ -3723,7 +3772,7 @@ msgstr "" " title\n" " sätt tabelltitel för efterkommande tabellutskrifter\n" -#: help.c:514 +#: help.c:491 msgid "" " tuples_only\n" " if set, only actual table data is shown\n" @@ -3731,7 +3780,7 @@ msgstr "" " tuples_only\n" " om satt, bara tabelldatan visas\n" -#: help.c:516 +#: help.c:493 msgid "" " unicode_border_linestyle\n" " unicode_column_linestyle\n" @@ -3743,7 +3792,17 @@ msgstr "" " unicode_header_linestyle\n" " sätter stilen på Unicode-linjer [single, double]\n" -#: help.c:521 +#: help.c:497 +msgid "" +" xheader_width\n" +" set the maximum width of the header for expanded output\n" +" [full, column, page, integer value]\n" +msgstr "" +" xheader_width\n" +" sätt maximal bredd på rubriken för expanderat utmatningsläge\n" +" [full, column, page, integer value]\n" + +#: help.c:501 msgid "" "\n" "Environment variables:\n" @@ -3751,7 +3810,7 @@ msgstr "" "\n" "Omgivningsvariabler:\n" -#: help.c:525 +#: help.c:505 msgid "" " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n" @@ -3761,7 +3820,7 @@ msgstr "" " eller \\setenv NAMN [VÄRDE] inne psql\n" "\n" -#: help.c:527 +#: help.c:507 msgid "" " set NAME=VALUE\n" " psql ...\n" @@ -3773,7 +3832,7 @@ msgstr "" " eller \\setenv NAMN [VÄRDE] inne i psql\n" "\n" -#: help.c:530 +#: help.c:510 msgid "" " COLUMNS\n" " number of columns for wrapped format\n" @@ -3781,7 +3840,7 @@ msgstr "" " COLUMNS\n" " antal kolumner i wrappade format\n" -#: help.c:532 +#: help.c:512 msgid "" " PGAPPNAME\n" " same as the application_name connection parameter\n" @@ -3789,7 +3848,7 @@ msgstr "" " PGAPPNAME\n" " samma som anslutningsparametern \"application_name\"\n" -#: help.c:534 +#: help.c:514 msgid "" " PGDATABASE\n" " same as the dbname connection parameter\n" @@ -3797,7 +3856,7 @@ msgstr "" " PGDATABASE\n" " samma som anslutningsparametern \"dbname\"\n" -#: help.c:536 +#: help.c:516 msgid "" " PGHOST\n" " same as the host connection parameter\n" @@ -3805,7 +3864,7 @@ msgstr "" " PGHOST\n" " samma som anslutningsparametern \"host\"\n" -#: help.c:538 +#: help.c:518 msgid "" " PGPASSFILE\n" " password file name\n" @@ -3813,7 +3872,7 @@ msgstr "" " PGPASSFILE\n" " lösenordsfilnamn\n" -#: help.c:540 +#: help.c:520 msgid "" " PGPASSWORD\n" " connection password (not recommended)\n" @@ -3821,7 +3880,7 @@ msgstr "" " PGPASSWORD\n" " uppkoppingens lösenord (rekommenderas inte)\n" -#: help.c:542 +#: help.c:522 msgid "" " PGPORT\n" " same as the port connection parameter\n" @@ -3829,7 +3888,7 @@ msgstr "" " PGPORT\n" " samma som anslutingsparametern \"port\"\n" -#: help.c:544 +#: help.c:524 msgid "" " PGUSER\n" " same as the user connection parameter\n" @@ -3837,7 +3896,7 @@ msgstr "" " PGUSER\n" " samma som anslutningsparametern \"user\"\n" -#: help.c:546 +#: help.c:526 msgid "" " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" @@ -3845,7 +3904,7 @@ msgstr "" " PSQL_EDITOR, EDITOR, VISUAL\n" " redigerare som används av kommanona \\e, \\ef och \\ev\n" -#: help.c:548 +#: help.c:528 msgid "" " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" @@ -3853,7 +3912,7 @@ msgstr "" " PSQL_EDITOR_LINENUMBER_ARG\n" " hur radnummer anges när redigerare startas\n" -#: help.c:550 +#: help.c:530 msgid "" " PSQL_HISTORY\n" " alternative location for the command history file\n" @@ -3861,7 +3920,7 @@ msgstr "" " PSQL_HISTORY\n" " alternativ plats för kommandohistorikfilen\n" -#: help.c:552 +#: help.c:532 msgid "" " PSQL_PAGER, PAGER\n" " name of external pager program\n" @@ -3869,7 +3928,7 @@ msgstr "" " PAGER\n" " namnet på den externa pageneraren\n" -#: help.c:555 +#: help.c:535 msgid "" " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" @@ -3877,7 +3936,7 @@ msgstr "" " PSQL_WATCH_PAGER\n" " namn på externt paginerarprogram för \\watch\n" -#: help.c:558 +#: help.c:538 msgid "" " PSQLRC\n" " alternative location for the user's .psqlrc file\n" @@ -3885,7 +3944,7 @@ msgstr "" " PSQLRC\n" " alternativ plats för användarens \".psqlrc\"-fil\n" -#: help.c:560 +#: help.c:540 msgid "" " SHELL\n" " shell used by the \\! command\n" @@ -3893,7 +3952,7 @@ msgstr "" " SHELL\n" " skalet som används av kommandot \\!\n" -#: help.c:562 +#: help.c:542 msgid "" " TMPDIR\n" " directory for temporary files\n" @@ -3901,11 +3960,11 @@ msgstr "" " TMPDIR\n" " katalog för temporärfiler\n" -#: help.c:622 +#: help.c:602 msgid "Available help:\n" msgstr "Tillgänglig hjälp:\n" -#: help.c:717 +#: help.c:697 #, c-format msgid "" "Command: %s\n" @@ -3924,7 +3983,7 @@ msgstr "" "URL: %s\n" "\n" -#: help.c:740 +#: help.c:720 #, c-format msgid "" "No help available for \"%s\".\n" @@ -3933,17 +3992,17 @@ msgstr "" "Ingen hjälp tillgänglig för \"%s\".\n" "Försök med \\h utan argument för att se den tillgängliga hjälpen.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "kunde inte läsa från infilen: %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "kunde inte skriva kommandohistorien till \"%s\": %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "historia stöds inte av denna installationen" @@ -4030,12 +4089,12 @@ msgstr "fråga ignorerat; använd \\endif eller Ctrl-C för att avsluta aktuellt msgid "reached EOF without finding closing \\endif(s)" msgstr "kom till EOF utan att hitta avslutande \\endif" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "icketerminerad citerad sträng" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s: slut på minne" @@ -4043,2427 +4102,2447 @@ msgstr "%s: slut på minne" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:238 -#: sql_help.c:240 sql_help.c:241 sql_help.c:243 sql_help.c:245 sql_help.c:248 -#: sql_help.c:250 sql_help.c:252 sql_help.c:254 sql_help.c:266 sql_help.c:267 -#: sql_help.c:268 sql_help.c:270 sql_help.c:319 sql_help.c:321 sql_help.c:323 -#: sql_help.c:325 sql_help.c:394 sql_help.c:399 sql_help.c:401 sql_help.c:443 -#: sql_help.c:445 sql_help.c:448 sql_help.c:450 sql_help.c:519 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:593 sql_help.c:595 -#: sql_help.c:597 sql_help.c:599 sql_help.c:601 sql_help.c:604 sql_help.c:606 -#: sql_help.c:609 sql_help.c:620 sql_help.c:622 sql_help.c:666 sql_help.c:668 -#: sql_help.c:670 sql_help.c:673 sql_help.c:675 sql_help.c:677 sql_help.c:714 -#: sql_help.c:718 sql_help.c:722 sql_help.c:741 sql_help.c:744 sql_help.c:747 -#: sql_help.c:776 sql_help.c:788 sql_help.c:796 sql_help.c:799 sql_help.c:802 -#: sql_help.c:817 sql_help.c:820 sql_help.c:849 sql_help.c:854 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:896 sql_help.c:898 sql_help.c:900 -#: sql_help.c:902 sql_help.c:905 sql_help.c:907 sql_help.c:954 sql_help.c:999 -#: sql_help.c:1004 sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 -#: sql_help.c:1038 sql_help.c:1049 sql_help.c:1051 sql_help.c:1071 -#: sql_help.c:1081 sql_help.c:1082 sql_help.c:1084 sql_help.c:1086 -#: sql_help.c:1098 sql_help.c:1102 sql_help.c:1104 sql_help.c:1116 -#: sql_help.c:1118 sql_help.c:1120 sql_help.c:1122 sql_help.c:1141 -#: sql_help.c:1143 sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 -#: sql_help.c:1158 sql_help.c:1159 sql_help.c:1160 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1168 sql_help.c:1308 sql_help.c:1310 -#: sql_help.c:1313 sql_help.c:1316 sql_help.c:1318 sql_help.c:1320 -#: sql_help.c:1323 sql_help.c:1326 sql_help.c:1443 sql_help.c:1445 -#: sql_help.c:1447 sql_help.c:1450 sql_help.c:1471 sql_help.c:1474 -#: sql_help.c:1477 sql_help.c:1480 sql_help.c:1484 sql_help.c:1486 -#: sql_help.c:1488 sql_help.c:1490 sql_help.c:1504 sql_help.c:1507 -#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1521 sql_help.c:1523 -#: sql_help.c:1533 sql_help.c:1535 sql_help.c:1545 sql_help.c:1548 -#: sql_help.c:1571 sql_help.c:1573 sql_help.c:1575 sql_help.c:1577 -#: sql_help.c:1580 sql_help.c:1582 sql_help.c:1585 sql_help.c:1588 -#: sql_help.c:1639 sql_help.c:1682 sql_help.c:1685 sql_help.c:1687 -#: sql_help.c:1689 sql_help.c:1692 sql_help.c:1694 sql_help.c:1696 -#: sql_help.c:1699 sql_help.c:1751 sql_help.c:1767 sql_help.c:2000 -#: sql_help.c:2069 sql_help.c:2088 sql_help.c:2101 sql_help.c:2159 -#: sql_help.c:2167 sql_help.c:2177 sql_help.c:2204 sql_help.c:2236 -#: sql_help.c:2254 sql_help.c:2282 sql_help.c:2393 sql_help.c:2439 -#: sql_help.c:2464 sql_help.c:2487 sql_help.c:2491 sql_help.c:2525 -#: sql_help.c:2545 sql_help.c:2567 sql_help.c:2581 sql_help.c:2602 -#: sql_help.c:2631 sql_help.c:2666 sql_help.c:2691 sql_help.c:2738 -#: sql_help.c:3033 sql_help.c:3046 sql_help.c:3063 sql_help.c:3079 -#: sql_help.c:3119 sql_help.c:3173 sql_help.c:3177 sql_help.c:3179 -#: sql_help.c:3186 sql_help.c:3205 sql_help.c:3232 sql_help.c:3267 -#: sql_help.c:3279 sql_help.c:3288 sql_help.c:3332 sql_help.c:3346 -#: sql_help.c:3374 sql_help.c:3382 sql_help.c:3394 sql_help.c:3404 -#: sql_help.c:3412 sql_help.c:3420 sql_help.c:3428 sql_help.c:3436 -#: sql_help.c:3445 sql_help.c:3456 sql_help.c:3464 sql_help.c:3472 -#: sql_help.c:3480 sql_help.c:3488 sql_help.c:3498 sql_help.c:3507 -#: sql_help.c:3516 sql_help.c:3524 sql_help.c:3534 sql_help.c:3545 -#: sql_help.c:3553 sql_help.c:3562 sql_help.c:3573 sql_help.c:3582 -#: sql_help.c:3590 sql_help.c:3598 sql_help.c:3606 sql_help.c:3614 -#: sql_help.c:3622 sql_help.c:3630 sql_help.c:3638 sql_help.c:3646 -#: sql_help.c:3654 sql_help.c:3662 sql_help.c:3679 sql_help.c:3688 -#: sql_help.c:3696 sql_help.c:3713 sql_help.c:3728 sql_help.c:4040 -#: sql_help.c:4150 sql_help.c:4179 sql_help.c:4195 sql_help.c:4197 -#: sql_help.c:4700 sql_help.c:4748 sql_help.c:4906 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:245 +#: sql_help.c:247 sql_help.c:248 sql_help.c:250 sql_help.c:252 sql_help.c:255 +#: sql_help.c:257 sql_help.c:259 sql_help.c:261 sql_help.c:276 sql_help.c:277 +#: sql_help.c:278 sql_help.c:280 sql_help.c:329 sql_help.c:331 sql_help.c:333 +#: sql_help.c:335 sql_help.c:404 sql_help.c:409 sql_help.c:411 sql_help.c:453 +#: sql_help.c:455 sql_help.c:458 sql_help.c:460 sql_help.c:529 sql_help.c:534 +#: sql_help.c:539 sql_help.c:544 sql_help.c:549 sql_help.c:603 sql_help.c:605 +#: sql_help.c:607 sql_help.c:609 sql_help.c:611 sql_help.c:614 sql_help.c:616 +#: sql_help.c:619 sql_help.c:630 sql_help.c:632 sql_help.c:676 sql_help.c:678 +#: sql_help.c:680 sql_help.c:683 sql_help.c:685 sql_help.c:687 sql_help.c:728 +#: sql_help.c:732 sql_help.c:736 sql_help.c:757 sql_help.c:760 sql_help.c:763 +#: sql_help.c:792 sql_help.c:804 sql_help.c:812 sql_help.c:815 sql_help.c:818 +#: sql_help.c:833 sql_help.c:836 sql_help.c:865 sql_help.c:870 sql_help.c:875 +#: sql_help.c:880 sql_help.c:885 sql_help.c:912 sql_help.c:914 sql_help.c:916 +#: sql_help.c:918 sql_help.c:921 sql_help.c:923 sql_help.c:970 sql_help.c:1015 +#: sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 sql_help.c:1035 +#: sql_help.c:1054 sql_help.c:1065 sql_help.c:1067 sql_help.c:1087 +#: sql_help.c:1097 sql_help.c:1098 sql_help.c:1100 sql_help.c:1102 +#: sql_help.c:1114 sql_help.c:1118 sql_help.c:1120 sql_help.c:1132 +#: sql_help.c:1134 sql_help.c:1136 sql_help.c:1138 sql_help.c:1157 +#: sql_help.c:1159 sql_help.c:1163 sql_help.c:1167 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1175 sql_help.c:1176 sql_help.c:1179 +#: sql_help.c:1182 sql_help.c:1184 sql_help.c:1324 sql_help.c:1326 +#: sql_help.c:1329 sql_help.c:1332 sql_help.c:1334 sql_help.c:1336 +#: sql_help.c:1339 sql_help.c:1342 sql_help.c:1464 sql_help.c:1466 +#: sql_help.c:1468 sql_help.c:1471 sql_help.c:1492 sql_help.c:1495 +#: sql_help.c:1498 sql_help.c:1501 sql_help.c:1505 sql_help.c:1507 +#: sql_help.c:1509 sql_help.c:1511 sql_help.c:1525 sql_help.c:1528 +#: sql_help.c:1530 sql_help.c:1532 sql_help.c:1542 sql_help.c:1544 +#: sql_help.c:1554 sql_help.c:1556 sql_help.c:1566 sql_help.c:1569 +#: sql_help.c:1592 sql_help.c:1594 sql_help.c:1596 sql_help.c:1598 +#: sql_help.c:1601 sql_help.c:1603 sql_help.c:1606 sql_help.c:1609 +#: sql_help.c:1660 sql_help.c:1703 sql_help.c:1706 sql_help.c:1708 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:1715 sql_help.c:1717 +#: sql_help.c:1720 sql_help.c:1770 sql_help.c:1786 sql_help.c:2019 +#: sql_help.c:2088 sql_help.c:2107 sql_help.c:2120 sql_help.c:2178 +#: sql_help.c:2186 sql_help.c:2196 sql_help.c:2224 sql_help.c:2257 +#: sql_help.c:2275 sql_help.c:2303 sql_help.c:2414 sql_help.c:2460 +#: sql_help.c:2485 sql_help.c:2508 sql_help.c:2512 sql_help.c:2546 +#: sql_help.c:2566 sql_help.c:2588 sql_help.c:2602 sql_help.c:2623 +#: sql_help.c:2652 sql_help.c:2685 sql_help.c:2708 sql_help.c:2755 +#: sql_help.c:3053 sql_help.c:3066 sql_help.c:3083 sql_help.c:3099 +#: sql_help.c:3139 sql_help.c:3193 sql_help.c:3197 sql_help.c:3199 +#: sql_help.c:3206 sql_help.c:3225 sql_help.c:3252 sql_help.c:3287 +#: sql_help.c:3299 sql_help.c:3308 sql_help.c:3352 sql_help.c:3366 +#: sql_help.c:3394 sql_help.c:3402 sql_help.c:3414 sql_help.c:3424 +#: sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 sql_help.c:3456 +#: sql_help.c:3465 sql_help.c:3476 sql_help.c:3484 sql_help.c:3492 +#: sql_help.c:3500 sql_help.c:3508 sql_help.c:3518 sql_help.c:3527 +#: sql_help.c:3536 sql_help.c:3544 sql_help.c:3554 sql_help.c:3565 +#: sql_help.c:3573 sql_help.c:3582 sql_help.c:3593 sql_help.c:3602 +#: sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 sql_help.c:3634 +#: sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 sql_help.c:3666 +#: sql_help.c:3674 sql_help.c:3682 sql_help.c:3699 sql_help.c:3708 +#: sql_help.c:3716 sql_help.c:3733 sql_help.c:3748 sql_help.c:4061 +#: sql_help.c:4182 sql_help.c:4211 sql_help.c:4227 sql_help.c:4229 +#: sql_help.c:4733 sql_help.c:4781 sql_help.c:4940 msgid "name" msgstr "namn" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:330 sql_help.c:1848 -#: sql_help.c:3347 sql_help.c:4468 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:340 sql_help.c:1863 +#: sql_help.c:3367 sql_help.c:4500 msgid "aggregate_signature" msgstr "aggregatsignatur" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:449 sql_help.c:528 sql_help.c:576 -#: sql_help.c:594 sql_help.c:621 sql_help.c:674 sql_help.c:743 sql_help.c:798 -#: sql_help.c:819 sql_help.c:858 sql_help.c:908 sql_help.c:955 sql_help.c:1008 -#: sql_help.c:1040 sql_help.c:1050 sql_help.c:1085 sql_help.c:1105 -#: sql_help.c:1119 sql_help.c:1169 sql_help.c:1317 sql_help.c:1444 -#: sql_help.c:1487 sql_help.c:1508 sql_help.c:1522 sql_help.c:1534 -#: sql_help.c:1547 sql_help.c:1574 sql_help.c:1640 sql_help.c:1693 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:260 +#: sql_help.c:281 sql_help.c:412 sql_help.c:459 sql_help.c:538 sql_help.c:586 +#: sql_help.c:604 sql_help.c:631 sql_help.c:684 sql_help.c:759 sql_help.c:814 +#: sql_help.c:835 sql_help.c:874 sql_help.c:924 sql_help.c:971 sql_help.c:1024 +#: sql_help.c:1056 sql_help.c:1066 sql_help.c:1101 sql_help.c:1121 +#: sql_help.c:1135 sql_help.c:1185 sql_help.c:1333 sql_help.c:1465 +#: sql_help.c:1508 sql_help.c:1529 sql_help.c:1543 sql_help.c:1555 +#: sql_help.c:1568 sql_help.c:1595 sql_help.c:1661 sql_help.c:1714 msgid "new_name" msgstr "nytt_namn" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:251 -#: sql_help.c:269 sql_help.c:400 sql_help.c:485 sql_help.c:533 sql_help.c:623 -#: sql_help.c:632 sql_help.c:697 sql_help.c:717 sql_help.c:746 sql_help.c:801 -#: sql_help.c:863 sql_help.c:906 sql_help.c:1013 sql_help.c:1052 -#: sql_help.c:1083 sql_help.c:1103 sql_help.c:1117 sql_help.c:1167 -#: sql_help.c:1381 sql_help.c:1446 sql_help.c:1489 sql_help.c:1510 -#: sql_help.c:1572 sql_help.c:1688 sql_help.c:3019 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:258 +#: sql_help.c:279 sql_help.c:410 sql_help.c:495 sql_help.c:543 sql_help.c:633 +#: sql_help.c:642 sql_help.c:707 sql_help.c:731 sql_help.c:762 sql_help.c:817 +#: sql_help.c:879 sql_help.c:922 sql_help.c:1029 sql_help.c:1068 +#: sql_help.c:1099 sql_help.c:1119 sql_help.c:1133 sql_help.c:1183 +#: sql_help.c:1399 sql_help.c:1467 sql_help.c:1510 sql_help.c:1531 +#: sql_help.c:1593 sql_help.c:1709 sql_help.c:3039 msgid "new_owner" msgstr "ny_ägare" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:255 sql_help.c:322 -#: sql_help.c:451 sql_help.c:538 sql_help.c:676 sql_help.c:721 sql_help.c:749 -#: sql_help.c:804 sql_help.c:868 sql_help.c:1018 sql_help.c:1087 -#: sql_help.c:1121 sql_help.c:1319 sql_help.c:1491 sql_help.c:1512 -#: sql_help.c:1524 sql_help.c:1536 sql_help.c:1576 sql_help.c:1695 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:262 sql_help.c:332 +#: sql_help.c:461 sql_help.c:548 sql_help.c:686 sql_help.c:735 sql_help.c:765 +#: sql_help.c:820 sql_help.c:884 sql_help.c:1034 sql_help.c:1103 +#: sql_help.c:1137 sql_help.c:1335 sql_help.c:1512 sql_help.c:1533 +#: sql_help.c:1545 sql_help.c:1557 sql_help.c:1597 sql_help.c:1716 msgid "new_schema" msgstr "nytt_schema" -#: sql_help.c:44 sql_help.c:1912 sql_help.c:3348 sql_help.c:4497 +#: sql_help.c:44 sql_help.c:1927 sql_help.c:3368 sql_help.c:4529 msgid "where aggregate_signature is:" msgstr "där aggregatsignatur är:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:340 sql_help.c:353 -#: sql_help.c:357 sql_help.c:373 sql_help.c:376 sql_help.c:379 sql_help.c:520 -#: sql_help.c:525 sql_help.c:530 sql_help.c:535 sql_help.c:540 sql_help.c:850 -#: sql_help.c:855 sql_help.c:860 sql_help.c:865 sql_help.c:870 sql_help.c:1000 -#: sql_help.c:1005 sql_help.c:1010 sql_help.c:1015 sql_help.c:1020 -#: sql_help.c:1866 sql_help.c:1883 sql_help.c:1889 sql_help.c:1913 -#: sql_help.c:1916 sql_help.c:1919 sql_help.c:2070 sql_help.c:2089 -#: sql_help.c:2092 sql_help.c:2394 sql_help.c:2603 sql_help.c:3349 -#: sql_help.c:3352 sql_help.c:3355 sql_help.c:3446 sql_help.c:3535 -#: sql_help.c:3563 sql_help.c:3915 sql_help.c:4367 sql_help.c:4474 -#: sql_help.c:4481 sql_help.c:4487 sql_help.c:4498 sql_help.c:4501 -#: sql_help.c:4504 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:350 sql_help.c:363 +#: sql_help.c:367 sql_help.c:383 sql_help.c:386 sql_help.c:389 sql_help.c:530 +#: sql_help.c:535 sql_help.c:540 sql_help.c:545 sql_help.c:550 sql_help.c:866 +#: sql_help.c:871 sql_help.c:876 sql_help.c:881 sql_help.c:886 sql_help.c:1016 +#: sql_help.c:1021 sql_help.c:1026 sql_help.c:1031 sql_help.c:1036 +#: sql_help.c:1881 sql_help.c:1898 sql_help.c:1904 sql_help.c:1928 +#: sql_help.c:1931 sql_help.c:1934 sql_help.c:2089 sql_help.c:2108 +#: sql_help.c:2111 sql_help.c:2415 sql_help.c:2624 sql_help.c:3369 +#: sql_help.c:3372 sql_help.c:3375 sql_help.c:3466 sql_help.c:3555 +#: sql_help.c:3583 sql_help.c:3936 sql_help.c:4399 sql_help.c:4506 +#: sql_help.c:4513 sql_help.c:4519 sql_help.c:4530 sql_help.c:4533 +#: sql_help.c:4536 msgid "argmode" msgstr "arg_läge" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:341 sql_help.c:354 -#: sql_help.c:358 sql_help.c:374 sql_help.c:377 sql_help.c:380 sql_help.c:521 -#: sql_help.c:526 sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:851 -#: sql_help.c:856 sql_help.c:861 sql_help.c:866 sql_help.c:871 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1867 sql_help.c:1884 sql_help.c:1890 sql_help.c:1914 -#: sql_help.c:1917 sql_help.c:1920 sql_help.c:2071 sql_help.c:2090 -#: sql_help.c:2093 sql_help.c:2395 sql_help.c:2604 sql_help.c:3350 -#: sql_help.c:3353 sql_help.c:3356 sql_help.c:3447 sql_help.c:3536 -#: sql_help.c:3564 sql_help.c:4475 sql_help.c:4482 sql_help.c:4488 -#: sql_help.c:4499 sql_help.c:4502 sql_help.c:4505 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:351 sql_help.c:364 +#: sql_help.c:368 sql_help.c:384 sql_help.c:387 sql_help.c:390 sql_help.c:531 +#: sql_help.c:536 sql_help.c:541 sql_help.c:546 sql_help.c:551 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:882 sql_help.c:887 sql_help.c:1017 +#: sql_help.c:1022 sql_help.c:1027 sql_help.c:1032 sql_help.c:1037 +#: sql_help.c:1882 sql_help.c:1899 sql_help.c:1905 sql_help.c:1929 +#: sql_help.c:1932 sql_help.c:1935 sql_help.c:2090 sql_help.c:2109 +#: sql_help.c:2112 sql_help.c:2416 sql_help.c:2625 sql_help.c:3370 +#: sql_help.c:3373 sql_help.c:3376 sql_help.c:3467 sql_help.c:3556 +#: sql_help.c:3584 sql_help.c:4507 sql_help.c:4514 sql_help.c:4520 +#: sql_help.c:4531 sql_help.c:4534 sql_help.c:4537 msgid "argname" msgstr "arg_namn" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1868 sql_help.c:1885 sql_help.c:1891 sql_help.c:1915 -#: sql_help.c:1918 sql_help.c:1921 sql_help.c:2396 sql_help.c:2605 -#: sql_help.c:3351 sql_help.c:3354 sql_help.c:3357 sql_help.c:3448 -#: sql_help.c:3537 sql_help.c:3565 sql_help.c:4476 sql_help.c:4483 -#: sql_help.c:4489 sql_help.c:4500 sql_help.c:4503 sql_help.c:4506 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:352 sql_help.c:365 +#: sql_help.c:369 sql_help.c:385 sql_help.c:388 sql_help.c:391 sql_help.c:532 +#: sql_help.c:537 sql_help.c:542 sql_help.c:547 sql_help.c:552 sql_help.c:868 +#: sql_help.c:873 sql_help.c:878 sql_help.c:883 sql_help.c:888 sql_help.c:1018 +#: sql_help.c:1023 sql_help.c:1028 sql_help.c:1033 sql_help.c:1038 +#: sql_help.c:1883 sql_help.c:1900 sql_help.c:1906 sql_help.c:1930 +#: sql_help.c:1933 sql_help.c:1936 sql_help.c:2417 sql_help.c:2626 +#: sql_help.c:3371 sql_help.c:3374 sql_help.c:3377 sql_help.c:3468 +#: sql_help.c:3557 sql_help.c:3585 sql_help.c:4508 sql_help.c:4515 +#: sql_help.c:4521 sql_help.c:4532 sql_help.c:4535 sql_help.c:4538 msgid "argtype" msgstr "arg_typ" -#: sql_help.c:114 sql_help.c:397 sql_help.c:474 sql_help.c:486 sql_help.c:949 -#: sql_help.c:1100 sql_help.c:1505 sql_help.c:1634 sql_help.c:1666 -#: sql_help.c:1719 sql_help.c:1783 sql_help.c:1970 sql_help.c:1977 -#: sql_help.c:2285 sql_help.c:2335 sql_help.c:2342 sql_help.c:2351 -#: sql_help.c:2440 sql_help.c:2667 sql_help.c:2760 sql_help.c:3048 -#: sql_help.c:3233 sql_help.c:3255 sql_help.c:3395 sql_help.c:3751 -#: sql_help.c:3959 sql_help.c:4194 sql_help.c:4196 sql_help.c:4973 +#: sql_help.c:114 sql_help.c:407 sql_help.c:484 sql_help.c:496 sql_help.c:965 +#: sql_help.c:1116 sql_help.c:1526 sql_help.c:1655 sql_help.c:1687 +#: sql_help.c:1739 sql_help.c:1798 sql_help.c:1987 sql_help.c:1994 +#: sql_help.c:2306 sql_help.c:2356 sql_help.c:2363 sql_help.c:2372 +#: sql_help.c:2461 sql_help.c:2686 sql_help.c:2777 sql_help.c:3068 +#: sql_help.c:3253 sql_help.c:3275 sql_help.c:3415 sql_help.c:3772 +#: sql_help.c:3980 sql_help.c:4226 sql_help.c:4228 sql_help.c:5006 msgid "option" msgstr "flaggor" -#: sql_help.c:115 sql_help.c:950 sql_help.c:1635 sql_help.c:2441 -#: sql_help.c:2668 sql_help.c:3234 sql_help.c:3396 +#: sql_help.c:115 sql_help.c:966 sql_help.c:1656 sql_help.c:2462 +#: sql_help.c:2687 sql_help.c:3254 sql_help.c:3416 msgid "where option can be:" msgstr "där flaggor kan vara:" -#: sql_help.c:116 sql_help.c:2217 +#: sql_help.c:116 sql_help.c:2238 msgid "allowconn" msgstr "tillåtansl" -#: sql_help.c:117 sql_help.c:951 sql_help.c:1636 sql_help.c:2218 -#: sql_help.c:2442 sql_help.c:2669 sql_help.c:3235 +#: sql_help.c:117 sql_help.c:967 sql_help.c:1657 sql_help.c:2239 +#: sql_help.c:2463 sql_help.c:2688 sql_help.c:3255 msgid "connlimit" msgstr "anslutningstak" -#: sql_help.c:118 sql_help.c:2219 +#: sql_help.c:118 sql_help.c:2240 msgid "istemplate" msgstr "ärmall" -#: sql_help.c:124 sql_help.c:611 sql_help.c:679 sql_help.c:693 sql_help.c:1322 -#: sql_help.c:1374 sql_help.c:4200 +#: sql_help.c:124 sql_help.c:621 sql_help.c:689 sql_help.c:703 sql_help.c:1338 +#: sql_help.c:1392 sql_help.c:4232 msgid "new_tablespace" msgstr "nytt_tabellutrymme" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:548 sql_help.c:550 -#: sql_help.c:551 sql_help.c:875 sql_help.c:877 sql_help.c:878 sql_help.c:958 -#: sql_help.c:962 sql_help.c:965 sql_help.c:1027 sql_help.c:1029 -#: sql_help.c:1030 sql_help.c:1180 sql_help.c:1183 sql_help.c:1643 -#: sql_help.c:1647 sql_help.c:1650 sql_help.c:2406 sql_help.c:2609 -#: sql_help.c:3927 sql_help.c:4218 sql_help.c:4379 sql_help.c:4688 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:558 sql_help.c:560 +#: sql_help.c:561 sql_help.c:891 sql_help.c:893 sql_help.c:894 sql_help.c:974 +#: sql_help.c:978 sql_help.c:981 sql_help.c:1043 sql_help.c:1045 +#: sql_help.c:1046 sql_help.c:1196 sql_help.c:1198 sql_help.c:1664 +#: sql_help.c:1668 sql_help.c:1671 sql_help.c:2427 sql_help.c:2630 +#: sql_help.c:3948 sql_help.c:4250 sql_help.c:4411 sql_help.c:4721 msgid "configuration_parameter" msgstr "konfigurationsparameter" -#: sql_help.c:128 sql_help.c:398 sql_help.c:469 sql_help.c:475 sql_help.c:487 -#: sql_help.c:549 sql_help.c:603 sql_help.c:685 sql_help.c:695 sql_help.c:876 -#: sql_help.c:904 sql_help.c:959 sql_help.c:1028 sql_help.c:1101 -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:1157 -#: sql_help.c:1162 sql_help.c:1165 sql_help.c:1181 sql_help.c:1182 -#: sql_help.c:1353 sql_help.c:1376 sql_help.c:1424 sql_help.c:1449 -#: sql_help.c:1506 sql_help.c:1590 sql_help.c:1644 sql_help.c:1667 -#: sql_help.c:2286 sql_help.c:2336 sql_help.c:2343 sql_help.c:2352 -#: sql_help.c:2407 sql_help.c:2408 sql_help.c:2472 sql_help.c:2475 -#: sql_help.c:2509 sql_help.c:2610 sql_help.c:2611 sql_help.c:2634 -#: sql_help.c:2761 sql_help.c:2800 sql_help.c:2910 sql_help.c:2923 -#: sql_help.c:2937 sql_help.c:2978 sql_help.c:3005 sql_help.c:3022 -#: sql_help.c:3049 sql_help.c:3256 sql_help.c:3960 sql_help.c:4689 -#: sql_help.c:4690 sql_help.c:4691 sql_help.c:4692 +#: sql_help.c:128 sql_help.c:408 sql_help.c:479 sql_help.c:485 sql_help.c:497 +#: sql_help.c:559 sql_help.c:613 sql_help.c:695 sql_help.c:705 sql_help.c:892 +#: sql_help.c:920 sql_help.c:975 sql_help.c:1044 sql_help.c:1117 +#: sql_help.c:1162 sql_help.c:1166 sql_help.c:1170 sql_help.c:1173 +#: sql_help.c:1178 sql_help.c:1181 sql_help.c:1197 sql_help.c:1371 +#: sql_help.c:1394 sql_help.c:1442 sql_help.c:1450 sql_help.c:1470 +#: sql_help.c:1527 sql_help.c:1611 sql_help.c:1665 sql_help.c:1688 +#: sql_help.c:2307 sql_help.c:2357 sql_help.c:2364 sql_help.c:2373 +#: sql_help.c:2428 sql_help.c:2429 sql_help.c:2493 sql_help.c:2496 +#: sql_help.c:2530 sql_help.c:2631 sql_help.c:2632 sql_help.c:2655 +#: sql_help.c:2778 sql_help.c:2817 sql_help.c:2927 sql_help.c:2940 +#: sql_help.c:2954 sql_help.c:2995 sql_help.c:3003 sql_help.c:3025 +#: sql_help.c:3042 sql_help.c:3069 sql_help.c:3276 sql_help.c:3981 +#: sql_help.c:4722 sql_help.c:4723 sql_help.c:4724 sql_help.c:4725 msgid "value" msgstr "värde" -#: sql_help.c:200 +#: sql_help.c:202 msgid "target_role" msgstr "målroll" -#: sql_help.c:201 sql_help.c:913 sql_help.c:2270 sql_help.c:2639 -#: sql_help.c:2716 sql_help.c:2721 sql_help.c:3890 sql_help.c:3899 -#: sql_help.c:3918 sql_help.c:3930 sql_help.c:4342 sql_help.c:4351 -#: sql_help.c:4370 sql_help.c:4382 +#: sql_help.c:203 sql_help.c:929 sql_help.c:2291 sql_help.c:2660 +#: sql_help.c:2733 sql_help.c:2738 sql_help.c:3911 sql_help.c:3920 +#: sql_help.c:3939 sql_help.c:3951 sql_help.c:4374 sql_help.c:4383 +#: sql_help.c:4402 sql_help.c:4414 msgid "schema_name" msgstr "schemanamn" -#: sql_help.c:202 +#: sql_help.c:204 msgid "abbreviated_grant_or_revoke" msgstr "förkortad_grant_eller_revoke" -#: sql_help.c:203 +#: sql_help.c:205 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "där förkortad_grant_eller_revok är en av:" -#: sql_help.c:204 sql_help.c:205 sql_help.c:206 sql_help.c:207 sql_help.c:208 -#: sql_help.c:209 sql_help.c:210 sql_help.c:211 sql_help.c:212 sql_help.c:213 -#: sql_help.c:574 sql_help.c:610 sql_help.c:678 sql_help.c:822 sql_help.c:969 -#: sql_help.c:1321 sql_help.c:1654 sql_help.c:2445 sql_help.c:2446 -#: sql_help.c:2447 sql_help.c:2448 sql_help.c:2449 sql_help.c:2583 -#: sql_help.c:2672 sql_help.c:2673 sql_help.c:2674 sql_help.c:2675 -#: sql_help.c:2676 sql_help.c:3238 sql_help.c:3239 sql_help.c:3240 -#: sql_help.c:3241 sql_help.c:3242 sql_help.c:3939 sql_help.c:3943 -#: sql_help.c:4391 sql_help.c:4395 sql_help.c:4710 +#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 +#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 +#: sql_help.c:584 sql_help.c:620 sql_help.c:688 sql_help.c:838 sql_help.c:985 +#: sql_help.c:1337 sql_help.c:1675 sql_help.c:2466 sql_help.c:2467 +#: sql_help.c:2468 sql_help.c:2469 sql_help.c:2470 sql_help.c:2604 +#: sql_help.c:2691 sql_help.c:2692 sql_help.c:2693 sql_help.c:3258 +#: sql_help.c:3259 sql_help.c:3260 sql_help.c:3261 sql_help.c:3262 +#: sql_help.c:3960 sql_help.c:3964 sql_help.c:4423 sql_help.c:4427 +#: sql_help.c:4743 msgid "role_name" msgstr "rollnamn" -#: sql_help.c:239 sql_help.c:462 sql_help.c:912 sql_help.c:1337 sql_help.c:1339 -#: sql_help.c:1391 sql_help.c:1403 sql_help.c:1428 sql_help.c:1684 -#: sql_help.c:2239 sql_help.c:2243 sql_help.c:2355 sql_help.c:2360 -#: sql_help.c:2468 sql_help.c:2638 sql_help.c:2777 sql_help.c:2782 -#: sql_help.c:2784 sql_help.c:2905 sql_help.c:2918 sql_help.c:2932 -#: sql_help.c:2941 sql_help.c:2953 sql_help.c:2982 sql_help.c:3991 -#: sql_help.c:4006 sql_help.c:4008 sql_help.c:4095 sql_help.c:4098 -#: sql_help.c:4100 sql_help.c:4561 sql_help.c:4562 sql_help.c:4571 -#: sql_help.c:4618 sql_help.c:4619 sql_help.c:4620 sql_help.c:4621 -#: sql_help.c:4622 sql_help.c:4623 sql_help.c:4663 sql_help.c:4664 -#: sql_help.c:4669 sql_help.c:4674 sql_help.c:4818 sql_help.c:4819 -#: sql_help.c:4828 sql_help.c:4875 sql_help.c:4876 sql_help.c:4877 -#: sql_help.c:4878 sql_help.c:4879 sql_help.c:4880 sql_help.c:4934 -#: sql_help.c:4936 sql_help.c:5004 sql_help.c:5064 sql_help.c:5065 -#: sql_help.c:5074 sql_help.c:5121 sql_help.c:5122 sql_help.c:5123 -#: sql_help.c:5124 sql_help.c:5125 sql_help.c:5126 +#: sql_help.c:246 sql_help.c:265 sql_help.c:472 sql_help.c:928 sql_help.c:1353 +#: sql_help.c:1355 sql_help.c:1359 sql_help.c:1409 sql_help.c:1421 +#: sql_help.c:1446 sql_help.c:1705 sql_help.c:2260 sql_help.c:2264 +#: sql_help.c:2376 sql_help.c:2381 sql_help.c:2489 sql_help.c:2659 +#: sql_help.c:2794 sql_help.c:2799 sql_help.c:2801 sql_help.c:2922 +#: sql_help.c:2935 sql_help.c:2949 sql_help.c:2958 sql_help.c:2970 +#: sql_help.c:2999 sql_help.c:4012 sql_help.c:4027 sql_help.c:4029 +#: sql_help.c:4125 sql_help.c:4128 sql_help.c:4130 sql_help.c:4593 +#: sql_help.c:4594 sql_help.c:4603 sql_help.c:4650 sql_help.c:4651 +#: sql_help.c:4652 sql_help.c:4653 sql_help.c:4654 sql_help.c:4655 +#: sql_help.c:4696 sql_help.c:4697 sql_help.c:4702 sql_help.c:4707 +#: sql_help.c:4851 sql_help.c:4852 sql_help.c:4861 sql_help.c:4908 +#: sql_help.c:4909 sql_help.c:4910 sql_help.c:4911 sql_help.c:4912 +#: sql_help.c:4913 sql_help.c:4968 sql_help.c:4970 sql_help.c:5036 +#: sql_help.c:5096 sql_help.c:5097 sql_help.c:5106 sql_help.c:5153 +#: sql_help.c:5154 sql_help.c:5155 sql_help.c:5156 sql_help.c:5157 +#: sql_help.c:5158 msgid "expression" msgstr "uttryck" -#: sql_help.c:242 +#: sql_help.c:249 sql_help.c:2261 msgid "domain_constraint" msgstr "domain_villkor" -#: sql_help.c:244 sql_help.c:246 sql_help.c:249 sql_help.c:477 sql_help.c:478 -#: sql_help.c:1314 sql_help.c:1361 sql_help.c:1362 sql_help.c:1363 -#: sql_help.c:1390 sql_help.c:1402 sql_help.c:1419 sql_help.c:1854 -#: sql_help.c:1856 sql_help.c:2242 sql_help.c:2354 sql_help.c:2359 -#: sql_help.c:2940 sql_help.c:2952 sql_help.c:4003 +#: sql_help.c:251 sql_help.c:253 sql_help.c:256 sql_help.c:264 sql_help.c:487 +#: sql_help.c:488 sql_help.c:1330 sql_help.c:1379 sql_help.c:1380 +#: sql_help.c:1381 sql_help.c:1408 sql_help.c:1420 sql_help.c:1437 +#: sql_help.c:1869 sql_help.c:1871 sql_help.c:2263 sql_help.c:2375 +#: sql_help.c:2380 sql_help.c:2957 sql_help.c:2969 sql_help.c:4024 msgid "constraint_name" msgstr "villkorsnamn" -#: sql_help.c:247 sql_help.c:1315 +#: sql_help.c:254 sql_help.c:1331 msgid "new_constraint_name" msgstr "nyy_villkorsnamn" -#: sql_help.c:320 sql_help.c:1099 +#: sql_help.c:263 sql_help.c:2262 +msgid "where domain_constraint is:" +msgstr "där domän_villkor är:" + +#: sql_help.c:330 sql_help.c:1115 msgid "new_version" msgstr "ny_version" -#: sql_help.c:324 sql_help.c:326 +#: sql_help.c:334 sql_help.c:336 msgid "member_object" msgstr "medlemsobjekt" -#: sql_help.c:327 +#: sql_help.c:337 msgid "where member_object is:" msgstr "där medlemsobjekt är:" -#: sql_help.c:328 sql_help.c:333 sql_help.c:334 sql_help.c:335 sql_help.c:336 -#: sql_help.c:337 sql_help.c:338 sql_help.c:343 sql_help.c:347 sql_help.c:349 -#: sql_help.c:351 sql_help.c:360 sql_help.c:361 sql_help.c:362 sql_help.c:363 -#: sql_help.c:364 sql_help.c:365 sql_help.c:366 sql_help.c:367 sql_help.c:370 -#: sql_help.c:371 sql_help.c:1846 sql_help.c:1851 sql_help.c:1858 -#: sql_help.c:1859 sql_help.c:1860 sql_help.c:1861 sql_help.c:1862 -#: sql_help.c:1863 sql_help.c:1864 sql_help.c:1869 sql_help.c:1871 -#: sql_help.c:1875 sql_help.c:1877 sql_help.c:1881 sql_help.c:1886 -#: sql_help.c:1887 sql_help.c:1894 sql_help.c:1895 sql_help.c:1896 -#: sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 sql_help.c:1900 -#: sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 sql_help.c:1904 -#: sql_help.c:1909 sql_help.c:1910 sql_help.c:4464 sql_help.c:4469 -#: sql_help.c:4470 sql_help.c:4471 sql_help.c:4472 sql_help.c:4478 -#: sql_help.c:4479 sql_help.c:4484 sql_help.c:4485 sql_help.c:4490 -#: sql_help.c:4491 sql_help.c:4492 sql_help.c:4493 sql_help.c:4494 -#: sql_help.c:4495 +#: sql_help.c:338 sql_help.c:343 sql_help.c:344 sql_help.c:345 sql_help.c:346 +#: sql_help.c:347 sql_help.c:348 sql_help.c:353 sql_help.c:357 sql_help.c:359 +#: sql_help.c:361 sql_help.c:370 sql_help.c:371 sql_help.c:372 sql_help.c:373 +#: sql_help.c:374 sql_help.c:375 sql_help.c:376 sql_help.c:377 sql_help.c:380 +#: sql_help.c:381 sql_help.c:1861 sql_help.c:1866 sql_help.c:1873 +#: sql_help.c:1874 sql_help.c:1875 sql_help.c:1876 sql_help.c:1877 +#: sql_help.c:1878 sql_help.c:1879 sql_help.c:1884 sql_help.c:1886 +#: sql_help.c:1890 sql_help.c:1892 sql_help.c:1896 sql_help.c:1901 +#: sql_help.c:1902 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1912 sql_help.c:1913 sql_help.c:1914 sql_help.c:1915 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:1918 sql_help.c:1919 +#: sql_help.c:1924 sql_help.c:1925 sql_help.c:4496 sql_help.c:4501 +#: sql_help.c:4502 sql_help.c:4503 sql_help.c:4504 sql_help.c:4510 +#: sql_help.c:4511 sql_help.c:4516 sql_help.c:4517 sql_help.c:4522 +#: sql_help.c:4523 sql_help.c:4524 sql_help.c:4525 sql_help.c:4526 +#: sql_help.c:4527 msgid "object_name" msgstr "objektnamn" -#: sql_help.c:329 sql_help.c:1847 sql_help.c:4467 +#: sql_help.c:339 sql_help.c:1862 sql_help.c:4499 msgid "aggregate_name" msgstr "aggregatnamn" -#: sql_help.c:331 sql_help.c:1849 sql_help.c:2135 sql_help.c:2139 -#: sql_help.c:2141 sql_help.c:3365 +#: sql_help.c:341 sql_help.c:1864 sql_help.c:2154 sql_help.c:2158 +#: sql_help.c:2160 sql_help.c:3385 msgid "source_type" msgstr "källtyp" -#: sql_help.c:332 sql_help.c:1850 sql_help.c:2136 sql_help.c:2140 -#: sql_help.c:2142 sql_help.c:3366 +#: sql_help.c:342 sql_help.c:1865 sql_help.c:2155 sql_help.c:2159 +#: sql_help.c:2161 sql_help.c:3386 msgid "target_type" msgstr "måltyp" -#: sql_help.c:339 sql_help.c:786 sql_help.c:1865 sql_help.c:2137 -#: sql_help.c:2180 sql_help.c:2258 sql_help.c:2526 sql_help.c:2557 -#: sql_help.c:3125 sql_help.c:4366 sql_help.c:4473 sql_help.c:4590 -#: sql_help.c:4594 sql_help.c:4598 sql_help.c:4601 sql_help.c:4847 -#: sql_help.c:4851 sql_help.c:4855 sql_help.c:4858 sql_help.c:5093 -#: sql_help.c:5097 sql_help.c:5101 sql_help.c:5104 +#: sql_help.c:349 sql_help.c:802 sql_help.c:1880 sql_help.c:2156 +#: sql_help.c:2199 sql_help.c:2279 sql_help.c:2547 sql_help.c:2578 +#: sql_help.c:3145 sql_help.c:4398 sql_help.c:4505 sql_help.c:4622 +#: sql_help.c:4626 sql_help.c:4630 sql_help.c:4633 sql_help.c:4880 +#: sql_help.c:4884 sql_help.c:4888 sql_help.c:4891 sql_help.c:5125 +#: sql_help.c:5129 sql_help.c:5133 sql_help.c:5136 msgid "function_name" msgstr "funktionsnamn" -#: sql_help.c:344 sql_help.c:779 sql_help.c:1872 sql_help.c:2550 +#: sql_help.c:354 sql_help.c:795 sql_help.c:1887 sql_help.c:2571 msgid "operator_name" msgstr "operatornamn" -#: sql_help.c:345 sql_help.c:715 sql_help.c:719 sql_help.c:723 sql_help.c:1873 -#: sql_help.c:2527 sql_help.c:3489 +#: sql_help.c:355 sql_help.c:729 sql_help.c:733 sql_help.c:737 sql_help.c:1888 +#: sql_help.c:2548 sql_help.c:3509 msgid "left_type" msgstr "vänster_typ" -#: sql_help.c:346 sql_help.c:716 sql_help.c:720 sql_help.c:724 sql_help.c:1874 -#: sql_help.c:2528 sql_help.c:3490 +#: sql_help.c:356 sql_help.c:730 sql_help.c:734 sql_help.c:738 sql_help.c:1889 +#: sql_help.c:2549 sql_help.c:3510 msgid "right_type" msgstr "höger_typ" -#: sql_help.c:348 sql_help.c:350 sql_help.c:742 sql_help.c:745 sql_help.c:748 -#: sql_help.c:777 sql_help.c:789 sql_help.c:797 sql_help.c:800 sql_help.c:803 -#: sql_help.c:1408 sql_help.c:1876 sql_help.c:1878 sql_help.c:2547 -#: sql_help.c:2568 sql_help.c:2958 sql_help.c:3499 sql_help.c:3508 +#: sql_help.c:358 sql_help.c:360 sql_help.c:758 sql_help.c:761 sql_help.c:764 +#: sql_help.c:793 sql_help.c:805 sql_help.c:813 sql_help.c:816 sql_help.c:819 +#: sql_help.c:1426 sql_help.c:1891 sql_help.c:1893 sql_help.c:2568 +#: sql_help.c:2589 sql_help.c:2975 sql_help.c:3519 sql_help.c:3528 msgid "index_method" msgstr "indexmetod" -#: sql_help.c:352 sql_help.c:1882 sql_help.c:4480 +#: sql_help.c:362 sql_help.c:1897 sql_help.c:4512 msgid "procedure_name" msgstr "procedurnamn" -#: sql_help.c:356 sql_help.c:1888 sql_help.c:3914 sql_help.c:4486 +#: sql_help.c:366 sql_help.c:1903 sql_help.c:3935 sql_help.c:4518 msgid "routine_name" msgstr "rutinnamn" -#: sql_help.c:368 sql_help.c:1380 sql_help.c:1905 sql_help.c:2402 -#: sql_help.c:2608 sql_help.c:2913 sql_help.c:3092 sql_help.c:3670 -#: sql_help.c:3936 sql_help.c:4388 +#: sql_help.c:378 sql_help.c:1398 sql_help.c:1920 sql_help.c:2423 +#: sql_help.c:2629 sql_help.c:2930 sql_help.c:3112 sql_help.c:3690 +#: sql_help.c:3957 sql_help.c:4420 msgid "type_name" msgstr "typnamn" -#: sql_help.c:369 sql_help.c:1906 sql_help.c:2401 sql_help.c:2607 -#: sql_help.c:3093 sql_help.c:3323 sql_help.c:3671 sql_help.c:3921 -#: sql_help.c:4373 +#: sql_help.c:379 sql_help.c:1921 sql_help.c:2422 sql_help.c:2628 +#: sql_help.c:3113 sql_help.c:3343 sql_help.c:3691 sql_help.c:3942 +#: sql_help.c:4405 msgid "lang_name" msgstr "språknamn" -#: sql_help.c:372 +#: sql_help.c:382 msgid "and aggregate_signature is:" msgstr "och aggregatsignatur är:" -#: sql_help.c:395 sql_help.c:2002 sql_help.c:2283 +#: sql_help.c:405 sql_help.c:2021 sql_help.c:2304 msgid "handler_function" msgstr "hanterarfunktion" -#: sql_help.c:396 sql_help.c:2284 +#: sql_help.c:406 sql_help.c:2305 msgid "validator_function" msgstr "valideringsfunktion" -#: sql_help.c:444 sql_help.c:523 sql_help.c:667 sql_help.c:853 sql_help.c:1003 -#: sql_help.c:1309 sql_help.c:1581 +#: sql_help.c:454 sql_help.c:533 sql_help.c:677 sql_help.c:869 sql_help.c:1019 +#: sql_help.c:1325 sql_help.c:1602 msgid "action" msgstr "aktion" -#: sql_help.c:446 sql_help.c:453 sql_help.c:457 sql_help.c:458 sql_help.c:461 -#: sql_help.c:463 sql_help.c:464 sql_help.c:465 sql_help.c:467 sql_help.c:470 -#: sql_help.c:472 sql_help.c:473 sql_help.c:671 sql_help.c:681 sql_help.c:683 -#: sql_help.c:686 sql_help.c:688 sql_help.c:689 sql_help.c:911 sql_help.c:1080 -#: sql_help.c:1311 sql_help.c:1329 sql_help.c:1333 sql_help.c:1334 -#: sql_help.c:1338 sql_help.c:1340 sql_help.c:1341 sql_help.c:1342 -#: sql_help.c:1343 sql_help.c:1345 sql_help.c:1348 sql_help.c:1349 -#: sql_help.c:1351 sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 -#: sql_help.c:1404 sql_help.c:1406 sql_help.c:1413 sql_help.c:1422 -#: sql_help.c:1427 sql_help.c:1431 sql_help.c:1432 sql_help.c:1683 -#: sql_help.c:1686 sql_help.c:1690 sql_help.c:1728 sql_help.c:1853 -#: sql_help.c:1967 sql_help.c:1973 sql_help.c:1987 sql_help.c:1988 -#: sql_help.c:1989 sql_help.c:2333 sql_help.c:2346 sql_help.c:2399 -#: sql_help.c:2467 sql_help.c:2473 sql_help.c:2506 sql_help.c:2637 -#: sql_help.c:2746 sql_help.c:2781 sql_help.c:2783 sql_help.c:2895 -#: sql_help.c:2904 sql_help.c:2914 sql_help.c:2917 sql_help.c:2927 -#: sql_help.c:2931 sql_help.c:2954 sql_help.c:2956 sql_help.c:2963 -#: sql_help.c:2976 sql_help.c:2981 sql_help.c:2985 sql_help.c:2986 -#: sql_help.c:3002 sql_help.c:3128 sql_help.c:3268 sql_help.c:3893 -#: sql_help.c:3894 sql_help.c:3990 sql_help.c:4005 sql_help.c:4007 -#: sql_help.c:4009 sql_help.c:4094 sql_help.c:4097 sql_help.c:4099 -#: sql_help.c:4345 sql_help.c:4346 sql_help.c:4466 sql_help.c:4627 -#: sql_help.c:4633 sql_help.c:4635 sql_help.c:4884 sql_help.c:4890 -#: sql_help.c:4892 sql_help.c:4933 sql_help.c:4935 sql_help.c:4937 -#: sql_help.c:4992 sql_help.c:5130 sql_help.c:5136 sql_help.c:5138 +#: sql_help.c:456 sql_help.c:463 sql_help.c:467 sql_help.c:468 sql_help.c:471 +#: sql_help.c:473 sql_help.c:474 sql_help.c:475 sql_help.c:477 sql_help.c:480 +#: sql_help.c:482 sql_help.c:483 sql_help.c:681 sql_help.c:691 sql_help.c:693 +#: sql_help.c:696 sql_help.c:698 sql_help.c:699 sql_help.c:927 sql_help.c:1096 +#: sql_help.c:1327 sql_help.c:1345 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1354 sql_help.c:1356 sql_help.c:1357 sql_help.c:1358 +#: sql_help.c:1360 sql_help.c:1361 sql_help.c:1363 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1369 sql_help.c:1372 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1422 sql_help.c:1424 sql_help.c:1431 +#: sql_help.c:1440 sql_help.c:1445 sql_help.c:1452 sql_help.c:1453 +#: sql_help.c:1704 sql_help.c:1707 sql_help.c:1711 sql_help.c:1747 +#: sql_help.c:1868 sql_help.c:1984 sql_help.c:1990 sql_help.c:2004 +#: sql_help.c:2005 sql_help.c:2006 sql_help.c:2354 sql_help.c:2367 +#: sql_help.c:2420 sql_help.c:2488 sql_help.c:2494 sql_help.c:2527 +#: sql_help.c:2658 sql_help.c:2763 sql_help.c:2798 sql_help.c:2800 +#: sql_help.c:2912 sql_help.c:2921 sql_help.c:2931 sql_help.c:2934 +#: sql_help.c:2944 sql_help.c:2948 sql_help.c:2971 sql_help.c:2973 +#: sql_help.c:2980 sql_help.c:2993 sql_help.c:2998 sql_help.c:3005 +#: sql_help.c:3006 sql_help.c:3022 sql_help.c:3148 sql_help.c:3288 +#: sql_help.c:3914 sql_help.c:3915 sql_help.c:4011 sql_help.c:4026 +#: sql_help.c:4028 sql_help.c:4030 sql_help.c:4124 sql_help.c:4127 +#: sql_help.c:4129 sql_help.c:4131 sql_help.c:4377 sql_help.c:4378 +#: sql_help.c:4498 sql_help.c:4659 sql_help.c:4666 sql_help.c:4668 +#: sql_help.c:4917 sql_help.c:4924 sql_help.c:4926 sql_help.c:4967 +#: sql_help.c:4969 sql_help.c:4971 sql_help.c:5024 sql_help.c:5162 +#: sql_help.c:5169 sql_help.c:5171 msgid "column_name" msgstr "kolumnnamn" -#: sql_help.c:447 sql_help.c:672 sql_help.c:1312 sql_help.c:1691 +#: sql_help.c:457 sql_help.c:682 sql_help.c:1328 sql_help.c:1712 msgid "new_column_name" msgstr "nytt_kolumnnamn" -#: sql_help.c:452 sql_help.c:544 sql_help.c:680 sql_help.c:874 sql_help.c:1024 -#: sql_help.c:1328 sql_help.c:1591 +#: sql_help.c:462 sql_help.c:554 sql_help.c:690 sql_help.c:890 sql_help.c:1040 +#: sql_help.c:1344 sql_help.c:1612 msgid "where action is one of:" msgstr "där aktion är en av:" -#: sql_help.c:454 sql_help.c:459 sql_help.c:1072 sql_help.c:1330 -#: sql_help.c:1335 sql_help.c:1593 sql_help.c:1597 sql_help.c:2237 -#: sql_help.c:2334 sql_help.c:2546 sql_help.c:2739 sql_help.c:2896 -#: sql_help.c:3175 sql_help.c:4151 +#: sql_help.c:464 sql_help.c:469 sql_help.c:1088 sql_help.c:1346 +#: sql_help.c:1351 sql_help.c:1614 sql_help.c:1618 sql_help.c:2258 +#: sql_help.c:2355 sql_help.c:2567 sql_help.c:2756 sql_help.c:2913 +#: sql_help.c:3195 sql_help.c:4183 msgid "data_type" msgstr "datatyp" -#: sql_help.c:455 sql_help.c:460 sql_help.c:1331 sql_help.c:1336 -#: sql_help.c:1594 sql_help.c:1598 sql_help.c:2238 sql_help.c:2337 -#: sql_help.c:2469 sql_help.c:2898 sql_help.c:2906 sql_help.c:2919 -#: sql_help.c:2933 sql_help.c:3176 sql_help.c:3182 sql_help.c:4000 +#: sql_help.c:465 sql_help.c:470 sql_help.c:1347 sql_help.c:1352 +#: sql_help.c:1447 sql_help.c:1615 sql_help.c:1619 sql_help.c:2259 +#: sql_help.c:2358 sql_help.c:2490 sql_help.c:2915 sql_help.c:2923 +#: sql_help.c:2936 sql_help.c:2950 sql_help.c:3000 sql_help.c:3196 +#: sql_help.c:3202 sql_help.c:4021 msgid "collation" msgstr "jämförelse" -#: sql_help.c:456 sql_help.c:1332 sql_help.c:2338 sql_help.c:2347 -#: sql_help.c:2899 sql_help.c:2915 sql_help.c:2928 +#: sql_help.c:466 sql_help.c:1348 sql_help.c:2359 sql_help.c:2368 +#: sql_help.c:2916 sql_help.c:2932 sql_help.c:2945 msgid "column_constraint" msgstr "kolumnvillkor" -#: sql_help.c:466 sql_help.c:608 sql_help.c:682 sql_help.c:1350 sql_help.c:4986 +#: sql_help.c:476 sql_help.c:618 sql_help.c:692 sql_help.c:1368 sql_help.c:5018 msgid "integer" msgstr "heltal" -#: sql_help.c:468 sql_help.c:471 sql_help.c:684 sql_help.c:687 sql_help.c:1352 -#: sql_help.c:1355 +#: sql_help.c:478 sql_help.c:481 sql_help.c:694 sql_help.c:697 sql_help.c:1370 +#: sql_help.c:1373 msgid "attribute_option" msgstr "attributalternativ" -#: sql_help.c:476 sql_help.c:1359 sql_help.c:2339 sql_help.c:2348 -#: sql_help.c:2900 sql_help.c:2916 sql_help.c:2929 +#: sql_help.c:486 sql_help.c:1377 sql_help.c:2360 sql_help.c:2369 +#: sql_help.c:2917 sql_help.c:2933 sql_help.c:2946 msgid "table_constraint" msgstr "tabellvillkor" -#: sql_help.c:479 sql_help.c:480 sql_help.c:481 sql_help.c:482 sql_help.c:1364 -#: sql_help.c:1365 sql_help.c:1366 sql_help.c:1367 sql_help.c:1907 +#: sql_help.c:489 sql_help.c:490 sql_help.c:491 sql_help.c:492 sql_help.c:1382 +#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:1922 msgid "trigger_name" msgstr "triggernamn" -#: sql_help.c:483 sql_help.c:484 sql_help.c:1378 sql_help.c:1379 -#: sql_help.c:2340 sql_help.c:2345 sql_help.c:2903 sql_help.c:2926 +#: sql_help.c:493 sql_help.c:494 sql_help.c:1396 sql_help.c:1397 +#: sql_help.c:2361 sql_help.c:2366 sql_help.c:2920 sql_help.c:2943 msgid "parent_table" msgstr "föräldertabell" -#: sql_help.c:543 sql_help.c:600 sql_help.c:669 sql_help.c:873 sql_help.c:1023 -#: sql_help.c:1550 sql_help.c:2269 +#: sql_help.c:553 sql_help.c:610 sql_help.c:679 sql_help.c:889 sql_help.c:1039 +#: sql_help.c:1571 sql_help.c:2290 msgid "extension_name" msgstr "utökningsnamn" -#: sql_help.c:545 sql_help.c:1025 sql_help.c:2403 +#: sql_help.c:555 sql_help.c:1041 sql_help.c:2424 msgid "execution_cost" msgstr "körkostnad" -#: sql_help.c:546 sql_help.c:1026 sql_help.c:2404 +#: sql_help.c:556 sql_help.c:1042 sql_help.c:2425 msgid "result_rows" msgstr "resultatrader" -#: sql_help.c:547 sql_help.c:2405 +#: sql_help.c:557 sql_help.c:2426 msgid "support_function" msgstr "supportfunktion" -#: sql_help.c:569 sql_help.c:571 sql_help.c:948 sql_help.c:956 sql_help.c:960 -#: sql_help.c:963 sql_help.c:966 sql_help.c:1633 sql_help.c:1641 -#: sql_help.c:1645 sql_help.c:1648 sql_help.c:1651 sql_help.c:2717 -#: sql_help.c:2719 sql_help.c:2722 sql_help.c:2723 sql_help.c:3891 -#: sql_help.c:3892 sql_help.c:3896 sql_help.c:3897 sql_help.c:3900 -#: sql_help.c:3901 sql_help.c:3903 sql_help.c:3904 sql_help.c:3906 -#: sql_help.c:3907 sql_help.c:3909 sql_help.c:3910 sql_help.c:3912 -#: sql_help.c:3913 sql_help.c:3919 sql_help.c:3920 sql_help.c:3922 -#: sql_help.c:3923 sql_help.c:3925 sql_help.c:3926 sql_help.c:3928 -#: sql_help.c:3929 sql_help.c:3931 sql_help.c:3932 sql_help.c:3934 -#: sql_help.c:3935 sql_help.c:3937 sql_help.c:3938 sql_help.c:3940 -#: sql_help.c:3941 sql_help.c:4343 sql_help.c:4344 sql_help.c:4348 -#: sql_help.c:4349 sql_help.c:4352 sql_help.c:4353 sql_help.c:4355 -#: sql_help.c:4356 sql_help.c:4358 sql_help.c:4359 sql_help.c:4361 -#: sql_help.c:4362 sql_help.c:4364 sql_help.c:4365 sql_help.c:4371 -#: sql_help.c:4372 sql_help.c:4374 sql_help.c:4375 sql_help.c:4377 -#: sql_help.c:4378 sql_help.c:4380 sql_help.c:4381 sql_help.c:4383 -#: sql_help.c:4384 sql_help.c:4386 sql_help.c:4387 sql_help.c:4389 -#: sql_help.c:4390 sql_help.c:4392 sql_help.c:4393 +#: sql_help.c:579 sql_help.c:581 sql_help.c:964 sql_help.c:972 sql_help.c:976 +#: sql_help.c:979 sql_help.c:982 sql_help.c:1654 sql_help.c:1662 +#: sql_help.c:1666 sql_help.c:1669 sql_help.c:1672 sql_help.c:2734 +#: sql_help.c:2736 sql_help.c:2739 sql_help.c:2740 sql_help.c:3912 +#: sql_help.c:3913 sql_help.c:3917 sql_help.c:3918 sql_help.c:3921 +#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 +#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 +#: sql_help.c:3934 sql_help.c:3940 sql_help.c:3941 sql_help.c:3943 +#: sql_help.c:3944 sql_help.c:3946 sql_help.c:3947 sql_help.c:3949 +#: sql_help.c:3950 sql_help.c:3952 sql_help.c:3953 sql_help.c:3955 +#: sql_help.c:3956 sql_help.c:3958 sql_help.c:3959 sql_help.c:3961 +#: sql_help.c:3962 sql_help.c:4375 sql_help.c:4376 sql_help.c:4380 +#: sql_help.c:4381 sql_help.c:4384 sql_help.c:4385 sql_help.c:4387 +#: sql_help.c:4388 sql_help.c:4390 sql_help.c:4391 sql_help.c:4393 +#: sql_help.c:4394 sql_help.c:4396 sql_help.c:4397 sql_help.c:4403 +#: sql_help.c:4404 sql_help.c:4406 sql_help.c:4407 sql_help.c:4409 +#: sql_help.c:4410 sql_help.c:4412 sql_help.c:4413 sql_help.c:4415 +#: sql_help.c:4416 sql_help.c:4418 sql_help.c:4419 sql_help.c:4421 +#: sql_help.c:4422 sql_help.c:4424 sql_help.c:4425 msgid "role_specification" msgstr "rollspecifikation" -#: sql_help.c:570 sql_help.c:572 sql_help.c:1664 sql_help.c:2205 -#: sql_help.c:2725 sql_help.c:3253 sql_help.c:3704 sql_help.c:4720 +#: sql_help.c:580 sql_help.c:582 sql_help.c:1685 sql_help.c:2225 +#: sql_help.c:2742 sql_help.c:3273 sql_help.c:3724 sql_help.c:4753 msgid "user_name" msgstr "användarnamn" -#: sql_help.c:573 sql_help.c:968 sql_help.c:1653 sql_help.c:2724 -#: sql_help.c:3942 sql_help.c:4394 +#: sql_help.c:583 sql_help.c:984 sql_help.c:1674 sql_help.c:2741 +#: sql_help.c:3963 sql_help.c:4426 msgid "where role_specification can be:" msgstr "där rollspecifikation kan vara:" -#: sql_help.c:575 +#: sql_help.c:585 msgid "group_name" msgstr "gruppnamn" -#: sql_help.c:596 sql_help.c:1425 sql_help.c:2216 sql_help.c:2476 -#: sql_help.c:2510 sql_help.c:2911 sql_help.c:2924 sql_help.c:2938 -#: sql_help.c:2979 sql_help.c:3006 sql_help.c:3018 sql_help.c:3933 -#: sql_help.c:4385 +#: sql_help.c:606 sql_help.c:1443 sql_help.c:2237 sql_help.c:2497 +#: sql_help.c:2531 sql_help.c:2928 sql_help.c:2941 sql_help.c:2955 +#: sql_help.c:2996 sql_help.c:3026 sql_help.c:3038 sql_help.c:3954 +#: sql_help.c:4417 msgid "tablespace_name" msgstr "tabellutrymmesnamn" -#: sql_help.c:598 sql_help.c:691 sql_help.c:1372 sql_help.c:1382 -#: sql_help.c:1420 sql_help.c:1782 sql_help.c:1785 +#: sql_help.c:608 sql_help.c:701 sql_help.c:1390 sql_help.c:1400 +#: sql_help.c:1438 sql_help.c:1800 msgid "index_name" msgstr "indexnamn" -#: sql_help.c:602 sql_help.c:605 sql_help.c:694 sql_help.c:696 sql_help.c:1375 -#: sql_help.c:1377 sql_help.c:1423 sql_help.c:2474 sql_help.c:2508 -#: sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 sql_help.c:2977 -#: sql_help.c:3004 +#: sql_help.c:612 sql_help.c:615 sql_help.c:704 sql_help.c:706 sql_help.c:1393 +#: sql_help.c:1395 sql_help.c:1441 sql_help.c:2495 sql_help.c:2529 +#: sql_help.c:2926 sql_help.c:2939 sql_help.c:2953 sql_help.c:2994 +#: sql_help.c:3024 msgid "storage_parameter" msgstr "lagringsparameter" -#: sql_help.c:607 +#: sql_help.c:617 msgid "column_number" msgstr "kolumnnummer" -#: sql_help.c:631 sql_help.c:1870 sql_help.c:4477 +#: sql_help.c:641 sql_help.c:1885 sql_help.c:4509 msgid "large_object_oid" msgstr "stort_objekt_oid" -#: sql_help.c:690 sql_help.c:1358 sql_help.c:2897 +#: sql_help.c:700 sql_help.c:1376 sql_help.c:2914 msgid "compression_method" msgstr "komprimeringsmetod" -#: sql_help.c:692 sql_help.c:1373 +#: sql_help.c:702 sql_help.c:1391 msgid "new_access_method" msgstr "ny_accessmetod" -#: sql_help.c:725 sql_help.c:2531 +#: sql_help.c:739 sql_help.c:2552 msgid "res_proc" msgstr "res_proc" -#: sql_help.c:726 sql_help.c:2532 +#: sql_help.c:740 sql_help.c:2553 msgid "join_proc" msgstr "join_proc" -#: sql_help.c:778 sql_help.c:790 sql_help.c:2549 +#: sql_help.c:741 sql_help.c:2550 +msgid "com_op" +msgstr "com_op" + +#: sql_help.c:742 sql_help.c:2551 +msgid "neg_op" +msgstr "neg_op" + +#: sql_help.c:794 sql_help.c:806 sql_help.c:2570 msgid "strategy_number" msgstr "strateginummer" -#: sql_help.c:780 sql_help.c:781 sql_help.c:784 sql_help.c:785 sql_help.c:791 -#: sql_help.c:792 sql_help.c:794 sql_help.c:795 sql_help.c:2551 sql_help.c:2552 -#: sql_help.c:2555 sql_help.c:2556 +#: sql_help.c:796 sql_help.c:797 sql_help.c:800 sql_help.c:801 sql_help.c:807 +#: sql_help.c:808 sql_help.c:810 sql_help.c:811 sql_help.c:2572 sql_help.c:2573 +#: sql_help.c:2576 sql_help.c:2577 msgid "op_type" msgstr "op_typ" -#: sql_help.c:782 sql_help.c:2553 +#: sql_help.c:798 sql_help.c:2574 msgid "sort_family_name" msgstr "sorteringsfamiljnamn" -#: sql_help.c:783 sql_help.c:793 sql_help.c:2554 +#: sql_help.c:799 sql_help.c:809 sql_help.c:2575 msgid "support_number" msgstr "supportnummer" -#: sql_help.c:787 sql_help.c:2138 sql_help.c:2558 sql_help.c:3095 -#: sql_help.c:3097 +#: sql_help.c:803 sql_help.c:2157 sql_help.c:2579 sql_help.c:3115 +#: sql_help.c:3117 msgid "argument_type" msgstr "argumenttyp" -#: sql_help.c:818 sql_help.c:821 sql_help.c:910 sql_help.c:1039 sql_help.c:1079 -#: sql_help.c:1546 sql_help.c:1549 sql_help.c:1727 sql_help.c:1781 -#: sql_help.c:1784 sql_help.c:1855 sql_help.c:1880 sql_help.c:1893 -#: sql_help.c:1908 sql_help.c:1966 sql_help.c:1972 sql_help.c:2332 -#: sql_help.c:2344 sql_help.c:2465 sql_help.c:2505 sql_help.c:2582 -#: sql_help.c:2636 sql_help.c:2693 sql_help.c:2745 sql_help.c:2778 -#: sql_help.c:2785 sql_help.c:2894 sql_help.c:2912 sql_help.c:2925 -#: sql_help.c:3001 sql_help.c:3121 sql_help.c:3302 sql_help.c:3525 -#: sql_help.c:3574 sql_help.c:3680 sql_help.c:3889 sql_help.c:3895 -#: sql_help.c:3956 sql_help.c:3988 sql_help.c:4341 sql_help.c:4347 -#: sql_help.c:4465 sql_help.c:4576 sql_help.c:4578 sql_help.c:4640 -#: sql_help.c:4679 sql_help.c:4833 sql_help.c:4835 sql_help.c:4897 -#: sql_help.c:4931 sql_help.c:4991 sql_help.c:5079 sql_help.c:5081 -#: sql_help.c:5143 +#: sql_help.c:834 sql_help.c:837 sql_help.c:926 sql_help.c:1055 sql_help.c:1095 +#: sql_help.c:1567 sql_help.c:1570 sql_help.c:1746 sql_help.c:1799 +#: sql_help.c:1870 sql_help.c:1895 sql_help.c:1908 sql_help.c:1923 +#: sql_help.c:1983 sql_help.c:1989 sql_help.c:2353 sql_help.c:2365 +#: sql_help.c:2486 sql_help.c:2526 sql_help.c:2603 sql_help.c:2657 +#: sql_help.c:2710 sql_help.c:2762 sql_help.c:2795 sql_help.c:2802 +#: sql_help.c:2911 sql_help.c:2929 sql_help.c:2942 sql_help.c:3021 +#: sql_help.c:3141 sql_help.c:3322 sql_help.c:3545 sql_help.c:3594 +#: sql_help.c:3700 sql_help.c:3910 sql_help.c:3916 sql_help.c:3977 +#: sql_help.c:4009 sql_help.c:4373 sql_help.c:4379 sql_help.c:4497 +#: sql_help.c:4610 sql_help.c:4673 sql_help.c:4712 sql_help.c:4868 +#: sql_help.c:4931 sql_help.c:4965 sql_help.c:5023 sql_help.c:5113 +#: sql_help.c:5176 msgid "table_name" msgstr "tabellnamn" -#: sql_help.c:823 sql_help.c:2584 +#: sql_help.c:839 sql_help.c:2605 msgid "using_expression" msgstr "using-uttryck" -#: sql_help.c:824 sql_help.c:2585 +#: sql_help.c:840 sql_help.c:2606 msgid "check_expression" msgstr "check-uttryck" -#: sql_help.c:897 sql_help.c:899 sql_help.c:901 sql_help.c:2632 +#: sql_help.c:913 sql_help.c:915 sql_help.c:917 sql_help.c:2653 msgid "publication_object" msgstr "publiceringsobject" -#: sql_help.c:903 sql_help.c:2633 +#: sql_help.c:919 sql_help.c:2654 msgid "publication_parameter" msgstr "publiceringsparameter" -#: sql_help.c:909 sql_help.c:2635 +#: sql_help.c:925 sql_help.c:2656 msgid "where publication_object is one of:" msgstr "där publiceringsobjekt är en av:" -#: sql_help.c:952 sql_help.c:1637 sql_help.c:2443 sql_help.c:2670 -#: sql_help.c:3236 +#: sql_help.c:968 sql_help.c:1658 sql_help.c:2464 sql_help.c:2689 +#: sql_help.c:3256 msgid "password" msgstr "lösenord" -#: sql_help.c:953 sql_help.c:1638 sql_help.c:2444 sql_help.c:2671 -#: sql_help.c:3237 +#: sql_help.c:969 sql_help.c:1659 sql_help.c:2465 sql_help.c:2690 +#: sql_help.c:3257 msgid "timestamp" msgstr "tidsstämpel" -#: sql_help.c:957 sql_help.c:961 sql_help.c:964 sql_help.c:967 sql_help.c:1642 -#: sql_help.c:1646 sql_help.c:1649 sql_help.c:1652 sql_help.c:3902 -#: sql_help.c:4354 +#: sql_help.c:973 sql_help.c:977 sql_help.c:980 sql_help.c:983 sql_help.c:1663 +#: sql_help.c:1667 sql_help.c:1670 sql_help.c:1673 sql_help.c:3923 +#: sql_help.c:4386 msgid "database_name" msgstr "databasnamn" -#: sql_help.c:1073 sql_help.c:2740 +#: sql_help.c:1089 sql_help.c:2757 msgid "increment" msgstr "ökningsvärde" -#: sql_help.c:1074 sql_help.c:2741 +#: sql_help.c:1090 sql_help.c:2758 msgid "minvalue" msgstr "minvärde" -#: sql_help.c:1075 sql_help.c:2742 +#: sql_help.c:1091 sql_help.c:2759 msgid "maxvalue" msgstr "maxvärde" -#: sql_help.c:1076 sql_help.c:2743 sql_help.c:4574 sql_help.c:4677 -#: sql_help.c:4831 sql_help.c:5008 sql_help.c:5077 +#: sql_help.c:1092 sql_help.c:2760 sql_help.c:4606 sql_help.c:4710 +#: sql_help.c:4864 sql_help.c:5040 sql_help.c:5109 msgid "start" msgstr "start" -#: sql_help.c:1077 sql_help.c:1347 +#: sql_help.c:1093 sql_help.c:1365 msgid "restart" msgstr "starta om" -#: sql_help.c:1078 sql_help.c:2744 +#: sql_help.c:1094 sql_help.c:2761 msgid "cache" msgstr "cache" -#: sql_help.c:1123 +#: sql_help.c:1139 msgid "new_target" msgstr "nytt_mål" -#: sql_help.c:1142 sql_help.c:2797 +#: sql_help.c:1158 sql_help.c:2814 msgid "conninfo" msgstr "anslinfo" -#: sql_help.c:1144 sql_help.c:1148 sql_help.c:1152 sql_help.c:2798 +#: sql_help.c:1160 sql_help.c:1164 sql_help.c:1168 sql_help.c:2815 msgid "publication_name" msgstr "publiceringsnamn" -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 +#: sql_help.c:1161 sql_help.c:1165 sql_help.c:1169 msgid "publication_option" msgstr "publicerings_alternativ" -#: sql_help.c:1156 +#: sql_help.c:1172 msgid "refresh_option" msgstr "refresh_alternativ" -#: sql_help.c:1161 sql_help.c:2799 +#: sql_help.c:1177 sql_help.c:2816 msgid "subscription_parameter" msgstr "prenumerationsparameter" -#: sql_help.c:1164 +#: sql_help.c:1180 msgid "skip_option" msgstr "skip_alternativ" -#: sql_help.c:1324 sql_help.c:1327 +#: sql_help.c:1340 sql_help.c:1343 msgid "partition_name" msgstr "partitionsnamn" -#: sql_help.c:1325 sql_help.c:2349 sql_help.c:2930 +#: sql_help.c:1341 sql_help.c:2370 sql_help.c:2947 msgid "partition_bound_spec" msgstr "partitionsgränsspec" -#: sql_help.c:1344 sql_help.c:1394 sql_help.c:2944 +#: sql_help.c:1362 sql_help.c:1412 sql_help.c:2961 msgid "sequence_options" msgstr "sekvensalternativ" -#: sql_help.c:1346 +#: sql_help.c:1364 msgid "sequence_option" msgstr "sekvensalternativ" -#: sql_help.c:1360 +#: sql_help.c:1378 msgid "table_constraint_using_index" msgstr "tabellvillkor_för_index" -#: sql_help.c:1368 sql_help.c:1369 sql_help.c:1370 sql_help.c:1371 +#: sql_help.c:1386 sql_help.c:1387 sql_help.c:1388 sql_help.c:1389 msgid "rewrite_rule_name" msgstr "omskrivningsregelnamn" -#: sql_help.c:1383 sql_help.c:2361 sql_help.c:2969 +#: sql_help.c:1401 sql_help.c:2382 sql_help.c:2986 msgid "and partition_bound_spec is:" msgstr "och partitionsgränsspec är:" -#: sql_help.c:1384 sql_help.c:1385 sql_help.c:1386 sql_help.c:2362 -#: sql_help.c:2363 sql_help.c:2364 sql_help.c:2970 sql_help.c:2971 -#: sql_help.c:2972 +#: sql_help.c:1402 sql_help.c:1403 sql_help.c:1404 sql_help.c:2383 +#: sql_help.c:2384 sql_help.c:2385 sql_help.c:2987 sql_help.c:2988 +#: sql_help.c:2989 msgid "partition_bound_expr" msgstr "partitionsgränsuttryck" -#: sql_help.c:1387 sql_help.c:1388 sql_help.c:2365 sql_help.c:2366 -#: sql_help.c:2973 sql_help.c:2974 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:2386 sql_help.c:2387 +#: sql_help.c:2990 sql_help.c:2991 msgid "numeric_literal" msgstr "numerisk_literal" -#: sql_help.c:1389 +#: sql_help.c:1407 msgid "and column_constraint is:" msgstr "och kolumnvillkor är:" -#: sql_help.c:1392 sql_help.c:2356 sql_help.c:2397 sql_help.c:2606 -#: sql_help.c:2942 +#: sql_help.c:1410 sql_help.c:2377 sql_help.c:2418 sql_help.c:2627 +#: sql_help.c:2959 msgid "default_expr" msgstr "default_uttryck" -#: sql_help.c:1393 sql_help.c:2357 sql_help.c:2943 +#: sql_help.c:1411 sql_help.c:2378 sql_help.c:2960 msgid "generation_expr" msgstr "generatoruttryck" -#: sql_help.c:1395 sql_help.c:1396 sql_help.c:1405 sql_help.c:1407 -#: sql_help.c:1411 sql_help.c:2945 sql_help.c:2946 sql_help.c:2955 -#: sql_help.c:2957 sql_help.c:2961 +#: sql_help.c:1413 sql_help.c:1414 sql_help.c:1423 sql_help.c:1425 +#: sql_help.c:1429 sql_help.c:2962 sql_help.c:2963 sql_help.c:2972 +#: sql_help.c:2974 sql_help.c:2978 msgid "index_parameters" msgstr "indexparametrar" -#: sql_help.c:1397 sql_help.c:1414 sql_help.c:2947 sql_help.c:2964 +#: sql_help.c:1415 sql_help.c:1432 sql_help.c:2964 sql_help.c:2981 msgid "reftable" msgstr "reftabell" -#: sql_help.c:1398 sql_help.c:1415 sql_help.c:2948 sql_help.c:2965 +#: sql_help.c:1416 sql_help.c:1433 sql_help.c:2965 sql_help.c:2982 msgid "refcolumn" msgstr "refkolumn" -#: sql_help.c:1399 sql_help.c:1400 sql_help.c:1416 sql_help.c:1417 -#: sql_help.c:2949 sql_help.c:2950 sql_help.c:2966 sql_help.c:2967 +#: sql_help.c:1417 sql_help.c:1418 sql_help.c:1434 sql_help.c:1435 +#: sql_help.c:2966 sql_help.c:2967 sql_help.c:2983 sql_help.c:2984 msgid "referential_action" msgstr "referentiell_aktion" -#: sql_help.c:1401 sql_help.c:2358 sql_help.c:2951 +#: sql_help.c:1419 sql_help.c:2379 sql_help.c:2968 msgid "and table_constraint is:" msgstr "och tabellvillkor är:" -#: sql_help.c:1409 sql_help.c:2959 +#: sql_help.c:1427 sql_help.c:2976 msgid "exclude_element" msgstr "uteslutelement" -#: sql_help.c:1410 sql_help.c:2960 sql_help.c:4572 sql_help.c:4675 -#: sql_help.c:4829 sql_help.c:5006 sql_help.c:5075 +#: sql_help.c:1428 sql_help.c:2977 sql_help.c:4604 sql_help.c:4708 +#: sql_help.c:4862 sql_help.c:5038 sql_help.c:5107 msgid "operator" msgstr "operator" -#: sql_help.c:1412 sql_help.c:2477 sql_help.c:2962 +#: sql_help.c:1430 sql_help.c:2498 sql_help.c:2979 msgid "predicate" msgstr "predikat" -#: sql_help.c:1418 +#: sql_help.c:1436 msgid "and table_constraint_using_index is:" msgstr "och tabellvillkor_för_index är:" -#: sql_help.c:1421 sql_help.c:2975 +#: sql_help.c:1439 sql_help.c:2992 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "indexparametrar i UNIQUE-, PRIMARY KEY- och EXCLUDE-villkor är:" -#: sql_help.c:1426 sql_help.c:2980 +#: sql_help.c:1444 sql_help.c:2997 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "uteslutelement i ett EXCLUDE-villkort är:" -#: sql_help.c:1429 sql_help.c:2470 sql_help.c:2907 sql_help.c:2920 -#: sql_help.c:2934 sql_help.c:2983 sql_help.c:4001 +#: sql_help.c:1448 sql_help.c:2491 sql_help.c:2924 sql_help.c:2937 +#: sql_help.c:2951 sql_help.c:3001 sql_help.c:4022 msgid "opclass" msgstr "op-klass" -#: sql_help.c:1430 sql_help.c:2984 +#: sql_help.c:1449 sql_help.c:2492 sql_help.c:3002 +msgid "opclass_parameter" +msgstr "opclass_parameter" + +#: sql_help.c:1451 sql_help.c:3004 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "referentiell_aktion i ett FOREIGN KEY/REFERENCES-villkor är:" -#: sql_help.c:1448 sql_help.c:1451 sql_help.c:3021 +#: sql_help.c:1469 sql_help.c:1472 sql_help.c:3041 msgid "tablespace_option" msgstr "tabellutrymmesalternativ" -#: sql_help.c:1472 sql_help.c:1475 sql_help.c:1481 sql_help.c:1485 +#: sql_help.c:1493 sql_help.c:1496 sql_help.c:1502 sql_help.c:1506 msgid "token_type" msgstr "symboltyp" -#: sql_help.c:1473 sql_help.c:1476 +#: sql_help.c:1494 sql_help.c:1497 msgid "dictionary_name" msgstr "ordlistnamn" -#: sql_help.c:1478 sql_help.c:1482 +#: sql_help.c:1499 sql_help.c:1503 msgid "old_dictionary" msgstr "gammal_ordlista" -#: sql_help.c:1479 sql_help.c:1483 +#: sql_help.c:1500 sql_help.c:1504 msgid "new_dictionary" msgstr "ny_ordlista" -#: sql_help.c:1578 sql_help.c:1592 sql_help.c:1595 sql_help.c:1596 -#: sql_help.c:3174 +#: sql_help.c:1599 sql_help.c:1613 sql_help.c:1616 sql_help.c:1617 +#: sql_help.c:3194 msgid "attribute_name" msgstr "attributnamn" -#: sql_help.c:1579 +#: sql_help.c:1600 msgid "new_attribute_name" msgstr "nytt_attributnamn" -#: sql_help.c:1583 sql_help.c:1587 +#: sql_help.c:1604 sql_help.c:1608 msgid "new_enum_value" msgstr "nytt_enumvärde" -#: sql_help.c:1584 +#: sql_help.c:1605 msgid "neighbor_enum_value" msgstr "närliggande_enumvärde" -#: sql_help.c:1586 +#: sql_help.c:1607 msgid "existing_enum_value" msgstr "existerande_enumvärde" -#: sql_help.c:1589 +#: sql_help.c:1610 msgid "property" msgstr "egenskap" -#: sql_help.c:1665 sql_help.c:2341 sql_help.c:2350 sql_help.c:2756 -#: sql_help.c:3254 sql_help.c:3705 sql_help.c:3911 sql_help.c:3957 -#: sql_help.c:4363 +#: sql_help.c:1686 sql_help.c:2362 sql_help.c:2371 sql_help.c:2773 +#: sql_help.c:3274 sql_help.c:3725 sql_help.c:3932 sql_help.c:3978 +#: sql_help.c:4395 msgid "server_name" msgstr "servernamn" -#: sql_help.c:1697 sql_help.c:1700 sql_help.c:3269 +#: sql_help.c:1718 sql_help.c:1721 sql_help.c:3289 msgid "view_option_name" msgstr "visningsalternativnamn" -#: sql_help.c:1698 sql_help.c:3270 +#: sql_help.c:1719 sql_help.c:3290 msgid "view_option_value" msgstr "visningsalternativvärde" -#: sql_help.c:1720 sql_help.c:1721 sql_help.c:4974 sql_help.c:4975 +#: sql_help.c:1740 sql_help.c:5007 msgid "table_and_columns" msgstr "tabell_och_kolumner" -#: sql_help.c:1722 sql_help.c:1786 sql_help.c:1978 sql_help.c:3754 -#: sql_help.c:4198 sql_help.c:4976 +#: sql_help.c:1741 sql_help.c:1801 sql_help.c:1995 sql_help.c:3774 +#: sql_help.c:4230 sql_help.c:5008 msgid "where option can be one of:" msgstr "där flaggor kan vara en av:" -#: sql_help.c:1723 sql_help.c:1724 sql_help.c:1787 sql_help.c:1980 -#: sql_help.c:1984 sql_help.c:2164 sql_help.c:3755 sql_help.c:3756 -#: sql_help.c:3757 sql_help.c:3758 sql_help.c:3759 sql_help.c:3760 -#: sql_help.c:3761 sql_help.c:3762 sql_help.c:3763 sql_help.c:4199 -#: sql_help.c:4201 sql_help.c:4977 sql_help.c:4978 sql_help.c:4979 -#: sql_help.c:4980 sql_help.c:4981 sql_help.c:4982 sql_help.c:4983 -#: sql_help.c:4984 sql_help.c:4985 sql_help.c:4987 sql_help.c:4988 +#: sql_help.c:1742 sql_help.c:1743 sql_help.c:1802 sql_help.c:1997 +#: sql_help.c:2001 sql_help.c:2183 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:3777 sql_help.c:3778 sql_help.c:3779 sql_help.c:3780 +#: sql_help.c:3781 sql_help.c:3782 sql_help.c:3783 sql_help.c:3784 +#: sql_help.c:4231 sql_help.c:4233 sql_help.c:5009 sql_help.c:5010 +#: sql_help.c:5011 sql_help.c:5012 sql_help.c:5013 sql_help.c:5014 +#: sql_help.c:5015 sql_help.c:5016 sql_help.c:5017 sql_help.c:5019 +#: sql_help.c:5020 msgid "boolean" msgstr "boolean" -#: sql_help.c:1725 sql_help.c:4989 +#: sql_help.c:1744 sql_help.c:5021 msgid "size" msgstr "storlek" -#: sql_help.c:1726 sql_help.c:4990 +#: sql_help.c:1745 sql_help.c:5022 msgid "and table_and_columns is:" msgstr "och tabell_och_kolumner är:" -#: sql_help.c:1742 sql_help.c:4736 sql_help.c:4738 sql_help.c:4762 +#: sql_help.c:1761 sql_help.c:4769 sql_help.c:4771 sql_help.c:4795 msgid "transaction_mode" msgstr "transaktionsläge" -#: sql_help.c:1743 sql_help.c:4739 sql_help.c:4763 +#: sql_help.c:1762 sql_help.c:4772 sql_help.c:4796 msgid "where transaction_mode is one of:" msgstr "där transaktionsläge är en av:" -#: sql_help.c:1752 sql_help.c:4582 sql_help.c:4591 sql_help.c:4595 -#: sql_help.c:4599 sql_help.c:4602 sql_help.c:4839 sql_help.c:4848 -#: sql_help.c:4852 sql_help.c:4856 sql_help.c:4859 sql_help.c:5085 -#: sql_help.c:5094 sql_help.c:5098 sql_help.c:5102 sql_help.c:5105 +#: sql_help.c:1771 sql_help.c:4614 sql_help.c:4623 sql_help.c:4627 +#: sql_help.c:4631 sql_help.c:4634 sql_help.c:4872 sql_help.c:4881 +#: sql_help.c:4885 sql_help.c:4889 sql_help.c:4892 sql_help.c:5117 +#: sql_help.c:5126 sql_help.c:5130 sql_help.c:5134 sql_help.c:5137 msgid "argument" msgstr "argument" -#: sql_help.c:1852 +#: sql_help.c:1867 msgid "relation_name" msgstr "relationsnamn" -#: sql_help.c:1857 sql_help.c:3905 sql_help.c:4357 +#: sql_help.c:1872 sql_help.c:3926 sql_help.c:4389 msgid "domain_name" msgstr "domännamn" -#: sql_help.c:1879 +#: sql_help.c:1894 msgid "policy_name" msgstr "policynamn" -#: sql_help.c:1892 +#: sql_help.c:1907 msgid "rule_name" msgstr "regelnamn" -#: sql_help.c:1911 sql_help.c:4496 +#: sql_help.c:1926 sql_help.c:4528 msgid "string_literal" msgstr "sträng_literal" -#: sql_help.c:1936 sql_help.c:4160 sql_help.c:4410 +#: sql_help.c:1951 sql_help.c:4192 sql_help.c:4442 msgid "transaction_id" msgstr "transaktions-id" -#: sql_help.c:1968 sql_help.c:1975 sql_help.c:4027 +#: sql_help.c:1985 sql_help.c:1992 sql_help.c:4048 msgid "filename" msgstr "filnamn" -#: sql_help.c:1969 sql_help.c:1976 sql_help.c:2695 sql_help.c:2696 -#: sql_help.c:2697 +#: sql_help.c:1986 sql_help.c:1993 sql_help.c:2712 sql_help.c:2713 +#: sql_help.c:2714 msgid "command" msgstr "kommando" -#: sql_help.c:1971 sql_help.c:2694 sql_help.c:3124 sql_help.c:3305 -#: sql_help.c:4011 sql_help.c:4088 sql_help.c:4091 sql_help.c:4565 -#: sql_help.c:4567 sql_help.c:4668 sql_help.c:4670 sql_help.c:4822 -#: sql_help.c:4824 sql_help.c:4940 sql_help.c:5068 sql_help.c:5070 +#: sql_help.c:1988 sql_help.c:2711 sql_help.c:3144 sql_help.c:3325 +#: sql_help.c:4032 sql_help.c:4115 sql_help.c:4118 sql_help.c:4121 +#: sql_help.c:4597 sql_help.c:4599 sql_help.c:4701 sql_help.c:4703 +#: sql_help.c:4855 sql_help.c:4857 sql_help.c:4974 sql_help.c:5100 +#: sql_help.c:5102 msgid "condition" msgstr "villkor" -#: sql_help.c:1974 sql_help.c:2511 sql_help.c:3007 sql_help.c:3271 -#: sql_help.c:3289 sql_help.c:3992 +#: sql_help.c:1991 sql_help.c:2532 sql_help.c:3027 sql_help.c:3291 +#: sql_help.c:3309 sql_help.c:4013 msgid "query" msgstr "fråga" -#: sql_help.c:1979 +#: sql_help.c:1996 msgid "format_name" msgstr "formatnamn" -#: sql_help.c:1981 +#: sql_help.c:1998 msgid "delimiter_character" msgstr "avdelartecken" -#: sql_help.c:1982 +#: sql_help.c:1999 msgid "null_string" msgstr "null-sträng" -#: sql_help.c:1983 +#: sql_help.c:2000 msgid "default_string" msgstr "standard-sträng" -#: sql_help.c:1985 +#: sql_help.c:2002 msgid "quote_character" msgstr "citattecken" -#: sql_help.c:1986 +#: sql_help.c:2003 msgid "escape_character" msgstr "escape-tecken" -#: sql_help.c:1990 +#: sql_help.c:2007 +msgid "error_action" +msgstr "fel_aktion" + +#: sql_help.c:2008 msgid "encoding_name" msgstr "kodningsnamn" -#: sql_help.c:2001 +#: sql_help.c:2009 +msgid "verbosity" +msgstr "verbosity" + +#: sql_help.c:2020 msgid "access_method_type" msgstr "accessmetodtyp" -#: sql_help.c:2072 sql_help.c:2091 sql_help.c:2094 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2113 msgid "arg_data_type" msgstr "arg_datatyp" -#: sql_help.c:2073 sql_help.c:2095 sql_help.c:2103 +#: sql_help.c:2092 sql_help.c:2114 sql_help.c:2122 msgid "sfunc" msgstr "sfunc" -#: sql_help.c:2074 sql_help.c:2096 sql_help.c:2104 +#: sql_help.c:2093 sql_help.c:2115 sql_help.c:2123 msgid "state_data_type" msgstr "tillståndsdatatyp" -#: sql_help.c:2075 sql_help.c:2097 sql_help.c:2105 +#: sql_help.c:2094 sql_help.c:2116 sql_help.c:2124 msgid "state_data_size" msgstr "tillståndsdatastorlek" -#: sql_help.c:2076 sql_help.c:2098 sql_help.c:2106 +#: sql_help.c:2095 sql_help.c:2117 sql_help.c:2125 msgid "ffunc" msgstr "ffunc" -#: sql_help.c:2077 sql_help.c:2107 +#: sql_help.c:2096 sql_help.c:2126 msgid "combinefunc" msgstr "kombinerafunk" -#: sql_help.c:2078 sql_help.c:2108 +#: sql_help.c:2097 sql_help.c:2127 msgid "serialfunc" msgstr "serialiseringsfunk" -#: sql_help.c:2079 sql_help.c:2109 +#: sql_help.c:2098 sql_help.c:2128 msgid "deserialfunc" msgstr "deserialiseringsfunk" -#: sql_help.c:2080 sql_help.c:2099 sql_help.c:2110 +#: sql_help.c:2099 sql_help.c:2118 sql_help.c:2129 msgid "initial_condition" msgstr "startvärde" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2100 sql_help.c:2130 msgid "msfunc" msgstr "msfunk" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2101 sql_help.c:2131 msgid "minvfunc" msgstr "minvfunk" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2102 sql_help.c:2132 msgid "mstate_data_type" msgstr "mtillståndsdatatyp" -#: sql_help.c:2084 sql_help.c:2114 +#: sql_help.c:2103 sql_help.c:2133 msgid "mstate_data_size" msgstr "ntillståndsstorlek" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2104 sql_help.c:2134 msgid "mffunc" msgstr "mffunk" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2105 sql_help.c:2135 msgid "minitial_condition" msgstr "mstartvärde" -#: sql_help.c:2087 sql_help.c:2117 +#: sql_help.c:2106 sql_help.c:2136 msgid "sort_operator" msgstr "sorteringsoperator" -#: sql_help.c:2100 +#: sql_help.c:2119 msgid "or the old syntax" msgstr "eller gamla syntaxen" -#: sql_help.c:2102 +#: sql_help.c:2121 msgid "base_type" msgstr "bastyp" -#: sql_help.c:2160 sql_help.c:2209 +#: sql_help.c:2179 sql_help.c:2229 msgid "locale" msgstr "lokal" -#: sql_help.c:2161 sql_help.c:2210 +#: sql_help.c:2180 sql_help.c:2230 msgid "lc_collate" msgstr "lc_collate" -#: sql_help.c:2162 sql_help.c:2211 +#: sql_help.c:2181 sql_help.c:2231 msgid "lc_ctype" msgstr "lc_ctype" -#: sql_help.c:2163 sql_help.c:4463 +#: sql_help.c:2182 sql_help.c:4495 msgid "provider" msgstr "leverantör" -#: sql_help.c:2165 +#: sql_help.c:2184 msgid "rules" msgstr "regler" -#: sql_help.c:2166 sql_help.c:2271 +#: sql_help.c:2185 sql_help.c:2292 msgid "version" msgstr "version" -#: sql_help.c:2168 +#: sql_help.c:2187 msgid "existing_collation" msgstr "existerande_jämförelse" -#: sql_help.c:2178 +#: sql_help.c:2197 msgid "source_encoding" msgstr "källkodning" -#: sql_help.c:2179 +#: sql_help.c:2198 msgid "dest_encoding" msgstr "målkodning" -#: sql_help.c:2206 sql_help.c:3047 +#: sql_help.c:2226 sql_help.c:3067 msgid "template" msgstr "mall" -#: sql_help.c:2207 +#: sql_help.c:2227 msgid "encoding" msgstr "kodning" -#: sql_help.c:2208 +#: sql_help.c:2228 msgid "strategy" msgstr "strategi" -#: sql_help.c:2212 +#: sql_help.c:2232 +msgid "builtin_locale" +msgstr "inbyggd_lokal" + +#: sql_help.c:2233 msgid "icu_locale" msgstr "icu_lokal" -#: sql_help.c:2213 +#: sql_help.c:2234 msgid "icu_rules" msgstr "icu_regler" -#: sql_help.c:2214 +#: sql_help.c:2235 msgid "locale_provider" msgstr "lokal_leverantör" -#: sql_help.c:2215 +#: sql_help.c:2236 msgid "collation_version" msgstr "jämförelse_version" -#: sql_help.c:2220 +#: sql_help.c:2241 msgid "oid" msgstr "oid" -#: sql_help.c:2240 -msgid "constraint" -msgstr "villkor" - -#: sql_help.c:2241 -msgid "where constraint is:" -msgstr "där villkor är:" - -#: sql_help.c:2255 sql_help.c:2692 sql_help.c:3120 +#: sql_help.c:2276 sql_help.c:2709 sql_help.c:3140 msgid "event" msgstr "händelse" -#: sql_help.c:2256 +#: sql_help.c:2277 msgid "filter_variable" msgstr "filtervariabel" -#: sql_help.c:2257 +#: sql_help.c:2278 msgid "filter_value" msgstr "filtervärde" -#: sql_help.c:2353 sql_help.c:2939 +#: sql_help.c:2374 sql_help.c:2956 msgid "where column_constraint is:" msgstr "där kolumnvillkor är:" -#: sql_help.c:2398 +#: sql_help.c:2419 msgid "rettype" msgstr "rettyp" -#: sql_help.c:2400 +#: sql_help.c:2421 msgid "column_type" msgstr "kolumntyp" -#: sql_help.c:2409 sql_help.c:2612 +#: sql_help.c:2430 sql_help.c:2633 msgid "definition" msgstr "definition" -#: sql_help.c:2410 sql_help.c:2613 +#: sql_help.c:2431 sql_help.c:2634 msgid "obj_file" msgstr "obj-fil" -#: sql_help.c:2411 sql_help.c:2614 +#: sql_help.c:2432 sql_help.c:2635 msgid "link_symbol" msgstr "linksymbol" -#: sql_help.c:2412 sql_help.c:2615 +#: sql_help.c:2433 sql_help.c:2636 msgid "sql_body" msgstr "sql-kropp" -#: sql_help.c:2450 sql_help.c:2677 sql_help.c:3243 +#: sql_help.c:2471 sql_help.c:2694 sql_help.c:3263 msgid "uid" msgstr "uid" -#: sql_help.c:2466 sql_help.c:2507 sql_help.c:2908 sql_help.c:2921 -#: sql_help.c:2935 sql_help.c:3003 +#: sql_help.c:2487 sql_help.c:2528 sql_help.c:2925 sql_help.c:2938 +#: sql_help.c:2952 sql_help.c:3023 msgid "method" msgstr "metod" -#: sql_help.c:2471 -msgid "opclass_parameter" -msgstr "opclass_parameter" - -#: sql_help.c:2488 +#: sql_help.c:2509 msgid "call_handler" msgstr "anropshanterare" -#: sql_help.c:2489 +#: sql_help.c:2510 msgid "inline_handler" msgstr "inline-hanterare" -#: sql_help.c:2490 +#: sql_help.c:2511 msgid "valfunction" msgstr "val-funktion" -#: sql_help.c:2529 -msgid "com_op" -msgstr "com_op" - -#: sql_help.c:2530 -msgid "neg_op" -msgstr "neg_op" - -#: sql_help.c:2548 +#: sql_help.c:2569 msgid "family_name" msgstr "familjenamn" -#: sql_help.c:2559 +#: sql_help.c:2580 msgid "storage_type" msgstr "lagringstyp" -#: sql_help.c:2698 sql_help.c:3127 +#: sql_help.c:2715 sql_help.c:3147 msgid "where event can be one of:" msgstr "där händelse kan vara en av:" -#: sql_help.c:2718 sql_help.c:2720 +#: sql_help.c:2735 sql_help.c:2737 msgid "schema_element" msgstr "schema-element" -#: sql_help.c:2757 +#: sql_help.c:2774 msgid "server_type" msgstr "servertyp" -#: sql_help.c:2758 +#: sql_help.c:2775 msgid "server_version" msgstr "serverversion" -#: sql_help.c:2759 sql_help.c:3908 sql_help.c:4360 +#: sql_help.c:2776 sql_help.c:3929 sql_help.c:4392 msgid "fdw_name" msgstr "fdw-namn" -#: sql_help.c:2776 sql_help.c:2779 +#: sql_help.c:2793 sql_help.c:2796 msgid "statistics_name" msgstr "statistiknamn" -#: sql_help.c:2780 +#: sql_help.c:2797 msgid "statistics_kind" msgstr "statistiksort" -#: sql_help.c:2796 +#: sql_help.c:2813 msgid "subscription_name" msgstr "prenumerationsnamn" -#: sql_help.c:2901 +#: sql_help.c:2918 msgid "source_table" msgstr "källtabell" -#: sql_help.c:2902 +#: sql_help.c:2919 msgid "like_option" msgstr "like_alternativ" -#: sql_help.c:2968 +#: sql_help.c:2985 msgid "and like_option is:" msgstr "och likealternativ är:" -#: sql_help.c:3020 +#: sql_help.c:3040 msgid "directory" msgstr "katalog" -#: sql_help.c:3034 +#: sql_help.c:3054 msgid "parser_name" msgstr "parsernamn" -#: sql_help.c:3035 +#: sql_help.c:3055 msgid "source_config" msgstr "källkonfig" -#: sql_help.c:3064 +#: sql_help.c:3084 msgid "start_function" msgstr "startfunktion" -#: sql_help.c:3065 +#: sql_help.c:3085 msgid "gettoken_function" msgstr "gettoken_funktion" -#: sql_help.c:3066 +#: sql_help.c:3086 msgid "end_function" msgstr "slutfunktion" -#: sql_help.c:3067 +#: sql_help.c:3087 msgid "lextypes_function" msgstr "symboltypfunktion" -#: sql_help.c:3068 +#: sql_help.c:3088 msgid "headline_function" msgstr "rubrikfunktion" -#: sql_help.c:3080 +#: sql_help.c:3100 msgid "init_function" msgstr "init_funktion" -#: sql_help.c:3081 +#: sql_help.c:3101 msgid "lexize_function" msgstr "symboluppdelningsfunktion" -#: sql_help.c:3094 +#: sql_help.c:3114 msgid "from_sql_function_name" msgstr "från_sql_funktionsnamn" -#: sql_help.c:3096 +#: sql_help.c:3116 msgid "to_sql_function_name" msgstr "till_sql_funktionsnamn" -#: sql_help.c:3122 +#: sql_help.c:3142 msgid "referenced_table_name" msgstr "refererat_tabellnamn" -#: sql_help.c:3123 +#: sql_help.c:3143 msgid "transition_relation_name" msgstr "övergångsrelationsnamn" -#: sql_help.c:3126 +#: sql_help.c:3146 msgid "arguments" msgstr "argument" -#: sql_help.c:3178 +#: sql_help.c:3198 msgid "label" msgstr "etikett" -#: sql_help.c:3180 +#: sql_help.c:3200 msgid "subtype" msgstr "subtyp" -#: sql_help.c:3181 +#: sql_help.c:3201 msgid "subtype_operator_class" msgstr "subtypoperatorklass" -#: sql_help.c:3183 +#: sql_help.c:3203 msgid "canonical_function" msgstr "kanonisk_funktion" -#: sql_help.c:3184 +#: sql_help.c:3204 msgid "subtype_diff_function" msgstr "subtyp_diff_funktion" -#: sql_help.c:3185 +#: sql_help.c:3205 msgid "multirange_type_name" msgstr "multirange_typnamn" -#: sql_help.c:3187 +#: sql_help.c:3207 msgid "input_function" msgstr "inmatningsfunktion" -#: sql_help.c:3188 +#: sql_help.c:3208 msgid "output_function" msgstr "utmatningsfunktion" -#: sql_help.c:3189 +#: sql_help.c:3209 msgid "receive_function" msgstr "mottagarfunktion" -#: sql_help.c:3190 +#: sql_help.c:3210 msgid "send_function" msgstr "sändfunktion" -#: sql_help.c:3191 +#: sql_help.c:3211 msgid "type_modifier_input_function" msgstr "typmodifiering_indatafunktion" -#: sql_help.c:3192 +#: sql_help.c:3212 msgid "type_modifier_output_function" msgstr "typmodifiering_utdatafunktion" -#: sql_help.c:3193 +#: sql_help.c:3213 msgid "analyze_function" msgstr "analysfunktion" -#: sql_help.c:3194 +#: sql_help.c:3214 msgid "subscript_function" msgstr "arrayindexfunktion" -#: sql_help.c:3195 +#: sql_help.c:3215 msgid "internallength" msgstr "internlängd" -#: sql_help.c:3196 +#: sql_help.c:3216 msgid "alignment" msgstr "justering" -#: sql_help.c:3197 +#: sql_help.c:3217 msgid "storage" msgstr "lagring" -#: sql_help.c:3198 +#: sql_help.c:3218 msgid "like_type" msgstr "liketyp" -#: sql_help.c:3199 +#: sql_help.c:3219 msgid "category" msgstr "kategori" -#: sql_help.c:3200 +#: sql_help.c:3220 msgid "preferred" msgstr "föredragen" -#: sql_help.c:3201 +#: sql_help.c:3221 msgid "default" msgstr "standard" -#: sql_help.c:3202 +#: sql_help.c:3222 msgid "element" msgstr "element" -#: sql_help.c:3203 +#: sql_help.c:3223 msgid "delimiter" msgstr "avskiljare" -#: sql_help.c:3204 +#: sql_help.c:3224 msgid "collatable" msgstr "sorterbar" -#: sql_help.c:3301 sql_help.c:3987 sql_help.c:4077 sql_help.c:4560 -#: sql_help.c:4662 sql_help.c:4817 sql_help.c:4930 sql_help.c:5063 +#: sql_help.c:3321 sql_help.c:4008 sql_help.c:4102 sql_help.c:4592 +#: sql_help.c:4695 sql_help.c:4850 sql_help.c:4964 sql_help.c:5095 msgid "with_query" msgstr "with_fråga" -#: sql_help.c:3303 sql_help.c:3989 sql_help.c:4579 sql_help.c:4585 -#: sql_help.c:4588 sql_help.c:4592 sql_help.c:4596 sql_help.c:4604 -#: sql_help.c:4836 sql_help.c:4842 sql_help.c:4845 sql_help.c:4849 -#: sql_help.c:4853 sql_help.c:4861 sql_help.c:4932 sql_help.c:5082 -#: sql_help.c:5088 sql_help.c:5091 sql_help.c:5095 sql_help.c:5099 -#: sql_help.c:5107 +#: sql_help.c:3323 sql_help.c:4010 sql_help.c:4611 sql_help.c:4617 +#: sql_help.c:4620 sql_help.c:4624 sql_help.c:4628 sql_help.c:4636 +#: sql_help.c:4869 sql_help.c:4875 sql_help.c:4878 sql_help.c:4882 +#: sql_help.c:4886 sql_help.c:4894 sql_help.c:4966 sql_help.c:5114 +#: sql_help.c:5120 sql_help.c:5123 sql_help.c:5127 sql_help.c:5131 +#: sql_help.c:5139 msgid "alias" msgstr "alias" -#: sql_help.c:3304 sql_help.c:4564 sql_help.c:4606 sql_help.c:4608 -#: sql_help.c:4612 sql_help.c:4614 sql_help.c:4615 sql_help.c:4616 -#: sql_help.c:4667 sql_help.c:4821 sql_help.c:4863 sql_help.c:4865 -#: sql_help.c:4869 sql_help.c:4871 sql_help.c:4872 sql_help.c:4873 -#: sql_help.c:4939 sql_help.c:5067 sql_help.c:5109 sql_help.c:5111 -#: sql_help.c:5115 sql_help.c:5117 sql_help.c:5118 sql_help.c:5119 +#: sql_help.c:3324 sql_help.c:4596 sql_help.c:4638 sql_help.c:4640 +#: sql_help.c:4644 sql_help.c:4646 sql_help.c:4647 sql_help.c:4648 +#: sql_help.c:4700 sql_help.c:4854 sql_help.c:4896 sql_help.c:4898 +#: sql_help.c:4902 sql_help.c:4904 sql_help.c:4905 sql_help.c:4906 +#: sql_help.c:4973 sql_help.c:5099 sql_help.c:5141 sql_help.c:5143 +#: sql_help.c:5147 sql_help.c:5149 sql_help.c:5150 sql_help.c:5151 msgid "from_item" msgstr "frånval" -#: sql_help.c:3306 sql_help.c:3789 sql_help.c:4127 sql_help.c:4941 +#: sql_help.c:3326 sql_help.c:3810 sql_help.c:4159 sql_help.c:4975 msgid "cursor_name" msgstr "markörnamn" -#: sql_help.c:3307 sql_help.c:3995 sql_help.c:4942 +#: sql_help.c:3327 sql_help.c:4016 sql_help.c:4108 sql_help.c:4976 msgid "output_expression" msgstr "utdatauttryck" -#: sql_help.c:3308 sql_help.c:3996 sql_help.c:4563 sql_help.c:4665 -#: sql_help.c:4820 sql_help.c:4943 sql_help.c:5066 +#: sql_help.c:3328 sql_help.c:4017 sql_help.c:4109 sql_help.c:4595 +#: sql_help.c:4698 sql_help.c:4853 sql_help.c:4977 sql_help.c:5098 msgid "output_name" msgstr "utdatanamn" -#: sql_help.c:3324 +#: sql_help.c:3344 msgid "code" msgstr "kod" -#: sql_help.c:3729 +#: sql_help.c:3749 msgid "parameter" msgstr "parameter" -#: sql_help.c:3752 sql_help.c:3753 sql_help.c:4152 +#: sql_help.c:3773 sql_help.c:4184 msgid "statement" msgstr "sats" -#: sql_help.c:3788 sql_help.c:4126 +#: sql_help.c:3809 sql_help.c:4158 msgid "direction" msgstr "riktning" -#: sql_help.c:3790 sql_help.c:4128 +#: sql_help.c:3811 sql_help.c:4160 msgid "where direction can be one of:" msgstr "där riktning kan vara en av:" -#: sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 sql_help.c:3794 -#: sql_help.c:3795 sql_help.c:4129 sql_help.c:4130 sql_help.c:4131 -#: sql_help.c:4132 sql_help.c:4133 sql_help.c:4573 sql_help.c:4575 -#: sql_help.c:4676 sql_help.c:4678 sql_help.c:4830 sql_help.c:4832 -#: sql_help.c:5007 sql_help.c:5009 sql_help.c:5076 sql_help.c:5078 +#: sql_help.c:3812 sql_help.c:3813 sql_help.c:3814 sql_help.c:3815 +#: sql_help.c:3816 sql_help.c:4161 sql_help.c:4162 sql_help.c:4163 +#: sql_help.c:4164 sql_help.c:4165 sql_help.c:4605 sql_help.c:4607 +#: sql_help.c:4709 sql_help.c:4711 sql_help.c:4863 sql_help.c:4865 +#: sql_help.c:5039 sql_help.c:5041 sql_help.c:5108 sql_help.c:5110 msgid "count" msgstr "antal" -#: sql_help.c:3898 sql_help.c:4350 +#: sql_help.c:3919 sql_help.c:4382 msgid "sequence_name" msgstr "sekvensnamn" -#: sql_help.c:3916 sql_help.c:4368 +#: sql_help.c:3937 sql_help.c:4400 msgid "arg_name" msgstr "arg_namn" -#: sql_help.c:3917 sql_help.c:4369 +#: sql_help.c:3938 sql_help.c:4401 msgid "arg_type" msgstr "arg_typ" -#: sql_help.c:3924 sql_help.c:4376 +#: sql_help.c:3945 sql_help.c:4408 msgid "loid" msgstr "loid" -#: sql_help.c:3955 +#: sql_help.c:3976 msgid "remote_schema" msgstr "externt_schema" -#: sql_help.c:3958 +#: sql_help.c:3979 msgid "local_schema" msgstr "lokalt_schema" -#: sql_help.c:3993 +#: sql_help.c:4014 msgid "conflict_target" msgstr "konfliktmål" -#: sql_help.c:3994 +#: sql_help.c:4015 msgid "conflict_action" msgstr "konfliktaktion" -#: sql_help.c:3997 +#: sql_help.c:4018 msgid "where conflict_target can be one of:" msgstr "där konfliktmål kan vara en av:" -#: sql_help.c:3998 +#: sql_help.c:4019 msgid "index_column_name" msgstr "indexkolumnnamn" -#: sql_help.c:3999 +#: sql_help.c:4020 msgid "index_expression" msgstr "indexuttryck" -#: sql_help.c:4002 +#: sql_help.c:4023 msgid "index_predicate" msgstr "indexpredikat" -#: sql_help.c:4004 +#: sql_help.c:4025 msgid "and conflict_action is one of:" msgstr "och konfliktaktion är en av:" -#: sql_help.c:4010 sql_help.c:4938 +#: sql_help.c:4031 sql_help.c:4132 sql_help.c:4972 msgid "sub-SELECT" msgstr "sub-SELECT" -#: sql_help.c:4019 sql_help.c:4141 sql_help.c:4914 +#: sql_help.c:4040 sql_help.c:4173 sql_help.c:4948 msgid "channel" msgstr "kanal" -#: sql_help.c:4041 +#: sql_help.c:4062 msgid "lockmode" msgstr "låsläge" -#: sql_help.c:4042 +#: sql_help.c:4063 msgid "where lockmode is one of:" msgstr "där låsläge är en av:" -#: sql_help.c:4078 +#: sql_help.c:4103 msgid "target_table_name" msgstr "måltabellnamn" -#: sql_help.c:4079 +#: sql_help.c:4104 msgid "target_alias" msgstr "målalias" -#: sql_help.c:4080 +#: sql_help.c:4105 msgid "data_source" msgstr "datakälla" -#: sql_help.c:4081 sql_help.c:4609 sql_help.c:4866 sql_help.c:5112 +#: sql_help.c:4106 sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "join_condition" msgstr "join-villkor" -#: sql_help.c:4082 +#: sql_help.c:4107 msgid "when_clause" msgstr "when_sats" -#: sql_help.c:4083 +#: sql_help.c:4110 msgid "where data_source is:" msgstr "där datakälla är:" -#: sql_help.c:4084 +#: sql_help.c:4111 msgid "source_table_name" msgstr "källtabellnamn" -#: sql_help.c:4085 +#: sql_help.c:4112 msgid "source_query" msgstr "källfråga" -#: sql_help.c:4086 +#: sql_help.c:4113 msgid "source_alias" msgstr "källalias" -#: sql_help.c:4087 +#: sql_help.c:4114 msgid "and when_clause is:" msgstr "och when_sats är:" -#: sql_help.c:4089 +#: sql_help.c:4116 sql_help.c:4119 msgid "merge_update" msgstr "merge_update" -#: sql_help.c:4090 +#: sql_help.c:4117 sql_help.c:4120 msgid "merge_delete" msgstr "merge_delete" -#: sql_help.c:4092 +#: sql_help.c:4122 msgid "merge_insert" msgstr "merge_insert" -#: sql_help.c:4093 +#: sql_help.c:4123 msgid "and merge_insert is:" msgstr "och merge_insert är:" -#: sql_help.c:4096 +#: sql_help.c:4126 msgid "and merge_update is:" msgstr "och merge_update är:" -#: sql_help.c:4101 +#: sql_help.c:4133 msgid "and merge_delete is:" msgstr "och merge_delete är:" -#: sql_help.c:4142 +#: sql_help.c:4174 msgid "payload" msgstr "innehåll" -#: sql_help.c:4169 +#: sql_help.c:4201 msgid "old_role" msgstr "gammal_roll" -#: sql_help.c:4170 +#: sql_help.c:4202 msgid "new_role" msgstr "ny_roll" -#: sql_help.c:4209 sql_help.c:4418 sql_help.c:4426 +#: sql_help.c:4241 sql_help.c:4450 sql_help.c:4458 msgid "savepoint_name" msgstr "sparpunktnamn" -#: sql_help.c:4566 sql_help.c:4624 sql_help.c:4823 sql_help.c:4881 -#: sql_help.c:5069 sql_help.c:5127 +#: sql_help.c:4598 sql_help.c:4656 sql_help.c:4856 sql_help.c:4914 +#: sql_help.c:5101 sql_help.c:5159 msgid "grouping_element" msgstr "gruperingselement" -#: sql_help.c:4568 sql_help.c:4671 sql_help.c:4825 sql_help.c:5071 +#: sql_help.c:4600 sql_help.c:4704 sql_help.c:4858 sql_help.c:5103 msgid "window_name" msgstr "fönsternamn" -#: sql_help.c:4569 sql_help.c:4672 sql_help.c:4826 sql_help.c:5072 +#: sql_help.c:4601 sql_help.c:4705 sql_help.c:4859 sql_help.c:5104 msgid "window_definition" msgstr "fönsterdefinition" -#: sql_help.c:4570 sql_help.c:4584 sql_help.c:4628 sql_help.c:4673 -#: sql_help.c:4827 sql_help.c:4841 sql_help.c:4885 sql_help.c:5073 -#: sql_help.c:5087 sql_help.c:5131 +#: sql_help.c:4602 sql_help.c:4616 sql_help.c:4660 sql_help.c:4706 +#: sql_help.c:4860 sql_help.c:4874 sql_help.c:4918 sql_help.c:5105 +#: sql_help.c:5119 sql_help.c:5163 msgid "select" msgstr "select" -#: sql_help.c:4577 sql_help.c:4834 sql_help.c:5080 +#: sql_help.c:4608 sql_help.c:4866 sql_help.c:5111 +msgid "from_reference" +msgstr "från_referens" + +#: sql_help.c:4609 sql_help.c:4867 sql_help.c:5112 msgid "where from_item can be one of:" msgstr "där frånval kan vara en av:" -#: sql_help.c:4580 sql_help.c:4586 sql_help.c:4589 sql_help.c:4593 -#: sql_help.c:4605 sql_help.c:4837 sql_help.c:4843 sql_help.c:4846 -#: sql_help.c:4850 sql_help.c:4862 sql_help.c:5083 sql_help.c:5089 -#: sql_help.c:5092 sql_help.c:5096 sql_help.c:5108 +#: sql_help.c:4612 sql_help.c:4618 sql_help.c:4621 sql_help.c:4625 +#: sql_help.c:4637 sql_help.c:4870 sql_help.c:4876 sql_help.c:4879 +#: sql_help.c:4883 sql_help.c:4895 sql_help.c:5115 sql_help.c:5121 +#: sql_help.c:5124 sql_help.c:5128 sql_help.c:5140 msgid "column_alias" msgstr "kolumnalias" -#: sql_help.c:4581 sql_help.c:4838 sql_help.c:5084 +#: sql_help.c:4613 sql_help.c:4871 sql_help.c:5116 msgid "sampling_method" msgstr "samplingsmetod" -#: sql_help.c:4583 sql_help.c:4840 sql_help.c:5086 +#: sql_help.c:4615 sql_help.c:4873 sql_help.c:5118 msgid "seed" msgstr "frö" -#: sql_help.c:4587 sql_help.c:4626 sql_help.c:4844 sql_help.c:4883 -#: sql_help.c:5090 sql_help.c:5129 +#: sql_help.c:4619 sql_help.c:4658 sql_help.c:4877 sql_help.c:4916 +#: sql_help.c:5122 sql_help.c:5161 msgid "with_query_name" msgstr "with_frågenamn" -#: sql_help.c:4597 sql_help.c:4600 sql_help.c:4603 sql_help.c:4854 -#: sql_help.c:4857 sql_help.c:4860 sql_help.c:5100 sql_help.c:5103 -#: sql_help.c:5106 +#: sql_help.c:4629 sql_help.c:4632 sql_help.c:4635 sql_help.c:4887 +#: sql_help.c:4890 sql_help.c:4893 sql_help.c:5132 sql_help.c:5135 +#: sql_help.c:5138 msgid "column_definition" msgstr "kolumndefinition" -#: sql_help.c:4607 sql_help.c:4613 sql_help.c:4864 sql_help.c:4870 -#: sql_help.c:5110 sql_help.c:5116 +#: sql_help.c:4639 sql_help.c:4645 sql_help.c:4897 sql_help.c:4903 +#: sql_help.c:5142 sql_help.c:5148 msgid "join_type" msgstr "join-typ" -#: sql_help.c:4610 sql_help.c:4867 sql_help.c:5113 +#: sql_help.c:4642 sql_help.c:4900 sql_help.c:5145 msgid "join_column" msgstr "join-kolumn" -#: sql_help.c:4611 sql_help.c:4868 sql_help.c:5114 +#: sql_help.c:4643 sql_help.c:4901 sql_help.c:5146 msgid "join_using_alias" msgstr "join_using_alias" -#: sql_help.c:4617 sql_help.c:4874 sql_help.c:5120 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and grouping_element can be one of:" msgstr "och grupperingselement kan vara en av:" -#: sql_help.c:4625 sql_help.c:4882 sql_help.c:5128 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 msgid "and with_query is:" msgstr "och with_fråga är:" -#: sql_help.c:4629 sql_help.c:4886 sql_help.c:5132 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "values" msgstr "värden" -#: sql_help.c:4630 sql_help.c:4887 sql_help.c:5133 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "insert" msgstr "insert" -#: sql_help.c:4631 sql_help.c:4888 sql_help.c:5134 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "update" msgstr "update" -#: sql_help.c:4632 sql_help.c:4889 sql_help.c:5135 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "delete" msgstr "delete" -#: sql_help.c:4634 sql_help.c:4891 sql_help.c:5137 +#: sql_help.c:4665 sql_help.c:4923 sql_help.c:5168 +msgid "merge" +msgstr "merge" + +#: sql_help.c:4667 sql_help.c:4925 sql_help.c:5170 msgid "search_seq_col_name" msgstr "söksekvens_kolumnnamn" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4669 sql_help.c:4927 sql_help.c:5172 msgid "cycle_mark_col_name" msgstr "cykelmarkering_kolumnnamn" -#: sql_help.c:4637 sql_help.c:4894 sql_help.c:5140 +#: sql_help.c:4670 sql_help.c:4928 sql_help.c:5173 msgid "cycle_mark_value" msgstr "cykelmarkering_värde" -#: sql_help.c:4638 sql_help.c:4895 sql_help.c:5141 +#: sql_help.c:4671 sql_help.c:4929 sql_help.c:5174 msgid "cycle_mark_default" msgstr "cykelmarkering_standard" -#: sql_help.c:4639 sql_help.c:4896 sql_help.c:5142 +#: sql_help.c:4672 sql_help.c:4930 sql_help.c:5175 msgid "cycle_path_col_name" msgstr "cykelväg_kolumnnamn" -#: sql_help.c:4666 +#: sql_help.c:4699 msgid "new_table" msgstr "ny_tabell" -#: sql_help.c:4737 +#: sql_help.c:4770 msgid "snapshot_id" msgstr "snapshot_id" -#: sql_help.c:5005 +#: sql_help.c:5037 msgid "sort_expression" msgstr "sorteringsuttryck" -#: sql_help.c:5149 sql_help.c:6133 +#: sql_help.c:5182 sql_help.c:6166 msgid "abort the current transaction" msgstr "avbryt aktuell transaktion" -#: sql_help.c:5155 +#: sql_help.c:5188 msgid "change the definition of an aggregate function" msgstr "ändra definitionen av en aggregatfunktion" -#: sql_help.c:5161 +#: sql_help.c:5194 msgid "change the definition of a collation" msgstr "ändra definitionen av en jämförelse" -#: sql_help.c:5167 +#: sql_help.c:5200 msgid "change the definition of a conversion" msgstr "ändra definitionen av en konvertering" -#: sql_help.c:5173 +#: sql_help.c:5206 msgid "change a database" msgstr "ändra en databas" -#: sql_help.c:5179 +#: sql_help.c:5212 msgid "define default access privileges" msgstr "definiera standardaccessrättigheter" -#: sql_help.c:5185 +#: sql_help.c:5218 msgid "change the definition of a domain" msgstr "ändra definitionen av en domän" -#: sql_help.c:5191 +#: sql_help.c:5224 msgid "change the definition of an event trigger" msgstr "ändra definitionen av en händelsetrigger" -#: sql_help.c:5197 +#: sql_help.c:5230 msgid "change the definition of an extension" msgstr "ändra definitionen av en utökning" -#: sql_help.c:5203 +#: sql_help.c:5236 msgid "change the definition of a foreign-data wrapper" msgstr "ändra definitionen av en främmande data-omvandlare" -#: sql_help.c:5209 +#: sql_help.c:5242 msgid "change the definition of a foreign table" msgstr "ändra definitionen av en främmande tabell" -#: sql_help.c:5215 +#: sql_help.c:5248 msgid "change the definition of a function" msgstr "ändra definitionen av en funktion" -#: sql_help.c:5221 +#: sql_help.c:5254 msgid "change role name or membership" msgstr "ändra rollnamn eller medlemskap" -#: sql_help.c:5227 +#: sql_help.c:5260 msgid "change the definition of an index" msgstr "ändra definitionen av ett index" -#: sql_help.c:5233 +#: sql_help.c:5266 msgid "change the definition of a procedural language" msgstr "ändra definitionen av ett procedur-språk" -#: sql_help.c:5239 +#: sql_help.c:5272 msgid "change the definition of a large object" msgstr "ändra definitionen av ett stort objekt" -#: sql_help.c:5245 +#: sql_help.c:5278 msgid "change the definition of a materialized view" msgstr "ändra definitionen av en materialiserad vy" -#: sql_help.c:5251 +#: sql_help.c:5284 msgid "change the definition of an operator" msgstr "ändra definitionen av en operator" -#: sql_help.c:5257 +#: sql_help.c:5290 msgid "change the definition of an operator class" msgstr "ändra definitionen av en operatorklass" -#: sql_help.c:5263 +#: sql_help.c:5296 msgid "change the definition of an operator family" msgstr "ändra definitionen av en operatorfamilj" -#: sql_help.c:5269 +#: sql_help.c:5302 msgid "change the definition of a row-level security policy" msgstr "ändra definitionen av en säkerhetspolicy på radnivå" -#: sql_help.c:5275 +#: sql_help.c:5308 msgid "change the definition of a procedure" msgstr "ändra definitionen av en procedur" -#: sql_help.c:5281 +#: sql_help.c:5314 msgid "change the definition of a publication" msgstr "ändra definitionen av en publicering" -#: sql_help.c:5287 sql_help.c:5389 +#: sql_help.c:5320 sql_help.c:5422 msgid "change a database role" msgstr "ändra databasroll" -#: sql_help.c:5293 +#: sql_help.c:5326 msgid "change the definition of a routine" msgstr "ändra definitionen av en rutin" -#: sql_help.c:5299 +#: sql_help.c:5332 msgid "change the definition of a rule" msgstr "ändra definitionen av en regel" -#: sql_help.c:5305 +#: sql_help.c:5338 msgid "change the definition of a schema" msgstr "ändra definitionen av ett schema" -#: sql_help.c:5311 +#: sql_help.c:5344 msgid "change the definition of a sequence generator" msgstr "ändra definitionen av en sekvensgenerator" -#: sql_help.c:5317 +#: sql_help.c:5350 msgid "change the definition of a foreign server" msgstr "ändra definitionen av en främmande server" -#: sql_help.c:5323 +#: sql_help.c:5356 msgid "change the definition of an extended statistics object" msgstr "ändra definitionen av ett utökat statistikobjekt" -#: sql_help.c:5329 +#: sql_help.c:5362 msgid "change the definition of a subscription" msgstr "ändra definitionen av en prenumerering" -#: sql_help.c:5335 +#: sql_help.c:5368 msgid "change a server configuration parameter" msgstr "ändra en servers konfigurationsparameter" -#: sql_help.c:5341 +#: sql_help.c:5374 msgid "change the definition of a table" msgstr "ändra definitionen av en tabell" -#: sql_help.c:5347 +#: sql_help.c:5380 msgid "change the definition of a tablespace" msgstr "ändra definitionen av ett tabellutrymme" -#: sql_help.c:5353 +#: sql_help.c:5386 msgid "change the definition of a text search configuration" msgstr "ändra definitionen av en textsökkonfiguration" -#: sql_help.c:5359 +#: sql_help.c:5392 msgid "change the definition of a text search dictionary" msgstr "ändra definitionen av en textsökordlista" -#: sql_help.c:5365 +#: sql_help.c:5398 msgid "change the definition of a text search parser" msgstr "ändra definitionen av en textsökparser" -#: sql_help.c:5371 +#: sql_help.c:5404 msgid "change the definition of a text search template" msgstr "ändra definitionen av en textsökmall" -#: sql_help.c:5377 +#: sql_help.c:5410 msgid "change the definition of a trigger" msgstr "ändra definitionen av en trigger" -#: sql_help.c:5383 +#: sql_help.c:5416 msgid "change the definition of a type" msgstr "ändra definitionen av en typ" -#: sql_help.c:5395 +#: sql_help.c:5428 msgid "change the definition of a user mapping" msgstr "ändra definitionen av en användarmappning" -#: sql_help.c:5401 +#: sql_help.c:5434 msgid "change the definition of a view" msgstr "ändra definitionen av en vy" -#: sql_help.c:5407 +#: sql_help.c:5440 msgid "collect statistics about a database" msgstr "samla in statistik om en databas" -#: sql_help.c:5413 sql_help.c:6211 +#: sql_help.c:5446 sql_help.c:6244 msgid "start a transaction block" msgstr "starta ett transaktionsblock" -#: sql_help.c:5419 +#: sql_help.c:5452 msgid "invoke a procedure" msgstr "anropa en procedur" -#: sql_help.c:5425 +#: sql_help.c:5458 msgid "force a write-ahead log checkpoint" msgstr "tvinga checkpoint i transaktionsloggen" -#: sql_help.c:5431 +#: sql_help.c:5464 msgid "close a cursor" msgstr "stäng en markör" -#: sql_help.c:5437 +#: sql_help.c:5470 msgid "cluster a table according to an index" msgstr "klustra en tabell efter ett index" -#: sql_help.c:5443 +#: sql_help.c:5476 msgid "define or change the comment of an object" msgstr "definiera eller ändra en kommentar på ett objekt" -#: sql_help.c:5449 sql_help.c:6007 +#: sql_help.c:5482 sql_help.c:6040 msgid "commit the current transaction" msgstr "utför den aktuella transaktionen" -#: sql_help.c:5455 +#: sql_help.c:5488 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "utför commit på en transaktion som tidigare förberetts för två-fas-commit" -#: sql_help.c:5461 +#: sql_help.c:5494 msgid "copy data between a file and a table" msgstr "kopiera data mellan en fil och en tabell" -#: sql_help.c:5467 +#: sql_help.c:5500 msgid "define a new access method" msgstr "definiera en ny accessmetod" -#: sql_help.c:5473 +#: sql_help.c:5506 msgid "define a new aggregate function" msgstr "definiera en ny aggregatfunktion" -#: sql_help.c:5479 +#: sql_help.c:5512 msgid "define a new cast" msgstr "definiera en ny typomvandling" -#: sql_help.c:5485 +#: sql_help.c:5518 msgid "define a new collation" msgstr "definiera en ny jämförelse" -#: sql_help.c:5491 +#: sql_help.c:5524 msgid "define a new encoding conversion" msgstr "definiera en ny teckenkodningskonvertering" -#: sql_help.c:5497 +#: sql_help.c:5530 msgid "create a new database" msgstr "skapa en ny databas" -#: sql_help.c:5503 +#: sql_help.c:5536 msgid "define a new domain" msgstr "definiera en ny domän" -#: sql_help.c:5509 +#: sql_help.c:5542 msgid "define a new event trigger" msgstr "definiera en ny händelsetrigger" -#: sql_help.c:5515 +#: sql_help.c:5548 msgid "install an extension" msgstr "installera en utökning" -#: sql_help.c:5521 +#: sql_help.c:5554 msgid "define a new foreign-data wrapper" msgstr "definiera en ny främmande data-omvandlare" -#: sql_help.c:5527 +#: sql_help.c:5560 msgid "define a new foreign table" msgstr "definiera en ny främmande tabell" -#: sql_help.c:5533 +#: sql_help.c:5566 msgid "define a new function" msgstr "definiera en ny funktion" -#: sql_help.c:5539 sql_help.c:5599 sql_help.c:5701 +#: sql_help.c:5572 sql_help.c:5632 sql_help.c:5734 msgid "define a new database role" msgstr "definiera en ny databasroll" -#: sql_help.c:5545 +#: sql_help.c:5578 msgid "define a new index" msgstr "skapa ett nytt index" -#: sql_help.c:5551 +#: sql_help.c:5584 msgid "define a new procedural language" msgstr "definiera ett nytt procedur-språk" -#: sql_help.c:5557 +#: sql_help.c:5590 msgid "define a new materialized view" msgstr "definiera en ny materialiserad vy" -#: sql_help.c:5563 +#: sql_help.c:5596 msgid "define a new operator" msgstr "definiera en ny operator" -#: sql_help.c:5569 +#: sql_help.c:5602 msgid "define a new operator class" msgstr "definiera en ny operatorklass" -#: sql_help.c:5575 +#: sql_help.c:5608 msgid "define a new operator family" msgstr "definiera en ny operatorfamilj" -#: sql_help.c:5581 +#: sql_help.c:5614 msgid "define a new row-level security policy for a table" msgstr "definiera en ny säkerhetspolicy på radnivå för en tabell" -#: sql_help.c:5587 +#: sql_help.c:5620 msgid "define a new procedure" msgstr "definiera ett ny procedur" -#: sql_help.c:5593 +#: sql_help.c:5626 msgid "define a new publication" msgstr "definiera en ny publicering" -#: sql_help.c:5605 +#: sql_help.c:5638 msgid "define a new rewrite rule" msgstr "definiera en ny omskrivningsregel" -#: sql_help.c:5611 +#: sql_help.c:5644 msgid "define a new schema" msgstr "definiera ett nytt schema" -#: sql_help.c:5617 +#: sql_help.c:5650 msgid "define a new sequence generator" msgstr "definiera en ny sekvensgenerator" -#: sql_help.c:5623 +#: sql_help.c:5656 msgid "define a new foreign server" msgstr "definiera en ny främmande server" -#: sql_help.c:5629 +#: sql_help.c:5662 msgid "define extended statistics" msgstr "definiera utökad statistik" -#: sql_help.c:5635 +#: sql_help.c:5668 msgid "define a new subscription" msgstr "definiera en ny prenumeration" -#: sql_help.c:5641 +#: sql_help.c:5674 msgid "define a new table" msgstr "definiera en ny tabell" -#: sql_help.c:5647 sql_help.c:6169 +#: sql_help.c:5680 sql_help.c:6202 msgid "define a new table from the results of a query" msgstr "definiera en ny tabell utifrån resultatet av en fråga" -#: sql_help.c:5653 +#: sql_help.c:5686 msgid "define a new tablespace" msgstr "definiera ett nytt tabellutrymme" -#: sql_help.c:5659 +#: sql_help.c:5692 msgid "define a new text search configuration" msgstr "definiera en ny textsökkonfiguration" -#: sql_help.c:5665 +#: sql_help.c:5698 msgid "define a new text search dictionary" msgstr "definiera en ny textsökordlista" -#: sql_help.c:5671 +#: sql_help.c:5704 msgid "define a new text search parser" msgstr "definiera en ny textsökparser" -#: sql_help.c:5677 +#: sql_help.c:5710 msgid "define a new text search template" msgstr "definiera en ny textsökmall" -#: sql_help.c:5683 +#: sql_help.c:5716 msgid "define a new transform" msgstr "definiera en ny transform" -#: sql_help.c:5689 +#: sql_help.c:5722 msgid "define a new trigger" msgstr "definiera en ny trigger" -#: sql_help.c:5695 +#: sql_help.c:5728 msgid "define a new data type" msgstr "definiera en ny datatyp" -#: sql_help.c:5707 +#: sql_help.c:5740 msgid "define a new mapping of a user to a foreign server" msgstr "definiera en ny mappning av en användare till en främmande server" -#: sql_help.c:5713 +#: sql_help.c:5746 msgid "define a new view" msgstr "definiera en ny vy" -#: sql_help.c:5719 +#: sql_help.c:5752 msgid "deallocate a prepared statement" msgstr "deallokera en förberedd sats" -#: sql_help.c:5725 +#: sql_help.c:5758 msgid "define a cursor" msgstr "definiera en markör" -#: sql_help.c:5731 +#: sql_help.c:5764 msgid "delete rows of a table" msgstr "radera rader i en tabell" -#: sql_help.c:5737 +#: sql_help.c:5770 msgid "discard session state" msgstr "släng sessionstillstånd" -#: sql_help.c:5743 +#: sql_help.c:5776 msgid "execute an anonymous code block" msgstr "kör ett annonymt kodblock" -#: sql_help.c:5749 +#: sql_help.c:5782 msgid "remove an access method" msgstr "ta bort en accessmetod" -#: sql_help.c:5755 +#: sql_help.c:5788 msgid "remove an aggregate function" msgstr "ta bort en aggregatfunktioner" -#: sql_help.c:5761 +#: sql_help.c:5794 msgid "remove a cast" msgstr "ta bort en typomvandling" -#: sql_help.c:5767 +#: sql_help.c:5800 msgid "remove a collation" msgstr "ta bort en jämförelse" -#: sql_help.c:5773 +#: sql_help.c:5806 msgid "remove a conversion" msgstr "ta bort en konvertering" -#: sql_help.c:5779 +#: sql_help.c:5812 msgid "remove a database" msgstr "ta bort en databas" -#: sql_help.c:5785 +#: sql_help.c:5818 msgid "remove a domain" msgstr "ta bort en domän" -#: sql_help.c:5791 +#: sql_help.c:5824 msgid "remove an event trigger" msgstr "ta bort en händelsetrigger" -#: sql_help.c:5797 +#: sql_help.c:5830 msgid "remove an extension" msgstr "ta bort en utökning" -#: sql_help.c:5803 +#: sql_help.c:5836 msgid "remove a foreign-data wrapper" msgstr "ta bort en frammande data-omvandlare" -#: sql_help.c:5809 +#: sql_help.c:5842 msgid "remove a foreign table" msgstr "ta bort en främmande tabell" -#: sql_help.c:5815 +#: sql_help.c:5848 msgid "remove a function" msgstr "ta bort en funktion" -#: sql_help.c:5821 sql_help.c:5887 sql_help.c:5989 +#: sql_help.c:5854 sql_help.c:5920 sql_help.c:6022 msgid "remove a database role" msgstr "ta bort en databasroll" -#: sql_help.c:5827 +#: sql_help.c:5860 msgid "remove an index" msgstr "ta bort ett index" -#: sql_help.c:5833 +#: sql_help.c:5866 msgid "remove a procedural language" msgstr "ta bort ett procedur-språk" -#: sql_help.c:5839 +#: sql_help.c:5872 msgid "remove a materialized view" msgstr "ta bort en materialiserad vy" -#: sql_help.c:5845 +#: sql_help.c:5878 msgid "remove an operator" msgstr "ta bort en operator" -#: sql_help.c:5851 +#: sql_help.c:5884 msgid "remove an operator class" msgstr "ta bort en operatorklass" -#: sql_help.c:5857 +#: sql_help.c:5890 msgid "remove an operator family" msgstr "ta bort en operatorfamilj" -#: sql_help.c:5863 +#: sql_help.c:5896 msgid "remove database objects owned by a database role" msgstr "ta bort databasobjekt som ägs av databasroll" -#: sql_help.c:5869 +#: sql_help.c:5902 msgid "remove a row-level security policy from a table" msgstr "ta bort en säkerhetspolicy på radnivå från en tabell" -#: sql_help.c:5875 +#: sql_help.c:5908 msgid "remove a procedure" msgstr "ta bort en procedur" -#: sql_help.c:5881 +#: sql_help.c:5914 msgid "remove a publication" msgstr "ta bort en publicering" -#: sql_help.c:5893 +#: sql_help.c:5926 msgid "remove a routine" msgstr "ta bort en rutin" -#: sql_help.c:5899 +#: sql_help.c:5932 msgid "remove a rewrite rule" msgstr "ta bort en omskrivningsregel" -#: sql_help.c:5905 +#: sql_help.c:5938 msgid "remove a schema" msgstr "ta bort ett schema" -#: sql_help.c:5911 +#: sql_help.c:5944 msgid "remove a sequence" msgstr "ta bort en sekvens" -#: sql_help.c:5917 +#: sql_help.c:5950 msgid "remove a foreign server descriptor" msgstr "ta bort en främmande server-deskriptor" -#: sql_help.c:5923 +#: sql_help.c:5956 msgid "remove extended statistics" msgstr "ta bort utökad statistik" -#: sql_help.c:5929 +#: sql_help.c:5962 msgid "remove a subscription" msgstr "ta bort en prenumeration" -#: sql_help.c:5935 +#: sql_help.c:5968 msgid "remove a table" msgstr "ta bort en tabell" -#: sql_help.c:5941 +#: sql_help.c:5974 msgid "remove a tablespace" msgstr "ta bort ett tabellutrymme" -#: sql_help.c:5947 +#: sql_help.c:5980 msgid "remove a text search configuration" msgstr "ta bort en textsökkonfiguration" -#: sql_help.c:5953 +#: sql_help.c:5986 msgid "remove a text search dictionary" msgstr "ta bort en textsökordlista" -#: sql_help.c:5959 +#: sql_help.c:5992 msgid "remove a text search parser" msgstr "ta bort en textsökparser" -#: sql_help.c:5965 +#: sql_help.c:5998 msgid "remove a text search template" msgstr "ta bort en textsökmall" -#: sql_help.c:5971 +#: sql_help.c:6004 msgid "remove a transform" msgstr "ta bort en transform" -#: sql_help.c:5977 +#: sql_help.c:6010 msgid "remove a trigger" msgstr "ta bort en trigger" -#: sql_help.c:5983 +#: sql_help.c:6016 msgid "remove a data type" msgstr "ta bort en datatyp" -#: sql_help.c:5995 +#: sql_help.c:6028 msgid "remove a user mapping for a foreign server" msgstr "ta bort en användarmappning för en främmande server" -#: sql_help.c:6001 +#: sql_help.c:6034 msgid "remove a view" msgstr "ta bort en vy" -#: sql_help.c:6013 +#: sql_help.c:6046 msgid "execute a prepared statement" msgstr "utför en förberedd sats" -#: sql_help.c:6019 +#: sql_help.c:6052 msgid "show the execution plan of a statement" msgstr "visa körningsplanen för en sats" -#: sql_help.c:6025 +#: sql_help.c:6058 msgid "retrieve rows from a query using a cursor" msgstr "hämta rader från en fråga med hjälp av en markör" -#: sql_help.c:6031 +#: sql_help.c:6064 msgid "define access privileges" msgstr "definera åtkomsträttigheter" -#: sql_help.c:6037 +#: sql_help.c:6070 msgid "import table definitions from a foreign server" msgstr "importera tabelldefinitioner från en främmande server" -#: sql_help.c:6043 +#: sql_help.c:6076 msgid "create new rows in a table" msgstr "skapa nya rader i en tabell" -#: sql_help.c:6049 +#: sql_help.c:6082 msgid "listen for a notification" msgstr "lyssna efter notifiering" -#: sql_help.c:6055 +#: sql_help.c:6088 msgid "load a shared library file" msgstr "ladda en delad biblioteksfil (shared library)" -#: sql_help.c:6061 +#: sql_help.c:6094 msgid "lock a table" msgstr "lås en tabell" -#: sql_help.c:6067 +#: sql_help.c:6100 msgid "conditionally insert, update, or delete rows of a table" msgstr "villkorlig insert, updare eller delete av rader i en tabell" -#: sql_help.c:6073 +#: sql_help.c:6106 msgid "position a cursor" msgstr "flytta en markör" -#: sql_help.c:6079 +#: sql_help.c:6112 msgid "generate a notification" msgstr "generera en notifiering" -#: sql_help.c:6085 +#: sql_help.c:6118 msgid "prepare a statement for execution" msgstr "förbered en sats för körning" -#: sql_help.c:6091 +#: sql_help.c:6124 msgid "prepare the current transaction for two-phase commit" msgstr "avbryt aktuell transaktion för två-fas-commit" -#: sql_help.c:6097 +#: sql_help.c:6130 msgid "change the ownership of database objects owned by a database role" msgstr "byt ägare på databasobjekt som ägs av en databasroll" -#: sql_help.c:6103 +#: sql_help.c:6136 msgid "replace the contents of a materialized view" msgstr "ersätt innehållet av en materialiserad vy" -#: sql_help.c:6109 +#: sql_help.c:6142 msgid "rebuild indexes" msgstr "återskapa index" -#: sql_help.c:6115 +#: sql_help.c:6148 msgid "release a previously defined savepoint" msgstr "frigör en tidigare definierad sparpunkt" -#: sql_help.c:6121 +#: sql_help.c:6154 msgid "restore the value of a run-time parameter to the default value" msgstr "återställ värde av körningsparameter till standardvärdet" -#: sql_help.c:6127 +#: sql_help.c:6160 msgid "remove access privileges" msgstr "ta bort åtkomsträttigheter" -#: sql_help.c:6139 +#: sql_help.c:6172 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "avbryt en transaktion som tidigare förberetts för två-fas-commit" -#: sql_help.c:6145 +#: sql_help.c:6178 msgid "roll back to a savepoint" msgstr "rulla tillbaka till sparpunkt" -#: sql_help.c:6151 +#: sql_help.c:6184 msgid "define a new savepoint within the current transaction" msgstr "definera en ny sparpunkt i den aktuella transaktionen" -#: sql_help.c:6157 +#: sql_help.c:6190 msgid "define or change a security label applied to an object" msgstr "definiera eller ändra en säkerhetsetikett på ett objekt" -#: sql_help.c:6163 sql_help.c:6217 sql_help.c:6253 +#: sql_help.c:6196 sql_help.c:6250 sql_help.c:6286 msgid "retrieve rows from a table or view" msgstr "hämta rader från en tabell eller vy" -#: sql_help.c:6175 +#: sql_help.c:6208 msgid "change a run-time parameter" msgstr "ändra en körningsparameter" -#: sql_help.c:6181 +#: sql_help.c:6214 msgid "set constraint check timing for the current transaction" msgstr "sätt integritetsvillkorstiming för nuvarande transaktion" -#: sql_help.c:6187 +#: sql_help.c:6220 msgid "set the current user identifier of the current session" msgstr "sätt användare för den aktiva sessionen" -#: sql_help.c:6193 +#: sql_help.c:6226 msgid "set the session user identifier and the current user identifier of the current session" msgstr "sätt sessionsanvändaridentifierare och nuvarande användaridentifierare för den aktiva sessionen" -#: sql_help.c:6199 +#: sql_help.c:6232 msgid "set the characteristics of the current transaction" msgstr "sätt inställningar för nuvarande transaktionen" -#: sql_help.c:6205 +#: sql_help.c:6238 msgid "show the value of a run-time parameter" msgstr "visa värde på en körningsparameter" -#: sql_help.c:6223 +#: sql_help.c:6256 msgid "empty a table or set of tables" msgstr "töm en eller flera tabeller" -#: sql_help.c:6229 +#: sql_help.c:6262 msgid "stop listening for a notification" msgstr "sluta att lyssna efter notifiering" -#: sql_help.c:6235 +#: sql_help.c:6268 msgid "update rows of a table" msgstr "uppdatera rader i en tabell" -#: sql_help.c:6241 +#: sql_help.c:6274 msgid "garbage-collect and optionally analyze a database" msgstr "skräpsamla och eventuellt analysera en databas" -#: sql_help.c:6247 +#: sql_help.c:6280 msgid "compute a set of rows" msgstr "beräkna en mängd rader" @@ -6506,7 +6585,7 @@ msgstr "extra kommandoradsargument \"%s\" ignorerad" msgid "could not find own program executable" msgstr "kunde inte hitta det egna programmets körbara fil" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "" "tab completion query failed: %s\n" @@ -6540,54 +6619,3 @@ msgid "" msgstr "" "okänt värde \"%s\" för \"%s\"\n" "Tillgängliga värden är: %s." - -#, c-format -#~ msgid "" -#~ " \\lo_export LOBOID FILE\n" -#~ " \\lo_import FILE [COMMENT]\n" -#~ " \\lo_list[+]\n" -#~ " \\lo_unlink LOBOID large object operations\n" -#~ msgstr "" -#~ " \\lo_export LOBOID FIL\n" -#~ " \\lo_import FIL [KOMMENTAR]\n" -#~ " \\lo_list[+]\n" -#~ " \\lo_unlink LOBOID operationer på stora objekt\n" - -#~ msgid "Source code" -#~ msgstr "Källkod" - -#, c-format -#~ msgid "\\watch cannot be used with COPY" -#~ msgstr "\\watch kan inte användas med COPY" - -#, c-format -#~ msgid "could not change directory to \"%s\": %m" -#~ msgstr "kunde inte byta katalog till \"%s\": %m" - -#, c-format -#~ msgid "could not identify current directory: %m" -#~ msgstr "kunde inte identifiera aktuell katalog: %m" - -#, c-format -#~ msgid "could not read binary \"%s\"" -#~ msgstr "kunde inte läsa binär \"%s\"" - -#, c-format -#~ msgid "could not read symbolic link \"%s\": %m" -#~ msgstr "kan inte läsa symbolisk länk \"%s\": %m" - -#, c-format -#~ msgid "invalid binary \"%s\"" -#~ msgstr "ogiltig binär \"%s\"" - -#~ msgid "match" -#~ msgstr "match" - -#~ msgid "text" -#~ msgstr "text" - -#~ msgid "timezone" -#~ msgstr "tidszon" - -#~ msgid "where direction can be empty or one of:" -#~ msgstr "där riktning kan vara tom eller en av:" diff --git a/src/bin/psql/po/uk.po b/src/bin/psql/po/uk.po index 3d8898f3ec32f..bd64a745d18e1 100644 --- a/src/bin/psql/po/uk.po +++ b/src/bin/psql/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:17+0000\n" -"PO-Revision-Date: 2023-12-19 15:38\n" +"POT-Creation-Date: 2024-09-23 10:48+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/psql.pot\n" -"X-Crowdin-File-ID: 981\n" +"X-Crowdin-File: /REL_17_STABLE/psql.pot\n" +"X-Crowdin-File-ID: 996\n" #: ../../../src/common/logging.c:276 #, c-format @@ -37,33 +37,48 @@ msgstr "деталі: " msgid "hint: " msgstr "підказка: " -#: ../../common/exec.c:172 +#: ../../common/exec.c:174 #, c-format msgid "invalid binary \"%s\": %m" msgstr "невірний бінарний файл \"%s\": %m" -#: ../../common/exec.c:215 +#: ../../common/exec.c:217 #, c-format msgid "could not read binary \"%s\": %m" msgstr "не вдалося прочитати бінарний файл \"%s\": %m" -#: ../../common/exec.c:223 +#: ../../common/exec.c:225 #, c-format msgid "could not find a \"%s\" to execute" msgstr "неможливо знайти \"%s\" для виконання" -#: ../../common/exec.c:250 +#: ../../common/exec.c:252 #, c-format msgid "could not resolve path \"%s\" to absolute form: %m" msgstr "не вдалося знайти абсолютний шлях \"%s\": %m" -#: ../../common/exec.c:412 +#: ../../common/exec.c:382 copy.c:326 +#, c-format +msgid "could not execute command \"%s\": %m" +msgstr "не вдалося виконати команду \"%s\": %m" + +#: ../../common/exec.c:394 +#, c-format +msgid "could not read from command \"%s\": %m" +msgstr "не вдалося прочитати висновок команди \"%s\": %m" + +#: ../../common/exec.c:397 +#, c-format +msgid "no data was returned by command \"%s\"" +msgstr "команда \"%s\" не повернула жодних даних" + +#: ../../common/exec.c:424 #, c-format msgid "%s() failed: %m" msgstr "%s() помилка: %m" -#: ../../common/exec.c:550 ../../common/exec.c:595 ../../common/exec.c:687 -#: command.c:1354 command.c:3439 command.c:3488 command.c:3612 input.c:226 +#: ../../common/exec.c:562 ../../common/exec.c:607 ../../common/exec.c:699 +#: command.c:1372 command.c:3458 command.c:3507 command.c:3632 input.c:225 #: mainloop.c:80 mainloop.c:398 #, c-format msgid "out of memory" @@ -85,7 +100,7 @@ msgstr "неможливо дублювати нульовий покажчик msgid "could not look up effective user ID %ld: %s" msgstr "не можу знайти користувача з ефективним ID %ld: %s" -#: ../../common/username.c:45 command.c:613 +#: ../../common/username.c:45 command.c:616 msgid "user does not exist" msgstr "користувача не існує" @@ -124,11 +139,11 @@ msgstr "дочірній процес перервано через сигнал msgid "child process exited with unrecognized status %d" msgstr "дочірній процес завершився з невизнаним статусом %d" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Запит на скасування відправлений\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Не вдалося надіслати запит на скасування: " @@ -146,341 +161,370 @@ msgstr[3] "(%lu рядка)" msgid "Interrupted\n" msgstr "Перервано\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Неможливо надрукувати вміст таблиці: кількість комірок %lld дорівнює або перевищує максимальне значення %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "Неможливо додати заголовок до вмісту таблиці: кількість колонок %d перевищено.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "Неможливо додати комірку до вмісту таблиці: перевищено загальну кількість комірок %d.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "Неможливо додати комірку до вмісту таблиці: перевищено загальну кількість комірок %lld.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "невірний формат виводу (внутрішня помилка): %d" -#: ../../fe_utils/psqlscan.l:717 +#: ../../fe_utils/psqlscan.l:732 #, c-format msgid "skipping recursive expansion of variable \"%s\"" msgstr "пропуск рекурсивного розгортання змінної \"%s\"" -#: ../../port/thread.c:50 ../../port/thread.c:86 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../port/user.c:43 ../../port/user.c:79 #, c-format msgid "could not look up local user ID %d: %s" msgstr "не вдалося знайти локального користувача з ідентифікатором %d: %s" -#: ../../port/thread.c:55 ../../port/thread.c:91 +#: ../../port/user.c:48 ../../port/user.c:84 #, c-format msgid "local user with ID %d does not exist" msgstr "локального користувача з ідентифікатором %d не існує" -#: command.c:234 +#: command.c:235 #, c-format msgid "invalid command \\%s" msgstr "Невірна команда \\%s" -#: command.c:236 +#: command.c:237 #, c-format msgid "Try \\? for help." msgstr "Спробуйте \\? для отримання довідки." -#: command.c:254 +#: command.c:255 #, c-format msgid "\\%s: extra argument \"%s\" ignored" msgstr "\\%s: зайвий аргумент \"%s\" проігноровано" -#: command.c:306 +#: command.c:307 #, c-format msgid "\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block" msgstr "\\%s команду проігноровано; скористайтесь \\endif або Ctrl-C, щоб вийти з поточного блоку \\if" -#: command.c:611 +#: command.c:614 #, c-format msgid "could not get home directory for user ID %ld: %s" msgstr "неможливо отримати домашню директорію для користувача ID %ld: %s" -#: command.c:630 +#: command.c:633 #, c-format msgid "\\%s: could not change directory to \"%s\": %m" msgstr "\\%s: неможливо змінити директорію на \"%s\": %m" -#: command.c:654 +#: command.c:657 #, c-format msgid "You are currently not connected to a database.\n" msgstr "На даний момент ви від'єднанні від бази даних.\n" -#: command.c:664 +#: command.c:667 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" за аресою \"%s\" на порту \"%s\".\n" -#: command.c:667 +#: command.c:670 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" через сокет в \"%s\" на порту \"%s\".\n" -#: command.c:673 +#: command.c:676 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" на хості \"%s\" (за аресою \"%s\") на порту \"%s\".\n" -#: command.c:676 +#: command.c:679 #, c-format msgid "You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" на хості \"%s\" на порту \"%s\".\n" -#: command.c:1066 command.c:1159 command.c:2682 +#: command.c:1069 command.c:1170 command.c:2675 #, c-format msgid "no query buffer" msgstr "немає буферу запитів" -#: command.c:1099 command.c:5689 +#: command.c:1102 command.c:5771 #, c-format msgid "invalid line number: %s" msgstr "невірний номер рядка: %s" -#: command.c:1237 +#: command.c:1248 msgid "No changes" msgstr "Без змін" -#: command.c:1315 +#: command.c:1333 #, c-format msgid "%s: invalid encoding name or conversion procedure not found" msgstr "%s: невірне ім'я кодування або не знайдено процедуру конверсії" -#: command.c:1350 command.c:2152 command.c:3435 command.c:3632 command.c:5795 -#: common.c:182 common.c:231 common.c:400 common.c:1102 common.c:1120 -#: common.c:1194 common.c:1313 common.c:1351 common.c:1444 common.c:1480 -#: copy.c:486 copy.c:721 help.c:66 large_obj.c:157 large_obj.c:192 -#: large_obj.c:254 startup.c:304 +#: command.c:1368 command.c:2157 command.c:3454 command.c:3652 command.c:5877 +#: common.c:221 common.c:270 common.c:440 common.c:1142 common.c:1160 +#: common.c:1228 common.c:1340 common.c:1378 common.c:1475 common.c:1541 +#: copy.c:486 copy.c:722 large_obj.c:157 large_obj.c:192 large_obj.c:254 +#: startup.c:304 #, c-format msgid "%s" msgstr "%s" -#: command.c:1357 +#: command.c:1375 msgid "There is no previous error." msgstr "Попередня помилка відсутня." -#: command.c:1470 +#: command.c:1488 #, c-format msgid "\\%s: missing right parenthesis" msgstr "\\%s: відсутня права дужка" -#: command.c:1554 command.c:1684 command.c:1988 command.c:2002 command.c:2021 -#: command.c:2203 command.c:2444 command.c:2649 command.c:2689 +#: command.c:1572 command.c:1691 command.c:1995 command.c:2009 command.c:2028 +#: command.c:2196 command.c:2437 command.c:2642 command.c:2682 #, c-format msgid "\\%s: missing required argument" msgstr "\\%s: не вистачає обов'язкового аргументу" -#: command.c:1815 +#: command.c:1822 #, c-format msgid "\\elif: cannot occur after \\else" msgstr "\\elif: не може йти після \\else" -#: command.c:1820 +#: command.c:1827 #, c-format msgid "\\elif: no matching \\if" msgstr "\\elif: немає відповідного \\if" -#: command.c:1884 +#: command.c:1891 #, c-format msgid "\\else: cannot occur after \\else" msgstr "\\else: не може йти після \\else" -#: command.c:1889 +#: command.c:1896 #, c-format msgid "\\else: no matching \\if" msgstr "\\else: немає відповідного \\if" -#: command.c:1929 +#: command.c:1936 #, c-format msgid "\\endif: no matching \\if" msgstr "\\endif: немає відповідного \\if" -#: command.c:2085 +#: command.c:2092 msgid "Query buffer is empty." msgstr "Буфер запиту порожній." -#: command.c:2128 +#: command.c:2135 #, c-format msgid "Enter new password for user \"%s\": " msgstr "Введіть новий пароль користувача \"%s\": " -#: command.c:2132 +#: command.c:2139 msgid "Enter it again: " msgstr "Введіть знову: " -#: command.c:2141 +#: command.c:2148 #, c-format msgid "Passwords didn't match." msgstr "Паролі не співпадають." -#: command.c:2238 +#: command.c:2231 #, c-format msgid "\\%s: could not read value for variable" msgstr "\\%s: не вдалося прочитати значення змінної" -#: command.c:2340 +#: command.c:2333 msgid "Query buffer reset (cleared)." msgstr "Буфер запитів скинуто (очищено)." -#: command.c:2362 +#: command.c:2355 #, c-format msgid "Wrote history to file \"%s\".\n" msgstr "Історію записано до файлу \"%s\".\n" -#: command.c:2449 +#: command.c:2442 #, c-format msgid "\\%s: environment variable name must not contain \"=\"" msgstr "\\%s: змінна середовища не повинна містити \"=\"" -#: command.c:2497 +#: command.c:2490 #, c-format msgid "function name is required" msgstr "необхідне ім'я функції" -#: command.c:2499 +#: command.c:2492 #, c-format msgid "view name is required" msgstr "необхідне ім'я подання" -#: command.c:2621 +#: command.c:2614 msgid "Timing is on." msgstr "Таймер увімкнено." -#: command.c:2623 +#: command.c:2616 msgid "Timing is off." msgstr "Таймер вимкнено." -#: command.c:2709 command.c:2747 command.c:4074 command.c:4077 command.c:4080 -#: command.c:4086 command.c:4088 command.c:4114 command.c:4124 command.c:4136 -#: command.c:4150 command.c:4177 command.c:4235 common.c:78 copy.c:329 -#: copy.c:401 psqlscanslash.l:788 psqlscanslash.l:800 psqlscanslash.l:818 +#: command.c:2702 command.c:2740 command.c:4163 command.c:4166 command.c:4169 +#: command.c:4175 command.c:4177 command.c:4203 command.c:4213 command.c:4225 +#: command.c:4239 command.c:4266 command.c:4324 common.c:77 copy.c:329 +#: copy.c:401 psqlscanslash.l:805 psqlscanslash.l:817 psqlscanslash.l:835 #, c-format msgid "%s: %m" msgstr "%s: %m" -#: command.c:2736 copy.c:388 +#: command.c:2729 copy.c:388 #, c-format msgid "%s: %s" msgstr "%s: %s" -#: command.c:2806 command.c:2852 +#: command.c:2801 command.c:2867 #, c-format msgid "\\watch: interval value is specified more than once" msgstr "\\watch: інтервал зазначається неодноразово" -#: command.c:2816 command.c:2862 +#: command.c:2811 command.c:2877 #, c-format msgid "\\watch: incorrect interval value \"%s\"" msgstr "\\watch: неправильне значення інтервалу \"%s\"" -#: command.c:2826 +#: command.c:2821 #, c-format msgid "\\watch: iteration count is specified more than once" msgstr "\\watch: інтервал зазначається неодноразово" -#: command.c:2836 +#: command.c:2831 #, c-format msgid "\\watch: incorrect iteration count \"%s\"" msgstr "\\watch: неправильна кількість ітерацій \"%s\"" -#: command.c:2843 +#: command.c:2841 +#, c-format +msgid "\\watch: minimum row count specified more than once" +msgstr "\\watch: мінімальна кількість рядків вказана більше одного разу" + +#: command.c:2851 +#, c-format +msgid "\\watch: incorrect minimum row count \"%s\"" +msgstr "\\watch: неправильна мінімальна кількість рядків \"%s\"" + +#: command.c:2858 #, c-format msgid "\\watch: unrecognized parameter \"%s\"" msgstr "\\watch: нерозпізнаний параметр \"%s\"" -#: command.c:3236 startup.c:243 startup.c:293 +#: command.c:3255 startup.c:243 startup.c:293 msgid "Password: " msgstr "Пароль: " -#: command.c:3241 startup.c:290 +#: command.c:3260 startup.c:290 #, c-format msgid "Password for user %s: " msgstr "Пароль користувача %s:" -#: command.c:3297 +#: command.c:3316 #, c-format msgid "Do not give user, host, or port separately when using a connection string" msgstr "Не надайте користувачеві, хосту або порту окремо під час використання рядка підключення" -#: command.c:3332 +#: command.c:3351 #, c-format msgid "No database connection exists to re-use parameters from" msgstr "Не існує підключення до бази даних для повторного використання параметрів" -#: command.c:3638 +#: command.c:3658 #, c-format msgid "Previous connection kept" msgstr "Попереднє підключення триває" -#: command.c:3644 +#: command.c:3664 #, c-format msgid "\\connect: %s" msgstr "\\connect: %s" -#: command.c:3700 +#: command.c:3720 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" за адресою \"%s\" на порту \"%s\".\n" -#: command.c:3703 +#: command.c:3723 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n" msgstr "Ви тепер під'єднані до бази даних \"%s\" як користувач \"%s\" через сокет в \"%s\" на порту \"%s\".\n" -#: command.c:3709 +#: command.c:3729 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n" msgstr "Ви під'єднані до бази даних \"%s\" як користувач \"%s\" на хості \"%s\" (за адресою \"%s\") на порту \"%s\".\n" -#: command.c:3712 +#: command.c:3732 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n" msgstr "Ви тепер під'єднані до бази даних \"%s\" як користувач \"%s\" на хості \"%s\" на порту \"%s\".\n" -#: command.c:3717 +#: command.c:3737 #, c-format msgid "You are now connected to database \"%s\" as user \"%s\".\n" msgstr "Ви тепер під'єднані до бази даних \"%s\" як користувач \"%s\".\n" -#: command.c:3757 +#: command.c:3843 #, c-format msgid "%s (%s, server %s)\n" msgstr "%s (%s, сервер %s)\n" -#: command.c:3770 +#: command.c:3856 #, c-format msgid "WARNING: %s major version %s, server major version %s.\n" " Some psql features might not work.\n" msgstr "УВАГА: мажорна версія %s %s, мажорна версія сервера %s.\n" " Деякі функції psql можуть не працювати.\n" -#: command.c:3807 +#: command.c:3895 #, c-format -msgid "SSL connection (protocol: %s, cipher: %s, compression: %s)\n" -msgstr "З'єднання SSL (протокол: %s, шифр: %s, компресія: %s)\n" +msgid "SSL connection (protocol: %s, cipher: %s, compression: %s, ALPN: %s)\n" +msgstr "З'єднання SSL (протокол: %s, шифр: %s, компресія: %s, ALPN: %s)\n" -#: command.c:3808 command.c:3809 +#: command.c:3896 command.c:3897 msgid "unknown" msgstr "невідомо" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "off" msgstr "вимк" -#: command.c:3810 help.c:42 +#: command.c:3898 help.c:42 msgid "on" msgstr "увімк" -#: command.c:3824 +#: command.c:3899 +msgid "none" +msgstr "нічого" + +#: command.c:3913 #, c-format msgid "GSSAPI-encrypted connection\n" msgstr "З'єднання зашифровано GSSAPI\n" -#: command.c:3844 +#: command.c:3933 #, c-format msgid "WARNING: Console code page (%u) differs from Windows code page (%u)\n" " 8-bit characters might not work correctly. See psql reference\n" @@ -489,187 +533,187 @@ msgstr "УВАГА: Кодова сторінка консолі (%u) відрі " 8-бітові символи можуть працювати неправильно. Детальніше у розділі \n" " \"Нотатки для користувачів Windows\" у документації psql.\n" -#: command.c:3949 +#: command.c:4038 #, c-format msgid "environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number" msgstr "змінна середовища PSQL_EDITOR_LINENUMBER_ARG має бути встановлена, щоб вказувати номер рядка" -#: command.c:3979 +#: command.c:4068 #, c-format msgid "could not start editor \"%s\"" msgstr "неможливо запустити редактор \"%s\"" -#: command.c:3981 +#: command.c:4070 #, c-format msgid "could not start /bin/sh" msgstr "неможливо запустити /bin/sh" -#: command.c:4031 +#: command.c:4120 #, c-format msgid "could not locate temporary directory: %s" msgstr "неможливо знайти тимчасову директорію: %s" -#: command.c:4058 +#: command.c:4147 #, c-format msgid "could not open temporary file \"%s\": %m" msgstr "неможливо відкрити тимчасовий файл \"%s\": %m" -#: command.c:4394 +#: command.c:4483 #, c-format msgid "\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"" msgstr "\\pset: неоднозначна абревіатура \"%s\" відповідає обом \"%s\" і \"%s" -#: command.c:4414 +#: command.c:4503 #, c-format msgid "\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" msgstr "\\pset: дозволені формати: aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped" -#: command.c:4433 +#: command.c:4522 #, c-format msgid "\\pset: allowed line styles are ascii, old-ascii, unicode" msgstr "\\pset: дозволені стилі ліній: ascii, old-ascii, unicode" -#: command.c:4448 +#: command.c:4537 #, c-format msgid "\\pset: allowed Unicode border line styles are single, double" msgstr "\\pset: дозволені стилі ліній рамок Unicode: single, double" -#: command.c:4463 +#: command.c:4552 #, c-format msgid "\\pset: allowed Unicode column line styles are single, double" msgstr "\\pset: дозволені стилі ліній стовпців для Unicode: single, double" -#: command.c:4478 +#: command.c:4567 #, c-format msgid "\\pset: allowed Unicode header line styles are single, double" msgstr "\\pset: дозволені стилі ліній заголовків для Unicode: single, double" -#: command.c:4530 +#: command.c:4619 #, c-format msgid "\\pset: allowed xheader_width values are \"%s\" (default), \"%s\", \"%s\", or a number specifying the exact width" msgstr "\\pset: дозволені значення xheader_width є \"%s\" (за замовчуванням), \"%s\", \"%s\" або число, яке визначає точну ширину" -#: command.c:4547 +#: command.c:4636 #, c-format msgid "\\pset: csv_fieldsep must be a single one-byte character" msgstr "\\pset: csv_fieldsep повинен бути однобайтовим символом" -#: command.c:4552 +#: command.c:4641 #, c-format msgid "\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return" msgstr "\\pset: csv_fieldsep не може бути подвійною лапкою, новим рядком або поверненням каретки" -#: command.c:4690 command.c:4891 +#: command.c:4779 command.c:4980 #, c-format msgid "\\pset: unknown option: %s" msgstr "\\pset: невідомий параметр: %s" -#: command.c:4710 +#: command.c:4799 #, c-format msgid "Border style is %d.\n" msgstr "Стиль рамки %d.\n" -#: command.c:4716 +#: command.c:4805 #, c-format msgid "Target width is unset.\n" msgstr "Цільова ширина не встановлена.\n" -#: command.c:4718 +#: command.c:4807 #, c-format msgid "Target width is %d.\n" msgstr "Цільова ширина %d.\n" -#: command.c:4725 +#: command.c:4814 #, c-format msgid "Expanded display is on.\n" msgstr "Розширене відображення увімкнуто.\n" -#: command.c:4727 +#: command.c:4816 #, c-format msgid "Expanded display is used automatically.\n" msgstr "Розширене відображення використовується автоматично.\n" -#: command.c:4729 +#: command.c:4818 #, c-format msgid "Expanded display is off.\n" msgstr "Розширене відображення вимкнуто.\n" -#: command.c:4736 command.c:4738 command.c:4740 +#: command.c:4825 command.c:4827 command.c:4829 #, c-format msgid "Expanded header width is \"%s\".\n" msgstr "Розширена ширина заголовка \"%s\".\n" -#: command.c:4742 +#: command.c:4831 #, c-format msgid "Expanded header width is %d.\n" msgstr "Розширена ширина заголовка %d.\n" -#: command.c:4748 +#: command.c:4837 #, c-format msgid "Field separator for CSV is \"%s\".\n" msgstr "Розділювач полів CSV: \"%s\".\n" -#: command.c:4756 command.c:4764 +#: command.c:4845 command.c:4853 #, c-format msgid "Field separator is zero byte.\n" msgstr "Розділювач полів - нульовий байт.\n" -#: command.c:4758 +#: command.c:4847 #, c-format msgid "Field separator is \"%s\".\n" msgstr "Розділювач полів \"%s\".\n" -#: command.c:4771 +#: command.c:4860 #, c-format msgid "Default footer is on.\n" msgstr "Нинжній колонтитул увімкнуто за замовчуванням.\n" -#: command.c:4773 +#: command.c:4862 #, c-format msgid "Default footer is off.\n" msgstr "Нинжній колонтитул вимкнуто за замовчуванням.\n" -#: command.c:4779 +#: command.c:4868 #, c-format msgid "Output format is %s.\n" msgstr "Формат виводу %s.\n" -#: command.c:4785 +#: command.c:4874 #, c-format msgid "Line style is %s.\n" msgstr "Стиль лінії %s.\n" -#: command.c:4792 +#: command.c:4881 #, c-format msgid "Null display is \"%s\".\n" msgstr "Null відображається як \"%s\".\n" -#: command.c:4800 +#: command.c:4889 #, c-format msgid "Locale-adjusted numeric output is on.\n" msgstr "Локалізоване виведення чисел ввімкнено.\n" -#: command.c:4802 +#: command.c:4891 #, c-format msgid "Locale-adjusted numeric output is off.\n" msgstr "Локалізоване виведення чисел вимкнено.\n" -#: command.c:4809 +#: command.c:4898 #, c-format msgid "Pager is used for long output.\n" msgstr "Пейджер використовується для виведення довгого тексту.\n" -#: command.c:4811 +#: command.c:4900 #, c-format msgid "Pager is always used.\n" msgstr "Завжди використовується пейджер.\n" -#: command.c:4813 +#: command.c:4902 #, c-format msgid "Pager usage is off.\n" msgstr "Пейджер не використовується.\n" -#: command.c:4819 +#: command.c:4908 #, c-format msgid "Pager won't be used for less than %d line.\n" msgid_plural "Pager won't be used for less than %d lines.\n" @@ -678,240 +722,245 @@ msgstr[1] "Пейджер не буде використовуватися дл msgstr[2] "Пейджер не буде використовуватися для менш ніж %d рядків.\n" msgstr[3] "Пейджер не буде використовуватися для менш ніж %d рядка.\n" -#: command.c:4829 command.c:4839 +#: command.c:4918 command.c:4928 #, c-format msgid "Record separator is zero byte.\n" msgstr "Розділювач записів - нульовий байт.\n" -#: command.c:4831 +#: command.c:4920 #, c-format msgid "Record separator is .\n" msgstr "Розділювач записів: .\n" -#: command.c:4833 +#: command.c:4922 #, c-format msgid "Record separator is \"%s\".\n" msgstr "Розділювач записів: \"%s\".\n" -#: command.c:4846 +#: command.c:4935 #, c-format msgid "Table attributes are \"%s\".\n" msgstr "Табличні атрибути \"%s\".\n" -#: command.c:4849 +#: command.c:4938 #, c-format msgid "Table attributes unset.\n" msgstr "Атрибути таблиць не задані.\n" -#: command.c:4856 +#: command.c:4945 #, c-format msgid "Title is \"%s\".\n" msgstr "Заголовок: \"%s\".\n" -#: command.c:4858 +#: command.c:4947 #, c-format msgid "Title is unset.\n" msgstr "Заголовок не встановлено.\n" -#: command.c:4865 +#: command.c:4954 #, c-format msgid "Tuples only is on.\n" msgstr "Увімкнуто тільки кортежі.\n" -#: command.c:4867 +#: command.c:4956 #, c-format msgid "Tuples only is off.\n" msgstr "Вимкнуто тільки кортежі.\n" -#: command.c:4873 +#: command.c:4962 #, c-format msgid "Unicode border line style is \"%s\".\n" msgstr "Стиль ліній рамки для Unicode: \"%s\".\n" -#: command.c:4879 +#: command.c:4968 #, c-format msgid "Unicode column line style is \"%s\".\n" msgstr "Стиль ліній стовпців для Unicode: \"%s\".\n" -#: command.c:4885 +#: command.c:4974 #, c-format msgid "Unicode header line style is \"%s\".\n" msgstr "Стиль ліній заголовків для Unicode: \"%s\".\n" -#: command.c:5134 +#: command.c:5223 #, c-format msgid "\\!: failed" msgstr "\\!: помилка" -#: command.c:5168 +#: command.c:5257 #, c-format msgid "\\watch cannot be used with an empty query" msgstr "\\watch не може бути використано із пустим запитом" -#: command.c:5200 +#: command.c:5289 #, c-format msgid "could not set timer: %m" msgstr "не вдалося встановити таймер: %m" -#: command.c:5269 +#: command.c:5358 #, c-format msgid "%s\t%s (every %gs)\n" msgstr "%s\t%s (кожні %g сек)\n" -#: command.c:5272 +#: command.c:5361 #, c-format msgid "%s (every %gs)\n" msgstr "%s (кожні %g сек)\n" -#: command.c:5340 +#: command.c:5424 #, c-format msgid "could not wait for signals: %m" msgstr "не вдалося дочекатися сигналів: %m" -#: command.c:5398 command.c:5405 common.c:592 common.c:599 common.c:1083 +#: command.c:5480 command.c:5487 common.c:632 common.c:639 common.c:1123 #, c-format -msgid "********* QUERY **********\n" +msgid "/******** QUERY *********/\n" "%s\n" -"**************************\n\n" -msgstr "********* ЗАПИТ **********\n" +"/************************/\n\n" +msgstr "/******** ЗАПИТ *********/\n" "%s\n" -"**************************\n\n" +"/************************/\n\n" -#: command.c:5584 +#: command.c:5666 #, c-format msgid "\"%s.%s\" is not a view" msgstr "\"%s.%s\" не є поданням" -#: command.c:5600 +#: command.c:5682 #, c-format msgid "could not parse reloptions array" msgstr "неможливо розібрати масив reloptions" -#: common.c:167 +#: common.c:206 #, c-format msgid "cannot escape without active connection" msgstr "не можна вийти без активного з'єднання" -#: common.c:208 +#: common.c:247 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"" msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"" -#: common.c:312 +#: common.c:351 #, c-format msgid "connection to server was lost" msgstr "з'єднання із сервером втрачено" -#: common.c:316 +#: common.c:355 #, c-format msgid "The connection to the server was lost. Attempting reset: " msgstr "З'єднання із сервером втрачено. Спроба перевстановити:" -#: common.c:321 +#: common.c:360 #, c-format msgid "Failed.\n" msgstr "Помилка.\n" -#: common.c:338 +#: common.c:377 #, c-format msgid "Succeeded.\n" msgstr "Вдало.\n" -#: common.c:390 common.c:1021 +#: common.c:430 common.c:1061 #, c-format msgid "unexpected PQresultStatus: %d" msgstr "неочікуваний PQresultStatus: %d" -#: common.c:531 +#: common.c:571 #, c-format msgid "Time: %.3f ms\n" msgstr "Час: %.3f мс\n" -#: common.c:546 +#: common.c:586 #, c-format msgid "Time: %.3f ms (%02d:%06.3f)\n" msgstr "Час: %.3f мс (%02d:%06.3f)\n" -#: common.c:555 +#: common.c:595 #, c-format msgid "Time: %.3f ms (%02d:%02d:%06.3f)\n" msgstr "Час: %.3f мс (%02d:%02d:%06.3f)\n" -#: common.c:562 +#: common.c:602 #, c-format msgid "Time: %.3f ms (%.0f d %02d:%02d:%06.3f)\n" msgstr "Час: %.3f мс (%.0f d %02d:%02d:%06.3f)\n" -#: common.c:586 common.c:643 common.c:1054 describe.c:6214 +#: common.c:626 common.c:683 common.c:1094 describe.c:6192 #, c-format msgid "You are currently not connected to a database." msgstr "На даний момент ви від'єднанні від бази даних." -#: common.c:674 +#: common.c:714 #, c-format msgid "Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n" msgstr "Асинхронне сповіщення \"%s\" з навантаженням \"%s\" отримане від серверного процесу з PID %d.\n" -#: common.c:677 +#: common.c:717 #, c-format msgid "Asynchronous notification \"%s\" received from server process with PID %d.\n" msgstr "Асинхронне сповіщення \"%s\" отримане від серверного процесу з PID %d.\n" -#: common.c:708 +#: common.c:748 #, c-format msgid "could not print result table: %m" msgstr "не вдалося надрукувати таблицю результатів: %m" -#: common.c:728 +#: common.c:768 #, c-format msgid "no rows returned for \\gset" msgstr "немає рядків повернутих для \\gset" -#: common.c:733 +#: common.c:773 #, c-format msgid "more than one row returned for \\gset" msgstr "більш, ніж один рядок повернуто для \\gset" -#: common.c:751 +#: common.c:791 #, c-format msgid "attempt to \\gset into specially treated variable \"%s\" ignored" msgstr "спробу виконати \\gset в спеціальну змінну \"%s\" проігноровано" -#: common.c:1063 +#: common.c:1103 #, c-format -msgid "***(Single step mode: verify command)*******************************************\n" +msgid "/**(Single step mode: verify command)******************************************/\n" "%s\n" -"***(press return to proceed or enter x and return to cancel)********************\n" -msgstr "***(Покроковий режим: перевірка команди)*******************************************\n" +"/**(press return to proceed or enter x and return to cancel)*******************/\n" +msgstr "/**(Однокроковий режим: команда verify)******************************************/\n" "%s\n" -"***(Enter - виповнити; х і Enter - відмінити)********************\n" +"/**(натисніть клавішу Return, щоб продовжити, або введіть x і Return, щоб скасувати.)*******************/\n" -#: common.c:1146 +#: common.c:1180 #, c-format msgid "STATEMENT: %s" msgstr "ІНСТРУКЦІЯ: %s" -#: common.c:1182 +#: common.c:1216 #, c-format msgid "unexpected transaction status (%d)" msgstr "неочікуваний стан транзакції (%d)" -#: common.c:1335 describe.c:2026 +#: common.c:1362 describe.c:2025 msgid "Column" msgstr "Стовпець" -#: common.c:1336 describe.c:170 describe.c:358 describe.c:376 describe.c:1046 -#: describe.c:1200 describe.c:1732 describe.c:1756 describe.c:2027 -#: describe.c:3958 describe.c:4170 describe.c:4409 describe.c:4571 -#: describe.c:5846 +#: common.c:1363 describe.c:169 describe.c:355 describe.c:373 describe.c:1043 +#: describe.c:1201 describe.c:1731 describe.c:1755 describe.c:2026 +#: describe.c:3956 describe.c:4167 describe.c:4404 describe.c:4564 +#: describe.c:5829 msgid "Type" msgstr "Тип" -#: common.c:1385 +#: common.c:1412 #, c-format msgid "The command has no result, or the result has no columns.\n" msgstr "Команда не має результату або результат не має стовпців.\n" +#: common.c:1504 +#, c-format +msgid "fetching results in chunked mode failed" +msgstr "помилка отримання результатів у режимі частинами" + #: copy.c:98 #, c-format msgid "\\copy: arguments required" @@ -927,11 +976,6 @@ msgstr "\\copy: помилка розбору аргументу біля \"%s\" msgid "\\copy: parse error at end of line" msgstr "\\copy: помилка розбору в кінці рядка" -#: copy.c:326 -#, c-format -msgid "could not execute command \"%s\": %m" -msgstr "не вдалося виконати команду \"%s\": %m" - #: copy.c:342 #, c-format msgid "could not stat file \"%s\": %m" @@ -967,338 +1011,339 @@ msgid "Enter data to be copied followed by a newline.\n" msgstr "Введіть дані для копювання, розділяючи переносом рядка.\n" "Завершіть введення за допомогою \"\\.\" або за допомогою сигналу EOF." -#: copy.c:683 +#: copy.c:684 msgid "aborted because of read failure" msgstr "перервано через помилку читання" -#: copy.c:717 +#: copy.c:718 msgid "trying to exit copy mode" msgstr "спроба вийти з режиму копіювання" -#: crosstabview.c:123 +#: crosstabview.c:124 #, c-format msgid "\\crosstabview: statement did not return a result set" msgstr "\\crosstabview: команда не повернула набір з результатами" -#: crosstabview.c:129 +#: crosstabview.c:130 #, c-format msgid "\\crosstabview: query must return at least three columns" msgstr "\\crosstabview: запит має повернути принаймні три стовпці" -#: crosstabview.c:156 +#: crosstabview.c:157 #, c-format msgid "\\crosstabview: vertical and horizontal headers must be different columns" msgstr "\\crosstabview: вертикальні і горизонтальні заголовки повинні бути різними стовпцями" -#: crosstabview.c:172 +#: crosstabview.c:173 #, c-format msgid "\\crosstabview: data column must be specified when query returns more than three columns" msgstr "\\crosstabview: необхідно вказати стовпець даних, коли запит повертає більше трьох стовпців" -#: crosstabview.c:228 +#: crosstabview.c:229 #, c-format msgid "\\crosstabview: maximum number of columns (%d) exceeded" msgstr "\\crosstabview: Максимальна кількість стовпців (%d) перевищена" -#: crosstabview.c:397 +#: crosstabview.c:398 #, c-format msgid "\\crosstabview: query result contains multiple data values for row \"%s\", column \"%s\"" msgstr "\\crosstabview: результат запиту містить кілька значень даних для рядка «%s», стовпця «%s»" -#: crosstabview.c:645 +#: crosstabview.c:646 #, c-format msgid "\\crosstabview: column number %d is out of range 1..%d" msgstr "\\crosstabview: номер стовпця %d поза межами 1..%d" -#: crosstabview.c:670 +#: crosstabview.c:671 #, c-format msgid "\\crosstabview: ambiguous column name: \"%s\"" msgstr "\\crosstabview: неоднозначна назва стовпця: \"%s\"" -#: crosstabview.c:678 +#: crosstabview.c:679 #, c-format msgid "\\crosstabview: column name not found: \"%s\"" msgstr "\\crosstabview: ім'я стовпця не знайдено: \"%s\"" -#: describe.c:87 describe.c:338 describe.c:630 describe.c:807 describe.c:1038 -#: describe.c:1189 describe.c:1264 describe.c:3947 describe.c:4157 -#: describe.c:4407 describe.c:4489 describe.c:4724 describe.c:4932 -#: describe.c:5174 describe.c:5418 describe.c:5488 describe.c:5499 -#: describe.c:5556 describe.c:5960 describe.c:6038 +#: describe.c:87 describe.c:335 describe.c:626 describe.c:802 describe.c:1035 +#: describe.c:1190 describe.c:1264 describe.c:3945 describe.c:4154 +#: describe.c:4402 describe.c:4483 describe.c:4715 describe.c:4921 +#: describe.c:5165 describe.c:5406 describe.c:5475 describe.c:5486 +#: describe.c:5542 describe.c:5941 describe.c:6018 msgid "Schema" msgstr "Схема" -#: describe.c:88 describe.c:167 describe.c:229 describe.c:339 describe.c:631 -#: describe.c:808 describe.c:930 describe.c:1039 describe.c:1265 -#: describe.c:3948 describe.c:4158 describe.c:4323 describe.c:4408 -#: describe.c:4490 describe.c:4653 describe.c:4725 describe.c:4933 -#: describe.c:5046 describe.c:5175 describe.c:5419 describe.c:5489 -#: describe.c:5500 describe.c:5557 describe.c:5756 describe.c:5827 -#: describe.c:6036 describe.c:6265 describe.c:6573 +#: describe.c:88 describe.c:166 describe.c:227 describe.c:336 describe.c:627 +#: describe.c:803 describe.c:924 describe.c:1036 describe.c:1265 +#: describe.c:3946 describe.c:4155 describe.c:4319 describe.c:4403 +#: describe.c:4484 describe.c:4645 describe.c:4716 describe.c:4922 +#: describe.c:5038 describe.c:5166 describe.c:5407 describe.c:5476 +#: describe.c:5487 describe.c:5543 describe.c:5740 describe.c:5810 +#: describe.c:6016 describe.c:6243 describe.c:6551 msgid "Name" msgstr "Назва" -#: describe.c:89 describe.c:351 describe.c:369 +#: describe.c:89 describe.c:348 describe.c:366 msgid "Result data type" msgstr "Тип даних результату" -#: describe.c:90 describe.c:352 describe.c:370 +#: describe.c:90 describe.c:349 describe.c:367 msgid "Argument data types" msgstr "Типи даних аргументів" -#: describe.c:98 describe.c:105 describe.c:178 describe.c:243 describe.c:418 -#: describe.c:662 describe.c:823 describe.c:974 describe.c:1267 describe.c:2047 -#: describe.c:3676 describe.c:4002 describe.c:4204 describe.c:4347 -#: describe.c:4421 describe.c:4499 describe.c:4666 describe.c:4844 -#: describe.c:4982 describe.c:5055 describe.c:5176 describe.c:5327 -#: describe.c:5369 describe.c:5435 describe.c:5492 describe.c:5501 -#: describe.c:5558 describe.c:5774 describe.c:5849 describe.c:5974 -#: describe.c:6039 describe.c:7093 +#: describe.c:98 describe.c:105 describe.c:177 describe.c:241 describe.c:415 +#: describe.c:658 describe.c:818 describe.c:972 describe.c:1267 describe.c:2046 +#: describe.c:3676 describe.c:4000 describe.c:4201 describe.c:4343 +#: describe.c:4416 describe.c:4493 describe.c:4658 describe.c:4834 +#: describe.c:4975 describe.c:5047 describe.c:5167 describe.c:5317 +#: describe.c:5358 describe.c:5423 describe.c:5479 describe.c:5488 +#: describe.c:5544 describe.c:5758 describe.c:5832 describe.c:5955 +#: describe.c:6019 describe.c:7078 msgid "Description" msgstr "Опис" -#: describe.c:128 +#: describe.c:127 msgid "List of aggregate functions" msgstr "Перелік агрегатних функцій" -#: describe.c:153 +#: describe.c:152 #, c-format msgid "The server (version %s) does not support access methods." msgstr "Сервер (версія %s) не підтримує методи доступу." -#: describe.c:168 +#: describe.c:167 msgid "Index" msgstr "Індекс" -#: describe.c:169 describe.c:3966 describe.c:4183 describe.c:5961 +#: describe.c:168 describe.c:3964 describe.c:4180 describe.c:5942 msgid "Table" msgstr "Таблиця" -#: describe.c:177 describe.c:5758 +#: describe.c:176 describe.c:5742 msgid "Handler" msgstr "Обробник" -#: describe.c:201 +#: describe.c:199 msgid "List of access methods" msgstr "Список методів доступу" -#: describe.c:230 describe.c:404 describe.c:655 describe.c:931 describe.c:1188 -#: describe.c:3959 describe.c:4159 describe.c:4324 describe.c:4655 -#: describe.c:5047 describe.c:5757 describe.c:5828 describe.c:6266 -#: describe.c:6454 describe.c:6574 describe.c:6733 describe.c:6819 -#: describe.c:7081 +#: describe.c:228 describe.c:401 describe.c:651 describe.c:925 describe.c:1189 +#: describe.c:3957 describe.c:4156 describe.c:4320 describe.c:4647 +#: describe.c:5039 describe.c:5741 describe.c:5811 describe.c:6244 +#: describe.c:6431 describe.c:6552 describe.c:6722 describe.c:6807 +#: describe.c:7066 msgid "Owner" msgstr "Власник" -#: describe.c:231 +#: describe.c:229 msgid "Location" msgstr "Розташування" -#: describe.c:241 describe.c:3517 describe.c:3858 +#: describe.c:239 describe.c:3517 describe.c:3857 msgid "Options" msgstr "Параметри" -#: describe.c:242 describe.c:653 describe.c:972 describe.c:4001 +#: describe.c:240 describe.c:649 describe.c:970 describe.c:3999 msgid "Size" msgstr "Розмір" -#: describe.c:266 +#: describe.c:263 msgid "List of tablespaces" msgstr "Список табличних просторів" -#: describe.c:311 +#: describe.c:308 #, c-format msgid "\\df only takes [anptwS+] as options" msgstr "\\df приймає в якості параметрів тільки [anptwS+]" -#: describe.c:319 +#: describe.c:316 #, c-format msgid "\\df does not take a \"%c\" option with server version %s" msgstr "\\df не приймає параметр \"%c\" із сервером версії %s" #. translator: "agg" is short for "aggregate" -#: describe.c:354 describe.c:372 +#: describe.c:351 describe.c:369 msgid "agg" msgstr "агр." -#: describe.c:355 describe.c:373 +#: describe.c:352 describe.c:370 msgid "window" msgstr "вікно" -#: describe.c:356 +#: describe.c:353 msgid "proc" msgstr "проц" -#: describe.c:357 describe.c:375 +#: describe.c:354 describe.c:372 msgid "func" msgstr "функ" -#: describe.c:374 describe.c:1397 +#: describe.c:371 describe.c:1397 msgid "trigger" msgstr "тригер" -#: describe.c:386 +#: describe.c:383 msgid "immutable" msgstr "постійна" -#: describe.c:387 +#: describe.c:384 msgid "stable" msgstr "стабільна" -#: describe.c:388 +#: describe.c:385 msgid "volatile" msgstr "мінлива" -#: describe.c:389 +#: describe.c:386 msgid "Volatility" msgstr "Мінливість" -#: describe.c:397 +#: describe.c:394 msgid "restricted" msgstr "обмежений" -#: describe.c:398 +#: describe.c:395 msgid "safe" msgstr "безпечний" -#: describe.c:399 +#: describe.c:396 msgid "unsafe" msgstr "небезпечний" -#: describe.c:400 +#: describe.c:397 msgid "Parallel" msgstr "Паралельність" -#: describe.c:405 +#: describe.c:402 msgid "definer" msgstr "визначник" -#: describe.c:406 +#: describe.c:403 msgid "invoker" msgstr "викликач" -#: describe.c:407 +#: describe.c:404 msgid "Security" msgstr "Безпека" -#: describe.c:412 +#: describe.c:409 msgid "Language" msgstr "Мова" -#: describe.c:415 describe.c:652 +#: describe.c:412 describe.c:648 msgid "Internal name" msgstr "Внутрішнє назва" -#: describe.c:589 +#: describe.c:585 msgid "List of functions" msgstr "Список функцій" -#: describe.c:654 +#: describe.c:650 msgid "Elements" msgstr "Елементи" -#: describe.c:706 +#: describe.c:701 msgid "List of data types" msgstr "Список типів даних" -#: describe.c:809 +#: describe.c:804 msgid "Left arg type" msgstr "Тип лівого аргумента" -#: describe.c:810 +#: describe.c:805 msgid "Right arg type" msgstr "Тип правого аргумента" -#: describe.c:811 +#: describe.c:806 msgid "Result type" msgstr "Результуючий тип" -#: describe.c:816 describe.c:4661 describe.c:4827 describe.c:5326 -#: describe.c:7010 describe.c:7014 +#: describe.c:811 describe.c:4653 describe.c:4817 describe.c:5316 +#: describe.c:6996 describe.c:7000 msgid "Function" msgstr "Функція" -#: describe.c:897 +#: describe.c:891 msgid "List of operators" msgstr "Список операторів" -#: describe.c:932 +#: describe.c:926 msgid "Encoding" msgstr "Кодування" -#: describe.c:936 describe.c:940 +#: describe.c:930 describe.c:934 msgid "Locale Provider" msgstr "Постачальник локалі" -#: describe.c:944 describe.c:4947 +#: describe.c:938 describe.c:4936 msgid "Collate" msgstr "Порядок сортування" -#: describe.c:945 describe.c:4948 +#: describe.c:939 describe.c:4937 msgid "Ctype" msgstr "Ctype" -#: describe.c:949 describe.c:953 describe.c:4953 describe.c:4957 -msgid "ICU Locale" -msgstr "Локалізація ICU" +#: describe.c:943 describe.c:947 describe.c:951 describe.c:4942 describe.c:4946 +#: describe.c:4950 +msgid "Locale" +msgstr "Локаль" -#: describe.c:957 describe.c:961 describe.c:4962 describe.c:4966 +#: describe.c:955 describe.c:959 describe.c:4955 describe.c:4959 msgid "ICU Rules" msgstr "Правила ICU" -#: describe.c:973 +#: describe.c:971 msgid "Tablespace" msgstr "Табличний простір" -#: describe.c:999 +#: describe.c:996 msgid "List of databases" msgstr "Список баз даних" -#: describe.c:1040 describe.c:1191 describe.c:3949 +#: describe.c:1037 describe.c:1192 describe.c:3947 msgid "table" msgstr "таблиця" -#: describe.c:1041 describe.c:3950 +#: describe.c:1038 describe.c:3948 msgid "view" msgstr "подання" -#: describe.c:1042 describe.c:3951 +#: describe.c:1039 describe.c:3949 msgid "materialized view" msgstr "матеріалізоване подання" -#: describe.c:1043 describe.c:1193 describe.c:3953 +#: describe.c:1040 describe.c:1194 describe.c:3951 msgid "sequence" msgstr "послідовність" -#: describe.c:1044 describe.c:3955 +#: describe.c:1041 describe.c:3953 msgid "foreign table" msgstr "зовнішня таблиця" -#: describe.c:1045 describe.c:3956 describe.c:4168 +#: describe.c:1042 describe.c:3954 describe.c:4165 msgid "partitioned table" msgstr "секційна таблиця" -#: describe.c:1056 +#: describe.c:1058 msgid "Column privileges" msgstr "Права для стовпців" -#: describe.c:1087 describe.c:1121 +#: describe.c:1089 describe.c:1123 msgid "Policies" msgstr "Політики" -#: describe.c:1150 describe.c:4577 describe.c:6678 +#: describe.c:1151 describe.c:4570 describe.c:6667 msgid "Access privileges" msgstr "Права доступу" -#: describe.c:1195 +#: describe.c:1196 msgid "function" msgstr "функція" -#: describe.c:1197 +#: describe.c:1198 msgid "type" msgstr "тип" -#: describe.c:1199 +#: describe.c:1200 msgid "schema" msgstr "схема" @@ -1330,293 +1375,293 @@ msgstr "сімейство операторів" msgid "rule" msgstr "правило" -#: describe.c:1421 +#: describe.c:1420 msgid "Object descriptions" msgstr "Опис об'єкту" -#: describe.c:1486 describe.c:4074 +#: describe.c:1485 describe.c:4072 #, c-format msgid "Did not find any relation named \"%s\"." msgstr "Не знайдено жодного відношення під назвою \"%s\"." -#: describe.c:1489 describe.c:4077 +#: describe.c:1488 describe.c:4075 #, c-format msgid "Did not find any relations." msgstr "Не знайдено жодного відношення." -#: describe.c:1685 +#: describe.c:1684 #, c-format msgid "Did not find any relation with OID %s." msgstr "Не знайдено жодного відношення з OID %s." -#: describe.c:1733 describe.c:1757 +#: describe.c:1732 describe.c:1756 msgid "Start" msgstr "Початок" -#: describe.c:1734 describe.c:1758 +#: describe.c:1733 describe.c:1757 msgid "Minimum" msgstr "Мінімум" -#: describe.c:1735 describe.c:1759 +#: describe.c:1734 describe.c:1758 msgid "Maximum" msgstr "Максимум" -#: describe.c:1736 describe.c:1760 +#: describe.c:1735 describe.c:1759 msgid "Increment" msgstr "Приріст" -#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4493 -#: describe.c:4838 describe.c:4971 describe.c:4976 describe.c:6721 +#: describe.c:1736 describe.c:1760 describe.c:1889 describe.c:4487 +#: describe.c:4828 describe.c:4964 describe.c:4969 describe.c:6710 msgid "yes" msgstr "так" -#: describe.c:1738 describe.c:1762 describe.c:1891 describe.c:4493 -#: describe.c:4835 describe.c:4971 describe.c:6722 +#: describe.c:1737 describe.c:1761 describe.c:1890 describe.c:4487 +#: describe.c:4825 describe.c:4964 describe.c:6711 msgid "no" msgstr "ні" -#: describe.c:1739 describe.c:1763 +#: describe.c:1738 describe.c:1762 msgid "Cycles?" msgstr "Цикли?" -#: describe.c:1740 describe.c:1764 +#: describe.c:1739 describe.c:1763 msgid "Cache" msgstr "Кеш" -#: describe.c:1805 +#: describe.c:1804 #, c-format msgid "Owned by: %s" msgstr "Власник: %s" -#: describe.c:1809 +#: describe.c:1808 #, c-format msgid "Sequence for identity column: %s" msgstr "Послідовність для стовпця identity: %s" -#: describe.c:1817 +#: describe.c:1816 #, c-format msgid "Unlogged sequence \"%s.%s\"" msgstr "Послідовність без журналювання \"%s.%s\"" -#: describe.c:1820 +#: describe.c:1819 #, c-format msgid "Sequence \"%s.%s\"" msgstr "Послідовність \"%s.%s\"" -#: describe.c:1963 +#: describe.c:1962 #, c-format msgid "Unlogged table \"%s.%s\"" msgstr "Таблиця без журналювання \"%s.%s\"" -#: describe.c:1966 +#: describe.c:1965 #, c-format msgid "Table \"%s.%s\"" msgstr "Таблиця \"%s.%s\"" -#: describe.c:1970 +#: describe.c:1969 #, c-format msgid "View \"%s.%s\"" msgstr "Подання \"%s.%s\"" -#: describe.c:1975 +#: describe.c:1974 #, c-format msgid "Unlogged materialized view \"%s.%s\"" msgstr "Матеріалізоване подання без журналювання \"%s.%s\"" -#: describe.c:1978 +#: describe.c:1977 #, c-format msgid "Materialized view \"%s.%s\"" msgstr "Матеріалізоване подання \"%s.%s\"" -#: describe.c:1983 +#: describe.c:1982 #, c-format msgid "Unlogged index \"%s.%s\"" msgstr "Індекс без журналювання \"%s.%s\"" -#: describe.c:1986 +#: describe.c:1985 #, c-format msgid "Index \"%s.%s\"" msgstr "Індекс \"%s.%s\"" -#: describe.c:1991 +#: describe.c:1990 #, c-format msgid "Unlogged partitioned index \"%s.%s\"" msgstr "Секційний індекс без журналювання \"%s.%s\"" -#: describe.c:1994 +#: describe.c:1993 #, c-format msgid "Partitioned index \"%s.%s\"" msgstr "Секційний індекс \"%s.%s\"" -#: describe.c:1998 +#: describe.c:1997 #, c-format msgid "TOAST table \"%s.%s\"" msgstr "Таблиця TOAST \"%s.%s\"" -#: describe.c:2002 +#: describe.c:2001 #, c-format msgid "Composite type \"%s.%s\"" msgstr "Композитний тип \"%s.%s\"" -#: describe.c:2006 +#: describe.c:2005 #, c-format msgid "Foreign table \"%s.%s\"" msgstr "Зовнішня таблиця \"%s.%s\"" -#: describe.c:2011 +#: describe.c:2010 #, c-format msgid "Unlogged partitioned table \"%s.%s\"" msgstr "Секційна таблиця без журналювання \"%s.%s\"" -#: describe.c:2014 +#: describe.c:2013 #, c-format msgid "Partitioned table \"%s.%s\"" msgstr "Секційна таблиця \"%s.%s\"" -#: describe.c:2030 describe.c:4410 +#: describe.c:2029 describe.c:4405 msgid "Collation" msgstr "Сортування" -#: describe.c:2031 describe.c:4411 +#: describe.c:2030 describe.c:4406 msgid "Nullable" msgstr "Обнуляється" -#: describe.c:2032 describe.c:4412 +#: describe.c:2031 describe.c:4407 msgid "Default" msgstr "За замовчуванням" -#: describe.c:2035 +#: describe.c:2034 msgid "Key?" msgstr "Ключ?" -#: describe.c:2037 describe.c:4732 describe.c:4743 +#: describe.c:2036 describe.c:4723 describe.c:4734 msgid "Definition" msgstr "Визначення" -#: describe.c:2039 describe.c:5773 describe.c:5848 describe.c:5914 -#: describe.c:5973 +#: describe.c:2038 describe.c:5757 describe.c:5831 describe.c:5896 +#: describe.c:5954 msgid "FDW options" msgstr "Налаштування FDW" -#: describe.c:2041 +#: describe.c:2040 msgid "Storage" msgstr "Сховище" -#: describe.c:2043 +#: describe.c:2042 msgid "Compression" msgstr "Стискання" -#: describe.c:2045 +#: describe.c:2044 msgid "Stats target" msgstr "Статистична ціль" -#: describe.c:2181 +#: describe.c:2180 #, c-format msgid "Partition of: %s %s%s" msgstr "Розділ: %s %s%s" -#: describe.c:2194 +#: describe.c:2193 msgid "No partition constraint" msgstr "Відсутнє розділове обмеження" -#: describe.c:2196 +#: describe.c:2195 #, c-format msgid "Partition constraint: %s" msgstr "Обмеження секції: %s" -#: describe.c:2220 +#: describe.c:2219 #, c-format msgid "Partition key: %s" msgstr "Ключ розділу: %s" -#: describe.c:2246 +#: describe.c:2245 #, c-format msgid "Owning table: \"%s.%s\"" msgstr "Таблиця, що володіє: \"%s.%s\"" -#: describe.c:2315 +#: describe.c:2314 msgid "primary key, " msgstr "первинний ключ," -#: describe.c:2318 +#: describe.c:2317 msgid "unique" msgstr "унікальний" -#: describe.c:2320 +#: describe.c:2319 msgid " nulls not distinct" msgstr " nulls не відрізняються" -#: describe.c:2321 +#: describe.c:2320 msgid ", " msgstr ", " -#: describe.c:2328 +#: describe.c:2327 #, c-format msgid "for table \"%s.%s\"" msgstr "для таблиці \"%s.%s\"" -#: describe.c:2332 +#: describe.c:2331 #, c-format msgid ", predicate (%s)" msgstr ", предикат (%s)" -#: describe.c:2335 +#: describe.c:2334 msgid ", clustered" msgstr ", кластеризовано" -#: describe.c:2338 +#: describe.c:2337 msgid ", invalid" msgstr ", недійсний" -#: describe.c:2341 +#: describe.c:2340 msgid ", deferrable" msgstr ", відтермінований" -#: describe.c:2344 +#: describe.c:2343 msgid ", initially deferred" msgstr ", від початку відтермінований" -#: describe.c:2347 +#: describe.c:2346 msgid ", replica identity" msgstr ", ідентичність репліки" -#: describe.c:2401 +#: describe.c:2400 msgid "Indexes:" msgstr "Індекси:" -#: describe.c:2484 +#: describe.c:2483 msgid "Check constraints:" msgstr "Обмеження перевірки:" -#: describe.c:2552 +#: describe.c:2551 msgid "Foreign-key constraints:" msgstr "Обмеження зовнішнього ключа:" -#: describe.c:2615 +#: describe.c:2614 msgid "Referenced by:" msgstr "Посилання ззовні:" -#: describe.c:2665 +#: describe.c:2664 msgid "Policies:" msgstr "Політики:" -#: describe.c:2668 +#: describe.c:2667 msgid "Policies (forced row security enabled):" msgstr "Політики (посилений захист рядків активовано):" -#: describe.c:2671 +#: describe.c:2670 msgid "Policies (row security enabled): (none)" msgstr "Політики (захист рядків ввімкнуто): (ні)" -#: describe.c:2674 +#: describe.c:2673 msgid "Policies (forced row security enabled): (none)" msgstr "Політики (посилений захист рядків ввімкнуто): (ні)" -#: describe.c:2677 +#: describe.c:2676 msgid "Policies (row security disabled):" msgstr "Політики (захист рядків вимкнуто):" -#: describe.c:2737 describe.c:2841 +#: describe.c:2736 describe.c:2841 msgid "Statistics objects:" msgstr "Об'єкти статистики:" @@ -1636,7 +1681,7 @@ msgstr "Правила, що завжди працюють:" msgid "Rules firing on replica only:" msgstr "Правила, що працюють тільки на репліці:" -#: describe.c:3031 describe.c:5109 +#: describe.c:3031 describe.c:5100 msgid "Publications:" msgstr "Публікації:" @@ -1735,7 +1780,7 @@ msgstr ", табличний простір \"%s\"" msgid "List of roles" msgstr "Список ролей" -#: describe.c:3672 describe.c:3841 +#: describe.c:3672 describe.c:3840 msgid "Role name" msgstr "Ім'я ролі" @@ -1815,673 +1860,680 @@ msgstr "Не знайдено жодного параметру для ролі msgid "Did not find any settings." msgstr "Не знайдено жодного параметру." -#: describe.c:3812 +#: describe.c:3811 msgid "List of settings" msgstr "Список параметрів" -#: describe.c:3842 +#: describe.c:3841 msgid "Member of" msgstr "Член" -#: describe.c:3859 +#: describe.c:3858 msgid "Grantor" msgstr "Надавач" -#: describe.c:3886 +#: describe.c:3884 msgid "List of role grants" msgstr "Перелік наданих ролей" -#: describe.c:3952 +#: describe.c:3950 msgid "index" msgstr "індекс" -#: describe.c:3954 +#: describe.c:3952 msgid "TOAST table" msgstr "Таблиця TOAST" -#: describe.c:3957 describe.c:4169 +#: describe.c:3955 describe.c:4166 msgid "partitioned index" msgstr "секційний індекс" -#: describe.c:3977 +#: describe.c:3975 msgid "permanent" msgstr "постійна" -#: describe.c:3978 +#: describe.c:3976 msgid "temporary" msgstr "тимчасова" -#: describe.c:3979 +#: describe.c:3977 msgid "unlogged" msgstr "нежурнальована" -#: describe.c:3980 +#: describe.c:3978 msgid "Persistence" msgstr "Стійкість" -#: describe.c:3996 +#: describe.c:3994 msgid "Access method" msgstr "Метод доступу" -#: describe.c:4082 +#: describe.c:4079 msgid "List of relations" msgstr "Список відношень" -#: describe.c:4130 +#: describe.c:4127 #, c-format msgid "The server (version %s) does not support declarative table partitioning." msgstr "Сервер (версія %s) не підтримує декларативне секціонування таблиць." -#: describe.c:4141 +#: describe.c:4138 msgid "List of partitioned indexes" msgstr "Список секційних індексів" -#: describe.c:4143 +#: describe.c:4140 msgid "List of partitioned tables" msgstr "Список секційних таблиць" -#: describe.c:4147 +#: describe.c:4144 msgid "List of partitioned relations" msgstr "Список секційних відношень" -#: describe.c:4178 +#: describe.c:4175 msgid "Parent name" msgstr "Батьківська назва" -#: describe.c:4191 +#: describe.c:4188 msgid "Leaf partition size" msgstr "Розмір дочірньої секції" -#: describe.c:4194 describe.c:4200 +#: describe.c:4191 describe.c:4197 msgid "Total size" msgstr "Загальний розмір" -#: describe.c:4325 +#: describe.c:4321 msgid "Trusted" msgstr "Надійний" -#: describe.c:4334 +#: describe.c:4330 msgid "Internal language" msgstr "Внутрішня мова" -#: describe.c:4335 +#: describe.c:4331 msgid "Call handler" msgstr "Обробник виклику" -#: describe.c:4336 describe.c:5759 +#: describe.c:4332 describe.c:5743 msgid "Validator" msgstr "Функція перевірки" -#: describe.c:4337 +#: describe.c:4333 msgid "Inline handler" msgstr "Оброблювач впровадженого коду" -#: describe.c:4372 +#: describe.c:4367 msgid "List of languages" msgstr "Список мов" -#: describe.c:4413 +#: describe.c:4408 msgid "Check" msgstr "Перевірка" -#: describe.c:4457 +#: describe.c:4451 msgid "List of domains" msgstr "Список доменів" -#: describe.c:4491 +#: describe.c:4485 msgid "Source" msgstr "Джерело" -#: describe.c:4492 +#: describe.c:4486 msgid "Destination" msgstr "Призначення" -#: describe.c:4494 describe.c:6723 +#: describe.c:4488 describe.c:6712 msgid "Default?" msgstr "За замовчуванням?" -#: describe.c:4536 +#: describe.c:4529 msgid "List of conversions" msgstr "Список перетворень" -#: describe.c:4564 +#: describe.c:4557 msgid "Parameter" msgstr "Параметр" -#: describe.c:4565 +#: describe.c:4558 msgid "Value" msgstr "Значення" -#: describe.c:4572 +#: describe.c:4565 msgid "Context" msgstr "Контекст" -#: describe.c:4605 +#: describe.c:4597 msgid "List of configuration parameters" msgstr "Список параметрів конфігурації" -#: describe.c:4607 +#: describe.c:4599 msgid "List of non-default configuration parameters" msgstr "Список параметрів конфігурації не за замовчуванням" -#: describe.c:4634 +#: describe.c:4626 #, c-format msgid "The server (version %s) does not support event triggers." msgstr "Сервер (версія %s) не підтримує тригери подій." -#: describe.c:4654 +#: describe.c:4646 msgid "Event" msgstr "Подія" -#: describe.c:4656 +#: describe.c:4648 msgid "enabled" msgstr "увімкнено" -#: describe.c:4657 +#: describe.c:4649 msgid "replica" msgstr "репліка" -#: describe.c:4658 +#: describe.c:4650 msgid "always" msgstr "завжди" -#: describe.c:4659 +#: describe.c:4651 msgid "disabled" msgstr "вимкнено" -#: describe.c:4660 describe.c:6575 +#: describe.c:4652 describe.c:6553 msgid "Enabled" msgstr "Увімкнено" -#: describe.c:4662 +#: describe.c:4654 msgid "Tags" msgstr "Теги" -#: describe.c:4686 +#: describe.c:4677 msgid "List of event triggers" msgstr "Список тригерів подій" -#: describe.c:4713 +#: describe.c:4704 #, c-format msgid "The server (version %s) does not support extended statistics." msgstr "Сервер (версія %s) не підтримує розширену статистику." -#: describe.c:4750 +#: describe.c:4741 msgid "Ndistinct" msgstr "Ndistinct" -#: describe.c:4751 +#: describe.c:4742 msgid "Dependencies" msgstr "Залежності" -#: describe.c:4761 +#: describe.c:4752 msgid "MCV" msgstr "MCV" -#: describe.c:4785 +#: describe.c:4775 msgid "List of extended statistics" msgstr "Список розширеної статистики" -#: describe.c:4812 +#: describe.c:4802 msgid "Source type" msgstr "Початковий тип" -#: describe.c:4813 +#: describe.c:4803 msgid "Target type" msgstr "Тип цілі" -#: describe.c:4837 +#: describe.c:4827 msgid "in assignment" msgstr "у призначенні" -#: describe.c:4839 +#: describe.c:4829 msgid "Implicit?" msgstr "Приховане?" -#: describe.c:4898 +#: describe.c:4887 msgid "List of casts" msgstr "Список приведення типів" -#: describe.c:4938 describe.c:4942 +#: describe.c:4927 describe.c:4931 msgid "Provider" msgstr "Постачальник" -#: describe.c:4972 describe.c:4977 +#: describe.c:4965 describe.c:4970 msgid "Deterministic?" msgstr "Детермінований?" -#: describe.c:5017 +#: describe.c:5009 msgid "List of collations" msgstr "Список правил сортування" -#: describe.c:5079 +#: describe.c:5070 msgid "List of schemas" msgstr "Список схем" -#: describe.c:5196 +#: describe.c:5186 msgid "List of text search parsers" msgstr "Список парсерів текстового пошуку" -#: describe.c:5246 +#: describe.c:5236 #, c-format msgid "Did not find any text search parser named \"%s\"." msgstr "Не знайдено жодного парсера текстового пошуку \"%s\"." -#: describe.c:5249 +#: describe.c:5239 #, c-format msgid "Did not find any text search parsers." msgstr "Не знайдено жодного парсера текстового пошуку." -#: describe.c:5324 +#: describe.c:5314 msgid "Start parse" msgstr "Почати розбір" -#: describe.c:5325 +#: describe.c:5315 msgid "Method" msgstr "Метод" -#: describe.c:5329 +#: describe.c:5319 msgid "Get next token" msgstr "Отримати наступний токен" -#: describe.c:5331 +#: describe.c:5321 msgid "End parse" msgstr "Закінчити розбір" -#: describe.c:5333 +#: describe.c:5323 msgid "Get headline" msgstr "Отримати заголовок" -#: describe.c:5335 +#: describe.c:5325 msgid "Get token types" msgstr "Отримати типи токенів" -#: describe.c:5346 +#: describe.c:5335 #, c-format msgid "Text search parser \"%s.%s\"" msgstr "Парсер текстового пошуку \"%s.%s\"" -#: describe.c:5349 +#: describe.c:5338 #, c-format msgid "Text search parser \"%s\"" msgstr "Парсер текстового пошуку \"%s\"" -#: describe.c:5368 +#: describe.c:5357 msgid "Token name" msgstr "Ім'я токену" -#: describe.c:5382 +#: describe.c:5370 #, c-format msgid "Token types for parser \"%s.%s\"" msgstr "Типи токенів для парсера \"%s.%s\"" -#: describe.c:5385 +#: describe.c:5373 #, c-format msgid "Token types for parser \"%s\"" msgstr "Типи токенів для парсера \"%s\"" -#: describe.c:5429 +#: describe.c:5417 msgid "Template" msgstr "Шаблон" -#: describe.c:5430 +#: describe.c:5418 msgid "Init options" msgstr "Параметри ініціалізації" -#: describe.c:5457 +#: describe.c:5444 msgid "List of text search dictionaries" msgstr "Список словників текстового пошуку" -#: describe.c:5490 +#: describe.c:5477 msgid "Init" msgstr "Ініціалізація" -#: describe.c:5491 +#: describe.c:5478 msgid "Lexize" msgstr "Виділення лексем" -#: describe.c:5523 +#: describe.c:5509 msgid "List of text search templates" msgstr "Список шаблонів текстового пошуку" -#: describe.c:5578 +#: describe.c:5563 msgid "List of text search configurations" msgstr "Список конфігурацій текстового пошуку" -#: describe.c:5629 +#: describe.c:5614 #, c-format msgid "Did not find any text search configuration named \"%s\"." msgstr "Не знайдено жодної конфігурації текстового пошуку під назвою \"%s\"." -#: describe.c:5632 +#: describe.c:5617 #, c-format msgid "Did not find any text search configurations." msgstr "Не знайдено жодної конфігурації текствого пошуку." -#: describe.c:5698 +#: describe.c:5683 msgid "Token" msgstr "Токен" -#: describe.c:5699 +#: describe.c:5684 msgid "Dictionaries" msgstr "Словники" -#: describe.c:5710 +#: describe.c:5695 #, c-format msgid "Text search configuration \"%s.%s\"" msgstr "Конфігурація пошуку тексту \"%s.%s\"" -#: describe.c:5713 +#: describe.c:5698 #, c-format msgid "Text search configuration \"%s\"" msgstr "Конфігурація пошуку тексту \"%s\"" -#: describe.c:5717 +#: describe.c:5702 #, c-format msgid "\n" "Parser: \"%s.%s\"" msgstr "\n" "Парсер: \"%s.%s\"" -#: describe.c:5720 +#: describe.c:5705 #, c-format msgid "\n" "Parser: \"%s\"" msgstr "\n" "Парсер: \"%s\"" -#: describe.c:5801 +#: describe.c:5784 msgid "List of foreign-data wrappers" msgstr "Список джерел сторонніх даних" -#: describe.c:5829 +#: describe.c:5812 msgid "Foreign-data wrapper" msgstr "Джерело сторонніх даних" -#: describe.c:5847 describe.c:6037 +#: describe.c:5830 describe.c:6017 msgid "Version" msgstr "Версія" -#: describe.c:5878 +#: describe.c:5860 msgid "List of foreign servers" msgstr "Список сторонніх серверів" -#: describe.c:5903 describe.c:5962 +#: describe.c:5885 describe.c:5943 msgid "Server" msgstr "Сервер" -#: describe.c:5904 +#: describe.c:5886 msgid "User name" msgstr "Ім'я користувача" -#: describe.c:5934 +#: describe.c:5915 msgid "List of user mappings" msgstr "Список зіставлень користувачів" -#: describe.c:6007 +#: describe.c:5987 msgid "List of foreign tables" msgstr "Список сторонніх таблиць" -#: describe.c:6059 +#: describe.c:6038 msgid "List of installed extensions" msgstr "Список встановлених розширень" -#: describe.c:6107 +#: describe.c:6086 #, c-format msgid "Did not find any extension named \"%s\"." msgstr "Не знайдено жодного розширення під назвою \"%s\"." -#: describe.c:6110 +#: describe.c:6089 #, c-format msgid "Did not find any extensions." msgstr "Не знайдено жодного розширення." -#: describe.c:6154 +#: describe.c:6133 msgid "Object description" msgstr "Опис об'єкту" -#: describe.c:6164 +#: describe.c:6142 #, c-format msgid "Objects in extension \"%s\"" msgstr "Об'єкти в розширенні \"%s\"" -#: describe.c:6205 +#: describe.c:6183 #, c-format msgid "improper qualified name (too many dotted names): %s" msgstr "неправильне повне ім'я (забагато компонентів): %s" -#: describe.c:6219 +#: describe.c:6197 #, c-format msgid "cross-database references are not implemented: %s" msgstr "міжбазові посилання не реалізовані: %s" -#: describe.c:6250 describe.c:6377 +#: describe.c:6228 describe.c:6354 #, c-format msgid "The server (version %s) does not support publications." msgstr "Сервер (версія %s) не підтримує публікації." -#: describe.c:6267 describe.c:6455 +#: describe.c:6245 describe.c:6432 msgid "All tables" msgstr "Усі таблиці" -#: describe.c:6268 describe.c:6456 +#: describe.c:6246 describe.c:6433 msgid "Inserts" msgstr "Вставки" -#: describe.c:6269 describe.c:6457 +#: describe.c:6247 describe.c:6434 msgid "Updates" msgstr "Оновлення" -#: describe.c:6270 describe.c:6458 +#: describe.c:6248 describe.c:6435 msgid "Deletes" msgstr "Видалення" -#: describe.c:6274 describe.c:6460 +#: describe.c:6252 describe.c:6437 msgid "Truncates" msgstr "Очищення" -#: describe.c:6278 describe.c:6462 +#: describe.c:6256 describe.c:6439 msgid "Via root" msgstr "Через root" -#: describe.c:6300 +#: describe.c:6277 msgid "List of publications" msgstr "Список публікацій" -#: describe.c:6424 +#: describe.c:6401 #, c-format msgid "Did not find any publication named \"%s\"." msgstr "Не знайдено жодної публікації під назвою \"%s\"." -#: describe.c:6427 +#: describe.c:6404 #, c-format msgid "Did not find any publications." msgstr "Не знайдено жодної публікації." -#: describe.c:6451 +#: describe.c:6428 #, c-format msgid "Publication %s" msgstr "Публікація %s" -#: describe.c:6504 +#: describe.c:6481 msgid "Tables:" msgstr "Таблиці:" -#: describe.c:6516 +#: describe.c:6493 msgid "Tables from schemas:" msgstr "Таблиці зі схеми:" -#: describe.c:6560 +#: describe.c:6538 #, c-format msgid "The server (version %s) does not support subscriptions." msgstr "Сервер (версія %s) не підтримує підписки." -#: describe.c:6576 +#: describe.c:6554 msgid "Publication" msgstr "Публікація" -#: describe.c:6585 +#: describe.c:6563 msgid "Binary" msgstr "Бінарний" -#: describe.c:6594 describe.c:6598 +#: describe.c:6572 describe.c:6576 msgid "Streaming" msgstr "Потокова передача" -#: describe.c:6606 +#: describe.c:6584 msgid "Two-phase commit" msgstr "Двофазовий коміт" -#: describe.c:6607 +#: describe.c:6585 msgid "Disable on error" msgstr "Вимкнути при помилці" -#: describe.c:6614 +#: describe.c:6592 msgid "Origin" msgstr "Джерело" -#: describe.c:6615 +#: describe.c:6593 msgid "Password required" msgstr "Потрібен пароль" -#: describe.c:6616 +#: describe.c:6594 msgid "Run as owner?" msgstr "Запустити як власник?" -#: describe.c:6621 +#: describe.c:6599 +msgid "Failover" +msgstr "Відновлення після збою" + +#: describe.c:6604 msgid "Synchronous commit" msgstr "Синхронні затвердження" -#: describe.c:6622 +#: describe.c:6605 msgid "Conninfo" msgstr "Conninfo" -#: describe.c:6628 +#: describe.c:6611 msgid "Skip LSN" msgstr "Пропустити LSN" -#: describe.c:6655 +#: describe.c:6637 msgid "List of subscriptions" msgstr "Список підписок" -#: describe.c:6717 describe.c:6813 describe.c:6906 describe.c:7001 +#: describe.c:6666 +msgid "(none)" +msgstr "(нічого)" + +#: describe.c:6706 describe.c:6801 describe.c:6893 describe.c:6987 msgid "AM" msgstr "АМ" -#: describe.c:6718 +#: describe.c:6707 msgid "Input type" msgstr "Тип вводу" -#: describe.c:6719 +#: describe.c:6708 msgid "Storage type" msgstr "Тип сховища" -#: describe.c:6720 +#: describe.c:6709 msgid "Operator class" msgstr "Клас операторів" -#: describe.c:6732 describe.c:6814 describe.c:6907 describe.c:7002 +#: describe.c:6721 describe.c:6802 describe.c:6894 describe.c:6988 msgid "Operator family" msgstr "Сімейство операторів" -#: describe.c:6768 +#: describe.c:6756 msgid "List of operator classes" msgstr "Список класів операторів" -#: describe.c:6815 +#: describe.c:6803 msgid "Applicable types" msgstr "Типи для застосування" -#: describe.c:6857 +#: describe.c:6844 msgid "List of operator families" msgstr "Список сімейств операторів" -#: describe.c:6908 +#: describe.c:6895 msgid "Operator" msgstr "Оператор" -#: describe.c:6909 +#: describe.c:6896 msgid "Strategy" msgstr "Стратегія" -#: describe.c:6910 +#: describe.c:6897 msgid "ordering" msgstr "упорядкування" -#: describe.c:6911 +#: describe.c:6898 msgid "search" msgstr "пошук" -#: describe.c:6912 +#: describe.c:6899 msgid "Purpose" msgstr "Ціль" -#: describe.c:6917 +#: describe.c:6904 msgid "Sort opfamily" msgstr "Сімейство операторів сортування" -#: describe.c:6956 +#: describe.c:6942 msgid "List of operators of operator families" msgstr "Список операторів сімейств операторів" -#: describe.c:7003 +#: describe.c:6989 msgid "Registered left type" msgstr "Зареєстрований лівий тип" -#: describe.c:7004 +#: describe.c:6990 msgid "Registered right type" msgstr "Зареєстрований правий тип" -#: describe.c:7005 +#: describe.c:6991 msgid "Number" msgstr "Число" -#: describe.c:7049 +#: describe.c:7034 msgid "List of support functions of operator families" msgstr "Список функцій підтримки сімейств операторів" -#: describe.c:7080 +#: describe.c:7065 msgid "ID" msgstr "ID" -#: describe.c:7101 +#: describe.c:7085 msgid "Large objects" msgstr "Великі об'єкти" -#: help.c:75 +#: help.c:63 msgid "psql is the PostgreSQL interactive terminal.\n\n" msgstr "psql - це інтерактивний термінал PostgreSQL.\n\n" -#: help.c:76 help.c:395 help.c:479 help.c:522 +#: help.c:64 help.c:372 help.c:456 help.c:499 msgid "Usage:\n" msgstr "Використання:\n" -#: help.c:77 +#: help.c:65 msgid " psql [OPTION]... [DBNAME [USERNAME]]\n\n" msgstr " psql [ОПЦІЯ]... [БД [КОРИСТУВАЧ]]\n\n" -#: help.c:79 +#: help.c:67 msgid "General options:\n" msgstr "Основні налаштування:\n" -#: help.c:84 +#: help.c:68 msgid " -c, --command=COMMAND run only single command (SQL or internal) and exit\n" msgstr " -c, --command=КОМАНДА виконати лише одну команду (SQL або внутрішню) і вийти\n" -#: help.c:85 -#, c-format -msgid " -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n" -msgstr " -d, --dbname=DBNAME ім'я бази даних для підключення (за замовчання: \"%s\") \n" +#: help.c:69 +msgid " -d, --dbname=DBNAME database name to connect to\n" +msgstr " -d, --dbname=DBNAME назва бази даних для підключення\n" -#: help.c:87 +#: help.c:70 msgid " -f, --file=FILENAME execute commands from file, then exit\n" msgstr " -f, --file=FILENAME виконує команди з файлу, потім виходить\n" -#: help.c:88 +#: help.c:71 msgid " -l, --list list available databases, then exit\n" msgstr " -l, --list виводить список доступних баз даних, потім виходить\n" -#: help.c:89 +#: help.c:72 msgid " -v, --set=, --variable=NAME=VALUE\n" " set psql variable NAME to VALUE\n" " (e.g., -v ON_ERROR_STOP=1)\n" @@ -2489,93 +2541,93 @@ msgstr " -v, --set=, --variable=NAME=VALUE\n" " присвоїти змінній psql NAME значення VALUE\n" " (наприклад, -v ON_ERROR_STOP=1)\n" -#: help.c:92 +#: help.c:75 msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: help.c:93 +#: help.c:76 msgid " -X, --no-psqlrc do not read startup file (~/.psqlrc)\n" msgstr " -X, --no-psqlrc ігнорувати файл параметрів запуска (~/.psqlrc)\n" -#: help.c:94 +#: help.c:77 msgid " -1 (\"one\"), --single-transaction\n" " execute as a single transaction (if non-interactive)\n" msgstr " -1 (\"один\"), --single-transaction\n" " виконує як одну транзакцію (якщо не інтерактивна)\n" -#: help.c:96 +#: help.c:79 msgid " -?, --help[=options] show this help, then exit\n" msgstr " -?, --help [=options] показати цю довідку, потім вийти\n" -#: help.c:97 +#: help.c:80 msgid " --help=commands list backslash commands, then exit\n" msgstr " --help=commands перерахувати команди, потім вийти\n" -#: help.c:98 +#: help.c:81 msgid " --help=variables list special variables, then exit\n" msgstr " --help=variables перерахувати спеціальні змінні, потім вийти\n" -#: help.c:100 +#: help.c:83 msgid "\n" "Input and output options:\n" msgstr "\n" "Параметри вводу і виводу:\n" -#: help.c:101 +#: help.c:84 msgid " -a, --echo-all echo all input from script\n" msgstr " -a, --echo-all відобразити всі вхідні дані з скрипта\n" -#: help.c:102 +#: help.c:85 msgid " -b, --echo-errors echo failed commands\n" msgstr " -b, --echo-errors відобразити команди з помилками\n" -#: help.c:103 +#: help.c:86 msgid " -e, --echo-queries echo commands sent to server\n" msgstr " -e, --echo-queries відобразити команди, відправлені на сервер\n" -#: help.c:104 +#: help.c:87 msgid " -E, --echo-hidden display queries that internal commands generate\n" msgstr " -E, --echo-hidden відобразити запити, згенеровані внутрішніми командами\n" -#: help.c:105 +#: help.c:88 msgid " -L, --log-file=FILENAME send session log to file\n" msgstr " -L, --log-file=FILENAME зберегти протокол роботи у файл\n" -#: help.c:106 +#: help.c:89 msgid " -n, --no-readline disable enhanced command line editing (readline)\n" msgstr " -n, --no-readline вимкнути розширене редагування командного рядка (readline)\n" -#: help.c:107 +#: help.c:90 msgid " -o, --output=FILENAME send query results to file (or |pipe)\n" msgstr " -o, --output=FILENAME надсилати результати запиту до файлу (або до каналу |)\n" -#: help.c:108 +#: help.c:91 msgid " -q, --quiet run quietly (no messages, only query output)\n" msgstr " -q, --quiet тихий запуск (ніяких повідомлень, лише результат запитів)\n" -#: help.c:109 +#: help.c:92 msgid " -s, --single-step single-step mode (confirm each query)\n" msgstr " -s, --single-step покроковий режим (підтвердження кожного запиту)\n" -#: help.c:110 +#: help.c:93 msgid " -S, --single-line single-line mode (end of line terminates SQL command)\n" msgstr " -S, --single-line однорядковий режим (кінець рядка завершує команду)\n" -#: help.c:112 +#: help.c:95 msgid "\n" "Output format options:\n" msgstr "\n" "Параметри формату виводу:\n" -#: help.c:113 +#: help.c:96 msgid " -A, --no-align unaligned table output mode\n" msgstr " -A, --no-align режим виводу не вирівняної таблиці\n" -#: help.c:114 +#: help.c:97 msgid " --csv CSV (Comma-Separated Values) table output mode\n" msgstr " --csv режим виводу таблиць CSV (Comma-Separated Values)\n" -#: help.c:115 +#: help.c:98 #, c-format msgid " -F, --field-separator=STRING\n" " field separator for unaligned output (default: \"%s\")\n" @@ -2583,79 +2635,72 @@ msgstr " -F, --field-separator=СТРОКА\n" " розділювач полів при не вирівняному виводі\n" " (за замовчуванням: \"%s\")\n" -#: help.c:118 +#: help.c:101 msgid " -H, --html HTML table output mode\n" msgstr " -H, --html вивід таблиці у форматі HTML\n" -#: help.c:119 +#: help.c:102 msgid " -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n" msgstr " -P, --pset=VAR[=ARG] встановити параметр виводу змінної VAR значенню ARG (див. команду \"\\pset\")\n" -#: help.c:120 +#: help.c:103 msgid " -R, --record-separator=STRING\n" " record separator for unaligned output (default: newline)\n" msgstr " -R, --record-separator=СТРОКА\n" " розділювач записів при не вирівняному виводі\n" " (за замовчуванням: новий рядок)\n" -#: help.c:122 +#: help.c:105 msgid " -t, --tuples-only print rows only\n" msgstr " -t, --tuples-only виводити лише рядки\n" -#: help.c:123 +#: help.c:106 msgid " -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n" msgstr " -T, --table-attr=ТЕКСТ встановити атрибути HTML-таблиці (width, border)\n" -#: help.c:124 +#: help.c:107 msgid " -x, --expanded turn on expanded table output\n" msgstr " -x, --expanded ввімкнути розширене виведення таблиці\n" -#: help.c:125 +#: help.c:108 msgid " -z, --field-separator-zero\n" " set field separator for unaligned output to zero byte\n" msgstr " -z, --field-separator-zero\n" " встановити розділювач полів для не вирівняного виводу в нульовий байт\n" -#: help.c:127 +#: help.c:110 msgid " -0, --record-separator-zero\n" " set record separator for unaligned output to zero byte\n" msgstr " -0, --record-separator-zero\n" " встановити розділювач записів для не вирівняного виводу в нульовий байт\n" -#: help.c:130 +#: help.c:113 msgid "\n" "Connection options:\n" msgstr "\n" "Налаштування з'єднання:\n" -#: help.c:133 -#, c-format -msgid " -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n" -msgstr " -h, --host=HOSTNAME хост сервера бази даних або каталог сокетів (за замовчуванням: \"%s)\n" - -#: help.c:134 -msgid "local socket" -msgstr "локальний сокет" +#: help.c:114 +msgid " -h, --host=HOSTNAME database server host or socket directory\n" +msgstr " -h, --host=HOSTNAME хост серверу баз даних або каталог сокетів\n" -#: help.c:137 -#, c-format -msgid " -p, --port=PORT database server port (default: \"%s\")\n" -msgstr " -p, --port=PORT порт сервера бази даних (за замовчуванням: \"%s\")\n" +#: help.c:115 +msgid " -p, --port=PORT database server port\n" +msgstr " -p, --port=ПОРТ порт сервера бази даних\n" -#: help.c:140 -#, c-format -msgid " -U, --username=USERNAME database user name (default: \"%s\")\n" -msgstr " -U, --username=USERNAME ім'я користувача бази даних (за змовчуванням: \"%s\")\n" +#: help.c:116 +msgid " -U, --username=USERNAME database user name\n" +msgstr " -U, --username=USERNAME ім'я користувача бази даних\n" -#: help.c:142 +#: help.c:117 msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не запитувати пароль\n" -#: help.c:143 +#: help.c:118 msgid " -W, --password force password prompt (should happen automatically)\n" msgstr " -W, --password запитувати пароль завжди (повинно траплятись автоматично)\n" -#: help.c:145 +#: help.c:120 msgid "\n" "For more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" "commands) from within psql, or consult the psql section in the PostgreSQL\n" @@ -2663,435 +2708,439 @@ msgid "\n" msgstr "\n" "Щоб дізнатися більше, введіть \"\\?\" (для внутрішніх команд) або \"\\help\"(для команд SQL) в psql, або звіртеся з розділом psql документації PostgreSQL. \n\n" -#: help.c:148 +#: help.c:123 #, c-format msgid "Report bugs to <%s>.\n" msgstr "Повідомляти про помилки на <%s>.\n" -#: help.c:149 +#: help.c:124 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: help.c:191 +#: help.c:166 msgid "General\n" msgstr "Загальні\n" -#: help.c:192 +#: help.c:167 msgid " \\bind [PARAM]... set query parameters\n" msgstr " \\bind [PARAM]... встановити параметри запиту\n" -#: help.c:193 +#: help.c:168 msgid " \\copyright show PostgreSQL usage and distribution terms\n" msgstr " \\copyright умови використання і розповсюдження PostgreSQL\n" -#: help.c:194 +#: help.c:169 msgid " \\crosstabview [COLUMNS] execute query and display result in crosstab\n" msgstr " \\crosstabview [COLUMNS] виконати запит і відобразити результат у перехресній таблиці\n" -#: help.c:195 +#: help.c:170 msgid " \\errverbose show most recent error message at maximum verbosity\n" msgstr " \\errverbose вивести максимально докладне повідомлення про останню помилку\n" -#: help.c:196 +#: help.c:171 msgid " \\g [(OPTIONS)] [FILE] execute query (and send result to file or |pipe);\n" " \\g with no arguments is equivalent to a semicolon\n" msgstr " \\g [(OPTIONS)] [FILE] виконати запит (і надіслати результат до файлу або |каналу);\n" " \\g без аргументів рівнозначно крапці з комою\n" -#: help.c:198 +#: help.c:173 msgid " \\gdesc describe result of query, without executing it\n" msgstr " \\gdesc описати результат запиту без виконання\n" -#: help.c:199 +#: help.c:174 msgid " \\gexec execute query, then execute each value in its result\n" msgstr " \\gexec виконати запит, потім виконати кожне значення в його результаті\n" -#: help.c:200 +#: help.c:175 msgid " \\gset [PREFIX] execute query and store result in psql variables\n" msgstr " \\gset [PREFIX] виконати запит та зберегти результат в змінних psql \n" -#: help.c:201 +#: help.c:176 msgid " \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n" msgstr " \\gx [(OPTIONS)] [FILE] як \\g, але вмикає розширений режим виводу\n" -#: help.c:202 +#: help.c:177 msgid " \\q quit psql\n" msgstr " \\q вийти з psql\n" -#: help.c:203 -msgid " \\watch [[i=]SEC] [c=N] execute query every SEC seconds, up to N times\n" -msgstr " \\watch [[i=]SEC] [c=N] виконувати кожні SEC секунд, не більше N разів\n" +#: help.c:178 +msgid " \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" execute query every SEC seconds, up to N times,\n" +" stop if less than MIN rows are returned\n" +msgstr " \\watch [[i=]SEC] [c=N] [m=MIN]\n" +" виконувати запит кожні SEC секунд, до N разів або\n" +" зупинитися, якщо повернуто менше ніж MIN рядків\n" -#: help.c:204 help.c:212 help.c:224 help.c:234 help.c:241 help.c:298 help.c:306 -#: help.c:326 help.c:339 help.c:348 +#: help.c:181 help.c:189 help.c:201 help.c:211 help.c:218 help.c:275 help.c:283 +#: help.c:303 help.c:316 help.c:325 msgid "\n" msgstr "\n" -#: help.c:206 +#: help.c:183 msgid "Help\n" msgstr "Довідка\n" -#: help.c:208 +#: help.c:185 msgid " \\? [commands] show help on backslash commands\n" msgstr " \\? [commands] показати довідку по командах з \\\n" -#: help.c:209 +#: help.c:186 msgid " \\? options show help on psql command-line options\n" msgstr " \\? options показати довідку по параметрах командного рядку psql\n" -#: help.c:210 +#: help.c:187 msgid " \\? variables show help on special variables\n" msgstr " \\? variables показати довідку по спеціальних змінних\n" -#: help.c:211 +#: help.c:188 msgid " \\h [NAME] help on syntax of SQL commands, * for all commands\n" msgstr " \\h [NAME] довідка з синтаксису команд SQL, * для всіх команд\n" -#: help.c:214 +#: help.c:191 msgid "Query Buffer\n" msgstr "Буфер запитів\n" -#: help.c:215 +#: help.c:192 msgid " \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n" msgstr " \\e [FILE] [LINE] редагувати буфер запитів (або файл) зовнішнім редактором\n" -#: help.c:216 +#: help.c:193 msgid " \\ef [FUNCNAME [LINE]] edit function definition with external editor\n" msgstr " \\ef [FUNCNAME [LINE]] редагувати визначення функції зовнішнім редактором\n" -#: help.c:217 +#: help.c:194 msgid " \\ev [VIEWNAME [LINE]] edit view definition with external editor\n" msgstr " \\ev [VIEWNAME [LINE]] редагувати визначення подання зовнішнім редактором\n" -#: help.c:218 +#: help.c:195 msgid " \\p show the contents of the query buffer\n" msgstr " \\p показати вміст буфера запитів\n" -#: help.c:219 +#: help.c:196 msgid " \\r reset (clear) the query buffer\n" msgstr " \\r скинути (очистити) буфер запитів\n" -#: help.c:221 +#: help.c:198 msgid " \\s [FILE] display history or save it to file\n" msgstr " \\s [FILE] відобразити історію або зберегти її до файлу\n" -#: help.c:223 +#: help.c:200 msgid " \\w FILE write query buffer to file\n" msgstr " \\w FILE писати буфер запитів до файлу\n" -#: help.c:226 +#: help.c:203 msgid "Input/Output\n" msgstr "Ввід/Вивід\n" -#: help.c:227 +#: help.c:204 msgid " \\copy ... perform SQL COPY with data stream to the client host\n" msgstr " \\copy ... виконати команду SQL COPY з потоком даних на клієнтський хост\n" -#: help.c:228 +#: help.c:205 msgid " \\echo [-n] [STRING] write string to standard output (-n for no newline)\n" msgstr " \\echo [-n] [STRING] записати рядок до стандартного виводу (-n для пропуску нового рядка)\n" -#: help.c:229 +#: help.c:206 msgid " \\i FILE execute commands from file\n" msgstr " \\i FILE виконати команди з файлу\n" -#: help.c:230 +#: help.c:207 msgid " \\ir FILE as \\i, but relative to location of current script\n" msgstr " \\ir ФАЙЛ те саме, що \\i, але відносно розташування поточного сценарію\n" -#: help.c:231 +#: help.c:208 msgid " \\o [FILE] send all query results to file or |pipe\n" msgstr " \\o [FILE] надсилати всі результати запитів до файлу або до каналу |\n" -#: help.c:232 +#: help.c:209 msgid " \\qecho [-n] [STRING] write string to \\o output stream (-n for no newline)\n" msgstr " \\qecho [-n] [STRING] записати рядок до вихідного потоку \\o (-n для пропуску нового рядка)\n" -#: help.c:233 +#: help.c:210 msgid " \\warn [-n] [STRING] write string to standard error (-n for no newline)\n" msgstr " \\warn [-n] [STRING] записати рядок до стандартної помилки (-n для пропуску нового рядка)\n" -#: help.c:236 +#: help.c:213 msgid "Conditional\n" msgstr "Умовний\n" -#: help.c:237 +#: help.c:214 msgid " \\if EXPR begin conditional block\n" msgstr " \\if EXPR початок умовного блоку\n" -#: help.c:238 +#: help.c:215 msgid " \\elif EXPR alternative within current conditional block\n" msgstr " \\elif EXPR альтернатива в рамках поточного блоку\n" -#: help.c:239 +#: help.c:216 msgid " \\else final alternative within current conditional block\n" msgstr " \\else остаточна альтернатива в рамках поточного умовного блоку\n" -#: help.c:240 +#: help.c:217 msgid " \\endif end conditional block\n" msgstr " \\endif кінець умовного блоку\n" -#: help.c:243 +#: help.c:220 msgid "Informational\n" msgstr "Інформаційний\n" -#: help.c:244 +#: help.c:221 msgid " (options: S = show system objects, + = additional detail)\n" msgstr " (параметри: S = показати системні об'єкти, + = додаткові деталі)\n" -#: help.c:245 +#: help.c:222 msgid " \\d[S+] list tables, views, and sequences\n" msgstr " \\d[S+] вивести таблиці, подання і послідовності\n" -#: help.c:246 +#: help.c:223 msgid " \\d[S+] NAME describe table, view, sequence, or index\n" msgstr " \\d[S+] NAME описати таблицю, подання, послідовність або індекс\n" -#: help.c:247 +#: help.c:224 msgid " \\da[S] [PATTERN] list aggregates\n" msgstr " \\da[S] [PATTERN] вивести агрегати\n" -#: help.c:248 +#: help.c:225 msgid " \\dA[+] [PATTERN] list access methods\n" msgstr " \\dA[+] [PATTERN] вивести методи доступу\n" -#: help.c:249 +#: help.c:226 msgid " \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n" msgstr " \\dAc[+] [AMPTRN [TYPEPTRN]] список класів операторів\n" -#: help.c:250 +#: help.c:227 msgid " \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n" msgstr " \\dAf[+] [AMPTRN [TYPEPTRN]] список сімейств операторів\n" -#: help.c:251 +#: help.c:228 msgid " \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n" msgstr " \\dAo[+] [AMPTRN [OPFPTRN]] список операторів сімейств операторів\n" -#: help.c:252 +#: help.c:229 msgid " \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n" msgstr " \\dAp[+] [AMPTRN [OPFPTRN]] список функцій підтримки сімейств операторів\n" -#: help.c:253 +#: help.c:230 msgid " \\db[+] [PATTERN] list tablespaces\n" msgstr " \\db[+] [PATTERN] вивести табличні простори\n" -#: help.c:254 +#: help.c:231 msgid " \\dc[S+] [PATTERN] list conversions\n" msgstr " \\dc[S+] [PATTERN] вивести перетворення\n" -#: help.c:255 +#: help.c:232 msgid " \\dconfig[+] [PATTERN] list configuration parameters\n" msgstr " \\dconfig[+] [PATTERN] вивести параметри конфігурації\n" -#: help.c:256 +#: help.c:233 msgid " \\dC[+] [PATTERN] list casts\n" msgstr " \\dC[+] [PATTERN] вивести приведення типів\n" -#: help.c:257 +#: help.c:234 msgid " \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n" msgstr " \\dd[S] [PATTERN] показати опис об'єкта, що не відображається в іншому місці\n" -#: help.c:258 +#: help.c:235 msgid " \\dD[S+] [PATTERN] list domains\n" msgstr " \\dD[S+] [PATTERN] вивести домени\n" -#: help.c:259 +#: help.c:236 msgid " \\ddp [PATTERN] list default privileges\n" msgstr " \\ddp [PATTERN] вивести привілеї за замовчуванням\n" -#: help.c:260 +#: help.c:237 msgid " \\dE[S+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [PATTERN] вивести зовнішні таблиці\n" -#: help.c:261 +#: help.c:238 msgid " \\des[+] [PATTERN] list foreign servers\n" msgstr " \\des[+] [PATTERN] вивести зовнішні сервери\n" -#: help.c:262 +#: help.c:239 msgid " \\det[+] [PATTERN] list foreign tables\n" msgstr " \\dE[S+] [PATTERN] вивести зовнішні таблиці\n" -#: help.c:263 +#: help.c:240 msgid " \\deu[+] [PATTERN] list user mappings\n" msgstr " \\deu[+] [PATTERN] вивести користувацькі зіставлення\n" -#: help.c:264 +#: help.c:241 msgid " \\dew[+] [PATTERN] list foreign-data wrappers\n" msgstr " \\dew[+] [PATTERN] список джерел сторонніх даних\n" -#: help.c:265 +#: help.c:242 msgid " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " list [only agg/normal/procedure/trigger/window] functions\n" msgstr " \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n" " список [лише агрегатних/нормальних/процедурних/тригерних/віконних] функцій\n" -#: help.c:267 +#: help.c:244 msgid " \\dF[+] [PATTERN] list text search configurations\n" msgstr " \\dF[+] [PATTERN] вивести конфігурації текстового пошуку\n" -#: help.c:268 +#: help.c:245 msgid " \\dFd[+] [PATTERN] list text search dictionaries\n" msgstr " \\dFd[+] [PATTERN] вивести словники текстового пошуку\n" -#: help.c:269 +#: help.c:246 msgid " \\dFp[+] [PATTERN] list text search parsers\n" msgstr " \\dFp[+] [PATTERN] вивести парсери текстового пошуку\n" -#: help.c:270 +#: help.c:247 msgid " \\dFt[+] [PATTERN] list text search templates\n" msgstr " \\dFt[+] [PATTERN] вивести шаблони текстового пошуку\n" -#: help.c:271 +#: help.c:248 msgid " \\dg[S+] [PATTERN] list roles\n" msgstr " \\dg[S+] [PATTERN] вивести ролі\n" -#: help.c:272 +#: help.c:249 msgid " \\di[S+] [PATTERN] list indexes\n" msgstr " \\di[S+] [PATTERN] вивести індекси\n" -#: help.c:273 +#: help.c:250 msgid " \\dl[+] list large objects, same as \\lo_list\n" msgstr " \\dl[+] вивести великі об'єкти, те саме, що \\lo_list\n" -#: help.c:274 +#: help.c:251 msgid " \\dL[S+] [PATTERN] list procedural languages\n" msgstr " \\dL[S+] [PATTERN] вивести процедурні мови\n" -#: help.c:275 +#: help.c:252 msgid " \\dm[S+] [PATTERN] list materialized views\n" msgstr " \\dm[S+] [PATTERN] вивести матеріалізовані подання\n" -#: help.c:276 +#: help.c:253 msgid " \\dn[S+] [PATTERN] list schemas\n" msgstr " \\dn[S+] [PATTERN] вивести схеми\n" -#: help.c:277 +#: help.c:254 msgid " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " list operators\n" msgstr " \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n" " список операторів\n" -#: help.c:279 +#: help.c:256 msgid " \\dO[S+] [PATTERN] list collations\n" msgstr " \\dO[S+] [PATTERN] вивести правила сортування\n" -#: help.c:280 +#: help.c:257 msgid " \\dp[S] [PATTERN] list table, view, and sequence access privileges\n" msgstr " \\dp[S] [PATTERN] вивести привілеї доступу до таблиць, подань або послідовностей \n" -#: help.c:281 +#: help.c:258 msgid " \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n" msgstr " \\dP[itn+] [PATTERN] вивести [тільки індекс/таблицю] секційні відношення [n=вкладені]\n" -#: help.c:282 +#: help.c:259 msgid " \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n" msgstr " \\drds [ROLEPTRN [DBPTRN]] вивести налаштування ролей побазово\n" -#: help.c:283 +#: help.c:260 msgid " \\drg[S] [PATTERN] list role grants\n" msgstr " \\drg[S] [PATTERN] вивести надані ролі\n" -#: help.c:284 +#: help.c:261 msgid " \\dRp[+] [PATTERN] list replication publications\n" msgstr " \\dRp[+] [PATTERN] вивести реплікаційні публікації\n" -#: help.c:285 +#: help.c:262 msgid " \\dRs[+] [PATTERN] list replication subscriptions\n" msgstr " \\dRs[+] [PATTERN] вивести реплікаційні підписки\n" -#: help.c:286 +#: help.c:263 msgid " \\ds[S+] [PATTERN] list sequences\n" msgstr " \\ds[S+] [PATTERN] вивести послідовності\n" -#: help.c:287 +#: help.c:264 msgid " \\dt[S+] [PATTERN] list tables\n" msgstr " \\dt[S+] [PATTERN] вивести таблиці\n" -#: help.c:288 +#: help.c:265 msgid " \\dT[S+] [PATTERN] list data types\n" msgstr " \\dT[S+] [PATTERN] вивести типи даних\n" -#: help.c:289 +#: help.c:266 msgid " \\du[S+] [PATTERN] list roles\n" msgstr " \\du[S+] [PATTERN] вивести ролі\n" -#: help.c:290 +#: help.c:267 msgid " \\dv[S+] [PATTERN] list views\n" msgstr " \\dv[S+] [PATTERN] вивести подання\n" -#: help.c:291 +#: help.c:268 msgid " \\dx[+] [PATTERN] list extensions\n" msgstr " \\dx[+] [PATTERN] вивести розширення\n" -#: help.c:292 +#: help.c:269 msgid " \\dX [PATTERN] list extended statistics\n" msgstr " \\dX [PATTERN] список розширеної статистики\n" -#: help.c:293 +#: help.c:270 msgid " \\dy[+] [PATTERN] list event triggers\n" msgstr " \\dy[+] [PATTERN] вивести тригери подій\n" -#: help.c:294 +#: help.c:271 msgid " \\l[+] [PATTERN] list databases\n" msgstr " \\l[+] [PATTERN] вивести бази даних\n" -#: help.c:295 +#: help.c:272 msgid " \\sf[+] FUNCNAME show a function's definition\n" msgstr " \\sf[+] FUNCNAME відобразити визначення функції\n" -#: help.c:296 +#: help.c:273 msgid " \\sv[+] VIEWNAME show a view's definition\n" msgstr " \\sv[+] VIEWNAME відобразити визначення подання\n" -#: help.c:297 +#: help.c:274 msgid " \\z[S] [PATTERN] same as \\dp\n" msgstr " \\z[S] [PATTERN] те саме, що \\dp\n" -#: help.c:300 +#: help.c:277 msgid "Large Objects\n" msgstr "Великі об'єкти\n" -#: help.c:301 +#: help.c:278 msgid " \\lo_export LOBOID FILE write large object to file\n" msgstr " \\lo_export LOBOID FILE записати великий об'єкт в файл\n" -#: help.c:302 +#: help.c:279 msgid " \\lo_import FILE [COMMENT]\n" " read large object from file\n" msgstr " \\lo_import FILE [COMMENT]\n" " читати великий об'єкт з файлу\n" -#: help.c:304 +#: help.c:281 msgid " \\lo_list[+] list large objects\n" msgstr " \\lo_list[+] вивести великі об'єкти\n" -#: help.c:305 +#: help.c:282 msgid " \\lo_unlink LOBOID delete a large object\n" msgstr " \\lo_unlink LOBOID видалити великий об’єкт\n" -#: help.c:308 +#: help.c:285 msgid "Formatting\n" msgstr "Форматування\n" -#: help.c:309 +#: help.c:286 msgid " \\a toggle between unaligned and aligned output mode\n" msgstr " \\a перемикання між режимами виводу: unaligned, aligned\n" -#: help.c:310 +#: help.c:287 msgid " \\C [STRING] set table title, or unset if none\n" msgstr " \\C [STRING] встановити заголовок таблиці або прибрати, якщо не задано\n" -#: help.c:311 +#: help.c:288 msgid " \\f [STRING] show or set field separator for unaligned query output\n" msgstr " \\f [STRING] показати або встановити розділювач полів для не вирівняного виводу запиту\n" -#: help.c:312 +#: help.c:289 #, c-format msgid " \\H toggle HTML output mode (currently %s)\n" msgstr " \\H переключити режим виводу HTML (поточний: %s)\n" -#: help.c:314 +#: help.c:291 msgid " \\pset [NAME [VALUE]] set table output option\n" " (border|columns|csv_fieldsep|expanded|fieldsep|\n" " fieldsep_zero|footer|format|linestyle|null|\n" @@ -3107,113 +3156,113 @@ msgstr " \\pset [NAME [VALUE]] встановити параметр виво " unicode_border_linestyle|unicode_column_linestyle|\n" " unicode_header_linestyle)\n" -#: help.c:321 +#: help.c:298 #, c-format msgid " \\t [on|off] show only rows (currently %s)\n" msgstr " \\t [on|off] показувати лише рядки (поточно %s)\n" -#: help.c:323 +#: help.c:300 msgid " \\T [STRING] set HTML
tag attributes, or unset if none\n" msgstr " \\T [STRING] встановити атрибути для HTML
або прибрати, якщо не задані\n" -#: help.c:324 +#: help.c:301 #, c-format msgid " \\x [on|off|auto] toggle expanded output (currently %s)\n" msgstr " \\x [on|off|auto] переключити розширений вивід (поточний: %s)\n" -#: help.c:325 +#: help.c:302 msgid "auto" msgstr "авто" -#: help.c:328 +#: help.c:305 msgid "Connection\n" msgstr "Підключення\n" -#: help.c:330 +#: help.c:307 #, c-format msgid " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently \"%s\")\n" msgstr " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo} під'єднатися до нової бази даних (поточно \"%s\")\n" -#: help.c:334 +#: help.c:311 msgid " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" " connect to new database (currently no connection)\n" msgstr " \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo} під'єднатися до нової бази даних (зараз з'єднання відсутнє)\n" -#: help.c:336 +#: help.c:313 msgid " \\conninfo display information about current connection\n" msgstr " \\conninfo показати інформацію про поточне з'єднання\n" -#: help.c:337 +#: help.c:314 msgid " \\encoding [ENCODING] show or set client encoding\n" msgstr " \\encoding [ENCODING] показати або встановити кодування клієнта\n" -#: help.c:338 +#: help.c:315 msgid " \\password [USERNAME] securely change the password for a user\n" msgstr " \\password [USERNAME] безпечно змінити пароль користувача \n" -#: help.c:341 +#: help.c:318 msgid "Operating System\n" msgstr "Операційна система\n" -#: help.c:342 +#: help.c:319 msgid " \\cd [DIR] change the current working directory\n" msgstr " \\cd [DIR] змінити поточний робочий каталог\n" -#: help.c:343 +#: help.c:320 msgid " \\getenv PSQLVAR ENVVAR fetch environment variable\n" msgstr " \\getenv PSQLVAR ENVAR отримати змінну середовища\n" -#: help.c:344 +#: help.c:321 msgid " \\setenv NAME [VALUE] set or unset environment variable\n" msgstr " \\setenv NAME [VALUE] встановити або скинути змінну середовища\n" -#: help.c:345 +#: help.c:322 #, c-format msgid " \\timing [on|off] toggle timing of commands (currently %s)\n" msgstr " \\timing [on|off] переключити таймер команд (поточний: %s)\n" -#: help.c:347 +#: help.c:324 msgid " \\! [COMMAND] execute command in shell or start interactive shell\n" msgstr " \\! [COMMAND] виконати команду в оболонці або запустити інтерактивну оболонку\n" -#: help.c:350 +#: help.c:327 msgid "Variables\n" msgstr "Змінні\n" -#: help.c:351 +#: help.c:328 msgid " \\prompt [TEXT] NAME prompt user to set internal variable\n" msgstr " \\prompt [TEXT] NAME запитати користувача значення внутрішньої змінної\n" -#: help.c:352 +#: help.c:329 msgid " \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n" msgstr " \\set [NAME [VALUE]] встановити внутрішню змінну або вивести всі, якщо не задані параметри\n" -#: help.c:353 +#: help.c:330 msgid " \\unset NAME unset (delete) internal variable\n" msgstr " \\unset NAME скинути (видалити) значення внутрішньої змінної\n" -#: help.c:392 +#: help.c:369 msgid "List of specially treated variables\n\n" msgstr "Список спеціальних змінних\n\n" -#: help.c:394 +#: help.c:371 msgid "psql variables:\n" msgstr "змінні psql:\n" -#: help.c:396 +#: help.c:373 msgid " psql --set=NAME=VALUE\n" " or \\set NAME VALUE inside psql\n\n" msgstr " psql --set=ІМ'Я=ЗНАЧЕННЯ\n" " або \\set ІМ'Я ЗНАЧЕННЯ усередині psql\n\n" -#: help.c:398 +#: help.c:375 msgid " AUTOCOMMIT\n" " if set, successful SQL commands are automatically committed\n" msgstr " AUTOCOMMIT\n" " якщо встановлений, успішні SQL-команди підтверджуються автоматично\n" -#: help.c:400 +#: help.c:377 msgid " COMP_KEYWORD_CASE\n" " determines the case used to complete SQL key words\n" " [lower, upper, preserve-lower, preserve-upper]\n" @@ -3221,18 +3270,18 @@ msgstr " COMP_KEYWORD_CASE\n" " визначає регістр для автодоповнення ключових слів SQL\n" " [lower, upper, preserve-lower, preserve-upper]\n" -#: help.c:403 +#: help.c:380 msgid " DBNAME\n" " the currently connected database name\n" msgstr " DBNAME назва під'єднаної бази даних\n" -#: help.c:405 +#: help.c:382 msgid " ECHO\n" " controls what input is written to standard output\n" " [all, errors, none, queries]\n" msgstr " ECHO контролює ввід, що виводиться на стандартний вивід [all, errors, none, queries]\n" -#: help.c:408 +#: help.c:385 msgid " ECHO_HIDDEN\n" " if set, display internal queries executed by backslash commands;\n" " if set to \"noexec\", just show them without execution\n" @@ -3240,67 +3289,67 @@ msgstr " ECHO_HIDDEN\n" " якщо ввімкнено, виводить внутрішні запити, виконані за допомогою \"\\\";\n" " якщо встановлено значення \"noexec\", тільки виводяться, але не виконуються\n" -#: help.c:411 +#: help.c:388 msgid " ENCODING\n" " current client character set encoding\n" msgstr " ENCODING\n" " поточне кодування набору символів клієнта\n" -#: help.c:413 +#: help.c:390 msgid " ERROR\n" " \"true\" if last query failed, else \"false\"\n" msgstr " ERROR\n" " \"true\", якщо в останньому запиті є помилка, в іншому разі - \"false\"\n" -#: help.c:415 +#: help.c:392 msgid " FETCH_COUNT\n" " the number of result rows to fetch and display at a time (0 = unlimited)\n" msgstr " FETCH_COUNT\n" " число рядків з результатами для передачі та відображення за один раз (0 = необмежено)\n" -#: help.c:417 +#: help.c:394 msgid " HIDE_TABLEAM\n" " if set, table access methods are not displayed\n" msgstr " HIDE_TABLEAM\n" " якщо вказано, методи доступу до таблиць не відображаються\n" -#: help.c:419 +#: help.c:396 msgid " HIDE_TOAST_COMPRESSION\n" " if set, compression methods are not displayed\n" msgstr " HIDE_TOAST_COMPRESSION\n" " якщо встановлено, методи стискання не відображаються\n" -#: help.c:421 +#: help.c:398 msgid " HISTCONTROL\n" " controls command history [ignorespace, ignoredups, ignoreboth]\n" msgstr " HISTCONTROL контролює історію команд [ignorespace, ignoredups, ignoreboth]\n" -#: help.c:423 +#: help.c:400 msgid " HISTFILE\n" " file name used to store the command history\n" msgstr " HISTFILE ім'я файлу для зберігання історії команд\n" -#: help.c:425 +#: help.c:402 msgid " HISTSIZE\n" " maximum number of commands to store in the command history\n" msgstr " HISTSIZE максимальна кількість команд для зберігання в історії команд\n" -#: help.c:427 +#: help.c:404 msgid " HOST\n" " the currently connected database server host\n" msgstr " HOST поточний підключений хост сервера бази даних\n" -#: help.c:429 +#: help.c:406 msgid " IGNOREEOF\n" " number of EOFs needed to terminate an interactive session\n" msgstr " IGNOREEOF кількість EOF для завершення інтерактивної сесії\n" -#: help.c:431 +#: help.c:408 msgid " LASTOID\n" " value of the last affected OID\n" msgstr " LASTOID значення останнього залученого OID\n" -#: help.c:433 +#: help.c:410 msgid " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" " message and SQLSTATE of last error, or empty string and \"00000\" if none\n" @@ -3308,55 +3357,55 @@ msgstr " LAST_ERROR_MESSAGE\n" " LAST_ERROR_SQLSTATE\n" " повідомлення та код SQLSTATE останньої помилки, або пустий рядок та \"00000\", якщо помилки не було\n" -#: help.c:436 +#: help.c:413 msgid " ON_ERROR_ROLLBACK\n" " if set, an error doesn't stop a transaction (uses implicit savepoints)\n" msgstr " ON_ERROR_ROLLBACK\n" " якщо встановлено, транзакція не припиняється у разі помилки (використовуються неявні точки збереження)\n" -#: help.c:438 +#: help.c:415 msgid " ON_ERROR_STOP\n" " stop batch execution after error\n" msgstr " ON_ERROR_STOP\n" " зупиняти виконання пакету команд після помилки\n" -#: help.c:440 +#: help.c:417 msgid " PORT\n" " server port of the current connection\n" msgstr " PORT\n" " порт сервера для поточного з'єднання\n" -#: help.c:442 +#: help.c:419 msgid " PROMPT1\n" " specifies the standard psql prompt\n" msgstr " PROMPT1\n" " визначає стандратне запрошення psql \n" -#: help.c:444 +#: help.c:421 msgid " PROMPT2\n" " specifies the prompt used when a statement continues from a previous line\n" msgstr " PROMPT2\n" " визначає запрошення, яке використовується при продовженні команди з попереднього рядка\n" -#: help.c:446 +#: help.c:423 msgid " PROMPT3\n" " specifies the prompt used during COPY ... FROM STDIN\n" msgstr " PROMPT3\n" " визначає запрошення, яке виконується під час COPY ... FROM STDIN\n" -#: help.c:448 +#: help.c:425 msgid " QUIET\n" " run quietly (same as -q option)\n" msgstr " QUIET\n" " тихий запуск ( як із параметром -q)\n" -#: help.c:450 +#: help.c:427 msgid " ROW_COUNT\n" " number of rows returned or affected by last query, or 0\n" msgstr " ROW_COUNT\n" " число повернених або оброблених рядків останнім запитом, або 0\n" -#: help.c:452 +#: help.c:429 msgid " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" " server's version (in short string or numeric format)\n" @@ -3364,61 +3413,61 @@ msgstr " SERVER_VERSION_NAME\n" " SERVER_VERSION_NUM\n" " версія серевера (у короткому текстовому або числовому форматі)\n" -#: help.c:455 +#: help.c:432 msgid " SHELL_ERROR\n" " \"true\" if the last shell command failed, \"false\" if it succeeded\n" msgstr " SHELL_ERROR\n" " \"true\", якщо остання команда оболонки завершилася помилкою, \"false\", якщо успішно\n" -#: help.c:457 +#: help.c:434 msgid " SHELL_EXIT_CODE\n" " exit status of the last shell command\n" msgstr " SHEL_EXIT_CODE\n" " статус виконання останньої команди оболонки\n" -#: help.c:459 +#: help.c:436 msgid " SHOW_ALL_RESULTS\n" " show all results of a combined query (\\;) instead of only the last\n" msgstr " SHOW_ALL_RESULTS\n" " показати всі результати комбінованого запиту (\\;) замість тільки останнього\n" -#: help.c:461 +#: help.c:438 msgid " SHOW_CONTEXT\n" " controls display of message context fields [never, errors, always]\n" msgstr " SHOW_CONTEXT\n" " керує відображенням полів контексту повідомлень [never, errors, always]\n" -#: help.c:463 +#: help.c:440 msgid " SINGLELINE\n" " if set, end of line terminates SQL commands (same as -S option)\n" msgstr " SINGLELINE\n" " якщо встановлено, кінець рядка завершує режим вводу SQL-команди (як з параметром -S)\n" -#: help.c:465 +#: help.c:442 msgid " SINGLESTEP\n" " single-step mode (same as -s option)\n" msgstr " SINGLESTEP\n" " покроковий режим (як з параметром -s)\n" -#: help.c:467 +#: help.c:444 msgid " SQLSTATE\n" " SQLSTATE of last query, or \"00000\" if no error\n" msgstr " SQLSTATE\n" " SQLSTATE останнього запиту, або \"00000\" якщо немає помилок\n" -#: help.c:469 +#: help.c:446 msgid " USER\n" " the currently connected database user\n" msgstr " USER\n" " поточний користувач, підключений до бази даних\n" -#: help.c:471 +#: help.c:448 msgid " VERBOSITY\n" " controls verbosity of error reports [default, verbose, terse, sqlstate]\n" msgstr " VERBOSITY\n" " контролює докладність звітів про помилку [default, verbose, terse, sqlstate]\n" -#: help.c:473 +#: help.c:450 msgid " VERSION\n" " VERSION_NAME\n" " VERSION_NUM\n" @@ -3428,98 +3477,98 @@ msgstr " VERSION\n" " VERSION_NUM\n" " psql версія (в розгорнутому, в короткому текстовому або числовому форматі)\n" -#: help.c:478 +#: help.c:455 msgid "\n" "Display settings:\n" msgstr "\n" "Налаштування відобреження:\n" -#: help.c:480 +#: help.c:457 msgid " psql --pset=NAME[=VALUE]\n" " or \\pset NAME [VALUE] inside psql\n\n" msgstr " psql --pset=NAME[=VALUE]\n" " або \\pset ІМ'Я [VALUE] всередині psql\n\n" -#: help.c:482 +#: help.c:459 msgid " border\n" " border style (number)\n" msgstr " border\n" " стиль рамки (число)\n" -#: help.c:484 +#: help.c:461 msgid " columns\n" " target width for the wrapped format\n" msgstr " columns\n" " цільова ширина для формату з переносом\n" -#: help.c:486 +#: help.c:463 msgid " expanded (or x)\n" " expanded output [on, off, auto]\n" msgstr " expanded (or x)\n" " розширений вивід [on, off, auto]\n" -#: help.c:488 +#: help.c:465 #, c-format msgid " fieldsep\n" " field separator for unaligned output (default \"%s\")\n" msgstr " fieldsep\n" " розділювач полів для не вирівняного виводу (за замовчуванням \"%s\")\n" -#: help.c:491 +#: help.c:468 msgid " fieldsep_zero\n" " set field separator for unaligned output to a zero byte\n" msgstr " fieldsep_zero\n" " встановити розділювач полів для невирівняного виводу на нульовий байт\n" -#: help.c:493 +#: help.c:470 msgid " footer\n" " enable or disable display of the table footer [on, off]\n" msgstr " footer\n" " вмикає або вимикає вивід підписів таблиці [on, off]\n" -#: help.c:495 +#: help.c:472 msgid " format\n" " set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n" msgstr " format\n" " встановити формат виводу [unaligned, aligned, wrapped, html, asciidoc, ...]\n" -#: help.c:497 +#: help.c:474 msgid " linestyle\n" " set the border line drawing style [ascii, old-ascii, unicode]\n" msgstr " linestyle\n" " встановлює стиль малювання ліній рамки [ascii, old-ascii, unicode]\n" -#: help.c:499 +#: help.c:476 msgid " null\n" " set the string to be printed in place of a null value\n" msgstr " null\n" " встановлює рядок, який буде виведено замість значення (null)\n" -#: help.c:501 +#: help.c:478 msgid " numericlocale\n" " enable display of a locale-specific character to separate groups of digits\n" msgstr " numericlocale\n" " вмикає виведення заданого локалью роздільника групи цифр\n" -#: help.c:503 +#: help.c:480 msgid " pager\n" " control when an external pager is used [yes, no, always]\n" msgstr " pager\n" " контролює використання зовнішнього пейджера [yes, no, always]\n" -#: help.c:505 +#: help.c:482 msgid " recordsep\n" " record (line) separator for unaligned output\n" msgstr " recordsep\n" " розділювач записів (рядків) для не вирівняного виводу\n" -#: help.c:507 +#: help.c:484 msgid " recordsep_zero\n" " set record separator for unaligned output to a zero byte\n" msgstr " recordsep_zero\n" " встановлює розділювач записів для невирівняного виводу на нульовий байт\n" -#: help.c:509 +#: help.c:486 msgid " tableattr (or T)\n" " specify attributes for table tag in html format, or proportional\n" " column widths for left-aligned data types in latex-longtable format\n" @@ -3527,19 +3576,19 @@ msgstr " tableattr (або T)\n" " вказує атрибути для тегу table у html форматі або пропорційні \n" " ширини стовпців для вирівняних вліво даних, у latex-longtable форматі\n" -#: help.c:512 +#: help.c:489 msgid " title\n" " set the table title for subsequently printed tables\n" msgstr " title\n" " задає заголовок таблиці для послідовно друкованих таблиць\n" -#: help.c:514 +#: help.c:491 msgid " tuples_only\n" " if set, only actual table data is shown\n" msgstr " tuples_only\n" " якщо встановлено, виводяться лише фактичні табличні дані\n" -#: help.c:516 +#: help.c:493 msgid " unicode_border_linestyle\n" " unicode_column_linestyle\n" " unicode_header_linestyle\n" @@ -3549,19 +3598,19 @@ msgstr " unicode_border_linestyle\n" " unicode_header_linestyle\n" " задає стиль мальювання ліній (Unicode) [single, double]\n" -#: help.c:521 +#: help.c:498 msgid "\n" "Environment variables:\n" msgstr "\n" "Змінні оточення:\n" -#: help.c:525 +#: help.c:502 msgid " NAME=VALUE [NAME=VALUE] psql ...\n" " or \\setenv NAME [VALUE] inside psql\n\n" msgstr " ІМ'Я=ЗНАЧЕННЯ [ІМ'Я=ЗНАЧЕННЯ] psql ...\n" " або \\setenv ІМ'Я [VALUE] всередині psql\n\n" -#: help.c:527 +#: help.c:504 msgid " set NAME=VALUE\n" " psql ...\n" " or \\setenv NAME [VALUE] inside psql\n\n" @@ -3569,107 +3618,107 @@ msgstr " встановлює ІМ'Я=ЗНАЧЕННЯ\n" " psql ...\n" " або \\setenv ІМ'Я [VALUE] всередині psql\n\n" -#: help.c:530 +#: help.c:507 msgid " COLUMNS\n" " number of columns for wrapped format\n" msgstr " COLUMNS\n" " число стовпців для форматування з переносом\n" -#: help.c:532 +#: help.c:509 msgid " PGAPPNAME\n" " same as the application_name connection parameter\n" msgstr " PGAPPNAME\n" " те саме, що параметр підключення application_name\n" -#: help.c:534 +#: help.c:511 msgid " PGDATABASE\n" " same as the dbname connection parameter\n" msgstr " PGDATABASE\n" " те саме, що параметр підключення dbname\n" -#: help.c:536 +#: help.c:513 msgid " PGHOST\n" " same as the host connection parameter\n" msgstr " PGHOST\n" " те саме, що параметр підключення host\n" -#: help.c:538 +#: help.c:515 msgid " PGPASSFILE\n" " password file name\n" msgstr " PGPASSFILE\n" " назва файлу з паролем\n" -#: help.c:540 +#: help.c:517 msgid " PGPASSWORD\n" " connection password (not recommended)\n" msgstr " PGPASSWORD\n" " пароль для підключення (не рекомендується)\n" -#: help.c:542 +#: help.c:519 msgid " PGPORT\n" " same as the port connection parameter\n" msgstr " PGPORT\n" " те саме, що параметр підключення port\n" -#: help.c:544 +#: help.c:521 msgid " PGUSER\n" " same as the user connection parameter\n" msgstr " PGUSER\n" " те саме, що параметр підключення user\n" -#: help.c:546 +#: help.c:523 msgid " PSQL_EDITOR, EDITOR, VISUAL\n" " editor used by the \\e, \\ef, and \\ev commands\n" msgstr " PSQL_EDITOR, EDITOR, VISUAL\n" " редактор для команд \\e, \\ef і \\ev\n" -#: help.c:548 +#: help.c:525 msgid " PSQL_EDITOR_LINENUMBER_ARG\n" " how to specify a line number when invoking the editor\n" msgstr " PSQL_EDITOR_LINENUMBER_ARG\n" " як вказати номер рядка при виклику редактора\n" -#: help.c:550 +#: help.c:527 msgid " PSQL_HISTORY\n" " alternative location for the command history file\n" msgstr " PSQL_HISTORY\n" " альтернативне розміщення файлу з історією команд\n" -#: help.c:552 +#: help.c:529 msgid " PSQL_PAGER, PAGER\n" " name of external pager program\n" msgstr " PSQL_PAGER, PAGER\n" " ім'я програми зовнішнього пейджеру\n" -#: help.c:555 +#: help.c:532 msgid " PSQL_WATCH_PAGER\n" " name of external pager program used for \\watch\n" msgstr " PSQL_WATCH_PAGER\n" " назва зовнішньої програми-пейджера для використання з \\watch\n" -#: help.c:558 +#: help.c:535 msgid " PSQLRC\n" " alternative location for the user's .psqlrc file\n" msgstr " PSQLRC\n" " альтернативне розміщення користувацького файла .psqlrc\n" -#: help.c:560 +#: help.c:537 msgid " SHELL\n" " shell used by the \\! command\n" msgstr " SHELL\n" " оболонка, що використовується командою \\!\n" -#: help.c:562 +#: help.c:539 msgid " TMPDIR\n" " directory for temporary files\n" msgstr " TMPDIR\n" " каталог для тимчасових файлів\n" -#: help.c:622 +#: help.c:599 msgid "Available help:\n" msgstr "Доступна довідка:\n" -#: help.c:717 +#: help.c:694 #, c-format msgid "Command: %s\n" "Description: %s\n" @@ -3682,24 +3731,24 @@ msgstr "Команда: %s\n" "%s\n\n" "URL: %s\n\n" -#: help.c:740 +#: help.c:717 #, c-format msgid "No help available for \"%s\".\n" "Try \\h with no arguments to see available help.\n" msgstr "Немає доступної довідки по команді \"%s\".\n" "Спробуйте \\h без аргументів, щоб подивитись доступну довідку.\n" -#: input.c:216 +#: input.c:215 #, c-format msgid "could not read from input file: %m" msgstr "не вдалося прочитати з вхідного файлу: %m" -#: input.c:477 input.c:515 +#: input.c:476 input.c:514 #, c-format msgid "could not save history to file \"%s\": %m" msgstr "не можливо зберегти історію в файлі \"%s\": %m" -#: input.c:534 +#: input.c:533 #, c-format msgid "history is not supported by this installation" msgstr "ця установка не підтримує історію" @@ -3782,12 +3831,12 @@ msgstr "запит ігнорується; введіть \\endif або нат msgid "reached EOF without finding closing \\endif(s)" msgstr "досягнуто кінця файлу без завершального \\endif" -#: psqlscanslash.l:640 +#: psqlscanslash.l:642 #, c-format msgid "unterminated quoted string" msgstr "незавершений рядок в лапках" -#: psqlscanslash.l:825 +#: psqlscanslash.l:842 #, c-format msgid "%s: out of memory" msgstr "%s: бракує пам'яті" @@ -3795,2427 +3844,2446 @@ msgstr "%s: бракує пам'яті" #: sql_help.c:35 sql_help.c:38 sql_help.c:41 sql_help.c:65 sql_help.c:66 #: sql_help.c:68 sql_help.c:70 sql_help.c:81 sql_help.c:83 sql_help.c:85 #: sql_help.c:113 sql_help.c:119 sql_help.c:121 sql_help.c:123 sql_help.c:125 -#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:238 -#: sql_help.c:240 sql_help.c:241 sql_help.c:243 sql_help.c:245 sql_help.c:248 -#: sql_help.c:250 sql_help.c:252 sql_help.c:254 sql_help.c:266 sql_help.c:267 -#: sql_help.c:268 sql_help.c:270 sql_help.c:319 sql_help.c:321 sql_help.c:323 -#: sql_help.c:325 sql_help.c:394 sql_help.c:399 sql_help.c:401 sql_help.c:443 -#: sql_help.c:445 sql_help.c:448 sql_help.c:450 sql_help.c:519 sql_help.c:524 -#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:593 sql_help.c:595 -#: sql_help.c:597 sql_help.c:599 sql_help.c:601 sql_help.c:604 sql_help.c:606 -#: sql_help.c:609 sql_help.c:620 sql_help.c:622 sql_help.c:666 sql_help.c:668 -#: sql_help.c:670 sql_help.c:673 sql_help.c:675 sql_help.c:677 sql_help.c:714 -#: sql_help.c:718 sql_help.c:722 sql_help.c:741 sql_help.c:744 sql_help.c:747 -#: sql_help.c:776 sql_help.c:788 sql_help.c:796 sql_help.c:799 sql_help.c:802 -#: sql_help.c:817 sql_help.c:820 sql_help.c:849 sql_help.c:854 sql_help.c:859 -#: sql_help.c:864 sql_help.c:869 sql_help.c:896 sql_help.c:898 sql_help.c:900 -#: sql_help.c:902 sql_help.c:905 sql_help.c:907 sql_help.c:954 sql_help.c:999 -#: sql_help.c:1004 sql_help.c:1009 sql_help.c:1014 sql_help.c:1019 -#: sql_help.c:1038 sql_help.c:1049 sql_help.c:1051 sql_help.c:1071 -#: sql_help.c:1081 sql_help.c:1082 sql_help.c:1084 sql_help.c:1086 -#: sql_help.c:1098 sql_help.c:1102 sql_help.c:1104 sql_help.c:1116 -#: sql_help.c:1118 sql_help.c:1120 sql_help.c:1122 sql_help.c:1141 -#: sql_help.c:1143 sql_help.c:1147 sql_help.c:1151 sql_help.c:1155 -#: sql_help.c:1158 sql_help.c:1159 sql_help.c:1160 sql_help.c:1163 -#: sql_help.c:1166 sql_help.c:1168 sql_help.c:1307 sql_help.c:1309 -#: sql_help.c:1312 sql_help.c:1315 sql_help.c:1317 sql_help.c:1319 -#: sql_help.c:1322 sql_help.c:1325 sql_help.c:1442 sql_help.c:1444 -#: sql_help.c:1446 sql_help.c:1449 sql_help.c:1470 sql_help.c:1473 -#: sql_help.c:1476 sql_help.c:1479 sql_help.c:1483 sql_help.c:1485 -#: sql_help.c:1487 sql_help.c:1489 sql_help.c:1503 sql_help.c:1506 -#: sql_help.c:1508 sql_help.c:1510 sql_help.c:1520 sql_help.c:1522 -#: sql_help.c:1532 sql_help.c:1534 sql_help.c:1544 sql_help.c:1547 -#: sql_help.c:1570 sql_help.c:1572 sql_help.c:1574 sql_help.c:1576 -#: sql_help.c:1579 sql_help.c:1581 sql_help.c:1584 sql_help.c:1587 -#: sql_help.c:1638 sql_help.c:1681 sql_help.c:1684 sql_help.c:1686 -#: sql_help.c:1688 sql_help.c:1691 sql_help.c:1693 sql_help.c:1695 -#: sql_help.c:1698 sql_help.c:1750 sql_help.c:1766 sql_help.c:1999 -#: sql_help.c:2068 sql_help.c:2087 sql_help.c:2100 sql_help.c:2158 -#: sql_help.c:2166 sql_help.c:2176 sql_help.c:2203 sql_help.c:2235 -#: sql_help.c:2253 sql_help.c:2281 sql_help.c:2392 sql_help.c:2438 -#: sql_help.c:2463 sql_help.c:2486 sql_help.c:2490 sql_help.c:2524 -#: sql_help.c:2544 sql_help.c:2566 sql_help.c:2580 sql_help.c:2601 -#: sql_help.c:2630 sql_help.c:2665 sql_help.c:2690 sql_help.c:2737 -#: sql_help.c:3032 sql_help.c:3045 sql_help.c:3062 sql_help.c:3078 -#: sql_help.c:3118 sql_help.c:3172 sql_help.c:3176 sql_help.c:3178 -#: sql_help.c:3185 sql_help.c:3204 sql_help.c:3231 sql_help.c:3266 -#: sql_help.c:3278 sql_help.c:3287 sql_help.c:3331 sql_help.c:3345 -#: sql_help.c:3373 sql_help.c:3381 sql_help.c:3393 sql_help.c:3403 -#: sql_help.c:3411 sql_help.c:3419 sql_help.c:3427 sql_help.c:3435 -#: sql_help.c:3444 sql_help.c:3455 sql_help.c:3463 sql_help.c:3471 -#: sql_help.c:3479 sql_help.c:3487 sql_help.c:3497 sql_help.c:3506 -#: sql_help.c:3515 sql_help.c:3523 sql_help.c:3533 sql_help.c:3544 -#: sql_help.c:3552 sql_help.c:3561 sql_help.c:3572 sql_help.c:3581 -#: sql_help.c:3589 sql_help.c:3597 sql_help.c:3605 sql_help.c:3613 -#: sql_help.c:3621 sql_help.c:3629 sql_help.c:3637 sql_help.c:3645 -#: sql_help.c:3653 sql_help.c:3661 sql_help.c:3678 sql_help.c:3687 -#: sql_help.c:3695 sql_help.c:3712 sql_help.c:3727 sql_help.c:4039 -#: sql_help.c:4149 sql_help.c:4178 sql_help.c:4194 sql_help.c:4196 -#: sql_help.c:4699 sql_help.c:4747 sql_help.c:4905 +#: sql_help.c:126 sql_help.c:129 sql_help.c:131 sql_help.c:133 sql_help.c:240 +#: sql_help.c:242 sql_help.c:243 sql_help.c:245 sql_help.c:247 sql_help.c:250 +#: sql_help.c:252 sql_help.c:254 sql_help.c:256 sql_help.c:268 sql_help.c:269 +#: sql_help.c:270 sql_help.c:272 sql_help.c:321 sql_help.c:323 sql_help.c:325 +#: sql_help.c:327 sql_help.c:396 sql_help.c:401 sql_help.c:403 sql_help.c:445 +#: sql_help.c:447 sql_help.c:450 sql_help.c:452 sql_help.c:521 sql_help.c:526 +#: sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:595 sql_help.c:597 +#: sql_help.c:599 sql_help.c:601 sql_help.c:603 sql_help.c:606 sql_help.c:608 +#: sql_help.c:611 sql_help.c:622 sql_help.c:624 sql_help.c:668 sql_help.c:670 +#: sql_help.c:672 sql_help.c:675 sql_help.c:677 sql_help.c:679 sql_help.c:720 +#: sql_help.c:724 sql_help.c:728 sql_help.c:749 sql_help.c:752 sql_help.c:755 +#: sql_help.c:784 sql_help.c:796 sql_help.c:804 sql_help.c:807 sql_help.c:810 +#: sql_help.c:825 sql_help.c:828 sql_help.c:857 sql_help.c:862 sql_help.c:867 +#: sql_help.c:872 sql_help.c:877 sql_help.c:904 sql_help.c:906 sql_help.c:908 +#: sql_help.c:910 sql_help.c:913 sql_help.c:915 sql_help.c:962 sql_help.c:1007 +#: sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 sql_help.c:1027 +#: sql_help.c:1046 sql_help.c:1057 sql_help.c:1059 sql_help.c:1079 +#: sql_help.c:1089 sql_help.c:1090 sql_help.c:1092 sql_help.c:1094 +#: sql_help.c:1106 sql_help.c:1110 sql_help.c:1112 sql_help.c:1124 +#: sql_help.c:1126 sql_help.c:1128 sql_help.c:1130 sql_help.c:1149 +#: sql_help.c:1151 sql_help.c:1155 sql_help.c:1159 sql_help.c:1163 +#: sql_help.c:1166 sql_help.c:1167 sql_help.c:1168 sql_help.c:1171 +#: sql_help.c:1174 sql_help.c:1176 sql_help.c:1316 sql_help.c:1318 +#: sql_help.c:1321 sql_help.c:1324 sql_help.c:1326 sql_help.c:1328 +#: sql_help.c:1331 sql_help.c:1334 sql_help.c:1456 sql_help.c:1458 +#: sql_help.c:1460 sql_help.c:1463 sql_help.c:1484 sql_help.c:1487 +#: sql_help.c:1490 sql_help.c:1493 sql_help.c:1497 sql_help.c:1499 +#: sql_help.c:1501 sql_help.c:1503 sql_help.c:1517 sql_help.c:1520 +#: sql_help.c:1522 sql_help.c:1524 sql_help.c:1534 sql_help.c:1536 +#: sql_help.c:1546 sql_help.c:1548 sql_help.c:1558 sql_help.c:1561 +#: sql_help.c:1584 sql_help.c:1586 sql_help.c:1588 sql_help.c:1590 +#: sql_help.c:1593 sql_help.c:1595 sql_help.c:1598 sql_help.c:1601 +#: sql_help.c:1652 sql_help.c:1695 sql_help.c:1698 sql_help.c:1700 +#: sql_help.c:1702 sql_help.c:1705 sql_help.c:1707 sql_help.c:1709 +#: sql_help.c:1712 sql_help.c:1762 sql_help.c:1778 sql_help.c:2011 +#: sql_help.c:2080 sql_help.c:2099 sql_help.c:2112 sql_help.c:2170 +#: sql_help.c:2178 sql_help.c:2188 sql_help.c:2216 sql_help.c:2249 +#: sql_help.c:2267 sql_help.c:2295 sql_help.c:2406 sql_help.c:2452 +#: sql_help.c:2477 sql_help.c:2500 sql_help.c:2504 sql_help.c:2538 +#: sql_help.c:2558 sql_help.c:2580 sql_help.c:2594 sql_help.c:2615 +#: sql_help.c:2644 sql_help.c:2677 sql_help.c:2700 sql_help.c:2747 +#: sql_help.c:3045 sql_help.c:3058 sql_help.c:3075 sql_help.c:3091 +#: sql_help.c:3131 sql_help.c:3185 sql_help.c:3189 sql_help.c:3191 +#: sql_help.c:3198 sql_help.c:3217 sql_help.c:3244 sql_help.c:3279 +#: sql_help.c:3291 sql_help.c:3300 sql_help.c:3344 sql_help.c:3358 +#: sql_help.c:3386 sql_help.c:3394 sql_help.c:3406 sql_help.c:3416 +#: sql_help.c:3424 sql_help.c:3432 sql_help.c:3440 sql_help.c:3448 +#: sql_help.c:3457 sql_help.c:3468 sql_help.c:3476 sql_help.c:3484 +#: sql_help.c:3492 sql_help.c:3500 sql_help.c:3510 sql_help.c:3519 +#: sql_help.c:3528 sql_help.c:3536 sql_help.c:3546 sql_help.c:3557 +#: sql_help.c:3565 sql_help.c:3574 sql_help.c:3585 sql_help.c:3594 +#: sql_help.c:3602 sql_help.c:3610 sql_help.c:3618 sql_help.c:3626 +#: sql_help.c:3634 sql_help.c:3642 sql_help.c:3650 sql_help.c:3658 +#: sql_help.c:3666 sql_help.c:3674 sql_help.c:3691 sql_help.c:3700 +#: sql_help.c:3708 sql_help.c:3725 sql_help.c:3740 sql_help.c:4053 +#: sql_help.c:4174 sql_help.c:4203 sql_help.c:4219 sql_help.c:4221 +#: sql_help.c:4725 sql_help.c:4773 sql_help.c:4932 msgid "name" msgstr "назва" -#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:330 sql_help.c:1847 -#: sql_help.c:3346 sql_help.c:4467 +#: sql_help.c:36 sql_help.c:39 sql_help.c:42 sql_help.c:332 sql_help.c:1855 +#: sql_help.c:3359 sql_help.c:4492 msgid "aggregate_signature" msgstr "сигнатура_агр_функції" -#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:253 -#: sql_help.c:271 sql_help.c:402 sql_help.c:449 sql_help.c:528 sql_help.c:576 -#: sql_help.c:594 sql_help.c:621 sql_help.c:674 sql_help.c:743 sql_help.c:798 -#: sql_help.c:819 sql_help.c:858 sql_help.c:908 sql_help.c:955 sql_help.c:1008 -#: sql_help.c:1040 sql_help.c:1050 sql_help.c:1085 sql_help.c:1105 -#: sql_help.c:1119 sql_help.c:1169 sql_help.c:1316 sql_help.c:1443 -#: sql_help.c:1486 sql_help.c:1507 sql_help.c:1521 sql_help.c:1533 -#: sql_help.c:1546 sql_help.c:1573 sql_help.c:1639 sql_help.c:1692 +#: sql_help.c:37 sql_help.c:67 sql_help.c:82 sql_help.c:120 sql_help.c:255 +#: sql_help.c:273 sql_help.c:404 sql_help.c:451 sql_help.c:530 sql_help.c:578 +#: sql_help.c:596 sql_help.c:623 sql_help.c:676 sql_help.c:751 sql_help.c:806 +#: sql_help.c:827 sql_help.c:866 sql_help.c:916 sql_help.c:963 sql_help.c:1016 +#: sql_help.c:1048 sql_help.c:1058 sql_help.c:1093 sql_help.c:1113 +#: sql_help.c:1127 sql_help.c:1177 sql_help.c:1325 sql_help.c:1457 +#: sql_help.c:1500 sql_help.c:1521 sql_help.c:1535 sql_help.c:1547 +#: sql_help.c:1560 sql_help.c:1587 sql_help.c:1653 sql_help.c:1706 msgid "new_name" msgstr "нова_назва" -#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:251 -#: sql_help.c:269 sql_help.c:400 sql_help.c:485 sql_help.c:533 sql_help.c:623 -#: sql_help.c:632 sql_help.c:697 sql_help.c:717 sql_help.c:746 sql_help.c:801 -#: sql_help.c:863 sql_help.c:906 sql_help.c:1013 sql_help.c:1052 -#: sql_help.c:1083 sql_help.c:1103 sql_help.c:1117 sql_help.c:1167 -#: sql_help.c:1380 sql_help.c:1445 sql_help.c:1488 sql_help.c:1509 -#: sql_help.c:1571 sql_help.c:1687 sql_help.c:3018 +#: sql_help.c:40 sql_help.c:69 sql_help.c:84 sql_help.c:122 sql_help.c:253 +#: sql_help.c:271 sql_help.c:402 sql_help.c:487 sql_help.c:535 sql_help.c:625 +#: sql_help.c:634 sql_help.c:699 sql_help.c:723 sql_help.c:754 sql_help.c:809 +#: sql_help.c:871 sql_help.c:914 sql_help.c:1021 sql_help.c:1060 +#: sql_help.c:1091 sql_help.c:1111 sql_help.c:1125 sql_help.c:1175 +#: sql_help.c:1391 sql_help.c:1459 sql_help.c:1502 sql_help.c:1523 +#: sql_help.c:1585 sql_help.c:1701 sql_help.c:3031 msgid "new_owner" msgstr "новий_власник" -#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:255 sql_help.c:322 -#: sql_help.c:451 sql_help.c:538 sql_help.c:676 sql_help.c:721 sql_help.c:749 -#: sql_help.c:804 sql_help.c:868 sql_help.c:1018 sql_help.c:1087 -#: sql_help.c:1121 sql_help.c:1318 sql_help.c:1490 sql_help.c:1511 -#: sql_help.c:1523 sql_help.c:1535 sql_help.c:1575 sql_help.c:1694 +#: sql_help.c:43 sql_help.c:71 sql_help.c:86 sql_help.c:257 sql_help.c:324 +#: sql_help.c:453 sql_help.c:540 sql_help.c:678 sql_help.c:727 sql_help.c:757 +#: sql_help.c:812 sql_help.c:876 sql_help.c:1026 sql_help.c:1095 +#: sql_help.c:1129 sql_help.c:1327 sql_help.c:1504 sql_help.c:1525 +#: sql_help.c:1537 sql_help.c:1549 sql_help.c:1589 sql_help.c:1708 msgid "new_schema" msgstr "нова_схема" -#: sql_help.c:44 sql_help.c:1911 sql_help.c:3347 sql_help.c:4496 +#: sql_help.c:44 sql_help.c:1919 sql_help.c:3360 sql_help.c:4521 msgid "where aggregate_signature is:" msgstr "де сигнатура_агр_функції:" -#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:340 sql_help.c:353 -#: sql_help.c:357 sql_help.c:373 sql_help.c:376 sql_help.c:379 sql_help.c:520 -#: sql_help.c:525 sql_help.c:530 sql_help.c:535 sql_help.c:540 sql_help.c:850 -#: sql_help.c:855 sql_help.c:860 sql_help.c:865 sql_help.c:870 sql_help.c:1000 -#: sql_help.c:1005 sql_help.c:1010 sql_help.c:1015 sql_help.c:1020 -#: sql_help.c:1865 sql_help.c:1882 sql_help.c:1888 sql_help.c:1912 -#: sql_help.c:1915 sql_help.c:1918 sql_help.c:2069 sql_help.c:2088 -#: sql_help.c:2091 sql_help.c:2393 sql_help.c:2602 sql_help.c:3348 -#: sql_help.c:3351 sql_help.c:3354 sql_help.c:3445 sql_help.c:3534 -#: sql_help.c:3562 sql_help.c:3914 sql_help.c:4366 sql_help.c:4473 -#: sql_help.c:4480 sql_help.c:4486 sql_help.c:4497 sql_help.c:4500 -#: sql_help.c:4503 +#: sql_help.c:45 sql_help.c:48 sql_help.c:51 sql_help.c:342 sql_help.c:355 +#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 +#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:858 +#: sql_help.c:863 sql_help.c:868 sql_help.c:873 sql_help.c:878 sql_help.c:1008 +#: sql_help.c:1013 sql_help.c:1018 sql_help.c:1023 sql_help.c:1028 +#: sql_help.c:1873 sql_help.c:1890 sql_help.c:1896 sql_help.c:1920 +#: sql_help.c:1923 sql_help.c:1926 sql_help.c:2081 sql_help.c:2100 +#: sql_help.c:2103 sql_help.c:2407 sql_help.c:2616 sql_help.c:3361 +#: sql_help.c:3364 sql_help.c:3367 sql_help.c:3458 sql_help.c:3547 +#: sql_help.c:3575 sql_help.c:3928 sql_help.c:4391 sql_help.c:4498 +#: sql_help.c:4505 sql_help.c:4511 sql_help.c:4522 sql_help.c:4525 +#: sql_help.c:4528 msgid "argmode" msgstr "режим_аргументу" -#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:341 sql_help.c:354 -#: sql_help.c:358 sql_help.c:374 sql_help.c:377 sql_help.c:380 sql_help.c:521 -#: sql_help.c:526 sql_help.c:531 sql_help.c:536 sql_help.c:541 sql_help.c:851 -#: sql_help.c:856 sql_help.c:861 sql_help.c:866 sql_help.c:871 sql_help.c:1001 -#: sql_help.c:1006 sql_help.c:1011 sql_help.c:1016 sql_help.c:1021 -#: sql_help.c:1866 sql_help.c:1883 sql_help.c:1889 sql_help.c:1913 -#: sql_help.c:1916 sql_help.c:1919 sql_help.c:2070 sql_help.c:2089 -#: sql_help.c:2092 sql_help.c:2394 sql_help.c:2603 sql_help.c:3349 -#: sql_help.c:3352 sql_help.c:3355 sql_help.c:3446 sql_help.c:3535 -#: sql_help.c:3563 sql_help.c:4474 sql_help.c:4481 sql_help.c:4487 -#: sql_help.c:4498 sql_help.c:4501 sql_help.c:4504 +#: sql_help.c:46 sql_help.c:49 sql_help.c:52 sql_help.c:343 sql_help.c:356 +#: sql_help.c:360 sql_help.c:376 sql_help.c:379 sql_help.c:382 sql_help.c:523 +#: sql_help.c:528 sql_help.c:533 sql_help.c:538 sql_help.c:543 sql_help.c:859 +#: sql_help.c:864 sql_help.c:869 sql_help.c:874 sql_help.c:879 sql_help.c:1009 +#: sql_help.c:1014 sql_help.c:1019 sql_help.c:1024 sql_help.c:1029 +#: sql_help.c:1874 sql_help.c:1891 sql_help.c:1897 sql_help.c:1921 +#: sql_help.c:1924 sql_help.c:1927 sql_help.c:2082 sql_help.c:2101 +#: sql_help.c:2104 sql_help.c:2408 sql_help.c:2617 sql_help.c:3362 +#: sql_help.c:3365 sql_help.c:3368 sql_help.c:3459 sql_help.c:3548 +#: sql_help.c:3576 sql_help.c:4499 sql_help.c:4506 sql_help.c:4512 +#: sql_help.c:4523 sql_help.c:4526 sql_help.c:4529 msgid "argname" msgstr "ім'я_аргументу" -#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:342 sql_help.c:355 -#: sql_help.c:359 sql_help.c:375 sql_help.c:378 sql_help.c:381 sql_help.c:522 -#: sql_help.c:527 sql_help.c:532 sql_help.c:537 sql_help.c:542 sql_help.c:852 -#: sql_help.c:857 sql_help.c:862 sql_help.c:867 sql_help.c:872 sql_help.c:1002 -#: sql_help.c:1007 sql_help.c:1012 sql_help.c:1017 sql_help.c:1022 -#: sql_help.c:1867 sql_help.c:1884 sql_help.c:1890 sql_help.c:1914 -#: sql_help.c:1917 sql_help.c:1920 sql_help.c:2395 sql_help.c:2604 -#: sql_help.c:3350 sql_help.c:3353 sql_help.c:3356 sql_help.c:3447 -#: sql_help.c:3536 sql_help.c:3564 sql_help.c:4475 sql_help.c:4482 -#: sql_help.c:4488 sql_help.c:4499 sql_help.c:4502 sql_help.c:4505 +#: sql_help.c:47 sql_help.c:50 sql_help.c:53 sql_help.c:344 sql_help.c:357 +#: sql_help.c:361 sql_help.c:377 sql_help.c:380 sql_help.c:383 sql_help.c:524 +#: sql_help.c:529 sql_help.c:534 sql_help.c:539 sql_help.c:544 sql_help.c:860 +#: sql_help.c:865 sql_help.c:870 sql_help.c:875 sql_help.c:880 sql_help.c:1010 +#: sql_help.c:1015 sql_help.c:1020 sql_help.c:1025 sql_help.c:1030 +#: sql_help.c:1875 sql_help.c:1892 sql_help.c:1898 sql_help.c:1922 +#: sql_help.c:1925 sql_help.c:1928 sql_help.c:2409 sql_help.c:2618 +#: sql_help.c:3363 sql_help.c:3366 sql_help.c:3369 sql_help.c:3460 +#: sql_help.c:3549 sql_help.c:3577 sql_help.c:4500 sql_help.c:4507 +#: sql_help.c:4513 sql_help.c:4524 sql_help.c:4527 sql_help.c:4530 msgid "argtype" msgstr "тип_аргументу" -#: sql_help.c:114 sql_help.c:397 sql_help.c:474 sql_help.c:486 sql_help.c:949 -#: sql_help.c:1100 sql_help.c:1504 sql_help.c:1633 sql_help.c:1665 -#: sql_help.c:1718 sql_help.c:1782 sql_help.c:1969 sql_help.c:1976 -#: sql_help.c:2284 sql_help.c:2334 sql_help.c:2341 sql_help.c:2350 -#: sql_help.c:2439 sql_help.c:2666 sql_help.c:2759 sql_help.c:3047 -#: sql_help.c:3232 sql_help.c:3254 sql_help.c:3394 sql_help.c:3750 -#: sql_help.c:3958 sql_help.c:4193 sql_help.c:4195 sql_help.c:4972 +#: sql_help.c:114 sql_help.c:399 sql_help.c:476 sql_help.c:488 sql_help.c:957 +#: sql_help.c:1108 sql_help.c:1518 sql_help.c:1647 sql_help.c:1679 +#: sql_help.c:1731 sql_help.c:1790 sql_help.c:1979 sql_help.c:1986 +#: sql_help.c:2298 sql_help.c:2348 sql_help.c:2355 sql_help.c:2364 +#: sql_help.c:2453 sql_help.c:2678 sql_help.c:2769 sql_help.c:3060 +#: sql_help.c:3245 sql_help.c:3267 sql_help.c:3407 sql_help.c:3764 +#: sql_help.c:3972 sql_help.c:4218 sql_help.c:4220 sql_help.c:4998 msgid "option" msgstr "параметр" -#: sql_help.c:115 sql_help.c:950 sql_help.c:1634 sql_help.c:2440 -#: sql_help.c:2667 sql_help.c:3233 sql_help.c:3395 +#: sql_help.c:115 sql_help.c:958 sql_help.c:1648 sql_help.c:2454 +#: sql_help.c:2679 sql_help.c:3246 sql_help.c:3408 msgid "where option can be:" msgstr "де параметр може бути:" -#: sql_help.c:116 sql_help.c:2216 +#: sql_help.c:116 sql_help.c:2230 msgid "allowconn" msgstr "дозвол_підкл" -#: sql_help.c:117 sql_help.c:951 sql_help.c:1635 sql_help.c:2217 -#: sql_help.c:2441 sql_help.c:2668 sql_help.c:3234 +#: sql_help.c:117 sql_help.c:959 sql_help.c:1649 sql_help.c:2231 +#: sql_help.c:2455 sql_help.c:2680 sql_help.c:3247 msgid "connlimit" msgstr "ліміт_підключень" -#: sql_help.c:118 sql_help.c:2218 +#: sql_help.c:118 sql_help.c:2232 msgid "istemplate" msgstr "чи_шаблон" -#: sql_help.c:124 sql_help.c:611 sql_help.c:679 sql_help.c:693 sql_help.c:1321 -#: sql_help.c:1373 sql_help.c:4199 +#: sql_help.c:124 sql_help.c:613 sql_help.c:681 sql_help.c:695 sql_help.c:1330 +#: sql_help.c:1384 sql_help.c:4224 msgid "new_tablespace" msgstr "новий_табл_простір" -#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:548 sql_help.c:550 -#: sql_help.c:551 sql_help.c:875 sql_help.c:877 sql_help.c:878 sql_help.c:958 -#: sql_help.c:962 sql_help.c:965 sql_help.c:1027 sql_help.c:1029 -#: sql_help.c:1030 sql_help.c:1180 sql_help.c:1182 sql_help.c:1642 -#: sql_help.c:1646 sql_help.c:1649 sql_help.c:2405 sql_help.c:2608 -#: sql_help.c:3926 sql_help.c:4217 sql_help.c:4378 sql_help.c:4687 +#: sql_help.c:127 sql_help.c:130 sql_help.c:132 sql_help.c:550 sql_help.c:552 +#: sql_help.c:553 sql_help.c:883 sql_help.c:885 sql_help.c:886 sql_help.c:966 +#: sql_help.c:970 sql_help.c:973 sql_help.c:1035 sql_help.c:1037 +#: sql_help.c:1038 sql_help.c:1188 sql_help.c:1190 sql_help.c:1656 +#: sql_help.c:1660 sql_help.c:1663 sql_help.c:2419 sql_help.c:2622 +#: sql_help.c:3940 sql_help.c:4242 sql_help.c:4403 sql_help.c:4713 msgid "configuration_parameter" msgstr "параметр_конфігурації" -#: sql_help.c:128 sql_help.c:398 sql_help.c:469 sql_help.c:475 sql_help.c:487 -#: sql_help.c:549 sql_help.c:603 sql_help.c:685 sql_help.c:695 sql_help.c:876 -#: sql_help.c:904 sql_help.c:959 sql_help.c:1028 sql_help.c:1101 -#: sql_help.c:1146 sql_help.c:1150 sql_help.c:1154 sql_help.c:1157 -#: sql_help.c:1162 sql_help.c:1165 sql_help.c:1181 sql_help.c:1352 -#: sql_help.c:1375 sql_help.c:1423 sql_help.c:1448 sql_help.c:1505 -#: sql_help.c:1589 sql_help.c:1643 sql_help.c:1666 sql_help.c:2285 -#: sql_help.c:2335 sql_help.c:2342 sql_help.c:2351 sql_help.c:2406 -#: sql_help.c:2407 sql_help.c:2471 sql_help.c:2474 sql_help.c:2508 -#: sql_help.c:2609 sql_help.c:2610 sql_help.c:2633 sql_help.c:2760 -#: sql_help.c:2799 sql_help.c:2909 sql_help.c:2922 sql_help.c:2936 -#: sql_help.c:2977 sql_help.c:3004 sql_help.c:3021 sql_help.c:3048 -#: sql_help.c:3255 sql_help.c:3959 sql_help.c:4688 sql_help.c:4689 -#: sql_help.c:4690 sql_help.c:4691 +#: sql_help.c:128 sql_help.c:400 sql_help.c:471 sql_help.c:477 sql_help.c:489 +#: sql_help.c:551 sql_help.c:605 sql_help.c:687 sql_help.c:697 sql_help.c:884 +#: sql_help.c:912 sql_help.c:967 sql_help.c:1036 sql_help.c:1109 +#: sql_help.c:1154 sql_help.c:1158 sql_help.c:1162 sql_help.c:1165 +#: sql_help.c:1170 sql_help.c:1173 sql_help.c:1189 sql_help.c:1363 +#: sql_help.c:1386 sql_help.c:1434 sql_help.c:1442 sql_help.c:1462 +#: sql_help.c:1519 sql_help.c:1603 sql_help.c:1657 sql_help.c:1680 +#: sql_help.c:2299 sql_help.c:2349 sql_help.c:2356 sql_help.c:2365 +#: sql_help.c:2420 sql_help.c:2421 sql_help.c:2485 sql_help.c:2488 +#: sql_help.c:2522 sql_help.c:2623 sql_help.c:2624 sql_help.c:2647 +#: sql_help.c:2770 sql_help.c:2809 sql_help.c:2919 sql_help.c:2932 +#: sql_help.c:2946 sql_help.c:2987 sql_help.c:2995 sql_help.c:3017 +#: sql_help.c:3034 sql_help.c:3061 sql_help.c:3268 sql_help.c:3973 +#: sql_help.c:4714 sql_help.c:4715 sql_help.c:4716 sql_help.c:4717 msgid "value" msgstr "значення" -#: sql_help.c:200 +#: sql_help.c:202 msgid "target_role" msgstr "цільова_роль" -#: sql_help.c:201 sql_help.c:913 sql_help.c:2269 sql_help.c:2638 -#: sql_help.c:2715 sql_help.c:2720 sql_help.c:3889 sql_help.c:3898 -#: sql_help.c:3917 sql_help.c:3929 sql_help.c:4341 sql_help.c:4350 -#: sql_help.c:4369 sql_help.c:4381 +#: sql_help.c:203 sql_help.c:921 sql_help.c:2283 sql_help.c:2652 +#: sql_help.c:2725 sql_help.c:2730 sql_help.c:3903 sql_help.c:3912 +#: sql_help.c:3931 sql_help.c:3943 sql_help.c:4366 sql_help.c:4375 +#: sql_help.c:4394 sql_help.c:4406 msgid "schema_name" msgstr "ім'я_схеми" -#: sql_help.c:202 +#: sql_help.c:204 msgid "abbreviated_grant_or_revoke" msgstr "скорочено_GRANT_або_REVOKE" -#: sql_help.c:203 +#: sql_help.c:205 msgid "where abbreviated_grant_or_revoke is one of:" msgstr "де скорочено_GRANT_або_REVOKE є одним з:" -#: sql_help.c:204 sql_help.c:205 sql_help.c:206 sql_help.c:207 sql_help.c:208 -#: sql_help.c:209 sql_help.c:210 sql_help.c:211 sql_help.c:212 sql_help.c:213 -#: sql_help.c:574 sql_help.c:610 sql_help.c:678 sql_help.c:822 sql_help.c:969 -#: sql_help.c:1320 sql_help.c:1653 sql_help.c:2444 sql_help.c:2445 -#: sql_help.c:2446 sql_help.c:2447 sql_help.c:2448 sql_help.c:2582 -#: sql_help.c:2671 sql_help.c:2672 sql_help.c:2673 sql_help.c:2674 -#: sql_help.c:2675 sql_help.c:3237 sql_help.c:3238 sql_help.c:3239 -#: sql_help.c:3240 sql_help.c:3241 sql_help.c:3938 sql_help.c:3942 -#: sql_help.c:4390 sql_help.c:4394 sql_help.c:4709 +#: sql_help.c:206 sql_help.c:207 sql_help.c:208 sql_help.c:209 sql_help.c:210 +#: sql_help.c:211 sql_help.c:212 sql_help.c:213 sql_help.c:214 sql_help.c:215 +#: sql_help.c:576 sql_help.c:612 sql_help.c:680 sql_help.c:830 sql_help.c:977 +#: sql_help.c:1329 sql_help.c:1667 sql_help.c:2458 sql_help.c:2459 +#: sql_help.c:2460 sql_help.c:2461 sql_help.c:2462 sql_help.c:2596 +#: sql_help.c:2683 sql_help.c:2684 sql_help.c:2685 sql_help.c:3250 +#: sql_help.c:3251 sql_help.c:3252 sql_help.c:3253 sql_help.c:3254 +#: sql_help.c:3952 sql_help.c:3956 sql_help.c:4415 sql_help.c:4419 +#: sql_help.c:4735 msgid "role_name" msgstr "ім'я_ролі" -#: sql_help.c:239 sql_help.c:462 sql_help.c:912 sql_help.c:1336 sql_help.c:1338 -#: sql_help.c:1390 sql_help.c:1402 sql_help.c:1427 sql_help.c:1683 -#: sql_help.c:2238 sql_help.c:2242 sql_help.c:2354 sql_help.c:2359 -#: sql_help.c:2467 sql_help.c:2637 sql_help.c:2776 sql_help.c:2781 -#: sql_help.c:2783 sql_help.c:2904 sql_help.c:2917 sql_help.c:2931 -#: sql_help.c:2940 sql_help.c:2952 sql_help.c:2981 sql_help.c:3990 -#: sql_help.c:4005 sql_help.c:4007 sql_help.c:4094 sql_help.c:4097 -#: sql_help.c:4099 sql_help.c:4560 sql_help.c:4561 sql_help.c:4570 -#: sql_help.c:4617 sql_help.c:4618 sql_help.c:4619 sql_help.c:4620 -#: sql_help.c:4621 sql_help.c:4622 sql_help.c:4662 sql_help.c:4663 -#: sql_help.c:4668 sql_help.c:4673 sql_help.c:4817 sql_help.c:4818 -#: sql_help.c:4827 sql_help.c:4874 sql_help.c:4875 sql_help.c:4876 -#: sql_help.c:4877 sql_help.c:4878 sql_help.c:4879 sql_help.c:4933 -#: sql_help.c:4935 sql_help.c:5003 sql_help.c:5063 sql_help.c:5064 -#: sql_help.c:5073 sql_help.c:5120 sql_help.c:5121 sql_help.c:5122 -#: sql_help.c:5123 sql_help.c:5124 sql_help.c:5125 +#: sql_help.c:241 sql_help.c:464 sql_help.c:920 sql_help.c:1345 sql_help.c:1347 +#: sql_help.c:1351 sql_help.c:1401 sql_help.c:1413 sql_help.c:1438 +#: sql_help.c:1697 sql_help.c:2252 sql_help.c:2256 sql_help.c:2368 +#: sql_help.c:2373 sql_help.c:2481 sql_help.c:2651 sql_help.c:2786 +#: sql_help.c:2791 sql_help.c:2793 sql_help.c:2914 sql_help.c:2927 +#: sql_help.c:2941 sql_help.c:2950 sql_help.c:2962 sql_help.c:2991 +#: sql_help.c:4004 sql_help.c:4019 sql_help.c:4021 sql_help.c:4117 +#: sql_help.c:4120 sql_help.c:4122 sql_help.c:4585 sql_help.c:4586 +#: sql_help.c:4595 sql_help.c:4642 sql_help.c:4643 sql_help.c:4644 +#: sql_help.c:4645 sql_help.c:4646 sql_help.c:4647 sql_help.c:4688 +#: sql_help.c:4689 sql_help.c:4694 sql_help.c:4699 sql_help.c:4843 +#: sql_help.c:4844 sql_help.c:4853 sql_help.c:4900 sql_help.c:4901 +#: sql_help.c:4902 sql_help.c:4903 sql_help.c:4904 sql_help.c:4905 +#: sql_help.c:4960 sql_help.c:4962 sql_help.c:5028 sql_help.c:5088 +#: sql_help.c:5089 sql_help.c:5098 sql_help.c:5145 sql_help.c:5146 +#: sql_help.c:5147 sql_help.c:5148 sql_help.c:5149 sql_help.c:5150 msgid "expression" msgstr "вираз" -#: sql_help.c:242 +#: sql_help.c:244 sql_help.c:2253 msgid "domain_constraint" msgstr "обмеження_домену" -#: sql_help.c:244 sql_help.c:246 sql_help.c:249 sql_help.c:477 sql_help.c:478 -#: sql_help.c:1313 sql_help.c:1360 sql_help.c:1361 sql_help.c:1362 -#: sql_help.c:1389 sql_help.c:1401 sql_help.c:1418 sql_help.c:1853 -#: sql_help.c:1855 sql_help.c:2241 sql_help.c:2353 sql_help.c:2358 -#: sql_help.c:2939 sql_help.c:2951 sql_help.c:4002 +#: sql_help.c:246 sql_help.c:248 sql_help.c:251 sql_help.c:479 sql_help.c:480 +#: sql_help.c:1322 sql_help.c:1371 sql_help.c:1372 sql_help.c:1373 +#: sql_help.c:1400 sql_help.c:1412 sql_help.c:1429 sql_help.c:1861 +#: sql_help.c:1863 sql_help.c:2255 sql_help.c:2367 sql_help.c:2372 +#: sql_help.c:2949 sql_help.c:2961 sql_help.c:4016 msgid "constraint_name" msgstr "ім'я_обмеження" -#: sql_help.c:247 sql_help.c:1314 +#: sql_help.c:249 sql_help.c:1323 msgid "new_constraint_name" msgstr "ім'я_нового_обмеження" -#: sql_help.c:320 sql_help.c:1099 +#: sql_help.c:322 sql_help.c:1107 msgid "new_version" msgstr "нова_версія" -#: sql_help.c:324 sql_help.c:326 +#: sql_help.c:326 sql_help.c:328 msgid "member_object" msgstr "елемент_об'єкт" -#: sql_help.c:327 +#: sql_help.c:329 msgid "where member_object is:" msgstr "де елемент_об'єкт є:" -#: sql_help.c:328 sql_help.c:333 sql_help.c:334 sql_help.c:335 sql_help.c:336 -#: sql_help.c:337 sql_help.c:338 sql_help.c:343 sql_help.c:347 sql_help.c:349 -#: sql_help.c:351 sql_help.c:360 sql_help.c:361 sql_help.c:362 sql_help.c:363 -#: sql_help.c:364 sql_help.c:365 sql_help.c:366 sql_help.c:367 sql_help.c:370 -#: sql_help.c:371 sql_help.c:1845 sql_help.c:1850 sql_help.c:1857 -#: sql_help.c:1858 sql_help.c:1859 sql_help.c:1860 sql_help.c:1861 -#: sql_help.c:1862 sql_help.c:1863 sql_help.c:1868 sql_help.c:1870 -#: sql_help.c:1874 sql_help.c:1876 sql_help.c:1880 sql_help.c:1885 -#: sql_help.c:1886 sql_help.c:1893 sql_help.c:1894 sql_help.c:1895 -#: sql_help.c:1896 sql_help.c:1897 sql_help.c:1898 sql_help.c:1899 -#: sql_help.c:1900 sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 -#: sql_help.c:1908 sql_help.c:1909 sql_help.c:4463 sql_help.c:4468 -#: sql_help.c:4469 sql_help.c:4470 sql_help.c:4471 sql_help.c:4477 -#: sql_help.c:4478 sql_help.c:4483 sql_help.c:4484 sql_help.c:4489 -#: sql_help.c:4490 sql_help.c:4491 sql_help.c:4492 sql_help.c:4493 -#: sql_help.c:4494 +#: sql_help.c:330 sql_help.c:335 sql_help.c:336 sql_help.c:337 sql_help.c:338 +#: sql_help.c:339 sql_help.c:340 sql_help.c:345 sql_help.c:349 sql_help.c:351 +#: sql_help.c:353 sql_help.c:362 sql_help.c:363 sql_help.c:364 sql_help.c:365 +#: sql_help.c:366 sql_help.c:367 sql_help.c:368 sql_help.c:369 sql_help.c:372 +#: sql_help.c:373 sql_help.c:1853 sql_help.c:1858 sql_help.c:1865 +#: sql_help.c:1866 sql_help.c:1867 sql_help.c:1868 sql_help.c:1869 +#: sql_help.c:1870 sql_help.c:1871 sql_help.c:1876 sql_help.c:1878 +#: sql_help.c:1882 sql_help.c:1884 sql_help.c:1888 sql_help.c:1893 +#: sql_help.c:1894 sql_help.c:1901 sql_help.c:1902 sql_help.c:1903 +#: sql_help.c:1904 sql_help.c:1905 sql_help.c:1906 sql_help.c:1907 +#: sql_help.c:1908 sql_help.c:1909 sql_help.c:1910 sql_help.c:1911 +#: sql_help.c:1916 sql_help.c:1917 sql_help.c:4488 sql_help.c:4493 +#: sql_help.c:4494 sql_help.c:4495 sql_help.c:4496 sql_help.c:4502 +#: sql_help.c:4503 sql_help.c:4508 sql_help.c:4509 sql_help.c:4514 +#: sql_help.c:4515 sql_help.c:4516 sql_help.c:4517 sql_help.c:4518 +#: sql_help.c:4519 msgid "object_name" msgstr "ім'я_об'єкту" -#: sql_help.c:329 sql_help.c:1846 sql_help.c:4466 +#: sql_help.c:331 sql_help.c:1854 sql_help.c:4491 msgid "aggregate_name" msgstr "ім'я_агр_функції" -#: sql_help.c:331 sql_help.c:1848 sql_help.c:2134 sql_help.c:2138 -#: sql_help.c:2140 sql_help.c:3364 +#: sql_help.c:333 sql_help.c:1856 sql_help.c:2146 sql_help.c:2150 +#: sql_help.c:2152 sql_help.c:3377 msgid "source_type" msgstr "початковий_тип" -#: sql_help.c:332 sql_help.c:1849 sql_help.c:2135 sql_help.c:2139 -#: sql_help.c:2141 sql_help.c:3365 +#: sql_help.c:334 sql_help.c:1857 sql_help.c:2147 sql_help.c:2151 +#: sql_help.c:2153 sql_help.c:3378 msgid "target_type" msgstr "тип_цілі" -#: sql_help.c:339 sql_help.c:786 sql_help.c:1864 sql_help.c:2136 -#: sql_help.c:2179 sql_help.c:2257 sql_help.c:2525 sql_help.c:2556 -#: sql_help.c:3124 sql_help.c:4365 sql_help.c:4472 sql_help.c:4589 -#: sql_help.c:4593 sql_help.c:4597 sql_help.c:4600 sql_help.c:4846 -#: sql_help.c:4850 sql_help.c:4854 sql_help.c:4857 sql_help.c:5092 -#: sql_help.c:5096 sql_help.c:5100 sql_help.c:5103 +#: sql_help.c:341 sql_help.c:794 sql_help.c:1872 sql_help.c:2148 +#: sql_help.c:2191 sql_help.c:2271 sql_help.c:2539 sql_help.c:2570 +#: sql_help.c:3137 sql_help.c:4390 sql_help.c:4497 sql_help.c:4614 +#: sql_help.c:4618 sql_help.c:4622 sql_help.c:4625 sql_help.c:4872 +#: sql_help.c:4876 sql_help.c:4880 sql_help.c:4883 sql_help.c:5117 +#: sql_help.c:5121 sql_help.c:5125 sql_help.c:5128 msgid "function_name" msgstr "ім'я_функції" -#: sql_help.c:344 sql_help.c:779 sql_help.c:1871 sql_help.c:2549 +#: sql_help.c:346 sql_help.c:787 sql_help.c:1879 sql_help.c:2563 msgid "operator_name" msgstr "ім'я_оператора" -#: sql_help.c:345 sql_help.c:715 sql_help.c:719 sql_help.c:723 sql_help.c:1872 -#: sql_help.c:2526 sql_help.c:3488 +#: sql_help.c:347 sql_help.c:721 sql_help.c:725 sql_help.c:729 sql_help.c:1880 +#: sql_help.c:2540 sql_help.c:3501 msgid "left_type" msgstr "тип_ліворуч" -#: sql_help.c:346 sql_help.c:716 sql_help.c:720 sql_help.c:724 sql_help.c:1873 -#: sql_help.c:2527 sql_help.c:3489 +#: sql_help.c:348 sql_help.c:722 sql_help.c:726 sql_help.c:730 sql_help.c:1881 +#: sql_help.c:2541 sql_help.c:3502 msgid "right_type" msgstr "тип_праворуч" -#: sql_help.c:348 sql_help.c:350 sql_help.c:742 sql_help.c:745 sql_help.c:748 -#: sql_help.c:777 sql_help.c:789 sql_help.c:797 sql_help.c:800 sql_help.c:803 -#: sql_help.c:1407 sql_help.c:1875 sql_help.c:1877 sql_help.c:2546 -#: sql_help.c:2567 sql_help.c:2957 sql_help.c:3498 sql_help.c:3507 +#: sql_help.c:350 sql_help.c:352 sql_help.c:750 sql_help.c:753 sql_help.c:756 +#: sql_help.c:785 sql_help.c:797 sql_help.c:805 sql_help.c:808 sql_help.c:811 +#: sql_help.c:1418 sql_help.c:1883 sql_help.c:1885 sql_help.c:2560 +#: sql_help.c:2581 sql_help.c:2967 sql_help.c:3511 sql_help.c:3520 msgid "index_method" msgstr "метод_індексу" -#: sql_help.c:352 sql_help.c:1881 sql_help.c:4479 +#: sql_help.c:354 sql_help.c:1889 sql_help.c:4504 msgid "procedure_name" msgstr "назва_процедури" -#: sql_help.c:356 sql_help.c:1887 sql_help.c:3913 sql_help.c:4485 +#: sql_help.c:358 sql_help.c:1895 sql_help.c:3927 sql_help.c:4510 msgid "routine_name" msgstr "ім'я_підпрограми" -#: sql_help.c:368 sql_help.c:1379 sql_help.c:1904 sql_help.c:2401 -#: sql_help.c:2607 sql_help.c:2912 sql_help.c:3091 sql_help.c:3669 -#: sql_help.c:3935 sql_help.c:4387 +#: sql_help.c:370 sql_help.c:1390 sql_help.c:1912 sql_help.c:2415 +#: sql_help.c:2621 sql_help.c:2922 sql_help.c:3104 sql_help.c:3682 +#: sql_help.c:3949 sql_help.c:4412 msgid "type_name" msgstr "назва_типу" -#: sql_help.c:369 sql_help.c:1905 sql_help.c:2400 sql_help.c:2606 -#: sql_help.c:3092 sql_help.c:3322 sql_help.c:3670 sql_help.c:3920 -#: sql_help.c:4372 +#: sql_help.c:371 sql_help.c:1913 sql_help.c:2414 sql_help.c:2620 +#: sql_help.c:3105 sql_help.c:3335 sql_help.c:3683 sql_help.c:3934 +#: sql_help.c:4397 msgid "lang_name" msgstr "назва_мови" -#: sql_help.c:372 +#: sql_help.c:374 msgid "and aggregate_signature is:" msgstr "і сигнатура_агр_функції:" -#: sql_help.c:395 sql_help.c:2001 sql_help.c:2282 +#: sql_help.c:397 sql_help.c:2013 sql_help.c:2296 msgid "handler_function" msgstr "функція_обробник" -#: sql_help.c:396 sql_help.c:2283 +#: sql_help.c:398 sql_help.c:2297 msgid "validator_function" msgstr "функція_перевірки" -#: sql_help.c:444 sql_help.c:523 sql_help.c:667 sql_help.c:853 sql_help.c:1003 -#: sql_help.c:1308 sql_help.c:1580 +#: sql_help.c:446 sql_help.c:525 sql_help.c:669 sql_help.c:861 sql_help.c:1011 +#: sql_help.c:1317 sql_help.c:1594 msgid "action" msgstr "дія" -#: sql_help.c:446 sql_help.c:453 sql_help.c:457 sql_help.c:458 sql_help.c:461 -#: sql_help.c:463 sql_help.c:464 sql_help.c:465 sql_help.c:467 sql_help.c:470 -#: sql_help.c:472 sql_help.c:473 sql_help.c:671 sql_help.c:681 sql_help.c:683 -#: sql_help.c:686 sql_help.c:688 sql_help.c:689 sql_help.c:911 sql_help.c:1080 -#: sql_help.c:1310 sql_help.c:1328 sql_help.c:1332 sql_help.c:1333 -#: sql_help.c:1337 sql_help.c:1339 sql_help.c:1340 sql_help.c:1341 -#: sql_help.c:1342 sql_help.c:1344 sql_help.c:1347 sql_help.c:1348 -#: sql_help.c:1350 sql_help.c:1353 sql_help.c:1355 sql_help.c:1356 -#: sql_help.c:1403 sql_help.c:1405 sql_help.c:1412 sql_help.c:1421 -#: sql_help.c:1426 sql_help.c:1430 sql_help.c:1431 sql_help.c:1682 -#: sql_help.c:1685 sql_help.c:1689 sql_help.c:1727 sql_help.c:1852 -#: sql_help.c:1966 sql_help.c:1972 sql_help.c:1986 sql_help.c:1987 -#: sql_help.c:1988 sql_help.c:2332 sql_help.c:2345 sql_help.c:2398 -#: sql_help.c:2466 sql_help.c:2472 sql_help.c:2505 sql_help.c:2636 -#: sql_help.c:2745 sql_help.c:2780 sql_help.c:2782 sql_help.c:2894 -#: sql_help.c:2903 sql_help.c:2913 sql_help.c:2916 sql_help.c:2926 -#: sql_help.c:2930 sql_help.c:2953 sql_help.c:2955 sql_help.c:2962 -#: sql_help.c:2975 sql_help.c:2980 sql_help.c:2984 sql_help.c:2985 -#: sql_help.c:3001 sql_help.c:3127 sql_help.c:3267 sql_help.c:3892 -#: sql_help.c:3893 sql_help.c:3989 sql_help.c:4004 sql_help.c:4006 -#: sql_help.c:4008 sql_help.c:4093 sql_help.c:4096 sql_help.c:4098 -#: sql_help.c:4344 sql_help.c:4345 sql_help.c:4465 sql_help.c:4626 -#: sql_help.c:4632 sql_help.c:4634 sql_help.c:4883 sql_help.c:4889 -#: sql_help.c:4891 sql_help.c:4932 sql_help.c:4934 sql_help.c:4936 -#: sql_help.c:4991 sql_help.c:5129 sql_help.c:5135 sql_help.c:5137 +#: sql_help.c:448 sql_help.c:455 sql_help.c:459 sql_help.c:460 sql_help.c:463 +#: sql_help.c:465 sql_help.c:466 sql_help.c:467 sql_help.c:469 sql_help.c:472 +#: sql_help.c:474 sql_help.c:475 sql_help.c:673 sql_help.c:683 sql_help.c:685 +#: sql_help.c:688 sql_help.c:690 sql_help.c:691 sql_help.c:919 sql_help.c:1088 +#: sql_help.c:1319 sql_help.c:1337 sql_help.c:1341 sql_help.c:1342 +#: sql_help.c:1346 sql_help.c:1348 sql_help.c:1349 sql_help.c:1350 +#: sql_help.c:1352 sql_help.c:1353 sql_help.c:1355 sql_help.c:1358 +#: sql_help.c:1359 sql_help.c:1361 sql_help.c:1364 sql_help.c:1366 +#: sql_help.c:1367 sql_help.c:1414 sql_help.c:1416 sql_help.c:1423 +#: sql_help.c:1432 sql_help.c:1437 sql_help.c:1444 sql_help.c:1445 +#: sql_help.c:1696 sql_help.c:1699 sql_help.c:1703 sql_help.c:1739 +#: sql_help.c:1860 sql_help.c:1976 sql_help.c:1982 sql_help.c:1996 +#: sql_help.c:1997 sql_help.c:1998 sql_help.c:2346 sql_help.c:2359 +#: sql_help.c:2412 sql_help.c:2480 sql_help.c:2486 sql_help.c:2519 +#: sql_help.c:2650 sql_help.c:2755 sql_help.c:2790 sql_help.c:2792 +#: sql_help.c:2904 sql_help.c:2913 sql_help.c:2923 sql_help.c:2926 +#: sql_help.c:2936 sql_help.c:2940 sql_help.c:2963 sql_help.c:2965 +#: sql_help.c:2972 sql_help.c:2985 sql_help.c:2990 sql_help.c:2997 +#: sql_help.c:2998 sql_help.c:3014 sql_help.c:3140 sql_help.c:3280 +#: sql_help.c:3906 sql_help.c:3907 sql_help.c:4003 sql_help.c:4018 +#: sql_help.c:4020 sql_help.c:4022 sql_help.c:4116 sql_help.c:4119 +#: sql_help.c:4121 sql_help.c:4123 sql_help.c:4369 sql_help.c:4370 +#: sql_help.c:4490 sql_help.c:4651 sql_help.c:4658 sql_help.c:4660 +#: sql_help.c:4909 sql_help.c:4916 sql_help.c:4918 sql_help.c:4959 +#: sql_help.c:4961 sql_help.c:4963 sql_help.c:5016 sql_help.c:5154 +#: sql_help.c:5161 sql_help.c:5163 msgid "column_name" msgstr "назва_стовпця" -#: sql_help.c:447 sql_help.c:672 sql_help.c:1311 sql_help.c:1690 +#: sql_help.c:449 sql_help.c:674 sql_help.c:1320 sql_help.c:1704 msgid "new_column_name" msgstr "нова_назва_стовпця" -#: sql_help.c:452 sql_help.c:544 sql_help.c:680 sql_help.c:874 sql_help.c:1024 -#: sql_help.c:1327 sql_help.c:1590 +#: sql_help.c:454 sql_help.c:546 sql_help.c:682 sql_help.c:882 sql_help.c:1032 +#: sql_help.c:1336 sql_help.c:1604 msgid "where action is one of:" msgstr "де допустима дія:" -#: sql_help.c:454 sql_help.c:459 sql_help.c:1072 sql_help.c:1329 -#: sql_help.c:1334 sql_help.c:1592 sql_help.c:1596 sql_help.c:2236 -#: sql_help.c:2333 sql_help.c:2545 sql_help.c:2738 sql_help.c:2895 -#: sql_help.c:3174 sql_help.c:4150 +#: sql_help.c:456 sql_help.c:461 sql_help.c:1080 sql_help.c:1338 +#: sql_help.c:1343 sql_help.c:1606 sql_help.c:1610 sql_help.c:2250 +#: sql_help.c:2347 sql_help.c:2559 sql_help.c:2748 sql_help.c:2905 +#: sql_help.c:3187 sql_help.c:4175 msgid "data_type" msgstr "тип_даних" -#: sql_help.c:455 sql_help.c:460 sql_help.c:1330 sql_help.c:1335 -#: sql_help.c:1593 sql_help.c:1597 sql_help.c:2237 sql_help.c:2336 -#: sql_help.c:2468 sql_help.c:2897 sql_help.c:2905 sql_help.c:2918 -#: sql_help.c:2932 sql_help.c:3175 sql_help.c:3181 sql_help.c:3999 +#: sql_help.c:457 sql_help.c:462 sql_help.c:1339 sql_help.c:1344 +#: sql_help.c:1439 sql_help.c:1607 sql_help.c:1611 sql_help.c:2251 +#: sql_help.c:2350 sql_help.c:2482 sql_help.c:2907 sql_help.c:2915 +#: sql_help.c:2928 sql_help.c:2942 sql_help.c:2992 sql_help.c:3188 +#: sql_help.c:3194 sql_help.c:4013 msgid "collation" msgstr "правила_сортування" -#: sql_help.c:456 sql_help.c:1331 sql_help.c:2337 sql_help.c:2346 -#: sql_help.c:2898 sql_help.c:2914 sql_help.c:2927 +#: sql_help.c:458 sql_help.c:1340 sql_help.c:2351 sql_help.c:2360 +#: sql_help.c:2908 sql_help.c:2924 sql_help.c:2937 msgid "column_constraint" msgstr "обмеження_стовпця" -#: sql_help.c:466 sql_help.c:608 sql_help.c:682 sql_help.c:1349 sql_help.c:4985 +#: sql_help.c:468 sql_help.c:610 sql_help.c:684 sql_help.c:1360 sql_help.c:5010 msgid "integer" msgstr "ціле" -#: sql_help.c:468 sql_help.c:471 sql_help.c:684 sql_help.c:687 sql_help.c:1351 -#: sql_help.c:1354 +#: sql_help.c:470 sql_help.c:473 sql_help.c:686 sql_help.c:689 sql_help.c:1362 +#: sql_help.c:1365 msgid "attribute_option" msgstr "параметр_атрибуту" -#: sql_help.c:476 sql_help.c:1358 sql_help.c:2338 sql_help.c:2347 -#: sql_help.c:2899 sql_help.c:2915 sql_help.c:2928 +#: sql_help.c:478 sql_help.c:1369 sql_help.c:2352 sql_help.c:2361 +#: sql_help.c:2909 sql_help.c:2925 sql_help.c:2938 msgid "table_constraint" msgstr "обмеження_таблиці" -#: sql_help.c:479 sql_help.c:480 sql_help.c:481 sql_help.c:482 sql_help.c:1363 -#: sql_help.c:1364 sql_help.c:1365 sql_help.c:1366 sql_help.c:1906 +#: sql_help.c:481 sql_help.c:482 sql_help.c:483 sql_help.c:484 sql_help.c:1374 +#: sql_help.c:1375 sql_help.c:1376 sql_help.c:1377 sql_help.c:1914 msgid "trigger_name" msgstr "ім'я_тригеру" -#: sql_help.c:483 sql_help.c:484 sql_help.c:1377 sql_help.c:1378 -#: sql_help.c:2339 sql_help.c:2344 sql_help.c:2902 sql_help.c:2925 +#: sql_help.c:485 sql_help.c:486 sql_help.c:1388 sql_help.c:1389 +#: sql_help.c:2353 sql_help.c:2358 sql_help.c:2912 sql_help.c:2935 msgid "parent_table" msgstr "батьківська_таблиця" -#: sql_help.c:543 sql_help.c:600 sql_help.c:669 sql_help.c:873 sql_help.c:1023 -#: sql_help.c:1549 sql_help.c:2268 +#: sql_help.c:545 sql_help.c:602 sql_help.c:671 sql_help.c:881 sql_help.c:1031 +#: sql_help.c:1563 sql_help.c:2282 msgid "extension_name" msgstr "ім'я_розширення" -#: sql_help.c:545 sql_help.c:1025 sql_help.c:2402 +#: sql_help.c:547 sql_help.c:1033 sql_help.c:2416 msgid "execution_cost" msgstr "вартість_виконання" -#: sql_help.c:546 sql_help.c:1026 sql_help.c:2403 +#: sql_help.c:548 sql_help.c:1034 sql_help.c:2417 msgid "result_rows" msgstr "рядки_результату" -#: sql_help.c:547 sql_help.c:2404 +#: sql_help.c:549 sql_help.c:2418 msgid "support_function" msgstr "функція_підтримки" -#: sql_help.c:569 sql_help.c:571 sql_help.c:948 sql_help.c:956 sql_help.c:960 -#: sql_help.c:963 sql_help.c:966 sql_help.c:1632 sql_help.c:1640 -#: sql_help.c:1644 sql_help.c:1647 sql_help.c:1650 sql_help.c:2716 -#: sql_help.c:2718 sql_help.c:2721 sql_help.c:2722 sql_help.c:3890 -#: sql_help.c:3891 sql_help.c:3895 sql_help.c:3896 sql_help.c:3899 -#: sql_help.c:3900 sql_help.c:3902 sql_help.c:3903 sql_help.c:3905 -#: sql_help.c:3906 sql_help.c:3908 sql_help.c:3909 sql_help.c:3911 -#: sql_help.c:3912 sql_help.c:3918 sql_help.c:3919 sql_help.c:3921 -#: sql_help.c:3922 sql_help.c:3924 sql_help.c:3925 sql_help.c:3927 -#: sql_help.c:3928 sql_help.c:3930 sql_help.c:3931 sql_help.c:3933 -#: sql_help.c:3934 sql_help.c:3936 sql_help.c:3937 sql_help.c:3939 -#: sql_help.c:3940 sql_help.c:4342 sql_help.c:4343 sql_help.c:4347 -#: sql_help.c:4348 sql_help.c:4351 sql_help.c:4352 sql_help.c:4354 -#: sql_help.c:4355 sql_help.c:4357 sql_help.c:4358 sql_help.c:4360 -#: sql_help.c:4361 sql_help.c:4363 sql_help.c:4364 sql_help.c:4370 -#: sql_help.c:4371 sql_help.c:4373 sql_help.c:4374 sql_help.c:4376 -#: sql_help.c:4377 sql_help.c:4379 sql_help.c:4380 sql_help.c:4382 -#: sql_help.c:4383 sql_help.c:4385 sql_help.c:4386 sql_help.c:4388 -#: sql_help.c:4389 sql_help.c:4391 sql_help.c:4392 +#: sql_help.c:571 sql_help.c:573 sql_help.c:956 sql_help.c:964 sql_help.c:968 +#: sql_help.c:971 sql_help.c:974 sql_help.c:1646 sql_help.c:1654 +#: sql_help.c:1658 sql_help.c:1661 sql_help.c:1664 sql_help.c:2726 +#: sql_help.c:2728 sql_help.c:2731 sql_help.c:2732 sql_help.c:3904 +#: sql_help.c:3905 sql_help.c:3909 sql_help.c:3910 sql_help.c:3913 +#: sql_help.c:3914 sql_help.c:3916 sql_help.c:3917 sql_help.c:3919 +#: sql_help.c:3920 sql_help.c:3922 sql_help.c:3923 sql_help.c:3925 +#: sql_help.c:3926 sql_help.c:3932 sql_help.c:3933 sql_help.c:3935 +#: sql_help.c:3936 sql_help.c:3938 sql_help.c:3939 sql_help.c:3941 +#: sql_help.c:3942 sql_help.c:3944 sql_help.c:3945 sql_help.c:3947 +#: sql_help.c:3948 sql_help.c:3950 sql_help.c:3951 sql_help.c:3953 +#: sql_help.c:3954 sql_help.c:4367 sql_help.c:4368 sql_help.c:4372 +#: sql_help.c:4373 sql_help.c:4376 sql_help.c:4377 sql_help.c:4379 +#: sql_help.c:4380 sql_help.c:4382 sql_help.c:4383 sql_help.c:4385 +#: sql_help.c:4386 sql_help.c:4388 sql_help.c:4389 sql_help.c:4395 +#: sql_help.c:4396 sql_help.c:4398 sql_help.c:4399 sql_help.c:4401 +#: sql_help.c:4402 sql_help.c:4404 sql_help.c:4405 sql_help.c:4407 +#: sql_help.c:4408 sql_help.c:4410 sql_help.c:4411 sql_help.c:4413 +#: sql_help.c:4414 sql_help.c:4416 sql_help.c:4417 msgid "role_specification" msgstr "вказання_ролі" -#: sql_help.c:570 sql_help.c:572 sql_help.c:1663 sql_help.c:2204 -#: sql_help.c:2724 sql_help.c:3252 sql_help.c:3703 sql_help.c:4719 +#: sql_help.c:572 sql_help.c:574 sql_help.c:1677 sql_help.c:2217 +#: sql_help.c:2734 sql_help.c:3265 sql_help.c:3716 sql_help.c:4745 msgid "user_name" msgstr "ім'я_користувача" -#: sql_help.c:573 sql_help.c:968 sql_help.c:1652 sql_help.c:2723 -#: sql_help.c:3941 sql_help.c:4393 +#: sql_help.c:575 sql_help.c:976 sql_help.c:1666 sql_help.c:2733 +#: sql_help.c:3955 sql_help.c:4418 msgid "where role_specification can be:" msgstr "де вказання_ролі може бути:" -#: sql_help.c:575 +#: sql_help.c:577 msgid "group_name" msgstr "ім'я_групи" -#: sql_help.c:596 sql_help.c:1424 sql_help.c:2215 sql_help.c:2475 -#: sql_help.c:2509 sql_help.c:2910 sql_help.c:2923 sql_help.c:2937 -#: sql_help.c:2978 sql_help.c:3005 sql_help.c:3017 sql_help.c:3932 -#: sql_help.c:4384 +#: sql_help.c:598 sql_help.c:1435 sql_help.c:2229 sql_help.c:2489 +#: sql_help.c:2523 sql_help.c:2920 sql_help.c:2933 sql_help.c:2947 +#: sql_help.c:2988 sql_help.c:3018 sql_help.c:3030 sql_help.c:3946 +#: sql_help.c:4409 msgid "tablespace_name" msgstr "ім'я_табличного_простору" -#: sql_help.c:598 sql_help.c:691 sql_help.c:1371 sql_help.c:1381 -#: sql_help.c:1419 sql_help.c:1781 sql_help.c:1784 +#: sql_help.c:600 sql_help.c:693 sql_help.c:1382 sql_help.c:1392 +#: sql_help.c:1430 sql_help.c:1792 msgid "index_name" msgstr "назва_індексу" -#: sql_help.c:602 sql_help.c:605 sql_help.c:694 sql_help.c:696 sql_help.c:1374 -#: sql_help.c:1376 sql_help.c:1422 sql_help.c:2473 sql_help.c:2507 -#: sql_help.c:2908 sql_help.c:2921 sql_help.c:2935 sql_help.c:2976 -#: sql_help.c:3003 +#: sql_help.c:604 sql_help.c:607 sql_help.c:696 sql_help.c:698 sql_help.c:1385 +#: sql_help.c:1387 sql_help.c:1433 sql_help.c:2487 sql_help.c:2521 +#: sql_help.c:2918 sql_help.c:2931 sql_help.c:2945 sql_help.c:2986 +#: sql_help.c:3016 msgid "storage_parameter" msgstr "параметр_зберігання" -#: sql_help.c:607 +#: sql_help.c:609 msgid "column_number" msgstr "номер_стовпця" -#: sql_help.c:631 sql_help.c:1869 sql_help.c:4476 +#: sql_help.c:633 sql_help.c:1877 sql_help.c:4501 msgid "large_object_oid" msgstr "oid_великого_об'єкта" -#: sql_help.c:690 sql_help.c:1357 sql_help.c:2896 +#: sql_help.c:692 sql_help.c:1368 sql_help.c:2906 msgid "compression_method" msgstr "compression_method" -#: sql_help.c:692 sql_help.c:1372 +#: sql_help.c:694 sql_help.c:1383 msgid "new_access_method" msgstr "новий_метод_доступа" -#: sql_help.c:725 sql_help.c:2530 +#: sql_help.c:731 sql_help.c:2544 msgid "res_proc" msgstr "res_процедура" -#: sql_help.c:726 sql_help.c:2531 +#: sql_help.c:732 sql_help.c:2545 msgid "join_proc" msgstr "процедура_приєднання" -#: sql_help.c:778 sql_help.c:790 sql_help.c:2548 +#: sql_help.c:733 sql_help.c:2542 +msgid "com_op" +msgstr "комут_оператор" + +#: sql_help.c:734 sql_help.c:2543 +msgid "neg_op" +msgstr "зворотній_оператор" + +#: sql_help.c:786 sql_help.c:798 sql_help.c:2562 msgid "strategy_number" msgstr "номер_стратегії" -#: sql_help.c:780 sql_help.c:781 sql_help.c:784 sql_help.c:785 sql_help.c:791 -#: sql_help.c:792 sql_help.c:794 sql_help.c:795 sql_help.c:2550 sql_help.c:2551 -#: sql_help.c:2554 sql_help.c:2555 +#: sql_help.c:788 sql_help.c:789 sql_help.c:792 sql_help.c:793 sql_help.c:799 +#: sql_help.c:800 sql_help.c:802 sql_help.c:803 sql_help.c:2564 sql_help.c:2565 +#: sql_help.c:2568 sql_help.c:2569 msgid "op_type" msgstr "тип_операції" -#: sql_help.c:782 sql_help.c:2552 +#: sql_help.c:790 sql_help.c:2566 msgid "sort_family_name" msgstr "ім'я_родини_сортування" -#: sql_help.c:783 sql_help.c:793 sql_help.c:2553 +#: sql_help.c:791 sql_help.c:801 sql_help.c:2567 msgid "support_number" msgstr "номер_підтримки" -#: sql_help.c:787 sql_help.c:2137 sql_help.c:2557 sql_help.c:3094 -#: sql_help.c:3096 +#: sql_help.c:795 sql_help.c:2149 sql_help.c:2571 sql_help.c:3107 +#: sql_help.c:3109 msgid "argument_type" msgstr "тип_аргументу" -#: sql_help.c:818 sql_help.c:821 sql_help.c:910 sql_help.c:1039 sql_help.c:1079 -#: sql_help.c:1545 sql_help.c:1548 sql_help.c:1726 sql_help.c:1780 -#: sql_help.c:1783 sql_help.c:1854 sql_help.c:1879 sql_help.c:1892 -#: sql_help.c:1907 sql_help.c:1965 sql_help.c:1971 sql_help.c:2331 -#: sql_help.c:2343 sql_help.c:2464 sql_help.c:2504 sql_help.c:2581 -#: sql_help.c:2635 sql_help.c:2692 sql_help.c:2744 sql_help.c:2777 -#: sql_help.c:2784 sql_help.c:2893 sql_help.c:2911 sql_help.c:2924 -#: sql_help.c:3000 sql_help.c:3120 sql_help.c:3301 sql_help.c:3524 -#: sql_help.c:3573 sql_help.c:3679 sql_help.c:3888 sql_help.c:3894 -#: sql_help.c:3955 sql_help.c:3987 sql_help.c:4340 sql_help.c:4346 -#: sql_help.c:4464 sql_help.c:4575 sql_help.c:4577 sql_help.c:4639 -#: sql_help.c:4678 sql_help.c:4832 sql_help.c:4834 sql_help.c:4896 -#: sql_help.c:4930 sql_help.c:4990 sql_help.c:5078 sql_help.c:5080 -#: sql_help.c:5142 +#: sql_help.c:826 sql_help.c:829 sql_help.c:918 sql_help.c:1047 sql_help.c:1087 +#: sql_help.c:1559 sql_help.c:1562 sql_help.c:1738 sql_help.c:1791 +#: sql_help.c:1862 sql_help.c:1887 sql_help.c:1900 sql_help.c:1915 +#: sql_help.c:1975 sql_help.c:1981 sql_help.c:2345 sql_help.c:2357 +#: sql_help.c:2478 sql_help.c:2518 sql_help.c:2595 sql_help.c:2649 +#: sql_help.c:2702 sql_help.c:2754 sql_help.c:2787 sql_help.c:2794 +#: sql_help.c:2903 sql_help.c:2921 sql_help.c:2934 sql_help.c:3013 +#: sql_help.c:3133 sql_help.c:3314 sql_help.c:3537 sql_help.c:3586 +#: sql_help.c:3692 sql_help.c:3902 sql_help.c:3908 sql_help.c:3969 +#: sql_help.c:4001 sql_help.c:4365 sql_help.c:4371 sql_help.c:4489 +#: sql_help.c:4602 sql_help.c:4665 sql_help.c:4704 sql_help.c:4860 +#: sql_help.c:4923 sql_help.c:4957 sql_help.c:5015 sql_help.c:5105 +#: sql_help.c:5168 msgid "table_name" msgstr "ім'я_таблиці" -#: sql_help.c:823 sql_help.c:2583 +#: sql_help.c:831 sql_help.c:2597 msgid "using_expression" msgstr "вираз_використання" -#: sql_help.c:824 sql_help.c:2584 +#: sql_help.c:832 sql_help.c:2598 msgid "check_expression" msgstr "вираз_перевірки" -#: sql_help.c:897 sql_help.c:899 sql_help.c:901 sql_help.c:2631 +#: sql_help.c:905 sql_help.c:907 sql_help.c:909 sql_help.c:2645 msgid "publication_object" msgstr "об'єкт_публікація" -#: sql_help.c:903 sql_help.c:2632 +#: sql_help.c:911 sql_help.c:2646 msgid "publication_parameter" msgstr "параметр_публікації" -#: sql_help.c:909 sql_help.c:2634 +#: sql_help.c:917 sql_help.c:2648 msgid "where publication_object is one of:" msgstr "де об'єкт_публікація є одним з:" -#: sql_help.c:952 sql_help.c:1636 sql_help.c:2442 sql_help.c:2669 -#: sql_help.c:3235 +#: sql_help.c:960 sql_help.c:1650 sql_help.c:2456 sql_help.c:2681 +#: sql_help.c:3248 msgid "password" msgstr "пароль" -#: sql_help.c:953 sql_help.c:1637 sql_help.c:2443 sql_help.c:2670 -#: sql_help.c:3236 +#: sql_help.c:961 sql_help.c:1651 sql_help.c:2457 sql_help.c:2682 +#: sql_help.c:3249 msgid "timestamp" msgstr "мітка часу" -#: sql_help.c:957 sql_help.c:961 sql_help.c:964 sql_help.c:967 sql_help.c:1641 -#: sql_help.c:1645 sql_help.c:1648 sql_help.c:1651 sql_help.c:3901 -#: sql_help.c:4353 +#: sql_help.c:965 sql_help.c:969 sql_help.c:972 sql_help.c:975 sql_help.c:1655 +#: sql_help.c:1659 sql_help.c:1662 sql_help.c:1665 sql_help.c:3915 +#: sql_help.c:4378 msgid "database_name" msgstr "назва_бази_даних" -#: sql_help.c:1073 sql_help.c:2739 +#: sql_help.c:1081 sql_help.c:2749 msgid "increment" msgstr "інкремент" -#: sql_help.c:1074 sql_help.c:2740 +#: sql_help.c:1082 sql_help.c:2750 msgid "minvalue" msgstr "мін_значення" -#: sql_help.c:1075 sql_help.c:2741 +#: sql_help.c:1083 sql_help.c:2751 msgid "maxvalue" msgstr "макс_значення" -#: sql_help.c:1076 sql_help.c:2742 sql_help.c:4573 sql_help.c:4676 -#: sql_help.c:4830 sql_help.c:5007 sql_help.c:5076 +#: sql_help.c:1084 sql_help.c:2752 sql_help.c:4598 sql_help.c:4702 +#: sql_help.c:4856 sql_help.c:5032 sql_help.c:5101 msgid "start" msgstr "початок" -#: sql_help.c:1077 sql_help.c:1346 +#: sql_help.c:1085 sql_help.c:1357 msgid "restart" msgstr "перезапуск" -#: sql_help.c:1078 sql_help.c:2743 +#: sql_help.c:1086 sql_help.c:2753 msgid "cache" msgstr "кеш" -#: sql_help.c:1123 +#: sql_help.c:1131 msgid "new_target" msgstr "нова_ціль" -#: sql_help.c:1142 sql_help.c:2796 +#: sql_help.c:1150 sql_help.c:2806 msgid "conninfo" msgstr "інформація_підключення" -#: sql_help.c:1144 sql_help.c:1148 sql_help.c:1152 sql_help.c:2797 +#: sql_help.c:1152 sql_help.c:1156 sql_help.c:1160 sql_help.c:2807 msgid "publication_name" msgstr "назва_публікації" -#: sql_help.c:1145 sql_help.c:1149 sql_help.c:1153 +#: sql_help.c:1153 sql_help.c:1157 sql_help.c:1161 msgid "publication_option" msgstr "publication_option" -#: sql_help.c:1156 +#: sql_help.c:1164 msgid "refresh_option" msgstr "опція_оновлення" -#: sql_help.c:1161 sql_help.c:2798 +#: sql_help.c:1169 sql_help.c:2808 msgid "subscription_parameter" msgstr "параметр_підписки" -#: sql_help.c:1164 +#: sql_help.c:1172 msgid "skip_option" msgstr "опція_пропуска" -#: sql_help.c:1323 sql_help.c:1326 +#: sql_help.c:1332 sql_help.c:1335 msgid "partition_name" msgstr "ім'я_розділу" -#: sql_help.c:1324 sql_help.c:2348 sql_help.c:2929 +#: sql_help.c:1333 sql_help.c:2362 sql_help.c:2939 msgid "partition_bound_spec" msgstr "специфікація_рамок_розділу" -#: sql_help.c:1343 sql_help.c:1393 sql_help.c:2943 +#: sql_help.c:1354 sql_help.c:1404 sql_help.c:2953 msgid "sequence_options" msgstr "опції_послідовності" -#: sql_help.c:1345 +#: sql_help.c:1356 msgid "sequence_option" msgstr "опція_послідовності" -#: sql_help.c:1359 +#: sql_help.c:1370 msgid "table_constraint_using_index" msgstr "індекс_обмеження_таблиці" -#: sql_help.c:1367 sql_help.c:1368 sql_help.c:1369 sql_help.c:1370 +#: sql_help.c:1378 sql_help.c:1379 sql_help.c:1380 sql_help.c:1381 msgid "rewrite_rule_name" msgstr "ім'я_правила_перезапису" -#: sql_help.c:1382 sql_help.c:2360 sql_help.c:2968 +#: sql_help.c:1393 sql_help.c:2374 sql_help.c:2978 msgid "and partition_bound_spec is:" msgstr "і специфікація_рамок_розділу:" -#: sql_help.c:1383 sql_help.c:1384 sql_help.c:1385 sql_help.c:2361 -#: sql_help.c:2362 sql_help.c:2363 sql_help.c:2969 sql_help.c:2970 -#: sql_help.c:2971 +#: sql_help.c:1394 sql_help.c:1395 sql_help.c:1396 sql_help.c:2375 +#: sql_help.c:2376 sql_help.c:2377 sql_help.c:2979 sql_help.c:2980 +#: sql_help.c:2981 msgid "partition_bound_expr" msgstr "код_секції" -#: sql_help.c:1386 sql_help.c:1387 sql_help.c:2364 sql_help.c:2365 -#: sql_help.c:2972 sql_help.c:2973 +#: sql_help.c:1397 sql_help.c:1398 sql_help.c:2378 sql_help.c:2379 +#: sql_help.c:2982 sql_help.c:2983 msgid "numeric_literal" msgstr "числовий_літерал" -#: sql_help.c:1388 +#: sql_help.c:1399 msgid "and column_constraint is:" msgstr "і обмеження_стовпця:" -#: sql_help.c:1391 sql_help.c:2355 sql_help.c:2396 sql_help.c:2605 -#: sql_help.c:2941 +#: sql_help.c:1402 sql_help.c:2369 sql_help.c:2410 sql_help.c:2619 +#: sql_help.c:2951 msgid "default_expr" msgstr "вираз_за_замовчуванням" -#: sql_help.c:1392 sql_help.c:2356 sql_help.c:2942 +#: sql_help.c:1403 sql_help.c:2370 sql_help.c:2952 msgid "generation_expr" msgstr "код_генерації" -#: sql_help.c:1394 sql_help.c:1395 sql_help.c:1404 sql_help.c:1406 -#: sql_help.c:1410 sql_help.c:2944 sql_help.c:2945 sql_help.c:2954 -#: sql_help.c:2956 sql_help.c:2960 +#: sql_help.c:1405 sql_help.c:1406 sql_help.c:1415 sql_help.c:1417 +#: sql_help.c:1421 sql_help.c:2954 sql_help.c:2955 sql_help.c:2964 +#: sql_help.c:2966 sql_help.c:2970 msgid "index_parameters" msgstr "параметри_індексу" -#: sql_help.c:1396 sql_help.c:1413 sql_help.c:2946 sql_help.c:2963 +#: sql_help.c:1407 sql_help.c:1424 sql_help.c:2956 sql_help.c:2973 msgid "reftable" msgstr "залежна_таблиця" -#: sql_help.c:1397 sql_help.c:1414 sql_help.c:2947 sql_help.c:2964 +#: sql_help.c:1408 sql_help.c:1425 sql_help.c:2957 sql_help.c:2974 msgid "refcolumn" msgstr "залежний_стовпець" -#: sql_help.c:1398 sql_help.c:1399 sql_help.c:1415 sql_help.c:1416 -#: sql_help.c:2948 sql_help.c:2949 sql_help.c:2965 sql_help.c:2966 +#: sql_help.c:1409 sql_help.c:1410 sql_help.c:1426 sql_help.c:1427 +#: sql_help.c:2958 sql_help.c:2959 sql_help.c:2975 sql_help.c:2976 msgid "referential_action" msgstr "дія_посилання" -#: sql_help.c:1400 sql_help.c:2357 sql_help.c:2950 +#: sql_help.c:1411 sql_help.c:2371 sql_help.c:2960 msgid "and table_constraint is:" msgstr "і обмеження_таблиці:" -#: sql_help.c:1408 sql_help.c:2958 +#: sql_help.c:1419 sql_help.c:2968 msgid "exclude_element" msgstr "об'єкт_виключення" -#: sql_help.c:1409 sql_help.c:2959 sql_help.c:4571 sql_help.c:4674 -#: sql_help.c:4828 sql_help.c:5005 sql_help.c:5074 +#: sql_help.c:1420 sql_help.c:2969 sql_help.c:4596 sql_help.c:4700 +#: sql_help.c:4854 sql_help.c:5030 sql_help.c:5099 msgid "operator" msgstr "оператор" -#: sql_help.c:1411 sql_help.c:2476 sql_help.c:2961 +#: sql_help.c:1422 sql_help.c:2490 sql_help.c:2971 msgid "predicate" msgstr "предикат" -#: sql_help.c:1417 +#: sql_help.c:1428 msgid "and table_constraint_using_index is:" msgstr "і індекс_обмеження_таблиці:" -#: sql_help.c:1420 sql_help.c:2974 +#: sql_help.c:1431 sql_help.c:2984 msgid "index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:" msgstr "параметри_індексу в обмеженнях UNIQUE, PRIMARY KEY, EXCLUDE:" -#: sql_help.c:1425 sql_help.c:2979 +#: sql_help.c:1436 sql_help.c:2989 msgid "exclude_element in an EXCLUDE constraint is:" msgstr "елемент_виключення в обмеженні EXCLUDE:" -#: sql_help.c:1428 sql_help.c:2469 sql_help.c:2906 sql_help.c:2919 -#: sql_help.c:2933 sql_help.c:2982 sql_help.c:4000 +#: sql_help.c:1440 sql_help.c:2483 sql_help.c:2916 sql_help.c:2929 +#: sql_help.c:2943 sql_help.c:2993 sql_help.c:4014 msgid "opclass" msgstr "клас_оператора" -#: sql_help.c:1429 sql_help.c:2983 +#: sql_help.c:1441 sql_help.c:2484 sql_help.c:2994 +msgid "opclass_parameter" +msgstr "opclass_parameter" + +#: sql_help.c:1443 sql_help.c:2996 msgid "referential_action in a FOREIGN KEY/REFERENCES constraint is:" msgstr "посилання на дію в обмеженні FOREIGN KEY/REFERENCES:" -#: sql_help.c:1447 sql_help.c:1450 sql_help.c:3020 +#: sql_help.c:1461 sql_help.c:1464 sql_help.c:3033 msgid "tablespace_option" msgstr "опція_табличного_простору" -#: sql_help.c:1471 sql_help.c:1474 sql_help.c:1480 sql_help.c:1484 +#: sql_help.c:1485 sql_help.c:1488 sql_help.c:1494 sql_help.c:1498 msgid "token_type" msgstr "тип_токену" -#: sql_help.c:1472 sql_help.c:1475 +#: sql_help.c:1486 sql_help.c:1489 msgid "dictionary_name" msgstr "ім'я_словника" -#: sql_help.c:1477 sql_help.c:1481 +#: sql_help.c:1491 sql_help.c:1495 msgid "old_dictionary" msgstr "старий_словник" -#: sql_help.c:1478 sql_help.c:1482 +#: sql_help.c:1492 sql_help.c:1496 msgid "new_dictionary" msgstr "новий_словник" -#: sql_help.c:1577 sql_help.c:1591 sql_help.c:1594 sql_help.c:1595 -#: sql_help.c:3173 +#: sql_help.c:1591 sql_help.c:1605 sql_help.c:1608 sql_help.c:1609 +#: sql_help.c:3186 msgid "attribute_name" msgstr "ім'я_атрибута" -#: sql_help.c:1578 +#: sql_help.c:1592 msgid "new_attribute_name" msgstr "нове_ім'я_атрибута" -#: sql_help.c:1582 sql_help.c:1586 +#: sql_help.c:1596 sql_help.c:1600 msgid "new_enum_value" msgstr "нове_значення_перерахування" -#: sql_help.c:1583 +#: sql_help.c:1597 msgid "neighbor_enum_value" msgstr "сусіднє_значення_перерахування" -#: sql_help.c:1585 +#: sql_help.c:1599 msgid "existing_enum_value" msgstr "існуюче_значення_перерахування" -#: sql_help.c:1588 +#: sql_help.c:1602 msgid "property" msgstr "властивість" -#: sql_help.c:1664 sql_help.c:2340 sql_help.c:2349 sql_help.c:2755 -#: sql_help.c:3253 sql_help.c:3704 sql_help.c:3910 sql_help.c:3956 -#: sql_help.c:4362 +#: sql_help.c:1678 sql_help.c:2354 sql_help.c:2363 sql_help.c:2765 +#: sql_help.c:3266 sql_help.c:3717 sql_help.c:3924 sql_help.c:3970 +#: sql_help.c:4387 msgid "server_name" msgstr "назва_серверу" -#: sql_help.c:1696 sql_help.c:1699 sql_help.c:3268 +#: sql_help.c:1710 sql_help.c:1713 sql_help.c:3281 msgid "view_option_name" msgstr "ім'я_параметра_представлення" -#: sql_help.c:1697 sql_help.c:3269 +#: sql_help.c:1711 sql_help.c:3282 msgid "view_option_value" msgstr "значення_параметра_представлення" -#: sql_help.c:1719 sql_help.c:1720 sql_help.c:4973 sql_help.c:4974 +#: sql_help.c:1732 sql_help.c:4999 msgid "table_and_columns" msgstr "таблиця_і_стовпці" -#: sql_help.c:1721 sql_help.c:1785 sql_help.c:1977 sql_help.c:3753 -#: sql_help.c:4197 sql_help.c:4975 +#: sql_help.c:1733 sql_help.c:1793 sql_help.c:1987 sql_help.c:3766 +#: sql_help.c:4222 sql_help.c:5000 msgid "where option can be one of:" msgstr "де параметр може бути одним із:" -#: sql_help.c:1722 sql_help.c:1723 sql_help.c:1786 sql_help.c:1979 -#: sql_help.c:1983 sql_help.c:2163 sql_help.c:3754 sql_help.c:3755 -#: sql_help.c:3756 sql_help.c:3757 sql_help.c:3758 sql_help.c:3759 -#: sql_help.c:3760 sql_help.c:3761 sql_help.c:3762 sql_help.c:4198 -#: sql_help.c:4200 sql_help.c:4976 sql_help.c:4977 sql_help.c:4978 -#: sql_help.c:4979 sql_help.c:4980 sql_help.c:4981 sql_help.c:4982 -#: sql_help.c:4983 sql_help.c:4984 sql_help.c:4986 sql_help.c:4987 +#: sql_help.c:1734 sql_help.c:1735 sql_help.c:1794 sql_help.c:1989 +#: sql_help.c:1993 sql_help.c:2175 sql_help.c:3767 sql_help.c:3768 +#: sql_help.c:3769 sql_help.c:3770 sql_help.c:3771 sql_help.c:3772 +#: sql_help.c:3773 sql_help.c:3774 sql_help.c:3775 sql_help.c:3776 +#: sql_help.c:4223 sql_help.c:4225 sql_help.c:5001 sql_help.c:5002 +#: sql_help.c:5003 sql_help.c:5004 sql_help.c:5005 sql_help.c:5006 +#: sql_help.c:5007 sql_help.c:5008 sql_help.c:5009 sql_help.c:5011 +#: sql_help.c:5012 msgid "boolean" msgstr "логічний" -#: sql_help.c:1724 sql_help.c:4988 +#: sql_help.c:1736 sql_help.c:5013 msgid "size" msgstr "розмір" -#: sql_help.c:1725 sql_help.c:4989 +#: sql_help.c:1737 sql_help.c:5014 msgid "and table_and_columns is:" msgstr "і таблиця_і_стовпці:" -#: sql_help.c:1741 sql_help.c:4735 sql_help.c:4737 sql_help.c:4761 +#: sql_help.c:1753 sql_help.c:4761 sql_help.c:4763 sql_help.c:4787 msgid "transaction_mode" msgstr "режим_транзакції" -#: sql_help.c:1742 sql_help.c:4738 sql_help.c:4762 +#: sql_help.c:1754 sql_help.c:4764 sql_help.c:4788 msgid "where transaction_mode is one of:" msgstr "де режим_транзакції один з:" -#: sql_help.c:1751 sql_help.c:4581 sql_help.c:4590 sql_help.c:4594 -#: sql_help.c:4598 sql_help.c:4601 sql_help.c:4838 sql_help.c:4847 -#: sql_help.c:4851 sql_help.c:4855 sql_help.c:4858 sql_help.c:5084 -#: sql_help.c:5093 sql_help.c:5097 sql_help.c:5101 sql_help.c:5104 +#: sql_help.c:1763 sql_help.c:4606 sql_help.c:4615 sql_help.c:4619 +#: sql_help.c:4623 sql_help.c:4626 sql_help.c:4864 sql_help.c:4873 +#: sql_help.c:4877 sql_help.c:4881 sql_help.c:4884 sql_help.c:5109 +#: sql_help.c:5118 sql_help.c:5122 sql_help.c:5126 sql_help.c:5129 msgid "argument" msgstr "аргумент" -#: sql_help.c:1851 +#: sql_help.c:1859 msgid "relation_name" msgstr "назва_відношення" -#: sql_help.c:1856 sql_help.c:3904 sql_help.c:4356 +#: sql_help.c:1864 sql_help.c:3918 sql_help.c:4381 msgid "domain_name" msgstr "назва_домену" -#: sql_help.c:1878 +#: sql_help.c:1886 msgid "policy_name" msgstr "назва_політики" -#: sql_help.c:1891 +#: sql_help.c:1899 msgid "rule_name" msgstr "назва_правила" -#: sql_help.c:1910 sql_help.c:4495 +#: sql_help.c:1918 sql_help.c:4520 msgid "string_literal" msgstr "рядковий_літерал" -#: sql_help.c:1935 sql_help.c:4159 sql_help.c:4409 +#: sql_help.c:1943 sql_help.c:4184 sql_help.c:4434 msgid "transaction_id" msgstr "ідентифікатор_транзакції" -#: sql_help.c:1967 sql_help.c:1974 sql_help.c:4026 +#: sql_help.c:1977 sql_help.c:1984 sql_help.c:4040 msgid "filename" msgstr "ім'я файлу" -#: sql_help.c:1968 sql_help.c:1975 sql_help.c:2694 sql_help.c:2695 -#: sql_help.c:2696 +#: sql_help.c:1978 sql_help.c:1985 sql_help.c:2704 sql_help.c:2705 +#: sql_help.c:2706 msgid "command" msgstr "команда" -#: sql_help.c:1970 sql_help.c:2693 sql_help.c:3123 sql_help.c:3304 -#: sql_help.c:4010 sql_help.c:4087 sql_help.c:4090 sql_help.c:4564 -#: sql_help.c:4566 sql_help.c:4667 sql_help.c:4669 sql_help.c:4821 -#: sql_help.c:4823 sql_help.c:4939 sql_help.c:5067 sql_help.c:5069 +#: sql_help.c:1980 sql_help.c:2703 sql_help.c:3136 sql_help.c:3317 +#: sql_help.c:4024 sql_help.c:4107 sql_help.c:4110 sql_help.c:4113 +#: sql_help.c:4589 sql_help.c:4591 sql_help.c:4693 sql_help.c:4695 +#: sql_help.c:4847 sql_help.c:4849 sql_help.c:4966 sql_help.c:5092 +#: sql_help.c:5094 msgid "condition" msgstr "умова" -#: sql_help.c:1973 sql_help.c:2510 sql_help.c:3006 sql_help.c:3270 -#: sql_help.c:3288 sql_help.c:3991 +#: sql_help.c:1983 sql_help.c:2524 sql_help.c:3019 sql_help.c:3283 +#: sql_help.c:3301 sql_help.c:4005 msgid "query" msgstr "запит" -#: sql_help.c:1978 +#: sql_help.c:1988 msgid "format_name" msgstr "назва_формату" -#: sql_help.c:1980 +#: sql_help.c:1990 msgid "delimiter_character" msgstr "символ_роздільник" -#: sql_help.c:1981 +#: sql_help.c:1991 msgid "null_string" msgstr "представлення_NULL" -#: sql_help.c:1982 +#: sql_help.c:1992 msgid "default_string" msgstr "рядок_за_замовчуванням" -#: sql_help.c:1984 +#: sql_help.c:1994 msgid "quote_character" msgstr "символ_лапок" -#: sql_help.c:1985 +#: sql_help.c:1995 msgid "escape_character" msgstr "символ_екранування" -#: sql_help.c:1989 +#: sql_help.c:1999 +msgid "error_action" +msgstr "error_action" + +#: sql_help.c:2000 msgid "encoding_name" msgstr "ім'я_кодування" -#: sql_help.c:2000 +#: sql_help.c:2001 +msgid "verbosity" +msgstr "детальність" + +#: sql_help.c:2012 msgid "access_method_type" msgstr "тип_метода_доступа" -#: sql_help.c:2071 sql_help.c:2090 sql_help.c:2093 +#: sql_help.c:2083 sql_help.c:2102 sql_help.c:2105 msgid "arg_data_type" msgstr "тип_даних_аргумента" -#: sql_help.c:2072 sql_help.c:2094 sql_help.c:2102 +#: sql_help.c:2084 sql_help.c:2106 sql_help.c:2114 msgid "sfunc" msgstr "функція_стану" -#: sql_help.c:2073 sql_help.c:2095 sql_help.c:2103 +#: sql_help.c:2085 sql_help.c:2107 sql_help.c:2115 msgid "state_data_type" msgstr "тип_даних_стану" -#: sql_help.c:2074 sql_help.c:2096 sql_help.c:2104 +#: sql_help.c:2086 sql_help.c:2108 sql_help.c:2116 msgid "state_data_size" msgstr "розмір_даних_стану" -#: sql_help.c:2075 sql_help.c:2097 sql_help.c:2105 +#: sql_help.c:2087 sql_help.c:2109 sql_help.c:2117 msgid "ffunc" msgstr "функція_завершення" -#: sql_help.c:2076 sql_help.c:2106 +#: sql_help.c:2088 sql_help.c:2118 msgid "combinefunc" msgstr "комбінуюча_функція" -#: sql_help.c:2077 sql_help.c:2107 +#: sql_help.c:2089 sql_help.c:2119 msgid "serialfunc" msgstr "функція_серіалізації" -#: sql_help.c:2078 sql_help.c:2108 +#: sql_help.c:2090 sql_help.c:2120 msgid "deserialfunc" msgstr "функція_десеріалізації" -#: sql_help.c:2079 sql_help.c:2098 sql_help.c:2109 +#: sql_help.c:2091 sql_help.c:2110 sql_help.c:2121 msgid "initial_condition" msgstr "початкова_умова" -#: sql_help.c:2080 sql_help.c:2110 +#: sql_help.c:2092 sql_help.c:2122 msgid "msfunc" msgstr "функція_стану_рух" -#: sql_help.c:2081 sql_help.c:2111 +#: sql_help.c:2093 sql_help.c:2123 msgid "minvfunc" msgstr "зворотна_функція_рух" -#: sql_help.c:2082 sql_help.c:2112 +#: sql_help.c:2094 sql_help.c:2124 msgid "mstate_data_type" msgstr "тип_даних_стану_рух" -#: sql_help.c:2083 sql_help.c:2113 +#: sql_help.c:2095 sql_help.c:2125 msgid "mstate_data_size" msgstr "розмір_даних_стану_рух" -#: sql_help.c:2084 sql_help.c:2114 +#: sql_help.c:2096 sql_help.c:2126 msgid "mffunc" msgstr "функція_завершення_рух" -#: sql_help.c:2085 sql_help.c:2115 +#: sql_help.c:2097 sql_help.c:2127 msgid "minitial_condition" msgstr "початкова_умова_рух" -#: sql_help.c:2086 sql_help.c:2116 +#: sql_help.c:2098 sql_help.c:2128 msgid "sort_operator" msgstr "оператор_сортування" -#: sql_help.c:2099 +#: sql_help.c:2111 msgid "or the old syntax" msgstr "або старий синтаксис" -#: sql_help.c:2101 +#: sql_help.c:2113 msgid "base_type" msgstr "базовий_тип" -#: sql_help.c:2159 sql_help.c:2208 +#: sql_help.c:2171 sql_help.c:2221 msgid "locale" msgstr "локаль" -#: sql_help.c:2160 sql_help.c:2209 +#: sql_help.c:2172 sql_help.c:2222 msgid "lc_collate" msgstr "код_правила_сортування" -#: sql_help.c:2161 sql_help.c:2210 +#: sql_help.c:2173 sql_help.c:2223 msgid "lc_ctype" msgstr "код_класифікації_символів" -#: sql_help.c:2162 sql_help.c:4462 +#: sql_help.c:2174 sql_help.c:4487 msgid "provider" msgstr "постачальник" -#: sql_help.c:2164 +#: sql_help.c:2176 msgid "rules" msgstr "правила" -#: sql_help.c:2165 sql_help.c:2270 +#: sql_help.c:2177 sql_help.c:2284 msgid "version" msgstr "версія" -#: sql_help.c:2167 +#: sql_help.c:2179 msgid "existing_collation" msgstr "існуюче_правило_сортування" -#: sql_help.c:2177 +#: sql_help.c:2189 msgid "source_encoding" msgstr "початкове_кодування" -#: sql_help.c:2178 +#: sql_help.c:2190 msgid "dest_encoding" msgstr "цільве_кодування" -#: sql_help.c:2205 sql_help.c:3046 +#: sql_help.c:2218 sql_help.c:3059 msgid "template" msgstr "шаблон" -#: sql_help.c:2206 +#: sql_help.c:2219 msgid "encoding" msgstr "кодування" -#: sql_help.c:2207 +#: sql_help.c:2220 msgid "strategy" msgstr "стратегія" -#: sql_help.c:2211 +#: sql_help.c:2224 +msgid "builtin_locale" +msgstr "вбудована_локаль" + +#: sql_help.c:2225 msgid "icu_locale" msgstr "icu_locale" -#: sql_help.c:2212 +#: sql_help.c:2226 msgid "icu_rules" msgstr "правила_icu" -#: sql_help.c:2213 +#: sql_help.c:2227 msgid "locale_provider" msgstr "локаль_провайдер" -#: sql_help.c:2214 +#: sql_help.c:2228 msgid "collation_version" msgstr "версія_сортування" -#: sql_help.c:2219 +#: sql_help.c:2233 msgid "oid" msgstr "oid" -#: sql_help.c:2239 -msgid "constraint" -msgstr "обмеження" - -#: sql_help.c:2240 -msgid "where constraint is:" -msgstr "де обмеження:" +#: sql_help.c:2254 +msgid "where domain_constraint is:" +msgstr "де обмеження_домену:" -#: sql_help.c:2254 sql_help.c:2691 sql_help.c:3119 +#: sql_help.c:2268 sql_help.c:2701 sql_help.c:3132 msgid "event" msgstr "подія" -#: sql_help.c:2255 +#: sql_help.c:2269 msgid "filter_variable" msgstr "змінна_фільтру" -#: sql_help.c:2256 +#: sql_help.c:2270 msgid "filter_value" msgstr "значення_фільтру" -#: sql_help.c:2352 sql_help.c:2938 +#: sql_help.c:2366 sql_help.c:2948 msgid "where column_constraint is:" msgstr "де обмеження_стовпців:" -#: sql_help.c:2397 +#: sql_help.c:2411 msgid "rettype" msgstr "тип_результату" -#: sql_help.c:2399 +#: sql_help.c:2413 msgid "column_type" msgstr "тип_стовпця" -#: sql_help.c:2408 sql_help.c:2611 +#: sql_help.c:2422 sql_help.c:2625 msgid "definition" msgstr "визначення" -#: sql_help.c:2409 sql_help.c:2612 +#: sql_help.c:2423 sql_help.c:2626 msgid "obj_file" msgstr "об'єктний_файл" -#: sql_help.c:2410 sql_help.c:2613 +#: sql_help.c:2424 sql_help.c:2627 msgid "link_symbol" msgstr "символ_експорту" -#: sql_help.c:2411 sql_help.c:2614 +#: sql_help.c:2425 sql_help.c:2628 msgid "sql_body" msgstr "sql_body" -#: sql_help.c:2449 sql_help.c:2676 sql_help.c:3242 +#: sql_help.c:2463 sql_help.c:2686 sql_help.c:3255 msgid "uid" msgstr "uid" -#: sql_help.c:2465 sql_help.c:2506 sql_help.c:2907 sql_help.c:2920 -#: sql_help.c:2934 sql_help.c:3002 +#: sql_help.c:2479 sql_help.c:2520 sql_help.c:2917 sql_help.c:2930 +#: sql_help.c:2944 sql_help.c:3015 msgid "method" msgstr "метод" -#: sql_help.c:2470 -msgid "opclass_parameter" -msgstr "opclass_parameter" - -#: sql_help.c:2487 +#: sql_help.c:2501 msgid "call_handler" msgstr "обробник_виклику" -#: sql_help.c:2488 +#: sql_help.c:2502 msgid "inline_handler" msgstr "обробник_впровадженого_коду" -#: sql_help.c:2489 +#: sql_help.c:2503 msgid "valfunction" msgstr "функція_перевірки" -#: sql_help.c:2528 -msgid "com_op" -msgstr "комут_оператор" - -#: sql_help.c:2529 -msgid "neg_op" -msgstr "зворотній_оператор" - -#: sql_help.c:2547 +#: sql_help.c:2561 msgid "family_name" msgstr "назва_сімейства" -#: sql_help.c:2558 +#: sql_help.c:2572 msgid "storage_type" msgstr "тип_зберігання" -#: sql_help.c:2697 sql_help.c:3126 +#: sql_help.c:2707 sql_help.c:3139 msgid "where event can be one of:" msgstr "де подія може бути однією з:" -#: sql_help.c:2717 sql_help.c:2719 +#: sql_help.c:2727 sql_help.c:2729 msgid "schema_element" msgstr "елемент_схеми" -#: sql_help.c:2756 +#: sql_help.c:2766 msgid "server_type" msgstr "тип_серверу" -#: sql_help.c:2757 +#: sql_help.c:2767 msgid "server_version" msgstr "версія_серверу" -#: sql_help.c:2758 sql_help.c:3907 sql_help.c:4359 +#: sql_help.c:2768 sql_help.c:3921 sql_help.c:4384 msgid "fdw_name" msgstr "назва_fdw" -#: sql_help.c:2775 sql_help.c:2778 +#: sql_help.c:2785 sql_help.c:2788 msgid "statistics_name" msgstr "назва_статистики" -#: sql_help.c:2779 +#: sql_help.c:2789 msgid "statistics_kind" msgstr "вид_статистики" -#: sql_help.c:2795 +#: sql_help.c:2805 msgid "subscription_name" msgstr "назва_підписки" -#: sql_help.c:2900 +#: sql_help.c:2910 msgid "source_table" msgstr "вихідна_таблиця" -#: sql_help.c:2901 +#: sql_help.c:2911 msgid "like_option" msgstr "параметр_породження" -#: sql_help.c:2967 +#: sql_help.c:2977 msgid "and like_option is:" msgstr "і параметр_породження:" -#: sql_help.c:3019 +#: sql_help.c:3032 msgid "directory" msgstr "каталог" -#: sql_help.c:3033 +#: sql_help.c:3046 msgid "parser_name" msgstr "назва_парсера" -#: sql_help.c:3034 +#: sql_help.c:3047 msgid "source_config" msgstr "початкова_конфігурація" -#: sql_help.c:3063 +#: sql_help.c:3076 msgid "start_function" msgstr "функція_початку" -#: sql_help.c:3064 +#: sql_help.c:3077 msgid "gettoken_function" msgstr "функція_видачі_токену" -#: sql_help.c:3065 +#: sql_help.c:3078 msgid "end_function" msgstr "функція_завершення" -#: sql_help.c:3066 +#: sql_help.c:3079 msgid "lextypes_function" msgstr "функція_лекс_типів" -#: sql_help.c:3067 +#: sql_help.c:3080 msgid "headline_function" msgstr "функція_створення_заголовків" -#: sql_help.c:3079 +#: sql_help.c:3092 msgid "init_function" msgstr "функція_ініціалізації" -#: sql_help.c:3080 +#: sql_help.c:3093 msgid "lexize_function" msgstr "функція_виділення_лексем" -#: sql_help.c:3093 +#: sql_help.c:3106 msgid "from_sql_function_name" msgstr "ім'я_функції_з_sql" -#: sql_help.c:3095 +#: sql_help.c:3108 msgid "to_sql_function_name" msgstr "ім'я_функції_в_sql" -#: sql_help.c:3121 +#: sql_help.c:3134 msgid "referenced_table_name" msgstr "ім'я_залежної_таблиці" -#: sql_help.c:3122 +#: sql_help.c:3135 msgid "transition_relation_name" msgstr "ім'я_перехідного_відношення" -#: sql_help.c:3125 +#: sql_help.c:3138 msgid "arguments" msgstr "аргументи" -#: sql_help.c:3177 +#: sql_help.c:3190 msgid "label" msgstr "мітка" -#: sql_help.c:3179 +#: sql_help.c:3192 msgid "subtype" msgstr "підтип" -#: sql_help.c:3180 +#: sql_help.c:3193 msgid "subtype_operator_class" msgstr "клас_оператора_підтипу" -#: sql_help.c:3182 +#: sql_help.c:3195 msgid "canonical_function" msgstr "канонічна_функція" -#: sql_help.c:3183 +#: sql_help.c:3196 msgid "subtype_diff_function" msgstr "функція_розбіжностей_підтипу" -#: sql_help.c:3184 +#: sql_help.c:3197 msgid "multirange_type_name" msgstr "multirange_type_name" -#: sql_help.c:3186 +#: sql_help.c:3199 msgid "input_function" msgstr "функція_вводу" -#: sql_help.c:3187 +#: sql_help.c:3200 msgid "output_function" msgstr "функція_виводу" -#: sql_help.c:3188 +#: sql_help.c:3201 msgid "receive_function" msgstr "функція_отримання" -#: sql_help.c:3189 +#: sql_help.c:3202 msgid "send_function" msgstr "функція_відправки" -#: sql_help.c:3190 +#: sql_help.c:3203 msgid "type_modifier_input_function" msgstr "функція_введення_модифікатора_типу" -#: sql_help.c:3191 +#: sql_help.c:3204 msgid "type_modifier_output_function" msgstr "функція_виводу_модифікатора_типу" -#: sql_help.c:3192 +#: sql_help.c:3205 msgid "analyze_function" msgstr "функція_аналізу" -#: sql_help.c:3193 +#: sql_help.c:3206 msgid "subscript_function" msgstr "subscript_function" -#: sql_help.c:3194 +#: sql_help.c:3207 msgid "internallength" msgstr "внутр_довжина" -#: sql_help.c:3195 +#: sql_help.c:3208 msgid "alignment" msgstr "вирівнювання" -#: sql_help.c:3196 +#: sql_help.c:3209 msgid "storage" msgstr "зберігання" -#: sql_help.c:3197 +#: sql_help.c:3210 msgid "like_type" msgstr "тип_зразок" -#: sql_help.c:3198 +#: sql_help.c:3211 msgid "category" msgstr "категорія" -#: sql_help.c:3199 +#: sql_help.c:3212 msgid "preferred" msgstr "привілейований" -#: sql_help.c:3200 +#: sql_help.c:3213 msgid "default" msgstr "за_замовчуванням" -#: sql_help.c:3201 +#: sql_help.c:3214 msgid "element" msgstr "елемент" -#: sql_help.c:3202 +#: sql_help.c:3215 msgid "delimiter" msgstr "роздільник" -#: sql_help.c:3203 +#: sql_help.c:3216 msgid "collatable" msgstr "сортувальний" -#: sql_help.c:3300 sql_help.c:3986 sql_help.c:4076 sql_help.c:4559 -#: sql_help.c:4661 sql_help.c:4816 sql_help.c:4929 sql_help.c:5062 +#: sql_help.c:3313 sql_help.c:4000 sql_help.c:4094 sql_help.c:4584 +#: sql_help.c:4687 sql_help.c:4842 sql_help.c:4956 sql_help.c:5087 msgid "with_query" msgstr "with_запит" -#: sql_help.c:3302 sql_help.c:3988 sql_help.c:4578 sql_help.c:4584 -#: sql_help.c:4587 sql_help.c:4591 sql_help.c:4595 sql_help.c:4603 -#: sql_help.c:4835 sql_help.c:4841 sql_help.c:4844 sql_help.c:4848 -#: sql_help.c:4852 sql_help.c:4860 sql_help.c:4931 sql_help.c:5081 -#: sql_help.c:5087 sql_help.c:5090 sql_help.c:5094 sql_help.c:5098 -#: sql_help.c:5106 +#: sql_help.c:3315 sql_help.c:4002 sql_help.c:4603 sql_help.c:4609 +#: sql_help.c:4612 sql_help.c:4616 sql_help.c:4620 sql_help.c:4628 +#: sql_help.c:4861 sql_help.c:4867 sql_help.c:4870 sql_help.c:4874 +#: sql_help.c:4878 sql_help.c:4886 sql_help.c:4958 sql_help.c:5106 +#: sql_help.c:5112 sql_help.c:5115 sql_help.c:5119 sql_help.c:5123 +#: sql_help.c:5131 msgid "alias" msgstr "псевдонім" -#: sql_help.c:3303 sql_help.c:4563 sql_help.c:4605 sql_help.c:4607 -#: sql_help.c:4611 sql_help.c:4613 sql_help.c:4614 sql_help.c:4615 -#: sql_help.c:4666 sql_help.c:4820 sql_help.c:4862 sql_help.c:4864 -#: sql_help.c:4868 sql_help.c:4870 sql_help.c:4871 sql_help.c:4872 -#: sql_help.c:4938 sql_help.c:5066 sql_help.c:5108 sql_help.c:5110 -#: sql_help.c:5114 sql_help.c:5116 sql_help.c:5117 sql_help.c:5118 +#: sql_help.c:3316 sql_help.c:4588 sql_help.c:4630 sql_help.c:4632 +#: sql_help.c:4636 sql_help.c:4638 sql_help.c:4639 sql_help.c:4640 +#: sql_help.c:4692 sql_help.c:4846 sql_help.c:4888 sql_help.c:4890 +#: sql_help.c:4894 sql_help.c:4896 sql_help.c:4897 sql_help.c:4898 +#: sql_help.c:4965 sql_help.c:5091 sql_help.c:5133 sql_help.c:5135 +#: sql_help.c:5139 sql_help.c:5141 sql_help.c:5142 sql_help.c:5143 msgid "from_item" msgstr "джерело_даних" -#: sql_help.c:3305 sql_help.c:3788 sql_help.c:4126 sql_help.c:4940 +#: sql_help.c:3318 sql_help.c:3802 sql_help.c:4151 sql_help.c:4967 msgid "cursor_name" msgstr "ім'я_курсору" -#: sql_help.c:3306 sql_help.c:3994 sql_help.c:4941 +#: sql_help.c:3319 sql_help.c:4008 sql_help.c:4100 sql_help.c:4968 msgid "output_expression" msgstr "вираз_результату" -#: sql_help.c:3307 sql_help.c:3995 sql_help.c:4562 sql_help.c:4664 -#: sql_help.c:4819 sql_help.c:4942 sql_help.c:5065 +#: sql_help.c:3320 sql_help.c:4009 sql_help.c:4101 sql_help.c:4587 +#: sql_help.c:4690 sql_help.c:4845 sql_help.c:4969 sql_help.c:5090 msgid "output_name" msgstr "ім'я_результату" -#: sql_help.c:3323 +#: sql_help.c:3336 msgid "code" msgstr "код" -#: sql_help.c:3728 +#: sql_help.c:3741 msgid "parameter" msgstr "параметр" -#: sql_help.c:3751 sql_help.c:3752 sql_help.c:4151 +#: sql_help.c:3765 sql_help.c:4176 msgid "statement" msgstr "оператор" -#: sql_help.c:3787 sql_help.c:4125 +#: sql_help.c:3801 sql_help.c:4150 msgid "direction" msgstr "напрямок" -#: sql_help.c:3789 sql_help.c:4127 +#: sql_help.c:3803 sql_help.c:4152 msgid "where direction can be one of:" msgstr "де напрямок може бути одним із:" -#: sql_help.c:3790 sql_help.c:3791 sql_help.c:3792 sql_help.c:3793 -#: sql_help.c:3794 sql_help.c:4128 sql_help.c:4129 sql_help.c:4130 -#: sql_help.c:4131 sql_help.c:4132 sql_help.c:4572 sql_help.c:4574 -#: sql_help.c:4675 sql_help.c:4677 sql_help.c:4829 sql_help.c:4831 -#: sql_help.c:5006 sql_help.c:5008 sql_help.c:5075 sql_help.c:5077 +#: sql_help.c:3804 sql_help.c:3805 sql_help.c:3806 sql_help.c:3807 +#: sql_help.c:3808 sql_help.c:4153 sql_help.c:4154 sql_help.c:4155 +#: sql_help.c:4156 sql_help.c:4157 sql_help.c:4597 sql_help.c:4599 +#: sql_help.c:4701 sql_help.c:4703 sql_help.c:4855 sql_help.c:4857 +#: sql_help.c:5031 sql_help.c:5033 sql_help.c:5100 sql_help.c:5102 msgid "count" msgstr "кількість" -#: sql_help.c:3897 sql_help.c:4349 +#: sql_help.c:3911 sql_help.c:4374 msgid "sequence_name" msgstr "ім'я_послідовності" -#: sql_help.c:3915 sql_help.c:4367 +#: sql_help.c:3929 sql_help.c:4392 msgid "arg_name" msgstr "ім'я_аргументу" -#: sql_help.c:3916 sql_help.c:4368 +#: sql_help.c:3930 sql_help.c:4393 msgid "arg_type" msgstr "тип_аргументу" -#: sql_help.c:3923 sql_help.c:4375 +#: sql_help.c:3937 sql_help.c:4400 msgid "loid" msgstr "код_вел_об'єкту" -#: sql_help.c:3954 +#: sql_help.c:3968 msgid "remote_schema" msgstr "віддалена_схема" -#: sql_help.c:3957 +#: sql_help.c:3971 msgid "local_schema" msgstr "локальна_схема" -#: sql_help.c:3992 +#: sql_help.c:4006 msgid "conflict_target" msgstr "ціль_конфлікту" -#: sql_help.c:3993 +#: sql_help.c:4007 msgid "conflict_action" msgstr "дія_при_конфлікті" -#: sql_help.c:3996 +#: sql_help.c:4010 msgid "where conflict_target can be one of:" msgstr "де ціль_конфлікту може бути одним з:" -#: sql_help.c:3997 +#: sql_help.c:4011 msgid "index_column_name" msgstr "ім'я_стовпця_індексу" -#: sql_help.c:3998 +#: sql_help.c:4012 msgid "index_expression" msgstr "вираз_індексу" -#: sql_help.c:4001 +#: sql_help.c:4015 msgid "index_predicate" msgstr "предикат_індексу" -#: sql_help.c:4003 +#: sql_help.c:4017 msgid "and conflict_action is one of:" msgstr "і дія_при_конфлікті одна з:" -#: sql_help.c:4009 sql_help.c:4937 +#: sql_help.c:4023 sql_help.c:4124 sql_help.c:4964 msgid "sub-SELECT" msgstr "вкладений-SELECT" -#: sql_help.c:4018 sql_help.c:4140 sql_help.c:4913 +#: sql_help.c:4032 sql_help.c:4165 sql_help.c:4940 msgid "channel" msgstr "канал" -#: sql_help.c:4040 +#: sql_help.c:4054 msgid "lockmode" msgstr "режим_блокування" -#: sql_help.c:4041 +#: sql_help.c:4055 msgid "where lockmode is one of:" msgstr "де режим_блокування один з:" -#: sql_help.c:4077 +#: sql_help.c:4095 msgid "target_table_name" msgstr "ім'я_цілі_таблиці" -#: sql_help.c:4078 +#: sql_help.c:4096 msgid "target_alias" msgstr "псевдонім_цілі" -#: sql_help.c:4079 +#: sql_help.c:4097 msgid "data_source" msgstr "джерело_даних" -#: sql_help.c:4080 sql_help.c:4608 sql_help.c:4865 sql_help.c:5111 +#: sql_help.c:4098 sql_help.c:4633 sql_help.c:4891 sql_help.c:5136 msgid "join_condition" msgstr "умова_поєднання" -#: sql_help.c:4081 +#: sql_help.c:4099 msgid "when_clause" msgstr "when_твердження" -#: sql_help.c:4082 +#: sql_help.c:4102 msgid "where data_source is:" msgstr "де джерело_даних:" -#: sql_help.c:4083 +#: sql_help.c:4103 msgid "source_table_name" msgstr "ім'я_початкова_таблиці" -#: sql_help.c:4084 +#: sql_help.c:4104 msgid "source_query" msgstr "джерело_запит" -#: sql_help.c:4085 +#: sql_help.c:4105 msgid "source_alias" msgstr "джерело_псевдоніма" -#: sql_help.c:4086 +#: sql_help.c:4106 msgid "and when_clause is:" msgstr "і when_clause:" -#: sql_help.c:4088 +#: sql_help.c:4108 sql_help.c:4111 msgid "merge_update" msgstr "merge_update" -#: sql_help.c:4089 +#: sql_help.c:4109 sql_help.c:4112 msgid "merge_delete" msgstr "merge_delete" -#: sql_help.c:4091 +#: sql_help.c:4114 msgid "merge_insert" msgstr "merge_insert" -#: sql_help.c:4092 +#: sql_help.c:4115 msgid "and merge_insert is:" msgstr "і merge_insert:" -#: sql_help.c:4095 +#: sql_help.c:4118 msgid "and merge_update is:" msgstr "і merge_update:" -#: sql_help.c:4100 +#: sql_help.c:4125 msgid "and merge_delete is:" msgstr "і merge_delete:" -#: sql_help.c:4141 +#: sql_help.c:4166 msgid "payload" msgstr "зміст" -#: sql_help.c:4168 +#: sql_help.c:4193 msgid "old_role" msgstr "стара_роль" -#: sql_help.c:4169 +#: sql_help.c:4194 msgid "new_role" msgstr "нова_роль" -#: sql_help.c:4208 sql_help.c:4417 sql_help.c:4425 +#: sql_help.c:4233 sql_help.c:4442 sql_help.c:4450 msgid "savepoint_name" msgstr "ім'я_точки_збереження" -#: sql_help.c:4565 sql_help.c:4623 sql_help.c:4822 sql_help.c:4880 -#: sql_help.c:5068 sql_help.c:5126 +#: sql_help.c:4590 sql_help.c:4648 sql_help.c:4848 sql_help.c:4906 +#: sql_help.c:5093 sql_help.c:5151 msgid "grouping_element" msgstr "елемент_групування" -#: sql_help.c:4567 sql_help.c:4670 sql_help.c:4824 sql_help.c:5070 +#: sql_help.c:4592 sql_help.c:4696 sql_help.c:4850 sql_help.c:5095 msgid "window_name" msgstr "назва_вікна" -#: sql_help.c:4568 sql_help.c:4671 sql_help.c:4825 sql_help.c:5071 +#: sql_help.c:4593 sql_help.c:4697 sql_help.c:4851 sql_help.c:5096 msgid "window_definition" msgstr "визначення_вікна" -#: sql_help.c:4569 sql_help.c:4583 sql_help.c:4627 sql_help.c:4672 -#: sql_help.c:4826 sql_help.c:4840 sql_help.c:4884 sql_help.c:5072 -#: sql_help.c:5086 sql_help.c:5130 +#: sql_help.c:4594 sql_help.c:4608 sql_help.c:4652 sql_help.c:4698 +#: sql_help.c:4852 sql_help.c:4866 sql_help.c:4910 sql_help.c:5097 +#: sql_help.c:5111 sql_help.c:5155 msgid "select" msgstr "виберіть" -#: sql_help.c:4576 sql_help.c:4833 sql_help.c:5079 +#: sql_help.c:4600 sql_help.c:4858 sql_help.c:5103 +msgid "from_reference" +msgstr "from_reference" + +#: sql_help.c:4601 sql_help.c:4859 sql_help.c:5104 msgid "where from_item can be one of:" msgstr "де джерело_даних може бути одним з:" -#: sql_help.c:4579 sql_help.c:4585 sql_help.c:4588 sql_help.c:4592 -#: sql_help.c:4604 sql_help.c:4836 sql_help.c:4842 sql_help.c:4845 -#: sql_help.c:4849 sql_help.c:4861 sql_help.c:5082 sql_help.c:5088 -#: sql_help.c:5091 sql_help.c:5095 sql_help.c:5107 +#: sql_help.c:4604 sql_help.c:4610 sql_help.c:4613 sql_help.c:4617 +#: sql_help.c:4629 sql_help.c:4862 sql_help.c:4868 sql_help.c:4871 +#: sql_help.c:4875 sql_help.c:4887 sql_help.c:5107 sql_help.c:5113 +#: sql_help.c:5116 sql_help.c:5120 sql_help.c:5132 msgid "column_alias" msgstr "псевдонім_стовпця" -#: sql_help.c:4580 sql_help.c:4837 sql_help.c:5083 +#: sql_help.c:4605 sql_help.c:4863 sql_help.c:5108 msgid "sampling_method" msgstr "метод_вибірки" -#: sql_help.c:4582 sql_help.c:4839 sql_help.c:5085 +#: sql_help.c:4607 sql_help.c:4865 sql_help.c:5110 msgid "seed" msgstr "початкове_число" -#: sql_help.c:4586 sql_help.c:4625 sql_help.c:4843 sql_help.c:4882 -#: sql_help.c:5089 sql_help.c:5128 +#: sql_help.c:4611 sql_help.c:4650 sql_help.c:4869 sql_help.c:4908 +#: sql_help.c:5114 sql_help.c:5153 msgid "with_query_name" msgstr "ім'я_запиту_WITH" -#: sql_help.c:4596 sql_help.c:4599 sql_help.c:4602 sql_help.c:4853 -#: sql_help.c:4856 sql_help.c:4859 sql_help.c:5099 sql_help.c:5102 -#: sql_help.c:5105 +#: sql_help.c:4621 sql_help.c:4624 sql_help.c:4627 sql_help.c:4879 +#: sql_help.c:4882 sql_help.c:4885 sql_help.c:5124 sql_help.c:5127 +#: sql_help.c:5130 msgid "column_definition" msgstr "визначення_стовпця" -#: sql_help.c:4606 sql_help.c:4612 sql_help.c:4863 sql_help.c:4869 -#: sql_help.c:5109 sql_help.c:5115 +#: sql_help.c:4631 sql_help.c:4637 sql_help.c:4889 sql_help.c:4895 +#: sql_help.c:5134 sql_help.c:5140 msgid "join_type" msgstr "тип_поєднання" -#: sql_help.c:4609 sql_help.c:4866 sql_help.c:5112 +#: sql_help.c:4634 sql_help.c:4892 sql_help.c:5137 msgid "join_column" msgstr "стовпець_поєднання" -#: sql_help.c:4610 sql_help.c:4867 sql_help.c:5113 +#: sql_help.c:4635 sql_help.c:4893 sql_help.c:5138 msgid "join_using_alias" msgstr "join_using_alias" -#: sql_help.c:4616 sql_help.c:4873 sql_help.c:5119 +#: sql_help.c:4641 sql_help.c:4899 sql_help.c:5144 msgid "and grouping_element can be one of:" msgstr "і елемент_групування може бути одним з:" -#: sql_help.c:4624 sql_help.c:4881 sql_help.c:5127 +#: sql_help.c:4649 sql_help.c:4907 sql_help.c:5152 msgid "and with_query is:" msgstr "і запит_WITH:" -#: sql_help.c:4628 sql_help.c:4885 sql_help.c:5131 +#: sql_help.c:4653 sql_help.c:4911 sql_help.c:5156 msgid "values" msgstr "значення" -#: sql_help.c:4629 sql_help.c:4886 sql_help.c:5132 +#: sql_help.c:4654 sql_help.c:4912 sql_help.c:5157 msgid "insert" msgstr "вставка" -#: sql_help.c:4630 sql_help.c:4887 sql_help.c:5133 +#: sql_help.c:4655 sql_help.c:4913 sql_help.c:5158 msgid "update" msgstr "оновлення" -#: sql_help.c:4631 sql_help.c:4888 sql_help.c:5134 +#: sql_help.c:4656 sql_help.c:4914 sql_help.c:5159 msgid "delete" msgstr "видалення" -#: sql_help.c:4633 sql_help.c:4890 sql_help.c:5136 +#: sql_help.c:4657 sql_help.c:4915 sql_help.c:5160 +msgid "merge" +msgstr "об’єднати" + +#: sql_help.c:4659 sql_help.c:4917 sql_help.c:5162 msgid "search_seq_col_name" msgstr "search_seq_col_name" -#: sql_help.c:4635 sql_help.c:4892 sql_help.c:5138 +#: sql_help.c:4661 sql_help.c:4919 sql_help.c:5164 msgid "cycle_mark_col_name" msgstr "cycle_mark_col_name" -#: sql_help.c:4636 sql_help.c:4893 sql_help.c:5139 +#: sql_help.c:4662 sql_help.c:4920 sql_help.c:5165 msgid "cycle_mark_value" msgstr "cycle_mark_value" -#: sql_help.c:4637 sql_help.c:4894 sql_help.c:5140 +#: sql_help.c:4663 sql_help.c:4921 sql_help.c:5166 msgid "cycle_mark_default" msgstr "cycle_mark_default" -#: sql_help.c:4638 sql_help.c:4895 sql_help.c:5141 +#: sql_help.c:4664 sql_help.c:4922 sql_help.c:5167 msgid "cycle_path_col_name" msgstr "cycle_path_col_name" -#: sql_help.c:4665 +#: sql_help.c:4691 msgid "new_table" msgstr "нова_таблиця" -#: sql_help.c:4736 +#: sql_help.c:4762 msgid "snapshot_id" msgstr "код_знімку" -#: sql_help.c:5004 +#: sql_help.c:5029 msgid "sort_expression" msgstr "вираз_сортування" -#: sql_help.c:5148 sql_help.c:6132 +#: sql_help.c:5174 sql_help.c:6158 msgid "abort the current transaction" msgstr "перервати поточну транзакцію" -#: sql_help.c:5154 +#: sql_help.c:5180 msgid "change the definition of an aggregate function" msgstr "змінити визначення агрегатної функції" -#: sql_help.c:5160 +#: sql_help.c:5186 msgid "change the definition of a collation" msgstr "змінити визначення правила сортування" -#: sql_help.c:5166 +#: sql_help.c:5192 msgid "change the definition of a conversion" msgstr "змінити визначення перетворення" -#: sql_help.c:5172 +#: sql_help.c:5198 msgid "change a database" msgstr "змінити базу даних" -#: sql_help.c:5178 +#: sql_help.c:5204 msgid "define default access privileges" msgstr "визначити права доступу за замовчуванням" -#: sql_help.c:5184 +#: sql_help.c:5210 msgid "change the definition of a domain" msgstr "змінити визначення домену" -#: sql_help.c:5190 +#: sql_help.c:5216 msgid "change the definition of an event trigger" msgstr "змінити визначення тригеру події" -#: sql_help.c:5196 +#: sql_help.c:5222 msgid "change the definition of an extension" msgstr "змінити визначення розширення" -#: sql_help.c:5202 +#: sql_help.c:5228 msgid "change the definition of a foreign-data wrapper" msgstr "змінити визначення джерела сторонніх даних" -#: sql_help.c:5208 +#: sql_help.c:5234 msgid "change the definition of a foreign table" msgstr "змінити визначення сторонньої таблиці" -#: sql_help.c:5214 +#: sql_help.c:5240 msgid "change the definition of a function" msgstr "змінити визначення функції" -#: sql_help.c:5220 +#: sql_help.c:5246 msgid "change role name or membership" msgstr "змінити назву ролі або членства" -#: sql_help.c:5226 +#: sql_help.c:5252 msgid "change the definition of an index" msgstr "змінити визначення індексу" -#: sql_help.c:5232 +#: sql_help.c:5258 msgid "change the definition of a procedural language" msgstr "змінити визначення процедурної мови" -#: sql_help.c:5238 +#: sql_help.c:5264 msgid "change the definition of a large object" msgstr "змінити визначення великого об'єкту" -#: sql_help.c:5244 +#: sql_help.c:5270 msgid "change the definition of a materialized view" msgstr "змінити визначення матеріалізованого подання" -#: sql_help.c:5250 +#: sql_help.c:5276 msgid "change the definition of an operator" msgstr "змінити визначення оператора" -#: sql_help.c:5256 +#: sql_help.c:5282 msgid "change the definition of an operator class" msgstr "змінити визначення класа операторів" -#: sql_help.c:5262 +#: sql_help.c:5288 msgid "change the definition of an operator family" msgstr "змінити визначення сімейства операторів" -#: sql_help.c:5268 +#: sql_help.c:5294 msgid "change the definition of a row-level security policy" msgstr "змінити визначення політики безпеки на рівні рядків" -#: sql_help.c:5274 +#: sql_help.c:5300 msgid "change the definition of a procedure" msgstr "змінити визначення процедури" -#: sql_help.c:5280 +#: sql_help.c:5306 msgid "change the definition of a publication" msgstr "змінити визначення публікації" -#: sql_help.c:5286 sql_help.c:5388 +#: sql_help.c:5312 sql_help.c:5414 msgid "change a database role" msgstr "змінити роль бази даних" -#: sql_help.c:5292 +#: sql_help.c:5318 msgid "change the definition of a routine" msgstr "змінити визначення підпрограми" -#: sql_help.c:5298 +#: sql_help.c:5324 msgid "change the definition of a rule" msgstr "змінити визначення правила" -#: sql_help.c:5304 +#: sql_help.c:5330 msgid "change the definition of a schema" msgstr "змінити визначення схеми" -#: sql_help.c:5310 +#: sql_help.c:5336 msgid "change the definition of a sequence generator" msgstr "змінити визначення генератору послідовності" -#: sql_help.c:5316 +#: sql_help.c:5342 msgid "change the definition of a foreign server" msgstr "змінити визначення стороннього серверу" -#: sql_help.c:5322 +#: sql_help.c:5348 msgid "change the definition of an extended statistics object" msgstr "змінити визначення об'єкту розширеної статистики" -#: sql_help.c:5328 +#: sql_help.c:5354 msgid "change the definition of a subscription" msgstr "змінити визначення підписки" -#: sql_help.c:5334 +#: sql_help.c:5360 msgid "change a server configuration parameter" msgstr "змінити параметр конфігурації сервера" -#: sql_help.c:5340 +#: sql_help.c:5366 msgid "change the definition of a table" msgstr "змінити визначення таблиці" -#: sql_help.c:5346 +#: sql_help.c:5372 msgid "change the definition of a tablespace" msgstr "змінити визначення табличного простору" -#: sql_help.c:5352 +#: sql_help.c:5378 msgid "change the definition of a text search configuration" msgstr "змінити визначення конфігурації текстового пошуку" -#: sql_help.c:5358 +#: sql_help.c:5384 msgid "change the definition of a text search dictionary" msgstr "змінити визначення словника текстового пошуку" -#: sql_help.c:5364 +#: sql_help.c:5390 msgid "change the definition of a text search parser" msgstr "змінити визначення парсера текстового пошуку" -#: sql_help.c:5370 +#: sql_help.c:5396 msgid "change the definition of a text search template" msgstr "змінити визначення шаблона текстового пошуку" -#: sql_help.c:5376 +#: sql_help.c:5402 msgid "change the definition of a trigger" msgstr "змінити визначення тригеру" -#: sql_help.c:5382 +#: sql_help.c:5408 msgid "change the definition of a type" msgstr "змінити визначення типу" -#: sql_help.c:5394 +#: sql_help.c:5420 msgid "change the definition of a user mapping" msgstr "змінити визначення зіставлень користувачів" -#: sql_help.c:5400 +#: sql_help.c:5426 msgid "change the definition of a view" msgstr "змінити визначення подання" -#: sql_help.c:5406 +#: sql_help.c:5432 msgid "collect statistics about a database" msgstr "зібрати статистику про базу даних" -#: sql_help.c:5412 sql_help.c:6210 +#: sql_help.c:5438 sql_help.c:6236 msgid "start a transaction block" msgstr "розпочати транзакцію" -#: sql_help.c:5418 +#: sql_help.c:5444 msgid "invoke a procedure" msgstr "викликати процедуру" -#: sql_help.c:5424 +#: sql_help.c:5450 msgid "force a write-ahead log checkpoint" msgstr "провести контрольну точку в журналі попереднього запису" -#: sql_help.c:5430 +#: sql_help.c:5456 msgid "close a cursor" msgstr "закрити курсор" -#: sql_help.c:5436 +#: sql_help.c:5462 msgid "cluster a table according to an index" msgstr "перегрупувати таблицю за індексом" -#: sql_help.c:5442 +#: sql_help.c:5468 msgid "define or change the comment of an object" msgstr "задати або змінити коментар об'єкта" -#: sql_help.c:5448 sql_help.c:6006 +#: sql_help.c:5474 sql_help.c:6032 msgid "commit the current transaction" msgstr "затвердити поточну транзакцію" -#: sql_help.c:5454 +#: sql_help.c:5480 msgid "commit a transaction that was earlier prepared for two-phase commit" msgstr "затвердити транзакцію, раніше підготовлену до двохфазного затвердження" -#: sql_help.c:5460 +#: sql_help.c:5486 msgid "copy data between a file and a table" msgstr "копіювати дані між файлом та таблицею" -#: sql_help.c:5466 +#: sql_help.c:5492 msgid "define a new access method" msgstr "визначити новий метод доступу" -#: sql_help.c:5472 +#: sql_help.c:5498 msgid "define a new aggregate function" msgstr "визначити нову агрегатну функцію" -#: sql_help.c:5478 +#: sql_help.c:5504 msgid "define a new cast" msgstr "визначити приведення типів" -#: sql_help.c:5484 +#: sql_help.c:5510 msgid "define a new collation" msgstr "визначити нове правило сортування" -#: sql_help.c:5490 +#: sql_help.c:5516 msgid "define a new encoding conversion" msgstr "визначити нове перетворення кодування" -#: sql_help.c:5496 +#: sql_help.c:5522 msgid "create a new database" msgstr "створити нову базу даних" -#: sql_help.c:5502 +#: sql_help.c:5528 msgid "define a new domain" msgstr "визначити новий домен" -#: sql_help.c:5508 +#: sql_help.c:5534 msgid "define a new event trigger" msgstr "визначити новий тригер події" -#: sql_help.c:5514 +#: sql_help.c:5540 msgid "install an extension" msgstr "встановити розширення" -#: sql_help.c:5520 +#: sql_help.c:5546 msgid "define a new foreign-data wrapper" msgstr "визначити нове джерело сторонніх даних" -#: sql_help.c:5526 +#: sql_help.c:5552 msgid "define a new foreign table" msgstr "визначити нову сторонню таблицю" -#: sql_help.c:5532 +#: sql_help.c:5558 msgid "define a new function" msgstr "визначити нову функцію" -#: sql_help.c:5538 sql_help.c:5598 sql_help.c:5700 +#: sql_help.c:5564 sql_help.c:5624 sql_help.c:5726 msgid "define a new database role" msgstr "визначити нову роль бази даних" -#: sql_help.c:5544 +#: sql_help.c:5570 msgid "define a new index" msgstr "визначити новий індекс" -#: sql_help.c:5550 +#: sql_help.c:5576 msgid "define a new procedural language" msgstr "визначити нову процедурну мову" -#: sql_help.c:5556 +#: sql_help.c:5582 msgid "define a new materialized view" msgstr "визначити нове матеріалізоване подання" -#: sql_help.c:5562 +#: sql_help.c:5588 msgid "define a new operator" msgstr "визначити новий оператор" -#: sql_help.c:5568 +#: sql_help.c:5594 msgid "define a new operator class" msgstr "визначити новий клас оператора" -#: sql_help.c:5574 +#: sql_help.c:5600 msgid "define a new operator family" msgstr "визначити нове сімейство операторів" -#: sql_help.c:5580 +#: sql_help.c:5606 msgid "define a new row-level security policy for a table" msgstr "визначити нову політику безпеки на рівні рядків для таблиці" -#: sql_help.c:5586 +#: sql_help.c:5612 msgid "define a new procedure" msgstr "визначити нову процедуру" -#: sql_help.c:5592 +#: sql_help.c:5618 msgid "define a new publication" msgstr "визначити нову публікацію" -#: sql_help.c:5604 +#: sql_help.c:5630 msgid "define a new rewrite rule" msgstr "визначити нове правило перезапису" -#: sql_help.c:5610 +#: sql_help.c:5636 msgid "define a new schema" msgstr "визначити нову схему" -#: sql_help.c:5616 +#: sql_help.c:5642 msgid "define a new sequence generator" msgstr "визначити новий генератор послідовностей" -#: sql_help.c:5622 +#: sql_help.c:5648 msgid "define a new foreign server" msgstr "визначити новий сторонній сервер" -#: sql_help.c:5628 +#: sql_help.c:5654 msgid "define extended statistics" msgstr "визначити розширену статистику" -#: sql_help.c:5634 +#: sql_help.c:5660 msgid "define a new subscription" msgstr "визначити нову підписку" -#: sql_help.c:5640 +#: sql_help.c:5666 msgid "define a new table" msgstr "визначити нову таблицю" -#: sql_help.c:5646 sql_help.c:6168 +#: sql_help.c:5672 sql_help.c:6194 msgid "define a new table from the results of a query" msgstr "визначити нову таблицю з результатів запиту" -#: sql_help.c:5652 +#: sql_help.c:5678 msgid "define a new tablespace" msgstr "визначити новий табличний простір" -#: sql_help.c:5658 +#: sql_help.c:5684 msgid "define a new text search configuration" msgstr "визначити нову конфігурацію текстового пошуку" -#: sql_help.c:5664 +#: sql_help.c:5690 msgid "define a new text search dictionary" msgstr "визначити новий словник текстового пошуку" -#: sql_help.c:5670 +#: sql_help.c:5696 msgid "define a new text search parser" msgstr "визначити новий аналізатор текстового пошуку" -#: sql_help.c:5676 +#: sql_help.c:5702 msgid "define a new text search template" msgstr "визначити новий шаблон текстового пошуку" -#: sql_help.c:5682 +#: sql_help.c:5708 msgid "define a new transform" msgstr "визначити нове перетворення" -#: sql_help.c:5688 +#: sql_help.c:5714 msgid "define a new trigger" msgstr "визначити новий тригер" -#: sql_help.c:5694 +#: sql_help.c:5720 msgid "define a new data type" msgstr "визначити новий тип даних" -#: sql_help.c:5706 +#: sql_help.c:5732 msgid "define a new mapping of a user to a foreign server" msgstr "визначити нове зіставлення користувача для стороннього сервера" -#: sql_help.c:5712 +#: sql_help.c:5738 msgid "define a new view" msgstr "визначити нове подання" -#: sql_help.c:5718 +#: sql_help.c:5744 msgid "deallocate a prepared statement" msgstr "звільнити підготовлену команду" -#: sql_help.c:5724 +#: sql_help.c:5750 msgid "define a cursor" msgstr "визначити курсор" -#: sql_help.c:5730 +#: sql_help.c:5756 msgid "delete rows of a table" msgstr "видалити рядки таблиці" -#: sql_help.c:5736 +#: sql_help.c:5762 msgid "discard session state" msgstr "очистити стан сесії" -#: sql_help.c:5742 +#: sql_help.c:5768 msgid "execute an anonymous code block" msgstr "виконати анонімний блок коду" -#: sql_help.c:5748 +#: sql_help.c:5774 msgid "remove an access method" msgstr "видалити метод доступу" -#: sql_help.c:5754 +#: sql_help.c:5780 msgid "remove an aggregate function" msgstr "видалити агрегатну функцію" -#: sql_help.c:5760 +#: sql_help.c:5786 msgid "remove a cast" msgstr "видалити приведення типів" -#: sql_help.c:5766 +#: sql_help.c:5792 msgid "remove a collation" msgstr "видалити правило сортування" -#: sql_help.c:5772 +#: sql_help.c:5798 msgid "remove a conversion" msgstr "видалити перетворення" -#: sql_help.c:5778 +#: sql_help.c:5804 msgid "remove a database" msgstr "видалити базу даних" -#: sql_help.c:5784 +#: sql_help.c:5810 msgid "remove a domain" msgstr "видалити домен" -#: sql_help.c:5790 +#: sql_help.c:5816 msgid "remove an event trigger" msgstr "видалити тригер події" -#: sql_help.c:5796 +#: sql_help.c:5822 msgid "remove an extension" msgstr "видалити розширення" -#: sql_help.c:5802 +#: sql_help.c:5828 msgid "remove a foreign-data wrapper" msgstr "видалити джерело сторонніх даних" -#: sql_help.c:5808 +#: sql_help.c:5834 msgid "remove a foreign table" msgstr "видалити сторонню таблицю" -#: sql_help.c:5814 +#: sql_help.c:5840 msgid "remove a function" msgstr "видалити функцію" -#: sql_help.c:5820 sql_help.c:5886 sql_help.c:5988 +#: sql_help.c:5846 sql_help.c:5912 sql_help.c:6014 msgid "remove a database role" msgstr "видалити роль бази даних" -#: sql_help.c:5826 +#: sql_help.c:5852 msgid "remove an index" msgstr "видалити індекс" -#: sql_help.c:5832 +#: sql_help.c:5858 msgid "remove a procedural language" msgstr "видалити процедурну мову" -#: sql_help.c:5838 +#: sql_help.c:5864 msgid "remove a materialized view" msgstr "видалити матеріалізоване подання" -#: sql_help.c:5844 +#: sql_help.c:5870 msgid "remove an operator" msgstr "видалити оператор" -#: sql_help.c:5850 +#: sql_help.c:5876 msgid "remove an operator class" msgstr "видалити клас операторів" -#: sql_help.c:5856 +#: sql_help.c:5882 msgid "remove an operator family" msgstr "видалити сімейство операторів" -#: sql_help.c:5862 +#: sql_help.c:5888 msgid "remove database objects owned by a database role" msgstr "видалити об'єкти бази даних, що належать ролі" -#: sql_help.c:5868 +#: sql_help.c:5894 msgid "remove a row-level security policy from a table" msgstr "видалити політику безпеки на рівні рядків з таблиці" -#: sql_help.c:5874 +#: sql_help.c:5900 msgid "remove a procedure" msgstr "видалити процедуру" -#: sql_help.c:5880 +#: sql_help.c:5906 msgid "remove a publication" msgstr "видалити публікацію" -#: sql_help.c:5892 +#: sql_help.c:5918 msgid "remove a routine" msgstr "видалити підпрограму" -#: sql_help.c:5898 +#: sql_help.c:5924 msgid "remove a rewrite rule" msgstr "видалити правило перезапису" -#: sql_help.c:5904 +#: sql_help.c:5930 msgid "remove a schema" msgstr "видалити схему" -#: sql_help.c:5910 +#: sql_help.c:5936 msgid "remove a sequence" msgstr "видалити послідовність" -#: sql_help.c:5916 +#: sql_help.c:5942 msgid "remove a foreign server descriptor" msgstr "видалити опис стороннього серверу" -#: sql_help.c:5922 +#: sql_help.c:5948 msgid "remove extended statistics" msgstr "видалити розширену статистику" -#: sql_help.c:5928 +#: sql_help.c:5954 msgid "remove a subscription" msgstr "видалити підписку" -#: sql_help.c:5934 +#: sql_help.c:5960 msgid "remove a table" msgstr "видалити таблицю" -#: sql_help.c:5940 +#: sql_help.c:5966 msgid "remove a tablespace" msgstr "видалити табличний простір" -#: sql_help.c:5946 +#: sql_help.c:5972 msgid "remove a text search configuration" msgstr "видалити конфігурацію тектового пошуку" -#: sql_help.c:5952 +#: sql_help.c:5978 msgid "remove a text search dictionary" msgstr "видалити словник тектового пошуку" -#: sql_help.c:5958 +#: sql_help.c:5984 msgid "remove a text search parser" msgstr "видалити парсер тектового пошуку" -#: sql_help.c:5964 +#: sql_help.c:5990 msgid "remove a text search template" msgstr "видалити шаблон тектового пошуку" -#: sql_help.c:5970 +#: sql_help.c:5996 msgid "remove a transform" msgstr "видалити перетворення" -#: sql_help.c:5976 +#: sql_help.c:6002 msgid "remove a trigger" msgstr "видалити тригер" -#: sql_help.c:5982 +#: sql_help.c:6008 msgid "remove a data type" msgstr "видалити тип даних" -#: sql_help.c:5994 +#: sql_help.c:6020 msgid "remove a user mapping for a foreign server" msgstr "видалити зіставлення користувача для стороннього серверу" -#: sql_help.c:6000 +#: sql_help.c:6026 msgid "remove a view" msgstr "видалити подання" -#: sql_help.c:6012 +#: sql_help.c:6038 msgid "execute a prepared statement" msgstr "виконати підготовлену команду" -#: sql_help.c:6018 +#: sql_help.c:6044 msgid "show the execution plan of a statement" msgstr "показати план виконання команди" -#: sql_help.c:6024 +#: sql_help.c:6050 msgid "retrieve rows from a query using a cursor" msgstr "отримати рядки запиту з курсору" -#: sql_help.c:6030 +#: sql_help.c:6056 msgid "define access privileges" msgstr "визначити права доступу" -#: sql_help.c:6036 +#: sql_help.c:6062 msgid "import table definitions from a foreign server" msgstr "імпортувати визначення таблиць зі стороннього серверу" -#: sql_help.c:6042 +#: sql_help.c:6068 msgid "create new rows in a table" msgstr "створити нові рядки в таблиці" -#: sql_help.c:6048 +#: sql_help.c:6074 msgid "listen for a notification" msgstr "очікувати на повідомлення" -#: sql_help.c:6054 +#: sql_help.c:6080 msgid "load a shared library file" msgstr "завантажити файл спільної бібліотеки" -#: sql_help.c:6060 +#: sql_help.c:6086 msgid "lock a table" msgstr "заблокувати таблицю" -#: sql_help.c:6066 +#: sql_help.c:6092 msgid "conditionally insert, update, or delete rows of a table" msgstr "умовно вставити, оновити або видалити рядки таблиці" -#: sql_help.c:6072 +#: sql_help.c:6098 msgid "position a cursor" msgstr "розташувати курсор" -#: sql_help.c:6078 +#: sql_help.c:6104 msgid "generate a notification" msgstr "згенерувати повідомлення" -#: sql_help.c:6084 +#: sql_help.c:6110 msgid "prepare a statement for execution" msgstr "підготувати команду для виконання" -#: sql_help.c:6090 +#: sql_help.c:6116 msgid "prepare the current transaction for two-phase commit" msgstr "підготувати поточну транзакцію для двохфазного затвердження" -#: sql_help.c:6096 +#: sql_help.c:6122 msgid "change the ownership of database objects owned by a database role" msgstr "змінити власника об'єктів БД, що належать заданій ролі" -#: sql_help.c:6102 +#: sql_help.c:6128 msgid "replace the contents of a materialized view" msgstr "замінити вміст матеріалізованого подання" -#: sql_help.c:6108 +#: sql_help.c:6134 msgid "rebuild indexes" msgstr "перебудувати індекси" -#: sql_help.c:6114 +#: sql_help.c:6140 msgid "release a previously defined savepoint" msgstr "звільнити раніше визначену точку збереження" -#: sql_help.c:6120 +#: sql_help.c:6146 msgid "restore the value of a run-time parameter to the default value" msgstr "відновити початкове значення параметру виконання" -#: sql_help.c:6126 +#: sql_help.c:6152 msgid "remove access privileges" msgstr "видалити права доступу" -#: sql_help.c:6138 +#: sql_help.c:6164 msgid "cancel a transaction that was earlier prepared for two-phase commit" msgstr "скасувати транзакцію, раніше підготовлену до двохфазного затвердження" -#: sql_help.c:6144 +#: sql_help.c:6170 msgid "roll back to a savepoint" msgstr "відкотитися до точки збереження" -#: sql_help.c:6150 +#: sql_help.c:6176 msgid "define a new savepoint within the current transaction" msgstr "визначити нову точку збереження в рамках поточної транзакції" -#: sql_help.c:6156 +#: sql_help.c:6182 msgid "define or change a security label applied to an object" msgstr "визначити або змінити мітку безпеки, застосовану до об'єкта" -#: sql_help.c:6162 sql_help.c:6216 sql_help.c:6252 +#: sql_help.c:6188 sql_help.c:6242 sql_help.c:6278 msgid "retrieve rows from a table or view" msgstr "отримати рядки з таблиці або подання" -#: sql_help.c:6174 +#: sql_help.c:6200 msgid "change a run-time parameter" msgstr "змінити параметр виконання" -#: sql_help.c:6180 +#: sql_help.c:6206 msgid "set constraint check timing for the current transaction" msgstr "встановити час перевірки обмеження для поточної транзакції" -#: sql_help.c:6186 +#: sql_help.c:6212 msgid "set the current user identifier of the current session" msgstr "встановити ідентифікатор поточного користувача в поточній сесії" -#: sql_help.c:6192 +#: sql_help.c:6218 msgid "set the session user identifier and the current user identifier of the current session" msgstr "встановити ідентифікатор користувача сесії й ідентифікатор поточного користувача в поточній сесії" -#: sql_help.c:6198 +#: sql_help.c:6224 msgid "set the characteristics of the current transaction" msgstr "встановити характеристики поточної транзакції" -#: sql_help.c:6204 +#: sql_help.c:6230 msgid "show the value of a run-time parameter" msgstr "показати значення параметра виконання" -#: sql_help.c:6222 +#: sql_help.c:6248 msgid "empty a table or set of tables" msgstr "очистити таблицю або декілька таблиць" -#: sql_help.c:6228 +#: sql_help.c:6254 msgid "stop listening for a notification" msgstr "припинити очікування повідомлень" -#: sql_help.c:6234 +#: sql_help.c:6260 msgid "update rows of a table" msgstr "змінити рядки таблиці" -#: sql_help.c:6240 +#: sql_help.c:6266 msgid "garbage-collect and optionally analyze a database" msgstr "виконати збір сміття і проаналізувати базу даних" -#: sql_help.c:6246 +#: sql_help.c:6272 msgid "compute a set of rows" msgstr "отримати набір рядків" @@ -6254,7 +6322,7 @@ msgstr "зайвий аргумент \"%s\" проігнорований" msgid "could not find own program executable" msgstr "не вдалося знайти ехе файл власної програми" -#: tab-complete.c:6078 +#: tab-complete.c:6216 #, c-format msgid "tab completion query failed: %s\n" "Query was:\n" diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index 0d99d00ac922c..3aa7d2d06c80e 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/prompt.c */ @@ -31,8 +31,10 @@ * sockets, "[local:/dir/name]" if not default * %m - like %M, but hostname only (before first dot), or always "[local]" * %p - backend pid + * %P - pipeline status: on, off or abort * %> - database server port number * %n - database user name + * %s - service * %/ - current database * %~ - like %/ but "~" when database name equals user name * %w - whitespace of the same width as the most recent output of PROMPT1 @@ -165,6 +167,11 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) if (pset.db) strlcpy(buf, session_username(), sizeof(buf)); break; + /* service name */ + case 's': + if (pset.db && PQservice(pset.db)) + strlcpy(buf, PQservice(pset.db), sizeof(buf)); + break; /* backend pid */ case 'p': if (pset.db) @@ -175,6 +182,19 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) snprintf(buf, sizeof(buf), "%d", pid); } break; + /* pipeline status */ + case 'P': + { + PGpipelineStatus status = PQpipelineStatus(pset.db); + + if (status == PQ_PIPELINE_ON) + strlcpy(buf, "on", sizeof(buf)); + else if (status == PQ_PIPELINE_ABORTED) + strlcpy(buf, "abort", sizeof(buf)); + else + strlcpy(buf, "off", sizeof(buf)); + break; + } case '0': case '1': diff --git a/src/bin/psql/prompt.h b/src/bin/psql/prompt.h index f7c4cf018b2dd..f1f6ca51aba0a 100644 --- a/src/bin/psql/prompt.h +++ b/src/bin/psql/prompt.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/prompt.h */ diff --git a/src/bin/psql/psqlscanslash.h b/src/bin/psql/psqlscanslash.h index 8afd748e87e1f..497e7e2c9634a 100644 --- a/src/bin/psql/psqlscanslash.h +++ b/src/bin/psql/psqlscanslash.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/psqlscanslash.h */ diff --git a/src/bin/psql/psqlscanslash.l b/src/bin/psql/psqlscanslash.l index e1ae8627dbf27..ae7602a61dfc1 100644 --- a/src/bin/psql/psqlscanslash.l +++ b/src/bin/psql/psqlscanslash.l @@ -8,7 +8,7 @@ * * See fe_utils/psqlscan_int.h for additional commentary. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -38,12 +38,6 @@ */ typedef int YYSTYPE; -/* - * Set the type of yyextra; we use it as a pointer back to the containing - * PsqlScanState. - */ -#define YY_EXTRA_TYPE PsqlScanState - /* * These variables do not need to be saved across calls. Yeah, it's a bit * of a hack, but putting them into PsqlScanStateData would be klugy too. @@ -63,15 +57,6 @@ static void evaluate_backtick(PsqlScanState state); #define ECHO psqlscan_emit(cur_state, yytext, yyleng) -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int slash_yyget_column(yyscan_t yyscanner); -extern void slash_yyset_column(int column_no, yyscan_t yyscanner); - /* LCOV_EXCL_START */ %} @@ -88,6 +73,12 @@ extern void slash_yyset_column(int column_no, yyscan_t yyscanner); %option warn %option prefix="slash_yy" +/* + * Set the type of yyextra; we use it as a pointer back to the containing + * PsqlScanState. + */ +%option extra-type="PsqlScanState" + /* * OK, here is a short description of lex/flex rules behavior. * The longest pattern which matches an input string is always chosen. @@ -598,9 +589,9 @@ psql_scan_slash_option(PsqlScanState state, psql_scan_reselect_sql_lexer(state); /* - * Check the lex result: we should have gotten back either LEXRES_OK - * or LEXRES_EOL (the latter indicating end of string). If we were inside - * a quoted string, as indicated by final_state, EOL is an error. + * Check the lex result: we should have gotten back either LEXRES_OK or + * LEXRES_EOL (the latter indicating end of string). If we were inside a + * quoted string, as indicated by final_state, EOL is an error. */ Assert(lexresult == LEXRES_EOL || lexresult == LEXRES_OK); @@ -642,6 +633,7 @@ psql_scan_slash_option(PsqlScanState state, termPQExpBuffer(&mybuf); return NULL; case xslashwholeline: + /* * In whole-line mode, we interpret semicolon = true as stripping * trailing whitespace as well as semicolons; this gives the diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index 505f99d8e47de..fd82303f776c4 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/settings.h */ @@ -27,6 +27,12 @@ #define DEFAULT_PROMPT2 "%/%R%x%# " #define DEFAULT_PROMPT3 ">> " +#define DEFAULT_WATCH_INTERVAL "2" +/* + * Limit the max default setting to a value which should be safe for the + * itimer call, yet large enough to cover all realistic usecases. + */ +#define DEFAULT_WATCH_INTERVAL_MAX (1000*1000) /* * Note: these enums should generally be chosen so that zero corresponds * to the default behavior. @@ -62,6 +68,21 @@ typedef enum PSQL_COMP_CASE_LOWER, } PSQL_COMP_CASE; +typedef enum +{ + PSQL_SEND_QUERY, + PSQL_SEND_EXTENDED_CLOSE, + PSQL_SEND_EXTENDED_PARSE, + PSQL_SEND_EXTENDED_QUERY_PARAMS, + PSQL_SEND_EXTENDED_QUERY_PREPARED, + PSQL_SEND_PIPELINE_SYNC, + PSQL_SEND_START_PIPELINE_MODE, + PSQL_SEND_END_PIPELINE_MODE, + PSQL_SEND_FLUSH, + PSQL_SEND_FLUSH_REQUEST, + PSQL_SEND_GET_RESULTS, +} PSQL_SEND_MODE; + typedef enum { hctl_none = 0, @@ -96,10 +117,18 @@ typedef struct _psqlSettings char *gset_prefix; /* one-shot prefix argument for \gset */ bool gdesc_flag; /* one-shot request to describe query result */ bool gexec_flag; /* one-shot request to execute query result */ - bool bind_flag; /* one-shot request to use extended query - * protocol */ + PSQL_SEND_MODE send_mode; /* one-shot request to send query with normal + * or extended query protocol */ int bind_nparams; /* number of parameters */ char **bind_params; /* parameters for extended query protocol call */ + char *stmtName; /* prepared statement name used for extended + * query protocol commands */ + int piped_commands; /* number of piped commands */ + int piped_syncs; /* number of piped syncs */ + int available_results; /* number of results available to get */ + int requested_results; /* number of requested results, including + * sync messages. Used to read a limited + * subset of the available_results. */ bool crosstab_flag; /* one-shot request to crosstab result */ char *ctv_args[4]; /* \crosstabview arguments */ @@ -143,6 +172,7 @@ typedef struct _psqlSettings int fetch_count; int histsize; int ignoreeof; + double watch_interval; PSQL_ECHO echo; PSQL_ECHO_HIDDEN echo_hidden; PSQL_ERROR_ROLLBACK on_error_rollback; diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 036caaec2ffca..249b6aa516902 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/startup.c */ @@ -205,6 +205,11 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); SetVariableBool(pset.vars, "SHOW_ALL_RESULTS"); + /* Initialize pipeline variables */ + SetVariable(pset.vars, "PIPELINE_SYNC_COUNT", "0"); + SetVariable(pset.vars, "PIPELINE_COMMAND_COUNT", "0"); + SetVariable(pset.vars, "PIPELINE_RESULT_COUNT", "0"); + parse_psql_options(argc, argv, &options); /* @@ -399,7 +404,7 @@ main(int argc, char *argv[]) cell->val, strlen(cell->val), pset.encoding, standard_strings()); cond_stack = conditional_stack_create(); - psql_scan_set_passthrough(scan_state, (void *) cond_stack); + psql_scan_set_passthrough(scan_state, cond_stack); successResult = HandleSlashCmds(scan_state, cond_stack, @@ -939,6 +944,21 @@ histsize_hook(const char *newval) return ParseVariableNum(newval, "HISTSIZE", &pset.histsize); } +static char * +watch_interval_substitute_hook(char *newval) +{ + if (newval == NULL) + newval = pg_strdup(DEFAULT_WATCH_INTERVAL); + return newval; +} + +static bool +watch_interval_hook(const char *newval) +{ + return ParseVariableDouble(newval, "WATCH_INTERVAL", &pset.watch_interval, + 0, DEFAULT_WATCH_INTERVAL_MAX); +} + static char * ignoreeof_substitute_hook(char *newval) { @@ -1265,4 +1285,7 @@ EstablishVariableSpace(void) SetVariableHooks(pset.vars, "HIDE_TABLEAM", bool_substitute_hook, hide_tableam_hook); + SetVariableHooks(pset.vars, "WATCH_INTERVAL", + watch_interval_substitute_hook, + watch_interval_hook); } diff --git a/src/bin/psql/stringutils.c b/src/bin/psql/stringutils.c index c07f7d13007eb..f613413553e29 100644 --- a/src/bin/psql/stringutils.c +++ b/src/bin/psql/stringutils.c @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/stringutils.c */ diff --git a/src/bin/psql/stringutils.h b/src/bin/psql/stringutils.h index f742b4f87c66d..5b91e96410344 100644 --- a/src/bin/psql/stringutils.h +++ b/src/bin/psql/stringutils.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/stringutils.h */ diff --git a/src/bin/psql/t/001_basic.pl b/src/bin/psql/t/001_basic.pl index 5f2f4541af0e2..f42c3961e09f7 100644 --- a/src/bin/psql/t/001_basic.pl +++ b/src/bin/psql/t/001_basic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -34,11 +34,13 @@ sub psql_fails_like { local $Test::Builder::Level = $Test::Builder::Level + 1; - my ($node, $sql, $expected_stderr, $test_name) = @_; + my ($node, $sql, $expected_stderr, $test_name, $replication) = @_; + + # Use the context of a WAL sender, if requested by the caller. + $replication = '' unless defined($replication); - # Use the context of a WAL sender, some of the tests rely on that. my ($ret, $stdout, $stderr) = - $node->psql('postgres', $sql, replication => 'database'); + $node->psql('postgres', $sql, replication => $replication); isnt($ret, 0, "$test_name: exit code not 0"); like($stderr, $expected_stderr, "$test_name: matches"); @@ -52,8 +54,9 @@ sub psql_fails_like my ($stdout, $stderr); my $result; - $result = IPC::Run::run [ 'psql', "--help=$arg" ], '>', \$stdout, '2>', - \$stderr; + $result = IPC::Run::run [ 'psql', "--help=$arg" ], + '>' => \$stdout, + '2>' => \$stderr; ok($result, "psql --help=$arg exit code 0"); isnt($stdout, '', "psql --help=$arg goes to stdout"); is($stderr, '', "psql --help=$arg nothing to stderr"); @@ -78,7 +81,7 @@ sub psql_fails_like $node, 'START_REPLICATION 0/0', qr/unexpected PQresultStatus: 8$/, - 'handling of unexpected PQresultStatus'); + 'handling of unexpected PQresultStatus', 'database'); # test \timing psql_like( @@ -216,11 +219,12 @@ sub psql_fails_like # Tests with ON_ERROR_STOP. $node->command_ok( [ - 'psql', '-X', - '--single-transaction', '-v', - 'ON_ERROR_STOP=1', '-c', - 'INSERT INTO tab_psql_single VALUES (1)', '-c', - 'INSERT INTO tab_psql_single VALUES (2)' + 'psql', + '--no-psqlrc', + '--single-transaction', + '--set' => 'ON_ERROR_STOP=1', + '--command' => 'INSERT INTO tab_psql_single VALUES (1)', + '--command' => 'INSERT INTO tab_psql_single VALUES (2)', ], 'ON_ERROR_STOP, --single-transaction and multiple -c switches'); my $row_count = @@ -231,11 +235,12 @@ sub psql_fails_like $node->command_fails( [ - 'psql', '-X', - '--single-transaction', '-v', - 'ON_ERROR_STOP=1', '-c', - 'INSERT INTO tab_psql_single VALUES (3)', '-c', - "\\copy tab_psql_single FROM '$tempdir/nonexistent'" + 'psql', + '--no-psqlrc', + '--single-transaction', + '--set' => 'ON_ERROR_STOP=1', + '--command' => 'INSERT INTO tab_psql_single VALUES (3)', + '--command' => "\\copy tab_psql_single FROM '$tempdir/nonexistent'" ], 'ON_ERROR_STOP, --single-transaction and multiple -c switches, error'); $row_count = @@ -252,9 +257,12 @@ sub psql_fails_like append_to_file($insert_sql_file, 'INSERT INTO tab_psql_single VALUES (4);'); $node->command_ok( [ - 'psql', '-X', '--single-transaction', '-v', - 'ON_ERROR_STOP=1', '-f', $insert_sql_file, '-f', - $insert_sql_file + 'psql', + '--no-psqlrc', + '--single-transaction', + '--set' => 'ON_ERROR_STOP=1', + '--file' => $insert_sql_file, + '--file' => $insert_sql_file ], 'ON_ERROR_STOP, --single-transaction and multiple -f switches'); $row_count = @@ -265,9 +273,12 @@ sub psql_fails_like $node->command_fails( [ - 'psql', '-X', '--single-transaction', '-v', - 'ON_ERROR_STOP=1', '-f', $insert_sql_file, '-f', - $copy_sql_file + 'psql', + '--no-psqlrc', + '--single-transaction', + '--set' => 'ON_ERROR_STOP=1', + '--file' => $insert_sql_file, + '--file' => $copy_sql_file ], 'ON_ERROR_STOP, --single-transaction and multiple -f switches, error'); $row_count = @@ -281,11 +292,12 @@ sub psql_fails_like # transaction commits. $node->command_fails( [ - 'psql', '-X', - '--single-transaction', '-f', - $insert_sql_file, '-f', - $insert_sql_file, '-c', - "\\copy tab_psql_single FROM '$tempdir/nonexistent'" + 'psql', + '--no-psqlrc', + '--single-transaction', + '--file' => $insert_sql_file, + '--file' => $insert_sql_file, + '--command' => "\\copy tab_psql_single FROM '$tempdir/nonexistent'" ], 'no ON_ERROR_STOP, --single-transaction and multiple -f/-c switches'); $row_count = @@ -298,9 +310,12 @@ sub psql_fails_like # returns a success and the transaction commits. $node->command_ok( [ - 'psql', '-X', '--single-transaction', '-f', - $insert_sql_file, '-f', $insert_sql_file, '-f', - $copy_sql_file + 'psql', + '--no-psqlrc', + '--single-transaction', + '--file' => $insert_sql_file, + '--file' => $insert_sql_file, + '--file' => $copy_sql_file ], 'no ON_ERROR_STOP, --single-transaction and multiple -f switches'); $row_count = @@ -313,11 +328,12 @@ sub psql_fails_like # the transaction commit even if there is a failure in-between. $node->command_ok( [ - 'psql', '-X', - '--single-transaction', '-c', - 'INSERT INTO tab_psql_single VALUES (5)', '-f', - $copy_sql_file, '-c', - 'INSERT INTO tab_psql_single VALUES (6)' + 'psql', + '--no-psqlrc', + '--single-transaction', + '--command' => 'INSERT INTO tab_psql_single VALUES (5)', + '--file' => $copy_sql_file, + '--command' => 'INSERT INTO tab_psql_single VALUES (6)' ], 'no ON_ERROR_STOP, --single-transaction and multiple -c switches'); $row_count = @@ -352,8 +368,20 @@ sub psql_fails_like # Check \watch # Note: the interval value is parsed with locale-aware strtod() -psql_like($node, sprintf('SELECT 1 \watch c=3 i=%g', 0.01), - qr/1\n1\n1/, '\watch with 3 iterations'); +psql_like( + $node, sprintf('SELECT 1 \watch c=3 i=%g', 0.01), + qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.01'); + +# Sub-millisecond wait works, equivalent to 0. +psql_like( + $node, sprintf('SELECT 1 \watch c=3 i=%g', 0.0001), + qr/1\n1\n1/, '\watch with 3 iterations, interval of 0.0001'); + +# Test zero interval +psql_like( + $node, '\set WATCH_INTERVAL 0 +SELECT 1 \watch c=3', + qr/1\n1\n1/, '\watch with 3 iterations, interval of 0'); # Check \watch minimum row count psql_fails_like( @@ -406,6 +434,24 @@ sub psql_fails_like qr/iteration count is specified more than once/, '\watch, iteration count is specified more than once'); +# Check WATCH_INTERVAL +psql_like( + $node, + '\echo :WATCH_INTERVAL +\set WATCH_INTERVAL 10 +\echo :WATCH_INTERVAL +\unset WATCH_INTERVAL +\echo :WATCH_INTERVAL', + qr/^2$ +^10$ +^2$/m, + 'WATCH_INTERVAL variable is set and updated'); +psql_fails_like( + $node, + '\set WATCH_INTERVAL 1e500', + qr/is out of range/, + 'WATCH_INTERVAL variable is out of range'); + # Test \g output piped into a program. # The program is perl -pe '' to simply copy the input to the output. my $g_file = "$tempdir/g_file_1.out"; @@ -437,4 +483,51 @@ sub psql_fails_like my $c4 = slurp_file($g_file); like($c4, qr/foo.*bar/s); +# Test COPY within pipelines. These abort the connection from +# the frontend so they cannot be tested via SQL. +$node->safe_psql('postgres', 'CREATE TABLE psql_pipeline()'); +my $log_location = -s $node->logfile; +psql_fails_like( + $node, + qq{\\startpipeline +COPY psql_pipeline FROM STDIN; +SELECT 'val1'; +\\syncpipeline +\\endpipeline}, + qr/COPY in a pipeline is not supported, aborting connection/, + 'COPY FROM in pipeline: fails'); +$node->wait_for_log( + qr/FATAL: .*terminating connection because protocol synchronization was lost/, + $log_location); + +# Remove \syncpipeline here. +psql_fails_like( + $node, + qq{\\startpipeline +COPY psql_pipeline TO STDOUT; +SELECT 'val1'; +\\endpipeline}, + qr/COPY in a pipeline is not supported, aborting connection/, + 'COPY TO in pipeline: fails'); + +psql_fails_like( + $node, + qq{\\startpipeline +\\copy psql_pipeline from stdin; +SELECT 'val1'; +\\syncpipeline +\\endpipeline}, + qr/COPY in a pipeline is not supported, aborting connection/, + '\copy from in pipeline: fails'); + +# Sync attempt after a COPY TO/FROM. +psql_fails_like( + $node, + qq{\\startpipeline +\\copy psql_pipeline to stdout; +\\syncpipeline +\\endpipeline}, + qr/COPY in a pipeline is not supported, aborting connection/, + '\copy to in pipeline: fails'); + done_testing(); diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl index b45c39f0f5249..fa7427af8c58d 100644 --- a/src/bin/psql/t/010_tab_completion.pl +++ b/src/bin/psql/t/010_tab_completion.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -39,7 +39,7 @@ # set up a few database objects $node->safe_psql('postgres', - "CREATE TABLE tab1 (c1 int primary key, c2 text);\n" + "CREATE TABLE tab1 (c1 int primary key constraint foo not null, c2 text);\n" . "CREATE TABLE mytab123 (f1 int, f2 text);\n" . "CREATE TABLE mytab246 (f1 int, f2 text);\n" . "CREATE TABLE \"mixedName\" (f1 int, f2 text);\n" @@ -167,26 +167,18 @@ sub clear_line qr/"mytab123" +"mytab246"/, "offer multiple quoted table choices"); -# note: broken versions of libedit want to backslash the closing quote; -# not much we can do about that -check_completion("2\t", qr/246\\?" /, +check_completion("2\t", qr/246" /, "finish completion of one of multiple quoted table choices"); -# note: broken versions of libedit may leave us in a state where psql -# thinks there's an unclosed double quote, so that we have to use -# clear_line not clear_query here -clear_line(); +clear_query(); # check handling of mixed-case names -# note: broken versions of libedit want to backslash the closing quote; -# not much we can do about that check_completion( "select * from \"mi\t", - qr/"mixedName\\?" /, + qr/"mixedName" /, "complete a mixed-case name"); -# as above, must use clear_line not clear_query here -clear_line(); +clear_query(); # check case folding check_completion("select * from TAB\t", qr/tab1 /, "automatically fold case"); @@ -198,8 +190,7 @@ sub clear_line # differently, so just check that the replacement comes out correctly check_completion("\\DRD\t", qr/drds /, "complete \\DRD to \\drds"); -# broken versions of libedit require clear_line not clear_query here -clear_line(); +clear_query(); # check completion of a schema-qualified name check_completion("select * from pub\t", @@ -218,21 +209,21 @@ sub clear_line # check interpretation of referenced names check_completion( - "alter table tab1 drop constraint \t", + "alter table tab1 drop constraint t\t", qr/tab1_pkey /, "complete index name for referenced table"); clear_query(); check_completion( - "alter table TAB1 drop constraint \t", + "alter table TAB1 drop constraint t\t", qr/tab1_pkey /, "complete index name for referenced table, with downcasing"); clear_query(); check_completion( - "alter table public.\"tab1\" drop constraint \t", + "alter table public.\"tab1\" drop constraint t\t", qr/tab1_pkey /, "complete index name for referenced table, with schema and quoting"); @@ -261,18 +252,16 @@ sub clear_line qr|tab_comp_dir/af\a?ile|, "filename completion with multiple possibilities"); -# broken versions of libedit require clear_line not clear_query here +# here we are inside a string literal 'afile*', so must use clear_line(). clear_line(); # COPY requires quoting -# note: broken versions of libedit want to backslash the closing quote; -# not much we can do about that check_completion( "COPY foo FROM tab_comp_dir/some\t", - qr|'tab_comp_dir/somefile\\?' |, + qr|'tab_comp_dir/somefile' |, "quoted filename completion with one possibility"); -clear_line(); +clear_query(); check_completion( "COPY foo FROM tab_comp_dir/af\t", diff --git a/src/bin/psql/t/020_cancel.pl b/src/bin/psql/t/020_cancel.pl index 7a0c917e3edf8..154a24bca98c7 100644 --- a/src/bin/psql/t/020_cancel.pl +++ b/src/bin/psql/t/020_cancel.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -22,8 +22,13 @@ local %ENV = $node->_get_env(); my ($stdin, $stdout, $stderr); -my $h = IPC::Run::start([ 'psql', '-X', '-v', 'ON_ERROR_STOP=1' ], - \$stdin, \$stdout, \$stderr); +my $h = IPC::Run::start( + [ + 'psql', '--no-psqlrc', '--set' => 'ON_ERROR_STOP=1', + ], + '<' => \$stdin, + '>' => \$stdout, + '2>' => \$stderr); # Send sleep command and wait until the server has registered it $stdin = "select pg_sleep($PostgreSQL::Test::Utils::timeout_default);\n"; diff --git a/src/bin/psql/tab-complete.h b/src/bin/psql/tab-complete.h index 0adbd754f4d67..8d24e71f1bc62 100644 --- a/src/bin/psql/tab-complete.h +++ b/src/bin/psql/tab-complete.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/tab-complete.h */ diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.in.c similarity index 90% rename from src/bin/psql/tab-complete.c rename to src/bin/psql/tab-complete.in.c index 891face1b654b..2c0b4f28c14dd 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.in.c @@ -1,9 +1,16 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * - * src/bin/psql/tab-complete.c + * src/bin/psql/tab-complete.in.c + * + * Note: this will compile and work as-is if SWITCH_CONVERSION_APPLIED + * is not defined. However, the expected usage is that it's first run + * through gen_tabcomplete.pl, which will #define that symbol, fill in the + * tcpatterns[] array, and convert the else-if chain in match_previous_words() + * into a switch. See comments for match_previous_words() and the header + * comment in gen_tabcomplete.pl for more detail. */ /*---------------------------------------------------------------------- @@ -993,6 +1000,15 @@ static const SchemaQuery Query_for_trigger_of_table = { "SELECT datname FROM pg_catalog.pg_database "\ " WHERE datname LIKE '%s'" +#define Query_for_list_of_database_vars \ +"SELECT conf FROM ("\ +" SELECT setdatabase, pg_catalog.split_part(unnest(setconfig),'=',1) conf"\ +" FROM pg_db_role_setting "\ +" ) s, pg_database d "\ +" WHERE s.setdatabase = d.oid "\ +" AND conf LIKE '%s'"\ +" AND d.datname LIKE '%s'" + #define Query_for_list_of_tablespaces \ "SELECT spcname FROM pg_catalog.pg_tablespace "\ " WHERE spcname LIKE '%s'" @@ -1061,6 +1077,11 @@ Keywords_for_list_of_owner_roles, "PUBLIC" " FROM pg_catalog.pg_user_mappings "\ " WHERE usename LIKE '%s'" +#define Query_for_list_of_user_vars \ +" SELECT pg_catalog.split_part(pg_catalog.unnest(rolconfig),'=',1) "\ +" FROM pg_catalog.pg_roles "\ +" WHERE rolname LIKE '%s'" + #define Query_for_list_of_access_methods \ " SELECT amname "\ " FROM pg_catalog.pg_am "\ @@ -1195,6 +1216,20 @@ static const VersionedQuery Query_for_list_of_subscriptions[] = { {0, NULL} }; + /* Known command-starting keywords. */ +static const char *const sql_commands[] = { + "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER", + "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", + "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN", + "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD", "LOCK", + "MERGE INTO", "MOVE", "NOTIFY", "PREPARE", + "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", + "RESET", "REVOKE", "ROLLBACK", + "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START", + "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH", + NULL +}; + /* * This is a list of all "things" in Pgsql, which can show up after CREATE or * DROP; and there is also a query to get a list of them. @@ -1287,6 +1322,51 @@ static const pgsql_thing_t words_after_create[] = { {NULL} /* end of list */ }; +/* + * The tcpatterns[] table provides the initial pattern-match rule for each + * switch case in match_previous_words(). The contents of the table + * are constructed by gen_tabcomplete.pl. + */ + +/* Basic match rules appearing in tcpatterns[].kind */ +enum TCPatternKind +{ + Match, + MatchCS, + HeadMatch, + HeadMatchCS, + TailMatch, + TailMatchCS, +}; + +/* Things besides string literals that can appear in tcpatterns[].words */ +#define MatchAny NULL +#define MatchAnyExcept(pattern) ("!" pattern) +#define MatchAnyN "" + +/* One entry in tcpatterns[] */ +typedef struct +{ + int id; /* case label used in match_previous_words */ + enum TCPatternKind kind; /* match kind, see above */ + int nwords; /* length of words[] array */ + const char *const *words; /* array of match words */ +} TCPattern; + +/* Macro emitted by gen_tabcomplete.pl to fill a tcpatterns[] entry */ +#define TCPAT(id, kind, ...) \ + { (id), (kind), VA_ARGS_NARGS(__VA_ARGS__), \ + (const char * const []) { __VA_ARGS__ } } + +#ifdef SWITCH_CONVERSION_APPLIED + +static const TCPattern tcpatterns[] = +{ + /* Insert tab-completion pattern data here. */ +}; + +#endif /* SWITCH_CONVERSION_APPLIED */ + /* Storage parameters for CREATE TABLE and ALTER TABLE */ static const char *const table_storage_parameters[] = { "autovacuum_analyze_scale_factor", @@ -1302,6 +1382,7 @@ static const char *const table_storage_parameters[] = { "autovacuum_vacuum_cost_limit", "autovacuum_vacuum_insert_scale_factor", "autovacuum_vacuum_insert_threshold", + "autovacuum_vacuum_max_threshold", "autovacuum_vacuum_scale_factor", "autovacuum_vacuum_threshold", "fillfactor", @@ -1318,14 +1399,17 @@ static const char *const table_storage_parameters[] = { "toast.autovacuum_vacuum_cost_limit", "toast.autovacuum_vacuum_insert_scale_factor", "toast.autovacuum_vacuum_insert_threshold", + "toast.autovacuum_vacuum_max_threshold", "toast.autovacuum_vacuum_scale_factor", "toast.autovacuum_vacuum_threshold", "toast.log_autovacuum_min_duration", "toast.vacuum_index_cleanup", + "toast.vacuum_max_eager_freeze_failure_rate", "toast.vacuum_truncate", "toast_tuple_target", "user_catalog_table", "vacuum_index_cleanup", + "vacuum_max_eager_freeze_failure_rate", "vacuum_truncate", NULL }; @@ -1340,6 +1424,10 @@ static const char *const view_optional_parameters[] = { /* Forward declaration of functions */ static char **psql_completion(const char *text, int start, int end); +static char **match_previous_words(int pattern_id, + const char *text, int start, int end, + char **previous_words, + int previous_words_count); static char *create_command_generator(const char *text, int state); static char *drop_command_generator(const char *text, int state); static char *alter_command_generator(const char *text, int state); @@ -1446,11 +1534,9 @@ initialize_readline(void) * * For readability, callers should use the macros MatchAny and MatchAnyExcept * to invoke those two special cases for 'pattern'. (But '|' and '*' must - * just be written directly in patterns.) + * just be written directly in patterns.) There is also MatchAnyN, but that + * is supported only in Matches/MatchesCS and is not handled here. */ -#define MatchAny NULL -#define MatchAnyExcept(pattern) ("!" pattern) - static bool word_matches(const char *pattern, const char *word, @@ -1514,107 +1600,196 @@ word_matches(const char *pattern, } /* - * Implementation of TailMatches and TailMatchesCS macros: do the last N words - * in previous_words match the variadic arguments? + * Implementation of TailMatches and TailMatchesCS tests: do the last N words + * in previous_words match the pattern arguments? * * The array indexing might look backwards, but remember that * previous_words[0] contains the *last* word on the line, not the first. */ static bool -TailMatchesImpl(bool case_sensitive, - int previous_words_count, char **previous_words, - int narg,...) +TailMatchesArray(bool case_sensitive, + int previous_words_count, char **previous_words, + int narg, const char *const *args) { - va_list args; - if (previous_words_count < narg) return false; - va_start(args, narg); - for (int argno = 0; argno < narg; argno++) { - const char *arg = va_arg(args, const char *); + const char *arg = args[argno]; if (!word_matches(arg, previous_words[narg - argno - 1], case_sensitive)) - { - va_end(args); return false; - } } - va_end(args); - return true; } /* - * Implementation of Matches and MatchesCS macros: do all of the words - * in previous_words match the variadic arguments? + * As above, but the pattern is passed as a variadic argument list. */ static bool -MatchesImpl(bool case_sensitive, - int previous_words_count, char **previous_words, - int narg,...) +TailMatchesImpl(bool case_sensitive, + int previous_words_count, char **previous_words, + int narg,...) { + const char *argarray[64]; va_list args; - if (previous_words_count != narg) + Assert(narg <= lengthof(argarray)); + + if (previous_words_count < narg) return false; va_start(args, narg); + for (int argno = 0; argno < narg; argno++) + argarray[argno] = va_arg(args, const char *); + va_end(args); + + return TailMatchesArray(case_sensitive, + previous_words_count, previous_words, + narg, argarray); +} + +/* + * Implementation of HeadMatches and HeadMatchesCS tests: do the first N + * words in previous_words match the pattern arguments? + */ +static bool +HeadMatchesArray(bool case_sensitive, + int previous_words_count, char **previous_words, + int narg, const char *const *args) +{ + if (previous_words_count < narg) + return false; for (int argno = 0; argno < narg; argno++) { - const char *arg = va_arg(args, const char *); + const char *arg = args[argno]; - if (!word_matches(arg, previous_words[narg - argno - 1], + if (!word_matches(arg, previous_words[previous_words_count - argno - 1], case_sensitive)) - { - va_end(args); return false; - } } - va_end(args); - return true; } /* - * Implementation of HeadMatches and HeadMatchesCS macros: do the first N - * words in previous_words match the variadic arguments? + * As above, but the pattern is passed as a variadic argument list. */ static bool HeadMatchesImpl(bool case_sensitive, int previous_words_count, char **previous_words, int narg,...) { + const char *argarray[64]; va_list args; + Assert(narg <= lengthof(argarray)); + if (previous_words_count < narg) return false; va_start(args, narg); + for (int argno = 0; argno < narg; argno++) + argarray[argno] = va_arg(args, const char *); + va_end(args); + + return HeadMatchesArray(case_sensitive, + previous_words_count, previous_words, + narg, argarray); +} + +/* + * Implementation of Matches and MatchesCS tests: do all of the words + * in previous_words match the pattern arguments? + * + * This supports an additional kind of wildcard: MatchAnyN (represented as "") + * can match any number of words, including zero, in the middle of the list. + */ +static bool +MatchesArray(bool case_sensitive, + int previous_words_count, char **previous_words, + int narg, const char *const *args) +{ + int match_any_pos = -1; + + /* Even with MatchAnyN, there must be at least N-1 words */ + if (previous_words_count < narg - 1) + return false; + /* Check for MatchAnyN */ for (int argno = 0; argno < narg; argno++) { - const char *arg = va_arg(args, const char *); + const char *arg = args[argno]; - if (!word_matches(arg, previous_words[previous_words_count - argno - 1], - case_sensitive)) + if (arg != NULL && arg[0] == '\0') { - va_end(args); - return false; + match_any_pos = argno; + break; } } - va_end(args); + if (match_any_pos < 0) + { + /* Standard case without MatchAnyN */ + if (previous_words_count != narg) + return false; + + /* Either Head or Tail match will do for the rest */ + if (!HeadMatchesArray(case_sensitive, + previous_words_count, previous_words, + narg, args)) + return false; + } + else + { + /* Match against head */ + if (!HeadMatchesArray(case_sensitive, + previous_words_count, previous_words, + match_any_pos, args)) + return false; + + /* Match against tail */ + if (!TailMatchesArray(case_sensitive, + previous_words_count, previous_words, + narg - match_any_pos - 1, + args + match_any_pos + 1)) + return false; + } return true; } +/* + * As above, but the pattern is passed as a variadic argument list. + */ +static bool +MatchesImpl(bool case_sensitive, + int previous_words_count, char **previous_words, + int narg,...) +{ + const char *argarray[64]; + va_list args; + + Assert(narg <= lengthof(argarray)); + + /* Even with MatchAnyN, there must be at least N-1 words */ + if (previous_words_count < narg - 1) + return false; + + va_start(args, narg); + for (int argno = 0; argno < narg; argno++) + argarray[argno] = va_arg(args, const char *); + va_end(args); + + return MatchesArray(case_sensitive, + previous_words_count, previous_words, + narg, argarray); +} + /* * Check if the final character of 's' is 'c'. */ @@ -1696,25 +1871,11 @@ psql_completion(const char *text, int start, int end) HeadMatchesImpl(true, previous_words_count, previous_words, \ VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__) - /* Known command-starting keywords. */ - static const char *const sql_commands[] = { - "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER", - "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", - "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN", - "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD", "LOCK", - "MERGE INTO", "MOVE", "NOTIFY", "PREPARE", - "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", - "RESET", "REVOKE", "ROLLBACK", - "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START", - "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH", - NULL - }; - /* psql's backslash commands. */ static const char *const backslash_commands[] = { "\\a", - "\\bind", - "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy", + "\\bind", "\\bind_named", + "\\connect", "\\conninfo", "\\C", "\\cd", "\\close", "\\copy", "\\copyright", "\\crosstabview", "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp", "\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD", @@ -1724,17 +1885,18 @@ psql_completion(const char *text, int start, int end) "\\drds", "\\drg", "\\dRs", "\\dRp", "\\ds", "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy", "\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding", - "\\endif", "\\errverbose", "\\ev", - "\\f", - "\\g", "\\gdesc", "\\getenv", "\\gexec", "\\gset", "\\gx", + "\\endif", "\\endpipeline", "\\errverbose", "\\ev", + "\\f", "\\flush", "\\flushrequest", + "\\g", "\\gdesc", "\\getenv", "\\getresults", "\\gexec", "\\gset", "\\gx", "\\help", "\\html", "\\if", "\\include", "\\include_relative", "\\ir", "\\list", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink", "\\out", - "\\password", "\\print", "\\prompt", "\\pset", + "\\parse", "\\password", "\\print", "\\prompt", "\\pset", "\\qecho", "\\quit", "\\reset", - "\\s", "\\set", "\\setenv", "\\sf", "\\sv", + "\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf", + "\\startpipeline", "\\sv", "\\syncpipeline", "\\t", "\\T", "\\timing", "\\unset", "\\x", @@ -1796,6 +1958,196 @@ psql_completion(const char *text, int start, int end) else if (previous_words_count == 0) COMPLETE_WITH_LIST(sql_commands); + /* Else try completions based on matching patterns of previous words */ + else + { +#ifdef SWITCH_CONVERSION_APPLIED + /* + * If we have transformed match_previous_words into a switch, iterate + * through tcpatterns[] to see which pattern ids match. + * + * For now, we have to try the patterns in the order they are stored + * (matching the order of switch cases in match_previous_words), + * because some of the logic in match_previous_words assumes that + * previous matches have been eliminated. This is fairly + * unprincipled, and it is likely that there are undesirable as well + * as desirable interactions hidden in the order of the pattern + * checks. TODO: think about a better way to manage that. + */ + for (int tindx = 0; tindx < lengthof(tcpatterns); tindx++) + { + const TCPattern *tcpat = tcpatterns + tindx; + bool match = false; + + switch (tcpat->kind) + { + case Match: + match = MatchesArray(false, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + case MatchCS: + match = MatchesArray(true, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + case HeadMatch: + match = HeadMatchesArray(false, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + case HeadMatchCS: + match = HeadMatchesArray(true, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + case TailMatch: + match = TailMatchesArray(false, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + case TailMatchCS: + match = TailMatchesArray(true, + previous_words_count, + previous_words, + tcpat->nwords, tcpat->words); + break; + } + if (match) + { + matches = match_previous_words(tcpat->id, text, start, end, + previous_words, + previous_words_count); + if (matches != NULL) + break; + } + } +#else /* !SWITCH_CONVERSION_APPLIED */ + /* + * If gen_tabcomplete.pl hasn't been applied to this code, just let + * match_previous_words scan through all its patterns. + */ + matches = match_previous_words(0, text, start, end, + previous_words, + previous_words_count); +#endif /* SWITCH_CONVERSION_APPLIED */ + } + + /* + * Finally, we look through the list of "things", such as TABLE, INDEX and + * check if that was the previous word. If so, execute the query to get a + * list of them. + */ + if (matches == NULL && previous_words_count > 0) + { + const pgsql_thing_t *wac; + + for (wac = words_after_create; wac->name != NULL; wac++) + { + if (pg_strcasecmp(prev_wd, wac->name) == 0) + { + if (wac->query) + COMPLETE_WITH_QUERY_LIST(wac->query, + wac->keywords); + else if (wac->vquery) + COMPLETE_WITH_VERSIONED_QUERY_LIST(wac->vquery, + wac->keywords); + else if (wac->squery) + COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(wac->squery, + wac->keywords); + break; + } + } + } + + /* + * If we still don't have anything to match we have to fabricate some sort + * of default list. If we were to just return NULL, readline automatically + * attempts filename completion, and that's usually no good. + */ + if (matches == NULL) + { + COMPLETE_WITH_CONST(true, ""); + /* Also, prevent Readline from appending stuff to the non-match */ + rl_completion_append_character = '\0'; +#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE + rl_completion_suppress_quote = 1; +#endif + } + + /* free storage */ + free(previous_words); + free(words_buffer); + free(text_copy); + free(completion_ref_object); + completion_ref_object = NULL; + free(completion_ref_schema); + completion_ref_schema = NULL; + + /* Return our Grand List O' Matches */ + return matches; +} + +/* + * Subroutine to try matches based on previous_words. + * + * This can operate in one of two modes. As presented, the body of the + * function is a long if-else-if chain that sequentially tries each known + * match rule. That works, but some C compilers have trouble with such a long + * else-if chain, either taking extra time to compile or failing altogether. + * Therefore, we prefer to transform the else-if chain into a switch, and then + * each call of this function considers just one match rule (under control of + * a loop in psql_completion()). Compilers tend to be more ready to deal + * with many-arm switches than many-arm else-if chains. + * + * Each if-condition in this function must begin with a call of one of the + * functions Matches, HeadMatches, TailMatches, MatchesCS, HeadMatchesCS, or + * TailMatchesCS. The preprocessor gen_tabcomplete.pl strips out those + * calls and converts them into entries in tcpatterns[], which are evaluated + * by the calling loop in psql_completion(). Successful matches result in + * calls to this function with the appropriate pattern_id, causing just the + * corresponding switch case to be executed. + * + * If-conditions in this function can be more complex than a single *Matches + * function call in one of two ways (but not both!). They can be OR's + * of *Matches calls, such as + * else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) || + * Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny)) + * or they can be a *Matches call AND'ed with some other condition, e.g. + * else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && + * !ends_with(prev_wd, ',')) + * The former case is transformed into multiple tcpatterns[] entries and + * multiple case labels for the same bit of code. The latter case is + * transformed into a case label and a contained if-statement. + * + * This is split out of psql_completion() primarily to separate code that + * gen_tabcomplete.pl should process from code that it should not, although + * doing so also helps to avoid extra indentation of this code. + * + * Returns a matches list, or NULL if no match. + */ +static char ** +match_previous_words(int pattern_id, + const char *text, int start, int end, + char **previous_words, int previous_words_count) +{ + /* This is the variable we'll return. */ + char **matches = NULL; + + /* Dummy statement, allowing all the match rules to look like "else if" */ + if (0) + { + /* skip */ + } + + /* gen_tabcomplete.pl begins special processing here */ + /* BEGIN GEN_TABCOMPLETE */ + /* CREATE */ /* complete with something you can create */ else if (TailMatches("CREATE")) @@ -1894,9 +2246,10 @@ psql_completion(const char *text, int start, int end) /* ALTER PUBLICATION ADD */ else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD")) COMPLETE_WITH("TABLES IN SCHEMA", "TABLE"); - else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") || - (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") && - ends_with(prev_wd, ','))) + else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables); + else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") && + ends_with(prev_wd, ',')) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables); /* @@ -1906,9 +2259,9 @@ psql_completion(const char *text, int start, int end) * "ALTER PUBLICATION ADD TABLE WHERE (" - complete with * table attributes */ - else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE")) + else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE")) COMPLETE_WITH("("); - else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE", "(")) + else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(")) COMPLETE_WITH_ATTR(prev3_wd); else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") && !TailMatches("WHERE", "(*)")) @@ -1926,44 +2279,42 @@ psql_completion(const char *text, int start, int end) " AND nspname NOT LIKE E'pg\\\\_%%'", "CURRENT_SCHEMA"); /* ALTER PUBLICATION SET ( */ - else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("SET", "(")) - COMPLETE_WITH("publish", "publish_via_partition_root"); + else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "SET", "(")) + COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root"); /* ALTER SUBSCRIPTION */ else if (Matches("ALTER", "SUBSCRIPTION", MatchAny)) COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO", "RENAME TO", "REFRESH PUBLICATION", "SET", "SKIP (", "ADD PUBLICATION", "DROP PUBLICATION"); /* ALTER SUBSCRIPTION REFRESH PUBLICATION */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && - TailMatches("REFRESH", "PUBLICATION")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION")) COMPLETE_WITH("WITH ("); /* ALTER SUBSCRIPTION REFRESH PUBLICATION WITH ( */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && - TailMatches("REFRESH", "PUBLICATION", "WITH", "(")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION", "WITH", "(")) COMPLETE_WITH("copy_data"); /* ALTER SUBSCRIPTION SET */ else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET")) COMPLETE_WITH("(", "PUBLICATION"); /* ALTER SUBSCRIPTION SET ( */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "(")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "(")) COMPLETE_WITH("binary", "disable_on_error", "failover", "origin", "password_required", "run_as_owner", "slot_name", "streaming", "synchronous_commit", "two_phase"); /* ALTER SUBSCRIPTION SKIP ( */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SKIP", "(")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SKIP", "(")) COMPLETE_WITH("lsn"); /* ALTER SUBSCRIPTION SET PUBLICATION */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "PUBLICATION")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "PUBLICATION")) { /* complete with nothing here as this refers to remote publications */ } /* ALTER SUBSCRIPTION ADD|DROP|SET PUBLICATION */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && - TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny)) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, + "ADD|DROP|SET", "PUBLICATION", MatchAny)) COMPLETE_WITH("WITH ("); /* ALTER SUBSCRIPTION ADD|DROP|SET PUBLICATION WITH ( */ - else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && - TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "(")) + else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, + "ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "(")) COMPLETE_WITH("copy_data", "refresh"); /* ALTER SCHEMA */ @@ -1984,6 +2335,13 @@ psql_completion(const char *text, int start, int end) "IS_TEMPLATE", "ALLOW_CONNECTIONS", "CONNECTION LIMIT"); + /* ALTER DATABASE RESET */ + else if (Matches("ALTER", "DATABASE", MatchAny, "RESET")) + { + set_completion_reference(prev2_wd); + COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_database_vars, "ALL"); + } + /* ALTER DATABASE SET TABLESPACE */ else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE")) COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); @@ -2135,6 +2493,10 @@ psql_completion(const char *text, int start, int end) "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER", "VALID UNTIL", "WITH"); + /* ALTER USER,ROLE RESET */ + else if (Matches("ALTER", "USER|ROLE", MatchAny, "RESET")) + COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_user_vars, "ALL"); + /* ALTER USER,ROLE WITH */ else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH")) /* Similar to the above, but don't complete "WITH" again. */ @@ -2177,6 +2539,12 @@ psql_completion(const char *text, int start, int end) else if (Matches("ALTER", "DOMAIN", MatchAny)) COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT"); + /* ALTER DOMAIN ADD */ + else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD")) + COMPLETE_WITH("CONSTRAINT", "NOT NULL", "CHECK ("); + /* ALTER DOMAIN ADD CONSTRAINT */ + else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD", "CONSTRAINT", MatchAny)) + COMPLETE_WITH("NOT NULL", "CHECK ("); /* ALTER DOMAIN DROP */ else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP")) COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL"); @@ -2353,7 +2721,6 @@ psql_completion(const char *text, int start, int end) "OWNER TO", "SET", "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION", "DETACH PARTITION", "FORCE ROW LEVEL SECURITY", - "SPLIT PARTITION", "MERGE PARTITIONS (", "OF", "NOT OF"); /* ALTER TABLE xxx ADD */ else if (Matches("ALTER", "TABLE", MatchAny, "ADD")) @@ -2364,8 +2731,7 @@ psql_completion(const char *text, int start, int end) } /* ALTER TABLE xxx ADD [COLUMN] yyy */ else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) || - (Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAny) && - !Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN"))) + Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN"))) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes); /* ALTER TABLE xxx ADD CONSTRAINT yyy */ else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny)) @@ -2610,10 +2976,10 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("FROM (", "IN (", "WITH ("); /* - * If we have ALTER TABLE DETACH|SPLIT PARTITION, provide a list of + * If we have ALTER TABLE DETACH PARTITION, provide a list of * partitions of . */ - else if (Matches("ALTER", "TABLE", MatchAny, "DETACH|SPLIT", "PARTITION")) + else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION")) { set_completion_reference(prev3_wd); COMPLETE_WITH_SCHEMA_QUERY(Query_for_partition_of_table); @@ -2621,19 +2987,6 @@ psql_completion(const char *text, int start, int end) else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny)) COMPLETE_WITH("CONCURRENTLY", "FINALIZE"); - /* ALTER TABLE SPLIT PARTITION */ - else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny)) - COMPLETE_WITH("INTO ( PARTITION"); - - /* ALTER TABLE MERGE PARTITIONS ( */ - else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "(")) - { - set_completion_reference(prev4_wd); - COMPLETE_WITH_SCHEMA_QUERY(Query_for_partition_of_table); - } - else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "(*)")) - COMPLETE_WITH("INTO"); - /* ALTER TABLE OF */ else if (Matches("ALTER", "TABLE", MatchAny, "OF")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes); @@ -2675,6 +3028,9 @@ psql_completion(const char *text, int start, int end) /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */ else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny)) COMPLETE_WITH("TO"); + /* ALTER TYPE xxx RENAME ATTRIBUTE yyy TO zzz */ + else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny, "TO", MatchAny)) + COMPLETE_WITH("CASCADE", "RESTRICT"); /* * If we have ALTER TYPE ALTER/DROP/RENAME ATTRIBUTE, provide list @@ -2682,9 +3038,21 @@ psql_completion(const char *text, int start, int end) */ else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE")) COMPLETE_WITH_ATTR(prev3_wd); + /* complete ALTER TYPE ADD ATTRIBUTE with list of types */ + else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes); + /* complete ALTER TYPE ADD ATTRIBUTE with CASCADE/RESTRICT */ + else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny, MatchAny)) + COMPLETE_WITH("CASCADE", "RESTRICT"); + /* complete ALTER TYPE DROP ATTRIBUTE with CASCADE/RESTRICT */ + else if (Matches("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", MatchAny)) + COMPLETE_WITH("CASCADE", "RESTRICT"); /* ALTER TYPE ALTER ATTRIBUTE */ else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny)) COMPLETE_WITH("TYPE"); + /* ALTER TYPE ALTER ATTRIBUTE TYPE */ + else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny, "TYPE", MatchAny)) + COMPLETE_WITH("CASCADE", "RESTRICT"); /* complete ALTER TYPE RENAME VALUE with list of enum values */ else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE")) COMPLETE_WITH_ENUM_VALUE(prev3_wd); @@ -2707,12 +3075,15 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* - * ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ] - * ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ] + * ANALYZE [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ] + * ANALYZE [ VERBOSE ] [ [ ONLY ] table_and_columns [, ...] ] */ else if (Matches("ANALYZE")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables, - "VERBOSE"); + "(", "VERBOSE", "ONLY"); + else if (Matches("ANALYZE", "VERBOSE")) + COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables, + "ONLY"); else if (HeadMatches("ANALYZE", "(*") && !HeadMatches("ANALYZE", "(*)")) { @@ -2726,7 +3097,7 @@ psql_completion(const char *text, int start, int end) else if (TailMatches("VERBOSE|SKIP_LOCKED")) COMPLETE_WITH("ON", "OFF"); } - else if (HeadMatches("ANALYZE") && TailMatches("(")) + else if (Matches("ANALYZE", MatchAnyN, "(")) /* "ANALYZE (" should be caught above, so assume we want columns */ COMPLETE_WITH_ATTR(prev2_wd); else if (HeadMatches("ANALYZE")) @@ -2887,7 +3258,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables, "("); /* Complete COPY ( with legal query commands */ else if (Matches("COPY|\\copy", "(")) - COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "WITH"); + COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH"); /* Complete COPY */ else if (Matches("COPY|\\copy", MatchAny)) COMPLETE_WITH("FROM", "TO"); @@ -2918,7 +3289,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL", "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE", "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT", - "ON_ERROR", "LOG_VERBOSITY"); + "ON_ERROR", "LOG_VERBOSITY", "REJECT_LIMIT"); /* Complete COPY FROM|TO filename WITH (FORMAT */ else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT")) @@ -2930,7 +3301,7 @@ psql_completion(const char *text, int start, int end) /* Complete COPY FROM filename WITH (LOG_VERBOSITY */ else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "LOG_VERBOSITY")) - COMPLETE_WITH("default", "verbose"); + COMPLETE_WITH("silent", "default", "verbose"); /* Complete COPY FROM WITH () */ else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny)) @@ -3178,11 +3549,11 @@ psql_completion(const char *text, int start, int end) * "CREATE PUBLICATION FOR TABLE WHERE (" - complete with * table attributes */ - else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE")) + else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE")) COMPLETE_WITH("("); - else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "(")) + else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(")) COMPLETE_WITH_ATTR(prev3_wd); - else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "(*)")) + else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)")) COMPLETE_WITH(" WITH ("); /* @@ -3195,8 +3566,8 @@ psql_completion(const char *text, int start, int end) else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ','))) COMPLETE_WITH("WITH ("); /* Complete "CREATE PUBLICATION [...] WITH" */ - else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("WITH", "(")) - COMPLETE_WITH("publish", "publish_via_partition_root"); + else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "(")) + COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root"); /* CREATE RULE */ /* Complete "CREATE [ OR REPLACE ] RULE " with "AS ON" */ @@ -3259,23 +3630,16 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("ndistinct", "dependencies", "mcv"); else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)")) COMPLETE_WITH("ON"); - else if (HeadMatches("CREATE", "STATISTICS", MatchAny) && - TailMatches("FROM")) + else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables); /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */ /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */ else if (TailMatches("CREATE", "TEMP|TEMPORARY")) COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW"); - /* Complete "CREATE UNLOGGED" with TABLE, SEQUENCE or MATVIEW */ + /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */ else if (TailMatches("CREATE", "UNLOGGED")) - { - /* but not MATVIEW in CREATE SCHEMA */ - if (HeadMatches("CREATE", "SCHEMA")) - COMPLETE_WITH("TABLE", "SEQUENCE"); - else - COMPLETE_WITH("TABLE", "SEQUENCE", "MATERIALIZED VIEW"); - } + COMPLETE_WITH("TABLE", "SEQUENCE"); /* Complete PARTITION BY with RANGE ( or LIST ( or ... */ else if (TailMatches("PARTITION", "BY")) COMPLETE_WITH("RANGE (", "LIST (", "HASH ("); @@ -3300,11 +3664,12 @@ psql_completion(const char *text, int start, int end) TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS")) COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH"); /* Complete CREATE TABLE name (...) with supported options */ - else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)") || - TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)")) + else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)")) COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH ("); + else if (TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)")) + COMPLETE_WITH("AS", "INHERITS (", "USING", "TABLESPACE", "WITH ("); else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)")) - COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", + COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING", "TABLESPACE", "WITH ("); /* Complete CREATE TABLE (...) USING with table access methods */ else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") || @@ -3358,10 +3723,10 @@ psql_completion(const char *text, int start, int end) { /* complete with nothing here as this refers to remote publications */ } - else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("PUBLICATION", MatchAny)) + else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny)) COMPLETE_WITH("WITH ("); /* Complete "CREATE SUBSCRIPTION ... WITH ( " */ - else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("WITH", "(")) + else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "(")) COMPLETE_WITH("binary", "connect", "copy_data", "create_slot", "disable_on_error", "enabled", "failover", "origin", "password_required", "run_as_owner", "slot_name", @@ -3415,9 +3780,10 @@ psql_completion(const char *text, int start, int end) else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") || TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views); - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("ON", MatchAny)) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "ON", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "ON", MatchAny)) { if (pset.sversion >= 110000) COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY", @@ -3426,76 +3792,108 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY", "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - (TailMatches("DEFERRABLE") || TailMatches("INITIALLY", "IMMEDIATE|DEFERRED"))) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "DEFERRABLE") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "DEFERRABLE") || + Matches("CREATE", "TRIGGER", MatchAnyN, + "INITIALLY", "IMMEDIATE|DEFERRED") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "INITIALLY", "IMMEDIATE|DEFERRED")) { if (pset.sversion >= 110000) COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION"); else COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("REFERENCING")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING")) COMPLETE_WITH("OLD TABLE", "NEW TABLE"); - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("OLD|NEW", "TABLE")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "OLD|NEW", "TABLE") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "OLD|NEW", "TABLE")) COMPLETE_WITH("AS"); - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - (TailMatches("REFERENCING", "OLD", "TABLE", "AS", MatchAny) || - TailMatches("REFERENCING", "OLD", "TABLE", MatchAny))) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD", "TABLE", "AS", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD", "TABLE", "AS", MatchAny) || + Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD", "TABLE", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD", "TABLE", MatchAny)) { if (pset.sversion >= 110000) COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION"); else COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - (TailMatches("REFERENCING", "NEW", "TABLE", "AS", MatchAny) || - TailMatches("REFERENCING", "NEW", "TABLE", MatchAny))) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "NEW", "TABLE", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "NEW", "TABLE", MatchAny)) { if (pset.sversion >= 110000) COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION"); else COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - (TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || - TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || - TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) || - TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) || + Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) || + Matches("CREATE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)) { if (pset.sversion >= 110000) COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION"); else COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("FOR")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "FOR") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "FOR")) COMPLETE_WITH("EACH", "ROW", "STATEMENT"); - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("FOR", "EACH")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "FOR", "EACH") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "FOR", "EACH")) COMPLETE_WITH("ROW", "STATEMENT"); - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - (TailMatches("FOR", "EACH", "ROW|STATEMENT") || - TailMatches("FOR", "ROW|STATEMENT"))) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "FOR", "EACH", "ROW|STATEMENT") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "FOR", "EACH", "ROW|STATEMENT") || + Matches("CREATE", "TRIGGER", MatchAnyN, + "FOR", "ROW|STATEMENT") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "FOR", "ROW|STATEMENT")) { if (pset.sversion >= 110000) COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION"); else COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("WHEN", "(*)")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "WHEN", "(*)") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "WHEN", "(*)")) { if (pset.sversion >= 110000) COMPLETE_WITH("EXECUTE FUNCTION"); @@ -3507,18 +3905,20 @@ psql_completion(const char *text, int start, int end) * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with * PROCEDURE|FUNCTION. */ - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("EXECUTE")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "EXECUTE") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "EXECUTE")) { if (pset.sversion >= 110000) COMPLETE_WITH("FUNCTION"); else COMPLETE_WITH("PROCEDURE"); } - else if ((HeadMatches("CREATE", "TRIGGER") || - HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) && - TailMatches("EXECUTE", "FUNCTION|PROCEDURE")) + else if (Matches("CREATE", "TRIGGER", MatchAnyN, + "EXECUTE", "FUNCTION|PROCEDURE") || + Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN, + "EXECUTE", "FUNCTION|PROCEDURE")) COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions); /* CREATE ROLE,USER,GROUP */ @@ -3621,11 +4021,26 @@ psql_completion(const char *text, int start, int end) /* CREATE MATERIALIZED VIEW */ else if (Matches("CREATE", "MATERIALIZED")) COMPLETE_WITH("VIEW"); - /* Complete CREATE MATERIALIZED VIEW with AS */ + /* Complete CREATE MATERIALIZED VIEW with AS or USING */ else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny)) + COMPLETE_WITH("AS", "USING"); + + /* + * Complete CREATE MATERIALIZED VIEW USING with list of access + * methods + */ + else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING")) + COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods); + /* Complete CREATE MATERIALIZED VIEW USING with AS */ + else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny)) COMPLETE_WITH("AS"); - /* Complete "CREATE MATERIALIZED VIEW AS with "SELECT" */ - else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS")) + + /* + * Complete CREATE MATERIALIZED VIEW [USING ] AS + * with "SELECT" + */ + else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") || + Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS")) COMPLETE_WITH("SELECT"); /* CREATE EVENT TRIGGER */ @@ -3651,16 +4066,14 @@ psql_completion(const char *text, int start, int end) else COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE"); } - else if (HeadMatches("CREATE", "EVENT", "TRIGGER") && - TailMatches("WHEN|AND", MatchAny, "IN", "(*)")) + else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)")) { if (pset.sversion >= 110000) COMPLETE_WITH("EXECUTE FUNCTION"); else COMPLETE_WITH("EXECUTE PROCEDURE"); } - else if (HeadMatches("CREATE", "EVENT", "TRIGGER") && - TailMatches("EXECUTE", "FUNCTION|PROCEDURE")) + else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE")) COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions); /* DEALLOCATE */ @@ -3685,27 +4098,27 @@ psql_completion(const char *text, int start, int end) * provides, like the syntax of DECLARE command in the documentation * indicates. */ - else if (HeadMatches("DECLARE") && TailMatches("BINARY")) + else if (Matches("DECLARE", MatchAnyN, "BINARY")) COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR"); - else if (HeadMatches("DECLARE") && TailMatches("ASENSITIVE|INSENSITIVE")) + else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE")) COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR"); - else if (HeadMatches("DECLARE") && TailMatches("SCROLL")) + else if (Matches("DECLARE", MatchAnyN, "SCROLL")) COMPLETE_WITH("CURSOR"); /* Complete DECLARE ... [options] NO with SCROLL */ - else if (HeadMatches("DECLARE") && TailMatches("NO")) + else if (Matches("DECLARE", MatchAnyN, "NO")) COMPLETE_WITH("SCROLL"); /* * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and * FOR */ - else if (HeadMatches("DECLARE") && TailMatches("CURSOR")) + else if (Matches("DECLARE", MatchAnyN, "CURSOR")) COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR"); /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */ - else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT")) + else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT")) COMPLETE_WITH("HOLD"); /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */ - else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT", "HOLD")) + else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD")) COMPLETE_WITH("FOR"); /* DELETE --- can be inside EXPLAIN, RULE, etc */ @@ -3734,13 +4147,14 @@ psql_completion(const char *text, int start, int end) "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW", MatchAny) || Matches("DROP", "ACCESS", "METHOD", MatchAny) || - (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) && - ends_with(prev_wd, ')')) || Matches("DROP", "EVENT", "TRIGGER", MatchAny) || Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) || Matches("DROP", "FOREIGN", "TABLE", MatchAny) || Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny)) COMPLETE_WITH("CASCADE", "RESTRICT"); + else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) && + ends_with(prev_wd, ')')) + COMPLETE_WITH("CASCADE", "RESTRICT"); /* help completing some of the variants */ else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny)) @@ -3930,8 +4344,7 @@ psql_completion(const char *text, int start, int end) "FROM", "IN"); /* Complete FETCH "FROM" or "IN" with a list of cursors */ - else if (HeadMatches("FETCH|MOVE") && - TailMatches("FROM|IN")) + else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN")) COMPLETE_WITH_QUERY(Query_for_list_of_cursors); /* FOREIGN DATA WRAPPER */ @@ -3940,8 +4353,7 @@ psql_completion(const char *text, int start, int end) !TailMatches("CREATE", MatchAny, MatchAny, MatchAny)) COMPLETE_WITH_QUERY(Query_for_list_of_fdws); /* applies in CREATE SERVER */ - else if (TailMatches("FOREIGN", "DATA", "WRAPPER", MatchAny) && - HeadMatches("CREATE", "SERVER")) + else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny)) COMPLETE_WITH("OPTIONS"); /* FOREIGN TABLE */ @@ -4052,7 +4464,7 @@ psql_completion(const char *text, int start, int end) * objects supported. */ if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES")) - COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS"); + COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS"); else COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_grantables, "ALL FUNCTIONS IN SCHEMA", @@ -4128,44 +4540,43 @@ psql_completion(const char *text, int start, int end) * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC, * CURRENT_ROLE, CURRENT_USER, or SESSION_USER. */ - else if ((HeadMatches("GRANT") && TailMatches("TO")) || - (HeadMatches("REVOKE") && TailMatches("FROM"))) + else if (Matches("GRANT", MatchAnyN, "TO") || + Matches("REVOKE", MatchAnyN, "FROM")) COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles, Keywords_for_list_of_grant_roles); /* * Offer grant options after that. */ - else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny)) + else if (Matches("GRANT", MatchAnyN, "TO", MatchAny)) COMPLETE_WITH("WITH ADMIN", "WITH INHERIT", "WITH SET", "WITH GRANT OPTION", "GRANTED BY"); - else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH")) + else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH")) COMPLETE_WITH("ADMIN", "INHERIT", "SET", "GRANT OPTION"); - else if (HeadMatches("GRANT") && - (TailMatches("TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))) + else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET")) COMPLETE_WITH("OPTION", "TRUE", "FALSE"); - else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION")) + else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION")) COMPLETE_WITH("GRANTED BY"); - else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY")) + else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY")) COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles, Keywords_for_list_of_grant_roles); /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */ - else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO|FROM")) + else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM")) COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles, Keywords_for_list_of_grant_roles); /* Offer WITH GRANT OPTION after that */ - else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO", MatchAny)) + else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny)) COMPLETE_WITH("WITH GRANT OPTION"); /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */ - else if (HeadMatches("GRANT") && TailMatches("ON", MatchAny, MatchAny)) + else if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny)) COMPLETE_WITH("TO"); - else if (HeadMatches("REVOKE") && TailMatches("ON", MatchAny, MatchAny)) + else if (Matches("REVOKE", MatchAnyN, "ON", MatchAny, MatchAny)) COMPLETE_WITH("FROM"); /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */ @@ -4280,7 +4691,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("IN", "NOWAIT"); /* Complete LOCK [TABLE] [ONLY]
IN with a lock mode */ - else if (HeadMatches("LOCK") && TailMatches("IN")) + else if (Matches("LOCK", MatchAnyN, "IN")) COMPLETE_WITH("ACCESS SHARE MODE", "ROW SHARE MODE", "ROW EXCLUSIVE MODE", "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", @@ -4291,16 +4702,16 @@ psql_completion(const char *text, int start, int end) * Complete LOCK [TABLE][ONLY]
IN ACCESS|ROW with rest of lock * mode */ - else if (HeadMatches("LOCK") && TailMatches("IN", "ACCESS|ROW")) + else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW")) COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE"); /* Complete LOCK [TABLE] [ONLY]
IN SHARE with rest of lock mode */ - else if (HeadMatches("LOCK") && TailMatches("IN", "SHARE")) + else if (Matches("LOCK", MatchAnyN, "IN", "SHARE")) COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE", "UPDATE EXCLUSIVE MODE"); /* Complete LOCK [TABLE] [ONLY]
[IN lockmode MODE] with "NOWAIT" */ - else if (HeadMatches("LOCK") && TailMatches("MODE")) + else if (Matches("LOCK", MatchAnyN, "MODE")) COMPLETE_WITH("NOWAIT"); /* MERGE --- can be inside EXPLAIN */ @@ -4531,7 +4942,9 @@ psql_completion(const char *text, int start, int end) /* SET, RESET, SHOW */ /* Complete with a variable name */ - else if (TailMatches("SET|RESET") && !TailMatches("UPDATE", MatchAny, "SET")) + else if (TailMatches("SET|RESET") && + !TailMatches("UPDATE", MatchAny, "SET") && + !TailMatches("ALTER", "DATABASE", MatchAny, "RESET")) COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars, "CONSTRAINTS", "TRANSACTION", @@ -4605,9 +5018,7 @@ psql_completion(const char *text, int start, int end) * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET * */ - else if (HeadMatches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") && - TailMatches("SET", MatchAny) && - !TailMatches("SCHEMA")) + else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA"))) COMPLETE_WITH("FROM CURRENT", "TO"); /* @@ -4683,13 +5094,13 @@ psql_completion(const char *text, int start, int end) else if (Matches("TRUNCATE", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables, "ONLY"); - else if (HeadMatches("TRUNCATE") && TailMatches("ONLY")) + else if (Matches("TRUNCATE", MatchAnyN, "ONLY")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_truncatables); else if (Matches("TRUNCATE", MatchAny) || Matches("TRUNCATE", "TABLE|ONLY", MatchAny) || Matches("TRUNCATE", "TABLE", "ONLY", MatchAny)) COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT"); - else if (HeadMatches("TRUNCATE") && TailMatches("IDENTITY")) + else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY")) COMPLETE_WITH("CASCADE", "RESTRICT"); /* UNLISTEN */ @@ -4727,30 +5138,35 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("OPTIONS"); /* - * VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ] - * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ] + * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ] + * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ] */ else if (Matches("VACUUM")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables, + "(", "FULL", "FREEZE", + "VERBOSE", "ANALYZE", - "VERBOSE"); + "ONLY"); else if (Matches("VACUUM", "FULL")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables, "FREEZE", + "VERBOSE", "ANALYZE", - "VERBOSE"); - else if (Matches("VACUUM", "FREEZE") || - Matches("VACUUM", "FULL", "FREEZE")) + "ONLY"); + else if (Matches("VACUUM", MatchAnyN, "FREEZE")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables, "VERBOSE", - "ANALYZE"); - else if (Matches("VACUUM", "VERBOSE") || - Matches("VACUUM", "FULL|FREEZE", "VERBOSE") || - Matches("VACUUM", "FULL", "FREEZE", "VERBOSE")) + "ANALYZE", + "ONLY"); + else if (Matches("VACUUM", MatchAnyN, "VERBOSE")) COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables, - "ANALYZE"); + "ANALYZE", + "ONLY"); + else if (Matches("VACUUM", MatchAnyN, "ANALYZE")) + COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables, + "ONLY"); else if (HeadMatches("VACUUM", "(*") && !HeadMatches("VACUUM", "(*)")) { @@ -4770,7 +5186,7 @@ psql_completion(const char *text, int start, int end) else if (TailMatches("INDEX_CLEANUP")) COMPLETE_WITH("AUTO", "ON", "OFF"); } - else if (HeadMatches("VACUUM") && TailMatches("(")) + else if (Matches("VACUUM", MatchAnyN, "(")) /* "VACUUM (" should be caught above, so assume we want columns */ COMPLETE_WITH_ATTR(prev2_wd); else if (HeadMatches("VACUUM")) @@ -4797,7 +5213,23 @@ psql_completion(const char *text, int start, int end) /* ... JOIN ... */ else if (TailMatches("JOIN")) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables); + COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_selectables, "LATERAL"); + else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny)) + COMPLETE_WITH("ON", "USING ("); + else if (TailMatches("JOIN", MatchAny, MatchAny) && + !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING")) + COMPLETE_WITH("ON", "USING ("); + else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) && + !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING")) + COMPLETE_WITH("ON", "USING ("); + else if (TailMatches("JOIN", MatchAny, "USING") || + TailMatches("JOIN", MatchAny, MatchAny, "USING") || + TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING")) + COMPLETE_WITH("("); + else if (TailMatches("JOIN", MatchAny, "USING", "(")) + COMPLETE_WITH_ATTR(prev3_wd); + else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "(")) + COMPLETE_WITH_ATTR(prev4_wd); /* ... AT [ LOCAL | TIME ZONE ] ... */ else if (TailMatches("AT")) @@ -5024,58 +5456,9 @@ psql_completion(const char *text, int start, int end) matches = rl_completion_matches(text, complete_from_files); } - /* - * Finally, we look through the list of "things", such as TABLE, INDEX and - * check if that was the previous word. If so, execute the query to get a - * list of them. - */ - else - { - const pgsql_thing_t *wac; + /* gen_tabcomplete.pl ends special processing here */ + /* END GEN_TABCOMPLETE */ - for (wac = words_after_create; wac->name != NULL; wac++) - { - if (pg_strcasecmp(prev_wd, wac->name) == 0) - { - if (wac->query) - COMPLETE_WITH_QUERY_LIST(wac->query, - wac->keywords); - else if (wac->vquery) - COMPLETE_WITH_VERSIONED_QUERY_LIST(wac->vquery, - wac->keywords); - else if (wac->squery) - COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(wac->squery, - wac->keywords); - break; - } - } - } - - /* - * If we still don't have anything to match we have to fabricate some sort - * of default list. If we were to just return NULL, readline automatically - * attempts filename completion, and that's usually no good. - */ - if (matches == NULL) - { - COMPLETE_WITH_CONST(true, ""); - /* Also, prevent Readline from appending stuff to the non-match */ - rl_completion_append_character = '\0'; -#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE - rl_completion_suppress_quote = 1; -#endif - } - - /* free storage */ - free(previous_words); - free(words_buffer); - free(text_copy); - free(completion_ref_object); - completion_ref_object = NULL; - free(completion_ref_schema); - completion_ref_schema = NULL; - - /* Return our Grand List O' Matches */ return matches; } diff --git a/src/bin/psql/variables.c b/src/bin/psql/variables.c index 56d70f3a1091e..6b64302ebca86 100644 --- a/src/bin/psql/variables.c +++ b/src/bin/psql/variables.c @@ -1,12 +1,14 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/bin/psql/variables.c */ #include "postgres_fe.h" +#include + #include "common.h" #include "common/logging.h" #include "variables.h" @@ -179,6 +181,74 @@ ParseVariableNum(const char *value, const char *name, int *result) } } +/* + * Try to interpret "value" as a double value, and if successful store it in + * *result. If unsuccessful, *result isn't clobbered. "name" is the variable + * which is being assigned, the value of which is only used to produce a good + * error message. Pass NULL as the name to suppress the error message. The + * value must be within the range [min,max] in order to be considered valid. + * + * Returns true, with *result containing the interpreted value, if "value" is + * syntactically valid, else false (with *result unchanged). + */ +bool +ParseVariableDouble(const char *value, const char *name, double *result, double min, double max) +{ + char *end; + double dblval; + + /* + * Empty-string input has historically been treated differently by strtod + * on various platforms, so handle that by specifically checking for it. + */ + if ((value == NULL) || (*value == '\0')) + { + if (name) + pg_log_error("invalid input syntax for variable \"%s\"", name); + return false; + } + + errno = 0; + dblval = strtod(value, &end); + if (errno == 0 && *end == '\0' && end != value) + { + if (dblval < min) + { + if (name) + pg_log_error("invalid value \"%s\" for variable \"%s\": must be greater than %.2f", + value, name, min); + return false; + } + else if (dblval > max) + { + if (name) + pg_log_error("invalid value \"%s\" for variable \"%s\": must be less than %.2f", + value, name, max); + } + *result = dblval; + return true; + } + + /* + * Cater for platforms which treat values which aren't zero, but that are + * too close to zero to have full precision, by checking for zero or real + * out-of-range values. + */ + else if ((errno == ERANGE) && + (dblval == 0.0 || dblval >= HUGE_VAL || dblval <= -HUGE_VAL)) + { + if (name) + pg_log_error("value \"%s\" is out of range for variable \"%s\"", value, name); + return false; + } + else + { + if (name) + pg_log_error("invalid value \"%s\" for variable \"%s\"", value, name); + return false; + } +} + /* * Print values of all variables. */ diff --git a/src/bin/psql/variables.h b/src/bin/psql/variables.h index dca4f06dbbbdc..df23ccb987d72 100644 --- a/src/bin/psql/variables.h +++ b/src/bin/psql/variables.h @@ -1,7 +1,7 @@ /* * psql - the PostgreSQL interactive terminal * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * This implements a sort of variable repository. One could also think of it * as a cheap version of an associative array. Each variable has a string @@ -81,6 +81,9 @@ bool ParseVariableBool(const char *value, const char *name, bool ParseVariableNum(const char *value, const char *name, int *result); +bool ParseVariableDouble(const char *value, const char *name, + double *result, double min, double max); + void PrintVariables(VariableSpace space); bool SetVariable(VariableSpace space, const char *name, const char *value); diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile index 9633c99136880..f6b4d40810b45 100644 --- a/src/bin/scripts/Makefile +++ b/src/bin/scripts/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/bin/scripts # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/bin/scripts/Makefile diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c index 3503a3bb5840f..a0aa950b784e1 100644 --- a/src/bin/scripts/clusterdb.c +++ b/src/bin/scripts/clusterdb.c @@ -2,7 +2,7 @@ * * clusterdb * - * Portions Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2002-2025, PostgreSQL Global Development Group * * src/bin/scripts/clusterdb.c * @@ -16,7 +16,6 @@ #include "fe_utils/option_utils.h" #include "fe_utils/query_utils.h" #include "fe_utils/simple_list.h" -#include "fe_utils/string_utils.h" static void cluster_one_database(const ConnParams *cparams, const char *table, diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c index d16381eda903c..7b8f7d4c52661 100644 --- a/src/bin/scripts/common.c +++ b/src/bin/scripts/common.c @@ -4,7 +4,7 @@ * Common support routines for bin/scripts/ * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/common.c @@ -21,7 +21,6 @@ #include "common/connect.h" #include "common/logging.h" #include "common/string.h" -#include "fe_utils/cancel.h" #include "fe_utils/query_utils.h" #include "fe_utils/string_utils.h" @@ -112,8 +111,9 @@ appendQualifiedRelation(PQExpBuffer buf, const char *spec, exit(1); } appendPQExpBufferStr(buf, - fmtQualifiedId(PQgetvalue(res, 0, 1), - PQgetvalue(res, 0, 0))); + fmtQualifiedIdEnc(PQgetvalue(res, 0, 1), + PQgetvalue(res, 0, 0), + PQclientEncoding(conn))); appendPQExpBufferStr(buf, columns); PQclear(res); termPQExpBuffer(&sql); diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h index 97f19986c3bd6..7fab1fb6e038f 100644 --- a/src/bin/scripts/common.h +++ b/src/bin/scripts/common.h @@ -2,7 +2,7 @@ * common.h * Common support routines for bin/scripts/ * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/bin/scripts/common.h */ @@ -11,9 +11,9 @@ #include "common/username.h" #include "fe_utils/connect_utils.h" -#include "getopt_long.h" /* pgrminclude ignore */ +#include "getopt_long.h" #include "libpq-fe.h" -#include "pqexpbuffer.h" /* pgrminclude ignore */ +#include "pqexpbuffer.h" extern void splitTableColumnsSpec(const char *spec, int encoding, char **table, const char **columns); diff --git a/src/bin/scripts/createdb.c b/src/bin/scripts/createdb.c index 30426860efae4..7c0cf32d6a11b 100644 --- a/src/bin/scripts/createdb.c +++ b/src/bin/scripts/createdb.c @@ -2,7 +2,7 @@ * * createdb * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/createdb.c @@ -198,6 +198,8 @@ main(int argc, char *argv[]) conn = connectMaintenanceDatabase(&cparams, progname, echo); + setFmtEncoding(PQclientEncoding(conn)); + initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "CREATE DATABASE %s", diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c index f5f03c1145fb8..81e6abfc46e70 100644 --- a/src/bin/scripts/createuser.c +++ b/src/bin/scripts/createuser.c @@ -2,7 +2,7 @@ * * createuser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/createuser.c @@ -292,6 +292,8 @@ main(int argc, char *argv[]) conn = connectMaintenanceDatabase(&cparams, progname, echo); + setFmtEncoding(PQclientEncoding(conn)); + initPQExpBuffer(&sql); printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser)); diff --git a/src/bin/scripts/dropdb.c b/src/bin/scripts/dropdb.c index 57656ba8988ab..0b63081827713 100644 --- a/src/bin/scripts/dropdb.c +++ b/src/bin/scripts/dropdb.c @@ -2,7 +2,7 @@ * * dropdb * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/dropdb.c @@ -129,13 +129,6 @@ main(int argc, char *argv[]) exit(0); } - initPQExpBuffer(&sql); - - appendPQExpBuffer(&sql, "DROP DATABASE %s%s%s;", - (if_exists ? "IF EXISTS " : ""), - fmtId(dbname), - force ? " WITH (FORCE)" : ""); - /* Avoid trying to drop postgres db while we are connected to it. */ if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0) maintenance_db = "template1"; @@ -149,6 +142,12 @@ main(int argc, char *argv[]) conn = connectMaintenanceDatabase(&cparams, progname, echo); + initPQExpBuffer(&sql); + appendPQExpBuffer(&sql, "DROP DATABASE %s%s%s;", + (if_exists ? "IF EXISTS " : ""), + fmtIdEnc(dbname, PQclientEncoding(conn)), + force ? " WITH (FORCE)" : ""); + if (echo) printf("%s\n", sql.data); result = PQexec(conn, sql.data); diff --git a/src/bin/scripts/dropuser.c b/src/bin/scripts/dropuser.c index 233ccd288b7fd..39bb16861736f 100644 --- a/src/bin/scripts/dropuser.c +++ b/src/bin/scripts/dropuser.c @@ -2,7 +2,7 @@ * * dropuser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/dropuser.c @@ -143,7 +143,8 @@ main(int argc, char *argv[]) initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "DROP ROLE %s%s;", - (if_exists ? "IF EXISTS " : ""), fmtId(dropuser)); + (if_exists ? "IF EXISTS " : ""), + fmtIdEnc(dropuser, PQclientEncoding(conn))); if (echo) printf("%s\n", sql.data); diff --git a/src/bin/scripts/meson.build b/src/bin/scripts/meson.build index cef24d7806bb9..80df7c332572a 100644 --- a/src/bin/scripts/meson.build +++ b/src/bin/scripts/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group scripts_common = static_library('libscripts_common', files('common.c'), diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c index 100589da147b0..7b4ea3f39a9c5 100644 --- a/src/bin/scripts/pg_isready.c +++ b/src/bin/scripts/pg_isready.c @@ -2,7 +2,7 @@ * * pg_isready --- checks the status of the PostgreSQL server * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * src/bin/scripts/pg_isready.c * diff --git a/src/bin/scripts/po/de.po b/src/bin/scripts/po/de.po index 70225e6904436..ce0cbba47bdf8 100644 --- a/src/bin/scripts/po/de.po +++ b/src/bin/scripts/po/de.po @@ -1,14 +1,14 @@ # German message translation file for "scripts". -# Peter Eisentraut , 2003 - 2024. +# Peter Eisentraut , 2003 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-16 10:21+0000\n" -"PO-Revision-Date: 2024-06-16 19:03+0200\n" +"POT-Creation-Date: 2025-04-27 00:51+0000\n" +"PO-Revision-Date: 2025-04-27 15:40+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -17,22 +17,22 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "Fehler: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "Warnung: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "Detail: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "Tipp: " @@ -48,44 +48,44 @@ msgstr "Speicher aufgebraucht\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "konnte Datei »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "konnte Dateisystem für Datei »%s« nicht synchronisieren: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "diese Installation unterstützt Sync-Methode »%s« nicht" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #, c-format msgid "could not open directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht öffnen: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "konnte Verzeichnis »%s« nicht lesen: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "konnte Datei »%s« nicht fsyncen: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "konnte Datei »%s« nicht in »%s« umbenennen: %m" @@ -175,8 +175,8 @@ msgstr "Unterbrochen\n" #: ../../fe_utils/print.c:3188 #, c-format -msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" -msgstr "Kann Tabelleninhalt nicht ausgeben: Anzahl der Zellen %lld ist gleich oder überschreitet Maximum %lld.\n" +msgid "Cannot print table contents: number of cells % is equal to or exceeds maximum %zu.\n" +msgstr "Kann Tabelleninhalt nicht ausgeben: Anzahl der Zellen % ist gleich oder überschreitet Maximum %zu.\n" #: ../../fe_utils/print.c:3229 #, c-format @@ -185,8 +185,8 @@ msgstr "Kann keinen weiteren Spaltenkopf zur Tabelle hinzufügen: Spaltenzahl %d #: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" -msgstr "Kann keine weitere Zelle zur Tabelle hinzufügen: Zellengesamtzahl %lld überschritten.\n" +msgid "Cannot add cell to table content: total cell count of % exceeded.\n" +msgstr "Kann keine weitere Zelle zur Tabelle hinzufügen: Zellengesamtzahl % überschritten.\n" #: ../../fe_utils/print.c:3530 #, c-format @@ -203,51 +203,51 @@ msgstr "Anfrage fehlgeschlagen: %s" msgid "Query was: %s" msgstr "Anfrage war: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "Argument des Shell-Befehls enthält Newline oder Carriage Return: »%s«\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "Datenbankname enthält Newline oder Carriage Return: »%s«\n" -#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 +#: clusterdb.c:113 clusterdb.c:132 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 +#: reindexdb.c:184 reindexdb.c:203 vacuumdb.c:291 vacuumdb.c:311 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Versuchen Sie »%s --help« für weitere Informationen." -#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 +#: clusterdb.c:130 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:201 vacuumdb.c:309 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)" -#: clusterdb.c:149 +#: clusterdb.c:148 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "kann nicht alle Datenbanken und eine bestimmte gleichzeitig clustern" -#: clusterdb.c:214 +#: clusterdb.c:213 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "Clustern der Tabelle »%s« in Datenbank »%s« fehlgeschlagen: %s" -#: clusterdb.c:217 +#: clusterdb.c:216 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "Clustern der Datenbank »%s« fehlgeschlagen: %s" -#: clusterdb.c:248 +#: clusterdb.c:247 #, c-format msgid "%s: clustering database \"%s\"\n" msgstr "%s: clustere Datenbank »%s«\n" -#: clusterdb.c:274 +#: clusterdb.c:273 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -256,19 +256,19 @@ msgstr "" "%s clustert alle vorher geclusterten Tabellen in einer Datenbank.\n" "\n" -#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 +#: clusterdb.c:274 createdb.c:300 createuser.c:417 dropdb.c:171 dropuser.c:171 +#: pg_isready.c:226 reindexdb.c:898 vacuumdb.c:1337 #, c-format msgid "Usage:\n" msgstr "Aufruf:\n" -#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 +#: clusterdb.c:275 reindexdb.c:899 vacuumdb.c:1338 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 +#: clusterdb.c:276 createdb.c:302 createuser.c:419 dropdb.c:173 dropuser.c:173 +#: pg_isready.c:229 reindexdb.c:900 vacuumdb.c:1339 #, c-format msgid "" "\n" @@ -277,50 +277,50 @@ msgstr "" "\n" "Optionen:\n" -#: clusterdb.c:278 +#: clusterdb.c:277 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all clustere alle Datenbanken\n" -#: clusterdb.c:279 +#: clusterdb.c:278 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=DBNAME zu clusternde Datenbank\n" -#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:279 createuser.c:425 dropdb.c:174 dropuser.c:174 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr "" " -e, --echo zeige die Befehle, die an den Server\n" " gesendet werden\n" -#: clusterdb.c:281 +#: clusterdb.c:280 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet unterdrücke alle Mitteilungen\n" -#: clusterdb.c:282 +#: clusterdb.c:281 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=TABELLE clustere nur bestimmte Tabelle(n)\n" -#: clusterdb.c:283 +#: clusterdb.c:282 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose erzeuge viele Meldungen\n" -#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:283 createuser.c:441 dropdb.c:177 dropuser.c:177 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:284 createuser.c:449 dropdb.c:179 dropuser.c:179 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 +#: clusterdb.c:285 createdb.c:319 createuser.c:450 dropdb.c:180 dropuser.c:180 +#: pg_isready.c:235 reindexdb.c:915 vacuumdb.c:1369 #, c-format msgid "" "\n" @@ -329,37 +329,37 @@ msgstr "" "\n" "Verbindungsoptionen:\n" -#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 +#: clusterdb.c:286 createuser.c:451 dropdb.c:181 dropuser.c:181 vacuumdb.c:1370 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" -#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 +#: clusterdb.c:287 createuser.c:452 dropdb.c:182 dropuser.c:182 vacuumdb.c:1371 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT Port des Datenbankservers\n" -#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 +#: clusterdb.c:288 dropdb.c:183 vacuumdb.c:1372 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=NAME Datenbankbenutzername\n" -#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 +#: clusterdb.c:289 createuser.c:454 dropdb.c:184 dropuser.c:184 vacuumdb.c:1373 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password niemals nach Passwort fragen\n" -#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 +#: clusterdb.c:290 createuser.c:455 dropdb.c:185 dropuser.c:185 vacuumdb.c:1374 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password Passwortfrage erzwingen\n" -#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 +#: clusterdb.c:291 dropdb.c:186 vacuumdb.c:1375 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME alternative Wartungsdatenbank\n" -#: clusterdb.c:293 +#: clusterdb.c:292 #, c-format msgid "" "\n" @@ -369,8 +369,8 @@ msgstr "" "Für weitere Informationen lesen Sie bitte die Beschreibung des\n" "SQL-Befehls CLUSTER.\n" -#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 +#: clusterdb.c:293 createdb.c:327 createuser.c:456 dropdb.c:187 dropuser.c:186 +#: pg_isready.c:240 reindexdb.c:923 vacuumdb.c:1377 #, c-format msgid "" "\n" @@ -379,13 +379,13 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 +#: clusterdb.c:294 createdb.c:328 createuser.c:457 dropdb.c:188 dropuser.c:187 +#: pg_isready.c:241 reindexdb.c:924 vacuumdb.c:1378 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: common.c:107 +#: common.c:106 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" @@ -419,17 +419,17 @@ msgstr "Bitte antworten Sie »%s« oder »%s«.\n" msgid "\"%s\" is not a valid encoding name" msgstr "»%s« ist kein gültiger Kodierungsname" -#: createdb.c:260 +#: createdb.c:262 #, c-format msgid "database creation failed: %s" msgstr "Erzeugen der Datenbank ist fehlgeschlagen: %s" -#: createdb.c:279 +#: createdb.c:281 #, c-format msgid "comment creation failed (database was created): %s" msgstr "Erzeugen des Kommentars ist fehlgeschlagen (Datenbank wurde erzeugt): %s" -#: createdb.c:297 +#: createdb.c:299 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -438,61 +438,61 @@ msgstr "" "%s erzeugt eine PostgreSQL-Datenbank.\n" "\n" -#: createdb.c:299 +#: createdb.c:301 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [OPTION]... [DBNAME] [BESCHREIBUNG]\n" -#: createdb.c:301 +#: createdb.c:303 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=TABLESPACE Standard-Tablespace der Datenbank\n" -#: createdb.c:302 reindexdb.c:874 +#: createdb.c:304 reindexdb.c:904 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr "" " -e, --echo zeige die Befehle, die an den Server\n" " gesendet werden\n" -#: createdb.c:303 +#: createdb.c:305 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=KODIERUNG Kodierung für die Datenbank\n" -#: createdb.c:304 +#: createdb.c:306 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOCALE Locale-Einstellungen für die Datenbank\n" -#: createdb.c:305 +#: createdb.c:307 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOCALE LC_COLLATE-Einstellung für die Datenbank\n" -#: createdb.c:306 +#: createdb.c:308 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOCALE LC_CTYPE-Einstellung für die Datenbank\n" -#: createdb.c:307 +#: createdb.c:309 #, c-format msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" msgstr "" " --builtin-locale=LOCALE Locale-Einstellung für Provider »builtin« für\n" " die Datenbank\n" -#: createdb.c:308 +#: createdb.c:310 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE ICU-Locale-Einstellung für die Datenbank\n" -#: createdb.c:309 +#: createdb.c:311 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=REGELN ICU-Regel-Einstellung für die Datenbank\n" -#: createdb.c:310 +#: createdb.c:312 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -501,62 +501,62 @@ msgstr "" " --locale-provider={builtin|libc|icu}\n" " Locale-Provider für Standardsortierfolge der Datenbank\n" -#: createdb.c:312 +#: createdb.c:314 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --owner=EIGENTÜMER Eigentümer der neuen Datenbank\n" -#: createdb.c:313 +#: createdb.c:315 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr " -S, --strategy=STRATEGIE Datenbankerzeugungsstrategie wal_log oder file_copy\n" -#: createdb.c:314 +#: createdb.c:316 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=TEMPLATE zu kopierende Template-Datenbank\n" -#: createdb.c:315 reindexdb.c:883 +#: createdb.c:317 reindexdb.c:913 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: createdb.c:316 reindexdb.c:884 +#: createdb.c:318 reindexdb.c:914 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: createdb.c:318 reindexdb.c:886 +#: createdb.c:320 reindexdb.c:916 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME Name des Datenbankservers oder Socket-Verzeichnis\n" -#: createdb.c:319 reindexdb.c:887 +#: createdb.c:321 reindexdb.c:917 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT Port des Datenbankservers\n" -#: createdb.c:320 reindexdb.c:888 +#: createdb.c:322 reindexdb.c:918 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=NAME Datenbankbenutzername\n" -#: createdb.c:321 reindexdb.c:889 +#: createdb.c:323 reindexdb.c:919 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password niemals nach Passwort fragen\n" -#: createdb.c:322 reindexdb.c:890 +#: createdb.c:324 reindexdb.c:920 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password Passwortfrage erzwingen\n" -#: createdb.c:323 reindexdb.c:891 +#: createdb.c:325 reindexdb.c:921 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME alternative Wartungsdatenbank\n" -#: createdb.c:324 +#: createdb.c:326 #, c-format msgid "" "\n" @@ -595,17 +595,17 @@ msgstr "Soll die neue Rolle Datenbanken erzeugen dürfen?" msgid "Shall the new role be allowed to create more new roles?" msgstr "Soll die neue Rolle weitere neue Rollen erzeugen dürfen?" -#: createuser.c:309 +#: createuser.c:311 #, c-format msgid "password encryption failed: %s" msgstr "Passwortverschlüsselung ist fehlgeschlagen: %s" -#: createuser.c:400 +#: createuser.c:402 #, c-format msgid "creation of new role failed: %s" msgstr "Erzeugen der neuen Rolle fehlgeschlagen: %s" -#: createuser.c:414 +#: createuser.c:416 #, c-format msgid "" "%s creates a new PostgreSQL role.\n" @@ -614,12 +614,12 @@ msgstr "" "%s erzeugt eine neue PostgreSQL-Rolle.\n" "\n" -#: createuser.c:416 dropuser.c:171 +#: createuser.c:418 dropuser.c:172 #, c-format msgid " %s [OPTION]... [ROLENAME]\n" msgstr " %s [OPTION]... [ROLLENNAME]\n" -#: createuser.c:418 +#: createuser.c:420 #, c-format msgid "" " -a, --with-admin=ROLE ROLE will be a member of new role with admin\n" @@ -628,34 +628,34 @@ msgstr "" " -a, --with-admin=ROLLE ROLLE wird Mitglied der neuen Rolle mit\n" " Admin-Option\n" -#: createuser.c:420 +#: createuser.c:422 #, c-format msgid " -c, --connection-limit=N connection limit for role (default: no limit)\n" msgstr "" " -c, --connection-limit=N Hochzahl an Verbindungen für Rolle\n" " (Voreinstellung: keine Begrenzung)\n" -#: createuser.c:421 +#: createuser.c:423 #, c-format msgid " -d, --createdb role can create new databases\n" msgstr " -d, --createdb Rolle kann neue Datenbanken erzeugen\n" -#: createuser.c:422 +#: createuser.c:424 #, c-format msgid " -D, --no-createdb role cannot create databases (default)\n" msgstr " -D, --no-createdb Rolle kann keine Datenbanken erzeugen (Voreinstellung)\n" -#: createuser.c:424 +#: createuser.c:426 #, c-format msgid " -g, --member-of=ROLE new role will be a member of ROLE\n" msgstr " -g, --member-of=ROLLE neue Rolle wird Mitglied von ROLLE\n" -#: createuser.c:425 +#: createuser.c:427 #, c-format msgid " --role=ROLE (same as --member-of, deprecated)\n" msgstr " --role=ROLLE (gleich --member-of, veraltet)\n" -#: createuser.c:426 +#: createuser.c:428 #, c-format msgid "" " -i, --inherit role inherits privileges of roles it is a\n" @@ -664,52 +664,52 @@ msgstr "" " -i, --inherit Rolle erbt alle Privilegien von Rollen, deren\n" " Mitglied sie ist (Voreinstellung)\n" -#: createuser.c:428 +#: createuser.c:430 #, c-format msgid " -I, --no-inherit role does not inherit privileges\n" msgstr " -I, --no-inherit Rolle erbt keine Privilegien\n" -#: createuser.c:429 +#: createuser.c:431 #, c-format msgid " -l, --login role can login (default)\n" msgstr " -l, --login Rolle kann sich anmelden (Voreinstellung)\n" -#: createuser.c:430 +#: createuser.c:432 #, c-format msgid " -L, --no-login role cannot login\n" msgstr " -L, --no-login Rolle kann sich nicht anmelden\n" -#: createuser.c:431 +#: createuser.c:433 #, c-format msgid " -m, --with-member=ROLE ROLE will be a member of new role\n" msgstr " -m, --with-member=ROLLE ROLLE wird Mitglied der neuen Rolle\n" -#: createuser.c:432 +#: createuser.c:434 #, c-format msgid " -P, --pwprompt assign a password to new role\n" msgstr " -P, --pwprompt weise der neuen Rolle ein Passwort zu\n" -#: createuser.c:433 +#: createuser.c:435 #, c-format msgid " -r, --createrole role can create new roles\n" msgstr " -r, --createrole Rolle kann neue Rollen erzeugen\n" -#: createuser.c:434 +#: createuser.c:436 #, c-format msgid " -R, --no-createrole role cannot create roles (default)\n" msgstr " -R, --no-createrole Rolle kann keine Rollen erzeugen (Voreinstellung)\n" -#: createuser.c:435 +#: createuser.c:437 #, c-format msgid " -s, --superuser role will be superuser\n" msgstr " -s, --superuser Rolle wird Superuser\n" -#: createuser.c:436 +#: createuser.c:438 #, c-format msgid " -S, --no-superuser role will not be superuser (default)\n" msgstr " -S, --no-superuser Rolle wird kein Superuser (Voreinstellung)\n" -#: createuser.c:437 +#: createuser.c:439 #, c-format msgid "" " -v, --valid-until=TIMESTAMP\n" @@ -718,7 +718,7 @@ msgstr "" " -v, --valid-until=TIMESTAMP\n" " Ablaufdatum und -zeit des Passworts der Rolle\n" -#: createuser.c:440 +#: createuser.c:442 #, c-format msgid "" " --interactive prompt for missing role name and attributes rather\n" @@ -727,14 +727,14 @@ msgstr "" " --interactive nach fehlenden Rollennamen und -attributen fragen\n" " anstatt Vorgabewerte zu nehmen\n" -#: createuser.c:442 +#: createuser.c:444 #, c-format msgid " --bypassrls role can bypass row-level security (RLS) policy\n" msgstr "" " --bypassrls Rolle kann Policy für Sicherheit auf Zeilenebene (RLS)\n" " umgehen\n" -#: createuser.c:443 +#: createuser.c:445 #, c-format msgid "" " --no-bypassrls role cannot bypass row-level security (RLS) policy\n" @@ -743,17 +743,17 @@ msgstr "" " --no-bypassrls Rolle kann Policy für Sicherheit auf Zeilenebene (RLS)\n" " nicht umgehen (Voreinstellung)\n" -#: createuser.c:445 +#: createuser.c:447 #, c-format msgid " --replication role can initiate replication\n" msgstr " --replication Rolle kann Replikation einleiten\n" -#: createuser.c:446 +#: createuser.c:448 #, c-format msgid " --no-replication role cannot initiate replication (default)\n" msgstr " --no-replication Rolle kann Replikation nicht einleiten (Voreinstellung)\n" -#: createuser.c:451 +#: createuser.c:453 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to create)\n" msgstr "" @@ -774,12 +774,12 @@ msgstr "Datenbank »%s« wird unwiderruflich gelöscht werden.\n" msgid "Are you sure?" msgstr "Sind Sie sich sicher?" -#: dropdb.c:157 +#: dropdb.c:156 #, c-format msgid "database removal failed: %s" msgstr "Löschen der Datenbank fehlgeschlagen: %s" -#: dropdb.c:171 +#: dropdb.c:170 #, c-format msgid "" "%s removes a PostgreSQL database.\n" @@ -788,22 +788,22 @@ msgstr "" "%s löscht eine PostgreSQL-Datenbank.\n" "\n" -#: dropdb.c:173 +#: dropdb.c:172 #, c-format msgid " %s [OPTION]... DBNAME\n" msgstr " %s [OPTION]... DBNAME\n" -#: dropdb.c:176 +#: dropdb.c:175 #, c-format msgid " -f, --force try to terminate other connections before dropping\n" msgstr " -f, --force vor dem Löschen versuchen andere Verbindungen abzubrechen\n" -#: dropdb.c:177 +#: dropdb.c:176 #, c-format msgid " -i, --interactive prompt before deleting anything\n" msgstr " -i, --interactive frage nach, bevor irgendetwas gelöscht wird\n" -#: dropdb.c:179 +#: dropdb.c:178 #, c-format msgid " --if-exists don't report error if database doesn't exist\n" msgstr " --if-exists keinen Fehler ausgeben, wenn Datenbank nicht existiert\n" @@ -822,12 +822,12 @@ msgstr "Rollenname als Argument fehlt" msgid "Role \"%s\" will be permanently removed.\n" msgstr "Rolle »%s« wird unwiderruflich gelöscht werden.\n" -#: dropuser.c:154 +#: dropuser.c:155 #, c-format msgid "removal of role \"%s\" failed: %s" msgstr "Löschen der Rolle »%s« fehlgeschlagen: %s" -#: dropuser.c:169 +#: dropuser.c:170 #, c-format msgid "" "%s removes a PostgreSQL role.\n" @@ -836,7 +836,7 @@ msgstr "" "%s löscht eine PostgreSQL-Rolle.\n" "\n" -#: dropuser.c:174 +#: dropuser.c:175 #, c-format msgid "" " -i, --interactive prompt before deleting anything, and prompt for\n" @@ -845,12 +845,12 @@ msgstr "" " -i, --interactive nachfragen, bevor irgendetwas gelöscht wird, und\n" " nach Rollennamen fragen, wenn nicht angegeben\n" -#: dropuser.c:177 +#: dropuser.c:178 #, c-format msgid " --if-exists don't report error if user doesn't exist\n" msgstr " --if-exists keinen Fehler ausgeben, wenn Benutzer nicht existiert\n" -#: dropuser.c:182 +#: dropuser.c:183 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to drop)\n" msgstr "" @@ -941,54 +941,54 @@ msgstr " -t, --timeout=SEK Sekunden auf Verbindung warten, 0 schaltet au msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=NAME Datenbankbenutzername\n" -#: reindexdb.c:210 +#: reindexdb.c:217 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "kann nicht mehrere Jobs verwenden, um Systemkataloge zu reindizieren" -#: reindexdb.c:215 +#: reindexdb.c:222 #, c-format msgid "cannot reindex all databases and a specific one at the same time" msgstr "kann nicht alle Datenbanken und eine bestimmte gleichzeitig reindizieren" -#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 -#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 -#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 +#: reindexdb.c:302 reindexdb.c:309 vacuumdb.c:558 vacuumdb.c:565 vacuumdb.c:572 +#: vacuumdb.c:579 vacuumdb.c:586 vacuumdb.c:593 vacuumdb.c:600 vacuumdb.c:607 +#: vacuumdb.c:614 vacuumdb.c:621 vacuumdb.c:628 vacuumdb.c:635 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "Option »%s« kann nicht mit Serverversionen älter als PostgreSQL %s verwendet werden" -#: reindexdb.c:584 +#: reindexdb.c:597 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "Reindizieren der Datenbank »%s« fehlgeschlagen: %s" -#: reindexdb.c:588 +#: reindexdb.c:601 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "Reindizieren des Index »%s« in Datenbank »%s« fehlgeschlagen: %s" -#: reindexdb.c:592 +#: reindexdb.c:605 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "Reindizieren des Schemas »%s« in Datenbank »%s« fehlgeschlagen: %s" -#: reindexdb.c:596 +#: reindexdb.c:609 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "Reindizieren der Systemkataloge in Datenbank »%s« fehlgeschlagen: %s" -#: reindexdb.c:600 +#: reindexdb.c:613 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "Reindizieren der Tabelle »%s« in Datenbank »%s« fehlgeschlagen: %s" -#: reindexdb.c:824 +#: reindexdb.c:854 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: reindiziere Datenbank »%s«\n" -#: reindexdb.c:867 +#: reindexdb.c:897 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -997,64 +997,64 @@ msgstr "" "%s reindiziert eine PostgreSQL-Datenbank.\n" "\n" -#: reindexdb.c:871 +#: reindexdb.c:901 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all alle Datenbanken reindizieren\n" -#: reindexdb.c:872 +#: reindexdb.c:902 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently nebenläufig reindizieren\n" -#: reindexdb.c:873 +#: reindexdb.c:903 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=DBNAME zu reindizierende Datenbank\n" -#: reindexdb.c:875 +#: reindexdb.c:905 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX nur bestimmte(n) Index(e) erneuern\n" -#: reindexdb.c:876 +#: reindexdb.c:906 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr "" " -j, --jobs=NUM so viele parallele Verbindungen zum Reindizieren\n" " verwenden\n" -#: reindexdb.c:877 +#: reindexdb.c:907 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet unterdrücke alle Mitteilungen\n" -#: reindexdb.c:878 +#: reindexdb.c:908 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system nur Systemkataloge reindizieren\n" -#: reindexdb.c:879 +#: reindexdb.c:909 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHEMA nur bestimmte(s) Schema(s) reindizieren\n" -#: reindexdb.c:880 +#: reindexdb.c:910 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABELLE nur bestimmte Tabelle(n) reindizieren\n" -#: reindexdb.c:881 +#: reindexdb.c:911 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " --tablespace=TABLESPACE Tablespace wo Indexe neu gebaut werden\n" -#: reindexdb.c:882 +#: reindexdb.c:912 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose erzeuge viele Meldungen\n" -#: reindexdb.c:892 +#: reindexdb.c:922 #, c-format msgid "" "\n" @@ -1064,80 +1064,85 @@ msgstr "" "Für weitere Informationen lesen Sie bitte die Beschreibung des\n" "SQL-Befehls REINDEX.\n" -#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 -#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 +#: vacuumdb.c:324 vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:336 +#: vacuumdb.c:339 vacuumdb.c:342 vacuumdb.c:345 vacuumdb.c:354 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "kann Option »%s« nicht verwenden, wenn nur Analyze durchgeführt wird" -#: vacuumdb.c:346 +#: vacuumdb.c:357 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "kann Option »%s« nicht verwenden, wenn volles Vacuum durchgeführt wird" -#: vacuumdb.c:352 vacuumdb.c:360 +#: vacuumdb.c:363 vacuumdb.c:371 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "kann Option »%s« nicht mit der Option »%s« verwenden" -#: vacuumdb.c:432 +#: vacuumdb.c:379 +#, c-format +msgid "cannot use the \"%s\" option without \"%s\" or \"%s\"" +msgstr "kann Option »%s« nicht ohne »%s« oder »%s« verwenden" + +#: vacuumdb.c:453 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "kann nicht alle Datenbanken und eine bestimmte gleichzeitig vacuumen" -#: vacuumdb.c:436 +#: vacuumdb.c:457 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "kann nicht alle Tabellen in Schemas und bestimmte Tabellen gleichzeitig vacuumen" -#: vacuumdb.c:440 +#: vacuumdb.c:461 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "kann nicht bestimmte Tabelle(n) vacuumen und gleichzeitig Schemas ausschließen" -#: vacuumdb.c:444 +#: vacuumdb.c:465 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "kann nicht alle Tabellen in Schemas vacuumen und gleichzeitig Schemas ausschließen" -#: vacuumdb.c:457 +#: vacuumdb.c:478 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" -#: vacuumdb.c:502 +#: vacuumdb.c:545 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Erzeuge minimale Optimierer-Statistiken (1 Ziel)" -#: vacuumdb.c:503 +#: vacuumdb.c:546 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Erzeuge mittlere Optimierer-Statistiken (10 Ziele)" -#: vacuumdb.c:504 +#: vacuumdb.c:547 msgid "Generating default (full) optimizer statistics" msgstr "Erzeuge volle Optimierer-Statistiken" -#: vacuumdb.c:583 +#: vacuumdb.c:645 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: bearbeite Datenbank »%s«: %s\n" -#: vacuumdb.c:586 +#: vacuumdb.c:648 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: führe Vacuum in Datenbank »%s« aus\n" -#: vacuumdb.c:1135 +#: vacuumdb.c:1325 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "Vacuum der Tabelle »%s« in Datenbank »%s« fehlgeschlagen: %s" -#: vacuumdb.c:1138 +#: vacuumdb.c:1328 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "Vacuum der Datenbank »%s« fehlgeschlagen: %s" -#: vacuumdb.c:1146 +#: vacuumdb.c:1336 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1146,148 +1151,153 @@ msgstr "" "%s säubert und analysiert eine PostgreSQL-Datenbank.\n" "\n" -#: vacuumdb.c:1150 +#: vacuumdb.c:1340 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all führe Vacuum in allen Datenbanken aus\n" -#: vacuumdb.c:1151 +#: vacuumdb.c:1341 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=GRÖSSE Größe des für Vacuum verwendeten Ringpuffers\n" -#: vacuumdb.c:1152 +#: vacuumdb.c:1342 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=DBNAME führe Vacuum in dieser Datenbank aus\n" -#: vacuumdb.c:1153 +#: vacuumdb.c:1343 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping Page-Skipping-Verhalten abschalten\n" -#: vacuumdb.c:1154 +#: vacuumdb.c:1344 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr "" " -e, --echo zeige die Befehle, die an den Server\n" " gesendet werden\n" -#: vacuumdb.c:1155 +#: vacuumdb.c:1345 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full führe volles Vacuum durch\n" -#: vacuumdb.c:1156 +#: vacuumdb.c:1346 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze Zeilentransaktionsinformationen einfrieren\n" -#: vacuumdb.c:1157 +#: vacuumdb.c:1347 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr " --force-index-cleanup Indexeinträge, die auf tote Tupel zeigen, immer entfernen\n" -#: vacuumdb.c:1158 +#: vacuumdb.c:1348 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr "" " -j, --jobs=NUM so viele parallele Verbindungen zum Vacuum\n" " verwenden\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1349 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr "" " --min-mxid-age=MXID-ALTER minimales Multixact-ID-Alter zu bearbeitender\n" " Tabellen\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1350 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr "" " --min-xid-age=XID-ALTER minimales Transaktions-ID-Alter zu bearbeitender\n" " Tabellen\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1351 +#, c-format +msgid " --missing-stats-only only analyze relations with missing statistics\n" +msgstr " --missing-stats-only nur Relationen mit fehlenden Statistiken analysieren\n" + +#: vacuumdb.c:1352 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr " --no-index-cleanup Indexeinträge, die auf tote Tupel zeigen, nicht entfernen\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1353 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main die Hauptrelation überspringen\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1354 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr " --no-process-toast zur Tabelle gehörige TOAST-Tabelle überspringen\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1355 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate leere Seiten am Ende der Tabelle nicht abschneiden\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1356 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" msgstr " -n, --schema=SCHEMA nur Tabellen in den angegebenen Schemas vacuumen\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1357 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" msgstr " -N, --exclude-schema=SCHEMA Tabellen in den angegebenen Schemas nicht vacuumen\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1358 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr "" " -P, --parallel=PARALLEL-PROZ so viele Background-Worker für Vacuum verwenden,\n" " wenn verfügbar\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1359 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet unterdrücke alle Mitteilungen\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1360 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr "" " --skip-locked Relationen überspringen, die nicht sofort\n" " gesperrt werden können\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1361 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr "" " -t, --table='TABELLE[(SPALTEN)]'\n" " führe Vacuum für bestimmte Tabelle(n) aus\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1362 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose erzeuge viele Meldungen\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1363 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1364 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze aktualisiere Statistiken für den Optimierer\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1365 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr "" " -Z, --analyze-only aktualisiere nur Statistiken für den Optimierer;\n" " kein Vacuum\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1366 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1297,12 +1307,12 @@ msgstr "" " in mehreren Phasen für schnellere Ergebnisse;\n" " kein Vacuum\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1368 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: vacuumdb.c:1185 +#: vacuumdb.c:1376 #, c-format msgid "" "\n" diff --git a/src/bin/scripts/po/es.po b/src/bin/scripts/po/es.po index 82ffa20755691..97f4e2e30684e 100644 --- a/src/bin/scripts/po/es.po +++ b/src/bin/scripts/po/es.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pgscripts (PostgreSQL) 16\n" +"Project-Id-Version: pgscripts (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-03 07:20+0000\n" -"PO-Revision-Date: 2023-10-03 16:25+0200\n" +"POT-Creation-Date: 2025-02-16 19:51+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -54,6 +54,48 @@ msgstr "memoria agotada\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "no se puede duplicar un puntero nulo (error interno)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "no se pudo abrir el archivo «%s»: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "no se pudo sincronizar el sistema de archivos para el archivo «%s»: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "no se pudo hacer stat al archivo «%s»: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "esta instalación no soporta el método de sync «%s»" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "no se pudo abrir el directorio «%s»: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "no se pudo leer el directorio «%s»: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "no se pudo sincronizar (fsync) archivo «%s»: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "no se pudo renombrar el archivo de «%s» a «%s»: %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -68,11 +110,11 @@ msgstr "el usuario no existe" msgid "user name lookup failure: error code %lu" msgstr "fallo en la búsqueda de nombre de usuario: código de error %lu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Petición de cancelación enviada\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "No se pudo enviar el paquete de cancelación: " @@ -100,12 +142,27 @@ msgstr "el valor «%s» no es válido para la opción %s" msgid "%s must be in range %d..%d" msgstr "%s debe estar en el rango %d..%d" -#: ../../fe_utils/parallel_slot.c:299 +#: ../../fe_utils/option_utils.c:106 #, c-format -msgid "too many jobs for this platform" -msgstr "demasiados procesos para esta plataforma" +msgid "unrecognized sync method: %s" +msgstr "método sync no reconocido: %s" -#: ../../fe_utils/parallel_slot.c:520 +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "demasiados procesos para esta plataforma: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "descriptor de archivo para socket fuera de rango para select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Intente con menos trabajos." + +#: ../../fe_utils/parallel_slot.c:553 #, c-format msgid "processing of database \"%s\" failed: %s" msgstr "falló el procesamiento de la base de datos «%s»: %s" @@ -122,17 +179,22 @@ msgstr[1] "(%lu filas)" msgid "Interrupted\n" msgstr "Interrumpido\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "No se puede imprimir el contenido de la tabla: el número de celdas %lld es igual o mayor al máximo %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "No se puede agregar un encabezado al contenido de la tabla: la cantidad de columnas de %d ha sido excedida.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "No se puede agregar una celda al contenido de la tabla: la cantidad de celdas de %d ha sido excedida.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "No se puede agregar una celda al contenido de la tabla: la cantidad de celdas de %lld ha sido excedida.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "formato de salida no válido (error interno): %d" @@ -147,36 +209,41 @@ msgstr "la consulta falló: %s" msgid "Query was: %s" msgstr "La consulta era: %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:587 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "el argumento de la orden de shell contiene un salto de línea o retorno de carro: «%s»\n" + +#: ../../fe_utils/string_utils.c:760 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "el nombre de base de datos contiene un salto de línea o retorno de carro: «%s»\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:279 vacuumdb.c:299 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Pruebe «%s --help» para mayor información." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:297 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "no se puede reordenar todas las bases de datos y una de ellas en particular simultáneamente" -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "no es posible reordenar tablas específicas en todas las bases de datos" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "falló el reordenamiento de la tabla «%s» en la base de datos «%s»: %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "falló el reordenamiento de la base de datos «%s»: %s" @@ -186,7 +253,7 @@ msgstr "falló el reordenamiento de la base de datos «%s»: %s" msgid "%s: clustering database \"%s\"\n" msgstr "%s: reordenando la base de datos «%s»\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -196,19 +263,19 @@ msgstr "" "en una base de datos.\n" "\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1156 +#: clusterdb.c:275 createdb.c:300 createuser.c:417 dropdb.c:171 dropuser.c:171 +#: pg_isready.c:226 reindexdb.c:876 vacuumdb.c:1171 #, c-format msgid "Usage:\n" msgstr "Empleo:\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1157 +#: clusterdb.c:276 reindexdb.c:877 vacuumdb.c:1172 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPCIÓN]... [BASE-DE-DATOS]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1158 +#: clusterdb.c:277 createdb.c:302 createuser.c:419 dropdb.c:173 dropuser.c:173 +#: pg_isready.c:229 reindexdb.c:878 vacuumdb.c:1173 #, c-format msgid "" "\n" @@ -217,48 +284,48 @@ msgstr "" "\n" "Opciones:\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all reordenar todas las bases de datos\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=BASE base de datos a reordenar\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:425 dropdb.c:174 dropuser.c:174 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo mostrar las órdenes a medida que se ejecutan\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet no escribir ningún mensaje\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=TABLA reordenar sólo esta(s) tabla(s)\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose desplegar varios mensajes informativos\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:441 dropdb.c:177 dropuser.c:177 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:449 dropdb.c:179 dropuser.c:179 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1187 +#: clusterdb.c:286 createdb.c:319 createuser.c:450 dropdb.c:180 dropuser.c:180 +#: pg_isready.c:235 reindexdb.c:893 vacuumdb.c:1202 #, c-format msgid "" "\n" @@ -267,37 +334,37 @@ msgstr "" "\n" "Opciones de conexión:\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1188 +#: clusterdb.c:287 createuser.c:451 dropdb.c:181 dropuser.c:181 vacuumdb.c:1203 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=ANFITRIÓN nombre del servidor o directorio del socket\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1189 +#: clusterdb.c:288 createuser.c:452 dropdb.c:182 dropuser.c:182 vacuumdb.c:1204 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PUERTO puerto del servidor\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1190 +#: clusterdb.c:289 dropdb.c:183 vacuumdb.c:1205 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USUARIO nombre de usuario para la conexión\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1191 +#: clusterdb.c:290 createuser.c:454 dropdb.c:184 dropuser.c:184 vacuumdb.c:1206 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir contraseña\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1192 +#: clusterdb.c:291 createuser.c:455 dropdb.c:185 dropuser.c:185 vacuumdb.c:1207 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password forzar la petición de contraseña\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1193 +#: clusterdb.c:292 dropdb.c:186 vacuumdb.c:1208 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE base de datos de mantención alternativa\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "" "\n" @@ -306,8 +373,8 @@ msgstr "" "\n" "Lea la descripción de la orden CLUSTER de SQL para obtener mayores detalles.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1195 +#: clusterdb.c:294 createdb.c:327 createuser.c:456 dropdb.c:187 dropuser.c:186 +#: pg_isready.c:240 reindexdb.c:901 vacuumdb.c:1210 #, c-format msgid "" "\n" @@ -316,8 +383,8 @@ msgstr "" "\n" "Reporte errores a <%s>.\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1196 +#: clusterdb.c:295 createdb.c:328 createuser.c:457 dropdb.c:188 dropuser.c:187 +#: pg_isready.c:241 reindexdb.c:902 vacuumdb.c:1211 #, c-format msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" @@ -330,43 +397,43 @@ msgstr[0] "la consulta retornó %d fila en lugar de una: %s" msgstr[1] "la consulta retornó %d filas en lugar de una: %s" #. translator: abbreviation for "yes" -#: common.c:131 +#: common.c:132 msgid "y" msgstr "s" #. translator: abbreviation for "no" -#: common.c:133 +#: common.c:134 msgid "n" msgstr "n" #. translator: This is a question followed by the translated options for #. "yes" and "no". -#: common.c:143 +#: common.c:144 #, c-format msgid "%s (%s/%s) " msgstr "%s (%s/%s) " -#: common.c:164 +#: common.c:165 #, c-format msgid "Please answer \"%s\" or \"%s\".\n" msgstr "Por favor conteste «%s» o «%s».\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "«%s» no es un nombre válido de codificación" -#: createdb.c:250 +#: createdb.c:262 #, c-format msgid "database creation failed: %s" msgstr "falló la creación de la base de datos: %s" -#: createdb.c:269 +#: createdb.c:281 #, c-format msgid "comment creation failed (database was created): %s" msgstr "falló la creación del comentario (la base de datos fue creada): %s" -#: createdb.c:287 +#: createdb.c:299 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -375,119 +442,124 @@ msgstr "" "%s crea una base de datos PostgreSQL.\n" "\n" -#: createdb.c:289 +#: createdb.c:301 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [OPCIÓN]... [NOMBRE] [DESCRIPCIÓN]\n" -#: createdb.c:291 +#: createdb.c:303 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=TBLSPC tablespace por omisión de la base de datos\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:304 reindexdb.c:882 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo mostrar las órdenes enviadas al servidor\n" -#: createdb.c:293 +#: createdb.c:305 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=CODIF codificación para la base de datos\n" -#: createdb.c:294 +#: createdb.c:306 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOCALE configuración regional para la base de datos\n" -#: createdb.c:295 +#: createdb.c:307 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOCALE configuración LC_COLLATE para la base de datos\n" -#: createdb.c:296 +#: createdb.c:308 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOCALE configuración LC_CTYPE para la base de datos\n" -#: createdb.c:297 +#: createdb.c:309 +#, c-format +msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=LOCALE configuración regional builtin para la base de datos\n" + +#: createdb.c:310 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE configuración regional ICU para la base de datos\n" -#: createdb.c:298 +#: createdb.c:311 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=REGLAS configuración de reglas ICU para la base de datos\n" -#: createdb.c:299 +#: createdb.c:312 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default collation\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " proveedor de configuración regional para el ordenamiento\n" " por omisión de las bases de datos\n" -#: createdb.c:301 +#: createdb.c:314 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --owner=DUEÑO usuario que será dueño de la base de datos\n" -#: createdb.c:302 +#: createdb.c:315 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr "" " -S, --strategy=ESTRATEGIA estrategia de creación de bases de datos\n" " wal_log o file_copy\n" -#: createdb.c:303 +#: createdb.c:316 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=PATRÓN base de datos patrón a copiar\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:317 reindexdb.c:891 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:318 reindexdb.c:892 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:320 reindexdb.c:894 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=ANFITRIÓN nombre del servidor o directorio del socket\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:321 reindexdb.c:895 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PUERTO puerto del servidor\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:322 reindexdb.c:896 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USUARIO nombre de usuario para la conexión\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:323 reindexdb.c:897 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password nunca pedir contraseña\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:324 reindexdb.c:898 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password forzar la petición de contraseña\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:325 reindexdb.c:899 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE base de datos de mantención alternativa\n" -#: createdb.c:313 +#: createdb.c:326 #, c-format msgid "" "\n" @@ -526,17 +598,17 @@ msgstr "¿Debe permitírsele al rol la creación de bases de datos?" msgid "Shall the new role be allowed to create more new roles?" msgstr "¿Debe permitírsele al rol la creación de otros roles?" -#: createuser.c:309 +#: createuser.c:311 #, c-format msgid "password encryption failed: %s" msgstr "el cifrado de la contraseña falló: %s" -#: createuser.c:400 +#: createuser.c:402 #, c-format msgid "creation of new role failed: %s" msgstr "falló la creación del nuevo rol: %s" -#: createuser.c:414 +#: createuser.c:416 #, c-format msgid "" "%s creates a new PostgreSQL role.\n" @@ -545,46 +617,46 @@ msgstr "" "%s crea un nuevo rol de PostgreSQL.\n" "\n" -#: createuser.c:416 dropuser.c:171 +#: createuser.c:418 dropuser.c:172 #, c-format msgid " %s [OPTION]... [ROLENAME]\n" msgstr " %s [OPCIÓN]... [ROL]\n" -#: createuser.c:418 +#: createuser.c:420 #, c-format msgid "" " -a, --with-admin=ROLE ROLE will be a member of new role with admin\n" " option\n" msgstr " -a, --with-admin=ROL ROL será miembro del nuevo rol con “opción de admin”\n" -#: createuser.c:420 +#: createuser.c:422 #, c-format msgid " -c, --connection-limit=N connection limit for role (default: no limit)\n" msgstr "" " -c, --connection-limit=N límite de conexiones para el rol\n" " (predeterminado: sin límite)\n" -#: createuser.c:421 +#: createuser.c:423 #, c-format msgid " -d, --createdb role can create new databases\n" msgstr " -d, --createdb el rol podrá crear bases de datos\n" -#: createuser.c:422 +#: createuser.c:424 #, c-format msgid " -D, --no-createdb role cannot create databases (default)\n" msgstr " -D, --no-createdb el rol no podrá crear bases de datos (predeterm.)\n" -#: createuser.c:424 +#: createuser.c:426 #, c-format msgid " -g, --member-of=ROLE new role will be a member of ROLE\n" msgstr " -g, --member-of=ROL el nuevo rol será un miembro de ROL\n" -#: createuser.c:425 +#: createuser.c:427 #, c-format msgid " --role=ROLE (same as --member-of, deprecated)\n" msgstr " --role=ROL (lo mismo que --member-of; obsoleto)\n" -#: createuser.c:426 +#: createuser.c:428 #, c-format msgid "" " -i, --inherit role inherits privileges of roles it is a\n" @@ -593,52 +665,52 @@ msgstr "" " -i, --inherit el rol heredará los privilegios de los roles de\n" " los cuales es miembro (predeterminado)\n" -#: createuser.c:428 +#: createuser.c:430 #, c-format msgid " -I, --no-inherit role does not inherit privileges\n" msgstr " -I, --no-inherit rol no heredará privilegios\n" -#: createuser.c:429 +#: createuser.c:431 #, c-format msgid " -l, --login role can login (default)\n" msgstr " -l, --login el rol podrá conectarse (predeterminado)\n" -#: createuser.c:430 +#: createuser.c:432 #, c-format msgid " -L, --no-login role cannot login\n" msgstr " -L, --no-login el rol no podrá conectarse\n" -#: createuser.c:431 +#: createuser.c:433 #, c-format msgid " -m, --with-member=ROLE ROLE will be a member of new role\n" msgstr " -m, --with-member=ROL ROL será miembro del nuevo rol\n" -#: createuser.c:432 +#: createuser.c:434 #, c-format msgid " -P, --pwprompt assign a password to new role\n" msgstr " -P, --pwprompt asignar una contraseña al nuevo rol\n" -#: createuser.c:433 +#: createuser.c:435 #, c-format msgid " -r, --createrole role can create new roles\n" msgstr " -r, --createrole el rol podrá crear otros roles\n" -#: createuser.c:434 +#: createuser.c:436 #, c-format msgid " -R, --no-createrole role cannot create roles (default)\n" msgstr " -R, --no-createrole el rol no podrá crear otros roles (predeterminado)\n" -#: createuser.c:435 +#: createuser.c:437 #, c-format msgid " -s, --superuser role will be superuser\n" msgstr " -s, --superuser el rol será un superusuario\n" -#: createuser.c:436 +#: createuser.c:438 #, c-format msgid " -S, --no-superuser role will not be superuser (default)\n" msgstr " -S, --no-superuser el rol no será un superusuario (predeterminado)\n" -#: createuser.c:437 +#: createuser.c:439 #, c-format msgid "" " -v, --valid-until=TIMESTAMP\n" @@ -647,7 +719,7 @@ msgstr "" " -v, --valid-until=TIEMPO\n" " fecha/hora de expiración de contraseña para el rol\n" -#: createuser.c:440 +#: createuser.c:442 #, c-format msgid "" " --interactive prompt for missing role name and attributes rather\n" @@ -656,14 +728,14 @@ msgstr "" " --interactive preguntar los nombres y atributos de rol faltantes\n" " en lugar de asumir los valores por omisión\n" -#: createuser.c:442 +#: createuser.c:444 #, c-format msgid " --bypassrls role can bypass row-level security (RLS) policy\n" msgstr "" " --bypassrls el rol puede sobrepasar la política de\n" " seguridad de registros (RLS)\n" -#: createuser.c:443 +#: createuser.c:445 #, c-format msgid "" " --no-bypassrls role cannot bypass row-level security (RLS) policy\n" @@ -672,17 +744,17 @@ msgstr "" " --no-bypassrls el rol no puede sobrepasar la política de seguridad\n" " de registros (por omisión)\n" -#: createuser.c:445 +#: createuser.c:447 #, c-format msgid " --replication role can initiate replication\n" msgstr " --replication el rol podrá iniciar replicación\n" -#: createuser.c:446 +#: createuser.c:448 #, c-format msgid " --no-replication role cannot initiate replication (default)\n" msgstr " --no-replication el rol no puede iniciar replicación (por omisión)\n" -#: createuser.c:451 +#: createuser.c:453 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to create)\n" msgstr "" @@ -703,12 +775,12 @@ msgstr "La base de datos «%s» será eliminada permanentemente.\n" msgid "Are you sure?" msgstr "¿Está seguro?" -#: dropdb.c:157 +#: dropdb.c:156 #, c-format msgid "database removal failed: %s" msgstr "falló la eliminación de la base de datos: %s" -#: dropdb.c:171 +#: dropdb.c:170 #, c-format msgid "" "%s removes a PostgreSQL database.\n" @@ -717,22 +789,22 @@ msgstr "" "%s elimina una base de datos de PostgreSQL.\n" "\n" -#: dropdb.c:173 +#: dropdb.c:172 #, c-format msgid " %s [OPTION]... DBNAME\n" msgstr " %s [OPCIÓN]... BASE-DE-DATOS\n" -#: dropdb.c:176 +#: dropdb.c:175 #, c-format msgid " -f, --force try to terminate other connections before dropping\n" msgstr " -f, --force intentar cancelar otras conexiones antes de borrar\n" -#: dropdb.c:177 +#: dropdb.c:176 #, c-format msgid " -i, --interactive prompt before deleting anything\n" msgstr " -i, --interactive preguntar antes de eliminar\n" -#: dropdb.c:179 +#: dropdb.c:178 #, c-format msgid " --if-exists don't report error if database doesn't exist\n" msgstr " --if-exists no reportar error si la base de datos no existe\n" @@ -751,12 +823,12 @@ msgstr "falta el nombre de rol requerido" msgid "Role \"%s\" will be permanently removed.\n" msgstr "El rol «%s» será eliminado permanentemente.\n" -#: dropuser.c:154 +#: dropuser.c:155 #, c-format msgid "removal of role \"%s\" failed: %s" msgstr "falló la eliminación del rol «%s»: %s" -#: dropuser.c:169 +#: dropuser.c:170 #, c-format msgid "" "%s removes a PostgreSQL role.\n" @@ -765,7 +837,7 @@ msgstr "" "%s elimina un rol de PostgreSQL.\n" "\n" -#: dropuser.c:174 +#: dropuser.c:175 #, c-format msgid "" " -i, --interactive prompt before deleting anything, and prompt for\n" @@ -774,12 +846,12 @@ msgstr "" " -i, --interactive preguntar antes de eliminar cualquier cosa, y\n" " preguntar el nombre de rol si no se especifica\n" -#: dropuser.c:177 +#: dropuser.c:178 #, c-format msgid " --if-exists don't report error if user doesn't exist\n" msgstr " --if-exists no reportar error si el usuario no existe\n" -#: dropuser.c:182 +#: dropuser.c:183 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to drop)\n" msgstr "" @@ -872,94 +944,54 @@ msgstr "" msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USUARIO nombre de usuario para la conexión\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "no se puede reindexar todas las bases de datos y una de ellas en particular simultáneamente" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "no se puede reindexar todas las bases de datos y los catálogos del sistema simultáneamente" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "no es posible reindexar esquemas específicos en todas las bases de datos" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "no es posible reindexar tablas específicas en todas las bases de datos" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "no es posible reindexar índices específicos en todas las bases de datos" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "no es posible reindexar esquemas específicos y los catálogos del sistema simultáneamente" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "no es posible reindexar tablas específicas y los catálogos del sistema simultáneamente" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "no es posible reindexar índices específicos y los catálogos del sistema simultáneamente" - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "no se puede usar múltiples procesos para reindexar índices de sistema" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "no se puede usar múltiples procesos para reindexar índices" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "no se puede reindexar todas las bases de datos y una de ellas en particular simultáneamente" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:525 vacuumdb.c:532 vacuumdb.c:539 -#: vacuumdb.c:546 vacuumdb.c:553 vacuumdb.c:560 vacuumdb.c:567 vacuumdb.c:572 -#: vacuumdb.c:576 vacuumdb.c:580 vacuumdb.c:584 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:514 vacuumdb.c:521 vacuumdb.c:528 +#: vacuumdb.c:535 vacuumdb.c:542 vacuumdb.c:549 vacuumdb.c:556 vacuumdb.c:563 +#: vacuumdb.c:570 vacuumdb.c:577 vacuumdb.c:584 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "no se puede usar la opción «%s» cuando con versiones más antiguas que PostgreSQL %s" -#: reindexdb.c:561 +#: reindexdb.c:586 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "falló la reindexación de la base de datos «%s»: %s" -#: reindexdb.c:565 +#: reindexdb.c:590 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "falló la reindexación del índice «%s» en la base de datos «%s»: %s" -#: reindexdb.c:569 +#: reindexdb.c:594 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "falló la reindexación del esquema «%s» en la base de datos «%s»: %s" -#: reindexdb.c:573 +#: reindexdb.c:598 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "falló la reindexación de los catálogos de sistema en la base de datos «%s»: %s" -#: reindexdb.c:577 +#: reindexdb.c:602 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "falló la reindexación de la tabla «%s» en la base de datos «%s»: %s" -#: reindexdb.c:732 +#: reindexdb.c:832 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: reindexando la base de datos «%s»\n" -#: reindexdb.c:749 +#: reindexdb.c:875 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -968,62 +1000,62 @@ msgstr "" "%s reindexa una base de datos PostgreSQL.\n" "\n" -#: reindexdb.c:753 +#: reindexdb.c:879 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all reindexar todas las bases de datos\n" -#: reindexdb.c:754 +#: reindexdb.c:880 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently reindexar en modo concurrente\n" -#: reindexdb.c:755 +#: reindexdb.c:881 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=BASE-DATOS base de datos a reindexar\n" -#: reindexdb.c:757 +#: reindexdb.c:883 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=ÍNDICE recrear sólo este o estos índice(s)\n" -#: reindexdb.c:758 +#: reindexdb.c:884 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr " -j, --jobs=NÚM usar esta cantidad de conexiones concurrentes\n" -#: reindexdb.c:759 +#: reindexdb.c:885 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet no desplegar mensajes\n" -#: reindexdb.c:760 +#: reindexdb.c:886 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system sólo reindexar los catálogos del sistema\n" -#: reindexdb.c:761 +#: reindexdb.c:887 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=ESQUEMA reindexar sólo este o estos esquemas\n" -#: reindexdb.c:762 +#: reindexdb.c:888 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABLA reindexar sólo esta(s) tabla(s)\n" -#: reindexdb.c:763 +#: reindexdb.c:889 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " --tablespace=TABLESPACE tablespace donde se reconstruirán los índices\n" -#: reindexdb.c:764 +#: reindexdb.c:890 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose desplegar varios mensajes informativos\n" -#: reindexdb.c:774 +#: reindexdb.c:900 #, c-format msgid "" "\n" @@ -1032,95 +1064,80 @@ msgstr "" "\n" "Lea la descripción de la orden REINDEX de SQL para obtener mayores detalles.\n" -#: vacuumdb.c:312 vacuumdb.c:315 vacuumdb.c:318 vacuumdb.c:321 vacuumdb.c:324 -#: vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:342 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "no se puede usar la opción «%s» cuando se está sólo actualizando estadísticas" -#: vacuumdb.c:345 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "no se puede usar la opción «%s» cuando se está ejecutando vacuum full" -#: vacuumdb.c:351 vacuumdb.c:359 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "no se puede usar la opción «%s» junto con la opción «%s»" -#: vacuumdb.c:430 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "no se puede limpiar todas las bases de datos y una de ellas en particular simultáneamente" -#: vacuumdb.c:434 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "no es posible limpiar tablas específicas en todas las bases de datos" - -#: vacuumdb.c:438 -#, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "no es posible limpiar esquemas específicos en todas las bases de datos" - -#: vacuumdb.c:442 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "no es posible excluir esquemas específicos en todas las bases de datos" - -#: vacuumdb.c:446 +#: vacuumdb.c:436 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "no se puede limpiar todas las tablas en esquema(s) y tabla(s) específicas simultáneamente" -#: vacuumdb.c:450 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "no es posible limpiar tablas específicas y excluir esquema(s) simultáneamente" -#: vacuumdb.c:454 +#: vacuumdb.c:444 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "no se puede limpiar todas las tablas en esquema(s) y excluir esquema(s) simultáneamente" -#: vacuumdb.c:467 +#: vacuumdb.c:457 #, c-format msgid "out of memory" msgstr "memoria agotada" -#: vacuumdb.c:512 +#: vacuumdb.c:501 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Generando estadísticas mínimas para el optimizador (tamaño = 1)" -#: vacuumdb.c:513 +#: vacuumdb.c:502 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Generando estadísticas medias para el optimizador (tamaño = 10)" -#: vacuumdb.c:514 +#: vacuumdb.c:503 msgid "Generating default (full) optimizer statistics" msgstr "Generando estadísticas predeterminadas (completas) para el optimizador" -#: vacuumdb.c:593 +#: vacuumdb.c:594 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: procesando la base de datos «%s»: %s\n" -#: vacuumdb.c:596 +#: vacuumdb.c:597 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: limpiando la base de datos «%s»\n" -#: vacuumdb.c:1144 +#: vacuumdb.c:1159 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "falló la limpieza de la tabla «%s» en la base de datos «%s»: %s" -#: vacuumdb.c:1147 +#: vacuumdb.c:1162 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "falló la limpieza de la base de datos «%s»: %s" -#: vacuumdb.c:1155 +#: vacuumdb.c:1170 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1129,136 +1146,136 @@ msgstr "" "%s limpia (VACUUM) y analiza una base de datos PostgreSQL.\n" "\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1174 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all limpia todas las bases de datos\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1175 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=SZ tamaño de anillo de búfers a usar para vacuum\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1176 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=BASE base de datos a limpiar\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1177 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping desactiva todo comportamiento de saltar páginas\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1178 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo mostrar las órdenes enviadas al servidor\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1179 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full usar «vacuum full»\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1180 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze usar «vacuum freeze»\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1181 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr " --force-index-cleanup siempre eliminar entradas de índice que apunten a tuplas muertas\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1182 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr " -j, --jobs=NUM usar esta cantidad de conexiones concurrentes\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1183 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr " --min-mxid-age=EDAD_MXID edad de multixact ID mínima de tablas a limpiar\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1184 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr " --min-xid-age=EDAD_XID edad de ID de transacción mínima de tablas a limpiar\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1185 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr " --no-index-cleanup no eliminar entradas de índice que apunten a tuplas muertas\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1186 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main omitir la relación principal\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1187 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr " --no-process-toast omitir la tabla TOAST asociada con la tabla a la que se hará vacuum\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1188 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate no truncar las páginas vacías al final de la tabla\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1189 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" msgstr " -n, --schema=ESQUEMA limpia sólo tablas en el/los esquemas especificados\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1190 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" msgstr " -N, --exclude-schema=ESQUEMA no limpia tablas en el/los esquemas especificados\n" -#: vacuumdb.c:1176 +#: vacuumdb.c:1191 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr " -P, --parallel=NPROCS usar esta cantidad de procesos para vacuum, si están disponibles\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1192 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet no desplegar mensajes\n" -#: vacuumdb.c:1178 +#: vacuumdb.c:1193 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr " --skip-locked ignorar relaciones que no pueden bloquearse inmediatamente\n" -#: vacuumdb.c:1179 +#: vacuumdb.c:1194 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr "" " -t, --table='TABLA[(COLUMNAS)]'\n" " limpiar sólo esta(s) tabla(s)\n" -#: vacuumdb.c:1180 +#: vacuumdb.c:1195 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose desplegar varios mensajes informativos\n" -#: vacuumdb.c:1181 +#: vacuumdb.c:1196 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version mostrar información de versión y salir\n" -#: vacuumdb.c:1182 +#: vacuumdb.c:1197 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze actualizar las estadísticas del optimizador\n" -#: vacuumdb.c:1183 +#: vacuumdb.c:1198 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr "" " -Z, --analyze-only sólo actualizar las estadísticas del optimizador;\n" " no hacer vacuum\n" -#: vacuumdb.c:1184 +#: vacuumdb.c:1199 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1268,12 +1285,12 @@ msgstr "" " en múltiples etapas para resultados más rápidos;\n" " no hacer vacuum\n" -#: vacuumdb.c:1186 +#: vacuumdb.c:1201 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help mostrar esta ayuda y salir\n" -#: vacuumdb.c:1194 +#: vacuumdb.c:1209 #, c-format msgid "" "\n" diff --git a/src/bin/scripts/po/fr.po b/src/bin/scripts/po/fr.po index f17e17606ea11..1582cf94510a1 100644 --- a/src/bin/scripts/po/fr.po +++ b/src/bin/scripts/po/fr.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-10-29 17:19+0000\n" -"PO-Revision-Date: 2023-10-30 13:38+0100\n" +"POT-Creation-Date: 2024-08-23 14:21+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -21,7 +21,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.4\n" +"X-Generator: Poedit 3.5\n" #: ../../../src/common/logging.c:276 #, c-format @@ -54,6 +54,48 @@ msgstr "mémoire épuisée\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "n'a pas pu ouvrir le fichier « %s » : %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le système de fichiers pour le fichier « %s » : %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "n'a pas pu tester le fichier « %s » : %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "cette construction ne supporte pas la méthode de synchronisation « %s »" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "n'a pas pu ouvrir le répertoire « %s » : %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "n'a pas pu lire le répertoire « %s » : %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "n'a pas pu synchroniser sur disque (fsync) le fichier « %s » : %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "n'a pas pu renommer le fichier « %s » en « %s » : %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -68,11 +110,11 @@ msgstr "l'utilisateur n'existe pas" msgid "user name lookup failure: error code %lu" msgstr "échec de la recherche du nom d'utilisateur : code d'erreur %lu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Requête d'annulation envoyée\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "N'a pas pu envoyer la requête d'annulation : " @@ -100,6 +142,11 @@ msgstr "valeur « %s » invalide pour l'option %s" msgid "%s must be in range %d..%d" msgstr "%s doit être compris entre %d et %d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "méthode de synchronisation non reconnu : %s" + #: ../../fe_utils/parallel_slot.c:317 #, c-format msgid "too many jobs for this platform: %d" @@ -132,21 +179,26 @@ msgstr[1] "(%lu lignes)" msgid "Interrupted\n" msgstr "Interrompu\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Ne peut pas afficher le contenu de la table : le nombre de cellules %lld est égal à ou dépasse le maximum %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "" "Ne peut pas ajouter l'en-tête au contenu de la table : le nombre de colonnes\n" "%d est dépassé.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" msgstr "" "Ne peut pas ajouter une cellule au contenu de la table : le nombre total des\n" -"cellules %d est dépassé.\n" +"cellules %lld est dépassé.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "format de sortie invalide (erreur interne) : %d" @@ -161,36 +213,41 @@ msgstr "échec de la requête : %s" msgid "Query was: %s" msgstr "La requête était : %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "l'argument de la commande shell contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "le nom de la base contient un retour à la ligne ou un retour chariot : « %s »\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:279 vacuumdb.c:299 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Essayez « %s --help » pour plus d'informations." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:297 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "ne peut pas réorganiser à la fois toutes les bases de données et une base spécifique via la commande CLUSTER" -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "ne peut pas réorganiser la(les) table(s) spécifique(s) dans toutes les bases de données" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "la réorganisation de la table « %s » de la base de données « %s » avec la commande CLUSTER a échoué : %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "la réorganisation de la base de données « %s » via la commande CLUSTER a échoué : %s" @@ -200,7 +257,7 @@ msgstr "la réorganisation de la base de données « %s » via la commande CLUST msgid "%s: clustering database \"%s\"\n" msgstr "%s : réorganisation de la base de données « %s » via la commande CLUSTER\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -210,19 +267,19 @@ msgstr "" "base de données via la commande CLUSTER.\n" "\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1156 +#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 +#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 #, c-format msgid "Usage:\n" msgstr "Usage :\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1157 +#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [BASE]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1158 +#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 +#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 #, c-format msgid "" "\n" @@ -231,48 +288,48 @@ msgstr "" "\n" "Options :\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all réorganise toutes les bases de données\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=BASE réorganise la base de données spécifiée\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo affiche les commandes envoyées au serveur\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet n'écrit aucun message\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=TABLE réorganise uniquement la table spécifiée\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose mode verbeux\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1187 +#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 +#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 #, c-format msgid "" "\n" @@ -281,39 +338,39 @@ msgstr "" "\n" "Options de connexion :\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1188 +#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HÔTE hôte du serveur de bases de données ou\n" " répertoire des sockets\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1189 +#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT port du serveur de bases de données\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1190 +#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=UTILISATEUR nom d'utilisateur pour la connexion\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1191 +#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password empêche la demande d'un mot de passe\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1192 +#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password force la demande d'un mot de passe\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1193 +#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE indique une autre base par défaut\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "" "\n" @@ -322,8 +379,8 @@ msgstr "" "\n" "Lire la description de la commande SQL CLUSTER pour de plus amples détails.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1195 +#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 +#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 #, c-format msgid "" "\n" @@ -332,8 +389,8 @@ msgstr "" "\n" "Rapporter les bogues à <%s>.\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1196 +#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 +#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 #, c-format msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" @@ -367,22 +424,22 @@ msgstr "%s (%s/%s) " msgid "Please answer \"%s\" or \"%s\".\n" msgstr "Merci de répondre « %s » ou « %s ».\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "« %s » n'est pas un nom d'encodage valide" -#: createdb.c:250 +#: createdb.c:260 #, c-format msgid "database creation failed: %s" msgstr "la création de la base de données a échoué : %s" -#: createdb.c:269 +#: createdb.c:279 #, c-format msgid "comment creation failed (database was created): %s" msgstr "l'ajout du commentaire a échoué (la base de données a été créée) : %s" -#: createdb.c:287 +#: createdb.c:297 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -391,120 +448,125 @@ msgstr "" "%s crée une base de données PostgreSQL.\n" "\n" -#: createdb.c:289 +#: createdb.c:299 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [OPTION]... [BASE] [DESCRIPTION]\n" -#: createdb.c:291 +#: createdb.c:301 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=TABLESPACE tablespace par défaut de la base de données\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:302 reindexdb.c:874 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo affiche les commandes envoyées au serveur\n" -#: createdb.c:293 +#: createdb.c:303 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=ENCODAGE encodage de la base de données\n" -#: createdb.c:294 +#: createdb.c:304 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOCALE paramètre de la locale pour la base de données\n" -#: createdb.c:295 +#: createdb.c:305 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOCALE paramètre LC_COLLATE pour la base de données\n" -#: createdb.c:296 +#: createdb.c:306 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOCALE paramètre LC_CTYPE pour la base de données\n" -#: createdb.c:297 +#: createdb.c:307 +#, c-format +msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=LOCALE paramètre de la locale native pour la base de données\n" + +#: createdb.c:308 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE paramètre de la locale ICU pour la base de données\n" -#: createdb.c:298 +#: createdb.c:309 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" -msgstr " --icu-rules=RÈGLES configuration des règles ICU pour la base de données\n" +msgstr " --icu-rules=RÈGLES configuration des règles ICU pour la base de données\n" -#: createdb.c:299 +#: createdb.c:310 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default collation\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " fournisseur de locale pour la collation par défaut de la base de données\n" -#: createdb.c:301 +#: createdb.c:312 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr "" " -O, --owner=PROPRIÉTAIRE nom du propriétaire de la nouvelle base de\n" " données\n" -#: createdb.c:302 +#: createdb.c:313 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr " -S, --strategy=STRATEGIE stratégie de création de base (wal_log ou file_copy)\n" -#: createdb.c:303 +#: createdb.c:314 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=MODÈLE base de données modèle à copier\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:315 reindexdb.c:883 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:316 reindexdb.c:884 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:318 reindexdb.c:886 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HÔTE hôte du serveur de bases de données\n" " ou répertoire des sockets\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:319 reindexdb.c:887 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT port du serveur de bases de données\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:320 reindexdb.c:888 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=UTILISATEUR nom d'utilisateur pour la connexion\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:321 reindexdb.c:889 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password empêche la demande d'un mot de passe\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:322 reindexdb.c:890 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password force la demande d'un mot de passe\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:323 reindexdb.c:891 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=BASE indique une autre base par défaut\n" -#: createdb.c:313 +#: createdb.c:324 #, c-format msgid "" "\n" @@ -571,7 +633,7 @@ msgstr " %s [OPTION]... [RÔLE]\n" msgid "" " -a, --with-admin=ROLE ROLE will be a member of new role with admin\n" " option\n" -msgstr " -a, --with-admin=ROLE ROLE sera un membre du nouveau rôle avec l'option admin\n" +msgstr " -a, --with-admin=ROLE ROLE sera un membre du nouveau rôle avec l'option admin\n" #: createuser.c:420 #, c-format @@ -595,12 +657,12 @@ msgstr "" #: createuser.c:424 #, c-format msgid " -g, --member-of=ROLE new role will be a member of ROLE\n" -msgstr " -g, --member-of=ROLE le nouveau rôle sera un membre de ROLE\n" +msgstr " -g, --member-of=ROLE le nouveau rôle sera un membre de ROLE\n" #: createuser.c:425 #, c-format msgid " --role=ROLE (same as --member-of, deprecated)\n" -msgstr " --role=ROLE (identique à --member-of, obsolète)\n" +msgstr " --role=ROLE (identique à --member-of, obsolète)\n" #: createuser.c:426 #, c-format @@ -629,7 +691,7 @@ msgstr " -L, --no-login le rôle ne peut pas se connecter\n" #: createuser.c:431 #, c-format msgid " -m, --with-member=ROLE ROLE will be a member of new role\n" -msgstr " -m, --with-member=ROLE ROLE sera un membre du nouveau rôle\n" +msgstr " -m, --with-member=ROLE ROLE sera un membre du nouveau rôle\n" #: createuser.c:432 #, c-format @@ -663,9 +725,7 @@ msgstr "" msgid "" " -v, --valid-until=TIMESTAMP\n" " password expiration date and time for role\n" -msgstr "" -" -v, --valid-until=TIMESTAMP\n" -" date et heure d'expiration du mot de passe pour le rôle\n" +msgstr " -v, --valid-until=TIMESTAMP date et heure d'expiration du mot de passe pour le rôle\n" #: createuser.c:440 #, c-format @@ -679,7 +739,7 @@ msgstr "" #: createuser.c:442 #, c-format msgid " --bypassrls role can bypass row-level security (RLS) policy\n" -msgstr " --bypassrls le rôle peut contourner la politique de sécurité niveau ligne (RLS)\n" +msgstr " --bypassrls le rôle peut contourner la politique de sécurité niveau ligne (RLS)\n" #: createuser.c:443 #, c-format @@ -687,8 +747,8 @@ msgid "" " --no-bypassrls role cannot bypass row-level security (RLS) policy\n" " (default)\n" msgstr "" -" --no-bypassrls le rôle ne peut pas contourner la politique de sécurité niveau ligne (RLS)\n" -" (par défaut)\n" +" --no-bypassrls le rôle ne peut pas contourner la politique de sécurité niveau ligne (RLS)\n" +" (par défaut)\n" #: createuser.c:445 #, c-format @@ -905,94 +965,54 @@ msgstr "" msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=UTILISATEUR nom d'utilisateur pour la connexion\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "ne peut pas réindexer toutes les bases de données et une base spécifique en même temps" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "ne peut pas réindexer toutes les bases de données et les catalogues système en même temps" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "ne peut pas réindexer un (des) schéma(s) spécifique(s) dans toutes les bases de données" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "ne peut pas réindexer une (des) table(s) spécifique(s) dans toutes les bases de données" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "ne peut pas réindexer un (des) index spécifique(s) dans toutes les bases de données" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "ne peut pas réindexer un (des) schéma(s) spécifique(s) et les catalogues système en même temps" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "ne peut pas réindexer une (des) table(s) spécifique(s) etles catalogues système en même temps" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "ne peut pas réindexer un (des) index spécifique(s) et les catalogues système en même temps" - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "ne peut pas utiliser plusieurs jobs pour réindexer les catalogues systèmes" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "ne peut pas utiliser plusieurs jobs pour réindexer les index" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "ne peut pas réindexer toutes les bases de données et une base spécifique en même temps" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:525 vacuumdb.c:532 vacuumdb.c:539 -#: vacuumdb.c:546 vacuumdb.c:553 vacuumdb.c:560 vacuumdb.c:567 vacuumdb.c:572 -#: vacuumdb.c:576 vacuumdb.c:580 vacuumdb.c:584 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 +#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 +#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "ne peut utiliser l'option « %s » sur des versions serveurs plus anciennes que PostgreSQL %s" -#: reindexdb.c:561 +#: reindexdb.c:584 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "la réindexation de la base de données « %s » a échoué : %s" -#: reindexdb.c:565 +#: reindexdb.c:588 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "la réindexation de l'index « %s » dans la base de données « %s » a échoué : %s" -#: reindexdb.c:569 +#: reindexdb.c:592 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "la réindexation du schéma « %s » dans la base de données « %s » a échoué : %s" -#: reindexdb.c:573 +#: reindexdb.c:596 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "la réindexation des catalogues systèmes dans la base de données « %s » a échoué : %s" -#: reindexdb.c:577 +#: reindexdb.c:600 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "la réindexation de la table « %s » dans la base de données « %s » a échoué : %s" -#: reindexdb.c:732 +#: reindexdb.c:824 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s : réindexation de la base de données « %s »\n" -#: reindexdb.c:749 +#: reindexdb.c:867 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -1001,66 +1021,66 @@ msgstr "" "%s réindexe une base de données PostgreSQL.\n" "\n" -#: reindexdb.c:753 +#: reindexdb.c:871 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all réindexe toutes les bases de données\n" -#: reindexdb.c:754 +#: reindexdb.c:872 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently réindexation en concurrence\n" -#: reindexdb.c:755 +#: reindexdb.c:873 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=BASE réindexe la base de données spécifiée\n" -#: reindexdb.c:757 +#: reindexdb.c:875 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX réindexe uniquement l'index spécifié\n" -#: reindexdb.c:758 +#: reindexdb.c:876 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr "" " -j, --jobs=NOMBRE utilise ce nombre de connexions concurrentes\n" " pour l'opération de réindexation\n" -#: reindexdb.c:759 +#: reindexdb.c:877 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet n'écrit aucun message\n" -#: reindexdb.c:760 +#: reindexdb.c:878 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system réindexe seulement les catalogues système\n" -#: reindexdb.c:761 +#: reindexdb.c:879 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHÉMA réindexe uniquement le schéma spécifié\n" -#: reindexdb.c:762 +#: reindexdb.c:880 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABLE réindexe uniquement la table spécifiée\n" -#: reindexdb.c:763 +#: reindexdb.c:881 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr "" " --tablespace=TABLESPACE précise le tablespace où les index seront\n" " reconstruits\n" -#: reindexdb.c:764 +#: reindexdb.c:882 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose mode verbeux\n" -#: reindexdb.c:774 +#: reindexdb.c:892 #, c-format msgid "" "\n" @@ -1069,95 +1089,80 @@ msgstr "" "\n" "Lire la description de la commande SQL REINDEX pour plus d'informations.\n" -#: vacuumdb.c:312 vacuumdb.c:315 vacuumdb.c:318 vacuumdb.c:321 vacuumdb.c:324 -#: vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:342 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "ne peut pas utiliser l'option « %s » lors de l'exécution d'un ANALYZE seul" -#: vacuumdb.c:345 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "ne peut pas utiliser l'option « %s » lors de l'exécution d'un VACUUM FULL" -#: vacuumdb.c:351 vacuumdb.c:359 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "ne peut pas utiliser l'option « %s » lors de l'option « %s »" -#: vacuumdb.c:430 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "ne peut pas exécuter VACUUM sur toutes les bases de données et sur une base spécifique en même temps" -#: vacuumdb.c:434 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "ne peut pas exécuter VACUUM sur une(des) table(s) spécifique(s) dans toutes les bases de données" - -#: vacuumdb.c:438 -#, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "ne peut pas exécuter VACUUM sur les schémas spécifiques dans toutes les bases de données" - -#: vacuumdb.c:442 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "ne peut pas exclure des schémas dans toutes les bases de données" - -#: vacuumdb.c:446 +#: vacuumdb.c:436 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "ne peut pas exécuter VACUUM sur toutes les tables des schémas et sur des tables spécifiques en même temps" -#: vacuumdb.c:450 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "ne peut pas exécuter VACUUM sur des tables spécifiques et exclure des schémas en même temps" -#: vacuumdb.c:454 +#: vacuumdb.c:444 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "ne peut pas exécuter VACUUM sur toutes les tables et exclure des schémas en même temps" -#: vacuumdb.c:467 +#: vacuumdb.c:457 #, c-format msgid "out of memory" msgstr "mémoire épuisée" -#: vacuumdb.c:512 +#: vacuumdb.c:502 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Génération de statistiques minimales pour l'optimiseur (une cible)" -#: vacuumdb.c:513 +#: vacuumdb.c:503 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Génération de statistiques moyennes pour l'optimiseur (dix cibles)" -#: vacuumdb.c:514 +#: vacuumdb.c:504 msgid "Generating default (full) optimizer statistics" msgstr "Génération de statistiques complètes pour l'optimiseur" -#: vacuumdb.c:593 +#: vacuumdb.c:583 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s : traitement de la base de données « %s » %s\n" -#: vacuumdb.c:596 +#: vacuumdb.c:586 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s : exécution de VACUUM sur la base de données « %s »\n" -#: vacuumdb.c:1144 +#: vacuumdb.c:1135 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "l'exécution de VACUUM sur la table « %s » dans la base de données « %s » a échoué : %s" -#: vacuumdb.c:1147 +#: vacuumdb.c:1138 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "l'exécution de VACUUM sur la base de données « %s » a échoué : %s" -#: vacuumdb.c:1155 +#: vacuumdb.c:1146 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1166,154 +1171,154 @@ msgstr "" "%s nettoie et analyse une base de données PostgreSQL.\n" "\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1150 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all exécute VACUUM sur toutes les bases de données\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1151 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=TAILLE taille du buffer spécialisé pour VACUUM\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1152 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=BASE exécute VACUUM sur cette base de données\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1153 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping désactive le comportement page-skipping\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1154 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo affiche les commandes envoyées au serveur\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1155 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full exécute VACUUM en mode FULL\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1156 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr "" " -F, --freeze gèle les informations de transactions des\n" " lignes\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1157 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr "" " --force-index-cleanup supprime toujours les enregistrements dans\n" " l'index pointant vers des lignes mortes\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1158 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr "" " -j, --jobs=NOMBRE utilise ce nombre de connexions concurrentes\n" " pour le VACUUM\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1159 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr "" " --min-mxid-age=MXID_AGE âge minimum des identifiants de\n" " multitransactions pour les tables à nettoyer\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1160 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr "" " --min-xid-age=XID_AGE âge minimum des identifiants de transactions\n" " pour les tables à nettoyer\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1161 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr "" " --no-index-cleanup ne supprime pas les enregistrements dans\n" " l'index pointant vers des lignes mortes\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1162 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main ignore la relation principale\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1163 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr "" " --no-process-toast ignore la table TOAST associée à la table à\n" " traiter\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1164 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr "" " --no-truncate ne supprime pas les pages vides à la fin de\n" " la table\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1165 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" msgstr " -n, --schema=MOTIF exécute VACUUM uniquement sur les tables des schémas indiqués\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1166 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" msgstr " -N, --exclude-schema=MOTIF n'exécute pas VACUUM sur les tables des schémas indiqués\n" -#: vacuumdb.c:1176 +#: vacuumdb.c:1167 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr "" " -P, --parallel=NOMBRE utilise ce nombre de processus en tâche de\n" " fond pour le VACUUM, si possible\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1168 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet n'écrit aucun message\n" -#: vacuumdb.c:1178 +#: vacuumdb.c:1169 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr "" " --skip-locked ignore les relations qui ne peuvent pas être\n" " verrouillées immédiatement\n" -#: vacuumdb.c:1179 +#: vacuumdb.c:1170 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='TABLE[(COLONNES)]' exécute VACUUM sur cette table\n" -#: vacuumdb.c:1180 +#: vacuumdb.c:1171 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose mode verbeux\n" -#: vacuumdb.c:1181 +#: vacuumdb.c:1172 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version affiche la version puis quitte\n" -#: vacuumdb.c:1182 +#: vacuumdb.c:1173 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze met à jour les statistiques de l'optimiseur\n" -#: vacuumdb.c:1183 +#: vacuumdb.c:1174 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr "" " -Z, --analyze-only met seulement à jour les statistiques de\n" " l'optimiseur ; pas de VACUUM\n" -#: vacuumdb.c:1184 +#: vacuumdb.c:1175 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1323,12 +1328,12 @@ msgstr "" " l'optimiseur, en plusieurs étapes pour de\n" " meilleurs résultats ; pas de VACUUM\n" -#: vacuumdb.c:1186 +#: vacuumdb.c:1177 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help affiche cette aide puis quitte\n" -#: vacuumdb.c:1194 +#: vacuumdb.c:1185 #, c-format msgid "" "\n" @@ -1336,203 +1341,3 @@ msgid "" msgstr "" "\n" "Lire la description de la commande SQL VACUUM pour plus d'informations.\n" - -#~ msgid "" -#~ "\n" -#~ "If one of -d, -D, -r, -R, -s, -S, and ROLENAME is not specified, you will\n" -#~ "be prompted interactively.\n" -#~ msgstr "" -#~ "\n" -#~ "Si une des options -d, -D, -r, -R, -s, -S et RÔLE n'est pas précisée,\n" -#~ "elle sera demandée interactivement.\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid " %s [OPTION]... LANGNAME [DBNAME]\n" -#~ msgstr " %s [OPTION]... NOMLANGAGE [BASE]\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --help show this help, then exit\n" -#~ msgstr " --help affiche cette aide et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid " -E, --encrypted encrypt stored password\n" -#~ msgstr " -E, --encrypted chiffre le mot de passe stocké\n" - -#~ msgid " -N, --unencrypted do not encrypt stored password\n" -#~ msgstr " -N, --unencrypted ne chiffre pas le mot de passe stocké\n" - -#~ msgid " -d, --dbname=DBNAME database from which to remove the language\n" -#~ msgstr "" -#~ " -d, --dbname=BASE base de données à partir de laquelle\n" -#~ " supprimer le langage\n" - -#~ msgid " -d, --dbname=DBNAME database to install language in\n" -#~ msgstr " -d, --dbname=BASE base sur laquelle installer le langage\n" - -#~ msgid " -l, --list show a list of currently installed languages\n" -#~ msgstr "" -#~ " -l, --list affiche la liste des langages déjà\n" -#~ " installés\n" - -#~ msgid "" -#~ "%s installs a procedural language into a PostgreSQL database.\n" -#~ "\n" -#~ msgstr "" -#~ "%s installe un langage de procédures dans une base de données PostgreSQL.\n" -#~ "\n" - -#~ msgid "" -#~ "%s removes a procedural language from a database.\n" -#~ "\n" -#~ msgstr "" -#~ "%s supprime un langage procédural d'une base de données.\n" -#~ "\n" - -#~ msgid "%s: \"%s\" is not a valid encoding name\n" -#~ msgstr "%s : « %s » n'est pas un nom d'encodage valide\n" - -#~ msgid "%s: %s" -#~ msgstr "%s : %s" - -#~ msgid "%s: cannot use the \"freeze\" option when performing only analyze\n" -#~ msgstr "" -#~ "%s : ne peut utiliser l'option « freeze » lors de l'exécution d'un ANALYZE\n" -#~ "seul\n" - -#~ msgid "%s: could not get current user name: %s\n" -#~ msgstr "%s : n'a pas pu récupérer le nom de l'utilisateur actuel : %s\n" - -#~ msgid "%s: could not obtain information about current user: %s\n" -#~ msgstr "%s : n'a pas pu obtenir les informations concernant l'utilisateur actuel : %s\n" - -#~ msgid "%s: invalid socket: %s" -#~ msgstr "%s : socket invalide : %s" - -#~ msgid "%s: language \"%s\" is already installed in database \"%s\"\n" -#~ msgstr "%s : le langage « %s » est déjà installé sur la base de données « %s »\n" - -#~ msgid "%s: language \"%s\" is not installed in database \"%s\"\n" -#~ msgstr "%s : le langage « %s » n'est pas installé dans la base de données « %s »\n" - -#~ msgid "%s: language installation failed: %s" -#~ msgstr "%s : l'installation du langage a échoué : %s" - -#~ msgid "%s: language removal failed: %s" -#~ msgstr "%s : la suppression du langage a échoué : %s" - -#~ msgid "%s: missing required argument language name\n" -#~ msgstr "%s : argument nom du langage requis mais manquant\n" - -#~ msgid "%s: out of memory\n" -#~ msgstr "%s : mémoire épuisée\n" - -#~ msgid "%s: query failed: %s" -#~ msgstr "%s : échec de la requête : %s" - -#~ msgid "%s: query returned %d row instead of one: %s\n" -#~ msgid_plural "%s: query returned %d rows instead of one: %s\n" -#~ msgstr[0] "%s : la requête a renvoyé %d ligne au lieu d'une seule : %s\n" -#~ msgstr[1] "%s : la requête a renvoyé %d lignes au lieu d'une seule : %s\n" - -#~ msgid "%s: query was: %s\n" -#~ msgstr "%s : la requête était : %s\n" - -#~ msgid "%s: still %s functions declared in language \"%s\"; language not removed\n" -#~ msgstr "" -#~ "%s : il existe encore %s fonctions déclarées dans le langage « %s » ;\n" -#~ "langage non supprimé\n" - -#~ msgid "%s: too many command-line arguments (first is \"%s\")\n" -#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n" - -#~ msgid "%s: too many parallel jobs requested (maximum: %d)\n" -#~ msgstr "%s : trop de jobs en parallèle demandés (maximum %d)\n" - -#~ msgid "Could not send cancel request: %s" -#~ msgstr "N'a pas pu envoyer la requête d'annulation : %s" - -#~ msgid "Name" -#~ msgstr "Nom" - -#~ msgid "Procedural Languages" -#~ msgstr "Langages procéduraux" - -#~ msgid "Trusted?" -#~ msgstr "De confiance (trusted) ?" - -#, c-format -#~ msgid "Try \"%s --help\" for more information.\n" -#~ msgstr "Essayer « %s --help » pour plus d'informations.\n" - -#, c-format -#~ msgid "cannot reindex system catalogs concurrently, skipping all" -#~ msgstr "ne peut pas réindexer les catalogues système de manière concurrente, ignore tout" - -#~ msgid "could not connect to database %s: %s" -#~ msgstr "n'a pas pu se connecter à la base de données %s : %s" - -#, c-format -#~ msgid "fatal: " -#~ msgstr "fatal : " - -#, c-format -#~ msgid "invalid value for --connection-limit: %s" -#~ msgstr "valeur invalide pour --connection-limit : %s" - -#, c-format -#~ msgid "minimum multixact ID age must be at least 1" -#~ msgstr "l'âge minimum de l'identifiant de multitransaction doit au moins être 1" - -#, c-format -#~ msgid "minimum transaction ID age must be at least 1" -#~ msgstr "l'identifiant de la transaction (-x) doit valoir au moins 1" - -#~ msgid "no" -#~ msgstr "non" - -#, c-format -#~ msgid "number of parallel jobs must be at least 1" -#~ msgstr "le nombre maximum de jobs en parallèle doit être au moins de 1" - -#, c-format -#~ msgid "only one of --locale and --lc-collate can be specified" -#~ msgstr "une seule des options --locale et --lc-collate peut être indiquée" - -#, c-format -#~ msgid "only one of --locale and --lc-ctype can be specified" -#~ msgstr "une seule des options --locale et --lc-ctype peut être indiquée" - -#~ msgid "parallel vacuum degree must be a non-negative integer" -#~ msgstr "le degré de parallélisation du VACUUM doit être un entier non négatif" - -#, c-format -#~ msgid "parallel workers for vacuum must be greater than or equal to zero" -#~ msgstr "le nombre de processus parallélisés pour l VACUUM doit être supérieur à zéro" - -#~ msgid "pg_strdup: cannot duplicate null pointer (internal error)\n" -#~ msgstr "pg_strdup : ne peut pas dupliquer un pointeur nul (erreur interne)\n" - -#~ msgid "reindexing of system catalogs failed: %s" -#~ msgstr "la réindexation des catalogues système a échoué : %s" - -#~ msgid "yes" -#~ msgstr "oui" diff --git a/src/bin/scripts/po/ja.po b/src/bin/scripts/po/ja.po index f9b6d53773052..1b6a7b9f99935 100644 --- a/src/bin/scripts/po/ja.po +++ b/src/bin/scripts/po/ja.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: scripts (PostgreSQL 17)\n" +"Project-Id-Version: scripts (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:24+0900\n" -"PO-Revision-Date: 2024-06-14 11:31+0900\n" +"POT-Creation-Date: 2025-03-31 09:54+0900\n" +"PO-Revision-Date: 2025-03-31 16:30+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: jpug-doc \n" "Language: ja\n" @@ -20,22 +20,22 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "エラー: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "警告: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "詳細: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "ヒント: " @@ -51,44 +51,44 @@ msgstr "メモリ不足です\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "nullポインタを複製できません(内部エラー)。\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ファイル\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "ファイル\"%s\"に対してファイルシステムを同期できませんでした: %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ファイル\"%s\"のstatに失敗しました: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "このビルドでは同期方式\"%s\"をサポートしていません" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #, c-format msgid "could not open directory \"%s\": %m" msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ファイル\"%s\"をfsyncできませんでした: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "ファイル\"%s\"の名前を\"%s\"に変更できませんでした: %m" @@ -177,8 +177,8 @@ msgstr "中断されました\n" #: ../../fe_utils/print.c:3188 #, c-format -msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" -msgstr "テーブルの内容を表示できません: セル数%lldが上限値%lld以上です。\n" +msgid "Cannot print table contents: number of cells % is equal to or exceeds maximum %zu.\n" +msgstr "テーブルの内容を表示できません: セル数%が上限値%zu以上です。\n" #: ../../fe_utils/print.c:3229 #, c-format @@ -187,8 +187,8 @@ msgstr "テーブルの内容に見出しを追加できませんでした:列 #: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" -msgstr "テーブルの内容にセルを追加できません: セルの総数%lldを超過しています。\n" +msgid "Cannot add cell to table content: total cell count of % exceeded.\n" +msgstr "テーブルの内容にセルを追加できません: セルの総数%を超過しています。\n" #: ../../fe_utils/print.c:3530 #, c-format @@ -205,70 +205,70 @@ msgstr "問い合わせが失敗しました: %s" msgid "Query was: %s" msgstr "問い合わせ: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "シェルコマンドの引数に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "データベース名に改行(LF)または復帰(CR)が含まれています: \"%s\"\n" -#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 +#: clusterdb.c:113 clusterdb.c:132 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 +#: reindexdb.c:184 reindexdb.c:203 vacuumdb.c:291 vacuumdb.c:311 #, c-format msgid "Try \"%s --help\" for more information." msgstr "詳細は\"%s --help\"を実行してください。" -#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 +#: clusterdb.c:130 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:201 vacuumdb.c:309 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "コマンドライン引数が多すぎます。(先頭は\"%s\")" -#: clusterdb.c:149 +#: clusterdb.c:148 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "全データベースと特定のデータベースを同時にクラスタ化することはできません" -#: clusterdb.c:214 +#: clusterdb.c:213 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "データベース\"%2$s\"のテーブル\"%1$s\"のクラスタ化に失敗しました: %3$s" -#: clusterdb.c:217 +#: clusterdb.c:216 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "データベース\"%s\"のクラスタ化に失敗しました: %s" -#: clusterdb.c:248 +#: clusterdb.c:247 #, c-format msgid "%s: clustering database \"%s\"\n" msgstr "%s: データベース\"%s\"をクラスタ化しています\n" -#: clusterdb.c:274 +#: clusterdb.c:273 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" "\n" msgstr "%sはデータベース内で事前にクラスタ化されているすべてのテーブルをクラスタ化します。\n" -#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 +#: clusterdb.c:274 createdb.c:300 createuser.c:417 dropdb.c:171 dropuser.c:171 +#: pg_isready.c:226 reindexdb.c:898 vacuumdb.c:1337 #, c-format msgid "Usage:\n" msgstr "使用方法:\n" -#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 +#: clusterdb.c:275 reindexdb.c:899 vacuumdb.c:1338 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [オプション]... [データベース名]\n" -#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 +#: clusterdb.c:276 createdb.c:302 createuser.c:419 dropdb.c:173 dropuser.c:173 +#: pg_isready.c:229 reindexdb.c:900 vacuumdb.c:1339 #, c-format msgid "" "\n" @@ -277,48 +277,48 @@ msgstr "" "\n" "オプション:\n" -#: clusterdb.c:278 +#: clusterdb.c:277 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all すべてのデータベースをクラスタ化\n" -#: clusterdb.c:279 +#: clusterdb.c:278 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=DBNAME クラスタ化するデータベース\n" -#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:279 createuser.c:425 dropdb.c:174 dropuser.c:174 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo サーバーへ送信されるコマンドを表示\n" -#: clusterdb.c:281 +#: clusterdb.c:280 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet メッセージを何も出力しない\n" -#: clusterdb.c:282 +#: clusterdb.c:281 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=テーブル名 指定したテーブル(群)のみをクラスタ化\n" -#: clusterdb.c:283 +#: clusterdb.c:282 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 多量のメッセージを出力\n" -#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:283 createuser.c:441 dropdb.c:177 dropuser.c:177 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:284 createuser.c:449 dropdb.c:179 dropuser.c:179 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 +#: clusterdb.c:285 createdb.c:319 createuser.c:450 dropdb.c:180 dropuser.c:180 +#: pg_isready.c:235 reindexdb.c:915 vacuumdb.c:1369 #, c-format msgid "" "\n" @@ -327,39 +327,39 @@ msgstr "" "\n" "接続オプション:\n" -#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 +#: clusterdb.c:286 createuser.c:451 dropdb.c:181 dropuser.c:181 vacuumdb.c:1370 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME データベースサーバーのホストまたはソケット\n" " ディレクトリ\n" -#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 +#: clusterdb.c:287 createuser.c:452 dropdb.c:182 dropuser.c:182 vacuumdb.c:1371 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT データベースサーバーのポート番号\n" -#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 +#: clusterdb.c:288 dropdb.c:183 vacuumdb.c:1372 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME このユーザー名で接続\n" -#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 +#: clusterdb.c:289 createuser.c:454 dropdb.c:184 dropuser.c:184 vacuumdb.c:1373 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password パスワード入力を要求しない\n" -#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 +#: clusterdb.c:290 createuser.c:455 dropdb.c:185 dropuser.c:185 vacuumdb.c:1374 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password パスワードプロンプトを強制表示\n" -#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 +#: clusterdb.c:291 dropdb.c:186 vacuumdb.c:1375 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME 別の保守用データベースを指定\n" -#: clusterdb.c:293 +#: clusterdb.c:292 #, c-format msgid "" "\n" @@ -368,8 +368,8 @@ msgstr "" "\n" "詳細は SQL コマンドの CLUSTER の説明を参照してください。\n" -#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 +#: clusterdb.c:293 createdb.c:327 createuser.c:456 dropdb.c:187 dropuser.c:186 +#: pg_isready.c:240 reindexdb.c:923 vacuumdb.c:1377 #, c-format msgid "" "\n" @@ -378,13 +378,13 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 +#: clusterdb.c:294 createdb.c:328 createuser.c:457 dropdb.c:188 dropuser.c:187 +#: pg_isready.c:241 reindexdb.c:924 vacuumdb.c:1378 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: common.c:107 +#: common.c:106 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" @@ -417,17 +417,17 @@ msgstr " \"%s\" または \"%s\" に答えてください\n" msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" は有効な符号化方式名ではありません" -#: createdb.c:260 +#: createdb.c:262 #, c-format msgid "database creation failed: %s" msgstr "データベースの生成に失敗しました:%s" -#: createdb.c:279 +#: createdb.c:281 #, c-format msgid "comment creation failed (database was created): %s" msgstr "コメントの生成に失敗(データベースは生成されました): %s" -#: createdb.c:297 +#: createdb.c:299 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -436,57 +436,57 @@ msgstr "" "%sはPostgreSQLデータベースを生成します。\n" "\n" -#: createdb.c:299 +#: createdb.c:301 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [オプション]... [データベース名] [説明]\n" -#: createdb.c:301 +#: createdb.c:303 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=TABLESPACE データベースのデフォルトテーブルスペース名\n" -#: createdb.c:302 reindexdb.c:874 +#: createdb.c:304 reindexdb.c:904 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo サーバーへ送信されるコマンドを表示\n" -#: createdb.c:303 +#: createdb.c:305 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=ENCODING データベースの符号化方式\n" -#: createdb.c:304 +#: createdb.c:306 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOCALE データベースのロケール設定\n" -#: createdb.c:305 +#: createdb.c:307 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOCALE データベースのLC_COLLATE設定\n" -#: createdb.c:306 +#: createdb.c:308 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOCALE データベースのLC_CTYPE設定\n" -#: createdb.c:307 +#: createdb.c:309 #, c-format msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" msgstr " --builtin-locale=LOCALE データベースの組み込みロケールを指定\n" -#: createdb.c:308 +#: createdb.c:310 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE データベースのICUロケールを指定\n" -#: createdb.c:309 +#: createdb.c:311 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=RULES データベースのICUルール(群)を設定\n" -#: createdb.c:310 +#: createdb.c:312 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -496,64 +496,64 @@ msgstr "" " データベースのデフォルト照合順序のロケール\n" " プロバイダ\n" -#: createdb.c:312 +#: createdb.c:314 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --owner=OWNER 新しいデータベースを所有するデータベースユーザー\n" -#: createdb.c:313 +#: createdb.c:315 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr " -S, --strategy=STRATEGY データベース生成方法 wal_log または file_copy\n" -#: createdb.c:314 +#: createdb.c:316 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=TEMPLATE コピーするテンプレートデータベース\n" -#: createdb.c:315 reindexdb.c:883 +#: createdb.c:317 reindexdb.c:913 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: createdb.c:316 reindexdb.c:884 +#: createdb.c:318 reindexdb.c:914 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: createdb.c:318 reindexdb.c:886 +#: createdb.c:320 reindexdb.c:916 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME データベースサーバーホストまたはソケット\n" " ディレクトリ\n" -#: createdb.c:319 reindexdb.c:887 +#: createdb.c:321 reindexdb.c:917 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT データベースサーバーのポート番号\n" -#: createdb.c:320 reindexdb.c:888 +#: createdb.c:322 reindexdb.c:918 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME 接続する際のユーザー名\n" -#: createdb.c:321 reindexdb.c:889 +#: createdb.c:323 reindexdb.c:919 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password パスワード入力を要求しない\n" -#: createdb.c:322 reindexdb.c:890 +#: createdb.c:324 reindexdb.c:920 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password パスワードプロンプトを強制\n" -#: createdb.c:323 reindexdb.c:891 +#: createdb.c:325 reindexdb.c:921 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME 別の保守用データベースを指定\n" -#: createdb.c:324 +#: createdb.c:326 #, c-format msgid "" "\n" @@ -591,17 +591,17 @@ msgstr "新しいロールに対してデータベースを作成する権限を msgid "Shall the new role be allowed to create more new roles?" msgstr "新しいロールに対して別のロールを作成する権限を与えますか?" -#: createuser.c:309 +#: createuser.c:311 #, c-format msgid "password encryption failed: %s" msgstr "パスワードの暗号化に失敗しました: %s" -#: createuser.c:400 +#: createuser.c:402 #, c-format msgid "creation of new role failed: %s" msgstr "新しいロールの作成に失敗しました: %s" -#: createuser.c:414 +#: createuser.c:416 #, c-format msgid "" "%s creates a new PostgreSQL role.\n" @@ -610,12 +610,12 @@ msgstr "" "%sは新しいPostgreSQLロールを作成します。\n" "\n" -#: createuser.c:416 dropuser.c:171 +#: createuser.c:418 dropuser.c:172 #, c-format msgid " %s [OPTION]... [ROLENAME]\n" msgstr " %s [オプション]... [ロール名]\n" -#: createuser.c:418 +#: createuser.c:420 #, c-format msgid "" " -a, --with-admin=ROLE ROLE will be a member of new role with admin\n" @@ -624,32 +624,32 @@ msgstr "" " -a, --with-admin=ROLE ROLEは新しいロールのADMINオプション付きの\n" " メンバーとなる\n" -#: createuser.c:420 +#: createuser.c:422 #, c-format msgid " -c, --connection-limit=N connection limit for role (default: no limit)\n" msgstr " -c, --connection-limit=N ロールのコネクション数制限(デフォルト: 制限なし)\n" -#: createuser.c:421 +#: createuser.c:423 #, c-format msgid " -d, --createdb role can create new databases\n" msgstr " -d, --createdb ロールは新しいデータベースを作成可\n" -#: createuser.c:422 +#: createuser.c:424 #, c-format msgid " -D, --no-createdb role cannot create databases (default)\n" msgstr " -D, --no-createdb ロールは新しいデータベースを作成不可(デフォルト)\n" -#: createuser.c:424 +#: createuser.c:426 #, c-format msgid " -g, --member-of=ROLE new role will be a member of ROLE\n" msgstr " -g, --member-of=ROLE 新しいロールをROLEのメンバーにする\n" -#: createuser.c:425 +#: createuser.c:427 #, c-format msgid " --role=ROLE (same as --member-of, deprecated)\n" msgstr " --role=ROLE (--member-ofに同じ、非推奨)\n" -#: createuser.c:426 +#: createuser.c:428 #, c-format msgid "" " -i, --inherit role inherits privileges of roles it is a\n" @@ -658,52 +658,52 @@ msgstr "" " -i, --inherit ロールがメンバーとなるロール群から権限を継承\n" " (デフォルト)\n" -#: createuser.c:428 +#: createuser.c:430 #, c-format msgid " -I, --no-inherit role does not inherit privileges\n" msgstr " -I, --no-inherit 権限を継承しない\n" -#: createuser.c:429 +#: createuser.c:431 #, c-format msgid " -l, --login role can login (default)\n" msgstr " -l, --login ロールはログイン可能(デフォルト)\n" -#: createuser.c:430 +#: createuser.c:432 #, c-format msgid " -L, --no-login role cannot login\n" msgstr " -L, --no-login ロールはログイン不可\n" -#: createuser.c:431 +#: createuser.c:433 #, c-format msgid " -m, --with-member=ROLE ROLE will be a member of new role\n" msgstr " -m, --with-member=ROLE ROLEは新しいロールのメンバとなる\n" -#: createuser.c:432 +#: createuser.c:434 #, c-format msgid " -P, --pwprompt assign a password to new role\n" msgstr " -P, --pwprompt 新しいロールにパスワードを割り当てる\n" -#: createuser.c:433 +#: createuser.c:435 #, c-format msgid " -r, --createrole role can create new roles\n" msgstr " -r, --createrole ロールは別のロールを作成可\n" -#: createuser.c:434 +#: createuser.c:436 #, c-format msgid " -R, --no-createrole role cannot create roles (default)\n" msgstr " -R, --no-createrole ロールは別のロールを作成不可(デフォルト)\n" -#: createuser.c:435 +#: createuser.c:437 #, c-format msgid " -s, --superuser role will be superuser\n" msgstr " -s, --superuser ロールをスーパーユーザーにする\n" -#: createuser.c:436 +#: createuser.c:438 #, c-format msgid " -S, --no-superuser role will not be superuser (default)\n" msgstr " -S, --no-superuser ロールをスーパーユーザーにしない(デフォルト)\n" -#: createuser.c:437 +#: createuser.c:439 #, c-format msgid "" " -v, --valid-until=TIMESTAMP\n" @@ -712,19 +712,19 @@ msgstr "" " -v, --valid-until=TIMESTAMP\n" " このロールのパスワード有効期限日時\n" -#: createuser.c:440 +#: createuser.c:442 #, c-format msgid "" " --interactive prompt for missing role name and attributes rather\n" " than using defaults\n" msgstr " --interactive デフォルトを使わず未指定のロール名や属性は入力を促す\n" -#: createuser.c:442 +#: createuser.c:444 #, c-format msgid " --bypassrls role can bypass row-level security (RLS) policy\n" msgstr " --bypassrls ロールは行セキュリティポリシー(RLS)を迂回できる\n" -#: createuser.c:443 +#: createuser.c:445 #, c-format msgid "" " --no-bypassrls role cannot bypass row-level security (RLS) policy\n" @@ -733,17 +733,17 @@ msgstr "" " --no-bypassrls ロールは行セキュリティポリシー(RLS)を迂回できない\n" " (デフォルト)\n" -#: createuser.c:445 +#: createuser.c:447 #, c-format msgid " --replication role can initiate replication\n" msgstr " --replication ロールはレプリケーションを開始可能\n" -#: createuser.c:446 +#: createuser.c:448 #, c-format msgid " --no-replication role cannot initiate replication (default)\n" msgstr " --no-replication ロールはレプリケーションを開始不可 (デフォルト)\n" -#: createuser.c:451 +#: createuser.c:453 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to create)\n" msgstr " -U, --username=USERNAME このユーザーとして接続(作成対象ユーザーではない)\n" @@ -762,12 +762,12 @@ msgstr "データベース\"%s\"は永久に削除されます。\n" msgid "Are you sure?" msgstr "実行しますか?" -#: dropdb.c:157 +#: dropdb.c:156 #, c-format msgid "database removal failed: %s" msgstr "データベースの削除に失敗しました: %s" -#: dropdb.c:171 +#: dropdb.c:170 #, c-format msgid "" "%s removes a PostgreSQL database.\n" @@ -776,22 +776,22 @@ msgstr "" "%sはPostgreSQLデータベースを削除します。\n" "\n" -#: dropdb.c:173 +#: dropdb.c:172 #, c-format msgid " %s [OPTION]... DBNAME\n" msgstr " %s [オプション]... [データベース名]\n" -#: dropdb.c:176 +#: dropdb.c:175 #, c-format msgid " -f, --force try to terminate other connections before dropping\n" msgstr " -f, --force 削除前に他の接続の終了を試行\n" -#: dropdb.c:177 +#: dropdb.c:176 #, c-format msgid " -i, --interactive prompt before deleting anything\n" msgstr " -i, --interactive 何かを削除する前に警告する\n" -#: dropdb.c:179 +#: dropdb.c:178 #, c-format msgid " --if-exists don't report error if database doesn't exist\n" msgstr " --if-exists データベースが存在しない場合にエラーを報告しない\n" @@ -810,12 +810,12 @@ msgstr "必須の引数であるロール名がありません" msgid "Role \"%s\" will be permanently removed.\n" msgstr "ロール\"%s\"は永久に削除されます\n" -#: dropuser.c:154 +#: dropuser.c:155 #, c-format msgid "removal of role \"%s\" failed: %s" msgstr "ロール\"%s\"の削除に失敗しました: %s" -#: dropuser.c:169 +#: dropuser.c:170 #, c-format msgid "" "%s removes a PostgreSQL role.\n" @@ -824,7 +824,7 @@ msgstr "" "%sはPostgreSQLのロールを削除します。\n" "\n" -#: dropuser.c:174 +#: dropuser.c:175 #, c-format msgid "" " -i, --interactive prompt before deleting anything, and prompt for\n" @@ -833,12 +833,12 @@ msgstr "" " -i, --interactive 何かを削除する前に入力を促し、またロール名が指定\n" " されていない場合はその入力を促す\n" -#: dropuser.c:177 +#: dropuser.c:178 #, c-format msgid " --if-exists don't report error if user doesn't exist\n" msgstr " --if-exists ユーザーが存在しない場合にエラーを報告しない\n" -#: dropuser.c:182 +#: dropuser.c:183 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to drop)\n" msgstr " -U, --username=USERNAME このユーザーとして接続(削除対象ユーザーではない)\n" @@ -929,54 +929,54 @@ msgstr " -t, --timeout=SECS 接続試行時の待機秒数、ゼロで無 msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME このユーザー名で接続する\n" -#: reindexdb.c:210 +#: reindexdb.c:217 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "システムカタログのインデックス再構築では複数ジョブを使用できません" -#: reindexdb.c:215 +#: reindexdb.c:222 #, c-format msgid "cannot reindex all databases and a specific one at the same time" msgstr "全データベースと特定のデータベースは同時に再インデックス化はできません" -#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 -#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 -#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 +#: reindexdb.c:302 reindexdb.c:309 vacuumdb.c:558 vacuumdb.c:565 vacuumdb.c:572 +#: vacuumdb.c:579 vacuumdb.c:586 vacuumdb.c:593 vacuumdb.c:600 vacuumdb.c:607 +#: vacuumdb.c:614 vacuumdb.c:621 vacuumdb.c:628 vacuumdb.c:635 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "PostgreSQL %2$sよりも古いサーバーバージョンでは\"%1$s\"オプションは使えません" -#: reindexdb.c:584 +#: reindexdb.c:597 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "データベース\"%s\"のインデックス再構築に失敗しました: %s" -#: reindexdb.c:588 +#: reindexdb.c:601 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "データベース\"%2$s\"中にあるインデックス\"%1$s\"の再作成に失敗しました: %3$s" -#: reindexdb.c:592 +#: reindexdb.c:605 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "データベース\"%2$s\"中にあるスキーマ\"%1$s\"のインデックス再構築に失敗しました: %3$s" -#: reindexdb.c:596 +#: reindexdb.c:609 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "データベース\"%s\"中のシステムカタログのインデックス再構築に失敗しました: %s" -#: reindexdb.c:600 +#: reindexdb.c:613 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "データベース\"%2$s\"中にあるテーブル\"%1$s\"のインでックス再構築に失敗しました: %3$s" -#: reindexdb.c:824 +#: reindexdb.c:854 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: データベース\"%s\"を再インデックス化しています\n" -#: reindexdb.c:867 +#: reindexdb.c:897 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -985,62 +985,62 @@ msgstr "" "%sはPostgreSQLデータベースを再インデックス化します。\n" "\n" -#: reindexdb.c:871 +#: reindexdb.c:901 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all 全データベースでインデックス再構築を行う\n" -#: reindexdb.c:872 +#: reindexdb.c:902 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently 並行インデックス再構築\n" -#: reindexdb.c:873 +#: reindexdb.c:903 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=DBNAME インデックス再構築対象のデータベース\n" -#: reindexdb.c:875 +#: reindexdb.c:905 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX 指定したインデックス(群)のみを再構築\n" -#: reindexdb.c:876 +#: reindexdb.c:906 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr " -j, --jobs=NUM インデックス再構築にこの数の並列接続を使用\n" -#: reindexdb.c:877 +#: reindexdb.c:907 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet メッセージを一切出力しない\n" -#: reindexdb.c:878 +#: reindexdb.c:908 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system システムカタログのインデックスのみを再構築\n" -#: reindexdb.c:879 +#: reindexdb.c:909 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHEMA 指定したスキーマ(群)のインデックスのみを再構築\n" -#: reindexdb.c:880 +#: reindexdb.c:910 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABLE 指定したテーブル(群)のインデックスを再構築\n" -#: reindexdb.c:881 +#: reindexdb.c:911 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " -D, --tablespace=TABLESPACE インデックス再構築先のテーブル空間\n" -#: reindexdb.c:882 +#: reindexdb.c:912 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 多量のメッセージを出力\n" -#: reindexdb.c:892 +#: reindexdb.c:922 #, c-format msgid "" "\n" @@ -1049,224 +1049,234 @@ msgstr "" "\n" "詳細はSQLコマンドREINDEXに関する説明を参照してください。\n" -#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 -#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 +#: vacuumdb.c:324 vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:336 +#: vacuumdb.c:339 vacuumdb.c:342 vacuumdb.c:345 vacuumdb.c:354 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "analyzeのみを実行する場合\"%s\"は使えません" -#: vacuumdb.c:346 +#: vacuumdb.c:357 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "完全(full)VACUUMを実行する場合は\"%s\"オプションは使えません" -#: vacuumdb.c:352 vacuumdb.c:360 +#: vacuumdb.c:363 vacuumdb.c:371 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "\"%s\"オプションは\"%s\"と同時には使えません" -#: vacuumdb.c:432 +#: vacuumdb.c:379 +#, c-format +msgid "cannot use the \"%s\" option without \"%s\" or \"%s\"" +msgstr "\"%s\"オプションは、\"%s\"または\"%s\"がないと使用できません。" + +#: vacuumdb.c:453 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "全データベースと特定のデータベースを同時にVACUUMすることはできません" -#: vacuumdb.c:436 +#: vacuumdb.c:457 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" -msgstr "スキーマ(郡)に属するすべてのテーブルと、特定のテーブル(郡)とを同時にVACUUMすることはできません" +msgstr "スキーマ(群)に属するすべてのテーブルと、特定のテーブル(群)とを同時にVACUUMすることはできません" -#: vacuumdb.c:440 +#: vacuumdb.c:461 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" -msgstr "特定のテーブル(郡)のVACUUMと同時にスキーマ(郡)の除外を行うことはできません" +msgstr "特定のテーブル(群)のVACUUMと同時にスキーマ(群)の除外を行うことはできません" -#: vacuumdb.c:444 +#: vacuumdb.c:465 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" -msgstr "スキーマ(郡)のすべてのテーブルのVACUUMと同時にスキーマ(郡)の除外を行うことはできません" +msgstr "スキーマ(群)のすべてのテーブルのVACUUMと同時にスキーマ(群)の除外を行うことはできません" -#: vacuumdb.c:457 +#: vacuumdb.c:478 #, c-format msgid "out of memory" msgstr "メモリ不足です" -#: vacuumdb.c:502 +#: vacuumdb.c:545 msgid "Generating minimal optimizer statistics (1 target)" msgstr "最適化のための情報を最小限生成します(1対象)" -#: vacuumdb.c:503 +#: vacuumdb.c:546 msgid "Generating medium optimizer statistics (10 targets)" msgstr "最適化のための情報を複数生成します(10対象)" -#: vacuumdb.c:504 +#: vacuumdb.c:547 msgid "Generating default (full) optimizer statistics" msgstr "最適化のための情報をデフォルト数(全て)生成します" -#: vacuumdb.c:583 +#: vacuumdb.c:645 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: データベース\"%s\"の処理中です: %s\n" -#: vacuumdb.c:586 +#: vacuumdb.c:648 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: データベース\"%s\"をVACUUMしています\n" -#: vacuumdb.c:1135 +#: vacuumdb.c:1325 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "データベース \"%2$s\"のテーブル\"%1$sのVACUUMに失敗しました: %3$s" -#: vacuumdb.c:1138 +#: vacuumdb.c:1328 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "データベース\"%s\"のVACUUMに失敗しました: %s" -#: vacuumdb.c:1146 +#: vacuumdb.c:1336 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" "\n" msgstr "%sはPostgreSQLデータベースのゴミ回収および分析を行います。\n" -#: vacuumdb.c:1150 +#: vacuumdb.c:1340 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all 全データベースをVACUUM\n" -#: vacuumdb.c:1151 +#: vacuumdb.c:1341 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=SIZE VACUUMで使用するリングバッファのサイズ\n" -#: vacuumdb.c:1152 +#: vacuumdb.c:1342 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=DBNAME VACUUMするデータベース名\n" -#: vacuumdb.c:1153 +#: vacuumdb.c:1343 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping すべてのページスキップ動作を禁止\n" -#: vacuumdb.c:1154 +#: vacuumdb.c:1344 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo サーバーへ送信されるコマンドを表示\n" -#: vacuumdb.c:1155 +#: vacuumdb.c:1345 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full VACUUM FULLを実行\n" -#: vacuumdb.c:1156 +#: vacuumdb.c:1346 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze 行トランザクション情報を凍結\n" -#: vacuumdb.c:1157 +#: vacuumdb.c:1347 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr "" " --force-index-cleanup デッドタプルを指すインデックスエントリを常に\n" " 除去する\n" -#: vacuumdb.c:1158 +#: vacuumdb.c:1348 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr " -j, --jobs=NUM バキューム時に指定した同時接続数を使用\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1349 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr "" " --min-mxid-age=MXID_AGE VACUUM対象とするテーブルの最小のマルチ\n" " トランザクションID差分\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1350 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr "" " --min-xid-age=XID_AGE VACUUM対象とするテーブルの最小の\n" " トランザクションID差分\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1351 +#, c-format +msgid " --missing-stats-only only analyze relations with missing statistics\n" +msgstr " --missing-stats-only 統計情報がないリレーションのみをANALYZEする\n" + +#: vacuumdb.c:1352 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr "" " --no-index-cleanup デッドタプルを指すインデックスエントリを\n" " 削除しない\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1353 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main メインリレーションをスキップ\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1354 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr "" " --no-process-toast テーブルに関連づくTOASTテーブルのVACUUMを\n" " スキップ\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1355 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate テーブル終端の空ページの切り詰めを行わない\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1356 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" -msgstr " - -n, --schema=SCHEMA 指定したスキーマ(郡)のテーブルのみをVACUUMする\n" +msgstr " - -n, --schema=SCHEMA 指定したスキーマ(群)のテーブルのみをVACUUMする\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1357 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" -msgstr " -N, --exclude-schema=SCHEMA 指定したスキーマ(郡)のテーブルをVACUUMしない\n" +msgstr " -N, --exclude-schema=SCHEMA 指定したスキーマ(群)のテーブルをVACUUMしない\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1358 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr "" " -P, --parallel=PARALLEL_WORKERS 可能であればVACUUMで指定の数のバックグラウンド\n" " ワーカーを使用\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1359 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet メッセージを出力しない\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1360 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr " --skip-locked 直ちにロックできなかったリレーションをスキップ\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1361 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='TABLE[(COLUMNS)]' 指定したテーブル(複数可)のみをVACUUM\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1362 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 多量のメッセージを出力\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1363 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を表示して終了\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1364 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze 最適化用統計情報を更新\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1365 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr " -Z, --analyze-only 最適化用統計情報のみ更新; バキュームは行わない\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1366 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1275,12 +1285,12 @@ msgstr "" " --analyze-in-stages 高速化のため最適化用統計情報のみを複数段階で\n" " 更新; VACUUMは行わない\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1368 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: vacuumdb.c:1185 +#: vacuumdb.c:1376 #, c-format msgid "" "\n" diff --git a/src/bin/scripts/po/ka.po b/src/bin/scripts/po/ka.po index 5ac10ae07046e..0312e86948629 100644 --- a/src/bin/scripts/po/ka.po +++ b/src/bin/scripts/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pgscripts (PostgreSQL) 16\n" +"Project-Id-Version: pgscripts (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:21+0000\n" -"PO-Revision-Date: 2024-06-14 06:16+0200\n" +"POT-Creation-Date: 2025-04-25 17:51+0000\n" +"PO-Revision-Date: 2025-04-26 05:06+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,24 +16,24 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../../src/common/logging.c:276 +#: ../../../src/common/logging.c:279 #, c-format msgid "error: " msgstr "შეცდომა: " -#: ../../../src/common/logging.c:283 +#: ../../../src/common/logging.c:286 #, c-format msgid "warning: " msgstr "warning: " -#: ../../../src/common/logging.c:294 +#: ../../../src/common/logging.c:297 #, c-format msgid "detail: " msgstr "დეტალები: " -#: ../../../src/common/logging.c:301 +#: ../../../src/common/logging.c:304 #, c-format msgid "hint: " msgstr "მინიშნება: " @@ -49,44 +49,44 @@ msgstr "არასაკმარისი მეხსიერება\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "ნულოვანი მაჩვენებლის დუბლირება შეუძლებელია (შიდა შეცდომა)\n" -#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 -#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#: ../../common/file_utils.c:69 ../../common/file_utils.c:370 +#: ../../common/file_utils.c:428 ../../common/file_utils.c:502 #, c-format msgid "could not open file \"%s\": %m" msgstr "ფაილის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:76 +#: ../../common/file_utils.c:75 #, c-format msgid "could not synchronize file system for file \"%s\": %m" msgstr "შეუძლებელია ფაილური სისტემის სინქრონიზაცია ფაილისთვის \"%s\": %m" -#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#: ../../common/file_utils.c:123 ../../common/file_utils.c:588 #, c-format msgid "could not stat file \"%s\": %m" msgstr "ფაილი \"%s\" არ არსებობს: %m" -#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../common/file_utils.c:133 ../../common/file_utils.c:243 #: ../../fe_utils/option_utils.c:99 #, c-format msgid "this build does not support sync method \"%s\"" msgstr "ამ აგებას სინქრონიზაციის მეთოდის \"%s\" მხარდაჭერა არ გააჩნია" -#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#: ../../common/file_utils.c:156 ../../common/file_utils.c:304 #, c-format msgid "could not open directory \"%s\": %m" msgstr "საქაღალდის (%s) გახსნის შეცდომა: %m" -#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#: ../../common/file_utils.c:174 ../../common/file_utils.c:338 #, c-format msgid "could not read directory \"%s\": %m" msgstr "საქაღალდის (%s) წაკითხვის შეცდომა: %m" -#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#: ../../common/file_utils.c:440 ../../common/file_utils.c:510 #, c-format msgid "could not fsync file \"%s\": %m" msgstr "ფაილის (%s) fsync-ის შეცდომა: %m" -#: ../../common/file_utils.c:498 +#: ../../common/file_utils.c:520 #, c-format msgid "could not rename file \"%s\" to \"%s\": %m" msgstr "გადარქმევის შეცდომა %s - %s: %m" @@ -176,8 +176,8 @@ msgstr "შეწყვეტილია\n" #: ../../fe_utils/print.c:3188 #, c-format -msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" -msgstr "ვერ გამოვიტანე ცხრილის შემცველობა: უჯრედების რაოდენობა %lld მაქსიმუმის %lld ტოლი ან მასზე მეტია.\n" +msgid "Cannot print table contents: number of cells % is equal to or exceeds maximum %zu.\n" +msgstr "ვერ გამოვიტანე ცხრილის შემცველობა: უჯრედების რაოდენობა % მაქსიმუმის %zu ტოლი ან მასზე მეტია.\n" #: ../../fe_utils/print.c:3229 #, c-format @@ -186,8 +186,8 @@ msgstr "ცხრილის შემცველობაზე თავს #: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" -msgstr "ცხრილის შემცველობაზე უჯრედის დამატება შეუძლებელია: უჯრედების ჯამური რაოდენობა %lld-ზე მეტია.\n" +msgid "Cannot add cell to table content: total cell count of % exceeded.\n" +msgstr "ცხრილის შემცველობაზე უჯრედის დამატება შეუძლებელია: უჯრედების ჯამური რაოდენობა %-ზე მეტია.\n" #: ../../fe_utils/print.c:3530 #, c-format @@ -204,51 +204,51 @@ msgstr "მოთხოვნის შეცდომა: %s" msgid "Query was: %s" msgstr "მოთხოვნის შინაარსი: %s" -#: ../../fe_utils/string_utils.c:434 +#: ../../fe_utils/string_utils.c:587 #, c-format msgid "shell command argument contains a newline or carriage return: \"%s\"\n" msgstr "გარსის ბრძანების არგუმენტი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: ../../fe_utils/string_utils.c:607 +#: ../../fe_utils/string_utils.c:760 #, c-format msgid "database name contains a newline or carriage return: \"%s\"\n" msgstr "მონაცემთა ბაზის სახელი ხაზის გადატანას ან კარეტის დაბრუნებას შეიცავს: \"%s\"\n" -#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 +#: clusterdb.c:113 clusterdb.c:132 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 +#: reindexdb.c:184 reindexdb.c:203 vacuumdb.c:291 vacuumdb.c:311 #, c-format msgid "Try \"%s --help\" for more information." msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'." -#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 +#: clusterdb.c:130 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:201 vacuumdb.c:309 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "მეტისმეტად ბევრი ბრძანების-სტრიქონის არგუმენტი (პირველია \"%s\")" -#: clusterdb.c:149 +#: clusterdb.c:148 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "ყველა და მითითებული ბაზების ერთდროული დაკლასტერება შეუძლებელია" -#: clusterdb.c:214 +#: clusterdb.c:213 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "ცხრილის (\"%s\"), ბაზაში \"%s\" დაკლასტერების პრობლემა: %s" -#: clusterdb.c:217 +#: clusterdb.c:216 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "ბაზის (\"%s\") დაკლასტერების შეცდომა: %s" -#: clusterdb.c:248 +#: clusterdb.c:247 #, c-format msgid "%s: clustering database \"%s\"\n" msgstr "%s: ბაზის დაკლასტერება: \"%s\"\n" -#: clusterdb.c:274 +#: clusterdb.c:273 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -257,19 +257,19 @@ msgstr "" "%s ალაგებს ბაზაში ადრე დალაგებული ცხრილებს.\n" "\n" -#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 +#: clusterdb.c:274 createdb.c:300 createuser.c:417 dropdb.c:171 dropuser.c:171 +#: pg_isready.c:226 reindexdb.c:898 vacuumdb.c:1337 #, c-format msgid "Usage:\n" msgstr "გამოყენება:\n" -#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 +#: clusterdb.c:275 reindexdb.c:899 vacuumdb.c:1338 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [პარამეტრი]... [ბაზისსახელი]\n" -#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 +#: clusterdb.c:276 createdb.c:302 createuser.c:419 dropdb.c:173 dropuser.c:173 +#: pg_isready.c:229 reindexdb.c:900 vacuumdb.c:1339 #, c-format msgid "" "\n" @@ -278,48 +278,48 @@ msgstr "" "\n" "პარამეტრები:\n" -#: clusterdb.c:278 +#: clusterdb.c:277 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all ყველა ბაზის დაკლასტერება\n" -#: clusterdb.c:279 +#: clusterdb.c:278 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=ბაზისსახელი დასაკლასერებელი ბაზის სახელი\n" -#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:279 createuser.c:425 dropdb.c:174 dropuser.c:174 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo-queries სერვერზე გაგზავნილი ბრძანებების გამოტანა\n" -#: clusterdb.c:281 +#: clusterdb.c:280 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet არ გამოიტანო შეტყობინებები\n" -#: clusterdb.c:282 +#: clusterdb.c:281 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=ცხრილი მხოლოდ მითითებული ცხრილების დაკლასტერება\n" -#: clusterdb.c:283 +#: clusterdb.c:282 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:283 createuser.c:441 dropdb.c:177 dropuser.c:177 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:284 createuser.c:449 dropdb.c:179 dropuser.c:179 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 +#: clusterdb.c:285 createdb.c:319 createuser.c:450 dropdb.c:180 dropuser.c:180 +#: pg_isready.c:235 reindexdb.c:915 vacuumdb.c:1369 #, c-format msgid "" "\n" @@ -328,37 +328,37 @@ msgstr "" "\n" "შეერთების პარამეტრები:\n" -#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 +#: clusterdb.c:286 createuser.c:451 dropdb.c:181 dropuser.c:181 vacuumdb.c:1370 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME მონაცემთა ბაზის სერვერის ჰოსტის ან სოკეტის საქაღალდე\n" -#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 +#: clusterdb.c:287 createuser.c:452 dropdb.c:182 dropuser.c:182 vacuumdb.c:1371 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT მონაცემთა ბაზის სერვერის პორტი\n" -#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 +#: clusterdb.c:288 dropdb.c:183 vacuumdb.c:1372 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" -msgstr " -U, --username=მომხმარებელი ბაზის მომხმარებლის სახელი\n" +msgstr " -U, --username=მომხმარებ. ბაზის მომხმარებლის სახელი\n" -#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 +#: clusterdb.c:289 createuser.c:454 dropdb.c:184 dropuser.c:184 vacuumdb.c:1373 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password არასოდეს მკითხო პაროლი\n" -#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 +#: clusterdb.c:290 createuser.c:455 dropdb.c:185 dropuser.c:185 vacuumdb.c:1374 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password პაროლის ყოველთვის კითხვა\n" -#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 +#: clusterdb.c:291 dropdb.c:186 vacuumdb.c:1375 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=ბაზისსახელი ალტერნატიული საავარიო ბაზა\n" -#: clusterdb.c:293 +#: clusterdb.c:292 #, c-format msgid "" "\n" @@ -367,8 +367,8 @@ msgstr "" "\n" "დაკლასტერების შესახებ მეტი ინფორმაციის მიღება SQL ბრძანების, CLUSTER, დეტალებში შეგიძლიათ.\n" -#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 +#: clusterdb.c:293 createdb.c:327 createuser.c:456 dropdb.c:187 dropuser.c:186 +#: pg_isready.c:240 reindexdb.c:923 vacuumdb.c:1377 #, c-format msgid "" "\n" @@ -377,13 +377,13 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 +#: clusterdb.c:294 createdb.c:328 createuser.c:457 dropdb.c:188 dropuser.c:187 +#: pg_isready.c:241 reindexdb.c:924 vacuumdb.c:1378 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: common.c:107 +#: common.c:106 #, c-format msgid "query returned %d row instead of one: %s" msgid_plural "query returned %d rows instead of one: %s" @@ -417,17 +417,17 @@ msgstr "უპასუხეთ \"%s\" ან \"%s\".\n" msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" კოდირების სწორ სახელს არ წარმოადგენს" -#: createdb.c:260 +#: createdb.c:262 #, c-format msgid "database creation failed: %s" msgstr "ბაზის შექმნის შეცდომა:%s" -#: createdb.c:279 +#: createdb.c:281 #, c-format msgid "comment creation failed (database was created): %s" msgstr "კომენტარის შექმნის შეცდომა (ბაზა შეიქმნა): %s" -#: createdb.c:297 +#: createdb.c:299 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -436,57 +436,57 @@ msgstr "" "%s PostgreSQL-ის ბაზას ქმნის.\n" "\n" -#: createdb.c:299 +#: createdb.c:301 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [პარამეტრი]... [ბაზისსახელი] [აღწერა]\n" -#: createdb.c:301 +#: createdb.c:303 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=ცხრილებისსივრცე მონაცემთა ბაზის ცხრილების ნაგულისხმები სივრცე\n" -#: createdb.c:302 reindexdb.c:874 +#: createdb.c:304 reindexdb.c:904 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo-queries სერვერზე გაგზავნილი ბრძანებების გამოტანა\n" -#: createdb.c:303 +#: createdb.c:305 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" -msgstr " \\encoding [კოდირება] კლიენტის კოდირების ჩვენება ან დაყენება\n" +msgstr " \\encoding [კოდირება] კლიენტის კოდირების ჩვენება ან დაყენება\n" -#: createdb.c:304 +#: createdb.c:306 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=ენა ბაზის ენის პარამეტრები\n" -#: createdb.c:305 +#: createdb.c:307 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=ენა ბაზის LC_COLLATE პარამეტრი\n" -#: createdb.c:306 +#: createdb.c:308 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=ენა ბაზის LC_CTYPE პარამეტრი\n" -#: createdb.c:307 +#: createdb.c:309 #, c-format msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" msgstr " --builtin-locale=ლოკალი ჩაშენებული ლოკალის პარამეტრი მონაცემთა ბაზისთვის\n" -#: createdb.c:308 +#: createdb.c:310 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=ენა ბაზის ICU ენის პარამეტრი\n" -#: createdb.c:309 +#: createdb.c:311 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=წესი ბაზის ICU წესის პარამეტრი\n" -#: createdb.c:310 +#: createdb.c:312 #, c-format msgid "" " --locale-provider={builtin|libc|icu}\n" @@ -495,62 +495,62 @@ msgstr "" " --locale-provider={builtin|libc|icu}\n" " ბაზის ნაგულისხმები კოლაციის ენის მომწოდებელი\n" -#: createdb.c:312 +#: createdb.c:314 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" -msgstr " -O, --owner=მფლობელი ახალი ბაზის მფლობელი მომხმარებლის სახელი\n" +msgstr " -O, --owner=მფლობელი ახალი ბაზის მფლობელი მომხმარებლის სახელი\n" -#: createdb.c:313 +#: createdb.c:315 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" -msgstr " -S, --strategy=სტრატეგია ბაზის შექმნის სტრატეგია: wal_log ან file_copy\n" +msgstr " -S, --strategy=სტრატეგია ბაზის შექმნის სტრატეგია: wal_log ან file_copy\n" -#: createdb.c:314 +#: createdb.c:316 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=შაბლონი ბაზის დასაკოპირებელი შაბლონი\n" -#: createdb.c:315 reindexdb.c:883 +#: createdb.c:317 reindexdb.c:913 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: createdb.c:316 reindexdb.c:884 +#: createdb.c:318 reindexdb.c:914 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: createdb.c:318 reindexdb.c:886 +#: createdb.c:320 reindexdb.c:916 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME მონაცემთა ბაზის სერვერის ჰოსტის ან სოკეტის საქაღალდე\n" -#: createdb.c:319 reindexdb.c:887 +#: createdb.c:321 reindexdb.c:917 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT მონაცემთა ბაზის სერვერის პორტი\n" -#: createdb.c:320 reindexdb.c:888 +#: createdb.c:322 reindexdb.c:918 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=მომხმარებელი ბაზის მომხმარებლის სახელი\n" -#: createdb.c:321 reindexdb.c:889 +#: createdb.c:323 reindexdb.c:919 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password არასოდეს მკითხო პაროლი\n" -#: createdb.c:322 reindexdb.c:890 +#: createdb.c:324 reindexdb.c:920 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password პაროლის ყოველთვის კითხვა\n" -#: createdb.c:323 reindexdb.c:891 +#: createdb.c:325 reindexdb.c:921 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=ბაზისსახელი ალტერნატიული საავარიო ბაზა\n" -#: createdb.c:324 +#: createdb.c:326 #, c-format msgid "" "\n" @@ -588,17 +588,17 @@ msgstr "ექნება ახალ როლს ბაზების შ msgid "Shall the new role be allowed to create more new roles?" msgstr "ექნება ახალ როლს სხვა როლების შექმნს უფლება?" -#: createuser.c:309 +#: createuser.c:311 #, c-format msgid "password encryption failed: %s" msgstr "პაროლის დაშიფვრის შეცდომა: %s" -#: createuser.c:400 +#: createuser.c:402 #, c-format msgid "creation of new role failed: %s" msgstr "ახალი როლის შექმნის შეცდომა: %s" -#: createuser.c:414 +#: createuser.c:416 #, c-format msgid "" "%s creates a new PostgreSQL role.\n" @@ -607,12 +607,12 @@ msgstr "" "%s PostgreSQL-ის როლს ქმნის.\n" "\n" -#: createuser.c:416 dropuser.c:171 +#: createuser.c:418 dropuser.c:172 #, c-format msgid " %s [OPTION]... [ROLENAME]\n" msgstr " %s [პარამეტრი]... [როლისსახელი]\n" -#: createuser.c:418 +#: createuser.c:420 #, c-format msgid "" " -a, --with-admin=ROLE ROLE will be a member of new role with admin\n" @@ -621,32 +621,32 @@ msgstr "" " -a, --admin=როლი როლი ახალი როლის წევრი იქნება, ადმინისტრირების\n" " პარამეტრით\n" -#: createuser.c:420 +#: createuser.c:422 #, c-format msgid " -c, --connection-limit=N connection limit for role (default: no limit)\n" msgstr " -c, --connection-limit=N როლის შეერთებების ლიმიტი (ნაგულისხმები: ლიმიტის გარეშე)\n" -#: createuser.c:421 +#: createuser.c:423 #, c-format msgid " -d, --createdb role can create new databases\n" msgstr " -d, --createdb როლს შეუძლია ახალი ბაზების შექმნა\n" -#: createuser.c:422 +#: createuser.c:424 #, c-format msgid " -D, --no-createdb role cannot create databases (default)\n" msgstr " -D, --no-createdb როლს ბაზების შექმნა არ შეუძლია (ნაგულისხმები)\n" -#: createuser.c:424 +#: createuser.c:426 #, c-format msgid " -g, --member-of=ROLE new role will be a member of ROLE\n" msgstr " -g, --member-of=როლი ახალი როლი ამ როლის წევრი იქნება\n" -#: createuser.c:425 +#: createuser.c:427 #, c-format msgid " --role=ROLE (same as --member-of, deprecated)\n" msgstr " --role=როლი (იგივე, რაც --member-of, რომელიც მოძველებულია)\n" -#: createuser.c:426 +#: createuser.c:428 #, c-format msgid "" " -i, --inherit role inherits privileges of roles it is a\n" @@ -655,52 +655,52 @@ msgstr "" " -i, --inherit რომლი მემკვიდრეობით იღებს იმ როლებსაც, რომლის\n" " წევრიც თვითონაა (ნაგულისხმები)\n" -#: createuser.c:428 +#: createuser.c:430 #, c-format msgid " -I, --no-inherit role does not inherit privileges\n" msgstr " -I, --no-inherit როლი პრივილეგიებს მემკვიდრეობით არ მიიღებს\n" -#: createuser.c:429 +#: createuser.c:431 #, c-format msgid " -l, --login role can login (default)\n" msgstr " -l, --login როლით შესვლა შეიძლება (ნაგულისხმები)\n" -#: createuser.c:430 +#: createuser.c:432 #, c-format msgid " -L, --no-login role cannot login\n" msgstr " -L, --no-login როლს შესვლა არ შეუძლია\n" -#: createuser.c:431 +#: createuser.c:433 #, c-format msgid " -m, --with-member=ROLE ROLE will be a member of new role\n" msgstr " -m, --with-member=როლი როლი ახალი როლის წევრი იქნება\n" -#: createuser.c:432 +#: createuser.c:434 #, c-format msgid " -P, --pwprompt assign a password to new role\n" msgstr " -P, --pwprompt როლისთვის პაროლის მინიჭება\n" -#: createuser.c:433 +#: createuser.c:435 #, c-format msgid " -r, --createrole role can create new roles\n" msgstr " -r, --createrole როლს ახალი როლების შექმნა შეუძლია\n" -#: createuser.c:434 +#: createuser.c:436 #, c-format msgid " -R, --no-createrole role cannot create roles (default)\n" msgstr " -R, --no-createrole როლს ახალი როლების შექმნა არ შეუძლია (ნაგულისხმები)\n" -#: createuser.c:435 +#: createuser.c:437 #, c-format msgid " -s, --superuser role will be superuser\n" msgstr " -s, --superuser როლი ახალი ზემომხმარებელი იქნება\n" -#: createuser.c:436 +#: createuser.c:438 #, c-format msgid " -S, --no-superuser role will not be superuser (default)\n" msgstr " -S, --no-superuser როლი ზემომხმარებელი არ იქნება (ნაგულისხმები)\n" -#: createuser.c:437 +#: createuser.c:439 #, c-format msgid "" " -v, --valid-until=TIMESTAMP\n" @@ -709,7 +709,7 @@ msgstr "" " -v, --valid-until=დროისშტამპი\n" " პაროლის ამოწურვის თარიღი და დრო როლისთვის\n" -#: createuser.c:440 +#: createuser.c:442 #, c-format msgid "" " --interactive prompt for missing role name and attributes rather\n" @@ -718,12 +718,12 @@ msgstr "" " --interactive ნაგულისხმები მნიშვნელობების გამოყენების მაგიერ როლის \n" " ნაკლული სახელისა და ატრიბუტების ინტერაქტიურად კითხვაs\n" -#: createuser.c:442 +#: createuser.c:444 #, c-format msgid " --bypassrls role can bypass row-level security (RLS) policy\n" msgstr " --bypassrls როლს შეუძლია აიცილოს მწკრივის დონის უსაფრთხოების (RLS) წესები\n" -#: createuser.c:443 +#: createuser.c:445 #, c-format msgid "" " --no-bypassrls role cannot bypass row-level security (RLS) policy\n" @@ -732,17 +732,17 @@ msgstr "" " --no-bypassrls როლს მწკრივის დონის უსაფრთხოების წესების (RLS) აცილება\n" " არ შეუძლია (ნაგულისხმები)\n" -#: createuser.c:445 +#: createuser.c:447 #, c-format msgid " --replication role can initiate replication\n" msgstr " --replication როლს შეუძლია რეპლიკაციის ინიცირება\n" -#: createuser.c:446 +#: createuser.c:448 #, c-format msgid " --no-replication role cannot initiate replication (default)\n" msgstr " --no-replication როლს რეპლიკაციის ინიცირება არ შეუძლია (ნაგულისხმები)\n" -#: createuser.c:451 +#: createuser.c:453 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to create)\n" msgstr " -U, --username=მომხმარებელი სერვერთან მიერთების მომხმარებლის სახელი (ის არა, რომელსაც ქმნით)\n" @@ -761,12 +761,12 @@ msgstr "მონაცემთა ბაზა \"%s\" სამუდამო msgid "Are you sure?" msgstr "დარწმუნებული ბრძანდებით?" -#: dropdb.c:157 +#: dropdb.c:156 #, c-format msgid "database removal failed: %s" msgstr "ბაზის წაშლის შეცდომა:%s" -#: dropdb.c:171 +#: dropdb.c:170 #, c-format msgid "" "%s removes a PostgreSQL database.\n" @@ -775,22 +775,22 @@ msgstr "" "%s წაშლის PostgreSQL ბაზას.\n" "\n" -#: dropdb.c:173 +#: dropdb.c:172 #, c-format msgid " %s [OPTION]... DBNAME\n" msgstr " %s [პარამეტრი]... [ბაზისსახელი]\n" -#: dropdb.c:176 +#: dropdb.c:175 #, c-format msgid " -f, --force try to terminate other connections before dropping\n" msgstr " -f, --force შეერთებების დახურვა მათ გათიშვამდე\n" -#: dropdb.c:177 +#: dropdb.c:176 #, c-format msgid " -i, --interactive prompt before deleting anything\n" msgstr " -i, --interactive გკითხავ, სანამ რამეს წავშლი\n" -#: dropdb.c:179 +#: dropdb.c:178 #, c-format msgid " --if-exists don't report error if database doesn't exist\n" msgstr " --if-exists თუ ბაზა არ არსებობს, შეცდომა არ ამოაგდო\n" @@ -809,12 +809,12 @@ msgstr "აკლია აუცილებელი არგუმენტ msgid "Role \"%s\" will be permanently removed.\n" msgstr "როლი \"%s\" სამუდამოდ წაიშლება.\n" -#: dropuser.c:154 +#: dropuser.c:155 #, c-format msgid "removal of role \"%s\" failed: %s" msgstr "როლის (\"%s\") წაშლის შეცდომა: %s" -#: dropuser.c:169 +#: dropuser.c:170 #, c-format msgid "" "%s removes a PostgreSQL role.\n" @@ -823,7 +823,7 @@ msgstr "" "%s წაშლის PostgreSQL-ის როლს.\n" "\n" -#: dropuser.c:174 +#: dropuser.c:175 #, c-format msgid "" " -i, --interactive prompt before deleting anything, and prompt for\n" @@ -832,12 +832,12 @@ msgstr "" " -i, --interactive გკითხავ, სანამ რამეს წავშლი\n" " და გკითხავ როლის სახელსაც, თუ მითითბული არაა\n" -#: dropuser.c:177 +#: dropuser.c:178 #, c-format msgid " --if-exists don't report error if user doesn't exist\n" msgstr " --if-exists თუ მომხმარებელი არ არსებობს, შეცდომა არ ამოაგდო\n" -#: dropuser.c:182 +#: dropuser.c:183 #, c-format msgid " -U, --username=USERNAME user name to connect as (not the one to drop)\n" msgstr " -U, --username=მომხმარებელი სერვერთან მიერთების მომხმარებლის სახელი (ის არა, რომელსაც შლით)\n" @@ -926,54 +926,54 @@ msgstr " -t, --timeout=წამი შეერთების ლოდ msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=მომხმარებელი ბაზის მომხმარებლის სახელი\n" -#: reindexdb.c:210 +#: reindexdb.c:217 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "სისტემური კატალოგების რეინდექსისთვის ბევრი დავალების გამოყენება შეუძლებელია" -#: reindexdb.c:215 +#: reindexdb.c:222 #, c-format msgid "cannot reindex all databases and a specific one at the same time" msgstr "ყველა და მითითებული ბაზების ერთდროული რეინდექსი შეუძლებელია" -#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 -#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 -#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 +#: reindexdb.c:302 reindexdb.c:309 vacuumdb.c:558 vacuumdb.c:565 vacuumdb.c:572 +#: vacuumdb.c:579 vacuumdb.c:586 vacuumdb.c:593 vacuumdb.c:600 vacuumdb.c:607 +#: vacuumdb.c:614 vacuumdb.c:621 vacuumdb.c:628 vacuumdb.c:635 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "პარამეტრი \"%s\" არ გამოიყენება PostgreSQL-ის ვერსიაში \"%s\" ან უფრო ძველში" -#: reindexdb.c:584 +#: reindexdb.c:597 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "ბაზის (\"%s\") რეინდექსის პრობლემა: %s" -#: reindexdb.c:588 +#: reindexdb.c:601 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "რეინდექსის შეცდომა ინდექსისთვის \"%s\" ბაზაში \"%s\": %s" -#: reindexdb.c:592 +#: reindexdb.c:605 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "რეინდექსის შეცდომა სქემისთვის \"%s\" ბაზაში \"%s\": %s" -#: reindexdb.c:596 +#: reindexdb.c:609 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "სისტემური კატალოგების რეინდექსის შეცდომა ბაზაში \"%s\": %s" -#: reindexdb.c:600 +#: reindexdb.c:613 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "რეინდექსის შეცდომა ცხრილისთვის \"%s\" ბაზაში \"%s\": %s" -#: reindexdb.c:824 +#: reindexdb.c:854 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: ბაზის თავიდან ინდექსირება \"%s\"\n" -#: reindexdb.c:867 +#: reindexdb.c:897 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -982,62 +982,62 @@ msgstr "" "%s PostgreSQL ბაზის თავიდან ინდექსირება.\n" "\n" -#: reindexdb.c:871 +#: reindexdb.c:901 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all ყველა ბაზის თავიდან ინდექსირება\n" -#: reindexdb.c:872 +#: reindexdb.c:902 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently ერთდროული ინდექსირება\n" -#: reindexdb.c:873 +#: reindexdb.c:903 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=ბაზისსახელი დასაინდექსებელი ბაზის სახელი\n" -#: reindexdb.c:875 +#: reindexdb.c:905 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=ინდექსი მითითებული ინდექს(ებ)-ი თავიდან შეიქმნება\n" -#: reindexdb.c:876 +#: reindexdb.c:906 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr " -j, --jobs=რიცხვი თავიდან ინდექსირებისთვის მითითებული რაოდენობის შეერთებების გამოყენება\n" -#: reindexdb.c:877 +#: reindexdb.c:907 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet არ გამოიტანო შეტყობინებები\n" -#: reindexdb.c:878 +#: reindexdb.c:908 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system მოხდება მხოლოდ სისტემური კატალოგების თავიდან ინდექსირება\n" -#: reindexdb.c:879 +#: reindexdb.c:909 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=სქემა მოხდება მხოლოდ მითითებული სქემების თავიდან ინდექსირება\n" -#: reindexdb.c:880 +#: reindexdb.c:910 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=ცხრილი მოხდება მხოლოდ მითითებული ცხრილების თავიდან ინდექსირება\n" -#: reindexdb.c:881 +#: reindexdb.c:911 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " --tablespace=ცხრილებისსივრცე ცხრილების სივრცე, სადაც რეინდექსი მოხდება\n" -#: reindexdb.c:882 +#: reindexdb.c:912 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: reindexdb.c:892 +#: reindexdb.c:922 #, c-format msgid "" "\n" @@ -1046,80 +1046,85 @@ msgstr "" "\n" "მეტი დეტალებისთვის იხილეთ SQL-ის ბრძანების, REINDEX-ის დეტალები.\n" -#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 -#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 +#: vacuumdb.c:324 vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:336 +#: vacuumdb.c:339 vacuumdb.c:342 vacuumdb.c:345 vacuumdb.c:354 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "მხოლოდ ანალიზის დროს პარამეტრის \"%s\" გამოყენება შეუძლებელია" -#: vacuumdb.c:346 +#: vacuumdb.c:357 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "სრული დამტვერსასრუტების დროს პარამეტრის \"%s\" გამოყენება შეუძლებელია" -#: vacuumdb.c:352 vacuumdb.c:360 +#: vacuumdb.c:363 vacuumdb.c:371 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "\"%s\" პარამეტრთან ერთად \"%s\"-ის გამოყენება შეუძლებელია" -#: vacuumdb.c:432 +#: vacuumdb.c:379 +#, c-format +msgid "cannot use the \"%s\" option without \"%s\" or \"%s\"" +msgstr "\"%s\" პარამეტრთან ერთად \"%s\"-ის, ან \"%s\"-ის გამოყენება შეუძლებელია" + +#: vacuumdb.c:453 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "ყველა და მითითებული ბაზების ერთდროული დამტვერსასრუტება შეუძლებელია" -#: vacuumdb.c:436 +#: vacuumdb.c:457 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "სქემებში ყველა ცხრილის და მითითებული ცხრილების ერთდროული მომტვერსასრუტება შეუძლებელია" -#: vacuumdb.c:440 +#: vacuumdb.c:461 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "მითითებულ ცხრილების მომტვერსასრუტება და სქემების გამორიცხვა ერთდროულად შეუძლებელია" -#: vacuumdb.c:444 +#: vacuumdb.c:465 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "სქემებში ყველა ცხრილის მომტვერსასრუტება და ამავე დროს სქემების გამორიცხვა შეუძლებელია" -#: vacuumdb.c:457 +#: vacuumdb.c:478 #, c-format msgid "out of memory" msgstr "არასაკმარისი მეხსიერება" -#: vacuumdb.c:502 +#: vacuumdb.c:545 msgid "Generating minimal optimizer statistics (1 target)" msgstr "ოპტიმიზატორის მინიმალური სტატისტიკის გენერაცია (1 სამიზნე)" -#: vacuumdb.c:503 +#: vacuumdb.c:546 msgid "Generating medium optimizer statistics (10 targets)" msgstr "ოპტიმიზატორის საშუალო სტატისტიკის გენერაცია (10 სამიზნე)" -#: vacuumdb.c:504 +#: vacuumdb.c:547 msgid "Generating default (full) optimizer statistics" msgstr "ოპტიმიზატორის ნაგულისხმები (სრული) სტატისტიკის გენერაცია" -#: vacuumdb.c:583 +#: vacuumdb.c:645 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: ბაზის დამუშავება \"%s\": %s\n" -#: vacuumdb.c:586 +#: vacuumdb.c:648 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: ბაზის \"%s\" დამტვერასრუტება\n" -#: vacuumdb.c:1135 +#: vacuumdb.c:1325 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "ცხრილის (\"%s\") (ბაზაში \"%s\") დამტვერსასრუტების პრობლემა: %s" -#: vacuumdb.c:1138 +#: vacuumdb.c:1328 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "ბაზის (\"%s\") დამტვერსასრუტების პრობლემა: %s" -#: vacuumdb.c:1146 +#: vacuumdb.c:1336 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1128,132 +1133,137 @@ msgstr "" "%s PostgreSQL ბაზის გასუფთავება და ოპტიმიზაცია.\n" "\n" -#: vacuumdb.c:1150 +#: vacuumdb.c:1340 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all ყველა ბაზის დამტვერსასრუტება\n" -#: vacuumdb.c:1151 +#: vacuumdb.c:1341 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=ზომა მომტვერსასრუტებისთვის გამოყენებული რგოლის ბაფერის ზომა\n" -#: vacuumdb.c:1152 +#: vacuumdb.c:1342 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=ბაზისსახელი დასამტვერსასრუტებელი ბაზები\n" -#: vacuumdb.c:1153 +#: vacuumdb.c:1343 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping გვერდის გამოტოვების ყველა ვარიანტის გამორთვა\n" -#: vacuumdb.c:1154 +#: vacuumdb.c:1344 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo-queries სერვერზე გაგზავნილი ბრძანებების გამოტანა\n" -#: vacuumdb.c:1155 +#: vacuumdb.c:1345 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full სრული დამტვერსასრუტება\n" -#: vacuumdb.c:1156 +#: vacuumdb.c:1346 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze მწკრივის ტრანზაქციის ინფორმაციის გაყინვა\n" -#: vacuumdb.c:1157 +#: vacuumdb.c:1347 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr " --force-index-cleanup ინდექსის ჩანაწერები, რომლებიც მკვდარ მონაცემებზე მიუთითებენ, ყოველთვის წაიშლება\n" -#: vacuumdb.c:1158 +#: vacuumdb.c:1348 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr " -j, --jobs=რიცხვი დამტვერსასრუტებისას მითითებული რაოდენობის შეერთებების გამოყენება\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1349 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr " --min-mxid-age=MXID_AGE დასამტვერსასრუტებელი ცხრილების მულტიტრანზაქციის ID-ის მინიმალური ასაკი\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1350 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr " --min-xid-age=XID_AGE დასამტვერსასრუტებელი ცხრილების ტრანზაქციების ID-ის მინიმალური ასაკი\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1351 +#, c-format +msgid " --missing-stats-only only analyze relations with missing statistics\n" +msgstr " --missing-stats-only მხოლოდ, იმ ურთიერთობების ანალიზი, რომლებსაც სტატისტიკა აკლია\n" + +#: vacuumdb.c:1352 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr " --no-index-cleanup ინდექსის ჩანაწერები, რომლებიც მკვდარ მონაცემებზე მიუთითებენ, არ წაიშლება\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1353 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main მთავარი ურთიერთობის გამოტოვება\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1354 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr " --no-process-toast მომტვერსასრუტებისას ცხრილთან ასოცირებული TOAST cxrilis gamotoveba\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1355 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate ცხრილის ბოლოში ცარიელი გვერდები არ მოიკვეთება\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1356 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" msgstr " -n, --schema=სქემა ცხრილების, მხოლოდ, მითითებულ სქემებში მომტვერსასრუტება\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1357 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" msgstr " -N, --exclude-schema=სქემა მითითებული სქემებში ცხრილები მომტვერსასრუტებული არ იქნება\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1358 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr " -P, --parallel=პარალელური_დამხმარე_პროცესი დასამტვერსასრუტებლად მითითებული რაოდენობის დამხმარე პროცესის გამოყენება, თუ ეს შესაძლებელია\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1359 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet არ გამოიტანო შეტყობინებები\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1360 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr " --skip-locked გამოტოვებული იქნება ურთიერთობები, რომლის მაშინვე ჩაკეტვაც შეუძლებელია\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1361 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='ცხრილი[(სვეტები)]' მხოლოდ მითითებული ცხრილების დამტვერსასრუტება\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1362 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose დამატებითი ინფორმაციის გამოტანა\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1363 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ინფორმაციის გამოტანა და გასვლა\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1364 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze ოპტიმიზატორის სტატისტიკის განახლება\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1365 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr " -Z, --analyze-only მხოლოდ ოპტიმიზატორის სტატისტიკის განახლება; დამტვერსასრუტების გარეშე\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1366 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1262,12 +1272,12 @@ msgstr "" " --analyze-in-stages უკეთესი შედეგებისთვის ოპტიმიზატორის სტატისტიკის\n" " მრავალსაფეხურიანი რეჟიმი; დამტვერსასრუტების გარეშე\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1368 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: vacuumdb.c:1185 +#: vacuumdb.c:1376 #, c-format msgid "" "\n" diff --git a/src/bin/scripts/po/ko.po b/src/bin/scripts/po/ko.po index 9df2d7b7022e9..5e694f0725165 100644 --- a/src/bin/scripts/po/ko.po +++ b/src/bin/scripts/po/ko.po @@ -3,10 +3,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pgscripts (PostgreSQL) 16\n" +"Project-Id-Version: pgscripts (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:51+0000\n" -"PO-Revision-Date: 2023-05-26 13:22+0900\n" +"POT-Creation-Date: 2025-01-17 04:51+0000\n" +"PO-Revision-Date: 2025-01-16 14:23+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -46,6 +46,48 @@ msgstr "메모리 부족\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "null 포인터를 복제할 수 없음(내부 오류)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "\"%s\" 파일을 열 수 없음: %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "\"%s\" 파일을 위한 파일 시스템 동기화를 할 수 없음: %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "\"%s\" 파일 상태 정보를 구할 수 없음: %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "이 빌드는 \"%s\" 동기화 방법을 지원하지 않음" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 열 수 없음: %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "\"%s\" 파일을 fsync 할 수 없음: %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "\"%s\" 파일을 \"%s\" 파일로 이름을 바꿀 수 없음: %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -60,11 +102,11 @@ msgstr "사용자 없음" msgid "user name lookup failure: error code %lu" msgstr "사용자 이름 찾기 실패: 오류번호 %lu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "취소 요청을 전송함\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "취소 요청을 전송할 수 없음: " @@ -92,12 +134,27 @@ msgstr "\"%s\" 값은 \"%s\" 옵션 값으로 유효하지 않음" msgid "%s must be in range %d..%d" msgstr "%s 값은 %d부터 %d까지 지정할 수 있습니다." -#: ../../fe_utils/parallel_slot.c:299 +#: ../../fe_utils/option_utils.c:106 #, c-format -msgid "too many jobs for this platform" -msgstr "이 운영체제에서는 너무 많은 동시 작업임" +msgid "unrecognized sync method: %s" +msgstr "알 수 없는 동기화 방법: %s" -#: ../../fe_utils/parallel_slot.c:520 +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "이 운영체제에서는 너무 많은 동시 작업임: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "select() 작업을 위한 소켓 파일 기술자 범위를 벗어남: %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "job 수를 줄이세요." + +#: ../../fe_utils/parallel_slot.c:553 #, c-format msgid "processing of database \"%s\" failed: %s" msgstr "\"%s\" 데이터베이스 작업 실패: %s" @@ -113,17 +170,25 @@ msgstr[0] "(%lu개 행)" msgid "Interrupted\n" msgstr "인트럽트발생\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "" +"Cannot print table contents: number of cells %lld is equal to or exceeds " +"maximum %lld.\n" +msgstr "" +"테이블 내용을 출력할 수 없음: %lld 셀 수가 최대값 %lld 개와 같거나 초과함.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "테이블 내용에 헤더를 추가할 수 없음: 열 수가 %d개를 초과했습니다.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "테이블 내용에 셀을 추가할 수 없음: 총 셀 수가 %d개를 초과했습니다.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "테이블 내용에 셀을 추가할 수 없음: 총 셀 수가 %lld개를 초과했습니다.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "잘못된 출력 형식 (내부 오류): %d" @@ -138,36 +203,41 @@ msgstr "쿼리 실패: %s" msgid "Query was: %s" msgstr "사용한 쿼리: %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "쉘 명령 인자에 줄바꿈 문자가 포함되었음: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "데이터베이스 이름에 줄바꿈 문자가 포함되었음: \"%s\"\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:277 vacuumdb.c:297 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "자세한 사항은 \"%s --help\" 명령으로 살펴보세요." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:295 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "명령행 인자를 너무 많이 지정했습니다 (시작: \"%s\")" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "모든 DB 작업과 특정 DB 작업은 동시에 할 수 없습니다." -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "모든 DB를 대상으로 특정 테이블들을 클러스터할 수 없음" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "\"%s\" 테이블(해당DB: \"%s\") 클러스터 작업 실패: %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "\"%s\" 데이터베이스 클러스터 실패: %s" @@ -177,7 +247,7 @@ msgstr "\"%s\" 데이터베이스 클러스터 실패: %s" msgid "%s: clustering database \"%s\"\n" msgstr "%s: \"%s\" 데이터베이스 클러스터 작업 중\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -187,19 +257,19 @@ msgstr "" "다시 클러스터 작업을 합니다.\n" "\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1127 +#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 +#: pg_isready.c:226 reindexdb.c:872 vacuumdb.c:1158 #, c-format msgid "Usage:\n" msgstr "사용법:\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1128 +#: clusterdb.c:276 reindexdb.c:873 vacuumdb.c:1159 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [옵션]... [DB이름]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1129 +#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 +#: pg_isready.c:229 reindexdb.c:874 vacuumdb.c:1160 #, c-format msgid "" "\n" @@ -208,49 +278,49 @@ msgstr "" "\n" "옵션들:\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all 모든 데이터베이스를 대상으로\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=DBNAME 클러스터 작업할 DB\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 #, c-format msgid "" " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo 서버로 보내는 작업 명령을 보여줌\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet 어떠한 메시지도 보여주지 않음\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=TABLE 지정한 테이블들만 클러스터\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 많은 출력 작성\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1158 +#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 +#: pg_isready.c:235 reindexdb.c:889 vacuumdb.c:1189 #, c-format msgid "" "\n" @@ -259,38 +329,38 @@ msgstr "" "\n" "연결 옵션들:\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1159 +#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1190 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME 데이터베이스 서버 호스트 또는 소켓 디렉터리\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1160 +#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1191 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT 데이터베이스 서버 포트\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1161 +#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1192 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME 접속할 사용자이름\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1162 +#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1193 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password 암호 프롬프트 표시 안 함\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1163 +#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1194 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password 암호 프롬프트 표시함\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1164 +#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1195 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME 대체용 관리 대상 데이터베이스\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "" "\n" @@ -299,8 +369,8 @@ msgstr "" "\n" "보다 자세한 내용은 CLUSTER SQL 명령어 설명서를 참조하십시오.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1166 +#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 +#: pg_isready.c:240 reindexdb.c:897 vacuumdb.c:1197 #, c-format msgid "" "\n" @@ -309,8 +379,8 @@ msgstr "" "\n" "문제점 보고 주소: <%s>\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1167 +#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 +#: pg_isready.c:241 reindexdb.c:898 vacuumdb.c:1198 #, c-format msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" @@ -343,22 +413,22 @@ msgstr "%s (%s/%s) " msgid "Please answer \"%s\" or \"%s\".\n" msgstr "\"%s\" 또는 \"%s\" 만 허용합니다.\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" 이름은 잘못된 인코딩 이름임" -#: createdb.c:250 +#: createdb.c:260 #, c-format msgid "database creation failed: %s" msgstr "데이터베이스 만들기 실패: %s" -#: createdb.c:269 +#: createdb.c:279 #, c-format msgid "comment creation failed (database was created): %s" msgstr "코멘트 추가하기 실패 (데이터베이스는 만들어졌음): %s" -#: createdb.c:287 +#: createdb.c:297 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -367,70 +437,75 @@ msgstr "" "%s 프로그램은 PostgreSQL 데이터베이스를 만듭니다.\n" "\n" -#: createdb.c:289 +#: createdb.c:299 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [옵션]... [DB이름] [설명]\n" -#: createdb.c:291 +#: createdb.c:301 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr "" " -D, --tablespace=TABLESPACE 데이터베이스를 위한 기본 테이블스페이스\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:302 reindexdb.c:878 #, c-format msgid "" " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo 서버로 보내는 작업 명령들을 보여줌\n" -#: createdb.c:293 +#: createdb.c:303 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=ENCODING 데이터베이스 인코딩\n" -#: createdb.c:294 +#: createdb.c:304 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOCALE 데이터베이스의 로캘 설정\n" -#: createdb.c:295 +#: createdb.c:305 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOCALE 데이터베이스의 LC_COLLATE 설정\n" -#: createdb.c:296 +#: createdb.c:306 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOCALE 데이터베이스의 LC_CTYPE 설정\n" -#: createdb.c:297 +#: createdb.c:307 +#, c-format +msgid "" +" --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=LOCALE 데이터베이스 내장 로케일 설정\n" + +#: createdb.c:308 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE 데이터베이스 ICU 로캘 설정\n" -#: createdb.c:298 +#: createdb.c:309 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=RULES 데이터베이스 ICU 룰 설정\n" -#: createdb.c:299 +#: createdb.c:310 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default " "collation\n" msgstr "" -" --locale-provider={libc|icu}\n" -" 데이터베이스 기본 문자 정렬을 위한 로케일 제공" -"자\n" +" --locale-provider={builtin|libc|icu}\n" +" 데이터베이스 기본 문자 정렬 제공자 설정\n" -#: createdb.c:301 +#: createdb.c:312 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --owner=OWNER 데이터베이스 소유주\n" -#: createdb.c:302 +#: createdb.c:313 #, c-format msgid "" " -S, --strategy=STRATEGY database creation strategy wal_log or " @@ -439,54 +514,54 @@ msgstr "" " -S, --strategy=STRATEGY 데이터베이스 만드는 전략(wal_log 또는 " "file_copy)\n" -#: createdb.c:303 +#: createdb.c:314 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=TEMPLATE 복사할 템플릿 데이터베이스\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:315 reindexdb.c:887 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:316 reindexdb.c:888 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 보여주고 마침\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:318 reindexdb.c:890 #, c-format msgid "" " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" " -h, --host=HOSTNAME 데이터베이스 서버 호스트나 소켓 디렉터리\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:319 reindexdb.c:891 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT 데이터베이스 서버 포트\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:320 reindexdb.c:892 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME 접속할 사용자\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:321 reindexdb.c:893 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password 암호 프롬프트 표시 안 함\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:322 reindexdb.c:894 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password 암호 프롬프트 표시함\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:323 reindexdb.c:895 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME 대체용 관리 대상 데이터베이스\n" -#: createdb.c:313 +#: createdb.c:324 #, c-format msgid "" "\n" @@ -880,105 +955,57 @@ msgstr " -t, --timeout=초 연결 제한 시간, 0 무제한 (초기값 msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=USERNAME 접속할 사용자이름\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "" -"모든 데이터베이스 재색인 작업과 특정 데이터베이스 재색인 작업은 동시에 진행" -"할 수 없습니다" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "" -"모든 데이터베이스 재색인 작업과 시스템 카탈로그 재색인 작업은 동시에 진행할 " -"수 없습니다" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "" -"모든 데이터베이스 재색인 작업에서 특정 스키마들의 재색인 작업을 지정할 수 없" -"습니다" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "" -"모든 데이터베이스 재색인 작업에서 특정 테이블의 재색인 작업을 지정할 수 없습" -"니다" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "" -"모든 데이터베이스 재색인 작업에서 특정 인덱스 재색인 작업을 지정할 수 없습니" -"다" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "특정 스키마와 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "특정 테이블과 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "특정 인덱스와 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "시스템 카탈로그 재색인 작업은 병렬로 처리할 수 없음" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "인덱스 다시 만들기에서는 다중 작업을 사용할 수 없음" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "" +"모든 데이터베이스 재색인 작업과 특정 데이터베이스 재색인 작업은 동시에 진행" +"할 수 없습니다" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:509 vacuumdb.c:516 vacuumdb.c:523 -#: vacuumdb.c:530 vacuumdb.c:537 vacuumdb.c:544 vacuumdb.c:551 vacuumdb.c:556 -#: vacuumdb.c:560 vacuumdb.c:564 vacuumdb.c:568 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:514 vacuumdb.c:521 vacuumdb.c:528 +#: vacuumdb.c:535 vacuumdb.c:542 vacuumdb.c:549 vacuumdb.c:556 vacuumdb.c:561 +#: vacuumdb.c:565 vacuumdb.c:569 vacuumdb.c:573 #, c-format msgid "" "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "\"%s\" 옵션은 PostgreSQL %s 버전보다 오래된 서버에서는 사용할 수 없음" -#: reindexdb.c:561 +#: reindexdb.c:584 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "\"%s\" 데이터베이스 재색인 작업 실패: %s" -#: reindexdb.c:565 +#: reindexdb.c:588 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "\"%s\" 인덱스(해당DB: \"%s\") 재색인 작업 실패: %s" -#: reindexdb.c:569 +#: reindexdb.c:592 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "\"%s\" 스키마(해당DB: \"%s\") 재색인 작업 실패: %s" -#: reindexdb.c:573 +#: reindexdb.c:596 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "\"%s\" 데이터베이스 시스템 카탈로그 재색인 작업 실패: %s" -#: reindexdb.c:577 +#: reindexdb.c:600 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "\"%s\" 테이블(해당DB: \"%s\") 재색인 작업 실패: %s" -#: reindexdb.c:732 +#: reindexdb.c:828 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: \"%s\" 데이터베이스 재색인 작업 중\n" -#: reindexdb.c:749 +#: reindexdb.c:871 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -987,27 +1014,27 @@ msgstr "" "%s 프로그램은 PostgreSQL 데이터베이스 재색인 작업을 합니다.\n" "\n" -#: reindexdb.c:753 +#: reindexdb.c:875 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all 모든 데이터베이스 재색인\n" -#: reindexdb.c:754 +#: reindexdb.c:876 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently 테이블 잠그지 않는 재색인\n" -#: reindexdb.c:755 +#: reindexdb.c:877 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=DBNAME 지정한 데이터베이스의 재색인 작업\n" -#: reindexdb.c:757 +#: reindexdb.c:879 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX 지정한 인덱스들만 다시 만듬\n" -#: reindexdb.c:758 +#: reindexdb.c:880 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " @@ -1015,38 +1042,38 @@ msgid "" msgstr "" " -j, --jobs=NUM 재색인 작업을 여러개의 연결로 동시에 작업함\n" -#: reindexdb.c:759 +#: reindexdb.c:881 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet 어떠한 메시지도 보여주지 않음\n" -#: reindexdb.c:760 +#: reindexdb.c:882 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system 시스템 카탈로그 재색인\n" -#: reindexdb.c:761 +#: reindexdb.c:883 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHEMA 지정한 스키마들 자료만 덤프\n" -#: reindexdb.c:762 +#: reindexdb.c:884 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABLE 지정한 테이블들만 재색인 작업\n" -#: reindexdb.c:763 +#: reindexdb.c:885 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr "" " --tablespace=TABLESPACE 데이터베이스를 위한 기본 테이블스페이스\n" -#: reindexdb.c:764 +#: reindexdb.c:886 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 작업내역의 자세한 출력\n" -#: reindexdb.c:774 +#: reindexdb.c:896 #, c-format msgid "" "\n" @@ -1055,57 +1082,42 @@ msgstr "" "\n" "보다 자세한 내용은 REINDEX SQL 명령어 설명서를 참조하십시오.\n" -#: vacuumdb.c:310 vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 -#: vacuumdb.c:325 vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:340 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "통계 수집 전용 작업에서는 \"%s\" 옵션을 사용할 수 없음" -#: vacuumdb.c:343 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "full vacuum 작업에서는 \"%s\" 옵션을 사용할 수 없음" -#: vacuumdb.c:349 vacuumdb.c:357 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "\"%s\" 옵션과 \"%s\" 옵션을 함께 사용할 수 없음" -#: vacuumdb.c:428 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "" "-a 옵션이 있을 경우는 한 데이터베이스를 대상으로 작업을 진행할 수 없습니다." -#: vacuumdb.c:432 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "모든 데이터베이스를 대상으로는 특정 테이블들을 청소할 수는 없음" - #: vacuumdb.c:436 #, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "모든 데이터베이스를 대상으로는 특정 스키마들을 청소할 수는 없음" - -#: vacuumdb.c:440 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "모든 데이터베이스를 대상으로는 특정 스키마를 제외할 수 없음" - -#: vacuumdb.c:444 -#, c-format msgid "" "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "" "스키마 안에 있는 모든 테이블을 청소하는 것과 특정 테이블만 청소하는 것을 동시" "에 할 수 없음" -#: vacuumdb.c:448 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "특정 테이블만 청소하는 것과 스키마를 제외하는 것은 동시에 할 수 없음" -#: vacuumdb.c:452 +#: vacuumdb.c:444 #, c-format msgid "" "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" @@ -1113,39 +1125,44 @@ msgstr "" "스키마 안 모든 테이블만 청소하는 것과 스키마를 제외하는 것은 동시에 할 수 없" "음" -#: vacuumdb.c:496 +#: vacuumdb.c:457 +#, c-format +msgid "out of memory" +msgstr "메모리 부족" + +#: vacuumdb.c:501 msgid "Generating minimal optimizer statistics (1 target)" msgstr "최소 최적화 통계 수집 수행 중 (1% 대상)" -#: vacuumdb.c:497 +#: vacuumdb.c:502 msgid "Generating medium optimizer statistics (10 targets)" msgstr "일반 최적화 통계 수집 수행 중 (10% 대상)" -#: vacuumdb.c:498 +#: vacuumdb.c:503 msgid "Generating default (full) optimizer statistics" msgstr "최대 최적화 통계 수집 수행중 (모든 자료 대상)" -#: vacuumdb.c:577 +#: vacuumdb.c:582 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: \"%s\" 데이터베이스 작업 중: %s\n" -#: vacuumdb.c:580 +#: vacuumdb.c:585 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: \"%s\" 데이터베이스를 청소 중\n" -#: vacuumdb.c:1115 +#: vacuumdb.c:1146 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "\"%s\" 테이블 (해당 DB: \"%s\") 청소하기 실패: %s" -#: vacuumdb.c:1118 +#: vacuumdb.c:1149 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "\"%s\" 데이터베이스 청소하기 실패: %s" -#: vacuumdb.c:1126 +#: vacuumdb.c:1157 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1155,44 +1172,44 @@ msgstr "" "퀴리 최적화기의 참고 자료를 갱신합니다.\n" "\n" -#: vacuumdb.c:1130 +#: vacuumdb.c:1161 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all 모든 데이터베이스 청소\n" -#: vacuumdb.c:1131 +#: vacuumdb.c:1162 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=SIZE 청소를 위한 링 버커 크기\n" -#: vacuumdb.c:1132 +#: vacuumdb.c:1163 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=DBNAME DBNAME 데이터베이스 청소\n" -#: vacuumdb.c:1133 +#: vacuumdb.c:1164 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping 모든 page-skipping 기능 비활성화\n" -#: vacuumdb.c:1134 +#: vacuumdb.c:1165 #, c-format msgid "" " -e, --echo show the commands being sent to the " "server\n" msgstr " -e, --echo 서버로 보내는 명령들을 보여줌\n" -#: vacuumdb.c:1135 +#: vacuumdb.c:1166 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full 대청소\n" -#: vacuumdb.c:1136 +#: vacuumdb.c:1167 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze 행 트랜잭션 정보 동결\n" -#: vacuumdb.c:1137 +#: vacuumdb.c:1168 #, c-format msgid "" " --force-index-cleanup always remove index entries that point to " @@ -1200,7 +1217,7 @@ msgid "" msgstr "" " --force-index-cleanup 삭제된 튜플 대상 인덱스 항목 항상 삭제\n" -#: vacuumdb.c:1138 +#: vacuumdb.c:1169 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " @@ -1208,7 +1225,7 @@ msgid "" msgstr "" " -j, --jobs=NUM 청소 작업을 여러개의 연결로 동시에 작업함\n" -#: vacuumdb.c:1139 +#: vacuumdb.c:1170 #, c-format msgid "" " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to " @@ -1216,7 +1233,7 @@ msgid "" msgstr "" " --min-mxid-age=MXID_AGE 청소할 테이블의 최소 multixact ID 나이\n" -#: vacuumdb.c:1140 +#: vacuumdb.c:1171 #, c-format msgid "" " --min-xid-age=XID_AGE minimum transaction ID age of tables to " @@ -1224,7 +1241,7 @@ msgid "" msgstr "" " --min-xid-age=XID_AGE 청소할 테이블의 최소 트랜잭션 ID 나이\n" -#: vacuumdb.c:1141 +#: vacuumdb.c:1172 #, c-format msgid "" " --no-index-cleanup don't remove index entries that point to " @@ -1232,12 +1249,12 @@ msgid "" msgstr "" " --no-index-cleanup 삭제된 튜플 대상 인덱스 항목 지우지 않음\n" -#: vacuumdb.c:1142 +#: vacuumdb.c:1173 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main 메인 릴레이션 건너뜀\n" -#: vacuumdb.c:1143 +#: vacuumdb.c:1174 #, c-format msgid "" " --no-process-toast skip the TOAST table associated with the " @@ -1246,7 +1263,7 @@ msgstr "" " --no-process-toast vacuum 대상 테이블과 관련된 TOAST 테이블 건" "너뜀\n" -#: vacuumdb.c:1144 +#: vacuumdb.c:1175 #, c-format msgid "" " --no-truncate don't truncate empty pages at the end of " @@ -1254,23 +1271,23 @@ msgid "" msgstr "" " --no-truncate 테이블 끝에 있는 빈 페이지를 지우지 않음\n" -#: vacuumdb.c:1145 +#: vacuumdb.c:1176 #, c-format msgid "" -" -n, --schema=PATTERN vacuum tables in the specified schema(s) " +" -n, --schema=SCHEMA vacuum tables in the specified schema(s) " "only\n" msgstr "" -" -n, --schema=PATTERN 지정한 스키마 안에 있는 테이블만 청소함\n" +" -n, --schema=SCHEMA 지정한 스키마 안에 있는 테이블만 청소함\n" -#: vacuumdb.c:1146 +#: vacuumdb.c:1177 #, c-format msgid "" -" -N, --exclude-schema=PATTERN do not vacuum tables in the specified " +" -N, --exclude-schema=SCHEMA do not vacuum tables in the specified " "schema(s)\n" msgstr "" -" -N, --exclude-schema=PATTERN 지정한 스키마 안에 있는 테이블만 청소안함\n" +" -N, --exclude-schema=SCHEMA 지정한 스키마 안에 있는 테이블만 청소안함\n" -#: vacuumdb.c:1147 +#: vacuumdb.c:1178 #, c-format msgid "" " -P, --parallel=PARALLEL_WORKERS use this many background workers for " @@ -1279,12 +1296,12 @@ msgstr "" " -P, --parallel=병렬작업수 vacuum 작업을 병렬로 처리 할 수 있는 경우\n" " 백그라운드 작업 프로세스 수\n" -#: vacuumdb.c:1148 +#: vacuumdb.c:1179 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet 어떠한 메시지도 보여주지 않음\n" -#: vacuumdb.c:1149 +#: vacuumdb.c:1180 #, c-format msgid "" " --skip-locked skip relations that cannot be immediately " @@ -1292,28 +1309,28 @@ msgid "" msgstr "" " --skip-locked 즉시 잠글 수 없는 릴레이션은 건너 뜀\n" -#: vacuumdb.c:1150 +#: vacuumdb.c:1181 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='TABLE[(COLUMNS)]' 지정한 특정 테이블들만 청소\n" -#: vacuumdb.c:1151 +#: vacuumdb.c:1182 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose 작업내역의 자세한 출력\n" -#: vacuumdb.c:1152 +#: vacuumdb.c:1183 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version 버전 정보를 보여주고 마침\n" -#: vacuumdb.c:1153 +#: vacuumdb.c:1184 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze 쿼리최적화 통계 정보를 갱신함\n" -#: vacuumdb.c:1154 +#: vacuumdb.c:1185 #, c-format msgid "" " -Z, --analyze-only only update optimizer statistics; no " @@ -1322,7 +1339,7 @@ msgstr "" " -Z, --analyze-only 청소 작업 없이 쿼리최적화 통계 정보만 갱신" "함\n" -#: vacuumdb.c:1155 +#: vacuumdb.c:1186 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in " @@ -1332,12 +1349,12 @@ msgstr "" " --analyze-in-stages 보다 빠른 결과를 위해 다중 스테이지에서\n" " 최적화 통계치만 갱신함;청소 안함\n" -#: vacuumdb.c:1157 +#: vacuumdb.c:1188 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help 이 도움말을 표시하고 종료\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1196 #, c-format msgid "" "\n" @@ -1345,3 +1362,65 @@ msgid "" msgstr "" "\n" "보다 자세한 내용은 VACUUM SQL 명령어 설명서를 참조하십시오.\n" + +#, c-format +#~ msgid "cannot cluster specific table(s) in all databases" +#~ msgstr "모든 DB를 대상으로 특정 테이블들을 클러스터할 수 없음" + +#, c-format +#~ msgid "cannot reindex all databases and system catalogs at the same time" +#~ msgstr "" +#~ "모든 데이터베이스 재색인 작업과 시스템 카탈로그 재색인 작업은 동시에 진행" +#~ "할 수 없습니다" + +#, c-format +#~ msgid "cannot reindex specific schema(s) in all databases" +#~ msgstr "" +#~ "모든 데이터베이스 재색인 작업에서 특정 스키마들의 재색인 작업을 지정할 수 " +#~ "없습니다" + +#, c-format +#~ msgid "cannot reindex specific table(s) in all databases" +#~ msgstr "" +#~ "모든 데이터베이스 재색인 작업에서 특정 테이블의 재색인 작업을 지정할 수 없" +#~ "습니다" + +#, c-format +#~ msgid "cannot reindex specific index(es) in all databases" +#~ msgstr "" +#~ "모든 데이터베이스 재색인 작업에서 특정 인덱스 재색인 작업을 지정할 수 없습" +#~ "니다" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific schema(s) and system catalogs at the same time" +#~ msgstr "" +#~ "특정 스키마와 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific table(s) and system catalogs at the same time" +#~ msgstr "" +#~ "특정 테이블과 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific index(es) and system catalogs at the same time" +#~ msgstr "" +#~ "특정 인덱스와 시스템 카탈로그 재색인 작업은 동시에 진행할 수 없습니다" + +#, c-format +#~ msgid "cannot use multiple jobs to reindex indexes" +#~ msgstr "인덱스 다시 만들기에서는 다중 작업을 사용할 수 없음" + +#, c-format +#~ msgid "cannot vacuum specific table(s) in all databases" +#~ msgstr "모든 데이터베이스를 대상으로는 특정 테이블들을 청소할 수는 없음" + +#, c-format +#~ msgid "cannot vacuum specific schema(s) in all databases" +#~ msgstr "모든 데이터베이스를 대상으로는 특정 스키마들을 청소할 수는 없음" + +#, c-format +#~ msgid "cannot exclude specific schema(s) in all databases" +#~ msgstr "모든 데이터베이스를 대상으로는 특정 스키마를 제외할 수 없음" diff --git a/src/bin/scripts/po/meson.build b/src/bin/scripts/po/meson.build index f4dde2c8de4d8..e317f7ea9fbde 100644 --- a/src/bin/scripts/po/meson.build +++ b/src/bin/scripts/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pgscripts-' + pg_version_major.to_string())] diff --git a/src/bin/scripts/po/pt_BR.po b/src/bin/scripts/po/pt_BR.po index 0eccd72b48068..011367c29ca93 100644 --- a/src/bin/scripts/po/pt_BR.po +++ b/src/bin/scripts/po/pt_BR.po @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: PostgreSQL 15\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2022-09-27 13:15-0300\n" -"PO-Revision-Date: 2023-08-17 16:32+0200\n" +"PO-Revision-Date: 2024-06-26 10:46+0200\n" "Last-Translator: Euler Taveira \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" @@ -245,12 +245,12 @@ msgstr " -v, --verbose mostra muitas mensagens\n" #: clusterdb.c:272 createuser.c:364 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" -msgstr " -V, --version mostra informação sobre a versão e termina\n" +msgstr " -V, --version mostra informação sobre a versão e termina\n" #: clusterdb.c:273 createuser.c:369 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" -msgstr " -?, --help mostra essa ajuda e termina\n" +msgstr " -?, --help mostra essa ajuda e termina\n" #: clusterdb.c:274 createdb.c:298 createuser.c:370 dropdb.c:181 dropuser.c:179 #: pg_isready.c:235 reindexdb.c:777 vacuumdb.c:991 diff --git a/src/bin/scripts/po/ru.po b/src/bin/scripts/po/ru.po index 5ae3272f51147..2afac56ec193f 100644 --- a/src/bin/scripts/po/ru.po +++ b/src/bin/scripts/po/ru.po @@ -3,13 +3,13 @@ # This file is distributed under the same license as the PostgreSQL package. # Serguei A. Mokhov, , 2003-2004. # Oleg Bartunov , 2004. -# Alexander Lakhin , 2012-2017, 2019, 2020, 2021, 2022, 2023. +# Alexander Lakhin , 2012-2017, 2019, 2020, 2021, 2022, 2023, 2024. msgid "" msgstr "" "Project-Id-Version: pgscripts (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-11-03 09:08+0300\n" -"PO-Revision-Date: 2023-11-03 10:36+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-05 08:25+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -50,6 +50,48 @@ msgstr "нехватка памяти\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не удалось открыть файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не удалось получить информацию о файле \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "эта сборка программы не поддерживает метод синхронизации \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не удалось открыть каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не удалось прочитать каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не удалось синхронизировать с ФС файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не удалось переименовать файл \"%s\" в \"%s\": %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -64,11 +106,11 @@ msgstr "пользователь не существует" msgid "user name lookup failure: error code %lu" msgstr "распознать имя пользователя не удалось (код ошибки: %lu)" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Сигнал отмены отправлен\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Отправить сигнал отмены не удалось: " @@ -96,6 +138,11 @@ msgstr "неверное значение \"%s\" для параметра %s" msgid "%s must be in range %d..%d" msgstr "значение %s должно быть в диапазоне %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нераспознанный метод синхронизации: %s" + #: ../../fe_utils/parallel_slot.c:317 #, c-format msgid "too many jobs for this platform: %d" @@ -129,19 +176,28 @@ msgstr[2] "(%lu строк)" msgid "Interrupted\n" msgstr "Прервано\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "" +"Cannot print table contents: number of cells %lld is equal to or exceeds " +"maximum %lld.\n" +msgstr "" +"Вывести содержимое таблицы нельзя: число ячеек %lld достигло максимума " +"%lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "" "Ошибка добавления заголовка таблицы: превышен предел числа столбцов (%d).\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" msgstr "" -"Ошибка добавления ячейки в таблицу: превышен предел числа ячеек (%d).\n" +"Ошибка добавления ячейки в таблицу: превышен предел числа ячеек (%lld).\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "неверный формат вывода (внутренняя ошибка): %d" @@ -156,36 +212,44 @@ msgstr "ошибка при выполнении запроса: %s" msgid "Query was: %s" msgstr "Выполнялся запрос: %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "" +"аргумент команды оболочки содержит символ новой строки или перевода каретки: " +"\"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "" +"имя базы данных содержит символ новой строки или перевода каретки: \"%s\"\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:279 vacuumdb.c:299 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Для дополнительной информации попробуйте \"%s --help\"." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:297 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "слишком много аргументов командной строки (первый: \"%s\")" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "нельзя кластеризовать все базы и одну конкретную одновременно" -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "нельзя кластеризовать указанную таблицу(ы) во всех базах" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "кластеризовать таблицу \"%s\" в базе \"%s\" не удалось: %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "кластеризовать базу \"%s\" не удалось: %s" @@ -195,7 +259,7 @@ msgstr "кластеризовать базу \"%s\" не удалось: %s" msgid "%s: clustering database \"%s\"\n" msgstr "%s: кластеризация базы \"%s\"\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -204,19 +268,19 @@ msgstr "" "%s упорядочивает данные всех кластеризованных таблиц в базе данных.\n" "\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1156 +#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 +#: pg_isready.c:226 reindexdb.c:872 vacuumdb.c:1170 #, c-format msgid "Usage:\n" msgstr "Использование:\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1157 +#: clusterdb.c:276 reindexdb.c:873 vacuumdb.c:1171 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [ПАРАМЕТР]... [ИМЯ_БД]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1158 +#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 +#: pg_isready.c:229 reindexdb.c:874 vacuumdb.c:1172 #, c-format msgid "" "\n" @@ -225,50 +289,50 @@ msgstr "" "\n" "Параметры:\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all кластеризовать все базы\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=ИМЯ_БД имя базы данных для кластеризации\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 #, c-format msgid "" " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo отображать команды, отправляемые серверу\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не выводить никакие сообщения\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr "" " -t, --table=ТАБЛИЦА кластеризовать только указанную таблицу(ы)\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose выводить исчерпывающие сообщения\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1187 +#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 +#: pg_isready.c:235 reindexdb.c:889 vacuumdb.c:1201 #, c-format msgid "" "\n" @@ -277,39 +341,40 @@ msgstr "" "\n" "Параметры подключения:\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1188 +#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1202 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1189 +#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1203 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=ПОРТ порт сервера баз данных\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1190 +#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1204 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr "" " -U, --username=ИМЯ имя пользователя для подключения к серверу\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1191 +#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1205 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1192 +#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1206 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password запросить пароль\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1193 +#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1207 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=ИМЯ_БД сменить опорную базу данных\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "" "\n" @@ -318,8 +383,8 @@ msgstr "" "\n" "Подробнее о кластеризации вы можете узнать в описании SQL-команды CLUSTER.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1195 +#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 +#: pg_isready.c:240 reindexdb.c:897 vacuumdb.c:1209 #, c-format msgid "" "\n" @@ -328,8 +393,8 @@ msgstr "" "\n" "Об ошибках сообщайте по адресу <%s>.\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1196 +#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 +#: pg_isready.c:241 reindexdb.c:898 vacuumdb.c:1210 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашняя страница %s: <%s>\n" @@ -364,22 +429,22 @@ msgstr "%s (%s - да/%s - нет) " msgid "Please answer \"%s\" or \"%s\".\n" msgstr "Пожалуйста, введите \"%s\" или \"%s\".\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" не является верным названием кодировки" -#: createdb.c:250 +#: createdb.c:260 #, c-format msgid "database creation failed: %s" msgstr "создать базу данных не удалось: %s" -#: createdb.c:269 +#: createdb.c:279 #, c-format msgid "comment creation failed (database was created): %s" msgstr "создать комментарий не удалось (база данных была создана): %s" -#: createdb.c:287 +#: createdb.c:297 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -388,76 +453,82 @@ msgstr "" "%s создаёт базу данных PostgreSQL.\n" "\n" -#: createdb.c:289 +#: createdb.c:299 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [ПАРАМЕТР]... [ИМЯ_БД] [ОПИСАНИЕ]\n" # well-spelled: ПРОСТР -#: createdb.c:291 +#: createdb.c:301 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr "" " -D, --tablespace=ТАБЛ_ПРОСТР табличное пространство по умолчанию для базы " "данных\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:302 reindexdb.c:878 #, c-format msgid "" " -e, --echo show the commands being sent to the server\n" msgstr "" " -e, --echo отображать команды, отправляемые серверу\n" -#: createdb.c:293 +#: createdb.c:303 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=КОДИРОВКА кодировка базы данных\n" -#: createdb.c:294 +#: createdb.c:304 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=ЛОКАЛЬ локаль для базы данных\n" -#: createdb.c:295 +#: createdb.c:305 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=ЛОКАЛЬ параметр LC_COLLATE для базы данных\n" -#: createdb.c:296 +#: createdb.c:306 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=ЛОКАЛЬ параметр LC_CTYPE для базы данных\n" -#: createdb.c:297 +#: createdb.c:307 +#, c-format +msgid "" +" --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=ЛОКАЛЬ имя встроенной локали для базы данных\n" + +#: createdb.c:308 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=ЛОКАЛЬ локаль ICU для базы данных\n" -#: createdb.c:298 +#: createdb.c:309 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr "" " --icu-rules=ПРАВИЛА настройка правил сортировки ICU для базы " "данных\n" -#: createdb.c:299 +#: createdb.c:310 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default " "collation\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " провайдер локали для основного правила " "сортировки БД\n" -#: createdb.c:301 +#: createdb.c:312 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr "" " -O, --owner=ВЛАДЕЛЕЦ пользователь-владелец новой базы данных\n" -#: createdb.c:302 +#: createdb.c:313 #, c-format msgid "" " -S, --strategy=STRATEGY database creation strategy wal_log or " @@ -466,55 +537,56 @@ msgstr "" " -S, --strategy=STRATEGY стратегия создания базы данных: wal_log или " "file_copy\n" -#: createdb.c:303 +#: createdb.c:314 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=ШАБЛОН исходная база данных для копирования\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:315 reindexdb.c:887 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:316 reindexdb.c:888 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:318 reindexdb.c:890 #, c-format msgid "" " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:319 reindexdb.c:891 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=ПОРТ порт сервера баз данных\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:320 reindexdb.c:892 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr "" " -U, --username=ИМЯ имя пользователя для подключения к серверу\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:321 reindexdb.c:893 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password не запрашивать пароль\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:322 reindexdb.c:894 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password запросить пароль\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:323 reindexdb.c:895 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=ИМЯ_БД сменить опорную базу данных\n" -#: createdb.c:313 +#: createdb.c:324 #, c-format msgid "" "\n" @@ -907,7 +979,8 @@ msgstr " -?, --help показать эту справку и в #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr "" -" -h, --host=ИМЯ имя сервера баз данных или каталог сокетов\n" +" -h, --host=ИМЯ компьютер с сервером баз данных или каталог " +"сокетов\n" #: pg_isready.c:237 #, c-format @@ -929,105 +1002,59 @@ msgid " -U, --username=USERNAME user name to connect as\n" msgstr "" " -U, --username=ИМЯ имя пользователя для подключения к серверу\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "" -"нельзя переиндексировать все базы данных и одну конкретную одновременно" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "" -"нельзя переиндексировать все базы данных и системные каталоги одновременно" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "нельзя переиндексировать указанную схему(ы) во всех базах" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "нельзя переиндексировать указанную таблицу(ы) во всех базах" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "нельзя переиндексировать указанный индекс(ы) во всех базах" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "" -"нельзя переиндексировать указанную схему(ы) и системные каталоги одновременно" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "" -"нельзя переиндексировать указанную таблицу(ы) и системные каталоги " -"одновременно" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "" -"нельзя переиндексировать указанный индекс(ы) и системные каталоги " -"одновременно" - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "" "нельзя задействовать несколько заданий для переиндексирования системных " "каталогов" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "нельзя задействовать несколько заданий для перестроения индексов" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "" +"нельзя переиндексировать все базы данных и одну конкретную одновременно" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:525 vacuumdb.c:532 vacuumdb.c:539 -#: vacuumdb.c:546 vacuumdb.c:553 vacuumdb.c:560 vacuumdb.c:567 vacuumdb.c:572 -#: vacuumdb.c:576 vacuumdb.c:580 vacuumdb.c:584 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:514 vacuumdb.c:521 vacuumdb.c:528 +#: vacuumdb.c:535 vacuumdb.c:542 vacuumdb.c:549 vacuumdb.c:556 vacuumdb.c:563 +#: vacuumdb.c:570 vacuumdb.c:577 vacuumdb.c:584 #, c-format msgid "" "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "" "параметр \"%s\" нельзя использовать с серверами PostgreSQL версии старее %s" -#: reindexdb.c:561 +#: reindexdb.c:584 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "переиндексировать базу данных \"%s\" не удалось: %s" -#: reindexdb.c:565 +#: reindexdb.c:588 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "перестроить индекс \"%s\" в базе \"%s\" не удалось: %s" -#: reindexdb.c:569 +#: reindexdb.c:592 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "переиндексировать схему \"%s\" в базе \"%s\" не удалось: %s" -#: reindexdb.c:573 +#: reindexdb.c:596 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "переиндексировать системные каталоги в базе \"%s\" не удалось: %s" -#: reindexdb.c:577 +#: reindexdb.c:600 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "переиндексировать таблицу \"%s\" в базе \"%s\" не удалось: %s" -#: reindexdb.c:732 +#: reindexdb.c:828 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: переиндексация базы данных \"%s\"\n" -#: reindexdb.c:749 +#: reindexdb.c:871 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -1036,29 +1063,29 @@ msgstr "" "%s переиндексирует базу данных PostgreSQL.\n" "\n" -#: reindexdb.c:753 +#: reindexdb.c:875 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all переиндексировать все базы данных\n" -#: reindexdb.c:754 +#: reindexdb.c:876 #, c-format msgid " --concurrently reindex concurrently\n" msgstr "" " --concurrently переиндексировать в неблокирующем режиме\n" -#: reindexdb.c:755 +#: reindexdb.c:877 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=БД имя базы для переиндексации\n" -#: reindexdb.c:757 +#: reindexdb.c:879 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr "" " -i, --index=ИНДЕКС пересоздать только указанный индекс(ы)\n" -#: reindexdb.c:758 +#: reindexdb.c:880 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " @@ -1067,24 +1094,24 @@ msgstr "" " -j, --jobs=ЧИСЛО запускать для переиндексации заданное число\n" " заданий\n" -#: reindexdb.c:759 +#: reindexdb.c:881 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не выводить сообщения\n" -#: reindexdb.c:760 +#: reindexdb.c:882 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr "" " -s, --system переиндексировать только системные каталоги\n" -#: reindexdb.c:761 +#: reindexdb.c:883 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr "" " -S, --schema=СХЕМА переиндексировать только указанную схему(ы)\n" -#: reindexdb.c:762 +#: reindexdb.c:884 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr "" @@ -1092,19 +1119,19 @@ msgstr "" "таблицу(ы)\n" # well-spelled: ПРОСТР -#: reindexdb.c:763 +#: reindexdb.c:885 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr "" " --tablespace=ТАБЛ_ПРОСТР табличное пространство, в котором будут\n" " перестраиваться индексы\n" -#: reindexdb.c:764 +#: reindexdb.c:886 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose выводить исчерпывающие сообщения\n" -#: reindexdb.c:774 +#: reindexdb.c:896 #, c-format msgid "" "\n" @@ -1113,43 +1140,28 @@ msgstr "" "\n" "Подробнее о переиндексации вы можете узнать в описании SQL-команды REINDEX.\n" -#: vacuumdb.c:312 vacuumdb.c:315 vacuumdb.c:318 vacuumdb.c:321 vacuumdb.c:324 -#: vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:342 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "при выполнении только анализа нельзя использовать параметр \"%s\"" -#: vacuumdb.c:345 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "при выполнении полной очистки нельзя использовать параметр \"%s\"" -#: vacuumdb.c:351 vacuumdb.c:359 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "параметр \"%s\" нельзя использовать совместно с \"%s\"" -#: vacuumdb.c:430 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "нельзя очистить все базы данных и одну конкретную одновременно" -#: vacuumdb.c:434 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "нельзя очистить только указанную таблицу(ы) во всех базах" - -#: vacuumdb.c:438 -#, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "нельзя очистить только указанную схему(ы) во всех базах" - -#: vacuumdb.c:442 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "нельзя исключить указанную схему(ы) во всех базах" - -#: vacuumdb.c:446 +#: vacuumdb.c:436 #, c-format msgid "" "cannot vacuum all tables in schema(s) and specific table(s) at the same time" @@ -1157,57 +1169,57 @@ msgstr "" "нельзя очистить все таблицы в схеме(ах) и одну конкретную таблицу " "одновременно" -#: vacuumdb.c:450 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "" "нельзя очистить конкретную таблицу(ы) и исключить схему(ы) одновременно" -#: vacuumdb.c:454 +#: vacuumdb.c:444 #, c-format msgid "" "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "" "нельзя очистить все таблицы в схеме(ах) и исключить схему(ы) одновременно" -#: vacuumdb.c:467 +#: vacuumdb.c:457 #, c-format msgid "out of memory" msgstr "нехватка памяти" -#: vacuumdb.c:512 +#: vacuumdb.c:501 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Вычисление минимальной статистики для оптимизатора (1 запись)" -#: vacuumdb.c:513 +#: vacuumdb.c:502 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Вычисление средней статистики для оптимизатора (10 записей)" -#: vacuumdb.c:514 +#: vacuumdb.c:503 msgid "Generating default (full) optimizer statistics" msgstr "Вычисление стандартной (полной) статистики для оптимизатора" -#: vacuumdb.c:593 +#: vacuumdb.c:594 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: обработка базы данных \"%s\": %s\n" -#: vacuumdb.c:596 +#: vacuumdb.c:597 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: очистка базы данных \"%s\"\n" -#: vacuumdb.c:1144 +#: vacuumdb.c:1158 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "очистить таблицу \"%s\" в базе \"%s\" не удалось: %s" -#: vacuumdb.c:1147 +#: vacuumdb.c:1161 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "очистить базу данных \"%s\" не удалось: %s" -#: vacuumdb.c:1155 +#: vacuumdb.c:1169 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1216,12 +1228,12 @@ msgstr "" "%s очищает и анализирует базу данных PostgreSQL.\n" "\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1173 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all очистить все базы данных\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1174 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr "" @@ -1229,18 +1241,18 @@ msgstr "" "при\n" " очистке\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1175 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=ИМЯ_БД очистить указанную базу данных\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1176 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr "" " --disable-page-skipping исключить все варианты пропуска страниц\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1177 #, c-format msgid "" " -e, --echo show the commands being sent to the " @@ -1248,19 +1260,19 @@ msgid "" msgstr "" " -e, --echo отображать команды, отправляемые серверу\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1178 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full произвести полную очистку\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1179 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr "" " -F, --freeze заморозить информацию о транзакциях в " "строках\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1180 #, c-format msgid "" " --force-index-cleanup always remove index entries that point to " @@ -1270,7 +1282,7 @@ msgstr "" "указывающие\n" " на мёртвые кортежи\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1181 #, c-format msgid "" " -j, --jobs=NUM use this many concurrent connections to " @@ -1279,7 +1291,7 @@ msgstr "" " -j, --jobs=ЧИСЛО запускать для очистки заданное число " "заданий\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1182 #, c-format msgid "" " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to " @@ -1288,7 +1300,7 @@ msgstr "" " --min-mxid-age=ВОЗРАСТ минимальный возраст мультитранзакций для\n" " таблиц, подлежащих очистке\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1183 #, c-format msgid "" " --min-xid-age=XID_AGE minimum transaction ID age of tables to " @@ -1298,7 +1310,7 @@ msgstr "" "таблиц,\n" " подлежащих очистке\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1184 #, c-format msgid "" " --no-index-cleanup don't remove index entries that point to " @@ -1307,12 +1319,12 @@ msgstr "" " --no-index-cleanup не удалять элементы индекса, указывающие\n" " на мёртвые кортежи\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1185 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main пропускать основное отношение\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1186 #, c-format msgid "" " --no-process-toast skip the TOAST table associated with the " @@ -1321,7 +1333,7 @@ msgstr "" " --no-process-toast пропускать TOAST-таблицу, связанную\n" " с очищаемой таблицей\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1187 #, c-format msgid "" " --no-truncate don't truncate empty pages at the end of " @@ -1330,7 +1342,7 @@ msgstr "" " --no-truncate не отсекать пустые страницы в конце " "таблицы\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1188 #, c-format msgid "" " -n, --schema=SCHEMA vacuum tables in the specified schema(s) " @@ -1339,7 +1351,7 @@ msgstr "" " -n, --schema=СХЕМА очищать таблицы только в указанной " "схеме(ах)\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1189 #, c-format msgid "" " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified " @@ -1347,7 +1359,7 @@ msgid "" msgstr "" " -N, --exclude-schema=СХЕМА не очищать таблицы в указанной схеме(ах)\n" -#: vacuumdb.c:1176 +#: vacuumdb.c:1190 #, c-format msgid "" " -P, --parallel=PARALLEL_WORKERS use this many background workers for " @@ -1357,12 +1369,12 @@ msgstr "" " по возможности использовать для очистки\n" " заданное число фоновых процессов\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1191 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не выводить сообщения\n" -#: vacuumdb.c:1178 +#: vacuumdb.c:1192 #, c-format msgid "" " --skip-locked skip relations that cannot be immediately " @@ -1371,29 +1383,29 @@ msgstr "" " --skip-locked пропускать отношения, которые не удаётся\n" " заблокировать немедленно\n" -#: vacuumdb.c:1179 +#: vacuumdb.c:1193 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr "" " -t, --table='ТАБЛ[(СТОЛБЦЫ)]' очистить только указанную таблицу(ы)\n" -#: vacuumdb.c:1180 +#: vacuumdb.c:1194 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose выводить исчерпывающие сообщения\n" -#: vacuumdb.c:1181 +#: vacuumdb.c:1195 #, c-format msgid "" " -V, --version output version information, then exit\n" msgstr " -V, --version показать версию и выйти\n" -#: vacuumdb.c:1182 +#: vacuumdb.c:1196 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze обновить статистику оптимизатора\n" -#: vacuumdb.c:1183 +#: vacuumdb.c:1197 #, c-format msgid "" " -Z, --analyze-only only update optimizer statistics; no " @@ -1402,7 +1414,7 @@ msgstr "" " -Z, --analyze-only только обновить статистику оптимизатора,\n" " не очищать БД\n" -#: vacuumdb.c:1184 +#: vacuumdb.c:1198 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in " @@ -1414,12 +1426,12 @@ msgstr "" " (в несколько проходов для большей " "скорости), без очистки\n" -#: vacuumdb.c:1186 +#: vacuumdb.c:1200 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показать эту справку и выйти\n" -#: vacuumdb.c:1194 +#: vacuumdb.c:1208 #, c-format msgid "" "\n" @@ -1428,6 +1440,64 @@ msgstr "" "\n" "Подробнее об очистке вы можете узнать в описании SQL-команды VACUUM.\n" +#, c-format +#~ msgid "cannot cluster specific table(s) in all databases" +#~ msgstr "нельзя кластеризовать указанную таблицу(ы) во всех базах" + +#, c-format +#~ msgid "cannot reindex all databases and system catalogs at the same time" +#~ msgstr "" +#~ "нельзя переиндексировать все базы данных и системные каталоги одновременно" + +#, c-format +#~ msgid "cannot reindex specific schema(s) in all databases" +#~ msgstr "нельзя переиндексировать указанную схему(ы) во всех базах" + +#, c-format +#~ msgid "cannot reindex specific table(s) in all databases" +#~ msgstr "нельзя переиндексировать указанную таблицу(ы) во всех базах" + +#, c-format +#~ msgid "cannot reindex specific index(es) in all databases" +#~ msgstr "нельзя переиндексировать указанный индекс(ы) во всех базах" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific schema(s) and system catalogs at the same time" +#~ msgstr "" +#~ "нельзя переиндексировать указанную схему(ы) и системные каталоги " +#~ "одновременно" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific table(s) and system catalogs at the same time" +#~ msgstr "" +#~ "нельзя переиндексировать указанную таблицу(ы) и системные каталоги " +#~ "одновременно" + +#, c-format +#~ msgid "" +#~ "cannot reindex specific index(es) and system catalogs at the same time" +#~ msgstr "" +#~ "нельзя переиндексировать указанный индекс(ы) и системные каталоги " +#~ "одновременно" + +#, c-format +#~ msgid "cannot use multiple jobs to reindex indexes" +#~ msgstr "нельзя задействовать несколько заданий для перестроения индексов" + +#, c-format +#~ msgid "cannot vacuum specific table(s) in all databases" +#~ msgstr "нельзя очистить только указанную таблицу(ы) во всех базах" + +#, c-format +#~ msgid "cannot vacuum specific schema(s) in all databases" +#~ msgstr "нельзя очистить только указанную схему(ы) во всех базах" + +#, c-format +#~ msgid "cannot exclude specific schema(s) in all databases" +#~ msgstr "нельзя исключить указанную схему(ы) во всех базах" + #, c-format #~ msgid "cannot reindex system catalogs concurrently, skipping all" #~ msgstr "" @@ -1457,9 +1527,6 @@ msgstr "" #~ msgid "minimum multixact ID age must be at least 1" #~ msgstr "минимальный возраст мультитранзакций должен быть не меньше 1" -#~ msgid "could not connect to database %s: %s" -#~ msgstr "не удалось подключиться к базе %s: %s" - #~ msgid "parallel vacuum degree must be a non-negative integer" #~ msgstr "" #~ "степень параллельности для очистки должна задаваться неотрицательным целым" diff --git a/src/bin/scripts/po/sv.po b/src/bin/scripts/po/sv.po index 5003a9397bd98..6dfeaecb092fb 100644 --- a/src/bin/scripts/po/sv.po +++ b/src/bin/scripts/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for postgresql -# Dennis Björklund , 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2003, 2004, 2005, 2006, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # Peter Eisentraut , 2013. # Mats Erik Andersson , 2014. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-23 02:50+0000\n" -"PO-Revision-Date: 2023-08-02 07:51+0200\n" +"POT-Creation-Date: 2024-07-12 17:52+0000\n" +"PO-Revision-Date: 2024-07-12 22:17+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -48,6 +48,48 @@ msgstr "slut på minne\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "kan inte duplicera null-pekare (internt fel)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "kunde inte öppna fil \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "kan inte synkronisera filsystemet för fil \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "kunde inte göra stat() på fil \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "detta bygge stöder inte synkmetod \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "kunde inte öppna katalog \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "kunde inte läsa katalog \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "kunde inte fsync:a fil \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "kunde inte döpa om fil \"%s\" till \"%s\": %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -62,11 +104,11 @@ msgstr "användaren finns inte" msgid "user name lookup failure: error code %lu" msgstr "misslyckad sökning efter användarnamn: felkod %lu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Förfrågan om avbrytning skickad\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Kunde inte skicka förfrågan om avbrytning: " @@ -94,12 +136,27 @@ msgstr "ogiltigt värde \"%s\" för flaggan \"%s\"" msgid "%s must be in range %d..%d" msgstr "%s måste vara i intervallet %d..%d" -#: ../../fe_utils/parallel_slot.c:299 +#: ../../fe_utils/option_utils.c:106 #, c-format -msgid "too many jobs for this platform" -msgstr "för många jobb för denna plattform" +msgid "unrecognized sync method: %s" +msgstr "okänd synkmetod: %s" -#: ../../fe_utils/parallel_slot.c:520 +#: ../../fe_utils/parallel_slot.c:317 +#, c-format +msgid "too many jobs for this platform: %d" +msgstr "för många jobb för denna plattform: %d" + +#: ../../fe_utils/parallel_slot.c:326 +#, c-format +msgid "socket file descriptor out of range for select(): %d" +msgstr "deskriptor-index utanför sitt intervall för select(): %d" + +#: ../../fe_utils/parallel_slot.c:328 +#, c-format +msgid "Try fewer jobs." +msgstr "Försök med färre job." + +#: ../../fe_utils/parallel_slot.c:553 #, c-format msgid "processing of database \"%s\" failed: %s" msgstr "processande av databas \"%s\" misslyckades: %s" @@ -116,17 +173,22 @@ msgstr[1] "(%lu rader)" msgid "Interrupted\n" msgstr "Avbruten\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Kan inte skriva ut tabellinnehåll: antal celler %lld är lika med eller fler än maximala %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "Kan inte lägga till rubrik till tabellinnehåll: antal kolumner (%d) överskridet.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "Kan inte lägga till cell till tabellinnehåll: totala cellantalet (%d) överskridet.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "Kan inte lägga till cell till tabellinnehåll: totala cellantalet %lld är överskridet.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "ogiltigt utdataformat (internt fel): %d" @@ -141,36 +203,41 @@ msgstr "fråga misslyckades: %s" msgid "Query was: %s" msgstr "Frågan var: %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "shell-kommandots argument innehåller nyrad eller vagnretur: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "databasnamnet innehåller nyrad eller vagnretur: \"%s\"\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:279 vacuumdb.c:299 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Försök med \"%s --help\" för mer information." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:297 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "för många kommandoradsargument (första är \"%s\")" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "kan inte klustra alla databaser och en angiven på samma gång" -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "kan inte klustra angivna tabeller i alla databaser" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "klustring av tabell \"%s\" i databas \"%s\" misslyckades: %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "klustring av databas \"%s\" misslyckades: %s" @@ -180,7 +247,7 @@ msgstr "klustring av databas \"%s\" misslyckades: %s" msgid "%s: clustering database \"%s\"\n" msgstr "%s: klustring av databas \"%s\"\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "" "%s clusters all previously clustered tables in a database.\n" @@ -189,19 +256,19 @@ msgstr "" "%s klustrar alla tidigare klustrade tabeller i en databas.\n" "\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1150 +#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 +#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 #, c-format msgid "Usage:\n" msgstr "Användning:\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1151 +#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [FLAGGA]... [DBNAMN]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1152 +#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 +#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 #, c-format msgid "" "\n" @@ -210,48 +277,48 @@ msgstr "" "\n" "Flaggor:\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all klustra alla databaser\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=DBNAME databas att klustra\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo visa kommandon som skickas till servern\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet skriv inte ut några meddelanden\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=TABELL klustra enbart ingivna tabeller\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose skriv massor med utdata\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1181 +#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 +#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 #, c-format msgid "" "\n" @@ -260,37 +327,37 @@ msgstr "" "\n" "Flaggor för anslutning:\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1182 +#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1183 +#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT databasserverns port\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1184 +#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ANVÄNDARE användarnamn att ansluta som\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1185 +#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga ej efter lösenord\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1186 +#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password framtvinga fråga om lösenord\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1187 +#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAMN annat val av underhållsdatabas\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "" "\n" @@ -299,8 +366,8 @@ msgstr "" "\n" "Läs beskrivningen av SQL-kommandot CLUSTER för detaljer.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1189 +#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 +#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 #, c-format msgid "" "\n" @@ -309,8 +376,8 @@ msgstr "" "\n" "Rapportera fel till <%s>.\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1190 +#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 +#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 #, c-format msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" @@ -344,22 +411,22 @@ msgstr "%s (%s/%s) " msgid "Please answer \"%s\" or \"%s\".\n" msgstr "Var vänlig att svara \"%s\" eller \"%s\".\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" är inte ett giltigt kodningsnamn" -#: createdb.c:250 +#: createdb.c:260 #, c-format msgid "database creation failed: %s" msgstr "misslyckades att skapa databas: %s" -#: createdb.c:269 +#: createdb.c:279 #, c-format msgid "comment creation failed (database was created): %s" msgstr "misslyckades att skapa kommentar (databasen skapades): %s" -#: createdb.c:287 +#: createdb.c:297 #, c-format msgid "" "%s creates a PostgreSQL database.\n" @@ -368,118 +435,123 @@ msgstr "" "%s skapar en PostgreSQL-databas.\n" "\n" -#: createdb.c:289 +#: createdb.c:299 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [FLAGGA]... [DBNAMN] [BESKRIVNING]\n" -#: createdb.c:291 +#: createdb.c:301 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=TABELLRYMD förvalt tabellutrymme för databasen\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:302 reindexdb.c:874 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo visa kommandon som skickas till servern\n" -#: createdb.c:293 +#: createdb.c:303 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=KODNING teckenkodning för databasen\n" -#: createdb.c:294 +#: createdb.c:304 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=LOKAL lokalnamn för databasen\n" -#: createdb.c:295 +#: createdb.c:305 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=LOKAL värde på LC_COLLATE för databasen\n" -#: createdb.c:296 +#: createdb.c:306 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=LOKAL värde på LC_CTYPE för databasen\n" -#: createdb.c:297 +#: createdb.c:307 +#, c-format +msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=LOKAL inbyggd lokal-inställning för databasen\n" + +#: createdb.c:308 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOKAL värde på ICU-lokal för databasen\n" -#: createdb.c:298 +#: createdb.c:309 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-rules=REGLER ICU-regler för databasen\n" -#: createdb.c:299 +#: createdb.c:310 #, c-format msgid "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default collation\n" msgstr "" -" --locale-provider={libc|icu}\n" +" --locale-provider={builtin|libc|icu}\n" " lokalleverantör av databasens standardjämförelser\n" -#: createdb.c:301 +#: createdb.c:312 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --owner=ÄGARE databasanvändare som äger nya databasen\n" -#: createdb.c:302 +#: createdb.c:313 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr "" " -S, --strategy=STRATEGI strategi för att skapa en databas, wal_log\n" " eller file_copy\n" -#: createdb.c:303 +#: createdb.c:314 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --template=MALL databasmall att kopiera\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:315 reindexdb.c:883 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:316 reindexdb.c:884 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:318 reindexdb.c:886 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=VÄRDNAMN databasens värdnamn eller socketkatalog\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:319 reindexdb.c:887 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT databasserverns port\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:320 reindexdb.c:888 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ANVÄNDARE användarnamn att ansluta som\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:321 reindexdb.c:889 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password fråga ej efter lösenord\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:322 reindexdb.c:890 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password framtvinga fråga om lösenord\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:323 reindexdb.c:891 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAMN annat val av underhållsdatabas\n" -#: createdb.c:313 +#: createdb.c:324 #, c-format msgid "" "\n" @@ -853,94 +925,54 @@ msgstr " -t, --timeout=SEK sekunder att vänta på anslutning; 0 stänge msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ANVÄNDARE användarnamn att ansluta som\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "kan inte omindexera alla databaser och samtidigt en specifik databas" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "kan inte omindexera alla databaser samtidigt med systemkatalogerna" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "kan inte omindexera angivna scheman i alla databaser" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "Kan inte indexera specifik tabell i alla databaser" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "Kan inte omindexera angivet index i alla databaser" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "kan inte omindexera angivna scheman och systemkataloger på samma gång" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "kan inte omindexera specifik tabell och systemkatalogerna samtidigt" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "kan inte omindexera angivna index och systemkatalogerna samtidigt." - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "kan inte använda multipla jobb för att omindexera systemkataloger" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "kan inte använda multipla jobb för att omindexera index" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "kan inte omindexera alla databaser och samtidigt en specifik databas" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:525 vacuumdb.c:532 vacuumdb.c:539 -#: vacuumdb.c:546 vacuumdb.c:553 vacuumdb.c:560 vacuumdb.c:567 vacuumdb.c:572 -#: vacuumdb.c:576 vacuumdb.c:580 vacuumdb.c:584 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 +#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 +#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "flaggan \"%s\" kan inte användas på serverversioner äldre än PostgreSQL %s" -#: reindexdb.c:561 +#: reindexdb.c:584 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "omindexering av databasen \"%s\" misslyckades: %s" -#: reindexdb.c:565 +#: reindexdb.c:588 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "omindexering av index \"%s\" i databasen \"%s\" misslyckades: %s" -#: reindexdb.c:569 +#: reindexdb.c:592 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "omindexering av schemat \"%s\" i databasen \"%s\" misslyckades: %s" -#: reindexdb.c:573 +#: reindexdb.c:596 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "omindexering av systemkataloger i databasen \"%s\" misslyckades: %s" -#: reindexdb.c:577 +#: reindexdb.c:600 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "omindexering av tabell \"%s\" i databasen \"%s\" misslyckades: %s" -#: reindexdb.c:732 +#: reindexdb.c:824 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: omindexering av databasen \"%s\"\n" -#: reindexdb.c:749 +#: reindexdb.c:867 #, c-format msgid "" "%s reindexes a PostgreSQL database.\n" @@ -949,64 +981,64 @@ msgstr "" "%s indexerar om en PostgreSQL-databas.\n" "\n" -#: reindexdb.c:753 +#: reindexdb.c:871 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all indexera om alla databaser\n" -#: reindexdb.c:754 +#: reindexdb.c:872 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently indexera om utan att låsa\n" -#: reindexdb.c:755 +#: reindexdb.c:873 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=DBNAME databas att indexera om\n" -#: reindexdb.c:757 +#: reindexdb.c:875 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX återskapa enbart angivna index\n" -#: reindexdb.c:758 +#: reindexdb.c:876 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr "" " -j, --jobs=NUM använd så här många samtida anslutningar\n" " för omindexering\n" -#: reindexdb.c:759 +#: reindexdb.c:877 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet skriv inte ut några meddelanden\n" -#: reindexdb.c:760 +#: reindexdb.c:878 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system indexera enbart om systemkataloger\n" -#: reindexdb.c:761 +#: reindexdb.c:879 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHEMA indexera enbart om angivna scheman\n" -#: reindexdb.c:762 +#: reindexdb.c:880 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABELL indexera enbart om angivna tabeller\n" -#: reindexdb.c:763 +#: reindexdb.c:881 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " --tablespace=TABELLRYMD tabellutrymme där index byggs om\n" -#: reindexdb.c:764 +#: reindexdb.c:882 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose skriv massor med utdata\n" -#: reindexdb.c:774 +#: reindexdb.c:892 #, c-format msgid "" "\n" @@ -1015,95 +1047,80 @@ msgstr "" "\n" "Läs beskrivningen av SQL-kommandot REINDEX för detaljer.\n" -#: vacuumdb.c:312 vacuumdb.c:315 vacuumdb.c:318 vacuumdb.c:321 vacuumdb.c:324 -#: vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:342 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "flaggan \"%s\" kan inte användas vid enbart analys" -#: vacuumdb.c:345 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "flaggan \"%s\" kan inte användas vid \"full vacuum\"" -#: vacuumdb.c:351 vacuumdb.c:359 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "flaggan \"%s\" kan inte användas tillsammans med flaggan \"%s\"" -#: vacuumdb.c:430 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "kan inte städa alla databaser och endast en angiven på samma gång" -#: vacuumdb.c:434 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "kan inte städa en specifik tabell i alla databaser." - -#: vacuumdb.c:438 -#, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "kan inte städa en angivna scheman i alla databaser." - -#: vacuumdb.c:442 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "kan inte exkludera angivna scheman i alla databaser" - -#: vacuumdb.c:446 +#: vacuumdb.c:436 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "kan inte städa alla tabeller i scheman samt angivna tabeller på samma gång" -#: vacuumdb.c:450 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "kan inte städa angivna scheman och exkludera scheman på samma gång" -#: vacuumdb.c:454 +#: vacuumdb.c:444 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "kan inte städa alla tabeller i scheman och exkludera scheman på samma gång" -#: vacuumdb.c:467 +#: vacuumdb.c:457 #, c-format msgid "out of memory" msgstr "slut på minne" -#: vacuumdb.c:512 +#: vacuumdb.c:502 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Skapar minimal optimeringsstatistik (1 mål)" -#: vacuumdb.c:513 +#: vacuumdb.c:503 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Skapar medium optimeringsstatistik (10 mål)" -#: vacuumdb.c:514 +#: vacuumdb.c:504 msgid "Generating default (full) optimizer statistics" msgstr "Skapar förvald (full) optimeringsstatistik" -#: vacuumdb.c:593 +#: vacuumdb.c:583 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: processar databasen \"%s\": %s\n" -#: vacuumdb.c:596 +#: vacuumdb.c:586 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: städar databasen \"%s\".\n" -#: vacuumdb.c:1138 +#: vacuumdb.c:1135 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "städning av tabell \"%s\" i databasen \"%s\" misslyckades: %s" -#: vacuumdb.c:1141 +#: vacuumdb.c:1138 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "städning av databasen \"%s\" misslyckades: %s" -#: vacuumdb.c:1149 +#: vacuumdb.c:1146 #, c-format msgid "" "%s cleans and analyzes a PostgreSQL database.\n" @@ -1112,134 +1129,134 @@ msgstr "" "%s städar och analyserar en PostgreSQL-databas.\n" "\n" -#: vacuumdb.c:1153 +#: vacuumdb.c:1150 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all städa i alla databaser\n" -#: vacuumdb.c:1154 +#: vacuumdb.c:1151 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=STORLEK storlek på ringbuffert som används vid städning\n" -#: vacuumdb.c:1155 +#: vacuumdb.c:1152 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=DBNAMN databas att städa i\n" -#: vacuumdb.c:1156 +#: vacuumdb.c:1153 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping stäng av alla sidöverhoppande beteeenden\n" -#: vacuumdb.c:1157 +#: vacuumdb.c:1154 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo visa kommandon som skickas till servern\n" -#: vacuumdb.c:1158 +#: vacuumdb.c:1155 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full utför full städning\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1156 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze frys information om radtransaktioner\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1157 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr " --force-index-cleanup ta alltid bort indexposter som pekar på döda tupler\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1158 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr " -j, --jobs=NUM använd så här många samtida anslutningar för städning\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1159 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr " --min-mxid-age=MXID_ÅLDER minimal multixact-ID-ålder i tabeller som skall städas\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1160 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr " --min-xid-age=XID_ÅLDER minimal transaktions-ID-ålder i tabeller som skall städas\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1161 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr " --no-index-cleanup ta inte bort indexposter som pekar på döda tupler\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1162 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main skippa huvudrelationen\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1163 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr " --no-process-toast hoppa över TOAST-tabellen som hör ihop med tabellen som städas\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1164 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate trunkera inte tomma sidor i slutet av tabellen\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1165 #, c-format -msgid " -n, --schema=PATTERN vacuum tables in the specified schema(s) only\n" -msgstr " -n, --schema=MALL städa enbart tabeller i angiva scheman\n" +msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" +msgstr " -n, --schema=SCHEMA städa enbart tabeller i angiva scheman\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1166 #, c-format -msgid " -N, --exclude-schema=PATTERN do not vacuum tables in the specified schema(s)\n" -msgstr " -N, --exclude-schema=MALL städa inte tabeller i angivna scheman\n" +msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" +msgstr " -N, --exclude-schema=SCHEMA städa inte tabeller i angivna scheman\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1167 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr "" " -P, --parallel=PARALLELLA_ARBETARE\n" " använda så här många bakgrundsarbetare för städning, om det finns\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1168 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet skriv inte ut några meddelanden\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1169 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr " --skip-locked hoppa äver relationer som inte kan låsas direkt\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1170 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='TABELL[(KOLUMNER)]' städa enbart i dessa tabeller\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1171 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose skriv massor med utdata\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1172 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version visa versionsinformation, avsluta sedan\n" -#: vacuumdb.c:1176 +#: vacuumdb.c:1173 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze uppdatera optimeringsstatistik\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1174 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr " -Z, --analyze-only uppdatera bara optimeringsstatistik; ingen städning\n" -#: vacuumdb.c:1178 +#: vacuumdb.c:1175 #, c-format msgid "" " --analyze-in-stages only update optimizer statistics, in multiple\n" @@ -1248,12 +1265,12 @@ msgstr "" " --analyze-in-stages uppdatera bara optimeringsstatistik, men i\n" " flera steg för snabbare resultat; ingen städning\n" -#: vacuumdb.c:1180 +#: vacuumdb.c:1177 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help visa denna hjälp, avsluta sedan\n" -#: vacuumdb.c:1188 +#: vacuumdb.c:1185 #, c-format msgid "" "\n" @@ -1261,15 +1278,3 @@ msgid "" msgstr "" "\n" "Läs beskrivningen av SQL-kommandot VACUUM för detaljer.\n" - -#, c-format -#~ msgid "cannot reindex system catalogs concurrently, skipping all" -#~ msgstr "kan inte omindexera systemkataloger parallellt, hoppar över alla" - -#, c-format -#~ msgid "only one of --locale and --lc-collate can be specified" -#~ msgstr "endast en av --locale och --lc-collate kan anges" - -#, c-format -#~ msgid "only one of --locale and --lc-ctype can be specified" -#~ msgstr "endast en av --locale och --lc-ctype kan anges" diff --git a/src/bin/scripts/po/uk.po b/src/bin/scripts/po/uk.po index 9d8769a622f1a..5ba97aa5045d0 100644 --- a/src/bin/scripts/po/uk.po +++ b/src/bin/scripts/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:19+0000\n" -"PO-Revision-Date: 2023-12-20 11:53\n" +"POT-Creation-Date: 2024-08-31 06:22+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/pgscripts.pot\n" -"X-Crowdin-File-ID: 967\n" +"X-Crowdin-File: /REL_17_STABLE/pgscripts.pot\n" +"X-Crowdin-File-ID: 1038\n" #: ../../../src/common/logging.c:276 #, c-format @@ -48,6 +48,48 @@ msgstr "недостатньо пам'яті\n" msgid "cannot duplicate null pointer (internal error)\n" msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n" +#: ../../common/file_utils.c:70 ../../common/file_utils.c:347 +#: ../../common/file_utils.c:406 ../../common/file_utils.c:480 +#, c-format +msgid "could not open file \"%s\": %m" +msgstr "не можливо відкрити файл \"%s\": %m" + +#: ../../common/file_utils.c:76 +#, c-format +msgid "could not synchronize file system for file \"%s\": %m" +msgstr "не вдалося синхронізувати файлову систему для файлу \"%s\": %m" + +#: ../../common/file_utils.c:120 ../../common/file_utils.c:566 +#, c-format +msgid "could not stat file \"%s\": %m" +msgstr "не вдалося отримати інформацію від файлу \"%s\": %m" + +#: ../../common/file_utils.c:130 ../../common/file_utils.c:227 +#: ../../fe_utils/option_utils.c:99 +#, c-format +msgid "this build does not support sync method \"%s\"" +msgstr "ця збірка не підтримує метод синхронізації \"%s\"" + +#: ../../common/file_utils.c:151 ../../common/file_utils.c:281 +#, c-format +msgid "could not open directory \"%s\": %m" +msgstr "не вдалося відкрити каталог \"%s\": %m" + +#: ../../common/file_utils.c:169 ../../common/file_utils.c:315 +#, c-format +msgid "could not read directory \"%s\": %m" +msgstr "не вдалося прочитати каталог \"%s\": %m" + +#: ../../common/file_utils.c:418 ../../common/file_utils.c:488 +#, c-format +msgid "could not fsync file \"%s\": %m" +msgstr "не вдалося fsync файл \"%s\": %m" + +#: ../../common/file_utils.c:498 +#, c-format +msgid "could not rename file \"%s\" to \"%s\": %m" +msgstr "не вдалося перейменувати файл \"%s\" на \"%s\": %m" + #: ../../common/username.c:43 #, c-format msgid "could not look up effective user ID %ld: %s" @@ -62,11 +104,11 @@ msgstr "користувача не існує" msgid "user name lookup failure: error code %lu" msgstr "невдала підстановка імені користувача: код помилки %lu" -#: ../../fe_utils/cancel.c:189 ../../fe_utils/cancel.c:238 +#: ../../fe_utils/cancel.c:186 ../../fe_utils/cancel.c:235 msgid "Cancel request sent\n" msgstr "Запит на скасування відправлений\n" -#: ../../fe_utils/cancel.c:190 ../../fe_utils/cancel.c:239 +#: ../../fe_utils/cancel.c:187 ../../fe_utils/cancel.c:236 msgid "Could not send cancel request: " msgstr "Не вдалося надіслати запит на скасування: " @@ -94,6 +136,11 @@ msgstr "неприпустиме значення \"%s\" для параметр msgid "%s must be in range %d..%d" msgstr "%s має бути в діапазоні %d..%d" +#: ../../fe_utils/option_utils.c:106 +#, c-format +msgid "unrecognized sync method: %s" +msgstr "нерозпізнаний метод синхронізації: %s" + #: ../../fe_utils/parallel_slot.c:317 #, c-format msgid "too many jobs for this platform: %d" @@ -128,17 +175,22 @@ msgstr[3] "(%lu рядка)" msgid "Interrupted\n" msgstr "Перервано\n" -#: ../../fe_utils/print.c:3218 +#: ../../fe_utils/print.c:3188 +#, c-format +msgid "Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n" +msgstr "Неможливо надрукувати вміст таблиці: кількість комірок %lld дорівнює або перевищує максимальне значення %lld.\n" + +#: ../../fe_utils/print.c:3229 #, c-format msgid "Cannot add header to table content: column count of %d exceeded.\n" msgstr "Неможливо додати заголовок до вмісту таблиці: кількість колонок %d перевищено.\n" -#: ../../fe_utils/print.c:3258 +#: ../../fe_utils/print.c:3272 #, c-format -msgid "Cannot add cell to table content: total cell count of %d exceeded.\n" -msgstr "Неможливо додати комірку до вмісту таблиці: перевищено загальну кількість комірок %d.\n" +msgid "Cannot add cell to table content: total cell count of %lld exceeded.\n" +msgstr "Неможливо додати комірку до вмісту таблиці: перевищено загальну кількість комірок %lld.\n" -#: ../../fe_utils/print.c:3516 +#: ../../fe_utils/print.c:3530 #, c-format msgid "invalid output format (internal error): %d" msgstr "невірний формат виводу (внутрішня помилка): %d" @@ -153,36 +205,41 @@ msgstr "запит не вдався: %s" msgid "Query was: %s" msgstr "Запит був: %s" -#: clusterdb.c:113 clusterdb.c:132 createdb.c:144 createdb.c:163 +#: ../../fe_utils/string_utils.c:434 +#, c-format +msgid "shell command argument contains a newline or carriage return: \"%s\"\n" +msgstr "аргумент командної оболонки містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: ../../fe_utils/string_utils.c:607 +#, c-format +msgid "database name contains a newline or carriage return: \"%s\"\n" +msgstr "назва бази даних містить символ нового рядка або повернення каретки: \"%s\"\n" + +#: clusterdb.c:114 clusterdb.c:133 createdb.c:149 createdb.c:168 #: createuser.c:195 createuser.c:210 dropdb.c:104 dropdb.c:113 dropdb.c:121 #: dropuser.c:95 dropuser.c:110 dropuser.c:123 pg_isready.c:97 pg_isready.c:111 -#: reindexdb.c:174 reindexdb.c:193 vacuumdb.c:279 vacuumdb.c:299 +#: reindexdb.c:177 reindexdb.c:196 vacuumdb.c:280 vacuumdb.c:300 #, c-format msgid "Try \"%s --help\" for more information." msgstr "Спробуйте \"%s --help\" для додаткової інформації." -#: clusterdb.c:130 createdb.c:161 createuser.c:208 dropdb.c:119 dropuser.c:108 -#: pg_isready.c:109 reindexdb.c:191 vacuumdb.c:297 +#: clusterdb.c:131 createdb.c:166 createuser.c:208 dropdb.c:119 dropuser.c:108 +#: pg_isready.c:109 reindexdb.c:194 vacuumdb.c:298 #, c-format msgid "too many command-line arguments (first is \"%s\")" msgstr "забагато аргументів у командному рядку (перший \"%s\")" -#: clusterdb.c:148 +#: clusterdb.c:149 #, c-format msgid "cannot cluster all databases and a specific one at the same time" msgstr "неможливо кластеризувати всі бази даних і одну вказану одночасно" -#: clusterdb.c:151 -#, c-format -msgid "cannot cluster specific table(s) in all databases" -msgstr "неможливо кластеризувати вказані таблиці у всіх базах даних" - -#: clusterdb.c:215 +#: clusterdb.c:214 #, c-format msgid "clustering of table \"%s\" in database \"%s\" failed: %s" msgstr "кластеризувати таблицю \"%s\" у базі даних \"%s\" не вдалося: %s" -#: clusterdb.c:218 +#: clusterdb.c:217 #, c-format msgid "clustering of database \"%s\" failed: %s" msgstr "кластеризувати базу даних \"%s\" не вдалося: %s" @@ -192,125 +249,125 @@ msgstr "кластеризувати базу даних \"%s\" не вдало msgid "%s: clustering database \"%s\"\n" msgstr "%s: кластеризація бази даних \"%s\"\n" -#: clusterdb.c:264 +#: clusterdb.c:274 #, c-format msgid "%s clusters all previously clustered tables in a database.\n\n" msgstr "%s кластеризація усіх попередньо кластеризованих таблиць в базі даних.\n\n" -#: clusterdb.c:265 createdb.c:288 createuser.c:415 dropdb.c:172 dropuser.c:170 -#: pg_isready.c:226 reindexdb.c:750 vacuumdb.c:1156 +#: clusterdb.c:275 createdb.c:298 createuser.c:415 dropdb.c:172 dropuser.c:170 +#: pg_isready.c:226 reindexdb.c:868 vacuumdb.c:1147 #, c-format msgid "Usage:\n" msgstr "Використання:\n" -#: clusterdb.c:266 reindexdb.c:751 vacuumdb.c:1157 +#: clusterdb.c:276 reindexdb.c:869 vacuumdb.c:1148 #, c-format msgid " %s [OPTION]... [DBNAME]\n" msgstr " %s [OPTION]... [DBNAME]\n" -#: clusterdb.c:267 createdb.c:290 createuser.c:417 dropdb.c:174 dropuser.c:172 -#: pg_isready.c:229 reindexdb.c:752 vacuumdb.c:1158 +#: clusterdb.c:277 createdb.c:300 createuser.c:417 dropdb.c:174 dropuser.c:172 +#: pg_isready.c:229 reindexdb.c:870 vacuumdb.c:1149 #, c-format msgid "\n" "Options:\n" msgstr "\n" "Параметри:\n" -#: clusterdb.c:268 +#: clusterdb.c:278 #, c-format msgid " -a, --all cluster all databases\n" msgstr " -a, --all кластеризація усіх баз даних\n" -#: clusterdb.c:269 +#: clusterdb.c:279 #, c-format msgid " -d, --dbname=DBNAME database to cluster\n" msgstr " -d, --dbname=ІМ'Я_БД база даних для кластеризації\n" -#: clusterdb.c:270 createuser.c:423 dropdb.c:175 dropuser.c:173 +#: clusterdb.c:280 createuser.c:423 dropdb.c:175 dropuser.c:173 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo показати команди, надіслані серверу\n" -#: clusterdb.c:271 +#: clusterdb.c:281 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не виводити жодних повідомлень\n" -#: clusterdb.c:272 +#: clusterdb.c:282 #, c-format msgid " -t, --table=TABLE cluster specific table(s) only\n" msgstr " -t, --table=ТАБЛИЦЯ кластеризувати тільки вказані таблиці\n" -#: clusterdb.c:273 +#: clusterdb.c:283 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose виводити багато інформації\n" -#: clusterdb.c:274 createuser.c:439 dropdb.c:178 dropuser.c:176 +#: clusterdb.c:284 createuser.c:439 dropdb.c:178 dropuser.c:176 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: clusterdb.c:275 createuser.c:447 dropdb.c:180 dropuser.c:178 +#: clusterdb.c:285 createuser.c:447 dropdb.c:180 dropuser.c:178 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: clusterdb.c:276 createdb.c:306 createuser.c:448 dropdb.c:181 dropuser.c:179 -#: pg_isready.c:235 reindexdb.c:767 vacuumdb.c:1187 +#: clusterdb.c:286 createdb.c:317 createuser.c:448 dropdb.c:181 dropuser.c:179 +#: pg_isready.c:235 reindexdb.c:885 vacuumdb.c:1178 #, c-format msgid "\n" "Connection options:\n" msgstr "\n" "Налаштування з'єднання:\n" -#: clusterdb.c:277 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1188 +#: clusterdb.c:287 createuser.c:449 dropdb.c:182 dropuser.c:180 vacuumdb.c:1179 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=HOSTNAME хост сервера бази даних або каталог сокетів\n" -#: clusterdb.c:278 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1189 +#: clusterdb.c:288 createuser.c:450 dropdb.c:183 dropuser.c:181 vacuumdb.c:1180 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=PORT порт сервера бази даних\n" -#: clusterdb.c:279 dropdb.c:184 vacuumdb.c:1190 +#: clusterdb.c:289 dropdb.c:184 vacuumdb.c:1181 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ІМ'Я_КОРИСТУВАЧА ім'я користувача для з'єднання з сервером\n" -#: clusterdb.c:280 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1191 +#: clusterdb.c:290 createuser.c:452 dropdb.c:185 dropuser.c:183 vacuumdb.c:1182 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не запитувати пароль\n" -#: clusterdb.c:281 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1192 +#: clusterdb.c:291 createuser.c:453 dropdb.c:186 dropuser.c:184 vacuumdb.c:1183 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password запросити пароль\n" -#: clusterdb.c:282 dropdb.c:187 vacuumdb.c:1193 +#: clusterdb.c:292 dropdb.c:187 vacuumdb.c:1184 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME альтернативна бази даних для обслуговування\n" -#: clusterdb.c:283 +#: clusterdb.c:293 #, c-format msgid "\n" "Read the description of the SQL command CLUSTER for details.\n" msgstr "\n" "Для деталей читайте опис команди SQL CLUSTER.\n" -#: clusterdb.c:284 createdb.c:314 createuser.c:454 dropdb.c:188 dropuser.c:185 -#: pg_isready.c:240 reindexdb.c:775 vacuumdb.c:1195 +#: clusterdb.c:294 createdb.c:325 createuser.c:454 dropdb.c:188 dropuser.c:185 +#: pg_isready.c:240 reindexdb.c:893 vacuumdb.c:1186 #, c-format msgid "\n" "Report bugs to <%s>.\n" msgstr "\n" "Повідомляти про помилки на <%s>.\n" -#: clusterdb.c:285 createdb.c:315 createuser.c:455 dropdb.c:189 dropuser.c:186 -#: pg_isready.c:241 reindexdb.c:776 vacuumdb.c:1196 +#: clusterdb.c:295 createdb.c:326 createuser.c:455 dropdb.c:189 dropuser.c:186 +#: pg_isready.c:241 reindexdb.c:894 vacuumdb.c:1187 #, c-format msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" @@ -346,134 +403,139 @@ msgstr "%s (%s/%s) " msgid "Please answer \"%s\" or \"%s\".\n" msgstr "Відповідь має бути \"%s\" або \"%s\".\n" -#: createdb.c:170 +#: createdb.c:175 #, c-format msgid "\"%s\" is not a valid encoding name" msgstr "\"%s\" не є невірним ім'ям кодування" -#: createdb.c:250 +#: createdb.c:260 #, c-format msgid "database creation failed: %s" msgstr "створити базу даних не вдалося: %s" -#: createdb.c:269 +#: createdb.c:279 #, c-format msgid "comment creation failed (database was created): %s" msgstr "не вдалося створити коментарі (база даних була створена): %s" -#: createdb.c:287 +#: createdb.c:297 #, c-format msgid "%s creates a PostgreSQL database.\n\n" msgstr "%s створює базу даних PostgreSQL.\n\n" -#: createdb.c:289 +#: createdb.c:299 #, c-format msgid " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" msgstr " %s [OPTION]... [DBNAME] [DESCRIPTION]\n" -#: createdb.c:291 +#: createdb.c:301 #, c-format msgid " -D, --tablespace=TABLESPACE default tablespace for the database\n" msgstr " -D, --tablespace=ТАБЛИЧНИЙ_ПРОСТІР табличний простір для бази даних за замовчуванням\n" -#: createdb.c:292 reindexdb.c:756 +#: createdb.c:302 reindexdb.c:874 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo показати команди, надіслані серверу\n" -#: createdb.c:293 +#: createdb.c:303 #, c-format msgid " -E, --encoding=ENCODING encoding for the database\n" msgstr " -E, --encoding=КОДУВАННЯ кодування бази даних\n" -#: createdb.c:294 +#: createdb.c:304 #, c-format msgid " -l, --locale=LOCALE locale settings for the database\n" msgstr " -l, --locale=ЛОКАЛЬ параметри локалі бази даних\n" -#: createdb.c:295 +#: createdb.c:305 #, c-format msgid " --lc-collate=LOCALE LC_COLLATE setting for the database\n" msgstr " --lc-collate=ЛОКАЛЬ параметр LC_COLLATE для бази даних\n" -#: createdb.c:296 +#: createdb.c:306 #, c-format msgid " --lc-ctype=LOCALE LC_CTYPE setting for the database\n" msgstr " --lc-ctype=ЛОКАЛЬ параметр LC_CTYPE для бази даних\n" -#: createdb.c:297 +#: createdb.c:307 +#, c-format +msgid " --builtin-locale=LOCALE builtin locale setting for the database\n" +msgstr " --builtin-locale=LOCALE параметри вбудованої локалі бази даних\n" + +#: createdb.c:308 #, c-format msgid " --icu-locale=LOCALE ICU locale setting for the database\n" msgstr " --icu-locale=LOCALE параметр локалі ICU бази даних\n" -#: createdb.c:298 +#: createdb.c:309 #, c-format msgid " --icu-rules=RULES ICU rules setting for the database\n" msgstr " --icu-locale=RULES правила ICU для бази даних\n" -#: createdb.c:299 +#: createdb.c:310 #, c-format -msgid " --locale-provider={libc|icu}\n" +msgid " --locale-provider={builtin|libc|icu}\n" " locale provider for the database's default collation\n" -msgstr " --locale-provider={libc|icu}\n" +msgstr " --locale-provider={builtin|libc|icu}\n" " провайдер локалі для сортування бази даних за замовчуванням\n" -#: createdb.c:301 +#: createdb.c:312 #, c-format msgid " -O, --owner=OWNER database user to own the new database\n" msgstr " -O, --власник=ВЛАСНИК користувач-власник нової бази даних\n" -#: createdb.c:302 +#: createdb.c:313 #, c-format msgid " -S, --strategy=STRATEGY database creation strategy wal_log or file_copy\n" msgstr " -S, --strategy=STRATEGY стратегія створення бази даних для wal_log або file_copy\n" -#: createdb.c:303 +#: createdb.c:314 #, c-format msgid " -T, --template=TEMPLATE template database to copy\n" msgstr " -T, --шаблон=ШАБЛОН шаблонна база даних для копіювання\n" -#: createdb.c:304 reindexdb.c:765 +#: createdb.c:315 reindexdb.c:883 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію, потім вийти\n" -#: createdb.c:305 reindexdb.c:766 +#: createdb.c:316 reindexdb.c:884 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю довідку, потім вийти\n" -#: createdb.c:307 reindexdb.c:768 +#: createdb.c:318 reindexdb.c:886 #, c-format msgid " -h, --host=HOSTNAME database server host or socket directory\n" msgstr " -h, --host=ІМ'Я_ХОСТА хост сервера бази даних або каталог сокетів\n" -#: createdb.c:308 reindexdb.c:769 +#: createdb.c:319 reindexdb.c:887 #, c-format msgid " -p, --port=PORT database server port\n" msgstr " -p, --port=ПОРТ порт сервера бази даних\n" -#: createdb.c:309 reindexdb.c:770 +#: createdb.c:320 reindexdb.c:888 #, c-format msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ІМ'Я_КОРИСТУВАЧА ім'я користувача для з'єднання з сервером\n" -#: createdb.c:310 reindexdb.c:771 +#: createdb.c:321 reindexdb.c:889 #, c-format msgid " -w, --no-password never prompt for password\n" msgstr " -w, --no-password ніколи не запитувати пароль\n" -#: createdb.c:311 reindexdb.c:772 +#: createdb.c:322 reindexdb.c:890 #, c-format msgid " -W, --password force password prompt\n" msgstr " -W, --password запросити пароль\n" -#: createdb.c:312 reindexdb.c:773 +#: createdb.c:323 reindexdb.c:891 #, c-format msgid " --maintenance-db=DBNAME alternate maintenance database\n" msgstr " --maintenance-db=DBNAME альтернативна бази даних для обслуговування\n" -#: createdb.c:313 +#: createdb.c:324 #, c-format msgid "\n" "By default, a database with the same name as the current user is created.\n" @@ -818,390 +880,335 @@ msgstr " -t, --timeout=SECS секунд для очікування пр msgid " -U, --username=USERNAME user name to connect as\n" msgstr " -U, --username=ІМ'Я_КОРИСТУВАЧА ім'я користувача для з'єднання з сервером\n" -#: reindexdb.c:209 -#, c-format -msgid "cannot reindex all databases and a specific one at the same time" -msgstr "неможливо переіндексувати всі бази даних і одну вказану одночасно" - -#: reindexdb.c:211 -#, c-format -msgid "cannot reindex all databases and system catalogs at the same time" -msgstr "не можливо переіндексувати всі бази даних і системні каталоги одночасно" - -#: reindexdb.c:213 -#, c-format -msgid "cannot reindex specific schema(s) in all databases" -msgstr "неможливо переіндексувати вказані схеми в усіх базах даних" - -#: reindexdb.c:215 -#, c-format -msgid "cannot reindex specific table(s) in all databases" -msgstr "неможливо переіндексувати вказані таблиці в усіх базах даних" - -#: reindexdb.c:217 -#, c-format -msgid "cannot reindex specific index(es) in all databases" -msgstr "неможливо переіндексувати вказані індекси в усіх базах даних" - -#: reindexdb.c:227 -#, c-format -msgid "cannot reindex specific schema(s) and system catalogs at the same time" -msgstr "не можливо переіндексувати вказані схеми і системні каталоги одночасно" - -#: reindexdb.c:229 -#, c-format -msgid "cannot reindex specific table(s) and system catalogs at the same time" -msgstr "не можливо переіндексувати вказані таблиці і системні каталоги одночасно" - -#: reindexdb.c:231 -#, c-format -msgid "cannot reindex specific index(es) and system catalogs at the same time" -msgstr "не можливо переіндексувати вказані індекси і системні каталоги одночасно" - -#: reindexdb.c:234 +#: reindexdb.c:210 #, c-format msgid "cannot use multiple jobs to reindex system catalogs" msgstr "не можна використовувати декілька завдань для переіндексування системних каталогів" -#: reindexdb.c:260 +#: reindexdb.c:215 #, c-format -msgid "cannot use multiple jobs to reindex indexes" -msgstr "не можна використовувати декілька завдань для переіндексування індексів" +msgid "cannot reindex all databases and a specific one at the same time" +msgstr "неможливо переіндексувати всі бази даних і одну вказану одночасно" -#: reindexdb.c:323 reindexdb.c:330 vacuumdb.c:525 vacuumdb.c:532 vacuumdb.c:539 -#: vacuumdb.c:546 vacuumdb.c:553 vacuumdb.c:560 vacuumdb.c:567 vacuumdb.c:572 -#: vacuumdb.c:576 vacuumdb.c:580 vacuumdb.c:584 +#: reindexdb.c:296 reindexdb.c:303 vacuumdb.c:515 vacuumdb.c:522 vacuumdb.c:529 +#: vacuumdb.c:536 vacuumdb.c:543 vacuumdb.c:550 vacuumdb.c:557 vacuumdb.c:562 +#: vacuumdb.c:566 vacuumdb.c:570 vacuumdb.c:574 #, c-format msgid "cannot use the \"%s\" option on server versions older than PostgreSQL %s" msgstr "не можна використовувати параметр \"%s\" на серверній версії старішій за PostgreSQL %s" -#: reindexdb.c:561 +#: reindexdb.c:584 #, c-format msgid "reindexing of database \"%s\" failed: %s" msgstr "переіндексувати базу даних \"%s\" не вдалося: %s" -#: reindexdb.c:565 +#: reindexdb.c:588 #, c-format msgid "reindexing of index \"%s\" in database \"%s\" failed: %s" msgstr "переіндексувати індекси \"%s\" в базі даних \"%s\" не вдалося: %s" -#: reindexdb.c:569 +#: reindexdb.c:592 #, c-format msgid "reindexing of schema \"%s\" in database \"%s\" failed: %s" msgstr "переіндексувати схему \"%s\" в базі даних \"%s\" не вдалося: %s" -#: reindexdb.c:573 +#: reindexdb.c:596 #, c-format msgid "reindexing of system catalogs in database \"%s\" failed: %s" msgstr "переіндексування системних каталогів в базі даних \"%s\" не вдалося: %s" -#: reindexdb.c:577 +#: reindexdb.c:600 #, c-format msgid "reindexing of table \"%s\" in database \"%s\" failed: %s" msgstr "переіндексувати таблиці \"%s\" в базі даних \"%s\" не вдалося: %s" -#: reindexdb.c:732 +#: reindexdb.c:824 #, c-format msgid "%s: reindexing database \"%s\"\n" msgstr "%s: переіндексування бази даних \"%s\"\n" -#: reindexdb.c:749 +#: reindexdb.c:867 #, c-format msgid "%s reindexes a PostgreSQL database.\n\n" msgstr "%s переіндексовує базу даних PostgreSQL.\n\n" -#: reindexdb.c:753 +#: reindexdb.c:871 #, c-format msgid " -a, --all reindex all databases\n" msgstr " -a, --all переіндексувати всі бази даних\n" -#: reindexdb.c:754 +#: reindexdb.c:872 #, c-format msgid " --concurrently reindex concurrently\n" msgstr " --concurrently переіндексувати одночасно\n" -#: reindexdb.c:755 +#: reindexdb.c:873 #, c-format msgid " -d, --dbname=DBNAME database to reindex\n" msgstr " -d, --dbname=DBNAME база даних для переіндексування\n" -#: reindexdb.c:757 +#: reindexdb.c:875 #, c-format msgid " -i, --index=INDEX recreate specific index(es) only\n" msgstr " -i, --index=INDEX повторно створити лише вказані індекси\n" -#: reindexdb.c:758 +#: reindexdb.c:876 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to reindex\n" msgstr " -j, --jobs=NUM використати цю кількість паралельних підключень для переіндексування\n" -#: reindexdb.c:759 +#: reindexdb.c:877 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не писати жодних повідомлень\n" -#: reindexdb.c:760 +#: reindexdb.c:878 #, c-format msgid " -s, --system reindex system catalogs only\n" msgstr " -s, --system переіндексувати тільки системні каталоги\n" -#: reindexdb.c:761 +#: reindexdb.c:879 #, c-format msgid " -S, --schema=SCHEMA reindex specific schema(s) only\n" msgstr " -S, --schema=SCHEMA переіндексувати лише вказані схеми\n" -#: reindexdb.c:762 +#: reindexdb.c:880 #, c-format msgid " -t, --table=TABLE reindex specific table(s) only\n" msgstr " -t, --table=TABLE переіндексувати лише вказані таблиці\n" -#: reindexdb.c:763 +#: reindexdb.c:881 #, c-format msgid " --tablespace=TABLESPACE tablespace where indexes are rebuilt\n" msgstr " --tablespace=TABLESPACE табличний простір для перебудованих індексів\n" -#: reindexdb.c:764 +#: reindexdb.c:882 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose виводити багато повідомлень\n" -#: reindexdb.c:774 +#: reindexdb.c:892 #, c-format msgid "\n" "Read the description of the SQL command REINDEX for details.\n" msgstr "\n" "Для деталей читайте опис команди SQL REINDEX.\n" -#: vacuumdb.c:312 vacuumdb.c:315 vacuumdb.c:318 vacuumdb.c:321 vacuumdb.c:324 -#: vacuumdb.c:327 vacuumdb.c:330 vacuumdb.c:333 vacuumdb.c:342 +#: vacuumdb.c:313 vacuumdb.c:316 vacuumdb.c:319 vacuumdb.c:322 vacuumdb.c:325 +#: vacuumdb.c:328 vacuumdb.c:331 vacuumdb.c:334 vacuumdb.c:343 #, c-format msgid "cannot use the \"%s\" option when performing only analyze" msgstr "не можна використовувати параметр \"%s\" під час виконання лише аналіза" -#: vacuumdb.c:345 +#: vacuumdb.c:346 #, c-format msgid "cannot use the \"%s\" option when performing full vacuum" msgstr "не можна використовувати параметр \"%s\" під час виконання VACUUM FULL" -#: vacuumdb.c:351 vacuumdb.c:359 +#: vacuumdb.c:352 vacuumdb.c:360 #, c-format msgid "cannot use the \"%s\" option with the \"%s\" option" msgstr "використовувати параметр \"%s\" з параметром \"%s\" не можна" -#: vacuumdb.c:430 +#: vacuumdb.c:432 #, c-format msgid "cannot vacuum all databases and a specific one at the same time" msgstr "неможливо очистити всі бази даних і одну вказану одночасно" -#: vacuumdb.c:434 -#, c-format -msgid "cannot vacuum specific table(s) in all databases" -msgstr "неможливо очистити вказані таблиці в усіх базах даних" - -#: vacuumdb.c:438 -#, c-format -msgid "cannot vacuum specific schema(s) in all databases" -msgstr "неможливо очистити вказані схеми в усіх базах даних" - -#: vacuumdb.c:442 -#, c-format -msgid "cannot exclude specific schema(s) in all databases" -msgstr "неможливо виключити вказані схеми в усіх базах даних" - -#: vacuumdb.c:446 +#: vacuumdb.c:436 #, c-format msgid "cannot vacuum all tables in schema(s) and specific table(s) at the same time" msgstr "неможливо очистити всі таблиці в схемах та вказані таблиці одночасно" -#: vacuumdb.c:450 +#: vacuumdb.c:440 #, c-format msgid "cannot vacuum specific table(s) and exclude schema(s) at the same time" msgstr "неможливо очистити вказані таблиці і виключити схеми одночасно" -#: vacuumdb.c:454 +#: vacuumdb.c:444 #, c-format msgid "cannot vacuum all tables in schema(s) and exclude schema(s) at the same time" msgstr "неможливо очистити всі таблиці в схемах та виключити схеми одночасно" -#: vacuumdb.c:467 +#: vacuumdb.c:457 #, c-format msgid "out of memory" msgstr "недостатньо пам'яті" -#: vacuumdb.c:512 +#: vacuumdb.c:502 msgid "Generating minimal optimizer statistics (1 target)" msgstr "Генерування мінімальної статистики для оптімизатора (1 мета)" -#: vacuumdb.c:513 +#: vacuumdb.c:503 msgid "Generating medium optimizer statistics (10 targets)" msgstr "Генерування середньої статистики для оптимізатора (10 цілей)" -#: vacuumdb.c:514 +#: vacuumdb.c:504 msgid "Generating default (full) optimizer statistics" msgstr "Генерування статистики для оптимізатора за замовчуванням (повністю)" -#: vacuumdb.c:593 +#: vacuumdb.c:583 #, c-format msgid "%s: processing database \"%s\": %s\n" msgstr "%s: обробка бази даних \"%s\": %s\n" -#: vacuumdb.c:596 +#: vacuumdb.c:586 #, c-format msgid "%s: vacuuming database \"%s\"\n" msgstr "%s: очищення бази даних \"%s\"\n" -#: vacuumdb.c:1144 +#: vacuumdb.c:1135 #, c-format msgid "vacuuming of table \"%s\" in database \"%s\" failed: %s" msgstr "очистити таблиці \"%s\" в базі даних \"%s\" не вдалося: %s" -#: vacuumdb.c:1147 +#: vacuumdb.c:1138 #, c-format msgid "vacuuming of database \"%s\" failed: %s" msgstr "очистити базу даних \"%s\" не вдалося: %s" -#: vacuumdb.c:1155 +#: vacuumdb.c:1146 #, c-format msgid "%s cleans and analyzes a PostgreSQL database.\n\n" msgstr "%s очищує й аналізує базу даних PostgreSQL.\n\n" -#: vacuumdb.c:1159 +#: vacuumdb.c:1150 #, c-format msgid " -a, --all vacuum all databases\n" msgstr " -a, --all очистити усі бази даних\n" -#: vacuumdb.c:1160 +#: vacuumdb.c:1151 #, c-format msgid " --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n" msgstr " --buffer-usage-limit=SIZE розмір кільцевого буферу для очистки\n" -#: vacuumdb.c:1161 +#: vacuumdb.c:1152 #, c-format msgid " -d, --dbname=DBNAME database to vacuum\n" msgstr " -d, --dbname=ІМ'Я_БД база даних для очищення\n" -#: vacuumdb.c:1162 +#: vacuumdb.c:1153 #, c-format msgid " --disable-page-skipping disable all page-skipping behavior\n" msgstr " --disable-page-skipping відключити пропуск сторінок\n" -#: vacuumdb.c:1163 +#: vacuumdb.c:1154 #, c-format msgid " -e, --echo show the commands being sent to the server\n" msgstr " -e, --echo показати команди, надіслані серверу\n" -#: vacuumdb.c:1164 +#: vacuumdb.c:1155 #, c-format msgid " -f, --full do full vacuuming\n" msgstr " -f, --full зробити повне очищення\n" -#: vacuumdb.c:1165 +#: vacuumdb.c:1156 #, c-format msgid " -F, --freeze freeze row transaction information\n" msgstr " -F, --freeze заморозити інформацію щодо транзакцій в рядках\n" -#: vacuumdb.c:1166 +#: vacuumdb.c:1157 #, c-format msgid " --force-index-cleanup always remove index entries that point to dead tuples\n" msgstr " --force-index-cleanup завжди видаляти записи індексів, які вказують на мертві кортежі\n" -#: vacuumdb.c:1167 +#: vacuumdb.c:1158 #, c-format msgid " -j, --jobs=NUM use this many concurrent connections to vacuum\n" msgstr " -j, --jobs=ЧИСЛО використати ці паралельні підключення для очищення\n" -#: vacuumdb.c:1168 +#: vacuumdb.c:1159 #, c-format msgid " --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n" msgstr " --min-mxid-age=MXID_AGE мінімальний ID ери мультитранзакції таблиць для вакууму\n" -#: vacuumdb.c:1169 +#: vacuumdb.c:1160 #, c-format msgid " --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n" msgstr " --min-mxid-age=MXID_AGE мінімальний ID ери транзакції таблиць для вакууму\n" -#: vacuumdb.c:1170 +#: vacuumdb.c:1161 #, c-format msgid " --no-index-cleanup don't remove index entries that point to dead tuples\n" msgstr " --no-index-cleanup не видаляти записи індексів, які вказують на мертві кортежі\n" -#: vacuumdb.c:1171 +#: vacuumdb.c:1162 #, c-format msgid " --no-process-main skip the main relation\n" msgstr " --no-process-main пропустити головне відношення\n" -#: vacuumdb.c:1172 +#: vacuumdb.c:1163 #, c-format msgid " --no-process-toast skip the TOAST table associated with the table to vacuum\n" msgstr " --no-process-toast пропускати таблицю TOAST, пов'язану з таблицею для очищення\n" -#: vacuumdb.c:1173 +#: vacuumdb.c:1164 #, c-format msgid " --no-truncate don't truncate empty pages at the end of the table\n" msgstr " --no-truncate не скорочувати пусті сторінки наприкінці таблиці\n" -#: vacuumdb.c:1174 +#: vacuumdb.c:1165 #, c-format msgid " -n, --schema=SCHEMA vacuum tables in the specified schema(s) only\n" msgstr " -n, --schema=SCHEMA очистити тільки таблиці у вказаних схемах\n" -#: vacuumdb.c:1175 +#: vacuumdb.c:1166 #, c-format msgid " -N, --exclude-schema=SCHEMA do not vacuum tables in the specified schema(s)\n" msgstr " -N, --exclude-schema=SCHEMA не очищати таблиці у вказаних схемах\n" -#: vacuumdb.c:1176 +#: vacuumdb.c:1167 #, c-format msgid " -P, --parallel=PARALLEL_WORKERS use this many background workers for vacuum, if available\n" msgstr " -P, --parallel=PARALLEL_WORKERS використати таку кількість фонових робітників для очищення, якщо вони доступні\n" -#: vacuumdb.c:1177 +#: vacuumdb.c:1168 #, c-format msgid " -q, --quiet don't write any messages\n" msgstr " -q, --quiet не писати жодних повідомлень\n" -#: vacuumdb.c:1178 +#: vacuumdb.c:1169 #, c-format msgid " --skip-locked skip relations that cannot be immediately locked\n" msgstr " --skip-locked пропустити відношення, що не можуть бути заблоковані негайно\n" -#: vacuumdb.c:1179 +#: vacuumdb.c:1170 #, c-format msgid " -t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only\n" msgstr " -t, --table='ТАБЛИЦЯ[(СТОВПЦІ)]' очистити тільки вказані таблиці\n" -#: vacuumdb.c:1180 +#: vacuumdb.c:1171 #, c-format msgid " -v, --verbose write a lot of output\n" msgstr " -v, --verbose виводити багато інформації\n" -#: vacuumdb.c:1181 +#: vacuumdb.c:1172 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version вивести інформацію про версію і вийти\n" -#: vacuumdb.c:1182 +#: vacuumdb.c:1173 #, c-format msgid " -z, --analyze update optimizer statistics\n" msgstr " -z, --analyze оновити статистику для оптимізатора\n" -#: vacuumdb.c:1183 +#: vacuumdb.c:1174 #, c-format msgid " -Z, --analyze-only only update optimizer statistics; no vacuum\n" msgstr " -Z, --analyze-only оновити лише статистику для оптимізатора, не очищати\n" -#: vacuumdb.c:1184 +#: vacuumdb.c:1175 #, c-format msgid " --analyze-in-stages only update optimizer statistics, in multiple\n" " stages for faster results; no vacuum\n" msgstr " --analyze-in-stages оновити лише статистику для оптимізатора, у декілька стадій для швидших результатів, не очищати\n" -#: vacuumdb.c:1186 +#: vacuumdb.c:1177 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help показати цю справку, потім вийти\n" -#: vacuumdb.c:1194 +#: vacuumdb.c:1185 #, c-format msgid "\n" "Read the description of the SQL command VACUUM for details.\n" diff --git a/src/bin/scripts/po/zh_CN.po b/src/bin/scripts/po/zh_CN.po index 12c75603ec1a9..6a5262d069574 100644 --- a/src/bin/scripts/po/zh_CN.po +++ b/src/bin/scripts/po/zh_CN.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: pgscripts (PostgreSQL) 14\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2021-08-14 05:47+0000\n" -"PO-Revision-Date: 2021-08-15 18:30+0800\n" +"PO-Revision-Date: 2024-06-26 11:01+0200\n" "Last-Translator: Jie Zhang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" @@ -892,7 +892,7 @@ msgstr " -a, --all 对所有数据库进行重建索引操 #: reindexdb.c:796 msgid " --concurrently reindex concurrently\n" -msgstr " --concurrently 同时重新索引\n" +msgstr " --concurrently 同时重新索引\n" #: reindexdb.c:797 msgid " -d, --dbname=DBNAME database to reindex\n" diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c index 904c196fbbaa8..8ddcc5312f754 100644 --- a/src/bin/scripts/reindexdb.c +++ b/src/bin/scripts/reindexdb.c @@ -2,7 +2,7 @@ * * reindexdb * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/bin/scripts/reindexdb.c * @@ -12,10 +12,10 @@ #include "postgres_fe.h" #include +#include #include "catalog/pg_class_d.h" #include "common.h" -#include "common/connect.h" #include "common/logging.h" #include "fe_utils/cancel.h" #include "fe_utils/option_utils.h" @@ -34,10 +34,14 @@ typedef enum ReindexType } ReindexType; -static SimpleStringList *get_parallel_object_list(PGconn *conn, +static SimpleStringList *get_parallel_tables_list(PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo); +static void get_parallel_tabidx_list(PGconn *conn, + SimpleStringList *index_list, + SimpleOidList **table_list, + bool echo); static void reindex_one_database(ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, @@ -50,10 +54,13 @@ static void reindex_all_databases(ConnParams *cparams, bool syscatalog, SimpleStringList *schemas, SimpleStringList *tables, SimpleStringList *indexes); -static void run_reindex_command(PGconn *conn, ReindexType type, +static void gen_reindex_command(PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, - bool concurrently, bool async, - const char *tablespace); + bool concurrently, const char *tablespace, + PQExpBufferData *sql); +static void run_reindex_command(PGconn *conn, ReindexType type, + const char *name, bool echo, + PQExpBufferData *sql); static void help(const char *progname); @@ -277,15 +284,14 @@ reindex_one_database(ConnParams *cparams, ReindexType type, { PGconn *conn; SimpleStringListCell *cell; - SimpleStringListCell *indices_tables_cell = NULL; + SimpleOidListCell *indices_tables_cell = NULL; bool parallel = concurrentCons > 1; - SimpleStringList *process_list = user_list; - SimpleStringList *indices_tables_list = NULL; + SimpleStringList *process_list = NULL; + SimpleOidList *tableoid_list = NULL; ReindexType process_type = type; ParallelSlotArray *sa; bool failed = false; int items_count = 0; - char *prev_index_table_name = NULL; ParallelSlot *free_slot = NULL; conn = connectDatabase(cparams, progname, echo, false, true); @@ -323,6 +329,7 @@ reindex_one_database(ConnParams *cparams, ReindexType type, case REINDEX_INDEX: case REINDEX_SCHEMA: case REINDEX_TABLE: + process_list = user_list; Assert(user_list != NULL); break; } @@ -331,68 +338,54 @@ reindex_one_database(ConnParams *cparams, ReindexType type, { switch (process_type) { - case REINDEX_DATABASE: - - /* Build a list of relations from the database */ - process_list = get_parallel_object_list(conn, process_type, - user_list, echo); - process_type = REINDEX_TABLE; - - /* Bail out if nothing to process */ - if (process_list == NULL) - return; - break; - case REINDEX_SCHEMA: Assert(user_list != NULL); + /* fall through */ - /* Build a list of relations from all the schemas */ - process_list = get_parallel_object_list(conn, process_type, + case REINDEX_DATABASE: + + /* Build a list of relations from the database */ + process_list = get_parallel_tables_list(conn, process_type, user_list, echo); process_type = REINDEX_TABLE; /* Bail out if nothing to process */ if (process_list == NULL) + { + PQfinish(conn); return; + } break; case REINDEX_INDEX: Assert(user_list != NULL); /* - * Build a list of relations from the indices. This will - * accordingly reorder the list of indices too. + * Generate a list of indexes and a matching list of table + * OIDs, based on the user-specified index names. */ - indices_tables_list = get_parallel_object_list(conn, process_type, - user_list, echo); + get_parallel_tabidx_list(conn, user_list, &tableoid_list, + echo); - /* - * Bail out if nothing to process. 'user_list' was modified - * in-place, so check if it has at least one cell. - */ - if (user_list->head == NULL) + /* Bail out if nothing to process */ + if (tableoid_list == NULL) + { + PQfinish(conn); return; + } - /* - * Assuming 'user_list' is not empty, 'indices_tables_list' - * shouldn't be empty as well. - */ - Assert(indices_tables_list != NULL); - indices_tables_cell = indices_tables_list->head; - + indices_tables_cell = tableoid_list->head; + process_list = user_list; break; case REINDEX_SYSTEM: /* not supported */ + process_list = NULL; Assert(false); break; case REINDEX_TABLE: - - /* - * Fall through. The list of items for tables is already - * created. - */ + process_list = user_list; break; } } @@ -402,6 +395,7 @@ reindex_one_database(ConnParams *cparams, ReindexType type, * the list. We choose the minimum between the number of concurrent * connections and the number of items in the list. */ + items_count = 0; for (cell = process_list->head; cell; cell = cell->next) { items_count++; @@ -417,12 +411,13 @@ reindex_one_database(ConnParams *cparams, ReindexType type, sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL); ParallelSlotsAdoptConn(sa, conn); + conn = NULL; cell = process_list->head; do { + PQExpBufferData sql; const char *objname = cell->val; - bool need_new_slot = true; if (CancelRequested) { @@ -430,35 +425,45 @@ reindex_one_database(ConnParams *cparams, ReindexType type, goto finish; } - /* - * For parallel index-level REINDEX, the indices of the same table are - * ordered together and they are to be processed by the same job. So, - * we don't switch the job as soon as the index belongs to the same - * table as the previous one. - */ - if (parallel && process_type == REINDEX_INDEX) + free_slot = ParallelSlotsGetIdle(sa, NULL); + if (!free_slot) { - if (prev_index_table_name != NULL && - strcmp(prev_index_table_name, indices_tables_cell->val) == 0) - need_new_slot = false; - prev_index_table_name = indices_tables_cell->val; - indices_tables_cell = indices_tables_cell->next; + failed = true; + goto finish; } - if (need_new_slot) + ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); + initPQExpBuffer(&sql); + if (parallel && process_type == REINDEX_INDEX) { - free_slot = ParallelSlotsGetIdle(sa, NULL); - if (!free_slot) + /* + * For parallel index-level REINDEX, the indices of the same table + * are ordered together and they are to be processed by the same + * job. So, we put all the relevant REINDEX commands into the + * same SQL query to be processed by this job at once. + */ + gen_reindex_command(free_slot->connection, process_type, objname, + echo, verbose, concurrently, tablespace, &sql); + while (indices_tables_cell->next && + indices_tables_cell->val == indices_tables_cell->next->val) { - failed = true; - goto finish; + indices_tables_cell = indices_tables_cell->next; + cell = cell->next; + objname = cell->val; + appendPQExpBufferChar(&sql, '\n'); + gen_reindex_command(free_slot->connection, process_type, objname, + echo, verbose, concurrently, tablespace, &sql); } - - ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); + indices_tables_cell = indices_tables_cell->next; + } + else + { + gen_reindex_command(free_slot->connection, process_type, objname, + echo, verbose, concurrently, tablespace, &sql); } - run_reindex_command(free_slot->connection, process_type, objname, - echo, verbose, concurrently, true, tablespace); + echo, &sql); + termPQExpBuffer(&sql); cell = cell->next; } while (cell != NULL); @@ -473,10 +478,10 @@ reindex_one_database(ConnParams *cparams, ReindexType type, pg_free(process_list); } - if (indices_tables_list) + if (tableoid_list) { - simple_string_list_destroy(indices_tables_list); - pg_free(indices_tables_list); + simple_oid_list_destroy(tableoid_list); + pg_free(tableoid_list); } ParallelSlotsTerminate(sa); @@ -486,56 +491,57 @@ reindex_one_database(ConnParams *cparams, ReindexType type, exit(1); } +/* + * Append a SQL command required to reindex a given database object to the + * '*sql' string. + */ static void -run_reindex_command(PGconn *conn, ReindexType type, const char *name, - bool echo, bool verbose, bool concurrently, bool async, - const char *tablespace) +gen_reindex_command(PGconn *conn, ReindexType type, const char *name, + bool echo, bool verbose, bool concurrently, + const char *tablespace, PQExpBufferData *sql) { const char *paren = "("; const char *comma = ", "; const char *sep = paren; - PQExpBufferData sql; - bool status; Assert(name); /* build the REINDEX query */ - initPQExpBuffer(&sql); - - appendPQExpBufferStr(&sql, "REINDEX "); + appendPQExpBufferStr(sql, "REINDEX "); if (verbose) { - appendPQExpBuffer(&sql, "%sVERBOSE", sep); + appendPQExpBuffer(sql, "%sVERBOSE", sep); sep = comma; } if (tablespace) { - appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep, fmtId(tablespace)); + appendPQExpBuffer(sql, "%sTABLESPACE %s", sep, + fmtIdEnc(tablespace, PQclientEncoding(conn))); sep = comma; } if (sep != paren) - appendPQExpBufferStr(&sql, ") "); + appendPQExpBufferStr(sql, ") "); /* object type */ switch (type) { case REINDEX_DATABASE: - appendPQExpBufferStr(&sql, "DATABASE "); + appendPQExpBufferStr(sql, "DATABASE "); break; case REINDEX_INDEX: - appendPQExpBufferStr(&sql, "INDEX "); + appendPQExpBufferStr(sql, "INDEX "); break; case REINDEX_SCHEMA: - appendPQExpBufferStr(&sql, "SCHEMA "); + appendPQExpBufferStr(sql, "SCHEMA "); break; case REINDEX_SYSTEM: - appendPQExpBufferStr(&sql, "SYSTEM "); + appendPQExpBufferStr(sql, "SYSTEM "); break; case REINDEX_TABLE: - appendPQExpBufferStr(&sql, "TABLE "); + appendPQExpBufferStr(sql, "TABLE "); break; } @@ -545,36 +551,43 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name, * object type. */ if (concurrently) - appendPQExpBufferStr(&sql, "CONCURRENTLY "); + appendPQExpBufferStr(sql, "CONCURRENTLY "); /* object name */ switch (type) { case REINDEX_DATABASE: case REINDEX_SYSTEM: - appendPQExpBufferStr(&sql, fmtId(name)); + appendPQExpBufferStr(sql, + fmtIdEnc(name, PQclientEncoding(conn))); break; case REINDEX_INDEX: case REINDEX_TABLE: - appendQualifiedRelation(&sql, name, conn, echo); + appendQualifiedRelation(sql, name, conn, echo); break; case REINDEX_SCHEMA: - appendPQExpBufferStr(&sql, name); + appendPQExpBufferStr(sql, name); break; } /* finish the query */ - appendPQExpBufferChar(&sql, ';'); + appendPQExpBufferChar(sql, ';'); +} - if (async) - { - if (echo) - printf("%s\n", sql.data); +/* + * Run one or more reindex commands accumulated in the '*sql' string against + * a given database connection. + */ +static void +run_reindex_command(PGconn *conn, ReindexType type, const char *name, + bool echo, PQExpBufferData *sql) +{ + bool status; - status = PQsendQuery(conn, sql.data) == 1; - } - else - status = executeMaintenanceCommand(conn, sql.data, echo); + if (echo) + printf("%s\n", sql->data); + + status = PQsendQuery(conn, sql->data) == 1; if (!status) { @@ -601,18 +614,11 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name, name, PQdb(conn), PQerrorMessage(conn)); break; } - if (!async) - { - PQfinish(conn); - exit(1); - } } - - termPQExpBuffer(&sql); } /* - * Prepare the list of objects to process by querying the catalogs. + * Prepare the list of tables to process by querying the catalogs. * * This function will return a SimpleStringList object containing the entire * list of tables in the given database that should be processed by a parallel @@ -620,15 +626,13 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name, * table. */ static SimpleStringList * -get_parallel_object_list(PGconn *conn, ReindexType type, +get_parallel_tables_list(PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo) { PQExpBufferData catalog_query; - PQExpBufferData buf; PGresult *res; SimpleStringList *tables; - int ntups, - i; + int ntups; initPQExpBuffer(&catalog_query); @@ -649,13 +653,14 @@ get_parallel_object_list(PGconn *conn, ReindexType type, " AND c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_MATVIEW) ")\n" + " AND c.relpersistence != " + CppAsString2(RELPERSISTENCE_TEMP) "\n" " ORDER BY c.relpages DESC;"); break; case REINDEX_SCHEMA: { SimpleStringListCell *cell; - bool nsp_listed = false; Assert(user_list != NULL); @@ -671,18 +676,16 @@ get_parallel_object_list(PGconn *conn, ReindexType type, " WHERE c.relkind IN (" CppAsString2(RELKIND_RELATION) ", " CppAsString2(RELKIND_MATVIEW) ")\n" + " AND c.relpersistence != " + CppAsString2(RELPERSISTENCE_TEMP) "\n" " AND ns.nspname IN ("); for (cell = user_list->head; cell; cell = cell->next) { - const char *nspname = cell->val; - - if (nsp_listed) - appendPQExpBufferStr(&catalog_query, ", "); - else - nsp_listed = true; + if (cell != user_list->head) + appendPQExpBufferChar(&catalog_query, ','); - appendStringLiteralConn(&catalog_query, nspname, conn); + appendStringLiteralConn(&catalog_query, cell->val, conn); } appendPQExpBufferStr(&catalog_query, ")\n" @@ -691,59 +694,6 @@ get_parallel_object_list(PGconn *conn, ReindexType type, break; case REINDEX_INDEX: - { - SimpleStringListCell *cell; - - Assert(user_list != NULL); - - /* - * Straight-forward index-level REINDEX is not supported with - * multiple jobs as we cannot control the concurrent - * processing of multiple indexes depending on the same - * relation. But we can extract the appropriate table name - * for the index and put REINDEX INDEX commands into different - * jobs, according to the parent tables. - * - * We will order the results to group the same tables - * together. We fetch index names as well to build a new list - * of them with matching order. - */ - appendPQExpBufferStr(&catalog_query, - "SELECT t.relname, n.nspname, i.relname\n" - "FROM pg_catalog.pg_index x\n" - "JOIN pg_catalog.pg_class t ON t.oid = x.indrelid\n" - "JOIN pg_catalog.pg_class i ON i.oid = x.indexrelid\n" - "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace\n" - "WHERE x.indexrelid OPERATOR(pg_catalog.=) ANY(ARRAY['"); - - for (cell = user_list->head; cell; cell = cell->next) - { - if (cell != user_list->head) - appendPQExpBufferStr(&catalog_query, "', '"); - - appendQualifiedRelation(&catalog_query, cell->val, conn, echo); - } - - /* - * Order tables by the size of its greatest index. Within the - * table, order indexes by their sizes. - */ - appendPQExpBufferStr(&catalog_query, - "']::pg_catalog.regclass[])\n" - "ORDER BY max(i.relpages) OVER \n" - " (PARTITION BY n.nspname, t.relname),\n" - " n.nspname, t.relname, i.relpages;\n"); - - /* - * We're going to re-order the user_list to match the order of - * tables. So, empty the user_list to fill it from the query - * result. - */ - simple_string_list_destroy(user_list); - user_list->head = user_list->tail = NULL; - } - break; - case REINDEX_SYSTEM: case REINDEX_TABLE: Assert(false); @@ -760,41 +710,121 @@ get_parallel_object_list(PGconn *conn, ReindexType type, if (ntups == 0) { PQclear(res); - PQfinish(conn); return NULL; } tables = pg_malloc0(sizeof(SimpleStringList)); /* Build qualified identifiers for each table */ - initPQExpBuffer(&buf); - for (i = 0; i < ntups; i++) + for (int i = 0; i < ntups; i++) { - appendPQExpBufferStr(&buf, - fmtQualifiedId(PQgetvalue(res, i, 1), - PQgetvalue(res, i, 0))); + simple_string_list_append(tables, + fmtQualifiedIdEnc(PQgetvalue(res, i, 1), + PQgetvalue(res, i, 0), + PQclientEncoding(conn))); + } + PQclear(res); - simple_string_list_append(tables, buf.data); - resetPQExpBuffer(&buf); + return tables; +} - if (type == REINDEX_INDEX) - { - /* - * For index-level REINDEX, rebuild the list of indexes to match - * the order of tables list. - */ - appendPQExpBufferStr(&buf, - fmtQualifiedId(PQgetvalue(res, i, 1), - PQgetvalue(res, i, 2))); +/* + * Given a user-specified list of indexes, prepare a matching list + * indexes to process, and also a matching list of table OIDs to which each + * index belongs. The latter is needed to avoid scheduling two parallel tasks + * with concurrent reindexing of indexes on the same table. + * + * On input, index_list is the user-specified index list. table_list is an + * output argument which is filled with a list of the tables to process; on + * output, index_list is a matching reordered list of indexes. Caller is + * supposed to walk both lists in unison. Both pointers will be NULL if + * there's nothing to process. + */ +static void +get_parallel_tabidx_list(PGconn *conn, + SimpleStringList *index_list, + SimpleOidList **table_list, + bool echo) +{ + PQExpBufferData catalog_query; + PGresult *res; + SimpleStringListCell *cell; + int ntups; - simple_string_list_append(user_list, buf.data); - resetPQExpBuffer(&buf); - } + Assert(index_list != NULL); + + initPQExpBuffer(&catalog_query); + + /* + * The queries here are using a safe search_path, so there's no need to + * fully qualify everything. + */ + + /* + * We cannot use REINDEX in parallel in a straightforward way, because + * we'd be unable to control concurrent processing of multiple indexes on + * the same table. But we can extract the table OID together with each + * index, so that we can send all the REINDEX INDEX commands for the same + * table together on one parallel job. + */ + appendPQExpBufferStr(&catalog_query, + "SELECT x.indrelid, n.nspname, i.relname\n" + "FROM pg_catalog.pg_index x\n" + "JOIN pg_catalog.pg_class i ON i.oid = x.indexrelid\n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = i.relnamespace\n" + "WHERE x.indexrelid = ANY(ARRAY['"); + + for (cell = index_list->head; cell; cell = cell->next) + { + if (cell != index_list->head) + appendPQExpBufferStr(&catalog_query, "', '"); + + appendQualifiedRelation(&catalog_query, cell->val, conn, echo); } - termPQExpBuffer(&buf); - PQclear(res); - return tables; + /* + * We want all indexes of the same table together. Order tables by the + * size of its greatest index. Within each table, order indexes by size. + */ + appendPQExpBufferStr(&catalog_query, + "']::pg_catalog.regclass[])\n" + "ORDER BY max(i.relpages) OVER \n" + " (PARTITION BY x.indrelid),\n" + " x.indrelid, i.relpages;\n"); + + /* Empty the original index_list to fill it from the query result. */ + simple_string_list_destroy(index_list); + index_list->head = index_list->tail = NULL; + + res = executeQuery(conn, catalog_query.data, echo); + termPQExpBuffer(&catalog_query); + + /* + * If no rows are returned, there are no matching tables, so we are done. + */ + ntups = PQntuples(res); + if (ntups == 0) + { + PQclear(res); + return; + } + + *table_list = pg_malloc0(sizeof(SimpleOidList)); + + /* + * Build two lists, one with table OIDs and the other with fully-qualified + * index names. + */ + for (int i = 0; i < ntups; i++) + { + simple_oid_list_append(*table_list, atooid(PQgetvalue(res, i, 0))); + simple_string_list_append(index_list, + fmtQualifiedIdEnc(PQgetvalue(res, i, 1), + PQgetvalue(res, i, 2), + PQclientEncoding(conn))); + } + + PQclear(res); } static void diff --git a/src/bin/scripts/t/010_clusterdb.pl b/src/bin/scripts/t/010_clusterdb.pl index aa3bb291b2141..65a32b6c4c52e 100644 --- a/src/bin/scripts/t/010_clusterdb.pl +++ b/src/bin/scripts/t/010_clusterdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -21,14 +21,16 @@ qr/statement: CLUSTER;/, 'SQL CLUSTER run'); -$node->command_fails([ 'clusterdb', '-t', 'nonexistent' ], +$node->command_fails_like( + [ 'clusterdb', '--table' => 'nonexistent' ], + qr/relation "nonexistent" does not exist/, 'fails with nonexistent table'); $node->safe_psql('postgres', 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a); CLUSTER test1 USING test1x' ); $node->issues_sql_like( - [ 'clusterdb', '-t', 'test1' ], + [ 'clusterdb', '--table' => 'test1' ], qr/statement: CLUSTER public\.test1;/, 'cluster specific table'); diff --git a/src/bin/scripts/t/011_clusterdb_all.pl b/src/bin/scripts/t/011_clusterdb_all.pl index e0fd2201e547d..cf06c8c1f8e08 100644 --- a/src/bin/scripts/t/011_clusterdb_all.pl +++ b/src/bin/scripts/t/011_clusterdb_all.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -15,7 +15,7 @@ # clusterdb -a is not compatible with -d. This relies on PGDATABASE to be # set, something PostgreSQL::Test::Cluster does. $node->issues_sql_like( - [ 'clusterdb', '-a' ], + [ 'clusterdb', '--all' ], qr/statement: CLUSTER.*statement: CLUSTER/s, 'cluster all databases'); @@ -24,13 +24,13 @@ CREATE DATABASE regression_invalid; UPDATE pg_database SET datconnlimit = -2 WHERE datname = 'regression_invalid'; )); -$node->command_ok([ 'clusterdb', '-a' ], +$node->command_ok([ 'clusterdb', '--all' ], 'invalid database not targeted by clusterdb -a'); # Doesn't quite belong here, but don't want to waste time by creating an # invalid database in 010_clusterdb.pl as well. $node->command_fails_like( - [ 'clusterdb', '-d', 'regression_invalid' ], + [ 'clusterdb', '--dbname' => 'regression_invalid' ], qr/FATAL: cannot connect to invalid database "regression_invalid"/, 'clusterdb cannot target invalid database'); @@ -41,7 +41,7 @@ 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a); CLUSTER test1 USING test1x' ); $node->issues_sql_like( - [ 'clusterdb', '-a', '-t', 'test1' ], + [ 'clusterdb', '--all', '--table' => 'test1' ], qr/statement: CLUSTER public\.test1/s, 'cluster specific table in all databases'); diff --git a/src/bin/scripts/t/020_createdb.pl b/src/bin/scripts/t/020_createdb.pl index 4a0e2c883a11e..a8293390edea2 100644 --- a/src/bin/scripts/t/020_createdb.pl +++ b/src/bin/scripts/t/020_createdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -21,7 +21,13 @@ qr/statement: CREATE DATABASE foobar1/, 'SQL CREATE DATABASE run'); $node->issues_sql_like( - [ 'createdb', '-l', 'C', '-E', 'LATIN1', '-T', 'template0', 'foobar2' ], + [ + 'createdb', + '--locale' => 'C', + '--encoding' => 'LATIN1', + '--template' => 'template0', + 'foobar2', + ], qr/statement: CREATE DATABASE foobar2 ENCODING 'LATIN1'/, 'create database with encoding'); @@ -32,35 +38,45 @@ # provider. XXX Maybe split into multiple tests? $node->command_fails( [ - 'createdb', '-T', 'template0', '-E', 'UTF8', - '--locale-provider=icu', 'foobar4' + 'createdb', + '--template' => 'template0', + '--encoding' => 'UTF8', + '--locale-provider' => 'icu', + 'foobar4', ], 'create database with ICU fails without ICU locale specified'); $node->issues_sql_like( [ - 'createdb', '-T', - 'template0', '-E', - 'UTF8', '--locale-provider=icu', - '--locale=C', '--icu-locale=en', - 'foobar5' + 'createdb', + '--template' => 'template0', + '--encoding' => 'UTF8', + '--locale-provider' => 'icu', + '--locale' => 'C', + '--icu-locale' => 'en', + 'foobar5', ], qr/statement: CREATE DATABASE foobar5 .* LOCALE_PROVIDER icu ICU_LOCALE 'en'/, 'create database with ICU locale specified'); $node->command_fails( [ - 'createdb', '-T', 'template0', '-E', 'UTF8', - '--locale-provider=icu', - '--icu-locale=@colNumeric=lower', 'foobarX' + 'createdb', + '--template' => 'template0', + '--encoding' => 'UTF8', + '--locale-provider' => 'icu', + '--icu-locale' => '@colNumeric=lower', + 'foobarX', ], 'fails for invalid ICU locale'); $node->command_fails_like( [ - 'createdb', '-T', - 'template0', '--locale-provider=icu', - '--encoding=SQL_ASCII', 'foobarX' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'icu', + '--encoding' => 'SQL_ASCII', + 'foobarX', ], qr/ERROR: encoding "SQL_ASCII" is not supported with ICU provider/, 'fails for encoding not supported by ICU'); @@ -72,116 +88,144 @@ $node2->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider=libc', - 'foobar55' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'libc', + 'foobar55', ], 'create database with libc provider from template database with icu provider' ); $node2->command_ok( [ - 'createdb', '-T', 'template0', '--icu-locale', 'en-US', - 'foobar56' + 'createdb', + '--template' => 'template0', + '--icu-locale' => 'en-US', + 'foobar56', ], 'create database with icu locale from template database with icu provider' ); $node2->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider', - 'icu', '--locale', - 'en', '--lc-collate', - 'C', '--lc-ctype', - 'C', 'foobar57' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'icu', + '--locale' => 'en', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + 'foobar57', ], 'create database with locale as ICU locale'); } else { $node->command_fails( - [ 'createdb', '-T', 'template0', '--locale-provider=icu', 'foobar4' ], + [ + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'icu', + 'foobar4', + ], 'create database with ICU fails since no ICU support'); } $node->command_fails( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - 'tbuiltin1' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + 'tbuiltin1', ], 'create database with provider "builtin" fails without --locale'); $node->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--locale=C', 'tbuiltin2' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--locale' => 'C', + 'tbuiltin2', ], 'create database with provider "builtin" and locale "C"'); $node->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--locale=C', '--lc-collate=C', - 'tbuiltin3' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--locale' => 'C', + '--lc-collate' => 'C', + 'tbuiltin3', ], 'create database with provider "builtin" and LC_COLLATE=C'); $node->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--locale=C', '--lc-ctype=C', - 'tbuiltin4' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--locale' => 'C', + '--lc-ctype' => 'C', + 'tbuiltin4', ], 'create database with provider "builtin" and LC_CTYPE=C'); $node->command_ok( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--lc-collate=C', '--lc-ctype=C', - '-E UTF-8', '--builtin-locale=C.UTF8', - 'tbuiltin5' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + '--encoding' => 'UTF-8', + '--builtin-locale' => 'C.UTF8', + 'tbuiltin5', ], 'create database with --builtin-locale C.UTF-8 and -E UTF-8'); $node->command_fails( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--lc-collate=C', '--lc-ctype=C', - '-E LATIN1', '--builtin-locale=C.UTF-8', - 'tbuiltin6' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--lc-collate' => 'C', + '--lc-ctype' => 'C', + '--encoding' => 'LATIN1', + '--builtin-locale' => 'C.UTF-8', + 'tbuiltin6', ], 'create database with --builtin-locale C.UTF-8 and -E LATIN1'); $node->command_fails( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--locale=C', '--icu-locale=en', - 'tbuiltin7' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--locale' => 'C', + '--icu-locale' => 'en', + 'tbuiltin7', ], 'create database with provider "builtin" and ICU_LOCALE="en"'); $node->command_fails( [ - 'createdb', '-T', - 'template0', '--locale-provider=builtin', - '--locale=C', '--icu-rules=""', - 'tbuiltin8' + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'builtin', + '--locale' => 'C', + '--icu-rules' => '""', + 'tbuiltin8', ], 'create database with provider "builtin" and ICU_RULES=""'); $node->command_fails( [ - 'createdb', '-T', - 'template1', '--locale-provider=builtin', - '--locale=C', 'tbuiltin9' + 'createdb', + '--template' => 'template1', + '--locale-provider' => 'builtin', + '--locale' => 'C', + 'tbuiltin9', ], 'create database with provider "builtin" not matching template'); @@ -189,7 +233,12 @@ 'fails if database already exists'); $node->command_fails( - [ 'createdb', '-T', 'template0', '--locale-provider=xyz', 'foobarX' ], + [ + 'createdb', + '--template' => 'template0', + '--locale-provider' => 'xyz', + 'foobarX', + ], 'fails for invalid locale provider'); # Check use of templates with shared dependencies copied from the template. @@ -200,7 +249,7 @@ ALTER TABLE tab_foobar owner to role_foobar; CREATE POLICY pol_foobar ON tab_foobar FOR ALL TO role_foobar;'); $node->issues_sql_like( - [ 'createdb', '-l', 'C', '-T', 'foobar2', 'foobar3' ], + [ 'createdb', '--locale' => 'C', '--template' => 'foobar2', 'foobar3' ], qr/statement: CREATE DATABASE foobar3 TEMPLATE foobar2 LOCALE 'C'/, 'create database with template'); ($ret, $stdout, $stderr) = $node->psql( @@ -228,7 +277,7 @@ 1, [qr/^$/], [ - qr/^createdb: error: database creation failed: ERROR: invalid LC_COLLATE locale name|^createdb: error: database creation failed: ERROR: new collation \(foo'; SELECT '1\) is incompatible with the collation of the template database/s + qr/^createdb: error: database creation failed: ERROR: invalid LC_COLLATE locale name|^createdb: error: database creation failed: ERROR: new collation \(foo'; SELECT '1\) is incompatible with the collation of the template database/s, ], 'createdb with incorrect --lc-collate'); $node->command_checks_all( @@ -236,7 +285,7 @@ 1, [qr/^$/], [ - qr/^createdb: error: database creation failed: ERROR: invalid LC_CTYPE locale name|^createdb: error: database creation failed: ERROR: new LC_CTYPE \(foo'; SELECT '1\) is incompatible with the LC_CTYPE of the template database/s + qr/^createdb: error: database creation failed: ERROR: invalid LC_CTYPE locale name|^createdb: error: database creation failed: ERROR: new LC_CTYPE \(foo'; SELECT '1\) is incompatible with the LC_CTYPE of the template database/s, ], 'createdb with incorrect --lc-ctype'); @@ -245,34 +294,59 @@ 1, [qr/^$/], [ - qr/^createdb: error: database creation failed: ERROR: invalid create database strategy "foo"/s + qr/^createdb: error: database creation failed: ERROR: invalid create database strategy "foo"/s, ], 'createdb with incorrect --strategy'); # Check database creation strategy $node->issues_sql_like( - [ 'createdb', '-T', 'foobar2', '-S', 'wal_log', 'foobar6' ], + [ + 'createdb', + '--template' => 'foobar2', + '--strategy' => 'wal_log', + 'foobar6', + ], qr/statement: CREATE DATABASE foobar6 STRATEGY wal_log TEMPLATE foobar2/, 'create database with WAL_LOG strategy'); $node->issues_sql_like( - [ 'createdb', '-T', 'foobar2', '-S', 'WAL_LOG', 'foobar6s' ], + [ + 'createdb', + '--template' => 'foobar2', + '--strategy' => 'WAL_LOG', + 'foobar6s', + ], qr/statement: CREATE DATABASE foobar6s STRATEGY "WAL_LOG" TEMPLATE foobar2/, 'create database with WAL_LOG strategy'); $node->issues_sql_like( - [ 'createdb', '-T', 'foobar2', '-S', 'file_copy', 'foobar7' ], + [ + 'createdb', + '--template' => 'foobar2', + '--strategy' => 'file_copy', + 'foobar7', + ], qr/statement: CREATE DATABASE foobar7 STRATEGY file_copy TEMPLATE foobar2/, 'create database with FILE_COPY strategy'); $node->issues_sql_like( - [ 'createdb', '-T', 'foobar2', '-S', 'FILE_COPY', 'foobar7s' ], + [ + 'createdb', + '--template' => 'foobar2', + '--strategy' => 'FILE_COPY', + 'foobar7s', + ], qr/statement: CREATE DATABASE foobar7s STRATEGY "FILE_COPY" TEMPLATE foobar2/, 'create database with FILE_COPY strategy'); # Create database owned by role_foobar. $node->issues_sql_like( - [ 'createdb', '-T', 'foobar2', '-O', 'role_foobar', 'foobar8' ], + [ + 'createdb', + '--template' => 'foobar2', + '--owner' => 'role_foobar', + 'foobar8', + ], qr/statement: CREATE DATABASE foobar8 OWNER role_foobar TEMPLATE foobar2/, 'create database with owner role_foobar'); ($ret, $stdout, $stderr) = diff --git a/src/bin/scripts/t/040_createuser.pl b/src/bin/scripts/t/040_createuser.pl index 93b432381f012..54af43401bb05 100644 --- a/src/bin/scripts/t/040_createuser.pl +++ b/src/bin/scripts/t/040_createuser.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -21,34 +21,37 @@ qr/statement: CREATE ROLE regress_user1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS;/, 'SQL CREATE USER run'); $node->issues_sql_like( - [ 'createuser', '-L', 'regress_role1' ], + [ 'createuser', '--no-login', 'regress_role1' ], qr/statement: CREATE ROLE regress_role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS;/, 'create a non-login role'); $node->issues_sql_like( - [ 'createuser', '-r', 'regress user2' ], + [ 'createuser', '--createrole', 'regress user2' ], qr/statement: CREATE ROLE "regress user2" NOSUPERUSER NOCREATEDB CREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS;/, 'create a CREATEROLE user'); $node->issues_sql_like( - [ 'createuser', '-s', 'regress_user3' ], + [ 'createuser', '--superuser', 'regress_user3' ], qr/statement: CREATE ROLE regress_user3 SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS;/, 'create a superuser'); $node->issues_sql_like( [ - 'createuser', '-a', - 'regress_user1', '-a', - 'regress user2', 'regress user #4' + 'createuser', + '--with-admin' => 'regress_user1', + '--with-admin' => 'regress user2', + 'regress user #4' ], qr/statement: CREATE ROLE "regress user #4" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS ADMIN regress_user1,"regress user2";/, 'add a role as a member with admin option of the newly created role'); $node->issues_sql_like( [ - 'createuser', 'REGRESS_USER5', '-m', 'regress_user3', - '-m', 'regress user #4' + 'createuser', + 'REGRESS_USER5', + '--with-member' => 'regress_user3', + '--with-member' => 'regress user #4' ], qr/statement: CREATE ROLE "REGRESS_USER5" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS ROLE regress_user3,"regress user #4";/, 'add a role as a member of the newly created role'); $node->issues_sql_like( - [ 'createuser', '-v', '2029 12 31', 'regress_user6' ], + [ 'createuser', '--valid-until' => '2029 12 31', 'regress_user6' ], qr/statement: CREATE ROLE regress_user6 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS VALID UNTIL \'2029 12 31\';/, 'create a role with a password expiration date'); $node->issues_sql_like( @@ -60,26 +63,31 @@ qr/statement: CREATE ROLE regress_user8 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS;/, 'create a role without BYPASSRLS'); $node->issues_sql_like( - [ 'createuser', '--with-admin', 'regress_user1', 'regress_user9' ], + [ 'createuser', '--with-admin' => 'regress_user1', 'regress_user9' ], qr/statement: CREATE ROLE regress_user9 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS ADMIN regress_user1;/, '--with-admin'); $node->issues_sql_like( - [ 'createuser', '--with-member', 'regress_user1', 'regress_user10' ], + [ 'createuser', '--with-member' => 'regress_user1', 'regress_user10' ], qr/statement: CREATE ROLE regress_user10 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS ROLE regress_user1;/, '--with-member'); $node->issues_sql_like( - [ 'createuser', '--role', 'regress_user1', 'regress_user11' ], + [ 'createuser', '--role' => 'regress_user1', 'regress_user11' ], qr/statement: CREATE ROLE regress_user11 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS IN ROLE regress_user1;/, '--role'); $node->issues_sql_like( - [ 'createuser', 'regress_user12', '--member-of', 'regress_user1' ], + [ 'createuser', 'regress_user12', '--member-of' => 'regress_user1' ], qr/statement: CREATE ROLE regress_user12 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN NOREPLICATION NOBYPASSRLS IN ROLE regress_user1;/, '--member-of'); $node->command_fails([ 'createuser', 'regress_user1' ], 'fails if role already exists'); $node->command_fails( - [ 'createuser', 'regress_user1', '-m', 'regress_user2', 'regress_user3' ], + [ + 'createuser', + 'regress_user1', + '--with-member' => 'regress_user2', + 'regress_user3' + ], 'fails for too many non-options'); done_testing(); diff --git a/src/bin/scripts/t/050_dropdb.pl b/src/bin/scripts/t/050_dropdb.pl index 2cfd18ba1e532..d0bf4924ce48b 100644 --- a/src/bin/scripts/t/050_dropdb.pl +++ b/src/bin/scripts/t/050_dropdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -28,7 +28,9 @@ qr/statement: DROP DATABASE foobar2 WITH \(FORCE\);/, 'SQL DROP DATABASE (FORCE) run'); -$node->command_fails([ 'dropdb', 'nonexistent' ], +$node->command_fails_like( + [ 'dropdb', 'nonexistent' ], + qr/database "nonexistent" does not exist/, 'fails with nonexistent database'); # check that invalid database can be dropped with dropdb diff --git a/src/bin/scripts/t/070_dropuser.pl b/src/bin/scripts/t/070_dropuser.pl index f4de5662d8812..5f100978446b8 100644 --- a/src/bin/scripts/t/070_dropuser.pl +++ b/src/bin/scripts/t/070_dropuser.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -22,7 +22,9 @@ qr/statement: DROP ROLE regress_foobar1/, 'SQL DROP ROLE run'); -$node->command_fails([ 'dropuser', 'regress_nonexistent' ], +$node->command_fails_like( + [ 'dropuser', 'regress_nonexistent' ], + qr/role "regress_nonexistent" does not exist/, 'fails with nonexistent user'); done_testing(); diff --git a/src/bin/scripts/t/080_pg_isready.pl b/src/bin/scripts/t/080_pg_isready.pl index dd64502e69610..f184bd77388eb 100644 --- a/src/bin/scripts/t/080_pg_isready.pl +++ b/src/bin/scripts/t/080_pg_isready.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -20,7 +20,10 @@ $node->start; $node->command_ok( - [ 'pg_isready', "--timeout=$PostgreSQL::Test::Utils::timeout_default" ], + [ + 'pg_isready', + '--timeout' => $PostgreSQL::Test::Utils::timeout_default, + ], 'succeeds with server running'); done_testing(); diff --git a/src/bin/scripts/t/090_reindexdb.pl b/src/bin/scripts/t/090_reindexdb.pl index f02822da21859..1bd32d9426c96 100644 --- a/src/bin/scripts/t/090_reindexdb.pl +++ b/src/bin/scripts/t/090_reindexdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -96,7 +96,7 @@ $node->safe_psql('postgres', "TRUNCATE index_relfilenodes; $save_relfilenodes"); $node->issues_sql_like( - [ 'reindexdb', '-s', 'postgres' ], + [ 'reindexdb', '--system', 'postgres' ], qr/statement: REINDEX SYSTEM postgres;/, 'reindex system tables'); $relnode_info = $node->safe_psql('postgres', $compare_relfilenodes); @@ -108,29 +108,37 @@ 'relfilenode change after REINDEX SYSTEM'); $node->issues_sql_like( - [ 'reindexdb', '-t', 'test1', 'postgres' ], + [ 'reindexdb', '--table' => 'test1', 'postgres' ], qr/statement: REINDEX TABLE public\.test1;/, 'reindex specific table'); $node->issues_sql_like( - [ 'reindexdb', '-t', 'test1', '--tablespace', $tbspace_name, 'postgres' ], + [ + 'reindexdb', + '--table' => 'test1', + '--tablespace' => $tbspace_name, + 'postgres', + ], qr/statement: REINDEX \(TABLESPACE $tbspace_name\) TABLE public\.test1;/, 'reindex specific table on tablespace'); $node->issues_sql_like( - [ 'reindexdb', '-i', 'test1x', 'postgres' ], + [ 'reindexdb', '--index' => 'test1x', 'postgres' ], qr/statement: REINDEX INDEX public\.test1x;/, 'reindex specific index'); $node->issues_sql_like( - [ 'reindexdb', '-S', 'pg_catalog', 'postgres' ], + [ 'reindexdb', '--schema' => 'pg_catalog', 'postgres' ], qr/statement: REINDEX SCHEMA pg_catalog;/, 'reindex specific schema'); $node->issues_sql_like( - [ 'reindexdb', '-v', '-t', 'test1', 'postgres' ], + [ 'reindexdb', '--verbose', '--table' => 'test1', 'postgres' ], qr/statement: REINDEX \(VERBOSE\) TABLE public\.test1;/, 'reindex with verbose output'); $node->issues_sql_like( [ - 'reindexdb', '-v', '-t', 'test1', - '--tablespace', $tbspace_name, 'postgres' + 'reindexdb', + '--verbose', + '--table' => 'test1', + '--tablespace' => $tbspace_name, + 'postgres', ], qr/statement: REINDEX \(VERBOSE, TABLESPACE $tbspace_name\) TABLE public\.test1;/, 'reindex with verbose output and tablespace'); @@ -153,27 +161,36 @@ 'OID change after REINDEX DATABASE CONCURRENTLY'); $node->issues_sql_like( - [ 'reindexdb', '--concurrently', '-t', 'test1', 'postgres' ], + [ 'reindexdb', '--concurrently', '--table' => 'test1', 'postgres' ], qr/statement: REINDEX TABLE CONCURRENTLY public\.test1;/, 'reindex specific table concurrently'); $node->issues_sql_like( - [ 'reindexdb', '--concurrently', '-i', 'test1x', 'postgres' ], + [ 'reindexdb', '--concurrently', '--index' => 'test1x', 'postgres' ], qr/statement: REINDEX INDEX CONCURRENTLY public\.test1x;/, 'reindex specific index concurrently'); $node->issues_sql_like( - [ 'reindexdb', '--concurrently', '-S', 'public', 'postgres' ], + [ 'reindexdb', '--concurrently', '--schema' => 'public', 'postgres' ], qr/statement: REINDEX SCHEMA CONCURRENTLY public;/, 'reindex specific schema concurrently'); -$node->command_fails([ 'reindexdb', '--concurrently', '-s', 'postgres' ], +$node->command_fails( + [ 'reindexdb', '--concurrently', '--system', 'postgres' ], 'reindex system tables concurrently'); $node->issues_sql_like( - [ 'reindexdb', '--concurrently', '-v', '-t', 'test1', 'postgres' ], + [ + 'reindexdb', '--concurrently', '--verbose', + '--table' => 'test1', + 'postgres', + ], qr/statement: REINDEX \(VERBOSE\) TABLE CONCURRENTLY public\.test1;/, 'reindex with verbose output concurrently'); $node->issues_sql_like( [ - 'reindexdb', '--concurrently', '-v', '-t', - 'test1', '--tablespace', $tbspace_name, 'postgres' + 'reindexdb', + '--concurrently', + '--verbose', + '--table' => 'test1', + '--tablespace' => $tbspace_name, + 'postgres', ], qr/statement: REINDEX \(VERBOSE, TABLESPACE $tbspace_name\) TABLE CONCURRENTLY public\.test1;/, 'reindex concurrently with verbose output and tablespace'); @@ -185,8 +202,10 @@ # messages. $node->command_checks_all( [ - 'reindexdb', '-t', $toast_table, '--tablespace', - $tbspace_name, 'postgres' + 'reindexdb', + '--table' => $toast_table, + '--tablespace' => $tbspace_name, + 'postgres', ], 1, [], @@ -194,8 +213,11 @@ 'reindex toast table with tablespace'); $node->command_checks_all( [ - 'reindexdb', '--concurrently', '-t', $toast_table, - '--tablespace', $tbspace_name, 'postgres' + 'reindexdb', + '--concurrently', + '--table' => $toast_table, + '--tablespace' => $tbspace_name, + 'postgres', ], 1, [], @@ -203,8 +225,10 @@ 'reindex toast table concurrently with tablespace'); $node->command_checks_all( [ - 'reindexdb', '-i', $toast_index, '--tablespace', - $tbspace_name, 'postgres' + 'reindexdb', + '--index' => $toast_index, + '--tablespace' => $tbspace_name, + 'postgres', ], 1, [], @@ -212,8 +236,11 @@ 'reindex toast index with tablespace'); $node->command_checks_all( [ - 'reindexdb', '--concurrently', '-i', $toast_index, - '--tablespace', $tbspace_name, 'postgres' + 'reindexdb', + '--concurrently', + '--index' => $toast_index, + '--tablespace' => $tbspace_name, + 'postgres', ], 1, [], @@ -246,35 +273,53 @@ |); $node->command_fails( - [ 'reindexdb', '-j', '2', '-s', 'postgres' ], + [ 'reindexdb', '--jobs' => '2', '--system', 'postgres' ], 'parallel reindexdb cannot process system catalogs'); $node->command_ok( - [ 'reindexdb', '-j', '2', '-i', 's1.i1', '-i', 's2.i2', 'postgres' ], + [ + 'reindexdb', + '--jobs' => '2', + '--index' => 's1.i1', + '--index' => 's2.i2', + '--index' => 's1.t1_id_idx', + '--index' => 's2.t2_id_idx', + 'postgres', + ], 'parallel reindexdb for indices'); # Note that the ordering of the commands is not stable, so the second # command for s2.t2 is not checked after. $node->issues_sql_like( - [ 'reindexdb', '-j', '2', '-S', 's1', '-S', 's2', 'postgres' ], + [ + 'reindexdb', + '--jobs' => '2', + '--schema' => 's1', + '--schema' => 's2', + 'postgres', + ], qr/statement:\ REINDEX TABLE s1.t1;/, 'parallel reindexdb for schemas does a per-table REINDEX'); -$node->command_ok( - [ 'reindexdb', '-j', '2', '-S', 's3' ], +$node->command_ok([ 'reindexdb', '--jobs' => '2', '--schema' => 's3' ], 'parallel reindexdb with empty schema'); $node->command_ok( - [ 'reindexdb', '-j', '2', '--concurrently', '-d', 'postgres' ], + [ + 'reindexdb', + '--jobs' => '2', + '--concurrently', + '--dbname' => 'postgres', + ], 'parallel reindexdb on database, concurrently'); # combinations of objects $node->issues_sql_like( - [ 'reindexdb', '-s', '-t', 'test1', 'postgres' ], + [ 'reindexdb', '--system', '--table' => 'test1', 'postgres' ], qr/statement:\ REINDEX SYSTEM postgres;/, 'specify both --system and --table'); $node->issues_sql_like( - [ 'reindexdb', '-s', '-i', 'test1x', 'postgres' ], + [ 'reindexdb', '--system', '--index' => 'test1x', 'postgres' ], qr/statement:\ REINDEX INDEX public.test1x;/, 'specify both --system and --index'); $node->issues_sql_like( - [ 'reindexdb', '-s', '-S', 'pg_catalog', 'postgres' ], + [ 'reindexdb', '--system', '--schema' => 'pg_catalog', 'postgres' ], qr/statement:\ REINDEX SCHEMA pg_catalog;/, 'specify both --system and --schema'); diff --git a/src/bin/scripts/t/091_reindexdb_all.pl b/src/bin/scripts/t/091_reindexdb_all.pl index 7f5068667e3b7..6a75946b2b9ff 100644 --- a/src/bin/scripts/t/091_reindexdb_all.pl +++ b/src/bin/scripts/t/091_reindexdb_all.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -18,23 +18,23 @@ $node->safe_psql('template1', 'CREATE TABLE test1 (a int); CREATE INDEX test1x ON test1 (a);'); $node->issues_sql_like( - [ 'reindexdb', '-a' ], + [ 'reindexdb', '--all' ], qr/statement: REINDEX.*statement: REINDEX/s, 'reindex all databases'); $node->issues_sql_like( - [ 'reindexdb', '-a', '-s' ], + [ 'reindexdb', '--all', '--system' ], qr/statement: REINDEX SYSTEM postgres/s, 'reindex system catalogs in all databases'); $node->issues_sql_like( - [ 'reindexdb', '-a', '-S', 'public' ], + [ 'reindexdb', '--all', '--schema' => 'public' ], qr/statement: REINDEX SCHEMA public/s, 'reindex schema in all databases'); $node->issues_sql_like( - [ 'reindexdb', '-a', '-i', 'test1x' ], + [ 'reindexdb', '--all', '--index' => 'test1x' ], qr/statement: REINDEX INDEX public\.test1x/s, 'reindex index in all databases'); $node->issues_sql_like( - [ 'reindexdb', '-a', '-t', 'test1' ], + [ 'reindexdb', '--all', '--table' => 'test1' ], qr/statement: REINDEX TABLE public\.test1/s, 'reindex table in all databases'); @@ -43,13 +43,13 @@ CREATE DATABASE regression_invalid; UPDATE pg_database SET datconnlimit = -2 WHERE datname = 'regression_invalid'; )); -$node->command_ok([ 'reindexdb', '-a' ], - 'invalid database not targeted by reindexdb -a'); +$node->command_ok([ 'reindexdb', '--all' ], + 'invalid database not targeted by reindexdb --all'); # Doesn't quite belong here, but don't want to waste time by creating an # invalid database in 090_reindexdb.pl as well. $node->command_fails_like( - [ 'reindexdb', '-d', 'regression_invalid' ], + [ 'reindexdb', '--dbname' => 'regression_invalid' ], qr/FATAL: cannot connect to invalid database "regression_invalid"/, 'reindexdb cannot target invalid database'); diff --git a/src/bin/scripts/t/100_vacuumdb.pl b/src/bin/scripts/t/100_vacuumdb.pl index 1a2bcb495913a..75ac24a7a5539 100644 --- a/src/bin/scripts/t/100_vacuumdb.pl +++ b/src/bin/scripts/t/100_vacuumdb.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -80,11 +80,11 @@ [ 'vacuumdb', '--analyze-only', '--no-process-toast', 'postgres' ], '--analyze-only and --no-process-toast specified together'); $node->issues_sql_like( - [ 'vacuumdb', '-P', 2, 'postgres' ], + [ 'vacuumdb', '--parallel' => 2, 'postgres' ], qr/statement: VACUUM \(SKIP_DATABASE_STATS, PARALLEL 2\).*;/, 'vacuumdb -P 2'); $node->issues_sql_like( - [ 'vacuumdb', '-P', 0, 'postgres' ], + [ 'vacuumdb', '--parallel' => 0, 'postgres' ], qr/statement: VACUUM \(SKIP_DATABASE_STATS, PARALLEL 0\).*;/, 'vacuumdb -P 0'); $node->command_ok([qw(vacuumdb -Z --table=pg_am dbname=template1)], @@ -118,94 +118,183 @@ 'column list'); $node->command_fails( - [ 'vacuumdb', '--analyze', '--table', 'vactable(c)', 'postgres' ], + [ 'vacuumdb', '--analyze', '--table' => 'vactable(c)', 'postgres' ], 'incorrect column name with ANALYZE'); -$node->command_fails([ 'vacuumdb', '-P', -1, 'postgres' ], +$node->command_fails([ 'vacuumdb', '--parallel' => -1, 'postgres' ], 'negative parallel degree'); $node->issues_sql_like( - [ 'vacuumdb', '--analyze', '--table', 'vactable(a, b)', 'postgres' ], + [ 'vacuumdb', '--analyze', '--table' => 'vactable(a, b)', 'postgres' ], qr/statement: VACUUM \(SKIP_DATABASE_STATS, ANALYZE\) public.vactable\(a, b\);/, 'vacuumdb --analyze with complete column list'); $node->issues_sql_like( - [ 'vacuumdb', '--analyze-only', '--table', 'vactable(b)', 'postgres' ], + [ 'vacuumdb', '--analyze-only', '--table' => 'vactable(b)', 'postgres' ], qr/statement: ANALYZE public.vactable\(b\);/, 'vacuumdb --analyze-only with partial column list'); $node->command_checks_all( - [ 'vacuumdb', '--analyze', '--table', 'vacview', 'postgres' ], + [ 'vacuumdb', '--analyze', '--table' => 'vacview', 'postgres' ], 0, [qr/^.*vacuuming database "postgres"/], [qr/^WARNING.*cannot vacuum non-tables or special system tables/s], 'vacuumdb with view'); $node->command_fails( - [ 'vacuumdb', '--table', 'vactable', '--min-mxid-age', '0', 'postgres' ], + [ + 'vacuumdb', + '--table' => 'vactable', + '--min-mxid-age' => '0', + 'postgres' + ], 'vacuumdb --min-mxid-age with incorrect value'); $node->command_fails( - [ 'vacuumdb', '--table', 'vactable', '--min-xid-age', '0', 'postgres' ], + [ + 'vacuumdb', + '--table' => 'vactable', + '--min-xid-age' => '0', + 'postgres' + ], 'vacuumdb --min-xid-age with incorrect value'); $node->issues_sql_like( [ - 'vacuumdb', '--table', 'vactable', '--min-mxid-age', - '2147483000', 'postgres' + 'vacuumdb', + '--table' => 'vactable', + '--min-mxid-age' => '2147483000', + 'postgres' ], qr/GREATEST.*relminmxid.*2147483000/, 'vacuumdb --table --min-mxid-age'); $node->issues_sql_like( - [ 'vacuumdb', '--min-xid-age', '2147483001', 'postgres' ], + [ 'vacuumdb', '--min-xid-age' => '2147483001', 'postgres' ], qr/GREATEST.*relfrozenxid.*2147483001/, 'vacuumdb --table --min-xid-age'); $node->issues_sql_like( - [ 'vacuumdb', '--schema', '"Foo"', 'postgres' ], + [ 'vacuumdb', '--schema' => '"Foo"', 'postgres' ], qr/VACUUM \(SKIP_DATABASE_STATS\) "Foo".bar/, 'vacuumdb --schema'); $node->issues_sql_like( - [ 'vacuumdb', '--schema', '"Foo"', '--schema', '"Bar"', 'postgres' ], + [ 'vacuumdb', '--schema' => '"Foo"', '--schema' => '"Bar"', 'postgres' ], qr/VACUUM\ \(SKIP_DATABASE_STATS\)\ "Foo".bar .*VACUUM\ \(SKIP_DATABASE_STATS\)\ "Bar".baz /sx, 'vacuumdb multiple --schema switches'); $node->issues_sql_like( - [ 'vacuumdb', '--exclude-schema', '"Foo"', 'postgres' ], + [ 'vacuumdb', '--exclude-schema' => '"Foo"', 'postgres' ], qr/^(?!.*VACUUM \(SKIP_DATABASE_STATS\) "Foo".bar).*$/s, 'vacuumdb --exclude-schema'); $node->issues_sql_like( [ - 'vacuumdb', '--exclude-schema', '"Foo"', '--exclude-schema', - '"Bar"', 'postgres' + 'vacuumdb', + '--exclude-schema' => '"Foo"', + '--exclude-schema' => '"Bar"', + 'postgres' ], qr/^(?!.*VACUUM\ \(SKIP_DATABASE_STATS\)\ "Foo".bar | VACUUM\ \(SKIP_DATABASE_STATS\)\ "Bar".baz).*$/sx, 'vacuumdb multiple --exclude-schema switches'); $node->command_fails_like( - [ 'vacuumdb', '-N', 'pg_catalog', '-t', 'pg_class', 'postgres', ], + [ + 'vacuumdb', + '--exclude-schema' => 'pg_catalog', + '--table' => 'pg_class', + 'postgres', + ], qr/cannot vacuum specific table\(s\) and exclude schema\(s\) at the same time/, - 'cannot use options -N and -t at the same time'); + 'cannot use options --exclude-schema and ---table at the same time'); $node->command_fails_like( - [ 'vacuumdb', '-n', 'pg_catalog', '-t', 'pg_class', 'postgres' ], + [ + 'vacuumdb', + '--schema' => 'pg_catalog', + '--table' => 'pg_class', + 'postgres' + ], qr/cannot vacuum all tables in schema\(s\) and specific table\(s\) at the same time/, - 'cannot use options -n and -t at the same time'); + 'cannot use options --schema and ---table at the same time'); $node->command_fails_like( - [ 'vacuumdb', '-n', 'pg_catalog', '-N', '"Foo"', 'postgres' ], + [ + 'vacuumdb', + '--schema' => 'pg_catalog', + '--exclude-schema' => '"Foo"', + 'postgres' + ], qr/cannot vacuum all tables in schema\(s\) and exclude schema\(s\) at the same time/, - 'cannot use options -n and -N at the same time'); + 'cannot use options --schema and --exclude-schema at the same time'); $node->issues_sql_like( - [ 'vacuumdb', '-a', '-N', 'pg_catalog' ], + [ 'vacuumdb', '--all', '--exclude-schema' => 'pg_catalog' ], qr/(?:(?!VACUUM \(SKIP_DATABASE_STATS\) pg_catalog.pg_class).)*/, - 'vacuumdb -a -N'); + 'vacuumdb --all --exclude-schema'); $node->issues_sql_like( - [ 'vacuumdb', '-a', '-n', 'pg_catalog' ], + [ 'vacuumdb', '--all', '--schema' => 'pg_catalog' ], qr/VACUUM \(SKIP_DATABASE_STATS\) pg_catalog.pg_class/, - 'vacuumdb -a -n'); + 'vacuumdb --all ---schema'); $node->issues_sql_like( - [ 'vacuumdb', '-a', '-t', 'pg_class' ], + [ 'vacuumdb', '--all', '--table' => 'pg_class' ], qr/VACUUM \(SKIP_DATABASE_STATS\) pg_catalog.pg_class/, - 'vacuumdb -a -t'); + 'vacuumdb --all --table'); $node->command_fails_like( - [ 'vacuumdb', '-a', '-d', 'postgres' ], + [ 'vacuumdb', '--all', '-d' => 'postgres' ], qr/cannot vacuum all databases and a specific one at the same time/, - 'cannot use options -a and -d at the same time'); + 'cannot use options --all and --dbname at the same time'); $node->command_fails_like( - [ 'vacuumdb', '-a', 'postgres' ], + [ 'vacuumdb', '--all', 'postgres' ], qr/cannot vacuum all databases and a specific one at the same time/, - 'cannot use option -a and a dbname as argument at the same time'); + 'cannot use option --all and a dbname as argument at the same time'); + +$node->safe_psql('postgres', + 'CREATE TABLE regression_vacuumdb_test AS select generate_series(1, 10) a, generate_series(2, 11) b;'); +$node->issues_sql_like( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with missing stats'); +$node->issues_sql_unlike( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with no missing stats'); + +$node->safe_psql('postgres', + 'CREATE INDEX regression_vacuumdb_test_idx ON regression_vacuumdb_test (mod(a, 2));'); +$node->issues_sql_like( + [ 'vacuumdb', '--analyze-in-stages', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with missing index expression stats'); +$node->issues_sql_unlike( + [ 'vacuumdb', '--analyze-in-stages', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with no missing index expression stats'); + +$node->safe_psql('postgres', + 'CREATE STATISTICS regression_vacuumdb_test_stat ON a, b FROM regression_vacuumdb_test;'); +$node->issues_sql_like( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with missing extended stats'); +$node->issues_sql_unlike( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with no missing extended stats'); + +$node->safe_psql('postgres', + "CREATE TABLE regression_vacuumdb_child (a INT) INHERITS (regression_vacuumdb_test);\n" + . "INSERT INTO regression_vacuumdb_child VALUES (1, 2);\n" + . "ANALYZE regression_vacuumdb_child;\n"); +$node->issues_sql_like( + [ 'vacuumdb', '--analyze-in-stages', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with missing inherited stats'); +$node->issues_sql_unlike( + [ 'vacuumdb', '--analyze-in-stages', '--missing-stats-only', '-t', 'regression_vacuumdb_test', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with no missing inherited stats'); + +$node->safe_psql('postgres', + "CREATE TABLE regression_vacuumdb_parted (a INT) PARTITION BY LIST (a);\n" + . "CREATE TABLE regression_vacuumdb_part1 PARTITION OF regression_vacuumdb_parted FOR VALUES IN (1);\n" + . "INSERT INTO regression_vacuumdb_parted VALUES (1);\n" + . "ANALYZE regression_vacuumdb_part1;\n"); +$node->issues_sql_like( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_parted', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with missing partition stats'); +$node->issues_sql_unlike( + [ 'vacuumdb', '--analyze-only', '--missing-stats-only', '-t', 'regression_vacuumdb_parted', 'postgres' ], + qr/statement:\ ANALYZE/sx, + '--missing-stats-only with no missing partition stats'); done_testing(); diff --git a/src/bin/scripts/t/101_vacuumdb_all.pl b/src/bin/scripts/t/101_vacuumdb_all.pl index 9862f0c2082b8..74cb22dc3416c 100644 --- a/src/bin/scripts/t/101_vacuumdb_all.pl +++ b/src/bin/scripts/t/101_vacuumdb_all.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -12,7 +12,7 @@ $node->start; $node->issues_sql_like( - [ 'vacuumdb', '-a' ], + [ 'vacuumdb', '--all' ], qr/statement: VACUUM.*statement: VACUUM/s, 'vacuum all databases'); @@ -21,13 +21,13 @@ CREATE DATABASE regression_invalid; UPDATE pg_database SET datconnlimit = -2 WHERE datname = 'regression_invalid'; )); -$node->command_ok([ 'vacuumdb', '-a' ], +$node->command_ok([ 'vacuumdb', '--all' ], 'invalid database not targeted by vacuumdb -a'); # Doesn't quite belong here, but don't want to waste time by creating an # invalid database in 010_vacuumdb.pl as well. $node->command_fails_like( - [ 'vacuumdb', '-d', 'regression_invalid' ], + [ 'vacuumdb', '--dbname' => 'regression_invalid' ], qr/FATAL: cannot connect to invalid database "regression_invalid"/, 'vacuumdb cannot target invalid database'); diff --git a/src/bin/scripts/t/102_vacuumdb_stages.pl b/src/bin/scripts/t/102_vacuumdb_stages.pl index f41325818d962..984c8d06de60b 100644 --- a/src/bin/scripts/t/102_vacuumdb_stages.pl +++ b/src/bin/scripts/t/102_vacuumdb_stages.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/scripts/t/200_connstr.pl b/src/bin/scripts/t/200_connstr.pl index dbb99b6b09274..4d61f09347fc0 100644 --- a/src/bin/scripts/t/200_connstr.pl +++ b/src/bin/scripts/t/200_connstr.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c index 7c33e13e1ac3f..79b1096eb08c4 100644 --- a/src/bin/scripts/vacuumdb.c +++ b/src/bin/scripts/vacuumdb.c @@ -2,7 +2,7 @@ * * vacuumdb * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/bin/scripts/vacuumdb.c @@ -47,6 +47,7 @@ typedef struct vacuumingOptions bool process_toast; bool skip_database_stats; char *buffer_usage_limit; + bool missing_stats_only; } vacuumingOptions; /* object filter options */ @@ -62,10 +63,16 @@ typedef enum static VacObjFilter objfilter = OBJFILTER_NONE; +static SimpleStringList *retrieve_objects(PGconn *conn, + vacuumingOptions *vacopts, + SimpleStringList *objects, + bool echo); + static void vacuum_one_database(ConnParams *cparams, vacuumingOptions *vacopts, int stage, SimpleStringList *objects, + SimpleStringList **found_objs, int concurrentCons, const char *progname, bool echo, bool quiet); @@ -128,6 +135,7 @@ main(int argc, char *argv[]) {"no-process-toast", no_argument, NULL, 11}, {"no-process-main", no_argument, NULL, 12}, {"buffer-usage-limit", required_argument, NULL, 13}, + {"missing-stats-only", no_argument, NULL, 14}, {NULL, 0, NULL, 0} }; @@ -275,6 +283,9 @@ main(int argc, char *argv[]) case 13: vacopts.buffer_usage_limit = escape_quotes(optarg); break; + case 14: + vacopts.missing_stats_only = true; + break; default: /* getopt_long already emitted a complaint */ pg_log_error_hint("Try \"%s --help\" for more information.", progname); @@ -360,6 +371,14 @@ main(int argc, char *argv[]) pg_fatal("cannot use the \"%s\" option with the \"%s\" option", "buffer-usage-limit", "full"); + /* + * Prohibit --missing-stats-only without --analyze-only or + * --analyze-in-stages. + */ + if (vacopts.missing_stats_only && !vacopts.analyze_only) + pg_fatal("cannot use the \"%s\" option without \"%s\" or \"%s\"", + "missing-stats-only", "analyze-only", "analyze-in-stages"); + /* fill cparams except for dbname, which is set below */ cparams.pghost = host; cparams.pgport = port; @@ -400,12 +419,14 @@ main(int argc, char *argv[]) if (analyze_in_stages) { int stage; + SimpleStringList *found_objs = NULL; for (stage = 0; stage < ANALYZE_NUM_STAGES; stage++) { vacuum_one_database(&cparams, &vacopts, stage, &objects, + vacopts.missing_stats_only ? &found_objs : NULL, concurrentCons, progname, echo, quiet); } @@ -413,7 +434,7 @@ main(int argc, char *argv[]) else vacuum_one_database(&cparams, &vacopts, ANALYZE_NO_STAGE, - &objects, + &objects, NULL, concurrentCons, progname, echo, quiet); } @@ -461,38 +482,60 @@ escape_quotes(const char *src) /* * vacuum_one_database * - * Process tables in the given database. If the 'tables' list is empty, - * process all tables in the database. + * Process tables in the given database. + * + * There are two ways to specify the list of objects to process: + * + * 1) The "found_objs" parameter is a double pointer to a fully qualified list + * of objects to process, as returned by a previous call to + * vacuum_one_database(). + * + * a) If both "found_objs" (the double pointer) and "*found_objs" (the + * once-dereferenced double pointer) are not NULL, this list takes + * priority, and anything specified in "objects" is ignored. + * + * b) If "found_objs" (the double pointer) is not NULL but "*found_objs" + * (the once-dereferenced double pointer) _is_ NULL, the "objects" + * parameter takes priority, and the results of the catalog query + * described in (2) are stored in "found_objs". + * + * c) If "found_objs" (the double pointer) is NULL, the "objects" + * parameter again takes priority, and the results of the catalog query + * are not saved. + * + * 2) The "objects" parameter is a user-specified list of objects to process. + * When (1b) or (1c) applies, this function performs a catalog query to + * retrieve a fully qualified list of objects to process, as described + * below. + * + * a) If "objects" is not NULL, the catalog query gathers only the objects + * listed in "objects". + * + * b) If "objects" is NULL, all tables in the database are gathered. * * Note that this function is only concerned with running exactly one stage * when in analyze-in-stages mode; caller must iterate on us if necessary. * * If concurrentCons is > 1, multiple connections are used to vacuum tables - * in parallel. In this case and if the table list is empty, we first obtain - * a list of tables from the database. + * in parallel. */ static void vacuum_one_database(ConnParams *cparams, vacuumingOptions *vacopts, int stage, SimpleStringList *objects, + SimpleStringList **found_objs, int concurrentCons, const char *progname, bool echo, bool quiet) { PQExpBufferData sql; - PQExpBufferData buf; - PQExpBufferData catalog_query; - PGresult *res; PGconn *conn; SimpleStringListCell *cell; ParallelSlotArray *sa; - SimpleStringList dbtables = {NULL, NULL}; - int i; - int ntups; + int ntups = 0; bool failed = false; - bool objects_listed = false; - bool has_where = false; const char *initcmd; + SimpleStringList *ret = NULL; const char *stage_commands[] = { "SET default_statistics_target=1; SET vacuum_cost_delay=0;", "SET default_statistics_target=10; RESET vacuum_cost_delay;", @@ -559,20 +602,39 @@ vacuum_one_database(ConnParams *cparams, } if (vacopts->min_xid_age != 0 && PQserverVersion(conn) < 90600) + { + PQfinish(conn); pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", "--min-xid-age", "9.6"); + } if (vacopts->min_mxid_age != 0 && PQserverVersion(conn) < 90600) + { + PQfinish(conn); pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", "--min-mxid-age", "9.6"); + } if (vacopts->parallel_workers >= 0 && PQserverVersion(conn) < 130000) + { + PQfinish(conn); pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", "--parallel", "13"); + } if (vacopts->buffer_usage_limit && PQserverVersion(conn) < 160000) + { + PQfinish(conn); pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", "--buffer-usage-limit", "16"); + } + + if (vacopts->missing_stats_only && PQserverVersion(conn) < 150000) + { + PQfinish(conn); + pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s", + "--missing-stats-only", "15"); + } /* skip_database_stats is used automatically if server supports it */ vacopts->skip_database_stats = (PQserverVersion(conn) >= 160000); @@ -589,19 +651,155 @@ vacuum_one_database(ConnParams *cparams, } /* - * Prepare the list of tables to process by querying the catalogs. - * - * Since we execute the constructed query with the default search_path - * (which could be unsafe), everything in this query MUST be fully - * qualified. - * - * First, build a WITH clause for the catalog query if any tables were - * specified, with a set of values made of relation names and their - * optional set of columns. This is used to match any provided column - * lists with the generated qualified identifiers and to filter for the - * tables provided via --table. If a listed table does not exist, the - * catalog query will fail. + * If the caller provided the results of a previous catalog query, just + * use that. Otherwise, run the catalog query ourselves and set the + * return variable if provided. */ + if (found_objs && *found_objs) + ret = *found_objs; + else + { + ret = retrieve_objects(conn, vacopts, objects, echo); + if (found_objs) + *found_objs = ret; + } + + /* + * Count the number of objects in the catalog query result. If there are + * none, we are done. + */ + for (cell = ret ? ret->head : NULL; cell; cell = cell->next) + ntups++; + + if (ntups == 0) + { + PQfinish(conn); + return; + } + + /* + * Ensure concurrentCons is sane. If there are more connections than + * vacuumable relations, we don't need to use them all. + */ + if (concurrentCons > ntups) + concurrentCons = ntups; + if (concurrentCons <= 0) + concurrentCons = 1; + + /* + * All slots need to be prepared to run the appropriate analyze stage, if + * caller requested that mode. We have to prepare the initial connection + * ourselves before setting up the slots. + */ + if (stage == ANALYZE_NO_STAGE) + initcmd = NULL; + else + { + initcmd = stage_commands[stage]; + executeCommand(conn, initcmd, echo); + } + + /* + * Setup the database connections. We reuse the connection we already have + * for the first slot. If not in parallel mode, the first slot in the + * array contains the connection. + */ + sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, initcmd); + ParallelSlotsAdoptConn(sa, conn); + + initPQExpBuffer(&sql); + + cell = ret->head; + do + { + const char *tabname = cell->val; + ParallelSlot *free_slot; + + if (CancelRequested) + { + failed = true; + goto finish; + } + + free_slot = ParallelSlotsGetIdle(sa, NULL); + if (!free_slot) + { + failed = true; + goto finish; + } + + prepare_vacuum_command(&sql, PQserverVersion(free_slot->connection), + vacopts, tabname); + + /* + * Execute the vacuum. All errors are handled in processQueryResult + * through ParallelSlotsGetIdle. + */ + ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); + run_vacuum_command(free_slot->connection, sql.data, + echo, tabname); + + cell = cell->next; + } while (cell != NULL); + + if (!ParallelSlotsWaitCompletion(sa)) + { + failed = true; + goto finish; + } + + /* If we used SKIP_DATABASE_STATS, mop up with ONLY_DATABASE_STATS */ + if (vacopts->skip_database_stats && stage == ANALYZE_NO_STAGE) + { + const char *cmd = "VACUUM (ONLY_DATABASE_STATS);"; + ParallelSlot *free_slot = ParallelSlotsGetIdle(sa, NULL); + + if (!free_slot) + { + failed = true; + goto finish; + } + + ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); + run_vacuum_command(free_slot->connection, cmd, echo, NULL); + + if (!ParallelSlotsWaitCompletion(sa)) + failed = true; + } + +finish: + ParallelSlotsTerminate(sa); + pg_free(sa); + + termPQExpBuffer(&sql); + + if (failed) + exit(1); +} + +/* + * Prepare the list of tables to process by querying the catalogs. + * + * Since we execute the constructed query with the default search_path (which + * could be unsafe), everything in this query MUST be fully qualified. + * + * First, build a WITH clause for the catalog query if any tables were + * specified, with a set of values made of relation names and their optional + * set of columns. This is used to match any provided column lists with the + * generated qualified identifiers and to filter for the tables provided via + * --table. If a listed table does not exist, the catalog query will fail. + */ +static SimpleStringList * +retrieve_objects(PGconn *conn, vacuumingOptions *vacopts, + SimpleStringList *objects, bool echo) +{ + PQExpBufferData buf; + PQExpBufferData catalog_query; + PGresult *res; + SimpleStringListCell *cell; + SimpleStringList *found_objs = palloc0(sizeof(SimpleStringList)); + bool objects_listed = false; + initPQExpBuffer(&catalog_query); for (cell = objects ? objects->head : NULL; cell; cell = cell->next) { @@ -662,10 +860,16 @@ vacuum_one_database(ConnParams *cparams, " FROM pg_catalog.pg_class c\n" " JOIN pg_catalog.pg_namespace ns" " ON c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n" + " CROSS JOIN LATERAL (SELECT c.relkind IN (" + CppAsString2(RELKIND_PARTITIONED_TABLE) ", " + CppAsString2(RELKIND_PARTITIONED_INDEX) ")) as p (inherited)\n" " LEFT JOIN pg_catalog.pg_class t" " ON c.reltoastrelid OPERATOR(pg_catalog.=) t.oid\n"); - /* Used to match the tables or schemas listed by the user */ + /* + * Used to match the tables or schemas listed by the user, completing the + * JOIN clause. + */ if (objects_listed) { appendPQExpBufferStr(&catalog_query, " LEFT JOIN listed_objects" @@ -676,14 +880,27 @@ vacuum_one_database(ConnParams *cparams, appendPQExpBufferStr(&catalog_query, "c.oid\n"); else appendPQExpBufferStr(&catalog_query, "ns.oid\n"); + } + /* + * Exclude temporary tables, beginning the WHERE clause. + */ + appendPQExpBufferStr(&catalog_query, + " WHERE c.relpersistence OPERATOR(pg_catalog.!=) " + CppAsString2(RELPERSISTENCE_TEMP) "\n"); + + /* + * Used to match the tables or schemas listed by the user, for the WHERE + * clause. + */ + if (objects_listed) + { if (objfilter & OBJFILTER_SCHEMA_EXCLUDE) - appendPQExpBuffer(&catalog_query, - " WHERE listed_objects.object_oid IS NULL\n"); + appendPQExpBufferStr(&catalog_query, + " AND listed_objects.object_oid IS NULL\n"); else - appendPQExpBuffer(&catalog_query, - " WHERE listed_objects.object_oid IS NOT NULL\n"); - has_where = true; + appendPQExpBufferStr(&catalog_query, + " AND listed_objects.object_oid IS NOT NULL\n"); } /* @@ -694,12 +911,10 @@ vacuum_one_database(ConnParams *cparams, */ if ((objfilter & OBJFILTER_TABLE) == 0) { - appendPQExpBuffer(&catalog_query, - " %s c.relkind OPERATOR(pg_catalog.=) ANY (array[" - CppAsString2(RELKIND_RELATION) ", " - CppAsString2(RELKIND_MATVIEW) "])\n", - has_where ? "AND" : "WHERE"); - has_where = true; + appendPQExpBufferStr(&catalog_query, + " AND c.relkind OPERATOR(pg_catalog.=) ANY (array[" + CppAsString2(RELKIND_RELATION) ", " + CppAsString2(RELKIND_MATVIEW) "])\n"); } /* @@ -712,25 +927,96 @@ vacuum_one_database(ConnParams *cparams, if (vacopts->min_xid_age != 0) { appendPQExpBuffer(&catalog_query, - " %s GREATEST(pg_catalog.age(c.relfrozenxid)," + " AND GREATEST(pg_catalog.age(c.relfrozenxid)," " pg_catalog.age(t.relfrozenxid)) " " OPERATOR(pg_catalog.>=) '%d'::pg_catalog.int4\n" " AND c.relfrozenxid OPERATOR(pg_catalog.!=)" " '0'::pg_catalog.xid\n", - has_where ? "AND" : "WHERE", vacopts->min_xid_age); - has_where = true; + vacopts->min_xid_age); } if (vacopts->min_mxid_age != 0) { appendPQExpBuffer(&catalog_query, - " %s GREATEST(pg_catalog.mxid_age(c.relminmxid)," + " AND GREATEST(pg_catalog.mxid_age(c.relminmxid)," " pg_catalog.mxid_age(t.relminmxid)) OPERATOR(pg_catalog.>=)" " '%d'::pg_catalog.int4\n" " AND c.relminmxid OPERATOR(pg_catalog.!=)" " '0'::pg_catalog.xid\n", - has_where ? "AND" : "WHERE", vacopts->min_mxid_age); - has_where = true; + vacopts->min_mxid_age); + } + + if (vacopts->missing_stats_only) + { + appendPQExpBufferStr(&catalog_query, " AND (\n"); + + /* regular stats */ + appendPQExpBufferStr(&catalog_query, + " EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n" + " WHERE a.attrelid OPERATOR(pg_catalog.=) c.oid\n" + " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n" + " AND NOT a.attisdropped\n" + " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n" + " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n" + " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n" + " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n" + " AND s.stainherit OPERATOR(pg_catalog.=) p.inherited))\n"); + + /* extended stats */ + appendPQExpBufferStr(&catalog_query, + " OR EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext e\n" + " WHERE e.stxrelid OPERATOR(pg_catalog.=) c.oid\n" + " AND e.stxstattarget IS DISTINCT FROM 0::pg_catalog.int2\n" + " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext_data d\n" + " WHERE d.stxoid OPERATOR(pg_catalog.=) e.oid\n" + " AND d.stxdinherit OPERATOR(pg_catalog.=) p.inherited))\n"); + + /* expression indexes */ + appendPQExpBufferStr(&catalog_query, + " OR EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n" + " JOIN pg_catalog.pg_index i" + " ON i.indexrelid OPERATOR(pg_catalog.=) a.attrelid\n" + " WHERE i.indrelid OPERATOR(pg_catalog.=) c.oid\n" + " AND i.indkey[a.attnum OPERATOR(pg_catalog.-) 1::pg_catalog.int2]" + " OPERATOR(pg_catalog.=) 0::pg_catalog.int2\n" + " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n" + " AND NOT a.attisdropped\n" + " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n" + " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n" + " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n" + " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n" + " AND s.stainherit OPERATOR(pg_catalog.=) p.inherited))\n"); + + /* inheritance and regular stats */ + appendPQExpBufferStr(&catalog_query, + " OR EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n" + " WHERE a.attrelid OPERATOR(pg_catalog.=) c.oid\n" + " AND a.attnum OPERATOR(pg_catalog.>) 0::pg_catalog.int2\n" + " AND NOT a.attisdropped\n" + " AND a.attstattarget IS DISTINCT FROM 0::pg_catalog.int2\n" + " AND c.relhassubclass\n" + " AND NOT p.inherited\n" + " AND EXISTS (SELECT NULL FROM pg_catalog.pg_inherits h\n" + " WHERE h.inhparent OPERATOR(pg_catalog.=) c.oid)\n" + " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic s\n" + " WHERE s.starelid OPERATOR(pg_catalog.=) a.attrelid\n" + " AND s.staattnum OPERATOR(pg_catalog.=) a.attnum\n" + " AND s.stainherit))\n"); + + /* inheritance and extended stats */ + appendPQExpBufferStr(&catalog_query, + " OR EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext e\n" + " WHERE e.stxrelid OPERATOR(pg_catalog.=) c.oid\n" + " AND e.stxstattarget IS DISTINCT FROM 0::pg_catalog.int2\n" + " AND c.relhassubclass\n" + " AND NOT p.inherited\n" + " AND EXISTS (SELECT NULL FROM pg_catalog.pg_inherits h\n" + " WHERE h.inhparent OPERATOR(pg_catalog.=) c.oid)\n" + " AND NOT EXISTS (SELECT NULL FROM pg_catalog.pg_statistic_ext_data d\n" + " WHERE d.stxoid OPERATOR(pg_catalog.=) e.oid\n" + " AND d.stxdinherit))\n"); + + appendPQExpBufferStr(&catalog_query, " )\n"); } /* @@ -743,135 +1029,28 @@ vacuum_one_database(ConnParams *cparams, termPQExpBuffer(&catalog_query); PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo)); - /* - * If no rows are returned, there are no matching tables, so we are done. - */ - ntups = PQntuples(res); - if (ntups == 0) - { - PQclear(res); - PQfinish(conn); - return; - } - /* * Build qualified identifiers for each table, including the column list * if given. */ initPQExpBuffer(&buf); - for (i = 0; i < ntups; i++) + for (int i = 0; i < PQntuples(res); i++) { appendPQExpBufferStr(&buf, - fmtQualifiedId(PQgetvalue(res, i, 1), - PQgetvalue(res, i, 0))); + fmtQualifiedIdEnc(PQgetvalue(res, i, 1), + PQgetvalue(res, i, 0), + PQclientEncoding(conn))); if (objects_listed && !PQgetisnull(res, i, 2)) appendPQExpBufferStr(&buf, PQgetvalue(res, i, 2)); - simple_string_list_append(&dbtables, buf.data); + simple_string_list_append(found_objs, buf.data); resetPQExpBuffer(&buf); } termPQExpBuffer(&buf); PQclear(res); - /* - * Ensure concurrentCons is sane. If there are more connections than - * vacuumable relations, we don't need to use them all. - */ - if (concurrentCons > ntups) - concurrentCons = ntups; - if (concurrentCons <= 0) - concurrentCons = 1; - - /* - * All slots need to be prepared to run the appropriate analyze stage, if - * caller requested that mode. We have to prepare the initial connection - * ourselves before setting up the slots. - */ - if (stage == ANALYZE_NO_STAGE) - initcmd = NULL; - else - { - initcmd = stage_commands[stage]; - executeCommand(conn, initcmd, echo); - } - - /* - * Setup the database connections. We reuse the connection we already have - * for the first slot. If not in parallel mode, the first slot in the - * array contains the connection. - */ - sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, initcmd); - ParallelSlotsAdoptConn(sa, conn); - - initPQExpBuffer(&sql); - - cell = dbtables.head; - do - { - const char *tabname = cell->val; - ParallelSlot *free_slot; - - if (CancelRequested) - { - failed = true; - goto finish; - } - - free_slot = ParallelSlotsGetIdle(sa, NULL); - if (!free_slot) - { - failed = true; - goto finish; - } - - prepare_vacuum_command(&sql, PQserverVersion(free_slot->connection), - vacopts, tabname); - - /* - * Execute the vacuum. All errors are handled in processQueryResult - * through ParallelSlotsGetIdle. - */ - ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); - run_vacuum_command(free_slot->connection, sql.data, - echo, tabname); - - cell = cell->next; - } while (cell != NULL); - - if (!ParallelSlotsWaitCompletion(sa)) - { - failed = true; - goto finish; - } - - /* If we used SKIP_DATABASE_STATS, mop up with ONLY_DATABASE_STATS */ - if (vacopts->skip_database_stats && stage == ANALYZE_NO_STAGE) - { - const char *cmd = "VACUUM (ONLY_DATABASE_STATS);"; - ParallelSlot *free_slot = ParallelSlotsGetIdle(sa, NULL); - - if (!free_slot) - { - failed = true; - goto finish; - } - - ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); - run_vacuum_command(free_slot->connection, cmd, echo, NULL); - - if (!ParallelSlotsWaitCompletion(sa)) - failed = true; - } - -finish: - ParallelSlotsTerminate(sa); - pg_free(sa); - - termPQExpBuffer(&sql); - - if (failed) - exit(1); + return found_objs; } /* @@ -902,6 +1081,11 @@ vacuum_all_databases(ConnParams *cparams, if (analyze_in_stages) { + SimpleStringList **found_objs = NULL; + + if (vacopts->missing_stats_only) + found_objs = palloc0(PQntuples(result) * sizeof(SimpleStringList *)); + /* * When analyzing all databases in stages, we analyze them all in the * fastest stage first, so that initial statistics become available @@ -919,6 +1103,7 @@ vacuum_all_databases(ConnParams *cparams, vacuum_one_database(cparams, vacopts, stage, objects, + vacopts->missing_stats_only ? &found_objs[i] : NULL, concurrentCons, progname, echo, quiet); } @@ -932,7 +1117,7 @@ vacuum_all_databases(ConnParams *cparams, vacuum_one_database(cparams, vacopts, ANALYZE_NO_STAGE, - objects, + objects, NULL, concurrentCons, progname, echo, quiet); } @@ -1158,6 +1343,7 @@ help(const char *progname) printf(_(" -j, --jobs=NUM use this many concurrent connections to vacuum\n")); printf(_(" --min-mxid-age=MXID_AGE minimum multixact ID age of tables to vacuum\n")); printf(_(" --min-xid-age=XID_AGE minimum transaction ID age of tables to vacuum\n")); + printf(_(" --missing-stats-only only analyze relations with missing statistics\n")); printf(_(" --no-index-cleanup don't remove index entries that point to dead tuples\n")); printf(_(" --no-process-main skip the main relation\n")); printf(_(" --no-process-toast skip the TOAST table associated with the table to vacuum\n")); diff --git a/src/common/Makefile b/src/common/Makefile index 3d83299432b94..1e2b91c83c4c4 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -88,8 +88,7 @@ OBJS_COMMON = \ ifeq ($(with_ssl),openssl) OBJS_COMMON += \ cryptohash_openssl.o \ - hmac_openssl.o \ - protocol_openssl.o + hmac_openssl.o else OBJS_COMMON += \ cryptohash.o \ @@ -102,15 +101,22 @@ endif # A few files are currently only built for frontend, not server. # logging.c is excluded from OBJS_FRONTEND_SHLIB (shared library) as # a matter of policy, because it is not appropriate for general purpose -# libraries such as libpq to report errors directly. +# libraries such as libpq to report errors directly. fe_memutils.c is +# excluded because libpq must not exit() on allocation failure. +# +# The excluded files for _shlib builds are pulled into their own static +# library, for the benefit of test programs that need not follow the +# shlib rules. OBJS_FRONTEND_SHLIB = \ $(OBJS_COMMON) \ - fe_memutils.o \ restricted_token.o \ sprompt.o +OBJS_EXCLUDED_SHLIB = \ + fe_memutils.o \ + logging.o OBJS_FRONTEND = \ $(OBJS_FRONTEND_SHLIB) \ - logging.o + $(OBJS_EXCLUDED_SHLIB) # foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c OBJS_SHLIB = $(OBJS_FRONTEND_SHLIB:%.o=%_shlib.o) @@ -121,7 +127,7 @@ TOOLSDIR = $(top_srcdir)/src/tools GEN_KEYWORDLIST = $(PERL) -I $(TOOLSDIR) $(TOOLSDIR)/gen_keywordlist.pl GEN_KEYWORDLIST_DEPS = $(TOOLSDIR)/gen_keywordlist.pl $(TOOLSDIR)/PerfectHash.pm -all: libpgcommon.a libpgcommon_shlib.a libpgcommon_srv.a +all: libpgcommon.a libpgcommon_shlib.a libpgcommon_srv.a libpgcommon_excluded_shlib.a # libpgcommon is needed by some contrib install: all installdirs @@ -154,6 +160,11 @@ libpgcommon_shlib.a: $(OBJS_SHLIB) rm -f $@ $(AR) $(AROPT) $@ $^ +# The JSON API normally exits on out-of-memory; disable that behavior for shared +# library builds. This requires libpq's pqexpbuffer.h. +jsonapi_shlib.o: override CPPFLAGS += -DJSONAPI_USE_PQEXPBUFFER +jsonapi_shlib.o: override CPPFLAGS += -I$(libpq_srcdir) + # Because this uses its own compilation rule, it doesn't use the # dependency tracking logic from Makefile.global. To make sure that # dependency tracking works anyway for the *_shlib.o files, depend on @@ -163,6 +174,10 @@ libpgcommon_shlib.a: $(OBJS_SHLIB) %_shlib.o: %.c %.o $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) -c $< -o $@ +libpgcommon_excluded_shlib.a: $(OBJS_EXCLUDED_SHLIB) + rm -f $@ + $(AR) $(AROPT) $@ $^ + # # Server versions of object files # @@ -196,6 +211,6 @@ RYU_OBJS = $(RYU_FILES) $(RYU_FILES:%.o=%_shlib.o) $(RYU_FILES:%.o=%_srv.o) $(RYU_OBJS): CFLAGS += $(PERMIT_DECLARATION_AFTER_STATEMENT) clean distclean: - rm -f libpgcommon.a libpgcommon_shlib.a libpgcommon_srv.a + rm -f libpgcommon.a libpgcommon_shlib.a libpgcommon_srv.a libpgcommon_excluded_shlib.a rm -f $(OBJS_FRONTEND) $(OBJS_SHLIB) $(OBJS_SRV) rm -f kwlist_d.h diff --git a/src/common/archive.c b/src/common/archive.c index 00b53705a5106..325f6d7b7f3aa 100644 --- a/src/common/archive.c +++ b/src/common/archive.c @@ -3,7 +3,7 @@ * archive.c * Common WAL archive routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/base64.c b/src/common/base64.c index 4f23c96305243..240461fe1e6ab 100644 --- a/src/common/base64.c +++ b/src/common/base64.c @@ -3,7 +3,7 @@ * base64.c * Encoding and decoding routines for base64 without whitespace. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -41,15 +41,15 @@ static const int8 b64lookup[128] = { /* * pg_b64_encode * - * Encode into base64 the given string. Returns the length of the encoded - * string, and -1 in the event of an error with the result buffer zeroed - * for safety. + * Encode the 'src' byte array into base64. Returns the length of the encoded + * string, and -1 in the event of an error with the result buffer zeroed for + * safety. */ int -pg_b64_encode(const char *src, int len, char *dst, int dstlen) +pg_b64_encode(const uint8 *src, int len, char *dst, int dstlen) { char *p; - const char *s, + const uint8 *s, *end = src + len; int pos = 2; uint32 buf = 0; @@ -59,7 +59,7 @@ pg_b64_encode(const char *src, int len, char *dst, int dstlen) while (s < end) { - buf |= (unsigned char) *s << (pos << 3); + buf |= *s << (pos << 3); pos--; s++; @@ -113,11 +113,11 @@ pg_b64_encode(const char *src, int len, char *dst, int dstlen) * buffer zeroed for safety. */ int -pg_b64_decode(const char *src, int len, char *dst, int dstlen) +pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen) { const char *srcend = src + len, *s = src; - char *p = dst; + uint8 *p = dst; char c; int b = 0; uint32 buf = 0; diff --git a/src/common/binaryheap.c b/src/common/binaryheap.c index 7377ebdf15681..b13816f6f8495 100644 --- a/src/common/binaryheap.c +++ b/src/common/binaryheap.c @@ -3,7 +3,7 @@ * binaryheap.c * A simple binary heap implementation * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/binaryheap.c @@ -323,34 +323,23 @@ sift_down(binaryheap *heap, int node_off) { int left_off = left_offset(node_off); int right_off = right_offset(node_off); - int swap_off = 0; + int swap_off = left_off; - /* Is the left child larger than the parent? */ - if (left_off < heap->bh_size && - heap->bh_compare(node_val, - heap->bh_nodes[left_off], - heap->bh_arg) < 0) - swap_off = left_off; - - /* Is the right child larger than the parent? */ + /* Is the right child larger than the left child? */ if (right_off < heap->bh_size && - heap->bh_compare(node_val, + heap->bh_compare(heap->bh_nodes[left_off], heap->bh_nodes[right_off], heap->bh_arg) < 0) - { - /* swap with the larger child */ - if (!swap_off || - heap->bh_compare(heap->bh_nodes[left_off], - heap->bh_nodes[right_off], - heap->bh_arg) < 0) - swap_off = right_off; - } + swap_off = right_off; /* - * If we didn't find anything to swap, the heap condition is + * If no children or parent is >= the larger child, heap condition is * satisfied, and we're done. */ - if (!swap_off) + if (left_off >= heap->bh_size || + heap->bh_compare(node_val, + heap->bh_nodes[swap_off], + heap->bh_arg) >= 0) break; /* diff --git a/src/common/blkreftable.c b/src/common/blkreftable.c index 845b5d1dc46ed..b935baf9ad4bb 100644 --- a/src/common/blkreftable.c +++ b/src/common/blkreftable.c @@ -18,7 +18,7 @@ * later be marked as modified again; if that happens, it means the relation * was re-extended. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/common/blkreftable.c * @@ -265,7 +265,7 @@ BlockRefTableSetLimitBlock(BlockRefTable *brtab, BlockNumber limit_block) { BlockRefTableEntry *brtentry; - BlockRefTableKey key = {{0}}; /* make sure any padding is zero */ + BlockRefTableKey key = {0}; /* make sure any padding is zero */ bool found; memcpy(&key.rlocator, rlocator, sizeof(RelFileLocator)); @@ -300,7 +300,7 @@ BlockRefTableMarkBlockModified(BlockRefTable *brtab, BlockNumber blknum) { BlockRefTableEntry *brtentry; - BlockRefTableKey key = {{0}}; /* make sure any padding is zero */ + BlockRefTableKey key = {0}; /* make sure any padding is zero */ bool found; #ifndef FRONTEND MemoryContext oldcontext = MemoryContextSwitchTo(brtab->mcxt); @@ -340,7 +340,7 @@ BlockRefTableEntry * BlockRefTableGetEntry(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber *limit_block) { - BlockRefTableKey key = {{0}}; /* make sure any padding is zero */ + BlockRefTableKey key = {0}; /* make sure any padding is zero */ BlockRefTableEntry *entry; Assert(limit_block != NULL); @@ -521,7 +521,7 @@ WriteBlockRefTable(BlockRefTable *brtab, for (i = 0; i < brtab->hash->members; ++i) { BlockRefTableSerializedEntry *sentry = &sdata[i]; - BlockRefTableKey key = {{0}}; /* make sure any padding is zero */ + BlockRefTableKey key = {0}; /* make sure any padding is zero */ unsigned j; /* Write the serialized entry itself. */ @@ -616,7 +616,7 @@ BlockRefTableReaderNextRelation(BlockRefTableReader *reader, BlockNumber *limit_block) { BlockRefTableSerializedEntry sentry; - BlockRefTableSerializedEntry zentry = {{0}}; + BlockRefTableSerializedEntry zentry = {0}; /* * Sanity check: caller must read all blocks from all chunks before moving @@ -1291,7 +1291,7 @@ BlockRefTableWrite(BlockRefTableBuffer *buffer, void *data, int length) static void BlockRefTableFileTerminate(BlockRefTableBuffer *buffer) { - BlockRefTableSerializedEntry zentry = {{0}}; + BlockRefTableSerializedEntry zentry = {0}; pg_crc32c crc; /* Write a sentinel indicating that there are no more entries. */ diff --git a/src/common/checksum_helper.c b/src/common/checksum_helper.c index cc111401aebeb..716a481cea5df 100644 --- a/src/common/checksum_helper.c +++ b/src/common/checksum_helper.c @@ -3,7 +3,7 @@ * checksum_helper.c * Compute a checksum of any of various types using common routines * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/checksum_helper.c diff --git a/src/common/compression.c b/src/common/compression.c index 52e9ed01fbc54..4c3c9fd7b507b 100644 --- a/src/common/compression.c +++ b/src/common/compression.c @@ -14,7 +14,7 @@ * * Currently, the supported keywords are "level", "long", and "workers". * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/compression.c diff --git a/src/common/config_info.c b/src/common/config_info.c index 89c1ccb7f6273..113a8a6eb474c 100644 --- a/src/common/config_info.c +++ b/src/common/config_info.c @@ -4,7 +4,7 @@ * Common code for pg_config output * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/controldata_utils.c b/src/common/controldata_utils.c index 82309b2510771..fa375dc91293b 100644 --- a/src/common/controldata_utils.c +++ b/src/common/controldata_utils.c @@ -4,7 +4,7 @@ * Common code for control data file output. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,8 +28,8 @@ #include "access/xlog_internal.h" #include "catalog/pg_control.h" #include "common/controldata_utils.h" -#include "common/file_perm.h" #ifdef FRONTEND +#include "common/file_perm.h" #include "common/logging.h" #endif #include "port/pg_crc32c.h" @@ -53,7 +53,7 @@ get_controlfile(const char *DataDir, bool *crc_ok_p) { char ControlFilePath[MAXPGPATH]; - snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir); + snprintf(ControlFilePath, MAXPGPATH, "%s/%s", DataDir, XLOG_CONTROL_FILE); return get_controlfile_by_exact_path(ControlFilePath, crc_ok_p); } @@ -135,7 +135,7 @@ get_controlfile_by_exact_path(const char *ControlFilePath, bool *crc_ok_p) /* Check the CRC. */ INIT_CRC32C(crc); COMP_CRC32C(crc, - (char *) ControlFile, + ControlFile, offsetof(ControlFileData, crc)); FIN_CRC32C(crc); @@ -199,7 +199,7 @@ update_controlfile(const char *DataDir, /* Recalculate CRC of control file */ INIT_CRC32C(ControlFile->crc); COMP_CRC32C(ControlFile->crc, - (char *) ControlFile, + ControlFile, offsetof(ControlFileData, crc)); FIN_CRC32C(ControlFile->crc); diff --git a/src/common/cryptohash.c b/src/common/cryptohash.c index c96f241dc9958..533e4aaea36df 100644 --- a/src/common/cryptohash.c +++ b/src/common/cryptohash.c @@ -6,7 +6,7 @@ * This is the set of in-core functions used when there are no other * alternative options like OpenSSL. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c index 2c6eb11dc0e3e..c4f15bee563af 100644 --- a/src/common/cryptohash_openssl.c +++ b/src/common/cryptohash_openssl.c @@ -6,7 +6,7 @@ * * This should only be used if code is compiled with OpenSSL support. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/d2s.c b/src/common/d2s.c index fbdbd70062a5b..5322c465d53df 100644 --- a/src/common/d2s.c +++ b/src/common/d2s.c @@ -2,7 +2,7 @@ * * Ryu floating-point output for double precision. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/d2s.c diff --git a/src/common/d2s_full_table.h b/src/common/d2s_full_table.h index e7e728d557741..c6ce63567b50f 100644 --- a/src/common/d2s_full_table.h +++ b/src/common/d2s_full_table.h @@ -2,7 +2,7 @@ * * Ryu floating-point output for double precision. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/d2s_full_table.h diff --git a/src/common/d2s_intrinsics.h b/src/common/d2s_intrinsics.h index cd1b88963d3f8..0c6313e0df6b9 100644 --- a/src/common/d2s_intrinsics.h +++ b/src/common/d2s_intrinsics.h @@ -2,7 +2,7 @@ * * Ryu floating-point output for double precision. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/d2s_intrinsics.h diff --git a/src/common/encnames.c b/src/common/encnames.c index 910cc2c7e5cf0..dd468af204060 100644 --- a/src/common/encnames.c +++ b/src/common/encnames.c @@ -3,7 +3,7 @@ * encnames.c * Encoding names and routines for working with them. * - * Portions Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2001-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/encnames.c diff --git a/src/common/exec.c b/src/common/exec.c index 0bee19c1e539f..8b690a1018501 100644 --- a/src/common/exec.c +++ b/src/common/exec.c @@ -4,7 +4,7 @@ * Functions for finding and validating executable files * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -285,25 +285,6 @@ pg_realpath(const char *fname) #ifndef WIN32 path = realpath(fname, NULL); - if (path == NULL && errno == EINVAL) - { - /* - * Cope with old-POSIX systems that require a user-provided buffer. - * Assume MAXPGPATH is enough room on all such systems. - */ - char *buf = malloc(MAXPGPATH); - - if (buf == NULL) - return NULL; /* assume errno is set */ - path = realpath(fname, buf); - if (path == NULL) /* don't leak memory */ - { - int save_errno = errno; - - free(buf); - errno = save_errno; - } - } #else /* WIN32 */ /* diff --git a/src/common/f2s.c b/src/common/f2s.c index 59e89f36f02ae..a239a8765b07b 100644 --- a/src/common/f2s.c +++ b/src/common/f2s.c @@ -2,7 +2,7 @@ * * Ryu floating-point output for single precision. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/f2s.c diff --git a/src/common/fe_memutils.c b/src/common/fe_memutils.c index f17a9a5d9f6a3..4ba793a6132bb 100644 --- a/src/common/fe_memutils.c +++ b/src/common/fe_memutils.c @@ -3,7 +3,7 @@ * fe_memutils.c * memory management support for frontend code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/file_perm.c b/src/common/file_perm.c index 35ce341880cf5..a65a34d4d3f93 100644 --- a/src/common/file_perm.c +++ b/src/common/file_perm.c @@ -3,7 +3,7 @@ * File and directory permission routines * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/common/file_perm.c diff --git a/src/common/file_utils.c b/src/common/file_utils.c index 6bac537a1e55c..7b62687a2aa75 100644 --- a/src/common/file_utils.c +++ b/src/common/file_utils.c @@ -5,7 +5,7 @@ * Assorted utility functions to work on files. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/common/file_utils.c @@ -28,6 +28,7 @@ #ifdef FRONTEND #include "common/logging.h" #endif +#include "common/relpath.h" #include "port/pg_iovec.h" #ifdef FRONTEND @@ -44,12 +45,10 @@ */ #define MINIMUM_VERSION_FOR_PG_WAL 100000 -#ifdef PG_FLUSH_DATA_WORKS -static int pre_sync_fname(const char *fname, bool isdir); -#endif static void walkdir(const char *path, int (*action) (const char *fname, bool isdir), - bool process_symlinks); + bool process_symlinks, + const char *exclude_dir); #ifdef HAVE_SYNCFS @@ -92,11 +91,15 @@ do_syncfs(const char *path) * syncing, and might not have privileges to write at all. * * serverVersion indicates the version of the server to be sync'd. + * + * If sync_data_files is false, this function skips syncing "base/" and any + * other tablespace directories. */ void sync_pgdata(const char *pg_data, int serverVersion, - DataDirSyncMethod sync_method) + DataDirSyncMethod sync_method, + bool sync_data_files) { bool xlog_is_symlink; char pg_wal[MAXPGPATH]; @@ -105,7 +108,7 @@ sync_pgdata(const char *pg_data, /* handle renaming of pg_xlog to pg_wal in post-10 clusters */ snprintf(pg_wal, MAXPGPATH, "%s/%s", pg_data, serverVersion < MINIMUM_VERSION_FOR_PG_WAL ? "pg_xlog" : "pg_wal"); - snprintf(pg_tblspc, MAXPGPATH, "%s/pg_tblspc", pg_data); + snprintf(pg_tblspc, MAXPGPATH, "%s/%s", pg_data, PG_TBLSPC_DIR); /* * If pg_wal is a symlink, we'll need to recurse into it separately, @@ -146,30 +149,33 @@ sync_pgdata(const char *pg_data, do_syncfs(pg_data); /* If any tablespaces are configured, sync each of those. */ - dir = opendir(pg_tblspc); - if (dir == NULL) - pg_log_error("could not open directory \"%s\": %m", - pg_tblspc); - else + if (sync_data_files) { - while (errno = 0, (de = readdir(dir)) != NULL) + dir = opendir(pg_tblspc); + if (dir == NULL) + pg_log_error("could not open directory \"%s\": %m", + pg_tblspc); + else { - char subpath[MAXPGPATH * 2]; + while (errno = 0, (de = readdir(dir)) != NULL) + { + char subpath[MAXPGPATH * 2]; - if (strcmp(de->d_name, ".") == 0 || - strcmp(de->d_name, "..") == 0) - continue; + if (strcmp(de->d_name, ".") == 0 || + strcmp(de->d_name, "..") == 0) + continue; - snprintf(subpath, sizeof(subpath), "%s/%s", - pg_tblspc, de->d_name); - do_syncfs(subpath); - } + snprintf(subpath, sizeof(subpath), "%s/%s", + pg_tblspc, de->d_name); + do_syncfs(subpath); + } - if (errno) - pg_log_error("could not read directory \"%s\": %m", - pg_tblspc); + if (errno) + pg_log_error("could not read directory \"%s\": %m", + pg_tblspc); - (void) closedir(dir); + (void) closedir(dir); + } } /* If pg_wal is a symlink, process that too. */ @@ -181,15 +187,21 @@ sync_pgdata(const char *pg_data, case DATA_DIR_SYNC_METHOD_FSYNC: { + char *exclude_dir = NULL; + + if (!sync_data_files) + exclude_dir = psprintf("%s/base", pg_data); + /* * If possible, hint to the kernel that we're soon going to * fsync the data directory and its contents. */ #ifdef PG_FLUSH_DATA_WORKS - walkdir(pg_data, pre_sync_fname, false); + walkdir(pg_data, pre_sync_fname, false, exclude_dir); if (xlog_is_symlink) - walkdir(pg_wal, pre_sync_fname, false); - walkdir(pg_tblspc, pre_sync_fname, true); + walkdir(pg_wal, pre_sync_fname, false, NULL); + if (sync_data_files) + walkdir(pg_tblspc, pre_sync_fname, true, NULL); #endif /* @@ -202,10 +214,14 @@ sync_pgdata(const char *pg_data, * get fsync'd twice. That's not an expected case so we don't * worry about optimizing it. */ - walkdir(pg_data, fsync_fname, false); + walkdir(pg_data, fsync_fname, false, exclude_dir); if (xlog_is_symlink) - walkdir(pg_wal, fsync_fname, false); - walkdir(pg_tblspc, fsync_fname, true); + walkdir(pg_wal, fsync_fname, false, NULL); + if (sync_data_files) + walkdir(pg_tblspc, fsync_fname, true, NULL); + + if (exclude_dir) + pfree(exclude_dir); } break; } @@ -244,10 +260,10 @@ sync_dir_recurse(const char *dir, DataDirSyncMethod sync_method) * fsync the data directory and its contents. */ #ifdef PG_FLUSH_DATA_WORKS - walkdir(dir, pre_sync_fname, false); + walkdir(dir, pre_sync_fname, false, NULL); #endif - walkdir(dir, fsync_fname, false); + walkdir(dir, fsync_fname, false, NULL); } break; } @@ -263,6 +279,9 @@ sync_dir_recurse(const char *dir, DataDirSyncMethod sync_method) * ignored in subdirectories, ie we intentionally don't pass down the * process_symlinks flag to recursive calls. * + * If exclude_dir is not NULL, it specifies a directory path to skip + * processing. + * * Errors are reported but not considered fatal. * * See also walkdir in fd.c, which is a backend version of this logic. @@ -270,11 +289,15 @@ sync_dir_recurse(const char *dir, DataDirSyncMethod sync_method) static void walkdir(const char *path, int (*action) (const char *fname, bool isdir), - bool process_symlinks) + bool process_symlinks, + const char *exclude_dir) { DIR *dir; struct dirent *de; + if (exclude_dir && strcmp(exclude_dir, path) == 0) + return; + dir = opendir(path); if (dir == NULL) { @@ -298,7 +321,7 @@ walkdir(const char *path, (*action) (subpath, false); break; case PGFILETYPE_DIR: - walkdir(subpath, action, false); + walkdir(subpath, action, false, exclude_dir); break; default: @@ -326,16 +349,16 @@ walkdir(const char *path, } /* - * Hint to the OS that it should get ready to fsync() this file. + * Hint to the OS that it should get ready to fsync() this file, if supported + * by the platform. * * Ignores errors trying to open unreadable files, and reports other errors * non-fatally. */ -#ifdef PG_FLUSH_DATA_WORKS - -static int +int pre_sync_fname(const char *fname, bool isdir) { +#ifdef PG_FLUSH_DATA_WORKS int fd; fd = open(fname, O_RDONLY | PG_BINARY, 0); @@ -362,11 +385,10 @@ pre_sync_fname(const char *fname, bool isdir) #endif (void) close(fd); +#endif /* PG_FLUSH_DATA_WORKS */ return 0; } -#endif /* PG_FLUSH_DATA_WORKS */ - /* * fsync_fname -- Try to fsync a file or directory * @@ -686,7 +708,7 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset) ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset) { - static const PGIOAlignedBlock zbuffer = {{0}}; /* worth BLCKSZ */ + static const PGIOAlignedBlock zbuffer = {0}; /* worth BLCKSZ */ void *zerobuf_addr = unconstify(PGIOAlignedBlock *, &zbuffer)->data; struct iovec iov[PG_IOV_MAX]; size_t remaining_size = size; diff --git a/src/common/hashfn.c b/src/common/hashfn.c index 4db468cf85b7b..8a6bd8114efa3 100644 --- a/src/common/hashfn.c +++ b/src/common/hashfn.c @@ -5,7 +5,7 @@ * hashtables * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/hmac.c b/src/common/hmac.c index 508b2fcd9326d..9b85910672842 100644 --- a/src/common/hmac.c +++ b/src/common/hmac.c @@ -5,7 +5,7 @@ * * Fallback implementation of HMAC, as specified in RFC 2104. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c index 84fcf340d8e57..31cd188904384 100644 --- a/src/common/hmac_openssl.c +++ b/src/common/hmac_openssl.c @@ -5,7 +5,7 @@ * * This should only be used if code is compiled with OpenSSL support. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -35,17 +35,12 @@ /* * In backend, use an allocation in TopMemoryContext to count for resowner - * cleanup handling if necessary. For versions of OpenSSL where HMAC_CTX is - * known, just use palloc(). In frontend, use malloc to be able to return + * cleanup handling if necessary. In frontend, use malloc to be able to return * a failure status back to the caller. */ #ifndef FRONTEND -#ifdef HAVE_HMAC_CTX_NEW #define USE_RESOWNER_FOR_HMAC #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size) -#else -#define ALLOC(size) palloc(size) -#endif #define FREE(ptr) pfree(ptr) #else /* FRONTEND */ #define ALLOC(size) malloc(size) @@ -144,11 +139,7 @@ pg_hmac_create(pg_cryptohash_type type) ResourceOwnerEnlarge(CurrentResourceOwner); #endif -#ifdef HAVE_HMAC_CTX_NEW ctx->hmacctx = HMAC_CTX_new(); -#else - ctx->hmacctx = ALLOC(sizeof(HMAC_CTX)); -#endif if (ctx->hmacctx == NULL) { @@ -162,9 +153,6 @@ pg_hmac_create(pg_cryptohash_type type) return NULL; } -#ifndef HAVE_HMAC_CTX_NEW - memset(ctx->hmacctx, 0, sizeof(HMAC_CTX)); -#endif #ifdef USE_RESOWNER_FOR_HMAC ctx->resowner = CurrentResourceOwner; @@ -328,13 +316,7 @@ pg_hmac_free(pg_hmac_ctx *ctx) if (ctx == NULL) return; -#ifdef HAVE_HMAC_CTX_FREE HMAC_CTX_free(ctx->hmacctx); -#else - explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX)); - FREE(ctx->hmacctx); -#endif - #ifdef USE_RESOWNER_FOR_HMAC if (ctx->resowner) ResourceOwnerForgetHMAC(ctx->resowner, ctx); diff --git a/src/common/ip.c b/src/common/ip.c index b5ba02347aa71..0e7897a5c8fe8 100644 --- a/src/common/ip.c +++ b/src/common/ip.c @@ -3,7 +3,7 @@ * ip.c * IPv6-aware network access. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/jsonapi.c b/src/common/jsonapi.c index 2527dbe1da921..7dad4da65f636 100644 --- a/src/common/jsonapi.c +++ b/src/common/jsonapi.c @@ -3,7 +3,7 @@ * jsonapi.c * JSON parser and lexer interfaces * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -21,10 +21,70 @@ #include "mb/pg_wchar.h" #include "port/pg_lfind.h" -#ifndef FRONTEND +#ifdef JSONAPI_USE_PQEXPBUFFER +#include "pqexpbuffer.h" +#else +#include "lib/stringinfo.h" #include "miscadmin.h" #endif +/* + * By default, we will use palloc/pfree along with StringInfo. In libpq, + * use malloc and PQExpBuffer, and return JSON_OUT_OF_MEMORY on out-of-memory. + */ +#ifdef JSONAPI_USE_PQEXPBUFFER + +#define STRDUP(s) strdup(s) +#define ALLOC(size) malloc(size) +#define ALLOC0(size) calloc(1, size) +#define REALLOC realloc +#define FREE(s) free(s) + +#define jsonapi_appendStringInfo appendPQExpBuffer +#define jsonapi_appendBinaryStringInfo appendBinaryPQExpBuffer +#define jsonapi_appendStringInfoChar appendPQExpBufferChar +/* XXX should we add a macro version to PQExpBuffer? */ +#define jsonapi_appendStringInfoCharMacro appendPQExpBufferChar +#define jsonapi_makeStringInfo createPQExpBuffer +#define jsonapi_initStringInfo initPQExpBuffer +#define jsonapi_resetStringInfo resetPQExpBuffer +#define jsonapi_termStringInfo termPQExpBuffer +#define jsonapi_destroyStringInfo destroyPQExpBuffer + +#else /* !JSONAPI_USE_PQEXPBUFFER */ + +#define STRDUP(s) pstrdup(s) +#define ALLOC(size) palloc(size) +#define ALLOC0(size) palloc0(size) +#define REALLOC repalloc + +#ifdef FRONTEND +#define FREE pfree +#else +/* + * Backend pfree() doesn't handle NULL pointers like the frontend's does; smooth + * that over to reduce mental gymnastics. Avoid multiple evaluation of the macro + * argument to avoid future hair-pulling. + */ +#define FREE(s) do { \ + void *__v = (s); \ + if (__v) \ + pfree(__v); \ +} while (0) +#endif + +#define jsonapi_appendStringInfo appendStringInfo +#define jsonapi_appendBinaryStringInfo appendBinaryStringInfo +#define jsonapi_appendStringInfoChar appendStringInfoChar +#define jsonapi_appendStringInfoCharMacro appendStringInfoCharMacro +#define jsonapi_makeStringInfo makeStringInfo +#define jsonapi_initStringInfo initStringInfo +#define jsonapi_resetStringInfo resetStringInfo +#define jsonapi_termStringInfo(s) pfree((s)->data) +#define jsonapi_destroyStringInfo destroyStringInfo + +#endif /* JSONAPI_USE_PQEXPBUFFER */ + /* * The context of the parser is maintained by the recursive descent * mechanism, but is passed explicitly to the error reporting routine @@ -101,9 +161,10 @@ struct JsonParserStack */ struct JsonIncrementalState { + bool started; bool is_last_chunk; bool partial_completed; - StringInfoData partial_token; + jsonapi_StrValType partial_token; }; /* @@ -213,20 +274,26 @@ static char JSON_PROD_GOAL[] = {JSON_TOKEN_END, JSON_NT_JSON, 0}; static inline JsonParseErrorType json_lex_string(JsonLexContext *lex); static inline JsonParseErrorType json_lex_number(JsonLexContext *lex, const char *s, bool *num_err, size_t *total_len); -static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, JsonSemAction *sem); -static JsonParseErrorType parse_object_field(JsonLexContext *lex, JsonSemAction *sem); -static JsonParseErrorType parse_object(JsonLexContext *lex, JsonSemAction *sem); -static JsonParseErrorType parse_array_element(JsonLexContext *lex, JsonSemAction *sem); -static JsonParseErrorType parse_array(JsonLexContext *lex, JsonSemAction *sem); +static inline JsonParseErrorType parse_scalar(JsonLexContext *lex, const JsonSemAction *sem); +static JsonParseErrorType parse_object_field(JsonLexContext *lex, const JsonSemAction *sem); +static JsonParseErrorType parse_object(JsonLexContext *lex, const JsonSemAction *sem); +static JsonParseErrorType parse_array_element(JsonLexContext *lex, const JsonSemAction *sem); +static JsonParseErrorType parse_array(JsonLexContext *lex, const JsonSemAction *sem); static JsonParseErrorType report_parse_error(JsonParseContext ctx, JsonLexContext *lex); +static bool allocate_incremental_state(JsonLexContext *lex); +static inline void set_fname(JsonLexContext *lex, char *fname); /* the null action object used for pure validation */ -JsonSemAction nullSemAction = +const JsonSemAction nullSemAction = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; +/* sentinels used for out-of-memory conditions */ +static JsonLexContext failed_oom; +static JsonIncrementalState failed_inc_oom; + /* Parser support routines */ /* @@ -273,15 +340,11 @@ IsValidJsonNumber(const char *str, size_t len) { bool numeric_error; size_t total_len; - JsonLexContext dummy_lex; + JsonLexContext dummy_lex = {0}; if (len <= 0) return false; - dummy_lex.incremental = false; - dummy_lex.inc_state = NULL; - dummy_lex.pstack = NULL; - /* * json_lex_number expects a leading '-' to have been eaten already. * @@ -321,6 +384,9 @@ IsValidJsonNumber(const char *str, size_t len) * responsible for freeing the returned struct, either by calling * freeJsonLexContext() or (in backend environment) via memory context * cleanup. + * + * In shlib code, any out-of-memory failures will be deferred to time + * of use; this function is guaranteed to return a valid JsonLexContext. */ JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, @@ -328,7 +394,9 @@ makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, { if (lex == NULL) { - lex = palloc0(sizeof(JsonLexContext)); + lex = ALLOC0(sizeof(JsonLexContext)); + if (!lex) + return &failed_oom; lex->flags |= JSONLEX_FREE_STRUCT; } else @@ -339,15 +407,80 @@ makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, lex->line_number = 1; lex->input_length = len; lex->input_encoding = encoding; + lex->need_escapes = need_escapes; if (need_escapes) { - lex->strval = makeStringInfo(); + /* + * This call can fail in shlib code. We defer error handling to time + * of use (json_lex_string()) since we might not need to parse any + * strings anyway. + */ + lex->strval = jsonapi_makeStringInfo(); lex->flags |= JSONLEX_FREE_STRVAL; } return lex; } +/* + * Allocates the internal bookkeeping structures for incremental parsing. This + * can only fail in-band with shlib code. + */ +#define JS_STACK_CHUNK_SIZE 64 +#define JS_MAX_PROD_LEN 10 /* more than we need */ +#define JSON_TD_MAX_STACK 6400 /* hard coded for now - this is a REALLY high + * number */ +static bool +allocate_incremental_state(JsonLexContext *lex) +{ + void *pstack, + *prediction, + *fnames, + *fnull; + + lex->inc_state = ALLOC0(sizeof(JsonIncrementalState)); + pstack = ALLOC0(sizeof(JsonParserStack)); + prediction = ALLOC(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN); + fnames = ALLOC(JS_STACK_CHUNK_SIZE * sizeof(char *)); + fnull = ALLOC(JS_STACK_CHUNK_SIZE * sizeof(bool)); + +#ifdef JSONAPI_USE_PQEXPBUFFER + if (!lex->inc_state + || !pstack + || !prediction + || !fnames + || !fnull) + { + FREE(lex->inc_state); + FREE(pstack); + FREE(prediction); + FREE(fnames); + FREE(fnull); + + lex->inc_state = &failed_inc_oom; + return false; + } +#endif + + jsonapi_initStringInfo(&(lex->inc_state->partial_token)); + lex->pstack = pstack; + lex->pstack->stack_size = JS_STACK_CHUNK_SIZE; + lex->pstack->prediction = prediction; + lex->pstack->fnames = fnames; + lex->pstack->fnull = fnull; + + /* + * fnames between 0 and lex_level must always be defined so that + * freeJsonLexContext() can handle them safely. inc/dec_lex_level() handle + * the rest. + */ + Assert(lex->lex_level == 0); + lex->pstack->fnames[0] = NULL; + + lex->incremental = true; + return true; +} + /* * makeJsonLexContextIncremental @@ -357,19 +490,20 @@ makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, * we don't need the input, that will be handed in bit by bit to the * parse routine. We also need an accumulator for partial tokens in case * the boundary between chunks happens to fall in the middle of a token. + * + * In shlib code, any out-of-memory failures will be deferred to time of use; + * this function is guaranteed to return a valid JsonLexContext. */ -#define JS_STACK_CHUNK_SIZE 64 -#define JS_MAX_PROD_LEN 10 /* more than we need */ -#define JSON_TD_MAX_STACK 6400 /* hard coded for now - this is a REALLY high - * number */ - JsonLexContext * makeJsonLexContextIncremental(JsonLexContext *lex, int encoding, bool need_escapes) { if (lex == NULL) { - lex = palloc0(sizeof(JsonLexContext)); + lex = ALLOC0(sizeof(JsonLexContext)); + if (!lex) + return &failed_oom; + lex->flags |= JSONLEX_FREE_STRUCT; } else @@ -377,47 +511,109 @@ makeJsonLexContextIncremental(JsonLexContext *lex, int encoding, lex->line_number = 1; lex->input_encoding = encoding; - lex->incremental = true; - lex->inc_state = palloc0(sizeof(JsonIncrementalState)); - initStringInfo(&(lex->inc_state->partial_token)); - lex->pstack = palloc(sizeof(JsonParserStack)); - lex->pstack->stack_size = JS_STACK_CHUNK_SIZE; - lex->pstack->prediction = palloc(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN); - lex->pstack->pred_index = 0; - lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *)); - lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool)); + + if (!allocate_incremental_state(lex)) + { + if (lex->flags & JSONLEX_FREE_STRUCT) + { + FREE(lex); + return &failed_oom; + } + + /* lex->inc_state tracks the OOM failure; we can return here. */ + return lex; + } + + lex->need_escapes = need_escapes; if (need_escapes) { - lex->strval = makeStringInfo(); + /* + * This call can fail in shlib code. We defer error handling to time + * of use (json_lex_string()) since we might not need to parse any + * strings anyway. + */ + lex->strval = jsonapi_makeStringInfo(); lex->flags |= JSONLEX_FREE_STRVAL; } + return lex; } -static inline void +void +setJsonLexContextOwnsTokens(JsonLexContext *lex, bool owned_by_context) +{ + if (lex->incremental && lex->inc_state->started) + { + /* + * Switching this flag after parsing has already started is a + * programming error. + */ + Assert(false); + return; + } + + if (owned_by_context) + lex->flags |= JSONLEX_CTX_OWNS_TOKENS; + else + lex->flags &= ~JSONLEX_CTX_OWNS_TOKENS; +} + +static inline bool inc_lex_level(JsonLexContext *lex) { + if (lex->incremental && (lex->lex_level + 1) >= lex->pstack->stack_size) + { + size_t new_stack_size; + char *new_prediction; + char **new_fnames; + bool *new_fnull; + + new_stack_size = lex->pstack->stack_size + JS_STACK_CHUNK_SIZE; + + new_prediction = REALLOC(lex->pstack->prediction, + new_stack_size * JS_MAX_PROD_LEN); +#ifdef JSONAPI_USE_PQEXPBUFFER + if (!new_prediction) + return false; +#endif + lex->pstack->prediction = new_prediction; + + new_fnames = REALLOC(lex->pstack->fnames, + new_stack_size * sizeof(char *)); +#ifdef JSONAPI_USE_PQEXPBUFFER + if (!new_fnames) + return false; +#endif + lex->pstack->fnames = new_fnames; + + new_fnull = REALLOC(lex->pstack->fnull, new_stack_size * sizeof(bool)); +#ifdef JSONAPI_USE_PQEXPBUFFER + if (!new_fnull) + return false; +#endif + lex->pstack->fnull = new_fnull; + + lex->pstack->stack_size = new_stack_size; + } + lex->lex_level += 1; - if (lex->incremental && lex->lex_level >= lex->pstack->stack_size) + if (lex->incremental) { - lex->pstack->stack_size += JS_STACK_CHUNK_SIZE; - lex->pstack->prediction = - repalloc(lex->pstack->prediction, - lex->pstack->stack_size * JS_MAX_PROD_LEN); - if (lex->pstack->fnames) - lex->pstack->fnames = - repalloc(lex->pstack->fnames, - lex->pstack->stack_size * sizeof(char *)); - if (lex->pstack->fnull) - lex->pstack->fnull = - repalloc(lex->pstack->fnull, lex->pstack->stack_size * sizeof(bool)); + /* + * Ensure freeJsonLexContext() remains safe even if no fname is + * assigned at this level. + */ + lex->pstack->fnames[lex->lex_level] = NULL; } + + return true; } static inline void dec_lex_level(JsonLexContext *lex) { + set_fname(lex, NULL); /* free the current level's fname, if needed */ lex->lex_level -= 1; } @@ -451,6 +647,15 @@ have_prediction(JsonParserStack *pstack) static inline void set_fname(JsonLexContext *lex, char *fname) { + if (lex->flags & JSONLEX_CTX_OWNS_TOKENS) + { + /* + * Don't leak prior fnames. If one hasn't been assigned yet, + * inc_lex_level ensured that it's NULL (and therefore safe to free). + */ + FREE(lex->pstack->fnames[lex->lex_level]); + } + lex->pstack->fnames[lex->lex_level] = fname; } @@ -482,24 +687,42 @@ get_fnull(JsonLexContext *lex) void freeJsonLexContext(JsonLexContext *lex) { + static const JsonLexContext empty = {0}; + + if (!lex || lex == &failed_oom) + return; + if (lex->flags & JSONLEX_FREE_STRVAL) - destroyStringInfo(lex->strval); + jsonapi_destroyStringInfo(lex->strval); if (lex->errormsg) - destroyStringInfo(lex->errormsg); + jsonapi_destroyStringInfo(lex->errormsg); if (lex->incremental) { - pfree(lex->inc_state->partial_token.data); - pfree(lex->inc_state); - pfree(lex->pstack->prediction); - pfree(lex->pstack->fnames); - pfree(lex->pstack->fnull); - pfree(lex->pstack); + jsonapi_termStringInfo(&lex->inc_state->partial_token); + FREE(lex->inc_state); + FREE(lex->pstack->prediction); + + if (lex->flags & JSONLEX_CTX_OWNS_TOKENS) + { + int i; + + /* Clean up any tokens that were left behind. */ + for (i = 0; i <= lex->lex_level; i++) + FREE(lex->pstack->fnames[i]); + } + + FREE(lex->pstack->fnames); + FREE(lex->pstack->fnull); + FREE(lex->pstack->scalar_val); + FREE(lex->pstack); } if (lex->flags & JSONLEX_FREE_STRUCT) - pfree(lex); + FREE(lex); + else + *lex = empty; } /* @@ -519,25 +742,16 @@ freeJsonLexContext(JsonLexContext *lex) * other differences. */ JsonParseErrorType -pg_parse_json(JsonLexContext *lex, JsonSemAction *sem) +pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem) { #ifdef FORCE_JSON_PSTACK - - lex->incremental = true; - lex->inc_state = palloc0(sizeof(JsonIncrementalState)); - /* * We don't need partial token processing, there is only one chunk. But we * still need to init the partial token string so that freeJsonLexContext - * works. + * works, so perform the full incremental initialization. */ - initStringInfo(&(lex->inc_state->partial_token)); - lex->pstack = palloc(sizeof(JsonParserStack)); - lex->pstack->stack_size = JS_STACK_CHUNK_SIZE; - lex->pstack->prediction = palloc(JS_STACK_CHUNK_SIZE * JS_MAX_PROD_LEN); - lex->pstack->pred_index = 0; - lex->pstack->fnames = palloc(JS_STACK_CHUNK_SIZE * sizeof(char *)); - lex->pstack->fnull = palloc(JS_STACK_CHUNK_SIZE * sizeof(bool)); + if (!allocate_incremental_state(lex)) + return JSON_OUT_OF_MEMORY; return pg_parse_json_incremental(lex, sem, lex->input, lex->input_length, true); @@ -546,6 +760,8 @@ pg_parse_json(JsonLexContext *lex, JsonSemAction *sem) JsonTokenType tok; JsonParseErrorType result; + if (lex == &failed_oom) + return JSON_OUT_OF_MEMORY; if (lex->incremental) return JSON_INVALID_LEXER_TYPE; @@ -591,13 +807,16 @@ json_count_array_elements(JsonLexContext *lex, int *elements) int count; JsonParseErrorType result; + if (lex == &failed_oom) + return JSON_OUT_OF_MEMORY; + /* * It's safe to do this with a shallow copy because the lexical routines * don't scribble on the input. They do scribble on the other pointers * etc, so doing this with a copy makes that safe. */ memcpy(©lex, lex, sizeof(JsonLexContext)); - copylex.strval = NULL; /* not interested in values here */ + copylex.need_escapes = false; /* not interested in values here */ copylex.lex_level++; count = 0; @@ -648,7 +867,7 @@ json_count_array_elements(JsonLexContext *lex, int *elements) */ JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, - JsonSemAction *sem, + const JsonSemAction *sem, const char *json, size_t len, bool is_last) @@ -658,13 +877,15 @@ pg_parse_json_incremental(JsonLexContext *lex, JsonParseContext ctx = JSON_PARSE_VALUE; JsonParserStack *pstack = lex->pstack; - + if (lex == &failed_oom || lex->inc_state == &failed_inc_oom) + return JSON_OUT_OF_MEMORY; if (!lex->incremental) return JSON_INVALID_LEXER_TYPE; lex->input = lex->token_terminator = lex->line_start = json; lex->input_length = len; lex->inc_state->is_last_chunk = is_last; + lex->inc_state->started = true; /* get the initial token */ result = json_lex(lex); @@ -737,7 +958,9 @@ pg_parse_json_incremental(JsonLexContext *lex, if (result != JSON_SUCCESS) return result; } - inc_lex_level(lex); + + if (!inc_lex_level(lex)) + return JSON_OUT_OF_MEMORY; } break; case JSON_SEM_OEND: @@ -766,7 +989,9 @@ pg_parse_json_incremental(JsonLexContext *lex, if (result != JSON_SUCCESS) return result; } - inc_lex_level(lex); + + if (!inc_lex_level(lex)) + return JSON_OUT_OF_MEMORY; } break; case JSON_SEM_AEND: @@ -793,9 +1018,11 @@ pg_parse_json_incremental(JsonLexContext *lex, json_ofield_action ostart = sem->object_field_start; json_ofield_action oend = sem->object_field_end; - if ((ostart != NULL || oend != NULL) && lex->strval != NULL) + if ((ostart != NULL || oend != NULL) && lex->need_escapes) { - fname = pstrdup(lex->strval->data); + fname = STRDUP(lex->strval->data); + if (fname == NULL) + return JSON_OUT_OF_MEMORY; } set_fname(lex, fname); } @@ -883,14 +1110,21 @@ pg_parse_json_incremental(JsonLexContext *lex, */ if (tok == JSON_TOKEN_STRING) { - if (lex->strval != NULL) - pstack->scalar_val = pstrdup(lex->strval->data); + if (lex->need_escapes) + { + pstack->scalar_val = STRDUP(lex->strval->data); + if (pstack->scalar_val == NULL) + return JSON_OUT_OF_MEMORY; + } } else { ptrdiff_t tlen = (lex->token_terminator - lex->token_start); - pstack->scalar_val = palloc(tlen + 1); + pstack->scalar_val = ALLOC(tlen + 1); + if (pstack->scalar_val == NULL) + return JSON_OUT_OF_MEMORY; + memcpy(pstack->scalar_val, lex->token_start, tlen); pstack->scalar_val[tlen] = '\0'; } @@ -912,6 +1146,17 @@ pg_parse_json_incremental(JsonLexContext *lex, if (sfunc != NULL) { result = (*sfunc) (sem->semstate, pstack->scalar_val, pstack->scalar_tok); + + /* + * Either ownership of the token passed to the + * callback, or we need to free it now. Either + * way, clear our pointer to it so it doesn't get + * freed in the future. + */ + if (lex->flags & JSONLEX_CTX_OWNS_TOKENS) + FREE(pstack->scalar_val); + pstack->scalar_val = NULL; + if (result != JSON_SUCCESS) return result; } @@ -1005,7 +1250,7 @@ pg_parse_json_incremental(JsonLexContext *lex, * - object field */ static inline JsonParseErrorType -parse_scalar(JsonLexContext *lex, JsonSemAction *sem) +parse_scalar(JsonLexContext *lex, const JsonSemAction *sem) { char *val = NULL; json_scalar_action sfunc = sem->scalar; @@ -1025,14 +1270,21 @@ parse_scalar(JsonLexContext *lex, JsonSemAction *sem) /* extract the de-escaped string value, or the raw lexeme */ if (lex_peek(lex) == JSON_TOKEN_STRING) { - if (lex->strval != NULL) - val = pstrdup(lex->strval->data); + if (lex->need_escapes) + { + val = STRDUP(lex->strval->data); + if (val == NULL) + return JSON_OUT_OF_MEMORY; + } } else { int len = (lex->token_terminator - lex->token_start); - val = palloc(len + 1); + val = ALLOC(len + 1); + if (val == NULL) + return JSON_OUT_OF_MEMORY; + memcpy(val, lex->token_start, len); val[len] = '\0'; } @@ -1040,16 +1292,25 @@ parse_scalar(JsonLexContext *lex, JsonSemAction *sem) /* consume the token */ result = json_lex(lex); if (result != JSON_SUCCESS) + { + FREE(val); return result; + } - /* invoke the callback */ + /* + * invoke the callback, which may take ownership of val. For string + * values, val is NULL if need_escapes is false. + */ result = (*sfunc) (sem->semstate, val, tok); + if (lex->flags & JSONLEX_CTX_OWNS_TOKENS) + FREE(val); + return result; } static JsonParseErrorType -parse_object_field(JsonLexContext *lex, JsonSemAction *sem) +parse_object_field(JsonLexContext *lex, const JsonSemAction *sem) { /* * An object field is "fieldname" : value where value can be a scalar, @@ -1057,7 +1318,7 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem) * generally call a field name a "key". */ - char *fname = NULL; /* keep compiler quiet */ + char *fname = NULL; json_ofield_action ostart = sem->object_field_start; json_ofield_action oend = sem->object_field_end; bool isnull; @@ -1066,15 +1327,26 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem) if (lex_peek(lex) != JSON_TOKEN_STRING) return report_parse_error(JSON_PARSE_STRING, lex); - if ((ostart != NULL || oend != NULL) && lex->strval != NULL) - fname = pstrdup(lex->strval->data); + if ((ostart != NULL || oend != NULL) && lex->need_escapes) + { + /* fname is NULL if need_escapes is false */ + fname = STRDUP(lex->strval->data); + if (fname == NULL) + return JSON_OUT_OF_MEMORY; + } result = json_lex(lex); if (result != JSON_SUCCESS) + { + FREE(fname); return result; + } result = lex_expect(JSON_PARSE_OBJECT_LABEL, lex, JSON_TOKEN_COLON); if (result != JSON_SUCCESS) + { + FREE(fname); return result; + } tok = lex_peek(lex); isnull = tok == JSON_TOKEN_NULL; @@ -1083,7 +1355,7 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem) { result = (*ostart) (sem->semstate, fname, isnull); if (result != JSON_SUCCESS) - return result; + goto ofield_cleanup; } switch (tok) @@ -1098,20 +1370,23 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem) result = parse_scalar(lex, sem); } if (result != JSON_SUCCESS) - return result; + goto ofield_cleanup; if (oend != NULL) { result = (*oend) (sem->semstate, fname, isnull); if (result != JSON_SUCCESS) - return result; + goto ofield_cleanup; } - return JSON_SUCCESS; +ofield_cleanup: + if (lex->flags & JSONLEX_CTX_OWNS_TOKENS) + FREE(fname); + return result; } static JsonParseErrorType -parse_object(JsonLexContext *lex, JsonSemAction *sem) +parse_object(JsonLexContext *lex, const JsonSemAction *sem) { /* * an object is a possibly empty sequence of object fields, separated by @@ -1123,6 +1398,11 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem) JsonParseErrorType result; #ifndef FRONTEND + + /* + * TODO: clients need some way to put a bound on stack growth. Parse level + * limits maybe? + */ check_stack_depth(); #endif @@ -1185,7 +1465,7 @@ parse_object(JsonLexContext *lex, JsonSemAction *sem) } static JsonParseErrorType -parse_array_element(JsonLexContext *lex, JsonSemAction *sem) +parse_array_element(JsonLexContext *lex, const JsonSemAction *sem) { json_aelem_action astart = sem->array_element_start; json_aelem_action aend = sem->array_element_end; @@ -1229,7 +1509,7 @@ parse_array_element(JsonLexContext *lex, JsonSemAction *sem) } static JsonParseErrorType -parse_array(JsonLexContext *lex, JsonSemAction *sem) +parse_array(JsonLexContext *lex, const JsonSemAction *sem) { /* * an array is a possibly empty sequence of array elements, separated by @@ -1312,15 +1592,27 @@ json_lex(JsonLexContext *lex) const char *const end = lex->input + lex->input_length; JsonParseErrorType result; - if (lex->incremental && lex->inc_state->partial_completed) + if (lex == &failed_oom || lex->inc_state == &failed_inc_oom) + return JSON_OUT_OF_MEMORY; + + if (lex->incremental) { - /* - * We just lexed a completed partial token on the last call, so reset - * everything - */ - resetStringInfo(&(lex->inc_state->partial_token)); - lex->token_terminator = lex->input; - lex->inc_state->partial_completed = false; + if (lex->inc_state->partial_completed) + { + /* + * We just lexed a completed partial token on the last call, so + * reset everything + */ + jsonapi_resetStringInfo(&(lex->inc_state->partial_token)); + lex->token_terminator = lex->input; + lex->inc_state->partial_completed = false; + } + +#ifdef JSONAPI_USE_PQEXPBUFFER + /* Make sure our partial token buffer is valid before using it below. */ + if (PQExpBufferDataBroken(lex->inc_state->partial_token)) + return JSON_OUT_OF_MEMORY; +#endif } s = lex->token_terminator; @@ -1331,10 +1623,10 @@ json_lex(JsonLexContext *lex) * We have a partial token. Extend it and if completed lex it by a * recursive call */ - StringInfo ptok = &(lex->inc_state->partial_token); + jsonapi_StrValType *ptok = &(lex->inc_state->partial_token); size_t added = 0; bool tok_done = false; - JsonLexContext dummy_lex; + JsonLexContext dummy_lex = {0}; JsonParseErrorType partial_result; if (ptok->data[0] == '"') @@ -1358,7 +1650,7 @@ json_lex(JsonLexContext *lex) { char c = lex->input[i]; - appendStringInfoCharMacro(ptok, c); + jsonapi_appendStringInfoCharMacro(ptok, c); added++; if (c == '"' && escapes % 2 == 0) { @@ -1403,7 +1695,7 @@ json_lex(JsonLexContext *lex) case '8': case '9': { - appendStringInfoCharMacro(ptok, cc); + jsonapi_appendStringInfoCharMacro(ptok, cc); added++; } break; @@ -1424,7 +1716,7 @@ json_lex(JsonLexContext *lex) if (JSON_ALPHANUMERIC_CHAR(cc)) { - appendStringInfoCharMacro(ptok, cc); + jsonapi_appendStringInfoCharMacro(ptok, cc); added++; } else @@ -1467,6 +1759,7 @@ json_lex(JsonLexContext *lex) dummy_lex.input_length = ptok->len; dummy_lex.input_encoding = lex->input_encoding; dummy_lex.incremental = false; + dummy_lex.need_escapes = lex->need_escapes; dummy_lex.strval = lex->strval; partial_result = json_lex(&dummy_lex); @@ -1622,8 +1915,7 @@ json_lex(JsonLexContext *lex) if (lex->incremental && !lex->inc_state->is_last_chunk && p == lex->input + lex->input_length) { - appendBinaryStringInfo( - &(lex->inc_state->partial_token), s, end - s); + jsonapi_appendBinaryStringInfo(&(lex->inc_state->partial_token), s, end - s); return JSON_INCOMPLETE; } @@ -1680,8 +1972,9 @@ json_lex_string(JsonLexContext *lex) do { \ if (lex->incremental && !lex->inc_state->is_last_chunk) \ { \ - appendBinaryStringInfo(&lex->inc_state->partial_token, \ - lex->token_start, end - lex->token_start); \ + jsonapi_appendBinaryStringInfo(&lex->inc_state->partial_token, \ + lex->token_start, \ + end - lex->token_start); \ return JSON_INCOMPLETE; \ } \ lex->token_terminator = s; \ @@ -1689,13 +1982,23 @@ json_lex_string(JsonLexContext *lex) } while (0) #define FAIL_AT_CHAR_END(code) \ do { \ - const char *term = s + pg_encoding_mblen(lex->input_encoding, s); \ - lex->token_terminator = (term <= end) ? term : end; \ + ptrdiff_t remaining = end - s; \ + int charlen; \ + charlen = pg_encoding_mblen_or_incomplete(lex->input_encoding, \ + s, remaining); \ + lex->token_terminator = (charlen <= remaining) ? s + charlen : end; \ return code; \ } while (0) - if (lex->strval != NULL) - resetStringInfo(lex->strval); + if (lex->need_escapes) + { +#ifdef JSONAPI_USE_PQEXPBUFFER + /* make sure initialization succeeded */ + if (lex->strval == NULL) + return JSON_OUT_OF_MEMORY; +#endif + jsonapi_resetStringInfo(lex->strval); + } Assert(lex->input_length > 0); s = lex->token_start; @@ -1732,7 +2035,7 @@ json_lex_string(JsonLexContext *lex) else FAIL_AT_CHAR_END(JSON_UNICODE_ESCAPE_FORMAT); } - if (lex->strval != NULL) + if (lex->need_escapes) { /* * Combine surrogate pairs. @@ -1789,19 +2092,19 @@ json_lex_string(JsonLexContext *lex) unicode_to_utf8(ch, (unsigned char *) utf8str); utf8len = pg_utf_mblen((unsigned char *) utf8str); - appendBinaryStringInfo(lex->strval, utf8str, utf8len); + jsonapi_appendBinaryStringInfo(lex->strval, utf8str, utf8len); } else if (ch <= 0x007f) { /* The ASCII range is the same in all encodings */ - appendStringInfoChar(lex->strval, (char) ch); + jsonapi_appendStringInfoChar(lex->strval, (char) ch); } else FAIL_AT_CHAR_END(JSON_UNICODE_HIGH_ESCAPE); #endif /* FRONTEND */ } } - else if (lex->strval != NULL) + else if (lex->need_escapes) { if (hi_surrogate != -1) FAIL_AT_CHAR_END(JSON_UNICODE_LOW_SURROGATE); @@ -1811,22 +2114,22 @@ json_lex_string(JsonLexContext *lex) case '"': case '\\': case '/': - appendStringInfoChar(lex->strval, *s); + jsonapi_appendStringInfoChar(lex->strval, *s); break; case 'b': - appendStringInfoChar(lex->strval, '\b'); + jsonapi_appendStringInfoChar(lex->strval, '\b'); break; case 'f': - appendStringInfoChar(lex->strval, '\f'); + jsonapi_appendStringInfoChar(lex->strval, '\f'); break; case 'n': - appendStringInfoChar(lex->strval, '\n'); + jsonapi_appendStringInfoChar(lex->strval, '\n'); break; case 'r': - appendStringInfoChar(lex->strval, '\r'); + jsonapi_appendStringInfoChar(lex->strval, '\r'); break; case 't': - appendStringInfoChar(lex->strval, '\t'); + jsonapi_appendStringInfoChar(lex->strval, '\t'); break; default: @@ -1861,7 +2164,7 @@ json_lex_string(JsonLexContext *lex) /* * Skip to the first byte that requires special handling, so we - * can batch calls to appendBinaryStringInfo. + * can batch calls to jsonapi_appendBinaryStringInfo. */ while (p < end - sizeof(Vector8) && !pg_lfind8('\\', (uint8 *) p, sizeof(Vector8)) && @@ -1885,8 +2188,8 @@ json_lex_string(JsonLexContext *lex) } } - if (lex->strval != NULL) - appendBinaryStringInfo(lex->strval, s, p - s); + if (lex->need_escapes) + jsonapi_appendBinaryStringInfo(lex->strval, s, p - s); /* * s will be incremented at the top of the loop, so set it to just @@ -1902,6 +2205,11 @@ json_lex_string(JsonLexContext *lex) return JSON_UNICODE_LOW_SURROGATE; } +#ifdef JSONAPI_USE_PQEXPBUFFER + if (lex->need_escapes && PQExpBufferBroken(lex->strval)) + return JSON_OUT_OF_MEMORY; +#endif + /* Hooray, we found the end of the string! */ lex->prev_token_terminator = lex->token_terminator; lex->token_terminator = s + 1; @@ -2019,8 +2327,8 @@ json_lex_number(JsonLexContext *lex, const char *s, if (lex->incremental && !lex->inc_state->is_last_chunk && len >= lex->input_length) { - appendBinaryStringInfo(&lex->inc_state->partial_token, - lex->token_start, s - lex->token_start); + jsonapi_appendBinaryStringInfo(&lex->inc_state->partial_token, + lex->token_start, s - lex->token_start); if (num_err != NULL) *num_err = error; @@ -2096,19 +2404,25 @@ report_parse_error(JsonParseContext ctx, JsonLexContext *lex) char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex) { + if (error == JSON_OUT_OF_MEMORY || lex == &failed_oom) + { + /* Short circuit. Allocating anything for this case is unhelpful. */ + return _("out of memory"); + } + if (lex->errormsg) - resetStringInfo(lex->errormsg); + jsonapi_resetStringInfo(lex->errormsg); else - lex->errormsg = makeStringInfo(); + lex->errormsg = jsonapi_makeStringInfo(); /* * A helper for error messages that should print the current token. The * format must contain exactly one %.*s specifier. */ #define json_token_error(lex, format) \ - appendStringInfo((lex)->errormsg, _(format), \ - (int) ((lex)->token_terminator - (lex)->token_start), \ - (lex)->token_start); + jsonapi_appendStringInfo((lex)->errormsg, _(format), \ + (int) ((lex)->token_terminator - (lex)->token_start), \ + (lex)->token_start); switch (error) { @@ -2127,9 +2441,9 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex) json_token_error(lex, "Escape sequence \"\\%.*s\" is invalid."); break; case JSON_ESCAPING_REQUIRED: - appendStringInfo(lex->errormsg, - _("Character with value 0x%02x must be escaped."), - (unsigned char) *(lex->token_terminator)); + jsonapi_appendStringInfo(lex->errormsg, + _("Character with value 0x%02x must be escaped."), + (unsigned char) *(lex->token_terminator)); break; case JSON_EXPECTED_END: json_token_error(lex, "Expected end of input, but found \"%.*s\"."); @@ -2160,6 +2474,9 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex) case JSON_INVALID_TOKEN: json_token_error(lex, "Token \"%.*s\" is invalid."); break; + case JSON_OUT_OF_MEMORY: + /* should have been handled above; use the error path */ + break; case JSON_UNICODE_CODE_POINT_ZERO: return _("\\u0000 cannot be converted to text."); case JSON_UNICODE_ESCAPE_FORMAT: @@ -2191,15 +2508,23 @@ json_errdetail(JsonParseErrorType error, JsonLexContext *lex) } #undef json_token_error - /* - * We don't use a default: case, so that the compiler will warn about - * unhandled enum values. But this needs to be here anyway to cover the - * possibility of an incorrect input. - */ - if (lex->errormsg->len == 0) - appendStringInfo(lex->errormsg, - "unexpected json parse error type: %d", - (int) error); + /* Note that lex->errormsg can be NULL in shlib code. */ + if (lex->errormsg && lex->errormsg->len == 0) + { + /* + * We don't use a default: case, so that the compiler will warn about + * unhandled enum values. But this needs to be here anyway to cover + * the possibility of an incorrect input. + */ + jsonapi_appendStringInfo(lex->errormsg, + "unexpected json parse error type: %d", + (int) error); + } + +#ifdef JSONAPI_USE_PQEXPBUFFER + if (PQExpBufferBroken(lex->errormsg)) + return _("out of memory while constructing error description"); +#endif return lex->errormsg->data; } diff --git a/src/common/keywords.c b/src/common/keywords.c index cfd2cb2983d73..8c5639e220e25 100644 --- a/src/common/keywords.c +++ b/src/common/keywords.c @@ -4,7 +4,7 @@ * PostgreSQL's list of SQL keywords * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/kwlookup.c b/src/common/kwlookup.c index eda06f04925ea..76b20c5bb4d58 100644 --- a/src/common/kwlookup.c +++ b/src/common/kwlookup.c @@ -4,7 +4,7 @@ * Key word lookup for PostgreSQL * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/link-canary.c b/src/common/link-canary.c index 5b2d0fc8854f0..5fdc4858e2d19 100644 --- a/src/common/link-canary.c +++ b/src/common/link-canary.c @@ -2,7 +2,7 @@ * link-canary.c * Detect whether src/common functions came from frontend or backend. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/link-canary.c diff --git a/src/common/logging.c b/src/common/logging.c index aedd1ae2d8c12..125a172af80cf 100644 --- a/src/common/logging.c +++ b/src/common/logging.c @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * Logging framework for frontend programs * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * src/common/logging.c * @@ -120,8 +120,9 @@ pg_logging_init(const char *argv0) if (colors) { char *token; + char *cp = colors; - while ((token = strsep(&colors, ":"))) + while ((token = strsep(&cp, ":"))) { char *e = strchr(token, '='); diff --git a/src/common/md5.c b/src/common/md5.c index f1d47722f8a50..c8b4a204964b6 100644 --- a/src/common/md5.c +++ b/src/common/md5.c @@ -7,7 +7,7 @@ * implementation is a simple one, in that it needs every input byte * to be buffered before doing any calculations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -150,10 +150,6 @@ static const uint8 md5_paddat[MD5_BUFLEN] = { 0, 0, 0, 0, 0, 0, 0, 0, }; -#ifdef WORDS_BIGENDIAN -static uint32 X[16]; -#endif - static void md5_calc(const uint8 *b64, pg_md5_ctx *ctx) { @@ -167,6 +163,7 @@ md5_calc(const uint8 *b64, pg_md5_ctx *ctx) #else /* 4 byte words */ /* what a brute force but fast! */ + uint32 X[16]; uint8 *y = (uint8 *) X; y[0] = b64[3]; diff --git a/src/common/md5_common.c b/src/common/md5_common.c index c654efe9718ac..057ae7a449f1c 100644 --- a/src/common/md5_common.c +++ b/src/common/md5_common.c @@ -6,7 +6,7 @@ * * Sverre H. Huseby * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -105,7 +105,7 @@ pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr) * (of size MD5_DIGEST_LENGTH) rather than being converted to ASCII hex. */ bool -pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr) +pg_md5_binary(const void *buff, size_t len, uint8 *outbuf, const char **errstr) { pg_cryptohash_ctx *ctx; @@ -142,7 +142,7 @@ pg_md5_binary(const void *buff, size_t len, void *outbuf, const char **errstr) * error context. */ bool -pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, +pg_md5_encrypt(const char *passwd, const uint8 *salt, size_t salt_len, char *buf, const char **errstr) { size_t passwd_len = strlen(passwd); diff --git a/src/common/md5_int.h b/src/common/md5_int.h index 479e82386f0ef..2706836188cbd 100644 --- a/src/common/md5_int.h +++ b/src/common/md5_int.h @@ -3,7 +3,7 @@ * md5_int.h * Internal headers for fallback implementation of MD5 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/meson.build b/src/common/meson.build index de68e408fa395..1540ba67cca41 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group common_sources = files( 'archive.c', @@ -44,7 +44,6 @@ if ssl.found() common_sources += files( 'cryptohash_openssl.c', 'hmac_openssl.c', - 'protocol_openssl.c', ) else common_sources += files( @@ -101,20 +100,29 @@ common_sources_cflags = { # A few files are currently only built for frontend, not server. # logging.c is excluded from OBJS_FRONTEND_SHLIB (shared library) as # a matter of policy, because it is not appropriate for general purpose -# libraries such as libpq to report errors directly. +# libraries such as libpq to report errors directly. fe_memutils.c is +# excluded because libpq must not exit() on allocation failure. +# +# The excluded files for _shlib builds are pulled into their own static +# library, for the benefit of test programs that need not follow the +# shlib rules. common_sources_frontend_shlib = common_sources common_sources_frontend_shlib += files( - 'fe_memutils.c', 'restricted_token.c', 'sprompt.c', ) -common_sources_frontend_static = common_sources_frontend_shlib -common_sources_frontend_static += files( +common_sources_excluded_shlib = files( + 'fe_memutils.c', 'logging.c', ) +common_sources_frontend_static = [ + common_sources_frontend_shlib, + common_sources_excluded_shlib, +] + # Build pgcommon once for backend, once for use in frontend binaries, and # once for use in shared libraries # @@ -142,6 +150,10 @@ pgcommon_variants = { 'pic': true, 'sources': common_sources_frontend_shlib, 'dependencies': [frontend_common_code], + # The JSON API normally exits on out-of-memory; disable that behavior for + # shared library builds. This requires libpq's pqexpbuffer.h. + 'c_args': ['-DJSONAPI_USE_PQEXPBUFFER'], + 'include_directories': include_directories('../interfaces/libpq'), }, } @@ -157,8 +169,11 @@ foreach name, opts : pgcommon_variants c_args = opts.get('c_args', []) + common_cflags[cflagname] cflag_libs += static_library('libpgcommon@0@_@1@'.format(name, cflagname), c_pch: pch_c_h, - include_directories: include_directories('.'), kwargs: opts + { + 'include_directories': [ + include_directories('.'), + opts.get('include_directories', []), + ], 'sources': sources, 'c_args': c_args, 'build_by_default': false, @@ -169,9 +184,13 @@ foreach name, opts : pgcommon_variants lib = static_library('libpgcommon@0@'.format(name), link_with: cflag_libs, + link_whole: cflag_libs, c_pch: pch_c_h, - include_directories: include_directories('.'), kwargs: opts + { + 'include_directories': [ + include_directories('.'), + opts.get('include_directories', []), + ], 'dependencies': opts['dependencies'] + [ssl], } ) @@ -182,4 +201,13 @@ common_srv = pgcommon['_srv'] common_shlib = pgcommon['_shlib'] common_static = pgcommon[''] +common_excluded_shlib = static_library('libpgcommon_excluded_shlib', + sources: common_sources_excluded_shlib, + dependencies: [frontend_common_code], + build_by_default: false, + kwargs: default_lib_args + { + 'install': false, + }, +) + subdir('unicode') diff --git a/src/common/parse_manifest.c b/src/common/parse_manifest.c index 612e120b17aee..71973af199b90 100644 --- a/src/common/parse_manifest.c +++ b/src/common/parse_manifest.c @@ -3,7 +3,7 @@ * parse_manifest.c * Parse a backup manifest in JSON format. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/common/parse_manifest.c @@ -114,8 +114,8 @@ static void json_manifest_finalize_wal_range(JsonManifestParseState *parse); static void verify_manifest_checksum(JsonManifestParseState *parse, const char *buffer, size_t size, pg_cryptohash_ctx *incr_ctx); -static void json_manifest_parse_failure(JsonManifestParseContext *context, - char *msg); +pg_noreturn static void json_manifest_parse_failure(JsonManifestParseContext *context, + char *msg); static int hexdecode_char(char c); static bool hexdecode_string(uint8 *result, char *input, int nbytes); @@ -182,9 +182,8 @@ json_parse_manifest_incremental_shutdown(JsonManifestParseIncrementalState *incs */ void -json_parse_manifest_incremental_chunk( - JsonManifestParseIncrementalState *incstate, const char *chunk, size_t size, - bool is_last) +json_parse_manifest_incremental_chunk(JsonManifestParseIncrementalState *incstate, + const char *chunk, size_t size, bool is_last) { JsonParseErrorType res, expected; @@ -634,7 +633,7 @@ json_manifest_finalize_system_identifier(JsonManifestParseState *parse) system_identifier = strtou64(parse->manifest_system_identifier, &ep, 10); if (*ep) json_manifest_parse_failure(parse->context, - "manifest system identifier not an integer"); + "system identifier in manifest not an integer"); /* Invoke the callback for system identifier */ context->system_identifier_cb(context, system_identifier); @@ -650,7 +649,7 @@ static void json_manifest_finalize_file(JsonManifestParseState *parse) { JsonManifestParseContext *context = parse->context; - size_t size; + uint64 size; char *ep; int checksum_string_length; pg_checksum_type checksum_type; @@ -688,7 +687,7 @@ json_manifest_finalize_file(JsonManifestParseState *parse) } /* Parse size. */ - size = strtoul(parse->size, &ep, 10); + size = strtou64(parse->size, &ep, 10); if (*ep) json_manifest_parse_failure(parse->context, "file size is not an integer"); @@ -890,6 +889,7 @@ static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg) { context->error_cb(context, "could not parse backup manifest: %s", msg); + pg_unreachable(); } /* diff --git a/src/common/percentrepl.c b/src/common/percentrepl.c index acad6aacf3b01..8225a281d7d0c 100644 --- a/src/common/percentrepl.c +++ b/src/common/percentrepl.c @@ -3,7 +3,7 @@ * percentrepl.c * Common routines to replace percent placeholders in strings * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/pg_get_line.c b/src/common/pg_get_line.c index ea37a359454cd..8d28a0ae6dbce 100644 --- a/src/common/pg_get_line.c +++ b/src/common/pg_get_line.c @@ -3,7 +3,7 @@ * pg_get_line.c * fgets() with an expansible result buffer * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/pg_lzcompress.c b/src/common/pg_lzcompress.c index 64237424b512f..86354d660fdf5 100644 --- a/src/common/pg_lzcompress.c +++ b/src/common/pg_lzcompress.c @@ -172,7 +172,7 @@ * * Jan Wieck * - * Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Copyright (c) 1999-2025, PostgreSQL Global Development Group * * src/common/pg_lzcompress.c * ---------- diff --git a/src/common/pg_prng.c b/src/common/pg_prng.c index 15b39411a9b69..370d81b31673d 100644 --- a/src/common/pg_prng.c +++ b/src/common/pg_prng.c @@ -10,7 +10,7 @@ * About these generators: https://prng.di.unimi.it/ * See also https://en.wikipedia.org/wiki/List_of_random_number_generators * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * src/common/pg_prng.c * diff --git a/src/common/pgfnames.c b/src/common/pgfnames.c index 532870812de75..8fb79105714b6 100644 --- a/src/common/pgfnames.c +++ b/src/common/pgfnames.c @@ -3,7 +3,7 @@ * pgfnames.c * directory handling functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/protocol_openssl.c b/src/common/protocol_openssl.c deleted file mode 100644 index ae378685e1f60..0000000000000 --- a/src/common/protocol_openssl.c +++ /dev/null @@ -1,117 +0,0 @@ -/*------------------------------------------------------------------------- - * - * protocol_openssl.c - * OpenSSL functionality shared between frontend and backend - * - * This should only be used if code is compiled with OpenSSL support. - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * src/common/protocol_openssl.c - * - *------------------------------------------------------------------------- - */ - -#ifndef FRONTEND -#include "postgres.h" -#else -#include "postgres_fe.h" -#endif - -#include "common/openssl.h" - -/* - * Replacements for APIs introduced in OpenSSL 1.1.0. - */ -#ifndef SSL_CTX_set_min_proto_version - -/* - * OpenSSL versions that support TLS 1.3 shouldn't get here because they - * already have these functions. So we don't have to keep updating the below - * code for every new TLS version, and eventually it can go away. But let's - * just check this to make sure ... - */ -#ifdef TLS1_3_VERSION -#error OpenSSL version mismatch -#endif - -int -SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version) -{ - int ssl_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - - if (version > TLS1_VERSION) - ssl_options |= SSL_OP_NO_TLSv1; - - /* - * Some OpenSSL versions define TLS*_VERSION macros but not the - * corresponding SSL_OP_NO_* macro, so in those cases we have to return - * unsuccessfully here. - */ -#ifdef TLS1_1_VERSION - if (version > TLS1_1_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_1 - ssl_options |= SSL_OP_NO_TLSv1_1; -#else - return 0; -#endif - } -#endif -#ifdef TLS1_2_VERSION - if (version > TLS1_2_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_2 - ssl_options |= SSL_OP_NO_TLSv1_2; -#else - return 0; -#endif - } -#endif - - SSL_CTX_set_options(ctx, ssl_options); - - return 1; /* success */ -} - -int -SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version) -{ - int ssl_options = 0; - - Assert(version != 0); - - /* - * Some OpenSSL versions define TLS*_VERSION macros but not the - * corresponding SSL_OP_NO_* macro, so in those cases we have to return - * unsuccessfully here. - */ -#ifdef TLS1_1_VERSION - if (version < TLS1_1_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_1 - ssl_options |= SSL_OP_NO_TLSv1_1; -#else - return 0; -#endif - } -#endif -#ifdef TLS1_2_VERSION - if (version < TLS1_2_VERSION) - { -#ifdef SSL_OP_NO_TLSv1_2 - ssl_options |= SSL_OP_NO_TLSv1_2; -#else - return 0; -#endif - } -#endif - - SSL_CTX_set_options(ctx, ssl_options); - - return 1; /* success */ -} - -#endif /* !SSL_CTX_set_min_proto_version */ diff --git a/src/common/psprintf.c b/src/common/psprintf.c index a063fd26d51a2..15e68599dc55f 100644 --- a/src/common/psprintf.c +++ b/src/common/psprintf.c @@ -4,7 +4,7 @@ * sprintf into an allocated-on-demand buffer * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -24,9 +24,6 @@ #include "postgres_fe.h" -/* It's possible we could use a different value for this in frontend code */ -#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */ - #endif diff --git a/src/common/relpath.c b/src/common/relpath.c index f54c36ef7ac9f..7dcf987afcd01 100644 --- a/src/common/relpath.c +++ b/src/common/relpath.c @@ -4,7 +4,7 @@ * * This module also contains some logic associated with fork names. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -123,25 +123,27 @@ GetDatabasePath(Oid dbOid, Oid spcOid) else { /* All other tablespaces are accessed via symlinks */ - return psprintf("pg_tblspc/%u/%s/%u", - spcOid, TABLESPACE_VERSION_DIRECTORY, dbOid); + return psprintf("%s/%u/%s/%u", + PG_TBLSPC_DIR, spcOid, + TABLESPACE_VERSION_DIRECTORY, dbOid); } } /* * GetRelationPath - construct path to a relation's file * - * Result is a palloc'd string. + * The result is returned in-place as a struct, to make it suitable for use in + * critical sections etc. * * Note: ideally, procNumber would be declared as type ProcNumber, but * relpath.h would have to include a backend-only header to do that; doesn't * seem worth the trouble considering ProcNumber is just int anyway. */ -char * +RelPathStr GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, int procNumber, ForkNumber forkNumber) { - char *path; + RelPathStr rp; if (spcOid == GLOBALTABLESPACE_OID) { @@ -149,10 +151,11 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, Assert(dbOid == 0); Assert(procNumber == INVALID_PROC_NUMBER); if (forkNumber != MAIN_FORKNUM) - path = psprintf("global/%u_%s", - relNumber, forkNames[forkNumber]); + sprintf(rp.str, "global/%u_%s", + relNumber, forkNames[forkNumber]); else - path = psprintf("global/%u", relNumber); + sprintf(rp.str, "global/%u", + relNumber); } else if (spcOid == DEFAULTTABLESPACE_OID) { @@ -160,22 +163,24 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, if (procNumber == INVALID_PROC_NUMBER) { if (forkNumber != MAIN_FORKNUM) - path = psprintf("base/%u/%u_%s", - dbOid, relNumber, - forkNames[forkNumber]); + { + sprintf(rp.str, "base/%u/%u_%s", + dbOid, relNumber, + forkNames[forkNumber]); + } else - path = psprintf("base/%u/%u", - dbOid, relNumber); + sprintf(rp.str, "base/%u/%u", + dbOid, relNumber); } else { if (forkNumber != MAIN_FORKNUM) - path = psprintf("base/%u/t%d_%u_%s", - dbOid, procNumber, relNumber, - forkNames[forkNumber]); + sprintf(rp.str, "base/%u/t%d_%u_%s", + dbOid, procNumber, relNumber, + forkNames[forkNumber]); else - path = psprintf("base/%u/t%d_%u", - dbOid, procNumber, relNumber); + sprintf(rp.str, "base/%u/t%d_%u", + dbOid, procNumber, relNumber); } } else @@ -184,27 +189,34 @@ GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, if (procNumber == INVALID_PROC_NUMBER) { if (forkNumber != MAIN_FORKNUM) - path = psprintf("pg_tblspc/%u/%s/%u/%u_%s", - spcOid, TABLESPACE_VERSION_DIRECTORY, - dbOid, relNumber, - forkNames[forkNumber]); + sprintf(rp.str, "%s/%u/%s/%u/%u_%s", + PG_TBLSPC_DIR, spcOid, + TABLESPACE_VERSION_DIRECTORY, + dbOid, relNumber, + forkNames[forkNumber]); else - path = psprintf("pg_tblspc/%u/%s/%u/%u", - spcOid, TABLESPACE_VERSION_DIRECTORY, - dbOid, relNumber); + sprintf(rp.str, "%s/%u/%s/%u/%u", + PG_TBLSPC_DIR, spcOid, + TABLESPACE_VERSION_DIRECTORY, + dbOid, relNumber); } else { if (forkNumber != MAIN_FORKNUM) - path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u_%s", - spcOid, TABLESPACE_VERSION_DIRECTORY, - dbOid, procNumber, relNumber, - forkNames[forkNumber]); + sprintf(rp.str, "%s/%u/%s/%u/t%d_%u_%s", + PG_TBLSPC_DIR, spcOid, + TABLESPACE_VERSION_DIRECTORY, + dbOid, procNumber, relNumber, + forkNames[forkNumber]); else - path = psprintf("pg_tblspc/%u/%s/%u/t%d_%u", - spcOid, TABLESPACE_VERSION_DIRECTORY, - dbOid, procNumber, relNumber); + sprintf(rp.str, "%s/%u/%s/%u/t%d_%u", + PG_TBLSPC_DIR, spcOid, + TABLESPACE_VERSION_DIRECTORY, + dbOid, procNumber, relNumber); } } - return path; + + Assert(strnlen(rp.str, REL_PATH_STR_MAXLEN + 1) <= REL_PATH_STR_MAXLEN); + + return rp; } diff --git a/src/common/restricted_token.c b/src/common/restricted_token.c index d04101d6d15d2..61884f59dea8c 100644 --- a/src/common/restricted_token.c +++ b/src/common/restricted_token.c @@ -4,7 +4,7 @@ * helper routine to ensure restricted token on Windows * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,7 +26,7 @@ #ifdef WIN32 /* internal vars */ -char *restrict_env; +static char *restrict_env; /* Windows API define missing from some versions of MingW headers */ #ifndef DISABLE_MAX_PRIVILEGE diff --git a/src/common/rmtree.c b/src/common/rmtree.c index 7871796099970..2f364f84ae5b2 100644 --- a/src/common/rmtree.c +++ b/src/common/rmtree.c @@ -2,7 +2,7 @@ * * rmtree.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/ryu_common.h b/src/common/ryu_common.h index 3de519bb725d6..bb1389bac3774 100644 --- a/src/common/ryu_common.h +++ b/src/common/ryu_common.h @@ -2,7 +2,7 @@ * * Common routines for Ryu floating-point output. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/ryu_common.h diff --git a/src/common/saslprep.c b/src/common/saslprep.c index 315ccacd7ce45..97beb47940bfe 100644 --- a/src/common/saslprep.c +++ b/src/common/saslprep.c @@ -12,7 +12,7 @@ * http://www.ietf.org/rfc/rfc4013.txt * * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/saslprep.c @@ -21,6 +21,7 @@ */ #ifndef FRONTEND #include "postgres.h" +#include "utils/memutils.h" #else #include "postgres_fe.h" #endif @@ -1004,15 +1005,17 @@ pg_utf8_string_len(const char *source) const unsigned char *p = (const unsigned char *) source; int l; int num_chars = 0; + size_t len = strlen(source); - while (*p) + while (len) { l = pg_utf_mblen(p); - if (!pg_utf8_islegal(p, l)) + if (len < l || !pg_utf8_islegal(p, l)) return -1; p += l; + len -= l; num_chars++; } @@ -1077,6 +1080,8 @@ pg_saslprep(const char *input, char **output) input_size = pg_utf8_string_len(input); if (input_size < 0) return SASLPREP_INVALID_UTF8; + if (input_size >= MaxAllocSize / sizeof(pg_wchar)) + goto oom; input_chars = ALLOC((input_size + 1) * sizeof(pg_wchar)); if (!input_chars) diff --git a/src/common/scram-common.c b/src/common/scram-common.c index b611bb8fe71c9..e47a6ebbaab0f 100644 --- a/src/common/scram-common.c +++ b/src/common/scram-common.c @@ -6,7 +6,7 @@ * backend, for implement the Salted Challenge Response Authentication * Mechanism (SCRAM), per IETF's RFC 5802. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/scram-common.c @@ -37,7 +37,7 @@ int scram_SaltedPassword(const char *password, pg_cryptohash_type hash_type, int key_length, - const char *salt, int saltlen, int iterations, + const uint8 *salt, int saltlen, int iterations, uint8 *result, const char **errstr) { int password_len = strlen(password); @@ -62,7 +62,7 @@ scram_SaltedPassword(const char *password, /* First iteration */ if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 || - pg_hmac_update(hmac_ctx, (uint8 *) salt, saltlen) < 0 || + pg_hmac_update(hmac_ctx, salt, saltlen) < 0 || pg_hmac_update(hmac_ctx, (uint8 *) &one, sizeof(uint32)) < 0 || pg_hmac_final(hmac_ctx, Ui_prev, key_length) < 0) { @@ -74,7 +74,7 @@ scram_SaltedPassword(const char *password, memcpy(result, Ui_prev, key_length); /* Subsequent iterations */ - for (i = 2; i <= iterations; i++) + for (i = 1; i < iterations; i++) { #ifndef FRONTEND /* @@ -200,15 +200,14 @@ scram_ServerKey(const uint8 *salted_password, * * The password should already have been processed with SASLprep, if necessary! * - * If iterations is 0, default number of iterations is used. The result is - * palloc'd or malloc'd, so caller is responsible for freeing it. + * The result is palloc'd or malloc'd, so caller is responsible for freeing it. * * On error, returns NULL and sets *errstr to point to a message about the * error details. */ char * scram_build_secret(pg_cryptohash_type hash_type, int key_length, - const char *salt, int saltlen, int iterations, + const uint8 *salt, int saltlen, int iterations, const char *password, const char **errstr) { uint8 salted_password[SCRAM_MAX_KEY_LEN]; @@ -291,7 +290,7 @@ scram_build_secret(pg_cryptohash_type hash_type, int key_length, *(p++) = '$'; /* stored key */ - encoded_result = pg_b64_encode((char *) stored_key, key_length, p, + encoded_result = pg_b64_encode(stored_key, key_length, p, encoded_stored_len); if (encoded_result < 0) { @@ -308,7 +307,7 @@ scram_build_secret(pg_cryptohash_type hash_type, int key_length, *(p++) = ':'; /* server key */ - encoded_result = pg_b64_encode((char *) server_key, key_length, p, + encoded_result = pg_b64_encode(server_key, key_length, p, encoded_server_len); if (encoded_result < 0) { diff --git a/src/common/sha1.c b/src/common/sha1.c index 0525c4ff31652..f29866f8359bc 100644 --- a/src/common/sha1.c +++ b/src/common/sha1.c @@ -5,7 +5,7 @@ * * Fallback implementation of SHA1, as specified in RFC 3174. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -61,7 +61,7 @@ #include "sha1_int.h" /* constant table */ -static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; +static const uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; #define K(t) _K[(t) / 20] diff --git a/src/common/sha1_int.h b/src/common/sha1_int.h index ee56488e574c9..a7a72fe1deb10 100644 --- a/src/common/sha1_int.h +++ b/src/common/sha1_int.h @@ -3,7 +3,7 @@ * sha1_int.h * Internal headers for fallback implementation of SHA1 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/sha2.c b/src/common/sha2.c index 736634b24be5d..e7c163dba561a 100644 --- a/src/common/sha2.c +++ b/src/common/sha2.c @@ -6,7 +6,7 @@ * This includes the fallback implementation for SHA2 cryptographic * hashes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/sha2_int.h b/src/common/sha2_int.h index 0e32c651c38b1..f9c77b856edaf 100644 --- a/src/common/sha2_int.h +++ b/src/common/sha2_int.h @@ -3,7 +3,7 @@ * sha2_int.h * Internal headers for fallback implementation of SHA{224,256,384,512} * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/sha2_int.h diff --git a/src/common/sprompt.c b/src/common/sprompt.c index 27c336f03f37c..06e1b5335a4bb 100644 --- a/src/common/sprompt.c +++ b/src/common/sprompt.c @@ -3,7 +3,7 @@ * sprompt.c * simple_prompt() routine * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/string.c b/src/common/string.c index ce9f2bc7ca592..d8a3129c3ba8d 100644 --- a/src/common/string.c +++ b/src/common/string.c @@ -4,7 +4,7 @@ * string handling helpers * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,7 +22,6 @@ #endif #include "common/string.h" -#include "lib/stringinfo.h" /* diff --git a/src/common/stringinfo.c b/src/common/stringinfo.c index eb9d6502fc89a..22d03807697ec 100644 --- a/src/common/stringinfo.c +++ b/src/common/stringinfo.c @@ -7,7 +7,7 @@ * (null-terminated text) or arbitrary binary data. All storage is allocated * with palloc() (falling back to malloc in frontend code). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/common/stringinfo.c @@ -24,14 +24,45 @@ #include "postgres_fe.h" -/* It's possible we could use a different value for this in frontend code */ -#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */ - #endif #include "lib/stringinfo.h" +/* + * initStringInfoInternal + * + * Initialize a StringInfoData struct (with previously undefined contents) + * to describe an empty string. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +static inline void +initStringInfoInternal(StringInfo str, int initsize) +{ + Assert(initsize >= 1 && initsize <= MaxAllocSize); + + str->data = (char *) palloc(initsize); + str->maxlen = initsize; + resetStringInfo(str); +} + +/* + * makeStringInfoInternal(int initsize) + * + * Create an empty 'StringInfoData' & return a pointer to it. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +static inline StringInfo +makeStringInfoInternal(int initsize) +{ + StringInfo res = (StringInfo) palloc(sizeof(StringInfoData)); + + initStringInfoInternal(res, initsize); + return res; +} + /* * makeStringInfo * @@ -40,13 +71,20 @@ StringInfo makeStringInfo(void) { - StringInfo res; - - res = (StringInfo) palloc(sizeof(StringInfoData)); - - initStringInfo(res); + return makeStringInfoInternal(STRINGINFO_DEFAULT_SIZE); +} - return res; +/* + * makeStringInfoExt(int initsize) + * + * Create an empty 'StringInfoData' & return a pointer to it. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +StringInfo +makeStringInfoExt(int initsize) +{ + return makeStringInfoInternal(initsize); } /* @@ -58,11 +96,21 @@ makeStringInfo(void) void initStringInfo(StringInfo str) { - int size = 1024; /* initial default buffer size */ + initStringInfoInternal(str, STRINGINFO_DEFAULT_SIZE); +} - str->data = (char *) palloc(size); - str->maxlen = size; - resetStringInfo(str); +/* + * initStringInfoExt + * + * Initialize a StringInfoData struct (with previously undefined contents) + * to describe an empty string. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +void +initStringInfoExt(StringInfo str, int initsize) +{ + initStringInfoInternal(str, initsize); } /* diff --git a/src/common/unicode/Makefile b/src/common/unicode/Makefile index c38ab36b1e4a1..c150e403cda39 100644 --- a/src/common/unicode/Makefile +++ b/src/common/unicode/Makefile @@ -30,13 +30,13 @@ update-unicode: unicode_case_table.h unicode_category_table.h unicode_east_asian # These files are part of the Unicode Character Database. Download # them on demand. The dependency on Makefile.global is for # UNICODE_VERSION. -CompositionExclusions.txt DerivedCoreProperties.txt DerivedNormalizationProps.txt EastAsianWidth.txt NormalizationTest.txt PropList.txt UnicodeData.txt: $(top_builddir)/src/Makefile.global +CompositionExclusions.txt CaseFolding.txt DerivedCoreProperties.txt DerivedNormalizationProps.txt EastAsianWidth.txt NormalizationTest.txt PropList.txt SpecialCasing.txt UnicodeData.txt: $(top_builddir)/src/Makefile.global $(DOWNLOAD) https://www.unicode.org/Public/$(UNICODE_VERSION)/ucd/$(@F) unicode_version.h: generate-unicode_version.pl $(PERL) $< --version $(UNICODE_VERSION) -unicode_case_table.h: generate-unicode_case_table.pl UnicodeData.txt +unicode_case_table.h: generate-unicode_case_table.pl CaseFolding.txt SpecialCasing.txt UnicodeData.txt $(PERL) $< unicode_category_table.h: generate-unicode_category_table.pl DerivedCoreProperties.txt PropList.txt UnicodeData.txt @@ -91,4 +91,4 @@ clean: rm -f $(OBJS) case_test case_test.o category_test category_test.o norm_test norm_test.o distclean: clean - rm -f CompositionExclusions.txt DerivedCoreProperties.txt DerivedNormalizationProps.txt EastAsianWidth.txt NormalizationTest.txt PropList.txt UnicodeData.txt norm_test_table.h unicode_case_table.h unicode_category_table.h unicode_norm_table.h + rm -f CompositionExclusions.txt CaseFolding.txt DerivedCoreProperties.txt DerivedNormalizationProps.txt EastAsianWidth.txt NormalizationTest.txt PropList.txt SpecialCasing.txt UnicodeData.txt norm_test_table.h unicode_case_table.h unicode_category_table.h unicode_norm_table.h diff --git a/src/common/unicode/case_test.c b/src/common/unicode/case_test.c index de92811ec7261..fdfb62e855286 100644 --- a/src/common/unicode/case_test.c +++ b/src/common/unicode/case_test.c @@ -2,7 +2,7 @@ * case_test.c * Program to test Unicode case mapping functions. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode/case_test.c @@ -18,12 +18,62 @@ #include #ifdef USE_ICU +#include #include #endif #include "common/unicode_case.h" #include "common/unicode_category.h" #include "common/unicode_version.h" +/* enough to hold largest source or result string, including NUL */ +#define BUFSZ 256 + +#ifdef USE_ICU +static UCaseMap * casemap = NULL; +#endif + +typedef size_t (*TestFunc) (char *dst, size_t dstsize, const char *src, + ssize_t srclen); + +/* simple boundary iterator copied from pg_locale_builtin.c */ +struct WordBoundaryState +{ + const char *str; + size_t len; + size_t offset; + bool posix; + bool init; + bool prev_alnum; +}; + +static size_t +initcap_wbnext(void *state) +{ + struct WordBoundaryState *wbstate = (struct WordBoundaryState *) state; + + while (wbstate->offset < wbstate->len && + wbstate->str[wbstate->offset] != '\0') + { + pg_wchar u = utf8_to_unicode((unsigned char *) wbstate->str + + wbstate->offset); + bool curr_alnum = pg_u_isalnum(u, wbstate->posix); + + if (!wbstate->init || curr_alnum != wbstate->prev_alnum) + { + size_t prev_offset = wbstate->offset; + + wbstate->init = true; + wbstate->offset += unicode_utf8len(u); + wbstate->prev_alnum = curr_alnum; + return prev_offset; + } + + wbstate->offset += unicode_utf8len(u); + } + + return wbstate->len; +} + #ifdef USE_ICU static void @@ -32,22 +82,87 @@ icu_test_simple(pg_wchar code) pg_wchar lower = unicode_lowercase_simple(code); pg_wchar title = unicode_titlecase_simple(code); pg_wchar upper = unicode_uppercase_simple(code); + pg_wchar fold = unicode_casefold_simple(code); pg_wchar iculower = u_tolower(code); pg_wchar icutitle = u_totitle(code); pg_wchar icuupper = u_toupper(code); + pg_wchar icufold = u_foldCase(code, U_FOLD_CASE_DEFAULT); - if (lower != iculower || title != icutitle || upper != icuupper) + if (lower != iculower || title != icutitle || upper != icuupper || + fold != icufold) { printf("case_test: FAILURE for codepoint 0x%06x\n", code); - printf("case_test: Postgres lower/title/upper: 0x%06x/0x%06x/0x%06x\n", - lower, title, upper); - printf("case_test: ICU lower/title/upper: 0x%06x/0x%06x/0x%06x\n", - iculower, icutitle, icuupper); + printf("case_test: Postgres lower/title/upper/fold: 0x%06x/0x%06x/0x%06x/0x%06x\n", + lower, title, upper, fold); + printf("case_test: ICU lower/title/upper/fold: 0x%06x/0x%06x/0x%06x/0x%06x\n", + iculower, icutitle, icuupper, icufold); printf("\n"); exit(1); } } +static void +icu_test_full(char *str) +{ + char lower[BUFSZ]; + char title[BUFSZ]; + char upper[BUFSZ]; + char fold[BUFSZ]; + char icu_lower[BUFSZ]; + char icu_title[BUFSZ]; + char icu_upper[BUFSZ]; + char icu_fold[BUFSZ]; + UErrorCode status; + + /* full case mapping doesn't use posix semantics */ + struct WordBoundaryState wbstate = { + .str = str, + .len = strlen(str), + .offset = 0, + .posix = false, + .init = false, + .prev_alnum = false, + }; + + unicode_strlower(lower, BUFSZ, str, -1, true); + unicode_strtitle(title, BUFSZ, str, -1, true, initcap_wbnext, &wbstate); + unicode_strupper(upper, BUFSZ, str, -1, true); + unicode_strfold(fold, BUFSZ, str, -1, true); + status = U_ZERO_ERROR; + ucasemap_utf8ToLower(casemap, icu_lower, BUFSZ, str, -1, &status); + status = U_ZERO_ERROR; + ucasemap_utf8ToTitle(casemap, icu_title, BUFSZ, str, -1, &status); + status = U_ZERO_ERROR; + ucasemap_utf8ToUpper(casemap, icu_upper, BUFSZ, str, -1, &status); + status = U_ZERO_ERROR; + ucasemap_utf8FoldCase(casemap, icu_fold, BUFSZ, str, -1, &status); + + if (strcmp(lower, icu_lower) != 0) + { + printf("case_test: str='%s' lower='%s' icu_lower='%s'\n", str, lower, + icu_lower); + exit(1); + } + if (strcmp(title, icu_title) != 0) + { + printf("case_test: str='%s' title='%s' icu_title='%s'\n", str, title, + icu_title); + exit(1); + } + if (strcmp(upper, icu_upper) != 0) + { + printf("case_test: str='%s' upper='%s' icu_upper='%s'\n", str, upper, + icu_upper); + exit(1); + } + if (strcmp(fold, icu_fold) != 0) + { + printf("case_test: str='%s' fold='%s' icu_fold='%s'\n", str, fold, + icu_fold); + exit(1); + } +} + /* * Exhaustively compare case mappings with the results from ICU. */ @@ -64,6 +179,7 @@ test_icu(void) if (category != PG_U_UNASSIGNED) { uint8_t icu_category = u_charType(code); + char code_str[5] = {0}; if (icu_category == PG_U_UNASSIGNED) { @@ -72,6 +188,9 @@ test_icu(void) } icu_test_simple(code); + unicode_to_utf8(code, (unsigned char *) code_str); + icu_test_full(code_str); + successful++; } } @@ -86,7 +205,7 @@ test_icu(void) #endif static void -test_strlower(const char *test_string, const char *expected) +test_convert(TestFunc tfunc, const char *test_string, const char *expected) { size_t src1len = strlen(test_string); size_t src2len = -1; /* NUL-terminated */ @@ -102,10 +221,11 @@ test_strlower(const char *test_string, const char *expected) /* neither source nor destination are NUL-terminated */ memset(dst1, 0x7F, dst1len); - needed = unicode_strlower(dst1, dst1len, src1, src1len); + needed = tfunc(dst1, dst1len, src1, src1len); if (needed != strlen(expected)) { - printf("case_test: convert_case test1 FAILURE: needed %zu\n", needed); + printf("case_test: convert_case test1 FAILURE: '%s' needed %zu expected %zu\n", + test_string, needed, strlen(expected)); exit(1); } if (memcmp(dst1, expected, dst1len) != 0) @@ -117,10 +237,11 @@ test_strlower(const char *test_string, const char *expected) /* destination is NUL-terminated and source is not */ memset(dst2, 0x7F, dst2len); - needed = unicode_strlower(dst2, dst2len, src1, src1len); + needed = tfunc(dst2, dst2len, src1, src1len); if (needed != strlen(expected)) { - printf("case_test: convert_case test2 FAILURE: needed %zu\n", needed); + printf("case_test: convert_case test2 FAILURE: '%s' needed %zu expected %zu\n", + test_string, needed, strlen(expected)); exit(1); } if (strcmp(dst2, expected) != 0) @@ -132,9 +253,11 @@ test_strlower(const char *test_string, const char *expected) /* source is NUL-terminated and destination is not */ memset(dst1, 0x7F, dst1len); - needed = unicode_strlower(dst1, dst1len, src2, src2len); + needed = tfunc(dst1, dst1len, src2, src2len); if (needed != strlen(expected)) { + printf("case_test: convert_case test3 FAILURE: '%s' needed %zu expected %zu\n", + test_string, needed, strlen(expected)); printf("case_test: convert_case test3 FAILURE: needed %zu\n", needed); exit(1); } @@ -147,10 +270,11 @@ test_strlower(const char *test_string, const char *expected) /* both source and destination are NUL-terminated */ memset(dst2, 0x7F, dst2len); - needed = unicode_strlower(dst2, dst2len, src2, src2len); + needed = tfunc(dst2, dst2len, src2, src2len); if (needed != strlen(expected)) { - printf("case_test: convert_case test4 FAILURE: needed %zu\n", needed); + printf("case_test: convert_case test4 FAILURE: '%s' needed %zu expected %zu\n", + test_string, needed, strlen(expected)); exit(1); } if (strcmp(dst2, expected) != 0) @@ -166,15 +290,84 @@ test_strlower(const char *test_string, const char *expected) free(dst2); } +static size_t +tfunc_lower(char *dst, size_t dstsize, const char *src, + ssize_t srclen) +{ + return unicode_strlower(dst, dstsize, src, srclen, true); +} + +static size_t +tfunc_title(char *dst, size_t dstsize, const char *src, + ssize_t srclen) +{ + struct WordBoundaryState wbstate = { + .str = src, + .len = srclen, + .offset = 0, + .init = false, + .prev_alnum = false, + }; + + return unicode_strtitle(dst, dstsize, src, srclen, true, initcap_wbnext, + &wbstate); +} + +static size_t +tfunc_upper(char *dst, size_t dstsize, const char *src, + ssize_t srclen) +{ + return unicode_strupper(dst, dstsize, src, srclen, true); +} + +static size_t +tfunc_fold(char *dst, size_t dstsize, const char *src, + ssize_t srclen) +{ + return unicode_strfold(dst, dstsize, src, srclen, true); +} + static void test_convert_case() { /* test string with no case changes */ - test_strlower("√∞", "√∞"); + test_convert(tfunc_lower, "√∞", "√∞"); + /* test adjust-to-cased behavior */ + test_convert(tfunc_title, "abc 123xyz", "Abc 123xyz"); /* test string with case changes */ - test_strlower("ABC", "abc"); + test_convert(tfunc_upper, "abc", "ABC"); /* test string with case changes and byte length changes */ - test_strlower("ȺȺȺ", "ⱥⱥⱥ"); + test_convert(tfunc_lower, "ȺȺȺ", "ⱥⱥⱥ"); + /* test special case conversions */ + test_convert(tfunc_upper, "ß", "SS"); + test_convert(tfunc_lower, "ıiIİ", "ıiii\u0307"); + test_convert(tfunc_upper, "ıiIİ", "IIIİ"); + test_convert(tfunc_fold, "ıiIİ", "ıiii\u0307"); + /* test final sigma */ + test_convert(tfunc_lower, "σςΣ ΣΣΣ", "σςς σσς"); + test_convert(tfunc_lower, "σς'Σ' ΣΣ'Σ'", "σς'ς' σσ'ς'"); + test_convert(tfunc_title, "σςΣ ΣΣΣ", "Σςς Σσς"); + test_convert(tfunc_fold, "σςΣ ΣΣΣ", "σσσ σσσ"); + /* test that alphanumerics are word characters */ + test_convert(tfunc_title, "λλ", "Λλ"); + test_convert(tfunc_title, "1a", "1a"); + /* U+FF11 FULLWIDTH ONE is alphanumeric for full case mapping */ + test_convert(tfunc_title, "\uFF11a", "\uFF11a"); + + +#ifdef USE_ICU + icu_test_full(""); + icu_test_full("ȺȺȺ"); + icu_test_full("ßßß"); + icu_test_full("√∞"); + icu_test_full("a b"); + icu_test_full("abc 123xyz"); + icu_test_full("σςΣ ΣΣΣ"); + icu_test_full("ıiIİ"); + icu_test_full("\uFF11a"); + /* test */ + icu_test_full("\u0391\u0345\u0301"); +#endif printf("case_test: convert_case: success\n"); } @@ -182,6 +375,22 @@ test_convert_case() int main(int argc, char **argv) { +#ifdef USE_ICU + UErrorCode status = U_ZERO_ERROR; + + /* + * Disable ICU's word break adjustment for titlecase to match the expected + * behavior of unicode_strtitle(). + */ + casemap = ucasemap_open("und", U_TITLECASE_NO_BREAK_ADJUSTMENT, &status); + if (U_FAILURE(status)) + { + printf("case_test: failure opening UCaseMap: %s\n", + u_errorName(status)); + exit(1); + } +#endif + printf("case_test: Postgres Unicode version:\t%s\n", PG_UNICODE_VERSION); #ifdef USE_ICU printf("case_test: ICU Unicode version:\t\t%s\n", U_UNICODE_VERSION); @@ -191,5 +400,9 @@ main(int argc, char **argv) #endif test_convert_case(); + +#ifdef USE_ICU + ucasemap_close(casemap); +#endif exit(0); } diff --git a/src/common/unicode/category_test.c b/src/common/unicode/category_test.c index e823044d63a2f..5d37ba391968e 100644 --- a/src/common/unicode/category_test.c +++ b/src/common/unicode/category_test.c @@ -2,7 +2,7 @@ * category_test.c * Program to test Unicode general category and character properties. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode/category_test.c @@ -74,22 +74,14 @@ icu_test() bool prop_hex_digit = pg_u_prop_hex_digit(code); bool prop_join_control = pg_u_prop_join_control(code); - bool icu_prop_alphabetic = u_hasBinaryProperty( - code, UCHAR_ALPHABETIC); - bool icu_prop_lowercase = u_hasBinaryProperty( - code, UCHAR_LOWERCASE); - bool icu_prop_uppercase = u_hasBinaryProperty( - code, UCHAR_UPPERCASE); - bool icu_prop_cased = u_hasBinaryProperty( - code, UCHAR_CASED); - bool icu_prop_case_ignorable = u_hasBinaryProperty( - code, UCHAR_CASE_IGNORABLE); - bool icu_prop_white_space = u_hasBinaryProperty( - code, UCHAR_WHITE_SPACE); - bool icu_prop_hex_digit = u_hasBinaryProperty( - code, UCHAR_HEX_DIGIT); - bool icu_prop_join_control = u_hasBinaryProperty( - code, UCHAR_JOIN_CONTROL); + bool icu_prop_alphabetic = u_hasBinaryProperty(code, UCHAR_ALPHABETIC); + bool icu_prop_lowercase = u_hasBinaryProperty(code, UCHAR_LOWERCASE); + bool icu_prop_uppercase = u_hasBinaryProperty(code, UCHAR_UPPERCASE); + bool icu_prop_cased = u_hasBinaryProperty(code, UCHAR_CASED); + bool icu_prop_case_ignorable = u_hasBinaryProperty(code, UCHAR_CASE_IGNORABLE); + bool icu_prop_white_space = u_hasBinaryProperty(code, UCHAR_WHITE_SPACE); + bool icu_prop_hex_digit = u_hasBinaryProperty(code, UCHAR_HEX_DIGIT); + bool icu_prop_join_control = u_hasBinaryProperty(code, UCHAR_JOIN_CONTROL); /* * Compare with ICU for character classes using: diff --git a/src/common/unicode/generate-norm_test_table.pl b/src/common/unicode/generate-norm_test_table.pl index 610fac57cf33f..1b401be940931 100644 --- a/src/common/unicode/generate-norm_test_table.pl +++ b/src/common/unicode/generate-norm_test_table.pl @@ -5,7 +5,7 @@ # # NormalizationTest.txt is part of the Unicode Character Database. # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -30,7 +30,7 @@ * norm_test_table.h * Test strings for Unicode normalization. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/common/unicode/norm_test_table.h diff --git a/src/common/unicode/generate-unicode_case_table.pl b/src/common/unicode/generate-unicode_case_table.pl index 508b05af8e9e1..5d9ddd628038c 100644 --- a/src/common/unicode/generate-unicode_case_table.pl +++ b/src/common/unicode/generate-unicode_case_table.pl @@ -3,10 +3,10 @@ # Generate Unicode character case mappings. Does not include tailoring # or locale-specific mappings. # -# Input: UnicodeData.txt +# Input: CaseFolding.txt SpecialCasing.txt UnicodeData.txt # Output: unicode_case_table.h # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -21,6 +21,10 @@ my $output_table_file = "$output_path/unicode_case_table.h"; +# The maximum number of codepoints that can result from case mapping +# of a single character. See Unicode section 5.18 "Case Mappings". +my $MAX_CASE_EXPANSION = 3; + my $FH; my %simple = (); @@ -45,31 +49,213 @@ $simple{$code} = { Simple_Lowercase => ($simple_lowercase || $code), Simple_Titlecase => ($simple_titlecase || $code), - Simple_Uppercase => ($simple_uppercase || $code) + Simple_Uppercase => ($simple_uppercase || $code), + Simple_Foldcase => $code, }; } } close $FH; -# Start writing out the output files -open my $OT, '>', $output_table_file - or die "Could not open output file $output_table_file: $!\n"; +# Map for special casing rules that aren't represented in the simple +# mapping. Language-sensitive mappings are not supported. +# +# See https://www.unicode.org/reports/tr44/#SpecialCasing.txt, or the +# SpecialCasing.txt file itself for details. -# determine size of array given that codepoints <= 0x80 are dense and -# the rest of the entries are sparse -my $num_simple = 0x80; -foreach my $code (sort { $a <=> $b } (keys %simple)) +# for now, only Final_Sigma is supported +my %condition_map = (Final_Sigma => 'PG_U_FINAL_SIGMA'); + +my %special = (); +open($FH, '<', "$output_path/SpecialCasing.txt") + or die "Could not open $output_path/SpecialCasing.txt: $!."; +while (my $line = <$FH>) +{ + # language-sensitive mappings not supported + last if $line =~ /\# Language-Sensitive Mappings/; + + # remove comments + $line =~ s/^(.*?)#.*$/$1/s; + + # ignore empty lines + next unless $line =~ /;/; + + my @elts = split /;/, $line; + my $code = hex($elts[0]); + + # Codepoint may map to multiple characters when converting + # case. Split each mapping on whitespace and extract the + # hexadecimal into an array of codepoints. + my @lower = map { hex $_ } (grep /^[0-9A-F]+$/, (split /\s+/, $elts[1])); + my @title = map { hex $_ } (grep /^[0-9A-F]+$/, (split /\s+/, $elts[2])); + my @upper = map { hex $_ } (grep /^[0-9A-F]+$/, (split /\s+/, $elts[3])); + my @fold = (); + my @conditions = map { + # supporting negated conditions may require storing a + # mask of relevant conditions for a given rule to differentiate + # between lack of a condition and a negated condition + die "negated conditions not supported" if /^Not_/; + $condition_map{$_} || die "unrecognized condition: $_" + } (grep /\w+/, (split /\s+/, $elts[4])); + + my $cond_str = (join '|', @conditions) || '0'; + + # if empty, create a self-mapping + push @lower, $code if (scalar @lower == 0); + push @title, $code if (scalar @title == 0); + push @upper, $code if (scalar @upper == 0); + push @fold, $code; + + # none should map to more than 3 codepoints + die "lowercase expansion for 0x$elts[0] exceeds maximum: '$elts[1]'" + if (scalar @lower) > $MAX_CASE_EXPANSION; + die "titlecase expansion for 0x$elts[0] exceeds maximum: '$elts[2]'" + if (scalar @title) > $MAX_CASE_EXPANSION; + die "uppercase expansion for 0x$elts[0] exceeds maximum: '$elts[3]'" + if (scalar @upper) > $MAX_CASE_EXPANSION; + + # pad arrays to a fixed length of 3 + while (scalar @upper < $MAX_CASE_EXPANSION) { push @upper, 0x000000 } + while (scalar @lower < $MAX_CASE_EXPANSION) { push @lower, 0x000000 } + while (scalar @title < $MAX_CASE_EXPANSION) { push @title, 0x000000 } + while (scalar @fold < $MAX_CASE_EXPANSION) { push @fold, 0x000000 } + + # Characters with special mappings may not have simple mappings; + # ensure that an entry exists. + $simple{$code} ||= { + Simple_Lowercase => $code, + Simple_Titlecase => $code, + Simple_Uppercase => $code, + Simple_Foldcase => $code + }; + + # Multiple special case rules for a single codepoint could be + # supported by making several entries for each codepoint, and have + # the simple mapping point to the first entry. The caller could + # scan forward looking for an entry that matches the conditions, + # or fall back to the normal behavior. + die "multiple special case mappings not supported" + if defined $special{$code}; + + $special{$code} = { + Lowercase => \@lower, + Titlecase => \@title, + Uppercase => \@upper, + Foldcase => \@fold, + Conditions => $cond_str + }; +} +close $FH; + +open($FH, '<', "$output_path/CaseFolding.txt") + or die "Could not open $output_path/CaseFolding.txt: $!."; +while (my $line = <$FH>) +{ + # remove comments + $line =~ s/^(.*?)#.*$/$1/s; + + # ignore empty lines + next unless $line =~ /;/; + + my @elts = split(';', $line); + my $code = hex($elts[0]); + my $status = $elts[1] =~ s/^\s+|\s+$//rg; + + # Codepoint may map to multiple characters when folding. Split + # each mapping on whitespace and extract the hexadecimal into an + # array of codepoints. + my @fold = map { hex $_ } (grep /[0-9A-F]+/, (split /\s+/, $elts[2])); + + die "codepoint $code out of range" if $code > 0x10FFFF; + + # status 'T' unsupported; skip + next if $status eq 'T'; + + # encountered unrecognized status type + die "unsupported status type '$status'" + if $status ne 'S' && $status ne 'C' && $status ne 'F'; + + # initialize simple case mappings if they don't exist + $simple{$code} ||= { + Simple_Lowercase => $code, + Simple_Titlecase => $code, + Simple_Uppercase => $code, + Simple_Foldcase => $code + }; + + if ($status eq 'S' || $status eq 'C') + { + die + "Simple case folding for $code has multiple codepoints: '$line' '$elts[2]'" + if scalar @fold != 1; + my $simple_foldcase = $fold[0]; + + die "Simple_Foldcase $code out of range" + if $simple_foldcase > 0x10FFFF; + + $simple{$code}{Simple_Foldcase} = $simple_foldcase; + } + + if ($status eq 'F' || ($status eq 'C' && defined $special{$code})) + { + while (scalar @fold < $MAX_CASE_EXPANSION) { push @fold, 0x000000 } + + #initialize special case mappings if they don't exist + if (!defined $special{$code}) + { + my @lower = ($simple{$code}{Simple_Lowercase}); + my @title = ($simple{$code}{Simple_Titlecase}); + my @upper = ($simple{$code}{Simple_Uppercase}); + while (scalar @lower < $MAX_CASE_EXPANSION) + { + push @lower, 0x000000; + } + while (scalar @title < $MAX_CASE_EXPANSION) + { + push @title, 0x000000; + } + while (scalar @upper < $MAX_CASE_EXPANSION) + { + push @upper, 0x000000; + } + $special{$code} = { + Lowercase => \@lower, + Titlecase => \@title, + Uppercase => \@upper, + Conditions => '0' + }; + } + + $special{$code}{Foldcase} = \@fold; + } +} +close $FH; + +# assign sequential array indexes to the special mappings +# 0 is reserved for NULL +my $special_idx = 1; +foreach my $code (sort { $a <=> $b } (keys %special)) { - $num_simple++ unless $code < 0x80; + $special{$code}{Index} = $special_idx++; } +# determine size of array +my $num_special = scalar(keys %special) + 1; + +die + "special case map contains $num_special entries which cannot be represented in uint8" + if ($num_special > 256); + +# Start writing out the output files +open my $OT, '>', $output_table_file + or die "Could not open output file $output_table_file: $!\n"; + print $OT <<"EOS"; /*------------------------------------------------------------------------- * * unicode_case_table.h * Case mapping and information table. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_case_table.h @@ -86,49 +272,396 @@ #include "common/unicode_case.h" #include "mb/pg_wchar.h" +/* + * The maximum number of codepoints that can result from case mapping + * of a single character. See Unicode section 5.18 "Case Mappings". + */ +#define MAX_CASE_EXPANSION 3 + +/* + * Case mapping condition flags. For now, only Final_Sigma is supported. + * + * See Unicode Context Specification for Casing. + */ +#define PG_U_FINAL_SIGMA (1 << 0) + typedef enum { CaseLower = 0, CaseTitle = 1, CaseUpper = 2, + CaseFold = 3, NCaseKind -} CaseKind; +} CaseKind; typedef struct { - pg_wchar codepoint; /* Unicode codepoint */ - pg_wchar simplemap[NCaseKind]; -} pg_case_map; + int16 conditions; + pg_wchar map[NCaseKind][MAX_CASE_EXPANSION]; +} pg_special_case; /* - * Case mapping table. Dense for codepoints < 0x80 (enabling fast lookup), - * sparse for higher codepoints (requiring scan or binary search). + * Special case mappings that aren't representable in the simple map. + * Entries are referenced from simple_case_map. */ -static const pg_case_map case_map[$num_simple] = +static const pg_special_case special_case[$num_special] = { + {0, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}, EOS -printf $OT "\t/* begin dense entries for codepoints < 0x80 */\n"; +foreach my $code (sort { $a <=> $b } (keys %special)) +{ + die if scalar @{ $special{$code}{Lowercase} } != $MAX_CASE_EXPANSION; + die if scalar @{ $special{$code}{Titlecase} } != $MAX_CASE_EXPANSION; + die if scalar @{ $special{$code}{Uppercase} } != $MAX_CASE_EXPANSION; + die if scalar @{ $special{$code}{Foldcase} } != $MAX_CASE_EXPANSION; + my $lower = join ", ", + (map { sprintf "0x%06x", $_ } @{ $special{$code}{Lowercase} }); + my $title = join ", ", + (map { sprintf "0x%06x", $_ } @{ $special{$code}{Titlecase} }); + my $upper = join ", ", + (map { sprintf "0x%06x", $_ } @{ $special{$code}{Uppercase} }); + my $fold = join ", ", + (map { sprintf "0x%06x", $_ } @{ $special{$code}{Foldcase} }); + printf $OT "\t{%s, ", $special{$code}{Conditions}; + printf $OT + "{[CaseLower] = {%s},[CaseTitle] = {%s},[CaseUpper] = {%s},[CaseFold] = {%s}}},\n", + $lower, $title, $upper, $fold; +} +print $OT "};\n"; + +# Separate maps for each case form, starting with the reserved entry +# at index 0. The first element is the result code point, and the +# second element is the input code point (which is not ultimately +# stored in the C array, it's just there as a comment). +my %map = ( + lower => [ [ 0, -1 ] ], + title => [ [ 0, -1 ] ], + upper => [ [ 0, -1 ] ], + fold => [ [ 0, -1 ] ], + special => [ [ 0, -1 ] ]); + + +# Current index into the map arrays above. +my $index = 1; + +# Sets of case forms/variations. Simple case pairs have the same set +# of case forms, e.g. the letters 'a' and 'A' both lowercase to 'a'; +# both uppercase to 'A', etc. By tracking unique sets using a hash, we +# cut the size needed for the maps in half (some characters are +# exceptions, so it's not exactly half). The key is an array of all +# case forms, and the value is an index into the maps. +my %case_forms; + +# Perl doesn't allow arrays as hash keys, so we need to transform the +# set of case forms to a scalar. +sub get_hash_key +{ + return join ",", @_; +} + +# Create map entries for all codepoints < 0x80, so that the caller can +# have a fast-path lookup without needing to go through the main +# table. for (my $code = 0; $code < 0x80; $code++) { my $lc = ($simple{$code}{Simple_Lowercase} || $code); my $tc = ($simple{$code}{Simple_Titlecase} || $code); my $uc = ($simple{$code}{Simple_Uppercase} || $code); - printf $OT - "\t{0x%06x, {[CaseLower] = 0x%06x,[CaseTitle] = 0x%06x,[CaseUpper] = 0x%06x}},\n", - $code, $lc, $tc, $uc; + my $fc = ($simple{$code}{Simple_Foldcase} || $code); + + die "unexpected special case for code $code" + if defined $special{$code}; + + push @{ $map{lower} }, [ $lc, $code ]; + push @{ $map{title} }, [ $tc, $code ]; + push @{ $map{upper} }, [ $uc, $code ]; + push @{ $map{fold} }, [ $fc, $code ]; + push @{ $map{special} }, [ 0, $code ]; + + my $key = get_hash_key($lc, $tc, $uc, $fc, 0); + + $simple{$code}{Index} = $index; + $case_forms{$key} = $index++; } -printf $OT "\n"; -printf $OT "\t/* begin sparse entries for codepoints >= 0x80 */\n"; +# Create map entries for all characters >= 0x80 that have case +# mappings (any character with a special case mapping also has an +# entry in %simple). foreach my $code (sort { $a <=> $b } (keys %simple)) { next unless $code >= 0x80; # already output above - my $map = $simple{$code}; - printf $OT - "\t{0x%06x, {[CaseLower] = 0x%06x,[CaseTitle] = 0x%06x,[CaseUpper] = 0x%06x}},\n", - $code, $map->{Simple_Lowercase}, $map->{Simple_Titlecase}, - $map->{Simple_Uppercase}; + my $entry = $simple{$code}; + my $special_case = 0; + if (exists $special{$code}) + { + $special_case = $special{$code}{Index}; + } + + my $key = get_hash_key( + $entry->{Simple_Lowercase}, $entry->{Simple_Titlecase}, + $entry->{Simple_Uppercase}, $entry->{Simple_Foldcase}, + $special_case); + + unless (exists $case_forms{$key}) + { + $case_forms{$key} = $index++; + + push @{ $map{lower} }, [ $entry->{Simple_Lowercase}, $code ]; + push @{ $map{title} }, [ $entry->{Simple_Titlecase}, $code ]; + push @{ $map{upper} }, [ $entry->{Simple_Uppercase}, $code ]; + push @{ $map{fold} }, [ $entry->{Simple_Foldcase}, $code ]; + push @{ $map{special} }, [ $special_case, $code ]; + } + + $simple{$code}{Index} = $case_forms{$key}; +} + +die + "mapping tables contains $index entries which cannot be represented in uint16" + if ($index > 65536); + +foreach my $kind ('lower', 'title', 'upper', 'fold') +{ + print $OT <<"EOS"; + +/* + * The entry case_map_${kind}[case_index(codepoint)] is the mapping for the + * given codepoint. + */ +static const pg_wchar case_map_$kind\[$index\] = +{ +EOS + + foreach my $entry (@{ $map{$kind} }) + { + my $comment = + @$entry[1] == -1 ? "reserved" : sprintf("U+%06x", @$entry[1]); + print $OT + sprintf("\t0x%06x,\t\t\t\t\t/* %s */\n", @$entry[0], $comment); + } + + print $OT "\n};\n"; +} + +print $OT <<"EOS"; + +/* + * The entry case_map_special[case_index(codepoint)] is the index in + * special_case for that codepoint, or 0 if no special case mapping exists. + */ +static const uint8 case_map_special\[$index\] = +{ +EOS + +foreach my $entry (@{ $map{special} }) +{ + my $s = sprintf("%d,", @$entry[0]); + $s .= "\t" if length($s) < 4; + my $comment = + @$entry[1] == -1 ? "reserved" : sprintf("U+%06x", @$entry[1]); + print $OT sprintf("\t%s\t\t\t\t\t\t/* %s */\n", $s, $comment); +} + +print $OT "\n};\n"; + +my @codepoints = keys %simple; +my $range = make_ranges(\@codepoints, 500); +my @case_map_lines = range_tables($range); +my $case_map_length = scalar @case_map_lines; +my $case_map_table = join "\n", @case_map_lines; + +print $OT <<"EOS"; + +/* + * Used by case_index() to map a codepoint to an index that can be used in any + * of the following arrays: case_map_lower, case_map_title, case_map_upper, + * case_map_fold. + */ +static const uint16 case_map[$case_map_length] = +{ +$case_map_table +}; + + +EOS + +# First range is the fast path. It must start at codepoint zero, and +# the end is the fastpath limit. Track the limit here and then +# remove it before generating the other branches. +die "first range must start at 0" unless ${ @$range[0] }{Start} == 0; +my $fastpath_limit = sprintf("0x%04X", ${ @$range[0] }{End}); +shift @$range; + +print $OT <<"EOS"; +/* + * case_index() + * + * Given a code point, compute the index in the case_map at which we can find + * the offset into the mapping tables. + */ +static inline uint16 +case_index(pg_wchar cp) +{ + /* Fast path for codepoints < $fastpath_limit */ + if (cp < $fastpath_limit) + { + return case_map[cp]; + } + +EOS + +print $OT join("\n", @{ branch($range, 0, $#$range, 1) }); + +print $OT <<"EOS"; + + + return 0; +} +EOS + +close $OT; + +# The function generates C code with a series of nested if-else conditions +# to search for the matching interval. +sub branch +{ + my ($range, $from, $to, $indent) = @_; + my ($idx, $space, $entry, $table, @result); + + $idx = ($from + int(($to - $from) / 2)); + return \@result unless exists $range->[$idx]; + + $space = "\t" x $indent; + + $entry = $range->[$idx]; + + # IF state + if ($idx == $from) + { + if ($idx == 0) + { + push @result, + sprintf("%sif (cp >= 0x%04X && cp < 0x%04X)\n%s{", + $space, $entry->{Start}, $entry->{End}, $space); + } + else + { + push @result, + sprintf("%sif (cp < 0x%04X)\n%s{", + $space, $entry->{End}, $space); + } + + push @result, + sprintf("%s\treturn case_map[cp - 0x%04X + %d];", + $space, $entry->{Start}, $entry->{Offset}); + } + else + { + push @result, + sprintf("%sif (cp < 0x%04X)\n%s{", $space, $entry->{End}, $space); + push @result, @{ branch($range, $from, $idx - 1, $indent + 1) }; + } + + push @result, $space . "}"; + + # return now if it's the last range + return \@result if $idx == (scalar @$range) - 1; + + # ELSE looks ahead to the next range to avoid adding an + # unnecessary level of branching. + $entry = @$range[ $idx + 1 ]; + + # ELSE state + push @result, + sprintf("%selse if (cp >= 0x%04X)\n%s{", + $space, $entry->{Start}, $space); + + if ($idx == $to) + { + push @result, + sprintf("%s\treturn case_map\[cp - 0x%04X + %d];", + $space, $entry->{Start}, $entry->{Offset}); + } + else + { + push @result, @{ branch($range, $idx + 1, $to, $indent + 1) }; + } + + push @result, $space . "}"; + + return \@result; +} + +# Group numbers into ranges where the difference between neighboring +# elements does not exceed $limit. If the difference is greater, a new +# range is created. This is used to break the sequence into intervals +# where the gaps between numbers are greater than limit. +# +# For example, if there are numbers 1, 2, 3, 5, 6 and limit = 1, then +# there is a difference of 2 between 3 and 5, which is greater than 1, +# so there will be ranges 1-3 and 5-6. +sub make_ranges +{ + my ($nums, $limit) = @_; + my ($prev, $start, $total, @sorted, @range); + + @sorted = sort { $a <=> $b } @$nums; + + die "expecting at least 2 codepoints" if (scalar @sorted < 2); + + $start = shift @sorted; + + die "expecting first codepoint to start at 0" unless $start == 0; + + $prev = $start; + $total = 0; + + # append final 'undef' to signal final iteration + push @sorted, undef; + + foreach my $curr (@sorted) + { + # if last iteration always append the range + if (!defined($curr) || ($curr - $prev > $limit)) + { + push @range, + { + Start => $start, + End => $prev + 1, + Offset => $total + }; + $total += $prev + 1 - $start; + $start = $curr; + } + + $prev = $curr; + } + + return \@range; +} + +# The function combines all ranges into the case_map table. Ranges may +# include codepoints without a case mapping at all, in which case the +# entry in case_map should be zero. +sub range_tables +{ + my ($range) = @_; + my (@lines, @result); + + foreach my $entry (@$range) + { + my $start = $entry->{Start}; + my $end = $entry->{End} - 1; + + foreach my $cp ($start .. $end) + { + my $idx = sprintf("%d,", ($simple{$cp}{Index} || 0)); + $idx .= "\t" if length($idx) < 4; + push @lines, sprintf("\t%s\t\t\t\t\t\t/* U+%06X */", $idx, $cp); + } + } + + return @lines; } -print $OT "};\n"; diff --git a/src/common/unicode/generate-unicode_category_table.pl b/src/common/unicode/generate-unicode_category_table.pl index 12914c0243399..abab5cd96968c 100644 --- a/src/common/unicode/generate-unicode_category_table.pl +++ b/src/common/unicode/generate-unicode_category_table.pl @@ -6,7 +6,7 @@ # Input: UnicodeData.txt # Output: unicode_category_table.h # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -349,7 +349,7 @@ * unicode_category_table.h * Category table for Unicode character classification. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_category_table.h @@ -369,19 +369,19 @@ uint32 first; /* Unicode codepoint */ uint32 last; /* Unicode codepoint */ uint8 category; /* General Category */ -} pg_category_range; +} pg_category_range; typedef struct { uint32 first; /* Unicode codepoint */ uint32 last; /* Unicode codepoint */ -} pg_unicode_range; +} pg_unicode_range; typedef struct { uint8 category; uint8 properties; -} pg_unicode_properties; +} pg_unicode_properties; /* * The properties currently used, in no particular order. Fits in a uint8, but diff --git a/src/common/unicode/generate-unicode_east_asian_fw_table.pl b/src/common/unicode/generate-unicode_east_asian_fw_table.pl index 05fb0cfa8002f..f35a645f78557 100644 --- a/src/common/unicode/generate-unicode_east_asian_fw_table.pl +++ b/src/common/unicode/generate-unicode_east_asian_fw_table.pl @@ -4,7 +4,7 @@ # and East Asian Fullwidth (F) characters, using Unicode data files as input. # Pass EastAsianWidth.txt as argument. The output is on stdout. # -# Copyright (c) 2019-2024, PostgreSQL Global Development Group +# Copyright (c) 2019-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/common/unicode/generate-unicode_nonspacing_table.pl b/src/common/unicode/generate-unicode_nonspacing_table.pl index 04adbaed71fd2..790cde33736ec 100644 --- a/src/common/unicode/generate-unicode_nonspacing_table.pl +++ b/src/common/unicode/generate-unicode_nonspacing_table.pl @@ -4,7 +4,7 @@ # characters, using Unicode data files as input. Pass UnicodeData.txt # as argument. The output is on stdout. # -# Copyright (c) 2019-2024, PostgreSQL Global Development Group +# Copyright (c) 2019-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/common/unicode/generate-unicode_norm_table.pl b/src/common/unicode/generate-unicode_norm_table.pl index 456c64aa39488..5e4330e458f73 100644 --- a/src/common/unicode/generate-unicode_norm_table.pl +++ b/src/common/unicode/generate-unicode_norm_table.pl @@ -6,7 +6,7 @@ # Input: UnicodeData.txt and CompositionExclusions.txt # Output: unicode_norm_table.h and unicode_norm_hashfunc.h # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -88,7 +88,7 @@ * unicode_norm_table.h * Composition table used for Unicode normalization * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_norm_table.h @@ -131,7 +131,7 @@ * unicode_norm_hashfunc.h * Perfect hash functions used for Unicode normalization * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_norm_hashfunc.h diff --git a/src/common/unicode/generate-unicode_normprops_table.pl b/src/common/unicode/generate-unicode_normprops_table.pl index acc4be7559d65..7064abfba2581 100644 --- a/src/common/unicode/generate-unicode_normprops_table.pl +++ b/src/common/unicode/generate-unicode_normprops_table.pl @@ -4,7 +4,7 @@ # (see UAX #15). Pass DerivedNormalizationProps.txt as argument. The # output is on stdout. # -# Copyright (c) 2020-2024, PostgreSQL Global Development Group +# Copyright (c) 2020-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/common/unicode/generate-unicode_version.pl b/src/common/unicode/generate-unicode_version.pl index d98ab0d9561a8..6c3b7243c6cbe 100644 --- a/src/common/unicode/generate-unicode_version.pl +++ b/src/common/unicode/generate-unicode_version.pl @@ -4,7 +4,7 @@ # # Output: unicode_version.h # -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -35,7 +35,7 @@ * unicode_version.h * Unicode version used by Postgres. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_version.h diff --git a/src/common/unicode/meson.build b/src/common/unicode/meson.build index b9a4181c32024..c6a4715ccc553 100644 --- a/src/common/unicode/meson.build +++ b/src/common/unicode/meson.build @@ -1,6 +1,6 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group -UNICODE_VERSION = '15.1.0' +UNICODE_VERSION = '16.0.0' unicode_data = {} unicode_baseurl = 'https://www.unicode.org/Public/@0@/ucd/@1@' @@ -11,7 +11,7 @@ endif # These files are part of the Unicode Character Database. Download them on # demand. -foreach f : ['CompositionExclusions.txt', 'DerivedCoreProperties.txt', 'DerivedNormalizationProps.txt', 'EastAsianWidth.txt', 'NormalizationTest.txt', 'PropList.txt', 'UnicodeData.txt'] +foreach f : ['CompositionExclusions.txt', 'CaseFolding.txt', 'DerivedCoreProperties.txt', 'DerivedNormalizationProps.txt', 'EastAsianWidth.txt', 'NormalizationTest.txt', 'PropList.txt', 'SpecialCasing.txt', 'UnicodeData.txt'] url = unicode_baseurl.format(UNICODE_VERSION, f) target = custom_target(f, output: f, @@ -26,7 +26,7 @@ update_unicode_targets = [] update_unicode_targets += \ custom_target('unicode_case_table.h', - input: [unicode_data['UnicodeData.txt']], + input: [unicode_data['CaseFolding.txt'], unicode_data['SpecialCasing.txt'], unicode_data['UnicodeData.txt']], output: ['unicode_case_table.h'], command: [ perl, files('generate-unicode_case_table.pl'), @@ -104,7 +104,7 @@ inc = include_directories('.') case_test = executable('case_test', ['case_test.c'], - dependencies: [frontend_port_code, icu], + dependencies: [frontend_port_code, icu, libintl], include_directories: inc, link_with: [common_static, pgport_static], build_by_default: false, @@ -115,7 +115,7 @@ case_test = executable('case_test', category_test = executable('category_test', ['category_test.c'], - dependencies: [frontend_port_code, icu], + dependencies: [frontend_port_code, icu, libintl], include_directories: inc, link_with: [common_static, pgport_static], build_by_default: false, @@ -126,7 +126,7 @@ category_test = executable('category_test', norm_test = executable('norm_test', ['norm_test.c', norm_test_table], - dependencies: [frontend_port_code], + dependencies: [frontend_port_code, libintl], include_directories: inc, link_with: [common_static, pgport_static], build_by_default: false, diff --git a/src/common/unicode/norm_test.c b/src/common/unicode/norm_test.c index 1b2c709ae6727..25bc59463f24d 100644 --- a/src/common/unicode/norm_test.c +++ b/src/common/unicode/norm_test.c @@ -2,7 +2,7 @@ * norm_test.c * Program to test Unicode normalization functions. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode/norm_test.c diff --git a/src/common/unicode_case.c b/src/common/unicode_case.c index 291e256e639af..073faf6a0d58b 100644 --- a/src/common/unicode_case.c +++ b/src/common/unicode_case.c @@ -2,7 +2,7 @@ * unicode_case.c * Unicode case mapping and case conversion. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode_case.c @@ -20,33 +20,62 @@ #include "common/unicode_category.h" #include "mb/pg_wchar.h" -static const pg_case_map *find_case_map(pg_wchar ucs); +enum CaseMapResult +{ + CASEMAP_SELF, + CASEMAP_SIMPLE, + CASEMAP_SPECIAL, +}; + +/* + * Map for each case kind. + */ +static const pg_wchar *const casekind_map[NCaseKind] = +{ + [CaseLower] = case_map_lower, + [CaseTitle] = case_map_title, + [CaseUpper] = case_map_upper, + [CaseFold] = case_map_fold, +}; + +static pg_wchar find_case_map(pg_wchar ucs, const pg_wchar *map); static size_t convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, - CaseKind str_casekind, WordBoundaryNext wbnext, + CaseKind str_casekind, bool full, WordBoundaryNext wbnext, void *wbstate); +static enum CaseMapResult casemap(pg_wchar u1, CaseKind casekind, bool full, + const char *src, size_t srclen, size_t srcoff, + pg_wchar *simple, const pg_wchar **special); pg_wchar unicode_lowercase_simple(pg_wchar code) { - const pg_case_map *map = find_case_map(code); + pg_wchar cp = find_case_map(code, case_map_lower); - return map ? map->simplemap[CaseLower] : code; + return cp != 0 ? cp : code; } pg_wchar unicode_titlecase_simple(pg_wchar code) { - const pg_case_map *map = find_case_map(code); + pg_wchar cp = find_case_map(code, case_map_title); - return map ? map->simplemap[CaseTitle] : code; + return cp != 0 ? cp : code; } pg_wchar unicode_uppercase_simple(pg_wchar code) { - const pg_case_map *map = find_case_map(code); + pg_wchar cp = find_case_map(code, case_map_upper); + + return cp != 0 ? cp : code; +} + +pg_wchar +unicode_casefold_simple(pg_wchar code) +{ + pg_wchar cp = find_case_map(code, case_map_fold); - return map ? map->simplemap[CaseUpper] : code; + return cp != 0 ? cp : code; } /* @@ -64,11 +93,16 @@ unicode_uppercase_simple(pg_wchar code) * * If dstsize is zero, dst may be NULL. This is useful for calculating the * required buffer size before allocating. + * + * If full is true, use special case mappings if available and if the + * conditions are satisfied. */ size_t -unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen) +unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen, + bool full) { - return convert_case(dst, dstsize, src, srclen, CaseLower, NULL, NULL); + return convert_case(dst, dstsize, src, srclen, CaseLower, full, NULL, + NULL); } /* @@ -87,6 +121,10 @@ unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen) * If dstsize is zero, dst may be NULL. This is useful for calculating the * required buffer size before allocating. * + * If full is true, use special case mappings if available and if the + * conditions are satisfied. Otherwise, use only simple mappings and use + * uppercase instead of titlecase. + * * Titlecasing requires knowledge about word boundaries, which is provided by * the callback wbnext. A word boundary is the offset of the start of a word * or the offset of the character immediately following a word. @@ -98,9 +136,9 @@ unicode_strlower(char *dst, size_t dstsize, const char *src, ssize_t srclen) */ size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, - WordBoundaryNext wbnext, void *wbstate) + bool full, WordBoundaryNext wbnext, void *wbstate) { - return convert_case(dst, dstsize, src, srclen, CaseTitle, wbnext, + return convert_case(dst, dstsize, src, srclen, CaseTitle, full, wbnext, wbstate); } @@ -119,23 +157,62 @@ unicode_strtitle(char *dst, size_t dstsize, const char *src, ssize_t srclen, * * If dstsize is zero, dst may be NULL. This is useful for calculating the * required buffer size before allocating. + * + * If full is true, use special case mappings if available and if the + * conditions are satisfied. + */ +size_t +unicode_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen, + bool full) +{ + return convert_case(dst, dstsize, src, srclen, CaseUpper, full, NULL, + NULL); +} + +/* + * unicode_strfold() + * + * Case fold src, and return the result length (not including terminating + * NUL). + * + * String src must be encoded in UTF-8. If srclen < 0, src must be + * NUL-terminated. + * + * Result string is stored in dst, truncating if larger than dstsize. If + * dstsize is greater than the result length, dst will be NUL-terminated; + * otherwise not. + * + * If dstsize is zero, dst may be NULL. This is useful for calculating the + * required buffer size before allocating. */ size_t -unicode_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen) +unicode_strfold(char *dst, size_t dstsize, const char *src, ssize_t srclen, + bool full) { - return convert_case(dst, dstsize, src, srclen, CaseUpper, NULL, NULL); + return convert_case(dst, dstsize, src, srclen, CaseFold, full, NULL, + NULL); } /* + * Implement Unicode Default Case Conversion algorithm. + * * If str_casekind is CaseLower or CaseUpper, map each character in the string * for which a mapping is available. * * If str_casekind is CaseTitle, maps characters found on a word boundary to - * uppercase and other characters to lowercase. + * titlecase (or uppercase if full is false) and other characters to + * lowercase. NB: does not currently implement the Unicode behavior in which + * the word boundary is adjusted to the next Cased character. That behavior + * could be implemented as an option, but it doesn't match the default + * behavior of ICU, nor does it match the documented behavior of INITCAP(). + * + * If full is true, use special mappings for relevant characters, which can + * map a single codepoint to multiple codepoints, or depend on conditions. */ static size_t convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, - CaseKind str_casekind, WordBoundaryNext wbnext, void *wbstate) + CaseKind str_casekind, bool full, WordBoundaryNext wbnext, + void *wbstate) { /* character CaseKind varies while titlecasing */ CaseKind chr_casekind = str_casekind; @@ -156,37 +233,62 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, { pg_wchar u1 = utf8_to_unicode((unsigned char *) src + srcoff); int u1len = unicode_utf8len(u1); - const pg_case_map *casemap = find_case_map(u1); + pg_wchar simple = 0; + const pg_wchar *special = NULL; + enum CaseMapResult casemap_result; if (str_casekind == CaseTitle) { if (srcoff == boundary) { - chr_casekind = CaseUpper; + chr_casekind = full ? CaseTitle : CaseUpper; boundary = wbnext(wbstate); } else chr_casekind = CaseLower; } - /* perform mapping, update result_len, and write to dst */ - if (casemap) + casemap_result = casemap(u1, chr_casekind, full, src, srclen, srcoff, + &simple, &special); + + switch (casemap_result) { - pg_wchar u2 = casemap->simplemap[chr_casekind]; - pg_wchar u2len = unicode_utf8len(u2); + case CASEMAP_SELF: + /* no mapping; copy bytes from src */ + Assert(simple == 0); + Assert(special == NULL); + if (result_len + u1len <= dstsize) + memcpy(dst + result_len, src + srcoff, u1len); - if (result_len + u2len <= dstsize) - unicode_to_utf8(u2, (unsigned char *) dst + result_len); + result_len += u1len; + break; + case CASEMAP_SIMPLE: + { + /* replace with single character */ + pg_wchar u2 = simple; + pg_wchar u2len = unicode_utf8len(u2); - result_len += u2len; - } - else - { - /* no mapping; copy bytes from src */ - if (result_len + u1len <= dstsize) - memcpy(dst + result_len, src + srcoff, u1len); + Assert(special == NULL); + if (result_len + u2len <= dstsize) + unicode_to_utf8(u2, (unsigned char *) dst + result_len); + + result_len += u2len; + } + break; + case CASEMAP_SPECIAL: + /* replace with up to MAX_CASE_EXPANSION characters */ + Assert(simple == 0); + for (int i = 0; i < MAX_CASE_EXPANSION && special[i]; i++) + { + pg_wchar u2 = special[i]; + size_t u2len = unicode_utf8len(u2); - result_len += u1len; + if (result_len + u2len <= dstsize) + unicode_to_utf8(u2, (unsigned char *) dst + result_len); + + result_len += u2len; + } + break; } srcoff += u1len; @@ -198,37 +300,146 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen, return result_len; } -/* find entry in simple case map, if any */ -static const pg_case_map * -find_case_map(pg_wchar ucs) +/* + * Check that the condition matches Final_Sigma, described in Unicode Table + * 3-17. The character at the given offset must be directly preceded by a + * Cased character, and must not be directly followed by a Cased character. + * + * Case_Ignorable characters are ignored. NB: some characters may be both + * Cased and Case_Ignorable, in which case they are ignored. + */ +static bool +check_final_sigma(const unsigned char *str, size_t len, size_t offset) { - int min; - int mid; - int max; + /* the start of the string is not preceded by a Cased character */ + if (offset == 0) + return false; - /* all chars <= 0x80 are stored in array for fast lookup */ - Assert(lengthof(case_map) >= 0x80); - if (ucs < 0x80) + /* iterate backwards, looking for Cased character */ + for (int i = offset - 1; i >= 0; i--) { - const pg_case_map *map = &case_map[ucs]; + if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0) + { + pg_wchar curr = utf8_to_unicode(str + i); + + if (pg_u_prop_case_ignorable(curr)) + continue; + else if (pg_u_prop_cased(curr)) + break; + else + return false; + } + else if ((str[i] & 0xC0) == 0x80) + continue; - Assert(map->codepoint == ucs); - return map; + Assert(false); /* invalid UTF-8 */ } - /* otherwise, binary search */ - min = 0x80; - max = lengthof(case_map) - 1; - while (max >= min) + /* end of string is not followed by a Cased character */ + if (offset == len) + return true; + + /* iterate forwards, looking for Cased character */ + for (int i = offset + 1; i < len && str[i] != '\0'; i++) { - mid = (min + max) / 2; - if (ucs > case_map[mid].codepoint) - min = mid + 1; - else if (ucs < case_map[mid].codepoint) - max = mid - 1; - else - return &case_map[mid]; + if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0) + { + pg_wchar curr = utf8_to_unicode(str + i); + + if (pg_u_prop_case_ignorable(curr)) + continue; + else if (pg_u_prop_cased(curr)) + return false; + else + break; + } + else if ((str[i] & 0xC0) == 0x80) + continue; + + Assert(false); /* invalid UTF-8 */ } - return NULL; + return true; +} + +/* + * Unicode allows for special casing to be applied only under certain + * circumstances. The only currently-supported condition is Final_Sigma. + */ +static bool +check_special_conditions(int conditions, const char *str, size_t len, + size_t offset) +{ + if (conditions == 0) + return true; + else if (conditions == PG_U_FINAL_SIGMA) + return check_final_sigma((unsigned char *) str, len, offset); + + /* no other conditions supported */ + Assert(false); + return false; +} + +/* + * Map the given character to the requested case. + * + * If full is true, and a special case mapping is found and the conditions are + * met, 'special' is set to the mapping result (which is an array of up to + * MAX_CASE_EXPANSION characters) and CASEMAP_SPECIAL is returned. + * + * Otherwise, search for a simple mapping, and if found, set 'simple' to the + * result and return CASEMAP_SIMPLE. + * + * If no mapping is found, return CASEMAP_SELF, and the caller should copy the + * character without modification. + */ +static enum CaseMapResult +casemap(pg_wchar u1, CaseKind casekind, bool full, + const char *src, size_t srclen, size_t srcoff, + pg_wchar *simple, const pg_wchar **special) +{ + uint16 idx; + + /* Fast path for codepoints < 0x80 */ + if (u1 < 0x80) + { + /* + * The first elements in all tables are reserved as 0 (as NULL). The + * data starts at index 1, not 0. + */ + *simple = casekind_map[casekind][u1 + 1]; + + return CASEMAP_SIMPLE; + } + + idx = case_index(u1); + + if (idx == 0) + return CASEMAP_SELF; + + if (full && case_map_special[idx] && + check_special_conditions(special_case[case_map_special[idx]].conditions, + src, srclen, srcoff)) + { + *special = special_case[case_map_special[idx]].map[casekind]; + return CASEMAP_SPECIAL; + } + + *simple = casekind_map[casekind][idx]; + + return CASEMAP_SIMPLE; +} + +/* + * Find entry in simple case map. + * If the entry does not exist, 0 will be returned. + */ +static pg_wchar +find_case_map(pg_wchar ucs, const pg_wchar *map) +{ + /* Fast path for codepoints < 0x80 */ + if (ucs < 0x80) + /* The first elements in all tables are reserved as 0 (as NULL). */ + return map[ucs + 1]; + return map[case_index(ucs)]; } diff --git a/src/common/unicode_category.c b/src/common/unicode_category.c index a615a9056787c..4136c4d4f926f 100644 --- a/src/common/unicode_category.c +++ b/src/common/unicode_category.c @@ -4,7 +4,7 @@ * characters. Encoding must be UTF8, where we assume that the pg_wchar * representation is a code point. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode_category.c diff --git a/src/common/unicode_norm.c b/src/common/unicode_norm.c index ff8a03b84939f..6654b4cbc49cf 100644 --- a/src/common/unicode_norm.c +++ b/src/common/unicode_norm.c @@ -5,7 +5,7 @@ * This implements Unicode normalization, per the documentation at * https://www.unicode.org/reports/tr15/. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/unicode_norm.c diff --git a/src/common/username.c b/src/common/username.c index acaeb13d2e696..ae5f02d96b3f7 100644 --- a/src/common/username.c +++ b/src/common/username.c @@ -3,7 +3,7 @@ * username.c * get user name * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/common/wait_error.c b/src/common/wait_error.c index e79c61a66cfe0..1477887dee844 100644 --- a/src/common/wait_error.c +++ b/src/common/wait_error.c @@ -4,7 +4,7 @@ * Convert a wait/waitpid(2) result code to a human-readable string * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/common/wchar.c b/src/common/wchar.c index 76b7dfdfcb668..a4bc29921dedd 100644 --- a/src/common/wchar.c +++ b/src/common/wchar.c @@ -3,7 +3,7 @@ * wchar.c * Functions for working with multibyte characters in various encodings. * - * Portions Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1998-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/common/wchar.c @@ -12,10 +12,31 @@ */ #include "c.h" +#include + #include "mb/pg_wchar.h" #include "utils/ascii.h" +/* + * In today's multibyte encodings other than UTF8, this two-byte sequence + * ensures pg_encoding_mblen() == 2 && pg_encoding_verifymbstr() == 0. + * + * For historical reasons, several verifychar implementations opt to reject + * this pair specifically. Byte pair range constraints, in encoding + * originator documentation, always excluded this pair. No core conversion + * could translate it. However, longstanding verifychar implementations + * accepted any non-NUL byte. big5_to_euc_tw and big5_to_mic even translate + * pairs not valid per encoding originator documentation. To avoid tightening + * core or non-core conversions in a security patch, we sought this one pair. + * + * PQescapeString() historically used spaces for BYTE1; many other values + * could suffice for BYTE1. + */ +#define NONUTF8_INVALID_BYTE0 (0x8d) +#define NONUTF8_INVALID_BYTE1 (' ') + + /* * Operations on multi-byte encodings are driven by a table of helper * functions. @@ -1465,6 +1486,11 @@ pg_big5_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -1514,6 +1540,11 @@ pg_gbk_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -1563,6 +1594,11 @@ pg_uhc_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -2007,6 +2043,19 @@ pg_utf8_islegal(const unsigned char *source, int length) } +/* + * Fills the provided buffer with two bytes such that: + * pg_encoding_mblen(dst) == 2 && pg_encoding_verifymbstr(dst) == 0 + */ +void +pg_encoding_set_invalid(int encoding, char *dst) +{ + Assert(pg_encoding_max_length(encoding) > 1); + + dst[0] = (encoding == PG_UTF8 ? 0xc0 : NONUTF8_INVALID_BYTE0); + dst[1] = NONUTF8_INVALID_BYTE1; +} + /* *------------------------------------------------------------------- * encoding info table @@ -2060,10 +2109,27 @@ const pg_wchar_tbl pg_wchar_table[] = { /* * Returns the byte length of a multibyte character. * - * Caution: when dealing with text that is not certainly valid in the - * specified encoding, the result may exceed the actual remaining - * string length. Callers that are not prepared to deal with that - * should use pg_encoding_mblen_bounded() instead. + * Choose "mblen" functions based on the input string characteristics. + * pg_encoding_mblen() can be used when ANY of these conditions are met: + * + * - The input string is zero-terminated + * + * - The input string is known to be valid in the encoding (e.g., string + * converted from database encoding) + * + * - The encoding is not GB18030 (e.g., when only database encodings are + * passed to 'encoding' parameter) + * + * encoding==GB18030 requires examining up to two bytes to determine character + * length. Therefore, callers satisfying none of those conditions must use + * pg_encoding_mblen_or_incomplete() instead, as access to mbstr[1] cannot be + * guaranteed to be within allocation bounds. + * + * When dealing with text that is not certainly valid in the specified + * encoding, the result may exceed the actual remaining string length. + * Callers that are not prepared to deal with that should use Min(remaining, + * pg_encoding_mblen_or_incomplete()). For zero-terminated strings, that and + * pg_encoding_mblen_bounded() are interchangeable. */ int pg_encoding_mblen(int encoding, const char *mbstr) @@ -2074,8 +2140,28 @@ pg_encoding_mblen(int encoding, const char *mbstr) } /* - * Returns the byte length of a multibyte character; but not more than - * the distance to end of string. + * Returns the byte length of a multibyte character (possibly not + * zero-terminated), or INT_MAX if too few bytes remain to determine a length. + */ +int +pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr, + size_t remaining) +{ + /* + * Define zero remaining as too few, even for single-byte encodings. + * pg_gb18030_mblen() reads one or two bytes; single-byte encodings read + * zero; others read one. + */ + if (remaining < 1 || + (encoding == PG_GB18030 && IS_HIGHBIT_SET(*mbstr) && remaining < 2)) + return INT_MAX; + return pg_encoding_mblen(encoding, mbstr); +} + +/* + * Returns the byte length of a multibyte character; but not more than the + * distance to the terminating zero byte. For input that might lack a + * terminating zero, use Min(remaining, pg_encoding_mblen_or_incomplete()). */ int pg_encoding_mblen_bounded(int encoding, const char *mbstr) @@ -2128,5 +2214,11 @@ pg_encoding_max_length(int encoding) { Assert(PG_VALID_ENCODING(encoding)); - return pg_wchar_table[encoding].maxmblen; + /* + * Check for the encoding despite the assert, due to some mingw versions + * otherwise issuing bogus warnings. + */ + return PG_VALID_ENCODING(encoding) ? + pg_wchar_table[encoding].maxmblen : + pg_wchar_table[PG_SQL_ASCII].maxmblen; } diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile index 946c05258f008..28196ce0f6ae6 100644 --- a/src/fe_utils/Makefile +++ b/src/fe_utils/Makefile @@ -5,7 +5,7 @@ # This makefile generates a static library, libpgfeutils.a, # for use by client applications # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # IDENTIFICATION @@ -21,6 +21,11 @@ override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS) OBJS = \ archive.o \ + astreamer_file.o \ + astreamer_gzip.o \ + astreamer_lz4.o \ + astreamer_tar.o \ + astreamer_zstd.o \ cancel.o \ conditional.o \ connect_utils.o \ @@ -46,7 +51,6 @@ libpgfeutils.a: $(OBJS) psqlscan.c: FLEXFLAGS = -Cfe -p -p psqlscan.c: FLEX_NO_BACKUP=yes -psqlscan.c: FLEX_FIX_WARNING=yes # libpgfeutils could be useful to contrib, so install it install: all installdirs diff --git a/src/fe_utils/archive.c b/src/fe_utils/archive.c index f194809d53b65..5de3617cb2988 100644 --- a/src/fe_utils/archive.c +++ b/src/fe_utils/archive.c @@ -3,7 +3,7 @@ * archive.c * Routines to access WAL archives from frontend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/bin/pg_basebackup/bbstreamer_file.c b/src/fe_utils/astreamer_file.c similarity index 67% rename from src/bin/pg_basebackup/bbstreamer_file.c rename to src/fe_utils/astreamer_file.c index bab6cd4a6b1ad..c685628508636 100644 --- a/src/bin/pg_basebackup/bbstreamer_file.c +++ b/src/fe_utils/astreamer_file.c @@ -1,11 +1,15 @@ /*------------------------------------------------------------------------- * - * bbstreamer_file.c + * astreamer_file.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Archive streamers that write to files. astreamer_plain_writer writes + * the whole archive to a single file, and astreamer_extractor writes + * each archive member to a separate file in a given directory. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_file.c + * src/fe_utils/astreamer_file.c *------------------------------------------------------------------------- */ @@ -13,60 +17,59 @@ #include -#include "bbstreamer.h" #include "common/file_perm.h" #include "common/logging.h" -#include "common/string.h" +#include "fe_utils/astreamer.h" -typedef struct bbstreamer_plain_writer +typedef struct astreamer_plain_writer { - bbstreamer base; + astreamer base; char *pathname; FILE *file; bool should_close_file; -} bbstreamer_plain_writer; +} astreamer_plain_writer; -typedef struct bbstreamer_extractor +typedef struct astreamer_extractor { - bbstreamer base; + astreamer base; char *basepath; const char *(*link_map) (const char *); void (*report_output_file) (const char *); char filename[MAXPGPATH]; FILE *file; -} bbstreamer_extractor; - -static void bbstreamer_plain_writer_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_plain_writer_finalize(bbstreamer *streamer); -static void bbstreamer_plain_writer_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_plain_writer_ops = { - .content = bbstreamer_plain_writer_content, - .finalize = bbstreamer_plain_writer_finalize, - .free = bbstreamer_plain_writer_free +} astreamer_extractor; + +static void astreamer_plain_writer_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_plain_writer_finalize(astreamer *streamer); +static void astreamer_plain_writer_free(astreamer *streamer); + +static const astreamer_ops astreamer_plain_writer_ops = { + .content = astreamer_plain_writer_content, + .finalize = astreamer_plain_writer_finalize, + .free = astreamer_plain_writer_free }; -static void bbstreamer_extractor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_extractor_finalize(bbstreamer *streamer); -static void bbstreamer_extractor_free(bbstreamer *streamer); +static void astreamer_extractor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_extractor_finalize(astreamer *streamer); +static void astreamer_extractor_free(astreamer *streamer); static void extract_directory(const char *filename, mode_t mode); static void extract_link(const char *filename, const char *linktarget); static FILE *create_file_for_extract(const char *filename, mode_t mode); -static const bbstreamer_ops bbstreamer_extractor_ops = { - .content = bbstreamer_extractor_content, - .finalize = bbstreamer_extractor_finalize, - .free = bbstreamer_extractor_free +static const astreamer_ops astreamer_extractor_ops = { + .content = astreamer_extractor_content, + .finalize = astreamer_extractor_finalize, + .free = astreamer_extractor_free }; /* - * Create a bbstreamer that just writes data to a file. + * Create a astreamer that just writes data to a file. * * The caller must specify a pathname and may specify a file. The pathname is * used for error-reporting purposes either way. If file is NULL, the pathname @@ -74,14 +77,14 @@ static const bbstreamer_ops bbstreamer_extractor_ops = { * for writing and closed when done. If file is not NULL, the data is written * there. */ -bbstreamer * -bbstreamer_plain_writer_new(char *pathname, FILE *file) +astreamer * +astreamer_plain_writer_new(char *pathname, FILE *file) { - bbstreamer_plain_writer *streamer; + astreamer_plain_writer *streamer; - streamer = palloc0(sizeof(bbstreamer_plain_writer)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_plain_writer_ops; + streamer = palloc0(sizeof(astreamer_plain_writer)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_plain_writer_ops; streamer->pathname = pstrdup(pathname); streamer->file = file; @@ -101,13 +104,13 @@ bbstreamer_plain_writer_new(char *pathname, FILE *file) * Write archive content to file. */ static void -bbstreamer_plain_writer_content(bbstreamer *streamer, - bbstreamer_member *member, const char *data, - int len, bbstreamer_archive_context context) +astreamer_plain_writer_content(astreamer *streamer, + astreamer_member *member, const char *data, + int len, astreamer_archive_context context) { - bbstreamer_plain_writer *mystreamer; + astreamer_plain_writer *mystreamer; - mystreamer = (bbstreamer_plain_writer *) streamer; + mystreamer = (astreamer_plain_writer *) streamer; if (len == 0) return; @@ -128,11 +131,11 @@ bbstreamer_plain_writer_content(bbstreamer *streamer, * the file if we opened it, but not if the caller provided it. */ static void -bbstreamer_plain_writer_finalize(bbstreamer *streamer) +astreamer_plain_writer_finalize(astreamer *streamer) { - bbstreamer_plain_writer *mystreamer; + astreamer_plain_writer *mystreamer; - mystreamer = (bbstreamer_plain_writer *) streamer; + mystreamer = (astreamer_plain_writer *) streamer; if (mystreamer->should_close_file && fclose(mystreamer->file) != 0) pg_fatal("could not close file \"%s\": %m", @@ -143,14 +146,14 @@ bbstreamer_plain_writer_finalize(bbstreamer *streamer) } /* - * Free memory associated with this bbstreamer. + * Free memory associated with this astreamer. */ static void -bbstreamer_plain_writer_free(bbstreamer *streamer) +astreamer_plain_writer_free(astreamer *streamer) { - bbstreamer_plain_writer *mystreamer; + astreamer_plain_writer *mystreamer; - mystreamer = (bbstreamer_plain_writer *) streamer; + mystreamer = (astreamer_plain_writer *) streamer; Assert(!mystreamer->should_close_file); Assert(mystreamer->base.bbs_next == NULL); @@ -160,13 +163,13 @@ bbstreamer_plain_writer_free(bbstreamer *streamer) } /* - * Create a bbstreamer that extracts an archive. + * Create a astreamer that extracts an archive. * * All pathnames in the archive are interpreted relative to basepath. * - * Unlike e.g. bbstreamer_plain_writer_new() we can't do anything useful here + * Unlike e.g. astreamer_plain_writer_new() we can't do anything useful here * with untyped chunks; we need typed chunks which follow the rules described - * in bbstreamer.h. Assuming we have that, we don't need to worry about the + * in astreamer.h. Assuming we have that, we don't need to worry about the * original archive format; it's enough to just look at the member information * provided and write to the corresponding file. * @@ -179,16 +182,16 @@ bbstreamer_plain_writer_free(bbstreamer *streamer) * new output file. The pathname to that file is passed as an argument. If * NULL, the call is skipped. */ -bbstreamer * -bbstreamer_extractor_new(const char *basepath, - const char *(*link_map) (const char *), - void (*report_output_file) (const char *)) +astreamer * +astreamer_extractor_new(const char *basepath, + const char *(*link_map) (const char *), + void (*report_output_file) (const char *)) { - bbstreamer_extractor *streamer; + astreamer_extractor *streamer; - streamer = palloc0(sizeof(bbstreamer_extractor)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_extractor_ops; + streamer = palloc0(sizeof(astreamer_extractor)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_extractor_ops; streamer->basepath = pstrdup(basepath); streamer->link_map = link_map; streamer->report_output_file = report_output_file; @@ -200,19 +203,19 @@ bbstreamer_extractor_new(const char *basepath, * Extract archive contents to the filesystem. */ static void -bbstreamer_extractor_content(bbstreamer *streamer, bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_extractor_content(astreamer *streamer, astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_extractor *mystreamer = (bbstreamer_extractor *) streamer; + astreamer_extractor *mystreamer = (astreamer_extractor *) streamer; int fnamelen; - Assert(member != NULL || context == BBSTREAMER_ARCHIVE_TRAILER); - Assert(context != BBSTREAMER_UNKNOWN); + Assert(member != NULL || context == ASTREAMER_ARCHIVE_TRAILER); + Assert(context != ASTREAMER_UNKNOWN); switch (context) { - case BBSTREAMER_MEMBER_HEADER: + case ASTREAMER_MEMBER_HEADER: Assert(mystreamer->file == NULL); /* Prepend basepath. */ @@ -245,7 +248,7 @@ bbstreamer_extractor_content(bbstreamer *streamer, bbstreamer_member *member, mystreamer->report_output_file(mystreamer->filename); break; - case BBSTREAMER_MEMBER_CONTENTS: + case ASTREAMER_MEMBER_CONTENTS: if (mystreamer->file == NULL) break; @@ -260,14 +263,14 @@ bbstreamer_extractor_content(bbstreamer *streamer, bbstreamer_member *member, } break; - case BBSTREAMER_MEMBER_TRAILER: + case ASTREAMER_MEMBER_TRAILER: if (mystreamer->file == NULL) break; fclose(mystreamer->file); mystreamer->file = NULL; break; - case BBSTREAMER_ARCHIVE_TRAILER: + case ASTREAMER_ARCHIVE_TRAILER: break; default: @@ -375,10 +378,10 @@ create_file_for_extract(const char *filename, mode_t mode) * There's nothing to do here but sanity checking. */ static void -bbstreamer_extractor_finalize(bbstreamer *streamer) +astreamer_extractor_finalize(astreamer *streamer) { - bbstreamer_extractor *mystreamer PG_USED_FOR_ASSERTS_ONLY - = (bbstreamer_extractor *) streamer; + astreamer_extractor *mystreamer PG_USED_FOR_ASSERTS_ONLY + = (astreamer_extractor *) streamer; Assert(mystreamer->file == NULL); } @@ -387,9 +390,9 @@ bbstreamer_extractor_finalize(bbstreamer *streamer) * Free memory. */ static void -bbstreamer_extractor_free(bbstreamer *streamer) +astreamer_extractor_free(astreamer *streamer) { - bbstreamer_extractor *mystreamer = (bbstreamer_extractor *) streamer; + astreamer_extractor *mystreamer = (astreamer_extractor *) streamer; pfree(mystreamer->basepath); pfree(mystreamer); diff --git a/src/bin/pg_basebackup/bbstreamer_gzip.c b/src/fe_utils/astreamer_gzip.c similarity index 53% rename from src/bin/pg_basebackup/bbstreamer_gzip.c rename to src/fe_utils/astreamer_gzip.c index 0417fd9bc2ceb..a395f57edcd70 100644 --- a/src/bin/pg_basebackup/bbstreamer_gzip.c +++ b/src/fe_utils/astreamer_gzip.c @@ -1,11 +1,26 @@ /*------------------------------------------------------------------------- * - * bbstreamer_gzip.c + * astreamer_gzip.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Archive streamers that deal with data compressed using gzip. + * astreamer_gzip_writer applies gzip compression to the input data + * and writes the result to a file. astreamer_gzip_decompressor assumes + * that the input stream is compressed using gzip and decompresses it. + * + * Note that the code in this file is asymmetric with what we do for + * other compression types: for lz4 and zstd, there is a compressor and + * a decompressor, rather than a writer and a decompressor. The approach + * taken here is less flexible, because a writer can only write to a file, + * while a compressor can write to a subsequent astreamer which is free + * to do whatever it likes. The reason it's like this is because this + * code was adapted from old, less-modular pg_basebackup code that used + * the same APIs that astreamer_gzip_writer now uses, and it didn't seem + * necessary to change anything at the time. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_gzip.c + * src/fe_utils/astreamer_gzip.c *------------------------------------------------------------------------- */ @@ -17,74 +32,79 @@ #include #endif -#include "bbstreamer.h" -#include "common/file_perm.h" #include "common/logging.h" -#include "common/string.h" +#include "fe_utils/astreamer.h" #ifdef HAVE_LIBZ -typedef struct bbstreamer_gzip_writer +typedef struct astreamer_gzip_writer { - bbstreamer base; + astreamer base; char *pathname; gzFile gzfile; -} bbstreamer_gzip_writer; +} astreamer_gzip_writer; -typedef struct bbstreamer_gzip_decompressor +typedef struct astreamer_gzip_decompressor { - bbstreamer base; + astreamer base; z_stream zstream; size_t bytes_written; -} bbstreamer_gzip_decompressor; - -static void bbstreamer_gzip_writer_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_gzip_writer_finalize(bbstreamer *streamer); -static void bbstreamer_gzip_writer_free(bbstreamer *streamer); +} astreamer_gzip_decompressor; + +static void astreamer_gzip_writer_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_gzip_writer_finalize(astreamer *streamer); +static void astreamer_gzip_writer_free(astreamer *streamer); static const char *get_gz_error(gzFile gzf); -static const bbstreamer_ops bbstreamer_gzip_writer_ops = { - .content = bbstreamer_gzip_writer_content, - .finalize = bbstreamer_gzip_writer_finalize, - .free = bbstreamer_gzip_writer_free +static const astreamer_ops astreamer_gzip_writer_ops = { + .content = astreamer_gzip_writer_content, + .finalize = astreamer_gzip_writer_finalize, + .free = astreamer_gzip_writer_free }; -static void bbstreamer_gzip_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_gzip_decompressor_finalize(bbstreamer *streamer); -static void bbstreamer_gzip_decompressor_free(bbstreamer *streamer); +static void astreamer_gzip_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_gzip_decompressor_finalize(astreamer *streamer); +static void astreamer_gzip_decompressor_free(astreamer *streamer); static void *gzip_palloc(void *opaque, unsigned items, unsigned size); static void gzip_pfree(void *opaque, void *address); -static const bbstreamer_ops bbstreamer_gzip_decompressor_ops = { - .content = bbstreamer_gzip_decompressor_content, - .finalize = bbstreamer_gzip_decompressor_finalize, - .free = bbstreamer_gzip_decompressor_free +static const astreamer_ops astreamer_gzip_decompressor_ops = { + .content = astreamer_gzip_decompressor_content, + .finalize = astreamer_gzip_decompressor_finalize, + .free = astreamer_gzip_decompressor_free }; #endif /* - * Create a bbstreamer that just compresses data using gzip, and then writes + * Create a astreamer that just compresses data using gzip, and then writes * it to a file. * - * As in the case of bbstreamer_plain_writer_new, pathname is always used - * for error reporting purposes; if file is NULL, it is also the opened and - * closed so that the data may be written there. + * The caller must specify a pathname and may specify a file. The pathname is + * used for error-reporting purposes either way. If file is NULL, the pathname + * also identifies the file to which the data should be written: it is opened + * for writing and closed when done. If file is not NULL, the data is written + * there. + * + * Note that zlib does not use the FILE interface, but operates directly on + * a duplicate of the underlying fd. Hence, callers must take care if they + * plan to write any other data to the same FILE, either before or after using + * this. */ -bbstreamer * -bbstreamer_gzip_writer_new(char *pathname, FILE *file, - pg_compress_specification *compress) +astreamer * +astreamer_gzip_writer_new(char *pathname, FILE *file, + pg_compress_specification *compress) { #ifdef HAVE_LIBZ - bbstreamer_gzip_writer *streamer; + astreamer_gzip_writer *streamer; - streamer = palloc0(sizeof(bbstreamer_gzip_writer)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_gzip_writer_ops; + streamer = palloc0(sizeof(astreamer_gzip_writer)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_gzip_writer_ops; streamer->pathname = pstrdup(pathname); @@ -97,6 +117,10 @@ bbstreamer_gzip_writer_new(char *pathname, FILE *file, } else { + /* + * We must dup the file handle so that gzclose doesn't break the + * caller's FILE. See comment for astreamer_gzip_writer_finalize. + */ int fd = dup(fileno(file)); if (fd < 0) @@ -123,13 +147,13 @@ bbstreamer_gzip_writer_new(char *pathname, FILE *file, * Write archive content to gzip file. */ static void -bbstreamer_gzip_writer_content(bbstreamer *streamer, - bbstreamer_member *member, const char *data, - int len, bbstreamer_archive_context context) +astreamer_gzip_writer_content(astreamer *streamer, + astreamer_member *member, const char *data, + int len, astreamer_archive_context context) { - bbstreamer_gzip_writer *mystreamer; + astreamer_gzip_writer *mystreamer; - mystreamer = (bbstreamer_gzip_writer *) streamer; + mystreamer = (astreamer_gzip_writer *) streamer; if (len == 0) return; @@ -151,16 +175,16 @@ bbstreamer_gzip_writer_content(bbstreamer *streamer, * * It makes no difference whether we opened the file or the caller did it, * because libz provides no way of avoiding a close on the underlying file - * handle. Notice, however, that bbstreamer_gzip_writer_new() uses dup() to + * handle. Notice, however, that astreamer_gzip_writer_new() uses dup() to * work around this issue, so that the behavior from the caller's viewpoint - * is the same as for bbstreamer_plain_writer. + * is the same as for astreamer_plain_writer. */ static void -bbstreamer_gzip_writer_finalize(bbstreamer *streamer) +astreamer_gzip_writer_finalize(astreamer *streamer) { - bbstreamer_gzip_writer *mystreamer; + astreamer_gzip_writer *mystreamer; - mystreamer = (bbstreamer_gzip_writer *) streamer; + mystreamer = (astreamer_gzip_writer *) streamer; errno = 0; /* in case gzclose() doesn't set it */ if (gzclose(mystreamer->gzfile) != 0) @@ -171,14 +195,14 @@ bbstreamer_gzip_writer_finalize(bbstreamer *streamer) } /* - * Free memory associated with this bbstreamer. + * Free memory associated with this astreamer. */ static void -bbstreamer_gzip_writer_free(bbstreamer *streamer) +astreamer_gzip_writer_free(astreamer *streamer) { - bbstreamer_gzip_writer *mystreamer; + astreamer_gzip_writer *mystreamer; - mystreamer = (bbstreamer_gzip_writer *) streamer; + mystreamer = (astreamer_gzip_writer *) streamer; Assert(mystreamer->base.bbs_next == NULL); Assert(mystreamer->gzfile == NULL); @@ -208,18 +232,18 @@ get_gz_error(gzFile gzf) * Create a new base backup streamer that performs decompression of gzip * compressed blocks. */ -bbstreamer * -bbstreamer_gzip_decompressor_new(bbstreamer *next) +astreamer * +astreamer_gzip_decompressor_new(astreamer *next) { #ifdef HAVE_LIBZ - bbstreamer_gzip_decompressor *streamer; + astreamer_gzip_decompressor *streamer; z_stream *zs; Assert(next != NULL); - streamer = palloc0(sizeof(bbstreamer_gzip_decompressor)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_gzip_decompressor_ops; + streamer = palloc0(sizeof(astreamer_gzip_decompressor)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_gzip_decompressor_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); @@ -258,15 +282,15 @@ bbstreamer_gzip_decompressor_new(bbstreamer *next) * to the next streamer. */ static void -bbstreamer_gzip_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_gzip_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_gzip_decompressor *mystreamer; + astreamer_gzip_decompressor *mystreamer; z_stream *zs; - mystreamer = (bbstreamer_gzip_decompressor *) streamer; + mystreamer = (astreamer_gzip_decompressor *) streamer; zs = &mystreamer->zstream; zs->next_in = (const uint8 *) data; @@ -301,9 +325,9 @@ bbstreamer_gzip_decompressor_content(bbstreamer *streamer, /* If output buffer is full then pass data to next streamer */ if (mystreamer->bytes_written >= mystreamer->base.bbs_buffer.maxlen) { - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->base.bbs_buffer.data, - mystreamer->base.bbs_buffer.maxlen, context); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->base.bbs_buffer.data, + mystreamer->base.bbs_buffer.maxlen, context); mystreamer->bytes_written = 0; } } @@ -313,31 +337,31 @@ bbstreamer_gzip_decompressor_content(bbstreamer *streamer, * End-of-stream processing. */ static void -bbstreamer_gzip_decompressor_finalize(bbstreamer *streamer) +astreamer_gzip_decompressor_finalize(astreamer *streamer) { - bbstreamer_gzip_decompressor *mystreamer; + astreamer_gzip_decompressor *mystreamer; - mystreamer = (bbstreamer_gzip_decompressor *) streamer; + mystreamer = (astreamer_gzip_decompressor *) streamer; /* * End of the stream, if there is some pending data in output buffers then * we must forward it to next streamer. */ - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->base.bbs_buffer.data, - mystreamer->base.bbs_buffer.maxlen, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->base.bbs_buffer.data, + mystreamer->base.bbs_buffer.maxlen, + ASTREAMER_UNKNOWN); - bbstreamer_finalize(mystreamer->base.bbs_next); + astreamer_finalize(mystreamer->base.bbs_next); } /* * Free memory. */ static void -bbstreamer_gzip_decompressor_free(bbstreamer *streamer) +astreamer_gzip_decompressor_free(astreamer *streamer) { - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); pfree(streamer->bbs_buffer.data); pfree(streamer); } diff --git a/src/bin/pg_basebackup/bbstreamer_lz4.c b/src/fe_utils/astreamer_lz4.c similarity index 67% rename from src/bin/pg_basebackup/bbstreamer_lz4.c rename to src/fe_utils/astreamer_lz4.c index f5c9e68150c80..781aaf99f38fe 100644 --- a/src/bin/pg_basebackup/bbstreamer_lz4.c +++ b/src/fe_utils/astreamer_lz4.c @@ -1,11 +1,15 @@ /*------------------------------------------------------------------------- * - * bbstreamer_lz4.c + * astreamer_lz4.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Archive streamers that deal with data compressed using lz4. + * astreamer_lz4_compressor applies lz4 compression to the input stream, + * and astreamer_lz4_decompressor does the reverse. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_lz4.c + * src/fe_utils/astreamer_lz4.c *------------------------------------------------------------------------- */ @@ -17,15 +21,13 @@ #include #endif -#include "bbstreamer.h" -#include "common/file_perm.h" #include "common/logging.h" -#include "common/string.h" +#include "fe_utils/astreamer.h" #ifdef USE_LZ4 -typedef struct bbstreamer_lz4_frame +typedef struct astreamer_lz4_frame { - bbstreamer base; + astreamer base; LZ4F_compressionContext_t cctx; LZ4F_decompressionContext_t dctx; @@ -33,32 +35,32 @@ typedef struct bbstreamer_lz4_frame size_t bytes_written; bool header_written; -} bbstreamer_lz4_frame; - -static void bbstreamer_lz4_compressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_lz4_compressor_finalize(bbstreamer *streamer); -static void bbstreamer_lz4_compressor_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_lz4_compressor_ops = { - .content = bbstreamer_lz4_compressor_content, - .finalize = bbstreamer_lz4_compressor_finalize, - .free = bbstreamer_lz4_compressor_free +} astreamer_lz4_frame; + +static void astreamer_lz4_compressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_lz4_compressor_finalize(astreamer *streamer); +static void astreamer_lz4_compressor_free(astreamer *streamer); + +static const astreamer_ops astreamer_lz4_compressor_ops = { + .content = astreamer_lz4_compressor_content, + .finalize = astreamer_lz4_compressor_finalize, + .free = astreamer_lz4_compressor_free }; -static void bbstreamer_lz4_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_lz4_decompressor_finalize(bbstreamer *streamer); -static void bbstreamer_lz4_decompressor_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_lz4_decompressor_ops = { - .content = bbstreamer_lz4_decompressor_content, - .finalize = bbstreamer_lz4_decompressor_finalize, - .free = bbstreamer_lz4_decompressor_free +static void astreamer_lz4_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_lz4_decompressor_finalize(astreamer *streamer); +static void astreamer_lz4_decompressor_free(astreamer *streamer); + +static const astreamer_ops astreamer_lz4_decompressor_ops = { + .content = astreamer_lz4_decompressor_content, + .finalize = astreamer_lz4_decompressor_finalize, + .free = astreamer_lz4_decompressor_free }; #endif @@ -66,19 +68,19 @@ static const bbstreamer_ops bbstreamer_lz4_decompressor_ops = { * Create a new base backup streamer that performs lz4 compression of tar * blocks. */ -bbstreamer * -bbstreamer_lz4_compressor_new(bbstreamer *next, pg_compress_specification *compress) +astreamer * +astreamer_lz4_compressor_new(astreamer *next, pg_compress_specification *compress) { #ifdef USE_LZ4 - bbstreamer_lz4_frame *streamer; + astreamer_lz4_frame *streamer; LZ4F_errorCode_t ctxError; LZ4F_preferences_t *prefs; Assert(next != NULL); - streamer = palloc0(sizeof(bbstreamer_lz4_frame)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_lz4_compressor_ops; + streamer = palloc0(sizeof(astreamer_lz4_frame)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_lz4_compressor_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); @@ -113,19 +115,19 @@ bbstreamer_lz4_compressor_new(bbstreamer *next, pg_compress_specification *compr * of output buffer to next streamer and empty the buffer. */ static void -bbstreamer_lz4_compressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_lz4_compressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; uint8 *next_in, *next_out; size_t out_bound, compressed_size, avail_out; - mystreamer = (bbstreamer_lz4_frame *) streamer; + mystreamer = (astreamer_lz4_frame *) streamer; next_in = (uint8 *) data; /* Write header before processing the first input chunk. */ @@ -159,10 +161,10 @@ bbstreamer_lz4_compressor_content(bbstreamer *streamer, out_bound = LZ4F_compressBound(len, &mystreamer->prefs); if (avail_out < out_bound) { - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->base.bbs_buffer.data, - mystreamer->bytes_written, - context); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->base.bbs_buffer.data, + mystreamer->bytes_written, + context); /* Enlarge buffer if it falls short of out bound. */ if (mystreamer->base.bbs_buffer.maxlen < out_bound) @@ -196,25 +198,25 @@ bbstreamer_lz4_compressor_content(bbstreamer *streamer, * End-of-stream processing. */ static void -bbstreamer_lz4_compressor_finalize(bbstreamer *streamer) +astreamer_lz4_compressor_finalize(astreamer *streamer) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; uint8 *next_out; size_t footer_bound, compressed_size, avail_out; - mystreamer = (bbstreamer_lz4_frame *) streamer; + mystreamer = (astreamer_lz4_frame *) streamer; /* Find out the footer bound and update the output buffer. */ footer_bound = LZ4F_compressBound(0, &mystreamer->prefs); if ((mystreamer->base.bbs_buffer.maxlen - mystreamer->bytes_written) < footer_bound) { - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->base.bbs_buffer.data, - mystreamer->bytes_written, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->base.bbs_buffer.data, + mystreamer->bytes_written, + ASTREAMER_UNKNOWN); /* Enlarge buffer if it falls short of footer bound. */ if (mystreamer->base.bbs_buffer.maxlen < footer_bound) @@ -243,24 +245,24 @@ bbstreamer_lz4_compressor_finalize(bbstreamer *streamer) mystreamer->bytes_written += compressed_size; - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->base.bbs_buffer.data, - mystreamer->bytes_written, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->base.bbs_buffer.data, + mystreamer->bytes_written, + ASTREAMER_UNKNOWN); - bbstreamer_finalize(mystreamer->base.bbs_next); + astreamer_finalize(mystreamer->base.bbs_next); } /* * Free memory. */ static void -bbstreamer_lz4_compressor_free(bbstreamer *streamer) +astreamer_lz4_compressor_free(astreamer *streamer) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; - mystreamer = (bbstreamer_lz4_frame *) streamer; - bbstreamer_free(streamer->bbs_next); + mystreamer = (astreamer_lz4_frame *) streamer; + astreamer_free(streamer->bbs_next); LZ4F_freeCompressionContext(mystreamer->cctx); pfree(streamer->bbs_buffer.data); pfree(streamer); @@ -271,18 +273,18 @@ bbstreamer_lz4_compressor_free(bbstreamer *streamer) * Create a new base backup streamer that performs decompression of lz4 * compressed blocks. */ -bbstreamer * -bbstreamer_lz4_decompressor_new(bbstreamer *next) +astreamer * +astreamer_lz4_decompressor_new(astreamer *next) { #ifdef USE_LZ4 - bbstreamer_lz4_frame *streamer; + astreamer_lz4_frame *streamer; LZ4F_errorCode_t ctxError; Assert(next != NULL); - streamer = palloc0(sizeof(bbstreamer_lz4_frame)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_lz4_decompressor_ops; + streamer = palloc0(sizeof(astreamer_lz4_frame)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_lz4_decompressor_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); @@ -307,18 +309,18 @@ bbstreamer_lz4_decompressor_new(bbstreamer *next) * to the next streamer. */ static void -bbstreamer_lz4_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_lz4_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; uint8 *next_in, *next_out; size_t avail_in, avail_out; - mystreamer = (bbstreamer_lz4_frame *) streamer; + mystreamer = (astreamer_lz4_frame *) streamer; next_in = (uint8 *) data; next_out = (uint8 *) mystreamer->base.bbs_buffer.data; avail_in = len; @@ -366,10 +368,10 @@ bbstreamer_lz4_decompressor_content(bbstreamer *streamer, */ if (mystreamer->bytes_written >= mystreamer->base.bbs_buffer.maxlen) { - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->base.bbs_buffer.data, - mystreamer->base.bbs_buffer.maxlen, - context); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->base.bbs_buffer.data, + mystreamer->base.bbs_buffer.maxlen, + context); avail_out = mystreamer->base.bbs_buffer.maxlen; mystreamer->bytes_written = 0; @@ -387,34 +389,34 @@ bbstreamer_lz4_decompressor_content(bbstreamer *streamer, * End-of-stream processing. */ static void -bbstreamer_lz4_decompressor_finalize(bbstreamer *streamer) +astreamer_lz4_decompressor_finalize(astreamer *streamer) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; - mystreamer = (bbstreamer_lz4_frame *) streamer; + mystreamer = (astreamer_lz4_frame *) streamer; /* * End of the stream, if there is some pending data in output buffers then * we must forward it to next streamer. */ - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->base.bbs_buffer.data, - mystreamer->base.bbs_buffer.maxlen, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->base.bbs_buffer.data, + mystreamer->base.bbs_buffer.maxlen, + ASTREAMER_UNKNOWN); - bbstreamer_finalize(mystreamer->base.bbs_next); + astreamer_finalize(mystreamer->base.bbs_next); } /* * Free memory. */ static void -bbstreamer_lz4_decompressor_free(bbstreamer *streamer) +astreamer_lz4_decompressor_free(astreamer *streamer) { - bbstreamer_lz4_frame *mystreamer; + astreamer_lz4_frame *mystreamer; - mystreamer = (bbstreamer_lz4_frame *) streamer; - bbstreamer_free(streamer->bbs_next); + mystreamer = (astreamer_lz4_frame *) streamer; + astreamer_free(streamer->bbs_next); LZ4F_freeDecompressionContext(mystreamer->dctx); pfree(streamer->bbs_buffer.data); pfree(streamer); diff --git a/src/bin/pg_basebackup/bbstreamer_tar.c b/src/fe_utils/astreamer_tar.c similarity index 50% rename from src/bin/pg_basebackup/bbstreamer_tar.c rename to src/fe_utils/astreamer_tar.c index 9137d17ddc1a9..088e2357920c5 100644 --- a/src/bin/pg_basebackup/bbstreamer_tar.c +++ b/src/fe_utils/astreamer_tar.c @@ -1,21 +1,21 @@ /*------------------------------------------------------------------------- * - * bbstreamer_tar.c + * astreamer_tar.c * * This module implements three types of tar processing. A tar parser - * expects unlabelled chunks of data (e.g. BBSTREAMER_UNKNOWN) and splits - * it into labelled chunks (any other value of bbstreamer_archive_context). + * expects unlabelled chunks of data (e.g. ASTREAMER_UNKNOWN) and splits + * it into labelled chunks (any other value of astreamer_archive_context). * A tar archiver does the reverse: it takes a bunch of labelled chunks * and produces a tarfile, optionally replacing member headers and trailers - * so that upstream bbstreamer objects can perform surgery on the tarfile + * so that upstream astreamer objects can perform surgery on the tarfile * contents without knowing the details of the tar format. A tar terminator * just adds two blocks of NUL bytes to the end of the file, since older * server versions produce files with this terminator omitted. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_tar.c + * src/fe_utils/astreamer_tar.c *------------------------------------------------------------------------- */ @@ -23,83 +23,83 @@ #include -#include "bbstreamer.h" #include "common/logging.h" +#include "fe_utils/astreamer.h" #include "pgtar.h" -typedef struct bbstreamer_tar_parser +typedef struct astreamer_tar_parser { - bbstreamer base; - bbstreamer_archive_context next_context; - bbstreamer_member member; + astreamer base; + astreamer_archive_context next_context; + astreamer_member member; size_t file_bytes_sent; size_t pad_bytes_expected; -} bbstreamer_tar_parser; +} astreamer_tar_parser; -typedef struct bbstreamer_tar_archiver +typedef struct astreamer_tar_archiver { - bbstreamer base; + astreamer base; bool rearchive_member; -} bbstreamer_tar_archiver; - -static void bbstreamer_tar_parser_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_tar_parser_finalize(bbstreamer *streamer); -static void bbstreamer_tar_parser_free(bbstreamer *streamer); -static bool bbstreamer_tar_header(bbstreamer_tar_parser *mystreamer); - -static const bbstreamer_ops bbstreamer_tar_parser_ops = { - .content = bbstreamer_tar_parser_content, - .finalize = bbstreamer_tar_parser_finalize, - .free = bbstreamer_tar_parser_free +} astreamer_tar_archiver; + +static void astreamer_tar_parser_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_tar_parser_finalize(astreamer *streamer); +static void astreamer_tar_parser_free(astreamer *streamer); +static bool astreamer_tar_header(astreamer_tar_parser *mystreamer); + +static const astreamer_ops astreamer_tar_parser_ops = { + .content = astreamer_tar_parser_content, + .finalize = astreamer_tar_parser_finalize, + .free = astreamer_tar_parser_free }; -static void bbstreamer_tar_archiver_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_tar_archiver_finalize(bbstreamer *streamer); -static void bbstreamer_tar_archiver_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_tar_archiver_ops = { - .content = bbstreamer_tar_archiver_content, - .finalize = bbstreamer_tar_archiver_finalize, - .free = bbstreamer_tar_archiver_free +static void astreamer_tar_archiver_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_tar_archiver_finalize(astreamer *streamer); +static void astreamer_tar_archiver_free(astreamer *streamer); + +static const astreamer_ops astreamer_tar_archiver_ops = { + .content = astreamer_tar_archiver_content, + .finalize = astreamer_tar_archiver_finalize, + .free = astreamer_tar_archiver_free }; -static void bbstreamer_tar_terminator_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_tar_terminator_finalize(bbstreamer *streamer); -static void bbstreamer_tar_terminator_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_tar_terminator_ops = { - .content = bbstreamer_tar_terminator_content, - .finalize = bbstreamer_tar_terminator_finalize, - .free = bbstreamer_tar_terminator_free +static void astreamer_tar_terminator_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_tar_terminator_finalize(astreamer *streamer); +static void astreamer_tar_terminator_free(astreamer *streamer); + +static const astreamer_ops astreamer_tar_terminator_ops = { + .content = astreamer_tar_terminator_content, + .finalize = astreamer_tar_terminator_finalize, + .free = astreamer_tar_terminator_free }; /* - * Create a bbstreamer that can parse a stream of content as tar data. + * Create a astreamer that can parse a stream of content as tar data. * - * The input should be a series of BBSTREAMER_UNKNOWN chunks; the bbstreamer + * The input should be a series of ASTREAMER_UNKNOWN chunks; the astreamer * specified by 'next' will receive a series of typed chunks, as per the - * conventions described in bbstreamer.h. + * conventions described in astreamer.h. */ -bbstreamer * -bbstreamer_tar_parser_new(bbstreamer *next) +astreamer * +astreamer_tar_parser_new(astreamer *next) { - bbstreamer_tar_parser *streamer; + astreamer_tar_parser *streamer; - streamer = palloc0(sizeof(bbstreamer_tar_parser)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_tar_parser_ops; + streamer = palloc0(sizeof(astreamer_tar_parser)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_tar_parser_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); - streamer->next_context = BBSTREAMER_MEMBER_HEADER; + streamer->next_context = ASTREAMER_MEMBER_HEADER; return &streamer->base; } @@ -108,29 +108,29 @@ bbstreamer_tar_parser_new(bbstreamer *next) * Parse unknown content as tar data. */ static void -bbstreamer_tar_parser_content(bbstreamer *streamer, bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_tar_parser_content(astreamer *streamer, astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_tar_parser *mystreamer = (bbstreamer_tar_parser *) streamer; + astreamer_tar_parser *mystreamer = (astreamer_tar_parser *) streamer; size_t nbytes; /* Expect unparsed input. */ Assert(member == NULL); - Assert(context == BBSTREAMER_UNKNOWN); + Assert(context == ASTREAMER_UNKNOWN); while (len > 0) { switch (mystreamer->next_context) { - case BBSTREAMER_MEMBER_HEADER: + case ASTREAMER_MEMBER_HEADER: /* * If we're expecting an archive member header, accumulate a * full block of data before doing anything further. */ - if (!bbstreamer_buffer_until(streamer, &data, &len, - TAR_BLOCK_SIZE)) + if (!astreamer_buffer_until(streamer, &data, &len, + TAR_BLOCK_SIZE)) return; /* @@ -139,32 +139,32 @@ bbstreamer_tar_parser_content(bbstreamer *streamer, bbstreamer_member *member, * thought was the next file header is actually the start of * the archive trailer. Switch modes accordingly. */ - if (bbstreamer_tar_header(mystreamer)) + if (astreamer_tar_header(mystreamer)) { if (mystreamer->member.size == 0) { /* No content; trailer is zero-length. */ - bbstreamer_content(mystreamer->base.bbs_next, - &mystreamer->member, - NULL, 0, - BBSTREAMER_MEMBER_TRAILER); + astreamer_content(mystreamer->base.bbs_next, + &mystreamer->member, + NULL, 0, + ASTREAMER_MEMBER_TRAILER); /* Expect next header. */ - mystreamer->next_context = BBSTREAMER_MEMBER_HEADER; + mystreamer->next_context = ASTREAMER_MEMBER_HEADER; } else { /* Expect contents. */ - mystreamer->next_context = BBSTREAMER_MEMBER_CONTENTS; + mystreamer->next_context = ASTREAMER_MEMBER_CONTENTS; } mystreamer->base.bbs_buffer.len = 0; mystreamer->file_bytes_sent = 0; } else - mystreamer->next_context = BBSTREAMER_ARCHIVE_TRAILER; + mystreamer->next_context = ASTREAMER_ARCHIVE_TRAILER; break; - case BBSTREAMER_MEMBER_CONTENTS: + case ASTREAMER_MEMBER_CONTENTS: /* * Send as much content as we have, but not more than the @@ -174,10 +174,10 @@ bbstreamer_tar_parser_content(bbstreamer *streamer, bbstreamer_member *member, nbytes = mystreamer->member.size - mystreamer->file_bytes_sent; nbytes = Min(nbytes, len); Assert(nbytes > 0); - bbstreamer_content(mystreamer->base.bbs_next, - &mystreamer->member, - data, nbytes, - BBSTREAMER_MEMBER_CONTENTS); + astreamer_content(mystreamer->base.bbs_next, + &mystreamer->member, + data, nbytes, + ASTREAMER_MEMBER_CONTENTS); mystreamer->file_bytes_sent += nbytes; data += nbytes; len -= nbytes; @@ -193,53 +193,53 @@ bbstreamer_tar_parser_content(bbstreamer *streamer, bbstreamer_member *member, if (mystreamer->pad_bytes_expected == 0) { /* Trailer is zero-length. */ - bbstreamer_content(mystreamer->base.bbs_next, - &mystreamer->member, - NULL, 0, - BBSTREAMER_MEMBER_TRAILER); + astreamer_content(mystreamer->base.bbs_next, + &mystreamer->member, + NULL, 0, + ASTREAMER_MEMBER_TRAILER); /* Expect next header. */ - mystreamer->next_context = BBSTREAMER_MEMBER_HEADER; + mystreamer->next_context = ASTREAMER_MEMBER_HEADER; } else { /* Trailer is not zero-length. */ - mystreamer->next_context = BBSTREAMER_MEMBER_TRAILER; + mystreamer->next_context = ASTREAMER_MEMBER_TRAILER; } mystreamer->base.bbs_buffer.len = 0; } break; - case BBSTREAMER_MEMBER_TRAILER: + case ASTREAMER_MEMBER_TRAILER: /* * If we're expecting an archive member trailer, accumulate * the expected number of padding bytes before sending * anything onward. */ - if (!bbstreamer_buffer_until(streamer, &data, &len, - mystreamer->pad_bytes_expected)) + if (!astreamer_buffer_until(streamer, &data, &len, + mystreamer->pad_bytes_expected)) return; /* OK, now we can send it. */ - bbstreamer_content(mystreamer->base.bbs_next, - &mystreamer->member, - data, mystreamer->pad_bytes_expected, - BBSTREAMER_MEMBER_TRAILER); + astreamer_content(mystreamer->base.bbs_next, + &mystreamer->member, + data, mystreamer->pad_bytes_expected, + ASTREAMER_MEMBER_TRAILER); /* Expect next file header. */ - mystreamer->next_context = BBSTREAMER_MEMBER_HEADER; + mystreamer->next_context = ASTREAMER_MEMBER_HEADER; mystreamer->base.bbs_buffer.len = 0; break; - case BBSTREAMER_ARCHIVE_TRAILER: + case ASTREAMER_ARCHIVE_TRAILER: /* * We've seen an end-of-archive indicator, so anything more is * buffered and sent as part of the archive trailer. But we * don't expect more than 2 blocks. */ - bbstreamer_buffer_bytes(streamer, &data, &len, len); + astreamer_buffer_bytes(streamer, &data, &len, len); if (len > 2 * TAR_BLOCK_SIZE) pg_fatal("tar file trailer exceeds 2 blocks"); return; @@ -255,14 +255,14 @@ bbstreamer_tar_parser_content(bbstreamer *streamer, bbstreamer_member *member, * Parse a file header within a tar stream. * * The return value is true if we found a file header and passed it on to the - * next bbstreamer; it is false if we have reached the archive trailer. + * next astreamer; it is false if we have reached the archive trailer. */ static bool -bbstreamer_tar_header(bbstreamer_tar_parser *mystreamer) +astreamer_tar_header(astreamer_tar_parser *mystreamer) { bool has_nonzero_byte = false; int i; - bbstreamer_member *member = &mystreamer->member; + astreamer_member *member = &mystreamer->member; char *buffer = mystreamer->base.bbs_buffer.data; Assert(mystreamer->base.bbs_buffer.len == TAR_BLOCK_SIZE); @@ -304,10 +304,10 @@ bbstreamer_tar_header(bbstreamer_tar_parser *mystreamer) /* Compute number of padding bytes. */ mystreamer->pad_bytes_expected = tarPaddingBytesRequired(member->size); - /* Forward the entire header to the next bbstreamer. */ - bbstreamer_content(mystreamer->base.bbs_next, member, - buffer, TAR_BLOCK_SIZE, - BBSTREAMER_MEMBER_HEADER); + /* Forward the entire header to the next astreamer. */ + astreamer_content(mystreamer->base.bbs_next, member, + buffer, TAR_BLOCK_SIZE, + ASTREAMER_MEMBER_HEADER); return true; } @@ -316,50 +316,50 @@ bbstreamer_tar_header(bbstreamer_tar_parser *mystreamer) * End-of-stream processing for a tar parser. */ static void -bbstreamer_tar_parser_finalize(bbstreamer *streamer) +astreamer_tar_parser_finalize(astreamer *streamer) { - bbstreamer_tar_parser *mystreamer = (bbstreamer_tar_parser *) streamer; + astreamer_tar_parser *mystreamer = (astreamer_tar_parser *) streamer; - if (mystreamer->next_context != BBSTREAMER_ARCHIVE_TRAILER && - (mystreamer->next_context != BBSTREAMER_MEMBER_HEADER || + if (mystreamer->next_context != ASTREAMER_ARCHIVE_TRAILER && + (mystreamer->next_context != ASTREAMER_MEMBER_HEADER || mystreamer->base.bbs_buffer.len > 0)) pg_fatal("COPY stream ended before last file was finished"); /* Send the archive trailer, even if empty. */ - bbstreamer_content(streamer->bbs_next, NULL, - streamer->bbs_buffer.data, streamer->bbs_buffer.len, - BBSTREAMER_ARCHIVE_TRAILER); + astreamer_content(streamer->bbs_next, NULL, + streamer->bbs_buffer.data, streamer->bbs_buffer.len, + ASTREAMER_ARCHIVE_TRAILER); /* Now finalize successor. */ - bbstreamer_finalize(streamer->bbs_next); + astreamer_finalize(streamer->bbs_next); } /* * Free memory associated with a tar parser. */ static void -bbstreamer_tar_parser_free(bbstreamer *streamer) +astreamer_tar_parser_free(astreamer *streamer) { pfree(streamer->bbs_buffer.data); - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); } /* - * Create a bbstreamer that can generate a tar archive. + * Create a astreamer that can generate a tar archive. * * This is intended to be usable either for generating a brand-new tar archive * or for modifying one on the fly. The input should be a series of typed - * chunks (i.e. not BBSTREAMER_UNKNOWN). See also the comments for - * bbstreamer_tar_parser_content. + * chunks (i.e. not ASTREAMER_UNKNOWN). See also the comments for + * astreamer_tar_parser_content. */ -bbstreamer * -bbstreamer_tar_archiver_new(bbstreamer *next) +astreamer * +astreamer_tar_archiver_new(astreamer *next) { - bbstreamer_tar_archiver *streamer; + astreamer_tar_archiver *streamer; - streamer = palloc0(sizeof(bbstreamer_tar_archiver)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_tar_archiver_ops; + streamer = palloc0(sizeof(astreamer_tar_archiver)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_tar_archiver_ops; streamer->base.bbs_next = next; return &streamer->base; @@ -368,36 +368,36 @@ bbstreamer_tar_archiver_new(bbstreamer *next) /* * Fix up the stream of input chunks to create a valid tar file. * - * If a BBSTREAMER_MEMBER_HEADER chunk is of size 0, it is replaced with a + * If a ASTREAMER_MEMBER_HEADER chunk is of size 0, it is replaced with a * newly-constructed tar header. If it is of size TAR_BLOCK_SIZE, it is * passed through without change. Any other size is a fatal error (and * indicates a bug). * - * Whenever a new BBSTREAMER_MEMBER_HEADER chunk is constructed, the - * corresponding BBSTREAMER_MEMBER_TRAILER chunk is also constructed from + * Whenever a new ASTREAMER_MEMBER_HEADER chunk is constructed, the + * corresponding ASTREAMER_MEMBER_TRAILER chunk is also constructed from * scratch. Specifically, we construct a block of zero bytes sufficient to * pad out to a block boundary, as required by the tar format. Other - * BBSTREAMER_MEMBER_TRAILER chunks are passed through without change. + * ASTREAMER_MEMBER_TRAILER chunks are passed through without change. * - * Any BBSTREAMER_MEMBER_CONTENTS chunks are passed through without change. + * Any ASTREAMER_MEMBER_CONTENTS chunks are passed through without change. * - * The BBSTREAMER_ARCHIVE_TRAILER chunk is replaced with two + * The ASTREAMER_ARCHIVE_TRAILER chunk is replaced with two * blocks of zero bytes. Not all tar programs require this, but apparently * some do. The server does not supply this trailer. If no archive trailer is - * present, one will be added by bbstreamer_tar_parser_finalize. + * present, one will be added by astreamer_tar_parser_finalize. */ static void -bbstreamer_tar_archiver_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_tar_archiver_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_tar_archiver *mystreamer = (bbstreamer_tar_archiver *) streamer; + astreamer_tar_archiver *mystreamer = (astreamer_tar_archiver *) streamer; char buffer[2 * TAR_BLOCK_SIZE]; - Assert(context != BBSTREAMER_UNKNOWN); + Assert(context != ASTREAMER_UNKNOWN); - if (context == BBSTREAMER_MEMBER_HEADER && len != TAR_BLOCK_SIZE) + if (context == ASTREAMER_MEMBER_HEADER && len != TAR_BLOCK_SIZE) { Assert(len == 0); @@ -411,7 +411,7 @@ bbstreamer_tar_archiver_content(bbstreamer *streamer, /* Also make a note to replace padding, in case size changed. */ mystreamer->rearchive_member = true; } - else if (context == BBSTREAMER_MEMBER_TRAILER && + else if (context == ASTREAMER_MEMBER_TRAILER && mystreamer->rearchive_member) { int pad_bytes = tarPaddingBytesRequired(member->size); @@ -424,7 +424,7 @@ bbstreamer_tar_archiver_content(bbstreamer *streamer, /* Don't do this again unless we replace another header. */ mystreamer->rearchive_member = false; } - else if (context == BBSTREAMER_ARCHIVE_TRAILER) + else if (context == ASTREAMER_ARCHIVE_TRAILER) { /* Trailer should always be two blocks of zero bytes. */ memset(buffer, 0, 2 * TAR_BLOCK_SIZE); @@ -432,40 +432,40 @@ bbstreamer_tar_archiver_content(bbstreamer *streamer, len = 2 * TAR_BLOCK_SIZE; } - bbstreamer_content(streamer->bbs_next, member, data, len, context); + astreamer_content(streamer->bbs_next, member, data, len, context); } /* * End-of-stream processing for a tar archiver. */ static void -bbstreamer_tar_archiver_finalize(bbstreamer *streamer) +astreamer_tar_archiver_finalize(astreamer *streamer) { - bbstreamer_finalize(streamer->bbs_next); + astreamer_finalize(streamer->bbs_next); } /* * Free memory associated with a tar archiver. */ static void -bbstreamer_tar_archiver_free(bbstreamer *streamer) +astreamer_tar_archiver_free(astreamer *streamer) { - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); pfree(streamer); } /* - * Create a bbstreamer that blindly adds two blocks of NUL bytes to the + * Create a astreamer that blindly adds two blocks of NUL bytes to the * end of an incomplete tarfile that the server might send us. */ -bbstreamer * -bbstreamer_tar_terminator_new(bbstreamer *next) +astreamer * +astreamer_tar_terminator_new(astreamer *next) { - bbstreamer *streamer; + astreamer *streamer; - streamer = palloc0(sizeof(bbstreamer)); - *((const bbstreamer_ops **) &streamer->bbs_ops) = - &bbstreamer_tar_terminator_ops; + streamer = palloc0(sizeof(astreamer)); + *((const astreamer_ops **) &streamer->bbs_ops) = + &astreamer_tar_terminator_ops; streamer->bbs_next = next; return streamer; @@ -475,17 +475,17 @@ bbstreamer_tar_terminator_new(bbstreamer *next) * Pass all the content through without change. */ static void -bbstreamer_tar_terminator_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_tar_terminator_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { /* Expect unparsed input. */ Assert(member == NULL); - Assert(context == BBSTREAMER_UNKNOWN); + Assert(context == ASTREAMER_UNKNOWN); /* Just forward it. */ - bbstreamer_content(streamer->bbs_next, member, data, len, context); + astreamer_content(streamer->bbs_next, member, data, len, context); } /* @@ -493,22 +493,22 @@ bbstreamer_tar_terminator_content(bbstreamer *streamer, * to supply. */ static void -bbstreamer_tar_terminator_finalize(bbstreamer *streamer) +astreamer_tar_terminator_finalize(astreamer *streamer) { char buffer[2 * TAR_BLOCK_SIZE]; memset(buffer, 0, 2 * TAR_BLOCK_SIZE); - bbstreamer_content(streamer->bbs_next, NULL, buffer, - 2 * TAR_BLOCK_SIZE, BBSTREAMER_UNKNOWN); - bbstreamer_finalize(streamer->bbs_next); + astreamer_content(streamer->bbs_next, NULL, buffer, + 2 * TAR_BLOCK_SIZE, ASTREAMER_UNKNOWN); + astreamer_finalize(streamer->bbs_next); } /* * Free memory associated with a tar terminator. */ static void -bbstreamer_tar_terminator_free(bbstreamer *streamer) +astreamer_tar_terminator_free(astreamer *streamer) { - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); pfree(streamer); } diff --git a/src/bin/pg_basebackup/bbstreamer_zstd.c b/src/fe_utils/astreamer_zstd.c similarity index 63% rename from src/bin/pg_basebackup/bbstreamer_zstd.c rename to src/fe_utils/astreamer_zstd.c index 20f11d4450e09..bacdcc150c40f 100644 --- a/src/bin/pg_basebackup/bbstreamer_zstd.c +++ b/src/fe_utils/astreamer_zstd.c @@ -1,11 +1,15 @@ /*------------------------------------------------------------------------- * - * bbstreamer_zstd.c + * astreamer_zstd.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Archive streamers that deal with data compressed using zstd. + * astreamer_zstd_compressor applies lz4 compression to the input stream, + * and astreamer_zstd_decompressor does the reverse. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION - * src/bin/pg_basebackup/bbstreamer_zstd.c + * src/fe_utils/astreamer_zstd.c *------------------------------------------------------------------------- */ @@ -17,44 +21,44 @@ #include #endif -#include "bbstreamer.h" #include "common/logging.h" +#include "fe_utils/astreamer.h" #ifdef USE_ZSTD -typedef struct bbstreamer_zstd_frame +typedef struct astreamer_zstd_frame { - bbstreamer base; + astreamer base; ZSTD_CCtx *cctx; ZSTD_DCtx *dctx; ZSTD_outBuffer zstd_outBuf; -} bbstreamer_zstd_frame; - -static void bbstreamer_zstd_compressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_zstd_compressor_finalize(bbstreamer *streamer); -static void bbstreamer_zstd_compressor_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_zstd_compressor_ops = { - .content = bbstreamer_zstd_compressor_content, - .finalize = bbstreamer_zstd_compressor_finalize, - .free = bbstreamer_zstd_compressor_free +} astreamer_zstd_frame; + +static void astreamer_zstd_compressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_zstd_compressor_finalize(astreamer *streamer); +static void astreamer_zstd_compressor_free(astreamer *streamer); + +static const astreamer_ops astreamer_zstd_compressor_ops = { + .content = astreamer_zstd_compressor_content, + .finalize = astreamer_zstd_compressor_finalize, + .free = astreamer_zstd_compressor_free }; -static void bbstreamer_zstd_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context); -static void bbstreamer_zstd_decompressor_finalize(bbstreamer *streamer); -static void bbstreamer_zstd_decompressor_free(bbstreamer *streamer); - -static const bbstreamer_ops bbstreamer_zstd_decompressor_ops = { - .content = bbstreamer_zstd_decompressor_content, - .finalize = bbstreamer_zstd_decompressor_finalize, - .free = bbstreamer_zstd_decompressor_free +static void astreamer_zstd_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); +static void astreamer_zstd_decompressor_finalize(astreamer *streamer); +static void astreamer_zstd_decompressor_free(astreamer *streamer); + +static const astreamer_ops astreamer_zstd_decompressor_ops = { + .content = astreamer_zstd_decompressor_content, + .finalize = astreamer_zstd_decompressor_finalize, + .free = astreamer_zstd_decompressor_free }; #endif @@ -62,19 +66,19 @@ static const bbstreamer_ops bbstreamer_zstd_decompressor_ops = { * Create a new base backup streamer that performs zstd compression of tar * blocks. */ -bbstreamer * -bbstreamer_zstd_compressor_new(bbstreamer *next, pg_compress_specification *compress) +astreamer * +astreamer_zstd_compressor_new(astreamer *next, pg_compress_specification *compress) { #ifdef USE_ZSTD - bbstreamer_zstd_frame *streamer; + astreamer_zstd_frame *streamer; size_t ret; Assert(next != NULL); - streamer = palloc0(sizeof(bbstreamer_zstd_frame)); + streamer = palloc0(sizeof(astreamer_zstd_frame)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_zstd_compressor_ops; + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_zstd_compressor_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); @@ -142,12 +146,12 @@ bbstreamer_zstd_compressor_new(bbstreamer *next, pg_compress_specification *comp * of output buffer to next streamer and empty the buffer. */ static void -bbstreamer_zstd_compressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_zstd_compressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; ZSTD_inBuffer inBuf = {data, len, 0}; while (inBuf.pos < inBuf.size) @@ -162,10 +166,10 @@ bbstreamer_zstd_compressor_content(bbstreamer *streamer, if (mystreamer->zstd_outBuf.size - mystreamer->zstd_outBuf.pos < max_needed) { - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->zstd_outBuf.dst, - mystreamer->zstd_outBuf.pos, - context); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->zstd_outBuf.dst, + mystreamer->zstd_outBuf.pos, + context); /* Reset the ZSTD output buffer. */ mystreamer->zstd_outBuf.dst = mystreamer->base.bbs_buffer.data; @@ -187,9 +191,9 @@ bbstreamer_zstd_compressor_content(bbstreamer *streamer, * End-of-stream processing. */ static void -bbstreamer_zstd_compressor_finalize(bbstreamer *streamer) +astreamer_zstd_compressor_finalize(astreamer *streamer) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; size_t yet_to_flush; do @@ -204,10 +208,10 @@ bbstreamer_zstd_compressor_finalize(bbstreamer *streamer) if (mystreamer->zstd_outBuf.size - mystreamer->zstd_outBuf.pos < max_needed) { - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->zstd_outBuf.dst, - mystreamer->zstd_outBuf.pos, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->zstd_outBuf.dst, + mystreamer->zstd_outBuf.pos, + ASTREAMER_UNKNOWN); /* Reset the ZSTD output buffer. */ mystreamer->zstd_outBuf.dst = mystreamer->base.bbs_buffer.data; @@ -227,23 +231,23 @@ bbstreamer_zstd_compressor_finalize(bbstreamer *streamer) /* Make sure to pass any remaining bytes to the next streamer. */ if (mystreamer->zstd_outBuf.pos > 0) - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->zstd_outBuf.dst, - mystreamer->zstd_outBuf.pos, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->zstd_outBuf.dst, + mystreamer->zstd_outBuf.pos, + ASTREAMER_UNKNOWN); - bbstreamer_finalize(mystreamer->base.bbs_next); + astreamer_finalize(mystreamer->base.bbs_next); } /* * Free memory. */ static void -bbstreamer_zstd_compressor_free(bbstreamer *streamer) +astreamer_zstd_compressor_free(astreamer *streamer) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); ZSTD_freeCCtx(mystreamer->cctx); pfree(streamer->bbs_buffer.data); pfree(streamer); @@ -254,17 +258,17 @@ bbstreamer_zstd_compressor_free(bbstreamer *streamer) * Create a new base backup streamer that performs decompression of zstd * compressed blocks. */ -bbstreamer * -bbstreamer_zstd_decompressor_new(bbstreamer *next) +astreamer * +astreamer_zstd_decompressor_new(astreamer *next) { #ifdef USE_ZSTD - bbstreamer_zstd_frame *streamer; + astreamer_zstd_frame *streamer; Assert(next != NULL); - streamer = palloc0(sizeof(bbstreamer_zstd_frame)); - *((const bbstreamer_ops **) &streamer->base.bbs_ops) = - &bbstreamer_zstd_decompressor_ops; + streamer = palloc0(sizeof(astreamer_zstd_frame)); + *((const astreamer_ops **) &streamer->base.bbs_ops) = + &astreamer_zstd_decompressor_ops; streamer->base.bbs_next = next; initStringInfo(&streamer->base.bbs_buffer); @@ -293,12 +297,12 @@ bbstreamer_zstd_decompressor_new(bbstreamer *next) * to the next streamer. */ static void -bbstreamer_zstd_decompressor_content(bbstreamer *streamer, - bbstreamer_member *member, - const char *data, int len, - bbstreamer_archive_context context) +astreamer_zstd_decompressor_content(astreamer *streamer, + astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; ZSTD_inBuffer inBuf = {data, len, 0}; while (inBuf.pos < inBuf.size) @@ -311,10 +315,10 @@ bbstreamer_zstd_decompressor_content(bbstreamer *streamer, */ if (mystreamer->zstd_outBuf.pos >= mystreamer->zstd_outBuf.size) { - bbstreamer_content(mystreamer->base.bbs_next, member, - mystreamer->zstd_outBuf.dst, - mystreamer->zstd_outBuf.pos, - context); + astreamer_content(mystreamer->base.bbs_next, member, + mystreamer->zstd_outBuf.dst, + mystreamer->zstd_outBuf.pos, + context); /* Reset the ZSTD output buffer. */ mystreamer->zstd_outBuf.dst = mystreamer->base.bbs_buffer.data; @@ -335,32 +339,32 @@ bbstreamer_zstd_decompressor_content(bbstreamer *streamer, * End-of-stream processing. */ static void -bbstreamer_zstd_decompressor_finalize(bbstreamer *streamer) +astreamer_zstd_decompressor_finalize(astreamer *streamer) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; /* * End of the stream, if there is some pending data in output buffers then * we must forward it to next streamer. */ if (mystreamer->zstd_outBuf.pos > 0) - bbstreamer_content(mystreamer->base.bbs_next, NULL, - mystreamer->base.bbs_buffer.data, - mystreamer->base.bbs_buffer.maxlen, - BBSTREAMER_UNKNOWN); + astreamer_content(mystreamer->base.bbs_next, NULL, + mystreamer->base.bbs_buffer.data, + mystreamer->base.bbs_buffer.maxlen, + ASTREAMER_UNKNOWN); - bbstreamer_finalize(mystreamer->base.bbs_next); + astreamer_finalize(mystreamer->base.bbs_next); } /* * Free memory. */ static void -bbstreamer_zstd_decompressor_free(bbstreamer *streamer) +astreamer_zstd_decompressor_free(astreamer *streamer) { - bbstreamer_zstd_frame *mystreamer = (bbstreamer_zstd_frame *) streamer; + astreamer_zstd_frame *mystreamer = (astreamer_zstd_frame *) streamer; - bbstreamer_free(streamer->bbs_next); + astreamer_free(streamer->bbs_next); ZSTD_freeDCtx(mystreamer->dctx); pfree(streamer->bbs_buffer.data); pfree(streamer); diff --git a/src/fe_utils/cancel.c b/src/fe_utils/cancel.c index dcff9a8564184..f434718eac802 100644 --- a/src/fe_utils/cancel.c +++ b/src/fe_utils/cancel.c @@ -6,7 +6,7 @@ * handler for SIGINT. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/cancel.c diff --git a/src/fe_utils/conditional.c b/src/fe_utils/conditional.c index d9109cf1e98c8..9e1ad687f08c8 100644 --- a/src/fe_utils/conditional.c +++ b/src/fe_utils/conditional.c @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * A stack of automaton states to handle nested conditionals. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/fe_utils/conditional.c * diff --git a/src/fe_utils/connect_utils.c b/src/fe_utils/connect_utils.c index 5ed9f3ba17b78..cda1c11099789 100644 --- a/src/fe_utils/connect_utils.c +++ b/src/fe_utils/connect_utils.c @@ -2,7 +2,7 @@ * * Facilities for frontend code to connect to and disconnect from databases. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/connect_utils.c diff --git a/src/fe_utils/mbprint.c b/src/fe_utils/mbprint.c index 5ad469f5ddd1e..eb3eeee9925cb 100644 --- a/src/fe_utils/mbprint.c +++ b/src/fe_utils/mbprint.c @@ -3,7 +3,7 @@ * Multibyte character printing support for frontend code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/mbprint.c diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build index 14d0482a2cc7a..a18cbc939e412 100644 --- a/src/fe_utils/meson.build +++ b/src/fe_utils/meson.build @@ -1,7 +1,12 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group fe_utils_sources = files( 'archive.c', + 'astreamer_file.c', + 'astreamer_gzip.c', + 'astreamer_lz4.c', + 'astreamer_tar.c', + 'astreamer_zstd.c', 'cancel.c', 'conditional.c', 'connect_utils.c', @@ -18,7 +23,7 @@ fe_utils_sources = files( psqlscan = custom_target('psqlscan', input: 'psqlscan.l', output: 'psqlscan.c', - command: [flex_cmd, '--no-backup', '--fix-warnings', '--', '-Cfe', '-p', '-p'], + command: [flex_cmd, '--no-backup', '--', '-Cfe', '-p', '-p'], ) generated_sources += psqlscan fe_utils_sources += psqlscan diff --git a/src/fe_utils/option_utils.c b/src/fe_utils/option_utils.c index 7828ae2b2f2b2..6cb4ac7ffeb06 100644 --- a/src/fe_utils/option_utils.c +++ b/src/fe_utils/option_utils.c @@ -2,7 +2,7 @@ * * Command line option processing facilities for frontend code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/option_utils.c diff --git a/src/fe_utils/parallel_slot.c b/src/fe_utils/parallel_slot.c index ce539699c3d02..253a840865e87 100644 --- a/src/fe_utils/parallel_slot.c +++ b/src/fe_utils/parallel_slot.c @@ -4,7 +4,7 @@ * Parallel support for front-end parallel database connections * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/parallel_slot.c @@ -347,11 +347,11 @@ connect_slot(ParallelSlotArray *sa, int slotno, const char *dbname) * returned allowing the connection to be reused. * * Otherwise, if any idle slot is not yet connected to any database, the slot - * will be returned with it's connection opened using the stored cparams and + * will be returned with its connection opened using the stored cparams and * optionally the given dbname if not null. * * Otherwise, if any idle slot exists, an idle slot will be chosen and returned - * after having it's connection disconnected and reconnected using the stored + * after having its connection disconnected and reconnected using the stored * cparams and optionally the given dbname if not null. * * Otherwise, if any slots have connections that are busy, we loop on select() diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c index d6c4d78f98161..4af0f32f2fc05 100644 --- a/src/fe_utils/print.c +++ b/src/fe_utils/print.c @@ -8,7 +8,7 @@ * pager open/close functions, all that stuff came with it. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/print.c @@ -3185,9 +3185,9 @@ printTableInit(printTableContent *const content, const printTableOpt *opt, /* Catch possible overflow. Using >= here allows adding 1 below */ if (total_cells >= SIZE_MAX / sizeof(*content->cells)) { - fprintf(stderr, _("Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n"), - (long long int) total_cells, - (long long int) (SIZE_MAX / sizeof(*content->cells))); + fprintf(stderr, _("Cannot print table contents: number of cells %" PRIu64 " is equal to or exceeds maximum %zu.\n"), + total_cells, + SIZE_MAX / sizeof(*content->cells)); exit(EXIT_FAILURE); } content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells)); @@ -3269,8 +3269,8 @@ printTableAddCell(printTableContent *const content, char *cell, total_cells = (uint64) content->ncolumns * content->nrows; if (content->cellsadded >= total_cells) { - fprintf(stderr, _("Cannot add cell to table content: total cell count of %lld exceeded.\n"), - (long long int) total_cells); + fprintf(stderr, _("Cannot add cell to table content: total cell count of %" PRIu64 " exceeded.\n"), + total_cells); exit(EXIT_FAILURE); } diff --git a/src/fe_utils/psqlscan.l b/src/fe_utils/psqlscan.l index ddc4658b9256c..fc5bfa597bb92 100644 --- a/src/fe_utils/psqlscan.l +++ b/src/fe_utils/psqlscan.l @@ -24,7 +24,7 @@ * See psqlscan_int.h for additional commentary. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -52,12 +52,6 @@ */ typedef int YYSTYPE; -/* - * Set the type of yyextra; we use it as a pointer back to the containing - * PsqlScanState. - */ -#define YY_EXTRA_TYPE PsqlScanState - /* Return values from yylex() */ #define LEXRES_EOL 0 /* end of input */ @@ -67,15 +61,6 @@ typedef int YYSTYPE; #define ECHO psqlscan_emit(cur_state, yytext, yyleng) -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int psql_yyget_column(yyscan_t yyscanner); -extern void psql_yyset_column(int column_no, yyscan_t yyscanner); - %} %option reentrant @@ -89,6 +74,12 @@ extern void psql_yyset_column(int column_no, yyscan_t yyscanner); %option warn %option prefix="psql_yy" +/* + * Set the type of yyextra; we use it as a pointer back to the containing + * PsqlScanState. + */ +%option extra-type="PsqlScanState" + /* * All of the following definitions and rules should exactly match * src/backend/parser/scan.l so far as the flex patterns are concerned. @@ -348,16 +339,30 @@ numericfail {decinteger}\.\. real ({decinteger}|{numeric})[Ee][-+]?{decinteger} realfail ({decinteger}|{numeric})[Ee][-+] -decinteger_junk {decinteger}{ident_start} -hexinteger_junk {hexinteger}{ident_start} -octinteger_junk {octinteger}{ident_start} -bininteger_junk {bininteger}{ident_start} -numeric_junk {numeric}{ident_start} -real_junk {real}{ident_start} - /* Positional parameters don't accept underscores. */ param \${decdigit}+ -param_junk \${decdigit}+{ident_start} + +/* + * An identifier immediately following an integer literal is disallowed because + * in some cases it's ambiguous what is meant: for example, 0x1234 could be + * either a hexinteger or a decinteger "0" and an identifier "x1234". We can + * detect such problems by seeing if integer_junk matches a longer substring + * than any of the XXXinteger patterns (decinteger, hexinteger, octinteger, + * bininteger). One "junk" pattern is sufficient because + * {decinteger}{identifier} will match all the same strings we'd match with + * {hexinteger}{identifier} etc. + * + * Note that the rule for integer_junk must appear after the ones for + * XXXinteger to make this work correctly: 0x1234 will match both hexinteger + * and integer_junk, and we need hexinteger to be chosen in that case. + * + * Also disallow strings matched by numeric_junk, real_junk and param_junk + * for consistency. + */ +integer_junk {decinteger}{identifier} +numeric_junk {numeric}{identifier} +real_junk {real}{identifier} +param_junk \${decdigit}+{identifier} /* psql-specific: characters allowed in variable names */ variable_char [A-Za-z\200-\377_0-9] @@ -898,16 +903,7 @@ other . {realfail} { ECHO; } -{decinteger_junk} { - ECHO; - } -{hexinteger_junk} { - ECHO; - } -{octinteger_junk} { - ECHO; - } -{bininteger_junk} { +{integer_junk} { ECHO; } {numeric_junk} { @@ -1083,6 +1079,10 @@ psql_scan_setup(PsqlScanState state, /* Set lookaside data in case we have to map unsafe encoding */ state->curline = state->scanbuf; state->refline = state->scanline; + + /* Initialize state for psql_scan_get_location() */ + state->cur_line_no = 0; /* yylex not called yet */ + state->cur_line_ptr = state->scanbuf; } /* @@ -1140,6 +1140,10 @@ psql_scan(PsqlScanState state, /* And lex. */ lexresult = yylex(NULL, state->scanner); + /* Notify psql_scan_get_location() that a yylex call has been made. */ + if (state->cur_line_no == 0) + state->cur_line_no = 1; + /* * Check termination state and return appropriate result info. */ @@ -1312,7 +1316,53 @@ bool psql_scan_in_quote(PsqlScanState state) { return state->start_state != INITIAL && - state->start_state != xqs; + state->start_state != xqs; +} + +/* + * Return the current scanning location (end+1 of last scanned token), + * as a line number counted from 1 and an offset from string start. + * + * This considers only the outermost input string, and therefore is of + * limited use for programs that use psqlscan_push_new_buffer(). + * + * It would be a bit easier probably to use "%option yylineno" to count + * lines, but the flex manual says that has a performance cost, and only + * a minority of programs using psqlscan have need for this functionality. + * So we implement it ourselves without adding overhead to the lexer itself. + */ +void +psql_scan_get_location(PsqlScanState state, + int *lineno, int *offset) +{ + const char *line_end; + + /* + * We rely on flex's having stored a NUL after the current token in + * scanbuf. Therefore we must specially handle the state before yylex() + * has been called, when obviously that won't have happened yet. + */ + if (state->cur_line_no == 0) + { + *lineno = 1; + *offset = 0; + return; + } + + /* + * Advance cur_line_no/cur_line_ptr past whatever has been lexed so far. + * Doing this prevents repeated calls from being O(N^2) for long inputs. + */ + while ((line_end = strchr(state->cur_line_ptr, '\n')) != NULL) + { + state->cur_line_no++; + state->cur_line_ptr = line_end + 1; + } + state->cur_line_ptr += strlen(state->cur_line_ptr); + + /* Report current location. */ + *lineno = state->cur_line_no; + *offset = state->cur_line_ptr - state->scanbuf; } /* @@ -1563,8 +1613,8 @@ psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, void psqlscan_test_variable(PsqlScanState state, const char *txt, int len) { - char *varname; - char *value; + char *varname; + char *value; varname = psqlscan_extract_substring(state, txt + 3, len - 4); if (state->callbacks->get_variable) @@ -1576,11 +1626,11 @@ psqlscan_test_variable(PsqlScanState state, const char *txt, int len) if (value != NULL) { - psqlscan_emit(state, "TRUE", 4); + appendPQExpBufferStr(state->output_buf, "TRUE"); free(value); } else { - psqlscan_emit(state, "FALSE", 5); + appendPQExpBufferStr(state->output_buf, "FALSE"); } } diff --git a/src/fe_utils/query_utils.c b/src/fe_utils/query_utils.c index 4970c4575da85..1fa727a81c853 100644 --- a/src/fe_utils/query_utils.c +++ b/src/fe_utils/query_utils.c @@ -2,7 +2,7 @@ * * Facilities for frontend code to query a databases. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/query_utils.c diff --git a/src/fe_utils/recovery_gen.c b/src/fe_utils/recovery_gen.c index c4838a4bddce1..e9023584768d5 100644 --- a/src/fe_utils/recovery_gen.c +++ b/src/fe_utils/recovery_gen.c @@ -3,7 +3,7 @@ * recovery_gen.c * Generator for recovery configuration * - * Portions Copyright (c) 2011-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2011-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -14,6 +14,7 @@ #include "fe_utils/string_utils.h" static char *escape_quotes(const char *src); +static char *FindDbnameInConnOpts(PQconninfoOption *conn_opts); /* * Write recovery configuration contents into a fresh PQExpBuffer, and @@ -168,3 +169,68 @@ escape_quotes(const char *src) pg_fatal("out of memory"); return result; } + +/* + * FindDbnameInConnOpts + * + * This is a helper function for GetDbnameFromConnectionOptions(). Extract + * the value of dbname from PQconninfoOption parameters, if it's present. + * Returns a strdup'd result or NULL. + */ +static char * +FindDbnameInConnOpts(PQconninfoOption *conn_opts) +{ + for (PQconninfoOption *conn_opt = conn_opts; + conn_opt->keyword != NULL; + conn_opt++) + { + if (strcmp(conn_opt->keyword, "dbname") == 0 && + conn_opt->val != NULL && conn_opt->val[0] != '\0') + return pg_strdup(conn_opt->val); + } + return NULL; +} + +/* + * GetDbnameFromConnectionOptions + * + * This is a special purpose function to retrieve the dbname from either the + * 'connstr' specified by the caller or from the environment variables. + * + * Returns NULL, if dbname is not specified by the user in the given + * connection options. + */ +char * +GetDbnameFromConnectionOptions(const char *connstr) +{ + PQconninfoOption *conn_opts; + char *err_msg = NULL; + char *dbname; + + /* First try to get the dbname from connection string. */ + if (connstr) + { + conn_opts = PQconninfoParse(connstr, &err_msg); + if (conn_opts == NULL) + pg_fatal("%s", err_msg); + + dbname = FindDbnameInConnOpts(conn_opts); + + PQconninfoFree(conn_opts); + if (dbname) + return dbname; + } + + /* + * Next try to get the dbname from default values that are available from + * the environment. + */ + conn_opts = PQconndefaults(); + if (conn_opts == NULL) + pg_fatal("out of memory"); + + dbname = FindDbnameInConnOpts(conn_opts); + + PQconninfoFree(conn_opts); + return dbname; +} diff --git a/src/fe_utils/simple_list.c b/src/fe_utils/simple_list.c index 2d88eb540677a..483d5455594b3 100644 --- a/src/fe_utils/simple_list.c +++ b/src/fe_utils/simple_list.c @@ -7,7 +7,7 @@ * it's all we need in, eg, pg_dump. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/simple_list.c @@ -173,3 +173,22 @@ simple_ptr_list_append(SimplePtrList *list, void *ptr) list->head = cell; list->tail = cell; } + +/* + * Destroy only pointer list and not the pointed-to element + */ +void +simple_ptr_list_destroy(SimplePtrList *list) +{ + SimplePtrListCell *cell; + + cell = list->head; + while (cell != NULL) + { + SimplePtrListCell *next; + + next = cell->next; + pg_free(cell); + cell = next; + } +} diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c index 09fd33907ddc8..130d1020d504d 100644 --- a/src/fe_utils/string_utils.c +++ b/src/fe_utils/string_utils.c @@ -6,7 +6,7 @@ * and interpreting backend output. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/fe_utils/string_utils.c @@ -19,6 +19,7 @@ #include "common/keywords.h" #include "fe_utils/string_utils.h" +#include "mb/pg_wchar.h" static PQExpBuffer defaultGetLocalPQExpBuffer(void); @@ -26,6 +27,8 @@ static PQExpBuffer defaultGetLocalPQExpBuffer(void); int quote_all_identifiers = 0; PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer; +static int fmtIdEncoding = -1; + /* * Returns a temporary PQExpBuffer, valid until the next call to the function. @@ -54,19 +57,54 @@ defaultGetLocalPQExpBuffer(void) return id_return; } +/* + * Set the encoding that fmtId() and fmtQualifiedId() use. + * + * This is not safe against multiple connections having different encodings, + * but there is no real other way to address the need to know the encoding for + * fmtId()/fmtQualifiedId() input for safe escaping. Eventually we should get + * rid of fmtId(). + */ +void +setFmtEncoding(int encoding) +{ + fmtIdEncoding = encoding; +} + +/* + * Return the currently configured encoding for fmtId() and fmtQualifiedId(). + */ +static int +getFmtEncoding(void) +{ + if (fmtIdEncoding != -1) + return fmtIdEncoding; + + /* + * In assertion builds it seems best to fail hard if the encoding was not + * set, to make it easier to find places with missing calls. But in + * production builds that seems like a bad idea, thus we instead just + * default to UTF-8. + */ + Assert(fmtIdEncoding != -1); + + return PG_UTF8; +} + /* * Quotes input string if it's not a legitimate SQL identifier as-is. * - * Note that the returned string must be used before calling fmtId again, + * Note that the returned string must be used before calling fmtIdEnc again, * since we re-use the same return buffer each time. */ const char * -fmtId(const char *rawid) +fmtIdEnc(const char *rawid, int encoding) { PQExpBuffer id_return = getLocalPQExpBuffer(); const char *cp; bool need_quotes = false; + size_t remaining = strlen(rawid); /* * These checks need to match the identifier production in scan.l. Don't @@ -80,7 +118,8 @@ fmtId(const char *rawid) else { /* otherwise check the entire string */ - for (cp = rawid; *cp; cp++) + cp = rawid; + for (size_t i = 0; i < remaining; i++, cp++) { if (!((*cp >= 'a' && *cp <= 'z') || (*cp >= '0' && *cp <= '9') @@ -116,17 +155,79 @@ fmtId(const char *rawid) else { appendPQExpBufferChar(id_return, '"'); - for (cp = rawid; *cp; cp++) + + cp = &rawid[0]; + while (remaining > 0) { - /* - * Did we find a double-quote in the string? Then make this a - * double double-quote per SQL99. Before, we put in a - * backslash/double-quote pair. - thomas 2000-08-05 - */ - if (*cp == '"') - appendPQExpBufferChar(id_return, '"'); - appendPQExpBufferChar(id_return, *cp); + int charlen; + + /* Fast path for plain ASCII */ + if (!IS_HIGHBIT_SET(*cp)) + { + /* + * Did we find a double-quote in the string? Then make this a + * double double-quote per SQL99. Before, we put in a + * backslash/double-quote pair. - thomas 2000-08-05 + */ + if (*cp == '"') + appendPQExpBufferChar(id_return, '"'); + appendPQExpBufferChar(id_return, *cp); + remaining--; + cp++; + continue; + } + + /* Slow path for possible multibyte characters */ + charlen = pg_encoding_mblen(encoding, cp); + + if (remaining < charlen || + pg_encoding_verifymbchar(encoding, cp, charlen) == -1) + { + /* + * Multibyte character is invalid. It's important to verify + * that as invalid multibyte characters could e.g. be used to + * "skip" over quote characters, e.g. when parsing + * character-by-character. + * + * Replace the character's first byte with an invalid + * sequence. The invalid sequence ensures that the escaped + * string will trigger an error on the server-side, even if we + * can't directly report an error here. + * + * It would be a bit faster to verify the whole string the + * first time we encounter a set highbit, but this way we can + * replace just the invalid data, which probably makes it + * easier for users to find the invalidly encoded portion of a + * larger string. + */ + if (enlargePQExpBuffer(id_return, 2)) + { + pg_encoding_set_invalid(encoding, + id_return->data + id_return->len); + id_return->len += 2; + id_return->data[id_return->len] = '\0'; + } + + /* + * Handle the following bytes as if this byte didn't exist. + * That's safer in case the subsequent bytes contain + * characters that are significant for the caller (e.g. '>' in + * html). + */ + remaining--; + cp++; + } + else + { + for (int i = 0; i < charlen; i++) + { + appendPQExpBufferChar(id_return, *cp); + remaining--; + cp++; + } + } } + appendPQExpBufferChar(id_return, '"'); } @@ -134,7 +235,24 @@ fmtId(const char *rawid) } /* - * fmtQualifiedId - construct a schema-qualified name, with quoting as needed. + * Quotes input string if it's not a legitimate SQL identifier as-is. + * + * Note that the returned string must be used before calling fmtId again, + * since we re-use the same return buffer each time. + * + * NB: This assumes setFmtEncoding() previously has been called to configure + * the encoding of rawid. It is preferable to use fmtIdEnc() with an + * explicit encoding. + */ +const char * +fmtId(const char *rawid) +{ + return fmtIdEnc(rawid, getFmtEncoding()); +} + +/* + * fmtQualifiedIdEnc - construct a schema-qualified name, with quoting as + * needed. * * Like fmtId, use the result before calling again. * @@ -142,7 +260,7 @@ fmtId(const char *rawid) * use that buffer until we're finished with calling fmtId(). */ const char * -fmtQualifiedId(const char *schema, const char *id) +fmtQualifiedIdEnc(const char *schema, const char *id, int encoding) { PQExpBuffer id_return; PQExpBuffer lcl_pqexp = createPQExpBuffer(); @@ -150,9 +268,9 @@ fmtQualifiedId(const char *schema, const char *id) /* Some callers might fail to provide a schema name */ if (schema && *schema) { - appendPQExpBuffer(lcl_pqexp, "%s.", fmtId(schema)); + appendPQExpBuffer(lcl_pqexp, "%s.", fmtIdEnc(schema, encoding)); } - appendPQExpBufferStr(lcl_pqexp, fmtId(id)); + appendPQExpBufferStr(lcl_pqexp, fmtIdEnc(id, encoding)); id_return = getLocalPQExpBuffer(); @@ -162,6 +280,24 @@ fmtQualifiedId(const char *schema, const char *id) return id_return->data; } +/* + * fmtQualifiedId - construct a schema-qualified name, with quoting as needed. + * + * Like fmtId, use the result before calling again. + * + * Since we call fmtId and it also uses getLocalPQExpBuffer() we cannot + * use that buffer until we're finished with calling fmtId(). + * + * NB: This assumes setFmtEncoding() previously has been called to configure + * the encoding of schema/id. It is preferable to use fmtQualifiedIdEnc() + * with an explicit encoding. + */ +const char * +fmtQualifiedId(const char *schema, const char *id) +{ + return fmtQualifiedIdEnc(schema, id, getFmtEncoding()); +} + /* * Format a Postgres version number (in the PG_VERSION_NUM integer format @@ -218,6 +354,7 @@ appendStringLiteral(PQExpBuffer buf, const char *str, size_t length = strlen(str); const char *source = str; char *target; + size_t remaining = length; if (!enlargePQExpBuffer(buf, 2 * length + 2)) return; @@ -225,10 +362,10 @@ appendStringLiteral(PQExpBuffer buf, const char *str, target = buf->data + buf->len; *target++ = '\''; - while (*source != '\0') + while (remaining > 0) { char c = *source; - int len; + int charlen; int i; /* Fast path for plain ASCII */ @@ -240,39 +377,55 @@ appendStringLiteral(PQExpBuffer buf, const char *str, /* Copy the character */ *target++ = c; source++; + remaining--; continue; } /* Slow path for possible multibyte characters */ - len = PQmblen(source, encoding); + charlen = PQmblen(source, encoding); - /* Copy the character */ - for (i = 0; i < len; i++) + if (remaining < charlen || + pg_encoding_verifymbchar(encoding, source, charlen) == -1) { - if (*source == '\0') - break; - *target++ = *source++; - } + /* + * Multibyte character is invalid. It's important to verify that + * as invalid multibyte characters could e.g. be used to "skip" + * over quote characters, e.g. when parsing + * character-by-character. + * + * Replace the character's first byte with an invalid sequence. + * The invalid sequence ensures that the escaped string will + * trigger an error on the server-side, even if we can't directly + * report an error here. + * + * We know there's enough space for the invalid sequence because + * the "target" buffer is 2 * length + 2 long, and at worst we're + * replacing a single input byte with two invalid bytes. + * + * It would be a bit faster to verify the whole string the first + * time we encounter a set highbit, but this way we can replace + * just the invalid data, which probably makes it easier for users + * to find the invalidly encoded portion of a larger string. + */ + pg_encoding_set_invalid(encoding, target); + target += 2; - /* - * If we hit premature end of string (ie, incomplete multibyte - * character), try to pad out to the correct length with spaces. We - * may not be able to pad completely, but we will always be able to - * insert at least one pad space (since we'd not have quoted a - * multibyte character). This should be enough to make a string that - * the server will error out on. - */ - if (i < len) + /* + * Handle the following bytes as if this byte didn't exist. That's + * safer in case the subsequent bytes contain important characters + * for the caller (e.g. '>' in html). + */ + source++; + remaining--; + } + else { - char *stop = buf->data + buf->maxlen - 2; - - for (; i < len; i++) + /* Copy the character */ + for (i = 0; i < charlen; i++) { - if (target >= stop) - break; - *target++ = ' '; + *target++ = *source++; + remaining--; } - break; } } @@ -616,29 +769,38 @@ appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname) } } - appendPQExpBufferStr(buf, "\\connect "); if (complex) { PQExpBufferData connstr; initPQExpBuffer(&connstr); + + /* + * Force the target psql's encoding to SQL_ASCII. We don't really + * know the encoding of the database name, and it doesn't matter as + * long as psql will forward it to the server unchanged. + */ + appendPQExpBufferStr(buf, "\\encoding SQL_ASCII\n"); + appendPQExpBufferStr(buf, "\\connect -reuse-previous=on "); + appendPQExpBufferStr(&connstr, "dbname="); appendConnStrVal(&connstr, dbname); - appendPQExpBufferStr(buf, "-reuse-previous=on "); - /* * As long as the name does not contain a newline, SQL identifier * quoting satisfies the psql meta-command parser. Prefer not to * involve psql-interpreted single quotes, which behaved differently * before PostgreSQL 9.2. */ - appendPQExpBufferStr(buf, fmtId(connstr.data)); + appendPQExpBufferStr(buf, fmtIdEnc(connstr.data, PG_SQL_ASCII)); termPQExpBuffer(&connstr); } else - appendPQExpBufferStr(buf, fmtId(dbname)); + { + appendPQExpBufferStr(buf, "\\connect "); + appendPQExpBufferStr(buf, fmtIdEnc(dbname, PG_SQL_ASCII)); + } appendPQExpBufferChar(buf, '\n'); } diff --git a/src/include/.gitignore b/src/include/.gitignore index 51819fb4dddc9..6e99e82fe0c47 100644 --- a/src/include/.gitignore +++ b/src/include/.gitignore @@ -1,5 +1,3 @@ /stamp-h -/stamp-ext-h /pg_config.h -/pg_config_ext.h /pg_config_os.h diff --git a/src/include/Makefile b/src/include/Makefile index b8b576a4de3b7..3f94543f3270b 100644 --- a/src/include/Makefile +++ b/src/include/Makefile @@ -13,7 +13,7 @@ top_builddir = ../.. include $(top_builddir)/src/Makefile.global -all: pg_config.h pg_config_ext.h pg_config_os.h +all: pg_config.h pg_config_os.h # Subdirectories containing installable headers @@ -32,7 +32,6 @@ install: all installdirs $(INSTALL_DATA) $(srcdir)/postgres_ext.h '$(DESTDIR)$(includedir)' $(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq' $(INSTALL_DATA) pg_config.h '$(DESTDIR)$(includedir)' - $(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)' $(INSTALL_DATA) pg_config_os.h '$(DESTDIR)$(includedir)' $(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)' # These headers are needed by the not-so-public headers of the interfaces. @@ -43,7 +42,6 @@ install: all installdirs $(INSTALL_DATA) $(srcdir)/libpq/protocol.h '$(DESTDIR)$(includedir_internal)/libpq' # These headers are needed for server-side development $(INSTALL_DATA) pg_config.h '$(DESTDIR)$(includedir_server)' - $(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)' $(INSTALL_DATA) pg_config_os.h '$(DESTDIR)$(includedir_server)' $(INSTALL_DATA) nodes/nodetags.h '$(DESTDIR)$(includedir_server)/nodes' $(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils' @@ -66,7 +64,7 @@ installdirs: uninstall: - rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h) + rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h) rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h libpq/protocol.h) # heuristic... rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h) @@ -80,4 +78,4 @@ clean: $(MAKE) -C catalog clean distclean: clean - rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h + rm -f pg_config.h pg_config_os.h stamp-h diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index f25c9d58a7daa..52916bab7a31f 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -3,7 +3,7 @@ * amapi.h * API for Postgres index access methods. * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * src/include/access/amapi.h * @@ -12,7 +12,9 @@ #ifndef AMAPI_H #define AMAPI_H +#include "access/cmptype.h" #include "access/genam.h" +#include "access/stratnum.h" /* * We don't wish to include planner header files here, since most of an index @@ -76,6 +78,10 @@ typedef enum IndexAMProperty * opfamily. This allows ALTER OPERATOR FAMILY DROP, and causes that to * happen automatically if the operator or support func is dropped. This * is the right behavior for inessential ("loose") objects. + * + * We also make dependencies on lefttype/righttype, of the same strength as + * the dependency on the operator or support func, unless these dependencies + * are redundant with the dependency on the operator or support func. */ typedef struct OpFamilyMember { @@ -95,6 +101,12 @@ typedef struct OpFamilyMember * Callback function signatures --- see indexam.sgml for more info. */ +/* translate AM-specific strategies to general operator types */ +typedef CompareType (*amtranslate_strategy_function) (StrategyNumber strategy, Oid opfamily); + +/* translate general operator types to AM-specific strategies */ +typedef StrategyNumber (*amtranslate_cmptype_function) (CompareType cmptype, Oid opfamily); + /* build new index */ typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation, Relation indexRelation, @@ -140,6 +152,13 @@ typedef void (*amcostestimate_function) (struct PlannerInfo *root, double *indexCorrelation, double *indexPages); +/* estimate height of a tree-structured index + * + * XXX This just computes a value that is later used by amcostestimate. This + * API could be expanded to support passing more values if the need arises. + */ +typedef int (*amgettreeheight_function) (Relation rel); + /* parse index reloptions */ typedef bytea *(*amoptions_function) (Datum reloptions, bool validate); @@ -195,7 +214,8 @@ typedef void (*amrestrpos_function) (IndexScanDesc scan); */ /* estimate size of parallel scan descriptor */ -typedef Size (*amestimateparallelscan_function) (int nkeys, int norderbys); +typedef Size (*amestimateparallelscan_function) (Relation indexRelation, + int nkeys, int norderbys); /* prepare for parallel index scan */ typedef void (*aminitparallelscan_function) (void *target); @@ -224,6 +244,12 @@ typedef struct IndexAmRoutine bool amcanorder; /* does AM support ORDER BY result of an operator on indexed column? */ bool amcanorderbyop; + /* does AM support hashing using API consistent with the hash AM? */ + bool amcanhash; + /* do operators within an opfamily have consistent equality semantics? */ + bool amconsistentequality; + /* do operators within an opfamily have consistent ordering semantics? */ + bool amconsistentordering; /* does AM support backward scanning? */ bool amcanbackward; /* does AM support UNIQUE indexes? */ @@ -272,6 +298,7 @@ typedef struct IndexAmRoutine amvacuumcleanup_function amvacuumcleanup; amcanreturn_function amcanreturn; /* can be NULL */ amcostestimate_function amcostestimate; + amgettreeheight_function amgettreeheight; /* can be NULL */ amoptions_function amoptions; amproperty_function amproperty; /* can be NULL */ ambuildphasename_function ambuildphasename; /* can be NULL */ @@ -289,11 +316,17 @@ typedef struct IndexAmRoutine amestimateparallelscan_function amestimateparallelscan; /* can be NULL */ aminitparallelscan_function aminitparallelscan; /* can be NULL */ amparallelrescan_function amparallelrescan; /* can be NULL */ + + /* interface functions to support planning */ + amtranslate_strategy_function amtranslatestrategy; /* can be NULL */ + amtranslate_cmptype_function amtranslatecmptype; /* can be NULL */ } IndexAmRoutine; /* Functions in access/index/amapi.c */ extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler); extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror); +extern CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok); +extern StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok); #endif /* AMAPI_H */ diff --git a/src/include/access/amvalidate.h b/src/include/access/amvalidate.h index 424ab63fa5ac0..43b1692b07937 100644 --- a/src/include/access/amvalidate.h +++ b/src/include/access/amvalidate.h @@ -4,7 +4,7 @@ * Support routines for index access methods' amvalidate and * amadjustmembers functions. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/access/amvalidate.h * diff --git a/src/include/access/attmap.h b/src/include/access/attmap.h index 123ec45c1390c..8f9218826c992 100644 --- a/src/include/access/attmap.h +++ b/src/include/access/attmap.h @@ -4,7 +4,7 @@ * Definitions for PostgreSQL attribute mappings * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/attmap.h diff --git a/src/include/access/attnum.h b/src/include/access/attnum.h index 0c17e33b1437a..06c91672018be 100644 --- a/src/include/access/attnum.h +++ b/src/include/access/attnum.h @@ -4,7 +4,7 @@ * POSTGRES attribute number definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/attnum.h diff --git a/src/include/access/brin.h b/src/include/access/brin.h index 1c786281dd9f1..821f1e02806d8 100644 --- a/src/include/access/brin.h +++ b/src/include/access/brin.h @@ -1,7 +1,7 @@ /* * AM-callable functions for BRIN indexes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h index a5a9772621c7f..d093a0bf1307a 100644 --- a/src/include/access/brin_internal.h +++ b/src/include/access/brin_internal.h @@ -2,7 +2,7 @@ * brin_internal.h * internal declarations for BRIN indexes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_page.h b/src/include/access/brin_page.h index 70b141c25ec1d..06742a3c6dd7b 100644 --- a/src/include/access/brin_page.h +++ b/src/include/access/brin_page.h @@ -2,7 +2,7 @@ * brin_page.h * Prototypes and definitions for BRIN page layouts * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_pageops.h b/src/include/access/brin_pageops.h index 9b6230993b279..be343767027fb 100644 --- a/src/include/access/brin_pageops.h +++ b/src/include/access/brin_pageops.h @@ -2,7 +2,7 @@ * brin_pageops.h * Prototypes for operating on BRIN pages. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_revmap.h b/src/include/access/brin_revmap.h index 62e97965194d2..b88473c9860db 100644 --- a/src/include/access/brin_revmap.h +++ b/src/include/access/brin_revmap.h @@ -2,7 +2,7 @@ * brin_revmap.h * Prototypes for BRIN reverse range maps * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_tuple.h b/src/include/access/brin_tuple.h index c8850fd6c0824..010ba4ea3c0ee 100644 --- a/src/include/access/brin_tuple.h +++ b/src/include/access/brin_tuple.h @@ -2,7 +2,7 @@ * brin_tuple.h * Declarations for dealing with BRIN-specific tuples. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/brin_xlog.h b/src/include/access/brin_xlog.h index 34719344f7c28..992b057f4600a 100644 --- a/src/include/access/brin_xlog.h +++ b/src/include/access/brin_xlog.h @@ -4,7 +4,7 @@ * POSTGRES BRIN access XLOG definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/brin_xlog.h diff --git a/src/include/access/bufmask.h b/src/include/access/bufmask.h index 83174d1ef0fd9..b6632cf62732f 100644 --- a/src/include/access/bufmask.h +++ b/src/include/access/bufmask.h @@ -7,7 +7,7 @@ * individual rmgr, but we make things easier by providing some * common routines to handle cases which occur in multiple rmgrs. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/access/bufmask.h * diff --git a/src/include/access/clog.h b/src/include/access/clog.h index 8e62917e498a4..7eb3ffede4c1f 100644 --- a/src/include/access/clog.h +++ b/src/include/access/clog.h @@ -3,7 +3,7 @@ * * PostgreSQL transaction-commit-log manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/clog.h diff --git a/src/include/access/cmptype.h b/src/include/access/cmptype.h new file mode 100644 index 0000000000000..ed6da1eada12b --- /dev/null +++ b/src/include/access/cmptype.h @@ -0,0 +1,44 @@ +/*------------------------------------------------------------------------- + * + * cmptype.h + * POSTGRES compare type definitions. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/access/cmptype.h + * + *------------------------------------------------------------------------- + */ +#ifndef CMPTYPE_H +#define CMPTYPE_H + +/* + * CompareType - fundamental semantics of certain operators + * + * These enum symbols represent the fundamental semantics of certain operators + * that the system needs to have some hardcoded knowledge about. (For + * example, RowCompareExpr needs to know which operators can be determined to + * act like =, <>, <, etc.) Index access methods map (some of) strategy + * numbers to these values so that the system can know about the meaning of + * (some of) the operators without needing hardcoded knowledge of index AM's + * strategy numbering. + * + * XXX Currently, this mapping is not fully developed and most values are + * chosen to match btree strategy numbers, which is not going to work very + * well for other access methods. + */ +typedef enum CompareType +{ + COMPARE_INVALID = 0, + COMPARE_LT = 1, /* BTLessStrategyNumber */ + COMPARE_LE = 2, /* BTLessEqualStrategyNumber */ + COMPARE_EQ = 3, /* BTEqualStrategyNumber */ + COMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */ + COMPARE_GT = 5, /* BTGreaterStrategyNumber */ + COMPARE_NE = 6, /* no such btree strategy */ + COMPARE_OVERLAP, + COMPARE_CONTAINED_BY, +} CompareType; + +#endif /* CMPTYPE_H */ diff --git a/src/include/access/commit_ts.h b/src/include/access/commit_ts.h index 82d3aa862753f..b8294e41b978e 100644 --- a/src/include/access/commit_ts.h +++ b/src/include/access/commit_ts.h @@ -3,7 +3,7 @@ * * PostgreSQL commit timestamp manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/commit_ts.h diff --git a/src/include/access/detoast.h b/src/include/access/detoast.h index 12d8cdb356a84..e603a2276c381 100644 --- a/src/include/access/detoast.h +++ b/src/include/access/detoast.h @@ -3,7 +3,7 @@ * detoast.h * Access to compressed and external varlena values. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/access/detoast.h * diff --git a/src/include/access/genam.h b/src/include/access/genam.h index fdcfbe8db74d3..5b2ab181b5f8d 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -4,7 +4,7 @@ * POSTGRES generalized index access method definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/genam.h @@ -14,9 +14,11 @@ #ifndef GENAM_H #define GENAM_H +#include "access/htup.h" #include "access/sdir.h" #include "access/skey.h" #include "nodes/tidbitmap.h" +#include "storage/buf.h" #include "storage/lockdefs.h" #include "utils/relcache.h" #include "utils/snapshot.h" @@ -24,6 +26,27 @@ /* We don't want this file to depend on execnodes.h. */ struct IndexInfo; +/* + * Struct for statistics maintained by amgettuple and amgetbitmap + * + * Note: IndexScanInstrumentation can't contain any pointers, since it is + * copied into a SharedIndexScanInstrumentation during parallel scans + */ +typedef struct IndexScanInstrumentation +{ + /* Index search count (incremented with pgstat_count_index_scan call) */ + uint64 nsearches; +} IndexScanInstrumentation; + +/* + * Struct for every worker's IndexScanInstrumentation, stored in shared memory + */ +typedef struct SharedIndexScanInstrumentation +{ + int num_workers; + IndexScanInstrumentation winstrument[FLEXIBLE_ARRAY_MEMBER]; +} SharedIndexScanInstrumentation; + /* * Struct for statistics returned by ambuild */ @@ -155,9 +178,11 @@ extern void index_insert_cleanup(Relation indexRelation, extern IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, + IndexScanInstrumentation *instrument, int nkeys, int norderbys); extern IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, + IndexScanInstrumentation *instrument, int nkeys); extern void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, @@ -166,13 +191,20 @@ extern void index_endscan(IndexScanDesc scan); extern void index_markpos(IndexScanDesc scan); extern void index_restrpos(IndexScanDesc scan); extern Size index_parallelscan_estimate(Relation indexRelation, - int nkeys, int norderbys, Snapshot snapshot); + int nkeys, int norderbys, Snapshot snapshot, + bool instrument, bool parallel_aware, + int nworkers); extern void index_parallelscan_initialize(Relation heapRelation, Relation indexRelation, Snapshot snapshot, + bool instrument, bool parallel_aware, + int nworkers, + SharedIndexScanInstrumentation **sharedinfo, ParallelIndexScanDesc target); extern void index_parallelrescan(IndexScanDesc scan); extern IndexScanDesc index_beginscan_parallel(Relation heaprel, - Relation indexrel, int nkeys, int norderbys, + Relation indexrel, + IndexScanInstrumentation *instrument, + int nkeys, int norderbys, ParallelIndexScanDesc pscan); extern ItemPointer index_getnext_tid(IndexScanDesc scan, ScanDirection direction); @@ -233,5 +265,14 @@ extern SysScanDesc systable_beginscan_ordered(Relation heapRelation, extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction); extern void systable_endscan_ordered(SysScanDesc sysscan); +extern void systable_inplace_update_begin(Relation relation, + Oid indexId, + bool indexOK, + Snapshot snapshot, + int nkeys, const ScanKeyData *key, + HeapTuple *oldtupcopy, + void **state); +extern void systable_inplace_update_finish(void *state, HeapTuple tuple); +extern void systable_inplace_update_cancel(void *state); #endif /* GENAM_H */ diff --git a/src/include/access/generic_xlog.h b/src/include/access/generic_xlog.h index fd1aeb81f46eb..4d1cbab55e1dd 100644 --- a/src/include/access/generic_xlog.h +++ b/src/include/access/generic_xlog.h @@ -4,7 +4,7 @@ * Generic xlog API definition. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/generic_xlog.h diff --git a/src/include/access/gin.h b/src/include/access/gin.h index 25983b7a50566..2e1076a04992b 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -2,7 +2,7 @@ * gin.h * Public header file for Generalized Inverted Index access method. * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/include/access/gin.h *-------------------------------------------------------------------------- @@ -12,6 +12,8 @@ #include "access/xlogreader.h" #include "lib/stringinfo.h" +#include "nodes/execnodes.h" +#include "storage/shm_toc.h" #include "storage/block.h" #include "utils/relcache.h" @@ -36,6 +38,17 @@ #define GIN_SEARCH_MODE_ALL 2 #define GIN_SEARCH_MODE_EVERYTHING 3 /* for internal use only */ +/* + * Constant definition for progress reporting. Phase numbers must match + * ginbuildphasename. + */ +/* PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE is 1 (see progress.h) */ +#define PROGRESS_GIN_PHASE_INDEXBUILD_TABLESCAN 2 +#define PROGRESS_GIN_PHASE_PERFORMSORT_1 3 +#define PROGRESS_GIN_PHASE_MERGE_1 4 +#define PROGRESS_GIN_PHASE_PERFORMSORT_2 5 +#define PROGRESS_GIN_PHASE_MERGE_2 6 + /* * GinStatsData represents stats data for planner use */ @@ -88,4 +101,6 @@ extern void ginGetStats(Relation index, GinStatsData *stats); extern void ginUpdateStats(Relation index, const GinStatsData *stats, bool is_build); +extern void _gin_parallel_build_main(dsm_segment *seg, shm_toc *toc); + #endif /* GIN_H */ diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h index 3013a44bae1c2..aee1f70c22eee 100644 --- a/src/include/access/gin_private.h +++ b/src/include/access/gin_private.h @@ -2,7 +2,7 @@ * gin_private.h * header file for postgres inverted index access method implementation. * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/include/access/gin_private.h *-------------------------------------------------------------------------- @@ -109,6 +109,7 @@ extern Datum *ginExtractEntries(GinState *ginstate, OffsetNumber attnum, extern OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple); extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category); +extern char *ginbuildphasename(int64 phasenum); /* gininsert.c */ extern IndexBuildResult *ginbuild(Relation heap, Relation index, @@ -352,8 +353,15 @@ typedef struct GinScanEntryData /* for a partial-match or full-scan query, we accumulate all TIDs here */ TIDBitmap *matchBitmap; - TBMIterator *matchIterator; - TBMIterateResult *matchResult; + TBMPrivateIterator *matchIterator; + + /* + * If blockno is InvalidBlockNumber, all of the other fields in the + * matchResult are meaningless. + */ + TBMIterateResult matchResult; + OffsetNumber matchOffsets[TBM_MAX_TUPLES_PER_PAGE]; + int matchNtuples; /* used for Posting list and one page in Posting tree */ ItemPointerData *list; diff --git a/src/include/access/gin_tuple.h b/src/include/access/gin_tuple.h new file mode 100644 index 0000000000000..702f7d12889d8 --- /dev/null +++ b/src/include/access/gin_tuple.h @@ -0,0 +1,44 @@ +/*-------------------------------------------------------------------------- + * gin.h + * Public header file for Generalized Inverted Index access method. + * + * Copyright (c) 2006-2025, PostgreSQL Global Development Group + * + * src/include/access/gin.h + *-------------------------------------------------------------------------- + */ +#ifndef GIN_TUPLE_H +#define GIN_TUPLE_H + +#include "access/ginblock.h" +#include "storage/itemptr.h" +#include "utils/sortsupport.h" + +/* + * Data for one key in a GIN index. + */ +typedef struct GinTuple +{ + int tuplen; /* length of the whole tuple */ + OffsetNumber attrnum; /* attnum of index key */ + uint16 keylen; /* bytes in data for key value */ + int16 typlen; /* typlen for key */ + bool typbyval; /* typbyval for key */ + signed char category; /* category: normal or NULL? */ + int nitems; /* number of TIDs in the data */ + char data[FLEXIBLE_ARRAY_MEMBER]; +} GinTuple; + +static inline ItemPointer +GinTupleGetFirst(GinTuple *tup) +{ + GinPostingList *list; + + list = (GinPostingList *) SHORTALIGN(tup->data + tup->keylen); + + return &list->first; +} + +extern int _gin_compare_tuples(GinTuple *a, GinTuple *b, SortSupport ssup); + +#endif /* GIN_TUPLE_H */ diff --git a/src/include/access/ginblock.h b/src/include/access/ginblock.h index b3b7daa049ac6..4c1681068db2a 100644 --- a/src/include/access/ginblock.h +++ b/src/include/access/ginblock.h @@ -2,7 +2,7 @@ * ginblock.h * details of structures stored in GIN index blocks * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/include/access/ginblock.h *-------------------------------------------------------------------------- diff --git a/src/include/access/ginxlog.h b/src/include/access/ginxlog.h index 0c2ddbd82a649..f8c671c2e0d8e 100644 --- a/src/include/access/ginxlog.h +++ b/src/include/access/ginxlog.h @@ -2,7 +2,7 @@ * ginxlog.h * header file for postgres inverted index xlog implementation. * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/include/access/ginxlog.h *-------------------------------------------------------------------------- diff --git a/src/include/access/gist.h b/src/include/access/gist.h index c6dcd6a90ddbc..b3f4e02cbfd21 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -6,7 +6,7 @@ * changes should be made with care. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/gist.h @@ -17,9 +17,11 @@ #define GIST_H #include "access/itup.h" +#include "access/stratnum.h" #include "access/transam.h" #include "access/xlog.h" #include "access/xlogdefs.h" +#include "nodes/primnodes.h" #include "storage/block.h" #include "storage/bufpage.h" #include "utils/relcache.h" @@ -38,7 +40,8 @@ #define GIST_FETCH_PROC 9 #define GIST_OPTIONS_PROC 10 #define GIST_SORTSUPPORT_PROC 11 -#define GISTNProcs 11 +#define GIST_TRANSLATE_CMPTYPE_PROC 12 +#define GISTNProcs 12 /* * Page opaque data in a GiST index page. @@ -245,4 +248,6 @@ typedef struct do { (e).key = (k); (e).rel = (r); (e).page = (pg); \ (e).offset = (o); (e).leafkey = (l); } while (0) +extern StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily); + #endif /* GIST_H */ diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index 7b8749c8db06e..39404ec7cdb6d 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -4,7 +4,7 @@ * private declarations for GiST -- declarations related to the * internal implementation of GiST, not the public API * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/gist_private.h diff --git a/src/include/access/gistscan.h b/src/include/access/gistscan.h index ba2153869a319..518034c36d54f 100644 --- a/src/include/access/gistscan.h +++ b/src/include/access/gistscan.h @@ -4,7 +4,7 @@ * routines defined in access/gist/gistscan.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/gistscan.h diff --git a/src/include/access/gistxlog.h b/src/include/access/gistxlog.h index a0bdc5d7d7bea..d551c0a19d41e 100644 --- a/src/include/access/gistxlog.h +++ b/src/include/access/gistxlog.h @@ -3,7 +3,7 @@ * gistxlog.h * gist xlog routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/gistxlog.h diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 9c7d81525b4f4..073ad29b19b92 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -4,7 +4,7 @@ * header file for postgres hash access method implementation * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/hash.h @@ -387,6 +387,9 @@ extern void hashadjustmembers(Oid opfamilyoid, List *operators, List *functions); +extern CompareType hashtranslatestrategy(StrategyNumber strategy, Oid opfamily); +extern StrategyNumber hashtranslatecmptype(CompareType cmptype, Oid opfamily); + /* private routines */ /* hashinsert.c */ diff --git a/src/include/access/hash_xlog.h b/src/include/access/hash_xlog.h index daca9531d0c74..6fe97de4d66f1 100644 --- a/src/include/access/hash_xlog.h +++ b/src/include/access/hash_xlog.h @@ -4,7 +4,7 @@ * header file for Postgres hash AM implementation * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/hash_xlog.h diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 9e9aec88a620a..3a9424c19c9ae 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -4,7 +4,7 @@ * POSTGRES heap access method definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/heapam.h @@ -14,6 +14,7 @@ #ifndef HEAPAM_H #define HEAPAM_H +#include "access/heapam_xlog.h" #include "access/relation.h" /* for backward compatibility */ #include "access/relscan.h" #include "access/sdir.h" @@ -91,23 +92,21 @@ typedef struct HeapScanDescData */ ParallelBlockTableScanWorkerData *rs_parallelworkerdata; - /* - * These fields are only used for bitmap scans for the "skip fetch" - * optimization. Bitmap scans needing no fields from the heap may skip - * fetching an all visible block, instead using the number of tuples per - * block reported by the bitmap to determine how many NULL-filled tuples - * to return. - */ - Buffer rs_vmbuffer; - int rs_empty_tuples_pending; - /* these fields only used in page-at-a-time mode and for bitmap scans */ - int rs_cindex; /* current tuple's index in vistuples */ - int rs_ntuples; /* number of visible tuples on page */ + uint32 rs_cindex; /* current tuple's index in vistuples */ + uint32 rs_ntuples; /* number of visible tuples on page */ OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */ -} HeapScanDescData; +} HeapScanDescData; typedef struct HeapScanDescData *HeapScanDesc; +typedef struct BitmapHeapScanDescData +{ + HeapScanDescData rs_heap_base; + + /* Holds no data */ +} BitmapHeapScanDescData; +typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc; + /* * Descriptor for fetches from heap via an index. */ @@ -336,7 +335,14 @@ extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple, bool follow_updates, Buffer *buffer, struct TM_FailureData *tmfd); -extern void heap_inplace_update(Relation relation, HeapTuple tuple); +extern bool heap_inplace_lock(Relation relation, + HeapTuple oldtup_ptr, Buffer buffer, + void (*release_callback) (void *), void *arg); +extern void heap_inplace_update_and_unlock(Relation relation, + HeapTuple oldtup, HeapTuple tuple, + Buffer buffer); +extern void heap_inplace_unlock(Relation relation, + HeapTuple oldtup, Buffer buffer); extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, const struct VacuumCutoffs *cutoffs, HeapPageFreeze *pagefrz, @@ -422,4 +428,28 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data, extern void HeapCheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot); +/* + * heap_execute_freeze_tuple + * Execute the prepared freezing of a tuple with caller's freeze plan. + * + * Caller is responsible for ensuring that no other backend can access the + * storage underlying this tuple, either by holding an exclusive lock on the + * buffer containing it (which is what lazy VACUUM does), or by having it be + * in private storage (which is what CLUSTER and friends do). + */ +static inline void +heap_execute_freeze_tuple(HeapTupleHeader tuple, HeapTupleFreeze *frz) +{ + HeapTupleHeaderSetXmax(tuple, frz->xmax); + + if (frz->frzflags & XLH_FREEZE_XVAC) + HeapTupleHeaderSetXvac(tuple, FrozenTransactionId); + + if (frz->frzflags & XLH_INVALID_XVAC) + HeapTupleHeaderSetXvac(tuple, InvalidTransactionId); + + tuple->t_infomask = frz->t_infomask; + tuple->t_infomask2 = frz->t_infomask2; +} + #endif /* HEAPAM_H */ diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index 42736f37e79f3..277df6b3cf0b3 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -4,7 +4,7 @@ * POSTGRES heap access XLOG definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/heapam_xlog.h @@ -20,6 +20,7 @@ #include "storage/buf.h" #include "storage/bufpage.h" #include "storage/relfilelocator.h" +#include "storage/sinval.h" #include "utils/relcache.h" @@ -425,9 +426,14 @@ typedef struct xl_heap_confirm typedef struct xl_heap_inplace { OffsetNumber offnum; /* updated tuple's offset on page */ + Oid dbId; /* MyDatabaseId */ + Oid tsId; /* MyDatabaseTableSpace */ + bool relcacheInitFileInval; /* invalidate relcache init files */ + int nmsgs; /* number of shared inval msgs */ + SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER]; } xl_heap_inplace; -#define SizeOfHeapInplace (offsetof(xl_heap_inplace, offnum) + sizeof(OffsetNumber)) +#define MinSizeOfHeapInplace (offsetof(xl_heap_inplace, nmsgs) + sizeof(int)) /* * This is what we need to know about setting a visibility map bit diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h index c376dff48d7d5..6385a27caf83e 100644 --- a/src/include/access/heaptoast.h +++ b/src/include/access/heaptoast.h @@ -4,7 +4,7 @@ * Heap-specific definitions for external and compressed storage * of variable size attributes. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/access/heaptoast.h * diff --git a/src/include/access/hio.h b/src/include/access/hio.h index 24621cf22b21d..60b802647fe56 100644 --- a/src/include/access/hio.h +++ b/src/include/access/hio.h @@ -4,7 +4,7 @@ * POSTGRES heap access method input/output definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/hio.h diff --git a/src/include/access/htup.h b/src/include/access/htup.h index 116cb1bb27315..f0e3aa87dc306 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -4,7 +4,7 @@ * POSTGRES heap tuple definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/htup.h @@ -78,12 +78,12 @@ typedef HeapTupleData *HeapTuple; #define HeapTupleIsValid(tuple) PointerIsValid(tuple) /* HeapTupleHeader functions implemented in utils/time/combocid.c */ -extern CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup); -extern CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup); -extern void HeapTupleHeaderAdjustCmax(HeapTupleHeader tup, +extern CommandId HeapTupleHeaderGetCmin(const HeapTupleHeaderData *tup); +extern CommandId HeapTupleHeaderGetCmax(const HeapTupleHeaderData *tup); +extern void HeapTupleHeaderAdjustCmax(const HeapTupleHeaderData *tup, CommandId *cmax, bool *iscombo); /* Prototype for HeapTupleHeader accessors in heapam.c */ -extern TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple); +extern TransactionId HeapTupleGetUpdateXid(const HeapTupleHeaderData *tup); #endif /* HTUP_H */ diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index 5e38ef869697a..aa957cf3b0165 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -4,7 +4,7 @@ * POSTGRES heap tuple header definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/htup_details.h @@ -225,12 +225,13 @@ struct HeapTupleHeaderData * * See also HeapTupleHeaderIsOnlyLocked, which also checks for a possible * aborted updater transaction. - * - * Beware of multiple evaluations of the argument. */ -#define HEAP_XMAX_IS_LOCKED_ONLY(infomask) \ - (((infomask) & HEAP_XMAX_LOCK_ONLY) || \ - (((infomask) & (HEAP_XMAX_IS_MULTI | HEAP_LOCK_MASK)) == HEAP_XMAX_EXCL_LOCK)) +static inline bool +HEAP_XMAX_IS_LOCKED_ONLY(uint16 infomask) +{ + return (infomask & HEAP_XMAX_LOCK_ONLY) || + (infomask & (HEAP_XMAX_IS_MULTI | HEAP_LOCK_MASK)) == HEAP_XMAX_EXCL_LOCK; +} /* * A tuple that has HEAP_XMAX_IS_MULTI and HEAP_XMAX_LOCK_ONLY but neither of @@ -250,22 +251,35 @@ struct HeapTupleHeaderData * bogus, regardless of where they stand with respect to the current valid * multixact range. */ -#define HEAP_LOCKED_UPGRADED(infomask) \ -( \ - ((infomask) & HEAP_XMAX_IS_MULTI) != 0 && \ - ((infomask) & HEAP_XMAX_LOCK_ONLY) != 0 && \ - (((infomask) & (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)) == 0) \ -) +static inline bool +HEAP_LOCKED_UPGRADED(uint16 infomask) +{ + return + (infomask & HEAP_XMAX_IS_MULTI) != 0 && + (infomask & HEAP_XMAX_LOCK_ONLY) != 0 && + (infomask & (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)) == 0; +} /* * Use these to test whether a particular lock is applied to a tuple */ -#define HEAP_XMAX_IS_SHR_LOCKED(infomask) \ - (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_SHR_LOCK) -#define HEAP_XMAX_IS_EXCL_LOCKED(infomask) \ - (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_EXCL_LOCK) -#define HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) \ - (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_KEYSHR_LOCK) +static inline bool +HEAP_XMAX_IS_SHR_LOCKED(int16 infomask) +{ + return (infomask & HEAP_LOCK_MASK) == HEAP_XMAX_SHR_LOCK; +} + +static inline bool +HEAP_XMAX_IS_EXCL_LOCKED(int16 infomask) +{ + return (infomask & HEAP_LOCK_MASK) == HEAP_XMAX_EXCL_LOCK; +} + +static inline bool +HEAP_XMAX_IS_KEYSHR_LOCKED(int16 infomask) +{ + return (infomask & HEAP_LOCK_MASK) == HEAP_XMAX_KEYSHR_LOCK; +} /* turn these all off when Xmax is to change */ #define HEAP_XMAX_BITS (HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | \ @@ -292,12 +306,11 @@ struct HeapTupleHeaderData #define HEAP_TUPLE_HAS_MATCH HEAP_ONLY_TUPLE /* tuple has a join match */ /* - * HeapTupleHeader accessor macros - * - * Note: beware of multiple evaluations of "tup" argument. But the Set - * macros evaluate their other argument only once. + * HeapTupleHeader accessor functions */ +static bool HeapTupleHeaderXminFrozen(const HeapTupleHeaderData *tup); + /* * HeapTupleHeaderGetRawXmin returns the "raw" xmin field, which is the xid * originally used to insert the tuple. However, the tuple might actually @@ -306,56 +319,78 @@ struct HeapTupleHeaderData * the xmin to FrozenTransactionId, and that value may still be encountered * on disk. */ -#define HeapTupleHeaderGetRawXmin(tup) \ -( \ - (tup)->t_choice.t_heap.t_xmin \ -) +static inline TransactionId +HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup) +{ + return tup->t_choice.t_heap.t_xmin; +} -#define HeapTupleHeaderGetXmin(tup) \ -( \ - HeapTupleHeaderXminFrozen(tup) ? \ - FrozenTransactionId : HeapTupleHeaderGetRawXmin(tup) \ -) +static inline TransactionId +HeapTupleHeaderGetXmin(const HeapTupleHeaderData *tup) +{ + return HeapTupleHeaderXminFrozen(tup) ? + FrozenTransactionId : HeapTupleHeaderGetRawXmin(tup); +} -#define HeapTupleHeaderSetXmin(tup, xid) \ -( \ - (tup)->t_choice.t_heap.t_xmin = (xid) \ -) +static inline void +HeapTupleHeaderSetXmin(HeapTupleHeaderData *tup, TransactionId xid) +{ + tup->t_choice.t_heap.t_xmin = xid; +} -#define HeapTupleHeaderXminCommitted(tup) \ -( \ - ((tup)->t_infomask & HEAP_XMIN_COMMITTED) != 0 \ -) +static inline bool +HeapTupleHeaderXminCommitted(const HeapTupleHeaderData *tup) +{ + return (tup->t_infomask & HEAP_XMIN_COMMITTED) != 0; +} -#define HeapTupleHeaderXminInvalid(tup) \ -( \ - ((tup)->t_infomask & (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)) == \ - HEAP_XMIN_INVALID \ -) +static inline bool +HeapTupleHeaderXminInvalid(const HeapTupleHeaderData *tup) \ +{ + return (tup->t_infomask & (HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID)) == + HEAP_XMIN_INVALID; +} -#define HeapTupleHeaderXminFrozen(tup) \ -( \ - ((tup)->t_infomask & (HEAP_XMIN_FROZEN)) == HEAP_XMIN_FROZEN \ -) +static inline bool +HeapTupleHeaderXminFrozen(const HeapTupleHeaderData *tup) +{ + return (tup->t_infomask & HEAP_XMIN_FROZEN) == HEAP_XMIN_FROZEN; +} -#define HeapTupleHeaderSetXminCommitted(tup) \ -( \ - AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \ - ((tup)->t_infomask |= HEAP_XMIN_COMMITTED) \ -) +static inline void +HeapTupleHeaderSetXminCommitted(HeapTupleHeaderData *tup) +{ + Assert(!HeapTupleHeaderXminInvalid(tup)); + tup->t_infomask |= HEAP_XMIN_COMMITTED; +} -#define HeapTupleHeaderSetXminInvalid(tup) \ -( \ - AssertMacro(!HeapTupleHeaderXminCommitted(tup)), \ - ((tup)->t_infomask |= HEAP_XMIN_INVALID) \ -) +static inline void +HeapTupleHeaderSetXminInvalid(HeapTupleHeaderData *tup) +{ + Assert(!HeapTupleHeaderXminCommitted(tup)); + tup->t_infomask |= HEAP_XMIN_INVALID; +} -#define HeapTupleHeaderSetXminFrozen(tup) \ -( \ - AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \ - ((tup)->t_infomask |= HEAP_XMIN_FROZEN) \ -) +static inline void +HeapTupleHeaderSetXminFrozen(HeapTupleHeaderData *tup) +{ + Assert(!HeapTupleHeaderXminInvalid(tup)); + tup->t_infomask |= HEAP_XMIN_FROZEN; +} +static inline TransactionId +HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup) +{ + return tup->t_choice.t_heap.t_xmax; +} + +static inline void +HeapTupleHeaderSetXmax(HeapTupleHeaderData *tup, TransactionId xid) +{ + tup->t_choice.t_heap.t_xmax = xid; +} + +#ifndef FRONTEND /* * HeapTupleHeaderGetRawXmax gets you the raw Xmax field. To find out the Xid * that updated a tuple, you might need to resolve the MultiXactId if certain @@ -363,25 +398,17 @@ struct HeapTupleHeaderData * to resolve the MultiXactId if necessary. This might involve multixact I/O, * so it should only be used if absolutely necessary. */ -#define HeapTupleHeaderGetUpdateXid(tup) \ -( \ - (!((tup)->t_infomask & HEAP_XMAX_INVALID) && \ - ((tup)->t_infomask & HEAP_XMAX_IS_MULTI) && \ - !((tup)->t_infomask & HEAP_XMAX_LOCK_ONLY)) ? \ - HeapTupleGetUpdateXid(tup) \ - : \ - HeapTupleHeaderGetRawXmax(tup) \ -) - -#define HeapTupleHeaderGetRawXmax(tup) \ -( \ - (tup)->t_choice.t_heap.t_xmax \ -) - -#define HeapTupleHeaderSetXmax(tup, xid) \ -( \ - (tup)->t_choice.t_heap.t_xmax = (xid) \ -) +static inline TransactionId +HeapTupleHeaderGetUpdateXid(const HeapTupleHeaderData *tup) +{ + if (!((tup)->t_infomask & HEAP_XMAX_INVALID) && + ((tup)->t_infomask & HEAP_XMAX_IS_MULTI) && + !((tup)->t_infomask & HEAP_XMAX_LOCK_ONLY)) + return HeapTupleGetUpdateXid(tup); + else + return HeapTupleHeaderGetRawXmax(tup); +} +#endif /* FRONTEND */ /* * HeapTupleHeaderGetRawCommandId will give you what's in the header whether @@ -389,147 +416,168 @@ struct HeapTupleHeaderData * HeapTupleHeaderGetCmax instead, but note that those Assert that you can * get a legitimate result, ie you are in the originating transaction! */ -#define HeapTupleHeaderGetRawCommandId(tup) \ -( \ - (tup)->t_choice.t_heap.t_field3.t_cid \ -) +static inline CommandId +HeapTupleHeaderGetRawCommandId(const HeapTupleHeaderData *tup) +{ + return tup->t_choice.t_heap.t_field3.t_cid; +} /* SetCmin is reasonably simple since we never need a combo CID */ -#define HeapTupleHeaderSetCmin(tup, cid) \ -do { \ - Assert(!((tup)->t_infomask & HEAP_MOVED)); \ - (tup)->t_choice.t_heap.t_field3.t_cid = (cid); \ - (tup)->t_infomask &= ~HEAP_COMBOCID; \ -} while (0) +static inline void +HeapTupleHeaderSetCmin(HeapTupleHeaderData *tup, CommandId cid) +{ + Assert(!(tup->t_infomask & HEAP_MOVED)); + tup->t_choice.t_heap.t_field3.t_cid = cid; + tup->t_infomask &= ~HEAP_COMBOCID; +} /* SetCmax must be used after HeapTupleHeaderAdjustCmax; see combocid.c */ -#define HeapTupleHeaderSetCmax(tup, cid, iscombo) \ -do { \ - Assert(!((tup)->t_infomask & HEAP_MOVED)); \ - (tup)->t_choice.t_heap.t_field3.t_cid = (cid); \ - if (iscombo) \ - (tup)->t_infomask |= HEAP_COMBOCID; \ - else \ - (tup)->t_infomask &= ~HEAP_COMBOCID; \ -} while (0) - -#define HeapTupleHeaderGetXvac(tup) \ -( \ - ((tup)->t_infomask & HEAP_MOVED) ? \ - (tup)->t_choice.t_heap.t_field3.t_xvac \ - : \ - InvalidTransactionId \ -) +static inline void +HeapTupleHeaderSetCmax(HeapTupleHeaderData *tup, CommandId cid, bool iscombo) +{ + Assert(!((tup)->t_infomask & HEAP_MOVED)); + tup->t_choice.t_heap.t_field3.t_cid = cid; + if (iscombo) + tup->t_infomask |= HEAP_COMBOCID; + else + tup->t_infomask &= ~HEAP_COMBOCID; +} + +static inline TransactionId +HeapTupleHeaderGetXvac(const HeapTupleHeaderData *tup) +{ + if (tup->t_infomask & HEAP_MOVED) + return tup->t_choice.t_heap.t_field3.t_xvac; + else + return InvalidTransactionId; +} -#define HeapTupleHeaderSetXvac(tup, xid) \ -do { \ - Assert((tup)->t_infomask & HEAP_MOVED); \ - (tup)->t_choice.t_heap.t_field3.t_xvac = (xid); \ -} while (0) +static inline void +HeapTupleHeaderSetXvac(HeapTupleHeaderData *tup, TransactionId xid) +{ + Assert(tup->t_infomask & HEAP_MOVED); + tup->t_choice.t_heap.t_field3.t_xvac = xid; +} StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, "invalid speculative token constant"); -#define HeapTupleHeaderIsSpeculative(tup) \ -( \ - (ItemPointerGetOffsetNumberNoCheck(&(tup)->t_ctid) == SpecTokenOffsetNumber) \ -) +static inline bool +HeapTupleHeaderIsSpeculative(const HeapTupleHeaderData *tup) +{ + return ItemPointerGetOffsetNumberNoCheck(&tup->t_ctid) == SpecTokenOffsetNumber; +} -#define HeapTupleHeaderGetSpeculativeToken(tup) \ -( \ - AssertMacro(HeapTupleHeaderIsSpeculative(tup)), \ - ItemPointerGetBlockNumber(&(tup)->t_ctid) \ -) +static inline BlockNumber +HeapTupleHeaderGetSpeculativeToken(const HeapTupleHeaderData *tup) +{ + Assert(HeapTupleHeaderIsSpeculative(tup)); + return ItemPointerGetBlockNumber(&tup->t_ctid); +} -#define HeapTupleHeaderSetSpeculativeToken(tup, token) \ -( \ - ItemPointerSet(&(tup)->t_ctid, token, SpecTokenOffsetNumber) \ -) +static inline void +HeapTupleHeaderSetSpeculativeToken(HeapTupleHeaderData *tup, BlockNumber token) +{ + ItemPointerSet(&tup->t_ctid, token, SpecTokenOffsetNumber); +} -#define HeapTupleHeaderIndicatesMovedPartitions(tup) \ - ItemPointerIndicatesMovedPartitions(&(tup)->t_ctid) +static inline bool +HeapTupleHeaderIndicatesMovedPartitions(const HeapTupleHeaderData *tup) +{ + return ItemPointerIndicatesMovedPartitions(&tup->t_ctid); +} -#define HeapTupleHeaderSetMovedPartitions(tup) \ - ItemPointerSetMovedPartitions(&(tup)->t_ctid) +static inline void +HeapTupleHeaderSetMovedPartitions(HeapTupleHeaderData *tup) +{ + ItemPointerSetMovedPartitions(&tup->t_ctid); +} -#define HeapTupleHeaderGetDatumLength(tup) \ - VARSIZE(tup) +static inline uint32 +HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup) +{ + return VARSIZE(tup); +} -#define HeapTupleHeaderSetDatumLength(tup, len) \ - SET_VARSIZE(tup, len) +static inline void +HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len) +{ + SET_VARSIZE(tup, len); +} -#define HeapTupleHeaderGetTypeId(tup) \ -( \ - (tup)->t_choice.t_datum.datum_typeid \ -) +static inline Oid +HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup) +{ + return tup->t_choice.t_datum.datum_typeid; +} -#define HeapTupleHeaderSetTypeId(tup, typeid) \ -( \ - (tup)->t_choice.t_datum.datum_typeid = (typeid) \ -) +static inline void +HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid) +{ + tup->t_choice.t_datum.datum_typeid = datum_typeid; +} -#define HeapTupleHeaderGetTypMod(tup) \ -( \ - (tup)->t_choice.t_datum.datum_typmod \ -) +static inline int32 +HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup) +{ + return tup->t_choice.t_datum.datum_typmod; +} -#define HeapTupleHeaderSetTypMod(tup, typmod) \ -( \ - (tup)->t_choice.t_datum.datum_typmod = (typmod) \ -) +static inline void +HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod) +{ + tup->t_choice.t_datum.datum_typmod = typmod; +} /* * Note that we stop considering a tuple HOT-updated as soon as it is known * aborted or the would-be updating transaction is known aborted. For best - * efficiency, check tuple visibility before using this macro, so that the + * efficiency, check tuple visibility before using this function, so that the * INVALID bits will be as up to date as possible. */ -#define HeapTupleHeaderIsHotUpdated(tup) \ -( \ - ((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 && \ - ((tup)->t_infomask & HEAP_XMAX_INVALID) == 0 && \ - !HeapTupleHeaderXminInvalid(tup) \ -) - -#define HeapTupleHeaderSetHotUpdated(tup) \ -( \ - (tup)->t_infomask2 |= HEAP_HOT_UPDATED \ -) - -#define HeapTupleHeaderClearHotUpdated(tup) \ -( \ - (tup)->t_infomask2 &= ~HEAP_HOT_UPDATED \ -) +static inline bool +HeapTupleHeaderIsHotUpdated(const HeapTupleHeaderData *tup) +{ + return + (tup->t_infomask2 & HEAP_HOT_UPDATED) != 0 && + (tup->t_infomask & HEAP_XMAX_INVALID) == 0 && + !HeapTupleHeaderXminInvalid(tup); +} -#define HeapTupleHeaderIsHeapOnly(tup) \ -( \ - ((tup)->t_infomask2 & HEAP_ONLY_TUPLE) != 0 \ -) +static inline void +HeapTupleHeaderSetHotUpdated(HeapTupleHeaderData *tup) +{ + tup->t_infomask2 |= HEAP_HOT_UPDATED; +} -#define HeapTupleHeaderSetHeapOnly(tup) \ -( \ - (tup)->t_infomask2 |= HEAP_ONLY_TUPLE \ -) +static inline void +HeapTupleHeaderClearHotUpdated(HeapTupleHeaderData *tup) +{ + tup->t_infomask2 &= ~HEAP_HOT_UPDATED; +} -#define HeapTupleHeaderClearHeapOnly(tup) \ -( \ - (tup)->t_infomask2 &= ~HEAP_ONLY_TUPLE \ -) +static inline bool +HeapTupleHeaderIsHeapOnly(const HeapTupleHeaderData *tup) \ +{ + return (tup->t_infomask2 & HEAP_ONLY_TUPLE) != 0; +} -#define HeapTupleHeaderHasMatch(tup) \ -( \ - ((tup)->t_infomask2 & HEAP_TUPLE_HAS_MATCH) != 0 \ -) +static inline void +HeapTupleHeaderSetHeapOnly(HeapTupleHeaderData *tup) +{ + tup->t_infomask2 |= HEAP_ONLY_TUPLE; +} -#define HeapTupleHeaderSetMatch(tup) \ -( \ - (tup)->t_infomask2 |= HEAP_TUPLE_HAS_MATCH \ -) +static inline void +HeapTupleHeaderClearHeapOnly(HeapTupleHeaderData *tup) +{ + tup->t_infomask2 &= ~HEAP_ONLY_TUPLE; +} -#define HeapTupleHeaderClearMatch(tup) \ -( \ - (tup)->t_infomask2 &= ~HEAP_TUPLE_HAS_MATCH \ -) +/* + * These are used with both HeapTuple and MinimalTuple, so they must be + * macros. + */ #define HeapTupleHeaderGetNatts(tup) \ ((tup)->t_infomask2 & HEAP_NATTS_MASK) @@ -547,7 +595,11 @@ StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, * BITMAPLEN(NATTS) - * Computes size of null bitmap given number of data columns. */ -#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8) +static inline int +BITMAPLEN(int NATTS) +{ + return (NATTS + 7) / 8; +} /* * MaxHeapTupleSize is the maximum allowed size of a heap tuple, including @@ -651,48 +703,107 @@ struct MinimalTupleData #define SizeofMinimalTupleHeader offsetof(MinimalTupleData, t_bits) +/* + * MinimalTuple accessor functions + */ + +static inline bool +HeapTupleHeaderHasMatch(const MinimalTupleData *tup) +{ + return (tup->t_infomask2 & HEAP_TUPLE_HAS_MATCH) != 0; +} + +static inline void +HeapTupleHeaderSetMatch(MinimalTupleData *tup) +{ + tup->t_infomask2 |= HEAP_TUPLE_HAS_MATCH; +} + +static inline void +HeapTupleHeaderClearMatch(MinimalTupleData *tup) +{ + tup->t_infomask2 &= ~HEAP_TUPLE_HAS_MATCH; +} + /* * GETSTRUCT - given a HeapTuple pointer, return address of the user data */ -#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff) +static inline void * +GETSTRUCT(const HeapTupleData *tuple) +{ + return ((char *) (tuple->t_data) + tuple->t_data->t_hoff); +} /* - * Accessor macros to be used with HeapTuple pointers. + * Accessor functions to be used with HeapTuple pointers. */ -#define HeapTupleHasNulls(tuple) \ - (((tuple)->t_data->t_infomask & HEAP_HASNULL) != 0) +static inline bool +HeapTupleHasNulls(const HeapTupleData *tuple) +{ + return (tuple->t_data->t_infomask & HEAP_HASNULL) != 0; +} -#define HeapTupleNoNulls(tuple) \ - (!((tuple)->t_data->t_infomask & HEAP_HASNULL)) +static inline bool +HeapTupleNoNulls(const HeapTupleData *tuple) +{ + return !HeapTupleHasNulls(tuple); +} -#define HeapTupleHasVarWidth(tuple) \ - (((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH) != 0) +static inline bool +HeapTupleHasVarWidth(const HeapTupleData *tuple) +{ + return (tuple->t_data->t_infomask & HEAP_HASVARWIDTH) != 0; +} -#define HeapTupleAllFixed(tuple) \ - (!((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH)) +static inline bool +HeapTupleAllFixed(const HeapTupleData *tuple) +{ + return !HeapTupleHasVarWidth(tuple); +} -#define HeapTupleHasExternal(tuple) \ - (((tuple)->t_data->t_infomask & HEAP_HASEXTERNAL) != 0) +static inline bool +HeapTupleHasExternal(const HeapTupleData *tuple) +{ + return (tuple->t_data->t_infomask & HEAP_HASEXTERNAL) != 0; +} -#define HeapTupleIsHotUpdated(tuple) \ - HeapTupleHeaderIsHotUpdated((tuple)->t_data) +static inline bool +HeapTupleIsHotUpdated(const HeapTupleData *tuple) +{ + return HeapTupleHeaderIsHotUpdated(tuple->t_data); +} -#define HeapTupleSetHotUpdated(tuple) \ - HeapTupleHeaderSetHotUpdated((tuple)->t_data) +static inline void +HeapTupleSetHotUpdated(const HeapTupleData *tuple) +{ + HeapTupleHeaderSetHotUpdated(tuple->t_data); +} -#define HeapTupleClearHotUpdated(tuple) \ - HeapTupleHeaderClearHotUpdated((tuple)->t_data) +static inline void +HeapTupleClearHotUpdated(const HeapTupleData *tuple) +{ + HeapTupleHeaderClearHotUpdated(tuple->t_data); +} -#define HeapTupleIsHeapOnly(tuple) \ - HeapTupleHeaderIsHeapOnly((tuple)->t_data) +static inline bool +HeapTupleIsHeapOnly(const HeapTupleData *tuple) +{ + return HeapTupleHeaderIsHeapOnly(tuple->t_data); +} -#define HeapTupleSetHeapOnly(tuple) \ - HeapTupleHeaderSetHeapOnly((tuple)->t_data) +static inline void +HeapTupleSetHeapOnly(const HeapTupleData *tuple) +{ + HeapTupleHeaderSetHeapOnly(tuple->t_data); +} -#define HeapTupleClearHeapOnly(tuple) \ - HeapTupleHeaderClearHeapOnly((tuple)->t_data) +static inline void +HeapTupleClearHeapOnly(const HeapTupleData *tuple) +{ + HeapTupleHeaderClearHeapOnly(tuple->t_data); +} /* prototypes for functions in common/heaptuple.c */ extern Size heap_compute_data_size(TupleDesc tupleDesc, @@ -728,11 +839,12 @@ extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull); extern void heap_freetuple(HeapTuple htup); extern MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, - const Datum *values, const bool *isnull); + const Datum *values, const bool *isnull, + Size extra); extern void heap_free_minimal_tuple(MinimalTuple mtup); -extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup); +extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra); extern HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup); -extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup); +extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra); extern size_t varsize_any(void *p); extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc); extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc); @@ -758,9 +870,9 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) *isnull = false; if (HeapTupleNoNulls(tup)) { - Form_pg_attribute att; + CompactAttribute *att; - att = TupleDescAttr(tupleDesc, attnum - 1); + att = TupleDescCompactAttr(tupleDesc, attnum - 1); if (att->attcacheoff >= 0) return fetchatt(att, (char *) tup->t_data + tup->t_data->t_hoff + att->attcacheoff); diff --git a/src/include/access/itup.h b/src/include/access/itup.h index 94885751e590f..7066c2a2868b3 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -4,7 +4,7 @@ * POSTGRES index tuple definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/itup.h @@ -68,9 +68,23 @@ typedef IndexAttributeBitMapData * IndexAttributeBitMap; #define INDEX_VAR_MASK 0x4000 #define INDEX_NULL_MASK 0x8000 -#define IndexTupleSize(itup) ((Size) ((itup)->t_info & INDEX_SIZE_MASK)) -#define IndexTupleHasNulls(itup) ((((IndexTuple) (itup))->t_info & INDEX_NULL_MASK)) -#define IndexTupleHasVarwidths(itup) ((((IndexTuple) (itup))->t_info & INDEX_VAR_MASK)) +static inline Size +IndexTupleSize(const IndexTupleData *itup) +{ + return (itup->t_info & INDEX_SIZE_MASK); +} + +static inline bool +IndexTupleHasNulls(const IndexTupleData *itup) +{ + return itup->t_info & INDEX_NULL_MASK; +} + +static inline bool +IndexTupleHasVarwidths(const IndexTupleData *itup) +{ + return itup->t_info & INDEX_VAR_MASK; +} /* routines in indextuple.c */ @@ -124,11 +138,13 @@ index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull) if (!IndexTupleHasNulls(tup)) { - if (TupleDescAttr(tupleDesc, attnum - 1)->attcacheoff >= 0) + CompactAttribute *attr = TupleDescCompactAttr(tupleDesc, attnum - 1); + + if (attr->attcacheoff >= 0) { - return fetchatt(TupleDescAttr(tupleDesc, attnum - 1), - (char *) tup + IndexInfoFindDataOffset(tup->t_info) - + TupleDescAttr(tupleDesc, attnum - 1)->attcacheoff); + return fetchatt(attr, + (char *) tup + IndexInfoFindDataOffset(tup->t_info) + + attr->attcacheoff); } else return nocache_index_getattr(tup, attnum, tupleDesc); diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 7ffd256c744d3..4e6b0eec2ff4e 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -3,7 +3,7 @@ * * PostgreSQL multi-transaction-log manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/multixact.h diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 749304334809e..e709d2e0afe94 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -4,7 +4,7 @@ * header file for postgres btree access method implementation. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/nbtree.h @@ -24,6 +24,7 @@ #include "lib/stringinfo.h" #include "storage/bufmgr.h" #include "storage/shm_toc.h" +#include "utils/skipsupport.h" /* There's room for a 16-bit vacuum cycle ID in BTPageOpaqueData */ typedef uint16 BTCycleId; @@ -161,13 +162,13 @@ typedef struct BTMetaPageData * a heap index tuple to make space for a tiebreaker heap TID * attribute, which we account for here. */ -#define BTMaxItemSize(page) \ - (MAXALIGN_DOWN((PageGetPageSize(page) - \ +#define BTMaxItemSize \ + (MAXALIGN_DOWN((BLCKSZ - \ MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \ MAXALIGN(sizeof(BTPageOpaqueData))) / 3) - \ MAXALIGN(sizeof(ItemPointerData))) -#define BTMaxItemSizeNoHeapTid(page) \ - MAXALIGN_DOWN((PageGetPageSize(page) - \ +#define BTMaxItemSizeNoHeapTid \ + MAXALIGN_DOWN((BLCKSZ - \ MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \ MAXALIGN(sizeof(BTPageOpaqueData))) / 3) @@ -702,6 +703,15 @@ BTreeTupleGetMaxHeapTID(IndexTuple itup) * To facilitate B-Tree deduplication, an operator class may choose to * offer a forth amproc procedure (BTEQUALIMAGE_PROC). For full details, * see doc/src/sgml/btree.sgml. + * + * An operator class may choose to offer a fifth amproc procedure + * (BTOPTIONS_PROC). These procedures define a set of user-visible + * parameters that can be used to control operator class behavior. None of + * the built-in B-Tree operator classes currently register an "options" proc. + * + * To facilitate more efficient B-Tree skip scans, an operator class may + * choose to offer a sixth amproc procedure (BTSKIPSUPPORT_PROC). For full + * details, see src/include/utils/skipsupport.h. */ #define BTORDER_PROC 1 @@ -709,7 +719,8 @@ BTreeTupleGetMaxHeapTID(IndexTuple itup) #define BTINRANGE_PROC 3 #define BTEQUALIMAGE_PROC 4 #define BTOPTIONS_PROC 5 -#define BTNProcs 5 +#define BTSKIPSUPPORT_PROC 6 +#define BTNProcs 6 /* * We need to be able to tell the difference between read and write @@ -925,13 +936,13 @@ typedef BTVacuumPostingData *BTVacuumPosting; * Index scans work a page at a time: we pin and read-lock the page, identify * all the matching items on the page and save them in BTScanPosData, then * release the read-lock while returning the items to the caller for - * processing. This approach minimizes lock/unlock traffic. Note that we - * keep the pin on the index page until the caller is done with all the items - * (this is needed for VACUUM synchronization, see nbtree/README). When we - * are ready to step to the next page, if the caller has told us any of the - * items were killed, we re-lock the page to mark them killed, then unlock. - * Finally we drop the pin and step to the next page in the appropriate - * direction. + * processing. This approach minimizes lock/unlock traffic. We must always + * drop the lock to make it okay for caller to process the returned items. + * Whether or not we can also release the pin during this window will vary. + * We drop the pin (when so->dropPin) to avoid blocking progress by VACUUM + * (see nbtree/README section about making concurrent TID recycling safe). + * We'll always release both the lock and the pin on the current page before + * moving on to its sibling page. * * If we are doing an index-only scan, we save the entire IndexTuple for each * matched item, otherwise only its heap TID and offset. The IndexTuples go @@ -950,28 +961,15 @@ typedef struct BTScanPosItem /* what we remember about each match */ typedef struct BTScanPosData { - Buffer buf; /* if valid, the buffer is pinned */ + Buffer buf; /* currPage buf (invalid means unpinned) */ - XLogRecPtr lsn; /* pos in the WAL stream when page was read */ + /* page details as of the saved position's call to _bt_readpage */ BlockNumber currPage; /* page referenced by items array */ - BlockNumber nextPage; /* page's right link when we scanned it */ - - /* - * moreLeft and moreRight track whether we think there may be matching - * index entries to the left and right of the current page, respectively. - * We can clear the appropriate one of these flags when _bt_checkkeys() - * sets BTReadPageState.continuescan = false. - */ - bool moreLeft; - bool moreRight; + BlockNumber prevPage; /* currPage's left link */ + BlockNumber nextPage; /* currPage's right link */ + XLogRecPtr lsn; /* currPage's LSN (when so->dropPin) */ - /* - * Direction of the scan at the time that _bt_readpage was called. - * - * Used by btrestrpos to "restore" the scan's array keys by resetting each - * array to its first element's value (first in this scan direction). This - * avoids the need to directly track the array keys in btmarkpos. - */ + /* scan direction for the saved position's call to _bt_readpage */ ScanDirection dir; /* @@ -980,6 +978,13 @@ typedef struct BTScanPosData */ int nextTupleOffset; + /* + * moreLeft and moreRight track whether we think there may be matching + * index entries to the left and right of the current page, respectively. + */ + bool moreLeft; + bool moreRight; + /* * The items array is always ordered in index order (ie, increasing * indexoffset). When scanning backwards it is convenient to fill the @@ -1021,20 +1026,28 @@ typedef BTScanPosData *BTScanPos; ) #define BTScanPosInvalidate(scanpos) \ do { \ - (scanpos).currPage = InvalidBlockNumber; \ - (scanpos).nextPage = InvalidBlockNumber; \ (scanpos).buf = InvalidBuffer; \ - (scanpos).lsn = InvalidXLogRecPtr; \ - (scanpos).nextTupleOffset = 0; \ + (scanpos).currPage = InvalidBlockNumber; \ } while (0) /* We need one of these for each equality-type SK_SEARCHARRAY scan key */ typedef struct BTArrayKeyInfo { + /* fields set for both kinds of array (SAOP arrays and skip arrays) */ int scan_key; /* index of associated key in keyData */ - int cur_elem; /* index of current element in elem_values */ - int num_elems; /* number of elems in current array value */ + int num_elems; /* number of elems (-1 means skip array) */ + + /* fields set for ScalarArrayOpExpr arrays only */ Datum *elem_values; /* array of num_elems Datums */ + int cur_elem; /* index of current element in elem_values */ + + /* fields set for skip arrays only */ + int16 attlen; /* attr's length, in bytes */ + bool attbyval; /* attr's FormData_pg_attribute.attbyval */ + bool null_elem; /* NULL is lowest/highest element? */ + SkipSupport sksup; /* skip support (NULL if opclass lacks it) */ + ScanKey low_compare; /* array's > or >= lower bound */ + ScanKey high_compare; /* array's < or <= upper bound */ } BTArrayKeyInfo; typedef struct BTScanOpaqueData @@ -1046,8 +1059,10 @@ typedef struct BTScanOpaqueData /* workspace for SK_SEARCHARRAY support */ int numArrayKeys; /* number of equality-type array keys */ + bool skipScan; /* At least one skip array in arrayKeys[]? */ bool needPrimScan; /* New prim scan to continue in current dir? */ - bool scanBehind; /* Last array advancement matched -inf attr? */ + bool scanBehind; /* Check scan not still behind on next page? */ + bool oppositeDirCheck; /* scanBehind opposite-scan-dir check? */ BTArrayKeyInfo *arrayKeys; /* info about each equality-type array key */ FmgrInfo *orderProcs; /* ORDER procs for required equality keys */ MemoryContext arrayContext; /* scan-lifespan context for array data */ @@ -1055,6 +1070,7 @@ typedef struct BTScanOpaqueData /* info about killed items if any (killedItems is NULL if never used) */ int *killedItems; /* currPos.items indexes of killed items */ int numKilled; /* number of currently stored items */ + bool dropPin; /* drop leaf pin before btgettuple returns? */ /* * If we are doing an index-only scan, these are the tuple storage @@ -1086,33 +1102,28 @@ typedef BTScanOpaqueData *BTScanOpaque; typedef struct BTReadPageState { /* Input parameters, set by _bt_readpage for _bt_checkkeys */ - ScanDirection dir; /* current scan direction */ OffsetNumber minoff; /* Lowest non-pivot tuple's offset */ OffsetNumber maxoff; /* Highest non-pivot tuple's offset */ IndexTuple finaltup; /* Needed by scans with array keys */ - BlockNumber prev_scan_page; /* previous _bt_parallel_release block */ Page page; /* Page being read */ + bool firstpage; /* page is first for primitive scan? */ + bool forcenonrequired; /* treat all keys as nonrequired? */ + int startikey; /* start comparisons from this scan key */ /* Per-tuple input parameters, set by _bt_readpage for _bt_checkkeys */ OffsetNumber offnum; /* current tuple's page offset number */ - /* Output parameter, set by _bt_checkkeys for _bt_readpage */ + /* Output parameters, set by _bt_checkkeys for _bt_readpage */ OffsetNumber skip; /* Array keys "look ahead" skip offnum */ bool continuescan; /* Terminate ongoing (primitive) index scan? */ - /* - * Input and output parameters, set and unset by both _bt_readpage and - * _bt_checkkeys to manage precheck optimizations - */ - bool prechecked; /* precheck set continuescan to 'true'? */ - bool firstmatch; /* at least one match so far? */ - /* * Private _bt_checkkeys state used to manage "look ahead" optimization - * (only used during scans with array keys) + * and primscan scheduling (only used during scans with array keys) */ int16 rechecks; int16 targetdistance; + int16 nskipadvances; } BTReadPageState; @@ -1123,6 +1134,15 @@ typedef struct BTReadPageState */ #define SK_BT_REQFWD 0x00010000 /* required to continue forward scan */ #define SK_BT_REQBKWD 0x00020000 /* required to continue backward scan */ +#define SK_BT_SKIP 0x00040000 /* skip array on column without input = */ + +/* SK_BT_SKIP-only flags (set and unset by array advancement) */ +#define SK_BT_MINVAL 0x00080000 /* invalid sk_argument, use low_compare */ +#define SK_BT_MAXVAL 0x00100000 /* invalid sk_argument, use high_compare */ +#define SK_BT_NEXT 0x00200000 /* positions the scan > sk_argument */ +#define SK_BT_PRIOR 0x00400000 /* positions the scan < sk_argument */ + +/* Remaps pg_index flag bits to uppermost SK_BT_* byte */ #define SK_BT_INDOPTION_SHIFT 24 /* must clear the above bits */ #define SK_BT_DESC (INDOPTION_DESC << SK_BT_INDOPTION_SHIFT) #define SK_BT_NULLS_FIRST (INDOPTION_NULLS_FIRST << SK_BT_INDOPTION_SHIFT) @@ -1169,7 +1189,7 @@ extern bool btinsert(Relation rel, Datum *values, bool *isnull, bool indexUnchanged, struct IndexInfo *indexInfo); extern IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys); -extern Size btestimateparallelscan(int nkeys, int norderbys); +extern Size btestimateparallelscan(Relation rel, int nkeys, int norderbys); extern void btinitparallelscan(void *target); extern bool btgettuple(IndexScanDesc scan, ScanDirection dir); extern int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm); @@ -1186,16 +1206,22 @@ extern IndexBulkDeleteResult *btbulkdelete(IndexVacuumInfo *info, extern IndexBulkDeleteResult *btvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats); extern bool btcanreturn(Relation index, int attno); +extern int btgettreeheight(Relation rel); + +extern CompareType bttranslatestrategy(StrategyNumber strategy, Oid opfamily); +extern StrategyNumber bttranslatecmptype(CompareType cmptype, Oid opfamily); /* * prototypes for internal functions in nbtree.c */ -extern bool _bt_parallel_seize(IndexScanDesc scan, BlockNumber *pageno, - bool first); -extern void _bt_parallel_release(IndexScanDesc scan, BlockNumber scan_page); +extern bool _bt_parallel_seize(IndexScanDesc scan, BlockNumber *next_scan_page, + BlockNumber *last_curr_page, bool first); +extern void _bt_parallel_release(IndexScanDesc scan, + BlockNumber next_scan_page, + BlockNumber curr_page); extern void _bt_parallel_done(IndexScanDesc scan); extern void _bt_parallel_primscan_schedule(IndexScanDesc scan, - BlockNumber prev_scan_page); + BlockNumber curr_page); /* * prototypes for functions in nbtdedup.c @@ -1267,14 +1293,16 @@ extern void _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly); extern void _bt_pendingfsm_finalize(Relation rel, BTVacState *vstate); +/* + * prototypes for functions in nbtpreprocesskeys.c + */ +extern void _bt_preprocess_keys(IndexScanDesc scan); + /* * prototypes for functions in nbtsearch.c */ extern BTStack _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP, int access); -extern Buffer _bt_moveright(Relation rel, Relation heaprel, BTScanInsert key, - Buffer buf, bool forupdate, BTStack stack, - int access); extern OffsetNumber _bt_binsrch_insert(Relation rel, BTInsertState insertstate); extern int32 _bt_compare(Relation rel, BTScanInsert key, Page page, OffsetNumber offnum); extern bool _bt_first(IndexScanDesc scan, ScanDirection dir); @@ -1287,10 +1315,17 @@ extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost); extern BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup); extern void _bt_freestack(BTStack stack); extern bool _bt_start_prim_scan(IndexScanDesc scan, ScanDirection dir); +extern int _bt_binsrch_array_skey(FmgrInfo *orderproc, + bool cur_elem_trig, ScanDirection dir, + Datum tupdatum, bool tupnull, + BTArrayKeyInfo *array, ScanKey cur, + int32 *set_elem_result); extern void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir); -extern void _bt_preprocess_keys(IndexScanDesc scan); extern bool _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys, IndexTuple tuple, int tupnatts); +extern bool _bt_scanbehind_checkkeys(IndexScanDesc scan, ScanDirection dir, + IndexTuple finaltup); +extern void _bt_set_startikey(IndexScanDesc scan, BTReadPageState *pstate); extern void _bt_killitems(IndexScanDesc scan); extern BTCycleId _bt_vacuum_cycleid(Relation rel); extern BTCycleId _bt_start_vacuum(Relation rel); diff --git a/src/include/access/nbtxlog.h b/src/include/access/nbtxlog.h index e42ac1611cddc..fbbe115c77126 100644 --- a/src/include/access/nbtxlog.h +++ b/src/include/access/nbtxlog.h @@ -3,7 +3,7 @@ * nbtxlog.h * header file for postgres btree xlog routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/nbtxlog.h diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h index 69ffe5498f9e7..f37be6d56909b 100644 --- a/src/include/access/parallel.h +++ b/src/include/access/parallel.h @@ -3,7 +3,7 @@ * parallel.h * Infrastructure for launching parallel workers * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/parallel.h @@ -71,7 +71,7 @@ extern void DestroyParallelContext(ParallelContext *pcxt); extern bool ParallelContextActive(void); extern void HandleParallelMessageInterrupt(void); -extern void HandleParallelMessages(void); +extern void ProcessParallelMessages(void); extern void AtEOXact_Parallel(bool isCommit); extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId); extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end); diff --git a/src/include/access/printsimple.h b/src/include/access/printsimple.h index 5c549dc5164ae..760d1482aa6fa 100644 --- a/src/include/access/printsimple.h +++ b/src/include/access/printsimple.h @@ -3,7 +3,7 @@ * printsimple.h * print simple tuples without catalog access * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/printsimple.h diff --git a/src/include/access/printtup.h b/src/include/access/printtup.h index b1fecf873b413..b9bca20d718fc 100644 --- a/src/include/access/printtup.h +++ b/src/include/access/printtup.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/printtup.h diff --git a/src/include/access/relation.h b/src/include/access/relation.h index aa5ccadc36cca..79b0198283e61 100644 --- a/src/include/access/relation.h +++ b/src/include/access/relation.h @@ -4,7 +4,7 @@ * Generic relation related routines. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/relation.h diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index 81829b8270a79..dfbb4c854606c 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -9,7 +9,7 @@ * into a lot of low-level code. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/reloptions.h @@ -152,6 +152,19 @@ typedef struct const char *optname; /* option's name */ relopt_type opttype; /* option's datatype */ int offset; /* offset of field in result struct */ + + /* + * isset_offset is an optional offset of a field in the result struct that + * stores whether the option is explicitly set for the relation or if it + * just picked up the default value. In most cases, this can be + * accomplished by giving the reloption a special out-of-range default + * value (e.g., some integer reloptions use -2), but this isn't always + * possible. For example, a Boolean reloption cannot be given an + * out-of-range default, so we need another way to discover the source of + * its value. This offset is only used if given a value greater than + * zero. + */ + int isset_offset; } relopt_parse_elt; /* Local reloption definition */ @@ -220,7 +233,7 @@ extern void add_local_string_reloption(local_relopts *relopts, const char *name, fill_string_relopt filler, int offset); extern Datum transformRelOptions(Datum oldOptions, List *defList, - const char *namspace, char *validnsps[], + const char *namspace, const char *const validnsps[], bool acceptOidsOff, bool isReset); extern List *untransformRelOptions(Datum options); extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index 521043304abb9..b5e0fb386c0aa 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -4,7 +4,7 @@ * POSTGRES relation scan descriptor definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/relscan.h @@ -16,8 +16,10 @@ #include "access/htup_details.h" #include "access/itup.h" +#include "nodes/tidbitmap.h" #include "port/atomics.h" #include "storage/buf.h" +#include "storage/relfilelocator.h" #include "storage/spin.h" #include "utils/relcache.h" @@ -36,9 +38,24 @@ typedef struct TableScanDescData int rs_nkeys; /* number of scan keys */ struct ScanKeyData *rs_key; /* array of scan key descriptors */ - /* Range of ItemPointers for table_scan_getnextslot_tidrange() to scan. */ - ItemPointerData rs_mintid; - ItemPointerData rs_maxtid; + /* + * Scan type-specific members + */ + union + { + /* Iterator for Bitmap Table Scans */ + TBMIterator rs_tbmiterator; + + /* + * Range of ItemPointers for table_scan_getnextslot_tidrange() to + * scan. + */ + struct + { + ItemPointerData rs_mintid; + ItemPointerData rs_maxtid; + } tidrange; + } st; /* * Information about type and behaviour of the scan, a bitmask of members @@ -62,7 +79,7 @@ typedef struct TableScanDescData *TableScanDesc; */ typedef struct ParallelTableScanDescData { - Oid phs_relid; /* OID of relation to scan */ + RelFileLocator phs_locator; /* physical relation to scan */ bool phs_syncscan; /* report location to syncscan logic? */ bool phs_snapshot_any; /* SnapshotAny, not phs_snapshot_data? */ Size phs_snapshot_off; /* data for snapshot */ @@ -106,6 +123,8 @@ typedef struct IndexFetchTableData Relation rel; } IndexFetchTableData; +struct IndexScanInstrumentation; + /* * We use the same IndexScanDescData structure for both amgettuple-based * and amgetbitmap-based index scans. Some fields are only relevant in @@ -133,6 +152,12 @@ typedef struct IndexScanDescData /* index access method's private state */ void *opaque; /* access-method-specific info */ + /* + * Instrumentation counters maintained by all index AMs during both + * amgettuple calls and amgetbitmap calls (unless field remains NULL) + */ + struct IndexScanInstrumentation *instrument; + /* * In an index-only scan, a successful amgettuple call must fill either * xs_itup (and xs_itupdesc) or xs_hitup (and xs_hitupdesc) to provide the @@ -169,9 +194,10 @@ typedef struct IndexScanDescData /* Generic structure for parallel scans */ typedef struct ParallelIndexScanDescData { - Oid ps_relid; - Oid ps_indexid; - Size ps_offset; /* Offset in bytes of am specific structure */ + RelFileLocator ps_locator; /* physical table relation to scan */ + RelFileLocator ps_indexlocator; /* physical index relation to scan */ + Size ps_offset_ins; /* Offset to SharedIndexScanInstrumentation */ + Size ps_offset_am; /* Offset to am-specific structure */ char ps_snapshot_data[FLEXIBLE_ARRAY_MEMBER]; } ParallelIndexScanDescData; diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h index 5866a26bdddf0..99c3f362adc62 100644 --- a/src/include/access/rewriteheap.h +++ b/src/include/access/rewriteheap.h @@ -3,7 +3,7 @@ * rewriteheap.h * Declarations for heap rewrite support functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * src/include/access/rewriteheap.h diff --git a/src/include/access/rmgrdesc_utils.h b/src/include/access/rmgrdesc_utils.h index fcf214309c332..cda2ee55311ee 100644 --- a/src/include/access/rmgrdesc_utils.h +++ b/src/include/access/rmgrdesc_utils.h @@ -3,7 +3,7 @@ * rmgrdesc_utils.h * Support functions for rmgrdesc routines * - * Copyright (c) 2023-2024, PostgreSQL Global Development Group + * Copyright (c) 2023-2025, PostgreSQL Global Development Group * * src/include/access/rmgrdesc_utils.h * diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h index 78e6b908c6e76..8e7fc9db87786 100644 --- a/src/include/access/rmgrlist.h +++ b/src/include/access/rmgrlist.h @@ -6,7 +6,7 @@ * by the PG_RMGR macro, which is not defined in this file; it can be * defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/rmgrlist.h diff --git a/src/include/access/sdir.h b/src/include/access/sdir.h index d40d809bd2308..6544d24ed4e7e 100644 --- a/src/include/access/sdir.h +++ b/src/include/access/sdir.h @@ -4,7 +4,7 @@ * POSTGRES scan direction definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/sdir.h @@ -17,9 +17,9 @@ /* * Defines the direction for scanning a table or an index. Scans are never - * invoked using NoMovementScanDirectionScans. For convenience, we use the - * values -1 and 1 for backward and forward scans. This allows us to perform - * a few mathematical tricks such as what is done in ScanDirectionCombine. + * invoked using NoMovementScanDirection. For convenience, we use the values + * -1 and 1 for backward and forward scans. This allows us to perform a few + * mathematical tricks such as what is done in ScanDirectionCombine. */ typedef enum ScanDirection { diff --git a/src/include/access/sequence.h b/src/include/access/sequence.h index fb8708861b552..27dde29542a83 100644 --- a/src/include/access/sequence.h +++ b/src/include/access/sequence.h @@ -4,7 +4,7 @@ * Generic routines for sequence-related code. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/sequence.h diff --git a/src/include/access/session.h b/src/include/access/session.h index ce48449a87195..b4946278aec2d 100644 --- a/src/include/access/session.h +++ b/src/include/access/session.h @@ -3,7 +3,7 @@ * session.h * Encapsulation of user session. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/access/session.h * diff --git a/src/include/access/skey.h b/src/include/access/skey.h index 8054d3edce456..e650c2e7baf66 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -4,7 +4,7 @@ * POSTGRES scan key definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/skey.h diff --git a/src/include/access/slru.h b/src/include/access/slru.h index 97e612cd100b9..e142800aab216 100644 --- a/src/include/access/slru.h +++ b/src/include/access/slru.h @@ -3,7 +3,7 @@ * slru.h * Simple LRU buffering for transaction status logfiles * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/slru.h @@ -128,10 +128,8 @@ typedef struct SlruCtlData { SlruShared shared; - /* - * Bitmask to determine bank number from page number. - */ - bits16 bank_mask; + /* Number of banks in this SLRU. */ + uint16 nbanks; /* * If true, use long segment file names. Otherwise, use short file names. @@ -163,7 +161,6 @@ typedef struct SlruCtlData * it's always the same, it doesn't need to be in shared memory. */ char Dir[64]; - } SlruCtlData; typedef SlruCtlData *SlruCtl; @@ -179,7 +176,7 @@ SimpleLruGetBankLock(SlruCtl ctl, int64 pageno) { int bankno; - bankno = pageno & ctl->bank_mask; + bankno = pageno % ctl->nbanks; return &(ctl->shared->bank_locks[bankno].lock); } diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h index d6a4953120074..cbe9b347d8fa4 100644 --- a/src/include/access/spgist.h +++ b/src/include/access/spgist.h @@ -4,7 +4,7 @@ * Public header file for SP-GiST access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/spgist.h diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h index e7cbe10a89b5c..cb43a278f4667 100644 --- a/src/include/access/spgist_private.h +++ b/src/include/access/spgist_private.h @@ -4,7 +4,7 @@ * Private declarations for SP-GiST access method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/spgist_private.h diff --git a/src/include/access/spgxlog.h b/src/include/access/spgxlog.h index 16cc73500129c..695b01421b20b 100644 --- a/src/include/access/spgxlog.h +++ b/src/include/access/spgxlog.h @@ -3,7 +3,7 @@ * spgxlog.h * xlog declarations for SP-GiST access method. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/spgxlog.h diff --git a/src/include/access/stratnum.h b/src/include/access/stratnum.h index 8a47d3c9ec807..ee036d2b62fdc 100644 --- a/src/include/access/stratnum.h +++ b/src/include/access/stratnum.h @@ -4,7 +4,7 @@ * POSTGRES strategy number definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/stratnum.h diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h index e2213cf3fd2ef..c1193a4dd475f 100644 --- a/src/include/access/subtrans.h +++ b/src/include/access/subtrans.h @@ -3,7 +3,7 @@ * * PostgreSQL subtransaction-log manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/subtrans.h diff --git a/src/include/access/syncscan.h b/src/include/access/syncscan.h index e6ee91fc08ac3..397bacab05562 100644 --- a/src/include/access/syncscan.h +++ b/src/include/access/syncscan.h @@ -4,7 +4,7 @@ * POSTGRES synchronous scan support functions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/syncscan.h diff --git a/src/include/access/sysattr.h b/src/include/access/sysattr.h index e88dec71ee94f..47104f3721c68 100644 --- a/src/include/access/sysattr.h +++ b/src/include/access/sysattr.h @@ -4,7 +4,7 @@ * POSTGRES system attribute definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/sysattr.h diff --git a/src/include/access/table.h b/src/include/access/table.h index 1c0bee79fd8b2..f530b06089dbf 100644 --- a/src/include/access/table.h +++ b/src/include/access/table.h @@ -4,7 +4,7 @@ * Generic routines for table related code. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/table.h diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index da661289c1fd4..8713e12cbfb99 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -4,7 +4,7 @@ * POSTGRES table access method definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tableam.h @@ -36,7 +36,6 @@ extern PGDLLIMPORT bool synchronize_seqscans; struct BulkInsertStateData; struct IndexInfo; struct SampleScanState; -struct TBMIterateResult; struct VacuumParams; struct ValidateIndexState; @@ -63,13 +62,6 @@ typedef enum ScanOptions /* unregister snapshot at scan end? */ SO_TEMP_SNAPSHOT = 1 << 9, - - /* - * At the discretion of the table AM, bitmap table scans may be able to - * skip fetching a block from the table if none of the table data is - * needed. If table data may be needed, set SO_NEED_TUPLES. - */ - SO_NEED_TUPLES = 1 << 10, } ScanOptions; /* @@ -137,7 +129,8 @@ typedef enum TU_UpdateIndexes * * xmax is the outdating transaction's XID. If the caller wants to visit the * replacement tuple, it must check that this matches before believing the - * replacement is really a match. + * replacement is really a match. This is InvalidTransactionId if the target + * was !LP_NORMAL (expected only for a TID retrieved from syscache). * * cmax is the outdating command's CID, but only when the failure code is * TM_SelfModified (i.e., something in the current transaction outdated the @@ -779,54 +772,23 @@ typedef struct TableAmRoutine * ------------------------------------------------------------------------ */ - /* - * Prepare to fetch / check / return tuples from `tbmres->blockno` as part - * of a bitmap table scan. `scan` was started via table_beginscan_bm(). - * Return false if there are no tuples to be found on the page, true - * otherwise. - * - * This will typically read and pin the target block, and do the necessary - * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might - * make sense to perform tuple visibility checks at this time). For some - * AMs it will make more sense to do all the work referencing `tbmres` - * contents here, for others it might be better to defer more work to - * scan_bitmap_next_tuple. - * - * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples - * on the page have to be returned, otherwise the tuples at offsets in - * `tbmres->offsets` need to be returned. - * - * XXX: Currently this may only be implemented if the AM uses md.c as its - * storage manager, and uses ItemPointer->ip_blkid in a manner that maps - * blockids directly to the underlying storage. nodeBitmapHeapscan.c - * performs prefetching directly using that interface. This probably - * needs to be rectified at a later point. - * - * XXX: Currently this may only be implemented if the AM uses the - * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to - * perform prefetching. This probably needs to be rectified at a later - * point. - * - * Optional callback, but either both scan_bitmap_next_block and - * scan_bitmap_next_tuple need to exist, or neither. - */ - bool (*scan_bitmap_next_block) (TableScanDesc scan, - struct TBMIterateResult *tbmres); - /* * Fetch the next tuple of a bitmap table scan into `slot` and return true * if a visible tuple was found, false otherwise. * - * For some AMs it will make more sense to do all the work referencing - * `tbmres` contents in scan_bitmap_next_block, for others it might be - * better to defer more work to this callback. + * `lossy_pages` is incremented if the bitmap is lossy for the selected + * page; otherwise, `exact_pages` is incremented. These are tracked for + * display in EXPLAIN ANALYZE output. * - * Optional callback, but either both scan_bitmap_next_block and - * scan_bitmap_next_tuple need to exist, or neither. + * Prefetching additional data from the bitmap is left to the table AM. + * + * This is an optional callback. */ bool (*scan_bitmap_next_tuple) (TableScanDesc scan, - struct TBMIterateResult *tbmres, - TupleTableSlot *slot); + TupleTableSlot *slot, + bool *recheck, + uint64 *lossy_pages, + uint64 *exact_pages); /* * Prepare to fetch tuples from the next block in a sample scan. Return @@ -951,14 +913,12 @@ table_beginscan_strat(Relation rel, Snapshot snapshot, */ static inline TableScanDesc table_beginscan_bm(Relation rel, Snapshot snapshot, - int nkeys, struct ScanKeyData *key, bool need_tuple) + int nkeys, struct ScanKeyData *key) { uint32 flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE; - if (need_tuple) - flags |= SO_NEED_TUPLES; - - return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags); + return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, + NULL, flags); } /* @@ -1949,42 +1909,24 @@ table_relation_estimate_size(Relation rel, int32 *attr_widths, */ /* - * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of - * a bitmap table scan. `scan` needs to have been started via - * table_beginscan_bm(). Returns false if there are no tuples to be found on - * the page, true otherwise. + * Fetch / check / return tuples as part of a bitmap table scan. `scan` needs + * to have been started via table_beginscan_bm(). Fetch the next tuple of a + * bitmap table scan into `slot` and return true if a visible tuple was found, + * false otherwise. * - * Note, this is an optionally implemented function, therefore should only be - * used after verifying the presence (at plan time or such). - */ -static inline bool -table_scan_bitmap_next_block(TableScanDesc scan, - struct TBMIterateResult *tbmres) -{ - /* - * We don't expect direct calls to table_scan_bitmap_next_block with valid - * CheckXidAlive for catalog or regular tables. See detailed comments in - * xact.c where these variables are declared. - */ - if (unlikely(TransactionIdIsValid(CheckXidAlive) && !bsysscan)) - elog(ERROR, "unexpected table_scan_bitmap_next_block call during logical decoding"); - - return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan, - tbmres); -} - -/* - * Fetch the next tuple of a bitmap table scan into `slot` and return true if - * a visible tuple was found, false otherwise. - * table_scan_bitmap_next_block() needs to previously have selected a - * block (i.e. returned true), and no previous - * table_scan_bitmap_next_tuple() for the same block may have - * returned false. + * `recheck` is set by the table AM to indicate whether or not the tuple in + * `slot` should be rechecked. Tuples from lossy pages will always need to be + * rechecked, but some non-lossy pages' tuples may also require recheck. + * + * `lossy_pages` is incremented if the block's representation in the bitmap is + * lossy; otherwise, `exact_pages` is incremented. */ static inline bool table_scan_bitmap_next_tuple(TableScanDesc scan, - struct TBMIterateResult *tbmres, - TupleTableSlot *slot) + TupleTableSlot *slot, + bool *recheck, + uint64 *lossy_pages, + uint64 *exact_pages) { /* * We don't expect direct calls to table_scan_bitmap_next_tuple with valid @@ -1995,8 +1937,10 @@ table_scan_bitmap_next_tuple(TableScanDesc scan, elog(ERROR, "unexpected table_scan_bitmap_next_tuple call during logical decoding"); return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan, - tbmres, - slot); + slot, + recheck, + lossy_pages, + exact_pages); } /* diff --git a/src/include/access/tidstore.h b/src/include/access/tidstore.h index d95cabd7b5e65..041091df2786d 100644 --- a/src/include/access/tidstore.h +++ b/src/include/access/tidstore.h @@ -4,7 +4,7 @@ * TidStore interface. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tidstore.h @@ -22,7 +22,7 @@ typedef struct TidStoreIter TidStoreIter; /* * Result struct for TidStoreIterateNext. This is copyable, but should be - * treated as opaque. Call TidStoreGetOffsets() to obtain the offsets. + * treated as opaque. Call TidStoreGetBlockOffsets() to obtain the offsets. */ typedef struct TidStoreIterResult { diff --git a/src/include/access/timeline.h b/src/include/access/timeline.h index d4356ec120c91..219b580b00865 100644 --- a/src/include/access/timeline.h +++ b/src/include/access/timeline.h @@ -3,7 +3,7 @@ * * Functions for reading and writing timeline history files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/timeline.h diff --git a/src/include/access/toast_compression.h b/src/include/access/toast_compression.h index 64d5e079fa9dd..13c4612ceedcf 100644 --- a/src/include/access/toast_compression.h +++ b/src/include/access/toast_compression.h @@ -3,7 +3,7 @@ * toast_compression.h * Functions for toast compression. * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * src/include/access/toast_compression.h * diff --git a/src/include/access/toast_helper.h b/src/include/access/toast_helper.h index 349a513f77dd5..e6ab8afffb67c 100644 --- a/src/include/access/toast_helper.h +++ b/src/include/access/toast_helper.h @@ -4,7 +4,7 @@ * Helper functions for table AMs implementing compressed or * out-of-line storage of varlena attributes. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/access/toast_helper.h * diff --git a/src/include/access/toast_internals.h b/src/include/access/toast_internals.h index 0eeefe59fec08..06ae8583c1e1e 100644 --- a/src/include/access/toast_internals.h +++ b/src/include/access/toast_internals.h @@ -3,7 +3,7 @@ * toast_internals.h * Internal definitions for the TOAST system. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/access/toast_internals.h * @@ -58,6 +58,6 @@ extern int toast_open_indexes(Relation toastrel, int *num_indexes); extern void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock); -extern void init_toast_snapshot(Snapshot toast_snapshot); +extern Snapshot get_toast_snapshot(void); #endif /* TOAST_INTERNALS_H */ diff --git a/src/include/access/transam.h b/src/include/access/transam.h index 28a2d287fd5a3..7d82cd2eb5621 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -4,7 +4,7 @@ * postgres transaction access method support code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/transam.h @@ -370,6 +370,49 @@ FullTransactionIdNewer(FullTransactionId a, FullTransactionId b) return b; } +/* + * Compute FullTransactionId for the given TransactionId, assuming xid was + * between [oldestXid, nextXid] at the time when TransamVariables->nextXid was + * nextFullXid. When adding calls, evaluate what prevents xid from preceding + * oldestXid if SetTransactionIdLimit() runs between the collection of xid and + * the collection of nextFullXid. + */ +static inline FullTransactionId +FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid, + TransactionId xid) +{ + uint32 epoch; + + /* Special transaction ID. */ + if (!TransactionIdIsNormal(xid)) + return FullTransactionIdFromEpochAndXid(0, xid); + + Assert(TransactionIdPrecedesOrEquals(xid, + XidFromFullTransactionId(nextFullXid))); + + /* + * The 64 bit result must be <= nextFullXid, since nextFullXid hadn't been + * issued yet when xid was in the past. The xid must therefore be from + * the epoch of nextFullXid or the epoch before. We know this because we + * must remove (by freezing) an XID before assigning the XID half an epoch + * ahead of it. + * + * The unlikely() branch hint is dubious. It's perfect for the first 2^32 + * XIDs of a cluster's life. Right at 2^32 XIDs, misprediction shoots to + * 100%, then improves until perfection returns 2^31 XIDs later. Since + * current callers pass relatively-recent XIDs, expect >90% prediction + * accuracy overall. This favors average latency over tail latency. + */ + epoch = EpochFromFullTransactionId(nextFullXid); + if (unlikely(xid > XidFromFullTransactionId(nextFullXid))) + { + Assert(epoch != 0); + epoch--; + } + + return FullTransactionIdFromEpochAndXid(epoch, xid); +} + #endif /* FRONTEND */ #endif /* TRANSAM_H */ diff --git a/src/include/access/tsmapi.h b/src/include/access/tsmapi.h index da9a6c38cd9ad..94d230bf8edf2 100644 --- a/src/include/access/tsmapi.h +++ b/src/include/access/tsmapi.h @@ -3,7 +3,7 @@ * tsmapi.h * API for tablesample methods * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * src/include/access/tsmapi.h * diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h index 62a6d127613c9..2ab3936f22ea8 100644 --- a/src/include/access/tupconvert.h +++ b/src/include/access/tupconvert.h @@ -4,7 +4,7 @@ * Tuple conversion support. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tupconvert.h diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index 8930a28d6602e..a25b94ba42333 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -4,7 +4,7 @@ * POSTGRES tuple descriptor definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tupdesc.h @@ -29,6 +29,7 @@ typedef struct ConstrCheck { char *ccname; char *ccbin; /* nodeToString representation of expr */ + bool ccenforced; bool ccvalid; bool ccnoinherit; /* this is a non-inheritable constraint */ } ConstrCheck; @@ -41,10 +42,50 @@ typedef struct TupleConstr struct AttrMissing *missing; /* missing attributes values, NULL if none */ uint16 num_defval; uint16 num_check; - bool has_not_null; + bool has_not_null; /* any not-null, including not valid ones */ bool has_generated_stored; + bool has_generated_virtual; } TupleConstr; +/* + * CompactAttribute + * Cut-down version of FormData_pg_attribute for faster access for tasks + * such as tuple deformation. The fields of this struct are populated + * using the populate_compact_attribute() function, which must be called + * directly after the FormData_pg_attribute struct is populated or + * altered in any way. + * + * Currently, this struct is 16 bytes. Any code changes which enlarge this + * struct should be considered very carefully. + * + * Code which must access a TupleDesc's attribute data should always make use + * the fields of this struct when required fields are available here. It's + * more efficient to access the memory in CompactAttribute due to it being a + * more compact representation of FormData_pg_attribute and also because + * accessing the FormData_pg_attribute requires an additional calculations to + * obtain the base address of the array within the TupleDesc. + */ +typedef struct CompactAttribute +{ + int32 attcacheoff; /* fixed offset into tuple, if known, or -1 */ + int16 attlen; /* attr len in bytes or -1 = varlen, -2 = + * cstring */ + bool attbyval; /* as FormData_pg_attribute.attbyval */ + bool attispackable; /* FormData_pg_attribute.attstorage != + * TYPSTORAGE_PLAIN */ + bool atthasmissing; /* as FormData_pg_attribute.atthasmissing */ + bool attisdropped; /* as FormData_pg_attribute.attisdropped */ + bool attgenerated; /* FormData_pg_attribute.attgenerated != '\0' */ + char attnullability; /* status of not-null constraint, see below */ + uint8 attalignby; /* alignment requirement in bytes */ +} CompactAttribute; + +/* Valid values for CompactAttribute->attnullability */ +#define ATTNULLABLE_UNRESTRICTED 'f' /* No constraint exists */ +#define ATTNULLABLE_UNKNOWN 'u' /* constraint exists, validity unknown */ +#define ATTNULLABLE_VALID 'v' /* valid constraint exists */ +#define ATTNULLABLE_INVALID 'i' /* constraint exists, marked invalid */ + /* * This struct is passed around within the backend to describe the structure * of tuples. For tuples coming from on-disk relations, the information is @@ -75,6 +116,21 @@ typedef struct TupleConstr * context and go away when the context is freed. We set the tdrefcount * field of such a descriptor to -1, while reference-counted descriptors * always have tdrefcount >= 0. + * + * Beyond the compact_attrs variable length array, the TupleDesc stores an + * array of FormData_pg_attribute. The TupleDescAttr() function, as defined + * below, takes care of calculating the address of the elements of the + * FormData_pg_attribute array. + * + * The array of CompactAttribute is effectively an abbreviated version of the + * array of FormData_pg_attribute. Because CompactAttribute is significantly + * smaller than FormData_pg_attribute, code, especially performance-critical + * code, should prioritize using the fields from the CompactAttribute over the + * equivalent fields in FormData_pg_attribute. + * + * Any code making changes manually to and fields in the FormData_pg_attribute + * array must subsequently call populate_compact_attribute() to flush the + * changes out to the corresponding 'compact_attrs' element. */ typedef struct TupleDescData { @@ -83,13 +139,51 @@ typedef struct TupleDescData int32 tdtypmod; /* typmod for tuple type */ int tdrefcount; /* reference count, or -1 if not counting */ TupleConstr *constr; /* constraints, or NULL if none */ - /* attrs[N] is the description of Attribute Number N+1 */ - FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER]; + /* compact_attrs[N] is the compact metadata of Attribute Number N+1 */ + CompactAttribute compact_attrs[FLEXIBLE_ARRAY_MEMBER]; } TupleDescData; typedef struct TupleDescData *TupleDesc; -/* Accessor for the i'th attribute of tupdesc. */ -#define TupleDescAttr(tupdesc, i) (&(tupdesc)->attrs[(i)]) +extern void populate_compact_attribute(TupleDesc tupdesc, int attnum); + +/* + * Calculates the base address of the Form_pg_attribute at the end of the + * TupleDescData struct. + */ +#define TupleDescAttrAddress(desc) \ + (Form_pg_attribute) ((char *) (desc) + \ + (offsetof(struct TupleDescData, compact_attrs) + \ + (desc)->natts * sizeof(CompactAttribute))) + +/* Accessor for the i'th FormData_pg_attribute element of tupdesc. */ +static inline FormData_pg_attribute * +TupleDescAttr(TupleDesc tupdesc, int i) +{ + FormData_pg_attribute *attrs = TupleDescAttrAddress(tupdesc); + + return &attrs[i]; +} + +#undef TupleDescAttrAddress + +extern void verify_compact_attribute(TupleDesc, int attnum); + +/* + * Accessor for the i'th CompactAttribute element of tupdesc. + */ +static inline CompactAttribute * +TupleDescCompactAttr(TupleDesc tupdesc, int i) +{ + CompactAttribute *cattr = &tupdesc->compact_attrs[i]; + +#ifdef USE_ASSERT_CHECKING + + /* Check that the CompactAttribute is correctly populated */ + verify_compact_attribute(tupdesc, i); +#endif + + return cattr; +} extern TupleDesc CreateTemplateTupleDesc(int natts); @@ -97,10 +191,13 @@ extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs); extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc); +extern TupleDesc CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts); + extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc); #define TupleDescSize(src) \ - (offsetof(struct TupleDescData, attrs) + \ + (offsetof(struct TupleDescData, compact_attrs) + \ + (src)->natts * sizeof(CompactAttribute) + \ (src)->natts * sizeof(FormData_pg_attribute)) extern void TupleDescCopy(TupleDesc dst, TupleDesc src); diff --git a/src/include/access/tupdesc_details.h b/src/include/access/tupdesc_details.h index cc8ff5149a63c..8c0e1a12ece9d 100644 --- a/src/include/access/tupdesc_details.h +++ b/src/include/access/tupdesc_details.h @@ -4,7 +4,7 @@ * POSTGRES tuple descriptor definitions we can't include everywhere * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tupdesc_details.h diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h index 58b3a58cfd06c..6240ec930e7a9 100644 --- a/src/include/access/tupmacs.h +++ b/src/include/access/tupmacs.h @@ -4,7 +4,7 @@ * Tuple macros used by both index tuples and heap tuples. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/tupmacs.h @@ -30,13 +30,14 @@ att_isnull(int ATT, const bits8 *BITS) #ifndef FRONTEND /* - * Given a Form_pg_attribute and a pointer into a tuple's data area, - * return the correct value or pointer. + * Given an attbyval and an attlen from either a Form_pg_attribute or + * CompactAttribute and a pointer into a tuple's data area, return the + * correct value or pointer. * - * We return a Datum value in all cases. If the attribute has "byval" false, - * we return the same pointer into the tuple data area that we're passed. - * Otherwise, we return the correct number of bytes fetched from the data - * area and extended to Datum form. + * We return a Datum value in all cases. If attbyval is false, we return the + * same pointer into the tuple data area that we're passed. Otherwise, we + * return the correct number of bytes fetched from the data area and extended + * to Datum form. * * On machines where Datum is 8 bytes, we support fetching 8-byte byval * attributes; otherwise, only 1, 2, and 4-byte values are supported. @@ -90,6 +91,16 @@ fetch_att(const void *T, bool attbyval, int attlen) att_align_nominal(cur_offset, attalign) \ ) +/* + * Similar to att_align_datum, but accepts a number of bytes, typically from + * CompactAttribute.attalignby to align the Datum by. + */ +#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum) \ + ( \ + ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \ + (uintptr_t) (cur_offset) : \ + TYPEALIGN(attalignby, cur_offset)) + /* * att_align_pointer performs the same calculation as att_align_datum, * but is used when walking a tuple. attptr is the current actual data @@ -111,6 +122,16 @@ fetch_att(const void *T, bool attbyval, int attlen) att_align_nominal(cur_offset, attalign) \ ) +/* + * Similar to att_align_pointer, but accepts a number of bytes, typically from + * CompactAttribute.attalignby to align the pointer by. + */ +#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr) \ + ( \ + ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \ + (uintptr_t) (cur_offset) : \ + TYPEALIGN(attalignby, cur_offset)) + /* * att_align_nominal aligns the given offset as needed for a datum of alignment * requirement attalign, ignoring any consideration of packed varlena datums. @@ -137,6 +158,13 @@ fetch_att(const void *T, bool attbyval, int attlen) ))) \ ) +/* + * Similar to att_align_nominal, but accepts a number of bytes, typically from + * CompactAttribute.attalignby to align the offset by. + */ +#define att_nominal_alignby(cur_offset, attalignby) \ + TYPEALIGN(attalignby, cur_offset) + /* * att_addlength_datum increments the given offset by the space needed for * the given Datum variable. attdatum is only accessed if we are dealing diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h index b85b65c604e25..9fa8235503375 100644 --- a/src/include/access/twophase.h +++ b/src/include/access/twophase.h @@ -4,7 +4,7 @@ * Two-phase-commit related declarations. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/twophase.h diff --git a/src/include/access/twophase_rmgr.h b/src/include/access/twophase_rmgr.h index bdd2cb7b33998..3ed154bb23127 100644 --- a/src/include/access/twophase_rmgr.h +++ b/src/include/access/twophase_rmgr.h @@ -4,7 +4,7 @@ * Two-phase-commit resource managers definition * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/twophase_rmgr.h diff --git a/src/include/access/valid.h b/src/include/access/valid.h index 78c5f023ac420..8b33089dac4e3 100644 --- a/src/include/access/valid.h +++ b/src/include/access/valid.h @@ -4,7 +4,7 @@ * POSTGRES tuple qualification validity definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/valid.h diff --git a/src/include/access/visibilitymap.h b/src/include/access/visibilitymap.h index 1a4d467e6f02f..be21c6dd1a306 100644 --- a/src/include/access/visibilitymap.h +++ b/src/include/access/visibilitymap.h @@ -4,7 +4,7 @@ * visibility map interface * * - * Portions Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2007-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/visibilitymap.h @@ -31,9 +31,12 @@ extern bool visibilitymap_clear(Relation rel, BlockNumber heapBlk, extern void visibilitymap_pin(Relation rel, BlockNumber heapBlk, Buffer *vmbuf); extern bool visibilitymap_pin_ok(BlockNumber heapBlk, Buffer vmbuf); -extern void visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf, - XLogRecPtr recptr, Buffer vmBuf, TransactionId cutoff_xid, - uint8 flags); +extern uint8 visibilitymap_set(Relation rel, + BlockNumber heapBlk, Buffer heapBuf, + XLogRecPtr recptr, + Buffer vmBuf, + TransactionId cutoff_xid, + uint8 flags); extern uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *vmbuf); extern void visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen); extern BlockNumber visibilitymap_prepare_truncate(Relation rel, diff --git a/src/include/access/visibilitymapdefs.h b/src/include/access/visibilitymapdefs.h index 472200f29d025..5ad5c0208779c 100644 --- a/src/include/access/visibilitymapdefs.h +++ b/src/include/access/visibilitymapdefs.h @@ -4,7 +4,7 @@ * macros for accessing contents of visibility map pages * * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * src/include/access/visibilitymapdefs.h * diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 6d4439f0524ee..b2bc10ee04196 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -4,7 +4,7 @@ * postgres transaction system definitions * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xact.h @@ -283,7 +283,13 @@ typedef struct xl_xact_stats_item { int kind; Oid dboid; - Oid objoid; + + /* + * This stores the value of PgStat_HashKey.objid as two uint32 as all the + * fields of xl_xact_xinfo should be multiples of size(int). + */ + uint32 objid_lo; + uint32 objid_hi; } xl_xact_stats_item; typedef struct xl_xact_stats_items diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 083810f5b4c0d..d313099c027f0 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -3,7 +3,7 @@ * * PostgreSQL write-ahead log manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlog.h @@ -167,6 +167,7 @@ typedef struct CheckpointStatsData TimestampTz ckpt_end_t; /* end of checkpoint */ int ckpt_bufs_written; /* # of buffers written */ + int ckpt_slru_written; /* # of SLRU buffers written */ int ckpt_segs_added; /* # of new xlog segments created */ int ckpt_segs_removed; /* # of xlog segments deleted */ @@ -230,6 +231,7 @@ extern XLogRecPtr GetXLogWriteRecPtr(void); extern uint64 GetSystemIdentifier(void); extern char *GetMockAuthenticationNonce(void); extern bool DataChecksumsEnabled(void); +extern bool GetDefaultCharSignedness(void); extern XLogRecPtr GetFakeLSNForUnloggedRel(void); extern Size XLOGShmemSize(void); extern void XLOGShmemInit(void); @@ -239,7 +241,7 @@ extern void LocalProcessControlFile(bool reset); extern WalLevel GetActiveWalLevelOnStandby(void); extern void StartupXLOG(void); extern void ShutdownXLOG(int code, Datum arg); -extern void CreateCheckPoint(int flags); +extern bool CreateCheckPoint(int flags); extern bool CreateRestartPoint(int flags); extern WALAvailability GetWALAvailability(XLogRecPtr targetLSN); extern void XLogPutNextOid(Oid nextOid); diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h index c6a91fb456055..2cf8d55d706d1 100644 --- a/src/include/access/xlog_internal.h +++ b/src/include/access/xlog_internal.h @@ -11,7 +11,7 @@ * Note: This file must be includable in both frontend and backend contexts, * to allow stand-alone tools like pg_receivewal to deal with WAL files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlog_internal.h @@ -31,7 +31,7 @@ /* * Each page of XLOG file has a header like this: */ -#define XLOG_PAGE_MAGIC 0xD116 /* can be used as WAL version indicator */ +#define XLOG_PAGE_MAGIC 0xD118 /* can be used as WAL version indicator */ typedef struct XLogPageHeaderData { @@ -312,7 +312,7 @@ typedef struct xl_end_of_recovery typedef struct XLogRecData { struct XLogRecData *next; /* next struct in chain, or NULL */ - char *data; /* start of rmgr data to include */ + const void *data; /* start of rmgr data to include */ uint32 len; /* length of rmgr data to include */ } XLogRecData; diff --git a/src/include/access/xlogarchive.h b/src/include/access/xlogarchive.h index 0701475fb40c9..6ed47e99f12fb 100644 --- a/src/include/access/xlogarchive.h +++ b/src/include/access/xlogarchive.h @@ -3,7 +3,7 @@ * xlogarchive.h * Prototypes for WAL archives in the backend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/xlogbackup.h b/src/include/access/xlogbackup.h index c30d4a599159f..6b828ce2cac98 100644 --- a/src/include/access/xlogbackup.h +++ b/src/include/access/xlogbackup.h @@ -3,7 +3,7 @@ * xlogbackup.h * Definitions for internals of base backups. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h index 30097989521bc..9e41c9f6e8446 100644 --- a/src/include/access/xlogdefs.h +++ b/src/include/access/xlogdefs.h @@ -4,7 +4,7 @@ * Postgres write-ahead log manager record pointer and * timeline number definitions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlogdefs.h diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h index b44fa29eac515..cf057f033a281 100644 --- a/src/include/access/xloginsert.h +++ b/src/include/access/xloginsert.h @@ -3,7 +3,7 @@ * * Functions for generating WAL records * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xloginsert.h @@ -15,6 +15,7 @@ #include "access/xlogdefs.h" #include "storage/block.h" #include "storage/buf.h" +#include "storage/bufpage.h" #include "storage/relfilelocator.h" #include "utils/relcache.h" @@ -44,19 +45,19 @@ extern void XLogBeginInsert(void); extern void XLogSetRecordFlags(uint8 flags); extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info); extern void XLogEnsureRecordSpace(int max_block_id, int ndatas); -extern void XLogRegisterData(char *data, uint32 len); +extern void XLogRegisterData(const void *data, uint32 len); extern void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags); extern void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, - ForkNumber forknum, BlockNumber blknum, char *page, + ForkNumber forknum, BlockNumber blknum, const PageData *page, uint8 flags); -extern void XLogRegisterBufData(uint8 block_id, char *data, uint32 len); +extern void XLogRegisterBufData(uint8 block_id, const void *data, uint32 len); extern void XLogResetInsertion(void); extern bool XLogCheckBufferNeedsBackup(Buffer buffer); extern XLogRecPtr log_newpage(RelFileLocator *rlocator, ForkNumber forknum, - BlockNumber blkno, char *page, bool page_std); + BlockNumber blkno, Page page, bool page_std); extern void log_newpages(RelFileLocator *rlocator, ForkNumber forknum, int num_pages, - BlockNumber *blknos, char **pages, bool page_std); + BlockNumber *blknos, Page *pages, bool page_std); extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std); extern void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std); diff --git a/src/include/access/xlogprefetcher.h b/src/include/access/xlogprefetcher.h index 98cf990103bc7..50b39c1fb0d77 100644 --- a/src/include/access/xlogprefetcher.h +++ b/src/include/access/xlogprefetcher.h @@ -3,7 +3,7 @@ * xlogprefetcher.h * Declarations for the recovery prefetching module. * - * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2022-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h index 2e9e5f43eb2de..9738462d3c9f1 100644 --- a/src/include/access/xlogreader.h +++ b/src/include/access/xlogreader.h @@ -3,7 +3,7 @@ * xlogreader.h * Definitions for the generic XLog reading facility * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/access/xlogreader.h @@ -224,9 +224,9 @@ struct XLogReaderState * should not be accessed directly. * ---------------------------------------- * Start and end point of the last record read and decoded by - * XLogReadRecordInternal(). NextRecPtr is also used as the position to - * decode next. Calling XLogBeginRead() sets NextRecPtr and EndRecPtr to - * the requested starting position. + * XLogReadRecord(). NextRecPtr is also used as the position to decode + * next. Calling XLogBeginRead() sets NextRecPtr and EndRecPtr to the + * requested starting position. */ XLogRecPtr DecodeRecPtr; /* start of last record decoded */ XLogRecPtr NextRecPtr; /* end+1 of last record decoded */ diff --git a/src/include/access/xlogrecord.h b/src/include/access/xlogrecord.h index b9e5c59fae34d..a06833ce0a31f 100644 --- a/src/include/access/xlogrecord.h +++ b/src/include/access/xlogrecord.h @@ -3,7 +3,7 @@ * * Definitions for the WAL record format. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlogrecord.h diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h index c423464e8bc15..91446303024ae 100644 --- a/src/include/access/xlogrecovery.h +++ b/src/include/access/xlogrecovery.h @@ -3,7 +3,7 @@ * * Functions for WAL recovery and standby mode * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlogrecovery.h diff --git a/src/include/access/xlogstats.h b/src/include/access/xlogstats.h index 35bc5c974c687..528a640524a27 100644 --- a/src/include/access/xlogstats.h +++ b/src/include/access/xlogstats.h @@ -3,7 +3,7 @@ * xlogstats.h * Definitions for WAL Statitstics * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/access/xlogstats.h diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h index 20950ce0336ca..a1870d8e5aa17 100644 --- a/src/include/access/xlogutils.h +++ b/src/include/access/xlogutils.h @@ -3,7 +3,7 @@ * * Utilities for replaying WAL records. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/access/xlogutils.h diff --git a/src/include/archive/archive_module.h b/src/include/archive/archive_module.h index 763af76e542c7..3b17ca7eecad4 100644 --- a/src/include/archive/archive_module.h +++ b/src/include/archive/archive_module.h @@ -3,7 +3,7 @@ * archive_module.h * Exports for archive modules. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * src/include/archive/archive_module.h * diff --git a/src/include/archive/shell_archive.h b/src/include/archive/shell_archive.h index 6f2e92aa9b138..cf131f5dc99fb 100644 --- a/src/include/archive/shell_archive.h +++ b/src/include/archive/shell_archive.h @@ -3,7 +3,7 @@ * shell_archive.h * Exports for archiving via shell. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * src/include/archive/shell_archive.h * diff --git a/src/include/backup/backup_manifest.h b/src/include/backup/backup_manifest.h index 3853d2ca90026..6db019782608b 100644 --- a/src/include/backup/backup_manifest.h +++ b/src/include/backup/backup_manifest.h @@ -3,7 +3,7 @@ * backup_manifest.h * Routines for generating a backup manifest. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/backup_manifest.h * diff --git a/src/include/backup/basebackup.h b/src/include/backup/basebackup.h index 2888ec0f81502..ff88ff7207031 100644 --- a/src/include/backup/basebackup.h +++ b/src/include/backup/basebackup.h @@ -3,7 +3,7 @@ * basebackup.h * Exports from replication/basebackup.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/basebackup.h * diff --git a/src/include/backup/basebackup_incremental.h b/src/include/backup/basebackup_incremental.h index 6ba9c9035e250..1c3d0c925b153 100644 --- a/src/include/backup/basebackup_incremental.h +++ b/src/include/backup/basebackup_incremental.h @@ -3,7 +3,7 @@ * basebackup_incremental.h * API for incremental backup support * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/basebackup_incremental.h * diff --git a/src/include/backup/basebackup_sink.h b/src/include/backup/basebackup_sink.h index fcedba75a6543..8a5ee996a45ed 100644 --- a/src/include/backup/basebackup_sink.h +++ b/src/include/backup/basebackup_sink.h @@ -17,7 +17,7 @@ * single task e.g. command progress reporting, throttling, or * communication with the client. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/basebackup_sink.h * diff --git a/src/include/backup/basebackup_target.h b/src/include/backup/basebackup_target.h index 5814a656f5339..0903df0d28256 100644 --- a/src/include/backup/basebackup_target.h +++ b/src/include/backup/basebackup_target.h @@ -3,7 +3,7 @@ * basebackup_target.h * Extensibility framework for adding base backup targets. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/basebackup_target.h * diff --git a/src/include/backup/walsummary.h b/src/include/backup/walsummary.h index 6575df8e4067c..a3927983f8dcb 100644 --- a/src/include/backup/walsummary.h +++ b/src/include/backup/walsummary.h @@ -3,7 +3,7 @@ * walsummary.h * WAL summary management * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/backup/walsummary.h * diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index 73b78b31335d3..befc4fa1b3d87 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -4,7 +4,7 @@ * include file for the bootstrapping code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/bootstrap/bootstrap.h @@ -33,7 +33,7 @@ extern PGDLLIMPORT Form_pg_attribute attrtypes[MAXATTR]; extern PGDLLIMPORT int numattr; -extern void BootstrapModeMain(int argc, char *argv[], bool check_only) pg_attribute_noreturn(); +pg_noreturn extern void BootstrapModeMain(int argc, char *argv[], bool check_only); extern void closerel(char *relname); extern void boot_openrel(char *relname); @@ -55,9 +55,15 @@ extern void boot_get_type_io_data(Oid typid, Oid *typinput, Oid *typoutput); -extern int boot_yyparse(void); +union YYSTYPE; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif -extern int boot_yylex(void); -extern void boot_yyerror(const char *message) pg_attribute_noreturn(); +extern int boot_yyparse(yyscan_t yyscanner); +extern int boot_yylex_init(yyscan_t *yyscannerp); +extern int boot_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner); +pg_noreturn extern void boot_yyerror(yyscan_t yyscanner, const char *message); #endif /* BOOTSTRAP_H */ diff --git a/src/include/c.h b/src/include/c.h index dc1841346cd36..8cdc16a0f4a9b 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -9,13 +9,14 @@ * polluting the namespace with lots of stuff... * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/c.h * *------------------------------------------------------------------------- */ +/* IWYU pragma: always_keep */ /* *---------------------------------------------------------------- * TABLE OF CONTENTS @@ -46,16 +47,19 @@ #ifndef C_H #define C_H -#include "postgres_ext.h" - -/* Must undef pg_config_ext.h symbols before including pg_config.h */ -#undef PG_INT64_TYPE +/* IWYU pragma: begin_exports */ +/* + * These headers must be included before any system headers, because on some + * platforms they affect the behavior of the system headers (for example, by + * defining _FILE_OFFSET_BITS). + */ #include "pg_config.h" #include "pg_config_manual.h" /* must be after pg_config.h */ -#include "pg_config_os.h" /* must be before any system header files */ +#include "pg_config_os.h" /* config from include/port/PORTNAME.h */ /* System header files that should be available everywhere in Postgres */ +#include #include #include #include @@ -71,10 +75,16 @@ #include /* ensure O_BINARY is available */ #endif #include +#ifdef HAVE_XLOCALE_H +#include +#endif #ifdef ENABLE_NLS #include #endif + /* Pull in fundamental symbols that we also expose to applications */ +#include "postgres_ext.h" + /* Define before including zlib.h to add const decorations to zlib API. */ #ifdef HAVE_LIBZ #define ZLIB_CONST @@ -125,9 +135,9 @@ /* * pg_nodiscard means the compiler should warn if the result of a function - * call is ignored. The name "nodiscard" is chosen in alignment with - * (possibly future) C and C++ standards. For maximum compatibility, use it - * as a function declaration specifier, so it goes before the return type. + * call is ignored. The name "nodiscard" is chosen in alignment with the C23 + * standard attribute with the same name. For maximum forward compatibility, + * place it before the declaration. */ #ifdef __GNUC__ #define pg_nodiscard __attribute__((warn_unused_result)) @@ -135,6 +145,26 @@ #define pg_nodiscard #endif +/* + * pg_noreturn corresponds to the C11 noreturn/_Noreturn function specifier. + * We can't use the standard name "noreturn" because some third-party code + * uses __attribute__((noreturn)) in headers, which would get confused if + * "noreturn" is defined to "_Noreturn", as is done by . + * + * In a declaration, function specifiers go before the function name. The + * common style is to put them before the return type. (The MSVC fallback has + * the same requirement. The GCC fallback is more flexible.) + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define pg_noreturn _Noreturn +#elif defined(__GNUC__) || defined(__SUNPRO_C) +#define pg_noreturn __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define pg_noreturn __declspec(noreturn) +#else +#define pg_noreturn +#endif + /* * This macro will disable address safety instrumentation for a function * when running with "-fsanitize=address". Think twice before using this! @@ -171,6 +201,18 @@ #define pg_attribute_nonnull(...) #endif +/* + * pg_attribute_target allows specifying different target options that the + * function should be compiled with (e.g., for using special CPU instructions). + * Note that there still needs to be a configure-time check to verify that a + * specific target is understood by the compiler. + */ +#if __has_attribute (target) +#define pg_attribute_target(...) __attribute__((target(__VA_ARGS__))) +#else +#define pg_attribute_target(...) +#endif + /* * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only * used in assert-enabled builds, to avoid compiler warnings about unused @@ -191,30 +233,24 @@ #define pg_attribute_printf(f,a) #endif -/* GCC and Sunpro support aligned, packed and noreturn */ +/* GCC and Sunpro support aligned and packed */ #if defined(__GNUC__) || defined(__SUNPRO_C) #define pg_attribute_aligned(a) __attribute__((aligned(a))) -#define pg_attribute_noreturn() __attribute__((noreturn)) #define pg_attribute_packed() __attribute__((packed)) -#define HAVE_PG_ATTRIBUTE_NORETURN 1 #elif defined(_MSC_VER) /* - * MSVC supports aligned. noreturn is also possible but in MSVC it is - * declared before the definition while pg_attribute_noreturn() macro - * is currently used after the definition. + * MSVC supports aligned. * * Packing is also possible but only by wrapping the entire struct definition * which doesn't fit into our current macro declarations. */ #define pg_attribute_aligned(a) __declspec(align(a)) -#define pg_attribute_noreturn() #else /* * NB: aligned and packed are not given default definitions because they * affect code functionality; they *must* be implemented by the compiler * if they are to be used. */ -#define pg_attribute_noreturn() #endif /* @@ -435,37 +471,11 @@ typedef void (*pg_funcptr_t) (void); * bool * Boolean value, either true or false. * - * We use stdbool.h if available and its bool has size 1. That's useful for - * better compiler and debugger output and for compatibility with third-party - * libraries. But PostgreSQL currently cannot deal with bool of other sizes; - * there are static assertions around the code to prevent that. - * - * For C++ compilers, we assume the compiler has a compatible built-in - * definition of bool. - * - * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h. + * PostgreSQL currently cannot deal with bool of size other than 1; there are + * static assertions around the code to prevent that. */ -#ifndef __cplusplus - -#ifdef PG_USE_STDBOOL #include -#else - -#ifndef bool -typedef unsigned char bool; -#endif - -#ifndef true -#define true ((bool) 1) -#endif - -#ifndef false -#define false ((bool) 0) -#endif - -#endif /* not PG_USE_STDBOOL */ -#endif /* not C++ */ /* ---------------------------------------------------------------- @@ -482,29 +492,15 @@ typedef unsigned char bool; */ typedef char *Pointer; -/* - * intN - * Signed integer, EXACTLY N BITS IN SIZE, - * used for numerical computations and the - * frontend/backend protocol. - */ -#ifndef HAVE_INT8 -typedef signed char int8; /* == 8 bits */ -typedef signed short int16; /* == 16 bits */ -typedef signed int int32; /* == 32 bits */ -#endif /* not HAVE_INT8 */ - -/* - * uintN - * Unsigned integer, EXACTLY N BITS IN SIZE, - * used for numerical computations and the - * frontend/backend protocol. - */ -#ifndef HAVE_UINT8 -typedef unsigned char uint8; /* == 8 bits */ -typedef unsigned short uint16; /* == 16 bits */ -typedef unsigned int uint32; /* == 32 bits */ -#endif /* not HAVE_UINT8 */ +/* Historical names for types in . */ +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; /* * bitsN @@ -517,36 +513,14 @@ typedef uint32 bits32; /* >= 32 bits */ /* * 64-bit integers */ -#ifdef HAVE_LONG_INT_64 -/* Plain "long int" fits, use it */ - -#ifndef HAVE_INT64 -typedef long int int64; -#endif -#ifndef HAVE_UINT64 -typedef unsigned long int uint64; -#endif -#define INT64CONST(x) (x##L) -#define UINT64CONST(x) (x##UL) -#elif defined(HAVE_LONG_LONG_INT_64) -/* We have working support for "long long int", use that */ - -#ifndef HAVE_INT64 -typedef long long int int64; -#endif -#ifndef HAVE_UINT64 -typedef unsigned long long int uint64; -#endif -#define INT64CONST(x) (x##LL) -#define UINT64CONST(x) (x##ULL) -#else -/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */ -#error must have a working 64-bit integer datatype -#endif +#define INT64CONST(x) INT64_C(x) +#define UINT64CONST(x) UINT64_C(x) /* snprintf format strings to use for 64-bit integers */ -#define INT64_FORMAT "%" INT64_MODIFIER "d" -#define UINT64_FORMAT "%" INT64_MODIFIER "u" +#define INT64_FORMAT "%" PRId64 +#define UINT64_FORMAT "%" PRIu64 +#define INT64_HEX_FORMAT "%" PRIx64 +#define UINT64_HEX_FORMAT "%" PRIx64 /* * 128-bit signed and unsigned integers @@ -575,22 +549,19 @@ typedef unsigned PG_INT128_TYPE uint128 #endif #endif -/* - * stdint.h limits aren't guaranteed to have compatible types with our fixed - * width types. So just define our own. - */ -#define PG_INT8_MIN (-0x7F-1) -#define PG_INT8_MAX (0x7F) -#define PG_UINT8_MAX (0xFF) -#define PG_INT16_MIN (-0x7FFF-1) -#define PG_INT16_MAX (0x7FFF) -#define PG_UINT16_MAX (0xFFFF) -#define PG_INT32_MIN (-0x7FFFFFFF-1) -#define PG_INT32_MAX (0x7FFFFFFF) -#define PG_UINT32_MAX (0xFFFFFFFFU) -#define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1) -#define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF) -#define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF) +/* Historical names for limits in . */ +#define PG_INT8_MIN INT8_MIN +#define PG_INT8_MAX INT8_MAX +#define PG_UINT8_MAX UINT8_MAX +#define PG_INT16_MIN INT16_MIN +#define PG_INT16_MAX INT16_MAX +#define PG_UINT16_MAX UINT16_MAX +#define PG_INT32_MIN INT32_MIN +#define PG_INT32_MAX INT32_MAX +#define PG_UINT32_MAX UINT32_MAX +#define PG_INT64_MIN INT64_MIN +#define PG_INT64_MAX INT64_MAX +#define PG_UINT64_MAX UINT64_MAX /* * We now always use int64 timestamps, but keep this symbol defined for the @@ -901,8 +872,8 @@ typedef NameData *Name; * we should declare it as long as !FRONTEND. */ #ifndef FRONTEND -extern void ExceptionalCondition(const char *conditionName, - const char *fileName, int lineNumber) pg_attribute_noreturn(); +pg_noreturn extern void ExceptionalCondition(const char *conditionName, + const char *fileName, int lineNumber); #endif /* @@ -1293,21 +1264,25 @@ extern int fdatasync(int fildes); * definition of int64. (For the naming, compare that POSIX has * strtoimax()/strtoumax() which return intmax_t/uintmax_t.) */ -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_LONG == 8 #define strtoi64(str, endptr, base) ((int64) strtol(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoul(str, endptr, base)) -#else +#elif SIZEOF_LONG_LONG == 8 #define strtoi64(str, endptr, base) ((int64) strtoll(str, endptr, base)) #define strtou64(str, endptr, base) ((uint64) strtoull(str, endptr, base)) +#else +#error "cannot find integer type of the same size as int64_t" #endif /* * Similarly, wrappers around labs()/llabs() matching our int64. */ -#ifdef HAVE_LONG_INT_64 -#define i64abs(i) labs(i) +#if SIZEOF_LONG == 8 +#define i64abs(i) ((int64) labs(i)) +#elif SIZEOF_LONG_LONG == 8 +#define i64abs(i) ((int64) llabs(i)) #else -#define i64abs(i) llabs(i) +#error "cannot find integer type of the same size as int64_t" #endif /* @@ -1369,4 +1344,6 @@ typedef intptr_t sigjmp_buf[5]; /* /port compatibility functions */ #include "port.h" +/* IWYU pragma: end_exports */ + #endif /* C_H */ diff --git a/src/include/catalog/Makefile b/src/include/catalog/Makefile index 167f91a6e3fb3..2bbc7805fe37d 100644 --- a/src/include/catalog/Makefile +++ b/src/include/catalog/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/include/catalog # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/Makefile diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h index 1d5826195e273..6fcc59edebd86 100644 --- a/src/include/catalog/binary_upgrade.h +++ b/src/include/catalog/binary_upgrade.h @@ -4,7 +4,7 @@ * variables used for binary upgrades * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/binary_upgrade.h diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index a8dd304b1ad0d..9b5e750b7e408 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -4,7 +4,7 @@ * prototypes for functions in backend/catalog/catalog.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/catalog.h @@ -27,6 +27,7 @@ extern bool IsSystemClass(Oid relid, Form_pg_class reltuple); extern bool IsToastClass(Form_pg_class reltuple); extern bool IsCatalogRelationOid(Oid relid); +extern bool IsCatalogTextUniqueIndexOid(Oid relid); extern bool IsInplaceUpdateOid(Oid relid); extern bool IsCatalogNamespace(Oid namespaceId); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 2f221b6ad0a49..67fbe9c929276 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -38,7 +38,7 @@ * parsenodes.h will warrant a catversion update. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202407252 +#define CATALOG_VERSION_NO 202506121 #endif diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 6908ca7180ae1..0ea7ccf524301 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -4,7 +4,7 @@ * Routines to support inter-object dependencies. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/dependency.h diff --git a/src/include/catalog/duplicate_oids b/src/include/catalog/duplicate_oids index 8965cfb813703..b8ab4ed80bf29 100755 --- a/src/include/catalog/duplicate_oids +++ b/src/include/catalog/duplicate_oids @@ -9,7 +9,7 @@ # the same catalog, our project policy is that manually assigned OIDs # should be globally unique, to avoid confusion. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/duplicate_oids diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h index 201c8c7ef9b76..26e205529dca7 100644 --- a/src/include/catalog/genbki.h +++ b/src/include/catalog/genbki.h @@ -9,7 +9,7 @@ * bootstrap file from these header files.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/genbki.h diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index c512824cd1cc1..dbd339e9df4f2 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -4,7 +4,7 @@ * prototypes for functions in backend/catalog/heap.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/heap.h @@ -23,25 +23,27 @@ #define CHKATYPE_ANYARRAY 0x01 /* allow ANYARRAY */ #define CHKATYPE_ANYRECORD 0x02 /* allow RECORD and RECORD[] */ #define CHKATYPE_IS_PARTKEY 0x04 /* attname is part key # not column */ +#define CHKATYPE_IS_VIRTUAL 0x08 /* is virtual generated column */ typedef struct RawColumnDefault { AttrNumber attnum; /* attribute to attach default to */ Node *raw_default; /* default value (untransformed parse tree) */ - bool missingMode; /* true if part of add column processing */ char generated; /* attgenerated setting */ } RawColumnDefault; typedef struct CookedConstraint { - ConstrType contype; /* CONSTR_DEFAULT or CONSTR_CHECK */ + ConstrType contype; /* CONSTR_DEFAULT, CONSTR_CHECK, + * CONSTR_NOTNULL */ Oid conoid; /* constr OID if created, otherwise Invalid */ char *name; /* name, or NULL if none */ - AttrNumber attnum; /* which attr (only for DEFAULT) */ + AttrNumber attnum; /* which attr (only for NOTNULL, DEFAULT) */ Node *expr; /* transformed default or check expr */ + bool is_enforced; /* is enforced? (only for CHECK) */ bool skip_validation; /* skip validation? (only for CHECK) */ bool is_local; /* constraint has local (non-inherited) def */ - int inhcount; /* number of times constraint is inherited */ + int16 inhcount; /* number of times constraint is inherited */ bool is_no_inherit; /* constraint has local def and cannot be * inherited */ } CookedConstraint; @@ -113,8 +115,14 @@ extern List *AddRelationNewConstraints(Relation rel, bool is_local, bool is_internal, const char *queryString); +extern List *AddRelationNotNullConstraints(Relation rel, + List *constraints, + List *old_notnulls); extern void RelationClearMissing(Relation rel); + +extern void StoreAttrMissingVal(Relation rel, AttrNumber attnum, + Datum missingval); extern void SetAttrMissing(Oid relid, char *attname, char *value); extern Node *cookDefault(ParseState *pstate, diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 7d434f8e65354..4daa8bef5eeab 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -4,7 +4,7 @@ * prototypes for catalog/index.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/index.h @@ -93,6 +93,7 @@ extern Oid index_create(Relation heapRelation, #define INDEX_CONSTR_CREATE_INIT_DEFERRED (1 << 2) #define INDEX_CONSTR_CREATE_UPDATE_INDEX (1 << 3) #define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS (1 << 4) +#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS (1 << 5) extern Oid index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index 30b5350059965..667aca7ace801 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -5,7 +5,7 @@ * on system catalogs * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/indexing.h diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build index f70d1daba52a3..ec1cf467f6fa0 100644 --- a/src/include/catalog/meson.build +++ b/src/include/catalog/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Note: the order of this list determines the order in which the catalog # header files are assembled into postgres.bki. BKI_BOOTSTRAP catalogs diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 8d434d48d573a..8c7ccc69a3c3d 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -4,7 +4,7 @@ * prototypes for functions in backend/catalog/namespace.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/namespace.h diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h index 88387feb2c322..126d9c96aef0f 100644 --- a/src/include/catalog/objectaccess.h +++ b/src/include/catalog/objectaccess.h @@ -3,7 +3,7 @@ * * Object access hooks. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California */ diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h index 3a70d80e3201e..630434b73cf1a 100644 --- a/src/include/catalog/objectaddress.h +++ b/src/include/catalog/objectaddress.h @@ -3,7 +3,7 @@ * objectaddress.h * functions for working with object addresses * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/objectaddress.h @@ -69,6 +69,10 @@ extern bool get_object_namensp_unique(Oid class_id); extern HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId); +extern HeapTuple get_catalog_object_by_oid_extended(Relation catalog, + AttrNumber oidcol, + Oid objectId, + bool locktup); extern char *getObjectDescription(const ObjectAddress *object, bool missing_ok); diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index 1540fccf4be3b..520374af90337 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -4,7 +4,7 @@ * Header file for structures and utility functions related to * partitioning * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/include/catalog/partition.h * diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat index b6b6352d91712..d6aa1f6ec4787 100644 --- a/src/include/catalog/pg_aggregate.dat +++ b/src/include/catalog/pg_aggregate.dat @@ -3,7 +3,7 @@ # pg_aggregate.dat # Initial contents of the pg_aggregate system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_aggregate.dat @@ -161,6 +161,9 @@ { aggfnoid => 'max(xid8)', aggtransfn => 'xid8_larger', aggcombinefn => 'xid8_larger', aggsortop => '>(xid8,xid8)', aggtranstype => 'xid8' }, +{ aggfnoid => 'max(bytea)', aggtransfn => 'bytea_larger', + aggcombinefn => 'bytea_larger', aggsortop => '>(bytea,bytea)', + aggtranstype => 'bytea' }, # min { aggfnoid => 'min(int8)', aggtransfn => 'int8smaller', @@ -232,6 +235,9 @@ { aggfnoid => 'min(xid8)', aggtransfn => 'xid8_smaller', aggcombinefn => 'xid8_smaller', aggsortop => '<(xid8,xid8)', aggtranstype => 'xid8' }, +{ aggfnoid => 'min(bytea)', aggtransfn => 'bytea_smaller', + aggcombinefn => 'bytea_smaller', aggsortop => '<(bytea,bytea)', + aggtranstype => 'bytea' }, # count { aggfnoid => 'count(any)', aggtransfn => 'int8inc_any', diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 490f64546956e..c15f8d2c9fc74 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -4,7 +4,7 @@ * definition of the "aggregate" system catalog (pg_aggregate) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_aggregate.h @@ -19,7 +19,7 @@ #define PG_AGGREGATE_H #include "catalog/genbki.h" -#include "catalog/pg_aggregate_d.h" +#include "catalog/pg_aggregate_d.h" /* IWYU pragma: export */ #include "catalog/objectaddress.h" #include "nodes/pg_list.h" diff --git a/src/include/catalog/pg_am.dat b/src/include/catalog/pg_am.dat index db8749028206b..26d15928a1557 100644 --- a/src/include/catalog/pg_am.dat +++ b/src/include/catalog/pg_am.dat @@ -3,7 +3,7 @@ # pg_am.dat # Initial contents of the pg_am system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_am.dat diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 475593fad4cab..6e98a0930c271 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -4,7 +4,7 @@ * definition of the "access method" system catalog (pg_am) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_am.h @@ -19,7 +19,7 @@ #define PG_AM_H #include "catalog/genbki.h" -#include "catalog/pg_am_d.h" +#include "catalog/pg_am_d.h" /* IWYU pragma: export */ /* ---------------- * pg_am definition. cpp turns this into diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat index d8a05214b1184..2a693cfc31c6f 100644 --- a/src/include/catalog/pg_amop.dat +++ b/src/include/catalog/pg_amop.dat @@ -3,7 +3,7 @@ # pg_amop.dat # Initial contents of the pg_amop system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_amop.dat diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 570100fad418d..cc71cab498b7a 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -29,7 +29,7 @@ * intentional denormalization of the catalogs to buy lookup speed. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_amop.h @@ -44,7 +44,7 @@ #define PG_AMOP_H #include "catalog/genbki.h" -#include "catalog/pg_amop_d.h" +#include "catalog/pg_amop_d.h" /* IWYU pragma: export */ /* ---------------- * pg_amop definition. cpp turns this into diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat index f639c3a6a5180..e3477500baa7d 100644 --- a/src/include/catalog/pg_amproc.dat +++ b/src/include/catalog/pg_amproc.dat @@ -3,7 +3,7 @@ # pg_amproc.dat # Initial contents of the pg_amproc system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_amproc.dat @@ -21,6 +21,8 @@ amprocrighttype => 'bit', amprocnum => '4', amproc => 'btequalimage' }, { amprocfamily => 'btree/bool_ops', amproclefttype => 'bool', amprocrighttype => 'bool', amprocnum => '1', amproc => 'btboolcmp' }, +{ amprocfamily => 'btree/bool_ops', amproclefttype => 'bool', + amprocrighttype => 'bool', amprocnum => '6', amproc => 'btboolskipsupport' }, { amprocfamily => 'btree/bool_ops', amproclefttype => 'bool', amprocrighttype => 'bool', amprocnum => '4', amproc => 'btequalimage' }, { amprocfamily => 'btree/bpchar_ops', amproclefttype => 'bpchar', @@ -41,12 +43,16 @@ amprocrighttype => 'char', amprocnum => '1', amproc => 'btcharcmp' }, { amprocfamily => 'btree/char_ops', amproclefttype => 'char', amprocrighttype => 'char', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/char_ops', amproclefttype => 'char', + amprocrighttype => 'char', amprocnum => '6', amproc => 'btcharskipsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'date', amprocrighttype => 'date', amprocnum => '1', amproc => 'date_cmp' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'date', amprocrighttype => 'date', amprocnum => '2', amproc => 'date_sortsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'date', amprocrighttype => 'date', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date', + amprocrighttype => 'date', amprocnum => '6', amproc => 'date_skipsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'date', amprocrighttype => 'timestamp', amprocnum => '1', amproc => 'date_cmp_timestamp' }, @@ -60,6 +66,9 @@ amproc => 'timestamp_sortsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp', amprocrighttype => 'timestamp', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp', + amprocrighttype => 'timestamp', amprocnum => '6', + amproc => 'timestamp_skipsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp', amprocrighttype => 'date', amprocnum => '1', amproc => 'timestamp_cmp_date' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp', @@ -74,6 +83,9 @@ { amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz', + amprocrighttype => 'timestamptz', amprocnum => '6', + amproc => 'timestamp_skipsupport' }, { amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz', amprocrighttype => 'date', amprocnum => '1', amproc => 'timestamptz_cmp_date' }, @@ -122,6 +134,8 @@ amprocrighttype => 'int2', amprocnum => '2', amproc => 'btint2sortsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int2', amprocrighttype => 'int2', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2', + amprocrighttype => 'int2', amprocnum => '6', amproc => 'btint2skipsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int2', amprocrighttype => 'int4', amprocnum => '1', amproc => 'btint24cmp' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int2', @@ -141,6 +155,8 @@ amprocrighttype => 'int4', amprocnum => '2', amproc => 'btint4sortsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int4', amprocrighttype => 'int4', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4', + amprocrighttype => 'int4', amprocnum => '6', amproc => 'btint4skipsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int4', amprocrighttype => 'int8', amprocnum => '1', amproc => 'btint48cmp' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int4', @@ -160,6 +176,8 @@ amprocrighttype => 'int8', amprocnum => '2', amproc => 'btint8sortsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int8', amprocrighttype => 'int8', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8', + amprocrighttype => 'int8', amprocnum => '6', amproc => 'btint8skipsupport' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int8', amprocrighttype => 'int4', amprocnum => '1', amproc => 'btint84cmp' }, { amprocfamily => 'btree/integer_ops', amproclefttype => 'int8', @@ -193,6 +211,8 @@ amprocrighttype => 'oid', amprocnum => '2', amproc => 'btoidsortsupport' }, { amprocfamily => 'btree/oid_ops', amproclefttype => 'oid', amprocrighttype => 'oid', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/oid_ops', amproclefttype => 'oid', + amprocrighttype => 'oid', amprocnum => '6', amproc => 'btoidskipsupport' }, { amprocfamily => 'btree/oidvector_ops', amproclefttype => 'oidvector', amprocrighttype => 'oidvector', amprocnum => '1', amproc => 'btoidvectorcmp' }, @@ -261,6 +281,8 @@ amprocrighttype => 'uuid', amprocnum => '2', amproc => 'uuid_sortsupport' }, { amprocfamily => 'btree/uuid_ops', amproclefttype => 'uuid', amprocrighttype => 'uuid', amprocnum => '4', amproc => 'btequalimage' }, +{ amprocfamily => 'btree/uuid_ops', amproclefttype => 'uuid', + amprocrighttype => 'uuid', amprocnum => '6', amproc => 'uuid_skipsupport' }, { amprocfamily => 'btree/record_ops', amproclefttype => 'record', amprocrighttype => 'record', amprocnum => '1', amproc => 'btrecordcmp' }, { amprocfamily => 'btree/record_image_ops', amproclefttype => 'record', @@ -283,6 +305,9 @@ amprocrighttype => 'tsquery', amprocnum => '1', amproc => 'tsquery_cmp' }, { amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange', amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' }, +{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange', + amprocrighttype => 'anyrange', amprocnum => '2', + amproc => 'range_sortsupport' }, { amprocfamily => 'btree/multirange_ops', amproclefttype => 'anymultirange', amprocrighttype => 'anymultirange', amprocnum => '1', amproc => 'multirange_cmp' }, @@ -304,9 +329,9 @@ { amprocfamily => 'hash/char_ops', amproclefttype => 'char', amprocrighttype => 'char', amprocnum => '2', amproc => 'hashcharextended' }, { amprocfamily => 'hash/date_ops', amproclefttype => 'date', - amprocrighttype => 'date', amprocnum => '1', amproc => 'hashint4' }, + amprocrighttype => 'date', amprocnum => '1', amproc => 'hashdate' }, { amprocfamily => 'hash/date_ops', amproclefttype => 'date', - amprocrighttype => 'date', amprocnum => '2', amproc => 'hashint4extended' }, + amprocrighttype => 'date', amprocnum => '2', amproc => 'hashdateextended' }, { amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray', amprocrighttype => 'anyarray', amprocnum => '1', amproc => 'hash_array' }, { amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray', @@ -376,10 +401,10 @@ amproc => 'hash_numeric_extended' }, { amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', amprocnum => '1', - amproc => 'timestamp_hash' }, + amproc => 'timestamptz_hash' }, { amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz', amprocrighttype => 'timestamptz', amprocnum => '2', - amproc => 'timestamp_hash_extended' }, + amproc => 'timestamptz_hash_extended' }, { amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz', amprocrighttype => 'timetz', amprocnum => '1', amproc => 'timetz_hash' }, { amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz', @@ -392,26 +417,25 @@ amprocrighttype => 'timestamp', amprocnum => '2', amproc => 'timestamp_hash_extended' }, { amprocfamily => 'hash/bool_ops', amproclefttype => 'bool', - amprocrighttype => 'bool', amprocnum => '1', amproc => 'hashchar' }, + amprocrighttype => 'bool', amprocnum => '1', amproc => 'hashbool' }, { amprocfamily => 'hash/bool_ops', amproclefttype => 'bool', - amprocrighttype => 'bool', amprocnum => '2', amproc => 'hashcharextended' }, + amprocrighttype => 'bool', amprocnum => '2', amproc => 'hashboolextended' }, { amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea', - amprocrighttype => 'bytea', amprocnum => '1', amproc => 'hashvarlena' }, + amprocrighttype => 'bytea', amprocnum => '1', amproc => 'hashbytea' }, { amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea', - amprocrighttype => 'bytea', amprocnum => '2', - amproc => 'hashvarlenaextended' }, + amprocrighttype => 'bytea', amprocnum => '2', amproc => 'hashbyteaextended' }, { amprocfamily => 'hash/xid_ops', amproclefttype => 'xid', - amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashint4' }, + amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashxid' }, { amprocfamily => 'hash/xid_ops', amproclefttype => 'xid', - amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashint4extended' }, + amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashxidextended' }, { amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8', - amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashint8' }, + amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashxid8' }, { amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8', - amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashint8extended' }, + amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashxid8extended' }, { amprocfamily => 'hash/cid_ops', amproclefttype => 'cid', - amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashint4' }, + amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashcid' }, { amprocfamily => 'hash/cid_ops', amproclefttype => 'cid', - amprocrighttype => 'cid', amprocnum => '2', amproc => 'hashint4extended' }, + amprocrighttype => 'cid', amprocnum => '2', amproc => 'hashcidextended' }, { amprocfamily => 'hash/tid_ops', amproclefttype => 'tid', amprocrighttype => 'tid', amprocnum => '1', amproc => 'hashtid' }, { amprocfamily => 'hash/tid_ops', amproclefttype => 'tid', @@ -507,6 +531,9 @@ amprocrighttype => 'box', amprocnum => '7', amproc => 'gist_box_same' }, { amprocfamily => 'gist/box_ops', amproclefttype => 'box', amprocrighttype => 'box', amprocnum => '8', amproc => 'gist_box_distance' }, +{ amprocfamily => 'gist/box_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, { amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon', amprocrighttype => 'polygon', amprocnum => '1', amproc => 'gist_poly_consistent' }, @@ -526,6 +553,9 @@ { amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon', amprocrighttype => 'polygon', amprocnum => '8', amproc => 'gist_poly_distance' }, +{ amprocfamily => 'gist/poly_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, { amprocfamily => 'gist/circle_ops', amproclefttype => 'circle', amprocrighttype => 'circle', amprocnum => '1', amproc => 'gist_circle_consistent' }, @@ -544,6 +574,9 @@ { amprocfamily => 'gist/circle_ops', amproclefttype => 'circle', amprocrighttype => 'circle', amprocnum => '8', amproc => 'gist_circle_distance' }, +{ amprocfamily => 'gist/circle_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, { amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector', amprocrighttype => 'tsvector', amprocnum => '1', amproc => 'gtsvector_consistent(internal,tsvector,int2,oid,internal)' }, @@ -598,6 +631,12 @@ { amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange', amprocrighttype => 'anyrange', amprocnum => '7', amproc => 'range_gist_same' }, +{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange', + amprocrighttype => 'anyrange', amprocnum => '11', + amproc => 'range_sortsupport' }, +{ amprocfamily => 'gist/range_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, { amprocfamily => 'gist/network_ops', amproclefttype => 'inet', amprocrighttype => 'inet', amprocnum => '1', amproc => 'inet_gist_consistent' }, @@ -614,6 +653,9 @@ amprocrighttype => 'inet', amprocnum => '7', amproc => 'inet_gist_same' }, { amprocfamily => 'gist/network_ops', amproclefttype => 'inet', amprocrighttype => 'inet', amprocnum => '9', amproc => 'inet_gist_fetch' }, +{ amprocfamily => 'gist/network_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, { amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', amprocrighttype => 'anymultirange', amprocnum => '1', amproc => 'multirange_gist_consistent' }, @@ -632,6 +674,9 @@ { amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', amprocrighttype => 'anymultirange', amprocnum => '7', amproc => 'range_gist_same' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'any', + amprocrighttype => 'any', amprocnum => '12', + amproc => 'gist_translate_cmptype_common' }, # gin { amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray', @@ -819,7 +864,7 @@ amprocrighttype => 'bytea', amprocnum => '5', amproc => 'brin_bloom_options' }, { amprocfamily => 'brin/bytea_bloom_ops', amproclefttype => 'bytea', - amprocrighttype => 'bytea', amprocnum => '11', amproc => 'hashvarlena' }, + amprocrighttype => 'bytea', amprocnum => '11', amproc => 'hashbytea' }, # minmax "char" { amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char', diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index 1dbebeca1752c..bf8de4618c751 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -18,7 +18,7 @@ * some don't pay attention to non-default functions at all. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_amproc.h @@ -33,7 +33,7 @@ #define PG_AMPROC_H #include "catalog/genbki.h" -#include "catalog/pg_amproc_d.h" +#include "catalog/pg_amproc_d.h" /* IWYU pragma: export */ /* ---------------- * pg_amproc definition. cpp turns this into diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h index 14f034a3b52e3..3067a8357c038 100644 --- a/src/include/catalog/pg_attrdef.h +++ b/src/include/catalog/pg_attrdef.h @@ -4,7 +4,7 @@ * definition of the "attribute defaults" system catalog (pg_attrdef) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_attrdef.h @@ -20,7 +20,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_attrdef_d.h" +#include "catalog/pg_attrdef_d.h" /* IWYU pragma: export */ /* ---------------- * pg_attrdef definition. cpp turns this into @@ -57,8 +57,7 @@ DECLARE_FOREIGN_KEY((adrelid, adnum), pg_attribute, (attrelid, attnum)); extern Oid StoreAttrDefault(Relation rel, AttrNumber attnum, - Node *expr, bool is_internal, - bool add_column_mode); + Node *expr, bool is_internal); extern void RemoveAttrDefault(Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal); diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 1c62b8bfcb58e..c612aed620f63 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * relations need be included. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_attribute.h @@ -23,7 +23,7 @@ #define PG_ATTRIBUTE_H #include "catalog/genbki.h" -#include "catalog/pg_attribute_d.h" +#include "catalog/pg_attribute_d.h" /* IWYU pragma: export */ /* ---------------- * pg_attribute definition. cpp turns this into @@ -73,15 +73,6 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75, */ int16 attnum; - /* - * fastgetattr() uses attcacheoff to cache byte offsets of attributes in - * heap tuples. The value actually stored in pg_attribute (-1) indicates - * no cached value. But when we copy these tuples into a tuple - * descriptor, we may then update attcacheoff in the copies. This speeds - * up the attribute walking process. - */ - int32 attcacheoff BKI_DEFAULT(-1); - /* * atttypmod records type-specific data supplied at table creation time * (for example, the max length of a varchar field). It is passed to @@ -126,7 +117,9 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75, */ char attcompression BKI_DEFAULT('\0'); - /* This flag represents the "NOT NULL" constraint */ + /* + * Whether a (possibly invalid) not-null constraint exists for the column + */ bool attnotnull; /* Has DEFAULT value or not */ @@ -234,6 +227,7 @@ MAKE_SYSCACHE(ATTNUM, pg_attribute_relid_attnum_index, 128); #define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd' #define ATTRIBUTE_GENERATED_STORED 's' +#define ATTRIBUTE_GENERATED_VIRTUAL 'v' #endif /* EXPOSE_TO_CLIENT_CODE */ diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h index 5f4b30756ca65..387316e44f079 100644 --- a/src/include/catalog/pg_auth_members.h +++ b/src/include/catalog/pg_auth_members.h @@ -5,7 +5,7 @@ * (pg_auth_members). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_auth_members.h @@ -20,7 +20,7 @@ #define PG_AUTH_MEMBERS_H #include "catalog/genbki.h" -#include "catalog/pg_auth_members_d.h" +#include "catalog/pg_auth_members_d.h" /* IWYU pragma: export */ /* ---------------- * pg_auth_members definition. cpp turns this into diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index 0129f67eaaa27..eb4dab5c6aa77 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -3,7 +3,7 @@ # pg_authid.dat # Initial contents of the pg_authid system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_authid.dat diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h index e08863f78abde..b2f3e9d01eec9 100644 --- a/src/include/catalog/pg_authid.h +++ b/src/include/catalog/pg_authid.h @@ -3,10 +3,10 @@ * pg_authid.h * definition of the "authorization identifier" system catalog (pg_authid) * - * pg_shadow and pg_group are now publicly accessible views on pg_authid. + * pg_shadow and pg_group are now views on pg_authid. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_authid.h @@ -21,7 +21,7 @@ #define PG_AUTHID_H #include "catalog/genbki.h" -#include "catalog/pg_authid_d.h" +#include "catalog/pg_authid_d.h" /* IWYU pragma: export */ /* ---------------- * pg_authid definition. cpp turns this into @@ -55,8 +55,6 @@ CATALOG(pg_authid,1260,AuthIdRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(284 */ typedef FormData_pg_authid *Form_pg_authid; -DECLARE_TOAST_WITH_MACRO(pg_authid, 4175, 4176, PgAuthidToastTable, PgAuthidToastIndex); - DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, AuthIdRolnameIndexId, pg_authid, btree(rolname name_ops)); DECLARE_UNIQUE_INDEX_PKEY(pg_authid_oid_index, 2677, AuthIdOidIndexId, pg_authid, btree(oid oid_ops)); diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat index ca7b6d7191f97..ab46be606f03d 100644 --- a/src/include/catalog/pg_cast.dat +++ b/src/include/catalog/pg_cast.dat @@ -3,7 +3,7 @@ # pg_cast.dat # Initial contents of the pg_cast system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_cast.dat @@ -320,6 +320,20 @@ { castsource => 'varchar', casttarget => 'name', castfunc => 'name(varchar)', castcontext => 'i', castmethod => 'f' }, +# Allow explicit coercions between bytea and integer types +{ castsource => 'int2', casttarget => 'bytea', castfunc => 'bytea(int2)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int4', casttarget => 'bytea', castfunc => 'bytea(int4)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'int8', casttarget => 'bytea', castfunc => 'bytea(int8)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int2', castfunc => 'int2(bytea)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int4', castfunc => 'int4(bytea)', + castcontext => 'e', castmethod => 'f' }, +{ castsource => 'bytea', casttarget => 'int8', castfunc => 'int8(bytea)', + castcontext => 'e', castmethod => 'f' }, + # Allow explicit coercions between int4 and "char" { castsource => 'char', casttarget => 'int4', castfunc => 'int4(char)', castcontext => 'e', castmethod => 'f' }, diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index 6c995509bc388..6a0ca3371534e 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -6,7 +6,7 @@ * As of Postgres 8.0, pg_cast describes not only type coercion functions * but also length coercion functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_cast.h @@ -22,7 +22,7 @@ #include "catalog/dependency.h" #include "catalog/genbki.h" -#include "catalog/pg_cast_d.h" +#include "catalog/pg_cast_d.h" /* IWYU pragma: export */ /* ---------------- * pg_cast definition. cpp turns this into diff --git a/src/include/catalog/pg_class.dat b/src/include/catalog/pg_class.dat index 830e7e425bb08..8c89ad1bc2ea8 100644 --- a/src/include/catalog/pg_class.dat +++ b/src/include/catalog/pg_class.dat @@ -3,7 +3,7 @@ # pg_class.dat # Initial contents of the pg_class system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_class.dat @@ -14,7 +14,7 @@ # Note: only bootstrap catalogs, ie those marked BKI_BOOTSTRAP, need to # have entries here. Be sure that the OIDs listed here match those given in -# their CATALOG and BKI_ROWTYPE_OID macros. +# the corresponding CATALOG macros. { oid => '1247', relname => 'pg_type', reltype => 'pg_type' }, diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 0fc2c093b0d4e..07d182da796a0 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -4,7 +4,7 @@ * definition of the "relation" system catalog (pg_class) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_class.h @@ -19,7 +19,7 @@ #define PG_CLASS_H #include "catalog/genbki.h" -#include "catalog/pg_class_d.h" +#include "catalog/pg_class_d.h" /* IWYU pragma: export */ /* ---------------- * pg_class definition. cpp turns this into @@ -68,6 +68,9 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat /* # of all-visible blocks (not always up-to-date) */ int32 relallvisible BKI_DEFAULT(0); + /* # of all-frozen blocks (not always up-to-date) */ + int32 relallfrozen BKI_DEFAULT(0); + /* OID of toast table; 0 if none */ Oid reltoastrelid BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_class); @@ -228,8 +231,8 @@ MAKE_SYSCACHE(RELNAMENSP, pg_class_relname_nsp_index, 128); (relkind) == RELKIND_TOASTVALUE || \ (relkind) == RELKIND_MATVIEW) -extern int errdetail_relkind_not_supported(char relkind); - #endif /* EXPOSE_TO_CLIENT_CODE */ +extern int errdetail_relkind_not_supported(char relkind); + #endif /* PG_CLASS_H */ diff --git a/src/include/catalog/pg_collation.dat b/src/include/catalog/pg_collation.dat index f126201276071..fb76c421931ea 100644 --- a/src/include/catalog/pg_collation.dat +++ b/src/include/catalog/pg_collation.dat @@ -3,7 +3,7 @@ # pg_collation.dat # Initial contents of the pg_collation system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_collation.dat @@ -19,8 +19,7 @@ descr => 'standard C collation', collname => 'C', collprovider => 'c', collencoding => '-1', collcollate => 'C', collctype => 'C' }, -{ oid => '951', oid_symbol => 'POSIX_COLLATION_OID', - descr => 'standard POSIX collation', +{ oid => '951', descr => 'standard POSIX collation', collname => 'POSIX', collprovider => 'c', collencoding => '-1', collcollate => 'POSIX', collctype => 'POSIX' }, { oid => '962', descr => 'sorts by Unicode code point, C character semantics', @@ -34,5 +33,8 @@ descr => 'sorts by Unicode code point; Unicode and POSIX character semantics', collname => 'pg_c_utf8', collprovider => 'b', collencoding => '6', colllocale => 'C.UTF-8', collversion => '1' }, +{ oid => '9535', descr => 'sorts by Unicode code point; Unicode character semantics', + collname => 'pg_unicode_fast', collprovider => 'b', collencoding => '6', + colllocale => 'PG_UNICODE_FAST', collversion => '1' }, ] diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h index 5ce289d74bd0e..7c5d5b11300b9 100644 --- a/src/include/catalog/pg_collation.h +++ b/src/include/catalog/pg_collation.h @@ -4,7 +4,7 @@ * definition of the "collation" system catalog (pg_collation) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_collation.h @@ -19,7 +19,7 @@ #define PG_COLLATION_H #include "catalog/genbki.h" -#include "catalog/pg_collation_d.h" +#include "catalog/pg_collation_d.h" /* IWYU pragma: export */ /* ---------------- * pg_collation definition. cpp turns this into diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h index 7a8017f15b5df..4afceb5c692d2 100644 --- a/src/include/catalog/pg_constraint.h +++ b/src/include/catalog/pg_constraint.h @@ -4,7 +4,7 @@ * definition of the "constraint" system catalog (pg_constraint) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_constraint.h @@ -20,7 +20,7 @@ #include "catalog/dependency.h" #include "catalog/genbki.h" -#include "catalog/pg_constraint_d.h" +#include "catalog/pg_constraint_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" /* ---------------- @@ -51,6 +51,7 @@ CATALOG(pg_constraint,2606,ConstraintRelationId) char contype; /* constraint type; see codes below */ bool condeferrable; /* deferrable constraint? */ bool condeferred; /* deferred by default? */ + bool conenforced; /* enforced constraint? */ bool convalidated; /* constraint has been validated? */ /* @@ -107,6 +108,12 @@ CATALOG(pg_constraint,2606,ConstraintRelationId) /* Has a local definition and cannot be inherited */ bool connoinherit; + /* + * For primary keys, unique constraints, and foreign keys, signifies the + * last column uses overlaps instead of equals. + */ + bool conperiod; + #ifdef CATALOG_VARLEN /* variable-length fields start here */ /* @@ -121,20 +128,22 @@ CATALOG(pg_constraint,2606,ConstraintRelationId) int16 confkey[1]; /* - * If a foreign key, the OIDs of the PK = FK equality operators for each - * column of the constraint + * If a foreign key, the OIDs of the PK = FK equality/overlap operators + * for each column of the constraint */ Oid conpfeqop[1] BKI_LOOKUP(pg_operator); /* - * If a foreign key, the OIDs of the PK = PK equality operators for each - * column of the constraint (i.e., equality for the referenced columns) + * If a foreign key, the OIDs of the PK = PK equality/overlap operators + * for each column of the constraint (i.e., equality for the referenced + * columns) */ Oid conppeqop[1] BKI_LOOKUP(pg_operator); /* - * If a foreign key, the OIDs of the FK = FK equality operators for each - * column of the constraint (i.e., equality for the referencing columns) + * If a foreign key, the OIDs of the FK = FK equality/overlap operators + * for each column of the constraint (i.e., equality for the referencing + * columns) */ Oid conffeqop[1] BKI_LOOKUP(pg_operator); @@ -146,7 +155,8 @@ CATALOG(pg_constraint,2606,ConstraintRelationId) /* * If an exclusion constraint, the OIDs of the exclusion operators for - * each column of the constraint + * each column of the constraint. Also set for unique constraints/primary + * keys using WITHOUT OVERLAPS. */ Oid conexclop[1] BKI_LOOKUP(pg_operator); @@ -213,6 +223,7 @@ extern Oid CreateConstraintEntry(const char *constraintName, char constraintType, bool isDeferrable, bool isDeferred, + bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, @@ -236,8 +247,9 @@ extern Oid CreateConstraintEntry(const char *constraintName, Node *conExpr, const char *conBin, bool conIsLocal, - int conInhCount, + int16 conInhCount, bool conNoInherit, + bool conPeriod, bool is_internal); extern bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, @@ -247,7 +259,14 @@ extern char *ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others); +extern HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum); +extern HeapTuple findNotNullConstraint(Oid relid, const char *colname); extern HeapTuple findDomainNotNullConstraint(Oid typid); +extern AttrNumber extractNotNullColumn(HeapTuple constrTup); +extern bool AdjustNotNullInheritance(Oid relid, AttrNumber attnum, + bool is_local, bool is_no_inherit, bool is_notvalid); +extern List *RelationGetNotNullConstraints(Oid relid, bool cooked, + bool include_noinh); extern void RemoveConstraintById(Oid conId); extern void RenameConstraintById(Oid conId, const char *newname); @@ -269,6 +288,10 @@ extern void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols); +extern void FindFKPeriodOpers(Oid opclass, + Oid *containedbyoperoid, + Oid *aggedcontainedbyoperoid, + Oid *intersectoperoid); extern bool check_functional_grouping(Oid relid, Index varno, Index varlevelsup, diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h index e80ff8e4140a8..63e834a6ce477 100644 --- a/src/include/catalog/pg_control.h +++ b/src/include/catalog/pg_control.h @@ -5,7 +5,7 @@ * However, we define it here so that the format is documented. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_control.h @@ -22,7 +22,7 @@ /* Version identifier for this pg_control format */ -#define PG_CONTROL_VERSION 1700 +#define PG_CONTROL_VERSION 1800 /* Nonce key length, see below */ #define MOCK_AUTH_NONCE_LEN 32 @@ -221,6 +221,12 @@ typedef struct ControlFileData /* Are data pages protected by checksums? Zero if no checksum version */ uint32 data_checksum_version; + /* + * True if the default signedness of char is "signed" on a platform where + * the cluster is initialized. + */ + bool default_char_signedness; + /* * Random nonce, used in authentication requests that need to proceed * based on values that are cluster-unique, like a SASL exchange that diff --git a/src/include/catalog/pg_conversion.dat b/src/include/catalog/pg_conversion.dat index 145c4cc07db7f..0fb716cdc0ecc 100644 --- a/src/include/catalog/pg_conversion.dat +++ b/src/include/catalog/pg_conversion.dat @@ -3,7 +3,7 @@ # pg_conversion.dat # Initial contents of the pg_conversion system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_conversion.dat diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h index d94f022967256..477b8d09ae5ec 100644 --- a/src/include/catalog/pg_conversion.h +++ b/src/include/catalog/pg_conversion.h @@ -3,7 +3,7 @@ * pg_conversion.h * definition of the "conversion" system catalog (pg_conversion) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_conversion.h @@ -19,7 +19,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_conversion_d.h" +#include "catalog/pg_conversion_d.h" /* IWYU pragma: export */ /* ---------------- * pg_conversion definition. cpp turns this into diff --git a/src/include/catalog/pg_database.dat b/src/include/catalog/pg_database.dat index d134d52bb0fe5..1a7f3fed81a1a 100644 --- a/src/include/catalog/pg_database.dat +++ b/src/include/catalog/pg_database.dat @@ -3,7 +3,7 @@ # pg_database.dat # Initial contents of the pg_database system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_database.dat diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h index dbd4379ffa5b7..54f0d38c9c9e1 100644 --- a/src/include/catalog/pg_database.h +++ b/src/include/catalog/pg_database.h @@ -4,7 +4,7 @@ * definition of the "database" system catalog (pg_database) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_database.h @@ -19,7 +19,7 @@ #define PG_DATABASE_H #include "catalog/genbki.h" -#include "catalog/pg_database_d.h" +#include "catalog/pg_database_d.h" /* IWYU pragma: export */ /* ---------------- * pg_database definition. cpp turns this into diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h index 7e1a652381f9a..be5cde022862c 100644 --- a/src/include/catalog/pg_db_role_setting.h +++ b/src/include/catalog/pg_db_role_setting.h @@ -5,7 +5,7 @@ * configuration settings (pg_db_role_setting) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_db_role_setting.h @@ -20,7 +20,7 @@ #define PG_DB_ROLE_SETTING_H #include "catalog/genbki.h" -#include "catalog/pg_db_role_setting_d.h" +#include "catalog/pg_db_role_setting_d.h" /* IWYU pragma: export */ #include "utils/guc.h" #include "utils/relcache.h" diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h index d272cdf08b476..ce6e5098eaf02 100644 --- a/src/include/catalog/pg_default_acl.h +++ b/src/include/catalog/pg_default_acl.h @@ -5,7 +5,7 @@ * (pg_default_acl) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_default_acl.h @@ -20,7 +20,7 @@ #define PG_DEFAULT_ACL_H #include "catalog/genbki.h" -#include "catalog/pg_default_acl_d.h" +#include "catalog/pg_default_acl_d.h" /* IWYU pragma: export */ /* ---------------- * pg_default_acl definition. cpp turns this into @@ -68,6 +68,7 @@ MAKE_SYSCACHE(DEFACLROLENSPOBJ, pg_default_acl_role_nsp_obj_index, 8); #define DEFACLOBJ_FUNCTION 'f' /* function */ #define DEFACLOBJ_TYPE 'T' /* type */ #define DEFACLOBJ_NAMESPACE 'n' /* namespace */ +#define DEFACLOBJ_LARGEOBJECT 'L' /* large object */ #endif /* EXPOSE_TO_CLIENT_CODE */ diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h index eb1ee43b012eb..8d0daa9bb7a73 100644 --- a/src/include/catalog/pg_depend.h +++ b/src/include/catalog/pg_depend.h @@ -17,7 +17,7 @@ * convenient to find from the contents of other catalogs. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_depend.h @@ -32,7 +32,7 @@ #define PG_DEPEND_H #include "catalog/genbki.h" -#include "catalog/pg_depend_d.h" +#include "catalog/pg_depend_d.h" /* IWYU pragma: export */ /* ---------------- * pg_depend definition. cpp turns this into diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h index e30a6976beb04..4cd2bf904306a 100644 --- a/src/include/catalog/pg_description.h +++ b/src/include/catalog/pg_description.h @@ -23,7 +23,7 @@ * for example). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_description.h @@ -38,7 +38,7 @@ #define PG_DESCRIPTION_H #include "catalog/genbki.h" -#include "catalog/pg_description_d.h" +#include "catalog/pg_description_d.h" /* IWYU pragma: export */ /* ---------------- * pg_description definition. cpp turns this into diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h index 4d9a241d34890..7cb69ae013b5d 100644 --- a/src/include/catalog/pg_enum.h +++ b/src/include/catalog/pg_enum.h @@ -4,7 +4,7 @@ * definition of the "enum" system catalog (pg_enum) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_enum.h @@ -19,7 +19,7 @@ #define PG_ENUM_H #include "catalog/genbki.h" -#include "catalog/pg_enum_d.h" +#include "catalog/pg_enum_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h index 9170a4ddfe80f..bcb516c4f2dd5 100644 --- a/src/include/catalog/pg_event_trigger.h +++ b/src/include/catalog/pg_event_trigger.h @@ -4,7 +4,7 @@ * definition of the "event trigger" system catalog (pg_event_trigger) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_event_trigger.h @@ -19,7 +19,7 @@ #define PG_EVENT_TRIGGER_H #include "catalog/genbki.h" -#include "catalog/pg_event_trigger_d.h" +#include "catalog/pg_event_trigger_d.h" /* IWYU pragma: export */ /* ---------------- * pg_event_trigger definition. cpp turns this into diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h index cdfacc0930364..9214ebedafa3c 100644 --- a/src/include/catalog/pg_extension.h +++ b/src/include/catalog/pg_extension.h @@ -4,7 +4,7 @@ * definition of the "extension" system catalog (pg_extension) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_extension.h @@ -19,7 +19,7 @@ #define PG_EXTENSION_H #include "catalog/genbki.h" -#include "catalog/pg_extension_d.h" +#include "catalog/pg_extension_d.h" /* IWYU pragma: export */ /* ---------------- * pg_extension definition. cpp turns this into @@ -56,4 +56,7 @@ DECLARE_TOAST(pg_extension, 4147, 4148); DECLARE_UNIQUE_INDEX_PKEY(pg_extension_oid_index, 3080, ExtensionOidIndexId, pg_extension, btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, ExtensionNameIndexId, pg_extension, btree(extname name_ops)); +MAKE_SYSCACHE(EXTENSIONOID, pg_extension_oid_index, 2); +MAKE_SYSCACHE(EXTENSIONNAME, pg_extension_name_index, 2); + #endif /* PG_EXTENSION_H */ diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h index 0d8759d3fd385..d03ab5a4f28bf 100644 --- a/src/include/catalog/pg_foreign_data_wrapper.h +++ b/src/include/catalog/pg_foreign_data_wrapper.h @@ -4,7 +4,7 @@ * definition of the "foreign-data wrapper" system catalog (pg_foreign_data_wrapper) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_foreign_data_wrapper.h @@ -19,7 +19,7 @@ #define PG_FOREIGN_DATA_WRAPPER_H #include "catalog/genbki.h" -#include "catalog/pg_foreign_data_wrapper_d.h" +#include "catalog/pg_foreign_data_wrapper_d.h" /* IWYU pragma: export */ /* ---------------- * pg_foreign_data_wrapper definition. cpp turns this into diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h index a4b81936b0954..d53f0974c688e 100644 --- a/src/include/catalog/pg_foreign_server.h +++ b/src/include/catalog/pg_foreign_server.h @@ -3,7 +3,7 @@ * pg_foreign_server.h * definition of the "foreign server" system catalog (pg_foreign_server) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_foreign_server.h @@ -18,7 +18,7 @@ #define PG_FOREIGN_SERVER_H #include "catalog/genbki.h" -#include "catalog/pg_foreign_server_d.h" +#include "catalog/pg_foreign_server_d.h" /* IWYU pragma: export */ /* ---------------- * pg_foreign_server definition. cpp turns this into diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h index d17ff0e76e18b..aea94aa3faa6a 100644 --- a/src/include/catalog/pg_foreign_table.h +++ b/src/include/catalog/pg_foreign_table.h @@ -3,7 +3,7 @@ * pg_foreign_table.h * definition of the "foreign table" system catalog (pg_foreign_table) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_foreign_table.h @@ -18,7 +18,7 @@ #define PG_FOREIGN_TABLE_H #include "catalog/genbki.h" -#include "catalog/pg_foreign_table_d.h" +#include "catalog/pg_foreign_table_d.h" /* IWYU pragma: export */ /* ---------------- * pg_foreign_table definition. cpp turns this into diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h index 3462572eb55bb..4392b9d221d5a 100644 --- a/src/include/catalog/pg_index.h +++ b/src/include/catalog/pg_index.h @@ -4,7 +4,7 @@ * definition of the "index" system catalog (pg_index) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_index.h @@ -19,7 +19,7 @@ #define PG_INDEX_H #include "catalog/genbki.h" -#include "catalog/pg_index_d.h" +#include "catalog/pg_index_d.h" /* IWYU pragma: export */ /* ---------------- * pg_index definition. cpp turns this into @@ -69,6 +69,8 @@ CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO */ typedef FormData_pg_index *Form_pg_index; +DECLARE_TOAST_WITH_MACRO(pg_index, 8149, 8150, PgIndexToastTable, PgIndexToastIndex); + DECLARE_INDEX(pg_index_indrelid_index, 2678, IndexIndrelidIndexId, pg_index, btree(indrelid oid_ops)); DECLARE_UNIQUE_INDEX_PKEY(pg_index_indexrelid_index, 2679, IndexRelidIndexId, pg_index, btree(indexrelid oid_ops)); diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h index b3da78c24bd6b..1d6765ae9112c 100644 --- a/src/include/catalog/pg_inherits.h +++ b/src/include/catalog/pg_inherits.h @@ -4,7 +4,7 @@ * definition of the "inherits" system catalog (pg_inherits) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_inherits.h @@ -19,7 +19,7 @@ #define PG_INHERITS_H #include "catalog/genbki.h" -#include "catalog/pg_inherits_d.h" +#include "catalog/pg_inherits_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" #include "storage/lock.h" diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h index ecd5d0812b7c5..594efffca8f90 100644 --- a/src/include/catalog/pg_init_privs.h +++ b/src/include/catalog/pg_init_privs.h @@ -21,7 +21,7 @@ * are loaded near the end of initdb. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_init_privs.h @@ -36,7 +36,7 @@ #define PG_INIT_PRIVS_H #include "catalog/genbki.h" -#include "catalog/pg_init_privs_d.h" +#include "catalog/pg_init_privs_d.h" /* IWYU pragma: export */ /* ---------------- * pg_init_privs definition. cpp turns this into diff --git a/src/include/catalog/pg_language.dat b/src/include/catalog/pg_language.dat index 04c1c738c263b..84a958e2ef194 100644 --- a/src/include/catalog/pg_language.dat +++ b/src/include/catalog/pg_language.dat @@ -3,7 +3,7 @@ # pg_language.dat # Initial contents of the pg_language system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_language.dat diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h index 7256908a95c8a..3558b99858af9 100644 --- a/src/include/catalog/pg_language.h +++ b/src/include/catalog/pg_language.h @@ -4,7 +4,7 @@ * definition of the "language" system catalog (pg_language) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_language.h @@ -19,7 +19,7 @@ #define PG_LANGUAGE_H #include "catalog/genbki.h" -#include "catalog/pg_language_d.h" +#include "catalog/pg_language_d.h" /* IWYU pragma: export */ /* ---------------- * pg_language definition. cpp turns this into diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h index b40c90b749db3..42971bf3bbb6a 100644 --- a/src/include/catalog/pg_largeobject.h +++ b/src/include/catalog/pg_largeobject.h @@ -4,7 +4,7 @@ * definition of the "large object" system catalog (pg_largeobject) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_largeobject.h @@ -19,7 +19,8 @@ #define PG_LARGEOBJECT_H #include "catalog/genbki.h" -#include "catalog/pg_largeobject_d.h" +#include "catalog/pg_largeobject_d.h" /* IWYU pragma: export */ +#include "utils/snapshot.h" /* ---------------- * pg_largeobject definition. cpp turns this into @@ -49,5 +50,6 @@ DECLARE_UNIQUE_INDEX_PKEY(pg_largeobject_loid_pn_index, 2683, LargeObjectLOidPNI extern Oid LargeObjectCreate(Oid loid); extern void LargeObjectDrop(Oid loid); extern bool LargeObjectExists(Oid loid); +extern bool LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot); #endif /* PG_LARGEOBJECT_H */ diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h index 8a8274421870d..e618cd51e031e 100644 --- a/src/include/catalog/pg_largeobject_metadata.h +++ b/src/include/catalog/pg_largeobject_metadata.h @@ -5,7 +5,7 @@ * (pg_largeobject_metadata) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_largeobject_metadata.h @@ -20,7 +20,7 @@ #define PG_LARGEOBJECT_METADATA_H #include "catalog/genbki.h" -#include "catalog/pg_largeobject_metadata_d.h" +#include "catalog/pg_largeobject_metadata_d.h" /* IWYU pragma: export */ /* ---------------- * pg_largeobject_metadata definition. cpp turns this into diff --git a/src/include/catalog/pg_namespace.dat b/src/include/catalog/pg_namespace.dat index 816ec7ec8d143..008373728f338 100644 --- a/src/include/catalog/pg_namespace.dat +++ b/src/include/catalog/pg_namespace.dat @@ -3,7 +3,7 @@ # pg_namespace.dat # Initial contents of the pg_namespace system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_namespace.dat diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h index e101808ae1e0b..affb36f11407e 100644 --- a/src/include/catalog/pg_namespace.h +++ b/src/include/catalog/pg_namespace.h @@ -4,7 +4,7 @@ * definition of the "namespace" system catalog (pg_namespace) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_namespace.h @@ -19,7 +19,7 @@ #define PG_NAMESPACE_H #include "catalog/genbki.h" -#include "catalog/pg_namespace_d.h" +#include "catalog/pg_namespace_d.h" /* IWYU pragma: export */ #include "utils/acl.h" /* ---------------------------------------------------------------- diff --git a/src/include/catalog/pg_opclass.dat b/src/include/catalog/pg_opclass.dat index f503c652ebca6..4a9624802aa55 100644 --- a/src/include/catalog/pg_opclass.dat +++ b/src/include/catalog/pg_opclass.dat @@ -3,7 +3,7 @@ # pg_opclass.dat # Initial contents of the pg_opclass system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_opclass.dat diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 05867d08f9312..cb63bd9ced629 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -24,7 +24,7 @@ * AMs support this. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_opclass.h @@ -39,7 +39,7 @@ #define PG_OPCLASS_H #include "catalog/genbki.h" -#include "catalog/pg_opclass_d.h" +#include "catalog/pg_opclass_d.h" /* IWYU pragma: export */ /* ---------------- * pg_opclass definition. cpp turns this into diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat index 0e7511dde1c64..6d9dc1528d6eb 100644 --- a/src/include/catalog/pg_operator.dat +++ b/src/include/catalog/pg_operator.dat @@ -3,7 +3,7 @@ # pg_operator.dat # Initial contents of the pg_operator system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_operator.dat @@ -3150,7 +3150,8 @@ { oid => '3899', descr => 'range difference', oprname => '-', oprleft => 'anyrange', oprright => 'anyrange', oprresult => 'anyrange', oprcode => 'range_minus' }, -{ oid => '3900', descr => 'range intersection', +{ oid => '3900', oid_symbol => 'OID_RANGE_INTERSECT_RANGE_OP', + descr => 'range intersection', oprname => '*', oprleft => 'anyrange', oprright => 'anyrange', oprresult => 'anyrange', oprcom => '*(anyrange,anyrange)', oprcode => 'range_intersect' }, @@ -3417,7 +3418,8 @@ { oid => '4393', descr => 'multirange minus', oprname => '-', oprleft => 'anymultirange', oprright => 'anymultirange', oprresult => 'anymultirange', oprcode => 'multirange_minus' }, -{ oid => '4394', descr => 'multirange intersect', +{ oid => '4394', oid_symbol => 'OID_MULTIRANGE_INTERSECT_MULTIRANGE_OP', + descr => 'multirange intersect', oprname => '*', oprleft => 'anymultirange', oprright => 'anymultirange', oprresult => 'anymultirange', oprcom => '*(anymultirange,anymultirange)', oprcode => 'multirange_intersect' }, diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index 3ff1acc37ef9e..c3ddfb28fa4f0 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -4,7 +4,7 @@ * definition of the "operator" system catalog (pg_operator) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_operator.h @@ -20,7 +20,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_operator_d.h" +#include "catalog/pg_operator_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" /* ---------------- diff --git a/src/include/catalog/pg_opfamily.dat b/src/include/catalog/pg_opfamily.dat index c8ac8c73def7e..f7dcb96b43ce5 100644 --- a/src/include/catalog/pg_opfamily.dat +++ b/src/include/catalog/pg_opfamily.dat @@ -3,7 +3,7 @@ # pg_opfamily.dat # Initial contents of the pg_opfamily system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_opfamily.dat diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h index 52f9c4acf976b..7472e7e9cfa2e 100644 --- a/src/include/catalog/pg_opfamily.h +++ b/src/include/catalog/pg_opfamily.h @@ -4,7 +4,7 @@ * definition of the "operator family" system catalog (pg_opfamily) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_opfamily.h @@ -19,7 +19,7 @@ #define PG_OPFAMILY_H #include "catalog/genbki.h" -#include "catalog/pg_opfamily_d.h" +#include "catalog/pg_opfamily_d.h" /* IWYU pragma: export */ /* ---------------- * pg_opfamily definition. cpp turns this into diff --git a/src/include/catalog/pg_parameter_acl.h b/src/include/catalog/pg_parameter_acl.h index 8f6b6f92b3e6e..ae4049ba75608 100644 --- a/src/include/catalog/pg_parameter_acl.h +++ b/src/include/catalog/pg_parameter_acl.h @@ -5,7 +5,7 @@ * (pg_parameter_acl). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_parameter_acl.h @@ -20,7 +20,7 @@ #define PG_PARAMETER_ACL_H #include "catalog/genbki.h" -#include "catalog/pg_parameter_acl_d.h" +#include "catalog/pg_parameter_acl_d.h" /* IWYU pragma: export */ /* ---------------- * pg_parameter_acl definition. cpp turns this into diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h index daf57008b6963..0527f347690ca 100644 --- a/src/include/catalog/pg_partitioned_table.h +++ b/src/include/catalog/pg_partitioned_table.h @@ -5,7 +5,7 @@ * (pg_partitioned_table) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_partitioned_table.h @@ -20,7 +20,7 @@ #define PG_PARTITIONED_TABLE_H #include "catalog/genbki.h" -#include "catalog/pg_partitioned_table_d.h" +#include "catalog/pg_partitioned_table_d.h" /* IWYU pragma: export */ /* ---------------- * pg_partitioned_table definition. cpp turns this into diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h index 05d6398f7b865..3c2498cdf11f6 100644 --- a/src/include/catalog/pg_policy.h +++ b/src/include/catalog/pg_policy.h @@ -4,7 +4,7 @@ * definition of the "policy" system catalog (pg_policy) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_policy.h @@ -19,7 +19,7 @@ #define PG_POLICY_H #include "catalog/genbki.h" -#include "catalog/pg_policy_d.h" +#include "catalog/pg_policy_d.h" /* IWYU pragma: export */ /* ---------------- * pg_policy definition. cpp turns this into diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 06b2f4ba66c75..d3d28a263fa99 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -3,7 +3,7 @@ # pg_proc.dat # Initial contents of the pg_proc system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_proc.dat @@ -1004,18 +1004,27 @@ { oid => '3129', descr => 'sort support', proname => 'btint2sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'btint2sortsupport' }, +{ oid => '9290', descr => 'skip support', + proname => 'btint2skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btint2skipsupport' }, { oid => '351', descr => 'less-equal-greater', proname => 'btint4cmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'int4 int4', prosrc => 'btint4cmp' }, { oid => '3130', descr => 'sort support', proname => 'btint4sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'btint4sortsupport' }, +{ oid => '9291', descr => 'skip support', + proname => 'btint4skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btint4skipsupport' }, { oid => '842', descr => 'less-equal-greater', proname => 'btint8cmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'int8 int8', prosrc => 'btint8cmp' }, { oid => '3131', descr => 'sort support', proname => 'btint8sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'btint8sortsupport' }, +{ oid => '9292', descr => 'skip support', + proname => 'btint8skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btint8skipsupport' }, { oid => '354', descr => 'less-equal-greater', proname => 'btfloat4cmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'float4 float4', prosrc => 'btfloat4cmp' }, @@ -1034,12 +1043,18 @@ { oid => '3134', descr => 'sort support', proname => 'btoidsortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'btoidsortsupport' }, +{ oid => '9293', descr => 'skip support', + proname => 'btoidskipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btoidskipsupport' }, { oid => '404', descr => 'less-equal-greater', proname => 'btoidvectorcmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'oidvector oidvector', prosrc => 'btoidvectorcmp' }, { oid => '358', descr => 'less-equal-greater', proname => 'btcharcmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'char char', prosrc => 'btcharcmp' }, +{ oid => '9294', descr => 'skip support', + proname => 'btcharskipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btcharskipsupport' }, { oid => '359', descr => 'less-equal-greater', proname => 'btnamecmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'name name', prosrc => 'btnamecmp' }, @@ -1165,6 +1180,25 @@ proname => 'name', proleakproof => 't', prorettype => 'name', proargtypes => 'bpchar', prosrc => 'bpchar_name' }, +{ oid => '8577', descr => 'convert int2 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int2', prosrc => 'int2_bytea' }, +{ oid => '8578', descr => 'convert int4 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int4', prosrc => 'int4_bytea' }, +{ oid => '8579', descr => 'convert int8 to bytea', + proname => 'bytea', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'int8', prosrc => 'int8_bytea' }, +{ oid => '8580', descr => 'convert bytea to int2', + proname => 'int2', prorettype => 'int2', + proargtypes => 'bytea', prosrc => 'bytea_int2' }, +{ oid => '8581', descr => 'convert bytea to int4', + proname => 'int4', prorettype => 'int4', + proargtypes => 'bytea', prosrc => 'bytea_int4' }, +{ oid => '8582', descr => 'convert bytea to int8', + proname => 'int8', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'bytea_int8' }, + { oid => '449', descr => 'hash', proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2', prosrc => 'hashint2' }, @@ -1225,6 +1259,12 @@ { oid => '772', descr => 'hash', proname => 'hashvarlenaextended', prorettype => 'int8', proargtypes => 'internal int8', prosrc => 'hashvarlenaextended' }, +{ oid => '9708', descr => 'hash', + proname => 'hashbytea', prorettype => 'int4', proargtypes => 'bytea', + prosrc => 'hashbytea' }, +{ oid => '9709', descr => 'hash', + proname => 'hashbyteaextended', prorettype => 'int8', + proargtypes => 'bytea int8', prosrc => 'hashbyteaextended' }, { oid => '457', descr => 'hash', proname => 'hashoidvector', prorettype => 'int4', proargtypes => 'oidvector', prosrc => 'hashoidvector' }, @@ -1261,6 +1301,36 @@ { oid => '781', descr => 'hash', proname => 'hashmacaddr8extended', prorettype => 'int8', proargtypes => 'macaddr8 int8', prosrc => 'hashmacaddr8extended' }, +{ oid => '9710', descr => 'hash', + proname => 'hashdate', prorettype => 'int4', proargtypes => 'date', + prosrc => 'hashdate' }, +{ oid => '9711', descr => 'hash', + proname => 'hashdateextended', prorettype => 'int8', + proargtypes => 'date int8', prosrc => 'hashdateextended' }, +{ oid => '9712', descr => 'hash', + proname => 'hashbool', prorettype => 'int4', proargtypes => 'bool', + prosrc => 'hashbool' }, +{ oid => '9713', descr => 'hash', + proname => 'hashboolextended', prorettype => 'int8', + proargtypes => 'bool int8', prosrc => 'hashboolextended' }, +{ oid => '9714', descr => 'hash', + proname => 'hashxid', prorettype => 'int4', proargtypes => 'xid', + prosrc => 'hashxid' }, +{ oid => '9715', descr => 'hash', + proname => 'hashxidextended', prorettype => 'int8', proargtypes => 'xid int8', + prosrc => 'hashxidextended' }, +{ oid => '9716', descr => 'hash', + proname => 'hashxid8', prorettype => 'int4', proargtypes => 'xid8', + prosrc => 'hashxid8' }, +{ oid => '9717', descr => 'hash', + proname => 'hashxid8extended', prorettype => 'int8', + proargtypes => 'xid8 int8', prosrc => 'hashxid8extended' }, +{ oid => '9718', descr => 'hash', + proname => 'hashcid', prorettype => 'int4', proargtypes => 'cid', + prosrc => 'hashcid' }, +{ oid => '9719', descr => 'hash', + proname => 'hashcidextended', prorettype => 'int8', proargtypes => 'cid int8', + prosrc => 'hashcidextended' }, { oid => '438', descr => 'count the number of NULL arguments', proname => 'num_nulls', provariadic => 'any', proisstrict => 'f', @@ -1278,6 +1348,13 @@ proname => 'text_smaller', proleakproof => 't', prorettype => 'text', proargtypes => 'text text', prosrc => 'text_smaller' }, +{ oid => '8920', descr => 'larger of two', + proname => 'bytea_larger', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'bytea bytea', prosrc => 'bytea_larger' }, +{ oid => '8921', descr => 'smaller of two', + proname => 'bytea_smaller', proleakproof => 't', prorettype => 'bytea', + proargtypes => 'bytea bytea', prosrc => 'bytea_smaller' }, + { oid => '460', descr => 'I/O', proname => 'int8in', prorettype => 'int8', proargtypes => 'cstring', prosrc => 'int8in' }, @@ -1456,6 +1533,9 @@ { oid => '6163', descr => 'number of set bits', proname => 'bit_count', prorettype => 'int8', proargtypes => 'bytea', prosrc => 'bytea_bit_count' }, +{ oid => '8694', descr => 'reverse bytea', + proname => 'reverse', prorettype => 'bytea', proargtypes => 'bytea', + prosrc => 'bytea_reverse' }, { oid => '725', proname => 'dist_pl', prorettype => 'float8', proargtypes => 'point line', @@ -1555,14 +1635,20 @@ proname => 'cardinality', prorettype => 'int4', proargtypes => 'anyarray', prosrc => 'array_cardinality' }, { oid => '378', descr => 'append element onto end of array', - proname => 'array_append', proisstrict => 'f', - prorettype => 'anycompatiblearray', + proname => 'array_append', prosupport => 'array_append_support', + proisstrict => 'f', prorettype => 'anycompatiblearray', proargtypes => 'anycompatiblearray anycompatible', prosrc => 'array_append' }, +{ oid => '8680', descr => 'planner support for array_append', + proname => 'array_append_support', prorettype => 'internal', + proargtypes => 'internal', prosrc => 'array_append_support' }, { oid => '379', descr => 'prepend element onto front of array', - proname => 'array_prepend', proisstrict => 'f', - prorettype => 'anycompatiblearray', + proname => 'array_prepend', prosupport => 'array_prepend_support', + proisstrict => 'f', prorettype => 'anycompatiblearray', proargtypes => 'anycompatible anycompatiblearray', prosrc => 'array_prepend' }, +{ oid => '8681', descr => 'planner support for array_prepend', + proname => 'array_prepend_support', prorettype => 'internal', + proargtypes => 'internal', prosrc => 'array_prepend_support' }, { oid => '383', proname => 'array_cat', proisstrict => 'f', prorettype => 'anycompatiblearray', @@ -1698,6 +1784,21 @@ { oid => '6216', descr => 'take samples from array', proname => 'array_sample', provolatile => 'v', prorettype => 'anyarray', proargtypes => 'anyarray int4', prosrc => 'array_sample' }, +{ oid => '8686', descr => 'reverse array', + proname => 'array_reverse', prorettype => 'anyarray', + proargtypes => 'anyarray', prosrc => 'array_reverse' }, +{ oid => '8810', descr => 'sort array', + proname => 'array_sort', prorettype => 'anyarray', proargtypes => 'anyarray', + prosrc => 'array_sort' }, +{ oid => '8811', descr => 'sort array', + proname => 'array_sort', prorettype => 'anyarray', + proargtypes => 'anyarray bool', proargnames => '{array,descending}', + prosrc => 'array_sort_order' }, +{ oid => '8812', descr => 'sort array', + proname => 'array_sort', prorettype => 'anyarray', + proargtypes => 'anyarray bool bool', + proargnames => '{array,descending,nulls_first}', + prosrc => 'array_sort_order_nulls_first' }, { oid => '3816', descr => 'array typanalyze', proname => 'array_typanalyze', provolatile => 's', prorettype => 'bool', proargtypes => 'internal', prosrc => 'array_typanalyze' }, @@ -2214,6 +2315,9 @@ { oid => '3136', descr => 'sort support', proname => 'date_sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'date_sortsupport' }, +{ oid => '9295', descr => 'skip support', + proname => 'date_skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'date_skipsupport' }, { oid => '4133', descr => 'window RANGE support', proname => 'in_range', prorettype => 'bool', proargtypes => 'date date interval bool bool', @@ -3329,6 +3433,12 @@ proname => 'pg_sequence_last_value', provolatile => 'v', proparallel => 'u', prorettype => 'int8', proargtypes => 'regclass', prosrc => 'pg_sequence_last_value' }, +{ oid => '9876', descr => 'return sequence tuple, for use by pg_dump', + proname => 'pg_get_sequence_data', provolatile => 'v', proparallel => 'u', + prorettype => 'record', proargtypes => 'regclass', + proallargtypes => '{regclass,int8,bool}', proargmodes => '{i,o,o}', + proargnames => '{sequence_oid,last_value,is_called}', + prosrc => 'pg_get_sequence_data' }, { oid => '275', descr => 'return the next oid for a system table', proname => 'pg_nextoid', provolatile => 'v', proparallel => 'u', @@ -3484,6 +3594,13 @@ proname => 'erfc', prorettype => 'float8', proargtypes => 'float8', prosrc => 'derfc' }, +{ oid => '8702', descr => 'gamma function', + proname => 'gamma', prorettype => 'float8', proargtypes => 'float8', + prosrc => 'dgamma' }, +{ oid => '8703', descr => 'natural logarithm of absolute value of gamma function', + proname => 'lgamma', prorettype => 'float8', proargtypes => 'float8', + prosrc => 'dlgamma' }, + { oid => '1618', proname => 'interval_mul', prorettype => 'interval', proargtypes => 'interval float8', prosrc => 'interval_mul' }, @@ -3571,6 +3688,9 @@ { oid => '872', descr => 'capitalize each word', proname => 'initcap', prorettype => 'text', proargtypes => 'text', prosrc => 'initcap' }, +{ oid => '9569', descr => 'fold case', + proname => 'casefold', prorettype => 'text', proargtypes => 'text', + prosrc => 'casefold' }, { oid => '873', descr => 'left-pad string to length', proname => 'lpad', prorettype => 'text', proargtypes => 'text int4 text', prosrc => 'lpad' }, @@ -4395,6 +4515,9 @@ { oid => '1693', descr => 'less-equal-greater', proname => 'btboolcmp', proleakproof => 't', prorettype => 'int4', proargtypes => 'bool bool', prosrc => 'btboolcmp' }, +{ oid => '9296', descr => 'skip support', + proname => 'btboolskipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'btboolskipsupport' }, { oid => '1688', descr => 'hash', proname => 'time_hash', prorettype => 'int4', proargtypes => 'time', @@ -5327,6 +5450,22 @@ prorettype => 'bool', proargtypes => 'oid text', prosrc => 'has_any_column_privilege_id' }, +{ oid => '8048', + descr => 'user privilege on large object by username, large object oid', + proname => 'has_largeobject_privilege', procost => '10', provolatile => 's', + prorettype => 'bool', proargtypes => 'name oid text', + prosrc => 'has_largeobject_privilege_name_id' }, +{ oid => '8049', + descr => 'current user privilege on large object by large object oid', + proname => 'has_largeobject_privilege', procost => '10', provolatile => 's', + prorettype => 'bool', proargtypes => 'oid text', + prosrc => 'has_largeobject_privilege_id' }, +{ oid => '8050', + descr => 'user privilege on large object by user oid, large object oid', + proname => 'has_largeobject_privilege', procost => '10', provolatile => 's', + prorettype => 'bool', proargtypes => 'oid oid text', + prosrc => 'has_largeobject_privilege_id_id' }, + { oid => '3355', descr => 'I/O', proname => 'pg_ndistinct_in', prorettype => 'pg_ndistinct', proargtypes => 'cstring', prosrc => 'pg_ndistinct_in' }, @@ -5472,6 +5611,22 @@ proname => 'pg_stat_get_autoanalyze_count', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_stat_get_autoanalyze_count' }, +{ oid => '8406', descr => 'total vacuum time, in milliseconds', + proname => 'pg_stat_get_total_vacuum_time', provolatile => 's', + proparallel => 'r', prorettype => 'float8', proargtypes => 'oid', + prosrc => 'pg_stat_get_total_vacuum_time' }, +{ oid => '8407', descr => 'total autovacuum time, in milliseconds', + proname => 'pg_stat_get_total_autovacuum_time', provolatile => 's', + proparallel => 'r', prorettype => 'float8', proargtypes => 'oid', + prosrc => 'pg_stat_get_total_autovacuum_time' }, +{ oid => '8408', descr => 'total analyze time, in milliseconds', + proname => 'pg_stat_get_total_analyze_time', provolatile => 's', + proparallel => 'r', prorettype => 'float8', proargtypes => 'oid', + prosrc => 'pg_stat_get_total_analyze_time' }, +{ oid => '8409', descr => 'total autoanalyze time, in milliseconds', + proname => 'pg_stat_get_total_autoanalyze_time', provolatile => 's', + proparallel => 'r', prorettype => 'float8', proargtypes => 'oid', + prosrc => 'pg_stat_get_total_autoanalyze_time' }, { oid => '1936', descr => 'statistics: currently active backend IDs', proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't', provolatile => 's', proparallel => 'r', prorettype => 'int4', @@ -5526,15 +5681,15 @@ { oid => '6230', descr => 'statistics: check if a stats object exists', proname => 'pg_stat_have_stats', provolatile => 'v', proparallel => 'r', - prorettype => 'bool', proargtypes => 'text oid oid', + prorettype => 'bool', proargtypes => 'text oid int8', prosrc => 'pg_stat_have_stats' }, { oid => '6231', descr => 'statistics: information about subscription stats', proname => 'pg_stat_get_subscription_stats', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => 'oid', - proallargtypes => '{oid,oid,int8,int8,timestamptz}', - proargmodes => '{i,o,o,o,o}', - proargnames => '{subid,subid,apply_error_count,sync_error_count,stats_reset}', + proallargtypes => '{oid,oid,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}', + proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{subid,subid,apply_error_count,sync_error_count,confl_insert_exists,confl_update_origin_differs,confl_update_exists,confl_update_missing,confl_delete_origin_differs,confl_delete_missing,confl_multiple_unique_conflicts,stats_reset}', prosrc => 'pg_stat_get_subscription_stats' }, { oid => '6118', descr => 'statistics: information about subscription', proname => 'pg_stat_get_subscription', prorows => '10', proisstrict => 'f', @@ -5745,6 +5900,16 @@ proname => 'pg_stat_get_db_sessions_killed', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => 'oid', prosrc => 'pg_stat_get_db_sessions_killed' }, +{ oid => '8403', + descr => 'statistics: number of parallel workers planned to be launched by queries', + proname => 'pg_stat_get_db_parallel_workers_to_launch', provolatile => 's', + proparallel => 'r', prorettype => 'int8', proargtypes => 'oid', + prosrc => 'pg_stat_get_db_parallel_workers_to_launch' }, +{ oid => '8404', + descr => 'statistics: number of parallel workers effectively launched by queries', + proname => 'pg_stat_get_db_parallel_workers_launched', provolatile => 's', + proparallel => 'r', prorettype => 'int8', proargtypes => 'oid', + prosrc => 'pg_stat_get_db_parallel_workers_launched' }, { oid => '3195', descr => 'statistics: information about WAL archiver', proname => 'pg_stat_get_archiver', proisstrict => 'f', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => '', @@ -5758,23 +5923,28 @@ proparallel => 'r', prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_checkpointer_num_timed' }, { oid => '2770', - descr => 'statistics: number of backend requested checkpoints started by the checkpointer', + descr => 'statistics: number of requested checkpoints started by the checkpointer', proname => 'pg_stat_get_checkpointer_num_requested', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_checkpointer_num_requested' }, +{ oid => '8599', + descr => 'statistics: number of checkpoints performed by the checkpointer', + proname => 'pg_stat_get_checkpointer_num_performed', provolatile => 's', + proparallel => 'r', prorettype => 'int8', proargtypes => '', + prosrc => 'pg_stat_get_checkpointer_num_performed' }, { oid => '6327', descr => 'statistics: number of timed restartpoints started by the checkpointer', proname => 'pg_stat_get_checkpointer_restartpoints_timed', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_checkpointer_restartpoints_timed' }, { oid => '6328', - descr => 'statistics: number of backend requested restartpoints started by the checkpointer', + descr => 'statistics: number of requested restartpoints started by the checkpointer', proname => 'pg_stat_get_checkpointer_restartpoints_requested', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_checkpointer_restartpoints_requested' }, { oid => '6329', - descr => 'statistics: number of backend performed restartpoints', + descr => 'statistics: number of restartpoints performed by the checkpointer', proname => 'pg_stat_get_checkpointer_restartpoints_performed', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => '', @@ -5784,6 +5954,11 @@ proname => 'pg_stat_get_checkpointer_buffers_written', provolatile => 's', proparallel => 'r', prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_checkpointer_buffers_written' }, +{ oid => '8573', + descr => 'statistics: number of SLRU buffers written during checkpoints and restartpoints', + proname => 'pg_stat_get_checkpointer_slru_written', provolatile => 's', + proparallel => 'r', prorettype => 'int8', proargtypes => '', + prosrc => 'pg_stat_get_checkpointer_slru_written' }, { oid => '6314', descr => 'statistics: last reset for the checkpointer', proname => 'pg_stat_get_checkpointer_stat_reset_time', provolatile => 's', proparallel => 'r', prorettype => 'timestamptz', proargtypes => '', @@ -5820,18 +5995,34 @@ proname => 'pg_stat_get_io', prorows => '30', proretset => 't', provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => '', - proallargtypes => '{text,text,text,int8,float8,int8,float8,int8,float8,int8,float8,int8,int8,int8,int8,int8,float8,timestamptz}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{backend_type,object,context,reads,read_time,writes,write_time,writebacks,writeback_time,extends,extend_time,op_bytes,hits,evictions,reuses,fsyncs,fsync_time,stats_reset}', + proallargtypes => '{text,text,text,int8,numeric,float8,int8,numeric,float8,int8,float8,int8,numeric,float8,int8,int8,int8,int8,float8,timestamptz}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{backend_type,object,context,reads,read_bytes,read_time,writes,write_bytes,write_time,writebacks,writeback_time,extends,extend_bytes,extend_time,hits,evictions,reuses,fsyncs,fsync_time,stats_reset}', prosrc => 'pg_stat_get_io' }, +{ oid => '8806', descr => 'statistics: backend IO statistics', + proname => 'pg_stat_get_backend_io', prorows => '5', proretset => 't', + provolatile => 'v', proparallel => 'r', prorettype => 'record', + proargtypes => 'int4', + proallargtypes => '{int4,text,text,text,int8,numeric,float8,int8,numeric,float8,int8,float8,int8,numeric,float8,int8,int8,int8,int8,float8,timestamptz}', + proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{backend_pid,backend_type,object,context,reads,read_bytes,read_time,writes,write_bytes,write_time,writebacks,writeback_time,extends,extend_bytes,extend_time,hits,evictions,reuses,fsyncs,fsync_time,stats_reset}', + prosrc => 'pg_stat_get_backend_io' }, + { oid => '1136', descr => 'statistics: information about WAL activity', proname => 'pg_stat_get_wal', proisstrict => 'f', provolatile => 's', proparallel => 'r', prorettype => 'record', proargtypes => '', - proallargtypes => '{int8,int8,numeric,int8,int8,int8,float8,float8,timestamptz}', - proargmodes => '{o,o,o,o,o,o,o,o,o}', - proargnames => '{wal_records,wal_fpi,wal_bytes,wal_buffers_full,wal_write,wal_sync,wal_write_time,wal_sync_time,stats_reset}', + proallargtypes => '{int8,int8,numeric,int8,timestamptz}', + proargmodes => '{o,o,o,o,o}', + proargnames => '{wal_records,wal_fpi,wal_bytes,wal_buffers_full,stats_reset}', prosrc => 'pg_stat_get_wal' }, +{ oid => '8037', descr => 'statistics: backend WAL activity', + proname => 'pg_stat_get_backend_wal', provolatile => 'v', proparallel => 'r', + prorettype => 'record', proargtypes => 'int4', + proallargtypes => '{int4,int8,int8,numeric,int8,timestamptz}', + proargmodes => '{i,o,o,o,o,o}', + proargnames => '{backend_pid,wal_records,wal_fpi,wal_bytes,wal_buffers_full,stats_reset}', + prosrc => 'pg_stat_get_backend_wal' }, { oid => '6248', descr => 'statistics: information about WAL prefetching', proname => 'pg_stat_get_recovery_prefetch', prorows => '1', proretset => 't', provolatile => 'v', prorettype => 'record', proargtypes => '', @@ -5964,6 +6155,10 @@ proname => 'pg_stat_reset_single_function_counters', provolatile => 'v', prorettype => 'void', proargtypes => 'oid', prosrc => 'pg_stat_reset_single_function_counters' }, +{ oid => '8807', descr => 'statistics: reset statistics for a single backend', + proname => 'pg_stat_reset_backend_stats', provolatile => 'v', + prorettype => 'void', proargtypes => 'int4', + prosrc => 'pg_stat_reset_backend_stats' }, { oid => '2307', descr => 'statistics: reset collected statistics for a single SLRU', proname => 'pg_stat_reset_slru', proisstrict => 'f', provolatile => 'v', @@ -6174,6 +6369,12 @@ { oid => '3411', descr => 'hash', proname => 'timestamp_hash_extended', prorettype => 'int8', proargtypes => 'timestamp int8', prosrc => 'timestamp_hash_extended' }, +{ oid => '9720', descr => 'hash', + proname => 'timestamptz_hash', prorettype => 'int4', + proargtypes => 'timestamptz', prosrc => 'timestamptz_hash' }, +{ oid => '9721', descr => 'hash', + proname => 'timestamptz_hash_extended', prorettype => 'int8', + proargtypes => 'timestamptz int8', prosrc => 'timestamptz_hash_extended' }, { oid => '2041', descr => 'intervals overlap?', proname => 'overlaps', proisstrict => 'f', prorettype => 'bool', proargtypes => 'timestamp timestamp timestamp timestamp', @@ -6196,6 +6397,9 @@ { oid => '3137', descr => 'sort support', proname => 'timestamp_sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'timestamp_sortsupport' }, +{ oid => '9297', descr => 'skip support', + proname => 'timestamp_skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'timestamp_skipsupport' }, { oid => '4134', descr => 'window RANGE support', proname => 'in_range', prorettype => 'bool', @@ -6588,6 +6792,13 @@ proargnames => '{rm_id, rm_name, rm_builtin}', prosrc => 'pg_get_wal_resource_managers' }, +{ oid => '8303', descr => 'get info about loaded modules', + proname => 'pg_get_loaded_modules', prorows => '10', proretset => 't', + provolatile => 'v', proparallel => 'r', prorettype => 'record', + proargtypes => '', proallargtypes => '{text,text,text}', + proargmodes => '{o,o,o}', proargnames => '{module_name,version,file_name}', + prosrc => 'pg_get_loaded_modules' }, + { oid => '2621', descr => 'reload configuration files', proname => 'pg_reload_conf', provolatile => 'v', prorettype => 'bool', proargtypes => '', prosrc => 'pg_reload_conf' }, @@ -6799,6 +7010,9 @@ { oid => '5099', descr => 'maximum value of all xid8 input values', proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'xid8', proargtypes => 'xid8', prosrc => 'aggregate_dummy' }, +{ oid => '8922', descr => 'maximum value of all bytea input values', + proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bytea', + proargtypes => 'bytea', prosrc => 'aggregate_dummy' }, { oid => '2131', descr => 'minimum value of all bigint input values', proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int8', @@ -6872,6 +7086,9 @@ { oid => '5100', descr => 'minimum value of all xid8 input values', proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'xid8', proargtypes => 'xid8', prosrc => 'aggregate_dummy' }, +{ oid => '8923', descr => 'minimum value of all bytea input values', + proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bytea', + proargtypes => 'bytea', prosrc => 'aggregate_dummy' }, # count has two forms: count(any) and count(*) { oid => '2147', @@ -7731,6 +7948,14 @@ proname => 'system', provolatile => 'v', prorettype => 'tsm_handler', proargtypes => 'internal', prosrc => 'tsm_system_handler' }, +# CRC variants +{ oid => '8571', descr => 'CRC-32 value', + proname => 'crc32', proleakproof => 't', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'crc32_bytea' }, +{ oid => '8572', descr => 'CRC-32C value', + proname => 'crc32c', proleakproof => 't', prorettype => 'int8', + proargtypes => 'bytea', prosrc => 'crc32c_bytea' }, + # cryptographic { oid => '2311', descr => 'MD5 hash', proname => 'md5', proleakproof => 't', prorettype => 'text', @@ -8271,12 +8496,18 @@ proargmodes => '{o,o,o,o,o,o}', proargnames => '{name,statement,is_holdable,is_binary,is_scrollable,creation_time}', prosrc => 'pg_cursor' }, -{ oid => '2599', descr => 'get the available time zone abbreviations', - proname => 'pg_timezone_abbrevs', prorows => '1000', proretset => 't', +{ oid => '9221', descr => 'get abbreviations from current timezone', + proname => 'pg_timezone_abbrevs_zone', prorows => '10', proretset => 't', + provolatile => 's', prorettype => 'record', proargtypes => '', + proallargtypes => '{text,interval,bool}', proargmodes => '{o,o,o}', + proargnames => '{abbrev,utc_offset,is_dst}', + prosrc => 'pg_timezone_abbrevs_zone' }, +{ oid => '2599', descr => 'get abbreviations from timezone_abbreviations', + proname => 'pg_timezone_abbrevs_abbrevs', prorows => '1000', proretset => 't', provolatile => 's', prorettype => 'record', proargtypes => '', proallargtypes => '{text,interval,bool}', proargmodes => '{o,o,o}', proargnames => '{abbrev,utc_offset,is_dst}', - prosrc => 'pg_timezone_abbrevs' }, + prosrc => 'pg_timezone_abbrevs_abbrevs' }, { oid => '2856', descr => 'get the available time zone names', proname => 'pg_timezone_names', prorows => '1000', proretset => 't', provolatile => 's', prorettype => 'record', proargtypes => '', @@ -8311,15 +8542,27 @@ proargnames => '{name,off,size,allocated_size}', prosrc => 'pg_get_shmem_allocations' }, +{ oid => '4099', descr => 'Is NUMA support available?', + proname => 'pg_numa_available', provolatile => 's', prorettype => 'bool', + proargtypes => '', prosrc => 'pg_numa_available' }, + +# shared memory usage with NUMA info +{ oid => '4100', descr => 'NUMA mappings for the main shared memory segment', + proname => 'pg_get_shmem_allocations_numa', prorows => '50', proretset => 't', + provolatile => 'v', prorettype => 'record', proargtypes => '', + proallargtypes => '{text,int4,int8}', proargmodes => '{o,o,o}', + proargnames => '{name,numa_node,size}', + prosrc => 'pg_get_shmem_allocations_numa' }, + # memory context of local backend { oid => '2282', descr => 'information about all memory contexts of local backend', proname => 'pg_get_backend_memory_contexts', prorows => '100', proretset => 't', provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => '', - proallargtypes => '{text,text,text,text,int4,_int4,int8,int8,int8,int8,int8}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{name, ident, parent, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes}', + proallargtypes => '{text,text,text,int4,_int4,int8,int8,int8,int8,int8}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o}', + proargnames => '{name, ident, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes}', prosrc => 'pg_get_backend_memory_contexts' }, # logging memory contexts of the specified backend @@ -8356,13 +8599,18 @@ proname => 'generate_series_int8_support', prorettype => 'internal', proargtypes => 'internal', prosrc => 'generate_series_int8_support' }, { oid => '3259', descr => 'non-persistent series generator', - proname => 'generate_series', prorows => '1000', proretset => 't', + proname => 'generate_series', prorows => '1000', + prosupport => 'generate_series_numeric_support', proretset => 't', prorettype => 'numeric', proargtypes => 'numeric numeric numeric', prosrc => 'generate_series_step_numeric' }, { oid => '3260', descr => 'non-persistent series generator', - proname => 'generate_series', prorows => '1000', proretset => 't', + proname => 'generate_series', prorows => '1000', + prosupport => 'generate_series_numeric_support', proretset => 't', prorettype => 'numeric', proargtypes => 'numeric numeric', prosrc => 'generate_series_numeric' }, +{ oid => '8405', descr => 'planner support for generate_series', + proname => 'generate_series_numeric_support', prorettype => 'internal', + proargtypes => 'internal', prosrc => 'generate_series_numeric_support' }, { oid => '938', descr => 'non-persistent series generator', proname => 'generate_series', prorows => '1000', prosupport => 'generate_series_timestamp_support', proretset => 't', @@ -9112,7 +9360,7 @@ proname => 'to_json', provolatile => 's', prorettype => 'json', proargtypes => 'anyelement', prosrc => 'to_json' }, { oid => '3261', descr => 'remove object fields with null values from json', - proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json', + proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json bool', prosrc => 'json_strip_nulls' }, { oid => '3947', @@ -9219,6 +9467,9 @@ { oid => '3300', descr => 'sort support', proname => 'uuid_sortsupport', prorettype => 'void', proargtypes => 'internal', prosrc => 'uuid_sortsupport' }, +{ oid => '9298', descr => 'skip support', + proname => 'uuid_skipsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'uuid_skipsupport' }, { oid => '2961', descr => 'I/O', proname => 'uuid_recv', prorettype => 'uuid', proargtypes => 'internal', prosrc => 'uuid_recv' }, @@ -9232,13 +9483,22 @@ proname => 'uuid_hash_extended', prorettype => 'int8', proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' }, { oid => '3432', descr => 'generate random UUID', - proname => 'gen_random_uuid', proleakproof => 't', provolatile => 'v', + proname => 'gen_random_uuid', provolatile => 'v', prorettype => 'uuid', proargtypes => '', prosrc => 'gen_random_uuid' }, +{ oid => '9895', descr => 'generate UUID version 4', + proname => 'uuidv4', provolatile => 'v', + prorettype => 'uuid', proargtypes => '', prosrc => 'gen_random_uuid' }, +{ oid => '9896', descr => 'generate UUID version 7', + proname => 'uuidv7', provolatile => 'v', + prorettype => 'uuid', proargtypes => '', prosrc => 'uuidv7' }, +{ oid => '9897', descr => 'generate UUID version 7 with a timestamp shifted by specified interval', + proname => 'uuidv7', provolatile => 'v', proargnames => '{shift}', + prorettype => 'uuid', proargtypes => 'interval', prosrc => 'uuidv7_interval' }, { oid => '6342', descr => 'extract timestamp from UUID', proname => 'uuid_extract_timestamp', proleakproof => 't', prorettype => 'timestamptz', proargtypes => 'uuid', prosrc => 'uuid_extract_timestamp' }, -{ oid => '6343', descr => 'extract version from RFC 4122 UUID', +{ oid => '6343', descr => 'extract version from RFC 9562 UUID', proname => 'uuid_extract_version', proleakproof => 't', prorettype => 'int2', proargtypes => 'uuid', prosrc => 'uuid_extract_version' }, @@ -10039,7 +10299,7 @@ prorettype => 'jsonb', proargtypes => '', prosrc => 'jsonb_build_object_noargs' }, { oid => '3262', descr => 'remove object fields with null values from jsonb', - proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb', + proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb bool', prosrc => 'jsonb_strip_nulls' }, { oid => '3478', @@ -10634,6 +10894,9 @@ { oid => '3870', descr => 'less-equal-greater', proname => 'range_cmp', prorettype => 'int4', proargtypes => 'anyrange anyrange', prosrc => 'range_cmp' }, +{ oid => '8849', descr => 'sort support', + proname => 'range_sortsupport', prorettype => 'void', + proargtypes => 'internal', prosrc => 'range_sortsupport' }, { oid => '3871', proname => 'range_lt', prorettype => 'bool', proargtypes => 'anyrange anyrange', prosrc => 'range_lt' }, @@ -11200,9 +11463,9 @@ proname => 'pg_get_replication_slots', prorows => '10', proisstrict => 'f', proretset => 't', provolatile => 's', prorettype => 'record', proargtypes => '', - proallargtypes => '{name,name,text,oid,bool,bool,int4,xid,xid,pg_lsn,pg_lsn,text,int8,bool,timestamptz,bool,text,bool,bool}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size,two_phase,inactive_since,conflicting,invalidation_reason,failover,synced}', + proallargtypes => '{name,name,text,oid,bool,bool,int4,xid,xid,pg_lsn,pg_lsn,text,int8,bool,pg_lsn,timestamptz,bool,text,bool,bool}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size,two_phase,two_phase_at,inactive_since,conflicting,invalidation_reason,failover,synced}', prosrc => 'pg_get_replication_slots' }, { oid => '3786', descr => 'set up a logical replication slot', proname => 'pg_create_logical_replication_slot', provolatile => 'v', @@ -12040,15 +12303,19 @@ descr => 'pg_controldata init state information as a function', proname => 'pg_control_init', provolatile => 'v', prorettype => 'record', proargtypes => '', - proallargtypes => '{int4,int4,int4,int4,int4,int4,int4,int4,int4,bool,int4}', - proargmodes => '{o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,float8_pass_by_value,data_page_checksum_version}', + proallargtypes => '{int4,int4,int4,int4,int4,int4,int4,int4,int4,bool,int4,bool}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,float8_pass_by_value,data_page_checksum_version,default_char_signedness}', prosrc => 'pg_control_init' }, # subscripting support for built-in types { oid => '6179', descr => 'standard array subscripting support', - proname => 'array_subscript_handler', prorettype => 'internal', + proname => 'array_subscript_handler', + prosupport => 'array_subscript_handler_support', prorettype => 'internal', proargtypes => 'internal', prosrc => 'array_subscript_handler' }, +{ oid => '8682', descr => 'planner support for array_subscript_handler', + proname => 'array_subscript_handler_support', prorettype => 'internal', + proargtypes => 'internal', prosrc => 'array_subscript_handler_support' }, { oid => '6180', descr => 'raw array subscripting support', proname => 'raw_array_subscript_handler', prorettype => 'internal', proargtypes => 'internal', prosrc => 'raw_array_subscript_handler' }, @@ -12085,6 +12352,12 @@ provolatile => 'v', prorettype => 'record', proargtypes => '', proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}', proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' }, +{ oid => '9220', descr => 'list of files in the pg_wal/summaries directory', + proname => 'pg_ls_summariesdir', procost => '10', prorows => '20', + proretset => 't', provolatile => 'v', prorettype => 'record', + proargtypes => '', proallargtypes => '{text,int8,timestamptz}', + proargmodes => '{o,o,o}', proargnames => '{name,size,modification}', + prosrc => 'pg_ls_summariesdir' }, { oid => '5031', descr => 'list of files in the archive_status directory', proname => 'pg_ls_archive_statusdir', procost => '10', prorows => '20', proretset => 't', provolatile => 'v', prorettype => 'record', @@ -12234,5 +12507,53 @@ proallargtypes => '{int8,pg_lsn,pg_lsn,int4}', proargmodes => '{o,o,o,o}', proargnames => '{summarized_tli,summarized_lsn,pending_lsn,summarizer_pid}', prosrc => 'pg_get_wal_summarizer_state' }, +# Statistics Import +{ oid => '8459', + descr => 'restore statistics on relation', + proname => 'pg_restore_relation_stats', provolatile => 'v', proisstrict => 'f', + provariadic => 'any', + proparallel => 'u', prorettype => 'bool', + proargtypes => 'any', + proargnames => '{kwargs}', + proargmodes => '{v}', + prosrc => 'pg_restore_relation_stats' }, +{ oid => '9160', + descr => 'clear statistics on relation', + proname => 'pg_clear_relation_stats', provolatile => 'v', proisstrict => 'f', + proparallel => 'u', prorettype => 'void', + proargtypes => 'text text', + proargnames => '{schemaname,relname}', + prosrc => 'pg_clear_relation_stats' }, +{ oid => '8461', + descr => 'restore statistics on attribute', + proname => 'pg_restore_attribute_stats', provolatile => 'v', proisstrict => 'f', + provariadic => 'any', + proparallel => 'u', prorettype => 'bool', + proargtypes => 'any', + proargnames => '{kwargs}', + proargmodes => '{v}', + prosrc => 'pg_restore_attribute_stats' }, +{ oid => '9162', + descr => 'clear statistics on attribute', + proname => 'pg_clear_attribute_stats', provolatile => 'v', proisstrict => 'f', + proparallel => 'u', prorettype => 'void', + proargtypes => 'text text text bool', + proargnames => '{schemaname,relname,attname,inherited}', + prosrc => 'pg_clear_attribute_stats' }, + +# GiST stratnum implementations +{ oid => '8047', descr => 'GiST support', + proname => 'gist_translate_cmptype_common', prorettype => 'int2', + proargtypes => 'int4', + prosrc => 'gist_translate_cmptype_common' }, + +# AIO related functions +{ oid => '9200', descr => 'information about in-progress asynchronous IOs', + proname => 'pg_get_aios', prorows => '100', proretset => 't', + provolatile => 'v', proparallel => 'r', prorettype => 'record', proargtypes => '', + proallargtypes => '{int4,int4,int8,text,text,int8,int8,text,int2,int4,text,text,bool,bool,bool}', + proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', + proargnames => '{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}', + prosrc => 'pg_get_aios' }, ] diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 51f43092415e9..d7353e7a088ff 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3,7 +3,7 @@ * pg_proc.h * definition of the "procedure" system catalog (pg_proc) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_proc.h @@ -19,7 +19,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_proc_d.h" +#include "catalog/pg_proc_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" /* ---------------- @@ -61,7 +61,7 @@ CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,Proce /* security definer */ bool prosecdef BKI_DEFAULT(f); - /* is it a leak-proof function? */ + /* is it a leakproof function? */ bool proleakproof BKI_DEFAULT(f); /* strict with respect to NULLs? */ @@ -211,6 +211,7 @@ extern ObjectAddress ProcedureCreate(const char *procedureName, Datum parameterNames, List *parameterDefaults, Datum trftypes, + List *trfoids, Datum proconfig, Oid prosupport, float4 procost, diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h index 2f1b6abbfa7c6..48c7d1a861527 100644 --- a/src/include/catalog/pg_publication.h +++ b/src/include/catalog/pg_publication.h @@ -3,7 +3,7 @@ * pg_publication.h * definition of the "publication" system catalog (pg_publication) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_publication.h @@ -19,7 +19,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_publication_d.h" +#include "catalog/pg_publication_d.h" /* IWYU pragma: export */ /* ---------------- * pg_publication definition. cpp turns this into @@ -54,6 +54,12 @@ CATALOG(pg_publication,6104,PublicationRelationId) /* true if partition changes are published using root schema */ bool pubviaroot; + + /* + * 'n'(none) if generated column data should not be published. 's'(stored) + * if stored generated column data should be published. + */ + char pubgencols; } FormData_pg_publication; /* ---------------- @@ -95,14 +101,36 @@ typedef struct PublicationDesc */ bool cols_valid_for_update; bool cols_valid_for_delete; + + /* + * true if all generated columns that are part of replica identity are + * published or the publication actions do not include UPDATE or DELETE. + */ + bool gencols_valid_for_update; + bool gencols_valid_for_delete; } PublicationDesc; +#ifdef EXPOSE_TO_CLIENT_CODE + +typedef enum PublishGencolsType +{ + /* Generated columns present should not be replicated. */ + PUBLISH_GENCOLS_NONE = 'n', + + /* Generated columns present should be replicated. */ + PUBLISH_GENCOLS_STORED = 's', + +} PublishGencolsType; + +#endif /* EXPOSE_TO_CLIENT_CODE */ + typedef struct Publication { Oid oid; char *name; bool alltables; bool pubviaroot; + PublishGencolsType pubgencols_type; PublicationActions pubactions; } Publication; @@ -150,12 +178,17 @@ extern Oid GetTopMostAncestorInPublication(Oid puboid, List *ancestors, extern bool is_publishable_relation(Relation rel); extern bool is_schema_publication(Oid pubid); +extern bool check_and_fetch_column_list(Publication *pub, Oid relid, + MemoryContext mcxt, Bitmapset **cols); extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *pri, bool if_not_exists); +extern Bitmapset *pub_collist_validate(Relation targetrel, List *columns); extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists); extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols, MemoryContext mcxt); +extern Bitmapset *pub_form_cols_map(Relation relation, + PublishGencolsType include_gencols_type); #endif /* PG_PUBLICATION_H */ diff --git a/src/include/catalog/pg_publication_namespace.h b/src/include/catalog/pg_publication_namespace.h index 1cfb557684f9f..3bf308d98bd3e 100644 --- a/src/include/catalog/pg_publication_namespace.h +++ b/src/include/catalog/pg_publication_namespace.h @@ -4,7 +4,7 @@ * definition of the system catalog for mappings between schemas and * publications (pg_publication_namespace) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_publication_namespace.h @@ -19,7 +19,7 @@ #define PG_PUBLICATION_NAMESPACE_H #include "catalog/genbki.h" -#include "catalog/pg_publication_namespace_d.h" +#include "catalog/pg_publication_namespace_d.h" /* IWYU pragma: export */ /* ---------------- diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h index 25fa630675aaa..92cc36dfdf698 100644 --- a/src/include/catalog/pg_publication_rel.h +++ b/src/include/catalog/pg_publication_rel.h @@ -4,7 +4,7 @@ * definition of the system catalog for mappings between relations and * publications (pg_publication_rel) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_publication_rel.h @@ -19,7 +19,7 @@ #define PG_PUBLICATION_REL_H #include "catalog/genbki.h" -#include "catalog/pg_publication_rel_d.h" +#include "catalog/pg_publication_rel_d.h" /* IWYU pragma: export */ /* ---------------- * pg_publication_rel definition. cpp turns this into diff --git a/src/include/catalog/pg_range.dat b/src/include/catalog/pg_range.dat index 76ea2d949e1e9..1d423dc7caf37 100644 --- a/src/include/catalog/pg_range.dat +++ b/src/include/catalog/pg_range.dat @@ -3,7 +3,7 @@ # pg_range.dat # Initial contents of the pg_range system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_range.dat diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h index 0bd3ab688bd85..3bba61627821f 100644 --- a/src/include/catalog/pg_range.h +++ b/src/include/catalog/pg_range.h @@ -4,7 +4,7 @@ * definition of the "range type" system catalog (pg_range) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_range.h @@ -19,7 +19,7 @@ #define PG_RANGE_H #include "catalog/genbki.h" -#include "catalog/pg_range_d.h" +#include "catalog/pg_range_d.h" /* IWYU pragma: export */ /* ---------------- * pg_range definition. cpp turns this into diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h index e9bc0209c2667..7ade8bbda3964 100644 --- a/src/include/catalog/pg_replication_origin.h +++ b/src/include/catalog/pg_replication_origin.h @@ -4,7 +4,7 @@ * definition of the "replication origin" system catalog * (pg_replication_origin) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_replication_origin.h @@ -20,7 +20,7 @@ #include "access/xlogdefs.h" #include "catalog/genbki.h" -#include "catalog/pg_replication_origin_d.h" +#include "catalog/pg_replication_origin_d.h" /* IWYU pragma: export */ /* ---------------- * pg_replication_origin. cpp turns this into @@ -54,8 +54,6 @@ CATALOG(pg_replication_origin,6000,ReplicationOriginRelationId) BKI_SHARED_RELAT typedef FormData_pg_replication_origin *Form_pg_replication_origin; -DECLARE_TOAST_WITH_MACRO(pg_replication_origin, 4181, 4182, PgReplicationOriginToastTable, PgReplicationOriginToastIndex); - DECLARE_UNIQUE_INDEX_PKEY(pg_replication_origin_roiident_index, 6001, ReplicationOriginIdentIndex, pg_replication_origin, btree(roident oid_ops)); DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, ReplicationOriginNameIndex, pg_replication_origin, btree(roname text_ops)); diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h index e42ff73d29c32..c70bc45d1b3e8 100644 --- a/src/include/catalog/pg_rewrite.h +++ b/src/include/catalog/pg_rewrite.h @@ -7,7 +7,7 @@ * --- ie, rule names are only unique among the rules of a given table. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_rewrite.h @@ -22,7 +22,7 @@ #define PG_REWRITE_H #include "catalog/genbki.h" -#include "catalog/pg_rewrite_d.h" +#include "catalog/pg_rewrite_d.h" /* IWYU pragma: export */ /* ---------------- * pg_rewrite definition. cpp turns this into diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h index 5f6f5c9c05986..5b1b433600fba 100644 --- a/src/include/catalog/pg_seclabel.h +++ b/src/include/catalog/pg_seclabel.h @@ -3,7 +3,7 @@ * pg_seclabel.h * definition of the "security label" system catalog (pg_seclabel) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_seclabel.h @@ -18,7 +18,7 @@ #define PG_SECLABEL_H #include "catalog/genbki.h" -#include "catalog/pg_seclabel_d.h" +#include "catalog/pg_seclabel_d.h" /* IWYU pragma: export */ /* ---------------- * pg_seclabel definition. cpp turns this into diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h index 8c3f0dd1ab897..580c7f2cbe6f9 100644 --- a/src/include/catalog/pg_sequence.h +++ b/src/include/catalog/pg_sequence.h @@ -3,7 +3,7 @@ * pg_sequence.h * definition of the "sequence" system catalog (pg_sequence) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_sequence.h @@ -18,7 +18,7 @@ #define PG_SEQUENCE_H #include "catalog/genbki.h" -#include "catalog/pg_sequence_d.h" +#include "catalog/pg_sequence_d.h" /* IWYU pragma: export */ CATALOG(pg_sequence,2224,SequenceRelationId) { diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h index 7bd48ab97cbcc..62df9f757f6db 100644 --- a/src/include/catalog/pg_shdepend.h +++ b/src/include/catalog/pg_shdepend.h @@ -13,7 +13,7 @@ * from a relation to its database. Currently, only dependencies on roles * are explicitly stored in pg_shdepend. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_shdepend.h @@ -28,7 +28,7 @@ #define PG_SHDEPEND_H #include "catalog/genbki.h" -#include "catalog/pg_shdepend_d.h" +#include "catalog/pg_shdepend_d.h" /* IWYU pragma: export */ /* ---------------- * pg_shdepend definition. cpp turns this into diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h index c9433d229ef47..ccd1f2ecb4cc5 100644 --- a/src/include/catalog/pg_shdescription.h +++ b/src/include/catalog/pg_shdescription.h @@ -16,7 +16,7 @@ * across tables. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_shdescription.h @@ -31,7 +31,7 @@ #define PG_SHDESCRIPTION_H #include "catalog/genbki.h" -#include "catalog/pg_shdescription_d.h" +#include "catalog/pg_shdescription_d.h" /* IWYU pragma: export */ /* ---------------- * pg_shdescription definition. cpp turns this into diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h index 478d46969c0b8..523d6058b2440 100644 --- a/src/include/catalog/pg_shseclabel.h +++ b/src/include/catalog/pg_shseclabel.h @@ -3,7 +3,7 @@ * pg_shseclabel.h * definition of the "shared security label" system catalog (pg_shseclabel) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_shseclabel.h @@ -18,7 +18,7 @@ #define PG_SHSECLABEL_H #include "catalog/genbki.h" -#include "catalog/pg_shseclabel_d.h" +#include "catalog/pg_shseclabel_d.h" /* IWYU pragma: export */ /* ---------------- * pg_shseclabel definition. cpp turns this into diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h index 041e626390a15..4216e27a8a4f7 100644 --- a/src/include/catalog/pg_statistic.h +++ b/src/include/catalog/pg_statistic.h @@ -4,7 +4,7 @@ * definition of the "statistics" system catalog (pg_statistic) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_statistic.h @@ -19,7 +19,7 @@ #define PG_STATISTIC_H #include "catalog/genbki.h" -#include "catalog/pg_statistic_d.h" +#include "catalog/pg_statistic_d.h" /* IWYU pragma: export */ /* ---------------- * pg_statistic definition. cpp turns this into @@ -183,9 +183,9 @@ DECLARE_FOREIGN_KEY((starelid, staattnum), pg_attribute, (attrelid, attnum)); * the K most common non-null values appearing in the column, and stanumbers * contains their frequencies (fractions of total row count). The values * shall be ordered in decreasing frequency. Note that since the arrays are - * variable-size, K may be chosen may be chosen at ANALYZE time. Values should - * not appear in MCV unless they have been observed to occur more than once; - * a unique column will have no MCV slot. + * variable-size, K may be chosen at ANALYZE time. Values should not appear + * in MCV unless they have been observed to occur more than once; a unique + * column will have no MCV slot. */ #define STATISTIC_KIND_MCV 1 diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h index 50a5c021edf53..d476095029c4d 100644 --- a/src/include/catalog/pg_statistic_ext.h +++ b/src/include/catalog/pg_statistic_ext.h @@ -8,7 +8,7 @@ * objects, created by CREATE STATISTICS, but not the actual statistical data, * created by running ANALYZE. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_statistic_ext.h @@ -23,7 +23,7 @@ #define PG_STATISTIC_EXT_H #include "catalog/genbki.h" -#include "catalog/pg_statistic_ext_d.h" +#include "catalog/pg_statistic_ext_d.h" /* IWYU pragma: export */ /* ---------------- * pg_statistic_ext definition. cpp turns this into diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h index 18b00ce8b526a..809b525199454 100644 --- a/src/include/catalog/pg_statistic_ext_data.h +++ b/src/include/catalog/pg_statistic_ext_data.h @@ -6,7 +6,7 @@ * * This catalog stores the statistical data for extended statistics objects. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_statistic_ext_data.h @@ -21,7 +21,7 @@ #define PG_STATISTIC_EXT_DATA_H #include "catalog/genbki.h" -#include "catalog/pg_statistic_ext_data_d.h" +#include "catalog/pg_statistic_ext_data_d.h" /* IWYU pragma: export */ /* ---------------- * pg_statistic_ext_data definition. cpp turns this into diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h index 0aa14ec4a27ed..20fc329992dc5 100644 --- a/src/include/catalog/pg_subscription.h +++ b/src/include/catalog/pg_subscription.h @@ -3,7 +3,7 @@ * pg_subscription.h * definition of the "subscription" system catalog (pg_subscription) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_subscription.h @@ -19,30 +19,10 @@ #include "access/xlogdefs.h" #include "catalog/genbki.h" -#include "catalog/pg_subscription_d.h" - +#include "catalog/pg_subscription_d.h" /* IWYU pragma: export */ +#include "lib/stringinfo.h" #include "nodes/pg_list.h" -/* - * two_phase tri-state values. See comments atop worker.c to know more about - * these states. - */ -#define LOGICALREP_TWOPHASE_STATE_DISABLED 'd' -#define LOGICALREP_TWOPHASE_STATE_PENDING 'p' -#define LOGICALREP_TWOPHASE_STATE_ENABLED 'e' - -/* - * The subscription will request the publisher to only send changes that do not - * have any origin. - */ -#define LOGICALREP_ORIGIN_NONE "none" - -/* - * The subscription will request the publisher to send changes regardless - * of their origin. - */ -#define LOGICALREP_ORIGIN_ANY "any" - /* ---------------- * pg_subscription definition. cpp turns this into * typedef struct FormData_pg_subscription @@ -159,6 +139,28 @@ typedef struct Subscription * specified origin */ } Subscription; +#ifdef EXPOSE_TO_CLIENT_CODE + +/* + * two_phase tri-state values. See comments atop worker.c to know more about + * these states. + */ +#define LOGICALREP_TWOPHASE_STATE_DISABLED 'd' +#define LOGICALREP_TWOPHASE_STATE_PENDING 'p' +#define LOGICALREP_TWOPHASE_STATE_ENABLED 'e' + +/* + * The subscription will request the publisher to only send changes that do not + * have any origin. + */ +#define LOGICALREP_ORIGIN_NONE "none" + +/* + * The subscription will request the publisher to send changes regardless + * of their origin. + */ +#define LOGICALREP_ORIGIN_ANY "any" + /* Disallow streaming in-progress transactions. */ #define LOGICALREP_STREAM_OFF 'f' @@ -174,10 +176,15 @@ typedef struct Subscription */ #define LOGICALREP_STREAM_PARALLEL 'p' +#endif /* EXPOSE_TO_CLIENT_CODE */ + extern Subscription *GetSubscription(Oid subid, bool missing_ok); extern void FreeSubscription(Subscription *sub); extern void DisableSubscription(Oid subid); extern int CountDBSubscriptions(Oid dbid); +extern void GetPublicationsStr(List *publications, StringInfo dest, + bool quote_literal); + #endif /* PG_SUBSCRIPTION_H */ diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h index 8244ad537aea9..c91797c869c24 100644 --- a/src/include/catalog/pg_subscription_rel.h +++ b/src/include/catalog/pg_subscription_rel.h @@ -4,7 +4,7 @@ * definition of the system catalog containing the state for each * replicated table in each subscription (pg_subscription_rel) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_subscription_rel.h @@ -20,7 +20,7 @@ #include "access/xlogdefs.h" #include "catalog/genbki.h" -#include "catalog/pg_subscription_rel_d.h" +#include "catalog/pg_subscription_rel_d.h" /* IWYU pragma: export */ #include "nodes/pg_list.h" /* ---------------- diff --git a/src/include/catalog/pg_tablespace.dat b/src/include/catalog/pg_tablespace.dat index fbd396387c74e..1302a3d75cd2f 100644 --- a/src/include/catalog/pg_tablespace.dat +++ b/src/include/catalog/pg_tablespace.dat @@ -3,7 +3,7 @@ # pg_tablespace.dat # Initial contents of the pg_tablespace system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_tablespace.dat diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h index 6b9bdcf8b05ec..5293488c63091 100644 --- a/src/include/catalog/pg_tablespace.h +++ b/src/include/catalog/pg_tablespace.h @@ -4,7 +4,7 @@ * definition of the "tablespace" system catalog (pg_tablespace) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_tablespace.h @@ -19,7 +19,7 @@ #define PG_TABLESPACE_H #include "catalog/genbki.h" -#include "catalog/pg_tablespace_d.h" +#include "catalog/pg_tablespace_d.h" /* IWYU pragma: export */ /* ---------------- * pg_tablespace definition. cpp turns this into diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h index 3b69960af6046..bc3d943230f41 100644 --- a/src/include/catalog/pg_transform.h +++ b/src/include/catalog/pg_transform.h @@ -4,7 +4,7 @@ * definition of the "transform" system catalog (pg_transform) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_transform.h @@ -19,7 +19,7 @@ #define PG_TRANSFORM_H #include "catalog/genbki.h" -#include "catalog/pg_transform_d.h" +#include "catalog/pg_transform_d.h" /* IWYU pragma: export */ /* ---------------- * pg_transform definition. cpp turns this into diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h index 7fdff16118405..24a9152806140 100644 --- a/src/include/catalog/pg_trigger.h +++ b/src/include/catalog/pg_trigger.h @@ -4,7 +4,7 @@ * definition of the "trigger" system catalog (pg_trigger) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_trigger.h @@ -19,7 +19,7 @@ #define PG_TRIGGER_H #include "catalog/genbki.h" -#include "catalog/pg_trigger_d.h" +#include "catalog/pg_trigger_d.h" /* IWYU pragma: export */ /* ---------------- * pg_trigger definition. cpp turns this into diff --git a/src/include/catalog/pg_ts_config.dat b/src/include/catalog/pg_ts_config.dat index 949a73be243df..6bd03f7f4ef3c 100644 --- a/src/include/catalog/pg_ts_config.dat +++ b/src/include/catalog/pg_ts_config.dat @@ -3,7 +3,7 @@ # pg_ts_config.dat # Initial contents of the pg_ts_config system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_ts_config.dat diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h index fc0bf447b1d07..0f5df37f0974d 100644 --- a/src/include/catalog/pg_ts_config.h +++ b/src/include/catalog/pg_ts_config.h @@ -5,7 +5,7 @@ * (pg_ts_config) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_ts_config.h @@ -20,7 +20,7 @@ #define PG_TS_CONFIG_H #include "catalog/genbki.h" -#include "catalog/pg_ts_config_d.h" +#include "catalog/pg_ts_config_d.h" /* IWYU pragma: export */ /* ---------------- * pg_ts_config definition. cpp turns this into diff --git a/src/include/catalog/pg_ts_config_map.dat b/src/include/catalog/pg_ts_config_map.dat index 37bd2c98598a1..0a376b0dd8c04 100644 --- a/src/include/catalog/pg_ts_config_map.dat +++ b/src/include/catalog/pg_ts_config_map.dat @@ -3,7 +3,7 @@ # pg_ts_config_map.dat # Initial contents of the pg_ts_config_map system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_ts_config_map.dat diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h index efced44941dd6..38c3d4426c64d 100644 --- a/src/include/catalog/pg_ts_config_map.h +++ b/src/include/catalog/pg_ts_config_map.h @@ -5,7 +5,7 @@ * (pg_ts_config_map) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_ts_config_map.h diff --git a/src/include/catalog/pg_ts_dict.dat b/src/include/catalog/pg_ts_dict.dat index ec2ca6bc1f323..f5c9cd8398467 100644 --- a/src/include/catalog/pg_ts_dict.dat +++ b/src/include/catalog/pg_ts_dict.dat @@ -3,7 +3,7 @@ # pg_ts_dict.dat # Initial contents of the pg_ts_dict system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_ts_dict.dat diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h index 1320468de0e1d..86102c73a6bf4 100644 --- a/src/include/catalog/pg_ts_dict.h +++ b/src/include/catalog/pg_ts_dict.h @@ -4,7 +4,7 @@ * definition of the "text search dictionary" system catalog (pg_ts_dict) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_ts_dict.h @@ -19,7 +19,7 @@ #define PG_TS_DICT_H #include "catalog/genbki.h" -#include "catalog/pg_ts_dict_d.h" +#include "catalog/pg_ts_dict_d.h" /* IWYU pragma: export */ /* ---------------- * pg_ts_dict definition. cpp turns this into diff --git a/src/include/catalog/pg_ts_parser.dat b/src/include/catalog/pg_ts_parser.dat index 4b838362198c6..28e33d4819d93 100644 --- a/src/include/catalog/pg_ts_parser.dat +++ b/src/include/catalog/pg_ts_parser.dat @@ -3,7 +3,7 @@ # pg_ts_parser.dat # Initial contents of the pg_ts_parser system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_ts_parser.dat diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h index 909644c96f2ec..f3a40e5d2936e 100644 --- a/src/include/catalog/pg_ts_parser.h +++ b/src/include/catalog/pg_ts_parser.h @@ -4,7 +4,7 @@ * definition of the "text search parser" system catalog (pg_ts_parser) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_ts_parser.h @@ -19,7 +19,7 @@ #define PG_TS_PARSER_H #include "catalog/genbki.h" -#include "catalog/pg_ts_parser_d.h" +#include "catalog/pg_ts_parser_d.h" /* IWYU pragma: export */ /* ---------------- * pg_ts_parser definition. cpp turns this into diff --git a/src/include/catalog/pg_ts_template.dat b/src/include/catalog/pg_ts_template.dat index a7ff957396f24..dd571aa33f195 100644 --- a/src/include/catalog/pg_ts_template.dat +++ b/src/include/catalog/pg_ts_template.dat @@ -3,7 +3,7 @@ # pg_ts_template.dat # Initial contents of the pg_ts_template system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_ts_template.dat diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h index 0562a4a7583b9..aa06b7a840a82 100644 --- a/src/include/catalog/pg_ts_template.h +++ b/src/include/catalog/pg_ts_template.h @@ -4,7 +4,7 @@ * definition of the "text search template" system catalog (pg_ts_template) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_ts_template.h @@ -19,7 +19,7 @@ #define PG_TS_TEMPLATE_H #include "catalog/genbki.h" -#include "catalog/pg_ts_template_d.h" +#include "catalog/pg_ts_template_d.h" /* IWYU pragma: export */ /* ---------------- * pg_ts_template definition. cpp turns this into diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat index ceff66ccde1aa..6dca77e0a22f7 100644 --- a/src/include/catalog/pg_type.dat +++ b/src/include/catalog/pg_type.dat @@ -3,7 +3,7 @@ # pg_type.dat # Initial contents of the pg_type system catalog. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/pg_type.dat diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index e9259697321da..ff666711a54f8 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -4,7 +4,7 @@ * definition of the "type" system catalog (pg_type) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_type.h @@ -20,7 +20,7 @@ #include "catalog/genbki.h" #include "catalog/objectaddress.h" -#include "catalog/pg_type_d.h" +#include "catalog/pg_type_d.h" /* IWYU pragma: export */ #include "nodes/nodes.h" /* ---------------- diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h index 3632448cce0b0..7a0465c4d9745 100644 --- a/src/include/catalog/pg_user_mapping.h +++ b/src/include/catalog/pg_user_mapping.h @@ -3,7 +3,7 @@ * pg_user_mapping.h * definition of the "user mapping" system catalog (pg_user_mapping) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_user_mapping.h @@ -18,7 +18,7 @@ #define PG_USER_MAPPING_H #include "catalog/genbki.h" -#include "catalog/pg_user_mapping_d.h" +#include "catalog/pg_user_mapping_d.h" /* IWYU pragma: export */ /* ---------------- * pg_user_mapping definition. cpp turns this into diff --git a/src/include/catalog/reformat_dat_file.pl b/src/include/catalog/reformat_dat_file.pl index 838cd0af73946..0e2e5a278de53 100755 --- a/src/include/catalog/reformat_dat_file.pl +++ b/src/include/catalog/reformat_dat_file.pl @@ -10,7 +10,7 @@ # in the same order as the columns of the corresponding catalog. # Comments and blank lines are preserved. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/reformat_dat_file.pl @@ -84,7 +84,7 @@ # if you need to. In the following example, the "next if !ref $row" # check below is a hack to filter out non-hash objects. This is because # we build the lookup tables from data that we read using the -# "preserve_formatting" parameter. +# "preserve_comments" parameter. # ##Index access method lookup. #my %amnames; diff --git a/src/include/catalog/renumber_oids.pl b/src/include/catalog/renumber_oids.pl index b20a2efada862..1f93da50b6d88 100755 --- a/src/include/catalog/renumber_oids.pl +++ b/src/include/catalog/renumber_oids.pl @@ -8,7 +8,7 @@ # Note: This does not reformat the .dat files, so you may want # to run reformat_dat_file.pl afterwards. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/renumber_oids.pl diff --git a/src/include/catalog/storage.h b/src/include/catalog/storage.h index 72ef3ee92c012..ba99225b0a37f 100644 --- a/src/include/catalog/storage.h +++ b/src/include/catalog/storage.h @@ -4,7 +4,7 @@ * prototypes for functions in backend/catalog/storage.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/storage.h diff --git a/src/include/catalog/storage_xlog.h b/src/include/catalog/storage_xlog.h index a490e05f88401..e807c442cfe39 100644 --- a/src/include/catalog/storage_xlog.h +++ b/src/include/catalog/storage_xlog.h @@ -4,7 +4,7 @@ * prototypes for XLog support for backend/catalog/storage.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/storage_xlog.h diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 725f31617bbe0..0950a07e7c46f 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -4,7 +4,7 @@ * This file provides some definitions to support creation of toast tables * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/toasting.h diff --git a/src/include/catalog/unused_oids b/src/include/catalog/unused_oids index 32f3ca32b43ed..763322f52aea8 100755 --- a/src/include/catalog/unused_oids +++ b/src/include/catalog/unused_oids @@ -11,7 +11,7 @@ # to take over what was intended as expansion space for something # else. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/include/catalog/unused_oids diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h index f00af75befff1..b1e4630388a64 100644 --- a/src/include/commands/alter.h +++ b/src/include/commands/alter.h @@ -4,7 +4,7 @@ * prototypes for commands/alter.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/alter.h diff --git a/src/include/commands/async.h b/src/include/commands/async.h index 78daa25fa0806..f75c3df9556b3 100644 --- a/src/include/commands/async.h +++ b/src/include/commands/async.h @@ -3,7 +3,7 @@ * async.h * Asynchronous notification: NOTIFY, LISTEN, UNLISTEN * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/async.h diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h index 4e3238041712b..60088a64cbb6e 100644 --- a/src/include/commands/cluster.h +++ b/src/include/commands/cluster.h @@ -3,7 +3,7 @@ * cluster.h * header file for postgres cluster command stuff * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * src/include/commands/cluster.h @@ -32,7 +32,7 @@ typedef struct ClusterParams } ClusterParams; extern void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel); -extern void cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params); +extern void cluster_rel(Relation OldHeap, Oid indexOid, ClusterParams *params); extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid, LOCKMODE lockmode); extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal); diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h index 718f021656b3f..c228ac72df4fb 100644 --- a/src/include/commands/collationcmds.h +++ b/src/include/commands/collationcmds.h @@ -4,7 +4,7 @@ * prototypes for collationcmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/collationcmds.h diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h index 18c089de3c069..f083ea3a3864f 100644 --- a/src/include/commands/comment.h +++ b/src/include/commands/comment.h @@ -7,7 +7,7 @@ * * Prototypes for functions in commands/comment.c * - * Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Copyright (c) 1999-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h index dc2a1e64ef4ae..95cd84c833e6b 100644 --- a/src/include/commands/conversioncmds.h +++ b/src/include/commands/conversioncmds.h @@ -4,7 +4,7 @@ * prototypes for conversioncmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/conversioncmds.h diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h index 141fd48dc10df..06dfdfef7210c 100644 --- a/src/include/commands/copy.h +++ b/src/include/commands/copy.h @@ -4,7 +4,7 @@ * Definitions for using the POSTGRES copy command. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/copy.h @@ -45,7 +45,9 @@ typedef enum CopyOnErrorChoice */ typedef enum CopyLogVerbosityChoice { - COPY_LOG_VERBOSITY_DEFAULT = 0, /* logs no additional messages, default */ + COPY_LOG_VERBOSITY_SILENT = -1, /* logs none */ + COPY_LOG_VERBOSITY_DEFAULT = 0, /* logs no additional messages. As this is + * the default, assign 0 */ COPY_LOG_VERBOSITY_VERBOSE, /* logs additional messages */ } CopyLogVerbosityChoice; @@ -83,6 +85,7 @@ typedef struct CopyFormatOptions bool convert_selectively; /* do selective binary conversion? */ CopyOnErrorChoice on_error; /* what to do when error happened */ CopyLogVerbosityChoice log_verbosity; /* verbosity of logged messages */ + int64 reject_limit; /* maximum tolerable number of errors */ List *convert_select; /* list of column names (can be NIL) */ } CopyFormatOptions; diff --git a/src/include/commands/copyapi.h b/src/include/commands/copyapi.h new file mode 100644 index 0000000000000..2a2d2f9876baf --- /dev/null +++ b/src/include/commands/copyapi.h @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------- + * + * copyapi.h + * API for COPY TO/FROM handlers + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/commands/copyapi.h + * + *------------------------------------------------------------------------- + */ +#ifndef COPYAPI_H +#define COPYAPI_H + +#include "commands/copy.h" + +/* + * API structure for a COPY TO format implementation. Note this must be + * allocated in a server-lifetime manner, typically as a static const struct. + */ +typedef struct CopyToRoutine +{ + /* + * Set output function information. This callback is called once at the + * beginning of COPY TO. + * + * 'finfo' can be optionally filled to provide the catalog information of + * the output function. + * + * 'atttypid' is the OID of data type used by the relation's attribute. + */ + void (*CopyToOutFunc) (CopyToState cstate, Oid atttypid, + FmgrInfo *finfo); + + /* + * Start a COPY TO. This callback is called once at the beginning of COPY + * TO. + * + * 'tupDesc' is the tuple descriptor of the relation from where the data + * is read. + */ + void (*CopyToStart) (CopyToState cstate, TupleDesc tupDesc); + + /* + * Write one row stored in 'slot' to the destination. + */ + void (*CopyToOneRow) (CopyToState cstate, TupleTableSlot *slot); + + /* + * End a COPY TO. This callback is called once at the end of COPY TO. + */ + void (*CopyToEnd) (CopyToState cstate); +} CopyToRoutine; + +/* + * API structure for a COPY FROM format implementation. Note this must be + * allocated in a server-lifetime manner, typically as a static const struct. + */ +typedef struct CopyFromRoutine +{ + /* + * Set input function information. This callback is called once at the + * beginning of COPY FROM. + * + * 'finfo' can be optionally filled to provide the catalog information of + * the input function. + * + * 'typioparam' can be optionally filled to define the OID of the type to + * pass to the input function.'atttypid' is the OID of data type used by + * the relation's attribute. + */ + void (*CopyFromInFunc) (CopyFromState cstate, Oid atttypid, + FmgrInfo *finfo, Oid *typioparam); + + /* + * Start a COPY FROM. This callback is called once at the beginning of + * COPY FROM. + * + * 'tupDesc' is the tuple descriptor of the relation where the data needs + * to be copied. This can be used for any initialization steps required by + * a format. + */ + void (*CopyFromStart) (CopyFromState cstate, TupleDesc tupDesc); + + /* + * Read one row from the source and fill *values and *nulls. + * + * 'econtext' is used to evaluate default expression for each column that + * is either not read from the file or is using the DEFAULT option of COPY + * FROM. It is NULL if no default values are used. + * + * Returns false if there are no more tuples to read. + */ + bool (*CopyFromOneRow) (CopyFromState cstate, ExprContext *econtext, + Datum *values, bool *nulls); + + /* + * End a COPY FROM. This callback is called once at the end of COPY FROM. + */ + void (*CopyFromEnd) (CopyFromState cstate); +} CopyFromRoutine; + +#endif /* COPYAPI_H */ diff --git a/src/include/commands/copyfrom_internal.h b/src/include/commands/copyfrom_internal.h index cad52fcc78370..c8b22af22d852 100644 --- a/src/include/commands/copyfrom_internal.h +++ b/src/include/commands/copyfrom_internal.h @@ -4,7 +4,7 @@ * Internal definitions for COPY FROM command. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/copyfrom_internal.h @@ -58,6 +58,9 @@ typedef enum CopyInsertMethod */ typedef struct CopyFromStateData { + /* format routine */ + const struct CopyFromRoutine *routine; + /* low-level state data */ CopySource copy_src; /* type of copy source */ FILE *copy_file; /* used if copy_src == COPY_FILE */ @@ -95,7 +98,7 @@ typedef struct CopyFromStateData * default value */ FmgrInfo *in_functions; /* array of input functions for each attrs */ Oid *typioparams; /* array of element types for in_functions */ - ErrorSaveContext *escontext; /* soft error trapper during in_functions + ErrorSaveContext *escontext; /* soft error trapped during in_functions * execution */ uint64 num_errors; /* total number of rows which contained soft * errors */ @@ -183,4 +186,12 @@ typedef struct CopyFromStateData extern void ReceiveCopyBegin(CopyFromState cstate); extern void ReceiveCopyBinaryHeader(CopyFromState cstate); +/* One-row callbacks for built-in formats defined in copyfromparse.c */ +extern bool CopyFromTextOneRow(CopyFromState cstate, ExprContext *econtext, + Datum *values, bool *nulls); +extern bool CopyFromCSVOneRow(CopyFromState cstate, ExprContext *econtext, + Datum *values, bool *nulls); +extern bool CopyFromBinaryOneRow(CopyFromState cstate, ExprContext *econtext, + Datum *values, bool *nulls); + #endif /* COPYFROM_INTERNAL_H */ diff --git a/src/include/commands/createas.h b/src/include/commands/createas.h index 94678e3834d2b..90612ebbb0e17 100644 --- a/src/include/commands/createas.h +++ b/src/include/commands/createas.h @@ -4,7 +4,7 @@ * prototypes for createas.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/createas.h diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index 92e17c7115857..524ac6d97e898 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -4,7 +4,7 @@ * Database management commands (create/drop database). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/dbcommands.h diff --git a/src/include/commands/dbcommands_xlog.h b/src/include/commands/dbcommands_xlog.h index c008b8ffea0e6..c4202c3156e04 100644 --- a/src/include/commands/dbcommands_xlog.h +++ b/src/include/commands/dbcommands_xlog.h @@ -4,7 +4,7 @@ * Database resource manager XLOG definitions (create/drop database). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/dbcommands_xlog.h diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 29c511e319693..dd22b5efdfd91 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -4,7 +4,7 @@ * POSTGRES define and remove utility definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/defrem.h @@ -14,6 +14,7 @@ #ifndef DEFREM_H #define DEFREM_H +#include "access/stratnum.h" #include "catalog/objectaddress.h" #include "nodes/params.h" #include "parser/parse_node.h" @@ -44,10 +45,13 @@ extern char *ChooseRelationName(const char *name1, const char *name2, extern bool CheckIndexCompatible(Oid oldId, const char *accessMethodName, const List *attributeList, - const List *exclusionOpNames); + const List *exclusionOpNames, + bool isWithoutOverlaps); extern Oid GetDefaultOpClass(Oid type_id, Oid am_id); extern Oid ResolveOpClass(const List *opclass, Oid attrType, const char *accessMethodName, Oid accessMethodId); +extern void GetOperatorFromCompareType(Oid opclass, Oid rhstype, CompareType cmptype, + Oid *opid, StrategyNumber *strat); /* commands/functioncmds.c */ extern ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt); @@ -156,6 +160,6 @@ extern List *defGetQualifiedName(DefElem *def); extern TypeName *defGetTypeName(DefElem *def); extern int defGetTypeLength(DefElem *def); extern List *defGetStringList(DefElem *def); -extern void errorConflictingDefElem(DefElem *defel, ParseState *pstate) pg_attribute_noreturn(); +pg_noreturn extern void errorConflictingDefElem(DefElem *defel, ParseState *pstate); #endif /* DEFREM_H */ diff --git a/src/include/commands/discard.h b/src/include/commands/discard.h index c1f91d8e3f695..fac63e9e720c0 100644 --- a/src/include/commands/discard.h +++ b/src/include/commands/discard.h @@ -4,7 +4,7 @@ * prototypes for discard.c. * * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/commands/discard.h * diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index 90fc1af5f696b..4c67dd862e305 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -3,7 +3,7 @@ * event_trigger.h * Declarations for command trigger handling. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/event_trigger.h @@ -31,6 +31,12 @@ typedef struct EventTriggerData extern PGDLLIMPORT bool event_triggers; +/* + * Reasons for relation rewrites. + * + * pg_event_trigger_table_rewrite_reason() uses these values, so make sure to + * update the documentation when changing this list. + */ #define AT_REWRITE_ALTER_PERSISTENCE 0x01 #define AT_REWRITE_DEFAULT_VAL 0x02 #define AT_REWRITE_COLUMN_REWRITE 0x04 diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h index 9b8b351d9a218..3b122f79ed848 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h @@ -3,7 +3,7 @@ * explain.h * prototypes for explain.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * src/include/commands/explain.h @@ -14,73 +14,37 @@ #define EXPLAIN_H #include "executor/executor.h" -#include "lib/stringinfo.h" #include "parser/parse_node.h" -typedef enum ExplainSerializeOption -{ - EXPLAIN_SERIALIZE_NONE, - EXPLAIN_SERIALIZE_TEXT, - EXPLAIN_SERIALIZE_BINARY, -} ExplainSerializeOption; - -typedef enum ExplainFormat -{ - EXPLAIN_FORMAT_TEXT, - EXPLAIN_FORMAT_XML, - EXPLAIN_FORMAT_JSON, - EXPLAIN_FORMAT_YAML, -} ExplainFormat; - -typedef struct ExplainWorkersState -{ - int num_workers; /* # of worker processes the plan used */ - bool *worker_inited; /* per-worker state-initialized flags */ - StringInfoData *worker_str; /* per-worker transient output buffers */ - int *worker_state_save; /* per-worker grouping state save areas */ - StringInfo prev_str; /* saved output buffer while redirecting */ -} ExplainWorkersState; - -typedef struct ExplainState -{ - StringInfo str; /* output buffer */ - /* options */ - bool verbose; /* be verbose */ - bool analyze; /* print actual times */ - bool costs; /* print estimated costs */ - bool buffers; /* print buffer usage */ - bool wal; /* print WAL usage */ - bool timing; /* print detailed node timing */ - bool summary; /* print total planning and execution timing */ - bool memory; /* print planner's memory usage information */ - bool settings; /* print modified settings */ - bool generic; /* generate a generic plan */ - ExplainSerializeOption serialize; /* serialize the query's output? */ - ExplainFormat format; /* output format */ - /* state for output formatting --- not reset for each new plan tree */ - int indent; /* current indentation level */ - List *grouping_stack; /* format-specific grouping state */ - /* state related to the current plan tree (filled by ExplainPrintPlan) */ - PlannedStmt *pstmt; /* top of plan */ - List *rtable; /* range table */ - List *rtable_names; /* alias names for RTEs */ - List *deparse_cxt; /* context list for deparsing expressions */ - Bitmapset *printed_subplans; /* ids of SubPlans we've printed */ - bool hide_workers; /* set if we find an invisible Gather */ - /* state related to the current plan node */ - ExplainWorkersState *workers_state; /* needed if parallel plan */ -} ExplainState; +struct ExplainState; /* defined in explain_state.h */ /* Hook for plugins to get control in ExplainOneQuery() */ typedef void (*ExplainOneQuery_hook_type) (Query *query, int cursorOptions, IntoClause *into, - ExplainState *es, + struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv); extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook; +/* Hook for EXPLAIN plugins to print extra information for each plan */ +typedef void (*explain_per_plan_hook_type) (PlannedStmt *plannedstmt, + IntoClause *into, + struct ExplainState *es, + const char *queryString, + ParamListInfo params, + QueryEnvironment *queryEnv); +extern PGDLLIMPORT explain_per_plan_hook_type explain_per_plan_hook; + +/* Hook for EXPLAIN plugins to print extra fields on individual plan nodes */ +typedef void (*explain_per_node_hook_type) (PlanState *planstate, + List *ancestors, + const char *relationship, + const char *plan_name, + struct ExplainState *es); +extern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook; + /* Hook for plugins to get control in explain_get_index_name() */ typedef const char *(*explain_get_index_name_hook_type) (Oid indexId); extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; @@ -89,57 +53,32 @@ extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest); extern void standard_ExplainOneQuery(Query *query, int cursorOptions, - IntoClause *into, ExplainState *es, + IntoClause *into, struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv); -extern ExplainState *NewExplainState(void); - extern TupleDesc ExplainResultDesc(ExplainStmt *stmt); extern void ExplainOneUtility(Node *utilityStmt, IntoClause *into, - ExplainState *es, const char *queryString, - ParamListInfo params, QueryEnvironment *queryEnv); + struct ExplainState *es, ParseState *pstate, + ParamListInfo params); extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, - ExplainState *es, const char *queryString, + struct ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters); -extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc); -extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc); - -extern void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc); - -extern void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc); -extern void ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen); - -extern void ExplainBeginOutput(ExplainState *es); -extern void ExplainEndOutput(ExplainState *es); -extern void ExplainSeparatePlans(ExplainState *es); - -extern void ExplainPropertyList(const char *qlabel, List *data, - ExplainState *es); -extern void ExplainPropertyListNested(const char *qlabel, List *data, - ExplainState *es); -extern void ExplainPropertyText(const char *qlabel, const char *value, - ExplainState *es); -extern void ExplainPropertyInteger(const char *qlabel, const char *unit, - int64 value, ExplainState *es); -extern void ExplainPropertyUInteger(const char *qlabel, const char *unit, - uint64 value, ExplainState *es); -extern void ExplainPropertyFloat(const char *qlabel, const char *unit, - double value, int ndigits, ExplainState *es); -extern void ExplainPropertyBool(const char *qlabel, bool value, - ExplainState *es); +extern void ExplainPrintPlan(struct ExplainState *es, QueryDesc *queryDesc); +extern void ExplainPrintTriggers(struct ExplainState *es, + QueryDesc *queryDesc); -extern void ExplainOpenGroup(const char *objtype, const char *labelname, - bool labeled, ExplainState *es); -extern void ExplainCloseGroup(const char *objtype, const char *labelname, - bool labeled, ExplainState *es); +extern void ExplainPrintJITSummary(struct ExplainState *es, + QueryDesc *queryDesc); -extern DestReceiver *CreateExplainSerializeDestReceiver(ExplainState *es); +extern void ExplainQueryText(struct ExplainState *es, QueryDesc *queryDesc); +extern void ExplainQueryParameters(struct ExplainState *es, + ParamListInfo params, int maxlen); #endif /* EXPLAIN_H */ diff --git a/src/include/commands/explain_dr.h b/src/include/commands/explain_dr.h new file mode 100644 index 0000000000000..55da63d66bdf6 --- /dev/null +++ b/src/include/commands/explain_dr.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * explain_dr.h + * prototypes for explain_dr.c + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * src/include/commands/explain_dr.h + * + *------------------------------------------------------------------------- + */ +#ifndef EXPLAIN_DR_H +#define EXPLAIN_DR_H + +#include "executor/instrument.h" +#include "tcop/dest.h" + +struct ExplainState; /* avoid including explain.h here */ + +/* Instrumentation data for EXPLAIN's SERIALIZE option */ +typedef struct SerializeMetrics +{ + uint64 bytesSent; /* # of bytes serialized */ + instr_time timeSpent; /* time spent serializing */ + BufferUsage bufferUsage; /* buffers accessed during serialization */ +} SerializeMetrics; + +extern DestReceiver *CreateExplainSerializeDestReceiver(struct ExplainState *es); +extern SerializeMetrics GetSerializationMetrics(DestReceiver *dest); + +#endif diff --git a/src/include/commands/explain_format.h b/src/include/commands/explain_format.h new file mode 100644 index 0000000000000..05045bf8cb4af --- /dev/null +++ b/src/include/commands/explain_format.h @@ -0,0 +1,58 @@ +/*------------------------------------------------------------------------- + * + * explain_format.h + * prototypes for explain_format.c + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * src/include/commands/explain_format.h + * + *------------------------------------------------------------------------- + */ +#ifndef EXPLAIN_FORMAT_H +#define EXPLAIN_FORMAT_H + +#include "nodes/pg_list.h" + +struct ExplainState; /* avoid including explain.h here */ + +extern void ExplainPropertyList(const char *qlabel, List *data, + struct ExplainState *es); +extern void ExplainPropertyListNested(const char *qlabel, List *data, + struct ExplainState *es); +extern void ExplainPropertyText(const char *qlabel, const char *value, + struct ExplainState *es); +extern void ExplainPropertyInteger(const char *qlabel, const char *unit, + int64 value, struct ExplainState *es); +extern void ExplainPropertyUInteger(const char *qlabel, const char *unit, + uint64 value, struct ExplainState *es); +extern void ExplainPropertyFloat(const char *qlabel, const char *unit, + double value, int ndigits, + struct ExplainState *es); +extern void ExplainPropertyBool(const char *qlabel, bool value, + struct ExplainState *es); + +extern void ExplainOpenGroup(const char *objtype, const char *labelname, + bool labeled, struct ExplainState *es); +extern void ExplainCloseGroup(const char *objtype, const char *labelname, + bool labeled, struct ExplainState *es); + +extern void ExplainOpenSetAsideGroup(const char *objtype, const char *labelname, + bool labeled, int depth, + struct ExplainState *es); +extern void ExplainSaveGroup(struct ExplainState *es, int depth, + int *state_save); +extern void ExplainRestoreGroup(struct ExplainState *es, int depth, + int *state_save); + +extern void ExplainDummyGroup(const char *objtype, const char *labelname, + struct ExplainState *es); + +extern void ExplainBeginOutput(struct ExplainState *es); +extern void ExplainEndOutput(struct ExplainState *es); +extern void ExplainSeparatePlans(struct ExplainState *es); + +extern void ExplainIndentText(struct ExplainState *es); + +#endif diff --git a/src/include/commands/explain_state.h b/src/include/commands/explain_state.h new file mode 100644 index 0000000000000..32728f5d1a175 --- /dev/null +++ b/src/include/commands/explain_state.h @@ -0,0 +1,100 @@ +/*------------------------------------------------------------------------- + * + * explain_state.h + * prototypes for explain_state.c + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * src/include/commands/explain_state.h + * + *------------------------------------------------------------------------- + */ +#ifndef EXPLAIN_STATE_H +#define EXPLAIN_STATE_H + +#include "nodes/parsenodes.h" +#include "nodes/plannodes.h" +#include "parser/parse_node.h" + +typedef enum ExplainSerializeOption +{ + EXPLAIN_SERIALIZE_NONE, + EXPLAIN_SERIALIZE_TEXT, + EXPLAIN_SERIALIZE_BINARY, +} ExplainSerializeOption; + +typedef enum ExplainFormat +{ + EXPLAIN_FORMAT_TEXT, + EXPLAIN_FORMAT_XML, + EXPLAIN_FORMAT_JSON, + EXPLAIN_FORMAT_YAML, +} ExplainFormat; + +typedef struct ExplainWorkersState +{ + int num_workers; /* # of worker processes the plan used */ + bool *worker_inited; /* per-worker state-initialized flags */ + StringInfoData *worker_str; /* per-worker transient output buffers */ + int *worker_state_save; /* per-worker grouping state save areas */ + StringInfo prev_str; /* saved output buffer while redirecting */ +} ExplainWorkersState; + +typedef struct ExplainState +{ + StringInfo str; /* output buffer */ + /* options */ + bool verbose; /* be verbose */ + bool analyze; /* print actual times */ + bool costs; /* print estimated costs */ + bool buffers; /* print buffer usage */ + bool wal; /* print WAL usage */ + bool timing; /* print detailed node timing */ + bool summary; /* print total planning and execution timing */ + bool memory; /* print planner's memory usage information */ + bool settings; /* print modified settings */ + bool generic; /* generate a generic plan */ + ExplainSerializeOption serialize; /* serialize the query's output? */ + ExplainFormat format; /* output format */ + /* state for output formatting --- not reset for each new plan tree */ + int indent; /* current indentation level */ + List *grouping_stack; /* format-specific grouping state */ + /* state related to the current plan tree (filled by ExplainPrintPlan) */ + PlannedStmt *pstmt; /* top of plan */ + List *rtable; /* range table */ + List *rtable_names; /* alias names for RTEs */ + List *deparse_cxt; /* context list for deparsing expressions */ + Bitmapset *printed_subplans; /* ids of SubPlans we've printed */ + bool hide_workers; /* set if we find an invisible Gather */ + int rtable_size; /* length of rtable excluding the RTE_GROUP + * entry */ + /* state related to the current plan node */ + ExplainWorkersState *workers_state; /* needed if parallel plan */ + /* extensions */ + void **extension_state; + int extension_state_allocated; +} ExplainState; + +typedef void (*ExplainOptionHandler) (ExplainState *, DefElem *, ParseState *); + +/* Hook to perform additional EXPLAIN options validation */ +typedef void (*explain_validate_options_hook_type) (struct ExplainState *es, List *options, + ParseState *pstate); +extern PGDLLIMPORT explain_validate_options_hook_type explain_validate_options_hook; + +extern ExplainState *NewExplainState(void); +extern void ParseExplainOptionList(ExplainState *es, List *options, + ParseState *pstate); + +extern int GetExplainExtensionId(const char *extension_name); +extern void *GetExplainExtensionState(ExplainState *es, int extension_id); +extern void SetExplainExtensionState(ExplainState *es, int extension_id, + void *opaque); + +extern void RegisterExtensionExplainOption(const char *option_name, + ExplainOptionHandler handler); +extern bool ApplyExtensionExplainOption(ExplainState *es, DefElem *opt, + ParseState *pstate); + +#endif /* EXPLAIN_STATE_H */ diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h index c6f3f867eb7c1..24419bfb5c902 100644 --- a/src/include/commands/extension.h +++ b/src/include/commands/extension.h @@ -4,7 +4,7 @@ * Extension management commands (create/drop extension). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/extension.h @@ -17,6 +17,8 @@ #include "catalog/objectaddress.h" #include "parser/parse_node.h" +/* GUC */ +extern PGDLLIMPORT char *Extension_control_path; /* * creating_extension is only true while running a CREATE EXTENSION or ALTER diff --git a/src/include/commands/lockcmds.h b/src/include/commands/lockcmds.h index c3b2839f3f151..8a0025142ec92 100644 --- a/src/include/commands/lockcmds.h +++ b/src/include/commands/lockcmds.h @@ -4,7 +4,7 @@ * prototypes for lockcmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/lockcmds.h diff --git a/src/include/commands/matview.h b/src/include/commands/matview.h index a226b2e68fba5..750bb10ddca45 100644 --- a/src/include/commands/matview.h +++ b/src/include/commands/matview.h @@ -4,7 +4,7 @@ * prototypes for matview.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/matview.h @@ -24,9 +24,9 @@ extern void SetMatViewPopulatedState(Relation relation, bool newstate); extern ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, - ParamListInfo params, QueryCompletion *qc); -extern ObjectAddress RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, - const char *queryString, ParamListInfo params, + QueryCompletion *qc); +extern ObjectAddress RefreshMatViewByOid(Oid matviewOid, bool is_create, bool skipData, + bool concurrent, const char *queryString, QueryCompletion *qc); extern DestReceiver *CreateTransientRelDestReceiver(Oid transientoid); diff --git a/src/include/commands/policy.h b/src/include/commands/policy.h index f66ef49831f9b..f06aa1df43946 100644 --- a/src/include/commands/policy.h +++ b/src/include/commands/policy.h @@ -4,7 +4,7 @@ * prototypes for policy.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/policy.h diff --git a/src/include/commands/portalcmds.h b/src/include/commands/portalcmds.h index f09a1e17220d6..baef23d4215c9 100644 --- a/src/include/commands/portalcmds.h +++ b/src/include/commands/portalcmds.h @@ -4,7 +4,7 @@ * prototypes for portalcmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/portalcmds.h diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h index 61472c111d6ed..08daac8c92665 100644 --- a/src/include/commands/prepare.h +++ b/src/include/commands/prepare.h @@ -4,7 +4,7 @@ * PREPARE, EXECUTE and DEALLOCATE commands, and prepared-stmt storage * * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * src/include/commands/prepare.h * @@ -13,8 +13,9 @@ #ifndef PREPARE_H #define PREPARE_H -#include "commands/explain.h" +#include "commands/explain_state.h" #include "datatype/timestamp.h" +#include "tcop/dest.h" #include "utils/plancache.h" /* @@ -43,8 +44,8 @@ extern void ExecuteQuery(ParseState *pstate, DestReceiver *dest, QueryCompletion *qc); extern void DeallocateQuery(DeallocateStmt *stmt); extern void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, - ExplainState *es, const char *queryString, - ParamListInfo params, QueryEnvironment *queryEnv); + ExplainState *es, ParseState *pstate, + ParamListInfo params); /* Low-level access to stored prepared statements */ extern void StorePreparedStatement(const char *stmt_name, diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h index eebc806edc7c0..fc89282c3656c 100644 --- a/src/include/commands/proclang.h +++ b/src/include/commands/proclang.h @@ -3,7 +3,7 @@ * proclang.h * prototypes for proclang.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/proclang.h diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h index 5616d645230ce..7c736e7b03bcf 100644 --- a/src/include/commands/progress.h +++ b/src/include/commands/progress.h @@ -7,7 +7,7 @@ * constants, you probably also need to update the views based on them * in system_views.sql. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/progress.h @@ -28,6 +28,7 @@ #define PROGRESS_VACUUM_NUM_DEAD_ITEM_IDS 7 #define PROGRESS_VACUUM_INDEXES_TOTAL 8 #define PROGRESS_VACUUM_INDEXES_PROCESSED 9 +#define PROGRESS_VACUUM_DELAY_TIME 10 /* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */ #define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1 @@ -46,6 +47,7 @@ #define PROGRESS_ANALYZE_CHILD_TABLES_TOTAL 5 #define PROGRESS_ANALYZE_CHILD_TABLES_DONE 6 #define PROGRESS_ANALYZE_CURRENT_CHILD_TABLE_RELID 7 +#define PROGRESS_ANALYZE_DELAY_TIME 8 /* Phases of analyze (as advertised via PROGRESS_ANALYZE_PHASE) */ #define PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS 1 diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h index 5487c571f66c7..f90cf1ef896ee 100644 --- a/src/include/commands/publicationcmds.h +++ b/src/include/commands/publicationcmds.h @@ -4,7 +4,7 @@ * prototypes for publicationcmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/publicationcmds.h @@ -29,11 +29,15 @@ extern void RemovePublicationRelById(Oid proid); extern void RemovePublicationSchemaById(Oid psoid); extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId); -extern void AlterPublicationOwner_oid(Oid subid, Oid newOwnerId); +extern void AlterPublicationOwner_oid(Oid pubid, Oid newOwnerId); extern void InvalidatePublicationRels(List *relids); extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot); -extern bool pub_collist_contains_invalid_column(Oid pubid, Relation relation, - List *ancestors, bool pubviaroot); +extern bool pub_contains_invalid_column(Oid pubid, Relation relation, + List *ancestors, bool pubviaroot, + char pubgencols_type, + bool *invalid_column_list, + bool *invalid_gen_col); +extern void InvalidatePubRelSyncCache(Oid pubid, bool puballtables); #endif /* PUBLICATIONCMDS_H */ diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h index 5598dfa5d7665..8557176b66aa1 100644 --- a/src/include/commands/schemacmds.h +++ b/src/include/commands/schemacmds.h @@ -4,7 +4,7 @@ * prototypes for schemacmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/schemacmds.h diff --git a/src/include/commands/seclabel.h b/src/include/commands/seclabel.h index 89def5699a088..4550be94bc965 100644 --- a/src/include/commands/seclabel.h +++ b/src/include/commands/seclabel.h @@ -3,7 +3,7 @@ * * Prototypes for functions in commands/seclabel.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California */ #ifndef SECLABEL_H diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h index e88cbee3b56bc..9ac0b67683d3c 100644 --- a/src/include/commands/sequence.h +++ b/src/include/commands/sequence.h @@ -3,7 +3,7 @@ * sequence.h * prototypes for sequence.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/sequence.h diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h index 6971933190b5d..c2262e46a7f5c 100644 --- a/src/include/commands/subscriptioncmds.h +++ b/src/include/commands/subscriptioncmds.h @@ -4,7 +4,7 @@ * prototypes for subscriptioncmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/subscriptioncmds.h diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 85cbad3d0c204..6832470d38729 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -4,7 +4,7 @@ * prototypes for tablecmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/tablecmds.h diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 6ab2402896df1..4e8bf4dc0debd 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -4,7 +4,7 @@ * Tablespace management commands (create/drop tablespace). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/tablespace.h diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 8a5a9fe642274..2ed2c4bb3784b 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -3,7 +3,7 @@ * trigger.h * Declarations for trigger handling. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/trigger.h diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index e1b02927c4bab..6cc387e333712 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -4,7 +4,7 @@ * prototypes for typecmds.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/typecmds.h @@ -23,7 +23,7 @@ extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameters); extern void RemoveTypeById(Oid typeOid); -extern ObjectAddress DefineDomain(CreateDomainStmt *stmt); +extern ObjectAddress DefineDomain(ParseState *pstate, CreateDomainStmt *stmt); extern ObjectAddress DefineEnum(CreateEnumStmt *stmt); extern ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt); extern ObjectAddress AlterEnum(AlterEnumStmt *stmt); diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 759f9a87d38e5..bc37a80dc74fa 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -4,7 +4,7 @@ * header file for postgres vacuum cleaner and statistics analyzer * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/vacuum.h @@ -231,6 +231,13 @@ typedef struct VacuumParams VacOptValue truncate; /* Truncate empty pages at the end */ Oid toast_parent; /* for privilege checks when recursing */ + /* + * Fraction of pages in a relation that vacuum can eagerly scan and fail + * to freeze. Only applicable for table AMs using visibility maps. Derived + * from GUC or table storage parameter. 0 if disabled. + */ + double max_eager_freeze_failure_rate; + /* * The number of parallel vacuum workers. 0 by default which means choose * based on the number of indexes. -1 indicates parallel vacuum is @@ -296,6 +303,18 @@ extern PGDLLIMPORT int vacuum_multixact_freeze_min_age; extern PGDLLIMPORT int vacuum_multixact_freeze_table_age; extern PGDLLIMPORT int vacuum_failsafe_age; extern PGDLLIMPORT int vacuum_multixact_failsafe_age; +extern PGDLLIMPORT bool track_cost_delay_timing; +extern PGDLLIMPORT bool vacuum_truncate; + +/* + * Relevant for vacuums implementing eager scanning. Normal vacuums may + * eagerly scan some all-visible but not all-frozen pages. Since the goal + * is to freeze these pages, an eager scan that fails to set the page + * all-frozen in the VM is considered to have "failed". This is the + * fraction of pages in the relation vacuum may scan and fail to freeze + * before disabling eager scanning. + */ +extern PGDLLIMPORT double vacuum_max_eager_freeze_failure_rate; /* * Maximum value for default_statistics_target and per-column statistics @@ -313,6 +332,8 @@ extern PGDLLIMPORT bool VacuumFailsafeActive; extern PGDLLIMPORT double vacuum_cost_delay; extern PGDLLIMPORT int vacuum_cost_limit; +extern PGDLLIMPORT int64 parallel_vacuum_worker_delay_ns; + /* in commands/vacuum.c */ extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel); extern void vacuum(List *relations, VacuumParams *params, @@ -329,6 +350,7 @@ extern void vac_update_relstats(Relation relation, BlockNumber num_pages, double num_tuples, BlockNumber num_all_visible_pages, + BlockNumber num_all_frozen_pages, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, @@ -339,7 +361,7 @@ extern bool vacuum_get_cutoffs(Relation rel, const VacuumParams *params, struct VacuumCutoffs *cutoffs); extern bool vacuum_xid_failsafe_check(const struct VacuumCutoffs *cutoffs); extern void vac_update_datfrozenxid(void); -extern void vacuum_delay_point(void); +extern void vacuum_delay_point(bool is_analyze); extern bool vacuum_is_permitted_for_relation(Oid relid, Form_pg_class reltuple, bits32 options); extern Relation vacuum_open_relation(Oid relid, RangeVar *relation, diff --git a/src/include/commands/view.h b/src/include/commands/view.h index d2d8588989d1c..c41f51b161c95 100644 --- a/src/include/commands/view.h +++ b/src/include/commands/view.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/commands/view.h diff --git a/src/include/common/archive.h b/src/include/common/archive.h index f3f677ab6556c..6fed2a3a6c8b6 100644 --- a/src/include/common/archive.h +++ b/src/include/common/archive.h @@ -3,7 +3,7 @@ * archive.h * Common WAL archive routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/archive.h diff --git a/src/include/common/base64.h b/src/include/common/base64.h index 0d6d31b72b03d..66cb57b017fb9 100644 --- a/src/include/common/base64.h +++ b/src/include/common/base64.h @@ -3,7 +3,7 @@ * Encoding and decoding routines for base64 without whitespace * support. * - * Portions Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/common/base64.h */ @@ -11,8 +11,8 @@ #define BASE64_H /* base 64 */ -extern int pg_b64_encode(const char *src, int len, char *dst, int dstlen); -extern int pg_b64_decode(const char *src, int len, char *dst, int dstlen); +pg_nodiscard extern int pg_b64_encode(const uint8 *src, int len, char *dst, int dstlen); +pg_nodiscard extern int pg_b64_decode(const char *src, int len, uint8 *dst, int dstlen); extern int pg_b64_enc_len(int srclen); extern int pg_b64_dec_len(int srclen); diff --git a/src/include/common/blkreftable.h b/src/include/common/blkreftable.h index 43b913a82ecdf..67630d7460439 100644 --- a/src/include/common/blkreftable.h +++ b/src/include/common/blkreftable.h @@ -14,7 +14,7 @@ * the limit block number should be set to the length in blocks to * which it was truncated. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/common/blkreftable.h * diff --git a/src/include/common/checksum_helper.h b/src/include/common/checksum_helper.h index 116957d52e6ab..af423c30d7be0 100644 --- a/src/include/common/checksum_helper.h +++ b/src/include/common/checksum_helper.h @@ -3,7 +3,7 @@ * checksum_helper.h * Compute a checksum of any of various types using common routines * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/common/checksum_helper.h diff --git a/src/include/common/compression.h b/src/include/common/compression.h index b79bed9e245c2..640b42040483b 100644 --- a/src/include/common/compression.h +++ b/src/include/common/compression.h @@ -4,7 +4,7 @@ * * Shared definitions for compression methods and specifications. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/common/compression.h diff --git a/src/include/common/config_info.h b/src/include/common/config_info.h index 76d23f8b8beb0..860277410b952 100644 --- a/src/include/common/config_info.h +++ b/src/include/common/config_info.h @@ -2,7 +2,7 @@ * config_info.h * Common code for pg_config output * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/common/config_info.h */ diff --git a/src/include/common/connect.h b/src/include/common/connect.h index ddbd33a917b1d..e7413c1bd8153 100644 --- a/src/include/common/connect.h +++ b/src/include/common/connect.h @@ -3,7 +3,7 @@ * Interfaces in support of FE/BE connections. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/connect.h diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h index 6e263ce0de0ce..778eba1fb6abf 100644 --- a/src/include/common/controldata_utils.h +++ b/src/include/common/controldata_utils.h @@ -2,7 +2,7 @@ * controldata_utils.h * Common code for pg_controldata output * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/controldata_utils.h diff --git a/src/include/common/cryptohash.h b/src/include/common/cryptohash.h index 0fe77341232d3..ca103efbc3f18 100644 --- a/src/include/common/cryptohash.h +++ b/src/include/common/cryptohash.h @@ -3,7 +3,7 @@ * cryptohash.h * Generic headers for cryptographic hash functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/common/fe_memutils.h b/src/include/common/fe_memutils.h index 492cc97e8d19a..cd2052878618e 100644 --- a/src/include/common/fe_memutils.h +++ b/src/include/common/fe_memutils.h @@ -2,13 +2,25 @@ * fe_memutils.h * memory management support for frontend code * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/common/fe_memutils.h */ #ifndef FE_MEMUTILS_H #define FE_MEMUTILS_H +/* + * Assumed maximum size for allocation requests. + * + * We don't enforce this, so the actual maximum is the platform's SIZE_MAX. + * But it's useful to have it defined in frontend builds, so that common + * code can check for oversized requests without having frontend-vs-backend + * differences. Also, some code relies on MaxAllocSize being no more than + * INT_MAX/2, so rather than setting this to SIZE_MAX, make it the same as + * the backend's value. + */ +#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */ + /* * Flags for pg_malloc_extended and palloc_extended, deliberately named * the same as the backend flags. diff --git a/src/include/common/file_perm.h b/src/include/common/file_perm.h index d1f5616793e6a..c621d82511efe 100644 --- a/src/include/common/file_perm.h +++ b/src/include/common/file_perm.h @@ -3,7 +3,7 @@ * File and directory permission definitions * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/file_perm.h diff --git a/src/include/common/file_utils.h b/src/include/common/file_utils.h index e4339fb7b6c14..9fd88953e43b1 100644 --- a/src/include/common/file_utils.h +++ b/src/include/common/file_utils.h @@ -3,7 +3,7 @@ * Assorted utility functions to work on files. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/file_utils.h @@ -33,9 +33,10 @@ typedef enum DataDirSyncMethod struct iovec; /* avoid including port/pg_iovec.h here */ #ifdef FRONTEND +extern int pre_sync_fname(const char *fname, bool isdir); extern int fsync_fname(const char *fname, bool isdir); extern void sync_pgdata(const char *pg_data, int serverVersion, - DataDirSyncMethod sync_method); + DataDirSyncMethod sync_method, bool sync_data_files); extern void sync_dir_recurse(const char *dir, DataDirSyncMethod sync_method); extern int durable_rename(const char *oldfile, const char *newfile); extern int fsync_parent_path(const char *fname); diff --git a/src/include/common/hashfn.h b/src/include/common/hashfn.h index 0251b30af3e80..4430fb6983740 100644 --- a/src/include/common/hashfn.h +++ b/src/include/common/hashfn.h @@ -1,7 +1,7 @@ /* * Utilities for working with hash values. * - * Portions Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2017-2025, PostgreSQL Global Development Group */ #ifndef HASHFN_H diff --git a/src/include/common/hashfn_unstable.h b/src/include/common/hashfn_unstable.h index 0adb0f82f9a1f..8818a0d360b69 100644 --- a/src/include/common/hashfn_unstable.h +++ b/src/include/common/hashfn_unstable.h @@ -7,15 +7,13 @@ * indexes or other on-disk structures. See hashfn.h if you need stability. * * - * Portions Copyright (c) 2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2024-2025, PostgreSQL Global Development Group * * src/include/common/hashfn_unstable.h */ #ifndef HASHFN_UNSTABLE_H #define HASHFN_UNSTABLE_H -#include "port/pg_bitutils.h" -#include "port/pg_bswap.h" /* * fasthash is a modification of code taken from @@ -219,13 +217,6 @@ fasthash_accum(fasthash_state *hs, const char *k, size_t len) #define haszero64(v) \ (((v) - 0x0101010101010101) & ~(v) & 0x8080808080808080) -/* get first byte in memory order */ -#ifdef WORDS_BIGENDIAN -#define firstbyte64(v) ((v) >> 56) -#else -#define firstbyte64(v) ((v) & 0xFF) -#endif - /* * all-purpose workhorse for fasthash_accum_cstring */ @@ -262,33 +253,20 @@ static inline size_t fasthash_accum_cstring_aligned(fasthash_state *hs, const char *str) { const char *const start = str; - uint64 chunk; + size_t remainder; uint64 zero_byte_low; Assert(PointerIsAligned(start, uint64)); /* * For every chunk of input, check for zero bytes before mixing into the - * hash. The chunk with zeros must contain the NUL terminator. We arrange - * so that zero_byte_low tells us not only that a zero exists, but also - * where it is, so we can hash the remainder of the string. - * - * The haszero64 calculation will set bits corresponding to the lowest - * byte where a zero exists, so that suffices for little-endian machines. - * For big-endian machines, we would need bits set for the highest zero - * byte in the chunk, since the trailing junk past the terminator could - * contain additional zeros. haszero64 does not give us that, so we - * byteswap the chunk first. + * hash. The chunk with zeros must contain the NUL terminator. */ for (;;) { - chunk = *(uint64 *) str; + uint64 chunk = *(uint64 *) str; -#ifdef WORDS_BIGENDIAN - zero_byte_low = haszero64(pg_bswap64(chunk)); -#else zero_byte_low = haszero64(chunk); -#endif if (zero_byte_low) break; @@ -297,33 +275,9 @@ fasthash_accum_cstring_aligned(fasthash_state *hs, const char *str) str += FH_SIZEOF_ACCUM; } - if (firstbyte64(chunk) != 0) - { - size_t remainder; - uint64 mask; - - /* - * The byte corresponding to the NUL will be 0x80, so the rightmost - * bit position will be in the range 15, 23, ..., 63. Turn this into - * byte position by dividing by 8. - */ - remainder = pg_rightmost_one_pos64(zero_byte_low) / BITS_PER_BYTE; - - /* - * Create a mask for the remaining bytes so we can combine them into - * the hash. This must have the same result as mixing the remaining - * bytes with fasthash_accum(). - */ -#ifdef WORDS_BIGENDIAN - mask = ~UINT64CONST(0) << BITS_PER_BYTE * (FH_SIZEOF_ACCUM - remainder); -#else - mask = ~UINT64CONST(0) >> BITS_PER_BYTE * (FH_SIZEOF_ACCUM - remainder); -#endif - hs->accum = chunk & mask; - fasthash_combine(hs); - - str += remainder; - } + /* mix in remaining bytes */ + remainder = fasthash_accum_cstring_unaligned(hs, str); + str += remainder; return str - start; } diff --git a/src/include/common/hmac.h b/src/include/common/hmac.h index 1b93aa2892b70..c4d069e49a13e 100644 --- a/src/include/common/hmac.h +++ b/src/include/common/hmac.h @@ -3,7 +3,7 @@ * hmac.h * Generic headers for HMAC * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/common/int.h b/src/include/common/int.h index 7fc046e78afba..3973f13379d86 100644 --- a/src/include/common/int.h +++ b/src/include/common/int.h @@ -11,7 +11,7 @@ * the 64 bit cases can be considerably faster with intrinsics. In case no * intrinsics are available 128 bit math is used where available. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/int.h * @@ -23,15 +23,35 @@ /*--------- * The following guidelines apply to all the overflow routines: - * - If a + b overflows, return true, otherwise store the result of a + b - * into *result. The content of *result is implementation defined in case of - * overflow. - * - If a - b overflows, return true, otherwise store the result of a - b - * into *result. The content of *result is implementation defined in case of - * overflow. - * - If a * b overflows, return true, otherwise store the result of a * b - * into *result. The content of *result is implementation defined in case of + * + * If the result overflows, return true, otherwise store the result into + * *result. The content of *result is implementation defined in case of * overflow. + * + * bool pg_add_*_overflow(a, b, *result) + * + * Calculate a + b + * + * bool pg_sub_*_overflow(a, b, *result) + * + * Calculate a - b + * + * bool pg_mul_*_overflow(a, b, *result) + * + * Calculate a * b + * + * bool pg_neg_*_overflow(a, *result) + * + * Calculate -a + * + * + * In addition, this file contains: + * + * pg_abs_*( a) + * + * Calculate absolute value of a. Unlike the standard library abs() + * and labs() functions, the return type is unsigned, so the operation + * cannot overflow. *--------- */ @@ -97,6 +117,33 @@ pg_mul_s16_overflow(int16 a, int16 b, int16 *result) #endif } +static inline bool +pg_neg_s16_overflow(int16 a, int16 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#else + if (unlikely(a == PG_INT16_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = -a; + return false; +#endif +} + +static inline uint16 +pg_abs_s16(int16 a) +{ + /* + * This first widens the argument from int16 to int32 for use with abs(). + * The result is then narrowed from int32 to uint16. This prevents any + * possibility of overflow. + */ + return (uint16) abs((int32) a); +} + /* * INT32 */ @@ -154,6 +201,33 @@ pg_mul_s32_overflow(int32 a, int32 b, int32 *result) #endif } +static inline bool +pg_neg_s32_overflow(int32 a, int32 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#else + if (unlikely(a == PG_INT32_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = -a; + return false; +#endif +} + +static inline uint32 +pg_abs_s32(int32 a) +{ + /* + * This first widens the argument from int32 to int64 for use with + * i64abs(). The result is then narrowed from int64 to uint32. This + * prevents any possibility of overflow. + */ + return (uint32) i64abs((int64) a); +} + /* * INT64 */ @@ -258,6 +332,30 @@ pg_mul_s64_overflow(int64 a, int64 b, int64 *result) #endif } +static inline bool +pg_neg_s64_overflow(int64 a, int64 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#else + if (unlikely(a == PG_INT64_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = -a; + return false; +#endif +} + +static inline uint64 +pg_abs_s64(int64 a) +{ + if (unlikely(a == PG_INT64_MIN)) + return (uint64) PG_INT64_MAX + 1; + return (uint64) i64abs(a); +} + /*------------------------------------------------------------------------ * Overflow routines for unsigned integers *------------------------------------------------------------------------ @@ -318,6 +416,24 @@ pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result) #endif } +static inline bool +pg_neg_u16_overflow(uint16 a, int16 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#else + int32 res = -((int32) a); + + if (unlikely(res < PG_INT16_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = res; + return false; +#endif +} + /* * INT32 */ @@ -373,6 +489,24 @@ pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result) #endif } +static inline bool +pg_neg_u32_overflow(uint32 a, int32 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#else + int64 res = -((int64) a); + + if (unlikely(res < PG_INT32_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = res; + return false; +#endif +} + /* * UINT64 */ @@ -438,6 +572,35 @@ pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result) #endif } +static inline bool +pg_neg_u64_overflow(uint64 a, int64 *result) +{ +#if defined(HAVE__BUILTIN_OP_OVERFLOW) + return __builtin_sub_overflow(0, a, result); +#elif defined(HAVE_INT128) + int128 res = -((int128) a); + + if (unlikely(res < PG_INT64_MIN)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + *result = res; + return false; +#else + if (unlikely(a > (uint64) PG_INT64_MAX + 1)) + { + *result = 0x5EED; /* to avoid spurious warnings */ + return true; + } + if (unlikely(a == (uint64) PG_INT64_MAX + 1)) + *result = PG_INT64_MIN; + else + *result = -((int64) a); + return false; +#endif +} + /*------------------------------------------------------------------------ * * Comparison routines for integer types. diff --git a/src/include/common/int128.h b/src/include/common/int128.h index bb443303a84c8..a50f5709c2988 100644 --- a/src/include/common/int128.h +++ b/src/include/common/int128.h @@ -8,7 +8,7 @@ * * See src/tools/testint128.c for a simple test harness for this file. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/int128.h * diff --git a/src/include/common/ip.h b/src/include/common/ip.h index 5648b6e52214d..8eeae215435be 100644 --- a/src/include/common/ip.h +++ b/src/include/common/ip.h @@ -5,7 +5,7 @@ * * These definitions are used by both frontend and backend code. * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/common/ip.h * @@ -17,7 +17,7 @@ #include #include -#include "libpq/pqcomm.h" /* pgrminclude ignore */ +#include "libpq/pqcomm.h" extern int pg_getaddrinfo_all(const char *hostname, const char *servname, diff --git a/src/include/common/jsonapi.h b/src/include/common/jsonapi.h index 71a491d72dc0e..5d1a3ef3833bd 100644 --- a/src/include/common/jsonapi.h +++ b/src/include/common/jsonapi.h @@ -3,7 +3,7 @@ * jsonapi.h * Declarations for JSON API support. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/jsonapi.h @@ -14,8 +14,6 @@ #ifndef JSONAPI_H #define JSONAPI_H -#include "lib/stringinfo.h" - typedef enum JsonTokenType { JSON_TOKEN_INVALID, @@ -51,6 +49,7 @@ typedef enum JsonParseErrorType JSON_EXPECTED_OBJECT_NEXT, JSON_EXPECTED_STRING, JSON_INVALID_TOKEN, + JSON_OUT_OF_MEMORY, JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_ESCAPE_FORMAT, JSON_UNICODE_HIGH_ESCAPE, @@ -64,6 +63,16 @@ typedef enum JsonParseErrorType typedef struct JsonParserStack JsonParserStack; typedef struct JsonIncrementalState JsonIncrementalState; +/* + * Don't depend on the internal type header for strval; if callers need access + * then they can include the appropriate header themselves. + */ +#ifdef JSONAPI_USE_PQEXPBUFFER +#define jsonapi_StrValType PQExpBufferData +#else +#define jsonapi_StrValType StringInfoData +#endif + /* * All the fields in this structure should be treated as read-only. * @@ -83,9 +92,11 @@ typedef struct JsonIncrementalState JsonIncrementalState; * conjunction with token_start. * * JSONLEX_FREE_STRUCT/STRVAL are used to drive freeJsonLexContext. + * JSONLEX_CTX_OWNS_TOKENS is used by setJsonLexContextOwnsTokens. */ #define JSONLEX_FREE_STRUCT (1 << 0) #define JSONLEX_FREE_STRVAL (1 << 1) +#define JSONLEX_CTX_OWNS_TOKENS (1 << 2) typedef struct JsonLexContext { const char *input; @@ -102,10 +113,17 @@ typedef struct JsonLexContext const char *line_start; /* where that line starts within input */ JsonParserStack *pstack; JsonIncrementalState *inc_state; - StringInfo strval; - StringInfo errormsg; + bool need_escapes; + struct jsonapi_StrValType *strval; /* only used if need_escapes == true */ + struct jsonapi_StrValType *errormsg; } JsonLexContext; +/* + * Function types for custom json parsing actions. + * + * fname will be NULL if the context has need_escapes=false, as will token for + * string type values. + */ typedef JsonParseErrorType (*json_struct_action) (void *state); typedef JsonParseErrorType (*json_ofield_action) (void *state, char *fname, bool isnull); typedef JsonParseErrorType (*json_aelem_action) (void *state, bool isnull); @@ -120,9 +138,10 @@ typedef JsonParseErrorType (*json_scalar_action) (void *state, char *token, Json * to doing a pure parse with no side-effects, and is therefore exactly * what the json input routines do. * - * The 'fname' and 'token' strings passed to these actions are palloc'd. - * They are not free'd or used further by the parser, so the action function - * is free to do what it wishes with them. + * By default, the 'fname' and 'token' strings passed to these actions are + * palloc'd. They are not free'd or used further by the parser, so the action + * function is free to do what it wishes with them. This behavior may be + * modified by setJsonLexContextOwnsTokens(). * * All action functions return JsonParseErrorType. If the result isn't * JSON_SUCCESS, the parse is abandoned and that error code is returned. @@ -153,16 +172,16 @@ typedef struct JsonSemAction * does nothing and just continues. */ extern JsonParseErrorType pg_parse_json(JsonLexContext *lex, - JsonSemAction *sem); + const JsonSemAction *sem); extern JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, - JsonSemAction *sem, + const JsonSemAction *sem, const char *json, size_t len, bool is_last); /* the null action object used for pure validation */ -extern PGDLLIMPORT JsonSemAction nullSemAction; +extern PGDLLIMPORT const JsonSemAction nullSemAction; /* * json_count_array_elements performs a fast secondary parse to determine the @@ -184,12 +203,17 @@ extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex, * struct is allocated. * * If need_escapes is true, ->strval stores the unescaped lexemes. + * + * Setting need_escapes to true is necessary if the operation needs + * to reference field names or scalar string values. This is true of most + * operations beyond purely checking the json-validity of the source + * document. + * * Unescaping is expensive, so only request it when necessary. * * If need_escapes is true or lex was given as NULL, then the caller is * responsible for freeing the returned struct, either by calling - * freeJsonLexContext() or (in backend environment) via memory context - * cleanup. + * freeJsonLexContext() or (in backends) via memory context cleanup. */ extern JsonLexContext *makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, @@ -206,6 +230,25 @@ extern JsonLexContext *makeJsonLexContextIncremental(JsonLexContext *lex, int encoding, bool need_escapes); +/* + * Sets whether tokens passed to semantic action callbacks are owned by the + * context (in which case, the callback must duplicate the tokens for long-term + * storage) or by the callback (in which case, the callback must explicitly + * free tokens to avoid leaks). + * + * By default, this setting is false: the callback owns the tokens that are + * passed to it (and if parsing fails between the two object-field callbacks, + * the field name token will likely leak). If set to true, tokens will be freed + * by the lexer after the callback completes. + * + * Setting this to true is important for long-lived clients (such as libpq) + * that must not leak memory during a parse failure. For a server backend using + * memory contexts, or a client application which will exit on parse failure, + * this setting is less critical. + */ +extern void setJsonLexContextOwnsTokens(JsonLexContext *lex, + bool owned_by_context); + extern void freeJsonLexContext(JsonLexContext *lex); /* lex one token */ diff --git a/src/include/common/keywords.h b/src/include/common/keywords.h index 0144377ab5b3e..8a35cc8395633 100644 --- a/src/include/common/keywords.h +++ b/src/include/common/keywords.h @@ -4,7 +4,7 @@ * PostgreSQL's list of SQL keywords * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/keywords.h diff --git a/src/include/common/kwlookup.h b/src/include/common/kwlookup.h index 3725e47cddab6..bcc2a018bb454 100644 --- a/src/include/common/kwlookup.h +++ b/src/include/common/kwlookup.h @@ -4,7 +4,7 @@ * Key word lookup for PostgreSQL * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/kwlookup.h diff --git a/src/include/common/link-canary.h b/src/include/common/link-canary.h index 0c6daed0a7520..699d3a0baa17f 100644 --- a/src/include/common/link-canary.h +++ b/src/include/common/link-canary.h @@ -3,7 +3,7 @@ * link-canary.h * Detect whether src/common functions came from frontend or backend. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * src/include/common/link-canary.h * diff --git a/src/include/common/logging.h b/src/include/common/logging.h index afbd9c059a952..81529ee8f2926 100644 --- a/src/include/common/logging.h +++ b/src/include/common/logging.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * Logging framework for frontend programs * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * src/include/common/logging.h * @@ -153,4 +153,11 @@ void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, exit(1); \ } while(0) +/* + * Use these variants for "can't happen" cases, if it seems translating their + * messages would be a waste of effort. + */ +#define pg_log_error_internal(...) pg_log_error(__VA_ARGS__) +#define pg_fatal_internal(...) pg_fatal(__VA_ARGS__) + #endif /* COMMON_LOGGING_H */ diff --git a/src/include/common/md5.h b/src/include/common/md5.h index 6c32f10e89af2..0c9ae4888f2d8 100644 --- a/src/include/common/md5.h +++ b/src/include/common/md5.h @@ -6,7 +6,7 @@ * These definitions are needed by both frontend and backend code to work * with MD5-encrypted passwords. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/md5.h @@ -28,9 +28,9 @@ /* Utilities common to all the MD5 implementations, as of md5_common.c */ extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr); -extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf, +extern bool pg_md5_binary(const void *buff, size_t len, uint8 *outbuf, const char **errstr); -extern bool pg_md5_encrypt(const char *passwd, const char *salt, +extern bool pg_md5_encrypt(const char *passwd, const uint8 *salt, size_t salt_len, char *buf, const char **errstr); diff --git a/src/include/common/oauth-common.h b/src/include/common/oauth-common.h new file mode 100644 index 0000000000000..5fb559d84b2bd --- /dev/null +++ b/src/include/common/oauth-common.h @@ -0,0 +1,19 @@ +/*------------------------------------------------------------------------- + * + * oauth-common.h + * Declarations for helper functions used for OAuth/OIDC authentication + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/common/oauth-common.h + * + *------------------------------------------------------------------------- + */ +#ifndef OAUTH_COMMON_H +#define OAUTH_COMMON_H + +/* Name of SASL mechanism per IANA */ +#define OAUTHBEARER_NAME "OAUTHBEARER" + +#endif /* OAUTH_COMMON_H */ diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h index 964d691d32de5..eab2c14cc37ea 100644 --- a/src/include/common/openssl.h +++ b/src/include/common/openssl.h @@ -3,7 +3,7 @@ * openssl.h * OpenSSL supporting functionality shared between frontend and backend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,10 +18,10 @@ #include /* - * OpenSSL doesn't provide any very nice way to identify the min/max - * protocol versions the library supports, so we fake it as best we can. - * Note in particular that this doesn't account for restrictions that - * might be specified in the installation's openssl.cnf. + * LibreSSL doesn't provide any very nice way to identify the max protocol + * versions the library supports, analogous to TLS_MAX_VERSION in OpenSSL, so + * we define our own. Note in particular that this doesn't account for + * restrictions that might be specified in the installation's openssl.cnf. * * We disable SSLv3 and older in library setup, so TLSv1 is the oldest * protocol version of interest. @@ -38,12 +38,6 @@ #define MAX_OPENSSL_TLS_VERSION "TLSv1" #endif -/* src/common/protocol_openssl.c */ -#ifndef SSL_CTX_set_min_proto_version -extern int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version); -extern int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version); -#endif - #endif /* USE_OPENSSL */ #endif /* COMMON_OPENSSL_H */ diff --git a/src/include/common/parse_manifest.h b/src/include/common/parse_manifest.h index ee571a568a19b..6172d1d52244e 100644 --- a/src/include/common/parse_manifest.h +++ b/src/include/common/parse_manifest.h @@ -3,7 +3,7 @@ * parse_manifest.h * Parse a backup manifest in JSON format. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/parse_manifest.h @@ -28,14 +28,13 @@ typedef void (*json_manifest_system_identifier_callback) (JsonManifestParseConte uint64 manifest_system_identifier); typedef void (*json_manifest_per_file_callback) (JsonManifestParseContext *, const char *pathname, - size_t size, pg_checksum_type checksum_type, + uint64 size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload); typedef void (*json_manifest_per_wal_range_callback) (JsonManifestParseContext *, TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn); typedef void (*json_manifest_error_callback) (JsonManifestParseContext *, - const char *fmt,...) pg_attribute_printf(2, 3) - pg_attribute_noreturn(); + const char *fmt,...) pg_attribute_printf(2, 3); struct JsonManifestParseContext { @@ -50,8 +49,8 @@ struct JsonManifestParseContext extern void json_parse_manifest(JsonManifestParseContext *context, const char *buffer, size_t size); extern JsonManifestParseIncrementalState *json_parse_manifest_incremental_init(JsonManifestParseContext *context); -extern void json_parse_manifest_incremental_chunk( - JsonManifestParseIncrementalState *incstate, const char *chunk, size_t size, +extern void json_parse_manifest_incremental_chunk(JsonManifestParseIncrementalState *incstate, + const char *chunk, size_t size, bool is_last); extern void json_parse_manifest_incremental_shutdown(JsonManifestParseIncrementalState *incstate); diff --git a/src/include/common/percentrepl.h b/src/include/common/percentrepl.h index fbca9c1fc901e..a4786b9224e5b 100644 --- a/src/include/common/percentrepl.h +++ b/src/include/common/percentrepl.h @@ -3,7 +3,7 @@ * percentrepl.h * Common routines to replace percent placeholders in strings * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/percentrepl.h diff --git a/src/include/common/pg_prng.h b/src/include/common/pg_prng.h index c114c6419d009..085c5ad3dfdd5 100644 --- a/src/include/common/pg_prng.h +++ b/src/include/common/pg_prng.h @@ -2,7 +2,7 @@ * * Pseudo-Random Number Generator * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * * src/include/common/pg_prng.h * @@ -44,7 +44,7 @@ extern bool pg_prng_seed_check(pg_prng_state *state); * pg_strong_random.c and thence OpenSSL. */ #define pg_prng_strong_seed(state) \ - (pg_strong_random((void *) (state), sizeof(pg_prng_state)) ? \ + (pg_strong_random(state, sizeof(pg_prng_state)) ? \ pg_prng_seed_check(state) : false) extern uint64 pg_prng_uint64(pg_prng_state *state); diff --git a/src/include/common/relpath.h b/src/include/common/relpath.h index 6f006d5a938c5..6f2fce216f8c5 100644 --- a/src/include/common/relpath.h +++ b/src/include/common/relpath.h @@ -3,7 +3,7 @@ * relpath.h * Declarations for GetRelationPath() and friends * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/relpath.h @@ -14,10 +14,10 @@ #define RELPATH_H /* - * 'pgrminclude ignore' needed here because CppAsString2() does not throw - * an error if the symbol is not defined. + * Required here; note that CppAsString2() does not throw an error if the + * symbol is not defined. */ -#include "catalog/catversion.h" /* pgrminclude ignore */ +#include "catalog/catversion.h" /* * RelFileNumber data type identifies the specific relation file name. @@ -33,6 +33,15 @@ typedef Oid RelFileNumber; #define TABLESPACE_VERSION_DIRECTORY "PG_" PG_MAJORVERSION "_" \ CppAsString2(CATALOG_VERSION_NO) +/* + * Tablespace path (relative to installation's $PGDATA). + * + * These values should not be changed as many tools rely on it. + */ +#define PG_TBLSPC_DIR "pg_tblspc" +#define PG_TBLSPC_DIR_SLASH "pg_tblspc/" /* required for strings + * comparisons */ + /* Characters to allow for an OID in a relation path */ #define OIDCHARS 10 /* max chars printed by %u */ @@ -68,13 +77,61 @@ extern PGDLLIMPORT const char *const forkNames[]; extern ForkNumber forkname_to_number(const char *forkName); extern int forkname_chars(const char *str, ForkNumber *fork); + +/* + * Unfortunately, there's no easy way to derive PROCNUMBER_CHARS from + * MAX_BACKENDS. MAX_BACKENDS is 2^18-1. Crosschecked in test_relpath(). + */ +#define PROCNUMBER_CHARS 6 + +/* + * The longest possible relation path lengths is from the following format: + * sprintf(rp.path, "%s/%u/%s/%u/t%d_%u", + * PG_TBLSPC_DIR, spcOid, + * TABLESPACE_VERSION_DIRECTORY, + * dbOid, procNumber, relNumber); + * + * Note this does *not* include the trailing null-byte, to make it easier to + * combine it with other lengths. + */ +#define REL_PATH_STR_MAXLEN \ + ( \ + sizeof(PG_TBLSPC_DIR) - 1 \ + + sizeof((char)'/') \ + + OIDCHARS /* spcOid */ \ + + sizeof((char)'/') \ + + sizeof(TABLESPACE_VERSION_DIRECTORY) - 1 \ + + sizeof((char)'/') \ + + OIDCHARS /* dbOid */ \ + + sizeof((char)'/') \ + + sizeof((char)'t') /* temporary table indicator */ \ + + PROCNUMBER_CHARS /* procNumber */ \ + + sizeof((char)'_') \ + + OIDCHARS /* relNumber */ \ + + sizeof((char)'_') \ + + FORKNAMECHARS /* forkNames[forkNumber] */ \ + ) + +/* + * String of the exact length required to represent a relation path. We return + * this struct, instead of char[REL_PATH_STR_MAXLEN + 1], as the pointer would + * decay to a plain char * too easily, possibly preventing the compiler from + * detecting invalid references to the on-stack return value of + * GetRelationPath(). + */ +typedef struct RelPathStr +{ + char str[REL_PATH_STR_MAXLEN + 1]; +} RelPathStr; + + /* * Stuff for computing filesystem pathnames for relations. */ extern char *GetDatabasePath(Oid dbOid, Oid spcOid); -extern char *GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, - int procNumber, ForkNumber forkNumber); +extern RelPathStr GetRelationPath(Oid dbOid, Oid spcOid, RelFileNumber relNumber, + int procNumber, ForkNumber forkNumber); /* * Wrapper macros for GetRelationPath. Beware of multiple diff --git a/src/include/common/restricted_token.h b/src/include/common/restricted_token.h index aa83eb2cd0f07..3b8e3d6ca6cc1 100644 --- a/src/include/common/restricted_token.h +++ b/src/include/common/restricted_token.h @@ -2,7 +2,7 @@ * restricted_token.h * helper routine to ensure restricted token on Windows * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/restricted_token.h diff --git a/src/include/common/saslprep.h b/src/include/common/saslprep.h index aaf3e8e12cb14..f4b006dfd9bb4 100644 --- a/src/include/common/saslprep.h +++ b/src/include/common/saslprep.h @@ -5,7 +5,7 @@ * * These definitions are used by both frontend and backend code. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/saslprep.h * diff --git a/src/include/common/scram-common.h b/src/include/common/scram-common.h index ce848aa328df9..5ce055e0e274d 100644 --- a/src/include/common/scram-common.h +++ b/src/include/common/scram-common.h @@ -3,7 +3,7 @@ * scram-common.h * Declarations for helper functions used for SCRAM authentication * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/scram-common.h @@ -51,7 +51,7 @@ extern int scram_SaltedPassword(const char *password, pg_cryptohash_type hash_type, int key_length, - const char *salt, int saltlen, int iterations, + const uint8 *salt, int saltlen, int iterations, uint8 *result, const char **errstr); extern int scram_H(const uint8 *input, pg_cryptohash_type hash_type, int key_length, uint8 *result, @@ -64,7 +64,7 @@ extern int scram_ServerKey(const uint8 *salted_password, uint8 *result, const char **errstr); extern char *scram_build_secret(pg_cryptohash_type hash_type, int key_length, - const char *salt, int saltlen, int iterations, + const uint8 *salt, int saltlen, int iterations, const char *password, const char **errstr); #endif /* SCRAM_COMMON_H */ diff --git a/src/include/common/sha1.h b/src/include/common/sha1.h index b66d9ae033c2c..27abde143ba63 100644 --- a/src/include/common/sha1.h +++ b/src/include/common/sha1.h @@ -3,7 +3,7 @@ * sha1.h * Constants related to SHA1. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/sha1.h diff --git a/src/include/common/sha2.h b/src/include/common/sha2.h index ea040c579f32b..5a0fe1b481ee7 100644 --- a/src/include/common/sha2.h +++ b/src/include/common/sha2.h @@ -3,7 +3,7 @@ * sha2.h * Constants related to SHA224, 256, 384 AND 512. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/common/shortest_dec.h b/src/include/common/shortest_dec.h index d780b23eedf96..9ca909ef5616f 100644 --- a/src/include/common/shortest_dec.h +++ b/src/include/common/shortest_dec.h @@ -2,7 +2,7 @@ * * Ryu floating-point output. * - * Portions Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/common/shortest_dec.h diff --git a/src/include/common/string.h b/src/include/common/string.h index 721aabe9dc1b6..ffe5ed51c5db6 100644 --- a/src/include/common/string.h +++ b/src/include/common/string.h @@ -2,7 +2,7 @@ * string.h * string handling helpers * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/string.h diff --git a/src/include/common/unicode_case.h b/src/include/common/unicode_case.h index 5a65c12d45315..41e2c1f4b33f5 100644 --- a/src/include/common/unicode_case.h +++ b/src/include/common/unicode_case.h @@ -5,7 +5,7 @@ * * These definitions can be used by both frontend and backend code. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/unicode_case.h * @@ -21,12 +21,15 @@ typedef size_t (*WordBoundaryNext) (void *wbstate); pg_wchar unicode_lowercase_simple(pg_wchar code); pg_wchar unicode_titlecase_simple(pg_wchar code); pg_wchar unicode_uppercase_simple(pg_wchar code); +pg_wchar unicode_casefold_simple(pg_wchar code); size_t unicode_strlower(char *dst, size_t dstsize, const char *src, - ssize_t srclen); + ssize_t srclen, bool full); size_t unicode_strtitle(char *dst, size_t dstsize, const char *src, - ssize_t srclen, WordBoundaryNext wbnext, - void *wbstate); + ssize_t srclen, bool full, + WordBoundaryNext wbnext, void *wbstate); size_t unicode_strupper(char *dst, size_t dstsize, const char *src, - ssize_t srclen); + ssize_t srclen, bool full); +size_t unicode_strfold(char *dst, size_t dstsize, const char *src, + ssize_t srclen, bool full); #endif /* UNICODE_CASE_H */ diff --git a/src/include/common/unicode_case_table.h b/src/include/common/unicode_case_table.h index eeda045839970..d53117865820b 100644 --- a/src/include/common/unicode_case_table.h +++ b/src/include/common/unicode_case_table.h @@ -3,7 +3,7 @@ * unicode_case_table.h * Case mapping and information table. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_case_table.h @@ -20,2982 +20,13611 @@ #include "common/unicode_case.h" #include "mb/pg_wchar.h" +/* + * The maximum number of codepoints that can result from case mapping + * of a single character. See Unicode section 5.18 "Case Mappings". + */ +#define MAX_CASE_EXPANSION 3 + +/* + * Case mapping condition flags. For now, only Final_Sigma is supported. + * + * See Unicode Context Specification for Casing. + */ +#define PG_U_FINAL_SIGMA (1 << 0) + typedef enum { CaseLower = 0, CaseTitle = 1, CaseUpper = 2, + CaseFold = 3, NCaseKind } CaseKind; typedef struct { - pg_wchar codepoint; /* Unicode codepoint */ - pg_wchar simplemap[NCaseKind]; -} pg_case_map; + int16 conditions; + pg_wchar map[NCaseKind][MAX_CASE_EXPANSION]; +} pg_special_case; /* - * Case mapping table. Dense for codepoints < 0x80 (enabling fast lookup), - * sparse for higher codepoints (requiring scan or binary search). + * Special case mappings that aren't representable in the simple map. + * Entries are referenced from simple_case_map. */ -static const pg_case_map case_map[2955] = +static const pg_special_case special_case[106] = { - /* begin dense entries for codepoints < 0x80 */ - {0x000000, {[CaseLower] = 0x000000,[CaseTitle] = 0x000000,[CaseUpper] = 0x000000}}, - {0x000001, {[CaseLower] = 0x000001,[CaseTitle] = 0x000001,[CaseUpper] = 0x000001}}, - {0x000002, {[CaseLower] = 0x000002,[CaseTitle] = 0x000002,[CaseUpper] = 0x000002}}, - {0x000003, {[CaseLower] = 0x000003,[CaseTitle] = 0x000003,[CaseUpper] = 0x000003}}, - {0x000004, {[CaseLower] = 0x000004,[CaseTitle] = 0x000004,[CaseUpper] = 0x000004}}, - {0x000005, {[CaseLower] = 0x000005,[CaseTitle] = 0x000005,[CaseUpper] = 0x000005}}, - {0x000006, {[CaseLower] = 0x000006,[CaseTitle] = 0x000006,[CaseUpper] = 0x000006}}, - {0x000007, {[CaseLower] = 0x000007,[CaseTitle] = 0x000007,[CaseUpper] = 0x000007}}, - {0x000008, {[CaseLower] = 0x000008,[CaseTitle] = 0x000008,[CaseUpper] = 0x000008}}, - {0x000009, {[CaseLower] = 0x000009,[CaseTitle] = 0x000009,[CaseUpper] = 0x000009}}, - {0x00000a, {[CaseLower] = 0x00000a,[CaseTitle] = 0x00000a,[CaseUpper] = 0x00000a}}, - {0x00000b, {[CaseLower] = 0x00000b,[CaseTitle] = 0x00000b,[CaseUpper] = 0x00000b}}, - {0x00000c, {[CaseLower] = 0x00000c,[CaseTitle] = 0x00000c,[CaseUpper] = 0x00000c}}, - {0x00000d, {[CaseLower] = 0x00000d,[CaseTitle] = 0x00000d,[CaseUpper] = 0x00000d}}, - {0x00000e, {[CaseLower] = 0x00000e,[CaseTitle] = 0x00000e,[CaseUpper] = 0x00000e}}, - {0x00000f, {[CaseLower] = 0x00000f,[CaseTitle] = 0x00000f,[CaseUpper] = 0x00000f}}, - {0x000010, {[CaseLower] = 0x000010,[CaseTitle] = 0x000010,[CaseUpper] = 0x000010}}, - {0x000011, {[CaseLower] = 0x000011,[CaseTitle] = 0x000011,[CaseUpper] = 0x000011}}, - {0x000012, {[CaseLower] = 0x000012,[CaseTitle] = 0x000012,[CaseUpper] = 0x000012}}, - {0x000013, {[CaseLower] = 0x000013,[CaseTitle] = 0x000013,[CaseUpper] = 0x000013}}, - {0x000014, {[CaseLower] = 0x000014,[CaseTitle] = 0x000014,[CaseUpper] = 0x000014}}, - {0x000015, {[CaseLower] = 0x000015,[CaseTitle] = 0x000015,[CaseUpper] = 0x000015}}, - {0x000016, {[CaseLower] = 0x000016,[CaseTitle] = 0x000016,[CaseUpper] = 0x000016}}, - {0x000017, {[CaseLower] = 0x000017,[CaseTitle] = 0x000017,[CaseUpper] = 0x000017}}, - {0x000018, {[CaseLower] = 0x000018,[CaseTitle] = 0x000018,[CaseUpper] = 0x000018}}, - {0x000019, {[CaseLower] = 0x000019,[CaseTitle] = 0x000019,[CaseUpper] = 0x000019}}, - {0x00001a, {[CaseLower] = 0x00001a,[CaseTitle] = 0x00001a,[CaseUpper] = 0x00001a}}, - {0x00001b, {[CaseLower] = 0x00001b,[CaseTitle] = 0x00001b,[CaseUpper] = 0x00001b}}, - {0x00001c, {[CaseLower] = 0x00001c,[CaseTitle] = 0x00001c,[CaseUpper] = 0x00001c}}, - {0x00001d, {[CaseLower] = 0x00001d,[CaseTitle] = 0x00001d,[CaseUpper] = 0x00001d}}, - {0x00001e, {[CaseLower] = 0x00001e,[CaseTitle] = 0x00001e,[CaseUpper] = 0x00001e}}, - {0x00001f, {[CaseLower] = 0x00001f,[CaseTitle] = 0x00001f,[CaseUpper] = 0x00001f}}, - {0x000020, {[CaseLower] = 0x000020,[CaseTitle] = 0x000020,[CaseUpper] = 0x000020}}, - {0x000021, {[CaseLower] = 0x000021,[CaseTitle] = 0x000021,[CaseUpper] = 0x000021}}, - {0x000022, {[CaseLower] = 0x000022,[CaseTitle] = 0x000022,[CaseUpper] = 0x000022}}, - {0x000023, {[CaseLower] = 0x000023,[CaseTitle] = 0x000023,[CaseUpper] = 0x000023}}, - {0x000024, {[CaseLower] = 0x000024,[CaseTitle] = 0x000024,[CaseUpper] = 0x000024}}, - {0x000025, {[CaseLower] = 0x000025,[CaseTitle] = 0x000025,[CaseUpper] = 0x000025}}, - {0x000026, {[CaseLower] = 0x000026,[CaseTitle] = 0x000026,[CaseUpper] = 0x000026}}, - {0x000027, {[CaseLower] = 0x000027,[CaseTitle] = 0x000027,[CaseUpper] = 0x000027}}, - {0x000028, {[CaseLower] = 0x000028,[CaseTitle] = 0x000028,[CaseUpper] = 0x000028}}, - {0x000029, {[CaseLower] = 0x000029,[CaseTitle] = 0x000029,[CaseUpper] = 0x000029}}, - {0x00002a, {[CaseLower] = 0x00002a,[CaseTitle] = 0x00002a,[CaseUpper] = 0x00002a}}, - {0x00002b, {[CaseLower] = 0x00002b,[CaseTitle] = 0x00002b,[CaseUpper] = 0x00002b}}, - {0x00002c, {[CaseLower] = 0x00002c,[CaseTitle] = 0x00002c,[CaseUpper] = 0x00002c}}, - {0x00002d, {[CaseLower] = 0x00002d,[CaseTitle] = 0x00002d,[CaseUpper] = 0x00002d}}, - {0x00002e, {[CaseLower] = 0x00002e,[CaseTitle] = 0x00002e,[CaseUpper] = 0x00002e}}, - {0x00002f, {[CaseLower] = 0x00002f,[CaseTitle] = 0x00002f,[CaseUpper] = 0x00002f}}, - {0x000030, {[CaseLower] = 0x000030,[CaseTitle] = 0x000030,[CaseUpper] = 0x000030}}, - {0x000031, {[CaseLower] = 0x000031,[CaseTitle] = 0x000031,[CaseUpper] = 0x000031}}, - {0x000032, {[CaseLower] = 0x000032,[CaseTitle] = 0x000032,[CaseUpper] = 0x000032}}, - {0x000033, {[CaseLower] = 0x000033,[CaseTitle] = 0x000033,[CaseUpper] = 0x000033}}, - {0x000034, {[CaseLower] = 0x000034,[CaseTitle] = 0x000034,[CaseUpper] = 0x000034}}, - {0x000035, {[CaseLower] = 0x000035,[CaseTitle] = 0x000035,[CaseUpper] = 0x000035}}, - {0x000036, {[CaseLower] = 0x000036,[CaseTitle] = 0x000036,[CaseUpper] = 0x000036}}, - {0x000037, {[CaseLower] = 0x000037,[CaseTitle] = 0x000037,[CaseUpper] = 0x000037}}, - {0x000038, {[CaseLower] = 0x000038,[CaseTitle] = 0x000038,[CaseUpper] = 0x000038}}, - {0x000039, {[CaseLower] = 0x000039,[CaseTitle] = 0x000039,[CaseUpper] = 0x000039}}, - {0x00003a, {[CaseLower] = 0x00003a,[CaseTitle] = 0x00003a,[CaseUpper] = 0x00003a}}, - {0x00003b, {[CaseLower] = 0x00003b,[CaseTitle] = 0x00003b,[CaseUpper] = 0x00003b}}, - {0x00003c, {[CaseLower] = 0x00003c,[CaseTitle] = 0x00003c,[CaseUpper] = 0x00003c}}, - {0x00003d, {[CaseLower] = 0x00003d,[CaseTitle] = 0x00003d,[CaseUpper] = 0x00003d}}, - {0x00003e, {[CaseLower] = 0x00003e,[CaseTitle] = 0x00003e,[CaseUpper] = 0x00003e}}, - {0x00003f, {[CaseLower] = 0x00003f,[CaseTitle] = 0x00003f,[CaseUpper] = 0x00003f}}, - {0x000040, {[CaseLower] = 0x000040,[CaseTitle] = 0x000040,[CaseUpper] = 0x000040}}, - {0x000041, {[CaseLower] = 0x000061,[CaseTitle] = 0x000041,[CaseUpper] = 0x000041}}, - {0x000042, {[CaseLower] = 0x000062,[CaseTitle] = 0x000042,[CaseUpper] = 0x000042}}, - {0x000043, {[CaseLower] = 0x000063,[CaseTitle] = 0x000043,[CaseUpper] = 0x000043}}, - {0x000044, {[CaseLower] = 0x000064,[CaseTitle] = 0x000044,[CaseUpper] = 0x000044}}, - {0x000045, {[CaseLower] = 0x000065,[CaseTitle] = 0x000045,[CaseUpper] = 0x000045}}, - {0x000046, {[CaseLower] = 0x000066,[CaseTitle] = 0x000046,[CaseUpper] = 0x000046}}, - {0x000047, {[CaseLower] = 0x000067,[CaseTitle] = 0x000047,[CaseUpper] = 0x000047}}, - {0x000048, {[CaseLower] = 0x000068,[CaseTitle] = 0x000048,[CaseUpper] = 0x000048}}, - {0x000049, {[CaseLower] = 0x000069,[CaseTitle] = 0x000049,[CaseUpper] = 0x000049}}, - {0x00004a, {[CaseLower] = 0x00006a,[CaseTitle] = 0x00004a,[CaseUpper] = 0x00004a}}, - {0x00004b, {[CaseLower] = 0x00006b,[CaseTitle] = 0x00004b,[CaseUpper] = 0x00004b}}, - {0x00004c, {[CaseLower] = 0x00006c,[CaseTitle] = 0x00004c,[CaseUpper] = 0x00004c}}, - {0x00004d, {[CaseLower] = 0x00006d,[CaseTitle] = 0x00004d,[CaseUpper] = 0x00004d}}, - {0x00004e, {[CaseLower] = 0x00006e,[CaseTitle] = 0x00004e,[CaseUpper] = 0x00004e}}, - {0x00004f, {[CaseLower] = 0x00006f,[CaseTitle] = 0x00004f,[CaseUpper] = 0x00004f}}, - {0x000050, {[CaseLower] = 0x000070,[CaseTitle] = 0x000050,[CaseUpper] = 0x000050}}, - {0x000051, {[CaseLower] = 0x000071,[CaseTitle] = 0x000051,[CaseUpper] = 0x000051}}, - {0x000052, {[CaseLower] = 0x000072,[CaseTitle] = 0x000052,[CaseUpper] = 0x000052}}, - {0x000053, {[CaseLower] = 0x000073,[CaseTitle] = 0x000053,[CaseUpper] = 0x000053}}, - {0x000054, {[CaseLower] = 0x000074,[CaseTitle] = 0x000054,[CaseUpper] = 0x000054}}, - {0x000055, {[CaseLower] = 0x000075,[CaseTitle] = 0x000055,[CaseUpper] = 0x000055}}, - {0x000056, {[CaseLower] = 0x000076,[CaseTitle] = 0x000056,[CaseUpper] = 0x000056}}, - {0x000057, {[CaseLower] = 0x000077,[CaseTitle] = 0x000057,[CaseUpper] = 0x000057}}, - {0x000058, {[CaseLower] = 0x000078,[CaseTitle] = 0x000058,[CaseUpper] = 0x000058}}, - {0x000059, {[CaseLower] = 0x000079,[CaseTitle] = 0x000059,[CaseUpper] = 0x000059}}, - {0x00005a, {[CaseLower] = 0x00007a,[CaseTitle] = 0x00005a,[CaseUpper] = 0x00005a}}, - {0x00005b, {[CaseLower] = 0x00005b,[CaseTitle] = 0x00005b,[CaseUpper] = 0x00005b}}, - {0x00005c, {[CaseLower] = 0x00005c,[CaseTitle] = 0x00005c,[CaseUpper] = 0x00005c}}, - {0x00005d, {[CaseLower] = 0x00005d,[CaseTitle] = 0x00005d,[CaseUpper] = 0x00005d}}, - {0x00005e, {[CaseLower] = 0x00005e,[CaseTitle] = 0x00005e,[CaseUpper] = 0x00005e}}, - {0x00005f, {[CaseLower] = 0x00005f,[CaseTitle] = 0x00005f,[CaseUpper] = 0x00005f}}, - {0x000060, {[CaseLower] = 0x000060,[CaseTitle] = 0x000060,[CaseUpper] = 0x000060}}, - {0x000061, {[CaseLower] = 0x000061,[CaseTitle] = 0x000041,[CaseUpper] = 0x000041}}, - {0x000062, {[CaseLower] = 0x000062,[CaseTitle] = 0x000042,[CaseUpper] = 0x000042}}, - {0x000063, {[CaseLower] = 0x000063,[CaseTitle] = 0x000043,[CaseUpper] = 0x000043}}, - {0x000064, {[CaseLower] = 0x000064,[CaseTitle] = 0x000044,[CaseUpper] = 0x000044}}, - {0x000065, {[CaseLower] = 0x000065,[CaseTitle] = 0x000045,[CaseUpper] = 0x000045}}, - {0x000066, {[CaseLower] = 0x000066,[CaseTitle] = 0x000046,[CaseUpper] = 0x000046}}, - {0x000067, {[CaseLower] = 0x000067,[CaseTitle] = 0x000047,[CaseUpper] = 0x000047}}, - {0x000068, {[CaseLower] = 0x000068,[CaseTitle] = 0x000048,[CaseUpper] = 0x000048}}, - {0x000069, {[CaseLower] = 0x000069,[CaseTitle] = 0x000049,[CaseUpper] = 0x000049}}, - {0x00006a, {[CaseLower] = 0x00006a,[CaseTitle] = 0x00004a,[CaseUpper] = 0x00004a}}, - {0x00006b, {[CaseLower] = 0x00006b,[CaseTitle] = 0x00004b,[CaseUpper] = 0x00004b}}, - {0x00006c, {[CaseLower] = 0x00006c,[CaseTitle] = 0x00004c,[CaseUpper] = 0x00004c}}, - {0x00006d, {[CaseLower] = 0x00006d,[CaseTitle] = 0x00004d,[CaseUpper] = 0x00004d}}, - {0x00006e, {[CaseLower] = 0x00006e,[CaseTitle] = 0x00004e,[CaseUpper] = 0x00004e}}, - {0x00006f, {[CaseLower] = 0x00006f,[CaseTitle] = 0x00004f,[CaseUpper] = 0x00004f}}, - {0x000070, {[CaseLower] = 0x000070,[CaseTitle] = 0x000050,[CaseUpper] = 0x000050}}, - {0x000071, {[CaseLower] = 0x000071,[CaseTitle] = 0x000051,[CaseUpper] = 0x000051}}, - {0x000072, {[CaseLower] = 0x000072,[CaseTitle] = 0x000052,[CaseUpper] = 0x000052}}, - {0x000073, {[CaseLower] = 0x000073,[CaseTitle] = 0x000053,[CaseUpper] = 0x000053}}, - {0x000074, {[CaseLower] = 0x000074,[CaseTitle] = 0x000054,[CaseUpper] = 0x000054}}, - {0x000075, {[CaseLower] = 0x000075,[CaseTitle] = 0x000055,[CaseUpper] = 0x000055}}, - {0x000076, {[CaseLower] = 0x000076,[CaseTitle] = 0x000056,[CaseUpper] = 0x000056}}, - {0x000077, {[CaseLower] = 0x000077,[CaseTitle] = 0x000057,[CaseUpper] = 0x000057}}, - {0x000078, {[CaseLower] = 0x000078,[CaseTitle] = 0x000058,[CaseUpper] = 0x000058}}, - {0x000079, {[CaseLower] = 0x000079,[CaseTitle] = 0x000059,[CaseUpper] = 0x000059}}, - {0x00007a, {[CaseLower] = 0x00007a,[CaseTitle] = 0x00005a,[CaseUpper] = 0x00005a}}, - {0x00007b, {[CaseLower] = 0x00007b,[CaseTitle] = 0x00007b,[CaseUpper] = 0x00007b}}, - {0x00007c, {[CaseLower] = 0x00007c,[CaseTitle] = 0x00007c,[CaseUpper] = 0x00007c}}, - {0x00007d, {[CaseLower] = 0x00007d,[CaseTitle] = 0x00007d,[CaseUpper] = 0x00007d}}, - {0x00007e, {[CaseLower] = 0x00007e,[CaseTitle] = 0x00007e,[CaseUpper] = 0x00007e}}, - {0x00007f, {[CaseLower] = 0x00007f,[CaseTitle] = 0x00007f,[CaseUpper] = 0x00007f}}, + {0, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}, + {0, {[CaseLower] = {0x0000df, 0x000000, 0x000000},[CaseTitle] = {0x000053, 0x000073, 0x000000},[CaseUpper] = {0x000053, 0x000053, 0x000000},[CaseFold] = {0x000073, 0x000073, 0x000000}}}, + {0, {[CaseLower] = {0x000069, 0x000307, 0x000000},[CaseTitle] = {0x000130, 0x000000, 0x000000},[CaseUpper] = {0x000130, 0x000000, 0x000000},[CaseFold] = {0x000069, 0x000307, 0x000000}}}, + {0, {[CaseLower] = {0x000149, 0x000000, 0x000000},[CaseTitle] = {0x0002bc, 0x00004e, 0x000000},[CaseUpper] = {0x0002bc, 0x00004e, 0x000000},[CaseFold] = {0x0002bc, 0x00006e, 0x000000}}}, + {0, {[CaseLower] = {0x0001f0, 0x000000, 0x000000},[CaseTitle] = {0x00004a, 0x00030c, 0x000000},[CaseUpper] = {0x00004a, 0x00030c, 0x000000},[CaseFold] = {0x00006a, 0x00030c, 0x000000}}}, + {0, {[CaseLower] = {0x000390, 0x000000, 0x000000},[CaseTitle] = {0x000399, 0x000308, 0x000301},[CaseUpper] = {0x000399, 0x000308, 0x000301},[CaseFold] = {0x0003b9, 0x000308, 0x000301}}}, + {PG_U_FINAL_SIGMA, {[CaseLower] = {0x0003c2, 0x000000, 0x000000},[CaseTitle] = {0x0003a3, 0x000000, 0x000000},[CaseUpper] = {0x0003a3, 0x000000, 0x000000},[CaseFold] = {0x0003c3, 0x000000, 0x000000}}}, + {0, {[CaseLower] = {0x0003b0, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000308, 0x000301},[CaseUpper] = {0x0003a5, 0x000308, 0x000301},[CaseFold] = {0x0003c5, 0x000308, 0x000301}}}, + {0, {[CaseLower] = {0x000587, 0x000000, 0x000000},[CaseTitle] = {0x000535, 0x000582, 0x000000},[CaseUpper] = {0x000535, 0x000552, 0x000000},[CaseFold] = {0x000565, 0x000582, 0x000000}}}, + {0, {[CaseLower] = {0x001e96, 0x000000, 0x000000},[CaseTitle] = {0x000048, 0x000331, 0x000000},[CaseUpper] = {0x000048, 0x000331, 0x000000},[CaseFold] = {0x000068, 0x000331, 0x000000}}}, + {0, {[CaseLower] = {0x001e97, 0x000000, 0x000000},[CaseTitle] = {0x000054, 0x000308, 0x000000},[CaseUpper] = {0x000054, 0x000308, 0x000000},[CaseFold] = {0x000074, 0x000308, 0x000000}}}, + {0, {[CaseLower] = {0x001e98, 0x000000, 0x000000},[CaseTitle] = {0x000057, 0x00030a, 0x000000},[CaseUpper] = {0x000057, 0x00030a, 0x000000},[CaseFold] = {0x000077, 0x00030a, 0x000000}}}, + {0, {[CaseLower] = {0x001e99, 0x000000, 0x000000},[CaseTitle] = {0x000059, 0x00030a, 0x000000},[CaseUpper] = {0x000059, 0x00030a, 0x000000},[CaseFold] = {0x000079, 0x00030a, 0x000000}}}, + {0, {[CaseLower] = {0x001e9a, 0x000000, 0x000000},[CaseTitle] = {0x000041, 0x0002be, 0x000000},[CaseUpper] = {0x000041, 0x0002be, 0x000000},[CaseFold] = {0x000061, 0x0002be, 0x000000}}}, + {0, {[CaseLower] = {0x0000df, 0x000000, 0x000000},[CaseTitle] = {0x001e9e, 0x000000, 0x000000},[CaseUpper] = {0x001e9e, 0x000000, 0x000000},[CaseFold] = {0x000073, 0x000073, 0x000000}}}, + {0, {[CaseLower] = {0x001f50, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000313, 0x000000},[CaseUpper] = {0x0003a5, 0x000313, 0x000000},[CaseFold] = {0x0003c5, 0x000313, 0x000000}}}, + {0, {[CaseLower] = {0x001f52, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000313, 0x000300},[CaseUpper] = {0x0003a5, 0x000313, 0x000300},[CaseFold] = {0x0003c5, 0x000313, 0x000300}}}, + {0, {[CaseLower] = {0x001f54, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000313, 0x000301},[CaseUpper] = {0x0003a5, 0x000313, 0x000301},[CaseFold] = {0x0003c5, 0x000313, 0x000301}}}, + {0, {[CaseLower] = {0x001f56, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000313, 0x000342},[CaseUpper] = {0x0003a5, 0x000313, 0x000342},[CaseFold] = {0x0003c5, 0x000313, 0x000342}}}, + {0, {[CaseLower] = {0x001f80, 0x000000, 0x000000},[CaseTitle] = {0x001f88, 0x000000, 0x000000},[CaseUpper] = {0x001f08, 0x000399, 0x000000},[CaseFold] = {0x001f00, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f81, 0x000000, 0x000000},[CaseTitle] = {0x001f89, 0x000000, 0x000000},[CaseUpper] = {0x001f09, 0x000399, 0x000000},[CaseFold] = {0x001f01, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f82, 0x000000, 0x000000},[CaseTitle] = {0x001f8a, 0x000000, 0x000000},[CaseUpper] = {0x001f0a, 0x000399, 0x000000},[CaseFold] = {0x001f02, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f83, 0x000000, 0x000000},[CaseTitle] = {0x001f8b, 0x000000, 0x000000},[CaseUpper] = {0x001f0b, 0x000399, 0x000000},[CaseFold] = {0x001f03, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f84, 0x000000, 0x000000},[CaseTitle] = {0x001f8c, 0x000000, 0x000000},[CaseUpper] = {0x001f0c, 0x000399, 0x000000},[CaseFold] = {0x001f04, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f85, 0x000000, 0x000000},[CaseTitle] = {0x001f8d, 0x000000, 0x000000},[CaseUpper] = {0x001f0d, 0x000399, 0x000000},[CaseFold] = {0x001f05, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f86, 0x000000, 0x000000},[CaseTitle] = {0x001f8e, 0x000000, 0x000000},[CaseUpper] = {0x001f0e, 0x000399, 0x000000},[CaseFold] = {0x001f06, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f87, 0x000000, 0x000000},[CaseTitle] = {0x001f8f, 0x000000, 0x000000},[CaseUpper] = {0x001f0f, 0x000399, 0x000000},[CaseFold] = {0x001f07, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f80, 0x000000, 0x000000},[CaseTitle] = {0x001f88, 0x000000, 0x000000},[CaseUpper] = {0x001f08, 0x000399, 0x000000},[CaseFold] = {0x001f00, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f81, 0x000000, 0x000000},[CaseTitle] = {0x001f89, 0x000000, 0x000000},[CaseUpper] = {0x001f09, 0x000399, 0x000000},[CaseFold] = {0x001f01, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f82, 0x000000, 0x000000},[CaseTitle] = {0x001f8a, 0x000000, 0x000000},[CaseUpper] = {0x001f0a, 0x000399, 0x000000},[CaseFold] = {0x001f02, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f83, 0x000000, 0x000000},[CaseTitle] = {0x001f8b, 0x000000, 0x000000},[CaseUpper] = {0x001f0b, 0x000399, 0x000000},[CaseFold] = {0x001f03, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f84, 0x000000, 0x000000},[CaseTitle] = {0x001f8c, 0x000000, 0x000000},[CaseUpper] = {0x001f0c, 0x000399, 0x000000},[CaseFold] = {0x001f04, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f85, 0x000000, 0x000000},[CaseTitle] = {0x001f8d, 0x000000, 0x000000},[CaseUpper] = {0x001f0d, 0x000399, 0x000000},[CaseFold] = {0x001f05, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f86, 0x000000, 0x000000},[CaseTitle] = {0x001f8e, 0x000000, 0x000000},[CaseUpper] = {0x001f0e, 0x000399, 0x000000},[CaseFold] = {0x001f06, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f87, 0x000000, 0x000000},[CaseTitle] = {0x001f8f, 0x000000, 0x000000},[CaseUpper] = {0x001f0f, 0x000399, 0x000000},[CaseFold] = {0x001f07, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f90, 0x000000, 0x000000},[CaseTitle] = {0x001f98, 0x000000, 0x000000},[CaseUpper] = {0x001f28, 0x000399, 0x000000},[CaseFold] = {0x001f20, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f91, 0x000000, 0x000000},[CaseTitle] = {0x001f99, 0x000000, 0x000000},[CaseUpper] = {0x001f29, 0x000399, 0x000000},[CaseFold] = {0x001f21, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f92, 0x000000, 0x000000},[CaseTitle] = {0x001f9a, 0x000000, 0x000000},[CaseUpper] = {0x001f2a, 0x000399, 0x000000},[CaseFold] = {0x001f22, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f93, 0x000000, 0x000000},[CaseTitle] = {0x001f9b, 0x000000, 0x000000},[CaseUpper] = {0x001f2b, 0x000399, 0x000000},[CaseFold] = {0x001f23, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f94, 0x000000, 0x000000},[CaseTitle] = {0x001f9c, 0x000000, 0x000000},[CaseUpper] = {0x001f2c, 0x000399, 0x000000},[CaseFold] = {0x001f24, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f95, 0x000000, 0x000000},[CaseTitle] = {0x001f9d, 0x000000, 0x000000},[CaseUpper] = {0x001f2d, 0x000399, 0x000000},[CaseFold] = {0x001f25, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f96, 0x000000, 0x000000},[CaseTitle] = {0x001f9e, 0x000000, 0x000000},[CaseUpper] = {0x001f2e, 0x000399, 0x000000},[CaseFold] = {0x001f26, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f97, 0x000000, 0x000000},[CaseTitle] = {0x001f9f, 0x000000, 0x000000},[CaseUpper] = {0x001f2f, 0x000399, 0x000000},[CaseFold] = {0x001f27, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f90, 0x000000, 0x000000},[CaseTitle] = {0x001f98, 0x000000, 0x000000},[CaseUpper] = {0x001f28, 0x000399, 0x000000},[CaseFold] = {0x001f20, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f91, 0x000000, 0x000000},[CaseTitle] = {0x001f99, 0x000000, 0x000000},[CaseUpper] = {0x001f29, 0x000399, 0x000000},[CaseFold] = {0x001f21, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f92, 0x000000, 0x000000},[CaseTitle] = {0x001f9a, 0x000000, 0x000000},[CaseUpper] = {0x001f2a, 0x000399, 0x000000},[CaseFold] = {0x001f22, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f93, 0x000000, 0x000000},[CaseTitle] = {0x001f9b, 0x000000, 0x000000},[CaseUpper] = {0x001f2b, 0x000399, 0x000000},[CaseFold] = {0x001f23, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f94, 0x000000, 0x000000},[CaseTitle] = {0x001f9c, 0x000000, 0x000000},[CaseUpper] = {0x001f2c, 0x000399, 0x000000},[CaseFold] = {0x001f24, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f95, 0x000000, 0x000000},[CaseTitle] = {0x001f9d, 0x000000, 0x000000},[CaseUpper] = {0x001f2d, 0x000399, 0x000000},[CaseFold] = {0x001f25, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f96, 0x000000, 0x000000},[CaseTitle] = {0x001f9e, 0x000000, 0x000000},[CaseUpper] = {0x001f2e, 0x000399, 0x000000},[CaseFold] = {0x001f26, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001f97, 0x000000, 0x000000},[CaseTitle] = {0x001f9f, 0x000000, 0x000000},[CaseUpper] = {0x001f2f, 0x000399, 0x000000},[CaseFold] = {0x001f27, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa0, 0x000000, 0x000000},[CaseTitle] = {0x001fa8, 0x000000, 0x000000},[CaseUpper] = {0x001f68, 0x000399, 0x000000},[CaseFold] = {0x001f60, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa1, 0x000000, 0x000000},[CaseTitle] = {0x001fa9, 0x000000, 0x000000},[CaseUpper] = {0x001f69, 0x000399, 0x000000},[CaseFold] = {0x001f61, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa2, 0x000000, 0x000000},[CaseTitle] = {0x001faa, 0x000000, 0x000000},[CaseUpper] = {0x001f6a, 0x000399, 0x000000},[CaseFold] = {0x001f62, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa3, 0x000000, 0x000000},[CaseTitle] = {0x001fab, 0x000000, 0x000000},[CaseUpper] = {0x001f6b, 0x000399, 0x000000},[CaseFold] = {0x001f63, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa4, 0x000000, 0x000000},[CaseTitle] = {0x001fac, 0x000000, 0x000000},[CaseUpper] = {0x001f6c, 0x000399, 0x000000},[CaseFold] = {0x001f64, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa5, 0x000000, 0x000000},[CaseTitle] = {0x001fad, 0x000000, 0x000000},[CaseUpper] = {0x001f6d, 0x000399, 0x000000},[CaseFold] = {0x001f65, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa6, 0x000000, 0x000000},[CaseTitle] = {0x001fae, 0x000000, 0x000000},[CaseUpper] = {0x001f6e, 0x000399, 0x000000},[CaseFold] = {0x001f66, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa7, 0x000000, 0x000000},[CaseTitle] = {0x001faf, 0x000000, 0x000000},[CaseUpper] = {0x001f6f, 0x000399, 0x000000},[CaseFold] = {0x001f67, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa0, 0x000000, 0x000000},[CaseTitle] = {0x001fa8, 0x000000, 0x000000},[CaseUpper] = {0x001f68, 0x000399, 0x000000},[CaseFold] = {0x001f60, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa1, 0x000000, 0x000000},[CaseTitle] = {0x001fa9, 0x000000, 0x000000},[CaseUpper] = {0x001f69, 0x000399, 0x000000},[CaseFold] = {0x001f61, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa2, 0x000000, 0x000000},[CaseTitle] = {0x001faa, 0x000000, 0x000000},[CaseUpper] = {0x001f6a, 0x000399, 0x000000},[CaseFold] = {0x001f62, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa3, 0x000000, 0x000000},[CaseTitle] = {0x001fab, 0x000000, 0x000000},[CaseUpper] = {0x001f6b, 0x000399, 0x000000},[CaseFold] = {0x001f63, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa4, 0x000000, 0x000000},[CaseTitle] = {0x001fac, 0x000000, 0x000000},[CaseUpper] = {0x001f6c, 0x000399, 0x000000},[CaseFold] = {0x001f64, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa5, 0x000000, 0x000000},[CaseTitle] = {0x001fad, 0x000000, 0x000000},[CaseUpper] = {0x001f6d, 0x000399, 0x000000},[CaseFold] = {0x001f65, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa6, 0x000000, 0x000000},[CaseTitle] = {0x001fae, 0x000000, 0x000000},[CaseUpper] = {0x001f6e, 0x000399, 0x000000},[CaseFold] = {0x001f66, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fa7, 0x000000, 0x000000},[CaseTitle] = {0x001faf, 0x000000, 0x000000},[CaseUpper] = {0x001f6f, 0x000399, 0x000000},[CaseFold] = {0x001f67, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fb2, 0x000000, 0x000000},[CaseTitle] = {0x001fba, 0x000345, 0x000000},[CaseUpper] = {0x001fba, 0x000399, 0x000000},[CaseFold] = {0x001f70, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fb3, 0x000000, 0x000000},[CaseTitle] = {0x001fbc, 0x000000, 0x000000},[CaseUpper] = {0x000391, 0x000399, 0x000000},[CaseFold] = {0x0003b1, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fb4, 0x000000, 0x000000},[CaseTitle] = {0x000386, 0x000345, 0x000000},[CaseUpper] = {0x000386, 0x000399, 0x000000},[CaseFold] = {0x0003ac, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fb6, 0x000000, 0x000000},[CaseTitle] = {0x000391, 0x000342, 0x000000},[CaseUpper] = {0x000391, 0x000342, 0x000000},[CaseFold] = {0x0003b1, 0x000342, 0x000000}}}, + {0, {[CaseLower] = {0x001fb7, 0x000000, 0x000000},[CaseTitle] = {0x000391, 0x000342, 0x000345},[CaseUpper] = {0x000391, 0x000342, 0x000399},[CaseFold] = {0x0003b1, 0x000342, 0x0003b9}}}, + {0, {[CaseLower] = {0x001fb3, 0x000000, 0x000000},[CaseTitle] = {0x001fbc, 0x000000, 0x000000},[CaseUpper] = {0x000391, 0x000399, 0x000000},[CaseFold] = {0x0003b1, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fc2, 0x000000, 0x000000},[CaseTitle] = {0x001fca, 0x000345, 0x000000},[CaseUpper] = {0x001fca, 0x000399, 0x000000},[CaseFold] = {0x001f74, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fc3, 0x000000, 0x000000},[CaseTitle] = {0x001fcc, 0x000000, 0x000000},[CaseUpper] = {0x000397, 0x000399, 0x000000},[CaseFold] = {0x0003b7, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fc4, 0x000000, 0x000000},[CaseTitle] = {0x000389, 0x000345, 0x000000},[CaseUpper] = {0x000389, 0x000399, 0x000000},[CaseFold] = {0x0003ae, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fc6, 0x000000, 0x000000},[CaseTitle] = {0x000397, 0x000342, 0x000000},[CaseUpper] = {0x000397, 0x000342, 0x000000},[CaseFold] = {0x0003b7, 0x000342, 0x000000}}}, + {0, {[CaseLower] = {0x001fc7, 0x000000, 0x000000},[CaseTitle] = {0x000397, 0x000342, 0x000345},[CaseUpper] = {0x000397, 0x000342, 0x000399},[CaseFold] = {0x0003b7, 0x000342, 0x0003b9}}}, + {0, {[CaseLower] = {0x001fc3, 0x000000, 0x000000},[CaseTitle] = {0x001fcc, 0x000000, 0x000000},[CaseUpper] = {0x000397, 0x000399, 0x000000},[CaseFold] = {0x0003b7, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001fd2, 0x000000, 0x000000},[CaseTitle] = {0x000399, 0x000308, 0x000300},[CaseUpper] = {0x000399, 0x000308, 0x000300},[CaseFold] = {0x0003b9, 0x000308, 0x000300}}}, + {0, {[CaseLower] = {0x001fd3, 0x000000, 0x000000},[CaseTitle] = {0x000399, 0x000308, 0x000301},[CaseUpper] = {0x000399, 0x000308, 0x000301},[CaseFold] = {0x0003b9, 0x000308, 0x000301}}}, + {0, {[CaseLower] = {0x001fd6, 0x000000, 0x000000},[CaseTitle] = {0x000399, 0x000342, 0x000000},[CaseUpper] = {0x000399, 0x000342, 0x000000},[CaseFold] = {0x0003b9, 0x000342, 0x000000}}}, + {0, {[CaseLower] = {0x001fd7, 0x000000, 0x000000},[CaseTitle] = {0x000399, 0x000308, 0x000342},[CaseUpper] = {0x000399, 0x000308, 0x000342},[CaseFold] = {0x0003b9, 0x000308, 0x000342}}}, + {0, {[CaseLower] = {0x001fe2, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000308, 0x000300},[CaseUpper] = {0x0003a5, 0x000308, 0x000300},[CaseFold] = {0x0003c5, 0x000308, 0x000300}}}, + {0, {[CaseLower] = {0x001fe3, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000308, 0x000301},[CaseUpper] = {0x0003a5, 0x000308, 0x000301},[CaseFold] = {0x0003c5, 0x000308, 0x000301}}}, + {0, {[CaseLower] = {0x001fe4, 0x000000, 0x000000},[CaseTitle] = {0x0003a1, 0x000313, 0x000000},[CaseUpper] = {0x0003a1, 0x000313, 0x000000},[CaseFold] = {0x0003c1, 0x000313, 0x000000}}}, + {0, {[CaseLower] = {0x001fe6, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000342, 0x000000},[CaseUpper] = {0x0003a5, 0x000342, 0x000000},[CaseFold] = {0x0003c5, 0x000342, 0x000000}}}, + {0, {[CaseLower] = {0x001fe7, 0x000000, 0x000000},[CaseTitle] = {0x0003a5, 0x000308, 0x000342},[CaseUpper] = {0x0003a5, 0x000308, 0x000342},[CaseFold] = {0x0003c5, 0x000308, 0x000342}}}, + {0, {[CaseLower] = {0x001ff2, 0x000000, 0x000000},[CaseTitle] = {0x001ffa, 0x000345, 0x000000},[CaseUpper] = {0x001ffa, 0x000399, 0x000000},[CaseFold] = {0x001f7c, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001ff3, 0x000000, 0x000000},[CaseTitle] = {0x001ffc, 0x000000, 0x000000},[CaseUpper] = {0x0003a9, 0x000399, 0x000000},[CaseFold] = {0x0003c9, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001ff4, 0x000000, 0x000000},[CaseTitle] = {0x00038f, 0x000345, 0x000000},[CaseUpper] = {0x00038f, 0x000399, 0x000000},[CaseFold] = {0x0003ce, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x001ff6, 0x000000, 0x000000},[CaseTitle] = {0x0003a9, 0x000342, 0x000000},[CaseUpper] = {0x0003a9, 0x000342, 0x000000},[CaseFold] = {0x0003c9, 0x000342, 0x000000}}}, + {0, {[CaseLower] = {0x001ff7, 0x000000, 0x000000},[CaseTitle] = {0x0003a9, 0x000342, 0x000345},[CaseUpper] = {0x0003a9, 0x000342, 0x000399},[CaseFold] = {0x0003c9, 0x000342, 0x0003b9}}}, + {0, {[CaseLower] = {0x001ff3, 0x000000, 0x000000},[CaseTitle] = {0x001ffc, 0x000000, 0x000000},[CaseUpper] = {0x0003a9, 0x000399, 0x000000},[CaseFold] = {0x0003c9, 0x0003b9, 0x000000}}}, + {0, {[CaseLower] = {0x00fb00, 0x000000, 0x000000},[CaseTitle] = {0x000046, 0x000066, 0x000000},[CaseUpper] = {0x000046, 0x000046, 0x000000},[CaseFold] = {0x000066, 0x000066, 0x000000}}}, + {0, {[CaseLower] = {0x00fb01, 0x000000, 0x000000},[CaseTitle] = {0x000046, 0x000069, 0x000000},[CaseUpper] = {0x000046, 0x000049, 0x000000},[CaseFold] = {0x000066, 0x000069, 0x000000}}}, + {0, {[CaseLower] = {0x00fb02, 0x000000, 0x000000},[CaseTitle] = {0x000046, 0x00006c, 0x000000},[CaseUpper] = {0x000046, 0x00004c, 0x000000},[CaseFold] = {0x000066, 0x00006c, 0x000000}}}, + {0, {[CaseLower] = {0x00fb03, 0x000000, 0x000000},[CaseTitle] = {0x000046, 0x000066, 0x000069},[CaseUpper] = {0x000046, 0x000046, 0x000049},[CaseFold] = {0x000066, 0x000066, 0x000069}}}, + {0, {[CaseLower] = {0x00fb04, 0x000000, 0x000000},[CaseTitle] = {0x000046, 0x000066, 0x00006c},[CaseUpper] = {0x000046, 0x000046, 0x00004c},[CaseFold] = {0x000066, 0x000066, 0x00006c}}}, + {0, {[CaseLower] = {0x00fb05, 0x000000, 0x000000},[CaseTitle] = {0x000053, 0x000074, 0x000000},[CaseUpper] = {0x000053, 0x000054, 0x000000},[CaseFold] = {0x000073, 0x000074, 0x000000}}}, + {0, {[CaseLower] = {0x00fb06, 0x000000, 0x000000},[CaseTitle] = {0x000053, 0x000074, 0x000000},[CaseUpper] = {0x000053, 0x000054, 0x000000},[CaseFold] = {0x000073, 0x000074, 0x000000}}}, + {0, {[CaseLower] = {0x00fb13, 0x000000, 0x000000},[CaseTitle] = {0x000544, 0x000576, 0x000000},[CaseUpper] = {0x000544, 0x000546, 0x000000},[CaseFold] = {0x000574, 0x000576, 0x000000}}}, + {0, {[CaseLower] = {0x00fb14, 0x000000, 0x000000},[CaseTitle] = {0x000544, 0x000565, 0x000000},[CaseUpper] = {0x000544, 0x000535, 0x000000},[CaseFold] = {0x000574, 0x000565, 0x000000}}}, + {0, {[CaseLower] = {0x00fb15, 0x000000, 0x000000},[CaseTitle] = {0x000544, 0x00056b, 0x000000},[CaseUpper] = {0x000544, 0x00053b, 0x000000},[CaseFold] = {0x000574, 0x00056b, 0x000000}}}, + {0, {[CaseLower] = {0x00fb16, 0x000000, 0x000000},[CaseTitle] = {0x00054e, 0x000576, 0x000000},[CaseUpper] = {0x00054e, 0x000546, 0x000000},[CaseFold] = {0x00057e, 0x000576, 0x000000}}}, + {0, {[CaseLower] = {0x00fb17, 0x000000, 0x000000},[CaseTitle] = {0x000544, 0x00056d, 0x000000},[CaseUpper] = {0x000544, 0x00053d, 0x000000},[CaseFold] = {0x000574, 0x00056d, 0x000000}}}, +}; + +/* + * The entry case_map_lower[case_index(codepoint)] is the mapping for the + * given codepoint. + */ +static const pg_wchar case_map_lower[1704] = +{ + 0x000000, /* reserved */ + 0x000000, /* U+000000 */ + 0x000001, /* U+000001 */ + 0x000002, /* U+000002 */ + 0x000003, /* U+000003 */ + 0x000004, /* U+000004 */ + 0x000005, /* U+000005 */ + 0x000006, /* U+000006 */ + 0x000007, /* U+000007 */ + 0x000008, /* U+000008 */ + 0x000009, /* U+000009 */ + 0x00000a, /* U+00000a */ + 0x00000b, /* U+00000b */ + 0x00000c, /* U+00000c */ + 0x00000d, /* U+00000d */ + 0x00000e, /* U+00000e */ + 0x00000f, /* U+00000f */ + 0x000010, /* U+000010 */ + 0x000011, /* U+000011 */ + 0x000012, /* U+000012 */ + 0x000013, /* U+000013 */ + 0x000014, /* U+000014 */ + 0x000015, /* U+000015 */ + 0x000016, /* U+000016 */ + 0x000017, /* U+000017 */ + 0x000018, /* U+000018 */ + 0x000019, /* U+000019 */ + 0x00001a, /* U+00001a */ + 0x00001b, /* U+00001b */ + 0x00001c, /* U+00001c */ + 0x00001d, /* U+00001d */ + 0x00001e, /* U+00001e */ + 0x00001f, /* U+00001f */ + 0x000020, /* U+000020 */ + 0x000021, /* U+000021 */ + 0x000022, /* U+000022 */ + 0x000023, /* U+000023 */ + 0x000024, /* U+000024 */ + 0x000025, /* U+000025 */ + 0x000026, /* U+000026 */ + 0x000027, /* U+000027 */ + 0x000028, /* U+000028 */ + 0x000029, /* U+000029 */ + 0x00002a, /* U+00002a */ + 0x00002b, /* U+00002b */ + 0x00002c, /* U+00002c */ + 0x00002d, /* U+00002d */ + 0x00002e, /* U+00002e */ + 0x00002f, /* U+00002f */ + 0x000030, /* U+000030 */ + 0x000031, /* U+000031 */ + 0x000032, /* U+000032 */ + 0x000033, /* U+000033 */ + 0x000034, /* U+000034 */ + 0x000035, /* U+000035 */ + 0x000036, /* U+000036 */ + 0x000037, /* U+000037 */ + 0x000038, /* U+000038 */ + 0x000039, /* U+000039 */ + 0x00003a, /* U+00003a */ + 0x00003b, /* U+00003b */ + 0x00003c, /* U+00003c */ + 0x00003d, /* U+00003d */ + 0x00003e, /* U+00003e */ + 0x00003f, /* U+00003f */ + 0x000040, /* U+000040 */ + 0x000061, /* U+000041 */ + 0x000062, /* U+000042 */ + 0x000063, /* U+000043 */ + 0x000064, /* U+000044 */ + 0x000065, /* U+000045 */ + 0x000066, /* U+000046 */ + 0x000067, /* U+000047 */ + 0x000068, /* U+000048 */ + 0x000069, /* U+000049 */ + 0x00006a, /* U+00004a */ + 0x00006b, /* U+00004b */ + 0x00006c, /* U+00004c */ + 0x00006d, /* U+00004d */ + 0x00006e, /* U+00004e */ + 0x00006f, /* U+00004f */ + 0x000070, /* U+000050 */ + 0x000071, /* U+000051 */ + 0x000072, /* U+000052 */ + 0x000073, /* U+000053 */ + 0x000074, /* U+000054 */ + 0x000075, /* U+000055 */ + 0x000076, /* U+000056 */ + 0x000077, /* U+000057 */ + 0x000078, /* U+000058 */ + 0x000079, /* U+000059 */ + 0x00007a, /* U+00005a */ + 0x00005b, /* U+00005b */ + 0x00005c, /* U+00005c */ + 0x00005d, /* U+00005d */ + 0x00005e, /* U+00005e */ + 0x00005f, /* U+00005f */ + 0x000060, /* U+000060 */ + 0x000061, /* U+000061 */ + 0x000062, /* U+000062 */ + 0x000063, /* U+000063 */ + 0x000064, /* U+000064 */ + 0x000065, /* U+000065 */ + 0x000066, /* U+000066 */ + 0x000067, /* U+000067 */ + 0x000068, /* U+000068 */ + 0x000069, /* U+000069 */ + 0x00006a, /* U+00006a */ + 0x00006b, /* U+00006b */ + 0x00006c, /* U+00006c */ + 0x00006d, /* U+00006d */ + 0x00006e, /* U+00006e */ + 0x00006f, /* U+00006f */ + 0x000070, /* U+000070 */ + 0x000071, /* U+000071 */ + 0x000072, /* U+000072 */ + 0x000073, /* U+000073 */ + 0x000074, /* U+000074 */ + 0x000075, /* U+000075 */ + 0x000076, /* U+000076 */ + 0x000077, /* U+000077 */ + 0x000078, /* U+000078 */ + 0x000079, /* U+000079 */ + 0x00007a, /* U+00007a */ + 0x00007b, /* U+00007b */ + 0x00007c, /* U+00007c */ + 0x00007d, /* U+00007d */ + 0x00007e, /* U+00007e */ + 0x00007f, /* U+00007f */ + 0x0000b5, /* U+0000b5 */ + 0x0000e0, /* U+0000c0 */ + 0x0000e1, /* U+0000c1 */ + 0x0000e2, /* U+0000c2 */ + 0x0000e3, /* U+0000c3 */ + 0x0000e4, /* U+0000c4 */ + 0x0000e5, /* U+0000c5 */ + 0x0000e6, /* U+0000c6 */ + 0x0000e7, /* U+0000c7 */ + 0x0000e8, /* U+0000c8 */ + 0x0000e9, /* U+0000c9 */ + 0x0000ea, /* U+0000ca */ + 0x0000eb, /* U+0000cb */ + 0x0000ec, /* U+0000cc */ + 0x0000ed, /* U+0000cd */ + 0x0000ee, /* U+0000ce */ + 0x0000ef, /* U+0000cf */ + 0x0000f0, /* U+0000d0 */ + 0x0000f1, /* U+0000d1 */ + 0x0000f2, /* U+0000d2 */ + 0x0000f3, /* U+0000d3 */ + 0x0000f4, /* U+0000d4 */ + 0x0000f5, /* U+0000d5 */ + 0x0000f6, /* U+0000d6 */ + 0x0000f8, /* U+0000d8 */ + 0x0000f9, /* U+0000d9 */ + 0x0000fa, /* U+0000da */ + 0x0000fb, /* U+0000db */ + 0x0000fc, /* U+0000dc */ + 0x0000fd, /* U+0000dd */ + 0x0000fe, /* U+0000de */ + 0x0000df, /* U+0000df */ + 0x0000ff, /* U+0000ff */ + 0x000101, /* U+000100 */ + 0x000103, /* U+000102 */ + 0x000105, /* U+000104 */ + 0x000107, /* U+000106 */ + 0x000109, /* U+000108 */ + 0x00010b, /* U+00010a */ + 0x00010d, /* U+00010c */ + 0x00010f, /* U+00010e */ + 0x000111, /* U+000110 */ + 0x000113, /* U+000112 */ + 0x000115, /* U+000114 */ + 0x000117, /* U+000116 */ + 0x000119, /* U+000118 */ + 0x00011b, /* U+00011a */ + 0x00011d, /* U+00011c */ + 0x00011f, /* U+00011e */ + 0x000121, /* U+000120 */ + 0x000123, /* U+000122 */ + 0x000125, /* U+000124 */ + 0x000127, /* U+000126 */ + 0x000129, /* U+000128 */ + 0x00012b, /* U+00012a */ + 0x00012d, /* U+00012c */ + 0x00012f, /* U+00012e */ + 0x000069, /* U+000130 */ + 0x000131, /* U+000131 */ + 0x000133, /* U+000132 */ + 0x000135, /* U+000134 */ + 0x000137, /* U+000136 */ + 0x00013a, /* U+000139 */ + 0x00013c, /* U+00013b */ + 0x00013e, /* U+00013d */ + 0x000140, /* U+00013f */ + 0x000142, /* U+000141 */ + 0x000144, /* U+000143 */ + 0x000146, /* U+000145 */ + 0x000148, /* U+000147 */ + 0x000149, /* U+000149 */ + 0x00014b, /* U+00014a */ + 0x00014d, /* U+00014c */ + 0x00014f, /* U+00014e */ + 0x000151, /* U+000150 */ + 0x000153, /* U+000152 */ + 0x000155, /* U+000154 */ + 0x000157, /* U+000156 */ + 0x000159, /* U+000158 */ + 0x00015b, /* U+00015a */ + 0x00015d, /* U+00015c */ + 0x00015f, /* U+00015e */ + 0x000161, /* U+000160 */ + 0x000163, /* U+000162 */ + 0x000165, /* U+000164 */ + 0x000167, /* U+000166 */ + 0x000169, /* U+000168 */ + 0x00016b, /* U+00016a */ + 0x00016d, /* U+00016c */ + 0x00016f, /* U+00016e */ + 0x000171, /* U+000170 */ + 0x000173, /* U+000172 */ + 0x000175, /* U+000174 */ + 0x000177, /* U+000176 */ + 0x00017a, /* U+000179 */ + 0x00017c, /* U+00017b */ + 0x00017e, /* U+00017d */ + 0x00017f, /* U+00017f */ + 0x000180, /* U+000180 */ + 0x000253, /* U+000181 */ + 0x000183, /* U+000182 */ + 0x000185, /* U+000184 */ + 0x000254, /* U+000186 */ + 0x000188, /* U+000187 */ + 0x000256, /* U+000189 */ + 0x000257, /* U+00018a */ + 0x00018c, /* U+00018b */ + 0x0001dd, /* U+00018e */ + 0x000259, /* U+00018f */ + 0x00025b, /* U+000190 */ + 0x000192, /* U+000191 */ + 0x000260, /* U+000193 */ + 0x000263, /* U+000194 */ + 0x000195, /* U+000195 */ + 0x000269, /* U+000196 */ + 0x000268, /* U+000197 */ + 0x000199, /* U+000198 */ + 0x00019a, /* U+00019a */ + 0x00019b, /* U+00019b */ + 0x00026f, /* U+00019c */ + 0x000272, /* U+00019d */ + 0x00019e, /* U+00019e */ + 0x000275, /* U+00019f */ + 0x0001a1, /* U+0001a0 */ + 0x0001a3, /* U+0001a2 */ + 0x0001a5, /* U+0001a4 */ + 0x000280, /* U+0001a6 */ + 0x0001a8, /* U+0001a7 */ + 0x000283, /* U+0001a9 */ + 0x0001ad, /* U+0001ac */ + 0x000288, /* U+0001ae */ + 0x0001b0, /* U+0001af */ + 0x00028a, /* U+0001b1 */ + 0x00028b, /* U+0001b2 */ + 0x0001b4, /* U+0001b3 */ + 0x0001b6, /* U+0001b5 */ + 0x000292, /* U+0001b7 */ + 0x0001b9, /* U+0001b8 */ + 0x0001bd, /* U+0001bc */ + 0x0001bf, /* U+0001bf */ + 0x0001c6, /* U+0001c4 */ + 0x0001c9, /* U+0001c7 */ + 0x0001cc, /* U+0001ca */ + 0x0001ce, /* U+0001cd */ + 0x0001d0, /* U+0001cf */ + 0x0001d2, /* U+0001d1 */ + 0x0001d4, /* U+0001d3 */ + 0x0001d6, /* U+0001d5 */ + 0x0001d8, /* U+0001d7 */ + 0x0001da, /* U+0001d9 */ + 0x0001dc, /* U+0001db */ + 0x0001df, /* U+0001de */ + 0x0001e1, /* U+0001e0 */ + 0x0001e3, /* U+0001e2 */ + 0x0001e5, /* U+0001e4 */ + 0x0001e7, /* U+0001e6 */ + 0x0001e9, /* U+0001e8 */ + 0x0001eb, /* U+0001ea */ + 0x0001ed, /* U+0001ec */ + 0x0001ef, /* U+0001ee */ + 0x0001f0, /* U+0001f0 */ + 0x0001f3, /* U+0001f1 */ + 0x0001f5, /* U+0001f4 */ + 0x0001f9, /* U+0001f8 */ + 0x0001fb, /* U+0001fa */ + 0x0001fd, /* U+0001fc */ + 0x0001ff, /* U+0001fe */ + 0x000201, /* U+000200 */ + 0x000203, /* U+000202 */ + 0x000205, /* U+000204 */ + 0x000207, /* U+000206 */ + 0x000209, /* U+000208 */ + 0x00020b, /* U+00020a */ + 0x00020d, /* U+00020c */ + 0x00020f, /* U+00020e */ + 0x000211, /* U+000210 */ + 0x000213, /* U+000212 */ + 0x000215, /* U+000214 */ + 0x000217, /* U+000216 */ + 0x000219, /* U+000218 */ + 0x00021b, /* U+00021a */ + 0x00021d, /* U+00021c */ + 0x00021f, /* U+00021e */ + 0x000223, /* U+000222 */ + 0x000225, /* U+000224 */ + 0x000227, /* U+000226 */ + 0x000229, /* U+000228 */ + 0x00022b, /* U+00022a */ + 0x00022d, /* U+00022c */ + 0x00022f, /* U+00022e */ + 0x000231, /* U+000230 */ + 0x000233, /* U+000232 */ + 0x002c65, /* U+00023a */ + 0x00023c, /* U+00023b */ + 0x002c66, /* U+00023e */ + 0x00023f, /* U+00023f */ + 0x000240, /* U+000240 */ + 0x000242, /* U+000241 */ + 0x000289, /* U+000244 */ + 0x00028c, /* U+000245 */ + 0x000247, /* U+000246 */ + 0x000249, /* U+000248 */ + 0x00024b, /* U+00024a */ + 0x00024d, /* U+00024c */ + 0x00024f, /* U+00024e */ + 0x000250, /* U+000250 */ + 0x000251, /* U+000251 */ + 0x000252, /* U+000252 */ + 0x00025c, /* U+00025c */ + 0x000261, /* U+000261 */ + 0x000264, /* U+000264 */ + 0x000265, /* U+000265 */ + 0x000266, /* U+000266 */ + 0x00026a, /* U+00026a */ + 0x00026b, /* U+00026b */ + 0x00026c, /* U+00026c */ + 0x000271, /* U+000271 */ + 0x00027d, /* U+00027d */ + 0x000282, /* U+000282 */ + 0x000287, /* U+000287 */ + 0x00029d, /* U+00029d */ + 0x00029e, /* U+00029e */ + 0x000345, /* U+000345 */ + 0x000371, /* U+000370 */ + 0x000373, /* U+000372 */ + 0x000377, /* U+000376 */ + 0x00037b, /* U+00037b */ + 0x00037c, /* U+00037c */ + 0x00037d, /* U+00037d */ + 0x0003f3, /* U+00037f */ + 0x0003ac, /* U+000386 */ + 0x0003ad, /* U+000388 */ + 0x0003ae, /* U+000389 */ + 0x0003af, /* U+00038a */ + 0x0003cc, /* U+00038c */ + 0x0003cd, /* U+00038e */ + 0x0003ce, /* U+00038f */ + 0x000390, /* U+000390 */ + 0x0003b1, /* U+000391 */ + 0x0003b2, /* U+000392 */ + 0x0003b3, /* U+000393 */ + 0x0003b4, /* U+000394 */ + 0x0003b5, /* U+000395 */ + 0x0003b6, /* U+000396 */ + 0x0003b7, /* U+000397 */ + 0x0003b8, /* U+000398 */ + 0x0003b9, /* U+000399 */ + 0x0003ba, /* U+00039a */ + 0x0003bb, /* U+00039b */ + 0x0003bc, /* U+00039c */ + 0x0003bd, /* U+00039d */ + 0x0003be, /* U+00039e */ + 0x0003bf, /* U+00039f */ + 0x0003c0, /* U+0003a0 */ + 0x0003c1, /* U+0003a1 */ + 0x0003c3, /* U+0003a3 */ + 0x0003c4, /* U+0003a4 */ + 0x0003c5, /* U+0003a5 */ + 0x0003c6, /* U+0003a6 */ + 0x0003c7, /* U+0003a7 */ + 0x0003c8, /* U+0003a8 */ + 0x0003c9, /* U+0003a9 */ + 0x0003ca, /* U+0003aa */ + 0x0003cb, /* U+0003ab */ + 0x0003b0, /* U+0003b0 */ + 0x0003c2, /* U+0003c2 */ + 0x0003c3, /* U+0003c3 */ + 0x0003d7, /* U+0003cf */ + 0x0003d0, /* U+0003d0 */ + 0x0003d1, /* U+0003d1 */ + 0x0003d5, /* U+0003d5 */ + 0x0003d6, /* U+0003d6 */ + 0x0003d9, /* U+0003d8 */ + 0x0003db, /* U+0003da */ + 0x0003dd, /* U+0003dc */ + 0x0003df, /* U+0003de */ + 0x0003e1, /* U+0003e0 */ + 0x0003e3, /* U+0003e2 */ + 0x0003e5, /* U+0003e4 */ + 0x0003e7, /* U+0003e6 */ + 0x0003e9, /* U+0003e8 */ + 0x0003eb, /* U+0003ea */ + 0x0003ed, /* U+0003ec */ + 0x0003ef, /* U+0003ee */ + 0x0003f0, /* U+0003f0 */ + 0x0003f1, /* U+0003f1 */ + 0x0003f2, /* U+0003f2 */ + 0x0003b8, /* U+0003f4 */ + 0x0003f5, /* U+0003f5 */ + 0x0003f8, /* U+0003f7 */ + 0x0003fb, /* U+0003fa */ + 0x000450, /* U+000400 */ + 0x000451, /* U+000401 */ + 0x000452, /* U+000402 */ + 0x000453, /* U+000403 */ + 0x000454, /* U+000404 */ + 0x000455, /* U+000405 */ + 0x000456, /* U+000406 */ + 0x000457, /* U+000407 */ + 0x000458, /* U+000408 */ + 0x000459, /* U+000409 */ + 0x00045a, /* U+00040a */ + 0x00045b, /* U+00040b */ + 0x00045c, /* U+00040c */ + 0x00045d, /* U+00040d */ + 0x00045e, /* U+00040e */ + 0x00045f, /* U+00040f */ + 0x000430, /* U+000410 */ + 0x000431, /* U+000411 */ + 0x000432, /* U+000412 */ + 0x000433, /* U+000413 */ + 0x000434, /* U+000414 */ + 0x000435, /* U+000415 */ + 0x000436, /* U+000416 */ + 0x000437, /* U+000417 */ + 0x000438, /* U+000418 */ + 0x000439, /* U+000419 */ + 0x00043a, /* U+00041a */ + 0x00043b, /* U+00041b */ + 0x00043c, /* U+00041c */ + 0x00043d, /* U+00041d */ + 0x00043e, /* U+00041e */ + 0x00043f, /* U+00041f */ + 0x000440, /* U+000420 */ + 0x000441, /* U+000421 */ + 0x000442, /* U+000422 */ + 0x000443, /* U+000423 */ + 0x000444, /* U+000424 */ + 0x000445, /* U+000425 */ + 0x000446, /* U+000426 */ + 0x000447, /* U+000427 */ + 0x000448, /* U+000428 */ + 0x000449, /* U+000429 */ + 0x00044a, /* U+00042a */ + 0x00044b, /* U+00042b */ + 0x00044c, /* U+00042c */ + 0x00044d, /* U+00042d */ + 0x00044e, /* U+00042e */ + 0x00044f, /* U+00042f */ + 0x000461, /* U+000460 */ + 0x000463, /* U+000462 */ + 0x000465, /* U+000464 */ + 0x000467, /* U+000466 */ + 0x000469, /* U+000468 */ + 0x00046b, /* U+00046a */ + 0x00046d, /* U+00046c */ + 0x00046f, /* U+00046e */ + 0x000471, /* U+000470 */ + 0x000473, /* U+000472 */ + 0x000475, /* U+000474 */ + 0x000477, /* U+000476 */ + 0x000479, /* U+000478 */ + 0x00047b, /* U+00047a */ + 0x00047d, /* U+00047c */ + 0x00047f, /* U+00047e */ + 0x000481, /* U+000480 */ + 0x00048b, /* U+00048a */ + 0x00048d, /* U+00048c */ + 0x00048f, /* U+00048e */ + 0x000491, /* U+000490 */ + 0x000493, /* U+000492 */ + 0x000495, /* U+000494 */ + 0x000497, /* U+000496 */ + 0x000499, /* U+000498 */ + 0x00049b, /* U+00049a */ + 0x00049d, /* U+00049c */ + 0x00049f, /* U+00049e */ + 0x0004a1, /* U+0004a0 */ + 0x0004a3, /* U+0004a2 */ + 0x0004a5, /* U+0004a4 */ + 0x0004a7, /* U+0004a6 */ + 0x0004a9, /* U+0004a8 */ + 0x0004ab, /* U+0004aa */ + 0x0004ad, /* U+0004ac */ + 0x0004af, /* U+0004ae */ + 0x0004b1, /* U+0004b0 */ + 0x0004b3, /* U+0004b2 */ + 0x0004b5, /* U+0004b4 */ + 0x0004b7, /* U+0004b6 */ + 0x0004b9, /* U+0004b8 */ + 0x0004bb, /* U+0004ba */ + 0x0004bd, /* U+0004bc */ + 0x0004bf, /* U+0004be */ + 0x0004cf, /* U+0004c0 */ + 0x0004c2, /* U+0004c1 */ + 0x0004c4, /* U+0004c3 */ + 0x0004c6, /* U+0004c5 */ + 0x0004c8, /* U+0004c7 */ + 0x0004ca, /* U+0004c9 */ + 0x0004cc, /* U+0004cb */ + 0x0004ce, /* U+0004cd */ + 0x0004d1, /* U+0004d0 */ + 0x0004d3, /* U+0004d2 */ + 0x0004d5, /* U+0004d4 */ + 0x0004d7, /* U+0004d6 */ + 0x0004d9, /* U+0004d8 */ + 0x0004db, /* U+0004da */ + 0x0004dd, /* U+0004dc */ + 0x0004df, /* U+0004de */ + 0x0004e1, /* U+0004e0 */ + 0x0004e3, /* U+0004e2 */ + 0x0004e5, /* U+0004e4 */ + 0x0004e7, /* U+0004e6 */ + 0x0004e9, /* U+0004e8 */ + 0x0004eb, /* U+0004ea */ + 0x0004ed, /* U+0004ec */ + 0x0004ef, /* U+0004ee */ + 0x0004f1, /* U+0004f0 */ + 0x0004f3, /* U+0004f2 */ + 0x0004f5, /* U+0004f4 */ + 0x0004f7, /* U+0004f6 */ + 0x0004f9, /* U+0004f8 */ + 0x0004fb, /* U+0004fa */ + 0x0004fd, /* U+0004fc */ + 0x0004ff, /* U+0004fe */ + 0x000501, /* U+000500 */ + 0x000503, /* U+000502 */ + 0x000505, /* U+000504 */ + 0x000507, /* U+000506 */ + 0x000509, /* U+000508 */ + 0x00050b, /* U+00050a */ + 0x00050d, /* U+00050c */ + 0x00050f, /* U+00050e */ + 0x000511, /* U+000510 */ + 0x000513, /* U+000512 */ + 0x000515, /* U+000514 */ + 0x000517, /* U+000516 */ + 0x000519, /* U+000518 */ + 0x00051b, /* U+00051a */ + 0x00051d, /* U+00051c */ + 0x00051f, /* U+00051e */ + 0x000521, /* U+000520 */ + 0x000523, /* U+000522 */ + 0x000525, /* U+000524 */ + 0x000527, /* U+000526 */ + 0x000529, /* U+000528 */ + 0x00052b, /* U+00052a */ + 0x00052d, /* U+00052c */ + 0x00052f, /* U+00052e */ + 0x000561, /* U+000531 */ + 0x000562, /* U+000532 */ + 0x000563, /* U+000533 */ + 0x000564, /* U+000534 */ + 0x000565, /* U+000535 */ + 0x000566, /* U+000536 */ + 0x000567, /* U+000537 */ + 0x000568, /* U+000538 */ + 0x000569, /* U+000539 */ + 0x00056a, /* U+00053a */ + 0x00056b, /* U+00053b */ + 0x00056c, /* U+00053c */ + 0x00056d, /* U+00053d */ + 0x00056e, /* U+00053e */ + 0x00056f, /* U+00053f */ + 0x000570, /* U+000540 */ + 0x000571, /* U+000541 */ + 0x000572, /* U+000542 */ + 0x000573, /* U+000543 */ + 0x000574, /* U+000544 */ + 0x000575, /* U+000545 */ + 0x000576, /* U+000546 */ + 0x000577, /* U+000547 */ + 0x000578, /* U+000548 */ + 0x000579, /* U+000549 */ + 0x00057a, /* U+00054a */ + 0x00057b, /* U+00054b */ + 0x00057c, /* U+00054c */ + 0x00057d, /* U+00054d */ + 0x00057e, /* U+00054e */ + 0x00057f, /* U+00054f */ + 0x000580, /* U+000550 */ + 0x000581, /* U+000551 */ + 0x000582, /* U+000552 */ + 0x000583, /* U+000553 */ + 0x000584, /* U+000554 */ + 0x000585, /* U+000555 */ + 0x000586, /* U+000556 */ + 0x000587, /* U+000587 */ + 0x002d00, /* U+0010a0 */ + 0x002d01, /* U+0010a1 */ + 0x002d02, /* U+0010a2 */ + 0x002d03, /* U+0010a3 */ + 0x002d04, /* U+0010a4 */ + 0x002d05, /* U+0010a5 */ + 0x002d06, /* U+0010a6 */ + 0x002d07, /* U+0010a7 */ + 0x002d08, /* U+0010a8 */ + 0x002d09, /* U+0010a9 */ + 0x002d0a, /* U+0010aa */ + 0x002d0b, /* U+0010ab */ + 0x002d0c, /* U+0010ac */ + 0x002d0d, /* U+0010ad */ + 0x002d0e, /* U+0010ae */ + 0x002d0f, /* U+0010af */ + 0x002d10, /* U+0010b0 */ + 0x002d11, /* U+0010b1 */ + 0x002d12, /* U+0010b2 */ + 0x002d13, /* U+0010b3 */ + 0x002d14, /* U+0010b4 */ + 0x002d15, /* U+0010b5 */ + 0x002d16, /* U+0010b6 */ + 0x002d17, /* U+0010b7 */ + 0x002d18, /* U+0010b8 */ + 0x002d19, /* U+0010b9 */ + 0x002d1a, /* U+0010ba */ + 0x002d1b, /* U+0010bb */ + 0x002d1c, /* U+0010bc */ + 0x002d1d, /* U+0010bd */ + 0x002d1e, /* U+0010be */ + 0x002d1f, /* U+0010bf */ + 0x002d20, /* U+0010c0 */ + 0x002d21, /* U+0010c1 */ + 0x002d22, /* U+0010c2 */ + 0x002d23, /* U+0010c3 */ + 0x002d24, /* U+0010c4 */ + 0x002d25, /* U+0010c5 */ + 0x002d27, /* U+0010c7 */ + 0x002d2d, /* U+0010cd */ + 0x0010d0, /* U+0010d0 */ + 0x0010d1, /* U+0010d1 */ + 0x0010d2, /* U+0010d2 */ + 0x0010d3, /* U+0010d3 */ + 0x0010d4, /* U+0010d4 */ + 0x0010d5, /* U+0010d5 */ + 0x0010d6, /* U+0010d6 */ + 0x0010d7, /* U+0010d7 */ + 0x0010d8, /* U+0010d8 */ + 0x0010d9, /* U+0010d9 */ + 0x0010da, /* U+0010da */ + 0x0010db, /* U+0010db */ + 0x0010dc, /* U+0010dc */ + 0x0010dd, /* U+0010dd */ + 0x0010de, /* U+0010de */ + 0x0010df, /* U+0010df */ + 0x0010e0, /* U+0010e0 */ + 0x0010e1, /* U+0010e1 */ + 0x0010e2, /* U+0010e2 */ + 0x0010e3, /* U+0010e3 */ + 0x0010e4, /* U+0010e4 */ + 0x0010e5, /* U+0010e5 */ + 0x0010e6, /* U+0010e6 */ + 0x0010e7, /* U+0010e7 */ + 0x0010e8, /* U+0010e8 */ + 0x0010e9, /* U+0010e9 */ + 0x0010ea, /* U+0010ea */ + 0x0010eb, /* U+0010eb */ + 0x0010ec, /* U+0010ec */ + 0x0010ed, /* U+0010ed */ + 0x0010ee, /* U+0010ee */ + 0x0010ef, /* U+0010ef */ + 0x0010f0, /* U+0010f0 */ + 0x0010f1, /* U+0010f1 */ + 0x0010f2, /* U+0010f2 */ + 0x0010f3, /* U+0010f3 */ + 0x0010f4, /* U+0010f4 */ + 0x0010f5, /* U+0010f5 */ + 0x0010f6, /* U+0010f6 */ + 0x0010f7, /* U+0010f7 */ + 0x0010f8, /* U+0010f8 */ + 0x0010f9, /* U+0010f9 */ + 0x0010fa, /* U+0010fa */ + 0x0010fd, /* U+0010fd */ + 0x0010fe, /* U+0010fe */ + 0x0010ff, /* U+0010ff */ + 0x00ab70, /* U+0013a0 */ + 0x00ab71, /* U+0013a1 */ + 0x00ab72, /* U+0013a2 */ + 0x00ab73, /* U+0013a3 */ + 0x00ab74, /* U+0013a4 */ + 0x00ab75, /* U+0013a5 */ + 0x00ab76, /* U+0013a6 */ + 0x00ab77, /* U+0013a7 */ + 0x00ab78, /* U+0013a8 */ + 0x00ab79, /* U+0013a9 */ + 0x00ab7a, /* U+0013aa */ + 0x00ab7b, /* U+0013ab */ + 0x00ab7c, /* U+0013ac */ + 0x00ab7d, /* U+0013ad */ + 0x00ab7e, /* U+0013ae */ + 0x00ab7f, /* U+0013af */ + 0x00ab80, /* U+0013b0 */ + 0x00ab81, /* U+0013b1 */ + 0x00ab82, /* U+0013b2 */ + 0x00ab83, /* U+0013b3 */ + 0x00ab84, /* U+0013b4 */ + 0x00ab85, /* U+0013b5 */ + 0x00ab86, /* U+0013b6 */ + 0x00ab87, /* U+0013b7 */ + 0x00ab88, /* U+0013b8 */ + 0x00ab89, /* U+0013b9 */ + 0x00ab8a, /* U+0013ba */ + 0x00ab8b, /* U+0013bb */ + 0x00ab8c, /* U+0013bc */ + 0x00ab8d, /* U+0013bd */ + 0x00ab8e, /* U+0013be */ + 0x00ab8f, /* U+0013bf */ + 0x00ab90, /* U+0013c0 */ + 0x00ab91, /* U+0013c1 */ + 0x00ab92, /* U+0013c2 */ + 0x00ab93, /* U+0013c3 */ + 0x00ab94, /* U+0013c4 */ + 0x00ab95, /* U+0013c5 */ + 0x00ab96, /* U+0013c6 */ + 0x00ab97, /* U+0013c7 */ + 0x00ab98, /* U+0013c8 */ + 0x00ab99, /* U+0013c9 */ + 0x00ab9a, /* U+0013ca */ + 0x00ab9b, /* U+0013cb */ + 0x00ab9c, /* U+0013cc */ + 0x00ab9d, /* U+0013cd */ + 0x00ab9e, /* U+0013ce */ + 0x00ab9f, /* U+0013cf */ + 0x00aba0, /* U+0013d0 */ + 0x00aba1, /* U+0013d1 */ + 0x00aba2, /* U+0013d2 */ + 0x00aba3, /* U+0013d3 */ + 0x00aba4, /* U+0013d4 */ + 0x00aba5, /* U+0013d5 */ + 0x00aba6, /* U+0013d6 */ + 0x00aba7, /* U+0013d7 */ + 0x00aba8, /* U+0013d8 */ + 0x00aba9, /* U+0013d9 */ + 0x00abaa, /* U+0013da */ + 0x00abab, /* U+0013db */ + 0x00abac, /* U+0013dc */ + 0x00abad, /* U+0013dd */ + 0x00abae, /* U+0013de */ + 0x00abaf, /* U+0013df */ + 0x00abb0, /* U+0013e0 */ + 0x00abb1, /* U+0013e1 */ + 0x00abb2, /* U+0013e2 */ + 0x00abb3, /* U+0013e3 */ + 0x00abb4, /* U+0013e4 */ + 0x00abb5, /* U+0013e5 */ + 0x00abb6, /* U+0013e6 */ + 0x00abb7, /* U+0013e7 */ + 0x00abb8, /* U+0013e8 */ + 0x00abb9, /* U+0013e9 */ + 0x00abba, /* U+0013ea */ + 0x00abbb, /* U+0013eb */ + 0x00abbc, /* U+0013ec */ + 0x00abbd, /* U+0013ed */ + 0x00abbe, /* U+0013ee */ + 0x00abbf, /* U+0013ef */ + 0x0013f8, /* U+0013f0 */ + 0x0013f9, /* U+0013f1 */ + 0x0013fa, /* U+0013f2 */ + 0x0013fb, /* U+0013f3 */ + 0x0013fc, /* U+0013f4 */ + 0x0013fd, /* U+0013f5 */ + 0x001c80, /* U+001c80 */ + 0x001c81, /* U+001c81 */ + 0x001c82, /* U+001c82 */ + 0x001c83, /* U+001c83 */ + 0x001c84, /* U+001c84 */ + 0x001c85, /* U+001c85 */ + 0x001c86, /* U+001c86 */ + 0x001c87, /* U+001c87 */ + 0x001c88, /* U+001c88 */ + 0x001c8a, /* U+001c89 */ + 0x0010d0, /* U+001c90 */ + 0x0010d1, /* U+001c91 */ + 0x0010d2, /* U+001c92 */ + 0x0010d3, /* U+001c93 */ + 0x0010d4, /* U+001c94 */ + 0x0010d5, /* U+001c95 */ + 0x0010d6, /* U+001c96 */ + 0x0010d7, /* U+001c97 */ + 0x0010d8, /* U+001c98 */ + 0x0010d9, /* U+001c99 */ + 0x0010da, /* U+001c9a */ + 0x0010db, /* U+001c9b */ + 0x0010dc, /* U+001c9c */ + 0x0010dd, /* U+001c9d */ + 0x0010de, /* U+001c9e */ + 0x0010df, /* U+001c9f */ + 0x0010e0, /* U+001ca0 */ + 0x0010e1, /* U+001ca1 */ + 0x0010e2, /* U+001ca2 */ + 0x0010e3, /* U+001ca3 */ + 0x0010e4, /* U+001ca4 */ + 0x0010e5, /* U+001ca5 */ + 0x0010e6, /* U+001ca6 */ + 0x0010e7, /* U+001ca7 */ + 0x0010e8, /* U+001ca8 */ + 0x0010e9, /* U+001ca9 */ + 0x0010ea, /* U+001caa */ + 0x0010eb, /* U+001cab */ + 0x0010ec, /* U+001cac */ + 0x0010ed, /* U+001cad */ + 0x0010ee, /* U+001cae */ + 0x0010ef, /* U+001caf */ + 0x0010f0, /* U+001cb0 */ + 0x0010f1, /* U+001cb1 */ + 0x0010f2, /* U+001cb2 */ + 0x0010f3, /* U+001cb3 */ + 0x0010f4, /* U+001cb4 */ + 0x0010f5, /* U+001cb5 */ + 0x0010f6, /* U+001cb6 */ + 0x0010f7, /* U+001cb7 */ + 0x0010f8, /* U+001cb8 */ + 0x0010f9, /* U+001cb9 */ + 0x0010fa, /* U+001cba */ + 0x0010fd, /* U+001cbd */ + 0x0010fe, /* U+001cbe */ + 0x0010ff, /* U+001cbf */ + 0x001d79, /* U+001d79 */ + 0x001d7d, /* U+001d7d */ + 0x001d8e, /* U+001d8e */ + 0x001e01, /* U+001e00 */ + 0x001e03, /* U+001e02 */ + 0x001e05, /* U+001e04 */ + 0x001e07, /* U+001e06 */ + 0x001e09, /* U+001e08 */ + 0x001e0b, /* U+001e0a */ + 0x001e0d, /* U+001e0c */ + 0x001e0f, /* U+001e0e */ + 0x001e11, /* U+001e10 */ + 0x001e13, /* U+001e12 */ + 0x001e15, /* U+001e14 */ + 0x001e17, /* U+001e16 */ + 0x001e19, /* U+001e18 */ + 0x001e1b, /* U+001e1a */ + 0x001e1d, /* U+001e1c */ + 0x001e1f, /* U+001e1e */ + 0x001e21, /* U+001e20 */ + 0x001e23, /* U+001e22 */ + 0x001e25, /* U+001e24 */ + 0x001e27, /* U+001e26 */ + 0x001e29, /* U+001e28 */ + 0x001e2b, /* U+001e2a */ + 0x001e2d, /* U+001e2c */ + 0x001e2f, /* U+001e2e */ + 0x001e31, /* U+001e30 */ + 0x001e33, /* U+001e32 */ + 0x001e35, /* U+001e34 */ + 0x001e37, /* U+001e36 */ + 0x001e39, /* U+001e38 */ + 0x001e3b, /* U+001e3a */ + 0x001e3d, /* U+001e3c */ + 0x001e3f, /* U+001e3e */ + 0x001e41, /* U+001e40 */ + 0x001e43, /* U+001e42 */ + 0x001e45, /* U+001e44 */ + 0x001e47, /* U+001e46 */ + 0x001e49, /* U+001e48 */ + 0x001e4b, /* U+001e4a */ + 0x001e4d, /* U+001e4c */ + 0x001e4f, /* U+001e4e */ + 0x001e51, /* U+001e50 */ + 0x001e53, /* U+001e52 */ + 0x001e55, /* U+001e54 */ + 0x001e57, /* U+001e56 */ + 0x001e59, /* U+001e58 */ + 0x001e5b, /* U+001e5a */ + 0x001e5d, /* U+001e5c */ + 0x001e5f, /* U+001e5e */ + 0x001e61, /* U+001e60 */ + 0x001e63, /* U+001e62 */ + 0x001e65, /* U+001e64 */ + 0x001e67, /* U+001e66 */ + 0x001e69, /* U+001e68 */ + 0x001e6b, /* U+001e6a */ + 0x001e6d, /* U+001e6c */ + 0x001e6f, /* U+001e6e */ + 0x001e71, /* U+001e70 */ + 0x001e73, /* U+001e72 */ + 0x001e75, /* U+001e74 */ + 0x001e77, /* U+001e76 */ + 0x001e79, /* U+001e78 */ + 0x001e7b, /* U+001e7a */ + 0x001e7d, /* U+001e7c */ + 0x001e7f, /* U+001e7e */ + 0x001e81, /* U+001e80 */ + 0x001e83, /* U+001e82 */ + 0x001e85, /* U+001e84 */ + 0x001e87, /* U+001e86 */ + 0x001e89, /* U+001e88 */ + 0x001e8b, /* U+001e8a */ + 0x001e8d, /* U+001e8c */ + 0x001e8f, /* U+001e8e */ + 0x001e91, /* U+001e90 */ + 0x001e93, /* U+001e92 */ + 0x001e95, /* U+001e94 */ + 0x001e96, /* U+001e96 */ + 0x001e97, /* U+001e97 */ + 0x001e98, /* U+001e98 */ + 0x001e99, /* U+001e99 */ + 0x001e9a, /* U+001e9a */ + 0x001e9b, /* U+001e9b */ + 0x0000df, /* U+001e9e */ + 0x001ea1, /* U+001ea0 */ + 0x001ea3, /* U+001ea2 */ + 0x001ea5, /* U+001ea4 */ + 0x001ea7, /* U+001ea6 */ + 0x001ea9, /* U+001ea8 */ + 0x001eab, /* U+001eaa */ + 0x001ead, /* U+001eac */ + 0x001eaf, /* U+001eae */ + 0x001eb1, /* U+001eb0 */ + 0x001eb3, /* U+001eb2 */ + 0x001eb5, /* U+001eb4 */ + 0x001eb7, /* U+001eb6 */ + 0x001eb9, /* U+001eb8 */ + 0x001ebb, /* U+001eba */ + 0x001ebd, /* U+001ebc */ + 0x001ebf, /* U+001ebe */ + 0x001ec1, /* U+001ec0 */ + 0x001ec3, /* U+001ec2 */ + 0x001ec5, /* U+001ec4 */ + 0x001ec7, /* U+001ec6 */ + 0x001ec9, /* U+001ec8 */ + 0x001ecb, /* U+001eca */ + 0x001ecd, /* U+001ecc */ + 0x001ecf, /* U+001ece */ + 0x001ed1, /* U+001ed0 */ + 0x001ed3, /* U+001ed2 */ + 0x001ed5, /* U+001ed4 */ + 0x001ed7, /* U+001ed6 */ + 0x001ed9, /* U+001ed8 */ + 0x001edb, /* U+001eda */ + 0x001edd, /* U+001edc */ + 0x001edf, /* U+001ede */ + 0x001ee1, /* U+001ee0 */ + 0x001ee3, /* U+001ee2 */ + 0x001ee5, /* U+001ee4 */ + 0x001ee7, /* U+001ee6 */ + 0x001ee9, /* U+001ee8 */ + 0x001eeb, /* U+001eea */ + 0x001eed, /* U+001eec */ + 0x001eef, /* U+001eee */ + 0x001ef1, /* U+001ef0 */ + 0x001ef3, /* U+001ef2 */ + 0x001ef5, /* U+001ef4 */ + 0x001ef7, /* U+001ef6 */ + 0x001ef9, /* U+001ef8 */ + 0x001efb, /* U+001efa */ + 0x001efd, /* U+001efc */ + 0x001eff, /* U+001efe */ + 0x001f00, /* U+001f00 */ + 0x001f01, /* U+001f01 */ + 0x001f02, /* U+001f02 */ + 0x001f03, /* U+001f03 */ + 0x001f04, /* U+001f04 */ + 0x001f05, /* U+001f05 */ + 0x001f06, /* U+001f06 */ + 0x001f07, /* U+001f07 */ + 0x001f10, /* U+001f10 */ + 0x001f11, /* U+001f11 */ + 0x001f12, /* U+001f12 */ + 0x001f13, /* U+001f13 */ + 0x001f14, /* U+001f14 */ + 0x001f15, /* U+001f15 */ + 0x001f20, /* U+001f20 */ + 0x001f21, /* U+001f21 */ + 0x001f22, /* U+001f22 */ + 0x001f23, /* U+001f23 */ + 0x001f24, /* U+001f24 */ + 0x001f25, /* U+001f25 */ + 0x001f26, /* U+001f26 */ + 0x001f27, /* U+001f27 */ + 0x001f30, /* U+001f30 */ + 0x001f31, /* U+001f31 */ + 0x001f32, /* U+001f32 */ + 0x001f33, /* U+001f33 */ + 0x001f34, /* U+001f34 */ + 0x001f35, /* U+001f35 */ + 0x001f36, /* U+001f36 */ + 0x001f37, /* U+001f37 */ + 0x001f40, /* U+001f40 */ + 0x001f41, /* U+001f41 */ + 0x001f42, /* U+001f42 */ + 0x001f43, /* U+001f43 */ + 0x001f44, /* U+001f44 */ + 0x001f45, /* U+001f45 */ + 0x001f50, /* U+001f50 */ + 0x001f51, /* U+001f51 */ + 0x001f52, /* U+001f52 */ + 0x001f53, /* U+001f53 */ + 0x001f54, /* U+001f54 */ + 0x001f55, /* U+001f55 */ + 0x001f56, /* U+001f56 */ + 0x001f57, /* U+001f57 */ + 0x001f60, /* U+001f60 */ + 0x001f61, /* U+001f61 */ + 0x001f62, /* U+001f62 */ + 0x001f63, /* U+001f63 */ + 0x001f64, /* U+001f64 */ + 0x001f65, /* U+001f65 */ + 0x001f66, /* U+001f66 */ + 0x001f67, /* U+001f67 */ + 0x001f70, /* U+001f70 */ + 0x001f71, /* U+001f71 */ + 0x001f72, /* U+001f72 */ + 0x001f73, /* U+001f73 */ + 0x001f74, /* U+001f74 */ + 0x001f75, /* U+001f75 */ + 0x001f76, /* U+001f76 */ + 0x001f77, /* U+001f77 */ + 0x001f78, /* U+001f78 */ + 0x001f79, /* U+001f79 */ + 0x001f7a, /* U+001f7a */ + 0x001f7b, /* U+001f7b */ + 0x001f7c, /* U+001f7c */ + 0x001f7d, /* U+001f7d */ + 0x001f80, /* U+001f80 */ + 0x001f81, /* U+001f81 */ + 0x001f82, /* U+001f82 */ + 0x001f83, /* U+001f83 */ + 0x001f84, /* U+001f84 */ + 0x001f85, /* U+001f85 */ + 0x001f86, /* U+001f86 */ + 0x001f87, /* U+001f87 */ + 0x001f80, /* U+001f88 */ + 0x001f81, /* U+001f89 */ + 0x001f82, /* U+001f8a */ + 0x001f83, /* U+001f8b */ + 0x001f84, /* U+001f8c */ + 0x001f85, /* U+001f8d */ + 0x001f86, /* U+001f8e */ + 0x001f87, /* U+001f8f */ + 0x001f90, /* U+001f90 */ + 0x001f91, /* U+001f91 */ + 0x001f92, /* U+001f92 */ + 0x001f93, /* U+001f93 */ + 0x001f94, /* U+001f94 */ + 0x001f95, /* U+001f95 */ + 0x001f96, /* U+001f96 */ + 0x001f97, /* U+001f97 */ + 0x001f90, /* U+001f98 */ + 0x001f91, /* U+001f99 */ + 0x001f92, /* U+001f9a */ + 0x001f93, /* U+001f9b */ + 0x001f94, /* U+001f9c */ + 0x001f95, /* U+001f9d */ + 0x001f96, /* U+001f9e */ + 0x001f97, /* U+001f9f */ + 0x001fa0, /* U+001fa0 */ + 0x001fa1, /* U+001fa1 */ + 0x001fa2, /* U+001fa2 */ + 0x001fa3, /* U+001fa3 */ + 0x001fa4, /* U+001fa4 */ + 0x001fa5, /* U+001fa5 */ + 0x001fa6, /* U+001fa6 */ + 0x001fa7, /* U+001fa7 */ + 0x001fa0, /* U+001fa8 */ + 0x001fa1, /* U+001fa9 */ + 0x001fa2, /* U+001faa */ + 0x001fa3, /* U+001fab */ + 0x001fa4, /* U+001fac */ + 0x001fa5, /* U+001fad */ + 0x001fa6, /* U+001fae */ + 0x001fa7, /* U+001faf */ + 0x001fb0, /* U+001fb0 */ + 0x001fb1, /* U+001fb1 */ + 0x001fb2, /* U+001fb2 */ + 0x001fb3, /* U+001fb3 */ + 0x001fb4, /* U+001fb4 */ + 0x001fb6, /* U+001fb6 */ + 0x001fb7, /* U+001fb7 */ + 0x001fb3, /* U+001fbc */ + 0x001fbe, /* U+001fbe */ + 0x001fc2, /* U+001fc2 */ + 0x001fc3, /* U+001fc3 */ + 0x001fc4, /* U+001fc4 */ + 0x001fc6, /* U+001fc6 */ + 0x001fc7, /* U+001fc7 */ + 0x001fc3, /* U+001fcc */ + 0x001fd0, /* U+001fd0 */ + 0x001fd1, /* U+001fd1 */ + 0x001fd2, /* U+001fd2 */ + 0x001fd3, /* U+001fd3 */ + 0x001fd6, /* U+001fd6 */ + 0x001fd7, /* U+001fd7 */ + 0x001fe0, /* U+001fe0 */ + 0x001fe1, /* U+001fe1 */ + 0x001fe2, /* U+001fe2 */ + 0x001fe3, /* U+001fe3 */ + 0x001fe4, /* U+001fe4 */ + 0x001fe5, /* U+001fe5 */ + 0x001fe6, /* U+001fe6 */ + 0x001fe7, /* U+001fe7 */ + 0x001ff2, /* U+001ff2 */ + 0x001ff3, /* U+001ff3 */ + 0x001ff4, /* U+001ff4 */ + 0x001ff6, /* U+001ff6 */ + 0x001ff7, /* U+001ff7 */ + 0x001ff3, /* U+001ffc */ + 0x0003c9, /* U+002126 */ + 0x00006b, /* U+00212a */ + 0x0000e5, /* U+00212b */ + 0x00214e, /* U+002132 */ + 0x002170, /* U+002160 */ + 0x002171, /* U+002161 */ + 0x002172, /* U+002162 */ + 0x002173, /* U+002163 */ + 0x002174, /* U+002164 */ + 0x002175, /* U+002165 */ + 0x002176, /* U+002166 */ + 0x002177, /* U+002167 */ + 0x002178, /* U+002168 */ + 0x002179, /* U+002169 */ + 0x00217a, /* U+00216a */ + 0x00217b, /* U+00216b */ + 0x00217c, /* U+00216c */ + 0x00217d, /* U+00216d */ + 0x00217e, /* U+00216e */ + 0x00217f, /* U+00216f */ + 0x002184, /* U+002183 */ + 0x0024d0, /* U+0024b6 */ + 0x0024d1, /* U+0024b7 */ + 0x0024d2, /* U+0024b8 */ + 0x0024d3, /* U+0024b9 */ + 0x0024d4, /* U+0024ba */ + 0x0024d5, /* U+0024bb */ + 0x0024d6, /* U+0024bc */ + 0x0024d7, /* U+0024bd */ + 0x0024d8, /* U+0024be */ + 0x0024d9, /* U+0024bf */ + 0x0024da, /* U+0024c0 */ + 0x0024db, /* U+0024c1 */ + 0x0024dc, /* U+0024c2 */ + 0x0024dd, /* U+0024c3 */ + 0x0024de, /* U+0024c4 */ + 0x0024df, /* U+0024c5 */ + 0x0024e0, /* U+0024c6 */ + 0x0024e1, /* U+0024c7 */ + 0x0024e2, /* U+0024c8 */ + 0x0024e3, /* U+0024c9 */ + 0x0024e4, /* U+0024ca */ + 0x0024e5, /* U+0024cb */ + 0x0024e6, /* U+0024cc */ + 0x0024e7, /* U+0024cd */ + 0x0024e8, /* U+0024ce */ + 0x0024e9, /* U+0024cf */ + 0x002c30, /* U+002c00 */ + 0x002c31, /* U+002c01 */ + 0x002c32, /* U+002c02 */ + 0x002c33, /* U+002c03 */ + 0x002c34, /* U+002c04 */ + 0x002c35, /* U+002c05 */ + 0x002c36, /* U+002c06 */ + 0x002c37, /* U+002c07 */ + 0x002c38, /* U+002c08 */ + 0x002c39, /* U+002c09 */ + 0x002c3a, /* U+002c0a */ + 0x002c3b, /* U+002c0b */ + 0x002c3c, /* U+002c0c */ + 0x002c3d, /* U+002c0d */ + 0x002c3e, /* U+002c0e */ + 0x002c3f, /* U+002c0f */ + 0x002c40, /* U+002c10 */ + 0x002c41, /* U+002c11 */ + 0x002c42, /* U+002c12 */ + 0x002c43, /* U+002c13 */ + 0x002c44, /* U+002c14 */ + 0x002c45, /* U+002c15 */ + 0x002c46, /* U+002c16 */ + 0x002c47, /* U+002c17 */ + 0x002c48, /* U+002c18 */ + 0x002c49, /* U+002c19 */ + 0x002c4a, /* U+002c1a */ + 0x002c4b, /* U+002c1b */ + 0x002c4c, /* U+002c1c */ + 0x002c4d, /* U+002c1d */ + 0x002c4e, /* U+002c1e */ + 0x002c4f, /* U+002c1f */ + 0x002c50, /* U+002c20 */ + 0x002c51, /* U+002c21 */ + 0x002c52, /* U+002c22 */ + 0x002c53, /* U+002c23 */ + 0x002c54, /* U+002c24 */ + 0x002c55, /* U+002c25 */ + 0x002c56, /* U+002c26 */ + 0x002c57, /* U+002c27 */ + 0x002c58, /* U+002c28 */ + 0x002c59, /* U+002c29 */ + 0x002c5a, /* U+002c2a */ + 0x002c5b, /* U+002c2b */ + 0x002c5c, /* U+002c2c */ + 0x002c5d, /* U+002c2d */ + 0x002c5e, /* U+002c2e */ + 0x002c5f, /* U+002c2f */ + 0x002c61, /* U+002c60 */ + 0x002c68, /* U+002c67 */ + 0x002c6a, /* U+002c69 */ + 0x002c6c, /* U+002c6b */ + 0x002c73, /* U+002c72 */ + 0x002c76, /* U+002c75 */ + 0x002c81, /* U+002c80 */ + 0x002c83, /* U+002c82 */ + 0x002c85, /* U+002c84 */ + 0x002c87, /* U+002c86 */ + 0x002c89, /* U+002c88 */ + 0x002c8b, /* U+002c8a */ + 0x002c8d, /* U+002c8c */ + 0x002c8f, /* U+002c8e */ + 0x002c91, /* U+002c90 */ + 0x002c93, /* U+002c92 */ + 0x002c95, /* U+002c94 */ + 0x002c97, /* U+002c96 */ + 0x002c99, /* U+002c98 */ + 0x002c9b, /* U+002c9a */ + 0x002c9d, /* U+002c9c */ + 0x002c9f, /* U+002c9e */ + 0x002ca1, /* U+002ca0 */ + 0x002ca3, /* U+002ca2 */ + 0x002ca5, /* U+002ca4 */ + 0x002ca7, /* U+002ca6 */ + 0x002ca9, /* U+002ca8 */ + 0x002cab, /* U+002caa */ + 0x002cad, /* U+002cac */ + 0x002caf, /* U+002cae */ + 0x002cb1, /* U+002cb0 */ + 0x002cb3, /* U+002cb2 */ + 0x002cb5, /* U+002cb4 */ + 0x002cb7, /* U+002cb6 */ + 0x002cb9, /* U+002cb8 */ + 0x002cbb, /* U+002cba */ + 0x002cbd, /* U+002cbc */ + 0x002cbf, /* U+002cbe */ + 0x002cc1, /* U+002cc0 */ + 0x002cc3, /* U+002cc2 */ + 0x002cc5, /* U+002cc4 */ + 0x002cc7, /* U+002cc6 */ + 0x002cc9, /* U+002cc8 */ + 0x002ccb, /* U+002cca */ + 0x002ccd, /* U+002ccc */ + 0x002ccf, /* U+002cce */ + 0x002cd1, /* U+002cd0 */ + 0x002cd3, /* U+002cd2 */ + 0x002cd5, /* U+002cd4 */ + 0x002cd7, /* U+002cd6 */ + 0x002cd9, /* U+002cd8 */ + 0x002cdb, /* U+002cda */ + 0x002cdd, /* U+002cdc */ + 0x002cdf, /* U+002cde */ + 0x002ce1, /* U+002ce0 */ + 0x002ce3, /* U+002ce2 */ + 0x002cec, /* U+002ceb */ + 0x002cee, /* U+002ced */ + 0x002cf3, /* U+002cf2 */ + 0x00a641, /* U+00a640 */ + 0x00a643, /* U+00a642 */ + 0x00a645, /* U+00a644 */ + 0x00a647, /* U+00a646 */ + 0x00a649, /* U+00a648 */ + 0x00a64b, /* U+00a64a */ + 0x00a64d, /* U+00a64c */ + 0x00a64f, /* U+00a64e */ + 0x00a651, /* U+00a650 */ + 0x00a653, /* U+00a652 */ + 0x00a655, /* U+00a654 */ + 0x00a657, /* U+00a656 */ + 0x00a659, /* U+00a658 */ + 0x00a65b, /* U+00a65a */ + 0x00a65d, /* U+00a65c */ + 0x00a65f, /* U+00a65e */ + 0x00a661, /* U+00a660 */ + 0x00a663, /* U+00a662 */ + 0x00a665, /* U+00a664 */ + 0x00a667, /* U+00a666 */ + 0x00a669, /* U+00a668 */ + 0x00a66b, /* U+00a66a */ + 0x00a66d, /* U+00a66c */ + 0x00a681, /* U+00a680 */ + 0x00a683, /* U+00a682 */ + 0x00a685, /* U+00a684 */ + 0x00a687, /* U+00a686 */ + 0x00a689, /* U+00a688 */ + 0x00a68b, /* U+00a68a */ + 0x00a68d, /* U+00a68c */ + 0x00a68f, /* U+00a68e */ + 0x00a691, /* U+00a690 */ + 0x00a693, /* U+00a692 */ + 0x00a695, /* U+00a694 */ + 0x00a697, /* U+00a696 */ + 0x00a699, /* U+00a698 */ + 0x00a69b, /* U+00a69a */ + 0x00a723, /* U+00a722 */ + 0x00a725, /* U+00a724 */ + 0x00a727, /* U+00a726 */ + 0x00a729, /* U+00a728 */ + 0x00a72b, /* U+00a72a */ + 0x00a72d, /* U+00a72c */ + 0x00a72f, /* U+00a72e */ + 0x00a733, /* U+00a732 */ + 0x00a735, /* U+00a734 */ + 0x00a737, /* U+00a736 */ + 0x00a739, /* U+00a738 */ + 0x00a73b, /* U+00a73a */ + 0x00a73d, /* U+00a73c */ + 0x00a73f, /* U+00a73e */ + 0x00a741, /* U+00a740 */ + 0x00a743, /* U+00a742 */ + 0x00a745, /* U+00a744 */ + 0x00a747, /* U+00a746 */ + 0x00a749, /* U+00a748 */ + 0x00a74b, /* U+00a74a */ + 0x00a74d, /* U+00a74c */ + 0x00a74f, /* U+00a74e */ + 0x00a751, /* U+00a750 */ + 0x00a753, /* U+00a752 */ + 0x00a755, /* U+00a754 */ + 0x00a757, /* U+00a756 */ + 0x00a759, /* U+00a758 */ + 0x00a75b, /* U+00a75a */ + 0x00a75d, /* U+00a75c */ + 0x00a75f, /* U+00a75e */ + 0x00a761, /* U+00a760 */ + 0x00a763, /* U+00a762 */ + 0x00a765, /* U+00a764 */ + 0x00a767, /* U+00a766 */ + 0x00a769, /* U+00a768 */ + 0x00a76b, /* U+00a76a */ + 0x00a76d, /* U+00a76c */ + 0x00a76f, /* U+00a76e */ + 0x00a77a, /* U+00a779 */ + 0x00a77c, /* U+00a77b */ + 0x00a77f, /* U+00a77e */ + 0x00a781, /* U+00a780 */ + 0x00a783, /* U+00a782 */ + 0x00a785, /* U+00a784 */ + 0x00a787, /* U+00a786 */ + 0x00a78c, /* U+00a78b */ + 0x00a791, /* U+00a790 */ + 0x00a793, /* U+00a792 */ + 0x00a794, /* U+00a794 */ + 0x00a797, /* U+00a796 */ + 0x00a799, /* U+00a798 */ + 0x00a79b, /* U+00a79a */ + 0x00a79d, /* U+00a79c */ + 0x00a79f, /* U+00a79e */ + 0x00a7a1, /* U+00a7a0 */ + 0x00a7a3, /* U+00a7a2 */ + 0x00a7a5, /* U+00a7a4 */ + 0x00a7a7, /* U+00a7a6 */ + 0x00a7a9, /* U+00a7a8 */ + 0x00ab53, /* U+00a7b3 */ + 0x00a7b5, /* U+00a7b4 */ + 0x00a7b7, /* U+00a7b6 */ + 0x00a7b9, /* U+00a7b8 */ + 0x00a7bb, /* U+00a7ba */ + 0x00a7bd, /* U+00a7bc */ + 0x00a7bf, /* U+00a7be */ + 0x00a7c1, /* U+00a7c0 */ + 0x00a7c3, /* U+00a7c2 */ + 0x00a7c8, /* U+00a7c7 */ + 0x00a7ca, /* U+00a7c9 */ + 0x00a7cd, /* U+00a7cc */ + 0x00a7d1, /* U+00a7d0 */ + 0x00a7d7, /* U+00a7d6 */ + 0x00a7d9, /* U+00a7d8 */ + 0x00a7db, /* U+00a7da */ + 0x00a7f6, /* U+00a7f5 */ + 0x00fb00, /* U+00fb00 */ + 0x00fb01, /* U+00fb01 */ + 0x00fb02, /* U+00fb02 */ + 0x00fb03, /* U+00fb03 */ + 0x00fb04, /* U+00fb04 */ + 0x00fb05, /* U+00fb05 */ + 0x00fb06, /* U+00fb06 */ + 0x00fb13, /* U+00fb13 */ + 0x00fb14, /* U+00fb14 */ + 0x00fb15, /* U+00fb15 */ + 0x00fb16, /* U+00fb16 */ + 0x00fb17, /* U+00fb17 */ + 0x00ff41, /* U+00ff21 */ + 0x00ff42, /* U+00ff22 */ + 0x00ff43, /* U+00ff23 */ + 0x00ff44, /* U+00ff24 */ + 0x00ff45, /* U+00ff25 */ + 0x00ff46, /* U+00ff26 */ + 0x00ff47, /* U+00ff27 */ + 0x00ff48, /* U+00ff28 */ + 0x00ff49, /* U+00ff29 */ + 0x00ff4a, /* U+00ff2a */ + 0x00ff4b, /* U+00ff2b */ + 0x00ff4c, /* U+00ff2c */ + 0x00ff4d, /* U+00ff2d */ + 0x00ff4e, /* U+00ff2e */ + 0x00ff4f, /* U+00ff2f */ + 0x00ff50, /* U+00ff30 */ + 0x00ff51, /* U+00ff31 */ + 0x00ff52, /* U+00ff32 */ + 0x00ff53, /* U+00ff33 */ + 0x00ff54, /* U+00ff34 */ + 0x00ff55, /* U+00ff35 */ + 0x00ff56, /* U+00ff36 */ + 0x00ff57, /* U+00ff37 */ + 0x00ff58, /* U+00ff38 */ + 0x00ff59, /* U+00ff39 */ + 0x00ff5a, /* U+00ff3a */ + 0x010428, /* U+010400 */ + 0x010429, /* U+010401 */ + 0x01042a, /* U+010402 */ + 0x01042b, /* U+010403 */ + 0x01042c, /* U+010404 */ + 0x01042d, /* U+010405 */ + 0x01042e, /* U+010406 */ + 0x01042f, /* U+010407 */ + 0x010430, /* U+010408 */ + 0x010431, /* U+010409 */ + 0x010432, /* U+01040a */ + 0x010433, /* U+01040b */ + 0x010434, /* U+01040c */ + 0x010435, /* U+01040d */ + 0x010436, /* U+01040e */ + 0x010437, /* U+01040f */ + 0x010438, /* U+010410 */ + 0x010439, /* U+010411 */ + 0x01043a, /* U+010412 */ + 0x01043b, /* U+010413 */ + 0x01043c, /* U+010414 */ + 0x01043d, /* U+010415 */ + 0x01043e, /* U+010416 */ + 0x01043f, /* U+010417 */ + 0x010440, /* U+010418 */ + 0x010441, /* U+010419 */ + 0x010442, /* U+01041a */ + 0x010443, /* U+01041b */ + 0x010444, /* U+01041c */ + 0x010445, /* U+01041d */ + 0x010446, /* U+01041e */ + 0x010447, /* U+01041f */ + 0x010448, /* U+010420 */ + 0x010449, /* U+010421 */ + 0x01044a, /* U+010422 */ + 0x01044b, /* U+010423 */ + 0x01044c, /* U+010424 */ + 0x01044d, /* U+010425 */ + 0x01044e, /* U+010426 */ + 0x01044f, /* U+010427 */ + 0x0104d8, /* U+0104b0 */ + 0x0104d9, /* U+0104b1 */ + 0x0104da, /* U+0104b2 */ + 0x0104db, /* U+0104b3 */ + 0x0104dc, /* U+0104b4 */ + 0x0104dd, /* U+0104b5 */ + 0x0104de, /* U+0104b6 */ + 0x0104df, /* U+0104b7 */ + 0x0104e0, /* U+0104b8 */ + 0x0104e1, /* U+0104b9 */ + 0x0104e2, /* U+0104ba */ + 0x0104e3, /* U+0104bb */ + 0x0104e4, /* U+0104bc */ + 0x0104e5, /* U+0104bd */ + 0x0104e6, /* U+0104be */ + 0x0104e7, /* U+0104bf */ + 0x0104e8, /* U+0104c0 */ + 0x0104e9, /* U+0104c1 */ + 0x0104ea, /* U+0104c2 */ + 0x0104eb, /* U+0104c3 */ + 0x0104ec, /* U+0104c4 */ + 0x0104ed, /* U+0104c5 */ + 0x0104ee, /* U+0104c6 */ + 0x0104ef, /* U+0104c7 */ + 0x0104f0, /* U+0104c8 */ + 0x0104f1, /* U+0104c9 */ + 0x0104f2, /* U+0104ca */ + 0x0104f3, /* U+0104cb */ + 0x0104f4, /* U+0104cc */ + 0x0104f5, /* U+0104cd */ + 0x0104f6, /* U+0104ce */ + 0x0104f7, /* U+0104cf */ + 0x0104f8, /* U+0104d0 */ + 0x0104f9, /* U+0104d1 */ + 0x0104fa, /* U+0104d2 */ + 0x0104fb, /* U+0104d3 */ + 0x010597, /* U+010570 */ + 0x010598, /* U+010571 */ + 0x010599, /* U+010572 */ + 0x01059a, /* U+010573 */ + 0x01059b, /* U+010574 */ + 0x01059c, /* U+010575 */ + 0x01059d, /* U+010576 */ + 0x01059e, /* U+010577 */ + 0x01059f, /* U+010578 */ + 0x0105a0, /* U+010579 */ + 0x0105a1, /* U+01057a */ + 0x0105a3, /* U+01057c */ + 0x0105a4, /* U+01057d */ + 0x0105a5, /* U+01057e */ + 0x0105a6, /* U+01057f */ + 0x0105a7, /* U+010580 */ + 0x0105a8, /* U+010581 */ + 0x0105a9, /* U+010582 */ + 0x0105aa, /* U+010583 */ + 0x0105ab, /* U+010584 */ + 0x0105ac, /* U+010585 */ + 0x0105ad, /* U+010586 */ + 0x0105ae, /* U+010587 */ + 0x0105af, /* U+010588 */ + 0x0105b0, /* U+010589 */ + 0x0105b1, /* U+01058a */ + 0x0105b3, /* U+01058c */ + 0x0105b4, /* U+01058d */ + 0x0105b5, /* U+01058e */ + 0x0105b6, /* U+01058f */ + 0x0105b7, /* U+010590 */ + 0x0105b8, /* U+010591 */ + 0x0105b9, /* U+010592 */ + 0x0105bb, /* U+010594 */ + 0x0105bc, /* U+010595 */ + 0x010cc0, /* U+010c80 */ + 0x010cc1, /* U+010c81 */ + 0x010cc2, /* U+010c82 */ + 0x010cc3, /* U+010c83 */ + 0x010cc4, /* U+010c84 */ + 0x010cc5, /* U+010c85 */ + 0x010cc6, /* U+010c86 */ + 0x010cc7, /* U+010c87 */ + 0x010cc8, /* U+010c88 */ + 0x010cc9, /* U+010c89 */ + 0x010cca, /* U+010c8a */ + 0x010ccb, /* U+010c8b */ + 0x010ccc, /* U+010c8c */ + 0x010ccd, /* U+010c8d */ + 0x010cce, /* U+010c8e */ + 0x010ccf, /* U+010c8f */ + 0x010cd0, /* U+010c90 */ + 0x010cd1, /* U+010c91 */ + 0x010cd2, /* U+010c92 */ + 0x010cd3, /* U+010c93 */ + 0x010cd4, /* U+010c94 */ + 0x010cd5, /* U+010c95 */ + 0x010cd6, /* U+010c96 */ + 0x010cd7, /* U+010c97 */ + 0x010cd8, /* U+010c98 */ + 0x010cd9, /* U+010c99 */ + 0x010cda, /* U+010c9a */ + 0x010cdb, /* U+010c9b */ + 0x010cdc, /* U+010c9c */ + 0x010cdd, /* U+010c9d */ + 0x010cde, /* U+010c9e */ + 0x010cdf, /* U+010c9f */ + 0x010ce0, /* U+010ca0 */ + 0x010ce1, /* U+010ca1 */ + 0x010ce2, /* U+010ca2 */ + 0x010ce3, /* U+010ca3 */ + 0x010ce4, /* U+010ca4 */ + 0x010ce5, /* U+010ca5 */ + 0x010ce6, /* U+010ca6 */ + 0x010ce7, /* U+010ca7 */ + 0x010ce8, /* U+010ca8 */ + 0x010ce9, /* U+010ca9 */ + 0x010cea, /* U+010caa */ + 0x010ceb, /* U+010cab */ + 0x010cec, /* U+010cac */ + 0x010ced, /* U+010cad */ + 0x010cee, /* U+010cae */ + 0x010cef, /* U+010caf */ + 0x010cf0, /* U+010cb0 */ + 0x010cf1, /* U+010cb1 */ + 0x010cf2, /* U+010cb2 */ + 0x010d70, /* U+010d50 */ + 0x010d71, /* U+010d51 */ + 0x010d72, /* U+010d52 */ + 0x010d73, /* U+010d53 */ + 0x010d74, /* U+010d54 */ + 0x010d75, /* U+010d55 */ + 0x010d76, /* U+010d56 */ + 0x010d77, /* U+010d57 */ + 0x010d78, /* U+010d58 */ + 0x010d79, /* U+010d59 */ + 0x010d7a, /* U+010d5a */ + 0x010d7b, /* U+010d5b */ + 0x010d7c, /* U+010d5c */ + 0x010d7d, /* U+010d5d */ + 0x010d7e, /* U+010d5e */ + 0x010d7f, /* U+010d5f */ + 0x010d80, /* U+010d60 */ + 0x010d81, /* U+010d61 */ + 0x010d82, /* U+010d62 */ + 0x010d83, /* U+010d63 */ + 0x010d84, /* U+010d64 */ + 0x010d85, /* U+010d65 */ + 0x0118c0, /* U+0118a0 */ + 0x0118c1, /* U+0118a1 */ + 0x0118c2, /* U+0118a2 */ + 0x0118c3, /* U+0118a3 */ + 0x0118c4, /* U+0118a4 */ + 0x0118c5, /* U+0118a5 */ + 0x0118c6, /* U+0118a6 */ + 0x0118c7, /* U+0118a7 */ + 0x0118c8, /* U+0118a8 */ + 0x0118c9, /* U+0118a9 */ + 0x0118ca, /* U+0118aa */ + 0x0118cb, /* U+0118ab */ + 0x0118cc, /* U+0118ac */ + 0x0118cd, /* U+0118ad */ + 0x0118ce, /* U+0118ae */ + 0x0118cf, /* U+0118af */ + 0x0118d0, /* U+0118b0 */ + 0x0118d1, /* U+0118b1 */ + 0x0118d2, /* U+0118b2 */ + 0x0118d3, /* U+0118b3 */ + 0x0118d4, /* U+0118b4 */ + 0x0118d5, /* U+0118b5 */ + 0x0118d6, /* U+0118b6 */ + 0x0118d7, /* U+0118b7 */ + 0x0118d8, /* U+0118b8 */ + 0x0118d9, /* U+0118b9 */ + 0x0118da, /* U+0118ba */ + 0x0118db, /* U+0118bb */ + 0x0118dc, /* U+0118bc */ + 0x0118dd, /* U+0118bd */ + 0x0118de, /* U+0118be */ + 0x0118df, /* U+0118bf */ + 0x016e60, /* U+016e40 */ + 0x016e61, /* U+016e41 */ + 0x016e62, /* U+016e42 */ + 0x016e63, /* U+016e43 */ + 0x016e64, /* U+016e44 */ + 0x016e65, /* U+016e45 */ + 0x016e66, /* U+016e46 */ + 0x016e67, /* U+016e47 */ + 0x016e68, /* U+016e48 */ + 0x016e69, /* U+016e49 */ + 0x016e6a, /* U+016e4a */ + 0x016e6b, /* U+016e4b */ + 0x016e6c, /* U+016e4c */ + 0x016e6d, /* U+016e4d */ + 0x016e6e, /* U+016e4e */ + 0x016e6f, /* U+016e4f */ + 0x016e70, /* U+016e50 */ + 0x016e71, /* U+016e51 */ + 0x016e72, /* U+016e52 */ + 0x016e73, /* U+016e53 */ + 0x016e74, /* U+016e54 */ + 0x016e75, /* U+016e55 */ + 0x016e76, /* U+016e56 */ + 0x016e77, /* U+016e57 */ + 0x016e78, /* U+016e58 */ + 0x016e79, /* U+016e59 */ + 0x016e7a, /* U+016e5a */ + 0x016e7b, /* U+016e5b */ + 0x016e7c, /* U+016e5c */ + 0x016e7d, /* U+016e5d */ + 0x016e7e, /* U+016e5e */ + 0x016e7f, /* U+016e5f */ + 0x01e922, /* U+01e900 */ + 0x01e923, /* U+01e901 */ + 0x01e924, /* U+01e902 */ + 0x01e925, /* U+01e903 */ + 0x01e926, /* U+01e904 */ + 0x01e927, /* U+01e905 */ + 0x01e928, /* U+01e906 */ + 0x01e929, /* U+01e907 */ + 0x01e92a, /* U+01e908 */ + 0x01e92b, /* U+01e909 */ + 0x01e92c, /* U+01e90a */ + 0x01e92d, /* U+01e90b */ + 0x01e92e, /* U+01e90c */ + 0x01e92f, /* U+01e90d */ + 0x01e930, /* U+01e90e */ + 0x01e931, /* U+01e90f */ + 0x01e932, /* U+01e910 */ + 0x01e933, /* U+01e911 */ + 0x01e934, /* U+01e912 */ + 0x01e935, /* U+01e913 */ + 0x01e936, /* U+01e914 */ + 0x01e937, /* U+01e915 */ + 0x01e938, /* U+01e916 */ + 0x01e939, /* U+01e917 */ + 0x01e93a, /* U+01e918 */ + 0x01e93b, /* U+01e919 */ + 0x01e93c, /* U+01e91a */ + 0x01e93d, /* U+01e91b */ + 0x01e93e, /* U+01e91c */ + 0x01e93f, /* U+01e91d */ + 0x01e940, /* U+01e91e */ + 0x01e941, /* U+01e91f */ + 0x01e942, /* U+01e920 */ + 0x01e943, /* U+01e921 */ - /* begin sparse entries for codepoints >= 0x80 */ - {0x0000b5, {[CaseLower] = 0x0000b5,[CaseTitle] = 0x00039c,[CaseUpper] = 0x00039c}}, - {0x0000c0, {[CaseLower] = 0x0000e0,[CaseTitle] = 0x0000c0,[CaseUpper] = 0x0000c0}}, - {0x0000c1, {[CaseLower] = 0x0000e1,[CaseTitle] = 0x0000c1,[CaseUpper] = 0x0000c1}}, - {0x0000c2, {[CaseLower] = 0x0000e2,[CaseTitle] = 0x0000c2,[CaseUpper] = 0x0000c2}}, - {0x0000c3, {[CaseLower] = 0x0000e3,[CaseTitle] = 0x0000c3,[CaseUpper] = 0x0000c3}}, - {0x0000c4, {[CaseLower] = 0x0000e4,[CaseTitle] = 0x0000c4,[CaseUpper] = 0x0000c4}}, - {0x0000c5, {[CaseLower] = 0x0000e5,[CaseTitle] = 0x0000c5,[CaseUpper] = 0x0000c5}}, - {0x0000c6, {[CaseLower] = 0x0000e6,[CaseTitle] = 0x0000c6,[CaseUpper] = 0x0000c6}}, - {0x0000c7, {[CaseLower] = 0x0000e7,[CaseTitle] = 0x0000c7,[CaseUpper] = 0x0000c7}}, - {0x0000c8, {[CaseLower] = 0x0000e8,[CaseTitle] = 0x0000c8,[CaseUpper] = 0x0000c8}}, - {0x0000c9, {[CaseLower] = 0x0000e9,[CaseTitle] = 0x0000c9,[CaseUpper] = 0x0000c9}}, - {0x0000ca, {[CaseLower] = 0x0000ea,[CaseTitle] = 0x0000ca,[CaseUpper] = 0x0000ca}}, - {0x0000cb, {[CaseLower] = 0x0000eb,[CaseTitle] = 0x0000cb,[CaseUpper] = 0x0000cb}}, - {0x0000cc, {[CaseLower] = 0x0000ec,[CaseTitle] = 0x0000cc,[CaseUpper] = 0x0000cc}}, - {0x0000cd, {[CaseLower] = 0x0000ed,[CaseTitle] = 0x0000cd,[CaseUpper] = 0x0000cd}}, - {0x0000ce, {[CaseLower] = 0x0000ee,[CaseTitle] = 0x0000ce,[CaseUpper] = 0x0000ce}}, - {0x0000cf, {[CaseLower] = 0x0000ef,[CaseTitle] = 0x0000cf,[CaseUpper] = 0x0000cf}}, - {0x0000d0, {[CaseLower] = 0x0000f0,[CaseTitle] = 0x0000d0,[CaseUpper] = 0x0000d0}}, - {0x0000d1, {[CaseLower] = 0x0000f1,[CaseTitle] = 0x0000d1,[CaseUpper] = 0x0000d1}}, - {0x0000d2, {[CaseLower] = 0x0000f2,[CaseTitle] = 0x0000d2,[CaseUpper] = 0x0000d2}}, - {0x0000d3, {[CaseLower] = 0x0000f3,[CaseTitle] = 0x0000d3,[CaseUpper] = 0x0000d3}}, - {0x0000d4, {[CaseLower] = 0x0000f4,[CaseTitle] = 0x0000d4,[CaseUpper] = 0x0000d4}}, - {0x0000d5, {[CaseLower] = 0x0000f5,[CaseTitle] = 0x0000d5,[CaseUpper] = 0x0000d5}}, - {0x0000d6, {[CaseLower] = 0x0000f6,[CaseTitle] = 0x0000d6,[CaseUpper] = 0x0000d6}}, - {0x0000d8, {[CaseLower] = 0x0000f8,[CaseTitle] = 0x0000d8,[CaseUpper] = 0x0000d8}}, - {0x0000d9, {[CaseLower] = 0x0000f9,[CaseTitle] = 0x0000d9,[CaseUpper] = 0x0000d9}}, - {0x0000da, {[CaseLower] = 0x0000fa,[CaseTitle] = 0x0000da,[CaseUpper] = 0x0000da}}, - {0x0000db, {[CaseLower] = 0x0000fb,[CaseTitle] = 0x0000db,[CaseUpper] = 0x0000db}}, - {0x0000dc, {[CaseLower] = 0x0000fc,[CaseTitle] = 0x0000dc,[CaseUpper] = 0x0000dc}}, - {0x0000dd, {[CaseLower] = 0x0000fd,[CaseTitle] = 0x0000dd,[CaseUpper] = 0x0000dd}}, - {0x0000de, {[CaseLower] = 0x0000fe,[CaseTitle] = 0x0000de,[CaseUpper] = 0x0000de}}, - {0x0000e0, {[CaseLower] = 0x0000e0,[CaseTitle] = 0x0000c0,[CaseUpper] = 0x0000c0}}, - {0x0000e1, {[CaseLower] = 0x0000e1,[CaseTitle] = 0x0000c1,[CaseUpper] = 0x0000c1}}, - {0x0000e2, {[CaseLower] = 0x0000e2,[CaseTitle] = 0x0000c2,[CaseUpper] = 0x0000c2}}, - {0x0000e3, {[CaseLower] = 0x0000e3,[CaseTitle] = 0x0000c3,[CaseUpper] = 0x0000c3}}, - {0x0000e4, {[CaseLower] = 0x0000e4,[CaseTitle] = 0x0000c4,[CaseUpper] = 0x0000c4}}, - {0x0000e5, {[CaseLower] = 0x0000e5,[CaseTitle] = 0x0000c5,[CaseUpper] = 0x0000c5}}, - {0x0000e6, {[CaseLower] = 0x0000e6,[CaseTitle] = 0x0000c6,[CaseUpper] = 0x0000c6}}, - {0x0000e7, {[CaseLower] = 0x0000e7,[CaseTitle] = 0x0000c7,[CaseUpper] = 0x0000c7}}, - {0x0000e8, {[CaseLower] = 0x0000e8,[CaseTitle] = 0x0000c8,[CaseUpper] = 0x0000c8}}, - {0x0000e9, {[CaseLower] = 0x0000e9,[CaseTitle] = 0x0000c9,[CaseUpper] = 0x0000c9}}, - {0x0000ea, {[CaseLower] = 0x0000ea,[CaseTitle] = 0x0000ca,[CaseUpper] = 0x0000ca}}, - {0x0000eb, {[CaseLower] = 0x0000eb,[CaseTitle] = 0x0000cb,[CaseUpper] = 0x0000cb}}, - {0x0000ec, {[CaseLower] = 0x0000ec,[CaseTitle] = 0x0000cc,[CaseUpper] = 0x0000cc}}, - {0x0000ed, {[CaseLower] = 0x0000ed,[CaseTitle] = 0x0000cd,[CaseUpper] = 0x0000cd}}, - {0x0000ee, {[CaseLower] = 0x0000ee,[CaseTitle] = 0x0000ce,[CaseUpper] = 0x0000ce}}, - {0x0000ef, {[CaseLower] = 0x0000ef,[CaseTitle] = 0x0000cf,[CaseUpper] = 0x0000cf}}, - {0x0000f0, {[CaseLower] = 0x0000f0,[CaseTitle] = 0x0000d0,[CaseUpper] = 0x0000d0}}, - {0x0000f1, {[CaseLower] = 0x0000f1,[CaseTitle] = 0x0000d1,[CaseUpper] = 0x0000d1}}, - {0x0000f2, {[CaseLower] = 0x0000f2,[CaseTitle] = 0x0000d2,[CaseUpper] = 0x0000d2}}, - {0x0000f3, {[CaseLower] = 0x0000f3,[CaseTitle] = 0x0000d3,[CaseUpper] = 0x0000d3}}, - {0x0000f4, {[CaseLower] = 0x0000f4,[CaseTitle] = 0x0000d4,[CaseUpper] = 0x0000d4}}, - {0x0000f5, {[CaseLower] = 0x0000f5,[CaseTitle] = 0x0000d5,[CaseUpper] = 0x0000d5}}, - {0x0000f6, {[CaseLower] = 0x0000f6,[CaseTitle] = 0x0000d6,[CaseUpper] = 0x0000d6}}, - {0x0000f8, {[CaseLower] = 0x0000f8,[CaseTitle] = 0x0000d8,[CaseUpper] = 0x0000d8}}, - {0x0000f9, {[CaseLower] = 0x0000f9,[CaseTitle] = 0x0000d9,[CaseUpper] = 0x0000d9}}, - {0x0000fa, {[CaseLower] = 0x0000fa,[CaseTitle] = 0x0000da,[CaseUpper] = 0x0000da}}, - {0x0000fb, {[CaseLower] = 0x0000fb,[CaseTitle] = 0x0000db,[CaseUpper] = 0x0000db}}, - {0x0000fc, {[CaseLower] = 0x0000fc,[CaseTitle] = 0x0000dc,[CaseUpper] = 0x0000dc}}, - {0x0000fd, {[CaseLower] = 0x0000fd,[CaseTitle] = 0x0000dd,[CaseUpper] = 0x0000dd}}, - {0x0000fe, {[CaseLower] = 0x0000fe,[CaseTitle] = 0x0000de,[CaseUpper] = 0x0000de}}, - {0x0000ff, {[CaseLower] = 0x0000ff,[CaseTitle] = 0x000178,[CaseUpper] = 0x000178}}, - {0x000100, {[CaseLower] = 0x000101,[CaseTitle] = 0x000100,[CaseUpper] = 0x000100}}, - {0x000101, {[CaseLower] = 0x000101,[CaseTitle] = 0x000100,[CaseUpper] = 0x000100}}, - {0x000102, {[CaseLower] = 0x000103,[CaseTitle] = 0x000102,[CaseUpper] = 0x000102}}, - {0x000103, {[CaseLower] = 0x000103,[CaseTitle] = 0x000102,[CaseUpper] = 0x000102}}, - {0x000104, {[CaseLower] = 0x000105,[CaseTitle] = 0x000104,[CaseUpper] = 0x000104}}, - {0x000105, {[CaseLower] = 0x000105,[CaseTitle] = 0x000104,[CaseUpper] = 0x000104}}, - {0x000106, {[CaseLower] = 0x000107,[CaseTitle] = 0x000106,[CaseUpper] = 0x000106}}, - {0x000107, {[CaseLower] = 0x000107,[CaseTitle] = 0x000106,[CaseUpper] = 0x000106}}, - {0x000108, {[CaseLower] = 0x000109,[CaseTitle] = 0x000108,[CaseUpper] = 0x000108}}, - {0x000109, {[CaseLower] = 0x000109,[CaseTitle] = 0x000108,[CaseUpper] = 0x000108}}, - {0x00010a, {[CaseLower] = 0x00010b,[CaseTitle] = 0x00010a,[CaseUpper] = 0x00010a}}, - {0x00010b, {[CaseLower] = 0x00010b,[CaseTitle] = 0x00010a,[CaseUpper] = 0x00010a}}, - {0x00010c, {[CaseLower] = 0x00010d,[CaseTitle] = 0x00010c,[CaseUpper] = 0x00010c}}, - {0x00010d, {[CaseLower] = 0x00010d,[CaseTitle] = 0x00010c,[CaseUpper] = 0x00010c}}, - {0x00010e, {[CaseLower] = 0x00010f,[CaseTitle] = 0x00010e,[CaseUpper] = 0x00010e}}, - {0x00010f, {[CaseLower] = 0x00010f,[CaseTitle] = 0x00010e,[CaseUpper] = 0x00010e}}, - {0x000110, {[CaseLower] = 0x000111,[CaseTitle] = 0x000110,[CaseUpper] = 0x000110}}, - {0x000111, {[CaseLower] = 0x000111,[CaseTitle] = 0x000110,[CaseUpper] = 0x000110}}, - {0x000112, {[CaseLower] = 0x000113,[CaseTitle] = 0x000112,[CaseUpper] = 0x000112}}, - {0x000113, {[CaseLower] = 0x000113,[CaseTitle] = 0x000112,[CaseUpper] = 0x000112}}, - {0x000114, {[CaseLower] = 0x000115,[CaseTitle] = 0x000114,[CaseUpper] = 0x000114}}, - {0x000115, {[CaseLower] = 0x000115,[CaseTitle] = 0x000114,[CaseUpper] = 0x000114}}, - {0x000116, {[CaseLower] = 0x000117,[CaseTitle] = 0x000116,[CaseUpper] = 0x000116}}, - {0x000117, {[CaseLower] = 0x000117,[CaseTitle] = 0x000116,[CaseUpper] = 0x000116}}, - {0x000118, {[CaseLower] = 0x000119,[CaseTitle] = 0x000118,[CaseUpper] = 0x000118}}, - {0x000119, {[CaseLower] = 0x000119,[CaseTitle] = 0x000118,[CaseUpper] = 0x000118}}, - {0x00011a, {[CaseLower] = 0x00011b,[CaseTitle] = 0x00011a,[CaseUpper] = 0x00011a}}, - {0x00011b, {[CaseLower] = 0x00011b,[CaseTitle] = 0x00011a,[CaseUpper] = 0x00011a}}, - {0x00011c, {[CaseLower] = 0x00011d,[CaseTitle] = 0x00011c,[CaseUpper] = 0x00011c}}, - {0x00011d, {[CaseLower] = 0x00011d,[CaseTitle] = 0x00011c,[CaseUpper] = 0x00011c}}, - {0x00011e, {[CaseLower] = 0x00011f,[CaseTitle] = 0x00011e,[CaseUpper] = 0x00011e}}, - {0x00011f, {[CaseLower] = 0x00011f,[CaseTitle] = 0x00011e,[CaseUpper] = 0x00011e}}, - {0x000120, {[CaseLower] = 0x000121,[CaseTitle] = 0x000120,[CaseUpper] = 0x000120}}, - {0x000121, {[CaseLower] = 0x000121,[CaseTitle] = 0x000120,[CaseUpper] = 0x000120}}, - {0x000122, {[CaseLower] = 0x000123,[CaseTitle] = 0x000122,[CaseUpper] = 0x000122}}, - {0x000123, {[CaseLower] = 0x000123,[CaseTitle] = 0x000122,[CaseUpper] = 0x000122}}, - {0x000124, {[CaseLower] = 0x000125,[CaseTitle] = 0x000124,[CaseUpper] = 0x000124}}, - {0x000125, {[CaseLower] = 0x000125,[CaseTitle] = 0x000124,[CaseUpper] = 0x000124}}, - {0x000126, {[CaseLower] = 0x000127,[CaseTitle] = 0x000126,[CaseUpper] = 0x000126}}, - {0x000127, {[CaseLower] = 0x000127,[CaseTitle] = 0x000126,[CaseUpper] = 0x000126}}, - {0x000128, {[CaseLower] = 0x000129,[CaseTitle] = 0x000128,[CaseUpper] = 0x000128}}, - {0x000129, {[CaseLower] = 0x000129,[CaseTitle] = 0x000128,[CaseUpper] = 0x000128}}, - {0x00012a, {[CaseLower] = 0x00012b,[CaseTitle] = 0x00012a,[CaseUpper] = 0x00012a}}, - {0x00012b, {[CaseLower] = 0x00012b,[CaseTitle] = 0x00012a,[CaseUpper] = 0x00012a}}, - {0x00012c, {[CaseLower] = 0x00012d,[CaseTitle] = 0x00012c,[CaseUpper] = 0x00012c}}, - {0x00012d, {[CaseLower] = 0x00012d,[CaseTitle] = 0x00012c,[CaseUpper] = 0x00012c}}, - {0x00012e, {[CaseLower] = 0x00012f,[CaseTitle] = 0x00012e,[CaseUpper] = 0x00012e}}, - {0x00012f, {[CaseLower] = 0x00012f,[CaseTitle] = 0x00012e,[CaseUpper] = 0x00012e}}, - {0x000130, {[CaseLower] = 0x000069,[CaseTitle] = 0x000130,[CaseUpper] = 0x000130}}, - {0x000131, {[CaseLower] = 0x000131,[CaseTitle] = 0x000049,[CaseUpper] = 0x000049}}, - {0x000132, {[CaseLower] = 0x000133,[CaseTitle] = 0x000132,[CaseUpper] = 0x000132}}, - {0x000133, {[CaseLower] = 0x000133,[CaseTitle] = 0x000132,[CaseUpper] = 0x000132}}, - {0x000134, {[CaseLower] = 0x000135,[CaseTitle] = 0x000134,[CaseUpper] = 0x000134}}, - {0x000135, {[CaseLower] = 0x000135,[CaseTitle] = 0x000134,[CaseUpper] = 0x000134}}, - {0x000136, {[CaseLower] = 0x000137,[CaseTitle] = 0x000136,[CaseUpper] = 0x000136}}, - {0x000137, {[CaseLower] = 0x000137,[CaseTitle] = 0x000136,[CaseUpper] = 0x000136}}, - {0x000139, {[CaseLower] = 0x00013a,[CaseTitle] = 0x000139,[CaseUpper] = 0x000139}}, - {0x00013a, {[CaseLower] = 0x00013a,[CaseTitle] = 0x000139,[CaseUpper] = 0x000139}}, - {0x00013b, {[CaseLower] = 0x00013c,[CaseTitle] = 0x00013b,[CaseUpper] = 0x00013b}}, - {0x00013c, {[CaseLower] = 0x00013c,[CaseTitle] = 0x00013b,[CaseUpper] = 0x00013b}}, - {0x00013d, {[CaseLower] = 0x00013e,[CaseTitle] = 0x00013d,[CaseUpper] = 0x00013d}}, - {0x00013e, {[CaseLower] = 0x00013e,[CaseTitle] = 0x00013d,[CaseUpper] = 0x00013d}}, - {0x00013f, {[CaseLower] = 0x000140,[CaseTitle] = 0x00013f,[CaseUpper] = 0x00013f}}, - {0x000140, {[CaseLower] = 0x000140,[CaseTitle] = 0x00013f,[CaseUpper] = 0x00013f}}, - {0x000141, {[CaseLower] = 0x000142,[CaseTitle] = 0x000141,[CaseUpper] = 0x000141}}, - {0x000142, {[CaseLower] = 0x000142,[CaseTitle] = 0x000141,[CaseUpper] = 0x000141}}, - {0x000143, {[CaseLower] = 0x000144,[CaseTitle] = 0x000143,[CaseUpper] = 0x000143}}, - {0x000144, {[CaseLower] = 0x000144,[CaseTitle] = 0x000143,[CaseUpper] = 0x000143}}, - {0x000145, {[CaseLower] = 0x000146,[CaseTitle] = 0x000145,[CaseUpper] = 0x000145}}, - {0x000146, {[CaseLower] = 0x000146,[CaseTitle] = 0x000145,[CaseUpper] = 0x000145}}, - {0x000147, {[CaseLower] = 0x000148,[CaseTitle] = 0x000147,[CaseUpper] = 0x000147}}, - {0x000148, {[CaseLower] = 0x000148,[CaseTitle] = 0x000147,[CaseUpper] = 0x000147}}, - {0x00014a, {[CaseLower] = 0x00014b,[CaseTitle] = 0x00014a,[CaseUpper] = 0x00014a}}, - {0x00014b, {[CaseLower] = 0x00014b,[CaseTitle] = 0x00014a,[CaseUpper] = 0x00014a}}, - {0x00014c, {[CaseLower] = 0x00014d,[CaseTitle] = 0x00014c,[CaseUpper] = 0x00014c}}, - {0x00014d, {[CaseLower] = 0x00014d,[CaseTitle] = 0x00014c,[CaseUpper] = 0x00014c}}, - {0x00014e, {[CaseLower] = 0x00014f,[CaseTitle] = 0x00014e,[CaseUpper] = 0x00014e}}, - {0x00014f, {[CaseLower] = 0x00014f,[CaseTitle] = 0x00014e,[CaseUpper] = 0x00014e}}, - {0x000150, {[CaseLower] = 0x000151,[CaseTitle] = 0x000150,[CaseUpper] = 0x000150}}, - {0x000151, {[CaseLower] = 0x000151,[CaseTitle] = 0x000150,[CaseUpper] = 0x000150}}, - {0x000152, {[CaseLower] = 0x000153,[CaseTitle] = 0x000152,[CaseUpper] = 0x000152}}, - {0x000153, {[CaseLower] = 0x000153,[CaseTitle] = 0x000152,[CaseUpper] = 0x000152}}, - {0x000154, {[CaseLower] = 0x000155,[CaseTitle] = 0x000154,[CaseUpper] = 0x000154}}, - {0x000155, {[CaseLower] = 0x000155,[CaseTitle] = 0x000154,[CaseUpper] = 0x000154}}, - {0x000156, {[CaseLower] = 0x000157,[CaseTitle] = 0x000156,[CaseUpper] = 0x000156}}, - {0x000157, {[CaseLower] = 0x000157,[CaseTitle] = 0x000156,[CaseUpper] = 0x000156}}, - {0x000158, {[CaseLower] = 0x000159,[CaseTitle] = 0x000158,[CaseUpper] = 0x000158}}, - {0x000159, {[CaseLower] = 0x000159,[CaseTitle] = 0x000158,[CaseUpper] = 0x000158}}, - {0x00015a, {[CaseLower] = 0x00015b,[CaseTitle] = 0x00015a,[CaseUpper] = 0x00015a}}, - {0x00015b, {[CaseLower] = 0x00015b,[CaseTitle] = 0x00015a,[CaseUpper] = 0x00015a}}, - {0x00015c, {[CaseLower] = 0x00015d,[CaseTitle] = 0x00015c,[CaseUpper] = 0x00015c}}, - {0x00015d, {[CaseLower] = 0x00015d,[CaseTitle] = 0x00015c,[CaseUpper] = 0x00015c}}, - {0x00015e, {[CaseLower] = 0x00015f,[CaseTitle] = 0x00015e,[CaseUpper] = 0x00015e}}, - {0x00015f, {[CaseLower] = 0x00015f,[CaseTitle] = 0x00015e,[CaseUpper] = 0x00015e}}, - {0x000160, {[CaseLower] = 0x000161,[CaseTitle] = 0x000160,[CaseUpper] = 0x000160}}, - {0x000161, {[CaseLower] = 0x000161,[CaseTitle] = 0x000160,[CaseUpper] = 0x000160}}, - {0x000162, {[CaseLower] = 0x000163,[CaseTitle] = 0x000162,[CaseUpper] = 0x000162}}, - {0x000163, {[CaseLower] = 0x000163,[CaseTitle] = 0x000162,[CaseUpper] = 0x000162}}, - {0x000164, {[CaseLower] = 0x000165,[CaseTitle] = 0x000164,[CaseUpper] = 0x000164}}, - {0x000165, {[CaseLower] = 0x000165,[CaseTitle] = 0x000164,[CaseUpper] = 0x000164}}, - {0x000166, {[CaseLower] = 0x000167,[CaseTitle] = 0x000166,[CaseUpper] = 0x000166}}, - {0x000167, {[CaseLower] = 0x000167,[CaseTitle] = 0x000166,[CaseUpper] = 0x000166}}, - {0x000168, {[CaseLower] = 0x000169,[CaseTitle] = 0x000168,[CaseUpper] = 0x000168}}, - {0x000169, {[CaseLower] = 0x000169,[CaseTitle] = 0x000168,[CaseUpper] = 0x000168}}, - {0x00016a, {[CaseLower] = 0x00016b,[CaseTitle] = 0x00016a,[CaseUpper] = 0x00016a}}, - {0x00016b, {[CaseLower] = 0x00016b,[CaseTitle] = 0x00016a,[CaseUpper] = 0x00016a}}, - {0x00016c, {[CaseLower] = 0x00016d,[CaseTitle] = 0x00016c,[CaseUpper] = 0x00016c}}, - {0x00016d, {[CaseLower] = 0x00016d,[CaseTitle] = 0x00016c,[CaseUpper] = 0x00016c}}, - {0x00016e, {[CaseLower] = 0x00016f,[CaseTitle] = 0x00016e,[CaseUpper] = 0x00016e}}, - {0x00016f, {[CaseLower] = 0x00016f,[CaseTitle] = 0x00016e,[CaseUpper] = 0x00016e}}, - {0x000170, {[CaseLower] = 0x000171,[CaseTitle] = 0x000170,[CaseUpper] = 0x000170}}, - {0x000171, {[CaseLower] = 0x000171,[CaseTitle] = 0x000170,[CaseUpper] = 0x000170}}, - {0x000172, {[CaseLower] = 0x000173,[CaseTitle] = 0x000172,[CaseUpper] = 0x000172}}, - {0x000173, {[CaseLower] = 0x000173,[CaseTitle] = 0x000172,[CaseUpper] = 0x000172}}, - {0x000174, {[CaseLower] = 0x000175,[CaseTitle] = 0x000174,[CaseUpper] = 0x000174}}, - {0x000175, {[CaseLower] = 0x000175,[CaseTitle] = 0x000174,[CaseUpper] = 0x000174}}, - {0x000176, {[CaseLower] = 0x000177,[CaseTitle] = 0x000176,[CaseUpper] = 0x000176}}, - {0x000177, {[CaseLower] = 0x000177,[CaseTitle] = 0x000176,[CaseUpper] = 0x000176}}, - {0x000178, {[CaseLower] = 0x0000ff,[CaseTitle] = 0x000178,[CaseUpper] = 0x000178}}, - {0x000179, {[CaseLower] = 0x00017a,[CaseTitle] = 0x000179,[CaseUpper] = 0x000179}}, - {0x00017a, {[CaseLower] = 0x00017a,[CaseTitle] = 0x000179,[CaseUpper] = 0x000179}}, - {0x00017b, {[CaseLower] = 0x00017c,[CaseTitle] = 0x00017b,[CaseUpper] = 0x00017b}}, - {0x00017c, {[CaseLower] = 0x00017c,[CaseTitle] = 0x00017b,[CaseUpper] = 0x00017b}}, - {0x00017d, {[CaseLower] = 0x00017e,[CaseTitle] = 0x00017d,[CaseUpper] = 0x00017d}}, - {0x00017e, {[CaseLower] = 0x00017e,[CaseTitle] = 0x00017d,[CaseUpper] = 0x00017d}}, - {0x00017f, {[CaseLower] = 0x00017f,[CaseTitle] = 0x000053,[CaseUpper] = 0x000053}}, - {0x000180, {[CaseLower] = 0x000180,[CaseTitle] = 0x000243,[CaseUpper] = 0x000243}}, - {0x000181, {[CaseLower] = 0x000253,[CaseTitle] = 0x000181,[CaseUpper] = 0x000181}}, - {0x000182, {[CaseLower] = 0x000183,[CaseTitle] = 0x000182,[CaseUpper] = 0x000182}}, - {0x000183, {[CaseLower] = 0x000183,[CaseTitle] = 0x000182,[CaseUpper] = 0x000182}}, - {0x000184, {[CaseLower] = 0x000185,[CaseTitle] = 0x000184,[CaseUpper] = 0x000184}}, - {0x000185, {[CaseLower] = 0x000185,[CaseTitle] = 0x000184,[CaseUpper] = 0x000184}}, - {0x000186, {[CaseLower] = 0x000254,[CaseTitle] = 0x000186,[CaseUpper] = 0x000186}}, - {0x000187, {[CaseLower] = 0x000188,[CaseTitle] = 0x000187,[CaseUpper] = 0x000187}}, - {0x000188, {[CaseLower] = 0x000188,[CaseTitle] = 0x000187,[CaseUpper] = 0x000187}}, - {0x000189, {[CaseLower] = 0x000256,[CaseTitle] = 0x000189,[CaseUpper] = 0x000189}}, - {0x00018a, {[CaseLower] = 0x000257,[CaseTitle] = 0x00018a,[CaseUpper] = 0x00018a}}, - {0x00018b, {[CaseLower] = 0x00018c,[CaseTitle] = 0x00018b,[CaseUpper] = 0x00018b}}, - {0x00018c, {[CaseLower] = 0x00018c,[CaseTitle] = 0x00018b,[CaseUpper] = 0x00018b}}, - {0x00018e, {[CaseLower] = 0x0001dd,[CaseTitle] = 0x00018e,[CaseUpper] = 0x00018e}}, - {0x00018f, {[CaseLower] = 0x000259,[CaseTitle] = 0x00018f,[CaseUpper] = 0x00018f}}, - {0x000190, {[CaseLower] = 0x00025b,[CaseTitle] = 0x000190,[CaseUpper] = 0x000190}}, - {0x000191, {[CaseLower] = 0x000192,[CaseTitle] = 0x000191,[CaseUpper] = 0x000191}}, - {0x000192, {[CaseLower] = 0x000192,[CaseTitle] = 0x000191,[CaseUpper] = 0x000191}}, - {0x000193, {[CaseLower] = 0x000260,[CaseTitle] = 0x000193,[CaseUpper] = 0x000193}}, - {0x000194, {[CaseLower] = 0x000263,[CaseTitle] = 0x000194,[CaseUpper] = 0x000194}}, - {0x000195, {[CaseLower] = 0x000195,[CaseTitle] = 0x0001f6,[CaseUpper] = 0x0001f6}}, - {0x000196, {[CaseLower] = 0x000269,[CaseTitle] = 0x000196,[CaseUpper] = 0x000196}}, - {0x000197, {[CaseLower] = 0x000268,[CaseTitle] = 0x000197,[CaseUpper] = 0x000197}}, - {0x000198, {[CaseLower] = 0x000199,[CaseTitle] = 0x000198,[CaseUpper] = 0x000198}}, - {0x000199, {[CaseLower] = 0x000199,[CaseTitle] = 0x000198,[CaseUpper] = 0x000198}}, - {0x00019a, {[CaseLower] = 0x00019a,[CaseTitle] = 0x00023d,[CaseUpper] = 0x00023d}}, - {0x00019c, {[CaseLower] = 0x00026f,[CaseTitle] = 0x00019c,[CaseUpper] = 0x00019c}}, - {0x00019d, {[CaseLower] = 0x000272,[CaseTitle] = 0x00019d,[CaseUpper] = 0x00019d}}, - {0x00019e, {[CaseLower] = 0x00019e,[CaseTitle] = 0x000220,[CaseUpper] = 0x000220}}, - {0x00019f, {[CaseLower] = 0x000275,[CaseTitle] = 0x00019f,[CaseUpper] = 0x00019f}}, - {0x0001a0, {[CaseLower] = 0x0001a1,[CaseTitle] = 0x0001a0,[CaseUpper] = 0x0001a0}}, - {0x0001a1, {[CaseLower] = 0x0001a1,[CaseTitle] = 0x0001a0,[CaseUpper] = 0x0001a0}}, - {0x0001a2, {[CaseLower] = 0x0001a3,[CaseTitle] = 0x0001a2,[CaseUpper] = 0x0001a2}}, - {0x0001a3, {[CaseLower] = 0x0001a3,[CaseTitle] = 0x0001a2,[CaseUpper] = 0x0001a2}}, - {0x0001a4, {[CaseLower] = 0x0001a5,[CaseTitle] = 0x0001a4,[CaseUpper] = 0x0001a4}}, - {0x0001a5, {[CaseLower] = 0x0001a5,[CaseTitle] = 0x0001a4,[CaseUpper] = 0x0001a4}}, - {0x0001a6, {[CaseLower] = 0x000280,[CaseTitle] = 0x0001a6,[CaseUpper] = 0x0001a6}}, - {0x0001a7, {[CaseLower] = 0x0001a8,[CaseTitle] = 0x0001a7,[CaseUpper] = 0x0001a7}}, - {0x0001a8, {[CaseLower] = 0x0001a8,[CaseTitle] = 0x0001a7,[CaseUpper] = 0x0001a7}}, - {0x0001a9, {[CaseLower] = 0x000283,[CaseTitle] = 0x0001a9,[CaseUpper] = 0x0001a9}}, - {0x0001ac, {[CaseLower] = 0x0001ad,[CaseTitle] = 0x0001ac,[CaseUpper] = 0x0001ac}}, - {0x0001ad, {[CaseLower] = 0x0001ad,[CaseTitle] = 0x0001ac,[CaseUpper] = 0x0001ac}}, - {0x0001ae, {[CaseLower] = 0x000288,[CaseTitle] = 0x0001ae,[CaseUpper] = 0x0001ae}}, - {0x0001af, {[CaseLower] = 0x0001b0,[CaseTitle] = 0x0001af,[CaseUpper] = 0x0001af}}, - {0x0001b0, {[CaseLower] = 0x0001b0,[CaseTitle] = 0x0001af,[CaseUpper] = 0x0001af}}, - {0x0001b1, {[CaseLower] = 0x00028a,[CaseTitle] = 0x0001b1,[CaseUpper] = 0x0001b1}}, - {0x0001b2, {[CaseLower] = 0x00028b,[CaseTitle] = 0x0001b2,[CaseUpper] = 0x0001b2}}, - {0x0001b3, {[CaseLower] = 0x0001b4,[CaseTitle] = 0x0001b3,[CaseUpper] = 0x0001b3}}, - {0x0001b4, {[CaseLower] = 0x0001b4,[CaseTitle] = 0x0001b3,[CaseUpper] = 0x0001b3}}, - {0x0001b5, {[CaseLower] = 0x0001b6,[CaseTitle] = 0x0001b5,[CaseUpper] = 0x0001b5}}, - {0x0001b6, {[CaseLower] = 0x0001b6,[CaseTitle] = 0x0001b5,[CaseUpper] = 0x0001b5}}, - {0x0001b7, {[CaseLower] = 0x000292,[CaseTitle] = 0x0001b7,[CaseUpper] = 0x0001b7}}, - {0x0001b8, {[CaseLower] = 0x0001b9,[CaseTitle] = 0x0001b8,[CaseUpper] = 0x0001b8}}, - {0x0001b9, {[CaseLower] = 0x0001b9,[CaseTitle] = 0x0001b8,[CaseUpper] = 0x0001b8}}, - {0x0001bc, {[CaseLower] = 0x0001bd,[CaseTitle] = 0x0001bc,[CaseUpper] = 0x0001bc}}, - {0x0001bd, {[CaseLower] = 0x0001bd,[CaseTitle] = 0x0001bc,[CaseUpper] = 0x0001bc}}, - {0x0001bf, {[CaseLower] = 0x0001bf,[CaseTitle] = 0x0001f7,[CaseUpper] = 0x0001f7}}, - {0x0001c4, {[CaseLower] = 0x0001c6,[CaseTitle] = 0x0001c5,[CaseUpper] = 0x0001c4}}, - {0x0001c5, {[CaseLower] = 0x0001c6,[CaseTitle] = 0x0001c5,[CaseUpper] = 0x0001c4}}, - {0x0001c6, {[CaseLower] = 0x0001c6,[CaseTitle] = 0x0001c5,[CaseUpper] = 0x0001c4}}, - {0x0001c7, {[CaseLower] = 0x0001c9,[CaseTitle] = 0x0001c8,[CaseUpper] = 0x0001c7}}, - {0x0001c8, {[CaseLower] = 0x0001c9,[CaseTitle] = 0x0001c8,[CaseUpper] = 0x0001c7}}, - {0x0001c9, {[CaseLower] = 0x0001c9,[CaseTitle] = 0x0001c8,[CaseUpper] = 0x0001c7}}, - {0x0001ca, {[CaseLower] = 0x0001cc,[CaseTitle] = 0x0001cb,[CaseUpper] = 0x0001ca}}, - {0x0001cb, {[CaseLower] = 0x0001cc,[CaseTitle] = 0x0001cb,[CaseUpper] = 0x0001ca}}, - {0x0001cc, {[CaseLower] = 0x0001cc,[CaseTitle] = 0x0001cb,[CaseUpper] = 0x0001ca}}, - {0x0001cd, {[CaseLower] = 0x0001ce,[CaseTitle] = 0x0001cd,[CaseUpper] = 0x0001cd}}, - {0x0001ce, {[CaseLower] = 0x0001ce,[CaseTitle] = 0x0001cd,[CaseUpper] = 0x0001cd}}, - {0x0001cf, {[CaseLower] = 0x0001d0,[CaseTitle] = 0x0001cf,[CaseUpper] = 0x0001cf}}, - {0x0001d0, {[CaseLower] = 0x0001d0,[CaseTitle] = 0x0001cf,[CaseUpper] = 0x0001cf}}, - {0x0001d1, {[CaseLower] = 0x0001d2,[CaseTitle] = 0x0001d1,[CaseUpper] = 0x0001d1}}, - {0x0001d2, {[CaseLower] = 0x0001d2,[CaseTitle] = 0x0001d1,[CaseUpper] = 0x0001d1}}, - {0x0001d3, {[CaseLower] = 0x0001d4,[CaseTitle] = 0x0001d3,[CaseUpper] = 0x0001d3}}, - {0x0001d4, {[CaseLower] = 0x0001d4,[CaseTitle] = 0x0001d3,[CaseUpper] = 0x0001d3}}, - {0x0001d5, {[CaseLower] = 0x0001d6,[CaseTitle] = 0x0001d5,[CaseUpper] = 0x0001d5}}, - {0x0001d6, {[CaseLower] = 0x0001d6,[CaseTitle] = 0x0001d5,[CaseUpper] = 0x0001d5}}, - {0x0001d7, {[CaseLower] = 0x0001d8,[CaseTitle] = 0x0001d7,[CaseUpper] = 0x0001d7}}, - {0x0001d8, {[CaseLower] = 0x0001d8,[CaseTitle] = 0x0001d7,[CaseUpper] = 0x0001d7}}, - {0x0001d9, {[CaseLower] = 0x0001da,[CaseTitle] = 0x0001d9,[CaseUpper] = 0x0001d9}}, - {0x0001da, {[CaseLower] = 0x0001da,[CaseTitle] = 0x0001d9,[CaseUpper] = 0x0001d9}}, - {0x0001db, {[CaseLower] = 0x0001dc,[CaseTitle] = 0x0001db,[CaseUpper] = 0x0001db}}, - {0x0001dc, {[CaseLower] = 0x0001dc,[CaseTitle] = 0x0001db,[CaseUpper] = 0x0001db}}, - {0x0001dd, {[CaseLower] = 0x0001dd,[CaseTitle] = 0x00018e,[CaseUpper] = 0x00018e}}, - {0x0001de, {[CaseLower] = 0x0001df,[CaseTitle] = 0x0001de,[CaseUpper] = 0x0001de}}, - {0x0001df, {[CaseLower] = 0x0001df,[CaseTitle] = 0x0001de,[CaseUpper] = 0x0001de}}, - {0x0001e0, {[CaseLower] = 0x0001e1,[CaseTitle] = 0x0001e0,[CaseUpper] = 0x0001e0}}, - {0x0001e1, {[CaseLower] = 0x0001e1,[CaseTitle] = 0x0001e0,[CaseUpper] = 0x0001e0}}, - {0x0001e2, {[CaseLower] = 0x0001e3,[CaseTitle] = 0x0001e2,[CaseUpper] = 0x0001e2}}, - {0x0001e3, {[CaseLower] = 0x0001e3,[CaseTitle] = 0x0001e2,[CaseUpper] = 0x0001e2}}, - {0x0001e4, {[CaseLower] = 0x0001e5,[CaseTitle] = 0x0001e4,[CaseUpper] = 0x0001e4}}, - {0x0001e5, {[CaseLower] = 0x0001e5,[CaseTitle] = 0x0001e4,[CaseUpper] = 0x0001e4}}, - {0x0001e6, {[CaseLower] = 0x0001e7,[CaseTitle] = 0x0001e6,[CaseUpper] = 0x0001e6}}, - {0x0001e7, {[CaseLower] = 0x0001e7,[CaseTitle] = 0x0001e6,[CaseUpper] = 0x0001e6}}, - {0x0001e8, {[CaseLower] = 0x0001e9,[CaseTitle] = 0x0001e8,[CaseUpper] = 0x0001e8}}, - {0x0001e9, {[CaseLower] = 0x0001e9,[CaseTitle] = 0x0001e8,[CaseUpper] = 0x0001e8}}, - {0x0001ea, {[CaseLower] = 0x0001eb,[CaseTitle] = 0x0001ea,[CaseUpper] = 0x0001ea}}, - {0x0001eb, {[CaseLower] = 0x0001eb,[CaseTitle] = 0x0001ea,[CaseUpper] = 0x0001ea}}, - {0x0001ec, {[CaseLower] = 0x0001ed,[CaseTitle] = 0x0001ec,[CaseUpper] = 0x0001ec}}, - {0x0001ed, {[CaseLower] = 0x0001ed,[CaseTitle] = 0x0001ec,[CaseUpper] = 0x0001ec}}, - {0x0001ee, {[CaseLower] = 0x0001ef,[CaseTitle] = 0x0001ee,[CaseUpper] = 0x0001ee}}, - {0x0001ef, {[CaseLower] = 0x0001ef,[CaseTitle] = 0x0001ee,[CaseUpper] = 0x0001ee}}, - {0x0001f1, {[CaseLower] = 0x0001f3,[CaseTitle] = 0x0001f2,[CaseUpper] = 0x0001f1}}, - {0x0001f2, {[CaseLower] = 0x0001f3,[CaseTitle] = 0x0001f2,[CaseUpper] = 0x0001f1}}, - {0x0001f3, {[CaseLower] = 0x0001f3,[CaseTitle] = 0x0001f2,[CaseUpper] = 0x0001f1}}, - {0x0001f4, {[CaseLower] = 0x0001f5,[CaseTitle] = 0x0001f4,[CaseUpper] = 0x0001f4}}, - {0x0001f5, {[CaseLower] = 0x0001f5,[CaseTitle] = 0x0001f4,[CaseUpper] = 0x0001f4}}, - {0x0001f6, {[CaseLower] = 0x000195,[CaseTitle] = 0x0001f6,[CaseUpper] = 0x0001f6}}, - {0x0001f7, {[CaseLower] = 0x0001bf,[CaseTitle] = 0x0001f7,[CaseUpper] = 0x0001f7}}, - {0x0001f8, {[CaseLower] = 0x0001f9,[CaseTitle] = 0x0001f8,[CaseUpper] = 0x0001f8}}, - {0x0001f9, {[CaseLower] = 0x0001f9,[CaseTitle] = 0x0001f8,[CaseUpper] = 0x0001f8}}, - {0x0001fa, {[CaseLower] = 0x0001fb,[CaseTitle] = 0x0001fa,[CaseUpper] = 0x0001fa}}, - {0x0001fb, {[CaseLower] = 0x0001fb,[CaseTitle] = 0x0001fa,[CaseUpper] = 0x0001fa}}, - {0x0001fc, {[CaseLower] = 0x0001fd,[CaseTitle] = 0x0001fc,[CaseUpper] = 0x0001fc}}, - {0x0001fd, {[CaseLower] = 0x0001fd,[CaseTitle] = 0x0001fc,[CaseUpper] = 0x0001fc}}, - {0x0001fe, {[CaseLower] = 0x0001ff,[CaseTitle] = 0x0001fe,[CaseUpper] = 0x0001fe}}, - {0x0001ff, {[CaseLower] = 0x0001ff,[CaseTitle] = 0x0001fe,[CaseUpper] = 0x0001fe}}, - {0x000200, {[CaseLower] = 0x000201,[CaseTitle] = 0x000200,[CaseUpper] = 0x000200}}, - {0x000201, {[CaseLower] = 0x000201,[CaseTitle] = 0x000200,[CaseUpper] = 0x000200}}, - {0x000202, {[CaseLower] = 0x000203,[CaseTitle] = 0x000202,[CaseUpper] = 0x000202}}, - {0x000203, {[CaseLower] = 0x000203,[CaseTitle] = 0x000202,[CaseUpper] = 0x000202}}, - {0x000204, {[CaseLower] = 0x000205,[CaseTitle] = 0x000204,[CaseUpper] = 0x000204}}, - {0x000205, {[CaseLower] = 0x000205,[CaseTitle] = 0x000204,[CaseUpper] = 0x000204}}, - {0x000206, {[CaseLower] = 0x000207,[CaseTitle] = 0x000206,[CaseUpper] = 0x000206}}, - {0x000207, {[CaseLower] = 0x000207,[CaseTitle] = 0x000206,[CaseUpper] = 0x000206}}, - {0x000208, {[CaseLower] = 0x000209,[CaseTitle] = 0x000208,[CaseUpper] = 0x000208}}, - {0x000209, {[CaseLower] = 0x000209,[CaseTitle] = 0x000208,[CaseUpper] = 0x000208}}, - {0x00020a, {[CaseLower] = 0x00020b,[CaseTitle] = 0x00020a,[CaseUpper] = 0x00020a}}, - {0x00020b, {[CaseLower] = 0x00020b,[CaseTitle] = 0x00020a,[CaseUpper] = 0x00020a}}, - {0x00020c, {[CaseLower] = 0x00020d,[CaseTitle] = 0x00020c,[CaseUpper] = 0x00020c}}, - {0x00020d, {[CaseLower] = 0x00020d,[CaseTitle] = 0x00020c,[CaseUpper] = 0x00020c}}, - {0x00020e, {[CaseLower] = 0x00020f,[CaseTitle] = 0x00020e,[CaseUpper] = 0x00020e}}, - {0x00020f, {[CaseLower] = 0x00020f,[CaseTitle] = 0x00020e,[CaseUpper] = 0x00020e}}, - {0x000210, {[CaseLower] = 0x000211,[CaseTitle] = 0x000210,[CaseUpper] = 0x000210}}, - {0x000211, {[CaseLower] = 0x000211,[CaseTitle] = 0x000210,[CaseUpper] = 0x000210}}, - {0x000212, {[CaseLower] = 0x000213,[CaseTitle] = 0x000212,[CaseUpper] = 0x000212}}, - {0x000213, {[CaseLower] = 0x000213,[CaseTitle] = 0x000212,[CaseUpper] = 0x000212}}, - {0x000214, {[CaseLower] = 0x000215,[CaseTitle] = 0x000214,[CaseUpper] = 0x000214}}, - {0x000215, {[CaseLower] = 0x000215,[CaseTitle] = 0x000214,[CaseUpper] = 0x000214}}, - {0x000216, {[CaseLower] = 0x000217,[CaseTitle] = 0x000216,[CaseUpper] = 0x000216}}, - {0x000217, {[CaseLower] = 0x000217,[CaseTitle] = 0x000216,[CaseUpper] = 0x000216}}, - {0x000218, {[CaseLower] = 0x000219,[CaseTitle] = 0x000218,[CaseUpper] = 0x000218}}, - {0x000219, {[CaseLower] = 0x000219,[CaseTitle] = 0x000218,[CaseUpper] = 0x000218}}, - {0x00021a, {[CaseLower] = 0x00021b,[CaseTitle] = 0x00021a,[CaseUpper] = 0x00021a}}, - {0x00021b, {[CaseLower] = 0x00021b,[CaseTitle] = 0x00021a,[CaseUpper] = 0x00021a}}, - {0x00021c, {[CaseLower] = 0x00021d,[CaseTitle] = 0x00021c,[CaseUpper] = 0x00021c}}, - {0x00021d, {[CaseLower] = 0x00021d,[CaseTitle] = 0x00021c,[CaseUpper] = 0x00021c}}, - {0x00021e, {[CaseLower] = 0x00021f,[CaseTitle] = 0x00021e,[CaseUpper] = 0x00021e}}, - {0x00021f, {[CaseLower] = 0x00021f,[CaseTitle] = 0x00021e,[CaseUpper] = 0x00021e}}, - {0x000220, {[CaseLower] = 0x00019e,[CaseTitle] = 0x000220,[CaseUpper] = 0x000220}}, - {0x000222, {[CaseLower] = 0x000223,[CaseTitle] = 0x000222,[CaseUpper] = 0x000222}}, - {0x000223, {[CaseLower] = 0x000223,[CaseTitle] = 0x000222,[CaseUpper] = 0x000222}}, - {0x000224, {[CaseLower] = 0x000225,[CaseTitle] = 0x000224,[CaseUpper] = 0x000224}}, - {0x000225, {[CaseLower] = 0x000225,[CaseTitle] = 0x000224,[CaseUpper] = 0x000224}}, - {0x000226, {[CaseLower] = 0x000227,[CaseTitle] = 0x000226,[CaseUpper] = 0x000226}}, - {0x000227, {[CaseLower] = 0x000227,[CaseTitle] = 0x000226,[CaseUpper] = 0x000226}}, - {0x000228, {[CaseLower] = 0x000229,[CaseTitle] = 0x000228,[CaseUpper] = 0x000228}}, - {0x000229, {[CaseLower] = 0x000229,[CaseTitle] = 0x000228,[CaseUpper] = 0x000228}}, - {0x00022a, {[CaseLower] = 0x00022b,[CaseTitle] = 0x00022a,[CaseUpper] = 0x00022a}}, - {0x00022b, {[CaseLower] = 0x00022b,[CaseTitle] = 0x00022a,[CaseUpper] = 0x00022a}}, - {0x00022c, {[CaseLower] = 0x00022d,[CaseTitle] = 0x00022c,[CaseUpper] = 0x00022c}}, - {0x00022d, {[CaseLower] = 0x00022d,[CaseTitle] = 0x00022c,[CaseUpper] = 0x00022c}}, - {0x00022e, {[CaseLower] = 0x00022f,[CaseTitle] = 0x00022e,[CaseUpper] = 0x00022e}}, - {0x00022f, {[CaseLower] = 0x00022f,[CaseTitle] = 0x00022e,[CaseUpper] = 0x00022e}}, - {0x000230, {[CaseLower] = 0x000231,[CaseTitle] = 0x000230,[CaseUpper] = 0x000230}}, - {0x000231, {[CaseLower] = 0x000231,[CaseTitle] = 0x000230,[CaseUpper] = 0x000230}}, - {0x000232, {[CaseLower] = 0x000233,[CaseTitle] = 0x000232,[CaseUpper] = 0x000232}}, - {0x000233, {[CaseLower] = 0x000233,[CaseTitle] = 0x000232,[CaseUpper] = 0x000232}}, - {0x00023a, {[CaseLower] = 0x002c65,[CaseTitle] = 0x00023a,[CaseUpper] = 0x00023a}}, - {0x00023b, {[CaseLower] = 0x00023c,[CaseTitle] = 0x00023b,[CaseUpper] = 0x00023b}}, - {0x00023c, {[CaseLower] = 0x00023c,[CaseTitle] = 0x00023b,[CaseUpper] = 0x00023b}}, - {0x00023d, {[CaseLower] = 0x00019a,[CaseTitle] = 0x00023d,[CaseUpper] = 0x00023d}}, - {0x00023e, {[CaseLower] = 0x002c66,[CaseTitle] = 0x00023e,[CaseUpper] = 0x00023e}}, - {0x00023f, {[CaseLower] = 0x00023f,[CaseTitle] = 0x002c7e,[CaseUpper] = 0x002c7e}}, - {0x000240, {[CaseLower] = 0x000240,[CaseTitle] = 0x002c7f,[CaseUpper] = 0x002c7f}}, - {0x000241, {[CaseLower] = 0x000242,[CaseTitle] = 0x000241,[CaseUpper] = 0x000241}}, - {0x000242, {[CaseLower] = 0x000242,[CaseTitle] = 0x000241,[CaseUpper] = 0x000241}}, - {0x000243, {[CaseLower] = 0x000180,[CaseTitle] = 0x000243,[CaseUpper] = 0x000243}}, - {0x000244, {[CaseLower] = 0x000289,[CaseTitle] = 0x000244,[CaseUpper] = 0x000244}}, - {0x000245, {[CaseLower] = 0x00028c,[CaseTitle] = 0x000245,[CaseUpper] = 0x000245}}, - {0x000246, {[CaseLower] = 0x000247,[CaseTitle] = 0x000246,[CaseUpper] = 0x000246}}, - {0x000247, {[CaseLower] = 0x000247,[CaseTitle] = 0x000246,[CaseUpper] = 0x000246}}, - {0x000248, {[CaseLower] = 0x000249,[CaseTitle] = 0x000248,[CaseUpper] = 0x000248}}, - {0x000249, {[CaseLower] = 0x000249,[CaseTitle] = 0x000248,[CaseUpper] = 0x000248}}, - {0x00024a, {[CaseLower] = 0x00024b,[CaseTitle] = 0x00024a,[CaseUpper] = 0x00024a}}, - {0x00024b, {[CaseLower] = 0x00024b,[CaseTitle] = 0x00024a,[CaseUpper] = 0x00024a}}, - {0x00024c, {[CaseLower] = 0x00024d,[CaseTitle] = 0x00024c,[CaseUpper] = 0x00024c}}, - {0x00024d, {[CaseLower] = 0x00024d,[CaseTitle] = 0x00024c,[CaseUpper] = 0x00024c}}, - {0x00024e, {[CaseLower] = 0x00024f,[CaseTitle] = 0x00024e,[CaseUpper] = 0x00024e}}, - {0x00024f, {[CaseLower] = 0x00024f,[CaseTitle] = 0x00024e,[CaseUpper] = 0x00024e}}, - {0x000250, {[CaseLower] = 0x000250,[CaseTitle] = 0x002c6f,[CaseUpper] = 0x002c6f}}, - {0x000251, {[CaseLower] = 0x000251,[CaseTitle] = 0x002c6d,[CaseUpper] = 0x002c6d}}, - {0x000252, {[CaseLower] = 0x000252,[CaseTitle] = 0x002c70,[CaseUpper] = 0x002c70}}, - {0x000253, {[CaseLower] = 0x000253,[CaseTitle] = 0x000181,[CaseUpper] = 0x000181}}, - {0x000254, {[CaseLower] = 0x000254,[CaseTitle] = 0x000186,[CaseUpper] = 0x000186}}, - {0x000256, {[CaseLower] = 0x000256,[CaseTitle] = 0x000189,[CaseUpper] = 0x000189}}, - {0x000257, {[CaseLower] = 0x000257,[CaseTitle] = 0x00018a,[CaseUpper] = 0x00018a}}, - {0x000259, {[CaseLower] = 0x000259,[CaseTitle] = 0x00018f,[CaseUpper] = 0x00018f}}, - {0x00025b, {[CaseLower] = 0x00025b,[CaseTitle] = 0x000190,[CaseUpper] = 0x000190}}, - {0x00025c, {[CaseLower] = 0x00025c,[CaseTitle] = 0x00a7ab,[CaseUpper] = 0x00a7ab}}, - {0x000260, {[CaseLower] = 0x000260,[CaseTitle] = 0x000193,[CaseUpper] = 0x000193}}, - {0x000261, {[CaseLower] = 0x000261,[CaseTitle] = 0x00a7ac,[CaseUpper] = 0x00a7ac}}, - {0x000263, {[CaseLower] = 0x000263,[CaseTitle] = 0x000194,[CaseUpper] = 0x000194}}, - {0x000265, {[CaseLower] = 0x000265,[CaseTitle] = 0x00a78d,[CaseUpper] = 0x00a78d}}, - {0x000266, {[CaseLower] = 0x000266,[CaseTitle] = 0x00a7aa,[CaseUpper] = 0x00a7aa}}, - {0x000268, {[CaseLower] = 0x000268,[CaseTitle] = 0x000197,[CaseUpper] = 0x000197}}, - {0x000269, {[CaseLower] = 0x000269,[CaseTitle] = 0x000196,[CaseUpper] = 0x000196}}, - {0x00026a, {[CaseLower] = 0x00026a,[CaseTitle] = 0x00a7ae,[CaseUpper] = 0x00a7ae}}, - {0x00026b, {[CaseLower] = 0x00026b,[CaseTitle] = 0x002c62,[CaseUpper] = 0x002c62}}, - {0x00026c, {[CaseLower] = 0x00026c,[CaseTitle] = 0x00a7ad,[CaseUpper] = 0x00a7ad}}, - {0x00026f, {[CaseLower] = 0x00026f,[CaseTitle] = 0x00019c,[CaseUpper] = 0x00019c}}, - {0x000271, {[CaseLower] = 0x000271,[CaseTitle] = 0x002c6e,[CaseUpper] = 0x002c6e}}, - {0x000272, {[CaseLower] = 0x000272,[CaseTitle] = 0x00019d,[CaseUpper] = 0x00019d}}, - {0x000275, {[CaseLower] = 0x000275,[CaseTitle] = 0x00019f,[CaseUpper] = 0x00019f}}, - {0x00027d, {[CaseLower] = 0x00027d,[CaseTitle] = 0x002c64,[CaseUpper] = 0x002c64}}, - {0x000280, {[CaseLower] = 0x000280,[CaseTitle] = 0x0001a6,[CaseUpper] = 0x0001a6}}, - {0x000282, {[CaseLower] = 0x000282,[CaseTitle] = 0x00a7c5,[CaseUpper] = 0x00a7c5}}, - {0x000283, {[CaseLower] = 0x000283,[CaseTitle] = 0x0001a9,[CaseUpper] = 0x0001a9}}, - {0x000287, {[CaseLower] = 0x000287,[CaseTitle] = 0x00a7b1,[CaseUpper] = 0x00a7b1}}, - {0x000288, {[CaseLower] = 0x000288,[CaseTitle] = 0x0001ae,[CaseUpper] = 0x0001ae}}, - {0x000289, {[CaseLower] = 0x000289,[CaseTitle] = 0x000244,[CaseUpper] = 0x000244}}, - {0x00028a, {[CaseLower] = 0x00028a,[CaseTitle] = 0x0001b1,[CaseUpper] = 0x0001b1}}, - {0x00028b, {[CaseLower] = 0x00028b,[CaseTitle] = 0x0001b2,[CaseUpper] = 0x0001b2}}, - {0x00028c, {[CaseLower] = 0x00028c,[CaseTitle] = 0x000245,[CaseUpper] = 0x000245}}, - {0x000292, {[CaseLower] = 0x000292,[CaseTitle] = 0x0001b7,[CaseUpper] = 0x0001b7}}, - {0x00029d, {[CaseLower] = 0x00029d,[CaseTitle] = 0x00a7b2,[CaseUpper] = 0x00a7b2}}, - {0x00029e, {[CaseLower] = 0x00029e,[CaseTitle] = 0x00a7b0,[CaseUpper] = 0x00a7b0}}, - {0x000345, {[CaseLower] = 0x000345,[CaseTitle] = 0x000399,[CaseUpper] = 0x000399}}, - {0x000370, {[CaseLower] = 0x000371,[CaseTitle] = 0x000370,[CaseUpper] = 0x000370}}, - {0x000371, {[CaseLower] = 0x000371,[CaseTitle] = 0x000370,[CaseUpper] = 0x000370}}, - {0x000372, {[CaseLower] = 0x000373,[CaseTitle] = 0x000372,[CaseUpper] = 0x000372}}, - {0x000373, {[CaseLower] = 0x000373,[CaseTitle] = 0x000372,[CaseUpper] = 0x000372}}, - {0x000376, {[CaseLower] = 0x000377,[CaseTitle] = 0x000376,[CaseUpper] = 0x000376}}, - {0x000377, {[CaseLower] = 0x000377,[CaseTitle] = 0x000376,[CaseUpper] = 0x000376}}, - {0x00037b, {[CaseLower] = 0x00037b,[CaseTitle] = 0x0003fd,[CaseUpper] = 0x0003fd}}, - {0x00037c, {[CaseLower] = 0x00037c,[CaseTitle] = 0x0003fe,[CaseUpper] = 0x0003fe}}, - {0x00037d, {[CaseLower] = 0x00037d,[CaseTitle] = 0x0003ff,[CaseUpper] = 0x0003ff}}, - {0x00037f, {[CaseLower] = 0x0003f3,[CaseTitle] = 0x00037f,[CaseUpper] = 0x00037f}}, - {0x000386, {[CaseLower] = 0x0003ac,[CaseTitle] = 0x000386,[CaseUpper] = 0x000386}}, - {0x000388, {[CaseLower] = 0x0003ad,[CaseTitle] = 0x000388,[CaseUpper] = 0x000388}}, - {0x000389, {[CaseLower] = 0x0003ae,[CaseTitle] = 0x000389,[CaseUpper] = 0x000389}}, - {0x00038a, {[CaseLower] = 0x0003af,[CaseTitle] = 0x00038a,[CaseUpper] = 0x00038a}}, - {0x00038c, {[CaseLower] = 0x0003cc,[CaseTitle] = 0x00038c,[CaseUpper] = 0x00038c}}, - {0x00038e, {[CaseLower] = 0x0003cd,[CaseTitle] = 0x00038e,[CaseUpper] = 0x00038e}}, - {0x00038f, {[CaseLower] = 0x0003ce,[CaseTitle] = 0x00038f,[CaseUpper] = 0x00038f}}, - {0x000391, {[CaseLower] = 0x0003b1,[CaseTitle] = 0x000391,[CaseUpper] = 0x000391}}, - {0x000392, {[CaseLower] = 0x0003b2,[CaseTitle] = 0x000392,[CaseUpper] = 0x000392}}, - {0x000393, {[CaseLower] = 0x0003b3,[CaseTitle] = 0x000393,[CaseUpper] = 0x000393}}, - {0x000394, {[CaseLower] = 0x0003b4,[CaseTitle] = 0x000394,[CaseUpper] = 0x000394}}, - {0x000395, {[CaseLower] = 0x0003b5,[CaseTitle] = 0x000395,[CaseUpper] = 0x000395}}, - {0x000396, {[CaseLower] = 0x0003b6,[CaseTitle] = 0x000396,[CaseUpper] = 0x000396}}, - {0x000397, {[CaseLower] = 0x0003b7,[CaseTitle] = 0x000397,[CaseUpper] = 0x000397}}, - {0x000398, {[CaseLower] = 0x0003b8,[CaseTitle] = 0x000398,[CaseUpper] = 0x000398}}, - {0x000399, {[CaseLower] = 0x0003b9,[CaseTitle] = 0x000399,[CaseUpper] = 0x000399}}, - {0x00039a, {[CaseLower] = 0x0003ba,[CaseTitle] = 0x00039a,[CaseUpper] = 0x00039a}}, - {0x00039b, {[CaseLower] = 0x0003bb,[CaseTitle] = 0x00039b,[CaseUpper] = 0x00039b}}, - {0x00039c, {[CaseLower] = 0x0003bc,[CaseTitle] = 0x00039c,[CaseUpper] = 0x00039c}}, - {0x00039d, {[CaseLower] = 0x0003bd,[CaseTitle] = 0x00039d,[CaseUpper] = 0x00039d}}, - {0x00039e, {[CaseLower] = 0x0003be,[CaseTitle] = 0x00039e,[CaseUpper] = 0x00039e}}, - {0x00039f, {[CaseLower] = 0x0003bf,[CaseTitle] = 0x00039f,[CaseUpper] = 0x00039f}}, - {0x0003a0, {[CaseLower] = 0x0003c0,[CaseTitle] = 0x0003a0,[CaseUpper] = 0x0003a0}}, - {0x0003a1, {[CaseLower] = 0x0003c1,[CaseTitle] = 0x0003a1,[CaseUpper] = 0x0003a1}}, - {0x0003a3, {[CaseLower] = 0x0003c3,[CaseTitle] = 0x0003a3,[CaseUpper] = 0x0003a3}}, - {0x0003a4, {[CaseLower] = 0x0003c4,[CaseTitle] = 0x0003a4,[CaseUpper] = 0x0003a4}}, - {0x0003a5, {[CaseLower] = 0x0003c5,[CaseTitle] = 0x0003a5,[CaseUpper] = 0x0003a5}}, - {0x0003a6, {[CaseLower] = 0x0003c6,[CaseTitle] = 0x0003a6,[CaseUpper] = 0x0003a6}}, - {0x0003a7, {[CaseLower] = 0x0003c7,[CaseTitle] = 0x0003a7,[CaseUpper] = 0x0003a7}}, - {0x0003a8, {[CaseLower] = 0x0003c8,[CaseTitle] = 0x0003a8,[CaseUpper] = 0x0003a8}}, - {0x0003a9, {[CaseLower] = 0x0003c9,[CaseTitle] = 0x0003a9,[CaseUpper] = 0x0003a9}}, - {0x0003aa, {[CaseLower] = 0x0003ca,[CaseTitle] = 0x0003aa,[CaseUpper] = 0x0003aa}}, - {0x0003ab, {[CaseLower] = 0x0003cb,[CaseTitle] = 0x0003ab,[CaseUpper] = 0x0003ab}}, - {0x0003ac, {[CaseLower] = 0x0003ac,[CaseTitle] = 0x000386,[CaseUpper] = 0x000386}}, - {0x0003ad, {[CaseLower] = 0x0003ad,[CaseTitle] = 0x000388,[CaseUpper] = 0x000388}}, - {0x0003ae, {[CaseLower] = 0x0003ae,[CaseTitle] = 0x000389,[CaseUpper] = 0x000389}}, - {0x0003af, {[CaseLower] = 0x0003af,[CaseTitle] = 0x00038a,[CaseUpper] = 0x00038a}}, - {0x0003b1, {[CaseLower] = 0x0003b1,[CaseTitle] = 0x000391,[CaseUpper] = 0x000391}}, - {0x0003b2, {[CaseLower] = 0x0003b2,[CaseTitle] = 0x000392,[CaseUpper] = 0x000392}}, - {0x0003b3, {[CaseLower] = 0x0003b3,[CaseTitle] = 0x000393,[CaseUpper] = 0x000393}}, - {0x0003b4, {[CaseLower] = 0x0003b4,[CaseTitle] = 0x000394,[CaseUpper] = 0x000394}}, - {0x0003b5, {[CaseLower] = 0x0003b5,[CaseTitle] = 0x000395,[CaseUpper] = 0x000395}}, - {0x0003b6, {[CaseLower] = 0x0003b6,[CaseTitle] = 0x000396,[CaseUpper] = 0x000396}}, - {0x0003b7, {[CaseLower] = 0x0003b7,[CaseTitle] = 0x000397,[CaseUpper] = 0x000397}}, - {0x0003b8, {[CaseLower] = 0x0003b8,[CaseTitle] = 0x000398,[CaseUpper] = 0x000398}}, - {0x0003b9, {[CaseLower] = 0x0003b9,[CaseTitle] = 0x000399,[CaseUpper] = 0x000399}}, - {0x0003ba, {[CaseLower] = 0x0003ba,[CaseTitle] = 0x00039a,[CaseUpper] = 0x00039a}}, - {0x0003bb, {[CaseLower] = 0x0003bb,[CaseTitle] = 0x00039b,[CaseUpper] = 0x00039b}}, - {0x0003bc, {[CaseLower] = 0x0003bc,[CaseTitle] = 0x00039c,[CaseUpper] = 0x00039c}}, - {0x0003bd, {[CaseLower] = 0x0003bd,[CaseTitle] = 0x00039d,[CaseUpper] = 0x00039d}}, - {0x0003be, {[CaseLower] = 0x0003be,[CaseTitle] = 0x00039e,[CaseUpper] = 0x00039e}}, - {0x0003bf, {[CaseLower] = 0x0003bf,[CaseTitle] = 0x00039f,[CaseUpper] = 0x00039f}}, - {0x0003c0, {[CaseLower] = 0x0003c0,[CaseTitle] = 0x0003a0,[CaseUpper] = 0x0003a0}}, - {0x0003c1, {[CaseLower] = 0x0003c1,[CaseTitle] = 0x0003a1,[CaseUpper] = 0x0003a1}}, - {0x0003c2, {[CaseLower] = 0x0003c2,[CaseTitle] = 0x0003a3,[CaseUpper] = 0x0003a3}}, - {0x0003c3, {[CaseLower] = 0x0003c3,[CaseTitle] = 0x0003a3,[CaseUpper] = 0x0003a3}}, - {0x0003c4, {[CaseLower] = 0x0003c4,[CaseTitle] = 0x0003a4,[CaseUpper] = 0x0003a4}}, - {0x0003c5, {[CaseLower] = 0x0003c5,[CaseTitle] = 0x0003a5,[CaseUpper] = 0x0003a5}}, - {0x0003c6, {[CaseLower] = 0x0003c6,[CaseTitle] = 0x0003a6,[CaseUpper] = 0x0003a6}}, - {0x0003c7, {[CaseLower] = 0x0003c7,[CaseTitle] = 0x0003a7,[CaseUpper] = 0x0003a7}}, - {0x0003c8, {[CaseLower] = 0x0003c8,[CaseTitle] = 0x0003a8,[CaseUpper] = 0x0003a8}}, - {0x0003c9, {[CaseLower] = 0x0003c9,[CaseTitle] = 0x0003a9,[CaseUpper] = 0x0003a9}}, - {0x0003ca, {[CaseLower] = 0x0003ca,[CaseTitle] = 0x0003aa,[CaseUpper] = 0x0003aa}}, - {0x0003cb, {[CaseLower] = 0x0003cb,[CaseTitle] = 0x0003ab,[CaseUpper] = 0x0003ab}}, - {0x0003cc, {[CaseLower] = 0x0003cc,[CaseTitle] = 0x00038c,[CaseUpper] = 0x00038c}}, - {0x0003cd, {[CaseLower] = 0x0003cd,[CaseTitle] = 0x00038e,[CaseUpper] = 0x00038e}}, - {0x0003ce, {[CaseLower] = 0x0003ce,[CaseTitle] = 0x00038f,[CaseUpper] = 0x00038f}}, - {0x0003cf, {[CaseLower] = 0x0003d7,[CaseTitle] = 0x0003cf,[CaseUpper] = 0x0003cf}}, - {0x0003d0, {[CaseLower] = 0x0003d0,[CaseTitle] = 0x000392,[CaseUpper] = 0x000392}}, - {0x0003d1, {[CaseLower] = 0x0003d1,[CaseTitle] = 0x000398,[CaseUpper] = 0x000398}}, - {0x0003d5, {[CaseLower] = 0x0003d5,[CaseTitle] = 0x0003a6,[CaseUpper] = 0x0003a6}}, - {0x0003d6, {[CaseLower] = 0x0003d6,[CaseTitle] = 0x0003a0,[CaseUpper] = 0x0003a0}}, - {0x0003d7, {[CaseLower] = 0x0003d7,[CaseTitle] = 0x0003cf,[CaseUpper] = 0x0003cf}}, - {0x0003d8, {[CaseLower] = 0x0003d9,[CaseTitle] = 0x0003d8,[CaseUpper] = 0x0003d8}}, - {0x0003d9, {[CaseLower] = 0x0003d9,[CaseTitle] = 0x0003d8,[CaseUpper] = 0x0003d8}}, - {0x0003da, {[CaseLower] = 0x0003db,[CaseTitle] = 0x0003da,[CaseUpper] = 0x0003da}}, - {0x0003db, {[CaseLower] = 0x0003db,[CaseTitle] = 0x0003da,[CaseUpper] = 0x0003da}}, - {0x0003dc, {[CaseLower] = 0x0003dd,[CaseTitle] = 0x0003dc,[CaseUpper] = 0x0003dc}}, - {0x0003dd, {[CaseLower] = 0x0003dd,[CaseTitle] = 0x0003dc,[CaseUpper] = 0x0003dc}}, - {0x0003de, {[CaseLower] = 0x0003df,[CaseTitle] = 0x0003de,[CaseUpper] = 0x0003de}}, - {0x0003df, {[CaseLower] = 0x0003df,[CaseTitle] = 0x0003de,[CaseUpper] = 0x0003de}}, - {0x0003e0, {[CaseLower] = 0x0003e1,[CaseTitle] = 0x0003e0,[CaseUpper] = 0x0003e0}}, - {0x0003e1, {[CaseLower] = 0x0003e1,[CaseTitle] = 0x0003e0,[CaseUpper] = 0x0003e0}}, - {0x0003e2, {[CaseLower] = 0x0003e3,[CaseTitle] = 0x0003e2,[CaseUpper] = 0x0003e2}}, - {0x0003e3, {[CaseLower] = 0x0003e3,[CaseTitle] = 0x0003e2,[CaseUpper] = 0x0003e2}}, - {0x0003e4, {[CaseLower] = 0x0003e5,[CaseTitle] = 0x0003e4,[CaseUpper] = 0x0003e4}}, - {0x0003e5, {[CaseLower] = 0x0003e5,[CaseTitle] = 0x0003e4,[CaseUpper] = 0x0003e4}}, - {0x0003e6, {[CaseLower] = 0x0003e7,[CaseTitle] = 0x0003e6,[CaseUpper] = 0x0003e6}}, - {0x0003e7, {[CaseLower] = 0x0003e7,[CaseTitle] = 0x0003e6,[CaseUpper] = 0x0003e6}}, - {0x0003e8, {[CaseLower] = 0x0003e9,[CaseTitle] = 0x0003e8,[CaseUpper] = 0x0003e8}}, - {0x0003e9, {[CaseLower] = 0x0003e9,[CaseTitle] = 0x0003e8,[CaseUpper] = 0x0003e8}}, - {0x0003ea, {[CaseLower] = 0x0003eb,[CaseTitle] = 0x0003ea,[CaseUpper] = 0x0003ea}}, - {0x0003eb, {[CaseLower] = 0x0003eb,[CaseTitle] = 0x0003ea,[CaseUpper] = 0x0003ea}}, - {0x0003ec, {[CaseLower] = 0x0003ed,[CaseTitle] = 0x0003ec,[CaseUpper] = 0x0003ec}}, - {0x0003ed, {[CaseLower] = 0x0003ed,[CaseTitle] = 0x0003ec,[CaseUpper] = 0x0003ec}}, - {0x0003ee, {[CaseLower] = 0x0003ef,[CaseTitle] = 0x0003ee,[CaseUpper] = 0x0003ee}}, - {0x0003ef, {[CaseLower] = 0x0003ef,[CaseTitle] = 0x0003ee,[CaseUpper] = 0x0003ee}}, - {0x0003f0, {[CaseLower] = 0x0003f0,[CaseTitle] = 0x00039a,[CaseUpper] = 0x00039a}}, - {0x0003f1, {[CaseLower] = 0x0003f1,[CaseTitle] = 0x0003a1,[CaseUpper] = 0x0003a1}}, - {0x0003f2, {[CaseLower] = 0x0003f2,[CaseTitle] = 0x0003f9,[CaseUpper] = 0x0003f9}}, - {0x0003f3, {[CaseLower] = 0x0003f3,[CaseTitle] = 0x00037f,[CaseUpper] = 0x00037f}}, - {0x0003f4, {[CaseLower] = 0x0003b8,[CaseTitle] = 0x0003f4,[CaseUpper] = 0x0003f4}}, - {0x0003f5, {[CaseLower] = 0x0003f5,[CaseTitle] = 0x000395,[CaseUpper] = 0x000395}}, - {0x0003f7, {[CaseLower] = 0x0003f8,[CaseTitle] = 0x0003f7,[CaseUpper] = 0x0003f7}}, - {0x0003f8, {[CaseLower] = 0x0003f8,[CaseTitle] = 0x0003f7,[CaseUpper] = 0x0003f7}}, - {0x0003f9, {[CaseLower] = 0x0003f2,[CaseTitle] = 0x0003f9,[CaseUpper] = 0x0003f9}}, - {0x0003fa, {[CaseLower] = 0x0003fb,[CaseTitle] = 0x0003fa,[CaseUpper] = 0x0003fa}}, - {0x0003fb, {[CaseLower] = 0x0003fb,[CaseTitle] = 0x0003fa,[CaseUpper] = 0x0003fa}}, - {0x0003fd, {[CaseLower] = 0x00037b,[CaseTitle] = 0x0003fd,[CaseUpper] = 0x0003fd}}, - {0x0003fe, {[CaseLower] = 0x00037c,[CaseTitle] = 0x0003fe,[CaseUpper] = 0x0003fe}}, - {0x0003ff, {[CaseLower] = 0x00037d,[CaseTitle] = 0x0003ff,[CaseUpper] = 0x0003ff}}, - {0x000400, {[CaseLower] = 0x000450,[CaseTitle] = 0x000400,[CaseUpper] = 0x000400}}, - {0x000401, {[CaseLower] = 0x000451,[CaseTitle] = 0x000401,[CaseUpper] = 0x000401}}, - {0x000402, {[CaseLower] = 0x000452,[CaseTitle] = 0x000402,[CaseUpper] = 0x000402}}, - {0x000403, {[CaseLower] = 0x000453,[CaseTitle] = 0x000403,[CaseUpper] = 0x000403}}, - {0x000404, {[CaseLower] = 0x000454,[CaseTitle] = 0x000404,[CaseUpper] = 0x000404}}, - {0x000405, {[CaseLower] = 0x000455,[CaseTitle] = 0x000405,[CaseUpper] = 0x000405}}, - {0x000406, {[CaseLower] = 0x000456,[CaseTitle] = 0x000406,[CaseUpper] = 0x000406}}, - {0x000407, {[CaseLower] = 0x000457,[CaseTitle] = 0x000407,[CaseUpper] = 0x000407}}, - {0x000408, {[CaseLower] = 0x000458,[CaseTitle] = 0x000408,[CaseUpper] = 0x000408}}, - {0x000409, {[CaseLower] = 0x000459,[CaseTitle] = 0x000409,[CaseUpper] = 0x000409}}, - {0x00040a, {[CaseLower] = 0x00045a,[CaseTitle] = 0x00040a,[CaseUpper] = 0x00040a}}, - {0x00040b, {[CaseLower] = 0x00045b,[CaseTitle] = 0x00040b,[CaseUpper] = 0x00040b}}, - {0x00040c, {[CaseLower] = 0x00045c,[CaseTitle] = 0x00040c,[CaseUpper] = 0x00040c}}, - {0x00040d, {[CaseLower] = 0x00045d,[CaseTitle] = 0x00040d,[CaseUpper] = 0x00040d}}, - {0x00040e, {[CaseLower] = 0x00045e,[CaseTitle] = 0x00040e,[CaseUpper] = 0x00040e}}, - {0x00040f, {[CaseLower] = 0x00045f,[CaseTitle] = 0x00040f,[CaseUpper] = 0x00040f}}, - {0x000410, {[CaseLower] = 0x000430,[CaseTitle] = 0x000410,[CaseUpper] = 0x000410}}, - {0x000411, {[CaseLower] = 0x000431,[CaseTitle] = 0x000411,[CaseUpper] = 0x000411}}, - {0x000412, {[CaseLower] = 0x000432,[CaseTitle] = 0x000412,[CaseUpper] = 0x000412}}, - {0x000413, {[CaseLower] = 0x000433,[CaseTitle] = 0x000413,[CaseUpper] = 0x000413}}, - {0x000414, {[CaseLower] = 0x000434,[CaseTitle] = 0x000414,[CaseUpper] = 0x000414}}, - {0x000415, {[CaseLower] = 0x000435,[CaseTitle] = 0x000415,[CaseUpper] = 0x000415}}, - {0x000416, {[CaseLower] = 0x000436,[CaseTitle] = 0x000416,[CaseUpper] = 0x000416}}, - {0x000417, {[CaseLower] = 0x000437,[CaseTitle] = 0x000417,[CaseUpper] = 0x000417}}, - {0x000418, {[CaseLower] = 0x000438,[CaseTitle] = 0x000418,[CaseUpper] = 0x000418}}, - {0x000419, {[CaseLower] = 0x000439,[CaseTitle] = 0x000419,[CaseUpper] = 0x000419}}, - {0x00041a, {[CaseLower] = 0x00043a,[CaseTitle] = 0x00041a,[CaseUpper] = 0x00041a}}, - {0x00041b, {[CaseLower] = 0x00043b,[CaseTitle] = 0x00041b,[CaseUpper] = 0x00041b}}, - {0x00041c, {[CaseLower] = 0x00043c,[CaseTitle] = 0x00041c,[CaseUpper] = 0x00041c}}, - {0x00041d, {[CaseLower] = 0x00043d,[CaseTitle] = 0x00041d,[CaseUpper] = 0x00041d}}, - {0x00041e, {[CaseLower] = 0x00043e,[CaseTitle] = 0x00041e,[CaseUpper] = 0x00041e}}, - {0x00041f, {[CaseLower] = 0x00043f,[CaseTitle] = 0x00041f,[CaseUpper] = 0x00041f}}, - {0x000420, {[CaseLower] = 0x000440,[CaseTitle] = 0x000420,[CaseUpper] = 0x000420}}, - {0x000421, {[CaseLower] = 0x000441,[CaseTitle] = 0x000421,[CaseUpper] = 0x000421}}, - {0x000422, {[CaseLower] = 0x000442,[CaseTitle] = 0x000422,[CaseUpper] = 0x000422}}, - {0x000423, {[CaseLower] = 0x000443,[CaseTitle] = 0x000423,[CaseUpper] = 0x000423}}, - {0x000424, {[CaseLower] = 0x000444,[CaseTitle] = 0x000424,[CaseUpper] = 0x000424}}, - {0x000425, {[CaseLower] = 0x000445,[CaseTitle] = 0x000425,[CaseUpper] = 0x000425}}, - {0x000426, {[CaseLower] = 0x000446,[CaseTitle] = 0x000426,[CaseUpper] = 0x000426}}, - {0x000427, {[CaseLower] = 0x000447,[CaseTitle] = 0x000427,[CaseUpper] = 0x000427}}, - {0x000428, {[CaseLower] = 0x000448,[CaseTitle] = 0x000428,[CaseUpper] = 0x000428}}, - {0x000429, {[CaseLower] = 0x000449,[CaseTitle] = 0x000429,[CaseUpper] = 0x000429}}, - {0x00042a, {[CaseLower] = 0x00044a,[CaseTitle] = 0x00042a,[CaseUpper] = 0x00042a}}, - {0x00042b, {[CaseLower] = 0x00044b,[CaseTitle] = 0x00042b,[CaseUpper] = 0x00042b}}, - {0x00042c, {[CaseLower] = 0x00044c,[CaseTitle] = 0x00042c,[CaseUpper] = 0x00042c}}, - {0x00042d, {[CaseLower] = 0x00044d,[CaseTitle] = 0x00042d,[CaseUpper] = 0x00042d}}, - {0x00042e, {[CaseLower] = 0x00044e,[CaseTitle] = 0x00042e,[CaseUpper] = 0x00042e}}, - {0x00042f, {[CaseLower] = 0x00044f,[CaseTitle] = 0x00042f,[CaseUpper] = 0x00042f}}, - {0x000430, {[CaseLower] = 0x000430,[CaseTitle] = 0x000410,[CaseUpper] = 0x000410}}, - {0x000431, {[CaseLower] = 0x000431,[CaseTitle] = 0x000411,[CaseUpper] = 0x000411}}, - {0x000432, {[CaseLower] = 0x000432,[CaseTitle] = 0x000412,[CaseUpper] = 0x000412}}, - {0x000433, {[CaseLower] = 0x000433,[CaseTitle] = 0x000413,[CaseUpper] = 0x000413}}, - {0x000434, {[CaseLower] = 0x000434,[CaseTitle] = 0x000414,[CaseUpper] = 0x000414}}, - {0x000435, {[CaseLower] = 0x000435,[CaseTitle] = 0x000415,[CaseUpper] = 0x000415}}, - {0x000436, {[CaseLower] = 0x000436,[CaseTitle] = 0x000416,[CaseUpper] = 0x000416}}, - {0x000437, {[CaseLower] = 0x000437,[CaseTitle] = 0x000417,[CaseUpper] = 0x000417}}, - {0x000438, {[CaseLower] = 0x000438,[CaseTitle] = 0x000418,[CaseUpper] = 0x000418}}, - {0x000439, {[CaseLower] = 0x000439,[CaseTitle] = 0x000419,[CaseUpper] = 0x000419}}, - {0x00043a, {[CaseLower] = 0x00043a,[CaseTitle] = 0x00041a,[CaseUpper] = 0x00041a}}, - {0x00043b, {[CaseLower] = 0x00043b,[CaseTitle] = 0x00041b,[CaseUpper] = 0x00041b}}, - {0x00043c, {[CaseLower] = 0x00043c,[CaseTitle] = 0x00041c,[CaseUpper] = 0x00041c}}, - {0x00043d, {[CaseLower] = 0x00043d,[CaseTitle] = 0x00041d,[CaseUpper] = 0x00041d}}, - {0x00043e, {[CaseLower] = 0x00043e,[CaseTitle] = 0x00041e,[CaseUpper] = 0x00041e}}, - {0x00043f, {[CaseLower] = 0x00043f,[CaseTitle] = 0x00041f,[CaseUpper] = 0x00041f}}, - {0x000440, {[CaseLower] = 0x000440,[CaseTitle] = 0x000420,[CaseUpper] = 0x000420}}, - {0x000441, {[CaseLower] = 0x000441,[CaseTitle] = 0x000421,[CaseUpper] = 0x000421}}, - {0x000442, {[CaseLower] = 0x000442,[CaseTitle] = 0x000422,[CaseUpper] = 0x000422}}, - {0x000443, {[CaseLower] = 0x000443,[CaseTitle] = 0x000423,[CaseUpper] = 0x000423}}, - {0x000444, {[CaseLower] = 0x000444,[CaseTitle] = 0x000424,[CaseUpper] = 0x000424}}, - {0x000445, {[CaseLower] = 0x000445,[CaseTitle] = 0x000425,[CaseUpper] = 0x000425}}, - {0x000446, {[CaseLower] = 0x000446,[CaseTitle] = 0x000426,[CaseUpper] = 0x000426}}, - {0x000447, {[CaseLower] = 0x000447,[CaseTitle] = 0x000427,[CaseUpper] = 0x000427}}, - {0x000448, {[CaseLower] = 0x000448,[CaseTitle] = 0x000428,[CaseUpper] = 0x000428}}, - {0x000449, {[CaseLower] = 0x000449,[CaseTitle] = 0x000429,[CaseUpper] = 0x000429}}, - {0x00044a, {[CaseLower] = 0x00044a,[CaseTitle] = 0x00042a,[CaseUpper] = 0x00042a}}, - {0x00044b, {[CaseLower] = 0x00044b,[CaseTitle] = 0x00042b,[CaseUpper] = 0x00042b}}, - {0x00044c, {[CaseLower] = 0x00044c,[CaseTitle] = 0x00042c,[CaseUpper] = 0x00042c}}, - {0x00044d, {[CaseLower] = 0x00044d,[CaseTitle] = 0x00042d,[CaseUpper] = 0x00042d}}, - {0x00044e, {[CaseLower] = 0x00044e,[CaseTitle] = 0x00042e,[CaseUpper] = 0x00042e}}, - {0x00044f, {[CaseLower] = 0x00044f,[CaseTitle] = 0x00042f,[CaseUpper] = 0x00042f}}, - {0x000450, {[CaseLower] = 0x000450,[CaseTitle] = 0x000400,[CaseUpper] = 0x000400}}, - {0x000451, {[CaseLower] = 0x000451,[CaseTitle] = 0x000401,[CaseUpper] = 0x000401}}, - {0x000452, {[CaseLower] = 0x000452,[CaseTitle] = 0x000402,[CaseUpper] = 0x000402}}, - {0x000453, {[CaseLower] = 0x000453,[CaseTitle] = 0x000403,[CaseUpper] = 0x000403}}, - {0x000454, {[CaseLower] = 0x000454,[CaseTitle] = 0x000404,[CaseUpper] = 0x000404}}, - {0x000455, {[CaseLower] = 0x000455,[CaseTitle] = 0x000405,[CaseUpper] = 0x000405}}, - {0x000456, {[CaseLower] = 0x000456,[CaseTitle] = 0x000406,[CaseUpper] = 0x000406}}, - {0x000457, {[CaseLower] = 0x000457,[CaseTitle] = 0x000407,[CaseUpper] = 0x000407}}, - {0x000458, {[CaseLower] = 0x000458,[CaseTitle] = 0x000408,[CaseUpper] = 0x000408}}, - {0x000459, {[CaseLower] = 0x000459,[CaseTitle] = 0x000409,[CaseUpper] = 0x000409}}, - {0x00045a, {[CaseLower] = 0x00045a,[CaseTitle] = 0x00040a,[CaseUpper] = 0x00040a}}, - {0x00045b, {[CaseLower] = 0x00045b,[CaseTitle] = 0x00040b,[CaseUpper] = 0x00040b}}, - {0x00045c, {[CaseLower] = 0x00045c,[CaseTitle] = 0x00040c,[CaseUpper] = 0x00040c}}, - {0x00045d, {[CaseLower] = 0x00045d,[CaseTitle] = 0x00040d,[CaseUpper] = 0x00040d}}, - {0x00045e, {[CaseLower] = 0x00045e,[CaseTitle] = 0x00040e,[CaseUpper] = 0x00040e}}, - {0x00045f, {[CaseLower] = 0x00045f,[CaseTitle] = 0x00040f,[CaseUpper] = 0x00040f}}, - {0x000460, {[CaseLower] = 0x000461,[CaseTitle] = 0x000460,[CaseUpper] = 0x000460}}, - {0x000461, {[CaseLower] = 0x000461,[CaseTitle] = 0x000460,[CaseUpper] = 0x000460}}, - {0x000462, {[CaseLower] = 0x000463,[CaseTitle] = 0x000462,[CaseUpper] = 0x000462}}, - {0x000463, {[CaseLower] = 0x000463,[CaseTitle] = 0x000462,[CaseUpper] = 0x000462}}, - {0x000464, {[CaseLower] = 0x000465,[CaseTitle] = 0x000464,[CaseUpper] = 0x000464}}, - {0x000465, {[CaseLower] = 0x000465,[CaseTitle] = 0x000464,[CaseUpper] = 0x000464}}, - {0x000466, {[CaseLower] = 0x000467,[CaseTitle] = 0x000466,[CaseUpper] = 0x000466}}, - {0x000467, {[CaseLower] = 0x000467,[CaseTitle] = 0x000466,[CaseUpper] = 0x000466}}, - {0x000468, {[CaseLower] = 0x000469,[CaseTitle] = 0x000468,[CaseUpper] = 0x000468}}, - {0x000469, {[CaseLower] = 0x000469,[CaseTitle] = 0x000468,[CaseUpper] = 0x000468}}, - {0x00046a, {[CaseLower] = 0x00046b,[CaseTitle] = 0x00046a,[CaseUpper] = 0x00046a}}, - {0x00046b, {[CaseLower] = 0x00046b,[CaseTitle] = 0x00046a,[CaseUpper] = 0x00046a}}, - {0x00046c, {[CaseLower] = 0x00046d,[CaseTitle] = 0x00046c,[CaseUpper] = 0x00046c}}, - {0x00046d, {[CaseLower] = 0x00046d,[CaseTitle] = 0x00046c,[CaseUpper] = 0x00046c}}, - {0x00046e, {[CaseLower] = 0x00046f,[CaseTitle] = 0x00046e,[CaseUpper] = 0x00046e}}, - {0x00046f, {[CaseLower] = 0x00046f,[CaseTitle] = 0x00046e,[CaseUpper] = 0x00046e}}, - {0x000470, {[CaseLower] = 0x000471,[CaseTitle] = 0x000470,[CaseUpper] = 0x000470}}, - {0x000471, {[CaseLower] = 0x000471,[CaseTitle] = 0x000470,[CaseUpper] = 0x000470}}, - {0x000472, {[CaseLower] = 0x000473,[CaseTitle] = 0x000472,[CaseUpper] = 0x000472}}, - {0x000473, {[CaseLower] = 0x000473,[CaseTitle] = 0x000472,[CaseUpper] = 0x000472}}, - {0x000474, {[CaseLower] = 0x000475,[CaseTitle] = 0x000474,[CaseUpper] = 0x000474}}, - {0x000475, {[CaseLower] = 0x000475,[CaseTitle] = 0x000474,[CaseUpper] = 0x000474}}, - {0x000476, {[CaseLower] = 0x000477,[CaseTitle] = 0x000476,[CaseUpper] = 0x000476}}, - {0x000477, {[CaseLower] = 0x000477,[CaseTitle] = 0x000476,[CaseUpper] = 0x000476}}, - {0x000478, {[CaseLower] = 0x000479,[CaseTitle] = 0x000478,[CaseUpper] = 0x000478}}, - {0x000479, {[CaseLower] = 0x000479,[CaseTitle] = 0x000478,[CaseUpper] = 0x000478}}, - {0x00047a, {[CaseLower] = 0x00047b,[CaseTitle] = 0x00047a,[CaseUpper] = 0x00047a}}, - {0x00047b, {[CaseLower] = 0x00047b,[CaseTitle] = 0x00047a,[CaseUpper] = 0x00047a}}, - {0x00047c, {[CaseLower] = 0x00047d,[CaseTitle] = 0x00047c,[CaseUpper] = 0x00047c}}, - {0x00047d, {[CaseLower] = 0x00047d,[CaseTitle] = 0x00047c,[CaseUpper] = 0x00047c}}, - {0x00047e, {[CaseLower] = 0x00047f,[CaseTitle] = 0x00047e,[CaseUpper] = 0x00047e}}, - {0x00047f, {[CaseLower] = 0x00047f,[CaseTitle] = 0x00047e,[CaseUpper] = 0x00047e}}, - {0x000480, {[CaseLower] = 0x000481,[CaseTitle] = 0x000480,[CaseUpper] = 0x000480}}, - {0x000481, {[CaseLower] = 0x000481,[CaseTitle] = 0x000480,[CaseUpper] = 0x000480}}, - {0x00048a, {[CaseLower] = 0x00048b,[CaseTitle] = 0x00048a,[CaseUpper] = 0x00048a}}, - {0x00048b, {[CaseLower] = 0x00048b,[CaseTitle] = 0x00048a,[CaseUpper] = 0x00048a}}, - {0x00048c, {[CaseLower] = 0x00048d,[CaseTitle] = 0x00048c,[CaseUpper] = 0x00048c}}, - {0x00048d, {[CaseLower] = 0x00048d,[CaseTitle] = 0x00048c,[CaseUpper] = 0x00048c}}, - {0x00048e, {[CaseLower] = 0x00048f,[CaseTitle] = 0x00048e,[CaseUpper] = 0x00048e}}, - {0x00048f, {[CaseLower] = 0x00048f,[CaseTitle] = 0x00048e,[CaseUpper] = 0x00048e}}, - {0x000490, {[CaseLower] = 0x000491,[CaseTitle] = 0x000490,[CaseUpper] = 0x000490}}, - {0x000491, {[CaseLower] = 0x000491,[CaseTitle] = 0x000490,[CaseUpper] = 0x000490}}, - {0x000492, {[CaseLower] = 0x000493,[CaseTitle] = 0x000492,[CaseUpper] = 0x000492}}, - {0x000493, {[CaseLower] = 0x000493,[CaseTitle] = 0x000492,[CaseUpper] = 0x000492}}, - {0x000494, {[CaseLower] = 0x000495,[CaseTitle] = 0x000494,[CaseUpper] = 0x000494}}, - {0x000495, {[CaseLower] = 0x000495,[CaseTitle] = 0x000494,[CaseUpper] = 0x000494}}, - {0x000496, {[CaseLower] = 0x000497,[CaseTitle] = 0x000496,[CaseUpper] = 0x000496}}, - {0x000497, {[CaseLower] = 0x000497,[CaseTitle] = 0x000496,[CaseUpper] = 0x000496}}, - {0x000498, {[CaseLower] = 0x000499,[CaseTitle] = 0x000498,[CaseUpper] = 0x000498}}, - {0x000499, {[CaseLower] = 0x000499,[CaseTitle] = 0x000498,[CaseUpper] = 0x000498}}, - {0x00049a, {[CaseLower] = 0x00049b,[CaseTitle] = 0x00049a,[CaseUpper] = 0x00049a}}, - {0x00049b, {[CaseLower] = 0x00049b,[CaseTitle] = 0x00049a,[CaseUpper] = 0x00049a}}, - {0x00049c, {[CaseLower] = 0x00049d,[CaseTitle] = 0x00049c,[CaseUpper] = 0x00049c}}, - {0x00049d, {[CaseLower] = 0x00049d,[CaseTitle] = 0x00049c,[CaseUpper] = 0x00049c}}, - {0x00049e, {[CaseLower] = 0x00049f,[CaseTitle] = 0x00049e,[CaseUpper] = 0x00049e}}, - {0x00049f, {[CaseLower] = 0x00049f,[CaseTitle] = 0x00049e,[CaseUpper] = 0x00049e}}, - {0x0004a0, {[CaseLower] = 0x0004a1,[CaseTitle] = 0x0004a0,[CaseUpper] = 0x0004a0}}, - {0x0004a1, {[CaseLower] = 0x0004a1,[CaseTitle] = 0x0004a0,[CaseUpper] = 0x0004a0}}, - {0x0004a2, {[CaseLower] = 0x0004a3,[CaseTitle] = 0x0004a2,[CaseUpper] = 0x0004a2}}, - {0x0004a3, {[CaseLower] = 0x0004a3,[CaseTitle] = 0x0004a2,[CaseUpper] = 0x0004a2}}, - {0x0004a4, {[CaseLower] = 0x0004a5,[CaseTitle] = 0x0004a4,[CaseUpper] = 0x0004a4}}, - {0x0004a5, {[CaseLower] = 0x0004a5,[CaseTitle] = 0x0004a4,[CaseUpper] = 0x0004a4}}, - {0x0004a6, {[CaseLower] = 0x0004a7,[CaseTitle] = 0x0004a6,[CaseUpper] = 0x0004a6}}, - {0x0004a7, {[CaseLower] = 0x0004a7,[CaseTitle] = 0x0004a6,[CaseUpper] = 0x0004a6}}, - {0x0004a8, {[CaseLower] = 0x0004a9,[CaseTitle] = 0x0004a8,[CaseUpper] = 0x0004a8}}, - {0x0004a9, {[CaseLower] = 0x0004a9,[CaseTitle] = 0x0004a8,[CaseUpper] = 0x0004a8}}, - {0x0004aa, {[CaseLower] = 0x0004ab,[CaseTitle] = 0x0004aa,[CaseUpper] = 0x0004aa}}, - {0x0004ab, {[CaseLower] = 0x0004ab,[CaseTitle] = 0x0004aa,[CaseUpper] = 0x0004aa}}, - {0x0004ac, {[CaseLower] = 0x0004ad,[CaseTitle] = 0x0004ac,[CaseUpper] = 0x0004ac}}, - {0x0004ad, {[CaseLower] = 0x0004ad,[CaseTitle] = 0x0004ac,[CaseUpper] = 0x0004ac}}, - {0x0004ae, {[CaseLower] = 0x0004af,[CaseTitle] = 0x0004ae,[CaseUpper] = 0x0004ae}}, - {0x0004af, {[CaseLower] = 0x0004af,[CaseTitle] = 0x0004ae,[CaseUpper] = 0x0004ae}}, - {0x0004b0, {[CaseLower] = 0x0004b1,[CaseTitle] = 0x0004b0,[CaseUpper] = 0x0004b0}}, - {0x0004b1, {[CaseLower] = 0x0004b1,[CaseTitle] = 0x0004b0,[CaseUpper] = 0x0004b0}}, - {0x0004b2, {[CaseLower] = 0x0004b3,[CaseTitle] = 0x0004b2,[CaseUpper] = 0x0004b2}}, - {0x0004b3, {[CaseLower] = 0x0004b3,[CaseTitle] = 0x0004b2,[CaseUpper] = 0x0004b2}}, - {0x0004b4, {[CaseLower] = 0x0004b5,[CaseTitle] = 0x0004b4,[CaseUpper] = 0x0004b4}}, - {0x0004b5, {[CaseLower] = 0x0004b5,[CaseTitle] = 0x0004b4,[CaseUpper] = 0x0004b4}}, - {0x0004b6, {[CaseLower] = 0x0004b7,[CaseTitle] = 0x0004b6,[CaseUpper] = 0x0004b6}}, - {0x0004b7, {[CaseLower] = 0x0004b7,[CaseTitle] = 0x0004b6,[CaseUpper] = 0x0004b6}}, - {0x0004b8, {[CaseLower] = 0x0004b9,[CaseTitle] = 0x0004b8,[CaseUpper] = 0x0004b8}}, - {0x0004b9, {[CaseLower] = 0x0004b9,[CaseTitle] = 0x0004b8,[CaseUpper] = 0x0004b8}}, - {0x0004ba, {[CaseLower] = 0x0004bb,[CaseTitle] = 0x0004ba,[CaseUpper] = 0x0004ba}}, - {0x0004bb, {[CaseLower] = 0x0004bb,[CaseTitle] = 0x0004ba,[CaseUpper] = 0x0004ba}}, - {0x0004bc, {[CaseLower] = 0x0004bd,[CaseTitle] = 0x0004bc,[CaseUpper] = 0x0004bc}}, - {0x0004bd, {[CaseLower] = 0x0004bd,[CaseTitle] = 0x0004bc,[CaseUpper] = 0x0004bc}}, - {0x0004be, {[CaseLower] = 0x0004bf,[CaseTitle] = 0x0004be,[CaseUpper] = 0x0004be}}, - {0x0004bf, {[CaseLower] = 0x0004bf,[CaseTitle] = 0x0004be,[CaseUpper] = 0x0004be}}, - {0x0004c0, {[CaseLower] = 0x0004cf,[CaseTitle] = 0x0004c0,[CaseUpper] = 0x0004c0}}, - {0x0004c1, {[CaseLower] = 0x0004c2,[CaseTitle] = 0x0004c1,[CaseUpper] = 0x0004c1}}, - {0x0004c2, {[CaseLower] = 0x0004c2,[CaseTitle] = 0x0004c1,[CaseUpper] = 0x0004c1}}, - {0x0004c3, {[CaseLower] = 0x0004c4,[CaseTitle] = 0x0004c3,[CaseUpper] = 0x0004c3}}, - {0x0004c4, {[CaseLower] = 0x0004c4,[CaseTitle] = 0x0004c3,[CaseUpper] = 0x0004c3}}, - {0x0004c5, {[CaseLower] = 0x0004c6,[CaseTitle] = 0x0004c5,[CaseUpper] = 0x0004c5}}, - {0x0004c6, {[CaseLower] = 0x0004c6,[CaseTitle] = 0x0004c5,[CaseUpper] = 0x0004c5}}, - {0x0004c7, {[CaseLower] = 0x0004c8,[CaseTitle] = 0x0004c7,[CaseUpper] = 0x0004c7}}, - {0x0004c8, {[CaseLower] = 0x0004c8,[CaseTitle] = 0x0004c7,[CaseUpper] = 0x0004c7}}, - {0x0004c9, {[CaseLower] = 0x0004ca,[CaseTitle] = 0x0004c9,[CaseUpper] = 0x0004c9}}, - {0x0004ca, {[CaseLower] = 0x0004ca,[CaseTitle] = 0x0004c9,[CaseUpper] = 0x0004c9}}, - {0x0004cb, {[CaseLower] = 0x0004cc,[CaseTitle] = 0x0004cb,[CaseUpper] = 0x0004cb}}, - {0x0004cc, {[CaseLower] = 0x0004cc,[CaseTitle] = 0x0004cb,[CaseUpper] = 0x0004cb}}, - {0x0004cd, {[CaseLower] = 0x0004ce,[CaseTitle] = 0x0004cd,[CaseUpper] = 0x0004cd}}, - {0x0004ce, {[CaseLower] = 0x0004ce,[CaseTitle] = 0x0004cd,[CaseUpper] = 0x0004cd}}, - {0x0004cf, {[CaseLower] = 0x0004cf,[CaseTitle] = 0x0004c0,[CaseUpper] = 0x0004c0}}, - {0x0004d0, {[CaseLower] = 0x0004d1,[CaseTitle] = 0x0004d0,[CaseUpper] = 0x0004d0}}, - {0x0004d1, {[CaseLower] = 0x0004d1,[CaseTitle] = 0x0004d0,[CaseUpper] = 0x0004d0}}, - {0x0004d2, {[CaseLower] = 0x0004d3,[CaseTitle] = 0x0004d2,[CaseUpper] = 0x0004d2}}, - {0x0004d3, {[CaseLower] = 0x0004d3,[CaseTitle] = 0x0004d2,[CaseUpper] = 0x0004d2}}, - {0x0004d4, {[CaseLower] = 0x0004d5,[CaseTitle] = 0x0004d4,[CaseUpper] = 0x0004d4}}, - {0x0004d5, {[CaseLower] = 0x0004d5,[CaseTitle] = 0x0004d4,[CaseUpper] = 0x0004d4}}, - {0x0004d6, {[CaseLower] = 0x0004d7,[CaseTitle] = 0x0004d6,[CaseUpper] = 0x0004d6}}, - {0x0004d7, {[CaseLower] = 0x0004d7,[CaseTitle] = 0x0004d6,[CaseUpper] = 0x0004d6}}, - {0x0004d8, {[CaseLower] = 0x0004d9,[CaseTitle] = 0x0004d8,[CaseUpper] = 0x0004d8}}, - {0x0004d9, {[CaseLower] = 0x0004d9,[CaseTitle] = 0x0004d8,[CaseUpper] = 0x0004d8}}, - {0x0004da, {[CaseLower] = 0x0004db,[CaseTitle] = 0x0004da,[CaseUpper] = 0x0004da}}, - {0x0004db, {[CaseLower] = 0x0004db,[CaseTitle] = 0x0004da,[CaseUpper] = 0x0004da}}, - {0x0004dc, {[CaseLower] = 0x0004dd,[CaseTitle] = 0x0004dc,[CaseUpper] = 0x0004dc}}, - {0x0004dd, {[CaseLower] = 0x0004dd,[CaseTitle] = 0x0004dc,[CaseUpper] = 0x0004dc}}, - {0x0004de, {[CaseLower] = 0x0004df,[CaseTitle] = 0x0004de,[CaseUpper] = 0x0004de}}, - {0x0004df, {[CaseLower] = 0x0004df,[CaseTitle] = 0x0004de,[CaseUpper] = 0x0004de}}, - {0x0004e0, {[CaseLower] = 0x0004e1,[CaseTitle] = 0x0004e0,[CaseUpper] = 0x0004e0}}, - {0x0004e1, {[CaseLower] = 0x0004e1,[CaseTitle] = 0x0004e0,[CaseUpper] = 0x0004e0}}, - {0x0004e2, {[CaseLower] = 0x0004e3,[CaseTitle] = 0x0004e2,[CaseUpper] = 0x0004e2}}, - {0x0004e3, {[CaseLower] = 0x0004e3,[CaseTitle] = 0x0004e2,[CaseUpper] = 0x0004e2}}, - {0x0004e4, {[CaseLower] = 0x0004e5,[CaseTitle] = 0x0004e4,[CaseUpper] = 0x0004e4}}, - {0x0004e5, {[CaseLower] = 0x0004e5,[CaseTitle] = 0x0004e4,[CaseUpper] = 0x0004e4}}, - {0x0004e6, {[CaseLower] = 0x0004e7,[CaseTitle] = 0x0004e6,[CaseUpper] = 0x0004e6}}, - {0x0004e7, {[CaseLower] = 0x0004e7,[CaseTitle] = 0x0004e6,[CaseUpper] = 0x0004e6}}, - {0x0004e8, {[CaseLower] = 0x0004e9,[CaseTitle] = 0x0004e8,[CaseUpper] = 0x0004e8}}, - {0x0004e9, {[CaseLower] = 0x0004e9,[CaseTitle] = 0x0004e8,[CaseUpper] = 0x0004e8}}, - {0x0004ea, {[CaseLower] = 0x0004eb,[CaseTitle] = 0x0004ea,[CaseUpper] = 0x0004ea}}, - {0x0004eb, {[CaseLower] = 0x0004eb,[CaseTitle] = 0x0004ea,[CaseUpper] = 0x0004ea}}, - {0x0004ec, {[CaseLower] = 0x0004ed,[CaseTitle] = 0x0004ec,[CaseUpper] = 0x0004ec}}, - {0x0004ed, {[CaseLower] = 0x0004ed,[CaseTitle] = 0x0004ec,[CaseUpper] = 0x0004ec}}, - {0x0004ee, {[CaseLower] = 0x0004ef,[CaseTitle] = 0x0004ee,[CaseUpper] = 0x0004ee}}, - {0x0004ef, {[CaseLower] = 0x0004ef,[CaseTitle] = 0x0004ee,[CaseUpper] = 0x0004ee}}, - {0x0004f0, {[CaseLower] = 0x0004f1,[CaseTitle] = 0x0004f0,[CaseUpper] = 0x0004f0}}, - {0x0004f1, {[CaseLower] = 0x0004f1,[CaseTitle] = 0x0004f0,[CaseUpper] = 0x0004f0}}, - {0x0004f2, {[CaseLower] = 0x0004f3,[CaseTitle] = 0x0004f2,[CaseUpper] = 0x0004f2}}, - {0x0004f3, {[CaseLower] = 0x0004f3,[CaseTitle] = 0x0004f2,[CaseUpper] = 0x0004f2}}, - {0x0004f4, {[CaseLower] = 0x0004f5,[CaseTitle] = 0x0004f4,[CaseUpper] = 0x0004f4}}, - {0x0004f5, {[CaseLower] = 0x0004f5,[CaseTitle] = 0x0004f4,[CaseUpper] = 0x0004f4}}, - {0x0004f6, {[CaseLower] = 0x0004f7,[CaseTitle] = 0x0004f6,[CaseUpper] = 0x0004f6}}, - {0x0004f7, {[CaseLower] = 0x0004f7,[CaseTitle] = 0x0004f6,[CaseUpper] = 0x0004f6}}, - {0x0004f8, {[CaseLower] = 0x0004f9,[CaseTitle] = 0x0004f8,[CaseUpper] = 0x0004f8}}, - {0x0004f9, {[CaseLower] = 0x0004f9,[CaseTitle] = 0x0004f8,[CaseUpper] = 0x0004f8}}, - {0x0004fa, {[CaseLower] = 0x0004fb,[CaseTitle] = 0x0004fa,[CaseUpper] = 0x0004fa}}, - {0x0004fb, {[CaseLower] = 0x0004fb,[CaseTitle] = 0x0004fa,[CaseUpper] = 0x0004fa}}, - {0x0004fc, {[CaseLower] = 0x0004fd,[CaseTitle] = 0x0004fc,[CaseUpper] = 0x0004fc}}, - {0x0004fd, {[CaseLower] = 0x0004fd,[CaseTitle] = 0x0004fc,[CaseUpper] = 0x0004fc}}, - {0x0004fe, {[CaseLower] = 0x0004ff,[CaseTitle] = 0x0004fe,[CaseUpper] = 0x0004fe}}, - {0x0004ff, {[CaseLower] = 0x0004ff,[CaseTitle] = 0x0004fe,[CaseUpper] = 0x0004fe}}, - {0x000500, {[CaseLower] = 0x000501,[CaseTitle] = 0x000500,[CaseUpper] = 0x000500}}, - {0x000501, {[CaseLower] = 0x000501,[CaseTitle] = 0x000500,[CaseUpper] = 0x000500}}, - {0x000502, {[CaseLower] = 0x000503,[CaseTitle] = 0x000502,[CaseUpper] = 0x000502}}, - {0x000503, {[CaseLower] = 0x000503,[CaseTitle] = 0x000502,[CaseUpper] = 0x000502}}, - {0x000504, {[CaseLower] = 0x000505,[CaseTitle] = 0x000504,[CaseUpper] = 0x000504}}, - {0x000505, {[CaseLower] = 0x000505,[CaseTitle] = 0x000504,[CaseUpper] = 0x000504}}, - {0x000506, {[CaseLower] = 0x000507,[CaseTitle] = 0x000506,[CaseUpper] = 0x000506}}, - {0x000507, {[CaseLower] = 0x000507,[CaseTitle] = 0x000506,[CaseUpper] = 0x000506}}, - {0x000508, {[CaseLower] = 0x000509,[CaseTitle] = 0x000508,[CaseUpper] = 0x000508}}, - {0x000509, {[CaseLower] = 0x000509,[CaseTitle] = 0x000508,[CaseUpper] = 0x000508}}, - {0x00050a, {[CaseLower] = 0x00050b,[CaseTitle] = 0x00050a,[CaseUpper] = 0x00050a}}, - {0x00050b, {[CaseLower] = 0x00050b,[CaseTitle] = 0x00050a,[CaseUpper] = 0x00050a}}, - {0x00050c, {[CaseLower] = 0x00050d,[CaseTitle] = 0x00050c,[CaseUpper] = 0x00050c}}, - {0x00050d, {[CaseLower] = 0x00050d,[CaseTitle] = 0x00050c,[CaseUpper] = 0x00050c}}, - {0x00050e, {[CaseLower] = 0x00050f,[CaseTitle] = 0x00050e,[CaseUpper] = 0x00050e}}, - {0x00050f, {[CaseLower] = 0x00050f,[CaseTitle] = 0x00050e,[CaseUpper] = 0x00050e}}, - {0x000510, {[CaseLower] = 0x000511,[CaseTitle] = 0x000510,[CaseUpper] = 0x000510}}, - {0x000511, {[CaseLower] = 0x000511,[CaseTitle] = 0x000510,[CaseUpper] = 0x000510}}, - {0x000512, {[CaseLower] = 0x000513,[CaseTitle] = 0x000512,[CaseUpper] = 0x000512}}, - {0x000513, {[CaseLower] = 0x000513,[CaseTitle] = 0x000512,[CaseUpper] = 0x000512}}, - {0x000514, {[CaseLower] = 0x000515,[CaseTitle] = 0x000514,[CaseUpper] = 0x000514}}, - {0x000515, {[CaseLower] = 0x000515,[CaseTitle] = 0x000514,[CaseUpper] = 0x000514}}, - {0x000516, {[CaseLower] = 0x000517,[CaseTitle] = 0x000516,[CaseUpper] = 0x000516}}, - {0x000517, {[CaseLower] = 0x000517,[CaseTitle] = 0x000516,[CaseUpper] = 0x000516}}, - {0x000518, {[CaseLower] = 0x000519,[CaseTitle] = 0x000518,[CaseUpper] = 0x000518}}, - {0x000519, {[CaseLower] = 0x000519,[CaseTitle] = 0x000518,[CaseUpper] = 0x000518}}, - {0x00051a, {[CaseLower] = 0x00051b,[CaseTitle] = 0x00051a,[CaseUpper] = 0x00051a}}, - {0x00051b, {[CaseLower] = 0x00051b,[CaseTitle] = 0x00051a,[CaseUpper] = 0x00051a}}, - {0x00051c, {[CaseLower] = 0x00051d,[CaseTitle] = 0x00051c,[CaseUpper] = 0x00051c}}, - {0x00051d, {[CaseLower] = 0x00051d,[CaseTitle] = 0x00051c,[CaseUpper] = 0x00051c}}, - {0x00051e, {[CaseLower] = 0x00051f,[CaseTitle] = 0x00051e,[CaseUpper] = 0x00051e}}, - {0x00051f, {[CaseLower] = 0x00051f,[CaseTitle] = 0x00051e,[CaseUpper] = 0x00051e}}, - {0x000520, {[CaseLower] = 0x000521,[CaseTitle] = 0x000520,[CaseUpper] = 0x000520}}, - {0x000521, {[CaseLower] = 0x000521,[CaseTitle] = 0x000520,[CaseUpper] = 0x000520}}, - {0x000522, {[CaseLower] = 0x000523,[CaseTitle] = 0x000522,[CaseUpper] = 0x000522}}, - {0x000523, {[CaseLower] = 0x000523,[CaseTitle] = 0x000522,[CaseUpper] = 0x000522}}, - {0x000524, {[CaseLower] = 0x000525,[CaseTitle] = 0x000524,[CaseUpper] = 0x000524}}, - {0x000525, {[CaseLower] = 0x000525,[CaseTitle] = 0x000524,[CaseUpper] = 0x000524}}, - {0x000526, {[CaseLower] = 0x000527,[CaseTitle] = 0x000526,[CaseUpper] = 0x000526}}, - {0x000527, {[CaseLower] = 0x000527,[CaseTitle] = 0x000526,[CaseUpper] = 0x000526}}, - {0x000528, {[CaseLower] = 0x000529,[CaseTitle] = 0x000528,[CaseUpper] = 0x000528}}, - {0x000529, {[CaseLower] = 0x000529,[CaseTitle] = 0x000528,[CaseUpper] = 0x000528}}, - {0x00052a, {[CaseLower] = 0x00052b,[CaseTitle] = 0x00052a,[CaseUpper] = 0x00052a}}, - {0x00052b, {[CaseLower] = 0x00052b,[CaseTitle] = 0x00052a,[CaseUpper] = 0x00052a}}, - {0x00052c, {[CaseLower] = 0x00052d,[CaseTitle] = 0x00052c,[CaseUpper] = 0x00052c}}, - {0x00052d, {[CaseLower] = 0x00052d,[CaseTitle] = 0x00052c,[CaseUpper] = 0x00052c}}, - {0x00052e, {[CaseLower] = 0x00052f,[CaseTitle] = 0x00052e,[CaseUpper] = 0x00052e}}, - {0x00052f, {[CaseLower] = 0x00052f,[CaseTitle] = 0x00052e,[CaseUpper] = 0x00052e}}, - {0x000531, {[CaseLower] = 0x000561,[CaseTitle] = 0x000531,[CaseUpper] = 0x000531}}, - {0x000532, {[CaseLower] = 0x000562,[CaseTitle] = 0x000532,[CaseUpper] = 0x000532}}, - {0x000533, {[CaseLower] = 0x000563,[CaseTitle] = 0x000533,[CaseUpper] = 0x000533}}, - {0x000534, {[CaseLower] = 0x000564,[CaseTitle] = 0x000534,[CaseUpper] = 0x000534}}, - {0x000535, {[CaseLower] = 0x000565,[CaseTitle] = 0x000535,[CaseUpper] = 0x000535}}, - {0x000536, {[CaseLower] = 0x000566,[CaseTitle] = 0x000536,[CaseUpper] = 0x000536}}, - {0x000537, {[CaseLower] = 0x000567,[CaseTitle] = 0x000537,[CaseUpper] = 0x000537}}, - {0x000538, {[CaseLower] = 0x000568,[CaseTitle] = 0x000538,[CaseUpper] = 0x000538}}, - {0x000539, {[CaseLower] = 0x000569,[CaseTitle] = 0x000539,[CaseUpper] = 0x000539}}, - {0x00053a, {[CaseLower] = 0x00056a,[CaseTitle] = 0x00053a,[CaseUpper] = 0x00053a}}, - {0x00053b, {[CaseLower] = 0x00056b,[CaseTitle] = 0x00053b,[CaseUpper] = 0x00053b}}, - {0x00053c, {[CaseLower] = 0x00056c,[CaseTitle] = 0x00053c,[CaseUpper] = 0x00053c}}, - {0x00053d, {[CaseLower] = 0x00056d,[CaseTitle] = 0x00053d,[CaseUpper] = 0x00053d}}, - {0x00053e, {[CaseLower] = 0x00056e,[CaseTitle] = 0x00053e,[CaseUpper] = 0x00053e}}, - {0x00053f, {[CaseLower] = 0x00056f,[CaseTitle] = 0x00053f,[CaseUpper] = 0x00053f}}, - {0x000540, {[CaseLower] = 0x000570,[CaseTitle] = 0x000540,[CaseUpper] = 0x000540}}, - {0x000541, {[CaseLower] = 0x000571,[CaseTitle] = 0x000541,[CaseUpper] = 0x000541}}, - {0x000542, {[CaseLower] = 0x000572,[CaseTitle] = 0x000542,[CaseUpper] = 0x000542}}, - {0x000543, {[CaseLower] = 0x000573,[CaseTitle] = 0x000543,[CaseUpper] = 0x000543}}, - {0x000544, {[CaseLower] = 0x000574,[CaseTitle] = 0x000544,[CaseUpper] = 0x000544}}, - {0x000545, {[CaseLower] = 0x000575,[CaseTitle] = 0x000545,[CaseUpper] = 0x000545}}, - {0x000546, {[CaseLower] = 0x000576,[CaseTitle] = 0x000546,[CaseUpper] = 0x000546}}, - {0x000547, {[CaseLower] = 0x000577,[CaseTitle] = 0x000547,[CaseUpper] = 0x000547}}, - {0x000548, {[CaseLower] = 0x000578,[CaseTitle] = 0x000548,[CaseUpper] = 0x000548}}, - {0x000549, {[CaseLower] = 0x000579,[CaseTitle] = 0x000549,[CaseUpper] = 0x000549}}, - {0x00054a, {[CaseLower] = 0x00057a,[CaseTitle] = 0x00054a,[CaseUpper] = 0x00054a}}, - {0x00054b, {[CaseLower] = 0x00057b,[CaseTitle] = 0x00054b,[CaseUpper] = 0x00054b}}, - {0x00054c, {[CaseLower] = 0x00057c,[CaseTitle] = 0x00054c,[CaseUpper] = 0x00054c}}, - {0x00054d, {[CaseLower] = 0x00057d,[CaseTitle] = 0x00054d,[CaseUpper] = 0x00054d}}, - {0x00054e, {[CaseLower] = 0x00057e,[CaseTitle] = 0x00054e,[CaseUpper] = 0x00054e}}, - {0x00054f, {[CaseLower] = 0x00057f,[CaseTitle] = 0x00054f,[CaseUpper] = 0x00054f}}, - {0x000550, {[CaseLower] = 0x000580,[CaseTitle] = 0x000550,[CaseUpper] = 0x000550}}, - {0x000551, {[CaseLower] = 0x000581,[CaseTitle] = 0x000551,[CaseUpper] = 0x000551}}, - {0x000552, {[CaseLower] = 0x000582,[CaseTitle] = 0x000552,[CaseUpper] = 0x000552}}, - {0x000553, {[CaseLower] = 0x000583,[CaseTitle] = 0x000553,[CaseUpper] = 0x000553}}, - {0x000554, {[CaseLower] = 0x000584,[CaseTitle] = 0x000554,[CaseUpper] = 0x000554}}, - {0x000555, {[CaseLower] = 0x000585,[CaseTitle] = 0x000555,[CaseUpper] = 0x000555}}, - {0x000556, {[CaseLower] = 0x000586,[CaseTitle] = 0x000556,[CaseUpper] = 0x000556}}, - {0x000561, {[CaseLower] = 0x000561,[CaseTitle] = 0x000531,[CaseUpper] = 0x000531}}, - {0x000562, {[CaseLower] = 0x000562,[CaseTitle] = 0x000532,[CaseUpper] = 0x000532}}, - {0x000563, {[CaseLower] = 0x000563,[CaseTitle] = 0x000533,[CaseUpper] = 0x000533}}, - {0x000564, {[CaseLower] = 0x000564,[CaseTitle] = 0x000534,[CaseUpper] = 0x000534}}, - {0x000565, {[CaseLower] = 0x000565,[CaseTitle] = 0x000535,[CaseUpper] = 0x000535}}, - {0x000566, {[CaseLower] = 0x000566,[CaseTitle] = 0x000536,[CaseUpper] = 0x000536}}, - {0x000567, {[CaseLower] = 0x000567,[CaseTitle] = 0x000537,[CaseUpper] = 0x000537}}, - {0x000568, {[CaseLower] = 0x000568,[CaseTitle] = 0x000538,[CaseUpper] = 0x000538}}, - {0x000569, {[CaseLower] = 0x000569,[CaseTitle] = 0x000539,[CaseUpper] = 0x000539}}, - {0x00056a, {[CaseLower] = 0x00056a,[CaseTitle] = 0x00053a,[CaseUpper] = 0x00053a}}, - {0x00056b, {[CaseLower] = 0x00056b,[CaseTitle] = 0x00053b,[CaseUpper] = 0x00053b}}, - {0x00056c, {[CaseLower] = 0x00056c,[CaseTitle] = 0x00053c,[CaseUpper] = 0x00053c}}, - {0x00056d, {[CaseLower] = 0x00056d,[CaseTitle] = 0x00053d,[CaseUpper] = 0x00053d}}, - {0x00056e, {[CaseLower] = 0x00056e,[CaseTitle] = 0x00053e,[CaseUpper] = 0x00053e}}, - {0x00056f, {[CaseLower] = 0x00056f,[CaseTitle] = 0x00053f,[CaseUpper] = 0x00053f}}, - {0x000570, {[CaseLower] = 0x000570,[CaseTitle] = 0x000540,[CaseUpper] = 0x000540}}, - {0x000571, {[CaseLower] = 0x000571,[CaseTitle] = 0x000541,[CaseUpper] = 0x000541}}, - {0x000572, {[CaseLower] = 0x000572,[CaseTitle] = 0x000542,[CaseUpper] = 0x000542}}, - {0x000573, {[CaseLower] = 0x000573,[CaseTitle] = 0x000543,[CaseUpper] = 0x000543}}, - {0x000574, {[CaseLower] = 0x000574,[CaseTitle] = 0x000544,[CaseUpper] = 0x000544}}, - {0x000575, {[CaseLower] = 0x000575,[CaseTitle] = 0x000545,[CaseUpper] = 0x000545}}, - {0x000576, {[CaseLower] = 0x000576,[CaseTitle] = 0x000546,[CaseUpper] = 0x000546}}, - {0x000577, {[CaseLower] = 0x000577,[CaseTitle] = 0x000547,[CaseUpper] = 0x000547}}, - {0x000578, {[CaseLower] = 0x000578,[CaseTitle] = 0x000548,[CaseUpper] = 0x000548}}, - {0x000579, {[CaseLower] = 0x000579,[CaseTitle] = 0x000549,[CaseUpper] = 0x000549}}, - {0x00057a, {[CaseLower] = 0x00057a,[CaseTitle] = 0x00054a,[CaseUpper] = 0x00054a}}, - {0x00057b, {[CaseLower] = 0x00057b,[CaseTitle] = 0x00054b,[CaseUpper] = 0x00054b}}, - {0x00057c, {[CaseLower] = 0x00057c,[CaseTitle] = 0x00054c,[CaseUpper] = 0x00054c}}, - {0x00057d, {[CaseLower] = 0x00057d,[CaseTitle] = 0x00054d,[CaseUpper] = 0x00054d}}, - {0x00057e, {[CaseLower] = 0x00057e,[CaseTitle] = 0x00054e,[CaseUpper] = 0x00054e}}, - {0x00057f, {[CaseLower] = 0x00057f,[CaseTitle] = 0x00054f,[CaseUpper] = 0x00054f}}, - {0x000580, {[CaseLower] = 0x000580,[CaseTitle] = 0x000550,[CaseUpper] = 0x000550}}, - {0x000581, {[CaseLower] = 0x000581,[CaseTitle] = 0x000551,[CaseUpper] = 0x000551}}, - {0x000582, {[CaseLower] = 0x000582,[CaseTitle] = 0x000552,[CaseUpper] = 0x000552}}, - {0x000583, {[CaseLower] = 0x000583,[CaseTitle] = 0x000553,[CaseUpper] = 0x000553}}, - {0x000584, {[CaseLower] = 0x000584,[CaseTitle] = 0x000554,[CaseUpper] = 0x000554}}, - {0x000585, {[CaseLower] = 0x000585,[CaseTitle] = 0x000555,[CaseUpper] = 0x000555}}, - {0x000586, {[CaseLower] = 0x000586,[CaseTitle] = 0x000556,[CaseUpper] = 0x000556}}, - {0x0010a0, {[CaseLower] = 0x002d00,[CaseTitle] = 0x0010a0,[CaseUpper] = 0x0010a0}}, - {0x0010a1, {[CaseLower] = 0x002d01,[CaseTitle] = 0x0010a1,[CaseUpper] = 0x0010a1}}, - {0x0010a2, {[CaseLower] = 0x002d02,[CaseTitle] = 0x0010a2,[CaseUpper] = 0x0010a2}}, - {0x0010a3, {[CaseLower] = 0x002d03,[CaseTitle] = 0x0010a3,[CaseUpper] = 0x0010a3}}, - {0x0010a4, {[CaseLower] = 0x002d04,[CaseTitle] = 0x0010a4,[CaseUpper] = 0x0010a4}}, - {0x0010a5, {[CaseLower] = 0x002d05,[CaseTitle] = 0x0010a5,[CaseUpper] = 0x0010a5}}, - {0x0010a6, {[CaseLower] = 0x002d06,[CaseTitle] = 0x0010a6,[CaseUpper] = 0x0010a6}}, - {0x0010a7, {[CaseLower] = 0x002d07,[CaseTitle] = 0x0010a7,[CaseUpper] = 0x0010a7}}, - {0x0010a8, {[CaseLower] = 0x002d08,[CaseTitle] = 0x0010a8,[CaseUpper] = 0x0010a8}}, - {0x0010a9, {[CaseLower] = 0x002d09,[CaseTitle] = 0x0010a9,[CaseUpper] = 0x0010a9}}, - {0x0010aa, {[CaseLower] = 0x002d0a,[CaseTitle] = 0x0010aa,[CaseUpper] = 0x0010aa}}, - {0x0010ab, {[CaseLower] = 0x002d0b,[CaseTitle] = 0x0010ab,[CaseUpper] = 0x0010ab}}, - {0x0010ac, {[CaseLower] = 0x002d0c,[CaseTitle] = 0x0010ac,[CaseUpper] = 0x0010ac}}, - {0x0010ad, {[CaseLower] = 0x002d0d,[CaseTitle] = 0x0010ad,[CaseUpper] = 0x0010ad}}, - {0x0010ae, {[CaseLower] = 0x002d0e,[CaseTitle] = 0x0010ae,[CaseUpper] = 0x0010ae}}, - {0x0010af, {[CaseLower] = 0x002d0f,[CaseTitle] = 0x0010af,[CaseUpper] = 0x0010af}}, - {0x0010b0, {[CaseLower] = 0x002d10,[CaseTitle] = 0x0010b0,[CaseUpper] = 0x0010b0}}, - {0x0010b1, {[CaseLower] = 0x002d11,[CaseTitle] = 0x0010b1,[CaseUpper] = 0x0010b1}}, - {0x0010b2, {[CaseLower] = 0x002d12,[CaseTitle] = 0x0010b2,[CaseUpper] = 0x0010b2}}, - {0x0010b3, {[CaseLower] = 0x002d13,[CaseTitle] = 0x0010b3,[CaseUpper] = 0x0010b3}}, - {0x0010b4, {[CaseLower] = 0x002d14,[CaseTitle] = 0x0010b4,[CaseUpper] = 0x0010b4}}, - {0x0010b5, {[CaseLower] = 0x002d15,[CaseTitle] = 0x0010b5,[CaseUpper] = 0x0010b5}}, - {0x0010b6, {[CaseLower] = 0x002d16,[CaseTitle] = 0x0010b6,[CaseUpper] = 0x0010b6}}, - {0x0010b7, {[CaseLower] = 0x002d17,[CaseTitle] = 0x0010b7,[CaseUpper] = 0x0010b7}}, - {0x0010b8, {[CaseLower] = 0x002d18,[CaseTitle] = 0x0010b8,[CaseUpper] = 0x0010b8}}, - {0x0010b9, {[CaseLower] = 0x002d19,[CaseTitle] = 0x0010b9,[CaseUpper] = 0x0010b9}}, - {0x0010ba, {[CaseLower] = 0x002d1a,[CaseTitle] = 0x0010ba,[CaseUpper] = 0x0010ba}}, - {0x0010bb, {[CaseLower] = 0x002d1b,[CaseTitle] = 0x0010bb,[CaseUpper] = 0x0010bb}}, - {0x0010bc, {[CaseLower] = 0x002d1c,[CaseTitle] = 0x0010bc,[CaseUpper] = 0x0010bc}}, - {0x0010bd, {[CaseLower] = 0x002d1d,[CaseTitle] = 0x0010bd,[CaseUpper] = 0x0010bd}}, - {0x0010be, {[CaseLower] = 0x002d1e,[CaseTitle] = 0x0010be,[CaseUpper] = 0x0010be}}, - {0x0010bf, {[CaseLower] = 0x002d1f,[CaseTitle] = 0x0010bf,[CaseUpper] = 0x0010bf}}, - {0x0010c0, {[CaseLower] = 0x002d20,[CaseTitle] = 0x0010c0,[CaseUpper] = 0x0010c0}}, - {0x0010c1, {[CaseLower] = 0x002d21,[CaseTitle] = 0x0010c1,[CaseUpper] = 0x0010c1}}, - {0x0010c2, {[CaseLower] = 0x002d22,[CaseTitle] = 0x0010c2,[CaseUpper] = 0x0010c2}}, - {0x0010c3, {[CaseLower] = 0x002d23,[CaseTitle] = 0x0010c3,[CaseUpper] = 0x0010c3}}, - {0x0010c4, {[CaseLower] = 0x002d24,[CaseTitle] = 0x0010c4,[CaseUpper] = 0x0010c4}}, - {0x0010c5, {[CaseLower] = 0x002d25,[CaseTitle] = 0x0010c5,[CaseUpper] = 0x0010c5}}, - {0x0010c7, {[CaseLower] = 0x002d27,[CaseTitle] = 0x0010c7,[CaseUpper] = 0x0010c7}}, - {0x0010cd, {[CaseLower] = 0x002d2d,[CaseTitle] = 0x0010cd,[CaseUpper] = 0x0010cd}}, - {0x0010d0, {[CaseLower] = 0x0010d0,[CaseTitle] = 0x0010d0,[CaseUpper] = 0x001c90}}, - {0x0010d1, {[CaseLower] = 0x0010d1,[CaseTitle] = 0x0010d1,[CaseUpper] = 0x001c91}}, - {0x0010d2, {[CaseLower] = 0x0010d2,[CaseTitle] = 0x0010d2,[CaseUpper] = 0x001c92}}, - {0x0010d3, {[CaseLower] = 0x0010d3,[CaseTitle] = 0x0010d3,[CaseUpper] = 0x001c93}}, - {0x0010d4, {[CaseLower] = 0x0010d4,[CaseTitle] = 0x0010d4,[CaseUpper] = 0x001c94}}, - {0x0010d5, {[CaseLower] = 0x0010d5,[CaseTitle] = 0x0010d5,[CaseUpper] = 0x001c95}}, - {0x0010d6, {[CaseLower] = 0x0010d6,[CaseTitle] = 0x0010d6,[CaseUpper] = 0x001c96}}, - {0x0010d7, {[CaseLower] = 0x0010d7,[CaseTitle] = 0x0010d7,[CaseUpper] = 0x001c97}}, - {0x0010d8, {[CaseLower] = 0x0010d8,[CaseTitle] = 0x0010d8,[CaseUpper] = 0x001c98}}, - {0x0010d9, {[CaseLower] = 0x0010d9,[CaseTitle] = 0x0010d9,[CaseUpper] = 0x001c99}}, - {0x0010da, {[CaseLower] = 0x0010da,[CaseTitle] = 0x0010da,[CaseUpper] = 0x001c9a}}, - {0x0010db, {[CaseLower] = 0x0010db,[CaseTitle] = 0x0010db,[CaseUpper] = 0x001c9b}}, - {0x0010dc, {[CaseLower] = 0x0010dc,[CaseTitle] = 0x0010dc,[CaseUpper] = 0x001c9c}}, - {0x0010dd, {[CaseLower] = 0x0010dd,[CaseTitle] = 0x0010dd,[CaseUpper] = 0x001c9d}}, - {0x0010de, {[CaseLower] = 0x0010de,[CaseTitle] = 0x0010de,[CaseUpper] = 0x001c9e}}, - {0x0010df, {[CaseLower] = 0x0010df,[CaseTitle] = 0x0010df,[CaseUpper] = 0x001c9f}}, - {0x0010e0, {[CaseLower] = 0x0010e0,[CaseTitle] = 0x0010e0,[CaseUpper] = 0x001ca0}}, - {0x0010e1, {[CaseLower] = 0x0010e1,[CaseTitle] = 0x0010e1,[CaseUpper] = 0x001ca1}}, - {0x0010e2, {[CaseLower] = 0x0010e2,[CaseTitle] = 0x0010e2,[CaseUpper] = 0x001ca2}}, - {0x0010e3, {[CaseLower] = 0x0010e3,[CaseTitle] = 0x0010e3,[CaseUpper] = 0x001ca3}}, - {0x0010e4, {[CaseLower] = 0x0010e4,[CaseTitle] = 0x0010e4,[CaseUpper] = 0x001ca4}}, - {0x0010e5, {[CaseLower] = 0x0010e5,[CaseTitle] = 0x0010e5,[CaseUpper] = 0x001ca5}}, - {0x0010e6, {[CaseLower] = 0x0010e6,[CaseTitle] = 0x0010e6,[CaseUpper] = 0x001ca6}}, - {0x0010e7, {[CaseLower] = 0x0010e7,[CaseTitle] = 0x0010e7,[CaseUpper] = 0x001ca7}}, - {0x0010e8, {[CaseLower] = 0x0010e8,[CaseTitle] = 0x0010e8,[CaseUpper] = 0x001ca8}}, - {0x0010e9, {[CaseLower] = 0x0010e9,[CaseTitle] = 0x0010e9,[CaseUpper] = 0x001ca9}}, - {0x0010ea, {[CaseLower] = 0x0010ea,[CaseTitle] = 0x0010ea,[CaseUpper] = 0x001caa}}, - {0x0010eb, {[CaseLower] = 0x0010eb,[CaseTitle] = 0x0010eb,[CaseUpper] = 0x001cab}}, - {0x0010ec, {[CaseLower] = 0x0010ec,[CaseTitle] = 0x0010ec,[CaseUpper] = 0x001cac}}, - {0x0010ed, {[CaseLower] = 0x0010ed,[CaseTitle] = 0x0010ed,[CaseUpper] = 0x001cad}}, - {0x0010ee, {[CaseLower] = 0x0010ee,[CaseTitle] = 0x0010ee,[CaseUpper] = 0x001cae}}, - {0x0010ef, {[CaseLower] = 0x0010ef,[CaseTitle] = 0x0010ef,[CaseUpper] = 0x001caf}}, - {0x0010f0, {[CaseLower] = 0x0010f0,[CaseTitle] = 0x0010f0,[CaseUpper] = 0x001cb0}}, - {0x0010f1, {[CaseLower] = 0x0010f1,[CaseTitle] = 0x0010f1,[CaseUpper] = 0x001cb1}}, - {0x0010f2, {[CaseLower] = 0x0010f2,[CaseTitle] = 0x0010f2,[CaseUpper] = 0x001cb2}}, - {0x0010f3, {[CaseLower] = 0x0010f3,[CaseTitle] = 0x0010f3,[CaseUpper] = 0x001cb3}}, - {0x0010f4, {[CaseLower] = 0x0010f4,[CaseTitle] = 0x0010f4,[CaseUpper] = 0x001cb4}}, - {0x0010f5, {[CaseLower] = 0x0010f5,[CaseTitle] = 0x0010f5,[CaseUpper] = 0x001cb5}}, - {0x0010f6, {[CaseLower] = 0x0010f6,[CaseTitle] = 0x0010f6,[CaseUpper] = 0x001cb6}}, - {0x0010f7, {[CaseLower] = 0x0010f7,[CaseTitle] = 0x0010f7,[CaseUpper] = 0x001cb7}}, - {0x0010f8, {[CaseLower] = 0x0010f8,[CaseTitle] = 0x0010f8,[CaseUpper] = 0x001cb8}}, - {0x0010f9, {[CaseLower] = 0x0010f9,[CaseTitle] = 0x0010f9,[CaseUpper] = 0x001cb9}}, - {0x0010fa, {[CaseLower] = 0x0010fa,[CaseTitle] = 0x0010fa,[CaseUpper] = 0x001cba}}, - {0x0010fd, {[CaseLower] = 0x0010fd,[CaseTitle] = 0x0010fd,[CaseUpper] = 0x001cbd}}, - {0x0010fe, {[CaseLower] = 0x0010fe,[CaseTitle] = 0x0010fe,[CaseUpper] = 0x001cbe}}, - {0x0010ff, {[CaseLower] = 0x0010ff,[CaseTitle] = 0x0010ff,[CaseUpper] = 0x001cbf}}, - {0x0013a0, {[CaseLower] = 0x00ab70,[CaseTitle] = 0x0013a0,[CaseUpper] = 0x0013a0}}, - {0x0013a1, {[CaseLower] = 0x00ab71,[CaseTitle] = 0x0013a1,[CaseUpper] = 0x0013a1}}, - {0x0013a2, {[CaseLower] = 0x00ab72,[CaseTitle] = 0x0013a2,[CaseUpper] = 0x0013a2}}, - {0x0013a3, {[CaseLower] = 0x00ab73,[CaseTitle] = 0x0013a3,[CaseUpper] = 0x0013a3}}, - {0x0013a4, {[CaseLower] = 0x00ab74,[CaseTitle] = 0x0013a4,[CaseUpper] = 0x0013a4}}, - {0x0013a5, {[CaseLower] = 0x00ab75,[CaseTitle] = 0x0013a5,[CaseUpper] = 0x0013a5}}, - {0x0013a6, {[CaseLower] = 0x00ab76,[CaseTitle] = 0x0013a6,[CaseUpper] = 0x0013a6}}, - {0x0013a7, {[CaseLower] = 0x00ab77,[CaseTitle] = 0x0013a7,[CaseUpper] = 0x0013a7}}, - {0x0013a8, {[CaseLower] = 0x00ab78,[CaseTitle] = 0x0013a8,[CaseUpper] = 0x0013a8}}, - {0x0013a9, {[CaseLower] = 0x00ab79,[CaseTitle] = 0x0013a9,[CaseUpper] = 0x0013a9}}, - {0x0013aa, {[CaseLower] = 0x00ab7a,[CaseTitle] = 0x0013aa,[CaseUpper] = 0x0013aa}}, - {0x0013ab, {[CaseLower] = 0x00ab7b,[CaseTitle] = 0x0013ab,[CaseUpper] = 0x0013ab}}, - {0x0013ac, {[CaseLower] = 0x00ab7c,[CaseTitle] = 0x0013ac,[CaseUpper] = 0x0013ac}}, - {0x0013ad, {[CaseLower] = 0x00ab7d,[CaseTitle] = 0x0013ad,[CaseUpper] = 0x0013ad}}, - {0x0013ae, {[CaseLower] = 0x00ab7e,[CaseTitle] = 0x0013ae,[CaseUpper] = 0x0013ae}}, - {0x0013af, {[CaseLower] = 0x00ab7f,[CaseTitle] = 0x0013af,[CaseUpper] = 0x0013af}}, - {0x0013b0, {[CaseLower] = 0x00ab80,[CaseTitle] = 0x0013b0,[CaseUpper] = 0x0013b0}}, - {0x0013b1, {[CaseLower] = 0x00ab81,[CaseTitle] = 0x0013b1,[CaseUpper] = 0x0013b1}}, - {0x0013b2, {[CaseLower] = 0x00ab82,[CaseTitle] = 0x0013b2,[CaseUpper] = 0x0013b2}}, - {0x0013b3, {[CaseLower] = 0x00ab83,[CaseTitle] = 0x0013b3,[CaseUpper] = 0x0013b3}}, - {0x0013b4, {[CaseLower] = 0x00ab84,[CaseTitle] = 0x0013b4,[CaseUpper] = 0x0013b4}}, - {0x0013b5, {[CaseLower] = 0x00ab85,[CaseTitle] = 0x0013b5,[CaseUpper] = 0x0013b5}}, - {0x0013b6, {[CaseLower] = 0x00ab86,[CaseTitle] = 0x0013b6,[CaseUpper] = 0x0013b6}}, - {0x0013b7, {[CaseLower] = 0x00ab87,[CaseTitle] = 0x0013b7,[CaseUpper] = 0x0013b7}}, - {0x0013b8, {[CaseLower] = 0x00ab88,[CaseTitle] = 0x0013b8,[CaseUpper] = 0x0013b8}}, - {0x0013b9, {[CaseLower] = 0x00ab89,[CaseTitle] = 0x0013b9,[CaseUpper] = 0x0013b9}}, - {0x0013ba, {[CaseLower] = 0x00ab8a,[CaseTitle] = 0x0013ba,[CaseUpper] = 0x0013ba}}, - {0x0013bb, {[CaseLower] = 0x00ab8b,[CaseTitle] = 0x0013bb,[CaseUpper] = 0x0013bb}}, - {0x0013bc, {[CaseLower] = 0x00ab8c,[CaseTitle] = 0x0013bc,[CaseUpper] = 0x0013bc}}, - {0x0013bd, {[CaseLower] = 0x00ab8d,[CaseTitle] = 0x0013bd,[CaseUpper] = 0x0013bd}}, - {0x0013be, {[CaseLower] = 0x00ab8e,[CaseTitle] = 0x0013be,[CaseUpper] = 0x0013be}}, - {0x0013bf, {[CaseLower] = 0x00ab8f,[CaseTitle] = 0x0013bf,[CaseUpper] = 0x0013bf}}, - {0x0013c0, {[CaseLower] = 0x00ab90,[CaseTitle] = 0x0013c0,[CaseUpper] = 0x0013c0}}, - {0x0013c1, {[CaseLower] = 0x00ab91,[CaseTitle] = 0x0013c1,[CaseUpper] = 0x0013c1}}, - {0x0013c2, {[CaseLower] = 0x00ab92,[CaseTitle] = 0x0013c2,[CaseUpper] = 0x0013c2}}, - {0x0013c3, {[CaseLower] = 0x00ab93,[CaseTitle] = 0x0013c3,[CaseUpper] = 0x0013c3}}, - {0x0013c4, {[CaseLower] = 0x00ab94,[CaseTitle] = 0x0013c4,[CaseUpper] = 0x0013c4}}, - {0x0013c5, {[CaseLower] = 0x00ab95,[CaseTitle] = 0x0013c5,[CaseUpper] = 0x0013c5}}, - {0x0013c6, {[CaseLower] = 0x00ab96,[CaseTitle] = 0x0013c6,[CaseUpper] = 0x0013c6}}, - {0x0013c7, {[CaseLower] = 0x00ab97,[CaseTitle] = 0x0013c7,[CaseUpper] = 0x0013c7}}, - {0x0013c8, {[CaseLower] = 0x00ab98,[CaseTitle] = 0x0013c8,[CaseUpper] = 0x0013c8}}, - {0x0013c9, {[CaseLower] = 0x00ab99,[CaseTitle] = 0x0013c9,[CaseUpper] = 0x0013c9}}, - {0x0013ca, {[CaseLower] = 0x00ab9a,[CaseTitle] = 0x0013ca,[CaseUpper] = 0x0013ca}}, - {0x0013cb, {[CaseLower] = 0x00ab9b,[CaseTitle] = 0x0013cb,[CaseUpper] = 0x0013cb}}, - {0x0013cc, {[CaseLower] = 0x00ab9c,[CaseTitle] = 0x0013cc,[CaseUpper] = 0x0013cc}}, - {0x0013cd, {[CaseLower] = 0x00ab9d,[CaseTitle] = 0x0013cd,[CaseUpper] = 0x0013cd}}, - {0x0013ce, {[CaseLower] = 0x00ab9e,[CaseTitle] = 0x0013ce,[CaseUpper] = 0x0013ce}}, - {0x0013cf, {[CaseLower] = 0x00ab9f,[CaseTitle] = 0x0013cf,[CaseUpper] = 0x0013cf}}, - {0x0013d0, {[CaseLower] = 0x00aba0,[CaseTitle] = 0x0013d0,[CaseUpper] = 0x0013d0}}, - {0x0013d1, {[CaseLower] = 0x00aba1,[CaseTitle] = 0x0013d1,[CaseUpper] = 0x0013d1}}, - {0x0013d2, {[CaseLower] = 0x00aba2,[CaseTitle] = 0x0013d2,[CaseUpper] = 0x0013d2}}, - {0x0013d3, {[CaseLower] = 0x00aba3,[CaseTitle] = 0x0013d3,[CaseUpper] = 0x0013d3}}, - {0x0013d4, {[CaseLower] = 0x00aba4,[CaseTitle] = 0x0013d4,[CaseUpper] = 0x0013d4}}, - {0x0013d5, {[CaseLower] = 0x00aba5,[CaseTitle] = 0x0013d5,[CaseUpper] = 0x0013d5}}, - {0x0013d6, {[CaseLower] = 0x00aba6,[CaseTitle] = 0x0013d6,[CaseUpper] = 0x0013d6}}, - {0x0013d7, {[CaseLower] = 0x00aba7,[CaseTitle] = 0x0013d7,[CaseUpper] = 0x0013d7}}, - {0x0013d8, {[CaseLower] = 0x00aba8,[CaseTitle] = 0x0013d8,[CaseUpper] = 0x0013d8}}, - {0x0013d9, {[CaseLower] = 0x00aba9,[CaseTitle] = 0x0013d9,[CaseUpper] = 0x0013d9}}, - {0x0013da, {[CaseLower] = 0x00abaa,[CaseTitle] = 0x0013da,[CaseUpper] = 0x0013da}}, - {0x0013db, {[CaseLower] = 0x00abab,[CaseTitle] = 0x0013db,[CaseUpper] = 0x0013db}}, - {0x0013dc, {[CaseLower] = 0x00abac,[CaseTitle] = 0x0013dc,[CaseUpper] = 0x0013dc}}, - {0x0013dd, {[CaseLower] = 0x00abad,[CaseTitle] = 0x0013dd,[CaseUpper] = 0x0013dd}}, - {0x0013de, {[CaseLower] = 0x00abae,[CaseTitle] = 0x0013de,[CaseUpper] = 0x0013de}}, - {0x0013df, {[CaseLower] = 0x00abaf,[CaseTitle] = 0x0013df,[CaseUpper] = 0x0013df}}, - {0x0013e0, {[CaseLower] = 0x00abb0,[CaseTitle] = 0x0013e0,[CaseUpper] = 0x0013e0}}, - {0x0013e1, {[CaseLower] = 0x00abb1,[CaseTitle] = 0x0013e1,[CaseUpper] = 0x0013e1}}, - {0x0013e2, {[CaseLower] = 0x00abb2,[CaseTitle] = 0x0013e2,[CaseUpper] = 0x0013e2}}, - {0x0013e3, {[CaseLower] = 0x00abb3,[CaseTitle] = 0x0013e3,[CaseUpper] = 0x0013e3}}, - {0x0013e4, {[CaseLower] = 0x00abb4,[CaseTitle] = 0x0013e4,[CaseUpper] = 0x0013e4}}, - {0x0013e5, {[CaseLower] = 0x00abb5,[CaseTitle] = 0x0013e5,[CaseUpper] = 0x0013e5}}, - {0x0013e6, {[CaseLower] = 0x00abb6,[CaseTitle] = 0x0013e6,[CaseUpper] = 0x0013e6}}, - {0x0013e7, {[CaseLower] = 0x00abb7,[CaseTitle] = 0x0013e7,[CaseUpper] = 0x0013e7}}, - {0x0013e8, {[CaseLower] = 0x00abb8,[CaseTitle] = 0x0013e8,[CaseUpper] = 0x0013e8}}, - {0x0013e9, {[CaseLower] = 0x00abb9,[CaseTitle] = 0x0013e9,[CaseUpper] = 0x0013e9}}, - {0x0013ea, {[CaseLower] = 0x00abba,[CaseTitle] = 0x0013ea,[CaseUpper] = 0x0013ea}}, - {0x0013eb, {[CaseLower] = 0x00abbb,[CaseTitle] = 0x0013eb,[CaseUpper] = 0x0013eb}}, - {0x0013ec, {[CaseLower] = 0x00abbc,[CaseTitle] = 0x0013ec,[CaseUpper] = 0x0013ec}}, - {0x0013ed, {[CaseLower] = 0x00abbd,[CaseTitle] = 0x0013ed,[CaseUpper] = 0x0013ed}}, - {0x0013ee, {[CaseLower] = 0x00abbe,[CaseTitle] = 0x0013ee,[CaseUpper] = 0x0013ee}}, - {0x0013ef, {[CaseLower] = 0x00abbf,[CaseTitle] = 0x0013ef,[CaseUpper] = 0x0013ef}}, - {0x0013f0, {[CaseLower] = 0x0013f8,[CaseTitle] = 0x0013f0,[CaseUpper] = 0x0013f0}}, - {0x0013f1, {[CaseLower] = 0x0013f9,[CaseTitle] = 0x0013f1,[CaseUpper] = 0x0013f1}}, - {0x0013f2, {[CaseLower] = 0x0013fa,[CaseTitle] = 0x0013f2,[CaseUpper] = 0x0013f2}}, - {0x0013f3, {[CaseLower] = 0x0013fb,[CaseTitle] = 0x0013f3,[CaseUpper] = 0x0013f3}}, - {0x0013f4, {[CaseLower] = 0x0013fc,[CaseTitle] = 0x0013f4,[CaseUpper] = 0x0013f4}}, - {0x0013f5, {[CaseLower] = 0x0013fd,[CaseTitle] = 0x0013f5,[CaseUpper] = 0x0013f5}}, - {0x0013f8, {[CaseLower] = 0x0013f8,[CaseTitle] = 0x0013f0,[CaseUpper] = 0x0013f0}}, - {0x0013f9, {[CaseLower] = 0x0013f9,[CaseTitle] = 0x0013f1,[CaseUpper] = 0x0013f1}}, - {0x0013fa, {[CaseLower] = 0x0013fa,[CaseTitle] = 0x0013f2,[CaseUpper] = 0x0013f2}}, - {0x0013fb, {[CaseLower] = 0x0013fb,[CaseTitle] = 0x0013f3,[CaseUpper] = 0x0013f3}}, - {0x0013fc, {[CaseLower] = 0x0013fc,[CaseTitle] = 0x0013f4,[CaseUpper] = 0x0013f4}}, - {0x0013fd, {[CaseLower] = 0x0013fd,[CaseTitle] = 0x0013f5,[CaseUpper] = 0x0013f5}}, - {0x001c80, {[CaseLower] = 0x001c80,[CaseTitle] = 0x000412,[CaseUpper] = 0x000412}}, - {0x001c81, {[CaseLower] = 0x001c81,[CaseTitle] = 0x000414,[CaseUpper] = 0x000414}}, - {0x001c82, {[CaseLower] = 0x001c82,[CaseTitle] = 0x00041e,[CaseUpper] = 0x00041e}}, - {0x001c83, {[CaseLower] = 0x001c83,[CaseTitle] = 0x000421,[CaseUpper] = 0x000421}}, - {0x001c84, {[CaseLower] = 0x001c84,[CaseTitle] = 0x000422,[CaseUpper] = 0x000422}}, - {0x001c85, {[CaseLower] = 0x001c85,[CaseTitle] = 0x000422,[CaseUpper] = 0x000422}}, - {0x001c86, {[CaseLower] = 0x001c86,[CaseTitle] = 0x00042a,[CaseUpper] = 0x00042a}}, - {0x001c87, {[CaseLower] = 0x001c87,[CaseTitle] = 0x000462,[CaseUpper] = 0x000462}}, - {0x001c88, {[CaseLower] = 0x001c88,[CaseTitle] = 0x00a64a,[CaseUpper] = 0x00a64a}}, - {0x001c90, {[CaseLower] = 0x0010d0,[CaseTitle] = 0x001c90,[CaseUpper] = 0x001c90}}, - {0x001c91, {[CaseLower] = 0x0010d1,[CaseTitle] = 0x001c91,[CaseUpper] = 0x001c91}}, - {0x001c92, {[CaseLower] = 0x0010d2,[CaseTitle] = 0x001c92,[CaseUpper] = 0x001c92}}, - {0x001c93, {[CaseLower] = 0x0010d3,[CaseTitle] = 0x001c93,[CaseUpper] = 0x001c93}}, - {0x001c94, {[CaseLower] = 0x0010d4,[CaseTitle] = 0x001c94,[CaseUpper] = 0x001c94}}, - {0x001c95, {[CaseLower] = 0x0010d5,[CaseTitle] = 0x001c95,[CaseUpper] = 0x001c95}}, - {0x001c96, {[CaseLower] = 0x0010d6,[CaseTitle] = 0x001c96,[CaseUpper] = 0x001c96}}, - {0x001c97, {[CaseLower] = 0x0010d7,[CaseTitle] = 0x001c97,[CaseUpper] = 0x001c97}}, - {0x001c98, {[CaseLower] = 0x0010d8,[CaseTitle] = 0x001c98,[CaseUpper] = 0x001c98}}, - {0x001c99, {[CaseLower] = 0x0010d9,[CaseTitle] = 0x001c99,[CaseUpper] = 0x001c99}}, - {0x001c9a, {[CaseLower] = 0x0010da,[CaseTitle] = 0x001c9a,[CaseUpper] = 0x001c9a}}, - {0x001c9b, {[CaseLower] = 0x0010db,[CaseTitle] = 0x001c9b,[CaseUpper] = 0x001c9b}}, - {0x001c9c, {[CaseLower] = 0x0010dc,[CaseTitle] = 0x001c9c,[CaseUpper] = 0x001c9c}}, - {0x001c9d, {[CaseLower] = 0x0010dd,[CaseTitle] = 0x001c9d,[CaseUpper] = 0x001c9d}}, - {0x001c9e, {[CaseLower] = 0x0010de,[CaseTitle] = 0x001c9e,[CaseUpper] = 0x001c9e}}, - {0x001c9f, {[CaseLower] = 0x0010df,[CaseTitle] = 0x001c9f,[CaseUpper] = 0x001c9f}}, - {0x001ca0, {[CaseLower] = 0x0010e0,[CaseTitle] = 0x001ca0,[CaseUpper] = 0x001ca0}}, - {0x001ca1, {[CaseLower] = 0x0010e1,[CaseTitle] = 0x001ca1,[CaseUpper] = 0x001ca1}}, - {0x001ca2, {[CaseLower] = 0x0010e2,[CaseTitle] = 0x001ca2,[CaseUpper] = 0x001ca2}}, - {0x001ca3, {[CaseLower] = 0x0010e3,[CaseTitle] = 0x001ca3,[CaseUpper] = 0x001ca3}}, - {0x001ca4, {[CaseLower] = 0x0010e4,[CaseTitle] = 0x001ca4,[CaseUpper] = 0x001ca4}}, - {0x001ca5, {[CaseLower] = 0x0010e5,[CaseTitle] = 0x001ca5,[CaseUpper] = 0x001ca5}}, - {0x001ca6, {[CaseLower] = 0x0010e6,[CaseTitle] = 0x001ca6,[CaseUpper] = 0x001ca6}}, - {0x001ca7, {[CaseLower] = 0x0010e7,[CaseTitle] = 0x001ca7,[CaseUpper] = 0x001ca7}}, - {0x001ca8, {[CaseLower] = 0x0010e8,[CaseTitle] = 0x001ca8,[CaseUpper] = 0x001ca8}}, - {0x001ca9, {[CaseLower] = 0x0010e9,[CaseTitle] = 0x001ca9,[CaseUpper] = 0x001ca9}}, - {0x001caa, {[CaseLower] = 0x0010ea,[CaseTitle] = 0x001caa,[CaseUpper] = 0x001caa}}, - {0x001cab, {[CaseLower] = 0x0010eb,[CaseTitle] = 0x001cab,[CaseUpper] = 0x001cab}}, - {0x001cac, {[CaseLower] = 0x0010ec,[CaseTitle] = 0x001cac,[CaseUpper] = 0x001cac}}, - {0x001cad, {[CaseLower] = 0x0010ed,[CaseTitle] = 0x001cad,[CaseUpper] = 0x001cad}}, - {0x001cae, {[CaseLower] = 0x0010ee,[CaseTitle] = 0x001cae,[CaseUpper] = 0x001cae}}, - {0x001caf, {[CaseLower] = 0x0010ef,[CaseTitle] = 0x001caf,[CaseUpper] = 0x001caf}}, - {0x001cb0, {[CaseLower] = 0x0010f0,[CaseTitle] = 0x001cb0,[CaseUpper] = 0x001cb0}}, - {0x001cb1, {[CaseLower] = 0x0010f1,[CaseTitle] = 0x001cb1,[CaseUpper] = 0x001cb1}}, - {0x001cb2, {[CaseLower] = 0x0010f2,[CaseTitle] = 0x001cb2,[CaseUpper] = 0x001cb2}}, - {0x001cb3, {[CaseLower] = 0x0010f3,[CaseTitle] = 0x001cb3,[CaseUpper] = 0x001cb3}}, - {0x001cb4, {[CaseLower] = 0x0010f4,[CaseTitle] = 0x001cb4,[CaseUpper] = 0x001cb4}}, - {0x001cb5, {[CaseLower] = 0x0010f5,[CaseTitle] = 0x001cb5,[CaseUpper] = 0x001cb5}}, - {0x001cb6, {[CaseLower] = 0x0010f6,[CaseTitle] = 0x001cb6,[CaseUpper] = 0x001cb6}}, - {0x001cb7, {[CaseLower] = 0x0010f7,[CaseTitle] = 0x001cb7,[CaseUpper] = 0x001cb7}}, - {0x001cb8, {[CaseLower] = 0x0010f8,[CaseTitle] = 0x001cb8,[CaseUpper] = 0x001cb8}}, - {0x001cb9, {[CaseLower] = 0x0010f9,[CaseTitle] = 0x001cb9,[CaseUpper] = 0x001cb9}}, - {0x001cba, {[CaseLower] = 0x0010fa,[CaseTitle] = 0x001cba,[CaseUpper] = 0x001cba}}, - {0x001cbd, {[CaseLower] = 0x0010fd,[CaseTitle] = 0x001cbd,[CaseUpper] = 0x001cbd}}, - {0x001cbe, {[CaseLower] = 0x0010fe,[CaseTitle] = 0x001cbe,[CaseUpper] = 0x001cbe}}, - {0x001cbf, {[CaseLower] = 0x0010ff,[CaseTitle] = 0x001cbf,[CaseUpper] = 0x001cbf}}, - {0x001d79, {[CaseLower] = 0x001d79,[CaseTitle] = 0x00a77d,[CaseUpper] = 0x00a77d}}, - {0x001d7d, {[CaseLower] = 0x001d7d,[CaseTitle] = 0x002c63,[CaseUpper] = 0x002c63}}, - {0x001d8e, {[CaseLower] = 0x001d8e,[CaseTitle] = 0x00a7c6,[CaseUpper] = 0x00a7c6}}, - {0x001e00, {[CaseLower] = 0x001e01,[CaseTitle] = 0x001e00,[CaseUpper] = 0x001e00}}, - {0x001e01, {[CaseLower] = 0x001e01,[CaseTitle] = 0x001e00,[CaseUpper] = 0x001e00}}, - {0x001e02, {[CaseLower] = 0x001e03,[CaseTitle] = 0x001e02,[CaseUpper] = 0x001e02}}, - {0x001e03, {[CaseLower] = 0x001e03,[CaseTitle] = 0x001e02,[CaseUpper] = 0x001e02}}, - {0x001e04, {[CaseLower] = 0x001e05,[CaseTitle] = 0x001e04,[CaseUpper] = 0x001e04}}, - {0x001e05, {[CaseLower] = 0x001e05,[CaseTitle] = 0x001e04,[CaseUpper] = 0x001e04}}, - {0x001e06, {[CaseLower] = 0x001e07,[CaseTitle] = 0x001e06,[CaseUpper] = 0x001e06}}, - {0x001e07, {[CaseLower] = 0x001e07,[CaseTitle] = 0x001e06,[CaseUpper] = 0x001e06}}, - {0x001e08, {[CaseLower] = 0x001e09,[CaseTitle] = 0x001e08,[CaseUpper] = 0x001e08}}, - {0x001e09, {[CaseLower] = 0x001e09,[CaseTitle] = 0x001e08,[CaseUpper] = 0x001e08}}, - {0x001e0a, {[CaseLower] = 0x001e0b,[CaseTitle] = 0x001e0a,[CaseUpper] = 0x001e0a}}, - {0x001e0b, {[CaseLower] = 0x001e0b,[CaseTitle] = 0x001e0a,[CaseUpper] = 0x001e0a}}, - {0x001e0c, {[CaseLower] = 0x001e0d,[CaseTitle] = 0x001e0c,[CaseUpper] = 0x001e0c}}, - {0x001e0d, {[CaseLower] = 0x001e0d,[CaseTitle] = 0x001e0c,[CaseUpper] = 0x001e0c}}, - {0x001e0e, {[CaseLower] = 0x001e0f,[CaseTitle] = 0x001e0e,[CaseUpper] = 0x001e0e}}, - {0x001e0f, {[CaseLower] = 0x001e0f,[CaseTitle] = 0x001e0e,[CaseUpper] = 0x001e0e}}, - {0x001e10, {[CaseLower] = 0x001e11,[CaseTitle] = 0x001e10,[CaseUpper] = 0x001e10}}, - {0x001e11, {[CaseLower] = 0x001e11,[CaseTitle] = 0x001e10,[CaseUpper] = 0x001e10}}, - {0x001e12, {[CaseLower] = 0x001e13,[CaseTitle] = 0x001e12,[CaseUpper] = 0x001e12}}, - {0x001e13, {[CaseLower] = 0x001e13,[CaseTitle] = 0x001e12,[CaseUpper] = 0x001e12}}, - {0x001e14, {[CaseLower] = 0x001e15,[CaseTitle] = 0x001e14,[CaseUpper] = 0x001e14}}, - {0x001e15, {[CaseLower] = 0x001e15,[CaseTitle] = 0x001e14,[CaseUpper] = 0x001e14}}, - {0x001e16, {[CaseLower] = 0x001e17,[CaseTitle] = 0x001e16,[CaseUpper] = 0x001e16}}, - {0x001e17, {[CaseLower] = 0x001e17,[CaseTitle] = 0x001e16,[CaseUpper] = 0x001e16}}, - {0x001e18, {[CaseLower] = 0x001e19,[CaseTitle] = 0x001e18,[CaseUpper] = 0x001e18}}, - {0x001e19, {[CaseLower] = 0x001e19,[CaseTitle] = 0x001e18,[CaseUpper] = 0x001e18}}, - {0x001e1a, {[CaseLower] = 0x001e1b,[CaseTitle] = 0x001e1a,[CaseUpper] = 0x001e1a}}, - {0x001e1b, {[CaseLower] = 0x001e1b,[CaseTitle] = 0x001e1a,[CaseUpper] = 0x001e1a}}, - {0x001e1c, {[CaseLower] = 0x001e1d,[CaseTitle] = 0x001e1c,[CaseUpper] = 0x001e1c}}, - {0x001e1d, {[CaseLower] = 0x001e1d,[CaseTitle] = 0x001e1c,[CaseUpper] = 0x001e1c}}, - {0x001e1e, {[CaseLower] = 0x001e1f,[CaseTitle] = 0x001e1e,[CaseUpper] = 0x001e1e}}, - {0x001e1f, {[CaseLower] = 0x001e1f,[CaseTitle] = 0x001e1e,[CaseUpper] = 0x001e1e}}, - {0x001e20, {[CaseLower] = 0x001e21,[CaseTitle] = 0x001e20,[CaseUpper] = 0x001e20}}, - {0x001e21, {[CaseLower] = 0x001e21,[CaseTitle] = 0x001e20,[CaseUpper] = 0x001e20}}, - {0x001e22, {[CaseLower] = 0x001e23,[CaseTitle] = 0x001e22,[CaseUpper] = 0x001e22}}, - {0x001e23, {[CaseLower] = 0x001e23,[CaseTitle] = 0x001e22,[CaseUpper] = 0x001e22}}, - {0x001e24, {[CaseLower] = 0x001e25,[CaseTitle] = 0x001e24,[CaseUpper] = 0x001e24}}, - {0x001e25, {[CaseLower] = 0x001e25,[CaseTitle] = 0x001e24,[CaseUpper] = 0x001e24}}, - {0x001e26, {[CaseLower] = 0x001e27,[CaseTitle] = 0x001e26,[CaseUpper] = 0x001e26}}, - {0x001e27, {[CaseLower] = 0x001e27,[CaseTitle] = 0x001e26,[CaseUpper] = 0x001e26}}, - {0x001e28, {[CaseLower] = 0x001e29,[CaseTitle] = 0x001e28,[CaseUpper] = 0x001e28}}, - {0x001e29, {[CaseLower] = 0x001e29,[CaseTitle] = 0x001e28,[CaseUpper] = 0x001e28}}, - {0x001e2a, {[CaseLower] = 0x001e2b,[CaseTitle] = 0x001e2a,[CaseUpper] = 0x001e2a}}, - {0x001e2b, {[CaseLower] = 0x001e2b,[CaseTitle] = 0x001e2a,[CaseUpper] = 0x001e2a}}, - {0x001e2c, {[CaseLower] = 0x001e2d,[CaseTitle] = 0x001e2c,[CaseUpper] = 0x001e2c}}, - {0x001e2d, {[CaseLower] = 0x001e2d,[CaseTitle] = 0x001e2c,[CaseUpper] = 0x001e2c}}, - {0x001e2e, {[CaseLower] = 0x001e2f,[CaseTitle] = 0x001e2e,[CaseUpper] = 0x001e2e}}, - {0x001e2f, {[CaseLower] = 0x001e2f,[CaseTitle] = 0x001e2e,[CaseUpper] = 0x001e2e}}, - {0x001e30, {[CaseLower] = 0x001e31,[CaseTitle] = 0x001e30,[CaseUpper] = 0x001e30}}, - {0x001e31, {[CaseLower] = 0x001e31,[CaseTitle] = 0x001e30,[CaseUpper] = 0x001e30}}, - {0x001e32, {[CaseLower] = 0x001e33,[CaseTitle] = 0x001e32,[CaseUpper] = 0x001e32}}, - {0x001e33, {[CaseLower] = 0x001e33,[CaseTitle] = 0x001e32,[CaseUpper] = 0x001e32}}, - {0x001e34, {[CaseLower] = 0x001e35,[CaseTitle] = 0x001e34,[CaseUpper] = 0x001e34}}, - {0x001e35, {[CaseLower] = 0x001e35,[CaseTitle] = 0x001e34,[CaseUpper] = 0x001e34}}, - {0x001e36, {[CaseLower] = 0x001e37,[CaseTitle] = 0x001e36,[CaseUpper] = 0x001e36}}, - {0x001e37, {[CaseLower] = 0x001e37,[CaseTitle] = 0x001e36,[CaseUpper] = 0x001e36}}, - {0x001e38, {[CaseLower] = 0x001e39,[CaseTitle] = 0x001e38,[CaseUpper] = 0x001e38}}, - {0x001e39, {[CaseLower] = 0x001e39,[CaseTitle] = 0x001e38,[CaseUpper] = 0x001e38}}, - {0x001e3a, {[CaseLower] = 0x001e3b,[CaseTitle] = 0x001e3a,[CaseUpper] = 0x001e3a}}, - {0x001e3b, {[CaseLower] = 0x001e3b,[CaseTitle] = 0x001e3a,[CaseUpper] = 0x001e3a}}, - {0x001e3c, {[CaseLower] = 0x001e3d,[CaseTitle] = 0x001e3c,[CaseUpper] = 0x001e3c}}, - {0x001e3d, {[CaseLower] = 0x001e3d,[CaseTitle] = 0x001e3c,[CaseUpper] = 0x001e3c}}, - {0x001e3e, {[CaseLower] = 0x001e3f,[CaseTitle] = 0x001e3e,[CaseUpper] = 0x001e3e}}, - {0x001e3f, {[CaseLower] = 0x001e3f,[CaseTitle] = 0x001e3e,[CaseUpper] = 0x001e3e}}, - {0x001e40, {[CaseLower] = 0x001e41,[CaseTitle] = 0x001e40,[CaseUpper] = 0x001e40}}, - {0x001e41, {[CaseLower] = 0x001e41,[CaseTitle] = 0x001e40,[CaseUpper] = 0x001e40}}, - {0x001e42, {[CaseLower] = 0x001e43,[CaseTitle] = 0x001e42,[CaseUpper] = 0x001e42}}, - {0x001e43, {[CaseLower] = 0x001e43,[CaseTitle] = 0x001e42,[CaseUpper] = 0x001e42}}, - {0x001e44, {[CaseLower] = 0x001e45,[CaseTitle] = 0x001e44,[CaseUpper] = 0x001e44}}, - {0x001e45, {[CaseLower] = 0x001e45,[CaseTitle] = 0x001e44,[CaseUpper] = 0x001e44}}, - {0x001e46, {[CaseLower] = 0x001e47,[CaseTitle] = 0x001e46,[CaseUpper] = 0x001e46}}, - {0x001e47, {[CaseLower] = 0x001e47,[CaseTitle] = 0x001e46,[CaseUpper] = 0x001e46}}, - {0x001e48, {[CaseLower] = 0x001e49,[CaseTitle] = 0x001e48,[CaseUpper] = 0x001e48}}, - {0x001e49, {[CaseLower] = 0x001e49,[CaseTitle] = 0x001e48,[CaseUpper] = 0x001e48}}, - {0x001e4a, {[CaseLower] = 0x001e4b,[CaseTitle] = 0x001e4a,[CaseUpper] = 0x001e4a}}, - {0x001e4b, {[CaseLower] = 0x001e4b,[CaseTitle] = 0x001e4a,[CaseUpper] = 0x001e4a}}, - {0x001e4c, {[CaseLower] = 0x001e4d,[CaseTitle] = 0x001e4c,[CaseUpper] = 0x001e4c}}, - {0x001e4d, {[CaseLower] = 0x001e4d,[CaseTitle] = 0x001e4c,[CaseUpper] = 0x001e4c}}, - {0x001e4e, {[CaseLower] = 0x001e4f,[CaseTitle] = 0x001e4e,[CaseUpper] = 0x001e4e}}, - {0x001e4f, {[CaseLower] = 0x001e4f,[CaseTitle] = 0x001e4e,[CaseUpper] = 0x001e4e}}, - {0x001e50, {[CaseLower] = 0x001e51,[CaseTitle] = 0x001e50,[CaseUpper] = 0x001e50}}, - {0x001e51, {[CaseLower] = 0x001e51,[CaseTitle] = 0x001e50,[CaseUpper] = 0x001e50}}, - {0x001e52, {[CaseLower] = 0x001e53,[CaseTitle] = 0x001e52,[CaseUpper] = 0x001e52}}, - {0x001e53, {[CaseLower] = 0x001e53,[CaseTitle] = 0x001e52,[CaseUpper] = 0x001e52}}, - {0x001e54, {[CaseLower] = 0x001e55,[CaseTitle] = 0x001e54,[CaseUpper] = 0x001e54}}, - {0x001e55, {[CaseLower] = 0x001e55,[CaseTitle] = 0x001e54,[CaseUpper] = 0x001e54}}, - {0x001e56, {[CaseLower] = 0x001e57,[CaseTitle] = 0x001e56,[CaseUpper] = 0x001e56}}, - {0x001e57, {[CaseLower] = 0x001e57,[CaseTitle] = 0x001e56,[CaseUpper] = 0x001e56}}, - {0x001e58, {[CaseLower] = 0x001e59,[CaseTitle] = 0x001e58,[CaseUpper] = 0x001e58}}, - {0x001e59, {[CaseLower] = 0x001e59,[CaseTitle] = 0x001e58,[CaseUpper] = 0x001e58}}, - {0x001e5a, {[CaseLower] = 0x001e5b,[CaseTitle] = 0x001e5a,[CaseUpper] = 0x001e5a}}, - {0x001e5b, {[CaseLower] = 0x001e5b,[CaseTitle] = 0x001e5a,[CaseUpper] = 0x001e5a}}, - {0x001e5c, {[CaseLower] = 0x001e5d,[CaseTitle] = 0x001e5c,[CaseUpper] = 0x001e5c}}, - {0x001e5d, {[CaseLower] = 0x001e5d,[CaseTitle] = 0x001e5c,[CaseUpper] = 0x001e5c}}, - {0x001e5e, {[CaseLower] = 0x001e5f,[CaseTitle] = 0x001e5e,[CaseUpper] = 0x001e5e}}, - {0x001e5f, {[CaseLower] = 0x001e5f,[CaseTitle] = 0x001e5e,[CaseUpper] = 0x001e5e}}, - {0x001e60, {[CaseLower] = 0x001e61,[CaseTitle] = 0x001e60,[CaseUpper] = 0x001e60}}, - {0x001e61, {[CaseLower] = 0x001e61,[CaseTitle] = 0x001e60,[CaseUpper] = 0x001e60}}, - {0x001e62, {[CaseLower] = 0x001e63,[CaseTitle] = 0x001e62,[CaseUpper] = 0x001e62}}, - {0x001e63, {[CaseLower] = 0x001e63,[CaseTitle] = 0x001e62,[CaseUpper] = 0x001e62}}, - {0x001e64, {[CaseLower] = 0x001e65,[CaseTitle] = 0x001e64,[CaseUpper] = 0x001e64}}, - {0x001e65, {[CaseLower] = 0x001e65,[CaseTitle] = 0x001e64,[CaseUpper] = 0x001e64}}, - {0x001e66, {[CaseLower] = 0x001e67,[CaseTitle] = 0x001e66,[CaseUpper] = 0x001e66}}, - {0x001e67, {[CaseLower] = 0x001e67,[CaseTitle] = 0x001e66,[CaseUpper] = 0x001e66}}, - {0x001e68, {[CaseLower] = 0x001e69,[CaseTitle] = 0x001e68,[CaseUpper] = 0x001e68}}, - {0x001e69, {[CaseLower] = 0x001e69,[CaseTitle] = 0x001e68,[CaseUpper] = 0x001e68}}, - {0x001e6a, {[CaseLower] = 0x001e6b,[CaseTitle] = 0x001e6a,[CaseUpper] = 0x001e6a}}, - {0x001e6b, {[CaseLower] = 0x001e6b,[CaseTitle] = 0x001e6a,[CaseUpper] = 0x001e6a}}, - {0x001e6c, {[CaseLower] = 0x001e6d,[CaseTitle] = 0x001e6c,[CaseUpper] = 0x001e6c}}, - {0x001e6d, {[CaseLower] = 0x001e6d,[CaseTitle] = 0x001e6c,[CaseUpper] = 0x001e6c}}, - {0x001e6e, {[CaseLower] = 0x001e6f,[CaseTitle] = 0x001e6e,[CaseUpper] = 0x001e6e}}, - {0x001e6f, {[CaseLower] = 0x001e6f,[CaseTitle] = 0x001e6e,[CaseUpper] = 0x001e6e}}, - {0x001e70, {[CaseLower] = 0x001e71,[CaseTitle] = 0x001e70,[CaseUpper] = 0x001e70}}, - {0x001e71, {[CaseLower] = 0x001e71,[CaseTitle] = 0x001e70,[CaseUpper] = 0x001e70}}, - {0x001e72, {[CaseLower] = 0x001e73,[CaseTitle] = 0x001e72,[CaseUpper] = 0x001e72}}, - {0x001e73, {[CaseLower] = 0x001e73,[CaseTitle] = 0x001e72,[CaseUpper] = 0x001e72}}, - {0x001e74, {[CaseLower] = 0x001e75,[CaseTitle] = 0x001e74,[CaseUpper] = 0x001e74}}, - {0x001e75, {[CaseLower] = 0x001e75,[CaseTitle] = 0x001e74,[CaseUpper] = 0x001e74}}, - {0x001e76, {[CaseLower] = 0x001e77,[CaseTitle] = 0x001e76,[CaseUpper] = 0x001e76}}, - {0x001e77, {[CaseLower] = 0x001e77,[CaseTitle] = 0x001e76,[CaseUpper] = 0x001e76}}, - {0x001e78, {[CaseLower] = 0x001e79,[CaseTitle] = 0x001e78,[CaseUpper] = 0x001e78}}, - {0x001e79, {[CaseLower] = 0x001e79,[CaseTitle] = 0x001e78,[CaseUpper] = 0x001e78}}, - {0x001e7a, {[CaseLower] = 0x001e7b,[CaseTitle] = 0x001e7a,[CaseUpper] = 0x001e7a}}, - {0x001e7b, {[CaseLower] = 0x001e7b,[CaseTitle] = 0x001e7a,[CaseUpper] = 0x001e7a}}, - {0x001e7c, {[CaseLower] = 0x001e7d,[CaseTitle] = 0x001e7c,[CaseUpper] = 0x001e7c}}, - {0x001e7d, {[CaseLower] = 0x001e7d,[CaseTitle] = 0x001e7c,[CaseUpper] = 0x001e7c}}, - {0x001e7e, {[CaseLower] = 0x001e7f,[CaseTitle] = 0x001e7e,[CaseUpper] = 0x001e7e}}, - {0x001e7f, {[CaseLower] = 0x001e7f,[CaseTitle] = 0x001e7e,[CaseUpper] = 0x001e7e}}, - {0x001e80, {[CaseLower] = 0x001e81,[CaseTitle] = 0x001e80,[CaseUpper] = 0x001e80}}, - {0x001e81, {[CaseLower] = 0x001e81,[CaseTitle] = 0x001e80,[CaseUpper] = 0x001e80}}, - {0x001e82, {[CaseLower] = 0x001e83,[CaseTitle] = 0x001e82,[CaseUpper] = 0x001e82}}, - {0x001e83, {[CaseLower] = 0x001e83,[CaseTitle] = 0x001e82,[CaseUpper] = 0x001e82}}, - {0x001e84, {[CaseLower] = 0x001e85,[CaseTitle] = 0x001e84,[CaseUpper] = 0x001e84}}, - {0x001e85, {[CaseLower] = 0x001e85,[CaseTitle] = 0x001e84,[CaseUpper] = 0x001e84}}, - {0x001e86, {[CaseLower] = 0x001e87,[CaseTitle] = 0x001e86,[CaseUpper] = 0x001e86}}, - {0x001e87, {[CaseLower] = 0x001e87,[CaseTitle] = 0x001e86,[CaseUpper] = 0x001e86}}, - {0x001e88, {[CaseLower] = 0x001e89,[CaseTitle] = 0x001e88,[CaseUpper] = 0x001e88}}, - {0x001e89, {[CaseLower] = 0x001e89,[CaseTitle] = 0x001e88,[CaseUpper] = 0x001e88}}, - {0x001e8a, {[CaseLower] = 0x001e8b,[CaseTitle] = 0x001e8a,[CaseUpper] = 0x001e8a}}, - {0x001e8b, {[CaseLower] = 0x001e8b,[CaseTitle] = 0x001e8a,[CaseUpper] = 0x001e8a}}, - {0x001e8c, {[CaseLower] = 0x001e8d,[CaseTitle] = 0x001e8c,[CaseUpper] = 0x001e8c}}, - {0x001e8d, {[CaseLower] = 0x001e8d,[CaseTitle] = 0x001e8c,[CaseUpper] = 0x001e8c}}, - {0x001e8e, {[CaseLower] = 0x001e8f,[CaseTitle] = 0x001e8e,[CaseUpper] = 0x001e8e}}, - {0x001e8f, {[CaseLower] = 0x001e8f,[CaseTitle] = 0x001e8e,[CaseUpper] = 0x001e8e}}, - {0x001e90, {[CaseLower] = 0x001e91,[CaseTitle] = 0x001e90,[CaseUpper] = 0x001e90}}, - {0x001e91, {[CaseLower] = 0x001e91,[CaseTitle] = 0x001e90,[CaseUpper] = 0x001e90}}, - {0x001e92, {[CaseLower] = 0x001e93,[CaseTitle] = 0x001e92,[CaseUpper] = 0x001e92}}, - {0x001e93, {[CaseLower] = 0x001e93,[CaseTitle] = 0x001e92,[CaseUpper] = 0x001e92}}, - {0x001e94, {[CaseLower] = 0x001e95,[CaseTitle] = 0x001e94,[CaseUpper] = 0x001e94}}, - {0x001e95, {[CaseLower] = 0x001e95,[CaseTitle] = 0x001e94,[CaseUpper] = 0x001e94}}, - {0x001e9b, {[CaseLower] = 0x001e9b,[CaseTitle] = 0x001e60,[CaseUpper] = 0x001e60}}, - {0x001e9e, {[CaseLower] = 0x0000df,[CaseTitle] = 0x001e9e,[CaseUpper] = 0x001e9e}}, - {0x001ea0, {[CaseLower] = 0x001ea1,[CaseTitle] = 0x001ea0,[CaseUpper] = 0x001ea0}}, - {0x001ea1, {[CaseLower] = 0x001ea1,[CaseTitle] = 0x001ea0,[CaseUpper] = 0x001ea0}}, - {0x001ea2, {[CaseLower] = 0x001ea3,[CaseTitle] = 0x001ea2,[CaseUpper] = 0x001ea2}}, - {0x001ea3, {[CaseLower] = 0x001ea3,[CaseTitle] = 0x001ea2,[CaseUpper] = 0x001ea2}}, - {0x001ea4, {[CaseLower] = 0x001ea5,[CaseTitle] = 0x001ea4,[CaseUpper] = 0x001ea4}}, - {0x001ea5, {[CaseLower] = 0x001ea5,[CaseTitle] = 0x001ea4,[CaseUpper] = 0x001ea4}}, - {0x001ea6, {[CaseLower] = 0x001ea7,[CaseTitle] = 0x001ea6,[CaseUpper] = 0x001ea6}}, - {0x001ea7, {[CaseLower] = 0x001ea7,[CaseTitle] = 0x001ea6,[CaseUpper] = 0x001ea6}}, - {0x001ea8, {[CaseLower] = 0x001ea9,[CaseTitle] = 0x001ea8,[CaseUpper] = 0x001ea8}}, - {0x001ea9, {[CaseLower] = 0x001ea9,[CaseTitle] = 0x001ea8,[CaseUpper] = 0x001ea8}}, - {0x001eaa, {[CaseLower] = 0x001eab,[CaseTitle] = 0x001eaa,[CaseUpper] = 0x001eaa}}, - {0x001eab, {[CaseLower] = 0x001eab,[CaseTitle] = 0x001eaa,[CaseUpper] = 0x001eaa}}, - {0x001eac, {[CaseLower] = 0x001ead,[CaseTitle] = 0x001eac,[CaseUpper] = 0x001eac}}, - {0x001ead, {[CaseLower] = 0x001ead,[CaseTitle] = 0x001eac,[CaseUpper] = 0x001eac}}, - {0x001eae, {[CaseLower] = 0x001eaf,[CaseTitle] = 0x001eae,[CaseUpper] = 0x001eae}}, - {0x001eaf, {[CaseLower] = 0x001eaf,[CaseTitle] = 0x001eae,[CaseUpper] = 0x001eae}}, - {0x001eb0, {[CaseLower] = 0x001eb1,[CaseTitle] = 0x001eb0,[CaseUpper] = 0x001eb0}}, - {0x001eb1, {[CaseLower] = 0x001eb1,[CaseTitle] = 0x001eb0,[CaseUpper] = 0x001eb0}}, - {0x001eb2, {[CaseLower] = 0x001eb3,[CaseTitle] = 0x001eb2,[CaseUpper] = 0x001eb2}}, - {0x001eb3, {[CaseLower] = 0x001eb3,[CaseTitle] = 0x001eb2,[CaseUpper] = 0x001eb2}}, - {0x001eb4, {[CaseLower] = 0x001eb5,[CaseTitle] = 0x001eb4,[CaseUpper] = 0x001eb4}}, - {0x001eb5, {[CaseLower] = 0x001eb5,[CaseTitle] = 0x001eb4,[CaseUpper] = 0x001eb4}}, - {0x001eb6, {[CaseLower] = 0x001eb7,[CaseTitle] = 0x001eb6,[CaseUpper] = 0x001eb6}}, - {0x001eb7, {[CaseLower] = 0x001eb7,[CaseTitle] = 0x001eb6,[CaseUpper] = 0x001eb6}}, - {0x001eb8, {[CaseLower] = 0x001eb9,[CaseTitle] = 0x001eb8,[CaseUpper] = 0x001eb8}}, - {0x001eb9, {[CaseLower] = 0x001eb9,[CaseTitle] = 0x001eb8,[CaseUpper] = 0x001eb8}}, - {0x001eba, {[CaseLower] = 0x001ebb,[CaseTitle] = 0x001eba,[CaseUpper] = 0x001eba}}, - {0x001ebb, {[CaseLower] = 0x001ebb,[CaseTitle] = 0x001eba,[CaseUpper] = 0x001eba}}, - {0x001ebc, {[CaseLower] = 0x001ebd,[CaseTitle] = 0x001ebc,[CaseUpper] = 0x001ebc}}, - {0x001ebd, {[CaseLower] = 0x001ebd,[CaseTitle] = 0x001ebc,[CaseUpper] = 0x001ebc}}, - {0x001ebe, {[CaseLower] = 0x001ebf,[CaseTitle] = 0x001ebe,[CaseUpper] = 0x001ebe}}, - {0x001ebf, {[CaseLower] = 0x001ebf,[CaseTitle] = 0x001ebe,[CaseUpper] = 0x001ebe}}, - {0x001ec0, {[CaseLower] = 0x001ec1,[CaseTitle] = 0x001ec0,[CaseUpper] = 0x001ec0}}, - {0x001ec1, {[CaseLower] = 0x001ec1,[CaseTitle] = 0x001ec0,[CaseUpper] = 0x001ec0}}, - {0x001ec2, {[CaseLower] = 0x001ec3,[CaseTitle] = 0x001ec2,[CaseUpper] = 0x001ec2}}, - {0x001ec3, {[CaseLower] = 0x001ec3,[CaseTitle] = 0x001ec2,[CaseUpper] = 0x001ec2}}, - {0x001ec4, {[CaseLower] = 0x001ec5,[CaseTitle] = 0x001ec4,[CaseUpper] = 0x001ec4}}, - {0x001ec5, {[CaseLower] = 0x001ec5,[CaseTitle] = 0x001ec4,[CaseUpper] = 0x001ec4}}, - {0x001ec6, {[CaseLower] = 0x001ec7,[CaseTitle] = 0x001ec6,[CaseUpper] = 0x001ec6}}, - {0x001ec7, {[CaseLower] = 0x001ec7,[CaseTitle] = 0x001ec6,[CaseUpper] = 0x001ec6}}, - {0x001ec8, {[CaseLower] = 0x001ec9,[CaseTitle] = 0x001ec8,[CaseUpper] = 0x001ec8}}, - {0x001ec9, {[CaseLower] = 0x001ec9,[CaseTitle] = 0x001ec8,[CaseUpper] = 0x001ec8}}, - {0x001eca, {[CaseLower] = 0x001ecb,[CaseTitle] = 0x001eca,[CaseUpper] = 0x001eca}}, - {0x001ecb, {[CaseLower] = 0x001ecb,[CaseTitle] = 0x001eca,[CaseUpper] = 0x001eca}}, - {0x001ecc, {[CaseLower] = 0x001ecd,[CaseTitle] = 0x001ecc,[CaseUpper] = 0x001ecc}}, - {0x001ecd, {[CaseLower] = 0x001ecd,[CaseTitle] = 0x001ecc,[CaseUpper] = 0x001ecc}}, - {0x001ece, {[CaseLower] = 0x001ecf,[CaseTitle] = 0x001ece,[CaseUpper] = 0x001ece}}, - {0x001ecf, {[CaseLower] = 0x001ecf,[CaseTitle] = 0x001ece,[CaseUpper] = 0x001ece}}, - {0x001ed0, {[CaseLower] = 0x001ed1,[CaseTitle] = 0x001ed0,[CaseUpper] = 0x001ed0}}, - {0x001ed1, {[CaseLower] = 0x001ed1,[CaseTitle] = 0x001ed0,[CaseUpper] = 0x001ed0}}, - {0x001ed2, {[CaseLower] = 0x001ed3,[CaseTitle] = 0x001ed2,[CaseUpper] = 0x001ed2}}, - {0x001ed3, {[CaseLower] = 0x001ed3,[CaseTitle] = 0x001ed2,[CaseUpper] = 0x001ed2}}, - {0x001ed4, {[CaseLower] = 0x001ed5,[CaseTitle] = 0x001ed4,[CaseUpper] = 0x001ed4}}, - {0x001ed5, {[CaseLower] = 0x001ed5,[CaseTitle] = 0x001ed4,[CaseUpper] = 0x001ed4}}, - {0x001ed6, {[CaseLower] = 0x001ed7,[CaseTitle] = 0x001ed6,[CaseUpper] = 0x001ed6}}, - {0x001ed7, {[CaseLower] = 0x001ed7,[CaseTitle] = 0x001ed6,[CaseUpper] = 0x001ed6}}, - {0x001ed8, {[CaseLower] = 0x001ed9,[CaseTitle] = 0x001ed8,[CaseUpper] = 0x001ed8}}, - {0x001ed9, {[CaseLower] = 0x001ed9,[CaseTitle] = 0x001ed8,[CaseUpper] = 0x001ed8}}, - {0x001eda, {[CaseLower] = 0x001edb,[CaseTitle] = 0x001eda,[CaseUpper] = 0x001eda}}, - {0x001edb, {[CaseLower] = 0x001edb,[CaseTitle] = 0x001eda,[CaseUpper] = 0x001eda}}, - {0x001edc, {[CaseLower] = 0x001edd,[CaseTitle] = 0x001edc,[CaseUpper] = 0x001edc}}, - {0x001edd, {[CaseLower] = 0x001edd,[CaseTitle] = 0x001edc,[CaseUpper] = 0x001edc}}, - {0x001ede, {[CaseLower] = 0x001edf,[CaseTitle] = 0x001ede,[CaseUpper] = 0x001ede}}, - {0x001edf, {[CaseLower] = 0x001edf,[CaseTitle] = 0x001ede,[CaseUpper] = 0x001ede}}, - {0x001ee0, {[CaseLower] = 0x001ee1,[CaseTitle] = 0x001ee0,[CaseUpper] = 0x001ee0}}, - {0x001ee1, {[CaseLower] = 0x001ee1,[CaseTitle] = 0x001ee0,[CaseUpper] = 0x001ee0}}, - {0x001ee2, {[CaseLower] = 0x001ee3,[CaseTitle] = 0x001ee2,[CaseUpper] = 0x001ee2}}, - {0x001ee3, {[CaseLower] = 0x001ee3,[CaseTitle] = 0x001ee2,[CaseUpper] = 0x001ee2}}, - {0x001ee4, {[CaseLower] = 0x001ee5,[CaseTitle] = 0x001ee4,[CaseUpper] = 0x001ee4}}, - {0x001ee5, {[CaseLower] = 0x001ee5,[CaseTitle] = 0x001ee4,[CaseUpper] = 0x001ee4}}, - {0x001ee6, {[CaseLower] = 0x001ee7,[CaseTitle] = 0x001ee6,[CaseUpper] = 0x001ee6}}, - {0x001ee7, {[CaseLower] = 0x001ee7,[CaseTitle] = 0x001ee6,[CaseUpper] = 0x001ee6}}, - {0x001ee8, {[CaseLower] = 0x001ee9,[CaseTitle] = 0x001ee8,[CaseUpper] = 0x001ee8}}, - {0x001ee9, {[CaseLower] = 0x001ee9,[CaseTitle] = 0x001ee8,[CaseUpper] = 0x001ee8}}, - {0x001eea, {[CaseLower] = 0x001eeb,[CaseTitle] = 0x001eea,[CaseUpper] = 0x001eea}}, - {0x001eeb, {[CaseLower] = 0x001eeb,[CaseTitle] = 0x001eea,[CaseUpper] = 0x001eea}}, - {0x001eec, {[CaseLower] = 0x001eed,[CaseTitle] = 0x001eec,[CaseUpper] = 0x001eec}}, - {0x001eed, {[CaseLower] = 0x001eed,[CaseTitle] = 0x001eec,[CaseUpper] = 0x001eec}}, - {0x001eee, {[CaseLower] = 0x001eef,[CaseTitle] = 0x001eee,[CaseUpper] = 0x001eee}}, - {0x001eef, {[CaseLower] = 0x001eef,[CaseTitle] = 0x001eee,[CaseUpper] = 0x001eee}}, - {0x001ef0, {[CaseLower] = 0x001ef1,[CaseTitle] = 0x001ef0,[CaseUpper] = 0x001ef0}}, - {0x001ef1, {[CaseLower] = 0x001ef1,[CaseTitle] = 0x001ef0,[CaseUpper] = 0x001ef0}}, - {0x001ef2, {[CaseLower] = 0x001ef3,[CaseTitle] = 0x001ef2,[CaseUpper] = 0x001ef2}}, - {0x001ef3, {[CaseLower] = 0x001ef3,[CaseTitle] = 0x001ef2,[CaseUpper] = 0x001ef2}}, - {0x001ef4, {[CaseLower] = 0x001ef5,[CaseTitle] = 0x001ef4,[CaseUpper] = 0x001ef4}}, - {0x001ef5, {[CaseLower] = 0x001ef5,[CaseTitle] = 0x001ef4,[CaseUpper] = 0x001ef4}}, - {0x001ef6, {[CaseLower] = 0x001ef7,[CaseTitle] = 0x001ef6,[CaseUpper] = 0x001ef6}}, - {0x001ef7, {[CaseLower] = 0x001ef7,[CaseTitle] = 0x001ef6,[CaseUpper] = 0x001ef6}}, - {0x001ef8, {[CaseLower] = 0x001ef9,[CaseTitle] = 0x001ef8,[CaseUpper] = 0x001ef8}}, - {0x001ef9, {[CaseLower] = 0x001ef9,[CaseTitle] = 0x001ef8,[CaseUpper] = 0x001ef8}}, - {0x001efa, {[CaseLower] = 0x001efb,[CaseTitle] = 0x001efa,[CaseUpper] = 0x001efa}}, - {0x001efb, {[CaseLower] = 0x001efb,[CaseTitle] = 0x001efa,[CaseUpper] = 0x001efa}}, - {0x001efc, {[CaseLower] = 0x001efd,[CaseTitle] = 0x001efc,[CaseUpper] = 0x001efc}}, - {0x001efd, {[CaseLower] = 0x001efd,[CaseTitle] = 0x001efc,[CaseUpper] = 0x001efc}}, - {0x001efe, {[CaseLower] = 0x001eff,[CaseTitle] = 0x001efe,[CaseUpper] = 0x001efe}}, - {0x001eff, {[CaseLower] = 0x001eff,[CaseTitle] = 0x001efe,[CaseUpper] = 0x001efe}}, - {0x001f00, {[CaseLower] = 0x001f00,[CaseTitle] = 0x001f08,[CaseUpper] = 0x001f08}}, - {0x001f01, {[CaseLower] = 0x001f01,[CaseTitle] = 0x001f09,[CaseUpper] = 0x001f09}}, - {0x001f02, {[CaseLower] = 0x001f02,[CaseTitle] = 0x001f0a,[CaseUpper] = 0x001f0a}}, - {0x001f03, {[CaseLower] = 0x001f03,[CaseTitle] = 0x001f0b,[CaseUpper] = 0x001f0b}}, - {0x001f04, {[CaseLower] = 0x001f04,[CaseTitle] = 0x001f0c,[CaseUpper] = 0x001f0c}}, - {0x001f05, {[CaseLower] = 0x001f05,[CaseTitle] = 0x001f0d,[CaseUpper] = 0x001f0d}}, - {0x001f06, {[CaseLower] = 0x001f06,[CaseTitle] = 0x001f0e,[CaseUpper] = 0x001f0e}}, - {0x001f07, {[CaseLower] = 0x001f07,[CaseTitle] = 0x001f0f,[CaseUpper] = 0x001f0f}}, - {0x001f08, {[CaseLower] = 0x001f00,[CaseTitle] = 0x001f08,[CaseUpper] = 0x001f08}}, - {0x001f09, {[CaseLower] = 0x001f01,[CaseTitle] = 0x001f09,[CaseUpper] = 0x001f09}}, - {0x001f0a, {[CaseLower] = 0x001f02,[CaseTitle] = 0x001f0a,[CaseUpper] = 0x001f0a}}, - {0x001f0b, {[CaseLower] = 0x001f03,[CaseTitle] = 0x001f0b,[CaseUpper] = 0x001f0b}}, - {0x001f0c, {[CaseLower] = 0x001f04,[CaseTitle] = 0x001f0c,[CaseUpper] = 0x001f0c}}, - {0x001f0d, {[CaseLower] = 0x001f05,[CaseTitle] = 0x001f0d,[CaseUpper] = 0x001f0d}}, - {0x001f0e, {[CaseLower] = 0x001f06,[CaseTitle] = 0x001f0e,[CaseUpper] = 0x001f0e}}, - {0x001f0f, {[CaseLower] = 0x001f07,[CaseTitle] = 0x001f0f,[CaseUpper] = 0x001f0f}}, - {0x001f10, {[CaseLower] = 0x001f10,[CaseTitle] = 0x001f18,[CaseUpper] = 0x001f18}}, - {0x001f11, {[CaseLower] = 0x001f11,[CaseTitle] = 0x001f19,[CaseUpper] = 0x001f19}}, - {0x001f12, {[CaseLower] = 0x001f12,[CaseTitle] = 0x001f1a,[CaseUpper] = 0x001f1a}}, - {0x001f13, {[CaseLower] = 0x001f13,[CaseTitle] = 0x001f1b,[CaseUpper] = 0x001f1b}}, - {0x001f14, {[CaseLower] = 0x001f14,[CaseTitle] = 0x001f1c,[CaseUpper] = 0x001f1c}}, - {0x001f15, {[CaseLower] = 0x001f15,[CaseTitle] = 0x001f1d,[CaseUpper] = 0x001f1d}}, - {0x001f18, {[CaseLower] = 0x001f10,[CaseTitle] = 0x001f18,[CaseUpper] = 0x001f18}}, - {0x001f19, {[CaseLower] = 0x001f11,[CaseTitle] = 0x001f19,[CaseUpper] = 0x001f19}}, - {0x001f1a, {[CaseLower] = 0x001f12,[CaseTitle] = 0x001f1a,[CaseUpper] = 0x001f1a}}, - {0x001f1b, {[CaseLower] = 0x001f13,[CaseTitle] = 0x001f1b,[CaseUpper] = 0x001f1b}}, - {0x001f1c, {[CaseLower] = 0x001f14,[CaseTitle] = 0x001f1c,[CaseUpper] = 0x001f1c}}, - {0x001f1d, {[CaseLower] = 0x001f15,[CaseTitle] = 0x001f1d,[CaseUpper] = 0x001f1d}}, - {0x001f20, {[CaseLower] = 0x001f20,[CaseTitle] = 0x001f28,[CaseUpper] = 0x001f28}}, - {0x001f21, {[CaseLower] = 0x001f21,[CaseTitle] = 0x001f29,[CaseUpper] = 0x001f29}}, - {0x001f22, {[CaseLower] = 0x001f22,[CaseTitle] = 0x001f2a,[CaseUpper] = 0x001f2a}}, - {0x001f23, {[CaseLower] = 0x001f23,[CaseTitle] = 0x001f2b,[CaseUpper] = 0x001f2b}}, - {0x001f24, {[CaseLower] = 0x001f24,[CaseTitle] = 0x001f2c,[CaseUpper] = 0x001f2c}}, - {0x001f25, {[CaseLower] = 0x001f25,[CaseTitle] = 0x001f2d,[CaseUpper] = 0x001f2d}}, - {0x001f26, {[CaseLower] = 0x001f26,[CaseTitle] = 0x001f2e,[CaseUpper] = 0x001f2e}}, - {0x001f27, {[CaseLower] = 0x001f27,[CaseTitle] = 0x001f2f,[CaseUpper] = 0x001f2f}}, - {0x001f28, {[CaseLower] = 0x001f20,[CaseTitle] = 0x001f28,[CaseUpper] = 0x001f28}}, - {0x001f29, {[CaseLower] = 0x001f21,[CaseTitle] = 0x001f29,[CaseUpper] = 0x001f29}}, - {0x001f2a, {[CaseLower] = 0x001f22,[CaseTitle] = 0x001f2a,[CaseUpper] = 0x001f2a}}, - {0x001f2b, {[CaseLower] = 0x001f23,[CaseTitle] = 0x001f2b,[CaseUpper] = 0x001f2b}}, - {0x001f2c, {[CaseLower] = 0x001f24,[CaseTitle] = 0x001f2c,[CaseUpper] = 0x001f2c}}, - {0x001f2d, {[CaseLower] = 0x001f25,[CaseTitle] = 0x001f2d,[CaseUpper] = 0x001f2d}}, - {0x001f2e, {[CaseLower] = 0x001f26,[CaseTitle] = 0x001f2e,[CaseUpper] = 0x001f2e}}, - {0x001f2f, {[CaseLower] = 0x001f27,[CaseTitle] = 0x001f2f,[CaseUpper] = 0x001f2f}}, - {0x001f30, {[CaseLower] = 0x001f30,[CaseTitle] = 0x001f38,[CaseUpper] = 0x001f38}}, - {0x001f31, {[CaseLower] = 0x001f31,[CaseTitle] = 0x001f39,[CaseUpper] = 0x001f39}}, - {0x001f32, {[CaseLower] = 0x001f32,[CaseTitle] = 0x001f3a,[CaseUpper] = 0x001f3a}}, - {0x001f33, {[CaseLower] = 0x001f33,[CaseTitle] = 0x001f3b,[CaseUpper] = 0x001f3b}}, - {0x001f34, {[CaseLower] = 0x001f34,[CaseTitle] = 0x001f3c,[CaseUpper] = 0x001f3c}}, - {0x001f35, {[CaseLower] = 0x001f35,[CaseTitle] = 0x001f3d,[CaseUpper] = 0x001f3d}}, - {0x001f36, {[CaseLower] = 0x001f36,[CaseTitle] = 0x001f3e,[CaseUpper] = 0x001f3e}}, - {0x001f37, {[CaseLower] = 0x001f37,[CaseTitle] = 0x001f3f,[CaseUpper] = 0x001f3f}}, - {0x001f38, {[CaseLower] = 0x001f30,[CaseTitle] = 0x001f38,[CaseUpper] = 0x001f38}}, - {0x001f39, {[CaseLower] = 0x001f31,[CaseTitle] = 0x001f39,[CaseUpper] = 0x001f39}}, - {0x001f3a, {[CaseLower] = 0x001f32,[CaseTitle] = 0x001f3a,[CaseUpper] = 0x001f3a}}, - {0x001f3b, {[CaseLower] = 0x001f33,[CaseTitle] = 0x001f3b,[CaseUpper] = 0x001f3b}}, - {0x001f3c, {[CaseLower] = 0x001f34,[CaseTitle] = 0x001f3c,[CaseUpper] = 0x001f3c}}, - {0x001f3d, {[CaseLower] = 0x001f35,[CaseTitle] = 0x001f3d,[CaseUpper] = 0x001f3d}}, - {0x001f3e, {[CaseLower] = 0x001f36,[CaseTitle] = 0x001f3e,[CaseUpper] = 0x001f3e}}, - {0x001f3f, {[CaseLower] = 0x001f37,[CaseTitle] = 0x001f3f,[CaseUpper] = 0x001f3f}}, - {0x001f40, {[CaseLower] = 0x001f40,[CaseTitle] = 0x001f48,[CaseUpper] = 0x001f48}}, - {0x001f41, {[CaseLower] = 0x001f41,[CaseTitle] = 0x001f49,[CaseUpper] = 0x001f49}}, - {0x001f42, {[CaseLower] = 0x001f42,[CaseTitle] = 0x001f4a,[CaseUpper] = 0x001f4a}}, - {0x001f43, {[CaseLower] = 0x001f43,[CaseTitle] = 0x001f4b,[CaseUpper] = 0x001f4b}}, - {0x001f44, {[CaseLower] = 0x001f44,[CaseTitle] = 0x001f4c,[CaseUpper] = 0x001f4c}}, - {0x001f45, {[CaseLower] = 0x001f45,[CaseTitle] = 0x001f4d,[CaseUpper] = 0x001f4d}}, - {0x001f48, {[CaseLower] = 0x001f40,[CaseTitle] = 0x001f48,[CaseUpper] = 0x001f48}}, - {0x001f49, {[CaseLower] = 0x001f41,[CaseTitle] = 0x001f49,[CaseUpper] = 0x001f49}}, - {0x001f4a, {[CaseLower] = 0x001f42,[CaseTitle] = 0x001f4a,[CaseUpper] = 0x001f4a}}, - {0x001f4b, {[CaseLower] = 0x001f43,[CaseTitle] = 0x001f4b,[CaseUpper] = 0x001f4b}}, - {0x001f4c, {[CaseLower] = 0x001f44,[CaseTitle] = 0x001f4c,[CaseUpper] = 0x001f4c}}, - {0x001f4d, {[CaseLower] = 0x001f45,[CaseTitle] = 0x001f4d,[CaseUpper] = 0x001f4d}}, - {0x001f51, {[CaseLower] = 0x001f51,[CaseTitle] = 0x001f59,[CaseUpper] = 0x001f59}}, - {0x001f53, {[CaseLower] = 0x001f53,[CaseTitle] = 0x001f5b,[CaseUpper] = 0x001f5b}}, - {0x001f55, {[CaseLower] = 0x001f55,[CaseTitle] = 0x001f5d,[CaseUpper] = 0x001f5d}}, - {0x001f57, {[CaseLower] = 0x001f57,[CaseTitle] = 0x001f5f,[CaseUpper] = 0x001f5f}}, - {0x001f59, {[CaseLower] = 0x001f51,[CaseTitle] = 0x001f59,[CaseUpper] = 0x001f59}}, - {0x001f5b, {[CaseLower] = 0x001f53,[CaseTitle] = 0x001f5b,[CaseUpper] = 0x001f5b}}, - {0x001f5d, {[CaseLower] = 0x001f55,[CaseTitle] = 0x001f5d,[CaseUpper] = 0x001f5d}}, - {0x001f5f, {[CaseLower] = 0x001f57,[CaseTitle] = 0x001f5f,[CaseUpper] = 0x001f5f}}, - {0x001f60, {[CaseLower] = 0x001f60,[CaseTitle] = 0x001f68,[CaseUpper] = 0x001f68}}, - {0x001f61, {[CaseLower] = 0x001f61,[CaseTitle] = 0x001f69,[CaseUpper] = 0x001f69}}, - {0x001f62, {[CaseLower] = 0x001f62,[CaseTitle] = 0x001f6a,[CaseUpper] = 0x001f6a}}, - {0x001f63, {[CaseLower] = 0x001f63,[CaseTitle] = 0x001f6b,[CaseUpper] = 0x001f6b}}, - {0x001f64, {[CaseLower] = 0x001f64,[CaseTitle] = 0x001f6c,[CaseUpper] = 0x001f6c}}, - {0x001f65, {[CaseLower] = 0x001f65,[CaseTitle] = 0x001f6d,[CaseUpper] = 0x001f6d}}, - {0x001f66, {[CaseLower] = 0x001f66,[CaseTitle] = 0x001f6e,[CaseUpper] = 0x001f6e}}, - {0x001f67, {[CaseLower] = 0x001f67,[CaseTitle] = 0x001f6f,[CaseUpper] = 0x001f6f}}, - {0x001f68, {[CaseLower] = 0x001f60,[CaseTitle] = 0x001f68,[CaseUpper] = 0x001f68}}, - {0x001f69, {[CaseLower] = 0x001f61,[CaseTitle] = 0x001f69,[CaseUpper] = 0x001f69}}, - {0x001f6a, {[CaseLower] = 0x001f62,[CaseTitle] = 0x001f6a,[CaseUpper] = 0x001f6a}}, - {0x001f6b, {[CaseLower] = 0x001f63,[CaseTitle] = 0x001f6b,[CaseUpper] = 0x001f6b}}, - {0x001f6c, {[CaseLower] = 0x001f64,[CaseTitle] = 0x001f6c,[CaseUpper] = 0x001f6c}}, - {0x001f6d, {[CaseLower] = 0x001f65,[CaseTitle] = 0x001f6d,[CaseUpper] = 0x001f6d}}, - {0x001f6e, {[CaseLower] = 0x001f66,[CaseTitle] = 0x001f6e,[CaseUpper] = 0x001f6e}}, - {0x001f6f, {[CaseLower] = 0x001f67,[CaseTitle] = 0x001f6f,[CaseUpper] = 0x001f6f}}, - {0x001f70, {[CaseLower] = 0x001f70,[CaseTitle] = 0x001fba,[CaseUpper] = 0x001fba}}, - {0x001f71, {[CaseLower] = 0x001f71,[CaseTitle] = 0x001fbb,[CaseUpper] = 0x001fbb}}, - {0x001f72, {[CaseLower] = 0x001f72,[CaseTitle] = 0x001fc8,[CaseUpper] = 0x001fc8}}, - {0x001f73, {[CaseLower] = 0x001f73,[CaseTitle] = 0x001fc9,[CaseUpper] = 0x001fc9}}, - {0x001f74, {[CaseLower] = 0x001f74,[CaseTitle] = 0x001fca,[CaseUpper] = 0x001fca}}, - {0x001f75, {[CaseLower] = 0x001f75,[CaseTitle] = 0x001fcb,[CaseUpper] = 0x001fcb}}, - {0x001f76, {[CaseLower] = 0x001f76,[CaseTitle] = 0x001fda,[CaseUpper] = 0x001fda}}, - {0x001f77, {[CaseLower] = 0x001f77,[CaseTitle] = 0x001fdb,[CaseUpper] = 0x001fdb}}, - {0x001f78, {[CaseLower] = 0x001f78,[CaseTitle] = 0x001ff8,[CaseUpper] = 0x001ff8}}, - {0x001f79, {[CaseLower] = 0x001f79,[CaseTitle] = 0x001ff9,[CaseUpper] = 0x001ff9}}, - {0x001f7a, {[CaseLower] = 0x001f7a,[CaseTitle] = 0x001fea,[CaseUpper] = 0x001fea}}, - {0x001f7b, {[CaseLower] = 0x001f7b,[CaseTitle] = 0x001feb,[CaseUpper] = 0x001feb}}, - {0x001f7c, {[CaseLower] = 0x001f7c,[CaseTitle] = 0x001ffa,[CaseUpper] = 0x001ffa}}, - {0x001f7d, {[CaseLower] = 0x001f7d,[CaseTitle] = 0x001ffb,[CaseUpper] = 0x001ffb}}, - {0x001f80, {[CaseLower] = 0x001f80,[CaseTitle] = 0x001f88,[CaseUpper] = 0x001f88}}, - {0x001f81, {[CaseLower] = 0x001f81,[CaseTitle] = 0x001f89,[CaseUpper] = 0x001f89}}, - {0x001f82, {[CaseLower] = 0x001f82,[CaseTitle] = 0x001f8a,[CaseUpper] = 0x001f8a}}, - {0x001f83, {[CaseLower] = 0x001f83,[CaseTitle] = 0x001f8b,[CaseUpper] = 0x001f8b}}, - {0x001f84, {[CaseLower] = 0x001f84,[CaseTitle] = 0x001f8c,[CaseUpper] = 0x001f8c}}, - {0x001f85, {[CaseLower] = 0x001f85,[CaseTitle] = 0x001f8d,[CaseUpper] = 0x001f8d}}, - {0x001f86, {[CaseLower] = 0x001f86,[CaseTitle] = 0x001f8e,[CaseUpper] = 0x001f8e}}, - {0x001f87, {[CaseLower] = 0x001f87,[CaseTitle] = 0x001f8f,[CaseUpper] = 0x001f8f}}, - {0x001f88, {[CaseLower] = 0x001f80,[CaseTitle] = 0x001f88,[CaseUpper] = 0x001f88}}, - {0x001f89, {[CaseLower] = 0x001f81,[CaseTitle] = 0x001f89,[CaseUpper] = 0x001f89}}, - {0x001f8a, {[CaseLower] = 0x001f82,[CaseTitle] = 0x001f8a,[CaseUpper] = 0x001f8a}}, - {0x001f8b, {[CaseLower] = 0x001f83,[CaseTitle] = 0x001f8b,[CaseUpper] = 0x001f8b}}, - {0x001f8c, {[CaseLower] = 0x001f84,[CaseTitle] = 0x001f8c,[CaseUpper] = 0x001f8c}}, - {0x001f8d, {[CaseLower] = 0x001f85,[CaseTitle] = 0x001f8d,[CaseUpper] = 0x001f8d}}, - {0x001f8e, {[CaseLower] = 0x001f86,[CaseTitle] = 0x001f8e,[CaseUpper] = 0x001f8e}}, - {0x001f8f, {[CaseLower] = 0x001f87,[CaseTitle] = 0x001f8f,[CaseUpper] = 0x001f8f}}, - {0x001f90, {[CaseLower] = 0x001f90,[CaseTitle] = 0x001f98,[CaseUpper] = 0x001f98}}, - {0x001f91, {[CaseLower] = 0x001f91,[CaseTitle] = 0x001f99,[CaseUpper] = 0x001f99}}, - {0x001f92, {[CaseLower] = 0x001f92,[CaseTitle] = 0x001f9a,[CaseUpper] = 0x001f9a}}, - {0x001f93, {[CaseLower] = 0x001f93,[CaseTitle] = 0x001f9b,[CaseUpper] = 0x001f9b}}, - {0x001f94, {[CaseLower] = 0x001f94,[CaseTitle] = 0x001f9c,[CaseUpper] = 0x001f9c}}, - {0x001f95, {[CaseLower] = 0x001f95,[CaseTitle] = 0x001f9d,[CaseUpper] = 0x001f9d}}, - {0x001f96, {[CaseLower] = 0x001f96,[CaseTitle] = 0x001f9e,[CaseUpper] = 0x001f9e}}, - {0x001f97, {[CaseLower] = 0x001f97,[CaseTitle] = 0x001f9f,[CaseUpper] = 0x001f9f}}, - {0x001f98, {[CaseLower] = 0x001f90,[CaseTitle] = 0x001f98,[CaseUpper] = 0x001f98}}, - {0x001f99, {[CaseLower] = 0x001f91,[CaseTitle] = 0x001f99,[CaseUpper] = 0x001f99}}, - {0x001f9a, {[CaseLower] = 0x001f92,[CaseTitle] = 0x001f9a,[CaseUpper] = 0x001f9a}}, - {0x001f9b, {[CaseLower] = 0x001f93,[CaseTitle] = 0x001f9b,[CaseUpper] = 0x001f9b}}, - {0x001f9c, {[CaseLower] = 0x001f94,[CaseTitle] = 0x001f9c,[CaseUpper] = 0x001f9c}}, - {0x001f9d, {[CaseLower] = 0x001f95,[CaseTitle] = 0x001f9d,[CaseUpper] = 0x001f9d}}, - {0x001f9e, {[CaseLower] = 0x001f96,[CaseTitle] = 0x001f9e,[CaseUpper] = 0x001f9e}}, - {0x001f9f, {[CaseLower] = 0x001f97,[CaseTitle] = 0x001f9f,[CaseUpper] = 0x001f9f}}, - {0x001fa0, {[CaseLower] = 0x001fa0,[CaseTitle] = 0x001fa8,[CaseUpper] = 0x001fa8}}, - {0x001fa1, {[CaseLower] = 0x001fa1,[CaseTitle] = 0x001fa9,[CaseUpper] = 0x001fa9}}, - {0x001fa2, {[CaseLower] = 0x001fa2,[CaseTitle] = 0x001faa,[CaseUpper] = 0x001faa}}, - {0x001fa3, {[CaseLower] = 0x001fa3,[CaseTitle] = 0x001fab,[CaseUpper] = 0x001fab}}, - {0x001fa4, {[CaseLower] = 0x001fa4,[CaseTitle] = 0x001fac,[CaseUpper] = 0x001fac}}, - {0x001fa5, {[CaseLower] = 0x001fa5,[CaseTitle] = 0x001fad,[CaseUpper] = 0x001fad}}, - {0x001fa6, {[CaseLower] = 0x001fa6,[CaseTitle] = 0x001fae,[CaseUpper] = 0x001fae}}, - {0x001fa7, {[CaseLower] = 0x001fa7,[CaseTitle] = 0x001faf,[CaseUpper] = 0x001faf}}, - {0x001fa8, {[CaseLower] = 0x001fa0,[CaseTitle] = 0x001fa8,[CaseUpper] = 0x001fa8}}, - {0x001fa9, {[CaseLower] = 0x001fa1,[CaseTitle] = 0x001fa9,[CaseUpper] = 0x001fa9}}, - {0x001faa, {[CaseLower] = 0x001fa2,[CaseTitle] = 0x001faa,[CaseUpper] = 0x001faa}}, - {0x001fab, {[CaseLower] = 0x001fa3,[CaseTitle] = 0x001fab,[CaseUpper] = 0x001fab}}, - {0x001fac, {[CaseLower] = 0x001fa4,[CaseTitle] = 0x001fac,[CaseUpper] = 0x001fac}}, - {0x001fad, {[CaseLower] = 0x001fa5,[CaseTitle] = 0x001fad,[CaseUpper] = 0x001fad}}, - {0x001fae, {[CaseLower] = 0x001fa6,[CaseTitle] = 0x001fae,[CaseUpper] = 0x001fae}}, - {0x001faf, {[CaseLower] = 0x001fa7,[CaseTitle] = 0x001faf,[CaseUpper] = 0x001faf}}, - {0x001fb0, {[CaseLower] = 0x001fb0,[CaseTitle] = 0x001fb8,[CaseUpper] = 0x001fb8}}, - {0x001fb1, {[CaseLower] = 0x001fb1,[CaseTitle] = 0x001fb9,[CaseUpper] = 0x001fb9}}, - {0x001fb3, {[CaseLower] = 0x001fb3,[CaseTitle] = 0x001fbc,[CaseUpper] = 0x001fbc}}, - {0x001fb8, {[CaseLower] = 0x001fb0,[CaseTitle] = 0x001fb8,[CaseUpper] = 0x001fb8}}, - {0x001fb9, {[CaseLower] = 0x001fb1,[CaseTitle] = 0x001fb9,[CaseUpper] = 0x001fb9}}, - {0x001fba, {[CaseLower] = 0x001f70,[CaseTitle] = 0x001fba,[CaseUpper] = 0x001fba}}, - {0x001fbb, {[CaseLower] = 0x001f71,[CaseTitle] = 0x001fbb,[CaseUpper] = 0x001fbb}}, - {0x001fbc, {[CaseLower] = 0x001fb3,[CaseTitle] = 0x001fbc,[CaseUpper] = 0x001fbc}}, - {0x001fbe, {[CaseLower] = 0x001fbe,[CaseTitle] = 0x000399,[CaseUpper] = 0x000399}}, - {0x001fc3, {[CaseLower] = 0x001fc3,[CaseTitle] = 0x001fcc,[CaseUpper] = 0x001fcc}}, - {0x001fc8, {[CaseLower] = 0x001f72,[CaseTitle] = 0x001fc8,[CaseUpper] = 0x001fc8}}, - {0x001fc9, {[CaseLower] = 0x001f73,[CaseTitle] = 0x001fc9,[CaseUpper] = 0x001fc9}}, - {0x001fca, {[CaseLower] = 0x001f74,[CaseTitle] = 0x001fca,[CaseUpper] = 0x001fca}}, - {0x001fcb, {[CaseLower] = 0x001f75,[CaseTitle] = 0x001fcb,[CaseUpper] = 0x001fcb}}, - {0x001fcc, {[CaseLower] = 0x001fc3,[CaseTitle] = 0x001fcc,[CaseUpper] = 0x001fcc}}, - {0x001fd0, {[CaseLower] = 0x001fd0,[CaseTitle] = 0x001fd8,[CaseUpper] = 0x001fd8}}, - {0x001fd1, {[CaseLower] = 0x001fd1,[CaseTitle] = 0x001fd9,[CaseUpper] = 0x001fd9}}, - {0x001fd8, {[CaseLower] = 0x001fd0,[CaseTitle] = 0x001fd8,[CaseUpper] = 0x001fd8}}, - {0x001fd9, {[CaseLower] = 0x001fd1,[CaseTitle] = 0x001fd9,[CaseUpper] = 0x001fd9}}, - {0x001fda, {[CaseLower] = 0x001f76,[CaseTitle] = 0x001fda,[CaseUpper] = 0x001fda}}, - {0x001fdb, {[CaseLower] = 0x001f77,[CaseTitle] = 0x001fdb,[CaseUpper] = 0x001fdb}}, - {0x001fe0, {[CaseLower] = 0x001fe0,[CaseTitle] = 0x001fe8,[CaseUpper] = 0x001fe8}}, - {0x001fe1, {[CaseLower] = 0x001fe1,[CaseTitle] = 0x001fe9,[CaseUpper] = 0x001fe9}}, - {0x001fe5, {[CaseLower] = 0x001fe5,[CaseTitle] = 0x001fec,[CaseUpper] = 0x001fec}}, - {0x001fe8, {[CaseLower] = 0x001fe0,[CaseTitle] = 0x001fe8,[CaseUpper] = 0x001fe8}}, - {0x001fe9, {[CaseLower] = 0x001fe1,[CaseTitle] = 0x001fe9,[CaseUpper] = 0x001fe9}}, - {0x001fea, {[CaseLower] = 0x001f7a,[CaseTitle] = 0x001fea,[CaseUpper] = 0x001fea}}, - {0x001feb, {[CaseLower] = 0x001f7b,[CaseTitle] = 0x001feb,[CaseUpper] = 0x001feb}}, - {0x001fec, {[CaseLower] = 0x001fe5,[CaseTitle] = 0x001fec,[CaseUpper] = 0x001fec}}, - {0x001ff3, {[CaseLower] = 0x001ff3,[CaseTitle] = 0x001ffc,[CaseUpper] = 0x001ffc}}, - {0x001ff8, {[CaseLower] = 0x001f78,[CaseTitle] = 0x001ff8,[CaseUpper] = 0x001ff8}}, - {0x001ff9, {[CaseLower] = 0x001f79,[CaseTitle] = 0x001ff9,[CaseUpper] = 0x001ff9}}, - {0x001ffa, {[CaseLower] = 0x001f7c,[CaseTitle] = 0x001ffa,[CaseUpper] = 0x001ffa}}, - {0x001ffb, {[CaseLower] = 0x001f7d,[CaseTitle] = 0x001ffb,[CaseUpper] = 0x001ffb}}, - {0x001ffc, {[CaseLower] = 0x001ff3,[CaseTitle] = 0x001ffc,[CaseUpper] = 0x001ffc}}, - {0x002126, {[CaseLower] = 0x0003c9,[CaseTitle] = 0x002126,[CaseUpper] = 0x002126}}, - {0x00212a, {[CaseLower] = 0x00006b,[CaseTitle] = 0x00212a,[CaseUpper] = 0x00212a}}, - {0x00212b, {[CaseLower] = 0x0000e5,[CaseTitle] = 0x00212b,[CaseUpper] = 0x00212b}}, - {0x002132, {[CaseLower] = 0x00214e,[CaseTitle] = 0x002132,[CaseUpper] = 0x002132}}, - {0x00214e, {[CaseLower] = 0x00214e,[CaseTitle] = 0x002132,[CaseUpper] = 0x002132}}, - {0x002160, {[CaseLower] = 0x002170,[CaseTitle] = 0x002160,[CaseUpper] = 0x002160}}, - {0x002161, {[CaseLower] = 0x002171,[CaseTitle] = 0x002161,[CaseUpper] = 0x002161}}, - {0x002162, {[CaseLower] = 0x002172,[CaseTitle] = 0x002162,[CaseUpper] = 0x002162}}, - {0x002163, {[CaseLower] = 0x002173,[CaseTitle] = 0x002163,[CaseUpper] = 0x002163}}, - {0x002164, {[CaseLower] = 0x002174,[CaseTitle] = 0x002164,[CaseUpper] = 0x002164}}, - {0x002165, {[CaseLower] = 0x002175,[CaseTitle] = 0x002165,[CaseUpper] = 0x002165}}, - {0x002166, {[CaseLower] = 0x002176,[CaseTitle] = 0x002166,[CaseUpper] = 0x002166}}, - {0x002167, {[CaseLower] = 0x002177,[CaseTitle] = 0x002167,[CaseUpper] = 0x002167}}, - {0x002168, {[CaseLower] = 0x002178,[CaseTitle] = 0x002168,[CaseUpper] = 0x002168}}, - {0x002169, {[CaseLower] = 0x002179,[CaseTitle] = 0x002169,[CaseUpper] = 0x002169}}, - {0x00216a, {[CaseLower] = 0x00217a,[CaseTitle] = 0x00216a,[CaseUpper] = 0x00216a}}, - {0x00216b, {[CaseLower] = 0x00217b,[CaseTitle] = 0x00216b,[CaseUpper] = 0x00216b}}, - {0x00216c, {[CaseLower] = 0x00217c,[CaseTitle] = 0x00216c,[CaseUpper] = 0x00216c}}, - {0x00216d, {[CaseLower] = 0x00217d,[CaseTitle] = 0x00216d,[CaseUpper] = 0x00216d}}, - {0x00216e, {[CaseLower] = 0x00217e,[CaseTitle] = 0x00216e,[CaseUpper] = 0x00216e}}, - {0x00216f, {[CaseLower] = 0x00217f,[CaseTitle] = 0x00216f,[CaseUpper] = 0x00216f}}, - {0x002170, {[CaseLower] = 0x002170,[CaseTitle] = 0x002160,[CaseUpper] = 0x002160}}, - {0x002171, {[CaseLower] = 0x002171,[CaseTitle] = 0x002161,[CaseUpper] = 0x002161}}, - {0x002172, {[CaseLower] = 0x002172,[CaseTitle] = 0x002162,[CaseUpper] = 0x002162}}, - {0x002173, {[CaseLower] = 0x002173,[CaseTitle] = 0x002163,[CaseUpper] = 0x002163}}, - {0x002174, {[CaseLower] = 0x002174,[CaseTitle] = 0x002164,[CaseUpper] = 0x002164}}, - {0x002175, {[CaseLower] = 0x002175,[CaseTitle] = 0x002165,[CaseUpper] = 0x002165}}, - {0x002176, {[CaseLower] = 0x002176,[CaseTitle] = 0x002166,[CaseUpper] = 0x002166}}, - {0x002177, {[CaseLower] = 0x002177,[CaseTitle] = 0x002167,[CaseUpper] = 0x002167}}, - {0x002178, {[CaseLower] = 0x002178,[CaseTitle] = 0x002168,[CaseUpper] = 0x002168}}, - {0x002179, {[CaseLower] = 0x002179,[CaseTitle] = 0x002169,[CaseUpper] = 0x002169}}, - {0x00217a, {[CaseLower] = 0x00217a,[CaseTitle] = 0x00216a,[CaseUpper] = 0x00216a}}, - {0x00217b, {[CaseLower] = 0x00217b,[CaseTitle] = 0x00216b,[CaseUpper] = 0x00216b}}, - {0x00217c, {[CaseLower] = 0x00217c,[CaseTitle] = 0x00216c,[CaseUpper] = 0x00216c}}, - {0x00217d, {[CaseLower] = 0x00217d,[CaseTitle] = 0x00216d,[CaseUpper] = 0x00216d}}, - {0x00217e, {[CaseLower] = 0x00217e,[CaseTitle] = 0x00216e,[CaseUpper] = 0x00216e}}, - {0x00217f, {[CaseLower] = 0x00217f,[CaseTitle] = 0x00216f,[CaseUpper] = 0x00216f}}, - {0x002183, {[CaseLower] = 0x002184,[CaseTitle] = 0x002183,[CaseUpper] = 0x002183}}, - {0x002184, {[CaseLower] = 0x002184,[CaseTitle] = 0x002183,[CaseUpper] = 0x002183}}, - {0x0024b6, {[CaseLower] = 0x0024d0,[CaseTitle] = 0x0024b6,[CaseUpper] = 0x0024b6}}, - {0x0024b7, {[CaseLower] = 0x0024d1,[CaseTitle] = 0x0024b7,[CaseUpper] = 0x0024b7}}, - {0x0024b8, {[CaseLower] = 0x0024d2,[CaseTitle] = 0x0024b8,[CaseUpper] = 0x0024b8}}, - {0x0024b9, {[CaseLower] = 0x0024d3,[CaseTitle] = 0x0024b9,[CaseUpper] = 0x0024b9}}, - {0x0024ba, {[CaseLower] = 0x0024d4,[CaseTitle] = 0x0024ba,[CaseUpper] = 0x0024ba}}, - {0x0024bb, {[CaseLower] = 0x0024d5,[CaseTitle] = 0x0024bb,[CaseUpper] = 0x0024bb}}, - {0x0024bc, {[CaseLower] = 0x0024d6,[CaseTitle] = 0x0024bc,[CaseUpper] = 0x0024bc}}, - {0x0024bd, {[CaseLower] = 0x0024d7,[CaseTitle] = 0x0024bd,[CaseUpper] = 0x0024bd}}, - {0x0024be, {[CaseLower] = 0x0024d8,[CaseTitle] = 0x0024be,[CaseUpper] = 0x0024be}}, - {0x0024bf, {[CaseLower] = 0x0024d9,[CaseTitle] = 0x0024bf,[CaseUpper] = 0x0024bf}}, - {0x0024c0, {[CaseLower] = 0x0024da,[CaseTitle] = 0x0024c0,[CaseUpper] = 0x0024c0}}, - {0x0024c1, {[CaseLower] = 0x0024db,[CaseTitle] = 0x0024c1,[CaseUpper] = 0x0024c1}}, - {0x0024c2, {[CaseLower] = 0x0024dc,[CaseTitle] = 0x0024c2,[CaseUpper] = 0x0024c2}}, - {0x0024c3, {[CaseLower] = 0x0024dd,[CaseTitle] = 0x0024c3,[CaseUpper] = 0x0024c3}}, - {0x0024c4, {[CaseLower] = 0x0024de,[CaseTitle] = 0x0024c4,[CaseUpper] = 0x0024c4}}, - {0x0024c5, {[CaseLower] = 0x0024df,[CaseTitle] = 0x0024c5,[CaseUpper] = 0x0024c5}}, - {0x0024c6, {[CaseLower] = 0x0024e0,[CaseTitle] = 0x0024c6,[CaseUpper] = 0x0024c6}}, - {0x0024c7, {[CaseLower] = 0x0024e1,[CaseTitle] = 0x0024c7,[CaseUpper] = 0x0024c7}}, - {0x0024c8, {[CaseLower] = 0x0024e2,[CaseTitle] = 0x0024c8,[CaseUpper] = 0x0024c8}}, - {0x0024c9, {[CaseLower] = 0x0024e3,[CaseTitle] = 0x0024c9,[CaseUpper] = 0x0024c9}}, - {0x0024ca, {[CaseLower] = 0x0024e4,[CaseTitle] = 0x0024ca,[CaseUpper] = 0x0024ca}}, - {0x0024cb, {[CaseLower] = 0x0024e5,[CaseTitle] = 0x0024cb,[CaseUpper] = 0x0024cb}}, - {0x0024cc, {[CaseLower] = 0x0024e6,[CaseTitle] = 0x0024cc,[CaseUpper] = 0x0024cc}}, - {0x0024cd, {[CaseLower] = 0x0024e7,[CaseTitle] = 0x0024cd,[CaseUpper] = 0x0024cd}}, - {0x0024ce, {[CaseLower] = 0x0024e8,[CaseTitle] = 0x0024ce,[CaseUpper] = 0x0024ce}}, - {0x0024cf, {[CaseLower] = 0x0024e9,[CaseTitle] = 0x0024cf,[CaseUpper] = 0x0024cf}}, - {0x0024d0, {[CaseLower] = 0x0024d0,[CaseTitle] = 0x0024b6,[CaseUpper] = 0x0024b6}}, - {0x0024d1, {[CaseLower] = 0x0024d1,[CaseTitle] = 0x0024b7,[CaseUpper] = 0x0024b7}}, - {0x0024d2, {[CaseLower] = 0x0024d2,[CaseTitle] = 0x0024b8,[CaseUpper] = 0x0024b8}}, - {0x0024d3, {[CaseLower] = 0x0024d3,[CaseTitle] = 0x0024b9,[CaseUpper] = 0x0024b9}}, - {0x0024d4, {[CaseLower] = 0x0024d4,[CaseTitle] = 0x0024ba,[CaseUpper] = 0x0024ba}}, - {0x0024d5, {[CaseLower] = 0x0024d5,[CaseTitle] = 0x0024bb,[CaseUpper] = 0x0024bb}}, - {0x0024d6, {[CaseLower] = 0x0024d6,[CaseTitle] = 0x0024bc,[CaseUpper] = 0x0024bc}}, - {0x0024d7, {[CaseLower] = 0x0024d7,[CaseTitle] = 0x0024bd,[CaseUpper] = 0x0024bd}}, - {0x0024d8, {[CaseLower] = 0x0024d8,[CaseTitle] = 0x0024be,[CaseUpper] = 0x0024be}}, - {0x0024d9, {[CaseLower] = 0x0024d9,[CaseTitle] = 0x0024bf,[CaseUpper] = 0x0024bf}}, - {0x0024da, {[CaseLower] = 0x0024da,[CaseTitle] = 0x0024c0,[CaseUpper] = 0x0024c0}}, - {0x0024db, {[CaseLower] = 0x0024db,[CaseTitle] = 0x0024c1,[CaseUpper] = 0x0024c1}}, - {0x0024dc, {[CaseLower] = 0x0024dc,[CaseTitle] = 0x0024c2,[CaseUpper] = 0x0024c2}}, - {0x0024dd, {[CaseLower] = 0x0024dd,[CaseTitle] = 0x0024c3,[CaseUpper] = 0x0024c3}}, - {0x0024de, {[CaseLower] = 0x0024de,[CaseTitle] = 0x0024c4,[CaseUpper] = 0x0024c4}}, - {0x0024df, {[CaseLower] = 0x0024df,[CaseTitle] = 0x0024c5,[CaseUpper] = 0x0024c5}}, - {0x0024e0, {[CaseLower] = 0x0024e0,[CaseTitle] = 0x0024c6,[CaseUpper] = 0x0024c6}}, - {0x0024e1, {[CaseLower] = 0x0024e1,[CaseTitle] = 0x0024c7,[CaseUpper] = 0x0024c7}}, - {0x0024e2, {[CaseLower] = 0x0024e2,[CaseTitle] = 0x0024c8,[CaseUpper] = 0x0024c8}}, - {0x0024e3, {[CaseLower] = 0x0024e3,[CaseTitle] = 0x0024c9,[CaseUpper] = 0x0024c9}}, - {0x0024e4, {[CaseLower] = 0x0024e4,[CaseTitle] = 0x0024ca,[CaseUpper] = 0x0024ca}}, - {0x0024e5, {[CaseLower] = 0x0024e5,[CaseTitle] = 0x0024cb,[CaseUpper] = 0x0024cb}}, - {0x0024e6, {[CaseLower] = 0x0024e6,[CaseTitle] = 0x0024cc,[CaseUpper] = 0x0024cc}}, - {0x0024e7, {[CaseLower] = 0x0024e7,[CaseTitle] = 0x0024cd,[CaseUpper] = 0x0024cd}}, - {0x0024e8, {[CaseLower] = 0x0024e8,[CaseTitle] = 0x0024ce,[CaseUpper] = 0x0024ce}}, - {0x0024e9, {[CaseLower] = 0x0024e9,[CaseTitle] = 0x0024cf,[CaseUpper] = 0x0024cf}}, - {0x002c00, {[CaseLower] = 0x002c30,[CaseTitle] = 0x002c00,[CaseUpper] = 0x002c00}}, - {0x002c01, {[CaseLower] = 0x002c31,[CaseTitle] = 0x002c01,[CaseUpper] = 0x002c01}}, - {0x002c02, {[CaseLower] = 0x002c32,[CaseTitle] = 0x002c02,[CaseUpper] = 0x002c02}}, - {0x002c03, {[CaseLower] = 0x002c33,[CaseTitle] = 0x002c03,[CaseUpper] = 0x002c03}}, - {0x002c04, {[CaseLower] = 0x002c34,[CaseTitle] = 0x002c04,[CaseUpper] = 0x002c04}}, - {0x002c05, {[CaseLower] = 0x002c35,[CaseTitle] = 0x002c05,[CaseUpper] = 0x002c05}}, - {0x002c06, {[CaseLower] = 0x002c36,[CaseTitle] = 0x002c06,[CaseUpper] = 0x002c06}}, - {0x002c07, {[CaseLower] = 0x002c37,[CaseTitle] = 0x002c07,[CaseUpper] = 0x002c07}}, - {0x002c08, {[CaseLower] = 0x002c38,[CaseTitle] = 0x002c08,[CaseUpper] = 0x002c08}}, - {0x002c09, {[CaseLower] = 0x002c39,[CaseTitle] = 0x002c09,[CaseUpper] = 0x002c09}}, - {0x002c0a, {[CaseLower] = 0x002c3a,[CaseTitle] = 0x002c0a,[CaseUpper] = 0x002c0a}}, - {0x002c0b, {[CaseLower] = 0x002c3b,[CaseTitle] = 0x002c0b,[CaseUpper] = 0x002c0b}}, - {0x002c0c, {[CaseLower] = 0x002c3c,[CaseTitle] = 0x002c0c,[CaseUpper] = 0x002c0c}}, - {0x002c0d, {[CaseLower] = 0x002c3d,[CaseTitle] = 0x002c0d,[CaseUpper] = 0x002c0d}}, - {0x002c0e, {[CaseLower] = 0x002c3e,[CaseTitle] = 0x002c0e,[CaseUpper] = 0x002c0e}}, - {0x002c0f, {[CaseLower] = 0x002c3f,[CaseTitle] = 0x002c0f,[CaseUpper] = 0x002c0f}}, - {0x002c10, {[CaseLower] = 0x002c40,[CaseTitle] = 0x002c10,[CaseUpper] = 0x002c10}}, - {0x002c11, {[CaseLower] = 0x002c41,[CaseTitle] = 0x002c11,[CaseUpper] = 0x002c11}}, - {0x002c12, {[CaseLower] = 0x002c42,[CaseTitle] = 0x002c12,[CaseUpper] = 0x002c12}}, - {0x002c13, {[CaseLower] = 0x002c43,[CaseTitle] = 0x002c13,[CaseUpper] = 0x002c13}}, - {0x002c14, {[CaseLower] = 0x002c44,[CaseTitle] = 0x002c14,[CaseUpper] = 0x002c14}}, - {0x002c15, {[CaseLower] = 0x002c45,[CaseTitle] = 0x002c15,[CaseUpper] = 0x002c15}}, - {0x002c16, {[CaseLower] = 0x002c46,[CaseTitle] = 0x002c16,[CaseUpper] = 0x002c16}}, - {0x002c17, {[CaseLower] = 0x002c47,[CaseTitle] = 0x002c17,[CaseUpper] = 0x002c17}}, - {0x002c18, {[CaseLower] = 0x002c48,[CaseTitle] = 0x002c18,[CaseUpper] = 0x002c18}}, - {0x002c19, {[CaseLower] = 0x002c49,[CaseTitle] = 0x002c19,[CaseUpper] = 0x002c19}}, - {0x002c1a, {[CaseLower] = 0x002c4a,[CaseTitle] = 0x002c1a,[CaseUpper] = 0x002c1a}}, - {0x002c1b, {[CaseLower] = 0x002c4b,[CaseTitle] = 0x002c1b,[CaseUpper] = 0x002c1b}}, - {0x002c1c, {[CaseLower] = 0x002c4c,[CaseTitle] = 0x002c1c,[CaseUpper] = 0x002c1c}}, - {0x002c1d, {[CaseLower] = 0x002c4d,[CaseTitle] = 0x002c1d,[CaseUpper] = 0x002c1d}}, - {0x002c1e, {[CaseLower] = 0x002c4e,[CaseTitle] = 0x002c1e,[CaseUpper] = 0x002c1e}}, - {0x002c1f, {[CaseLower] = 0x002c4f,[CaseTitle] = 0x002c1f,[CaseUpper] = 0x002c1f}}, - {0x002c20, {[CaseLower] = 0x002c50,[CaseTitle] = 0x002c20,[CaseUpper] = 0x002c20}}, - {0x002c21, {[CaseLower] = 0x002c51,[CaseTitle] = 0x002c21,[CaseUpper] = 0x002c21}}, - {0x002c22, {[CaseLower] = 0x002c52,[CaseTitle] = 0x002c22,[CaseUpper] = 0x002c22}}, - {0x002c23, {[CaseLower] = 0x002c53,[CaseTitle] = 0x002c23,[CaseUpper] = 0x002c23}}, - {0x002c24, {[CaseLower] = 0x002c54,[CaseTitle] = 0x002c24,[CaseUpper] = 0x002c24}}, - {0x002c25, {[CaseLower] = 0x002c55,[CaseTitle] = 0x002c25,[CaseUpper] = 0x002c25}}, - {0x002c26, {[CaseLower] = 0x002c56,[CaseTitle] = 0x002c26,[CaseUpper] = 0x002c26}}, - {0x002c27, {[CaseLower] = 0x002c57,[CaseTitle] = 0x002c27,[CaseUpper] = 0x002c27}}, - {0x002c28, {[CaseLower] = 0x002c58,[CaseTitle] = 0x002c28,[CaseUpper] = 0x002c28}}, - {0x002c29, {[CaseLower] = 0x002c59,[CaseTitle] = 0x002c29,[CaseUpper] = 0x002c29}}, - {0x002c2a, {[CaseLower] = 0x002c5a,[CaseTitle] = 0x002c2a,[CaseUpper] = 0x002c2a}}, - {0x002c2b, {[CaseLower] = 0x002c5b,[CaseTitle] = 0x002c2b,[CaseUpper] = 0x002c2b}}, - {0x002c2c, {[CaseLower] = 0x002c5c,[CaseTitle] = 0x002c2c,[CaseUpper] = 0x002c2c}}, - {0x002c2d, {[CaseLower] = 0x002c5d,[CaseTitle] = 0x002c2d,[CaseUpper] = 0x002c2d}}, - {0x002c2e, {[CaseLower] = 0x002c5e,[CaseTitle] = 0x002c2e,[CaseUpper] = 0x002c2e}}, - {0x002c2f, {[CaseLower] = 0x002c5f,[CaseTitle] = 0x002c2f,[CaseUpper] = 0x002c2f}}, - {0x002c30, {[CaseLower] = 0x002c30,[CaseTitle] = 0x002c00,[CaseUpper] = 0x002c00}}, - {0x002c31, {[CaseLower] = 0x002c31,[CaseTitle] = 0x002c01,[CaseUpper] = 0x002c01}}, - {0x002c32, {[CaseLower] = 0x002c32,[CaseTitle] = 0x002c02,[CaseUpper] = 0x002c02}}, - {0x002c33, {[CaseLower] = 0x002c33,[CaseTitle] = 0x002c03,[CaseUpper] = 0x002c03}}, - {0x002c34, {[CaseLower] = 0x002c34,[CaseTitle] = 0x002c04,[CaseUpper] = 0x002c04}}, - {0x002c35, {[CaseLower] = 0x002c35,[CaseTitle] = 0x002c05,[CaseUpper] = 0x002c05}}, - {0x002c36, {[CaseLower] = 0x002c36,[CaseTitle] = 0x002c06,[CaseUpper] = 0x002c06}}, - {0x002c37, {[CaseLower] = 0x002c37,[CaseTitle] = 0x002c07,[CaseUpper] = 0x002c07}}, - {0x002c38, {[CaseLower] = 0x002c38,[CaseTitle] = 0x002c08,[CaseUpper] = 0x002c08}}, - {0x002c39, {[CaseLower] = 0x002c39,[CaseTitle] = 0x002c09,[CaseUpper] = 0x002c09}}, - {0x002c3a, {[CaseLower] = 0x002c3a,[CaseTitle] = 0x002c0a,[CaseUpper] = 0x002c0a}}, - {0x002c3b, {[CaseLower] = 0x002c3b,[CaseTitle] = 0x002c0b,[CaseUpper] = 0x002c0b}}, - {0x002c3c, {[CaseLower] = 0x002c3c,[CaseTitle] = 0x002c0c,[CaseUpper] = 0x002c0c}}, - {0x002c3d, {[CaseLower] = 0x002c3d,[CaseTitle] = 0x002c0d,[CaseUpper] = 0x002c0d}}, - {0x002c3e, {[CaseLower] = 0x002c3e,[CaseTitle] = 0x002c0e,[CaseUpper] = 0x002c0e}}, - {0x002c3f, {[CaseLower] = 0x002c3f,[CaseTitle] = 0x002c0f,[CaseUpper] = 0x002c0f}}, - {0x002c40, {[CaseLower] = 0x002c40,[CaseTitle] = 0x002c10,[CaseUpper] = 0x002c10}}, - {0x002c41, {[CaseLower] = 0x002c41,[CaseTitle] = 0x002c11,[CaseUpper] = 0x002c11}}, - {0x002c42, {[CaseLower] = 0x002c42,[CaseTitle] = 0x002c12,[CaseUpper] = 0x002c12}}, - {0x002c43, {[CaseLower] = 0x002c43,[CaseTitle] = 0x002c13,[CaseUpper] = 0x002c13}}, - {0x002c44, {[CaseLower] = 0x002c44,[CaseTitle] = 0x002c14,[CaseUpper] = 0x002c14}}, - {0x002c45, {[CaseLower] = 0x002c45,[CaseTitle] = 0x002c15,[CaseUpper] = 0x002c15}}, - {0x002c46, {[CaseLower] = 0x002c46,[CaseTitle] = 0x002c16,[CaseUpper] = 0x002c16}}, - {0x002c47, {[CaseLower] = 0x002c47,[CaseTitle] = 0x002c17,[CaseUpper] = 0x002c17}}, - {0x002c48, {[CaseLower] = 0x002c48,[CaseTitle] = 0x002c18,[CaseUpper] = 0x002c18}}, - {0x002c49, {[CaseLower] = 0x002c49,[CaseTitle] = 0x002c19,[CaseUpper] = 0x002c19}}, - {0x002c4a, {[CaseLower] = 0x002c4a,[CaseTitle] = 0x002c1a,[CaseUpper] = 0x002c1a}}, - {0x002c4b, {[CaseLower] = 0x002c4b,[CaseTitle] = 0x002c1b,[CaseUpper] = 0x002c1b}}, - {0x002c4c, {[CaseLower] = 0x002c4c,[CaseTitle] = 0x002c1c,[CaseUpper] = 0x002c1c}}, - {0x002c4d, {[CaseLower] = 0x002c4d,[CaseTitle] = 0x002c1d,[CaseUpper] = 0x002c1d}}, - {0x002c4e, {[CaseLower] = 0x002c4e,[CaseTitle] = 0x002c1e,[CaseUpper] = 0x002c1e}}, - {0x002c4f, {[CaseLower] = 0x002c4f,[CaseTitle] = 0x002c1f,[CaseUpper] = 0x002c1f}}, - {0x002c50, {[CaseLower] = 0x002c50,[CaseTitle] = 0x002c20,[CaseUpper] = 0x002c20}}, - {0x002c51, {[CaseLower] = 0x002c51,[CaseTitle] = 0x002c21,[CaseUpper] = 0x002c21}}, - {0x002c52, {[CaseLower] = 0x002c52,[CaseTitle] = 0x002c22,[CaseUpper] = 0x002c22}}, - {0x002c53, {[CaseLower] = 0x002c53,[CaseTitle] = 0x002c23,[CaseUpper] = 0x002c23}}, - {0x002c54, {[CaseLower] = 0x002c54,[CaseTitle] = 0x002c24,[CaseUpper] = 0x002c24}}, - {0x002c55, {[CaseLower] = 0x002c55,[CaseTitle] = 0x002c25,[CaseUpper] = 0x002c25}}, - {0x002c56, {[CaseLower] = 0x002c56,[CaseTitle] = 0x002c26,[CaseUpper] = 0x002c26}}, - {0x002c57, {[CaseLower] = 0x002c57,[CaseTitle] = 0x002c27,[CaseUpper] = 0x002c27}}, - {0x002c58, {[CaseLower] = 0x002c58,[CaseTitle] = 0x002c28,[CaseUpper] = 0x002c28}}, - {0x002c59, {[CaseLower] = 0x002c59,[CaseTitle] = 0x002c29,[CaseUpper] = 0x002c29}}, - {0x002c5a, {[CaseLower] = 0x002c5a,[CaseTitle] = 0x002c2a,[CaseUpper] = 0x002c2a}}, - {0x002c5b, {[CaseLower] = 0x002c5b,[CaseTitle] = 0x002c2b,[CaseUpper] = 0x002c2b}}, - {0x002c5c, {[CaseLower] = 0x002c5c,[CaseTitle] = 0x002c2c,[CaseUpper] = 0x002c2c}}, - {0x002c5d, {[CaseLower] = 0x002c5d,[CaseTitle] = 0x002c2d,[CaseUpper] = 0x002c2d}}, - {0x002c5e, {[CaseLower] = 0x002c5e,[CaseTitle] = 0x002c2e,[CaseUpper] = 0x002c2e}}, - {0x002c5f, {[CaseLower] = 0x002c5f,[CaseTitle] = 0x002c2f,[CaseUpper] = 0x002c2f}}, - {0x002c60, {[CaseLower] = 0x002c61,[CaseTitle] = 0x002c60,[CaseUpper] = 0x002c60}}, - {0x002c61, {[CaseLower] = 0x002c61,[CaseTitle] = 0x002c60,[CaseUpper] = 0x002c60}}, - {0x002c62, {[CaseLower] = 0x00026b,[CaseTitle] = 0x002c62,[CaseUpper] = 0x002c62}}, - {0x002c63, {[CaseLower] = 0x001d7d,[CaseTitle] = 0x002c63,[CaseUpper] = 0x002c63}}, - {0x002c64, {[CaseLower] = 0x00027d,[CaseTitle] = 0x002c64,[CaseUpper] = 0x002c64}}, - {0x002c65, {[CaseLower] = 0x002c65,[CaseTitle] = 0x00023a,[CaseUpper] = 0x00023a}}, - {0x002c66, {[CaseLower] = 0x002c66,[CaseTitle] = 0x00023e,[CaseUpper] = 0x00023e}}, - {0x002c67, {[CaseLower] = 0x002c68,[CaseTitle] = 0x002c67,[CaseUpper] = 0x002c67}}, - {0x002c68, {[CaseLower] = 0x002c68,[CaseTitle] = 0x002c67,[CaseUpper] = 0x002c67}}, - {0x002c69, {[CaseLower] = 0x002c6a,[CaseTitle] = 0x002c69,[CaseUpper] = 0x002c69}}, - {0x002c6a, {[CaseLower] = 0x002c6a,[CaseTitle] = 0x002c69,[CaseUpper] = 0x002c69}}, - {0x002c6b, {[CaseLower] = 0x002c6c,[CaseTitle] = 0x002c6b,[CaseUpper] = 0x002c6b}}, - {0x002c6c, {[CaseLower] = 0x002c6c,[CaseTitle] = 0x002c6b,[CaseUpper] = 0x002c6b}}, - {0x002c6d, {[CaseLower] = 0x000251,[CaseTitle] = 0x002c6d,[CaseUpper] = 0x002c6d}}, - {0x002c6e, {[CaseLower] = 0x000271,[CaseTitle] = 0x002c6e,[CaseUpper] = 0x002c6e}}, - {0x002c6f, {[CaseLower] = 0x000250,[CaseTitle] = 0x002c6f,[CaseUpper] = 0x002c6f}}, - {0x002c70, {[CaseLower] = 0x000252,[CaseTitle] = 0x002c70,[CaseUpper] = 0x002c70}}, - {0x002c72, {[CaseLower] = 0x002c73,[CaseTitle] = 0x002c72,[CaseUpper] = 0x002c72}}, - {0x002c73, {[CaseLower] = 0x002c73,[CaseTitle] = 0x002c72,[CaseUpper] = 0x002c72}}, - {0x002c75, {[CaseLower] = 0x002c76,[CaseTitle] = 0x002c75,[CaseUpper] = 0x002c75}}, - {0x002c76, {[CaseLower] = 0x002c76,[CaseTitle] = 0x002c75,[CaseUpper] = 0x002c75}}, - {0x002c7e, {[CaseLower] = 0x00023f,[CaseTitle] = 0x002c7e,[CaseUpper] = 0x002c7e}}, - {0x002c7f, {[CaseLower] = 0x000240,[CaseTitle] = 0x002c7f,[CaseUpper] = 0x002c7f}}, - {0x002c80, {[CaseLower] = 0x002c81,[CaseTitle] = 0x002c80,[CaseUpper] = 0x002c80}}, - {0x002c81, {[CaseLower] = 0x002c81,[CaseTitle] = 0x002c80,[CaseUpper] = 0x002c80}}, - {0x002c82, {[CaseLower] = 0x002c83,[CaseTitle] = 0x002c82,[CaseUpper] = 0x002c82}}, - {0x002c83, {[CaseLower] = 0x002c83,[CaseTitle] = 0x002c82,[CaseUpper] = 0x002c82}}, - {0x002c84, {[CaseLower] = 0x002c85,[CaseTitle] = 0x002c84,[CaseUpper] = 0x002c84}}, - {0x002c85, {[CaseLower] = 0x002c85,[CaseTitle] = 0x002c84,[CaseUpper] = 0x002c84}}, - {0x002c86, {[CaseLower] = 0x002c87,[CaseTitle] = 0x002c86,[CaseUpper] = 0x002c86}}, - {0x002c87, {[CaseLower] = 0x002c87,[CaseTitle] = 0x002c86,[CaseUpper] = 0x002c86}}, - {0x002c88, {[CaseLower] = 0x002c89,[CaseTitle] = 0x002c88,[CaseUpper] = 0x002c88}}, - {0x002c89, {[CaseLower] = 0x002c89,[CaseTitle] = 0x002c88,[CaseUpper] = 0x002c88}}, - {0x002c8a, {[CaseLower] = 0x002c8b,[CaseTitle] = 0x002c8a,[CaseUpper] = 0x002c8a}}, - {0x002c8b, {[CaseLower] = 0x002c8b,[CaseTitle] = 0x002c8a,[CaseUpper] = 0x002c8a}}, - {0x002c8c, {[CaseLower] = 0x002c8d,[CaseTitle] = 0x002c8c,[CaseUpper] = 0x002c8c}}, - {0x002c8d, {[CaseLower] = 0x002c8d,[CaseTitle] = 0x002c8c,[CaseUpper] = 0x002c8c}}, - {0x002c8e, {[CaseLower] = 0x002c8f,[CaseTitle] = 0x002c8e,[CaseUpper] = 0x002c8e}}, - {0x002c8f, {[CaseLower] = 0x002c8f,[CaseTitle] = 0x002c8e,[CaseUpper] = 0x002c8e}}, - {0x002c90, {[CaseLower] = 0x002c91,[CaseTitle] = 0x002c90,[CaseUpper] = 0x002c90}}, - {0x002c91, {[CaseLower] = 0x002c91,[CaseTitle] = 0x002c90,[CaseUpper] = 0x002c90}}, - {0x002c92, {[CaseLower] = 0x002c93,[CaseTitle] = 0x002c92,[CaseUpper] = 0x002c92}}, - {0x002c93, {[CaseLower] = 0x002c93,[CaseTitle] = 0x002c92,[CaseUpper] = 0x002c92}}, - {0x002c94, {[CaseLower] = 0x002c95,[CaseTitle] = 0x002c94,[CaseUpper] = 0x002c94}}, - {0x002c95, {[CaseLower] = 0x002c95,[CaseTitle] = 0x002c94,[CaseUpper] = 0x002c94}}, - {0x002c96, {[CaseLower] = 0x002c97,[CaseTitle] = 0x002c96,[CaseUpper] = 0x002c96}}, - {0x002c97, {[CaseLower] = 0x002c97,[CaseTitle] = 0x002c96,[CaseUpper] = 0x002c96}}, - {0x002c98, {[CaseLower] = 0x002c99,[CaseTitle] = 0x002c98,[CaseUpper] = 0x002c98}}, - {0x002c99, {[CaseLower] = 0x002c99,[CaseTitle] = 0x002c98,[CaseUpper] = 0x002c98}}, - {0x002c9a, {[CaseLower] = 0x002c9b,[CaseTitle] = 0x002c9a,[CaseUpper] = 0x002c9a}}, - {0x002c9b, {[CaseLower] = 0x002c9b,[CaseTitle] = 0x002c9a,[CaseUpper] = 0x002c9a}}, - {0x002c9c, {[CaseLower] = 0x002c9d,[CaseTitle] = 0x002c9c,[CaseUpper] = 0x002c9c}}, - {0x002c9d, {[CaseLower] = 0x002c9d,[CaseTitle] = 0x002c9c,[CaseUpper] = 0x002c9c}}, - {0x002c9e, {[CaseLower] = 0x002c9f,[CaseTitle] = 0x002c9e,[CaseUpper] = 0x002c9e}}, - {0x002c9f, {[CaseLower] = 0x002c9f,[CaseTitle] = 0x002c9e,[CaseUpper] = 0x002c9e}}, - {0x002ca0, {[CaseLower] = 0x002ca1,[CaseTitle] = 0x002ca0,[CaseUpper] = 0x002ca0}}, - {0x002ca1, {[CaseLower] = 0x002ca1,[CaseTitle] = 0x002ca0,[CaseUpper] = 0x002ca0}}, - {0x002ca2, {[CaseLower] = 0x002ca3,[CaseTitle] = 0x002ca2,[CaseUpper] = 0x002ca2}}, - {0x002ca3, {[CaseLower] = 0x002ca3,[CaseTitle] = 0x002ca2,[CaseUpper] = 0x002ca2}}, - {0x002ca4, {[CaseLower] = 0x002ca5,[CaseTitle] = 0x002ca4,[CaseUpper] = 0x002ca4}}, - {0x002ca5, {[CaseLower] = 0x002ca5,[CaseTitle] = 0x002ca4,[CaseUpper] = 0x002ca4}}, - {0x002ca6, {[CaseLower] = 0x002ca7,[CaseTitle] = 0x002ca6,[CaseUpper] = 0x002ca6}}, - {0x002ca7, {[CaseLower] = 0x002ca7,[CaseTitle] = 0x002ca6,[CaseUpper] = 0x002ca6}}, - {0x002ca8, {[CaseLower] = 0x002ca9,[CaseTitle] = 0x002ca8,[CaseUpper] = 0x002ca8}}, - {0x002ca9, {[CaseLower] = 0x002ca9,[CaseTitle] = 0x002ca8,[CaseUpper] = 0x002ca8}}, - {0x002caa, {[CaseLower] = 0x002cab,[CaseTitle] = 0x002caa,[CaseUpper] = 0x002caa}}, - {0x002cab, {[CaseLower] = 0x002cab,[CaseTitle] = 0x002caa,[CaseUpper] = 0x002caa}}, - {0x002cac, {[CaseLower] = 0x002cad,[CaseTitle] = 0x002cac,[CaseUpper] = 0x002cac}}, - {0x002cad, {[CaseLower] = 0x002cad,[CaseTitle] = 0x002cac,[CaseUpper] = 0x002cac}}, - {0x002cae, {[CaseLower] = 0x002caf,[CaseTitle] = 0x002cae,[CaseUpper] = 0x002cae}}, - {0x002caf, {[CaseLower] = 0x002caf,[CaseTitle] = 0x002cae,[CaseUpper] = 0x002cae}}, - {0x002cb0, {[CaseLower] = 0x002cb1,[CaseTitle] = 0x002cb0,[CaseUpper] = 0x002cb0}}, - {0x002cb1, {[CaseLower] = 0x002cb1,[CaseTitle] = 0x002cb0,[CaseUpper] = 0x002cb0}}, - {0x002cb2, {[CaseLower] = 0x002cb3,[CaseTitle] = 0x002cb2,[CaseUpper] = 0x002cb2}}, - {0x002cb3, {[CaseLower] = 0x002cb3,[CaseTitle] = 0x002cb2,[CaseUpper] = 0x002cb2}}, - {0x002cb4, {[CaseLower] = 0x002cb5,[CaseTitle] = 0x002cb4,[CaseUpper] = 0x002cb4}}, - {0x002cb5, {[CaseLower] = 0x002cb5,[CaseTitle] = 0x002cb4,[CaseUpper] = 0x002cb4}}, - {0x002cb6, {[CaseLower] = 0x002cb7,[CaseTitle] = 0x002cb6,[CaseUpper] = 0x002cb6}}, - {0x002cb7, {[CaseLower] = 0x002cb7,[CaseTitle] = 0x002cb6,[CaseUpper] = 0x002cb6}}, - {0x002cb8, {[CaseLower] = 0x002cb9,[CaseTitle] = 0x002cb8,[CaseUpper] = 0x002cb8}}, - {0x002cb9, {[CaseLower] = 0x002cb9,[CaseTitle] = 0x002cb8,[CaseUpper] = 0x002cb8}}, - {0x002cba, {[CaseLower] = 0x002cbb,[CaseTitle] = 0x002cba,[CaseUpper] = 0x002cba}}, - {0x002cbb, {[CaseLower] = 0x002cbb,[CaseTitle] = 0x002cba,[CaseUpper] = 0x002cba}}, - {0x002cbc, {[CaseLower] = 0x002cbd,[CaseTitle] = 0x002cbc,[CaseUpper] = 0x002cbc}}, - {0x002cbd, {[CaseLower] = 0x002cbd,[CaseTitle] = 0x002cbc,[CaseUpper] = 0x002cbc}}, - {0x002cbe, {[CaseLower] = 0x002cbf,[CaseTitle] = 0x002cbe,[CaseUpper] = 0x002cbe}}, - {0x002cbf, {[CaseLower] = 0x002cbf,[CaseTitle] = 0x002cbe,[CaseUpper] = 0x002cbe}}, - {0x002cc0, {[CaseLower] = 0x002cc1,[CaseTitle] = 0x002cc0,[CaseUpper] = 0x002cc0}}, - {0x002cc1, {[CaseLower] = 0x002cc1,[CaseTitle] = 0x002cc0,[CaseUpper] = 0x002cc0}}, - {0x002cc2, {[CaseLower] = 0x002cc3,[CaseTitle] = 0x002cc2,[CaseUpper] = 0x002cc2}}, - {0x002cc3, {[CaseLower] = 0x002cc3,[CaseTitle] = 0x002cc2,[CaseUpper] = 0x002cc2}}, - {0x002cc4, {[CaseLower] = 0x002cc5,[CaseTitle] = 0x002cc4,[CaseUpper] = 0x002cc4}}, - {0x002cc5, {[CaseLower] = 0x002cc5,[CaseTitle] = 0x002cc4,[CaseUpper] = 0x002cc4}}, - {0x002cc6, {[CaseLower] = 0x002cc7,[CaseTitle] = 0x002cc6,[CaseUpper] = 0x002cc6}}, - {0x002cc7, {[CaseLower] = 0x002cc7,[CaseTitle] = 0x002cc6,[CaseUpper] = 0x002cc6}}, - {0x002cc8, {[CaseLower] = 0x002cc9,[CaseTitle] = 0x002cc8,[CaseUpper] = 0x002cc8}}, - {0x002cc9, {[CaseLower] = 0x002cc9,[CaseTitle] = 0x002cc8,[CaseUpper] = 0x002cc8}}, - {0x002cca, {[CaseLower] = 0x002ccb,[CaseTitle] = 0x002cca,[CaseUpper] = 0x002cca}}, - {0x002ccb, {[CaseLower] = 0x002ccb,[CaseTitle] = 0x002cca,[CaseUpper] = 0x002cca}}, - {0x002ccc, {[CaseLower] = 0x002ccd,[CaseTitle] = 0x002ccc,[CaseUpper] = 0x002ccc}}, - {0x002ccd, {[CaseLower] = 0x002ccd,[CaseTitle] = 0x002ccc,[CaseUpper] = 0x002ccc}}, - {0x002cce, {[CaseLower] = 0x002ccf,[CaseTitle] = 0x002cce,[CaseUpper] = 0x002cce}}, - {0x002ccf, {[CaseLower] = 0x002ccf,[CaseTitle] = 0x002cce,[CaseUpper] = 0x002cce}}, - {0x002cd0, {[CaseLower] = 0x002cd1,[CaseTitle] = 0x002cd0,[CaseUpper] = 0x002cd0}}, - {0x002cd1, {[CaseLower] = 0x002cd1,[CaseTitle] = 0x002cd0,[CaseUpper] = 0x002cd0}}, - {0x002cd2, {[CaseLower] = 0x002cd3,[CaseTitle] = 0x002cd2,[CaseUpper] = 0x002cd2}}, - {0x002cd3, {[CaseLower] = 0x002cd3,[CaseTitle] = 0x002cd2,[CaseUpper] = 0x002cd2}}, - {0x002cd4, {[CaseLower] = 0x002cd5,[CaseTitle] = 0x002cd4,[CaseUpper] = 0x002cd4}}, - {0x002cd5, {[CaseLower] = 0x002cd5,[CaseTitle] = 0x002cd4,[CaseUpper] = 0x002cd4}}, - {0x002cd6, {[CaseLower] = 0x002cd7,[CaseTitle] = 0x002cd6,[CaseUpper] = 0x002cd6}}, - {0x002cd7, {[CaseLower] = 0x002cd7,[CaseTitle] = 0x002cd6,[CaseUpper] = 0x002cd6}}, - {0x002cd8, {[CaseLower] = 0x002cd9,[CaseTitle] = 0x002cd8,[CaseUpper] = 0x002cd8}}, - {0x002cd9, {[CaseLower] = 0x002cd9,[CaseTitle] = 0x002cd8,[CaseUpper] = 0x002cd8}}, - {0x002cda, {[CaseLower] = 0x002cdb,[CaseTitle] = 0x002cda,[CaseUpper] = 0x002cda}}, - {0x002cdb, {[CaseLower] = 0x002cdb,[CaseTitle] = 0x002cda,[CaseUpper] = 0x002cda}}, - {0x002cdc, {[CaseLower] = 0x002cdd,[CaseTitle] = 0x002cdc,[CaseUpper] = 0x002cdc}}, - {0x002cdd, {[CaseLower] = 0x002cdd,[CaseTitle] = 0x002cdc,[CaseUpper] = 0x002cdc}}, - {0x002cde, {[CaseLower] = 0x002cdf,[CaseTitle] = 0x002cde,[CaseUpper] = 0x002cde}}, - {0x002cdf, {[CaseLower] = 0x002cdf,[CaseTitle] = 0x002cde,[CaseUpper] = 0x002cde}}, - {0x002ce0, {[CaseLower] = 0x002ce1,[CaseTitle] = 0x002ce0,[CaseUpper] = 0x002ce0}}, - {0x002ce1, {[CaseLower] = 0x002ce1,[CaseTitle] = 0x002ce0,[CaseUpper] = 0x002ce0}}, - {0x002ce2, {[CaseLower] = 0x002ce3,[CaseTitle] = 0x002ce2,[CaseUpper] = 0x002ce2}}, - {0x002ce3, {[CaseLower] = 0x002ce3,[CaseTitle] = 0x002ce2,[CaseUpper] = 0x002ce2}}, - {0x002ceb, {[CaseLower] = 0x002cec,[CaseTitle] = 0x002ceb,[CaseUpper] = 0x002ceb}}, - {0x002cec, {[CaseLower] = 0x002cec,[CaseTitle] = 0x002ceb,[CaseUpper] = 0x002ceb}}, - {0x002ced, {[CaseLower] = 0x002cee,[CaseTitle] = 0x002ced,[CaseUpper] = 0x002ced}}, - {0x002cee, {[CaseLower] = 0x002cee,[CaseTitle] = 0x002ced,[CaseUpper] = 0x002ced}}, - {0x002cf2, {[CaseLower] = 0x002cf3,[CaseTitle] = 0x002cf2,[CaseUpper] = 0x002cf2}}, - {0x002cf3, {[CaseLower] = 0x002cf3,[CaseTitle] = 0x002cf2,[CaseUpper] = 0x002cf2}}, - {0x002d00, {[CaseLower] = 0x002d00,[CaseTitle] = 0x0010a0,[CaseUpper] = 0x0010a0}}, - {0x002d01, {[CaseLower] = 0x002d01,[CaseTitle] = 0x0010a1,[CaseUpper] = 0x0010a1}}, - {0x002d02, {[CaseLower] = 0x002d02,[CaseTitle] = 0x0010a2,[CaseUpper] = 0x0010a2}}, - {0x002d03, {[CaseLower] = 0x002d03,[CaseTitle] = 0x0010a3,[CaseUpper] = 0x0010a3}}, - {0x002d04, {[CaseLower] = 0x002d04,[CaseTitle] = 0x0010a4,[CaseUpper] = 0x0010a4}}, - {0x002d05, {[CaseLower] = 0x002d05,[CaseTitle] = 0x0010a5,[CaseUpper] = 0x0010a5}}, - {0x002d06, {[CaseLower] = 0x002d06,[CaseTitle] = 0x0010a6,[CaseUpper] = 0x0010a6}}, - {0x002d07, {[CaseLower] = 0x002d07,[CaseTitle] = 0x0010a7,[CaseUpper] = 0x0010a7}}, - {0x002d08, {[CaseLower] = 0x002d08,[CaseTitle] = 0x0010a8,[CaseUpper] = 0x0010a8}}, - {0x002d09, {[CaseLower] = 0x002d09,[CaseTitle] = 0x0010a9,[CaseUpper] = 0x0010a9}}, - {0x002d0a, {[CaseLower] = 0x002d0a,[CaseTitle] = 0x0010aa,[CaseUpper] = 0x0010aa}}, - {0x002d0b, {[CaseLower] = 0x002d0b,[CaseTitle] = 0x0010ab,[CaseUpper] = 0x0010ab}}, - {0x002d0c, {[CaseLower] = 0x002d0c,[CaseTitle] = 0x0010ac,[CaseUpper] = 0x0010ac}}, - {0x002d0d, {[CaseLower] = 0x002d0d,[CaseTitle] = 0x0010ad,[CaseUpper] = 0x0010ad}}, - {0x002d0e, {[CaseLower] = 0x002d0e,[CaseTitle] = 0x0010ae,[CaseUpper] = 0x0010ae}}, - {0x002d0f, {[CaseLower] = 0x002d0f,[CaseTitle] = 0x0010af,[CaseUpper] = 0x0010af}}, - {0x002d10, {[CaseLower] = 0x002d10,[CaseTitle] = 0x0010b0,[CaseUpper] = 0x0010b0}}, - {0x002d11, {[CaseLower] = 0x002d11,[CaseTitle] = 0x0010b1,[CaseUpper] = 0x0010b1}}, - {0x002d12, {[CaseLower] = 0x002d12,[CaseTitle] = 0x0010b2,[CaseUpper] = 0x0010b2}}, - {0x002d13, {[CaseLower] = 0x002d13,[CaseTitle] = 0x0010b3,[CaseUpper] = 0x0010b3}}, - {0x002d14, {[CaseLower] = 0x002d14,[CaseTitle] = 0x0010b4,[CaseUpper] = 0x0010b4}}, - {0x002d15, {[CaseLower] = 0x002d15,[CaseTitle] = 0x0010b5,[CaseUpper] = 0x0010b5}}, - {0x002d16, {[CaseLower] = 0x002d16,[CaseTitle] = 0x0010b6,[CaseUpper] = 0x0010b6}}, - {0x002d17, {[CaseLower] = 0x002d17,[CaseTitle] = 0x0010b7,[CaseUpper] = 0x0010b7}}, - {0x002d18, {[CaseLower] = 0x002d18,[CaseTitle] = 0x0010b8,[CaseUpper] = 0x0010b8}}, - {0x002d19, {[CaseLower] = 0x002d19,[CaseTitle] = 0x0010b9,[CaseUpper] = 0x0010b9}}, - {0x002d1a, {[CaseLower] = 0x002d1a,[CaseTitle] = 0x0010ba,[CaseUpper] = 0x0010ba}}, - {0x002d1b, {[CaseLower] = 0x002d1b,[CaseTitle] = 0x0010bb,[CaseUpper] = 0x0010bb}}, - {0x002d1c, {[CaseLower] = 0x002d1c,[CaseTitle] = 0x0010bc,[CaseUpper] = 0x0010bc}}, - {0x002d1d, {[CaseLower] = 0x002d1d,[CaseTitle] = 0x0010bd,[CaseUpper] = 0x0010bd}}, - {0x002d1e, {[CaseLower] = 0x002d1e,[CaseTitle] = 0x0010be,[CaseUpper] = 0x0010be}}, - {0x002d1f, {[CaseLower] = 0x002d1f,[CaseTitle] = 0x0010bf,[CaseUpper] = 0x0010bf}}, - {0x002d20, {[CaseLower] = 0x002d20,[CaseTitle] = 0x0010c0,[CaseUpper] = 0x0010c0}}, - {0x002d21, {[CaseLower] = 0x002d21,[CaseTitle] = 0x0010c1,[CaseUpper] = 0x0010c1}}, - {0x002d22, {[CaseLower] = 0x002d22,[CaseTitle] = 0x0010c2,[CaseUpper] = 0x0010c2}}, - {0x002d23, {[CaseLower] = 0x002d23,[CaseTitle] = 0x0010c3,[CaseUpper] = 0x0010c3}}, - {0x002d24, {[CaseLower] = 0x002d24,[CaseTitle] = 0x0010c4,[CaseUpper] = 0x0010c4}}, - {0x002d25, {[CaseLower] = 0x002d25,[CaseTitle] = 0x0010c5,[CaseUpper] = 0x0010c5}}, - {0x002d27, {[CaseLower] = 0x002d27,[CaseTitle] = 0x0010c7,[CaseUpper] = 0x0010c7}}, - {0x002d2d, {[CaseLower] = 0x002d2d,[CaseTitle] = 0x0010cd,[CaseUpper] = 0x0010cd}}, - {0x00a640, {[CaseLower] = 0x00a641,[CaseTitle] = 0x00a640,[CaseUpper] = 0x00a640}}, - {0x00a641, {[CaseLower] = 0x00a641,[CaseTitle] = 0x00a640,[CaseUpper] = 0x00a640}}, - {0x00a642, {[CaseLower] = 0x00a643,[CaseTitle] = 0x00a642,[CaseUpper] = 0x00a642}}, - {0x00a643, {[CaseLower] = 0x00a643,[CaseTitle] = 0x00a642,[CaseUpper] = 0x00a642}}, - {0x00a644, {[CaseLower] = 0x00a645,[CaseTitle] = 0x00a644,[CaseUpper] = 0x00a644}}, - {0x00a645, {[CaseLower] = 0x00a645,[CaseTitle] = 0x00a644,[CaseUpper] = 0x00a644}}, - {0x00a646, {[CaseLower] = 0x00a647,[CaseTitle] = 0x00a646,[CaseUpper] = 0x00a646}}, - {0x00a647, {[CaseLower] = 0x00a647,[CaseTitle] = 0x00a646,[CaseUpper] = 0x00a646}}, - {0x00a648, {[CaseLower] = 0x00a649,[CaseTitle] = 0x00a648,[CaseUpper] = 0x00a648}}, - {0x00a649, {[CaseLower] = 0x00a649,[CaseTitle] = 0x00a648,[CaseUpper] = 0x00a648}}, - {0x00a64a, {[CaseLower] = 0x00a64b,[CaseTitle] = 0x00a64a,[CaseUpper] = 0x00a64a}}, - {0x00a64b, {[CaseLower] = 0x00a64b,[CaseTitle] = 0x00a64a,[CaseUpper] = 0x00a64a}}, - {0x00a64c, {[CaseLower] = 0x00a64d,[CaseTitle] = 0x00a64c,[CaseUpper] = 0x00a64c}}, - {0x00a64d, {[CaseLower] = 0x00a64d,[CaseTitle] = 0x00a64c,[CaseUpper] = 0x00a64c}}, - {0x00a64e, {[CaseLower] = 0x00a64f,[CaseTitle] = 0x00a64e,[CaseUpper] = 0x00a64e}}, - {0x00a64f, {[CaseLower] = 0x00a64f,[CaseTitle] = 0x00a64e,[CaseUpper] = 0x00a64e}}, - {0x00a650, {[CaseLower] = 0x00a651,[CaseTitle] = 0x00a650,[CaseUpper] = 0x00a650}}, - {0x00a651, {[CaseLower] = 0x00a651,[CaseTitle] = 0x00a650,[CaseUpper] = 0x00a650}}, - {0x00a652, {[CaseLower] = 0x00a653,[CaseTitle] = 0x00a652,[CaseUpper] = 0x00a652}}, - {0x00a653, {[CaseLower] = 0x00a653,[CaseTitle] = 0x00a652,[CaseUpper] = 0x00a652}}, - {0x00a654, {[CaseLower] = 0x00a655,[CaseTitle] = 0x00a654,[CaseUpper] = 0x00a654}}, - {0x00a655, {[CaseLower] = 0x00a655,[CaseTitle] = 0x00a654,[CaseUpper] = 0x00a654}}, - {0x00a656, {[CaseLower] = 0x00a657,[CaseTitle] = 0x00a656,[CaseUpper] = 0x00a656}}, - {0x00a657, {[CaseLower] = 0x00a657,[CaseTitle] = 0x00a656,[CaseUpper] = 0x00a656}}, - {0x00a658, {[CaseLower] = 0x00a659,[CaseTitle] = 0x00a658,[CaseUpper] = 0x00a658}}, - {0x00a659, {[CaseLower] = 0x00a659,[CaseTitle] = 0x00a658,[CaseUpper] = 0x00a658}}, - {0x00a65a, {[CaseLower] = 0x00a65b,[CaseTitle] = 0x00a65a,[CaseUpper] = 0x00a65a}}, - {0x00a65b, {[CaseLower] = 0x00a65b,[CaseTitle] = 0x00a65a,[CaseUpper] = 0x00a65a}}, - {0x00a65c, {[CaseLower] = 0x00a65d,[CaseTitle] = 0x00a65c,[CaseUpper] = 0x00a65c}}, - {0x00a65d, {[CaseLower] = 0x00a65d,[CaseTitle] = 0x00a65c,[CaseUpper] = 0x00a65c}}, - {0x00a65e, {[CaseLower] = 0x00a65f,[CaseTitle] = 0x00a65e,[CaseUpper] = 0x00a65e}}, - {0x00a65f, {[CaseLower] = 0x00a65f,[CaseTitle] = 0x00a65e,[CaseUpper] = 0x00a65e}}, - {0x00a660, {[CaseLower] = 0x00a661,[CaseTitle] = 0x00a660,[CaseUpper] = 0x00a660}}, - {0x00a661, {[CaseLower] = 0x00a661,[CaseTitle] = 0x00a660,[CaseUpper] = 0x00a660}}, - {0x00a662, {[CaseLower] = 0x00a663,[CaseTitle] = 0x00a662,[CaseUpper] = 0x00a662}}, - {0x00a663, {[CaseLower] = 0x00a663,[CaseTitle] = 0x00a662,[CaseUpper] = 0x00a662}}, - {0x00a664, {[CaseLower] = 0x00a665,[CaseTitle] = 0x00a664,[CaseUpper] = 0x00a664}}, - {0x00a665, {[CaseLower] = 0x00a665,[CaseTitle] = 0x00a664,[CaseUpper] = 0x00a664}}, - {0x00a666, {[CaseLower] = 0x00a667,[CaseTitle] = 0x00a666,[CaseUpper] = 0x00a666}}, - {0x00a667, {[CaseLower] = 0x00a667,[CaseTitle] = 0x00a666,[CaseUpper] = 0x00a666}}, - {0x00a668, {[CaseLower] = 0x00a669,[CaseTitle] = 0x00a668,[CaseUpper] = 0x00a668}}, - {0x00a669, {[CaseLower] = 0x00a669,[CaseTitle] = 0x00a668,[CaseUpper] = 0x00a668}}, - {0x00a66a, {[CaseLower] = 0x00a66b,[CaseTitle] = 0x00a66a,[CaseUpper] = 0x00a66a}}, - {0x00a66b, {[CaseLower] = 0x00a66b,[CaseTitle] = 0x00a66a,[CaseUpper] = 0x00a66a}}, - {0x00a66c, {[CaseLower] = 0x00a66d,[CaseTitle] = 0x00a66c,[CaseUpper] = 0x00a66c}}, - {0x00a66d, {[CaseLower] = 0x00a66d,[CaseTitle] = 0x00a66c,[CaseUpper] = 0x00a66c}}, - {0x00a680, {[CaseLower] = 0x00a681,[CaseTitle] = 0x00a680,[CaseUpper] = 0x00a680}}, - {0x00a681, {[CaseLower] = 0x00a681,[CaseTitle] = 0x00a680,[CaseUpper] = 0x00a680}}, - {0x00a682, {[CaseLower] = 0x00a683,[CaseTitle] = 0x00a682,[CaseUpper] = 0x00a682}}, - {0x00a683, {[CaseLower] = 0x00a683,[CaseTitle] = 0x00a682,[CaseUpper] = 0x00a682}}, - {0x00a684, {[CaseLower] = 0x00a685,[CaseTitle] = 0x00a684,[CaseUpper] = 0x00a684}}, - {0x00a685, {[CaseLower] = 0x00a685,[CaseTitle] = 0x00a684,[CaseUpper] = 0x00a684}}, - {0x00a686, {[CaseLower] = 0x00a687,[CaseTitle] = 0x00a686,[CaseUpper] = 0x00a686}}, - {0x00a687, {[CaseLower] = 0x00a687,[CaseTitle] = 0x00a686,[CaseUpper] = 0x00a686}}, - {0x00a688, {[CaseLower] = 0x00a689,[CaseTitle] = 0x00a688,[CaseUpper] = 0x00a688}}, - {0x00a689, {[CaseLower] = 0x00a689,[CaseTitle] = 0x00a688,[CaseUpper] = 0x00a688}}, - {0x00a68a, {[CaseLower] = 0x00a68b,[CaseTitle] = 0x00a68a,[CaseUpper] = 0x00a68a}}, - {0x00a68b, {[CaseLower] = 0x00a68b,[CaseTitle] = 0x00a68a,[CaseUpper] = 0x00a68a}}, - {0x00a68c, {[CaseLower] = 0x00a68d,[CaseTitle] = 0x00a68c,[CaseUpper] = 0x00a68c}}, - {0x00a68d, {[CaseLower] = 0x00a68d,[CaseTitle] = 0x00a68c,[CaseUpper] = 0x00a68c}}, - {0x00a68e, {[CaseLower] = 0x00a68f,[CaseTitle] = 0x00a68e,[CaseUpper] = 0x00a68e}}, - {0x00a68f, {[CaseLower] = 0x00a68f,[CaseTitle] = 0x00a68e,[CaseUpper] = 0x00a68e}}, - {0x00a690, {[CaseLower] = 0x00a691,[CaseTitle] = 0x00a690,[CaseUpper] = 0x00a690}}, - {0x00a691, {[CaseLower] = 0x00a691,[CaseTitle] = 0x00a690,[CaseUpper] = 0x00a690}}, - {0x00a692, {[CaseLower] = 0x00a693,[CaseTitle] = 0x00a692,[CaseUpper] = 0x00a692}}, - {0x00a693, {[CaseLower] = 0x00a693,[CaseTitle] = 0x00a692,[CaseUpper] = 0x00a692}}, - {0x00a694, {[CaseLower] = 0x00a695,[CaseTitle] = 0x00a694,[CaseUpper] = 0x00a694}}, - {0x00a695, {[CaseLower] = 0x00a695,[CaseTitle] = 0x00a694,[CaseUpper] = 0x00a694}}, - {0x00a696, {[CaseLower] = 0x00a697,[CaseTitle] = 0x00a696,[CaseUpper] = 0x00a696}}, - {0x00a697, {[CaseLower] = 0x00a697,[CaseTitle] = 0x00a696,[CaseUpper] = 0x00a696}}, - {0x00a698, {[CaseLower] = 0x00a699,[CaseTitle] = 0x00a698,[CaseUpper] = 0x00a698}}, - {0x00a699, {[CaseLower] = 0x00a699,[CaseTitle] = 0x00a698,[CaseUpper] = 0x00a698}}, - {0x00a69a, {[CaseLower] = 0x00a69b,[CaseTitle] = 0x00a69a,[CaseUpper] = 0x00a69a}}, - {0x00a69b, {[CaseLower] = 0x00a69b,[CaseTitle] = 0x00a69a,[CaseUpper] = 0x00a69a}}, - {0x00a722, {[CaseLower] = 0x00a723,[CaseTitle] = 0x00a722,[CaseUpper] = 0x00a722}}, - {0x00a723, {[CaseLower] = 0x00a723,[CaseTitle] = 0x00a722,[CaseUpper] = 0x00a722}}, - {0x00a724, {[CaseLower] = 0x00a725,[CaseTitle] = 0x00a724,[CaseUpper] = 0x00a724}}, - {0x00a725, {[CaseLower] = 0x00a725,[CaseTitle] = 0x00a724,[CaseUpper] = 0x00a724}}, - {0x00a726, {[CaseLower] = 0x00a727,[CaseTitle] = 0x00a726,[CaseUpper] = 0x00a726}}, - {0x00a727, {[CaseLower] = 0x00a727,[CaseTitle] = 0x00a726,[CaseUpper] = 0x00a726}}, - {0x00a728, {[CaseLower] = 0x00a729,[CaseTitle] = 0x00a728,[CaseUpper] = 0x00a728}}, - {0x00a729, {[CaseLower] = 0x00a729,[CaseTitle] = 0x00a728,[CaseUpper] = 0x00a728}}, - {0x00a72a, {[CaseLower] = 0x00a72b,[CaseTitle] = 0x00a72a,[CaseUpper] = 0x00a72a}}, - {0x00a72b, {[CaseLower] = 0x00a72b,[CaseTitle] = 0x00a72a,[CaseUpper] = 0x00a72a}}, - {0x00a72c, {[CaseLower] = 0x00a72d,[CaseTitle] = 0x00a72c,[CaseUpper] = 0x00a72c}}, - {0x00a72d, {[CaseLower] = 0x00a72d,[CaseTitle] = 0x00a72c,[CaseUpper] = 0x00a72c}}, - {0x00a72e, {[CaseLower] = 0x00a72f,[CaseTitle] = 0x00a72e,[CaseUpper] = 0x00a72e}}, - {0x00a72f, {[CaseLower] = 0x00a72f,[CaseTitle] = 0x00a72e,[CaseUpper] = 0x00a72e}}, - {0x00a732, {[CaseLower] = 0x00a733,[CaseTitle] = 0x00a732,[CaseUpper] = 0x00a732}}, - {0x00a733, {[CaseLower] = 0x00a733,[CaseTitle] = 0x00a732,[CaseUpper] = 0x00a732}}, - {0x00a734, {[CaseLower] = 0x00a735,[CaseTitle] = 0x00a734,[CaseUpper] = 0x00a734}}, - {0x00a735, {[CaseLower] = 0x00a735,[CaseTitle] = 0x00a734,[CaseUpper] = 0x00a734}}, - {0x00a736, {[CaseLower] = 0x00a737,[CaseTitle] = 0x00a736,[CaseUpper] = 0x00a736}}, - {0x00a737, {[CaseLower] = 0x00a737,[CaseTitle] = 0x00a736,[CaseUpper] = 0x00a736}}, - {0x00a738, {[CaseLower] = 0x00a739,[CaseTitle] = 0x00a738,[CaseUpper] = 0x00a738}}, - {0x00a739, {[CaseLower] = 0x00a739,[CaseTitle] = 0x00a738,[CaseUpper] = 0x00a738}}, - {0x00a73a, {[CaseLower] = 0x00a73b,[CaseTitle] = 0x00a73a,[CaseUpper] = 0x00a73a}}, - {0x00a73b, {[CaseLower] = 0x00a73b,[CaseTitle] = 0x00a73a,[CaseUpper] = 0x00a73a}}, - {0x00a73c, {[CaseLower] = 0x00a73d,[CaseTitle] = 0x00a73c,[CaseUpper] = 0x00a73c}}, - {0x00a73d, {[CaseLower] = 0x00a73d,[CaseTitle] = 0x00a73c,[CaseUpper] = 0x00a73c}}, - {0x00a73e, {[CaseLower] = 0x00a73f,[CaseTitle] = 0x00a73e,[CaseUpper] = 0x00a73e}}, - {0x00a73f, {[CaseLower] = 0x00a73f,[CaseTitle] = 0x00a73e,[CaseUpper] = 0x00a73e}}, - {0x00a740, {[CaseLower] = 0x00a741,[CaseTitle] = 0x00a740,[CaseUpper] = 0x00a740}}, - {0x00a741, {[CaseLower] = 0x00a741,[CaseTitle] = 0x00a740,[CaseUpper] = 0x00a740}}, - {0x00a742, {[CaseLower] = 0x00a743,[CaseTitle] = 0x00a742,[CaseUpper] = 0x00a742}}, - {0x00a743, {[CaseLower] = 0x00a743,[CaseTitle] = 0x00a742,[CaseUpper] = 0x00a742}}, - {0x00a744, {[CaseLower] = 0x00a745,[CaseTitle] = 0x00a744,[CaseUpper] = 0x00a744}}, - {0x00a745, {[CaseLower] = 0x00a745,[CaseTitle] = 0x00a744,[CaseUpper] = 0x00a744}}, - {0x00a746, {[CaseLower] = 0x00a747,[CaseTitle] = 0x00a746,[CaseUpper] = 0x00a746}}, - {0x00a747, {[CaseLower] = 0x00a747,[CaseTitle] = 0x00a746,[CaseUpper] = 0x00a746}}, - {0x00a748, {[CaseLower] = 0x00a749,[CaseTitle] = 0x00a748,[CaseUpper] = 0x00a748}}, - {0x00a749, {[CaseLower] = 0x00a749,[CaseTitle] = 0x00a748,[CaseUpper] = 0x00a748}}, - {0x00a74a, {[CaseLower] = 0x00a74b,[CaseTitle] = 0x00a74a,[CaseUpper] = 0x00a74a}}, - {0x00a74b, {[CaseLower] = 0x00a74b,[CaseTitle] = 0x00a74a,[CaseUpper] = 0x00a74a}}, - {0x00a74c, {[CaseLower] = 0x00a74d,[CaseTitle] = 0x00a74c,[CaseUpper] = 0x00a74c}}, - {0x00a74d, {[CaseLower] = 0x00a74d,[CaseTitle] = 0x00a74c,[CaseUpper] = 0x00a74c}}, - {0x00a74e, {[CaseLower] = 0x00a74f,[CaseTitle] = 0x00a74e,[CaseUpper] = 0x00a74e}}, - {0x00a74f, {[CaseLower] = 0x00a74f,[CaseTitle] = 0x00a74e,[CaseUpper] = 0x00a74e}}, - {0x00a750, {[CaseLower] = 0x00a751,[CaseTitle] = 0x00a750,[CaseUpper] = 0x00a750}}, - {0x00a751, {[CaseLower] = 0x00a751,[CaseTitle] = 0x00a750,[CaseUpper] = 0x00a750}}, - {0x00a752, {[CaseLower] = 0x00a753,[CaseTitle] = 0x00a752,[CaseUpper] = 0x00a752}}, - {0x00a753, {[CaseLower] = 0x00a753,[CaseTitle] = 0x00a752,[CaseUpper] = 0x00a752}}, - {0x00a754, {[CaseLower] = 0x00a755,[CaseTitle] = 0x00a754,[CaseUpper] = 0x00a754}}, - {0x00a755, {[CaseLower] = 0x00a755,[CaseTitle] = 0x00a754,[CaseUpper] = 0x00a754}}, - {0x00a756, {[CaseLower] = 0x00a757,[CaseTitle] = 0x00a756,[CaseUpper] = 0x00a756}}, - {0x00a757, {[CaseLower] = 0x00a757,[CaseTitle] = 0x00a756,[CaseUpper] = 0x00a756}}, - {0x00a758, {[CaseLower] = 0x00a759,[CaseTitle] = 0x00a758,[CaseUpper] = 0x00a758}}, - {0x00a759, {[CaseLower] = 0x00a759,[CaseTitle] = 0x00a758,[CaseUpper] = 0x00a758}}, - {0x00a75a, {[CaseLower] = 0x00a75b,[CaseTitle] = 0x00a75a,[CaseUpper] = 0x00a75a}}, - {0x00a75b, {[CaseLower] = 0x00a75b,[CaseTitle] = 0x00a75a,[CaseUpper] = 0x00a75a}}, - {0x00a75c, {[CaseLower] = 0x00a75d,[CaseTitle] = 0x00a75c,[CaseUpper] = 0x00a75c}}, - {0x00a75d, {[CaseLower] = 0x00a75d,[CaseTitle] = 0x00a75c,[CaseUpper] = 0x00a75c}}, - {0x00a75e, {[CaseLower] = 0x00a75f,[CaseTitle] = 0x00a75e,[CaseUpper] = 0x00a75e}}, - {0x00a75f, {[CaseLower] = 0x00a75f,[CaseTitle] = 0x00a75e,[CaseUpper] = 0x00a75e}}, - {0x00a760, {[CaseLower] = 0x00a761,[CaseTitle] = 0x00a760,[CaseUpper] = 0x00a760}}, - {0x00a761, {[CaseLower] = 0x00a761,[CaseTitle] = 0x00a760,[CaseUpper] = 0x00a760}}, - {0x00a762, {[CaseLower] = 0x00a763,[CaseTitle] = 0x00a762,[CaseUpper] = 0x00a762}}, - {0x00a763, {[CaseLower] = 0x00a763,[CaseTitle] = 0x00a762,[CaseUpper] = 0x00a762}}, - {0x00a764, {[CaseLower] = 0x00a765,[CaseTitle] = 0x00a764,[CaseUpper] = 0x00a764}}, - {0x00a765, {[CaseLower] = 0x00a765,[CaseTitle] = 0x00a764,[CaseUpper] = 0x00a764}}, - {0x00a766, {[CaseLower] = 0x00a767,[CaseTitle] = 0x00a766,[CaseUpper] = 0x00a766}}, - {0x00a767, {[CaseLower] = 0x00a767,[CaseTitle] = 0x00a766,[CaseUpper] = 0x00a766}}, - {0x00a768, {[CaseLower] = 0x00a769,[CaseTitle] = 0x00a768,[CaseUpper] = 0x00a768}}, - {0x00a769, {[CaseLower] = 0x00a769,[CaseTitle] = 0x00a768,[CaseUpper] = 0x00a768}}, - {0x00a76a, {[CaseLower] = 0x00a76b,[CaseTitle] = 0x00a76a,[CaseUpper] = 0x00a76a}}, - {0x00a76b, {[CaseLower] = 0x00a76b,[CaseTitle] = 0x00a76a,[CaseUpper] = 0x00a76a}}, - {0x00a76c, {[CaseLower] = 0x00a76d,[CaseTitle] = 0x00a76c,[CaseUpper] = 0x00a76c}}, - {0x00a76d, {[CaseLower] = 0x00a76d,[CaseTitle] = 0x00a76c,[CaseUpper] = 0x00a76c}}, - {0x00a76e, {[CaseLower] = 0x00a76f,[CaseTitle] = 0x00a76e,[CaseUpper] = 0x00a76e}}, - {0x00a76f, {[CaseLower] = 0x00a76f,[CaseTitle] = 0x00a76e,[CaseUpper] = 0x00a76e}}, - {0x00a779, {[CaseLower] = 0x00a77a,[CaseTitle] = 0x00a779,[CaseUpper] = 0x00a779}}, - {0x00a77a, {[CaseLower] = 0x00a77a,[CaseTitle] = 0x00a779,[CaseUpper] = 0x00a779}}, - {0x00a77b, {[CaseLower] = 0x00a77c,[CaseTitle] = 0x00a77b,[CaseUpper] = 0x00a77b}}, - {0x00a77c, {[CaseLower] = 0x00a77c,[CaseTitle] = 0x00a77b,[CaseUpper] = 0x00a77b}}, - {0x00a77d, {[CaseLower] = 0x001d79,[CaseTitle] = 0x00a77d,[CaseUpper] = 0x00a77d}}, - {0x00a77e, {[CaseLower] = 0x00a77f,[CaseTitle] = 0x00a77e,[CaseUpper] = 0x00a77e}}, - {0x00a77f, {[CaseLower] = 0x00a77f,[CaseTitle] = 0x00a77e,[CaseUpper] = 0x00a77e}}, - {0x00a780, {[CaseLower] = 0x00a781,[CaseTitle] = 0x00a780,[CaseUpper] = 0x00a780}}, - {0x00a781, {[CaseLower] = 0x00a781,[CaseTitle] = 0x00a780,[CaseUpper] = 0x00a780}}, - {0x00a782, {[CaseLower] = 0x00a783,[CaseTitle] = 0x00a782,[CaseUpper] = 0x00a782}}, - {0x00a783, {[CaseLower] = 0x00a783,[CaseTitle] = 0x00a782,[CaseUpper] = 0x00a782}}, - {0x00a784, {[CaseLower] = 0x00a785,[CaseTitle] = 0x00a784,[CaseUpper] = 0x00a784}}, - {0x00a785, {[CaseLower] = 0x00a785,[CaseTitle] = 0x00a784,[CaseUpper] = 0x00a784}}, - {0x00a786, {[CaseLower] = 0x00a787,[CaseTitle] = 0x00a786,[CaseUpper] = 0x00a786}}, - {0x00a787, {[CaseLower] = 0x00a787,[CaseTitle] = 0x00a786,[CaseUpper] = 0x00a786}}, - {0x00a78b, {[CaseLower] = 0x00a78c,[CaseTitle] = 0x00a78b,[CaseUpper] = 0x00a78b}}, - {0x00a78c, {[CaseLower] = 0x00a78c,[CaseTitle] = 0x00a78b,[CaseUpper] = 0x00a78b}}, - {0x00a78d, {[CaseLower] = 0x000265,[CaseTitle] = 0x00a78d,[CaseUpper] = 0x00a78d}}, - {0x00a790, {[CaseLower] = 0x00a791,[CaseTitle] = 0x00a790,[CaseUpper] = 0x00a790}}, - {0x00a791, {[CaseLower] = 0x00a791,[CaseTitle] = 0x00a790,[CaseUpper] = 0x00a790}}, - {0x00a792, {[CaseLower] = 0x00a793,[CaseTitle] = 0x00a792,[CaseUpper] = 0x00a792}}, - {0x00a793, {[CaseLower] = 0x00a793,[CaseTitle] = 0x00a792,[CaseUpper] = 0x00a792}}, - {0x00a794, {[CaseLower] = 0x00a794,[CaseTitle] = 0x00a7c4,[CaseUpper] = 0x00a7c4}}, - {0x00a796, {[CaseLower] = 0x00a797,[CaseTitle] = 0x00a796,[CaseUpper] = 0x00a796}}, - {0x00a797, {[CaseLower] = 0x00a797,[CaseTitle] = 0x00a796,[CaseUpper] = 0x00a796}}, - {0x00a798, {[CaseLower] = 0x00a799,[CaseTitle] = 0x00a798,[CaseUpper] = 0x00a798}}, - {0x00a799, {[CaseLower] = 0x00a799,[CaseTitle] = 0x00a798,[CaseUpper] = 0x00a798}}, - {0x00a79a, {[CaseLower] = 0x00a79b,[CaseTitle] = 0x00a79a,[CaseUpper] = 0x00a79a}}, - {0x00a79b, {[CaseLower] = 0x00a79b,[CaseTitle] = 0x00a79a,[CaseUpper] = 0x00a79a}}, - {0x00a79c, {[CaseLower] = 0x00a79d,[CaseTitle] = 0x00a79c,[CaseUpper] = 0x00a79c}}, - {0x00a79d, {[CaseLower] = 0x00a79d,[CaseTitle] = 0x00a79c,[CaseUpper] = 0x00a79c}}, - {0x00a79e, {[CaseLower] = 0x00a79f,[CaseTitle] = 0x00a79e,[CaseUpper] = 0x00a79e}}, - {0x00a79f, {[CaseLower] = 0x00a79f,[CaseTitle] = 0x00a79e,[CaseUpper] = 0x00a79e}}, - {0x00a7a0, {[CaseLower] = 0x00a7a1,[CaseTitle] = 0x00a7a0,[CaseUpper] = 0x00a7a0}}, - {0x00a7a1, {[CaseLower] = 0x00a7a1,[CaseTitle] = 0x00a7a0,[CaseUpper] = 0x00a7a0}}, - {0x00a7a2, {[CaseLower] = 0x00a7a3,[CaseTitle] = 0x00a7a2,[CaseUpper] = 0x00a7a2}}, - {0x00a7a3, {[CaseLower] = 0x00a7a3,[CaseTitle] = 0x00a7a2,[CaseUpper] = 0x00a7a2}}, - {0x00a7a4, {[CaseLower] = 0x00a7a5,[CaseTitle] = 0x00a7a4,[CaseUpper] = 0x00a7a4}}, - {0x00a7a5, {[CaseLower] = 0x00a7a5,[CaseTitle] = 0x00a7a4,[CaseUpper] = 0x00a7a4}}, - {0x00a7a6, {[CaseLower] = 0x00a7a7,[CaseTitle] = 0x00a7a6,[CaseUpper] = 0x00a7a6}}, - {0x00a7a7, {[CaseLower] = 0x00a7a7,[CaseTitle] = 0x00a7a6,[CaseUpper] = 0x00a7a6}}, - {0x00a7a8, {[CaseLower] = 0x00a7a9,[CaseTitle] = 0x00a7a8,[CaseUpper] = 0x00a7a8}}, - {0x00a7a9, {[CaseLower] = 0x00a7a9,[CaseTitle] = 0x00a7a8,[CaseUpper] = 0x00a7a8}}, - {0x00a7aa, {[CaseLower] = 0x000266,[CaseTitle] = 0x00a7aa,[CaseUpper] = 0x00a7aa}}, - {0x00a7ab, {[CaseLower] = 0x00025c,[CaseTitle] = 0x00a7ab,[CaseUpper] = 0x00a7ab}}, - {0x00a7ac, {[CaseLower] = 0x000261,[CaseTitle] = 0x00a7ac,[CaseUpper] = 0x00a7ac}}, - {0x00a7ad, {[CaseLower] = 0x00026c,[CaseTitle] = 0x00a7ad,[CaseUpper] = 0x00a7ad}}, - {0x00a7ae, {[CaseLower] = 0x00026a,[CaseTitle] = 0x00a7ae,[CaseUpper] = 0x00a7ae}}, - {0x00a7b0, {[CaseLower] = 0x00029e,[CaseTitle] = 0x00a7b0,[CaseUpper] = 0x00a7b0}}, - {0x00a7b1, {[CaseLower] = 0x000287,[CaseTitle] = 0x00a7b1,[CaseUpper] = 0x00a7b1}}, - {0x00a7b2, {[CaseLower] = 0x00029d,[CaseTitle] = 0x00a7b2,[CaseUpper] = 0x00a7b2}}, - {0x00a7b3, {[CaseLower] = 0x00ab53,[CaseTitle] = 0x00a7b3,[CaseUpper] = 0x00a7b3}}, - {0x00a7b4, {[CaseLower] = 0x00a7b5,[CaseTitle] = 0x00a7b4,[CaseUpper] = 0x00a7b4}}, - {0x00a7b5, {[CaseLower] = 0x00a7b5,[CaseTitle] = 0x00a7b4,[CaseUpper] = 0x00a7b4}}, - {0x00a7b6, {[CaseLower] = 0x00a7b7,[CaseTitle] = 0x00a7b6,[CaseUpper] = 0x00a7b6}}, - {0x00a7b7, {[CaseLower] = 0x00a7b7,[CaseTitle] = 0x00a7b6,[CaseUpper] = 0x00a7b6}}, - {0x00a7b8, {[CaseLower] = 0x00a7b9,[CaseTitle] = 0x00a7b8,[CaseUpper] = 0x00a7b8}}, - {0x00a7b9, {[CaseLower] = 0x00a7b9,[CaseTitle] = 0x00a7b8,[CaseUpper] = 0x00a7b8}}, - {0x00a7ba, {[CaseLower] = 0x00a7bb,[CaseTitle] = 0x00a7ba,[CaseUpper] = 0x00a7ba}}, - {0x00a7bb, {[CaseLower] = 0x00a7bb,[CaseTitle] = 0x00a7ba,[CaseUpper] = 0x00a7ba}}, - {0x00a7bc, {[CaseLower] = 0x00a7bd,[CaseTitle] = 0x00a7bc,[CaseUpper] = 0x00a7bc}}, - {0x00a7bd, {[CaseLower] = 0x00a7bd,[CaseTitle] = 0x00a7bc,[CaseUpper] = 0x00a7bc}}, - {0x00a7be, {[CaseLower] = 0x00a7bf,[CaseTitle] = 0x00a7be,[CaseUpper] = 0x00a7be}}, - {0x00a7bf, {[CaseLower] = 0x00a7bf,[CaseTitle] = 0x00a7be,[CaseUpper] = 0x00a7be}}, - {0x00a7c0, {[CaseLower] = 0x00a7c1,[CaseTitle] = 0x00a7c0,[CaseUpper] = 0x00a7c0}}, - {0x00a7c1, {[CaseLower] = 0x00a7c1,[CaseTitle] = 0x00a7c0,[CaseUpper] = 0x00a7c0}}, - {0x00a7c2, {[CaseLower] = 0x00a7c3,[CaseTitle] = 0x00a7c2,[CaseUpper] = 0x00a7c2}}, - {0x00a7c3, {[CaseLower] = 0x00a7c3,[CaseTitle] = 0x00a7c2,[CaseUpper] = 0x00a7c2}}, - {0x00a7c4, {[CaseLower] = 0x00a794,[CaseTitle] = 0x00a7c4,[CaseUpper] = 0x00a7c4}}, - {0x00a7c5, {[CaseLower] = 0x000282,[CaseTitle] = 0x00a7c5,[CaseUpper] = 0x00a7c5}}, - {0x00a7c6, {[CaseLower] = 0x001d8e,[CaseTitle] = 0x00a7c6,[CaseUpper] = 0x00a7c6}}, - {0x00a7c7, {[CaseLower] = 0x00a7c8,[CaseTitle] = 0x00a7c7,[CaseUpper] = 0x00a7c7}}, - {0x00a7c8, {[CaseLower] = 0x00a7c8,[CaseTitle] = 0x00a7c7,[CaseUpper] = 0x00a7c7}}, - {0x00a7c9, {[CaseLower] = 0x00a7ca,[CaseTitle] = 0x00a7c9,[CaseUpper] = 0x00a7c9}}, - {0x00a7ca, {[CaseLower] = 0x00a7ca,[CaseTitle] = 0x00a7c9,[CaseUpper] = 0x00a7c9}}, - {0x00a7d0, {[CaseLower] = 0x00a7d1,[CaseTitle] = 0x00a7d0,[CaseUpper] = 0x00a7d0}}, - {0x00a7d1, {[CaseLower] = 0x00a7d1,[CaseTitle] = 0x00a7d0,[CaseUpper] = 0x00a7d0}}, - {0x00a7d6, {[CaseLower] = 0x00a7d7,[CaseTitle] = 0x00a7d6,[CaseUpper] = 0x00a7d6}}, - {0x00a7d7, {[CaseLower] = 0x00a7d7,[CaseTitle] = 0x00a7d6,[CaseUpper] = 0x00a7d6}}, - {0x00a7d8, {[CaseLower] = 0x00a7d9,[CaseTitle] = 0x00a7d8,[CaseUpper] = 0x00a7d8}}, - {0x00a7d9, {[CaseLower] = 0x00a7d9,[CaseTitle] = 0x00a7d8,[CaseUpper] = 0x00a7d8}}, - {0x00a7f5, {[CaseLower] = 0x00a7f6,[CaseTitle] = 0x00a7f5,[CaseUpper] = 0x00a7f5}}, - {0x00a7f6, {[CaseLower] = 0x00a7f6,[CaseTitle] = 0x00a7f5,[CaseUpper] = 0x00a7f5}}, - {0x00ab53, {[CaseLower] = 0x00ab53,[CaseTitle] = 0x00a7b3,[CaseUpper] = 0x00a7b3}}, - {0x00ab70, {[CaseLower] = 0x00ab70,[CaseTitle] = 0x0013a0,[CaseUpper] = 0x0013a0}}, - {0x00ab71, {[CaseLower] = 0x00ab71,[CaseTitle] = 0x0013a1,[CaseUpper] = 0x0013a1}}, - {0x00ab72, {[CaseLower] = 0x00ab72,[CaseTitle] = 0x0013a2,[CaseUpper] = 0x0013a2}}, - {0x00ab73, {[CaseLower] = 0x00ab73,[CaseTitle] = 0x0013a3,[CaseUpper] = 0x0013a3}}, - {0x00ab74, {[CaseLower] = 0x00ab74,[CaseTitle] = 0x0013a4,[CaseUpper] = 0x0013a4}}, - {0x00ab75, {[CaseLower] = 0x00ab75,[CaseTitle] = 0x0013a5,[CaseUpper] = 0x0013a5}}, - {0x00ab76, {[CaseLower] = 0x00ab76,[CaseTitle] = 0x0013a6,[CaseUpper] = 0x0013a6}}, - {0x00ab77, {[CaseLower] = 0x00ab77,[CaseTitle] = 0x0013a7,[CaseUpper] = 0x0013a7}}, - {0x00ab78, {[CaseLower] = 0x00ab78,[CaseTitle] = 0x0013a8,[CaseUpper] = 0x0013a8}}, - {0x00ab79, {[CaseLower] = 0x00ab79,[CaseTitle] = 0x0013a9,[CaseUpper] = 0x0013a9}}, - {0x00ab7a, {[CaseLower] = 0x00ab7a,[CaseTitle] = 0x0013aa,[CaseUpper] = 0x0013aa}}, - {0x00ab7b, {[CaseLower] = 0x00ab7b,[CaseTitle] = 0x0013ab,[CaseUpper] = 0x0013ab}}, - {0x00ab7c, {[CaseLower] = 0x00ab7c,[CaseTitle] = 0x0013ac,[CaseUpper] = 0x0013ac}}, - {0x00ab7d, {[CaseLower] = 0x00ab7d,[CaseTitle] = 0x0013ad,[CaseUpper] = 0x0013ad}}, - {0x00ab7e, {[CaseLower] = 0x00ab7e,[CaseTitle] = 0x0013ae,[CaseUpper] = 0x0013ae}}, - {0x00ab7f, {[CaseLower] = 0x00ab7f,[CaseTitle] = 0x0013af,[CaseUpper] = 0x0013af}}, - {0x00ab80, {[CaseLower] = 0x00ab80,[CaseTitle] = 0x0013b0,[CaseUpper] = 0x0013b0}}, - {0x00ab81, {[CaseLower] = 0x00ab81,[CaseTitle] = 0x0013b1,[CaseUpper] = 0x0013b1}}, - {0x00ab82, {[CaseLower] = 0x00ab82,[CaseTitle] = 0x0013b2,[CaseUpper] = 0x0013b2}}, - {0x00ab83, {[CaseLower] = 0x00ab83,[CaseTitle] = 0x0013b3,[CaseUpper] = 0x0013b3}}, - {0x00ab84, {[CaseLower] = 0x00ab84,[CaseTitle] = 0x0013b4,[CaseUpper] = 0x0013b4}}, - {0x00ab85, {[CaseLower] = 0x00ab85,[CaseTitle] = 0x0013b5,[CaseUpper] = 0x0013b5}}, - {0x00ab86, {[CaseLower] = 0x00ab86,[CaseTitle] = 0x0013b6,[CaseUpper] = 0x0013b6}}, - {0x00ab87, {[CaseLower] = 0x00ab87,[CaseTitle] = 0x0013b7,[CaseUpper] = 0x0013b7}}, - {0x00ab88, {[CaseLower] = 0x00ab88,[CaseTitle] = 0x0013b8,[CaseUpper] = 0x0013b8}}, - {0x00ab89, {[CaseLower] = 0x00ab89,[CaseTitle] = 0x0013b9,[CaseUpper] = 0x0013b9}}, - {0x00ab8a, {[CaseLower] = 0x00ab8a,[CaseTitle] = 0x0013ba,[CaseUpper] = 0x0013ba}}, - {0x00ab8b, {[CaseLower] = 0x00ab8b,[CaseTitle] = 0x0013bb,[CaseUpper] = 0x0013bb}}, - {0x00ab8c, {[CaseLower] = 0x00ab8c,[CaseTitle] = 0x0013bc,[CaseUpper] = 0x0013bc}}, - {0x00ab8d, {[CaseLower] = 0x00ab8d,[CaseTitle] = 0x0013bd,[CaseUpper] = 0x0013bd}}, - {0x00ab8e, {[CaseLower] = 0x00ab8e,[CaseTitle] = 0x0013be,[CaseUpper] = 0x0013be}}, - {0x00ab8f, {[CaseLower] = 0x00ab8f,[CaseTitle] = 0x0013bf,[CaseUpper] = 0x0013bf}}, - {0x00ab90, {[CaseLower] = 0x00ab90,[CaseTitle] = 0x0013c0,[CaseUpper] = 0x0013c0}}, - {0x00ab91, {[CaseLower] = 0x00ab91,[CaseTitle] = 0x0013c1,[CaseUpper] = 0x0013c1}}, - {0x00ab92, {[CaseLower] = 0x00ab92,[CaseTitle] = 0x0013c2,[CaseUpper] = 0x0013c2}}, - {0x00ab93, {[CaseLower] = 0x00ab93,[CaseTitle] = 0x0013c3,[CaseUpper] = 0x0013c3}}, - {0x00ab94, {[CaseLower] = 0x00ab94,[CaseTitle] = 0x0013c4,[CaseUpper] = 0x0013c4}}, - {0x00ab95, {[CaseLower] = 0x00ab95,[CaseTitle] = 0x0013c5,[CaseUpper] = 0x0013c5}}, - {0x00ab96, {[CaseLower] = 0x00ab96,[CaseTitle] = 0x0013c6,[CaseUpper] = 0x0013c6}}, - {0x00ab97, {[CaseLower] = 0x00ab97,[CaseTitle] = 0x0013c7,[CaseUpper] = 0x0013c7}}, - {0x00ab98, {[CaseLower] = 0x00ab98,[CaseTitle] = 0x0013c8,[CaseUpper] = 0x0013c8}}, - {0x00ab99, {[CaseLower] = 0x00ab99,[CaseTitle] = 0x0013c9,[CaseUpper] = 0x0013c9}}, - {0x00ab9a, {[CaseLower] = 0x00ab9a,[CaseTitle] = 0x0013ca,[CaseUpper] = 0x0013ca}}, - {0x00ab9b, {[CaseLower] = 0x00ab9b,[CaseTitle] = 0x0013cb,[CaseUpper] = 0x0013cb}}, - {0x00ab9c, {[CaseLower] = 0x00ab9c,[CaseTitle] = 0x0013cc,[CaseUpper] = 0x0013cc}}, - {0x00ab9d, {[CaseLower] = 0x00ab9d,[CaseTitle] = 0x0013cd,[CaseUpper] = 0x0013cd}}, - {0x00ab9e, {[CaseLower] = 0x00ab9e,[CaseTitle] = 0x0013ce,[CaseUpper] = 0x0013ce}}, - {0x00ab9f, {[CaseLower] = 0x00ab9f,[CaseTitle] = 0x0013cf,[CaseUpper] = 0x0013cf}}, - {0x00aba0, {[CaseLower] = 0x00aba0,[CaseTitle] = 0x0013d0,[CaseUpper] = 0x0013d0}}, - {0x00aba1, {[CaseLower] = 0x00aba1,[CaseTitle] = 0x0013d1,[CaseUpper] = 0x0013d1}}, - {0x00aba2, {[CaseLower] = 0x00aba2,[CaseTitle] = 0x0013d2,[CaseUpper] = 0x0013d2}}, - {0x00aba3, {[CaseLower] = 0x00aba3,[CaseTitle] = 0x0013d3,[CaseUpper] = 0x0013d3}}, - {0x00aba4, {[CaseLower] = 0x00aba4,[CaseTitle] = 0x0013d4,[CaseUpper] = 0x0013d4}}, - {0x00aba5, {[CaseLower] = 0x00aba5,[CaseTitle] = 0x0013d5,[CaseUpper] = 0x0013d5}}, - {0x00aba6, {[CaseLower] = 0x00aba6,[CaseTitle] = 0x0013d6,[CaseUpper] = 0x0013d6}}, - {0x00aba7, {[CaseLower] = 0x00aba7,[CaseTitle] = 0x0013d7,[CaseUpper] = 0x0013d7}}, - {0x00aba8, {[CaseLower] = 0x00aba8,[CaseTitle] = 0x0013d8,[CaseUpper] = 0x0013d8}}, - {0x00aba9, {[CaseLower] = 0x00aba9,[CaseTitle] = 0x0013d9,[CaseUpper] = 0x0013d9}}, - {0x00abaa, {[CaseLower] = 0x00abaa,[CaseTitle] = 0x0013da,[CaseUpper] = 0x0013da}}, - {0x00abab, {[CaseLower] = 0x00abab,[CaseTitle] = 0x0013db,[CaseUpper] = 0x0013db}}, - {0x00abac, {[CaseLower] = 0x00abac,[CaseTitle] = 0x0013dc,[CaseUpper] = 0x0013dc}}, - {0x00abad, {[CaseLower] = 0x00abad,[CaseTitle] = 0x0013dd,[CaseUpper] = 0x0013dd}}, - {0x00abae, {[CaseLower] = 0x00abae,[CaseTitle] = 0x0013de,[CaseUpper] = 0x0013de}}, - {0x00abaf, {[CaseLower] = 0x00abaf,[CaseTitle] = 0x0013df,[CaseUpper] = 0x0013df}}, - {0x00abb0, {[CaseLower] = 0x00abb0,[CaseTitle] = 0x0013e0,[CaseUpper] = 0x0013e0}}, - {0x00abb1, {[CaseLower] = 0x00abb1,[CaseTitle] = 0x0013e1,[CaseUpper] = 0x0013e1}}, - {0x00abb2, {[CaseLower] = 0x00abb2,[CaseTitle] = 0x0013e2,[CaseUpper] = 0x0013e2}}, - {0x00abb3, {[CaseLower] = 0x00abb3,[CaseTitle] = 0x0013e3,[CaseUpper] = 0x0013e3}}, - {0x00abb4, {[CaseLower] = 0x00abb4,[CaseTitle] = 0x0013e4,[CaseUpper] = 0x0013e4}}, - {0x00abb5, {[CaseLower] = 0x00abb5,[CaseTitle] = 0x0013e5,[CaseUpper] = 0x0013e5}}, - {0x00abb6, {[CaseLower] = 0x00abb6,[CaseTitle] = 0x0013e6,[CaseUpper] = 0x0013e6}}, - {0x00abb7, {[CaseLower] = 0x00abb7,[CaseTitle] = 0x0013e7,[CaseUpper] = 0x0013e7}}, - {0x00abb8, {[CaseLower] = 0x00abb8,[CaseTitle] = 0x0013e8,[CaseUpper] = 0x0013e8}}, - {0x00abb9, {[CaseLower] = 0x00abb9,[CaseTitle] = 0x0013e9,[CaseUpper] = 0x0013e9}}, - {0x00abba, {[CaseLower] = 0x00abba,[CaseTitle] = 0x0013ea,[CaseUpper] = 0x0013ea}}, - {0x00abbb, {[CaseLower] = 0x00abbb,[CaseTitle] = 0x0013eb,[CaseUpper] = 0x0013eb}}, - {0x00abbc, {[CaseLower] = 0x00abbc,[CaseTitle] = 0x0013ec,[CaseUpper] = 0x0013ec}}, - {0x00abbd, {[CaseLower] = 0x00abbd,[CaseTitle] = 0x0013ed,[CaseUpper] = 0x0013ed}}, - {0x00abbe, {[CaseLower] = 0x00abbe,[CaseTitle] = 0x0013ee,[CaseUpper] = 0x0013ee}}, - {0x00abbf, {[CaseLower] = 0x00abbf,[CaseTitle] = 0x0013ef,[CaseUpper] = 0x0013ef}}, - {0x00ff21, {[CaseLower] = 0x00ff41,[CaseTitle] = 0x00ff21,[CaseUpper] = 0x00ff21}}, - {0x00ff22, {[CaseLower] = 0x00ff42,[CaseTitle] = 0x00ff22,[CaseUpper] = 0x00ff22}}, - {0x00ff23, {[CaseLower] = 0x00ff43,[CaseTitle] = 0x00ff23,[CaseUpper] = 0x00ff23}}, - {0x00ff24, {[CaseLower] = 0x00ff44,[CaseTitle] = 0x00ff24,[CaseUpper] = 0x00ff24}}, - {0x00ff25, {[CaseLower] = 0x00ff45,[CaseTitle] = 0x00ff25,[CaseUpper] = 0x00ff25}}, - {0x00ff26, {[CaseLower] = 0x00ff46,[CaseTitle] = 0x00ff26,[CaseUpper] = 0x00ff26}}, - {0x00ff27, {[CaseLower] = 0x00ff47,[CaseTitle] = 0x00ff27,[CaseUpper] = 0x00ff27}}, - {0x00ff28, {[CaseLower] = 0x00ff48,[CaseTitle] = 0x00ff28,[CaseUpper] = 0x00ff28}}, - {0x00ff29, {[CaseLower] = 0x00ff49,[CaseTitle] = 0x00ff29,[CaseUpper] = 0x00ff29}}, - {0x00ff2a, {[CaseLower] = 0x00ff4a,[CaseTitle] = 0x00ff2a,[CaseUpper] = 0x00ff2a}}, - {0x00ff2b, {[CaseLower] = 0x00ff4b,[CaseTitle] = 0x00ff2b,[CaseUpper] = 0x00ff2b}}, - {0x00ff2c, {[CaseLower] = 0x00ff4c,[CaseTitle] = 0x00ff2c,[CaseUpper] = 0x00ff2c}}, - {0x00ff2d, {[CaseLower] = 0x00ff4d,[CaseTitle] = 0x00ff2d,[CaseUpper] = 0x00ff2d}}, - {0x00ff2e, {[CaseLower] = 0x00ff4e,[CaseTitle] = 0x00ff2e,[CaseUpper] = 0x00ff2e}}, - {0x00ff2f, {[CaseLower] = 0x00ff4f,[CaseTitle] = 0x00ff2f,[CaseUpper] = 0x00ff2f}}, - {0x00ff30, {[CaseLower] = 0x00ff50,[CaseTitle] = 0x00ff30,[CaseUpper] = 0x00ff30}}, - {0x00ff31, {[CaseLower] = 0x00ff51,[CaseTitle] = 0x00ff31,[CaseUpper] = 0x00ff31}}, - {0x00ff32, {[CaseLower] = 0x00ff52,[CaseTitle] = 0x00ff32,[CaseUpper] = 0x00ff32}}, - {0x00ff33, {[CaseLower] = 0x00ff53,[CaseTitle] = 0x00ff33,[CaseUpper] = 0x00ff33}}, - {0x00ff34, {[CaseLower] = 0x00ff54,[CaseTitle] = 0x00ff34,[CaseUpper] = 0x00ff34}}, - {0x00ff35, {[CaseLower] = 0x00ff55,[CaseTitle] = 0x00ff35,[CaseUpper] = 0x00ff35}}, - {0x00ff36, {[CaseLower] = 0x00ff56,[CaseTitle] = 0x00ff36,[CaseUpper] = 0x00ff36}}, - {0x00ff37, {[CaseLower] = 0x00ff57,[CaseTitle] = 0x00ff37,[CaseUpper] = 0x00ff37}}, - {0x00ff38, {[CaseLower] = 0x00ff58,[CaseTitle] = 0x00ff38,[CaseUpper] = 0x00ff38}}, - {0x00ff39, {[CaseLower] = 0x00ff59,[CaseTitle] = 0x00ff39,[CaseUpper] = 0x00ff39}}, - {0x00ff3a, {[CaseLower] = 0x00ff5a,[CaseTitle] = 0x00ff3a,[CaseUpper] = 0x00ff3a}}, - {0x00ff41, {[CaseLower] = 0x00ff41,[CaseTitle] = 0x00ff21,[CaseUpper] = 0x00ff21}}, - {0x00ff42, {[CaseLower] = 0x00ff42,[CaseTitle] = 0x00ff22,[CaseUpper] = 0x00ff22}}, - {0x00ff43, {[CaseLower] = 0x00ff43,[CaseTitle] = 0x00ff23,[CaseUpper] = 0x00ff23}}, - {0x00ff44, {[CaseLower] = 0x00ff44,[CaseTitle] = 0x00ff24,[CaseUpper] = 0x00ff24}}, - {0x00ff45, {[CaseLower] = 0x00ff45,[CaseTitle] = 0x00ff25,[CaseUpper] = 0x00ff25}}, - {0x00ff46, {[CaseLower] = 0x00ff46,[CaseTitle] = 0x00ff26,[CaseUpper] = 0x00ff26}}, - {0x00ff47, {[CaseLower] = 0x00ff47,[CaseTitle] = 0x00ff27,[CaseUpper] = 0x00ff27}}, - {0x00ff48, {[CaseLower] = 0x00ff48,[CaseTitle] = 0x00ff28,[CaseUpper] = 0x00ff28}}, - {0x00ff49, {[CaseLower] = 0x00ff49,[CaseTitle] = 0x00ff29,[CaseUpper] = 0x00ff29}}, - {0x00ff4a, {[CaseLower] = 0x00ff4a,[CaseTitle] = 0x00ff2a,[CaseUpper] = 0x00ff2a}}, - {0x00ff4b, {[CaseLower] = 0x00ff4b,[CaseTitle] = 0x00ff2b,[CaseUpper] = 0x00ff2b}}, - {0x00ff4c, {[CaseLower] = 0x00ff4c,[CaseTitle] = 0x00ff2c,[CaseUpper] = 0x00ff2c}}, - {0x00ff4d, {[CaseLower] = 0x00ff4d,[CaseTitle] = 0x00ff2d,[CaseUpper] = 0x00ff2d}}, - {0x00ff4e, {[CaseLower] = 0x00ff4e,[CaseTitle] = 0x00ff2e,[CaseUpper] = 0x00ff2e}}, - {0x00ff4f, {[CaseLower] = 0x00ff4f,[CaseTitle] = 0x00ff2f,[CaseUpper] = 0x00ff2f}}, - {0x00ff50, {[CaseLower] = 0x00ff50,[CaseTitle] = 0x00ff30,[CaseUpper] = 0x00ff30}}, - {0x00ff51, {[CaseLower] = 0x00ff51,[CaseTitle] = 0x00ff31,[CaseUpper] = 0x00ff31}}, - {0x00ff52, {[CaseLower] = 0x00ff52,[CaseTitle] = 0x00ff32,[CaseUpper] = 0x00ff32}}, - {0x00ff53, {[CaseLower] = 0x00ff53,[CaseTitle] = 0x00ff33,[CaseUpper] = 0x00ff33}}, - {0x00ff54, {[CaseLower] = 0x00ff54,[CaseTitle] = 0x00ff34,[CaseUpper] = 0x00ff34}}, - {0x00ff55, {[CaseLower] = 0x00ff55,[CaseTitle] = 0x00ff35,[CaseUpper] = 0x00ff35}}, - {0x00ff56, {[CaseLower] = 0x00ff56,[CaseTitle] = 0x00ff36,[CaseUpper] = 0x00ff36}}, - {0x00ff57, {[CaseLower] = 0x00ff57,[CaseTitle] = 0x00ff37,[CaseUpper] = 0x00ff37}}, - {0x00ff58, {[CaseLower] = 0x00ff58,[CaseTitle] = 0x00ff38,[CaseUpper] = 0x00ff38}}, - {0x00ff59, {[CaseLower] = 0x00ff59,[CaseTitle] = 0x00ff39,[CaseUpper] = 0x00ff39}}, - {0x00ff5a, {[CaseLower] = 0x00ff5a,[CaseTitle] = 0x00ff3a,[CaseUpper] = 0x00ff3a}}, - {0x010400, {[CaseLower] = 0x010428,[CaseTitle] = 0x010400,[CaseUpper] = 0x010400}}, - {0x010401, {[CaseLower] = 0x010429,[CaseTitle] = 0x010401,[CaseUpper] = 0x010401}}, - {0x010402, {[CaseLower] = 0x01042a,[CaseTitle] = 0x010402,[CaseUpper] = 0x010402}}, - {0x010403, {[CaseLower] = 0x01042b,[CaseTitle] = 0x010403,[CaseUpper] = 0x010403}}, - {0x010404, {[CaseLower] = 0x01042c,[CaseTitle] = 0x010404,[CaseUpper] = 0x010404}}, - {0x010405, {[CaseLower] = 0x01042d,[CaseTitle] = 0x010405,[CaseUpper] = 0x010405}}, - {0x010406, {[CaseLower] = 0x01042e,[CaseTitle] = 0x010406,[CaseUpper] = 0x010406}}, - {0x010407, {[CaseLower] = 0x01042f,[CaseTitle] = 0x010407,[CaseUpper] = 0x010407}}, - {0x010408, {[CaseLower] = 0x010430,[CaseTitle] = 0x010408,[CaseUpper] = 0x010408}}, - {0x010409, {[CaseLower] = 0x010431,[CaseTitle] = 0x010409,[CaseUpper] = 0x010409}}, - {0x01040a, {[CaseLower] = 0x010432,[CaseTitle] = 0x01040a,[CaseUpper] = 0x01040a}}, - {0x01040b, {[CaseLower] = 0x010433,[CaseTitle] = 0x01040b,[CaseUpper] = 0x01040b}}, - {0x01040c, {[CaseLower] = 0x010434,[CaseTitle] = 0x01040c,[CaseUpper] = 0x01040c}}, - {0x01040d, {[CaseLower] = 0x010435,[CaseTitle] = 0x01040d,[CaseUpper] = 0x01040d}}, - {0x01040e, {[CaseLower] = 0x010436,[CaseTitle] = 0x01040e,[CaseUpper] = 0x01040e}}, - {0x01040f, {[CaseLower] = 0x010437,[CaseTitle] = 0x01040f,[CaseUpper] = 0x01040f}}, - {0x010410, {[CaseLower] = 0x010438,[CaseTitle] = 0x010410,[CaseUpper] = 0x010410}}, - {0x010411, {[CaseLower] = 0x010439,[CaseTitle] = 0x010411,[CaseUpper] = 0x010411}}, - {0x010412, {[CaseLower] = 0x01043a,[CaseTitle] = 0x010412,[CaseUpper] = 0x010412}}, - {0x010413, {[CaseLower] = 0x01043b,[CaseTitle] = 0x010413,[CaseUpper] = 0x010413}}, - {0x010414, {[CaseLower] = 0x01043c,[CaseTitle] = 0x010414,[CaseUpper] = 0x010414}}, - {0x010415, {[CaseLower] = 0x01043d,[CaseTitle] = 0x010415,[CaseUpper] = 0x010415}}, - {0x010416, {[CaseLower] = 0x01043e,[CaseTitle] = 0x010416,[CaseUpper] = 0x010416}}, - {0x010417, {[CaseLower] = 0x01043f,[CaseTitle] = 0x010417,[CaseUpper] = 0x010417}}, - {0x010418, {[CaseLower] = 0x010440,[CaseTitle] = 0x010418,[CaseUpper] = 0x010418}}, - {0x010419, {[CaseLower] = 0x010441,[CaseTitle] = 0x010419,[CaseUpper] = 0x010419}}, - {0x01041a, {[CaseLower] = 0x010442,[CaseTitle] = 0x01041a,[CaseUpper] = 0x01041a}}, - {0x01041b, {[CaseLower] = 0x010443,[CaseTitle] = 0x01041b,[CaseUpper] = 0x01041b}}, - {0x01041c, {[CaseLower] = 0x010444,[CaseTitle] = 0x01041c,[CaseUpper] = 0x01041c}}, - {0x01041d, {[CaseLower] = 0x010445,[CaseTitle] = 0x01041d,[CaseUpper] = 0x01041d}}, - {0x01041e, {[CaseLower] = 0x010446,[CaseTitle] = 0x01041e,[CaseUpper] = 0x01041e}}, - {0x01041f, {[CaseLower] = 0x010447,[CaseTitle] = 0x01041f,[CaseUpper] = 0x01041f}}, - {0x010420, {[CaseLower] = 0x010448,[CaseTitle] = 0x010420,[CaseUpper] = 0x010420}}, - {0x010421, {[CaseLower] = 0x010449,[CaseTitle] = 0x010421,[CaseUpper] = 0x010421}}, - {0x010422, {[CaseLower] = 0x01044a,[CaseTitle] = 0x010422,[CaseUpper] = 0x010422}}, - {0x010423, {[CaseLower] = 0x01044b,[CaseTitle] = 0x010423,[CaseUpper] = 0x010423}}, - {0x010424, {[CaseLower] = 0x01044c,[CaseTitle] = 0x010424,[CaseUpper] = 0x010424}}, - {0x010425, {[CaseLower] = 0x01044d,[CaseTitle] = 0x010425,[CaseUpper] = 0x010425}}, - {0x010426, {[CaseLower] = 0x01044e,[CaseTitle] = 0x010426,[CaseUpper] = 0x010426}}, - {0x010427, {[CaseLower] = 0x01044f,[CaseTitle] = 0x010427,[CaseUpper] = 0x010427}}, - {0x010428, {[CaseLower] = 0x010428,[CaseTitle] = 0x010400,[CaseUpper] = 0x010400}}, - {0x010429, {[CaseLower] = 0x010429,[CaseTitle] = 0x010401,[CaseUpper] = 0x010401}}, - {0x01042a, {[CaseLower] = 0x01042a,[CaseTitle] = 0x010402,[CaseUpper] = 0x010402}}, - {0x01042b, {[CaseLower] = 0x01042b,[CaseTitle] = 0x010403,[CaseUpper] = 0x010403}}, - {0x01042c, {[CaseLower] = 0x01042c,[CaseTitle] = 0x010404,[CaseUpper] = 0x010404}}, - {0x01042d, {[CaseLower] = 0x01042d,[CaseTitle] = 0x010405,[CaseUpper] = 0x010405}}, - {0x01042e, {[CaseLower] = 0x01042e,[CaseTitle] = 0x010406,[CaseUpper] = 0x010406}}, - {0x01042f, {[CaseLower] = 0x01042f,[CaseTitle] = 0x010407,[CaseUpper] = 0x010407}}, - {0x010430, {[CaseLower] = 0x010430,[CaseTitle] = 0x010408,[CaseUpper] = 0x010408}}, - {0x010431, {[CaseLower] = 0x010431,[CaseTitle] = 0x010409,[CaseUpper] = 0x010409}}, - {0x010432, {[CaseLower] = 0x010432,[CaseTitle] = 0x01040a,[CaseUpper] = 0x01040a}}, - {0x010433, {[CaseLower] = 0x010433,[CaseTitle] = 0x01040b,[CaseUpper] = 0x01040b}}, - {0x010434, {[CaseLower] = 0x010434,[CaseTitle] = 0x01040c,[CaseUpper] = 0x01040c}}, - {0x010435, {[CaseLower] = 0x010435,[CaseTitle] = 0x01040d,[CaseUpper] = 0x01040d}}, - {0x010436, {[CaseLower] = 0x010436,[CaseTitle] = 0x01040e,[CaseUpper] = 0x01040e}}, - {0x010437, {[CaseLower] = 0x010437,[CaseTitle] = 0x01040f,[CaseUpper] = 0x01040f}}, - {0x010438, {[CaseLower] = 0x010438,[CaseTitle] = 0x010410,[CaseUpper] = 0x010410}}, - {0x010439, {[CaseLower] = 0x010439,[CaseTitle] = 0x010411,[CaseUpper] = 0x010411}}, - {0x01043a, {[CaseLower] = 0x01043a,[CaseTitle] = 0x010412,[CaseUpper] = 0x010412}}, - {0x01043b, {[CaseLower] = 0x01043b,[CaseTitle] = 0x010413,[CaseUpper] = 0x010413}}, - {0x01043c, {[CaseLower] = 0x01043c,[CaseTitle] = 0x010414,[CaseUpper] = 0x010414}}, - {0x01043d, {[CaseLower] = 0x01043d,[CaseTitle] = 0x010415,[CaseUpper] = 0x010415}}, - {0x01043e, {[CaseLower] = 0x01043e,[CaseTitle] = 0x010416,[CaseUpper] = 0x010416}}, - {0x01043f, {[CaseLower] = 0x01043f,[CaseTitle] = 0x010417,[CaseUpper] = 0x010417}}, - {0x010440, {[CaseLower] = 0x010440,[CaseTitle] = 0x010418,[CaseUpper] = 0x010418}}, - {0x010441, {[CaseLower] = 0x010441,[CaseTitle] = 0x010419,[CaseUpper] = 0x010419}}, - {0x010442, {[CaseLower] = 0x010442,[CaseTitle] = 0x01041a,[CaseUpper] = 0x01041a}}, - {0x010443, {[CaseLower] = 0x010443,[CaseTitle] = 0x01041b,[CaseUpper] = 0x01041b}}, - {0x010444, {[CaseLower] = 0x010444,[CaseTitle] = 0x01041c,[CaseUpper] = 0x01041c}}, - {0x010445, {[CaseLower] = 0x010445,[CaseTitle] = 0x01041d,[CaseUpper] = 0x01041d}}, - {0x010446, {[CaseLower] = 0x010446,[CaseTitle] = 0x01041e,[CaseUpper] = 0x01041e}}, - {0x010447, {[CaseLower] = 0x010447,[CaseTitle] = 0x01041f,[CaseUpper] = 0x01041f}}, - {0x010448, {[CaseLower] = 0x010448,[CaseTitle] = 0x010420,[CaseUpper] = 0x010420}}, - {0x010449, {[CaseLower] = 0x010449,[CaseTitle] = 0x010421,[CaseUpper] = 0x010421}}, - {0x01044a, {[CaseLower] = 0x01044a,[CaseTitle] = 0x010422,[CaseUpper] = 0x010422}}, - {0x01044b, {[CaseLower] = 0x01044b,[CaseTitle] = 0x010423,[CaseUpper] = 0x010423}}, - {0x01044c, {[CaseLower] = 0x01044c,[CaseTitle] = 0x010424,[CaseUpper] = 0x010424}}, - {0x01044d, {[CaseLower] = 0x01044d,[CaseTitle] = 0x010425,[CaseUpper] = 0x010425}}, - {0x01044e, {[CaseLower] = 0x01044e,[CaseTitle] = 0x010426,[CaseUpper] = 0x010426}}, - {0x01044f, {[CaseLower] = 0x01044f,[CaseTitle] = 0x010427,[CaseUpper] = 0x010427}}, - {0x0104b0, {[CaseLower] = 0x0104d8,[CaseTitle] = 0x0104b0,[CaseUpper] = 0x0104b0}}, - {0x0104b1, {[CaseLower] = 0x0104d9,[CaseTitle] = 0x0104b1,[CaseUpper] = 0x0104b1}}, - {0x0104b2, {[CaseLower] = 0x0104da,[CaseTitle] = 0x0104b2,[CaseUpper] = 0x0104b2}}, - {0x0104b3, {[CaseLower] = 0x0104db,[CaseTitle] = 0x0104b3,[CaseUpper] = 0x0104b3}}, - {0x0104b4, {[CaseLower] = 0x0104dc,[CaseTitle] = 0x0104b4,[CaseUpper] = 0x0104b4}}, - {0x0104b5, {[CaseLower] = 0x0104dd,[CaseTitle] = 0x0104b5,[CaseUpper] = 0x0104b5}}, - {0x0104b6, {[CaseLower] = 0x0104de,[CaseTitle] = 0x0104b6,[CaseUpper] = 0x0104b6}}, - {0x0104b7, {[CaseLower] = 0x0104df,[CaseTitle] = 0x0104b7,[CaseUpper] = 0x0104b7}}, - {0x0104b8, {[CaseLower] = 0x0104e0,[CaseTitle] = 0x0104b8,[CaseUpper] = 0x0104b8}}, - {0x0104b9, {[CaseLower] = 0x0104e1,[CaseTitle] = 0x0104b9,[CaseUpper] = 0x0104b9}}, - {0x0104ba, {[CaseLower] = 0x0104e2,[CaseTitle] = 0x0104ba,[CaseUpper] = 0x0104ba}}, - {0x0104bb, {[CaseLower] = 0x0104e3,[CaseTitle] = 0x0104bb,[CaseUpper] = 0x0104bb}}, - {0x0104bc, {[CaseLower] = 0x0104e4,[CaseTitle] = 0x0104bc,[CaseUpper] = 0x0104bc}}, - {0x0104bd, {[CaseLower] = 0x0104e5,[CaseTitle] = 0x0104bd,[CaseUpper] = 0x0104bd}}, - {0x0104be, {[CaseLower] = 0x0104e6,[CaseTitle] = 0x0104be,[CaseUpper] = 0x0104be}}, - {0x0104bf, {[CaseLower] = 0x0104e7,[CaseTitle] = 0x0104bf,[CaseUpper] = 0x0104bf}}, - {0x0104c0, {[CaseLower] = 0x0104e8,[CaseTitle] = 0x0104c0,[CaseUpper] = 0x0104c0}}, - {0x0104c1, {[CaseLower] = 0x0104e9,[CaseTitle] = 0x0104c1,[CaseUpper] = 0x0104c1}}, - {0x0104c2, {[CaseLower] = 0x0104ea,[CaseTitle] = 0x0104c2,[CaseUpper] = 0x0104c2}}, - {0x0104c3, {[CaseLower] = 0x0104eb,[CaseTitle] = 0x0104c3,[CaseUpper] = 0x0104c3}}, - {0x0104c4, {[CaseLower] = 0x0104ec,[CaseTitle] = 0x0104c4,[CaseUpper] = 0x0104c4}}, - {0x0104c5, {[CaseLower] = 0x0104ed,[CaseTitle] = 0x0104c5,[CaseUpper] = 0x0104c5}}, - {0x0104c6, {[CaseLower] = 0x0104ee,[CaseTitle] = 0x0104c6,[CaseUpper] = 0x0104c6}}, - {0x0104c7, {[CaseLower] = 0x0104ef,[CaseTitle] = 0x0104c7,[CaseUpper] = 0x0104c7}}, - {0x0104c8, {[CaseLower] = 0x0104f0,[CaseTitle] = 0x0104c8,[CaseUpper] = 0x0104c8}}, - {0x0104c9, {[CaseLower] = 0x0104f1,[CaseTitle] = 0x0104c9,[CaseUpper] = 0x0104c9}}, - {0x0104ca, {[CaseLower] = 0x0104f2,[CaseTitle] = 0x0104ca,[CaseUpper] = 0x0104ca}}, - {0x0104cb, {[CaseLower] = 0x0104f3,[CaseTitle] = 0x0104cb,[CaseUpper] = 0x0104cb}}, - {0x0104cc, {[CaseLower] = 0x0104f4,[CaseTitle] = 0x0104cc,[CaseUpper] = 0x0104cc}}, - {0x0104cd, {[CaseLower] = 0x0104f5,[CaseTitle] = 0x0104cd,[CaseUpper] = 0x0104cd}}, - {0x0104ce, {[CaseLower] = 0x0104f6,[CaseTitle] = 0x0104ce,[CaseUpper] = 0x0104ce}}, - {0x0104cf, {[CaseLower] = 0x0104f7,[CaseTitle] = 0x0104cf,[CaseUpper] = 0x0104cf}}, - {0x0104d0, {[CaseLower] = 0x0104f8,[CaseTitle] = 0x0104d0,[CaseUpper] = 0x0104d0}}, - {0x0104d1, {[CaseLower] = 0x0104f9,[CaseTitle] = 0x0104d1,[CaseUpper] = 0x0104d1}}, - {0x0104d2, {[CaseLower] = 0x0104fa,[CaseTitle] = 0x0104d2,[CaseUpper] = 0x0104d2}}, - {0x0104d3, {[CaseLower] = 0x0104fb,[CaseTitle] = 0x0104d3,[CaseUpper] = 0x0104d3}}, - {0x0104d8, {[CaseLower] = 0x0104d8,[CaseTitle] = 0x0104b0,[CaseUpper] = 0x0104b0}}, - {0x0104d9, {[CaseLower] = 0x0104d9,[CaseTitle] = 0x0104b1,[CaseUpper] = 0x0104b1}}, - {0x0104da, {[CaseLower] = 0x0104da,[CaseTitle] = 0x0104b2,[CaseUpper] = 0x0104b2}}, - {0x0104db, {[CaseLower] = 0x0104db,[CaseTitle] = 0x0104b3,[CaseUpper] = 0x0104b3}}, - {0x0104dc, {[CaseLower] = 0x0104dc,[CaseTitle] = 0x0104b4,[CaseUpper] = 0x0104b4}}, - {0x0104dd, {[CaseLower] = 0x0104dd,[CaseTitle] = 0x0104b5,[CaseUpper] = 0x0104b5}}, - {0x0104de, {[CaseLower] = 0x0104de,[CaseTitle] = 0x0104b6,[CaseUpper] = 0x0104b6}}, - {0x0104df, {[CaseLower] = 0x0104df,[CaseTitle] = 0x0104b7,[CaseUpper] = 0x0104b7}}, - {0x0104e0, {[CaseLower] = 0x0104e0,[CaseTitle] = 0x0104b8,[CaseUpper] = 0x0104b8}}, - {0x0104e1, {[CaseLower] = 0x0104e1,[CaseTitle] = 0x0104b9,[CaseUpper] = 0x0104b9}}, - {0x0104e2, {[CaseLower] = 0x0104e2,[CaseTitle] = 0x0104ba,[CaseUpper] = 0x0104ba}}, - {0x0104e3, {[CaseLower] = 0x0104e3,[CaseTitle] = 0x0104bb,[CaseUpper] = 0x0104bb}}, - {0x0104e4, {[CaseLower] = 0x0104e4,[CaseTitle] = 0x0104bc,[CaseUpper] = 0x0104bc}}, - {0x0104e5, {[CaseLower] = 0x0104e5,[CaseTitle] = 0x0104bd,[CaseUpper] = 0x0104bd}}, - {0x0104e6, {[CaseLower] = 0x0104e6,[CaseTitle] = 0x0104be,[CaseUpper] = 0x0104be}}, - {0x0104e7, {[CaseLower] = 0x0104e7,[CaseTitle] = 0x0104bf,[CaseUpper] = 0x0104bf}}, - {0x0104e8, {[CaseLower] = 0x0104e8,[CaseTitle] = 0x0104c0,[CaseUpper] = 0x0104c0}}, - {0x0104e9, {[CaseLower] = 0x0104e9,[CaseTitle] = 0x0104c1,[CaseUpper] = 0x0104c1}}, - {0x0104ea, {[CaseLower] = 0x0104ea,[CaseTitle] = 0x0104c2,[CaseUpper] = 0x0104c2}}, - {0x0104eb, {[CaseLower] = 0x0104eb,[CaseTitle] = 0x0104c3,[CaseUpper] = 0x0104c3}}, - {0x0104ec, {[CaseLower] = 0x0104ec,[CaseTitle] = 0x0104c4,[CaseUpper] = 0x0104c4}}, - {0x0104ed, {[CaseLower] = 0x0104ed,[CaseTitle] = 0x0104c5,[CaseUpper] = 0x0104c5}}, - {0x0104ee, {[CaseLower] = 0x0104ee,[CaseTitle] = 0x0104c6,[CaseUpper] = 0x0104c6}}, - {0x0104ef, {[CaseLower] = 0x0104ef,[CaseTitle] = 0x0104c7,[CaseUpper] = 0x0104c7}}, - {0x0104f0, {[CaseLower] = 0x0104f0,[CaseTitle] = 0x0104c8,[CaseUpper] = 0x0104c8}}, - {0x0104f1, {[CaseLower] = 0x0104f1,[CaseTitle] = 0x0104c9,[CaseUpper] = 0x0104c9}}, - {0x0104f2, {[CaseLower] = 0x0104f2,[CaseTitle] = 0x0104ca,[CaseUpper] = 0x0104ca}}, - {0x0104f3, {[CaseLower] = 0x0104f3,[CaseTitle] = 0x0104cb,[CaseUpper] = 0x0104cb}}, - {0x0104f4, {[CaseLower] = 0x0104f4,[CaseTitle] = 0x0104cc,[CaseUpper] = 0x0104cc}}, - {0x0104f5, {[CaseLower] = 0x0104f5,[CaseTitle] = 0x0104cd,[CaseUpper] = 0x0104cd}}, - {0x0104f6, {[CaseLower] = 0x0104f6,[CaseTitle] = 0x0104ce,[CaseUpper] = 0x0104ce}}, - {0x0104f7, {[CaseLower] = 0x0104f7,[CaseTitle] = 0x0104cf,[CaseUpper] = 0x0104cf}}, - {0x0104f8, {[CaseLower] = 0x0104f8,[CaseTitle] = 0x0104d0,[CaseUpper] = 0x0104d0}}, - {0x0104f9, {[CaseLower] = 0x0104f9,[CaseTitle] = 0x0104d1,[CaseUpper] = 0x0104d1}}, - {0x0104fa, {[CaseLower] = 0x0104fa,[CaseTitle] = 0x0104d2,[CaseUpper] = 0x0104d2}}, - {0x0104fb, {[CaseLower] = 0x0104fb,[CaseTitle] = 0x0104d3,[CaseUpper] = 0x0104d3}}, - {0x010570, {[CaseLower] = 0x010597,[CaseTitle] = 0x010570,[CaseUpper] = 0x010570}}, - {0x010571, {[CaseLower] = 0x010598,[CaseTitle] = 0x010571,[CaseUpper] = 0x010571}}, - {0x010572, {[CaseLower] = 0x010599,[CaseTitle] = 0x010572,[CaseUpper] = 0x010572}}, - {0x010573, {[CaseLower] = 0x01059a,[CaseTitle] = 0x010573,[CaseUpper] = 0x010573}}, - {0x010574, {[CaseLower] = 0x01059b,[CaseTitle] = 0x010574,[CaseUpper] = 0x010574}}, - {0x010575, {[CaseLower] = 0x01059c,[CaseTitle] = 0x010575,[CaseUpper] = 0x010575}}, - {0x010576, {[CaseLower] = 0x01059d,[CaseTitle] = 0x010576,[CaseUpper] = 0x010576}}, - {0x010577, {[CaseLower] = 0x01059e,[CaseTitle] = 0x010577,[CaseUpper] = 0x010577}}, - {0x010578, {[CaseLower] = 0x01059f,[CaseTitle] = 0x010578,[CaseUpper] = 0x010578}}, - {0x010579, {[CaseLower] = 0x0105a0,[CaseTitle] = 0x010579,[CaseUpper] = 0x010579}}, - {0x01057a, {[CaseLower] = 0x0105a1,[CaseTitle] = 0x01057a,[CaseUpper] = 0x01057a}}, - {0x01057c, {[CaseLower] = 0x0105a3,[CaseTitle] = 0x01057c,[CaseUpper] = 0x01057c}}, - {0x01057d, {[CaseLower] = 0x0105a4,[CaseTitle] = 0x01057d,[CaseUpper] = 0x01057d}}, - {0x01057e, {[CaseLower] = 0x0105a5,[CaseTitle] = 0x01057e,[CaseUpper] = 0x01057e}}, - {0x01057f, {[CaseLower] = 0x0105a6,[CaseTitle] = 0x01057f,[CaseUpper] = 0x01057f}}, - {0x010580, {[CaseLower] = 0x0105a7,[CaseTitle] = 0x010580,[CaseUpper] = 0x010580}}, - {0x010581, {[CaseLower] = 0x0105a8,[CaseTitle] = 0x010581,[CaseUpper] = 0x010581}}, - {0x010582, {[CaseLower] = 0x0105a9,[CaseTitle] = 0x010582,[CaseUpper] = 0x010582}}, - {0x010583, {[CaseLower] = 0x0105aa,[CaseTitle] = 0x010583,[CaseUpper] = 0x010583}}, - {0x010584, {[CaseLower] = 0x0105ab,[CaseTitle] = 0x010584,[CaseUpper] = 0x010584}}, - {0x010585, {[CaseLower] = 0x0105ac,[CaseTitle] = 0x010585,[CaseUpper] = 0x010585}}, - {0x010586, {[CaseLower] = 0x0105ad,[CaseTitle] = 0x010586,[CaseUpper] = 0x010586}}, - {0x010587, {[CaseLower] = 0x0105ae,[CaseTitle] = 0x010587,[CaseUpper] = 0x010587}}, - {0x010588, {[CaseLower] = 0x0105af,[CaseTitle] = 0x010588,[CaseUpper] = 0x010588}}, - {0x010589, {[CaseLower] = 0x0105b0,[CaseTitle] = 0x010589,[CaseUpper] = 0x010589}}, - {0x01058a, {[CaseLower] = 0x0105b1,[CaseTitle] = 0x01058a,[CaseUpper] = 0x01058a}}, - {0x01058c, {[CaseLower] = 0x0105b3,[CaseTitle] = 0x01058c,[CaseUpper] = 0x01058c}}, - {0x01058d, {[CaseLower] = 0x0105b4,[CaseTitle] = 0x01058d,[CaseUpper] = 0x01058d}}, - {0x01058e, {[CaseLower] = 0x0105b5,[CaseTitle] = 0x01058e,[CaseUpper] = 0x01058e}}, - {0x01058f, {[CaseLower] = 0x0105b6,[CaseTitle] = 0x01058f,[CaseUpper] = 0x01058f}}, - {0x010590, {[CaseLower] = 0x0105b7,[CaseTitle] = 0x010590,[CaseUpper] = 0x010590}}, - {0x010591, {[CaseLower] = 0x0105b8,[CaseTitle] = 0x010591,[CaseUpper] = 0x010591}}, - {0x010592, {[CaseLower] = 0x0105b9,[CaseTitle] = 0x010592,[CaseUpper] = 0x010592}}, - {0x010594, {[CaseLower] = 0x0105bb,[CaseTitle] = 0x010594,[CaseUpper] = 0x010594}}, - {0x010595, {[CaseLower] = 0x0105bc,[CaseTitle] = 0x010595,[CaseUpper] = 0x010595}}, - {0x010597, {[CaseLower] = 0x010597,[CaseTitle] = 0x010570,[CaseUpper] = 0x010570}}, - {0x010598, {[CaseLower] = 0x010598,[CaseTitle] = 0x010571,[CaseUpper] = 0x010571}}, - {0x010599, {[CaseLower] = 0x010599,[CaseTitle] = 0x010572,[CaseUpper] = 0x010572}}, - {0x01059a, {[CaseLower] = 0x01059a,[CaseTitle] = 0x010573,[CaseUpper] = 0x010573}}, - {0x01059b, {[CaseLower] = 0x01059b,[CaseTitle] = 0x010574,[CaseUpper] = 0x010574}}, - {0x01059c, {[CaseLower] = 0x01059c,[CaseTitle] = 0x010575,[CaseUpper] = 0x010575}}, - {0x01059d, {[CaseLower] = 0x01059d,[CaseTitle] = 0x010576,[CaseUpper] = 0x010576}}, - {0x01059e, {[CaseLower] = 0x01059e,[CaseTitle] = 0x010577,[CaseUpper] = 0x010577}}, - {0x01059f, {[CaseLower] = 0x01059f,[CaseTitle] = 0x010578,[CaseUpper] = 0x010578}}, - {0x0105a0, {[CaseLower] = 0x0105a0,[CaseTitle] = 0x010579,[CaseUpper] = 0x010579}}, - {0x0105a1, {[CaseLower] = 0x0105a1,[CaseTitle] = 0x01057a,[CaseUpper] = 0x01057a}}, - {0x0105a3, {[CaseLower] = 0x0105a3,[CaseTitle] = 0x01057c,[CaseUpper] = 0x01057c}}, - {0x0105a4, {[CaseLower] = 0x0105a4,[CaseTitle] = 0x01057d,[CaseUpper] = 0x01057d}}, - {0x0105a5, {[CaseLower] = 0x0105a5,[CaseTitle] = 0x01057e,[CaseUpper] = 0x01057e}}, - {0x0105a6, {[CaseLower] = 0x0105a6,[CaseTitle] = 0x01057f,[CaseUpper] = 0x01057f}}, - {0x0105a7, {[CaseLower] = 0x0105a7,[CaseTitle] = 0x010580,[CaseUpper] = 0x010580}}, - {0x0105a8, {[CaseLower] = 0x0105a8,[CaseTitle] = 0x010581,[CaseUpper] = 0x010581}}, - {0x0105a9, {[CaseLower] = 0x0105a9,[CaseTitle] = 0x010582,[CaseUpper] = 0x010582}}, - {0x0105aa, {[CaseLower] = 0x0105aa,[CaseTitle] = 0x010583,[CaseUpper] = 0x010583}}, - {0x0105ab, {[CaseLower] = 0x0105ab,[CaseTitle] = 0x010584,[CaseUpper] = 0x010584}}, - {0x0105ac, {[CaseLower] = 0x0105ac,[CaseTitle] = 0x010585,[CaseUpper] = 0x010585}}, - {0x0105ad, {[CaseLower] = 0x0105ad,[CaseTitle] = 0x010586,[CaseUpper] = 0x010586}}, - {0x0105ae, {[CaseLower] = 0x0105ae,[CaseTitle] = 0x010587,[CaseUpper] = 0x010587}}, - {0x0105af, {[CaseLower] = 0x0105af,[CaseTitle] = 0x010588,[CaseUpper] = 0x010588}}, - {0x0105b0, {[CaseLower] = 0x0105b0,[CaseTitle] = 0x010589,[CaseUpper] = 0x010589}}, - {0x0105b1, {[CaseLower] = 0x0105b1,[CaseTitle] = 0x01058a,[CaseUpper] = 0x01058a}}, - {0x0105b3, {[CaseLower] = 0x0105b3,[CaseTitle] = 0x01058c,[CaseUpper] = 0x01058c}}, - {0x0105b4, {[CaseLower] = 0x0105b4,[CaseTitle] = 0x01058d,[CaseUpper] = 0x01058d}}, - {0x0105b5, {[CaseLower] = 0x0105b5,[CaseTitle] = 0x01058e,[CaseUpper] = 0x01058e}}, - {0x0105b6, {[CaseLower] = 0x0105b6,[CaseTitle] = 0x01058f,[CaseUpper] = 0x01058f}}, - {0x0105b7, {[CaseLower] = 0x0105b7,[CaseTitle] = 0x010590,[CaseUpper] = 0x010590}}, - {0x0105b8, {[CaseLower] = 0x0105b8,[CaseTitle] = 0x010591,[CaseUpper] = 0x010591}}, - {0x0105b9, {[CaseLower] = 0x0105b9,[CaseTitle] = 0x010592,[CaseUpper] = 0x010592}}, - {0x0105bb, {[CaseLower] = 0x0105bb,[CaseTitle] = 0x010594,[CaseUpper] = 0x010594}}, - {0x0105bc, {[CaseLower] = 0x0105bc,[CaseTitle] = 0x010595,[CaseUpper] = 0x010595}}, - {0x010c80, {[CaseLower] = 0x010cc0,[CaseTitle] = 0x010c80,[CaseUpper] = 0x010c80}}, - {0x010c81, {[CaseLower] = 0x010cc1,[CaseTitle] = 0x010c81,[CaseUpper] = 0x010c81}}, - {0x010c82, {[CaseLower] = 0x010cc2,[CaseTitle] = 0x010c82,[CaseUpper] = 0x010c82}}, - {0x010c83, {[CaseLower] = 0x010cc3,[CaseTitle] = 0x010c83,[CaseUpper] = 0x010c83}}, - {0x010c84, {[CaseLower] = 0x010cc4,[CaseTitle] = 0x010c84,[CaseUpper] = 0x010c84}}, - {0x010c85, {[CaseLower] = 0x010cc5,[CaseTitle] = 0x010c85,[CaseUpper] = 0x010c85}}, - {0x010c86, {[CaseLower] = 0x010cc6,[CaseTitle] = 0x010c86,[CaseUpper] = 0x010c86}}, - {0x010c87, {[CaseLower] = 0x010cc7,[CaseTitle] = 0x010c87,[CaseUpper] = 0x010c87}}, - {0x010c88, {[CaseLower] = 0x010cc8,[CaseTitle] = 0x010c88,[CaseUpper] = 0x010c88}}, - {0x010c89, {[CaseLower] = 0x010cc9,[CaseTitle] = 0x010c89,[CaseUpper] = 0x010c89}}, - {0x010c8a, {[CaseLower] = 0x010cca,[CaseTitle] = 0x010c8a,[CaseUpper] = 0x010c8a}}, - {0x010c8b, {[CaseLower] = 0x010ccb,[CaseTitle] = 0x010c8b,[CaseUpper] = 0x010c8b}}, - {0x010c8c, {[CaseLower] = 0x010ccc,[CaseTitle] = 0x010c8c,[CaseUpper] = 0x010c8c}}, - {0x010c8d, {[CaseLower] = 0x010ccd,[CaseTitle] = 0x010c8d,[CaseUpper] = 0x010c8d}}, - {0x010c8e, {[CaseLower] = 0x010cce,[CaseTitle] = 0x010c8e,[CaseUpper] = 0x010c8e}}, - {0x010c8f, {[CaseLower] = 0x010ccf,[CaseTitle] = 0x010c8f,[CaseUpper] = 0x010c8f}}, - {0x010c90, {[CaseLower] = 0x010cd0,[CaseTitle] = 0x010c90,[CaseUpper] = 0x010c90}}, - {0x010c91, {[CaseLower] = 0x010cd1,[CaseTitle] = 0x010c91,[CaseUpper] = 0x010c91}}, - {0x010c92, {[CaseLower] = 0x010cd2,[CaseTitle] = 0x010c92,[CaseUpper] = 0x010c92}}, - {0x010c93, {[CaseLower] = 0x010cd3,[CaseTitle] = 0x010c93,[CaseUpper] = 0x010c93}}, - {0x010c94, {[CaseLower] = 0x010cd4,[CaseTitle] = 0x010c94,[CaseUpper] = 0x010c94}}, - {0x010c95, {[CaseLower] = 0x010cd5,[CaseTitle] = 0x010c95,[CaseUpper] = 0x010c95}}, - {0x010c96, {[CaseLower] = 0x010cd6,[CaseTitle] = 0x010c96,[CaseUpper] = 0x010c96}}, - {0x010c97, {[CaseLower] = 0x010cd7,[CaseTitle] = 0x010c97,[CaseUpper] = 0x010c97}}, - {0x010c98, {[CaseLower] = 0x010cd8,[CaseTitle] = 0x010c98,[CaseUpper] = 0x010c98}}, - {0x010c99, {[CaseLower] = 0x010cd9,[CaseTitle] = 0x010c99,[CaseUpper] = 0x010c99}}, - {0x010c9a, {[CaseLower] = 0x010cda,[CaseTitle] = 0x010c9a,[CaseUpper] = 0x010c9a}}, - {0x010c9b, {[CaseLower] = 0x010cdb,[CaseTitle] = 0x010c9b,[CaseUpper] = 0x010c9b}}, - {0x010c9c, {[CaseLower] = 0x010cdc,[CaseTitle] = 0x010c9c,[CaseUpper] = 0x010c9c}}, - {0x010c9d, {[CaseLower] = 0x010cdd,[CaseTitle] = 0x010c9d,[CaseUpper] = 0x010c9d}}, - {0x010c9e, {[CaseLower] = 0x010cde,[CaseTitle] = 0x010c9e,[CaseUpper] = 0x010c9e}}, - {0x010c9f, {[CaseLower] = 0x010cdf,[CaseTitle] = 0x010c9f,[CaseUpper] = 0x010c9f}}, - {0x010ca0, {[CaseLower] = 0x010ce0,[CaseTitle] = 0x010ca0,[CaseUpper] = 0x010ca0}}, - {0x010ca1, {[CaseLower] = 0x010ce1,[CaseTitle] = 0x010ca1,[CaseUpper] = 0x010ca1}}, - {0x010ca2, {[CaseLower] = 0x010ce2,[CaseTitle] = 0x010ca2,[CaseUpper] = 0x010ca2}}, - {0x010ca3, {[CaseLower] = 0x010ce3,[CaseTitle] = 0x010ca3,[CaseUpper] = 0x010ca3}}, - {0x010ca4, {[CaseLower] = 0x010ce4,[CaseTitle] = 0x010ca4,[CaseUpper] = 0x010ca4}}, - {0x010ca5, {[CaseLower] = 0x010ce5,[CaseTitle] = 0x010ca5,[CaseUpper] = 0x010ca5}}, - {0x010ca6, {[CaseLower] = 0x010ce6,[CaseTitle] = 0x010ca6,[CaseUpper] = 0x010ca6}}, - {0x010ca7, {[CaseLower] = 0x010ce7,[CaseTitle] = 0x010ca7,[CaseUpper] = 0x010ca7}}, - {0x010ca8, {[CaseLower] = 0x010ce8,[CaseTitle] = 0x010ca8,[CaseUpper] = 0x010ca8}}, - {0x010ca9, {[CaseLower] = 0x010ce9,[CaseTitle] = 0x010ca9,[CaseUpper] = 0x010ca9}}, - {0x010caa, {[CaseLower] = 0x010cea,[CaseTitle] = 0x010caa,[CaseUpper] = 0x010caa}}, - {0x010cab, {[CaseLower] = 0x010ceb,[CaseTitle] = 0x010cab,[CaseUpper] = 0x010cab}}, - {0x010cac, {[CaseLower] = 0x010cec,[CaseTitle] = 0x010cac,[CaseUpper] = 0x010cac}}, - {0x010cad, {[CaseLower] = 0x010ced,[CaseTitle] = 0x010cad,[CaseUpper] = 0x010cad}}, - {0x010cae, {[CaseLower] = 0x010cee,[CaseTitle] = 0x010cae,[CaseUpper] = 0x010cae}}, - {0x010caf, {[CaseLower] = 0x010cef,[CaseTitle] = 0x010caf,[CaseUpper] = 0x010caf}}, - {0x010cb0, {[CaseLower] = 0x010cf0,[CaseTitle] = 0x010cb0,[CaseUpper] = 0x010cb0}}, - {0x010cb1, {[CaseLower] = 0x010cf1,[CaseTitle] = 0x010cb1,[CaseUpper] = 0x010cb1}}, - {0x010cb2, {[CaseLower] = 0x010cf2,[CaseTitle] = 0x010cb2,[CaseUpper] = 0x010cb2}}, - {0x010cc0, {[CaseLower] = 0x010cc0,[CaseTitle] = 0x010c80,[CaseUpper] = 0x010c80}}, - {0x010cc1, {[CaseLower] = 0x010cc1,[CaseTitle] = 0x010c81,[CaseUpper] = 0x010c81}}, - {0x010cc2, {[CaseLower] = 0x010cc2,[CaseTitle] = 0x010c82,[CaseUpper] = 0x010c82}}, - {0x010cc3, {[CaseLower] = 0x010cc3,[CaseTitle] = 0x010c83,[CaseUpper] = 0x010c83}}, - {0x010cc4, {[CaseLower] = 0x010cc4,[CaseTitle] = 0x010c84,[CaseUpper] = 0x010c84}}, - {0x010cc5, {[CaseLower] = 0x010cc5,[CaseTitle] = 0x010c85,[CaseUpper] = 0x010c85}}, - {0x010cc6, {[CaseLower] = 0x010cc6,[CaseTitle] = 0x010c86,[CaseUpper] = 0x010c86}}, - {0x010cc7, {[CaseLower] = 0x010cc7,[CaseTitle] = 0x010c87,[CaseUpper] = 0x010c87}}, - {0x010cc8, {[CaseLower] = 0x010cc8,[CaseTitle] = 0x010c88,[CaseUpper] = 0x010c88}}, - {0x010cc9, {[CaseLower] = 0x010cc9,[CaseTitle] = 0x010c89,[CaseUpper] = 0x010c89}}, - {0x010cca, {[CaseLower] = 0x010cca,[CaseTitle] = 0x010c8a,[CaseUpper] = 0x010c8a}}, - {0x010ccb, {[CaseLower] = 0x010ccb,[CaseTitle] = 0x010c8b,[CaseUpper] = 0x010c8b}}, - {0x010ccc, {[CaseLower] = 0x010ccc,[CaseTitle] = 0x010c8c,[CaseUpper] = 0x010c8c}}, - {0x010ccd, {[CaseLower] = 0x010ccd,[CaseTitle] = 0x010c8d,[CaseUpper] = 0x010c8d}}, - {0x010cce, {[CaseLower] = 0x010cce,[CaseTitle] = 0x010c8e,[CaseUpper] = 0x010c8e}}, - {0x010ccf, {[CaseLower] = 0x010ccf,[CaseTitle] = 0x010c8f,[CaseUpper] = 0x010c8f}}, - {0x010cd0, {[CaseLower] = 0x010cd0,[CaseTitle] = 0x010c90,[CaseUpper] = 0x010c90}}, - {0x010cd1, {[CaseLower] = 0x010cd1,[CaseTitle] = 0x010c91,[CaseUpper] = 0x010c91}}, - {0x010cd2, {[CaseLower] = 0x010cd2,[CaseTitle] = 0x010c92,[CaseUpper] = 0x010c92}}, - {0x010cd3, {[CaseLower] = 0x010cd3,[CaseTitle] = 0x010c93,[CaseUpper] = 0x010c93}}, - {0x010cd4, {[CaseLower] = 0x010cd4,[CaseTitle] = 0x010c94,[CaseUpper] = 0x010c94}}, - {0x010cd5, {[CaseLower] = 0x010cd5,[CaseTitle] = 0x010c95,[CaseUpper] = 0x010c95}}, - {0x010cd6, {[CaseLower] = 0x010cd6,[CaseTitle] = 0x010c96,[CaseUpper] = 0x010c96}}, - {0x010cd7, {[CaseLower] = 0x010cd7,[CaseTitle] = 0x010c97,[CaseUpper] = 0x010c97}}, - {0x010cd8, {[CaseLower] = 0x010cd8,[CaseTitle] = 0x010c98,[CaseUpper] = 0x010c98}}, - {0x010cd9, {[CaseLower] = 0x010cd9,[CaseTitle] = 0x010c99,[CaseUpper] = 0x010c99}}, - {0x010cda, {[CaseLower] = 0x010cda,[CaseTitle] = 0x010c9a,[CaseUpper] = 0x010c9a}}, - {0x010cdb, {[CaseLower] = 0x010cdb,[CaseTitle] = 0x010c9b,[CaseUpper] = 0x010c9b}}, - {0x010cdc, {[CaseLower] = 0x010cdc,[CaseTitle] = 0x010c9c,[CaseUpper] = 0x010c9c}}, - {0x010cdd, {[CaseLower] = 0x010cdd,[CaseTitle] = 0x010c9d,[CaseUpper] = 0x010c9d}}, - {0x010cde, {[CaseLower] = 0x010cde,[CaseTitle] = 0x010c9e,[CaseUpper] = 0x010c9e}}, - {0x010cdf, {[CaseLower] = 0x010cdf,[CaseTitle] = 0x010c9f,[CaseUpper] = 0x010c9f}}, - {0x010ce0, {[CaseLower] = 0x010ce0,[CaseTitle] = 0x010ca0,[CaseUpper] = 0x010ca0}}, - {0x010ce1, {[CaseLower] = 0x010ce1,[CaseTitle] = 0x010ca1,[CaseUpper] = 0x010ca1}}, - {0x010ce2, {[CaseLower] = 0x010ce2,[CaseTitle] = 0x010ca2,[CaseUpper] = 0x010ca2}}, - {0x010ce3, {[CaseLower] = 0x010ce3,[CaseTitle] = 0x010ca3,[CaseUpper] = 0x010ca3}}, - {0x010ce4, {[CaseLower] = 0x010ce4,[CaseTitle] = 0x010ca4,[CaseUpper] = 0x010ca4}}, - {0x010ce5, {[CaseLower] = 0x010ce5,[CaseTitle] = 0x010ca5,[CaseUpper] = 0x010ca5}}, - {0x010ce6, {[CaseLower] = 0x010ce6,[CaseTitle] = 0x010ca6,[CaseUpper] = 0x010ca6}}, - {0x010ce7, {[CaseLower] = 0x010ce7,[CaseTitle] = 0x010ca7,[CaseUpper] = 0x010ca7}}, - {0x010ce8, {[CaseLower] = 0x010ce8,[CaseTitle] = 0x010ca8,[CaseUpper] = 0x010ca8}}, - {0x010ce9, {[CaseLower] = 0x010ce9,[CaseTitle] = 0x010ca9,[CaseUpper] = 0x010ca9}}, - {0x010cea, {[CaseLower] = 0x010cea,[CaseTitle] = 0x010caa,[CaseUpper] = 0x010caa}}, - {0x010ceb, {[CaseLower] = 0x010ceb,[CaseTitle] = 0x010cab,[CaseUpper] = 0x010cab}}, - {0x010cec, {[CaseLower] = 0x010cec,[CaseTitle] = 0x010cac,[CaseUpper] = 0x010cac}}, - {0x010ced, {[CaseLower] = 0x010ced,[CaseTitle] = 0x010cad,[CaseUpper] = 0x010cad}}, - {0x010cee, {[CaseLower] = 0x010cee,[CaseTitle] = 0x010cae,[CaseUpper] = 0x010cae}}, - {0x010cef, {[CaseLower] = 0x010cef,[CaseTitle] = 0x010caf,[CaseUpper] = 0x010caf}}, - {0x010cf0, {[CaseLower] = 0x010cf0,[CaseTitle] = 0x010cb0,[CaseUpper] = 0x010cb0}}, - {0x010cf1, {[CaseLower] = 0x010cf1,[CaseTitle] = 0x010cb1,[CaseUpper] = 0x010cb1}}, - {0x010cf2, {[CaseLower] = 0x010cf2,[CaseTitle] = 0x010cb2,[CaseUpper] = 0x010cb2}}, - {0x0118a0, {[CaseLower] = 0x0118c0,[CaseTitle] = 0x0118a0,[CaseUpper] = 0x0118a0}}, - {0x0118a1, {[CaseLower] = 0x0118c1,[CaseTitle] = 0x0118a1,[CaseUpper] = 0x0118a1}}, - {0x0118a2, {[CaseLower] = 0x0118c2,[CaseTitle] = 0x0118a2,[CaseUpper] = 0x0118a2}}, - {0x0118a3, {[CaseLower] = 0x0118c3,[CaseTitle] = 0x0118a3,[CaseUpper] = 0x0118a3}}, - {0x0118a4, {[CaseLower] = 0x0118c4,[CaseTitle] = 0x0118a4,[CaseUpper] = 0x0118a4}}, - {0x0118a5, {[CaseLower] = 0x0118c5,[CaseTitle] = 0x0118a5,[CaseUpper] = 0x0118a5}}, - {0x0118a6, {[CaseLower] = 0x0118c6,[CaseTitle] = 0x0118a6,[CaseUpper] = 0x0118a6}}, - {0x0118a7, {[CaseLower] = 0x0118c7,[CaseTitle] = 0x0118a7,[CaseUpper] = 0x0118a7}}, - {0x0118a8, {[CaseLower] = 0x0118c8,[CaseTitle] = 0x0118a8,[CaseUpper] = 0x0118a8}}, - {0x0118a9, {[CaseLower] = 0x0118c9,[CaseTitle] = 0x0118a9,[CaseUpper] = 0x0118a9}}, - {0x0118aa, {[CaseLower] = 0x0118ca,[CaseTitle] = 0x0118aa,[CaseUpper] = 0x0118aa}}, - {0x0118ab, {[CaseLower] = 0x0118cb,[CaseTitle] = 0x0118ab,[CaseUpper] = 0x0118ab}}, - {0x0118ac, {[CaseLower] = 0x0118cc,[CaseTitle] = 0x0118ac,[CaseUpper] = 0x0118ac}}, - {0x0118ad, {[CaseLower] = 0x0118cd,[CaseTitle] = 0x0118ad,[CaseUpper] = 0x0118ad}}, - {0x0118ae, {[CaseLower] = 0x0118ce,[CaseTitle] = 0x0118ae,[CaseUpper] = 0x0118ae}}, - {0x0118af, {[CaseLower] = 0x0118cf,[CaseTitle] = 0x0118af,[CaseUpper] = 0x0118af}}, - {0x0118b0, {[CaseLower] = 0x0118d0,[CaseTitle] = 0x0118b0,[CaseUpper] = 0x0118b0}}, - {0x0118b1, {[CaseLower] = 0x0118d1,[CaseTitle] = 0x0118b1,[CaseUpper] = 0x0118b1}}, - {0x0118b2, {[CaseLower] = 0x0118d2,[CaseTitle] = 0x0118b2,[CaseUpper] = 0x0118b2}}, - {0x0118b3, {[CaseLower] = 0x0118d3,[CaseTitle] = 0x0118b3,[CaseUpper] = 0x0118b3}}, - {0x0118b4, {[CaseLower] = 0x0118d4,[CaseTitle] = 0x0118b4,[CaseUpper] = 0x0118b4}}, - {0x0118b5, {[CaseLower] = 0x0118d5,[CaseTitle] = 0x0118b5,[CaseUpper] = 0x0118b5}}, - {0x0118b6, {[CaseLower] = 0x0118d6,[CaseTitle] = 0x0118b6,[CaseUpper] = 0x0118b6}}, - {0x0118b7, {[CaseLower] = 0x0118d7,[CaseTitle] = 0x0118b7,[CaseUpper] = 0x0118b7}}, - {0x0118b8, {[CaseLower] = 0x0118d8,[CaseTitle] = 0x0118b8,[CaseUpper] = 0x0118b8}}, - {0x0118b9, {[CaseLower] = 0x0118d9,[CaseTitle] = 0x0118b9,[CaseUpper] = 0x0118b9}}, - {0x0118ba, {[CaseLower] = 0x0118da,[CaseTitle] = 0x0118ba,[CaseUpper] = 0x0118ba}}, - {0x0118bb, {[CaseLower] = 0x0118db,[CaseTitle] = 0x0118bb,[CaseUpper] = 0x0118bb}}, - {0x0118bc, {[CaseLower] = 0x0118dc,[CaseTitle] = 0x0118bc,[CaseUpper] = 0x0118bc}}, - {0x0118bd, {[CaseLower] = 0x0118dd,[CaseTitle] = 0x0118bd,[CaseUpper] = 0x0118bd}}, - {0x0118be, {[CaseLower] = 0x0118de,[CaseTitle] = 0x0118be,[CaseUpper] = 0x0118be}}, - {0x0118bf, {[CaseLower] = 0x0118df,[CaseTitle] = 0x0118bf,[CaseUpper] = 0x0118bf}}, - {0x0118c0, {[CaseLower] = 0x0118c0,[CaseTitle] = 0x0118a0,[CaseUpper] = 0x0118a0}}, - {0x0118c1, {[CaseLower] = 0x0118c1,[CaseTitle] = 0x0118a1,[CaseUpper] = 0x0118a1}}, - {0x0118c2, {[CaseLower] = 0x0118c2,[CaseTitle] = 0x0118a2,[CaseUpper] = 0x0118a2}}, - {0x0118c3, {[CaseLower] = 0x0118c3,[CaseTitle] = 0x0118a3,[CaseUpper] = 0x0118a3}}, - {0x0118c4, {[CaseLower] = 0x0118c4,[CaseTitle] = 0x0118a4,[CaseUpper] = 0x0118a4}}, - {0x0118c5, {[CaseLower] = 0x0118c5,[CaseTitle] = 0x0118a5,[CaseUpper] = 0x0118a5}}, - {0x0118c6, {[CaseLower] = 0x0118c6,[CaseTitle] = 0x0118a6,[CaseUpper] = 0x0118a6}}, - {0x0118c7, {[CaseLower] = 0x0118c7,[CaseTitle] = 0x0118a7,[CaseUpper] = 0x0118a7}}, - {0x0118c8, {[CaseLower] = 0x0118c8,[CaseTitle] = 0x0118a8,[CaseUpper] = 0x0118a8}}, - {0x0118c9, {[CaseLower] = 0x0118c9,[CaseTitle] = 0x0118a9,[CaseUpper] = 0x0118a9}}, - {0x0118ca, {[CaseLower] = 0x0118ca,[CaseTitle] = 0x0118aa,[CaseUpper] = 0x0118aa}}, - {0x0118cb, {[CaseLower] = 0x0118cb,[CaseTitle] = 0x0118ab,[CaseUpper] = 0x0118ab}}, - {0x0118cc, {[CaseLower] = 0x0118cc,[CaseTitle] = 0x0118ac,[CaseUpper] = 0x0118ac}}, - {0x0118cd, {[CaseLower] = 0x0118cd,[CaseTitle] = 0x0118ad,[CaseUpper] = 0x0118ad}}, - {0x0118ce, {[CaseLower] = 0x0118ce,[CaseTitle] = 0x0118ae,[CaseUpper] = 0x0118ae}}, - {0x0118cf, {[CaseLower] = 0x0118cf,[CaseTitle] = 0x0118af,[CaseUpper] = 0x0118af}}, - {0x0118d0, {[CaseLower] = 0x0118d0,[CaseTitle] = 0x0118b0,[CaseUpper] = 0x0118b0}}, - {0x0118d1, {[CaseLower] = 0x0118d1,[CaseTitle] = 0x0118b1,[CaseUpper] = 0x0118b1}}, - {0x0118d2, {[CaseLower] = 0x0118d2,[CaseTitle] = 0x0118b2,[CaseUpper] = 0x0118b2}}, - {0x0118d3, {[CaseLower] = 0x0118d3,[CaseTitle] = 0x0118b3,[CaseUpper] = 0x0118b3}}, - {0x0118d4, {[CaseLower] = 0x0118d4,[CaseTitle] = 0x0118b4,[CaseUpper] = 0x0118b4}}, - {0x0118d5, {[CaseLower] = 0x0118d5,[CaseTitle] = 0x0118b5,[CaseUpper] = 0x0118b5}}, - {0x0118d6, {[CaseLower] = 0x0118d6,[CaseTitle] = 0x0118b6,[CaseUpper] = 0x0118b6}}, - {0x0118d7, {[CaseLower] = 0x0118d7,[CaseTitle] = 0x0118b7,[CaseUpper] = 0x0118b7}}, - {0x0118d8, {[CaseLower] = 0x0118d8,[CaseTitle] = 0x0118b8,[CaseUpper] = 0x0118b8}}, - {0x0118d9, {[CaseLower] = 0x0118d9,[CaseTitle] = 0x0118b9,[CaseUpper] = 0x0118b9}}, - {0x0118da, {[CaseLower] = 0x0118da,[CaseTitle] = 0x0118ba,[CaseUpper] = 0x0118ba}}, - {0x0118db, {[CaseLower] = 0x0118db,[CaseTitle] = 0x0118bb,[CaseUpper] = 0x0118bb}}, - {0x0118dc, {[CaseLower] = 0x0118dc,[CaseTitle] = 0x0118bc,[CaseUpper] = 0x0118bc}}, - {0x0118dd, {[CaseLower] = 0x0118dd,[CaseTitle] = 0x0118bd,[CaseUpper] = 0x0118bd}}, - {0x0118de, {[CaseLower] = 0x0118de,[CaseTitle] = 0x0118be,[CaseUpper] = 0x0118be}}, - {0x0118df, {[CaseLower] = 0x0118df,[CaseTitle] = 0x0118bf,[CaseUpper] = 0x0118bf}}, - {0x016e40, {[CaseLower] = 0x016e60,[CaseTitle] = 0x016e40,[CaseUpper] = 0x016e40}}, - {0x016e41, {[CaseLower] = 0x016e61,[CaseTitle] = 0x016e41,[CaseUpper] = 0x016e41}}, - {0x016e42, {[CaseLower] = 0x016e62,[CaseTitle] = 0x016e42,[CaseUpper] = 0x016e42}}, - {0x016e43, {[CaseLower] = 0x016e63,[CaseTitle] = 0x016e43,[CaseUpper] = 0x016e43}}, - {0x016e44, {[CaseLower] = 0x016e64,[CaseTitle] = 0x016e44,[CaseUpper] = 0x016e44}}, - {0x016e45, {[CaseLower] = 0x016e65,[CaseTitle] = 0x016e45,[CaseUpper] = 0x016e45}}, - {0x016e46, {[CaseLower] = 0x016e66,[CaseTitle] = 0x016e46,[CaseUpper] = 0x016e46}}, - {0x016e47, {[CaseLower] = 0x016e67,[CaseTitle] = 0x016e47,[CaseUpper] = 0x016e47}}, - {0x016e48, {[CaseLower] = 0x016e68,[CaseTitle] = 0x016e48,[CaseUpper] = 0x016e48}}, - {0x016e49, {[CaseLower] = 0x016e69,[CaseTitle] = 0x016e49,[CaseUpper] = 0x016e49}}, - {0x016e4a, {[CaseLower] = 0x016e6a,[CaseTitle] = 0x016e4a,[CaseUpper] = 0x016e4a}}, - {0x016e4b, {[CaseLower] = 0x016e6b,[CaseTitle] = 0x016e4b,[CaseUpper] = 0x016e4b}}, - {0x016e4c, {[CaseLower] = 0x016e6c,[CaseTitle] = 0x016e4c,[CaseUpper] = 0x016e4c}}, - {0x016e4d, {[CaseLower] = 0x016e6d,[CaseTitle] = 0x016e4d,[CaseUpper] = 0x016e4d}}, - {0x016e4e, {[CaseLower] = 0x016e6e,[CaseTitle] = 0x016e4e,[CaseUpper] = 0x016e4e}}, - {0x016e4f, {[CaseLower] = 0x016e6f,[CaseTitle] = 0x016e4f,[CaseUpper] = 0x016e4f}}, - {0x016e50, {[CaseLower] = 0x016e70,[CaseTitle] = 0x016e50,[CaseUpper] = 0x016e50}}, - {0x016e51, {[CaseLower] = 0x016e71,[CaseTitle] = 0x016e51,[CaseUpper] = 0x016e51}}, - {0x016e52, {[CaseLower] = 0x016e72,[CaseTitle] = 0x016e52,[CaseUpper] = 0x016e52}}, - {0x016e53, {[CaseLower] = 0x016e73,[CaseTitle] = 0x016e53,[CaseUpper] = 0x016e53}}, - {0x016e54, {[CaseLower] = 0x016e74,[CaseTitle] = 0x016e54,[CaseUpper] = 0x016e54}}, - {0x016e55, {[CaseLower] = 0x016e75,[CaseTitle] = 0x016e55,[CaseUpper] = 0x016e55}}, - {0x016e56, {[CaseLower] = 0x016e76,[CaseTitle] = 0x016e56,[CaseUpper] = 0x016e56}}, - {0x016e57, {[CaseLower] = 0x016e77,[CaseTitle] = 0x016e57,[CaseUpper] = 0x016e57}}, - {0x016e58, {[CaseLower] = 0x016e78,[CaseTitle] = 0x016e58,[CaseUpper] = 0x016e58}}, - {0x016e59, {[CaseLower] = 0x016e79,[CaseTitle] = 0x016e59,[CaseUpper] = 0x016e59}}, - {0x016e5a, {[CaseLower] = 0x016e7a,[CaseTitle] = 0x016e5a,[CaseUpper] = 0x016e5a}}, - {0x016e5b, {[CaseLower] = 0x016e7b,[CaseTitle] = 0x016e5b,[CaseUpper] = 0x016e5b}}, - {0x016e5c, {[CaseLower] = 0x016e7c,[CaseTitle] = 0x016e5c,[CaseUpper] = 0x016e5c}}, - {0x016e5d, {[CaseLower] = 0x016e7d,[CaseTitle] = 0x016e5d,[CaseUpper] = 0x016e5d}}, - {0x016e5e, {[CaseLower] = 0x016e7e,[CaseTitle] = 0x016e5e,[CaseUpper] = 0x016e5e}}, - {0x016e5f, {[CaseLower] = 0x016e7f,[CaseTitle] = 0x016e5f,[CaseUpper] = 0x016e5f}}, - {0x016e60, {[CaseLower] = 0x016e60,[CaseTitle] = 0x016e40,[CaseUpper] = 0x016e40}}, - {0x016e61, {[CaseLower] = 0x016e61,[CaseTitle] = 0x016e41,[CaseUpper] = 0x016e41}}, - {0x016e62, {[CaseLower] = 0x016e62,[CaseTitle] = 0x016e42,[CaseUpper] = 0x016e42}}, - {0x016e63, {[CaseLower] = 0x016e63,[CaseTitle] = 0x016e43,[CaseUpper] = 0x016e43}}, - {0x016e64, {[CaseLower] = 0x016e64,[CaseTitle] = 0x016e44,[CaseUpper] = 0x016e44}}, - {0x016e65, {[CaseLower] = 0x016e65,[CaseTitle] = 0x016e45,[CaseUpper] = 0x016e45}}, - {0x016e66, {[CaseLower] = 0x016e66,[CaseTitle] = 0x016e46,[CaseUpper] = 0x016e46}}, - {0x016e67, {[CaseLower] = 0x016e67,[CaseTitle] = 0x016e47,[CaseUpper] = 0x016e47}}, - {0x016e68, {[CaseLower] = 0x016e68,[CaseTitle] = 0x016e48,[CaseUpper] = 0x016e48}}, - {0x016e69, {[CaseLower] = 0x016e69,[CaseTitle] = 0x016e49,[CaseUpper] = 0x016e49}}, - {0x016e6a, {[CaseLower] = 0x016e6a,[CaseTitle] = 0x016e4a,[CaseUpper] = 0x016e4a}}, - {0x016e6b, {[CaseLower] = 0x016e6b,[CaseTitle] = 0x016e4b,[CaseUpper] = 0x016e4b}}, - {0x016e6c, {[CaseLower] = 0x016e6c,[CaseTitle] = 0x016e4c,[CaseUpper] = 0x016e4c}}, - {0x016e6d, {[CaseLower] = 0x016e6d,[CaseTitle] = 0x016e4d,[CaseUpper] = 0x016e4d}}, - {0x016e6e, {[CaseLower] = 0x016e6e,[CaseTitle] = 0x016e4e,[CaseUpper] = 0x016e4e}}, - {0x016e6f, {[CaseLower] = 0x016e6f,[CaseTitle] = 0x016e4f,[CaseUpper] = 0x016e4f}}, - {0x016e70, {[CaseLower] = 0x016e70,[CaseTitle] = 0x016e50,[CaseUpper] = 0x016e50}}, - {0x016e71, {[CaseLower] = 0x016e71,[CaseTitle] = 0x016e51,[CaseUpper] = 0x016e51}}, - {0x016e72, {[CaseLower] = 0x016e72,[CaseTitle] = 0x016e52,[CaseUpper] = 0x016e52}}, - {0x016e73, {[CaseLower] = 0x016e73,[CaseTitle] = 0x016e53,[CaseUpper] = 0x016e53}}, - {0x016e74, {[CaseLower] = 0x016e74,[CaseTitle] = 0x016e54,[CaseUpper] = 0x016e54}}, - {0x016e75, {[CaseLower] = 0x016e75,[CaseTitle] = 0x016e55,[CaseUpper] = 0x016e55}}, - {0x016e76, {[CaseLower] = 0x016e76,[CaseTitle] = 0x016e56,[CaseUpper] = 0x016e56}}, - {0x016e77, {[CaseLower] = 0x016e77,[CaseTitle] = 0x016e57,[CaseUpper] = 0x016e57}}, - {0x016e78, {[CaseLower] = 0x016e78,[CaseTitle] = 0x016e58,[CaseUpper] = 0x016e58}}, - {0x016e79, {[CaseLower] = 0x016e79,[CaseTitle] = 0x016e59,[CaseUpper] = 0x016e59}}, - {0x016e7a, {[CaseLower] = 0x016e7a,[CaseTitle] = 0x016e5a,[CaseUpper] = 0x016e5a}}, - {0x016e7b, {[CaseLower] = 0x016e7b,[CaseTitle] = 0x016e5b,[CaseUpper] = 0x016e5b}}, - {0x016e7c, {[CaseLower] = 0x016e7c,[CaseTitle] = 0x016e5c,[CaseUpper] = 0x016e5c}}, - {0x016e7d, {[CaseLower] = 0x016e7d,[CaseTitle] = 0x016e5d,[CaseUpper] = 0x016e5d}}, - {0x016e7e, {[CaseLower] = 0x016e7e,[CaseTitle] = 0x016e5e,[CaseUpper] = 0x016e5e}}, - {0x016e7f, {[CaseLower] = 0x016e7f,[CaseTitle] = 0x016e5f,[CaseUpper] = 0x016e5f}}, - {0x01e900, {[CaseLower] = 0x01e922,[CaseTitle] = 0x01e900,[CaseUpper] = 0x01e900}}, - {0x01e901, {[CaseLower] = 0x01e923,[CaseTitle] = 0x01e901,[CaseUpper] = 0x01e901}}, - {0x01e902, {[CaseLower] = 0x01e924,[CaseTitle] = 0x01e902,[CaseUpper] = 0x01e902}}, - {0x01e903, {[CaseLower] = 0x01e925,[CaseTitle] = 0x01e903,[CaseUpper] = 0x01e903}}, - {0x01e904, {[CaseLower] = 0x01e926,[CaseTitle] = 0x01e904,[CaseUpper] = 0x01e904}}, - {0x01e905, {[CaseLower] = 0x01e927,[CaseTitle] = 0x01e905,[CaseUpper] = 0x01e905}}, - {0x01e906, {[CaseLower] = 0x01e928,[CaseTitle] = 0x01e906,[CaseUpper] = 0x01e906}}, - {0x01e907, {[CaseLower] = 0x01e929,[CaseTitle] = 0x01e907,[CaseUpper] = 0x01e907}}, - {0x01e908, {[CaseLower] = 0x01e92a,[CaseTitle] = 0x01e908,[CaseUpper] = 0x01e908}}, - {0x01e909, {[CaseLower] = 0x01e92b,[CaseTitle] = 0x01e909,[CaseUpper] = 0x01e909}}, - {0x01e90a, {[CaseLower] = 0x01e92c,[CaseTitle] = 0x01e90a,[CaseUpper] = 0x01e90a}}, - {0x01e90b, {[CaseLower] = 0x01e92d,[CaseTitle] = 0x01e90b,[CaseUpper] = 0x01e90b}}, - {0x01e90c, {[CaseLower] = 0x01e92e,[CaseTitle] = 0x01e90c,[CaseUpper] = 0x01e90c}}, - {0x01e90d, {[CaseLower] = 0x01e92f,[CaseTitle] = 0x01e90d,[CaseUpper] = 0x01e90d}}, - {0x01e90e, {[CaseLower] = 0x01e930,[CaseTitle] = 0x01e90e,[CaseUpper] = 0x01e90e}}, - {0x01e90f, {[CaseLower] = 0x01e931,[CaseTitle] = 0x01e90f,[CaseUpper] = 0x01e90f}}, - {0x01e910, {[CaseLower] = 0x01e932,[CaseTitle] = 0x01e910,[CaseUpper] = 0x01e910}}, - {0x01e911, {[CaseLower] = 0x01e933,[CaseTitle] = 0x01e911,[CaseUpper] = 0x01e911}}, - {0x01e912, {[CaseLower] = 0x01e934,[CaseTitle] = 0x01e912,[CaseUpper] = 0x01e912}}, - {0x01e913, {[CaseLower] = 0x01e935,[CaseTitle] = 0x01e913,[CaseUpper] = 0x01e913}}, - {0x01e914, {[CaseLower] = 0x01e936,[CaseTitle] = 0x01e914,[CaseUpper] = 0x01e914}}, - {0x01e915, {[CaseLower] = 0x01e937,[CaseTitle] = 0x01e915,[CaseUpper] = 0x01e915}}, - {0x01e916, {[CaseLower] = 0x01e938,[CaseTitle] = 0x01e916,[CaseUpper] = 0x01e916}}, - {0x01e917, {[CaseLower] = 0x01e939,[CaseTitle] = 0x01e917,[CaseUpper] = 0x01e917}}, - {0x01e918, {[CaseLower] = 0x01e93a,[CaseTitle] = 0x01e918,[CaseUpper] = 0x01e918}}, - {0x01e919, {[CaseLower] = 0x01e93b,[CaseTitle] = 0x01e919,[CaseUpper] = 0x01e919}}, - {0x01e91a, {[CaseLower] = 0x01e93c,[CaseTitle] = 0x01e91a,[CaseUpper] = 0x01e91a}}, - {0x01e91b, {[CaseLower] = 0x01e93d,[CaseTitle] = 0x01e91b,[CaseUpper] = 0x01e91b}}, - {0x01e91c, {[CaseLower] = 0x01e93e,[CaseTitle] = 0x01e91c,[CaseUpper] = 0x01e91c}}, - {0x01e91d, {[CaseLower] = 0x01e93f,[CaseTitle] = 0x01e91d,[CaseUpper] = 0x01e91d}}, - {0x01e91e, {[CaseLower] = 0x01e940,[CaseTitle] = 0x01e91e,[CaseUpper] = 0x01e91e}}, - {0x01e91f, {[CaseLower] = 0x01e941,[CaseTitle] = 0x01e91f,[CaseUpper] = 0x01e91f}}, - {0x01e920, {[CaseLower] = 0x01e942,[CaseTitle] = 0x01e920,[CaseUpper] = 0x01e920}}, - {0x01e921, {[CaseLower] = 0x01e943,[CaseTitle] = 0x01e921,[CaseUpper] = 0x01e921}}, - {0x01e922, {[CaseLower] = 0x01e922,[CaseTitle] = 0x01e900,[CaseUpper] = 0x01e900}}, - {0x01e923, {[CaseLower] = 0x01e923,[CaseTitle] = 0x01e901,[CaseUpper] = 0x01e901}}, - {0x01e924, {[CaseLower] = 0x01e924,[CaseTitle] = 0x01e902,[CaseUpper] = 0x01e902}}, - {0x01e925, {[CaseLower] = 0x01e925,[CaseTitle] = 0x01e903,[CaseUpper] = 0x01e903}}, - {0x01e926, {[CaseLower] = 0x01e926,[CaseTitle] = 0x01e904,[CaseUpper] = 0x01e904}}, - {0x01e927, {[CaseLower] = 0x01e927,[CaseTitle] = 0x01e905,[CaseUpper] = 0x01e905}}, - {0x01e928, {[CaseLower] = 0x01e928,[CaseTitle] = 0x01e906,[CaseUpper] = 0x01e906}}, - {0x01e929, {[CaseLower] = 0x01e929,[CaseTitle] = 0x01e907,[CaseUpper] = 0x01e907}}, - {0x01e92a, {[CaseLower] = 0x01e92a,[CaseTitle] = 0x01e908,[CaseUpper] = 0x01e908}}, - {0x01e92b, {[CaseLower] = 0x01e92b,[CaseTitle] = 0x01e909,[CaseUpper] = 0x01e909}}, - {0x01e92c, {[CaseLower] = 0x01e92c,[CaseTitle] = 0x01e90a,[CaseUpper] = 0x01e90a}}, - {0x01e92d, {[CaseLower] = 0x01e92d,[CaseTitle] = 0x01e90b,[CaseUpper] = 0x01e90b}}, - {0x01e92e, {[CaseLower] = 0x01e92e,[CaseTitle] = 0x01e90c,[CaseUpper] = 0x01e90c}}, - {0x01e92f, {[CaseLower] = 0x01e92f,[CaseTitle] = 0x01e90d,[CaseUpper] = 0x01e90d}}, - {0x01e930, {[CaseLower] = 0x01e930,[CaseTitle] = 0x01e90e,[CaseUpper] = 0x01e90e}}, - {0x01e931, {[CaseLower] = 0x01e931,[CaseTitle] = 0x01e90f,[CaseUpper] = 0x01e90f}}, - {0x01e932, {[CaseLower] = 0x01e932,[CaseTitle] = 0x01e910,[CaseUpper] = 0x01e910}}, - {0x01e933, {[CaseLower] = 0x01e933,[CaseTitle] = 0x01e911,[CaseUpper] = 0x01e911}}, - {0x01e934, {[CaseLower] = 0x01e934,[CaseTitle] = 0x01e912,[CaseUpper] = 0x01e912}}, - {0x01e935, {[CaseLower] = 0x01e935,[CaseTitle] = 0x01e913,[CaseUpper] = 0x01e913}}, - {0x01e936, {[CaseLower] = 0x01e936,[CaseTitle] = 0x01e914,[CaseUpper] = 0x01e914}}, - {0x01e937, {[CaseLower] = 0x01e937,[CaseTitle] = 0x01e915,[CaseUpper] = 0x01e915}}, - {0x01e938, {[CaseLower] = 0x01e938,[CaseTitle] = 0x01e916,[CaseUpper] = 0x01e916}}, - {0x01e939, {[CaseLower] = 0x01e939,[CaseTitle] = 0x01e917,[CaseUpper] = 0x01e917}}, - {0x01e93a, {[CaseLower] = 0x01e93a,[CaseTitle] = 0x01e918,[CaseUpper] = 0x01e918}}, - {0x01e93b, {[CaseLower] = 0x01e93b,[CaseTitle] = 0x01e919,[CaseUpper] = 0x01e919}}, - {0x01e93c, {[CaseLower] = 0x01e93c,[CaseTitle] = 0x01e91a,[CaseUpper] = 0x01e91a}}, - {0x01e93d, {[CaseLower] = 0x01e93d,[CaseTitle] = 0x01e91b,[CaseUpper] = 0x01e91b}}, - {0x01e93e, {[CaseLower] = 0x01e93e,[CaseTitle] = 0x01e91c,[CaseUpper] = 0x01e91c}}, - {0x01e93f, {[CaseLower] = 0x01e93f,[CaseTitle] = 0x01e91d,[CaseUpper] = 0x01e91d}}, - {0x01e940, {[CaseLower] = 0x01e940,[CaseTitle] = 0x01e91e,[CaseUpper] = 0x01e91e}}, - {0x01e941, {[CaseLower] = 0x01e941,[CaseTitle] = 0x01e91f,[CaseUpper] = 0x01e91f}}, - {0x01e942, {[CaseLower] = 0x01e942,[CaseTitle] = 0x01e920,[CaseUpper] = 0x01e920}}, - {0x01e943, {[CaseLower] = 0x01e943,[CaseTitle] = 0x01e921,[CaseUpper] = 0x01e921}}, }; + +/* + * The entry case_map_title[case_index(codepoint)] is the mapping for the + * given codepoint. + */ +static const pg_wchar case_map_title[1704] = +{ + 0x000000, /* reserved */ + 0x000000, /* U+000000 */ + 0x000001, /* U+000001 */ + 0x000002, /* U+000002 */ + 0x000003, /* U+000003 */ + 0x000004, /* U+000004 */ + 0x000005, /* U+000005 */ + 0x000006, /* U+000006 */ + 0x000007, /* U+000007 */ + 0x000008, /* U+000008 */ + 0x000009, /* U+000009 */ + 0x00000a, /* U+00000a */ + 0x00000b, /* U+00000b */ + 0x00000c, /* U+00000c */ + 0x00000d, /* U+00000d */ + 0x00000e, /* U+00000e */ + 0x00000f, /* U+00000f */ + 0x000010, /* U+000010 */ + 0x000011, /* U+000011 */ + 0x000012, /* U+000012 */ + 0x000013, /* U+000013 */ + 0x000014, /* U+000014 */ + 0x000015, /* U+000015 */ + 0x000016, /* U+000016 */ + 0x000017, /* U+000017 */ + 0x000018, /* U+000018 */ + 0x000019, /* U+000019 */ + 0x00001a, /* U+00001a */ + 0x00001b, /* U+00001b */ + 0x00001c, /* U+00001c */ + 0x00001d, /* U+00001d */ + 0x00001e, /* U+00001e */ + 0x00001f, /* U+00001f */ + 0x000020, /* U+000020 */ + 0x000021, /* U+000021 */ + 0x000022, /* U+000022 */ + 0x000023, /* U+000023 */ + 0x000024, /* U+000024 */ + 0x000025, /* U+000025 */ + 0x000026, /* U+000026 */ + 0x000027, /* U+000027 */ + 0x000028, /* U+000028 */ + 0x000029, /* U+000029 */ + 0x00002a, /* U+00002a */ + 0x00002b, /* U+00002b */ + 0x00002c, /* U+00002c */ + 0x00002d, /* U+00002d */ + 0x00002e, /* U+00002e */ + 0x00002f, /* U+00002f */ + 0x000030, /* U+000030 */ + 0x000031, /* U+000031 */ + 0x000032, /* U+000032 */ + 0x000033, /* U+000033 */ + 0x000034, /* U+000034 */ + 0x000035, /* U+000035 */ + 0x000036, /* U+000036 */ + 0x000037, /* U+000037 */ + 0x000038, /* U+000038 */ + 0x000039, /* U+000039 */ + 0x00003a, /* U+00003a */ + 0x00003b, /* U+00003b */ + 0x00003c, /* U+00003c */ + 0x00003d, /* U+00003d */ + 0x00003e, /* U+00003e */ + 0x00003f, /* U+00003f */ + 0x000040, /* U+000040 */ + 0x000041, /* U+000041 */ + 0x000042, /* U+000042 */ + 0x000043, /* U+000043 */ + 0x000044, /* U+000044 */ + 0x000045, /* U+000045 */ + 0x000046, /* U+000046 */ + 0x000047, /* U+000047 */ + 0x000048, /* U+000048 */ + 0x000049, /* U+000049 */ + 0x00004a, /* U+00004a */ + 0x00004b, /* U+00004b */ + 0x00004c, /* U+00004c */ + 0x00004d, /* U+00004d */ + 0x00004e, /* U+00004e */ + 0x00004f, /* U+00004f */ + 0x000050, /* U+000050 */ + 0x000051, /* U+000051 */ + 0x000052, /* U+000052 */ + 0x000053, /* U+000053 */ + 0x000054, /* U+000054 */ + 0x000055, /* U+000055 */ + 0x000056, /* U+000056 */ + 0x000057, /* U+000057 */ + 0x000058, /* U+000058 */ + 0x000059, /* U+000059 */ + 0x00005a, /* U+00005a */ + 0x00005b, /* U+00005b */ + 0x00005c, /* U+00005c */ + 0x00005d, /* U+00005d */ + 0x00005e, /* U+00005e */ + 0x00005f, /* U+00005f */ + 0x000060, /* U+000060 */ + 0x000041, /* U+000061 */ + 0x000042, /* U+000062 */ + 0x000043, /* U+000063 */ + 0x000044, /* U+000064 */ + 0x000045, /* U+000065 */ + 0x000046, /* U+000066 */ + 0x000047, /* U+000067 */ + 0x000048, /* U+000068 */ + 0x000049, /* U+000069 */ + 0x00004a, /* U+00006a */ + 0x00004b, /* U+00006b */ + 0x00004c, /* U+00006c */ + 0x00004d, /* U+00006d */ + 0x00004e, /* U+00006e */ + 0x00004f, /* U+00006f */ + 0x000050, /* U+000070 */ + 0x000051, /* U+000071 */ + 0x000052, /* U+000072 */ + 0x000053, /* U+000073 */ + 0x000054, /* U+000074 */ + 0x000055, /* U+000075 */ + 0x000056, /* U+000076 */ + 0x000057, /* U+000077 */ + 0x000058, /* U+000078 */ + 0x000059, /* U+000079 */ + 0x00005a, /* U+00007a */ + 0x00007b, /* U+00007b */ + 0x00007c, /* U+00007c */ + 0x00007d, /* U+00007d */ + 0x00007e, /* U+00007e */ + 0x00007f, /* U+00007f */ + 0x00039c, /* U+0000b5 */ + 0x0000c0, /* U+0000c0 */ + 0x0000c1, /* U+0000c1 */ + 0x0000c2, /* U+0000c2 */ + 0x0000c3, /* U+0000c3 */ + 0x0000c4, /* U+0000c4 */ + 0x0000c5, /* U+0000c5 */ + 0x0000c6, /* U+0000c6 */ + 0x0000c7, /* U+0000c7 */ + 0x0000c8, /* U+0000c8 */ + 0x0000c9, /* U+0000c9 */ + 0x0000ca, /* U+0000ca */ + 0x0000cb, /* U+0000cb */ + 0x0000cc, /* U+0000cc */ + 0x0000cd, /* U+0000cd */ + 0x0000ce, /* U+0000ce */ + 0x0000cf, /* U+0000cf */ + 0x0000d0, /* U+0000d0 */ + 0x0000d1, /* U+0000d1 */ + 0x0000d2, /* U+0000d2 */ + 0x0000d3, /* U+0000d3 */ + 0x0000d4, /* U+0000d4 */ + 0x0000d5, /* U+0000d5 */ + 0x0000d6, /* U+0000d6 */ + 0x0000d8, /* U+0000d8 */ + 0x0000d9, /* U+0000d9 */ + 0x0000da, /* U+0000da */ + 0x0000db, /* U+0000db */ + 0x0000dc, /* U+0000dc */ + 0x0000dd, /* U+0000dd */ + 0x0000de, /* U+0000de */ + 0x0000df, /* U+0000df */ + 0x000178, /* U+0000ff */ + 0x000100, /* U+000100 */ + 0x000102, /* U+000102 */ + 0x000104, /* U+000104 */ + 0x000106, /* U+000106 */ + 0x000108, /* U+000108 */ + 0x00010a, /* U+00010a */ + 0x00010c, /* U+00010c */ + 0x00010e, /* U+00010e */ + 0x000110, /* U+000110 */ + 0x000112, /* U+000112 */ + 0x000114, /* U+000114 */ + 0x000116, /* U+000116 */ + 0x000118, /* U+000118 */ + 0x00011a, /* U+00011a */ + 0x00011c, /* U+00011c */ + 0x00011e, /* U+00011e */ + 0x000120, /* U+000120 */ + 0x000122, /* U+000122 */ + 0x000124, /* U+000124 */ + 0x000126, /* U+000126 */ + 0x000128, /* U+000128 */ + 0x00012a, /* U+00012a */ + 0x00012c, /* U+00012c */ + 0x00012e, /* U+00012e */ + 0x000130, /* U+000130 */ + 0x000049, /* U+000131 */ + 0x000132, /* U+000132 */ + 0x000134, /* U+000134 */ + 0x000136, /* U+000136 */ + 0x000139, /* U+000139 */ + 0x00013b, /* U+00013b */ + 0x00013d, /* U+00013d */ + 0x00013f, /* U+00013f */ + 0x000141, /* U+000141 */ + 0x000143, /* U+000143 */ + 0x000145, /* U+000145 */ + 0x000147, /* U+000147 */ + 0x000149, /* U+000149 */ + 0x00014a, /* U+00014a */ + 0x00014c, /* U+00014c */ + 0x00014e, /* U+00014e */ + 0x000150, /* U+000150 */ + 0x000152, /* U+000152 */ + 0x000154, /* U+000154 */ + 0x000156, /* U+000156 */ + 0x000158, /* U+000158 */ + 0x00015a, /* U+00015a */ + 0x00015c, /* U+00015c */ + 0x00015e, /* U+00015e */ + 0x000160, /* U+000160 */ + 0x000162, /* U+000162 */ + 0x000164, /* U+000164 */ + 0x000166, /* U+000166 */ + 0x000168, /* U+000168 */ + 0x00016a, /* U+00016a */ + 0x00016c, /* U+00016c */ + 0x00016e, /* U+00016e */ + 0x000170, /* U+000170 */ + 0x000172, /* U+000172 */ + 0x000174, /* U+000174 */ + 0x000176, /* U+000176 */ + 0x000179, /* U+000179 */ + 0x00017b, /* U+00017b */ + 0x00017d, /* U+00017d */ + 0x000053, /* U+00017f */ + 0x000243, /* U+000180 */ + 0x000181, /* U+000181 */ + 0x000182, /* U+000182 */ + 0x000184, /* U+000184 */ + 0x000186, /* U+000186 */ + 0x000187, /* U+000187 */ + 0x000189, /* U+000189 */ + 0x00018a, /* U+00018a */ + 0x00018b, /* U+00018b */ + 0x00018e, /* U+00018e */ + 0x00018f, /* U+00018f */ + 0x000190, /* U+000190 */ + 0x000191, /* U+000191 */ + 0x000193, /* U+000193 */ + 0x000194, /* U+000194 */ + 0x0001f6, /* U+000195 */ + 0x000196, /* U+000196 */ + 0x000197, /* U+000197 */ + 0x000198, /* U+000198 */ + 0x00023d, /* U+00019a */ + 0x00a7dc, /* U+00019b */ + 0x00019c, /* U+00019c */ + 0x00019d, /* U+00019d */ + 0x000220, /* U+00019e */ + 0x00019f, /* U+00019f */ + 0x0001a0, /* U+0001a0 */ + 0x0001a2, /* U+0001a2 */ + 0x0001a4, /* U+0001a4 */ + 0x0001a6, /* U+0001a6 */ + 0x0001a7, /* U+0001a7 */ + 0x0001a9, /* U+0001a9 */ + 0x0001ac, /* U+0001ac */ + 0x0001ae, /* U+0001ae */ + 0x0001af, /* U+0001af */ + 0x0001b1, /* U+0001b1 */ + 0x0001b2, /* U+0001b2 */ + 0x0001b3, /* U+0001b3 */ + 0x0001b5, /* U+0001b5 */ + 0x0001b7, /* U+0001b7 */ + 0x0001b8, /* U+0001b8 */ + 0x0001bc, /* U+0001bc */ + 0x0001f7, /* U+0001bf */ + 0x0001c5, /* U+0001c4 */ + 0x0001c8, /* U+0001c7 */ + 0x0001cb, /* U+0001ca */ + 0x0001cd, /* U+0001cd */ + 0x0001cf, /* U+0001cf */ + 0x0001d1, /* U+0001d1 */ + 0x0001d3, /* U+0001d3 */ + 0x0001d5, /* U+0001d5 */ + 0x0001d7, /* U+0001d7 */ + 0x0001d9, /* U+0001d9 */ + 0x0001db, /* U+0001db */ + 0x0001de, /* U+0001de */ + 0x0001e0, /* U+0001e0 */ + 0x0001e2, /* U+0001e2 */ + 0x0001e4, /* U+0001e4 */ + 0x0001e6, /* U+0001e6 */ + 0x0001e8, /* U+0001e8 */ + 0x0001ea, /* U+0001ea */ + 0x0001ec, /* U+0001ec */ + 0x0001ee, /* U+0001ee */ + 0x0001f0, /* U+0001f0 */ + 0x0001f2, /* U+0001f1 */ + 0x0001f4, /* U+0001f4 */ + 0x0001f8, /* U+0001f8 */ + 0x0001fa, /* U+0001fa */ + 0x0001fc, /* U+0001fc */ + 0x0001fe, /* U+0001fe */ + 0x000200, /* U+000200 */ + 0x000202, /* U+000202 */ + 0x000204, /* U+000204 */ + 0x000206, /* U+000206 */ + 0x000208, /* U+000208 */ + 0x00020a, /* U+00020a */ + 0x00020c, /* U+00020c */ + 0x00020e, /* U+00020e */ + 0x000210, /* U+000210 */ + 0x000212, /* U+000212 */ + 0x000214, /* U+000214 */ + 0x000216, /* U+000216 */ + 0x000218, /* U+000218 */ + 0x00021a, /* U+00021a */ + 0x00021c, /* U+00021c */ + 0x00021e, /* U+00021e */ + 0x000222, /* U+000222 */ + 0x000224, /* U+000224 */ + 0x000226, /* U+000226 */ + 0x000228, /* U+000228 */ + 0x00022a, /* U+00022a */ + 0x00022c, /* U+00022c */ + 0x00022e, /* U+00022e */ + 0x000230, /* U+000230 */ + 0x000232, /* U+000232 */ + 0x00023a, /* U+00023a */ + 0x00023b, /* U+00023b */ + 0x00023e, /* U+00023e */ + 0x002c7e, /* U+00023f */ + 0x002c7f, /* U+000240 */ + 0x000241, /* U+000241 */ + 0x000244, /* U+000244 */ + 0x000245, /* U+000245 */ + 0x000246, /* U+000246 */ + 0x000248, /* U+000248 */ + 0x00024a, /* U+00024a */ + 0x00024c, /* U+00024c */ + 0x00024e, /* U+00024e */ + 0x002c6f, /* U+000250 */ + 0x002c6d, /* U+000251 */ + 0x002c70, /* U+000252 */ + 0x00a7ab, /* U+00025c */ + 0x00a7ac, /* U+000261 */ + 0x00a7cb, /* U+000264 */ + 0x00a78d, /* U+000265 */ + 0x00a7aa, /* U+000266 */ + 0x00a7ae, /* U+00026a */ + 0x002c62, /* U+00026b */ + 0x00a7ad, /* U+00026c */ + 0x002c6e, /* U+000271 */ + 0x002c64, /* U+00027d */ + 0x00a7c5, /* U+000282 */ + 0x00a7b1, /* U+000287 */ + 0x00a7b2, /* U+00029d */ + 0x00a7b0, /* U+00029e */ + 0x000399, /* U+000345 */ + 0x000370, /* U+000370 */ + 0x000372, /* U+000372 */ + 0x000376, /* U+000376 */ + 0x0003fd, /* U+00037b */ + 0x0003fe, /* U+00037c */ + 0x0003ff, /* U+00037d */ + 0x00037f, /* U+00037f */ + 0x000386, /* U+000386 */ + 0x000388, /* U+000388 */ + 0x000389, /* U+000389 */ + 0x00038a, /* U+00038a */ + 0x00038c, /* U+00038c */ + 0x00038e, /* U+00038e */ + 0x00038f, /* U+00038f */ + 0x000390, /* U+000390 */ + 0x000391, /* U+000391 */ + 0x000392, /* U+000392 */ + 0x000393, /* U+000393 */ + 0x000394, /* U+000394 */ + 0x000395, /* U+000395 */ + 0x000396, /* U+000396 */ + 0x000397, /* U+000397 */ + 0x000398, /* U+000398 */ + 0x000399, /* U+000399 */ + 0x00039a, /* U+00039a */ + 0x00039b, /* U+00039b */ + 0x00039c, /* U+00039c */ + 0x00039d, /* U+00039d */ + 0x00039e, /* U+00039e */ + 0x00039f, /* U+00039f */ + 0x0003a0, /* U+0003a0 */ + 0x0003a1, /* U+0003a1 */ + 0x0003a3, /* U+0003a3 */ + 0x0003a4, /* U+0003a4 */ + 0x0003a5, /* U+0003a5 */ + 0x0003a6, /* U+0003a6 */ + 0x0003a7, /* U+0003a7 */ + 0x0003a8, /* U+0003a8 */ + 0x0003a9, /* U+0003a9 */ + 0x0003aa, /* U+0003aa */ + 0x0003ab, /* U+0003ab */ + 0x0003b0, /* U+0003b0 */ + 0x0003a3, /* U+0003c2 */ + 0x0003a3, /* U+0003c3 */ + 0x0003cf, /* U+0003cf */ + 0x000392, /* U+0003d0 */ + 0x000398, /* U+0003d1 */ + 0x0003a6, /* U+0003d5 */ + 0x0003a0, /* U+0003d6 */ + 0x0003d8, /* U+0003d8 */ + 0x0003da, /* U+0003da */ + 0x0003dc, /* U+0003dc */ + 0x0003de, /* U+0003de */ + 0x0003e0, /* U+0003e0 */ + 0x0003e2, /* U+0003e2 */ + 0x0003e4, /* U+0003e4 */ + 0x0003e6, /* U+0003e6 */ + 0x0003e8, /* U+0003e8 */ + 0x0003ea, /* U+0003ea */ + 0x0003ec, /* U+0003ec */ + 0x0003ee, /* U+0003ee */ + 0x00039a, /* U+0003f0 */ + 0x0003a1, /* U+0003f1 */ + 0x0003f9, /* U+0003f2 */ + 0x0003f4, /* U+0003f4 */ + 0x000395, /* U+0003f5 */ + 0x0003f7, /* U+0003f7 */ + 0x0003fa, /* U+0003fa */ + 0x000400, /* U+000400 */ + 0x000401, /* U+000401 */ + 0x000402, /* U+000402 */ + 0x000403, /* U+000403 */ + 0x000404, /* U+000404 */ + 0x000405, /* U+000405 */ + 0x000406, /* U+000406 */ + 0x000407, /* U+000407 */ + 0x000408, /* U+000408 */ + 0x000409, /* U+000409 */ + 0x00040a, /* U+00040a */ + 0x00040b, /* U+00040b */ + 0x00040c, /* U+00040c */ + 0x00040d, /* U+00040d */ + 0x00040e, /* U+00040e */ + 0x00040f, /* U+00040f */ + 0x000410, /* U+000410 */ + 0x000411, /* U+000411 */ + 0x000412, /* U+000412 */ + 0x000413, /* U+000413 */ + 0x000414, /* U+000414 */ + 0x000415, /* U+000415 */ + 0x000416, /* U+000416 */ + 0x000417, /* U+000417 */ + 0x000418, /* U+000418 */ + 0x000419, /* U+000419 */ + 0x00041a, /* U+00041a */ + 0x00041b, /* U+00041b */ + 0x00041c, /* U+00041c */ + 0x00041d, /* U+00041d */ + 0x00041e, /* U+00041e */ + 0x00041f, /* U+00041f */ + 0x000420, /* U+000420 */ + 0x000421, /* U+000421 */ + 0x000422, /* U+000422 */ + 0x000423, /* U+000423 */ + 0x000424, /* U+000424 */ + 0x000425, /* U+000425 */ + 0x000426, /* U+000426 */ + 0x000427, /* U+000427 */ + 0x000428, /* U+000428 */ + 0x000429, /* U+000429 */ + 0x00042a, /* U+00042a */ + 0x00042b, /* U+00042b */ + 0x00042c, /* U+00042c */ + 0x00042d, /* U+00042d */ + 0x00042e, /* U+00042e */ + 0x00042f, /* U+00042f */ + 0x000460, /* U+000460 */ + 0x000462, /* U+000462 */ + 0x000464, /* U+000464 */ + 0x000466, /* U+000466 */ + 0x000468, /* U+000468 */ + 0x00046a, /* U+00046a */ + 0x00046c, /* U+00046c */ + 0x00046e, /* U+00046e */ + 0x000470, /* U+000470 */ + 0x000472, /* U+000472 */ + 0x000474, /* U+000474 */ + 0x000476, /* U+000476 */ + 0x000478, /* U+000478 */ + 0x00047a, /* U+00047a */ + 0x00047c, /* U+00047c */ + 0x00047e, /* U+00047e */ + 0x000480, /* U+000480 */ + 0x00048a, /* U+00048a */ + 0x00048c, /* U+00048c */ + 0x00048e, /* U+00048e */ + 0x000490, /* U+000490 */ + 0x000492, /* U+000492 */ + 0x000494, /* U+000494 */ + 0x000496, /* U+000496 */ + 0x000498, /* U+000498 */ + 0x00049a, /* U+00049a */ + 0x00049c, /* U+00049c */ + 0x00049e, /* U+00049e */ + 0x0004a0, /* U+0004a0 */ + 0x0004a2, /* U+0004a2 */ + 0x0004a4, /* U+0004a4 */ + 0x0004a6, /* U+0004a6 */ + 0x0004a8, /* U+0004a8 */ + 0x0004aa, /* U+0004aa */ + 0x0004ac, /* U+0004ac */ + 0x0004ae, /* U+0004ae */ + 0x0004b0, /* U+0004b0 */ + 0x0004b2, /* U+0004b2 */ + 0x0004b4, /* U+0004b4 */ + 0x0004b6, /* U+0004b6 */ + 0x0004b8, /* U+0004b8 */ + 0x0004ba, /* U+0004ba */ + 0x0004bc, /* U+0004bc */ + 0x0004be, /* U+0004be */ + 0x0004c0, /* U+0004c0 */ + 0x0004c1, /* U+0004c1 */ + 0x0004c3, /* U+0004c3 */ + 0x0004c5, /* U+0004c5 */ + 0x0004c7, /* U+0004c7 */ + 0x0004c9, /* U+0004c9 */ + 0x0004cb, /* U+0004cb */ + 0x0004cd, /* U+0004cd */ + 0x0004d0, /* U+0004d0 */ + 0x0004d2, /* U+0004d2 */ + 0x0004d4, /* U+0004d4 */ + 0x0004d6, /* U+0004d6 */ + 0x0004d8, /* U+0004d8 */ + 0x0004da, /* U+0004da */ + 0x0004dc, /* U+0004dc */ + 0x0004de, /* U+0004de */ + 0x0004e0, /* U+0004e0 */ + 0x0004e2, /* U+0004e2 */ + 0x0004e4, /* U+0004e4 */ + 0x0004e6, /* U+0004e6 */ + 0x0004e8, /* U+0004e8 */ + 0x0004ea, /* U+0004ea */ + 0x0004ec, /* U+0004ec */ + 0x0004ee, /* U+0004ee */ + 0x0004f0, /* U+0004f0 */ + 0x0004f2, /* U+0004f2 */ + 0x0004f4, /* U+0004f4 */ + 0x0004f6, /* U+0004f6 */ + 0x0004f8, /* U+0004f8 */ + 0x0004fa, /* U+0004fa */ + 0x0004fc, /* U+0004fc */ + 0x0004fe, /* U+0004fe */ + 0x000500, /* U+000500 */ + 0x000502, /* U+000502 */ + 0x000504, /* U+000504 */ + 0x000506, /* U+000506 */ + 0x000508, /* U+000508 */ + 0x00050a, /* U+00050a */ + 0x00050c, /* U+00050c */ + 0x00050e, /* U+00050e */ + 0x000510, /* U+000510 */ + 0x000512, /* U+000512 */ + 0x000514, /* U+000514 */ + 0x000516, /* U+000516 */ + 0x000518, /* U+000518 */ + 0x00051a, /* U+00051a */ + 0x00051c, /* U+00051c */ + 0x00051e, /* U+00051e */ + 0x000520, /* U+000520 */ + 0x000522, /* U+000522 */ + 0x000524, /* U+000524 */ + 0x000526, /* U+000526 */ + 0x000528, /* U+000528 */ + 0x00052a, /* U+00052a */ + 0x00052c, /* U+00052c */ + 0x00052e, /* U+00052e */ + 0x000531, /* U+000531 */ + 0x000532, /* U+000532 */ + 0x000533, /* U+000533 */ + 0x000534, /* U+000534 */ + 0x000535, /* U+000535 */ + 0x000536, /* U+000536 */ + 0x000537, /* U+000537 */ + 0x000538, /* U+000538 */ + 0x000539, /* U+000539 */ + 0x00053a, /* U+00053a */ + 0x00053b, /* U+00053b */ + 0x00053c, /* U+00053c */ + 0x00053d, /* U+00053d */ + 0x00053e, /* U+00053e */ + 0x00053f, /* U+00053f */ + 0x000540, /* U+000540 */ + 0x000541, /* U+000541 */ + 0x000542, /* U+000542 */ + 0x000543, /* U+000543 */ + 0x000544, /* U+000544 */ + 0x000545, /* U+000545 */ + 0x000546, /* U+000546 */ + 0x000547, /* U+000547 */ + 0x000548, /* U+000548 */ + 0x000549, /* U+000549 */ + 0x00054a, /* U+00054a */ + 0x00054b, /* U+00054b */ + 0x00054c, /* U+00054c */ + 0x00054d, /* U+00054d */ + 0x00054e, /* U+00054e */ + 0x00054f, /* U+00054f */ + 0x000550, /* U+000550 */ + 0x000551, /* U+000551 */ + 0x000552, /* U+000552 */ + 0x000553, /* U+000553 */ + 0x000554, /* U+000554 */ + 0x000555, /* U+000555 */ + 0x000556, /* U+000556 */ + 0x000587, /* U+000587 */ + 0x0010a0, /* U+0010a0 */ + 0x0010a1, /* U+0010a1 */ + 0x0010a2, /* U+0010a2 */ + 0x0010a3, /* U+0010a3 */ + 0x0010a4, /* U+0010a4 */ + 0x0010a5, /* U+0010a5 */ + 0x0010a6, /* U+0010a6 */ + 0x0010a7, /* U+0010a7 */ + 0x0010a8, /* U+0010a8 */ + 0x0010a9, /* U+0010a9 */ + 0x0010aa, /* U+0010aa */ + 0x0010ab, /* U+0010ab */ + 0x0010ac, /* U+0010ac */ + 0x0010ad, /* U+0010ad */ + 0x0010ae, /* U+0010ae */ + 0x0010af, /* U+0010af */ + 0x0010b0, /* U+0010b0 */ + 0x0010b1, /* U+0010b1 */ + 0x0010b2, /* U+0010b2 */ + 0x0010b3, /* U+0010b3 */ + 0x0010b4, /* U+0010b4 */ + 0x0010b5, /* U+0010b5 */ + 0x0010b6, /* U+0010b6 */ + 0x0010b7, /* U+0010b7 */ + 0x0010b8, /* U+0010b8 */ + 0x0010b9, /* U+0010b9 */ + 0x0010ba, /* U+0010ba */ + 0x0010bb, /* U+0010bb */ + 0x0010bc, /* U+0010bc */ + 0x0010bd, /* U+0010bd */ + 0x0010be, /* U+0010be */ + 0x0010bf, /* U+0010bf */ + 0x0010c0, /* U+0010c0 */ + 0x0010c1, /* U+0010c1 */ + 0x0010c2, /* U+0010c2 */ + 0x0010c3, /* U+0010c3 */ + 0x0010c4, /* U+0010c4 */ + 0x0010c5, /* U+0010c5 */ + 0x0010c7, /* U+0010c7 */ + 0x0010cd, /* U+0010cd */ + 0x0010d0, /* U+0010d0 */ + 0x0010d1, /* U+0010d1 */ + 0x0010d2, /* U+0010d2 */ + 0x0010d3, /* U+0010d3 */ + 0x0010d4, /* U+0010d4 */ + 0x0010d5, /* U+0010d5 */ + 0x0010d6, /* U+0010d6 */ + 0x0010d7, /* U+0010d7 */ + 0x0010d8, /* U+0010d8 */ + 0x0010d9, /* U+0010d9 */ + 0x0010da, /* U+0010da */ + 0x0010db, /* U+0010db */ + 0x0010dc, /* U+0010dc */ + 0x0010dd, /* U+0010dd */ + 0x0010de, /* U+0010de */ + 0x0010df, /* U+0010df */ + 0x0010e0, /* U+0010e0 */ + 0x0010e1, /* U+0010e1 */ + 0x0010e2, /* U+0010e2 */ + 0x0010e3, /* U+0010e3 */ + 0x0010e4, /* U+0010e4 */ + 0x0010e5, /* U+0010e5 */ + 0x0010e6, /* U+0010e6 */ + 0x0010e7, /* U+0010e7 */ + 0x0010e8, /* U+0010e8 */ + 0x0010e9, /* U+0010e9 */ + 0x0010ea, /* U+0010ea */ + 0x0010eb, /* U+0010eb */ + 0x0010ec, /* U+0010ec */ + 0x0010ed, /* U+0010ed */ + 0x0010ee, /* U+0010ee */ + 0x0010ef, /* U+0010ef */ + 0x0010f0, /* U+0010f0 */ + 0x0010f1, /* U+0010f1 */ + 0x0010f2, /* U+0010f2 */ + 0x0010f3, /* U+0010f3 */ + 0x0010f4, /* U+0010f4 */ + 0x0010f5, /* U+0010f5 */ + 0x0010f6, /* U+0010f6 */ + 0x0010f7, /* U+0010f7 */ + 0x0010f8, /* U+0010f8 */ + 0x0010f9, /* U+0010f9 */ + 0x0010fa, /* U+0010fa */ + 0x0010fd, /* U+0010fd */ + 0x0010fe, /* U+0010fe */ + 0x0010ff, /* U+0010ff */ + 0x0013a0, /* U+0013a0 */ + 0x0013a1, /* U+0013a1 */ + 0x0013a2, /* U+0013a2 */ + 0x0013a3, /* U+0013a3 */ + 0x0013a4, /* U+0013a4 */ + 0x0013a5, /* U+0013a5 */ + 0x0013a6, /* U+0013a6 */ + 0x0013a7, /* U+0013a7 */ + 0x0013a8, /* U+0013a8 */ + 0x0013a9, /* U+0013a9 */ + 0x0013aa, /* U+0013aa */ + 0x0013ab, /* U+0013ab */ + 0x0013ac, /* U+0013ac */ + 0x0013ad, /* U+0013ad */ + 0x0013ae, /* U+0013ae */ + 0x0013af, /* U+0013af */ + 0x0013b0, /* U+0013b0 */ + 0x0013b1, /* U+0013b1 */ + 0x0013b2, /* U+0013b2 */ + 0x0013b3, /* U+0013b3 */ + 0x0013b4, /* U+0013b4 */ + 0x0013b5, /* U+0013b5 */ + 0x0013b6, /* U+0013b6 */ + 0x0013b7, /* U+0013b7 */ + 0x0013b8, /* U+0013b8 */ + 0x0013b9, /* U+0013b9 */ + 0x0013ba, /* U+0013ba */ + 0x0013bb, /* U+0013bb */ + 0x0013bc, /* U+0013bc */ + 0x0013bd, /* U+0013bd */ + 0x0013be, /* U+0013be */ + 0x0013bf, /* U+0013bf */ + 0x0013c0, /* U+0013c0 */ + 0x0013c1, /* U+0013c1 */ + 0x0013c2, /* U+0013c2 */ + 0x0013c3, /* U+0013c3 */ + 0x0013c4, /* U+0013c4 */ + 0x0013c5, /* U+0013c5 */ + 0x0013c6, /* U+0013c6 */ + 0x0013c7, /* U+0013c7 */ + 0x0013c8, /* U+0013c8 */ + 0x0013c9, /* U+0013c9 */ + 0x0013ca, /* U+0013ca */ + 0x0013cb, /* U+0013cb */ + 0x0013cc, /* U+0013cc */ + 0x0013cd, /* U+0013cd */ + 0x0013ce, /* U+0013ce */ + 0x0013cf, /* U+0013cf */ + 0x0013d0, /* U+0013d0 */ + 0x0013d1, /* U+0013d1 */ + 0x0013d2, /* U+0013d2 */ + 0x0013d3, /* U+0013d3 */ + 0x0013d4, /* U+0013d4 */ + 0x0013d5, /* U+0013d5 */ + 0x0013d6, /* U+0013d6 */ + 0x0013d7, /* U+0013d7 */ + 0x0013d8, /* U+0013d8 */ + 0x0013d9, /* U+0013d9 */ + 0x0013da, /* U+0013da */ + 0x0013db, /* U+0013db */ + 0x0013dc, /* U+0013dc */ + 0x0013dd, /* U+0013dd */ + 0x0013de, /* U+0013de */ + 0x0013df, /* U+0013df */ + 0x0013e0, /* U+0013e0 */ + 0x0013e1, /* U+0013e1 */ + 0x0013e2, /* U+0013e2 */ + 0x0013e3, /* U+0013e3 */ + 0x0013e4, /* U+0013e4 */ + 0x0013e5, /* U+0013e5 */ + 0x0013e6, /* U+0013e6 */ + 0x0013e7, /* U+0013e7 */ + 0x0013e8, /* U+0013e8 */ + 0x0013e9, /* U+0013e9 */ + 0x0013ea, /* U+0013ea */ + 0x0013eb, /* U+0013eb */ + 0x0013ec, /* U+0013ec */ + 0x0013ed, /* U+0013ed */ + 0x0013ee, /* U+0013ee */ + 0x0013ef, /* U+0013ef */ + 0x0013f0, /* U+0013f0 */ + 0x0013f1, /* U+0013f1 */ + 0x0013f2, /* U+0013f2 */ + 0x0013f3, /* U+0013f3 */ + 0x0013f4, /* U+0013f4 */ + 0x0013f5, /* U+0013f5 */ + 0x000412, /* U+001c80 */ + 0x000414, /* U+001c81 */ + 0x00041e, /* U+001c82 */ + 0x000421, /* U+001c83 */ + 0x000422, /* U+001c84 */ + 0x000422, /* U+001c85 */ + 0x00042a, /* U+001c86 */ + 0x000462, /* U+001c87 */ + 0x00a64a, /* U+001c88 */ + 0x001c89, /* U+001c89 */ + 0x001c90, /* U+001c90 */ + 0x001c91, /* U+001c91 */ + 0x001c92, /* U+001c92 */ + 0x001c93, /* U+001c93 */ + 0x001c94, /* U+001c94 */ + 0x001c95, /* U+001c95 */ + 0x001c96, /* U+001c96 */ + 0x001c97, /* U+001c97 */ + 0x001c98, /* U+001c98 */ + 0x001c99, /* U+001c99 */ + 0x001c9a, /* U+001c9a */ + 0x001c9b, /* U+001c9b */ + 0x001c9c, /* U+001c9c */ + 0x001c9d, /* U+001c9d */ + 0x001c9e, /* U+001c9e */ + 0x001c9f, /* U+001c9f */ + 0x001ca0, /* U+001ca0 */ + 0x001ca1, /* U+001ca1 */ + 0x001ca2, /* U+001ca2 */ + 0x001ca3, /* U+001ca3 */ + 0x001ca4, /* U+001ca4 */ + 0x001ca5, /* U+001ca5 */ + 0x001ca6, /* U+001ca6 */ + 0x001ca7, /* U+001ca7 */ + 0x001ca8, /* U+001ca8 */ + 0x001ca9, /* U+001ca9 */ + 0x001caa, /* U+001caa */ + 0x001cab, /* U+001cab */ + 0x001cac, /* U+001cac */ + 0x001cad, /* U+001cad */ + 0x001cae, /* U+001cae */ + 0x001caf, /* U+001caf */ + 0x001cb0, /* U+001cb0 */ + 0x001cb1, /* U+001cb1 */ + 0x001cb2, /* U+001cb2 */ + 0x001cb3, /* U+001cb3 */ + 0x001cb4, /* U+001cb4 */ + 0x001cb5, /* U+001cb5 */ + 0x001cb6, /* U+001cb6 */ + 0x001cb7, /* U+001cb7 */ + 0x001cb8, /* U+001cb8 */ + 0x001cb9, /* U+001cb9 */ + 0x001cba, /* U+001cba */ + 0x001cbd, /* U+001cbd */ + 0x001cbe, /* U+001cbe */ + 0x001cbf, /* U+001cbf */ + 0x00a77d, /* U+001d79 */ + 0x002c63, /* U+001d7d */ + 0x00a7c6, /* U+001d8e */ + 0x001e00, /* U+001e00 */ + 0x001e02, /* U+001e02 */ + 0x001e04, /* U+001e04 */ + 0x001e06, /* U+001e06 */ + 0x001e08, /* U+001e08 */ + 0x001e0a, /* U+001e0a */ + 0x001e0c, /* U+001e0c */ + 0x001e0e, /* U+001e0e */ + 0x001e10, /* U+001e10 */ + 0x001e12, /* U+001e12 */ + 0x001e14, /* U+001e14 */ + 0x001e16, /* U+001e16 */ + 0x001e18, /* U+001e18 */ + 0x001e1a, /* U+001e1a */ + 0x001e1c, /* U+001e1c */ + 0x001e1e, /* U+001e1e */ + 0x001e20, /* U+001e20 */ + 0x001e22, /* U+001e22 */ + 0x001e24, /* U+001e24 */ + 0x001e26, /* U+001e26 */ + 0x001e28, /* U+001e28 */ + 0x001e2a, /* U+001e2a */ + 0x001e2c, /* U+001e2c */ + 0x001e2e, /* U+001e2e */ + 0x001e30, /* U+001e30 */ + 0x001e32, /* U+001e32 */ + 0x001e34, /* U+001e34 */ + 0x001e36, /* U+001e36 */ + 0x001e38, /* U+001e38 */ + 0x001e3a, /* U+001e3a */ + 0x001e3c, /* U+001e3c */ + 0x001e3e, /* U+001e3e */ + 0x001e40, /* U+001e40 */ + 0x001e42, /* U+001e42 */ + 0x001e44, /* U+001e44 */ + 0x001e46, /* U+001e46 */ + 0x001e48, /* U+001e48 */ + 0x001e4a, /* U+001e4a */ + 0x001e4c, /* U+001e4c */ + 0x001e4e, /* U+001e4e */ + 0x001e50, /* U+001e50 */ + 0x001e52, /* U+001e52 */ + 0x001e54, /* U+001e54 */ + 0x001e56, /* U+001e56 */ + 0x001e58, /* U+001e58 */ + 0x001e5a, /* U+001e5a */ + 0x001e5c, /* U+001e5c */ + 0x001e5e, /* U+001e5e */ + 0x001e60, /* U+001e60 */ + 0x001e62, /* U+001e62 */ + 0x001e64, /* U+001e64 */ + 0x001e66, /* U+001e66 */ + 0x001e68, /* U+001e68 */ + 0x001e6a, /* U+001e6a */ + 0x001e6c, /* U+001e6c */ + 0x001e6e, /* U+001e6e */ + 0x001e70, /* U+001e70 */ + 0x001e72, /* U+001e72 */ + 0x001e74, /* U+001e74 */ + 0x001e76, /* U+001e76 */ + 0x001e78, /* U+001e78 */ + 0x001e7a, /* U+001e7a */ + 0x001e7c, /* U+001e7c */ + 0x001e7e, /* U+001e7e */ + 0x001e80, /* U+001e80 */ + 0x001e82, /* U+001e82 */ + 0x001e84, /* U+001e84 */ + 0x001e86, /* U+001e86 */ + 0x001e88, /* U+001e88 */ + 0x001e8a, /* U+001e8a */ + 0x001e8c, /* U+001e8c */ + 0x001e8e, /* U+001e8e */ + 0x001e90, /* U+001e90 */ + 0x001e92, /* U+001e92 */ + 0x001e94, /* U+001e94 */ + 0x001e96, /* U+001e96 */ + 0x001e97, /* U+001e97 */ + 0x001e98, /* U+001e98 */ + 0x001e99, /* U+001e99 */ + 0x001e9a, /* U+001e9a */ + 0x001e60, /* U+001e9b */ + 0x001e9e, /* U+001e9e */ + 0x001ea0, /* U+001ea0 */ + 0x001ea2, /* U+001ea2 */ + 0x001ea4, /* U+001ea4 */ + 0x001ea6, /* U+001ea6 */ + 0x001ea8, /* U+001ea8 */ + 0x001eaa, /* U+001eaa */ + 0x001eac, /* U+001eac */ + 0x001eae, /* U+001eae */ + 0x001eb0, /* U+001eb0 */ + 0x001eb2, /* U+001eb2 */ + 0x001eb4, /* U+001eb4 */ + 0x001eb6, /* U+001eb6 */ + 0x001eb8, /* U+001eb8 */ + 0x001eba, /* U+001eba */ + 0x001ebc, /* U+001ebc */ + 0x001ebe, /* U+001ebe */ + 0x001ec0, /* U+001ec0 */ + 0x001ec2, /* U+001ec2 */ + 0x001ec4, /* U+001ec4 */ + 0x001ec6, /* U+001ec6 */ + 0x001ec8, /* U+001ec8 */ + 0x001eca, /* U+001eca */ + 0x001ecc, /* U+001ecc */ + 0x001ece, /* U+001ece */ + 0x001ed0, /* U+001ed0 */ + 0x001ed2, /* U+001ed2 */ + 0x001ed4, /* U+001ed4 */ + 0x001ed6, /* U+001ed6 */ + 0x001ed8, /* U+001ed8 */ + 0x001eda, /* U+001eda */ + 0x001edc, /* U+001edc */ + 0x001ede, /* U+001ede */ + 0x001ee0, /* U+001ee0 */ + 0x001ee2, /* U+001ee2 */ + 0x001ee4, /* U+001ee4 */ + 0x001ee6, /* U+001ee6 */ + 0x001ee8, /* U+001ee8 */ + 0x001eea, /* U+001eea */ + 0x001eec, /* U+001eec */ + 0x001eee, /* U+001eee */ + 0x001ef0, /* U+001ef0 */ + 0x001ef2, /* U+001ef2 */ + 0x001ef4, /* U+001ef4 */ + 0x001ef6, /* U+001ef6 */ + 0x001ef8, /* U+001ef8 */ + 0x001efa, /* U+001efa */ + 0x001efc, /* U+001efc */ + 0x001efe, /* U+001efe */ + 0x001f08, /* U+001f00 */ + 0x001f09, /* U+001f01 */ + 0x001f0a, /* U+001f02 */ + 0x001f0b, /* U+001f03 */ + 0x001f0c, /* U+001f04 */ + 0x001f0d, /* U+001f05 */ + 0x001f0e, /* U+001f06 */ + 0x001f0f, /* U+001f07 */ + 0x001f18, /* U+001f10 */ + 0x001f19, /* U+001f11 */ + 0x001f1a, /* U+001f12 */ + 0x001f1b, /* U+001f13 */ + 0x001f1c, /* U+001f14 */ + 0x001f1d, /* U+001f15 */ + 0x001f28, /* U+001f20 */ + 0x001f29, /* U+001f21 */ + 0x001f2a, /* U+001f22 */ + 0x001f2b, /* U+001f23 */ + 0x001f2c, /* U+001f24 */ + 0x001f2d, /* U+001f25 */ + 0x001f2e, /* U+001f26 */ + 0x001f2f, /* U+001f27 */ + 0x001f38, /* U+001f30 */ + 0x001f39, /* U+001f31 */ + 0x001f3a, /* U+001f32 */ + 0x001f3b, /* U+001f33 */ + 0x001f3c, /* U+001f34 */ + 0x001f3d, /* U+001f35 */ + 0x001f3e, /* U+001f36 */ + 0x001f3f, /* U+001f37 */ + 0x001f48, /* U+001f40 */ + 0x001f49, /* U+001f41 */ + 0x001f4a, /* U+001f42 */ + 0x001f4b, /* U+001f43 */ + 0x001f4c, /* U+001f44 */ + 0x001f4d, /* U+001f45 */ + 0x001f50, /* U+001f50 */ + 0x001f59, /* U+001f51 */ + 0x001f52, /* U+001f52 */ + 0x001f5b, /* U+001f53 */ + 0x001f54, /* U+001f54 */ + 0x001f5d, /* U+001f55 */ + 0x001f56, /* U+001f56 */ + 0x001f5f, /* U+001f57 */ + 0x001f68, /* U+001f60 */ + 0x001f69, /* U+001f61 */ + 0x001f6a, /* U+001f62 */ + 0x001f6b, /* U+001f63 */ + 0x001f6c, /* U+001f64 */ + 0x001f6d, /* U+001f65 */ + 0x001f6e, /* U+001f66 */ + 0x001f6f, /* U+001f67 */ + 0x001fba, /* U+001f70 */ + 0x001fbb, /* U+001f71 */ + 0x001fc8, /* U+001f72 */ + 0x001fc9, /* U+001f73 */ + 0x001fca, /* U+001f74 */ + 0x001fcb, /* U+001f75 */ + 0x001fda, /* U+001f76 */ + 0x001fdb, /* U+001f77 */ + 0x001ff8, /* U+001f78 */ + 0x001ff9, /* U+001f79 */ + 0x001fea, /* U+001f7a */ + 0x001feb, /* U+001f7b */ + 0x001ffa, /* U+001f7c */ + 0x001ffb, /* U+001f7d */ + 0x001f88, /* U+001f80 */ + 0x001f89, /* U+001f81 */ + 0x001f8a, /* U+001f82 */ + 0x001f8b, /* U+001f83 */ + 0x001f8c, /* U+001f84 */ + 0x001f8d, /* U+001f85 */ + 0x001f8e, /* U+001f86 */ + 0x001f8f, /* U+001f87 */ + 0x001f88, /* U+001f88 */ + 0x001f89, /* U+001f89 */ + 0x001f8a, /* U+001f8a */ + 0x001f8b, /* U+001f8b */ + 0x001f8c, /* U+001f8c */ + 0x001f8d, /* U+001f8d */ + 0x001f8e, /* U+001f8e */ + 0x001f8f, /* U+001f8f */ + 0x001f98, /* U+001f90 */ + 0x001f99, /* U+001f91 */ + 0x001f9a, /* U+001f92 */ + 0x001f9b, /* U+001f93 */ + 0x001f9c, /* U+001f94 */ + 0x001f9d, /* U+001f95 */ + 0x001f9e, /* U+001f96 */ + 0x001f9f, /* U+001f97 */ + 0x001f98, /* U+001f98 */ + 0x001f99, /* U+001f99 */ + 0x001f9a, /* U+001f9a */ + 0x001f9b, /* U+001f9b */ + 0x001f9c, /* U+001f9c */ + 0x001f9d, /* U+001f9d */ + 0x001f9e, /* U+001f9e */ + 0x001f9f, /* U+001f9f */ + 0x001fa8, /* U+001fa0 */ + 0x001fa9, /* U+001fa1 */ + 0x001faa, /* U+001fa2 */ + 0x001fab, /* U+001fa3 */ + 0x001fac, /* U+001fa4 */ + 0x001fad, /* U+001fa5 */ + 0x001fae, /* U+001fa6 */ + 0x001faf, /* U+001fa7 */ + 0x001fa8, /* U+001fa8 */ + 0x001fa9, /* U+001fa9 */ + 0x001faa, /* U+001faa */ + 0x001fab, /* U+001fab */ + 0x001fac, /* U+001fac */ + 0x001fad, /* U+001fad */ + 0x001fae, /* U+001fae */ + 0x001faf, /* U+001faf */ + 0x001fb8, /* U+001fb0 */ + 0x001fb9, /* U+001fb1 */ + 0x001fb2, /* U+001fb2 */ + 0x001fbc, /* U+001fb3 */ + 0x001fb4, /* U+001fb4 */ + 0x001fb6, /* U+001fb6 */ + 0x001fb7, /* U+001fb7 */ + 0x001fbc, /* U+001fbc */ + 0x000399, /* U+001fbe */ + 0x001fc2, /* U+001fc2 */ + 0x001fcc, /* U+001fc3 */ + 0x001fc4, /* U+001fc4 */ + 0x001fc6, /* U+001fc6 */ + 0x001fc7, /* U+001fc7 */ + 0x001fcc, /* U+001fcc */ + 0x001fd8, /* U+001fd0 */ + 0x001fd9, /* U+001fd1 */ + 0x001fd2, /* U+001fd2 */ + 0x001fd3, /* U+001fd3 */ + 0x001fd6, /* U+001fd6 */ + 0x001fd7, /* U+001fd7 */ + 0x001fe8, /* U+001fe0 */ + 0x001fe9, /* U+001fe1 */ + 0x001fe2, /* U+001fe2 */ + 0x001fe3, /* U+001fe3 */ + 0x001fe4, /* U+001fe4 */ + 0x001fec, /* U+001fe5 */ + 0x001fe6, /* U+001fe6 */ + 0x001fe7, /* U+001fe7 */ + 0x001ff2, /* U+001ff2 */ + 0x001ffc, /* U+001ff3 */ + 0x001ff4, /* U+001ff4 */ + 0x001ff6, /* U+001ff6 */ + 0x001ff7, /* U+001ff7 */ + 0x001ffc, /* U+001ffc */ + 0x002126, /* U+002126 */ + 0x00212a, /* U+00212a */ + 0x00212b, /* U+00212b */ + 0x002132, /* U+002132 */ + 0x002160, /* U+002160 */ + 0x002161, /* U+002161 */ + 0x002162, /* U+002162 */ + 0x002163, /* U+002163 */ + 0x002164, /* U+002164 */ + 0x002165, /* U+002165 */ + 0x002166, /* U+002166 */ + 0x002167, /* U+002167 */ + 0x002168, /* U+002168 */ + 0x002169, /* U+002169 */ + 0x00216a, /* U+00216a */ + 0x00216b, /* U+00216b */ + 0x00216c, /* U+00216c */ + 0x00216d, /* U+00216d */ + 0x00216e, /* U+00216e */ + 0x00216f, /* U+00216f */ + 0x002183, /* U+002183 */ + 0x0024b6, /* U+0024b6 */ + 0x0024b7, /* U+0024b7 */ + 0x0024b8, /* U+0024b8 */ + 0x0024b9, /* U+0024b9 */ + 0x0024ba, /* U+0024ba */ + 0x0024bb, /* U+0024bb */ + 0x0024bc, /* U+0024bc */ + 0x0024bd, /* U+0024bd */ + 0x0024be, /* U+0024be */ + 0x0024bf, /* U+0024bf */ + 0x0024c0, /* U+0024c0 */ + 0x0024c1, /* U+0024c1 */ + 0x0024c2, /* U+0024c2 */ + 0x0024c3, /* U+0024c3 */ + 0x0024c4, /* U+0024c4 */ + 0x0024c5, /* U+0024c5 */ + 0x0024c6, /* U+0024c6 */ + 0x0024c7, /* U+0024c7 */ + 0x0024c8, /* U+0024c8 */ + 0x0024c9, /* U+0024c9 */ + 0x0024ca, /* U+0024ca */ + 0x0024cb, /* U+0024cb */ + 0x0024cc, /* U+0024cc */ + 0x0024cd, /* U+0024cd */ + 0x0024ce, /* U+0024ce */ + 0x0024cf, /* U+0024cf */ + 0x002c00, /* U+002c00 */ + 0x002c01, /* U+002c01 */ + 0x002c02, /* U+002c02 */ + 0x002c03, /* U+002c03 */ + 0x002c04, /* U+002c04 */ + 0x002c05, /* U+002c05 */ + 0x002c06, /* U+002c06 */ + 0x002c07, /* U+002c07 */ + 0x002c08, /* U+002c08 */ + 0x002c09, /* U+002c09 */ + 0x002c0a, /* U+002c0a */ + 0x002c0b, /* U+002c0b */ + 0x002c0c, /* U+002c0c */ + 0x002c0d, /* U+002c0d */ + 0x002c0e, /* U+002c0e */ + 0x002c0f, /* U+002c0f */ + 0x002c10, /* U+002c10 */ + 0x002c11, /* U+002c11 */ + 0x002c12, /* U+002c12 */ + 0x002c13, /* U+002c13 */ + 0x002c14, /* U+002c14 */ + 0x002c15, /* U+002c15 */ + 0x002c16, /* U+002c16 */ + 0x002c17, /* U+002c17 */ + 0x002c18, /* U+002c18 */ + 0x002c19, /* U+002c19 */ + 0x002c1a, /* U+002c1a */ + 0x002c1b, /* U+002c1b */ + 0x002c1c, /* U+002c1c */ + 0x002c1d, /* U+002c1d */ + 0x002c1e, /* U+002c1e */ + 0x002c1f, /* U+002c1f */ + 0x002c20, /* U+002c20 */ + 0x002c21, /* U+002c21 */ + 0x002c22, /* U+002c22 */ + 0x002c23, /* U+002c23 */ + 0x002c24, /* U+002c24 */ + 0x002c25, /* U+002c25 */ + 0x002c26, /* U+002c26 */ + 0x002c27, /* U+002c27 */ + 0x002c28, /* U+002c28 */ + 0x002c29, /* U+002c29 */ + 0x002c2a, /* U+002c2a */ + 0x002c2b, /* U+002c2b */ + 0x002c2c, /* U+002c2c */ + 0x002c2d, /* U+002c2d */ + 0x002c2e, /* U+002c2e */ + 0x002c2f, /* U+002c2f */ + 0x002c60, /* U+002c60 */ + 0x002c67, /* U+002c67 */ + 0x002c69, /* U+002c69 */ + 0x002c6b, /* U+002c6b */ + 0x002c72, /* U+002c72 */ + 0x002c75, /* U+002c75 */ + 0x002c80, /* U+002c80 */ + 0x002c82, /* U+002c82 */ + 0x002c84, /* U+002c84 */ + 0x002c86, /* U+002c86 */ + 0x002c88, /* U+002c88 */ + 0x002c8a, /* U+002c8a */ + 0x002c8c, /* U+002c8c */ + 0x002c8e, /* U+002c8e */ + 0x002c90, /* U+002c90 */ + 0x002c92, /* U+002c92 */ + 0x002c94, /* U+002c94 */ + 0x002c96, /* U+002c96 */ + 0x002c98, /* U+002c98 */ + 0x002c9a, /* U+002c9a */ + 0x002c9c, /* U+002c9c */ + 0x002c9e, /* U+002c9e */ + 0x002ca0, /* U+002ca0 */ + 0x002ca2, /* U+002ca2 */ + 0x002ca4, /* U+002ca4 */ + 0x002ca6, /* U+002ca6 */ + 0x002ca8, /* U+002ca8 */ + 0x002caa, /* U+002caa */ + 0x002cac, /* U+002cac */ + 0x002cae, /* U+002cae */ + 0x002cb0, /* U+002cb0 */ + 0x002cb2, /* U+002cb2 */ + 0x002cb4, /* U+002cb4 */ + 0x002cb6, /* U+002cb6 */ + 0x002cb8, /* U+002cb8 */ + 0x002cba, /* U+002cba */ + 0x002cbc, /* U+002cbc */ + 0x002cbe, /* U+002cbe */ + 0x002cc0, /* U+002cc0 */ + 0x002cc2, /* U+002cc2 */ + 0x002cc4, /* U+002cc4 */ + 0x002cc6, /* U+002cc6 */ + 0x002cc8, /* U+002cc8 */ + 0x002cca, /* U+002cca */ + 0x002ccc, /* U+002ccc */ + 0x002cce, /* U+002cce */ + 0x002cd0, /* U+002cd0 */ + 0x002cd2, /* U+002cd2 */ + 0x002cd4, /* U+002cd4 */ + 0x002cd6, /* U+002cd6 */ + 0x002cd8, /* U+002cd8 */ + 0x002cda, /* U+002cda */ + 0x002cdc, /* U+002cdc */ + 0x002cde, /* U+002cde */ + 0x002ce0, /* U+002ce0 */ + 0x002ce2, /* U+002ce2 */ + 0x002ceb, /* U+002ceb */ + 0x002ced, /* U+002ced */ + 0x002cf2, /* U+002cf2 */ + 0x00a640, /* U+00a640 */ + 0x00a642, /* U+00a642 */ + 0x00a644, /* U+00a644 */ + 0x00a646, /* U+00a646 */ + 0x00a648, /* U+00a648 */ + 0x00a64a, /* U+00a64a */ + 0x00a64c, /* U+00a64c */ + 0x00a64e, /* U+00a64e */ + 0x00a650, /* U+00a650 */ + 0x00a652, /* U+00a652 */ + 0x00a654, /* U+00a654 */ + 0x00a656, /* U+00a656 */ + 0x00a658, /* U+00a658 */ + 0x00a65a, /* U+00a65a */ + 0x00a65c, /* U+00a65c */ + 0x00a65e, /* U+00a65e */ + 0x00a660, /* U+00a660 */ + 0x00a662, /* U+00a662 */ + 0x00a664, /* U+00a664 */ + 0x00a666, /* U+00a666 */ + 0x00a668, /* U+00a668 */ + 0x00a66a, /* U+00a66a */ + 0x00a66c, /* U+00a66c */ + 0x00a680, /* U+00a680 */ + 0x00a682, /* U+00a682 */ + 0x00a684, /* U+00a684 */ + 0x00a686, /* U+00a686 */ + 0x00a688, /* U+00a688 */ + 0x00a68a, /* U+00a68a */ + 0x00a68c, /* U+00a68c */ + 0x00a68e, /* U+00a68e */ + 0x00a690, /* U+00a690 */ + 0x00a692, /* U+00a692 */ + 0x00a694, /* U+00a694 */ + 0x00a696, /* U+00a696 */ + 0x00a698, /* U+00a698 */ + 0x00a69a, /* U+00a69a */ + 0x00a722, /* U+00a722 */ + 0x00a724, /* U+00a724 */ + 0x00a726, /* U+00a726 */ + 0x00a728, /* U+00a728 */ + 0x00a72a, /* U+00a72a */ + 0x00a72c, /* U+00a72c */ + 0x00a72e, /* U+00a72e */ + 0x00a732, /* U+00a732 */ + 0x00a734, /* U+00a734 */ + 0x00a736, /* U+00a736 */ + 0x00a738, /* U+00a738 */ + 0x00a73a, /* U+00a73a */ + 0x00a73c, /* U+00a73c */ + 0x00a73e, /* U+00a73e */ + 0x00a740, /* U+00a740 */ + 0x00a742, /* U+00a742 */ + 0x00a744, /* U+00a744 */ + 0x00a746, /* U+00a746 */ + 0x00a748, /* U+00a748 */ + 0x00a74a, /* U+00a74a */ + 0x00a74c, /* U+00a74c */ + 0x00a74e, /* U+00a74e */ + 0x00a750, /* U+00a750 */ + 0x00a752, /* U+00a752 */ + 0x00a754, /* U+00a754 */ + 0x00a756, /* U+00a756 */ + 0x00a758, /* U+00a758 */ + 0x00a75a, /* U+00a75a */ + 0x00a75c, /* U+00a75c */ + 0x00a75e, /* U+00a75e */ + 0x00a760, /* U+00a760 */ + 0x00a762, /* U+00a762 */ + 0x00a764, /* U+00a764 */ + 0x00a766, /* U+00a766 */ + 0x00a768, /* U+00a768 */ + 0x00a76a, /* U+00a76a */ + 0x00a76c, /* U+00a76c */ + 0x00a76e, /* U+00a76e */ + 0x00a779, /* U+00a779 */ + 0x00a77b, /* U+00a77b */ + 0x00a77e, /* U+00a77e */ + 0x00a780, /* U+00a780 */ + 0x00a782, /* U+00a782 */ + 0x00a784, /* U+00a784 */ + 0x00a786, /* U+00a786 */ + 0x00a78b, /* U+00a78b */ + 0x00a790, /* U+00a790 */ + 0x00a792, /* U+00a792 */ + 0x00a7c4, /* U+00a794 */ + 0x00a796, /* U+00a796 */ + 0x00a798, /* U+00a798 */ + 0x00a79a, /* U+00a79a */ + 0x00a79c, /* U+00a79c */ + 0x00a79e, /* U+00a79e */ + 0x00a7a0, /* U+00a7a0 */ + 0x00a7a2, /* U+00a7a2 */ + 0x00a7a4, /* U+00a7a4 */ + 0x00a7a6, /* U+00a7a6 */ + 0x00a7a8, /* U+00a7a8 */ + 0x00a7b3, /* U+00a7b3 */ + 0x00a7b4, /* U+00a7b4 */ + 0x00a7b6, /* U+00a7b6 */ + 0x00a7b8, /* U+00a7b8 */ + 0x00a7ba, /* U+00a7ba */ + 0x00a7bc, /* U+00a7bc */ + 0x00a7be, /* U+00a7be */ + 0x00a7c0, /* U+00a7c0 */ + 0x00a7c2, /* U+00a7c2 */ + 0x00a7c7, /* U+00a7c7 */ + 0x00a7c9, /* U+00a7c9 */ + 0x00a7cc, /* U+00a7cc */ + 0x00a7d0, /* U+00a7d0 */ + 0x00a7d6, /* U+00a7d6 */ + 0x00a7d8, /* U+00a7d8 */ + 0x00a7da, /* U+00a7da */ + 0x00a7f5, /* U+00a7f5 */ + 0x00fb00, /* U+00fb00 */ + 0x00fb01, /* U+00fb01 */ + 0x00fb02, /* U+00fb02 */ + 0x00fb03, /* U+00fb03 */ + 0x00fb04, /* U+00fb04 */ + 0x00fb05, /* U+00fb05 */ + 0x00fb06, /* U+00fb06 */ + 0x00fb13, /* U+00fb13 */ + 0x00fb14, /* U+00fb14 */ + 0x00fb15, /* U+00fb15 */ + 0x00fb16, /* U+00fb16 */ + 0x00fb17, /* U+00fb17 */ + 0x00ff21, /* U+00ff21 */ + 0x00ff22, /* U+00ff22 */ + 0x00ff23, /* U+00ff23 */ + 0x00ff24, /* U+00ff24 */ + 0x00ff25, /* U+00ff25 */ + 0x00ff26, /* U+00ff26 */ + 0x00ff27, /* U+00ff27 */ + 0x00ff28, /* U+00ff28 */ + 0x00ff29, /* U+00ff29 */ + 0x00ff2a, /* U+00ff2a */ + 0x00ff2b, /* U+00ff2b */ + 0x00ff2c, /* U+00ff2c */ + 0x00ff2d, /* U+00ff2d */ + 0x00ff2e, /* U+00ff2e */ + 0x00ff2f, /* U+00ff2f */ + 0x00ff30, /* U+00ff30 */ + 0x00ff31, /* U+00ff31 */ + 0x00ff32, /* U+00ff32 */ + 0x00ff33, /* U+00ff33 */ + 0x00ff34, /* U+00ff34 */ + 0x00ff35, /* U+00ff35 */ + 0x00ff36, /* U+00ff36 */ + 0x00ff37, /* U+00ff37 */ + 0x00ff38, /* U+00ff38 */ + 0x00ff39, /* U+00ff39 */ + 0x00ff3a, /* U+00ff3a */ + 0x010400, /* U+010400 */ + 0x010401, /* U+010401 */ + 0x010402, /* U+010402 */ + 0x010403, /* U+010403 */ + 0x010404, /* U+010404 */ + 0x010405, /* U+010405 */ + 0x010406, /* U+010406 */ + 0x010407, /* U+010407 */ + 0x010408, /* U+010408 */ + 0x010409, /* U+010409 */ + 0x01040a, /* U+01040a */ + 0x01040b, /* U+01040b */ + 0x01040c, /* U+01040c */ + 0x01040d, /* U+01040d */ + 0x01040e, /* U+01040e */ + 0x01040f, /* U+01040f */ + 0x010410, /* U+010410 */ + 0x010411, /* U+010411 */ + 0x010412, /* U+010412 */ + 0x010413, /* U+010413 */ + 0x010414, /* U+010414 */ + 0x010415, /* U+010415 */ + 0x010416, /* U+010416 */ + 0x010417, /* U+010417 */ + 0x010418, /* U+010418 */ + 0x010419, /* U+010419 */ + 0x01041a, /* U+01041a */ + 0x01041b, /* U+01041b */ + 0x01041c, /* U+01041c */ + 0x01041d, /* U+01041d */ + 0x01041e, /* U+01041e */ + 0x01041f, /* U+01041f */ + 0x010420, /* U+010420 */ + 0x010421, /* U+010421 */ + 0x010422, /* U+010422 */ + 0x010423, /* U+010423 */ + 0x010424, /* U+010424 */ + 0x010425, /* U+010425 */ + 0x010426, /* U+010426 */ + 0x010427, /* U+010427 */ + 0x0104b0, /* U+0104b0 */ + 0x0104b1, /* U+0104b1 */ + 0x0104b2, /* U+0104b2 */ + 0x0104b3, /* U+0104b3 */ + 0x0104b4, /* U+0104b4 */ + 0x0104b5, /* U+0104b5 */ + 0x0104b6, /* U+0104b6 */ + 0x0104b7, /* U+0104b7 */ + 0x0104b8, /* U+0104b8 */ + 0x0104b9, /* U+0104b9 */ + 0x0104ba, /* U+0104ba */ + 0x0104bb, /* U+0104bb */ + 0x0104bc, /* U+0104bc */ + 0x0104bd, /* U+0104bd */ + 0x0104be, /* U+0104be */ + 0x0104bf, /* U+0104bf */ + 0x0104c0, /* U+0104c0 */ + 0x0104c1, /* U+0104c1 */ + 0x0104c2, /* U+0104c2 */ + 0x0104c3, /* U+0104c3 */ + 0x0104c4, /* U+0104c4 */ + 0x0104c5, /* U+0104c5 */ + 0x0104c6, /* U+0104c6 */ + 0x0104c7, /* U+0104c7 */ + 0x0104c8, /* U+0104c8 */ + 0x0104c9, /* U+0104c9 */ + 0x0104ca, /* U+0104ca */ + 0x0104cb, /* U+0104cb */ + 0x0104cc, /* U+0104cc */ + 0x0104cd, /* U+0104cd */ + 0x0104ce, /* U+0104ce */ + 0x0104cf, /* U+0104cf */ + 0x0104d0, /* U+0104d0 */ + 0x0104d1, /* U+0104d1 */ + 0x0104d2, /* U+0104d2 */ + 0x0104d3, /* U+0104d3 */ + 0x010570, /* U+010570 */ + 0x010571, /* U+010571 */ + 0x010572, /* U+010572 */ + 0x010573, /* U+010573 */ + 0x010574, /* U+010574 */ + 0x010575, /* U+010575 */ + 0x010576, /* U+010576 */ + 0x010577, /* U+010577 */ + 0x010578, /* U+010578 */ + 0x010579, /* U+010579 */ + 0x01057a, /* U+01057a */ + 0x01057c, /* U+01057c */ + 0x01057d, /* U+01057d */ + 0x01057e, /* U+01057e */ + 0x01057f, /* U+01057f */ + 0x010580, /* U+010580 */ + 0x010581, /* U+010581 */ + 0x010582, /* U+010582 */ + 0x010583, /* U+010583 */ + 0x010584, /* U+010584 */ + 0x010585, /* U+010585 */ + 0x010586, /* U+010586 */ + 0x010587, /* U+010587 */ + 0x010588, /* U+010588 */ + 0x010589, /* U+010589 */ + 0x01058a, /* U+01058a */ + 0x01058c, /* U+01058c */ + 0x01058d, /* U+01058d */ + 0x01058e, /* U+01058e */ + 0x01058f, /* U+01058f */ + 0x010590, /* U+010590 */ + 0x010591, /* U+010591 */ + 0x010592, /* U+010592 */ + 0x010594, /* U+010594 */ + 0x010595, /* U+010595 */ + 0x010c80, /* U+010c80 */ + 0x010c81, /* U+010c81 */ + 0x010c82, /* U+010c82 */ + 0x010c83, /* U+010c83 */ + 0x010c84, /* U+010c84 */ + 0x010c85, /* U+010c85 */ + 0x010c86, /* U+010c86 */ + 0x010c87, /* U+010c87 */ + 0x010c88, /* U+010c88 */ + 0x010c89, /* U+010c89 */ + 0x010c8a, /* U+010c8a */ + 0x010c8b, /* U+010c8b */ + 0x010c8c, /* U+010c8c */ + 0x010c8d, /* U+010c8d */ + 0x010c8e, /* U+010c8e */ + 0x010c8f, /* U+010c8f */ + 0x010c90, /* U+010c90 */ + 0x010c91, /* U+010c91 */ + 0x010c92, /* U+010c92 */ + 0x010c93, /* U+010c93 */ + 0x010c94, /* U+010c94 */ + 0x010c95, /* U+010c95 */ + 0x010c96, /* U+010c96 */ + 0x010c97, /* U+010c97 */ + 0x010c98, /* U+010c98 */ + 0x010c99, /* U+010c99 */ + 0x010c9a, /* U+010c9a */ + 0x010c9b, /* U+010c9b */ + 0x010c9c, /* U+010c9c */ + 0x010c9d, /* U+010c9d */ + 0x010c9e, /* U+010c9e */ + 0x010c9f, /* U+010c9f */ + 0x010ca0, /* U+010ca0 */ + 0x010ca1, /* U+010ca1 */ + 0x010ca2, /* U+010ca2 */ + 0x010ca3, /* U+010ca3 */ + 0x010ca4, /* U+010ca4 */ + 0x010ca5, /* U+010ca5 */ + 0x010ca6, /* U+010ca6 */ + 0x010ca7, /* U+010ca7 */ + 0x010ca8, /* U+010ca8 */ + 0x010ca9, /* U+010ca9 */ + 0x010caa, /* U+010caa */ + 0x010cab, /* U+010cab */ + 0x010cac, /* U+010cac */ + 0x010cad, /* U+010cad */ + 0x010cae, /* U+010cae */ + 0x010caf, /* U+010caf */ + 0x010cb0, /* U+010cb0 */ + 0x010cb1, /* U+010cb1 */ + 0x010cb2, /* U+010cb2 */ + 0x010d50, /* U+010d50 */ + 0x010d51, /* U+010d51 */ + 0x010d52, /* U+010d52 */ + 0x010d53, /* U+010d53 */ + 0x010d54, /* U+010d54 */ + 0x010d55, /* U+010d55 */ + 0x010d56, /* U+010d56 */ + 0x010d57, /* U+010d57 */ + 0x010d58, /* U+010d58 */ + 0x010d59, /* U+010d59 */ + 0x010d5a, /* U+010d5a */ + 0x010d5b, /* U+010d5b */ + 0x010d5c, /* U+010d5c */ + 0x010d5d, /* U+010d5d */ + 0x010d5e, /* U+010d5e */ + 0x010d5f, /* U+010d5f */ + 0x010d60, /* U+010d60 */ + 0x010d61, /* U+010d61 */ + 0x010d62, /* U+010d62 */ + 0x010d63, /* U+010d63 */ + 0x010d64, /* U+010d64 */ + 0x010d65, /* U+010d65 */ + 0x0118a0, /* U+0118a0 */ + 0x0118a1, /* U+0118a1 */ + 0x0118a2, /* U+0118a2 */ + 0x0118a3, /* U+0118a3 */ + 0x0118a4, /* U+0118a4 */ + 0x0118a5, /* U+0118a5 */ + 0x0118a6, /* U+0118a6 */ + 0x0118a7, /* U+0118a7 */ + 0x0118a8, /* U+0118a8 */ + 0x0118a9, /* U+0118a9 */ + 0x0118aa, /* U+0118aa */ + 0x0118ab, /* U+0118ab */ + 0x0118ac, /* U+0118ac */ + 0x0118ad, /* U+0118ad */ + 0x0118ae, /* U+0118ae */ + 0x0118af, /* U+0118af */ + 0x0118b0, /* U+0118b0 */ + 0x0118b1, /* U+0118b1 */ + 0x0118b2, /* U+0118b2 */ + 0x0118b3, /* U+0118b3 */ + 0x0118b4, /* U+0118b4 */ + 0x0118b5, /* U+0118b5 */ + 0x0118b6, /* U+0118b6 */ + 0x0118b7, /* U+0118b7 */ + 0x0118b8, /* U+0118b8 */ + 0x0118b9, /* U+0118b9 */ + 0x0118ba, /* U+0118ba */ + 0x0118bb, /* U+0118bb */ + 0x0118bc, /* U+0118bc */ + 0x0118bd, /* U+0118bd */ + 0x0118be, /* U+0118be */ + 0x0118bf, /* U+0118bf */ + 0x016e40, /* U+016e40 */ + 0x016e41, /* U+016e41 */ + 0x016e42, /* U+016e42 */ + 0x016e43, /* U+016e43 */ + 0x016e44, /* U+016e44 */ + 0x016e45, /* U+016e45 */ + 0x016e46, /* U+016e46 */ + 0x016e47, /* U+016e47 */ + 0x016e48, /* U+016e48 */ + 0x016e49, /* U+016e49 */ + 0x016e4a, /* U+016e4a */ + 0x016e4b, /* U+016e4b */ + 0x016e4c, /* U+016e4c */ + 0x016e4d, /* U+016e4d */ + 0x016e4e, /* U+016e4e */ + 0x016e4f, /* U+016e4f */ + 0x016e50, /* U+016e50 */ + 0x016e51, /* U+016e51 */ + 0x016e52, /* U+016e52 */ + 0x016e53, /* U+016e53 */ + 0x016e54, /* U+016e54 */ + 0x016e55, /* U+016e55 */ + 0x016e56, /* U+016e56 */ + 0x016e57, /* U+016e57 */ + 0x016e58, /* U+016e58 */ + 0x016e59, /* U+016e59 */ + 0x016e5a, /* U+016e5a */ + 0x016e5b, /* U+016e5b */ + 0x016e5c, /* U+016e5c */ + 0x016e5d, /* U+016e5d */ + 0x016e5e, /* U+016e5e */ + 0x016e5f, /* U+016e5f */ + 0x01e900, /* U+01e900 */ + 0x01e901, /* U+01e901 */ + 0x01e902, /* U+01e902 */ + 0x01e903, /* U+01e903 */ + 0x01e904, /* U+01e904 */ + 0x01e905, /* U+01e905 */ + 0x01e906, /* U+01e906 */ + 0x01e907, /* U+01e907 */ + 0x01e908, /* U+01e908 */ + 0x01e909, /* U+01e909 */ + 0x01e90a, /* U+01e90a */ + 0x01e90b, /* U+01e90b */ + 0x01e90c, /* U+01e90c */ + 0x01e90d, /* U+01e90d */ + 0x01e90e, /* U+01e90e */ + 0x01e90f, /* U+01e90f */ + 0x01e910, /* U+01e910 */ + 0x01e911, /* U+01e911 */ + 0x01e912, /* U+01e912 */ + 0x01e913, /* U+01e913 */ + 0x01e914, /* U+01e914 */ + 0x01e915, /* U+01e915 */ + 0x01e916, /* U+01e916 */ + 0x01e917, /* U+01e917 */ + 0x01e918, /* U+01e918 */ + 0x01e919, /* U+01e919 */ + 0x01e91a, /* U+01e91a */ + 0x01e91b, /* U+01e91b */ + 0x01e91c, /* U+01e91c */ + 0x01e91d, /* U+01e91d */ + 0x01e91e, /* U+01e91e */ + 0x01e91f, /* U+01e91f */ + 0x01e920, /* U+01e920 */ + 0x01e921, /* U+01e921 */ + +}; + +/* + * The entry case_map_upper[case_index(codepoint)] is the mapping for the + * given codepoint. + */ +static const pg_wchar case_map_upper[1704] = +{ + 0x000000, /* reserved */ + 0x000000, /* U+000000 */ + 0x000001, /* U+000001 */ + 0x000002, /* U+000002 */ + 0x000003, /* U+000003 */ + 0x000004, /* U+000004 */ + 0x000005, /* U+000005 */ + 0x000006, /* U+000006 */ + 0x000007, /* U+000007 */ + 0x000008, /* U+000008 */ + 0x000009, /* U+000009 */ + 0x00000a, /* U+00000a */ + 0x00000b, /* U+00000b */ + 0x00000c, /* U+00000c */ + 0x00000d, /* U+00000d */ + 0x00000e, /* U+00000e */ + 0x00000f, /* U+00000f */ + 0x000010, /* U+000010 */ + 0x000011, /* U+000011 */ + 0x000012, /* U+000012 */ + 0x000013, /* U+000013 */ + 0x000014, /* U+000014 */ + 0x000015, /* U+000015 */ + 0x000016, /* U+000016 */ + 0x000017, /* U+000017 */ + 0x000018, /* U+000018 */ + 0x000019, /* U+000019 */ + 0x00001a, /* U+00001a */ + 0x00001b, /* U+00001b */ + 0x00001c, /* U+00001c */ + 0x00001d, /* U+00001d */ + 0x00001e, /* U+00001e */ + 0x00001f, /* U+00001f */ + 0x000020, /* U+000020 */ + 0x000021, /* U+000021 */ + 0x000022, /* U+000022 */ + 0x000023, /* U+000023 */ + 0x000024, /* U+000024 */ + 0x000025, /* U+000025 */ + 0x000026, /* U+000026 */ + 0x000027, /* U+000027 */ + 0x000028, /* U+000028 */ + 0x000029, /* U+000029 */ + 0x00002a, /* U+00002a */ + 0x00002b, /* U+00002b */ + 0x00002c, /* U+00002c */ + 0x00002d, /* U+00002d */ + 0x00002e, /* U+00002e */ + 0x00002f, /* U+00002f */ + 0x000030, /* U+000030 */ + 0x000031, /* U+000031 */ + 0x000032, /* U+000032 */ + 0x000033, /* U+000033 */ + 0x000034, /* U+000034 */ + 0x000035, /* U+000035 */ + 0x000036, /* U+000036 */ + 0x000037, /* U+000037 */ + 0x000038, /* U+000038 */ + 0x000039, /* U+000039 */ + 0x00003a, /* U+00003a */ + 0x00003b, /* U+00003b */ + 0x00003c, /* U+00003c */ + 0x00003d, /* U+00003d */ + 0x00003e, /* U+00003e */ + 0x00003f, /* U+00003f */ + 0x000040, /* U+000040 */ + 0x000041, /* U+000041 */ + 0x000042, /* U+000042 */ + 0x000043, /* U+000043 */ + 0x000044, /* U+000044 */ + 0x000045, /* U+000045 */ + 0x000046, /* U+000046 */ + 0x000047, /* U+000047 */ + 0x000048, /* U+000048 */ + 0x000049, /* U+000049 */ + 0x00004a, /* U+00004a */ + 0x00004b, /* U+00004b */ + 0x00004c, /* U+00004c */ + 0x00004d, /* U+00004d */ + 0x00004e, /* U+00004e */ + 0x00004f, /* U+00004f */ + 0x000050, /* U+000050 */ + 0x000051, /* U+000051 */ + 0x000052, /* U+000052 */ + 0x000053, /* U+000053 */ + 0x000054, /* U+000054 */ + 0x000055, /* U+000055 */ + 0x000056, /* U+000056 */ + 0x000057, /* U+000057 */ + 0x000058, /* U+000058 */ + 0x000059, /* U+000059 */ + 0x00005a, /* U+00005a */ + 0x00005b, /* U+00005b */ + 0x00005c, /* U+00005c */ + 0x00005d, /* U+00005d */ + 0x00005e, /* U+00005e */ + 0x00005f, /* U+00005f */ + 0x000060, /* U+000060 */ + 0x000041, /* U+000061 */ + 0x000042, /* U+000062 */ + 0x000043, /* U+000063 */ + 0x000044, /* U+000064 */ + 0x000045, /* U+000065 */ + 0x000046, /* U+000066 */ + 0x000047, /* U+000067 */ + 0x000048, /* U+000068 */ + 0x000049, /* U+000069 */ + 0x00004a, /* U+00006a */ + 0x00004b, /* U+00006b */ + 0x00004c, /* U+00006c */ + 0x00004d, /* U+00006d */ + 0x00004e, /* U+00006e */ + 0x00004f, /* U+00006f */ + 0x000050, /* U+000070 */ + 0x000051, /* U+000071 */ + 0x000052, /* U+000072 */ + 0x000053, /* U+000073 */ + 0x000054, /* U+000074 */ + 0x000055, /* U+000075 */ + 0x000056, /* U+000076 */ + 0x000057, /* U+000077 */ + 0x000058, /* U+000078 */ + 0x000059, /* U+000079 */ + 0x00005a, /* U+00007a */ + 0x00007b, /* U+00007b */ + 0x00007c, /* U+00007c */ + 0x00007d, /* U+00007d */ + 0x00007e, /* U+00007e */ + 0x00007f, /* U+00007f */ + 0x00039c, /* U+0000b5 */ + 0x0000c0, /* U+0000c0 */ + 0x0000c1, /* U+0000c1 */ + 0x0000c2, /* U+0000c2 */ + 0x0000c3, /* U+0000c3 */ + 0x0000c4, /* U+0000c4 */ + 0x0000c5, /* U+0000c5 */ + 0x0000c6, /* U+0000c6 */ + 0x0000c7, /* U+0000c7 */ + 0x0000c8, /* U+0000c8 */ + 0x0000c9, /* U+0000c9 */ + 0x0000ca, /* U+0000ca */ + 0x0000cb, /* U+0000cb */ + 0x0000cc, /* U+0000cc */ + 0x0000cd, /* U+0000cd */ + 0x0000ce, /* U+0000ce */ + 0x0000cf, /* U+0000cf */ + 0x0000d0, /* U+0000d0 */ + 0x0000d1, /* U+0000d1 */ + 0x0000d2, /* U+0000d2 */ + 0x0000d3, /* U+0000d3 */ + 0x0000d4, /* U+0000d4 */ + 0x0000d5, /* U+0000d5 */ + 0x0000d6, /* U+0000d6 */ + 0x0000d8, /* U+0000d8 */ + 0x0000d9, /* U+0000d9 */ + 0x0000da, /* U+0000da */ + 0x0000db, /* U+0000db */ + 0x0000dc, /* U+0000dc */ + 0x0000dd, /* U+0000dd */ + 0x0000de, /* U+0000de */ + 0x0000df, /* U+0000df */ + 0x000178, /* U+0000ff */ + 0x000100, /* U+000100 */ + 0x000102, /* U+000102 */ + 0x000104, /* U+000104 */ + 0x000106, /* U+000106 */ + 0x000108, /* U+000108 */ + 0x00010a, /* U+00010a */ + 0x00010c, /* U+00010c */ + 0x00010e, /* U+00010e */ + 0x000110, /* U+000110 */ + 0x000112, /* U+000112 */ + 0x000114, /* U+000114 */ + 0x000116, /* U+000116 */ + 0x000118, /* U+000118 */ + 0x00011a, /* U+00011a */ + 0x00011c, /* U+00011c */ + 0x00011e, /* U+00011e */ + 0x000120, /* U+000120 */ + 0x000122, /* U+000122 */ + 0x000124, /* U+000124 */ + 0x000126, /* U+000126 */ + 0x000128, /* U+000128 */ + 0x00012a, /* U+00012a */ + 0x00012c, /* U+00012c */ + 0x00012e, /* U+00012e */ + 0x000130, /* U+000130 */ + 0x000049, /* U+000131 */ + 0x000132, /* U+000132 */ + 0x000134, /* U+000134 */ + 0x000136, /* U+000136 */ + 0x000139, /* U+000139 */ + 0x00013b, /* U+00013b */ + 0x00013d, /* U+00013d */ + 0x00013f, /* U+00013f */ + 0x000141, /* U+000141 */ + 0x000143, /* U+000143 */ + 0x000145, /* U+000145 */ + 0x000147, /* U+000147 */ + 0x000149, /* U+000149 */ + 0x00014a, /* U+00014a */ + 0x00014c, /* U+00014c */ + 0x00014e, /* U+00014e */ + 0x000150, /* U+000150 */ + 0x000152, /* U+000152 */ + 0x000154, /* U+000154 */ + 0x000156, /* U+000156 */ + 0x000158, /* U+000158 */ + 0x00015a, /* U+00015a */ + 0x00015c, /* U+00015c */ + 0x00015e, /* U+00015e */ + 0x000160, /* U+000160 */ + 0x000162, /* U+000162 */ + 0x000164, /* U+000164 */ + 0x000166, /* U+000166 */ + 0x000168, /* U+000168 */ + 0x00016a, /* U+00016a */ + 0x00016c, /* U+00016c */ + 0x00016e, /* U+00016e */ + 0x000170, /* U+000170 */ + 0x000172, /* U+000172 */ + 0x000174, /* U+000174 */ + 0x000176, /* U+000176 */ + 0x000179, /* U+000179 */ + 0x00017b, /* U+00017b */ + 0x00017d, /* U+00017d */ + 0x000053, /* U+00017f */ + 0x000243, /* U+000180 */ + 0x000181, /* U+000181 */ + 0x000182, /* U+000182 */ + 0x000184, /* U+000184 */ + 0x000186, /* U+000186 */ + 0x000187, /* U+000187 */ + 0x000189, /* U+000189 */ + 0x00018a, /* U+00018a */ + 0x00018b, /* U+00018b */ + 0x00018e, /* U+00018e */ + 0x00018f, /* U+00018f */ + 0x000190, /* U+000190 */ + 0x000191, /* U+000191 */ + 0x000193, /* U+000193 */ + 0x000194, /* U+000194 */ + 0x0001f6, /* U+000195 */ + 0x000196, /* U+000196 */ + 0x000197, /* U+000197 */ + 0x000198, /* U+000198 */ + 0x00023d, /* U+00019a */ + 0x00a7dc, /* U+00019b */ + 0x00019c, /* U+00019c */ + 0x00019d, /* U+00019d */ + 0x000220, /* U+00019e */ + 0x00019f, /* U+00019f */ + 0x0001a0, /* U+0001a0 */ + 0x0001a2, /* U+0001a2 */ + 0x0001a4, /* U+0001a4 */ + 0x0001a6, /* U+0001a6 */ + 0x0001a7, /* U+0001a7 */ + 0x0001a9, /* U+0001a9 */ + 0x0001ac, /* U+0001ac */ + 0x0001ae, /* U+0001ae */ + 0x0001af, /* U+0001af */ + 0x0001b1, /* U+0001b1 */ + 0x0001b2, /* U+0001b2 */ + 0x0001b3, /* U+0001b3 */ + 0x0001b5, /* U+0001b5 */ + 0x0001b7, /* U+0001b7 */ + 0x0001b8, /* U+0001b8 */ + 0x0001bc, /* U+0001bc */ + 0x0001f7, /* U+0001bf */ + 0x0001c4, /* U+0001c4 */ + 0x0001c7, /* U+0001c7 */ + 0x0001ca, /* U+0001ca */ + 0x0001cd, /* U+0001cd */ + 0x0001cf, /* U+0001cf */ + 0x0001d1, /* U+0001d1 */ + 0x0001d3, /* U+0001d3 */ + 0x0001d5, /* U+0001d5 */ + 0x0001d7, /* U+0001d7 */ + 0x0001d9, /* U+0001d9 */ + 0x0001db, /* U+0001db */ + 0x0001de, /* U+0001de */ + 0x0001e0, /* U+0001e0 */ + 0x0001e2, /* U+0001e2 */ + 0x0001e4, /* U+0001e4 */ + 0x0001e6, /* U+0001e6 */ + 0x0001e8, /* U+0001e8 */ + 0x0001ea, /* U+0001ea */ + 0x0001ec, /* U+0001ec */ + 0x0001ee, /* U+0001ee */ + 0x0001f0, /* U+0001f0 */ + 0x0001f1, /* U+0001f1 */ + 0x0001f4, /* U+0001f4 */ + 0x0001f8, /* U+0001f8 */ + 0x0001fa, /* U+0001fa */ + 0x0001fc, /* U+0001fc */ + 0x0001fe, /* U+0001fe */ + 0x000200, /* U+000200 */ + 0x000202, /* U+000202 */ + 0x000204, /* U+000204 */ + 0x000206, /* U+000206 */ + 0x000208, /* U+000208 */ + 0x00020a, /* U+00020a */ + 0x00020c, /* U+00020c */ + 0x00020e, /* U+00020e */ + 0x000210, /* U+000210 */ + 0x000212, /* U+000212 */ + 0x000214, /* U+000214 */ + 0x000216, /* U+000216 */ + 0x000218, /* U+000218 */ + 0x00021a, /* U+00021a */ + 0x00021c, /* U+00021c */ + 0x00021e, /* U+00021e */ + 0x000222, /* U+000222 */ + 0x000224, /* U+000224 */ + 0x000226, /* U+000226 */ + 0x000228, /* U+000228 */ + 0x00022a, /* U+00022a */ + 0x00022c, /* U+00022c */ + 0x00022e, /* U+00022e */ + 0x000230, /* U+000230 */ + 0x000232, /* U+000232 */ + 0x00023a, /* U+00023a */ + 0x00023b, /* U+00023b */ + 0x00023e, /* U+00023e */ + 0x002c7e, /* U+00023f */ + 0x002c7f, /* U+000240 */ + 0x000241, /* U+000241 */ + 0x000244, /* U+000244 */ + 0x000245, /* U+000245 */ + 0x000246, /* U+000246 */ + 0x000248, /* U+000248 */ + 0x00024a, /* U+00024a */ + 0x00024c, /* U+00024c */ + 0x00024e, /* U+00024e */ + 0x002c6f, /* U+000250 */ + 0x002c6d, /* U+000251 */ + 0x002c70, /* U+000252 */ + 0x00a7ab, /* U+00025c */ + 0x00a7ac, /* U+000261 */ + 0x00a7cb, /* U+000264 */ + 0x00a78d, /* U+000265 */ + 0x00a7aa, /* U+000266 */ + 0x00a7ae, /* U+00026a */ + 0x002c62, /* U+00026b */ + 0x00a7ad, /* U+00026c */ + 0x002c6e, /* U+000271 */ + 0x002c64, /* U+00027d */ + 0x00a7c5, /* U+000282 */ + 0x00a7b1, /* U+000287 */ + 0x00a7b2, /* U+00029d */ + 0x00a7b0, /* U+00029e */ + 0x000399, /* U+000345 */ + 0x000370, /* U+000370 */ + 0x000372, /* U+000372 */ + 0x000376, /* U+000376 */ + 0x0003fd, /* U+00037b */ + 0x0003fe, /* U+00037c */ + 0x0003ff, /* U+00037d */ + 0x00037f, /* U+00037f */ + 0x000386, /* U+000386 */ + 0x000388, /* U+000388 */ + 0x000389, /* U+000389 */ + 0x00038a, /* U+00038a */ + 0x00038c, /* U+00038c */ + 0x00038e, /* U+00038e */ + 0x00038f, /* U+00038f */ + 0x000390, /* U+000390 */ + 0x000391, /* U+000391 */ + 0x000392, /* U+000392 */ + 0x000393, /* U+000393 */ + 0x000394, /* U+000394 */ + 0x000395, /* U+000395 */ + 0x000396, /* U+000396 */ + 0x000397, /* U+000397 */ + 0x000398, /* U+000398 */ + 0x000399, /* U+000399 */ + 0x00039a, /* U+00039a */ + 0x00039b, /* U+00039b */ + 0x00039c, /* U+00039c */ + 0x00039d, /* U+00039d */ + 0x00039e, /* U+00039e */ + 0x00039f, /* U+00039f */ + 0x0003a0, /* U+0003a0 */ + 0x0003a1, /* U+0003a1 */ + 0x0003a3, /* U+0003a3 */ + 0x0003a4, /* U+0003a4 */ + 0x0003a5, /* U+0003a5 */ + 0x0003a6, /* U+0003a6 */ + 0x0003a7, /* U+0003a7 */ + 0x0003a8, /* U+0003a8 */ + 0x0003a9, /* U+0003a9 */ + 0x0003aa, /* U+0003aa */ + 0x0003ab, /* U+0003ab */ + 0x0003b0, /* U+0003b0 */ + 0x0003a3, /* U+0003c2 */ + 0x0003a3, /* U+0003c3 */ + 0x0003cf, /* U+0003cf */ + 0x000392, /* U+0003d0 */ + 0x000398, /* U+0003d1 */ + 0x0003a6, /* U+0003d5 */ + 0x0003a0, /* U+0003d6 */ + 0x0003d8, /* U+0003d8 */ + 0x0003da, /* U+0003da */ + 0x0003dc, /* U+0003dc */ + 0x0003de, /* U+0003de */ + 0x0003e0, /* U+0003e0 */ + 0x0003e2, /* U+0003e2 */ + 0x0003e4, /* U+0003e4 */ + 0x0003e6, /* U+0003e6 */ + 0x0003e8, /* U+0003e8 */ + 0x0003ea, /* U+0003ea */ + 0x0003ec, /* U+0003ec */ + 0x0003ee, /* U+0003ee */ + 0x00039a, /* U+0003f0 */ + 0x0003a1, /* U+0003f1 */ + 0x0003f9, /* U+0003f2 */ + 0x0003f4, /* U+0003f4 */ + 0x000395, /* U+0003f5 */ + 0x0003f7, /* U+0003f7 */ + 0x0003fa, /* U+0003fa */ + 0x000400, /* U+000400 */ + 0x000401, /* U+000401 */ + 0x000402, /* U+000402 */ + 0x000403, /* U+000403 */ + 0x000404, /* U+000404 */ + 0x000405, /* U+000405 */ + 0x000406, /* U+000406 */ + 0x000407, /* U+000407 */ + 0x000408, /* U+000408 */ + 0x000409, /* U+000409 */ + 0x00040a, /* U+00040a */ + 0x00040b, /* U+00040b */ + 0x00040c, /* U+00040c */ + 0x00040d, /* U+00040d */ + 0x00040e, /* U+00040e */ + 0x00040f, /* U+00040f */ + 0x000410, /* U+000410 */ + 0x000411, /* U+000411 */ + 0x000412, /* U+000412 */ + 0x000413, /* U+000413 */ + 0x000414, /* U+000414 */ + 0x000415, /* U+000415 */ + 0x000416, /* U+000416 */ + 0x000417, /* U+000417 */ + 0x000418, /* U+000418 */ + 0x000419, /* U+000419 */ + 0x00041a, /* U+00041a */ + 0x00041b, /* U+00041b */ + 0x00041c, /* U+00041c */ + 0x00041d, /* U+00041d */ + 0x00041e, /* U+00041e */ + 0x00041f, /* U+00041f */ + 0x000420, /* U+000420 */ + 0x000421, /* U+000421 */ + 0x000422, /* U+000422 */ + 0x000423, /* U+000423 */ + 0x000424, /* U+000424 */ + 0x000425, /* U+000425 */ + 0x000426, /* U+000426 */ + 0x000427, /* U+000427 */ + 0x000428, /* U+000428 */ + 0x000429, /* U+000429 */ + 0x00042a, /* U+00042a */ + 0x00042b, /* U+00042b */ + 0x00042c, /* U+00042c */ + 0x00042d, /* U+00042d */ + 0x00042e, /* U+00042e */ + 0x00042f, /* U+00042f */ + 0x000460, /* U+000460 */ + 0x000462, /* U+000462 */ + 0x000464, /* U+000464 */ + 0x000466, /* U+000466 */ + 0x000468, /* U+000468 */ + 0x00046a, /* U+00046a */ + 0x00046c, /* U+00046c */ + 0x00046e, /* U+00046e */ + 0x000470, /* U+000470 */ + 0x000472, /* U+000472 */ + 0x000474, /* U+000474 */ + 0x000476, /* U+000476 */ + 0x000478, /* U+000478 */ + 0x00047a, /* U+00047a */ + 0x00047c, /* U+00047c */ + 0x00047e, /* U+00047e */ + 0x000480, /* U+000480 */ + 0x00048a, /* U+00048a */ + 0x00048c, /* U+00048c */ + 0x00048e, /* U+00048e */ + 0x000490, /* U+000490 */ + 0x000492, /* U+000492 */ + 0x000494, /* U+000494 */ + 0x000496, /* U+000496 */ + 0x000498, /* U+000498 */ + 0x00049a, /* U+00049a */ + 0x00049c, /* U+00049c */ + 0x00049e, /* U+00049e */ + 0x0004a0, /* U+0004a0 */ + 0x0004a2, /* U+0004a2 */ + 0x0004a4, /* U+0004a4 */ + 0x0004a6, /* U+0004a6 */ + 0x0004a8, /* U+0004a8 */ + 0x0004aa, /* U+0004aa */ + 0x0004ac, /* U+0004ac */ + 0x0004ae, /* U+0004ae */ + 0x0004b0, /* U+0004b0 */ + 0x0004b2, /* U+0004b2 */ + 0x0004b4, /* U+0004b4 */ + 0x0004b6, /* U+0004b6 */ + 0x0004b8, /* U+0004b8 */ + 0x0004ba, /* U+0004ba */ + 0x0004bc, /* U+0004bc */ + 0x0004be, /* U+0004be */ + 0x0004c0, /* U+0004c0 */ + 0x0004c1, /* U+0004c1 */ + 0x0004c3, /* U+0004c3 */ + 0x0004c5, /* U+0004c5 */ + 0x0004c7, /* U+0004c7 */ + 0x0004c9, /* U+0004c9 */ + 0x0004cb, /* U+0004cb */ + 0x0004cd, /* U+0004cd */ + 0x0004d0, /* U+0004d0 */ + 0x0004d2, /* U+0004d2 */ + 0x0004d4, /* U+0004d4 */ + 0x0004d6, /* U+0004d6 */ + 0x0004d8, /* U+0004d8 */ + 0x0004da, /* U+0004da */ + 0x0004dc, /* U+0004dc */ + 0x0004de, /* U+0004de */ + 0x0004e0, /* U+0004e0 */ + 0x0004e2, /* U+0004e2 */ + 0x0004e4, /* U+0004e4 */ + 0x0004e6, /* U+0004e6 */ + 0x0004e8, /* U+0004e8 */ + 0x0004ea, /* U+0004ea */ + 0x0004ec, /* U+0004ec */ + 0x0004ee, /* U+0004ee */ + 0x0004f0, /* U+0004f0 */ + 0x0004f2, /* U+0004f2 */ + 0x0004f4, /* U+0004f4 */ + 0x0004f6, /* U+0004f6 */ + 0x0004f8, /* U+0004f8 */ + 0x0004fa, /* U+0004fa */ + 0x0004fc, /* U+0004fc */ + 0x0004fe, /* U+0004fe */ + 0x000500, /* U+000500 */ + 0x000502, /* U+000502 */ + 0x000504, /* U+000504 */ + 0x000506, /* U+000506 */ + 0x000508, /* U+000508 */ + 0x00050a, /* U+00050a */ + 0x00050c, /* U+00050c */ + 0x00050e, /* U+00050e */ + 0x000510, /* U+000510 */ + 0x000512, /* U+000512 */ + 0x000514, /* U+000514 */ + 0x000516, /* U+000516 */ + 0x000518, /* U+000518 */ + 0x00051a, /* U+00051a */ + 0x00051c, /* U+00051c */ + 0x00051e, /* U+00051e */ + 0x000520, /* U+000520 */ + 0x000522, /* U+000522 */ + 0x000524, /* U+000524 */ + 0x000526, /* U+000526 */ + 0x000528, /* U+000528 */ + 0x00052a, /* U+00052a */ + 0x00052c, /* U+00052c */ + 0x00052e, /* U+00052e */ + 0x000531, /* U+000531 */ + 0x000532, /* U+000532 */ + 0x000533, /* U+000533 */ + 0x000534, /* U+000534 */ + 0x000535, /* U+000535 */ + 0x000536, /* U+000536 */ + 0x000537, /* U+000537 */ + 0x000538, /* U+000538 */ + 0x000539, /* U+000539 */ + 0x00053a, /* U+00053a */ + 0x00053b, /* U+00053b */ + 0x00053c, /* U+00053c */ + 0x00053d, /* U+00053d */ + 0x00053e, /* U+00053e */ + 0x00053f, /* U+00053f */ + 0x000540, /* U+000540 */ + 0x000541, /* U+000541 */ + 0x000542, /* U+000542 */ + 0x000543, /* U+000543 */ + 0x000544, /* U+000544 */ + 0x000545, /* U+000545 */ + 0x000546, /* U+000546 */ + 0x000547, /* U+000547 */ + 0x000548, /* U+000548 */ + 0x000549, /* U+000549 */ + 0x00054a, /* U+00054a */ + 0x00054b, /* U+00054b */ + 0x00054c, /* U+00054c */ + 0x00054d, /* U+00054d */ + 0x00054e, /* U+00054e */ + 0x00054f, /* U+00054f */ + 0x000550, /* U+000550 */ + 0x000551, /* U+000551 */ + 0x000552, /* U+000552 */ + 0x000553, /* U+000553 */ + 0x000554, /* U+000554 */ + 0x000555, /* U+000555 */ + 0x000556, /* U+000556 */ + 0x000587, /* U+000587 */ + 0x0010a0, /* U+0010a0 */ + 0x0010a1, /* U+0010a1 */ + 0x0010a2, /* U+0010a2 */ + 0x0010a3, /* U+0010a3 */ + 0x0010a4, /* U+0010a4 */ + 0x0010a5, /* U+0010a5 */ + 0x0010a6, /* U+0010a6 */ + 0x0010a7, /* U+0010a7 */ + 0x0010a8, /* U+0010a8 */ + 0x0010a9, /* U+0010a9 */ + 0x0010aa, /* U+0010aa */ + 0x0010ab, /* U+0010ab */ + 0x0010ac, /* U+0010ac */ + 0x0010ad, /* U+0010ad */ + 0x0010ae, /* U+0010ae */ + 0x0010af, /* U+0010af */ + 0x0010b0, /* U+0010b0 */ + 0x0010b1, /* U+0010b1 */ + 0x0010b2, /* U+0010b2 */ + 0x0010b3, /* U+0010b3 */ + 0x0010b4, /* U+0010b4 */ + 0x0010b5, /* U+0010b5 */ + 0x0010b6, /* U+0010b6 */ + 0x0010b7, /* U+0010b7 */ + 0x0010b8, /* U+0010b8 */ + 0x0010b9, /* U+0010b9 */ + 0x0010ba, /* U+0010ba */ + 0x0010bb, /* U+0010bb */ + 0x0010bc, /* U+0010bc */ + 0x0010bd, /* U+0010bd */ + 0x0010be, /* U+0010be */ + 0x0010bf, /* U+0010bf */ + 0x0010c0, /* U+0010c0 */ + 0x0010c1, /* U+0010c1 */ + 0x0010c2, /* U+0010c2 */ + 0x0010c3, /* U+0010c3 */ + 0x0010c4, /* U+0010c4 */ + 0x0010c5, /* U+0010c5 */ + 0x0010c7, /* U+0010c7 */ + 0x0010cd, /* U+0010cd */ + 0x001c90, /* U+0010d0 */ + 0x001c91, /* U+0010d1 */ + 0x001c92, /* U+0010d2 */ + 0x001c93, /* U+0010d3 */ + 0x001c94, /* U+0010d4 */ + 0x001c95, /* U+0010d5 */ + 0x001c96, /* U+0010d6 */ + 0x001c97, /* U+0010d7 */ + 0x001c98, /* U+0010d8 */ + 0x001c99, /* U+0010d9 */ + 0x001c9a, /* U+0010da */ + 0x001c9b, /* U+0010db */ + 0x001c9c, /* U+0010dc */ + 0x001c9d, /* U+0010dd */ + 0x001c9e, /* U+0010de */ + 0x001c9f, /* U+0010df */ + 0x001ca0, /* U+0010e0 */ + 0x001ca1, /* U+0010e1 */ + 0x001ca2, /* U+0010e2 */ + 0x001ca3, /* U+0010e3 */ + 0x001ca4, /* U+0010e4 */ + 0x001ca5, /* U+0010e5 */ + 0x001ca6, /* U+0010e6 */ + 0x001ca7, /* U+0010e7 */ + 0x001ca8, /* U+0010e8 */ + 0x001ca9, /* U+0010e9 */ + 0x001caa, /* U+0010ea */ + 0x001cab, /* U+0010eb */ + 0x001cac, /* U+0010ec */ + 0x001cad, /* U+0010ed */ + 0x001cae, /* U+0010ee */ + 0x001caf, /* U+0010ef */ + 0x001cb0, /* U+0010f0 */ + 0x001cb1, /* U+0010f1 */ + 0x001cb2, /* U+0010f2 */ + 0x001cb3, /* U+0010f3 */ + 0x001cb4, /* U+0010f4 */ + 0x001cb5, /* U+0010f5 */ + 0x001cb6, /* U+0010f6 */ + 0x001cb7, /* U+0010f7 */ + 0x001cb8, /* U+0010f8 */ + 0x001cb9, /* U+0010f9 */ + 0x001cba, /* U+0010fa */ + 0x001cbd, /* U+0010fd */ + 0x001cbe, /* U+0010fe */ + 0x001cbf, /* U+0010ff */ + 0x0013a0, /* U+0013a0 */ + 0x0013a1, /* U+0013a1 */ + 0x0013a2, /* U+0013a2 */ + 0x0013a3, /* U+0013a3 */ + 0x0013a4, /* U+0013a4 */ + 0x0013a5, /* U+0013a5 */ + 0x0013a6, /* U+0013a6 */ + 0x0013a7, /* U+0013a7 */ + 0x0013a8, /* U+0013a8 */ + 0x0013a9, /* U+0013a9 */ + 0x0013aa, /* U+0013aa */ + 0x0013ab, /* U+0013ab */ + 0x0013ac, /* U+0013ac */ + 0x0013ad, /* U+0013ad */ + 0x0013ae, /* U+0013ae */ + 0x0013af, /* U+0013af */ + 0x0013b0, /* U+0013b0 */ + 0x0013b1, /* U+0013b1 */ + 0x0013b2, /* U+0013b2 */ + 0x0013b3, /* U+0013b3 */ + 0x0013b4, /* U+0013b4 */ + 0x0013b5, /* U+0013b5 */ + 0x0013b6, /* U+0013b6 */ + 0x0013b7, /* U+0013b7 */ + 0x0013b8, /* U+0013b8 */ + 0x0013b9, /* U+0013b9 */ + 0x0013ba, /* U+0013ba */ + 0x0013bb, /* U+0013bb */ + 0x0013bc, /* U+0013bc */ + 0x0013bd, /* U+0013bd */ + 0x0013be, /* U+0013be */ + 0x0013bf, /* U+0013bf */ + 0x0013c0, /* U+0013c0 */ + 0x0013c1, /* U+0013c1 */ + 0x0013c2, /* U+0013c2 */ + 0x0013c3, /* U+0013c3 */ + 0x0013c4, /* U+0013c4 */ + 0x0013c5, /* U+0013c5 */ + 0x0013c6, /* U+0013c6 */ + 0x0013c7, /* U+0013c7 */ + 0x0013c8, /* U+0013c8 */ + 0x0013c9, /* U+0013c9 */ + 0x0013ca, /* U+0013ca */ + 0x0013cb, /* U+0013cb */ + 0x0013cc, /* U+0013cc */ + 0x0013cd, /* U+0013cd */ + 0x0013ce, /* U+0013ce */ + 0x0013cf, /* U+0013cf */ + 0x0013d0, /* U+0013d0 */ + 0x0013d1, /* U+0013d1 */ + 0x0013d2, /* U+0013d2 */ + 0x0013d3, /* U+0013d3 */ + 0x0013d4, /* U+0013d4 */ + 0x0013d5, /* U+0013d5 */ + 0x0013d6, /* U+0013d6 */ + 0x0013d7, /* U+0013d7 */ + 0x0013d8, /* U+0013d8 */ + 0x0013d9, /* U+0013d9 */ + 0x0013da, /* U+0013da */ + 0x0013db, /* U+0013db */ + 0x0013dc, /* U+0013dc */ + 0x0013dd, /* U+0013dd */ + 0x0013de, /* U+0013de */ + 0x0013df, /* U+0013df */ + 0x0013e0, /* U+0013e0 */ + 0x0013e1, /* U+0013e1 */ + 0x0013e2, /* U+0013e2 */ + 0x0013e3, /* U+0013e3 */ + 0x0013e4, /* U+0013e4 */ + 0x0013e5, /* U+0013e5 */ + 0x0013e6, /* U+0013e6 */ + 0x0013e7, /* U+0013e7 */ + 0x0013e8, /* U+0013e8 */ + 0x0013e9, /* U+0013e9 */ + 0x0013ea, /* U+0013ea */ + 0x0013eb, /* U+0013eb */ + 0x0013ec, /* U+0013ec */ + 0x0013ed, /* U+0013ed */ + 0x0013ee, /* U+0013ee */ + 0x0013ef, /* U+0013ef */ + 0x0013f0, /* U+0013f0 */ + 0x0013f1, /* U+0013f1 */ + 0x0013f2, /* U+0013f2 */ + 0x0013f3, /* U+0013f3 */ + 0x0013f4, /* U+0013f4 */ + 0x0013f5, /* U+0013f5 */ + 0x000412, /* U+001c80 */ + 0x000414, /* U+001c81 */ + 0x00041e, /* U+001c82 */ + 0x000421, /* U+001c83 */ + 0x000422, /* U+001c84 */ + 0x000422, /* U+001c85 */ + 0x00042a, /* U+001c86 */ + 0x000462, /* U+001c87 */ + 0x00a64a, /* U+001c88 */ + 0x001c89, /* U+001c89 */ + 0x001c90, /* U+001c90 */ + 0x001c91, /* U+001c91 */ + 0x001c92, /* U+001c92 */ + 0x001c93, /* U+001c93 */ + 0x001c94, /* U+001c94 */ + 0x001c95, /* U+001c95 */ + 0x001c96, /* U+001c96 */ + 0x001c97, /* U+001c97 */ + 0x001c98, /* U+001c98 */ + 0x001c99, /* U+001c99 */ + 0x001c9a, /* U+001c9a */ + 0x001c9b, /* U+001c9b */ + 0x001c9c, /* U+001c9c */ + 0x001c9d, /* U+001c9d */ + 0x001c9e, /* U+001c9e */ + 0x001c9f, /* U+001c9f */ + 0x001ca0, /* U+001ca0 */ + 0x001ca1, /* U+001ca1 */ + 0x001ca2, /* U+001ca2 */ + 0x001ca3, /* U+001ca3 */ + 0x001ca4, /* U+001ca4 */ + 0x001ca5, /* U+001ca5 */ + 0x001ca6, /* U+001ca6 */ + 0x001ca7, /* U+001ca7 */ + 0x001ca8, /* U+001ca8 */ + 0x001ca9, /* U+001ca9 */ + 0x001caa, /* U+001caa */ + 0x001cab, /* U+001cab */ + 0x001cac, /* U+001cac */ + 0x001cad, /* U+001cad */ + 0x001cae, /* U+001cae */ + 0x001caf, /* U+001caf */ + 0x001cb0, /* U+001cb0 */ + 0x001cb1, /* U+001cb1 */ + 0x001cb2, /* U+001cb2 */ + 0x001cb3, /* U+001cb3 */ + 0x001cb4, /* U+001cb4 */ + 0x001cb5, /* U+001cb5 */ + 0x001cb6, /* U+001cb6 */ + 0x001cb7, /* U+001cb7 */ + 0x001cb8, /* U+001cb8 */ + 0x001cb9, /* U+001cb9 */ + 0x001cba, /* U+001cba */ + 0x001cbd, /* U+001cbd */ + 0x001cbe, /* U+001cbe */ + 0x001cbf, /* U+001cbf */ + 0x00a77d, /* U+001d79 */ + 0x002c63, /* U+001d7d */ + 0x00a7c6, /* U+001d8e */ + 0x001e00, /* U+001e00 */ + 0x001e02, /* U+001e02 */ + 0x001e04, /* U+001e04 */ + 0x001e06, /* U+001e06 */ + 0x001e08, /* U+001e08 */ + 0x001e0a, /* U+001e0a */ + 0x001e0c, /* U+001e0c */ + 0x001e0e, /* U+001e0e */ + 0x001e10, /* U+001e10 */ + 0x001e12, /* U+001e12 */ + 0x001e14, /* U+001e14 */ + 0x001e16, /* U+001e16 */ + 0x001e18, /* U+001e18 */ + 0x001e1a, /* U+001e1a */ + 0x001e1c, /* U+001e1c */ + 0x001e1e, /* U+001e1e */ + 0x001e20, /* U+001e20 */ + 0x001e22, /* U+001e22 */ + 0x001e24, /* U+001e24 */ + 0x001e26, /* U+001e26 */ + 0x001e28, /* U+001e28 */ + 0x001e2a, /* U+001e2a */ + 0x001e2c, /* U+001e2c */ + 0x001e2e, /* U+001e2e */ + 0x001e30, /* U+001e30 */ + 0x001e32, /* U+001e32 */ + 0x001e34, /* U+001e34 */ + 0x001e36, /* U+001e36 */ + 0x001e38, /* U+001e38 */ + 0x001e3a, /* U+001e3a */ + 0x001e3c, /* U+001e3c */ + 0x001e3e, /* U+001e3e */ + 0x001e40, /* U+001e40 */ + 0x001e42, /* U+001e42 */ + 0x001e44, /* U+001e44 */ + 0x001e46, /* U+001e46 */ + 0x001e48, /* U+001e48 */ + 0x001e4a, /* U+001e4a */ + 0x001e4c, /* U+001e4c */ + 0x001e4e, /* U+001e4e */ + 0x001e50, /* U+001e50 */ + 0x001e52, /* U+001e52 */ + 0x001e54, /* U+001e54 */ + 0x001e56, /* U+001e56 */ + 0x001e58, /* U+001e58 */ + 0x001e5a, /* U+001e5a */ + 0x001e5c, /* U+001e5c */ + 0x001e5e, /* U+001e5e */ + 0x001e60, /* U+001e60 */ + 0x001e62, /* U+001e62 */ + 0x001e64, /* U+001e64 */ + 0x001e66, /* U+001e66 */ + 0x001e68, /* U+001e68 */ + 0x001e6a, /* U+001e6a */ + 0x001e6c, /* U+001e6c */ + 0x001e6e, /* U+001e6e */ + 0x001e70, /* U+001e70 */ + 0x001e72, /* U+001e72 */ + 0x001e74, /* U+001e74 */ + 0x001e76, /* U+001e76 */ + 0x001e78, /* U+001e78 */ + 0x001e7a, /* U+001e7a */ + 0x001e7c, /* U+001e7c */ + 0x001e7e, /* U+001e7e */ + 0x001e80, /* U+001e80 */ + 0x001e82, /* U+001e82 */ + 0x001e84, /* U+001e84 */ + 0x001e86, /* U+001e86 */ + 0x001e88, /* U+001e88 */ + 0x001e8a, /* U+001e8a */ + 0x001e8c, /* U+001e8c */ + 0x001e8e, /* U+001e8e */ + 0x001e90, /* U+001e90 */ + 0x001e92, /* U+001e92 */ + 0x001e94, /* U+001e94 */ + 0x001e96, /* U+001e96 */ + 0x001e97, /* U+001e97 */ + 0x001e98, /* U+001e98 */ + 0x001e99, /* U+001e99 */ + 0x001e9a, /* U+001e9a */ + 0x001e60, /* U+001e9b */ + 0x001e9e, /* U+001e9e */ + 0x001ea0, /* U+001ea0 */ + 0x001ea2, /* U+001ea2 */ + 0x001ea4, /* U+001ea4 */ + 0x001ea6, /* U+001ea6 */ + 0x001ea8, /* U+001ea8 */ + 0x001eaa, /* U+001eaa */ + 0x001eac, /* U+001eac */ + 0x001eae, /* U+001eae */ + 0x001eb0, /* U+001eb0 */ + 0x001eb2, /* U+001eb2 */ + 0x001eb4, /* U+001eb4 */ + 0x001eb6, /* U+001eb6 */ + 0x001eb8, /* U+001eb8 */ + 0x001eba, /* U+001eba */ + 0x001ebc, /* U+001ebc */ + 0x001ebe, /* U+001ebe */ + 0x001ec0, /* U+001ec0 */ + 0x001ec2, /* U+001ec2 */ + 0x001ec4, /* U+001ec4 */ + 0x001ec6, /* U+001ec6 */ + 0x001ec8, /* U+001ec8 */ + 0x001eca, /* U+001eca */ + 0x001ecc, /* U+001ecc */ + 0x001ece, /* U+001ece */ + 0x001ed0, /* U+001ed0 */ + 0x001ed2, /* U+001ed2 */ + 0x001ed4, /* U+001ed4 */ + 0x001ed6, /* U+001ed6 */ + 0x001ed8, /* U+001ed8 */ + 0x001eda, /* U+001eda */ + 0x001edc, /* U+001edc */ + 0x001ede, /* U+001ede */ + 0x001ee0, /* U+001ee0 */ + 0x001ee2, /* U+001ee2 */ + 0x001ee4, /* U+001ee4 */ + 0x001ee6, /* U+001ee6 */ + 0x001ee8, /* U+001ee8 */ + 0x001eea, /* U+001eea */ + 0x001eec, /* U+001eec */ + 0x001eee, /* U+001eee */ + 0x001ef0, /* U+001ef0 */ + 0x001ef2, /* U+001ef2 */ + 0x001ef4, /* U+001ef4 */ + 0x001ef6, /* U+001ef6 */ + 0x001ef8, /* U+001ef8 */ + 0x001efa, /* U+001efa */ + 0x001efc, /* U+001efc */ + 0x001efe, /* U+001efe */ + 0x001f08, /* U+001f00 */ + 0x001f09, /* U+001f01 */ + 0x001f0a, /* U+001f02 */ + 0x001f0b, /* U+001f03 */ + 0x001f0c, /* U+001f04 */ + 0x001f0d, /* U+001f05 */ + 0x001f0e, /* U+001f06 */ + 0x001f0f, /* U+001f07 */ + 0x001f18, /* U+001f10 */ + 0x001f19, /* U+001f11 */ + 0x001f1a, /* U+001f12 */ + 0x001f1b, /* U+001f13 */ + 0x001f1c, /* U+001f14 */ + 0x001f1d, /* U+001f15 */ + 0x001f28, /* U+001f20 */ + 0x001f29, /* U+001f21 */ + 0x001f2a, /* U+001f22 */ + 0x001f2b, /* U+001f23 */ + 0x001f2c, /* U+001f24 */ + 0x001f2d, /* U+001f25 */ + 0x001f2e, /* U+001f26 */ + 0x001f2f, /* U+001f27 */ + 0x001f38, /* U+001f30 */ + 0x001f39, /* U+001f31 */ + 0x001f3a, /* U+001f32 */ + 0x001f3b, /* U+001f33 */ + 0x001f3c, /* U+001f34 */ + 0x001f3d, /* U+001f35 */ + 0x001f3e, /* U+001f36 */ + 0x001f3f, /* U+001f37 */ + 0x001f48, /* U+001f40 */ + 0x001f49, /* U+001f41 */ + 0x001f4a, /* U+001f42 */ + 0x001f4b, /* U+001f43 */ + 0x001f4c, /* U+001f44 */ + 0x001f4d, /* U+001f45 */ + 0x001f50, /* U+001f50 */ + 0x001f59, /* U+001f51 */ + 0x001f52, /* U+001f52 */ + 0x001f5b, /* U+001f53 */ + 0x001f54, /* U+001f54 */ + 0x001f5d, /* U+001f55 */ + 0x001f56, /* U+001f56 */ + 0x001f5f, /* U+001f57 */ + 0x001f68, /* U+001f60 */ + 0x001f69, /* U+001f61 */ + 0x001f6a, /* U+001f62 */ + 0x001f6b, /* U+001f63 */ + 0x001f6c, /* U+001f64 */ + 0x001f6d, /* U+001f65 */ + 0x001f6e, /* U+001f66 */ + 0x001f6f, /* U+001f67 */ + 0x001fba, /* U+001f70 */ + 0x001fbb, /* U+001f71 */ + 0x001fc8, /* U+001f72 */ + 0x001fc9, /* U+001f73 */ + 0x001fca, /* U+001f74 */ + 0x001fcb, /* U+001f75 */ + 0x001fda, /* U+001f76 */ + 0x001fdb, /* U+001f77 */ + 0x001ff8, /* U+001f78 */ + 0x001ff9, /* U+001f79 */ + 0x001fea, /* U+001f7a */ + 0x001feb, /* U+001f7b */ + 0x001ffa, /* U+001f7c */ + 0x001ffb, /* U+001f7d */ + 0x001f88, /* U+001f80 */ + 0x001f89, /* U+001f81 */ + 0x001f8a, /* U+001f82 */ + 0x001f8b, /* U+001f83 */ + 0x001f8c, /* U+001f84 */ + 0x001f8d, /* U+001f85 */ + 0x001f8e, /* U+001f86 */ + 0x001f8f, /* U+001f87 */ + 0x001f88, /* U+001f88 */ + 0x001f89, /* U+001f89 */ + 0x001f8a, /* U+001f8a */ + 0x001f8b, /* U+001f8b */ + 0x001f8c, /* U+001f8c */ + 0x001f8d, /* U+001f8d */ + 0x001f8e, /* U+001f8e */ + 0x001f8f, /* U+001f8f */ + 0x001f98, /* U+001f90 */ + 0x001f99, /* U+001f91 */ + 0x001f9a, /* U+001f92 */ + 0x001f9b, /* U+001f93 */ + 0x001f9c, /* U+001f94 */ + 0x001f9d, /* U+001f95 */ + 0x001f9e, /* U+001f96 */ + 0x001f9f, /* U+001f97 */ + 0x001f98, /* U+001f98 */ + 0x001f99, /* U+001f99 */ + 0x001f9a, /* U+001f9a */ + 0x001f9b, /* U+001f9b */ + 0x001f9c, /* U+001f9c */ + 0x001f9d, /* U+001f9d */ + 0x001f9e, /* U+001f9e */ + 0x001f9f, /* U+001f9f */ + 0x001fa8, /* U+001fa0 */ + 0x001fa9, /* U+001fa1 */ + 0x001faa, /* U+001fa2 */ + 0x001fab, /* U+001fa3 */ + 0x001fac, /* U+001fa4 */ + 0x001fad, /* U+001fa5 */ + 0x001fae, /* U+001fa6 */ + 0x001faf, /* U+001fa7 */ + 0x001fa8, /* U+001fa8 */ + 0x001fa9, /* U+001fa9 */ + 0x001faa, /* U+001faa */ + 0x001fab, /* U+001fab */ + 0x001fac, /* U+001fac */ + 0x001fad, /* U+001fad */ + 0x001fae, /* U+001fae */ + 0x001faf, /* U+001faf */ + 0x001fb8, /* U+001fb0 */ + 0x001fb9, /* U+001fb1 */ + 0x001fb2, /* U+001fb2 */ + 0x001fbc, /* U+001fb3 */ + 0x001fb4, /* U+001fb4 */ + 0x001fb6, /* U+001fb6 */ + 0x001fb7, /* U+001fb7 */ + 0x001fbc, /* U+001fbc */ + 0x000399, /* U+001fbe */ + 0x001fc2, /* U+001fc2 */ + 0x001fcc, /* U+001fc3 */ + 0x001fc4, /* U+001fc4 */ + 0x001fc6, /* U+001fc6 */ + 0x001fc7, /* U+001fc7 */ + 0x001fcc, /* U+001fcc */ + 0x001fd8, /* U+001fd0 */ + 0x001fd9, /* U+001fd1 */ + 0x001fd2, /* U+001fd2 */ + 0x001fd3, /* U+001fd3 */ + 0x001fd6, /* U+001fd6 */ + 0x001fd7, /* U+001fd7 */ + 0x001fe8, /* U+001fe0 */ + 0x001fe9, /* U+001fe1 */ + 0x001fe2, /* U+001fe2 */ + 0x001fe3, /* U+001fe3 */ + 0x001fe4, /* U+001fe4 */ + 0x001fec, /* U+001fe5 */ + 0x001fe6, /* U+001fe6 */ + 0x001fe7, /* U+001fe7 */ + 0x001ff2, /* U+001ff2 */ + 0x001ffc, /* U+001ff3 */ + 0x001ff4, /* U+001ff4 */ + 0x001ff6, /* U+001ff6 */ + 0x001ff7, /* U+001ff7 */ + 0x001ffc, /* U+001ffc */ + 0x002126, /* U+002126 */ + 0x00212a, /* U+00212a */ + 0x00212b, /* U+00212b */ + 0x002132, /* U+002132 */ + 0x002160, /* U+002160 */ + 0x002161, /* U+002161 */ + 0x002162, /* U+002162 */ + 0x002163, /* U+002163 */ + 0x002164, /* U+002164 */ + 0x002165, /* U+002165 */ + 0x002166, /* U+002166 */ + 0x002167, /* U+002167 */ + 0x002168, /* U+002168 */ + 0x002169, /* U+002169 */ + 0x00216a, /* U+00216a */ + 0x00216b, /* U+00216b */ + 0x00216c, /* U+00216c */ + 0x00216d, /* U+00216d */ + 0x00216e, /* U+00216e */ + 0x00216f, /* U+00216f */ + 0x002183, /* U+002183 */ + 0x0024b6, /* U+0024b6 */ + 0x0024b7, /* U+0024b7 */ + 0x0024b8, /* U+0024b8 */ + 0x0024b9, /* U+0024b9 */ + 0x0024ba, /* U+0024ba */ + 0x0024bb, /* U+0024bb */ + 0x0024bc, /* U+0024bc */ + 0x0024bd, /* U+0024bd */ + 0x0024be, /* U+0024be */ + 0x0024bf, /* U+0024bf */ + 0x0024c0, /* U+0024c0 */ + 0x0024c1, /* U+0024c1 */ + 0x0024c2, /* U+0024c2 */ + 0x0024c3, /* U+0024c3 */ + 0x0024c4, /* U+0024c4 */ + 0x0024c5, /* U+0024c5 */ + 0x0024c6, /* U+0024c6 */ + 0x0024c7, /* U+0024c7 */ + 0x0024c8, /* U+0024c8 */ + 0x0024c9, /* U+0024c9 */ + 0x0024ca, /* U+0024ca */ + 0x0024cb, /* U+0024cb */ + 0x0024cc, /* U+0024cc */ + 0x0024cd, /* U+0024cd */ + 0x0024ce, /* U+0024ce */ + 0x0024cf, /* U+0024cf */ + 0x002c00, /* U+002c00 */ + 0x002c01, /* U+002c01 */ + 0x002c02, /* U+002c02 */ + 0x002c03, /* U+002c03 */ + 0x002c04, /* U+002c04 */ + 0x002c05, /* U+002c05 */ + 0x002c06, /* U+002c06 */ + 0x002c07, /* U+002c07 */ + 0x002c08, /* U+002c08 */ + 0x002c09, /* U+002c09 */ + 0x002c0a, /* U+002c0a */ + 0x002c0b, /* U+002c0b */ + 0x002c0c, /* U+002c0c */ + 0x002c0d, /* U+002c0d */ + 0x002c0e, /* U+002c0e */ + 0x002c0f, /* U+002c0f */ + 0x002c10, /* U+002c10 */ + 0x002c11, /* U+002c11 */ + 0x002c12, /* U+002c12 */ + 0x002c13, /* U+002c13 */ + 0x002c14, /* U+002c14 */ + 0x002c15, /* U+002c15 */ + 0x002c16, /* U+002c16 */ + 0x002c17, /* U+002c17 */ + 0x002c18, /* U+002c18 */ + 0x002c19, /* U+002c19 */ + 0x002c1a, /* U+002c1a */ + 0x002c1b, /* U+002c1b */ + 0x002c1c, /* U+002c1c */ + 0x002c1d, /* U+002c1d */ + 0x002c1e, /* U+002c1e */ + 0x002c1f, /* U+002c1f */ + 0x002c20, /* U+002c20 */ + 0x002c21, /* U+002c21 */ + 0x002c22, /* U+002c22 */ + 0x002c23, /* U+002c23 */ + 0x002c24, /* U+002c24 */ + 0x002c25, /* U+002c25 */ + 0x002c26, /* U+002c26 */ + 0x002c27, /* U+002c27 */ + 0x002c28, /* U+002c28 */ + 0x002c29, /* U+002c29 */ + 0x002c2a, /* U+002c2a */ + 0x002c2b, /* U+002c2b */ + 0x002c2c, /* U+002c2c */ + 0x002c2d, /* U+002c2d */ + 0x002c2e, /* U+002c2e */ + 0x002c2f, /* U+002c2f */ + 0x002c60, /* U+002c60 */ + 0x002c67, /* U+002c67 */ + 0x002c69, /* U+002c69 */ + 0x002c6b, /* U+002c6b */ + 0x002c72, /* U+002c72 */ + 0x002c75, /* U+002c75 */ + 0x002c80, /* U+002c80 */ + 0x002c82, /* U+002c82 */ + 0x002c84, /* U+002c84 */ + 0x002c86, /* U+002c86 */ + 0x002c88, /* U+002c88 */ + 0x002c8a, /* U+002c8a */ + 0x002c8c, /* U+002c8c */ + 0x002c8e, /* U+002c8e */ + 0x002c90, /* U+002c90 */ + 0x002c92, /* U+002c92 */ + 0x002c94, /* U+002c94 */ + 0x002c96, /* U+002c96 */ + 0x002c98, /* U+002c98 */ + 0x002c9a, /* U+002c9a */ + 0x002c9c, /* U+002c9c */ + 0x002c9e, /* U+002c9e */ + 0x002ca0, /* U+002ca0 */ + 0x002ca2, /* U+002ca2 */ + 0x002ca4, /* U+002ca4 */ + 0x002ca6, /* U+002ca6 */ + 0x002ca8, /* U+002ca8 */ + 0x002caa, /* U+002caa */ + 0x002cac, /* U+002cac */ + 0x002cae, /* U+002cae */ + 0x002cb0, /* U+002cb0 */ + 0x002cb2, /* U+002cb2 */ + 0x002cb4, /* U+002cb4 */ + 0x002cb6, /* U+002cb6 */ + 0x002cb8, /* U+002cb8 */ + 0x002cba, /* U+002cba */ + 0x002cbc, /* U+002cbc */ + 0x002cbe, /* U+002cbe */ + 0x002cc0, /* U+002cc0 */ + 0x002cc2, /* U+002cc2 */ + 0x002cc4, /* U+002cc4 */ + 0x002cc6, /* U+002cc6 */ + 0x002cc8, /* U+002cc8 */ + 0x002cca, /* U+002cca */ + 0x002ccc, /* U+002ccc */ + 0x002cce, /* U+002cce */ + 0x002cd0, /* U+002cd0 */ + 0x002cd2, /* U+002cd2 */ + 0x002cd4, /* U+002cd4 */ + 0x002cd6, /* U+002cd6 */ + 0x002cd8, /* U+002cd8 */ + 0x002cda, /* U+002cda */ + 0x002cdc, /* U+002cdc */ + 0x002cde, /* U+002cde */ + 0x002ce0, /* U+002ce0 */ + 0x002ce2, /* U+002ce2 */ + 0x002ceb, /* U+002ceb */ + 0x002ced, /* U+002ced */ + 0x002cf2, /* U+002cf2 */ + 0x00a640, /* U+00a640 */ + 0x00a642, /* U+00a642 */ + 0x00a644, /* U+00a644 */ + 0x00a646, /* U+00a646 */ + 0x00a648, /* U+00a648 */ + 0x00a64a, /* U+00a64a */ + 0x00a64c, /* U+00a64c */ + 0x00a64e, /* U+00a64e */ + 0x00a650, /* U+00a650 */ + 0x00a652, /* U+00a652 */ + 0x00a654, /* U+00a654 */ + 0x00a656, /* U+00a656 */ + 0x00a658, /* U+00a658 */ + 0x00a65a, /* U+00a65a */ + 0x00a65c, /* U+00a65c */ + 0x00a65e, /* U+00a65e */ + 0x00a660, /* U+00a660 */ + 0x00a662, /* U+00a662 */ + 0x00a664, /* U+00a664 */ + 0x00a666, /* U+00a666 */ + 0x00a668, /* U+00a668 */ + 0x00a66a, /* U+00a66a */ + 0x00a66c, /* U+00a66c */ + 0x00a680, /* U+00a680 */ + 0x00a682, /* U+00a682 */ + 0x00a684, /* U+00a684 */ + 0x00a686, /* U+00a686 */ + 0x00a688, /* U+00a688 */ + 0x00a68a, /* U+00a68a */ + 0x00a68c, /* U+00a68c */ + 0x00a68e, /* U+00a68e */ + 0x00a690, /* U+00a690 */ + 0x00a692, /* U+00a692 */ + 0x00a694, /* U+00a694 */ + 0x00a696, /* U+00a696 */ + 0x00a698, /* U+00a698 */ + 0x00a69a, /* U+00a69a */ + 0x00a722, /* U+00a722 */ + 0x00a724, /* U+00a724 */ + 0x00a726, /* U+00a726 */ + 0x00a728, /* U+00a728 */ + 0x00a72a, /* U+00a72a */ + 0x00a72c, /* U+00a72c */ + 0x00a72e, /* U+00a72e */ + 0x00a732, /* U+00a732 */ + 0x00a734, /* U+00a734 */ + 0x00a736, /* U+00a736 */ + 0x00a738, /* U+00a738 */ + 0x00a73a, /* U+00a73a */ + 0x00a73c, /* U+00a73c */ + 0x00a73e, /* U+00a73e */ + 0x00a740, /* U+00a740 */ + 0x00a742, /* U+00a742 */ + 0x00a744, /* U+00a744 */ + 0x00a746, /* U+00a746 */ + 0x00a748, /* U+00a748 */ + 0x00a74a, /* U+00a74a */ + 0x00a74c, /* U+00a74c */ + 0x00a74e, /* U+00a74e */ + 0x00a750, /* U+00a750 */ + 0x00a752, /* U+00a752 */ + 0x00a754, /* U+00a754 */ + 0x00a756, /* U+00a756 */ + 0x00a758, /* U+00a758 */ + 0x00a75a, /* U+00a75a */ + 0x00a75c, /* U+00a75c */ + 0x00a75e, /* U+00a75e */ + 0x00a760, /* U+00a760 */ + 0x00a762, /* U+00a762 */ + 0x00a764, /* U+00a764 */ + 0x00a766, /* U+00a766 */ + 0x00a768, /* U+00a768 */ + 0x00a76a, /* U+00a76a */ + 0x00a76c, /* U+00a76c */ + 0x00a76e, /* U+00a76e */ + 0x00a779, /* U+00a779 */ + 0x00a77b, /* U+00a77b */ + 0x00a77e, /* U+00a77e */ + 0x00a780, /* U+00a780 */ + 0x00a782, /* U+00a782 */ + 0x00a784, /* U+00a784 */ + 0x00a786, /* U+00a786 */ + 0x00a78b, /* U+00a78b */ + 0x00a790, /* U+00a790 */ + 0x00a792, /* U+00a792 */ + 0x00a7c4, /* U+00a794 */ + 0x00a796, /* U+00a796 */ + 0x00a798, /* U+00a798 */ + 0x00a79a, /* U+00a79a */ + 0x00a79c, /* U+00a79c */ + 0x00a79e, /* U+00a79e */ + 0x00a7a0, /* U+00a7a0 */ + 0x00a7a2, /* U+00a7a2 */ + 0x00a7a4, /* U+00a7a4 */ + 0x00a7a6, /* U+00a7a6 */ + 0x00a7a8, /* U+00a7a8 */ + 0x00a7b3, /* U+00a7b3 */ + 0x00a7b4, /* U+00a7b4 */ + 0x00a7b6, /* U+00a7b6 */ + 0x00a7b8, /* U+00a7b8 */ + 0x00a7ba, /* U+00a7ba */ + 0x00a7bc, /* U+00a7bc */ + 0x00a7be, /* U+00a7be */ + 0x00a7c0, /* U+00a7c0 */ + 0x00a7c2, /* U+00a7c2 */ + 0x00a7c7, /* U+00a7c7 */ + 0x00a7c9, /* U+00a7c9 */ + 0x00a7cc, /* U+00a7cc */ + 0x00a7d0, /* U+00a7d0 */ + 0x00a7d6, /* U+00a7d6 */ + 0x00a7d8, /* U+00a7d8 */ + 0x00a7da, /* U+00a7da */ + 0x00a7f5, /* U+00a7f5 */ + 0x00fb00, /* U+00fb00 */ + 0x00fb01, /* U+00fb01 */ + 0x00fb02, /* U+00fb02 */ + 0x00fb03, /* U+00fb03 */ + 0x00fb04, /* U+00fb04 */ + 0x00fb05, /* U+00fb05 */ + 0x00fb06, /* U+00fb06 */ + 0x00fb13, /* U+00fb13 */ + 0x00fb14, /* U+00fb14 */ + 0x00fb15, /* U+00fb15 */ + 0x00fb16, /* U+00fb16 */ + 0x00fb17, /* U+00fb17 */ + 0x00ff21, /* U+00ff21 */ + 0x00ff22, /* U+00ff22 */ + 0x00ff23, /* U+00ff23 */ + 0x00ff24, /* U+00ff24 */ + 0x00ff25, /* U+00ff25 */ + 0x00ff26, /* U+00ff26 */ + 0x00ff27, /* U+00ff27 */ + 0x00ff28, /* U+00ff28 */ + 0x00ff29, /* U+00ff29 */ + 0x00ff2a, /* U+00ff2a */ + 0x00ff2b, /* U+00ff2b */ + 0x00ff2c, /* U+00ff2c */ + 0x00ff2d, /* U+00ff2d */ + 0x00ff2e, /* U+00ff2e */ + 0x00ff2f, /* U+00ff2f */ + 0x00ff30, /* U+00ff30 */ + 0x00ff31, /* U+00ff31 */ + 0x00ff32, /* U+00ff32 */ + 0x00ff33, /* U+00ff33 */ + 0x00ff34, /* U+00ff34 */ + 0x00ff35, /* U+00ff35 */ + 0x00ff36, /* U+00ff36 */ + 0x00ff37, /* U+00ff37 */ + 0x00ff38, /* U+00ff38 */ + 0x00ff39, /* U+00ff39 */ + 0x00ff3a, /* U+00ff3a */ + 0x010400, /* U+010400 */ + 0x010401, /* U+010401 */ + 0x010402, /* U+010402 */ + 0x010403, /* U+010403 */ + 0x010404, /* U+010404 */ + 0x010405, /* U+010405 */ + 0x010406, /* U+010406 */ + 0x010407, /* U+010407 */ + 0x010408, /* U+010408 */ + 0x010409, /* U+010409 */ + 0x01040a, /* U+01040a */ + 0x01040b, /* U+01040b */ + 0x01040c, /* U+01040c */ + 0x01040d, /* U+01040d */ + 0x01040e, /* U+01040e */ + 0x01040f, /* U+01040f */ + 0x010410, /* U+010410 */ + 0x010411, /* U+010411 */ + 0x010412, /* U+010412 */ + 0x010413, /* U+010413 */ + 0x010414, /* U+010414 */ + 0x010415, /* U+010415 */ + 0x010416, /* U+010416 */ + 0x010417, /* U+010417 */ + 0x010418, /* U+010418 */ + 0x010419, /* U+010419 */ + 0x01041a, /* U+01041a */ + 0x01041b, /* U+01041b */ + 0x01041c, /* U+01041c */ + 0x01041d, /* U+01041d */ + 0x01041e, /* U+01041e */ + 0x01041f, /* U+01041f */ + 0x010420, /* U+010420 */ + 0x010421, /* U+010421 */ + 0x010422, /* U+010422 */ + 0x010423, /* U+010423 */ + 0x010424, /* U+010424 */ + 0x010425, /* U+010425 */ + 0x010426, /* U+010426 */ + 0x010427, /* U+010427 */ + 0x0104b0, /* U+0104b0 */ + 0x0104b1, /* U+0104b1 */ + 0x0104b2, /* U+0104b2 */ + 0x0104b3, /* U+0104b3 */ + 0x0104b4, /* U+0104b4 */ + 0x0104b5, /* U+0104b5 */ + 0x0104b6, /* U+0104b6 */ + 0x0104b7, /* U+0104b7 */ + 0x0104b8, /* U+0104b8 */ + 0x0104b9, /* U+0104b9 */ + 0x0104ba, /* U+0104ba */ + 0x0104bb, /* U+0104bb */ + 0x0104bc, /* U+0104bc */ + 0x0104bd, /* U+0104bd */ + 0x0104be, /* U+0104be */ + 0x0104bf, /* U+0104bf */ + 0x0104c0, /* U+0104c0 */ + 0x0104c1, /* U+0104c1 */ + 0x0104c2, /* U+0104c2 */ + 0x0104c3, /* U+0104c3 */ + 0x0104c4, /* U+0104c4 */ + 0x0104c5, /* U+0104c5 */ + 0x0104c6, /* U+0104c6 */ + 0x0104c7, /* U+0104c7 */ + 0x0104c8, /* U+0104c8 */ + 0x0104c9, /* U+0104c9 */ + 0x0104ca, /* U+0104ca */ + 0x0104cb, /* U+0104cb */ + 0x0104cc, /* U+0104cc */ + 0x0104cd, /* U+0104cd */ + 0x0104ce, /* U+0104ce */ + 0x0104cf, /* U+0104cf */ + 0x0104d0, /* U+0104d0 */ + 0x0104d1, /* U+0104d1 */ + 0x0104d2, /* U+0104d2 */ + 0x0104d3, /* U+0104d3 */ + 0x010570, /* U+010570 */ + 0x010571, /* U+010571 */ + 0x010572, /* U+010572 */ + 0x010573, /* U+010573 */ + 0x010574, /* U+010574 */ + 0x010575, /* U+010575 */ + 0x010576, /* U+010576 */ + 0x010577, /* U+010577 */ + 0x010578, /* U+010578 */ + 0x010579, /* U+010579 */ + 0x01057a, /* U+01057a */ + 0x01057c, /* U+01057c */ + 0x01057d, /* U+01057d */ + 0x01057e, /* U+01057e */ + 0x01057f, /* U+01057f */ + 0x010580, /* U+010580 */ + 0x010581, /* U+010581 */ + 0x010582, /* U+010582 */ + 0x010583, /* U+010583 */ + 0x010584, /* U+010584 */ + 0x010585, /* U+010585 */ + 0x010586, /* U+010586 */ + 0x010587, /* U+010587 */ + 0x010588, /* U+010588 */ + 0x010589, /* U+010589 */ + 0x01058a, /* U+01058a */ + 0x01058c, /* U+01058c */ + 0x01058d, /* U+01058d */ + 0x01058e, /* U+01058e */ + 0x01058f, /* U+01058f */ + 0x010590, /* U+010590 */ + 0x010591, /* U+010591 */ + 0x010592, /* U+010592 */ + 0x010594, /* U+010594 */ + 0x010595, /* U+010595 */ + 0x010c80, /* U+010c80 */ + 0x010c81, /* U+010c81 */ + 0x010c82, /* U+010c82 */ + 0x010c83, /* U+010c83 */ + 0x010c84, /* U+010c84 */ + 0x010c85, /* U+010c85 */ + 0x010c86, /* U+010c86 */ + 0x010c87, /* U+010c87 */ + 0x010c88, /* U+010c88 */ + 0x010c89, /* U+010c89 */ + 0x010c8a, /* U+010c8a */ + 0x010c8b, /* U+010c8b */ + 0x010c8c, /* U+010c8c */ + 0x010c8d, /* U+010c8d */ + 0x010c8e, /* U+010c8e */ + 0x010c8f, /* U+010c8f */ + 0x010c90, /* U+010c90 */ + 0x010c91, /* U+010c91 */ + 0x010c92, /* U+010c92 */ + 0x010c93, /* U+010c93 */ + 0x010c94, /* U+010c94 */ + 0x010c95, /* U+010c95 */ + 0x010c96, /* U+010c96 */ + 0x010c97, /* U+010c97 */ + 0x010c98, /* U+010c98 */ + 0x010c99, /* U+010c99 */ + 0x010c9a, /* U+010c9a */ + 0x010c9b, /* U+010c9b */ + 0x010c9c, /* U+010c9c */ + 0x010c9d, /* U+010c9d */ + 0x010c9e, /* U+010c9e */ + 0x010c9f, /* U+010c9f */ + 0x010ca0, /* U+010ca0 */ + 0x010ca1, /* U+010ca1 */ + 0x010ca2, /* U+010ca2 */ + 0x010ca3, /* U+010ca3 */ + 0x010ca4, /* U+010ca4 */ + 0x010ca5, /* U+010ca5 */ + 0x010ca6, /* U+010ca6 */ + 0x010ca7, /* U+010ca7 */ + 0x010ca8, /* U+010ca8 */ + 0x010ca9, /* U+010ca9 */ + 0x010caa, /* U+010caa */ + 0x010cab, /* U+010cab */ + 0x010cac, /* U+010cac */ + 0x010cad, /* U+010cad */ + 0x010cae, /* U+010cae */ + 0x010caf, /* U+010caf */ + 0x010cb0, /* U+010cb0 */ + 0x010cb1, /* U+010cb1 */ + 0x010cb2, /* U+010cb2 */ + 0x010d50, /* U+010d50 */ + 0x010d51, /* U+010d51 */ + 0x010d52, /* U+010d52 */ + 0x010d53, /* U+010d53 */ + 0x010d54, /* U+010d54 */ + 0x010d55, /* U+010d55 */ + 0x010d56, /* U+010d56 */ + 0x010d57, /* U+010d57 */ + 0x010d58, /* U+010d58 */ + 0x010d59, /* U+010d59 */ + 0x010d5a, /* U+010d5a */ + 0x010d5b, /* U+010d5b */ + 0x010d5c, /* U+010d5c */ + 0x010d5d, /* U+010d5d */ + 0x010d5e, /* U+010d5e */ + 0x010d5f, /* U+010d5f */ + 0x010d60, /* U+010d60 */ + 0x010d61, /* U+010d61 */ + 0x010d62, /* U+010d62 */ + 0x010d63, /* U+010d63 */ + 0x010d64, /* U+010d64 */ + 0x010d65, /* U+010d65 */ + 0x0118a0, /* U+0118a0 */ + 0x0118a1, /* U+0118a1 */ + 0x0118a2, /* U+0118a2 */ + 0x0118a3, /* U+0118a3 */ + 0x0118a4, /* U+0118a4 */ + 0x0118a5, /* U+0118a5 */ + 0x0118a6, /* U+0118a6 */ + 0x0118a7, /* U+0118a7 */ + 0x0118a8, /* U+0118a8 */ + 0x0118a9, /* U+0118a9 */ + 0x0118aa, /* U+0118aa */ + 0x0118ab, /* U+0118ab */ + 0x0118ac, /* U+0118ac */ + 0x0118ad, /* U+0118ad */ + 0x0118ae, /* U+0118ae */ + 0x0118af, /* U+0118af */ + 0x0118b0, /* U+0118b0 */ + 0x0118b1, /* U+0118b1 */ + 0x0118b2, /* U+0118b2 */ + 0x0118b3, /* U+0118b3 */ + 0x0118b4, /* U+0118b4 */ + 0x0118b5, /* U+0118b5 */ + 0x0118b6, /* U+0118b6 */ + 0x0118b7, /* U+0118b7 */ + 0x0118b8, /* U+0118b8 */ + 0x0118b9, /* U+0118b9 */ + 0x0118ba, /* U+0118ba */ + 0x0118bb, /* U+0118bb */ + 0x0118bc, /* U+0118bc */ + 0x0118bd, /* U+0118bd */ + 0x0118be, /* U+0118be */ + 0x0118bf, /* U+0118bf */ + 0x016e40, /* U+016e40 */ + 0x016e41, /* U+016e41 */ + 0x016e42, /* U+016e42 */ + 0x016e43, /* U+016e43 */ + 0x016e44, /* U+016e44 */ + 0x016e45, /* U+016e45 */ + 0x016e46, /* U+016e46 */ + 0x016e47, /* U+016e47 */ + 0x016e48, /* U+016e48 */ + 0x016e49, /* U+016e49 */ + 0x016e4a, /* U+016e4a */ + 0x016e4b, /* U+016e4b */ + 0x016e4c, /* U+016e4c */ + 0x016e4d, /* U+016e4d */ + 0x016e4e, /* U+016e4e */ + 0x016e4f, /* U+016e4f */ + 0x016e50, /* U+016e50 */ + 0x016e51, /* U+016e51 */ + 0x016e52, /* U+016e52 */ + 0x016e53, /* U+016e53 */ + 0x016e54, /* U+016e54 */ + 0x016e55, /* U+016e55 */ + 0x016e56, /* U+016e56 */ + 0x016e57, /* U+016e57 */ + 0x016e58, /* U+016e58 */ + 0x016e59, /* U+016e59 */ + 0x016e5a, /* U+016e5a */ + 0x016e5b, /* U+016e5b */ + 0x016e5c, /* U+016e5c */ + 0x016e5d, /* U+016e5d */ + 0x016e5e, /* U+016e5e */ + 0x016e5f, /* U+016e5f */ + 0x01e900, /* U+01e900 */ + 0x01e901, /* U+01e901 */ + 0x01e902, /* U+01e902 */ + 0x01e903, /* U+01e903 */ + 0x01e904, /* U+01e904 */ + 0x01e905, /* U+01e905 */ + 0x01e906, /* U+01e906 */ + 0x01e907, /* U+01e907 */ + 0x01e908, /* U+01e908 */ + 0x01e909, /* U+01e909 */ + 0x01e90a, /* U+01e90a */ + 0x01e90b, /* U+01e90b */ + 0x01e90c, /* U+01e90c */ + 0x01e90d, /* U+01e90d */ + 0x01e90e, /* U+01e90e */ + 0x01e90f, /* U+01e90f */ + 0x01e910, /* U+01e910 */ + 0x01e911, /* U+01e911 */ + 0x01e912, /* U+01e912 */ + 0x01e913, /* U+01e913 */ + 0x01e914, /* U+01e914 */ + 0x01e915, /* U+01e915 */ + 0x01e916, /* U+01e916 */ + 0x01e917, /* U+01e917 */ + 0x01e918, /* U+01e918 */ + 0x01e919, /* U+01e919 */ + 0x01e91a, /* U+01e91a */ + 0x01e91b, /* U+01e91b */ + 0x01e91c, /* U+01e91c */ + 0x01e91d, /* U+01e91d */ + 0x01e91e, /* U+01e91e */ + 0x01e91f, /* U+01e91f */ + 0x01e920, /* U+01e920 */ + 0x01e921, /* U+01e921 */ + +}; + +/* + * The entry case_map_fold[case_index(codepoint)] is the mapping for the + * given codepoint. + */ +static const pg_wchar case_map_fold[1704] = +{ + 0x000000, /* reserved */ + 0x000000, /* U+000000 */ + 0x000001, /* U+000001 */ + 0x000002, /* U+000002 */ + 0x000003, /* U+000003 */ + 0x000004, /* U+000004 */ + 0x000005, /* U+000005 */ + 0x000006, /* U+000006 */ + 0x000007, /* U+000007 */ + 0x000008, /* U+000008 */ + 0x000009, /* U+000009 */ + 0x00000a, /* U+00000a */ + 0x00000b, /* U+00000b */ + 0x00000c, /* U+00000c */ + 0x00000d, /* U+00000d */ + 0x00000e, /* U+00000e */ + 0x00000f, /* U+00000f */ + 0x000010, /* U+000010 */ + 0x000011, /* U+000011 */ + 0x000012, /* U+000012 */ + 0x000013, /* U+000013 */ + 0x000014, /* U+000014 */ + 0x000015, /* U+000015 */ + 0x000016, /* U+000016 */ + 0x000017, /* U+000017 */ + 0x000018, /* U+000018 */ + 0x000019, /* U+000019 */ + 0x00001a, /* U+00001a */ + 0x00001b, /* U+00001b */ + 0x00001c, /* U+00001c */ + 0x00001d, /* U+00001d */ + 0x00001e, /* U+00001e */ + 0x00001f, /* U+00001f */ + 0x000020, /* U+000020 */ + 0x000021, /* U+000021 */ + 0x000022, /* U+000022 */ + 0x000023, /* U+000023 */ + 0x000024, /* U+000024 */ + 0x000025, /* U+000025 */ + 0x000026, /* U+000026 */ + 0x000027, /* U+000027 */ + 0x000028, /* U+000028 */ + 0x000029, /* U+000029 */ + 0x00002a, /* U+00002a */ + 0x00002b, /* U+00002b */ + 0x00002c, /* U+00002c */ + 0x00002d, /* U+00002d */ + 0x00002e, /* U+00002e */ + 0x00002f, /* U+00002f */ + 0x000030, /* U+000030 */ + 0x000031, /* U+000031 */ + 0x000032, /* U+000032 */ + 0x000033, /* U+000033 */ + 0x000034, /* U+000034 */ + 0x000035, /* U+000035 */ + 0x000036, /* U+000036 */ + 0x000037, /* U+000037 */ + 0x000038, /* U+000038 */ + 0x000039, /* U+000039 */ + 0x00003a, /* U+00003a */ + 0x00003b, /* U+00003b */ + 0x00003c, /* U+00003c */ + 0x00003d, /* U+00003d */ + 0x00003e, /* U+00003e */ + 0x00003f, /* U+00003f */ + 0x000040, /* U+000040 */ + 0x000061, /* U+000041 */ + 0x000062, /* U+000042 */ + 0x000063, /* U+000043 */ + 0x000064, /* U+000044 */ + 0x000065, /* U+000045 */ + 0x000066, /* U+000046 */ + 0x000067, /* U+000047 */ + 0x000068, /* U+000048 */ + 0x000069, /* U+000049 */ + 0x00006a, /* U+00004a */ + 0x00006b, /* U+00004b */ + 0x00006c, /* U+00004c */ + 0x00006d, /* U+00004d */ + 0x00006e, /* U+00004e */ + 0x00006f, /* U+00004f */ + 0x000070, /* U+000050 */ + 0x000071, /* U+000051 */ + 0x000072, /* U+000052 */ + 0x000073, /* U+000053 */ + 0x000074, /* U+000054 */ + 0x000075, /* U+000055 */ + 0x000076, /* U+000056 */ + 0x000077, /* U+000057 */ + 0x000078, /* U+000058 */ + 0x000079, /* U+000059 */ + 0x00007a, /* U+00005a */ + 0x00005b, /* U+00005b */ + 0x00005c, /* U+00005c */ + 0x00005d, /* U+00005d */ + 0x00005e, /* U+00005e */ + 0x00005f, /* U+00005f */ + 0x000060, /* U+000060 */ + 0x000061, /* U+000061 */ + 0x000062, /* U+000062 */ + 0x000063, /* U+000063 */ + 0x000064, /* U+000064 */ + 0x000065, /* U+000065 */ + 0x000066, /* U+000066 */ + 0x000067, /* U+000067 */ + 0x000068, /* U+000068 */ + 0x000069, /* U+000069 */ + 0x00006a, /* U+00006a */ + 0x00006b, /* U+00006b */ + 0x00006c, /* U+00006c */ + 0x00006d, /* U+00006d */ + 0x00006e, /* U+00006e */ + 0x00006f, /* U+00006f */ + 0x000070, /* U+000070 */ + 0x000071, /* U+000071 */ + 0x000072, /* U+000072 */ + 0x000073, /* U+000073 */ + 0x000074, /* U+000074 */ + 0x000075, /* U+000075 */ + 0x000076, /* U+000076 */ + 0x000077, /* U+000077 */ + 0x000078, /* U+000078 */ + 0x000079, /* U+000079 */ + 0x00007a, /* U+00007a */ + 0x00007b, /* U+00007b */ + 0x00007c, /* U+00007c */ + 0x00007d, /* U+00007d */ + 0x00007e, /* U+00007e */ + 0x00007f, /* U+00007f */ + 0x0003bc, /* U+0000b5 */ + 0x0000e0, /* U+0000c0 */ + 0x0000e1, /* U+0000c1 */ + 0x0000e2, /* U+0000c2 */ + 0x0000e3, /* U+0000c3 */ + 0x0000e4, /* U+0000c4 */ + 0x0000e5, /* U+0000c5 */ + 0x0000e6, /* U+0000c6 */ + 0x0000e7, /* U+0000c7 */ + 0x0000e8, /* U+0000c8 */ + 0x0000e9, /* U+0000c9 */ + 0x0000ea, /* U+0000ca */ + 0x0000eb, /* U+0000cb */ + 0x0000ec, /* U+0000cc */ + 0x0000ed, /* U+0000cd */ + 0x0000ee, /* U+0000ce */ + 0x0000ef, /* U+0000cf */ + 0x0000f0, /* U+0000d0 */ + 0x0000f1, /* U+0000d1 */ + 0x0000f2, /* U+0000d2 */ + 0x0000f3, /* U+0000d3 */ + 0x0000f4, /* U+0000d4 */ + 0x0000f5, /* U+0000d5 */ + 0x0000f6, /* U+0000d6 */ + 0x0000f8, /* U+0000d8 */ + 0x0000f9, /* U+0000d9 */ + 0x0000fa, /* U+0000da */ + 0x0000fb, /* U+0000db */ + 0x0000fc, /* U+0000dc */ + 0x0000fd, /* U+0000dd */ + 0x0000fe, /* U+0000de */ + 0x0000df, /* U+0000df */ + 0x0000ff, /* U+0000ff */ + 0x000101, /* U+000100 */ + 0x000103, /* U+000102 */ + 0x000105, /* U+000104 */ + 0x000107, /* U+000106 */ + 0x000109, /* U+000108 */ + 0x00010b, /* U+00010a */ + 0x00010d, /* U+00010c */ + 0x00010f, /* U+00010e */ + 0x000111, /* U+000110 */ + 0x000113, /* U+000112 */ + 0x000115, /* U+000114 */ + 0x000117, /* U+000116 */ + 0x000119, /* U+000118 */ + 0x00011b, /* U+00011a */ + 0x00011d, /* U+00011c */ + 0x00011f, /* U+00011e */ + 0x000121, /* U+000120 */ + 0x000123, /* U+000122 */ + 0x000125, /* U+000124 */ + 0x000127, /* U+000126 */ + 0x000129, /* U+000128 */ + 0x00012b, /* U+00012a */ + 0x00012d, /* U+00012c */ + 0x00012f, /* U+00012e */ + 0x000130, /* U+000130 */ + 0x000131, /* U+000131 */ + 0x000133, /* U+000132 */ + 0x000135, /* U+000134 */ + 0x000137, /* U+000136 */ + 0x00013a, /* U+000139 */ + 0x00013c, /* U+00013b */ + 0x00013e, /* U+00013d */ + 0x000140, /* U+00013f */ + 0x000142, /* U+000141 */ + 0x000144, /* U+000143 */ + 0x000146, /* U+000145 */ + 0x000148, /* U+000147 */ + 0x000149, /* U+000149 */ + 0x00014b, /* U+00014a */ + 0x00014d, /* U+00014c */ + 0x00014f, /* U+00014e */ + 0x000151, /* U+000150 */ + 0x000153, /* U+000152 */ + 0x000155, /* U+000154 */ + 0x000157, /* U+000156 */ + 0x000159, /* U+000158 */ + 0x00015b, /* U+00015a */ + 0x00015d, /* U+00015c */ + 0x00015f, /* U+00015e */ + 0x000161, /* U+000160 */ + 0x000163, /* U+000162 */ + 0x000165, /* U+000164 */ + 0x000167, /* U+000166 */ + 0x000169, /* U+000168 */ + 0x00016b, /* U+00016a */ + 0x00016d, /* U+00016c */ + 0x00016f, /* U+00016e */ + 0x000171, /* U+000170 */ + 0x000173, /* U+000172 */ + 0x000175, /* U+000174 */ + 0x000177, /* U+000176 */ + 0x00017a, /* U+000179 */ + 0x00017c, /* U+00017b */ + 0x00017e, /* U+00017d */ + 0x000073, /* U+00017f */ + 0x000180, /* U+000180 */ + 0x000253, /* U+000181 */ + 0x000183, /* U+000182 */ + 0x000185, /* U+000184 */ + 0x000254, /* U+000186 */ + 0x000188, /* U+000187 */ + 0x000256, /* U+000189 */ + 0x000257, /* U+00018a */ + 0x00018c, /* U+00018b */ + 0x0001dd, /* U+00018e */ + 0x000259, /* U+00018f */ + 0x00025b, /* U+000190 */ + 0x000192, /* U+000191 */ + 0x000260, /* U+000193 */ + 0x000263, /* U+000194 */ + 0x000195, /* U+000195 */ + 0x000269, /* U+000196 */ + 0x000268, /* U+000197 */ + 0x000199, /* U+000198 */ + 0x00019a, /* U+00019a */ + 0x00019b, /* U+00019b */ + 0x00026f, /* U+00019c */ + 0x000272, /* U+00019d */ + 0x00019e, /* U+00019e */ + 0x000275, /* U+00019f */ + 0x0001a1, /* U+0001a0 */ + 0x0001a3, /* U+0001a2 */ + 0x0001a5, /* U+0001a4 */ + 0x000280, /* U+0001a6 */ + 0x0001a8, /* U+0001a7 */ + 0x000283, /* U+0001a9 */ + 0x0001ad, /* U+0001ac */ + 0x000288, /* U+0001ae */ + 0x0001b0, /* U+0001af */ + 0x00028a, /* U+0001b1 */ + 0x00028b, /* U+0001b2 */ + 0x0001b4, /* U+0001b3 */ + 0x0001b6, /* U+0001b5 */ + 0x000292, /* U+0001b7 */ + 0x0001b9, /* U+0001b8 */ + 0x0001bd, /* U+0001bc */ + 0x0001bf, /* U+0001bf */ + 0x0001c6, /* U+0001c4 */ + 0x0001c9, /* U+0001c7 */ + 0x0001cc, /* U+0001ca */ + 0x0001ce, /* U+0001cd */ + 0x0001d0, /* U+0001cf */ + 0x0001d2, /* U+0001d1 */ + 0x0001d4, /* U+0001d3 */ + 0x0001d6, /* U+0001d5 */ + 0x0001d8, /* U+0001d7 */ + 0x0001da, /* U+0001d9 */ + 0x0001dc, /* U+0001db */ + 0x0001df, /* U+0001de */ + 0x0001e1, /* U+0001e0 */ + 0x0001e3, /* U+0001e2 */ + 0x0001e5, /* U+0001e4 */ + 0x0001e7, /* U+0001e6 */ + 0x0001e9, /* U+0001e8 */ + 0x0001eb, /* U+0001ea */ + 0x0001ed, /* U+0001ec */ + 0x0001ef, /* U+0001ee */ + 0x0001f0, /* U+0001f0 */ + 0x0001f3, /* U+0001f1 */ + 0x0001f5, /* U+0001f4 */ + 0x0001f9, /* U+0001f8 */ + 0x0001fb, /* U+0001fa */ + 0x0001fd, /* U+0001fc */ + 0x0001ff, /* U+0001fe */ + 0x000201, /* U+000200 */ + 0x000203, /* U+000202 */ + 0x000205, /* U+000204 */ + 0x000207, /* U+000206 */ + 0x000209, /* U+000208 */ + 0x00020b, /* U+00020a */ + 0x00020d, /* U+00020c */ + 0x00020f, /* U+00020e */ + 0x000211, /* U+000210 */ + 0x000213, /* U+000212 */ + 0x000215, /* U+000214 */ + 0x000217, /* U+000216 */ + 0x000219, /* U+000218 */ + 0x00021b, /* U+00021a */ + 0x00021d, /* U+00021c */ + 0x00021f, /* U+00021e */ + 0x000223, /* U+000222 */ + 0x000225, /* U+000224 */ + 0x000227, /* U+000226 */ + 0x000229, /* U+000228 */ + 0x00022b, /* U+00022a */ + 0x00022d, /* U+00022c */ + 0x00022f, /* U+00022e */ + 0x000231, /* U+000230 */ + 0x000233, /* U+000232 */ + 0x002c65, /* U+00023a */ + 0x00023c, /* U+00023b */ + 0x002c66, /* U+00023e */ + 0x00023f, /* U+00023f */ + 0x000240, /* U+000240 */ + 0x000242, /* U+000241 */ + 0x000289, /* U+000244 */ + 0x00028c, /* U+000245 */ + 0x000247, /* U+000246 */ + 0x000249, /* U+000248 */ + 0x00024b, /* U+00024a */ + 0x00024d, /* U+00024c */ + 0x00024f, /* U+00024e */ + 0x000250, /* U+000250 */ + 0x000251, /* U+000251 */ + 0x000252, /* U+000252 */ + 0x00025c, /* U+00025c */ + 0x000261, /* U+000261 */ + 0x000264, /* U+000264 */ + 0x000265, /* U+000265 */ + 0x000266, /* U+000266 */ + 0x00026a, /* U+00026a */ + 0x00026b, /* U+00026b */ + 0x00026c, /* U+00026c */ + 0x000271, /* U+000271 */ + 0x00027d, /* U+00027d */ + 0x000282, /* U+000282 */ + 0x000287, /* U+000287 */ + 0x00029d, /* U+00029d */ + 0x00029e, /* U+00029e */ + 0x0003b9, /* U+000345 */ + 0x000371, /* U+000370 */ + 0x000373, /* U+000372 */ + 0x000377, /* U+000376 */ + 0x00037b, /* U+00037b */ + 0x00037c, /* U+00037c */ + 0x00037d, /* U+00037d */ + 0x0003f3, /* U+00037f */ + 0x0003ac, /* U+000386 */ + 0x0003ad, /* U+000388 */ + 0x0003ae, /* U+000389 */ + 0x0003af, /* U+00038a */ + 0x0003cc, /* U+00038c */ + 0x0003cd, /* U+00038e */ + 0x0003ce, /* U+00038f */ + 0x000390, /* U+000390 */ + 0x0003b1, /* U+000391 */ + 0x0003b2, /* U+000392 */ + 0x0003b3, /* U+000393 */ + 0x0003b4, /* U+000394 */ + 0x0003b5, /* U+000395 */ + 0x0003b6, /* U+000396 */ + 0x0003b7, /* U+000397 */ + 0x0003b8, /* U+000398 */ + 0x0003b9, /* U+000399 */ + 0x0003ba, /* U+00039a */ + 0x0003bb, /* U+00039b */ + 0x0003bc, /* U+00039c */ + 0x0003bd, /* U+00039d */ + 0x0003be, /* U+00039e */ + 0x0003bf, /* U+00039f */ + 0x0003c0, /* U+0003a0 */ + 0x0003c1, /* U+0003a1 */ + 0x0003c3, /* U+0003a3 */ + 0x0003c4, /* U+0003a4 */ + 0x0003c5, /* U+0003a5 */ + 0x0003c6, /* U+0003a6 */ + 0x0003c7, /* U+0003a7 */ + 0x0003c8, /* U+0003a8 */ + 0x0003c9, /* U+0003a9 */ + 0x0003ca, /* U+0003aa */ + 0x0003cb, /* U+0003ab */ + 0x0003b0, /* U+0003b0 */ + 0x0003c3, /* U+0003c2 */ + 0x0003c3, /* U+0003c3 */ + 0x0003d7, /* U+0003cf */ + 0x0003b2, /* U+0003d0 */ + 0x0003b8, /* U+0003d1 */ + 0x0003c6, /* U+0003d5 */ + 0x0003c0, /* U+0003d6 */ + 0x0003d9, /* U+0003d8 */ + 0x0003db, /* U+0003da */ + 0x0003dd, /* U+0003dc */ + 0x0003df, /* U+0003de */ + 0x0003e1, /* U+0003e0 */ + 0x0003e3, /* U+0003e2 */ + 0x0003e5, /* U+0003e4 */ + 0x0003e7, /* U+0003e6 */ + 0x0003e9, /* U+0003e8 */ + 0x0003eb, /* U+0003ea */ + 0x0003ed, /* U+0003ec */ + 0x0003ef, /* U+0003ee */ + 0x0003ba, /* U+0003f0 */ + 0x0003c1, /* U+0003f1 */ + 0x0003f2, /* U+0003f2 */ + 0x0003b8, /* U+0003f4 */ + 0x0003b5, /* U+0003f5 */ + 0x0003f8, /* U+0003f7 */ + 0x0003fb, /* U+0003fa */ + 0x000450, /* U+000400 */ + 0x000451, /* U+000401 */ + 0x000452, /* U+000402 */ + 0x000453, /* U+000403 */ + 0x000454, /* U+000404 */ + 0x000455, /* U+000405 */ + 0x000456, /* U+000406 */ + 0x000457, /* U+000407 */ + 0x000458, /* U+000408 */ + 0x000459, /* U+000409 */ + 0x00045a, /* U+00040a */ + 0x00045b, /* U+00040b */ + 0x00045c, /* U+00040c */ + 0x00045d, /* U+00040d */ + 0x00045e, /* U+00040e */ + 0x00045f, /* U+00040f */ + 0x000430, /* U+000410 */ + 0x000431, /* U+000411 */ + 0x000432, /* U+000412 */ + 0x000433, /* U+000413 */ + 0x000434, /* U+000414 */ + 0x000435, /* U+000415 */ + 0x000436, /* U+000416 */ + 0x000437, /* U+000417 */ + 0x000438, /* U+000418 */ + 0x000439, /* U+000419 */ + 0x00043a, /* U+00041a */ + 0x00043b, /* U+00041b */ + 0x00043c, /* U+00041c */ + 0x00043d, /* U+00041d */ + 0x00043e, /* U+00041e */ + 0x00043f, /* U+00041f */ + 0x000440, /* U+000420 */ + 0x000441, /* U+000421 */ + 0x000442, /* U+000422 */ + 0x000443, /* U+000423 */ + 0x000444, /* U+000424 */ + 0x000445, /* U+000425 */ + 0x000446, /* U+000426 */ + 0x000447, /* U+000427 */ + 0x000448, /* U+000428 */ + 0x000449, /* U+000429 */ + 0x00044a, /* U+00042a */ + 0x00044b, /* U+00042b */ + 0x00044c, /* U+00042c */ + 0x00044d, /* U+00042d */ + 0x00044e, /* U+00042e */ + 0x00044f, /* U+00042f */ + 0x000461, /* U+000460 */ + 0x000463, /* U+000462 */ + 0x000465, /* U+000464 */ + 0x000467, /* U+000466 */ + 0x000469, /* U+000468 */ + 0x00046b, /* U+00046a */ + 0x00046d, /* U+00046c */ + 0x00046f, /* U+00046e */ + 0x000471, /* U+000470 */ + 0x000473, /* U+000472 */ + 0x000475, /* U+000474 */ + 0x000477, /* U+000476 */ + 0x000479, /* U+000478 */ + 0x00047b, /* U+00047a */ + 0x00047d, /* U+00047c */ + 0x00047f, /* U+00047e */ + 0x000481, /* U+000480 */ + 0x00048b, /* U+00048a */ + 0x00048d, /* U+00048c */ + 0x00048f, /* U+00048e */ + 0x000491, /* U+000490 */ + 0x000493, /* U+000492 */ + 0x000495, /* U+000494 */ + 0x000497, /* U+000496 */ + 0x000499, /* U+000498 */ + 0x00049b, /* U+00049a */ + 0x00049d, /* U+00049c */ + 0x00049f, /* U+00049e */ + 0x0004a1, /* U+0004a0 */ + 0x0004a3, /* U+0004a2 */ + 0x0004a5, /* U+0004a4 */ + 0x0004a7, /* U+0004a6 */ + 0x0004a9, /* U+0004a8 */ + 0x0004ab, /* U+0004aa */ + 0x0004ad, /* U+0004ac */ + 0x0004af, /* U+0004ae */ + 0x0004b1, /* U+0004b0 */ + 0x0004b3, /* U+0004b2 */ + 0x0004b5, /* U+0004b4 */ + 0x0004b7, /* U+0004b6 */ + 0x0004b9, /* U+0004b8 */ + 0x0004bb, /* U+0004ba */ + 0x0004bd, /* U+0004bc */ + 0x0004bf, /* U+0004be */ + 0x0004cf, /* U+0004c0 */ + 0x0004c2, /* U+0004c1 */ + 0x0004c4, /* U+0004c3 */ + 0x0004c6, /* U+0004c5 */ + 0x0004c8, /* U+0004c7 */ + 0x0004ca, /* U+0004c9 */ + 0x0004cc, /* U+0004cb */ + 0x0004ce, /* U+0004cd */ + 0x0004d1, /* U+0004d0 */ + 0x0004d3, /* U+0004d2 */ + 0x0004d5, /* U+0004d4 */ + 0x0004d7, /* U+0004d6 */ + 0x0004d9, /* U+0004d8 */ + 0x0004db, /* U+0004da */ + 0x0004dd, /* U+0004dc */ + 0x0004df, /* U+0004de */ + 0x0004e1, /* U+0004e0 */ + 0x0004e3, /* U+0004e2 */ + 0x0004e5, /* U+0004e4 */ + 0x0004e7, /* U+0004e6 */ + 0x0004e9, /* U+0004e8 */ + 0x0004eb, /* U+0004ea */ + 0x0004ed, /* U+0004ec */ + 0x0004ef, /* U+0004ee */ + 0x0004f1, /* U+0004f0 */ + 0x0004f3, /* U+0004f2 */ + 0x0004f5, /* U+0004f4 */ + 0x0004f7, /* U+0004f6 */ + 0x0004f9, /* U+0004f8 */ + 0x0004fb, /* U+0004fa */ + 0x0004fd, /* U+0004fc */ + 0x0004ff, /* U+0004fe */ + 0x000501, /* U+000500 */ + 0x000503, /* U+000502 */ + 0x000505, /* U+000504 */ + 0x000507, /* U+000506 */ + 0x000509, /* U+000508 */ + 0x00050b, /* U+00050a */ + 0x00050d, /* U+00050c */ + 0x00050f, /* U+00050e */ + 0x000511, /* U+000510 */ + 0x000513, /* U+000512 */ + 0x000515, /* U+000514 */ + 0x000517, /* U+000516 */ + 0x000519, /* U+000518 */ + 0x00051b, /* U+00051a */ + 0x00051d, /* U+00051c */ + 0x00051f, /* U+00051e */ + 0x000521, /* U+000520 */ + 0x000523, /* U+000522 */ + 0x000525, /* U+000524 */ + 0x000527, /* U+000526 */ + 0x000529, /* U+000528 */ + 0x00052b, /* U+00052a */ + 0x00052d, /* U+00052c */ + 0x00052f, /* U+00052e */ + 0x000561, /* U+000531 */ + 0x000562, /* U+000532 */ + 0x000563, /* U+000533 */ + 0x000564, /* U+000534 */ + 0x000565, /* U+000535 */ + 0x000566, /* U+000536 */ + 0x000567, /* U+000537 */ + 0x000568, /* U+000538 */ + 0x000569, /* U+000539 */ + 0x00056a, /* U+00053a */ + 0x00056b, /* U+00053b */ + 0x00056c, /* U+00053c */ + 0x00056d, /* U+00053d */ + 0x00056e, /* U+00053e */ + 0x00056f, /* U+00053f */ + 0x000570, /* U+000540 */ + 0x000571, /* U+000541 */ + 0x000572, /* U+000542 */ + 0x000573, /* U+000543 */ + 0x000574, /* U+000544 */ + 0x000575, /* U+000545 */ + 0x000576, /* U+000546 */ + 0x000577, /* U+000547 */ + 0x000578, /* U+000548 */ + 0x000579, /* U+000549 */ + 0x00057a, /* U+00054a */ + 0x00057b, /* U+00054b */ + 0x00057c, /* U+00054c */ + 0x00057d, /* U+00054d */ + 0x00057e, /* U+00054e */ + 0x00057f, /* U+00054f */ + 0x000580, /* U+000550 */ + 0x000581, /* U+000551 */ + 0x000582, /* U+000552 */ + 0x000583, /* U+000553 */ + 0x000584, /* U+000554 */ + 0x000585, /* U+000555 */ + 0x000586, /* U+000556 */ + 0x000587, /* U+000587 */ + 0x002d00, /* U+0010a0 */ + 0x002d01, /* U+0010a1 */ + 0x002d02, /* U+0010a2 */ + 0x002d03, /* U+0010a3 */ + 0x002d04, /* U+0010a4 */ + 0x002d05, /* U+0010a5 */ + 0x002d06, /* U+0010a6 */ + 0x002d07, /* U+0010a7 */ + 0x002d08, /* U+0010a8 */ + 0x002d09, /* U+0010a9 */ + 0x002d0a, /* U+0010aa */ + 0x002d0b, /* U+0010ab */ + 0x002d0c, /* U+0010ac */ + 0x002d0d, /* U+0010ad */ + 0x002d0e, /* U+0010ae */ + 0x002d0f, /* U+0010af */ + 0x002d10, /* U+0010b0 */ + 0x002d11, /* U+0010b1 */ + 0x002d12, /* U+0010b2 */ + 0x002d13, /* U+0010b3 */ + 0x002d14, /* U+0010b4 */ + 0x002d15, /* U+0010b5 */ + 0x002d16, /* U+0010b6 */ + 0x002d17, /* U+0010b7 */ + 0x002d18, /* U+0010b8 */ + 0x002d19, /* U+0010b9 */ + 0x002d1a, /* U+0010ba */ + 0x002d1b, /* U+0010bb */ + 0x002d1c, /* U+0010bc */ + 0x002d1d, /* U+0010bd */ + 0x002d1e, /* U+0010be */ + 0x002d1f, /* U+0010bf */ + 0x002d20, /* U+0010c0 */ + 0x002d21, /* U+0010c1 */ + 0x002d22, /* U+0010c2 */ + 0x002d23, /* U+0010c3 */ + 0x002d24, /* U+0010c4 */ + 0x002d25, /* U+0010c5 */ + 0x002d27, /* U+0010c7 */ + 0x002d2d, /* U+0010cd */ + 0x0010d0, /* U+0010d0 */ + 0x0010d1, /* U+0010d1 */ + 0x0010d2, /* U+0010d2 */ + 0x0010d3, /* U+0010d3 */ + 0x0010d4, /* U+0010d4 */ + 0x0010d5, /* U+0010d5 */ + 0x0010d6, /* U+0010d6 */ + 0x0010d7, /* U+0010d7 */ + 0x0010d8, /* U+0010d8 */ + 0x0010d9, /* U+0010d9 */ + 0x0010da, /* U+0010da */ + 0x0010db, /* U+0010db */ + 0x0010dc, /* U+0010dc */ + 0x0010dd, /* U+0010dd */ + 0x0010de, /* U+0010de */ + 0x0010df, /* U+0010df */ + 0x0010e0, /* U+0010e0 */ + 0x0010e1, /* U+0010e1 */ + 0x0010e2, /* U+0010e2 */ + 0x0010e3, /* U+0010e3 */ + 0x0010e4, /* U+0010e4 */ + 0x0010e5, /* U+0010e5 */ + 0x0010e6, /* U+0010e6 */ + 0x0010e7, /* U+0010e7 */ + 0x0010e8, /* U+0010e8 */ + 0x0010e9, /* U+0010e9 */ + 0x0010ea, /* U+0010ea */ + 0x0010eb, /* U+0010eb */ + 0x0010ec, /* U+0010ec */ + 0x0010ed, /* U+0010ed */ + 0x0010ee, /* U+0010ee */ + 0x0010ef, /* U+0010ef */ + 0x0010f0, /* U+0010f0 */ + 0x0010f1, /* U+0010f1 */ + 0x0010f2, /* U+0010f2 */ + 0x0010f3, /* U+0010f3 */ + 0x0010f4, /* U+0010f4 */ + 0x0010f5, /* U+0010f5 */ + 0x0010f6, /* U+0010f6 */ + 0x0010f7, /* U+0010f7 */ + 0x0010f8, /* U+0010f8 */ + 0x0010f9, /* U+0010f9 */ + 0x0010fa, /* U+0010fa */ + 0x0010fd, /* U+0010fd */ + 0x0010fe, /* U+0010fe */ + 0x0010ff, /* U+0010ff */ + 0x0013a0, /* U+0013a0 */ + 0x0013a1, /* U+0013a1 */ + 0x0013a2, /* U+0013a2 */ + 0x0013a3, /* U+0013a3 */ + 0x0013a4, /* U+0013a4 */ + 0x0013a5, /* U+0013a5 */ + 0x0013a6, /* U+0013a6 */ + 0x0013a7, /* U+0013a7 */ + 0x0013a8, /* U+0013a8 */ + 0x0013a9, /* U+0013a9 */ + 0x0013aa, /* U+0013aa */ + 0x0013ab, /* U+0013ab */ + 0x0013ac, /* U+0013ac */ + 0x0013ad, /* U+0013ad */ + 0x0013ae, /* U+0013ae */ + 0x0013af, /* U+0013af */ + 0x0013b0, /* U+0013b0 */ + 0x0013b1, /* U+0013b1 */ + 0x0013b2, /* U+0013b2 */ + 0x0013b3, /* U+0013b3 */ + 0x0013b4, /* U+0013b4 */ + 0x0013b5, /* U+0013b5 */ + 0x0013b6, /* U+0013b6 */ + 0x0013b7, /* U+0013b7 */ + 0x0013b8, /* U+0013b8 */ + 0x0013b9, /* U+0013b9 */ + 0x0013ba, /* U+0013ba */ + 0x0013bb, /* U+0013bb */ + 0x0013bc, /* U+0013bc */ + 0x0013bd, /* U+0013bd */ + 0x0013be, /* U+0013be */ + 0x0013bf, /* U+0013bf */ + 0x0013c0, /* U+0013c0 */ + 0x0013c1, /* U+0013c1 */ + 0x0013c2, /* U+0013c2 */ + 0x0013c3, /* U+0013c3 */ + 0x0013c4, /* U+0013c4 */ + 0x0013c5, /* U+0013c5 */ + 0x0013c6, /* U+0013c6 */ + 0x0013c7, /* U+0013c7 */ + 0x0013c8, /* U+0013c8 */ + 0x0013c9, /* U+0013c9 */ + 0x0013ca, /* U+0013ca */ + 0x0013cb, /* U+0013cb */ + 0x0013cc, /* U+0013cc */ + 0x0013cd, /* U+0013cd */ + 0x0013ce, /* U+0013ce */ + 0x0013cf, /* U+0013cf */ + 0x0013d0, /* U+0013d0 */ + 0x0013d1, /* U+0013d1 */ + 0x0013d2, /* U+0013d2 */ + 0x0013d3, /* U+0013d3 */ + 0x0013d4, /* U+0013d4 */ + 0x0013d5, /* U+0013d5 */ + 0x0013d6, /* U+0013d6 */ + 0x0013d7, /* U+0013d7 */ + 0x0013d8, /* U+0013d8 */ + 0x0013d9, /* U+0013d9 */ + 0x0013da, /* U+0013da */ + 0x0013db, /* U+0013db */ + 0x0013dc, /* U+0013dc */ + 0x0013dd, /* U+0013dd */ + 0x0013de, /* U+0013de */ + 0x0013df, /* U+0013df */ + 0x0013e0, /* U+0013e0 */ + 0x0013e1, /* U+0013e1 */ + 0x0013e2, /* U+0013e2 */ + 0x0013e3, /* U+0013e3 */ + 0x0013e4, /* U+0013e4 */ + 0x0013e5, /* U+0013e5 */ + 0x0013e6, /* U+0013e6 */ + 0x0013e7, /* U+0013e7 */ + 0x0013e8, /* U+0013e8 */ + 0x0013e9, /* U+0013e9 */ + 0x0013ea, /* U+0013ea */ + 0x0013eb, /* U+0013eb */ + 0x0013ec, /* U+0013ec */ + 0x0013ed, /* U+0013ed */ + 0x0013ee, /* U+0013ee */ + 0x0013ef, /* U+0013ef */ + 0x0013f0, /* U+0013f0 */ + 0x0013f1, /* U+0013f1 */ + 0x0013f2, /* U+0013f2 */ + 0x0013f3, /* U+0013f3 */ + 0x0013f4, /* U+0013f4 */ + 0x0013f5, /* U+0013f5 */ + 0x000432, /* U+001c80 */ + 0x000434, /* U+001c81 */ + 0x00043e, /* U+001c82 */ + 0x000441, /* U+001c83 */ + 0x000442, /* U+001c84 */ + 0x000442, /* U+001c85 */ + 0x00044a, /* U+001c86 */ + 0x000463, /* U+001c87 */ + 0x00a64b, /* U+001c88 */ + 0x001c8a, /* U+001c89 */ + 0x0010d0, /* U+001c90 */ + 0x0010d1, /* U+001c91 */ + 0x0010d2, /* U+001c92 */ + 0x0010d3, /* U+001c93 */ + 0x0010d4, /* U+001c94 */ + 0x0010d5, /* U+001c95 */ + 0x0010d6, /* U+001c96 */ + 0x0010d7, /* U+001c97 */ + 0x0010d8, /* U+001c98 */ + 0x0010d9, /* U+001c99 */ + 0x0010da, /* U+001c9a */ + 0x0010db, /* U+001c9b */ + 0x0010dc, /* U+001c9c */ + 0x0010dd, /* U+001c9d */ + 0x0010de, /* U+001c9e */ + 0x0010df, /* U+001c9f */ + 0x0010e0, /* U+001ca0 */ + 0x0010e1, /* U+001ca1 */ + 0x0010e2, /* U+001ca2 */ + 0x0010e3, /* U+001ca3 */ + 0x0010e4, /* U+001ca4 */ + 0x0010e5, /* U+001ca5 */ + 0x0010e6, /* U+001ca6 */ + 0x0010e7, /* U+001ca7 */ + 0x0010e8, /* U+001ca8 */ + 0x0010e9, /* U+001ca9 */ + 0x0010ea, /* U+001caa */ + 0x0010eb, /* U+001cab */ + 0x0010ec, /* U+001cac */ + 0x0010ed, /* U+001cad */ + 0x0010ee, /* U+001cae */ + 0x0010ef, /* U+001caf */ + 0x0010f0, /* U+001cb0 */ + 0x0010f1, /* U+001cb1 */ + 0x0010f2, /* U+001cb2 */ + 0x0010f3, /* U+001cb3 */ + 0x0010f4, /* U+001cb4 */ + 0x0010f5, /* U+001cb5 */ + 0x0010f6, /* U+001cb6 */ + 0x0010f7, /* U+001cb7 */ + 0x0010f8, /* U+001cb8 */ + 0x0010f9, /* U+001cb9 */ + 0x0010fa, /* U+001cba */ + 0x0010fd, /* U+001cbd */ + 0x0010fe, /* U+001cbe */ + 0x0010ff, /* U+001cbf */ + 0x001d79, /* U+001d79 */ + 0x001d7d, /* U+001d7d */ + 0x001d8e, /* U+001d8e */ + 0x001e01, /* U+001e00 */ + 0x001e03, /* U+001e02 */ + 0x001e05, /* U+001e04 */ + 0x001e07, /* U+001e06 */ + 0x001e09, /* U+001e08 */ + 0x001e0b, /* U+001e0a */ + 0x001e0d, /* U+001e0c */ + 0x001e0f, /* U+001e0e */ + 0x001e11, /* U+001e10 */ + 0x001e13, /* U+001e12 */ + 0x001e15, /* U+001e14 */ + 0x001e17, /* U+001e16 */ + 0x001e19, /* U+001e18 */ + 0x001e1b, /* U+001e1a */ + 0x001e1d, /* U+001e1c */ + 0x001e1f, /* U+001e1e */ + 0x001e21, /* U+001e20 */ + 0x001e23, /* U+001e22 */ + 0x001e25, /* U+001e24 */ + 0x001e27, /* U+001e26 */ + 0x001e29, /* U+001e28 */ + 0x001e2b, /* U+001e2a */ + 0x001e2d, /* U+001e2c */ + 0x001e2f, /* U+001e2e */ + 0x001e31, /* U+001e30 */ + 0x001e33, /* U+001e32 */ + 0x001e35, /* U+001e34 */ + 0x001e37, /* U+001e36 */ + 0x001e39, /* U+001e38 */ + 0x001e3b, /* U+001e3a */ + 0x001e3d, /* U+001e3c */ + 0x001e3f, /* U+001e3e */ + 0x001e41, /* U+001e40 */ + 0x001e43, /* U+001e42 */ + 0x001e45, /* U+001e44 */ + 0x001e47, /* U+001e46 */ + 0x001e49, /* U+001e48 */ + 0x001e4b, /* U+001e4a */ + 0x001e4d, /* U+001e4c */ + 0x001e4f, /* U+001e4e */ + 0x001e51, /* U+001e50 */ + 0x001e53, /* U+001e52 */ + 0x001e55, /* U+001e54 */ + 0x001e57, /* U+001e56 */ + 0x001e59, /* U+001e58 */ + 0x001e5b, /* U+001e5a */ + 0x001e5d, /* U+001e5c */ + 0x001e5f, /* U+001e5e */ + 0x001e61, /* U+001e60 */ + 0x001e63, /* U+001e62 */ + 0x001e65, /* U+001e64 */ + 0x001e67, /* U+001e66 */ + 0x001e69, /* U+001e68 */ + 0x001e6b, /* U+001e6a */ + 0x001e6d, /* U+001e6c */ + 0x001e6f, /* U+001e6e */ + 0x001e71, /* U+001e70 */ + 0x001e73, /* U+001e72 */ + 0x001e75, /* U+001e74 */ + 0x001e77, /* U+001e76 */ + 0x001e79, /* U+001e78 */ + 0x001e7b, /* U+001e7a */ + 0x001e7d, /* U+001e7c */ + 0x001e7f, /* U+001e7e */ + 0x001e81, /* U+001e80 */ + 0x001e83, /* U+001e82 */ + 0x001e85, /* U+001e84 */ + 0x001e87, /* U+001e86 */ + 0x001e89, /* U+001e88 */ + 0x001e8b, /* U+001e8a */ + 0x001e8d, /* U+001e8c */ + 0x001e8f, /* U+001e8e */ + 0x001e91, /* U+001e90 */ + 0x001e93, /* U+001e92 */ + 0x001e95, /* U+001e94 */ + 0x001e96, /* U+001e96 */ + 0x001e97, /* U+001e97 */ + 0x001e98, /* U+001e98 */ + 0x001e99, /* U+001e99 */ + 0x001e9a, /* U+001e9a */ + 0x001e61, /* U+001e9b */ + 0x0000df, /* U+001e9e */ + 0x001ea1, /* U+001ea0 */ + 0x001ea3, /* U+001ea2 */ + 0x001ea5, /* U+001ea4 */ + 0x001ea7, /* U+001ea6 */ + 0x001ea9, /* U+001ea8 */ + 0x001eab, /* U+001eaa */ + 0x001ead, /* U+001eac */ + 0x001eaf, /* U+001eae */ + 0x001eb1, /* U+001eb0 */ + 0x001eb3, /* U+001eb2 */ + 0x001eb5, /* U+001eb4 */ + 0x001eb7, /* U+001eb6 */ + 0x001eb9, /* U+001eb8 */ + 0x001ebb, /* U+001eba */ + 0x001ebd, /* U+001ebc */ + 0x001ebf, /* U+001ebe */ + 0x001ec1, /* U+001ec0 */ + 0x001ec3, /* U+001ec2 */ + 0x001ec5, /* U+001ec4 */ + 0x001ec7, /* U+001ec6 */ + 0x001ec9, /* U+001ec8 */ + 0x001ecb, /* U+001eca */ + 0x001ecd, /* U+001ecc */ + 0x001ecf, /* U+001ece */ + 0x001ed1, /* U+001ed0 */ + 0x001ed3, /* U+001ed2 */ + 0x001ed5, /* U+001ed4 */ + 0x001ed7, /* U+001ed6 */ + 0x001ed9, /* U+001ed8 */ + 0x001edb, /* U+001eda */ + 0x001edd, /* U+001edc */ + 0x001edf, /* U+001ede */ + 0x001ee1, /* U+001ee0 */ + 0x001ee3, /* U+001ee2 */ + 0x001ee5, /* U+001ee4 */ + 0x001ee7, /* U+001ee6 */ + 0x001ee9, /* U+001ee8 */ + 0x001eeb, /* U+001eea */ + 0x001eed, /* U+001eec */ + 0x001eef, /* U+001eee */ + 0x001ef1, /* U+001ef0 */ + 0x001ef3, /* U+001ef2 */ + 0x001ef5, /* U+001ef4 */ + 0x001ef7, /* U+001ef6 */ + 0x001ef9, /* U+001ef8 */ + 0x001efb, /* U+001efa */ + 0x001efd, /* U+001efc */ + 0x001eff, /* U+001efe */ + 0x001f00, /* U+001f00 */ + 0x001f01, /* U+001f01 */ + 0x001f02, /* U+001f02 */ + 0x001f03, /* U+001f03 */ + 0x001f04, /* U+001f04 */ + 0x001f05, /* U+001f05 */ + 0x001f06, /* U+001f06 */ + 0x001f07, /* U+001f07 */ + 0x001f10, /* U+001f10 */ + 0x001f11, /* U+001f11 */ + 0x001f12, /* U+001f12 */ + 0x001f13, /* U+001f13 */ + 0x001f14, /* U+001f14 */ + 0x001f15, /* U+001f15 */ + 0x001f20, /* U+001f20 */ + 0x001f21, /* U+001f21 */ + 0x001f22, /* U+001f22 */ + 0x001f23, /* U+001f23 */ + 0x001f24, /* U+001f24 */ + 0x001f25, /* U+001f25 */ + 0x001f26, /* U+001f26 */ + 0x001f27, /* U+001f27 */ + 0x001f30, /* U+001f30 */ + 0x001f31, /* U+001f31 */ + 0x001f32, /* U+001f32 */ + 0x001f33, /* U+001f33 */ + 0x001f34, /* U+001f34 */ + 0x001f35, /* U+001f35 */ + 0x001f36, /* U+001f36 */ + 0x001f37, /* U+001f37 */ + 0x001f40, /* U+001f40 */ + 0x001f41, /* U+001f41 */ + 0x001f42, /* U+001f42 */ + 0x001f43, /* U+001f43 */ + 0x001f44, /* U+001f44 */ + 0x001f45, /* U+001f45 */ + 0x001f50, /* U+001f50 */ + 0x001f51, /* U+001f51 */ + 0x001f52, /* U+001f52 */ + 0x001f53, /* U+001f53 */ + 0x001f54, /* U+001f54 */ + 0x001f55, /* U+001f55 */ + 0x001f56, /* U+001f56 */ + 0x001f57, /* U+001f57 */ + 0x001f60, /* U+001f60 */ + 0x001f61, /* U+001f61 */ + 0x001f62, /* U+001f62 */ + 0x001f63, /* U+001f63 */ + 0x001f64, /* U+001f64 */ + 0x001f65, /* U+001f65 */ + 0x001f66, /* U+001f66 */ + 0x001f67, /* U+001f67 */ + 0x001f70, /* U+001f70 */ + 0x001f71, /* U+001f71 */ + 0x001f72, /* U+001f72 */ + 0x001f73, /* U+001f73 */ + 0x001f74, /* U+001f74 */ + 0x001f75, /* U+001f75 */ + 0x001f76, /* U+001f76 */ + 0x001f77, /* U+001f77 */ + 0x001f78, /* U+001f78 */ + 0x001f79, /* U+001f79 */ + 0x001f7a, /* U+001f7a */ + 0x001f7b, /* U+001f7b */ + 0x001f7c, /* U+001f7c */ + 0x001f7d, /* U+001f7d */ + 0x001f80, /* U+001f80 */ + 0x001f81, /* U+001f81 */ + 0x001f82, /* U+001f82 */ + 0x001f83, /* U+001f83 */ + 0x001f84, /* U+001f84 */ + 0x001f85, /* U+001f85 */ + 0x001f86, /* U+001f86 */ + 0x001f87, /* U+001f87 */ + 0x001f80, /* U+001f88 */ + 0x001f81, /* U+001f89 */ + 0x001f82, /* U+001f8a */ + 0x001f83, /* U+001f8b */ + 0x001f84, /* U+001f8c */ + 0x001f85, /* U+001f8d */ + 0x001f86, /* U+001f8e */ + 0x001f87, /* U+001f8f */ + 0x001f90, /* U+001f90 */ + 0x001f91, /* U+001f91 */ + 0x001f92, /* U+001f92 */ + 0x001f93, /* U+001f93 */ + 0x001f94, /* U+001f94 */ + 0x001f95, /* U+001f95 */ + 0x001f96, /* U+001f96 */ + 0x001f97, /* U+001f97 */ + 0x001f90, /* U+001f98 */ + 0x001f91, /* U+001f99 */ + 0x001f92, /* U+001f9a */ + 0x001f93, /* U+001f9b */ + 0x001f94, /* U+001f9c */ + 0x001f95, /* U+001f9d */ + 0x001f96, /* U+001f9e */ + 0x001f97, /* U+001f9f */ + 0x001fa0, /* U+001fa0 */ + 0x001fa1, /* U+001fa1 */ + 0x001fa2, /* U+001fa2 */ + 0x001fa3, /* U+001fa3 */ + 0x001fa4, /* U+001fa4 */ + 0x001fa5, /* U+001fa5 */ + 0x001fa6, /* U+001fa6 */ + 0x001fa7, /* U+001fa7 */ + 0x001fa0, /* U+001fa8 */ + 0x001fa1, /* U+001fa9 */ + 0x001fa2, /* U+001faa */ + 0x001fa3, /* U+001fab */ + 0x001fa4, /* U+001fac */ + 0x001fa5, /* U+001fad */ + 0x001fa6, /* U+001fae */ + 0x001fa7, /* U+001faf */ + 0x001fb0, /* U+001fb0 */ + 0x001fb1, /* U+001fb1 */ + 0x001fb2, /* U+001fb2 */ + 0x001fb3, /* U+001fb3 */ + 0x001fb4, /* U+001fb4 */ + 0x001fb6, /* U+001fb6 */ + 0x001fb7, /* U+001fb7 */ + 0x001fb3, /* U+001fbc */ + 0x0003b9, /* U+001fbe */ + 0x001fc2, /* U+001fc2 */ + 0x001fc3, /* U+001fc3 */ + 0x001fc4, /* U+001fc4 */ + 0x001fc6, /* U+001fc6 */ + 0x001fc7, /* U+001fc7 */ + 0x001fc3, /* U+001fcc */ + 0x001fd0, /* U+001fd0 */ + 0x001fd1, /* U+001fd1 */ + 0x001fd2, /* U+001fd2 */ + 0x000390, /* U+001fd3 */ + 0x001fd6, /* U+001fd6 */ + 0x001fd7, /* U+001fd7 */ + 0x001fe0, /* U+001fe0 */ + 0x001fe1, /* U+001fe1 */ + 0x001fe2, /* U+001fe2 */ + 0x0003b0, /* U+001fe3 */ + 0x001fe4, /* U+001fe4 */ + 0x001fe5, /* U+001fe5 */ + 0x001fe6, /* U+001fe6 */ + 0x001fe7, /* U+001fe7 */ + 0x001ff2, /* U+001ff2 */ + 0x001ff3, /* U+001ff3 */ + 0x001ff4, /* U+001ff4 */ + 0x001ff6, /* U+001ff6 */ + 0x001ff7, /* U+001ff7 */ + 0x001ff3, /* U+001ffc */ + 0x0003c9, /* U+002126 */ + 0x00006b, /* U+00212a */ + 0x0000e5, /* U+00212b */ + 0x00214e, /* U+002132 */ + 0x002170, /* U+002160 */ + 0x002171, /* U+002161 */ + 0x002172, /* U+002162 */ + 0x002173, /* U+002163 */ + 0x002174, /* U+002164 */ + 0x002175, /* U+002165 */ + 0x002176, /* U+002166 */ + 0x002177, /* U+002167 */ + 0x002178, /* U+002168 */ + 0x002179, /* U+002169 */ + 0x00217a, /* U+00216a */ + 0x00217b, /* U+00216b */ + 0x00217c, /* U+00216c */ + 0x00217d, /* U+00216d */ + 0x00217e, /* U+00216e */ + 0x00217f, /* U+00216f */ + 0x002184, /* U+002183 */ + 0x0024d0, /* U+0024b6 */ + 0x0024d1, /* U+0024b7 */ + 0x0024d2, /* U+0024b8 */ + 0x0024d3, /* U+0024b9 */ + 0x0024d4, /* U+0024ba */ + 0x0024d5, /* U+0024bb */ + 0x0024d6, /* U+0024bc */ + 0x0024d7, /* U+0024bd */ + 0x0024d8, /* U+0024be */ + 0x0024d9, /* U+0024bf */ + 0x0024da, /* U+0024c0 */ + 0x0024db, /* U+0024c1 */ + 0x0024dc, /* U+0024c2 */ + 0x0024dd, /* U+0024c3 */ + 0x0024de, /* U+0024c4 */ + 0x0024df, /* U+0024c5 */ + 0x0024e0, /* U+0024c6 */ + 0x0024e1, /* U+0024c7 */ + 0x0024e2, /* U+0024c8 */ + 0x0024e3, /* U+0024c9 */ + 0x0024e4, /* U+0024ca */ + 0x0024e5, /* U+0024cb */ + 0x0024e6, /* U+0024cc */ + 0x0024e7, /* U+0024cd */ + 0x0024e8, /* U+0024ce */ + 0x0024e9, /* U+0024cf */ + 0x002c30, /* U+002c00 */ + 0x002c31, /* U+002c01 */ + 0x002c32, /* U+002c02 */ + 0x002c33, /* U+002c03 */ + 0x002c34, /* U+002c04 */ + 0x002c35, /* U+002c05 */ + 0x002c36, /* U+002c06 */ + 0x002c37, /* U+002c07 */ + 0x002c38, /* U+002c08 */ + 0x002c39, /* U+002c09 */ + 0x002c3a, /* U+002c0a */ + 0x002c3b, /* U+002c0b */ + 0x002c3c, /* U+002c0c */ + 0x002c3d, /* U+002c0d */ + 0x002c3e, /* U+002c0e */ + 0x002c3f, /* U+002c0f */ + 0x002c40, /* U+002c10 */ + 0x002c41, /* U+002c11 */ + 0x002c42, /* U+002c12 */ + 0x002c43, /* U+002c13 */ + 0x002c44, /* U+002c14 */ + 0x002c45, /* U+002c15 */ + 0x002c46, /* U+002c16 */ + 0x002c47, /* U+002c17 */ + 0x002c48, /* U+002c18 */ + 0x002c49, /* U+002c19 */ + 0x002c4a, /* U+002c1a */ + 0x002c4b, /* U+002c1b */ + 0x002c4c, /* U+002c1c */ + 0x002c4d, /* U+002c1d */ + 0x002c4e, /* U+002c1e */ + 0x002c4f, /* U+002c1f */ + 0x002c50, /* U+002c20 */ + 0x002c51, /* U+002c21 */ + 0x002c52, /* U+002c22 */ + 0x002c53, /* U+002c23 */ + 0x002c54, /* U+002c24 */ + 0x002c55, /* U+002c25 */ + 0x002c56, /* U+002c26 */ + 0x002c57, /* U+002c27 */ + 0x002c58, /* U+002c28 */ + 0x002c59, /* U+002c29 */ + 0x002c5a, /* U+002c2a */ + 0x002c5b, /* U+002c2b */ + 0x002c5c, /* U+002c2c */ + 0x002c5d, /* U+002c2d */ + 0x002c5e, /* U+002c2e */ + 0x002c5f, /* U+002c2f */ + 0x002c61, /* U+002c60 */ + 0x002c68, /* U+002c67 */ + 0x002c6a, /* U+002c69 */ + 0x002c6c, /* U+002c6b */ + 0x002c73, /* U+002c72 */ + 0x002c76, /* U+002c75 */ + 0x002c81, /* U+002c80 */ + 0x002c83, /* U+002c82 */ + 0x002c85, /* U+002c84 */ + 0x002c87, /* U+002c86 */ + 0x002c89, /* U+002c88 */ + 0x002c8b, /* U+002c8a */ + 0x002c8d, /* U+002c8c */ + 0x002c8f, /* U+002c8e */ + 0x002c91, /* U+002c90 */ + 0x002c93, /* U+002c92 */ + 0x002c95, /* U+002c94 */ + 0x002c97, /* U+002c96 */ + 0x002c99, /* U+002c98 */ + 0x002c9b, /* U+002c9a */ + 0x002c9d, /* U+002c9c */ + 0x002c9f, /* U+002c9e */ + 0x002ca1, /* U+002ca0 */ + 0x002ca3, /* U+002ca2 */ + 0x002ca5, /* U+002ca4 */ + 0x002ca7, /* U+002ca6 */ + 0x002ca9, /* U+002ca8 */ + 0x002cab, /* U+002caa */ + 0x002cad, /* U+002cac */ + 0x002caf, /* U+002cae */ + 0x002cb1, /* U+002cb0 */ + 0x002cb3, /* U+002cb2 */ + 0x002cb5, /* U+002cb4 */ + 0x002cb7, /* U+002cb6 */ + 0x002cb9, /* U+002cb8 */ + 0x002cbb, /* U+002cba */ + 0x002cbd, /* U+002cbc */ + 0x002cbf, /* U+002cbe */ + 0x002cc1, /* U+002cc0 */ + 0x002cc3, /* U+002cc2 */ + 0x002cc5, /* U+002cc4 */ + 0x002cc7, /* U+002cc6 */ + 0x002cc9, /* U+002cc8 */ + 0x002ccb, /* U+002cca */ + 0x002ccd, /* U+002ccc */ + 0x002ccf, /* U+002cce */ + 0x002cd1, /* U+002cd0 */ + 0x002cd3, /* U+002cd2 */ + 0x002cd5, /* U+002cd4 */ + 0x002cd7, /* U+002cd6 */ + 0x002cd9, /* U+002cd8 */ + 0x002cdb, /* U+002cda */ + 0x002cdd, /* U+002cdc */ + 0x002cdf, /* U+002cde */ + 0x002ce1, /* U+002ce0 */ + 0x002ce3, /* U+002ce2 */ + 0x002cec, /* U+002ceb */ + 0x002cee, /* U+002ced */ + 0x002cf3, /* U+002cf2 */ + 0x00a641, /* U+00a640 */ + 0x00a643, /* U+00a642 */ + 0x00a645, /* U+00a644 */ + 0x00a647, /* U+00a646 */ + 0x00a649, /* U+00a648 */ + 0x00a64b, /* U+00a64a */ + 0x00a64d, /* U+00a64c */ + 0x00a64f, /* U+00a64e */ + 0x00a651, /* U+00a650 */ + 0x00a653, /* U+00a652 */ + 0x00a655, /* U+00a654 */ + 0x00a657, /* U+00a656 */ + 0x00a659, /* U+00a658 */ + 0x00a65b, /* U+00a65a */ + 0x00a65d, /* U+00a65c */ + 0x00a65f, /* U+00a65e */ + 0x00a661, /* U+00a660 */ + 0x00a663, /* U+00a662 */ + 0x00a665, /* U+00a664 */ + 0x00a667, /* U+00a666 */ + 0x00a669, /* U+00a668 */ + 0x00a66b, /* U+00a66a */ + 0x00a66d, /* U+00a66c */ + 0x00a681, /* U+00a680 */ + 0x00a683, /* U+00a682 */ + 0x00a685, /* U+00a684 */ + 0x00a687, /* U+00a686 */ + 0x00a689, /* U+00a688 */ + 0x00a68b, /* U+00a68a */ + 0x00a68d, /* U+00a68c */ + 0x00a68f, /* U+00a68e */ + 0x00a691, /* U+00a690 */ + 0x00a693, /* U+00a692 */ + 0x00a695, /* U+00a694 */ + 0x00a697, /* U+00a696 */ + 0x00a699, /* U+00a698 */ + 0x00a69b, /* U+00a69a */ + 0x00a723, /* U+00a722 */ + 0x00a725, /* U+00a724 */ + 0x00a727, /* U+00a726 */ + 0x00a729, /* U+00a728 */ + 0x00a72b, /* U+00a72a */ + 0x00a72d, /* U+00a72c */ + 0x00a72f, /* U+00a72e */ + 0x00a733, /* U+00a732 */ + 0x00a735, /* U+00a734 */ + 0x00a737, /* U+00a736 */ + 0x00a739, /* U+00a738 */ + 0x00a73b, /* U+00a73a */ + 0x00a73d, /* U+00a73c */ + 0x00a73f, /* U+00a73e */ + 0x00a741, /* U+00a740 */ + 0x00a743, /* U+00a742 */ + 0x00a745, /* U+00a744 */ + 0x00a747, /* U+00a746 */ + 0x00a749, /* U+00a748 */ + 0x00a74b, /* U+00a74a */ + 0x00a74d, /* U+00a74c */ + 0x00a74f, /* U+00a74e */ + 0x00a751, /* U+00a750 */ + 0x00a753, /* U+00a752 */ + 0x00a755, /* U+00a754 */ + 0x00a757, /* U+00a756 */ + 0x00a759, /* U+00a758 */ + 0x00a75b, /* U+00a75a */ + 0x00a75d, /* U+00a75c */ + 0x00a75f, /* U+00a75e */ + 0x00a761, /* U+00a760 */ + 0x00a763, /* U+00a762 */ + 0x00a765, /* U+00a764 */ + 0x00a767, /* U+00a766 */ + 0x00a769, /* U+00a768 */ + 0x00a76b, /* U+00a76a */ + 0x00a76d, /* U+00a76c */ + 0x00a76f, /* U+00a76e */ + 0x00a77a, /* U+00a779 */ + 0x00a77c, /* U+00a77b */ + 0x00a77f, /* U+00a77e */ + 0x00a781, /* U+00a780 */ + 0x00a783, /* U+00a782 */ + 0x00a785, /* U+00a784 */ + 0x00a787, /* U+00a786 */ + 0x00a78c, /* U+00a78b */ + 0x00a791, /* U+00a790 */ + 0x00a793, /* U+00a792 */ + 0x00a794, /* U+00a794 */ + 0x00a797, /* U+00a796 */ + 0x00a799, /* U+00a798 */ + 0x00a79b, /* U+00a79a */ + 0x00a79d, /* U+00a79c */ + 0x00a79f, /* U+00a79e */ + 0x00a7a1, /* U+00a7a0 */ + 0x00a7a3, /* U+00a7a2 */ + 0x00a7a5, /* U+00a7a4 */ + 0x00a7a7, /* U+00a7a6 */ + 0x00a7a9, /* U+00a7a8 */ + 0x00ab53, /* U+00a7b3 */ + 0x00a7b5, /* U+00a7b4 */ + 0x00a7b7, /* U+00a7b6 */ + 0x00a7b9, /* U+00a7b8 */ + 0x00a7bb, /* U+00a7ba */ + 0x00a7bd, /* U+00a7bc */ + 0x00a7bf, /* U+00a7be */ + 0x00a7c1, /* U+00a7c0 */ + 0x00a7c3, /* U+00a7c2 */ + 0x00a7c8, /* U+00a7c7 */ + 0x00a7ca, /* U+00a7c9 */ + 0x00a7cd, /* U+00a7cc */ + 0x00a7d1, /* U+00a7d0 */ + 0x00a7d7, /* U+00a7d6 */ + 0x00a7d9, /* U+00a7d8 */ + 0x00a7db, /* U+00a7da */ + 0x00a7f6, /* U+00a7f5 */ + 0x00fb00, /* U+00fb00 */ + 0x00fb01, /* U+00fb01 */ + 0x00fb02, /* U+00fb02 */ + 0x00fb03, /* U+00fb03 */ + 0x00fb04, /* U+00fb04 */ + 0x00fb06, /* U+00fb05 */ + 0x00fb06, /* U+00fb06 */ + 0x00fb13, /* U+00fb13 */ + 0x00fb14, /* U+00fb14 */ + 0x00fb15, /* U+00fb15 */ + 0x00fb16, /* U+00fb16 */ + 0x00fb17, /* U+00fb17 */ + 0x00ff41, /* U+00ff21 */ + 0x00ff42, /* U+00ff22 */ + 0x00ff43, /* U+00ff23 */ + 0x00ff44, /* U+00ff24 */ + 0x00ff45, /* U+00ff25 */ + 0x00ff46, /* U+00ff26 */ + 0x00ff47, /* U+00ff27 */ + 0x00ff48, /* U+00ff28 */ + 0x00ff49, /* U+00ff29 */ + 0x00ff4a, /* U+00ff2a */ + 0x00ff4b, /* U+00ff2b */ + 0x00ff4c, /* U+00ff2c */ + 0x00ff4d, /* U+00ff2d */ + 0x00ff4e, /* U+00ff2e */ + 0x00ff4f, /* U+00ff2f */ + 0x00ff50, /* U+00ff30 */ + 0x00ff51, /* U+00ff31 */ + 0x00ff52, /* U+00ff32 */ + 0x00ff53, /* U+00ff33 */ + 0x00ff54, /* U+00ff34 */ + 0x00ff55, /* U+00ff35 */ + 0x00ff56, /* U+00ff36 */ + 0x00ff57, /* U+00ff37 */ + 0x00ff58, /* U+00ff38 */ + 0x00ff59, /* U+00ff39 */ + 0x00ff5a, /* U+00ff3a */ + 0x010428, /* U+010400 */ + 0x010429, /* U+010401 */ + 0x01042a, /* U+010402 */ + 0x01042b, /* U+010403 */ + 0x01042c, /* U+010404 */ + 0x01042d, /* U+010405 */ + 0x01042e, /* U+010406 */ + 0x01042f, /* U+010407 */ + 0x010430, /* U+010408 */ + 0x010431, /* U+010409 */ + 0x010432, /* U+01040a */ + 0x010433, /* U+01040b */ + 0x010434, /* U+01040c */ + 0x010435, /* U+01040d */ + 0x010436, /* U+01040e */ + 0x010437, /* U+01040f */ + 0x010438, /* U+010410 */ + 0x010439, /* U+010411 */ + 0x01043a, /* U+010412 */ + 0x01043b, /* U+010413 */ + 0x01043c, /* U+010414 */ + 0x01043d, /* U+010415 */ + 0x01043e, /* U+010416 */ + 0x01043f, /* U+010417 */ + 0x010440, /* U+010418 */ + 0x010441, /* U+010419 */ + 0x010442, /* U+01041a */ + 0x010443, /* U+01041b */ + 0x010444, /* U+01041c */ + 0x010445, /* U+01041d */ + 0x010446, /* U+01041e */ + 0x010447, /* U+01041f */ + 0x010448, /* U+010420 */ + 0x010449, /* U+010421 */ + 0x01044a, /* U+010422 */ + 0x01044b, /* U+010423 */ + 0x01044c, /* U+010424 */ + 0x01044d, /* U+010425 */ + 0x01044e, /* U+010426 */ + 0x01044f, /* U+010427 */ + 0x0104d8, /* U+0104b0 */ + 0x0104d9, /* U+0104b1 */ + 0x0104da, /* U+0104b2 */ + 0x0104db, /* U+0104b3 */ + 0x0104dc, /* U+0104b4 */ + 0x0104dd, /* U+0104b5 */ + 0x0104de, /* U+0104b6 */ + 0x0104df, /* U+0104b7 */ + 0x0104e0, /* U+0104b8 */ + 0x0104e1, /* U+0104b9 */ + 0x0104e2, /* U+0104ba */ + 0x0104e3, /* U+0104bb */ + 0x0104e4, /* U+0104bc */ + 0x0104e5, /* U+0104bd */ + 0x0104e6, /* U+0104be */ + 0x0104e7, /* U+0104bf */ + 0x0104e8, /* U+0104c0 */ + 0x0104e9, /* U+0104c1 */ + 0x0104ea, /* U+0104c2 */ + 0x0104eb, /* U+0104c3 */ + 0x0104ec, /* U+0104c4 */ + 0x0104ed, /* U+0104c5 */ + 0x0104ee, /* U+0104c6 */ + 0x0104ef, /* U+0104c7 */ + 0x0104f0, /* U+0104c8 */ + 0x0104f1, /* U+0104c9 */ + 0x0104f2, /* U+0104ca */ + 0x0104f3, /* U+0104cb */ + 0x0104f4, /* U+0104cc */ + 0x0104f5, /* U+0104cd */ + 0x0104f6, /* U+0104ce */ + 0x0104f7, /* U+0104cf */ + 0x0104f8, /* U+0104d0 */ + 0x0104f9, /* U+0104d1 */ + 0x0104fa, /* U+0104d2 */ + 0x0104fb, /* U+0104d3 */ + 0x010597, /* U+010570 */ + 0x010598, /* U+010571 */ + 0x010599, /* U+010572 */ + 0x01059a, /* U+010573 */ + 0x01059b, /* U+010574 */ + 0x01059c, /* U+010575 */ + 0x01059d, /* U+010576 */ + 0x01059e, /* U+010577 */ + 0x01059f, /* U+010578 */ + 0x0105a0, /* U+010579 */ + 0x0105a1, /* U+01057a */ + 0x0105a3, /* U+01057c */ + 0x0105a4, /* U+01057d */ + 0x0105a5, /* U+01057e */ + 0x0105a6, /* U+01057f */ + 0x0105a7, /* U+010580 */ + 0x0105a8, /* U+010581 */ + 0x0105a9, /* U+010582 */ + 0x0105aa, /* U+010583 */ + 0x0105ab, /* U+010584 */ + 0x0105ac, /* U+010585 */ + 0x0105ad, /* U+010586 */ + 0x0105ae, /* U+010587 */ + 0x0105af, /* U+010588 */ + 0x0105b0, /* U+010589 */ + 0x0105b1, /* U+01058a */ + 0x0105b3, /* U+01058c */ + 0x0105b4, /* U+01058d */ + 0x0105b5, /* U+01058e */ + 0x0105b6, /* U+01058f */ + 0x0105b7, /* U+010590 */ + 0x0105b8, /* U+010591 */ + 0x0105b9, /* U+010592 */ + 0x0105bb, /* U+010594 */ + 0x0105bc, /* U+010595 */ + 0x010cc0, /* U+010c80 */ + 0x010cc1, /* U+010c81 */ + 0x010cc2, /* U+010c82 */ + 0x010cc3, /* U+010c83 */ + 0x010cc4, /* U+010c84 */ + 0x010cc5, /* U+010c85 */ + 0x010cc6, /* U+010c86 */ + 0x010cc7, /* U+010c87 */ + 0x010cc8, /* U+010c88 */ + 0x010cc9, /* U+010c89 */ + 0x010cca, /* U+010c8a */ + 0x010ccb, /* U+010c8b */ + 0x010ccc, /* U+010c8c */ + 0x010ccd, /* U+010c8d */ + 0x010cce, /* U+010c8e */ + 0x010ccf, /* U+010c8f */ + 0x010cd0, /* U+010c90 */ + 0x010cd1, /* U+010c91 */ + 0x010cd2, /* U+010c92 */ + 0x010cd3, /* U+010c93 */ + 0x010cd4, /* U+010c94 */ + 0x010cd5, /* U+010c95 */ + 0x010cd6, /* U+010c96 */ + 0x010cd7, /* U+010c97 */ + 0x010cd8, /* U+010c98 */ + 0x010cd9, /* U+010c99 */ + 0x010cda, /* U+010c9a */ + 0x010cdb, /* U+010c9b */ + 0x010cdc, /* U+010c9c */ + 0x010cdd, /* U+010c9d */ + 0x010cde, /* U+010c9e */ + 0x010cdf, /* U+010c9f */ + 0x010ce0, /* U+010ca0 */ + 0x010ce1, /* U+010ca1 */ + 0x010ce2, /* U+010ca2 */ + 0x010ce3, /* U+010ca3 */ + 0x010ce4, /* U+010ca4 */ + 0x010ce5, /* U+010ca5 */ + 0x010ce6, /* U+010ca6 */ + 0x010ce7, /* U+010ca7 */ + 0x010ce8, /* U+010ca8 */ + 0x010ce9, /* U+010ca9 */ + 0x010cea, /* U+010caa */ + 0x010ceb, /* U+010cab */ + 0x010cec, /* U+010cac */ + 0x010ced, /* U+010cad */ + 0x010cee, /* U+010cae */ + 0x010cef, /* U+010caf */ + 0x010cf0, /* U+010cb0 */ + 0x010cf1, /* U+010cb1 */ + 0x010cf2, /* U+010cb2 */ + 0x010d70, /* U+010d50 */ + 0x010d71, /* U+010d51 */ + 0x010d72, /* U+010d52 */ + 0x010d73, /* U+010d53 */ + 0x010d74, /* U+010d54 */ + 0x010d75, /* U+010d55 */ + 0x010d76, /* U+010d56 */ + 0x010d77, /* U+010d57 */ + 0x010d78, /* U+010d58 */ + 0x010d79, /* U+010d59 */ + 0x010d7a, /* U+010d5a */ + 0x010d7b, /* U+010d5b */ + 0x010d7c, /* U+010d5c */ + 0x010d7d, /* U+010d5d */ + 0x010d7e, /* U+010d5e */ + 0x010d7f, /* U+010d5f */ + 0x010d80, /* U+010d60 */ + 0x010d81, /* U+010d61 */ + 0x010d82, /* U+010d62 */ + 0x010d83, /* U+010d63 */ + 0x010d84, /* U+010d64 */ + 0x010d85, /* U+010d65 */ + 0x0118c0, /* U+0118a0 */ + 0x0118c1, /* U+0118a1 */ + 0x0118c2, /* U+0118a2 */ + 0x0118c3, /* U+0118a3 */ + 0x0118c4, /* U+0118a4 */ + 0x0118c5, /* U+0118a5 */ + 0x0118c6, /* U+0118a6 */ + 0x0118c7, /* U+0118a7 */ + 0x0118c8, /* U+0118a8 */ + 0x0118c9, /* U+0118a9 */ + 0x0118ca, /* U+0118aa */ + 0x0118cb, /* U+0118ab */ + 0x0118cc, /* U+0118ac */ + 0x0118cd, /* U+0118ad */ + 0x0118ce, /* U+0118ae */ + 0x0118cf, /* U+0118af */ + 0x0118d0, /* U+0118b0 */ + 0x0118d1, /* U+0118b1 */ + 0x0118d2, /* U+0118b2 */ + 0x0118d3, /* U+0118b3 */ + 0x0118d4, /* U+0118b4 */ + 0x0118d5, /* U+0118b5 */ + 0x0118d6, /* U+0118b6 */ + 0x0118d7, /* U+0118b7 */ + 0x0118d8, /* U+0118b8 */ + 0x0118d9, /* U+0118b9 */ + 0x0118da, /* U+0118ba */ + 0x0118db, /* U+0118bb */ + 0x0118dc, /* U+0118bc */ + 0x0118dd, /* U+0118bd */ + 0x0118de, /* U+0118be */ + 0x0118df, /* U+0118bf */ + 0x016e60, /* U+016e40 */ + 0x016e61, /* U+016e41 */ + 0x016e62, /* U+016e42 */ + 0x016e63, /* U+016e43 */ + 0x016e64, /* U+016e44 */ + 0x016e65, /* U+016e45 */ + 0x016e66, /* U+016e46 */ + 0x016e67, /* U+016e47 */ + 0x016e68, /* U+016e48 */ + 0x016e69, /* U+016e49 */ + 0x016e6a, /* U+016e4a */ + 0x016e6b, /* U+016e4b */ + 0x016e6c, /* U+016e4c */ + 0x016e6d, /* U+016e4d */ + 0x016e6e, /* U+016e4e */ + 0x016e6f, /* U+016e4f */ + 0x016e70, /* U+016e50 */ + 0x016e71, /* U+016e51 */ + 0x016e72, /* U+016e52 */ + 0x016e73, /* U+016e53 */ + 0x016e74, /* U+016e54 */ + 0x016e75, /* U+016e55 */ + 0x016e76, /* U+016e56 */ + 0x016e77, /* U+016e57 */ + 0x016e78, /* U+016e58 */ + 0x016e79, /* U+016e59 */ + 0x016e7a, /* U+016e5a */ + 0x016e7b, /* U+016e5b */ + 0x016e7c, /* U+016e5c */ + 0x016e7d, /* U+016e5d */ + 0x016e7e, /* U+016e5e */ + 0x016e7f, /* U+016e5f */ + 0x01e922, /* U+01e900 */ + 0x01e923, /* U+01e901 */ + 0x01e924, /* U+01e902 */ + 0x01e925, /* U+01e903 */ + 0x01e926, /* U+01e904 */ + 0x01e927, /* U+01e905 */ + 0x01e928, /* U+01e906 */ + 0x01e929, /* U+01e907 */ + 0x01e92a, /* U+01e908 */ + 0x01e92b, /* U+01e909 */ + 0x01e92c, /* U+01e90a */ + 0x01e92d, /* U+01e90b */ + 0x01e92e, /* U+01e90c */ + 0x01e92f, /* U+01e90d */ + 0x01e930, /* U+01e90e */ + 0x01e931, /* U+01e90f */ + 0x01e932, /* U+01e910 */ + 0x01e933, /* U+01e911 */ + 0x01e934, /* U+01e912 */ + 0x01e935, /* U+01e913 */ + 0x01e936, /* U+01e914 */ + 0x01e937, /* U+01e915 */ + 0x01e938, /* U+01e916 */ + 0x01e939, /* U+01e917 */ + 0x01e93a, /* U+01e918 */ + 0x01e93b, /* U+01e919 */ + 0x01e93c, /* U+01e91a */ + 0x01e93d, /* U+01e91b */ + 0x01e93e, /* U+01e91c */ + 0x01e93f, /* U+01e91d */ + 0x01e940, /* U+01e91e */ + 0x01e941, /* U+01e91f */ + 0x01e942, /* U+01e920 */ + 0x01e943, /* U+01e921 */ + +}; + +/* + * The entry case_map_special[case_index(codepoint)] is the index in + * special_case for that codepoint, or 0 if no special case mapping exists. + */ +static const uint8 case_map_special[1704] = +{ + 0, /* reserved */ + 0, /* U+000000 */ + 0, /* U+000001 */ + 0, /* U+000002 */ + 0, /* U+000003 */ + 0, /* U+000004 */ + 0, /* U+000005 */ + 0, /* U+000006 */ + 0, /* U+000007 */ + 0, /* U+000008 */ + 0, /* U+000009 */ + 0, /* U+00000a */ + 0, /* U+00000b */ + 0, /* U+00000c */ + 0, /* U+00000d */ + 0, /* U+00000e */ + 0, /* U+00000f */ + 0, /* U+000010 */ + 0, /* U+000011 */ + 0, /* U+000012 */ + 0, /* U+000013 */ + 0, /* U+000014 */ + 0, /* U+000015 */ + 0, /* U+000016 */ + 0, /* U+000017 */ + 0, /* U+000018 */ + 0, /* U+000019 */ + 0, /* U+00001a */ + 0, /* U+00001b */ + 0, /* U+00001c */ + 0, /* U+00001d */ + 0, /* U+00001e */ + 0, /* U+00001f */ + 0, /* U+000020 */ + 0, /* U+000021 */ + 0, /* U+000022 */ + 0, /* U+000023 */ + 0, /* U+000024 */ + 0, /* U+000025 */ + 0, /* U+000026 */ + 0, /* U+000027 */ + 0, /* U+000028 */ + 0, /* U+000029 */ + 0, /* U+00002a */ + 0, /* U+00002b */ + 0, /* U+00002c */ + 0, /* U+00002d */ + 0, /* U+00002e */ + 0, /* U+00002f */ + 0, /* U+000030 */ + 0, /* U+000031 */ + 0, /* U+000032 */ + 0, /* U+000033 */ + 0, /* U+000034 */ + 0, /* U+000035 */ + 0, /* U+000036 */ + 0, /* U+000037 */ + 0, /* U+000038 */ + 0, /* U+000039 */ + 0, /* U+00003a */ + 0, /* U+00003b */ + 0, /* U+00003c */ + 0, /* U+00003d */ + 0, /* U+00003e */ + 0, /* U+00003f */ + 0, /* U+000040 */ + 0, /* U+000041 */ + 0, /* U+000042 */ + 0, /* U+000043 */ + 0, /* U+000044 */ + 0, /* U+000045 */ + 0, /* U+000046 */ + 0, /* U+000047 */ + 0, /* U+000048 */ + 0, /* U+000049 */ + 0, /* U+00004a */ + 0, /* U+00004b */ + 0, /* U+00004c */ + 0, /* U+00004d */ + 0, /* U+00004e */ + 0, /* U+00004f */ + 0, /* U+000050 */ + 0, /* U+000051 */ + 0, /* U+000052 */ + 0, /* U+000053 */ + 0, /* U+000054 */ + 0, /* U+000055 */ + 0, /* U+000056 */ + 0, /* U+000057 */ + 0, /* U+000058 */ + 0, /* U+000059 */ + 0, /* U+00005a */ + 0, /* U+00005b */ + 0, /* U+00005c */ + 0, /* U+00005d */ + 0, /* U+00005e */ + 0, /* U+00005f */ + 0, /* U+000060 */ + 0, /* U+000061 */ + 0, /* U+000062 */ + 0, /* U+000063 */ + 0, /* U+000064 */ + 0, /* U+000065 */ + 0, /* U+000066 */ + 0, /* U+000067 */ + 0, /* U+000068 */ + 0, /* U+000069 */ + 0, /* U+00006a */ + 0, /* U+00006b */ + 0, /* U+00006c */ + 0, /* U+00006d */ + 0, /* U+00006e */ + 0, /* U+00006f */ + 0, /* U+000070 */ + 0, /* U+000071 */ + 0, /* U+000072 */ + 0, /* U+000073 */ + 0, /* U+000074 */ + 0, /* U+000075 */ + 0, /* U+000076 */ + 0, /* U+000077 */ + 0, /* U+000078 */ + 0, /* U+000079 */ + 0, /* U+00007a */ + 0, /* U+00007b */ + 0, /* U+00007c */ + 0, /* U+00007d */ + 0, /* U+00007e */ + 0, /* U+00007f */ + 0, /* U+0000b5 */ + 0, /* U+0000c0 */ + 0, /* U+0000c1 */ + 0, /* U+0000c2 */ + 0, /* U+0000c3 */ + 0, /* U+0000c4 */ + 0, /* U+0000c5 */ + 0, /* U+0000c6 */ + 0, /* U+0000c7 */ + 0, /* U+0000c8 */ + 0, /* U+0000c9 */ + 0, /* U+0000ca */ + 0, /* U+0000cb */ + 0, /* U+0000cc */ + 0, /* U+0000cd */ + 0, /* U+0000ce */ + 0, /* U+0000cf */ + 0, /* U+0000d0 */ + 0, /* U+0000d1 */ + 0, /* U+0000d2 */ + 0, /* U+0000d3 */ + 0, /* U+0000d4 */ + 0, /* U+0000d5 */ + 0, /* U+0000d6 */ + 0, /* U+0000d8 */ + 0, /* U+0000d9 */ + 0, /* U+0000da */ + 0, /* U+0000db */ + 0, /* U+0000dc */ + 0, /* U+0000dd */ + 0, /* U+0000de */ + 1, /* U+0000df */ + 0, /* U+0000ff */ + 0, /* U+000100 */ + 0, /* U+000102 */ + 0, /* U+000104 */ + 0, /* U+000106 */ + 0, /* U+000108 */ + 0, /* U+00010a */ + 0, /* U+00010c */ + 0, /* U+00010e */ + 0, /* U+000110 */ + 0, /* U+000112 */ + 0, /* U+000114 */ + 0, /* U+000116 */ + 0, /* U+000118 */ + 0, /* U+00011a */ + 0, /* U+00011c */ + 0, /* U+00011e */ + 0, /* U+000120 */ + 0, /* U+000122 */ + 0, /* U+000124 */ + 0, /* U+000126 */ + 0, /* U+000128 */ + 0, /* U+00012a */ + 0, /* U+00012c */ + 0, /* U+00012e */ + 2, /* U+000130 */ + 0, /* U+000131 */ + 0, /* U+000132 */ + 0, /* U+000134 */ + 0, /* U+000136 */ + 0, /* U+000139 */ + 0, /* U+00013b */ + 0, /* U+00013d */ + 0, /* U+00013f */ + 0, /* U+000141 */ + 0, /* U+000143 */ + 0, /* U+000145 */ + 0, /* U+000147 */ + 3, /* U+000149 */ + 0, /* U+00014a */ + 0, /* U+00014c */ + 0, /* U+00014e */ + 0, /* U+000150 */ + 0, /* U+000152 */ + 0, /* U+000154 */ + 0, /* U+000156 */ + 0, /* U+000158 */ + 0, /* U+00015a */ + 0, /* U+00015c */ + 0, /* U+00015e */ + 0, /* U+000160 */ + 0, /* U+000162 */ + 0, /* U+000164 */ + 0, /* U+000166 */ + 0, /* U+000168 */ + 0, /* U+00016a */ + 0, /* U+00016c */ + 0, /* U+00016e */ + 0, /* U+000170 */ + 0, /* U+000172 */ + 0, /* U+000174 */ + 0, /* U+000176 */ + 0, /* U+000179 */ + 0, /* U+00017b */ + 0, /* U+00017d */ + 0, /* U+00017f */ + 0, /* U+000180 */ + 0, /* U+000181 */ + 0, /* U+000182 */ + 0, /* U+000184 */ + 0, /* U+000186 */ + 0, /* U+000187 */ + 0, /* U+000189 */ + 0, /* U+00018a */ + 0, /* U+00018b */ + 0, /* U+00018e */ + 0, /* U+00018f */ + 0, /* U+000190 */ + 0, /* U+000191 */ + 0, /* U+000193 */ + 0, /* U+000194 */ + 0, /* U+000195 */ + 0, /* U+000196 */ + 0, /* U+000197 */ + 0, /* U+000198 */ + 0, /* U+00019a */ + 0, /* U+00019b */ + 0, /* U+00019c */ + 0, /* U+00019d */ + 0, /* U+00019e */ + 0, /* U+00019f */ + 0, /* U+0001a0 */ + 0, /* U+0001a2 */ + 0, /* U+0001a4 */ + 0, /* U+0001a6 */ + 0, /* U+0001a7 */ + 0, /* U+0001a9 */ + 0, /* U+0001ac */ + 0, /* U+0001ae */ + 0, /* U+0001af */ + 0, /* U+0001b1 */ + 0, /* U+0001b2 */ + 0, /* U+0001b3 */ + 0, /* U+0001b5 */ + 0, /* U+0001b7 */ + 0, /* U+0001b8 */ + 0, /* U+0001bc */ + 0, /* U+0001bf */ + 0, /* U+0001c4 */ + 0, /* U+0001c7 */ + 0, /* U+0001ca */ + 0, /* U+0001cd */ + 0, /* U+0001cf */ + 0, /* U+0001d1 */ + 0, /* U+0001d3 */ + 0, /* U+0001d5 */ + 0, /* U+0001d7 */ + 0, /* U+0001d9 */ + 0, /* U+0001db */ + 0, /* U+0001de */ + 0, /* U+0001e0 */ + 0, /* U+0001e2 */ + 0, /* U+0001e4 */ + 0, /* U+0001e6 */ + 0, /* U+0001e8 */ + 0, /* U+0001ea */ + 0, /* U+0001ec */ + 0, /* U+0001ee */ + 4, /* U+0001f0 */ + 0, /* U+0001f1 */ + 0, /* U+0001f4 */ + 0, /* U+0001f8 */ + 0, /* U+0001fa */ + 0, /* U+0001fc */ + 0, /* U+0001fe */ + 0, /* U+000200 */ + 0, /* U+000202 */ + 0, /* U+000204 */ + 0, /* U+000206 */ + 0, /* U+000208 */ + 0, /* U+00020a */ + 0, /* U+00020c */ + 0, /* U+00020e */ + 0, /* U+000210 */ + 0, /* U+000212 */ + 0, /* U+000214 */ + 0, /* U+000216 */ + 0, /* U+000218 */ + 0, /* U+00021a */ + 0, /* U+00021c */ + 0, /* U+00021e */ + 0, /* U+000222 */ + 0, /* U+000224 */ + 0, /* U+000226 */ + 0, /* U+000228 */ + 0, /* U+00022a */ + 0, /* U+00022c */ + 0, /* U+00022e */ + 0, /* U+000230 */ + 0, /* U+000232 */ + 0, /* U+00023a */ + 0, /* U+00023b */ + 0, /* U+00023e */ + 0, /* U+00023f */ + 0, /* U+000240 */ + 0, /* U+000241 */ + 0, /* U+000244 */ + 0, /* U+000245 */ + 0, /* U+000246 */ + 0, /* U+000248 */ + 0, /* U+00024a */ + 0, /* U+00024c */ + 0, /* U+00024e */ + 0, /* U+000250 */ + 0, /* U+000251 */ + 0, /* U+000252 */ + 0, /* U+00025c */ + 0, /* U+000261 */ + 0, /* U+000264 */ + 0, /* U+000265 */ + 0, /* U+000266 */ + 0, /* U+00026a */ + 0, /* U+00026b */ + 0, /* U+00026c */ + 0, /* U+000271 */ + 0, /* U+00027d */ + 0, /* U+000282 */ + 0, /* U+000287 */ + 0, /* U+00029d */ + 0, /* U+00029e */ + 0, /* U+000345 */ + 0, /* U+000370 */ + 0, /* U+000372 */ + 0, /* U+000376 */ + 0, /* U+00037b */ + 0, /* U+00037c */ + 0, /* U+00037d */ + 0, /* U+00037f */ + 0, /* U+000386 */ + 0, /* U+000388 */ + 0, /* U+000389 */ + 0, /* U+00038a */ + 0, /* U+00038c */ + 0, /* U+00038e */ + 0, /* U+00038f */ + 5, /* U+000390 */ + 0, /* U+000391 */ + 0, /* U+000392 */ + 0, /* U+000393 */ + 0, /* U+000394 */ + 0, /* U+000395 */ + 0, /* U+000396 */ + 0, /* U+000397 */ + 0, /* U+000398 */ + 0, /* U+000399 */ + 0, /* U+00039a */ + 0, /* U+00039b */ + 0, /* U+00039c */ + 0, /* U+00039d */ + 0, /* U+00039e */ + 0, /* U+00039f */ + 0, /* U+0003a0 */ + 0, /* U+0003a1 */ + 6, /* U+0003a3 */ + 0, /* U+0003a4 */ + 0, /* U+0003a5 */ + 0, /* U+0003a6 */ + 0, /* U+0003a7 */ + 0, /* U+0003a8 */ + 0, /* U+0003a9 */ + 0, /* U+0003aa */ + 0, /* U+0003ab */ + 7, /* U+0003b0 */ + 0, /* U+0003c2 */ + 0, /* U+0003c3 */ + 0, /* U+0003cf */ + 0, /* U+0003d0 */ + 0, /* U+0003d1 */ + 0, /* U+0003d5 */ + 0, /* U+0003d6 */ + 0, /* U+0003d8 */ + 0, /* U+0003da */ + 0, /* U+0003dc */ + 0, /* U+0003de */ + 0, /* U+0003e0 */ + 0, /* U+0003e2 */ + 0, /* U+0003e4 */ + 0, /* U+0003e6 */ + 0, /* U+0003e8 */ + 0, /* U+0003ea */ + 0, /* U+0003ec */ + 0, /* U+0003ee */ + 0, /* U+0003f0 */ + 0, /* U+0003f1 */ + 0, /* U+0003f2 */ + 0, /* U+0003f4 */ + 0, /* U+0003f5 */ + 0, /* U+0003f7 */ + 0, /* U+0003fa */ + 0, /* U+000400 */ + 0, /* U+000401 */ + 0, /* U+000402 */ + 0, /* U+000403 */ + 0, /* U+000404 */ + 0, /* U+000405 */ + 0, /* U+000406 */ + 0, /* U+000407 */ + 0, /* U+000408 */ + 0, /* U+000409 */ + 0, /* U+00040a */ + 0, /* U+00040b */ + 0, /* U+00040c */ + 0, /* U+00040d */ + 0, /* U+00040e */ + 0, /* U+00040f */ + 0, /* U+000410 */ + 0, /* U+000411 */ + 0, /* U+000412 */ + 0, /* U+000413 */ + 0, /* U+000414 */ + 0, /* U+000415 */ + 0, /* U+000416 */ + 0, /* U+000417 */ + 0, /* U+000418 */ + 0, /* U+000419 */ + 0, /* U+00041a */ + 0, /* U+00041b */ + 0, /* U+00041c */ + 0, /* U+00041d */ + 0, /* U+00041e */ + 0, /* U+00041f */ + 0, /* U+000420 */ + 0, /* U+000421 */ + 0, /* U+000422 */ + 0, /* U+000423 */ + 0, /* U+000424 */ + 0, /* U+000425 */ + 0, /* U+000426 */ + 0, /* U+000427 */ + 0, /* U+000428 */ + 0, /* U+000429 */ + 0, /* U+00042a */ + 0, /* U+00042b */ + 0, /* U+00042c */ + 0, /* U+00042d */ + 0, /* U+00042e */ + 0, /* U+00042f */ + 0, /* U+000460 */ + 0, /* U+000462 */ + 0, /* U+000464 */ + 0, /* U+000466 */ + 0, /* U+000468 */ + 0, /* U+00046a */ + 0, /* U+00046c */ + 0, /* U+00046e */ + 0, /* U+000470 */ + 0, /* U+000472 */ + 0, /* U+000474 */ + 0, /* U+000476 */ + 0, /* U+000478 */ + 0, /* U+00047a */ + 0, /* U+00047c */ + 0, /* U+00047e */ + 0, /* U+000480 */ + 0, /* U+00048a */ + 0, /* U+00048c */ + 0, /* U+00048e */ + 0, /* U+000490 */ + 0, /* U+000492 */ + 0, /* U+000494 */ + 0, /* U+000496 */ + 0, /* U+000498 */ + 0, /* U+00049a */ + 0, /* U+00049c */ + 0, /* U+00049e */ + 0, /* U+0004a0 */ + 0, /* U+0004a2 */ + 0, /* U+0004a4 */ + 0, /* U+0004a6 */ + 0, /* U+0004a8 */ + 0, /* U+0004aa */ + 0, /* U+0004ac */ + 0, /* U+0004ae */ + 0, /* U+0004b0 */ + 0, /* U+0004b2 */ + 0, /* U+0004b4 */ + 0, /* U+0004b6 */ + 0, /* U+0004b8 */ + 0, /* U+0004ba */ + 0, /* U+0004bc */ + 0, /* U+0004be */ + 0, /* U+0004c0 */ + 0, /* U+0004c1 */ + 0, /* U+0004c3 */ + 0, /* U+0004c5 */ + 0, /* U+0004c7 */ + 0, /* U+0004c9 */ + 0, /* U+0004cb */ + 0, /* U+0004cd */ + 0, /* U+0004d0 */ + 0, /* U+0004d2 */ + 0, /* U+0004d4 */ + 0, /* U+0004d6 */ + 0, /* U+0004d8 */ + 0, /* U+0004da */ + 0, /* U+0004dc */ + 0, /* U+0004de */ + 0, /* U+0004e0 */ + 0, /* U+0004e2 */ + 0, /* U+0004e4 */ + 0, /* U+0004e6 */ + 0, /* U+0004e8 */ + 0, /* U+0004ea */ + 0, /* U+0004ec */ + 0, /* U+0004ee */ + 0, /* U+0004f0 */ + 0, /* U+0004f2 */ + 0, /* U+0004f4 */ + 0, /* U+0004f6 */ + 0, /* U+0004f8 */ + 0, /* U+0004fa */ + 0, /* U+0004fc */ + 0, /* U+0004fe */ + 0, /* U+000500 */ + 0, /* U+000502 */ + 0, /* U+000504 */ + 0, /* U+000506 */ + 0, /* U+000508 */ + 0, /* U+00050a */ + 0, /* U+00050c */ + 0, /* U+00050e */ + 0, /* U+000510 */ + 0, /* U+000512 */ + 0, /* U+000514 */ + 0, /* U+000516 */ + 0, /* U+000518 */ + 0, /* U+00051a */ + 0, /* U+00051c */ + 0, /* U+00051e */ + 0, /* U+000520 */ + 0, /* U+000522 */ + 0, /* U+000524 */ + 0, /* U+000526 */ + 0, /* U+000528 */ + 0, /* U+00052a */ + 0, /* U+00052c */ + 0, /* U+00052e */ + 0, /* U+000531 */ + 0, /* U+000532 */ + 0, /* U+000533 */ + 0, /* U+000534 */ + 0, /* U+000535 */ + 0, /* U+000536 */ + 0, /* U+000537 */ + 0, /* U+000538 */ + 0, /* U+000539 */ + 0, /* U+00053a */ + 0, /* U+00053b */ + 0, /* U+00053c */ + 0, /* U+00053d */ + 0, /* U+00053e */ + 0, /* U+00053f */ + 0, /* U+000540 */ + 0, /* U+000541 */ + 0, /* U+000542 */ + 0, /* U+000543 */ + 0, /* U+000544 */ + 0, /* U+000545 */ + 0, /* U+000546 */ + 0, /* U+000547 */ + 0, /* U+000548 */ + 0, /* U+000549 */ + 0, /* U+00054a */ + 0, /* U+00054b */ + 0, /* U+00054c */ + 0, /* U+00054d */ + 0, /* U+00054e */ + 0, /* U+00054f */ + 0, /* U+000550 */ + 0, /* U+000551 */ + 0, /* U+000552 */ + 0, /* U+000553 */ + 0, /* U+000554 */ + 0, /* U+000555 */ + 0, /* U+000556 */ + 8, /* U+000587 */ + 0, /* U+0010a0 */ + 0, /* U+0010a1 */ + 0, /* U+0010a2 */ + 0, /* U+0010a3 */ + 0, /* U+0010a4 */ + 0, /* U+0010a5 */ + 0, /* U+0010a6 */ + 0, /* U+0010a7 */ + 0, /* U+0010a8 */ + 0, /* U+0010a9 */ + 0, /* U+0010aa */ + 0, /* U+0010ab */ + 0, /* U+0010ac */ + 0, /* U+0010ad */ + 0, /* U+0010ae */ + 0, /* U+0010af */ + 0, /* U+0010b0 */ + 0, /* U+0010b1 */ + 0, /* U+0010b2 */ + 0, /* U+0010b3 */ + 0, /* U+0010b4 */ + 0, /* U+0010b5 */ + 0, /* U+0010b6 */ + 0, /* U+0010b7 */ + 0, /* U+0010b8 */ + 0, /* U+0010b9 */ + 0, /* U+0010ba */ + 0, /* U+0010bb */ + 0, /* U+0010bc */ + 0, /* U+0010bd */ + 0, /* U+0010be */ + 0, /* U+0010bf */ + 0, /* U+0010c0 */ + 0, /* U+0010c1 */ + 0, /* U+0010c2 */ + 0, /* U+0010c3 */ + 0, /* U+0010c4 */ + 0, /* U+0010c5 */ + 0, /* U+0010c7 */ + 0, /* U+0010cd */ + 0, /* U+0010d0 */ + 0, /* U+0010d1 */ + 0, /* U+0010d2 */ + 0, /* U+0010d3 */ + 0, /* U+0010d4 */ + 0, /* U+0010d5 */ + 0, /* U+0010d6 */ + 0, /* U+0010d7 */ + 0, /* U+0010d8 */ + 0, /* U+0010d9 */ + 0, /* U+0010da */ + 0, /* U+0010db */ + 0, /* U+0010dc */ + 0, /* U+0010dd */ + 0, /* U+0010de */ + 0, /* U+0010df */ + 0, /* U+0010e0 */ + 0, /* U+0010e1 */ + 0, /* U+0010e2 */ + 0, /* U+0010e3 */ + 0, /* U+0010e4 */ + 0, /* U+0010e5 */ + 0, /* U+0010e6 */ + 0, /* U+0010e7 */ + 0, /* U+0010e8 */ + 0, /* U+0010e9 */ + 0, /* U+0010ea */ + 0, /* U+0010eb */ + 0, /* U+0010ec */ + 0, /* U+0010ed */ + 0, /* U+0010ee */ + 0, /* U+0010ef */ + 0, /* U+0010f0 */ + 0, /* U+0010f1 */ + 0, /* U+0010f2 */ + 0, /* U+0010f3 */ + 0, /* U+0010f4 */ + 0, /* U+0010f5 */ + 0, /* U+0010f6 */ + 0, /* U+0010f7 */ + 0, /* U+0010f8 */ + 0, /* U+0010f9 */ + 0, /* U+0010fa */ + 0, /* U+0010fd */ + 0, /* U+0010fe */ + 0, /* U+0010ff */ + 0, /* U+0013a0 */ + 0, /* U+0013a1 */ + 0, /* U+0013a2 */ + 0, /* U+0013a3 */ + 0, /* U+0013a4 */ + 0, /* U+0013a5 */ + 0, /* U+0013a6 */ + 0, /* U+0013a7 */ + 0, /* U+0013a8 */ + 0, /* U+0013a9 */ + 0, /* U+0013aa */ + 0, /* U+0013ab */ + 0, /* U+0013ac */ + 0, /* U+0013ad */ + 0, /* U+0013ae */ + 0, /* U+0013af */ + 0, /* U+0013b0 */ + 0, /* U+0013b1 */ + 0, /* U+0013b2 */ + 0, /* U+0013b3 */ + 0, /* U+0013b4 */ + 0, /* U+0013b5 */ + 0, /* U+0013b6 */ + 0, /* U+0013b7 */ + 0, /* U+0013b8 */ + 0, /* U+0013b9 */ + 0, /* U+0013ba */ + 0, /* U+0013bb */ + 0, /* U+0013bc */ + 0, /* U+0013bd */ + 0, /* U+0013be */ + 0, /* U+0013bf */ + 0, /* U+0013c0 */ + 0, /* U+0013c1 */ + 0, /* U+0013c2 */ + 0, /* U+0013c3 */ + 0, /* U+0013c4 */ + 0, /* U+0013c5 */ + 0, /* U+0013c6 */ + 0, /* U+0013c7 */ + 0, /* U+0013c8 */ + 0, /* U+0013c9 */ + 0, /* U+0013ca */ + 0, /* U+0013cb */ + 0, /* U+0013cc */ + 0, /* U+0013cd */ + 0, /* U+0013ce */ + 0, /* U+0013cf */ + 0, /* U+0013d0 */ + 0, /* U+0013d1 */ + 0, /* U+0013d2 */ + 0, /* U+0013d3 */ + 0, /* U+0013d4 */ + 0, /* U+0013d5 */ + 0, /* U+0013d6 */ + 0, /* U+0013d7 */ + 0, /* U+0013d8 */ + 0, /* U+0013d9 */ + 0, /* U+0013da */ + 0, /* U+0013db */ + 0, /* U+0013dc */ + 0, /* U+0013dd */ + 0, /* U+0013de */ + 0, /* U+0013df */ + 0, /* U+0013e0 */ + 0, /* U+0013e1 */ + 0, /* U+0013e2 */ + 0, /* U+0013e3 */ + 0, /* U+0013e4 */ + 0, /* U+0013e5 */ + 0, /* U+0013e6 */ + 0, /* U+0013e7 */ + 0, /* U+0013e8 */ + 0, /* U+0013e9 */ + 0, /* U+0013ea */ + 0, /* U+0013eb */ + 0, /* U+0013ec */ + 0, /* U+0013ed */ + 0, /* U+0013ee */ + 0, /* U+0013ef */ + 0, /* U+0013f0 */ + 0, /* U+0013f1 */ + 0, /* U+0013f2 */ + 0, /* U+0013f3 */ + 0, /* U+0013f4 */ + 0, /* U+0013f5 */ + 0, /* U+001c80 */ + 0, /* U+001c81 */ + 0, /* U+001c82 */ + 0, /* U+001c83 */ + 0, /* U+001c84 */ + 0, /* U+001c85 */ + 0, /* U+001c86 */ + 0, /* U+001c87 */ + 0, /* U+001c88 */ + 0, /* U+001c89 */ + 0, /* U+001c90 */ + 0, /* U+001c91 */ + 0, /* U+001c92 */ + 0, /* U+001c93 */ + 0, /* U+001c94 */ + 0, /* U+001c95 */ + 0, /* U+001c96 */ + 0, /* U+001c97 */ + 0, /* U+001c98 */ + 0, /* U+001c99 */ + 0, /* U+001c9a */ + 0, /* U+001c9b */ + 0, /* U+001c9c */ + 0, /* U+001c9d */ + 0, /* U+001c9e */ + 0, /* U+001c9f */ + 0, /* U+001ca0 */ + 0, /* U+001ca1 */ + 0, /* U+001ca2 */ + 0, /* U+001ca3 */ + 0, /* U+001ca4 */ + 0, /* U+001ca5 */ + 0, /* U+001ca6 */ + 0, /* U+001ca7 */ + 0, /* U+001ca8 */ + 0, /* U+001ca9 */ + 0, /* U+001caa */ + 0, /* U+001cab */ + 0, /* U+001cac */ + 0, /* U+001cad */ + 0, /* U+001cae */ + 0, /* U+001caf */ + 0, /* U+001cb0 */ + 0, /* U+001cb1 */ + 0, /* U+001cb2 */ + 0, /* U+001cb3 */ + 0, /* U+001cb4 */ + 0, /* U+001cb5 */ + 0, /* U+001cb6 */ + 0, /* U+001cb7 */ + 0, /* U+001cb8 */ + 0, /* U+001cb9 */ + 0, /* U+001cba */ + 0, /* U+001cbd */ + 0, /* U+001cbe */ + 0, /* U+001cbf */ + 0, /* U+001d79 */ + 0, /* U+001d7d */ + 0, /* U+001d8e */ + 0, /* U+001e00 */ + 0, /* U+001e02 */ + 0, /* U+001e04 */ + 0, /* U+001e06 */ + 0, /* U+001e08 */ + 0, /* U+001e0a */ + 0, /* U+001e0c */ + 0, /* U+001e0e */ + 0, /* U+001e10 */ + 0, /* U+001e12 */ + 0, /* U+001e14 */ + 0, /* U+001e16 */ + 0, /* U+001e18 */ + 0, /* U+001e1a */ + 0, /* U+001e1c */ + 0, /* U+001e1e */ + 0, /* U+001e20 */ + 0, /* U+001e22 */ + 0, /* U+001e24 */ + 0, /* U+001e26 */ + 0, /* U+001e28 */ + 0, /* U+001e2a */ + 0, /* U+001e2c */ + 0, /* U+001e2e */ + 0, /* U+001e30 */ + 0, /* U+001e32 */ + 0, /* U+001e34 */ + 0, /* U+001e36 */ + 0, /* U+001e38 */ + 0, /* U+001e3a */ + 0, /* U+001e3c */ + 0, /* U+001e3e */ + 0, /* U+001e40 */ + 0, /* U+001e42 */ + 0, /* U+001e44 */ + 0, /* U+001e46 */ + 0, /* U+001e48 */ + 0, /* U+001e4a */ + 0, /* U+001e4c */ + 0, /* U+001e4e */ + 0, /* U+001e50 */ + 0, /* U+001e52 */ + 0, /* U+001e54 */ + 0, /* U+001e56 */ + 0, /* U+001e58 */ + 0, /* U+001e5a */ + 0, /* U+001e5c */ + 0, /* U+001e5e */ + 0, /* U+001e60 */ + 0, /* U+001e62 */ + 0, /* U+001e64 */ + 0, /* U+001e66 */ + 0, /* U+001e68 */ + 0, /* U+001e6a */ + 0, /* U+001e6c */ + 0, /* U+001e6e */ + 0, /* U+001e70 */ + 0, /* U+001e72 */ + 0, /* U+001e74 */ + 0, /* U+001e76 */ + 0, /* U+001e78 */ + 0, /* U+001e7a */ + 0, /* U+001e7c */ + 0, /* U+001e7e */ + 0, /* U+001e80 */ + 0, /* U+001e82 */ + 0, /* U+001e84 */ + 0, /* U+001e86 */ + 0, /* U+001e88 */ + 0, /* U+001e8a */ + 0, /* U+001e8c */ + 0, /* U+001e8e */ + 0, /* U+001e90 */ + 0, /* U+001e92 */ + 0, /* U+001e94 */ + 9, /* U+001e96 */ + 10, /* U+001e97 */ + 11, /* U+001e98 */ + 12, /* U+001e99 */ + 13, /* U+001e9a */ + 0, /* U+001e9b */ + 14, /* U+001e9e */ + 0, /* U+001ea0 */ + 0, /* U+001ea2 */ + 0, /* U+001ea4 */ + 0, /* U+001ea6 */ + 0, /* U+001ea8 */ + 0, /* U+001eaa */ + 0, /* U+001eac */ + 0, /* U+001eae */ + 0, /* U+001eb0 */ + 0, /* U+001eb2 */ + 0, /* U+001eb4 */ + 0, /* U+001eb6 */ + 0, /* U+001eb8 */ + 0, /* U+001eba */ + 0, /* U+001ebc */ + 0, /* U+001ebe */ + 0, /* U+001ec0 */ + 0, /* U+001ec2 */ + 0, /* U+001ec4 */ + 0, /* U+001ec6 */ + 0, /* U+001ec8 */ + 0, /* U+001eca */ + 0, /* U+001ecc */ + 0, /* U+001ece */ + 0, /* U+001ed0 */ + 0, /* U+001ed2 */ + 0, /* U+001ed4 */ + 0, /* U+001ed6 */ + 0, /* U+001ed8 */ + 0, /* U+001eda */ + 0, /* U+001edc */ + 0, /* U+001ede */ + 0, /* U+001ee0 */ + 0, /* U+001ee2 */ + 0, /* U+001ee4 */ + 0, /* U+001ee6 */ + 0, /* U+001ee8 */ + 0, /* U+001eea */ + 0, /* U+001eec */ + 0, /* U+001eee */ + 0, /* U+001ef0 */ + 0, /* U+001ef2 */ + 0, /* U+001ef4 */ + 0, /* U+001ef6 */ + 0, /* U+001ef8 */ + 0, /* U+001efa */ + 0, /* U+001efc */ + 0, /* U+001efe */ + 0, /* U+001f00 */ + 0, /* U+001f01 */ + 0, /* U+001f02 */ + 0, /* U+001f03 */ + 0, /* U+001f04 */ + 0, /* U+001f05 */ + 0, /* U+001f06 */ + 0, /* U+001f07 */ + 0, /* U+001f10 */ + 0, /* U+001f11 */ + 0, /* U+001f12 */ + 0, /* U+001f13 */ + 0, /* U+001f14 */ + 0, /* U+001f15 */ + 0, /* U+001f20 */ + 0, /* U+001f21 */ + 0, /* U+001f22 */ + 0, /* U+001f23 */ + 0, /* U+001f24 */ + 0, /* U+001f25 */ + 0, /* U+001f26 */ + 0, /* U+001f27 */ + 0, /* U+001f30 */ + 0, /* U+001f31 */ + 0, /* U+001f32 */ + 0, /* U+001f33 */ + 0, /* U+001f34 */ + 0, /* U+001f35 */ + 0, /* U+001f36 */ + 0, /* U+001f37 */ + 0, /* U+001f40 */ + 0, /* U+001f41 */ + 0, /* U+001f42 */ + 0, /* U+001f43 */ + 0, /* U+001f44 */ + 0, /* U+001f45 */ + 15, /* U+001f50 */ + 0, /* U+001f51 */ + 16, /* U+001f52 */ + 0, /* U+001f53 */ + 17, /* U+001f54 */ + 0, /* U+001f55 */ + 18, /* U+001f56 */ + 0, /* U+001f57 */ + 0, /* U+001f60 */ + 0, /* U+001f61 */ + 0, /* U+001f62 */ + 0, /* U+001f63 */ + 0, /* U+001f64 */ + 0, /* U+001f65 */ + 0, /* U+001f66 */ + 0, /* U+001f67 */ + 0, /* U+001f70 */ + 0, /* U+001f71 */ + 0, /* U+001f72 */ + 0, /* U+001f73 */ + 0, /* U+001f74 */ + 0, /* U+001f75 */ + 0, /* U+001f76 */ + 0, /* U+001f77 */ + 0, /* U+001f78 */ + 0, /* U+001f79 */ + 0, /* U+001f7a */ + 0, /* U+001f7b */ + 0, /* U+001f7c */ + 0, /* U+001f7d */ + 19, /* U+001f80 */ + 20, /* U+001f81 */ + 21, /* U+001f82 */ + 22, /* U+001f83 */ + 23, /* U+001f84 */ + 24, /* U+001f85 */ + 25, /* U+001f86 */ + 26, /* U+001f87 */ + 27, /* U+001f88 */ + 28, /* U+001f89 */ + 29, /* U+001f8a */ + 30, /* U+001f8b */ + 31, /* U+001f8c */ + 32, /* U+001f8d */ + 33, /* U+001f8e */ + 34, /* U+001f8f */ + 35, /* U+001f90 */ + 36, /* U+001f91 */ + 37, /* U+001f92 */ + 38, /* U+001f93 */ + 39, /* U+001f94 */ + 40, /* U+001f95 */ + 41, /* U+001f96 */ + 42, /* U+001f97 */ + 43, /* U+001f98 */ + 44, /* U+001f99 */ + 45, /* U+001f9a */ + 46, /* U+001f9b */ + 47, /* U+001f9c */ + 48, /* U+001f9d */ + 49, /* U+001f9e */ + 50, /* U+001f9f */ + 51, /* U+001fa0 */ + 52, /* U+001fa1 */ + 53, /* U+001fa2 */ + 54, /* U+001fa3 */ + 55, /* U+001fa4 */ + 56, /* U+001fa5 */ + 57, /* U+001fa6 */ + 58, /* U+001fa7 */ + 59, /* U+001fa8 */ + 60, /* U+001fa9 */ + 61, /* U+001faa */ + 62, /* U+001fab */ + 63, /* U+001fac */ + 64, /* U+001fad */ + 65, /* U+001fae */ + 66, /* U+001faf */ + 0, /* U+001fb0 */ + 0, /* U+001fb1 */ + 67, /* U+001fb2 */ + 68, /* U+001fb3 */ + 69, /* U+001fb4 */ + 70, /* U+001fb6 */ + 71, /* U+001fb7 */ + 72, /* U+001fbc */ + 0, /* U+001fbe */ + 73, /* U+001fc2 */ + 74, /* U+001fc3 */ + 75, /* U+001fc4 */ + 76, /* U+001fc6 */ + 77, /* U+001fc7 */ + 78, /* U+001fcc */ + 0, /* U+001fd0 */ + 0, /* U+001fd1 */ + 79, /* U+001fd2 */ + 80, /* U+001fd3 */ + 81, /* U+001fd6 */ + 82, /* U+001fd7 */ + 0, /* U+001fe0 */ + 0, /* U+001fe1 */ + 83, /* U+001fe2 */ + 84, /* U+001fe3 */ + 85, /* U+001fe4 */ + 0, /* U+001fe5 */ + 86, /* U+001fe6 */ + 87, /* U+001fe7 */ + 88, /* U+001ff2 */ + 89, /* U+001ff3 */ + 90, /* U+001ff4 */ + 91, /* U+001ff6 */ + 92, /* U+001ff7 */ + 93, /* U+001ffc */ + 0, /* U+002126 */ + 0, /* U+00212a */ + 0, /* U+00212b */ + 0, /* U+002132 */ + 0, /* U+002160 */ + 0, /* U+002161 */ + 0, /* U+002162 */ + 0, /* U+002163 */ + 0, /* U+002164 */ + 0, /* U+002165 */ + 0, /* U+002166 */ + 0, /* U+002167 */ + 0, /* U+002168 */ + 0, /* U+002169 */ + 0, /* U+00216a */ + 0, /* U+00216b */ + 0, /* U+00216c */ + 0, /* U+00216d */ + 0, /* U+00216e */ + 0, /* U+00216f */ + 0, /* U+002183 */ + 0, /* U+0024b6 */ + 0, /* U+0024b7 */ + 0, /* U+0024b8 */ + 0, /* U+0024b9 */ + 0, /* U+0024ba */ + 0, /* U+0024bb */ + 0, /* U+0024bc */ + 0, /* U+0024bd */ + 0, /* U+0024be */ + 0, /* U+0024bf */ + 0, /* U+0024c0 */ + 0, /* U+0024c1 */ + 0, /* U+0024c2 */ + 0, /* U+0024c3 */ + 0, /* U+0024c4 */ + 0, /* U+0024c5 */ + 0, /* U+0024c6 */ + 0, /* U+0024c7 */ + 0, /* U+0024c8 */ + 0, /* U+0024c9 */ + 0, /* U+0024ca */ + 0, /* U+0024cb */ + 0, /* U+0024cc */ + 0, /* U+0024cd */ + 0, /* U+0024ce */ + 0, /* U+0024cf */ + 0, /* U+002c00 */ + 0, /* U+002c01 */ + 0, /* U+002c02 */ + 0, /* U+002c03 */ + 0, /* U+002c04 */ + 0, /* U+002c05 */ + 0, /* U+002c06 */ + 0, /* U+002c07 */ + 0, /* U+002c08 */ + 0, /* U+002c09 */ + 0, /* U+002c0a */ + 0, /* U+002c0b */ + 0, /* U+002c0c */ + 0, /* U+002c0d */ + 0, /* U+002c0e */ + 0, /* U+002c0f */ + 0, /* U+002c10 */ + 0, /* U+002c11 */ + 0, /* U+002c12 */ + 0, /* U+002c13 */ + 0, /* U+002c14 */ + 0, /* U+002c15 */ + 0, /* U+002c16 */ + 0, /* U+002c17 */ + 0, /* U+002c18 */ + 0, /* U+002c19 */ + 0, /* U+002c1a */ + 0, /* U+002c1b */ + 0, /* U+002c1c */ + 0, /* U+002c1d */ + 0, /* U+002c1e */ + 0, /* U+002c1f */ + 0, /* U+002c20 */ + 0, /* U+002c21 */ + 0, /* U+002c22 */ + 0, /* U+002c23 */ + 0, /* U+002c24 */ + 0, /* U+002c25 */ + 0, /* U+002c26 */ + 0, /* U+002c27 */ + 0, /* U+002c28 */ + 0, /* U+002c29 */ + 0, /* U+002c2a */ + 0, /* U+002c2b */ + 0, /* U+002c2c */ + 0, /* U+002c2d */ + 0, /* U+002c2e */ + 0, /* U+002c2f */ + 0, /* U+002c60 */ + 0, /* U+002c67 */ + 0, /* U+002c69 */ + 0, /* U+002c6b */ + 0, /* U+002c72 */ + 0, /* U+002c75 */ + 0, /* U+002c80 */ + 0, /* U+002c82 */ + 0, /* U+002c84 */ + 0, /* U+002c86 */ + 0, /* U+002c88 */ + 0, /* U+002c8a */ + 0, /* U+002c8c */ + 0, /* U+002c8e */ + 0, /* U+002c90 */ + 0, /* U+002c92 */ + 0, /* U+002c94 */ + 0, /* U+002c96 */ + 0, /* U+002c98 */ + 0, /* U+002c9a */ + 0, /* U+002c9c */ + 0, /* U+002c9e */ + 0, /* U+002ca0 */ + 0, /* U+002ca2 */ + 0, /* U+002ca4 */ + 0, /* U+002ca6 */ + 0, /* U+002ca8 */ + 0, /* U+002caa */ + 0, /* U+002cac */ + 0, /* U+002cae */ + 0, /* U+002cb0 */ + 0, /* U+002cb2 */ + 0, /* U+002cb4 */ + 0, /* U+002cb6 */ + 0, /* U+002cb8 */ + 0, /* U+002cba */ + 0, /* U+002cbc */ + 0, /* U+002cbe */ + 0, /* U+002cc0 */ + 0, /* U+002cc2 */ + 0, /* U+002cc4 */ + 0, /* U+002cc6 */ + 0, /* U+002cc8 */ + 0, /* U+002cca */ + 0, /* U+002ccc */ + 0, /* U+002cce */ + 0, /* U+002cd0 */ + 0, /* U+002cd2 */ + 0, /* U+002cd4 */ + 0, /* U+002cd6 */ + 0, /* U+002cd8 */ + 0, /* U+002cda */ + 0, /* U+002cdc */ + 0, /* U+002cde */ + 0, /* U+002ce0 */ + 0, /* U+002ce2 */ + 0, /* U+002ceb */ + 0, /* U+002ced */ + 0, /* U+002cf2 */ + 0, /* U+00a640 */ + 0, /* U+00a642 */ + 0, /* U+00a644 */ + 0, /* U+00a646 */ + 0, /* U+00a648 */ + 0, /* U+00a64a */ + 0, /* U+00a64c */ + 0, /* U+00a64e */ + 0, /* U+00a650 */ + 0, /* U+00a652 */ + 0, /* U+00a654 */ + 0, /* U+00a656 */ + 0, /* U+00a658 */ + 0, /* U+00a65a */ + 0, /* U+00a65c */ + 0, /* U+00a65e */ + 0, /* U+00a660 */ + 0, /* U+00a662 */ + 0, /* U+00a664 */ + 0, /* U+00a666 */ + 0, /* U+00a668 */ + 0, /* U+00a66a */ + 0, /* U+00a66c */ + 0, /* U+00a680 */ + 0, /* U+00a682 */ + 0, /* U+00a684 */ + 0, /* U+00a686 */ + 0, /* U+00a688 */ + 0, /* U+00a68a */ + 0, /* U+00a68c */ + 0, /* U+00a68e */ + 0, /* U+00a690 */ + 0, /* U+00a692 */ + 0, /* U+00a694 */ + 0, /* U+00a696 */ + 0, /* U+00a698 */ + 0, /* U+00a69a */ + 0, /* U+00a722 */ + 0, /* U+00a724 */ + 0, /* U+00a726 */ + 0, /* U+00a728 */ + 0, /* U+00a72a */ + 0, /* U+00a72c */ + 0, /* U+00a72e */ + 0, /* U+00a732 */ + 0, /* U+00a734 */ + 0, /* U+00a736 */ + 0, /* U+00a738 */ + 0, /* U+00a73a */ + 0, /* U+00a73c */ + 0, /* U+00a73e */ + 0, /* U+00a740 */ + 0, /* U+00a742 */ + 0, /* U+00a744 */ + 0, /* U+00a746 */ + 0, /* U+00a748 */ + 0, /* U+00a74a */ + 0, /* U+00a74c */ + 0, /* U+00a74e */ + 0, /* U+00a750 */ + 0, /* U+00a752 */ + 0, /* U+00a754 */ + 0, /* U+00a756 */ + 0, /* U+00a758 */ + 0, /* U+00a75a */ + 0, /* U+00a75c */ + 0, /* U+00a75e */ + 0, /* U+00a760 */ + 0, /* U+00a762 */ + 0, /* U+00a764 */ + 0, /* U+00a766 */ + 0, /* U+00a768 */ + 0, /* U+00a76a */ + 0, /* U+00a76c */ + 0, /* U+00a76e */ + 0, /* U+00a779 */ + 0, /* U+00a77b */ + 0, /* U+00a77e */ + 0, /* U+00a780 */ + 0, /* U+00a782 */ + 0, /* U+00a784 */ + 0, /* U+00a786 */ + 0, /* U+00a78b */ + 0, /* U+00a790 */ + 0, /* U+00a792 */ + 0, /* U+00a794 */ + 0, /* U+00a796 */ + 0, /* U+00a798 */ + 0, /* U+00a79a */ + 0, /* U+00a79c */ + 0, /* U+00a79e */ + 0, /* U+00a7a0 */ + 0, /* U+00a7a2 */ + 0, /* U+00a7a4 */ + 0, /* U+00a7a6 */ + 0, /* U+00a7a8 */ + 0, /* U+00a7b3 */ + 0, /* U+00a7b4 */ + 0, /* U+00a7b6 */ + 0, /* U+00a7b8 */ + 0, /* U+00a7ba */ + 0, /* U+00a7bc */ + 0, /* U+00a7be */ + 0, /* U+00a7c0 */ + 0, /* U+00a7c2 */ + 0, /* U+00a7c7 */ + 0, /* U+00a7c9 */ + 0, /* U+00a7cc */ + 0, /* U+00a7d0 */ + 0, /* U+00a7d6 */ + 0, /* U+00a7d8 */ + 0, /* U+00a7da */ + 0, /* U+00a7f5 */ + 94, /* U+00fb00 */ + 95, /* U+00fb01 */ + 96, /* U+00fb02 */ + 97, /* U+00fb03 */ + 98, /* U+00fb04 */ + 99, /* U+00fb05 */ + 100, /* U+00fb06 */ + 101, /* U+00fb13 */ + 102, /* U+00fb14 */ + 103, /* U+00fb15 */ + 104, /* U+00fb16 */ + 105, /* U+00fb17 */ + 0, /* U+00ff21 */ + 0, /* U+00ff22 */ + 0, /* U+00ff23 */ + 0, /* U+00ff24 */ + 0, /* U+00ff25 */ + 0, /* U+00ff26 */ + 0, /* U+00ff27 */ + 0, /* U+00ff28 */ + 0, /* U+00ff29 */ + 0, /* U+00ff2a */ + 0, /* U+00ff2b */ + 0, /* U+00ff2c */ + 0, /* U+00ff2d */ + 0, /* U+00ff2e */ + 0, /* U+00ff2f */ + 0, /* U+00ff30 */ + 0, /* U+00ff31 */ + 0, /* U+00ff32 */ + 0, /* U+00ff33 */ + 0, /* U+00ff34 */ + 0, /* U+00ff35 */ + 0, /* U+00ff36 */ + 0, /* U+00ff37 */ + 0, /* U+00ff38 */ + 0, /* U+00ff39 */ + 0, /* U+00ff3a */ + 0, /* U+010400 */ + 0, /* U+010401 */ + 0, /* U+010402 */ + 0, /* U+010403 */ + 0, /* U+010404 */ + 0, /* U+010405 */ + 0, /* U+010406 */ + 0, /* U+010407 */ + 0, /* U+010408 */ + 0, /* U+010409 */ + 0, /* U+01040a */ + 0, /* U+01040b */ + 0, /* U+01040c */ + 0, /* U+01040d */ + 0, /* U+01040e */ + 0, /* U+01040f */ + 0, /* U+010410 */ + 0, /* U+010411 */ + 0, /* U+010412 */ + 0, /* U+010413 */ + 0, /* U+010414 */ + 0, /* U+010415 */ + 0, /* U+010416 */ + 0, /* U+010417 */ + 0, /* U+010418 */ + 0, /* U+010419 */ + 0, /* U+01041a */ + 0, /* U+01041b */ + 0, /* U+01041c */ + 0, /* U+01041d */ + 0, /* U+01041e */ + 0, /* U+01041f */ + 0, /* U+010420 */ + 0, /* U+010421 */ + 0, /* U+010422 */ + 0, /* U+010423 */ + 0, /* U+010424 */ + 0, /* U+010425 */ + 0, /* U+010426 */ + 0, /* U+010427 */ + 0, /* U+0104b0 */ + 0, /* U+0104b1 */ + 0, /* U+0104b2 */ + 0, /* U+0104b3 */ + 0, /* U+0104b4 */ + 0, /* U+0104b5 */ + 0, /* U+0104b6 */ + 0, /* U+0104b7 */ + 0, /* U+0104b8 */ + 0, /* U+0104b9 */ + 0, /* U+0104ba */ + 0, /* U+0104bb */ + 0, /* U+0104bc */ + 0, /* U+0104bd */ + 0, /* U+0104be */ + 0, /* U+0104bf */ + 0, /* U+0104c0 */ + 0, /* U+0104c1 */ + 0, /* U+0104c2 */ + 0, /* U+0104c3 */ + 0, /* U+0104c4 */ + 0, /* U+0104c5 */ + 0, /* U+0104c6 */ + 0, /* U+0104c7 */ + 0, /* U+0104c8 */ + 0, /* U+0104c9 */ + 0, /* U+0104ca */ + 0, /* U+0104cb */ + 0, /* U+0104cc */ + 0, /* U+0104cd */ + 0, /* U+0104ce */ + 0, /* U+0104cf */ + 0, /* U+0104d0 */ + 0, /* U+0104d1 */ + 0, /* U+0104d2 */ + 0, /* U+0104d3 */ + 0, /* U+010570 */ + 0, /* U+010571 */ + 0, /* U+010572 */ + 0, /* U+010573 */ + 0, /* U+010574 */ + 0, /* U+010575 */ + 0, /* U+010576 */ + 0, /* U+010577 */ + 0, /* U+010578 */ + 0, /* U+010579 */ + 0, /* U+01057a */ + 0, /* U+01057c */ + 0, /* U+01057d */ + 0, /* U+01057e */ + 0, /* U+01057f */ + 0, /* U+010580 */ + 0, /* U+010581 */ + 0, /* U+010582 */ + 0, /* U+010583 */ + 0, /* U+010584 */ + 0, /* U+010585 */ + 0, /* U+010586 */ + 0, /* U+010587 */ + 0, /* U+010588 */ + 0, /* U+010589 */ + 0, /* U+01058a */ + 0, /* U+01058c */ + 0, /* U+01058d */ + 0, /* U+01058e */ + 0, /* U+01058f */ + 0, /* U+010590 */ + 0, /* U+010591 */ + 0, /* U+010592 */ + 0, /* U+010594 */ + 0, /* U+010595 */ + 0, /* U+010c80 */ + 0, /* U+010c81 */ + 0, /* U+010c82 */ + 0, /* U+010c83 */ + 0, /* U+010c84 */ + 0, /* U+010c85 */ + 0, /* U+010c86 */ + 0, /* U+010c87 */ + 0, /* U+010c88 */ + 0, /* U+010c89 */ + 0, /* U+010c8a */ + 0, /* U+010c8b */ + 0, /* U+010c8c */ + 0, /* U+010c8d */ + 0, /* U+010c8e */ + 0, /* U+010c8f */ + 0, /* U+010c90 */ + 0, /* U+010c91 */ + 0, /* U+010c92 */ + 0, /* U+010c93 */ + 0, /* U+010c94 */ + 0, /* U+010c95 */ + 0, /* U+010c96 */ + 0, /* U+010c97 */ + 0, /* U+010c98 */ + 0, /* U+010c99 */ + 0, /* U+010c9a */ + 0, /* U+010c9b */ + 0, /* U+010c9c */ + 0, /* U+010c9d */ + 0, /* U+010c9e */ + 0, /* U+010c9f */ + 0, /* U+010ca0 */ + 0, /* U+010ca1 */ + 0, /* U+010ca2 */ + 0, /* U+010ca3 */ + 0, /* U+010ca4 */ + 0, /* U+010ca5 */ + 0, /* U+010ca6 */ + 0, /* U+010ca7 */ + 0, /* U+010ca8 */ + 0, /* U+010ca9 */ + 0, /* U+010caa */ + 0, /* U+010cab */ + 0, /* U+010cac */ + 0, /* U+010cad */ + 0, /* U+010cae */ + 0, /* U+010caf */ + 0, /* U+010cb0 */ + 0, /* U+010cb1 */ + 0, /* U+010cb2 */ + 0, /* U+010d50 */ + 0, /* U+010d51 */ + 0, /* U+010d52 */ + 0, /* U+010d53 */ + 0, /* U+010d54 */ + 0, /* U+010d55 */ + 0, /* U+010d56 */ + 0, /* U+010d57 */ + 0, /* U+010d58 */ + 0, /* U+010d59 */ + 0, /* U+010d5a */ + 0, /* U+010d5b */ + 0, /* U+010d5c */ + 0, /* U+010d5d */ + 0, /* U+010d5e */ + 0, /* U+010d5f */ + 0, /* U+010d60 */ + 0, /* U+010d61 */ + 0, /* U+010d62 */ + 0, /* U+010d63 */ + 0, /* U+010d64 */ + 0, /* U+010d65 */ + 0, /* U+0118a0 */ + 0, /* U+0118a1 */ + 0, /* U+0118a2 */ + 0, /* U+0118a3 */ + 0, /* U+0118a4 */ + 0, /* U+0118a5 */ + 0, /* U+0118a6 */ + 0, /* U+0118a7 */ + 0, /* U+0118a8 */ + 0, /* U+0118a9 */ + 0, /* U+0118aa */ + 0, /* U+0118ab */ + 0, /* U+0118ac */ + 0, /* U+0118ad */ + 0, /* U+0118ae */ + 0, /* U+0118af */ + 0, /* U+0118b0 */ + 0, /* U+0118b1 */ + 0, /* U+0118b2 */ + 0, /* U+0118b3 */ + 0, /* U+0118b4 */ + 0, /* U+0118b5 */ + 0, /* U+0118b6 */ + 0, /* U+0118b7 */ + 0, /* U+0118b8 */ + 0, /* U+0118b9 */ + 0, /* U+0118ba */ + 0, /* U+0118bb */ + 0, /* U+0118bc */ + 0, /* U+0118bd */ + 0, /* U+0118be */ + 0, /* U+0118bf */ + 0, /* U+016e40 */ + 0, /* U+016e41 */ + 0, /* U+016e42 */ + 0, /* U+016e43 */ + 0, /* U+016e44 */ + 0, /* U+016e45 */ + 0, /* U+016e46 */ + 0, /* U+016e47 */ + 0, /* U+016e48 */ + 0, /* U+016e49 */ + 0, /* U+016e4a */ + 0, /* U+016e4b */ + 0, /* U+016e4c */ + 0, /* U+016e4d */ + 0, /* U+016e4e */ + 0, /* U+016e4f */ + 0, /* U+016e50 */ + 0, /* U+016e51 */ + 0, /* U+016e52 */ + 0, /* U+016e53 */ + 0, /* U+016e54 */ + 0, /* U+016e55 */ + 0, /* U+016e56 */ + 0, /* U+016e57 */ + 0, /* U+016e58 */ + 0, /* U+016e59 */ + 0, /* U+016e5a */ + 0, /* U+016e5b */ + 0, /* U+016e5c */ + 0, /* U+016e5d */ + 0, /* U+016e5e */ + 0, /* U+016e5f */ + 0, /* U+01e900 */ + 0, /* U+01e901 */ + 0, /* U+01e902 */ + 0, /* U+01e903 */ + 0, /* U+01e904 */ + 0, /* U+01e905 */ + 0, /* U+01e906 */ + 0, /* U+01e907 */ + 0, /* U+01e908 */ + 0, /* U+01e909 */ + 0, /* U+01e90a */ + 0, /* U+01e90b */ + 0, /* U+01e90c */ + 0, /* U+01e90d */ + 0, /* U+01e90e */ + 0, /* U+01e90f */ + 0, /* U+01e910 */ + 0, /* U+01e911 */ + 0, /* U+01e912 */ + 0, /* U+01e913 */ + 0, /* U+01e914 */ + 0, /* U+01e915 */ + 0, /* U+01e916 */ + 0, /* U+01e917 */ + 0, /* U+01e918 */ + 0, /* U+01e919 */ + 0, /* U+01e91a */ + 0, /* U+01e91b */ + 0, /* U+01e91c */ + 0, /* U+01e91d */ + 0, /* U+01e91e */ + 0, /* U+01e91f */ + 0, /* U+01e920 */ + 0, /* U+01e921 */ + +}; + +/* + * Used by case_index() to map a codepoint to an index that can be used in any + * of the following arrays: case_map_lower, case_map_title, case_map_upper, + * case_map_fold. + */ +static const uint16 case_map[4778] = +{ + 1, /* U+000000 */ + 2, /* U+000001 */ + 3, /* U+000002 */ + 4, /* U+000003 */ + 5, /* U+000004 */ + 6, /* U+000005 */ + 7, /* U+000006 */ + 8, /* U+000007 */ + 9, /* U+000008 */ + 10, /* U+000009 */ + 11, /* U+00000A */ + 12, /* U+00000B */ + 13, /* U+00000C */ + 14, /* U+00000D */ + 15, /* U+00000E */ + 16, /* U+00000F */ + 17, /* U+000010 */ + 18, /* U+000011 */ + 19, /* U+000012 */ + 20, /* U+000013 */ + 21, /* U+000014 */ + 22, /* U+000015 */ + 23, /* U+000016 */ + 24, /* U+000017 */ + 25, /* U+000018 */ + 26, /* U+000019 */ + 27, /* U+00001A */ + 28, /* U+00001B */ + 29, /* U+00001C */ + 30, /* U+00001D */ + 31, /* U+00001E */ + 32, /* U+00001F */ + 33, /* U+000020 */ + 34, /* U+000021 */ + 35, /* U+000022 */ + 36, /* U+000023 */ + 37, /* U+000024 */ + 38, /* U+000025 */ + 39, /* U+000026 */ + 40, /* U+000027 */ + 41, /* U+000028 */ + 42, /* U+000029 */ + 43, /* U+00002A */ + 44, /* U+00002B */ + 45, /* U+00002C */ + 46, /* U+00002D */ + 47, /* U+00002E */ + 48, /* U+00002F */ + 49, /* U+000030 */ + 50, /* U+000031 */ + 51, /* U+000032 */ + 52, /* U+000033 */ + 53, /* U+000034 */ + 54, /* U+000035 */ + 55, /* U+000036 */ + 56, /* U+000037 */ + 57, /* U+000038 */ + 58, /* U+000039 */ + 59, /* U+00003A */ + 60, /* U+00003B */ + 61, /* U+00003C */ + 62, /* U+00003D */ + 63, /* U+00003E */ + 64, /* U+00003F */ + 65, /* U+000040 */ + 66, /* U+000041 */ + 67, /* U+000042 */ + 68, /* U+000043 */ + 69, /* U+000044 */ + 70, /* U+000045 */ + 71, /* U+000046 */ + 72, /* U+000047 */ + 73, /* U+000048 */ + 74, /* U+000049 */ + 75, /* U+00004A */ + 76, /* U+00004B */ + 77, /* U+00004C */ + 78, /* U+00004D */ + 79, /* U+00004E */ + 80, /* U+00004F */ + 81, /* U+000050 */ + 82, /* U+000051 */ + 83, /* U+000052 */ + 84, /* U+000053 */ + 85, /* U+000054 */ + 86, /* U+000055 */ + 87, /* U+000056 */ + 88, /* U+000057 */ + 89, /* U+000058 */ + 90, /* U+000059 */ + 91, /* U+00005A */ + 92, /* U+00005B */ + 93, /* U+00005C */ + 94, /* U+00005D */ + 95, /* U+00005E */ + 96, /* U+00005F */ + 97, /* U+000060 */ + 98, /* U+000061 */ + 99, /* U+000062 */ + 100, /* U+000063 */ + 101, /* U+000064 */ + 102, /* U+000065 */ + 103, /* U+000066 */ + 104, /* U+000067 */ + 105, /* U+000068 */ + 106, /* U+000069 */ + 107, /* U+00006A */ + 108, /* U+00006B */ + 109, /* U+00006C */ + 110, /* U+00006D */ + 111, /* U+00006E */ + 112, /* U+00006F */ + 113, /* U+000070 */ + 114, /* U+000071 */ + 115, /* U+000072 */ + 116, /* U+000073 */ + 117, /* U+000074 */ + 118, /* U+000075 */ + 119, /* U+000076 */ + 120, /* U+000077 */ + 121, /* U+000078 */ + 122, /* U+000079 */ + 123, /* U+00007A */ + 124, /* U+00007B */ + 125, /* U+00007C */ + 126, /* U+00007D */ + 127, /* U+00007E */ + 128, /* U+00007F */ + 0, /* U+000080 */ + 0, /* U+000081 */ + 0, /* U+000082 */ + 0, /* U+000083 */ + 0, /* U+000084 */ + 0, /* U+000085 */ + 0, /* U+000086 */ + 0, /* U+000087 */ + 0, /* U+000088 */ + 0, /* U+000089 */ + 0, /* U+00008A */ + 0, /* U+00008B */ + 0, /* U+00008C */ + 0, /* U+00008D */ + 0, /* U+00008E */ + 0, /* U+00008F */ + 0, /* U+000090 */ + 0, /* U+000091 */ + 0, /* U+000092 */ + 0, /* U+000093 */ + 0, /* U+000094 */ + 0, /* U+000095 */ + 0, /* U+000096 */ + 0, /* U+000097 */ + 0, /* U+000098 */ + 0, /* U+000099 */ + 0, /* U+00009A */ + 0, /* U+00009B */ + 0, /* U+00009C */ + 0, /* U+00009D */ + 0, /* U+00009E */ + 0, /* U+00009F */ + 0, /* U+0000A0 */ + 0, /* U+0000A1 */ + 0, /* U+0000A2 */ + 0, /* U+0000A3 */ + 0, /* U+0000A4 */ + 0, /* U+0000A5 */ + 0, /* U+0000A6 */ + 0, /* U+0000A7 */ + 0, /* U+0000A8 */ + 0, /* U+0000A9 */ + 0, /* U+0000AA */ + 0, /* U+0000AB */ + 0, /* U+0000AC */ + 0, /* U+0000AD */ + 0, /* U+0000AE */ + 0, /* U+0000AF */ + 0, /* U+0000B0 */ + 0, /* U+0000B1 */ + 0, /* U+0000B2 */ + 0, /* U+0000B3 */ + 0, /* U+0000B4 */ + 129, /* U+0000B5 */ + 0, /* U+0000B6 */ + 0, /* U+0000B7 */ + 0, /* U+0000B8 */ + 0, /* U+0000B9 */ + 0, /* U+0000BA */ + 0, /* U+0000BB */ + 0, /* U+0000BC */ + 0, /* U+0000BD */ + 0, /* U+0000BE */ + 0, /* U+0000BF */ + 130, /* U+0000C0 */ + 131, /* U+0000C1 */ + 132, /* U+0000C2 */ + 133, /* U+0000C3 */ + 134, /* U+0000C4 */ + 135, /* U+0000C5 */ + 136, /* U+0000C6 */ + 137, /* U+0000C7 */ + 138, /* U+0000C8 */ + 139, /* U+0000C9 */ + 140, /* U+0000CA */ + 141, /* U+0000CB */ + 142, /* U+0000CC */ + 143, /* U+0000CD */ + 144, /* U+0000CE */ + 145, /* U+0000CF */ + 146, /* U+0000D0 */ + 147, /* U+0000D1 */ + 148, /* U+0000D2 */ + 149, /* U+0000D3 */ + 150, /* U+0000D4 */ + 151, /* U+0000D5 */ + 152, /* U+0000D6 */ + 0, /* U+0000D7 */ + 153, /* U+0000D8 */ + 154, /* U+0000D9 */ + 155, /* U+0000DA */ + 156, /* U+0000DB */ + 157, /* U+0000DC */ + 158, /* U+0000DD */ + 159, /* U+0000DE */ + 160, /* U+0000DF */ + 130, /* U+0000E0 */ + 131, /* U+0000E1 */ + 132, /* U+0000E2 */ + 133, /* U+0000E3 */ + 134, /* U+0000E4 */ + 135, /* U+0000E5 */ + 136, /* U+0000E6 */ + 137, /* U+0000E7 */ + 138, /* U+0000E8 */ + 139, /* U+0000E9 */ + 140, /* U+0000EA */ + 141, /* U+0000EB */ + 142, /* U+0000EC */ + 143, /* U+0000ED */ + 144, /* U+0000EE */ + 145, /* U+0000EF */ + 146, /* U+0000F0 */ + 147, /* U+0000F1 */ + 148, /* U+0000F2 */ + 149, /* U+0000F3 */ + 150, /* U+0000F4 */ + 151, /* U+0000F5 */ + 152, /* U+0000F6 */ + 0, /* U+0000F7 */ + 153, /* U+0000F8 */ + 154, /* U+0000F9 */ + 155, /* U+0000FA */ + 156, /* U+0000FB */ + 157, /* U+0000FC */ + 158, /* U+0000FD */ + 159, /* U+0000FE */ + 161, /* U+0000FF */ + 162, /* U+000100 */ + 162, /* U+000101 */ + 163, /* U+000102 */ + 163, /* U+000103 */ + 164, /* U+000104 */ + 164, /* U+000105 */ + 165, /* U+000106 */ + 165, /* U+000107 */ + 166, /* U+000108 */ + 166, /* U+000109 */ + 167, /* U+00010A */ + 167, /* U+00010B */ + 168, /* U+00010C */ + 168, /* U+00010D */ + 169, /* U+00010E */ + 169, /* U+00010F */ + 170, /* U+000110 */ + 170, /* U+000111 */ + 171, /* U+000112 */ + 171, /* U+000113 */ + 172, /* U+000114 */ + 172, /* U+000115 */ + 173, /* U+000116 */ + 173, /* U+000117 */ + 174, /* U+000118 */ + 174, /* U+000119 */ + 175, /* U+00011A */ + 175, /* U+00011B */ + 176, /* U+00011C */ + 176, /* U+00011D */ + 177, /* U+00011E */ + 177, /* U+00011F */ + 178, /* U+000120 */ + 178, /* U+000121 */ + 179, /* U+000122 */ + 179, /* U+000123 */ + 180, /* U+000124 */ + 180, /* U+000125 */ + 181, /* U+000126 */ + 181, /* U+000127 */ + 182, /* U+000128 */ + 182, /* U+000129 */ + 183, /* U+00012A */ + 183, /* U+00012B */ + 184, /* U+00012C */ + 184, /* U+00012D */ + 185, /* U+00012E */ + 185, /* U+00012F */ + 186, /* U+000130 */ + 187, /* U+000131 */ + 188, /* U+000132 */ + 188, /* U+000133 */ + 189, /* U+000134 */ + 189, /* U+000135 */ + 190, /* U+000136 */ + 190, /* U+000137 */ + 0, /* U+000138 */ + 191, /* U+000139 */ + 191, /* U+00013A */ + 192, /* U+00013B */ + 192, /* U+00013C */ + 193, /* U+00013D */ + 193, /* U+00013E */ + 194, /* U+00013F */ + 194, /* U+000140 */ + 195, /* U+000141 */ + 195, /* U+000142 */ + 196, /* U+000143 */ + 196, /* U+000144 */ + 197, /* U+000145 */ + 197, /* U+000146 */ + 198, /* U+000147 */ + 198, /* U+000148 */ + 199, /* U+000149 */ + 200, /* U+00014A */ + 200, /* U+00014B */ + 201, /* U+00014C */ + 201, /* U+00014D */ + 202, /* U+00014E */ + 202, /* U+00014F */ + 203, /* U+000150 */ + 203, /* U+000151 */ + 204, /* U+000152 */ + 204, /* U+000153 */ + 205, /* U+000154 */ + 205, /* U+000155 */ + 206, /* U+000156 */ + 206, /* U+000157 */ + 207, /* U+000158 */ + 207, /* U+000159 */ + 208, /* U+00015A */ + 208, /* U+00015B */ + 209, /* U+00015C */ + 209, /* U+00015D */ + 210, /* U+00015E */ + 210, /* U+00015F */ + 211, /* U+000160 */ + 211, /* U+000161 */ + 212, /* U+000162 */ + 212, /* U+000163 */ + 213, /* U+000164 */ + 213, /* U+000165 */ + 214, /* U+000166 */ + 214, /* U+000167 */ + 215, /* U+000168 */ + 215, /* U+000169 */ + 216, /* U+00016A */ + 216, /* U+00016B */ + 217, /* U+00016C */ + 217, /* U+00016D */ + 218, /* U+00016E */ + 218, /* U+00016F */ + 219, /* U+000170 */ + 219, /* U+000171 */ + 220, /* U+000172 */ + 220, /* U+000173 */ + 221, /* U+000174 */ + 221, /* U+000175 */ + 222, /* U+000176 */ + 222, /* U+000177 */ + 161, /* U+000178 */ + 223, /* U+000179 */ + 223, /* U+00017A */ + 224, /* U+00017B */ + 224, /* U+00017C */ + 225, /* U+00017D */ + 225, /* U+00017E */ + 226, /* U+00017F */ + 227, /* U+000180 */ + 228, /* U+000181 */ + 229, /* U+000182 */ + 229, /* U+000183 */ + 230, /* U+000184 */ + 230, /* U+000185 */ + 231, /* U+000186 */ + 232, /* U+000187 */ + 232, /* U+000188 */ + 233, /* U+000189 */ + 234, /* U+00018A */ + 235, /* U+00018B */ + 235, /* U+00018C */ + 0, /* U+00018D */ + 236, /* U+00018E */ + 237, /* U+00018F */ + 238, /* U+000190 */ + 239, /* U+000191 */ + 239, /* U+000192 */ + 240, /* U+000193 */ + 241, /* U+000194 */ + 242, /* U+000195 */ + 243, /* U+000196 */ + 244, /* U+000197 */ + 245, /* U+000198 */ + 245, /* U+000199 */ + 246, /* U+00019A */ + 247, /* U+00019B */ + 248, /* U+00019C */ + 249, /* U+00019D */ + 250, /* U+00019E */ + 251, /* U+00019F */ + 252, /* U+0001A0 */ + 252, /* U+0001A1 */ + 253, /* U+0001A2 */ + 253, /* U+0001A3 */ + 254, /* U+0001A4 */ + 254, /* U+0001A5 */ + 255, /* U+0001A6 */ + 256, /* U+0001A7 */ + 256, /* U+0001A8 */ + 257, /* U+0001A9 */ + 0, /* U+0001AA */ + 0, /* U+0001AB */ + 258, /* U+0001AC */ + 258, /* U+0001AD */ + 259, /* U+0001AE */ + 260, /* U+0001AF */ + 260, /* U+0001B0 */ + 261, /* U+0001B1 */ + 262, /* U+0001B2 */ + 263, /* U+0001B3 */ + 263, /* U+0001B4 */ + 264, /* U+0001B5 */ + 264, /* U+0001B6 */ + 265, /* U+0001B7 */ + 266, /* U+0001B8 */ + 266, /* U+0001B9 */ + 0, /* U+0001BA */ + 0, /* U+0001BB */ + 267, /* U+0001BC */ + 267, /* U+0001BD */ + 0, /* U+0001BE */ + 268, /* U+0001BF */ + 0, /* U+0001C0 */ + 0, /* U+0001C1 */ + 0, /* U+0001C2 */ + 0, /* U+0001C3 */ + 269, /* U+0001C4 */ + 269, /* U+0001C5 */ + 269, /* U+0001C6 */ + 270, /* U+0001C7 */ + 270, /* U+0001C8 */ + 270, /* U+0001C9 */ + 271, /* U+0001CA */ + 271, /* U+0001CB */ + 271, /* U+0001CC */ + 272, /* U+0001CD */ + 272, /* U+0001CE */ + 273, /* U+0001CF */ + 273, /* U+0001D0 */ + 274, /* U+0001D1 */ + 274, /* U+0001D2 */ + 275, /* U+0001D3 */ + 275, /* U+0001D4 */ + 276, /* U+0001D5 */ + 276, /* U+0001D6 */ + 277, /* U+0001D7 */ + 277, /* U+0001D8 */ + 278, /* U+0001D9 */ + 278, /* U+0001DA */ + 279, /* U+0001DB */ + 279, /* U+0001DC */ + 236, /* U+0001DD */ + 280, /* U+0001DE */ + 280, /* U+0001DF */ + 281, /* U+0001E0 */ + 281, /* U+0001E1 */ + 282, /* U+0001E2 */ + 282, /* U+0001E3 */ + 283, /* U+0001E4 */ + 283, /* U+0001E5 */ + 284, /* U+0001E6 */ + 284, /* U+0001E7 */ + 285, /* U+0001E8 */ + 285, /* U+0001E9 */ + 286, /* U+0001EA */ + 286, /* U+0001EB */ + 287, /* U+0001EC */ + 287, /* U+0001ED */ + 288, /* U+0001EE */ + 288, /* U+0001EF */ + 289, /* U+0001F0 */ + 290, /* U+0001F1 */ + 290, /* U+0001F2 */ + 290, /* U+0001F3 */ + 291, /* U+0001F4 */ + 291, /* U+0001F5 */ + 242, /* U+0001F6 */ + 268, /* U+0001F7 */ + 292, /* U+0001F8 */ + 292, /* U+0001F9 */ + 293, /* U+0001FA */ + 293, /* U+0001FB */ + 294, /* U+0001FC */ + 294, /* U+0001FD */ + 295, /* U+0001FE */ + 295, /* U+0001FF */ + 296, /* U+000200 */ + 296, /* U+000201 */ + 297, /* U+000202 */ + 297, /* U+000203 */ + 298, /* U+000204 */ + 298, /* U+000205 */ + 299, /* U+000206 */ + 299, /* U+000207 */ + 300, /* U+000208 */ + 300, /* U+000209 */ + 301, /* U+00020A */ + 301, /* U+00020B */ + 302, /* U+00020C */ + 302, /* U+00020D */ + 303, /* U+00020E */ + 303, /* U+00020F */ + 304, /* U+000210 */ + 304, /* U+000211 */ + 305, /* U+000212 */ + 305, /* U+000213 */ + 306, /* U+000214 */ + 306, /* U+000215 */ + 307, /* U+000216 */ + 307, /* U+000217 */ + 308, /* U+000218 */ + 308, /* U+000219 */ + 309, /* U+00021A */ + 309, /* U+00021B */ + 310, /* U+00021C */ + 310, /* U+00021D */ + 311, /* U+00021E */ + 311, /* U+00021F */ + 250, /* U+000220 */ + 0, /* U+000221 */ + 312, /* U+000222 */ + 312, /* U+000223 */ + 313, /* U+000224 */ + 313, /* U+000225 */ + 314, /* U+000226 */ + 314, /* U+000227 */ + 315, /* U+000228 */ + 315, /* U+000229 */ + 316, /* U+00022A */ + 316, /* U+00022B */ + 317, /* U+00022C */ + 317, /* U+00022D */ + 318, /* U+00022E */ + 318, /* U+00022F */ + 319, /* U+000230 */ + 319, /* U+000231 */ + 320, /* U+000232 */ + 320, /* U+000233 */ + 0, /* U+000234 */ + 0, /* U+000235 */ + 0, /* U+000236 */ + 0, /* U+000237 */ + 0, /* U+000238 */ + 0, /* U+000239 */ + 321, /* U+00023A */ + 322, /* U+00023B */ + 322, /* U+00023C */ + 246, /* U+00023D */ + 323, /* U+00023E */ + 324, /* U+00023F */ + 325, /* U+000240 */ + 326, /* U+000241 */ + 326, /* U+000242 */ + 227, /* U+000243 */ + 327, /* U+000244 */ + 328, /* U+000245 */ + 329, /* U+000246 */ + 329, /* U+000247 */ + 330, /* U+000248 */ + 330, /* U+000249 */ + 331, /* U+00024A */ + 331, /* U+00024B */ + 332, /* U+00024C */ + 332, /* U+00024D */ + 333, /* U+00024E */ + 333, /* U+00024F */ + 334, /* U+000250 */ + 335, /* U+000251 */ + 336, /* U+000252 */ + 228, /* U+000253 */ + 231, /* U+000254 */ + 0, /* U+000255 */ + 233, /* U+000256 */ + 234, /* U+000257 */ + 0, /* U+000258 */ + 237, /* U+000259 */ + 0, /* U+00025A */ + 238, /* U+00025B */ + 337, /* U+00025C */ + 0, /* U+00025D */ + 0, /* U+00025E */ + 0, /* U+00025F */ + 240, /* U+000260 */ + 338, /* U+000261 */ + 0, /* U+000262 */ + 241, /* U+000263 */ + 339, /* U+000264 */ + 340, /* U+000265 */ + 341, /* U+000266 */ + 0, /* U+000267 */ + 244, /* U+000268 */ + 243, /* U+000269 */ + 342, /* U+00026A */ + 343, /* U+00026B */ + 344, /* U+00026C */ + 0, /* U+00026D */ + 0, /* U+00026E */ + 248, /* U+00026F */ + 0, /* U+000270 */ + 345, /* U+000271 */ + 249, /* U+000272 */ + 0, /* U+000273 */ + 0, /* U+000274 */ + 251, /* U+000275 */ + 0, /* U+000276 */ + 0, /* U+000277 */ + 0, /* U+000278 */ + 0, /* U+000279 */ + 0, /* U+00027A */ + 0, /* U+00027B */ + 0, /* U+00027C */ + 346, /* U+00027D */ + 0, /* U+00027E */ + 0, /* U+00027F */ + 255, /* U+000280 */ + 0, /* U+000281 */ + 347, /* U+000282 */ + 257, /* U+000283 */ + 0, /* U+000284 */ + 0, /* U+000285 */ + 0, /* U+000286 */ + 348, /* U+000287 */ + 259, /* U+000288 */ + 327, /* U+000289 */ + 261, /* U+00028A */ + 262, /* U+00028B */ + 328, /* U+00028C */ + 0, /* U+00028D */ + 0, /* U+00028E */ + 0, /* U+00028F */ + 0, /* U+000290 */ + 0, /* U+000291 */ + 265, /* U+000292 */ + 0, /* U+000293 */ + 0, /* U+000294 */ + 0, /* U+000295 */ + 0, /* U+000296 */ + 0, /* U+000297 */ + 0, /* U+000298 */ + 0, /* U+000299 */ + 0, /* U+00029A */ + 0, /* U+00029B */ + 0, /* U+00029C */ + 349, /* U+00029D */ + 350, /* U+00029E */ + 0, /* U+00029F */ + 0, /* U+0002A0 */ + 0, /* U+0002A1 */ + 0, /* U+0002A2 */ + 0, /* U+0002A3 */ + 0, /* U+0002A4 */ + 0, /* U+0002A5 */ + 0, /* U+0002A6 */ + 0, /* U+0002A7 */ + 0, /* U+0002A8 */ + 0, /* U+0002A9 */ + 0, /* U+0002AA */ + 0, /* U+0002AB */ + 0, /* U+0002AC */ + 0, /* U+0002AD */ + 0, /* U+0002AE */ + 0, /* U+0002AF */ + 0, /* U+0002B0 */ + 0, /* U+0002B1 */ + 0, /* U+0002B2 */ + 0, /* U+0002B3 */ + 0, /* U+0002B4 */ + 0, /* U+0002B5 */ + 0, /* U+0002B6 */ + 0, /* U+0002B7 */ + 0, /* U+0002B8 */ + 0, /* U+0002B9 */ + 0, /* U+0002BA */ + 0, /* U+0002BB */ + 0, /* U+0002BC */ + 0, /* U+0002BD */ + 0, /* U+0002BE */ + 0, /* U+0002BF */ + 0, /* U+0002C0 */ + 0, /* U+0002C1 */ + 0, /* U+0002C2 */ + 0, /* U+0002C3 */ + 0, /* U+0002C4 */ + 0, /* U+0002C5 */ + 0, /* U+0002C6 */ + 0, /* U+0002C7 */ + 0, /* U+0002C8 */ + 0, /* U+0002C9 */ + 0, /* U+0002CA */ + 0, /* U+0002CB */ + 0, /* U+0002CC */ + 0, /* U+0002CD */ + 0, /* U+0002CE */ + 0, /* U+0002CF */ + 0, /* U+0002D0 */ + 0, /* U+0002D1 */ + 0, /* U+0002D2 */ + 0, /* U+0002D3 */ + 0, /* U+0002D4 */ + 0, /* U+0002D5 */ + 0, /* U+0002D6 */ + 0, /* U+0002D7 */ + 0, /* U+0002D8 */ + 0, /* U+0002D9 */ + 0, /* U+0002DA */ + 0, /* U+0002DB */ + 0, /* U+0002DC */ + 0, /* U+0002DD */ + 0, /* U+0002DE */ + 0, /* U+0002DF */ + 0, /* U+0002E0 */ + 0, /* U+0002E1 */ + 0, /* U+0002E2 */ + 0, /* U+0002E3 */ + 0, /* U+0002E4 */ + 0, /* U+0002E5 */ + 0, /* U+0002E6 */ + 0, /* U+0002E7 */ + 0, /* U+0002E8 */ + 0, /* U+0002E9 */ + 0, /* U+0002EA */ + 0, /* U+0002EB */ + 0, /* U+0002EC */ + 0, /* U+0002ED */ + 0, /* U+0002EE */ + 0, /* U+0002EF */ + 0, /* U+0002F0 */ + 0, /* U+0002F1 */ + 0, /* U+0002F2 */ + 0, /* U+0002F3 */ + 0, /* U+0002F4 */ + 0, /* U+0002F5 */ + 0, /* U+0002F6 */ + 0, /* U+0002F7 */ + 0, /* U+0002F8 */ + 0, /* U+0002F9 */ + 0, /* U+0002FA */ + 0, /* U+0002FB */ + 0, /* U+0002FC */ + 0, /* U+0002FD */ + 0, /* U+0002FE */ + 0, /* U+0002FF */ + 0, /* U+000300 */ + 0, /* U+000301 */ + 0, /* U+000302 */ + 0, /* U+000303 */ + 0, /* U+000304 */ + 0, /* U+000305 */ + 0, /* U+000306 */ + 0, /* U+000307 */ + 0, /* U+000308 */ + 0, /* U+000309 */ + 0, /* U+00030A */ + 0, /* U+00030B */ + 0, /* U+00030C */ + 0, /* U+00030D */ + 0, /* U+00030E */ + 0, /* U+00030F */ + 0, /* U+000310 */ + 0, /* U+000311 */ + 0, /* U+000312 */ + 0, /* U+000313 */ + 0, /* U+000314 */ + 0, /* U+000315 */ + 0, /* U+000316 */ + 0, /* U+000317 */ + 0, /* U+000318 */ + 0, /* U+000319 */ + 0, /* U+00031A */ + 0, /* U+00031B */ + 0, /* U+00031C */ + 0, /* U+00031D */ + 0, /* U+00031E */ + 0, /* U+00031F */ + 0, /* U+000320 */ + 0, /* U+000321 */ + 0, /* U+000322 */ + 0, /* U+000323 */ + 0, /* U+000324 */ + 0, /* U+000325 */ + 0, /* U+000326 */ + 0, /* U+000327 */ + 0, /* U+000328 */ + 0, /* U+000329 */ + 0, /* U+00032A */ + 0, /* U+00032B */ + 0, /* U+00032C */ + 0, /* U+00032D */ + 0, /* U+00032E */ + 0, /* U+00032F */ + 0, /* U+000330 */ + 0, /* U+000331 */ + 0, /* U+000332 */ + 0, /* U+000333 */ + 0, /* U+000334 */ + 0, /* U+000335 */ + 0, /* U+000336 */ + 0, /* U+000337 */ + 0, /* U+000338 */ + 0, /* U+000339 */ + 0, /* U+00033A */ + 0, /* U+00033B */ + 0, /* U+00033C */ + 0, /* U+00033D */ + 0, /* U+00033E */ + 0, /* U+00033F */ + 0, /* U+000340 */ + 0, /* U+000341 */ + 0, /* U+000342 */ + 0, /* U+000343 */ + 0, /* U+000344 */ + 351, /* U+000345 */ + 0, /* U+000346 */ + 0, /* U+000347 */ + 0, /* U+000348 */ + 0, /* U+000349 */ + 0, /* U+00034A */ + 0, /* U+00034B */ + 0, /* U+00034C */ + 0, /* U+00034D */ + 0, /* U+00034E */ + 0, /* U+00034F */ + 0, /* U+000350 */ + 0, /* U+000351 */ + 0, /* U+000352 */ + 0, /* U+000353 */ + 0, /* U+000354 */ + 0, /* U+000355 */ + 0, /* U+000356 */ + 0, /* U+000357 */ + 0, /* U+000358 */ + 0, /* U+000359 */ + 0, /* U+00035A */ + 0, /* U+00035B */ + 0, /* U+00035C */ + 0, /* U+00035D */ + 0, /* U+00035E */ + 0, /* U+00035F */ + 0, /* U+000360 */ + 0, /* U+000361 */ + 0, /* U+000362 */ + 0, /* U+000363 */ + 0, /* U+000364 */ + 0, /* U+000365 */ + 0, /* U+000366 */ + 0, /* U+000367 */ + 0, /* U+000368 */ + 0, /* U+000369 */ + 0, /* U+00036A */ + 0, /* U+00036B */ + 0, /* U+00036C */ + 0, /* U+00036D */ + 0, /* U+00036E */ + 0, /* U+00036F */ + 352, /* U+000370 */ + 352, /* U+000371 */ + 353, /* U+000372 */ + 353, /* U+000373 */ + 0, /* U+000374 */ + 0, /* U+000375 */ + 354, /* U+000376 */ + 354, /* U+000377 */ + 0, /* U+000378 */ + 0, /* U+000379 */ + 0, /* U+00037A */ + 355, /* U+00037B */ + 356, /* U+00037C */ + 357, /* U+00037D */ + 0, /* U+00037E */ + 358, /* U+00037F */ + 0, /* U+000380 */ + 0, /* U+000381 */ + 0, /* U+000382 */ + 0, /* U+000383 */ + 0, /* U+000384 */ + 0, /* U+000385 */ + 359, /* U+000386 */ + 0, /* U+000387 */ + 360, /* U+000388 */ + 361, /* U+000389 */ + 362, /* U+00038A */ + 0, /* U+00038B */ + 363, /* U+00038C */ + 0, /* U+00038D */ + 364, /* U+00038E */ + 365, /* U+00038F */ + 366, /* U+000390 */ + 367, /* U+000391 */ + 368, /* U+000392 */ + 369, /* U+000393 */ + 370, /* U+000394 */ + 371, /* U+000395 */ + 372, /* U+000396 */ + 373, /* U+000397 */ + 374, /* U+000398 */ + 375, /* U+000399 */ + 376, /* U+00039A */ + 377, /* U+00039B */ + 378, /* U+00039C */ + 379, /* U+00039D */ + 380, /* U+00039E */ + 381, /* U+00039F */ + 382, /* U+0003A0 */ + 383, /* U+0003A1 */ + 0, /* U+0003A2 */ + 384, /* U+0003A3 */ + 385, /* U+0003A4 */ + 386, /* U+0003A5 */ + 387, /* U+0003A6 */ + 388, /* U+0003A7 */ + 389, /* U+0003A8 */ + 390, /* U+0003A9 */ + 391, /* U+0003AA */ + 392, /* U+0003AB */ + 359, /* U+0003AC */ + 360, /* U+0003AD */ + 361, /* U+0003AE */ + 362, /* U+0003AF */ + 393, /* U+0003B0 */ + 367, /* U+0003B1 */ + 368, /* U+0003B2 */ + 369, /* U+0003B3 */ + 370, /* U+0003B4 */ + 371, /* U+0003B5 */ + 372, /* U+0003B6 */ + 373, /* U+0003B7 */ + 374, /* U+0003B8 */ + 375, /* U+0003B9 */ + 376, /* U+0003BA */ + 377, /* U+0003BB */ + 378, /* U+0003BC */ + 379, /* U+0003BD */ + 380, /* U+0003BE */ + 381, /* U+0003BF */ + 382, /* U+0003C0 */ + 383, /* U+0003C1 */ + 394, /* U+0003C2 */ + 395, /* U+0003C3 */ + 385, /* U+0003C4 */ + 386, /* U+0003C5 */ + 387, /* U+0003C6 */ + 388, /* U+0003C7 */ + 389, /* U+0003C8 */ + 390, /* U+0003C9 */ + 391, /* U+0003CA */ + 392, /* U+0003CB */ + 363, /* U+0003CC */ + 364, /* U+0003CD */ + 365, /* U+0003CE */ + 396, /* U+0003CF */ + 397, /* U+0003D0 */ + 398, /* U+0003D1 */ + 0, /* U+0003D2 */ + 0, /* U+0003D3 */ + 0, /* U+0003D4 */ + 399, /* U+0003D5 */ + 400, /* U+0003D6 */ + 396, /* U+0003D7 */ + 401, /* U+0003D8 */ + 401, /* U+0003D9 */ + 402, /* U+0003DA */ + 402, /* U+0003DB */ + 403, /* U+0003DC */ + 403, /* U+0003DD */ + 404, /* U+0003DE */ + 404, /* U+0003DF */ + 405, /* U+0003E0 */ + 405, /* U+0003E1 */ + 406, /* U+0003E2 */ + 406, /* U+0003E3 */ + 407, /* U+0003E4 */ + 407, /* U+0003E5 */ + 408, /* U+0003E6 */ + 408, /* U+0003E7 */ + 409, /* U+0003E8 */ + 409, /* U+0003E9 */ + 410, /* U+0003EA */ + 410, /* U+0003EB */ + 411, /* U+0003EC */ + 411, /* U+0003ED */ + 412, /* U+0003EE */ + 412, /* U+0003EF */ + 413, /* U+0003F0 */ + 414, /* U+0003F1 */ + 415, /* U+0003F2 */ + 358, /* U+0003F3 */ + 416, /* U+0003F4 */ + 417, /* U+0003F5 */ + 0, /* U+0003F6 */ + 418, /* U+0003F7 */ + 418, /* U+0003F8 */ + 415, /* U+0003F9 */ + 419, /* U+0003FA */ + 419, /* U+0003FB */ + 0, /* U+0003FC */ + 355, /* U+0003FD */ + 356, /* U+0003FE */ + 357, /* U+0003FF */ + 420, /* U+000400 */ + 421, /* U+000401 */ + 422, /* U+000402 */ + 423, /* U+000403 */ + 424, /* U+000404 */ + 425, /* U+000405 */ + 426, /* U+000406 */ + 427, /* U+000407 */ + 428, /* U+000408 */ + 429, /* U+000409 */ + 430, /* U+00040A */ + 431, /* U+00040B */ + 432, /* U+00040C */ + 433, /* U+00040D */ + 434, /* U+00040E */ + 435, /* U+00040F */ + 436, /* U+000410 */ + 437, /* U+000411 */ + 438, /* U+000412 */ + 439, /* U+000413 */ + 440, /* U+000414 */ + 441, /* U+000415 */ + 442, /* U+000416 */ + 443, /* U+000417 */ + 444, /* U+000418 */ + 445, /* U+000419 */ + 446, /* U+00041A */ + 447, /* U+00041B */ + 448, /* U+00041C */ + 449, /* U+00041D */ + 450, /* U+00041E */ + 451, /* U+00041F */ + 452, /* U+000420 */ + 453, /* U+000421 */ + 454, /* U+000422 */ + 455, /* U+000423 */ + 456, /* U+000424 */ + 457, /* U+000425 */ + 458, /* U+000426 */ + 459, /* U+000427 */ + 460, /* U+000428 */ + 461, /* U+000429 */ + 462, /* U+00042A */ + 463, /* U+00042B */ + 464, /* U+00042C */ + 465, /* U+00042D */ + 466, /* U+00042E */ + 467, /* U+00042F */ + 436, /* U+000430 */ + 437, /* U+000431 */ + 438, /* U+000432 */ + 439, /* U+000433 */ + 440, /* U+000434 */ + 441, /* U+000435 */ + 442, /* U+000436 */ + 443, /* U+000437 */ + 444, /* U+000438 */ + 445, /* U+000439 */ + 446, /* U+00043A */ + 447, /* U+00043B */ + 448, /* U+00043C */ + 449, /* U+00043D */ + 450, /* U+00043E */ + 451, /* U+00043F */ + 452, /* U+000440 */ + 453, /* U+000441 */ + 454, /* U+000442 */ + 455, /* U+000443 */ + 456, /* U+000444 */ + 457, /* U+000445 */ + 458, /* U+000446 */ + 459, /* U+000447 */ + 460, /* U+000448 */ + 461, /* U+000449 */ + 462, /* U+00044A */ + 463, /* U+00044B */ + 464, /* U+00044C */ + 465, /* U+00044D */ + 466, /* U+00044E */ + 467, /* U+00044F */ + 420, /* U+000450 */ + 421, /* U+000451 */ + 422, /* U+000452 */ + 423, /* U+000453 */ + 424, /* U+000454 */ + 425, /* U+000455 */ + 426, /* U+000456 */ + 427, /* U+000457 */ + 428, /* U+000458 */ + 429, /* U+000459 */ + 430, /* U+00045A */ + 431, /* U+00045B */ + 432, /* U+00045C */ + 433, /* U+00045D */ + 434, /* U+00045E */ + 435, /* U+00045F */ + 468, /* U+000460 */ + 468, /* U+000461 */ + 469, /* U+000462 */ + 469, /* U+000463 */ + 470, /* U+000464 */ + 470, /* U+000465 */ + 471, /* U+000466 */ + 471, /* U+000467 */ + 472, /* U+000468 */ + 472, /* U+000469 */ + 473, /* U+00046A */ + 473, /* U+00046B */ + 474, /* U+00046C */ + 474, /* U+00046D */ + 475, /* U+00046E */ + 475, /* U+00046F */ + 476, /* U+000470 */ + 476, /* U+000471 */ + 477, /* U+000472 */ + 477, /* U+000473 */ + 478, /* U+000474 */ + 478, /* U+000475 */ + 479, /* U+000476 */ + 479, /* U+000477 */ + 480, /* U+000478 */ + 480, /* U+000479 */ + 481, /* U+00047A */ + 481, /* U+00047B */ + 482, /* U+00047C */ + 482, /* U+00047D */ + 483, /* U+00047E */ + 483, /* U+00047F */ + 484, /* U+000480 */ + 484, /* U+000481 */ + 0, /* U+000482 */ + 0, /* U+000483 */ + 0, /* U+000484 */ + 0, /* U+000485 */ + 0, /* U+000486 */ + 0, /* U+000487 */ + 0, /* U+000488 */ + 0, /* U+000489 */ + 485, /* U+00048A */ + 485, /* U+00048B */ + 486, /* U+00048C */ + 486, /* U+00048D */ + 487, /* U+00048E */ + 487, /* U+00048F */ + 488, /* U+000490 */ + 488, /* U+000491 */ + 489, /* U+000492 */ + 489, /* U+000493 */ + 490, /* U+000494 */ + 490, /* U+000495 */ + 491, /* U+000496 */ + 491, /* U+000497 */ + 492, /* U+000498 */ + 492, /* U+000499 */ + 493, /* U+00049A */ + 493, /* U+00049B */ + 494, /* U+00049C */ + 494, /* U+00049D */ + 495, /* U+00049E */ + 495, /* U+00049F */ + 496, /* U+0004A0 */ + 496, /* U+0004A1 */ + 497, /* U+0004A2 */ + 497, /* U+0004A3 */ + 498, /* U+0004A4 */ + 498, /* U+0004A5 */ + 499, /* U+0004A6 */ + 499, /* U+0004A7 */ + 500, /* U+0004A8 */ + 500, /* U+0004A9 */ + 501, /* U+0004AA */ + 501, /* U+0004AB */ + 502, /* U+0004AC */ + 502, /* U+0004AD */ + 503, /* U+0004AE */ + 503, /* U+0004AF */ + 504, /* U+0004B0 */ + 504, /* U+0004B1 */ + 505, /* U+0004B2 */ + 505, /* U+0004B3 */ + 506, /* U+0004B4 */ + 506, /* U+0004B5 */ + 507, /* U+0004B6 */ + 507, /* U+0004B7 */ + 508, /* U+0004B8 */ + 508, /* U+0004B9 */ + 509, /* U+0004BA */ + 509, /* U+0004BB */ + 510, /* U+0004BC */ + 510, /* U+0004BD */ + 511, /* U+0004BE */ + 511, /* U+0004BF */ + 512, /* U+0004C0 */ + 513, /* U+0004C1 */ + 513, /* U+0004C2 */ + 514, /* U+0004C3 */ + 514, /* U+0004C4 */ + 515, /* U+0004C5 */ + 515, /* U+0004C6 */ + 516, /* U+0004C7 */ + 516, /* U+0004C8 */ + 517, /* U+0004C9 */ + 517, /* U+0004CA */ + 518, /* U+0004CB */ + 518, /* U+0004CC */ + 519, /* U+0004CD */ + 519, /* U+0004CE */ + 512, /* U+0004CF */ + 520, /* U+0004D0 */ + 520, /* U+0004D1 */ + 521, /* U+0004D2 */ + 521, /* U+0004D3 */ + 522, /* U+0004D4 */ + 522, /* U+0004D5 */ + 523, /* U+0004D6 */ + 523, /* U+0004D7 */ + 524, /* U+0004D8 */ + 524, /* U+0004D9 */ + 525, /* U+0004DA */ + 525, /* U+0004DB */ + 526, /* U+0004DC */ + 526, /* U+0004DD */ + 527, /* U+0004DE */ + 527, /* U+0004DF */ + 528, /* U+0004E0 */ + 528, /* U+0004E1 */ + 529, /* U+0004E2 */ + 529, /* U+0004E3 */ + 530, /* U+0004E4 */ + 530, /* U+0004E5 */ + 531, /* U+0004E6 */ + 531, /* U+0004E7 */ + 532, /* U+0004E8 */ + 532, /* U+0004E9 */ + 533, /* U+0004EA */ + 533, /* U+0004EB */ + 534, /* U+0004EC */ + 534, /* U+0004ED */ + 535, /* U+0004EE */ + 535, /* U+0004EF */ + 536, /* U+0004F0 */ + 536, /* U+0004F1 */ + 537, /* U+0004F2 */ + 537, /* U+0004F3 */ + 538, /* U+0004F4 */ + 538, /* U+0004F5 */ + 539, /* U+0004F6 */ + 539, /* U+0004F7 */ + 540, /* U+0004F8 */ + 540, /* U+0004F9 */ + 541, /* U+0004FA */ + 541, /* U+0004FB */ + 542, /* U+0004FC */ + 542, /* U+0004FD */ + 543, /* U+0004FE */ + 543, /* U+0004FF */ + 544, /* U+000500 */ + 544, /* U+000501 */ + 545, /* U+000502 */ + 545, /* U+000503 */ + 546, /* U+000504 */ + 546, /* U+000505 */ + 547, /* U+000506 */ + 547, /* U+000507 */ + 548, /* U+000508 */ + 548, /* U+000509 */ + 549, /* U+00050A */ + 549, /* U+00050B */ + 550, /* U+00050C */ + 550, /* U+00050D */ + 551, /* U+00050E */ + 551, /* U+00050F */ + 552, /* U+000510 */ + 552, /* U+000511 */ + 553, /* U+000512 */ + 553, /* U+000513 */ + 554, /* U+000514 */ + 554, /* U+000515 */ + 555, /* U+000516 */ + 555, /* U+000517 */ + 556, /* U+000518 */ + 556, /* U+000519 */ + 557, /* U+00051A */ + 557, /* U+00051B */ + 558, /* U+00051C */ + 558, /* U+00051D */ + 559, /* U+00051E */ + 559, /* U+00051F */ + 560, /* U+000520 */ + 560, /* U+000521 */ + 561, /* U+000522 */ + 561, /* U+000523 */ + 562, /* U+000524 */ + 562, /* U+000525 */ + 563, /* U+000526 */ + 563, /* U+000527 */ + 564, /* U+000528 */ + 564, /* U+000529 */ + 565, /* U+00052A */ + 565, /* U+00052B */ + 566, /* U+00052C */ + 566, /* U+00052D */ + 567, /* U+00052E */ + 567, /* U+00052F */ + 0, /* U+000530 */ + 568, /* U+000531 */ + 569, /* U+000532 */ + 570, /* U+000533 */ + 571, /* U+000534 */ + 572, /* U+000535 */ + 573, /* U+000536 */ + 574, /* U+000537 */ + 575, /* U+000538 */ + 576, /* U+000539 */ + 577, /* U+00053A */ + 578, /* U+00053B */ + 579, /* U+00053C */ + 580, /* U+00053D */ + 581, /* U+00053E */ + 582, /* U+00053F */ + 583, /* U+000540 */ + 584, /* U+000541 */ + 585, /* U+000542 */ + 586, /* U+000543 */ + 587, /* U+000544 */ + 588, /* U+000545 */ + 589, /* U+000546 */ + 590, /* U+000547 */ + 591, /* U+000548 */ + 592, /* U+000549 */ + 593, /* U+00054A */ + 594, /* U+00054B */ + 595, /* U+00054C */ + 596, /* U+00054D */ + 597, /* U+00054E */ + 598, /* U+00054F */ + 599, /* U+000550 */ + 600, /* U+000551 */ + 601, /* U+000552 */ + 602, /* U+000553 */ + 603, /* U+000554 */ + 604, /* U+000555 */ + 605, /* U+000556 */ + 0, /* U+000557 */ + 0, /* U+000558 */ + 0, /* U+000559 */ + 0, /* U+00055A */ + 0, /* U+00055B */ + 0, /* U+00055C */ + 0, /* U+00055D */ + 0, /* U+00055E */ + 0, /* U+00055F */ + 0, /* U+000560 */ + 568, /* U+000561 */ + 569, /* U+000562 */ + 570, /* U+000563 */ + 571, /* U+000564 */ + 572, /* U+000565 */ + 573, /* U+000566 */ + 574, /* U+000567 */ + 575, /* U+000568 */ + 576, /* U+000569 */ + 577, /* U+00056A */ + 578, /* U+00056B */ + 579, /* U+00056C */ + 580, /* U+00056D */ + 581, /* U+00056E */ + 582, /* U+00056F */ + 583, /* U+000570 */ + 584, /* U+000571 */ + 585, /* U+000572 */ + 586, /* U+000573 */ + 587, /* U+000574 */ + 588, /* U+000575 */ + 589, /* U+000576 */ + 590, /* U+000577 */ + 591, /* U+000578 */ + 592, /* U+000579 */ + 593, /* U+00057A */ + 594, /* U+00057B */ + 595, /* U+00057C */ + 596, /* U+00057D */ + 597, /* U+00057E */ + 598, /* U+00057F */ + 599, /* U+000580 */ + 600, /* U+000581 */ + 601, /* U+000582 */ + 602, /* U+000583 */ + 603, /* U+000584 */ + 604, /* U+000585 */ + 605, /* U+000586 */ + 606, /* U+000587 */ + 607, /* U+0010A0 */ + 608, /* U+0010A1 */ + 609, /* U+0010A2 */ + 610, /* U+0010A3 */ + 611, /* U+0010A4 */ + 612, /* U+0010A5 */ + 613, /* U+0010A6 */ + 614, /* U+0010A7 */ + 615, /* U+0010A8 */ + 616, /* U+0010A9 */ + 617, /* U+0010AA */ + 618, /* U+0010AB */ + 619, /* U+0010AC */ + 620, /* U+0010AD */ + 621, /* U+0010AE */ + 622, /* U+0010AF */ + 623, /* U+0010B0 */ + 624, /* U+0010B1 */ + 625, /* U+0010B2 */ + 626, /* U+0010B3 */ + 627, /* U+0010B4 */ + 628, /* U+0010B5 */ + 629, /* U+0010B6 */ + 630, /* U+0010B7 */ + 631, /* U+0010B8 */ + 632, /* U+0010B9 */ + 633, /* U+0010BA */ + 634, /* U+0010BB */ + 635, /* U+0010BC */ + 636, /* U+0010BD */ + 637, /* U+0010BE */ + 638, /* U+0010BF */ + 639, /* U+0010C0 */ + 640, /* U+0010C1 */ + 641, /* U+0010C2 */ + 642, /* U+0010C3 */ + 643, /* U+0010C4 */ + 644, /* U+0010C5 */ + 0, /* U+0010C6 */ + 645, /* U+0010C7 */ + 0, /* U+0010C8 */ + 0, /* U+0010C9 */ + 0, /* U+0010CA */ + 0, /* U+0010CB */ + 0, /* U+0010CC */ + 646, /* U+0010CD */ + 0, /* U+0010CE */ + 0, /* U+0010CF */ + 647, /* U+0010D0 */ + 648, /* U+0010D1 */ + 649, /* U+0010D2 */ + 650, /* U+0010D3 */ + 651, /* U+0010D4 */ + 652, /* U+0010D5 */ + 653, /* U+0010D6 */ + 654, /* U+0010D7 */ + 655, /* U+0010D8 */ + 656, /* U+0010D9 */ + 657, /* U+0010DA */ + 658, /* U+0010DB */ + 659, /* U+0010DC */ + 660, /* U+0010DD */ + 661, /* U+0010DE */ + 662, /* U+0010DF */ + 663, /* U+0010E0 */ + 664, /* U+0010E1 */ + 665, /* U+0010E2 */ + 666, /* U+0010E3 */ + 667, /* U+0010E4 */ + 668, /* U+0010E5 */ + 669, /* U+0010E6 */ + 670, /* U+0010E7 */ + 671, /* U+0010E8 */ + 672, /* U+0010E9 */ + 673, /* U+0010EA */ + 674, /* U+0010EB */ + 675, /* U+0010EC */ + 676, /* U+0010ED */ + 677, /* U+0010EE */ + 678, /* U+0010EF */ + 679, /* U+0010F0 */ + 680, /* U+0010F1 */ + 681, /* U+0010F2 */ + 682, /* U+0010F3 */ + 683, /* U+0010F4 */ + 684, /* U+0010F5 */ + 685, /* U+0010F6 */ + 686, /* U+0010F7 */ + 687, /* U+0010F8 */ + 688, /* U+0010F9 */ + 689, /* U+0010FA */ + 0, /* U+0010FB */ + 0, /* U+0010FC */ + 690, /* U+0010FD */ + 691, /* U+0010FE */ + 692, /* U+0010FF */ + 693, /* U+0013A0 */ + 694, /* U+0013A1 */ + 695, /* U+0013A2 */ + 696, /* U+0013A3 */ + 697, /* U+0013A4 */ + 698, /* U+0013A5 */ + 699, /* U+0013A6 */ + 700, /* U+0013A7 */ + 701, /* U+0013A8 */ + 702, /* U+0013A9 */ + 703, /* U+0013AA */ + 704, /* U+0013AB */ + 705, /* U+0013AC */ + 706, /* U+0013AD */ + 707, /* U+0013AE */ + 708, /* U+0013AF */ + 709, /* U+0013B0 */ + 710, /* U+0013B1 */ + 711, /* U+0013B2 */ + 712, /* U+0013B3 */ + 713, /* U+0013B4 */ + 714, /* U+0013B5 */ + 715, /* U+0013B6 */ + 716, /* U+0013B7 */ + 717, /* U+0013B8 */ + 718, /* U+0013B9 */ + 719, /* U+0013BA */ + 720, /* U+0013BB */ + 721, /* U+0013BC */ + 722, /* U+0013BD */ + 723, /* U+0013BE */ + 724, /* U+0013BF */ + 725, /* U+0013C0 */ + 726, /* U+0013C1 */ + 727, /* U+0013C2 */ + 728, /* U+0013C3 */ + 729, /* U+0013C4 */ + 730, /* U+0013C5 */ + 731, /* U+0013C6 */ + 732, /* U+0013C7 */ + 733, /* U+0013C8 */ + 734, /* U+0013C9 */ + 735, /* U+0013CA */ + 736, /* U+0013CB */ + 737, /* U+0013CC */ + 738, /* U+0013CD */ + 739, /* U+0013CE */ + 740, /* U+0013CF */ + 741, /* U+0013D0 */ + 742, /* U+0013D1 */ + 743, /* U+0013D2 */ + 744, /* U+0013D3 */ + 745, /* U+0013D4 */ + 746, /* U+0013D5 */ + 747, /* U+0013D6 */ + 748, /* U+0013D7 */ + 749, /* U+0013D8 */ + 750, /* U+0013D9 */ + 751, /* U+0013DA */ + 752, /* U+0013DB */ + 753, /* U+0013DC */ + 754, /* U+0013DD */ + 755, /* U+0013DE */ + 756, /* U+0013DF */ + 757, /* U+0013E0 */ + 758, /* U+0013E1 */ + 759, /* U+0013E2 */ + 760, /* U+0013E3 */ + 761, /* U+0013E4 */ + 762, /* U+0013E5 */ + 763, /* U+0013E6 */ + 764, /* U+0013E7 */ + 765, /* U+0013E8 */ + 766, /* U+0013E9 */ + 767, /* U+0013EA */ + 768, /* U+0013EB */ + 769, /* U+0013EC */ + 770, /* U+0013ED */ + 771, /* U+0013EE */ + 772, /* U+0013EF */ + 773, /* U+0013F0 */ + 774, /* U+0013F1 */ + 775, /* U+0013F2 */ + 776, /* U+0013F3 */ + 777, /* U+0013F4 */ + 778, /* U+0013F5 */ + 0, /* U+0013F6 */ + 0, /* U+0013F7 */ + 773, /* U+0013F8 */ + 774, /* U+0013F9 */ + 775, /* U+0013FA */ + 776, /* U+0013FB */ + 777, /* U+0013FC */ + 778, /* U+0013FD */ + 779, /* U+001C80 */ + 780, /* U+001C81 */ + 781, /* U+001C82 */ + 782, /* U+001C83 */ + 783, /* U+001C84 */ + 784, /* U+001C85 */ + 785, /* U+001C86 */ + 786, /* U+001C87 */ + 787, /* U+001C88 */ + 788, /* U+001C89 */ + 788, /* U+001C8A */ + 0, /* U+001C8B */ + 0, /* U+001C8C */ + 0, /* U+001C8D */ + 0, /* U+001C8E */ + 0, /* U+001C8F */ + 789, /* U+001C90 */ + 790, /* U+001C91 */ + 791, /* U+001C92 */ + 792, /* U+001C93 */ + 793, /* U+001C94 */ + 794, /* U+001C95 */ + 795, /* U+001C96 */ + 796, /* U+001C97 */ + 797, /* U+001C98 */ + 798, /* U+001C99 */ + 799, /* U+001C9A */ + 800, /* U+001C9B */ + 801, /* U+001C9C */ + 802, /* U+001C9D */ + 803, /* U+001C9E */ + 804, /* U+001C9F */ + 805, /* U+001CA0 */ + 806, /* U+001CA1 */ + 807, /* U+001CA2 */ + 808, /* U+001CA3 */ + 809, /* U+001CA4 */ + 810, /* U+001CA5 */ + 811, /* U+001CA6 */ + 812, /* U+001CA7 */ + 813, /* U+001CA8 */ + 814, /* U+001CA9 */ + 815, /* U+001CAA */ + 816, /* U+001CAB */ + 817, /* U+001CAC */ + 818, /* U+001CAD */ + 819, /* U+001CAE */ + 820, /* U+001CAF */ + 821, /* U+001CB0 */ + 822, /* U+001CB1 */ + 823, /* U+001CB2 */ + 824, /* U+001CB3 */ + 825, /* U+001CB4 */ + 826, /* U+001CB5 */ + 827, /* U+001CB6 */ + 828, /* U+001CB7 */ + 829, /* U+001CB8 */ + 830, /* U+001CB9 */ + 831, /* U+001CBA */ + 0, /* U+001CBB */ + 0, /* U+001CBC */ + 832, /* U+001CBD */ + 833, /* U+001CBE */ + 834, /* U+001CBF */ + 0, /* U+001CC0 */ + 0, /* U+001CC1 */ + 0, /* U+001CC2 */ + 0, /* U+001CC3 */ + 0, /* U+001CC4 */ + 0, /* U+001CC5 */ + 0, /* U+001CC6 */ + 0, /* U+001CC7 */ + 0, /* U+001CC8 */ + 0, /* U+001CC9 */ + 0, /* U+001CCA */ + 0, /* U+001CCB */ + 0, /* U+001CCC */ + 0, /* U+001CCD */ + 0, /* U+001CCE */ + 0, /* U+001CCF */ + 0, /* U+001CD0 */ + 0, /* U+001CD1 */ + 0, /* U+001CD2 */ + 0, /* U+001CD3 */ + 0, /* U+001CD4 */ + 0, /* U+001CD5 */ + 0, /* U+001CD6 */ + 0, /* U+001CD7 */ + 0, /* U+001CD8 */ + 0, /* U+001CD9 */ + 0, /* U+001CDA */ + 0, /* U+001CDB */ + 0, /* U+001CDC */ + 0, /* U+001CDD */ + 0, /* U+001CDE */ + 0, /* U+001CDF */ + 0, /* U+001CE0 */ + 0, /* U+001CE1 */ + 0, /* U+001CE2 */ + 0, /* U+001CE3 */ + 0, /* U+001CE4 */ + 0, /* U+001CE5 */ + 0, /* U+001CE6 */ + 0, /* U+001CE7 */ + 0, /* U+001CE8 */ + 0, /* U+001CE9 */ + 0, /* U+001CEA */ + 0, /* U+001CEB */ + 0, /* U+001CEC */ + 0, /* U+001CED */ + 0, /* U+001CEE */ + 0, /* U+001CEF */ + 0, /* U+001CF0 */ + 0, /* U+001CF1 */ + 0, /* U+001CF2 */ + 0, /* U+001CF3 */ + 0, /* U+001CF4 */ + 0, /* U+001CF5 */ + 0, /* U+001CF6 */ + 0, /* U+001CF7 */ + 0, /* U+001CF8 */ + 0, /* U+001CF9 */ + 0, /* U+001CFA */ + 0, /* U+001CFB */ + 0, /* U+001CFC */ + 0, /* U+001CFD */ + 0, /* U+001CFE */ + 0, /* U+001CFF */ + 0, /* U+001D00 */ + 0, /* U+001D01 */ + 0, /* U+001D02 */ + 0, /* U+001D03 */ + 0, /* U+001D04 */ + 0, /* U+001D05 */ + 0, /* U+001D06 */ + 0, /* U+001D07 */ + 0, /* U+001D08 */ + 0, /* U+001D09 */ + 0, /* U+001D0A */ + 0, /* U+001D0B */ + 0, /* U+001D0C */ + 0, /* U+001D0D */ + 0, /* U+001D0E */ + 0, /* U+001D0F */ + 0, /* U+001D10 */ + 0, /* U+001D11 */ + 0, /* U+001D12 */ + 0, /* U+001D13 */ + 0, /* U+001D14 */ + 0, /* U+001D15 */ + 0, /* U+001D16 */ + 0, /* U+001D17 */ + 0, /* U+001D18 */ + 0, /* U+001D19 */ + 0, /* U+001D1A */ + 0, /* U+001D1B */ + 0, /* U+001D1C */ + 0, /* U+001D1D */ + 0, /* U+001D1E */ + 0, /* U+001D1F */ + 0, /* U+001D20 */ + 0, /* U+001D21 */ + 0, /* U+001D22 */ + 0, /* U+001D23 */ + 0, /* U+001D24 */ + 0, /* U+001D25 */ + 0, /* U+001D26 */ + 0, /* U+001D27 */ + 0, /* U+001D28 */ + 0, /* U+001D29 */ + 0, /* U+001D2A */ + 0, /* U+001D2B */ + 0, /* U+001D2C */ + 0, /* U+001D2D */ + 0, /* U+001D2E */ + 0, /* U+001D2F */ + 0, /* U+001D30 */ + 0, /* U+001D31 */ + 0, /* U+001D32 */ + 0, /* U+001D33 */ + 0, /* U+001D34 */ + 0, /* U+001D35 */ + 0, /* U+001D36 */ + 0, /* U+001D37 */ + 0, /* U+001D38 */ + 0, /* U+001D39 */ + 0, /* U+001D3A */ + 0, /* U+001D3B */ + 0, /* U+001D3C */ + 0, /* U+001D3D */ + 0, /* U+001D3E */ + 0, /* U+001D3F */ + 0, /* U+001D40 */ + 0, /* U+001D41 */ + 0, /* U+001D42 */ + 0, /* U+001D43 */ + 0, /* U+001D44 */ + 0, /* U+001D45 */ + 0, /* U+001D46 */ + 0, /* U+001D47 */ + 0, /* U+001D48 */ + 0, /* U+001D49 */ + 0, /* U+001D4A */ + 0, /* U+001D4B */ + 0, /* U+001D4C */ + 0, /* U+001D4D */ + 0, /* U+001D4E */ + 0, /* U+001D4F */ + 0, /* U+001D50 */ + 0, /* U+001D51 */ + 0, /* U+001D52 */ + 0, /* U+001D53 */ + 0, /* U+001D54 */ + 0, /* U+001D55 */ + 0, /* U+001D56 */ + 0, /* U+001D57 */ + 0, /* U+001D58 */ + 0, /* U+001D59 */ + 0, /* U+001D5A */ + 0, /* U+001D5B */ + 0, /* U+001D5C */ + 0, /* U+001D5D */ + 0, /* U+001D5E */ + 0, /* U+001D5F */ + 0, /* U+001D60 */ + 0, /* U+001D61 */ + 0, /* U+001D62 */ + 0, /* U+001D63 */ + 0, /* U+001D64 */ + 0, /* U+001D65 */ + 0, /* U+001D66 */ + 0, /* U+001D67 */ + 0, /* U+001D68 */ + 0, /* U+001D69 */ + 0, /* U+001D6A */ + 0, /* U+001D6B */ + 0, /* U+001D6C */ + 0, /* U+001D6D */ + 0, /* U+001D6E */ + 0, /* U+001D6F */ + 0, /* U+001D70 */ + 0, /* U+001D71 */ + 0, /* U+001D72 */ + 0, /* U+001D73 */ + 0, /* U+001D74 */ + 0, /* U+001D75 */ + 0, /* U+001D76 */ + 0, /* U+001D77 */ + 0, /* U+001D78 */ + 835, /* U+001D79 */ + 0, /* U+001D7A */ + 0, /* U+001D7B */ + 0, /* U+001D7C */ + 836, /* U+001D7D */ + 0, /* U+001D7E */ + 0, /* U+001D7F */ + 0, /* U+001D80 */ + 0, /* U+001D81 */ + 0, /* U+001D82 */ + 0, /* U+001D83 */ + 0, /* U+001D84 */ + 0, /* U+001D85 */ + 0, /* U+001D86 */ + 0, /* U+001D87 */ + 0, /* U+001D88 */ + 0, /* U+001D89 */ + 0, /* U+001D8A */ + 0, /* U+001D8B */ + 0, /* U+001D8C */ + 0, /* U+001D8D */ + 837, /* U+001D8E */ + 0, /* U+001D8F */ + 0, /* U+001D90 */ + 0, /* U+001D91 */ + 0, /* U+001D92 */ + 0, /* U+001D93 */ + 0, /* U+001D94 */ + 0, /* U+001D95 */ + 0, /* U+001D96 */ + 0, /* U+001D97 */ + 0, /* U+001D98 */ + 0, /* U+001D99 */ + 0, /* U+001D9A */ + 0, /* U+001D9B */ + 0, /* U+001D9C */ + 0, /* U+001D9D */ + 0, /* U+001D9E */ + 0, /* U+001D9F */ + 0, /* U+001DA0 */ + 0, /* U+001DA1 */ + 0, /* U+001DA2 */ + 0, /* U+001DA3 */ + 0, /* U+001DA4 */ + 0, /* U+001DA5 */ + 0, /* U+001DA6 */ + 0, /* U+001DA7 */ + 0, /* U+001DA8 */ + 0, /* U+001DA9 */ + 0, /* U+001DAA */ + 0, /* U+001DAB */ + 0, /* U+001DAC */ + 0, /* U+001DAD */ + 0, /* U+001DAE */ + 0, /* U+001DAF */ + 0, /* U+001DB0 */ + 0, /* U+001DB1 */ + 0, /* U+001DB2 */ + 0, /* U+001DB3 */ + 0, /* U+001DB4 */ + 0, /* U+001DB5 */ + 0, /* U+001DB6 */ + 0, /* U+001DB7 */ + 0, /* U+001DB8 */ + 0, /* U+001DB9 */ + 0, /* U+001DBA */ + 0, /* U+001DBB */ + 0, /* U+001DBC */ + 0, /* U+001DBD */ + 0, /* U+001DBE */ + 0, /* U+001DBF */ + 0, /* U+001DC0 */ + 0, /* U+001DC1 */ + 0, /* U+001DC2 */ + 0, /* U+001DC3 */ + 0, /* U+001DC4 */ + 0, /* U+001DC5 */ + 0, /* U+001DC6 */ + 0, /* U+001DC7 */ + 0, /* U+001DC8 */ + 0, /* U+001DC9 */ + 0, /* U+001DCA */ + 0, /* U+001DCB */ + 0, /* U+001DCC */ + 0, /* U+001DCD */ + 0, /* U+001DCE */ + 0, /* U+001DCF */ + 0, /* U+001DD0 */ + 0, /* U+001DD1 */ + 0, /* U+001DD2 */ + 0, /* U+001DD3 */ + 0, /* U+001DD4 */ + 0, /* U+001DD5 */ + 0, /* U+001DD6 */ + 0, /* U+001DD7 */ + 0, /* U+001DD8 */ + 0, /* U+001DD9 */ + 0, /* U+001DDA */ + 0, /* U+001DDB */ + 0, /* U+001DDC */ + 0, /* U+001DDD */ + 0, /* U+001DDE */ + 0, /* U+001DDF */ + 0, /* U+001DE0 */ + 0, /* U+001DE1 */ + 0, /* U+001DE2 */ + 0, /* U+001DE3 */ + 0, /* U+001DE4 */ + 0, /* U+001DE5 */ + 0, /* U+001DE6 */ + 0, /* U+001DE7 */ + 0, /* U+001DE8 */ + 0, /* U+001DE9 */ + 0, /* U+001DEA */ + 0, /* U+001DEB */ + 0, /* U+001DEC */ + 0, /* U+001DED */ + 0, /* U+001DEE */ + 0, /* U+001DEF */ + 0, /* U+001DF0 */ + 0, /* U+001DF1 */ + 0, /* U+001DF2 */ + 0, /* U+001DF3 */ + 0, /* U+001DF4 */ + 0, /* U+001DF5 */ + 0, /* U+001DF6 */ + 0, /* U+001DF7 */ + 0, /* U+001DF8 */ + 0, /* U+001DF9 */ + 0, /* U+001DFA */ + 0, /* U+001DFB */ + 0, /* U+001DFC */ + 0, /* U+001DFD */ + 0, /* U+001DFE */ + 0, /* U+001DFF */ + 838, /* U+001E00 */ + 838, /* U+001E01 */ + 839, /* U+001E02 */ + 839, /* U+001E03 */ + 840, /* U+001E04 */ + 840, /* U+001E05 */ + 841, /* U+001E06 */ + 841, /* U+001E07 */ + 842, /* U+001E08 */ + 842, /* U+001E09 */ + 843, /* U+001E0A */ + 843, /* U+001E0B */ + 844, /* U+001E0C */ + 844, /* U+001E0D */ + 845, /* U+001E0E */ + 845, /* U+001E0F */ + 846, /* U+001E10 */ + 846, /* U+001E11 */ + 847, /* U+001E12 */ + 847, /* U+001E13 */ + 848, /* U+001E14 */ + 848, /* U+001E15 */ + 849, /* U+001E16 */ + 849, /* U+001E17 */ + 850, /* U+001E18 */ + 850, /* U+001E19 */ + 851, /* U+001E1A */ + 851, /* U+001E1B */ + 852, /* U+001E1C */ + 852, /* U+001E1D */ + 853, /* U+001E1E */ + 853, /* U+001E1F */ + 854, /* U+001E20 */ + 854, /* U+001E21 */ + 855, /* U+001E22 */ + 855, /* U+001E23 */ + 856, /* U+001E24 */ + 856, /* U+001E25 */ + 857, /* U+001E26 */ + 857, /* U+001E27 */ + 858, /* U+001E28 */ + 858, /* U+001E29 */ + 859, /* U+001E2A */ + 859, /* U+001E2B */ + 860, /* U+001E2C */ + 860, /* U+001E2D */ + 861, /* U+001E2E */ + 861, /* U+001E2F */ + 862, /* U+001E30 */ + 862, /* U+001E31 */ + 863, /* U+001E32 */ + 863, /* U+001E33 */ + 864, /* U+001E34 */ + 864, /* U+001E35 */ + 865, /* U+001E36 */ + 865, /* U+001E37 */ + 866, /* U+001E38 */ + 866, /* U+001E39 */ + 867, /* U+001E3A */ + 867, /* U+001E3B */ + 868, /* U+001E3C */ + 868, /* U+001E3D */ + 869, /* U+001E3E */ + 869, /* U+001E3F */ + 870, /* U+001E40 */ + 870, /* U+001E41 */ + 871, /* U+001E42 */ + 871, /* U+001E43 */ + 872, /* U+001E44 */ + 872, /* U+001E45 */ + 873, /* U+001E46 */ + 873, /* U+001E47 */ + 874, /* U+001E48 */ + 874, /* U+001E49 */ + 875, /* U+001E4A */ + 875, /* U+001E4B */ + 876, /* U+001E4C */ + 876, /* U+001E4D */ + 877, /* U+001E4E */ + 877, /* U+001E4F */ + 878, /* U+001E50 */ + 878, /* U+001E51 */ + 879, /* U+001E52 */ + 879, /* U+001E53 */ + 880, /* U+001E54 */ + 880, /* U+001E55 */ + 881, /* U+001E56 */ + 881, /* U+001E57 */ + 882, /* U+001E58 */ + 882, /* U+001E59 */ + 883, /* U+001E5A */ + 883, /* U+001E5B */ + 884, /* U+001E5C */ + 884, /* U+001E5D */ + 885, /* U+001E5E */ + 885, /* U+001E5F */ + 886, /* U+001E60 */ + 886, /* U+001E61 */ + 887, /* U+001E62 */ + 887, /* U+001E63 */ + 888, /* U+001E64 */ + 888, /* U+001E65 */ + 889, /* U+001E66 */ + 889, /* U+001E67 */ + 890, /* U+001E68 */ + 890, /* U+001E69 */ + 891, /* U+001E6A */ + 891, /* U+001E6B */ + 892, /* U+001E6C */ + 892, /* U+001E6D */ + 893, /* U+001E6E */ + 893, /* U+001E6F */ + 894, /* U+001E70 */ + 894, /* U+001E71 */ + 895, /* U+001E72 */ + 895, /* U+001E73 */ + 896, /* U+001E74 */ + 896, /* U+001E75 */ + 897, /* U+001E76 */ + 897, /* U+001E77 */ + 898, /* U+001E78 */ + 898, /* U+001E79 */ + 899, /* U+001E7A */ + 899, /* U+001E7B */ + 900, /* U+001E7C */ + 900, /* U+001E7D */ + 901, /* U+001E7E */ + 901, /* U+001E7F */ + 902, /* U+001E80 */ + 902, /* U+001E81 */ + 903, /* U+001E82 */ + 903, /* U+001E83 */ + 904, /* U+001E84 */ + 904, /* U+001E85 */ + 905, /* U+001E86 */ + 905, /* U+001E87 */ + 906, /* U+001E88 */ + 906, /* U+001E89 */ + 907, /* U+001E8A */ + 907, /* U+001E8B */ + 908, /* U+001E8C */ + 908, /* U+001E8D */ + 909, /* U+001E8E */ + 909, /* U+001E8F */ + 910, /* U+001E90 */ + 910, /* U+001E91 */ + 911, /* U+001E92 */ + 911, /* U+001E93 */ + 912, /* U+001E94 */ + 912, /* U+001E95 */ + 913, /* U+001E96 */ + 914, /* U+001E97 */ + 915, /* U+001E98 */ + 916, /* U+001E99 */ + 917, /* U+001E9A */ + 918, /* U+001E9B */ + 0, /* U+001E9C */ + 0, /* U+001E9D */ + 919, /* U+001E9E */ + 0, /* U+001E9F */ + 920, /* U+001EA0 */ + 920, /* U+001EA1 */ + 921, /* U+001EA2 */ + 921, /* U+001EA3 */ + 922, /* U+001EA4 */ + 922, /* U+001EA5 */ + 923, /* U+001EA6 */ + 923, /* U+001EA7 */ + 924, /* U+001EA8 */ + 924, /* U+001EA9 */ + 925, /* U+001EAA */ + 925, /* U+001EAB */ + 926, /* U+001EAC */ + 926, /* U+001EAD */ + 927, /* U+001EAE */ + 927, /* U+001EAF */ + 928, /* U+001EB0 */ + 928, /* U+001EB1 */ + 929, /* U+001EB2 */ + 929, /* U+001EB3 */ + 930, /* U+001EB4 */ + 930, /* U+001EB5 */ + 931, /* U+001EB6 */ + 931, /* U+001EB7 */ + 932, /* U+001EB8 */ + 932, /* U+001EB9 */ + 933, /* U+001EBA */ + 933, /* U+001EBB */ + 934, /* U+001EBC */ + 934, /* U+001EBD */ + 935, /* U+001EBE */ + 935, /* U+001EBF */ + 936, /* U+001EC0 */ + 936, /* U+001EC1 */ + 937, /* U+001EC2 */ + 937, /* U+001EC3 */ + 938, /* U+001EC4 */ + 938, /* U+001EC5 */ + 939, /* U+001EC6 */ + 939, /* U+001EC7 */ + 940, /* U+001EC8 */ + 940, /* U+001EC9 */ + 941, /* U+001ECA */ + 941, /* U+001ECB */ + 942, /* U+001ECC */ + 942, /* U+001ECD */ + 943, /* U+001ECE */ + 943, /* U+001ECF */ + 944, /* U+001ED0 */ + 944, /* U+001ED1 */ + 945, /* U+001ED2 */ + 945, /* U+001ED3 */ + 946, /* U+001ED4 */ + 946, /* U+001ED5 */ + 947, /* U+001ED6 */ + 947, /* U+001ED7 */ + 948, /* U+001ED8 */ + 948, /* U+001ED9 */ + 949, /* U+001EDA */ + 949, /* U+001EDB */ + 950, /* U+001EDC */ + 950, /* U+001EDD */ + 951, /* U+001EDE */ + 951, /* U+001EDF */ + 952, /* U+001EE0 */ + 952, /* U+001EE1 */ + 953, /* U+001EE2 */ + 953, /* U+001EE3 */ + 954, /* U+001EE4 */ + 954, /* U+001EE5 */ + 955, /* U+001EE6 */ + 955, /* U+001EE7 */ + 956, /* U+001EE8 */ + 956, /* U+001EE9 */ + 957, /* U+001EEA */ + 957, /* U+001EEB */ + 958, /* U+001EEC */ + 958, /* U+001EED */ + 959, /* U+001EEE */ + 959, /* U+001EEF */ + 960, /* U+001EF0 */ + 960, /* U+001EF1 */ + 961, /* U+001EF2 */ + 961, /* U+001EF3 */ + 962, /* U+001EF4 */ + 962, /* U+001EF5 */ + 963, /* U+001EF6 */ + 963, /* U+001EF7 */ + 964, /* U+001EF8 */ + 964, /* U+001EF9 */ + 965, /* U+001EFA */ + 965, /* U+001EFB */ + 966, /* U+001EFC */ + 966, /* U+001EFD */ + 967, /* U+001EFE */ + 967, /* U+001EFF */ + 968, /* U+001F00 */ + 969, /* U+001F01 */ + 970, /* U+001F02 */ + 971, /* U+001F03 */ + 972, /* U+001F04 */ + 973, /* U+001F05 */ + 974, /* U+001F06 */ + 975, /* U+001F07 */ + 968, /* U+001F08 */ + 969, /* U+001F09 */ + 970, /* U+001F0A */ + 971, /* U+001F0B */ + 972, /* U+001F0C */ + 973, /* U+001F0D */ + 974, /* U+001F0E */ + 975, /* U+001F0F */ + 976, /* U+001F10 */ + 977, /* U+001F11 */ + 978, /* U+001F12 */ + 979, /* U+001F13 */ + 980, /* U+001F14 */ + 981, /* U+001F15 */ + 0, /* U+001F16 */ + 0, /* U+001F17 */ + 976, /* U+001F18 */ + 977, /* U+001F19 */ + 978, /* U+001F1A */ + 979, /* U+001F1B */ + 980, /* U+001F1C */ + 981, /* U+001F1D */ + 0, /* U+001F1E */ + 0, /* U+001F1F */ + 982, /* U+001F20 */ + 983, /* U+001F21 */ + 984, /* U+001F22 */ + 985, /* U+001F23 */ + 986, /* U+001F24 */ + 987, /* U+001F25 */ + 988, /* U+001F26 */ + 989, /* U+001F27 */ + 982, /* U+001F28 */ + 983, /* U+001F29 */ + 984, /* U+001F2A */ + 985, /* U+001F2B */ + 986, /* U+001F2C */ + 987, /* U+001F2D */ + 988, /* U+001F2E */ + 989, /* U+001F2F */ + 990, /* U+001F30 */ + 991, /* U+001F31 */ + 992, /* U+001F32 */ + 993, /* U+001F33 */ + 994, /* U+001F34 */ + 995, /* U+001F35 */ + 996, /* U+001F36 */ + 997, /* U+001F37 */ + 990, /* U+001F38 */ + 991, /* U+001F39 */ + 992, /* U+001F3A */ + 993, /* U+001F3B */ + 994, /* U+001F3C */ + 995, /* U+001F3D */ + 996, /* U+001F3E */ + 997, /* U+001F3F */ + 998, /* U+001F40 */ + 999, /* U+001F41 */ + 1000, /* U+001F42 */ + 1001, /* U+001F43 */ + 1002, /* U+001F44 */ + 1003, /* U+001F45 */ + 0, /* U+001F46 */ + 0, /* U+001F47 */ + 998, /* U+001F48 */ + 999, /* U+001F49 */ + 1000, /* U+001F4A */ + 1001, /* U+001F4B */ + 1002, /* U+001F4C */ + 1003, /* U+001F4D */ + 0, /* U+001F4E */ + 0, /* U+001F4F */ + 1004, /* U+001F50 */ + 1005, /* U+001F51 */ + 1006, /* U+001F52 */ + 1007, /* U+001F53 */ + 1008, /* U+001F54 */ + 1009, /* U+001F55 */ + 1010, /* U+001F56 */ + 1011, /* U+001F57 */ + 0, /* U+001F58 */ + 1005, /* U+001F59 */ + 0, /* U+001F5A */ + 1007, /* U+001F5B */ + 0, /* U+001F5C */ + 1009, /* U+001F5D */ + 0, /* U+001F5E */ + 1011, /* U+001F5F */ + 1012, /* U+001F60 */ + 1013, /* U+001F61 */ + 1014, /* U+001F62 */ + 1015, /* U+001F63 */ + 1016, /* U+001F64 */ + 1017, /* U+001F65 */ + 1018, /* U+001F66 */ + 1019, /* U+001F67 */ + 1012, /* U+001F68 */ + 1013, /* U+001F69 */ + 1014, /* U+001F6A */ + 1015, /* U+001F6B */ + 1016, /* U+001F6C */ + 1017, /* U+001F6D */ + 1018, /* U+001F6E */ + 1019, /* U+001F6F */ + 1020, /* U+001F70 */ + 1021, /* U+001F71 */ + 1022, /* U+001F72 */ + 1023, /* U+001F73 */ + 1024, /* U+001F74 */ + 1025, /* U+001F75 */ + 1026, /* U+001F76 */ + 1027, /* U+001F77 */ + 1028, /* U+001F78 */ + 1029, /* U+001F79 */ + 1030, /* U+001F7A */ + 1031, /* U+001F7B */ + 1032, /* U+001F7C */ + 1033, /* U+001F7D */ + 0, /* U+001F7E */ + 0, /* U+001F7F */ + 1034, /* U+001F80 */ + 1035, /* U+001F81 */ + 1036, /* U+001F82 */ + 1037, /* U+001F83 */ + 1038, /* U+001F84 */ + 1039, /* U+001F85 */ + 1040, /* U+001F86 */ + 1041, /* U+001F87 */ + 1042, /* U+001F88 */ + 1043, /* U+001F89 */ + 1044, /* U+001F8A */ + 1045, /* U+001F8B */ + 1046, /* U+001F8C */ + 1047, /* U+001F8D */ + 1048, /* U+001F8E */ + 1049, /* U+001F8F */ + 1050, /* U+001F90 */ + 1051, /* U+001F91 */ + 1052, /* U+001F92 */ + 1053, /* U+001F93 */ + 1054, /* U+001F94 */ + 1055, /* U+001F95 */ + 1056, /* U+001F96 */ + 1057, /* U+001F97 */ + 1058, /* U+001F98 */ + 1059, /* U+001F99 */ + 1060, /* U+001F9A */ + 1061, /* U+001F9B */ + 1062, /* U+001F9C */ + 1063, /* U+001F9D */ + 1064, /* U+001F9E */ + 1065, /* U+001F9F */ + 1066, /* U+001FA0 */ + 1067, /* U+001FA1 */ + 1068, /* U+001FA2 */ + 1069, /* U+001FA3 */ + 1070, /* U+001FA4 */ + 1071, /* U+001FA5 */ + 1072, /* U+001FA6 */ + 1073, /* U+001FA7 */ + 1074, /* U+001FA8 */ + 1075, /* U+001FA9 */ + 1076, /* U+001FAA */ + 1077, /* U+001FAB */ + 1078, /* U+001FAC */ + 1079, /* U+001FAD */ + 1080, /* U+001FAE */ + 1081, /* U+001FAF */ + 1082, /* U+001FB0 */ + 1083, /* U+001FB1 */ + 1084, /* U+001FB2 */ + 1085, /* U+001FB3 */ + 1086, /* U+001FB4 */ + 0, /* U+001FB5 */ + 1087, /* U+001FB6 */ + 1088, /* U+001FB7 */ + 1082, /* U+001FB8 */ + 1083, /* U+001FB9 */ + 1020, /* U+001FBA */ + 1021, /* U+001FBB */ + 1089, /* U+001FBC */ + 0, /* U+001FBD */ + 1090, /* U+001FBE */ + 0, /* U+001FBF */ + 0, /* U+001FC0 */ + 0, /* U+001FC1 */ + 1091, /* U+001FC2 */ + 1092, /* U+001FC3 */ + 1093, /* U+001FC4 */ + 0, /* U+001FC5 */ + 1094, /* U+001FC6 */ + 1095, /* U+001FC7 */ + 1022, /* U+001FC8 */ + 1023, /* U+001FC9 */ + 1024, /* U+001FCA */ + 1025, /* U+001FCB */ + 1096, /* U+001FCC */ + 0, /* U+001FCD */ + 0, /* U+001FCE */ + 0, /* U+001FCF */ + 1097, /* U+001FD0 */ + 1098, /* U+001FD1 */ + 1099, /* U+001FD2 */ + 1100, /* U+001FD3 */ + 0, /* U+001FD4 */ + 0, /* U+001FD5 */ + 1101, /* U+001FD6 */ + 1102, /* U+001FD7 */ + 1097, /* U+001FD8 */ + 1098, /* U+001FD9 */ + 1026, /* U+001FDA */ + 1027, /* U+001FDB */ + 0, /* U+001FDC */ + 0, /* U+001FDD */ + 0, /* U+001FDE */ + 0, /* U+001FDF */ + 1103, /* U+001FE0 */ + 1104, /* U+001FE1 */ + 1105, /* U+001FE2 */ + 1106, /* U+001FE3 */ + 1107, /* U+001FE4 */ + 1108, /* U+001FE5 */ + 1109, /* U+001FE6 */ + 1110, /* U+001FE7 */ + 1103, /* U+001FE8 */ + 1104, /* U+001FE9 */ + 1030, /* U+001FEA */ + 1031, /* U+001FEB */ + 1108, /* U+001FEC */ + 0, /* U+001FED */ + 0, /* U+001FEE */ + 0, /* U+001FEF */ + 0, /* U+001FF0 */ + 0, /* U+001FF1 */ + 1111, /* U+001FF2 */ + 1112, /* U+001FF3 */ + 1113, /* U+001FF4 */ + 0, /* U+001FF5 */ + 1114, /* U+001FF6 */ + 1115, /* U+001FF7 */ + 1028, /* U+001FF8 */ + 1029, /* U+001FF9 */ + 1032, /* U+001FFA */ + 1033, /* U+001FFB */ + 1116, /* U+001FFC */ + 0, /* U+001FFD */ + 0, /* U+001FFE */ + 0, /* U+001FFF */ + 0, /* U+002000 */ + 0, /* U+002001 */ + 0, /* U+002002 */ + 0, /* U+002003 */ + 0, /* U+002004 */ + 0, /* U+002005 */ + 0, /* U+002006 */ + 0, /* U+002007 */ + 0, /* U+002008 */ + 0, /* U+002009 */ + 0, /* U+00200A */ + 0, /* U+00200B */ + 0, /* U+00200C */ + 0, /* U+00200D */ + 0, /* U+00200E */ + 0, /* U+00200F */ + 0, /* U+002010 */ + 0, /* U+002011 */ + 0, /* U+002012 */ + 0, /* U+002013 */ + 0, /* U+002014 */ + 0, /* U+002015 */ + 0, /* U+002016 */ + 0, /* U+002017 */ + 0, /* U+002018 */ + 0, /* U+002019 */ + 0, /* U+00201A */ + 0, /* U+00201B */ + 0, /* U+00201C */ + 0, /* U+00201D */ + 0, /* U+00201E */ + 0, /* U+00201F */ + 0, /* U+002020 */ + 0, /* U+002021 */ + 0, /* U+002022 */ + 0, /* U+002023 */ + 0, /* U+002024 */ + 0, /* U+002025 */ + 0, /* U+002026 */ + 0, /* U+002027 */ + 0, /* U+002028 */ + 0, /* U+002029 */ + 0, /* U+00202A */ + 0, /* U+00202B */ + 0, /* U+00202C */ + 0, /* U+00202D */ + 0, /* U+00202E */ + 0, /* U+00202F */ + 0, /* U+002030 */ + 0, /* U+002031 */ + 0, /* U+002032 */ + 0, /* U+002033 */ + 0, /* U+002034 */ + 0, /* U+002035 */ + 0, /* U+002036 */ + 0, /* U+002037 */ + 0, /* U+002038 */ + 0, /* U+002039 */ + 0, /* U+00203A */ + 0, /* U+00203B */ + 0, /* U+00203C */ + 0, /* U+00203D */ + 0, /* U+00203E */ + 0, /* U+00203F */ + 0, /* U+002040 */ + 0, /* U+002041 */ + 0, /* U+002042 */ + 0, /* U+002043 */ + 0, /* U+002044 */ + 0, /* U+002045 */ + 0, /* U+002046 */ + 0, /* U+002047 */ + 0, /* U+002048 */ + 0, /* U+002049 */ + 0, /* U+00204A */ + 0, /* U+00204B */ + 0, /* U+00204C */ + 0, /* U+00204D */ + 0, /* U+00204E */ + 0, /* U+00204F */ + 0, /* U+002050 */ + 0, /* U+002051 */ + 0, /* U+002052 */ + 0, /* U+002053 */ + 0, /* U+002054 */ + 0, /* U+002055 */ + 0, /* U+002056 */ + 0, /* U+002057 */ + 0, /* U+002058 */ + 0, /* U+002059 */ + 0, /* U+00205A */ + 0, /* U+00205B */ + 0, /* U+00205C */ + 0, /* U+00205D */ + 0, /* U+00205E */ + 0, /* U+00205F */ + 0, /* U+002060 */ + 0, /* U+002061 */ + 0, /* U+002062 */ + 0, /* U+002063 */ + 0, /* U+002064 */ + 0, /* U+002065 */ + 0, /* U+002066 */ + 0, /* U+002067 */ + 0, /* U+002068 */ + 0, /* U+002069 */ + 0, /* U+00206A */ + 0, /* U+00206B */ + 0, /* U+00206C */ + 0, /* U+00206D */ + 0, /* U+00206E */ + 0, /* U+00206F */ + 0, /* U+002070 */ + 0, /* U+002071 */ + 0, /* U+002072 */ + 0, /* U+002073 */ + 0, /* U+002074 */ + 0, /* U+002075 */ + 0, /* U+002076 */ + 0, /* U+002077 */ + 0, /* U+002078 */ + 0, /* U+002079 */ + 0, /* U+00207A */ + 0, /* U+00207B */ + 0, /* U+00207C */ + 0, /* U+00207D */ + 0, /* U+00207E */ + 0, /* U+00207F */ + 0, /* U+002080 */ + 0, /* U+002081 */ + 0, /* U+002082 */ + 0, /* U+002083 */ + 0, /* U+002084 */ + 0, /* U+002085 */ + 0, /* U+002086 */ + 0, /* U+002087 */ + 0, /* U+002088 */ + 0, /* U+002089 */ + 0, /* U+00208A */ + 0, /* U+00208B */ + 0, /* U+00208C */ + 0, /* U+00208D */ + 0, /* U+00208E */ + 0, /* U+00208F */ + 0, /* U+002090 */ + 0, /* U+002091 */ + 0, /* U+002092 */ + 0, /* U+002093 */ + 0, /* U+002094 */ + 0, /* U+002095 */ + 0, /* U+002096 */ + 0, /* U+002097 */ + 0, /* U+002098 */ + 0, /* U+002099 */ + 0, /* U+00209A */ + 0, /* U+00209B */ + 0, /* U+00209C */ + 0, /* U+00209D */ + 0, /* U+00209E */ + 0, /* U+00209F */ + 0, /* U+0020A0 */ + 0, /* U+0020A1 */ + 0, /* U+0020A2 */ + 0, /* U+0020A3 */ + 0, /* U+0020A4 */ + 0, /* U+0020A5 */ + 0, /* U+0020A6 */ + 0, /* U+0020A7 */ + 0, /* U+0020A8 */ + 0, /* U+0020A9 */ + 0, /* U+0020AA */ + 0, /* U+0020AB */ + 0, /* U+0020AC */ + 0, /* U+0020AD */ + 0, /* U+0020AE */ + 0, /* U+0020AF */ + 0, /* U+0020B0 */ + 0, /* U+0020B1 */ + 0, /* U+0020B2 */ + 0, /* U+0020B3 */ + 0, /* U+0020B4 */ + 0, /* U+0020B5 */ + 0, /* U+0020B6 */ + 0, /* U+0020B7 */ + 0, /* U+0020B8 */ + 0, /* U+0020B9 */ + 0, /* U+0020BA */ + 0, /* U+0020BB */ + 0, /* U+0020BC */ + 0, /* U+0020BD */ + 0, /* U+0020BE */ + 0, /* U+0020BF */ + 0, /* U+0020C0 */ + 0, /* U+0020C1 */ + 0, /* U+0020C2 */ + 0, /* U+0020C3 */ + 0, /* U+0020C4 */ + 0, /* U+0020C5 */ + 0, /* U+0020C6 */ + 0, /* U+0020C7 */ + 0, /* U+0020C8 */ + 0, /* U+0020C9 */ + 0, /* U+0020CA */ + 0, /* U+0020CB */ + 0, /* U+0020CC */ + 0, /* U+0020CD */ + 0, /* U+0020CE */ + 0, /* U+0020CF */ + 0, /* U+0020D0 */ + 0, /* U+0020D1 */ + 0, /* U+0020D2 */ + 0, /* U+0020D3 */ + 0, /* U+0020D4 */ + 0, /* U+0020D5 */ + 0, /* U+0020D6 */ + 0, /* U+0020D7 */ + 0, /* U+0020D8 */ + 0, /* U+0020D9 */ + 0, /* U+0020DA */ + 0, /* U+0020DB */ + 0, /* U+0020DC */ + 0, /* U+0020DD */ + 0, /* U+0020DE */ + 0, /* U+0020DF */ + 0, /* U+0020E0 */ + 0, /* U+0020E1 */ + 0, /* U+0020E2 */ + 0, /* U+0020E3 */ + 0, /* U+0020E4 */ + 0, /* U+0020E5 */ + 0, /* U+0020E6 */ + 0, /* U+0020E7 */ + 0, /* U+0020E8 */ + 0, /* U+0020E9 */ + 0, /* U+0020EA */ + 0, /* U+0020EB */ + 0, /* U+0020EC */ + 0, /* U+0020ED */ + 0, /* U+0020EE */ + 0, /* U+0020EF */ + 0, /* U+0020F0 */ + 0, /* U+0020F1 */ + 0, /* U+0020F2 */ + 0, /* U+0020F3 */ + 0, /* U+0020F4 */ + 0, /* U+0020F5 */ + 0, /* U+0020F6 */ + 0, /* U+0020F7 */ + 0, /* U+0020F8 */ + 0, /* U+0020F9 */ + 0, /* U+0020FA */ + 0, /* U+0020FB */ + 0, /* U+0020FC */ + 0, /* U+0020FD */ + 0, /* U+0020FE */ + 0, /* U+0020FF */ + 0, /* U+002100 */ + 0, /* U+002101 */ + 0, /* U+002102 */ + 0, /* U+002103 */ + 0, /* U+002104 */ + 0, /* U+002105 */ + 0, /* U+002106 */ + 0, /* U+002107 */ + 0, /* U+002108 */ + 0, /* U+002109 */ + 0, /* U+00210A */ + 0, /* U+00210B */ + 0, /* U+00210C */ + 0, /* U+00210D */ + 0, /* U+00210E */ + 0, /* U+00210F */ + 0, /* U+002110 */ + 0, /* U+002111 */ + 0, /* U+002112 */ + 0, /* U+002113 */ + 0, /* U+002114 */ + 0, /* U+002115 */ + 0, /* U+002116 */ + 0, /* U+002117 */ + 0, /* U+002118 */ + 0, /* U+002119 */ + 0, /* U+00211A */ + 0, /* U+00211B */ + 0, /* U+00211C */ + 0, /* U+00211D */ + 0, /* U+00211E */ + 0, /* U+00211F */ + 0, /* U+002120 */ + 0, /* U+002121 */ + 0, /* U+002122 */ + 0, /* U+002123 */ + 0, /* U+002124 */ + 0, /* U+002125 */ + 1117, /* U+002126 */ + 0, /* U+002127 */ + 0, /* U+002128 */ + 0, /* U+002129 */ + 1118, /* U+00212A */ + 1119, /* U+00212B */ + 0, /* U+00212C */ + 0, /* U+00212D */ + 0, /* U+00212E */ + 0, /* U+00212F */ + 0, /* U+002130 */ + 0, /* U+002131 */ + 1120, /* U+002132 */ + 0, /* U+002133 */ + 0, /* U+002134 */ + 0, /* U+002135 */ + 0, /* U+002136 */ + 0, /* U+002137 */ + 0, /* U+002138 */ + 0, /* U+002139 */ + 0, /* U+00213A */ + 0, /* U+00213B */ + 0, /* U+00213C */ + 0, /* U+00213D */ + 0, /* U+00213E */ + 0, /* U+00213F */ + 0, /* U+002140 */ + 0, /* U+002141 */ + 0, /* U+002142 */ + 0, /* U+002143 */ + 0, /* U+002144 */ + 0, /* U+002145 */ + 0, /* U+002146 */ + 0, /* U+002147 */ + 0, /* U+002148 */ + 0, /* U+002149 */ + 0, /* U+00214A */ + 0, /* U+00214B */ + 0, /* U+00214C */ + 0, /* U+00214D */ + 1120, /* U+00214E */ + 0, /* U+00214F */ + 0, /* U+002150 */ + 0, /* U+002151 */ + 0, /* U+002152 */ + 0, /* U+002153 */ + 0, /* U+002154 */ + 0, /* U+002155 */ + 0, /* U+002156 */ + 0, /* U+002157 */ + 0, /* U+002158 */ + 0, /* U+002159 */ + 0, /* U+00215A */ + 0, /* U+00215B */ + 0, /* U+00215C */ + 0, /* U+00215D */ + 0, /* U+00215E */ + 0, /* U+00215F */ + 1121, /* U+002160 */ + 1122, /* U+002161 */ + 1123, /* U+002162 */ + 1124, /* U+002163 */ + 1125, /* U+002164 */ + 1126, /* U+002165 */ + 1127, /* U+002166 */ + 1128, /* U+002167 */ + 1129, /* U+002168 */ + 1130, /* U+002169 */ + 1131, /* U+00216A */ + 1132, /* U+00216B */ + 1133, /* U+00216C */ + 1134, /* U+00216D */ + 1135, /* U+00216E */ + 1136, /* U+00216F */ + 1121, /* U+002170 */ + 1122, /* U+002171 */ + 1123, /* U+002172 */ + 1124, /* U+002173 */ + 1125, /* U+002174 */ + 1126, /* U+002175 */ + 1127, /* U+002176 */ + 1128, /* U+002177 */ + 1129, /* U+002178 */ + 1130, /* U+002179 */ + 1131, /* U+00217A */ + 1132, /* U+00217B */ + 1133, /* U+00217C */ + 1134, /* U+00217D */ + 1135, /* U+00217E */ + 1136, /* U+00217F */ + 0, /* U+002180 */ + 0, /* U+002181 */ + 0, /* U+002182 */ + 1137, /* U+002183 */ + 1137, /* U+002184 */ + 1138, /* U+0024B6 */ + 1139, /* U+0024B7 */ + 1140, /* U+0024B8 */ + 1141, /* U+0024B9 */ + 1142, /* U+0024BA */ + 1143, /* U+0024BB */ + 1144, /* U+0024BC */ + 1145, /* U+0024BD */ + 1146, /* U+0024BE */ + 1147, /* U+0024BF */ + 1148, /* U+0024C0 */ + 1149, /* U+0024C1 */ + 1150, /* U+0024C2 */ + 1151, /* U+0024C3 */ + 1152, /* U+0024C4 */ + 1153, /* U+0024C5 */ + 1154, /* U+0024C6 */ + 1155, /* U+0024C7 */ + 1156, /* U+0024C8 */ + 1157, /* U+0024C9 */ + 1158, /* U+0024CA */ + 1159, /* U+0024CB */ + 1160, /* U+0024CC */ + 1161, /* U+0024CD */ + 1162, /* U+0024CE */ + 1163, /* U+0024CF */ + 1138, /* U+0024D0 */ + 1139, /* U+0024D1 */ + 1140, /* U+0024D2 */ + 1141, /* U+0024D3 */ + 1142, /* U+0024D4 */ + 1143, /* U+0024D5 */ + 1144, /* U+0024D6 */ + 1145, /* U+0024D7 */ + 1146, /* U+0024D8 */ + 1147, /* U+0024D9 */ + 1148, /* U+0024DA */ + 1149, /* U+0024DB */ + 1150, /* U+0024DC */ + 1151, /* U+0024DD */ + 1152, /* U+0024DE */ + 1153, /* U+0024DF */ + 1154, /* U+0024E0 */ + 1155, /* U+0024E1 */ + 1156, /* U+0024E2 */ + 1157, /* U+0024E3 */ + 1158, /* U+0024E4 */ + 1159, /* U+0024E5 */ + 1160, /* U+0024E6 */ + 1161, /* U+0024E7 */ + 1162, /* U+0024E8 */ + 1163, /* U+0024E9 */ + 1164, /* U+002C00 */ + 1165, /* U+002C01 */ + 1166, /* U+002C02 */ + 1167, /* U+002C03 */ + 1168, /* U+002C04 */ + 1169, /* U+002C05 */ + 1170, /* U+002C06 */ + 1171, /* U+002C07 */ + 1172, /* U+002C08 */ + 1173, /* U+002C09 */ + 1174, /* U+002C0A */ + 1175, /* U+002C0B */ + 1176, /* U+002C0C */ + 1177, /* U+002C0D */ + 1178, /* U+002C0E */ + 1179, /* U+002C0F */ + 1180, /* U+002C10 */ + 1181, /* U+002C11 */ + 1182, /* U+002C12 */ + 1183, /* U+002C13 */ + 1184, /* U+002C14 */ + 1185, /* U+002C15 */ + 1186, /* U+002C16 */ + 1187, /* U+002C17 */ + 1188, /* U+002C18 */ + 1189, /* U+002C19 */ + 1190, /* U+002C1A */ + 1191, /* U+002C1B */ + 1192, /* U+002C1C */ + 1193, /* U+002C1D */ + 1194, /* U+002C1E */ + 1195, /* U+002C1F */ + 1196, /* U+002C20 */ + 1197, /* U+002C21 */ + 1198, /* U+002C22 */ + 1199, /* U+002C23 */ + 1200, /* U+002C24 */ + 1201, /* U+002C25 */ + 1202, /* U+002C26 */ + 1203, /* U+002C27 */ + 1204, /* U+002C28 */ + 1205, /* U+002C29 */ + 1206, /* U+002C2A */ + 1207, /* U+002C2B */ + 1208, /* U+002C2C */ + 1209, /* U+002C2D */ + 1210, /* U+002C2E */ + 1211, /* U+002C2F */ + 1164, /* U+002C30 */ + 1165, /* U+002C31 */ + 1166, /* U+002C32 */ + 1167, /* U+002C33 */ + 1168, /* U+002C34 */ + 1169, /* U+002C35 */ + 1170, /* U+002C36 */ + 1171, /* U+002C37 */ + 1172, /* U+002C38 */ + 1173, /* U+002C39 */ + 1174, /* U+002C3A */ + 1175, /* U+002C3B */ + 1176, /* U+002C3C */ + 1177, /* U+002C3D */ + 1178, /* U+002C3E */ + 1179, /* U+002C3F */ + 1180, /* U+002C40 */ + 1181, /* U+002C41 */ + 1182, /* U+002C42 */ + 1183, /* U+002C43 */ + 1184, /* U+002C44 */ + 1185, /* U+002C45 */ + 1186, /* U+002C46 */ + 1187, /* U+002C47 */ + 1188, /* U+002C48 */ + 1189, /* U+002C49 */ + 1190, /* U+002C4A */ + 1191, /* U+002C4B */ + 1192, /* U+002C4C */ + 1193, /* U+002C4D */ + 1194, /* U+002C4E */ + 1195, /* U+002C4F */ + 1196, /* U+002C50 */ + 1197, /* U+002C51 */ + 1198, /* U+002C52 */ + 1199, /* U+002C53 */ + 1200, /* U+002C54 */ + 1201, /* U+002C55 */ + 1202, /* U+002C56 */ + 1203, /* U+002C57 */ + 1204, /* U+002C58 */ + 1205, /* U+002C59 */ + 1206, /* U+002C5A */ + 1207, /* U+002C5B */ + 1208, /* U+002C5C */ + 1209, /* U+002C5D */ + 1210, /* U+002C5E */ + 1211, /* U+002C5F */ + 1212, /* U+002C60 */ + 1212, /* U+002C61 */ + 343, /* U+002C62 */ + 836, /* U+002C63 */ + 346, /* U+002C64 */ + 321, /* U+002C65 */ + 323, /* U+002C66 */ + 1213, /* U+002C67 */ + 1213, /* U+002C68 */ + 1214, /* U+002C69 */ + 1214, /* U+002C6A */ + 1215, /* U+002C6B */ + 1215, /* U+002C6C */ + 335, /* U+002C6D */ + 345, /* U+002C6E */ + 334, /* U+002C6F */ + 336, /* U+002C70 */ + 0, /* U+002C71 */ + 1216, /* U+002C72 */ + 1216, /* U+002C73 */ + 0, /* U+002C74 */ + 1217, /* U+002C75 */ + 1217, /* U+002C76 */ + 0, /* U+002C77 */ + 0, /* U+002C78 */ + 0, /* U+002C79 */ + 0, /* U+002C7A */ + 0, /* U+002C7B */ + 0, /* U+002C7C */ + 0, /* U+002C7D */ + 324, /* U+002C7E */ + 325, /* U+002C7F */ + 1218, /* U+002C80 */ + 1218, /* U+002C81 */ + 1219, /* U+002C82 */ + 1219, /* U+002C83 */ + 1220, /* U+002C84 */ + 1220, /* U+002C85 */ + 1221, /* U+002C86 */ + 1221, /* U+002C87 */ + 1222, /* U+002C88 */ + 1222, /* U+002C89 */ + 1223, /* U+002C8A */ + 1223, /* U+002C8B */ + 1224, /* U+002C8C */ + 1224, /* U+002C8D */ + 1225, /* U+002C8E */ + 1225, /* U+002C8F */ + 1226, /* U+002C90 */ + 1226, /* U+002C91 */ + 1227, /* U+002C92 */ + 1227, /* U+002C93 */ + 1228, /* U+002C94 */ + 1228, /* U+002C95 */ + 1229, /* U+002C96 */ + 1229, /* U+002C97 */ + 1230, /* U+002C98 */ + 1230, /* U+002C99 */ + 1231, /* U+002C9A */ + 1231, /* U+002C9B */ + 1232, /* U+002C9C */ + 1232, /* U+002C9D */ + 1233, /* U+002C9E */ + 1233, /* U+002C9F */ + 1234, /* U+002CA0 */ + 1234, /* U+002CA1 */ + 1235, /* U+002CA2 */ + 1235, /* U+002CA3 */ + 1236, /* U+002CA4 */ + 1236, /* U+002CA5 */ + 1237, /* U+002CA6 */ + 1237, /* U+002CA7 */ + 1238, /* U+002CA8 */ + 1238, /* U+002CA9 */ + 1239, /* U+002CAA */ + 1239, /* U+002CAB */ + 1240, /* U+002CAC */ + 1240, /* U+002CAD */ + 1241, /* U+002CAE */ + 1241, /* U+002CAF */ + 1242, /* U+002CB0 */ + 1242, /* U+002CB1 */ + 1243, /* U+002CB2 */ + 1243, /* U+002CB3 */ + 1244, /* U+002CB4 */ + 1244, /* U+002CB5 */ + 1245, /* U+002CB6 */ + 1245, /* U+002CB7 */ + 1246, /* U+002CB8 */ + 1246, /* U+002CB9 */ + 1247, /* U+002CBA */ + 1247, /* U+002CBB */ + 1248, /* U+002CBC */ + 1248, /* U+002CBD */ + 1249, /* U+002CBE */ + 1249, /* U+002CBF */ + 1250, /* U+002CC0 */ + 1250, /* U+002CC1 */ + 1251, /* U+002CC2 */ + 1251, /* U+002CC3 */ + 1252, /* U+002CC4 */ + 1252, /* U+002CC5 */ + 1253, /* U+002CC6 */ + 1253, /* U+002CC7 */ + 1254, /* U+002CC8 */ + 1254, /* U+002CC9 */ + 1255, /* U+002CCA */ + 1255, /* U+002CCB */ + 1256, /* U+002CCC */ + 1256, /* U+002CCD */ + 1257, /* U+002CCE */ + 1257, /* U+002CCF */ + 1258, /* U+002CD0 */ + 1258, /* U+002CD1 */ + 1259, /* U+002CD2 */ + 1259, /* U+002CD3 */ + 1260, /* U+002CD4 */ + 1260, /* U+002CD5 */ + 1261, /* U+002CD6 */ + 1261, /* U+002CD7 */ + 1262, /* U+002CD8 */ + 1262, /* U+002CD9 */ + 1263, /* U+002CDA */ + 1263, /* U+002CDB */ + 1264, /* U+002CDC */ + 1264, /* U+002CDD */ + 1265, /* U+002CDE */ + 1265, /* U+002CDF */ + 1266, /* U+002CE0 */ + 1266, /* U+002CE1 */ + 1267, /* U+002CE2 */ + 1267, /* U+002CE3 */ + 0, /* U+002CE4 */ + 0, /* U+002CE5 */ + 0, /* U+002CE6 */ + 0, /* U+002CE7 */ + 0, /* U+002CE8 */ + 0, /* U+002CE9 */ + 0, /* U+002CEA */ + 1268, /* U+002CEB */ + 1268, /* U+002CEC */ + 1269, /* U+002CED */ + 1269, /* U+002CEE */ + 0, /* U+002CEF */ + 0, /* U+002CF0 */ + 0, /* U+002CF1 */ + 1270, /* U+002CF2 */ + 1270, /* U+002CF3 */ + 0, /* U+002CF4 */ + 0, /* U+002CF5 */ + 0, /* U+002CF6 */ + 0, /* U+002CF7 */ + 0, /* U+002CF8 */ + 0, /* U+002CF9 */ + 0, /* U+002CFA */ + 0, /* U+002CFB */ + 0, /* U+002CFC */ + 0, /* U+002CFD */ + 0, /* U+002CFE */ + 0, /* U+002CFF */ + 607, /* U+002D00 */ + 608, /* U+002D01 */ + 609, /* U+002D02 */ + 610, /* U+002D03 */ + 611, /* U+002D04 */ + 612, /* U+002D05 */ + 613, /* U+002D06 */ + 614, /* U+002D07 */ + 615, /* U+002D08 */ + 616, /* U+002D09 */ + 617, /* U+002D0A */ + 618, /* U+002D0B */ + 619, /* U+002D0C */ + 620, /* U+002D0D */ + 621, /* U+002D0E */ + 622, /* U+002D0F */ + 623, /* U+002D10 */ + 624, /* U+002D11 */ + 625, /* U+002D12 */ + 626, /* U+002D13 */ + 627, /* U+002D14 */ + 628, /* U+002D15 */ + 629, /* U+002D16 */ + 630, /* U+002D17 */ + 631, /* U+002D18 */ + 632, /* U+002D19 */ + 633, /* U+002D1A */ + 634, /* U+002D1B */ + 635, /* U+002D1C */ + 636, /* U+002D1D */ + 637, /* U+002D1E */ + 638, /* U+002D1F */ + 639, /* U+002D20 */ + 640, /* U+002D21 */ + 641, /* U+002D22 */ + 642, /* U+002D23 */ + 643, /* U+002D24 */ + 644, /* U+002D25 */ + 0, /* U+002D26 */ + 645, /* U+002D27 */ + 0, /* U+002D28 */ + 0, /* U+002D29 */ + 0, /* U+002D2A */ + 0, /* U+002D2B */ + 0, /* U+002D2C */ + 646, /* U+002D2D */ + 1271, /* U+00A640 */ + 1271, /* U+00A641 */ + 1272, /* U+00A642 */ + 1272, /* U+00A643 */ + 1273, /* U+00A644 */ + 1273, /* U+00A645 */ + 1274, /* U+00A646 */ + 1274, /* U+00A647 */ + 1275, /* U+00A648 */ + 1275, /* U+00A649 */ + 1276, /* U+00A64A */ + 1276, /* U+00A64B */ + 1277, /* U+00A64C */ + 1277, /* U+00A64D */ + 1278, /* U+00A64E */ + 1278, /* U+00A64F */ + 1279, /* U+00A650 */ + 1279, /* U+00A651 */ + 1280, /* U+00A652 */ + 1280, /* U+00A653 */ + 1281, /* U+00A654 */ + 1281, /* U+00A655 */ + 1282, /* U+00A656 */ + 1282, /* U+00A657 */ + 1283, /* U+00A658 */ + 1283, /* U+00A659 */ + 1284, /* U+00A65A */ + 1284, /* U+00A65B */ + 1285, /* U+00A65C */ + 1285, /* U+00A65D */ + 1286, /* U+00A65E */ + 1286, /* U+00A65F */ + 1287, /* U+00A660 */ + 1287, /* U+00A661 */ + 1288, /* U+00A662 */ + 1288, /* U+00A663 */ + 1289, /* U+00A664 */ + 1289, /* U+00A665 */ + 1290, /* U+00A666 */ + 1290, /* U+00A667 */ + 1291, /* U+00A668 */ + 1291, /* U+00A669 */ + 1292, /* U+00A66A */ + 1292, /* U+00A66B */ + 1293, /* U+00A66C */ + 1293, /* U+00A66D */ + 0, /* U+00A66E */ + 0, /* U+00A66F */ + 0, /* U+00A670 */ + 0, /* U+00A671 */ + 0, /* U+00A672 */ + 0, /* U+00A673 */ + 0, /* U+00A674 */ + 0, /* U+00A675 */ + 0, /* U+00A676 */ + 0, /* U+00A677 */ + 0, /* U+00A678 */ + 0, /* U+00A679 */ + 0, /* U+00A67A */ + 0, /* U+00A67B */ + 0, /* U+00A67C */ + 0, /* U+00A67D */ + 0, /* U+00A67E */ + 0, /* U+00A67F */ + 1294, /* U+00A680 */ + 1294, /* U+00A681 */ + 1295, /* U+00A682 */ + 1295, /* U+00A683 */ + 1296, /* U+00A684 */ + 1296, /* U+00A685 */ + 1297, /* U+00A686 */ + 1297, /* U+00A687 */ + 1298, /* U+00A688 */ + 1298, /* U+00A689 */ + 1299, /* U+00A68A */ + 1299, /* U+00A68B */ + 1300, /* U+00A68C */ + 1300, /* U+00A68D */ + 1301, /* U+00A68E */ + 1301, /* U+00A68F */ + 1302, /* U+00A690 */ + 1302, /* U+00A691 */ + 1303, /* U+00A692 */ + 1303, /* U+00A693 */ + 1304, /* U+00A694 */ + 1304, /* U+00A695 */ + 1305, /* U+00A696 */ + 1305, /* U+00A697 */ + 1306, /* U+00A698 */ + 1306, /* U+00A699 */ + 1307, /* U+00A69A */ + 1307, /* U+00A69B */ + 0, /* U+00A69C */ + 0, /* U+00A69D */ + 0, /* U+00A69E */ + 0, /* U+00A69F */ + 0, /* U+00A6A0 */ + 0, /* U+00A6A1 */ + 0, /* U+00A6A2 */ + 0, /* U+00A6A3 */ + 0, /* U+00A6A4 */ + 0, /* U+00A6A5 */ + 0, /* U+00A6A6 */ + 0, /* U+00A6A7 */ + 0, /* U+00A6A8 */ + 0, /* U+00A6A9 */ + 0, /* U+00A6AA */ + 0, /* U+00A6AB */ + 0, /* U+00A6AC */ + 0, /* U+00A6AD */ + 0, /* U+00A6AE */ + 0, /* U+00A6AF */ + 0, /* U+00A6B0 */ + 0, /* U+00A6B1 */ + 0, /* U+00A6B2 */ + 0, /* U+00A6B3 */ + 0, /* U+00A6B4 */ + 0, /* U+00A6B5 */ + 0, /* U+00A6B6 */ + 0, /* U+00A6B7 */ + 0, /* U+00A6B8 */ + 0, /* U+00A6B9 */ + 0, /* U+00A6BA */ + 0, /* U+00A6BB */ + 0, /* U+00A6BC */ + 0, /* U+00A6BD */ + 0, /* U+00A6BE */ + 0, /* U+00A6BF */ + 0, /* U+00A6C0 */ + 0, /* U+00A6C1 */ + 0, /* U+00A6C2 */ + 0, /* U+00A6C3 */ + 0, /* U+00A6C4 */ + 0, /* U+00A6C5 */ + 0, /* U+00A6C6 */ + 0, /* U+00A6C7 */ + 0, /* U+00A6C8 */ + 0, /* U+00A6C9 */ + 0, /* U+00A6CA */ + 0, /* U+00A6CB */ + 0, /* U+00A6CC */ + 0, /* U+00A6CD */ + 0, /* U+00A6CE */ + 0, /* U+00A6CF */ + 0, /* U+00A6D0 */ + 0, /* U+00A6D1 */ + 0, /* U+00A6D2 */ + 0, /* U+00A6D3 */ + 0, /* U+00A6D4 */ + 0, /* U+00A6D5 */ + 0, /* U+00A6D6 */ + 0, /* U+00A6D7 */ + 0, /* U+00A6D8 */ + 0, /* U+00A6D9 */ + 0, /* U+00A6DA */ + 0, /* U+00A6DB */ + 0, /* U+00A6DC */ + 0, /* U+00A6DD */ + 0, /* U+00A6DE */ + 0, /* U+00A6DF */ + 0, /* U+00A6E0 */ + 0, /* U+00A6E1 */ + 0, /* U+00A6E2 */ + 0, /* U+00A6E3 */ + 0, /* U+00A6E4 */ + 0, /* U+00A6E5 */ + 0, /* U+00A6E6 */ + 0, /* U+00A6E7 */ + 0, /* U+00A6E8 */ + 0, /* U+00A6E9 */ + 0, /* U+00A6EA */ + 0, /* U+00A6EB */ + 0, /* U+00A6EC */ + 0, /* U+00A6ED */ + 0, /* U+00A6EE */ + 0, /* U+00A6EF */ + 0, /* U+00A6F0 */ + 0, /* U+00A6F1 */ + 0, /* U+00A6F2 */ + 0, /* U+00A6F3 */ + 0, /* U+00A6F4 */ + 0, /* U+00A6F5 */ + 0, /* U+00A6F6 */ + 0, /* U+00A6F7 */ + 0, /* U+00A6F8 */ + 0, /* U+00A6F9 */ + 0, /* U+00A6FA */ + 0, /* U+00A6FB */ + 0, /* U+00A6FC */ + 0, /* U+00A6FD */ + 0, /* U+00A6FE */ + 0, /* U+00A6FF */ + 0, /* U+00A700 */ + 0, /* U+00A701 */ + 0, /* U+00A702 */ + 0, /* U+00A703 */ + 0, /* U+00A704 */ + 0, /* U+00A705 */ + 0, /* U+00A706 */ + 0, /* U+00A707 */ + 0, /* U+00A708 */ + 0, /* U+00A709 */ + 0, /* U+00A70A */ + 0, /* U+00A70B */ + 0, /* U+00A70C */ + 0, /* U+00A70D */ + 0, /* U+00A70E */ + 0, /* U+00A70F */ + 0, /* U+00A710 */ + 0, /* U+00A711 */ + 0, /* U+00A712 */ + 0, /* U+00A713 */ + 0, /* U+00A714 */ + 0, /* U+00A715 */ + 0, /* U+00A716 */ + 0, /* U+00A717 */ + 0, /* U+00A718 */ + 0, /* U+00A719 */ + 0, /* U+00A71A */ + 0, /* U+00A71B */ + 0, /* U+00A71C */ + 0, /* U+00A71D */ + 0, /* U+00A71E */ + 0, /* U+00A71F */ + 0, /* U+00A720 */ + 0, /* U+00A721 */ + 1308, /* U+00A722 */ + 1308, /* U+00A723 */ + 1309, /* U+00A724 */ + 1309, /* U+00A725 */ + 1310, /* U+00A726 */ + 1310, /* U+00A727 */ + 1311, /* U+00A728 */ + 1311, /* U+00A729 */ + 1312, /* U+00A72A */ + 1312, /* U+00A72B */ + 1313, /* U+00A72C */ + 1313, /* U+00A72D */ + 1314, /* U+00A72E */ + 1314, /* U+00A72F */ + 0, /* U+00A730 */ + 0, /* U+00A731 */ + 1315, /* U+00A732 */ + 1315, /* U+00A733 */ + 1316, /* U+00A734 */ + 1316, /* U+00A735 */ + 1317, /* U+00A736 */ + 1317, /* U+00A737 */ + 1318, /* U+00A738 */ + 1318, /* U+00A739 */ + 1319, /* U+00A73A */ + 1319, /* U+00A73B */ + 1320, /* U+00A73C */ + 1320, /* U+00A73D */ + 1321, /* U+00A73E */ + 1321, /* U+00A73F */ + 1322, /* U+00A740 */ + 1322, /* U+00A741 */ + 1323, /* U+00A742 */ + 1323, /* U+00A743 */ + 1324, /* U+00A744 */ + 1324, /* U+00A745 */ + 1325, /* U+00A746 */ + 1325, /* U+00A747 */ + 1326, /* U+00A748 */ + 1326, /* U+00A749 */ + 1327, /* U+00A74A */ + 1327, /* U+00A74B */ + 1328, /* U+00A74C */ + 1328, /* U+00A74D */ + 1329, /* U+00A74E */ + 1329, /* U+00A74F */ + 1330, /* U+00A750 */ + 1330, /* U+00A751 */ + 1331, /* U+00A752 */ + 1331, /* U+00A753 */ + 1332, /* U+00A754 */ + 1332, /* U+00A755 */ + 1333, /* U+00A756 */ + 1333, /* U+00A757 */ + 1334, /* U+00A758 */ + 1334, /* U+00A759 */ + 1335, /* U+00A75A */ + 1335, /* U+00A75B */ + 1336, /* U+00A75C */ + 1336, /* U+00A75D */ + 1337, /* U+00A75E */ + 1337, /* U+00A75F */ + 1338, /* U+00A760 */ + 1338, /* U+00A761 */ + 1339, /* U+00A762 */ + 1339, /* U+00A763 */ + 1340, /* U+00A764 */ + 1340, /* U+00A765 */ + 1341, /* U+00A766 */ + 1341, /* U+00A767 */ + 1342, /* U+00A768 */ + 1342, /* U+00A769 */ + 1343, /* U+00A76A */ + 1343, /* U+00A76B */ + 1344, /* U+00A76C */ + 1344, /* U+00A76D */ + 1345, /* U+00A76E */ + 1345, /* U+00A76F */ + 0, /* U+00A770 */ + 0, /* U+00A771 */ + 0, /* U+00A772 */ + 0, /* U+00A773 */ + 0, /* U+00A774 */ + 0, /* U+00A775 */ + 0, /* U+00A776 */ + 0, /* U+00A777 */ + 0, /* U+00A778 */ + 1346, /* U+00A779 */ + 1346, /* U+00A77A */ + 1347, /* U+00A77B */ + 1347, /* U+00A77C */ + 835, /* U+00A77D */ + 1348, /* U+00A77E */ + 1348, /* U+00A77F */ + 1349, /* U+00A780 */ + 1349, /* U+00A781 */ + 1350, /* U+00A782 */ + 1350, /* U+00A783 */ + 1351, /* U+00A784 */ + 1351, /* U+00A785 */ + 1352, /* U+00A786 */ + 1352, /* U+00A787 */ + 0, /* U+00A788 */ + 0, /* U+00A789 */ + 0, /* U+00A78A */ + 1353, /* U+00A78B */ + 1353, /* U+00A78C */ + 340, /* U+00A78D */ + 0, /* U+00A78E */ + 0, /* U+00A78F */ + 1354, /* U+00A790 */ + 1354, /* U+00A791 */ + 1355, /* U+00A792 */ + 1355, /* U+00A793 */ + 1356, /* U+00A794 */ + 0, /* U+00A795 */ + 1357, /* U+00A796 */ + 1357, /* U+00A797 */ + 1358, /* U+00A798 */ + 1358, /* U+00A799 */ + 1359, /* U+00A79A */ + 1359, /* U+00A79B */ + 1360, /* U+00A79C */ + 1360, /* U+00A79D */ + 1361, /* U+00A79E */ + 1361, /* U+00A79F */ + 1362, /* U+00A7A0 */ + 1362, /* U+00A7A1 */ + 1363, /* U+00A7A2 */ + 1363, /* U+00A7A3 */ + 1364, /* U+00A7A4 */ + 1364, /* U+00A7A5 */ + 1365, /* U+00A7A6 */ + 1365, /* U+00A7A7 */ + 1366, /* U+00A7A8 */ + 1366, /* U+00A7A9 */ + 341, /* U+00A7AA */ + 337, /* U+00A7AB */ + 338, /* U+00A7AC */ + 344, /* U+00A7AD */ + 342, /* U+00A7AE */ + 0, /* U+00A7AF */ + 350, /* U+00A7B0 */ + 348, /* U+00A7B1 */ + 349, /* U+00A7B2 */ + 1367, /* U+00A7B3 */ + 1368, /* U+00A7B4 */ + 1368, /* U+00A7B5 */ + 1369, /* U+00A7B6 */ + 1369, /* U+00A7B7 */ + 1370, /* U+00A7B8 */ + 1370, /* U+00A7B9 */ + 1371, /* U+00A7BA */ + 1371, /* U+00A7BB */ + 1372, /* U+00A7BC */ + 1372, /* U+00A7BD */ + 1373, /* U+00A7BE */ + 1373, /* U+00A7BF */ + 1374, /* U+00A7C0 */ + 1374, /* U+00A7C1 */ + 1375, /* U+00A7C2 */ + 1375, /* U+00A7C3 */ + 1356, /* U+00A7C4 */ + 347, /* U+00A7C5 */ + 837, /* U+00A7C6 */ + 1376, /* U+00A7C7 */ + 1376, /* U+00A7C8 */ + 1377, /* U+00A7C9 */ + 1377, /* U+00A7CA */ + 339, /* U+00A7CB */ + 1378, /* U+00A7CC */ + 1378, /* U+00A7CD */ + 0, /* U+00A7CE */ + 0, /* U+00A7CF */ + 1379, /* U+00A7D0 */ + 1379, /* U+00A7D1 */ + 0, /* U+00A7D2 */ + 0, /* U+00A7D3 */ + 0, /* U+00A7D4 */ + 0, /* U+00A7D5 */ + 1380, /* U+00A7D6 */ + 1380, /* U+00A7D7 */ + 1381, /* U+00A7D8 */ + 1381, /* U+00A7D9 */ + 1382, /* U+00A7DA */ + 1382, /* U+00A7DB */ + 247, /* U+00A7DC */ + 0, /* U+00A7DD */ + 0, /* U+00A7DE */ + 0, /* U+00A7DF */ + 0, /* U+00A7E0 */ + 0, /* U+00A7E1 */ + 0, /* U+00A7E2 */ + 0, /* U+00A7E3 */ + 0, /* U+00A7E4 */ + 0, /* U+00A7E5 */ + 0, /* U+00A7E6 */ + 0, /* U+00A7E7 */ + 0, /* U+00A7E8 */ + 0, /* U+00A7E9 */ + 0, /* U+00A7EA */ + 0, /* U+00A7EB */ + 0, /* U+00A7EC */ + 0, /* U+00A7ED */ + 0, /* U+00A7EE */ + 0, /* U+00A7EF */ + 0, /* U+00A7F0 */ + 0, /* U+00A7F1 */ + 0, /* U+00A7F2 */ + 0, /* U+00A7F3 */ + 0, /* U+00A7F4 */ + 1383, /* U+00A7F5 */ + 1383, /* U+00A7F6 */ + 1367, /* U+00AB53 */ + 0, /* U+00AB54 */ + 0, /* U+00AB55 */ + 0, /* U+00AB56 */ + 0, /* U+00AB57 */ + 0, /* U+00AB58 */ + 0, /* U+00AB59 */ + 0, /* U+00AB5A */ + 0, /* U+00AB5B */ + 0, /* U+00AB5C */ + 0, /* U+00AB5D */ + 0, /* U+00AB5E */ + 0, /* U+00AB5F */ + 0, /* U+00AB60 */ + 0, /* U+00AB61 */ + 0, /* U+00AB62 */ + 0, /* U+00AB63 */ + 0, /* U+00AB64 */ + 0, /* U+00AB65 */ + 0, /* U+00AB66 */ + 0, /* U+00AB67 */ + 0, /* U+00AB68 */ + 0, /* U+00AB69 */ + 0, /* U+00AB6A */ + 0, /* U+00AB6B */ + 0, /* U+00AB6C */ + 0, /* U+00AB6D */ + 0, /* U+00AB6E */ + 0, /* U+00AB6F */ + 693, /* U+00AB70 */ + 694, /* U+00AB71 */ + 695, /* U+00AB72 */ + 696, /* U+00AB73 */ + 697, /* U+00AB74 */ + 698, /* U+00AB75 */ + 699, /* U+00AB76 */ + 700, /* U+00AB77 */ + 701, /* U+00AB78 */ + 702, /* U+00AB79 */ + 703, /* U+00AB7A */ + 704, /* U+00AB7B */ + 705, /* U+00AB7C */ + 706, /* U+00AB7D */ + 707, /* U+00AB7E */ + 708, /* U+00AB7F */ + 709, /* U+00AB80 */ + 710, /* U+00AB81 */ + 711, /* U+00AB82 */ + 712, /* U+00AB83 */ + 713, /* U+00AB84 */ + 714, /* U+00AB85 */ + 715, /* U+00AB86 */ + 716, /* U+00AB87 */ + 717, /* U+00AB88 */ + 718, /* U+00AB89 */ + 719, /* U+00AB8A */ + 720, /* U+00AB8B */ + 721, /* U+00AB8C */ + 722, /* U+00AB8D */ + 723, /* U+00AB8E */ + 724, /* U+00AB8F */ + 725, /* U+00AB90 */ + 726, /* U+00AB91 */ + 727, /* U+00AB92 */ + 728, /* U+00AB93 */ + 729, /* U+00AB94 */ + 730, /* U+00AB95 */ + 731, /* U+00AB96 */ + 732, /* U+00AB97 */ + 733, /* U+00AB98 */ + 734, /* U+00AB99 */ + 735, /* U+00AB9A */ + 736, /* U+00AB9B */ + 737, /* U+00AB9C */ + 738, /* U+00AB9D */ + 739, /* U+00AB9E */ + 740, /* U+00AB9F */ + 741, /* U+00ABA0 */ + 742, /* U+00ABA1 */ + 743, /* U+00ABA2 */ + 744, /* U+00ABA3 */ + 745, /* U+00ABA4 */ + 746, /* U+00ABA5 */ + 747, /* U+00ABA6 */ + 748, /* U+00ABA7 */ + 749, /* U+00ABA8 */ + 750, /* U+00ABA9 */ + 751, /* U+00ABAA */ + 752, /* U+00ABAB */ + 753, /* U+00ABAC */ + 754, /* U+00ABAD */ + 755, /* U+00ABAE */ + 756, /* U+00ABAF */ + 757, /* U+00ABB0 */ + 758, /* U+00ABB1 */ + 759, /* U+00ABB2 */ + 760, /* U+00ABB3 */ + 761, /* U+00ABB4 */ + 762, /* U+00ABB5 */ + 763, /* U+00ABB6 */ + 764, /* U+00ABB7 */ + 765, /* U+00ABB8 */ + 766, /* U+00ABB9 */ + 767, /* U+00ABBA */ + 768, /* U+00ABBB */ + 769, /* U+00ABBC */ + 770, /* U+00ABBD */ + 771, /* U+00ABBE */ + 772, /* U+00ABBF */ + 1384, /* U+00FB00 */ + 1385, /* U+00FB01 */ + 1386, /* U+00FB02 */ + 1387, /* U+00FB03 */ + 1388, /* U+00FB04 */ + 1389, /* U+00FB05 */ + 1390, /* U+00FB06 */ + 0, /* U+00FB07 */ + 0, /* U+00FB08 */ + 0, /* U+00FB09 */ + 0, /* U+00FB0A */ + 0, /* U+00FB0B */ + 0, /* U+00FB0C */ + 0, /* U+00FB0D */ + 0, /* U+00FB0E */ + 0, /* U+00FB0F */ + 0, /* U+00FB10 */ + 0, /* U+00FB11 */ + 0, /* U+00FB12 */ + 1391, /* U+00FB13 */ + 1392, /* U+00FB14 */ + 1393, /* U+00FB15 */ + 1394, /* U+00FB16 */ + 1395, /* U+00FB17 */ + 1396, /* U+00FF21 */ + 1397, /* U+00FF22 */ + 1398, /* U+00FF23 */ + 1399, /* U+00FF24 */ + 1400, /* U+00FF25 */ + 1401, /* U+00FF26 */ + 1402, /* U+00FF27 */ + 1403, /* U+00FF28 */ + 1404, /* U+00FF29 */ + 1405, /* U+00FF2A */ + 1406, /* U+00FF2B */ + 1407, /* U+00FF2C */ + 1408, /* U+00FF2D */ + 1409, /* U+00FF2E */ + 1410, /* U+00FF2F */ + 1411, /* U+00FF30 */ + 1412, /* U+00FF31 */ + 1413, /* U+00FF32 */ + 1414, /* U+00FF33 */ + 1415, /* U+00FF34 */ + 1416, /* U+00FF35 */ + 1417, /* U+00FF36 */ + 1418, /* U+00FF37 */ + 1419, /* U+00FF38 */ + 1420, /* U+00FF39 */ + 1421, /* U+00FF3A */ + 0, /* U+00FF3B */ + 0, /* U+00FF3C */ + 0, /* U+00FF3D */ + 0, /* U+00FF3E */ + 0, /* U+00FF3F */ + 0, /* U+00FF40 */ + 1396, /* U+00FF41 */ + 1397, /* U+00FF42 */ + 1398, /* U+00FF43 */ + 1399, /* U+00FF44 */ + 1400, /* U+00FF45 */ + 1401, /* U+00FF46 */ + 1402, /* U+00FF47 */ + 1403, /* U+00FF48 */ + 1404, /* U+00FF49 */ + 1405, /* U+00FF4A */ + 1406, /* U+00FF4B */ + 1407, /* U+00FF4C */ + 1408, /* U+00FF4D */ + 1409, /* U+00FF4E */ + 1410, /* U+00FF4F */ + 1411, /* U+00FF50 */ + 1412, /* U+00FF51 */ + 1413, /* U+00FF52 */ + 1414, /* U+00FF53 */ + 1415, /* U+00FF54 */ + 1416, /* U+00FF55 */ + 1417, /* U+00FF56 */ + 1418, /* U+00FF57 */ + 1419, /* U+00FF58 */ + 1420, /* U+00FF59 */ + 1421, /* U+00FF5A */ + 1422, /* U+010400 */ + 1423, /* U+010401 */ + 1424, /* U+010402 */ + 1425, /* U+010403 */ + 1426, /* U+010404 */ + 1427, /* U+010405 */ + 1428, /* U+010406 */ + 1429, /* U+010407 */ + 1430, /* U+010408 */ + 1431, /* U+010409 */ + 1432, /* U+01040A */ + 1433, /* U+01040B */ + 1434, /* U+01040C */ + 1435, /* U+01040D */ + 1436, /* U+01040E */ + 1437, /* U+01040F */ + 1438, /* U+010410 */ + 1439, /* U+010411 */ + 1440, /* U+010412 */ + 1441, /* U+010413 */ + 1442, /* U+010414 */ + 1443, /* U+010415 */ + 1444, /* U+010416 */ + 1445, /* U+010417 */ + 1446, /* U+010418 */ + 1447, /* U+010419 */ + 1448, /* U+01041A */ + 1449, /* U+01041B */ + 1450, /* U+01041C */ + 1451, /* U+01041D */ + 1452, /* U+01041E */ + 1453, /* U+01041F */ + 1454, /* U+010420 */ + 1455, /* U+010421 */ + 1456, /* U+010422 */ + 1457, /* U+010423 */ + 1458, /* U+010424 */ + 1459, /* U+010425 */ + 1460, /* U+010426 */ + 1461, /* U+010427 */ + 1422, /* U+010428 */ + 1423, /* U+010429 */ + 1424, /* U+01042A */ + 1425, /* U+01042B */ + 1426, /* U+01042C */ + 1427, /* U+01042D */ + 1428, /* U+01042E */ + 1429, /* U+01042F */ + 1430, /* U+010430 */ + 1431, /* U+010431 */ + 1432, /* U+010432 */ + 1433, /* U+010433 */ + 1434, /* U+010434 */ + 1435, /* U+010435 */ + 1436, /* U+010436 */ + 1437, /* U+010437 */ + 1438, /* U+010438 */ + 1439, /* U+010439 */ + 1440, /* U+01043A */ + 1441, /* U+01043B */ + 1442, /* U+01043C */ + 1443, /* U+01043D */ + 1444, /* U+01043E */ + 1445, /* U+01043F */ + 1446, /* U+010440 */ + 1447, /* U+010441 */ + 1448, /* U+010442 */ + 1449, /* U+010443 */ + 1450, /* U+010444 */ + 1451, /* U+010445 */ + 1452, /* U+010446 */ + 1453, /* U+010447 */ + 1454, /* U+010448 */ + 1455, /* U+010449 */ + 1456, /* U+01044A */ + 1457, /* U+01044B */ + 1458, /* U+01044C */ + 1459, /* U+01044D */ + 1460, /* U+01044E */ + 1461, /* U+01044F */ + 0, /* U+010450 */ + 0, /* U+010451 */ + 0, /* U+010452 */ + 0, /* U+010453 */ + 0, /* U+010454 */ + 0, /* U+010455 */ + 0, /* U+010456 */ + 0, /* U+010457 */ + 0, /* U+010458 */ + 0, /* U+010459 */ + 0, /* U+01045A */ + 0, /* U+01045B */ + 0, /* U+01045C */ + 0, /* U+01045D */ + 0, /* U+01045E */ + 0, /* U+01045F */ + 0, /* U+010460 */ + 0, /* U+010461 */ + 0, /* U+010462 */ + 0, /* U+010463 */ + 0, /* U+010464 */ + 0, /* U+010465 */ + 0, /* U+010466 */ + 0, /* U+010467 */ + 0, /* U+010468 */ + 0, /* U+010469 */ + 0, /* U+01046A */ + 0, /* U+01046B */ + 0, /* U+01046C */ + 0, /* U+01046D */ + 0, /* U+01046E */ + 0, /* U+01046F */ + 0, /* U+010470 */ + 0, /* U+010471 */ + 0, /* U+010472 */ + 0, /* U+010473 */ + 0, /* U+010474 */ + 0, /* U+010475 */ + 0, /* U+010476 */ + 0, /* U+010477 */ + 0, /* U+010478 */ + 0, /* U+010479 */ + 0, /* U+01047A */ + 0, /* U+01047B */ + 0, /* U+01047C */ + 0, /* U+01047D */ + 0, /* U+01047E */ + 0, /* U+01047F */ + 0, /* U+010480 */ + 0, /* U+010481 */ + 0, /* U+010482 */ + 0, /* U+010483 */ + 0, /* U+010484 */ + 0, /* U+010485 */ + 0, /* U+010486 */ + 0, /* U+010487 */ + 0, /* U+010488 */ + 0, /* U+010489 */ + 0, /* U+01048A */ + 0, /* U+01048B */ + 0, /* U+01048C */ + 0, /* U+01048D */ + 0, /* U+01048E */ + 0, /* U+01048F */ + 0, /* U+010490 */ + 0, /* U+010491 */ + 0, /* U+010492 */ + 0, /* U+010493 */ + 0, /* U+010494 */ + 0, /* U+010495 */ + 0, /* U+010496 */ + 0, /* U+010497 */ + 0, /* U+010498 */ + 0, /* U+010499 */ + 0, /* U+01049A */ + 0, /* U+01049B */ + 0, /* U+01049C */ + 0, /* U+01049D */ + 0, /* U+01049E */ + 0, /* U+01049F */ + 0, /* U+0104A0 */ + 0, /* U+0104A1 */ + 0, /* U+0104A2 */ + 0, /* U+0104A3 */ + 0, /* U+0104A4 */ + 0, /* U+0104A5 */ + 0, /* U+0104A6 */ + 0, /* U+0104A7 */ + 0, /* U+0104A8 */ + 0, /* U+0104A9 */ + 0, /* U+0104AA */ + 0, /* U+0104AB */ + 0, /* U+0104AC */ + 0, /* U+0104AD */ + 0, /* U+0104AE */ + 0, /* U+0104AF */ + 1462, /* U+0104B0 */ + 1463, /* U+0104B1 */ + 1464, /* U+0104B2 */ + 1465, /* U+0104B3 */ + 1466, /* U+0104B4 */ + 1467, /* U+0104B5 */ + 1468, /* U+0104B6 */ + 1469, /* U+0104B7 */ + 1470, /* U+0104B8 */ + 1471, /* U+0104B9 */ + 1472, /* U+0104BA */ + 1473, /* U+0104BB */ + 1474, /* U+0104BC */ + 1475, /* U+0104BD */ + 1476, /* U+0104BE */ + 1477, /* U+0104BF */ + 1478, /* U+0104C0 */ + 1479, /* U+0104C1 */ + 1480, /* U+0104C2 */ + 1481, /* U+0104C3 */ + 1482, /* U+0104C4 */ + 1483, /* U+0104C5 */ + 1484, /* U+0104C6 */ + 1485, /* U+0104C7 */ + 1486, /* U+0104C8 */ + 1487, /* U+0104C9 */ + 1488, /* U+0104CA */ + 1489, /* U+0104CB */ + 1490, /* U+0104CC */ + 1491, /* U+0104CD */ + 1492, /* U+0104CE */ + 1493, /* U+0104CF */ + 1494, /* U+0104D0 */ + 1495, /* U+0104D1 */ + 1496, /* U+0104D2 */ + 1497, /* U+0104D3 */ + 0, /* U+0104D4 */ + 0, /* U+0104D5 */ + 0, /* U+0104D6 */ + 0, /* U+0104D7 */ + 1462, /* U+0104D8 */ + 1463, /* U+0104D9 */ + 1464, /* U+0104DA */ + 1465, /* U+0104DB */ + 1466, /* U+0104DC */ + 1467, /* U+0104DD */ + 1468, /* U+0104DE */ + 1469, /* U+0104DF */ + 1470, /* U+0104E0 */ + 1471, /* U+0104E1 */ + 1472, /* U+0104E2 */ + 1473, /* U+0104E3 */ + 1474, /* U+0104E4 */ + 1475, /* U+0104E5 */ + 1476, /* U+0104E6 */ + 1477, /* U+0104E7 */ + 1478, /* U+0104E8 */ + 1479, /* U+0104E9 */ + 1480, /* U+0104EA */ + 1481, /* U+0104EB */ + 1482, /* U+0104EC */ + 1483, /* U+0104ED */ + 1484, /* U+0104EE */ + 1485, /* U+0104EF */ + 1486, /* U+0104F0 */ + 1487, /* U+0104F1 */ + 1488, /* U+0104F2 */ + 1489, /* U+0104F3 */ + 1490, /* U+0104F4 */ + 1491, /* U+0104F5 */ + 1492, /* U+0104F6 */ + 1493, /* U+0104F7 */ + 1494, /* U+0104F8 */ + 1495, /* U+0104F9 */ + 1496, /* U+0104FA */ + 1497, /* U+0104FB */ + 0, /* U+0104FC */ + 0, /* U+0104FD */ + 0, /* U+0104FE */ + 0, /* U+0104FF */ + 0, /* U+010500 */ + 0, /* U+010501 */ + 0, /* U+010502 */ + 0, /* U+010503 */ + 0, /* U+010504 */ + 0, /* U+010505 */ + 0, /* U+010506 */ + 0, /* U+010507 */ + 0, /* U+010508 */ + 0, /* U+010509 */ + 0, /* U+01050A */ + 0, /* U+01050B */ + 0, /* U+01050C */ + 0, /* U+01050D */ + 0, /* U+01050E */ + 0, /* U+01050F */ + 0, /* U+010510 */ + 0, /* U+010511 */ + 0, /* U+010512 */ + 0, /* U+010513 */ + 0, /* U+010514 */ + 0, /* U+010515 */ + 0, /* U+010516 */ + 0, /* U+010517 */ + 0, /* U+010518 */ + 0, /* U+010519 */ + 0, /* U+01051A */ + 0, /* U+01051B */ + 0, /* U+01051C */ + 0, /* U+01051D */ + 0, /* U+01051E */ + 0, /* U+01051F */ + 0, /* U+010520 */ + 0, /* U+010521 */ + 0, /* U+010522 */ + 0, /* U+010523 */ + 0, /* U+010524 */ + 0, /* U+010525 */ + 0, /* U+010526 */ + 0, /* U+010527 */ + 0, /* U+010528 */ + 0, /* U+010529 */ + 0, /* U+01052A */ + 0, /* U+01052B */ + 0, /* U+01052C */ + 0, /* U+01052D */ + 0, /* U+01052E */ + 0, /* U+01052F */ + 0, /* U+010530 */ + 0, /* U+010531 */ + 0, /* U+010532 */ + 0, /* U+010533 */ + 0, /* U+010534 */ + 0, /* U+010535 */ + 0, /* U+010536 */ + 0, /* U+010537 */ + 0, /* U+010538 */ + 0, /* U+010539 */ + 0, /* U+01053A */ + 0, /* U+01053B */ + 0, /* U+01053C */ + 0, /* U+01053D */ + 0, /* U+01053E */ + 0, /* U+01053F */ + 0, /* U+010540 */ + 0, /* U+010541 */ + 0, /* U+010542 */ + 0, /* U+010543 */ + 0, /* U+010544 */ + 0, /* U+010545 */ + 0, /* U+010546 */ + 0, /* U+010547 */ + 0, /* U+010548 */ + 0, /* U+010549 */ + 0, /* U+01054A */ + 0, /* U+01054B */ + 0, /* U+01054C */ + 0, /* U+01054D */ + 0, /* U+01054E */ + 0, /* U+01054F */ + 0, /* U+010550 */ + 0, /* U+010551 */ + 0, /* U+010552 */ + 0, /* U+010553 */ + 0, /* U+010554 */ + 0, /* U+010555 */ + 0, /* U+010556 */ + 0, /* U+010557 */ + 0, /* U+010558 */ + 0, /* U+010559 */ + 0, /* U+01055A */ + 0, /* U+01055B */ + 0, /* U+01055C */ + 0, /* U+01055D */ + 0, /* U+01055E */ + 0, /* U+01055F */ + 0, /* U+010560 */ + 0, /* U+010561 */ + 0, /* U+010562 */ + 0, /* U+010563 */ + 0, /* U+010564 */ + 0, /* U+010565 */ + 0, /* U+010566 */ + 0, /* U+010567 */ + 0, /* U+010568 */ + 0, /* U+010569 */ + 0, /* U+01056A */ + 0, /* U+01056B */ + 0, /* U+01056C */ + 0, /* U+01056D */ + 0, /* U+01056E */ + 0, /* U+01056F */ + 1498, /* U+010570 */ + 1499, /* U+010571 */ + 1500, /* U+010572 */ + 1501, /* U+010573 */ + 1502, /* U+010574 */ + 1503, /* U+010575 */ + 1504, /* U+010576 */ + 1505, /* U+010577 */ + 1506, /* U+010578 */ + 1507, /* U+010579 */ + 1508, /* U+01057A */ + 0, /* U+01057B */ + 1509, /* U+01057C */ + 1510, /* U+01057D */ + 1511, /* U+01057E */ + 1512, /* U+01057F */ + 1513, /* U+010580 */ + 1514, /* U+010581 */ + 1515, /* U+010582 */ + 1516, /* U+010583 */ + 1517, /* U+010584 */ + 1518, /* U+010585 */ + 1519, /* U+010586 */ + 1520, /* U+010587 */ + 1521, /* U+010588 */ + 1522, /* U+010589 */ + 1523, /* U+01058A */ + 0, /* U+01058B */ + 1524, /* U+01058C */ + 1525, /* U+01058D */ + 1526, /* U+01058E */ + 1527, /* U+01058F */ + 1528, /* U+010590 */ + 1529, /* U+010591 */ + 1530, /* U+010592 */ + 0, /* U+010593 */ + 1531, /* U+010594 */ + 1532, /* U+010595 */ + 0, /* U+010596 */ + 1498, /* U+010597 */ + 1499, /* U+010598 */ + 1500, /* U+010599 */ + 1501, /* U+01059A */ + 1502, /* U+01059B */ + 1503, /* U+01059C */ + 1504, /* U+01059D */ + 1505, /* U+01059E */ + 1506, /* U+01059F */ + 1507, /* U+0105A0 */ + 1508, /* U+0105A1 */ + 0, /* U+0105A2 */ + 1509, /* U+0105A3 */ + 1510, /* U+0105A4 */ + 1511, /* U+0105A5 */ + 1512, /* U+0105A6 */ + 1513, /* U+0105A7 */ + 1514, /* U+0105A8 */ + 1515, /* U+0105A9 */ + 1516, /* U+0105AA */ + 1517, /* U+0105AB */ + 1518, /* U+0105AC */ + 1519, /* U+0105AD */ + 1520, /* U+0105AE */ + 1521, /* U+0105AF */ + 1522, /* U+0105B0 */ + 1523, /* U+0105B1 */ + 0, /* U+0105B2 */ + 1524, /* U+0105B3 */ + 1525, /* U+0105B4 */ + 1526, /* U+0105B5 */ + 1527, /* U+0105B6 */ + 1528, /* U+0105B7 */ + 1529, /* U+0105B8 */ + 1530, /* U+0105B9 */ + 0, /* U+0105BA */ + 1531, /* U+0105BB */ + 1532, /* U+0105BC */ + 1533, /* U+010C80 */ + 1534, /* U+010C81 */ + 1535, /* U+010C82 */ + 1536, /* U+010C83 */ + 1537, /* U+010C84 */ + 1538, /* U+010C85 */ + 1539, /* U+010C86 */ + 1540, /* U+010C87 */ + 1541, /* U+010C88 */ + 1542, /* U+010C89 */ + 1543, /* U+010C8A */ + 1544, /* U+010C8B */ + 1545, /* U+010C8C */ + 1546, /* U+010C8D */ + 1547, /* U+010C8E */ + 1548, /* U+010C8F */ + 1549, /* U+010C90 */ + 1550, /* U+010C91 */ + 1551, /* U+010C92 */ + 1552, /* U+010C93 */ + 1553, /* U+010C94 */ + 1554, /* U+010C95 */ + 1555, /* U+010C96 */ + 1556, /* U+010C97 */ + 1557, /* U+010C98 */ + 1558, /* U+010C99 */ + 1559, /* U+010C9A */ + 1560, /* U+010C9B */ + 1561, /* U+010C9C */ + 1562, /* U+010C9D */ + 1563, /* U+010C9E */ + 1564, /* U+010C9F */ + 1565, /* U+010CA0 */ + 1566, /* U+010CA1 */ + 1567, /* U+010CA2 */ + 1568, /* U+010CA3 */ + 1569, /* U+010CA4 */ + 1570, /* U+010CA5 */ + 1571, /* U+010CA6 */ + 1572, /* U+010CA7 */ + 1573, /* U+010CA8 */ + 1574, /* U+010CA9 */ + 1575, /* U+010CAA */ + 1576, /* U+010CAB */ + 1577, /* U+010CAC */ + 1578, /* U+010CAD */ + 1579, /* U+010CAE */ + 1580, /* U+010CAF */ + 1581, /* U+010CB0 */ + 1582, /* U+010CB1 */ + 1583, /* U+010CB2 */ + 0, /* U+010CB3 */ + 0, /* U+010CB4 */ + 0, /* U+010CB5 */ + 0, /* U+010CB6 */ + 0, /* U+010CB7 */ + 0, /* U+010CB8 */ + 0, /* U+010CB9 */ + 0, /* U+010CBA */ + 0, /* U+010CBB */ + 0, /* U+010CBC */ + 0, /* U+010CBD */ + 0, /* U+010CBE */ + 0, /* U+010CBF */ + 1533, /* U+010CC0 */ + 1534, /* U+010CC1 */ + 1535, /* U+010CC2 */ + 1536, /* U+010CC3 */ + 1537, /* U+010CC4 */ + 1538, /* U+010CC5 */ + 1539, /* U+010CC6 */ + 1540, /* U+010CC7 */ + 1541, /* U+010CC8 */ + 1542, /* U+010CC9 */ + 1543, /* U+010CCA */ + 1544, /* U+010CCB */ + 1545, /* U+010CCC */ + 1546, /* U+010CCD */ + 1547, /* U+010CCE */ + 1548, /* U+010CCF */ + 1549, /* U+010CD0 */ + 1550, /* U+010CD1 */ + 1551, /* U+010CD2 */ + 1552, /* U+010CD3 */ + 1553, /* U+010CD4 */ + 1554, /* U+010CD5 */ + 1555, /* U+010CD6 */ + 1556, /* U+010CD7 */ + 1557, /* U+010CD8 */ + 1558, /* U+010CD9 */ + 1559, /* U+010CDA */ + 1560, /* U+010CDB */ + 1561, /* U+010CDC */ + 1562, /* U+010CDD */ + 1563, /* U+010CDE */ + 1564, /* U+010CDF */ + 1565, /* U+010CE0 */ + 1566, /* U+010CE1 */ + 1567, /* U+010CE2 */ + 1568, /* U+010CE3 */ + 1569, /* U+010CE4 */ + 1570, /* U+010CE5 */ + 1571, /* U+010CE6 */ + 1572, /* U+010CE7 */ + 1573, /* U+010CE8 */ + 1574, /* U+010CE9 */ + 1575, /* U+010CEA */ + 1576, /* U+010CEB */ + 1577, /* U+010CEC */ + 1578, /* U+010CED */ + 1579, /* U+010CEE */ + 1580, /* U+010CEF */ + 1581, /* U+010CF0 */ + 1582, /* U+010CF1 */ + 1583, /* U+010CF2 */ + 0, /* U+010CF3 */ + 0, /* U+010CF4 */ + 0, /* U+010CF5 */ + 0, /* U+010CF6 */ + 0, /* U+010CF7 */ + 0, /* U+010CF8 */ + 0, /* U+010CF9 */ + 0, /* U+010CFA */ + 0, /* U+010CFB */ + 0, /* U+010CFC */ + 0, /* U+010CFD */ + 0, /* U+010CFE */ + 0, /* U+010CFF */ + 0, /* U+010D00 */ + 0, /* U+010D01 */ + 0, /* U+010D02 */ + 0, /* U+010D03 */ + 0, /* U+010D04 */ + 0, /* U+010D05 */ + 0, /* U+010D06 */ + 0, /* U+010D07 */ + 0, /* U+010D08 */ + 0, /* U+010D09 */ + 0, /* U+010D0A */ + 0, /* U+010D0B */ + 0, /* U+010D0C */ + 0, /* U+010D0D */ + 0, /* U+010D0E */ + 0, /* U+010D0F */ + 0, /* U+010D10 */ + 0, /* U+010D11 */ + 0, /* U+010D12 */ + 0, /* U+010D13 */ + 0, /* U+010D14 */ + 0, /* U+010D15 */ + 0, /* U+010D16 */ + 0, /* U+010D17 */ + 0, /* U+010D18 */ + 0, /* U+010D19 */ + 0, /* U+010D1A */ + 0, /* U+010D1B */ + 0, /* U+010D1C */ + 0, /* U+010D1D */ + 0, /* U+010D1E */ + 0, /* U+010D1F */ + 0, /* U+010D20 */ + 0, /* U+010D21 */ + 0, /* U+010D22 */ + 0, /* U+010D23 */ + 0, /* U+010D24 */ + 0, /* U+010D25 */ + 0, /* U+010D26 */ + 0, /* U+010D27 */ + 0, /* U+010D28 */ + 0, /* U+010D29 */ + 0, /* U+010D2A */ + 0, /* U+010D2B */ + 0, /* U+010D2C */ + 0, /* U+010D2D */ + 0, /* U+010D2E */ + 0, /* U+010D2F */ + 0, /* U+010D30 */ + 0, /* U+010D31 */ + 0, /* U+010D32 */ + 0, /* U+010D33 */ + 0, /* U+010D34 */ + 0, /* U+010D35 */ + 0, /* U+010D36 */ + 0, /* U+010D37 */ + 0, /* U+010D38 */ + 0, /* U+010D39 */ + 0, /* U+010D3A */ + 0, /* U+010D3B */ + 0, /* U+010D3C */ + 0, /* U+010D3D */ + 0, /* U+010D3E */ + 0, /* U+010D3F */ + 0, /* U+010D40 */ + 0, /* U+010D41 */ + 0, /* U+010D42 */ + 0, /* U+010D43 */ + 0, /* U+010D44 */ + 0, /* U+010D45 */ + 0, /* U+010D46 */ + 0, /* U+010D47 */ + 0, /* U+010D48 */ + 0, /* U+010D49 */ + 0, /* U+010D4A */ + 0, /* U+010D4B */ + 0, /* U+010D4C */ + 0, /* U+010D4D */ + 0, /* U+010D4E */ + 0, /* U+010D4F */ + 1584, /* U+010D50 */ + 1585, /* U+010D51 */ + 1586, /* U+010D52 */ + 1587, /* U+010D53 */ + 1588, /* U+010D54 */ + 1589, /* U+010D55 */ + 1590, /* U+010D56 */ + 1591, /* U+010D57 */ + 1592, /* U+010D58 */ + 1593, /* U+010D59 */ + 1594, /* U+010D5A */ + 1595, /* U+010D5B */ + 1596, /* U+010D5C */ + 1597, /* U+010D5D */ + 1598, /* U+010D5E */ + 1599, /* U+010D5F */ + 1600, /* U+010D60 */ + 1601, /* U+010D61 */ + 1602, /* U+010D62 */ + 1603, /* U+010D63 */ + 1604, /* U+010D64 */ + 1605, /* U+010D65 */ + 0, /* U+010D66 */ + 0, /* U+010D67 */ + 0, /* U+010D68 */ + 0, /* U+010D69 */ + 0, /* U+010D6A */ + 0, /* U+010D6B */ + 0, /* U+010D6C */ + 0, /* U+010D6D */ + 0, /* U+010D6E */ + 0, /* U+010D6F */ + 1584, /* U+010D70 */ + 1585, /* U+010D71 */ + 1586, /* U+010D72 */ + 1587, /* U+010D73 */ + 1588, /* U+010D74 */ + 1589, /* U+010D75 */ + 1590, /* U+010D76 */ + 1591, /* U+010D77 */ + 1592, /* U+010D78 */ + 1593, /* U+010D79 */ + 1594, /* U+010D7A */ + 1595, /* U+010D7B */ + 1596, /* U+010D7C */ + 1597, /* U+010D7D */ + 1598, /* U+010D7E */ + 1599, /* U+010D7F */ + 1600, /* U+010D80 */ + 1601, /* U+010D81 */ + 1602, /* U+010D82 */ + 1603, /* U+010D83 */ + 1604, /* U+010D84 */ + 1605, /* U+010D85 */ + 1606, /* U+0118A0 */ + 1607, /* U+0118A1 */ + 1608, /* U+0118A2 */ + 1609, /* U+0118A3 */ + 1610, /* U+0118A4 */ + 1611, /* U+0118A5 */ + 1612, /* U+0118A6 */ + 1613, /* U+0118A7 */ + 1614, /* U+0118A8 */ + 1615, /* U+0118A9 */ + 1616, /* U+0118AA */ + 1617, /* U+0118AB */ + 1618, /* U+0118AC */ + 1619, /* U+0118AD */ + 1620, /* U+0118AE */ + 1621, /* U+0118AF */ + 1622, /* U+0118B0 */ + 1623, /* U+0118B1 */ + 1624, /* U+0118B2 */ + 1625, /* U+0118B3 */ + 1626, /* U+0118B4 */ + 1627, /* U+0118B5 */ + 1628, /* U+0118B6 */ + 1629, /* U+0118B7 */ + 1630, /* U+0118B8 */ + 1631, /* U+0118B9 */ + 1632, /* U+0118BA */ + 1633, /* U+0118BB */ + 1634, /* U+0118BC */ + 1635, /* U+0118BD */ + 1636, /* U+0118BE */ + 1637, /* U+0118BF */ + 1606, /* U+0118C0 */ + 1607, /* U+0118C1 */ + 1608, /* U+0118C2 */ + 1609, /* U+0118C3 */ + 1610, /* U+0118C4 */ + 1611, /* U+0118C5 */ + 1612, /* U+0118C6 */ + 1613, /* U+0118C7 */ + 1614, /* U+0118C8 */ + 1615, /* U+0118C9 */ + 1616, /* U+0118CA */ + 1617, /* U+0118CB */ + 1618, /* U+0118CC */ + 1619, /* U+0118CD */ + 1620, /* U+0118CE */ + 1621, /* U+0118CF */ + 1622, /* U+0118D0 */ + 1623, /* U+0118D1 */ + 1624, /* U+0118D2 */ + 1625, /* U+0118D3 */ + 1626, /* U+0118D4 */ + 1627, /* U+0118D5 */ + 1628, /* U+0118D6 */ + 1629, /* U+0118D7 */ + 1630, /* U+0118D8 */ + 1631, /* U+0118D9 */ + 1632, /* U+0118DA */ + 1633, /* U+0118DB */ + 1634, /* U+0118DC */ + 1635, /* U+0118DD */ + 1636, /* U+0118DE */ + 1637, /* U+0118DF */ + 1638, /* U+016E40 */ + 1639, /* U+016E41 */ + 1640, /* U+016E42 */ + 1641, /* U+016E43 */ + 1642, /* U+016E44 */ + 1643, /* U+016E45 */ + 1644, /* U+016E46 */ + 1645, /* U+016E47 */ + 1646, /* U+016E48 */ + 1647, /* U+016E49 */ + 1648, /* U+016E4A */ + 1649, /* U+016E4B */ + 1650, /* U+016E4C */ + 1651, /* U+016E4D */ + 1652, /* U+016E4E */ + 1653, /* U+016E4F */ + 1654, /* U+016E50 */ + 1655, /* U+016E51 */ + 1656, /* U+016E52 */ + 1657, /* U+016E53 */ + 1658, /* U+016E54 */ + 1659, /* U+016E55 */ + 1660, /* U+016E56 */ + 1661, /* U+016E57 */ + 1662, /* U+016E58 */ + 1663, /* U+016E59 */ + 1664, /* U+016E5A */ + 1665, /* U+016E5B */ + 1666, /* U+016E5C */ + 1667, /* U+016E5D */ + 1668, /* U+016E5E */ + 1669, /* U+016E5F */ + 1638, /* U+016E60 */ + 1639, /* U+016E61 */ + 1640, /* U+016E62 */ + 1641, /* U+016E63 */ + 1642, /* U+016E64 */ + 1643, /* U+016E65 */ + 1644, /* U+016E66 */ + 1645, /* U+016E67 */ + 1646, /* U+016E68 */ + 1647, /* U+016E69 */ + 1648, /* U+016E6A */ + 1649, /* U+016E6B */ + 1650, /* U+016E6C */ + 1651, /* U+016E6D */ + 1652, /* U+016E6E */ + 1653, /* U+016E6F */ + 1654, /* U+016E70 */ + 1655, /* U+016E71 */ + 1656, /* U+016E72 */ + 1657, /* U+016E73 */ + 1658, /* U+016E74 */ + 1659, /* U+016E75 */ + 1660, /* U+016E76 */ + 1661, /* U+016E77 */ + 1662, /* U+016E78 */ + 1663, /* U+016E79 */ + 1664, /* U+016E7A */ + 1665, /* U+016E7B */ + 1666, /* U+016E7C */ + 1667, /* U+016E7D */ + 1668, /* U+016E7E */ + 1669, /* U+016E7F */ + 1670, /* U+01E900 */ + 1671, /* U+01E901 */ + 1672, /* U+01E902 */ + 1673, /* U+01E903 */ + 1674, /* U+01E904 */ + 1675, /* U+01E905 */ + 1676, /* U+01E906 */ + 1677, /* U+01E907 */ + 1678, /* U+01E908 */ + 1679, /* U+01E909 */ + 1680, /* U+01E90A */ + 1681, /* U+01E90B */ + 1682, /* U+01E90C */ + 1683, /* U+01E90D */ + 1684, /* U+01E90E */ + 1685, /* U+01E90F */ + 1686, /* U+01E910 */ + 1687, /* U+01E911 */ + 1688, /* U+01E912 */ + 1689, /* U+01E913 */ + 1690, /* U+01E914 */ + 1691, /* U+01E915 */ + 1692, /* U+01E916 */ + 1693, /* U+01E917 */ + 1694, /* U+01E918 */ + 1695, /* U+01E919 */ + 1696, /* U+01E91A */ + 1697, /* U+01E91B */ + 1698, /* U+01E91C */ + 1699, /* U+01E91D */ + 1700, /* U+01E91E */ + 1701, /* U+01E91F */ + 1702, /* U+01E920 */ + 1703, /* U+01E921 */ + 1670, /* U+01E922 */ + 1671, /* U+01E923 */ + 1672, /* U+01E924 */ + 1673, /* U+01E925 */ + 1674, /* U+01E926 */ + 1675, /* U+01E927 */ + 1676, /* U+01E928 */ + 1677, /* U+01E929 */ + 1678, /* U+01E92A */ + 1679, /* U+01E92B */ + 1680, /* U+01E92C */ + 1681, /* U+01E92D */ + 1682, /* U+01E92E */ + 1683, /* U+01E92F */ + 1684, /* U+01E930 */ + 1685, /* U+01E931 */ + 1686, /* U+01E932 */ + 1687, /* U+01E933 */ + 1688, /* U+01E934 */ + 1689, /* U+01E935 */ + 1690, /* U+01E936 */ + 1691, /* U+01E937 */ + 1692, /* U+01E938 */ + 1693, /* U+01E939 */ + 1694, /* U+01E93A */ + 1695, /* U+01E93B */ + 1696, /* U+01E93C */ + 1697, /* U+01E93D */ + 1698, /* U+01E93E */ + 1699, /* U+01E93F */ + 1700, /* U+01E940 */ + 1701, /* U+01E941 */ + 1702, /* U+01E942 */ + 1703, /* U+01E943 */ +}; + + +/* + * case_index() + * + * Given a code point, compute the index in the case_map at which we can find + * the offset into the mapping tables. + */ +static inline uint16 +case_index(pg_wchar cp) +{ + /* Fast path for codepoints < 0x0588 */ + if (cp < 0x0588) + { + return case_map[cp]; + } + + if (cp < 0xABC0) + { + if (cp < 0x2185) + { + if (cp >= 0x10A0 && cp < 0x1100) + { + return case_map[cp - 0x10A0 + 1416]; + } + else if (cp >= 0x13A0) + { + if (cp < 0x13FE) + { + return case_map[cp - 0x13A0 + 1512]; + } + else if (cp >= 0x1C80) + { + return case_map[cp - 0x1C80 + 1606]; + } + } + } + else if (cp >= 0x24B6) + { + if (cp < 0x2D2E) + { + if (cp < 0x24EA) + { + return case_map[cp - 0x24B6 + 2891]; + } + else if (cp >= 0x2C00) + { + return case_map[cp - 0x2C00 + 2943]; + } + } + else if (cp >= 0xA640) + { + if (cp < 0xA7F7) + { + return case_map[cp - 0xA640 + 3245]; + } + else if (cp >= 0xAB53) + { + return case_map[cp - 0xAB53 + 3684]; + } + } + } + } + else if (cp >= 0xFB00) + { + if (cp < 0x10D86) + { + if (cp < 0xFF5B) + { + if (cp < 0xFB18) + { + return case_map[cp - 0xFB00 + 3793]; + } + else if (cp >= 0xFF21) + { + return case_map[cp - 0xFF21 + 3817]; + } + } + else if (cp >= 0x10400) + { + if (cp < 0x105BD) + { + return case_map[cp - 0x10400 + 3875]; + } + else if (cp >= 0x10C80) + { + return case_map[cp - 0x10C80 + 4320]; + } + } + } + else if (cp >= 0x118A0) + { + if (cp < 0x16E80) + { + if (cp < 0x118E0) + { + return case_map[cp - 0x118A0 + 4582]; + } + else if (cp >= 0x16E40) + { + return case_map[cp - 0x16E40 + 4646]; + } + } + else if (cp >= 0x1E900) + { + if (cp < 0x1E944) + { + return case_map[cp - 0x1E900 + 4710]; + } + } + } + } + + return 0; +} diff --git a/src/include/common/unicode_category.h b/src/include/common/unicode_category.h index a68f9eb8c89b2..8fd8b67a416e6 100644 --- a/src/include/common/unicode_category.h +++ b/src/include/common/unicode_category.h @@ -5,7 +5,7 @@ * * These definitions can be used by both frontend and backend code. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/unicode_category.h * diff --git a/src/include/common/unicode_category_table.h b/src/include/common/unicode_category_table.h index 65ea5141fca99..95a1c65da7e6f 100644 --- a/src/include/common/unicode_category_table.h +++ b/src/include/common/unicode_category_table.h @@ -3,7 +3,7 @@ * unicode_category_table.h * Category table for Unicode character classification. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_category_table.h @@ -696,7 +696,7 @@ static const pg_unicode_properties unicode_opt_ascii[128] = }; /* table of Unicode codepoint ranges and their categories */ -static const pg_category_range unicode_categories[3302] = +static const pg_category_range unicode_categories[3368] = { {0x000000, 0x00001f, PG_U_CONTROL}, {0x000020, 0x000020, PG_U_SPACE_SEPARATOR}, @@ -1408,7 +1408,7 @@ static const pg_category_range unicode_categories[3302] = {0x000888, 0x000888, PG_U_MODIFIER_SYMBOL}, {0x000889, 0x00088e, PG_U_OTHER_LETTER}, {0x000890, 0x000891, PG_U_FORMAT}, - {0x000898, 0x00089f, PG_U_NONSPACING_MARK}, + {0x000897, 0x00089f, PG_U_NONSPACING_MARK}, {0x0008a0, 0x0008c8, PG_U_OTHER_LETTER}, {0x0008c9, 0x0008c9, PG_U_MODIFIER_LETTER}, {0x0008ca, 0x0008e1, PG_U_NONSPACING_MARK}, @@ -1887,12 +1887,13 @@ static const pg_category_range unicode_categories[3302] = {0x001b42, 0x001b42, PG_U_NONSPACING_MARK}, {0x001b43, 0x001b44, PG_U_SPACING_MARK}, {0x001b45, 0x001b4c, PG_U_OTHER_LETTER}, + {0x001b4e, 0x001b4f, PG_U_OTHER_PUNCTUATION}, {0x001b50, 0x001b59, PG_U_DECIMAL_NUMBER}, {0x001b5a, 0x001b60, PG_U_OTHER_PUNCTUATION}, {0x001b61, 0x001b6a, PG_U_OTHER_SYMBOL}, {0x001b6b, 0x001b73, PG_U_NONSPACING_MARK}, {0x001b74, 0x001b7c, PG_U_OTHER_SYMBOL}, - {0x001b7d, 0x001b7e, PG_U_OTHER_PUNCTUATION}, + {0x001b7d, 0x001b7f, PG_U_OTHER_PUNCTUATION}, {0x001b80, 0x001b81, PG_U_NONSPACING_MARK}, {0x001b82, 0x001b82, PG_U_SPACING_MARK}, {0x001b83, 0x001ba0, PG_U_OTHER_LETTER}, @@ -1927,6 +1928,8 @@ static const pg_category_range unicode_categories[3302] = {0x001c78, 0x001c7d, PG_U_MODIFIER_LETTER}, {0x001c7e, 0x001c7f, PG_U_OTHER_PUNCTUATION}, {0x001c80, 0x001c88, PG_U_LOWERCASE_LETTER}, + {0x001c89, 0x001c89, PG_U_UPPERCASE_LETTER}, + {0x001c8a, 0x001c8a, PG_U_LOWERCASE_LETTER}, {0x001c90, 0x001cba, PG_U_UPPERCASE_LETTER}, {0x001cbd, 0x001cbf, PG_U_UPPERCASE_LETTER}, {0x001cc0, 0x001cc7, PG_U_OTHER_PUNCTUATION}, @@ -2378,7 +2381,7 @@ static const pg_category_range unicode_categories[3302] = {0x00239b, 0x0023b3, PG_U_MATH_SYMBOL}, {0x0023b4, 0x0023db, PG_U_OTHER_SYMBOL}, {0x0023dc, 0x0023e1, PG_U_MATH_SYMBOL}, - {0x0023e2, 0x002426, PG_U_OTHER_SYMBOL}, + {0x0023e2, 0x002429, PG_U_OTHER_SYMBOL}, {0x002440, 0x00244a, PG_U_OTHER_SYMBOL}, {0x002460, 0x00249b, PG_U_OTHER_NUMBER}, {0x00249c, 0x0024e9, PG_U_OTHER_SYMBOL}, @@ -2719,7 +2722,7 @@ static const pg_category_range unicode_categories[3302] = {0x003192, 0x003195, PG_U_OTHER_NUMBER}, {0x003196, 0x00319f, PG_U_OTHER_SYMBOL}, {0x0031a0, 0x0031bf, PG_U_OTHER_LETTER}, - {0x0031c0, 0x0031e3, PG_U_OTHER_SYMBOL}, + {0x0031c0, 0x0031e5, PG_U_OTHER_SYMBOL}, {0x0031ef, 0x0031ef, PG_U_OTHER_SYMBOL}, {0x0031f0, 0x0031ff, PG_U_OTHER_LETTER}, {0x003200, 0x00321e, PG_U_OTHER_SYMBOL}, @@ -2983,6 +2986,8 @@ static const pg_category_range unicode_categories[3302] = {0x00a7c8, 0x00a7c8, PG_U_LOWERCASE_LETTER}, {0x00a7c9, 0x00a7c9, PG_U_UPPERCASE_LETTER}, {0x00a7ca, 0x00a7ca, PG_U_LOWERCASE_LETTER}, + {0x00a7cb, 0x00a7cc, PG_U_UPPERCASE_LETTER}, + {0x00a7cd, 0x00a7cd, PG_U_LOWERCASE_LETTER}, {0x00a7d0, 0x00a7d0, PG_U_UPPERCASE_LETTER}, {0x00a7d1, 0x00a7d1, PG_U_LOWERCASE_LETTER}, {0x00a7d3, 0x00a7d3, PG_U_LOWERCASE_LETTER}, @@ -2991,6 +2996,9 @@ static const pg_category_range unicode_categories[3302] = {0x00a7d7, 0x00a7d7, PG_U_LOWERCASE_LETTER}, {0x00a7d8, 0x00a7d8, PG_U_UPPERCASE_LETTER}, {0x00a7d9, 0x00a7d9, PG_U_LOWERCASE_LETTER}, + {0x00a7da, 0x00a7da, PG_U_UPPERCASE_LETTER}, + {0x00a7db, 0x00a7db, PG_U_LOWERCASE_LETTER}, + {0x00a7dc, 0x00a7dc, PG_U_UPPERCASE_LETTER}, {0x00a7f2, 0x00a7f4, PG_U_MODIFIER_LETTER}, {0x00a7f5, 0x00a7f5, PG_U_UPPERCASE_LETTER}, {0x00a7f6, 0x00a7f6, PG_U_LOWERCASE_LETTER}, @@ -3306,6 +3314,7 @@ static const pg_category_range unicode_categories[3302] = {0x0105a3, 0x0105b1, PG_U_LOWERCASE_LETTER}, {0x0105b3, 0x0105b9, PG_U_LOWERCASE_LETTER}, {0x0105bb, 0x0105bc, PG_U_LOWERCASE_LETTER}, + {0x0105c0, 0x0105f3, PG_U_OTHER_LETTER}, {0x010600, 0x010736, PG_U_OTHER_LETTER}, {0x010740, 0x010755, PG_U_OTHER_LETTER}, {0x010760, 0x010767, PG_U_OTHER_LETTER}, @@ -3376,12 +3385,23 @@ static const pg_category_range unicode_categories[3302] = {0x010d00, 0x010d23, PG_U_OTHER_LETTER}, {0x010d24, 0x010d27, PG_U_NONSPACING_MARK}, {0x010d30, 0x010d39, PG_U_DECIMAL_NUMBER}, + {0x010d40, 0x010d49, PG_U_DECIMAL_NUMBER}, + {0x010d4a, 0x010d4d, PG_U_OTHER_LETTER}, + {0x010d4e, 0x010d4e, PG_U_MODIFIER_LETTER}, + {0x010d4f, 0x010d4f, PG_U_OTHER_LETTER}, + {0x010d50, 0x010d65, PG_U_UPPERCASE_LETTER}, + {0x010d69, 0x010d6d, PG_U_NONSPACING_MARK}, + {0x010d6e, 0x010d6e, PG_U_DASH_PUNCTUATION}, + {0x010d6f, 0x010d6f, PG_U_MODIFIER_LETTER}, + {0x010d70, 0x010d85, PG_U_LOWERCASE_LETTER}, + {0x010d8e, 0x010d8f, PG_U_MATH_SYMBOL}, {0x010e60, 0x010e7e, PG_U_OTHER_NUMBER}, {0x010e80, 0x010ea9, PG_U_OTHER_LETTER}, {0x010eab, 0x010eac, PG_U_NONSPACING_MARK}, {0x010ead, 0x010ead, PG_U_DASH_PUNCTUATION}, {0x010eb0, 0x010eb1, PG_U_OTHER_LETTER}, - {0x010efd, 0x010eff, PG_U_NONSPACING_MARK}, + {0x010ec2, 0x010ec4, PG_U_OTHER_LETTER}, + {0x010efc, 0x010eff, PG_U_NONSPACING_MARK}, {0x010f00, 0x010f1c, PG_U_OTHER_LETTER}, {0x010f1d, 0x010f26, PG_U_OTHER_NUMBER}, {0x010f27, 0x010f27, PG_U_OTHER_LETTER}, @@ -3497,6 +3517,26 @@ static const pg_category_range unicode_categories[3302] = {0x011362, 0x011363, PG_U_SPACING_MARK}, {0x011366, 0x01136c, PG_U_NONSPACING_MARK}, {0x011370, 0x011374, PG_U_NONSPACING_MARK}, + {0x011380, 0x011389, PG_U_OTHER_LETTER}, + {0x01138b, 0x01138b, PG_U_OTHER_LETTER}, + {0x01138e, 0x01138e, PG_U_OTHER_LETTER}, + {0x011390, 0x0113b5, PG_U_OTHER_LETTER}, + {0x0113b7, 0x0113b7, PG_U_OTHER_LETTER}, + {0x0113b8, 0x0113ba, PG_U_SPACING_MARK}, + {0x0113bb, 0x0113c0, PG_U_NONSPACING_MARK}, + {0x0113c2, 0x0113c2, PG_U_SPACING_MARK}, + {0x0113c5, 0x0113c5, PG_U_SPACING_MARK}, + {0x0113c7, 0x0113ca, PG_U_SPACING_MARK}, + {0x0113cc, 0x0113cd, PG_U_SPACING_MARK}, + {0x0113ce, 0x0113ce, PG_U_NONSPACING_MARK}, + {0x0113cf, 0x0113cf, PG_U_SPACING_MARK}, + {0x0113d0, 0x0113d0, PG_U_NONSPACING_MARK}, + {0x0113d1, 0x0113d1, PG_U_OTHER_LETTER}, + {0x0113d2, 0x0113d2, PG_U_NONSPACING_MARK}, + {0x0113d3, 0x0113d3, PG_U_OTHER_LETTER}, + {0x0113d4, 0x0113d5, PG_U_OTHER_PUNCTUATION}, + {0x0113d7, 0x0113d8, PG_U_OTHER_PUNCTUATION}, + {0x0113e1, 0x0113e2, PG_U_NONSPACING_MARK}, {0x011400, 0x011434, PG_U_OTHER_LETTER}, {0x011435, 0x011437, PG_U_SPACING_MARK}, {0x011438, 0x01143f, PG_U_NONSPACING_MARK}, @@ -3556,8 +3596,11 @@ static const pg_category_range unicode_categories[3302] = {0x0116b8, 0x0116b8, PG_U_OTHER_LETTER}, {0x0116b9, 0x0116b9, PG_U_OTHER_PUNCTUATION}, {0x0116c0, 0x0116c9, PG_U_DECIMAL_NUMBER}, + {0x0116d0, 0x0116e3, PG_U_DECIMAL_NUMBER}, {0x011700, 0x01171a, PG_U_OTHER_LETTER}, - {0x01171d, 0x01171f, PG_U_NONSPACING_MARK}, + {0x01171d, 0x01171d, PG_U_NONSPACING_MARK}, + {0x01171e, 0x01171e, PG_U_SPACING_MARK}, + {0x01171f, 0x01171f, PG_U_NONSPACING_MARK}, {0x011720, 0x011721, PG_U_SPACING_MARK}, {0x011722, 0x011725, PG_U_NONSPACING_MARK}, {0x011726, 0x011726, PG_U_SPACING_MARK}, @@ -3627,6 +3670,9 @@ static const pg_category_range unicode_categories[3302] = {0x011a9e, 0x011aa2, PG_U_OTHER_PUNCTUATION}, {0x011ab0, 0x011af8, PG_U_OTHER_LETTER}, {0x011b00, 0x011b09, PG_U_OTHER_PUNCTUATION}, + {0x011bc0, 0x011be0, PG_U_OTHER_LETTER}, + {0x011be1, 0x011be1, PG_U_OTHER_PUNCTUATION}, + {0x011bf0, 0x011bf9, PG_U_DECIMAL_NUMBER}, {0x011c00, 0x011c08, PG_U_OTHER_LETTER}, {0x011c0a, 0x011c2e, PG_U_OTHER_LETTER}, {0x011c2f, 0x011c2f, PG_U_SPACING_MARK}, @@ -3685,6 +3731,7 @@ static const pg_category_range unicode_categories[3302] = {0x011f42, 0x011f42, PG_U_NONSPACING_MARK}, {0x011f43, 0x011f4f, PG_U_OTHER_PUNCTUATION}, {0x011f50, 0x011f59, PG_U_DECIMAL_NUMBER}, + {0x011f5a, 0x011f5a, PG_U_NONSPACING_MARK}, {0x011fb0, 0x011fb0, PG_U_OTHER_LETTER}, {0x011fc0, 0x011fd4, PG_U_OTHER_NUMBER}, {0x011fd5, 0x011fdc, PG_U_OTHER_SYMBOL}, @@ -3702,7 +3749,13 @@ static const pg_category_range unicode_categories[3302] = {0x013440, 0x013440, PG_U_NONSPACING_MARK}, {0x013441, 0x013446, PG_U_OTHER_LETTER}, {0x013447, 0x013455, PG_U_NONSPACING_MARK}, + {0x013460, 0x0143fa, PG_U_OTHER_LETTER}, {0x014400, 0x014646, PG_U_OTHER_LETTER}, + {0x016100, 0x01611d, PG_U_OTHER_LETTER}, + {0x01611e, 0x016129, PG_U_NONSPACING_MARK}, + {0x01612a, 0x01612c, PG_U_SPACING_MARK}, + {0x01612d, 0x01612f, PG_U_NONSPACING_MARK}, + {0x016130, 0x016139, PG_U_DECIMAL_NUMBER}, {0x016800, 0x016a38, PG_U_OTHER_LETTER}, {0x016a40, 0x016a5e, PG_U_OTHER_LETTER}, {0x016a60, 0x016a69, PG_U_DECIMAL_NUMBER}, @@ -3723,6 +3776,11 @@ static const pg_category_range unicode_categories[3302] = {0x016b5b, 0x016b61, PG_U_OTHER_NUMBER}, {0x016b63, 0x016b77, PG_U_OTHER_LETTER}, {0x016b7d, 0x016b8f, PG_U_OTHER_LETTER}, + {0x016d40, 0x016d42, PG_U_MODIFIER_LETTER}, + {0x016d43, 0x016d6a, PG_U_OTHER_LETTER}, + {0x016d6b, 0x016d6c, PG_U_MODIFIER_LETTER}, + {0x016d6d, 0x016d6f, PG_U_OTHER_PUNCTUATION}, + {0x016d70, 0x016d79, PG_U_DECIMAL_NUMBER}, {0x016e40, 0x016e5f, PG_U_UPPERCASE_LETTER}, {0x016e60, 0x016e7f, PG_U_LOWERCASE_LETTER}, {0x016e80, 0x016e96, PG_U_OTHER_NUMBER}, @@ -3740,7 +3798,7 @@ static const pg_category_range unicode_categories[3302] = {0x016ff0, 0x016ff1, PG_U_SPACING_MARK}, {0x017000, 0x0187f7, PG_U_OTHER_LETTER}, {0x018800, 0x018cd5, PG_U_OTHER_LETTER}, - {0x018d00, 0x018d08, PG_U_OTHER_LETTER}, + {0x018cff, 0x018d08, PG_U_OTHER_LETTER}, {0x01aff0, 0x01aff3, PG_U_MODIFIER_LETTER}, {0x01aff5, 0x01affb, PG_U_MODIFIER_LETTER}, {0x01affd, 0x01affe, PG_U_MODIFIER_LETTER}, @@ -3758,6 +3816,9 @@ static const pg_category_range unicode_categories[3302] = {0x01bc9d, 0x01bc9e, PG_U_NONSPACING_MARK}, {0x01bc9f, 0x01bc9f, PG_U_OTHER_PUNCTUATION}, {0x01bca0, 0x01bca3, PG_U_FORMAT}, + {0x01cc00, 0x01ccef, PG_U_OTHER_SYMBOL}, + {0x01ccf0, 0x01ccf9, PG_U_DECIMAL_NUMBER}, + {0x01cd00, 0x01ceb3, PG_U_OTHER_SYMBOL}, {0x01cf00, 0x01cf2d, PG_U_NONSPACING_MARK}, {0x01cf30, 0x01cf46, PG_U_NONSPACING_MARK}, {0x01cf50, 0x01cfc3, PG_U_OTHER_SYMBOL}, @@ -3891,6 +3952,11 @@ static const pg_category_range unicode_categories[3302] = {0x01e4eb, 0x01e4eb, PG_U_MODIFIER_LETTER}, {0x01e4ec, 0x01e4ef, PG_U_NONSPACING_MARK}, {0x01e4f0, 0x01e4f9, PG_U_DECIMAL_NUMBER}, + {0x01e5d0, 0x01e5ed, PG_U_OTHER_LETTER}, + {0x01e5ee, 0x01e5ef, PG_U_NONSPACING_MARK}, + {0x01e5f0, 0x01e5f0, PG_U_OTHER_LETTER}, + {0x01e5f1, 0x01e5fa, PG_U_DECIMAL_NUMBER}, + {0x01e5ff, 0x01e5ff, PG_U_OTHER_PUNCTUATION}, {0x01e7e0, 0x01e7e6, PG_U_OTHER_LETTER}, {0x01e7e8, 0x01e7eb, PG_U_OTHER_LETTER}, {0x01e7ed, 0x01e7ee, PG_U_OTHER_LETTER}, @@ -3973,18 +4039,18 @@ static const pg_category_range unicode_categories[3302] = {0x01f850, 0x01f859, PG_U_OTHER_SYMBOL}, {0x01f860, 0x01f887, PG_U_OTHER_SYMBOL}, {0x01f890, 0x01f8ad, PG_U_OTHER_SYMBOL}, - {0x01f8b0, 0x01f8b1, PG_U_OTHER_SYMBOL}, + {0x01f8b0, 0x01f8bb, PG_U_OTHER_SYMBOL}, + {0x01f8c0, 0x01f8c1, PG_U_OTHER_SYMBOL}, {0x01f900, 0x01fa53, PG_U_OTHER_SYMBOL}, {0x01fa60, 0x01fa6d, PG_U_OTHER_SYMBOL}, {0x01fa70, 0x01fa7c, PG_U_OTHER_SYMBOL}, - {0x01fa80, 0x01fa88, PG_U_OTHER_SYMBOL}, - {0x01fa90, 0x01fabd, PG_U_OTHER_SYMBOL}, - {0x01fabf, 0x01fac5, PG_U_OTHER_SYMBOL}, - {0x01face, 0x01fadb, PG_U_OTHER_SYMBOL}, - {0x01fae0, 0x01fae8, PG_U_OTHER_SYMBOL}, + {0x01fa80, 0x01fa89, PG_U_OTHER_SYMBOL}, + {0x01fa8f, 0x01fac6, PG_U_OTHER_SYMBOL}, + {0x01face, 0x01fadc, PG_U_OTHER_SYMBOL}, + {0x01fadf, 0x01fae9, PG_U_OTHER_SYMBOL}, {0x01faf0, 0x01faf8, PG_U_OTHER_SYMBOL}, {0x01fb00, 0x01fb92, PG_U_OTHER_SYMBOL}, - {0x01fb94, 0x01fbca, PG_U_OTHER_SYMBOL}, + {0x01fb94, 0x01fbef, PG_U_OTHER_SYMBOL}, {0x01fbf0, 0x01fbf9, PG_U_DECIMAL_NUMBER}, {0x020000, 0x02a6df, PG_U_OTHER_LETTER}, {0x02a700, 0x02b739, PG_U_OTHER_LETTER}, @@ -4003,7 +4069,7 @@ static const pg_category_range unicode_categories[3302] = }; /* table of Unicode codepoint ranges of Alphabetic characters */ -static const pg_unicode_range unicode_alphabetic[1141] = +static const pg_unicode_range unicode_alphabetic[1179] = { {0x000041, 0x00005a}, {0x000061, 0x00007a}, @@ -4025,6 +4091,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x0002ec, 0x0002ec}, {0x0002ee, 0x0002ee}, {0x000345, 0x000345}, + {0x000363, 0x00036f}, {0x000370, 0x000373}, {0x000374, 0x000374}, {0x000376, 0x000377}, @@ -4088,6 +4155,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x000860, 0x00086a}, {0x000870, 0x000887}, {0x000889, 0x00088e}, + {0x000897, 0x000897}, {0x0008a0, 0x0008c8}, {0x0008c9, 0x0008c9}, {0x0008d4, 0x0008df}, @@ -4455,7 +4523,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x001c4d, 0x001c4f}, {0x001c5a, 0x001c77}, {0x001c78, 0x001c7d}, - {0x001c80, 0x001c88}, + {0x001c80, 0x001c8a}, {0x001c90, 0x001cba}, {0x001cbd, 0x001cbf}, {0x001ce9, 0x001cec}, @@ -4468,7 +4536,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x001d78, 0x001d78}, {0x001d79, 0x001d9a}, {0x001d9b, 0x001dbf}, - {0x001de7, 0x001df4}, + {0x001dd3, 0x001df4}, {0x001e00, 0x001f15}, {0x001f18, 0x001f1d}, {0x001f20, 0x001f45}, @@ -4575,10 +4643,10 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x00a788, 0x00a788}, {0x00a78b, 0x00a78e}, {0x00a78f, 0x00a78f}, - {0x00a790, 0x00a7ca}, + {0x00a790, 0x00a7cd}, {0x00a7d0, 0x00a7d1}, {0x00a7d3, 0x00a7d3}, - {0x00a7d5, 0x00a7d9}, + {0x00a7d5, 0x00a7dc}, {0x00a7f2, 0x00a7f4}, {0x00a7f5, 0x00a7f6}, {0x00a7f7, 0x00a7f7}, @@ -4743,6 +4811,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x0105a3, 0x0105b1}, {0x0105b3, 0x0105b9}, {0x0105bb, 0x0105bc}, + {0x0105c0, 0x0105f3}, {0x010600, 0x010736}, {0x010740, 0x010755}, {0x010760, 0x010767}, @@ -4783,9 +4852,18 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x010cc0, 0x010cf2}, {0x010d00, 0x010d23}, {0x010d24, 0x010d27}, + {0x010d4a, 0x010d4d}, + {0x010d4e, 0x010d4e}, + {0x010d4f, 0x010d4f}, + {0x010d50, 0x010d65}, + {0x010d69, 0x010d69}, + {0x010d6f, 0x010d6f}, + {0x010d70, 0x010d85}, {0x010e80, 0x010ea9}, {0x010eab, 0x010eac}, {0x010eb0, 0x010eb1}, + {0x010ec2, 0x010ec4}, + {0x010efc, 0x010efc}, {0x010f00, 0x010f1c}, {0x010f27, 0x010f27}, {0x010f30, 0x010f45}, @@ -4866,6 +4944,19 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x011357, 0x011357}, {0x01135d, 0x011361}, {0x011362, 0x011363}, + {0x011380, 0x011389}, + {0x01138b, 0x01138b}, + {0x01138e, 0x01138e}, + {0x011390, 0x0113b5}, + {0x0113b7, 0x0113b7}, + {0x0113b8, 0x0113ba}, + {0x0113bb, 0x0113c0}, + {0x0113c2, 0x0113c2}, + {0x0113c5, 0x0113c5}, + {0x0113c7, 0x0113ca}, + {0x0113cc, 0x0113cd}, + {0x0113d1, 0x0113d1}, + {0x0113d3, 0x0113d3}, {0x011400, 0x011434}, {0x011435, 0x011437}, {0x011438, 0x01143f}, @@ -4908,7 +4999,9 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x0116b0, 0x0116b5}, {0x0116b8, 0x0116b8}, {0x011700, 0x01171a}, - {0x01171d, 0x01171f}, + {0x01171d, 0x01171d}, + {0x01171e, 0x01171e}, + {0x01171f, 0x01171f}, {0x011720, 0x011721}, {0x011722, 0x011725}, {0x011726, 0x011726}, @@ -4956,6 +5049,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x011a97, 0x011a97}, {0x011a9d, 0x011a9d}, {0x011ab0, 0x011af8}, + {0x011bc0, 0x011be0}, {0x011c00, 0x011c08}, {0x011c0a, 0x011c2e}, {0x011c2f, 0x011c2f}, @@ -5009,7 +5103,12 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x012f90, 0x012ff0}, {0x013000, 0x01342f}, {0x013441, 0x013446}, + {0x013460, 0x0143fa}, {0x014400, 0x014646}, + {0x016100, 0x01611d}, + {0x01611e, 0x016129}, + {0x01612a, 0x01612c}, + {0x01612d, 0x01612e}, {0x016800, 0x016a38}, {0x016a40, 0x016a5e}, {0x016a70, 0x016abe}, @@ -5018,6 +5117,9 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x016b40, 0x016b43}, {0x016b63, 0x016b77}, {0x016b7d, 0x016b8f}, + {0x016d40, 0x016d42}, + {0x016d43, 0x016d6a}, + {0x016d6b, 0x016d6c}, {0x016e40, 0x016e7f}, {0x016f00, 0x016f4a}, {0x016f4f, 0x016f4f}, @@ -5030,7 +5132,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x016ff0, 0x016ff1}, {0x017000, 0x0187f7}, {0x018800, 0x018cd5}, - {0x018d00, 0x018d08}, + {0x018cff, 0x018d08}, {0x01aff0, 0x01aff3}, {0x01aff5, 0x01affb}, {0x01affd, 0x01affe}, @@ -5093,6 +5195,8 @@ static const pg_unicode_range unicode_alphabetic[1141] = {0x01e2c0, 0x01e2eb}, {0x01e4d0, 0x01e4ea}, {0x01e4eb, 0x01e4eb}, + {0x01e5d0, 0x01e5ed}, + {0x01e5f0, 0x01e5f0}, {0x01e7e0, 0x01e7e6}, {0x01e7e8, 0x01e7eb}, {0x01e7ed, 0x01e7ee}, @@ -5149,7 +5253,7 @@ static const pg_unicode_range unicode_alphabetic[1141] = }; /* table of Unicode codepoint ranges of Lowercase characters */ -static const pg_unicode_range unicode_lowercase[686] = +static const pg_unicode_range unicode_lowercase[690] = { {0x000061, 0x00007a}, {0x0000aa, 0x0000aa}, @@ -5433,6 +5537,7 @@ static const pg_unicode_range unicode_lowercase[686] = {0x0010fd, 0x0010ff}, {0x0013f8, 0x0013fd}, {0x001c80, 0x001c88}, + {0x001c8a, 0x001c8a}, {0x001d00, 0x001d2b}, {0x001d2c, 0x001d6a}, {0x001d6b, 0x001d77}, @@ -5774,11 +5879,13 @@ static const pg_unicode_range unicode_lowercase[686] = {0x00a7c3, 0x00a7c3}, {0x00a7c8, 0x00a7c8}, {0x00a7ca, 0x00a7ca}, + {0x00a7cd, 0x00a7cd}, {0x00a7d1, 0x00a7d1}, {0x00a7d3, 0x00a7d3}, {0x00a7d5, 0x00a7d5}, {0x00a7d7, 0x00a7d7}, {0x00a7d9, 0x00a7d9}, + {0x00a7db, 0x00a7db}, {0x00a7f2, 0x00a7f4}, {0x00a7f6, 0x00a7f6}, {0x00a7f8, 0x00a7f9}, @@ -5802,6 +5909,7 @@ static const pg_unicode_range unicode_lowercase[686] = {0x010787, 0x0107b0}, {0x0107b2, 0x0107ba}, {0x010cc0, 0x010cf2}, + {0x010d70, 0x010d85}, {0x0118c0, 0x0118df}, {0x016e60, 0x016e7f}, {0x01d41a, 0x01d433}, @@ -5840,7 +5948,7 @@ static const pg_unicode_range unicode_lowercase[686] = }; /* table of Unicode codepoint ranges of Uppercase characters */ -static const pg_unicode_range unicode_uppercase[651] = +static const pg_unicode_range unicode_uppercase[656] = { {0x000041, 0x00005a}, {0x0000c0, 0x0000d6}, @@ -6118,6 +6226,7 @@ static const pg_unicode_range unicode_uppercase[651] = {0x0010c7, 0x0010c7}, {0x0010cd, 0x0010cd}, {0x0013a0, 0x0013f5}, + {0x001c89, 0x001c89}, {0x001c90, 0x001cba}, {0x001cbd, 0x001cbf}, {0x001e00, 0x001e00}, @@ -6444,9 +6553,12 @@ static const pg_unicode_range unicode_uppercase[651] = {0x00a7c2, 0x00a7c2}, {0x00a7c4, 0x00a7c7}, {0x00a7c9, 0x00a7c9}, + {0x00a7cb, 0x00a7cc}, {0x00a7d0, 0x00a7d0}, {0x00a7d6, 0x00a7d6}, {0x00a7d8, 0x00a7d8}, + {0x00a7da, 0x00a7da}, + {0x00a7dc, 0x00a7dc}, {0x00a7f5, 0x00a7f5}, {0x00ff21, 0x00ff3a}, {0x010400, 0x010427}, @@ -6456,6 +6568,7 @@ static const pg_unicode_range unicode_uppercase[651] = {0x01058c, 0x010592}, {0x010594, 0x010595}, {0x010c80, 0x010cb2}, + {0x010d50, 0x010d65}, {0x0118a0, 0x0118bf}, {0x016e40, 0x016e5f}, {0x01d400, 0x01d419}, @@ -6496,7 +6609,7 @@ static const pg_unicode_range unicode_uppercase[651] = }; /* table of Unicode codepoint ranges of Case_Ignorable characters */ -static const pg_unicode_range unicode_case_ignorable[491] = +static const pg_unicode_range unicode_case_ignorable[506] = { {0x000027, 0x000027}, {0x00002e, 0x00002e}, @@ -6565,7 +6678,7 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x000859, 0x00085b}, {0x000888, 0x000888}, {0x000890, 0x000891}, - {0x000898, 0x00089f}, + {0x000897, 0x00089f}, {0x0008c9, 0x0008c9}, {0x0008ca, 0x0008e1}, {0x0008e2, 0x0008e2}, @@ -6846,8 +6959,11 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x010a3f, 0x010a3f}, {0x010ae5, 0x010ae6}, {0x010d24, 0x010d27}, + {0x010d4e, 0x010d4e}, + {0x010d69, 0x010d6d}, + {0x010d6f, 0x010d6f}, {0x010eab, 0x010eac}, - {0x010efd, 0x010eff}, + {0x010efc, 0x010eff}, {0x010f46, 0x010f50}, {0x010f82, 0x010f85}, {0x011001, 0x011001}, @@ -6880,6 +6996,11 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x011340, 0x011340}, {0x011366, 0x01136c}, {0x011370, 0x011374}, + {0x0113bb, 0x0113c0}, + {0x0113ce, 0x0113ce}, + {0x0113d0, 0x0113d0}, + {0x0113d2, 0x0113d2}, + {0x0113e1, 0x0113e2}, {0x011438, 0x01143f}, {0x011442, 0x011444}, {0x011446, 0x011446}, @@ -6899,7 +7020,8 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x0116ad, 0x0116ad}, {0x0116b0, 0x0116b5}, {0x0116b7, 0x0116b7}, - {0x01171d, 0x01171f}, + {0x01171d, 0x01171d}, + {0x01171f, 0x01171f}, {0x011722, 0x011725}, {0x011727, 0x01172b}, {0x01182f, 0x011837}, @@ -6938,12 +7060,17 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x011f36, 0x011f3a}, {0x011f40, 0x011f40}, {0x011f42, 0x011f42}, + {0x011f5a, 0x011f5a}, {0x013430, 0x01343f}, {0x013440, 0x013440}, {0x013447, 0x013455}, + {0x01611e, 0x016129}, + {0x01612d, 0x01612f}, {0x016af0, 0x016af4}, {0x016b30, 0x016b36}, {0x016b40, 0x016b43}, + {0x016d40, 0x016d42}, + {0x016d6b, 0x016d6c}, {0x016f4f, 0x016f4f}, {0x016f8f, 0x016f92}, {0x016f93, 0x016f9f}, @@ -6982,6 +7109,7 @@ static const pg_unicode_range unicode_case_ignorable[491] = {0x01e2ec, 0x01e2ef}, {0x01e4eb, 0x01e4eb}, {0x01e4ec, 0x01e4ef}, + {0x01e5ee, 0x01e5ef}, {0x01e8d0, 0x01e8d6}, {0x01e944, 0x01e94a}, {0x01e94b, 0x01e94b}, diff --git a/src/include/common/unicode_east_asian_fw_table.h b/src/include/common/unicode_east_asian_fw_table.h index dcd1f136eb777..db8bd0ad89779 100644 --- a/src/include/common/unicode_east_asian_fw_table.h +++ b/src/include/common/unicode_east_asian_fw_table.h @@ -9,8 +9,10 @@ static const struct mbinterval east_asian_fw[] = { {0x23F3, 0x23F3}, {0x25FD, 0x25FE}, {0x2614, 0x2615}, + {0x2630, 0x2637}, {0x2648, 0x2653}, {0x267F, 0x267F}, + {0x268A, 0x268F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, {0x26AA, 0x26AB}, @@ -44,11 +46,10 @@ static const struct mbinterval east_asian_fw[] = { {0x3099, 0x30FF}, {0x3105, 0x312F}, {0x3131, 0x318E}, - {0x3190, 0x31E3}, + {0x3190, 0x31E5}, {0x31EF, 0x321E}, {0x3220, 0x3247}, - {0x3250, 0x4DBF}, - {0x4E00, 0xA48C}, + {0x3250, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, @@ -63,7 +64,7 @@ static const struct mbinterval east_asian_fw[] = { {0x16FF0, 0x16FF1}, {0x17000, 0x187F7}, {0x18800, 0x18CD5}, - {0x18D00, 0x18D08}, + {0x18CFF, 0x18D08}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB}, {0x1AFFD, 0x1AFFE}, @@ -73,6 +74,8 @@ static const struct mbinterval east_asian_fw[] = { {0x1B155, 0x1B155}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB}, + {0x1D300, 0x1D356}, + {0x1D360, 0x1D376}, {0x1F004, 0x1F004}, {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, @@ -113,11 +116,10 @@ static const struct mbinterval east_asian_fw[] = { {0x1F93C, 0x1F945}, {0x1F947, 0x1F9FF}, {0x1FA70, 0x1FA7C}, - {0x1FA80, 0x1FA88}, - {0x1FA90, 0x1FABD}, - {0x1FABF, 0x1FAC5}, - {0x1FACE, 0x1FADB}, - {0x1FAE0, 0x1FAE8}, + {0x1FA80, 0x1FA89}, + {0x1FA8F, 0x1FAC6}, + {0x1FACE, 0x1FADC}, + {0x1FADF, 0x1FAE9}, {0x1FAF0, 0x1FAF8}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, diff --git a/src/include/common/unicode_nonspacing_table.h b/src/include/common/unicode_nonspacing_table.h index 8d00e127fcd9c..d67f5b3f281d3 100644 --- a/src/include/common/unicode_nonspacing_table.h +++ b/src/include/common/unicode_nonspacing_table.h @@ -210,8 +210,9 @@ static const struct mbinterval nonspacing[] = { {0x10A38, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x10D24, 0x10D27}, + {0x10D69, 0x10D6D}, {0x10EAB, 0x10EAC}, - {0x10EFD, 0x10EFF}, + {0x10EFC, 0x10EFF}, {0x10F46, 0x10F50}, {0x10F82, 0x10F85}, {0x11001, 0x11001}, @@ -242,6 +243,11 @@ static const struct mbinterval nonspacing[] = { {0x1133B, 0x1133C}, {0x11340, 0x11340}, {0x11366, 0x11374}, + {0x113BB, 0x113C0}, + {0x113CE, 0x113CE}, + {0x113D0, 0x113D0}, + {0x113D2, 0x113D2}, + {0x113E1, 0x113E2}, {0x11438, 0x1143F}, {0x11442, 0x11444}, {0x11446, 0x11446}, @@ -261,7 +267,8 @@ static const struct mbinterval nonspacing[] = { {0x116AD, 0x116AD}, {0x116B0, 0x116B5}, {0x116B7, 0x116B7}, - {0x1171D, 0x1171F}, + {0x1171D, 0x1171D}, + {0x1171F, 0x1171F}, {0x11722, 0x11725}, {0x11727, 0x1172B}, {0x1182F, 0x11837}, @@ -295,15 +302,19 @@ static const struct mbinterval nonspacing[] = { {0x11F36, 0x11F3A}, {0x11F40, 0x11F40}, {0x11F42, 0x11F42}, + {0x11F5A, 0x11F5A}, {0x13430, 0x13440}, {0x13447, 0x13455}, + {0x1611E, 0x16129}, + {0x1612D, 0x1612F}, {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F4F, 0x16F4F}, {0x16F8F, 0x16F92}, {0x16FE4, 0x16FE4}, {0x1BC9D, 0x1BC9E}, - {0x1BCA0, 0x1CF46}, + {0x1BCA0, 0x1BCA3}, + {0x1CF00, 0x1CF46}, {0x1D167, 0x1D169}, {0x1D173, 0x1D182}, {0x1D185, 0x1D18B}, @@ -320,6 +331,7 @@ static const struct mbinterval nonspacing[] = { {0x1E2AE, 0x1E2AE}, {0x1E2EC, 0x1E2EF}, {0x1E4EC, 0x1E4EF}, + {0x1E5EE, 0x1E5EF}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, {0xE0001, 0xE01EF}, diff --git a/src/include/common/unicode_norm.h b/src/include/common/unicode_norm.h index 740b77a373e18..5bc3b79e78e08 100644 --- a/src/include/common/unicode_norm.h +++ b/src/include/common/unicode_norm.h @@ -5,7 +5,7 @@ * * These definitions are used by both frontend and backend code. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/common/unicode_norm.h * diff --git a/src/include/common/unicode_norm_hashfunc.h b/src/include/common/unicode_norm_hashfunc.h index 0913ea1c6587e..89e04c744d913 100644 --- a/src/include/common/unicode_norm_hashfunc.h +++ b/src/include/common/unicode_norm_hashfunc.h @@ -3,7 +3,7 @@ * unicode_norm_hashfunc.h * Perfect hash functions used for Unicode normalization * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_norm_hashfunc.h @@ -41,702 +41,662 @@ typedef struct static int Decomp_hash_func(const void *key) { - static const int16 h[13551] = { - 6102, 6103, 6104, 6105, 6106, 11163, 11164, 9247, - 3108, 32767, 32767, 5839, 5840, 11166, 3130, 3130, - 3130, 3130, -1926, -1926, 9274, 9275, 9276, 9277, - 9278, 473, 473, 6107, 0, 6110, 6111, -1569, - 9287, 9288, 9289, 9290, 9291, 9292, 9293, 9294, - 9295, 11077, 11078, 11079, 11080, 9300, 9301, 9302, - 9303, 9304, 9305, 9306, 9307, 9308, 9309, 9310, - 9311, 9312, 9313, 9314, 9315, 9316, 9317, 9318, - 9319, 9320, 4265, 4266, -1834, 4268, 4269, 4270, - 4271, 4272, 9329, 9330, 7413, 1274, 1274, 1274, - 5264, 1274, 9337, 1301, 1301, 1301, 1301, 8982, - -3754, 11381, 11382, 11383, 11384, 10049, 11386, 5605, - 5606, 5607, 5608, 5609, 5610, 5611, 5612, 465, - 465, 5617, 5618, 5619, 5620, 5621, 5622, 5623, - 465, 465, 465, 465, 465, 465, 465, 465, - 465, 465, 465, 465, 465, 465, 465, 465, - 465, 465, 465, 465, 465, 465, 465, 465, - 465, 465, 465, 465, 465, 465, 5256, 5256, - -10103,5256, 465, 465, 5256, 5256, 465, 5939, - 465, 465, 465, 465, 465, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -71, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -884, -884, -884, -884, -884, -884, - 0, -885, -885, -885, -885, -885, -885, 0, - 0, -886, -886, -886, -886, -886, -4378, 0, - -888, -888, 422, -888, -888, -888, 0, -7896, - -7896, -7896, 0, 0, 0, 0, 0, 1463, - 1463, 1463, 1463, 2951, 1464, 1464, -18469,1464, - 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, - 1215, 1216, 1464, 1464, 1464, 1464, 1464, 1464, - 1464, 1464, 0, 1465, 1465, 1465, 80, 1464, - 1464, 1464, 7565, 1464, 1464, 1464, 1464, 1464, - 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 32767, - 32767, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 32767, 112, 113, 114, 115, 116, - 117, 32767, 118, 119, 120, 121, 122, 123, - 124, 0, 0, 0, 126, 0, 0, 0, - 0, 0, 0, 0, 4145, 4146, 4147, 4148, - 4149, 4150, 4151, 4152, 4153, 4154, 0, 0, - 0, 0, 0, 0, 4155, 4156, 4157, 4158, - 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, - 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, - 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, - 4183, 4184, 4185, 4186, 4187, 4188, 4189, 179, - 180, 32767, 32767, 4192, 4193, 4194, 4195, 4196, - 4197, 4198, 4199, 4200, 4201, 4202, 4203, 32767, - 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, - 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, - 4220, 4221, 4222, 32767, 4223, 4224, 4225, 4226, - 32767, 32767, 32767, 32767, 4227, 4228, 4229, 32767, - -4545, -5662, -5662, -5662, -5662, -5662, -5662, -5662, - -5662, 4238, 4239, -5664, -5664, -5664, -5664, -5664, - -5664, -5664, -5664, 4248, 4249, 4250, 4251, 4252, - 4253, -6935, -1879, -1879, 4222, -1879, -1879, -1879, - -1879, -1879, -6935, -6935, 4265, 4266, 4267, 4268, - 4269, -4536, -4536, 1098, 1099, 1100, 1101, -6579, - 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, - 4285, 6067, 6068, 6069, 6070, 4290, 4291, 4292, - 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, - 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, - 4309, 4310, -745, -744, -6844, -742, -741, -740, - -739, -738, 4319, 4320, 2403, -3736, -3736, -3736, - 254, -3736, 4327, -3709, -3709, 4330, 0, 0, - 0, 0, 0, 0, 0, -2997, -2997, 2705, - 2705, 2705, 2705, 2705, 2705, 2705, 2705, 2705, - 0, 0, 0, 0, 0, 0, -4452, 0, - 0, 0, 0, 0, 2716, 0, 0, 0, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 1841, - 32767, 32767, 4710, 32767, 0, 32767, 32767, 0, + static const int16 h[13687] = { 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 32767, 32767, 32767, 32767, 0, + 0, 0, 0, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 32767, 1845, 32767, 32767, 32767, 32767, 32767, 0, - 0, 32767, 0, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 1850, 32767, 32767, 0, - 32767, 32767, 0, 32767, 1853, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 0, 32767, 0, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 0, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 0, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 0, 0, 32767, 32767, 0, - 0, 32767, 32767, 0, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 567, 567, 567, 567, -1649, -4447, - 32767, 32767, 566, 566, -1644, 566, 566, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, -1144, 0, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, - 0, 0, 0, 304, 305, 306, -2209, -2208, - 309, 2223, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, -550, 328, 329, 330, 331, 332, - 333, 334, 335, 0, 0, 0, 0, 340, - 341, 342, 343, -534, 345, 0, 0, 0, - 0, -6511, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, - 381, 382, 32767, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 4654, 410, 4655, - 412, 413, 414, 32767, 32767, 32767, 32767, 415, - 32767, 32767, 32767, 32767, 32767, 416, 32767, 32767, - 32767, -464, 32767, 32767, 32767, 32767, 32767, 418, - 419, 420, 421, 422, 423, 424, 32767, 425, - 32767, 426, 427, 428, 32767, 32767, 32767, 32767, - 4656, 4657, 4658, 32767, 32767, 32767, 32767, 4659, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 429, 430, 431, - 432, 433, 434, 435, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -2290, -2290, -2290, - -2290, -2290, 32767, -2291, -2291, -2291, -2291, -2291, - -2291, 2502, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 733, 733, 733, 32767, 732, - 732, 32767, 32767, 32767, 729, 32767, 0, 0, - 32767, 32767, 32767, 32767, -241, -241, 32767, -242, - 32767, 32767, 32767, -4550, 32767, 32767, 32767, 32767, - -249, -1737, -1737, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -1747, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -291, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 4660, 4661, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 3982, 3982, 3982, 32767, -1149, -1148, 32767, -1147, - 32767, 32767, 32767, -1146, 32767, 32767, 32767, 32767, - -1145, -1144, -1143, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, -4642, -1836, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, -1839, - -4651, -1838, -1838, 476, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 4708, 4709, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -4703, -1851, 32767, - 32767, 32767, 32767, 32767, 4710, 4711, 4712, 32767, - 32767, 32767, 32767, 32767, -1857, -4716, -1856, -4716, - 32767, 32767, -4718, -1855, 32767, 32767, -4720, -905, - -4720, -4720, -4720, -4720, 32767, 32767, -894, -893, - 4714, 4715, 4716, 1689, 8219, 4719, -4724, -1850, - -1850, 3912, 4721, 4722, 4723, 4724, -4724, -4724, - -4724, -4724, 32767, 32767, -4726, -4726, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - -1149, -1396, -1395, -1394, -1393, -1392, -1391, -1390, - -1389, 76, -1388, -1387, -1386, 0, -1383, -1382, - 32767, 32767, -1381, -1380, -1379, -1378, -1377, 0, + 0, 0, 0, 32767, 0, 32767, 0, 32767, + 0, 32767, 0, 32767, 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32767, 0, 0, 0, 0, 0, 0, - 32767, 0, 0, 0, 0, 0, 0, 0, - 125, 32767, 32767, 0, 127, 128, 129, 130, - 131, 132, 32767, 32767, -4013, -4013, -4013, -4013, - -4013, -4013, 32767, 32767, -4015, 140, 141, 142, - 143, 144, 145, -4009, -4009, -4009, -4009, -4009, - -4009, -4009, -4009, -4009, -4009, -4009, 32767, 32767, - -4011, -4011, -4011, -4011, -4011, -4011, -4011, -4011, - -4011, -4011, -4011, -4011, -4011, -4011, -4011, -4011, - -4011, -4011, -4011, -4011, -4011, -4011, 0, 0, - -2541, 32767, 32767, 32767, 32767, 32767, 512, 513, - 514, 515, 516, 517, -441, -441, 520, 521, - 522, 523, 524, 525, 526, 527, 528, 529, - 530, 531, 532, 533, 534, 535, 536, 537, - -4040, -4040, 540, 541, 542, 543, 544, 545, - 546, 547, 548, 549, 550, 551, 552, 4728, - 5846, 555, 556, 32767, 557, 32767, 558, 559, - 32767, 560, 561, 32767, 562, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -4065, -4065, -4065, -4065, - 7124, 2069, 2070, -4030, 2072, 2073, 2074, 2075, - 2076, 7133, 7134, -4065, -4065, -4065, -4065, -4065, - 4741, 4742, -891, -891, -891, 32767, 6789, -4066, - -4066, -4066, -4066, -4066, 32767, 32767, -4068, -4068, - -5849, -5849, -5849, -5849, -4068, -4068, -4068, -4068, - -4068, -4068, -4068, -4068, -4068, -4068, 5832, 5833, - -4070, -4070, -4070, -4070, -4070, -4070, -4070, -4070, - 5842, 5843, 5844, 5845, 5846, 5847, -5341, -285, - -285, 5816, -285, -285, -285, -285, -285, -5341, - -5341, 5859, 5860, 5861, 5862, 5863, -2942, -2942, - 2692, 2693, 2694, 2695, -4985, 5871, 5872, 5873, - 5874, 5875, 5876, 5877, 5878, 5879, 7661, 7662, - 7663, 7664, 5884, 5885, 5886, 5887, 5888, 5889, - 5890, 5891, 5892, 5893, 5894, 5895, 5896, 5897, - 5898, 5899, 5900, 5901, 5902, 5903, 5904, 849, - 850, -5250, 852, 853, 854, 855, 856, 5913, - 5914, 3997, -2142, -2142, 590, 591, 592, 5918, - -2118, -2118, -2118, -2118, 5563, -7173, 7962, 7963, - 7964, 7965, 6630, 7967, 2186, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 4034, 32767, - 32767, 32767, 5815, 5816, 5817, 5818, 5819, 5820, - 5821, 32767, 5822, 5823, 5824, 5825, 5826, 5827, - 5828, 5829, -272, -272, -272, -272, -272, -5328, - -5328, -3410, 2730, 2731, 0, 0, 0, -5325, - 2712, 2713, 2714, 2715, -4965, 7772, -3427, 32767, - -3428, -3428, -3428, 5378, 5379, 32767, 32767, 32767, - 32767, 32767, -3434, -3434, -3434, -3434, -3434, -3434, - -3434, -3434, -3434, -5215, -5215, -5215, -5215, -3434, - -3434, -3434, -3434, -3434, -3434, -3434, -3434, -3434, - -3434, -3434, -3434, -3434, -3434, -3434, -3434, -3434, - -3434, -3434, -3434, -3434, 1622, 1622, 7723, 1622, - 1622, 1622, 1622, 1622, -3434, -3434, -1516, 4624, - 4625, 4626, 637, 4628, -3434, 4603, 4604, 4605, - 4606, -3074, 9663, -5471, -5471, -5471, -5471, -4135, - 618, -4134, -4134, 32767, 32767, 621, 622, 32767, - 623, 624, 625, 626, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 4039, 32767, - 4040, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 5450, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -4019, 32767, 32767, 4042, -3994, -3994, -3994, - -3994, 3687, -9049, 32767, 32767, 6086, 6087, 4752, - 0, 4753, 4754, 32767, 32767, 0, 0, 32767, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 6862, - 6863, 6864, 6865, 1810, 1811, -4289, 1813, 1814, - 1815, 1816, 1817, 6874, 6875, 4958, -1181, -1181, - -1181, 2809, -1181, 6882, -1154, -1154, -1154, -1154, - 6527, -6209, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 82, 32767, 32767, 11618, 11619, 11620, 5919, 5920, - 5921, 5922, 32767, 32767, 786, 32767, 32767, 787, - 788, 789, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 790, 791, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, -1151, -1151, -1151, -1151, -1151, -1151, - -1151, -1400, -1399, 32767, 32767, 32767, 32767, 32767, - 792, 32767, 32767, 32767, -1159, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4666, - 4667, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 665, 666, - 667, 668, 32767, 669, 670, 671, 672, 673, - 674, 675, 676, 677, 32767, 678, 679, 680, - 32767, 681, 682, 683, 684, 685, -1578, -5751, - -5751, -5751, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - -1193, 32767, 32767, 32767, 32767, -5986, -5986, -5986, - -5986, -5986, -5986, -5986, -5986, -5986, -5986, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 686, 687, 688, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -174, 1314, -173, - -173, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32767, 32767, 32767, 32767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 32767, 0, 32767, 32767, 0, 0, 0, + 0, 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 689, 690, 691, 692, 693, 694, 695, 696, - 32767, 32767, 32767, 4671, 4672, 4673, 4674, 4675, - 4676, 4677, 4678, 4679, 4680, 4681, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -1552, -1552, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 697, 533, 533, 700, 701, 702, - 703, 704, 705, 706, 707, 708, 709, 710, - 711, 712, 713, 714, 715, 716, 717, 4682, - 6946, 2158, 4685, 721, 722, 723, 724, 725, - 726, 727, 728, 729, 730, 731, 732, 733, - 734, 735, 736, 737, 738, 739, 740, 741, - 742, 743, 744, 745, 746, 747, 748, 749, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 32767, 32767, 5923, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 4215, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 4181, 32767, 32767, -1922, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 4218, 32767, 32767, - 32767, 32767, 2986, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 4219, 32767, - 32767, 32767, 6001, 4221, 4222, 4223, 32767, 32767, - 32767, 4224, 4225, 4226, 4227, 4228, 4229, 4230, - 4231, 5925, 5926, 5927, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 1170, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 1, 32767, 2, 32767, 32767, 32767, 32767, 2792, + 32767, 32767, 4, 5, 6, 7, 32767, 32767, + 8, 9, 10, 32767, 11, 12, 13, 1734, + 14, -822, -822, 17, 18, 3020, 1739, 3021, + 3022, 3023, 1110, 24, 3024, 3025, 27, -3019, + 32767, 29, 30, 3026, 3027, 33, 34, 5016, + 1754, -4252, 36, 37, -4254, -4254, -4254, 32767, + 40, 41, 42, 43, 44, 45, 1912, 46, + 47, 48, 49, 50, 51, 52, 53, 54, + 1770, 55, 606, 57, 58, 59, 60, 1776, + 1777, 61, 62, 63, 64, 65, 32767, 66, + 32767, -1290, 6662, 3534, 3534, 3534, -172, 3322, + -170, -169, -168, -167, 3331, 1788, 0, 1790, + 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, + 1799, 3354, 1801, 1802, -964, -964, -964, -964, + 1807, 4976, 4976, 4976, 4976, 4976, 4976, 1814, + 1815, 4974, 2192, 11244, 2194, 11245, 0, 0, + 1605, 11251, 0, 11252, 0, 0, 3571, 3571, + -47, -47, 0, 0, -124, -123, -122, -4877, + -4877, -119, 32767, 32767, -118, 0, -116, -11032, + -114, -113, -112, 32767, 32767, -887, -110, -109, + -885, -107, 5320, 32767, 32767, -105, -882, 5328, + -102, -101, -100, -99, -4221, -4221, -4221, -95, + -94, -93, -92, -4221, -4221, -4221, -4221, 32767, + 32767, -4223, -4223, -4223, -4223, -4223, -4223, -4223, + -4223, -5481, -4223, -4223, -4223, -4223, -4223, -4223, + -4223, -4223, -4223, -4223, -4223, -4223, -4223, -4223, + -5495, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 1839, 1840, 1841, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 4663, 4664, 32767, + 32767, -4255, -4255, 32767, 0, 0, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -4268, -4268, 5881, 5882, 4722, 5884, 5885, 5886, + 5887, 32767, 5888, 5889, 5890, 5891, 5892, 5893, + 5894, 5895, 5896, 5897, 5898, 185, 186, -3976, + -3976, -3976, -3976, 6000, 6001, 6002, 6003, 6004, + 6005, 6006, 198, 5911, -3968, -3968, -826, -3968, + -3968, -3968, -3968, -3968, 208, 209, 32767, -3967, + -3967, -3032, -3967, -3967, -3030, 5922, 5923, -813, + 5925, 5926, 219, 220, 5929, 5930, 5931, 224, + -4290, -4290, -4290, -4290, -4290, -4290, -4290, 5940, + 5941, -4292, -4292, -4292, -4292, -4292, -4292, -4292, + -4292, 5950, 5951, 0, 0, 0, 0, 245, + 0, 0, 0, 0, 0, 0, 0, 253, + 254, 255, 256, -635, 258, 259, 260, 261, + 262, 263, 0, 265, 266, 267, 0, 0, + 268, 269, 32767, 32767, 32767, 32767, 32767, 32767, + 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 5981, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -901, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 767, 32767, 32767, - 32767, 32767, 32767, 32767, -5005, -4757, -4757, 32767, - 32767, 32767, -4760, -4760, 68, 68, 68, 32767, + 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 287, 32767, 32767, 32767, 58, 58, 32767, - 57, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 4689, 32767, 4690, 32767, 32767, 32767, 32767, -1717, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 4691, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 6903, - 4693, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 2763, + 975, 32767, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 289, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4382, 4382, 4382, 0, 7408, + 4383, 4383, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -4027, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -1642, -1641, -1640, -1639, + -1638, 3694, -1636, 3697, 3698, 3699, 0, 0, + -1627, 0, 0, -1622, -1621, 0, 6198, -1616, + -1615, -1614, -1613, 0, -1610, -1609, -1608, 0, + 0, 0, 0, 0, 0, 9558, -10546,0, + 6270, 6271, 6272, 6273, 6274, 6275, -3369, 6277, + 6545, 6279, 9583, 6281, -1402, -1402, 6284, 6285, + 304, 1947, 1947, 1947, 1947, 1947, -3384, 1947, + -3385, -3385, -3385, 315, 316, 1944, 318, 319, + 1942, 1942, 322, -5875, 1940, 1940, 1940, 1940, + 328, 1939, 1939, 1939, 332, 333, 334, 335, + 336, 337, -9220, 10885, 340, -5929, -5929, -5929, + -5929, -5929, -5929, 3716, -5929, -6196, -5929, -9232, + -5929, 1755, 1756, -5929, -5929, 53, -1589, -1588, + -1587, -1586, -1585, 3747, -1583, 3750, 3751, 3752, + 53, 53, -1574, 53, 53, -1569, -1568, 53, + 6251, -1563, -1562, -1561, -1560, 53, -1557, 5101, + -1556, 52, 52, 52, 52, 52, 52, 9610, + -10494,52, 6322, 6323, 6324, 6325, 6326, 6327, + -3317, 6329, 6597, 6331, 9635, 6333, -1350, -1350, + 6336, 6337, 356, 1999, 1999, 1999, 1999, 1999, + 0, 0, -2173, -3888, -3337, -5616, 0, 0, + 432, -2164, 1985, 0, 0, 0, 1980, 0, + 0, 0, 0, -1319, -4683, 1975, 368, 369, + 370, 371, 372, 0, -9185, 0, 374, -5895, + -5895, 0, 0, 0, 0, 864, 437, -16, + -16, 440, 32767, 441, 442, 443, -13, 445, + 446, 447, 32767, 32767, 32767, 32767, 32767, 6042, + 6043, 6044, 6045, 430, 431, 0, 2597, -1551, + 435, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 448, 449, 450, 32767, 451, + 452, 32767, 32767, 32767, 453, 0, 0, 0, + 0, 0, -428, 0, 454, 455, 0, 456, + 0, 0, 0, 457, 0, 0, 0, 0, + 458, 459, 460, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 3733, 3734, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 462, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 463, 464, 0, 465, + 0, 0, 0, 466, 0, 0, 0, 0, + 467, 0, 469, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5493, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5530, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -4339, -4339, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -7353, -7353, -7353, -5439, + 0, 0, -7353, -4354, 0, 0, 485, 486, + 487, 488, 489, 490, 0, 0, 491, 492, + 493, 494, -2541, -5542, 0, 0, -5544, -5544, + -3630, -2543, -5542, -5542, -2543, 504, -2543, -2543, + -2543, -5538, 0, 0, -2545, -2545, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 775, 32767, 32767, - 776, 32767, 32767, 32767, 32767, 32767, 777, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 778, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 779, 780, 781, 32767, 4694, - 4695, 4696, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 4697, 4698, 32767, - 32767, 32767, 4699, 4700, 32767, 32767, 32767, 2428, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 2995, 2996, 2997, 2998, 2999, - 2696, 2696, 2696, 5212, 5212, 2696, 783, 2696, - 2696, 2696, 2696, 2696, 2696, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 784, - 32767, 32767, 4701, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3448, + 3448, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3013, - 3014, 3015, 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 2139, 2140, -808, - 681, 682, 683, 684, 32767, 32767, 32767, 2633, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3016, - 685, 686, 936, 936, 689, 32767, 32767, 32767, - 32767, 32767, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, -5401, 701, 702, 703, - 704, 705, 706, 707, -779, 709, 80, -7189, - -7189, -7189, 0, 0, 32767, 0, 0, 0, - 0, 0, 32767, 0, 32767, 0, 0, 32767, - 0, 0, 32767, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, -3213, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 2540, 2540, + 2540, 2540, 2540, 0, 4830, 4831, -307, -307, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1310, 0, - 0, 0, 0, -7007, -7007, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6538, - 6539, 6540, 6541, 6542, 6543, 2371, 6545, 6546, - 6547, 6548, 6549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1693, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -796, -795, + -794, -793, -792, -791, 1061, 1062, 1063, 1064, + 1065, 0, 0, 0, 0, 0, 0, 0, + -785, -784, -783, -782, -4016, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -1097, -1096, -1095, -5270, -5270, -1094, -1093, + -1092, -2026, -1090, -1089, -2025, -2024, -765, -4241, + -10978,-10978,-5270, -5270, -10978,-10978,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3849, 0, + 0, 0, 0, 3854, 2311, 523, 2313, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -6893, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -6902, 0, 0, 0, - 0, -2600, 0, 1974, 1974, 0, 0, 0, - 0, -6912, -5556, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 3019, 0, 3020, - 3021, 3022, 0, 0, 3023, 3024, 0, 0, - 0, 0, 0, 2206, 3026, 0, 3027, 0, - 0, 0, 32767, 32767, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -3504, 0, 0, 0, -6893, 0, 0, 5606, - 0, 0, 0, 3028, -3501, 0, -3500, -3499, - 0, 808, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 32767, 0, 0, 0, 0, 0, 0, - 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1619, 1620, 32767, 32767, 1621, 1622, - 1623, 32767, 1624, 1625, 1626, 1627, 1628, 1629, - 0, 0, 1632, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 5994, 4146, 4146, 5997, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 2970, 32767, 32767, 32767, 32767, 1264, 1264, 1264, + 2215, 2216, 2217, 2218, 2219, 2220, 2221, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 5792, 32767, + 362, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 3029, 3030, 3031, 3032, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3033, - -1994, 810, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 811, - 1188, -1999, 814, 32767, 32767, 32767, 32767, 32767, + 32767, -3774, 32767, 32767, -3776, -3776, -3776, -3776, + -5034, -3776, -3776, 32767, 32767, -3778, -3778, -3778, + -3778, -3778, -3778, 32767, 32767, -3780, -3780, 32767, + -5053, -3781, -3781, -3781, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, -157, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 627, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 4695, 32767, + 32767, 2985, 2986, 32767, 32767, 32767, 32767, 628, + 629, 630, 631, 632, 633, -5911, 635, 636, + 637, 638, 639, 640, 641, 642, 643, 644, + 645, 646, 647, 648, 649, 650, 651, 652, + 653, 654, 32767, 32767, 32767, 32767, 32767, 32767, + -2208, 32767, 8339, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 4699, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4700, + 4701, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 2778, 32767, 32767, 32767, - 2775, 32767, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2863, -2863, -2863, -2863, - -2863, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 986, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 815, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 817, 818, 819, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2752, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4452, 0, - 4451, 0, 0, 0, 4448, 4732, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2022, 0, 32767, 32767, 32767, - 32767, -7994, 32767, 32767, 32767, 32767, -4824, -4824, - 2857, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, -8011, -8011, - -8011, -8011, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 5998, 0, 32767, + 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, + 32767, 0, 2987, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -1459, + -1459, -1459, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -1496, -2931, 32767, + 32767, 32767, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 664, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -251, -251, -251, -251, -251, -251, 4127, - 3239, 3239, 4549, 4549, 32767, 32767, 32767, 32767, - 32767, -3773, 4123, 4123, 4123, 4123, 4123, 5586, - 5586, 5586, 5586, 7074, 5587, 5587, -14346,5587, - 5587, 5587, 5587, 5587, 5587, 5587, 5587, 5587, - 5338, 0, 0, 0, 0, 0, 0, 0, - 32767, 0, 4131, 0, 0, 0, 0, 0, - 0, 828, 0, 0, 0, 0, 829, 830, - -3958, 0, 0, 8614, 4312, 0, 0, 0, - 0, 0, 4619, 0, 0, 0, 832, 833, - 834, 835, 32767, 32767, 32767, 32767, -215, -215, - 4094, 4630, -213, -213, -213, 32767, 32767, 32767, - 32767, 32767, -3542, -2653, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, -21505,-1572, -1572, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, + 32767, 32767, 4743, 32767, 32767, 32767, -3717, -3716, + 667, -6740, 32767, -3714, 670, 671, 672, 673, + 674, 675, 676, 677, 32767, 678, 679, 680, + 32767, 681, 4709, 683, 684, 685, 2990, 32767, + 32767, 32767, 2991, 2992, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -977, 32767, -2211, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 4386, 4386, -2210, - -2209, 32767, 4735, 4736, 32767, 32767, 32767, 32767, + 32767, 538, 32767, 32767, 32767, 32767, -1583, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -5881, 32767, 4018, 32767, - -5885, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 4020, 1382, 1382, 1382, 1382, 1382, - 5938, 32767, 32767, 32767, -2118, 32767, 32767, 32767, - 32767, 4022, 32767, 32767, 32767, 32767, -4783, 32767, - 32767, 32767, 32767, 850, 32767, 32767, 32767, 32767, + 32767, 686, -5583, -5583, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -1622, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 5806, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, - 4034, 4035, 4036, 4037, 4038, 32767, 32767, -1017, - -1016, -7116, -1014, -1013, 32767, -1012, -1011, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4710, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, -3993, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 4737, 302, 32767, 32767, 32767, - 32767, 303, 32767, 32767, 32767, 32767, 306, 32767, - 32767, 32767, 32767, 307, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 5939, - -4862, 5941, -388, -388, -388, -388, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -4874, 32767, 32767, + 4679, 4711, 4681, 4682, 4683, 4684, 4685, 4686, + 4687, 4688, 4689, 0, 0, 32767, 0, 32767, + 32767, 32767, 0, 5257, 32767, 32767, 32767, 6885, + 6619, 9923, 6621, -1062, -1062, 6624, 6625, 644, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 1637, 32767, 1637, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 4690, 4691, 4692, 4693, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 4015, -5630, -5897, -5630, -8933, -5630, + 2054, 2055, -5630, -5630, 352, -1290, -1289, -1288, + -1287, -1286, 714, 715, 2889, 4605, 4055, 6335, + 720, 721, 32767, 2886, -1262, 724, 725, 726, + -1253, 728, 729, 730, 731, 2051, 5416, -1241, + 367, 367, 367, 367, 367, 740, 9926, 742, + 369, 6639, 6640, 746, 747, 748, 749, -114, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, -8006, -8006, -2024, -3666, -3665, + -3664, -3663, -3662, 1670, -3660, 1673, 1674, 1675, + -2024, -2024, -3651, -2024, -2024, 32767, 32767, 32767, + 32767, 32767, -2866, 32767, 32767, -2865, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -2866, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -2866, 32767, + 32767, 32767, -4485, -4485, 758, 759, 32767, 32767, + 32767, 760, -2863, -2862, -2861, -2860, -2859, -2858, + -2857, 32767, 32767, 32767, 32767, 32767, 32767, 3014, + 3015, 3016, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 2516, 2516, 0, -1913, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 877, 0, - 0, 0, 0, 0, 0, 0, 0, 336, - 337, 338, 339, 0, 0, 0, 0, 878, - 0, 346, 347, 348, 349, 6861, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -4245, 0, -4244, 0, 0, 0, 32767, - 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, - 3833, 0, 32767, 32767, 32767, 881, 32767, 32767, - 32767, 0, 32767, 0, 0, 0, 0, 0, - 0, 0, 32767, 0, 32767, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 32767, 32767, 32767, 32767, 3017, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 2713, -2075, -2074, -2073, - -2072, -2071, -2070, 2720, -2068, -2067, -2066, 2724, - 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, - 2733, 2734, 2735, 2736, 2737, -2055, -2054, 2740, - -2052, 2742, 2743, 2744, 2745, 2746, 2747, -1630, - -741, -740, -2049, -2048, -738, -737, -1624, 6273, - 6274, -291, -290, -289, -288, -287, -286, -285, - -284, -283, -282, -281, -280, -279, -278, -277, - -276, 2772, 0, 0, 0, 0, 2779, -5015, - -269, -268, 0, 0, -2210, 0, 0, -262, - -261, -260, -259, -258, 0, 0, 0, 0, + 32767, 2180, 2180, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 768, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 769, 770, 771, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 32767, 32767, 32767, 32767, 32767, 772, 773, 32767, + 774, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3018, + 32767, 32767, 0, 32767, 4716, 4717, 32767, 32767, + 32767, 32767, 32767, 32767, 3019, 0, 3919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32767, 32767, 3643, + 32767, 32767, 3641, 32767, 32767, 0, 0, -3355, + 0, 0, 0, 0, 1998, 0, 0, 0, + 0, 0, 0, -3366, -3366, -3366, 0, 0, + -3368, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2040, 2040, - 2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3365, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 32767, - 32767, 32767, 32767, 32767, 32767, 0, 0, 0, - 0, 0, 0, 0, 0, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 677, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13799, 0, 0, 0, 9279, 2994, 32767, + 8461, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 1755, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 165, 166, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 3196, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -4700, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -3816, + 360, 361, 362, -572, 364, 365, -571, -570, + 689, -2787, -9524, -9524, -3816, -3816, -9524, -9524, + -9524, -3816, 699, 700, 701, 702, 703, 704, + 705, 706, 707, 8659, 5531, 5531, 5531, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, + 32767, 32767, 32767, 32767, 32767, 4746, 4747, 32767, + 4748, 32767, 32767, 32767, 4749, -507, -507, -507, + -507, -507, -507, -507, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -872, + 32767, 32767, 3030, 3031, 3032, 3033, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -3585, -3585, -3585, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3964, -6227, -1438, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 2824, 2825, 5791, 3454, - 3455, 3456, 32767, 10734, -115, 3459, 1375, 32767, - 32767, 3461, 10743, 5953, 3464, 3465, 3466, 3467, - 10751, 32767, 10753, 3470, 3471, 3472, 3473, 3474, - 3475, 32767, 3476, 5980, 10770, 5982, 7789, 7790, - 3482, 0, 2797, 0, 2798, 0, 2799, 0, - 2800, 0, 2801, 0, 2802, 0, 2803, 0, - 2804, 0, 0, 2806, 0, 2807, 32767, 2807, - 0, 0, 0, 32767, 0, 0, -376, 2812, - 0, 32767, 2812, 32767, 32767, 32767, 0, 2811, - 2811, 0, 2812, 2812, 0, 32767, 0, 0, + 0, 0, 0, 0, 0, -10784,-5076, -561, + -560, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2833, 0, 0, 0, 0, 3781, - 2837, 3782, 2837, 0, 3784, 3785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2850, 0, 2851, 0, 2852, 0, - 2853, 0, 2854, 0, 2855, 0, 2856, 0, - 2857, 0, 2858, 0, 2859, 0, 2860, 0, - 2861, 0, 0, 2863, 0, 2864, 0, 3815, - 0, 0, 0, 0, 0, 0, 3828, 3829, - 9436, 9437, 9438, 6411, 2873, 2873, 0, 2874, - 2874, 8636, 9445, 9446, 9447, 9448, 0, 0, + 2304, 2304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2897, 0, 0, 660, 7421, 7236, - 2899, 0, 0, 0, 2902, 816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 2013, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 5486, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 4750, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -3368, -3368, + 798, 32767, -372, -372, -372, -372, -372, -372, + 0, 1160, 0, 0, 0, 0, 0, 0, + 1161, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5714, 5714, 9877, 9878, 9879, 9880, 0, + 0, -97, -97, -97, -97, -97, 5712, 0, + 0, 9880, 6739, 0, 9882, 9883, 9884, 9885, + 5710, 0, 3820, 679, 0, 0, 9886, 9887, + 8951, 0, 0, 6737, 0, 0, 5708, 5708, + 0, 0, 0, 5708, 10223, 10224, 10225, 10226, + 10227, 10228, 10229, 0, 0, 10234, 10235, 10236, + 10237, 10238, 10239, 10240, 10241, 0, 0, 5952, + 5953, 5954, 5955, 5711, 5957, 5958, 5959, 5960, + 5961, 5962, 5963, 5711, 5711, 5711, 5711, 6603, + 5711, 5711, 5711, 5711, 5711, 5711, 5975, 5711, + 5711, 5711, 5979, 5980, 32767, 32767, 32767, 32767, + 803, 32767, 32767, 32767, 804, 32767, 32767, 32767, + 32767, 32767, 32767, 805, 806, 32767, 807, 808, + 32767, 809, 0, 5999, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 1389, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 840, 841, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 842, 32767, 843, 32767, 844, 32767, 32767, 32767, + 32767, 32767, 0, 0, 10606, 0, 845, 5378, + 0, 0, 0, 0, 1113, 1113, 1113, 1113, + 1113, 1113, 1113, 1113, 1113, -6838, -3709, -3708, + -3707, 0, -3493, 0, 0, 0, 0, -3497, + -1953, -164, -1953, -1953, 5407, 5408, -1955, -1955, + -1955, -1955, -1955, -1955, -3509, -1955, -1955, 812, + 813, 814, 815, -1955, -5123, -5122, -5121, -5120, + -5119, -5118, -14675,5430, -5115, -2332, -11383,-2332, + -11382,-136, -135, -1739, -11384,-11651,-11384,-131, + -130, -3700, -3699, -80, 5447, -126, -125, 0, + 0, 0, 4756, 4757, 0, 5456, -1715, 0, + -117, 0, 10917, 0, 0, 0, 5465, 5466, + 776, 0, 0, 777, 0, -5426, 5473, 5474, + 0, 778, -5431, 0, 0, 0, 0, 4123, + 4124, 4125, 0, 0, 0, 0, 4130, 4131, + 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, + 4140, 4141, 4142, 4143, 5402, 4145, 4146, 4147, + 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, + 4156, 4157, 4158, 5431, 5432, 4161, 4162, 4163, + 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, + 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, + 32767, 32767, 4180, 4181, 4182, 4183, 4184, 4185, + 4186, 4187, 4188, 4189, 4190, 4191, 4192, 6044, + 6045, 6046, 6047, 6048, 4198, 4199, 4200, 4201, + 4202, 4203, 4204, 4205, 4206, 4207, 4208, 974, + 4210, 11136, 3906, 3907, 3908, 3909, 3910, 3911, + 3912, 3913, 3914, 3915, 3916, 3917, 5988, 5989, + 0, 0, 3919, 3920, 3921, 3922, -6053, -6053, + -6053, -6053, -6053, -6053, -6053, -244, -5956, 3924, + 3925, 784, 3927, 3928, 3929, 3930, 3931, -244, + -244, 3932, 3933, 3934, 3000, 3936, 3937, 3001, + 3002, 4261, 785, -5952, -5952, -244, -244, -5952, + -5952, -5952, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -5739, -408, + -408, -408, 32767, 32767, 32767, 32767, 3724, 823, + 824, 32767, 32767, 32767, 32767, 32767, 32767, -421, + -2028, -2027, -2026, -2025, -2024, 517, -4312, -4312, + 827, 828, 522, 523, 524, 525, 526, 527, + 528, 529, 530, 531, 532, 533, 534, 535, + 536, 537, 538, 539, 540, 541, 542, 543, + 544, 545, 546, 547, 548, -3617, 550, 551, + 552, 553, 554, 555, 556, 32767, 557, 32767, + 558, 559, 32767, 560, 561, 32767, 562, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -1191, -1191, + -1191, -2792, 0, 0, 0, 0, -2791, -2790, + -4408, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -2791, -2790, + -2789, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 837, 838, 0, 0, -3001, 3038, + -3001, -3001, -3001, -1087, 0, -2999, -2999, 0, + 3047, 0, 0, 0, -2995, -2995, 0, 0, + 0, 0, 4287, 0, 0, 4292, 4293, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -550, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3918, 0, 0, 0, 0, 9976, 0, + 0, 0, 0, -6065, -6065, 0, 0, 0, + 0, 3142, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 935, 0, 0, 937, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9645, 0, -267, 0, -3303, 0, + 7684, 7685, 0, 0, 5982, 4340, 4341, 4342, + 4343, 4344, 9676, 4346, 4347, 9679, 9680, 4350, + 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, + 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, + 5974, 5974, 5974, 5974, 5974, 5974, 15532, -4572, + 5974, 3192, 12244, 3194, 12245, 12246, 12247, 2603, + 12249, 12517, 12251, 999, 12252, 4569, 4569, 12255, + 12256, 6275, 7918, 7918, 7918, 7918, 7918, 2587, + 7918, 2586, 2586, 2586, 6286, 6287, 7915, 6289, + 6290, 7913, 7913, 6293, 96, 7911, 7911, 7911, + 7911, 6299, 7910, 1253, 7911, 6304, 6305, 6306, + 6307, 6308, 6309, -3248, 16857, 6312, 43, 43, + 43, 43, 43, 43, 9688, 43, -224, 43, + -3260, 43, 7727, 7728, 43, 43, 6025, 1253, + 6234, 1253, 6384, 6385, 10526, -3272, 1253, 6388, + 10531, 1253, 1253, 1253, 1253, 6392, 6393, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6053, 6054, 6055, + 6056, 6057, 6058, 32767, 6059, 6060, 6061, 6062, + 32767, 6063, 32767, 6064, 32767, 32767, 32767, 4761, + 32767, 32767, 6065, 32767, 4762, 4763, 32767, 9404, + 32767, 6067, 4764, 6068, 32767, 6069, 6070, 6071, + 32767, 6072, 6073, 32767, 6074, 32767, 32767, 6075, + 32767, 6076, 32767, 6077, 32767, 6078, 32767, 6079, + 32767, 4374, 4374, 32767, 4373, 32767, 32767, 5324, + 5325, 5326, 5327, 32767, 6087, 6088, 6089, 6090, + 6091, 3057, 6093, 32767, 6094, 4376, -4013, 4376, + 32767, 4375, 4375, 4375, 4375, 32767, 4374, 32767, + 4373, 6104, 6105, 6106, 6107, 6108, 6109, 6110, + 6111, -3652, 881, -645, -645, -1903, 6116, 6117, + 6118, 4399, 4400, 4401, 6122, 6123, 3567, 3567, + 4406, 6127, 7410, 6129, 32767, 32767, 32767, 32767, + 32767, 7409, 7410, 4412, 32767, 6133, 4414, 4415, + 6136, 6137, 32767, 4420, 9402, 6140, 134, 134, + 13933, 134, 134, 134, 9413, 4429, 6149, 4432, + 6151, 4435, 6153, 6304, 6305, 6306, 6307, 6308, + 6309, 6310, 6311, 6312, 6313, 6314, 1068, 6316, + 5378, 6318, 5379, 6320, 803, 6322, -2232, 6324, + 6325, 6326, 1074, 6328, 6329, 6330, 6331, 6332, + 6333, 6334, 6335, 6336, 6337, 6338, 6339, 6340, + 6341, 6342, 6343, 6344, 6345, 6346, 6347, 6348, + 6349, 6350, 6351, 6352, 6353, 6354, 6355, 6356, + 6357, 6358, 6359, 6360, 5417, 6362, 6363, 6364, + 6365, 6366, 6367, 5423, 6369, 5424, 6371, 6372, + 5426, 5426, 6375, 5427, 5427, 6378, 6379, 6380, + 6381, 6382, 6383, 6384, 6385, 6386, 6387, 6388, + 6389, 6390, 6391, 6392, 6393, 6394, 6395, 6396, + 6397, 6398, 6399, 6400, 6401, 6402, 6403, 6404, + 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, + 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, + 6421, 6422, 7182, 5465, 6425, 6426, 6427, 6428, + 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, + 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, + 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, + 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, + 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6468, + 6469, 6470, 6471, 6472, 6473, 6474, 6475, 6476, + 6477, 6478, 5519, 5519, 6481, 6482, 6483, 6484, + 6485, 6486, 6487, 6488, 6489, 6490, 6491, 6492, + 6493, 6494, 6495, 6496, 6497, 6498, 6499, 6500, + 6501, 6502, 6503, 6504, 6505, 6506, 6507, 6508, + 6509, 6510, 6511, 6512, 6513, 6514, 6515, 6516, + 6517, 6518, 6519, 6520, 6521, 6522, 6523, 6524, + 6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, + 6533, 1330, 6535, 6536, 6537, 6538, 5577, 6540, + 6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, + 6549, 6550, 5588, 5588, 6553, 6554, 6555, 6556, + 32767, 6557, 1728, 1728, 6867, 6868, 6562, 6563, + 6564, 6565, 6566, 6567, 6568, 6569, 6570, 6571, + 6572, 6573, 6574, 6575, 6576, 6577, 6578, 6579, + 6580, 6581, 6582, 6583, 6584, 6585, 6586, 6587, + 6588, 2423, 6590, 6591, 6592, 6593, 6594, 6595, + 6596, 6597, 6598, 6599, 6600, 6601, 6602, 6603, + 6604, 6605, 6606, 6607, 6608, 6609, 6610, 6611, + 6612, 6613, 6614, 6615, 6616, 6617, 6618, 6619, + 6620, 6621, 6622, 6623, 6624, 6625, 6626, 6627, + 6628, 6629, 6630, 6631, 6632, 6633, 6634, 6635, + 6636, 6637, 6638, 6639, 6640, 6641, 6642, 6643, + 6644, 6645, 6646, 6647, 6648, 6649, 6650, 6651, + 6652, 6653, 6654, 6655, 6656, 6657, 6658, 6659, + 6660, 6661, 6693, 6663, 6664, 6665, 6666, 6667, + 6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, + 6676, 6677, 6678, 6679, 7476, 7476, 7476, 7476, + 7476, 7476, 5625, 5625, 5625, 5625, 5625, 6691, + 6692, 6693, 6694, 6695, 6696, 6697, 7483, 7483, + 7483, 7483, 10718, 6703, 6704, 6705, 6706, 6707, + 6708, 6709, 6710, 6711, 6712, 6713, 6714, 6715, + 6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, + 6724, 6725, 6726, 6727, 6728, 6729, 6730, 6731, + 6732, 6733, 6734, 6735, 6736, 6737, 6738, 7836, + 7836, 7836, 12012, 12013, 7838, 7838, 7838, 8773, + 7838, 7838, 8775, 8775, 7517, 10994, 17732, 17733, + 12026, 12027, 17736, 17737, 6760, 6761, 6762, 6763, + 6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, + 6772, 6773, 6774, 6775, 2927, 6777, 6778, 6779, + 6780, 2927, 4471, 6260, 4471, 6785, 6786, 6787, + 6788, 6789, 6790, 6791, 6792, 6793, 6794, 6795, + 6796, 6797, 6798, 6799, 6800, 6801, 6802, 6803, + 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, + 6812, 32767, 3411, 5540, 5541, 3411, 12221, 3411, + 3411, 3411, 3411, 5548, 5549, 5550, 5551, 5552, + 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, + 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, + 32767, 32767, 32767, 32767, 32767, 32767, 3915, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 6155, 6156, 6157, 6158, 6159, + 6160, 6161, 6162, 6163, 6164, 6165, 32767, 32767, + 32767, 32767, 32767, 6166, 6167, 6168, 6169, 6170, + 6171, 6172, 6173, 6174, 6175, 6176, 6177, 6178, + 6179, 6180, 4615, 4616, 4617, 4618, 4619, 6186, + 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, + 6195, 6196, 32767, 6197, 6198, 6199, 6200, 6201, + 7637, 4495, 4495, 6205, 4052, 4052, 6208, 6209, + 6210, 6211, 6212, 6213, 6214, 6215, 6216, 6217, + 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6225, + 6226, 6227, 6228, 32767, 32767, 0, 0, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 6229, 6230, 6231, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 6232, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 1009, -417, -417, -417, 32767, 3553, -9183, 5952, - 5953, 5954, 5955, 4620, 5957, 176, 177, 178, - 179, 180, 181, 182, 183, -4964, -4964, 188, - 189, 190, 191, 192, 193, 194, -4964, -4964, - 32767, -4965, -4965, 32767, -4966, 32767, 32767, -4968, - 32767, -4969, -4969, -4969, -4969, -4969, -4969, -4969, - -4969, -4969, -4969, 32767, -4970, -4970, -4970, -4970, - 32767, -4971, 32767, -4972, 32767, 32767, 32767, 32767, - 32767, 32767, -187, 32767, 32767, 32767, 32767, -4980, - 32767, -4981, 32767, -4982, 32767, -194, -194, -194, - 32767, -195, -195, 32767, -196, 32767, 32767, -4987, - 32767, -4988, 32767, -4989, 32767, -4990, 32767, -4991, - 32767, -4992, -4992, 0, -4993, 32767, 32767, -4995, - -202, -4995, -4995, 32767, -4996, -4996, -4996, -618, - -1506, -1506, -196, 32767, -1506, -1506, -618, -8514, - 32767, -8515, -619, -619, -619, 32767, 6034, 32767, - -455, -455, -455, -455, -455, -455, -455, -455, - -455, -455, 32767, -456, -456, -456, -456, -456, - -456, -456, -456, -456, -456, -456, -456, -456, - -456, -456, -456, -456, 32767, 32767, 32767, 32767, - 32767, -461, -461, -461, 32767, -7469, -462, -462, - -462, -462, 32767, -463, -463, -463, -463, -463, - 6075, 6076, 6077, 6078, 6079, 6080, 1908, 6082, - 6083, 6084, 6085, 6086, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 884, 885, 886, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 5994, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 6233, 6234, 6235, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 6236, 6237, 6238, 6239, + 6240, 6241, 6242, 6243, 6244, 6245, 6246, 6247, + 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6255, + 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, + 6264, 6265, 6266, 6267, 6268, 6269, 6270, 6271, + 6272, 6273, 6274, 6275, 6276, 6277, 6278, 6279, + 32767, 32767, 32767, 32767, 6280, 6281, 6282, 6283, + 6284, 6285, 6286, 6287, 6288, 4770, 32767, 4771, + 4772, 32767, 32767, 32767, 6289, 6290, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -5160, 2071, + 2071, 2071, 2071, 32767, 2070, 2070, 2070, 2070, + 2070, 2070, 2070, 0, 0, 6236, 6237, 2075, + 2075, 2075, 2075, 12051, 12052, 12053, 12054, 12055, + 12056, 12057, 6249, 11962, 2083, 2083, 5225, 2083, + 2083, 2083, 2083, 2083, 6259, 6260, 2085, 2085, + 2085, 3020, 2085, 2085, 3022, 3022, 32767, 5240, + 11978, 11979, 6272, 6273, 11982, 11983, 11984, 6277, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 4773, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -9650, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 4751, 32767, 32767, -6842, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -750,428 +710,137 @@ Decomp_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 415, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, -2468, -2468, + -2468, -2468, -2468, -2468, -2468, -2468, -2468, -2468, + -2468, -2468, -2468, -2468, -2468, -2468, -2468, -2468, + 2089, 2090, 2091, -2465, -2465, -2465, -2465, -2465, + -2465, 2098, 2099, -2463, -2463, -2463, -2463, -2463, + -2463, 2106, 2107, -2461, -2461, -2461, -2461, -2461, + -2461, 0, 0, -2459, -2459, -2459, 2119, 2120, + 2121, -2456, 2123, 2124, 2125, 2126, 2127, 2128, + 0, 0, 2131, -6678, 2133, 2134, 2135, 2136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2158, 2159, 2160, + 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, + 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, + 2177, 2178, 2179, 2180, 2181, -2412, -2412, -2412, + -2412, -2412, 2187, 2188, 2025, 2190, 2191, 2192, + 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, + 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, + 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, + 2217, 2218, 2219, 2220, 2221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 3990, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2002, 2002, 2002, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4118, 0, - 0, 0, 0, 0, 0, 0, 4126, 0, - 0, 2728, 0, 0, 32767, 32767, 32767, 32767, - 32767, 0, 5928, 5929, 5930, 5931, 0, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 4755, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 4132, 4133, 4134, 4135, - 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, - 4144, 32767, 32767, 886, 5880, 32767, 32767, 32767, - 32767, 32767, 32767, 1132, 1132, 1132, 1132, 32767, - 6280, 1129, 1129, 32767, 1128, 1128, 1128, 1128, - 6287, 6288, 6289, 6290, 6291, 6292, 6293, 32767, - 6294, 6295, 32767, 1343, 6296, 6297, 6298, 6299, - 6300, 32767, 32767, 6301, 6302, 6303, 32767, 6304, - 32767, 6305, 32767, 6306, 32767, 6307, 1517, 1518, - 16878, 32767, 6311, 6312, 1522, 32767, 6314, 1524, - 1525, 6315, 6316, 6317, 6318, 32767, 6319, 1531, - 1532, 1533, 1534, 1535, 32767, 32767, 32767, 32767, - 1536, 6326, 6327, 6328, 6329, 32767, 0, 32767, - 0, 10802, 0, 6330, 6331, 6332, 6333, 1541, - 1542, 6336, 1544, 6338, 6339, 6340, 6341, 6342, - 6343, 1966, 2855, 2856, 1547, 1548, 2858, 2859, - 1972, 9869, 9870, 9871, 1976, 1977, 1978, 1979, - 1980, 518, 519, 520, 521, -966, 522, 523, - 20457, 525, 526, 527, 528, 529, 530, 531, - 532, 533, 783, 6122, 6123, 6124, 6125, 6126, - 6127, 6128, 32767, 6129, 1999, 6131, 6132, 6133, - 6134, 6135, 6136, 5309, 6138, 6139, 6140, 6141, - 5313, 5313, 10102, 6145, 6146, -2467, 1836, 6149, - 6150, 6151, 6152, 6153, 1535, 6155, 6156, 6157, - 5326, 5326, 5326, 32767, 32767, 32767, 32767, 32767, - 32767, 1837, 32767, 1741, 32767, 32767, 32767, 32767, - 10538, 10539, 9184, 9185, 6237, 7726, 7727, 7728, - 7729, 7730, 6243, 7731, 7732, 27666, 7734, 7735, - 7736, 7737, 7738, 7739, 7740, 7741, 7742, 7992, - 7992, 7745, 7746, 7747, 7748, 7749, 7750, 7751, - 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, - 7760, 1660, 7762, 7763, 7764, 7765, 7766, 7767, - 7768, 6282, 7770, 7141, -128, -128, -128, 7768, - 7768, 7768, 4803, 7141, 7141, 7141, 5529, -136, - 10714, 7141, 9226, -10707,4652, 7141, -140, 4651, - 7141, 7141, 7141, 7141, -142, 5529, -143, 7141, - 7141, 7141, 6315, 7140, 7140, 6318, 6319, 4635, - 6321, 6322, 6323, 6324, 6325, 6326, 6327, 6328, - 6329, 6330, 9168, 9169, 9170, 15325, 15078, 15079, - 9174, 9175, 9176, 6539, 9178, 9179, 9180, 6344, - 6345, 6346, 6347, 8761, 6349, 6350, 6351, 9193, - 9194, 9195, 4634, 4634, 9196, 9197, 9198, -1165, - -1165, -1165, 4937, 6364, 6365, 6366, 10077, 2397, - 15134, 0, 0, 0, 0, 1336, 0, 5782, - 5782, 5782, 5782, 5782, 5782, 5782, 5782, 10930, - 10931, 5780, 5780, 5780, 5780, 5780, 5780, 5780, - 10939, 10940, 10941, 10942, 10943, 10944, 10945, 10946, - 10947, 10948, 10949, 10950, 10951, 10952, 10953, 10954, - 10955, 10956, 10957, 10958, 10959, 10960, 10961, 10962, - 10963, 10964, 10965, 10966, 10967, 10968, 6178, 6179, - 21539, 6181, 10973, 10974, 6184, 6185, 10977, 6187, - 6188, 10978, 10979, 10980, 10981, 10982, 10983, 6195, - 6196, 6197, 6198, 6199, 6200, 10990, 6202, 6203, - 6204, 10994, 10995, 10996, 10997, 10998, 10999, 11000, - 11001, 11002, 11003, 11004, 11005, 11006, 11007, 6215, - 6216, 11010, 6218, 11012, 11013, 11014, 11015, 11016, - 11017, 6640, 7529, 7530, 6221, 6222, 7532, 7533, - 6646, 14543, 14544, 14545, 6650, 6651, 6652, 6653, - 0, 6489, 6490, 6491, 6492, 6493, 6494, 6495, - 6496, 6497, 6498, 6499, 6500, 6501, 6502, 6503, - 6504, 6505, 6506, 6507, 6508, 6509, 6510, 6511, - 6512, 6513, 6514, 6515, 6516, 6517, 6518, 6519, - 6520, 5211, 6522, 6523, 6524, 6525, 13533, 13534, - 6528, 6529, 6530, 6531, 6532, 6533, 6534, 6535, - 6536, 6537, 0, 0, 0, 0, 0, 0, - 4173, 0, 0, 0, 0, 0, 6550, 6551, - 6552, 6553, 6554, 6555, 6556, 6557, 6558, 6559, - 6560, 6561, 6562, 6563, 6564, 6565, 4873, 6567, - 6568, 6569, 6570, 6571, 6572, 6573, 6574, 6575, - 6576, 6577, 6578, 6579, 6580, 6581, 6582, 6583, - 6584, 6585, 6586, 6587, 6588, 6589, 6590, 6591, - 6592, 6593, 6594, 6595, 6596, 6597, 6598, 6599, - 6600, 6601, 6602, 6603, 6604, 6605, 6606, 6607, - 6608, 6609, 6610, 6611, 6612, 6613, 6614, 6615, - 6616, 6617, 6618, 6619, 6620, 6621, 6622, 6623, - 6624, 6625, 6626, 6627, 6628, 6629, 6630, 6631, - 6632, 6633, 6634, 6635, 6636, 6637, 6638, 6639, - 6640, 6641, 6642, 6643, 6644, 6645, 6646, 6647, - 6648, 6649, 6650, 6651, 6652, 6653, 6654, 6655, - 6656, 6657, 6658, 13552, 6660, 6661, 6662, 6663, - 6664, 6665, 6666, 6667, 6668, 6669, 6670, 13573, - 6672, 6673, 6674, 6675, 9276, 6677, 4704, 4705, - 6680, 6681, 6682, 6683, 13596, 12241, 6686, 6687, - 6688, 6689, 6690, 6691, 6692, 6693, 6694, 6695, - 6696, 6697, 6698, 6699, 6700, 6701, 6702, 6703, - 6704, 6705, 6706, 6707, 6708, 6709, 6710, 6711, - 6712, 6713, 6714, 6715, 6716, 6717, 6718, 6719, - 6720, 6721, 6722, 6723, 6724, 6725, 6726, 6727, - 3709, 6729, 3710, 3710, 3710, 6733, 6734, 3712, - 3712, 6737, 6738, 6739, 6740, 6741, 4536, 3717, - 6744, 32767, 6745, 6746, 6747, 6748, 6749, 6750, - 6751, 6752, 6753, 6754, 6755, 6756, 6757, 6758, - 6759, 6760, 6761, 6762, 6763, 6764, 6765, 6766, - 6767, 6768, 6769, -2005, 6771, -3121, -3121, -3121, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 895, 896, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 4706, 4707, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 897, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 898, - 899, 900, 901, 902, 903, 904, 905, 32767, - 32767, 906, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 1, 32767, 2, 32767, 32767, 32767, 32767, 3, - 32767, 32767, 4, 5, 6, 7, 32767, 32767, - 8, 9, 10, 32767, 11, 83, 13, 32767, - 14, 15, 16, 17, 18, 19, 32767, 20, - 21, 22, 907, 908, 909, 910, 911, 912, - 913, 914, 915, 916, 917, 918, 919, 920, - 32767, 921, 922, 923, 924, 925, 926, 927, - 928, 929, -380, 931, 932, 933, 934, 7942, - 7943, 7944, 49, 50, 51, 52, 53, -1409, - 32767, -1408, -1407, -2894, -1406, -1405, 18529, 3171, - 32767, -1403, -1402, -1401, -1400, -1399, 32767, -1398, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 683, 32767, 7976, 32767, 4994, 32767, 686, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 937, 0, -3182, 0, -3183, 0, -3184, - 32767, 941, 32767, 32767, 32767, -3188, 0, 32767, - 0, 0, 32767, 0, 0, 32767, 0, 0, - 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 1566, 1566, + 1566, 1566, 1566, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32767, 0, + 0, 0, 0, 0, -1435, 1708, 1709, 0, + 2154, 2155, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 943, - 32767, 0, 32767, 32767, 32767, 32767, 944, 0, - 945, 0, 32767, 946, 947, 32767, 948, 949, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 32767, 0, 32767, 0, 32767, 950, 951, - 952, 953, 954, 955, 956, 957, 958, 32767, - 6565, 6566, 32767, 0, 0, 32767, 0, 0, - 32767, 6570, 6571, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 0, 32767, 32767, 4774, 4775, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 32767, 32767, -2239, 4522, 4337, 0, - 32767, 32767, 32767, 0, -2086, 32767, 32767, 0, - 0, 0, 0, 0, 0, 959, 960, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4578, 4579, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -4175, -5292, 0, 0, 32767, 0, 32767, 0, - 0, 32767, 0, 0, 32767, 0, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 961, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 962, 963, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 32767, 32767, 32767, 32767, 0, 0, 0, 0, + 0, 0, 0, 0, -2552, 0, 0, 32767, + 0, 32767, 32767, 32767, 1551, 293, 3770, 32767, + 32767, 32767, 32767, 0, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 0, + 0, 32767, 0, 0, 32767, 32767, 32767, 32767, + 0, 32767, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, -4309, -4309, 0, 32767, + 0, -4310, -4577, -4310, -7613, -4310, 3374, 3375, + -4310, -4310, 1672, -3100, 1881, -3100, 2031, 2032, + 6173, -7625, -3100, 2035, 6178, -3100, -3100, -3100, + -3100, 2039, 2040, 32767, 0, -4353, -4353, 0, + -4352, 0, 0, -4350, 0, -4349, -4349, -4349, + -4349, 32767, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 32767, 0, 0, 32767, 0, 0, + 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 964, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 0, 0, 0, + 0, 951, 952, 953, 954, 955, 956, 957, + 1717, 0, 32767, 32767, 32767, -1317, 32767, 32767, + 32767, 0, -8389, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 887, 888, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 32767, -5009, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 0, 0, 0, - 32767, 32767, -3913, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 5520, 32767, 32767, 32767, 32767, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 965, 966, 967, 32767, - 968, 969, 970, 971, 972, 973, 974, 975, - 976, 977, 978, 979, 980, 32767, 981, 982, - 983, 984, 985, 986, 987, 32767, 32767, 32767, - 32767, 988, 32767, 32767, 32767, 32767, 32767, 32767, - 989, 32767, 32767, 32767, -4941, 991, 32767, 32767, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 992, 993, 994, 32767, 995, 996, 997, - 998, 999, 1000, 1001, -3143, -3143, -3143, -3143, - 32767, -3144, -3144, -3144, -3144, -3144, 1011, 1012, - 1013, 1014, 1015, 1016, -3138, -3138, -3138, -3138, - -3138, -3138, -3138, 32767, -3139, -3139, -3139, -3139, - -3139, -3139, -3139, -3139, -3139, -3139, -3139, -3139, - -3139, -3139, -3139, -3139, -3139, -3139, -3139, -3139, - -3139, -3139, -3139, -3139, -3139, -3139, -3139, 872, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 3049, 3049, -3150, 3049, 3049, - 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049, - 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049, - 3049, 3049, 3049, 3049, 3049, 0, 0, 0, - 0, 0, 0, 0, 0, 3057, 5596, 5597, - 5598, 6716, 6717, 6718, 6719, 6720, 6721, 6722, - 6723, -3176, -3176, 6728, 6729, 6730, 6731, 6732, - 6733, 6734, 6735, -3176, -3176, -3176, -3176, -3176, - -3176, 8013, 2958, 2959, -3141, 2961, 2962, 2963, - 2964, 2965, 8022, 8023, -3176, -3176, -3176, -3176, - -3176, 5630, 5631, -2, -2, -2, -2, 7679, - -3176, -3176, -3176, -3176, -3176, -3176, -3176, -3176, - -3176, -4957, -4957, -4957, -4957, -3176, -3176, -3176, - -3176, -3176, -3176, -3176, -3176, -3176, -3176, -3176, - -3176, -3176, -3176, -3176, -3176, -3176, -3176, -3176, - -3176, -3176, 1880, 1880, 7981, 1880, 1880, 1880, - 1880, 1880, -3176, -3176, -1258, 4882, 4883, 4884, - 895, 4886, -3176, 4861, 4862, 4863, 4864, -2816, - 9921, -5213, -5213, -5213, -5213, -3877, -5213, 569, - 569, 569, 569, 569, 569, 569, 569, 5717, - 5718, 567, 567, 567, 567, 567, 567, 567, - 5726, 5727, 5728, 5729, 5730, 5731, 5732, 5733, - 5734, 5735, 5736, 5737, 5738, 5739, 5740, 5741, - 5742, 5743, 5744, 5745, 5746, 5747, 5748, 5749, - 5750, 5751, 5752, 5753, 5754, 5755, 965, 966, - 16326, 968, 5760, 5761, 971, 972, 5764, 974, - 975, 5765, 5766, 5767, 5768, 5769, 5770, 982, - 983, 984, 985, 986, 987, 5777, 989, 990, - 991, 5781, 5782, 5783, 5784, 5785, 5786, 5787, - 5788, 5789, 5790, 5791, 5792, 5793, 5794, 1002, - 1003, 5797, 1005, 5799, 5800, 5801, 5802, 5803, - 5804, 1427, 2316, 2317, 1008, 1009, 2319, 2320, - 1433, 9330, 9331, 9332, 1437, 1438, 1439, 1440, - 1441, -21, -20, -19, -18, -1505, -17, -16, - 19918, -14, -13, -12, -11, -10, -9, -8, - -7, -6, 244, 244, -3, -2, -1, 0, - 1, 2, 3, 4, 1469, 5, 6, 7, - 8, 9, 32767, 32767, 32767, 32767, 10, 11, - 12, 13, 5070, 5071, 3154, -2985, 1318, 1319, - 1320, -2988, 5075, -2961, -2961, -2961, -2961, 1327, - 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, - 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, - 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, - 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, - 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, - 7522, 7275, 7276, 1371, 1372, 1373, -1264, 1375, - 1376, 1377, 1378, 1379, 1380, 1381, 1382, 957, - -14402,957, 1386, 1387, 1388, 1389, 1390, 1391, - 1392, 1393, -8970, -8970, -8970, 1397, 1398, 948, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 1400, - 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, - 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, - 1417, 1418, 1419, 1420, 1421, 32767, 32767, 1422, - 1423, 1424, 1425, 1426, 1427, 32767, 32767, 1428, - 1429, 1430, 1431, 8325, 1433, 1434, 1435, 1436, - 1437, 1438, 1439, 1440, 1441, 1442, 1443, 8346, - 1445, 1446, 1447, 1448, 4049, 1450, -523, -522, - 1453, 1454, 1455, 1456, 8369, 7014, 1459, 1460, - 1461, 1462, 1463, 1464, 1465, 32767, 32767, 1466, - 1467, 1468, 1469, 1470, 1471, 32767, 32767, 1472, - 1473, 1474, 1475, 1476, 1477, 1478, 1479, 32767, - 1480, 32767, 1481, 32767, 1482, 32767, 1483, 1484, - 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, - -1526, 1494, -1525, -1525, -1525, 1498, 1499, -1523, - -1523, 1502, 1503, 1504, 1505, 1506, -699, -1518, - 1509, -1517, 1511, 1512, 1513, 32767, 32767, 1514, - 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, - 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, - 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, - 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, - 1547, 1548, 1549, 5054, 1551, 1552, 1553, 8447, - 1555, 1556, -4049, 1558, 1559, 1560, -1467, 5063, - 1563, 5064, 5064, 1566, 32767, 1567, 1568, 1569, - 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, - 1578, 1579, 1580, 1581, 32767, 1582, 1583, 1584, - 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, - 1593, 1594, 1595, 32767, 32767, 1596, 1597, 1598, - 1599, 1600, 1601, 32767, 1602, 1603, 1604, 1605, - 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, - 1614, 1615, 1616, 1617, 1618, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1630, 1631, 0, 32767, -5702, - -5702, -5702, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 0, 32767, 0, - 32767, -7163, 0, 0, 32767, 32767, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -7269, -7269, -7269, 627, - 627, 627, -2338, 0, 0, 0, -1612, -7277, - 3573, 0, 2085, -17848,-2489, 0, -7281, -2490, - 0, 0, 0, 0, -7283, -1612, -7284, 0, - 0, 0, 0, 0, 0, 0, 0, -2503, - -7292, -2503, -4309, -4309, 0, 536, -4307, -4307, - -4307, -4307, 677, -4306, -4306, -4306, -4306, -7305, - 0, -4306, -4306, 32767, 32767, -4308, -4308, -7312, - -4307, 690, -4306, -6530, 0, -4306, 0, 0, - -4306, 0, -4305, -4305, -4305, -4305, -4305, -4305, - -2949, -2949, 0, -1488, -1488, -1488, -1488, -1488, - 0, -1487, -1487, -21420,-1487, -1487, -1487, -1487, - -1487, -1487, -1487, -1487, -1487, -1736, -1735, -1487, - -1487, -1487, -1487, -1487, -1487, -1487, -1487, -1487, - -1487, -1487, -1487, -1487, -1487, -1487, -1487, 4614, - -1487, -1487, -1487, -1487, -1487, -1487, -1487, 0, - -1487, -857, 6413, 6414, 6415, -1480, -1479, -1478, - 1488, -849, -848, -847, 766, 6432, -4417, -843, - -2927, 17007, 1649, -839, 6443, 1653, -836, -835, - -834, -833, 6451, 781, 6454, -829, -828, -827, - 0, -824, -823, 0, 0, 1685, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -2837, -2837, -2837, -8991, -8743, -8743, -2837, -2837, - -2837, -199, -2837, -2837, -2837, 0, 0, 0, - 0, -2413, 0, 0, 0, -2841, -2841, -2841, - 1721, 1722, -2839, -2839, -2839, 7525, 7526, 7527, - 1426, 0, 0, 0, -3710, 3971, -8765, 6370, - 6371, 6372, 6373, 5038, 6375, 594, 595, 596, - 597, 598, 599, 600, 601, -4546, -4546, 606, - 607, 608, 609, 610, 611, 612, -4546, -4546, - -4546, -4546, -4546, -4546, -4546, -4546, -4546, -4546, - -4546, -4546, -4546, -4546, -4546, -4546, -4546, -4546, - -4546, -4546, -4546, -4546, -4546, -4546, -4546, -4546, - -4546, -4546, -4546, -4546, 245, 245, -15114,245, - -4546, -4546, 245, 245, -4546, 245, 245, -4544, - -4544, -4544, -4544, -4544, -4544, 245, 245, 245, - 245, 245, 245, -4544, 245, 245, 245, -4544, - -4544, -4544, -4544, -4544, -4544, -4544, -4544, -4544, - -4544, -4544, -4544, -4544, -4544, 249, 249, -4544, - 249, -4544, -4544, -4544, -4544, -4544, -4544, -166, - -1054, -1054, 256, 256, -1053, -1053, -165, -8061, - -8061, -8061, -165, -165, -165, -165, -165, 1298, - 1298, 1298, 1298, 2786, 1299, 1299, -18634,1299, - 1299, 1299, 1299, 1299, 1299, 1299, 1299, 1299, - 1050, 1051, 1299, 1299, 1299, 1299, 1299, 1299, - 1299, 1299, -165, 1300, 1300, 1300, 1300, 1300, - 1300, 1300, 7401, 1300, 1300, 1300, 1300, 1300, - -3756, -3756, -1838, 4302, 0, 0, 0, 4309, - -3753, 4284, 4285, 4286, 4287, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -6154, -5906, - -5906, 0, 0, 0, 2638, 0, 0, 0, - 0, 0, 0, 0, 0, 426, 15786, 428, - 0, 0, 0, 0, 0, 0, 0, 0, - 10364, 10365, 10366, 0, 0, 451, 452, 453, - 454, 455, 456, 32767, 32767, 0, 0, 0, - 32767, 32767, 32767, 0, 0, 0, 0, 0, - 0, 0, 32767, 0, 0, 0, 0, 0, - 0, 0, 32767, 1842, 32767, 32767, 1843, 32767, - 32767, 0, 32767, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 1844, 32767, - 0, 0, 0, 32767, 32767, 32767, 1846, 1847, - 32767, 1848, 1849, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 0, 32767, - 32767, 32767, 32767, 0, 32767, 32767, 1851, 32767, - 32767, 1852, 32767, 0, 0, 32767, 32767, 32767, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 5990, 5991, 5992, 5993, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 1854, 32767, 1855, 6223, 6224, 6225, - 6226, 6227, 6228, 6229, 6230, 6231, 6232, 1856, - 1857, 1574, 1574, 1574, 32767, 32767, 1572, 1572, - 32767, 32767, 1863, 1864, 32767, 32767, 32767, 32767, - 32767, 32767, 1865, 1866, 32767, 32767, 1867, 1868, - 32767, 32767, 1869, 1870, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 890, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 891, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 1871, 1872, - 3017, 1874, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 3018, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 799, 32767, 32767, 32767, + 32767, 800, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 801, 802, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 1875, 1876, 1877, 1878, 32767, 32767, - 32767, 0, 0, 32767, 1879, 1880, 1881, 1882, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, + 0, 0, 0, 0, 6545, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 32767, 0, 0, + 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, + -5711, 241, 242, 243, 244, 0, 246, 247, + 248, 249, 250, 251, 252, 0, 0, 0, + 0, 892, 0, 0, 0, 0, 0, 0, + 264, 0, 0, 0, 32767, 32767, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 1883, 1884, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -1179,23 +848,99 @@ Decomp_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 893, -266, 895, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 0, 0, 0, 0, 0, 0, 0, + 284, 285, 286, 287, 288, 0, 290, 291, + 292, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 293, 294, 295, 296, 297, 298, 32767, 32767, + 299, -4082, -4081, -4080, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32767, 0, 0, 0, 0, + 0, 32767, 0, 32767, 0, 0, 32767, 0, + 0, 32767, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -4245, -4245, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32767, 32767, 32767, 32767, + 32767, 32767, -689, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -706, + -706, -706, -706, -706, -706, -706, -706, 32767, + 32767, -7551, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, -2263, 2526, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, -4377, -4377, -8024, -8023, -4377, -4377, + -3916, -4377, -4377, -4377, -4377, -4377, -4377, -4377, + 32767, -4378, -4378, -4378, -4378, -4378, -4378, -4378, + -4378, -4378, -4378, -4378, -4378, -4378, -4378, -4378, + -4378, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 150, 1867, 150, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5247, 0, 939, 0, 940, 0, 5518, + 0, 8555, 0, 0, 0, 5253, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 944, + 0, 0, 0, 0, 0, 0, 945, 0, + 946, 0, 0, 947, 948, 0, 949, 950, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -759, 959, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 960, 961, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5204, 0, 0, 0, + 0, 962, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 963, 964, 0, + 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -1203,6 +948,7 @@ Decomp_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 5186, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -1210,219 +956,176 @@ Decomp_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 1885, 1886, 1887, 1888, - 1889, 1890, 1891, 1892, 1893, 1894, 4758, 4759, - 4760, 4761, 4762, 1900, 1901, 1902, 1903, 1904, - 1905, 1906, 1907, 1908, 1909, 924, 1911, 1912, - 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, - 1921, 1107, 1923, 1924, 1925, 1926, 1927, 1928, - 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, - 1937, 1938, 1939, 1123, 1123, 1123, 1943, 1944, - 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, - 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, - 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, - 1969, 1970, 1971, 1972, 1973, 1974, 4727, 1976, - 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, - 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, - 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - -2451, 2002, -2448, 2004, 2005, 2006, -2441, -2724, - 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, - 2017, 2018, 2019, 2020, 2021, 0, 2023, 985, - 985, 7086, 985, 985, 985, 985, 985, -4071, - -4071, -2153, 3987, 3988, 3989, 0, 3991, -4071, - 3966, 3967, -4071, 260, 261, 262, 263, 264, - 265, 266, 3264, 32767, 32767, -2437, -2436, 32767, - 32767, 32767, 32767, 32767, 32767, 270, 271, 272, - 273, 274, 275, 4728, 277, 278, 279, 280, - 281, -2434, 283, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 32767, 32767, 32767, 1329, 441, 441, 1751, - 1751, 442, 442, 1330, -6566, -6566, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -3047, -274, - -273, -272, -271, 1946, 4745, 0, 0, -267, - -266, 1945, -264, -263, 0, 0, 0, 0, - 0, 0, 0, 0, -6199, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 2539, 2540, 2541, - 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, - -6233, -6233, 3671, 3672, 3673, 3674, 3675, 3676, - 3677, 3678, -6233, -6233, -6233, -6233, -6233, -6233, - 4956, -99, -98, -6198, -96, -95, -94, -93, - -92, 4965, 4966, -6233, -6233, -6233, -6233, -6233, - 2573, 2574, -3059, 3049, -3060, -3060, 4621, -6234, - -6234, -6234, -6234, -6234, -6234, -6234, -6234, -6234, - -8015, -8015, -8015, -8015, -6234, -6234, -6234, -6234, - -6234, -6234, -6234, -6234, -6234, -6234, -6234, -6234, - -6234, -6234, -6234, -6234, -6234, -6234, -6234, -6234, - -6234, -1178, -1178, 4923, -1178, -1178, -1178, -1178, - -1178, -6234, -6234, -4316, 1824, 1825, 1826, -2163, - 1828, -6234, 1803, 1804, 1805, 1806, -5874, 6863, - -8271, -8271, -8271, -8271, -6935, -8271, -2489, -2489, - -2489, -2489, -2489, -2489, -2489, -2489, 2659, 2660, - -2491, -2491, -2491, -2491, -2491, -2491, -2491, 2668, - 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, - 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, - 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, - 2693, 2694, 2695, 2696, 2697, -2093, -2092, 13268, - -2090, 2702, 2703, -2087, -2086, 2706, -2767, 2708, - 2709, 2710, 2711, 2712, 3178, 3179, 3180, 3181, - 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, - 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, - 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, - 3206, 3207, 3208, 3209, 3281, 3211, 3212, 3213, - 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, - 3222, 4107, 4108, 4109, 4110, 4111, 4112, 3229, - 4115, 4116, 4117, 4118, 4119, 4120, 3236, 3237, - 4124, 4125, 4126, 4127, 4128, 7621, 3244, 4133, - 4134, 2825, 4136, 4137, 4138, 3251, 11148, 11149, - 11150, 3255, 3256, 3257, 3258, 3259, 1797, 1798, - 1799, 1800, 313, 1801, 1802, 21736, 1804, 1805, - 1806, 1807, 1808, 1809, 1810, 1811, 1812, 2062, - 2062, 1815, 1816, 1817, 1818, 1819, 1820, 1821, - 1822, 3287, 1823, 1824, 1825, 32767, 3291, 3292, - 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, - 3301, 3302, 3303, 3304, 32767, 32767, 3305, 32767, - 9008, 32767, 32767, 3307, 3308, 3309, 3310, 3311, - 3312, 3313, 3314, 3315, 3316, 32767, 3317, 32767, - 3318, 32767, 32767, 3319, 3320, 32767, 32767, 32767, - 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, - 3329, 3330, 3331, 3332, 3333, 10603, 10604, 10605, - 2710, 2711, 2712, 5678, 3341, 3342, 3343, 4956, - 10622, -227, 3347, 1263, 21197, 5839, 3351, 10633, - 5843, 3354, 3355, 3356, 3357, 10641, 4971, 10644, - 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, - 5872, 10662, 5874, 7681, 7682, 3374, 2839, 7683, - 7684, 7685, 7686, 2703, 7687, 7688, 7689, 7690, - 10690, 3386, 7693, 7694, 7695, 0, 7697, 7698, - 10703, 7699, 2703, 7700, 9925, 3396, 7703, 3398, - 3399, 7706, 3401, 7707, 7708, 7709, 7710, 7711, - 7712, 6357, 6358, 3410, 4899, 4900, 4901, 4902, - 4903, 3416, 4904, 4905, 24839, 4907, 4908, 4909, - 4910, 4911, 4912, 4913, 4914, 4915, 5165, 5165, - 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, - 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, - -1167, 4935, 4936, 4937, 4938, 4939, 4940, 4941, - 3455, 4943, 4314, -2955, -2955, -2955, 4941, 4941, - 4941, 1976, 4314, 4314, 4314, 2702, -2963, 7887, - 4314, 6399, -13534,1825, 4314, -2967, 1824, 4314, - 4314, 4314, 4314, -2969, 2702, -2970, 4314, 4314, - 4314, 3488, 4313, 4313, 3491, 3492, 1808, 3494, - 32767, 0, 0, 32767, 32767, 0, 0, 0, - 0, 32767, 0, 0, 0, 0, -2999, 4306, - 0, 0, 0, 7696, 0, 0, 32767, 0, - 32767, 0, -2224, 4306, 0, 4306, 4306, 0, - 0, 0, 0, 0, 0, 0, 0, 1356, - 1356, 4305, 2817, 2817, 2817, 2817, 2817, 2817, - 2817, 2817, -17116,2817, 2817, 2817, 2817, 2817, - 2817, 2817, 2817, 2817, 2568, 2569, 2817, 2817, - 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, - 2817, 2817, 2817, 2817, 2817, 2817, 8918, 2817, - 2817, 2817, 2817, 2817, 2817, 2817, 4304, 2817, - 3447, 10717, 10718, 10719, 3531, 3532, 32767, 3533, - 3534, 3535, 3536, 3537, 32767, 3538, 32767, 3539, - 3540, 32767, 3541, 3542, 32767, 3543, 3544, 3545, - 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, - 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, - 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, - 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, - 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, - 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, - 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, - 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, - 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, - 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, - 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, - 2324, 3635, 3636, 3637, 3638, 10646, 10647, 3641, - 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, - 3650, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 3651, 3652, 3653, 3654, 3655, 3656, - 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, - 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, - 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, - 3681, 3682, 3683, 3684, 3685, 3686, 3687, 3688, - 3689, 3690, 3691, 3692, 3693, 3694, 3695, 32767, - 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, - 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, - 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, - 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, - 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, - 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, - 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, - 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, - 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, - 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, - 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, - 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, - 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, - 3800, -210, -209, 3803, 3804, 3805, 3806, 3807, - 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, - 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, - 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, - 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, - 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, - 3848, 3849, -4925, 3851, -6041, -6041, -6041, -6041, - -6041, -6041, -6041, 3859, 3860, -6043, -6043, -6043, - -6043, -6043, -6043, -6043, -6043, 3869, 3870, 3871, - 3872, 3873, 3874, -7314, -2258, -2258, 3843, -2258, - -2258, -2258, -2258, -2258, -7314, -7314, 3886, 3887, - 3888, 3889, 3890, -4915, -4915, 719, 720, 721, - 722, -6958, 3898, 3899, 3900, 3901, 3902, 3903, - 3904, 3905, 3906, 5688, 5689, 5690, 5691, 3911, - 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, - 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, - 3928, 3929, 3930, 3931, -1124, -1123, -7223, -1121, - -1120, -1119, -1118, -1117, 3940, 3941, 2024, -4115, - -4115, -4115, -125, -4115, 3948, -4088, -4088, 3951, - 32767, 3952, 3953, 3954, 3955, 3956, 3957, 3958, - 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, - 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, - 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, - 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, - 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, - 3999, 4000, 4001, 4002, 4003, 14, 4005, 4006, - 4007, 4008, 4009, 4010, 4011, 4012, 4013, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 4014, 4015, 4016, 4017, 4018, 4019, 4020, - 4021, 4022, 4023, 4024, 4025, 4026, 2025, 2026, - 2027, 4030, 4031, 4032, 4033, 4034, 4035, 4036, - 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, - 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, - 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, - 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, - 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, - 4077, 32767, 32767, 4078, 4079, 4080, 4081, 4082, - 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, - 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, - 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, - 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, - 4115, 4116, 4117, 0, 4119, 4120, 4121, 4122, - 4123, 4124, 4125, 0, 4127, 4128, 1401, 4130, - 4131, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 5256, -4973, -4973, 32767, + 5261, 5262, 5263, 5264, 5265, 5266, 5267, -4974, + -4974, 978, 979, 980, 981, 32767, 982, 983, + 984, 985, 986, 987, 988, 32767, 32767, 32767, + 32767, 1624, 32767, 32767, 32767, 32767, 32767, 32767, + 990, 32767, 32767, 0, 991, 992, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4759, + 4760, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -723, -722, -2974, 32767, 996, -719, -168, + -717, -716, -715, 1002, 1003, 1004, -712, -711, + 32767, -710, 1008, 1009, 1010, 1011, -2060, 5892, + 2764, 2764, 2764, 1017, 1018, 1019, 1020, 1021, + 1022, 2567, 1024, 32767, 1025, 1026, 1027, 1028, + 1029, 1030, 1031, 1032, 1033, 1034, 2589, 1036, + 1037, -1729, -1729, -1729, -1729, 1042, 4211, 4211, + 4211, 4211, 4211, 4211, 1049, 1050, 4209, 1427, + 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -825, 32767, 32767, + 32767, 32767, 32767, 4718, 4719, 4720, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 4721, 4722, + 4723, 4724, 4725, 4726, 4727, 6291, 6292, 6293, + 4728, 4729, 4730, 4731, 4732, 6299, 6300, -4992, + 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, + 1078, 1079, 1080, 4733, 1082, 4734, 1084, 1085, + 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, + 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, + 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, + 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, + 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, + 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, + 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, + 1142, 1143, 1144, 1145, 1146, 4737, 1148, 4738, + 4739, 1151, 1152, 1153, 1154, 32767, 4740, 4741, + 4742, 1158, 1159, 1160, 1161, 1162, 1163, 1164, + 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, + 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, + 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, + 1189, 1190, 1191, 1192, 1193, 1194, 11979, 6272, + 1758, 1758, 1199, 1200, 1201, 1202, 1203, 1204, + 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, + 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, + 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, + 1229, -1074, -1073, 1232, 1233, 1234, 1235, 1236, + 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, + 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, + 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, + 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, + 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, + 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, + 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, + 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, + 1301, 1302, 1303, 1304, 1305, 1306, 1307, 4676, + 4677, 512, 32767, 32767, 32767, 32767, 1683, 1684, + 1685, 1314, 155, 1316, 1317, 1318, 1319, 1320, + 1321, 161, 1323, 1324, 1325, 1326, 1327, 1328, + 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, + 1337, 1338, -4375, -4374, -8536, -8536, -8536, -8536, + 1345, 1346, 1444, 1445, 1446, 1447, 1448, -4360, + 1353, 1354, -8525, -5383, 1357, -8524, -8524, -8524, + -8524, -4348, 1363, -2456, 686, 1366, 1367, -8518, + -8518, -7581, 1371, 1372, -5364, 1374, 1375, -4332, + -4331, 1378, 1379, 1380, -4327, -8841, -8841, -8841, + -8841, -8841, -8841, -8841, 1389, 1390, -8843, -8843, + -8843, -8843, -8843, -8843, -8843, -8843, 1399, 1400, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 5957, + 2655, -5028, -5028, 2658, 2659, -3322, -1679, -1679, + -1679, -1679, -1679, -7010, -1679, -1679, -7010, -7010, + -1679, -1679, -1679, -1679, -1679, 32767, 32767, -1681, + -1681, -1681, -1681, -1681, -1681, 32767, 32767, -1683, + -1683, -3290, -3289, -3288, -3287, -3286, -3285, -12842, + 7263, -3282, -499, -9550, -499, -9549, -9549, -9549, + 96, -9549, -9816, -9549, 1704, -9548, -1864, -1863, + -9548, -9548, -3566, -5208, -5207, -5206, -5205, -5204, + 128, -5202, 131, 132, 133, 32767, 32767, -5195, + -3568, -3568, -5190, -5189, -3568, 32767, 32767, -5185, + -5184, -5183, -3570, -5180, 1478, -5179, -3571, 32767, + -3572, 32767, -3573, 32767, 5984, 32767, -3575, 2695, + 2696, 2697, 2698, 2699, 2700, -6944, 2702, 2970, + 2704, 6008, 2706, -4977, -4977, 2709, 2710, -3271, + 1502, -3478, 1504, -3626, -3626, -7766, 6033, 1509, + -3625, -7767, 1512, 1513, 1514, 32767, 32767, -3625, + -3625, -3625, -3625, -3625, -3625, -3625, 1522, -3624, + 1524, 1525, 1526, 1527, 1528, 1529, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3128, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1581, -673, 0, 784, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3025, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -6843, + -6843, 0, 0, 0, 1619, 1620, 1621, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -2788, 32767, 32767, + 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, + 4194, 1643, 1644, 32767, 32767, 32767, 32767, 32767, + 32767, 1352, 32767, 32767, 32767, 32767, 32767, 1646, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 1647, 1648, 1649, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 1650, + 32767, 32767, 32767, 1651, 1652, 32767, 1653, 1654, + 32767, 32767, 32767, 32767, 1655, 32767, 1656, 32767, + 32767, 32767, 32767, 399, 399, 32767, 32767, 1657, + 1658, 1659, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 32767, 32767, 32767, 1660, + 32767, 32767, 32767, 32767, 32767, 6619, 32767, 1661, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 5971, 5972, 5973, 5974, 1664, 5975, 6243, 5977, + 9281, 5979, -1704, -1704, 5982, 5983, 2, 4775, + -205, 4777, -353, -353, -4493, 9306, 4782, -352, + -4494, 4785, 4786, 4787, 4788, -350, -350, 6044, + 1691, 6045, 6046, 1694, 6047, 1696, 1697, 6048, + 1699, 6049, 6050, 6051, 6052, 0, 0, 0, + 0, 0, 0, 32767, 0, 0, 0, 0, + 1704, 0, 32767, 0, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 32767, 32767, 32767, -3338, -3338, + -3338, 0, 32767, 0, 32767, 0, 0, 0, + 32767, 0, 0, 32767, 0, 32767, 32767, 0, + 0, 0, 0, 0, 32767, 0, 32767, 0, + 1705, 1706, 1707, 1708, 1709, 759, 759, 759, + 759, 759, 759, 759, 0, 0, 0, 0, + 0, 3035, 0, 32767, 0, 1719, 10109, 1721, + 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, + 1730, 0, 0, 0, 0, 0, 0, 0, + 0, 9764, 6757, 6758, 6759, 8018, 0, 0, + 0, 1720, 1720, 1720, 0, 0, 2557, 2558, + 1720, 0, -1282, 0, -1281, -1281, -1281, 633, + 1720, -1279, -1279, 1720, 4767, 0, 1720, 1720, + 0, 0, 1718, 1718, -3263, 0, 6007, 6008, + -7790, 6010, 6011, 6012, -3266, 1719, 0, 1718, + 0, 1717, 0, -150, 1717, 1717, 1717, 32767, + 1716, 1716, 1716, 3969, 1715, 0, 1716, 1166, + 1716, 1716, 1716, 0, 0, 0, 1717, 1717, + 1717, 1717, 0, 0, 0, 0, 3072, -4879, + -1750, -1749, -1748, 0, 0, 0, 0, 0, + 0, -1544, 0, 1789, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -1554, 0, + 0, 2767, 2768, 2769, 2770, 0, -3168, -3167, + -3166, -3165, -3164, -3163, 0, 0, -3158, -375, + -9426, -375, -9425, 1821, 1822, 218, -9427, 1825, + -9426, 1827, 1828, -1742, -1741, 1878, 1879, 1833, + 1834, 32767, 32767, 32767, 32767, 2642, -4765, -1739, + -1738, 32767, 1835, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 0, 0, + 32767, 32767, 32767, 2718, -3491, 3174, 3174, 3174, + -3669, -3669, -3669, -3669, -3669, -5232, -5232, -5232, + -3666, -3666, -3666, -3666, -3666, -5232, -5232, 6061, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -3652, 0, -3651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1430,83 +1133,586 @@ Decomp_hash_func(const void *key) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -3590, 0, -3589, + -3589, 0, 0, 0, 0, 32767, 1842, 32767, + 32767, 32767, 32767, 1843, 32767, 32767, 1844, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 1845, 32767, + 1846, 32767, 32767, 32767, 32767, 32767, 1847, 1848, + 0, 1849, 1850, 0, 32767, 32767, 0, 0, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 1851, 32767, 32767, 1852, 32767, + 32767, 1853, 32767, 1854, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, -4903, 32767, -6162, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 137, + 1858, 3141, 1860, 3142, 32767, 32767, 1229, 143, + 32767, 32767, 144, -2902, 0, 0, 32767, 32767, + 32767, 32767, 148, 5130, 0, 0, -4140, 9659, + 32767, 0, -4142, 5137, 5138, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32767, + 0, 5148, 5149, 5150, 5151, 5152, 5153, 4782, + 3623, 3623, 3623, 3623, 3623, 3623, 3623, 3623, + 3623, 3623, 3623, 3623, 3623, 3623, 6751, 3623, + 3623, 3623, 3623, 3623, 3623, 3623, 3623, 3623, + 3623, 3623, 3623, 3623, 32767, 3622, 3622, 3622, + 3622, 32767, 3621, 3621, 3621, 0, 3622, 32767, + 3621, 32767, 32767, 32767, 3618, 3618, 3618, 3618, + 3618, 3618, 3618, 32767, 2944, 0, 4402, 3618, + 3618, 3618, 3618, 3618, 3618, 3618, 3618, 3618, + 3618, 3618, 3618, 3618, 0, 0, 3620, 3620, + 3620, 3620, 3620, 3620, -762, 6646, 3621, 3621, + 3621, 3621, 3621, 3621, 3621, 3621, 3621, 3621, + -3222, -3222, 3621, 3621, 3621, 5240, 5241, 5242, + 0, 0, 3623, 3623, 3623, 0, 3624, 3624, + 3624, 3624, 3624, 3624, 3624, 3624, 836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -3647, -3646, 0, 0, + 461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4011, 4011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 8775, 0, - 9893, 9894, 9895, 9896, 9897, 9898, 9899, 0, - 0, 9904, 9905, 9906, 9907, 9908, 9909, 9910, - 9911, 0, 0, 0, 0, 0, 0, 11189, - 6134, 6135, 35, 6137, 6138, 6139, 6140, 6141, - 11198, 11199, 0, 0, 0, 0, 0, 8806, - 8807, 3174, 3174, 3174, 3174, 10855, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -1781, - -1781, -1781, -1781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 468, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5056, 5056, 11157, 5056, 5056, 5056, 5056, 5056, - 0, 0, 1918, 8058, 8059, 8060, 4071, 8062, - 0, 8037, 8038, 0, 4331, 4332, 4333, 4334, - 4335, 4336, 4337, 7335, 7336, 1635, 1636, 1637, - 1638, 1639, 1640, 1641, 1642, 1643, 4349, 4350, - 4351, 4352, 4353, 4354, 8807, 4356, 4357, 4358, - 4359, 4360, 1645, 4362, 4363, 4364, 4365, 32767, - 32767, 32767, 32767, 32767, 8912, 8913, 8914, 8915, - 8916, 8917, 8918, 8919, 8920, 8921, 8922, 8923, - 8924, 8925, 8926, 8927, 4137, 4138, 19498, 4140, - 8932, 8933, 4143, 4144, 8936, 4146, 4147, 8937, - 8938, 8939, 8940, 8941, 8942, 4154, 4155, 4156, - 4157, 4158, 4159, 8949, 4161, 4162, 4163, 8953, - 8954, 8955, 8956, 8957, 8958, 8959, 8960, 8961, - 8962, 8963, 8964, 8965, 8966, 4174, 4175, 8969, - 4177, 8971, 8972, 8973, 8974, 8975, 8976, 4599, - 5488, 5489, 4180, 4181, 5491, 5492, 4605, 12502, - 12503, 12504, 4609, 4610, 4611, 4612, 4613, 3151, - 3152, 3153, 3154, 1667, 3155, 3156, 23090, 3158, - 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, - 3416, 3416, 3169, 3170, 3171, 3172, 3173, 3174, - 3175, 3176, 4641, 3177, 3178, 3179, 3180, 3181, - 3182, 3183, -2917, 3185, 3186, 3187, 3188, 3189, - 8246, 8247, 6330, 191, 4494, 4495, 4496, 188, - 8251, 215, 215, 215, 215, 4503, 4504, 4505, - 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, - 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, - 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, - 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, - 4538, 4539, 4540, 4541, 4542, 4543, 10698, 10451, - 10452, 4547, 4548, 4549, 1912, 4551, 4552, 4553, - 4554, 4555, 0, 32767, 4130, 4130, -11229,4130, - 4559, 4560, 4561, 0, 0, 4562, 4563, 4564, - -5799, -5799, -5799, 303, 32767, 4117, 4117, 4117, - 4117, 4117, 4117, 2031, 2032, 4574, 4575, 4576, - 32767, 32767, 32767, 4577, 4578, 4579, 4580, 4581, - 4582, 4583, 32767, 4584, 4585, 4586, 4587, 4588, - 4589, 4590, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, - 32767, 32767, 32767, 32767, 2034, 4816, 4817, 4818, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 2035, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 32767, 0, 470, 471, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 472, 473, 474, 475, 476, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 775, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 4803, 4804, 7596, 7596, 7596, + 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, + 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, + 4824, 3988, 3988, 4827, 4828, 7830, 1792, 7832, + 7833, 7834, 5921, 4835, 7835, 7836, 4838, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3036, 6038, 0, + 6040, 6041, 6042, 4129, 3043, 6043, 6044, 3046, + 0, 3048, 3049, 3050, 6046, 6047, 3053, 3054, + 3055, 3056, -1230, 3058, 3059, -1232, -1232, 3062, + 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, + 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, + 3079, 3080, 3081, 3632, 3083, 3084, 3085, 3086, + 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, + 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, + 3103, -814, 3105, 3106, 3107, 3108, -6867, 3110, + 3111, 3112, 3113, 9179, 9180, 3116, 3117, 3118, + 3119, -22, 3121, 3122, 3123, 3124, 3125, 3126, + 3127, 3128, 3129, 3130, 2196, 3132, 3133, 2197, + 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, + 3143, 3144, -6500, 3146, 3414, 3148, 6452, 3150, + -4533, -4533, 3153, 3154, -2827, -1184, -1184, -1184, + -1184, -1184, -6515, -1184, -1184, -6515, -6515, -1184, + -1184, -1184, -1184, -1184, -1184, -1184, -1184, -1184, + -1184, -1184, -1184, -1184, -1184, -1184, -1184, -1184, + -2791, -2790, -2789, -2788, -2787, -2786, -12343,7762, + -2783, 0, -9051, 0, -9050, -9050, -9050, 595, + -9050, -9317, -9050, 2203, -9049, -1365, -1364, -9049, + -9049, -3067, -4709, -4708, -4707, -4706, -4705, 627, + -4703, 630, 631, 632, -3067, -3067, -4694, -3067, + -3067, -4689, -4688, -3067, 3131, -4683, -4682, -4681, + -4680, -3067, -4677, 1981, -4676, -3068, -3068, -3068, + -3068, -3068, -3068, 6490, -13614,-3068, 3202, 3203, + 3204, 3205, 3206, 3207, -6437, 3209, 3477, 3211, + 6515, 3213, -4470, -4470, 3216, 3217, -2764, 2009, + -2971, 2011, -3119, -3119, -7259, 6540, 2016, -3118, + -7260, 2019, 2020, 2021, 2022, -3116, -3116, 3278, + 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, + 3287, 3288, 3289, 3290, 3291, 32767, 3292, 3293, + -869, -869, -869, -869, 9107, 9108, 9109, 9110, + 9111, 9112, 9113, 3305, 32767, 32767, -863, 32767, + -864, 32767, 32767, -866, -866, 3310, 3311, -864, + -864, -864, 71, -864, -864, 32767, 72, 32767, + 2290, 32767, 32767, 3320, 3321, 32767, 32767, 32767, + 3322, -1192, -1192, -1192, -1192, -1192, -1192, -1192, + -1192, -1192, -1192, -1192, -1192, -1192, -1192, -1192, + -1192, -1192, -1192, -1192, -1192, -1192, -1192, -1192, + -1192, -1192, -1192, -1192, -1192, -1192, -1192, -1192, + -1192, -1192, -1192, -1192, -1192, -1192, -1192, -1192, + -1192, -1192, -1192, 3365, 3366, 3367, -1189, -1189, + -1189, -1189, -1189, -1189, 3374, 3375, -1187, -1187, + -1187, -1187, -1187, -1187, 3382, 3383, -1185, -1185, + -1185, -1185, -1185, -1185, 32767, 32767, -1185, -1185, + -1185, 3393, 3394, 3395, -1182, 3397, 3398, 3399, + 3400, 3401, 3402, 1274, 1274, 3405, -5404, 3407, + 3408, 3409, 3410, 1274, 1274, 1274, 1274, 1274, + 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, + 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, + 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, + 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, + -1138, -1138, -1138, -1138, -1138, 3461, 3462, 3299, + 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, + 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, + 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, + 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 3496, + 3497, 3498, 3499, 3500, 3501, 3502, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 3503, 3211, 3211, 3211, 3211, 32767, + 32767, 32767, 32767, 32767, 7590, 7590, 7590, 3208, + 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, + 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, + 3528, 3529, 3530, 3531, 3532, 3533, 32767, 3534, + 3535, 3536, 3537, 3538, 32767, 3539, 32767, 3540, + 3541, 32767, 3542, 3543, 32767, 3544, 3545, 3546, + 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, + 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, + 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, + 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, + 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, + 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, + 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, + 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, + 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, + 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, + 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, + 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, + 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, + 3651, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 3652, 3653, 3654, 3655, 3656, 3657, + 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, + 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, + 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, + 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, + 3690, 3691, 3692, 3693, 3694, 3695, 3696, 32767, + 3244, 3698, 3699, 3700, 3701, 3702, 4131, 3704, + 3251, 3251, 3707, 3252, 3709, 3710, 3711, 3255, + 3713, 3714, 3715, 3716, 3259, 3259, 3259, 3720, + 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, + 3729, 3730, 3731, 3732, 0, 0, 3735, 3736, + 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, + 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, + 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, + 3761, 3300, 3763, 3764, 3765, 3766, 3767, 3768, + 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, + 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, + 3322, 3322, 3787, 3323, 3789, 3790, 3791, 3326, + 3793, 3794, 3795, 3796, 3330, 3798, 3330, 3800, + 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, + 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, + 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, + 3825, -1667, 3827, 3828, 3829, 3830, 3831, 3832, + 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, + 3841, 3842, 3843, 3844, -1685, 3846, 3847, 3848, + 3849, 3850, 3851, 3852, 3853, 3854, 3855, 3856, + 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, + 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, + 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, + 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, + 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, + 3897, 8237, 8238, 3900, 3901, 3902, 3903, 3904, + 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, + 11266, 11267, 11268, 9355, 3917, 3918, 11272, 8274, + 3921, 3922, 3438, 3438, 3438, 3438, 3438, 3438, + 3929, 3930, 3440, 3440, 3440, 3440, 6476, 9478, + 3937, 3938, 9483, 9484, 7571, 6485, 9485, 9486, + 6488, 3442, 6490, 6491, 6492, 9488, 3951, 3952, + 32767, -866, -866, -866, -866, -866, -866, -29, + -28, -866, -866, -3867, 2172, -3867, -3867, -3867, + -1953, -866, -3865, -3865, -866, 3973, 3974, 3975, + 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, + 3984, 3985, 3986, 951, -2050, 3989, -2050, -2050, + -2050, -136, 951, -2048, -2048, 951, 3998, 951, + 951, 951, -2044, -2044, 951, 951, 951, 951, + 5238, 951, 951, 5243, 5244, 951, 951, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 383, 933, 933, 933, 933, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 4851, + 933, 933, 933, 933, 10909, 933, 933, 933, + 933, -5132, -5132, 933, 933, 933, 933, 4075, + 933, 933, 933, 933, 933, 933, 933, 933, + 933, 933, 1868, 933, 933, 1870, 933, 933, + 933, 933, 933, 933, 933, 933, 933, 933, + 10578, 0, 32767, 931, -2372, 931, 8615, 8616, + 931, 931, 6913, 5271, 5272, 5273, 5274, 5275, + 10607, 5277, 5278, 10610, 10611, 5281, 5282, 5283, + 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, + 5292, 5293, 5294, 5295, 5296, 5297, 6905, 6905, + 6905, 6905, 6905, 6905, 16463, -3641, 6905, 4123, + 13175, 4125, 13176, 13177, 13178, 3534, 13180, 13448, + 13182, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 0, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -2357, 17748, 7203, 934, 934, 934, 934, + 934, 934, 10579, 934, 667, 934, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 4146, 4147, 4148, 4149, 4150, 4151, + 4152, 4153, 4154, 4155, 32767, 32767, 32767, 32767, + 32767, 32767, 4156, 4157, 4158, 4159, 4160, 4161, + 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, + 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, + 4178, 4179, 4180, 4181, 4182, 5374, 5375, 5376, + 6978, 4187, 4188, 4189, 4190, 6982, 6982, 32767, + 32767, 4193, 4194, 4195, 4196, 4197, 4198, 4199, + 4200, 4201, 4202, 4203, 4204, 32767, 6995, 6995, + 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, + 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, + 4223, 32767, 3386, 4225, 4226, 7228, 32767, 32767, + 32767, 32767, 5315, 4229, 7229, 32767, 4231, 32767, + 4232, 4233, 4234, 7230, 7231, 4237, 4238, 4239, + 4240, -46, 4242, 4243, -48, -48, 4246, 4247, + 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, + 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, + 4264, 4265, 4816, 4267, 4268, 4269, 4270, 4271, + 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, + 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, + 370, 4289, 4290, 4291, 4292, -5683, 4294, 4295, + 4296, 4297, 10363, 10364, 4300, 4301, 4302, 4303, + 1162, 4305, 4306, 4307, 4308, 4309, 4310, 4311, + 4312, 4313, 4314, 3380, 4316, 4317, 3381, 4319, + 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, + 4328, -5316, 4330, 4598, 4332, 7636, 4334, -3349, + -3349, 4337, 4338, -1643, 0, 0, 0, 0, + 0, -5331, 0, 0, -5331, -5331, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4126, + 4127, 4128, 4129, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, -1258, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -1272, -1272, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -1851, -1851, -1851, -1851, + -1851, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3235, 0, -6925, 306, + 306, 306, 306, 306, 306, 306, 306, 306, + 306, 306, 306, -1764, -1764, 4472, 4473, 311, + 311, 311, 311, 10287, 10288, 10289, 10290, 10291, + 10292, 10293, 4485, 10198, 319, 319, 3461, 319, + 319, 319, 319, 319, 4495, 4496, 321, 321, + 321, 1256, 321, 321, 1258, 1258, 0, 3477, + 10215, 10216, 4509, 4510, 10219, 10220, 10221, 4514, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4579, 4580, 4581, 4582, + 4583, 4584, 32767, 2455, 4586, -4223, 4588, 4589, + 4590, 4591, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 4885, 4886, 4887, + 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, + 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, + 4904, 4616, 4906, 4907, 4908, 4909, 4910, 4911, + 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, + 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, + 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, + 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, + 4944, 4945, 4946, 4947, 4948, 567, 568, 569, + 4952, -2455, 571, 572, 4956, 4957, 4958, 4959, + 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, + 4968, 4969, 32767, 4970, 4971, 4972, 4973, 4974, + 4975, 4976, 4977, 4978, 4979, 4980, 6623, 6623, + 6623, 6623, 6623, 1292, 6623, 1291, 1291, 1291, + 4991, 4992, 6620, 4994, 4995, 6618, 6618, 4998, + -1199, 6616, 6616, 6616, 6616, 5004, 6615, 6615, + 6615, 5008, 5009, 5010, 5011, 5012, 5013, -4544, + 15561, 5016, -1253, -1253, -1253, -1253, -1253, -1253, + 8392, -1253, -1520, -1253, -4556, -1253, 6431, 6432, + -1253, -1253, 4729, 3087, 3088, 3089, 3090, 3091, + 8423, 3093, 3094, 8426, 8427, 3097, 3098, 3099, + 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, + 3108, 3109, 3110, 3111, 3112, 3113, 4721, 4721, + 4721, 4721, 4721, 4721, 14279, -5825, 4721, 1939, + 10991, 1941, 10992, 10993, 10994, 1350, 10996, 11264, + 10998, -254, 10999, 3316, 3316, 11002, 11003, 5022, + 6665, 6665, 6665, 6665, 6665, 1334, 6665, 1333, + 1333, 1333, 5033, 5034, 6662, 5036, 5037, 6660, + 6660, 5040, -1157, 6658, 6658, 6658, 6658, 5046, + 6657, 0, 6658, 5051, 5052, 5053, 5054, 5055, + 5056, -4501, 15604, 5059, -1210, -1210, -1210, -1210, + -1210, -1210, 8435, -1210, -1477, -1210, -4513, -1210, + 6474, 6475, -1210, -1210, 4772, 0, 4981, 0, + 5131, 5132, 9273, -4525, 0, 5135, 9278, 0, + 0, 0, 0, 5139, 5140, 5141, 5142, 5143, + 5144, 5145, 5146, 0, 5147, 0, 0, 0, + 0, 0, 0, 1530, 1531, 1532, 1533, 1534, + 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, + 1543, 1544, -1583, 1546, 1547, 1548, 1549, 1550, + 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, + 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, + 1567, 5189, 1568, 1569, 1570, 1571, 1572, 1573, + 1574, 1575, 1576, 1577, 1578, 1579, 1580, 0, + 2255, 5200, 799, 1584, 1585, 1586, 1587, 1588, + 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, + 5215, 5216, 1597, 1598, 1599, 1600, 1601, 1602, + 5985, -1422, 1604, 1605, 1606, 1607, 1608, 1609, + 1610, 1611, 1612, 1613, 8457, 8458, 1616, 1617, + 1618, 0, 0, 0, 5243, 5244, 1622, 1623, + 1624, 5248, 1625, 1626, 1627, 1628, 1629, 1630, + 1631, 1632, 4421, 5258, 5259, 5260, 5261, 5262, + 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, + 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, + 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, + 8934, 8934, 5289, 5290, 4830, 5292, 5293, 5294, + 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, + 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, + 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, + 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, + 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, + 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, + 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, + 5351, 5352, 5353, 5354, 5355, 5356, 5357, 5358, + 4891, 5360, 5361, 5362, 5363, 5364, 5365, 5366, + 5367, 5368, 5369, 5370, 5371, 5372, 32767, 5373, + 5374, -5231, 5376, 4532, 0, 5379, 5380, 5381, + 5382, 4270, 4271, 4272, 4273, 4274, 4275, 4276, + 4277, 4278, 12230, 9102, 9102, 9102, 5396, 8890, + 5398, 5399, 5400, 5401, 8899, 7356, 5568, 7358, + 7359, 0, 0, 7364, 7365, 7366, 7367, 7368, + 7369, 8924, 7371, 7372, 4606, 4606, 4606, 4606, + 7377, 10546, 10546, 10546, 10546, 10546, 10546, 20104, + 0, 10546, 7764, 16816, 7766, 16817, 5572, 5572, + 7177, 16823, 17091, 16825, 5573, 5573, 9144, 9144, + 5526, 0, 5574, 5574, 5450, 5451, 5452, 697, + 697, 5455, 0, 7172, 5458, 5576, 5460, -5456, + 5462, 5463, 5464, 0, 0, 4691, 5468, 5469, + 4693, 5471, 10898, 0, 0, 5475, 4698, 10908, + 5478, 5479, 5480, 5481, 1359, 1359, 1359, 5485, + 5486, 5487, 5488, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 101, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 87, 87, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, -492, -492, -492, -492, + -492, 1359, 1359, 1359, 1359, 1359, 1359, 1359, + 1359, 1359, 1359, 1359, 4594, 1359, -5566, 1665, + 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, + 1665, 1665, 1665, -405, -405, 5585, 5586, 1668, + 1668, 1668, 1668, 11644, 11645, 11646, 11647, 11648, + 11649, 11650, 5842, 11555, 1676, 1676, 4818, 1676, + 1676, 1676, 1676, 1676, 5852, 5853, 1678, 1678, + 1678, 2613, 1678, 1678, 2615, 2615, 1357, 4834, + 11572, 11573, 5866, 5867, 11576, 11577, 11578, 5871, + 1357, 1357, 1357, 1357, 1357, 1357, 1357, 1357, + 1357, -6594, -3465, -3464, -3463, 244, -3249, 244, + 244, 244, 244, -3253, -1709, 80, -1709, -1709, + 5651, 5652, -1711, -1711, -1711, -1711, -1711, -1711, + -3265, -1711, -1711, 1056, 1057, 1058, 1059, -1711, + -4879, -4878, -4877, -4876, -4875, -4874, -14431,5674, + -4871, -2088, -11139,-2088, -11138,108, 109, -1495, + -11140,-11407,-11140,113, 114, -3456, -3455, 164, + 5691, 118, 119, 244, 244, 244, 5000, 5001, + 244, 5700, -1471, 244, 127, 244, 11161, 244, + 244, 244, 5709, 5710, 1020, 244, 244, 1021, + 244, -5182, 5717, 5718, 244, 1022, -5187, 244, + 244, 244, 244, 4367, 4368, 4369, 244, 244, + 244, 244, 4374, 4375, 4376, 4377, 4378, 4379, + 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, + 5646, 4389, 4390, 4391, 4392, 4393, 4394, 4395, + 4396, 4397, 4398, 4399, 4400, 4401, 4402, 5675, + 5676, 4405, 4406, 4407, 4408, 4409, 4410, 4411, + 4412, 4413, 4414, 4415, 4416, 4417, 4418, 4419, + 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, + 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, + 4436, 4437, 4438, 6290, 6291, 6292, 6293, 6294, + 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, + 4452, 4453, 4454, 1220, 4456, 11382, 4152, 4153, + 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, + 4162, 4163, 6234, 6235, 0, 0, 4163, 4164, + 4165, 4166, -5809, -5809, -5809, -5809, -5809, -5809, + -5809, 0, -5712, 4168, 4169, 1028, 4171, 4172, + 4173, 4174, 4175, 0, 0, 4176, 4177, 4178, + 3244, 4180, 4181, 3245, 3246, 4505, 1029, -5708, + -5708, 0, 0, -5708, -5708, -5708, 0, 4515, + 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, + 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, + 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, + 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, + 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, + 4556, 0, 0, 0, 4557, 4558, 4559, 4560, + 4561, 4562, 0, 0, 4563, 4564, 4565, 4566, + 4567, 4568, 0, 0, 4569, 4570, 4571, 4572, + 4573, 4574, 2114, 2115, 4575, 4576, 4577, 0, + 0, 0, 4578, 0, 0, 0, 0, 0, + 0, 2129, 2130, 0, 8810, 0, 0, 0, + 0, 2137, 2138, 2139, 2140, 2141, 2142, 2143, + 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, + 2152, 2153, 2154, 2155, 2156, 2157, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4594, 4595, + 4596, 4597, 4598, 0, 0, 164, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2222, 2223, + 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, + 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, + 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, + 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, + 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, + 2264, 2265, 2266, 2267, 2268, 2269, 2270, 705, + 706, 707, 708, 709, 2276, 2277, 2278, 2279, + 2280, 2281, 2282, 2283, 2284, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 2285, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 2286, 2287, 2288, 2289, 2290, 2291, + 32767, 32767, 32767, 32767, 32767, 32767, 2292, 32767, + 2293, 2294, 2295, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 2296, 32767, 2297, 32767, + 2298, 32767, 2299, 32767, 2300, 32767, 2301, 32767, + 2302, 32767, 2303, 32767, 2304, 32767, 2305, 32767, + 2306, 32767, 2307, 32767, 32767, 2308, 32767, 2309, + 32767, 2310, 32767, 32767, 32767, 32767, 32767, 32767, + 2311, 2312, 32767, 2313, 2314, 32767, 2315, 2316, + 32767, 2317, 2318, 32767, 2319, 2320, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 2321, 32767, 32767, 32767, + 32767, 2322, 2323, 2324, 2325, 32767, 2326, 2327, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 2328, 32767, 2329, 32767, + 2330, 32767, 2331, 32767, 2332, 32767, 2333, 32767, + 2334, 32767, 2335, 32767, 2336, 32767, 2337, 32767, + 2338, 32767, 2339, 32767, 32767, 2340, 32767, 2341, + 32767, 2342, 32767, 32767, 32767, 32767, 32767, 32767, + 2343, 2344, 32767, 2345, 2346, 32767, 2347, 2348, + 32767, 2349, 2350, 32767, 2351, 2352, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 2353, 32767, 32767, 2354, + 2355, 2356, 2357, 32767, 32767, 32767, 2358, 2359, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 2360, 2361, 2362, 2363, 2364, 2365, + 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, + 2374, -753, 2376, 2377, 2378, 2379, 2380, 2381, + 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, + 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, + 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, + 2406, 2407, 2408, 2409, 2410, 2411, 831, 3086, + 2414, 1631, 2416, 2417, 2418, 2419, 2420, 2421, + 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, + 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, + -587, 2439, 2440, 2441, 2442, 2443, 2444, 2445, + 2446, 2447, 2448, 9292, 9293, 2451, 2452, 2453, + 32767, 32767, 32767, 2454, 2455, 2456, 2457, 2458, + 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, + 2467, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 4599, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 4600, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 2468, -1450, 2470, 2471, 2472, 2473, + 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, + 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, + 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, + 2498, 32767, 2499, 2500, 2501, 2502, 2503, 2504, + 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, + 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, + 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, + 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, + 2537, 2538, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 2539, 2540, 5896, 2542, 2543, 2544, + 2545, 548, 2547, 2548, 2549, 2550, 2551, 2552, + 5919, 5920, 5921, 2556, 2557, 5926, 2559, 2560, + 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, + 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, + 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, + 2585, 32767, 2586, 2587, 2588, 2589, 2590, 2591, + 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, + 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, + 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, + 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, + 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, + 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, + 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, + 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, + 2656, 2657, 2658, 2659, 2660, 2661, -703, 2663, + 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, + 2672, 2673, 2674, 1999, 2676, 2677, 2678, 2679, + 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, + 2688, 2689, 2690, 2014, 2692, 2693, 2694, 2695, + 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, + 2704, 2705, 2706, 2707, 2708, 2709, -11089,2711, + 2712, 2713, 32767, 2714, 2715, 2716, 2717, 2718, + 8050, 2720, 2721, 8053, 8054, 2724, 2725, 2726, + 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, + 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, + 2743, 2744, 2745, 2746, 2747, 2748, -1377, -1377, + -1377, -1377, 2753, 2754, 2755, 2756, 2757, 2758, + 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, + 4025, 2768, 2769, 2770, 2771, 2772, 2773, 2774, + 2775, 2776, 2777, 2778, 2779, 2780, 2781, 4054, + 4055, 2784, 2785, 2786, 2787, 2788, 2789, 2790, + 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, + 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, + 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, + 2815, 2816, 2817, 4669, 4670, 4671, 4672, 4673, + 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, + 2831, 2832, 2833, -401, 2835, 9761, 2531, 2532, + 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, + 2541, 2542, 4613, 4614, -1621, -1621, 2542, 2543, + 2544, 2545, -7430, -7430, -7430, -7430, -7430, -7430, + -7430, -1621, -7333, 2547, 2548, -593, 2550, 2551, + 2552, 2553, 2554, -1621, -1621, 2555, 2556, 2557, + 1623, 2559, 2560, 1624, 1625, 2884, -592, -7329, + -7329, -1621, -1621, -7329, -7329, -7329, -1621, 2894, + 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, + 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, + 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, + 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, + 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, + 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, + 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, + 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, + 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, + 2967, 2968, 2969, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -1515,227 +1721,38 @@ Decomp_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 2036, 2037, 2038, - 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, - 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, - 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, - 2063, 2064, 2065, 2066, 2067, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 0, 0, 0, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - -4778, -4778, -4778, 0, 32767, 32767, 32767, 0, - 0, 32767, 32767, 32767, 0, 0, 32767, 32767, - -4791, -4791, -4791, -4791, -4791, -4791, -4791, -4791, - -4791, -4791, 0, 0, -15359,0, -4791, -4791, - 0, 0, -4791, 0, 0, -4789, -4789, -4789, - -4789, -4789, -4789, 0, 0, 0, 0, 0, - 0, -4789, 0, 0, 0, -4789, -4789, -4789, - -4789, -4789, -4789, -4789, 32767, 32767, 32767, 32767, - -4793, -4793, -4793, 0, 0, -4793, 0, -4793, - -4793, 32767, 32767, 32767, 0, 32767, 32767, 32767, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 2069, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 4017, 32767, 32767, 32767, 2070, - 2071, 2072, 2073, 2074, 2075, 2076, 2077, 22011, - 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, - 2087, 2337, 2337, 2090, 2091, 2092, 2093, 2094, - 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, - 2103, 2104, 2105, -3995, 2107, 2108, 2109, 2110, - 2111, 2112, 2113, 627, 2115, 1486, -5783, -5783, - -5783, 2113, 2113, 2113, -852, 1486, 1486, 1486, - -126, -5791, 5059, 1486, 3571, -16362,-1003, 1486, - -5795, -1004, 1486, 1486, 1486, 1486, -5797, -126, - -5798, 1486, 1486, 1486, 1486, 1486, 1486, 1486, - 1486, -1017, -5806, -1017, -2823, -2823, 1486, 2022, - -2821, -2821, -2821, -2821, 2163, -2820, -2820, -2820, - -2820, -5819, 1486, -2820, -2820, -2820, 4876, -2820, - -2820, -5824, -2819, 2178, -2818, -5042, 1488, -2818, - 1488, 1488, -2818, 1488, -2817, -2817, -2817, -2817, - -2817, -2817, -1461, -1461, 1488, 0, 0, 0, - 0, 0, 0, 0, 0, -19933,0, 0, - 0, 0, 0, 0, 0, 0, 0, -249, - -248, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6101, 0, 0, 0, 0, 0, 0, - 0, 1487, 0, 630, 7900, 7901, 7902, 7, - 8, 9, 2975, 638, 639, 640, 2253, 7919, - -2930, 644, -1440, 18494, 3136, 648, 7930, 3140, - 651, 652, 653, 654, 7938, 2268, 7941, 658, - 659, 660, 661, 662, 663, 664, 665, 3169, - 7959, 3171, 4978, 4979, 671, 136, 4980, 4981, - 4982, 4983, 0, 4984, 4985, 4986, 4987, 7987, - 683, 4990, 4991, 4992, -2703, 4994, 4995, 8000, - 4996, 0, 4997, 7222, 693, 5000, 695, 696, - 5003, 698, 5004, 5005, 5006, 5007, 5008, 5009, - 3654, 3655, 707, 2196, 2197, 2198, 2199, 2200, - 2201, 2202, 2203, 22137, 2205, 2206, 2207, 2208, - 2209, 2210, 2211, 2212, 2213, 2463, 2463, 2216, - 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, - 2225, 2226, 2227, 2228, 2229, 2230, 2231, -3869, - 2233, 2234, 2235, 2236, 2237, 2238, 2239, 753, - 2241, 1612, -5657, -5657, -5657, 2239, 2239, 2239, - -726, 1612, 1612, 1612, 0, -5665, 5185, 1612, - 3697, -16236,-877, 1612, -5669, -878, 1612, 1612, - 1612, 1612, -5671, 0, -5672, 1612, 1612, 1612, - 1612, 1612, 1612, 1612, 1612, -891, -5680, -891, - -2697, -2697, 1612, 5095, 2299, 5097, 2300, 5099, - 2301, 5101, 2302, 5103, 2303, 5105, 2304, 5107, - 2305, 5109, 2306, 5111, 5112, 2307, 5114, 2308, - 32767, 2309, 5117, 5118, 5119, 32767, 5120, 5121, - 5498, 2311, 5124, 2312, 2313, 0, 2314, 2315, - 5126, 2316, 2317, 5129, 2318, 2319, 5132, 32767, - 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, - 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, - 5149, 5150, 5151, 5152, 2320, 5154, 5155, 5156, - 5157, 1377, 2322, 1378, 2324, 5162, 1379, 1379, - 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, - 5173, 5174, 5175, 5176, 2327, 5178, 2328, 5180, - 2329, 5182, 2330, 5184, 2331, 5186, 2332, 5188, - 2333, 5190, 2334, 5192, 2335, 5194, 2336, 5196, - 2337, 5198, 2338, 5200, 5201, 2339, 5203, 2340, - 5205, 1391, 5207, 5208, 5209, 5210, 5211, 5212, - 1385, 1385, -4221, -4221, -4221, -1193, 2346, 2347, - 5221, 2348, 2349, -3412, -4220, -4220, -4220, -4220, - 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, - 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, - 5245, 5246, 5247, 5248, 2352, 5250, 5251, 4592, - -2168, -1982, 2356, 5256, 5257, 5258, 2357, 4444, - 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, - 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, - 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, - 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, - 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, - 5301, 5302, 5303, 5304, 5305, 5306, 32767, 5307, - 5308, 5309, 6427, 6428, 6429, 6430, 6431, 6432, - 6433, 6434, -3465, -3465, 6439, 6440, 6441, 6442, - 6443, 6444, 6445, 6446, -3465, -3465, -3465, -3465, - -3465, -3465, 7724, 2669, 2670, -3430, 2672, 2673, - 2674, 2675, 2676, 7733, 7734, -3465, -3465, -3465, - -3465, -3465, 5341, 5342, -291, -291, -291, -291, - 7390, -3465, -3465, -3465, -3465, -3465, -3465, -3465, - -3465, -3465, -5246, -5246, -5246, -5246, -3465, -3465, - -3465, -3465, -3465, -3465, -3465, -3465, -3465, -3465, - -3465, -3465, -3465, -3465, -3465, -3465, -3465, -3465, - -3465, -3465, -3465, 1591, 1591, 7692, 1591, 1591, - 1591, 1591, 1591, -3465, -3465, -1547, 4593, 4594, - 4595, 606, 4597, -3465, 4572, 4573, 4574, 4575, - -3105, 9632, -5502, -5502, -5502, -5502, -4166, -5502, - 280, 280, 280, 280, 280, 280, 280, 280, - 5428, 5429, 278, 278, 278, 278, 278, 278, - 278, 5437, 5438, 5439, 5440, 5441, 5442, 5443, - 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, - 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, - 5460, 5461, 5462, 5463, 5464, 5465, 5466, 676, - 677, 16037, 679, 5471, 5472, 32767, 32767, 5473, - 0, 5475, 5476, 5477, 5478, 5479, 5480, 5481, - 693, 694, 695, 696, 697, 698, 5488, 700, - 701, 702, 5492, 5493, 5494, 5495, 5496, 5497, - 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, - 713, 714, 5508, 716, 5510, 5511, 5512, 5513, - 5514, 5515, 1138, 2027, 2028, 719, 720, 2030, - 2031, 1144, 9041, 9042, 2477, 2478, 2479, 2480, - 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, - 2489, 2490, 2491, 2492, 5540, 2768, 2768, 2768, - 2768, 5547, -2247, 2499, 2500, 2768, 2768, 558, - 2768, 2768, 2506, 2507, 2508, 2509, 2510, 2511, - 2512, 2513, 8713, 2515, 2516, 2517, 2518, 2519, - 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, - 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, - 2536, 2537, 5587, 5588, 5589, 5590, 5591, 5592, - 5593, 5594, 2538, 0, 0, 0, -1117, -1117, - -1117, -1117, -1117, -1117, -1117, -1117, 8783, 8784, - -1119, -1119, -1119, -1119, -1119, -1119, -1119, -1119, - 8793, 8794, 8795, 8796, 8797, 8798, -2390, 2666, - 2666, 8767, 2666, 2666, 2666, 2666, 2666, -2390, - -2390, 8810, 8811, 8812, 8813, 8814, 9, 9, - 5643, 5644, 5645, 5646, -2034, 8822, 8823, 8824, - 8825, 8826, 8827, 8828, 8829, 8830, 10612, 10613, - 10614, 10615, 8835, 8836, 8837, 8838, 8839, 8840, - 8841, 8842, 8843, 8844, 8845, 8846, 8847, 8848, - 8849, 8850, 8851, 8852, 8853, 8854, 8855, 3800, - 3801, -2299, 3803, 3804, 3805, 3806, 3807, 8864, - 8865, 6948, 809, 809, 809, 4799, 809, 8872, - 836, 836, 836, 836, 8517, -4219, 10916, 10917, - 10918, 10919, 9584, 10921, 5140, 5141, 5142, 5143, - 5144, 5145, 5146, 5147, 0, 0, 5152, 5153, - 5154, 5155, 5156, 5157, 5158, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4791, 4791, -10568,4791, 0, - 0, 4791, 4791, 0, 5474, 0, 0, 0, - 0, 0, 0, 0, 4789, 4789, 4789, 4789, - 4789, 4789, 0, 4789, 4789, 4789, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4793, 4793, 0, 4793, - 0, 0, 0, 0, 0, 0, 4378, 3490, - 3490, 4800, 4800, 3491, 3491, 4379, -3517, -3517, - 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049, - 3049, 3049, 3049, 3049, 3049, 3049, 3049, 3049, - 2, 2775, 2776, 2777, 2778, 0, 7795, 3050, - 3050, 2783, 2784, 4995, 2786, 2787, 3050, 3050, - 3050, 3050, 3050, 2793, 2794, 2795, 2796, 2797, - 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, - 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, - 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, - 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, - 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, - 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, - 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, - 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, - 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, - 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, - 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, - 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, - 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, - 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, - 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, - 2918, 2919, 2920, 2921, 2922, 883, 884, 885, - 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, - 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, - 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, - 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, - 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, - 2966, 2967, 2968, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 4770, 4771, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 0, 0, 0, 0, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 0, 0, 0, 0, 32767, 0, - 0, 0, 0, 0, 0, 0, 0 + 32767, 0, 32767, 0, 32767, 0, 32767, 0, + 32767, 0, 32767, 0, 32767, 0, 32767, 0, + 32767, 0, 32767, 0, 32767, 0, 32767, 0, + 32767, 32767, 0, 32767, 0, 32767, 0, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 0, 32767, + 0, 0, 32767, 0, 0, 32767, 0, 0, + 32767, 0, 0, 32767, 32767, 32767, 32767 }; const unsigned char *k = (const unsigned char *) key; @@ -1750,7 +1767,7 @@ Decomp_hash_func(const void *key) a = a * 257 + c; b = b * 8191 + c; } - return h[a % 13551] + h[b % 13551]; + return h[a % 13687] + h[b % 13687]; } /* Hash lookup information for decomposition */ @@ -1758,15 +1775,15 @@ static const pg_unicode_decompinfo UnicodeDecompInfo = { UnicodeDecompMain, Decomp_hash_func, - 6775 + 6843 }; /* Inverse lookup array -- contains indexes into UnicodeDecompMain[] */ -static const uint16 RecompInverseLookup[941] = +static const uint16 RecompInverseLookup[961] = { - /* U+003C+0338 -> U+226E */ 1857, - /* U+003D+0338 -> U+2260 */ 1854, - /* U+003E+0338 -> U+226F */ 1858, + /* U+003C+0338 -> U+226E */ 1858, + /* U+003D+0338 -> U+2260 */ 1855, + /* U+003E+0338 -> U+226F */ 1859, /* U+0041+0300 -> U+00C0 */ 14, /* U+0041+0301 -> U+00C1 */ 15, /* U+0041+0302 -> U+00C2 */ 16, @@ -1775,60 +1792,60 @@ static const uint16 RecompInverseLookup[941] = /* U+0041+0306 -> U+0102 */ 69, /* U+0041+0307 -> U+0226 */ 270, /* U+0041+0308 -> U+00C4 */ 18, - /* U+0041+0309 -> U+1EA2 */ 1312, + /* U+0041+0309 -> U+1EA2 */ 1313, /* U+0041+030A -> U+00C5 */ 19, /* U+0041+030C -> U+01CD */ 194, /* U+0041+030F -> U+0200 */ 240, /* U+0041+0311 -> U+0202 */ 242, - /* U+0041+0323 -> U+1EA0 */ 1310, - /* U+0041+0325 -> U+1E00 */ 1154, + /* U+0041+0323 -> U+1EA0 */ 1311, + /* U+0041+0325 -> U+1E00 */ 1155, /* U+0041+0328 -> U+0104 */ 71, - /* U+0042+0307 -> U+1E02 */ 1156, - /* U+0042+0323 -> U+1E04 */ 1158, - /* U+0042+0331 -> U+1E06 */ 1160, + /* U+0042+0307 -> U+1E02 */ 1157, + /* U+0042+0323 -> U+1E04 */ 1159, + /* U+0042+0331 -> U+1E06 */ 1161, /* U+0043+0301 -> U+0106 */ 73, /* U+0043+0302 -> U+0108 */ 75, /* U+0043+0307 -> U+010A */ 77, /* U+0043+030C -> U+010C */ 79, /* U+0043+0327 -> U+00C7 */ 20, - /* U+0044+0307 -> U+1E0A */ 1164, + /* U+0044+0307 -> U+1E0A */ 1165, /* U+0044+030C -> U+010E */ 81, - /* U+0044+0323 -> U+1E0C */ 1166, - /* U+0044+0327 -> U+1E10 */ 1170, - /* U+0044+032D -> U+1E12 */ 1172, - /* U+0044+0331 -> U+1E0E */ 1168, + /* U+0044+0323 -> U+1E0C */ 1167, + /* U+0044+0327 -> U+1E10 */ 1171, + /* U+0044+032D -> U+1E12 */ 1173, + /* U+0044+0331 -> U+1E0E */ 1169, /* U+0045+0300 -> U+00C8 */ 21, /* U+0045+0301 -> U+00C9 */ 22, /* U+0045+0302 -> U+00CA */ 23, - /* U+0045+0303 -> U+1EBC */ 1338, + /* U+0045+0303 -> U+1EBC */ 1339, /* U+0045+0304 -> U+0112 */ 83, /* U+0045+0306 -> U+0114 */ 85, /* U+0045+0307 -> U+0116 */ 87, /* U+0045+0308 -> U+00CB */ 24, - /* U+0045+0309 -> U+1EBA */ 1336, + /* U+0045+0309 -> U+1EBA */ 1337, /* U+0045+030C -> U+011A */ 91, /* U+0045+030F -> U+0204 */ 244, /* U+0045+0311 -> U+0206 */ 246, - /* U+0045+0323 -> U+1EB8 */ 1334, + /* U+0045+0323 -> U+1EB8 */ 1335, /* U+0045+0327 -> U+0228 */ 272, /* U+0045+0328 -> U+0118 */ 89, - /* U+0045+032D -> U+1E18 */ 1178, - /* U+0045+0330 -> U+1E1A */ 1180, - /* U+0046+0307 -> U+1E1E */ 1184, + /* U+0045+032D -> U+1E18 */ 1179, + /* U+0045+0330 -> U+1E1A */ 1181, + /* U+0046+0307 -> U+1E1E */ 1185, /* U+0047+0301 -> U+01F4 */ 230, /* U+0047+0302 -> U+011C */ 93, - /* U+0047+0304 -> U+1E20 */ 1186, + /* U+0047+0304 -> U+1E20 */ 1187, /* U+0047+0306 -> U+011E */ 95, /* U+0047+0307 -> U+0120 */ 97, /* U+0047+030C -> U+01E6 */ 216, /* U+0047+0327 -> U+0122 */ 99, /* U+0048+0302 -> U+0124 */ 101, - /* U+0048+0307 -> U+1E22 */ 1188, - /* U+0048+0308 -> U+1E26 */ 1192, + /* U+0048+0307 -> U+1E22 */ 1189, + /* U+0048+0308 -> U+1E26 */ 1193, /* U+0048+030C -> U+021E */ 268, - /* U+0048+0323 -> U+1E24 */ 1190, - /* U+0048+0327 -> U+1E28 */ 1194, - /* U+0048+032E -> U+1E2A */ 1196, + /* U+0048+0323 -> U+1E24 */ 1191, + /* U+0048+0327 -> U+1E28 */ 1195, + /* U+0048+032E -> U+1E2A */ 1197, /* U+0049+0300 -> U+00CC */ 25, /* U+0049+0301 -> U+00CD */ 26, /* U+0049+0302 -> U+00CE */ 27, @@ -1837,37 +1854,37 @@ static const uint16 RecompInverseLookup[941] = /* U+0049+0306 -> U+012C */ 107, /* U+0049+0307 -> U+0130 */ 111, /* U+0049+0308 -> U+00CF */ 28, - /* U+0049+0309 -> U+1EC8 */ 1350, + /* U+0049+0309 -> U+1EC8 */ 1351, /* U+0049+030C -> U+01CF */ 196, /* U+0049+030F -> U+0208 */ 248, /* U+0049+0311 -> U+020A */ 250, - /* U+0049+0323 -> U+1ECA */ 1352, + /* U+0049+0323 -> U+1ECA */ 1353, /* U+0049+0328 -> U+012E */ 109, - /* U+0049+0330 -> U+1E2C */ 1198, + /* U+0049+0330 -> U+1E2C */ 1199, /* U+004A+0302 -> U+0134 */ 114, - /* U+004B+0301 -> U+1E30 */ 1202, + /* U+004B+0301 -> U+1E30 */ 1203, /* U+004B+030C -> U+01E8 */ 218, - /* U+004B+0323 -> U+1E32 */ 1204, + /* U+004B+0323 -> U+1E32 */ 1205, /* U+004B+0327 -> U+0136 */ 116, - /* U+004B+0331 -> U+1E34 */ 1206, + /* U+004B+0331 -> U+1E34 */ 1207, /* U+004C+0301 -> U+0139 */ 118, /* U+004C+030C -> U+013D */ 122, - /* U+004C+0323 -> U+1E36 */ 1208, + /* U+004C+0323 -> U+1E36 */ 1209, /* U+004C+0327 -> U+013B */ 120, - /* U+004C+032D -> U+1E3C */ 1214, - /* U+004C+0331 -> U+1E3A */ 1212, - /* U+004D+0301 -> U+1E3E */ 1216, - /* U+004D+0307 -> U+1E40 */ 1218, - /* U+004D+0323 -> U+1E42 */ 1220, + /* U+004C+032D -> U+1E3C */ 1215, + /* U+004C+0331 -> U+1E3A */ 1213, + /* U+004D+0301 -> U+1E3E */ 1217, + /* U+004D+0307 -> U+1E40 */ 1219, + /* U+004D+0323 -> U+1E42 */ 1221, /* U+004E+0300 -> U+01F8 */ 232, /* U+004E+0301 -> U+0143 */ 126, /* U+004E+0303 -> U+00D1 */ 29, - /* U+004E+0307 -> U+1E44 */ 1222, + /* U+004E+0307 -> U+1E44 */ 1223, /* U+004E+030C -> U+0147 */ 130, - /* U+004E+0323 -> U+1E46 */ 1224, + /* U+004E+0323 -> U+1E46 */ 1225, /* U+004E+0327 -> U+0145 */ 128, - /* U+004E+032D -> U+1E4A */ 1228, - /* U+004E+0331 -> U+1E48 */ 1226, + /* U+004E+032D -> U+1E4A */ 1229, + /* U+004E+0331 -> U+1E48 */ 1227, /* U+004F+0300 -> U+00D2 */ 30, /* U+004F+0301 -> U+00D3 */ 31, /* U+004F+0302 -> U+00D4 */ 32, @@ -1876,38 +1893,38 @@ static const uint16 RecompInverseLookup[941] = /* U+004F+0306 -> U+014E */ 135, /* U+004F+0307 -> U+022E */ 278, /* U+004F+0308 -> U+00D6 */ 34, - /* U+004F+0309 -> U+1ECE */ 1356, + /* U+004F+0309 -> U+1ECE */ 1357, /* U+004F+030B -> U+0150 */ 137, /* U+004F+030C -> U+01D1 */ 198, /* U+004F+030F -> U+020C */ 252, /* U+004F+0311 -> U+020E */ 254, /* U+004F+031B -> U+01A0 */ 181, - /* U+004F+0323 -> U+1ECC */ 1354, + /* U+004F+0323 -> U+1ECC */ 1355, /* U+004F+0328 -> U+01EA */ 220, - /* U+0050+0301 -> U+1E54 */ 1238, - /* U+0050+0307 -> U+1E56 */ 1240, + /* U+0050+0301 -> U+1E54 */ 1239, + /* U+0050+0307 -> U+1E56 */ 1241, /* U+0052+0301 -> U+0154 */ 139, - /* U+0052+0307 -> U+1E58 */ 1242, + /* U+0052+0307 -> U+1E58 */ 1243, /* U+0052+030C -> U+0158 */ 143, /* U+0052+030F -> U+0210 */ 256, /* U+0052+0311 -> U+0212 */ 258, - /* U+0052+0323 -> U+1E5A */ 1244, + /* U+0052+0323 -> U+1E5A */ 1245, /* U+0052+0327 -> U+0156 */ 141, - /* U+0052+0331 -> U+1E5E */ 1248, + /* U+0052+0331 -> U+1E5E */ 1249, /* U+0053+0301 -> U+015A */ 145, /* U+0053+0302 -> U+015C */ 147, - /* U+0053+0307 -> U+1E60 */ 1250, + /* U+0053+0307 -> U+1E60 */ 1251, /* U+0053+030C -> U+0160 */ 151, - /* U+0053+0323 -> U+1E62 */ 1252, + /* U+0053+0323 -> U+1E62 */ 1253, /* U+0053+0326 -> U+0218 */ 264, /* U+0053+0327 -> U+015E */ 149, - /* U+0054+0307 -> U+1E6A */ 1260, + /* U+0054+0307 -> U+1E6A */ 1261, /* U+0054+030C -> U+0164 */ 155, - /* U+0054+0323 -> U+1E6C */ 1262, + /* U+0054+0323 -> U+1E6C */ 1263, /* U+0054+0326 -> U+021A */ 266, /* U+0054+0327 -> U+0162 */ 153, - /* U+0054+032D -> U+1E70 */ 1266, - /* U+0054+0331 -> U+1E6E */ 1264, + /* U+0054+032D -> U+1E70 */ 1267, + /* U+0054+0331 -> U+1E6E */ 1265, /* U+0055+0300 -> U+00D9 */ 35, /* U+0055+0301 -> U+00DA */ 36, /* U+0055+0302 -> U+00DB */ 37, @@ -1915,43 +1932,43 @@ static const uint16 RecompInverseLookup[941] = /* U+0055+0304 -> U+016A */ 159, /* U+0055+0306 -> U+016C */ 161, /* U+0055+0308 -> U+00DC */ 38, - /* U+0055+0309 -> U+1EE6 */ 1380, + /* U+0055+0309 -> U+1EE6 */ 1381, /* U+0055+030A -> U+016E */ 163, /* U+0055+030B -> U+0170 */ 165, /* U+0055+030C -> U+01D3 */ 200, /* U+0055+030F -> U+0214 */ 260, /* U+0055+0311 -> U+0216 */ 262, /* U+0055+031B -> U+01AF */ 183, - /* U+0055+0323 -> U+1EE4 */ 1378, - /* U+0055+0324 -> U+1E72 */ 1268, + /* U+0055+0323 -> U+1EE4 */ 1379, + /* U+0055+0324 -> U+1E72 */ 1269, /* U+0055+0328 -> U+0172 */ 167, - /* U+0055+032D -> U+1E76 */ 1272, - /* U+0055+0330 -> U+1E74 */ 1270, - /* U+0056+0303 -> U+1E7C */ 1278, - /* U+0056+0323 -> U+1E7E */ 1280, - /* U+0057+0300 -> U+1E80 */ 1282, - /* U+0057+0301 -> U+1E82 */ 1284, + /* U+0055+032D -> U+1E76 */ 1273, + /* U+0055+0330 -> U+1E74 */ 1271, + /* U+0056+0303 -> U+1E7C */ 1279, + /* U+0056+0323 -> U+1E7E */ 1281, + /* U+0057+0300 -> U+1E80 */ 1283, + /* U+0057+0301 -> U+1E82 */ 1285, /* U+0057+0302 -> U+0174 */ 169, - /* U+0057+0307 -> U+1E86 */ 1288, - /* U+0057+0308 -> U+1E84 */ 1286, - /* U+0057+0323 -> U+1E88 */ 1290, - /* U+0058+0307 -> U+1E8A */ 1292, - /* U+0058+0308 -> U+1E8C */ 1294, - /* U+0059+0300 -> U+1EF2 */ 1392, + /* U+0057+0307 -> U+1E86 */ 1289, + /* U+0057+0308 -> U+1E84 */ 1287, + /* U+0057+0323 -> U+1E88 */ 1291, + /* U+0058+0307 -> U+1E8A */ 1293, + /* U+0058+0308 -> U+1E8C */ 1295, + /* U+0059+0300 -> U+1EF2 */ 1393, /* U+0059+0301 -> U+00DD */ 39, /* U+0059+0302 -> U+0176 */ 171, - /* U+0059+0303 -> U+1EF8 */ 1398, + /* U+0059+0303 -> U+1EF8 */ 1399, /* U+0059+0304 -> U+0232 */ 282, - /* U+0059+0307 -> U+1E8E */ 1296, + /* U+0059+0307 -> U+1E8E */ 1297, /* U+0059+0308 -> U+0178 */ 173, - /* U+0059+0309 -> U+1EF6 */ 1396, - /* U+0059+0323 -> U+1EF4 */ 1394, + /* U+0059+0309 -> U+1EF6 */ 1397, + /* U+0059+0323 -> U+1EF4 */ 1395, /* U+005A+0301 -> U+0179 */ 174, - /* U+005A+0302 -> U+1E90 */ 1298, + /* U+005A+0302 -> U+1E90 */ 1299, /* U+005A+0307 -> U+017B */ 176, /* U+005A+030C -> U+017D */ 178, - /* U+005A+0323 -> U+1E92 */ 1300, - /* U+005A+0331 -> U+1E94 */ 1302, + /* U+005A+0323 -> U+1E92 */ 1301, + /* U+005A+0331 -> U+1E94 */ 1303, /* U+0061+0300 -> U+00E0 */ 40, /* U+0061+0301 -> U+00E1 */ 41, /* U+0061+0302 -> U+00E2 */ 42, @@ -1960,61 +1977,61 @@ static const uint16 RecompInverseLookup[941] = /* U+0061+0306 -> U+0103 */ 70, /* U+0061+0307 -> U+0227 */ 271, /* U+0061+0308 -> U+00E4 */ 44, - /* U+0061+0309 -> U+1EA3 */ 1313, + /* U+0061+0309 -> U+1EA3 */ 1314, /* U+0061+030A -> U+00E5 */ 45, /* U+0061+030C -> U+01CE */ 195, /* U+0061+030F -> U+0201 */ 241, /* U+0061+0311 -> U+0203 */ 243, - /* U+0061+0323 -> U+1EA1 */ 1311, - /* U+0061+0325 -> U+1E01 */ 1155, + /* U+0061+0323 -> U+1EA1 */ 1312, + /* U+0061+0325 -> U+1E01 */ 1156, /* U+0061+0328 -> U+0105 */ 72, - /* U+0062+0307 -> U+1E03 */ 1157, - /* U+0062+0323 -> U+1E05 */ 1159, - /* U+0062+0331 -> U+1E07 */ 1161, + /* U+0062+0307 -> U+1E03 */ 1158, + /* U+0062+0323 -> U+1E05 */ 1160, + /* U+0062+0331 -> U+1E07 */ 1162, /* U+0063+0301 -> U+0107 */ 74, /* U+0063+0302 -> U+0109 */ 76, /* U+0063+0307 -> U+010B */ 78, /* U+0063+030C -> U+010D */ 80, /* U+0063+0327 -> U+00E7 */ 46, - /* U+0064+0307 -> U+1E0B */ 1165, + /* U+0064+0307 -> U+1E0B */ 1166, /* U+0064+030C -> U+010F */ 82, - /* U+0064+0323 -> U+1E0D */ 1167, - /* U+0064+0327 -> U+1E11 */ 1171, - /* U+0064+032D -> U+1E13 */ 1173, - /* U+0064+0331 -> U+1E0F */ 1169, + /* U+0064+0323 -> U+1E0D */ 1168, + /* U+0064+0327 -> U+1E11 */ 1172, + /* U+0064+032D -> U+1E13 */ 1174, + /* U+0064+0331 -> U+1E0F */ 1170, /* U+0065+0300 -> U+00E8 */ 47, /* U+0065+0301 -> U+00E9 */ 48, /* U+0065+0302 -> U+00EA */ 49, - /* U+0065+0303 -> U+1EBD */ 1339, + /* U+0065+0303 -> U+1EBD */ 1340, /* U+0065+0304 -> U+0113 */ 84, /* U+0065+0306 -> U+0115 */ 86, /* U+0065+0307 -> U+0117 */ 88, /* U+0065+0308 -> U+00EB */ 50, - /* U+0065+0309 -> U+1EBB */ 1337, + /* U+0065+0309 -> U+1EBB */ 1338, /* U+0065+030C -> U+011B */ 92, /* U+0065+030F -> U+0205 */ 245, /* U+0065+0311 -> U+0207 */ 247, - /* U+0065+0323 -> U+1EB9 */ 1335, + /* U+0065+0323 -> U+1EB9 */ 1336, /* U+0065+0327 -> U+0229 */ 273, /* U+0065+0328 -> U+0119 */ 90, - /* U+0065+032D -> U+1E19 */ 1179, - /* U+0065+0330 -> U+1E1B */ 1181, - /* U+0066+0307 -> U+1E1F */ 1185, + /* U+0065+032D -> U+1E19 */ 1180, + /* U+0065+0330 -> U+1E1B */ 1182, + /* U+0066+0307 -> U+1E1F */ 1186, /* U+0067+0301 -> U+01F5 */ 231, /* U+0067+0302 -> U+011D */ 94, - /* U+0067+0304 -> U+1E21 */ 1187, + /* U+0067+0304 -> U+1E21 */ 1188, /* U+0067+0306 -> U+011F */ 96, /* U+0067+0307 -> U+0121 */ 98, /* U+0067+030C -> U+01E7 */ 217, /* U+0067+0327 -> U+0123 */ 100, /* U+0068+0302 -> U+0125 */ 102, - /* U+0068+0307 -> U+1E23 */ 1189, - /* U+0068+0308 -> U+1E27 */ 1193, + /* U+0068+0307 -> U+1E23 */ 1190, + /* U+0068+0308 -> U+1E27 */ 1194, /* U+0068+030C -> U+021F */ 269, - /* U+0068+0323 -> U+1E25 */ 1191, - /* U+0068+0327 -> U+1E29 */ 1195, - /* U+0068+032E -> U+1E2B */ 1197, - /* U+0068+0331 -> U+1E96 */ 1304, + /* U+0068+0323 -> U+1E25 */ 1192, + /* U+0068+0327 -> U+1E29 */ 1196, + /* U+0068+032E -> U+1E2B */ 1198, + /* U+0068+0331 -> U+1E96 */ 1305, /* U+0069+0300 -> U+00EC */ 51, /* U+0069+0301 -> U+00ED */ 52, /* U+0069+0302 -> U+00EE */ 53, @@ -2022,38 +2039,38 @@ static const uint16 RecompInverseLookup[941] = /* U+0069+0304 -> U+012B */ 106, /* U+0069+0306 -> U+012D */ 108, /* U+0069+0308 -> U+00EF */ 54, - /* U+0069+0309 -> U+1EC9 */ 1351, + /* U+0069+0309 -> U+1EC9 */ 1352, /* U+0069+030C -> U+01D0 */ 197, /* U+0069+030F -> U+0209 */ 249, /* U+0069+0311 -> U+020B */ 251, - /* U+0069+0323 -> U+1ECB */ 1353, + /* U+0069+0323 -> U+1ECB */ 1354, /* U+0069+0328 -> U+012F */ 110, - /* U+0069+0330 -> U+1E2D */ 1199, + /* U+0069+0330 -> U+1E2D */ 1200, /* U+006A+0302 -> U+0135 */ 115, /* U+006A+030C -> U+01F0 */ 226, - /* U+006B+0301 -> U+1E31 */ 1203, + /* U+006B+0301 -> U+1E31 */ 1204, /* U+006B+030C -> U+01E9 */ 219, - /* U+006B+0323 -> U+1E33 */ 1205, + /* U+006B+0323 -> U+1E33 */ 1206, /* U+006B+0327 -> U+0137 */ 117, - /* U+006B+0331 -> U+1E35 */ 1207, + /* U+006B+0331 -> U+1E35 */ 1208, /* U+006C+0301 -> U+013A */ 119, /* U+006C+030C -> U+013E */ 123, - /* U+006C+0323 -> U+1E37 */ 1209, + /* U+006C+0323 -> U+1E37 */ 1210, /* U+006C+0327 -> U+013C */ 121, - /* U+006C+032D -> U+1E3D */ 1215, - /* U+006C+0331 -> U+1E3B */ 1213, - /* U+006D+0301 -> U+1E3F */ 1217, - /* U+006D+0307 -> U+1E41 */ 1219, - /* U+006D+0323 -> U+1E43 */ 1221, + /* U+006C+032D -> U+1E3D */ 1216, + /* U+006C+0331 -> U+1E3B */ 1214, + /* U+006D+0301 -> U+1E3F */ 1218, + /* U+006D+0307 -> U+1E41 */ 1220, + /* U+006D+0323 -> U+1E43 */ 1222, /* U+006E+0300 -> U+01F9 */ 233, /* U+006E+0301 -> U+0144 */ 127, /* U+006E+0303 -> U+00F1 */ 55, - /* U+006E+0307 -> U+1E45 */ 1223, + /* U+006E+0307 -> U+1E45 */ 1224, /* U+006E+030C -> U+0148 */ 131, - /* U+006E+0323 -> U+1E47 */ 1225, + /* U+006E+0323 -> U+1E47 */ 1226, /* U+006E+0327 -> U+0146 */ 129, - /* U+006E+032D -> U+1E4B */ 1229, - /* U+006E+0331 -> U+1E49 */ 1227, + /* U+006E+032D -> U+1E4B */ 1230, + /* U+006E+0331 -> U+1E49 */ 1228, /* U+006F+0300 -> U+00F2 */ 56, /* U+006F+0301 -> U+00F3 */ 57, /* U+006F+0302 -> U+00F4 */ 58, @@ -2062,39 +2079,39 @@ static const uint16 RecompInverseLookup[941] = /* U+006F+0306 -> U+014F */ 136, /* U+006F+0307 -> U+022F */ 279, /* U+006F+0308 -> U+00F6 */ 60, - /* U+006F+0309 -> U+1ECF */ 1357, + /* U+006F+0309 -> U+1ECF */ 1358, /* U+006F+030B -> U+0151 */ 138, /* U+006F+030C -> U+01D2 */ 199, /* U+006F+030F -> U+020D */ 253, /* U+006F+0311 -> U+020F */ 255, /* U+006F+031B -> U+01A1 */ 182, - /* U+006F+0323 -> U+1ECD */ 1355, + /* U+006F+0323 -> U+1ECD */ 1356, /* U+006F+0328 -> U+01EB */ 221, - /* U+0070+0301 -> U+1E55 */ 1239, - /* U+0070+0307 -> U+1E57 */ 1241, + /* U+0070+0301 -> U+1E55 */ 1240, + /* U+0070+0307 -> U+1E57 */ 1242, /* U+0072+0301 -> U+0155 */ 140, - /* U+0072+0307 -> U+1E59 */ 1243, + /* U+0072+0307 -> U+1E59 */ 1244, /* U+0072+030C -> U+0159 */ 144, /* U+0072+030F -> U+0211 */ 257, /* U+0072+0311 -> U+0213 */ 259, - /* U+0072+0323 -> U+1E5B */ 1245, + /* U+0072+0323 -> U+1E5B */ 1246, /* U+0072+0327 -> U+0157 */ 142, - /* U+0072+0331 -> U+1E5F */ 1249, + /* U+0072+0331 -> U+1E5F */ 1250, /* U+0073+0301 -> U+015B */ 146, /* U+0073+0302 -> U+015D */ 148, - /* U+0073+0307 -> U+1E61 */ 1251, + /* U+0073+0307 -> U+1E61 */ 1252, /* U+0073+030C -> U+0161 */ 152, - /* U+0073+0323 -> U+1E63 */ 1253, + /* U+0073+0323 -> U+1E63 */ 1254, /* U+0073+0326 -> U+0219 */ 265, /* U+0073+0327 -> U+015F */ 150, - /* U+0074+0307 -> U+1E6B */ 1261, - /* U+0074+0308 -> U+1E97 */ 1305, + /* U+0074+0307 -> U+1E6B */ 1262, + /* U+0074+0308 -> U+1E97 */ 1306, /* U+0074+030C -> U+0165 */ 156, - /* U+0074+0323 -> U+1E6D */ 1263, + /* U+0074+0323 -> U+1E6D */ 1264, /* U+0074+0326 -> U+021B */ 267, /* U+0074+0327 -> U+0163 */ 154, - /* U+0074+032D -> U+1E71 */ 1267, - /* U+0074+0331 -> U+1E6F */ 1265, + /* U+0074+032D -> U+1E71 */ 1268, + /* U+0074+0331 -> U+1E6F */ 1266, /* U+0075+0300 -> U+00F9 */ 61, /* U+0075+0301 -> U+00FA */ 62, /* U+0075+0302 -> U+00FB */ 63, @@ -2102,251 +2119,251 @@ static const uint16 RecompInverseLookup[941] = /* U+0075+0304 -> U+016B */ 160, /* U+0075+0306 -> U+016D */ 162, /* U+0075+0308 -> U+00FC */ 64, - /* U+0075+0309 -> U+1EE7 */ 1381, + /* U+0075+0309 -> U+1EE7 */ 1382, /* U+0075+030A -> U+016F */ 164, /* U+0075+030B -> U+0171 */ 166, /* U+0075+030C -> U+01D4 */ 201, /* U+0075+030F -> U+0215 */ 261, /* U+0075+0311 -> U+0217 */ 263, /* U+0075+031B -> U+01B0 */ 184, - /* U+0075+0323 -> U+1EE5 */ 1379, - /* U+0075+0324 -> U+1E73 */ 1269, + /* U+0075+0323 -> U+1EE5 */ 1380, + /* U+0075+0324 -> U+1E73 */ 1270, /* U+0075+0328 -> U+0173 */ 168, - /* U+0075+032D -> U+1E77 */ 1273, - /* U+0075+0330 -> U+1E75 */ 1271, - /* U+0076+0303 -> U+1E7D */ 1279, - /* U+0076+0323 -> U+1E7F */ 1281, - /* U+0077+0300 -> U+1E81 */ 1283, - /* U+0077+0301 -> U+1E83 */ 1285, + /* U+0075+032D -> U+1E77 */ 1274, + /* U+0075+0330 -> U+1E75 */ 1272, + /* U+0076+0303 -> U+1E7D */ 1280, + /* U+0076+0323 -> U+1E7F */ 1282, + /* U+0077+0300 -> U+1E81 */ 1284, + /* U+0077+0301 -> U+1E83 */ 1286, /* U+0077+0302 -> U+0175 */ 170, - /* U+0077+0307 -> U+1E87 */ 1289, - /* U+0077+0308 -> U+1E85 */ 1287, - /* U+0077+030A -> U+1E98 */ 1306, - /* U+0077+0323 -> U+1E89 */ 1291, - /* U+0078+0307 -> U+1E8B */ 1293, - /* U+0078+0308 -> U+1E8D */ 1295, - /* U+0079+0300 -> U+1EF3 */ 1393, + /* U+0077+0307 -> U+1E87 */ 1290, + /* U+0077+0308 -> U+1E85 */ 1288, + /* U+0077+030A -> U+1E98 */ 1307, + /* U+0077+0323 -> U+1E89 */ 1292, + /* U+0078+0307 -> U+1E8B */ 1294, + /* U+0078+0308 -> U+1E8D */ 1296, + /* U+0079+0300 -> U+1EF3 */ 1394, /* U+0079+0301 -> U+00FD */ 65, /* U+0079+0302 -> U+0177 */ 172, - /* U+0079+0303 -> U+1EF9 */ 1399, + /* U+0079+0303 -> U+1EF9 */ 1400, /* U+0079+0304 -> U+0233 */ 283, - /* U+0079+0307 -> U+1E8F */ 1297, + /* U+0079+0307 -> U+1E8F */ 1298, /* U+0079+0308 -> U+00FF */ 66, - /* U+0079+0309 -> U+1EF7 */ 1397, - /* U+0079+030A -> U+1E99 */ 1307, - /* U+0079+0323 -> U+1EF5 */ 1395, + /* U+0079+0309 -> U+1EF7 */ 1398, + /* U+0079+030A -> U+1E99 */ 1308, + /* U+0079+0323 -> U+1EF5 */ 1396, /* U+007A+0301 -> U+017A */ 175, - /* U+007A+0302 -> U+1E91 */ 1299, + /* U+007A+0302 -> U+1E91 */ 1300, /* U+007A+0307 -> U+017C */ 177, /* U+007A+030C -> U+017E */ 179, - /* U+007A+0323 -> U+1E93 */ 1301, - /* U+007A+0331 -> U+1E95 */ 1303, - /* U+00A8+0300 -> U+1FED */ 1618, + /* U+007A+0323 -> U+1E93 */ 1302, + /* U+007A+0331 -> U+1E95 */ 1304, + /* U+00A8+0300 -> U+1FED */ 1619, /* U+00A8+0301 -> U+0385 */ 419, - /* U+00A8+0342 -> U+1FC1 */ 1578, - /* U+00C2+0300 -> U+1EA6 */ 1316, - /* U+00C2+0301 -> U+1EA4 */ 1314, - /* U+00C2+0303 -> U+1EAA */ 1320, - /* U+00C2+0309 -> U+1EA8 */ 1318, + /* U+00A8+0342 -> U+1FC1 */ 1579, + /* U+00C2+0300 -> U+1EA6 */ 1317, + /* U+00C2+0301 -> U+1EA4 */ 1315, + /* U+00C2+0303 -> U+1EAA */ 1321, + /* U+00C2+0309 -> U+1EA8 */ 1319, /* U+00C4+0304 -> U+01DE */ 210, /* U+00C5+0301 -> U+01FA */ 234, /* U+00C6+0301 -> U+01FC */ 236, /* U+00C6+0304 -> U+01E2 */ 214, - /* U+00C7+0301 -> U+1E08 */ 1162, - /* U+00CA+0300 -> U+1EC0 */ 1342, - /* U+00CA+0301 -> U+1EBE */ 1340, - /* U+00CA+0303 -> U+1EC4 */ 1346, - /* U+00CA+0309 -> U+1EC2 */ 1344, - /* U+00CF+0301 -> U+1E2E */ 1200, - /* U+00D4+0300 -> U+1ED2 */ 1360, - /* U+00D4+0301 -> U+1ED0 */ 1358, - /* U+00D4+0303 -> U+1ED6 */ 1364, - /* U+00D4+0309 -> U+1ED4 */ 1362, - /* U+00D5+0301 -> U+1E4C */ 1230, + /* U+00C7+0301 -> U+1E08 */ 1163, + /* U+00CA+0300 -> U+1EC0 */ 1343, + /* U+00CA+0301 -> U+1EBE */ 1341, + /* U+00CA+0303 -> U+1EC4 */ 1347, + /* U+00CA+0309 -> U+1EC2 */ 1345, + /* U+00CF+0301 -> U+1E2E */ 1201, + /* U+00D4+0300 -> U+1ED2 */ 1361, + /* U+00D4+0301 -> U+1ED0 */ 1359, + /* U+00D4+0303 -> U+1ED6 */ 1365, + /* U+00D4+0309 -> U+1ED4 */ 1363, + /* U+00D5+0301 -> U+1E4C */ 1231, /* U+00D5+0304 -> U+022C */ 276, - /* U+00D5+0308 -> U+1E4E */ 1232, + /* U+00D5+0308 -> U+1E4E */ 1233, /* U+00D6+0304 -> U+022A */ 274, /* U+00D8+0301 -> U+01FE */ 238, /* U+00DC+0300 -> U+01DB */ 208, /* U+00DC+0301 -> U+01D7 */ 204, /* U+00DC+0304 -> U+01D5 */ 202, /* U+00DC+030C -> U+01D9 */ 206, - /* U+00E2+0300 -> U+1EA7 */ 1317, - /* U+00E2+0301 -> U+1EA5 */ 1315, - /* U+00E2+0303 -> U+1EAB */ 1321, - /* U+00E2+0309 -> U+1EA9 */ 1319, + /* U+00E2+0300 -> U+1EA7 */ 1318, + /* U+00E2+0301 -> U+1EA5 */ 1316, + /* U+00E2+0303 -> U+1EAB */ 1322, + /* U+00E2+0309 -> U+1EA9 */ 1320, /* U+00E4+0304 -> U+01DF */ 211, /* U+00E5+0301 -> U+01FB */ 235, /* U+00E6+0301 -> U+01FD */ 237, /* U+00E6+0304 -> U+01E3 */ 215, - /* U+00E7+0301 -> U+1E09 */ 1163, - /* U+00EA+0300 -> U+1EC1 */ 1343, - /* U+00EA+0301 -> U+1EBF */ 1341, - /* U+00EA+0303 -> U+1EC5 */ 1347, - /* U+00EA+0309 -> U+1EC3 */ 1345, - /* U+00EF+0301 -> U+1E2F */ 1201, - /* U+00F4+0300 -> U+1ED3 */ 1361, - /* U+00F4+0301 -> U+1ED1 */ 1359, - /* U+00F4+0303 -> U+1ED7 */ 1365, - /* U+00F4+0309 -> U+1ED5 */ 1363, - /* U+00F5+0301 -> U+1E4D */ 1231, + /* U+00E7+0301 -> U+1E09 */ 1164, + /* U+00EA+0300 -> U+1EC1 */ 1344, + /* U+00EA+0301 -> U+1EBF */ 1342, + /* U+00EA+0303 -> U+1EC5 */ 1348, + /* U+00EA+0309 -> U+1EC3 */ 1346, + /* U+00EF+0301 -> U+1E2F */ 1202, + /* U+00F4+0300 -> U+1ED3 */ 1362, + /* U+00F4+0301 -> U+1ED1 */ 1360, + /* U+00F4+0303 -> U+1ED7 */ 1366, + /* U+00F4+0309 -> U+1ED5 */ 1364, + /* U+00F5+0301 -> U+1E4D */ 1232, /* U+00F5+0304 -> U+022D */ 277, - /* U+00F5+0308 -> U+1E4F */ 1233, + /* U+00F5+0308 -> U+1E4F */ 1234, /* U+00F6+0304 -> U+022B */ 275, /* U+00F8+0301 -> U+01FF */ 239, /* U+00FC+0300 -> U+01DC */ 209, /* U+00FC+0301 -> U+01D8 */ 205, /* U+00FC+0304 -> U+01D6 */ 203, /* U+00FC+030C -> U+01DA */ 207, - /* U+0102+0300 -> U+1EB0 */ 1326, - /* U+0102+0301 -> U+1EAE */ 1324, - /* U+0102+0303 -> U+1EB4 */ 1330, - /* U+0102+0309 -> U+1EB2 */ 1328, - /* U+0103+0300 -> U+1EB1 */ 1327, - /* U+0103+0301 -> U+1EAF */ 1325, - /* U+0103+0303 -> U+1EB5 */ 1331, - /* U+0103+0309 -> U+1EB3 */ 1329, - /* U+0112+0300 -> U+1E14 */ 1174, - /* U+0112+0301 -> U+1E16 */ 1176, - /* U+0113+0300 -> U+1E15 */ 1175, - /* U+0113+0301 -> U+1E17 */ 1177, - /* U+014C+0300 -> U+1E50 */ 1234, - /* U+014C+0301 -> U+1E52 */ 1236, - /* U+014D+0300 -> U+1E51 */ 1235, - /* U+014D+0301 -> U+1E53 */ 1237, - /* U+015A+0307 -> U+1E64 */ 1254, - /* U+015B+0307 -> U+1E65 */ 1255, - /* U+0160+0307 -> U+1E66 */ 1256, - /* U+0161+0307 -> U+1E67 */ 1257, - /* U+0168+0301 -> U+1E78 */ 1274, - /* U+0169+0301 -> U+1E79 */ 1275, - /* U+016A+0308 -> U+1E7A */ 1276, - /* U+016B+0308 -> U+1E7B */ 1277, - /* U+017F+0307 -> U+1E9B */ 1309, - /* U+01A0+0300 -> U+1EDC */ 1370, - /* U+01A0+0301 -> U+1EDA */ 1368, - /* U+01A0+0303 -> U+1EE0 */ 1374, - /* U+01A0+0309 -> U+1EDE */ 1372, - /* U+01A0+0323 -> U+1EE2 */ 1376, - /* U+01A1+0300 -> U+1EDD */ 1371, - /* U+01A1+0301 -> U+1EDB */ 1369, - /* U+01A1+0303 -> U+1EE1 */ 1375, - /* U+01A1+0309 -> U+1EDF */ 1373, - /* U+01A1+0323 -> U+1EE3 */ 1377, - /* U+01AF+0300 -> U+1EEA */ 1384, - /* U+01AF+0301 -> U+1EE8 */ 1382, - /* U+01AF+0303 -> U+1EEE */ 1388, - /* U+01AF+0309 -> U+1EEC */ 1386, - /* U+01AF+0323 -> U+1EF0 */ 1390, - /* U+01B0+0300 -> U+1EEB */ 1385, - /* U+01B0+0301 -> U+1EE9 */ 1383, - /* U+01B0+0303 -> U+1EEF */ 1389, - /* U+01B0+0309 -> U+1EED */ 1387, - /* U+01B0+0323 -> U+1EF1 */ 1391, + /* U+0102+0300 -> U+1EB0 */ 1327, + /* U+0102+0301 -> U+1EAE */ 1325, + /* U+0102+0303 -> U+1EB4 */ 1331, + /* U+0102+0309 -> U+1EB2 */ 1329, + /* U+0103+0300 -> U+1EB1 */ 1328, + /* U+0103+0301 -> U+1EAF */ 1326, + /* U+0103+0303 -> U+1EB5 */ 1332, + /* U+0103+0309 -> U+1EB3 */ 1330, + /* U+0112+0300 -> U+1E14 */ 1175, + /* U+0112+0301 -> U+1E16 */ 1177, + /* U+0113+0300 -> U+1E15 */ 1176, + /* U+0113+0301 -> U+1E17 */ 1178, + /* U+014C+0300 -> U+1E50 */ 1235, + /* U+014C+0301 -> U+1E52 */ 1237, + /* U+014D+0300 -> U+1E51 */ 1236, + /* U+014D+0301 -> U+1E53 */ 1238, + /* U+015A+0307 -> U+1E64 */ 1255, + /* U+015B+0307 -> U+1E65 */ 1256, + /* U+0160+0307 -> U+1E66 */ 1257, + /* U+0161+0307 -> U+1E67 */ 1258, + /* U+0168+0301 -> U+1E78 */ 1275, + /* U+0169+0301 -> U+1E79 */ 1276, + /* U+016A+0308 -> U+1E7A */ 1277, + /* U+016B+0308 -> U+1E7B */ 1278, + /* U+017F+0307 -> U+1E9B */ 1310, + /* U+01A0+0300 -> U+1EDC */ 1371, + /* U+01A0+0301 -> U+1EDA */ 1369, + /* U+01A0+0303 -> U+1EE0 */ 1375, + /* U+01A0+0309 -> U+1EDE */ 1373, + /* U+01A0+0323 -> U+1EE2 */ 1377, + /* U+01A1+0300 -> U+1EDD */ 1372, + /* U+01A1+0301 -> U+1EDB */ 1370, + /* U+01A1+0303 -> U+1EE1 */ 1376, + /* U+01A1+0309 -> U+1EDF */ 1374, + /* U+01A1+0323 -> U+1EE3 */ 1378, + /* U+01AF+0300 -> U+1EEA */ 1385, + /* U+01AF+0301 -> U+1EE8 */ 1383, + /* U+01AF+0303 -> U+1EEE */ 1389, + /* U+01AF+0309 -> U+1EEC */ 1387, + /* U+01AF+0323 -> U+1EF0 */ 1391, + /* U+01B0+0300 -> U+1EEB */ 1386, + /* U+01B0+0301 -> U+1EE9 */ 1384, + /* U+01B0+0303 -> U+1EEF */ 1390, + /* U+01B0+0309 -> U+1EED */ 1388, + /* U+01B0+0323 -> U+1EF1 */ 1392, /* U+01B7+030C -> U+01EE */ 224, /* U+01EA+0304 -> U+01EC */ 222, /* U+01EB+0304 -> U+01ED */ 223, /* U+0226+0304 -> U+01E0 */ 212, /* U+0227+0304 -> U+01E1 */ 213, - /* U+0228+0306 -> U+1E1C */ 1182, - /* U+0229+0306 -> U+1E1D */ 1183, + /* U+0228+0306 -> U+1E1C */ 1183, + /* U+0229+0306 -> U+1E1D */ 1184, /* U+022E+0304 -> U+0230 */ 280, /* U+022F+0304 -> U+0231 */ 281, /* U+0292+030C -> U+01EF */ 225, - /* U+0391+0300 -> U+1FBA */ 1571, + /* U+0391+0300 -> U+1FBA */ 1572, /* U+0391+0301 -> U+0386 */ 420, - /* U+0391+0304 -> U+1FB9 */ 1570, - /* U+0391+0306 -> U+1FB8 */ 1569, - /* U+0391+0313 -> U+1F08 */ 1408, - /* U+0391+0314 -> U+1F09 */ 1409, - /* U+0391+0345 -> U+1FBC */ 1573, - /* U+0395+0300 -> U+1FC8 */ 1584, + /* U+0391+0304 -> U+1FB9 */ 1571, + /* U+0391+0306 -> U+1FB8 */ 1570, + /* U+0391+0313 -> U+1F08 */ 1409, + /* U+0391+0314 -> U+1F09 */ 1410, + /* U+0391+0345 -> U+1FBC */ 1574, + /* U+0395+0300 -> U+1FC8 */ 1585, /* U+0395+0301 -> U+0388 */ 422, - /* U+0395+0313 -> U+1F18 */ 1422, - /* U+0395+0314 -> U+1F19 */ 1423, - /* U+0397+0300 -> U+1FCA */ 1586, + /* U+0395+0313 -> U+1F18 */ 1423, + /* U+0395+0314 -> U+1F19 */ 1424, + /* U+0397+0300 -> U+1FCA */ 1587, /* U+0397+0301 -> U+0389 */ 423, - /* U+0397+0313 -> U+1F28 */ 1436, - /* U+0397+0314 -> U+1F29 */ 1437, - /* U+0397+0345 -> U+1FCC */ 1588, - /* U+0399+0300 -> U+1FDA */ 1600, + /* U+0397+0313 -> U+1F28 */ 1437, + /* U+0397+0314 -> U+1F29 */ 1438, + /* U+0397+0345 -> U+1FCC */ 1589, + /* U+0399+0300 -> U+1FDA */ 1601, /* U+0399+0301 -> U+038A */ 424, - /* U+0399+0304 -> U+1FD9 */ 1599, - /* U+0399+0306 -> U+1FD8 */ 1598, + /* U+0399+0304 -> U+1FD9 */ 1600, + /* U+0399+0306 -> U+1FD8 */ 1599, /* U+0399+0308 -> U+03AA */ 429, - /* U+0399+0313 -> U+1F38 */ 1452, - /* U+0399+0314 -> U+1F39 */ 1453, - /* U+039F+0300 -> U+1FF8 */ 1626, + /* U+0399+0313 -> U+1F38 */ 1453, + /* U+0399+0314 -> U+1F39 */ 1454, + /* U+039F+0300 -> U+1FF8 */ 1627, /* U+039F+0301 -> U+038C */ 425, - /* U+039F+0313 -> U+1F48 */ 1466, - /* U+039F+0314 -> U+1F49 */ 1467, - /* U+03A1+0314 -> U+1FEC */ 1617, - /* U+03A5+0300 -> U+1FEA */ 1615, + /* U+039F+0313 -> U+1F48 */ 1467, + /* U+039F+0314 -> U+1F49 */ 1468, + /* U+03A1+0314 -> U+1FEC */ 1618, + /* U+03A5+0300 -> U+1FEA */ 1616, /* U+03A5+0301 -> U+038E */ 426, - /* U+03A5+0304 -> U+1FE9 */ 1614, - /* U+03A5+0306 -> U+1FE8 */ 1613, + /* U+03A5+0304 -> U+1FE9 */ 1615, + /* U+03A5+0306 -> U+1FE8 */ 1614, /* U+03A5+0308 -> U+03AB */ 430, - /* U+03A5+0314 -> U+1F59 */ 1480, - /* U+03A9+0300 -> U+1FFA */ 1628, + /* U+03A5+0314 -> U+1F59 */ 1481, + /* U+03A9+0300 -> U+1FFA */ 1629, /* U+03A9+0301 -> U+038F */ 427, - /* U+03A9+0313 -> U+1F68 */ 1492, - /* U+03A9+0314 -> U+1F69 */ 1493, - /* U+03A9+0345 -> U+1FFC */ 1630, - /* U+03AC+0345 -> U+1FB4 */ 1566, - /* U+03AE+0345 -> U+1FC4 */ 1581, - /* U+03B1+0300 -> U+1F70 */ 1500, + /* U+03A9+0313 -> U+1F68 */ 1493, + /* U+03A9+0314 -> U+1F69 */ 1494, + /* U+03A9+0345 -> U+1FFC */ 1631, + /* U+03AC+0345 -> U+1FB4 */ 1567, + /* U+03AE+0345 -> U+1FC4 */ 1582, + /* U+03B1+0300 -> U+1F70 */ 1501, /* U+03B1+0301 -> U+03AC */ 431, - /* U+03B1+0304 -> U+1FB1 */ 1563, - /* U+03B1+0306 -> U+1FB0 */ 1562, - /* U+03B1+0313 -> U+1F00 */ 1400, - /* U+03B1+0314 -> U+1F01 */ 1401, - /* U+03B1+0342 -> U+1FB6 */ 1567, - /* U+03B1+0345 -> U+1FB3 */ 1565, - /* U+03B5+0300 -> U+1F72 */ 1502, + /* U+03B1+0304 -> U+1FB1 */ 1564, + /* U+03B1+0306 -> U+1FB0 */ 1563, + /* U+03B1+0313 -> U+1F00 */ 1401, + /* U+03B1+0314 -> U+1F01 */ 1402, + /* U+03B1+0342 -> U+1FB6 */ 1568, + /* U+03B1+0345 -> U+1FB3 */ 1566, + /* U+03B5+0300 -> U+1F72 */ 1503, /* U+03B5+0301 -> U+03AD */ 432, - /* U+03B5+0313 -> U+1F10 */ 1416, - /* U+03B5+0314 -> U+1F11 */ 1417, - /* U+03B7+0300 -> U+1F74 */ 1504, + /* U+03B5+0313 -> U+1F10 */ 1417, + /* U+03B5+0314 -> U+1F11 */ 1418, + /* U+03B7+0300 -> U+1F74 */ 1505, /* U+03B7+0301 -> U+03AE */ 433, - /* U+03B7+0313 -> U+1F20 */ 1428, - /* U+03B7+0314 -> U+1F21 */ 1429, - /* U+03B7+0342 -> U+1FC6 */ 1582, - /* U+03B7+0345 -> U+1FC3 */ 1580, - /* U+03B9+0300 -> U+1F76 */ 1506, + /* U+03B7+0313 -> U+1F20 */ 1429, + /* U+03B7+0314 -> U+1F21 */ 1430, + /* U+03B7+0342 -> U+1FC6 */ 1583, + /* U+03B7+0345 -> U+1FC3 */ 1581, + /* U+03B9+0300 -> U+1F76 */ 1507, /* U+03B9+0301 -> U+03AF */ 434, - /* U+03B9+0304 -> U+1FD1 */ 1593, - /* U+03B9+0306 -> U+1FD0 */ 1592, + /* U+03B9+0304 -> U+1FD1 */ 1594, + /* U+03B9+0306 -> U+1FD0 */ 1593, /* U+03B9+0308 -> U+03CA */ 436, - /* U+03B9+0313 -> U+1F30 */ 1444, - /* U+03B9+0314 -> U+1F31 */ 1445, - /* U+03B9+0342 -> U+1FD6 */ 1596, - /* U+03BF+0300 -> U+1F78 */ 1508, + /* U+03B9+0313 -> U+1F30 */ 1445, + /* U+03B9+0314 -> U+1F31 */ 1446, + /* U+03B9+0342 -> U+1FD6 */ 1597, + /* U+03BF+0300 -> U+1F78 */ 1509, /* U+03BF+0301 -> U+03CC */ 438, - /* U+03BF+0313 -> U+1F40 */ 1460, - /* U+03BF+0314 -> U+1F41 */ 1461, - /* U+03C1+0313 -> U+1FE4 */ 1609, - /* U+03C1+0314 -> U+1FE5 */ 1610, - /* U+03C5+0300 -> U+1F7A */ 1510, + /* U+03BF+0313 -> U+1F40 */ 1461, + /* U+03BF+0314 -> U+1F41 */ 1462, + /* U+03C1+0313 -> U+1FE4 */ 1610, + /* U+03C1+0314 -> U+1FE5 */ 1611, + /* U+03C5+0300 -> U+1F7A */ 1511, /* U+03C5+0301 -> U+03CD */ 439, - /* U+03C5+0304 -> U+1FE1 */ 1606, - /* U+03C5+0306 -> U+1FE0 */ 1605, + /* U+03C5+0304 -> U+1FE1 */ 1607, + /* U+03C5+0306 -> U+1FE0 */ 1606, /* U+03C5+0308 -> U+03CB */ 437, - /* U+03C5+0313 -> U+1F50 */ 1472, - /* U+03C5+0314 -> U+1F51 */ 1473, - /* U+03C5+0342 -> U+1FE6 */ 1611, - /* U+03C9+0300 -> U+1F7C */ 1512, + /* U+03C5+0313 -> U+1F50 */ 1473, + /* U+03C5+0314 -> U+1F51 */ 1474, + /* U+03C5+0342 -> U+1FE6 */ 1612, + /* U+03C9+0300 -> U+1F7C */ 1513, /* U+03C9+0301 -> U+03CE */ 440, - /* U+03C9+0313 -> U+1F60 */ 1484, - /* U+03C9+0314 -> U+1F61 */ 1485, - /* U+03C9+0342 -> U+1FF6 */ 1624, - /* U+03C9+0345 -> U+1FF3 */ 1622, - /* U+03CA+0300 -> U+1FD2 */ 1594, + /* U+03C9+0313 -> U+1F60 */ 1485, + /* U+03C9+0314 -> U+1F61 */ 1486, + /* U+03C9+0342 -> U+1FF6 */ 1625, + /* U+03C9+0345 -> U+1FF3 */ 1623, + /* U+03CA+0300 -> U+1FD2 */ 1595, /* U+03CA+0301 -> U+0390 */ 428, - /* U+03CA+0342 -> U+1FD7 */ 1597, - /* U+03CB+0300 -> U+1FE2 */ 1607, + /* U+03CA+0342 -> U+1FD7 */ 1598, + /* U+03CB+0300 -> U+1FE2 */ 1608, /* U+03CB+0301 -> U+03B0 */ 435, - /* U+03CB+0342 -> U+1FE7 */ 1612, - /* U+03CE+0345 -> U+1FF4 */ 1623, + /* U+03CB+0342 -> U+1FE7 */ 1613, + /* U+03CE+0345 -> U+1FF4 */ 1624, /* U+03D2+0301 -> U+03D3 */ 444, /* U+03D2+0308 -> U+03D4 */ 445, /* U+0406+0308 -> U+0407 */ 457, @@ -2409,545 +2426,570 @@ static const uint16 RecompInverseLookup[941] = /* U+06C1+0654 -> U+06C2 */ 606, /* U+06D2+0654 -> U+06D3 */ 607, /* U+06D5+0654 -> U+06C0 */ 605, - /* U+0928+093C -> U+0929 */ 750, - /* U+0930+093C -> U+0931 */ 751, - /* U+0933+093C -> U+0934 */ 752, - /* U+09C7+09BE -> U+09CB */ 768, - /* U+09C7+09D7 -> U+09CC */ 769, - /* U+0B47+0B3E -> U+0B4B */ 787, - /* U+0B47+0B56 -> U+0B48 */ 786, - /* U+0B47+0B57 -> U+0B4C */ 788, - /* U+0B92+0BD7 -> U+0B94 */ 792, - /* U+0BC6+0BBE -> U+0BCA */ 793, - /* U+0BC6+0BD7 -> U+0BCC */ 795, - /* U+0BC7+0BBE -> U+0BCB */ 794, - /* U+0C46+0C56 -> U+0C48 */ 798, - /* U+0CBF+0CD5 -> U+0CC0 */ 803, - /* U+0CC6+0CC2 -> U+0CCA */ 806, - /* U+0CC6+0CD5 -> U+0CC7 */ 804, - /* U+0CC6+0CD6 -> U+0CC8 */ 805, - /* U+0CCA+0CD5 -> U+0CCB */ 807, - /* U+0D46+0D3E -> U+0D4A */ 811, - /* U+0D46+0D57 -> U+0D4C */ 813, - /* U+0D47+0D3E -> U+0D4B */ 812, - /* U+0DD9+0DCA -> U+0DDA */ 816, - /* U+0DD9+0DCF -> U+0DDC */ 817, - /* U+0DD9+0DDF -> U+0DDE */ 819, - /* U+0DDC+0DCA -> U+0DDD */ 818, - /* U+1025+102E -> U+1026 */ 877, - /* U+1B05+1B35 -> U+1B06 */ 937, - /* U+1B07+1B35 -> U+1B08 */ 938, - /* U+1B09+1B35 -> U+1B0A */ 939, - /* U+1B0B+1B35 -> U+1B0C */ 940, - /* U+1B0D+1B35 -> U+1B0E */ 941, - /* U+1B11+1B35 -> U+1B12 */ 942, - /* U+1B3A+1B35 -> U+1B3B */ 944, - /* U+1B3C+1B35 -> U+1B3D */ 945, - /* U+1B3E+1B35 -> U+1B40 */ 946, - /* U+1B3F+1B35 -> U+1B41 */ 947, - /* U+1B42+1B35 -> U+1B43 */ 948, - /* U+1E36+0304 -> U+1E38 */ 1210, - /* U+1E37+0304 -> U+1E39 */ 1211, - /* U+1E5A+0304 -> U+1E5C */ 1246, - /* U+1E5B+0304 -> U+1E5D */ 1247, - /* U+1E62+0307 -> U+1E68 */ 1258, - /* U+1E63+0307 -> U+1E69 */ 1259, - /* U+1EA0+0302 -> U+1EAC */ 1322, - /* U+1EA0+0306 -> U+1EB6 */ 1332, - /* U+1EA1+0302 -> U+1EAD */ 1323, - /* U+1EA1+0306 -> U+1EB7 */ 1333, - /* U+1EB8+0302 -> U+1EC6 */ 1348, - /* U+1EB9+0302 -> U+1EC7 */ 1349, - /* U+1ECC+0302 -> U+1ED8 */ 1366, - /* U+1ECD+0302 -> U+1ED9 */ 1367, - /* U+1F00+0300 -> U+1F02 */ 1402, - /* U+1F00+0301 -> U+1F04 */ 1404, - /* U+1F00+0342 -> U+1F06 */ 1406, - /* U+1F00+0345 -> U+1F80 */ 1514, - /* U+1F01+0300 -> U+1F03 */ 1403, - /* U+1F01+0301 -> U+1F05 */ 1405, - /* U+1F01+0342 -> U+1F07 */ 1407, - /* U+1F01+0345 -> U+1F81 */ 1515, - /* U+1F02+0345 -> U+1F82 */ 1516, - /* U+1F03+0345 -> U+1F83 */ 1517, - /* U+1F04+0345 -> U+1F84 */ 1518, - /* U+1F05+0345 -> U+1F85 */ 1519, - /* U+1F06+0345 -> U+1F86 */ 1520, - /* U+1F07+0345 -> U+1F87 */ 1521, - /* U+1F08+0300 -> U+1F0A */ 1410, - /* U+1F08+0301 -> U+1F0C */ 1412, - /* U+1F08+0342 -> U+1F0E */ 1414, - /* U+1F08+0345 -> U+1F88 */ 1522, - /* U+1F09+0300 -> U+1F0B */ 1411, - /* U+1F09+0301 -> U+1F0D */ 1413, - /* U+1F09+0342 -> U+1F0F */ 1415, - /* U+1F09+0345 -> U+1F89 */ 1523, - /* U+1F0A+0345 -> U+1F8A */ 1524, - /* U+1F0B+0345 -> U+1F8B */ 1525, - /* U+1F0C+0345 -> U+1F8C */ 1526, - /* U+1F0D+0345 -> U+1F8D */ 1527, - /* U+1F0E+0345 -> U+1F8E */ 1528, - /* U+1F0F+0345 -> U+1F8F */ 1529, - /* U+1F10+0300 -> U+1F12 */ 1418, - /* U+1F10+0301 -> U+1F14 */ 1420, - /* U+1F11+0300 -> U+1F13 */ 1419, - /* U+1F11+0301 -> U+1F15 */ 1421, - /* U+1F18+0300 -> U+1F1A */ 1424, - /* U+1F18+0301 -> U+1F1C */ 1426, - /* U+1F19+0300 -> U+1F1B */ 1425, - /* U+1F19+0301 -> U+1F1D */ 1427, - /* U+1F20+0300 -> U+1F22 */ 1430, - /* U+1F20+0301 -> U+1F24 */ 1432, - /* U+1F20+0342 -> U+1F26 */ 1434, - /* U+1F20+0345 -> U+1F90 */ 1530, - /* U+1F21+0300 -> U+1F23 */ 1431, - /* U+1F21+0301 -> U+1F25 */ 1433, - /* U+1F21+0342 -> U+1F27 */ 1435, - /* U+1F21+0345 -> U+1F91 */ 1531, - /* U+1F22+0345 -> U+1F92 */ 1532, - /* U+1F23+0345 -> U+1F93 */ 1533, - /* U+1F24+0345 -> U+1F94 */ 1534, - /* U+1F25+0345 -> U+1F95 */ 1535, - /* U+1F26+0345 -> U+1F96 */ 1536, - /* U+1F27+0345 -> U+1F97 */ 1537, - /* U+1F28+0300 -> U+1F2A */ 1438, - /* U+1F28+0301 -> U+1F2C */ 1440, - /* U+1F28+0342 -> U+1F2E */ 1442, - /* U+1F28+0345 -> U+1F98 */ 1538, - /* U+1F29+0300 -> U+1F2B */ 1439, - /* U+1F29+0301 -> U+1F2D */ 1441, - /* U+1F29+0342 -> U+1F2F */ 1443, - /* U+1F29+0345 -> U+1F99 */ 1539, - /* U+1F2A+0345 -> U+1F9A */ 1540, - /* U+1F2B+0345 -> U+1F9B */ 1541, - /* U+1F2C+0345 -> U+1F9C */ 1542, - /* U+1F2D+0345 -> U+1F9D */ 1543, - /* U+1F2E+0345 -> U+1F9E */ 1544, - /* U+1F2F+0345 -> U+1F9F */ 1545, - /* U+1F30+0300 -> U+1F32 */ 1446, - /* U+1F30+0301 -> U+1F34 */ 1448, - /* U+1F30+0342 -> U+1F36 */ 1450, - /* U+1F31+0300 -> U+1F33 */ 1447, - /* U+1F31+0301 -> U+1F35 */ 1449, - /* U+1F31+0342 -> U+1F37 */ 1451, - /* U+1F38+0300 -> U+1F3A */ 1454, - /* U+1F38+0301 -> U+1F3C */ 1456, - /* U+1F38+0342 -> U+1F3E */ 1458, - /* U+1F39+0300 -> U+1F3B */ 1455, - /* U+1F39+0301 -> U+1F3D */ 1457, - /* U+1F39+0342 -> U+1F3F */ 1459, - /* U+1F40+0300 -> U+1F42 */ 1462, - /* U+1F40+0301 -> U+1F44 */ 1464, - /* U+1F41+0300 -> U+1F43 */ 1463, - /* U+1F41+0301 -> U+1F45 */ 1465, - /* U+1F48+0300 -> U+1F4A */ 1468, - /* U+1F48+0301 -> U+1F4C */ 1470, - /* U+1F49+0300 -> U+1F4B */ 1469, - /* U+1F49+0301 -> U+1F4D */ 1471, - /* U+1F50+0300 -> U+1F52 */ 1474, - /* U+1F50+0301 -> U+1F54 */ 1476, - /* U+1F50+0342 -> U+1F56 */ 1478, - /* U+1F51+0300 -> U+1F53 */ 1475, - /* U+1F51+0301 -> U+1F55 */ 1477, - /* U+1F51+0342 -> U+1F57 */ 1479, - /* U+1F59+0300 -> U+1F5B */ 1481, - /* U+1F59+0301 -> U+1F5D */ 1482, - /* U+1F59+0342 -> U+1F5F */ 1483, - /* U+1F60+0300 -> U+1F62 */ 1486, - /* U+1F60+0301 -> U+1F64 */ 1488, - /* U+1F60+0342 -> U+1F66 */ 1490, - /* U+1F60+0345 -> U+1FA0 */ 1546, - /* U+1F61+0300 -> U+1F63 */ 1487, - /* U+1F61+0301 -> U+1F65 */ 1489, - /* U+1F61+0342 -> U+1F67 */ 1491, - /* U+1F61+0345 -> U+1FA1 */ 1547, - /* U+1F62+0345 -> U+1FA2 */ 1548, - /* U+1F63+0345 -> U+1FA3 */ 1549, - /* U+1F64+0345 -> U+1FA4 */ 1550, - /* U+1F65+0345 -> U+1FA5 */ 1551, - /* U+1F66+0345 -> U+1FA6 */ 1552, - /* U+1F67+0345 -> U+1FA7 */ 1553, - /* U+1F68+0300 -> U+1F6A */ 1494, - /* U+1F68+0301 -> U+1F6C */ 1496, - /* U+1F68+0342 -> U+1F6E */ 1498, - /* U+1F68+0345 -> U+1FA8 */ 1554, - /* U+1F69+0300 -> U+1F6B */ 1495, - /* U+1F69+0301 -> U+1F6D */ 1497, - /* U+1F69+0342 -> U+1F6F */ 1499, - /* U+1F69+0345 -> U+1FA9 */ 1555, - /* U+1F6A+0345 -> U+1FAA */ 1556, - /* U+1F6B+0345 -> U+1FAB */ 1557, - /* U+1F6C+0345 -> U+1FAC */ 1558, - /* U+1F6D+0345 -> U+1FAD */ 1559, - /* U+1F6E+0345 -> U+1FAE */ 1560, - /* U+1F6F+0345 -> U+1FAF */ 1561, - /* U+1F70+0345 -> U+1FB2 */ 1564, - /* U+1F74+0345 -> U+1FC2 */ 1579, - /* U+1F7C+0345 -> U+1FF2 */ 1621, - /* U+1FB6+0345 -> U+1FB7 */ 1568, - /* U+1FBF+0300 -> U+1FCD */ 1589, - /* U+1FBF+0301 -> U+1FCE */ 1590, - /* U+1FBF+0342 -> U+1FCF */ 1591, - /* U+1FC6+0345 -> U+1FC7 */ 1583, - /* U+1FF6+0345 -> U+1FF7 */ 1625, - /* U+1FFE+0300 -> U+1FDD */ 1602, - /* U+1FFE+0301 -> U+1FDE */ 1603, - /* U+1FFE+0342 -> U+1FDF */ 1604, - /* U+2190+0338 -> U+219A */ 1835, - /* U+2192+0338 -> U+219B */ 1836, - /* U+2194+0338 -> U+21AE */ 1837, - /* U+21D0+0338 -> U+21CD */ 1838, - /* U+21D2+0338 -> U+21CF */ 1840, - /* U+21D4+0338 -> U+21CE */ 1839, - /* U+2203+0338 -> U+2204 */ 1841, - /* U+2208+0338 -> U+2209 */ 1842, - /* U+220B+0338 -> U+220C */ 1843, - /* U+2223+0338 -> U+2224 */ 1844, - /* U+2225+0338 -> U+2226 */ 1845, - /* U+223C+0338 -> U+2241 */ 1850, - /* U+2243+0338 -> U+2244 */ 1851, - /* U+2245+0338 -> U+2247 */ 1852, - /* U+2248+0338 -> U+2249 */ 1853, - /* U+224D+0338 -> U+226D */ 1856, - /* U+2261+0338 -> U+2262 */ 1855, - /* U+2264+0338 -> U+2270 */ 1859, - /* U+2265+0338 -> U+2271 */ 1860, - /* U+2272+0338 -> U+2274 */ 1861, - /* U+2273+0338 -> U+2275 */ 1862, - /* U+2276+0338 -> U+2278 */ 1863, - /* U+2277+0338 -> U+2279 */ 1864, - /* U+227A+0338 -> U+2280 */ 1865, - /* U+227B+0338 -> U+2281 */ 1866, - /* U+227C+0338 -> U+22E0 */ 1875, - /* U+227D+0338 -> U+22E1 */ 1876, - /* U+2282+0338 -> U+2284 */ 1867, - /* U+2283+0338 -> U+2285 */ 1868, - /* U+2286+0338 -> U+2288 */ 1869, - /* U+2287+0338 -> U+2289 */ 1870, - /* U+2291+0338 -> U+22E2 */ 1877, - /* U+2292+0338 -> U+22E3 */ 1878, - /* U+22A2+0338 -> U+22AC */ 1871, - /* U+22A8+0338 -> U+22AD */ 1872, - /* U+22A9+0338 -> U+22AE */ 1873, - /* U+22AB+0338 -> U+22AF */ 1874, - /* U+22B2+0338 -> U+22EA */ 1879, - /* U+22B3+0338 -> U+22EB */ 1880, - /* U+22B4+0338 -> U+22EC */ 1881, - /* U+22B5+0338 -> U+22ED */ 1882, - /* U+3046+3099 -> U+3094 */ 2320, - /* U+304B+3099 -> U+304C */ 2295, - /* U+304D+3099 -> U+304E */ 2296, - /* U+304F+3099 -> U+3050 */ 2297, - /* U+3051+3099 -> U+3052 */ 2298, - /* U+3053+3099 -> U+3054 */ 2299, - /* U+3055+3099 -> U+3056 */ 2300, - /* U+3057+3099 -> U+3058 */ 2301, - /* U+3059+3099 -> U+305A */ 2302, - /* U+305B+3099 -> U+305C */ 2303, - /* U+305D+3099 -> U+305E */ 2304, - /* U+305F+3099 -> U+3060 */ 2305, - /* U+3061+3099 -> U+3062 */ 2306, - /* U+3064+3099 -> U+3065 */ 2307, - /* U+3066+3099 -> U+3067 */ 2308, - /* U+3068+3099 -> U+3069 */ 2309, - /* U+306F+3099 -> U+3070 */ 2310, - /* U+306F+309A -> U+3071 */ 2311, - /* U+3072+3099 -> U+3073 */ 2312, - /* U+3072+309A -> U+3074 */ 2313, - /* U+3075+3099 -> U+3076 */ 2314, - /* U+3075+309A -> U+3077 */ 2315, - /* U+3078+3099 -> U+3079 */ 2316, - /* U+3078+309A -> U+307A */ 2317, - /* U+307B+3099 -> U+307C */ 2318, - /* U+307B+309A -> U+307D */ 2319, - /* U+309D+3099 -> U+309E */ 2325, - /* U+30A6+3099 -> U+30F4 */ 2352, - /* U+30AB+3099 -> U+30AC */ 2327, - /* U+30AD+3099 -> U+30AE */ 2328, - /* U+30AF+3099 -> U+30B0 */ 2329, - /* U+30B1+3099 -> U+30B2 */ 2330, - /* U+30B3+3099 -> U+30B4 */ 2331, - /* U+30B5+3099 -> U+30B6 */ 2332, - /* U+30B7+3099 -> U+30B8 */ 2333, - /* U+30B9+3099 -> U+30BA */ 2334, - /* U+30BB+3099 -> U+30BC */ 2335, - /* U+30BD+3099 -> U+30BE */ 2336, - /* U+30BF+3099 -> U+30C0 */ 2337, - /* U+30C1+3099 -> U+30C2 */ 2338, - /* U+30C4+3099 -> U+30C5 */ 2339, - /* U+30C6+3099 -> U+30C7 */ 2340, - /* U+30C8+3099 -> U+30C9 */ 2341, - /* U+30CF+3099 -> U+30D0 */ 2342, - /* U+30CF+309A -> U+30D1 */ 2343, - /* U+30D2+3099 -> U+30D3 */ 2344, - /* U+30D2+309A -> U+30D4 */ 2345, - /* U+30D5+3099 -> U+30D6 */ 2346, - /* U+30D5+309A -> U+30D7 */ 2347, - /* U+30D8+3099 -> U+30D9 */ 2348, - /* U+30D8+309A -> U+30DA */ 2349, - /* U+30DB+3099 -> U+30DC */ 2350, - /* U+30DB+309A -> U+30DD */ 2351, - /* U+30EF+3099 -> U+30F7 */ 2353, - /* U+30F0+3099 -> U+30F8 */ 2354, - /* U+30F1+3099 -> U+30F9 */ 2355, - /* U+30F2+3099 -> U+30FA */ 2356, - /* U+30FD+3099 -> U+30FE */ 2357, - /* U+11099+110BA -> U+1109A */ 4689, - /* U+1109B+110BA -> U+1109C */ 4690, - /* U+110A5+110BA -> U+110AB */ 4691, - /* U+11131+11127 -> U+1112E */ 4697, - /* U+11132+11127 -> U+1112F */ 4698, - /* U+11347+1133E -> U+1134B */ 4710, - /* U+11347+11357 -> U+1134C */ 4711, - /* U+114B9+114B0 -> U+114BC */ 4729, - /* U+114B9+114BA -> U+114BB */ 4728, - /* U+114B9+114BD -> U+114BE */ 4730, - /* U+115B8+115AF -> U+115BA */ 4733, - /* U+115B9+115AF -> U+115BB */ 4734, - /* U+11935+11930 -> U+11938 */ 4743 + /* U+0928+093C -> U+0929 */ 751, + /* U+0930+093C -> U+0931 */ 752, + /* U+0933+093C -> U+0934 */ 753, + /* U+09C7+09BE -> U+09CB */ 769, + /* U+09C7+09D7 -> U+09CC */ 770, + /* U+0B47+0B3E -> U+0B4B */ 788, + /* U+0B47+0B56 -> U+0B48 */ 787, + /* U+0B47+0B57 -> U+0B4C */ 789, + /* U+0B92+0BD7 -> U+0B94 */ 793, + /* U+0BC6+0BBE -> U+0BCA */ 794, + /* U+0BC6+0BD7 -> U+0BCC */ 796, + /* U+0BC7+0BBE -> U+0BCB */ 795, + /* U+0C46+0C56 -> U+0C48 */ 799, + /* U+0CBF+0CD5 -> U+0CC0 */ 804, + /* U+0CC6+0CC2 -> U+0CCA */ 807, + /* U+0CC6+0CD5 -> U+0CC7 */ 805, + /* U+0CC6+0CD6 -> U+0CC8 */ 806, + /* U+0CCA+0CD5 -> U+0CCB */ 808, + /* U+0D46+0D3E -> U+0D4A */ 812, + /* U+0D46+0D57 -> U+0D4C */ 814, + /* U+0D47+0D3E -> U+0D4B */ 813, + /* U+0DD9+0DCA -> U+0DDA */ 817, + /* U+0DD9+0DCF -> U+0DDC */ 818, + /* U+0DD9+0DDF -> U+0DDE */ 820, + /* U+0DDC+0DCA -> U+0DDD */ 819, + /* U+1025+102E -> U+1026 */ 878, + /* U+1B05+1B35 -> U+1B06 */ 938, + /* U+1B07+1B35 -> U+1B08 */ 939, + /* U+1B09+1B35 -> U+1B0A */ 940, + /* U+1B0B+1B35 -> U+1B0C */ 941, + /* U+1B0D+1B35 -> U+1B0E */ 942, + /* U+1B11+1B35 -> U+1B12 */ 943, + /* U+1B3A+1B35 -> U+1B3B */ 945, + /* U+1B3C+1B35 -> U+1B3D */ 946, + /* U+1B3E+1B35 -> U+1B40 */ 947, + /* U+1B3F+1B35 -> U+1B41 */ 948, + /* U+1B42+1B35 -> U+1B43 */ 949, + /* U+1E36+0304 -> U+1E38 */ 1211, + /* U+1E37+0304 -> U+1E39 */ 1212, + /* U+1E5A+0304 -> U+1E5C */ 1247, + /* U+1E5B+0304 -> U+1E5D */ 1248, + /* U+1E62+0307 -> U+1E68 */ 1259, + /* U+1E63+0307 -> U+1E69 */ 1260, + /* U+1EA0+0302 -> U+1EAC */ 1323, + /* U+1EA0+0306 -> U+1EB6 */ 1333, + /* U+1EA1+0302 -> U+1EAD */ 1324, + /* U+1EA1+0306 -> U+1EB7 */ 1334, + /* U+1EB8+0302 -> U+1EC6 */ 1349, + /* U+1EB9+0302 -> U+1EC7 */ 1350, + /* U+1ECC+0302 -> U+1ED8 */ 1367, + /* U+1ECD+0302 -> U+1ED9 */ 1368, + /* U+1F00+0300 -> U+1F02 */ 1403, + /* U+1F00+0301 -> U+1F04 */ 1405, + /* U+1F00+0342 -> U+1F06 */ 1407, + /* U+1F00+0345 -> U+1F80 */ 1515, + /* U+1F01+0300 -> U+1F03 */ 1404, + /* U+1F01+0301 -> U+1F05 */ 1406, + /* U+1F01+0342 -> U+1F07 */ 1408, + /* U+1F01+0345 -> U+1F81 */ 1516, + /* U+1F02+0345 -> U+1F82 */ 1517, + /* U+1F03+0345 -> U+1F83 */ 1518, + /* U+1F04+0345 -> U+1F84 */ 1519, + /* U+1F05+0345 -> U+1F85 */ 1520, + /* U+1F06+0345 -> U+1F86 */ 1521, + /* U+1F07+0345 -> U+1F87 */ 1522, + /* U+1F08+0300 -> U+1F0A */ 1411, + /* U+1F08+0301 -> U+1F0C */ 1413, + /* U+1F08+0342 -> U+1F0E */ 1415, + /* U+1F08+0345 -> U+1F88 */ 1523, + /* U+1F09+0300 -> U+1F0B */ 1412, + /* U+1F09+0301 -> U+1F0D */ 1414, + /* U+1F09+0342 -> U+1F0F */ 1416, + /* U+1F09+0345 -> U+1F89 */ 1524, + /* U+1F0A+0345 -> U+1F8A */ 1525, + /* U+1F0B+0345 -> U+1F8B */ 1526, + /* U+1F0C+0345 -> U+1F8C */ 1527, + /* U+1F0D+0345 -> U+1F8D */ 1528, + /* U+1F0E+0345 -> U+1F8E */ 1529, + /* U+1F0F+0345 -> U+1F8F */ 1530, + /* U+1F10+0300 -> U+1F12 */ 1419, + /* U+1F10+0301 -> U+1F14 */ 1421, + /* U+1F11+0300 -> U+1F13 */ 1420, + /* U+1F11+0301 -> U+1F15 */ 1422, + /* U+1F18+0300 -> U+1F1A */ 1425, + /* U+1F18+0301 -> U+1F1C */ 1427, + /* U+1F19+0300 -> U+1F1B */ 1426, + /* U+1F19+0301 -> U+1F1D */ 1428, + /* U+1F20+0300 -> U+1F22 */ 1431, + /* U+1F20+0301 -> U+1F24 */ 1433, + /* U+1F20+0342 -> U+1F26 */ 1435, + /* U+1F20+0345 -> U+1F90 */ 1531, + /* U+1F21+0300 -> U+1F23 */ 1432, + /* U+1F21+0301 -> U+1F25 */ 1434, + /* U+1F21+0342 -> U+1F27 */ 1436, + /* U+1F21+0345 -> U+1F91 */ 1532, + /* U+1F22+0345 -> U+1F92 */ 1533, + /* U+1F23+0345 -> U+1F93 */ 1534, + /* U+1F24+0345 -> U+1F94 */ 1535, + /* U+1F25+0345 -> U+1F95 */ 1536, + /* U+1F26+0345 -> U+1F96 */ 1537, + /* U+1F27+0345 -> U+1F97 */ 1538, + /* U+1F28+0300 -> U+1F2A */ 1439, + /* U+1F28+0301 -> U+1F2C */ 1441, + /* U+1F28+0342 -> U+1F2E */ 1443, + /* U+1F28+0345 -> U+1F98 */ 1539, + /* U+1F29+0300 -> U+1F2B */ 1440, + /* U+1F29+0301 -> U+1F2D */ 1442, + /* U+1F29+0342 -> U+1F2F */ 1444, + /* U+1F29+0345 -> U+1F99 */ 1540, + /* U+1F2A+0345 -> U+1F9A */ 1541, + /* U+1F2B+0345 -> U+1F9B */ 1542, + /* U+1F2C+0345 -> U+1F9C */ 1543, + /* U+1F2D+0345 -> U+1F9D */ 1544, + /* U+1F2E+0345 -> U+1F9E */ 1545, + /* U+1F2F+0345 -> U+1F9F */ 1546, + /* U+1F30+0300 -> U+1F32 */ 1447, + /* U+1F30+0301 -> U+1F34 */ 1449, + /* U+1F30+0342 -> U+1F36 */ 1451, + /* U+1F31+0300 -> U+1F33 */ 1448, + /* U+1F31+0301 -> U+1F35 */ 1450, + /* U+1F31+0342 -> U+1F37 */ 1452, + /* U+1F38+0300 -> U+1F3A */ 1455, + /* U+1F38+0301 -> U+1F3C */ 1457, + /* U+1F38+0342 -> U+1F3E */ 1459, + /* U+1F39+0300 -> U+1F3B */ 1456, + /* U+1F39+0301 -> U+1F3D */ 1458, + /* U+1F39+0342 -> U+1F3F */ 1460, + /* U+1F40+0300 -> U+1F42 */ 1463, + /* U+1F40+0301 -> U+1F44 */ 1465, + /* U+1F41+0300 -> U+1F43 */ 1464, + /* U+1F41+0301 -> U+1F45 */ 1466, + /* U+1F48+0300 -> U+1F4A */ 1469, + /* U+1F48+0301 -> U+1F4C */ 1471, + /* U+1F49+0300 -> U+1F4B */ 1470, + /* U+1F49+0301 -> U+1F4D */ 1472, + /* U+1F50+0300 -> U+1F52 */ 1475, + /* U+1F50+0301 -> U+1F54 */ 1477, + /* U+1F50+0342 -> U+1F56 */ 1479, + /* U+1F51+0300 -> U+1F53 */ 1476, + /* U+1F51+0301 -> U+1F55 */ 1478, + /* U+1F51+0342 -> U+1F57 */ 1480, + /* U+1F59+0300 -> U+1F5B */ 1482, + /* U+1F59+0301 -> U+1F5D */ 1483, + /* U+1F59+0342 -> U+1F5F */ 1484, + /* U+1F60+0300 -> U+1F62 */ 1487, + /* U+1F60+0301 -> U+1F64 */ 1489, + /* U+1F60+0342 -> U+1F66 */ 1491, + /* U+1F60+0345 -> U+1FA0 */ 1547, + /* U+1F61+0300 -> U+1F63 */ 1488, + /* U+1F61+0301 -> U+1F65 */ 1490, + /* U+1F61+0342 -> U+1F67 */ 1492, + /* U+1F61+0345 -> U+1FA1 */ 1548, + /* U+1F62+0345 -> U+1FA2 */ 1549, + /* U+1F63+0345 -> U+1FA3 */ 1550, + /* U+1F64+0345 -> U+1FA4 */ 1551, + /* U+1F65+0345 -> U+1FA5 */ 1552, + /* U+1F66+0345 -> U+1FA6 */ 1553, + /* U+1F67+0345 -> U+1FA7 */ 1554, + /* U+1F68+0300 -> U+1F6A */ 1495, + /* U+1F68+0301 -> U+1F6C */ 1497, + /* U+1F68+0342 -> U+1F6E */ 1499, + /* U+1F68+0345 -> U+1FA8 */ 1555, + /* U+1F69+0300 -> U+1F6B */ 1496, + /* U+1F69+0301 -> U+1F6D */ 1498, + /* U+1F69+0342 -> U+1F6F */ 1500, + /* U+1F69+0345 -> U+1FA9 */ 1556, + /* U+1F6A+0345 -> U+1FAA */ 1557, + /* U+1F6B+0345 -> U+1FAB */ 1558, + /* U+1F6C+0345 -> U+1FAC */ 1559, + /* U+1F6D+0345 -> U+1FAD */ 1560, + /* U+1F6E+0345 -> U+1FAE */ 1561, + /* U+1F6F+0345 -> U+1FAF */ 1562, + /* U+1F70+0345 -> U+1FB2 */ 1565, + /* U+1F74+0345 -> U+1FC2 */ 1580, + /* U+1F7C+0345 -> U+1FF2 */ 1622, + /* U+1FB6+0345 -> U+1FB7 */ 1569, + /* U+1FBF+0300 -> U+1FCD */ 1590, + /* U+1FBF+0301 -> U+1FCE */ 1591, + /* U+1FBF+0342 -> U+1FCF */ 1592, + /* U+1FC6+0345 -> U+1FC7 */ 1584, + /* U+1FF6+0345 -> U+1FF7 */ 1626, + /* U+1FFE+0300 -> U+1FDD */ 1603, + /* U+1FFE+0301 -> U+1FDE */ 1604, + /* U+1FFE+0342 -> U+1FDF */ 1605, + /* U+2190+0338 -> U+219A */ 1836, + /* U+2192+0338 -> U+219B */ 1837, + /* U+2194+0338 -> U+21AE */ 1838, + /* U+21D0+0338 -> U+21CD */ 1839, + /* U+21D2+0338 -> U+21CF */ 1841, + /* U+21D4+0338 -> U+21CE */ 1840, + /* U+2203+0338 -> U+2204 */ 1842, + /* U+2208+0338 -> U+2209 */ 1843, + /* U+220B+0338 -> U+220C */ 1844, + /* U+2223+0338 -> U+2224 */ 1845, + /* U+2225+0338 -> U+2226 */ 1846, + /* U+223C+0338 -> U+2241 */ 1851, + /* U+2243+0338 -> U+2244 */ 1852, + /* U+2245+0338 -> U+2247 */ 1853, + /* U+2248+0338 -> U+2249 */ 1854, + /* U+224D+0338 -> U+226D */ 1857, + /* U+2261+0338 -> U+2262 */ 1856, + /* U+2264+0338 -> U+2270 */ 1860, + /* U+2265+0338 -> U+2271 */ 1861, + /* U+2272+0338 -> U+2274 */ 1862, + /* U+2273+0338 -> U+2275 */ 1863, + /* U+2276+0338 -> U+2278 */ 1864, + /* U+2277+0338 -> U+2279 */ 1865, + /* U+227A+0338 -> U+2280 */ 1866, + /* U+227B+0338 -> U+2281 */ 1867, + /* U+227C+0338 -> U+22E0 */ 1876, + /* U+227D+0338 -> U+22E1 */ 1877, + /* U+2282+0338 -> U+2284 */ 1868, + /* U+2283+0338 -> U+2285 */ 1869, + /* U+2286+0338 -> U+2288 */ 1870, + /* U+2287+0338 -> U+2289 */ 1871, + /* U+2291+0338 -> U+22E2 */ 1878, + /* U+2292+0338 -> U+22E3 */ 1879, + /* U+22A2+0338 -> U+22AC */ 1872, + /* U+22A8+0338 -> U+22AD */ 1873, + /* U+22A9+0338 -> U+22AE */ 1874, + /* U+22AB+0338 -> U+22AF */ 1875, + /* U+22B2+0338 -> U+22EA */ 1880, + /* U+22B3+0338 -> U+22EB */ 1881, + /* U+22B4+0338 -> U+22EC */ 1882, + /* U+22B5+0338 -> U+22ED */ 1883, + /* U+3046+3099 -> U+3094 */ 2321, + /* U+304B+3099 -> U+304C */ 2296, + /* U+304D+3099 -> U+304E */ 2297, + /* U+304F+3099 -> U+3050 */ 2298, + /* U+3051+3099 -> U+3052 */ 2299, + /* U+3053+3099 -> U+3054 */ 2300, + /* U+3055+3099 -> U+3056 */ 2301, + /* U+3057+3099 -> U+3058 */ 2302, + /* U+3059+3099 -> U+305A */ 2303, + /* U+305B+3099 -> U+305C */ 2304, + /* U+305D+3099 -> U+305E */ 2305, + /* U+305F+3099 -> U+3060 */ 2306, + /* U+3061+3099 -> U+3062 */ 2307, + /* U+3064+3099 -> U+3065 */ 2308, + /* U+3066+3099 -> U+3067 */ 2309, + /* U+3068+3099 -> U+3069 */ 2310, + /* U+306F+3099 -> U+3070 */ 2311, + /* U+306F+309A -> U+3071 */ 2312, + /* U+3072+3099 -> U+3073 */ 2313, + /* U+3072+309A -> U+3074 */ 2314, + /* U+3075+3099 -> U+3076 */ 2315, + /* U+3075+309A -> U+3077 */ 2316, + /* U+3078+3099 -> U+3079 */ 2317, + /* U+3078+309A -> U+307A */ 2318, + /* U+307B+3099 -> U+307C */ 2319, + /* U+307B+309A -> U+307D */ 2320, + /* U+309D+3099 -> U+309E */ 2326, + /* U+30A6+3099 -> U+30F4 */ 2353, + /* U+30AB+3099 -> U+30AC */ 2328, + /* U+30AD+3099 -> U+30AE */ 2329, + /* U+30AF+3099 -> U+30B0 */ 2330, + /* U+30B1+3099 -> U+30B2 */ 2331, + /* U+30B3+3099 -> U+30B4 */ 2332, + /* U+30B5+3099 -> U+30B6 */ 2333, + /* U+30B7+3099 -> U+30B8 */ 2334, + /* U+30B9+3099 -> U+30BA */ 2335, + /* U+30BB+3099 -> U+30BC */ 2336, + /* U+30BD+3099 -> U+30BE */ 2337, + /* U+30BF+3099 -> U+30C0 */ 2338, + /* U+30C1+3099 -> U+30C2 */ 2339, + /* U+30C4+3099 -> U+30C5 */ 2340, + /* U+30C6+3099 -> U+30C7 */ 2341, + /* U+30C8+3099 -> U+30C9 */ 2342, + /* U+30CF+3099 -> U+30D0 */ 2343, + /* U+30CF+309A -> U+30D1 */ 2344, + /* U+30D2+3099 -> U+30D3 */ 2345, + /* U+30D2+309A -> U+30D4 */ 2346, + /* U+30D5+3099 -> U+30D6 */ 2347, + /* U+30D5+309A -> U+30D7 */ 2348, + /* U+30D8+3099 -> U+30D9 */ 2349, + /* U+30D8+309A -> U+30DA */ 2350, + /* U+30DB+3099 -> U+30DC */ 2351, + /* U+30DB+309A -> U+30DD */ 2352, + /* U+30EF+3099 -> U+30F7 */ 2354, + /* U+30F0+3099 -> U+30F8 */ 2355, + /* U+30F1+3099 -> U+30F9 */ 2356, + /* U+30F2+3099 -> U+30FA */ 2357, + /* U+30FD+3099 -> U+30FE */ 2358, + /* U+105D2+0307 -> U+105C9 */ 4599, + /* U+105DA+0307 -> U+105E4 */ 4600, + /* U+11099+110BA -> U+1109A */ 4697, + /* U+1109B+110BA -> U+1109C */ 4698, + /* U+110A5+110BA -> U+110AB */ 4699, + /* U+11131+11127 -> U+1112E */ 4705, + /* U+11132+11127 -> U+1112F */ 4706, + /* U+11347+1133E -> U+1134B */ 4718, + /* U+11347+11357 -> U+1134C */ 4719, + /* U+11382+113C9 -> U+11383 */ 4733, + /* U+11384+113BB -> U+11385 */ 4734, + /* U+1138B+113C2 -> U+1138E */ 4735, + /* U+11390+113C9 -> U+11391 */ 4736, + /* U+113C2+113B8 -> U+113C7 */ 4738, + /* U+113C2+113C2 -> U+113C5 */ 4737, + /* U+113C2+113C9 -> U+113C8 */ 4739, + /* U+114B9+114B0 -> U+114BC */ 4747, + /* U+114B9+114BA -> U+114BB */ 4746, + /* U+114B9+114BD -> U+114BE */ 4748, + /* U+115B8+115AF -> U+115BA */ 4751, + /* U+115B9+115AF -> U+115BB */ 4752, + /* U+11935+11930 -> U+11938 */ 4761, + /* U+1611E+1611E -> U+16121 */ 4776, + /* U+1611E+1611F -> U+16123 */ 4778, + /* U+1611E+16120 -> U+16125 */ 4780, + /* U+1611E+16129 -> U+16122 */ 4777, + /* U+16121+1611F -> U+16126 */ 4781, + /* U+16121+16120 -> U+16128 */ 4783, + /* U+16122+1611F -> U+16127 */ 4782, + /* U+16129+1611F -> U+16124 */ 4779, + /* U+16D63+16D67 -> U+16D69 */ 4798, + /* U+16D67+16D67 -> U+16D68 */ 4797, + /* U+16D69+16D67 -> U+16D6A */ 4799 }; /* Perfect hash function for recomposition */ static int Recomp_hash_func(const void *key) { - static const int16 h[1883] = { - 772, 773, 621, 32767, 32767, 387, 653, 196, - 32767, 32767, 855, 463, -19, 651, 32767, 32767, - 32767, 364, 32767, 32767, -108, 32767, 32767, 32767, - 32767, 0, -568, 32767, 32767, 32767, 0, 0, - 0, -103, 364, 0, 210, 732, 0, 0, - -506, 0, 0, 0, 32767, 32767, 0, 32767, - 407, -140, 32767, 409, 32767, 772, 0, 86, - 842, 934, 32767, 32767, -499, -355, 32767, 32767, - 532, 138, 174, -243, 860, 1870, 742, 32767, - 32767, 339, 32767, 1290, 0, 32767, 32767, 0, - -449, -1386, 1633, 560, 561, 32767, 1219, 1004, - 139, -804, 32767, -179, 141, 579, 1586, 32767, - 32767, 32767, 142, 199, 32767, 32767, 143, 0, - 32767, 32767, 314, 896, 32767, 32767, 428, 129, - 286, -58, 0, 68, 32767, 0, 244, -566, - 32767, 32767, 32767, 246, 32767, 32767, 0, 32767, - 32767, 271, -108, 928, 32767, 715, 32767, 32767, - -211, -497, 32767, 0, 1055, 1339, 32767, 0, - 32767, 32767, -968, -144, 32767, 32767, 248, 32767, - -161, 32767, 32767, 282, 32767, -372, 0, 2, - -137, 1116, 32767, 687, 32767, 459, 913, 0, - 461, 879, -816, 443, 32767, 32767, 462, 1089, - 32767, 1054, 0, 314, 447, -26, 480, 32767, - 64, 0, 0, 112, 32767, 66, 0, 646, - 603, 22, -292, 0, 710, 475, 32767, 24, - -781, 32767, 32767, 32767, 281, 307, 32767, 1289, - 32767, 0, 1064, -149, 454, 118, 32767, 32767, - 0, 32767, -126, 0, 32767, 32767, 858, 32767, - 32767, 32767, 1029, 886, 665, 209, 0, 26, - 359, 0, 0, -108, -508, -603, 894, 906, - 32767, 32767, 14, 0, 0, 534, 984, 876, - 32767, -93, 110, -367, 167, 843, 32767, 32767, - -947, -290, 169, 0, 0, 32767, -42, 564, - 0, -927, 32767, 817, 32767, 32767, 32767, 110, - 0, 32767, 32767, -38, 32767, 32767, -101, 694, - -142, 190, 191, 1288, 32767, -687, 194, -579, - 534, -452, 0, -72, 536, 765, 823, 266, - -259, 684, 767, 32767, 654, 32767, 32767, 64, - 920, 32767, 32767, 32767, 0, 1653, 0, 0, - 32767, 32767, -452, -222, 855, 0, 32767, -1153, - 127, 490, 449, 863, 32767, -144, 32767, -379, - 545, 32767, 32767, 32767, 530, 32767, 32767, 1331, - 611, -612, 332, 545, -73, 0, 604, 201, - 32767, -279, 338, 836, 340, 408, 32767, -60, - -358, 32767, 343, 69, 707, 0, -129, 582, - 32767, 0, 32767, 96, 392, 490, 639, 157, - -4, 406, 32767, 32767, -571, 1077, 546, 32767, - 551, 0, 0, 0, 32767, 32767, 348, 32767, - 498, -181, 0, -433, 1057, 260, 0, 32767, - 32767, 397, 32767, 816, -130, 32767, 624, 0, - 0, 32767, 32767, 32767, 485, 0, 32767, 32767, - 32767, 32767, 32767, 0, 32767, 32767, 32767, 1222, - -230, 32767, 797, -538, 32767, 974, 32767, 32767, - 831, 70, -658, 145, 0, 147, 0, 32767, - 1295, 32767, 0, 0, 895, 0, 0, -385, - 491, -287, 32767, -587, 32767, 32767, 32767, 813, - -471, -13, 32767, 32767, 32767, 0, 203, 411, - 470, 0, -546, -179, 146, 0, 0, 32767, - -468, 32767, 0, 0, 32767, 32767, 32767, 211, - 32767, 32767, 0, 32767, 0, 52, 32767, 0, - 32767, 0, 692, 990, 32767, 32767, 32767, 56, - -507, 784, 951, 0, 32767, 0, 697, 32767, - 187, 0, 32767, 32767, 430, 1209, 682, 32767, - 130, 0, -25, 0, -1006, 0, 32767, 214, - 433, 22, 0, -1119, 32767, 285, 32767, 32767, - 32767, 216, 32767, 32767, 32767, 217, 527, 32767, - 32767, 32767, 829, 485, 419, 717, 620, 731, - 32767, 470, 0, -145, -620, 1162, -644, 848, - 287, -632, 32767, 32767, 32767, 32767, 381, 32767, - 510, 511, -554, -2, 32767, 0, 0, 698, - 32767, 32767, 436, 1154, 32767, 463, 32767, 32767, - 627, 517, 32767, 32767, 854, 579, 723, 396, - 110, -42, 354, 32767, 664, 32767, 32767, 0, - 0, 32767, 65, -163, 67, 140, 69, 341, - 70, 71, 402, 73, 623, 544, 624, 417, - -1375, 648, 32767, -26, 904, 0, 548, 0, - 0, 32767, 32767, 855, 32767, 488, -524, 599, - 130, 131, 32767, 32767, 542, -1110, -324, -462, - 32767, -405, -440, 0, 0, 629, 850, 0, - 741, 257, 258, 32767, 32767, 0, 32767, 923, - 0, 32767, 0, 32767, 1559, 32767, 32767, 32767, - 671, 32767, 134, 32767, 32767, -336, -104, 576, - 577, 829, 32767, 32767, 762, 902, 32767, 0, - 32767, 0, 1506, 887, 32767, 636, 601, 2465, - 426, 0, 236, 317, 427, 968, 32767, -975, - -559, -343, 341, 32767, 937, 241, 0, 32767, - 32767, 547, 32767, 32767, 32767, 32767, 32767, 789, - 0, 32767, 32767, 32767, 0, 0, 0, 32767, - -192, 859, 1185, 1153, 69, 32767, 32767, 32767, - -539, 32767, 32767, 0, 32767, 32767, 32767, 32767, - 640, 578, 32767, 32767, -766, 32767, 32767, 32767, - 32767, 1050, -572, 32767, 32767, 32767, 32767, 1268, - 32767, 32767, 32767, 754, 32767, 32767, 1640, 179, - 804, 32767, 32767, 32767, 32767, 0, 684, 943, - 1006, 32767, 32767, 652, 0, 32767, 1041, 32767, - 718, 791, 32767, 274, 697, 32767, 32767, 0, - 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 735, - 0, 32767, 32767, 32767, 275, 358, 688, 32767, - 32767, 32767, 548, -87, 770, 32767, -42, 0, - 551, 32767, 691, 222, 32767, 32767, 32767, 32767, - 0, 1273, 403, -121, 806, 553, 554, 163, - 32767, 32767, 892, 825, 32767, 32767, -490, 32767, - 32767, 32767, 32767, 32767, -109, 744, 910, 32767, - 91, 32767, 32767, 0, 0, 32767, 32767, 32767, - 1521, 50, 701, 32767, 32767, 32767, 32767, 164, - 658, 32767, 288, 0, 32767, 0, 51, 0, - 32767, 32767, 32767, 32767, 555, 1547, 32767, 32767, - 595, 585, 429, 32767, -80, 32767, 1258, 0, - 540, 486, -434, 865, 0, 192, 0, 884, - 0, 0, 0, 175, 555, 0, 32767, 32767, - 0, 32767, -566, 866, 591, 32767, 32767, 32767, - 32767, 32767, 496, 495, -215, 32767, 849, -772, - 32767, 32767, 502, 178, 483, 32767, 912, 793, - 794, 0, 32767, 32767, 32767, -556, 499, 838, - 32767, 32767, -506, 331, 0, 0, -1096, 512, - 880, 0, 774, -338, 649, 32767, 270, 32767, - 32767, -624, 328, 459, 32767, 32767, 32767, 32767, - 329, -201, -835, 813, -879, 560, 0, -212, - -114, 35, -494, 37, 523, 653, 751, -653, - -743, 32767, 1356, 818, 32767, 32767, 856, 0, - 44, 902, 0, 0, 0, 0, 32767, -26, - 526, 795, 456, 32767, 104, -209, -341, 133, - -372, 0, 45, 110, 111, 0, 511, 47, - 114, 32767, 32767, 93, 48, 116, -1031, -279, - 32767, 192, 0, 32767, 453, 415, 0, -190, - 32767, 471, 240, 175, 29, 665, 684, 0, - -11, -95, -344, 32767, 245, 148, 0, 530, - 0, 1185, -615, -712, 693, 784, 32767, 0, - -776, 32767, 32767, -813, 0, 0, 0, 207, - 208, 32767, 674, 32767, 742, -289, 249, 32767, - 520, 929, -50, 781, 0, -778, 32767, 0, - 302, 32767, 720, -465, 0, 32767, 32767, 32767, - 0, 0, 32767, 833, 328, 806, 32767, -403, - 0, 32767, -77, 32767, 0, 441, 930, 32767, - 643, 0, 32767, 1938, 0, 1334, 381, 32767, - 216, 32767, 32767, 0, 32767, 484, 383, 0, - 242, 395, 0, 32767, 32767, 32767, -781, 355, - 356, 32767, 292, 706, 32767, 32767, 32767, 32767, - 32767, -410, 32767, 32767, 782, 32767, 189, 32767, - 32767, 943, 0, -212, 407, 335, 0, 135, - 32767, 616, 0, -497, 0, -67, 853, 32767, - 700, 32767, 0, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, 459, -48, 32767, 58, 0, - -856, 1017, 32767, 59, 916, -731, 32767, 940, - -855, 347, 650, 0, 678, 32767, 0, 32767, - 32767, 530, 32767, 0, -80, 32767, -730, 32767, - 1214, 799, 58, 651, 841, 0, 0, -589, - -1530, -478, 651, 652, 93, 576, -1215, 32767, - 125, 32767, 1279, 32767, 32767, 0, 32767, 0, - -367, 416, -1236, 32767, 418, 32767, 815, 558, - 559, 781, 419, 32767, 739, 32767, 0, 32767, - 128, 570, 1349, -298, -66, 0, 147, -488, - 32767, 590, 189, 274, 524, 32767, 1082, -209, - 32767, 423, 32767, 32767, 975, 573, 32767, 424, - 32767, 32767, 1241, 32767, 32767, 32767, 32767, 32767, - 612, 391, 32767, 0, -803, 1004, -561, 32767, - 32767, 735, 870, 32767, 0, 32767, 32767, -123, - 99, 210, 600, 1294, 109, 1053, 32767, 307, - 834, 32767, 0, 1651, 32767, 644, 32767, 32767, - 0, 32767, -801, 385, 379, 32767, -368, 32767, - 32767, 830, 0, 32767, 32767, 739, 371, 372, - -275, 32767, 32767, 331, -780, 32767, 0, 1229, - -1462, 913, 266, 827, 125, 32767, 32767, 32767, - 393, 32767, 631, -33, -883, -661, -204, 6, - -19, 257, 8, 9, 118, 519, 615, -541, - -893, 0, 32767, 0, 1156, 15, 900, 32767, - 32767, 32767, 32767, 32767, 32767, 1022, 376, 0, - 32767, 32767, -972, 676, 840, -661, 631, 58, - 0, 17, 32767, 0, -799, 82, 0, 32767, - 32767, 680, 32767, 905, 0, 0, 32767, 32767, - 0, 0, 32767, 0, 828, 386, 802, 0, - 146, 0, 148, 32767, -1146, 0, 150, 151, - -743, 153, 154, 32767, 32767, 442, 32767, 743, - 0, 0, 746, 0, 32767, 32767, 32767, 98, - 32767, 157, 0, 696, 0, 32767, 32767, -294, - 32767, 158, 159, 32767, 0, 32767, 160, 32767, - 933, 32767, 32767, -50, 759, 824, 162, 672, - 32767, 356, 0, 356, 32767, 32767, 0, 0, - 656, 692, 253, 254, -374, 102, 256, 32767, - 0, 0, 32767, 32767, 259, 32767, 63, 260, - 510, 261, 32767, 0, 32767, 1061, 32767, 521, - 32767, 32767, 32767, 32767, 32767, 32767, 316, 317, - 846, 0, 32767, -500, 318, 0, 32767, 32767, - 263, 0, 790, 872, 32767, 32767, 32767, 2171, - 264, 32767, 32767, 32767, 32767, 486, 334, 465, - 32767, 466, 32767, 444, 606, 32767, 0, 445, - 320, -317, 0, 520, 322, 718, 32767, 32767, - 32767, 0, 1013, 32767, 32767, 32767, 32767, 32767, - 32767, 611, 32767, 0, 0, 32767, 32767, -120, - 156, 613, 0, 0, 32767, -68, 32767, 622, - 32767, 32767, 32767, 32767, 32767, 455, 32767, 32767, - 32767, 403, 533, 0, -161, 405, 95, 96, - 32767, 97, 32767, 0, 29, 0, 32767, 32767, - 30, 32767, 99, 32767, 32767, 0, 161, 32767, - 97, 0, 32, 32767, 32767, 0, 0, 315, - 32767, 32767, 414, 966, 0, 585, 32767, 32767, - -616, -256, 171, 172, 666, 101, 562, 563, - 32767, 95, 0, 0, 1492, 390, -251, 103, - 32767, 0, 32767, 188, 1487, 32767, 0, 0, - 586, 668, -126, 0, 0, 32767, 32767, 204, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 656, 32767, 32767, - 599, 0, 222, 32767, 0, 1368, -412, 435, - 32767, 936, 32767, -17, 32767, 832, 32767, 437, - 0, -518, 787, 32767, 864, -449, 0, 636, - 713, 206, 592, 572, 0, 483, -139, 32767, - 32767, 180, 818, 32767, 32767, 1304, 0, 32767, - 274, 0, 0, 0, 0, 705, 32767, 32767, - 32767, 0, -272, 0, 502, 503, 319, 0, - 32767, 0, 13, 32767, 32767, 0, 32767, 270, - 737, 0, 32767, 32767, 32767, 901, 32767, 616, - 180, 32767, 721, 353, 32767, 0, 32767, 32767, - -199, 0, 280, 788, 32767, 940, 32767, 51, - 0, 400, 53, 0, 54, -637, 0, -453, - 0, 0, 0, 380, 0, 32767, 504, 0, - 2049, 0, -964, 32767, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 798, 32767, 32767, 32767, 0, - 538, 488, 0, 32767, -528, 57, 819, 32767, - 32767, 1244, 0, 488, 739, 908, 32767, 32767, - 0, 32767, 32767, 0, 55, 533, 0, 32767, - 814, 0, 32767, 458, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 776, 777, 920, 0, - 0, 755, 32767, 0, 32767, 32767, 0, 32767, - 55, -954, 0, 372, 166, 218, 165, 857, - 221, 675, 0, 223, 224, -155, 226, 32767, - 1851, 227, 32767, 32767, 1192, 0, 229, 0, - -72, 0, 865, 0, 0, -330, 0, 683, - 32767, -550, -196, 725, -573, 293, 102, 32767, - -589, 296, 297, 298, 231, -256, 300, 32767, - 32767, 301, 233, 868, 32767, 234, 0, 811, - 1187, 32767, 32767, 0, 32767, 518, 0, 361, - 362, 466, 0, 365, 32767, -179, 366, 367, - 874, 369, 305, 0, 32767, 0, 32767, 0, - 32767, 2000, 1215, 451, 652, 0, 0, 799, - 32767, 32767, 32767 + static const int16 h[1923] = { + -109, -96, 32767, 0, -844, -182, -292, 32767, + 830, 793, 794, 665, 0, -9, 32767, 32767, + 32767, 32767, 32767, 428, 32767, 32767, 32767, 502, + 0, 32767, -230, 144, 356, -76, 0, 243, + 665, 32767, 32767, -1003, 244, 0, 32767, 32767, + 573, 246, 125, 32767, 32767, 32767, 0, 32767, + 32767, 32767, 32767, 0, 245, 32767, 723, 32767, + 0, 889, 32767, 32767, 32767, 0, 32767, 32767, + 0, 173, 157, 1215, 254, 255, -126, 0, + 0, 504, 459, -11, 238, -188, 722, 247, + 260, 32767, -184, -6, 2102, -578, 32767, 32767, + -598, -670, 260, 19, 32767, -472, 32767, 664, + 511, 0, 32767, 345, 291, 0, -370, 176, + 32767, 1017, -139, -519, -30, 0, -24, -23, + 481, -253, -1813, 32767, 0, 935, 32767, 32767, + -443, 32767, 773, 32767, 32767, 32767, -507, 427, + 0, 32767, 899, 32767, 32767, 277, 0, 32767, + 32767, 0, 842, 854, 0, 32767, 936, 621, + -195, 32767, 0, 32767, 707, 268, 32767, 32767, + 435, 32767, 32767, 32767, 0, 267, 88, 72, + 32767, 487, 32767, 32767, 32767, 0, 32767, 32767, + 32767, 32767, 32767, 875, -312, 32767, 483, 875, + 270, 89, 32767, 483, 32767, 32767, 32767, 32767, + 708, 273, 2053, -63, -242, -479, 32767, 352, + 32767, 32767, 0, 560, 544, 32767, 32767, 32767, + 0, 0, 32767, 0, 32767, 32767, 32767, 525, + 274, 32767, 404, 386, 518, 32767, -357, 32767, + -45, 1154, 276, 32767, 149, 0, 277, 714, + 313, 32767, 32767, 32767, 32767, 32767, 841, 460, + 431, 32767, 32767, -49, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 876, 280, 281, 131, 388, + 283, 32767, 1125, 32767, 695, 712, 32767, 0, + 713, 1732, 0, 32767, 0, 231, 32767, 0, + 32767, -755, 32767, 32767, 32767, 435, 32767, 0, + 951, 952, 32767, 32767, 464, 867, 1298, 0, + 660, -55, 0, 292, 663, 118, 661, -722, + 435, 816, 328, 0, 323, 323, -258, -684, + 2114, 0, 302, 0, 32767, 32767, 1607, 32767, + 0, 32767, 32767, 0, 810, 32767, -543, -5, + 515, 32767, 0, 877, 304, 32767, 472, 32767, + 683, -549, 258, 285, -904, 32767, 148, 1202, + 1044, 0, 32767, 32767, 659, 1395, 905, 32767, + 32767, 32767, -626, 32767, 32767, 32767, 32767, 672, + 0, 32767, -139, 32767, 32767, 0, 0, 660, + 1, 32767, -955, -293, 616, 391, 632, -126, + 32767, 32767, 1610, -166, 754, 324, 32767, 32767, + 931, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 0, 32767, 32767, 302, 391, 32767, 32767, + 516, 32767, 32767, 1131, 670, 544, 308, 286, + 0, 0, 32767, 32767, 531, -629, -35, 0, + 6, -63, 485, 0, 0, -486, -58, 0, + 0, 38, 470, -20, 0, 32767, 0, 0, + 956, 32767, 0, 294, -759, 0, 32767, 32767, + -362, 73, 316, 588, 314, 32767, 609, 0, + 318, 32767, 32767, 32767, -759, 1466, -212, 32767, + 1910, 226, 653, 32767, 219, 32767, 32767, 0, + 0, 32767, 1045, -6, -6, 32767, 0, 163, + 0, 0, -9, 879, -369, 32767, -18, 321, + 322, 32767, 32767, -449, 1082, 324, 57, 32767, + -403, 252, 697, 0, 491, 552, 0, 32767, + 32767, 32767, 864, 32767, 0, 32767, 929, -582, + 32767, 32767, 32767, 1521, 32767, 32767, 32767, 212, + 326, -542, 332, 333, 334, -490, 692, 336, + 32767, 337, 338, 31, 0, 714, 348, 34, + 342, 32767, 1602, 32767, 687, 143, 32767, 0, + 32767, 32767, 0, 32767, 196, -21, 32767, 32767, + -4, 32767, 32767, 880, -211, 203, 32767, 1078, + 83, 1661, 32767, 32767, 283, 787, 348, 32767, + 0, -464, 0, 32767, 725, -431, -811, -322, + 7, 32767, -315, 267, 694, -2103, 12, 247, + 13, 692, 32767, -1593, 32767, 15, 32767, 32767, + 830, 0, 623, 354, 32767, 32767, -154, 0, + 264, -712, 32767, 357, 32767, 32767, 220, -242, + 32767, 921, 905, 32767, -1184, 549, 32767, 19, + 319, 32767, 551, 32767, 1307, 0, 32767, 32767, + 32767, 0, 566, 881, 822, 936, 326, 89, + -313, 32767, 250, 0, 359, 360, 32767, 32767, + 32767, 32767, -575, 20, 32767, 98, 23, 32767, + 287, 744, 124, 1027, 32767, 0, 564, 0, + -548, -497, 982, 32767, 32767, 32767, 32767, 32767, + 35, 316, -1859, 343, 364, 786, 0, 32767, + 366, 4, 0, 753, 581, 524, 270, 686, + 0, -382, 32767, -1189, 0, 747, 32767, 363, + 32767, 32767, -1782, 32767, 28, 32767, 677, 452, + 210, 0, 884, 882, -258, 32767, -1099, -222, + 32767, 32767, 32767, 32767, 373, 671, 32767, 311, + 32767, 370, 32767, -831, 101, 32, 35, 36, + -1159, 930, 38, 39, -148, -148, 32767, 32767, + -150, -803, 1185, 675, 32767, -152, 32767, 0, + 633, 467, -279, 827, 32767, 1273, -410, 136, + 32767, 527, 842, 397, 32767, 1149, 376, 45, + 2221, 20, 0, -421, 47, 925, 0, 363, + 368, -384, 0, 32767, -230, 32767, -532, 32767, + 32767, 32767, 0, 32767, 634, 219, -6, 397, + 32767, 32767, 692, 385, 361, 483, 526, 32767, + 0, 32767, 628, 728, 2167, 51, 892, 32767, + -326, -595, 54, 55, 32767, 825, 0, 0, + 933, 32767, 32767, 32767, 828, 32767, 32767, 883, + -144, 32767, 32767, 32767, 933, 0, 0, 209, + 1580, 790, 0, 0, 32767, 32767, 32767, 730, + 731, 32767, 58, 57, 457, 557, 32767, 59, + 60, 0, -1438, 32767, 1016, 32767, 1344, 683, + 32767, 0, 32767, 32767, 32767, 32767, 32767, 558, + 45, 32767, 0, 32767, 0, 0, 843, 0, + 32767, 0, 503, 62, 488, 600, -395, -328, + 69, 566, -355, 1027, -737, -72, -606, 32767, + 74, 32767, 32767, 1144, 32767, -75, 32767, 884, + -144, 32767, 22, 598, 32767, 792, 32767, 32767, + 32767, 32767, 32767, -336, 32767, 32767, 0, 45, + 0, 32767, 658, 637, 78, 95, -962, 0, + 0, 32767, 256, 0, -247, -201, 32767, 32767, + 447, 0, 0, 0, 32767, 445, 806, 860, + -39, 74, 32767, -6, 32767, 529, 32767, 700, + 307, 179, 0, 893, 32767, 835, 0, -29, + 32767, 32767, 32767, 32767, -754, 32767, 32767, 32767, + -702, -227, -55, 0, 517, -196, 32767, 784, + 177, 0, -1082, 597, -166, 797, 32767, 32767, + 613, 32767, 1211, 32767, -283, 126, 32767, 83, + 526, -1584, 533, 172, 950, 0, 0, 32767, + 32767, -1767, -88, 32767, 87, -1289, 773, 953, + 1131, 0, 0, 32767, 1374, 0, 32767, 32767, + 32767, 798, 32767, 0, 1547, 158, 613, 32767, + 32767, -822, 32767, 88, 473, 474, 378, 89, + 940, 659, 352, -270, 0, -1015, 477, 32767, + 901, 91, 1068, 32767, 0, 0, 32767, 32767, + 0, 32767, 461, 404, 32767, 46, -65, 32767, + 32767, 815, 822, 32767, 32767, 32767, 406, 925, + 338, -487, 0, 97, 438, -464, 32767, 98, + 0, 0, 1113, 0, -416, 0, 32767, 0, + -35, 0, 180, 413, 32767, 32767, 0, -219, + 568, 175, 0, 0, 32767, 503, 0, 32767, + 528, 32767, 32767, -464, 733, 140, 106, 101, + 171, 32767, 109, 110, 597, 170, 32767, 113, + 76, 103, 32767, 115, 559, 116, 32767, -213, + 32767, 0, 597, 823, 32767, 801, 32767, 479, + 803, 631, 723, 32767, 538, -394, 468, -200, + 411, 29, 32767, 32767, -1347, 361, 32767, -458, + 655, 32767, 32767, 32767, -791, 0, 32767, 540, + 541, 32767, 32767, -14, 959, 32767, 0, 462, + 32767, 802, 32767, 32767, 846, 734, 32767, 32767, + 735, 32767, 32767, 32767, 32767, 32767, 0, 32767, + 32767, -685, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 44, 32767, 0, 807, 131, 349, 0, + 0, 7, -94, 423, 0, 529, 32767, 32767, + 32767, 286, 0, 32767, -145, 400, 281, 445, + 32767, 122, 32767, -300, 600, 571, 769, 945, + 518, 0, 461, 32767, -254, 32767, -423, -534, + 462, 396, 0, 886, 425, -956, 809, 145, + 573, 810, 0, 401, 0, -1069, 0, 151, + 1011, 0, 0, 81, 32767, -411, 0, -687, + 859, 451, -1447, 132, 32767, 32767, 32767, 32767, + -154, 32, 32767, 32767, 32767, 32767, 0, 32767, + 32767, 32767, 37, 408, 0, 811, 326, 32767, + 0, -374, 32767, -184, 741, -376, 91, 134, + 32767, 486, 135, -40, 579, 373, 32767, 547, + 32767, 32767, 32767, 32767, -259, 873, 0, 0, + 0, 825, -373, 0, 32767, 0, 0, 308, + 340, -373, 32767, 0, 0, 32767, -1259, 32767, + 742, 32767, 643, 139, 144, 349, -79, 147, + 148, 32767, 149, 732, 425, -219, 152, -446, + 556, 143, 32767, 155, 165, -1314, 0, 888, + 439, 32767, 0, 0, 0, 813, 405, 29, + 32767, 6, 0, 0, 743, 32767, 1902, 158, + 159, 32767, 381, 0, -102, 196, 0, 769, + -419, -596, 0, 782, 162, 32767, 32767, -580, + 32767, 32767, 32767, 32767, 1126, 32767, 32767, 412, + 32767, 814, 824, 32767, 32767, 0, 32767, 32767, + 744, 32767, 32767, 746, 0, 1480, 167, 0, + 1189, 32767, 32767, 168, 169, 32767, 0, 32767, + 906, 32767, 32767, 32767, 32767, 32767, 32767, 601, + 32767, 32767, -278, 0, 32767, 1261, 414, 32767, + 32767, 32767, 32767, 375, 378, 589, 644, 750, + 751, 937, 32767, 590, 32767, 591, 32767, 171, + 172, 32767, 32767, 32767, 32767, 1195, 32767, 32767, + 721, 0, 0, -505, -14, 6, 0, 0, + 0, 1058, -718, 99, 0, 372, 327, 32767, + 729, -166, 32767, 0, 173, -939, 175, 592, + 177, 576, 32767, 213, 179, 0, 0, 514, + 620, 32767, 32767, 32767, 32767, 0, 32767, 32767, + 958, -240, 0, -840, 32767, 379, 32767, 0, + 0, 752, 673, -432, 159, -877, 32767, -416, + 32767, 182, -211, 0, 0, 594, 32767, 184, + -1070, 32767, 32767, 32767, 185, 0, 0, 32767, + 710, 32767, 32767, 32767, 32767, 928, 32767, 32767, + 0, 126, 942, 32767, 0, 0, 32767, 867, + 697, -355, 32767, 625, 0, 596, 32767, 597, + -243, 583, 32767, 0, 0, 0, 0, 0, + 584, 650, 0, 32767, 515, 32767, 0, 892, + 0, 0, -271, 274, 32767, 418, 32767, 0, + 32767, 32767, 32767, 440, -1147, 32767, 0, 32767, + 32767, 651, 652, 564, 32767, 32767, 32767, 0, + 32767, 32767, 32767, 32767, 947, -68, 32767, 688, + 32767, 0, 0, 689, 915, 916, 0, 0, + -204, 225, 0, 0, 0, 0, 32767, -275, + 370, 0, 599, -402, 32767, 571, 0, 32767, + 1470, 594, 32767, 772, 773, 1458, 0, 907, + 1048, 32767, 128, 4, 32767, 0, 32767, 1880, + 32767, 32767, 0, 0, 684, 32767, 0, 262, + 32767, 32767, 32767, 32767, 757, 32767, 32767, 0, + 196, 32767, -258, -552, -998, 0, 950, 774, + -35, 32767, 0, 32767, 0, 32767, 15, 32767, + 0, 32767, 0, 27, 198, 760, 32767, 32767, + 1204, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 620, 32767, 32767, 760, 761, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 32767, 32767, 0, 32767, 0, + 1195, 918, 32767, 32767, 32767, 32767, 0, 0, + 32767, 32767, 32767, 32767, 903, 32767, 32767, 763, + 764, 0, 32767, 0, 32767, 32767, 0, 32767, + 833, 32767, 32767, 32767, 1132, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 450, 32767, 32767, 420, + 32767, 32767, 32767, 32767, -68, 2, 0, 0, + 1196, 0, 0, 0, 188, 189, 190, 191, + 192, 600, 0, -632, -43, 196, 89, 489, + 294, 1248, 32767, 1043, 32767, 492, 32767, 32767, + 519, 0, 32767, 863, 32767, 32767, 32767, 0, + 32767, 765, 493, 467, 0, 32767, 32767, 201, + 32767, 432, 849, 32767, 279, 0, 0, 204, + 834, 32767, 0, 32767, 1670, 32767, 0, 32767, + 0, 32767, 32767, 32767, 919, 929, 32767, 0, + 32767, -363, 0, 32767, 32767, 0, 434, -56, + 32767, 436, 0, 349, 0, 207, 208, 437, + 32767, 0, 32767, -694, -408, 32767, 0, 32767, + 210, 206, 0, 653, 32767, 32767, 0, 402, + 1105, 0, 32767, 693, 0, 0, 938, 32767, + 32767, 32767, 438, 541, 131, 440, 871, 32767, + 32767, 0, 32767, 279, 32767, 32767, 287, 212, + 0, 0, 32767, 32767, 367, 32767, 696, 697, + 32767, 0, 0, 0, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 0, -1321, 32767, + 0, 176, 32767, 214, 218, 724, 234, 215, + 222, 32767, 223, -834, 943, 127, 32767, 496, + -100, 217, 0, 394, 32767, 229, 32767, 0, + 0, 17, 421, 415, 447, 0, 32767, 686, + 32767, 32767, 1845, 138, 32767, 32767, 872, 230, + 32767, 601, 851, 471, 232, 603, 32767, 778, + 698, 233, 32767, 699, -439, 32767, 0, 32767, + 32767, 32767, 663, 32767, 32767, 32767, 32767, -298, + 449, 32767, -463, 687, 32767, 32767, 427, 32767, + 0, 0, 0, 0, 0, 236, 193, 826, + 238, 0, 108 }; const unsigned char *k = (const unsigned char *) key; @@ -2962,7 +3004,7 @@ Recomp_hash_func(const void *key) a = a * 257 + c; b = b * 17 + c; } - return h[a % 1883] + h[b % 1883]; + return h[a % 1923] + h[b % 1923]; } /* Hash lookup information for recomposition */ @@ -2970,5 +3012,5 @@ static const pg_unicode_recompinfo UnicodeRecompInfo = { RecompInverseLookup, Recomp_hash_func, - 941 + 961 }; diff --git a/src/include/common/unicode_norm_table.h b/src/include/common/unicode_norm_table.h index 7ef8efac8afab..6c98313599641 100644 --- a/src/include/common/unicode_norm_table.h +++ b/src/include/common/unicode_norm_table.h @@ -3,7 +3,7 @@ * unicode_norm_table.h * Composition table used for Unicode normalization * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_norm_table.h @@ -36,7 +36,7 @@ typedef struct #define DECOMPOSITION_IS_COMPAT(x) (((x)->dec_size_flags & DECOMP_COMPAT) != 0) /* Table of Unicode codepoints and their decompositions */ -static const pg_unicode_decomposition UnicodeDecompMain[6775] = +static const pg_unicode_decomposition UnicodeDecompMain[6843] = { {0x00A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020}, {0x00A8, 0, 2 | DECOMP_COMPAT, 0}, @@ -727,6 +727,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x0859, 220, 0, 0}, {0x085A, 220, 0, 0}, {0x085B, 220, 0, 0}, + {0x0897, 230, 0, 0}, {0x0898, 230, 0, 0}, {0x0899, 220, 0, 0}, {0x089A, 220, 0, 0}, @@ -4636,6 +4637,8 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x10378, 230, 0, 0}, {0x10379, 230, 0, 0}, {0x1037A, 230, 0, 0}, + {0x105C9, 0, 2, 4776}, + {0x105E4, 0, 2, 4778}, {0x10781, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02D0}, {0x10782, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02D1}, {0x10783, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00E6}, @@ -4662,18 +4665,18 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x10799, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02AA}, {0x1079A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x02AB}, {0x1079B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026C}, - {0x1079C, 0, 1 | DECOMP_COMPAT, 4776}, + {0x1079C, 0, 1 | DECOMP_COMPAT, 4780}, {0x1079D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA78E}, {0x1079E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026E}, - {0x1079F, 0, 1 | DECOMP_COMPAT, 4777}, + {0x1079F, 0, 1 | DECOMP_COMPAT, 4781}, {0x107A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028E}, - {0x107A1, 0, 1 | DECOMP_COMPAT, 4778}, + {0x107A1, 0, 1 | DECOMP_COMPAT, 4782}, {0x107A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00F8}, {0x107A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0276}, {0x107A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0277}, {0x107A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071}, {0x107A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027A}, - {0x107A7, 0, 1 | DECOMP_COMPAT, 4779}, + {0x107A7, 0, 1 | DECOMP_COMPAT, 4783}, {0x107A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027D}, {0x107A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027E}, {0x107AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0280}, @@ -4690,8 +4693,8 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x107B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C0}, {0x107B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C1}, {0x107B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01C2}, - {0x107B9, 0, 1 | DECOMP_COMPAT, 4780}, - {0x107BA, 0, 1 | DECOMP_COMPAT, 4781}, + {0x107B9, 0, 1 | DECOMP_COMPAT, 4784}, + {0x107BA, 0, 1 | DECOMP_COMPAT, 4785}, {0x10A0D, 220, 0, 0}, {0x10A0F, 230, 0, 0}, {0x10A38, 230, 0, 0}, @@ -4704,6 +4707,11 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x10D25, 230, 0, 0}, {0x10D26, 230, 0, 0}, {0x10D27, 230, 0, 0}, + {0x10D69, 230, 0, 0}, + {0x10D6A, 230, 0, 0}, + {0x10D6B, 230, 0, 0}, + {0x10D6C, 230, 0, 0}, + {0x10D6D, 230, 0, 0}, {0x10EAB, 230, 0, 0}, {0x10EAC, 230, 0, 0}, {0x10EFD, 220, 0, 0}, @@ -4727,16 +4735,16 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x11046, 9, 0, 0}, {0x11070, 9, 0, 0}, {0x1107F, 9, 0, 0}, - {0x1109A, 0, 2, 4782}, - {0x1109C, 0, 2, 4784}, - {0x110AB, 0, 2, 4786}, + {0x1109A, 0, 2, 4786}, + {0x1109C, 0, 2, 4788}, + {0x110AB, 0, 2, 4790}, {0x110B9, 9, 0, 0}, {0x110BA, 7, 0, 0}, {0x11100, 230, 0, 0}, {0x11101, 230, 0, 0}, {0x11102, 230, 0, 0}, - {0x1112E, 0, 2, 4788}, - {0x1112F, 0, 2, 4790}, + {0x1112E, 0, 2, 4792}, + {0x1112F, 0, 2, 4794}, {0x11133, 9, 0, 0}, {0x11134, 9, 0, 0}, {0x11173, 7, 0, 0}, @@ -4748,8 +4756,8 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x112EA, 9, 0, 0}, {0x1133B, 7, 0, 0}, {0x1133C, 7, 0, 0}, - {0x1134B, 0, 2, 4792}, - {0x1134C, 0, 2, 4794}, + {0x1134B, 0, 2, 4796}, + {0x1134C, 0, 2, 4798}, {0x1134D, 9, 0, 0}, {0x11366, 230, 0, 0}, {0x11367, 230, 0, 0}, @@ -4763,16 +4771,26 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x11372, 230, 0, 0}, {0x11373, 230, 0, 0}, {0x11374, 230, 0, 0}, + {0x11383, 0, 2, 4800}, + {0x11385, 0, 2, 4802}, + {0x1138E, 0, 2, 4804}, + {0x11391, 0, 2, 4806}, + {0x113C5, 0, 2, 4808}, + {0x113C7, 0, 2, 4810}, + {0x113C8, 0, 2, 4812}, + {0x113CE, 9, 0, 0}, + {0x113CF, 9, 0, 0}, + {0x113D0, 9, 0, 0}, {0x11442, 9, 0, 0}, {0x11446, 7, 0, 0}, {0x1145E, 230, 0, 0}, - {0x114BB, 0, 2, 4796}, - {0x114BC, 0, 2, 4798}, - {0x114BE, 0, 2, 4800}, + {0x114BB, 0, 2, 4814}, + {0x114BC, 0, 2, 4816}, + {0x114BE, 0, 2, 4818}, {0x114C2, 9, 0, 0}, {0x114C3, 7, 0, 0}, - {0x115BA, 0, 2, 4802}, - {0x115BB, 0, 2, 4804}, + {0x115BA, 0, 2, 4820}, + {0x115BB, 0, 2, 4822}, {0x115BF, 9, 0, 0}, {0x115C0, 7, 0, 0}, {0x1163F, 9, 0, 0}, @@ -4781,7 +4799,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1172B, 9, 0, 0}, {0x11839, 9, 0, 0}, {0x1183A, 7, 0, 0}, - {0x11938, 0, 2, 4806}, + {0x11938, 0, 2, 4824}, {0x1193D, 9, 0, 0}, {0x1193E, 9, 0, 0}, {0x11943, 7, 0, 0}, @@ -4796,6 +4814,15 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x11D97, 9, 0, 0}, {0x11F41, 9, 0, 0}, {0x11F42, 9, 0, 0}, + {0x16121, 0, 2, 4826}, + {0x16122, 0, 2, 4828}, + {0x16123, 0, 2, 4830}, + {0x16124, 0, 2, 4832}, + {0x16125, 0, 2, 4834}, + {0x16126, 0, 2, 4836}, + {0x16127, 0, 2, 4838}, + {0x16128, 0, 2, 4840}, + {0x1612F, 9, 0, 0}, {0x16AF0, 1, 0, 0}, {0x16AF1, 1, 0, 0}, {0x16AF2, 1, 0, 0}, @@ -4808,16 +4835,55 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x16B34, 230, 0, 0}, {0x16B35, 230, 0, 0}, {0x16B36, 230, 0, 0}, + {0x16D68, 0, 2, 4842}, + {0x16D69, 0, 2, 4844}, + {0x16D6A, 0, 2, 4846}, {0x16FF0, 6, 0, 0}, {0x16FF1, 6, 0, 0}, {0x1BC9E, 1, 0, 0}, - {0x1D15E, 0, 2 | DECOMP_NO_COMPOSE, 4808}, /* in exclusion list */ - {0x1D15F, 0, 2 | DECOMP_NO_COMPOSE, 4810}, /* in exclusion list */ - {0x1D160, 0, 2 | DECOMP_NO_COMPOSE, 4812}, /* in exclusion list */ - {0x1D161, 0, 2 | DECOMP_NO_COMPOSE, 4814}, /* in exclusion list */ - {0x1D162, 0, 2 | DECOMP_NO_COMPOSE, 4816}, /* in exclusion list */ - {0x1D163, 0, 2 | DECOMP_NO_COMPOSE, 4818}, /* in exclusion list */ - {0x1D164, 0, 2 | DECOMP_NO_COMPOSE, 4820}, /* in exclusion list */ + {0x1CCD6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041}, + {0x1CCD7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042}, + {0x1CCD8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043}, + {0x1CCD9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044}, + {0x1CCDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045}, + {0x1CCDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046}, + {0x1CCDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047}, + {0x1CCDD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048}, + {0x1CCDE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049}, + {0x1CCDF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A}, + {0x1CCE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B}, + {0x1CCE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C}, + {0x1CCE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D}, + {0x1CCE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E}, + {0x1CCE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F}, + {0x1CCE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050}, + {0x1CCE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051}, + {0x1CCE7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052}, + {0x1CCE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053}, + {0x1CCE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054}, + {0x1CCEA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055}, + {0x1CCEB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056}, + {0x1CCEC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057}, + {0x1CCED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058}, + {0x1CCEE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059}, + {0x1CCEF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A}, + {0x1CCF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030}, + {0x1CCF1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031}, + {0x1CCF2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032}, + {0x1CCF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033}, + {0x1CCF4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034}, + {0x1CCF5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035}, + {0x1CCF6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036}, + {0x1CCF7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037}, + {0x1CCF8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038}, + {0x1CCF9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039}, + {0x1D15E, 0, 2 | DECOMP_NO_COMPOSE, 4848}, /* in exclusion list */ + {0x1D15F, 0, 2 | DECOMP_NO_COMPOSE, 4850}, /* in exclusion list */ + {0x1D160, 0, 2 | DECOMP_NO_COMPOSE, 4852}, /* in exclusion list */ + {0x1D161, 0, 2 | DECOMP_NO_COMPOSE, 4854}, /* in exclusion list */ + {0x1D162, 0, 2 | DECOMP_NO_COMPOSE, 4856}, /* in exclusion list */ + {0x1D163, 0, 2 | DECOMP_NO_COMPOSE, 4858}, /* in exclusion list */ + {0x1D164, 0, 2 | DECOMP_NO_COMPOSE, 4860}, /* in exclusion list */ {0x1D165, 216, 0, 0}, {0x1D166, 216, 0, 0}, {0x1D167, 1, 0, 0}, @@ -4848,12 +4914,12 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1D1AB, 230, 0, 0}, {0x1D1AC, 230, 0, 0}, {0x1D1AD, 230, 0, 0}, - {0x1D1BB, 0, 2 | DECOMP_NO_COMPOSE, 4822}, /* in exclusion list */ - {0x1D1BC, 0, 2 | DECOMP_NO_COMPOSE, 4824}, /* in exclusion list */ - {0x1D1BD, 0, 2 | DECOMP_NO_COMPOSE, 4826}, /* in exclusion list */ - {0x1D1BE, 0, 2 | DECOMP_NO_COMPOSE, 4828}, /* in exclusion list */ - {0x1D1BF, 0, 2 | DECOMP_NO_COMPOSE, 4830}, /* in exclusion list */ - {0x1D1C0, 0, 2 | DECOMP_NO_COMPOSE, 4832}, /* in exclusion list */ + {0x1D1BB, 0, 2 | DECOMP_NO_COMPOSE, 4862}, /* in exclusion list */ + {0x1D1BC, 0, 2 | DECOMP_NO_COMPOSE, 4864}, /* in exclusion list */ + {0x1D1BD, 0, 2 | DECOMP_NO_COMPOSE, 4866}, /* in exclusion list */ + {0x1D1BE, 0, 2 | DECOMP_NO_COMPOSE, 4868}, /* in exclusion list */ + {0x1D1BF, 0, 2 | DECOMP_NO_COMPOSE, 4870}, /* in exclusion list */ + {0x1D1C0, 0, 2 | DECOMP_NO_COMPOSE, 4872}, /* in exclusion list */ {0x1D242, 230, 0, 0}, {0x1D243, 230, 0, 0}, {0x1D244, 230, 0, 0}, @@ -5970,6 +6036,8 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1E4ED, 232, 0, 0}, {0x1E4EE, 220, 0, 0}, {0x1E4EF, 230, 0, 0}, + {0x1E5EE, 230, 0, 0}, + {0x1E5EF, 220, 0, 0}, {0x1E8D0, 220, 0, 0}, {0x1E8D1, 220, 0, 0}, {0x1E8D2, 220, 0, 0}, @@ -6125,48 +6193,48 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1EEB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636}, {0x1EEBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638}, {0x1EEBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A}, - {0x1F100, 0, 2 | DECOMP_COMPAT, 4834}, - {0x1F101, 0, 2 | DECOMP_COMPAT, 4836}, - {0x1F102, 0, 2 | DECOMP_COMPAT, 4838}, - {0x1F103, 0, 2 | DECOMP_COMPAT, 4840}, - {0x1F104, 0, 2 | DECOMP_COMPAT, 4842}, - {0x1F105, 0, 2 | DECOMP_COMPAT, 4844}, - {0x1F106, 0, 2 | DECOMP_COMPAT, 4846}, - {0x1F107, 0, 2 | DECOMP_COMPAT, 4848}, - {0x1F108, 0, 2 | DECOMP_COMPAT, 4850}, - {0x1F109, 0, 2 | DECOMP_COMPAT, 4852}, - {0x1F10A, 0, 2 | DECOMP_COMPAT, 4854}, - {0x1F110, 0, 3 | DECOMP_COMPAT, 4856}, - {0x1F111, 0, 3 | DECOMP_COMPAT, 4859}, - {0x1F112, 0, 3 | DECOMP_COMPAT, 4862}, - {0x1F113, 0, 3 | DECOMP_COMPAT, 4865}, - {0x1F114, 0, 3 | DECOMP_COMPAT, 4868}, - {0x1F115, 0, 3 | DECOMP_COMPAT, 4871}, - {0x1F116, 0, 3 | DECOMP_COMPAT, 4874}, - {0x1F117, 0, 3 | DECOMP_COMPAT, 4877}, - {0x1F118, 0, 3 | DECOMP_COMPAT, 4880}, - {0x1F119, 0, 3 | DECOMP_COMPAT, 4883}, - {0x1F11A, 0, 3 | DECOMP_COMPAT, 4886}, - {0x1F11B, 0, 3 | DECOMP_COMPAT, 4889}, - {0x1F11C, 0, 3 | DECOMP_COMPAT, 4892}, - {0x1F11D, 0, 3 | DECOMP_COMPAT, 4895}, - {0x1F11E, 0, 3 | DECOMP_COMPAT, 4898}, - {0x1F11F, 0, 3 | DECOMP_COMPAT, 4901}, - {0x1F120, 0, 3 | DECOMP_COMPAT, 4904}, - {0x1F121, 0, 3 | DECOMP_COMPAT, 4907}, - {0x1F122, 0, 3 | DECOMP_COMPAT, 4910}, - {0x1F123, 0, 3 | DECOMP_COMPAT, 4913}, - {0x1F124, 0, 3 | DECOMP_COMPAT, 4916}, - {0x1F125, 0, 3 | DECOMP_COMPAT, 4919}, - {0x1F126, 0, 3 | DECOMP_COMPAT, 4922}, - {0x1F127, 0, 3 | DECOMP_COMPAT, 4925}, - {0x1F128, 0, 3 | DECOMP_COMPAT, 4928}, - {0x1F129, 0, 3 | DECOMP_COMPAT, 4931}, - {0x1F12A, 0, 3 | DECOMP_COMPAT, 4934}, + {0x1F100, 0, 2 | DECOMP_COMPAT, 4874}, + {0x1F101, 0, 2 | DECOMP_COMPAT, 4876}, + {0x1F102, 0, 2 | DECOMP_COMPAT, 4878}, + {0x1F103, 0, 2 | DECOMP_COMPAT, 4880}, + {0x1F104, 0, 2 | DECOMP_COMPAT, 4882}, + {0x1F105, 0, 2 | DECOMP_COMPAT, 4884}, + {0x1F106, 0, 2 | DECOMP_COMPAT, 4886}, + {0x1F107, 0, 2 | DECOMP_COMPAT, 4888}, + {0x1F108, 0, 2 | DECOMP_COMPAT, 4890}, + {0x1F109, 0, 2 | DECOMP_COMPAT, 4892}, + {0x1F10A, 0, 2 | DECOMP_COMPAT, 4894}, + {0x1F110, 0, 3 | DECOMP_COMPAT, 4896}, + {0x1F111, 0, 3 | DECOMP_COMPAT, 4899}, + {0x1F112, 0, 3 | DECOMP_COMPAT, 4902}, + {0x1F113, 0, 3 | DECOMP_COMPAT, 4905}, + {0x1F114, 0, 3 | DECOMP_COMPAT, 4908}, + {0x1F115, 0, 3 | DECOMP_COMPAT, 4911}, + {0x1F116, 0, 3 | DECOMP_COMPAT, 4914}, + {0x1F117, 0, 3 | DECOMP_COMPAT, 4917}, + {0x1F118, 0, 3 | DECOMP_COMPAT, 4920}, + {0x1F119, 0, 3 | DECOMP_COMPAT, 4923}, + {0x1F11A, 0, 3 | DECOMP_COMPAT, 4926}, + {0x1F11B, 0, 3 | DECOMP_COMPAT, 4929}, + {0x1F11C, 0, 3 | DECOMP_COMPAT, 4932}, + {0x1F11D, 0, 3 | DECOMP_COMPAT, 4935}, + {0x1F11E, 0, 3 | DECOMP_COMPAT, 4938}, + {0x1F11F, 0, 3 | DECOMP_COMPAT, 4941}, + {0x1F120, 0, 3 | DECOMP_COMPAT, 4944}, + {0x1F121, 0, 3 | DECOMP_COMPAT, 4947}, + {0x1F122, 0, 3 | DECOMP_COMPAT, 4950}, + {0x1F123, 0, 3 | DECOMP_COMPAT, 4953}, + {0x1F124, 0, 3 | DECOMP_COMPAT, 4956}, + {0x1F125, 0, 3 | DECOMP_COMPAT, 4959}, + {0x1F126, 0, 3 | DECOMP_COMPAT, 4962}, + {0x1F127, 0, 3 | DECOMP_COMPAT, 4965}, + {0x1F128, 0, 3 | DECOMP_COMPAT, 4968}, + {0x1F129, 0, 3 | DECOMP_COMPAT, 4971}, + {0x1F12A, 0, 3 | DECOMP_COMPAT, 4974}, {0x1F12B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043}, {0x1F12C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052}, - {0x1F12D, 0, 2 | DECOMP_COMPAT, 4937}, - {0x1F12E, 0, 2 | DECOMP_COMPAT, 4939}, + {0x1F12D, 0, 2 | DECOMP_COMPAT, 4977}, + {0x1F12E, 0, 2 | DECOMP_COMPAT, 4979}, {0x1F130, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041}, {0x1F131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042}, {0x1F132, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043}, @@ -6193,18 +6261,18 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1F147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058}, {0x1F148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059}, {0x1F149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A}, - {0x1F14A, 0, 2 | DECOMP_COMPAT, 4941}, - {0x1F14B, 0, 2 | DECOMP_COMPAT, 4943}, - {0x1F14C, 0, 2 | DECOMP_COMPAT, 4945}, - {0x1F14D, 0, 2 | DECOMP_COMPAT, 4947}, - {0x1F14E, 0, 3 | DECOMP_COMPAT, 4949}, - {0x1F14F, 0, 2 | DECOMP_COMPAT, 4952}, - {0x1F16A, 0, 2 | DECOMP_COMPAT, 4954}, - {0x1F16B, 0, 2 | DECOMP_COMPAT, 4956}, - {0x1F16C, 0, 2 | DECOMP_COMPAT, 4958}, - {0x1F190, 0, 2 | DECOMP_COMPAT, 4960}, - {0x1F200, 0, 2 | DECOMP_COMPAT, 4962}, - {0x1F201, 0, 2 | DECOMP_COMPAT, 4964}, + {0x1F14A, 0, 2 | DECOMP_COMPAT, 4981}, + {0x1F14B, 0, 2 | DECOMP_COMPAT, 4983}, + {0x1F14C, 0, 2 | DECOMP_COMPAT, 4985}, + {0x1F14D, 0, 2 | DECOMP_COMPAT, 4987}, + {0x1F14E, 0, 3 | DECOMP_COMPAT, 4989}, + {0x1F14F, 0, 2 | DECOMP_COMPAT, 4992}, + {0x1F16A, 0, 2 | DECOMP_COMPAT, 4994}, + {0x1F16B, 0, 2 | DECOMP_COMPAT, 4996}, + {0x1F16C, 0, 2 | DECOMP_COMPAT, 4998}, + {0x1F190, 0, 2 | DECOMP_COMPAT, 5000}, + {0x1F200, 0, 2 | DECOMP_COMPAT, 5002}, + {0x1F201, 0, 2 | DECOMP_COMPAT, 5004}, {0x1F202, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5}, {0x1F210, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x624B}, {0x1F211, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B57}, @@ -6250,15 +6318,15 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x1F239, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5272}, {0x1F23A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x55B6}, {0x1F23B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x914D}, - {0x1F240, 0, 3 | DECOMP_COMPAT, 4966}, - {0x1F241, 0, 3 | DECOMP_COMPAT, 4969}, - {0x1F242, 0, 3 | DECOMP_COMPAT, 4972}, - {0x1F243, 0, 3 | DECOMP_COMPAT, 4975}, - {0x1F244, 0, 3 | DECOMP_COMPAT, 4978}, - {0x1F245, 0, 3 | DECOMP_COMPAT, 4981}, - {0x1F246, 0, 3 | DECOMP_COMPAT, 4984}, - {0x1F247, 0, 3 | DECOMP_COMPAT, 4987}, - {0x1F248, 0, 3 | DECOMP_COMPAT, 4990}, + {0x1F240, 0, 3 | DECOMP_COMPAT, 5006}, + {0x1F241, 0, 3 | DECOMP_COMPAT, 5009}, + {0x1F242, 0, 3 | DECOMP_COMPAT, 5012}, + {0x1F243, 0, 3 | DECOMP_COMPAT, 5015}, + {0x1F244, 0, 3 | DECOMP_COMPAT, 5018}, + {0x1F245, 0, 3 | DECOMP_COMPAT, 5021}, + {0x1F246, 0, 3 | DECOMP_COMPAT, 5024}, + {0x1F247, 0, 3 | DECOMP_COMPAT, 5027}, + {0x1F248, 0, 3 | DECOMP_COMPAT, 5030}, {0x1F250, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F97}, {0x1F251, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53EF}, {0x1FBF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030}, @@ -6274,7 +6342,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F800, 0, 1 | DECOMP_INLINE, 0x4E3D}, {0x2F801, 0, 1 | DECOMP_INLINE, 0x4E38}, {0x2F802, 0, 1 | DECOMP_INLINE, 0x4E41}, - {0x2F803, 0, 1, 4993}, + {0x2F803, 0, 1, 5033}, {0x2F804, 0, 1 | DECOMP_INLINE, 0x4F60}, {0x2F805, 0, 1 | DECOMP_INLINE, 0x4FAE}, {0x2F806, 0, 1 | DECOMP_INLINE, 0x4FBB}, @@ -6284,22 +6352,22 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F80A, 0, 1 | DECOMP_INLINE, 0x50E7}, {0x2F80B, 0, 1 | DECOMP_INLINE, 0x50CF}, {0x2F80C, 0, 1 | DECOMP_INLINE, 0x349E}, - {0x2F80D, 0, 1, 4994}, + {0x2F80D, 0, 1, 5034}, {0x2F80E, 0, 1 | DECOMP_INLINE, 0x514D}, {0x2F80F, 0, 1 | DECOMP_INLINE, 0x5154}, {0x2F810, 0, 1 | DECOMP_INLINE, 0x5164}, {0x2F811, 0, 1 | DECOMP_INLINE, 0x5177}, - {0x2F812, 0, 1, 4995}, + {0x2F812, 0, 1, 5035}, {0x2F813, 0, 1 | DECOMP_INLINE, 0x34B9}, {0x2F814, 0, 1 | DECOMP_INLINE, 0x5167}, {0x2F815, 0, 1 | DECOMP_INLINE, 0x518D}, - {0x2F816, 0, 1, 4996}, + {0x2F816, 0, 1, 5036}, {0x2F817, 0, 1 | DECOMP_INLINE, 0x5197}, {0x2F818, 0, 1 | DECOMP_INLINE, 0x51A4}, {0x2F819, 0, 1 | DECOMP_INLINE, 0x4ECC}, {0x2F81A, 0, 1 | DECOMP_INLINE, 0x51AC}, {0x2F81B, 0, 1 | DECOMP_INLINE, 0x51B5}, - {0x2F81C, 0, 1, 4997}, + {0x2F81C, 0, 1, 5037}, {0x2F81D, 0, 1 | DECOMP_INLINE, 0x51F5}, {0x2F81E, 0, 1 | DECOMP_INLINE, 0x5203}, {0x2F81F, 0, 1 | DECOMP_INLINE, 0x34DF}, @@ -6323,11 +6391,11 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F831, 0, 1 | DECOMP_INLINE, 0x537F}, {0x2F832, 0, 1 | DECOMP_INLINE, 0x537F}, {0x2F833, 0, 1 | DECOMP_INLINE, 0x537F}, - {0x2F834, 0, 1, 4998}, + {0x2F834, 0, 1, 5038}, {0x2F835, 0, 1 | DECOMP_INLINE, 0x7070}, {0x2F836, 0, 1 | DECOMP_INLINE, 0x53CA}, {0x2F837, 0, 1 | DECOMP_INLINE, 0x53DF}, - {0x2F838, 0, 1, 4999}, + {0x2F838, 0, 1, 5039}, {0x2F839, 0, 1 | DECOMP_INLINE, 0x53EB}, {0x2F83A, 0, 1 | DECOMP_INLINE, 0x53F1}, {0x2F83B, 0, 1 | DECOMP_INLINE, 0x5406}, @@ -6360,15 +6428,15 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F856, 0, 1 | DECOMP_INLINE, 0x5832}, {0x2F857, 0, 1 | DECOMP_INLINE, 0x5831}, {0x2F858, 0, 1 | DECOMP_INLINE, 0x58AC}, - {0x2F859, 0, 1, 5000}, + {0x2F859, 0, 1, 5040}, {0x2F85A, 0, 1 | DECOMP_INLINE, 0x58F2}, {0x2F85B, 0, 1 | DECOMP_INLINE, 0x58F7}, {0x2F85C, 0, 1 | DECOMP_INLINE, 0x5906}, {0x2F85D, 0, 1 | DECOMP_INLINE, 0x591A}, {0x2F85E, 0, 1 | DECOMP_INLINE, 0x5922}, {0x2F85F, 0, 1 | DECOMP_INLINE, 0x5962}, - {0x2F860, 0, 1, 5001}, - {0x2F861, 0, 1, 5002}, + {0x2F860, 0, 1, 5041}, + {0x2F861, 0, 1, 5042}, {0x2F862, 0, 1 | DECOMP_INLINE, 0x59EC}, {0x2F863, 0, 1 | DECOMP_INLINE, 0x5A1B}, {0x2F864, 0, 1 | DECOMP_INLINE, 0x5A27}, @@ -6379,12 +6447,12 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F869, 0, 1 | DECOMP_INLINE, 0x5B08}, {0x2F86A, 0, 1 | DECOMP_INLINE, 0x5B3E}, {0x2F86B, 0, 1 | DECOMP_INLINE, 0x5B3E}, - {0x2F86C, 0, 1, 5003}, + {0x2F86C, 0, 1, 5043}, {0x2F86D, 0, 1 | DECOMP_INLINE, 0x5BC3}, {0x2F86E, 0, 1 | DECOMP_INLINE, 0x5BD8}, {0x2F86F, 0, 1 | DECOMP_INLINE, 0x5BE7}, {0x2F870, 0, 1 | DECOMP_INLINE, 0x5BF3}, - {0x2F871, 0, 1, 5004}, + {0x2F871, 0, 1, 5044}, {0x2F872, 0, 1 | DECOMP_INLINE, 0x5BFF}, {0x2F873, 0, 1 | DECOMP_INLINE, 0x5C06}, {0x2F874, 0, 1 | DECOMP_INLINE, 0x5F53}, @@ -6394,9 +6462,9 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F878, 0, 1 | DECOMP_INLINE, 0x5C6E}, {0x2F879, 0, 1 | DECOMP_INLINE, 0x5CC0}, {0x2F87A, 0, 1 | DECOMP_INLINE, 0x5C8D}, - {0x2F87B, 0, 1, 5005}, + {0x2F87B, 0, 1, 5045}, {0x2F87C, 0, 1 | DECOMP_INLINE, 0x5D43}, - {0x2F87D, 0, 1, 5006}, + {0x2F87D, 0, 1, 5046}, {0x2F87E, 0, 1 | DECOMP_INLINE, 0x5D6E}, {0x2F87F, 0, 1 | DECOMP_INLINE, 0x5D6B}, {0x2F880, 0, 1 | DECOMP_INLINE, 0x5D7C}, @@ -6408,22 +6476,22 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F886, 0, 1 | DECOMP_INLINE, 0x5E3D}, {0x2F887, 0, 1 | DECOMP_INLINE, 0x5E69}, {0x2F888, 0, 1 | DECOMP_INLINE, 0x3862}, - {0x2F889, 0, 1, 5007}, + {0x2F889, 0, 1, 5047}, {0x2F88A, 0, 1 | DECOMP_INLINE, 0x387C}, {0x2F88B, 0, 1 | DECOMP_INLINE, 0x5EB0}, {0x2F88C, 0, 1 | DECOMP_INLINE, 0x5EB3}, {0x2F88D, 0, 1 | DECOMP_INLINE, 0x5EB6}, {0x2F88E, 0, 1 | DECOMP_INLINE, 0x5ECA}, - {0x2F88F, 0, 1, 5008}, + {0x2F88F, 0, 1, 5048}, {0x2F890, 0, 1 | DECOMP_INLINE, 0x5EFE}, - {0x2F891, 0, 1, 5009}, - {0x2F892, 0, 1, 5010}, + {0x2F891, 0, 1, 5049}, + {0x2F892, 0, 1, 5050}, {0x2F893, 0, 1 | DECOMP_INLINE, 0x8201}, {0x2F894, 0, 1 | DECOMP_INLINE, 0x5F22}, {0x2F895, 0, 1 | DECOMP_INLINE, 0x5F22}, {0x2F896, 0, 1 | DECOMP_INLINE, 0x38C7}, - {0x2F897, 0, 1, 5011}, - {0x2F898, 0, 1, 5012}, + {0x2F897, 0, 1, 5051}, + {0x2F898, 0, 1, 5052}, {0x2F899, 0, 1 | DECOMP_INLINE, 0x5F62}, {0x2F89A, 0, 1 | DECOMP_INLINE, 0x5F6B}, {0x2F89B, 0, 1 | DECOMP_INLINE, 0x38E3}, @@ -6435,7 +6503,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F8A1, 0, 1 | DECOMP_INLINE, 0x393A}, {0x2F8A2, 0, 1 | DECOMP_INLINE, 0x391C}, {0x2F8A3, 0, 1 | DECOMP_INLINE, 0x6094}, - {0x2F8A4, 0, 1, 5013}, + {0x2F8A4, 0, 1, 5053}, {0x2F8A5, 0, 1 | DECOMP_INLINE, 0x60C7}, {0x2F8A6, 0, 1 | DECOMP_INLINE, 0x6148}, {0x2F8A7, 0, 1 | DECOMP_INLINE, 0x614C}, @@ -6455,13 +6523,13 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F8B5, 0, 1 | DECOMP_INLINE, 0x62B1}, {0x2F8B6, 0, 1 | DECOMP_INLINE, 0x62D4}, {0x2F8B7, 0, 1 | DECOMP_INLINE, 0x6350}, - {0x2F8B8, 0, 1, 5014}, + {0x2F8B8, 0, 1, 5054}, {0x2F8B9, 0, 1 | DECOMP_INLINE, 0x633D}, {0x2F8BA, 0, 1 | DECOMP_INLINE, 0x62FC}, {0x2F8BB, 0, 1 | DECOMP_INLINE, 0x6368}, {0x2F8BC, 0, 1 | DECOMP_INLINE, 0x6383}, {0x2F8BD, 0, 1 | DECOMP_INLINE, 0x63E4}, - {0x2F8BE, 0, 1, 5015}, + {0x2F8BE, 0, 1, 5055}, {0x2F8BF, 0, 1 | DECOMP_INLINE, 0x6422}, {0x2F8C0, 0, 1 | DECOMP_INLINE, 0x63C5}, {0x2F8C1, 0, 1 | DECOMP_INLINE, 0x63A9}, @@ -6473,7 +6541,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F8C7, 0, 1 | DECOMP_INLINE, 0x3A6C}, {0x2F8C8, 0, 1 | DECOMP_INLINE, 0x654F}, {0x2F8C9, 0, 1 | DECOMP_INLINE, 0x656C}, - {0x2F8CA, 0, 1, 5016}, + {0x2F8CA, 0, 1, 5056}, {0x2F8CB, 0, 1 | DECOMP_INLINE, 0x65E3}, {0x2F8CC, 0, 1 | DECOMP_INLINE, 0x66F8}, {0x2F8CD, 0, 1 | DECOMP_INLINE, 0x6649}, @@ -6492,13 +6560,13 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F8DA, 0, 1 | DECOMP_INLINE, 0x6721}, {0x2F8DB, 0, 1 | DECOMP_INLINE, 0x675E}, {0x2F8DC, 0, 1 | DECOMP_INLINE, 0x6753}, - {0x2F8DD, 0, 1, 5017}, + {0x2F8DD, 0, 1, 5057}, {0x2F8DE, 0, 1 | DECOMP_INLINE, 0x3B49}, {0x2F8DF, 0, 1 | DECOMP_INLINE, 0x67FA}, {0x2F8E0, 0, 1 | DECOMP_INLINE, 0x6785}, {0x2F8E1, 0, 1 | DECOMP_INLINE, 0x6852}, {0x2F8E2, 0, 1 | DECOMP_INLINE, 0x6885}, - {0x2F8E3, 0, 1, 5018}, + {0x2F8E3, 0, 1, 5058}, {0x2F8E4, 0, 1 | DECOMP_INLINE, 0x688E}, {0x2F8E5, 0, 1 | DECOMP_INLINE, 0x681F}, {0x2F8E6, 0, 1 | DECOMP_INLINE, 0x6914}, @@ -6507,22 +6575,22 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F8E9, 0, 1 | DECOMP_INLINE, 0x69A3}, {0x2F8EA, 0, 1 | DECOMP_INLINE, 0x69EA}, {0x2F8EB, 0, 1 | DECOMP_INLINE, 0x6AA8}, - {0x2F8EC, 0, 1, 5019}, + {0x2F8EC, 0, 1, 5059}, {0x2F8ED, 0, 1 | DECOMP_INLINE, 0x6ADB}, {0x2F8EE, 0, 1 | DECOMP_INLINE, 0x3C18}, {0x2F8EF, 0, 1 | DECOMP_INLINE, 0x6B21}, - {0x2F8F0, 0, 1, 5020}, + {0x2F8F0, 0, 1, 5060}, {0x2F8F1, 0, 1 | DECOMP_INLINE, 0x6B54}, {0x2F8F2, 0, 1 | DECOMP_INLINE, 0x3C4E}, {0x2F8F3, 0, 1 | DECOMP_INLINE, 0x6B72}, {0x2F8F4, 0, 1 | DECOMP_INLINE, 0x6B9F}, {0x2F8F5, 0, 1 | DECOMP_INLINE, 0x6BBA}, {0x2F8F6, 0, 1 | DECOMP_INLINE, 0x6BBB}, - {0x2F8F7, 0, 1, 5021}, - {0x2F8F8, 0, 1, 5022}, - {0x2F8F9, 0, 1, 5023}, + {0x2F8F7, 0, 1, 5061}, + {0x2F8F8, 0, 1, 5062}, + {0x2F8F9, 0, 1, 5063}, {0x2F8FA, 0, 1 | DECOMP_INLINE, 0x6C4E}, - {0x2F8FB, 0, 1, 5024}, + {0x2F8FB, 0, 1, 5064}, {0x2F8FC, 0, 1 | DECOMP_INLINE, 0x6CBF}, {0x2F8FD, 0, 1 | DECOMP_INLINE, 0x6CCD}, {0x2F8FE, 0, 1 | DECOMP_INLINE, 0x6C67}, @@ -6533,18 +6601,18 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F903, 0, 1 | DECOMP_INLINE, 0x6D69}, {0x2F904, 0, 1 | DECOMP_INLINE, 0x6D78}, {0x2F905, 0, 1 | DECOMP_INLINE, 0x6D85}, - {0x2F906, 0, 1, 5025}, + {0x2F906, 0, 1, 5065}, {0x2F907, 0, 1 | DECOMP_INLINE, 0x6D34}, {0x2F908, 0, 1 | DECOMP_INLINE, 0x6E2F}, {0x2F909, 0, 1 | DECOMP_INLINE, 0x6E6E}, {0x2F90A, 0, 1 | DECOMP_INLINE, 0x3D33}, {0x2F90B, 0, 1 | DECOMP_INLINE, 0x6ECB}, {0x2F90C, 0, 1 | DECOMP_INLINE, 0x6EC7}, - {0x2F90D, 0, 1, 5026}, + {0x2F90D, 0, 1, 5066}, {0x2F90E, 0, 1 | DECOMP_INLINE, 0x6DF9}, {0x2F90F, 0, 1 | DECOMP_INLINE, 0x6F6E}, - {0x2F910, 0, 1, 5027}, - {0x2F911, 0, 1, 5028}, + {0x2F910, 0, 1, 5067}, + {0x2F911, 0, 1, 5068}, {0x2F912, 0, 1 | DECOMP_INLINE, 0x6FC6}, {0x2F913, 0, 1 | DECOMP_INLINE, 0x7039}, {0x2F914, 0, 1 | DECOMP_INLINE, 0x701E}, @@ -6554,19 +6622,19 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F918, 0, 1 | DECOMP_INLINE, 0x707D}, {0x2F919, 0, 1 | DECOMP_INLINE, 0x7077}, {0x2F91A, 0, 1 | DECOMP_INLINE, 0x70AD}, - {0x2F91B, 0, 1, 5029}, + {0x2F91B, 0, 1, 5069}, {0x2F91C, 0, 1 | DECOMP_INLINE, 0x7145}, - {0x2F91D, 0, 1, 5030}, + {0x2F91D, 0, 1, 5070}, {0x2F91E, 0, 1 | DECOMP_INLINE, 0x719C}, - {0x2F91F, 0, 1, 5031}, + {0x2F91F, 0, 1, 5071}, {0x2F920, 0, 1 | DECOMP_INLINE, 0x7228}, {0x2F921, 0, 1 | DECOMP_INLINE, 0x7235}, {0x2F922, 0, 1 | DECOMP_INLINE, 0x7250}, - {0x2F923, 0, 1, 5032}, + {0x2F923, 0, 1, 5072}, {0x2F924, 0, 1 | DECOMP_INLINE, 0x7280}, {0x2F925, 0, 1 | DECOMP_INLINE, 0x7295}, - {0x2F926, 0, 1, 5033}, - {0x2F927, 0, 1, 5034}, + {0x2F926, 0, 1, 5073}, + {0x2F927, 0, 1, 5074}, {0x2F928, 0, 1 | DECOMP_INLINE, 0x737A}, {0x2F929, 0, 1 | DECOMP_INLINE, 0x738B}, {0x2F92A, 0, 1 | DECOMP_INLINE, 0x3EAC}, @@ -6580,22 +6648,22 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F932, 0, 1 | DECOMP_INLINE, 0x74CA}, {0x2F933, 0, 1 | DECOMP_INLINE, 0x3F1B}, {0x2F934, 0, 1 | DECOMP_INLINE, 0x7524}, - {0x2F935, 0, 1, 5035}, + {0x2F935, 0, 1, 5075}, {0x2F936, 0, 1 | DECOMP_INLINE, 0x753E}, - {0x2F937, 0, 1, 5036}, + {0x2F937, 0, 1, 5076}, {0x2F938, 0, 1 | DECOMP_INLINE, 0x7570}, - {0x2F939, 0, 1, 5037}, + {0x2F939, 0, 1, 5077}, {0x2F93A, 0, 1 | DECOMP_INLINE, 0x7610}, - {0x2F93B, 0, 1, 5038}, - {0x2F93C, 0, 1, 5039}, - {0x2F93D, 0, 1, 5040}, + {0x2F93B, 0, 1, 5078}, + {0x2F93C, 0, 1, 5079}, + {0x2F93D, 0, 1, 5080}, {0x2F93E, 0, 1 | DECOMP_INLINE, 0x3FFC}, {0x2F93F, 0, 1 | DECOMP_INLINE, 0x4008}, {0x2F940, 0, 1 | DECOMP_INLINE, 0x76F4}, - {0x2F941, 0, 1, 5041}, - {0x2F942, 0, 1, 5042}, - {0x2F943, 0, 1, 5043}, - {0x2F944, 0, 1, 5044}, + {0x2F941, 0, 1, 5081}, + {0x2F942, 0, 1, 5082}, + {0x2F943, 0, 1, 5083}, + {0x2F944, 0, 1, 5084}, {0x2F945, 0, 1 | DECOMP_INLINE, 0x771E}, {0x2F946, 0, 1 | DECOMP_INLINE, 0x771F}, {0x2F947, 0, 1 | DECOMP_INLINE, 0x771F}, @@ -6604,68 +6672,68 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F94A, 0, 1 | DECOMP_INLINE, 0x778B}, {0x2F94B, 0, 1 | DECOMP_INLINE, 0x4046}, {0x2F94C, 0, 1 | DECOMP_INLINE, 0x4096}, - {0x2F94D, 0, 1, 5045}, + {0x2F94D, 0, 1, 5085}, {0x2F94E, 0, 1 | DECOMP_INLINE, 0x784E}, {0x2F94F, 0, 1 | DECOMP_INLINE, 0x788C}, {0x2F950, 0, 1 | DECOMP_INLINE, 0x78CC}, {0x2F951, 0, 1 | DECOMP_INLINE, 0x40E3}, - {0x2F952, 0, 1, 5046}, + {0x2F952, 0, 1, 5086}, {0x2F953, 0, 1 | DECOMP_INLINE, 0x7956}, - {0x2F954, 0, 1, 5047}, - {0x2F955, 0, 1, 5048}, + {0x2F954, 0, 1, 5087}, + {0x2F955, 0, 1, 5088}, {0x2F956, 0, 1 | DECOMP_INLINE, 0x798F}, {0x2F957, 0, 1 | DECOMP_INLINE, 0x79EB}, {0x2F958, 0, 1 | DECOMP_INLINE, 0x412F}, {0x2F959, 0, 1 | DECOMP_INLINE, 0x7A40}, {0x2F95A, 0, 1 | DECOMP_INLINE, 0x7A4A}, {0x2F95B, 0, 1 | DECOMP_INLINE, 0x7A4F}, - {0x2F95C, 0, 1, 5049}, - {0x2F95D, 0, 1, 5050}, - {0x2F95E, 0, 1, 5051}, + {0x2F95C, 0, 1, 5089}, + {0x2F95D, 0, 1, 5090}, + {0x2F95E, 0, 1, 5091}, {0x2F95F, 0, 1 | DECOMP_INLINE, 0x7AEE}, {0x2F960, 0, 1 | DECOMP_INLINE, 0x4202}, - {0x2F961, 0, 1, 5052}, + {0x2F961, 0, 1, 5092}, {0x2F962, 0, 1 | DECOMP_INLINE, 0x7BC6}, {0x2F963, 0, 1 | DECOMP_INLINE, 0x7BC9}, {0x2F964, 0, 1 | DECOMP_INLINE, 0x4227}, - {0x2F965, 0, 1, 5053}, + {0x2F965, 0, 1, 5093}, {0x2F966, 0, 1 | DECOMP_INLINE, 0x7CD2}, {0x2F967, 0, 1 | DECOMP_INLINE, 0x42A0}, {0x2F968, 0, 1 | DECOMP_INLINE, 0x7CE8}, {0x2F969, 0, 1 | DECOMP_INLINE, 0x7CE3}, {0x2F96A, 0, 1 | DECOMP_INLINE, 0x7D00}, - {0x2F96B, 0, 1, 5054}, + {0x2F96B, 0, 1, 5094}, {0x2F96C, 0, 1 | DECOMP_INLINE, 0x7D63}, {0x2F96D, 0, 1 | DECOMP_INLINE, 0x4301}, {0x2F96E, 0, 1 | DECOMP_INLINE, 0x7DC7}, {0x2F96F, 0, 1 | DECOMP_INLINE, 0x7E02}, {0x2F970, 0, 1 | DECOMP_INLINE, 0x7E45}, {0x2F971, 0, 1 | DECOMP_INLINE, 0x4334}, - {0x2F972, 0, 1, 5055}, - {0x2F973, 0, 1, 5056}, + {0x2F972, 0, 1, 5095}, + {0x2F973, 0, 1, 5096}, {0x2F974, 0, 1 | DECOMP_INLINE, 0x4359}, - {0x2F975, 0, 1, 5057}, + {0x2F975, 0, 1, 5097}, {0x2F976, 0, 1 | DECOMP_INLINE, 0x7F7A}, - {0x2F977, 0, 1, 5058}, + {0x2F977, 0, 1, 5098}, {0x2F978, 0, 1 | DECOMP_INLINE, 0x7F95}, {0x2F979, 0, 1 | DECOMP_INLINE, 0x7FFA}, {0x2F97A, 0, 1 | DECOMP_INLINE, 0x8005}, - {0x2F97B, 0, 1, 5059}, - {0x2F97C, 0, 1, 5060}, + {0x2F97B, 0, 1, 5099}, + {0x2F97C, 0, 1, 5100}, {0x2F97D, 0, 1 | DECOMP_INLINE, 0x8060}, - {0x2F97E, 0, 1, 5061}, + {0x2F97E, 0, 1, 5101}, {0x2F97F, 0, 1 | DECOMP_INLINE, 0x8070}, - {0x2F980, 0, 1, 5062}, + {0x2F980, 0, 1, 5102}, {0x2F981, 0, 1 | DECOMP_INLINE, 0x43D5}, {0x2F982, 0, 1 | DECOMP_INLINE, 0x80B2}, {0x2F983, 0, 1 | DECOMP_INLINE, 0x8103}, {0x2F984, 0, 1 | DECOMP_INLINE, 0x440B}, {0x2F985, 0, 1 | DECOMP_INLINE, 0x813E}, {0x2F986, 0, 1 | DECOMP_INLINE, 0x5AB5}, - {0x2F987, 0, 1, 5063}, - {0x2F988, 0, 1, 5064}, - {0x2F989, 0, 1, 5065}, - {0x2F98A, 0, 1, 5066}, + {0x2F987, 0, 1, 5103}, + {0x2F988, 0, 1, 5104}, + {0x2F989, 0, 1, 5105}, + {0x2F98A, 0, 1, 5106}, {0x2F98B, 0, 1 | DECOMP_INLINE, 0x8201}, {0x2F98C, 0, 1 | DECOMP_INLINE, 0x8204}, {0x2F98D, 0, 1 | DECOMP_INLINE, 0x8F9E}, @@ -6678,7 +6746,7 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F994, 0, 1 | DECOMP_INLINE, 0x82B3}, {0x2F995, 0, 1 | DECOMP_INLINE, 0x82BD}, {0x2F996, 0, 1 | DECOMP_INLINE, 0x82E6}, - {0x2F997, 0, 1, 5067}, + {0x2F997, 0, 1, 5107}, {0x2F998, 0, 1 | DECOMP_INLINE, 0x82E5}, {0x2F999, 0, 1 | DECOMP_INLINE, 0x831D}, {0x2F99A, 0, 1 | DECOMP_INLINE, 0x8363}, @@ -6691,20 +6759,20 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F9A1, 0, 1 | DECOMP_INLINE, 0x83CA}, {0x2F9A2, 0, 1 | DECOMP_INLINE, 0x83CC}, {0x2F9A3, 0, 1 | DECOMP_INLINE, 0x83DC}, - {0x2F9A4, 0, 1, 5068}, - {0x2F9A5, 0, 1, 5069}, - {0x2F9A6, 0, 1, 5070}, + {0x2F9A4, 0, 1, 5108}, + {0x2F9A5, 0, 1, 5109}, + {0x2F9A6, 0, 1, 5110}, {0x2F9A7, 0, 1 | DECOMP_INLINE, 0x452B}, {0x2F9A8, 0, 1 | DECOMP_INLINE, 0x84F1}, {0x2F9A9, 0, 1 | DECOMP_INLINE, 0x84F3}, {0x2F9AA, 0, 1 | DECOMP_INLINE, 0x8516}, - {0x2F9AB, 0, 1, 5071}, + {0x2F9AB, 0, 1, 5111}, {0x2F9AC, 0, 1 | DECOMP_INLINE, 0x8564}, - {0x2F9AD, 0, 1, 5072}, + {0x2F9AD, 0, 1, 5112}, {0x2F9AE, 0, 1 | DECOMP_INLINE, 0x455D}, {0x2F9AF, 0, 1 | DECOMP_INLINE, 0x4561}, - {0x2F9B0, 0, 1, 5073}, - {0x2F9B1, 0, 1, 5074}, + {0x2F9B0, 0, 1, 5113}, + {0x2F9B1, 0, 1, 5114}, {0x2F9B2, 0, 1 | DECOMP_INLINE, 0x456B}, {0x2F9B3, 0, 1 | DECOMP_INLINE, 0x8650}, {0x2F9B4, 0, 1 | DECOMP_INLINE, 0x865C}, @@ -6724,39 +6792,39 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F9C2, 0, 1 | DECOMP_INLINE, 0x45F9}, {0x2F9C3, 0, 1 | DECOMP_INLINE, 0x8860}, {0x2F9C4, 0, 1 | DECOMP_INLINE, 0x8863}, - {0x2F9C5, 0, 1, 5075}, + {0x2F9C5, 0, 1, 5115}, {0x2F9C6, 0, 1 | DECOMP_INLINE, 0x88D7}, {0x2F9C7, 0, 1 | DECOMP_INLINE, 0x88DE}, {0x2F9C8, 0, 1 | DECOMP_INLINE, 0x4635}, {0x2F9C9, 0, 1 | DECOMP_INLINE, 0x88FA}, {0x2F9CA, 0, 1 | DECOMP_INLINE, 0x34BB}, - {0x2F9CB, 0, 1, 5076}, - {0x2F9CC, 0, 1, 5077}, + {0x2F9CB, 0, 1, 5116}, + {0x2F9CC, 0, 1, 5117}, {0x2F9CD, 0, 1 | DECOMP_INLINE, 0x46BE}, {0x2F9CE, 0, 1 | DECOMP_INLINE, 0x46C7}, {0x2F9CF, 0, 1 | DECOMP_INLINE, 0x8AA0}, {0x2F9D0, 0, 1 | DECOMP_INLINE, 0x8AED}, {0x2F9D1, 0, 1 | DECOMP_INLINE, 0x8B8A}, {0x2F9D2, 0, 1 | DECOMP_INLINE, 0x8C55}, - {0x2F9D3, 0, 1, 5078}, + {0x2F9D3, 0, 1, 5118}, {0x2F9D4, 0, 1 | DECOMP_INLINE, 0x8CAB}, {0x2F9D5, 0, 1 | DECOMP_INLINE, 0x8CC1}, {0x2F9D6, 0, 1 | DECOMP_INLINE, 0x8D1B}, {0x2F9D7, 0, 1 | DECOMP_INLINE, 0x8D77}, - {0x2F9D8, 0, 1, 5079}, - {0x2F9D9, 0, 1, 5080}, + {0x2F9D8, 0, 1, 5119}, + {0x2F9D9, 0, 1, 5120}, {0x2F9DA, 0, 1 | DECOMP_INLINE, 0x8DCB}, {0x2F9DB, 0, 1 | DECOMP_INLINE, 0x8DBC}, {0x2F9DC, 0, 1 | DECOMP_INLINE, 0x8DF0}, - {0x2F9DD, 0, 1, 5081}, + {0x2F9DD, 0, 1, 5121}, {0x2F9DE, 0, 1 | DECOMP_INLINE, 0x8ED4}, {0x2F9DF, 0, 1 | DECOMP_INLINE, 0x8F38}, - {0x2F9E0, 0, 1, 5082}, - {0x2F9E1, 0, 1, 5083}, + {0x2F9E0, 0, 1, 5122}, + {0x2F9E1, 0, 1, 5123}, {0x2F9E2, 0, 1 | DECOMP_INLINE, 0x9094}, {0x2F9E3, 0, 1 | DECOMP_INLINE, 0x90F1}, {0x2F9E4, 0, 1 | DECOMP_INLINE, 0x9111}, - {0x2F9E5, 0, 1, 5084}, + {0x2F9E5, 0, 1, 5124}, {0x2F9E6, 0, 1 | DECOMP_INLINE, 0x911B}, {0x2F9E7, 0, 1 | DECOMP_INLINE, 0x9238}, {0x2F9E8, 0, 1 | DECOMP_INLINE, 0x92D7}, @@ -6764,27 +6832,27 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2F9EA, 0, 1 | DECOMP_INLINE, 0x927C}, {0x2F9EB, 0, 1 | DECOMP_INLINE, 0x93F9}, {0x2F9EC, 0, 1 | DECOMP_INLINE, 0x9415}, - {0x2F9ED, 0, 1, 5085}, + {0x2F9ED, 0, 1, 5125}, {0x2F9EE, 0, 1 | DECOMP_INLINE, 0x958B}, {0x2F9EF, 0, 1 | DECOMP_INLINE, 0x4995}, {0x2F9F0, 0, 1 | DECOMP_INLINE, 0x95B7}, - {0x2F9F1, 0, 1, 5086}, + {0x2F9F1, 0, 1, 5126}, {0x2F9F2, 0, 1 | DECOMP_INLINE, 0x49E6}, {0x2F9F3, 0, 1 | DECOMP_INLINE, 0x96C3}, {0x2F9F4, 0, 1 | DECOMP_INLINE, 0x5DB2}, {0x2F9F5, 0, 1 | DECOMP_INLINE, 0x9723}, - {0x2F9F6, 0, 1, 5087}, - {0x2F9F7, 0, 1, 5088}, + {0x2F9F6, 0, 1, 5127}, + {0x2F9F7, 0, 1, 5128}, {0x2F9F8, 0, 1 | DECOMP_INLINE, 0x4A6E}, {0x2F9F9, 0, 1 | DECOMP_INLINE, 0x4A76}, {0x2F9FA, 0, 1 | DECOMP_INLINE, 0x97E0}, - {0x2F9FB, 0, 1, 5089}, + {0x2F9FB, 0, 1, 5129}, {0x2F9FC, 0, 1 | DECOMP_INLINE, 0x4AB2}, - {0x2F9FD, 0, 1, 5090}, + {0x2F9FD, 0, 1, 5130}, {0x2F9FE, 0, 1 | DECOMP_INLINE, 0x980B}, {0x2F9FF, 0, 1 | DECOMP_INLINE, 0x980B}, {0x2FA00, 0, 1 | DECOMP_INLINE, 0x9829}, - {0x2FA01, 0, 1, 5091}, + {0x2FA01, 0, 1, 5131}, {0x2FA02, 0, 1 | DECOMP_INLINE, 0x98E2}, {0x2FA03, 0, 1 | DECOMP_INLINE, 0x4B33}, {0x2FA04, 0, 1 | DECOMP_INLINE, 0x9929}, @@ -6792,18 +6860,18 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2FA06, 0, 1 | DECOMP_INLINE, 0x99C2}, {0x2FA07, 0, 1 | DECOMP_INLINE, 0x99FE}, {0x2FA08, 0, 1 | DECOMP_INLINE, 0x4BCE}, - {0x2FA09, 0, 1, 5092}, + {0x2FA09, 0, 1, 5132}, {0x2FA0A, 0, 1 | DECOMP_INLINE, 0x9B12}, {0x2FA0B, 0, 1 | DECOMP_INLINE, 0x9C40}, {0x2FA0C, 0, 1 | DECOMP_INLINE, 0x9CFD}, {0x2FA0D, 0, 1 | DECOMP_INLINE, 0x4CCE}, {0x2FA0E, 0, 1 | DECOMP_INLINE, 0x4CED}, {0x2FA0F, 0, 1 | DECOMP_INLINE, 0x9D67}, - {0x2FA10, 0, 1, 5093}, + {0x2FA10, 0, 1, 5133}, {0x2FA11, 0, 1 | DECOMP_INLINE, 0x4CF8}, - {0x2FA12, 0, 1, 5094}, - {0x2FA13, 0, 1, 5095}, - {0x2FA14, 0, 1, 5096}, + {0x2FA12, 0, 1, 5134}, + {0x2FA13, 0, 1, 5135}, + {0x2FA14, 0, 1, 5136}, {0x2FA15, 0, 1 | DECOMP_INLINE, 0x9EBB}, {0x2FA16, 0, 1 | DECOMP_INLINE, 0x4D56}, {0x2FA17, 0, 1 | DECOMP_INLINE, 0x9EF9}, @@ -6812,12 +6880,12 @@ static const pg_unicode_decomposition UnicodeDecompMain[6775] = {0x2FA1A, 0, 1 | DECOMP_INLINE, 0x9F0F}, {0x2FA1B, 0, 1 | DECOMP_INLINE, 0x9F16}, {0x2FA1C, 0, 1 | DECOMP_INLINE, 0x9F3B}, - {0x2FA1D, 0, 1, 5097} + {0x2FA1D, 0, 1, 5137} }; /* codepoints array */ -static const uint32 UnicodeDecomp_codepoints[5098] = +static const uint32 UnicodeDecomp_codepoints[5138] = { /* 0 */ 0x0020, 0x0308, /* 2 */ 0x0020, 0x0304, @@ -8913,202 +8981,222 @@ static const uint32 UnicodeDecomp_codepoints[5098] = /* 4770 */ 0x0644, 0x0625, /* 4772 */ 0x0644, 0x0627, /* 4774 */ 0x0644, 0x0627, - /* 4776 */ 0x1DF04, - /* 4777 */ 0x1DF05, - /* 4778 */ 0x1DF06, - /* 4779 */ 0x1DF08, - /* 4780 */ 0x1DF0A, - /* 4781 */ 0x1DF1E, - /* 4782 */ 0x11099, 0x110BA, - /* 4784 */ 0x1109B, 0x110BA, - /* 4786 */ 0x110A5, 0x110BA, - /* 4788 */ 0x11131, 0x11127, - /* 4790 */ 0x11132, 0x11127, - /* 4792 */ 0x11347, 0x1133E, - /* 4794 */ 0x11347, 0x11357, - /* 4796 */ 0x114B9, 0x114BA, - /* 4798 */ 0x114B9, 0x114B0, - /* 4800 */ 0x114B9, 0x114BD, - /* 4802 */ 0x115B8, 0x115AF, - /* 4804 */ 0x115B9, 0x115AF, - /* 4806 */ 0x11935, 0x11930, - /* 4808 */ 0x1D157, 0x1D165, - /* 4810 */ 0x1D158, 0x1D165, - /* 4812 */ 0x1D15F, 0x1D16E, - /* 4814 */ 0x1D15F, 0x1D16F, - /* 4816 */ 0x1D15F, 0x1D170, - /* 4818 */ 0x1D15F, 0x1D171, - /* 4820 */ 0x1D15F, 0x1D172, - /* 4822 */ 0x1D1B9, 0x1D165, - /* 4824 */ 0x1D1BA, 0x1D165, - /* 4826 */ 0x1D1BB, 0x1D16E, - /* 4828 */ 0x1D1BC, 0x1D16E, - /* 4830 */ 0x1D1BB, 0x1D16F, - /* 4832 */ 0x1D1BC, 0x1D16F, - /* 4834 */ 0x0030, 0x002E, - /* 4836 */ 0x0030, 0x002C, - /* 4838 */ 0x0031, 0x002C, - /* 4840 */ 0x0032, 0x002C, - /* 4842 */ 0x0033, 0x002C, - /* 4844 */ 0x0034, 0x002C, - /* 4846 */ 0x0035, 0x002C, - /* 4848 */ 0x0036, 0x002C, - /* 4850 */ 0x0037, 0x002C, - /* 4852 */ 0x0038, 0x002C, - /* 4854 */ 0x0039, 0x002C, - /* 4856 */ 0x0028, 0x0041, 0x0029, - /* 4859 */ 0x0028, 0x0042, 0x0029, - /* 4862 */ 0x0028, 0x0043, 0x0029, - /* 4865 */ 0x0028, 0x0044, 0x0029, - /* 4868 */ 0x0028, 0x0045, 0x0029, - /* 4871 */ 0x0028, 0x0046, 0x0029, - /* 4874 */ 0x0028, 0x0047, 0x0029, - /* 4877 */ 0x0028, 0x0048, 0x0029, - /* 4880 */ 0x0028, 0x0049, 0x0029, - /* 4883 */ 0x0028, 0x004A, 0x0029, - /* 4886 */ 0x0028, 0x004B, 0x0029, - /* 4889 */ 0x0028, 0x004C, 0x0029, - /* 4892 */ 0x0028, 0x004D, 0x0029, - /* 4895 */ 0x0028, 0x004E, 0x0029, - /* 4898 */ 0x0028, 0x004F, 0x0029, - /* 4901 */ 0x0028, 0x0050, 0x0029, - /* 4904 */ 0x0028, 0x0051, 0x0029, - /* 4907 */ 0x0028, 0x0052, 0x0029, - /* 4910 */ 0x0028, 0x0053, 0x0029, - /* 4913 */ 0x0028, 0x0054, 0x0029, - /* 4916 */ 0x0028, 0x0055, 0x0029, - /* 4919 */ 0x0028, 0x0056, 0x0029, - /* 4922 */ 0x0028, 0x0057, 0x0029, - /* 4925 */ 0x0028, 0x0058, 0x0029, - /* 4928 */ 0x0028, 0x0059, 0x0029, - /* 4931 */ 0x0028, 0x005A, 0x0029, - /* 4934 */ 0x3014, 0x0053, 0x3015, - /* 4937 */ 0x0043, 0x0044, - /* 4939 */ 0x0057, 0x005A, - /* 4941 */ 0x0048, 0x0056, - /* 4943 */ 0x004D, 0x0056, - /* 4945 */ 0x0053, 0x0044, - /* 4947 */ 0x0053, 0x0053, - /* 4949 */ 0x0050, 0x0050, 0x0056, - /* 4952 */ 0x0057, 0x0043, - /* 4954 */ 0x004D, 0x0043, - /* 4956 */ 0x004D, 0x0044, - /* 4958 */ 0x004D, 0x0052, - /* 4960 */ 0x0044, 0x004A, - /* 4962 */ 0x307B, 0x304B, - /* 4964 */ 0x30B3, 0x30B3, - /* 4966 */ 0x3014, 0x672C, 0x3015, - /* 4969 */ 0x3014, 0x4E09, 0x3015, - /* 4972 */ 0x3014, 0x4E8C, 0x3015, - /* 4975 */ 0x3014, 0x5B89, 0x3015, - /* 4978 */ 0x3014, 0x70B9, 0x3015, - /* 4981 */ 0x3014, 0x6253, 0x3015, - /* 4984 */ 0x3014, 0x76D7, 0x3015, - /* 4987 */ 0x3014, 0x52DD, 0x3015, - /* 4990 */ 0x3014, 0x6557, 0x3015, - /* 4993 */ 0x20122, - /* 4994 */ 0x2063A, - /* 4995 */ 0x2051C, - /* 4996 */ 0x2054B, - /* 4997 */ 0x291DF, - /* 4998 */ 0x20A2C, - /* 4999 */ 0x20B63, - /* 5000 */ 0x214E4, - /* 5001 */ 0x216A8, - /* 5002 */ 0x216EA, - /* 5003 */ 0x219C8, - /* 5004 */ 0x21B18, - /* 5005 */ 0x21DE4, - /* 5006 */ 0x21DE6, - /* 5007 */ 0x22183, - /* 5008 */ 0x2A392, - /* 5009 */ 0x22331, - /* 5010 */ 0x22331, - /* 5011 */ 0x232B8, - /* 5012 */ 0x261DA, - /* 5013 */ 0x226D4, - /* 5014 */ 0x22B0C, - /* 5015 */ 0x22BF1, - /* 5016 */ 0x2300A, - /* 5017 */ 0x233C3, - /* 5018 */ 0x2346D, - /* 5019 */ 0x236A3, - /* 5020 */ 0x238A7, - /* 5021 */ 0x23A8D, - /* 5022 */ 0x21D0B, - /* 5023 */ 0x23AFA, - /* 5024 */ 0x23CBC, - /* 5025 */ 0x23D1E, - /* 5026 */ 0x23ED1, - /* 5027 */ 0x23F5E, - /* 5028 */ 0x23F8E, - /* 5029 */ 0x20525, - /* 5030 */ 0x24263, - /* 5031 */ 0x243AB, - /* 5032 */ 0x24608, - /* 5033 */ 0x24735, - /* 5034 */ 0x24814, - /* 5035 */ 0x24C36, - /* 5036 */ 0x24C92, - /* 5037 */ 0x2219F, - /* 5038 */ 0x24FA1, - /* 5039 */ 0x24FB8, - /* 5040 */ 0x25044, - /* 5041 */ 0x250F3, - /* 5042 */ 0x250F2, - /* 5043 */ 0x25119, - /* 5044 */ 0x25133, - /* 5045 */ 0x2541D, - /* 5046 */ 0x25626, - /* 5047 */ 0x2569A, - /* 5048 */ 0x256C5, - /* 5049 */ 0x2597C, - /* 5050 */ 0x25AA7, - /* 5051 */ 0x25AA7, - /* 5052 */ 0x25BAB, - /* 5053 */ 0x25C80, - /* 5054 */ 0x25F86, - /* 5055 */ 0x26228, - /* 5056 */ 0x26247, - /* 5057 */ 0x262D9, - /* 5058 */ 0x2633E, - /* 5059 */ 0x264DA, - /* 5060 */ 0x26523, - /* 5061 */ 0x265A8, - /* 5062 */ 0x2335F, - /* 5063 */ 0x267A7, - /* 5064 */ 0x267B5, - /* 5065 */ 0x23393, - /* 5066 */ 0x2339C, - /* 5067 */ 0x26B3C, - /* 5068 */ 0x26C36, - /* 5069 */ 0x26D6B, - /* 5070 */ 0x26CD5, - /* 5071 */ 0x273CA, - /* 5072 */ 0x26F2C, - /* 5073 */ 0x26FB1, - /* 5074 */ 0x270D2, - /* 5075 */ 0x27667, - /* 5076 */ 0x278AE, - /* 5077 */ 0x27966, - /* 5078 */ 0x27CA8, - /* 5079 */ 0x27F2F, - /* 5080 */ 0x20804, - /* 5081 */ 0x208DE, - /* 5082 */ 0x285D2, - /* 5083 */ 0x285ED, - /* 5084 */ 0x2872E, - /* 5085 */ 0x28BFA, - /* 5086 */ 0x28D77, - /* 5087 */ 0x29145, - /* 5088 */ 0x2921A, - /* 5089 */ 0x2940A, - /* 5090 */ 0x29496, - /* 5091 */ 0x295B6, - /* 5092 */ 0x29B30, - /* 5093 */ 0x2A0CE, - /* 5094 */ 0x2A105, - /* 5095 */ 0x2A20E, - /* 5096 */ 0x2A291, - /* 5097 */ 0x2A600 + /* 4776 */ 0x105D2, 0x0307, + /* 4778 */ 0x105DA, 0x0307, + /* 4780 */ 0x1DF04, + /* 4781 */ 0x1DF05, + /* 4782 */ 0x1DF06, + /* 4783 */ 0x1DF08, + /* 4784 */ 0x1DF0A, + /* 4785 */ 0x1DF1E, + /* 4786 */ 0x11099, 0x110BA, + /* 4788 */ 0x1109B, 0x110BA, + /* 4790 */ 0x110A5, 0x110BA, + /* 4792 */ 0x11131, 0x11127, + /* 4794 */ 0x11132, 0x11127, + /* 4796 */ 0x11347, 0x1133E, + /* 4798 */ 0x11347, 0x11357, + /* 4800 */ 0x11382, 0x113C9, + /* 4802 */ 0x11384, 0x113BB, + /* 4804 */ 0x1138B, 0x113C2, + /* 4806 */ 0x11390, 0x113C9, + /* 4808 */ 0x113C2, 0x113C2, + /* 4810 */ 0x113C2, 0x113B8, + /* 4812 */ 0x113C2, 0x113C9, + /* 4814 */ 0x114B9, 0x114BA, + /* 4816 */ 0x114B9, 0x114B0, + /* 4818 */ 0x114B9, 0x114BD, + /* 4820 */ 0x115B8, 0x115AF, + /* 4822 */ 0x115B9, 0x115AF, + /* 4824 */ 0x11935, 0x11930, + /* 4826 */ 0x1611E, 0x1611E, + /* 4828 */ 0x1611E, 0x16129, + /* 4830 */ 0x1611E, 0x1611F, + /* 4832 */ 0x16129, 0x1611F, + /* 4834 */ 0x1611E, 0x16120, + /* 4836 */ 0x16121, 0x1611F, + /* 4838 */ 0x16122, 0x1611F, + /* 4840 */ 0x16121, 0x16120, + /* 4842 */ 0x16D67, 0x16D67, + /* 4844 */ 0x16D63, 0x16D67, + /* 4846 */ 0x16D69, 0x16D67, + /* 4848 */ 0x1D157, 0x1D165, + /* 4850 */ 0x1D158, 0x1D165, + /* 4852 */ 0x1D15F, 0x1D16E, + /* 4854 */ 0x1D15F, 0x1D16F, + /* 4856 */ 0x1D15F, 0x1D170, + /* 4858 */ 0x1D15F, 0x1D171, + /* 4860 */ 0x1D15F, 0x1D172, + /* 4862 */ 0x1D1B9, 0x1D165, + /* 4864 */ 0x1D1BA, 0x1D165, + /* 4866 */ 0x1D1BB, 0x1D16E, + /* 4868 */ 0x1D1BC, 0x1D16E, + /* 4870 */ 0x1D1BB, 0x1D16F, + /* 4872 */ 0x1D1BC, 0x1D16F, + /* 4874 */ 0x0030, 0x002E, + /* 4876 */ 0x0030, 0x002C, + /* 4878 */ 0x0031, 0x002C, + /* 4880 */ 0x0032, 0x002C, + /* 4882 */ 0x0033, 0x002C, + /* 4884 */ 0x0034, 0x002C, + /* 4886 */ 0x0035, 0x002C, + /* 4888 */ 0x0036, 0x002C, + /* 4890 */ 0x0037, 0x002C, + /* 4892 */ 0x0038, 0x002C, + /* 4894 */ 0x0039, 0x002C, + /* 4896 */ 0x0028, 0x0041, 0x0029, + /* 4899 */ 0x0028, 0x0042, 0x0029, + /* 4902 */ 0x0028, 0x0043, 0x0029, + /* 4905 */ 0x0028, 0x0044, 0x0029, + /* 4908 */ 0x0028, 0x0045, 0x0029, + /* 4911 */ 0x0028, 0x0046, 0x0029, + /* 4914 */ 0x0028, 0x0047, 0x0029, + /* 4917 */ 0x0028, 0x0048, 0x0029, + /* 4920 */ 0x0028, 0x0049, 0x0029, + /* 4923 */ 0x0028, 0x004A, 0x0029, + /* 4926 */ 0x0028, 0x004B, 0x0029, + /* 4929 */ 0x0028, 0x004C, 0x0029, + /* 4932 */ 0x0028, 0x004D, 0x0029, + /* 4935 */ 0x0028, 0x004E, 0x0029, + /* 4938 */ 0x0028, 0x004F, 0x0029, + /* 4941 */ 0x0028, 0x0050, 0x0029, + /* 4944 */ 0x0028, 0x0051, 0x0029, + /* 4947 */ 0x0028, 0x0052, 0x0029, + /* 4950 */ 0x0028, 0x0053, 0x0029, + /* 4953 */ 0x0028, 0x0054, 0x0029, + /* 4956 */ 0x0028, 0x0055, 0x0029, + /* 4959 */ 0x0028, 0x0056, 0x0029, + /* 4962 */ 0x0028, 0x0057, 0x0029, + /* 4965 */ 0x0028, 0x0058, 0x0029, + /* 4968 */ 0x0028, 0x0059, 0x0029, + /* 4971 */ 0x0028, 0x005A, 0x0029, + /* 4974 */ 0x3014, 0x0053, 0x3015, + /* 4977 */ 0x0043, 0x0044, + /* 4979 */ 0x0057, 0x005A, + /* 4981 */ 0x0048, 0x0056, + /* 4983 */ 0x004D, 0x0056, + /* 4985 */ 0x0053, 0x0044, + /* 4987 */ 0x0053, 0x0053, + /* 4989 */ 0x0050, 0x0050, 0x0056, + /* 4992 */ 0x0057, 0x0043, + /* 4994 */ 0x004D, 0x0043, + /* 4996 */ 0x004D, 0x0044, + /* 4998 */ 0x004D, 0x0052, + /* 5000 */ 0x0044, 0x004A, + /* 5002 */ 0x307B, 0x304B, + /* 5004 */ 0x30B3, 0x30B3, + /* 5006 */ 0x3014, 0x672C, 0x3015, + /* 5009 */ 0x3014, 0x4E09, 0x3015, + /* 5012 */ 0x3014, 0x4E8C, 0x3015, + /* 5015 */ 0x3014, 0x5B89, 0x3015, + /* 5018 */ 0x3014, 0x70B9, 0x3015, + /* 5021 */ 0x3014, 0x6253, 0x3015, + /* 5024 */ 0x3014, 0x76D7, 0x3015, + /* 5027 */ 0x3014, 0x52DD, 0x3015, + /* 5030 */ 0x3014, 0x6557, 0x3015, + /* 5033 */ 0x20122, + /* 5034 */ 0x2063A, + /* 5035 */ 0x2051C, + /* 5036 */ 0x2054B, + /* 5037 */ 0x291DF, + /* 5038 */ 0x20A2C, + /* 5039 */ 0x20B63, + /* 5040 */ 0x214E4, + /* 5041 */ 0x216A8, + /* 5042 */ 0x216EA, + /* 5043 */ 0x219C8, + /* 5044 */ 0x21B18, + /* 5045 */ 0x21DE4, + /* 5046 */ 0x21DE6, + /* 5047 */ 0x22183, + /* 5048 */ 0x2A392, + /* 5049 */ 0x22331, + /* 5050 */ 0x22331, + /* 5051 */ 0x232B8, + /* 5052 */ 0x261DA, + /* 5053 */ 0x226D4, + /* 5054 */ 0x22B0C, + /* 5055 */ 0x22BF1, + /* 5056 */ 0x2300A, + /* 5057 */ 0x233C3, + /* 5058 */ 0x2346D, + /* 5059 */ 0x236A3, + /* 5060 */ 0x238A7, + /* 5061 */ 0x23A8D, + /* 5062 */ 0x21D0B, + /* 5063 */ 0x23AFA, + /* 5064 */ 0x23CBC, + /* 5065 */ 0x23D1E, + /* 5066 */ 0x23ED1, + /* 5067 */ 0x23F5E, + /* 5068 */ 0x23F8E, + /* 5069 */ 0x20525, + /* 5070 */ 0x24263, + /* 5071 */ 0x243AB, + /* 5072 */ 0x24608, + /* 5073 */ 0x24735, + /* 5074 */ 0x24814, + /* 5075 */ 0x24C36, + /* 5076 */ 0x24C92, + /* 5077 */ 0x2219F, + /* 5078 */ 0x24FA1, + /* 5079 */ 0x24FB8, + /* 5080 */ 0x25044, + /* 5081 */ 0x250F3, + /* 5082 */ 0x250F2, + /* 5083 */ 0x25119, + /* 5084 */ 0x25133, + /* 5085 */ 0x2541D, + /* 5086 */ 0x25626, + /* 5087 */ 0x2569A, + /* 5088 */ 0x256C5, + /* 5089 */ 0x2597C, + /* 5090 */ 0x25AA7, + /* 5091 */ 0x25AA7, + /* 5092 */ 0x25BAB, + /* 5093 */ 0x25C80, + /* 5094 */ 0x25F86, + /* 5095 */ 0x26228, + /* 5096 */ 0x26247, + /* 5097 */ 0x262D9, + /* 5098 */ 0x2633E, + /* 5099 */ 0x264DA, + /* 5100 */ 0x26523, + /* 5101 */ 0x265A8, + /* 5102 */ 0x2335F, + /* 5103 */ 0x267A7, + /* 5104 */ 0x267B5, + /* 5105 */ 0x23393, + /* 5106 */ 0x2339C, + /* 5107 */ 0x26B3C, + /* 5108 */ 0x26C36, + /* 5109 */ 0x26D6B, + /* 5110 */ 0x26CD5, + /* 5111 */ 0x273CA, + /* 5112 */ 0x26F2C, + /* 5113 */ 0x26FB1, + /* 5114 */ 0x270D2, + /* 5115 */ 0x27667, + /* 5116 */ 0x278AE, + /* 5117 */ 0x27966, + /* 5118 */ 0x27CA8, + /* 5119 */ 0x27F2F, + /* 5120 */ 0x20804, + /* 5121 */ 0x208DE, + /* 5122 */ 0x285D2, + /* 5123 */ 0x285ED, + /* 5124 */ 0x2872E, + /* 5125 */ 0x28BFA, + /* 5126 */ 0x28D77, + /* 5127 */ 0x29145, + /* 5128 */ 0x2921A, + /* 5129 */ 0x2940A, + /* 5130 */ 0x29496, + /* 5131 */ 0x295B6, + /* 5132 */ 0x29B30, + /* 5133 */ 0x2A0CE, + /* 5134 */ 0x2A105, + /* 5135 */ 0x2A20E, + /* 5136 */ 0x2A291, + /* 5137 */ 0x2A600 }; diff --git a/src/include/common/unicode_normprops_table.h b/src/include/common/unicode_normprops_table.h index 7a13405525295..f1072c9f09966 100644 --- a/src/include/common/unicode_normprops_table.h +++ b/src/include/common/unicode_normprops_table.h @@ -695,11 +695,32 @@ static const pg_unicode_normprops UnicodeNormProps_NFC_QC[] = { {0x11127, UNICODE_NORM_QC_MAYBE}, {0x1133E, UNICODE_NORM_QC_MAYBE}, {0x11357, UNICODE_NORM_QC_MAYBE}, + {0x113B8, UNICODE_NORM_QC_MAYBE}, + {0x113BB, UNICODE_NORM_QC_MAYBE}, + {0x113C2, UNICODE_NORM_QC_MAYBE}, + {0x113C5, UNICODE_NORM_QC_MAYBE}, + {0x113C7, UNICODE_NORM_QC_MAYBE}, + {0x113C8, UNICODE_NORM_QC_MAYBE}, + {0x113C9, UNICODE_NORM_QC_MAYBE}, {0x114B0, UNICODE_NORM_QC_MAYBE}, {0x114BA, UNICODE_NORM_QC_MAYBE}, {0x114BD, UNICODE_NORM_QC_MAYBE}, {0x115AF, UNICODE_NORM_QC_MAYBE}, {0x11930, UNICODE_NORM_QC_MAYBE}, + {0x1611E, UNICODE_NORM_QC_MAYBE}, + {0x1611F, UNICODE_NORM_QC_MAYBE}, + {0x16120, UNICODE_NORM_QC_MAYBE}, + {0x16121, UNICODE_NORM_QC_MAYBE}, + {0x16122, UNICODE_NORM_QC_MAYBE}, + {0x16123, UNICODE_NORM_QC_MAYBE}, + {0x16124, UNICODE_NORM_QC_MAYBE}, + {0x16125, UNICODE_NORM_QC_MAYBE}, + {0x16126, UNICODE_NORM_QC_MAYBE}, + {0x16127, UNICODE_NORM_QC_MAYBE}, + {0x16128, UNICODE_NORM_QC_MAYBE}, + {0x16129, UNICODE_NORM_QC_MAYBE}, + {0x16D67, UNICODE_NORM_QC_MAYBE}, + {0x16D68, UNICODE_NORM_QC_MAYBE}, {0x1D15E, UNICODE_NORM_QC_NO}, {0x1D15F, UNICODE_NORM_QC_NO}, {0x1D160, UNICODE_NORM_QC_NO}, @@ -1261,315 +1282,321 @@ static const pg_unicode_normprops UnicodeNormProps_NFC_QC[] = { static int NFC_QC_hash_func(const void *key) { - static const int16 h[2463] = { - 0, -2717, 0, 221, 1293, 223, 1295, 225, - 226, 241, 0, 229, 230, 231, 0, 0, + static const int16 h[2505] = { + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 0, 32767, 32767, 32767, 32767, 0, 0, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 50, + 32767, 32767, 32767, 32767, 51, 52, 32767, 53, + 32767, 32767, 32767, 32767, 0, 0, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 668, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -713, + 32767, 32767, 32767, 32767, 806, 687, 807, -539, + 808, 581, 581, 693, -51, 695, 976, 977, + -281, 465, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, -1155, -1155, -1155, 1007, 1008, 59, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -386, 0, 0, 0, 0, 0, 0, 0, - -163, 0, 0, 0, 0, 0, 0, 0, + 0, 893, 1829, 1830, 1293, 1832, 1151, 0, + 1154, 1837, 1156, 1157, 2760, -135, 1842, 0, + 0, 1847, 980, 1850, 0, 1853, 733, 975, + 177, 1059, 1060, 1061, 644, 1867, 1064, 1065, + 1066, 1067, 1068, 1069, 1070, 1882, 1072, 1884, + 1885, 1088, 1887, 1077, 1089, 1079, 1080, 1896, + 1897, 1083, 1900, 634, 1086, 665, 666, 0, + 2100, 0, 1914, -172, -172, -172, -1307, -361, + -361, 1641, -361, -361, -361, -361, -172, 1654, + 0, 332, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 669, 0, -132, 0, 0, + 0, 0, 0, 0, 0, 670, 0, 0, + 0, 0, 671, 0, 0, 0, 0, 672, + 0, 0, 0, 0, -78, 0, -1541, 0, + 0, 0, 0, 0, 0, 0, 1869, 0, + 0, 674, 0, 0, 0, 0, 0, 0, + 2046, 1092, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -246, -175, 1260, 0, 0, 0, -174, -173, - 0, -172, 0, 0, 0, 0, 0, 0, - 1049, 0, 300, 301, 1071, 0, 1071, 0, - 1071, 1071, 1057, 0, 0, 0, 0, 1061, - 0, -1053, 1664, 0, 2956, 0, 0, -13, - 0, 0, 0, 0, 2156, 0, 0, 0, - 0, 0, 0, 0, 71, 0, 1082, 0, - 1083, 1083, 0, 1084, 0, 0, 0, 0, + 0, 0, 1116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 359, 360, 361, - -1091, 363, -762, -130, -129, -128, -127, -126, - 137, -124, -708, -707, -706, -120, -185, -705, - -117, -184, -1307, -114, -113, -112, -111, 0, - 386, 387, 388, 389, -90, 391, 171, 172, - 394, -94, -183, 397, 398, 399, -98, -225, - 402, -1019, -636, -1019, -225, 407, 408, 409, - 410, 411, 674, 413, -171, -170, -169, 417, - 352, -168, 420, 353, -770, 423, 424, 425, - 426, 427, 428, 32767, 239, 239, 239, 239, - 239, 239, 239, 239, 239, 239, 239, 239, - 239, 239, 32767, 32767, 237, 32767, 236, 32767, - 32767, 234, 234, 234, 234, 617, 234, 234, - 234, -2483, 234, -1430, 1526, -1430, 1527, 47, - 48, 471, 230, 32767, 32767, 32767, 227, 227, - 227, 227, 227, 227, 227, 227, 227, 227, - 227, 227, 227, 227, 227, 227, 227, 227, - -159, 227, 227, 227, 227, 227, 227, 227, - 64, 227, 227, 227, 227, 227, 227, 227, - 227, 227, 227, 227, 227, 227, 227, 227, - 227, 227, 227, 227, 227, 227, 227, 227, - -19, 52, 1487, 227, 227, 227, 53, 54, - 227, 55, 227, 227, 227, 227, 227, 227, - 1276, 227, -989, 32767, 1296, 225, 1296, 225, - 1296, 1296, 1282, 225, 225, 225, 225, 1286, - 225, -828, 1889, 225, 3181, 225, 225, 212, - 225, 225, 225, 225, 2381, 225, 225, 225, - 225, 225, 225, 225, 296, 225, 1307, 225, - 1308, 1308, 225, 1309, 225, 225, 225, 225, - 225, 225, 225, 225, 225, 225, 225, 225, - 225, 225, 225, 225, 225, 584, 585, 586, - -866, 588, -537, 95, 96, 97, 98, 99, - 362, 101, -483, -482, -481, 105, 40, -480, - 108, 41, -1082, 111, 112, 113, 114, 225, - 611, 612, 613, 614, 135, 616, 396, 397, - 619, 131, 42, 622, 623, 624, 127, 0, - 627, -794, -411, -794, 0, 632, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - -272, 32767, 32767, 32767, 0, 32767, 32767, 32767, - 32767, 32767, -166, -165, 32767, 32767, 32767, 32767, - -164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 397, 32767, 396, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 386, - 0, 386, 386, 386, 386, 386, 386, 386, - 223, 386, 386, 386, 32767, 385, 385, 385, - 385, 385, 32767, 384, 32767, 383, 383, 32767, - 382, 382, 32767, 381, 381, 381, 381, 381, - 135, 206, 1641, 381, 32767, 32767, 32767, 32767, - 32767, 32767, -160, 32767, 32767, 32767, 32767, 32767, + 60, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -15, + 61, 62, 32767, 32767, 32767, 32767, 63, 64, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 710, 57, 57, 713, + 58, 58, 716, 692, 59, 693, 59, 59, + 59, 59, 59, 59, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 506, 857, + 738, 858, -488, 859, 632, 632, 744, 0, + 746, 747, 748, 749, 750, 751, 752, 753, + 754, 755, 756, 757, 758, 759, 760, 761, + 762, 763, 764, 765, 766, 767, 768, 769, + 770, 771, 772, 773, 774, 775, 776, 777, + 778, 779, 780, 781, 782, 783, 784, 785, + 786, 787, 788, 789, 790, 791, 792, 0, + 0, 538, 0, 682, 0, 682, 0, 682, + 682, -920, 1976, 0, 0, 0, 0, 0, + 0, 0, 0, 1121, 20, 682, 0, 682, + 682, 1139, 0, 682, 682, 682, 1138, 825, + 826, 827, 0, 811, 0, 0, 798, 0, + 834, 835, 836, 837, 0, 0, 840, 0, + 1267, 843, 844, 845, 846, 847, 848, 0, + 850, 851, 822, 853, 854, 855, 856, 2290, + 2291, 2292, 2293, 2105, 280, 863, 864, 865, + 1839, -410, -410, 869, 870, 871, 872, 873, + 874, 875, 876, 877, 878, 879, 880, 881, + 882, 883, 884, 885, 0, 0, 2002, 0, + 0, 0, 0, 893, 894, 895, 896, 897, + 898, 899, 900, 901, 902, 903, 904, 905, + 906, 907, 908, 158, 910, 911, 912, 913, + 914, 915, 916, 917, 918, 0, 920, 921, + 922, 923, 924, 925, 926, 927, 2063, 1118, + 1119, -882, 1121, 1122, 1123, 1124, 936, 937, + 938, 939, 940, 941, 942, 943, 944, 945, + 946, 947, 948, 949, 950, 951, 952, 953, + 954, 955, 956, 957, 958, 959, 960, 961, + 962, 963, 964, 965, 510, 160, 280, 161, + 1508, 162, 390, 391, 280, 1025, 280, 0, + 0, 1259, 514, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2159, 2160, 2161, 0, 0, + 950, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, + 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, + 1033, 1034, 142, -793, -793, -255, -793, -111, + 1041, -112, -794, -112, -112, -1714, 1182, -794, + 1049, 1050, -796, 72, -797, 1054, -798, 323, + 82, 881, 0, 0, 0, 418, -804, 0, + 0, 0, 0, 0, 0, 0, -811, 0, + -811, -811, -13, -811, 0, -11, 0, 0, + -815, -815, 0, -816, 451, 0, 422, 422, + 1089, -1010, 1091, -822, 1265, 1266, 1267, 2403, + 1458, 1459, -542, 1461, 1462, 1463, 1464, 1276, + -549, 1106, 775, 1108, 1109, 1110, 1111, 1112, + 1113, 1114, 1115, 1116, 448, 1118, 1251, 1120, + 1121, 1122, 1123, 1124, 1125, 1126, 457, 1128, + 1129, 1130, 1131, 461, 1133, 1134, 1135, 1136, + 465, 1138, 1139, 1140, 1141, 1220, 1143, 2685, + 1145, 1146, 1147, 1148, 1149, 1150, 1151, -717, + 1153, 1154, 481, 1156, 1157, 1158, 1159, 1160, + 1161, -884, 71, 1164, 1165, 1166, 1167, 1168, + 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, + 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, + 1185, 1186, 1187, 72, 1189, 1190, 1191, 1192, + 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, + 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, + 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, + 1217, 1218, 1219, 1220, 1221, 32767, 1140, 342, + 1224, 1225, 1226, 809, 2032, 1229, 1230, 1231, + 1232, 1233, 1234, 1235, 2047, 1237, 2049, 2050, + 1253, 2052, 1242, 1254, 1244, 1245, 2061, 2062, + 1248, 2065, 799, 1251, 32767, 448, 32767, 448, + 676, 677, 170, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 165, 32767, 32767, 32767, + 166, 167, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 143, 32767, 144, + 32767, -690, 32767, -691, 32767, 147, 73, 148, + 32767, -694, 32767, -621, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 32767, 657, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -755, + 32767, 32767, -757, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 152, 32767, -768, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -964, + 32767, 32767, 32767, 32767, 32767, 32767, 0, -782, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -789, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -796, + 32767, 32767, -798, -798, 750, 0, 32767, 32767, + 32767, 32767, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 830, 831, + 832, 0, 0, 32767, 32767, 1125, 32767, 1126, + 32767, 32767, 2047, -848, 1129, 1130, 1131, 1132, + 1133, 1134, 1135, 1136, 32767, 1117, 32767, 1138, + 32767, 32767, 0, 1140, 32767, 32767, 32767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 678, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 679, 0, 0, 680, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32767, 32767, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1343, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, 211, 212, + -325, 214, -467, 216, -465, 218, -463, -462, + 1141, -1754, 223, 224, 225, 226, 227, 228, + 229, 230, -890, 212, -449, 234, -447, -446, + -902, 238, -443, -442, -441, -896, -582, -582, + -582, 246, -564, 248, 249, -548, 251, -582, + -582, -582, -582, 256, 257, -582, 259, -1007, + -582, -582, -582, -582, -582, -582, 267, -582, + -582, -552, -582, -582, -582, -582, -2015, -2015, + -2015, -2015, -1826, 0, -582, -582, -582, -1555, + 695, 696, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, 304, 305, -1696, 307, 308, + 309, 310, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, 169, -582, -582, -582, -582, -582, + -582, -582, -582, -582, 337, -582, -582, -582, + -582, -582, -582, -582, -582, -1717, -771, -771, + 1231, -771, -771, -771, -771, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -582, -582, -582, -582, -582, + -582, -582, -582, -126, 225, 106, 226, -1120, + 227, 0, 0, 112, -632, 114, 395, 396, + -862, -116, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, -1736, -1736, -1736, 426, 427, -522, + 32767, 429, 430, 431, 432, 433, 434, 435, + 436, 437, -392, -392, -392, 441, 442, 32767, + 0, -682, 0, -682, 0, 0, -1602, 1294, + -682, -682, -682, -682, -682, -682, -682, -682, + 439, -662, 0, -682, 0, 0, 457, -682, + 0, 0, 0, 459, 460, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, -201, 478, 479, + 480, 481, 482, 483, 484, 485, 486, -192, + 488, 489, -190, 491, 492, 493, 494, 495, + 496, 497, 498, 499, 500, 501, 502, 503, + 504, 505, 506, 507, 508, 509, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, + 520, 521, 522, 523, 524, 525, 526, 32767, + 32767, 527, 528, 529, 530, 531, 532, 533, + 534, 535, 536, 537, 538, 539, 540, 541, + 542, 543, 544, 545, 546, 547, 548, 549, + 550, 551, 552, 553, 554, 555, 556, 557, + 558, 559, 560, 561, 562, 563, 564, 565, + 566, 567, 568, 569, 570, 571, 572, 573, + 574, 575, 576, 577, 578, 579, 580, 581, + 582, 583, 584, 585, 586, 587, 588, 589, + 590, -752, 592, 593, 594, 595, 596, 597, + 598, 599, 600, 601, 602, 603, 604, 605, + 606, 607, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 617, 1200, 1201, 1202, 1203, + 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, + 1212, 1213, 1214, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 1148, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 0, 0, 0, 0, 0, 32767, 0, + 32767, 0, 0, 32767, 0, 0, 32767, 633, + 0, 634, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, 635, 636, 637, 638, + 639, 640, 641, 642, 643, 644, 645, 646, + 647, 32767, 648, 649, 650, 651, 652, 32767, + 653, 0, 654, 655, 0, 656, 657, 0, + 25, 659, 26, 661, 662, 663, 664, 665, + 666, 676, 677, 678, 679, 680, 681, 682, + 683, 684, 685, 230, -120, 0, -119, 1228, + -118, 110, 111, 0, 745, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 793, 794, 257, 796, + 115, 798, 117, 800, 119, 120, 1723, -1172, + 805, 806, 807, 808, 809, 810, 811, 812, + -308, 794, 133, 816, 135, 136, -320, 820, + 139, 140, 141, -314, 0, 0, 0, 828, + 18, 830, 831, 34, 833, 0, 0, 0, + 0, 838, 839, 0, 841, -425, 0, 0, + 0, 0, 0, 0, 849, 0, 0, 30, + 0, 0, 0, 0, -1433, -1433, -1433, -1433, + -1244, 582, 0, 0, 0, -973, 1277, 1278, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 886, 887, -1114, 889, 890, 891, 892, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 751, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 919, 0, 0, 0, 0, 0, + 0, 0, 0, -1135, -189, -189, 1813, -189, + -189, -189, -189, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 32767, 32767, 32767, 32767, 704, 705, + 706, 707, 708, 709, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -257, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -910, -910, 32767, 32767, - 0, 32767, 0, 32767, 0, 32767, 0, 32767, - 147, 32767, 0, 32767, 0, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 143, 32767, 144, 32767, 145, - 32767, 146, 32767, 0, 32767, 148, 32767, 149, - 32767, 32767, 32767, -160, 32767, 32767, 32767, 32767, - 32767, 32767, 15, 32767, 32767, 0, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 145, 32767, 144, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, -148, 32767, 32767, 32767, 32767, - 32767, 32767, 2009, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, 32767, 32767, 135, -918, 32767, - 151, 32767, 32767, 0, 1, 2, 3, 4, - 133, 5, 6, 7, 8, 9, 10, 11, - 32767, 32767, -1248, 32767, 13, 154, 188, 188, - 32767, 32767, 32767, 32767, 32767, 155, 16, 32767, - 32767, 32767, 32767, 32767, 32767, -1853, -1054, 18, - -1052, -1051, -1036, 22, 32767, 157, 32767, 28, - 23, 1077, 673, 25, -2930, 0, 32767, 32767, - 32767, 32767, 32767, 27, 32767, 155, 32767, 154, - 32767, 32767, -62, 28, -42, 30, -1051, 32, - -1050, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 34, + 32767, 32767, 0, 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 129, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 672, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, - 32767, 32767, 32767, 32767, -156, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -155, 32767, 32767, - 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 40, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 682, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 41, 42, 43, 44, 45, 46, 47, + 48, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 171, 172, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 73, 32767, 32767, 32767, 32767, 74, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 675, - 32767, 32767, 32767, 32767, 32767, 75, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 165, 32767, 32767, 32767, 166, 167, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 170, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 689, 690, 691, 692, 693, 694, 695, - 696, 697, 698, 699, 700, 701, 702, 703, - 704, 705, 706, 707, 708, 709, 710, 711, - 712, 713, 714, 715, 716, 717, 718, 719, - 720, 721, 722, -304, -303, -302, -301, -300, - -299, -298, -297, 930, -295, -294, -293, -292, - -291, -290, -289, -288, -287, -286, -285, -284, - -283, -282, -281, -280, -279, -278, -277, -276, - -275, 753, 754, 755, 646, 757, -712, -1765, - 952, -712, 2244, -712, 2245, 765, 766, 767, - 768, 125, 770, 771, 772, 773, 774, 775, - 603, 777, 778, 779, 780, 781, 782, 783, - 784, 2011, 786, 787, 788, 789, 790, 791, - 792, 793, 794, 795, 796, 797, 798, 799, - 800, 801, 802, 803, 804, 805, 806, 603, - 603, 809, 603, 811, 603, 603, 814, 815, - 816, 817, 435, 819, 820, 821, 3539, 823, - 603, -468, 603, -468, 603, 603, 589, 831, - 603, 603, 603, 835, 836, 837, 838, 839, - 840, 841, 842, 843, 844, 845, 846, 847, - 848, 849, 850, 851, 852, 1239, 854, 855, - 856, 857, 858, 859, 860, 1024, 862, 863, - 864, 865, 866, 867, 868, 869, 870, 871, - 872, 873, 874, 875, 876, 877, 878, 879, - 880, 881, 882, 883, 884, 1131, 1061, -373, - 888, 889, 890, 1065, 1065, 893, 1066, 895, - 896, 897, 898, 899, 900, -148, 902, 603, - 603, -166, 906, -164, 908, -162, -161, -146, - 912, 913, 914, 915, -145, 917, 1971, -745, - 920, -2035, 922, 923, 937, 925, 926, 927, - 928, -1227, 930, 931, 932, 933, 934, 935, - 936, 866, 938, -143, 940, -142, -141, 943, - -140, 32767, 945, 946, 947, 948, 949, 950, - 951, 952, 953, 954, 955, 956, 957, 958, - 959, 960, 961, -65, -64, -63, -62, -61, - -60, -59, -58, 1169, -56, -55, -54, -53, - -52, -51, -50, -49, -48, -47, -46, -45, - -44, -43, -42, -41, -40, -39, -38, -37, - -36, 992, 993, 994, 885, 996, -473, -1526, - 1191, -473, 2483, -473, 2484, 1004, 1005, 1006, - 1007, 364, 1009, 1010, 1011, 1012, 1013, 1014, - 842, 1016, 1017, 1018, 1019, 1020, 1021, 1022, - 1023, 2250, 1025, 1026, 1027, 1028, 1029, 1030, - 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, - 1039, 1040, 1041, 1042, 1043, 1044, 1045, 842, - 842, 1048, 842, 1050, 842, 842, 1053, 1054, - 1055, 1056, 674, 1058, 1059, 1060, 3778, 1062, - 842, -229, 842, -229, 842, 842, 828, 1070, - 842, 842, 842, 1074, 1075, 1076, 1077, 1078, - 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, - 1087, 1088, 1089, 1090, 1091, 1478, 1093, 1094, - 1095, 1096, 1097, 1098, 1099, 1263, 1101, 1102, - 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, - 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, - 1119, 1120, 1121, 1122, 1123, 1370, 1300, -134, - 1127, 1128, 1129, 1304, 1304, 1132, 1305, 1134, - 1135, 1136, 1137, 1138, 1139, 91, 1141, 842, - 842, 73, 1145, 75, 1147, 77, 78, 93, - 1151, 1152, 1153, 1154, 94, 1156, 2210, -506, - 1159, -1796, 1161, 1162, 1176, 1164, 1165, 1166, - 1167, -988, 1169, 1170, 1171, 1172, 1173, 1174, - 1175, 1105, 1177, 96, 1179, 97, 98, 1182, - 99, 1184, 1185, 1186, 1187, 1188, 1189, 1190, - 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, - 1199, 1200, 0, 174, 175, 176, 177, 178, - 179, 180, 181, 1408, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, - 203, 0, 0, 206, 0, 208, 0, 0, - 211, 212, 213, 214, -168, 216, 217, 218, - 2936, 220, 0, -1071, 0, -1071, 0, 0, - -14, 228, 0, 0, 0, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 636, - 251, 252, 253, 254, 255, 256, 257, 421, - 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 528, - 458, -976, 285, 286, 287, 462, 462, 290, - 463, 292, 293, 294, 295, 296, 297, -751, - 299, 0, 0, -769, 303, -767, 305, -765, - -764, -749, 309, 310, 311, 312, -748, 314, - 1368, -1348, 317, -2638, 319, 320, 334, 322, - 323, 324, 325, -1830, 327, 328, 329, 330, - 331, 332, 333, 263, 335, -746, 337, -745, - -744, 340, -743, 342, 343, 344, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 0, 0, 0, 1453, - 0, 1126, 495, 495, 495, 495, 495, 233, - 495, 1080, 1080, 1080, 495, 561, 1082, 495, - 563, 1687, 495, 495, 495, 495, 385, 0, - 0, 0, 0, 480, 0, 221, 221, 0, - 489, 579, 0, 0, 0, 498, 626, 0, - 1422, 1040, 1424, 631, 0, 0, 0, 0, - 0, -262, 0, 585, 585, 585, 0, 66, - 587, 0, 68, 1192, 0, 0, 0, 0, - 0, 0, 32767, 32767, 32767, 32767, 669, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 670, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 142, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, - 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1027, 1027, 1027, - 1027, 1027, 1027, 1027, 1027, -199, 1027, 1027, - 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, - 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, - 1027, 1027, 1027, 0, 0, 0, 110, 0, - 1470, 2524, -192, 1473, -1482, 1475, -1481, 0, - 0, 0, 0, 644, 0, 0, 0, 0, - 0, 0, 173, 0, 0, 0, 0, 0, - 0, 0, 0, -1226, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 204, 205, 0, 207, 0, 209, 210, - 0, 0, 0, 0, 383, 0, 0 + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 49, + 32767 }; const unsigned char *k = (const unsigned char *) key; @@ -1582,16 +1609,16 @@ NFC_QC_hash_func(const void *key) unsigned char c = *k++; a = a * 257 + c; - b = b * 17 + c; + b = b * 8191 + c; } - return h[a % 2463] + h[b % 2463]; + return h[a % 2505] + h[b % 2505]; } /* Hash lookup information for NFC_QC */ static const pg_unicode_norminfo UnicodeNormInfo_NFC_QC = { UnicodeNormProps_NFC_QC, NFC_QC_hash_func, - 1231 + 1252 }; static const pg_unicode_normprops UnicodeNormProps_NFKC_QC[] = { @@ -4729,11 +4756,68 @@ static const pg_unicode_normprops UnicodeNormProps_NFKC_QC[] = { {0x11127, UNICODE_NORM_QC_MAYBE}, {0x1133E, UNICODE_NORM_QC_MAYBE}, {0x11357, UNICODE_NORM_QC_MAYBE}, + {0x113B8, UNICODE_NORM_QC_MAYBE}, + {0x113BB, UNICODE_NORM_QC_MAYBE}, + {0x113C2, UNICODE_NORM_QC_MAYBE}, + {0x113C5, UNICODE_NORM_QC_MAYBE}, + {0x113C7, UNICODE_NORM_QC_MAYBE}, + {0x113C8, UNICODE_NORM_QC_MAYBE}, + {0x113C9, UNICODE_NORM_QC_MAYBE}, {0x114B0, UNICODE_NORM_QC_MAYBE}, {0x114BA, UNICODE_NORM_QC_MAYBE}, {0x114BD, UNICODE_NORM_QC_MAYBE}, {0x115AF, UNICODE_NORM_QC_MAYBE}, {0x11930, UNICODE_NORM_QC_MAYBE}, + {0x1611E, UNICODE_NORM_QC_MAYBE}, + {0x1611F, UNICODE_NORM_QC_MAYBE}, + {0x16120, UNICODE_NORM_QC_MAYBE}, + {0x16121, UNICODE_NORM_QC_MAYBE}, + {0x16122, UNICODE_NORM_QC_MAYBE}, + {0x16123, UNICODE_NORM_QC_MAYBE}, + {0x16124, UNICODE_NORM_QC_MAYBE}, + {0x16125, UNICODE_NORM_QC_MAYBE}, + {0x16126, UNICODE_NORM_QC_MAYBE}, + {0x16127, UNICODE_NORM_QC_MAYBE}, + {0x16128, UNICODE_NORM_QC_MAYBE}, + {0x16129, UNICODE_NORM_QC_MAYBE}, + {0x16D67, UNICODE_NORM_QC_MAYBE}, + {0x16D68, UNICODE_NORM_QC_MAYBE}, + {0x1CCD6, UNICODE_NORM_QC_NO}, + {0x1CCD7, UNICODE_NORM_QC_NO}, + {0x1CCD8, UNICODE_NORM_QC_NO}, + {0x1CCD9, UNICODE_NORM_QC_NO}, + {0x1CCDA, UNICODE_NORM_QC_NO}, + {0x1CCDB, UNICODE_NORM_QC_NO}, + {0x1CCDC, UNICODE_NORM_QC_NO}, + {0x1CCDD, UNICODE_NORM_QC_NO}, + {0x1CCDE, UNICODE_NORM_QC_NO}, + {0x1CCDF, UNICODE_NORM_QC_NO}, + {0x1CCE0, UNICODE_NORM_QC_NO}, + {0x1CCE1, UNICODE_NORM_QC_NO}, + {0x1CCE2, UNICODE_NORM_QC_NO}, + {0x1CCE3, UNICODE_NORM_QC_NO}, + {0x1CCE4, UNICODE_NORM_QC_NO}, + {0x1CCE5, UNICODE_NORM_QC_NO}, + {0x1CCE6, UNICODE_NORM_QC_NO}, + {0x1CCE7, UNICODE_NORM_QC_NO}, + {0x1CCE8, UNICODE_NORM_QC_NO}, + {0x1CCE9, UNICODE_NORM_QC_NO}, + {0x1CCEA, UNICODE_NORM_QC_NO}, + {0x1CCEB, UNICODE_NORM_QC_NO}, + {0x1CCEC, UNICODE_NORM_QC_NO}, + {0x1CCED, UNICODE_NORM_QC_NO}, + {0x1CCEE, UNICODE_NORM_QC_NO}, + {0x1CCEF, UNICODE_NORM_QC_NO}, + {0x1CCF0, UNICODE_NORM_QC_NO}, + {0x1CCF1, UNICODE_NORM_QC_NO}, + {0x1CCF2, UNICODE_NORM_QC_NO}, + {0x1CCF3, UNICODE_NORM_QC_NO}, + {0x1CCF4, UNICODE_NORM_QC_NO}, + {0x1CCF5, UNICODE_NORM_QC_NO}, + {0x1CCF6, UNICODE_NORM_QC_NO}, + {0x1CCF7, UNICODE_NORM_QC_NO}, + {0x1CCF8, UNICODE_NORM_QC_NO}, + {0x1CCF9, UNICODE_NORM_QC_NO}, {0x1D15E, UNICODE_NORM_QC_NO}, {0x1D15F, UNICODE_NORM_QC_NO}, {0x1D160, UNICODE_NORM_QC_NO}, @@ -6640,164 +6724,71 @@ static const pg_unicode_normprops UnicodeNormProps_NFKC_QC[] = { static int NFKC_QC_hash_func(const void *key) { - static const int16 h[10079] = { - 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, - 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, - 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, - 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, - 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, - 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, - 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, - 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, - 3606, 3607, 3608, 3970, 3488, 3611, 3612, 3613, - 3614, 3615, 3616, 3617, 3618, 7967, 3620, 3621, - 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, - 3630, 3631, 3632, 3633, 3634, 3512, 3636, 3637, - 3638, 3639, 32767, 11118, 11119, 11120, 11121, 11122, - 1470, 11124, 11125, 11126, 11127, 11128, 11129, 11130, - 11131, 11132, -287, 8773, 8774, 8775, 8776, 8777, - 8778, -287, 8781, 8782, -287, 8783, 8784, 8785, - 8786, 8787, 8788, 8789, 8790, 8791, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, 2372, -287, -287, -287, -287, -287, -287, - -287, -287, -287, 2458, 2458, 2458, 2458, 2458, - 2458, 2458, 2458, 2458, -287, -287, -287, -5017, - 5765, -287, -5019, -5019, -5019, -5019, -287, -287, - 4632, -5021, -5021, -287, -5022, -5022, -5022, 3732, - -287, -287, 3735, 3736, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - 4994, 2491, 2491, -287, -287, -287, 6887, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, 32767, 32767, -289, 1778, 629, 3809, 3810, - -3050, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, -287, -287, -287, -287, -287, -287, - -287, -287, 3861, 3862, 3863, 3864, 3865, 3866, - 3867, 3868, -1002, 3870, 3871, 3872, 3873, 3874, - 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, - 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, - 3891, 3892, 3893, 32767, 3392, 3392, 3392, -5411, - 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, - 3392, 3392, 224, 225, 226, 3392, 227, 228, - -5998, -5998, 3392, -5998, -5, 0, -5997, -5997, - -7477, 3923, -7478, -7478, -7478, -7478, -7478, -7478, - -7478, -7478, 2175, -7478, -7478, -7478, -7478, -7478, - -7478, -7478, -7478, -7478, 3942, -5117, -5117, -5117, - -5117, -5117, -5117, 3949, -5118, -5118, 3952, -5117, - -5117, -5117, -5117, -5117, -5117, -5117, -5117, -5117, - 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, - 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, - 3978, 3979, 3980, 1322, 3982, 3983, 3984, 3985, - 3986, 3987, 3988, 3989, 3990, 1246, 1247, 1248, - 1249, 1250, 1251, 1252, 1253, 1254, 4000, 4001, - 4002, 8733, -2048, 4005, 8738, 8739, 8740, 8741, - 4010, 4011, -907, 8747, 8748, 4015, 8751, 8752, - 8753, 0, 4020, 4021, 0, 0, 4024, 4025, - 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, - 4034, 4035, -1245, 1259, 1260, 4039, 4040, 4041, - -3132, 4043, 4044, 4045, 4046, 4047, 4048, 4049, - 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, - 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, - 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, - 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, - 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, - 4090, 4091, 4092, 4093, 4094, 4095, 2029, 3179, - 0, 0, 6861, 4099, 4100, 4101, 4102, 4103, - 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, - 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, - 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, - 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, - 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, - 4144, 4145, 4146, 4147, 0, 0, 0, 0, - 0, 0, 0, 0, 4871, 0, 0, 0, + static const int16 h[10193] = { + 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, + 1886, 1887, 1888, 32767, 32767, 1889, 3141, -7211, + 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, + -1320, 1901, 1902, -1322, 1904, 1905, 1921, 1921, + 1921, 1909, 1910, 1911, 1924, 1924, 1914, 1915, + 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, + 1924, 1925, -1976, 4681, 1323, 1929, 1930, 4682, + 1932, 1933, 1934, 1935, 1936, 1937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 422, 510, 422, 422, + 0, 0, 0, 0, 0, 0, 0, 1822, + 0, 431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32767, 32767, 32767, + 0, 0, 1840, 1840, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2762, 2762, 2762, + 2762, 2762, 2762, 2762, 2762, 2762, 2762, 2762, + 2762, 2762, 2762, 2762, 2762, 2762, 2762, 2762, + 2762, 2762, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2812, 2812, 2812, 2812, + 2812, 2812, 2812, 2812, 2812, 2812, 2812, 2812, + 2812, 2812, -1449, 5319, 2812, 2812, 2812, 2812, + 2812, 2812, 2812, 2812, 2812, 2812, -534, 0, + 0, 0, 0, 348, 32767, 349, 0, 0, + 0, 0, 0, 0, 32767, 32767, 0, 0, + 0, -1517, 0, -1517, 32767, -1516, 4370, 4371, + 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, + 0, 32767, 32767, -23190,4110, 0, 0, 0, + 0, 0, 0, 32767, 0, 0, 0, 0, + -622, -622, 0, -3928, -1253, -1252, -5473, -3927, + -3927, -3927, -3927, -3927, -3927, -3927, -3927, -3927, + -3927, -3927, -3927, -3927, -3927, -3580, -3580, -3925, + -3580, -3924, -3580, -3580, -3922, -3922, -3922, -3922, + -3922, -3922, -3922, -3922, 0, 0, -3484, -3919, + -3482, -3918, -3480, -3578, -3916, -3916, -3578, -3578, + -3578, -3913, -3913, -3913, -3913, -3913, -3913, -3913, + -3913, -3913, -3913, -3913, -3913, -3913, -3913, -3913, + -3913, -3913, -3913, -3913, -3913, -3913, -3913, -3913, + -3913, -3913, -3913, -3913, -3913, -3913, -3913, -3913, + -3913, -3913, -3913, -3913, -3913, -3578, 625, -5288, + 627, 628, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2496, 2497, 2498, 2499, 2500, + 2501, 2502, 2503, 2504, 2505, 2506, 2507, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -1769, -1768, -1767, -3528, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, -4117, -4459, -4459, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, -1786, -1785, -1784, -1783, -1782, 5982, - -630, -48, -48, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 677, - 32767, 32767, -636, -635, 1019, -3373, 1019, 1019, - 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, - 1019, 1019, 1019, 1019, 1019, -685, -684, -683, - -682, -681, -6170, -679, -678, 2476, 2477, -6912, - 2479, -3513, 3959, 2482, 2483, 3964, 3965, 3966, - 3967, 3968, 3969, 3970, 3971, 3972, 55, 56, - 2495, 57, 58, 59, 60, 61, 62, 63, - 2503, 2504, 64, 2506, 65, 2508, 66, 67, - 2511, 2512, 32767, 32767, 32767, 32767, 68, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 69, 70, - 71, 72, 73, 74, 1140, 2514, 2515, 422, - 75, 2518, -1594, 556, 557, 2522, 2523, 2524, - 2525, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 422, 422, 422, 422, 422, 422, - 422, 422, 422, 422, 422, 422, 422, -2277, - -2277, -2277, -2277, -2277, 32767, 32767, -2279, -2279, - -2279, -2279, -2279, -2279, -2279, -2279, -2279, 86, - -2279, -2279, -2279, -2279, -2279, 87, -2279, -2279, - -2279, 88, -2279, -2279, -2279, -2279, -2279, 89, - 453, 453, 453, 453, 453, 453, 2609, 453, - 453, 453, 453, 453, 453, 453, 453, 453, - 453, 453, 453, 1817, 453, 453, 453, 453, - 453, 453, 453, 453, 32767, 32767, 32767, 681, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -2319, 2632, -2319, -2319, - -2319, 2636, 2637, 92, 2639, 2640, 95, 96, - 97, 98, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 3279, 3280, 3281, 3282, 3283, 3284, - 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, - -384, -1535, -385, -385, 0, 3298, 3299, 3300, - 3301, 3302, 3303, 3304, -8646, -1149, -1148, -1147, - -1146, 32767, 3310, 3311, 3312, 3313, 3314, -1140, - -1139, -1138, -1137, -1136, -1135, -1134, -1133, -1132, - 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, - 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, - 3340, 3341, 3342, 3343, 3344, -1327, -1327, -1327, - -1327, -1327, 32767, 32767, 2346, 32767, 32767, 32767, - 32767, 32767, 3350, 335, 3245, 8185, 1818, 666, - 1818, 795, 795, 1818, 1818, 1818, 1818, 1818, - -5945, 668, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 0, 0, 671, 671, 671, - 671, 671, 0, 0, 673, 673, 673, 0, - 674, 0, 675, 0, 676, 0, 677, 677, - 677, 32767, 0, 677, 677, -976, 3417, -974, - -973, 678, 678, -972, -971, -970, -969, -968, - 1152, 1153, 1154, 1155, 1156, 0, 1022, 1022, - 5615, -6335, 1162, 1163, 1164, 1165, 5621, 5622, - 5623, 5624, 5625, 5626, 1172, 1173, 1174, 1175, - 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, - 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, - 1192, 1193, 9997, 1195, 1196, 1197, 1198, 1199, - 1200, 1201, 1202, 1203, 1204, 4373, 4373, 4373, - 1208, 4374, 4374, 10601, 10602, 1213, 10604, 4612, - 4608, 10606, 10607, 12088, 1220, 1221, 1222, 1223, - 1224, 1225, 1226, 2453, 2454, 2455, 2456, 2457, - 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, - 2466, 2467, 6860, 2469, 2470, 2471, 2472, 2473, - 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, - 2482, 2483, 2484, 258, 2486, 2487, 258, 258, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -6806,68 +6797,63 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 5673, 5674, - 0, 5677, 0, 5680, 5681, 5682, 5683, 5684, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 682, 683, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -2719, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 105, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 2315, 4754, 2316, 2317, 2318, 2319, 2320, 2321, - 2322, 4762, 4763, 2323, 4765, 2324, 4767, 2325, - 2326, 4770, 4771, 4772, 2377, 4774, 4775, 4776, - 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, - 4785, 4786, 4787, 4788, 4789, 3417, 4791, 4792, - 2699, 2352, 4795, 683, 2833, 2834, 4799, 4800, - 4801, 4802, 2699, 2699, 2699, 2699, 2699, 2699, - 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, - 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, - 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, - 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, - 2699, 2699, 2699, 2699, 2699, 2699, 2699, 2699, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2365, 0, 0, 0, 0, 0, 2366, 0, - 0, 0, 2367, 0, 0, 0, 0, 0, - 2368, 2732, 2732, 2732, 2732, 2732, 2732, 4888, - 2732, 2732, 2732, 2732, 2732, 2732, 2732, 2732, - 2732, 2732, 2732, 2732, 4096, 2732, 2732, 2732, - 2732, 2732, 2732, 2732, 2732, 2732, 2732, 2732, - 2732, 2732, 2732, 2732, 2732, 2732, 2732, 2732, - 2732, 2732, 2732, 2732, 2732, 2732, 4927, 0, - 0, 0, 0, 0, 4933, 0, 0, 0, - 0, -2910, 0, 4940, 4941, 4942, 0, 0, - 0, 0, 0, 0, 0, 0, 4951, 0, - 0, 0, 4955, 4956, 2411, 4958, 4959, 2414, - 2415, 2416, 0, 10954, 0, 3436, 0, 0, - 0, 0, 0, -3170, -3169, -3168, -3167, 3446, - 2865, 0, 0, 0, 0, 0, 2339, 2339, - 2339, 2339, 2339, 2339, 2339, 2339, 2892, 2339, - 0, 0, 0, 0, 0, 0, 2907, 0, - 0, 0, 0, 0, 0, 4719, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 1856, 868, 868, 868, 868, - 868, 868, 868, 868, 868, 868, 868, 1856, - 1856, 1856, 1856, 1856, 873, 873, 873, 873, - 873, 873, 873, 873, 873, 873, 873, 873, - 873, 873, 873, 873, 873, 6441, 6442, 6443, - 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, - 6452, -1169, 6454, 6455, 6456, 6457, 6458, 6459, - 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, - 6468, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -6479, -6478, -6477, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 41, 42, 43, 44, 45, 46, + 32767, 32767, 47, 48, 49, 50, 51, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 52, 1131, 8054, 3425, -19247, + 8047, -19248,8049, -19249,8051, -14620,8053, -19240, + 8056, 3330, 8058, 8059, 3430, -19242,3330, 3330, + 3330, 3330, 3330, -11231,8049, 3330, 3330, 3330, + 3330, -3326, 33, -3326, 3330, -3325, -3325, -3325, + 3330, -3326, -3326, 1075, 4681, 4682, 8076, -3327, + 8079, 19509, -7787, 4688, 4689, 1331, 4691, -1964, + 4692, 4693, 4694, 4695, 4696, 4697, 297, -3308, + -3308, -6701, 4703, -6702, -18131,9166, -3308, 4711, + -2199, 4724, 95, -22577,4717, -22578,4719, -22579, + 4721, -17950,4723, -22570,4726, 0, 4728, 4729, + 100, -22572,0, 0, 0, 0, 0, -14561, + 4719, 0, 0, 0, 0, -6656, -3297, -6656, + 0, -6655, -6655, -6655, 0, -6656, -6656, -2255, + 1351, 1352, 4746, -6657, 4749, 16179, -11117,1358, + 1359, -1999, 0, 0, 0, 938, 0, 0, + 0, 0, 0, 0, 1255, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4081, 4081, 4081, + 4081, 4081, 2312, 2313, 2314, 553, 0, 0, + 0, 0, 0, 0, 0, 0, 3580, 2958, + 2958, 3580, -348, 2327, 2328, -1893, -347, -347, + -347, -347, -347, -347, -347, -347, -347, -347, + -347, -347, -347, -347, 0, 0, -345, 0, + -344, 0, 0, -342, -342, -342, -342, -342, + -342, -342, -342, -342, -342, 94, -341, 96, + -340, 98, 0, -338, -338, 0, 0, 0, + -335, -335, -335, -335, -335, -335, -335, -335, + -335, -335, -335, -335, -335, -335, -335, -335, + -335, -335, -335, -335, -335, -335, -335, -335, + -335, -335, -335, -335, -335, -335, -335, -335, + -335, -335, -335, -335, 0, 4203, -1710, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -6877,433 +6863,29 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 1, 32767, 2, 32767, 32767, 32767, 32767, -2759, + 32767, 32767, -2758, -2757, -2756, -2755, 32767, 32767, + -2754, -2753, -2752, 32767, -2751, -2750, -2749, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, -3334, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, -1362, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -766, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, -1530, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 686, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 687, 688, 689, 690, 691, 692, 693, 694, - 695, 2465, 697, 698, 699, 700, 701, 702, - 703, 704, 705, 2484, 707, 708, 709, 710, - 2493, 712, 713, 714, 715, 2502, 717, 718, - 719, 720, 2511, 722, 723, 724, 725, 726, - 727, 728, 729, 730, 731, 732, 733, 2536, - 735, 736, 737, 738, 739, 740, 741, 742, - 743, 2555, 745, 2558, 2559, 2560, 2561, 2562, - 751, 752, 753, 754, 755, 756, 757, 2577, - 759, 760, 761, 762, 763, 764, 1224, 1224, - 767, 768, 769, 770, 3787, 772, 773, 774, - 775, 776, 777, 778, 779, 780, 781, 782, - 783, 784, 785, 786, 787, 788, 789, 790, - 791, 792, 793, 794, 795, 796, 797, 798, - 799, 800, 801, 802, 803, 804, 805, 806, - 807, 808, 809, 810, 811, 812, 813, 814, - 815, 816, 817, 818, 819, 820, 821, 822, - 823, 824, 825, 826, 827, 828, 829, 830, - 831, 832, 833, 834, 835, 836, 837, 838, - 839, 840, 841, 842, 843, 844, 845, 846, - 847, 848, 849, 850, 851, 852, 853, 854, - 855, 856, 857, 858, 859, 860, 861, 862, - 863, 864, 865, 866, 867, 868, 869, 870, - 871, 872, 873, 874, 875, 876, 877, 878, - 879, 880, 881, 882, 883, 884, 885, 886, - 887, 888, 889, 890, 891, 892, 893, 894, - 895, 896, 897, 898, 899, 900, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 682, + 683, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 901, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, -1268, - 32767, 32767, 32767, 32767, 32767, -984, -984, -2101, - -2101, -2101, -2101, 32767, 3402, 3403, -985, -985, - 32767, 32767, 0, -986, -986, -986, -986, -986, - -986, -986, 32767, -987, -987, -987, -987, -987, - -987, -987, 32767, -988, -988, -988, -988, -1746, - -988, -1747, -1747, -1194, -988, -988, -988, -988, - -988, -988, -988, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 32767, - 0, 0, 0, 321, 32767, 0, 0, 0, - 0, 0, 32767, 0, 32767, 32767, 32767, -968, - 0, 0, 0, 0, 0, 0, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 333, 113, 333, 2915, - 333, 333, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -934, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -361, 122, - 0, 0, 0, 0, 0, 0, 0, 0, - -4348, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 123, 0, 0, 0, 0, -3819, -3818, 32767, - 126, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 5367, 5368, 914, 915, 916, - 917, 918, 919, 920, 921, 922, 923, 924, - 925, 926, 927, 928, 929, 930, 931, 932, - 933, 934, 935, 9739, 937, 938, 939, 940, - 941, 942, 943, 944, 945, 946, 4115, 4115, - 4115, 950, 4116, 4116, 10343, 10344, 955, 10346, - 4354, 4350, 10348, 10349, 11830, 962, 963, 964, - 965, 966, 967, 968, 2195, 2196, 2197, 2198, - 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, - 2207, 2208, 2209, 6602, 2211, 2212, 2213, 2214, - 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, - 2223, 2224, 2225, 2226, 0, 2228, 2229, 0, - 0, 2232, 0, 129, 2235, 2236, -260, -260, - 2239, 2240, 2241, 2242, -260, 2244, 2245, 2246, - 2247, 2248, 2249, 2250, 2251, 2252, 2253, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, 2264, 2265, -2259, 2267, 2268, 2269, 2270, - 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, - -2729, 2280, 2281, 2282, 2283, 2284, 2285, 2286, - 2287, 2288, 2289, 2290, 2291, 2292, 3281, 3282, - 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, - 3291, 2304, 2305, 2306, 2307, 2308, 3292, 3293, - 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, - 3302, 3303, 3304, 3305, 3306, 3307, 3308, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, -2259, -2259, 5363, -2259, -2259, -2259, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, 1418, 2570, 1421, 1422, 1038, -2259, -2259, - -2259, -2259, -2259, -2259, -2259, 9692, 2196, 2196, - 2196, 2196, -2259, -2259, -2259, -2259, -2259, -2259, - 2196, 2196, 2196, 2196, 2196, 2196, 2196, 2196, - 2196, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, -2259, -2259, - -2259, -2259, -2259, -2259, -2259, -2259, 2413, 2414, - 2415, 2416, 2417, 2418, 2419, 301, 302, 760, - -2259, -2259, -2259, -2259, 757, -2152, -7091, -723, - 430, -721, 303, 304, -718, -717, -716, -715, - -714, 7050, 438, 1020, 1020, 1020, 1020, 1020, - 1020, 1020, 1020, 1020, 1116, 1117, 447, 448, - 449, 450, 451, 1123, 1124, 452, 453, 454, - 1128, 455, 1130, 456, 1132, 457, 1134, 458, - 459, 460, 461, 1138, 462, 463, 2117, -2275, - 2117, 2117, 467, 468, 2119, 2119, 2119, 2119, - 2119, 0, 0, 0, 0, 0, 1157, 136, - 137, -4455, 7496, 0, 0, 0, 0, -4455, - -4455, -4455, -4455, -4455, -4455, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -8803, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -3168, -3167, - -3166, 0, -3165, -3164, -9390, -9390, 0, -9390, - -3397, -3392, -9389, -9389, -10869,0, 0, 0, - 0, 0, 0, 0, -1226, -1226, -1226, -1226, - -1226, -1226, -1226, -1226, -1226, -1226, -1226, -1226, - -1226, -1226, -1226, -5618, -1226, -1226, -1226, -1226, - -1226, -1226, -1226, -1226, -1226, -1226, -1226, -1226, - -1226, -1226, -1226, -1226, 1001, -1226, -1226, 1004, - 1005, 1264, 1265, 32767, -1229, -1229, 1268, 1269, - -1229, -1229, -1229, -1229, 1274, -1229, -1229, -1229, - -1229, -1229, 139, 1281, 1282, 1283, 1284, 1285, - 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, - 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, - 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, - 1310, 1311, 1675, 1313, 1676, 1315, 1316, 1317, - 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, - 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, - 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, - 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, - 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, - 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, - 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, - 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, - 1382, 1383, 1384, 1385, 1386, 1387, 3934, 3935, - 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, - 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, - 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, - 1414, 1415, 1416, 1417, 1418, 935, 1320, 4618, - 1422, 4621, 4622, 1425, 1426, 1427, -7322, 5372, - 1430, 1431, 5375, 891, 891, 891, 891, 891, - 891, 891, 5376, 2037, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 891, 891, - 891, 891, 891, 891, 891, 891, 141, 891, - 891, 891, 891, 891, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 142, 143, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 1999, 4498, 4499, 4500, 4501, 1999, 4503, 4504, - 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4523, 4524, 0, 4526, 4527, 4528, - 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, - 4537, -470, 4539, 4540, 4541, 4542, 4543, 4544, - 4545, 4546, 4547, 4548, 4549, 4550, 4551, 5540, - 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, - 5549, 5550, 4563, 4564, 4565, 4566, 4567, 5551, - 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, - 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7622, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3677, 4829, 3680, 3681, 3297, 0, - 0, 0, 0, 0, 0, 0, 11951, 4455, - 4455, 4455, 4455, 0, 0, 0, 0, 0, - 0, 4455, 4455, 4455, 4455, 4455, 4455, 4455, - 4455, 4455, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4672, - 4673, 4674, 4675, 4676, 4677, 4678, 2560, 2561, - 3019, 0, 0, 0, 0, 3016, 107, -4832, - 1536, 2689, 1538, 2562, 2563, 1541, 1542, 1543, - 1544, 1545, 9309, 2697, 3279, 3279, 3279, 3279, - 3279, 3279, 3279, 3279, 3279, 3279, 3279, -1113, - 3279, 3279, 3279, 3279, 3279, 3279, 3279, 3279, - 3279, 3279, 3279, 3279, 3279, 3279, 3279, 1575, - 1576, 1577, 1578, 1579, -3910, 1581, 1582, 4736, - 4737, -4652, 4739, -1253, 6219, 4742, 4743, 6224, - 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, - 6233, -3419, 6235, 6236, 6237, 6238, 6239, 6240, - 6241, 6242, 6243, 3882, 3883, 3884, 3885, 3886, - 3887, 3888, -5177, 3891, 3892, -5177, 3893, 3894, - 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, - -5176, -5176, -5176, -5176, -5176, -5176, -5176, -5176, - 1640, 1641, 1642, 3924, 1644, 1645, 1646, 1647, - 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, - 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, - 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, - 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, - 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, - 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, - 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, - 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, - 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, - 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, - 1728, 1729, 1730, 1731, -847, -5786, 582, 1735, - 1736, 1609, 1610, 588, 1740, 591, 592, 593, - 8357, 1745, 2327, 2327, 2327, 2327, 2327, 2327, - 1357, 2328, 2328, 1755, 1756, 1757, 1758, 1759, - 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, - 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, - 1776, 1777, 1778, 1779, 1780, 3434, 1782, 3435, - 3435, 1785, 1786, 3437, 3437, 3437, 3306, 32767, - -2509, -2509, -2509, -2509, -2509, -2509, -2509, -2509, - -2509, 1800, -2508, -2508, -2508, -2508, 32767, 32767, - -2510, 32767, -2511, 32767, 32767, -2513, -2513, -2513, - -2513, -2513, -2513, 1813, 1814, 1815, 1816, 32767, - -2509, 32767, -2510, 32767, 32767, -2511, -2511, 32767, - 32767, 32767, -3871, -3871, -2513, -2513, -2513, -2513, - -2513, -2513, -2513, -2513, -2513, -2513, -2513, -2513, - -2513, -2513, -2513, 1838, 1839, 1840, 1841, 1842, - 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, - 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, - 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, - 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, - 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, - 1883, 1401, 1885, 1886, 1887, 1888, 32767, 32767, - 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, - 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, - 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, - 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, - 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, - 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, - 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, - 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, - 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, - 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, - 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, - 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, - 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, - 3710, 1994, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 167, 612, 32767, 32767, 2714, 32767, - 32767, 32767, 32767, 32767, 168, 32767, 32767, 32767, - 32767, 169, 32767, 32767, 32767, 32767, 170, 32767, - 32767, 32767, 32767, 171, 32767, 32767, 32767, 32767, - 32767, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 172, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -1151, -127, -126, -1148, - -1147, 32767, 32767, 32767, 32767, 32767, 585, 32767, - 584, 584, 584, 584, 584, 584, 584, 584, - 584, -3808, 584, 584, 584, 584, 584, 584, - 584, 584, 584, 584, 584, 584, 584, 584, - 32767, -1121, -1120, -1119, -1118, -1117, 32767, -1116, - 32767, 2038, 2039, 32767, 2040, -3952, 32767, 2042, - 2043, 3524, 3525, 3526, 3527, 3528, 3529, 3530, - 3531, 3532, -385, -384, 2055, -383, -382, -381, - -380, -379, -378, -377, 2063, 2064, -376, 2066, - -375, 2068, -374, -373, 2071, 2072, 2073, -322, - 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, - 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, - 718, 2092, 2093, 0, -347, 2096, -2016, 134, - 135, 2100, 2101, 2102, 2103, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2156, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1364, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -4392, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2227, 0, 0, 2230, 2231, 0, - 2233, 2105, 0, 0, 2497, 2498, 0, 0, - 0, 0, 2503, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 4513, 4514, 4515, - 4516, 4517, 4518, 4519, 4520, 4521, 4522, 0, - 0, 4525, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5008, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -988, -988, -988, -988, - -988, -988, -988, -988, -988, -988, -988, 0, - 0, 0, 0, 0, -983, -983, -983, -983, - -983, -983, -983, -983, -983, -983, -983, -983, - -983, -983, -983, -983, -983, 4585, 4586, 4587, - 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, - 4596, -3025, 4598, 4599, 4600, 4601, 4602, 4603, - 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, - 4612, 4613, 4614, 4615, 4616, 4617, 4618, 942, - -209, 941, 941, 1326, 4624, 4625, 4626, 4627, - 4628, 4629, 4630, -7320, 177, 178, 179, 180, - 4636, 4637, 4638, 4639, 4640, 4641, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 4651, - 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, - 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, - 4668, 4669, 4670, 4671, 0, 0, 0, 0, - 0, 0, 0, 2119, 2119, 1662, 4682, 4683, - 4684, 4685, 1670, 4580, 9520, 3153, 2001, 3153, - 2130, 2130, 3153, 3153, 3153, 3153, 3153, -4610, - 2003, 1422, 1423, 1424, 1425, 1426, 1427, 1428, - 1429, 1430, 1431, 1432, 5825, 1434, 1435, 1436, - 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, - 1445, 1446, 1447, 1448, 3153, 3153, 3153, 3153, - 3153, 8643, 3153, 3153, 0, 0, 9390, 0, - 5993, -1478, 0, 0, -1480, -1480, -1480, -1480, - -1480, -1480, -1480, -1480, -1480, 2438, 2438, 0, - 2439, 2439, 2439, 2439, 2439, 2439, 2439, 0, - 0, 2441, 0, 2442, 0, 2443, 2443, 0, - 0, 0, 2396, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1373, 0, 0, 2094, 2442, - 0, 4113, 1964, 1964, 0, 0, 0, 0, - 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, - 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, - 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, - 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, - 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, - 2144, 2145, 2146, 2147, 2148, 2149, 4849, 4850, - 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, - 4859, 4860, 4861, 4862, 4863, 4864, 2500, 4866, - 4867, 4868, 4869, 4870, 2505, 4872, 4873, 4874, - 2508, 4876, 4877, 4878, 4879, 4880, 2513, 2150, - 2151, 2152, 2153, 2154, 2155, 0, 2157, 2158, - 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, - 2167, 2168, 805, 2170, 2171, 2172, 2173, 2174, - 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, - 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, - 2191, 2192, 2193, 2194, 0, 4928, 4929, 4930, - 4931, 4932, 0, 4934, 4935, 4936, 4937, 7848, - 4939, 0, 0, 0, 4943, 4944, 4945, 4946, - 4947, 4948, 4949, 4950, 0, 4952, 4953, 4954, - 0, 0, 2546, 0, 0, 2546, 2546, 2546, - 4963, -5990, 4965, 1530, 4967, 4968, 4969, 4970, - 4971, 8142, 8142, 8142, 8142, 1530, 2112, 4978, - 4979, 4980, 4981, 4982, 2644, 2645, 2646, 2647, - 2648, 2649, 2650, 2651, 2099, 2653, 4993, 4994, - 4995, 4996, 4997, 4998, 2092, 5000, 5001, 5002, - 5003, 5004, 5005, 287, 5007, 5008, 32767, 5009, - 5010, 5011, 5012, -2457, 5014, -2456, 5016, 5017, - 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, - 5026, 5027, 5028, -4624, 5030, 5031, 5032, 5033, - 5034, 5035, 5036, 5037, 5038, 2677, 2678, 2679, - 2680, 2681, 2682, 2683, 2684, 2685, 2686, -6383, - 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, - 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, - 2703, 2704, 2705, 32767, 2706, 2707, 2708, 2709, - 32767, 32767, 32767, 32767, 2710, 4682, 4683, 32767, - 2713, 32767, 2714, 906, 907, 908, 909, 2719, - 2720, 910, 2722, 2723, 2724, 2725, 2726, 2727, - 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, - 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, - 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, - 2752, 2753, 2974, 2755, 174, 2757, 2758, 2759, - 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, - 2768, 2769, 2770, 6689, 6690, 6691, 2774, 2775, - 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, - 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, - 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, - 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, - 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, - 2816, 5259, 2818, 3298, 3299, 2821, 2822, 2823, - 2824, 2825, 2826, 3170, 2828, 2829, 2830, 2831, - 2832, 2833, 2834, 3177, 3177, 3177, 3177, 3177, - 3177, 2841, 2842, 2843, 2844, 2845, 2846, 2847, - 2848, 32767, 32767, 32767, 32767, 32767, 2849, 2850, - 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, - 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, - 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, - 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, - 2883, -1495, 2885, 2886, 4004, 4005, 4006, 4007, - 4008, -1495, -1495, 2894, 2895, -1495, -1495, 2898, - 2899, 2900, 2901, 2902, 2903, 2904, 2905, -1494, - 2907, 2908, 2909, 2910, 2911, 2912, 2913, -1494, - 2915, 2916, 2917, 2918, 3677, 2920, 3680, 3681, - 3129, 2924, 2925, 2926, 2927, 2928, 2929, 2930, - 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, - 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, - 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, - 2955, 2956, -1468, -1468, 2959, 2960, 2961, 2962, - 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, - 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, - 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, - 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, - 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, - 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, - 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, - 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, - 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, - 3035, 3036, 3037, 3038, 32767, 32767, 32767, 3039, - 3040, 3041, 3042, 3043, 3044, 32767, 32767, 3045, - 3046, 3047, 3048, 3049, 3050, 32767, 32767, 3051, - 3052, 3053, 3054, 3055, 3056, 32767, 32767, 3057, - 3058, 3059, 32767, 32767, 32767, 3060, 3061, 3062, - 3063, 3064, 3065, 3066, 32767, 3067, 3068, 3069, - 3070, 3071, 3072, 3073, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7311,6 +6893,16 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 4205, 4206, 4207, + 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, + 4216, -4880, 4218, 5470, -4882, 4221, 4222, 4223, + 4224, 4225, 4226, 4227, 4228, 1009, 4230, 4231, + 1007, 4233, 4234, 4250, 4250, 4250, 4238, 4239, + 4240, 4253, 4253, 4243, 4244, 4245, 4246, 4247, + 4248, 4249, 4250, 4251, 4252, 4253, 4254, 353, + 7010, 3652, 4258, 4259, 7011, 4261, 4262, 4263, + 4264, 4265, 4266, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 105, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7318,38 +6910,411 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 2834, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -2302, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 0, 0, 0, 32767, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 0, 0, 32767, 0, 32767, 32767, 0, - 32767, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 32767, 0, 0, 0, 0, - 32767, 0, 32767, 0, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -2356, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 0, - 32767, 0, 32767, 0, 32767, 0, 0, 0, - 32767, 0, 0, 32767, 0, 32767, 32767, 0, - 32767, 0, 32767, 0, 32767, 0, 32767, 0, - 32767, 0, 0, 32767, 0, 32767, 32767, 0, - 0, 0, 0, 32767, 0, 0, 0, 0, - 0, 0, 0, 32767, 0, 0, 0, 0, - 32767, 0, 0, 0, 0, 32767, 0, 32767, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32767, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, - 32767, 0, 0, 0, 32767, 0, 0, 0, - 0, 0, 32767, -1358, -1358, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, -4130, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -48, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 299, 32767, 300, 301, -2381, -2381, -2381, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -2388, 32767, + 32767, -4398, -4398, -4398, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -17740,32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 4825, 32767, 32767, 32767, 32767, -4293, + 32767, 32767, 32767, 109, -5804, 111, 112, 32767, + 32767, -4301, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -2438, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 685, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -20069,32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 3994, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, -6790, -6790, + 157, -3219, -17570,-1719, -1719, -3027, -3027, -19414, + -3027, -9665, -3028, -3028, -3028, -3028, -3028, 4977, + 577, -3028, -3028, -6421, 4983, -6422, -17851,9446, + -3028, -3028, 331, -3028, 3628, -3027, -3027, -3027, + -3027, -3027, -3027, 1374, 4980, 4981, 8375, -3028, + 8378, 19808, -7488, 4987, -3031, 3880, -3042, 1588, + 24261, -3032, 24264, -3032, 24267, -3032, 19640, -3032, + 24262, -3033, 1694, -3033, -3033, 1597, 24270, 1699, + 1700, 1701, 1702, 1703, 16265, -3014, 1706, 1707, + 1708, 1709, 8366, 5008, 8368, 1713, 8369, 8370, + 8371, 1717, 8374, 8375, 3975, 370, 370, -3023, + 8381, -3024, -14453,12844, 370, 8389, 1479, 8402, + 3773, -18899,8395, -18900,8397, -18901,8399, -14272, + 8401, -18892,8404, 3678, 8406, 8407, 3778, -18894, + 3678, 3678, 3678, 3678, 3678, -10883,8397, 3678, + 3678, 3678, 3678, -2978, 381, -2978, 3678, -2977, + -2977, -2977, 3678, -2978, -2978, 1423, 5029, 5030, + 8424, -2979, 8427, 19857, -7439, 5036, 5037, 1679, + 5039, -1616, 5040, 5041, 5042, 5043, 5044, 5045, + 645, -2960, -2960, -6353, 5051, -6354, -17783,9514, + -2960, 5059, -1851, 5072, 443, -22229,5065, -22230, + 5067, -22231,5069, -17602,5071, -22222,5074, 348, + 5076, 5077, 448, -22224,348, 348, 348, 348, + 348, -14213,5067, 348, 348, 348, 348, -6308, + -2949, -6308, 348, -6307, -6307, -6307, 348, -6308, + -6308, -1907, 1699, 1700, 5094, -6309, 5097, 16527, + -10769,1706, 1707, -1651, 348, 348, 348, 1286, + 348, 348, 348, 348, 348, 348, 1603, 348, + 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 4429, + 4429, 4429, 4429, 4429, 2660, 2661, 2662, 901, + 348, 348, 348, 348, 348, 348, 348, 348, + 3928, 3306, 3306, 3928, 0, 2675, 2676, 2677, + 2678, 0, 2680, 0, 0, 2683, 2684, 2685, + 2686, 4556, 2687, 2688, 2689, 8575, 2691, 2692, + -9266, -9266, -4636, 18037, -9256, 18040, -9256, 18043, + 18044, 13415, -9257, 18037, -9258, 18039, -9259, -9259, + -4629, 18044, 4581, 4582, 4583, -2184, -4527, 10035, + -9244, -2185, -4524, 4590, -4523, 2134, -1224, 2717, + 4595, 2719, 2720, 4598, 6107, 6107, 6107, 2725, + 2726, 2727, 4605, 2729, 2730, 2731, 4609, 2736, + 4611, 4612, 4613, 6118, 6118, 4616, 6119, 2743, + 4619, 4620, 2744, 2745, 6123, 2747, 6124, 4626, + 4627, 4628, 4629, 2753, 4631, 2755, 4633, 8896, + 8897, 8898, 4637, 4638, 4639, 4640, 0, 0, + 0, 0, 0, -1812, 0, 0, 0, 8925, + 0, 0, 1330, -3389, 0, 0, 0, 8940, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10649, 8068, 0, 0, 16017, 8807, 8808, -1676, + 906, 8811, -7039, -7038, 173, 173, 10658, 8077, + 173, 16024, 16024, 8814, 8815, -1669, 913, 8818, + -7032, -7031, 180, 180, 10665, 8084, 180, 16031, + 16031, 8821, 8822, -1662, 920, 8825, 9014, -7023, + 188, 188, 10673, 8092, 188, 0, 16038, 8828, + 8829, -1655, 927, 8832, 4727, 4728, 4729, 4730, + 4305, 4732, 4733, 4734, 4735, 4736, 4737, 4738, + 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, + 4747, 4748, 1540, 1540, 1540, 1540, 1540, 1540, + 1540, 1540, 1540, 1540, 1540, -1893, 1540, 1540, + 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, + 1540, 1540, 1540, 1540, 1540, 1540, 1540, 1540, + 1540, 1540, 1540, 1540, 1540, 1540, 911, 1540, + 4614, 4615, 4616, 4617, 4618, 1540, 4619, 4620, + 4621, 4622, 4623, 4624, 4625, 4626, 4627, -7592, + 11688, 4630, 4631, 4632, 4633, 4634, 4635, 32767, + 4810, 4811, 4812, 4813, 3850, 3851, 4816, 4817, + 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, + 4573, 4573, 4573, 4573, 4830, 4574, 4574, 4574, + 4834, 4575, 4575, 4575, 4575, 4575, 917, 918, + 4575, 4575, 4575, 4575, 923, 4576, 4576, 926, + 927, 928, 7709, 930, 931, 932, 933, 934, + 7717, 936, 7719, 938, 7722, 940, 941, 942, + 943, 944, 945, 946, 7733, 948, 949, 950, + 951, 952, 953, 954, 955, 956, 957, 958, + 959, 960, 961, 962, 963, 964, 965, 4765, + 967, 968, 969, 970, 971, 972, 973, 974, + 975, 976, 977, 978, 4902, 4903, -2043, 1334, + 15686, -164, -163, 1146, 1147, 17535, 1149, 7788, + 1152, 1153, 1154, 1155, 1156, -6848, -2447, 1159, + 1160, 4554, -6849, 4557, 15987, -11309,1166, 7797, + 7798, 7799, -5489, 1167, 1168, 1169, 1170, 1171, + 1172, -3228, -6833, -6833, -10226,1178, -10227,-21656, + 7812, 7813, 7814, 7815, 7816, 4951, 7817, 7818, + 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, + 4962, 7837, 4964, 4965, 4966, 4967, 4968, 4969, + 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, + 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, + 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, + 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, + 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, + 5010, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, -224, -224, -224, -6880, -3521, -6880, -224, + -6879, -6879, -6879, -6879, -6879, -6879, -2478, 1128, + 1129, 4523, -6880, 4526, 15956, -11340,1135, -6883, + 28, -6894, -2264, 20409, -6884, 20412, -6884, 20415, + 20416, 15787, -6885, 20409, -6886, -2159, -6886, -6886, + -2256, 20417, -2154, -2153, -2152, -2151, -2150, 12412, + -6867, -2147, -2146, -2145, -2144, 4513, 1155, 4515, + -2140, 4516, 4517, 4518, -2136, 4521, 4522, 122, + -3483, -3483, -6876, 4528, -6877, -18306,8991, -3483, + -3483, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -3490, 911, 4517, 4518, 7912, -3491, 7915, + 19345, -7951, 4524, -3494, 3417, -3505, 1125, 23798, + -3495, 23801, -3495, 23804, -3495, 19177, -3495, 23799, + -3496, 1231, -3496, -3496, 1134, 23807, 1236, 1237, + 1238, 1239, 1240, 15802, -3477, 1243, 1244, 1245, + 1246, 7903, 4545, 7905, 1250, 7906, 7907, 7908, + 7909, 7910, 7911, 3511, -94, -94, -3487, 7917, + -3488, -14917,12380, -94, 7925, 1015, 7938, 3309, + -19363,7931, -19364,7933, -19365,7935, -14736,7937, + -19356,7940, 3214, 7942, 7943, 3314, -19358,3214, + 3214, 3214, 3214, 3214, -11347,7933, 3214, 3214, + 3214, 3214, -3442, -83, -3442, 3214, -3441, -3441, + -3441, 3214, -3442, -3442, 959, 4565, 4566, 7960, + -3443, 7963, 19393, -7903, 4572, 4573, 1215, 4575, + -2080, 4576, 4577, 4578, 4579, 4580, 4581, 181, + -3424, -3424, -6817, 4587, -6818, -18247,9050, -3424, + 4595, -2315, 4608, -21, -22693,4601, -22694,4603, + -22695,4605, -18066,4607, -22686,4610, -116, 4612, + 4613, -16, -22688,-116, -116, -116, -116, -116, + -14677,4603, -116, -116, -116, -116, -6772, -3413, + -6772, -116, -6771, -6771, -6771, -116, -6772, -6772, + -2371, 1235, 1236, 4630, -6773, 4633, 16063, -11233, + 1242, -6776, 135, -6787, -2157, 20516, -6777, 20519, + -6777, 20522, -6777, 15895, -6777, 20517, -6778, -2051, + -6778, -6778, -2148, 20525, -2046, -2045, -2044, -2043, + -2042, 12520, -6759, -2039, -2038, -2037, -2036, 4621, + 1263, 4623, -2032, 4624, 4625, 4626, -2028, 4629, + 4630, 230, -3375, -3375, -6768, 4636, -6769, -18198, + 9099, -3375, -3375, -16, -3375, 3281, -3374, -3374, + -3374, -3374, -3374, -3374, 1027, 4633, 4634, 8028, + -3375, 8031, 19461, -7835, 4640, -3378, 3533, -3389, + 1241, 23914, -3379, 23917, -3379, 23920, -3379, 19293, + -3379, 23915, -3380, 1347, -3380, -3380, 1250, 23923, + 1352, 1353, 1354, 1355, 1356, 15918, -3361, 1359, + 1360, 1361, 1362, 8019, 4661, 8021, 1366, 8022, + 8023, 8024, 1370, 8027, 8028, 3628, 23, 23, + -3370, 8034, -3371, -14800,12497, 23, 23, 3382, + 1384, 1385, 1386, 449, 1388, 1389, 1390, 1391, + 1392, 1393, 139, 1395, 1396, 1397, 1398, 1399, + 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, + 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, + 1416, 1417, 1418, -2662, -2661, -2660, -2659, -2658, + -888, -888, -888, 874, 1428, 1429, 1430, 1431, + 1432, 1433, 1434, 1435, -2144, -1521, -1520, -2141, + 1788, -886, -886, 3336, 1791, 1792, 1793, 1794, + 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, + 1803, 1804, 1458, 1459, 1805, 1461, 1806, 1463, + 1464, 1807, 1808, 1809, 1810, 1811, 1812, 1813, + 1814, 1815, 1816, 1381, 1817, 1381, 1818, 1381, + 1480, 1819, 1820, 1483, 1484, 1485, 1821, 1822, + 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, + 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, + 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, + 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, + 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, + 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, + 1871, 1872, 1873, 1874, 1875, 1876, 1877, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9097, 0, -1251, 9102, 0, + 0, 0, 0, 0, 0, 0, 0, 3220, + 0, 0, 3225, 0, 0, -15, -14, -13, + 0, 0, 0, -12, -11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3902, -2754, 605, 0, 0, -2751, 0, + 0, 0, 0, 0, 0, 1938, 1939, 1940, + 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, + 1949, 1950, 1951, 1530, 1443, 1532, 1533, 1956, + 1957, 1958, 1959, 1960, 1961, 1962, 141, 1964, + 1534, 1966, 1967, 1968, 1969, 1970, 1971, 1972, + 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, + 1981, 142, 143, 1984, 1985, 1986, 1987, 1988, + 1989, 1990, 1991, 1992, 1993, 1994, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 1665, 1996, 1997, + 1998, 1999, 2000, 2001, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 2002, 2003, 2004, 2005, 2006, 32767, 32767, 32767, + 32767, 32767, 2007, 32767, 2008, 2009, 2010, 2011, + 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, + -4501, -4501, -4501, -4501, -1422, -4500, -4500, -4500, + 2035, 2036, 32767, 1706, 32767, 1706, 1706, 32767, + 1705, 1705, 32767, 2042, 2043, 2044, 2045, 2046, + 2047, 1711, 2049, 1712, 2051, 4525, 4525, 4525, + 2055, 2056, 2057, 4528, 2059, 2060, 2061, 2062, + 2063, 2064, 2065, 7042, 2067, 4536, 4536, 4536, + 2071, 2072, 2073, 4539, 2075, 2076, 2077, 2078, + 2079, 2080, 2081, 2082, 2083, 2084, 1735, 1735, + 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, + 226, 227, 2097, 228, 229, 230, 6116, 232, + 233, -11725,-11725,-7095, 15578, -11715,15581, -11715, + 15584, 15585, 10956, -11716,15578, -11717,15580, -11718, + -11718,-7088, 15585, 2122, 2123, 2124, -4643, -6986, + 7576, -11703,-4644, -6983, 2131, -6982, -325, -3683, + 258, 2136, 260, 261, 2139, 3648, 3648, 3648, + 266, 267, 268, 2146, 270, 271, 272, -1029, + 32767, 32767, 32767, 32767, 6972, 2572, 32767, -1034, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -4286, + 32767, 32767, -2089, 32767, 3715, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -2492, -2492, -2492, -2492, -4304, -2492, -2492, -2492, + 6433, -2492, -2492, -1162, -5881, -2492, -2492, -2492, + 6448, -2492, -2492, -2492, -2492, -2492, -2492, -2492, + -2492, -2492, -2492, -2492, -2492, -2492, -2492, -2492, + -2492, 8157, 5576, -2492, -2492, 13525, 6315, 6316, + -4168, -1586, 6319, -9531, -9530, 32767, 2195, 2196, + 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, + 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, + 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, + 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, + 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, + 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, + 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, + 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, + 2261, 2262, -5075, 2264, 2265, 2266, 2267, 2268, + 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, + 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, + 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, + 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, + 2301, 2302, 2303, 1667, 1667, 2306, 2307, 2308, + 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, + 2317, 2318, 2319, 2320, 2321, 1358, 1359, 2324, + 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, + 2333, 2081, 2081, 2081, 2081, 2338, 2082, 2082, + 2082, 2342, 2083, 2083, 2083, 2083, 2083, -1575, + -1574, 2083, 2083, 2083, 2083, -1569, 2084, 2084, + -1566, -1565, -1564, 5217, -1562, -1561, -1560, -1559, + -1558, 5225, -1556, 5227, -1554, 5230, -1552, -1551, + -1550, -1549, -1548, -1547, -1546, 5241, -1544, -1543, + -1542, -1541, -1540, -1539, -1538, -1537, -1536, -1535, + -1534, -1533, -1532, -1531, -1530, -1529, -1528, -1527, + 2273, -1525, -1524, -1523, -1522, -1521, -1520, -1519, + -1518, -1517, -1516, -1515, -1514, 2410, 2411, -4535, + -1158, 13194, -2656, -2655, -1346, -1345, 15043, -1343, + 5296, -1340, -1339, -1338, -1337, -1336, -9340, -4939, + -1333, -1332, 2062, -9341, 2065, 13495, -13801,-1326, + 5305, 5306, 5307, -7981, -1325, -1324, -1323, -1322, + -1321, -1320, -5720, -9325, -9325, -12718,32767, 2451, + 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, + 2460, 2461, 2462, 2463, 2464, 2465, -6169, 4316, + 1735, -6169, 9682, 9682, 2472, 2473, -8011, -5429, + 2476, -13374,-13373,2479, 2480, 2481, 2482, 2483, + 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, + 2492, 2493, 2494, 2495, 2496, 2497, 2498, 203, + 1141, 203, 203, 203, 203, 203, 203, 1458, + 203, 2509, 2510, 2511, 2512, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 155, 32767, 32767, 32767, + 32767, 156, 32767, 32767, 32767, 32767, 157, 207, + 4288, 4288, 4288, 4288, 4288, 2519, 2520, 2521, + 760, 207, 207, 207, 207, 207, 207, 207, + 207, 3787, 3165, 3165, 2534, 2535, 2536, 2537, + 2538, 2539, -139, 2541, -139, -139, 2544, 2545, + 2546, 2547, 2548, 2549, 2550, 2551, 8437, 2553, + 2554, -9404, -9404, -4774, 17899, -9394, 17902, -9394, + 17905, 17906, 13277, -9395, 17899, -9396, -4669, -9396, + -9396, -4766, 17907, -4664, -4663, -4662, -4661, 0, + 32767, -9379, -4659, -4658, -4657, -4656, 2001, -1357, + 2584, 4462, 2586, 2587, 4465, 5974, 5974, 5974, + 2592, 2593, 2594, 4472, 2596, 2597, 2598, 4476, + 2603, 4478, 4479, 4480, 5985, 5985, 4483, 5986, + 2610, 4486, 4487, 2611, 2612, 5990, 2614, 5991, + 4493, 4494, 4495, 4496, 2620, 4498, 2622, 4500, + 8763, 8764, 8765, 4504, 4505, 4506, 4507, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8635, + -1849, 733, 8638, -7212, -7211, 0, 0, 10485, + 7904, 0, 15851, 15851, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2296, 1359, 2298, 2299, 2300, 2301, 2302, 2303, + 1049, 2305, 0, 0, 0, 0, 0, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 173, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 2306, -1774, -1773, -1772, -1771, -1770, 0, 0, + 0, 1762, 2316, 2317, 2318, 2319, 2320, 2321, + 2322, 2323, -1256, -633, -632, 0, 0, 0, + 0, 0, 0, 2679, 0, 2681, 2682, 0, + 0, 0, 0, 0, 0, 0, 0, -5885, + 0, 0, 11959, 11960, 7331, -15341,11953, -15342, + 11955, -15343,-15343,-10713,11960, -15333,11963, 7237, + 11965, 11966, 7337, -15335,7237, 7237, 7237, 7237, + 7237, -7324, 11956, 7237, 7237, 7237, 7237, 581, + 3940, 0, -1877, 0, 0, -1877, -3385, -3384, + -3383, 0, 0, 0, -1877, 0, 0, 0, + -1877, -3, -1877, -1877, -1877, -3381, -3380, -1877, + -3379, -2, -1877, -1877, 0, 0, -3377, 0, + -3376, -1877, -1877, -1877, -1877, 0, -1877, 0, + -1877, -6139, -6139, -6139, -1877, -1877, -1877, -1877, + 2764, 2765, 2766, 2767, 2768, 4581, 2770, 2771, + 2772, -6152, 2774, 2775, 1446, 6166, 2778, 2779, + 2780, -6159, 2782, 2783, 2784, 2785, 2786, 2787, + 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, + 2796, 2797, -7851, -5269, 2800, 2801, -13215,-6004, + -6004, 4481, 1900, -6004, 9847, 9847, 2637, 2638, + -7846, -5264, 2641, -13209,-13208,-5997, -5997, 4488, + 1907, -5997, 9854, 9854, 2644, 2645, -7839, -5257, + 2648, -13202,-13201,-5990, -5990, 4495, 1914, -5990, + -6178, 9860, 2650, 2651, -7833, -5251, 2654, 2843, + -13194,-5983, -5983, 4502, 1921, 32767, 32767, 32767, + 32767, 32767, 2849, 2850, 1029, 2852, 2422, 2854, + 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, + 2863, 2864, 2865, 2866, 2867, 2868, 2869, 1030, + 1031, 2872, 2873, 2874, 2875, 2876, 2877, 2878, + 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, + 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, + 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, + 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, + 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, + 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, + 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, + 2935, 2936, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 2958, + 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, + 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, + 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, + 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, + 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, + 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, + 3007, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 4471, + -2296, 212, 213, 214, 215, 216, 217, 218, + 219, 220, 221, 3568, 3035, 3036, 3037, 3038, + 32767, 32767, 32767, 3039, 3040, 3041, 3042, 3043, + 3044, 32767, 32767, 3045, 3046, 3047, 4565, 3049, + 4567, 32767, 32767, -1319, -1319, -1319, -1319, -1319, + -1319, 32767, 32767, -1321, -1321, 3059, 32767, 32767, + 32767, -1050, 3061, 3062, 3063, 3064, 3065, 3066, + 32767, 3067, 3068, 3069, 3070, 3693, 3694, 3073, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7357,17 +7322,68 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 0, 0, + 0, 32767, 0, 0, 0, 0, 32767, 32767, + 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 0, 0, 0, 0, 0, 0, 0, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, -3663, -3662, -3661, -3660, -3659, 0, 0, + -3656, -3655, -3654, -3653, 0, -3652, -3651, 0, + 0, 0, -6780, 0, 0, 0, 0, 0, + -6782, 0, -6782, 0, -6783, 0, 0, 0, + 0, 0, 0, 0, -6786, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -3799, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -3923, -3923, 3024, -352, + -14703,1148, 1148, -160, -160, -16547,-160, -6798, + -161, -161, -161, -161, -161, 7844, 3444, -161, + -161, -3554, 7850, -3555, -14984,12313, -161, -161, + 3198, -161, 6495, -160, -160, -160, -160, -160, + -160, 4241, 7847, 7848, 11242, -161, 11245, 22675, + -4621, 7854, -164, 6747, -175, 4455, 27128, -165, + 27131, -165, 27134, -165, 22507, -165, 27129, -166, + 4561, -166, -166, 4464, 27137, 4566, 4567, 4568, + 4569, 4570, 19132, -147, 4573, 4574, 4575, 4576, + 11233, 7875, 11235, 4580, 11236, 11237, 11238, 4584, + 11241, 11242, 6842, 3237, 3237, -156, 11248, -157, + -11586,15711, 3237, 11256, 4346, 11269, 6640, -16032, + 11262, -16033,11264, -16034,11266, -11405,11268, -16025, + 11271, 6545, 11273, 11274, 6645, -16027,6545, 6545, + 6545, 6545, 6545, -8016, 11264, 6545, 6545, 6545, + 6545, -111, 3248, -111, 6545, -110, -110, -110, + 6545, -111, -111, 4290, 7896, 7897, 11291, -112, + 11294, 22724, -4572, 4364, 4365, 32767, 4366, 4367, + 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, + 4376, 4377, 4378, 4379, 4380, 4381, 4382, 32767, + 32767, 32767, 32767, 32767, 4383, 4384, 4385, 32767, + 4386, 4387, 4388, 4389, 4390, 32767, 4391, 4392, + 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, + 4401, 4402, 4403, 4404, 4405, 4406, 4407, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, -847, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, -1078, -8000, -3370, 19303, + 32767, 19305, -7991, 19308, -7991, 14681, -7991, 19303, + 32767, 32767, -7994, 32767, -3365, 32767, -3264, -3263, + 32767, 32767, 32767, 32767, 32767, 32767, -3262, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 3394, 3395, + -3259, 3398, 3399, -1001, 32767, 32767, 32767, 32767, + -8004, -19433,32767, -4611, -4611, 32767, 32767, 32767, + 32767, 32767, 32767, -4616, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 6782, 18212, -9084, 3391, -4627, + 2284, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 5181, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, -1272, + 32767, 32767, 32767, 32767, 32767, -851, 32767, 32767, + 0, 88, 0, 0, 32767, 32767, 32767, 89, + 90, 32767, 91, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7376,8 +7392,12 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 434, 435, 0, 436, 0, + 437, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 434, 435, 436, 32767, 437, + 438, 32767, 32767, 32767, 439, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7392,23 +7412,20 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, -2069, 32767, 32767, -2071, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, -2105, -2105, 32767, 32767, -2107, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4645, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + -1906, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 256, - 257, 258, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7416,92 +7433,112 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 4408, 4409, + 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4417, + 4418, 32767, 32767, 32767, 32767, 32767, 4419, 4420, + 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, + 20816, 4430, 4431, 4432, 4433, 4434, 4435, 4436, + -3568, 833, 4439, 4440, 7834, -3569, 7837, 19267, + -8029, 4446, 4447, 1089, 4449, -2206, 4450, 4451, + 4452, 4453, 4454, 4455, 55, -3550, 4458, -6944, + 4460, 4461, -18375,4463, 4464, 4465, 4466, 4477, + -152, -22824,4470, -22825,4472, -22826,4474, -18197, + 4476, 4477, 4478, -248, 4480, 4481, 32767, -22821, + 32767, -250, 32767, 32767, 32767, 32767, 32767, 32767, + -256, 32767, 32767, 32767, 32767, -6916, 32767, -6916, + 32767, -6917, 32767, -6919, -6919, -2518, 32767, 1088, + 4482, 4483, 4484, 32767, 32767, 1091, 32767, -17, + 32767, -2310, 32767, -6931, 32767, -6932, 32767, -6933, + 15739, 32767, 20360, 32767, 32767, -6937, -6937, -2307, + 20366, 32767, -2205, -2204, -2203, -2202, 12360, -6919, + -2199, 32767, -2198, -2197, 4460, 1102, 4485, -2194, + 4462, 4463, 4464, 32767, 4466, 32767, 66, -3539, + -3539, -6932, 4472, -6933, -18362,8935, 0, 0, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 0, + 0, 0, 32767, 0, 0, 0, 0, 0, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 4486, + 4487, 4488, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4489, + 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, + 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, + 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, + 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, + 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, + 4530, 4531, 4532, 32767, 32767, 32767, 32767, 4533, + 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4542, + 4543, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -1593, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 32767, 32767, 0, 32767, + 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 4210, 4211, 4212, 4213, 32767, - 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, - 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, - 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, - 4238, 4239, 4240, 32767, 4241, 4242, 32767, 4243, - 32767, 32767, 4244, 32767, 4245, 4246, 4247, 4248, - 4249, 4250, 4251, 4252, 4253, 4254, 32767, 4255, - 4256, 4257, 4258, 32767, 4259, 32767, 4260, 32767, - 32767, 32767, 32767, 32767, 32767, 4261, 32767, 32767, - 32767, 32767, 4262, 32767, 4263, 32767, 4264, 32767, - 4265, 4266, 4267, 32767, 4268, 4269, 32767, 4270, - 32767, 32767, 4271, 32767, 4272, 32767, 4273, 32767, - 4274, 32767, 4275, 32767, 4276, 4277, 32767, 4278, - 32767, 32767, 4279, 4280, 4281, 4282, 32767, 4283, - 4284, 4285, 4286, 4287, 4288, 4289, 32767, 4290, - 4291, 4292, 4293, 32767, 4294, 4295, 4296, 4297, - 32767, 4298, 32767, 4299, 4300, 4301, 4302, 4303, - 4304, 4305, 4306, 4307, 4308, 0, 4309, 4310, - 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, - 4319, 4320, 4321, 4322, 4323, 4324, 4325, 0, - 0, 0, 0, 32767, 4326, 4327, 4328, 32767, - 4329, 4330, 4331, 4332, 4333, 32767, 5692, 5693, - 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, - 4344, 4345, 4346, 4347, 4348, 4349, 4350, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 483, 0, 0, - 0, 0, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7338, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 637, + 638, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 964, 964, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 253, 254, 255, + 256, 0, 257, 258, 259, 0, 260, 261, + 262, 263, 264, 3923, 3923, 267, 268, 269, + 270, 3923, 271, 272, 3923, 3923, 3923, -2857, + 3923, 3923, 3923, 3923, 3923, -2859, 3923, -2859, + 3923, -2860, 3923, 3923, 3923, 3923, 3923, 3923, + 3923, -2863, 3923, 3923, 3923, 3923, 3923, 3923, + 3923, 3923, 3923, 3923, 3923, 3923, 3923, 3923, + 3923, 3923, 3923, 3923, 124, 3923, 3923, 3923, + 3923, 3923, 3923, 3923, 3923, 3923, 3923, 3923, + 3923, 0, 0, 6947, 3571, -10780,5071, 5071, + 3763, 3763, -12624,3763, -2875, 3762, 3762, 3762, + 3762, 3762, 11767, 7367, 3762, 3762, 369, 11773, + 368, -11061,16236, 3762, -2868, -2868, -2868, 10421, + 3766, 3766, 3766, 3766, 3766, 3766, 8167, 11773, + 11774, 15168, 3765, 15171, 26601, -2866, -2866, -2866, + -2866, -2866, 0, -2865, -2865, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -2874, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1717, 0, 32767, 32767, + 0, 0, 0, 0, 0, 0, 5011, 5012, + 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, + 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, + 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, + 5037, 5038, 5039, 5040, 5041, 5042, 5267, 5268, + 5269, 11926, 8568, 11928, 5273, 11929, 11930, 11931, + 11932, 11933, 11934, 7534, 3929, 3929, 536, 11940, + 535, -10894,16403, 3929, 11948, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1769, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -1778, 0, 0, - 0, 0, -1782, 0, 0, 0, 0, -1786, - 0, 0, 0, 0, -1790, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1802, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -1811, 0, -1812, -1812, -1812, - -1812, -1812, 0, 0, 0, 0, 0, 0, - 0, -1819, 0, 0, 0, 0, 0, 0, - -459, -458, 0, 0, 0, 0, -3016, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 32767, 32767, 32767, 32767, 32767, 32767, 0, 32767, - 0, 32767, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7509,94 +7546,69 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, + 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, + 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, + 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, + 3416, 3417, 3418, 10075, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 223, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4379, - 0, 0, -1117, -1117, -1117, -1117, -1117, 4387, - 4388, 0, 0, 4391, 4392, 0, 0, 0, - 0, 0, 0, 0, 0, 4400, 0, 0, - 0, 0, 0, 0, 0, 4408, 0, 0, - 0, 0, -758, 0, -759, -759, -206, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4425, 4426, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32767, 32767, 32767, 0, 0, 0, - 0, 0, 0, 32767, 32767, 0, 0, 0, - 0, 0, 0, 32767, 32767, 0, 0, 0, - 0, 0, 0, 32767, 32767, 0, 0, 0, - 32767, 32767, 32767, 0, 0, 0, 0, 0, - 0, 0, 32767, 0, 0, 0, 0, 0, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4429, - 4430, 4431, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 4432, - 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, - 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, - 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, - 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, - 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, - 4473, 4474, 4475, 32767, 32767, 32767, 32767, 4476, - 4477, 4478, 4479, 4480, 4481, 539, 540, 4484, - 0, 0, 0, 0, 0, 0, 0, 4485, - 1146, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -3433, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -629, 0, 3074, 3075, 3076, 3077, 3078, + 0, 3079, 3080, 3081, 3082, 3083, 3084, 3085, + 3086, 3087, -9132, 10148, 3090, 3091, 3092, 3093, + 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, + 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, + 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, + 3118, 3119, 3120, 6777, 3121, 3122, 3123, 3124, + 3125, 3126, 3127, 3128, 3129, 6780, 0, 6780, + 6780, 6780, 0, 0, 0, 6782, 0, 0, + 0, 0, 6784, 0, 6785, 0, 6786, 6786, + 0, 6786, 0, 6787, 6787, 6787, 0, 6788, + 6788, 6788, 6788, 6788, 6788, 6788, 0, 6789, + 6789, 6789, 6789, 2990, 6789, 0, 0, 0, + 0, 6793, 6793, 6793, 6793, 6793, 0, 0, + 0, 0, 0, 0, -7904, 7947, 7947, 6639, + 6639, -9748, 32767, 0, 6637, 32767, 32767, 6635, + 32767, 32767, 10238, 6633, 32767, 32767, 14642, 3237, + -8192, 19105, 32767, 0, 0, 0, 13289, 6634, + 6634, 6634, 6634, 6634, 6634, 11035, 14641, 32767, + 18035, 32767, 18037, 29467, 0, 0, 0, 0, + 0, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -750, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6227, - 6228, -3161, 6230, 238, 234, 6232, 6233, 7714, - 7715, 7716, 7717, 7718, 7719, 7720, 7721, 7722, - 7723, -1929, 7725, 7726, 7727, 7728, 7729, 7730, - 7731, 7732, 7733, 5372, 5373, 5374, 5375, 5376, - 5377, 5378, -3687, 5381, 5382, -3687, 5383, 5384, - 5385, 5386, 5387, 5388, 5389, 5390, 5391, -3687, - -3687, -3687, -3687, -3687, -3687, -3687, -3687, -3687, - 3129, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, -3700, 32767, 32767, + 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 285, -3734, -3734, 288, 289, -3734, -3734, -3734, - -3734, -3734, -3734, -3734, -3734, -3734, -3734, -3734, - -3734, 1547, -956, -956, -3734, -3734, -3734, 3440, - -3734, -3734, -3734, -3734, -3734, -3734, -3734, -3734, - -3734, -3734, -3734, -3734, -3734, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7624,128 +7636,23 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 322, 323, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 0, 0, + 0, 0, 0, 32767, 32767, 0, 0, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 114, 115, 116, 117, 118, 119, 120, - 121, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 32767, 32767, 32767, 32767, 0, - 0, 0, 0, 0, 0, 3943, 3943, 0, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 3340, 32767, 325, 32767, 326, 32767, 327, 32767, - 328, 32767, 329, 32767, 330, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 331, 32767, 332, 333, 334, 335, - 336, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 337, 32767, 338, 32767, 339, 340, 341, 32767, - 32767, 32767, 342, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 343, 32767, 344, 345, 346, 32767, - 32767, 32767, 347, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 348, 32767, 349, 350, 351, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 352, 32767, 353, 32767, 354, 355, 32767, 32767, - -1816, -1816, -1816, -1816, -1816, -1816, -1816, -1816, - -1816, -1816, -1816, 32767, 32767, 32767, 32767, 32767, - 32767, -1822, 32767, 32767, 32767, 32767, 32767, 368, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 369, 370, 371, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 372, - 32767, 32767, 32767, 373, 374, 32767, 375, 376, - 32767, 32767, 32767, 32767, 6367, 0, -1152, 0, - -1023, -1023, 0, 0, 0, 0, 0, -7763, - -1150, -1731, -1730, -1729, -1728, -1727, -1726, -1725, - -1724, -1723, -1722, -1721, 2672, -1719, -1718, -1717, - -1716, -1715, -1714, -1713, -1712, -1711, -1710, -1709, - -1708, -1707, -1706, -1705, 0, 0, 0, 0, - 0, 5490, 0, 0, -3153, -3153, 6237, -3153, - 2840, -4631, -3153, -3153, -4633, -4633, -4633, -4633, - -4633, -4633, -4633, -4633, -4633, -4633, 5020, -4633, - -4633, -4633, -4633, -4633, -4633, -4633, -4633, -4633, - -2271, -2271, -2271, -2271, -2271, -2271, -2271, 6795, - -2272, -2272, 6798, -2271, -2271, -2271, -2271, -2271, - -2271, -2271, -2271, -2271, -2271, 6808, 6809, 6810, - 6811, 6812, 6813, 6814, 6815, 0, 0, 0, - -2281, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2579, 7519, 1152, 0, 0, 128, 128, - 1151, 0, 1150, 1150, 1150, -6613, 0, -581, - -580, -579, -578, -577, -576, 395, -575, -574, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1653, 0, -1652, -1651, 0, 0, - -1650, -1649, -1648, -1516, -1647, 473, 474, 475, - 476, 477, 32767, 32767, 32767, 32767, -7018, 479, - 480, 481, 482, 32767, 32767, 32767, 32767, 32767, - 32767, 483, 484, 485, 486, 487, 488, 489, - 490, 491, 492, 493, 494, 495, 496, 497, - 498, 499, 500, 501, 502, 503, 504, 9308, - 506, 507, 508, 509, 510, 511, 512, 513, - 514, 515, 3684, 3684, 3684, 519, 3685, 3685, - 9912, 9913, 524, 9915, 3923, 3919, 9917, 9918, - 11399, 0, 11402, 11403, 11404, 11405, 11406, 11407, - 11408, 11409, 1757, 11411, 11412, 11413, 11414, 11415, - 11416, 11417, 11418, 11419, 0, 9060, 9061, 9062, - 9063, 9064, 9065, 0, 9068, 9069, 0, 9070, - 9071, 9072, 9073, 9074, 9075, 9076, 9077, 9078, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2659, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2745, 2745, 2745, - 2745, 2745, 2745, 2745, 2745, 2745, 0, 0, - 0, -4730, 6052, 0, -4732, -4732, -4732, -4732, - 0, 0, 4919, -4734, -4734, 0, -4735, -4735, - -4735, 4019, 0, 0, 4022, 4023, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5281, 2778, 2778, 0, 0, 0, - 7174, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2067, 918, - 32767, 534, -2763, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, @@ -7755,158 +7662,350 @@ NFKC_QC_hash_func(const void *key) 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 224, 225, 226, 32767, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, + 32767, 2087, -494, -8398, 7453, 7453, 243, 244, + -10240,-7658, 247, -15603,-15602,250, 251, 252, + 253, 254, 255, 32767, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, 266, 267, + 268, -2027, -1089, -2027, -2027, -2027, -2027, -2027, + -2027, -772, -2027, 279, 280, 281, 282, 283, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 284, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, -1717, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 0, 0, 0, 0, 0, - 0, 0, 0, 553, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 285, 286, 287, 288, 289, 290, 291, 292, + 6178, 294, 295, -11663,-11663,-7033, 15640, -11653, + 15643, -11653,15646, 15647, 11018, -11654,15640, -11655, + -6928, -11655,-11655,-7025, 15648, -6923, -6922, -6921, + -6920, -6919, 7643, -11636,-6916, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, -2360, 5111, -2360, -2360, -2360, - -2360, -2360, -2360, -2360, -2360, -2360, -2360, -2360, - -2360, -2360, 7293, -2360, -2360, -2360, -2360, -2360, - 3144, 3145, -2362, -2362, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 32767, 0, 0, 0, 0, 32767, - 32767, 32767, 32767, 0, -1971, -1971, 32767, 0, - 32767, 0, 1809, 1809, 1809, 1809, 0, 0, - 1811, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, -220, 0, 2582, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -3918, -3918, -3918, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - -2442, 0, -479, -479, 0, 0, 0, 0, - 0, 0, -343, 0, 0, 0, 0, 0, - 0, 0, -342, -341, -340, -339, -338, -337, - 0, 0, 0, 0, 0, 0, 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 2495, 2496, 0, 0, 2499, 2500, 2501, - 2502, 0, 2504, 2505, 2506, 2507, 2508, 1141, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -363, - 0, -362, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 0, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, -17220,-12590,10083, + -17210,10086, 5360, 10088, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, -4703, -4703, -4703, -4703, -4703, -4703, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -4261, 2507, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -3346, 32767, 32767, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -2546, -2546, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32767, 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 484, 100, -3197, 0, -3198, -3198, - 0, 0, 0, 8750, -3943, 0, 0, -3943, - 542, 543, 544, 545, 546, 547, 548, -3936, - -596, 551, 552, 553, 554, 555, 556, 557, - 558, 559, 560, 561, 562, 563, 564, 565, - 566, 567, 568, 569, 570, 571, 572, 573, - 574, 575, 576, 577, 578, 579, 580, 581, - 582, 583, 584, 585, 586, 587, 588, 589, - 590, 591, 592, 593, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 604, 605, - 606, 607, 608, 609, 610, 611, 612, 613, - 614, 615, 616, 617, 618, 619, 620, 621, - 622, 623, 624, 1375, 626, 627, 628, 629, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 324, 32767, 325, 32767, 326, 32767, 327, 32767, + 328, 32767, 329, 32767, 330, 0, 0, 0, + 0, 0, 0, 32767, 32767, 223, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, + 0, 0, 0, 0, 32767, 32767, 32767, 32767, + 32767, 0, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6529, + 6530, 6531, 6532, 32767, 6532, 6533, 6534, 0, + 0, 32767, 331, 32767, 332, 333, 334, 335, + 336, 32767, 0, 0, 0, 0, 0, 0, + 337, 0, 338, 0, -2473, -2472, -2471, 0, + 0, 0, -2470, 0, 0, 0, 0, 0, + 0, 0, -4976, 0, -2468, -2467, -2466, 0, + 0, 0, -2465, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 350, 351, 0, + 0, 0, 0, 0, 0, 0, 0, 1869, + 1869, 0, 1870, 1870, 1870, -4015, 1870, 1870, + 13829, 13830, 9201, -13471,13823, -13472,13825, -13473, + -13473,-8843, 13830, -13463,13833, -13463,13836, 13837, + 9208, -13464,0, 0, 0, 6768, 9112, -5449, + 13831, 6773, 9113, 0, 9114, 2458, 5817, 1877, + 0, 1877, 1877, 0, -1508, -1507, -1506, 1877, + 1877, 1877, 0, 1877, 1877, 1877, 0, 1874, + 0, 0, 0, -1504, -1503, 0, -1502, 1875, + 0, 0, 1877, 1877, -1500, 1877, -1499, 0, + 0, 0, 0, 1877, 0, 1877, 0, -4262, + -4262, -4262, 0, 0, 0, 0, 4641, 4642, + 4643, 4644, 4645, 6458, 4647, 4648, 4649, -4275, + 4651, 4652, 3323, 8043, 4655, 4656, 4657, -4282, + 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, + 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, + -5974, -3392, 4677, 4678, -11338,-4127, -4127, 6358, + 3777, -4127, 11724, 11724, 4514, 4515, -5969, -3387, + 4518, -11332,-11331,-4120, -4120, 6365, 3784, -4120, + 11731, 11731, 4521, 4522, -5962, -3380, 4525, -11325, + -11324,-4113, -4113, 6372, 3791, -4113, -4301, 11737, + 4527, 4528, -5956, -3374, 4531, 4720, -11317,-4106, + -4106, 6379, 3798, -4106, 0, 0, 0, 0, + 426, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3209, 3210, 3211, 3212, 3213, 3214, + 3215, 3216, 3217, 3218, 3219, 6653, 3221, 3222, + 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, + 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, + 3239, 3240, 3241, 3242, 3243, 3244, 3874, 3246, + 173, 173, 173, 173, 173, 3252, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 12394, + -6885, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, -3484, + -3483, 174, 174, 174, 174, 174, 174, 174, + 174, 174, -3476, 3305, -3474, -3473, -3472, 3309, + 3310, 3311, -3470, 3313, 3314, 3315, 3316, -3467, + 3318, -3466, 3320, -3465, -3464, 3323, -3462, 3325, + -3461, -3460, -3459, 3329, -3458, -3457, -3456, -3455, + -3454, -3453, -3452, 3337, -3451, -3450, -3449, -3448, + 352, -3446, 3344, 3345, 3346, 3347, -3445, -3444, + -3443, -3442, -3441, 3353, 3354, 3355, 3356, 3357, + 3358, 11263, -4587, -4586, -3277, -3276, 13112, -3274, + 3365, -3271, -3270, -3269, -3268, -3267, -11271,-6870, + -3264, -3263, 131, -11272,134, 11564, -15732,-3257, + 3374, 3375, 3376, -9912, -3256, -3255, -3254, -3253, + -3252, -3251, -7651, -11256,-11256,-14649,-3245, -14650, + -26079,3389, 3390, 3391, 3392, 3393, 528, 3394, + 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, + 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, + 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, + 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, + 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, + 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, + 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, + 3451, 3452, 32767, 3453, 3454, 3455, 3456, 3457, + 3458, 32767, 3459, 3460, 3461, 3462, 32767, 32767, + 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, + 32767, 3471, 3472, 3473, 3474, 3475, 3476, 3477, + 32767, 3478, 3479, 3480, 3481, 3482, 3483, 3484, + 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, + 3493, 7157, 7157, 7157, 7157, 7157, 3499, 3500, + 7157, 7157, 7157, 7157, 3505, 32767, 7157, 3507, + 3508, 3509, 32767, 3510, 3511, 3512, 3513, 3514, + 32767, 3515, 32767, 32767, 32767, 3516, 3517, 3518, + 3519, 3520, 3521, 3522, 32767, 3523, 3524, 3525, + 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, + 3534, 3535, 3536, 3537, 3538, 3539, 3540, 7340, + 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, + 3550, 3551, 3552, 3553, 7477, 7478, 532, 3909, + 18261, 2411, 2412, 3721, 3722, 20110, 3724, 10363, + 3727, 3728, 3729, 3730, 3731, -4273, 128, 3734, + 3735, 7129, -4274, 7132, 18562, -8734, 3741, 3742, + 384, 3744, -2911, 3745, 3746, 3747, 3748, 3749, + 3750, -650, -4255, -4255, -7648, 3756, -7649, -19078, + 8219, -4255, 3764, -3146, 3777, -852, -23524,3770, + -23525,3772, -23526,3774, -18897,3776, -23517,3779, + -947, 3781, 3782, -847, -23519,-947, -947, -947, + -947, -947, -15508,3772, -947, -947, -947, -947, + -7603, -4244, -7603, -947, -7602, -7602, -7602, -947, + -7603, -7603, -3202, 404, 405, 3799, -7604, 3802, + 15232, -12064,411, -7607, -696, -7618, -2988, 19685, + -7608, 19688, -7608, 19691, -7608, 15064, -7608, 19686, + -7609, -2882, -7609, -7609, -2979, 19694, -2877, -2876, + -2875, -2874, -2873, 11689, -7590, -2870, -2869, -2868, + -2867, 3790, 432, 3792, -2863, 3793, 3794, 3795, + -2859, 3798, 3799, -601, -4206, -4206, -7599, 3805, + -7600, -19029,8268, -4206, -4206, -847, -4206, 2450, + -4205, -4205, -4205, -4205, -4205, -4205, 196, 3802, + 3803, 7197, -4206, 7200, 18630, -8666, 3809, -4209, + 2702, -4220, 410, 23083, -4210, 23086, -4210, 23089, + -4210, 18462, -4210, 23084, -4211, 516, -4211, -4211, + 419, 23092, 521, 522, 523, 524, 525, 15087, + -4192, 528, 529, 530, 531, 7188, 3830, 7190, + 535, 7191, 7192, 7193, 539, 7196, 7197, 2797, + -808, -808, -4201, 7203, -4202, -15631,11666, -808, + -808, 2551, -808, 5848, -807, -807, -807, -807, + -807, -807, 3594, 7200, 7201, 10595, -808, 10598, + 22028, -5268, 7207, -811, 6100, -822, 3808, 26481, + -812, 26484, -812, 26487, -812, 21860, -812, 26482, + -813, 3914, -813, -813, 3817, 26490, 3919, 3920, + 3921, 3922, 3923, 18485, -794, 3926, 3927, 3928, + 3929, 10586, 7228, 10588, 3933, 10589, 10590, 10591, + 3937, 10594, 10595, 6195, 2590, 2590, -803, 10601, + -804, -12233,15064, 2590, 10609, 3699, 10622, 5993, + -16679,10615, -16680,10617, -16681,10619, -12052,10621, + -16672,10624, 5898, 10626, 10627, 5998, -16674,5898, + 5898, 5898, 5898, 5898, -8663, 10617, 5898, 5898, + 5898, 5898, 32767, 32767, -760, 5896, -759, -759, + -759, 5896, -760, -760, 3641, 7247, 7248, 10642, + -761, 10645, 22075, -5221, 7254, 7255, 3897, 7257, + 602, 7258, 7259, 7260, 7261, 7262, 7263, 2863, + -742, -742, -4135, 7269, -4136, -15565,11732, -742, + 7277, 367, 7290, 2661, -20011,7283, -20012,7285, + -20013,7287, -15384,7289, -20004,7292, 2566, 7294, + 7295, 2666, -20006,2566, 2566, 2566, 2566, 2566, + -11995,7285, 2566, 2566, 2566, 2566, -4090, -731, + -4090, 2566, -4089, -4089, -4089, 2566, -4090, -4090, + 311, 3917, 3918, 7312, -4091, 7315, 18745, -8551, + 3924, 3925, 567, 2566, 32767, 23198, -4095, 23201, + -4095, 23204, -4095, 18577, -4095, 23199, -4096, 631, + -4096, -4096, 534, 23207, 636, 637, 638, 639, + 640, 15202, -4077, 643, 644, 645, 646, 7303, + 3945, 7305, 650, 7306, 7307, 7308, 654, 7311, + 7312, 2912, -693, -693, -4086, 7318, -4087, -15516, + 11781, -693, -693, 2666, -693, 5963, -692, -692, + -692, -692, -692, -692, 3709, 7315, 7316, 10710, + -693, 10713, 22143, -5153, 7322, -696, 6215, -707, + 3923, 26596, -697, 26599, -697, 26602, -697, 21975, + -697, 26597, -698, 4029, -698, -698, 3932, 26605, + 4034, 4035, 4036, 4037, 4038, 18600, -679, 4041, + 4042, 4043, 4044, 10701, 7343, 10703, 4048, 10704, + 10705, 10706, 4052, 10709, 10710, 6310, 2705, 2705, + -688, 10716, -689, -12118,15179, 2705, 2705, 6064, + 4066, 4067, 4068, 3131, 4070, 4071, 4072, 4073, + 4074, 4075, 2821, 4077, 4078, 4079, 4080, 4081, + 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, + 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, + 4098, 4099, 4100, 20, 21, 22, 23, 24, + 1794, 1794, 1794, 3556, 4110, 4111, 4112, 4113, + 4114, 4115, 4116, 4117, 538, 1161, 1162, 541, + 4470, 1796, 1796, 6018, 4473, 4474, 4475, 4476, + 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, + 4485, 4486, 4140, 4141, 4487, 4143, 4488, 4145, + 4146, 4489, 4490, 4491, 4492, 4493, 4494, 4495, + 4496, 575, 576, 4061, 4497, 4061, 4498, 4061, + 4160, 4499, 4500, 4163, 4164, 4165, 4501, 4502, + 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, + 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, + 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, + 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, + 4535, 4536, 4202, 0, 5914, 0, 0, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, - 654, 655, 656, 657, 658, 659, 660, 661, - 662, 663, 664, 665, 666, 667, 668, 669, + -1842, -1842, -1842, -1842, -1842, -1842, -1842, -1842, + -1842, -1842, -1842, -1842, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, -4470, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 6910, 0, 32767, 32767, 32767, + 32767, -20383,6914, 32767, 32767, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 32767, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12220, + -7059, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, -7886, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, - 32767, 32767, 32767, 32767, 32767, 32767, 32767, 0, - 0, 0, 0, 7470, 0, 7471, 0, 0, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 3132, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 3133, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 0, 32767, 32767, 32767, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 32767, 32767, 32767, 32767, + 32767, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -16387,0, 0, 0, 0, + 0, 0, 0, 8005, 3605, 0, 0, -3393, + 8011, -3394, -14823,12474, 0, 0, 3359, 0, + 32767, 0, 0, 0, 0, 0, 0, 4401, + 8007, 0, 11403, 0, 0, 22837, 0, 0, + 0, 0, -10, 4620, 27293, 0, 27296, 0, + 27299, 0, 22672, 0, 0, 0, 4727, 0, + 0, 3135, 32767, 32767, 32767, 32767, 32767, 32767, + 3136, 32767, 32767, 3137, 32767, 3138, 3139, 3140, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 0, 0, 0, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 0, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9653, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32767, 32767, 32767, - 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, - 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, - 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, - 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, - 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, - 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, - 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, - 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, - 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, - 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, - 3232, 3233, 3234, 3235, 3236, 32767, 3237, 3238, - 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, - 3247, 3248, 1885, 3250, 3251, 3252, 3253, 3254, - 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, - 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, - 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, - 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, - 3287, 3288, 3289, 3290, 7683, 3292, 3293, 3294, - 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, - 3303, 3304, 3305, 3306, 3307, 32767, 3308, 3309, - 32767, 32767, 3310, 32767, 32767, 3311, 3312, 32767, - 32767, 3313, 3314, 3315, 3316, 32767, 3317, 3318, - 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, - -1186, -1186, 4489, -1187, 4491, -1188, -1188, -1188, - -1188, -1188, 3335, 3336, 32767, 3337, 3338, 3339, - 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, - 3348, -1659, 3350, 3351, 3352, 3353, 3354, 3355, - 3356, 3357, 3358, 3359, 3360, 3361, 3362, 4351, - 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, - 4360, 4361, 3374, 3375, 3376, 3377, 3378, 4362, - 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, - 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, - 0, 4380, 4381, 5499, 5500, 5501, 5502, 5503, - 0, 0, 4389, 4390, 0, 0, 3406, 4393, - 4394, 4395, 4396, 4397, 4398, 4399, 0, 4401, - 4402, 4403, 4404, 4405, 4406, 4407, 0, 4409, - 4410, 4411, 4412, 5171, 4414, 5174, 5175, 4623, - 4418, 4419, 4420, 4421, 4422, 4423, 4424, 3437, - 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, - 3446, 3447, 3448, 32767, 3449, 3450, 3451, 3131, - 32767, 3453, 3454, 3455, 3456, 3457, 32767, 3458, - 32767, 0, 0, 4427, 3460, 3461, 3462, 3463, - 3464, 3465, 32767, 3466, 3467, 3468, 3469, 3470, - 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, - 3146, 3367, 3148, 567, 3150, 3151, 3485, 3486, - 3487, 3488, 3489, 3490, 3491, 3492, 3493, 4428, - 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, - 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, - 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, - 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, - 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, - 3535, 3536, 3537, 3538, 3539, 3540, 3541 + 0, 0, 0, 0, 32767, 32767, 0, 32767, + 0, 32767, 32767, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32767, 0, 32767, + 0, 32767, 32767, 0, 0, 32767, 32767, 32767, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0 }; const unsigned char *k = (const unsigned char *) key; size_t keylen = 4; uint32 a = 0; - uint32 b = 1; + uint32 b = 3; while (keylen--) { @@ -7915,12 +8014,12 @@ NFKC_QC_hash_func(const void *key) a = a * 257 + c; b = b * 8191 + c; } - return h[a % 10079] + h[b % 10079]; + return h[a % 10193] + h[b % 10193]; } /* Hash lookup information for NFKC_QC */ static const pg_unicode_norminfo UnicodeNormInfo_NFKC_QC = { UnicodeNormProps_NFKC_QC, NFKC_QC_hash_func, - 5039 + 5096 }; diff --git a/src/include/common/unicode_version.h b/src/include/common/unicode_version.h index 487fcef78a540..5f6a00ba1eaea 100644 --- a/src/include/common/unicode_version.h +++ b/src/include/common/unicode_version.h @@ -3,7 +3,7 @@ * unicode_version.h * Unicode version used by Postgres. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/unicode_version.h @@ -11,4 +11,4 @@ *------------------------------------------------------------------------- */ -#define PG_UNICODE_VERSION "15.1" +#define PG_UNICODE_VERSION "16.0" diff --git a/src/include/common/username.h b/src/include/common/username.h index 60fcc70a970f0..e133bb7c5ebf5 100644 --- a/src/include/common/username.h +++ b/src/include/common/username.h @@ -2,7 +2,7 @@ * username.h * lookup effective username * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/common/username.h */ diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h index 3a37cb661e301..a924d58aabe1a 100644 --- a/src/include/datatype/timestamp.h +++ b/src/include/datatype/timestamp.h @@ -5,7 +5,7 @@ * * Note: this file must be includable in both frontend and backend contexts. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/datatype/timestamp.h @@ -136,7 +136,7 @@ struct pg_itm_in /* * We allow numeric timezone offsets up to 15:59:59 either way from Greenwich. * Currently, the record holders for wackiest offsets in actual use are zones - * Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42 + * Asia/Manila, at -15:56:08 until 1844, and America/Metlakatla, at +15:13:42 * until 1867. If we were to reject such values we would fail to dump and * restore old timestamptz values with these zone settings. */ diff --git a/src/include/executor/execAsync.h b/src/include/executor/execAsync.h index c5f26ced6750d..d8e8ea7955932 100644 --- a/src/include/executor/execAsync.h +++ b/src/include/executor/execAsync.h @@ -2,7 +2,7 @@ * execAsync.h * Support functions for asynchronous execution * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 55337d49166f6..75366203706cf 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -4,7 +4,7 @@ * Low level infrastructure related to expression evaluation * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/execExpr.h @@ -26,9 +26,9 @@ struct JsonConstructorExprState; /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */ /* expression's interpreter has been initialized */ -#define EEO_FLAG_INTERPRETER_INITIALIZED (1 << 1) +#define EEO_FLAG_INTERPRETER_INITIALIZED (1 << 5) /* jump-threading is in use */ -#define EEO_FLAG_DIRECT_THREADED (1 << 2) +#define EEO_FLAG_DIRECT_THREADED (1 << 6) /* Typical API for out-of-line evaluation subroutines */ typedef void (*ExecEvalSubroutine) (ExprState *state, @@ -65,23 +65,32 @@ typedef struct ExprEvalRowtypeCache */ typedef enum ExprEvalOp { - /* entire expression has been evaluated completely, return */ - EEOP_DONE, + /* entire expression has been evaluated, return value */ + EEOP_DONE_RETURN, + + /* entire expression has been evaluated, no return value */ + EEOP_DONE_NO_RETURN, /* apply slot_getsomeattrs on corresponding tuple slot */ EEOP_INNER_FETCHSOME, EEOP_OUTER_FETCHSOME, EEOP_SCAN_FETCHSOME, + EEOP_OLD_FETCHSOME, + EEOP_NEW_FETCHSOME, /* compute non-system Var value */ EEOP_INNER_VAR, EEOP_OUTER_VAR, EEOP_SCAN_VAR, + EEOP_OLD_VAR, + EEOP_NEW_VAR, /* compute system Var value */ EEOP_INNER_SYSVAR, EEOP_OUTER_SYSVAR, EEOP_SCAN_SYSVAR, + EEOP_OLD_SYSVAR, + EEOP_NEW_SYSVAR, /* compute wholerow Var */ EEOP_WHOLEROW, @@ -94,6 +103,8 @@ typedef enum ExprEvalOp EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, + EEOP_ASSIGN_OLD_VAR, + EEOP_ASSIGN_NEW_VAR, /* assign ExprState's resvalue/resnull to a column of its resultslot */ EEOP_ASSIGN_TMP, @@ -105,11 +116,13 @@ typedef enum ExprEvalOp /* * Evaluate function call (including OpExprs etc). For speed, we - * distinguish in the opcode whether the function is strict and/or - * requires usage stats tracking. + * distinguish in the opcode whether the function is strict with 1, 2, or + * more arguments and/or requires usage stats tracking. */ EEOP_FUNCEXPR, EEOP_FUNCEXPR_STRICT, + EEOP_FUNCEXPR_STRICT_1, + EEOP_FUNCEXPR_STRICT_2, EEOP_FUNCEXPR_FUSAGE, EEOP_FUNCEXPR_STRICT_FUSAGE, @@ -160,9 +173,12 @@ typedef enum ExprEvalOp EEOP_PARAM_EXEC, EEOP_PARAM_EXTERN, EEOP_PARAM_CALLBACK, + /* set PARAM_EXEC value */ + EEOP_PARAM_SET, /* return CaseTestExpr value */ EEOP_CASE_TESTVAL, + EEOP_CASE_TESTVAL_EXT, /* apply MakeExpandedObjectReadOnly() to target value */ EEOP_MAKE_READONLY, @@ -176,6 +192,7 @@ typedef enum ExprEvalOp EEOP_SQLVALUEFUNCTION, EEOP_CURRENTOFEXPR, EEOP_NEXTVALUEEXPR, + EEOP_RETURNINGEXPR, EEOP_ARRAYEXPR, EEOP_ARRAYCOERCE, EEOP_ROW, @@ -226,6 +243,7 @@ typedef enum ExprEvalOp /* evaluate value for CoerceToDomainValue */ EEOP_DOMAIN_TESTVAL, + EEOP_DOMAIN_TESTVAL_EXT, /* evaluate a domain's NOT NULL constraint */ EEOP_DOMAIN_NOTNULL, @@ -233,6 +251,13 @@ typedef enum ExprEvalOp /* evaluate a single domain CHECK constraint */ EEOP_DOMAIN_CHECK, + /* evaluation steps for hashing */ + EEOP_HASHDATUM_SET_INITVAL, + EEOP_HASHDATUM_FIRST, + EEOP_HASHDATUM_FIRST_STRICT, + EEOP_HASHDATUM_NEXT32, + EEOP_HASHDATUM_NEXT32_STRICT, + /* evaluate assorted special-purpose expression types */ EEOP_CONVERT_ROWTYPE, EEOP_SCALARARRAYOP, @@ -253,6 +278,7 @@ typedef enum ExprEvalOp EEOP_AGG_STRICT_DESERIALIZE, EEOP_AGG_DESERIALIZE, EEOP_AGG_STRICT_INPUT_CHECK_ARGS, + EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1, EEOP_AGG_STRICT_INPUT_CHECK_NULLS, EEOP_AGG_PLAIN_PERGROUP_NULLCHECK, EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL, @@ -292,7 +318,7 @@ typedef struct ExprEvalStep */ union { - /* for EEOP_INNER/OUTER/SCAN_FETCHSOME */ + /* for EEOP_INNER/OUTER/SCAN/OLD/NEW_FETCHSOME */ struct { /* attribute number up to which to fetch (inclusive) */ @@ -305,13 +331,14 @@ typedef struct ExprEvalStep const TupleTableSlotOps *kind; } fetch; - /* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */ + /* for EEOP_INNER/OUTER/SCAN/OLD/NEW_[SYS]VAR */ struct { /* attnum is attr number - 1 for regular VAR ... */ /* but it's just the normal (negative) attr number for SYSVAR */ int attnum; Oid vartype; /* type OID of variable */ + VarReturningType varreturningtype; /* return old/new/default */ } var; /* for EEOP_WHOLEROW */ @@ -340,6 +367,13 @@ typedef struct ExprEvalStep int resultnum; } assign_tmp; + /* for EEOP_RETURNINGEXPR */ + struct + { + uint8 nullflag; /* flag to test if OLD/NEW row is NULL */ + int jumpdone; /* jump here if OLD/NEW row is NULL */ + } returningexpr; + /* for EEOP_CONST */ struct { @@ -356,6 +390,7 @@ typedef struct ExprEvalStep /* faster to access without additional indirection: */ PGFunction fn_addr; /* actual call address */ int nargs; /* number of arguments */ + bool make_ro; /* make arg0 R/O (used only for NULLIF) */ } func; /* for EEOP_BOOL_*_STEP */ @@ -384,7 +419,7 @@ typedef struct ExprEvalStep ExprEvalRowtypeCache rowcache; } nulltest_row; - /* for EEOP_PARAM_EXEC/EXTERN */ + /* for EEOP_PARAM_EXEC/EXTERN and EEOP_PARAM_SET */ struct { int paramid; /* numeric ID for parameter */ @@ -396,6 +431,7 @@ typedef struct ExprEvalStep { ExecEvalSubroutine paramfunc; /* add-on evaluation subroutine */ void *paramarg; /* private data for same */ + void *paramarg2; /* more private data for same */ int paramid; /* numeric ID for parameter */ Oid paramtype; /* OID of parameter's datatype */ } cparam; @@ -484,7 +520,7 @@ typedef struct ExprEvalStep /* for EEOP_ROWCOMPARE_FINAL */ struct { - RowCompareType rctype; + CompareType cmptype; } rowcompare_final; /* for EEOP_MINMAX */ @@ -556,6 +592,24 @@ typedef struct ExprEvalStep ErrorSaveContext *escontext; } domaincheck; + /* for EEOP_HASH_SET_INITVAL */ + struct + { + Datum init_value; + + } hashdatum_initvalue; + + /* for EEOP_HASHDATUM_(FIRST|NEXT32)[_STRICT] */ + struct + { + FmgrInfo *finfo; /* function's lookup data */ + FunctionCallInfo fcinfo_data; /* arguments etc */ + /* faster to access without additional indirection: */ + PGFunction fn_addr; /* actual call address */ + int jumpdone; /* jump here on null */ + NullableDatum *iresult; /* intermediate hash result */ + } hashdatum; + /* for EEOP_CONVERT_ROWTYPE */ struct { @@ -708,7 +762,11 @@ typedef struct ExprEvalStep Oid targettype; int32 targettypmod; bool omit_quotes; - void *json_populate_type_cache; + /* exists_* fields only relevant for JSON_EXISTS_OP. */ + bool exists_coerce; + bool exists_cast_to_int; + bool exists_check_domain; + void *json_coercion_cache; ErrorSaveContext *escontext; } jsonexpr_coercion; } d; @@ -796,6 +854,8 @@ extern void ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op, ExprContext *econtext); extern void ExecEvalParamExec(ExprState *state, ExprEvalStep *op, ExprContext *econtext); +extern void ExecEvalParamSet(ExprState *state, ExprEvalStep *op, + ExprContext *econtext); extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op, ExprContext *econtext); extern void ExecEvalCoerceViaIOSafe(ExprState *state, ExprEvalStep *op); diff --git a/src/include/executor/execParallel.h b/src/include/executor/execParallel.h index 6b8c00bb0fbfa..5e7106c397a26 100644 --- a/src/include/executor/execParallel.h +++ b/src/include/executor/execParallel.h @@ -2,7 +2,7 @@ * execParallel.h * POSTGRES parallel execution interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index c09bc83b2ac3c..3b3f46aced05f 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -2,7 +2,7 @@ * execPartition.h * POSTGRES partitioning executor interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -42,9 +42,13 @@ extern void ExecCleanupTupleRouting(ModifyTableState *mtstate, * PartitionedRelPruneInfo (see plannodes.h); though note that here, * subpart_map contains indexes into PartitionPruningData.partrelprunedata[]. * + * partrel Partitioned table Relation; obtained by + * ExecGetRangeTableRelation(estate, rti, false), + * where rti is PartitionedRelPruneInfo.rtindex. * nparts Length of subplan_map[] and subpart_map[]. * subplan_map Subplan index by partition index, or -1. * subpart_map Subpart index by partition index, or -1. + * leafpart_rti_map RT index by partition index, or 0. * present_parts A Bitmapset of the partition indexes that we * have subplans or subparts for. * initial_pruning_steps List of PartitionPruneSteps used to @@ -58,9 +62,11 @@ extern void ExecCleanupTupleRouting(ModifyTableState *mtstate, */ typedef struct PartitionedRelPruningData { + Relation partrel; int nparts; int *subplan_map; int *subpart_map; + int *leafpart_rti_map; Bitmapset *present_parts; List *initial_pruning_steps; List *exec_pruning_steps; @@ -90,6 +96,8 @@ typedef struct PartitionPruningData * the clauses being unable to match to any tuple that the subplan could * possibly produce. * + * econtext Standalone ExprContext to evaluate expressions in + * the pruning steps * execparamids Contains paramids of PARAM_EXEC Params found within * any of the partprunedata structs. Pruning must be * done again each time the value of one of these @@ -112,6 +120,7 @@ typedef struct PartitionPruningData */ typedef struct PartitionPruneState { + ExprContext *econtext; Bitmapset *execparamids; Bitmapset *other_subplans; MemoryContext prune_context; @@ -121,11 +130,14 @@ typedef struct PartitionPruneState PartitionPruningData *partprunedata[FLEXIBLE_ARRAY_MEMBER]; } PartitionPruneState; -extern PartitionPruneState *ExecInitPartitionPruning(PlanState *planstate, - int n_total_subplans, - PartitionPruneInfo *pruneinfo, - Bitmapset **initially_valid_subplans); +extern void ExecDoInitialPruning(EState *estate); +extern PartitionPruneState *ExecInitPartitionExecPruning(PlanState *planstate, + int n_total_subplans, + int part_prune_index, + Bitmapset *relids, + Bitmapset **initially_valid_subplans); extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate, - bool initial_prune); + bool initial_prune, + Bitmapset **validsubplan_rtis); #endif /* EXECPARTITION_H */ diff --git a/src/include/executor/execScan.h b/src/include/executor/execScan.h new file mode 100644 index 0000000000000..837ea7785bb4c --- /dev/null +++ b/src/include/executor/execScan.h @@ -0,0 +1,246 @@ +/*------------------------------------------------------------------------- + * execScan.h + * Inline-able support functions for Scan nodes + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/include/executor/execScan.h + *------------------------------------------------------------------------- + */ + +#ifndef EXECSCAN_H +#define EXECSCAN_H + +#include "miscadmin.h" +#include "executor/executor.h" +#include "nodes/execnodes.h" + +/* + * ExecScanFetch -- check interrupts & fetch next potential tuple + * + * This routine substitutes a test tuple if inside an EvalPlanQual recheck. + * Otherwise, it simply executes the access method's next-tuple routine. + * + * The pg_attribute_always_inline attribute allows the compiler to inline + * this function into its caller. When EPQState is NULL, the EvalPlanQual + * logic is completely eliminated at compile time, avoiding unnecessary + * run-time checks and code for cases where EPQ is not required. + */ +static pg_attribute_always_inline TupleTableSlot * +ExecScanFetch(ScanState *node, + EPQState *epqstate, + ExecScanAccessMtd accessMtd, + ExecScanRecheckMtd recheckMtd) +{ + CHECK_FOR_INTERRUPTS(); + + if (epqstate != NULL) + { + /* + * We are inside an EvalPlanQual recheck. Return the test tuple if + * one is available, after rechecking any access-method-specific + * conditions. + */ + Index scanrelid = ((Scan *) node->ps.plan)->scanrelid; + + if (scanrelid == 0) + { + /* + * This is a ForeignScan or CustomScan which has pushed down a + * join to the remote side. The recheck method is responsible not + * only for rechecking the scan/join quals but also for storing + * the correct tuple in the slot. + */ + + TupleTableSlot *slot = node->ss_ScanTupleSlot; + + if (!(*recheckMtd) (node, slot)) + ExecClearTuple(slot); /* would not be returned by scan */ + return slot; + } + else if (epqstate->relsubs_done[scanrelid - 1]) + { + /* + * Return empty slot, as either there is no EPQ tuple for this rel + * or we already returned it. + */ + + TupleTableSlot *slot = node->ss_ScanTupleSlot; + + return ExecClearTuple(slot); + } + else if (epqstate->relsubs_slot[scanrelid - 1] != NULL) + { + /* + * Return replacement tuple provided by the EPQ caller. + */ + + TupleTableSlot *slot = epqstate->relsubs_slot[scanrelid - 1]; + + Assert(epqstate->relsubs_rowmark[scanrelid - 1] == NULL); + + /* Mark to remember that we shouldn't return it again */ + epqstate->relsubs_done[scanrelid - 1] = true; + + /* Return empty slot if we haven't got a test tuple */ + if (TupIsNull(slot)) + return NULL; + + /* Check if it meets the access-method conditions */ + if (!(*recheckMtd) (node, slot)) + return ExecClearTuple(slot); /* would not be returned by + * scan */ + return slot; + } + else if (epqstate->relsubs_rowmark[scanrelid - 1] != NULL) + { + /* + * Fetch and return replacement tuple using a non-locking rowmark. + */ + + TupleTableSlot *slot = node->ss_ScanTupleSlot; + + /* Mark to remember that we shouldn't return more */ + epqstate->relsubs_done[scanrelid - 1] = true; + + if (!EvalPlanQualFetchRowMark(epqstate, scanrelid, slot)) + return NULL; + + /* Return empty slot if we haven't got a test tuple */ + if (TupIsNull(slot)) + return NULL; + + /* Check if it meets the access-method conditions */ + if (!(*recheckMtd) (node, slot)) + return ExecClearTuple(slot); /* would not be returned by + * scan */ + return slot; + } + } + + /* + * Run the node-type-specific access method function to get the next tuple + */ + return (*accessMtd) (node); +} + +/* ---------------------------------------------------------------- + * ExecScanExtended + * Scans the relation using the specified 'access method' and returns the + * next tuple. Optionally checks the tuple against 'qual' and applies + * 'projInfo' if provided. + * + * The 'recheck method' validates an arbitrary tuple of the relation against + * conditions enforced by the access method. + * + * This function is an alternative to ExecScan, used when callers may omit + * 'qual' or 'projInfo'. The pg_attribute_always_inline attribute allows the + * compiler to eliminate non-relevant branches at compile time, avoiding + * run-time checks in those cases. + * + * Conditions: + * -- The AMI "cursor" is positioned at the previously returned tuple. + * + * Initial States: + * -- The relation is opened for scanning, with the "cursor" + * positioned before the first qualifying tuple. + * ---------------------------------------------------------------- + */ +static pg_attribute_always_inline TupleTableSlot * +ExecScanExtended(ScanState *node, + ExecScanAccessMtd accessMtd, /* function returning a tuple */ + ExecScanRecheckMtd recheckMtd, + EPQState *epqstate, + ExprState *qual, + ProjectionInfo *projInfo) +{ + ExprContext *econtext = node->ps.ps_ExprContext; + + /* interrupt checks are in ExecScanFetch */ + + /* + * If we have neither a qual to check nor a projection to do, just skip + * all the overhead and return the raw scan tuple. + */ + if (!qual && !projInfo) + { + ResetExprContext(econtext); + return ExecScanFetch(node, epqstate, accessMtd, recheckMtd); + } + + /* + * Reset per-tuple memory context to free any expression evaluation + * storage allocated in the previous tuple cycle. + */ + ResetExprContext(econtext); + + /* + * get a tuple from the access method. Loop until we obtain a tuple that + * passes the qualification. + */ + for (;;) + { + TupleTableSlot *slot; + + slot = ExecScanFetch(node, epqstate, accessMtd, recheckMtd); + + /* + * if the slot returned by the accessMtd contains NULL, then it means + * there is nothing more to scan so we just return an empty slot, + * being careful to use the projection result slot so it has correct + * tupleDesc. + */ + if (TupIsNull(slot)) + { + if (projInfo) + return ExecClearTuple(projInfo->pi_state.resultslot); + else + return slot; + } + + /* + * place the current tuple into the expr context + */ + econtext->ecxt_scantuple = slot; + + /* + * check that the current tuple satisfies the qual-clause + * + * check for non-null qual here to avoid a function call to ExecQual() + * when the qual is null ... saves only a few cycles, but they add up + * ... + */ + if (qual == NULL || ExecQual(qual, econtext)) + { + /* + * Found a satisfactory scan tuple. + */ + if (projInfo) + { + /* + * Form a projection tuple, store it in the result tuple slot + * and return it. + */ + return ExecProject(projInfo); + } + else + { + /* + * Here, we aren't projecting, so just return scan tuple. + */ + return slot; + } + } + else + InstrCountFiltered1(node, 1); + + /* + * Tuple fails qual, so free per-tuple memory and try again. + */ + ResetExprContext(econtext); + } +} + +#endif /* EXECSCAN_H */ diff --git a/src/include/executor/execdebug.h b/src/include/executor/execdebug.h index 27e30b16f57a5..e5d27fb6c9ab4 100644 --- a/src/include/executor/execdebug.h +++ b/src/include/executor/execdebug.h @@ -7,7 +7,7 @@ * for debug printouts, because that's more flexible than printf(). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/execdebug.h diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h index 0a7274e26c834..86db3dc8d0de2 100644 --- a/src/include/executor/execdesc.h +++ b/src/include/executor/execdesc.h @@ -5,7 +5,7 @@ * and related modules. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/execdesc.h @@ -48,7 +48,7 @@ typedef struct QueryDesc EState *estate; /* executor's query-wide state */ PlanState *planstate; /* tree of per-plan-node state */ - /* This field is set by ExecutorRun */ + /* This field is set by ExecutePlan */ bool already_executed; /* true if previously executed */ /* This is always set NULL by the core system, but plugins can change it */ diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 9770752ea3c1b..104b059544dd3 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -4,7 +4,7 @@ * support for the POSTGRES executor module * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/executor.h @@ -78,8 +78,7 @@ extern PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook; /* Hook for plugins to get control in ExecutorRun() */ typedef void (*ExecutorRun_hook_type) (QueryDesc *queryDesc, ScanDirection direction, - uint64 count, - bool execute_once); + uint64 count); extern PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook; /* Hook for plugins to get control in ExecutorFinish() */ @@ -132,23 +131,18 @@ extern void execTuplesHashPrepare(int numCols, FmgrInfo **hashFunctions); extern TupleHashTable BuildTupleHashTable(PlanState *parent, TupleDesc inputDesc, - int numCols, AttrNumber *keyColIdx, + const TupleTableSlotOps *inputOps, + int numCols, + AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, - long nbuckets, Size additionalsize, + long nbuckets, + Size additionalsize, + MemoryContext metacxt, MemoryContext tablecxt, - MemoryContext tempcxt, bool use_variable_hash_iv); -extern TupleHashTable BuildTupleHashTableExt(PlanState *parent, - TupleDesc inputDesc, - int numCols, AttrNumber *keyColIdx, - const Oid *eqfuncoids, - FmgrInfo *hashfunctions, - Oid *collations, - long nbuckets, Size additionalsize, - MemoryContext metacxt, - MemoryContext tablecxt, - MemoryContext tempcxt, bool use_variable_hash_iv); + MemoryContext tempcxt, + bool use_variable_hash_iv); extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 *hash); @@ -160,9 +154,46 @@ extern TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable, extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, - FmgrInfo *hashfunctions); + ExprState *hashexpr); extern void ResetTupleHashTable(TupleHashTable hashtable); +#ifndef FRONTEND +/* + * Return size of the hash bucket. Useful for estimating memory usage. + */ +static inline size_t +TupleHashEntrySize(void) +{ + return sizeof(TupleHashEntryData); +} + +/* + * Return tuple from hash entry. + */ +static inline MinimalTuple +TupleHashEntryGetTuple(TupleHashEntry entry) +{ + return entry->firstTuple; +} + +/* + * Get a pointer into the additional space allocated for this entry. The + * memory will be maxaligned and zeroed. + * + * The amount of space available is the additionalsize requested in the call + * to BuildTupleHashTable(). If additionalsize was specified as zero, return + * NULL. + */ +static inline void * +TupleHashEntryGetAdditional(TupleHashTable hashtable, TupleHashEntry entry) +{ + if (hashtable->additionalsize > 0) + return (char *) entry->firstTuple - hashtable->additionalsize; + else + return NULL; +} +#endif + /* * prototypes from functions in execJunk.c */ @@ -200,9 +231,9 @@ ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull) extern void ExecutorStart(QueryDesc *queryDesc, int eflags); extern void standard_ExecutorStart(QueryDesc *queryDesc, int eflags); extern void ExecutorRun(QueryDesc *queryDesc, - ScanDirection direction, uint64 count, bool execute_once); + ScanDirection direction, uint64 count); extern void standard_ExecutorRun(QueryDesc *queryDesc, - ScanDirection direction, uint64 count, bool execute_once); + ScanDirection direction, uint64 count); extern void ExecutorFinish(QueryDesc *queryDesc); extern void standard_ExecutorFinish(QueryDesc *queryDesc); extern void ExecutorEnd(QueryDesc *queryDesc); @@ -222,12 +253,20 @@ extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid, extern List *ExecGetAncestorResultRels(EState *estate, ResultRelInfo *resultRelInfo); extern void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); +extern AttrNumber ExecRelGenVirtualNotNull(ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, + EState *estate, + List *notnull_virtual_attrs); extern bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError); extern void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); extern void ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); +extern char *ExecBuildSlotValueDescription(Oid reloid, TupleTableSlot *slot, + TupleDesc tupdesc, + Bitmapset *modifiedCols, + int maxfieldlen); extern LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo); extern ExecRowMark *ExecFindRowMark(EState *estate, Index rti, bool missing_ok); extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist); @@ -285,6 +324,21 @@ extern ExprState *ExecInitCheck(List *qual, PlanState *parent); extern List *ExecInitExprList(List *nodes, PlanState *parent); extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase, bool doSort, bool doHash, bool nullcheck); +extern ExprState *ExecBuildHash32FromAttrs(TupleDesc desc, + const TupleTableSlotOps *ops, + FmgrInfo *hashfunctions, + Oid *collations, + int numCols, + AttrNumber *keyColIdx, + PlanState *parent, + uint32 init_value); +extern ExprState *ExecBuildHash32Expr(TupleDesc desc, + const TupleTableSlotOps *ops, + const Oid *hashfunc_oids, + const List *collations, + const List *hash_exprs, + const bool *opstrict, PlanState *parent, + uint32 init_value, bool keep_nulls); extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, int numCols, @@ -338,6 +392,34 @@ ExecEvalExpr(ExprState *state, } #endif +/* + * ExecEvalExprNoReturn + * + * Like ExecEvalExpr(), but for cases where no return value is expected, + * because the side-effects of expression evaluation are what's desired. This + * is e.g. used for projection and aggregate transition computation. + + * Evaluate expression identified by "state" in the execution context + * given by "econtext". + * + * The caller should already have switched into the temporary memory context + * econtext->ecxt_per_tuple_memory. The convenience entry point + * ExecEvalExprNoReturnSwitchContext() is provided for callers who don't + * prefer to do the switch in an outer loop. + */ +#ifndef FRONTEND +static inline void +ExecEvalExprNoReturn(ExprState *state, + ExprContext *econtext) +{ + PG_USED_FOR_ASSERTS_ONLY Datum retDatum; + + retDatum = state->evalfunc(state, econtext, NULL); + + Assert(retDatum == (Datum) 0); +} +#endif + /* * ExecEvalExprSwitchContext * @@ -359,6 +441,25 @@ ExecEvalExprSwitchContext(ExprState *state, } #endif +/* + * ExecEvalExprNoReturnSwitchContext + * + * Same as ExecEvalExprNoReturn, but get into the right allocation context + * explicitly. + */ +#ifndef FRONTEND +static inline void +ExecEvalExprNoReturnSwitchContext(ExprState *state, + ExprContext *econtext) +{ + MemoryContext oldContext; + + oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); + ExecEvalExprNoReturn(state, econtext); + MemoryContextSwitchTo(oldContext); +} +#endif + /* * ExecProject * @@ -378,7 +479,6 @@ ExecProject(ProjectionInfo *projInfo) ExprContext *econtext = projInfo->pi_exprContext; ExprState *state = &projInfo->pi_state; TupleTableSlot *slot = state->resultslot; - bool isnull; /* * Clear any former contents of the result slot. This makes it safe for @@ -386,8 +486,8 @@ ExecProject(ProjectionInfo *projInfo) */ ExecClearTuple(slot); - /* Run the expression, discarding scalar result from the last column. */ - (void) ExecEvalExprSwitchContext(state, econtext, &isnull); + /* Run the expression */ + ExecEvalExprNoReturnSwitchContext(state, econtext); /* * Successfully formed a result row. Mark the result slot as containing a @@ -566,6 +666,9 @@ extern void ExecAssignExprContext(EState *estate, PlanState *planstate); extern TupleDesc ExecGetResultType(PlanState *planstate); extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate, bool *isfixed); +extern const TupleTableSlotOps *ExecGetCommonSlotOps(PlanState **planstates, + int nplans); +extern const TupleTableSlotOps *ExecGetCommonChildSlotOps(PlanState *ps); extern void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc); extern void ExecConditionalAssignProjectionInfo(PlanState *planstate, @@ -579,7 +682,8 @@ extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid); extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags); -extern void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos); +extern void ExecInitRangeTable(EState *estate, List *rangeTable, List *permInfos, + Bitmapset *unpruned_relids); extern void ExecCloseRangeTableRelations(EState *estate); extern void ExecCloseResultRelations(EState *estate); @@ -589,7 +693,8 @@ exec_rt_fetch(Index rti, EState *estate) return (RangeTblEntry *) list_nth(estate->es_range_table, rti - 1); } -extern Relation ExecGetRangeTableRelation(EState *estate, Index rti); +extern Relation ExecGetRangeTableRelation(EState *estate, Index rti, + bool isResultRel); extern void ExecInitResultRelation(EState *estate, ResultRelInfo *resultRelInfo, Index rti); @@ -613,6 +718,7 @@ extern int ExecCleanTargetListLength(List *targetlist); extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo); extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo); extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo); +extern TupleTableSlot *ExecGetAllNullSlot(EState *estate, ResultRelInfo *relInfo); extern TupleConversionMap *ExecGetChildToRootMap(ResultRelInfo *resultRelInfo); extern TupleConversionMap *ExecGetRootToChildMap(ResultRelInfo *resultRelInfo, EState *estate); @@ -636,6 +742,7 @@ extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, extern bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, + ItemPointer tupleid, List *arbiterIndexes); extern void check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo, @@ -646,7 +753,6 @@ extern void check_exclusion_constraint(Relation heap, Relation index, /* * prototypes from functions in execReplication.c */ -extern StrategyNumber get_equal_strategy_number_for_am(Oid am); extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid, LockTupleMode lockmode, TupleTableSlot *searchslot, diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h index 27f948c6f52eb..58bdff9b0392d 100644 --- a/src/include/executor/functions.h +++ b/src/include/executor/functions.h @@ -4,7 +4,7 @@ * Declarations for execution of SQL-language functions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/functions.h @@ -48,8 +48,7 @@ extern void check_sql_fn_statements(List *queryTreeLists); extern bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, - bool insertDroppedCols, - List **resultTargetList); + bool insertDroppedCols); extern DestReceiver *CreateSQLFunctionDestReceiver(void); diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h index 9197846cda75a..ecff4842fd38d 100644 --- a/src/include/executor/hashjoin.h +++ b/src/include/executor/hashjoin.h @@ -4,7 +4,7 @@ * internal structures for hash joins * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/hashjoin.h @@ -147,7 +147,7 @@ typedef struct HashMemoryChunkData typedef struct HashMemoryChunkData *HashMemoryChunk; -#define HASH_CHUNK_SIZE (32 * 1024L) +#define HASH_CHUNK_SIZE ((Size) (32 * 1024)) #define HASH_CHUNK_HEADER_SIZE MAXALIGN(sizeof(HashMemoryChunkData)) #define HASH_CHUNK_DATA(hc) (((char *) (hc)) + HASH_CHUNK_HEADER_SIZE) /* tuples exceeding HASH_CHUNK_THRESHOLD bytes are put in their own chunk */ @@ -313,8 +313,6 @@ typedef struct HashJoinTableData dsa_pointer_atomic *shared; } buckets; - bool keepNulls; /* true to store unmatchable NULL tuples */ - bool skewEnabled; /* are we using skew optimization? */ HashSkewBucket **skewBucket; /* hashtable of skew buckets */ int skewBucketLen; /* size of skewBucket array (a power of 2!) */ @@ -343,16 +341,6 @@ typedef struct HashJoinTableData BufFile **innerBatchFile; /* buffered virtual temp file per batch */ BufFile **outerBatchFile; /* buffered virtual temp file per batch */ - /* - * Info about the datatype-specific hash functions for the datatypes being - * hashed. These are arrays of the same length as the number of hash join - * clauses (hash keys). - */ - FmgrInfo *outer_hashfunctions; /* lookup data for hash functions */ - FmgrInfo *inner_hashfunctions; /* lookup data for hash functions */ - bool *hashStrict; /* is each hash join operator strict? */ - Oid *collations; - Size spaceUsed; /* memory space currently used by tuples */ Size spaceAllowed; /* upper limit for space used */ Size spacePeak; /* peak space used */ diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h index bfd7b6d84452f..03653ab6c6cde 100644 --- a/src/include/executor/instrument.h +++ b/src/include/executor/instrument.h @@ -4,7 +4,7 @@ * definitions for run-time statistics collection * * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/executor/instrument.h * @@ -53,6 +53,7 @@ typedef struct WalUsage int64 wal_records; /* # of WAL records produced */ int64 wal_fpi; /* # of WAL full page images produced */ uint64 wal_bytes; /* size of WAL records produced */ + int64 wal_buffers_full; /* # of times the WAL buffers became full */ } WalUsage; /* Flag bits included in InstrAlloc's instrument_options bitmask */ diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h index 684779a6a326b..6c4891bbaeb49 100644 --- a/src/include/executor/nodeAgg.h +++ b/src/include/executor/nodeAgg.h @@ -4,7 +4,7 @@ * prototypes for nodeAgg.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeAgg.h diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h index ee75953d116dc..3c90847a32c87 100644 --- a/src/include/executor/nodeAppend.h +++ b/src/include/executor/nodeAppend.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeAppend.h diff --git a/src/include/executor/nodeBitmapAnd.h b/src/include/executor/nodeBitmapAnd.h index 299185f53dfea..99518736ec6eb 100644 --- a/src/include/executor/nodeBitmapAnd.h +++ b/src/include/executor/nodeBitmapAnd.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeBitmapAnd.h diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h index 446a664590a97..e241ac06f9d69 100644 --- a/src/include/executor/nodeBitmapHeapscan.h +++ b/src/include/executor/nodeBitmapHeapscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeBitmapHeapscan.h diff --git a/src/include/executor/nodeBitmapIndexscan.h b/src/include/executor/nodeBitmapIndexscan.h index 1de0a57787ac3..b6a5ae25ed19c 100644 --- a/src/include/executor/nodeBitmapIndexscan.h +++ b/src/include/executor/nodeBitmapIndexscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeBitmapIndexscan.h @@ -14,11 +14,17 @@ #ifndef NODEBITMAPINDEXSCAN_H #define NODEBITMAPINDEXSCAN_H +#include "access/parallel.h" #include "nodes/execnodes.h" extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags); extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node); extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node); extern void ExecReScanBitmapIndexScan(BitmapIndexScanState *node); +extern void ExecBitmapIndexScanEstimate(BitmapIndexScanState *node, ParallelContext *pcxt); +extern void ExecBitmapIndexScanInitializeDSM(BitmapIndexScanState *node, ParallelContext *pcxt); +extern void ExecBitmapIndexScanInitializeWorker(BitmapIndexScanState *node, + ParallelWorkerContext *pwcxt); +extern void ExecBitmapIndexScanRetrieveInstrumentation(BitmapIndexScanState *node); #endif /* NODEBITMAPINDEXSCAN_H */ diff --git a/src/include/executor/nodeBitmapOr.h b/src/include/executor/nodeBitmapOr.h index 8bafc5bec9a37..3ee94d334d19f 100644 --- a/src/include/executor/nodeBitmapOr.h +++ b/src/include/executor/nodeBitmapOr.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeBitmapOr.h diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h index 9df8ea71198e1..007fede3d9dd1 100644 --- a/src/include/executor/nodeCtescan.h +++ b/src/include/executor/nodeCtescan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeCtescan.h diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h index e8b7e53fbd5b0..bc0ca512e090a 100644 --- a/src/include/executor/nodeCustom.h +++ b/src/include/executor/nodeCustom.h @@ -4,7 +4,7 @@ * * prototypes for CustomScan nodes * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * ------------------------------------------------------------------------ diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h index 747fe4eee4114..3e55e0fa5974b 100644 --- a/src/include/executor/nodeForeignscan.h +++ b/src/include/executor/nodeForeignscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeForeignscan.h diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h index d957a885f6347..10b06ad96365d 100644 --- a/src/include/executor/nodeFunctionscan.h +++ b/src/include/executor/nodeFunctionscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeFunctionscan.h diff --git a/src/include/executor/nodeGather.h b/src/include/executor/nodeGather.h index 045c16d264765..2961a9bc57fc2 100644 --- a/src/include/executor/nodeGather.h +++ b/src/include/executor/nodeGather.h @@ -4,7 +4,7 @@ * prototypes for nodeGather.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeGather.h diff --git a/src/include/executor/nodeGatherMerge.h b/src/include/executor/nodeGatherMerge.h index d828c00f471ae..56076f49676ff 100644 --- a/src/include/executor/nodeGatherMerge.h +++ b/src/include/executor/nodeGatherMerge.h @@ -4,7 +4,7 @@ * prototypes for nodeGatherMerge.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeGatherMerge.h diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h index 9578b9229e396..0ead772fd499c 100644 --- a/src/include/executor/nodeGroup.h +++ b/src/include/executor/nodeGroup.h @@ -4,7 +4,7 @@ * prototypes for nodeGroup.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeGroup.h diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h index a95911c2feeb5..3c1a09415aa1e 100644 --- a/src/include/executor/nodeHash.h +++ b/src/include/executor/nodeHash.h @@ -4,7 +4,7 @@ * prototypes for nodeHash.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeHash.h @@ -24,8 +24,7 @@ extern Node *MultiExecHash(HashState *node); extern void ExecEndHash(HashState *node); extern void ExecReScanHash(HashState *node); -extern HashJoinTable ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations, - bool keepNulls); +extern HashJoinTable ExecHashTableCreate(HashState *state); extern void ExecParallelHashTableAlloc(HashJoinTable hashtable, int batchno); extern void ExecHashTableDestroy(HashJoinTable hashtable); @@ -43,12 +42,6 @@ extern void ExecParallelHashTableInsert(HashJoinTable hashtable, extern void ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable, TupleTableSlot *slot, uint32 hashvalue); -extern bool ExecHashGetHashValue(HashJoinTable hashtable, - ExprContext *econtext, - List *hashkeys, - bool outer_tuple, - bool keep_nulls, - uint32 *hashvalue); extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable, uint32 hashvalue, int *bucketno, diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h index 2b121094f278b..646095b4dc65e 100644 --- a/src/include/executor/nodeHashjoin.h +++ b/src/include/executor/nodeHashjoin.h @@ -4,7 +4,7 @@ * prototypes for nodeHashjoin.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeHashjoin.h diff --git a/src/include/executor/nodeIncrementalSort.h b/src/include/executor/nodeIncrementalSort.h index df020741aff7a..12c16bca8a6f9 100644 --- a/src/include/executor/nodeIncrementalSort.h +++ b/src/include/executor/nodeIncrementalSort.h @@ -2,7 +2,7 @@ * * nodeIncrementalSort.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeIncrementalSort.h diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h index 607af8c354003..ae85dee6d8f3a 100644 --- a/src/include/executor/nodeIndexonlyscan.h +++ b/src/include/executor/nodeIndexonlyscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeIndexonlyscan.h @@ -32,5 +32,6 @@ extern void ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node, ParallelContext *pcxt); extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, ParallelWorkerContext *pwcxt); +extern void ExecIndexOnlyScanRetrieveInstrumentation(IndexOnlyScanState *node); #endif /* NODEINDEXONLYSCAN_H */ diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h index 3cddece67c8eb..08f0a148db6c6 100644 --- a/src/include/executor/nodeIndexscan.h +++ b/src/include/executor/nodeIndexscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeIndexscan.h @@ -28,6 +28,7 @@ extern void ExecIndexScanInitializeDSM(IndexScanState *node, ParallelContext *pc extern void ExecIndexScanReInitializeDSM(IndexScanState *node, ParallelContext *pcxt); extern void ExecIndexScanInitializeWorker(IndexScanState *node, ParallelWorkerContext *pwcxt); +extern void ExecIndexScanRetrieveInstrumentation(IndexScanState *node); /* * These routines are exported to share code with nodeIndexonlyscan.c and diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h index 7cf5c1cad61f7..97a472c8f36a3 100644 --- a/src/include/executor/nodeLimit.h +++ b/src/include/executor/nodeLimit.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeLimit.h diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h index 310d2ba4458db..ad7d63d32dc9d 100644 --- a/src/include/executor/nodeLockRows.h +++ b/src/include/executor/nodeLockRows.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeLockRows.h diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h index 0ba7d0edc6d78..30c7a25dc0483 100644 --- a/src/include/executor/nodeMaterial.h +++ b/src/include/executor/nodeMaterial.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeMaterial.h diff --git a/src/include/executor/nodeMemoize.h b/src/include/executor/nodeMemoize.h index 758dcd6fe1b84..77a08f97d5008 100644 --- a/src/include/executor/nodeMemoize.h +++ b/src/include/executor/nodeMemoize.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2021-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeMemoize.h diff --git a/src/include/executor/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h index c39a9fc0cb284..4eb05dc30d614 100644 --- a/src/include/executor/nodeMergeAppend.h +++ b/src/include/executor/nodeMergeAppend.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeMergeAppend.h diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h index e60e1bb3357b4..5e79acadae848 100644 --- a/src/include/executor/nodeMergejoin.h +++ b/src/include/executor/nodeMergejoin.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeMergejoin.h diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index 681cdaa89dbc8..bf3b592e28fd1 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -3,7 +3,7 @@ * nodeModifyTable.h * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeModifyTable.h @@ -15,9 +15,9 @@ #include "nodes/execnodes.h" -extern void ExecInitStoredGenerated(ResultRelInfo *resultRelInfo, - EState *estate, - CmdType cmdtype); +extern void ExecInitGenerated(ResultRelInfo *resultRelInfo, + EState *estate, + CmdType cmdtype); extern void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, EState *estate, TupleTableSlot *slot, diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h index 97d1982006331..abfe4a2789677 100644 --- a/src/include/executor/nodeNamedtuplestorescan.h +++ b/src/include/executor/nodeNamedtuplestorescan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeNamedtuplestorescan.h diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h index 37dff400d376c..5a24cc9e8498d 100644 --- a/src/include/executor/nodeNestloop.h +++ b/src/include/executor/nodeNestloop.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeNestloop.h diff --git a/src/include/executor/nodeProjectSet.h b/src/include/executor/nodeProjectSet.h index 4ae6cffab5424..b0c7df0fb8068 100644 --- a/src/include/executor/nodeProjectSet.h +++ b/src/include/executor/nodeProjectSet.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeProjectSet.h diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h index f108d4553bdf0..7a5f20311b694 100644 --- a/src/include/executor/nodeRecursiveunion.h +++ b/src/include/executor/nodeRecursiveunion.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeRecursiveunion.h diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h index 1332640ab92c3..575e3639a9bc5 100644 --- a/src/include/executor/nodeResult.h +++ b/src/include/executor/nodeResult.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeResult.h diff --git a/src/include/executor/nodeSamplescan.h b/src/include/executor/nodeSamplescan.h index 838c1bf4abd2b..48fa135bb8010 100644 --- a/src/include/executor/nodeSamplescan.h +++ b/src/include/executor/nodeSamplescan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSamplescan.h diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h index 68f689e69417e..3adad8b585b22 100644 --- a/src/include/executor/nodeSeqscan.h +++ b/src/include/executor/nodeSeqscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSeqscan.h diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h index 9c484c1eab958..024c6ba1fceb8 100644 --- a/src/include/executor/nodeSetOp.h +++ b/src/include/executor/nodeSetOp.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSetOp.h diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h index 0fb2a12d8fbdc..f3b7f1895b58e 100644 --- a/src/include/executor/nodeSort.h +++ b/src/include/executor/nodeSort.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSort.h diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h index ad4014701f32a..a1cafbcc694d1 100644 --- a/src/include/executor/nodeSubplan.h +++ b/src/include/executor/nodeSubplan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSubplan.h diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h index f3cdec581c643..8276a728e294a 100644 --- a/src/include/executor/nodeSubqueryscan.h +++ b/src/include/executor/nodeSubqueryscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeSubqueryscan.h diff --git a/src/include/executor/nodeTableFuncscan.h b/src/include/executor/nodeTableFuncscan.h index b0fab0728a2f0..eb71a18a42be3 100644 --- a/src/include/executor/nodeTableFuncscan.h +++ b/src/include/executor/nodeTableFuncscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeTableFuncscan.h diff --git a/src/include/executor/nodeTidrangescan.h b/src/include/executor/nodeTidrangescan.h index 1cfc7a07be9b4..a831f1202cae3 100644 --- a/src/include/executor/nodeTidrangescan.h +++ b/src/include/executor/nodeTidrangescan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeTidrangescan.h diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h index b17de5dd3e917..5ef5781bd7115 100644 --- a/src/include/executor/nodeTidscan.h +++ b/src/include/executor/nodeTidscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeTidscan.h diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h index 9f1d39a0cc05d..2964b50a9bb30 100644 --- a/src/include/executor/nodeUnique.h +++ b/src/include/executor/nodeUnique.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeUnique.h diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h index 56096ce3d86f6..4a09fcce63dd2 100644 --- a/src/include/executor/nodeValuesscan.h +++ b/src/include/executor/nodeValuesscan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeValuesscan.h diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h index 1138af953a498..2e96683307613 100644 --- a/src/include/executor/nodeWindowAgg.h +++ b/src/include/executor/nodeWindowAgg.h @@ -4,7 +4,7 @@ * prototypes for nodeWindowAgg.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeWindowAgg.h diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h index 7198a67c33903..f21e6524abdf0 100644 --- a/src/include/executor/nodeWorktablescan.h +++ b/src/include/executor/nodeWorktablescan.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/nodeWorktablescan.h diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index 48b87730ea039..d064d1a9b76f9 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -3,7 +3,7 @@ * spi.h * Server Programming Interface public declarations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/spi.h diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h index 1129ae094e2f1..cc6688d5940e9 100644 --- a/src/include/executor/spi_priv.h +++ b/src/include/executor/spi_priv.h @@ -3,7 +3,7 @@ * spi_priv.h * Server Programming Interface private declarations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/spi_priv.h diff --git a/src/include/executor/tablefunc.h b/src/include/executor/tablefunc.h index f8ceef387cf8f..2c4498c5955e7 100644 --- a/src/include/executor/tablefunc.h +++ b/src/include/executor/tablefunc.h @@ -3,7 +3,7 @@ * tablefunc.h * interface for TableFunc executor node * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/tablefunc.h diff --git a/src/include/executor/tqueue.h b/src/include/executor/tqueue.h index 093a6b8875ce1..57d68a49c5807 100644 --- a/src/include/executor/tqueue.h +++ b/src/include/executor/tqueue.h @@ -3,7 +3,7 @@ * tqueue.h * Use shm_mq to send & receive tuples between parallel backends * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/tqueue.h diff --git a/src/include/executor/tstoreReceiver.h b/src/include/executor/tstoreReceiver.h index a46adad031698..11feca70b0e88 100644 --- a/src/include/executor/tstoreReceiver.h +++ b/src/include/executor/tstoreReceiver.h @@ -4,7 +4,7 @@ * prototypes for tstoreReceiver.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/tstoreReceiver.h diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index b82655e7e5551..095e4cc82e3d8 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -4,7 +4,7 @@ * tuple table support stuff * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/executor/tuptable.h @@ -218,8 +218,12 @@ struct TupleTableSlotOps * meaningful "system columns" in the copy. The copy is not be "owned" by * the slot i.e. the caller has to take responsibility to free memory * consumed by the slot. + * + * The copy has "extra" bytes (maxaligned and zeroed) available before the + * tuple, which is useful so that some callers may store extra data along + * with the minimal tuple without the need for an additional allocation. */ - MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot); + MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot, Size extra); }; /* @@ -491,7 +495,19 @@ ExecCopySlotHeapTuple(TupleTableSlot *slot) static inline MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot) { - return slot->tts_ops->copy_minimal_tuple(slot); + return slot->tts_ops->copy_minimal_tuple(slot, 0); +} + +/* + * ExecCopySlotMinimalTupleExtra - return MinimalTuple allocated in caller's + * context, with extra bytes (maxaligned and zeroed) before the tuple for data + * the caller wishes to store along with the tuple (without requiring the + * caller to make an additional allocation). + */ +static inline MinimalTuple +ExecCopySlotMinimalTupleExtra(TupleTableSlot *slot, Size extra) +{ + return slot->tts_ops->copy_minimal_tuple(slot, extra); } /* diff --git a/src/include/fe_utils/archive.h b/src/include/fe_utils/archive.h index 1df671978fadf..bd744c320d89d 100644 --- a/src/include/fe_utils/archive.h +++ b/src/include/fe_utils/archive.h @@ -3,7 +3,7 @@ * archive.h * Routines to access WAL archives from frontend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/archive.h diff --git a/src/include/fe_utils/astreamer.h b/src/include/fe_utils/astreamer.h new file mode 100644 index 0000000000000..0e0031741fa51 --- /dev/null +++ b/src/include/fe_utils/astreamer.h @@ -0,0 +1,229 @@ +/*------------------------------------------------------------------------- + * + * astreamer.h + * + * The "archive streamer" interface is intended to allow frontend code + * to stream from possibly-compressed archive files from any source and + * perform arbitrary actions based on the contents of those archives. + * Archive streamers are intended to be composable, and most tasks will + * require two or more archive streamers to complete. For instance, + * if the input is an uncompressed tar stream, a tar parser astreamer + * could be used to interpret it, and then an extractor astreamer could + * be used to write each archive member out to a file. + * + * In general, each archive streamer is relatively free to take whatever + * action it desires in the stream of chunks provided by the caller. It + * may do something simple, like write the archive to a file, perhaps after + * compressing it, but it can also do more complicated things, like + * annotating the byte stream to indicate which parts of the data + * correspond to tar headers or trailing padding, vs. which parts are + * payload data. A subsequent astreamer may use this information to + * make further decisions about how to process the data; for example, + * it might choose to modify the archive contents. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/include/fe_utils/astreamer.h + *------------------------------------------------------------------------- + */ + +#ifndef ASTREAMER_H +#define ASTREAMER_H + +#include "common/compression.h" +#include "lib/stringinfo.h" +#include "pqexpbuffer.h" + +struct astreamer; +struct astreamer_ops; +typedef struct astreamer astreamer; +typedef struct astreamer_ops astreamer_ops; + +/* + * Each chunk of archive data passed to a astreamer is classified into one + * of these categories. When data is initially passed to an archive streamer, + * each chunk will be categorized as ASTREAMER_UNKNOWN, and the chunks can + * be of whatever size the caller finds convenient. + * + * If the archive is parsed (e.g. see astreamer_tar_parser_new()), then all + * chunks should be labelled as one of the other types listed here. In + * addition, there should be exactly one ASTREAMER_MEMBER_HEADER chunk and + * exactly one ASTREAMER_MEMBER_TRAILER chunk per archive member, even if + * that means a zero-length call. There can be any number of + * ASTREAMER_MEMBER_CONTENTS chunks in between those calls. There + * should exactly ASTREAMER_ARCHIVE_TRAILER chunk, and it should follow the + * last ASTREAMER_MEMBER_TRAILER chunk. + * + * In theory, we could need other classifications here, such as a way of + * indicating an archive header, but the "tar" format doesn't need anything + * else, so for the time being there's no point. + */ +typedef enum +{ + ASTREAMER_UNKNOWN, + ASTREAMER_MEMBER_HEADER, + ASTREAMER_MEMBER_CONTENTS, + ASTREAMER_MEMBER_TRAILER, + ASTREAMER_ARCHIVE_TRAILER, +} astreamer_archive_context; + +/* + * Each chunk of data that is classified as ASTREAMER_MEMBER_HEADER, + * ASTREAMER_MEMBER_CONTENTS, or ASTREAMER_MEMBER_TRAILER should also + * pass a pointer to an instance of this struct. The details are expected + * to be present in the archive header and used to fill the struct, after + * which all subsequent calls for the same archive member are expected to + * pass the same details. + */ +typedef struct +{ + char pathname[MAXPGPATH]; + pgoff_t size; + mode_t mode; + uid_t uid; + gid_t gid; + bool is_directory; + bool is_link; + char linktarget[MAXPGPATH]; +} astreamer_member; + +/* + * Generally, each type of astreamer will define its own struct, but the + * first element should be 'astreamer base'. A astreamer that does not + * require any additional private data could use this structure directly. + * + * bbs_ops is a pointer to the astreamer_ops object which contains the + * function pointers appropriate to this type of astreamer. + * + * bbs_next is a pointer to the successor astreamer, for those types of + * astreamer which forward data to a successor. It need not be used and + * should be set to NULL when not relevant. + * + * bbs_buffer is a buffer for accumulating data for temporary storage. Each + * type of astreamer makes its own decisions about whether and how to use + * this buffer. + */ +struct astreamer +{ + const astreamer_ops *bbs_ops; + astreamer *bbs_next; + StringInfoData bbs_buffer; +}; + +/* + * There are three callbacks for a astreamer. The 'content' callback is + * called repeatedly, as described in the astreamer_archive_context comments. + * Then, the 'finalize' callback is called once at the end, to give the + * astreamer a chance to perform cleanup such as closing files. Finally, + * because this code is running in a frontend environment where, as of this + * writing, there are no memory contexts, the 'free' callback is called to + * release memory. These callbacks should always be invoked using the static + * inline functions defined below. + */ +struct astreamer_ops +{ + void (*content) (astreamer *streamer, astreamer_member *member, + const char *data, int len, + astreamer_archive_context context); + void (*finalize) (astreamer *streamer); + void (*free) (astreamer *streamer); +}; + +/* Send some content to a astreamer. */ +static inline void +astreamer_content(astreamer *streamer, astreamer_member *member, + const char *data, int len, + astreamer_archive_context context) +{ + Assert(streamer != NULL); + streamer->bbs_ops->content(streamer, member, data, len, context); +} + +/* Finalize a astreamer. */ +static inline void +astreamer_finalize(astreamer *streamer) +{ + Assert(streamer != NULL); + streamer->bbs_ops->finalize(streamer); +} + +/* Free a astreamer. */ +static inline void +astreamer_free(astreamer *streamer) +{ + Assert(streamer != NULL); + streamer->bbs_ops->free(streamer); +} + +/* + * This is a convenience method for use when implementing a astreamer; it is + * not for use by outside callers. It adds the amount of data specified by + * 'nbytes' to the astreamer's buffer and adjusts '*len' and '*data' + * accordingly. + */ +static inline void +astreamer_buffer_bytes(astreamer *streamer, const char **data, int *len, + int nbytes) +{ + Assert(nbytes <= *len); + + appendBinaryStringInfo(&streamer->bbs_buffer, *data, nbytes); + *len -= nbytes; + *data += nbytes; +} + +/* + * This is a convenience method for use when implementing a astreamer; it is + * not for use by outsider callers. It attempts to add enough data to the + * astreamer's buffer to reach a length of target_bytes and adjusts '*len' + * and '*data' accordingly. It returns true if the target length has been + * reached and false otherwise. + */ +static inline bool +astreamer_buffer_until(astreamer *streamer, const char **data, int *len, + int target_bytes) +{ + int buflen = streamer->bbs_buffer.len; + + if (buflen >= target_bytes) + { + /* Target length already reached; nothing to do. */ + return true; + } + + if (buflen + *len < target_bytes) + { + /* Not enough data to reach target length; buffer all of it. */ + astreamer_buffer_bytes(streamer, data, len, *len); + return false; + } + + /* Buffer just enough to reach the target length. */ + astreamer_buffer_bytes(streamer, data, len, target_bytes - buflen); + return true; +} + +/* + * Functions for creating astreamer objects of various types. See the header + * comments for each of these functions for details. + */ +extern astreamer *astreamer_plain_writer_new(char *pathname, FILE *file); +extern astreamer *astreamer_gzip_writer_new(char *pathname, FILE *file, + pg_compress_specification *compress); +extern astreamer *astreamer_extractor_new(const char *basepath, + const char *(*link_map) (const char *), + void (*report_output_file) (const char *)); + +extern astreamer *astreamer_gzip_decompressor_new(astreamer *next); +extern astreamer *astreamer_lz4_compressor_new(astreamer *next, + pg_compress_specification *compress); +extern astreamer *astreamer_lz4_decompressor_new(astreamer *next); +extern astreamer *astreamer_zstd_compressor_new(astreamer *next, + pg_compress_specification *compress); +extern astreamer *astreamer_zstd_decompressor_new(astreamer *next); +extern astreamer *astreamer_tar_parser_new(astreamer *next); +extern astreamer *astreamer_tar_terminator_new(astreamer *next); +extern astreamer *astreamer_tar_archiver_new(astreamer *next); + +#endif diff --git a/src/include/fe_utils/cancel.h b/src/include/fe_utils/cancel.h index e934f6cdd4c0c..977115fad4df8 100644 --- a/src/include/fe_utils/cancel.h +++ b/src/include/fe_utils/cancel.h @@ -3,7 +3,7 @@ * Query cancellation support for frontend code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/cancel.h diff --git a/src/include/fe_utils/conditional.h b/src/include/fe_utils/conditional.h index 1da96ced2eefc..435e97557555d 100644 --- a/src/include/fe_utils/conditional.h +++ b/src/include/fe_utils/conditional.h @@ -14,7 +14,7 @@ * a true branch?) so that the interpreter knows whether to execute * code and whether to evaluate conditions. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/fe_utils/conditional.h * diff --git a/src/include/fe_utils/connect_utils.h b/src/include/fe_utils/connect_utils.h index 1267d7f8ce8c0..26bd5064843db 100644 --- a/src/include/fe_utils/connect_utils.h +++ b/src/include/fe_utils/connect_utils.h @@ -2,7 +2,7 @@ * * Facilities for frontend code to connect to and disconnect from databases. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/connect_utils.h diff --git a/src/include/fe_utils/mbprint.h b/src/include/fe_utils/mbprint.h index d7f42f893d9f3..c8e37969e7d31 100644 --- a/src/include/fe_utils/mbprint.h +++ b/src/include/fe_utils/mbprint.h @@ -3,7 +3,7 @@ * Multibyte character printing support for frontend code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/mbprint.h diff --git a/src/include/fe_utils/option_utils.h b/src/include/fe_utils/option_utils.h index afd108fdabfa4..4504bbb36a83c 100644 --- a/src/include/fe_utils/option_utils.h +++ b/src/include/fe_utils/option_utils.h @@ -2,7 +2,7 @@ * * Command line option processing facilities for frontend code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/option_utils.h @@ -12,8 +12,6 @@ #ifndef OPTION_UTILS_H #define OPTION_UTILS_H -#include "postgres_fe.h" - #include "common/file_utils.h" typedef void (*help_handler) (const char *progname); diff --git a/src/include/fe_utils/parallel_slot.h b/src/include/fe_utils/parallel_slot.h index 4d79030aa6caf..7770a20de3456 100644 --- a/src/include/fe_utils/parallel_slot.h +++ b/src/include/fe_utils/parallel_slot.h @@ -3,7 +3,7 @@ * parallel_slot.h * Parallel support for bin/scripts/ * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/fe_utils/parallel_slot.h * diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h index 72824c5c2fa7c..c99c2ee1a31a2 100644 --- a/src/include/fe_utils/print.h +++ b/src/include/fe_utils/print.h @@ -3,7 +3,7 @@ * Query-result printing support for frontend code * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/print.h diff --git a/src/include/fe_utils/psqlscan.h b/src/include/fe_utils/psqlscan.h index ea489efbec26f..39d2065fe987b 100644 --- a/src/include/fe_utils/psqlscan.h +++ b/src/include/fe_utils/psqlscan.h @@ -10,7 +10,7 @@ * backslash commands. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/psqlscan.h @@ -87,4 +87,7 @@ extern void psql_scan_reselect_sql_lexer(PsqlScanState state); extern bool psql_scan_in_quote(PsqlScanState state); +extern void psql_scan_get_location(PsqlScanState state, + int *lineno, int *offset); + #endif /* PSQLSCAN_H */ diff --git a/src/include/fe_utils/psqlscan_int.h b/src/include/fe_utils/psqlscan_int.h index be3524e37e31d..2a3a9d7c82aaa 100644 --- a/src/include/fe_utils/psqlscan_int.h +++ b/src/include/fe_utils/psqlscan_int.h @@ -34,7 +34,7 @@ * same flex version, or if they don't use the same flex options. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/psqlscan_int.h @@ -104,6 +104,10 @@ typedef struct PsqlScanStateData const char *curline; /* actual flex input string for cur buf */ const char *refline; /* original data for cur buffer */ + /* status for psql_scan_get_location() */ + int cur_line_no; /* current line#, or 0 if no yylex done */ + const char *cur_line_ptr; /* points into cur_line_no'th line in scanbuf */ + /* * All this state lives across successive input lines, until explicitly * reset by psql_scan_reset. start_state is adopted by yylex() on entry, diff --git a/src/include/fe_utils/query_utils.h b/src/include/fe_utils/query_utils.h index 9a680d5bffe12..4d7f7d6057330 100644 --- a/src/include/fe_utils/query_utils.h +++ b/src/include/fe_utils/query_utils.h @@ -2,7 +2,7 @@ * * Facilities for frontend code to query a databases. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/query_utils.h @@ -12,8 +12,6 @@ #ifndef QUERY_UTILS_H #define QUERY_UTILS_H -#include "postgres_fe.h" - #include "libpq-fe.h" extern PGresult *executeQuery(PGconn *conn, const char *query, bool echo); diff --git a/src/include/fe_utils/recovery_gen.h b/src/include/fe_utils/recovery_gen.h index 73c1aa8e59e1a..c13f2263bcd33 100644 --- a/src/include/fe_utils/recovery_gen.h +++ b/src/include/fe_utils/recovery_gen.h @@ -2,7 +2,7 @@ * * Generator for recovery configuration * - * Portions Copyright (c) 2011-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2011-2025, PostgreSQL Global Development Group * * src/include/fe_utils/recovery_gen.h * @@ -25,5 +25,6 @@ extern PQExpBuffer GenerateRecoveryConfig(PGconn *pgconn, char *dbname); extern void WriteRecoveryConfig(PGconn *pgconn, const char *target_dir, PQExpBuffer contents); +extern char *GetDbnameFromConnectionOptions(const char *connstr); #endif /* RECOVERY_GEN_H */ diff --git a/src/include/fe_utils/simple_list.h b/src/include/fe_utils/simple_list.h index d42ecded8ed5d..3b8e38414ecde 100644 --- a/src/include/fe_utils/simple_list.h +++ b/src/include/fe_utils/simple_list.h @@ -7,7 +7,7 @@ * facilities, but it's all we need in, eg, pg_dump. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/simple_list.h @@ -66,5 +66,6 @@ extern void simple_string_list_destroy(SimpleStringList *list); extern const char *simple_string_list_not_touched(SimpleStringList *list); extern void simple_ptr_list_append(SimplePtrList *list, void *ptr); +extern void simple_ptr_list_destroy(SimplePtrList *list); #endif /* SIMPLE_LIST_H */ diff --git a/src/include/fe_utils/string_utils.h b/src/include/fe_utils/string_utils.h index f150a7f7ef7d8..dc991a932194a 100644 --- a/src/include/fe_utils/string_utils.h +++ b/src/include/fe_utils/string_utils.h @@ -6,7 +6,7 @@ * assorted contexts. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fe_utils/string_utils.h @@ -25,7 +25,10 @@ extern PQExpBuffer (*getLocalPQExpBuffer) (void); /* Functions */ extern const char *fmtId(const char *rawid); +extern const char *fmtIdEnc(const char *rawid, int encoding); extern const char *fmtQualifiedId(const char *schema, const char *id); +extern const char *fmtQualifiedIdEnc(const char *schema, const char *id, int encoding); +extern void setFmtEncoding(int encoding); extern char *formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen); diff --git a/src/include/fmgr.h b/src/include/fmgr.h index ccb4070a25140..0fe7b4ebc7719 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -8,7 +8,7 @@ * or call fmgr-callable functions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/fmgr.h @@ -425,14 +425,13 @@ extern int no_such_variable /* - * Declare _PG_init/_PG_fini centrally. Historically each shared library had - * its own declaration; but now that we want to mark these PGDLLEXPORT, using - * central declarations avoids each extension having to add that. Any - * existing declarations in extensions will continue to work if fmgr.h is - * included before them, otherwise compilation for Windows will fail. + * Declare _PG_init centrally. Historically each shared library had its own + * declaration; but now that we want to mark these PGDLLEXPORT, using central + * declarations avoids each extension having to add that. Any existing + * declarations in extensions will continue to work if fmgr.h is included + * before them, otherwise compilation for Windows will fail. */ extern PGDLLEXPORT void _PG_init(void); -extern PGDLLEXPORT void _PG_fini(void); /*------------------------------------------------------------------------- @@ -441,41 +440,52 @@ extern PGDLLEXPORT void _PG_fini(void); * We require dynamically-loaded modules to include the macro call * PG_MODULE_MAGIC; * so that we can check for obvious incompatibility, such as being compiled - * for a different major PostgreSQL version. + * for a different major PostgreSQL version. Alternatively, write + * PG_MODULE_MAGIC_EXT(...); + * where the optional arguments can specify module name and version, and + * perhaps other values in future. Note that in a multiple-source-file + * module, there should be exactly one such macro call. * - * To compile with versions of PostgreSQL that do not support this, - * you may put an #ifdef/#endif test around it. Note that in a multiple- - * source-file module, the macro call should only appear once. + * You may need an #ifdef test to verify that the version of PostgreSQL + * you are compiling against supports PG_MODULE_MAGIC_EXT(). * - * The specific items included in the magic block are intended to be ones that + * The specific items included in the ABI fields are intended to be ones that * are custom-configurable and especially likely to break dynamically loaded * modules if they were compiled with other values. Also, the length field * can be used to detect definition changes. * - * Note: we compare magic blocks with memcmp(), so there had better not be - * any alignment pad bytes in them. + * Note: we compare Pg_abi_values structs with memcmp(), so there had better + * not be any alignment pad bytes in them. * - * Note: when changing the contents of magic blocks, be sure to adjust the + * Note: when changing the contents of Pg_abi_values, be sure to adjust the * incompatible_module_error() function in dfmgr.c. *------------------------------------------------------------------------- */ -/* Definition of the magic block structure */ +/* Definition of the values we check to verify ABI compatibility */ typedef struct { - int len; /* sizeof(this struct) */ int version; /* PostgreSQL major version */ int funcmaxargs; /* FUNC_MAX_ARGS */ int indexmaxkeys; /* INDEX_MAX_KEYS */ int namedatalen; /* NAMEDATALEN */ int float8byval; /* FLOAT8PASSBYVAL */ char abi_extra[32]; /* see pg_config_manual.h */ +} Pg_abi_values; + +/* Definition of the magic block structure */ +typedef struct +{ + int len; /* sizeof(this struct) */ + Pg_abi_values abi_fields; /* see above */ + /* Remaining fields are zero unless filled via PG_MODULE_MAGIC_EXT */ + const char *name; /* optional module name */ + const char *version; /* optional module version */ } Pg_magic_struct; -/* The actual data block contents */ -#define PG_MODULE_MAGIC_DATA \ +/* Macro to fill the ABI fields */ +#define PG_MODULE_ABI_DATA \ { \ - sizeof(Pg_magic_struct), \ PG_VERSION_NUM / 100, \ FUNC_MAX_ARGS, \ INDEX_MAX_KEYS, \ @@ -484,7 +494,18 @@ typedef struct FMGR_ABI_EXTRA, \ } -StaticAssertDecl(sizeof(FMGR_ABI_EXTRA) <= sizeof(((Pg_magic_struct *) 0)->abi_extra), +/* + * Macro to fill a magic block. If any arguments are given, they should + * be field initializers. + */ +#define PG_MODULE_MAGIC_DATA(...) \ +{ \ + .len = sizeof(Pg_magic_struct), \ + .abi_fields = PG_MODULE_ABI_DATA, \ + __VA_ARGS__ \ +} + +StaticAssertDecl(sizeof(FMGR_ABI_EXTRA) <= sizeof(((Pg_abi_values *) 0)->abi_extra), "FMGR_ABI_EXTRA too long"); /* @@ -501,7 +522,26 @@ extern PGDLLEXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \ const Pg_magic_struct * \ PG_MAGIC_FUNCTION_NAME(void) \ { \ - static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \ + static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA(.name = NULL); \ + return &Pg_magic_data; \ +} \ +extern int no_such_variable + +/* + * Alternate declaration that allows specification of additional fields. + * The additional values should be written as field initializers, for example + * PG_MODULE_MAGIC_EXT( + * .name = "some string", + * .version = "some string" + * ); + */ +#define PG_MODULE_MAGIC_EXT(...) \ +extern PGDLLEXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \ +const Pg_magic_struct * \ +PG_MAGIC_FUNCTION_NAME(void) \ +{ \ + static const Pg_magic_struct Pg_magic_data = \ + PG_MODULE_MAGIC_DATA(__VA_ARGS__); \ return &Pg_magic_data; \ } \ extern int no_such_variable @@ -739,12 +779,23 @@ extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid); /* * Routines in dfmgr.c */ +typedef struct DynamicFileList DynamicFileList; /* opaque outside dfmgr.c */ + extern PGDLLIMPORT char *Dynamic_library_path; +extern char *substitute_path_macro(const char *str, const char *macro, const char *value); +extern char *find_in_path(const char *basename, const char *path, const char *path_param, + const char *macro, const char *macro_val); extern void *load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle); extern void *lookup_external_function(void *filehandle, const char *funcname); extern void load_file(const char *filename, bool restricted); +extern DynamicFileList *get_first_loaded_module(void); +extern DynamicFileList *get_next_loaded_module(DynamicFileList *dfptr); +extern void get_loaded_module_details(DynamicFileList *dfptr, + const char **library_path, + const char **module_name, + const char **module_version); extern void **find_rendezvous_variable(const char *varName); extern Size EstimateLibraryStateSpace(void); extern void SerializeLibraryState(Size maxsize, char *start_address); diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index fcde3876b288e..b4da4e6a16aac 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -3,7 +3,7 @@ * fdwapi.h * API for foreign-data wrappers * - * Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/foreign/fdwapi.h * diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 82b8153100fd1..7e9decd253789 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -4,7 +4,7 @@ * support for foreign-data wrappers, servers and user mappings. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/foreign/foreign.h * diff --git a/src/include/funcapi.h b/src/include/funcapi.h index 1529549a657f3..94b89b36192b8 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -8,7 +8,7 @@ * or call FUNCAPI-callable functions or macros. * * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * * src/include/funcapi.h * diff --git a/src/include/getopt_long.h b/src/include/getopt_long.h index 0fdbefae7fbc8..e7bdf909f7bed 100644 --- a/src/include/getopt_long.h +++ b/src/include/getopt_long.h @@ -2,14 +2,15 @@ * Portions Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * - * Portions Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/getopt_long.h */ +/* IWYU pragma: always_keep */ #ifndef GETOPT_LONG_H #define GETOPT_LONG_H -#include "pg_getopt.h" +#include "pg_getopt.h" /* IWYU pragma: export */ #ifndef HAVE_STRUCT_OPTION diff --git a/src/include/jit/SectionMemoryManager.h b/src/include/jit/SectionMemoryManager.h new file mode 100644 index 0000000000000..924a99b0d333a --- /dev/null +++ b/src/include/jit/SectionMemoryManager.h @@ -0,0 +1,226 @@ +/* + * This is a copy LLVM source code modified by the PostgreSQL project. + * See SectionMemoryManager.cpp for notes on provenance and license. + */ + +//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of a section-based memory manager used by +// the MCJIT execution engine and RuntimeDyld. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H + +#include +#include +#include +#include +#include +#include +#include + +namespace llvm { +namespace backport { + +/// This is a simple memory manager which implements the methods called by +/// the RuntimeDyld class to allocate memory for section-based loading of +/// objects, usually those generated by the MCJIT execution engine. +/// +/// This memory manager allocates all section memory as read-write. The +/// RuntimeDyld will copy JITed section memory into these allocated blocks +/// and perform any necessary linking and relocations. +/// +/// Any client using this memory manager MUST ensure that section-specific +/// page permissions have been applied before attempting to execute functions +/// in the JITed object. Permissions can be applied either by calling +/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory +/// directly. Clients of MCJIT should call MCJIT::finalizeObject. +class SectionMemoryManager : public RTDyldMemoryManager { +public: + /// This enum describes the various reasons to allocate pages from + /// allocateMappedMemory. + enum class AllocationPurpose { + Code, + ROData, + RWData, + }; + + /// Implementations of this interface are used by SectionMemoryManager to + /// request pages from the operating system. + class MemoryMapper { + public: + /// This method attempts to allocate \p NumBytes bytes of virtual memory for + /// \p Purpose. \p NearBlock may point to an existing allocation, in which + /// case an attempt is made to allocate more memory near the existing block. + /// The actual allocated address is not guaranteed to be near the requested + /// address. \p Flags is used to set the initial protection flags for the + /// block of the memory. \p EC [out] returns an object describing any error + /// that occurs. + /// + /// This method may allocate more than the number of bytes requested. The + /// actual number of bytes allocated is indicated in the returned + /// MemoryBlock. + /// + /// The start of the allocated block must be aligned with the system + /// allocation granularity (64K on Windows, page size on Linux). If the + /// address following \p NearBlock is not so aligned, it will be rounded up + /// to the next allocation granularity boundary. + /// + /// \r a non-null MemoryBlock if the function was successful, otherwise a + /// null MemoryBlock with \p EC describing the error. + virtual sys::MemoryBlock + allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes, + const sys::MemoryBlock *const NearBlock, + unsigned Flags, std::error_code &EC) = 0; + + /// This method sets the protection flags for a block of memory to the state + /// specified by \p Flags. The behavior is not specified if the memory was + /// not allocated using the allocateMappedMemory method. + /// \p Block describes the memory block to be protected. + /// \p Flags specifies the new protection state to be assigned to the block. + /// + /// If \p Flags is MF_WRITE, the actual behavior varies with the operating + /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture + /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block, + unsigned Flags) = 0; + + /// This method releases a block of memory that was allocated with the + /// allocateMappedMemory method. It should not be used to release any memory + /// block allocated any other way. + /// \p Block describes the memory to be released. + /// + /// \r error_success if the function was successful, or an error_code + /// describing the failure if an error occurred. + virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0; + + virtual ~MemoryMapper(); + }; + + /// Creates a SectionMemoryManager instance with \p MM as the associated + /// memory mapper. If \p MM is nullptr then a default memory mapper is used + /// that directly calls into the operating system. + /// + /// If \p ReserveAlloc is true all memory will be pre-allocated, and any + /// attempts to allocate beyond pre-allocated memory will fail. + SectionMemoryManager(MemoryMapper *MM = nullptr, bool ReserveAlloc = false); + SectionMemoryManager(const SectionMemoryManager &) = delete; + void operator=(const SectionMemoryManager &) = delete; + ~SectionMemoryManager() override; + + /// Enable reserveAllocationSpace when requested. + bool needsToReserveAllocationSpace() override { return ReserveAllocation; } + + /// Implements allocating all memory in a single block. This is required to + /// limit memory offsets to fit the ARM ABI; large memory systems may + /// otherwise allocate separate sections too far apart. +#if LLVM_VERSION_MAJOR < 16 + virtual void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, + uintptr_t RODataSize, + uint32_t RODataAlign, + uintptr_t RWDataSize, + uint32_t RWDataAlign) override; +#else + void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign, + uintptr_t RODataSize, Align RODataAlign, + uintptr_t RWDataSize, Align RWDataAlign) override; +#endif + + /// Allocates a memory block of (at least) the given size suitable for + /// executable code. + /// + /// The value of \p Alignment must be a power of two. If \p Alignment is zero + /// a default alignment of 16 will be used. + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override; + + /// Allocates a memory block of (at least) the given size suitable for + /// executable code. + /// + /// The value of \p Alignment must be a power of two. If \p Alignment is zero + /// a default alignment of 16 will be used. + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool IsReadOnly) override; + + /// Update section-specific memory permissions and other attributes. + /// + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// \returns true if an error occurred, false otherwise. + bool finalizeMemory(std::string *ErrMsg = nullptr) override; + + /// Invalidate instruction cache for code sections. + /// + /// Some platforms with separate data cache and instruction cache require + /// explicit cache flush, otherwise JIT code manipulations (like resolved + /// relocations) will get to the data cache but not to the instruction cache. + /// + /// This method is called from finalizeMemory. + virtual void invalidateInstructionCache(); + +private: + struct FreeMemBlock { + // The actual block of free memory + sys::MemoryBlock Free; + // If there is a pending allocation from the same reservation right before + // this block, store its index in PendingMem, to be able to update the + // pending region if part of this block is allocated, rather than having to + // create a new one + unsigned PendingPrefixIndex; + }; + + struct MemoryGroup { + // PendingMem contains all blocks of memory (subblocks of AllocatedMem) + // which have not yet had their permissions applied, but have been given + // out to the user. FreeMem contains all block of memory, which have + // neither had their permissions applied, nor been given out to the user. + SmallVector PendingMem; + SmallVector FreeMem; + + // All memory blocks that have been requested from the system + SmallVector AllocatedMem; + + sys::MemoryBlock Near; + }; + + uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size, + unsigned Alignment); + + std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, + unsigned Permissions); + + bool hasSpace(const MemoryGroup &MemGroup, uintptr_t Size) const; + + void anchor() override; + + MemoryGroup CodeMem; + MemoryGroup RWDataMem; + MemoryGroup RODataMem; + MemoryMapper *MMapper; + std::unique_ptr OwnedMMapper; + bool ReserveAllocation; +}; + +} // end namespace backport +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_BACKPORT_SECTIONMEMORYMANAGER_H diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h index d9a080ce98f50..33cb36c5d2ef7 100644 --- a/src/include/jit/jit.h +++ b/src/include/jit/jit.h @@ -2,7 +2,7 @@ * jit.h * Provider independent JIT infrastructure. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/jit/jit.h * diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 420775b1899a6..5038cf33e3fe9 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -2,7 +2,7 @@ * llvmjit.h * LLVM JIT provider. * - * Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/jit/llvmjit.h * @@ -17,7 +17,12 @@ */ #ifdef USE_LLVM +#include "jit/llvmjit_backport.h" + #include +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER +#include +#endif /* @@ -135,6 +140,9 @@ extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDes */ extern LLVMTypeRef LLVMGetFunctionReturnType(LLVMValueRef r); extern LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r); +#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER +extern LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/src/include/jit/llvmjit_backport.h b/src/include/jit/llvmjit_backport.h new file mode 100644 index 0000000000000..cba8eafc4f3c8 --- /dev/null +++ b/src/include/jit/llvmjit_backport.h @@ -0,0 +1,22 @@ +/* + * A small header than can be included by backported LLVM code or PostgreSQL + * code, to control conditional compilation. + */ +#ifndef LLVMJIT_BACKPORT_H +#define LLVMJIT_BACKPORT_H + +#include + +/* + * LLVM's RuntimeDyld can produce code that crashes on larger memory ARM + * systems, because llvm::SectionMemoryManager allocates multiple pieces of + * memory that can be placed too far apart for the generated code. See + * src/backend/jit/llvm/SectionMemoryManager.cpp for the patched replacement + * class llvm::backport::SectionMemoryManager that we use as a workaround. + * This header controls whether we use it. + */ +#if defined(__aarch64__) +#define USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER +#endif + +#endif diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h index 4f35f3dca139f..df5a9fc85007a 100644 --- a/src/include/jit/llvmjit_emit.h +++ b/src/include/jit/llvmjit_emit.h @@ -2,7 +2,7 @@ * llvmjit_emit.h * Helpers to make emitting LLVM IR a bit more concise and pgindent proof. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * src/include/jit/llvmjit_emit.h */ @@ -107,41 +107,25 @@ l_pbool_const(bool i) static inline LLVMValueRef l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name) { -#if LLVM_VERSION_MAJOR < 16 - return LLVMBuildStructGEP(b, v, idx, ""); -#else return LLVMBuildStructGEP2(b, t, v, idx, ""); -#endif } static inline LLVMValueRef l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name) { -#if LLVM_VERSION_MAJOR < 16 - return LLVMBuildGEP(b, v, indices, nindices, name); -#else return LLVMBuildGEP2(b, t, v, indices, nindices, name); -#endif } static inline LLVMValueRef l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name) { -#if LLVM_VERSION_MAJOR < 16 - return LLVMBuildLoad(b, v, name); -#else return LLVMBuildLoad2(b, t, v, name); -#endif } static inline LLVMValueRef l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name) { -#if LLVM_VERSION_MAJOR < 16 - return LLVMBuildCall(b, fn, args, nargs, name); -#else return LLVMBuildCall2(b, t, fn, args, nargs, name); -#endif } /* diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h index 19025c08ef1f3..e8a575ed867f7 100644 --- a/src/include/lib/binaryheap.h +++ b/src/include/lib/binaryheap.h @@ -3,7 +3,7 @@ * * A simple binary heap implementation * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * src/include/lib/binaryheap.h */ diff --git a/src/include/lib/bipartite_match.h b/src/include/lib/bipartite_match.h index f34a7c151d20e..3ad8494f4d75c 100644 --- a/src/include/lib/bipartite_match.h +++ b/src/include/lib/bipartite_match.h @@ -1,7 +1,7 @@ /* * bipartite_match.h * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * src/include/lib/bipartite_match.h */ diff --git a/src/include/lib/bloomfilter.h b/src/include/lib/bloomfilter.h index 6ec7173843fff..dd9fddd8422c8 100644 --- a/src/include/lib/bloomfilter.h +++ b/src/include/lib/bloomfilter.h @@ -3,7 +3,7 @@ * bloomfilter.h * Space-efficient set membership testing * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/lib/bloomfilter.h diff --git a/src/include/lib/dshash.h b/src/include/lib/dshash.h index 7dda269b7535e..cf5c291cbbb44 100644 --- a/src/include/lib/dshash.h +++ b/src/include/lib/dshash.h @@ -3,7 +3,7 @@ * dshash.h * Concurrent hash tables backed by dynamic shared memory areas. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/lib/hyperloglog.h b/src/include/lib/hyperloglog.h index 45f7de710bdc1..1e9c50feeb82a 100644 --- a/src/include/lib/hyperloglog.h +++ b/src/include/lib/hyperloglog.h @@ -3,7 +3,7 @@ * * A simple HyperLogLog cardinality estimator implementation * - * Portions Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2014-2025, PostgreSQL Global Development Group * * Based on Hideaki Ohno's C++ implementation. The copyright terms of Ohno's * original version (the MIT license) follow. diff --git a/src/include/lib/ilist.h b/src/include/lib/ilist.h index 381f6158645e7..85a641eb41ddf 100644 --- a/src/include/lib/ilist.h +++ b/src/include/lib/ilist.h @@ -112,7 +112,7 @@ * } * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/lib/integerset.h b/src/include/lib/integerset.h index fb27466003c1e..00626a6353725 100644 --- a/src/include/lib/integerset.h +++ b/src/include/lib/integerset.h @@ -2,7 +2,7 @@ * integerset.h * In-memory data structure to hold a large set of integers efficiently * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * src/include/lib/integerset.h */ diff --git a/src/include/lib/knapsack.h b/src/include/lib/knapsack.h index 1a93841fdc462..b870122f1c8fa 100644 --- a/src/include/lib/knapsack.h +++ b/src/include/lib/knapsack.h @@ -1,7 +1,7 @@ /* * knapsack.h * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * src/include/lib/knapsack.h */ diff --git a/src/include/lib/pairingheap.h b/src/include/lib/pairingheap.h index 7eade81535a5e..3c57d3fda1bbe 100644 --- a/src/include/lib/pairingheap.h +++ b/src/include/lib/pairingheap.h @@ -3,7 +3,7 @@ * * A Pairing Heap implementation * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * src/include/lib/pairingheap.h */ diff --git a/src/include/lib/qunique.h b/src/include/lib/qunique.h index eda617fde5a09..c699053a9bcab 100644 --- a/src/include/lib/qunique.h +++ b/src/include/lib/qunique.h @@ -2,7 +2,7 @@ * * qunique.h * inline array unique functions - * Portions Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/lib/qunique.h diff --git a/src/include/lib/radixtree.h b/src/include/lib/radixtree.h index 88bf695e3f354..a75b77270c4e6 100644 --- a/src/include/lib/radixtree.h +++ b/src/include/lib/radixtree.h @@ -143,7 +143,7 @@ * RT_DELETE - Delete a key-value pair. Declared/defined if RT_USE_DELETE is defined * * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/lib/radixtree.h @@ -151,13 +151,15 @@ *------------------------------------------------------------------------- */ -#include "postgres.h" - #include "nodes/bitmapset.h" #include "port/pg_bitutils.h" #include "port/simd.h" #include "utils/dsa.h" #include "utils/memutils.h" +#ifdef RT_SHMEM +#include "miscadmin.h" +#include "storage/lwlock.h" +#endif /* helpers */ #define RT_MAKE_PREFIX(a) CppConcat(a,_) @@ -273,7 +275,7 @@ typedef dsa_pointer RT_HANDLE; #endif #ifdef RT_SHMEM -RT_SCOPE RT_RADIX_TREE *RT_CREATE(MemoryContext ctx, dsa_area *dsa, int tranche_id); +RT_SCOPE RT_RADIX_TREE *RT_CREATE(dsa_area *dsa, int tranche_id); RT_SCOPE RT_RADIX_TREE *RT_ATTACH(dsa_area *dsa, dsa_pointer dp); RT_SCOPE void RT_DETACH(RT_RADIX_TREE * tree); RT_SCOPE RT_HANDLE RT_GET_HANDLE(RT_RADIX_TREE * tree); @@ -704,8 +706,6 @@ typedef struct RT_RADIX_TREE_CONTROL /* Entry point for allocating and accessing the tree */ struct RT_RADIX_TREE { - MemoryContext context; - /* pointing to either local memory or DSA */ RT_RADIX_TREE_CONTROL *ctl; @@ -717,7 +717,6 @@ struct RT_RADIX_TREE /* leaf_context is used only for single-value leaves */ MemoryContextData *leaf_context; #endif - MemoryContextData *iter_context; }; /* @@ -1808,39 +1807,25 @@ RT_SET(RT_RADIX_TREE * tree, uint64 key, RT_VALUE_TYPE * value_p) /***************** SETUP / TEARDOWN *****************/ /* - * Create the radix tree in the given memory context and return it. + * Create the radix tree root in the caller's memory context and return it. * - * All local memory required for a radix tree is allocated in the given - * memory context and its children. Note that RT_FREE() will delete all - * allocated space within the given memory context, so the dsa_area should - * be created in a different context. + * The tree's nodes and leaves are allocated in "ctx" and its children for + * local memory, or in "dsa" for shared memory. */ RT_SCOPE RT_RADIX_TREE * #ifdef RT_SHMEM -RT_CREATE(MemoryContext ctx, dsa_area *dsa, int tranche_id) +RT_CREATE(dsa_area *dsa, int tranche_id) #else RT_CREATE(MemoryContext ctx) #endif { RT_RADIX_TREE *tree; - MemoryContext old_ctx; RT_CHILD_PTR rootnode; #ifdef RT_SHMEM dsa_pointer dp; #endif - old_ctx = MemoryContextSwitchTo(ctx); - tree = (RT_RADIX_TREE *) palloc0(sizeof(RT_RADIX_TREE)); - tree->context = ctx; - - /* - * Separate context for iteration in case the tree context doesn't support - * pfree - */ - tree->iter_context = AllocSetContextCreate(ctx, - RT_STR(RT_PREFIX) "_radix_tree iter context", - ALLOCSET_SMALL_SIZES); #ifdef RT_SHMEM tree->dsa = dsa; @@ -1864,21 +1849,7 @@ RT_CREATE(MemoryContext ctx) size_class.allocsize); } - /* By default we use the passed context for leaves. */ - tree->leaf_context = tree->context; - -#ifndef RT_VARLEN_VALUE_SIZE - - /* - * For leaves storing fixed-length values, we use a slab context to avoid - * the possibility of space wastage by power-of-2 rounding up. - */ - if (sizeof(RT_VALUE_TYPE) > sizeof(RT_PTR_ALLOC)) - tree->leaf_context = SlabContextCreate(ctx, - RT_STR(RT_PREFIX) "_radix_tree leaf context", - RT_SLAB_BLOCK_SIZE(sizeof(RT_VALUE_TYPE)), - sizeof(RT_VALUE_TYPE)); -#endif /* !RT_VARLEN_VALUE_SIZE */ + tree->leaf_context = ctx; #endif /* RT_SHMEM */ /* add root node now so that RT_SET can assume it exists */ @@ -1887,8 +1858,6 @@ RT_CREATE(MemoryContext ctx) tree->ctl->start_shift = 0; tree->ctl->max_val = RT_SHIFT_GET_MAX_VAL(0); - MemoryContextSwitchTo(old_ctx); - return tree; } @@ -2061,19 +2030,23 @@ RT_FREE(RT_RADIX_TREE * tree) */ tree->ctl->magic = 0; dsa_free(tree->dsa, tree->ctl->handle); -#endif - +#else /* - * Free all space allocated within the tree's context and delete all child + * Free all space allocated within the leaf context and delete all child * contexts such as those used for nodes. */ - MemoryContextReset(tree->context); + MemoryContextReset(tree->leaf_context); + + pfree(tree->ctl); +#endif + pfree(tree); } /***************** ITERATION *****************/ /* - * Create and return the iterator for the given radix tree. + * Create and return an iterator for the given radix tree + * in the caller's memory context. * * Taking a lock in shared mode during the iteration is the caller's * responsibility. @@ -2084,8 +2057,7 @@ RT_BEGIN_ITERATE(RT_RADIX_TREE * tree) RT_ITER *iter; RT_CHILD_PTR root; - iter = (RT_ITER *) MemoryContextAllocZero(tree->iter_context, - sizeof(RT_ITER)); + iter = (RT_ITER *) palloc0(sizeof(RT_ITER)); iter->tree = tree; Assert(RT_PTR_ALLOC_IS_VALID(tree->ctl->root)); @@ -2681,7 +2653,7 @@ RT_MEMORY_USAGE(RT_RADIX_TREE * tree) Assert(tree->ctl->magic == RT_RADIX_TREE_MAGIC); total = dsa_get_total_size(tree->dsa); #else - total = MemoryContextMemAllocated(tree->context, true); + total = MemoryContextMemAllocated(tree->leaf_context, true); #endif return total; @@ -2782,7 +2754,7 @@ RT_SCOPE void RT_STATS(RT_RADIX_TREE * tree) { fprintf(stderr, "max_val = " UINT64_FORMAT "\n", tree->ctl->max_val); - fprintf(stderr, "num_keys = %lld\n", (long long) tree->ctl->num_keys); + fprintf(stderr, "num_keys = %" PRId64 "\n", tree->ctl->num_keys); #ifdef RT_SHMEM fprintf(stderr, "handle = " DSA_POINTER_FORMAT "\n", tree->ctl->handle); @@ -2794,10 +2766,10 @@ RT_STATS(RT_RADIX_TREE * tree) { RT_SIZE_CLASS_ELEM size_class = RT_SIZE_CLASS_INFO[i]; - fprintf(stderr, ", n%d = %lld", size_class.fanout, (long long) tree->ctl->num_nodes[i]); + fprintf(stderr, ", n%d = %" PRId64, size_class.fanout, tree->ctl->num_nodes[i]); } - fprintf(stderr, ", leaves = %lld", (long long) tree->ctl->num_leaves); + fprintf(stderr, ", leaves = %" PRId64, tree->ctl->num_leaves); fprintf(stderr, "\n"); } diff --git a/src/include/lib/rbtree.h b/src/include/lib/rbtree.h index 16de4c012c8a2..37d6d8ed03719 100644 --- a/src/include/lib/rbtree.h +++ b/src/include/lib/rbtree.h @@ -3,7 +3,7 @@ * rbtree.h * interface for PostgreSQL generic Red-Black binary tree package * - * Copyright (c) 2009-2024, PostgreSQL Global Development Group + * Copyright (c) 2009-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/lib/rbtree.h diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h index 3e1b1f946167d..327274c2340bf 100644 --- a/src/include/lib/simplehash.h +++ b/src/include/lib/simplehash.h @@ -87,7 +87,7 @@ * looking or is done - buckets following a deleted element are shifted * backwards, unless they're empty or already at their optimal position. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/lib/simplehash.h diff --git a/src/include/lib/sort_template.h b/src/include/lib/sort_template.h index 00a04a6da4878..11e136ca53d06 100644 --- a/src/include/lib/sort_template.h +++ b/src/include/lib/sort_template.h @@ -5,7 +5,7 @@ * A template for a sort algorithm that supports varying degrees of * specialization. * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1992-1994, Regents of the University of California * * Usage notes: diff --git a/src/include/lib/stringinfo.h b/src/include/lib/stringinfo.h index cd9632e3fcacf..c96df989bb0b7 100644 --- a/src/include/lib/stringinfo.h +++ b/src/include/lib/stringinfo.h @@ -8,7 +8,7 @@ * (null-terminated text) or arbitrary binary data. All storage is allocated * with palloc() (falling back to malloc in frontend code). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/lib/stringinfo.h @@ -55,11 +55,15 @@ typedef StringInfoData *StringInfo; /*------------------------ - * There are four ways to create a StringInfo object initially: + * There are six ways to create a StringInfo object initially: * * StringInfo stringptr = makeStringInfo(); * Both the StringInfoData and the data buffer are palloc'd. * + * StringInfo stringptr = makeStringInfoExt(initsize); + * Same as makeStringInfo except the data buffer is allocated + * with size 'initsize'. + * * StringInfoData string; * initStringInfo(&string); * The data buffer is palloc'd but the StringInfoData is just local. @@ -67,6 +71,11 @@ typedef StringInfoData *StringInfo; * only live as long as the current routine. * * StringInfoData string; + * initStringInfoExt(&string, initsize); + * Same as initStringInfo except the data buffer is allocated + * with size 'initsize'. + * + * StringInfoData string; * initReadOnlyStringInfo(&string, existingbuf, len); * The StringInfoData's data field is set to point directly to the * existing buffer and the StringInfoData's len is set to the given len. @@ -100,12 +109,22 @@ typedef StringInfoData *StringInfo; *------------------------- */ +#define STRINGINFO_DEFAULT_SIZE 1024 /* default initial allocation size */ + /*------------------------ * makeStringInfo * Create an empty 'StringInfoData' & return a pointer to it. */ extern StringInfo makeStringInfo(void); +/*------------------------ + * makeStringInfoExt + * Create an empty 'StringInfoData' & return a pointer to it. + * The data buffer is allocated with size 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +extern StringInfo makeStringInfoExt(int initsize); + /*------------------------ * initStringInfo * Initialize a StringInfoData struct (with previously undefined contents) @@ -113,6 +132,14 @@ extern StringInfo makeStringInfo(void); */ extern void initStringInfo(StringInfo str); +/*------------------------ + * initStringInfoExt + * Initialize a StringInfoData struct (with previously undefined contents) to + * describe an empty string. The data buffer is allocated with size + * 'initsize'. The valid range for 'initsize' is 1 to MaxAllocSize. + */ +extern void initStringInfoExt(StringInfo str, int initsize); + /*------------------------ * initReadOnlyStringInfo * Initialize a StringInfoData struct from an existing string without copying diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h index 227b41daf656f..cc9643cce2fd8 100644 --- a/src/include/libpq/auth.h +++ b/src/include/libpq/auth.h @@ -4,7 +4,7 @@ * Definitions for network authentication routines * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/auth.h @@ -16,13 +16,30 @@ #include "libpq/libpq-be.h" +/* + * Maximum accepted size of GSS and SSPI authentication tokens. + * We also use this as a limit on ordinary password packet lengths. + * + * Kerberos tickets are usually quite small, but the TGTs issued by Windows + * domain controllers include an authorization field known as the Privilege + * Attribute Certificate (PAC), which contains the user's Windows permissions + * (group memberships etc.). The PAC is copied into all tickets obtained on + * the basis of this TGT (even those issued by Unix realms which the Windows + * realm trusts), and can be several kB in size. The maximum token size + * accepted by Windows systems is determined by the MaxAuthToken Windows + * registry setting. Microsoft recommends that it is not set higher than + * 65535 bytes, so that seems like a reasonable limit for us as well. + */ +#define PG_MAX_AUTH_TOKEN_LENGTH 65535 + extern PGDLLIMPORT char *pg_krb_server_keyfile; extern PGDLLIMPORT bool pg_krb_caseins_users; extern PGDLLIMPORT bool pg_gss_accept_delegation; extern void ClientAuthentication(Port *port); -extern void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, +extern void sendAuthRequest(Port *port, AuthRequest areq, const void *extradata, int extralen); +extern void set_authn_id(Port *port, const char *id); /* Hook for plugins to get control in ClientAuthentication() */ typedef void (*ClientAuthentication_hook_type) (Port *, int); diff --git a/src/include/libpq/be-fsstubs.h b/src/include/libpq/be-fsstubs.h index 336b9cef12508..1b006438e906f 100644 --- a/src/include/libpq/be-fsstubs.h +++ b/src/include/libpq/be-fsstubs.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/be-fsstubs.h diff --git a/src/include/libpq/be-gssapi-common.h b/src/include/libpq/be-gssapi-common.h index 474c3a6c1f1f6..bfe8d7656edeb 100644 --- a/src/include/libpq/be-gssapi-common.h +++ b/src/include/libpq/be-gssapi-common.h @@ -3,7 +3,7 @@ * be-gssapi-common.h * Definitions for GSSAPI authentication and encryption handling * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/be-gssapi-common.h @@ -16,13 +16,7 @@ #ifdef ENABLE_GSS -#if defined(HAVE_GSSAPI_H) -#include -#include -#else -#include -#include -#endif +#include "libpq/pg-gssapi.h" extern void pg_GSS_error(const char *errmsg, OM_uint32 maj_stat, OM_uint32 min_stat); diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h index f744de4d202b6..a1b4b36314336 100644 --- a/src/include/libpq/crypt.h +++ b/src/include/libpq/crypt.h @@ -3,7 +3,7 @@ * crypt.h * Interface to libpq/crypt.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/crypt.h @@ -15,6 +15,19 @@ #include "datatype/timestamp.h" +/* + * Valid password hashes may be very long, but we don't want to store anything + * that might need out-of-line storage, since de-TOASTing won't work during + * authentication because we haven't selected a database yet and cannot read + * pg_class. 512 bytes should be more than enough for all practical use, and + * our own password encryption routines should never produce hashes longer than + * this. + */ +#define MAX_ENCRYPTED_PASSWORD_LEN (512) + +/* Enables deprecation warnings for MD5 passwords. */ +extern PGDLLIMPORT bool md5_password_warnings; + /* * Types of password hashes or secrets. * @@ -38,7 +51,7 @@ extern char *encrypt_password(PasswordType target_type, const char *role, extern char *get_role_password(const char *role, const char **logdetail); extern int md5_crypt_verify(const char *role, const char *shadow_pass, - const char *client_pass, const char *md5_salt, + const char *client_pass, const uint8 *md5_salt, int md5_salt_len, const char **logdetail); extern int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h index 8ea837ae82a6b..3657f182db3e3 100644 --- a/src/include/libpq/hba.h +++ b/src/include/libpq/hba.h @@ -11,7 +11,7 @@ #ifndef HBA_H #define HBA_H -#include "libpq/pqcomm.h" /* pgrminclude ignore */ /* needed for NetBSD */ +#include "libpq/pqcomm.h" /* needed for NetBSD */ #include "nodes/pg_list.h" #include "regex/regex.h" @@ -39,7 +39,8 @@ typedef enum UserAuth uaCert, uaRADIUS, uaPeer, -#define USER_AUTH_LAST uaPeer /* Must be last value of this enum */ + uaOAuth, +#define USER_AUTH_LAST uaOAuth /* Must be last value of this enum */ } UserAuth; /* @@ -135,6 +136,10 @@ typedef struct HbaLine char *radiusidentifiers_s; List *radiusports; char *radiusports_s; + char *oauth_issuer; + char *oauth_scope; + char *oauth_validator; + bool oauth_skip_usermap; } HbaLine; typedef struct IdentLine diff --git a/src/include/libpq/ifaddr.h b/src/include/libpq/ifaddr.h index 5a117d4fe1f0c..846999df1911a 100644 --- a/src/include/libpq/ifaddr.h +++ b/src/include/libpq/ifaddr.h @@ -3,7 +3,7 @@ * ifaddr.h * IP netmask calculations, and enumerating network interfaces. * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/libpq/ifaddr.h * @@ -12,7 +12,7 @@ #ifndef IFADDR_H #define IFADDR_H -#include "libpq/pqcomm.h" /* pgrminclude ignore */ +#include "libpq/pqcomm.h" typedef void (*PgIfAddrCallback) (struct sockaddr *addr, struct sockaddr *netmask, diff --git a/src/include/libpq/libpq-be-fe-helpers.h b/src/include/libpq/libpq-be-fe-helpers.h index fe508292743f6..16205b824fa55 100644 --- a/src/include/libpq/libpq-be-fe-helpers.h +++ b/src/include/libpq/libpq-be-fe-helpers.h @@ -20,7 +20,7 @@ * into non-blocking mode. That can lead to blocking even when only the async * libpq functions are used. This should be fixed. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/libpq-be-fe-helpers.h @@ -142,13 +142,13 @@ libpqsrv_connect_prepare(void) (errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION), errmsg("could not establish connection"), errdetail("There are too many open files on the local server."), - errhint("Raise the server's max_files_per_process and/or \"ulimit -n\" limits."))); + errhint("Raise the server's \"max_files_per_process\" and/or \"ulimit -n\" limits."))); #else ereport(ERROR, (errcode(ERRCODE_SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION), errmsg("could not establish connection"), errdetail("There are too many open files on the local server."), - errhint("Raise the server's max_files_per_process setting."))); + errhint("Raise the server's \"max_files_per_process\" setting."))); #endif } } diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index 05cb1874c580e..d6e671a638257 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -8,7 +8,7 @@ * Structs that need to be client-visible are in pqcomm.h. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/libpq-be.h @@ -18,6 +18,8 @@ #ifndef LIBPQ_BE_H #define LIBPQ_BE_H +#include "common/scram-common.h" + #include #ifdef USE_OPENSSL #include @@ -25,13 +27,7 @@ #endif #include -#ifdef ENABLE_GSS -#if defined(HAVE_GSSAPI_H) -#include -#else -#include -#endif /* HAVE_GSSAPI_H */ -#endif /* ENABLE_GSS */ +#include "libpq/pg-gssapi.h" #ifdef ENABLE_SSPI #define SECURITY_WIN32 @@ -143,6 +139,9 @@ typedef struct Port int remote_hostname_errcode; /* see above */ char *remote_port; /* text rep of remote port */ + /* local_host is filled only if needed (see log_status_format) */ + char local_host[64]; /* ip addr of local socket for client conn */ + /* * Information that needs to be saved from the startup packet and passed * into backend execution. "char *" fields are NULL if not set. @@ -181,6 +180,13 @@ typedef struct Port int keepalives_count; int tcp_user_timeout; + /* + * SCRAM structures. + */ + uint8 scram_ClientKey[SCRAM_MAX_KEY_LEN]; + uint8 scram_ServerKey[SCRAM_MAX_KEY_LEN]; + bool has_scram_keys; /* true if the above two are valid */ + /* * GSSAPI structures. */ @@ -204,14 +210,20 @@ typedef struct Port char *peer_dn; bool peer_cert_valid; bool alpn_used; + bool last_read_was_eof; /* - * OpenSSL structures. (Keep these last so that the locations of other - * fields are the same whether or not you build with SSL enabled.) + * OpenSSL structures. As with GSSAPI above, to keep struct offsets + * constant, NULL pointers are stored when SSL support is not enabled. + * (Although extensions should have no business accessing the raw_buf + * fields anyway.) */ #ifdef USE_OPENSSL SSL *ssl; X509 *peer; +#else + void *ssl; + void *peer; #endif /* @@ -297,7 +309,7 @@ extern ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor); /* * Write data to a secure connection. */ -extern ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor); +extern ssize_t be_tls_write(Port *port, const void *ptr, size_t len, int *waitfor); /* * Return information about the SSL connection. @@ -337,7 +349,7 @@ extern bool be_gssapi_get_delegation(Port *port); /* Read and write to a GSSAPI-encrypted connection. */ extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len); -extern ssize_t be_gssapi_write(Port *port, void *ptr, size_t len); +extern ssize_t be_gssapi_write(Port *port, const void *ptr, size_t len); #endif /* ENABLE_GSS */ extern PGDLLIMPORT ProtocolVersion FrontendProtocol; diff --git a/src/include/libpq/libpq-fs.h b/src/include/libpq/libpq-fs.h index dd4e4c2edda2d..26fa50c06b586 100644 --- a/src/include/libpq/libpq-fs.h +++ b/src/include/libpq/libpq-fs.h @@ -4,7 +4,7 @@ * definitions for using Inversion file system routines (ie, large objects) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/libpq-fs.h diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index 142c98462ed66..aeb66ca40cf38 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -4,7 +4,7 @@ * POSTGRES LIBPQ buffer structure definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/libpq.h @@ -71,7 +71,7 @@ extern int AcceptConnection(pgsocket server_fd, ClientSocket *client_sock); extern void TouchSocketFiles(void); extern void RemoveSocketFiles(void); extern Port *pq_init(ClientSocket *client_sock); -extern int pq_getbytes(char *s, size_t len); +extern int pq_getbytes(void *b, size_t len); extern void pq_startmsgread(void); extern void pq_endmsgread(void); extern bool pq_is_reading_msg(void); @@ -86,29 +86,38 @@ extern bool pq_check_connection(void); /* * prototypes for functions in be-secure.c */ +extern int secure_initialize(bool isServerStart); +extern bool secure_loaded_verify_locations(void); +extern void secure_destroy(void); +extern int secure_open_server(Port *port); +extern void secure_close(Port *port); +extern ssize_t secure_read(Port *port, void *ptr, size_t len); +extern ssize_t secure_write(Port *port, const void *ptr, size_t len); +extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len); +extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len); + +/* + * declarations for variables defined in be-secure.c + */ extern PGDLLIMPORT char *ssl_library; -extern PGDLLIMPORT char *ssl_cert_file; -extern PGDLLIMPORT char *ssl_key_file; extern PGDLLIMPORT char *ssl_ca_file; +extern PGDLLIMPORT char *ssl_cert_file; extern PGDLLIMPORT char *ssl_crl_file; extern PGDLLIMPORT char *ssl_crl_dir; -extern PGDLLIMPORT char *ssl_dh_params_file; +extern PGDLLIMPORT char *ssl_key_file; +extern PGDLLIMPORT int ssl_min_protocol_version; +extern PGDLLIMPORT int ssl_max_protocol_version; extern PGDLLIMPORT char *ssl_passphrase_command; extern PGDLLIMPORT bool ssl_passphrase_command_supports_reload; +extern PGDLLIMPORT char *ssl_dh_params_file; +extern PGDLLIMPORT char *SSLCipherSuites; +extern PGDLLIMPORT char *SSLCipherList; +extern PGDLLIMPORT char *SSLECDHCurve; +extern PGDLLIMPORT bool SSLPreferServerCiphers; #ifdef USE_SSL extern PGDLLIMPORT bool ssl_loaded_verify_locations; #endif -extern int secure_initialize(bool isServerStart); -extern bool secure_loaded_verify_locations(void); -extern void secure_destroy(void); -extern int secure_open_server(Port *port); -extern void secure_close(Port *port); -extern ssize_t secure_read(Port *port, void *ptr, size_t len); -extern ssize_t secure_write(Port *port, void *ptr, size_t len); -extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len); -extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len); - /* * prototypes for functions in be-secure-gssapi.c */ @@ -116,13 +125,6 @@ extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len); extern ssize_t secure_open_gssapi(Port *port); #endif -/* GUCs */ -extern PGDLLIMPORT char *SSLCipherSuites; -extern PGDLLIMPORT char *SSLECDHCurve; -extern PGDLLIMPORT bool SSLPreferServerCiphers; -extern PGDLLIMPORT int ssl_min_protocol_version; -extern PGDLLIMPORT int ssl_max_protocol_version; - enum ssl_protocol_versions { PG_TLS_ANY = 0, diff --git a/src/include/libpq/oauth.h b/src/include/libpq/oauth.h new file mode 100644 index 0000000000000..f75d2e31a68a8 --- /dev/null +++ b/src/include/libpq/oauth.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------- + * + * oauth.h + * Interface to libpq/auth-oauth.c + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/oauth.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_OAUTH_H +#define PG_OAUTH_H + +#include "libpq/libpq-be.h" +#include "libpq/sasl.h" + +extern PGDLLIMPORT char *oauth_validator_libraries_string; + +typedef struct ValidatorModuleState +{ + /* Holds the server's PG_VERSION_NUM. Reserved for future extensibility. */ + int sversion; + + /* + * Private data pointer for use by a validator module. This can be used to + * store state for the module that will be passed to each of its + * callbacks. + */ + void *private_data; +} ValidatorModuleState; + +typedef struct ValidatorModuleResult +{ + /* + * Should be set to true if the token carries sufficient permissions for + * the bearer to connect. + */ + bool authorized; + + /* + * If the token authenticates the user, this should be set to a palloc'd + * string containing the SYSTEM_USER to use for HBA mapping. Consider + * setting this even if result->authorized is false so that DBAs may use + * the logs to match end users to token failures. + * + * This is required if the module is not configured for ident mapping + * delegation. See the validator module documentation for details. + */ + char *authn_id; +} ValidatorModuleResult; + +/* + * Validator module callbacks + * + * These callback functions should be defined by validator modules and returned + * via _PG_oauth_validator_module_init(). ValidatorValidateCB is the only + * required callback. For more information about the purpose of each callback, + * refer to the OAuth validator modules documentation. + */ +typedef void (*ValidatorStartupCB) (ValidatorModuleState *state); +typedef void (*ValidatorShutdownCB) (ValidatorModuleState *state); +typedef bool (*ValidatorValidateCB) (const ValidatorModuleState *state, + const char *token, const char *role, + ValidatorModuleResult *result); + +/* + * Identifies the compiled ABI version of the validator module. Since the server + * already enforces the PG_MODULE_MAGIC number for modules across major + * versions, this is reserved for emergency use within a stable release line. + * May it never need to change. + */ +#define PG_OAUTH_VALIDATOR_MAGIC 0x20250220 + +typedef struct OAuthValidatorCallbacks +{ + uint32 magic; /* must be set to PG_OAUTH_VALIDATOR_MAGIC */ + + ValidatorStartupCB startup_cb; + ValidatorShutdownCB shutdown_cb; + ValidatorValidateCB validate_cb; +} OAuthValidatorCallbacks; + +/* + * Type of the shared library symbol _PG_oauth_validator_module_init which is + * required for all validator modules. This function will be invoked during + * module loading. + */ +typedef const OAuthValidatorCallbacks *(*OAuthValidatorModuleInit) (void); +extern PGDLLEXPORT const OAuthValidatorCallbacks *_PG_oauth_validator_module_init(void); + +/* Implementation */ +extern PGDLLIMPORT const pg_be_sasl_mech pg_be_oauth_mech; + +/* + * Ensure a validator named in the HBA is permitted by the configuration. + */ +extern bool check_oauth_validator(HbaLine *hbaline, int elevel, char **err_msg); + +#endif /* PG_OAUTH_H */ diff --git a/src/include/libpq/pg-gssapi.h b/src/include/libpq/pg-gssapi.h new file mode 100644 index 0000000000000..f49fad14fcc4b --- /dev/null +++ b/src/include/libpq/pg-gssapi.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + * + * pg-gssapi.h + * Definitions for including GSSAPI headers + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/pg-gssapi.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_GSSAPI_H +#define PG_GSSAPI_H + +#ifdef ENABLE_GSS + +/* IWYU pragma: begin_exports */ +#if defined(HAVE_GSSAPI_H) +#include +#include +#else +#include +#include +#endif +/* IWYU pragma: end_exports */ + +/* +* On Windows, includes a #define for X509_NAME, which breaks our +* ability to use OpenSSL's version of that symbol if is pulled +* in after ... and, at least on some builds, it is. We +* can't reliably fix that by re-ordering #includes, because libpq/libpq-be.h +* #includes . Instead, just zap the #define again here. +*/ +#ifdef X509_NAME +#undef X509_NAME +#endif + +#endif /* ENABLE_GSS */ + +#endif /* PG_GSSAPI_H */ diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 527735e3dba7a..f04ca13565398 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -6,7 +6,7 @@ * NOTE: for historical reasons, this does not correspond to pqcomm.c. * pqcomm.c's routines are declared in libpq.h. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/pqcomm.h @@ -86,15 +86,15 @@ is_unixsock_path(const char *path) #define PG_PROTOCOL_MAJOR(v) ((v) >> 16) #define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff) +#define PG_PROTOCOL_FULL(v) (PG_PROTOCOL_MAJOR(v) * 10000 + PG_PROTOCOL_MINOR(v)) #define PG_PROTOCOL(m,n) (((m) << 16) | (n)) /* * The earliest and latest frontend/backend protocol version supported. - * (Only protocol version 3 is currently supported) */ #define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,0) -#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0) +#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,2) typedef uint32 ProtocolVersion; /* FE/BE protocol version number */ @@ -128,7 +128,12 @@ typedef uint32 AuthRequest; * * The cancel request code must not match any protocol version number * we're ever likely to use. This random choice should do. + * + * Before PostgreSQL v18 and the protocol version bump from 3.0 to 3.2, the + * cancel key was always 4 bytes. With protocol version 3.2, it's variable + * length. */ + #define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678) typedef struct CancelRequestPacket @@ -136,7 +141,8 @@ typedef struct CancelRequestPacket /* Note that each field is stored in network byte order! */ MsgType cancelRequestCode; /* code to identify a cancel request */ uint32 backendPID; /* PID of client's backend */ - uint32 cancelAuthCode; /* secret key to authorize cancel */ + uint8 cancelAuthCode[FLEXIBLE_ARRAY_MEMBER]; /* secret key to + * authorize cancel */ } CancelRequestPacket; /* Application-Layer Protocol Negotiation is required for direct connections diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h index 7f48cbded97a7..9a1534be521c6 100644 --- a/src/include/libpq/pqformat.h +++ b/src/include/libpq/pqformat.h @@ -3,7 +3,7 @@ * pqformat.h * Definitions for formatting and parsing frontend/backend messages * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/pqformat.h @@ -200,7 +200,7 @@ extern int64 pq_getmsgint64(StringInfo msg); extern float4 pq_getmsgfloat4(StringInfo msg); extern float8 pq_getmsgfloat8(StringInfo msg); extern const char *pq_getmsgbytes(StringInfo msg, int datalen); -extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen); +extern void pq_copymsgbytes(StringInfo msg, void *buf, int datalen); extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes); extern const char *pq_getmsgstring(StringInfo msg); extern const char *pq_getmsgrawstring(StringInfo msg); diff --git a/src/include/libpq/pqmq.h b/src/include/libpq/pqmq.h index 227df8976f40f..348b4494333e1 100644 --- a/src/include/libpq/pqmq.h +++ b/src/include/libpq/pqmq.h @@ -3,7 +3,7 @@ * pqmq.h * Use the frontend/backend protocol for communication over a shm_mq * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/pqmq.h diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h index cf6a3942f6598..5be7870156ee0 100644 --- a/src/include/libpq/pqsignal.h +++ b/src/include/libpq/pqsignal.h @@ -3,7 +3,7 @@ * pqsignal.h * Backend signal(2) support (see also src/port/pqsignal.c) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/pqsignal.h diff --git a/src/include/libpq/protocol.h b/src/include/libpq/protocol.h index b71add1ec1508..b0bcb3cdc26eb 100644 --- a/src/include/libpq/protocol.h +++ b/src/include/libpq/protocol.h @@ -4,7 +4,7 @@ * Definitions of the request/response codes for the wire protocol. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/protocol.h diff --git a/src/include/libpq/sasl.h b/src/include/libpq/sasl.h index 7a1f970ccae65..581e2986473de 100644 --- a/src/include/libpq/sasl.h +++ b/src/include/libpq/sasl.h @@ -7,7 +7,7 @@ * * See src/interfaces/libpq/fe-auth-sasl.h for the frontend counterpart. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/sasl.h @@ -27,7 +27,15 @@ #define PG_SASL_EXCHANGE_FAILURE 2 /* - * Backend SASL mechanism callbacks. + * Maximum accepted size of SASL messages. + * + * The messages that the server or libpq generate are much smaller than this, + * but have some headroom. + */ +#define PG_MAX_SASL_MESSAGE_LENGTH 1024 + +/* + * Backend SASL mechanism callbacks and metadata. * * To implement a backend mechanism, declare a pg_be_sasl_mech struct with * appropriate callback implementations. Then pass the mechanism to @@ -127,6 +135,9 @@ typedef struct pg_be_sasl_mech const char *input, int inputlen, char **output, int *outputlen, const char **logdetail); + + /* The maximum size allowed for client SASLResponses. */ + int max_message_length; } pg_be_sasl_mech; /* Common implementation for auth.c */ diff --git a/src/include/libpq/scram.h b/src/include/libpq/scram.h index 2ae90105578e2..c1237d3bcd62d 100644 --- a/src/include/libpq/scram.h +++ b/src/include/libpq/scram.h @@ -3,7 +3,7 @@ * scram.h * Interface to libpq/scram.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/libpq/scram.h diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h index 249cd18a35701..4b4a9974b75b3 100644 --- a/src/include/mb/pg_wchar.h +++ b/src/include/mb/pg_wchar.h @@ -3,7 +3,7 @@ * pg_wchar.h * multibyte-character support * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/mb/pg_wchar.h @@ -662,7 +662,10 @@ extern int pg_valid_server_encoding_id(int encoding); * (in addition to the ones just above). The constant tables declared * earlier in this file are also available from libpgcommon. */ +extern void pg_encoding_set_invalid(int encoding, char *dst); extern int pg_encoding_mblen(int encoding, const char *mbstr); +extern int pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr, + size_t remaining); extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr); extern int pg_encoding_dsplen(int encoding, const char *mbstr); extern int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len); @@ -767,9 +770,9 @@ extern void check_encoding_conversion_args(int src_encoding, int expected_src_encoding, int expected_dest_encoding); -extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn(); -extern void report_untranslatable_char(int src_encoding, int dest_encoding, - const char *mbstr, int len) pg_attribute_noreturn(); +pg_noreturn extern void report_invalid_encoding(int encoding, const char *mbstr, int len); +pg_noreturn extern void report_untranslatable_char(int src_encoding, int dest_encoding, + const char *mbstr, int len); extern int local2local(const unsigned char *l, unsigned char *p, int len, int src_encoding, int dest_encoding, diff --git a/src/include/mb/stringinfo_mb.h b/src/include/mb/stringinfo_mb.h index bdef416e41a35..f682e7b539ca1 100644 --- a/src/include/mb/stringinfo_mb.h +++ b/src/include/mb/stringinfo_mb.h @@ -3,7 +3,7 @@ * stringinfo_mb.h * multibyte support for StringInfo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/mb/stringinfo_mb.h diff --git a/src/include/meson.build b/src/include/meson.build index 58b7a9c1e7e96..2e4b7aa529e26 100644 --- a/src/include/meson.build +++ b/src/include/meson.build @@ -1,13 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group - -pg_config_ext = configure_file( - input: 'pg_config_ext.h.meson', - output: 'pg_config_ext.h', - configuration: cdata, - install: true, - install_dir: dir_include, -) -configure_files += pg_config_ext +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_config_os = configure_file( output: 'pg_config_os.h', @@ -116,7 +107,6 @@ install_headers( 'postgres_fe.h', 'varatt.h', 'windowapi.h', - pg_config_ext, pg_config_os, pg_config, install_dir: dir_include_server, @@ -186,4 +176,4 @@ install_subdir('catalog', ) # autoconf generates the file there, ensure we get a conflict -generated_sources_ac += {'src/include': ['stamp-h', 'stamp-ext-h']} +generated_sources_ac += {'src/include': ['stamp-h']} diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 90f9b21b2584d..1bef98471c363 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -10,7 +10,7 @@ * Over time, this has also become the preferred place for widely known * resource-limitation stuff, such as work_mem and check_stack_depth(). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/miscadmin.h @@ -191,7 +191,8 @@ extern PGDLLIMPORT pg_time_t MyStartTime; extern PGDLLIMPORT TimestampTz MyStartTimestamp; extern PGDLLIMPORT struct Port *MyProcPort; extern PGDLLIMPORT struct Latch *MyLatch; -extern PGDLLIMPORT int32 MyCancelKey; +extern PGDLLIMPORT uint8 MyCancelKey[]; +extern PGDLLIMPORT int MyCancelKeyLength; extern PGDLLIMPORT int MyPMChildSlot; extern PGDLLIMPORT char OutputFileName[]; @@ -283,15 +284,16 @@ extern PGDLLIMPORT int VacuumCostPageDirty; extern PGDLLIMPORT int VacuumCostLimit; extern PGDLLIMPORT double VacuumCostDelay; -extern PGDLLIMPORT int64 VacuumPageHit; -extern PGDLLIMPORT int64 VacuumPageMiss; -extern PGDLLIMPORT int64 VacuumPageDirty; - extern PGDLLIMPORT int VacuumCostBalance; extern PGDLLIMPORT bool VacuumCostActive; -/* in tcop/postgres.c */ +/* in utils/misc/stack_depth.c */ + +extern PGDLLIMPORT int max_stack_depth; + +/* Required daylight between max_stack_depth and the kernel limit, in bytes */ +#define STACK_DEPTH_SLOP (512 * 1024) typedef char *pg_stack_base_t; @@ -299,6 +301,7 @@ extern pg_stack_base_t set_stack_base(void); extern void restore_stack_base(pg_stack_base_t base); extern void check_stack_depth(void); extern bool stack_is_too_deep(void); +extern ssize_t get_stack_depth_rlimit(void); /* in tcop/utility.c */ extern void PreventCommandIfReadOnly(const char *cmdname); @@ -336,6 +339,7 @@ typedef enum BackendType /* Backends and other backend-like processes */ B_BACKEND, + B_DEAD_END_BACKEND, B_AUTOVAC_LAUNCHER, B_AUTOVAC_WORKER, B_BG_WORKER, @@ -346,8 +350,9 @@ typedef enum BackendType /* * Auxiliary processes. These have PGPROC entries, but they are not - * attached to any particular database. There can be only one of each of - * these running at a time. + * attached to any particular database, and cannot run transactions or + * even take heavyweight locks. There can be only one of each of these + * running at a time, except for IO workers. * * If you modify these, make sure to update NUM_AUXILIARY_PROCS and the * glossary in the docs. @@ -355,6 +360,7 @@ typedef enum BackendType B_ARCHIVER, B_BG_WRITER, B_CHECKPOINTER, + B_IO_WORKER, B_STARTUP, B_WAL_RECEIVER, B_WAL_SUMMARIZER, @@ -371,6 +377,7 @@ typedef enum BackendType extern PGDLLIMPORT BackendType MyBackendType; +#define AmRegularBackendProcess() (MyBackendType == B_BACKEND) #define AmAutoVacuumLauncherProcess() (MyBackendType == B_AUTOVAC_LAUNCHER) #define AmAutoVacuumWorkerProcess() (MyBackendType == B_AUTOVAC_WORKER) #define AmBackgroundWorkerProcess() (MyBackendType == B_BG_WORKER) @@ -383,6 +390,19 @@ extern PGDLLIMPORT BackendType MyBackendType; #define AmWalReceiverProcess() (MyBackendType == B_WAL_RECEIVER) #define AmWalSummarizerProcess() (MyBackendType == B_WAL_SUMMARIZER) #define AmWalWriterProcess() (MyBackendType == B_WAL_WRITER) +#define AmIoWorkerProcess() (MyBackendType == B_IO_WORKER) + +#define AmSpecialWorkerProcess() \ + (AmAutoVacuumLauncherProcess() || \ + AmLogicalSlotSyncWorkerProcess()) + +/* + * Backend types that are spawned by the postmaster to serve a client or + * replication connection. These backend types have in common that they are + * externally initiated. + */ +#define IsExternalConnectionBackend(backend_type) \ + (backend_type == B_BACKEND || backend_type == B_WAL_SENDER) extern const char *GetBackendTypeDesc(BackendType backendType); @@ -395,7 +415,9 @@ extern char *GetUserNameFromId(Oid roleid, bool noerr); extern Oid GetUserId(void); extern Oid GetOuterUserId(void); extern Oid GetSessionUserId(void); +extern bool GetSessionUserIsSuperuser(void); extern Oid GetAuthenticatedUserId(void); +extern void SetAuthenticatedUserId(Oid userid); extern void GetUserIdAndSecContext(Oid *userid, int *sec_context); extern void SetUserIdAndSecContext(Oid userid, int sec_context); extern bool InLocalUserIdChange(void); @@ -478,6 +500,7 @@ extern PGDLLIMPORT ProcessingMode Mode; #define INIT_PG_OVERRIDE_ROLE_LOGIN 0x0004 extern void pg_split_opts(char **argv, int *argcp, const char *optstr); extern void InitializeMaxBackends(void); +extern void InitializeFastPathLocks(void); extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bits32 flags, diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h index 283bea5ea961d..03faca93084c6 100644 --- a/src/include/nodes/bitmapset.h +++ b/src/include/nodes/bitmapset.h @@ -9,7 +9,7 @@ * empty set by a NULL pointer. * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/nodes/bitmapset.h * diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index cac684d9b3af7..2492282213ff3 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -19,7 +19,7 @@ * not provided. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/execnodes.h @@ -74,11 +74,20 @@ typedef Datum (*ExprStateEvalFunc) (struct ExprState *expression, /* Bits in ExprState->flags (see also execExpr.h for private flag bits): */ /* expression is for use with ExecQual() */ #define EEO_FLAG_IS_QUAL (1 << 0) +/* expression refers to OLD table columns */ +#define EEO_FLAG_HAS_OLD (1 << 1) +/* expression refers to NEW table columns */ +#define EEO_FLAG_HAS_NEW (1 << 2) +/* OLD table row is NULL in RETURNING list */ +#define EEO_FLAG_OLD_IS_NULL (1 << 3) +/* NEW table row is NULL in RETURNING list */ +#define EEO_FLAG_NEW_IS_NULL (1 << 4) typedef struct ExprState { NodeTag type; +#define FIELDNO_EXPRSTATE_FLAGS 1 uint8 flags; /* bitmask of EEO_FLAG_* bits, see above */ /* @@ -132,8 +141,10 @@ typedef struct ExprState bool *innermost_domainnull; /* - * For expression nodes that support soft errors. Should be set to NULL - * before calling ExecInitExprRec() if the caller wants errors thrown. + * For expression nodes that support soft errors. Should be set to NULL if + * the caller wants errors to be thrown. Callers that do not want errors + * thrown should set it to a valid ErrorSaveContext before calling + * ExecInitExprRec(). */ ErrorSaveContext *escontext; } ExprState; @@ -202,6 +213,7 @@ typedef struct IndexInfo bool ii_Concurrent; bool ii_BrokenHotChain; bool ii_Summarizing; + bool ii_WithoutOverlaps; int ii_ParallelWorkers; Oid ii_Am; void *ii_AmCache; @@ -287,6 +299,12 @@ typedef struct ExprContext #define FIELDNO_EXPRCONTEXT_DOMAINNULL 13 bool domainValue_isNull; + /* Tuples that OLD/NEW Var nodes in RETURNING may refer to */ +#define FIELDNO_EXPRCONTEXT_OLDTUPLE 14 + TupleTableSlot *ecxt_oldtuple; +#define FIELDNO_EXPRCONTEXT_NEWTUPLE 15 + TupleTableSlot *ecxt_newtuple; + /* Link to containing EState (NULL if a standalone ExprContext) */ struct EState *ecxt_estate; @@ -465,13 +483,15 @@ typedef struct ResultRelInfo IndexInfo **ri_IndexRelationInfo; /* - * For UPDATE/DELETE result relations, the attribute number of the row - * identity junk attribute in the source plan's output tuples + * For UPDATE/DELETE/MERGE result relations, the attribute number of the + * row identity junk attribute in the source plan's output tuples */ AttrNumber ri_RowIdAttNo; /* For UPDATE, attnums of generated columns to be computed */ Bitmapset *ri_extraUpdatedCols; + /* true if the above has been computed */ + bool ri_extraUpdatedCols_valid; /* Projection to generate new tuple in an INSERT/UPDATE */ ProjectionInfo *ri_projectNew; @@ -482,6 +502,9 @@ typedef struct ResultRelInfo /* Have the projection and the slots above been initialized? */ bool ri_projectNewInfoValid; + /* updates do LockTuple() before oldtup read; see README.tuplock */ + bool ri_needLockTagTuple; + /* triggers to be fired, if any */ TriggerDesc *ri_TrigDesc; @@ -498,6 +521,7 @@ typedef struct ResultRelInfo TupleTableSlot *ri_ReturningSlot; /* for trigger output tuples */ TupleTableSlot *ri_TrigOldSlot; /* for a trigger's old tuple */ TupleTableSlot *ri_TrigNewSlot; /* for a trigger's new tuple */ + TupleTableSlot *ri_AllNullSlot; /* for RETURNING OLD/NEW */ /* FDW callback functions, if foreign table */ struct FdwRoutine *ri_FdwRoutine; @@ -521,10 +545,18 @@ typedef struct ResultRelInfo /* list of WithCheckOption expr states */ List *ri_WithCheckOptionExprs; - /* array of constraint-checking expr states */ - ExprState **ri_ConstraintExprs; + /* array of expr states for checking check constraints */ + ExprState **ri_CheckConstraintExprs; + + /* + * array of expr states for checking not-null constraints on virtual + * generated columns + */ + ExprState **ri_GenVirtualNotNullConstraintExprs; - /* arrays of stored generated columns expr states, for INSERT and UPDATE */ + /* + * Arrays of stored generated columns ExprStates for INSERT/UPDATE/MERGE. + */ ExprState **ri_GeneratedExprsI; ExprState **ri_GeneratedExprsU; @@ -631,6 +663,13 @@ typedef struct EState * ExecRowMarks, or NULL if none */ List *es_rteperminfos; /* List of RTEPermissionInfo */ PlannedStmt *es_plannedstmt; /* link to top of plan tree */ + List *es_part_prune_infos; /* List of PartitionPruneInfo */ + List *es_part_prune_states; /* List of PartitionPruneState */ + List *es_part_prune_results; /* List of Bitmapset */ + Bitmapset *es_unpruned_relids; /* PlannedStmt.unprunableRelids + RT + * indexes of leaf partitions that survive + * initial pruning; see + * ExecDoInitialPruning() */ const char *es_sourceText; /* Source text from QueryDesc */ JunkFilter *es_junkFilter; /* top-level junk filter, if any */ @@ -700,6 +739,11 @@ typedef struct EState bool es_use_parallel_mode; /* can we use parallel workers? */ + int es_parallel_workers_to_launch; /* number of workers to + * launch. */ + int es_parallel_workers_launched; /* number of workers actually + * launched. */ + /* The per-query shared memory area to use for parallel execution. */ struct dsa_area *es_query_dsa; @@ -782,15 +826,15 @@ typedef struct ExecAuxRowMark * * All-in-memory tuple hash tables are used for a number of purposes. * - * Note: tab_hash_funcs are for the key datatype(s) stored in the table, - * and tab_eq_funcs are non-cross-type equality operators for those types. - * Normally these are the only functions used, but FindTupleHashEntry() - * supports searching a hashtable using cross-data-type hashing. For that, - * the caller must supply hash functions for the LHS datatype as well as - * the cross-type equality operators to use. in_hash_funcs and cur_eq_func - * are set to point to the caller's function arrays while doing such a search. - * During LookupTupleHashEntry(), they point to tab_hash_funcs and - * tab_eq_func respectively. + * Note: tab_hash_expr is for hashing the key datatype(s) stored in the table, + * and tab_eq_func is a non-cross-type ExprState for equality checks on those + * types. Normally these are the only ExprStates used, but + * FindTupleHashEntry() supports searching a hashtable using cross-data-type + * hashing. For that, the caller must supply an ExprState to hash the LHS + * datatype as well as the cross-type equality ExprState to use. in_hash_expr + * and cur_eq_func are set to point to the caller's hash and equality + * ExprStates while doing such a search. During LookupTupleHashEntry(), they + * point to tab_hash_expr and tab_eq_func respectively. * ---------------------------------------------------------------- */ typedef struct TupleHashEntryData *TupleHashEntry; @@ -799,7 +843,6 @@ typedef struct TupleHashTableData *TupleHashTable; typedef struct TupleHashEntryData { MinimalTuple firstTuple; /* copy of first tuple in this group */ - void *additional; /* user data */ uint32 status; /* hash status */ uint32 hash; /* hash value (cached) */ } TupleHashEntryData; @@ -817,18 +860,17 @@ typedef struct TupleHashTableData tuplehash_hash *hashtab; /* underlying hash table */ int numCols; /* number of columns in lookup key */ AttrNumber *keyColIdx; /* attr numbers of key columns */ - FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */ + ExprState *tab_hash_expr; /* ExprState for hashing table datatype(s) */ ExprState *tab_eq_func; /* comparator for table datatype(s) */ Oid *tab_collations; /* collations for hash and comparison */ MemoryContext tablecxt; /* memory context containing table */ MemoryContext tempcxt; /* context for function evaluations */ - Size entrysize; /* actual size to make each hash entry */ + Size additionalsize; /* size of additional data */ TupleTableSlot *tableslot; /* slot for referencing table entries */ /* The following fields are set transiently for each table search: */ TupleTableSlot *inputslot; /* current input tuple's slot */ - FmgrInfo *in_hash_funcs; /* hash functions for input datatype(s) */ + ExprState *in_hash_expr; /* ExprState for hashing input datatype(s) */ ExprState *cur_eq_func; /* comparator for input vs. table */ - uint32 hash_iv; /* hash-function IV */ ExprContext *exprcontext; /* expression context */ } TupleHashTableData; @@ -961,7 +1003,6 @@ typedef struct SubPlanState struct PlanState *planstate; /* subselect plan's state tree */ struct PlanState *parent; /* parent plan node's state tree */ ExprState *testexpr; /* state of combining expression */ - List *args; /* states of argument expression(s) */ HeapTuple curTuple; /* copy of most recent tuple from subplan */ Datum curArray; /* most recent array from ARRAY() subplan */ /* these are used when hashing the subselect's output: */ @@ -982,8 +1023,7 @@ typedef struct SubPlanState * datatype(s) */ Oid *tab_collations; /* collations for hash and comparison */ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */ - FmgrInfo *tab_eq_funcs; /* equality functions for table datatype(s) */ - FmgrInfo *lhs_hash_funcs; /* hash functions for lefthand datatype(s) */ + ExprState *lhs_hash_expr; /* hash expr for lefthand datatype(s) */ FmgrInfo *cur_eq_funcs; /* equality functions for LHS vs. table */ ExprState *cur_eq_comp; /* equality comparator for LHS vs. table */ } SubPlanState; @@ -1412,6 +1452,15 @@ typedef struct ModifyTableState double mt_merge_inserted; double mt_merge_updated; double mt_merge_deleted; + + /* + * Lists of valid updateColnosLists, mergeActionLists, and + * mergeJoinConditions. These contain only entries for unpruned + * relations, filtered from the corresponding lists in ModifyTable. + */ + List *mt_updateColnosLists; + List *mt_mergeActionLists; + List *mt_mergeJoinConditions; } ModifyTableState; /* ---------------- @@ -1634,6 +1683,8 @@ typedef struct * RuntimeContext expr context for evaling runtime Skeys * RelationDesc index relation descriptor * ScanDesc index scan descriptor + * Instrument local index scan instrumentation + * SharedInfo parallel worker instrumentation (no leader entry) * * ReorderQueue tuples that need reordering due to re-check * ReachedEnd have we fetched all tuples from index already? @@ -1660,6 +1711,8 @@ typedef struct IndexScanState ExprContext *iss_RuntimeContext; Relation iss_RelationDesc; struct IndexScanDescData *iss_ScanDesc; + IndexScanInstrumentation iss_Instrument; + SharedIndexScanInstrumentation *iss_SharedInfo; /* These are needed for re-checking ORDER BY expr ordering */ pairingheap *iss_ReorderQueue; @@ -1686,6 +1739,8 @@ typedef struct IndexScanState * RuntimeContext expr context for evaling runtime Skeys * RelationDesc index relation descriptor * ScanDesc index scan descriptor + * Instrument local index scan instrumentation + * SharedInfo parallel worker instrumentation (no leader entry) * TableSlot slot for holding tuples fetched from the table * VMBuffer buffer in use for visibility map testing, if any * PscanLen size of parallel index-only scan descriptor @@ -1707,6 +1762,8 @@ typedef struct IndexOnlyScanState ExprContext *ioss_RuntimeContext; Relation ioss_RelationDesc; struct IndexScanDescData *ioss_ScanDesc; + IndexScanInstrumentation ioss_Instrument; + SharedIndexScanInstrumentation *ioss_SharedInfo; TupleTableSlot *ioss_TableSlot; Buffer ioss_VMBuffer; Size ioss_PscanLen; @@ -1728,6 +1785,8 @@ typedef struct IndexOnlyScanState * RuntimeContext expr context for evaling runtime Skeys * RelationDesc index relation descriptor * ScanDesc index scan descriptor + * Instrument local index scan instrumentation + * SharedInfo parallel worker instrumentation (no leader entry) * ---------------- */ typedef struct BitmapIndexScanState @@ -1744,6 +1803,8 @@ typedef struct BitmapIndexScanState ExprContext *biss_RuntimeContext; Relation biss_RelationDesc; struct IndexScanDescData *biss_ScanDesc; + IndexScanInstrumentation biss_Instrument; + SharedIndexScanInstrumentation *biss_SharedInfo; } BitmapIndexScanState; /* ---------------- @@ -1782,11 +1843,7 @@ typedef enum /* ---------------- * ParallelBitmapHeapState information * tbmiterator iterator for scanning current pages - * prefetch_iterator iterator for prefetching ahead of current page - * mutex mutual exclusion for the prefetching variable - * and state - * prefetch_pages # pages prefetch iterator is ahead of current - * prefetch_target current target prefetch distance + * mutex mutual exclusion for state * state current state of the TIDBitmap * cv conditional wait variable * ---------------- @@ -1794,10 +1851,7 @@ typedef enum typedef struct ParallelBitmapHeapState { dsa_pointer tbmiterator; - dsa_pointer prefetch_iterator; slock_t mutex; - int prefetch_pages; - int prefetch_target; SharedBitmapState state; ConditionVariable cv; } ParallelBitmapHeapState; @@ -1821,19 +1875,11 @@ typedef struct SharedBitmapHeapInstrumentation * * bitmapqualorig execution state for bitmapqualorig expressions * tbm bitmap obtained from child index scan(s) - * tbmiterator iterator for scanning current pages - * tbmres current-page data - * pvmbuffer buffer for visibility-map lookups of prefetched pages * stats execution statistics - * prefetch_iterator iterator for prefetching ahead of current page - * prefetch_pages # pages prefetch iterator is ahead of current - * prefetch_target current target prefetch distance - * prefetch_maximum maximum value for prefetch_target * initialized is node is ready to iterate - * shared_tbmiterator shared iterator - * shared_prefetch_iterator shared iterator for prefetching * pstate shared state for parallel bitmap scan * sinstrument statistics for parallel workers + * recheck do current page's tuples need recheck * ---------------- */ typedef struct BitmapHeapScanState @@ -1841,19 +1887,11 @@ typedef struct BitmapHeapScanState ScanState ss; /* its first field is NodeTag */ ExprState *bitmapqualorig; TIDBitmap *tbm; - TBMIterator *tbmiterator; - TBMIterateResult *tbmres; - Buffer pvmbuffer; BitmapHeapScanInstrumentation stats; - TBMIterator *prefetch_iterator; - int prefetch_pages; - int prefetch_target; - int prefetch_maximum; bool initialized; - TBMSharedIterator *shared_tbmiterator; - TBMSharedIterator *shared_prefetch_iterator; ParallelBitmapHeapState *pstate; SharedBitmapHeapInstrumentation *sinstrument; + bool recheck; } BitmapHeapScanState; /* ---------------- @@ -2183,8 +2221,7 @@ typedef struct MergeJoinState * HashJoinState information * * hashclauses original form of the hashjoin condition - * hj_OuterHashKeys the outer hash keys in the hashjoin condition - * hj_HashOperators the join operators in the hashjoin condition + * hj_OuterHash ExprState for hashing outer keys * hj_HashTable hash table for the hashjoin * (NULL if table not built yet) * hj_CurHashValue hash value for current outer tuple @@ -2214,9 +2251,7 @@ typedef struct HashJoinState { JoinState js; /* its first field is NodeTag */ ExprState *hashclauses; - List *hj_OuterHashKeys; /* list of ExprState nodes */ - List *hj_HashOperators; /* list of operator OIDs */ - List *hj_Collations; + ExprState *hj_OuterHash; HashJoinTable hj_HashTable; uint32 hj_CurHashValue; int hj_CurBucketNo; @@ -2528,7 +2563,8 @@ typedef struct AggState /* these fields are used in AGG_HASHED and AGG_MIXED modes: */ bool table_filled; /* hash table filled yet? */ int num_hashes; - MemoryContext hash_metacxt; /* memory for hash table itself */ + MemoryContext hash_metacxt; /* memory for hash table bucket array */ + MemoryContext hash_tablecxt; /* memory for hash table entries */ struct LogicalTapeSet *hash_tapeset; /* tape set for hash spill tapes */ struct HashAggSpill *hash_spills; /* HashAggSpill for each grouping set, * exists only during first pass */ @@ -2554,7 +2590,7 @@ typedef struct AggState * per-group pointers */ /* support for evaluation of agg input expressions: */ -#define FIELDNO_AGGSTATE_ALL_PERGROUPS 53 +#define FIELDNO_AGGSTATE_ALL_PERGROUPS 54 AggStatePerGroup *all_pergroups; /* array of first ->pergroups, than * ->hash_pergroup */ SharedAggInfo *shared_info; /* one entry per worker */ @@ -2621,6 +2657,17 @@ typedef struct WindowAggState bool inRangeAsc; /* use ASC sort order for in_range tests? */ bool inRangeNullsFirst; /* nulls sort first for in_range tests? */ + /* fields relating to runconditions */ + bool use_pass_through; /* When false, stop execution when + * runcondition is no longer true. Else + * just stop evaluating window funcs. */ + bool top_window; /* true if this is the top-most WindowAgg or + * the only WindowAgg in this query level */ + ExprState *runcondition; /* Condition which must remain true otherwise + * execution of the WindowAgg will finish or + * go into pass-through mode. NULL when there + * is no such condition. */ + /* these fields are used in GROUPS mode: */ int64 currentgroup; /* peer group # of current row in partition */ int64 frameheadgroup; /* peer group # of frame head row */ @@ -2633,19 +2680,10 @@ typedef struct WindowAggState MemoryContext curaggcontext; /* current aggregate's working data */ ExprContext *tmpcontext; /* short-term evaluation context */ - ExprState *runcondition; /* Condition which must remain true otherwise - * execution of the WindowAgg will finish or - * go into pass-through mode. NULL when there - * is no such condition. */ - - bool use_pass_through; /* When false, stop execution when - * runcondition is no longer true. Else - * just stop evaluating window funcs. */ - bool top_window; /* true if this is the top-most WindowAgg or - * the only WindowAgg in this query level */ bool all_first; /* true if the scan is starting */ bool partition_spooled; /* true if all tuples in current partition * have been spooled into tuplestore */ + bool next_partition; /* true if begin_partition needs to be called */ bool more_partitions; /* true if there's more partitions after * this one */ bool framehead_valid; /* true if frameheadpos is known up to @@ -2769,7 +2807,10 @@ typedef struct HashState { PlanState ps; /* its first field is NodeTag */ HashJoinTable hashtable; /* hash table for the hashjoin */ - List *hashkeys; /* list of ExprState nodes */ + ExprState *hash_expr; /* ExprState to get hash value */ + + FmgrInfo *skew_hashfunction; /* lookup data for skew hash function */ + Oid skew_collation; /* collation to call skew_hashfunction with */ /* * In a parallelized hash join, the leader retains a pointer to the @@ -2793,27 +2834,34 @@ typedef struct HashState /* ---------------- * SetOpState information * - * Even in "sorted" mode, SetOp nodes are more complex than a simple - * Unique, since we have to count how many duplicates to return. But - * we also support hashing, so this is really more like a cut-down - * form of Agg. + * SetOp nodes support either sorted or hashed de-duplication. + * The sorted mode is a bit like MergeJoin, the hashed mode like Agg. * ---------------- */ -/* this struct is private in nodeSetOp.c: */ -typedef struct SetOpStatePerGroupData *SetOpStatePerGroup; +typedef struct SetOpStatePerInput +{ + TupleTableSlot *firstTupleSlot; /* first tuple of current group */ + int64 numTuples; /* number of tuples in current group */ + TupleTableSlot *nextTupleSlot; /* next input tuple, if already read */ + bool needGroup; /* do we need to load a new group? */ +} SetOpStatePerInput; typedef struct SetOpState { PlanState ps; /* its first field is NodeTag */ - ExprState *eqfunction; /* equality comparator */ - Oid *eqfuncoids; /* per-grouping-field equality fns */ - FmgrInfo *hashfunctions; /* per-grouping-field hash fns */ bool setop_done; /* indicates completion of output scan */ - long numOutput; /* number of dups left to output */ + int64 numOutput; /* number of dups left to output */ + int numCols; /* number of grouping columns */ + /* these fields are used in SETOP_SORTED mode: */ - SetOpStatePerGroup pergroup; /* per-group working state */ - HeapTuple grp_firstTuple; /* copy of first tuple of current group */ + SortSupport sortKeys; /* per-grouping-field sort data */ + SetOpStatePerInput leftInput; /* current outer-relation input state */ + SetOpStatePerInput rightInput; /* current inner-relation input state */ + bool need_init; /* have we read the first tuples yet? */ + /* these fields are used in SETOP_HASHED mode: */ + Oid *eqfuncoids; /* per-grouping-field equality fns */ + FmgrInfo *hashfunctions; /* per-grouping-field hash fns */ TupleHashTable hashtable; /* hash table with one entry per group */ MemoryContext tableContext; /* memory context containing hash table */ bool table_filled; /* hash table filled yet? */ diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h index 697a0282de41f..1129c4ba4b1b4 100644 --- a/src/include/nodes/extensible.h +++ b/src/include/nodes/extensible.h @@ -4,7 +4,7 @@ * Definitions for extensible nodes and custom scans * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/extensible.h @@ -15,7 +15,7 @@ #define EXTENSIBLE_H #include "access/parallel.h" -#include "commands/explain.h" +#include "commands/explain_state.h" #include "nodes/execnodes.h" #include "nodes/pathnodes.h" #include "nodes/plannodes.h" diff --git a/src/include/nodes/lockoptions.h b/src/include/nodes/lockoptions.h index 044ef42ee101b..0b534e3060363 100644 --- a/src/include/nodes/lockoptions.h +++ b/src/include/nodes/lockoptions.h @@ -4,7 +4,7 @@ * Common header for some locking-related declarations. * * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * src/include/nodes/lockoptions.h * diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 5209d3de89cd2..5473ce9a288a3 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -4,7 +4,7 @@ * prototypes for the creator functions of various nodes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/makefuncs.h @@ -68,6 +68,7 @@ extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat); extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location); +extern Constraint *makeNotNullConstraint(String *colname); extern TypeName *makeTypeName(char *typnam); extern TypeName *makeTypeNameFromNameList(List *names); @@ -98,7 +99,7 @@ extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool nulls_not_distinct, bool isready, bool concurrent, - bool summarizing); + bool summarizing, bool withoutoverlaps); extern Node *makeStringConst(char *str, int location); extern DefElem *makeDefElem(char *name, Node *arg, int location); diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h index addfbb1ccdf5e..5807ef805bd86 100644 --- a/src/include/nodes/memnodes.h +++ b/src/include/nodes/memnodes.h @@ -4,7 +4,7 @@ * POSTGRES memory context node definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/memnodes.h diff --git a/src/include/nodes/meson.build b/src/include/nodes/meson.build index b665e55b6571f..d1ca24dd32f0b 100644 --- a/src/include/nodes/meson.build +++ b/src/include/nodes/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group node_support_input_i = [ 'nodes/nodes.h', @@ -8,6 +8,7 @@ node_support_input_i = [ 'nodes/plannodes.h', 'nodes/execnodes.h', 'access/amapi.h', + 'access/cmptype.h', 'access/sdir.h', 'access/tableam.h', 'access/tsmapi.h', diff --git a/src/include/nodes/miscnodes.h b/src/include/nodes/miscnodes.h index 1612b63acda0b..bbd1a43c3fb03 100644 --- a/src/include/nodes/miscnodes.h +++ b/src/include/nodes/miscnodes.h @@ -10,7 +10,7 @@ * "context" pointers. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/miscnodes.h @@ -36,9 +36,10 @@ * After calling code that might report an error this way, check * error_occurred to see if an error happened. If so, and if details_wanted * is true, error_data has been filled with error details (stored in the - * callee's memory context!). FreeErrorData() can be called to release - * error_data, although that step is typically not necessary if the called - * code was run in a short-lived context. + * callee's memory context!). The ErrorData can be modified (e.g. downgraded + * to a WARNING) and reported with ThrowErrorData(). FreeErrorData() can be + * called to release error_data, although that step is typically not necessary + * if the called code was run in a short-lived context. */ typedef struct ErrorSaveContext { diff --git a/src/include/nodes/multibitmapset.h b/src/include/nodes/multibitmapset.h index d6f23b87368c3..a3b2c2a703134 100644 --- a/src/include/nodes/multibitmapset.h +++ b/src/include/nodes/multibitmapset.h @@ -18,7 +18,7 @@ * a small fraction of that has been built out; we'll add more as needed. * * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * src/include/nodes/multibitmapset.h * diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h index eaba59bed834b..5653fec8cbe5e 100644 --- a/src/include/nodes/nodeFuncs.h +++ b/src/include/nodes/nodeFuncs.h @@ -3,7 +3,7 @@ * nodeFuncs.h * Various general-purpose manipulations of Node trees * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/nodeFuncs.h @@ -31,6 +31,8 @@ struct PlanState; /* avoid including execnodes.h too */ #define QTW_DONT_COPY_QUERY 0x40 /* do not copy top Query */ #define QTW_EXAMINE_SORTGROUP 0x80 /* include SortGroupClause lists */ +#define QTW_IGNORE_GROUPEXPRS 0x100 /* GROUP expressions list */ + /* callback function for check_functions_in_node */ typedef bool (*check_function_callback) (Oid func_id, void *context); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 0d71d821f714c..fbe333d88fac9 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -4,7 +4,7 @@ * Definitions for tagged nodes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/nodes.h @@ -54,6 +54,7 @@ typedef enum NodeTag * readfuncs.c. * * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c. + * Also available as a node field attribute. * * - no_copy: Does not support copyObject() at all. * @@ -101,10 +102,15 @@ typedef enum NodeTag * - equal_ignore_if_zero: Ignore the field for equality if it is zero. * (Otherwise, compare normally.) * + * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c + * for the field of a node. Also available as a node attribute. + * * - query_jumble_ignore: Ignore the field for the query jumbling. Note * that typmod and collation information are usually irrelevant for the * query jumbling. * + * - query_jumble_squash: Squash multiple values during query jumbling. + * * - query_jumble_location: Mark the field as a location to track. This is * only allowed for integer fields that include "location" in their name. * @@ -202,7 +208,7 @@ extern char *bmsToString(const struct Bitmapset *bms); * nodes/{readfuncs.c,read.c} */ extern void *stringToNode(const char *str); -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED extern void *stringToNodeWithLocations(const char *str); #endif extern struct Bitmapset *readBitmapset(void); diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index 10c9fc5413b12..4321ca6329bf4 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -4,7 +4,7 @@ * Support for finding the values associated with Param nodes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/params.h diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 85a62b538e50f..ba12678d1cbd1 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -12,7 +12,7 @@ * identifying statement boundaries in multi-statement source strings. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/parsenodes.h @@ -127,8 +127,13 @@ typedef struct Query * query identifier (can be set by plugins); ignored for equal, as it * might not be set; also not stored. This is the result of the query * jumble, hence ignored. + * + * We store this as a signed value as this is the form it's displayed to + * users in places such as EXPLAIN and pg_stat_statements. Primarily this + * is done due to lack of an SQL type to represent the full range of + * uint64. */ - uint64 queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0)); + int64 queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0)); /* do I set the command result tag? */ bool canSetTag pg_node_attr(query_jumble_ignore); @@ -160,6 +165,8 @@ typedef struct Query bool hasForUpdate pg_node_attr(query_jumble_ignore); /* rewriter has applied some RLS policy */ bool hasRowSecurity pg_node_attr(query_jumble_ignore); + /* parser has added an RTE_GROUP RTE */ + bool hasGroupRTE pg_node_attr(query_jumble_ignore); /* is a RETURN statement */ bool isReturn pg_node_attr(query_jumble_ignore); @@ -195,6 +202,15 @@ typedef struct Query OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */ + /* + * The following three fields describe the contents of the RETURNING list + * for INSERT/UPDATE/DELETE/MERGE. returningOldAlias and returningNewAlias + * are the alias names for OLD and NEW, which may be user-supplied values, + * the defaults "old" and "new", or NULL (if the default "old"/"new" is + * already in use as the alias for some other relation). + */ + char *returningOldAlias pg_node_attr(query_jumble_ignore); + char *returningNewAlias pg_node_attr(query_jumble_ignore); List *returningList; /* return-values list (of TargetEntry) */ List *groupClause; /* a list of SortGroupClause's */ @@ -335,6 +351,14 @@ typedef struct A_Expr List *name; /* possibly-qualified name of operator */ Node *lexpr; /* left argument, or NULL if none */ Node *rexpr; /* right argument, or NULL if none */ + + /* + * If rexpr is a list of some kind, we separately track its starting and + * ending location; it's not the same as the starting and ending location + * of the token itself. + */ + ParseLoc rexpr_list_start; + ParseLoc rexpr_list_end; ParseLoc location; /* token location, or -1 if unknown */ } A_Expr; @@ -490,6 +514,8 @@ typedef struct A_ArrayExpr { NodeTag type; List *elements; /* array element expressions */ + ParseLoc list_start; /* start of the element list */ + ParseLoc list_end; /* end of the elements list */ ParseLoc location; /* token location, or -1 if unknown */ } A_ArrayExpr; @@ -726,7 +752,7 @@ typedef struct ColumnDef char *colname; /* name of column */ TypeName *typeName; /* type of column */ char *compression; /* compression method for column */ - int inhcount; /* number of times column is inherited */ + int16 inhcount; /* number of times column is inherited */ bool is_local; /* column has local (non-inherited) def'n */ bool is_not_null; /* NOT NULL constraint specified? */ bool is_from_type; /* column definition came from table type */ @@ -937,17 +963,6 @@ typedef struct PartitionRangeDatum ParseLoc location; /* token location, or -1 if unknown */ } PartitionRangeDatum; -/* - * PartitionDesc - info about single partition for ALTER TABLE SPLIT PARTITION command - */ -typedef struct SinglePartitionSpec -{ - NodeTag type; - - RangeVar *name; /* name of partition */ - PartitionBoundSpec *bound; /* FOR VALUES, if attaching */ -} SinglePartitionSpec; - /* * PartitionCmd - info for ALTER TABLE/INDEX ATTACH/DETACH PARTITION commands */ @@ -956,8 +971,6 @@ typedef struct PartitionCmd NodeTag type; RangeVar *name; /* name of partition to attach/detach */ PartitionBoundSpec *bound; /* FOR VALUES, if attaching */ - List *partlist; /* list of partitions, for MERGE/SPLIT - * PARTITION command */ bool concurrent; } PartitionCmd; @@ -1036,6 +1049,7 @@ typedef enum RTEKind RTE_RESULT, /* RTE represents an empty FROM clause; such * RTEs are added by the planner, they're not * present during parsing or rewriting */ + RTE_GROUP, /* the grouping step */ } RTEKind; typedef struct RangeTblEntry @@ -1051,8 +1065,13 @@ typedef struct RangeTblEntry */ /* user-written alias clause, if any */ Alias *alias pg_node_attr(query_jumble_ignore); - /* expanded reference names */ - Alias *eref pg_node_attr(query_jumble_ignore); + + /* + * Expanded reference names. This uses a custom query jumble function so + * that the table name is included in the computation, but not its list of + * columns. + */ + Alias *eref pg_node_attr(custom_query_jumble); RTEKind rtekind; /* see above */ @@ -1095,7 +1114,7 @@ typedef struct RangeTblEntry * tables to be invalidated if the underlying table is altered. */ /* OID of the relation */ - Oid relid; + Oid relid pg_node_attr(query_jumble_ignore); /* inheritance requested? */ bool inh; /* relation kind (see pg_class.relkind) */ @@ -1242,6 +1261,12 @@ typedef struct RangeTblEntry /* estimated or actual from caller */ Cardinality enrtuples pg_node_attr(query_jumble_ignore); + /* + * Fields valid for a GROUP RTE (else NIL): + */ + /* list of grouping expressions */ + List *groupexprs pg_node_attr(query_jumble_ignore); + /* * Fields valid in all RTEs: */ @@ -1442,6 +1467,7 @@ typedef struct SortGroupClause Index tleSortGroupRef; /* reference into targetlist */ Oid eqop; /* the equality operator ('=' op) */ Oid sortop; /* the ordering operator ('<' op), or 0 */ + bool reverse_sort; /* is sortop a "greater than" operator? */ bool nulls_first; /* do NULLs come before normal values? */ /* can eqop be implemented by hashing? */ bool hashable pg_node_attr(query_jumble_ignore); @@ -1729,6 +1755,41 @@ typedef struct MergeWhenClause List *values; /* VALUES to INSERT, or NULL */ } MergeWhenClause; +/* + * ReturningOptionKind - + * Possible kinds of option in RETURNING WITH(...) list + * + * Currently, this is used only for specifying OLD/NEW aliases. + */ +typedef enum ReturningOptionKind +{ + RETURNING_OPTION_OLD, /* specify alias for OLD in RETURNING */ + RETURNING_OPTION_NEW, /* specify alias for NEW in RETURNING */ +} ReturningOptionKind; + +/* + * ReturningOption - + * An individual option in the RETURNING WITH(...) list + */ +typedef struct ReturningOption +{ + NodeTag type; + ReturningOptionKind option; /* specified option */ + char *value; /* option's value */ + ParseLoc location; /* token location, or -1 if unknown */ +} ReturningOption; + +/* + * ReturningClause - + * List of RETURNING expressions, together with any WITH(...) options + */ +typedef struct ReturningClause +{ + NodeTag type; + List *options; /* list of ReturningOption elements */ + List *exprs; /* list of expressions to return */ +} ReturningClause; + /* * TriggerTransition - * representation of transition row or table naming clause @@ -2046,7 +2107,7 @@ typedef struct InsertStmt List *cols; /* optional: names of the target columns */ Node *selectStmt; /* the source SELECT/VALUES, or NULL */ OnConflictClause *onConflictClause; /* ON CONFLICT clause */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ OverridingKind override; /* OVERRIDING clause */ } InsertStmt; @@ -2061,7 +2122,7 @@ typedef struct DeleteStmt RangeVar *relation; /* relation to delete from */ List *usingClause; /* optional using clause for more tables */ Node *whereClause; /* qualifications */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } DeleteStmt; @@ -2076,7 +2137,7 @@ typedef struct UpdateStmt List *targetList; /* the target list (of ResTarget) */ Node *whereClause; /* qualifications */ List *fromClause; /* optional from clause for more tables */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } UpdateStmt; @@ -2091,7 +2152,7 @@ typedef struct MergeStmt Node *sourceRelation; /* source relation */ Node *joinCondition; /* join condition between source and target */ List *mergeWhenClauses; /* list of MergeWhenClause(es) */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } MergeStmt; @@ -2358,7 +2419,6 @@ typedef enum AlterTableType AT_SetNotNull, /* alter column set not null */ AT_SetExpression, /* alter column set expression */ AT_DropExpression, /* alter column drop expression */ - AT_CheckNotNull, /* check column is already marked not null */ AT_SetStatistics, /* alter column set statistics */ AT_SetOptions, /* alter column set ( options ) */ AT_ResetOptions, /* alter column reset ( options ) */ @@ -2413,21 +2473,12 @@ typedef enum AlterTableType AT_AttachPartition, /* ATTACH PARTITION */ AT_DetachPartition, /* DETACH PARTITION */ AT_DetachPartitionFinalize, /* DETACH PARTITION FINALIZE */ - AT_SplitPartition, /* SPLIT PARTITION */ - AT_MergePartitions, /* MERGE PARTITIONS */ AT_AddIdentity, /* ADD IDENTITY */ AT_SetIdentity, /* SET identity column options */ AT_DropIdentity, /* DROP IDENTITY */ AT_ReAddStatistics, /* internal to commands/tablecmds.c */ } AlterTableType; -typedef struct ReplicaIdentityStmt -{ - NodeTag type; - char identity_type; - char *name; -} ReplicaIdentityStmt; - typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ { NodeTag type; @@ -2444,6 +2495,28 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ bool recurse; /* exec-time recursion */ } AlterTableCmd; +/* Ad-hoc node for AT_AlterConstraint */ +typedef struct ATAlterConstraint +{ + NodeTag type; + char *conname; /* Constraint name */ + bool alterEnforceability; /* changing enforceability properties? */ + bool is_enforced; /* ENFORCED? */ + bool alterDeferrability; /* changing deferrability properties? */ + bool deferrable; /* DEFERRABLE? */ + bool initdeferred; /* INITIALLY DEFERRED? */ + bool alterInheritability; /* changing inheritability properties */ + bool noinherit; +} ATAlterConstraint; + +/* Ad-hoc node for AT_ReplicaIdentity */ +typedef struct ReplicaIdentityStmt +{ + NodeTag type; + char identity_type; + char *name; +} ReplicaIdentityStmt; + /* ---------------------- * Alter Collation @@ -2622,11 +2695,26 @@ typedef enum VariableSetKind typedef struct VariableSetStmt { + pg_node_attr(custom_query_jumble) + NodeTag type; VariableSetKind kind; - char *name; /* variable to be set */ - List *args; /* List of A_Const nodes */ - bool is_local; /* SET LOCAL? */ + /* variable to be set */ + char *name; + /* List of A_Const nodes */ + List *args; + + /* + * True if arguments should be accounted for in query jumbling. We use a + * separate flag rather than query_jumble_ignore on "args" as several + * grammar flavors of SET rely on a list of values that are parsed + * directly from the grammar's keywords. + */ + bool jumble_args; + /* SET LOCAL? */ + bool is_local; + /* token location, or -1 if unknown */ + ParseLoc location pg_node_attr(query_jumble_location); } VariableSetStmt; /* ---------------------- @@ -2643,10 +2731,10 @@ typedef struct VariableShowStmt * Create Table Statement * * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are - * intermixed in tableElts, and constraints is NIL. After parse analysis, - * tableElts contains just ColumnDefs, and constraints contains just - * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present - * implementation). + * intermixed in tableElts, and constraints and nnconstraints are NIL. After + * parse analysis, tableElts contains just ColumnDefs, nnconstraints contains + * Constraint nodes of CONSTR_NOTNULL type from various sources, and + * constraints contains just CONSTR_CHECK Constraint nodes. * ---------------------- */ @@ -2661,6 +2749,7 @@ typedef struct CreateStmt PartitionSpec *partspec; /* PARTITION BY clause */ TypeName *ofTypename; /* OF typename */ List *constraints; /* constraints (list of Constraint nodes) */ + List *nnconstraints; /* NOT NULL constraints (ditto) */ List *options; /* options from WITH clause */ OnCommitAction oncommit; /* what do we do at COMMIT? */ char *tablespacename; /* table space to use, or NULL */ @@ -2716,6 +2805,8 @@ typedef enum ConstrType /* types of constraints */ CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_ATTR_DEFERRED, CONSTR_ATTR_IMMEDIATE, + CONSTR_ATTR_ENFORCED, + CONSTR_ATTR_NOT_ENFORCED, } ConstrType; /* Foreign key action codes */ @@ -2737,6 +2828,7 @@ typedef struct Constraint char *conname; /* Constraint name, or NULL if unnamed */ bool deferrable; /* DEFERRABLE? */ bool initdeferred; /* INITIALLY DEFERRED? */ + bool is_enforced; /* enforced constraint? */ bool skip_validation; /* skip validation of existing rows? */ bool initially_valid; /* mark the new constraint as valid? */ bool is_no_inherit; /* is constraint non-inheritable? */ @@ -2745,11 +2837,11 @@ typedef struct Constraint char *cooked_expr; /* CHECK or DEFAULT expression, as * nodeToString representation */ char generated_when; /* ALWAYS or BY DEFAULT */ - int inhcount; /* initial inheritance count to apply, for - * "raw" NOT NULL constraints */ + char generated_kind; /* STORED or VIRTUAL */ bool nulls_not_distinct; /* null treatment for UNIQUE constraints */ List *keys; /* String nodes naming referenced key * column(s); for UNIQUE/PK/NOT NULL */ + bool without_overlaps; /* WITHOUT OVERLAPS specified */ List *including; /* String nodes naming referenced nonkey * column(s); for UNIQUE/PK */ List *exclusions; /* list of (IndexElem, operator name) pairs; @@ -2766,6 +2858,8 @@ typedef struct Constraint RangeVar *pktable; /* Primary key table */ List *fk_attrs; /* Attributes of foreign key */ List *pk_attrs; /* Corresponding attrs in PK table */ + bool fk_with_period; /* Last attribute of FK uses PERIOD */ + bool pk_with_period; /* Last attribute of PK uses PERIOD */ char fk_matchtype; /* FULL, PARTIAL, SIMPLE */ char fk_upd_action; /* ON UPDATE action */ char fk_del_action; /* ON DELETE action */ @@ -3373,6 +3467,7 @@ typedef struct IndexStmt bool nulls_not_distinct; /* null treatment for UNIQUE constraints */ bool primary; /* is index a primary key? */ bool isconstraint; /* is it for a pkey/unique constraint? */ + bool iswithoutoverlaps; /* is the constraint WITHOUT OVERLAPS? */ bool deferrable; /* is the constraint DEFERRABLE? */ bool initdeferred; /* is the constraint INITIALLY DEFERRED? */ bool transformed; /* true when transformIndexStmt is finished */ @@ -3460,6 +3555,7 @@ typedef struct FunctionParameter TypeName *argType; /* TypeName for parameter type */ FunctionParameterMode mode; /* IN/OUT/etc */ Node *defexpr; /* raw default expr, or NULL if not given */ + ParseLoc location; /* token location, or -1 if unknown */ } FunctionParameter; typedef struct AlterFunctionStmt diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 14ccfc1ac1c78..6567759595daa 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -6,7 +6,7 @@ * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes. * There are some subsidiary structs that are useful to copy, though. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/pathnodes.h @@ -116,6 +116,19 @@ typedef struct PlannerGlobal /* "flat" rangetable for executor */ List *finalrtable; + /* + * RT indexes of all relation RTEs in finalrtable (RTE_RELATION and + * RTE_SUBQUERY RTEs of views) + */ + Bitmapset *allRelids; + + /* + * RT indexes of all leaf partitions in nodes that support pruning and are + * subject to runtime pruning at plan initialization time ("initial" + * pruning). + */ + Bitmapset *prunableRelids; + /* "flat" list of RTEPermissionInfos */ List *finalrteperminfos; @@ -128,6 +141,9 @@ typedef struct PlannerGlobal /* "flat" list of AppendRelInfos */ List *appendRelations; + /* "flat" list of PartitionPruneInfos */ + List *partPruneInfos; + /* OIDs of relations the plan depends on */ List *relationOids; @@ -185,6 +201,11 @@ typedef struct PlannerGlobal * Not all fields are printed. (In some cases, there is no print support for * the field type; in others, doing so would lead to infinite recursion or * bloat dump output more than seems useful.) + * + * NOTE: When adding new entries containing relids and relid bitmapsets, + * remember to check that they will be correctly processed by + * the remove_self_join_rel function - relid of removing relation will be + * correctly replaced with the keeping one. *---------- */ #ifndef HAVE_PLANNERINFO_TYPEDEF @@ -509,6 +530,12 @@ struct PlannerInfo /* true if planning a recursive WITH item */ bool hasRecursion; + /* + * The rangetable index for the RTE_GROUP RTE, or 0 if there is no + * RTE_GROUP RTE. + */ + int group_rtindex; + /* * Information about aggregates. Filled by preprocess_aggrefs(). */ @@ -553,6 +580,9 @@ struct PlannerInfo /* Does this query modify any partition key columns? */ bool partColsUpdated; + + /* PartitionPruneInfos added in this query's plan. */ + List *partPruneInfos; }; @@ -728,7 +758,7 @@ typedef struct PartitionSchemeData *PartitionScheme; * populate these fields, for base rels; but someday they might be used for * join rels too: * - * unique_for_rels - list of Relid sets, each one being a set of other + * unique_for_rels - list of UniqueRelInfo, each one being a set of other * rels for which this one has been proven unique * non_unique_for_rels - list of Relid sets, each one being a set of * other rels for which we have tried and failed to prove @@ -967,7 +997,7 @@ typedef struct RelOptInfo /* * cache space for remembering if we have proven this relation unique */ - /* known unique for these other relid set(s) */ + /* known unique for these other relid set(s) given in UniqueRelInfo(s) */ List *unique_for_rels; /* known not unique for these set(s) */ List *non_unique_for_rels; @@ -1101,6 +1131,8 @@ typedef struct IndexOptInfo IndexOptInfo; #define HAVE_INDEXOPTINFO_TYPEDEF 1 #endif +struct IndexPath; /* forward declaration */ + struct IndexOptInfo { pg_node_attr(no_copy_equal, no_read, no_query_jumble) @@ -1178,6 +1210,8 @@ struct IndexOptInfo bool predOK; /* true if a unique index */ bool unique; + /* true if the index was defined with NULLS NOT DISTINCT */ + bool nullsnotdistinct; /* is uniqueness enforced immediately? */ bool immediate; /* true if index doesn't really exist */ @@ -1200,7 +1234,7 @@ struct IndexOptInfo bool amcanmarkpos; /* AM's cost estimator */ /* Rather than include amapi.h here, we declare amcostestimate like this */ - void (*amcostestimate) () pg_node_attr(read_write_ignore); + void (*amcostestimate) (struct PlannerInfo *, struct IndexPath *, double, Cost *, Cost *, Selectivity *, double *, double *) pg_node_attr(read_write_ignore); }; /* @@ -1365,6 +1399,36 @@ typedef struct JoinDomain * entry: consider SELECT random() AS a, random() AS b ... ORDER BY b,a. * So we record the SortGroupRef of the originating sort clause. * + * Derived equality clauses are stored in ec_derives_list. For small queries, + * this list is scanned directly during lookup. For larger queries -- e.g., + * with many partitions or joins -- a hash table (ec_derives_hash) is built + * when the list grows beyond a threshold, for faster lookup. When present, + * the hash table contains the same RestrictInfos and is maintained alongside + * the list. We retain the list even when the hash is used to simplify + * serialization (e.g., in _outEquivalenceClass()) and support + * EquivalenceClass merging. + * + * In contrast, ec_sources holds equality clauses that appear directly in the + * query. These are typically few and do not require a hash table for lookup. + * + * 'ec_members' is a List of all !em_is_child EquivalenceMembers in the class. + * EquivalenceMembers for any RELOPT_OTHER_MEMBER_REL and RELOPT_OTHER_JOINREL + * relations are stored in the 'ec_childmembers' array in the index + * corresponding to the relid, or first component relid in the case of + * RELOPT_OTHER_JOINRELs. 'ec_childmembers' is NULL if the class has no child + * EquivalenceMembers. + * + * For code wishing to look at EquivalenceMembers, if only parent-level + * members are needed, then a simple foreach loop over ec_members is + * sufficient. When child members are also required, it is best to use the + * functionality provided by EquivalenceMemberIterator. This visits all + * parent members and only the relevant child members. The reason for this + * is that large numbers of child EquivalenceMembers can exist in queries to + * partitioned tables with many partitions. The functionality provided by + * EquivalenceMemberIterator allows efficient access to EquivalenceMembers + * which belong to specific child relids. See the header comments for + * EquivalenceMemberIterator below for further details. + * * NB: if ec_merged isn't NULL, this class has been merged into another, and * should be ignored in favor of using the pointed-to class. * @@ -1382,9 +1446,14 @@ typedef struct EquivalenceClass List *ec_opfamilies; /* btree operator family OIDs */ Oid ec_collation; /* collation, if datatypes are collatable */ + int ec_childmembers_size; /* # elements in ec_childmembers */ List *ec_members; /* list of EquivalenceMembers */ + List **ec_childmembers; /* array of Lists of child members */ List *ec_sources; /* list of generating RestrictInfos */ - List *ec_derives; /* list of derived RestrictInfos */ + List *ec_derives_list; /* list of derived RestrictInfos */ + struct derives_hash *ec_derives_hash; /* optional hash table for fast + * lookup; contains same + * RestrictInfos as list */ Relids ec_relids; /* all relids appearing in ec_members, except * for child members (see below) */ bool ec_has_const; /* any pseudoconstants in ec_members? */ @@ -1413,12 +1482,17 @@ typedef struct EquivalenceClass * child when necessary to build a MergeAppend path for the whole appendrel * tree. An em_is_child member has no impact on the properties of the EC as a * whole; in particular the EC's ec_relids field does NOT include the child - * relation. An em_is_child member should never be marked em_is_const nor - * cause ec_has_const or ec_has_volatile to be set, either. Thus, em_is_child - * members are not really full-fledged members of the EC, but just reflections - * or doppelgangers of real members. Most operations on EquivalenceClasses - * should ignore em_is_child members, and those that don't should test - * em_relids to make sure they only consider relevant members. + * relation. em_is_child members aren't stored in the ec_members List of the + * EC and instead they're stored and indexed by the relids of the child + * relation they represent in ec_childmembers. An em_is_child member + * should never be marked em_is_const nor cause ec_has_const or + * ec_has_volatile to be set, either. Thus, em_is_child members are not + * really full-fledged members of the EC, but just reflections or + * doppelgangers of real members. Most operations on EquivalenceClasses + * should ignore em_is_child members by only inspecting members in the + * ec_members list. Callers that require inspecting child members should do + * so using an EquivalenceMemberIterator and should test em_relids to make + * sure they only consider relevant members. * * em_datatype is usually the same as exprType(em_expr), but can be * different when dealing with a binary-compatible opfamily; in particular @@ -1441,6 +1515,67 @@ typedef struct EquivalenceMember struct EquivalenceMember *em_parent pg_node_attr(read_write_ignore); } EquivalenceMember; +/* + * EquivalenceMemberIterator + * + * EquivalenceMemberIterator allows efficient access to sets of + * EquivalenceMembers for callers which require access to child members. + * Because partitioning workloads can result in large numbers of child + * members, the child members are not stored in the EquivalenceClass's + * ec_members List. Instead, these are stored in the EquivalenceClass's + * ec_childmembers array of Lists. The functionality provided by + * EquivalenceMemberIterator aims to provide efficient access to parent + * members and child members belonging to specific child relids. + * + * Currently, there is only one way to initialize and iterate over an + * EquivalenceMemberIterator and that is via the setup_eclass_member_iterator + * and eclass_member_iterator_next functions. The iterator object is + * generally a local variable which is passed by address to + * setup_eclass_member_iterator. The calling function defines which + * EquivalenceClass the iterator should be looking at and which child + * relids to also return members for. child_relids can be passed as NULL, but + * the caller may as well just perform a foreach loop over ec_members as only + * parent-level members will be returned in that case. + * + * When calling the next function on an EquivalenceMemberIterator, all + * parent-level EquivalenceMembers are returned first, followed by all child + * members for the specified 'child_relids' for all child members which were + * indexed by any of the specified 'child_relids' in add_child_eq_member(). + * + * Code using the iterator method of finding EquivalenceMembers will generally + * always want to ensure the returned member matches their search criteria + * rather than relying on the filtering to be done for them as all parent + * members are returned and for members belonging to RELOPT_OTHER_JOINREL + * rels, the member's em_relids may be a superset of the specified + * 'child_relids', which might not be what the caller wants. + * + * The most common way to use this iterator is as follows: + * ----- + * EquivalenceMemberIterator it; + * EquivalenceMember *em; + * + * setup_eclass_member_iterator(&it, ec, child_relids); + * while ((em = eclass_member_iterator_next(&it)) != NULL) + * { + * ... + * } + * ----- + * It is not valid to call eclass_member_iterator_next() after it has returned + * NULL for any given EquivalenceMemberIterator. Individual fields within + * the EquivalenceMemberIterator struct must not be accessed by callers. + */ +typedef struct +{ + EquivalenceClass *ec; /* The EquivalenceClass to iterate over */ + int current_relid; /* Current relid position within 'relids'. -1 + * when still looping over ec_members and -2 + * at the end of iteration */ + Relids child_relids; /* Relids of child relations of interest. + * Non-child rels are ignored */ + ListCell *current_cell; /* Next cell to return within current_list */ + List *current_list; /* Current list of members being returned */ +} EquivalenceMemberIterator; + /* * PathKeys * @@ -1454,9 +1589,7 @@ typedef struct EquivalenceMember * equivalent and closely-related orderings. (See optimizer/README for more * information.) * - * Note: pk_strategy is either BTLessStrategyNumber (for ASC) or - * BTGreaterStrategyNumber (for DESC). We assume that all ordering-capable - * index types will use btree-compatible strategy numbers. + * Note: pk_cmptype is either COMPARE_LT (for ASC) or COMPARE_GT (for DESC). */ typedef struct PathKey { @@ -1466,8 +1599,8 @@ typedef struct PathKey /* the value that is ordered */ EquivalenceClass *pk_eclass pg_node_attr(copy_as_scalar, equal_as_scalar); - Oid pk_opfamily; /* btree opfamily defining the ordering */ - int pk_strategy; /* sort direction (ASC or DESC) */ + Oid pk_opfamily; /* index opfamily defining the ordering */ + CompareType pk_cmptype; /* sort direction (ASC or DESC) */ bool pk_nulls_first; /* do NULLs come before normal values? */ } PathKey; @@ -1658,6 +1791,7 @@ typedef struct Path /* estimated size/costs for path (see costsize.c for more info) */ Cardinality rows; /* estimated number of result tuples */ + int disabled_nodes; /* count of disabled nodes */ Cost startup_cost; /* cost expended before fetching any tuples */ Cost total_cost; /* total cost (assuming all tuples fetched) */ @@ -2116,6 +2250,12 @@ typedef struct NestPath * mergejoin. If it is not NIL then it is a PathKeys list describing * the ordering that must be created by an explicit Sort node. * + * outer_presorted_keys is the number of presorted keys of the outer + * path that match outersortkeys. It is used to determine whether + * explicit incremental sort can be applied when outersortkeys is not + * NIL. We do not track the number of presorted keys of the inner + * path, as incremental sort currently does not support mark/restore. + * * skip_mark_restore is true if the executor need not do mark/restore calls. * Mark/restore overhead is usually required, but can be skipped if we know * that the executor need find only one match per outer tuple, and that the @@ -2133,6 +2273,8 @@ typedef struct MergePath List *path_mergeclauses; /* join clauses to be used for merge */ List *outersortkeys; /* keys for explicit sort, if any */ List *innersortkeys; /* keys for explicit sort, if any */ + int outer_presorted_keys; /* number of presorted keys of the + * outer path */ bool skip_mark_restore; /* can executor skip mark/restore? */ bool materialize_inner; /* add Materialize to inner? */ } MergePath; @@ -2330,13 +2472,12 @@ typedef struct WindowAggPath typedef struct SetOpPath { Path path; - Path *subpath; /* path representing input source */ + Path *leftpath; /* paths representing input sources */ + Path *rightpath; SetOpCmd cmd; /* what to do, see nodes.h */ SetOpStrategy strategy; /* how to do it, see nodes.h */ - List *distinctList; /* SortGroupClauses identifying target cols */ - AttrNumber flagColIdx; /* where is the flag column, if any */ - int firstFlag; /* flag value for first input relation */ - Cardinality numGroups; /* estimated number of groups in input */ + List *groupList; /* SortGroupClauses identifying target cols */ + Cardinality numGroups; /* estimated number of groups in left input */ } SetOpPath; /* @@ -2732,9 +2873,9 @@ typedef struct RestrictInfo typedef struct MergeScanSelCache { /* Ordering details (cache lookup key) */ - Oid opfamily; /* btree opfamily defining the ordering */ + Oid opfamily; /* index opfamily defining the ordering */ Oid collation; /* collation for the ordering */ - int strategy; /* sort direction (ASC or DESC) */ + CompareType cmptype; /* sort direction (ASC or DESC) */ bool nulls_first; /* do NULLs come before normal values? */ /* Results */ Selectivity leftstartsel; /* first-join fraction for clause left side */ @@ -3333,6 +3474,7 @@ typedef struct typedef struct JoinCostWorkspace { /* Preliminary cost estimates --- must not be larger than final ones! */ + int disabled_nodes; Cost startup_cost; /* cost expended before fetching any tuples */ Cost total_cost; /* total cost (assuming all tuples fetched) */ @@ -3432,4 +3574,35 @@ typedef struct AggTransInfo bool initValueIsNull; } AggTransInfo; +/* + * UniqueRelInfo caches a fact that a relation is unique when being joined + * to other relation(s). + */ +typedef struct UniqueRelInfo +{ + pg_node_attr(no_copy_equal, no_read, no_query_jumble) + + NodeTag type; + + /* + * The relation in consideration is unique when being joined with this set + * of other relation(s). + */ + Relids outerrelids; + + /* + * The relation in consideration is unique when considering only clauses + * suitable for self-join (passed split_selfjoin_quals()). + */ + bool self_join; + + /* + * Additional clauses from a baserestrictinfo list that were used to prove + * the uniqueness. We cache it for the self-join checking procedure: a + * self-join can be removed if the outer relation contains strictly the + * same set of clauses. + */ + List *extra_clauses; +} UniqueRelInfo; + #endif /* PATHNODES_H */ diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h index 52df93759f7a2..4d1cdbbcfdd5e 100644 --- a/src/include/nodes/pg_list.h +++ b/src/include/nodes/pg_list.h @@ -29,7 +29,7 @@ * always be so; be careful to use the appropriate list type for your data.) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/pg_list.h @@ -485,7 +485,7 @@ for_each_cell_setup(const List *lst, const ListCell *initcell) for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ - (var = func(&var##__state.l->elements[var##__state.i]), true)); \ + (var = (type pointer) func(&var##__state.l->elements[var##__state.i]), true)); \ var##__state.i++) /* @@ -608,23 +608,23 @@ extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2, ListCell datum3, ListCell datum4, ListCell datum5); -extern pg_nodiscard List *lappend(List *list, void *datum); -extern pg_nodiscard List *lappend_int(List *list, int datum); -extern pg_nodiscard List *lappend_oid(List *list, Oid datum); -extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum); +pg_nodiscard extern List *lappend(List *list, void *datum); +pg_nodiscard extern List *lappend_int(List *list, int datum); +pg_nodiscard extern List *lappend_oid(List *list, Oid datum); +pg_nodiscard extern List *lappend_xid(List *list, TransactionId datum); -extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum); -extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum); -extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum); +pg_nodiscard extern List *list_insert_nth(List *list, int pos, void *datum); +pg_nodiscard extern List *list_insert_nth_int(List *list, int pos, int datum); +pg_nodiscard extern List *list_insert_nth_oid(List *list, int pos, Oid datum); -extern pg_nodiscard List *lcons(void *datum, List *list); -extern pg_nodiscard List *lcons_int(int datum, List *list); -extern pg_nodiscard List *lcons_oid(Oid datum, List *list); +pg_nodiscard extern List *lcons(void *datum, List *list); +pg_nodiscard extern List *lcons_int(int datum, List *list); +pg_nodiscard extern List *lcons_oid(Oid datum, List *list); -extern pg_nodiscard List *list_concat(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2); +pg_nodiscard extern List *list_concat(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_copy(const List *list1, const List *list2); -extern pg_nodiscard List *list_truncate(List *list, int new_size); +pg_nodiscard extern List *list_truncate(List *list, int new_size); extern bool list_member(const List *list, const void *datum); extern bool list_member_ptr(const List *list, const void *datum); @@ -632,15 +632,15 @@ extern bool list_member_int(const List *list, int datum); extern bool list_member_oid(const List *list, Oid datum); extern bool list_member_xid(const List *list, TransactionId datum); -extern pg_nodiscard List *list_delete(List *list, void *datum); -extern pg_nodiscard List *list_delete_ptr(List *list, void *datum); -extern pg_nodiscard List *list_delete_int(List *list, int datum); -extern pg_nodiscard List *list_delete_oid(List *list, Oid datum); -extern pg_nodiscard List *list_delete_first(List *list); -extern pg_nodiscard List *list_delete_last(List *list); -extern pg_nodiscard List *list_delete_first_n(List *list, int n); -extern pg_nodiscard List *list_delete_nth_cell(List *list, int n); -extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell); +pg_nodiscard extern List *list_delete(List *list, void *datum); +pg_nodiscard extern List *list_delete_ptr(List *list, void *datum); +pg_nodiscard extern List *list_delete_int(List *list, int datum); +pg_nodiscard extern List *list_delete_oid(List *list, Oid datum); +pg_nodiscard extern List *list_delete_first(List *list); +pg_nodiscard extern List *list_delete_last(List *list); +pg_nodiscard extern List *list_delete_first_n(List *list, int n); +pg_nodiscard extern List *list_delete_nth_cell(List *list, int n); +pg_nodiscard extern List *list_delete_cell(List *list, ListCell *cell); extern List *list_union(const List *list1, const List *list2); extern List *list_union_ptr(const List *list1, const List *list2); @@ -657,25 +657,25 @@ extern List *list_difference_ptr(const List *list1, const List *list2); extern List *list_difference_int(const List *list1, const List *list2); extern List *list_difference_oid(const List *list1, const List *list2); -extern pg_nodiscard List *list_append_unique(List *list, void *datum); -extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum); -extern pg_nodiscard List *list_append_unique_int(List *list, int datum); -extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum); +pg_nodiscard extern List *list_append_unique(List *list, void *datum); +pg_nodiscard extern List *list_append_unique_ptr(List *list, void *datum); +pg_nodiscard extern List *list_append_unique_int(List *list, int datum); +pg_nodiscard extern List *list_append_unique_oid(List *list, Oid datum); -extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_ptr(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_int(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_oid(List *list1, const List *list2); extern void list_deduplicate_oid(List *list); extern void list_free(List *list); extern void list_free_deep(List *list); -extern pg_nodiscard List *list_copy(const List *oldlist); -extern pg_nodiscard List *list_copy_head(const List *oldlist, int len); -extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip); -extern pg_nodiscard List *list_copy_deep(const List *oldlist); +pg_nodiscard extern List *list_copy(const List *oldlist); +pg_nodiscard extern List *list_copy_head(const List *oldlist, int len); +pg_nodiscard extern List *list_copy_tail(const List *oldlist, int nskip); +pg_nodiscard extern List *list_copy_deep(const List *oldlist); typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b); extern void list_sort(List *list, list_sort_comparator cmp); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 1aeeaec95e14c..4f59e30d62d5e 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -4,7 +4,7 @@ * definitions for query plan nodes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/plannodes.h @@ -49,54 +49,93 @@ typedef struct PlannedStmt NodeTag type; - CmdType commandType; /* select|insert|update|delete|merge|utility */ + /* select|insert|update|delete|merge|utility */ + CmdType commandType; - uint64 queryId; /* query identifier (copied from Query) */ + /* query identifier (copied from Query) */ + int64 queryId; - bool hasReturning; /* is it insert|update|delete|merge RETURNING? */ + /* plan identifier (can be set by plugins) */ + int64 planId; - bool hasModifyingCTE; /* has insert|update|delete|merge in WITH? */ + /* is it insert|update|delete|merge RETURNING? */ + bool hasReturning; - bool canSetTag; /* do I set the command result tag? */ + /* has insert|update|delete|merge in WITH? */ + bool hasModifyingCTE; - bool transientPlan; /* redo plan when TransactionXmin changes? */ + /* do I set the command result tag? */ + bool canSetTag; - bool dependsOnRole; /* is plan specific to current role? */ + /* redo plan when TransactionXmin changes? */ + bool transientPlan; - bool parallelModeNeeded; /* parallel mode required to execute? */ + /* is plan specific to current role? */ + bool dependsOnRole; - int jitFlags; /* which forms of JIT should be performed */ + /* parallel mode required to execute? */ + bool parallelModeNeeded; - struct Plan *planTree; /* tree of Plan nodes */ + /* which forms of JIT should be performed */ + int jitFlags; - List *rtable; /* list of RangeTblEntry nodes */ + /* tree of Plan nodes */ + struct Plan *planTree; - List *permInfos; /* list of RTEPermissionInfo nodes for rtable - * entries needing one */ + /* + * List of PartitionPruneInfo contained in the plan + */ + List *partPruneInfos; + + /* list of RangeTblEntry nodes */ + List *rtable; + + /* + * RT indexes of relations that are not subject to runtime pruning or are + * needed to perform runtime pruning + */ + Bitmapset *unprunableRelids; + + /* + * list of RTEPermissionInfo nodes for rtable entries needing one + */ + List *permInfos; /* rtable indexes of target relations for INSERT/UPDATE/DELETE/MERGE */ - List *resultRelations; /* integer list of RT indexes, or NIL */ + /* integer list of RT indexes, or NIL */ + List *resultRelations; - List *appendRelations; /* list of AppendRelInfo nodes */ + /* list of AppendRelInfo nodes */ + List *appendRelations; - List *subplans; /* Plan trees for SubPlan expressions; note - * that some could be NULL */ + /* + * Plan trees for SubPlan expressions; note that some could be NULL + */ + List *subplans; - Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */ + /* indices of subplans that require REWIND */ + Bitmapset *rewindPlanIDs; - List *rowMarks; /* a list of PlanRowMark's */ + /* a list of PlanRowMark's */ + List *rowMarks; - List *relationOids; /* OIDs of relations the plan depends on */ + /* OIDs of relations the plan depends on */ + List *relationOids; - List *invalItems; /* other dependencies, as PlanInvalItems */ + /* other dependencies, as PlanInvalItems */ + List *invalItems; - List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */ + /* type OIDs for PARAM_EXEC Params */ + List *paramExecTypes; - Node *utilityStmt; /* non-null if this is utility stmt */ + /* non-null if this is utility stmt */ + Node *utilityStmt; /* statement location in source string (copied from Query) */ - ParseLoc stmt_location; /* start location, or -1 if unknown */ - ParseLoc stmt_len; /* length in bytes; 0 means "rest of string" */ + /* start location, or -1 if unknown */ + ParseLoc stmt_location; + /* length in bytes; 0 means "rest of string" */ + ParseLoc stmt_len; } PlannedStmt; /* macro for fetching the Plan associated with a SubPlan node */ @@ -125,36 +164,49 @@ typedef struct Plan /* * estimated execution costs for plan (see costsize.c for more info) */ - Cost startup_cost; /* cost expended before fetching any tuples */ - Cost total_cost; /* total cost (assuming all tuples fetched) */ + /* count of disabled nodes */ + int disabled_nodes; + /* cost expended before fetching any tuples */ + Cost startup_cost; + /* total cost (assuming all tuples fetched) */ + Cost total_cost; /* * planner's estimate of result size of this plan step */ - Cardinality plan_rows; /* number of rows plan is expected to emit */ - int plan_width; /* average row width in bytes */ + /* number of rows plan is expected to emit */ + Cardinality plan_rows; + /* average row width in bytes */ + int plan_width; /* * information needed for parallel query */ - bool parallel_aware; /* engage parallel-aware logic? */ - bool parallel_safe; /* OK to use as part of parallel plan? */ + /* engage parallel-aware logic? */ + bool parallel_aware; + /* OK to use as part of parallel plan? */ + bool parallel_safe; /* * information needed for asynchronous execution */ - bool async_capable; /* engage asynchronous-capable logic? */ + /* engage asynchronous-capable logic? */ + bool async_capable; /* * Common structural data for all Plan types. */ - int plan_node_id; /* unique across entire final plan tree */ - List *targetlist; /* target list to be computed at this node */ - List *qual; /* implicitly-ANDed qual conditions */ - struct Plan *lefttree; /* input plan tree(s) */ + /* unique across entire final plan tree */ + int plan_node_id; + /* target list to be computed at this node */ + List *targetlist; + /* implicitly-ANDed qual conditions */ + List *qual; + /* input plan tree(s) */ + struct Plan *lefttree; struct Plan *righttree; - List *initPlan; /* Init Plan nodes (un-correlated expr - * subselects) */ + /* Init Plan nodes (un-correlated expr subselects) */ + List *initPlan; /* * Information for management of parameter-change-driven rescanning @@ -229,30 +281,54 @@ typedef struct ProjectSet typedef struct ModifyTable { Plan plan; - CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */ - bool canSetTag; /* do we set the command tag/es_processed? */ - Index nominalRelation; /* Parent RT index for use of EXPLAIN */ - Index rootRelation; /* Root RT index, if partitioned/inherited */ - bool partColsUpdated; /* some part key in hierarchy updated? */ - List *resultRelations; /* integer list of RT indexes */ - List *updateColnosLists; /* per-target-table update_colnos lists */ - List *withCheckOptionLists; /* per-target-table WCO lists */ - List *returningLists; /* per-target-table RETURNING tlists */ - List *fdwPrivLists; /* per-target-table FDW private data lists */ - Bitmapset *fdwDirectModifyPlans; /* indices of FDW DM plans */ - List *rowMarks; /* PlanRowMarks (non-locking only) */ - int epqParam; /* ID of Param for EvalPlanQual re-eval */ - OnConflictAction onConflictAction; /* ON CONFLICT action */ - List *arbiterIndexes; /* List of ON CONFLICT arbiter index OIDs */ - List *onConflictSet; /* INSERT ON CONFLICT DO UPDATE targetlist */ - List *onConflictCols; /* target column numbers for onConflictSet */ - Node *onConflictWhere; /* WHERE for ON CONFLICT UPDATE */ - Index exclRelRTI; /* RTI of the EXCLUDED pseudo relation */ - List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */ - List *mergeActionLists; /* per-target-table lists of actions for - * MERGE */ - List *mergeJoinConditions; /* per-target-table join conditions - * for MERGE */ + /* INSERT, UPDATE, DELETE, or MERGE */ + CmdType operation; + /* do we set the command tag/es_processed? */ + bool canSetTag; + /* Parent RT index for use of EXPLAIN */ + Index nominalRelation; + /* Root RT index, if partitioned/inherited */ + Index rootRelation; + /* some part key in hierarchy updated? */ + bool partColsUpdated; + /* integer list of RT indexes */ + List *resultRelations; + /* per-target-table update_colnos lists */ + List *updateColnosLists; + /* per-target-table WCO lists */ + List *withCheckOptionLists; + /* alias for OLD in RETURNING lists */ + char *returningOldAlias; + /* alias for NEW in RETURNING lists */ + char *returningNewAlias; + /* per-target-table RETURNING tlists */ + List *returningLists; + /* per-target-table FDW private data lists */ + List *fdwPrivLists; + /* indices of FDW DM plans */ + Bitmapset *fdwDirectModifyPlans; + /* PlanRowMarks (non-locking only) */ + List *rowMarks; + /* ID of Param for EvalPlanQual re-eval */ + int epqParam; + /* ON CONFLICT action */ + OnConflictAction onConflictAction; + /* List of ON CONFLICT arbiter index OIDs */ + List *arbiterIndexes; + /* INSERT ON CONFLICT DO UPDATE targetlist */ + List *onConflictSet; + /* target column numbers for onConflictSet */ + List *onConflictCols; + /* WHERE for ON CONFLICT UPDATE */ + Node *onConflictWhere; + /* RTI of the EXCLUDED pseudo relation */ + Index exclRelRTI; + /* tlist of the EXCLUDED pseudo relation */ + List *exclRelTlist; + /* per-target-table lists of actions for MERGE */ + List *mergeActionLists; + /* per-target-table join conditions for MERGE */ + List *mergeJoinConditions; } ModifyTable; struct PartitionPruneInfo; /* forward reference to struct below */ @@ -265,9 +341,11 @@ struct PartitionPruneInfo; /* forward reference to struct below */ typedef struct Append { Plan plan; - Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */ + /* RTIs of appendrel(s) formed by this node */ + Bitmapset *apprelids; List *appendplans; - int nasyncplans; /* # of asynchronous plans */ + /* # of asynchronous plans */ + int nasyncplans; /* * All 'appendplans' preceding this index are non-partial plans. All @@ -275,8 +353,12 @@ typedef struct Append */ int first_partial_plan; - /* Info for run-time subplan pruning; NULL if we're not doing that */ - struct PartitionPruneInfo *part_prune_info; + /* + * Index into PlannedStmt.partPruneInfos and parallel lists in EState: + * es_part_prune_states and es_part_prune_results. Set to -1 if no + * run-time pruning is used. + */ + int part_prune_index; } Append; /* ---------------- @@ -310,8 +392,12 @@ typedef struct MergeAppend /* NULLS FIRST/LAST directions */ bool *nullsFirst pg_node_attr(array_size(numCols)); - /* Info for run-time subplan pruning; NULL if we're not doing that */ - struct PartitionPruneInfo *part_prune_info; + /* + * Index into PlannedStmt.partPruneInfos and parallel lists in EState: + * es_part_prune_states and es_part_prune_results. Set to -1 if no + * run-time pruning is used. + */ + int part_prune_index; } MergeAppend; /* ---------------- @@ -386,7 +472,8 @@ typedef struct Scan pg_node_attr(abstract) Plan plan; - Index scanrelid; /* relid is index into the range table */ + /* relid is index into the range table */ + Index scanrelid; } Scan; /* ---------------- @@ -449,13 +536,20 @@ typedef struct SampleScan typedef struct IndexScan { Scan scan; - Oid indexid; /* OID of index to scan */ - List *indexqual; /* list of index quals (usually OpExprs) */ - List *indexqualorig; /* the same in original form */ - List *indexorderby; /* list of index ORDER BY exprs */ - List *indexorderbyorig; /* the same in original form */ - List *indexorderbyops; /* OIDs of sort ops for ORDER BY exprs */ - ScanDirection indexorderdir; /* forward or backward or don't care */ + /* OID of index to scan */ + Oid indexid; + /* list of index quals (usually OpExprs) */ + List *indexqual; + /* the same in original form */ + List *indexqualorig; + /* list of index ORDER BY exprs */ + List *indexorderby; + /* the same in original form */ + List *indexorderbyorig; + /* OIDs of sort ops for ORDER BY exprs */ + List *indexorderbyops; + /* forward or backward or don't care */ + ScanDirection indexorderdir; } IndexScan; /* ---------------- @@ -492,12 +586,18 @@ typedef struct IndexScan typedef struct IndexOnlyScan { Scan scan; - Oid indexid; /* OID of index to scan */ - List *indexqual; /* list of index quals (usually OpExprs) */ - List *recheckqual; /* index quals in recheckable form */ - List *indexorderby; /* list of index ORDER BY exprs */ - List *indextlist; /* TargetEntry list describing index's cols */ - ScanDirection indexorderdir; /* forward or backward or don't care */ + /* OID of index to scan */ + Oid indexid; + /* list of index quals (usually OpExprs) */ + List *indexqual; + /* index quals in recheckable form */ + List *recheckqual; + /* list of index ORDER BY exprs */ + List *indexorderby; + /* TargetEntry list describing index's cols */ + List *indextlist; + /* forward or backward or don't care */ + ScanDirection indexorderdir; } IndexOnlyScan; /* ---------------- @@ -520,10 +620,14 @@ typedef struct IndexOnlyScan typedef struct BitmapIndexScan { Scan scan; - Oid indexid; /* OID of index to scan */ - bool isshared; /* Create shared bitmap if set */ - List *indexqual; /* list of index quals (OpExprs) */ - List *indexqualorig; /* the same in original form */ + /* OID of index to scan */ + Oid indexid; + /* Create shared bitmap if set */ + bool isshared; + /* list of index quals (OpExprs) */ + List *indexqual; + /* the same in original form */ + List *indexqualorig; } BitmapIndexScan; /* ---------------- @@ -538,7 +642,8 @@ typedef struct BitmapIndexScan typedef struct BitmapHeapScan { Scan scan; - List *bitmapqualorig; /* index quals, in standard expr form */ + /* index quals, in standard expr form */ + List *bitmapqualorig; } BitmapHeapScan; /* ---------------- @@ -552,7 +657,8 @@ typedef struct BitmapHeapScan typedef struct TidScan { Scan scan; - List *tidquals; /* qual(s) involving CTID = something */ + /* qual(s) involving CTID = something */ + List *tidquals; } TidScan; /* ---------------- @@ -565,7 +671,8 @@ typedef struct TidScan typedef struct TidRangeScan { Scan scan; - List *tidrangequals; /* qual(s) involving CTID op something */ + /* qual(s) involving CTID op something */ + List *tidrangequals; } TidRangeScan; /* ---------------- @@ -609,8 +716,10 @@ typedef struct SubqueryScan typedef struct FunctionScan { Scan scan; - List *functions; /* list of RangeTblFunction nodes */ - bool funcordinality; /* WITH ORDINALITY */ + /* list of RangeTblFunction nodes */ + List *functions; + /* WITH ORDINALITY */ + bool funcordinality; } FunctionScan; /* ---------------- @@ -620,7 +729,8 @@ typedef struct FunctionScan typedef struct ValuesScan { Scan scan; - List *values_lists; /* list of expression lists */ + /* list of expression lists */ + List *values_lists; } ValuesScan; /* ---------------- @@ -630,7 +740,8 @@ typedef struct ValuesScan typedef struct TableFuncScan { Scan scan; - TableFunc *tablefunc; /* table function node */ + /* table function node */ + TableFunc *tablefunc; } TableFuncScan; /* ---------------- @@ -640,8 +751,10 @@ typedef struct TableFuncScan typedef struct CteScan { Scan scan; - int ctePlanId; /* ID of init SubPlan for CTE */ - int cteParam; /* ID of Param representing CTE output */ + /* ID of init SubPlan for CTE */ + int ctePlanId; + /* ID of Param representing CTE output */ + int cteParam; } CteScan; /* ---------------- @@ -651,7 +764,8 @@ typedef struct CteScan typedef struct NamedTuplestoreScan { Scan scan; - char *enrname; /* Name given to Ephemeral Named Relation */ + /* Name given to Ephemeral Named Relation */ + char *enrname; } NamedTuplestoreScan; /* ---------------- @@ -661,7 +775,8 @@ typedef struct NamedTuplestoreScan typedef struct WorkTableScan { Scan scan; - int wtParam; /* ID of Param representing work table */ + /* ID of Param representing work table */ + int wtParam; } WorkTableScan; /* ---------------- @@ -707,18 +822,28 @@ typedef struct WorkTableScan typedef struct ForeignScan { Scan scan; - CmdType operation; /* SELECT/INSERT/UPDATE/DELETE */ - Index resultRelation; /* direct modification target's RT index */ - Oid checkAsUser; /* user to perform the scan as; 0 means to - * check as current user */ - Oid fs_server; /* OID of foreign server */ - List *fdw_exprs; /* expressions that FDW may evaluate */ - List *fdw_private; /* private data for FDW */ - List *fdw_scan_tlist; /* optional tlist describing scan tuple */ - List *fdw_recheck_quals; /* original quals not in scan.plan.qual */ - Bitmapset *fs_relids; /* base+OJ RTIs generated by this scan */ - Bitmapset *fs_base_relids; /* base RTIs generated by this scan */ - bool fsSystemCol; /* true if any "system column" is needed */ + /* SELECT/INSERT/UPDATE/DELETE */ + CmdType operation; + /* direct modification target's RT index */ + Index resultRelation; + /* user to perform the scan as; 0 means to check as current user */ + Oid checkAsUser; + /* OID of foreign server */ + Oid fs_server; + /* expressions that FDW may evaluate */ + List *fdw_exprs; + /* private data for FDW */ + List *fdw_private; + /* optional tlist describing scan tuple */ + List *fdw_scan_tlist; + /* original quals not in scan.plan.qual */ + List *fdw_recheck_quals; + /* base+OJ RTIs generated by this scan */ + Bitmapset *fs_relids; + /* base RTIs generated by this scan */ + Bitmapset *fs_base_relids; + /* true if any "system column" is needed */ + bool fsSystemCol; } ForeignScan; /* ---------------- @@ -739,13 +864,18 @@ struct CustomScanMethods; typedef struct CustomScan { Scan scan; - uint32 flags; /* mask of CUSTOMPATH_* flags, see - * nodes/extensible.h */ - List *custom_plans; /* list of Plan nodes, if any */ - List *custom_exprs; /* expressions that custom code may evaluate */ - List *custom_private; /* private data for custom code */ - List *custom_scan_tlist; /* optional tlist describing scan tuple */ - Bitmapset *custom_relids; /* RTIs generated by this scan */ + /* mask of CUSTOMPATH_* flags, see nodes/extensible.h */ + uint32 flags; + /* list of Plan nodes, if any */ + List *custom_plans; + /* expressions that custom code may evaluate */ + List *custom_exprs; + /* private data for custom code */ + List *custom_private; + /* optional tlist describing scan tuple */ + List *custom_scan_tlist; + /* RTIs generated by this scan */ + Bitmapset *custom_relids; /* * NOTE: The method field of CustomScan is required to be a pointer to a @@ -790,7 +920,8 @@ typedef struct Join Plan plan; JoinType jointype; bool inner_unique; - List *joinqual; /* JOIN quals (in addition to plan.qual) */ + /* JOIN quals (in addition to plan.qual) */ + List *joinqual; } Join; /* ---------------- @@ -807,7 +938,8 @@ typedef struct Join typedef struct NestLoop { Join join; - List *nestParams; /* list of NestLoopParam nodes */ + /* list of NestLoopParam nodes */ + List *nestParams; } NestLoop; typedef struct NestLoopParam @@ -815,8 +947,10 @@ typedef struct NestLoopParam pg_node_attr(no_equal, no_query_jumble) NodeTag type; - int paramno; /* number of the PARAM_EXEC Param to set */ - Var *paramval; /* outer-relation Var to assign to Param */ + /* number of the PARAM_EXEC Param to set */ + int paramno; + /* outer-relation Var to assign to Param */ + Var *paramval; } NestLoopParam; /* ---------------- @@ -849,7 +983,7 @@ typedef struct MergeJoin Oid *mergeCollations pg_node_attr(array_size(mergeclauses)); /* per-clause ordering (ASC or DESC) */ - int *mergeStrategies pg_node_attr(array_size(mergeclauses)); + bool *mergeReversals pg_node_attr(array_size(mergeclauses)); /* per-clause nulls ordering */ bool *mergeNullsFirst pg_node_attr(array_size(mergeclauses)); @@ -955,7 +1089,8 @@ typedef struct Sort typedef struct IncrementalSort { Sort sort; - int nPresortedCols; /* number of presorted columns */ + /* number of presorted columns */ + int nPresortedCols; } IncrementalSort; /* --------------- @@ -1039,6 +1174,9 @@ typedef struct WindowAgg { Plan plan; + /* name of WindowClause implemented by this node */ + char *winname; + /* ID referenced by window functions */ Index winref; @@ -1140,12 +1278,20 @@ typedef struct Unique typedef struct Gather { Plan plan; - int num_workers; /* planned number of worker processes */ - int rescan_param; /* ID of Param that signals a rescan, or -1 */ - bool single_copy; /* don't execute plan more than once */ - bool invisible; /* suppress EXPLAIN display (for testing)? */ - Bitmapset *initParam; /* param id's of initplans which are referred - * at gather or one of it's child node */ + /* planned number of worker processes */ + int num_workers; + /* ID of Param that signals a rescan, or -1 */ + int rescan_param; + /* don't execute plan more than once */ + bool single_copy; + /* suppress EXPLAIN display (for testing)? */ + bool invisible; + + /* + * param id's of initplans which are referred at gather or one of its + * child nodes + */ + Bitmapset *initParam; } Gather; /* ------------ @@ -1181,7 +1327,7 @@ typedef struct GatherMerge /* * param id's of initplans which are referred at gather merge or one of - * it's child node + * its child nodes */ Bitmapset *initParam; } GatherMerge; @@ -1202,12 +1348,17 @@ typedef struct Hash * List of expressions to be hashed for tuples from Hash's outer plan, * needed to put them into the hashtable. */ - List *hashkeys; /* hash keys for the hashjoin condition */ - Oid skewTable; /* outer join key's table OID, or InvalidOid */ - AttrNumber skewColumn; /* outer join key's column #, or zero */ - bool skewInherit; /* is outer join rel an inheritance tree? */ + /* hash keys for the hashjoin condition */ + List *hashkeys; + /* outer join key's table OID, or InvalidOid */ + Oid skewTable; + /* outer join key's column #, or zero */ + AttrNumber skewColumn; + /* is outer join rel an inheritance tree? */ + bool skewInherit; /* all other info is in the parent HashJoin node */ - Cardinality rows_total; /* estimate total rows if parallel_aware */ + /* estimate total rows if parallel_aware */ + Cardinality rows_total; } Hash; /* ---------------- @@ -1224,23 +1375,20 @@ typedef struct SetOp /* how to do it, see nodes.h */ SetOpStrategy strategy; - /* number of columns to check for duplicate-ness */ + /* number of columns to compare */ int numCols; /* their indexes in the target list */ - AttrNumber *dupColIdx pg_node_attr(array_size(numCols)); + AttrNumber *cmpColIdx pg_node_attr(array_size(numCols)); - /* equality operators to compare with */ - Oid *dupOperators pg_node_attr(array_size(numCols)); - Oid *dupCollations pg_node_attr(array_size(numCols)); - - /* where is the flag column, if any */ - AttrNumber flagColIdx; + /* comparison operators (either equality operators or sort operators) */ + Oid *cmpOperators pg_node_attr(array_size(numCols)); + Oid *cmpCollations pg_node_attr(array_size(numCols)); - /* flag value for first input relation */ - int firstFlag; + /* nulls-first flags if sorting, otherwise not interesting */ + bool *cmpNullsFirst pg_node_attr(array_size(numCols)); - /* estimated number of groups in input */ + /* estimated number of groups in left input */ long numGroups; } SetOp; @@ -1256,8 +1404,10 @@ typedef struct SetOp typedef struct LockRows { Plan plan; - List *rowMarks; /* a list of PlanRowMark's */ - int epqParam; /* ID of Param for EvalPlanQual re-eval */ + /* a list of PlanRowMark's */ + List *rowMarks; + /* ID of Param for EvalPlanQual re-eval */ + int epqParam; } LockRows; /* ---------------- @@ -1379,14 +1529,22 @@ typedef struct PlanRowMark pg_node_attr(no_equal, no_query_jumble) NodeTag type; - Index rti; /* range table index of markable relation */ - Index prti; /* range table index of parent relation */ - Index rowmarkId; /* unique identifier for resjunk columns */ - RowMarkType markType; /* see enum above */ - int allMarkTypes; /* OR of (1< >= cases; * the = and <> cases are translated to simple AND or OR combinations - * of the pairwise comparisons. However, we include = and <> in the - * RowCompareType enum for the convenience of parser logic. + * of the pairwise comparisons. */ -typedef enum RowCompareType -{ - /* Values of this enum are chosen to match btree strategy numbers */ - ROWCOMPARE_LT = 1, /* BTLessStrategyNumber */ - ROWCOMPARE_LE = 2, /* BTLessEqualStrategyNumber */ - ROWCOMPARE_EQ = 3, /* BTEqualStrategyNumber */ - ROWCOMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */ - ROWCOMPARE_GT = 5, /* BTGreaterStrategyNumber */ - ROWCOMPARE_NE = 6, /* no such btree strategy */ -} RowCompareType; - typedef struct RowCompareExpr { Expr xpr; /* LT LE GE or GT, never EQ or NE */ - RowCompareType rctype; + CompareType cmptype; /* OID list of pairwise comparison ops */ List *opnos pg_node_attr(query_jumble_ignore); /* OID list of containing operator families */ @@ -1669,15 +1678,19 @@ typedef struct JsonReturning * JsonValueExpr - * representation of JSON value expression (expr [FORMAT JsonFormat]) * - * The actual value is obtained by evaluating formatted_expr. raw_expr is - * only there for displaying the original user-written expression and is not - * evaluated by ExecInterpExpr() and eval_const_expressions_mutator(). + * raw_expr is the user-specified value, while formatted_expr is the value + * obtained by coercing raw_expr to the type required by either the FORMAT + * clause or an enclosing node's RETURNING clause. + * + * When deparsing a JsonValueExpr, get_rule_expr() prints raw_expr. However, + * during the evaluation of a JsonValueExpr, the value of formatted_expr + * takes precedence over that of raw_expr. */ typedef struct JsonValueExpr { NodeTag type; - Expr *raw_expr; /* raw expression */ - Expr *formatted_expr; /* formatted expression */ + Expr *raw_expr; /* user-specified expression */ + Expr *formatted_expr; /* coerced formatted expression */ JsonFormat *format; /* FORMAT clause, if specified */ } JsonValueExpr; @@ -2124,6 +2137,30 @@ typedef struct InferenceElem Oid inferopclass; /* OID of att opclass, or InvalidOid */ } InferenceElem; +/* + * ReturningExpr - return OLD/NEW.(expression) in RETURNING list + * + * This is used when updating an auto-updatable view and returning a view + * column that is not simply a Var referring to the base relation. In such + * cases, OLD/NEW.viewcol can expand to an arbitrary expression, but the + * result is required to be NULL if the OLD/NEW row doesn't exist. To handle + * this, the rewriter wraps the expanded expression in a ReturningExpr, which + * is equivalent to "CASE WHEN (OLD/NEW row exists) THEN (expr) ELSE NULL". + * + * A similar situation can arise when rewriting the RETURNING clause of a + * rule, which may also contain arbitrary expressions. + * + * ReturningExpr nodes never appear in a parsed Query --- they are only ever + * inserted by the rewriter and the planner. + */ +typedef struct ReturningExpr +{ + Expr xpr; + int retlevelsup; /* > 0 if it belongs to outer query */ + bool retold; /* true for OLD, false for NEW */ + Expr *retexpr; /* expression to be returned */ +} ReturningExpr; + /*-------------------- * TargetEntry - * a target entry (used in query target lists) diff --git a/src/include/nodes/print.h b/src/include/nodes/print.h index 333103a4051b0..cc304dae82c1c 100644 --- a/src/include/nodes/print.h +++ b/src/include/nodes/print.h @@ -4,7 +4,7 @@ * definitions for nodes/print.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/print.h diff --git a/src/include/nodes/queryjumble.h b/src/include/nodes/queryjumble.h index f1c55c8067f40..da7c7abed2e6a 100644 --- a/src/include/nodes/queryjumble.h +++ b/src/include/nodes/queryjumble.h @@ -3,7 +3,7 @@ * queryjumble.h * Query normalization and fingerprinting. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -23,6 +23,12 @@ typedef struct LocationLen { int location; /* start offset in query text */ int length; /* length in bytes, or -1 to ignore */ + + /* + * Indicates that this location represents the beginning or end of a run + * of squashed constants. + */ + bool squashed; } LocationLen; /* @@ -48,6 +54,18 @@ typedef struct JumbleState /* highest Param id we've seen, in order to start normalization correctly */ int highest_extern_param_id; + + /* + * Count of the number of NULL nodes seen since last appending a value. + * These are flushed out to the jumble buffer before subsequent appends + * and before performing the final jumble hash. + */ + unsigned int pending_nulls; + +#ifdef USE_ASSERT_CHECKING + /* The total number of bytes added to the jumble buffer */ + Size total_jumble_len; +#endif } JumbleState; /* Values for the compute_query_id GUC */ diff --git a/src/include/nodes/readfuncs.h b/src/include/nodes/readfuncs.h index 8466038ed0677..dd260c446042c 100644 --- a/src/include/nodes/readfuncs.h +++ b/src/include/nodes/readfuncs.h @@ -4,7 +4,7 @@ * header file for read.c and readfuncs.c. These functions are internal * to the stringToNode interface and should not be used by anyone else. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/readfuncs.h @@ -19,7 +19,7 @@ /* * variable in read.c that needs to be accessible to readfuncs.c */ -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED extern PGDLLIMPORT bool restore_location_fields; #endif diff --git a/src/include/nodes/replnodes.h b/src/include/nodes/replnodes.h index ed23333e9286a..87e938933ebf7 100644 --- a/src/include/nodes/replnodes.h +++ b/src/include/nodes/replnodes.h @@ -4,7 +4,7 @@ * definitions for replication grammar parse nodes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/replnodes.h diff --git a/src/include/nodes/subscripting.h b/src/include/nodes/subscripting.h index 597209ba42d0e..234e8ad80120c 100644 --- a/src/include/nodes/subscripting.h +++ b/src/include/nodes/subscripting.h @@ -3,7 +3,7 @@ * subscripting.h * API for generic type subscripting * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/subscripting.h diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h index 5f7bcde891c7b..9c047cc401bec 100644 --- a/src/include/nodes/supportnodes.h +++ b/src/include/nodes/supportnodes.h @@ -6,10 +6,10 @@ * 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. + * about the target function. The name is now something of a misnomer, + * since some of the call sites are in the executor not the planner, + * but "function support function" would be a confusing name so we + * stick with "planner support function". * * A support function must have the SQL signature * supportfn(internal) returns internal @@ -23,7 +23,7 @@ * allows for future extensions of the set of request cases. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/supportnodes.h @@ -343,4 +343,51 @@ typedef struct SupportRequestOptimizeWindowClause * optimizations are possible. */ } SupportRequestOptimizeWindowClause; +/* + * The ModifyInPlace request allows the support function to detect whether + * a call to its target function can be allowed to modify a read/write + * expanded object in-place. The context is that we are considering a + * PL/pgSQL (or similar PL) assignment of the form "x := f(x, ...)" where + * the variable x is of a type that can be represented as an expanded object + * (see utils/expandeddatum.h). If f() can usefully optimize by modifying + * the passed-in object in-place, then this request can be implemented to + * instruct PL/pgSQL to pass a read-write expanded pointer to the variable's + * value. (Note that there is no guarantee that later calls to f() will + * actually do so. If f() receives a read-only pointer, or a pointer to a + * non-expanded object, it must follow the usual convention of not modifying + * the pointed-to object.) There are two requirements that must be met + * to make this safe: + * 1. f() must guarantee that it will not have modified the object if it + * fails. Otherwise the variable's value might change unexpectedly. + * 2. If the other arguments to f() ("..." in the above example) contain + * references to x, f() must be able to cope with that; or if that's not + * safe, the support function must scan the other arguments to verify that + * there are no other references to x. An example of the concern here is + * that in "arr := array_append(arr, arr[1])", if the array element type + * is pass-by-reference then array_append would receive a second argument + * that points into the array object it intends to modify. array_append is + * coded to make that safe, but other functions might not be able to cope. + * + * "args" is a node tree list representing the function's arguments. + * One or more nodes within the node tree will be PARAM_EXTERN Params + * with ID "paramid", which represent the assignment target variable. + * (Note that such references are not necessarily at top level in the list, + * for example we might have "x := f(x, g(x))". Generally it's only safe + * to optimize a reference that is at top level, else we're making promises + * about the behavior of g() as well as f().) + * + * If modify-in-place is safe, the support function should return the + * address of the Param node that is to return a read-write pointer. + * (At most one of the references is allowed to do so.) Otherwise, + * return NULL. + */ +typedef struct SupportRequestModifyInPlace +{ + NodeTag type; + + Oid funcid; /* PG_PROC OID of the target function */ + List *args; /* Arguments to the function */ + int paramid; /* ID of Param(s) representing variable */ +} SupportRequestModifyInPlace; + #endif /* SUPPORTNODES_H */ diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h index 1945f0639bf15..99f795ceab526 100644 --- a/src/include/nodes/tidbitmap.h +++ b/src/include/nodes/tidbitmap.h @@ -13,7 +13,7 @@ * fact that a particular page needs to be visited. * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/nodes/tidbitmap.h * @@ -22,9 +22,17 @@ #ifndef TIDBITMAP_H #define TIDBITMAP_H +#include "access/htup_details.h" #include "storage/itemptr.h" #include "utils/dsa.h" +/* + * The maximum number of tuples per page is not large (typically 256 with + * 8K pages, or 1024 with 32K pages). So there's not much point in making + * the per-page bitmaps variable size. We just legislate that the size + * is this: + */ +#define TBM_MAX_TUPLES_PER_PAGE MaxHeapTuplesPerPage /* * Actual bitmap representation is private to tidbitmap.c. Callers can @@ -32,23 +40,48 @@ */ typedef struct TIDBitmap TIDBitmap; -/* Likewise, TBMIterator is private */ -typedef struct TBMIterator TBMIterator; +/* Likewise, TBMPrivateIterator is private */ +typedef struct TBMPrivateIterator TBMPrivateIterator; typedef struct TBMSharedIterator TBMSharedIterator; +/* + * Callers with both private and shared implementations can use this unified + * API. + */ +typedef struct TBMIterator +{ + bool shared; + union + { + TBMPrivateIterator *private_iterator; + TBMSharedIterator *shared_iterator; + } i; +} TBMIterator; + /* Result structure for tbm_iterate */ typedef struct TBMIterateResult { - BlockNumber blockno; /* page number containing tuples */ - int ntuples; /* -1 indicates lossy result */ - bool recheck; /* should the tuples be rechecked? */ - /* Note: recheck is always true if ntuples < 0 */ - OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; + BlockNumber blockno; /* block number containing tuples */ + + bool lossy; + + /* + * Whether or not the tuples should be rechecked. This is always true if + * the page is lossy but may also be true if the query requires recheck. + */ + bool recheck; + + /* + * Pointer to the page containing the bitmap for this block. It is a void * + * to avoid exposing the details of the tidbitmap PagetableEntry to API + * users. + */ + void *internal_page; } TBMIterateResult; /* function prototypes in nodes/tidbitmap.c */ -extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa); +extern TIDBitmap *tbm_create(Size maxbytes, dsa_area *dsa); extern void tbm_free(TIDBitmap *tbm); extern void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp); @@ -60,16 +93,36 @@ extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno); extern void tbm_union(TIDBitmap *a, const TIDBitmap *b); extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b); +extern int tbm_extract_page_tuple(TBMIterateResult *iteritem, + OffsetNumber *offsets, + uint32 max_offsets); + extern bool tbm_is_empty(const TIDBitmap *tbm); -extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm); +extern TBMPrivateIterator *tbm_begin_private_iterate(TIDBitmap *tbm); extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm); -extern TBMIterateResult *tbm_iterate(TBMIterator *iterator); -extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator); -extern void tbm_end_iterate(TBMIterator *iterator); +extern bool tbm_private_iterate(TBMPrivateIterator *iterator, TBMIterateResult *tbmres); +extern bool tbm_shared_iterate(TBMSharedIterator *iterator, TBMIterateResult *tbmres); +extern void tbm_end_private_iterate(TBMPrivateIterator *iterator); extern void tbm_end_shared_iterate(TBMSharedIterator *iterator); extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp); -extern long tbm_calculate_entries(double maxbytes); +extern int tbm_calculate_entries(Size maxbytes); + +extern TBMIterator tbm_begin_iterate(TIDBitmap *tbm, + dsa_area *dsa, dsa_pointer dsp); +extern void tbm_end_iterate(TBMIterator *iterator); + +extern bool tbm_iterate(TBMIterator *iterator, TBMIterateResult *tbmres); + +static inline bool +tbm_exhausted(TBMIterator *iterator) +{ + /* + * It doesn't matter if we check the private or shared iterator here. If + * tbm_end_iterate() was called, they will be NULL + */ + return !iterator->i.private_iterator; +} #endif /* TIDBITMAP_H */ diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h index 8072cfb33f9bb..3ee3b976b8f9b 100644 --- a/src/include/nodes/value.h +++ b/src/include/nodes/value.h @@ -4,7 +4,7 @@ * interface for value nodes * * - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/nodes/value.h * diff --git a/src/include/optimizer/appendinfo.h b/src/include/optimizer/appendinfo.h index cc12c9c743da8..d06f93b72667b 100644 --- a/src/include/optimizer/appendinfo.h +++ b/src/include/optimizer/appendinfo.h @@ -4,7 +4,7 @@ * Routines for mapping expressions between append rel parent(s) and * children * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/appendinfo.h diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 34b301e537f52..0dffec00ede93 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -4,7 +4,7 @@ * prototypes for clauses.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/clauses.h diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index 57861bfb44608..d397fe27dc1e1 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -4,7 +4,7 @@ * prototypes for costsize.c and clausesel.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/cost.h @@ -108,35 +108,42 @@ extern void cost_resultscan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info); extern void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm); extern void cost_sort(Path *path, PlannerInfo *root, - List *pathkeys, Cost input_cost, double tuples, int width, + List *pathkeys, int input_disabled_nodes, + Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples); extern void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples); extern void cost_append(AppendPath *apath); extern void cost_merge_append(Path *path, PlannerInfo *root, List *pathkeys, int n_streams, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples); extern void cost_material(Path *path, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width); extern void cost_agg(Path *path, PlannerInfo *root, AggStrategy aggstrategy, const AggClauseCosts *aggcosts, int numGroupCols, double numGroups, List *quals, + int disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, double input_width); extern void cost_windowagg(Path *path, PlannerInfo *root, List *windowFuncs, WindowClause *winclause, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples); extern void cost_group(Path *path, PlannerInfo *root, int numGroupCols, double numGroups, List *quals, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples); extern void initial_cost_nestloop(PlannerInfo *root, @@ -153,6 +160,7 @@ extern void initial_cost_mergejoin(PlannerInfo *root, List *mergeclauses, Path *outer_path, Path *inner_path, List *outersortkeys, List *innersortkeys, + int outer_presorted_keys, JoinPathExtraData *extra); extern void final_cost_mergejoin(PlannerInfo *root, MergePath *path, JoinCostWorkspace *workspace, @@ -171,6 +179,7 @@ extern void cost_gather(GatherPath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, double *rows); extern void cost_gather_merge(GatherMergePath *path, PlannerInfo *root, RelOptInfo *rel, ParamPathInfo *param_info, + int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double *rows); extern void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan); diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h index c52906d0916e1..9f8e0f337aad4 100644 --- a/src/include/optimizer/geqo.h +++ b/src/include/optimizer/geqo.h @@ -3,7 +3,7 @@ * geqo.h * prototypes for various files in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo.h diff --git a/src/include/optimizer/geqo_copy.h b/src/include/optimizer/geqo_copy.h index b204dad5d373b..10e639f3ba85c 100644 --- a/src/include/optimizer/geqo_copy.h +++ b/src/include/optimizer/geqo_copy.h @@ -3,7 +3,7 @@ * geqo_copy.h * prototypes for copy functions in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_copy.h diff --git a/src/include/optimizer/geqo_gene.h b/src/include/optimizer/geqo_gene.h index 49b31bae30f80..9b9bcaadb7eb2 100644 --- a/src/include/optimizer/geqo_gene.h +++ b/src/include/optimizer/geqo_gene.h @@ -3,7 +3,7 @@ * geqo_gene.h * genome representation in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_gene.h diff --git a/src/include/optimizer/geqo_misc.h b/src/include/optimizer/geqo_misc.h index 722399de30adf..233f7c104616f 100644 --- a/src/include/optimizer/geqo_misc.h +++ b/src/include/optimizer/geqo_misc.h @@ -3,7 +3,7 @@ * geqo_misc.h * prototypes for printout routines in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_misc.h diff --git a/src/include/optimizer/geqo_mutation.h b/src/include/optimizer/geqo_mutation.h index f6f2247c992c4..57c8c91bbcea5 100644 --- a/src/include/optimizer/geqo_mutation.h +++ b/src/include/optimizer/geqo_mutation.h @@ -3,7 +3,7 @@ * geqo_mutation.h * prototypes for mutation functions in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_mutation.h diff --git a/src/include/optimizer/geqo_pool.h b/src/include/optimizer/geqo_pool.h index b5e8055472457..a28324af467b5 100644 --- a/src/include/optimizer/geqo_pool.h +++ b/src/include/optimizer/geqo_pool.h @@ -3,7 +3,7 @@ * geqo_pool.h * pool representation in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_pool.h diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h index 236f5954c158a..8fe28e46843f2 100644 --- a/src/include/optimizer/geqo_random.h +++ b/src/include/optimizer/geqo_random.h @@ -3,7 +3,7 @@ * geqo_random.h * random number generator * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_random.h diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h index 5d38276efb4f8..af394a2246048 100644 --- a/src/include/optimizer/geqo_recombination.h +++ b/src/include/optimizer/geqo_recombination.h @@ -3,7 +3,7 @@ * geqo_recombination.h * prototypes for recombination in the genetic query optimizer * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_recombination.h diff --git a/src/include/optimizer/geqo_selection.h b/src/include/optimizer/geqo_selection.h index fb1dcecdca843..bfe3c2280d063 100644 --- a/src/include/optimizer/geqo_selection.h +++ b/src/include/optimizer/geqo_selection.h @@ -3,7 +3,7 @@ * geqo_selection.h * prototypes for selection routines in optimizer/geqo * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/geqo_selection.h diff --git a/src/include/optimizer/inherit.h b/src/include/optimizer/inherit.h index c36c11837874f..5f8df60b9dd9d 100644 --- a/src/include/optimizer/inherit.h +++ b/src/include/optimizer/inherit.h @@ -4,7 +4,7 @@ * prototypes for inherit.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/inherit.h diff --git a/src/include/optimizer/joininfo.h b/src/include/optimizer/joininfo.h index da48a6b6c3bd3..2aa52c741be70 100644 --- a/src/include/optimizer/joininfo.h +++ b/src/include/optimizer/joininfo.h @@ -4,7 +4,7 @@ * prototypes for joininfo.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/joininfo.h diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index 7b63c5cf718db..546828b54bd27 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -12,7 +12,7 @@ * example. For the most part, however, code outside the core planner * should not need to include any optimizer/ header except this one. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/optimizer.h @@ -111,6 +111,7 @@ typedef enum /* GUC parameters */ extern PGDLLIMPORT int debug_parallel_query; extern PGDLLIMPORT bool parallel_leader_participation; +extern PGDLLIMPORT bool enable_distinct_reordering; extern struct PlannedStmt *planner(Query *parse, const char *query_string, int cursorOptions, @@ -157,6 +158,11 @@ extern List *expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, struct HeapTupleData *func_tuple); +extern ScalarArrayOpExpr *make_SAOP_expr(Oid oper, Node *leftexpr, + Oid coltype, Oid arraycollid, + Oid inputcollid, List *exprs, + bool haveNonConst); + /* in util/predtest.c: */ extern bool predicate_implied_by(List *predicate_list, List *clause_list, @@ -191,6 +197,8 @@ extern SortGroupClause *get_sortgroupref_clause_noerr(Index sortref, * output list */ #define PVC_RECURSE_PLACEHOLDERS 0x0020 /* recurse into PlaceHolderVar * arguments */ +#define PVC_INCLUDE_CONVERTROWTYPES 0x0040 /* include ConvertRowtypeExprs in + * output list */ extern Bitmapset *pull_varnos(PlannerInfo *root, Node *node); extern Bitmapset *pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup); @@ -198,8 +206,10 @@ extern void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos); extern List *pull_vars_of_level(Node *node, int levelsup); extern bool contain_var_clause(Node *node); extern bool contain_vars_of_level(Node *node, int levelsup); +extern bool contain_vars_returning_old_or_new(Node *node); extern int locate_var_of_level(Node *node, int levelsup); extern List *pull_var_clause(Node *node, int flags); extern Node *flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node); +extern Node *flatten_group_exprs(PlannerInfo *root, Query *query, Node *node); #endif /* OPTIMIZER_H */ diff --git a/src/include/optimizer/orclauses.h b/src/include/optimizer/orclauses.h index 3ef275357556c..046b08aaedb7a 100644 --- a/src/include/optimizer/orclauses.h +++ b/src/include/optimizer/orclauses.h @@ -4,7 +4,7 @@ * prototypes for orclauses.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/orclauses.h diff --git a/src/include/optimizer/paramassign.h b/src/include/optimizer/paramassign.h index 4026b74fab459..59dcb1ff05399 100644 --- a/src/include/optimizer/paramassign.h +++ b/src/include/optimizer/paramassign.h @@ -3,7 +3,7 @@ * paramassign.h * Functions for assigning PARAM_EXEC slots during planning. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/paramassign.h @@ -22,6 +22,8 @@ extern Param *replace_outer_agg(PlannerInfo *root, Aggref *agg); extern Param *replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp); extern Param *replace_outer_merge_support(PlannerInfo *root, MergeSupportFunc *msf); +extern Param *replace_outer_returning(PlannerInfo *root, + ReturningExpr *rexpr); extern Param *replace_nestloop_param_var(PlannerInfo *root, Var *var); extern Param *replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv); diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 112e7c23d4e1a..60dcdb77e41be 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -4,7 +4,7 @@ * prototypes for pathnode.c, relnode.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/pathnode.h @@ -27,11 +27,12 @@ extern int compare_fractional_path_costs(Path *path1, Path *path2, double fraction); extern void set_cheapest(RelOptInfo *parent_rel); extern void add_path(RelOptInfo *parent_rel, Path *new_path); -extern bool add_path_precheck(RelOptInfo *parent_rel, +extern bool add_path_precheck(RelOptInfo *parent_rel, int disabled_nodes, Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer); extern void add_partial_path(RelOptInfo *parent_rel, Path *new_path); extern bool add_partial_path_precheck(RelOptInfo *parent_rel, + int disabled_nodes, Cost total_cost, List *pathkeys); extern Path *create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, @@ -124,7 +125,8 @@ extern Path *create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer); extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, @@ -132,7 +134,8 @@ extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, List *fdw_private); extern ForeignPath *create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Relids required_outer, Path *fdw_outerpath, @@ -140,7 +143,8 @@ extern ForeignPath *create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, List *fdw_private); extern ForeignPath *create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, PathTarget *target, - double rows, Cost startup_cost, Cost total_cost, + double rows, int disabled_nodes, + Cost startup_cost, Cost total_cost, List *pathkeys, Path *fdw_outerpath, List *fdw_restrictinfo, @@ -175,7 +179,8 @@ extern MergePath *create_mergejoin_path(PlannerInfo *root, Relids required_outer, List *mergeclauses, List *outersortkeys, - List *innersortkeys); + List *innersortkeys, + int outer_presorted_keys); extern HashPath *create_hashjoin_path(PlannerInfo *root, RelOptInfo *joinrel, @@ -256,12 +261,11 @@ extern WindowAggPath *create_windowagg_path(PlannerInfo *root, bool topwindow); extern SetOpPath *create_setop_path(PlannerInfo *root, RelOptInfo *rel, - Path *subpath, + Path *leftpath, + Path *rightpath, SetOpCmd cmd, SetOpStrategy strategy, - List *distinctList, - AttrNumber flagColIdx, - int firstFlag, + List *groupList, double numGroups, double outputRows); extern RecursiveUnionPath *create_recursiveunion_path(PlannerInfo *root, @@ -346,6 +350,7 @@ extern Bitmapset *get_param_path_clause_serials(Path *path); extern RelOptInfo *build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, - SpecialJoinInfo *sjinfo); + SpecialJoinInfo *sjinfo, + int nappinfos, AppendRelInfo **appinfos); #endif /* PATHNODE_H */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 5c029b6b620dd..a48c972179712 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -4,7 +4,7 @@ * prototypes for various files in optimizer/path * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/paths.h @@ -72,6 +72,9 @@ extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel); extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List *exprlist, List *oprlist); +extern bool relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel, + List *restrictlist, List *exprlist, + List *oprlist, List **extra_clauses); extern bool indexcol_is_bool_constant_for_query(PlannerInfo *root, IndexOptInfo *index, int indexcol); @@ -128,6 +131,7 @@ extern bool process_equivalence(PlannerInfo *root, extern Expr *canonicalize_ec_expression(Expr *expr, Oid req_type, Oid req_collation); extern void reconsider_outer_join_clauses(PlannerInfo *root); +extern void rebuild_eclass_attr_needed(PlannerInfo *root); extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root, Expr *expr, List *opfamilies, @@ -158,11 +162,13 @@ extern List *generate_join_implied_equalities_for_ecs(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel); -extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2); +extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, + Oid opfamily); extern EquivalenceClass *match_eclasses_to_foreign_key_col(PlannerInfo *root, ForeignKeyOptInfo *fkinfo, int colno); -extern RestrictInfo *find_derived_clause_for_ec_member(EquivalenceClass *ec, +extern RestrictInfo *find_derived_clause_for_ec_member(PlannerInfo *root, + EquivalenceClass *ec, EquivalenceMember *em); extern void add_child_rel_equivalences(PlannerInfo *root, AppendRelInfo *appinfo, @@ -177,6 +183,10 @@ extern void add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, List *child_tlist, List *setop_pathkeys); +extern void setup_eclass_member_iterator(EquivalenceMemberIterator *it, + EquivalenceClass *ec, + Relids child_relids); +extern EquivalenceMember *eclass_member_iterator_next(EquivalenceMemberIterator *it); extern List *generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, @@ -192,6 +202,7 @@ extern bool eclass_useful_for_merging(PlannerInfo *root, extern bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist); extern bool is_redundant_with_indexclauses(RestrictInfo *rinfo, List *indexclauses); +extern void ec_clear_derived_clauses(EquivalenceClass *ec); /* * pathkeys.c @@ -239,6 +250,7 @@ extern List *make_pathkeys_for_sortclauses_extended(PlannerInfo *root, List **sortclauses, List *tlist, bool remove_redundant, + bool remove_group_rtindex, bool *sortable, bool set_ec_sortref); extern void initialize_mergeclause_eclasses(PlannerInfo *root, @@ -264,7 +276,7 @@ extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel); extern List *append_pathkeys(List *target, List *source); extern PathKey *make_canonical_pathkey(PlannerInfo *root, EquivalenceClass *eclass, Oid opfamily, - int strategy, bool nulls_first); + CompareType cmptype, bool nulls_first); extern void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, List *live_childrels); diff --git a/src/include/optimizer/placeholder.h b/src/include/optimizer/placeholder.h index d8610863fc5ca..d351045e2e056 100644 --- a/src/include/optimizer/placeholder.h +++ b/src/include/optimizer/placeholder.h @@ -4,7 +4,7 @@ * prototypes for optimizer/util/placeholder.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/placeholder.h @@ -23,6 +23,7 @@ extern PlaceHolderInfo *find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv); extern void find_placeholders_in_jointree(PlannerInfo *root); extern void fix_placeholder_input_needed_levels(PlannerInfo *root); +extern void rebuild_placeholder_attr_needed(PlannerInfo *root); extern void add_placeholders_to_base_rels(PlannerInfo *root); extern void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h index f59b77b10125c..cd74e4b1e8b36 100644 --- a/src/include/optimizer/plancat.h +++ b/src/include/optimizer/plancat.h @@ -4,7 +4,7 @@ * prototypes for plancat.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/plancat.h diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index aafc173792151..9d3debcab2801 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -4,7 +4,7 @@ * prototypes for various files in optimizer/plan * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/planmain.h @@ -20,6 +20,7 @@ /* GUC parameters */ #define DEFAULT_CURSOR_TUPLE_FRACTION 0.1 extern PGDLLIMPORT double cursor_tuple_fraction; +extern PGDLLIMPORT bool enable_self_join_elimination; /* query_planner callback to compute query_pathkeys */ typedef void (*query_pathkeys_callback) (PlannerInfo *root, void *extra); @@ -72,7 +73,11 @@ extern void add_other_rels_to_query(PlannerInfo *root); extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist); extern void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed); +extern void add_vars_to_attr_needed(PlannerInfo *root, List *vars, + Relids where_needed); +extern void remove_useless_groupby_columns(PlannerInfo *root); extern void find_lateral_references(PlannerInfo *root); +extern void rebuild_lateral_attr_needed(PlannerInfo *root); extern void create_lateral_join_info(PlannerInfo *root); extern List *deconstruct_jointree(PlannerInfo *root); extern bool restriction_is_always_true(PlannerInfo *root, @@ -96,6 +101,7 @@ extern RestrictInfo *build_implied_join_equality(PlannerInfo *root, Expr *item2, Relids qualscope, Index security_level); +extern void rebuild_joinclause_attr_needed(PlannerInfo *root); extern void match_foreign_keys_to_quals(PlannerInfo *root); /* @@ -108,6 +114,11 @@ extern bool query_is_distinct_for(Query *query, List *colnos, List *opids); extern bool innerrel_is_unique(PlannerInfo *root, Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel, JoinType jointype, List *restrictlist, bool force_cache); +extern bool innerrel_is_unique_ext(PlannerInfo *root, Relids joinrelids, + Relids outerrelids, RelOptInfo *innerrel, + JoinType jointype, List *restrictlist, + bool force_cache, List **extra_clauses); +extern List *remove_useless_self_joins(PlannerInfo *root, List *joinlist); /* * prototypes for plan/setrefs.c diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index 5aeff21b967f0..347c582a78927 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -8,7 +8,7 @@ * non-planner code. Declarations here are meant for use by other * planner modules. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/planner.h diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h index a52dec285d569..df56202777c7f 100644 --- a/src/include/optimizer/prep.h +++ b/src/include/optimizer/prep.h @@ -4,7 +4,7 @@ * prototypes for files in optimizer/prep/ * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/prep.h @@ -25,6 +25,7 @@ extern void transform_MERGE_to_join(Query *parse); extern void replace_empty_jointree(Query *parse); extern void pull_up_sublinks(PlannerInfo *root); extern void preprocess_function_rtes(PlannerInfo *root); +extern Query *expand_virtual_generated_columns(PlannerInfo *root); extern void pull_up_subqueries(PlannerInfo *root); extern void flatten_simple_union_all(PlannerInfo *root); extern void reduce_outer_joins(PlannerInfo *root); @@ -53,6 +54,5 @@ extern void preprocess_aggrefs(PlannerInfo *root, Node *clause); * prototypes for prepunion.c */ extern RelOptInfo *plan_set_operations(PlannerInfo *root); -extern bool set_operation_ordered_results_useful(SetOperationStmt *setop); #endif /* PREP_H */ diff --git a/src/include/optimizer/restrictinfo.h b/src/include/optimizer/restrictinfo.h index 1b42c832c5923..ec91fc9c58308 100644 --- a/src/include/optimizer/restrictinfo.h +++ b/src/include/optimizer/restrictinfo.h @@ -4,7 +4,7 @@ * prototypes for restrictinfo.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/restrictinfo.h @@ -22,6 +22,17 @@ make_restrictinfo(root, clause, true, false, false, false, 0, \ NULL, NULL, NULL) +extern RestrictInfo *make_plain_restrictinfo(PlannerInfo *root, + Expr *clause, + Expr *orclause, + bool is_pushed_down, + bool has_clone, + bool is_clone, + bool pseudoconstant, + Index security_level, + Relids required_relids, + Relids incompatible_relids, + Relids outer_relids); extern RestrictInfo *make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, @@ -48,4 +59,35 @@ extern bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer); +/* + * clause_sides_match_join + * Determine whether a join clause is of the right form to use in this join. + * + * We already know that the clause is a binary opclause referencing only the + * rels in the current join. The point here is to check whether it has the + * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr", + * rather than mixing outer and inner vars on either side. If it matches, + * we set the transient flag outer_is_left to identify which side is which. + */ +static inline bool +clause_sides_match_join(RestrictInfo *rinfo, Relids outerrelids, + Relids innerrelids) +{ + if (bms_is_subset(rinfo->left_relids, outerrelids) && + bms_is_subset(rinfo->right_relids, innerrelids)) + { + /* lefthand side is outer */ + rinfo->outer_is_left = true; + return true; + } + else if (bms_is_subset(rinfo->left_relids, innerrelids) && + bms_is_subset(rinfo->right_relids, outerrelids)) + { + /* righthand side is outer */ + rinfo->outer_is_left = false; + return true; + } + return false; /* no good for these input relations */ +} + #endif /* RESTRICTINFO_H */ diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index c20bd9924b85b..48507eb4bcad3 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -3,7 +3,7 @@ * subselect.h * Planning routines for subselects. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/subselect.h @@ -17,6 +17,9 @@ #include "nodes/plannodes.h" extern void SS_process_ctes(PlannerInfo *root); +extern ScalarArrayOpExpr *convert_VALUES_to_ANY(PlannerInfo *root, + Node *testexpr, + Query *values); extern JoinExpr *convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, Relids available_rels); diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h index 15f8f4a4b0061..9c355bf11794c 100644 --- a/src/include/optimizer/tlist.h +++ b/src/include/optimizer/tlist.h @@ -4,7 +4,7 @@ * prototypes for tlist.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/optimizer/tlist.h diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index 28b66fccb4339..f29ed03b476ec 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -4,7 +4,7 @@ * parse analysis for optimizable statements * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/analyze.h @@ -44,13 +44,15 @@ extern List *transformInsertRow(ParseState *pstate, List *exprlist, bool strip_indirection); extern List *transformUpdateTargetList(ParseState *pstate, List *origTlist); -extern List *transformReturningList(ParseState *pstate, List *returningList, - ParseExprKind exprKind); +extern void transformReturningClause(ParseState *pstate, Query *qry, + ReturningClause *returningClause, + ParseExprKind exprKind); extern Query *transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree); extern Query *transformStmt(ParseState *pstate, Node *parseTree); extern bool stmt_requires_parse_analysis(RawStmt *parseTree); extern bool analyze_requires_snapshot(RawStmt *parseTree); +extern bool query_requires_rewrite_plan(Query *query); extern const char *LCS_asString(LockClauseStrength strength); extern void CheckSelectLocking(Query *qry, LockClauseStrength strength); diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index f7fe834cf4551..a4af3f717a111 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -7,7 +7,7 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -153,6 +153,7 @@ PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("end", END_P, RESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("enforced", ENFORCED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("error", ERROR_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD, BARE_LABEL) @@ -307,6 +308,7 @@ PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("objects", OBJECTS_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("of", OF, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD, AS_LABEL) @@ -335,10 +337,10 @@ PG_KEYWORD("parameter", PARAMETER, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD, BARE_LABEL) -PG_KEYWORD("partitions", PARTITIONS, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("path", PATH, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("period", PERIOD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("plan", PLAN, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD, BARE_LABEL) @@ -363,7 +365,6 @@ PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("read", READ, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("real", REAL, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD, BARE_LABEL) -PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("ref", REF_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD, BARE_LABEL) @@ -419,7 +420,6 @@ PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("some", SOME, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("source", SOURCE, UNRESERVED_KEYWORD, BARE_LABEL) -PG_KEYWORD("split", SPLIT, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("sql", SQL_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("stable", STABLE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("standalone", STANDALONE_P, UNRESERVED_KEYWORD, BARE_LABEL) @@ -492,6 +492,7 @@ PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("virtual", VIRTUAL, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("when", WHEN, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("where", WHERE, RESERVED_KEYWORD, AS_LABEL) diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index 4df9b37e6d966..277d45baf83c6 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -3,7 +3,7 @@ * parse_agg.h * handle aggregates and window functions in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_agg.h diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index e71762b10cff0..3e9894926de13 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -4,7 +4,7 @@ * handle clauses in parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_clause.h diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index 05afda1b14a84..8d775c72c5993 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -4,7 +4,7 @@ * Routines for type coercion. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_coerce.h @@ -63,6 +63,9 @@ extern Node *coerce_to_specific_type_typmod(ParseState *pstate, Node *node, Oid targetTypeId, int32 targetTypmod, const char *constructName); +extern Node *coerce_null_to_domain(Oid typid, int32 typmod, Oid collation, + int typlen, bool typbyval); + extern int parser_coercion_errposition(ParseState *pstate, int coerce_location, Node *input_expr); diff --git a/src/include/parser/parse_collate.h b/src/include/parser/parse_collate.h index af69d13f5c1d5..1be6750b685ae 100644 --- a/src/include/parser/parse_collate.h +++ b/src/include/parser/parse_collate.h @@ -4,7 +4,7 @@ * Routines for assigning collation information. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_collate.h diff --git a/src/include/parser/parse_cte.h b/src/include/parser/parse_cte.h index 96547d420b38b..28ed837584973 100644 --- a/src/include/parser/parse_cte.h +++ b/src/include/parser/parse_cte.h @@ -4,7 +4,7 @@ * handle CTEs (common table expressions) in parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_cte.h diff --git a/src/include/parser/parse_enr.h b/src/include/parser/parse_enr.h index 5e259e1e311e6..3fe2bd0a026f8 100644 --- a/src/include/parser/parse_enr.h +++ b/src/include/parser/parse_enr.h @@ -4,7 +4,7 @@ * Internal definitions for parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_enr.h diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h index 9b46dfd9ecc68..efbaff8e71045 100644 --- a/src/include/parser/parse_expr.h +++ b/src/include/parser/parse_expr.h @@ -3,7 +3,7 @@ * parse_expr.h * handle expressions in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_expr.h diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index c7ba99dee74aa..a6f24b83d8436 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_func.h diff --git a/src/include/parser/parse_merge.h b/src/include/parser/parse_merge.h index 3fad202ae60ec..2e0cf0c9ae07e 100644 --- a/src/include/parser/parse_merge.h +++ b/src/include/parser/parse_merge.h @@ -4,7 +4,7 @@ * handle MERGE statement in parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_merge.h diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 5b781d87a9d24..f7d07c8454253 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -4,7 +4,7 @@ * Internal definitions for parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_node.h @@ -151,6 +151,8 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param, * * p_target_nsitem: target relation's ParseNamespaceItem. * + * p_grouping_nsitem: the ParseNamespaceItem that represents the grouping step. + * * p_is_insert: true to process assignment expressions like INSERT, false * to process them like UPDATE. (Note this can change intra-statement, for * cases like INSERT ON CONFLICT UPDATE.) @@ -206,6 +208,7 @@ struct ParseState CommonTableExpr *p_parent_cte; /* this query's containing CTE */ Relation p_target_relation; /* INSERT/UPDATE/DELETE/MERGE target rel */ ParseNamespaceItem *p_target_nsitem; /* target rel's NSItem, or NULL */ + ParseNamespaceItem *p_grouping_nsitem; /* NSItem for grouping, or NULL */ bool p_is_insert; /* process assignment like INSERT not UPDATE */ List *p_windowdefs; /* raw representations of window clauses */ ParseExprKind p_expr_kind; /* what kind of expression we're parsing */ @@ -276,6 +279,11 @@ struct ParseState * of SQL:2008 requires us to do it this way. We also use p_lateral_ok to * forbid LATERAL references to an UPDATE/DELETE target table. * + * While processing the RETURNING clause, special namespace items are added to + * refer to the OLD and NEW state of the result relation. These namespace + * items have p_returning_type set appropriately, for use when creating Vars. + * For convenience, this information is duplicated on each namespace column. + * * At no time should a namespace list contain two entries that conflict * according to the rules in checkNameSpaceConflicts; but note that those * are more complicated than "must have different alias names", so in practice @@ -293,6 +301,7 @@ struct ParseNamespaceItem bool p_cols_visible; /* Column names visible as unqualified refs? */ bool p_lateral_only; /* Is only visible to LATERAL expressions? */ bool p_lateral_ok; /* If so, does join type allow use? */ + VarReturningType p_returning_type; /* Is OLD/NEW for use in RETURNING? */ }; /* @@ -323,6 +332,7 @@ struct ParseNamespaceColumn Oid p_vartype; /* pg_type OID */ int32 p_vartypmod; /* type modifier value */ Oid p_varcollid; /* OID of collation, or InvalidOid */ + VarReturningType p_varreturningtype; /* for RETURNING OLD/NEW */ Index p_varnosyn; /* rangetable index of syntactic referent */ AttrNumber p_varattnosyn; /* attribute number of syntactic referent */ bool p_dontexpand; /* not included in star expansion */ diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h index beffe144c9a71..0f27609f8ffaf 100644 --- a/src/include/parser/parse_oper.h +++ b/src/include/parser/parse_oper.h @@ -4,7 +4,7 @@ * handle operator things for parser * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_oper.h diff --git a/src/include/parser/parse_param.h b/src/include/parser/parse_param.h index 6459d4ab6f3ea..821f89606c35f 100644 --- a/src/include/parser/parse_param.h +++ b/src/include/parser/parse_param.h @@ -3,7 +3,7 @@ * parse_param.h * handle parameters in parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_param.h diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index bea2da549617a..d59599cf2424e 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -4,7 +4,7 @@ * prototypes for parse_relation.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_relation.h @@ -100,6 +100,8 @@ extern ParseNamespaceItem *addRangeTableEntryForCTE(ParseState *pstate, extern ParseNamespaceItem *addRangeTableEntryForENR(ParseState *pstate, RangeVar *rv, bool inFromCl); +extern ParseNamespaceItem *addRangeTableEntryForGroup(ParseState *pstate, + List *groupClauses); extern RTEPermissionInfo *addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte); extern RTEPermissionInfo *getRTEPermissionInfo(List *rteperminfos, @@ -108,10 +110,11 @@ extern bool isLockedRefname(ParseState *pstate, const char *refname); extern void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace); -extern void errorMissingRTE(ParseState *pstate, RangeVar *relation) pg_attribute_noreturn(); -extern void errorMissingColumn(ParseState *pstate, - const char *relname, const char *colname, int location) pg_attribute_noreturn(); +pg_noreturn extern void errorMissingRTE(ParseState *pstate, RangeVar *relation); +pg_noreturn extern void errorMissingColumn(ParseState *pstate, + const char *relname, const char *colname, int location); extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, + VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars); extern List *expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem, diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h index 3281f63494631..89357f31ad623 100644 --- a/src/include/parser/parse_target.h +++ b/src/include/parser/parse_target.h @@ -4,7 +4,7 @@ * handle target lists * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_target.h diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h index b62e7a6ce99a8..0d919d8bfa22c 100644 --- a/src/include/parser/parse_type.h +++ b/src/include/parser/parse_type.h @@ -3,7 +3,7 @@ * parse_type.h * handle type operations for parser * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_type.h diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 1406589477942..9f2b58de79741 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -4,7 +4,7 @@ * parse analysis for utility commands * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parse_utilcmd.h diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h index be184ec50667c..350196cd641e7 100644 --- a/src/include/parser/parser.h +++ b/src/include/parser/parser.h @@ -5,7 +5,7 @@ * * This is the external API for the raw lexing/parsing functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parser.h diff --git a/src/include/parser/parsetree.h b/src/include/parser/parsetree.h index 3d51cd1530f5d..17f5c9ce11468 100644 --- a/src/include/parser/parsetree.h +++ b/src/include/parser/parsetree.h @@ -5,7 +5,7 @@ * parse trees. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parsetree.h diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h index d6293b1e87872..8d202d5b2848a 100644 --- a/src/include/parser/scanner.h +++ b/src/include/parser/scanner.h @@ -8,7 +8,7 @@ * higher-level API provided by parser.h. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/scanner.h @@ -145,6 +145,6 @@ extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate, core_yyscan_t yyscanner, int location); extern void cancel_scanner_errposition_callback(ScannerCallbackState *scbstate); -extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner) pg_attribute_noreturn(); +pg_noreturn extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner); #endif /* SCANNER_H */ diff --git a/src/include/parser/scansup.h b/src/include/parser/scansup.h index 4b68ddc2d8dac..8f3a9f4c527bd 100644 --- a/src/include/parser/scansup.h +++ b/src/include/parser/scansup.h @@ -3,7 +3,7 @@ * scansup.h * scanner support routines used by the core lexer * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/scansup.h diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h index 9d2a26705f062..65f161f7188c4 100644 --- a/src/include/partitioning/partbounds.h +++ b/src/include/partitioning/partbounds.h @@ -2,7 +2,7 @@ * * partbounds.h * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/include/partitioning/partbounds.h * @@ -143,15 +143,4 @@ extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc, extern int partition_hash_bsearch(PartitionBoundInfo boundinfo, int modulus, int remainder); -extern void check_partitions_for_split(Relation parent, - Oid splitPartOid, - RangeVar *splitPartName, - List *partlist, - ParseState *pstate); -extern void calculate_partition_bound_for_merge(Relation parent, - List *partNames, - List *partOids, - PartitionBoundSpec *spec, - ParseState *pstate); - #endif /* PARTBOUNDS_H */ diff --git a/src/include/partitioning/partdefs.h b/src/include/partitioning/partdefs.h index fcfd18f2ba1aa..6deb24f1c0700 100644 --- a/src/include/partitioning/partdefs.h +++ b/src/include/partitioning/partdefs.h @@ -3,7 +3,7 @@ * partdefs.h * Base definitions for partitioned table handling * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/include/partitioning/partdefs.h * diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h index 87abfd76d7889..34533f7004c11 100644 --- a/src/include/partitioning/partdesc.h +++ b/src/include/partitioning/partdesc.h @@ -2,7 +2,7 @@ * * partdesc.h * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/partitioning/partdesc.h * @@ -72,4 +72,4 @@ extern void DestroyPartitionDirectory(PartitionDirectory pdir); extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc); -#endif /* PARTCACHE_H */ +#endif /* PARTDESC_H */ diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index bd490d154f355..c413734789a97 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -4,7 +4,7 @@ * prototypes for partprune.c * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/partitioning/partprune.h @@ -70,10 +70,10 @@ typedef struct PartitionPruneContext #define PruneCxtStateIdx(partnatts, step_id, keyno) \ ((partnatts) * (step_id) + (keyno)) -extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root, - struct RelOptInfo *parentrel, - List *subpaths, - List *prunequal); +extern int make_partition_pruneinfo(struct PlannerInfo *root, + struct RelOptInfo *parentrel, + List *subpaths, + List *prunequal); extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel); extern Bitmapset *get_matching_partitions(PartitionPruneContext *context, List *pruning_steps); diff --git a/src/include/pch/meson.build b/src/include/pch/meson.build index 942d4c9956f62..f6babee6f6d88 100644 --- a/src/include/pch/meson.build +++ b/src/include/pch/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # See https://github.com/mesonbuild/meson/issues/10338 pch_c_h = meson.source_root() / meson.current_source_dir() / 'c_pch.h' diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 3dea3856aaf06..726a7c1be1f4d 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -9,12 +9,12 @@ /* The normal alignment of `int', in bytes. */ #undef ALIGNOF_INT +/* The normal alignment of `int64_t', in bytes. */ +#undef ALIGNOF_INT64_T + /* The normal alignment of `long', in bytes. */ #undef ALIGNOF_LONG -/* The normal alignment of `long long int', in bytes. */ -#undef ALIGNOF_LONG_LONG_INT - /* The normal alignment of `PG_INT128_TYPE', in bytes. */ #undef ALIGNOF_PG_INT128_TYPE @@ -54,21 +54,12 @@ /* Define to 1 if you have the `append_history' function. */ #undef HAVE_APPEND_HISTORY -/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */ -#undef HAVE_ASN1_STRING_GET0_DATA - -/* Define to 1 if you want to use atomics if available. */ -#undef HAVE_ATOMICS - /* Define to 1 if you have the header file. */ #undef HAVE_ATOMIC_H /* Define to 1 if you have the `backtrace_symbols' function. */ #undef HAVE_BACKTRACE_SYMBOLS -/* Define to 1 if you have the `BIO_meth_new' function. */ -#undef HAVE_BIO_METH_NEW - /* Define to 1 if your compiler handles computed gotos. */ #undef HAVE_COMPUTED_GOTO @@ -84,9 +75,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CRTDEFS_H -/* Define to 1 if you have the `CRYPTO_lock' function. */ -#undef HAVE_CRYPTO_LOCK - /* Define to 1 if you have the declaration of `fdatasync', and to 0 if you don't. */ #undef HAVE_DECL_FDATASYNC @@ -103,6 +91,10 @@ `LLVMCreatePerfJITEventListener', and to 0 if you don't. */ #undef HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER +/* Define to 1 if you have the declaration of `memset_s', and to 0 if you + don't. */ +#undef HAVE_DECL_MEMSET_S + /* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you don't. */ #undef HAVE_DECL_POSIX_FADVISE @@ -115,6 +107,10 @@ don't. */ #undef HAVE_DECL_PWRITEV +/* Define to 1 if you have the declaration of `strchrnul', and to 0 if you + don't. */ +#undef HAVE_DECL_STRCHRNUL + /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #undef HAVE_DECL_STRLCAT @@ -131,12 +127,19 @@ */ #undef HAVE_DECL_STRSEP +/* Define to 1 if you have the declaration of `timingsafe_bcmp', and to 0 if + you don't. */ +#undef HAVE_DECL_TIMINGSAFE_BCMP + /* Define to 1 if you have the header file. */ #undef HAVE_EDITLINE_HISTORY_H /* Define to 1 if you have the header file. */ #undef HAVE_EDITLINE_READLINE_H +/* Define to 1 if you have the `elf_aux_info' function. */ +#undef HAVE_ELF_AUX_INFO + /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H @@ -162,10 +165,13 @@ /* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ #undef HAVE_GCC__SYNC_INT32_TAS -/* Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64). - */ +/* Define to 1 if you have __sync_val_compare_and_swap(int64_t *, int64_t, + int64_t). */ #undef HAVE_GCC__SYNC_INT64_CAS +/* Define to 1 if you have the `getauxval' function. */ +#undef HAVE_GETAUXVAL + /* Define to 1 if you have the `getifaddrs' function. */ #undef HAVE_GETIFADDRS @@ -202,12 +208,6 @@ /* Define to 1 if you have the `history_truncate_file' function. */ #undef HAVE_HISTORY_TRUNCATE_FILE -/* Define to 1 if you have the `HMAC_CTX_free' function. */ -#undef HAVE_HMAC_CTX_FREE - -/* Define to 1 if you have the `HMAC_CTX_new' function. */ -#undef HAVE_HMAC_CTX_NEW - /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H @@ -217,12 +217,6 @@ /* Define to 1 if you have the `inet_pton' function. */ #undef HAVE_INET_PTON -/* Define to 1 if the system has the type `int64'. */ -#undef HAVE_INT64 - -/* Define to 1 if the system has the type `int8'. */ -#undef HAVE_INT8 - /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -241,15 +235,15 @@ /* Define to 1 if you have the `kqueue' function. */ #undef HAVE_KQUEUE -/* Define to 1 if you have the header file. */ -#undef HAVE_LANGINFO_H - /* Define to 1 if you have the `ldap_initialize' function. */ #undef HAVE_LDAP_INITIALIZE /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO +/* Define to 1 if you have the `curl' library (-lcurl). */ +#undef HAVE_LIBCURL + /* Define to 1 if you have the `ldap' library (-lldap). */ #undef HAVE_LIBLDAP @@ -259,6 +253,9 @@ /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the `numa' library (-lnuma). */ +#undef HAVE_LIBNUMA + /* Define to 1 if you have the `pam' library (-lpam). */ #undef HAVE_LIBPAM @@ -286,11 +283,8 @@ /* Define to 1 if you have the `zstd' library (-lzstd). */ #undef HAVE_LIBZSTD -/* Define to 1 if `long int' works and is 64 bits. */ -#undef HAVE_LONG_INT_64 - -/* Define to 1 if `long long int' works and is 64 bits. */ -#undef HAVE_LONG_LONG_INT_64 +/* Define to 1 if you have the `localeconv_l' function. */ +#undef HAVE_LOCALECONV_L /* Define to 1 if you have the header file. */ #undef HAVE_MBARRIER_H @@ -301,15 +295,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define to 1 if you have the `memset_s' function. */ -#undef HAVE_MEMSET_S - /* Define to 1 if you have the `mkdtemp' function. */ #undef HAVE_MKDTEMP -/* Define to 1 if you have the `OPENSSL_init_ssl' function. */ -#undef HAVE_OPENSSL_INIT_SSL - /* Define to 1 if you have the header file. */ #undef HAVE_OSSP_UUID_H @@ -382,27 +370,24 @@ /* Define to 1 if the system has the type `socklen_t'. */ #undef HAVE_SOCKLEN_T -/* Define to 1 if you have spinlocks. */ -#undef HAVE_SPINLOCKS - /* Define to 1 if you have the `SSL_CTX_set_cert_cb' function. */ #undef HAVE_SSL_CTX_SET_CERT_CB +/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */ +#undef HAVE_SSL_CTX_SET_CIPHERSUITES + +/* Define to 1 if you have the `SSL_CTX_set_keylog_callback' function. */ +#undef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK + /* Define to 1 if you have the `SSL_CTX_set_num_tickets' function. */ #undef HAVE_SSL_CTX_SET_NUM_TICKETS -/* Define to 1 if stdbool.h conforms to C99. */ -#undef HAVE_STDBOOL_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the `strchrnul' function. */ -#undef HAVE_STRCHRNUL - /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R @@ -475,18 +460,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H +/* Define to 1 if curl_global_init() is guaranteed to be thread-safe. */ +#undef HAVE_THREADSAFE_CURL_GLOBAL_INIT + +/* Define to 1 if you have the `timingsafe_bcmp' function. */ +#undef HAVE_TIMINGSAFE_BCMP + /* Define to 1 if your compiler understands `typeof' or something similar. */ #undef HAVE_TYPEOF /* Define to 1 if you have the header file. */ #undef HAVE_UCRED_H -/* Define to 1 if the system has the type `uint64'. */ -#undef HAVE_UINT64 - -/* Define to 1 if the system has the type `uint8'. */ -#undef HAVE_UINT8 - /* Define to 1 if the system has the type `union semun'. */ #undef HAVE_UNION_SEMUN @@ -523,12 +508,12 @@ /* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */ #undef HAVE_X86_64_POPCNTQ +/* Define to 1 if you have the header file. */ +#undef HAVE_XLOCALE_H + /* Define to 1 if you have XSAVE intrinsics. */ #undef HAVE_XSAVE_INTRINSICS -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - /* Define to 1 if your compiler understands __builtin_bswap16. */ #undef HAVE__BUILTIN_BSWAP16 @@ -562,9 +547,6 @@ /* Define to 1 if your compiler understands __builtin_unreachable. */ #undef HAVE__BUILTIN_UNREACHABLE -/* Define to 1 if you have the `_configthreadlocale' function. */ -#undef HAVE__CONFIGTHREADLOCALE - /* Define to 1 if you have __cpuid. */ #undef HAVE__CPUID @@ -580,12 +562,6 @@ /* Define to 1 if your compiler understands _Static_assert. */ #undef HAVE__STATIC_ASSERT -/* Define to the appropriate printf length modifier for 64-bit ints. */ -#undef INT64_MODIFIER - -/* Define to 1 if `locale_t' requires . */ -#undef LOCALE_T_IN_XLOCALE - /* Define as the maximum alignment requirement of any C data type. */ #undef MAXIMUM_ALIGNOF @@ -617,9 +593,6 @@ /* Define to the name of a signed 128-bit integer type. */ #undef PG_INT128_TYPE -/* Define to the name of a signed 64-bit integer type. */ -#undef PG_INT64_TYPE - /* Define to the name of the default PostgreSQL service principal in Kerberos (GSSAPI). (--with-krb-srvnam=NAME) */ #undef PG_KRB_SRVNAM @@ -636,9 +609,6 @@ /* Define to best printf format archetype, usually gnu_printf if available. */ #undef PG_PRINTF_ATTRIBUTE -/* Define to 1 to use to define type bool. */ -#undef PG_USE_STDBOOL - /* PostgreSQL version as a string */ #undef PG_VERSION @@ -669,12 +639,12 @@ RELSEG_SIZE requires an initdb. */ #undef RELSEG_SIZE -/* The size of `bool', as computed by sizeof. */ -#undef SIZEOF_BOOL - /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T @@ -699,6 +669,9 @@ /* Define to 1 to build with assertion checks. (--enable-cassert) */ #undef USE_ASSERT_CHECKING +/* Define to 1 to use AVX-512 CRC algorithms with a runtime check. */ +#undef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK + /* Define to 1 to use AVX-512 popcount instructions with a runtime check. */ #undef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK @@ -717,6 +690,15 @@ /* Define to 1 to build with LDAP support. (--with-ldap) */ #undef USE_LDAP +/* Define to 1 to build with libcurl support. (--with-libcurl) */ +#undef USE_LIBCURL + +/* Define to build with NUMA support. (--with-libnuma) */ +#undef USE_LIBNUMA + +/* Define to build with io_uring support. (--with-liburing) */ +#undef USE_LIBURING + /* Define to 1 to build with XML support. (--with-libxml) */ #undef USE_LIBXML @@ -751,6 +733,9 @@ /* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */ #undef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK +/* Define to 1 to use SVE popcount instructions with a runtime check. */ +#undef USE_SVE_POPCNT_WITH_RUNTIME_CHECK + /* Define to build with systemd support. (--with-systemd) */ #undef USE_SYSTEMD @@ -772,9 +757,6 @@ /* Define to 1 to build with ZSTD support. (--with-zstd) */ #undef USE_ZSTD -/* Define to 1 if `wcstombs_l' requires . */ -#undef WCSTOMBS_L_IN_XLOCALE - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in deleted file mode 100644 index 8acadbdafd4d6..0000000000000 --- a/src/include/pg_config_ext.h.in +++ /dev/null @@ -1,7 +0,0 @@ -/* - * src/include/pg_config_ext.h.in. This is generated manually, not by - * autoheader, since we want to limit which symbols get defined here. - */ - -/* Define to the name of a signed 64-bit integer type. */ -#undef PG_INT64_TYPE diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson deleted file mode 100644 index 57cdfca0cfd4a..0000000000000 --- a/src/include/pg_config_ext.h.meson +++ /dev/null @@ -1,7 +0,0 @@ -/* - * src/include/pg_config_ext.h.in. This is generated manually, not by - * autoheader, since we want to limit which symbols get defined here. - */ - -/* Define to the name of a signed 64-bit integer type. */ -#mesondefine PG_INT64_TYPE diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index f941ee2faf86b..125d3eb5fff5e 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -6,7 +6,7 @@ * for developers. If you edit any of these, be sure to do a *full* * rebuild (and an initdb if noted). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/pg_config_manual.h @@ -86,21 +86,6 @@ #define USE_FLOAT8_BYVAL 1 #endif -/* - * When we don't have native spinlocks, we use semaphores to simulate them. - * Decreasing this value reduces consumption of OS resources; increasing it - * may improve performance, but supplying a real spinlock implementation is - * probably far better. - */ -#define NUM_SPINLOCK_SEMAPHORES 128 - -/* - * When we have neither spinlocks nor atomic operations support we're - * implementing atomic operations on top of spinlock on top of semaphores. To - * be safe against atomic operations while holding a spinlock separate - * semaphores have to be used. - */ -#define NUM_ATOMICS_SEMAPHORES 64 /* * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence, @@ -154,9 +139,8 @@ /* * USE_PREFETCH code should be compiled only if we have a way to implement * prefetching. (This is decoupled from USE_POSIX_FADVISE because there - * might in future be support for alternative low-level prefetch APIs. - * If you change this, you probably need to adjust the error message in - * check_effective_io_concurrency.) + * might in future be support for alternative low-level prefetch APIs, + * as well as platform-specific APIs defined elsewhere.) */ #ifdef USE_POSIX_FADVISE #define USE_PREFETCH @@ -298,10 +282,10 @@ /* * For cache-invalidation debugging, define DISCARD_CACHES_ENABLED to enable - * use of the debug_discard_caches GUC to aggressively flush syscache/relcache - * entries whenever it's possible to deliver invalidations. See - * AcceptInvalidationMessages() in src/backend/utils/cache/inval.c for - * details. + * use of the debug_discard_caches GUC to aggressively flush + * syscache/relcache/relsynccache entries whenever it's possible to deliver + * invalidations. See AcceptInvalidationMessages() in + * src/backend/utils/cache/inval.c for details. * * USE_ASSERT_CHECKING builds default to enabling this. It's possible to use * DISCARD_CACHES_ENABLED without a cassert build and the implied @@ -336,31 +320,31 @@ /* #define RECOVER_RELATION_BUILD_MEMORY 1 */ /* Force enable */ /* - * Define this to force all parse and plan trees to be passed through - * copyObject(), to facilitate catching errors and omissions in - * copyObject(). + * Define DEBUG_NODE_TESTS_ENABLED to enable use of the GUCs + * debug_copy_parse_plan_trees, debug_write_read_parse_plan_trees, and + * debug_raw_expression_coverage_test, to test coverage of node support + * functions in src/backend/nodes/. + * + * USE_ASSERT_CHECKING builds default to enabling this. */ -/* #define COPY_PARSE_PLAN_TREES */ +/* #define DEBUG_NODE_TESTS_ENABLED */ -/* - * Define this to force Bitmapset reallocation on each modification. Helps - * to find dangling pointers to Bitmapset's. - */ -/* #define REALLOCATE_BITMAPSETS */ +#if defined(USE_ASSERT_CHECKING) && !defined(DEBUG_NODE_TESTS_ENABLED) +#define DEBUG_NODE_TESTS_ENABLED +#endif /* - * Define this to force all parse and plan trees to be passed through - * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in - * those modules. + * Backwards compatibility for the older compile-time-only node-tests macros. */ -/* #define WRITE_READ_PARSE_PLAN_TREES */ +#if !defined(DEBUG_NODE_TESTS_ENABLED) && (defined(COPY_PARSE_PLAN_TREES) || defined(WRITE_READ_PARSE_PLAN_TREES) || defined(RAW_EXPRESSION_COVERAGE_TEST)) +#define DEBUG_NODE_TESTS_ENABLED +#endif /* - * Define this to force all raw parse trees for DML statements to be scanned - * by raw_expression_tree_walker(), to facilitate catching errors and - * omissions in that function. + * Define this to force Bitmapset reallocation on each modification. Helps + * to find dangling pointers to Bitmapset's. */ -/* #define RAW_EXPRESSION_COVERAGE_TEST */ +/* #define REALLOCATE_BITMAPSETS */ /* * Enable debugging print statements for lock-related operations. @@ -373,12 +357,6 @@ */ /* #define WAL_DEBUG */ -/* - * Enable tracing of resource consumption during sort operations; - * see also the trace_sort GUC var. For 8.1 this is enabled by default. - */ -#define TRACE_SORT 1 - /* * Enable tracing of syncscan operations (see also the trace_syncscan GUC var). */ diff --git a/src/include/pg_getopt.h b/src/include/pg_getopt.h index c87ea20b14f0e..aad0886c054d2 100644 --- a/src/include/pg_getopt.h +++ b/src/include/pg_getopt.h @@ -11,19 +11,20 @@ * Portions Copyright (c) 1987, 1993, 1994 * The Regents of the University of California. All rights reserved. * - * Portions Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/pg_getopt.h */ +/* IWYU pragma: always_keep */ #ifndef PG_GETOPT_H #define PG_GETOPT_H /* POSIX says getopt() is provided by unistd.h */ -#include +#include /* IWYU pragma: export */ /* rely on the system's getopt.h if present */ #ifdef HAVE_GETOPT_H -#include +#include /* IWYU pragma: export */ #endif /* diff --git a/src/include/pg_trace.h b/src/include/pg_trace.h index bae819ab4669d..c82f34726f74e 100644 --- a/src/include/pg_trace.h +++ b/src/include/pg_trace.h @@ -3,7 +3,7 @@ * * Definitions for the PostgreSQL tracing framework * - * Copyright (c) 2006-2024, PostgreSQL Global Development Group + * Copyright (c) 2006-2025, PostgreSQL Global Development Group * * src/include/pg_trace.h * ---------- @@ -12,6 +12,6 @@ #ifndef PG_TRACE_H #define PG_TRACE_H -#include "utils/probes.h" /* pgrminclude ignore */ +#include "utils/probes.h" /* IWYU pragma: export */ #endif /* PG_TRACE_H */ diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 6b99bb8aadfca..378f2f2c2ba24 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -3,7 +3,7 @@ * * Definitions for the PostgreSQL cumulative statistics system. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/pgstat.h * ---------- @@ -14,10 +14,12 @@ #include "datatype/timestamp.h" #include "portability/instr_time.h" #include "postmaster/pgarch.h" /* for MAX_XFN_CHARS */ -#include "utils/backend_progress.h" /* for backward compatibility */ -#include "utils/backend_status.h" /* for backward compatibility */ +#include "replication/conflict.h" +#include "utils/backend_progress.h" /* for backward compatibility */ /* IWYU pragma: export */ +#include "utils/backend_status.h" /* for backward compatibility */ /* IWYU pragma: export */ +#include "utils/pgstat_kind.h" #include "utils/relcache.h" -#include "utils/wait_event.h" /* for backward compatibility */ +#include "utils/wait_event.h" /* for backward compatibility */ /* IWYU pragma: export */ /* ---------- @@ -31,32 +33,6 @@ /* Default directory to store temporary statistics data in */ #define PG_STAT_TMP_DIR "pg_stat_tmp" -/* The types of statistics entries */ -typedef enum PgStat_Kind -{ - /* use 0 for INVALID, to catch zero-initialized data */ - PGSTAT_KIND_INVALID = 0, - - /* stats for variable-numbered objects */ - PGSTAT_KIND_DATABASE, /* database-wide statistics */ - PGSTAT_KIND_RELATION, /* per-table statistics */ - PGSTAT_KIND_FUNCTION, /* per-function statistics */ - PGSTAT_KIND_REPLSLOT, /* per-slot statistics */ - PGSTAT_KIND_SUBSCRIPTION, /* per-subscription statistics */ - - /* stats for fixed-numbered objects */ - PGSTAT_KIND_ARCHIVER, - PGSTAT_KIND_BGWRITER, - PGSTAT_KIND_CHECKPOINTER, - PGSTAT_KIND_IO, - PGSTAT_KIND_SLRU, - PGSTAT_KIND_WAL, -} PgStat_Kind; - -#define PGSTAT_KIND_FIRST_VALID PGSTAT_KIND_DATABASE -#define PGSTAT_KIND_LAST PGSTAT_KIND_WAL -#define PGSTAT_NUM_KINDS (PGSTAT_KIND_LAST + 1) - /* Values for track_functions GUC variable --- order is significant! */ typedef enum TrackFunctionsLevel { @@ -97,9 +73,6 @@ typedef int64 PgStat_Counter; /* ---------- * PgStat_FunctionCounts The actual per-function counts kept by a backend * - * This struct should contain only actual event counters, because we memcmp - * it against zeroes to detect whether there are any pending stats. - * * Note that the time counters are in instr_time format here. We convert to * microseconds in PgStat_Counter format when flushing out pending statistics. * ---------- @@ -135,13 +108,16 @@ typedef struct PgStat_BackendSubEntry { PgStat_Counter apply_error_count; PgStat_Counter sync_error_count; + PgStat_Counter conflict_count[CONFLICT_NUM_TYPES]; } PgStat_BackendSubEntry; /* ---------- * PgStat_TableCounts The actual per-table counts kept by a backend * - * This struct should contain only actual event counters, because we memcmp - * it against zeroes to detect whether there are any stats updates to apply. + * This struct should contain only actual event counters, because we make use + * of pg_memory_is_all_zeros() to detect whether there are any stats updates + * to apply. + * * It is a component of PgStat_TableStatus (within-backend state). * * Note: for a table, tuples_returned is the number of tuples successfully @@ -235,7 +211,7 @@ typedef struct PgStat_TableXactStatus * ------------------------------------------------------------ */ -#define PGSTAT_FILE_FORMAT_ID 0x01A5BCAD +#define PGSTAT_FILE_FORMAT_ID 0x01A5BCB7 typedef struct PgStat_ArchiverStats { @@ -250,6 +226,14 @@ typedef struct PgStat_ArchiverStats TimestampTz stat_reset_timestamp; } PgStat_ArchiverStats; +/* --------- + * PgStat_BgWriterStats Background Writer statistics + * + * This struct should contain only actual event counters, because we make use + * of pg_memory_is_all_zeros() to detect whether there are any stats updates + * to apply. + * --------- + */ typedef struct PgStat_BgWriterStats { PgStat_Counter buf_written_clean; @@ -258,16 +242,26 @@ typedef struct PgStat_BgWriterStats TimestampTz stat_reset_timestamp; } PgStat_BgWriterStats; +/* -------- + * PgStat_CheckpointerStats Checkpoint statistics + * + * This struct should contain only actual event counters, because we make use + * of pg_memory_is_all_zeros() to detect whether there are any stats updates to + * apply. + * --------- + */ typedef struct PgStat_CheckpointerStats { PgStat_Counter num_timed; PgStat_Counter num_requested; + PgStat_Counter num_performed; PgStat_Counter restartpoints_timed; PgStat_Counter restartpoints_requested; PgStat_Counter restartpoints_performed; PgStat_Counter write_time; /* times in milliseconds */ PgStat_Counter sync_time; PgStat_Counter buffers_written; + PgStat_Counter slru_written; TimestampTz stat_reset_timestamp; } PgStat_CheckpointerStats; @@ -279,47 +273,72 @@ typedef enum IOObject { IOOBJECT_RELATION, IOOBJECT_TEMP_RELATION, + IOOBJECT_WAL, } IOObject; -#define IOOBJECT_NUM_TYPES (IOOBJECT_TEMP_RELATION + 1) +#define IOOBJECT_NUM_TYPES (IOOBJECT_WAL + 1) typedef enum IOContext { IOCONTEXT_BULKREAD, IOCONTEXT_BULKWRITE, + IOCONTEXT_INIT, IOCONTEXT_NORMAL, IOCONTEXT_VACUUM, } IOContext; #define IOCONTEXT_NUM_TYPES (IOCONTEXT_VACUUM + 1) +/* + * Enumeration of IO operations. + * + * This enum categorizes IO operations into two groups, depending on if + * byte operations are supported. + * + * Ensure IOOP_EXTEND is the first and IOOP_WRITE is the last ones in the + * tracked in bytes group and that the groups stay in that order. + */ typedef enum IOOp { + /* IOs not tracked in bytes */ IOOP_EVICT, - IOOP_EXTEND, IOOP_FSYNC, IOOP_HIT, - IOOP_READ, IOOP_REUSE, - IOOP_WRITE, IOOP_WRITEBACK, + + /* IOs tracked in bytes */ + IOOP_EXTEND, + IOOP_READ, + IOOP_WRITE, } IOOp; -#define IOOP_NUM_TYPES (IOOP_WRITEBACK + 1) +#define IOOP_NUM_TYPES (IOOP_WRITE + 1) + +#define pgstat_is_ioop_tracked_in_bytes(io_op) \ + (((unsigned int) (io_op)) < IOOP_NUM_TYPES && \ + ((unsigned int) (io_op)) >= IOOP_EXTEND) typedef struct PgStat_BktypeIO { + uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; PgStat_Counter times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; } PgStat_BktypeIO; +typedef struct PgStat_PendingIO +{ + uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; + PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; + instr_time pending_times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]; +} PgStat_PendingIO; + typedef struct PgStat_IO { TimestampTz stat_reset_timestamp; PgStat_BktypeIO stats[BACKEND_NUM_TYPES]; } PgStat_IO; - typedef struct PgStat_StatDBEntry { PgStat_Counter xact_commit; @@ -352,6 +371,8 @@ typedef struct PgStat_StatDBEntry PgStat_Counter sessions_abandoned; PgStat_Counter sessions_fatal; PgStat_Counter sessions_killed; + PgStat_Counter parallel_workers_to_launch; + PgStat_Counter parallel_workers_launched; TimestampTz stat_reset_timestamp; } PgStat_StatDBEntry; @@ -393,6 +414,7 @@ typedef struct PgStat_StatSubEntry { PgStat_Counter apply_error_count; PgStat_Counter sync_error_count; + PgStat_Counter conflict_count[CONFLICT_NUM_TYPES]; TimestampTz stat_reset_timestamp; } PgStat_StatSubEntry; @@ -426,36 +448,61 @@ typedef struct PgStat_StatTabEntry PgStat_Counter analyze_count; TimestampTz last_autoanalyze_time; /* autovacuum initiated */ PgStat_Counter autoanalyze_count; + + PgStat_Counter total_vacuum_time; /* times in milliseconds */ + PgStat_Counter total_autovacuum_time; + PgStat_Counter total_analyze_time; + PgStat_Counter total_autoanalyze_time; } PgStat_StatTabEntry; -typedef struct PgStat_WalStats +/* ------ + * PgStat_WalCounters WAL activity data gathered from WalUsage + * + * This stores all the counters and data gathered from WalUsage for WAL + * activity statistics, separated into its own structure so as this can be + * shared across multiple Stats structures. + * ------ + */ +typedef struct PgStat_WalCounters { PgStat_Counter wal_records; PgStat_Counter wal_fpi; uint64 wal_bytes; PgStat_Counter wal_buffers_full; - PgStat_Counter wal_write; - PgStat_Counter wal_sync; - PgStat_Counter wal_write_time; - PgStat_Counter wal_sync_time; +} PgStat_WalCounters; + +/* ------- + * PgStat_WalStats WAL statistics + * ------- + */ +typedef struct PgStat_WalStats +{ + PgStat_WalCounters wal_counters; TimestampTz stat_reset_timestamp; } PgStat_WalStats; -/* - * This struct stores wal-related durations as instr_time, which makes it - * cheaper and easier to accumulate them, by not requiring type - * conversions. During stats flush instr_time will be converted into - * microseconds. +/* ------- + * PgStat_Backend Backend statistics + * ------- */ -typedef struct PgStat_PendingWalStats +typedef struct PgStat_Backend { - PgStat_Counter wal_buffers_full; - PgStat_Counter wal_write; - PgStat_Counter wal_sync; - instr_time wal_write_time; - instr_time wal_sync_time; -} PgStat_PendingWalStats; + TimestampTz stat_reset_timestamp; + PgStat_BktypeIO io_stats; + PgStat_WalCounters wal_counters; +} PgStat_Backend; +/* --------- + * PgStat_BackendPending Non-flushed backend stats. + * --------- + */ +typedef struct PgStat_BackendPending +{ + /* + * Backend statistics store the same amount of IO data as PGSTAT_KIND_IO. + */ + PgStat_PendingIO pending_io; +} PgStat_BackendPending; /* * Functions in pgstat.c @@ -478,7 +525,7 @@ extern long pgstat_report_stat(bool force); extern void pgstat_force_next_flush(void); extern void pgstat_reset_counters(void); -extern void pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid); +extern void pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid); extern void pgstat_reset_of_kind(PgStat_Kind kind); /* stats accessors */ @@ -487,7 +534,7 @@ extern TimestampTz pgstat_get_stat_snapshot_timestamp(bool *have_snapshot); /* helpers */ extern PgStat_Kind pgstat_get_kind_from_str(char *kind_str); -extern bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid); +extern bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, uint64 objid); /* @@ -497,6 +544,24 @@ extern bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid); extern void pgstat_report_archiver(const char *xlog, bool failed); extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); +/* + * Functions in pgstat_backend.c + */ + +/* used by pgstat_io.c for I/O stats tracked in backends */ +extern void pgstat_count_backend_io_op_time(IOObject io_object, + IOContext io_context, + IOOp io_op, + instr_time io_time); +extern void pgstat_count_backend_io_op(IOObject io_object, + IOContext io_context, + IOOp io_op, uint32 cnt, + uint64 bytes); +extern PgStat_Backend *pgstat_fetch_stat_backend(ProcNumber procNumber); +extern PgStat_Backend *pgstat_fetch_stat_backend_by_pid(int pid, + BackendType *bktype); +extern bool pgstat_tracks_backend_bktype(BackendType bktype); +extern void pgstat_create_backend(ProcNumber procnum); /* * Functions in pgstat_bgwriter.c @@ -520,11 +585,12 @@ extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void); extern bool pgstat_bktype_io_stats_valid(PgStat_BktypeIO *backend_io, BackendType bktype); -extern void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op); -extern void pgstat_count_io_op_n(IOObject io_object, IOContext io_context, IOOp io_op, uint32 cnt); +extern void pgstat_count_io_op(IOObject io_object, IOContext io_context, + IOOp io_op, uint32 cnt, uint64 bytes); extern instr_time pgstat_prepare_io_time(bool track_io_guc); extern void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, - IOOp io_op, instr_time start_time, uint32 cnt); + IOOp io_op, instr_time start_time, + uint32 cnt, uint64 bytes); extern PgStat_IO *pgstat_fetch_stat_io(void); extern const char *pgstat_get_io_context_name(IOContext io_context); @@ -545,9 +611,11 @@ extern void pgstat_drop_database(Oid databaseid); extern void pgstat_report_autovac(Oid dboid); extern void pgstat_report_recovery_conflict(int reason); extern void pgstat_report_deadlock(void); +extern void pgstat_prepare_report_checksum_failure(Oid dboid); extern void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount); -extern void pgstat_report_checksum_failure(void); extern void pgstat_report_connect(Oid dboid); +extern void pgstat_update_parallel_workers_stats(PgStat_Counter workers_to_launch, + PgStat_Counter workers_launched); #define pgstat_count_buffer_read_time(n) \ (pgStatBlockReadTime += (n)) @@ -591,10 +659,11 @@ extern void pgstat_assoc_relation(Relation rel); extern void pgstat_unlink_relation(Relation rel); extern void pgstat_report_vacuum(Oid tableoid, bool shared, - PgStat_Counter livetuples, PgStat_Counter deadtuples); + PgStat_Counter livetuples, PgStat_Counter deadtuples, + TimestampTz starttime); extern void pgstat_report_analyze(Relation rel, PgStat_Counter livetuples, PgStat_Counter deadtuples, - bool resetcounter); + bool resetcounter, TimestampTz starttime); /* * If stats are enabled, but pending data hasn't been prepared yet, call @@ -695,6 +764,7 @@ extern PgStat_SLRUStats *pgstat_fetch_slru(void); */ extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error); +extern void pgstat_report_subscription_conflict(Oid subid, ConflictType type); extern void pgstat_create_subscription(Oid subid); extern void pgstat_drop_subscription(Oid subid); extern PgStat_StatSubEntry *pgstat_fetch_stat_subscription(Oid subid); @@ -768,13 +838,4 @@ extern PGDLLIMPORT PgStat_Counter pgStatTransactionIdleTime; /* updated by the traffic cop and in errfinish() */ extern PGDLLIMPORT SessionEndType pgStatSessionEndCause; - -/* - * Variables in pgstat_wal.c - */ - -/* updated directly by backends and background processes */ -extern PGDLLIMPORT PgStat_PendingWalStats PendingWalStats; - - #endif /* PGSTAT_H */ diff --git a/src/include/pgtar.h b/src/include/pgtar.h index b1ca71a673474..b2677578a3d1d 100644 --- a/src/include/pgtar.h +++ b/src/include/pgtar.h @@ -4,7 +4,7 @@ * Functions for manipulating tarfile datastructures (src/port/tar.c) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/pgtar.h diff --git a/src/include/pgtime.h b/src/include/pgtime.h index 27420867110cb..5fc9f223de30a 100644 --- a/src/include/pgtime.h +++ b/src/include/pgtime.h @@ -3,7 +3,7 @@ * pgtime.h * PostgreSQL internal timezone library * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/pgtime.h @@ -69,6 +69,13 @@ extern bool pg_interpret_timezone_abbrev(const char *abbrev, long int *gmtoff, int *isdst, const pg_tz *tz); +extern bool pg_timezone_abbrev_is_known(const char *abbrev, + bool *isfixed, + long int *gmtoff, + int *isdst, + const pg_tz *tz); +extern const char *pg_get_next_timezone_abbrev(int *indx, + const pg_tz *tz); extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff); extern const char *pg_get_timezone_name(pg_tz *tz); extern bool pg_tz_acceptable(pg_tz *tz); diff --git a/src/include/port.h b/src/include/port.h index c7400052675fc..3964d3b12936e 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -3,7 +3,7 @@ * port.h * Header for src/port/ compatibility functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port.h @@ -53,6 +53,7 @@ extern char *first_path_var_separator(const char *pathlist); extern void join_path_components(char *ret_path, const char *head, const char *tail); extern void canonicalize_path(char *path); +extern void canonicalize_path_enc(char *path, int encoding); extern void make_native_path(char *filename); extern void cleanup_path(char *path); extern bool path_contains_parent_reference(const char *path); @@ -306,6 +307,33 @@ extern bool rmtree(const char *path, bool rmtopdir); #if defined(WIN32) && !defined(__CYGWIN__) +/* + * We want the 64-bit variant of lseek(). + * + * For Visual Studio, this must be after to avoid messing up its + * lseek() and _lseeki64() function declarations. + * + * For MinGW there is already a macro, so we have to undefine it (depending on + * _FILE_OFFSET_BITS, it may point at its own lseek64, but we don't want to + * count on that being set). + */ +#undef lseek +#define lseek(a,b,c) _lseeki64((a),(b),(c)) + +/* + * We want the 64-bit variant of chsize(). It sets errno and also returns it, + * so convert non-zero result to -1 to match POSIX. + * + * Prevent MinGW from declaring functions, and undefine its macro before we + * define our own. + */ +#ifndef _MSC_VER +#define FTRUNCATE_DEFINED +#include +#undef ftruncate +#endif +#define ftruncate(a,b) (_chsize_s((a),(b)) == 0 ? 0 : -1) + /* * open() and fopen() replacements to allow deletion of open files and * passing of other special options. @@ -436,10 +464,8 @@ extern size_t strnlen(const char *str, size_t maxlen); extern char *strsep(char **stringp, const char *delim); #endif -/* port/user.c */ -#ifndef WIN32 -extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen); -extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen); +#if !HAVE_DECL_TIMINGSAFE_BCMP +extern int timingsafe_bcmp(const void *b1, const void *b2, size_t len); #endif /* @@ -465,6 +491,12 @@ extern void *bsearch_arg(const void *key, const void *base0, int (*compar) (const void *, const void *, void *), void *arg); +/* port/pg_localeconv_r.c */ +extern int pg_localeconv_r(const char *lc_monetary, + const char *lc_numeric, + struct lconv *output); +extern void pg_localeconv_free(struct lconv *lconv); + /* port/chklocale.c */ extern int pg_get_encoding_from_locale(const char *ctype, bool write_message); @@ -492,9 +524,14 @@ extern int pg_check_dir(const char *dir); /* port/pgmkdirp.c */ extern int pg_mkdir_p(char *path, int omode); -/* port/pqsignal.c */ +/* port/pqsignal.c (see also interfaces/libpq/legacy-pqsignal.c) */ +#ifdef FRONTEND +#define pqsignal pqsignal_fe +#else +#define pqsignal pqsignal_be +#endif typedef void (*pqsigfunc) (SIGNAL_ARGS); -extern pqsigfunc pqsignal(int signo, pqsigfunc func); +extern void pqsignal(int signo, pqsigfunc func); /* port/quotes.c */ extern char *escape_single_quotes_ascii(const char *src); diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h index f6fa432d2dfde..074136fe4c4a8 100644 --- a/src/include/port/atomics.h +++ b/src/include/port/atomics.h @@ -16,8 +16,8 @@ * * There exist generic, hardware independent, implementations for several * compilers which might be sufficient, although possibly not optimal, for a - * new platform. If no such generic implementation is available spinlocks (or - * even OS provided semaphores) will be used to implement the API. + * new platform. If no such generic implementation is available spinlocks will + * be used to implement the 64-bit parts of the API. * * Implement _u64 atomics if and only if your platform can use them * efficiently (and obviously correctly). @@ -28,7 +28,7 @@ * For an introduction to using memory barriers within the PostgreSQL backend, * see src/backend/storage/lmgr/README.barrier * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/atomics.h @@ -91,17 +91,24 @@ #elif defined(__SUNPRO_C) && !defined(__GNUC__) #include "port/atomics/generic-sunpro.h" #else -/* - * Unsupported compiler, we'll likely use slower fallbacks... At least - * compiler barriers should really be provided. - */ +/* Unknown compiler. */ +#endif + +/* Fail if we couldn't find implementations of required facilities. */ +#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT) +#error "could not find an implementation of pg_atomic_uint32" #endif +#if !defined(pg_compiler_barrier_impl) +#error "could not find an implementation of pg_compiler_barrier" +#endif +#if !defined(pg_memory_barrier_impl) +#error "could not find an implementation of pg_memory_barrier_impl" +#endif + /* - * Provide a full fallback of the pg_*_barrier(), pg_atomic**_flag and - * pg_atomic_* APIs for platforms without sufficient spinlock and/or atomics - * support. In the case of spinlock backed atomics the emulation is expected - * to be efficient, although less so than native atomics support. + * Provide a spinlock-based implementation of the 64 bit variants, if + * necessary. */ #include "port/atomics/fallback.h" diff --git a/src/include/port/atomics/arch-arm.h b/src/include/port/atomics/arch-arm.h index 3ca2dbbd2da6d..eb7e0ac93bacf 100644 --- a/src/include/port/atomics/arch-arm.h +++ b/src/include/port/atomics/arch-arm.h @@ -3,7 +3,7 @@ * arch-arm.h * Atomic operations considerations specific to ARM * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * NOTES: * diff --git a/src/include/port/atomics/arch-ppc.h b/src/include/port/atomics/arch-ppc.h index edaab7c8957fc..b93f6766d299f 100644 --- a/src/include/port/atomics/arch-ppc.h +++ b/src/include/port/atomics/arch-ppc.h @@ -3,7 +3,7 @@ * arch-ppc.h * Atomic operations considerations specific to PowerPC * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES: diff --git a/src/include/port/atomics/arch-x86.h b/src/include/port/atomics/arch-x86.h index 2a8eca30fcf9d..8983dd89d53d7 100644 --- a/src/include/port/atomics/arch-x86.h +++ b/src/include/port/atomics/arch-x86.h @@ -7,7 +7,7 @@ * support for xadd and cmpxchg. Given that the 386 isn't supported anywhere * anymore that's not much of a restriction luckily. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES: @@ -49,8 +49,6 @@ * nice to support older gcc's and the compare/exchange implementation here is * actually more efficient than the * __sync variant. */ -#if defined(HAVE_ATOMICS) - #if defined(__GNUC__) || defined(__INTEL_COMPILER) #define PG_HAVE_ATOMIC_FLAG_SUPPORT @@ -80,8 +78,6 @@ typedef struct pg_atomic_uint64 #endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */ -#endif /* defined(HAVE_ATOMICS) */ - #if !defined(PG_HAVE_SPIN_DELAY) /* * This sequence is equivalent to the PAUSE instruction ("rep" is @@ -132,8 +128,6 @@ pg_spin_delay_impl(void) #endif /* !defined(PG_HAVE_SPIN_DELAY) */ -#if defined(HAVE_ATOMICS) - #if defined(__GNUC__) || defined(__INTEL_COMPILER) #define PG_HAVE_ATOMIC_TEST_SET_FLAG @@ -250,5 +244,3 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_) defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) /* gcc, sunpro, msvc */ #define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY #endif /* 8 byte single-copy atomicity */ - -#endif /* HAVE_ATOMICS */ diff --git a/src/include/port/atomics/fallback.h b/src/include/port/atomics/fallback.h index 34cfee110fb12..d2f1b851668e9 100644 --- a/src/include/port/atomics/fallback.h +++ b/src/include/port/atomics/fallback.h @@ -1,10 +1,10 @@ /*------------------------------------------------------------------------- * * fallback.h - * Fallback for platforms without spinlock and/or atomics support. Slower + * Fallback for platforms without 64 bit atomics support. Slower * than native atomics support, but not unusably slow. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/atomics/fallback.h @@ -17,83 +17,6 @@ # error "should be included via atomics.h" #endif -#ifndef pg_memory_barrier_impl -/* - * If we have no memory barrier implementation for this architecture, we - * fall back to acquiring and releasing a spinlock. This might, in turn, - * fall back to the semaphore-based spinlock implementation, which will be - * amazingly slow. - * - * It's not self-evident that every possible legal implementation of a - * spinlock acquire-and-release would be equivalent to a full memory barrier. - * For example, I'm not sure that Itanium's acq and rel add up to a full - * fence. But all of our actual implementations seem OK in this regard. - */ -#define PG_HAVE_MEMORY_BARRIER_EMULATION - -extern void pg_spinlock_barrier(void); -#define pg_memory_barrier_impl pg_spinlock_barrier -#endif - -#ifndef pg_compiler_barrier_impl -/* - * If the compiler/arch combination does not provide compiler barriers, - * provide a fallback. The fallback simply consists of a function call into - * an externally defined function. That should guarantee compiler barrier - * semantics except for compilers that do inter translation unit/global - * optimization - those better provide an actual compiler barrier. - * - * A native compiler barrier for sure is a lot faster than this... - */ -#define PG_HAVE_COMPILER_BARRIER_EMULATION -extern void pg_extern_compiler_barrier(void); -#define pg_compiler_barrier_impl pg_extern_compiler_barrier -#endif - - -/* - * If we have atomics implementation for this platform, fall back to providing - * the atomics API using a spinlock to protect the internal state. Possibly - * the spinlock implementation uses semaphores internally... - * - * We have to be a bit careful here, as it's not guaranteed that atomic - * variables are mapped to the same address in every process (e.g. dynamic - * shared memory segments). We can't just hash the address and use that to map - * to a spinlock. Instead assign a spinlock on initialization of the atomic - * variable. - */ -#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && !defined(PG_HAVE_ATOMIC_U32_SUPPORT) - -#define PG_HAVE_ATOMIC_FLAG_SIMULATION -#define PG_HAVE_ATOMIC_FLAG_SUPPORT - -typedef struct pg_atomic_flag -{ - /* - * To avoid circular includes we can't use s_lock as a type here. Instead - * just reserve enough space for all spinlock types. Some platforms would - * be content with just one byte instead of 4, but that's not too much - * waste. - */ - int sema; - volatile bool value; -} pg_atomic_flag; - -#endif /* PG_HAVE_ATOMIC_FLAG_SUPPORT */ - -#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT) - -#define PG_HAVE_ATOMIC_U32_SIMULATION - -#define PG_HAVE_ATOMIC_U32_SUPPORT -typedef struct pg_atomic_uint32 -{ - /* Check pg_atomic_flag's definition above for an explanation */ - int sema; - volatile uint32 value; -} pg_atomic_uint32; - -#endif /* PG_HAVE_ATOMIC_U32_SUPPORT */ #if !defined(PG_HAVE_ATOMIC_U64_SUPPORT) @@ -102,49 +25,10 @@ typedef struct pg_atomic_uint32 #define PG_HAVE_ATOMIC_U64_SUPPORT typedef struct pg_atomic_uint64 { - /* Check pg_atomic_flag's definition above for an explanation */ int sema; volatile uint64 value; } pg_atomic_uint64; -#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */ - -#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION - -#define PG_HAVE_ATOMIC_INIT_FLAG -extern void pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr); - -#define PG_HAVE_ATOMIC_TEST_SET_FLAG -extern bool pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr); - -#define PG_HAVE_ATOMIC_CLEAR_FLAG -extern void pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr); - -#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG -extern bool pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr); - -#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */ - -#ifdef PG_HAVE_ATOMIC_U32_SIMULATION - -#define PG_HAVE_ATOMIC_INIT_U32 -extern void pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_); - -#define PG_HAVE_ATOMIC_WRITE_U32 -extern void pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val); - -#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32 -extern bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, - uint32 *expected, uint32 newval); - -#define PG_HAVE_ATOMIC_FETCH_ADD_U32 -extern uint32 pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_); - -#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */ - - -#ifdef PG_HAVE_ATOMIC_U64_SIMULATION - #define PG_HAVE_ATOMIC_INIT_U64 extern void pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_); @@ -155,4 +39,4 @@ extern bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, #define PG_HAVE_ATOMIC_FETCH_ADD_U64 extern uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_); -#endif /* PG_HAVE_ATOMIC_U64_SIMULATION */ +#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */ diff --git a/src/include/port/atomics/generic-gcc.h b/src/include/port/atomics/generic-gcc.h index 872d2f02af4a2..d8f04c89ccac2 100644 --- a/src/include/port/atomics/generic-gcc.h +++ b/src/include/port/atomics/generic-gcc.h @@ -3,7 +3,7 @@ * generic-gcc.h * Atomic operations, implemented using gcc (or compatible) intrinsics. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES: @@ -53,8 +53,6 @@ #endif -#ifdef HAVE_ATOMICS - /* generic gcc based atomic flag implementation */ #if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) \ && (defined(HAVE_GCC__SYNC_INT32_TAS) || defined(HAVE_GCC__SYNC_CHAR_TAS)) @@ -319,5 +317,3 @@ pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_) #endif #endif /* !defined(PG_DISABLE_64_BIT_ATOMICS) */ - -#endif /* defined(HAVE_ATOMICS) */ diff --git a/src/include/port/atomics/generic-msvc.h b/src/include/port/atomics/generic-msvc.h index c013aca5e7cfd..a6ea5f1c2e767 100644 --- a/src/include/port/atomics/generic-msvc.h +++ b/src/include/port/atomics/generic-msvc.h @@ -3,7 +3,7 @@ * generic-msvc.h * Atomic operations support when using MSVC * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES: @@ -30,8 +30,6 @@ #define pg_memory_barrier_impl() MemoryBarrier() #endif -#if defined(HAVE_ATOMICS) - #define PG_HAVE_ATOMIC_U32_SUPPORT typedef struct pg_atomic_uint32 { @@ -115,5 +113,3 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_) } #endif /* _WIN64 */ - -#endif /* HAVE_ATOMICS */ diff --git a/src/include/port/atomics/generic-sunpro.h b/src/include/port/atomics/generic-sunpro.h index 840a45e7788c7..09bba0be2037d 100644 --- a/src/include/port/atomics/generic-sunpro.h +++ b/src/include/port/atomics/generic-sunpro.h @@ -3,7 +3,7 @@ * generic-sunpro.h * Atomic operations for solaris' CC * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * * NOTES: * @@ -17,8 +17,6 @@ * ------------------------------------------------------------------------- */ -#if defined(HAVE_ATOMICS) - #ifdef HAVE_MBARRIER_H #include @@ -66,10 +64,6 @@ typedef struct pg_atomic_uint64 #endif /* HAVE_ATOMIC_H */ -#endif /* defined(HAVE_ATOMICS) */ - - -#if defined(HAVE_ATOMICS) #ifdef HAVE_ATOMIC_H @@ -117,5 +111,3 @@ pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 newval) } #endif /* HAVE_ATOMIC_H */ - -#endif /* defined(HAVE_ATOMICS) */ diff --git a/src/include/port/atomics/generic.h b/src/include/port/atomics/generic.h index 6113ab62a31ad..6b61a7b541665 100644 --- a/src/include/port/atomics/generic.h +++ b/src/include/port/atomics/generic.h @@ -4,7 +4,7 @@ * Implement higher level operations based on some lower level atomic * operations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/atomics/generic.h @@ -135,19 +135,9 @@ pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr) static inline void pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr) { - /* - * Use a memory barrier + plain write if we have a native memory - * barrier. But don't do so if memory barriers use spinlocks - that'd lead - * to circularity if flags are used to implement spinlocks. - */ -#ifndef PG_HAVE_MEMORY_BARRIER_EMULATION /* XXX: release semantics suffice? */ pg_memory_barrier_impl(); pg_atomic_write_u32_impl(ptr, 0); -#else - uint32 value = 1; - pg_atomic_compare_exchange_u32_impl(ptr, &value, 0); -#endif } #elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) diff --git a/src/include/port/darwin.h b/src/include/port/darwin.h index 15fb69d6dbb4b..6aa2ea70f6b0d 100644 --- a/src/include/port/darwin.h +++ b/src/include/port/darwin.h @@ -6,3 +6,8 @@ #define HAVE_FSYNC_WRITETHROUGH #endif + +/* + * macOS has a platform-specific implementation of prefetching. + */ +#define USE_PREFETCH diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h index 4d88478c9c24d..c7901bf8ddc0a 100644 --- a/src/include/port/pg_bitutils.h +++ b/src/include/port/pg_bitutils.h @@ -4,7 +4,7 @@ * Miscellaneous functions for bit-wise operations. * * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * src/include/port/pg_bitutils.h * @@ -74,13 +74,13 @@ pg_leftmost_one_pos64(uint64 word) #ifdef HAVE__BUILTIN_CLZ Assert(word != 0); -#if defined(HAVE_LONG_INT_64) +#if SIZEOF_LONG == 8 return 63 - __builtin_clzl(word); -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_LONG_LONG == 8 return 63 - __builtin_clzll(word); #else -#error must have a working 64-bit integer datatype -#endif /* HAVE_LONG_INT_64 */ +#error "cannot find integer type of the same size as uint64_t" +#endif #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64)) unsigned long result; @@ -147,13 +147,13 @@ pg_rightmost_one_pos64(uint64 word) #ifdef HAVE__BUILTIN_CTZ Assert(word != 0); -#if defined(HAVE_LONG_INT_64) +#if SIZEOF_LONG == 8 return __builtin_ctzl(word); -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_LONG_LONG == 8 return __builtin_ctzll(word); #else -#error must have a working 64-bit integer datatype -#endif /* HAVE_LONG_INT_64 */ +#error "cannot find integer type of the same size as uint64_t" +#endif #elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64)) unsigned long result; @@ -294,11 +294,20 @@ pg_ceil_log2_64(uint64 num) */ #ifdef HAVE_X86_64_POPCNTQ #if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID) -#define TRY_POPCNT_FAST 1 +#define TRY_POPCNT_X86_64 1 #endif #endif -#ifdef TRY_POPCNT_FAST +/* + * On AArch64, we can use Neon instructions if the compiler provides access to + * them (as indicated by __ARM_NEON). As in simd.h, we assume that all + * available 64-bit hardware has Neon support. + */ +#if defined(__aarch64__) && defined(__ARM_NEON) +#define POPCNT_AARCH64 1 +#endif + +#ifdef TRY_POPCNT_X86_64 /* Attempt to use the POPCNT instruction, but perform a runtime check first */ extern PGDLLIMPORT int (*pg_popcount32) (uint32 word); extern PGDLLIMPORT int (*pg_popcount64) (uint64 word); @@ -307,9 +316,7 @@ extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int /* * We can also try to use the AVX-512 popcount instruction on some systems. - * The implementation of that is located in its own file because it may - * require special compiler flags that we don't want to apply to any other - * files. + * The implementation of that is located in its own file. */ #ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK extern bool pg_popcount_avx512_available(void); @@ -317,6 +324,23 @@ extern uint64 pg_popcount_avx512(const char *buf, int bytes); extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask); #endif +#elif POPCNT_AARCH64 +/* Use the Neon version of pg_popcount{32,64} without function pointer. */ +extern int pg_popcount32(uint32 word); +extern int pg_popcount64(uint64 word); + +/* + * We can try to use an SVE-optimized pg_popcount() on some systems For that, + * we do use a function pointer. + */ +#ifdef USE_SVE_POPCNT_WITH_RUNTIME_CHECK +extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes); +extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask); +#else +extern uint64 pg_popcount_optimized(const char *buf, int bytes); +extern uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask); +#endif + #else /* Use a portable implementation -- no need for a function pointer. */ extern int pg_popcount32(uint32 word); @@ -324,7 +348,7 @@ extern int pg_popcount64(uint64 word); extern uint64 pg_popcount_optimized(const char *buf, int bytes); extern uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask); -#endif /* TRY_POPCNT_FAST */ +#endif /* TRY_POPCNT_X86_64 */ /* * Returns the number of 1-bits in buf. diff --git a/src/include/port/pg_bswap.h b/src/include/port/pg_bswap.h index 2379513f6570c..33648433c6377 100644 --- a/src/include/port/pg_bswap.h +++ b/src/include/port/pg_bswap.h @@ -11,7 +11,7 @@ * return the same. Use caution when using these wrapper macros with signed * integers. * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * src/include/port/pg_bswap.h * diff --git a/src/include/port/pg_crc32c.h b/src/include/port/pg_crc32c.h index 63c8e3a00b638..82313bb7fcfee 100644 --- a/src/include/port/pg_crc32c.h +++ b/src/include/port/pg_crc32c.h @@ -23,7 +23,7 @@ * EQ_CRC32C(c1, c2) * Check for equality of two CRCs. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/pg_crc32c.h @@ -42,12 +42,73 @@ typedef uint32 pg_crc32c; #define EQ_CRC32C(c1, c2) ((c1) == (c2)) #if defined(USE_SSE42_CRC32C) -/* Use Intel SSE4.2 instructions. */ +/* + * Use either Intel SSE 4.2 or AVX-512 instructions. We don't need a runtime check + * for SSE 4.2, so we can inline those in some cases. + */ + +#include + #define COMP_CRC32C(crc, data, len) \ - ((crc) = pg_comp_crc32c_sse42((crc), (data), (len))) + ((crc) = pg_comp_crc32c_dispatch((crc), (data), (len))) #define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) +extern pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len); extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len); +#ifdef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK +extern pg_crc32c pg_comp_crc32c_avx512(pg_crc32c crc, const void *data, size_t len); +#endif + +/* + * We can only get here if the host compiler targets SSE 4.2, but on some + * systems gcc and clang don't have the same built-in targets, so we still + * must use a function attribute here to accommodate "--with-llvm" builds. + */ +pg_attribute_no_sanitize_alignment() +pg_attribute_target("sse4.2") +static inline +pg_crc32c +pg_comp_crc32c_dispatch(pg_crc32c crc, const void *data, size_t len) +{ + if (__builtin_constant_p(len) && len < 32) + { + const unsigned char *p = data; + + /* + * For small constant inputs, inline the computation to avoid a + * function call and allow the compiler to unroll loops. + */ +#if SIZEOF_VOID_P >= 8 + for (; len >= 8; p += 8, len -= 8) + crc = _mm_crc32_u64(crc, *(const uint64 *) p); +#endif + for (; len >= 4; p += 4, len -= 4) + crc = _mm_crc32_u32(crc, *(const uint32 *) p); + for (; len > 0; --len) + crc = _mm_crc32_u8(crc, *p++); + return crc; + } + else + /* Otherwise, use a runtime check for AVX-512 instructions. */ + return pg_comp_crc32c(crc, data, len); +} + +#elif defined(USE_SSE42_CRC32C_WITH_RUNTIME_CHECK) + +/* + * Use Intel SSE 4.2 or AVX-512 instructions, but perform a runtime check first + * to check that they are available. + */ +#define COMP_CRC32C(crc, data, len) \ + ((crc) = pg_comp_crc32c((crc), (data), (len))) +#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF) + +extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len); +extern PGDLLIMPORT pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len); +extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len); +#ifdef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK +extern pg_crc32c pg_comp_crc32c_avx512(pg_crc32c crc, const void *data, size_t len); +#endif #elif defined(USE_ARMV8_CRC32C) /* Use ARMv8 CRC Extension instructions. */ @@ -67,10 +128,10 @@ extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t le extern pg_crc32c pg_comp_crc32c_loongarch(pg_crc32c crc, const void *data, size_t len); -#elif defined(USE_SSE42_CRC32C_WITH_RUNTIME_CHECK) || defined(USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK) +#elif defined(USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK) /* - * Use Intel SSE 4.2 or ARMv8 instructions, but perform a runtime check first + * Use ARMv8 instructions, but perform a runtime check first * to check that they are available. */ #define COMP_CRC32C(crc, data, len) \ @@ -79,13 +140,7 @@ extern pg_crc32c pg_comp_crc32c_loongarch(pg_crc32c crc, const void *data, size_ extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len); extern pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len); - -#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK -extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len); -#endif -#ifdef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len); -#endif #else /* diff --git a/src/include/port/pg_iovec.h b/src/include/port/pg_iovec.h index 7255c1bd911aa..df40c7208be48 100644 --- a/src/include/port/pg_iovec.h +++ b/src/include/port/pg_iovec.h @@ -3,7 +3,7 @@ * pg_iovec.h * Header for vectored I/O functions, to use in place of . * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/pg_iovec.h @@ -16,7 +16,7 @@ #ifndef WIN32 #include -#include +#include /* IWYU pragma: export */ #include #else @@ -33,8 +33,12 @@ struct iovec #endif -/* Define a reasonable maximum that is safe to use on the stack. */ -#define PG_IOV_MAX Min(IOV_MAX, 32) +/* + * Define a reasonable maximum that is safe to use on the stack in arrays of + * struct iovec and other small types. The operating system could limit us to + * a number as low as 16, but most systems have 1024. + */ +#define PG_IOV_MAX Min(IOV_MAX, 128) /* * Like preadv(), but with a prefix to remind us of a side-effect: on Windows @@ -68,7 +72,7 @@ pg_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) } sum += part; offset += part; - if (part < iov[i].iov_len) + if ((size_t) part < iov[i].iov_len) return sum; } return sum; @@ -107,7 +111,7 @@ pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) } sum += part; offset += part; - if (part < iov[i].iov_len) + if ((size_t) part < iov[i].iov_len) return sum; } return sum; diff --git a/src/include/port/pg_lfind.h b/src/include/port/pg_lfind.h index 4b1431ed00201..20f7497dcb767 100644 --- a/src/include/port/pg_lfind.h +++ b/src/include/port/pg_lfind.h @@ -4,7 +4,7 @@ * Optimized linear search routines using SIMD intrinsics where * available. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/port/pg_lfind.h diff --git a/src/include/port/pg_numa.h b/src/include/port/pg_numa.h new file mode 100644 index 0000000000000..40f1d324dcfe2 --- /dev/null +++ b/src/include/port/pg_numa.h @@ -0,0 +1,37 @@ +/*------------------------------------------------------------------------- + * + * pg_numa.h + * Basic NUMA portability routines + * + * + * Copyright (c) 2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/include/port/pg_numa.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_NUMA_H +#define PG_NUMA_H + +extern PGDLLIMPORT int pg_numa_init(void); +extern PGDLLIMPORT int pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status); +extern PGDLLIMPORT int pg_numa_get_max_node(void); + +#ifdef USE_LIBNUMA + +/* + * This is required on Linux, before pg_numa_query_pages() as we + * need to page-fault before move_pages(2) syscall returns valid results. + */ +#define pg_numa_touch_mem_if_required(ro_volatile_var, ptr) \ + ro_volatile_var = *(volatile uint64 *) ptr + +#else + +#define pg_numa_touch_mem_if_required(ro_volatile_var, ptr) \ + do {} while(0) + +#endif + +#endif /* PG_NUMA_H */ diff --git a/src/include/port/pg_pthread.h b/src/include/port/pg_pthread.h index d102ce9d6f33e..4dbb3c8a52f11 100644 --- a/src/include/port/pg_pthread.h +++ b/src/include/port/pg_pthread.h @@ -13,7 +13,7 @@ #ifndef PG_PTHREAD_H #define PG_PTHREAD_H -#include +#include /* IWYU pragma: export */ #ifndef HAVE_PTHREAD_BARRIER_WAIT diff --git a/src/include/port/simd.h b/src/include/port/simd.h index 597496f2fb7ed..97c5f3530221a 100644 --- a/src/include/port/simd.h +++ b/src/include/port/simd.h @@ -3,7 +3,7 @@ * simd.h * Support for platform-specific vector operations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/simd.h diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h index 7ffe5891c69ac..ff7028bdc81f9 100644 --- a/src/include/port/win32_port.h +++ b/src/include/port/win32_port.h @@ -6,7 +6,7 @@ * Note this is read in MinGW as well as native Windows builds, * but not in Cygwin builds. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/win32_port.h @@ -79,8 +79,6 @@ /* Must be here to avoid conflicting with prototype in windows.h */ #define mkdir(a,b) mkdir(a) -#define ftruncate(a,b) chsize(a,b) - /* Windows doesn't have fsync() as such, use _commit() */ #define fsync(fd) _commit(fd) @@ -156,14 +154,6 @@ #define sigmask(sig) ( 1 << ((sig)-1) ) -/* Signal function return values */ -#undef SIG_DFL -#undef SIG_ERR -#undef SIG_IGN -#define SIG_DFL ((pqsigfunc)0) -#define SIG_ERR ((pqsigfunc)-1) -#define SIG_IGN ((pqsigfunc)1) - /* Some extra signals */ #define SIGHUP 1 #define SIGQUIT 3 @@ -420,6 +410,19 @@ extern int _pglstat64(const char *name, struct stat *buf); */ #define strtok_r strtok_s +/* + * Supplement to . + */ +#ifdef _MSC_VER +/* + * MinGW has these functions if _POSIX_C_SOURCE is defined. Third-party + * libraries might do that, so to avoid clashes we get ahead of it and define + * it ourselves and use the system functions provided by MinGW. + */ +#define gmtime_r(clock, result) (gmtime_s(result, clock) ? NULL : (result)) +#define localtime_r(clock, result) (localtime_s(result, clock) ? NULL : (result)) +#endif + /* * Locale stuff. * diff --git a/src/include/port/win32ntdll.h b/src/include/port/win32ntdll.h index c8d22734832ca..c03fd52816950 100644 --- a/src/include/port/win32ntdll.h +++ b/src/include/port/win32ntdll.h @@ -3,7 +3,7 @@ * win32ntdll.h * Dynamically loaded Windows NT functions. * - * Portions Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2021-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/port/win32ntdll.h diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h index a6fc1922f2080..f71a851b18d87 100644 --- a/src/include/portability/instr_time.h +++ b/src/include/portability/instr_time.h @@ -32,9 +32,9 @@ * * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds) * - * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds) + * INSTR_TIME_GET_MICROSEC(t) convert t to int64 (in microseconds) * - * INSTR_TIME_GET_NANOSEC(t) convert t to uint64 (in nanoseconds) + * INSTR_TIME_GET_NANOSEC(t) convert t to int64 (in nanoseconds) * * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert * absolute times to intervals. The INSTR_TIME_GET_xxx operations are @@ -47,7 +47,7 @@ * Beware of multiple evaluations of the macro arguments. * * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/portability/instr_time.h * diff --git a/src/include/portability/mem.h b/src/include/portability/mem.h index 2cd05313b829c..ef9800732d901 100644 --- a/src/include/portability/mem.h +++ b/src/include/portability/mem.h @@ -3,7 +3,7 @@ * mem.h * portability definitions for various memory operations * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/portability/mem.h * diff --git a/src/include/postgres.h b/src/include/postgres.h index 5d5fd7813e808..8a41a6686877f 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -7,13 +7,14 @@ * Client-side code should include postgres_fe.h instead. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California * * src/include/postgres.h * *------------------------------------------------------------------------- */ +/* IWYU pragma: always_keep */ /* *---------------------------------------------------------------- * TABLE OF CONTENTS @@ -42,10 +43,14 @@ #ifndef POSTGRES_H #define POSTGRES_H +/* IWYU pragma: begin_exports */ + #include "c.h" #include "utils/elog.h" #include "utils/palloc.h" +/* IWYU pragma: end_exports */ + /* ---------------------------------------------------------------- * Section 1: Datum type + support functions * ---------------------------------------------------------------- diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h index 240ad4e93bf1e..bf45c50dcf318 100644 --- a/src/include/postgres_ext.h +++ b/src/include/postgres_ext.h @@ -19,12 +19,11 @@ * *------------------------------------------------------------------------- */ +/* IWYU pragma: always_keep */ #ifndef POSTGRES_EXT_H #define POSTGRES_EXT_H -#include "pg_config_ext.h" - /* * Object ID is a fundamental type in Postgres. */ @@ -43,9 +42,6 @@ typedef unsigned int Oid; /* the above needs */ -/* Define a signed 64-bit integer type for use in client API declarations. */ -typedef PG_INT64_TYPE pg_int64; - /* * Identifiers of error message fields. Kept here to keep common * between frontend and backend, and also to export them to libpq diff --git a/src/include/postgres_fe.h b/src/include/postgres_fe.h index 9c605daa3655b..a3f65b1dca45f 100644 --- a/src/include/postgres_fe.h +++ b/src/include/postgres_fe.h @@ -8,13 +8,14 @@ * postgres.h. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California * * src/include/postgres_fe.h * *------------------------------------------------------------------------- */ +/* IWYU pragma: always_keep */ #ifndef POSTGRES_FE_H #define POSTGRES_FE_H @@ -22,8 +23,12 @@ #define FRONTEND 1 #endif +/* IWYU pragma: begin_exports */ + #include "c.h" #include "common/fe_memutils.h" +/* IWYU pragma: end_exports */ + #endif /* POSTGRES_FE_H */ diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index cae1e8b3294f2..e8135f41a1c24 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -4,7 +4,7 @@ * header file for integrated autovacuum daemon * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/postmaster/autovacuum.h @@ -28,10 +28,12 @@ typedef enum /* GUC variables */ extern PGDLLIMPORT bool autovacuum_start_daemon; +extern PGDLLIMPORT int autovacuum_worker_slots; extern PGDLLIMPORT int autovacuum_max_workers; extern PGDLLIMPORT int autovacuum_work_mem; extern PGDLLIMPORT int autovacuum_naptime; extern PGDLLIMPORT int autovacuum_vac_thresh; +extern PGDLLIMPORT int autovacuum_vac_max_thresh; extern PGDLLIMPORT double autovacuum_vac_scale; extern PGDLLIMPORT int autovacuum_vac_ins_thresh; extern PGDLLIMPORT double autovacuum_vac_ins_scale; @@ -56,8 +58,8 @@ extern void autovac_init(void); /* called from postmaster when a worker could not be forked */ extern void AutoVacWorkerFailed(void); -extern void AutoVacLauncherMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); -extern void AutoVacWorkerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void AutoVacLauncherMain(const void *startup_data, size_t startup_data_len); +pg_noreturn extern void AutoVacWorkerMain(const void *startup_data, size_t startup_data_len); extern bool AutoVacuumRequestWork(AutoVacuumWorkItemType type, Oid relationId, BlockNumber blkno); diff --git a/src/include/postmaster/auxprocess.h b/src/include/postmaster/auxprocess.h index 4e80b1cfec7f3..23d4b2ad2ec39 100644 --- a/src/include/postmaster/auxprocess.h +++ b/src/include/postmaster/auxprocess.h @@ -3,7 +3,7 @@ * include file for functions related to auxiliary processes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 22fc49ec27f4e..058667a47a0a1 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -31,7 +31,7 @@ * different) code. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h index 9106a0ef3f08e..26cbc821edfbd 100644 --- a/src/include/postmaster/bgworker_internals.h +++ b/src/include/postmaster/bgworker_internals.h @@ -2,7 +2,7 @@ * bgworker_internals.h * POSTGRES pluggable background workers internals * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -26,35 +26,32 @@ /* * List of background workers, private to postmaster. * - * A worker that requests a database connection during registration will have - * rw_backend set, and will be present in BackendList. Note: do not rely on - * rw_backend being non-NULL for shmem-connected workers! + * All workers that are currently running will also have an entry in + * ActiveChildList. */ typedef struct RegisteredBgWorker { BackgroundWorker rw_worker; /* its registry entry */ - struct bkend *rw_backend; /* its BackendList entry, or NULL */ pid_t rw_pid; /* 0 if not running */ - int rw_child_slot; TimestampTz rw_crashed_at; /* if not 0, time it last crashed */ int rw_shmem_slot; bool rw_terminate; - slist_node rw_lnode; /* list link */ + dlist_node rw_lnode; /* list link */ } RegisteredBgWorker; -extern PGDLLIMPORT slist_head BackgroundWorkerList; +extern PGDLLIMPORT dlist_head BackgroundWorkerList; extern Size BackgroundWorkerShmemSize(void); extern void BackgroundWorkerShmemInit(void); extern void BackgroundWorkerStateChange(bool allow_new_workers); -extern void ForgetBackgroundWorker(slist_mutable_iter *cur); -extern void ReportBackgroundWorkerPID(RegisteredBgWorker *); -extern void ReportBackgroundWorkerExit(slist_mutable_iter *cur); +extern void ForgetBackgroundWorker(RegisteredBgWorker *rw); +extern void ReportBackgroundWorkerPID(RegisteredBgWorker *rw); +extern void ReportBackgroundWorkerExit(RegisteredBgWorker *rw); extern void BackgroundWorkerStopNotifications(pid_t pid); extern void ForgetUnstartedBackgroundWorkers(void); extern void ResetBackgroundWorkerCrashTimes(void); /* Entry point for background worker processes */ -extern void BackgroundWorkerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void BackgroundWorkerMain(const void *startup_data, size_t startup_data_len); #endif /* BGWORKER_INTERNALS_H */ diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h index 407f26e53025f..800ecbfd13b31 100644 --- a/src/include/postmaster/bgwriter.h +++ b/src/include/postmaster/bgwriter.h @@ -6,7 +6,7 @@ * The bgwriter process used to handle checkpointing duties too. Now * there is a separate process, but we did not bother to split this header. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/postmaster/bgwriter.h * @@ -27,8 +27,8 @@ extern PGDLLIMPORT int CheckPointTimeout; extern PGDLLIMPORT int CheckPointWarning; extern PGDLLIMPORT double CheckPointCompletionTarget; -extern void BackgroundWriterMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); -extern void CheckpointerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void BackgroundWriterMain(const void *startup_data, size_t startup_data_len); +pg_noreturn extern void CheckpointerMain(const void *startup_data, size_t startup_data_len); extern void RequestCheckpoint(int flags); extern void CheckpointWriteDelay(int flags, double progress); diff --git a/src/include/postmaster/fork_process.h b/src/include/postmaster/fork_process.h index d27d3d28fef58..a1b20316ecd82 100644 --- a/src/include/postmaster/fork_process.h +++ b/src/include/postmaster/fork_process.h @@ -3,7 +3,7 @@ * fork_process.h * Exports from postmaster/fork_process.c. * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/postmaster/fork_process.h * diff --git a/src/include/postmaster/interrupt.h b/src/include/postmaster/interrupt.h index 341a09d83fe46..3bf4932084683 100644 --- a/src/include/postmaster/interrupt.h +++ b/src/include/postmaster/interrupt.h @@ -7,7 +7,7 @@ * have their own implementations, but we provide a few generic things * here to facilitate code reuse. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -24,7 +24,7 @@ extern PGDLLIMPORT volatile sig_atomic_t ConfigReloadPending; extern PGDLLIMPORT volatile sig_atomic_t ShutdownRequestPending; -extern void HandleMainLoopInterrupts(void); +extern void ProcessMainLoopInterrupts(void); extern void SignalHandlerForConfigReload(SIGNAL_ARGS); extern void SignalHandlerForCrashExit(SIGNAL_ARGS); extern void SignalHandlerForShutdownRequest(SIGNAL_ARGS); diff --git a/src/include/postmaster/pgarch.h b/src/include/postmaster/pgarch.h index a7a417226b012..ef7b12520861f 100644 --- a/src/include/postmaster/pgarch.h +++ b/src/include/postmaster/pgarch.h @@ -3,7 +3,7 @@ * pgarch.h * Exports from postmaster/pgarch.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/postmaster/pgarch.h @@ -29,7 +29,7 @@ extern Size PgArchShmemSize(void); extern void PgArchShmemInit(void); extern bool PgArchCanRestart(void); -extern void PgArchiverMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void PgArchiverMain(const void *startup_data, size_t startup_data_len); extern void PgArchWakeup(void); extern void PgArchForceDirScan(void); diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index d19e103937dc4..92497cd6a0fb5 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -3,7 +3,7 @@ * postmaster.h * Exports from postmaster/postmaster.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/postmaster/postmaster.h @@ -13,8 +13,44 @@ #ifndef _POSTMASTER_H #define _POSTMASTER_H +#include "lib/ilist.h" #include "miscadmin.h" +/* + * A struct representing an active postmaster child process. This is used + * mainly to keep track of how many children we have and send them appropriate + * signals when necessary. All postmaster child processes are assigned a + * PMChild entry. That includes "normal" client sessions, but also autovacuum + * workers, walsenders, background workers, and aux processes. (Note that at + * the time of launch, walsenders are labeled B_BACKEND; we relabel them to + * B_WAL_SENDER upon noticing they've changed their PMChildFlags entry. Hence + * that check must be done before any operation that needs to distinguish + * walsenders from normal backends.) + * + * "dead-end" children are also allocated a PMChild entry: these are children + * launched just for the purpose of sending a friendly rejection message to a + * would-be client. We must track them because they are attached to shared + * memory, but we know they will never become live backends. + * + * child_slot is an identifier that is unique across all running child + * processes. It is used as an index into the PMChildFlags array. dead-end + * children are not assigned a child_slot and have child_slot == 0 (valid + * child_slot ids start from 1). + */ +typedef struct +{ + pid_t pid; /* process id of backend */ + int child_slot; /* PMChildSlot for this backend, if any */ + BackendType bkend_type; /* child process flavor, see above */ + struct RegisteredBgWorker *rw; /* bgworker info, if this is a bgworker */ + bool bgworker_notify; /* gets bgworker start/stop notifications */ + dlist_node elem; /* list link in ActiveChildList */ +} PMChild; + +#ifdef EXEC_BACKEND +extern PGDLLIMPORT int num_pmchild_slots; +#endif + /* GUC options */ extern PGDLLIMPORT bool EnableSSL; extern PGDLLIMPORT int SuperuserReservedConnections; @@ -27,7 +63,6 @@ extern PGDLLIMPORT char *ListenAddresses; extern PGDLLIMPORT bool ClientAuthInProgress; extern PGDLLIMPORT int PreAuthDelay; extern PGDLLIMPORT int AuthenticationTimeout; -extern PGDLLIMPORT bool Log_connections; extern PGDLLIMPORT bool log_hostname; extern PGDLLIMPORT bool enable_bonjour; extern PGDLLIMPORT char *bonjour_name; @@ -36,10 +71,6 @@ extern PGDLLIMPORT bool remove_temp_files_after_crash; extern PGDLLIMPORT bool send_abort_for_crash; extern PGDLLIMPORT bool send_abort_for_kill; -#ifdef EXEC_BACKEND -extern struct bkend *ShmemBackendArray; -#endif - #ifdef WIN32 extern PGDLLIMPORT HANDLE PostmasterHandle; #else @@ -59,7 +90,7 @@ extern PGDLLIMPORT const char *progname; extern PGDLLIMPORT bool redirection_done; extern PGDLLIMPORT bool LoadedSSL; -extern void PostmasterMain(int argc, char *argv[]) pg_attribute_noreturn(); +pg_noreturn extern void PostmasterMain(int argc, char *argv[]); extern void ClosePostmasterPorts(bool am_syslogger); extern void InitProcessGlobals(void); @@ -67,40 +98,48 @@ extern int MaxLivePostmasterChildren(void); extern bool PostmasterMarkPIDForWorkerNotify(int); -extern void processCancelRequest(int backendPID, int32 cancelAuthCode); - -#ifdef EXEC_BACKEND -extern Size ShmemBackendArraySize(void); -extern void ShmemBackendArrayAllocation(void); - #ifdef WIN32 extern void pgwin32_register_deadchild_callback(HANDLE procHandle, DWORD procId); #endif -#endif /* defined in globals.c */ extern PGDLLIMPORT struct ClientSocket *MyClientSocket; /* prototypes for functions in launch_backend.c */ extern pid_t postmaster_child_launch(BackendType child_type, - char *startup_data, + int child_slot, + const void *startup_data, size_t startup_data_len, struct ClientSocket *client_sock); const char *PostmasterChildName(BackendType child_type); #ifdef EXEC_BACKEND -extern void SubPostmasterMain(int argc, char *argv[]) pg_attribute_noreturn(); +pg_noreturn extern void SubPostmasterMain(int argc, char *argv[]); #endif +/* defined in pmchild.c */ +extern PGDLLIMPORT dlist_head ActiveChildList; + +extern void InitPostmasterChildSlots(void); +extern PMChild *AssignPostmasterChildSlot(BackendType btype); +extern PMChild *AllocDeadEndChild(void); +extern bool ReleasePostmasterChildSlot(PMChild *pmchild); +extern PMChild *FindPostmasterChildByPid(int pid); + /* - * Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved - * for buffer references in buf_internals.h. This limitation could be lifted - * by using a 64bit state; but it's unlikely to be worthwhile as 2^18-1 - * backends exceed currently realistic configurations. Even if that limitation - * were removed, we still could not a) exceed 2^23-1 because inval.c stores - * the ProcNumber as a 3-byte signed integer, b) INT_MAX/4 because some places - * compute 4*MaxBackends without any overflow check. This is rechecked in the - * relevant GUC check hooks and in RegisterBackgroundWorker(). + * These values correspond to the special must-be-first options for dispatching + * to various subprograms. parse_dispatch_option() can be used to convert an + * option name to one of these values. */ -#define MAX_BACKENDS 0x3FFFF +typedef enum DispatchOption +{ + DISPATCH_CHECK, + DISPATCH_BOOT, + DISPATCH_FORKCHILD, + DISPATCH_DESCRIBE_CONFIG, + DISPATCH_SINGLE, + DISPATCH_POSTMASTER, /* must be last */ +} DispatchOption; + +extern DispatchOption parse_dispatch_option(const char *name); #endif /* _POSTMASTER_H */ diff --git a/src/include/postmaster/startup.h b/src/include/postmaster/startup.h index dde7ebde88124..ec2c8d3bff56b 100644 --- a/src/include/postmaster/startup.h +++ b/src/include/postmaster/startup.h @@ -3,7 +3,7 @@ * startup.h * Exports from postmaster/startup.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/postmaster/startup.h * @@ -25,8 +25,8 @@ extern PGDLLIMPORT int log_startup_progress_interval; -extern void HandleStartupProcInterrupts(void); -extern void StartupProcessMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +extern void ProcessStartupProcInterrupts(void); +pg_noreturn extern void StartupProcessMain(const void *startup_data, size_t startup_data_len); extern void PreRestoreCommand(void); extern void PostRestoreCommand(void); extern bool IsPromoteSignaled(void); diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h index b5fc239ba9ca5..15fca58ff5dd2 100644 --- a/src/include/postmaster/syslogger.h +++ b/src/include/postmaster/syslogger.h @@ -3,7 +3,7 @@ * syslogger.h * Exports from postmaster/syslogger.c. * - * Copyright (c) 2004-2024, PostgreSQL Global Development Group + * Copyright (c) 2004-2025, PostgreSQL Global Development Group * * src/include/postmaster/syslogger.h * @@ -76,7 +76,7 @@ extern PGDLLIMPORT bool Log_truncate_on_rotation; extern PGDLLIMPORT int Log_file_mode; #ifdef EXEC_BACKEND -extern pg_time_t first_syslogger_file_time; +extern PGDLLIMPORT pg_time_t first_syslogger_file_time; #endif #ifndef WIN32 @@ -86,11 +86,11 @@ extern PGDLLIMPORT HANDLE syslogPipe[2]; #endif -extern int SysLogger_Start(void); +extern int SysLogger_Start(int child_slot); extern void write_syslogger_file(const char *buffer, int count, int destination); -extern void SysLoggerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void SysLoggerMain(const void *startup_data, size_t startup_data_len); extern bool CheckLogrotateSignal(void); extern void RemoveLogrotateSignalFiles(void); diff --git a/src/include/postmaster/walsummarizer.h b/src/include/postmaster/walsummarizer.h index aedca556764c4..34dda607c6931 100644 --- a/src/include/postmaster/walsummarizer.h +++ b/src/include/postmaster/walsummarizer.h @@ -4,7 +4,7 @@ * * Header file for background WAL summarization process. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/postmaster/walsummarizer.h @@ -21,7 +21,7 @@ extern PGDLLIMPORT int wal_summary_keep_time; extern Size WalSummarizerShmemSize(void); extern void WalSummarizerShmemInit(void); -extern void WalSummarizerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void WalSummarizerMain(const void *startup_data, size_t startup_data_len); extern void GetWalSummarizerState(TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn, @@ -29,7 +29,7 @@ extern void GetWalSummarizerState(TimeLineID *summarized_tli, int *summarizer_pid); extern XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact); -extern void SetWalSummarizerLatch(void); +extern void WakeupWalSummarizer(void); extern void WaitForWalSummarization(XLogRecPtr lsn); #endif diff --git a/src/include/postmaster/walwriter.h b/src/include/postmaster/walwriter.h index 5884d69fed110..58e5c913d5ab6 100644 --- a/src/include/postmaster/walwriter.h +++ b/src/include/postmaster/walwriter.h @@ -3,7 +3,7 @@ * walwriter.h * Exports from postmaster/walwriter.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/postmaster/walwriter.h * @@ -18,6 +18,6 @@ extern PGDLLIMPORT int WalWriterDelay; extern PGDLLIMPORT int WalWriterFlushAfter; -extern void WalWriterMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void WalWriterMain(const void *startup_data, size_t startup_data_len); #endif /* _WALWRITER_H */ diff --git a/src/include/regex/regexport.h b/src/include/regex/regexport.h index ada36990f6f3a..fe086d110f9bf 100644 --- a/src/include/regex/regexport.h +++ b/src/include/regex/regexport.h @@ -17,7 +17,7 @@ * line and start/end of string. Colors are numbered 0..C-1, but note that * color 0 is "white" (all unused characters) and can generally be ignored. * - * Portions Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2013-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1998, 1999 Henry Spencer * * IDENTIFICATION diff --git a/src/include/regex/regguts.h b/src/include/regex/regguts.h index 3ca3647e118ea..fd69299a16d24 100644 --- a/src/include/regex/regguts.h +++ b/src/include/regex/regguts.h @@ -410,6 +410,8 @@ struct cnfa int flags; /* bitmask of the following flags: */ #define HASLACONS 01 /* uses lookaround constraints */ #define MATCHALL 02 /* matches all strings of a range of lengths */ +#define HASCANTMATCH 04 /* contains CANTMATCH arcs */ + /* Note: HASCANTMATCH appears in nfa structs' flags, but never in cnfas */ int pre; /* setup state number */ int post; /* teardown state number */ color bos[2]; /* colors, if any, assigned to BOS and BOL */ diff --git a/src/include/replication/conflict.h b/src/include/replication/conflict.h new file mode 100644 index 0000000000000..6c59125f25657 --- /dev/null +++ b/src/include/replication/conflict.h @@ -0,0 +1,82 @@ +/*------------------------------------------------------------------------- + * conflict.h + * Exports for conflicts logging. + * + * Copyright (c) 2024-2025, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ +#ifndef CONFLICT_H +#define CONFLICT_H + +#include "nodes/execnodes.h" +#include "utils/timestamp.h" + +/* + * Conflict types that could occur while applying remote changes. + * + * This enum is used in statistics collection (see + * PgStat_StatSubEntry::conflict_count and + * PgStat_BackendSubEntry::conflict_count) as well, therefore, when adding new + * values or reordering existing ones, ensure to review and potentially adjust + * the corresponding statistics collection codes. + */ +typedef enum +{ + /* The row to be inserted violates unique constraint */ + CT_INSERT_EXISTS, + + /* The row to be updated was modified by a different origin */ + CT_UPDATE_ORIGIN_DIFFERS, + + /* The updated row value violates unique constraint */ + CT_UPDATE_EXISTS, + + /* The row to be updated is missing */ + CT_UPDATE_MISSING, + + /* The row to be deleted was modified by a different origin */ + CT_DELETE_ORIGIN_DIFFERS, + + /* The row to be deleted is missing */ + CT_DELETE_MISSING, + + /* The row to be inserted/updated violates multiple unique constraint */ + CT_MULTIPLE_UNIQUE_CONFLICTS, + + /* + * Other conflicts, such as exclusion constraint violations, involve more + * complex rules than simple equality checks. These conflicts are left for + * future improvements. + */ +} ConflictType; + +#define CONFLICT_NUM_TYPES (CT_MULTIPLE_UNIQUE_CONFLICTS + 1) + +/* + * Information for the existing local tuple that caused the conflict. + */ +typedef struct ConflictTupleInfo +{ + TupleTableSlot *slot; /* tuple slot holding the conflicting local + * tuple */ + Oid indexoid; /* OID of the index where the conflict + * occurred */ + TransactionId xmin; /* transaction ID of the modification causing + * the conflict */ + RepOriginId origin; /* origin identifier of the modification */ + TimestampTz ts; /* timestamp of when the modification on the + * conflicting local tuple occurred */ +} ConflictTupleInfo; + +extern bool GetTupleTransactionInfo(TupleTableSlot *localslot, + TransactionId *xmin, + RepOriginId *localorigin, + TimestampTz *localts); +extern void ReportApplyConflict(EState *estate, ResultRelInfo *relinfo, + int elevel, ConflictType type, + TupleTableSlot *searchslot, + TupleTableSlot *remoteslot, + List *conflicttuples); +extern void InitConflictIndexes(ResultRelInfo *relInfo); +#endif diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h index 17a5b5e95ab84..d6c3fc7aa9c6a 100644 --- a/src/include/replication/decode.h +++ b/src/include/replication/decode.h @@ -2,7 +2,7 @@ * decode.h * PostgreSQL WAL to logical transformation * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/include/replication/logical.h b/src/include/replication/logical.h index aff38e8d049f2..2e562bee5a9c1 100644 --- a/src/include/replication/logical.h +++ b/src/include/replication/logical.h @@ -2,7 +2,7 @@ * logical.h * PostgreSQL logical decoding coordination * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h index ff0438b5bb723..82b202f330515 100644 --- a/src/include/replication/logicallauncher.h +++ b/src/include/replication/logicallauncher.h @@ -3,7 +3,7 @@ * logicallauncher.h * Exports for logical replication launcher. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/replication/logicallauncher.h * diff --git a/src/include/replication/logicalproto.h b/src/include/replication/logicalproto.h index c409638a2eff6..b261c60d3fa14 100644 --- a/src/include/replication/logicalproto.h +++ b/src/include/replication/logicalproto.h @@ -3,7 +3,7 @@ * logicalproto.h * logical replication protocol * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/replication/logicalproto.h @@ -223,20 +223,22 @@ extern void logicalrep_write_origin(StringInfo out, const char *origin, XLogRecPtr origin_lsn); extern char *logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn); extern void logicalrep_write_insert(StringInfo out, TransactionId xid, - Relation rel, - TupleTableSlot *newslot, - bool binary, Bitmapset *columns); + Relation rel, TupleTableSlot *newslot, + bool binary, Bitmapset *columns, + PublishGencolsType include_gencols_type); extern LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup); extern void logicalrep_write_update(StringInfo out, TransactionId xid, - Relation rel, - TupleTableSlot *oldslot, - TupleTableSlot *newslot, bool binary, Bitmapset *columns); + Relation rel, TupleTableSlot *oldslot, + TupleTableSlot *newslot, bool binary, + Bitmapset *columns, + PublishGencolsType include_gencols_type); extern LogicalRepRelId logicalrep_read_update(StringInfo in, bool *has_oldtuple, LogicalRepTupleData *oldtup, LogicalRepTupleData *newtup); extern void logicalrep_write_delete(StringInfo out, TransactionId xid, Relation rel, TupleTableSlot *oldslot, - bool binary, Bitmapset *columns); + bool binary, Bitmapset *columns, + PublishGencolsType include_gencols_type); extern LogicalRepRelId logicalrep_read_delete(StringInfo in, LogicalRepTupleData *oldtup); extern void logicalrep_write_truncate(StringInfo out, TransactionId xid, @@ -247,7 +249,8 @@ extern List *logicalrep_read_truncate(StringInfo in, extern void logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecPtr lsn, bool transactional, const char *prefix, Size sz, const char *message); extern void logicalrep_write_rel(StringInfo out, TransactionId xid, - Relation rel, Bitmapset *columns); + Relation rel, Bitmapset *columns, + PublishGencolsType include_gencols_type); extern LogicalRepRelation *logicalrep_read_rel(StringInfo in); extern void logicalrep_write_typ(StringInfo out, TransactionId xid, Oid typoid); @@ -270,5 +273,8 @@ extern void logicalrep_read_stream_abort(StringInfo in, LogicalRepStreamAbortData *abort_data, bool read_abort_info); extern const char *logicalrep_message_type(LogicalRepMsgType action); +extern bool logicalrep_should_publish_column(Form_pg_attribute att, + Bitmapset *columns, + PublishGencolsType include_gencols_type); #endif /* LOGICAL_PROTO_H */ diff --git a/src/include/replication/logicalrelation.h b/src/include/replication/logicalrelation.h index e687b40a566f1..7a561a8e8d829 100644 --- a/src/include/replication/logicalrelation.h +++ b/src/include/replication/logicalrelation.h @@ -3,7 +3,7 @@ * logicalrelation.h * Relation definitions for logical replication relation mapping. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/replication/logicalrelation.h * @@ -48,7 +48,7 @@ extern LogicalRepRelMapEntry *logicalrep_partition_open(LogicalRepRelMapEntry *r Relation partrel, AttrMap *map); extern void logicalrep_rel_close(LogicalRepRelMapEntry *rel, LOCKMODE lockmode); -extern bool IsIndexUsableForReplicaIdentityFull(IndexInfo *indexInfo, AttrMap *attrmap); +extern bool IsIndexUsableForReplicaIdentityFull(Relation idxrel, AttrMap *attrmap); extern Oid GetRelationIdentityOrPK(Relation rel); #endif /* LOGICALRELATION_H */ diff --git a/src/include/replication/logicalworker.h b/src/include/replication/logicalworker.h index a18d79d1b2817..88912606e4d58 100644 --- a/src/include/replication/logicalworker.h +++ b/src/include/replication/logicalworker.h @@ -3,7 +3,7 @@ * logicalworker.h * Exports for logical replication workers. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/replication/logicalworker.h * @@ -24,7 +24,7 @@ extern bool IsLogicalWorker(void); extern bool IsLogicalParallelApplyWorker(void); extern void HandleParallelApplyMessageInterrupt(void); -extern void HandleParallelApplyMessages(void); +extern void ProcessParallelApplyMessages(void); extern void LogicalRepWorkersWakeupAtCommit(Oid subid); diff --git a/src/include/replication/message.h b/src/include/replication/message.h index d5fb2fe017205..8a0893ea53961 100644 --- a/src/include/replication/message.h +++ b/src/include/replication/message.h @@ -2,7 +2,7 @@ * message.h * Exports from replication/logical/message.c * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * src/include/replication/message.h *------------------------------------------------------------------------- diff --git a/src/include/replication/origin.h b/src/include/replication/origin.h index 7189ba9e7693a..2a73f6aa49296 100644 --- a/src/include/replication/origin.h +++ b/src/include/replication/origin.h @@ -2,7 +2,7 @@ * origin.h * Exports from replication/logical/origin.c * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * src/include/replication/origin.h *------------------------------------------------------------------------- @@ -33,10 +33,20 @@ typedef struct xl_replorigin_drop #define InvalidRepOriginId 0 #define DoNotReplicateId PG_UINT16_MAX +/* + * To avoid needing a TOAST table for pg_replication_origin, we limit + * replication origin names to 512 bytes. This should be more than enough for + * all practical use. + */ +#define MAX_RONAME_LEN 512 + extern PGDLLIMPORT RepOriginId replorigin_session_origin; extern PGDLLIMPORT XLogRecPtr replorigin_session_origin_lsn; extern PGDLLIMPORT TimestampTz replorigin_session_origin_timestamp; +/* GUCs */ +extern PGDLLIMPORT int max_active_replication_origins; + /* API for querying & manipulating replication origins */ extern RepOriginId replorigin_by_name(const char *roname, bool missing_ok); extern RepOriginId replorigin_create(const char *roname); diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h index 44988ebdd89e9..8d4d5b71887d2 100644 --- a/src/include/replication/output_plugin.h +++ b/src/include/replication/output_plugin.h @@ -2,7 +2,7 @@ * output_plugin.h * PostgreSQL Logical Decode Plugin Interface * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ diff --git a/src/include/replication/pgoutput.h b/src/include/replication/pgoutput.h index 89f94e114726f..e53456c26073d 100644 --- a/src/include/replication/pgoutput.h +++ b/src/include/replication/pgoutput.h @@ -3,7 +3,7 @@ * pgoutput.h * Logical Replication output plugin * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/replication/pgoutput.h @@ -20,6 +20,7 @@ typedef struct PGOutputData MemoryContext context; /* private memory context for transient * allocations */ MemoryContext cachectx; /* private memory context for cache data */ + MemoryContext pubctx; /* private memory context for publication data */ bool in_streaming; /* true if we are streaming a chunk of * transaction */ diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h index 851a001c8bb2b..fa0745552f86c 100644 --- a/src/include/replication/reorderbuffer.h +++ b/src/include/replication/reorderbuffer.h @@ -2,7 +2,7 @@ * reorderbuffer.h * PostgreSQL logical replay/reorder buffer management. * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * src/include/replication/reorderbuffer.h */ @@ -18,6 +18,11 @@ #include "utils/snapshot.h" #include "utils/timestamp.h" +/* paths for logical decoding data (relative to installation's $PGDATA) */ +#define PG_LOGICAL_DIR "pg_logical" +#define PG_LOGICAL_MAPPINGS_DIR PG_LOGICAL_DIR "/mappings" +#define PG_LOGICAL_SNAPSHOTS_DIR PG_LOGICAL_DIR "/snapshots" + /* GUC variables */ extern PGDLLIMPORT int logical_decoding_work_mem; extern PGDLLIMPORT int debug_logical_replication_streaming; @@ -165,9 +170,15 @@ typedef struct ReorderBufferChange #define RBTXN_IS_SERIALIZED_CLEAR 0x0008 #define RBTXN_IS_STREAMED 0x0010 #define RBTXN_HAS_PARTIAL_CHANGE 0x0020 -#define RBTXN_PREPARE 0x0040 +#define RBTXN_IS_PREPARED 0x0040 #define RBTXN_SKIPPED_PREPARE 0x0080 #define RBTXN_HAS_STREAMABLE_CHANGE 0x0100 +#define RBTXN_SENT_PREPARE 0x0200 +#define RBTXN_IS_COMMITTED 0x0400 +#define RBTXN_IS_ABORTED 0x0800 +#define RBTXN_DISTR_INVAL_OVERFLOWED 0x1000 + +#define RBTXN_PREPARE_STATUS_MASK (RBTXN_IS_PREPARED | RBTXN_SKIPPED_PREPARE | RBTXN_SENT_PREPARE) /* Does the transaction have catalog changes? */ #define rbtxn_has_catalog_changes(txn) \ @@ -193,7 +204,7 @@ typedef struct ReorderBufferChange ((txn)->txn_flags & RBTXN_IS_SERIALIZED_CLEAR) != 0 \ ) -/* Has this transaction contains partial changes? */ +/* Does this transaction contain partial changes? */ #define rbtxn_has_partial_change(txn) \ ( \ ((txn)->txn_flags & RBTXN_HAS_PARTIAL_CHANGE) != 0 \ @@ -219,10 +230,34 @@ typedef struct ReorderBufferChange ((txn)->txn_flags & RBTXN_IS_STREAMED) != 0 \ ) -/* Has this transaction been prepared? */ -#define rbtxn_prepared(txn) \ +/* + * Is this a prepared transaction? + * + * Being true means that this transaction should be prepared instead of + * committed. To check whether a prepare or a stream_prepare has already + * been sent for this transaction, we need to use rbtxn_sent_prepare(). + */ +#define rbtxn_is_prepared(txn) \ +( \ + ((txn)->txn_flags & RBTXN_IS_PREPARED) != 0 \ +) + +/* Has a prepare or stream_prepare already been sent? */ +#define rbtxn_sent_prepare(txn) \ +( \ + ((txn)->txn_flags & RBTXN_SENT_PREPARE) != 0 \ +) + +/* Is this transaction committed? */ +#define rbtxn_is_committed(txn) \ ( \ - ((txn)->txn_flags & RBTXN_PREPARE) != 0 \ + ((txn)->txn_flags & RBTXN_IS_COMMITTED) != 0 \ +) + +/* Is this transaction aborted? */ +#define rbtxn_is_aborted(txn) \ +( \ + ((txn)->txn_flags & RBTXN_IS_ABORTED) != 0 \ ) /* prepare for this transaction skipped? */ @@ -231,6 +266,12 @@ typedef struct ReorderBufferChange ((txn)->txn_flags & RBTXN_SKIPPED_PREPARE) != 0 \ ) +/* Is the array of distributed inval messages overflowed? */ +#define rbtxn_distr_inval_overflowed(txn) \ +( \ + ((txn)->txn_flags & RBTXN_DISTR_INVAL_OVERFLOWED) != 0 \ +) + /* Is this a top-level transaction? */ #define rbtxn_is_toptxn(txn) \ ( \ @@ -388,11 +429,16 @@ typedef struct ReorderBufferTXN uint32 ninvalidations; SharedInvalidationMessage *invalidations; + /* + * Stores cache invalidation messages distributed by other transactions. + */ + uint32 ninvalidations_distributed; + SharedInvalidationMessage *invalidations_distributed; + /* --- - * Position in one of three lists: + * Position in one of two lists: * * list of subtransactions if we are *known* to be subxact * * list of toplevel xacts (can be an as-yet unknown subxact) - * * list of preallocated ReorderBufferTXNs (if unused) * --- */ dlist_node node; @@ -415,9 +461,6 @@ typedef struct ReorderBufferTXN /* Size of top-transaction including sub-transactions. */ Size total_size; - /* If we have detected concurrent abort then ignore future changes. */ - bool concurrent_abort; - /* * Private data pointer of the output plugin. */ @@ -478,45 +521,38 @@ typedef void (*ReorderBufferRollbackPreparedCB) (ReorderBuffer *rb, TimestampTz prepare_time); /* start streaming transaction callback signature */ -typedef void (*ReorderBufferStreamStartCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamStartCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr first_lsn); /* stop streaming transaction callback signature */ -typedef void (*ReorderBufferStreamStopCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamStopCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr last_lsn); /* discard streamed transaction callback signature */ -typedef void (*ReorderBufferStreamAbortCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamAbortCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr abort_lsn); /* prepare streamed transaction callback signature */ -typedef void (*ReorderBufferStreamPrepareCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamPrepareCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr prepare_lsn); /* commit streamed transaction callback signature */ -typedef void (*ReorderBufferStreamCommitCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamCommitCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr commit_lsn); /* stream change callback signature */ -typedef void (*ReorderBufferStreamChangeCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamChangeCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change); /* stream message callback signature */ -typedef void (*ReorderBufferStreamMessageCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamMessageCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, @@ -524,16 +560,14 @@ typedef void (*ReorderBufferStreamMessageCB) ( const char *message); /* stream truncate callback signature */ -typedef void (*ReorderBufferStreamTruncateCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferStreamTruncateCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change); /* update progress txn callback signature */ -typedef void (*ReorderBufferUpdateProgressTxnCB) ( - ReorderBuffer *rb, +typedef void (*ReorderBufferUpdateProgressTxnCB) (ReorderBuffer *rb, ReorderBufferTXN *txn, XLogRecPtr lsn); @@ -668,16 +702,15 @@ struct ReorderBuffer extern ReorderBuffer *ReorderBufferAllocate(void); extern void ReorderBufferFree(ReorderBuffer *rb); -extern HeapTuple ReorderBufferGetTupleBuf(ReorderBuffer *rb, - Size tuple_len); -extern void ReorderBufferReturnTupleBuf(HeapTuple tuple); +extern HeapTuple ReorderBufferAllocTupleBuf(ReorderBuffer *rb, Size tuple_len); +extern void ReorderBufferFreeTupleBuf(HeapTuple tuple); -extern ReorderBufferChange *ReorderBufferGetChange(ReorderBuffer *rb); -extern void ReorderBufferReturnChange(ReorderBuffer *rb, - ReorderBufferChange *change, bool upd_mem); +extern ReorderBufferChange *ReorderBufferAllocChange(ReorderBuffer *rb); +extern void ReorderBufferFreeChange(ReorderBuffer *rb, + ReorderBufferChange *change, bool upd_mem); -extern Oid *ReorderBufferGetRelids(ReorderBuffer *rb, int nrelids); -extern void ReorderBufferReturnRelids(ReorderBuffer *rb, Oid *relids); +extern Oid *ReorderBufferAllocRelids(ReorderBuffer *rb, int nrelids); +extern void ReorderBufferFreeRelids(ReorderBuffer *rb, Oid *relids); extern void ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, ReorderBufferChange *change, @@ -718,6 +751,9 @@ extern void ReorderBufferAddNewTupleCids(ReorderBuffer *rb, TransactionId xid, CommandId cmin, CommandId cmax, CommandId combocid); extern void ReorderBufferAddInvalidations(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, Size nmsgs, SharedInvalidationMessage *msgs); +extern void ReorderBufferAddDistributedInvalidations(ReorderBuffer *rb, TransactionId xid, + XLogRecPtr lsn, Size nmsgs, + SharedInvalidationMessage *msgs); extern void ReorderBufferImmediateInvalidation(ReorderBuffer *rb, uint32 ninvalidations, SharedInvalidationMessage *invalidations); extern void ReorderBufferProcessXid(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn); @@ -738,6 +774,10 @@ extern TransactionId *ReorderBufferGetCatalogChangesXacts(ReorderBuffer *rb); extern void ReorderBufferSetRestartPoint(ReorderBuffer *rb, XLogRecPtr ptr); +extern uint32 ReorderBufferGetInvalidations(ReorderBuffer *rb, + TransactionId xid, + SharedInvalidationMessage **msgs); + extern void StartupReorderBuffer(void); #endif diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h index c2ee149fd6668..ffacba9d2ae52 100644 --- a/src/include/replication/slot.h +++ b/src/include/replication/slot.h @@ -2,7 +2,7 @@ * slot.h * Replication slot management. * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * *------------------------------------------------------------------------- */ @@ -17,6 +17,9 @@ #include "storage/spin.h" #include "replication/walreceiver.h" +/* directory to store replication slot data in */ +#define PG_REPLSLOT_DIR "pg_replslot" + /* * Behaviour of replication slots, upon release or crash. * @@ -41,21 +44,25 @@ typedef enum ReplicationSlotPersistency * Slots can be invalidated, e.g. due to max_slot_wal_keep_size. If so, the * 'invalidated' field is set to a value other than _NONE. * - * When adding a new invalidation cause here, remember to update - * SlotInvalidationCauses and RS_INVAL_MAX_CAUSES. + * When adding a new invalidation cause here, the value must be powers of 2 + * (e.g., 1, 2, 4...) for proper bitwise operations. Also, remember to update + * RS_INVAL_MAX_CAUSES below, and SlotInvalidationCauses in slot.c. */ typedef enum ReplicationSlotInvalidationCause { - RS_INVAL_NONE, + RS_INVAL_NONE = 0, /* required WAL has been removed */ - RS_INVAL_WAL_REMOVED, + RS_INVAL_WAL_REMOVED = (1 << 0), /* required rows have been removed */ - RS_INVAL_HORIZON, + RS_INVAL_HORIZON = (1 << 1), /* wal_level insufficient for slot */ - RS_INVAL_WAL_LEVEL, + RS_INVAL_WAL_LEVEL = (1 << 2), + /* idle slot timeout has occurred */ + RS_INVAL_IDLE_TIMEOUT = (1 << 3), } ReplicationSlotInvalidationCause; -extern PGDLLIMPORT const char *const SlotInvalidationCauses[]; +/* Maximum number of invalidation causes */ +#define RS_INVAL_MAX_CAUSES 4 /* * On-Disk data of a replication slot, preserved across restarts. @@ -202,8 +209,20 @@ typedef struct ReplicationSlot */ XLogRecPtr last_saved_confirmed_flush; - /* The time since the slot has become inactive */ + /* + * The time when the slot became inactive. For synced slots on a standby + * server, it represents the time when slot synchronization was most + * recently stopped. + */ TimestampTz inactive_since; + + /* + * Latest restart_lsn that has been flushed to disk. For persistent slots + * the flushed LSN should be taken into account when calculating the + * oldest LSN for WAL segments removal. + */ + XLogRecPtr last_saved_restart_lsn; + } ReplicationSlot; #define SlotIsPhysical(slot) ((slot)->data.database == InvalidOid) @@ -221,6 +240,23 @@ typedef struct ReplicationSlotCtlData ReplicationSlot replication_slots[1]; } ReplicationSlotCtlData; +/* + * Set slot's inactive_since property unless it was previously invalidated. + */ +static inline void +ReplicationSlotSetInactiveSince(ReplicationSlot *s, TimestampTz ts, + bool acquire_lock) +{ + if (acquire_lock) + SpinLockAcquire(&s->mutex); + + if (s->data.invalidated == RS_INVAL_NONE) + s->inactive_since = ts; + + if (acquire_lock) + SpinLockRelease(&s->mutex); +} + /* * Pointers to shared memory */ @@ -230,6 +266,7 @@ extern PGDLLIMPORT ReplicationSlot *MyReplicationSlot; /* GUCs */ extern PGDLLIMPORT int max_replication_slots; extern PGDLLIMPORT char *synchronized_standby_slots; +extern PGDLLIMPORT int idle_replication_slot_timeout_mins; /* shmem initialization functions */ extern Size ReplicationSlotsShmemSize(void); @@ -246,7 +283,8 @@ extern void ReplicationSlotDropAcquired(void); extern void ReplicationSlotAlter(const char *name, const bool *failover, const bool *two_phase); -extern void ReplicationSlotAcquire(const char *name, bool nowait); +extern void ReplicationSlotAcquire(const char *name, bool nowait, + bool error_if_invalid); extern void ReplicationSlotRelease(void); extern void ReplicationSlotCleanup(bool synced_only); extern void ReplicationSlotSave(void); @@ -261,7 +299,7 @@ extern void ReplicationSlotsComputeRequiredLSN(void); extern XLogRecPtr ReplicationSlotsComputeLogicalRestartLSN(void); extern bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive); extern void ReplicationSlotsDropDBSlots(Oid dboid); -extern bool InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, +extern bool InvalidateObsoleteReplicationSlots(uint32 possible_causes, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon); @@ -277,7 +315,8 @@ extern void CheckPointReplicationSlots(bool is_shutdown); extern void CheckSlotRequirements(void); extern void CheckSlotPermissions(void); extern ReplicationSlotInvalidationCause - GetSlotInvalidationCause(const char *invalidation_reason); + GetSlotInvalidationCause(const char *cause_name); +extern const char *GetSlotInvalidationCauseName(ReplicationSlotInvalidationCause cause); extern bool SlotExistsInSyncStandbySlots(const char *slot_name); extern bool StandbySlotsHaveCaughtup(XLogRecPtr wait_for_lsn, int elevel); diff --git a/src/include/replication/slotsync.h b/src/include/replication/slotsync.h index e03c2a005a429..16b721463dde6 100644 --- a/src/include/replication/slotsync.h +++ b/src/include/replication/slotsync.h @@ -3,7 +3,7 @@ * slotsync.h * Exports for slot synchronization. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/replication/slotsync.h * @@ -26,7 +26,7 @@ extern PGDLLIMPORT char *PrimarySlotName; extern char *CheckAndGetDbnameFromConninfo(void); extern bool ValidateSlotSyncParams(int elevel); -extern void ReplSlotSyncWorkerMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +pg_noreturn extern void ReplSlotSyncWorkerMain(const void *startup_data, size_t startup_data_len); extern void ShutDownSlotSync(void); extern bool SlotSyncWorkerCanRestart(void); diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h index caa5113ff81a8..44031dcf6e368 100644 --- a/src/include/replication/snapbuild.h +++ b/src/include/replication/snapbuild.h @@ -3,7 +3,7 @@ * snapbuild.h * Exports from replication/logical/snapbuild.c. * - * Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Copyright (c) 2012-2025, PostgreSQL Global Development Group * * src/include/replication/snapbuild.h * @@ -15,6 +15,10 @@ #include "access/xlogdefs.h" #include "utils/snapmgr.h" +/* + * Please keep get_snapbuild_state_desc() (located in the pg_logicalinspect + * module) updated if a change needs to be made to SnapBuildState. + */ typedef enum { /* @@ -46,7 +50,7 @@ typedef enum SNAPBUILD_CONSISTENT = 2, } SnapBuildState; -/* forward declare so we don't have to expose the struct to the public */ +/* forward declare so we don't have to include snapbuild_internal.h */ struct SnapBuild; typedef struct SnapBuild SnapBuild; diff --git a/src/include/replication/snapbuild_internal.h b/src/include/replication/snapbuild_internal.h new file mode 100644 index 0000000000000..3b915dc8793b8 --- /dev/null +++ b/src/include/replication/snapbuild_internal.h @@ -0,0 +1,199 @@ +/*------------------------------------------------------------------------- + * + * snapbuild_internal.h + * This file contains declarations for logical decoding utility + * functions for internal use. + * + * Copyright (c) 2024-2025, PostgreSQL Global Development Group + * + * src/include/replication/snapbuild_internal.h + * + *------------------------------------------------------------------------- + */ + +#ifndef SNAPBUILD_INTERNAL_H +#define SNAPBUILD_INTERNAL_H + +#include "port/pg_crc32c.h" +#include "replication/reorderbuffer.h" +#include "replication/snapbuild.h" + +/* + * This struct contains the current state of the snapshot building + * machinery. It is exposed to the public, so pay attention when changing its + * contents. + */ +struct SnapBuild +{ + /* how far are we along building our first full snapshot */ + SnapBuildState state; + + /* private memory context used to allocate memory for this module. */ + MemoryContext context; + + /* all transactions < than this have committed/aborted */ + TransactionId xmin; + + /* all transactions >= than this are uncommitted */ + TransactionId xmax; + + /* + * Don't replay commits from an LSN < this LSN. This can be set externally + * but it will also be advanced (never retreat) from within snapbuild.c. + */ + XLogRecPtr start_decoding_at; + + /* + * LSN at which two-phase decoding was enabled or LSN at which we found a + * consistent point at the time of slot creation. + * + * The prepared transactions, that were skipped because previously + * two-phase was not enabled or are not covered by initial snapshot, need + * to be sent later along with commit prepared and they must be before + * this point. + */ + XLogRecPtr two_phase_at; + + /* + * Don't start decoding WAL until the "xl_running_xacts" information + * indicates there are no running xids with an xid smaller than this. + */ + TransactionId initial_xmin_horizon; + + /* Indicates if we are building full snapshot or just catalog one. */ + bool building_full_snapshot; + + /* + * Indicates if we are using the snapshot builder for the creation of a + * logical replication slot. If it's true, the start point for decoding + * changes is not determined yet. So we skip snapshot restores to properly + * find the start point. See SnapBuildFindSnapshot() for details. + */ + bool in_slot_creation; + + /* + * Snapshot that's valid to see the catalog state seen at this moment. + */ + Snapshot snapshot; + + /* + * LSN of the last location we are sure a snapshot has been serialized to. + */ + XLogRecPtr last_serialized_snapshot; + + /* + * The reorderbuffer we need to update with usable snapshots et al. + */ + ReorderBuffer *reorder; + + /* + * TransactionId at which the next phase of initial snapshot building will + * happen. InvalidTransactionId if not known (i.e. SNAPBUILD_START), or + * when no next phase necessary (SNAPBUILD_CONSISTENT). + */ + TransactionId next_phase_at; + + /* + * Array of transactions which could have catalog changes that committed + * between xmin and xmax. + */ + struct + { + /* number of committed transactions */ + size_t xcnt; + + /* available space for committed transactions */ + size_t xcnt_space; + + /* + * Until we reach a CONSISTENT state, we record commits of all + * transactions, not just the catalog changing ones. Record when that + * changes so we know we cannot export a snapshot safely anymore. + */ + bool includes_all_transactions; + + /* + * Array of committed transactions that have modified the catalog. + * + * As this array is frequently modified we do *not* keep it in + * xidComparator order. Instead we sort the array when building & + * distributing a snapshot. + * + * TODO: It's unclear whether that reasoning has much merit. Every + * time we add something here after becoming consistent will also + * require distributing a snapshot. Storing them sorted would + * potentially also make it easier to purge (but more complicated wrt + * wraparound?). Should be improved if sorting while building the + * snapshot shows up in profiles. + */ + TransactionId *xip; + } committed; + + /* + * Array of transactions and subtransactions that had modified catalogs + * and were running when the snapshot was serialized. + * + * We normally rely on some WAL record types such as HEAP2_NEW_CID to know + * if the transaction has changed the catalog. But it could happen that + * the logical decoding decodes only the commit record of the transaction + * after restoring the previously serialized snapshot in which case we + * will miss adding the xid to the snapshot and end up looking at the + * catalogs with the wrong snapshot. + * + * Now to avoid the above problem, we serialize the transactions that had + * modified the catalogs and are still running at the time of snapshot + * serialization. We fill this array while restoring the snapshot and then + * refer it while decoding commit to ensure if the xact has modified the + * catalog. We discard this array when all the xids in the list become old + * enough to matter. See SnapBuildPurgeOlderTxn for details. + */ + struct + { + /* number of transactions */ + size_t xcnt; + + /* This array must be sorted in xidComparator order */ + TransactionId *xip; + } catchange; +}; + +/* ----------------------------------- + * Snapshot serialization support + * ----------------------------------- + */ + +/* + * We store current state of struct SnapBuild on disk in the following manner: + * + * struct SnapBuildOnDisk; + * TransactionId * committed.xcnt; (*not xcnt_space*) + * TransactionId * catchange.xcnt; + * + * Check if the SnapBuildOnDiskConstantSize and SnapBuildOnDiskNotChecksummedSize + * macros need to be updated when modifying the SnapBuildOnDisk struct. + */ +typedef struct SnapBuildOnDisk +{ + /* first part of this struct needs to be version independent */ + + /* data not covered by checksum */ + uint32 magic; + pg_crc32c checksum; + + /* data covered by checksum */ + + /* version, in case we want to support pg_upgrade */ + uint32 version; + /* how large is the on disk data, excluding the constant sized part */ + uint32 length; + + /* version dependent part */ + SnapBuild builder; + + /* variable amount of TransactionIds follows */ +} SnapBuildOnDisk; + +extern bool SnapBuildRestoreSnapshot(SnapBuildOnDisk *ondisk, XLogRecPtr lsn, + MemoryContext context, bool missing_ok); + +#endif /* SNAPBUILD_INTERNAL_H */ diff --git a/src/include/replication/syncrep.h b/src/include/replication/syncrep.h index ea439e6da6004..675669a79f7d3 100644 --- a/src/include/replication/syncrep.h +++ b/src/include/replication/syncrep.h @@ -3,7 +3,7 @@ * syncrep.h * Exports from replication/syncrep.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/replication/syncrep.h @@ -73,10 +73,6 @@ typedef struct SyncRepConfigData extern PGDLLIMPORT SyncRepConfigData *SyncRepConfig; -/* communication variables for parsing synchronous_standby_names GUC */ -extern PGDLLIMPORT SyncRepConfigData *syncrep_parse_result; -extern PGDLLIMPORT char *syncrep_parse_error_msg; - /* user-settable parameters for synchronous replication */ extern PGDLLIMPORT char *SyncRepStandbyNames; @@ -100,10 +96,15 @@ extern void SyncRepUpdateSyncStandbysDefined(void); * Internal functions for parsing synchronous_standby_names grammar, * in syncrep_gram.y and syncrep_scanner.l */ -extern int syncrep_yyparse(void); -extern int syncrep_yylex(void); -extern void syncrep_yyerror(const char *str); -extern void syncrep_scanner_init(const char *str); -extern void syncrep_scanner_finish(void); +union YYSTYPE; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif +extern int syncrep_yyparse(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner); +extern int syncrep_yylex(union YYSTYPE *yylval_param, char **syncrep_parse_error_msg_p, yyscan_t yyscanner); +extern void syncrep_yyerror(SyncRepConfigData **syncrep_parse_result_p, char **syncrep_parse_error_msg_p, yyscan_t yyscanner, const char *str); +extern void syncrep_scanner_init(const char *str, yyscan_t *yyscannerp); +extern void syncrep_scanner_finish(yyscan_t yyscanner); #endif /* _SYNCREP_H */ diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h index 132e789948bb9..89f63f908f8a8 100644 --- a/src/include/replication/walreceiver.h +++ b/src/include/replication/walreceiver.h @@ -3,7 +3,7 @@ * walreceiver.h * Exports from replication/walreceiverfuncs.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/replication/walreceiver.h * @@ -21,7 +21,6 @@ #include "replication/logicalproto.h" #include "replication/walsender.h" #include "storage/condition_variable.h" -#include "storage/latch.h" #include "storage/spin.h" #include "utils/tuplestore.h" @@ -58,13 +57,24 @@ typedef enum typedef struct { /* - * PID of currently active walreceiver process, its current state and - * start time (actually, the time at which it was requested to be - * started). + * Currently active walreceiver process's proc number and PID. + * + * The startup process uses the proc number to wake it up after telling it + * where to start streaming (after setting receiveStart and + * receiveStartTLI), and also to tell it to send apply feedback to the + * primary whenever specially marked commit records are applied. */ + ProcNumber procno; pid_t pid; + + /* Its current state */ WalRcvState walRcvState; ConditionVariable walRcvStoppedCV; + + /* + * Its start time (actually, the time at which it was requested to be + * started). + */ pg_time_t startTime; /* @@ -134,15 +144,6 @@ typedef struct /* set true once conninfo is ready to display (obfuscated pwds etc) */ bool ready_to_display; - /* - * Latch used by startup process to wake up walreceiver after telling it - * where to start streaming (after setting receiveStart and - * receiveStartTLI), and also to tell it to send apply feedback to the - * primary whenever specially marked commit records are applied. This is - * normally mapped to procLatch when walreceiver is running. - */ - Latch *latch; - slock_t mutex; /* locks shared variables shown above */ /* @@ -485,8 +486,7 @@ walrcv_clear_result(WalRcvExecResult *walres) } /* prototypes for functions in walreceiver.c */ -extern void WalReceiverMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); -extern void ProcessWalRcvInterrupts(void); +pg_noreturn extern void WalReceiverMain(const void *startup_data, size_t startup_data_len); extern void WalRcvForceReply(void); /* prototypes for functions in walreceiverfuncs.c */ diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h index f2d8297f016ea..c3e8e19133951 100644 --- a/src/include/replication/walsender.h +++ b/src/include/replication/walsender.h @@ -3,7 +3,7 @@ * walsender.h * Exports from replication/walsender.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/replication/walsender.h * @@ -38,7 +38,6 @@ extern PGDLLIMPORT bool log_replication_commands; extern void InitWalSender(void); extern bool exec_replication_command(const char *cmd_string); extern void WalSndErrorCleanup(void); -extern void WalSndResourceCleanup(bool isCommit); extern void PhysicalWakeupLogicalWalSnd(void); extern XLogRecPtr GetStandbyFlushRecPtr(TimeLineID *tli); extern void WalSndSignals(void); diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h index cf32ac2488a8d..e98701038f506 100644 --- a/src/include/replication/walsender_private.h +++ b/src/include/replication/walsender_private.h @@ -3,7 +3,7 @@ * walsender_private.h * Private definitions from replication/walsender.c. * - * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2025, PostgreSQL Global Development Group * * src/include/replication/walsender_private.h * @@ -18,7 +18,6 @@ #include "nodes/replnodes.h" #include "replication/syncrep.h" #include "storage/condition_variable.h" -#include "storage/latch.h" #include "storage/shmem.h" #include "storage/spin.h" @@ -71,12 +70,6 @@ typedef struct WalSnd /* Protects shared variables in this structure. */ slock_t mutex; - /* - * Pointer to the walsender's latch. Used by backends to wake up this - * walsender when it has work to do. NULL if the walsender isn't active. - */ - Latch *latch; - /* * Timestamp of the last message received from standby. */ @@ -103,11 +96,11 @@ typedef struct XLogRecPtr lsn[NUM_SYNC_REP_WAIT_MODE]; /* - * Are any sync standbys defined? Waiting backends can't reload the - * config file safely, so checkpointer updates this value as needed. - * Protected by SyncRepLock. + * Status of data related to the synchronous standbys. Waiting backends + * can't reload the config file safely, so checkpointer updates this value + * as needed. Protected by SyncRepLock. */ - bool sync_standbys_defined; + bits8 sync_standbys_status; /* used as a registry of physical / logical walsenders to wake */ ConditionVariable wal_flush_cv; @@ -123,6 +116,21 @@ typedef struct WalSnd walsnds[FLEXIBLE_ARRAY_MEMBER]; } WalSndCtlData; +/* Flags for WalSndCtlData->sync_standbys_status */ + +/* + * Is the synchronous standby data initialized from the GUC? This is set the + * first time synchronous_standby_names is processed by the checkpointer. + */ +#define SYNC_STANDBY_INIT (1 << 0) + +/* + * Is the synchronous standby data defined? This is set when + * synchronous_standby_names has some data, after being processed by the + * checkpointer. + */ +#define SYNC_STANDBY_DEFINED (1 << 1) + extern PGDLLIMPORT WalSndCtlData *WalSndCtl; @@ -132,13 +140,16 @@ extern void WalSndSetState(WalSndState state); * Internal functions for parsing the replication grammar, in repl_gram.y and * repl_scanner.l */ -extern int replication_yyparse(void); -extern int replication_yylex(void); -extern void replication_yyerror(const char *message) pg_attribute_noreturn(); -extern void replication_scanner_init(const char *str); -extern void replication_scanner_finish(void); -extern bool replication_scanner_is_replication_command(void); - -extern PGDLLIMPORT Node *replication_parse_result; +union YYSTYPE; +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif +extern int replication_yyparse(Node **replication_parse_result_p, yyscan_t yyscanner); +extern int replication_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner); +pg_noreturn extern void replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message); +extern void replication_scanner_init(const char *str, yyscan_t *yyscannerp); +extern void replication_scanner_finish(yyscan_t yyscanner); +extern bool replication_scanner_is_replication_command(yyscan_t yyscanner); #endif /* _WALSENDER_PRIVATE_H */ diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h index 9646261d7e999..30b2775952c38 100644 --- a/src/include/replication/worker_internal.h +++ b/src/include/replication/worker_internal.h @@ -3,7 +3,7 @@ * worker_internal.h * Internal headers shared by logical replication workers. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * src/include/replication/worker_internal.h * diff --git a/src/include/rewrite/prs2lock.h b/src/include/rewrite/prs2lock.h index fcc9beb0c92d9..17f468b351245 100644 --- a/src/include/rewrite/prs2lock.h +++ b/src/include/rewrite/prs2lock.h @@ -3,7 +3,7 @@ * prs2lock.h * data structures for POSTGRES Rule System II (rewrite rules only) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/prs2lock.h diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h index 30569a1fde1c1..63842e08649e0 100644 --- a/src/include/rewrite/rewriteDefine.h +++ b/src/include/rewrite/rewriteDefine.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteDefine.h diff --git a/src/include/rewrite/rewriteHandler.h b/src/include/rewrite/rewriteHandler.h index 1b65cda71cfc7..99cab1a3bfad6 100644 --- a/src/include/rewrite/rewriteHandler.h +++ b/src/include/rewrite/rewriteHandler.h @@ -4,7 +4,7 @@ * External interface to query rewriter. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteHandler.h @@ -38,4 +38,7 @@ extern void error_view_not_updatable(Relation view, List *mergeActionList, const char *detail); +extern Node *expand_generated_columns_in_expr(Node *node, Relation rel, int rt_index); +extern Node *build_generation_expression(Relation rel, int attrno); + #endif /* REWRITEHANDLER_H */ diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h index ac6d2049e8006..7c018f2a4e358 100644 --- a/src/include/rewrite/rewriteManip.h +++ b/src/include/rewrite/rewriteManip.h @@ -4,7 +4,7 @@ * Querytree manipulation subroutines for query rewriter. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteManip.h @@ -15,6 +15,7 @@ #define REWRITEMANIP_H #include "nodes/parsenodes.h" +#include "nodes/pathnodes.h" struct AttrMap; /* avoid including attmap.h here */ @@ -40,12 +41,30 @@ typedef enum ReplaceVarsNoMatchOption REPLACEVARS_SUBSTITUTE_NULL, /* replace with a NULL Const */ } ReplaceVarsNoMatchOption; +typedef struct ChangeVarNodes_context ChangeVarNodes_context; +typedef bool (*ChangeVarNodes_callback) (Node *node, + ChangeVarNodes_context *arg); + +struct ChangeVarNodes_context +{ + int rt_index; + int new_index; + int sublevels_up; + ChangeVarNodes_callback callback; +}; + +extern Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); extern void CombineRangeTables(List **dst_rtable, List **dst_perminfos, List *src_rtable, List *src_perminfos); extern void OffsetVarNodes(Node *node, int offset, int sublevels_up); extern void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up); +extern void ChangeVarNodesExtended(Node *node, int rt_index, int new_index, + int sublevels_up, + ChangeVarNodes_callback callback); +extern bool ChangeVarNodesWalkExpression(Node *node, + ChangeVarNodes_context *context); extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up); extern void IncrementVarSublevelsUp_rtable(List *rtable, @@ -85,10 +104,17 @@ extern Node *map_variable_attnos(Node *node, const struct AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row); +extern Node *ReplaceVarFromTargetList(Var *var, + RangeTblEntry *target_rte, + List *targetlist, + int result_relation, + ReplaceVarsNoMatchOption nomatch_option, + int nomatch_varno); extern Node *ReplaceVarsFromTargetList(Node *node, int target_varno, int sublevels_up, RangeTblEntry *target_rte, List *targetlist, + int result_relation, ReplaceVarsNoMatchOption nomatch_option, int nomatch_varno, bool *outer_hasSubLinks); diff --git a/src/include/rewrite/rewriteRemove.h b/src/include/rewrite/rewriteRemove.h index fb439e88babeb..3caa1c4296367 100644 --- a/src/include/rewrite/rewriteRemove.h +++ b/src/include/rewrite/rewriteRemove.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteRemove.h diff --git a/src/include/rewrite/rewriteSearchCycle.h b/src/include/rewrite/rewriteSearchCycle.h index ce809731b404c..9ed456dcd0527 100644 --- a/src/include/rewrite/rewriteSearchCycle.h +++ b/src/include/rewrite/rewriteSearchCycle.h @@ -4,7 +4,7 @@ * Support for rewriting SEARCH and CYCLE clauses. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteSearchCycle.h diff --git a/src/include/rewrite/rewriteSupport.h b/src/include/rewrite/rewriteSupport.h index 381713554844c..50f5af211e029 100644 --- a/src/include/rewrite/rewriteSupport.h +++ b/src/include/rewrite/rewriteSupport.h @@ -4,7 +4,7 @@ * * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/rewrite/rewriteSupport.h diff --git a/src/include/rewrite/rowsecurity.h b/src/include/rewrite/rowsecurity.h index 1717ed4e5e82a..8f81c40a2898b 100644 --- a/src/include/rewrite/rowsecurity.h +++ b/src/include/rewrite/rowsecurity.h @@ -5,7 +5,7 @@ * prototypes for rewrite/rowsecurity.c and the structures for managing * the row security policies for relations in relcache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * ------------------------------------------------------------------------- diff --git a/src/include/snowball/header.h b/src/include/snowball/header.h index 0495fd53b6310..84dc8280851ea 100644 --- a/src/include/snowball/header.h +++ b/src/include/snowball/header.h @@ -13,7 +13,7 @@ * * NOTE: this file should not be included into any non-snowball sources! * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/snowball/header.h * @@ -38,7 +38,7 @@ #endif /* Now we can include the original Snowball header.h */ -#include "snowball/libstemmer/header.h" /* pgrminclude ignore */ +#include "snowball/libstemmer/header.h" /* * Redefine standard memory allocation interface to pgsql's one. diff --git a/src/include/snowball/libstemmer/header.h b/src/include/snowball/libstemmer/header.h index ef5a5464067e9..bf172d5b9bdf9 100644 --- a/src/include/snowball/libstemmer/header.h +++ b/src/include/snowball/libstemmer/header.h @@ -45,7 +45,7 @@ extern int eq_v_b(struct SN_env * z, const symbol * p); extern int find_among(struct SN_env * z, const struct among * v, int v_size); extern int find_among_b(struct SN_env * z, const struct among * v, int v_size); -extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int * adjptr); +extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int * adjustment); extern int slice_from_s(struct SN_env * z, int s_size, const symbol * s); extern int slice_from_v(struct SN_env * z, const symbol * p); extern int slice_del(struct SN_env * z); diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h b/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h deleted file mode 100644 index a7acc38e17d46..0000000000000 --- a/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Generated by Snowball 2.2.0 - https://snowballstem.org/ */ - -#ifdef __cplusplus -extern "C" { -#endif - -extern struct SN_env * romanian_ISO_8859_2_create_env(void); -extern void romanian_ISO_8859_2_close_env(struct SN_env * z); - -extern int romanian_ISO_8859_2_stem(struct SN_env * z); - -#ifdef __cplusplus -} -#endif - diff --git a/src/include/snowball/libstemmer/stem_UTF_8_estonian.h b/src/include/snowball/libstemmer/stem_UTF_8_estonian.h new file mode 100644 index 0000000000000..9b9deb18a0ebe --- /dev/null +++ b/src/include/snowball/libstemmer/stem_UTF_8_estonian.h @@ -0,0 +1,15 @@ +/* Generated by Snowball 2.2.0 - https://snowballstem.org/ */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct SN_env * estonian_UTF_8_create_env(void); +extern void estonian_UTF_8_close_env(struct SN_env * z); + +extern int estonian_UTF_8_stem(struct SN_env * z); + +#ifdef __cplusplus +} +#endif + diff --git a/src/include/statistics/extended_stats_internal.h b/src/include/statistics/extended_stats_internal.h index 8eed9b338d4db..efcb7dc35461e 100644 --- a/src/include/statistics/extended_stats_internal.h +++ b/src/include/statistics/extended_stats_internal.h @@ -3,7 +3,7 @@ * extended_stats_internal.h * POSTGRES extended statistics internal declarations * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h new file mode 100644 index 0000000000000..512eb776e0e04 --- /dev/null +++ b/src/include/statistics/stat_utils.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------- + * + * stat_utils.h + * Extended statistics and selectivity estimation functions. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/statistics/stat_utils.h + * + *------------------------------------------------------------------------- + */ +#ifndef STATS_UTILS_H +#define STATS_UTILS_H + +#include "fmgr.h" + +struct StatsArgInfo +{ + const char *argname; + Oid argtype; +}; + +extern void stats_check_required_arg(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, + int argnum); +extern bool stats_check_arg_array(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, int argnum); +extern bool stats_check_arg_pair(FunctionCallInfo fcinfo, + struct StatsArgInfo *arginfo, + int argnum1, int argnum2); + +extern void stats_lock_check_privileges(Oid reloid); + +extern Oid stats_lookup_relid(const char *nspname, const char *relname); + +extern bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, + FunctionCallInfo positional_fcinfo, + struct StatsArgInfo *arginfo); + +#endif /* STATS_UTILS_H */ diff --git a/src/include/statistics/statistics.h b/src/include/statistics/statistics.h index 7f2bf18716d48..7dd0f9755454a 100644 --- a/src/include/statistics/statistics.h +++ b/src/include/statistics/statistics.h @@ -3,7 +3,7 @@ * statistics.h * Extended statistics and selectivity estimation functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/statistics/statistics.h diff --git a/src/include/storage/aio.h b/src/include/storage/aio.h new file mode 100644 index 0000000000000..e7a0a234b6cf2 --- /dev/null +++ b/src/include/storage/aio.h @@ -0,0 +1,369 @@ +/*------------------------------------------------------------------------- + * + * aio.h + * Main AIO interface + * + * This is the header to include when actually issuing AIO. When just + * declaring functions involving an AIO related type, it might suffice to + * include aio_types.h. Initialization related functions are in the dedicated + * aio_init.h. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/aio.h + * + *------------------------------------------------------------------------- + */ +#ifndef AIO_H +#define AIO_H + +#include "storage/aio_types.h" +#include "storage/procnumber.h" + + +/* io_uring is incompatible with EXEC_BACKEND */ +#if defined(USE_LIBURING) && !defined(EXEC_BACKEND) +#define IOMETHOD_IO_URING_ENABLED +#endif + + +/* Enum for io_method GUC. */ +typedef enum IoMethod +{ + IOMETHOD_SYNC = 0, + IOMETHOD_WORKER, +#ifdef IOMETHOD_IO_URING_ENABLED + IOMETHOD_IO_URING, +#endif +} IoMethod; + +/* We'll default to worker based execution. */ +#define DEFAULT_IO_METHOD IOMETHOD_WORKER + + +/* + * Flags for an IO that can be set with pgaio_io_set_flag(). + */ +typedef enum PgAioHandleFlags +{ + /* + * The IO references backend local memory. + * + * This needs to be set on an IO whenever the IO references process-local + * memory. Some IO methods do not support executing IO that references + * process local memory and thus need to fall back to executing IO + * synchronously for IOs with this flag set. + * + * Required for correctness. + */ + PGAIO_HF_REFERENCES_LOCAL = 1 << 1, + + /* + * Hint that IO will be executed synchronously. + * + * This can make it a bit cheaper to execute synchronous IO via the AIO + * interface, to avoid needing an AIO and non-AIO version of code. + * + * Advantageous to set, if applicable, but not required for correctness. + */ + PGAIO_HF_SYNCHRONOUS = 1 << 0, + + /* + * IO is using buffered IO, used to control heuristic in some IO methods. + * + * Advantageous to set, if applicable, but not required for correctness. + */ + PGAIO_HF_BUFFERED = 1 << 2, +} PgAioHandleFlags; + +/* + * The IO operations supported by the AIO subsystem. + * + * This could be in aio_internal.h, as it is not publicly referenced, but + * PgAioOpData currently *does* need to be public, therefore keeping this + * public seems to make sense. + */ +typedef enum PgAioOp +{ + /* intentionally the zero value, to help catch zeroed memory etc */ + PGAIO_OP_INVALID = 0, + + PGAIO_OP_READV, + PGAIO_OP_WRITEV, + + /** + * In the near term we'll need at least: + * - fsync / fdatasync + * - flush_range + * + * Eventually we'll additionally want at least: + * - send + * - recv + * - accept + **/ +} PgAioOp; + +#define PGAIO_OP_COUNT (PGAIO_OP_WRITEV + 1) + + +/* + * On what is IO being performed? + * + * PgAioTargetID specific behaviour should be implemented in + * aio_target.c. + */ +typedef enum PgAioTargetID +{ + /* intentionally the zero value, to help catch zeroed memory etc */ + PGAIO_TID_INVALID = 0, + PGAIO_TID_SMGR, +} PgAioTargetID; + +#define PGAIO_TID_COUNT (PGAIO_TID_SMGR + 1) + + +/* + * Data necessary for support IO operations (see PgAioOp). + * + * NB: Note that the FDs in here may *not* be relied upon for re-issuing + * requests (e.g. for partial reads/writes or in an IO worker) - the FD might + * be from another process, or closed since. That's not a problem for staged + * IOs, as all staged IOs are submitted when closing an FD. + */ +typedef union +{ + struct + { + int fd; + uint16 iov_length; + uint64 offset; + } read; + + struct + { + int fd; + uint16 iov_length; + uint64 offset; + } write; +} PgAioOpData; + + +/* + * Information the object that IO is executed on. Mostly callbacks that + * operate on PgAioTargetData. + * + * typedef is in aio_types.h + */ +struct PgAioTargetInfo +{ + /* + * To support executing using worker processes, the file descriptor for an + * IO may need to be reopened in a different process. + */ + void (*reopen) (PgAioHandle *ioh); + + /* describe the target of the IO, used for log messages and views */ + char *(*describe_identity) (const PgAioTargetData *sd); + + /* name of the target, used in log messages / views */ + const char *name; +}; + + +/* + * IDs for callbacks that can be registered on an IO. + * + * Callbacks are identified by an ID rather than a function pointer. There are + * two main reasons: + * + * 1) Memory within PgAioHandle is precious, due to the number of PgAioHandle + * structs in pre-allocated shared memory. + * + * 2) Due to EXEC_BACKEND function pointers are not necessarily stable between + * different backends, therefore function pointers cannot directly be in + * shared memory. + * + * Without 2), we could fairly easily allow to add new callbacks, by filling a + * ID->pointer mapping table on demand. In the presence of 2 that's still + * doable, but harder, because every process has to re-register the pointers + * so that a local ID->"backend local pointer" mapping can be maintained. + */ +typedef enum PgAioHandleCallbackID +{ + PGAIO_HCB_INVALID = 0, + + PGAIO_HCB_MD_READV, + + PGAIO_HCB_SHARED_BUFFER_READV, + + PGAIO_HCB_LOCAL_BUFFER_READV, +} PgAioHandleCallbackID; + +#define PGAIO_HCB_MAX PGAIO_HCB_LOCAL_BUFFER_READV +StaticAssertDecl(PGAIO_HCB_MAX <= (1 << PGAIO_RESULT_ID_BITS), + "PGAIO_HCB_MAX is too big for PGAIO_RESULT_ID_BITS"); + + +typedef void (*PgAioHandleCallbackStage) (PgAioHandle *ioh, uint8 cb_flags); +typedef PgAioResult (*PgAioHandleCallbackComplete) (PgAioHandle *ioh, PgAioResult prior_result, uint8 cb_flags); +typedef void (*PgAioHandleCallbackReport) (PgAioResult result, const PgAioTargetData *target_data, int elevel); + +/* typedef is in aio_types.h */ +struct PgAioHandleCallbacks +{ + /* + * Prepare resources affected by the IO for execution. This could e.g. + * include moving ownership of buffer pins to the AIO subsystem. + */ + PgAioHandleCallbackStage stage; + + /* + * Update the state of resources affected by the IO to reflect completion + * of the IO. This could e.g. include updating shared buffer state to + * signal the IO has finished. + * + * The _shared suffix indicates that this is executed by the backend that + * completed the IO, which may or may not be the backend that issued the + * IO. Obviously the callback thus can only modify resources in shared + * memory. + * + * The latest registered callback is called first. This allows + * higher-level code to register callbacks that can rely on callbacks + * registered by lower-level code to already have been executed. + * + * NB: This is called in a critical section. Errors can be signalled by + * the callback's return value, it's the responsibility of the IO's issuer + * to react appropriately. + */ + PgAioHandleCallbackComplete complete_shared; + + /* + * Like complete_shared, except called in the issuing backend. + * + * This variant of the completion callback is useful when backend-local + * state has to be updated to reflect the IO's completion. E.g. a + * temporary buffer's BufferDesc isn't accessible in complete_shared. + * + * Local callbacks are only called after complete_shared for all + * registered callbacks has been called. + */ + PgAioHandleCallbackComplete complete_local; + + /* + * Report the result of an IO operation. This is e.g. used to raise an + * error after an IO failed at the appropriate time (i.e. not when the IO + * failed, but under control of the code that issued the IO). + */ + PgAioHandleCallbackReport report; +}; + + + +/* + * How many callbacks can be registered for one IO handle. Currently we only + * need two, but it's not hard to imagine needing a few more. + */ +#define PGAIO_HANDLE_MAX_CALLBACKS 4 + + + +/* -------------------------------------------------------------------------------- + * IO Handles + * -------------------------------------------------------------------------------- + */ + +/* functions in aio.c */ +struct ResourceOwnerData; +extern PgAioHandle *pgaio_io_acquire(struct ResourceOwnerData *resowner, PgAioReturn *ret); +extern PgAioHandle *pgaio_io_acquire_nb(struct ResourceOwnerData *resowner, PgAioReturn *ret); + +extern void pgaio_io_release(PgAioHandle *ioh); +struct dlist_node; +extern void pgaio_io_release_resowner(struct dlist_node *ioh_node, bool on_error); + +extern void pgaio_io_set_flag(PgAioHandle *ioh, PgAioHandleFlags flag); + +extern int pgaio_io_get_id(PgAioHandle *ioh); +extern ProcNumber pgaio_io_get_owner(PgAioHandle *ioh); + +extern void pgaio_io_get_wref(PgAioHandle *ioh, PgAioWaitRef *iow); + +/* functions in aio_io.c */ +struct iovec; +extern int pgaio_io_get_iovec(PgAioHandle *ioh, struct iovec **iov); + +extern PgAioOp pgaio_io_get_op(PgAioHandle *ioh); +extern PgAioOpData *pgaio_io_get_op_data(PgAioHandle *ioh); + +extern void pgaio_io_start_readv(PgAioHandle *ioh, + int fd, int iovcnt, uint64 offset); +extern void pgaio_io_start_writev(PgAioHandle *ioh, + int fd, int iovcnt, uint64 offset); + +/* functions in aio_target.c */ +extern void pgaio_io_set_target(PgAioHandle *ioh, PgAioTargetID targetid); +extern bool pgaio_io_has_target(PgAioHandle *ioh); +extern PgAioTargetData *pgaio_io_get_target_data(PgAioHandle *ioh); +extern char *pgaio_io_get_target_description(PgAioHandle *ioh); + +/* functions in aio_callback.c */ +extern void pgaio_io_register_callbacks(PgAioHandle *ioh, PgAioHandleCallbackID cb_id, + uint8 cb_data); +extern void pgaio_io_set_handle_data_64(PgAioHandle *ioh, uint64 *data, uint8 len); +extern void pgaio_io_set_handle_data_32(PgAioHandle *ioh, uint32 *data, uint8 len); +extern uint64 *pgaio_io_get_handle_data(PgAioHandle *ioh, uint8 *len); + + + +/* -------------------------------------------------------------------------------- + * IO Wait References + * -------------------------------------------------------------------------------- + */ + +extern void pgaio_wref_clear(PgAioWaitRef *iow); +extern bool pgaio_wref_valid(PgAioWaitRef *iow); +extern int pgaio_wref_get_id(PgAioWaitRef *iow); + +extern void pgaio_wref_wait(PgAioWaitRef *iow); +extern bool pgaio_wref_check_done(PgAioWaitRef *iow); + + + +/* -------------------------------------------------------------------------------- + * IO Result + * -------------------------------------------------------------------------------- + */ + +extern void pgaio_result_report(PgAioResult result, const PgAioTargetData *target_data, + int elevel); + + + +/* -------------------------------------------------------------------------------- + * Actions on multiple IOs. + * -------------------------------------------------------------------------------- + */ + +extern void pgaio_enter_batchmode(void); +extern void pgaio_exit_batchmode(void); +extern void pgaio_submit_staged(void); +extern bool pgaio_have_staged(void); + + + +/* -------------------------------------------------------------------------------- + * Other + * -------------------------------------------------------------------------------- + */ + +extern void pgaio_closing_fd(int fd); + + + +/* GUCs */ +extern PGDLLIMPORT int io_method; +extern PGDLLIMPORT int io_max_concurrency; + + +#endif /* AIO_H */ diff --git a/src/include/storage/aio_internal.h b/src/include/storage/aio_internal.h new file mode 100644 index 0000000000000..2d37a243abe52 --- /dev/null +++ b/src/include/storage/aio_internal.h @@ -0,0 +1,410 @@ +/*------------------------------------------------------------------------- + * + * aio_internal.h + * AIO related declarations that should only be used by the AIO subsystem + * internally. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/aio_internal.h + * + *------------------------------------------------------------------------- + */ +#ifndef AIO_INTERNAL_H +#define AIO_INTERNAL_H + + +#include "lib/ilist.h" +#include "port/pg_iovec.h" +#include "storage/aio.h" +#include "storage/condition_variable.h" + + +/* + * The maximum number of IOs that can be batch submitted at once. + */ +#define PGAIO_SUBMIT_BATCH_SIZE 32 + + + +/* + * State machine for handles. With some exceptions, noted below, handles move + * linearly through all states. + * + * State changes should all go through pgaio_io_update_state(). + * + * Note that the externally visible functions to start IO + * (e.g. FileStartReadV(), via pgaio_io_start_readv()) move an IO from + * PGAIO_HS_HANDED_OUT to at least PGAIO_HS_STAGED and at most + * PGAIO_HS_COMPLETED_LOCAL (at which point the handle will be reused). + */ +typedef enum PgAioHandleState +{ + /* not in use */ + PGAIO_HS_IDLE = 0, + + /* + * Returned by pgaio_io_acquire(). The next state is either DEFINED (if + * pgaio_io_start_*() is called), or IDLE (if pgaio_io_release() is + * called). + */ + PGAIO_HS_HANDED_OUT, + + /* + * pgaio_io_start_*() has been called, but IO is not yet staged. At this + * point the handle has all the information for the IO to be executed. + */ + PGAIO_HS_DEFINED, + + /* + * stage() callbacks have been called, handle ready to be submitted for + * execution. Unless in batchmode (see c.f. pgaio_enter_batchmode()), the + * IO will be submitted immediately after. + */ + PGAIO_HS_STAGED, + + /* IO has been submitted to the IO method for execution */ + PGAIO_HS_SUBMITTED, + + /* IO finished, but result has not yet been processed */ + PGAIO_HS_COMPLETED_IO, + + /* + * IO completed, shared completion has been called. + * + * If the IO completion occurs in the issuing backend, local callbacks + * will immediately be called. Otherwise the handle stays in + * COMPLETED_SHARED until the issuing backend waits for the completion of + * the IO. + */ + PGAIO_HS_COMPLETED_SHARED, + + /* + * IO completed, local completion has been called. + * + * After this the handle will be made reusable and go into IDLE state. + */ + PGAIO_HS_COMPLETED_LOCAL, +} PgAioHandleState; + + +struct ResourceOwnerData; + +/* typedef is in aio_types.h */ +struct PgAioHandle +{ + /* all state updates should go through pgaio_io_update_state() */ + PgAioHandleState state:8; + + /* what are we operating on */ + PgAioTargetID target:8; + + /* which IO operation */ + PgAioOp op:8; + + /* bitfield of PgAioHandleFlags */ + uint8 flags; + + uint8 num_callbacks; + + /* using the proper type here would use more space */ + uint8 callbacks[PGAIO_HANDLE_MAX_CALLBACKS]; + + /* data forwarded to each callback */ + uint8 callbacks_data[PGAIO_HANDLE_MAX_CALLBACKS]; + + /* + * Length of data associated with handle using + * pgaio_io_set_handle_data_*(). + */ + uint8 handle_data_len; + + /* XXX: could be optimized out with some pointer math */ + int32 owner_procno; + + /* raw result of the IO operation */ + int32 result; + + /** + * In which list the handle is registered, depends on the state: + * - IDLE, in per-backend list + * - HANDED_OUT - not in a list + * - DEFINED - not in a list + * - STAGED - in per-backend staged array + * - SUBMITTED - in issuer's in_flight list + * - COMPLETED_IO - in issuer's in_flight list + * - COMPLETED_SHARED - in issuer's in_flight list + **/ + dlist_node node; + + struct ResourceOwnerData *resowner; + dlist_node resowner_node; + + /* incremented every time the IO handle is reused */ + uint64 generation; + + /* + * To wait for the IO to complete other backends can wait on this CV. Note + * that, if in SUBMITTED state, a waiter first needs to check if it needs + * to do work via IoMethodOps->wait_one(). + */ + ConditionVariable cv; + + /* result of shared callback, passed to issuer callback */ + PgAioResult distilled_result; + + /* + * Index into PgAioCtl->iovecs and PgAioCtl->handle_data. + * + * At the moment there's no need to differentiate between the two, but + * that won't necessarily stay that way. + */ + uint32 iovec_off; + + /* + * If not NULL, this memory location will be updated with information + * about the IOs completion iff the issuing backend learns about the IOs + * completion. + */ + PgAioReturn *report_return; + + /* Data necessary for the IO to be performed */ + PgAioOpData op_data; + + /* + * Data necessary to identify the object undergoing IO to higher-level + * code. Needs to be sufficient to allow another backend to reopen the + * file. + */ + PgAioTargetData target_data; +}; + + +typedef struct PgAioBackend +{ + /* index into PgAioCtl->io_handles */ + uint32 io_handle_off; + + /* IO Handles that currently are not used */ + dclist_head idle_ios; + + /* + * Only one IO may be returned by pgaio_io_acquire()/pgaio_io_acquire_nb() + * without having been either defined (by actually associating it with IO) + * or released (with pgaio_io_release()). This restriction is necessary to + * guarantee that we always can acquire an IO. ->handed_out_io is used to + * enforce that rule. + */ + PgAioHandle *handed_out_io; + + /* Are we currently in batchmode? See pgaio_enter_batchmode(). */ + bool in_batchmode; + + /* + * IOs that are defined, but not yet submitted. + */ + uint16 num_staged_ios; + PgAioHandle *staged_ios[PGAIO_SUBMIT_BATCH_SIZE]; + + /* + * List of in-flight IOs. Also contains IOs that aren't strictly speaking + * in-flight anymore, but have been waited-for and completed by another + * backend. Once this backend sees such an IO it'll be reclaimed. + * + * The list is ordered by submission time, with more recently submitted + * IOs being appended at the end. + */ + dclist_head in_flight_ios; +} PgAioBackend; + + +typedef struct PgAioCtl +{ + int backend_state_count; + PgAioBackend *backend_state; + + /* + * Array of iovec structs. Each iovec is owned by a specific backend. The + * allocation is in PgAioCtl to allow the maximum number of iovecs for + * individual IOs to be configurable with PGC_POSTMASTER GUC. + */ + uint32 iovec_count; + struct iovec *iovecs; + + /* + * For, e.g., an IO covering multiple buffers in shared / temp buffers, we + * need to get Buffer IDs during completion to be able to change the + * BufferDesc state accordingly. This space can be used to store e.g. + * Buffer IDs. Note that the actual iovec might be shorter than this, + * because we combine neighboring pages into one larger iovec entry. + */ + uint64 *handle_data; + + uint32 io_handle_count; + PgAioHandle *io_handles; +} PgAioCtl; + + + +/* + * Callbacks used to implement an IO method. + */ +typedef struct IoMethodOps +{ + /* properties */ + + /* + * If an FD is about to be closed, do we need to wait for all in-flight + * IOs referencing that FD? + */ + bool wait_on_fd_before_close; + + + /* global initialization */ + + /* + * Amount of additional shared memory to reserve for the io_method. Called + * just like a normal ipci.c style *Size() function. Optional. + */ + size_t (*shmem_size) (void); + + /* + * Initialize shared memory. First time is true if AIO's shared memory was + * just initialized, false otherwise. Optional. + */ + void (*shmem_init) (bool first_time); + + /* + * Per-backend initialization. Optional. + */ + void (*init_backend) (void); + + + /* handling of IOs */ + + /* optional */ + bool (*needs_synchronous_execution) (PgAioHandle *ioh); + + /* + * Start executing passed in IOs. + * + * Shall advance state to at least PGAIO_HS_SUBMITTED. (By the time this + * returns, other backends might have advanced the state further.) + * + * Will not be called if ->needs_synchronous_execution() returned true. + * + * num_staged_ios is <= PGAIO_SUBMIT_BATCH_SIZE. + * + * Always called in a critical section. + */ + int (*submit) (uint16 num_staged_ios, PgAioHandle **staged_ios); + + /* --- + * Wait for the IO to complete. Optional. + * + * On return, state shall be on of + * - PGAIO_HS_COMPLETED_IO + * - PGAIO_HS_COMPLETED_SHARED + * - PGAIO_HS_COMPLETED_LOCAL + * + * The callback must not block if the handle is already in one of those + * states, or has been reused (see pgaio_io_was_recycled()). If, on + * return, the state is PGAIO_HS_COMPLETED_IO, state will reach + * PGAIO_HS_COMPLETED_SHARED without further intervention by the IO + * method. + * + * If not provided, it needs to be guaranteed that the IO method calls + * pgaio_io_process_completion() without further interaction by the + * issuing backend. + * --- + */ + void (*wait_one) (PgAioHandle *ioh, + uint64 ref_generation); +} IoMethodOps; + + +/* aio.c */ +extern bool pgaio_io_was_recycled(PgAioHandle *ioh, uint64 ref_generation, PgAioHandleState *state); +extern void pgaio_io_stage(PgAioHandle *ioh, PgAioOp op); +extern void pgaio_io_process_completion(PgAioHandle *ioh, int result); +extern void pgaio_io_prepare_submit(PgAioHandle *ioh); +extern bool pgaio_io_needs_synchronous_execution(PgAioHandle *ioh); +extern const char *pgaio_io_get_state_name(PgAioHandle *ioh); +const char *pgaio_result_status_string(PgAioResultStatus rs); +extern void pgaio_shutdown(int code, Datum arg); + +/* aio_callback.c */ +extern void pgaio_io_call_stage(PgAioHandle *ioh); +extern void pgaio_io_call_complete_shared(PgAioHandle *ioh); +extern PgAioResult pgaio_io_call_complete_local(PgAioHandle *ioh); + +/* aio_io.c */ +extern void pgaio_io_perform_synchronously(PgAioHandle *ioh); +extern const char *pgaio_io_get_op_name(PgAioHandle *ioh); +extern bool pgaio_io_uses_fd(PgAioHandle *ioh, int fd); +extern int pgaio_io_get_iovec_length(PgAioHandle *ioh, struct iovec **iov); + +/* aio_target.c */ +extern bool pgaio_io_can_reopen(PgAioHandle *ioh); +extern void pgaio_io_reopen(PgAioHandle *ioh); +extern const char *pgaio_io_get_target_name(PgAioHandle *ioh); + + +/* + * The AIO subsystem has fairly verbose debug logging support. This can be + * enabled/disabled at build time. The reason for this is that + * a) the verbosity can make debugging things on higher levels hard + * b) even if logging can be skipped due to elevel checks, it still causes a + * measurable slowdown + * + * XXX: This likely should be eventually be disabled by default, at least in + * non-assert builds. + */ +#define PGAIO_VERBOSE 1 + +/* + * Simple ereport() wrapper that only logs if PGAIO_VERBOSE is defined. + * + * This intentionally still compiles the code, guarded by a constant if (0), + * if verbose logging is disabled, to make it less likely that debug logging + * is silently broken. + * + * The current definition requires passing at least one argument. + */ +#define pgaio_debug(elevel, msg, ...) \ + do { \ + if (PGAIO_VERBOSE) \ + ereport(elevel, \ + errhidestmt(true), errhidecontext(true), \ + errmsg_internal(msg, \ + __VA_ARGS__)); \ + } while(0) + +/* + * Simple ereport() wrapper. Note that the definition requires passing at + * least one argument. + */ +#define pgaio_debug_io(elevel, ioh, msg, ...) \ + pgaio_debug(elevel, "io %-10d|op %-5s|target %-4s|state %-16s: " msg, \ + pgaio_io_get_id(ioh), \ + pgaio_io_get_op_name(ioh), \ + pgaio_io_get_target_name(ioh), \ + pgaio_io_get_state_name(ioh), \ + __VA_ARGS__) + +/* Declarations for the tables of function pointers exposed by each IO method. */ +extern PGDLLIMPORT const IoMethodOps pgaio_sync_ops; +extern PGDLLIMPORT const IoMethodOps pgaio_worker_ops; +#ifdef IOMETHOD_IO_URING_ENABLED +extern PGDLLIMPORT const IoMethodOps pgaio_uring_ops; +#endif + +extern PGDLLIMPORT const IoMethodOps *pgaio_method_ops; +extern PGDLLIMPORT PgAioCtl *pgaio_ctl; +extern PGDLLIMPORT PgAioBackend *pgaio_my_backend; + + + +#endif /* AIO_INTERNAL_H */ diff --git a/src/include/storage/aio_subsys.h b/src/include/storage/aio_subsys.h new file mode 100644 index 0000000000000..0cf36bb35da70 --- /dev/null +++ b/src/include/storage/aio_subsys.h @@ -0,0 +1,37 @@ +/*------------------------------------------------------------------------- + * + * aio_subsys.h + * Interaction with AIO as a subsystem, rather than actually issuing AIO + * + * This header is for AIO related functionality that's being called by files + * that don't perform AIO, but interact with the AIO subsystem in some + * form. E.g. postmaster.c and shared memory initialization need to initialize + * AIO but don't perform AIO. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/aio_subsys.h + * + *------------------------------------------------------------------------- + */ +#ifndef AIO_SUBSYS_H +#define AIO_SUBSYS_H + + +/* aio_init.c */ +extern Size AioShmemSize(void); +extern void AioShmemInit(void); + +extern void pgaio_init_backend(void); + + +/* aio.c */ +extern void pgaio_error_cleanup(void); +extern void AtEOXact_Aio(bool is_commit); + + +/* method_worker.c */ +extern bool pgaio_workers_enabled(void); + +#endif /* AIO_SUBSYS_H */ diff --git a/src/include/storage/aio_types.h b/src/include/storage/aio_types.h new file mode 100644 index 0000000000000..181833660778e --- /dev/null +++ b/src/include/storage/aio_types.h @@ -0,0 +1,137 @@ +/*------------------------------------------------------------------------- + * + * aio_types.h + * AIO related types that are useful to include separately, to reduce the + * "include burden". + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/aio_types.h + * + *------------------------------------------------------------------------- + */ +#ifndef AIO_TYPES_H +#define AIO_TYPES_H + +#include "storage/block.h" +#include "storage/relfilelocator.h" + + +typedef struct PgAioHandle PgAioHandle; +typedef struct PgAioHandleCallbacks PgAioHandleCallbacks; +typedef struct PgAioTargetInfo PgAioTargetInfo; + +/* + * A reference to an IO that can be used to wait for the IO (using + * pgaio_wref_wait()) to complete. + * + * These can be passed across process boundaries. + */ +typedef struct PgAioWaitRef +{ + /* internal ID identifying the specific PgAioHandle */ + uint32 aio_index; + + /* + * IO handles are reused. To detect if a handle was reused, and thereby + * avoid unnecessarily waiting for a newer IO, each time the handle is + * reused a generation number is increased. + * + * To avoid requiring alignment sufficient for an int64, split the + * generation into two. + */ + uint32 generation_upper; + uint32 generation_lower; +} PgAioWaitRef; + + +/* + * Information identifying what the IO is being performed on. + * + * This needs sufficient information to + * + * a) Reopen the file for the IO if the IO is executed in a context that + * cannot use the FD provided initially (e.g. because the IO is executed in + * a worker process). + * + * b) Describe the object the IO is performed on in log / error messages. + */ +typedef union PgAioTargetData +{ + struct + { + RelFileLocator rlocator; /* physical relation identifier */ + BlockNumber blockNum; /* blknum relative to begin of reln */ + BlockNumber nblocks; + ForkNumber forkNum:8; /* don't waste 4 byte for four values */ + bool is_temp:1; /* proc can be inferred by owning AIO */ + bool skip_fsync:1; + } smgr; +} PgAioTargetData; + + +/* + * The status of an AIO operation. + */ +typedef enum PgAioResultStatus +{ + PGAIO_RS_UNKNOWN, /* not yet completed / uninitialized */ + PGAIO_RS_OK, + PGAIO_RS_PARTIAL, /* did not fully succeed, no warning/error */ + PGAIO_RS_WARNING, /* [partially] succeeded, with a warning */ + PGAIO_RS_ERROR, /* failed entirely */ +} PgAioResultStatus; + + +/* + * Result of IO operation, visible only to the initiator of IO. + * + * We need to be careful about the size of PgAioResult, as it is embedded in + * every PgAioHandle, as well as every PgAioReturn. Currently we assume we can + * fit it into one 8 byte value, restricting the space for per-callback error + * data to PGAIO_RESULT_ERROR_BITS. + */ +#define PGAIO_RESULT_ID_BITS 6 +#define PGAIO_RESULT_STATUS_BITS 3 +#define PGAIO_RESULT_ERROR_BITS 23 +typedef struct PgAioResult +{ + /* + * This is of type PgAioHandleCallbackID, but can't use a bitfield of an + * enum, because some compilers treat enums as signed. + */ + uint32 id:PGAIO_RESULT_ID_BITS; + + /* of type PgAioResultStatus, see above */ + uint32 status:PGAIO_RESULT_STATUS_BITS; + + /* meaning defined by callback->error */ + uint32 error_data:PGAIO_RESULT_ERROR_BITS; + + int32 result; +} PgAioResult; + + +StaticAssertDecl(PGAIO_RESULT_ID_BITS + + PGAIO_RESULT_STATUS_BITS + + PGAIO_RESULT_ERROR_BITS == 32, + "PgAioResult bits divided up incorrectly"); +StaticAssertDecl(sizeof(PgAioResult) == 8, + "PgAioResult has unexpected size"); + +/* + * Combination of PgAioResult with minimal metadata about the IO. + * + * Contains sufficient information to be able, in case the IO [partially] + * fails, to log/raise an error under control of the IO issuing code. + */ +typedef struct PgAioReturn +{ + PgAioResult result; + PgAioTargetData target_data; +} PgAioReturn; + + +#endif /* AIO_TYPES_H */ diff --git a/src/include/storage/barrier.h b/src/include/storage/barrier.h index 6bb1f665c8e14..4d8a95f4a4aec 100644 --- a/src/include/storage/barrier.h +++ b/src/include/storage/barrier.h @@ -3,7 +3,7 @@ * barrier.h * Barriers for synchronizing cooperating processes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/barrier.h diff --git a/src/include/storage/block.h b/src/include/storage/block.h index ecde8e051822f..cee5fcf3c5ec4 100644 --- a/src/include/storage/block.h +++ b/src/include/storage/block.h @@ -4,7 +4,7 @@ * POSTGRES disk block definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/block.h diff --git a/src/include/storage/buf.h b/src/include/storage/buf.h index 64a1ad9d2c47a..2a209cc3934fb 100644 --- a/src/include/storage/buf.h +++ b/src/include/storage/buf.h @@ -4,7 +4,7 @@ * Basic buffer manager data types. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/buf.h diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index f190e6e5e462b..0dec7d93b3b27 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -5,7 +5,7 @@ * strategy. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/buf_internals.h @@ -17,11 +17,12 @@ #include "pgstat.h" #include "port/atomics.h" +#include "storage/aio_types.h" #include "storage/buf.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" -#include "storage/latch.h" #include "storage/lwlock.h" +#include "storage/procnumber.h" #include "storage/shmem.h" #include "storage/smgr.h" #include "storage/spin.h" @@ -40,12 +41,19 @@ * * The definition of buffer state components is below. */ +#define BUF_REFCOUNT_BITS 18 +#define BUF_USAGECOUNT_BITS 4 +#define BUF_FLAG_BITS 10 + +StaticAssertDecl(BUF_REFCOUNT_BITS + BUF_USAGECOUNT_BITS + BUF_FLAG_BITS == 32, + "parts of buffer state space need to equal 32"); + #define BUF_REFCOUNT_ONE 1 -#define BUF_REFCOUNT_MASK ((1U << 18) - 1) -#define BUF_USAGECOUNT_MASK 0x003C0000U -#define BUF_USAGECOUNT_ONE (1U << 18) -#define BUF_USAGECOUNT_SHIFT 18 -#define BUF_FLAG_MASK 0xFFC00000U +#define BUF_REFCOUNT_MASK ((1U << BUF_REFCOUNT_BITS) - 1) +#define BUF_USAGECOUNT_MASK (((1U << BUF_USAGECOUNT_BITS) - 1) << (BUF_REFCOUNT_BITS)) +#define BUF_USAGECOUNT_ONE (1U << BUF_REFCOUNT_BITS) +#define BUF_USAGECOUNT_SHIFT BUF_REFCOUNT_BITS +#define BUF_FLAG_MASK (((1U << BUF_FLAG_BITS) - 1) << (BUF_REFCOUNT_BITS + BUF_USAGECOUNT_BITS)) /* Get refcount and usagecount from buffer state */ #define BUF_STATE_GET_REFCOUNT(state) ((state) & BUF_REFCOUNT_MASK) @@ -78,6 +86,11 @@ */ #define BM_MAX_USAGE_COUNT 5 +StaticAssertDecl(BM_MAX_USAGE_COUNT < (1 << BUF_USAGECOUNT_BITS), + "BM_MAX_USAGE_COUNT doesn't fit in BUF_USAGECOUNT_BITS bits"); +StaticAssertDecl(MAX_BACKENDS_BITS <= BUF_REFCOUNT_BITS, + "MAX_BACKENDS_BITS needs to be <= BUF_REFCOUNT_BITS"); + /* * Buffer tag identifies which disk block the buffer contains. * @@ -252,6 +265,8 @@ typedef struct BufferDesc int wait_backend_pgprocno; /* backend of pin-count waiter */ int freeNext; /* link in freelist chain */ + + PgAioWaitRef io_wref; /* set iff AIO is in progress */ LWLock content_lock; /* to lock access to buffer contents */ } BufferDesc; @@ -419,6 +434,12 @@ extern void IssuePendingWritebacks(WritebackContext *wb_context, IOContext io_co extern void ScheduleBufferTagForWriteback(WritebackContext *wb_context, IOContext io_context, BufferTag *tag); +/* solely to make it easier to write tests */ +extern bool StartBufferIO(BufferDesc *buf, bool forInput, bool nowait); +extern void TerminateBufferIO(BufferDesc *buf, bool clear_dirty, uint32 set_flag_bits, + bool forget_owner, bool release_aio); + + /* freelist.c */ extern IOContext IOContextForStrategy(BufferAccessStrategy strategy); extern BufferDesc *StrategyGetBuffer(BufferAccessStrategy strategy, @@ -459,6 +480,11 @@ extern BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr, Buffer *buffers, uint32 *extended_by); extern void MarkLocalBufferDirty(Buffer buffer); +extern void TerminateLocalBufferIO(BufferDesc *bufHdr, bool clear_dirty, + uint32 set_flag_bits, bool release_aio); +extern bool StartLocalBufferIO(BufferDesc *bufHdr, bool forInput, bool nowait); +extern void FlushLocalBuffer(BufferDesc *bufHdr, SMgrRelation reln); +extern void InvalidateLocalBuffer(BufferDesc *bufHdr, bool check_unreferenced); extern void DropRelationLocalBuffers(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock); diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h index 5f6d7c8e3ffba..a2f4821f240b9 100644 --- a/src/include/storage/buffile.h +++ b/src/include/storage/buffile.h @@ -15,7 +15,7 @@ * but currently we have no need for oversize temp files without buffered * access. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/buffile.h @@ -38,7 +38,7 @@ typedef struct BufFile BufFile; extern BufFile *BufFileCreateTemp(bool interXact); extern void BufFileClose(BufFile *file); -extern pg_nodiscard size_t BufFileRead(BufFile *file, void *ptr, size_t size); +pg_nodiscard extern size_t BufFileRead(BufFile *file, void *ptr, size_t size); extern void BufFileReadExact(BufFile *file, void *ptr, size_t size); extern size_t BufFileReadMaybeEOF(BufFile *file, void *ptr, size_t size, bool eofOK); extern void BufFileWrite(BufFile *file, const void *ptr, size_t size); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index c8422571b7f94..41fdc1e76938e 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -4,7 +4,7 @@ * POSTGRES buffer manager definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/bufmgr.h @@ -15,6 +15,7 @@ #define BUFMGR_H #include "port/pg_iovec.h" +#include "storage/aio_types.h" #include "storage/block.h" #include "storage/buf.h" #include "storage/bufpage.h" @@ -111,6 +112,11 @@ typedef struct BufferManagerRelation #define READ_BUFFERS_ZERO_ON_ERROR (1 << 0) /* Call smgrprefetch() if I/O necessary. */ #define READ_BUFFERS_ISSUE_ADVICE (1 << 1) +/* Don't treat page as invalid due to checksum failures. */ +#define READ_BUFFERS_IGNORE_CHECKSUM_FAILURES (1 << 2) +/* IO will immediately be waited for */ +#define READ_BUFFERS_SYNCHRONOUSLY (1 << 3) + struct ReadBuffersOperation { @@ -130,7 +136,9 @@ struct ReadBuffersOperation BlockNumber blocknum; int flags; int16 nblocks; - int16 io_buffers_len; + int16 nblocks_done; + PgAioWaitRef io_wref; + PgAioReturn io_return; }; typedef struct ReadBuffersOperation ReadBuffersOperation; @@ -150,25 +158,24 @@ extern PGDLLIMPORT int bgwriter_lru_maxpages; extern PGDLLIMPORT double bgwriter_lru_multiplier; extern PGDLLIMPORT bool track_io_timing; -/* only applicable when prefetching is available */ -#ifdef USE_PREFETCH -#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 1 -#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 10 -#else -#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 0 -#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 0 -#endif +#define DEFAULT_EFFECTIVE_IO_CONCURRENCY 16 +#define DEFAULT_MAINTENANCE_IO_CONCURRENCY 16 extern PGDLLIMPORT int effective_io_concurrency; extern PGDLLIMPORT int maintenance_io_concurrency; #define MAX_IO_COMBINE_LIMIT PG_IOV_MAX #define DEFAULT_IO_COMBINE_LIMIT Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ) -extern PGDLLIMPORT int io_combine_limit; +extern PGDLLIMPORT int io_combine_limit; /* min of the two GUCs below */ +extern PGDLLIMPORT int io_combine_limit_guc; +extern PGDLLIMPORT int io_max_combine_limit; extern PGDLLIMPORT int checkpoint_flush_after; extern PGDLLIMPORT int backend_flush_after; extern PGDLLIMPORT int bgwriter_flush_after; +extern PGDLLIMPORT const PgAioHandleCallbacks aio_shared_buffer_readv_cb; +extern PGDLLIMPORT const PgAioHandleCallbacks aio_local_buffer_readv_cb; + /* in buf_init.c */ extern PGDLLIMPORT char *BufferBlocks; @@ -249,8 +256,11 @@ extern Buffer ExtendBufferedRelTo(BufferManagerRelation bmr, BlockNumber extend_to, ReadBufferMode mode); -extern void InitBufferPoolAccess(void); +extern void InitBufferManagerAccess(void); extern void AtEOXact_Buffers(bool isCommit); +#ifdef USE_ASSERT_CHECKING +extern void AssertBufferLocksPermitCatalogRead(void); +#endif extern char *DebugPrintBufferRefcount(Buffer buffer); extern void CheckPointBuffers(int flags); extern BlockNumber BufferGetBlockNumber(Buffer buffer); @@ -275,10 +285,6 @@ extern void DropDatabaseBuffers(Oid dbid); extern bool BufferIsPermanent(Buffer buffer); extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer); - -#ifdef NOT_USED -extern void PrintPinnedBufs(void); -#endif extern void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum); @@ -294,14 +300,25 @@ extern bool HoldingBufferPinThatDelaysRecovery(void); extern bool BgBufferSync(struct WritebackContext *wb_context); +extern uint32 GetPinLimit(void); +extern uint32 GetLocalPinLimit(void); +extern uint32 GetAdditionalPinLimit(void); +extern uint32 GetAdditionalLocalPinLimit(void); extern void LimitAdditionalPins(uint32 *additional_pins); extern void LimitAdditionalLocalPins(uint32 *additional_pins); -extern bool EvictUnpinnedBuffer(Buffer buf); +extern bool EvictUnpinnedBuffer(Buffer buf, bool *buffer_flushed); +extern void EvictAllUnpinnedBuffers(int32 *buffers_evicted, + int32 *buffers_flushed, + int32 *buffers_skipped); +extern void EvictRelUnpinnedBuffers(Relation rel, + int32 *buffers_evicted, + int32 *buffers_flushed, + int32 *buffers_skipped); /* in buf_init.c */ -extern void InitBufferPool(void); -extern Size BufferShmemSize(void); +extern void BufferManagerShmemInit(void); +extern Size BufferManagerShmemSize(void); /* in localbuf.c */ extern void AtProcExit_LocalBuffers(void); @@ -388,7 +405,7 @@ BufferGetBlock(Buffer buffer) static inline Size BufferGetPageSize(Buffer buffer) { - AssertMacro(BufferIsValid(buffer)); + Assert(BufferIsValid(buffer)); return (Size) BLCKSZ; } diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index df91e80eceec2..aeb67c498c59f 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -4,7 +4,7 @@ * Standard POSTGRES buffer page definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/bufpage.h @@ -73,12 +73,13 @@ extern PGDLLIMPORT bool ignore_checksum_failure; * * AM-specific per-page data (if any) is kept in the area marked "special * space"; each AM has an "opaque" structure defined somewhere that is - * stored as the page trailer. an access method should always + * stored as the page trailer. An access method should always * initialize its pages with PageInit and then set its own opaque * fields. */ -typedef Pointer Page; +typedef char PageData; +typedef PageData *Page; /* @@ -221,9 +222,9 @@ typedef PageHeaderData *PageHeader; * returns true iff no itemid has been allocated on the page */ static inline bool -PageIsEmpty(Page page) +PageIsEmpty(const PageData *page) { - return ((PageHeader) page)->pd_lower <= SizeOfPageHeaderData; + return ((const PageHeaderData *) page)->pd_lower <= SizeOfPageHeaderData; } /* @@ -231,9 +232,9 @@ PageIsEmpty(Page page) * returns true iff page has not been initialized (by PageInit) */ static inline bool -PageIsNew(Page page) +PageIsNew(const PageData *page) { - return ((PageHeader) page)->pd_upper == 0; + return ((const PageHeaderData *) page)->pd_upper == 0; } /* @@ -274,9 +275,9 @@ PageGetContents(Page page) * however, it can be called on a page that is not stored in a buffer. */ static inline Size -PageGetPageSize(Page page) +PageGetPageSize(const PageData *page) { - return (Size) (((PageHeader) page)->pd_pagesize_version & (uint16) 0xFF00); + return (Size) (((const PageHeaderData *) page)->pd_pagesize_version & (uint16) 0xFF00); } /* @@ -284,9 +285,9 @@ PageGetPageSize(Page page) * Returns the page layout version of a page. */ static inline uint8 -PageGetPageLayoutVersion(Page page) +PageGetPageLayoutVersion(const PageData *page) { - return (((PageHeader) page)->pd_pagesize_version & 0x00FF); + return (((const PageHeaderData *) page)->pd_pagesize_version & 0x00FF); } /* @@ -314,9 +315,9 @@ PageSetPageSizeAndVersion(Page page, Size size, uint8 version) * Returns size of special space on a page. */ static inline uint16 -PageGetSpecialSize(Page page) +PageGetSpecialSize(const PageData *page) { - return (PageGetPageSize(page) - ((PageHeader) page)->pd_special); + return (PageGetPageSize(page) - ((const PageHeaderData *) page)->pd_special); } /* @@ -325,23 +326,22 @@ PageGetSpecialSize(Page page) * This is intended to catch use of the pointer before page initialization. */ static inline void -PageValidateSpecialPointer(Page page) +PageValidateSpecialPointer(const PageData *page) { Assert(page); - Assert(((PageHeader) page)->pd_special <= BLCKSZ); - Assert(((PageHeader) page)->pd_special >= SizeOfPageHeaderData); + Assert(((const PageHeaderData *) page)->pd_special <= BLCKSZ); + Assert(((const PageHeaderData *) page)->pd_special >= SizeOfPageHeaderData); } /* * PageGetSpecialPointer * Returns pointer to special space on a page. */ -static inline char * -PageGetSpecialPointer(Page page) -{ - PageValidateSpecialPointer(page); - return (char *) page + ((PageHeader) page)->pd_special; -} +#define PageGetSpecialPointer(page) \ +( \ + PageValidateSpecialPointer(page), \ + ((page) + ((PageHeader) (page))->pd_special) \ +) /* * PageGetItem @@ -352,12 +352,12 @@ PageGetSpecialPointer(Page page) * The semantics may change in the future. */ static inline Item -PageGetItem(Page page, ItemId itemId) +PageGetItem(const PageData *page, const ItemIdData *itemId) { Assert(page); Assert(ItemIdHasStorage(itemId)); - return (Item) (((char *) page) + ItemIdGetOffset(itemId)); + return (Item) (((const char *) page) + ItemIdGetOffset(itemId)); } /* @@ -370,9 +370,9 @@ PageGetItem(Page page, ItemId itemId) * return zero to ensure sane behavior. */ static inline OffsetNumber -PageGetMaxOffsetNumber(Page page) +PageGetMaxOffsetNumber(const PageData *page) { - PageHeader pageheader = (PageHeader) page; + const PageHeaderData *pageheader = (const PageHeaderData *) page; if (pageheader->pd_lower <= SizeOfPageHeaderData) return 0; @@ -384,9 +384,9 @@ PageGetMaxOffsetNumber(Page page) * Additional functions for access to page headers. */ static inline XLogRecPtr -PageGetLSN(Page page) +PageGetLSN(const PageData *page) { - return PageXLogRecPtrGet(((PageHeader) page)->pd_lsn); + return PageXLogRecPtrGet(((const PageHeaderData *) page)->pd_lsn); } static inline void PageSetLSN(Page page, XLogRecPtr lsn) @@ -395,9 +395,9 @@ PageSetLSN(Page page, XLogRecPtr lsn) } static inline bool -PageHasFreeLinePointers(Page page) +PageHasFreeLinePointers(const PageData *page) { - return ((PageHeader) page)->pd_flags & PD_HAS_FREE_LINES; + return ((const PageHeaderData *) page)->pd_flags & PD_HAS_FREE_LINES; } static inline void PageSetHasFreeLinePointers(Page page) @@ -411,9 +411,9 @@ PageClearHasFreeLinePointers(Page page) } static inline bool -PageIsFull(Page page) +PageIsFull(const PageData *page) { - return ((PageHeader) page)->pd_flags & PD_PAGE_FULL; + return ((const PageHeaderData *) page)->pd_flags & PD_PAGE_FULL; } static inline void PageSetFull(Page page) @@ -427,9 +427,9 @@ PageClearFull(Page page) } static inline bool -PageIsAllVisible(Page page) +PageIsAllVisible(const PageData *page) { - return ((PageHeader) page)->pd_flags & PD_ALL_VISIBLE; + return ((const PageHeaderData *) page)->pd_flags & PD_ALL_VISIBLE; } static inline void PageSetAllVisible(Page page) @@ -465,43 +465,41 @@ do { \ #define PAI_OVERWRITE (1 << 0) #define PAI_IS_HEAP (1 << 1) -/* flags for PageIsVerifiedExtended() */ +/* flags for PageIsVerified() */ #define PIV_LOG_WARNING (1 << 0) -#define PIV_REPORT_STAT (1 << 1) +#define PIV_LOG_LOG (1 << 1) +#define PIV_IGNORE_CHECKSUM_FAILURE (1 << 2) #define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap) \ PageAddItemExtended(page, item, size, offsetNumber, \ ((overwrite) ? PAI_OVERWRITE : 0) | \ ((is_heap) ? PAI_IS_HEAP : 0)) -#define PageIsVerified(page, blkno) \ - PageIsVerifiedExtended(page, blkno, \ - PIV_LOG_WARNING | PIV_REPORT_STAT) - /* - * Check that BLCKSZ is a multiple of sizeof(size_t). In - * PageIsVerifiedExtended(), it is much faster to check if a page is - * full of zeroes using the native word size. Note that this assertion - * is kept within a header to make sure that StaticAssertDecl() works - * across various combinations of platforms and compilers. + * Check that BLCKSZ is a multiple of sizeof(size_t). In PageIsVerified(), it + * is much faster to check if a page is full of zeroes using the native word + * size. Note that this assertion is kept within a header to make sure that + * StaticAssertDecl() works across various combinations of platforms and + * compilers. */ StaticAssertDecl(BLCKSZ == ((BLCKSZ / sizeof(size_t)) * sizeof(size_t)), "BLCKSZ has to be a multiple of sizeof(size_t)"); extern void PageInit(Page page, Size pageSize, Size specialSize); -extern bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags); +extern bool PageIsVerified(PageData *page, BlockNumber blkno, int flags, + bool *checksum_failure_p); extern OffsetNumber PageAddItemExtended(Page page, Item item, Size size, OffsetNumber offsetNumber, int flags); -extern Page PageGetTempPage(Page page); -extern Page PageGetTempPageCopy(Page page); -extern Page PageGetTempPageCopySpecial(Page page); +extern Page PageGetTempPage(const PageData *page); +extern Page PageGetTempPageCopy(const PageData *page); +extern Page PageGetTempPageCopySpecial(const PageData *page); extern void PageRestoreTempPage(Page tempPage, Page oldPage); extern void PageRepairFragmentation(Page page); extern void PageTruncateLinePointerArray(Page page); -extern Size PageGetFreeSpace(Page page); -extern Size PageGetFreeSpaceForMultipleTuples(Page page, int ntups); -extern Size PageGetExactFreeSpace(Page page); -extern Size PageGetHeapFreeSpace(Page page); +extern Size PageGetFreeSpace(const PageData *page); +extern Size PageGetFreeSpaceForMultipleTuples(const PageData *page, int ntups); +extern Size PageGetExactFreeSpace(const PageData *page); +extern Size PageGetHeapFreeSpace(const PageData *page); extern void PageIndexTupleDelete(Page page, OffsetNumber offnum); extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems); extern void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum); diff --git a/src/include/storage/bulk_write.h b/src/include/storage/bulk_write.h index cf6f6fcb3f286..7885415f6cb8f 100644 --- a/src/include/storage/bulk_write.h +++ b/src/include/storage/bulk_write.h @@ -4,7 +4,7 @@ * Efficiently and reliably populate a new relation * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/bulk_write.h diff --git a/src/include/storage/checksum.h b/src/include/storage/checksum.h index 08e9d598ce61c..25d13a798d102 100644 --- a/src/include/storage/checksum.h +++ b/src/include/storage/checksum.h @@ -3,7 +3,7 @@ * checksum.h * Checksum implementation for data pages. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/checksum.h diff --git a/src/include/storage/checksum_impl.h b/src/include/storage/checksum_impl.h index 7f20de373b4ea..da87d61ba5242 100644 --- a/src/include/storage/checksum_impl.h +++ b/src/include/storage/checksum_impl.h @@ -8,7 +8,7 @@ * referenced by storage/checksum.h. (Note: you may need to redefine * Assert() as empty to compile this successfully externally.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/checksum_impl.h diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index d4720d4bb525d..526c4ee105137 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -12,7 +12,7 @@ * can be canceled prior to the fulfillment of the condition) and do not * use pointers internally (so that they are safe to use within DSMs). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/condition_variable.h diff --git a/src/include/storage/copydir.h b/src/include/storage/copydir.h index a25e258f4797e..f1d7beeed1a3d 100644 --- a/src/include/storage/copydir.h +++ b/src/include/storage/copydir.h @@ -3,7 +3,7 @@ * copydir.h * Copy a directory. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/copydir.h @@ -13,6 +13,15 @@ #ifndef COPYDIR_H #define COPYDIR_H +typedef enum FileCopyMethod +{ + FILE_COPY_METHOD_COPY, + FILE_COPY_METHOD_CLONE, +} FileCopyMethod; + +/* GUC parameters */ +extern PGDLLIMPORT int file_copy_method; + extern void copydir(const char *fromdir, const char *todir, bool recurse); extern void copy_file(const char *fromfile, const char *tofile); diff --git a/src/include/storage/dsm.h b/src/include/storage/dsm.h index 1a22b32df1a4d..2302cc7f40b4b 100644 --- a/src/include/storage/dsm.h +++ b/src/include/storage/dsm.h @@ -3,7 +3,7 @@ * dsm.h * manage dynamic shared memory segments * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/dsm.h diff --git a/src/include/storage/dsm_impl.h b/src/include/storage/dsm_impl.h index 882269603daf7..7248cb1f9acc6 100644 --- a/src/include/storage/dsm_impl.h +++ b/src/include/storage/dsm_impl.h @@ -3,7 +3,7 @@ * dsm_impl.h * low-level dynamic shared memory primitives * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/dsm_impl.h diff --git a/src/include/storage/dsm_registry.h b/src/include/storage/dsm_registry.h index 5fa79731d2801..b381e44bc9d87 100644 --- a/src/include/storage/dsm_registry.h +++ b/src/include/storage/dsm_registry.h @@ -3,7 +3,7 @@ * dsm_registry.h * Functions for interfacing with the dynamic shared memory registry. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/dsm_registry.h diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 1456ab383a424..b77d8e5e30e3a 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -4,7 +4,7 @@ * Virtual file descriptor definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/fd.h @@ -101,6 +101,8 @@ extern PGDLLIMPORT int max_safe_fds; * prototypes for functions in fd.c */ +struct PgAioHandle; + /* Operations on virtual Files --- equivalent to Unix kernel file ops */ extern File PathNameOpenFile(const char *fileName, int fileFlags); extern File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode); @@ -109,6 +111,7 @@ extern void FileClose(File file); extern int FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info); extern ssize_t FileReadV(File file, const struct iovec *iov, int iovcnt, off_t offset, uint32 wait_event_info); extern ssize_t FileWriteV(File file, const struct iovec *iov, int iovcnt, off_t offset, uint32 wait_event_info); +extern int FileStartReadV(struct PgAioHandle *ioh, File file, int iovcnt, off_t offset, uint32 wait_event_info); extern int FileSync(File file, uint32 wait_event_info); extern int FileZero(File file, off_t offset, off_t amount, uint32 wait_event_info); extern int FileFallocate(File file, off_t offset, off_t amount, uint32 wait_event_info); diff --git a/src/include/storage/fileset.h b/src/include/storage/fileset.h index 1674f086d4ff6..80250015f5ec1 100644 --- a/src/include/storage/fileset.h +++ b/src/include/storage/fileset.h @@ -3,7 +3,7 @@ * fileset.h * Management of named temporary files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/fileset.h diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h index d64a634be35c6..427cb6a0df947 100644 --- a/src/include/storage/freespace.h +++ b/src/include/storage/freespace.h @@ -4,7 +4,7 @@ * POSTGRES free space map for quickly finding free space in relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/freespace.h diff --git a/src/include/storage/fsm_internals.h b/src/include/storage/fsm_internals.h index a922e691fe067..77b48d1ebc77a 100644 --- a/src/include/storage/fsm_internals.h +++ b/src/include/storage/fsm_internals.h @@ -4,7 +4,7 @@ * internal functions for free space map * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/fsm_internals.h diff --git a/src/include/storage/indexfsm.h b/src/include/storage/indexfsm.h index ad376b1131933..39ebb42ac8b7f 100644 --- a/src/include/storage/indexfsm.h +++ b/src/include/storage/indexfsm.h @@ -4,7 +4,7 @@ * POSTGRES free space map for quickly finding an unused page in index * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/indexfsm.h diff --git a/src/include/storage/io_worker.h b/src/include/storage/io_worker.h new file mode 100644 index 0000000000000..7bde7e89c8a8d --- /dev/null +++ b/src/include/storage/io_worker.h @@ -0,0 +1,22 @@ +/*------------------------------------------------------------------------- + * + * io_worker.h + * IO worker for implementing AIO "ourselves" + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/io.h + * + *------------------------------------------------------------------------- + */ +#ifndef IO_WORKER_H +#define IO_WORKER_H + + +pg_noreturn extern void IoWorkerMain(const void *startup_data, size_t startup_data_len); + +extern PGDLLIMPORT int io_workers; + +#endif /* IO_WORKER_H */ diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index b2d062781ecdb..3baf418b3d1ed 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -8,7 +8,7 @@ * exit-time cleanup for either a postmaster or a backend. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/ipc.h @@ -65,7 +65,7 @@ typedef void (*shmem_startup_hook_type) (void); extern PGDLLIMPORT bool proc_exit_inprogress; extern PGDLLIMPORT bool shmem_exit_inprogress; -extern void proc_exit(int code) pg_attribute_noreturn(); +pg_noreturn extern void proc_exit(int code); extern void shmem_exit(int code); extern void on_proc_exit(pg_on_exit_callback function, Datum arg); extern void on_shmem_exit(pg_on_exit_callback function, Datum arg); diff --git a/src/include/storage/item.h b/src/include/storage/item.h index d524246fb125b..5a4539cc381b0 100644 --- a/src/include/storage/item.h +++ b/src/include/storage/item.h @@ -4,7 +4,7 @@ * POSTGRES disk item definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/item.h diff --git a/src/include/storage/itemid.h b/src/include/storage/itemid.h index 6d29722ec1fe7..bfefacaab5c5e 100644 --- a/src/include/storage/itemid.h +++ b/src/include/storage/itemid.h @@ -4,7 +4,7 @@ * Standard POSTGRES buffer page item identifier/line pointer definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/itemid.h diff --git a/src/include/storage/itemptr.h b/src/include/storage/itemptr.h index cfe21df765067..74b87a9114a57 100644 --- a/src/include/storage/itemptr.h +++ b/src/include/storage/itemptr.h @@ -4,7 +4,7 @@ * POSTGRES disk item pointer definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/itemptr.h diff --git a/src/include/storage/large_object.h b/src/include/storage/large_object.h index 9cfb7aa777a6f..6fecf44244636 100644 --- a/src/include/storage/large_object.h +++ b/src/include/storage/large_object.h @@ -5,7 +5,7 @@ * zillions of large objects (internal, external, jaquith, inversion). * Now we only support inversion. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/large_object.h diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h index 7e194d536f055..e41dc70785afe 100644 --- a/src/include/storage/latch.h +++ b/src/include/storage/latch.h @@ -84,13 +84,14 @@ * use of any generic handler. * * - * WaitEventSets allow to wait for latches being set and additional events - - * postmaster dying and socket readiness of several sockets currently - at the - * same time. On many platforms using a long lived event set is more - * efficient than using WaitLatch or WaitLatchOrSocket. + * See also WaitEventSets in waiteventset.h. They allow to wait for latches + * being set and additional events - postmaster dying and socket readiness of + * several sockets currently - at the same time. On many platforms using a + * long lived event set is more efficient than using WaitLatch or + * WaitLatchOrSocket. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/latch.h @@ -102,7 +103,7 @@ #include -#include "utils/resowner.h" +#include "storage/waiteventset.h" /* for WL_* arguments to WaitLatch */ /* * Latch structure should be treated as opaque and only accessed through @@ -120,77 +121,20 @@ typedef struct Latch #endif } Latch; -/* - * Bitmasks for events that may wake-up WaitLatch(), WaitLatchOrSocket(), or - * WaitEventSetWait(). - */ -#define WL_LATCH_SET (1 << 0) -#define WL_SOCKET_READABLE (1 << 1) -#define WL_SOCKET_WRITEABLE (1 << 2) -#define WL_TIMEOUT (1 << 3) /* not for WaitEventSetWait() */ -#define WL_POSTMASTER_DEATH (1 << 4) -#define WL_EXIT_ON_PM_DEATH (1 << 5) -#ifdef WIN32 -#define WL_SOCKET_CONNECTED (1 << 6) -#else -/* avoid having to deal with case on platforms not requiring it */ -#define WL_SOCKET_CONNECTED WL_SOCKET_WRITEABLE -#endif -#define WL_SOCKET_CLOSED (1 << 7) -#ifdef WIN32 -#define WL_SOCKET_ACCEPT (1 << 8) -#else -/* avoid having to deal with case on platforms not requiring it */ -#define WL_SOCKET_ACCEPT WL_SOCKET_READABLE -#endif -#define WL_SOCKET_MASK (WL_SOCKET_READABLE | \ - WL_SOCKET_WRITEABLE | \ - WL_SOCKET_CONNECTED | \ - WL_SOCKET_ACCEPT | \ - WL_SOCKET_CLOSED) - -typedef struct WaitEvent -{ - int pos; /* position in the event data structure */ - uint32 events; /* triggered events */ - pgsocket fd; /* socket fd associated with event */ - void *user_data; /* pointer provided in AddWaitEventToSet */ -#ifdef WIN32 - bool reset; /* Is reset of the event required? */ -#endif -} WaitEvent; - -/* forward declaration to avoid exposing latch.c implementation details */ -typedef struct WaitEventSet WaitEventSet; - /* * prototypes for functions in latch.c */ -extern void InitializeLatchSupport(void); extern void InitLatch(Latch *latch); extern void InitSharedLatch(Latch *latch); extern void OwnLatch(Latch *latch); extern void DisownLatch(Latch *latch); extern void SetLatch(Latch *latch); extern void ResetLatch(Latch *latch); -extern void ShutdownLatchSupport(void); - -extern WaitEventSet *CreateWaitEventSet(ResourceOwner resowner, int nevents); -extern void FreeWaitEventSet(WaitEventSet *set); -extern void FreeWaitEventSetAfterFork(WaitEventSet *set); -extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, - Latch *latch, void *user_data); -extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch); -extern int WaitEventSetWait(WaitEventSet *set, long timeout, - WaitEvent *occurred_events, int nevents, - uint32 wait_event_info); extern int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info); extern int WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info); extern void InitializeLatchWaitSet(void); -extern int GetNumRegisteredWaitEvents(WaitEventSet *set); -extern bool WaitEventSetCanReportClosed(void); #endif /* LATCH_H */ diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index ce15125ac3bc0..58eee4e0d54c2 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -4,7 +4,7 @@ * POSTGRES lock manager definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/lmgr.h @@ -73,7 +73,7 @@ extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode); /* Lock a tuple (see heap_lock_tuple before assuming you understand this) */ extern void LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode); extern bool ConditionalLockTuple(Relation relation, ItemPointer tid, - LOCKMODE lockmode); + LOCKMODE lockmode, bool logLockFailure); extern void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode); /* Lock an XID (used to wait for a transaction to finish) */ @@ -81,7 +81,8 @@ extern void XactLockTableInsert(TransactionId xid); extern void XactLockTableDelete(TransactionId xid); extern void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper); -extern bool ConditionalXactLockTableWait(TransactionId xid); +extern bool ConditionalXactLockTableWait(TransactionId xid, + bool logLockFailure); /* Lock VXIDs, specified by conflicting locktags */ extern void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress); diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index cc1f6e78c396c..4862b80eec3c7 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -4,7 +4,7 @@ * POSTGRES low-level lock mechanism * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/lock.h @@ -30,6 +30,7 @@ typedef struct PGPROC PGPROC; /* GUC variables */ extern PGDLLIMPORT int max_locks_per_xact; +extern PGDLLIMPORT bool log_lock_failures; #ifdef LOCK_DEBUG extern PGDLLIMPORT int Trace_lock_oidmin; @@ -544,7 +545,9 @@ typedef enum /* * function prototypes */ -extern void InitLocks(void); +extern void LockManagerShmemInit(void); +extern Size LockManagerShmemSize(void); +extern void InitLockManagerAccess(void); extern LockMethod GetLocksMethodTable(const LOCK *lock); extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag); extern uint32 LockTagHashCode(const LOCKTAG *locktag); @@ -558,7 +561,8 @@ extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, bool sessionLock, bool dontWait, bool reportMemoryError, - LOCALLOCK **locallockp); + LOCALLOCK **locallockp, + bool logLockFailure); extern void AbortStrongLockAcquire(void); extern void MarkLockClear(LOCALLOCK *locallock); extern bool LockRelease(const LOCKTAG *locktag, @@ -583,8 +587,10 @@ extern bool LockCheckConflicts(LockMethod lockMethodTable, LOCK *lock, PROCLOCK *proclock); extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode); extern void GrantAwaitedLock(void); +extern LOCALLOCK *GetAwaitedLock(void); +extern void ResetAwaitedLock(void); + extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode); -extern Size LockShmemSize(void); extern LockData *GetLockStatusData(void); extern BlockedProcsData *GetBlockerStatusData(int blocked_pid); @@ -602,7 +608,7 @@ extern void lock_twophase_standby_recover(TransactionId xid, uint16 info, extern DeadLockState DeadLockCheck(PGPROC *proc); extern PGPROC *GetBlockingAutoVacuumPgproc(void); -extern void DeadLockReport(void) pg_attribute_noreturn(); +pg_noreturn extern void DeadLockReport(void); extern void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, diff --git a/src/include/storage/lockdefs.h b/src/include/storage/lockdefs.h index 934ba84f6a26e..7f3ba0352f655 100644 --- a/src/include/storage/lockdefs.h +++ b/src/include/storage/lockdefs.h @@ -7,7 +7,7 @@ * contains definition that have to (indirectly) be available when included by * FRONTEND code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/lockdefs.h @@ -47,6 +47,8 @@ typedef int LOCKMODE; #define MaxLockMode 8 /* highest standard lock mode */ +/* See README.tuplock section "Locking to write inplace-updated tables" */ +#define InplaceUpdateTupleLock ExclusiveLock /* WAL representation of an AccessExclusiveLock on a table */ typedef struct xl_standby_lock diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h index d70e6d37e097a..08a72569ae5fd 100644 --- a/src/include/storage/lwlock.h +++ b/src/include/storage/lwlock.h @@ -4,7 +4,7 @@ * Lightweight lock manager * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/lwlock.h @@ -129,6 +129,10 @@ extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode); extern void LWLockRelease(LWLock *lock); extern void LWLockReleaseClearVar(LWLock *lock, pg_atomic_uint64 *valptr, uint64 val); extern void LWLockReleaseAll(void); +extern void LWLockDisown(LWLock *lock); +extern void LWLockReleaseDisowned(LWLock *lock, LWLockMode mode); +extern void ForEachLWLockHeldByMe(void (*callback) (LWLock *, LWLockMode, void *), + void *context); extern bool LWLockHeldByMe(LWLock *lock); extern bool LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride); extern bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode); @@ -192,6 +196,7 @@ typedef enum BuiltinTrancheIds LWTRANCHE_LOCK_MANAGER, LWTRANCHE_PREDICATE_LOCK_MANAGER, LWTRANCHE_PARALLEL_HASH_JOIN, + LWTRANCHE_PARALLEL_BTREE_SCAN, LWTRANCHE_PARALLEL_QUERY_DSA, LWTRANCHE_PER_SESSION_DSA, LWTRANCHE_PER_SESSION_RECORD_TYPE, @@ -215,6 +220,7 @@ typedef enum BuiltinTrancheIds LWTRANCHE_SUBTRANS_SLRU, LWTRANCHE_XACT_SLRU, LWTRANCHE_PARALLEL_VACUUM_DSA, + LWTRANCHE_AIO_URING_COMPLETION, LWTRANCHE_FIRST_USER_DEFINED, } BuiltinTrancheIds; diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h index 6a2f64c54fb57..a9681738146e1 100644 --- a/src/include/storage/lwlocklist.h +++ b/src/include/storage/lwlocklist.h @@ -9,7 +9,7 @@ * * Also, generate-lwlocknames.pl processes this file to create lwlocknames.h. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -37,7 +37,7 @@ PG_LWLOCK(3, XidGen) PG_LWLOCK(4, ProcArray) PG_LWLOCK(5, SInvalRead) PG_LWLOCK(6, SInvalWrite) -PG_LWLOCK(7, WALBufMapping) +/* 7 was WALBufMapping */ PG_LWLOCK(8, WALWrite) PG_LWLOCK(9, ControlFile) /* 10 was CheckpointLock */ @@ -83,3 +83,4 @@ PG_LWLOCK(49, WALSummarizer) PG_LWLOCK(50, DSMRegistry) PG_LWLOCK(51, InjectionPoint) PG_LWLOCK(52, SerialControl) +PG_LWLOCK(53, AioWorkerSubmissionQueue) diff --git a/src/include/storage/md.h b/src/include/storage/md.h index 620f10abdeb58..b563c27abf092 100644 --- a/src/include/storage/md.h +++ b/src/include/storage/md.h @@ -4,7 +4,7 @@ * magnetic disk storage manager public interface declarations. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/md.h @@ -14,11 +14,14 @@ #ifndef MD_H #define MD_H +#include "storage/aio_types.h" #include "storage/block.h" #include "storage/relfilelocator.h" #include "storage/smgr.h" #include "storage/sync.h" +extern PGDLLIMPORT const PgAioHandleCallbacks aio_md_readv_cb; + /* md storage manager functionality */ extern void mdinit(void); extern void mdopen(SMgrRelation reln); @@ -32,8 +35,13 @@ extern void mdzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync); extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks); +extern uint32 mdmaxcombine(SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum); extern void mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks); +extern void mdstartreadv(PgAioHandle *ioh, + SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, + void **buffers, BlockNumber nblocks); extern void mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void **buffers, BlockNumber nblocks, bool skipFsync); @@ -41,9 +49,10 @@ extern void mdwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks); extern BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum); extern void mdtruncate(SMgrRelation reln, ForkNumber forknum, - BlockNumber nblocks); + BlockNumber curnblk, BlockNumber nblocks); extern void mdimmedsync(SMgrRelation reln, ForkNumber forknum); extern void mdregistersync(SMgrRelation reln, ForkNumber forknum); +extern int mdfd(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, uint32 *off); extern void ForgetDatabaseSyncRequests(Oid dbid); extern void DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo); diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build index f889093117e39..1e0f5080727ed 100644 --- a/src/include/storage/meson.build +++ b/src/include/storage/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group lwlocknames_h = custom_target('lwlocknames_h', input: files( diff --git a/src/include/storage/off.h b/src/include/storage/off.h index 575cca83dd19c..b0bcd371b0464 100644 --- a/src/include/storage/off.h +++ b/src/include/storage/off.h @@ -4,7 +4,7 @@ * POSTGRES disk "offset" definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/off.h diff --git a/src/include/storage/pg_sema.h b/src/include/storage/pg_sema.h index dfef79ac96384..fa6ca35a51f5c 100644 --- a/src/include/storage/pg_sema.h +++ b/src/include/storage/pg_sema.h @@ -10,7 +10,7 @@ * be provided by each port. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/pg_sema.h diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h index 3065ff5be71c1..5f7d4b83a60eb 100644 --- a/src/include/storage/pg_shmem.h +++ b/src/include/storage/pg_shmem.h @@ -14,7 +14,7 @@ * only one ID number. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/pg_shmem.h @@ -45,6 +45,7 @@ typedef struct PGShmemHeader /* standard header for all Postgres shmem */ extern PGDLLIMPORT int shared_memory_type; extern PGDLLIMPORT int huge_pages; extern PGDLLIMPORT int huge_page_size; +extern PGDLLIMPORT int huge_pages_status; /* Possible values for huge_pages and huge_pages_status */ typedef enum diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h index 0c9a7e32a8acb..428aa3fd68a0a 100644 --- a/src/include/storage/pmsignal.h +++ b/src/include/storage/pmsignal.h @@ -4,7 +4,7 @@ * routines for signaling between the postmaster and its child processes * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/pmsignal.h @@ -17,11 +17,11 @@ #include #ifdef HAVE_SYS_PRCTL_H -#include "sys/prctl.h" +#include #endif #ifdef HAVE_SYS_PROCCTL_H -#include "sys/procctl.h" +#include #endif /* @@ -33,6 +33,7 @@ typedef enum { PMSIGNAL_RECOVERY_STARTED, /* recovery has started */ + PMSIGNAL_RECOVERY_CONSISTENT, /* recovery has reached consistent state */ PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */ PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */ PMSIGNAL_START_AUTOVAC_LAUNCHER, /* start an autovacuum launcher */ @@ -40,10 +41,11 @@ typedef enum PMSIGNAL_BACKGROUND_WORKER_CHANGE, /* background worker state change */ PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */ PMSIGNAL_ADVANCE_STATE_MACHINE, /* advance postmaster's state machine */ - - NUM_PMSIGNALS /* Must be last value of enum! */ + PMSIGNAL_XLOG_IS_SHUTDOWN, /* ShutdownXLOG() completed */ } PMSignalReason; +#define NUM_PMSIGNALS (PMSIGNAL_XLOG_IS_SHUTDOWN+1) + /* * Reasons why the postmaster would send SIGQUIT to its children. */ @@ -58,7 +60,7 @@ typedef enum typedef struct PMSignalData PMSignalData; #ifdef EXEC_BACKEND -extern volatile PMSignalData *PMSignalState; +extern PGDLLIMPORT volatile PMSignalData *PMSignalState; #endif /* @@ -70,11 +72,10 @@ extern void SendPostmasterSignal(PMSignalReason reason); extern bool CheckPostmasterSignal(PMSignalReason reason); extern void SetQuitSignalReason(QuitSignalReason reason); extern QuitSignalReason GetQuitSignalReason(void); -extern int AssignPostmasterChildSlot(void); -extern bool ReleasePostmasterChildSlot(int slot); +extern void MarkPostmasterChildSlotAssigned(int slot); +extern bool MarkPostmasterChildSlotUnassigned(int slot); extern bool IsPostmasterChildWalSender(int slot); -extern void MarkPostmasterChildActive(void); -extern void MarkPostmasterChildInactive(void); +extern void RegisterPostmasterChildActive(void); extern void MarkPostmasterChildWalSender(void); extern bool PostmasterIsAliveInternal(void); extern void PostmasterDeathSignalInit(void); diff --git a/src/include/storage/predicate.h b/src/include/storage/predicate.h index 14ee9b94a2ff6..267d5d90e9486 100644 --- a/src/include/storage/predicate.h +++ b/src/include/storage/predicate.h @@ -4,7 +4,7 @@ * POSTGRES public predicate locking definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/predicate.h @@ -14,6 +14,7 @@ #ifndef PREDICATE_H #define PREDICATE_H +#include "storage/itemptr.h" #include "storage/lock.h" #include "utils/relcache.h" #include "utils/snapshot.h" @@ -37,7 +38,7 @@ typedef void *SerializableXactHandle; */ /* housekeeping for shared memory predicate lock structures */ -extern void InitPredicateLocks(void); +extern void PredicateLockShmemInit(void); extern Size PredicateLockShmemSize(void); extern void CheckPointPredicate(void); diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h index cb0ec9bc98e33..5c3ea37f25097 100644 --- a/src/include/storage/predicate_internals.h +++ b/src/include/storage/predicate_internals.h @@ -4,7 +4,7 @@ * POSTGRES internal predicate locking definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/predicate_internals.h diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index bbd893a544e80..9f9b3fcfbf1d7 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -4,7 +4,7 @@ * per-process shared memory data structures * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/proc.h @@ -78,12 +78,26 @@ struct XidCache #define PROC_XMIN_FLAGS (PROC_IN_VACUUM | PROC_IN_SAFE_IC) /* - * We allow a small number of "weak" relation locks (AccessShareLock, + * We allow a limited number of "weak" relation locks (AccessShareLock, * RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure - * rather than the main lock table. This eases contention on the lock - * manager LWLocks. See storage/lmgr/README for additional details. + * (or rather in shared memory referenced from PGPROC) rather than the main + * lock table. This eases contention on the lock manager LWLocks. See + * storage/lmgr/README for additional details. */ -#define FP_LOCK_SLOTS_PER_BACKEND 16 +extern PGDLLIMPORT int FastPathLockGroupsPerBackend; + +/* + * Define the maximum number of fast-path locking groups per backend. + * This must be a power-of-two value. The actual number of fast-path + * lock groups is calculated in InitializeFastPathLocks() based on + * max_locks_per_transaction. 1024 is an arbitrary upper limit (matching + * max_locks_per_transaction = 16k). Values over 1024 are unlikely to be + * beneficial as there are bottlenecks we'll hit way before that. + */ +#define FP_LOCK_GROUPS_PER_BACKEND_MAX 1024 +#define FP_LOCK_SLOTS_PER_GROUP 16 /* don't change */ +#define FastPathLockSlotsPerBackend() \ + (FP_LOCK_SLOTS_PER_GROUP * FastPathLockGroupsPerBackend) /* * Flags for PGPROC.delayChkptFlags @@ -104,10 +118,10 @@ struct XidCache * is inserted prior to the new redo point, the corresponding data changes will * also be flushed to disk before the checkpoint can complete. (In the * extremely common case where the data being modified is in shared buffers - * and we acquire an exclusive content lock on the relevant buffers before - * writing WAL, this mechanism is not needed, because phase 2 will block - * until we release the content lock and then flush the modified data to - * disk.) + * and we acquire an exclusive content lock and MarkBufferDirty() on the + * relevant buffers before writing WAL, this mechanism is not needed, because + * phase 2 will block until we release the content lock and then flush the + * modified data to disk. See transam/README and SyncOneBuffer().) * * Setting DELAY_CHKPT_COMPLETE prevents the system from moving from phase 2 * to phase 3. This is useful if we are performing a WAL-logged operation that @@ -144,7 +158,7 @@ typedef enum * but its myProcLocks[] lists are valid. * * We allow many fields of this struct to be accessed without locks, such as - * delayChkptFlags and isBackgroundWorker. However, keep in mind that writing + * delayChkptFlags and isRegularBackend. However, keep in mind that writing * mirrored ones (see below) requires holding ProcArrayLock or XidGenLock in * at least shared mode, so that pgxactoff does not change concurrently. * @@ -211,7 +225,7 @@ struct PGPROC Oid tempNamespaceId; /* OID of temp schema this backend is * using */ - bool isBackgroundWorker; /* true if background worker. */ + bool isRegularBackend; /* true if it's a regular backend. */ /* * While in hot standby mode, shows that a conflict signal has been sent @@ -292,8 +306,8 @@ struct PGPROC /* Lock manager data, recording fast-path locks taken by this backend. */ LWLock fpInfoLock; /* protects per-backend fast-path state */ - uint64 fpLockBits; /* lock modes held for each fast-path slot */ - Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]; /* slots for rel oids */ + uint64 *fpLockBits; /* lock modes held for each fast-path slot */ + Oid *fpRelId; /* slots for rel oids */ bool fpVXIDLock; /* are we holding a fast-path VXID lock? */ LocalTransactionId fpLocalTransactionId; /* lxid for fast-path VXID * lock */ @@ -312,19 +326,6 @@ struct PGPROC extern PGDLLIMPORT PGPROC *MyProc; -/* Proc number of this backend. Equal to GetNumberFromPGProc(MyProc). */ -extern PGDLLIMPORT ProcNumber MyProcNumber; - -/* Our parallel session leader, or INVALID_PROC_NUMBER if none */ -extern PGDLLIMPORT ProcNumber ParallelLeaderProcNumber; - -/* - * The proc number to use for our session's temp relations is normally our own, - * but parallel workers should use their leader's ID. - */ -#define ProcNumberForTempRelations() \ - (ParallelLeaderProcNumber == INVALID_PROC_NUMBER ? MyProcNumber : ParallelLeaderProcNumber) - /* * There is one ProcGlobal struct for the whole database cluster. * @@ -403,7 +404,7 @@ typedef struct PROC_HDR uint32 allProcCount; /* Head of list of free PGPROC structures */ dlist_head freeProcs; - /* Head of list of autovacuum's free PGPROC structures */ + /* Head of list of autovacuum & special worker free PGPROC structures */ dlist_head autovacFreeProcs; /* Head of list of bgworker free PGPROC structures */ dlist_head bgworkerFreeProcs; @@ -413,10 +414,14 @@ typedef struct PROC_HDR pg_atomic_uint32 procArrayGroupFirst; /* First pgproc waiting for group transaction status update */ pg_atomic_uint32 clogGroupFirst; - /* WALWriter process's latch */ - Latch *walwriterLatch; - /* Checkpointer process's latch */ - Latch *checkpointerLatch; + + /* + * Current slot numbers of some auxiliary processes. There can be only one + * of each of these running at a time. + */ + ProcNumber walwriterProc; + ProcNumber checkpointerProc; + /* Current shared estimate of appropriate spins_per_delay value */ int spins_per_delay; /* Buffer id of the buffer that Startup process waits for pin on, or -1 */ @@ -433,16 +438,28 @@ extern PGDLLIMPORT PGPROC *PreparedXactProcs; #define GetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)]) #define GetNumberFromPGProc(proc) ((proc) - &ProcGlobal->allProcs[0]) +/* + * We set aside some extra PGPROC structures for "special worker" processes, + * which are full-fledged backends (they can run transactions) + * but are unique animals that there's never more than one of. + * Currently there are two such processes: the autovacuum launcher + * and the slotsync worker. + */ +#define NUM_SPECIAL_WORKER_PROCS 2 + /* * We set aside some extra PGPROC structures for auxiliary processes, - * ie things that aren't full-fledged backends but need shmem access. + * ie things that aren't full-fledged backends (they cannot run transactions + * or take heavyweight locks) but need shmem access. * * Background writer, checkpointer, WAL writer, WAL summarizer, and archiver * run during normal operation. Startup process and WAL receiver also consume * 2 slots, but WAL writer is launched only after startup has exited, so we * only need 6 slots. */ -#define NUM_AUXILIARY_PROCS 6 +#define MAX_IO_WORKERS 32 +#define NUM_AUXILIARY_PROCS (6 + MAX_IO_WORKERS) + /* configurable options */ extern PGDLLIMPORT int DeadlockTimeout; @@ -454,8 +471,8 @@ extern PGDLLIMPORT int IdleSessionTimeout; extern PGDLLIMPORT bool log_lock_waits; #ifdef EXEC_BACKEND -extern slock_t *ProcStructLock; -extern PGPROC *AuxiliaryProcs; +extern PGDLLIMPORT slock_t *ProcStructLock; +extern PGDLLIMPORT PGPROC *AuxiliaryProcs; #endif @@ -475,14 +492,17 @@ extern int GetStartupBufferPinWaitBufId(void); extern bool HaveNFreeProcs(int n, int *nfree); extern void ProcReleaseLocks(bool isCommit); -extern ProcWaitStatus ProcSleep(LOCALLOCK *locallock, - LockMethod lockMethodTable, - bool dontWait); +extern ProcWaitStatus JoinWaitQueue(LOCALLOCK *locallock, + LockMethod lockMethodTable, bool dontWait); +extern ProcWaitStatus ProcSleep(LOCALLOCK *locallock); extern void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus); extern void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock); extern void CheckDeadLockAlert(void); -extern bool IsWaitingForLock(void); extern void LockErrorCleanup(void); +extern void GetLockHoldersAndWaiters(LOCALLOCK *locallock, + StringInfo lock_holders_sbuf, + StringInfo lock_waiters_sbuf, + int *lockHoldersNum); extern void ProcWaitForSignal(uint32 wait_event_info); extern void ProcSendSignal(ProcNumber procNumber); diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index 8ca6050462252..ef0b733ebe8be 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -4,7 +4,7 @@ * POSTGRES process array definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/procarray.h @@ -21,7 +21,7 @@ extern Size ProcArrayShmemSize(void); -extern void CreateSharedProcArray(void); +extern void ProcArrayShmemInit(void); extern void ProcArrayAdd(PGPROC *proc); extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid); diff --git a/src/include/storage/proclist.h b/src/include/storage/proclist.h index 34a1b7dcab56e..a157f8df67f35 100644 --- a/src/include/storage/proclist.h +++ b/src/include/storage/proclist.h @@ -10,7 +10,7 @@ * See proclist_types.h for the structs that these functions operate on. They * are separated to break a header dependency cycle with proc.h. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/storage/proclist.h diff --git a/src/include/storage/proclist_types.h b/src/include/storage/proclist_types.h index a4fb88c1d0de3..f314a6c3cfa0a 100644 --- a/src/include/storage/proclist_types.h +++ b/src/include/storage/proclist_types.h @@ -5,7 +5,7 @@ * * See proclist.h for functions that operate on these types. * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/storage/proclist_types.h diff --git a/src/include/storage/procnumber.h b/src/include/storage/procnumber.h index 49eb0e215ccad..2ddaaf0c64600 100644 --- a/src/include/storage/procnumber.h +++ b/src/include/storage/procnumber.h @@ -4,7 +4,7 @@ * definition of process number * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/procnumber.h @@ -25,6 +25,19 @@ typedef int ProcNumber; #define INVALID_PROC_NUMBER (-1) +/* + * Note: MAX_BACKENDS_BITS is 18 as that is the space available for buffer + * refcounts in buf_internals.h. This limitation could be lifted by using a + * 64bit state; but it's unlikely to be worthwhile as 2^18-1 backends exceed + * currently realistic configurations. Even if that limitation were removed, + * we still could not a) exceed 2^23-1 because inval.c stores the ProcNumber + * as a 3-byte signed integer, b) INT_MAX/4 because some places compute + * 4*MaxBackends without any overflow check. We check that the configured + * number of backends does not exceed MAX_BACKENDS in InitializeMaxBackends(). + */ +#define MAX_BACKENDS_BITS 18 +#define MAX_BACKENDS ((1U << MAX_BACKENDS_BITS)-1) + /* * Proc number of this backend (same as GetNumberFromPGProc(MyProc)) */ diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h index 7d290ea7d05cc..afeeb1ca019f8 100644 --- a/src/include/storage/procsignal.h +++ b/src/include/storage/procsignal.h @@ -4,7 +4,7 @@ * Routines for interprocess signaling * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/procsignal.h @@ -47,24 +47,35 @@ typedef enum PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_LAST = PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, - - NUM_PROCSIGNALS /* Must be last! */ } ProcSignalReason; +#define NUM_PROCSIGNALS (PROCSIG_RECOVERY_CONFLICT_LAST + 1) + typedef enum { PROCSIGNAL_BARRIER_SMGRRELEASE, /* ask smgr to close files */ } ProcSignalBarrierType; +/* + * Length of query cancel keys generated. + * + * Note that the protocol allows for longer keys, or shorter, but this is the + * length we actually generate. Client code, and the server code that handles + * incoming cancellation packets from clients, mustn't use this hardcoded + * length. + */ +#define MAX_CANCEL_KEY_LENGTH 32 + /* * prototypes for functions in procsignal.c */ extern Size ProcSignalShmemSize(void); extern void ProcSignalShmemInit(void); -extern void ProcSignalInit(void); +extern void ProcSignalInit(const uint8 *cancel_key, int cancel_key_len); extern int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber); +extern void SendCancelRequest(int backendPID, const uint8 *cancel_key, int cancel_key_len); extern uint64 EmitProcSignalBarrier(ProcSignalBarrierType type); extern void WaitForProcSignalBarrier(uint64 generation); @@ -72,4 +83,11 @@ extern void ProcessProcSignalBarrier(void); extern void procsignal_sigusr1_handler(SIGNAL_ARGS); +/* ProcSignalHeader is an opaque struct, details known only within procsignal.c */ +typedef struct ProcSignalHeader ProcSignalHeader; + +#ifdef EXEC_BACKEND +extern PGDLLIMPORT ProcSignalHeader *ProcSignal; +#endif + #endif /* PROCSIGNAL_H */ diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h index 4e599904f26a9..9b0d65161d02c 100644 --- a/src/include/storage/read_stream.h +++ b/src/include/storage/read_stream.h @@ -4,7 +4,7 @@ * Mechanism for accessing buffered relation data with look-ahead * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/read_stream.h @@ -42,14 +42,45 @@ */ #define READ_STREAM_FULL 0x04 +/* --- + * Opt-in to using AIO batchmode. + * + * Submitting IO in larger batches can be more efficient than doing so + * one-by-one, particularly for many small reads. It does, however, require + * the ReadStreamBlockNumberCB callback to abide by the restrictions of AIO + * batching (c.f. pgaio_enter_batchmode()). Basically, the callback may not: + * + * a) block without first calling pgaio_submit_staged(), unless a + * to-be-waited-on lock cannot be part of a deadlock, e.g. because it is + * never held while waiting for IO. + * + * b) start another batch (without first exiting batchmode and re-entering + * before returning) + * + * As this requires care and is nontrivial in some cases, batching is only + * used with explicit opt-in. + * --- + */ +#define READ_STREAM_USE_BATCHING 0x08 + struct ReadStream; typedef struct ReadStream ReadStream; +/* for block_range_read_stream_cb */ +typedef struct BlockRangeReadStreamPrivate +{ + BlockNumber current_blocknum; + BlockNumber last_exclusive; +} BlockRangeReadStreamPrivate; + /* Callback that returns the next block number to read. */ typedef BlockNumber (*ReadStreamBlockNumberCB) (ReadStream *stream, void *callback_private_data, void *per_buffer_data); +extern BlockNumber block_range_read_stream_cb(ReadStream *stream, + void *callback_private_data, + void *per_buffer_data); extern ReadStream *read_stream_begin_relation(int flags, BufferAccessStrategy strategy, Relation rel, @@ -58,6 +89,8 @@ extern ReadStream *read_stream_begin_relation(int flags, void *callback_private_data, size_t per_buffer_data_size); extern Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_data); +extern BlockNumber read_stream_next_block(ReadStream *stream, + BufferAccessStrategy *strategy); extern ReadStream *read_stream_begin_smgr_relation(int flags, BufferAccessStrategy strategy, SMgrRelation smgr, @@ -66,7 +99,6 @@ extern ReadStream *read_stream_begin_smgr_relation(int flags, ReadStreamBlockNumberCB callback, void *callback_private_data, size_t per_buffer_data_size); -extern Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_private); extern void read_stream_reset(ReadStream *stream); extern void read_stream_end(ReadStream *stream); diff --git a/src/include/storage/reinit.h b/src/include/storage/reinit.h index 1373d509df236..37fcbb1345f66 100644 --- a/src/include/storage/reinit.h +++ b/src/include/storage/reinit.h @@ -4,7 +4,7 @@ * Reinitialization of unlogged relations * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/reinit.h diff --git a/src/include/storage/relfilelocator.h b/src/include/storage/relfilelocator.h index 2f970a25c36c7..0f841e3804d4e 100644 --- a/src/include/storage/relfilelocator.h +++ b/src/include/storage/relfilelocator.h @@ -4,7 +4,7 @@ * Physical access information for relations. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/relfilelocator.h diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 02c68513a534e..2f73f9fcf57a2 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -1,10 +1,10 @@ /*------------------------------------------------------------------------- * * s_lock.h - * Hardware-dependent implementation of spinlocks. + * Implementation of spinlocks. * * NOTE: none of the macros in this file are intended to be called directly. - * Call them through the hardware-independent macros in spin.h. + * Call them through the macros in spin.h. * * The following hardware-dependent macros must be provided for each * supported platform: @@ -78,15 +78,8 @@ * in assembly language to execute a hardware atomic-test-and-set * instruction. Equivalent OS-supplied mutex routines could be used too. * - * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not - * defined), then we fall back on an emulation that uses SysV semaphores - * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS() - * implementation, because of the cost of a kernel call per lock or unlock. - * An old report is that Postgres spends around 40% of its time in semop(2) - * when using the SysV semaphore code. * - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/s_lock.h @@ -100,8 +93,6 @@ #error "s_lock.h may not be included from frontend code" #endif -#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */ - #if defined(__GNUC__) || defined(__INTEL_COMPILER) /************************************************************************* * All the gcc inlines @@ -272,18 +263,24 @@ tas(volatile slock_t *lock) #define S_UNLOCK(lock) __sync_lock_release(lock) +#if defined(__aarch64__) + /* - * Using an ISB instruction to delay in spinlock loops appears beneficial on - * high-core-count ARM64 processors. It seems mostly a wash for smaller gear, - * and ISB doesn't exist at all on pre-v7 ARM chips. + * On ARM64, it's a win to use a non-locking test before the TAS proper. It + * may be a win on 32-bit ARM, too, but nobody's tested it yet. */ -#if defined(__aarch64__) +#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock)) #define SPIN_DELAY() spin_delay() static __inline__ void spin_delay(void) { + /* + * Using an ISB instruction to delay in spinlock loops appears beneficial + * on high-core-count ARM64 processors. It seems mostly a wash for smaller + * gear, and ISB doesn't exist at all on pre-v7 ARM chips. + */ __asm__ __volatile__( " isb; \n"); } @@ -655,34 +652,10 @@ spin_delay(void) /* Blow up if we didn't have any way to do spinlocks */ #ifndef HAS_TEST_AND_SET -#error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-bugs@lists.postgresql.org. +#error PostgreSQL does not have spinlock support on this platform. Please report this to pgsql-bugs@lists.postgresql.org. #endif -#else /* !HAVE_SPINLOCKS */ - - -/* - * Fake spinlock implementation using semaphores --- slow and prone - * to fall foul of kernel limits on number of semaphores, so don't use this - * unless you must! The subroutines appear in spin.c. - */ -typedef int slock_t; - -extern bool s_lock_free_sema(volatile slock_t *lock); -extern void s_unlock_sema(volatile slock_t *lock); -extern void s_init_lock_sema(volatile slock_t *lock, bool nested); -extern int tas_sema(volatile slock_t *lock); - -#define S_LOCK_FREE(lock) s_lock_free_sema(lock) -#define S_UNLOCK(lock) s_unlock_sema(lock) -#define S_INIT_LOCK(lock) s_init_lock_sema(lock, false) -#define TAS(lock) tas_sema(lock) - - -#endif /* HAVE_SPINLOCKS */ - - /* * Default Definitions - override these above as needed. */ diff --git a/src/include/storage/sharedfileset.h b/src/include/storage/sharedfileset.h index 7186aba2698c1..71a2167158a55 100644 --- a/src/include/storage/sharedfileset.h +++ b/src/include/storage/sharedfileset.h @@ -4,7 +4,7 @@ * Shared temporary file management. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/sharedfileset.h diff --git a/src/include/storage/shm_mq.h b/src/include/storage/shm_mq.h index 80f63f4fba5e4..4e58e6675d4d7 100644 --- a/src/include/storage/shm_mq.h +++ b/src/include/storage/shm_mq.h @@ -3,7 +3,7 @@ * shm_mq.h * single-reader, single-writer shared memory message queue * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/shm_mq.h diff --git a/src/include/storage/shm_toc.h b/src/include/storage/shm_toc.h index a46470d68b8a0..800363470905c 100644 --- a/src/include/storage/shm_toc.h +++ b/src/include/storage/shm_toc.h @@ -12,7 +12,7 @@ * other data structure within the segment and only put the pointer to * the data structure itself in the table of contents. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/shm_toc.h diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index 842989111c31a..c1f668ded9523 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -11,7 +11,7 @@ * at the same address. This means shared memory pointers can be passed * around directly between different processes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/shmem.h @@ -27,7 +27,8 @@ /* shmem.c */ extern PGDLLIMPORT slock_t *ShmemLock; -extern void InitShmemAccess(void *seghdr); +struct PGShmemHeader; /* avoid including storage/pg_shmem.h here */ +extern void InitShmemAccess(struct PGShmemHeader *seghdr); extern void InitShmemAllocation(void); extern void *ShmemAlloc(Size size); extern void *ShmemAllocNoError(Size size); @@ -40,6 +41,8 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr); extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); +extern PGDLLIMPORT Size pg_get_shmem_pagesize(void); + /* ipci.c */ extern void RequestAddinShmemSpace(Size size); diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index 8f5744b21bc9a..845a5851b574e 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -4,7 +4,7 @@ * POSTGRES shared cache invalidation communication definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/sinval.h @@ -27,6 +27,7 @@ * * invalidate an smgr cache entry for a specific physical relation * * invalidate the mapped-relation mapping for a given database * * invalidate any saved snapshot that might be used to scan a given relation + * * invalidate a RelationSyncCache entry for a specific relation * More types could be added if needed. The message type is identified by * the first "int8" field of the message struct. Zero or positive means a * specific-catcache inval message (and also serves as the catcache ID field). @@ -46,12 +47,12 @@ * catcache inval messages must be generated for each of its caches, since * the hash keys will generally be different. * - * Catcache, relcache, and snapshot invalidations are transactional, and so - * are sent to other backends upon commit. Internally to the generating - * backend, they are also processed at CommandCounterIncrement so that later - * commands in the same transaction see the new state. The generating backend - * also has to process them at abort, to flush out any cache state it's loaded - * from no-longer-valid entries. + * Catcache, relcache, relsynccache, and snapshot invalidations are + * transactional, and so are sent to other backends upon commit. Internally + * to the generating backend, they are also processed at + * CommandCounterIncrement so that later commands in the same transaction see + * the new state. The generating backend also has to process them at abort, + * to flush out any cache state it's loaded from no-longer-valid entries. * * smgr and relation mapping invalidations are non-transactional: they are * sent immediately when the underlying file change is made. @@ -110,6 +111,16 @@ typedef struct Oid relId; /* relation ID */ } SharedInvalSnapshotMsg; +#define SHAREDINVALRELSYNC_ID (-6) + +typedef struct +{ + int8 id; /* type field --- must be first */ + Oid dbId; /* database ID */ + Oid relid; /* relation ID, or 0 if whole + * RelationSyncCache */ +} SharedInvalRelSyncMsg; + typedef union { int8 id; /* type field --- must be first */ @@ -119,6 +130,7 @@ typedef union SharedInvalSmgrMsg sm; SharedInvalRelmapMsg rm; SharedInvalSnapshotMsg sn; + SharedInvalRelSyncMsg rs; } SharedInvalidationMessage; @@ -144,6 +156,8 @@ extern void ProcessCatchupInterrupt(void); extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, bool *RelcacheInitFileInval); +extern int inplaceGetInvalidationMessages(SharedInvalidationMessage **msgs, + bool *RelcacheInitFileInval); extern void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs, int nmsgs, bool RelcacheInitFileInval, Oid dbid, Oid tsid); diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h index c3c97b3f8b7ed..ea71cea8cacde 100644 --- a/src/include/storage/sinvaladt.h +++ b/src/include/storage/sinvaladt.h @@ -12,7 +12,7 @@ * The struct type SharedInvalidationMessage, defining the contents of * a single message, is defined in sinval.h. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/sinvaladt.h @@ -28,8 +28,8 @@ /* * prototypes for functions in sinvaladt.c */ -extern Size SInvalShmemSize(void); -extern void CreateSharedInvalidationState(void); +extern Size SharedInvalShmemSize(void); +extern void SharedInvalShmemInit(void); extern void SharedInvalBackendInit(bool sendOnly); extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n); diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index e15b20a566a0d..3964d9334b3a7 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -4,7 +4,7 @@ * storage manager switch public interface declarations. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/smgr.h @@ -15,6 +15,7 @@ #define SMGR_H #include "lib/ilist.h" +#include "storage/aio_types.h" #include "storage/block.h" #include "storage/relfilelocator.h" @@ -27,7 +28,7 @@ * descriptors.) * * An SMgrRelation may be "pinned", to prevent it from being destroyed while - * it's in use. We use this to prevent pointers relcache to smgr from being + * it's in use. We use this to prevent pointers in relcache to smgr from being * invalidated. SMgrRelations that are not pinned are deleted at end of * transaction. */ @@ -73,6 +74,8 @@ typedef SMgrRelationData *SMgrRelation; #define SmgrIsTemp(smgr) \ RelFileLocatorBackendIsTemp((smgr)->smgr_rlocator) +extern PGDLLIMPORT const PgAioTargetInfo aio_smgr_target_info; + extern void smgrinit(void); extern SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend); extern bool smgrexists(SMgrRelation reln, ForkNumber forknum); @@ -92,9 +95,15 @@ extern void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync); extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks); +extern uint32 smgrmaxcombine(SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum); extern void smgrreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void **buffers, BlockNumber nblocks); +extern void smgrstartreadv(PgAioHandle *ioh, + SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum, + void **buffers, BlockNumber nblocks); extern void smgrwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void **buffers, BlockNumber nblocks, @@ -103,8 +112,9 @@ extern void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks); extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum); extern BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum); -extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, - int nforks, BlockNumber *nblocks); +extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, + BlockNumber *old_nblocks, + BlockNumber *nblocks); extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum); extern void smgrregistersync(SMgrRelation reln, ForkNumber forknum); extern void AtEOXact_SMgr(void); @@ -124,4 +134,11 @@ smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, smgrwritev(reln, forknum, blocknum, &buffer, 1, skipFsync); } +extern void pgaio_io_set_target_smgr(PgAioHandle *ioh, + SMgrRelationData *smgr, + ForkNumber forknum, + BlockNumber blocknum, + int nblocks, + bool skip_fsync); + #endif /* SMGR_H */ diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h index c0679c599921f..33e2ab8757233 100644 --- a/src/include/storage/spin.h +++ b/src/include/storage/spin.h @@ -1,11 +1,11 @@ /*------------------------------------------------------------------------- * * spin.h - * Hardware-independent implementation of spinlocks. + * API for spinlocks. * * - * The hardware-independent interface to spinlocks is defined by the - * typedef "slock_t" and these macros: + * The interface to spinlocks is defined by the typedef "slock_t" and + * these macros: * * void SpinLockInit(volatile slock_t *lock) * Initialize a spinlock (to the unlocked state). @@ -41,7 +41,7 @@ * be again. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/spin.h @@ -52,9 +52,6 @@ #define SPIN_H #include "storage/s_lock.h" -#ifndef HAVE_SPINLOCKS -#include "storage/pg_sema.h" -#endif #define SpinLockInit(lock) S_INIT_LOCK(lock) @@ -65,13 +62,4 @@ #define SpinLockFree(lock) S_LOCK_FREE(lock) - -extern int SpinlockSemas(void); -extern Size SpinlockSemaSize(void); - -#ifndef HAVE_SPINLOCKS -extern void SpinlockSemaInit(void); -extern PGDLLIMPORT PGSemaphore *SpinlockSemaArray; -#endif - #endif /* SPIN_H */ diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h index cce0bc521e758..24e2f5082bc80 100644 --- a/src/include/storage/standby.h +++ b/src/include/storage/standby.h @@ -4,7 +4,7 @@ * Definitions for hot standby mode. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/standby.h diff --git a/src/include/storage/standbydefs.h b/src/include/storage/standbydefs.h index fe12f463a8628..71e5ae878b579 100644 --- a/src/include/storage/standbydefs.h +++ b/src/include/storage/standbydefs.h @@ -4,7 +4,7 @@ * Frontend exposed definitions for hot standby mode. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/standbydefs.h diff --git a/src/include/storage/sync.h b/src/include/storage/sync.h index 9dee8fa6e5bb3..c2272d1417585 100644 --- a/src/include/storage/sync.h +++ b/src/include/storage/sync.h @@ -3,7 +3,7 @@ * sync.h * File synchronization management code. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/storage/sync.h diff --git a/src/include/storage/waiteventset.h b/src/include/storage/waiteventset.h new file mode 100644 index 0000000000000..dd514d5299104 --- /dev/null +++ b/src/include/storage/waiteventset.h @@ -0,0 +1,98 @@ +/*------------------------------------------------------------------------- + * + * waiteventset.h + * ppoll() / pselect() like interface for waiting for events + * + * WaitEventSets allow to wait for latches being set and additional events - + * postmaster dying and socket readiness of several sockets currently - at the + * same time. On many platforms using a long lived event set is more + * efficient than using WaitLatch or WaitLatchOrSocket. + * + * WaitEventSetWait includes a provision for timeouts (which should be avoided + * when possible, as they incur extra overhead) and a provision for postmaster + * child processes to wake up immediately on postmaster death. See + * storage/ipc/waiteventset.c for detailed specifications for the exported + * functions. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/storage/waiteventset.h + * + *------------------------------------------------------------------------- + */ +#ifndef WAITEVENTSET_H +#define WAITEVENTSET_H + +#include "utils/resowner.h" + +/* + * Bitmasks for events that may wake-up WaitLatch(), WaitLatchOrSocket(), or + * WaitEventSetWait(). + */ +#define WL_LATCH_SET (1 << 0) +#define WL_SOCKET_READABLE (1 << 1) +#define WL_SOCKET_WRITEABLE (1 << 2) +#define WL_TIMEOUT (1 << 3) /* not for WaitEventSetWait() */ +#define WL_POSTMASTER_DEATH (1 << 4) +#define WL_EXIT_ON_PM_DEATH (1 << 5) +#ifdef WIN32 +#define WL_SOCKET_CONNECTED (1 << 6) +#else +/* avoid having to deal with case on platforms not requiring it */ +#define WL_SOCKET_CONNECTED WL_SOCKET_WRITEABLE +#endif +#define WL_SOCKET_CLOSED (1 << 7) +#ifdef WIN32 +#define WL_SOCKET_ACCEPT (1 << 8) +#else +/* avoid having to deal with case on platforms not requiring it */ +#define WL_SOCKET_ACCEPT WL_SOCKET_READABLE +#endif +#define WL_SOCKET_MASK (WL_SOCKET_READABLE | \ + WL_SOCKET_WRITEABLE | \ + WL_SOCKET_CONNECTED | \ + WL_SOCKET_ACCEPT | \ + WL_SOCKET_CLOSED) + +typedef struct WaitEvent +{ + int pos; /* position in the event data structure */ + uint32 events; /* triggered events */ + pgsocket fd; /* socket fd associated with event */ + void *user_data; /* pointer provided in AddWaitEventToSet */ +#ifdef WIN32 + bool reset; /* Is reset of the event required? */ +#endif +} WaitEvent; + +/* forward declarations to avoid exposing waiteventset.c implementation details */ +typedef struct WaitEventSet WaitEventSet; + +struct Latch; + +/* + * prototypes for functions in waiteventset.c + */ +extern void InitializeWaitEventSupport(void); + +extern WaitEventSet *CreateWaitEventSet(ResourceOwner resowner, int nevents); +extern void FreeWaitEventSet(WaitEventSet *set); +extern void FreeWaitEventSetAfterFork(WaitEventSet *set); +extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, + struct Latch *latch, void *user_data); +extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, + struct Latch *latch); +extern int WaitEventSetWait(WaitEventSet *set, long timeout, + WaitEvent *occurred_events, int nevents, + uint32 wait_event_info); +extern int GetNumRegisteredWaitEvents(WaitEventSet *set); +extern bool WaitEventSetCanReportClosed(void); + +#ifndef WIN32 +extern void WakeupMyProc(void); +extern void WakeupOtherProc(int pid); +#endif + +#endif /* WAITEVENTSET_H */ diff --git a/src/include/tcop/backend_startup.h b/src/include/tcop/backend_startup.h index 993b013afddc6..e8639688c00bc 100644 --- a/src/include/tcop/backend_startup.h +++ b/src/include/tcop/backend_startup.h @@ -4,7 +4,7 @@ * prototypes for backend_startup.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/backend_startup.h @@ -14,8 +14,15 @@ #ifndef BACKEND_STARTUP_H #define BACKEND_STARTUP_H +#include "utils/timestamp.h" + /* GUCs */ extern PGDLLIMPORT bool Trace_connection_negotiation; +extern PGDLLIMPORT uint32 log_connections; +extern PGDLLIMPORT char *log_connections_string; + +/* Other globals */ +extern PGDLLIMPORT struct ConnectionTiming conn_timing; /* * CAC_state is passed from postmaster to the backend process, to indicate @@ -29,7 +36,7 @@ typedef enum CAC_state CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, - CAC_NOTCONSISTENT, + CAC_NOTHOTSTANDBY, CAC_TOOMANY, } CAC_state; @@ -37,8 +44,79 @@ typedef enum CAC_state typedef struct BackendStartupData { CAC_state canAcceptConnections; + + /* + * Time at which the connection client socket is created. Only used for + * client and wal sender connections. + */ + TimestampTz socket_created; + + /* + * Time at which the postmaster initiates process creation -- either + * through fork or otherwise. Only used for client and wal sender + * connections. + */ + TimestampTz fork_started; } BackendStartupData; -extern void BackendMain(char *startup_data, size_t startup_data_len) pg_attribute_noreturn(); +/* + * Granular control over which messages to log for the log_connections GUC. + * + * RECEIPT, AUTHENTICATION, AUTHORIZATION, and SETUP_DURATIONS are different + * aspects of connection establishment and backend setup for which we may emit + * a log message. + * + * ALL is a convenience alias equivalent to all of the above aspects. + * + * ON is backwards compatibility alias for the connection aspects that were + * logged in Postgres versions < 18. + */ +typedef enum LogConnectionOption +{ + LOG_CONNECTION_RECEIPT = (1 << 0), + LOG_CONNECTION_AUTHENTICATION = (1 << 1), + LOG_CONNECTION_AUTHORIZATION = (1 << 2), + LOG_CONNECTION_SETUP_DURATIONS = (1 << 3), + LOG_CONNECTION_ON = + LOG_CONNECTION_RECEIPT | + LOG_CONNECTION_AUTHENTICATION | + LOG_CONNECTION_AUTHORIZATION, + LOG_CONNECTION_ALL = + LOG_CONNECTION_RECEIPT | + LOG_CONNECTION_AUTHENTICATION | + LOG_CONNECTION_AUTHORIZATION | + LOG_CONNECTION_SETUP_DURATIONS, +} LogConnectionOption; + +/* + * A collection of timings of various stages of connection establishment and + * setup for client backends and WAL senders. + * + * Used to emit the setup_durations log message for the log_connections GUC. + */ +typedef struct ConnectionTiming +{ + /* + * The time at which the client socket is created and the time at which + * the connection is fully set up and first ready for query. Together + * these represent the total connection establishment and setup time. + */ + TimestampTz socket_create; + TimestampTz ready_for_use; + + /* Time at which process creation was initiated */ + TimestampTz fork_start; + + /* Time at which process creation was completed */ + TimestampTz fork_end; + + /* Time at which authentication started */ + TimestampTz auth_start; + + /* Time at which authentication was finished */ + TimestampTz auth_end; +} ConnectionTiming; + +pg_noreturn extern void BackendMain(const void *startup_data, size_t startup_data_len); #endif /* BACKEND_STARTUP_H */ diff --git a/src/include/tcop/cmdtag.h b/src/include/tcop/cmdtag.h index 23c99d7eca654..8d027fcc457cd 100644 --- a/src/include/tcop/cmdtag.h +++ b/src/include/tcop/cmdtag.h @@ -3,7 +3,7 @@ * cmdtag.h * Declarations for commandtag names and enumeration. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/cmdtag.h diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h index 7fdcec6dd93d9..d250a714d597d 100644 --- a/src/include/tcop/cmdtaglist.h +++ b/src/include/tcop/cmdtaglist.h @@ -8,7 +8,7 @@ * determined by the PG_CMDTAG macro, which is not defined in this file; * it can be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/cmdtaglist.h diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h index bb94342119e6e..36510451d833f 100644 --- a/src/include/tcop/deparse_utility.h +++ b/src/include/tcop/deparse_utility.h @@ -2,7 +2,7 @@ * * deparse_utility.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/deparse_utility.h diff --git a/src/include/tcop/dest.h b/src/include/tcop/dest.h index a3d521b6f97f8..00c092e3d7c06 100644 --- a/src/include/tcop/dest.h +++ b/src/include/tcop/dest.h @@ -57,7 +57,7 @@ * calls in portal and cursor manipulations. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/dest.h diff --git a/src/include/tcop/fastpath.h b/src/include/tcop/fastpath.h index da0bd715f517e..3a94ec4f8a6ae 100644 --- a/src/include/tcop/fastpath.h +++ b/src/include/tcop/fastpath.h @@ -3,7 +3,7 @@ * fastpath.h * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/fastpath.h diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h index 073fb323bc128..fa3cc5f2dfcaf 100644 --- a/src/include/tcop/pquery.h +++ b/src/include/tcop/pquery.h @@ -4,7 +4,7 @@ * prototypes for pquery.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/pquery.h @@ -36,7 +36,7 @@ extern void PortalSetResultFormat(Portal portal, int nFormats, int16 *formats); extern bool PortalRun(Portal portal, long count, bool isTopLevel, - bool run_once, DestReceiver *dest, DestReceiver *altdest, + DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc); extern uint64 PortalRunFetch(Portal portal, diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 147a294950efd..a83cc4f485016 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -4,7 +4,7 @@ * prototypes for postgres.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/tcopprot.h @@ -21,12 +21,8 @@ #include "utils/queryenvironment.h" -/* Required daylight between max_stack_depth and the kernel limit, in bytes */ -#define STACK_DEPTH_SLOP (512 * 1024L) - extern PGDLLIMPORT CommandDest whereToSendOutput; extern PGDLLIMPORT const char *debug_query_string; -extern PGDLLIMPORT int max_stack_depth; extern PGDLLIMPORT int PostAuthDelay; extern PGDLLIMPORT int client_connection_check_interval; @@ -43,6 +39,12 @@ typedef enum extern PGDLLIMPORT bool Log_disconnections; extern PGDLLIMPORT int log_statement; +/* Flags for restrict_nonsystem_relation_kind value */ +#define RESTRICT_RELKIND_VIEW 0x01 +#define RESTRICT_RELKIND_FOREIGN_TABLE 0x02 + +extern PGDLLIMPORT int restrict_nonsystem_relation_kind; + extern List *pg_parse_query(const char *query_string); extern List *pg_rewrite_query(Query *query); extern List *pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, @@ -67,20 +69,19 @@ extern List *pg_plan_queries(List *querytrees, const char *query_string, ParamListInfo boundParams); extern void die(SIGNAL_ARGS); -extern void quickdie(SIGNAL_ARGS) pg_attribute_noreturn(); +pg_noreturn extern void quickdie(SIGNAL_ARGS); extern void StatementCancelHandler(SIGNAL_ARGS); -extern void FloatExceptionHandler(SIGNAL_ARGS) pg_attribute_noreturn(); +pg_noreturn extern void FloatExceptionHandler(SIGNAL_ARGS); extern void HandleRecoveryConflictInterrupt(ProcSignalReason reason); extern void ProcessClientReadInterrupt(bool blocked); extern void ProcessClientWriteInterrupt(bool blocked); extern void process_postgres_switches(int argc, char *argv[], GucContext ctx, const char **dbname); -extern void PostgresSingleUserMain(int argc, char *argv[], - const char *username) pg_attribute_noreturn(); -extern void PostgresMain(const char *dbname, - const char *username) pg_attribute_noreturn(); -extern long get_stack_depth_rlimit(void); +pg_noreturn extern void PostgresSingleUserMain(int argc, char *argv[], + const char *username); +pg_noreturn extern void PostgresMain(const char *dbname, + const char *username); extern void ResetUsage(void); extern void ShowUsage(const char *title); extern int check_log_duration(char *msec_str, bool was_logged); diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h index 9aa1de3879000..2f05dd50e2584 100644 --- a/src/include/tcop/utility.h +++ b/src/include/tcop/utility.h @@ -4,7 +4,7 @@ * prototypes for utility.c. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tcop/utility.h diff --git a/src/include/tsearch/dicts/regis.h b/src/include/tsearch/dicts/regis.h index d3d9b6ec22da3..3f40cdc92e452 100644 --- a/src/include/tsearch/dicts/regis.h +++ b/src/include/tsearch/dicts/regis.h @@ -4,7 +4,7 @@ * * Declarations for fast regex subset, used by ISpell * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/tsearch/dicts/regis.h * diff --git a/src/include/tsearch/dicts/spell.h b/src/include/tsearch/dicts/spell.h index 10c05769ac734..919b7df63705b 100644 --- a/src/include/tsearch/dicts/spell.h +++ b/src/include/tsearch/dicts/spell.h @@ -4,7 +4,7 @@ * * Declarations for ISpell dictionary * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/tsearch/dicts/spell.h * @@ -66,7 +66,7 @@ typedef struct spell_struct * flag is filled in by NIImportDictionary(). After * NISortDictionary(), d is used instead of flag. */ - char *flag; + const char *flag; /* d is used in mkSPNode() */ struct { @@ -86,15 +86,15 @@ typedef struct spell_struct */ typedef struct aff_struct { - char *flag; + const char *flag; /* FF_SUFFIX or FF_PREFIX */ uint32 type:1, flagflags:7, issimple:1, isregis:1, replen:14; - char *find; - char *repl; + const char *find; + const char *repl; union { /* @@ -146,7 +146,7 @@ typedef struct AffixNode typedef struct { - char *affix; + const char *affix; int len; bool issuffix; } CMPDAffix; @@ -170,7 +170,7 @@ typedef struct CompoundAffixFlag union { /* Flag name if flagMode is FM_CHAR or FM_LONG */ - char *s; + const char *s; /* Flag name if flagMode is FM_NUM */ uint32 i; } flag; @@ -192,7 +192,7 @@ typedef struct SPNode *Dictionary; /* Array of sets of affixes */ - char **AffixData; + const char **AffixData; int lenAffixData; int nAffixData; bool useFlagAliases; @@ -229,7 +229,7 @@ typedef struct size_t avail; /* free space remaining at firstfree */ } IspellDict; -extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word); +extern TSLexeme *NINormalizeWord(IspellDict *Conf, const char *word); extern void NIStartBuild(IspellDict *Conf); extern void NIImportAffixes(IspellDict *Conf, const char *filename); diff --git a/src/include/tsearch/ts_cache.h b/src/include/tsearch/ts_cache.h index 2f8fcd4e9c9f6..ed7527bb954db 100644 --- a/src/include/tsearch/ts_cache.h +++ b/src/include/tsearch/ts_cache.h @@ -3,7 +3,7 @@ * ts_cache.h * Tsearch related object caches. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/tsearch/ts_cache.h diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h index abc21a7ebeae6..c29588d8532c6 100644 --- a/src/include/tsearch/ts_locale.h +++ b/src/include/tsearch/ts_locale.h @@ -3,7 +3,7 @@ * ts_locale.h * locale compatibility layer for tsearch * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * src/include/tsearch/ts_locale.h * @@ -39,14 +39,8 @@ typedef struct #define COPYCHAR(d,s) memcpy(d, s, pg_mblen(s)) -extern int t_isdigit(const char *ptr); -extern int t_isspace(const char *ptr); extern int t_isalpha(const char *ptr); extern int t_isalnum(const char *ptr); -extern int t_isprint(const char *ptr); - -extern char *lowerstr(const char *str); -extern char *lowerstr_with_len(const char *str, int len); extern bool tsearch_readline_begin(tsearch_readline_state *stp, const char *filename); diff --git a/src/include/tsearch/ts_public.h b/src/include/tsearch/ts_public.h index e1549863a12c8..52e8bde683e95 100644 --- a/src/include/tsearch/ts_public.h +++ b/src/include/tsearch/ts_public.h @@ -4,7 +4,7 @@ * Public interface to various tsearch modules, such as * parsers and dictionaries. * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * src/include/tsearch/ts_public.h * @@ -104,7 +104,7 @@ typedef struct } StopList; extern void readstoplist(const char *fname, StopList *s, - char *(*wordop) (const char *)); + char *(*wordop) (const char *, size_t, Oid)); extern bool searchstoplist(StopList *s, char *key); /* diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h index 060d539096e8a..d9d5334f28ba1 100644 --- a/src/include/tsearch/ts_type.h +++ b/src/include/tsearch/ts_type.h @@ -3,7 +3,7 @@ * ts_type.h * Definitions for the tsvector and tsquery types * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * src/include/tsearch/ts_type.h * diff --git a/src/include/tsearch/ts_utils.h b/src/include/tsearch/ts_utils.h index 6dc739086494a..7debc85ed80fa 100644 --- a/src/include/tsearch/ts_utils.h +++ b/src/include/tsearch/ts_utils.h @@ -3,7 +3,7 @@ * ts_utils.h * helper utilities for tsearch * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * src/include/tsearch/ts_utils.h * diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 731d84b2a939c..01ae5b719fd78 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -4,7 +4,7 @@ * Definition of (and support for) access control list data structures. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/acl.h diff --git a/src/include/utils/aclchk_internal.h b/src/include/utils/aclchk_internal.h index 11cd87dda7dfe..62af290779a8f 100644 --- a/src/include/utils/aclchk_internal.h +++ b/src/include/utils/aclchk_internal.h @@ -2,7 +2,7 @@ * * aclchk_internal.h * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/aclchk_internal.h diff --git a/src/include/utils/array.h b/src/include/utils/array.h index 157cc0e4c6e77..52f1fbf8d43f6 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -51,7 +51,7 @@ * arrays holding the elements. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/array.h diff --git a/src/include/utils/arrayaccess.h b/src/include/utils/arrayaccess.h index fff31e2984611..0e48ee07f57fd 100644 --- a/src/include/utils/arrayaccess.h +++ b/src/include/utils/arrayaccess.h @@ -4,7 +4,7 @@ * Declarations for element-by-element access to Postgres arrays. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/arrayaccess.h diff --git a/src/include/utils/ascii.h b/src/include/utils/ascii.h index 863f0f7e0e8d1..02d45d5494533 100644 --- a/src/include/utils/ascii.h +++ b/src/include/utils/ascii.h @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------- * ascii.h * - * Portions Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1999-2025, PostgreSQL Global Development Group * * src/include/utils/ascii.h * diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h index a1a9bfc0fb906..f684a772af52a 100644 --- a/src/include/utils/attoptcache.h +++ b/src/include/utils/attoptcache.h @@ -3,7 +3,7 @@ * attoptcache.h * Attribute options cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/attoptcache.h diff --git a/src/include/utils/backend_progress.h b/src/include/utils/backend_progress.h index 7b63d38f9756f..dda813ab4076b 100644 --- a/src/include/utils/backend_progress.h +++ b/src/include/utils/backend_progress.h @@ -6,7 +6,7 @@ * backend's command progress counters, without ascribing meaning to the * individual fields. See commands/progress.h and system_views.sql for that. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/utils/backend_progress.h * ---------- diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h index 7b7f6f59d07a8..3016501ac0597 100644 --- a/src/include/utils/backend_status.h +++ b/src/include/utils/backend_status.h @@ -2,7 +2,7 @@ * backend_status.h * Definitions related to backend status reporting * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/utils/backend_status.h * ---------- @@ -24,6 +24,7 @@ typedef enum BackendState { STATE_UNDEFINED, + STATE_STARTING, STATE_IDLE, STATE_RUNNING, STATE_IDLEINTRANSACTION, @@ -169,7 +170,10 @@ typedef struct PgBackendStatus int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM]; /* query identifier, optionally computed using post_parse_analyze_hook */ - uint64 st_query_id; + int64 st_query_id; + + /* plan identifier, optionally computed using planner_hook */ + int64 st_plan_id; } PgBackendStatus; @@ -299,7 +303,7 @@ extern PGDLLIMPORT PgBackendStatus *MyBEEntry; * ---------- */ extern Size BackendStatusShmemSize(void); -extern void CreateSharedBackendStatus(void); +extern void BackendStatusShmemInit(void); /* ---------- @@ -309,20 +313,25 @@ extern void CreateSharedBackendStatus(void); /* Initialization functions */ extern void pgstat_beinit(void); -extern void pgstat_bestart(void); +extern void pgstat_bestart_initial(void); +extern void pgstat_bestart_security(void); +extern void pgstat_bestart_final(void); extern void pgstat_clear_backend_activity_snapshot(void); /* Activity reporting functions */ extern void pgstat_report_activity(BackendState state, const char *cmd_str); -extern void pgstat_report_query_id(uint64 query_id, bool force); +extern void pgstat_report_query_id(int64 query_id, bool force); +extern void pgstat_report_plan_id(int64 plan_id, bool force); extern void pgstat_report_tempfile(size_t filesize); extern void pgstat_report_appname(const char *appname); extern void pgstat_report_xact_timestamp(TimestampTz tstamp); extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser); extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen); -extern uint64 pgstat_get_my_query_id(void); +extern int64 pgstat_get_my_query_id(void); +extern int64 pgstat_get_my_plan_id(void); +extern BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber); /* ---------- diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 359c570f23e20..1c98c7d2255ce 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -4,7 +4,7 @@ * Declarations for operations on built-in types. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/builtins.h diff --git a/src/include/utils/bytea.h b/src/include/utils/bytea.h index dcc55d879b920..7b31fc84ba46b 100644 --- a/src/include/utils/bytea.h +++ b/src/include/utils/bytea.h @@ -4,7 +4,7 @@ * Declarations for BYTEA data type support. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/bytea.h diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h index 3fb9647b87c87..277ec33c00bac 100644 --- a/src/include/utils/catcache.h +++ b/src/include/utils/catcache.h @@ -10,7 +10,7 @@ * guarantee that there can only be one matching row for a key combination. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/catcache.h @@ -220,11 +220,13 @@ extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys, extern void ReleaseCatCacheList(CatCList *list); extern void ResetCatalogCaches(void); +extern void ResetCatalogCachesExt(bool debug_discard); extern void CatalogCacheFlushCatalog(Oid catId); extern void CatCacheInvalidate(CatCache *cache, uint32 hashValue); extern void PrepareToInvalidateCacheTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple, - void (*function) (int, uint32, Oid)); + void (*function) (int, uint32, Oid, void *), + void *context); #endif /* CATCACHE_H */ diff --git a/src/include/utils/combocid.h b/src/include/utils/combocid.h index 00a9b561ec98f..4a2069b2869b7 100644 --- a/src/include/utils/combocid.h +++ b/src/include/utils/combocid.h @@ -4,7 +4,7 @@ * Combo command ID support routines * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/combocid.h diff --git a/src/include/utils/conffiles.h b/src/include/utils/conffiles.h index 82ca89bbccf5a..799abb41bd066 100644 --- a/src/include/utils/conffiles.h +++ b/src/include/utils/conffiles.h @@ -3,7 +3,7 @@ * * Utilities related to configuration files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/conffiles.h diff --git a/src/include/utils/date.h b/src/include/utils/date.h index aaed6471a633a..bb5c1e57b073e 100644 --- a/src/include/utils/date.h +++ b/src/include/utils/date.h @@ -4,7 +4,7 @@ * Definitions for the SQL "date" and "time" types. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/date.h diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index e4ac2b8e7f6c9..53a1c69eda52d 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -6,7 +6,7 @@ * including date, and time. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/datetime.h @@ -351,6 +351,8 @@ extern pg_tz *DecodeTimezoneNameToTz(const char *tzname); extern int DecodeTimezoneAbbrevPrefix(const char *str, int *offset, pg_tz **tz); +extern void ClearTimeZoneAbbrevCache(void); + extern int j2day(int date); extern struct Node *TemporalSimplify(int32 max_precis, struct Node *node); diff --git a/src/include/utils/datum.h b/src/include/utils/datum.h index 8e3728f1b551f..fce048ec033f3 100644 --- a/src/include/utils/datum.h +++ b/src/include/utils/datum.h @@ -8,7 +8,7 @@ * of the Datum. (We do it this way because in most situations the caller * can look up the info just once and use it for many per-datum operations.) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/datum.h diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h index 8dff964bf3334..9eca87889087c 100644 --- a/src/include/utils/dsa.h +++ b/src/include/utils/dsa.h @@ -3,7 +3,7 @@ * dsa.h * Dynamic shared memory areas. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -66,7 +66,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic; #define dsa_pointer_atomic_write pg_atomic_write_u64 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64 -#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x" +#define DSA_POINTER_FORMAT "%016" PRIx64 #endif /* Flags for dsa_allocate_extended. */ @@ -97,7 +97,7 @@ typedef pg_atomic_uint64 dsa_pointer_atomic; #define DSA_DEFAULT_INIT_SEGMENT_SIZE ((size_t) (1 * 1024 * 1024)) /* The minimum size of a DSM segment. */ -#define DSA_MIN_SEGMENT_SIZE ((size_t) (256 * 1024L)) +#define DSA_MIN_SEGMENT_SIZE ((size_t) (256 * 1024)) /* The maximum size of a DSM segment. */ #define DSA_MAX_SEGMENT_SIZE ((size_t) 1 << DSA_OFFSET_WIDTH) diff --git a/src/include/utils/dynahash.h b/src/include/utils/dynahash.h index 418166f01ec93..8a31d9524e2a4 100644 --- a/src/include/utils/dynahash.h +++ b/src/include/utils/dynahash.h @@ -4,7 +4,7 @@ * POSTGRES dynahash.h file definitions * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 054dd2bf62f38..675f4f5f4694d 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -4,7 +4,7 @@ * POSTGRES error reporting/logging definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/elog.h @@ -195,6 +195,7 @@ extern int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4); extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2); +extern int errhint_internal(const char *fmt,...) pg_attribute_printf(1, 2); extern int errhint_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4); @@ -414,17 +415,8 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; error_context_stack = _save_context_stack##__VA_ARGS__; \ } while (0) -/* - * Some compilers understand pg_attribute_noreturn(); for other compilers, - * insert pg_unreachable() so that the compiler gets the point. - */ -#ifdef HAVE_PG_ATTRIBUTE_NORETURN #define PG_RE_THROW() \ pg_re_throw() -#else -#define PG_RE_THROW() \ - (pg_re_throw(), pg_unreachable()) -#endif extern PGDLLIMPORT sigjmp_buf *PG_exception_stack; @@ -475,9 +467,9 @@ extern void EmitErrorReport(void); extern ErrorData *CopyErrorData(void); extern void FreeErrorData(ErrorData *edata); extern void FlushErrorState(void); -extern void ReThrowError(ErrorData *edata) pg_attribute_noreturn(); +pg_noreturn extern void ReThrowError(ErrorData *edata); extern void ThrowErrorData(ErrorData *edata); -extern void pg_re_throw(void) pg_attribute_noreturn(); +pg_noreturn extern void pg_re_throw(void); extern char *GetErrorContextStack(void); diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h index 573e1de4066c9..9d9fcb8657b97 100644 --- a/src/include/utils/evtcache.h +++ b/src/include/utils/evtcache.h @@ -3,7 +3,7 @@ * evtcache.h * Special-purpose cache for event trigger data. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/include/utils/expandeddatum.h b/src/include/utils/expandeddatum.h index 4a6637dae3478..cde9a0c073b8c 100644 --- a/src/include/utils/expandeddatum.h +++ b/src/include/utils/expandeddatum.h @@ -34,7 +34,7 @@ * value if they fail partway through. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/expandeddatum.h diff --git a/src/include/utils/expandedrecord.h b/src/include/utils/expandedrecord.h index 936aaf19a1f59..4e5cbc44d635d 100644 --- a/src/include/utils/expandedrecord.h +++ b/src/include/utils/expandedrecord.h @@ -3,7 +3,7 @@ * expandedrecord.h * Declarations for composite expanded objects. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/expandedrecord.h diff --git a/src/include/utils/float.h b/src/include/utils/float.h index 7d1badd292ad1..0e2e9ec534783 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -3,7 +3,7 @@ * float.h * Definitions for the built-in floating-point types * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -37,9 +37,9 @@ extern PGDLLIMPORT int extra_float_digits; /* * Utility functions in float.c */ -extern void float_overflow_error(void) pg_attribute_noreturn(); -extern void float_underflow_error(void) pg_attribute_noreturn(); -extern void float_zero_divide_error(void) pg_attribute_noreturn(); +pg_noreturn extern void float_overflow_error(void); +pg_noreturn extern void float_underflow_error(void); +pg_noreturn extern void float_zero_divide_error(void); extern int is_infinite(float8 val); extern float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, diff --git a/src/include/utils/fmgrtab.h b/src/include/utils/fmgrtab.h index 151dd74055d0b..8d43583c6880f 100644 --- a/src/include/utils/fmgrtab.h +++ b/src/include/utils/fmgrtab.h @@ -3,7 +3,7 @@ * fmgrtab.h * The function manager's table of internal functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/fmgrtab.h diff --git a/src/include/utils/formatting.h b/src/include/utils/formatting.h index cde030414ee44..835307dac0935 100644 --- a/src/include/utils/formatting.h +++ b/src/include/utils/formatting.h @@ -4,7 +4,7 @@ * src/include/utils/formatting.h * * - * Portions Copyright (c) 1999-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1999-2025, PostgreSQL Global Development Group * * The PostgreSQL routines for a DateTime/int/float/numeric formatting, * inspired by the Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines. @@ -21,6 +21,7 @@ extern char *str_tolower(const char *buff, size_t nbytes, Oid collid); extern char *str_toupper(const char *buff, size_t nbytes, Oid collid); extern char *str_initcap(const char *buff, size_t nbytes, Oid collid); +extern char *str_casefold(const char *buff, size_t nbytes, Oid collid); extern char *asc_tolower(const char *buff, size_t nbytes); extern char *asc_toupper(const char *buff, size_t nbytes); diff --git a/src/include/utils/freepage.h b/src/include/utils/freepage.h index c7c004657f015..18643a8c35d31 100644 --- a/src/include/utils/freepage.h +++ b/src/include/utils/freepage.h @@ -3,7 +3,7 @@ * freepage.h * Management of page-organized free memory. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/freepage.h diff --git a/src/include/utils/funccache.h b/src/include/utils/funccache.h new file mode 100644 index 0000000000000..e0112ebfa11de --- /dev/null +++ b/src/include/utils/funccache.h @@ -0,0 +1,134 @@ +/*------------------------------------------------------------------------- + * + * funccache.h + * Function cache definitions. + * + * See funccache.c for comments. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/utils/funccache.h + * + *------------------------------------------------------------------------- + */ +#ifndef FUNCCACHE_H +#define FUNCCACHE_H + +#include "access/htup_details.h" +#include "fmgr.h" +#include "storage/itemptr.h" + +struct CachedFunctionHashKey; /* forward references */ +struct CachedFunction; + +/* + * Callback that cached_function_compile() invokes when it's necessary to + * compile a cached function. The callback must fill in *function (except + * for the fields of struct CachedFunction), or throw an error if trouble. + * fcinfo: current call information + * procTup: function's pg_proc row from catcache + * hashkey: hash key that will be used for the function + * function: pre-zeroed workspace, of size passed to cached_function_compile() + * forValidator: passed through from cached_function_compile() + */ +typedef void (*CachedFunctionCompileCallback) (FunctionCallInfo fcinfo, + HeapTuple procTup, + const struct CachedFunctionHashKey *hashkey, + struct CachedFunction *function, + bool forValidator); + +/* + * Callback called when discarding a cache entry. Free any free-able + * subsidiary data of cfunc, but not the struct CachedFunction itself. + */ +typedef void (*CachedFunctionDeleteCallback) (struct CachedFunction *cfunc); + +/* + * Hash lookup key for functions. This must account for all aspects + * of a specific call that might lead to different data types or + * collations being used within the function. + */ +typedef struct CachedFunctionHashKey +{ + Oid funcOid; + + bool isTrigger; /* true if called as a DML trigger */ + bool isEventTrigger; /* true if called as an event trigger */ + + /* be careful that pad bytes in this struct get zeroed! */ + + /* + * We include the language-specific size of the function's cache entry in + * the cache key. This covers the case where CREATE OR REPLACE FUNCTION + * is used to change the implementation language, and the new language + * also uses funccache.c but needs a different-sized cache entry. + */ + Size cacheEntrySize; + + /* + * For a trigger function, the OID of the trigger is part of the hash key + * --- we want to compile the trigger function separately for each trigger + * it is used with, in case the rowtype or transition table names are + * different. Zero if not called as a DML trigger. + */ + Oid trigOid; + + /* + * We must include the input collation as part of the hash key too, + * because we have to generate different plans (with different Param + * collations) for different collation settings. + */ + Oid inputCollation; + + /* Number of arguments (counting input arguments only, ie pronargs) */ + int nargs; + + /* If you change anything below here, fix hashing code in funccache.c! */ + + /* + * If relevant, the result descriptor for a function returning composite. + */ + TupleDesc callResultType; + + /* + * Input argument types, with any polymorphic types resolved to actual + * types. Only the first nargs entries are valid. + */ + Oid argtypes[FUNC_MAX_ARGS]; +} CachedFunctionHashKey; + +/* + * Representation of a compiled function. This struct contains just the + * fields that funccache.c needs to deal with. It will typically be + * embedded in a larger struct containing function-language-specific data. + */ +typedef struct CachedFunction +{ + /* back-link to hashtable entry, or NULL if not in hash table */ + CachedFunctionHashKey *fn_hashkey; + /* xmin and ctid of function's pg_proc row; used to detect invalidation */ + TransactionId fn_xmin; + ItemPointerData fn_tid; + /* deletion callback */ + CachedFunctionDeleteCallback dcallback; + + /* this field changes when the function is used: */ + uint64 use_count; +} CachedFunction; + +extern CachedFunction *cached_function_compile(FunctionCallInfo fcinfo, + CachedFunction *function, + CachedFunctionCompileCallback ccallback, + CachedFunctionDeleteCallback dcallback, + Size cacheEntrySize, + bool includeResultType, + bool forValidator); +extern void cfunc_resolve_polymorphic_argtypes(int numargs, + Oid *argtypes, + char *argmodes, + Node *call_expr, + bool forValidator, + const char *proname); + +#endif /* FUNCCACHE_H */ diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 02e2062e8f0df..8a9df75c93c9d 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -3,7 +3,7 @@ * geo_decls.h - Declarations for various 2D constructs. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/geo_decls.h diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index cd2cee3dfe02a..f619100467df2 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -3,7 +3,7 @@ * * External declarations pertaining to Grand Unified Configuration. * - * Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Copyright (c) 2000-2025, PostgreSQL Global Development Group * Written by Peter Eisentraut . * * src/include/utils/guc.h @@ -17,9 +17,13 @@ #include "utils/array.h" -/* upper limit for GUC variables measured in kilobytes of memory */ -/* note that various places assume the byte size fits in a "long" variable */ -#if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4 +/* + * Maximum for integer GUC variables that are measured in kilobytes of memory. + * This value is chosen to ensure that the corresponding number of bytes fits + * into a variable of type size_t or ssize_t. Be sure to compute the number + * of bytes like "guc_var * (Size) 1024" to avoid int-width overflow. + */ +#if SIZEOF_SIZE_T > 4 #define MAX_KILOBYTES INT_MAX #else #define MAX_KILOBYTES (INT_MAX / 1024) @@ -223,6 +227,7 @@ typedef enum #define GUC_DISALLOW_IN_AUTO_FILE \ 0x002000 /* can't set in PG_AUTOCONF_FILENAME */ #define GUC_RUNTIME_COMPUTED 0x004000 /* delay processing in 'postgres -C' */ +#define GUC_ALLOW_IN_PARALLEL 0x008000 /* allow setting in parallel mode */ #define GUC_UNIT_KB 0x01000000 /* value is in kilobytes */ #define GUC_UNIT_BLOCKS 0x02000000 /* value is in blocks */ @@ -245,6 +250,12 @@ extern PGDLLIMPORT bool Debug_print_parse; extern PGDLLIMPORT bool Debug_print_rewritten; extern PGDLLIMPORT bool Debug_pretty_print; +#ifdef DEBUG_NODE_TESTS_ENABLED +extern PGDLLIMPORT bool Debug_copy_parse_plan_trees; +extern PGDLLIMPORT bool Debug_write_read_parse_plan_trees; +extern PGDLLIMPORT bool Debug_raw_expression_coverage_test; +#endif + extern PGDLLIMPORT bool log_parser_stats; extern PGDLLIMPORT bool log_planner_stats; extern PGDLLIMPORT bool log_executor_stats; @@ -288,10 +299,7 @@ extern PGDLLIMPORT int tcp_user_timeout; extern PGDLLIMPORT char *role_string; extern PGDLLIMPORT bool in_hot_standby_guc; - -#ifdef TRACE_SORT extern PGDLLIMPORT bool trace_sort; -#endif #ifdef DEBUG_BOUNDED_SORT extern PGDLLIMPORT bool optimize_bounded_sort; @@ -308,11 +316,12 @@ extern PGDLLIMPORT bool optimize_bounded_sort; * that would then require including the definition of struct * config_enum_entry into those header files.) */ -extern const struct config_enum_entry archive_mode_options[]; -extern const struct config_enum_entry dynamic_shared_memory_options[]; -extern const struct config_enum_entry recovery_target_action_options[]; -extern const struct config_enum_entry wal_level_options[]; -extern const struct config_enum_entry wal_sync_method_options[]; +extern PGDLLIMPORT const struct config_enum_entry archive_mode_options[]; +extern PGDLLIMPORT const struct config_enum_entry dynamic_shared_memory_options[]; +extern PGDLLIMPORT const struct config_enum_entry io_method_options[]; +extern PGDLLIMPORT const struct config_enum_entry recovery_target_action_options[]; +extern PGDLLIMPORT const struct config_enum_entry wal_level_options[]; +extern PGDLLIMPORT const struct config_enum_entry wal_sync_method_options[]; /* * Functions exported by guc.c @@ -436,7 +445,7 @@ extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name); extern ArrayType *GUCArrayReset(ArrayType *array); extern void *guc_malloc(int elevel, size_t size); -extern pg_nodiscard void *guc_realloc(int elevel, void *old, size_t size); +pg_nodiscard extern void *guc_realloc(int elevel, void *old, size_t size); extern char *guc_strdup(int elevel, const char *src); extern void guc_free(void *ptr); diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h index 153c652c93ed9..799fa7ace6847 100644 --- a/src/include/utils/guc_hooks.h +++ b/src/include/utils/guc_hooks.h @@ -7,7 +7,7 @@ * declare them all here to avoid having to propagate guc.h into * a lot of unrelated header files. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/utils/guc_hooks.h * @@ -51,6 +51,8 @@ extern bool check_datestyle(char **newval, void **extra, GucSource source); extern void assign_datestyle(const char *newval, void *extra); extern bool check_debug_io_direct(char **newval, void **extra, GucSource source); extern void assign_debug_io_direct(const char *newval, void *extra); +extern bool check_log_connections(char **newval, void **extra, GucSource source); +extern void assign_log_connections(const char *newval, void *extra); extern bool check_default_table_access_method(char **newval, void **extra, GucSource source); extern bool check_default_tablespace(char **newval, void **extra, @@ -59,9 +61,9 @@ extern bool check_default_text_search_config(char **newval, void **extra, GucSou extern void assign_default_text_search_config(const char *newval, void *extra); extern bool check_default_with_oids(bool *newval, void **extra, GucSource source); -extern bool check_effective_io_concurrency(int *newval, void **extra, - GucSource source); extern bool check_huge_page_size(int *newval, void **extra, GucSource source); +extern void assign_io_method(int newval, void *extra); +extern bool check_io_max_concurrency(int *newval, void **extra, GucSource source); extern const char *show_in_hot_standby(void); extern bool check_locale_messages(char **newval, void **extra, GucSource source); extern void assign_locale_messages(const char *newval, void *extra); @@ -79,9 +81,9 @@ extern bool check_log_stats(bool *newval, void **extra, GucSource source); extern bool check_log_timezone(char **newval, void **extra, GucSource source); extern void assign_log_timezone(const char *newval, void *extra); extern const char *show_log_timezone(void); -extern bool check_maintenance_io_concurrency(int *newval, void **extra, - GucSource source); extern void assign_maintenance_io_concurrency(int newval, void *extra); +extern void assign_io_max_combine_limit(int newval, void *extra); +extern void assign_io_combine_limit(int newval, void *extra); extern bool check_max_slot_wal_keep_size(int *newval, void **extra, GucSource source); extern void assign_max_wal_size(int newval, void *extra); @@ -121,6 +123,9 @@ extern void assign_recovery_target_xid(const char *newval, void *extra); extern bool check_role(char **newval, void **extra, GucSource source); extern void assign_role(const char *newval, void *extra); extern const char *show_role(void); +extern bool check_restrict_nonsystem_relation_kind(char **newval, void **extra, + GucSource source); +extern void assign_restrict_nonsystem_relation_kind(const char *newval, void *extra); extern bool check_search_path(char **newval, void **extra, GucSource source); extern void assign_search_path(const char *newval, void *extra); extern bool check_serial_buffers(int *newval, void **extra, GucSource source); @@ -171,5 +176,7 @@ extern void assign_wal_sync_method(int new_wal_sync_method, void *extra); extern bool check_synchronized_standby_slots(char **newval, void **extra, GucSource source); extern void assign_synchronized_standby_slots(const char *newval, void *extra); +extern bool check_idle_replication_slot_timeout(int *newval, void **extra, + GucSource source); #endif /* GUC_HOOKS_H */ diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 0c0277c423026..f72ce944d7f9f 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -5,7 +5,7 @@ * * See src/backend/utils/misc/README for design notes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/utils/guc_tables.h * @@ -63,9 +63,9 @@ enum config_group RESOURCES_MEM, RESOURCES_DISK, RESOURCES_KERNEL, - RESOURCES_VACUUM_DELAY, RESOURCES_BGWRITER, - RESOURCES_ASYNCHRONOUS, + RESOURCES_IO, + RESOURCES_WORKER_PROCESSES, WAL_SETTINGS, WAL_CHECKPOINTS, WAL_ARCHIVING, @@ -87,7 +87,10 @@ enum config_group PROCESS_TITLE, STATS_MONITORING, STATS_CUMULATIVE, - AUTOVACUUM, + VACUUM_AUTOVACUUM, + VACUUM_COST_DELAY, + VACUUM_DEFAULT, + VACUUM_FREEZING, CLIENT_CONN_STATEMENT, CLIENT_CONN_LOCALE, CLIENT_CONN_PRELOAD, @@ -136,6 +139,21 @@ typedef struct guc_stack * applications may use the long description as well, and will append * it to the short description. (separated by a newline or '. ') * + * If the GUC accepts a special value like -1 to disable the feature, use a + * system default, etc., it should be mentioned in the long description with + * the following style: + * + * - Special values should be listed at the end of the long description. + * - Descriptions should use numerals (e.g., "0") instead of words (e.g., + * "zero"). + * - Special value mentions should be concise and direct (e.g., "0 disables + * the timeout.", "An empty string means use the operating system + * setting."). + * - Multiple special values should be listed in ascending order. + * + * As an exception, special values should _not_ be mentioned if the description + * would be too complex or if the meaning is sufficiently obvious. + * * srole is the role that set the current value, or BOOTSTRAP_SUPERUSERID * if the value came from an internal source or the config file. Similarly * for reset_srole (which is usually BOOTSTRAP_SUPERUSERID, but not always). diff --git a/src/include/utils/help_config.h b/src/include/utils/help_config.h index c27a54f1b913c..4e58f130054e0 100644 --- a/src/include/utils/help_config.h +++ b/src/include/utils/help_config.h @@ -3,7 +3,7 @@ * help_config.h * Interface to the --help-config option of main.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/utils/help_config.h * @@ -12,6 +12,6 @@ #ifndef HELP_CONFIG_H #define HELP_CONFIG_H 1 -extern void GucInfoMain(void) pg_attribute_noreturn(); +pg_noreturn extern void GucInfoMain(void); #endif diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h index da26941f6db5f..932cc4f34d90d 100644 --- a/src/include/utils/hsearch.h +++ b/src/include/utils/hsearch.h @@ -4,7 +4,7 @@ * exported definitions for utils/hash/dynahash.c; see notes therein * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/hsearch.h @@ -122,6 +122,8 @@ typedef struct HTAB *hashp; uint32 curBucket; /* index of current bucket */ HASHELEMENT *curEntry; /* current entry in bucket */ + bool hasHashvalue; /* true if hashvalue was provided */ + uint32 hashvalue; /* hashvalue to start seqscan over hash */ } HASH_SEQ_STATUS; /* @@ -141,6 +143,9 @@ extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr); extern long hash_get_num_entries(HTAB *hashp); extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp); +extern void hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status, + HTAB *hashp, + uint32 hashvalue); extern void *hash_seq_search(HASH_SEQ_STATUS *status); extern void hash_seq_term(HASH_SEQ_STATUS *status); extern void hash_freeze(HTAB *hashp); diff --git a/src/include/utils/index_selfuncs.h b/src/include/utils/index_selfuncs.h index a41cd2b7fd979..6c64db6d456cf 100644 --- a/src/include/utils/index_selfuncs.h +++ b/src/include/utils/index_selfuncs.h @@ -9,7 +9,7 @@ * If you make it depend on anything besides access/amapi.h, that's likely * a mistake. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/index_selfuncs.h diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h index 882617c704a04..ace8957f22082 100644 --- a/src/include/utils/inet.h +++ b/src/include/utils/inet.h @@ -4,7 +4,7 @@ * Declarations for operations on INET datatypes. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/inet.h diff --git a/src/include/utils/injection_point.h b/src/include/utils/injection_point.h index b4fc677c9b435..a37958e1835fd 100644 --- a/src/include/utils/injection_point.h +++ b/src/include/utils/injection_point.h @@ -2,7 +2,7 @@ * injection_point.h * Definitions related to injection points. * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/utils/injection_point.h *------------------------------------------------------------------------- @@ -12,17 +12,17 @@ #define INJECTION_POINT_H /* - * Injections points require --enable-injection-points. + * Injection points require --enable-injection-points. */ #ifdef USE_INJECTION_POINTS #define INJECTION_POINT_LOAD(name) InjectionPointLoad(name) -#define INJECTION_POINT(name) InjectionPointRun(name) -#define INJECTION_POINT_CACHED(name) InjectionPointCached(name) +#define INJECTION_POINT(name, arg) InjectionPointRun(name, arg) +#define INJECTION_POINT_CACHED(name, arg) InjectionPointCached(name, arg) #define IS_INJECTION_POINT_ATTACHED(name) IsInjectionPointAttached(name) #else #define INJECTION_POINT_LOAD(name) ((void) name) -#define INJECTION_POINT(name) ((void) name) -#define INJECTION_POINT_CACHED(name) ((void) name) +#define INJECTION_POINT(name, arg) ((void) name) +#define INJECTION_POINT_CACHED(name, arg) ((void) name) #define IS_INJECTION_POINT_ATTACHED(name) (false) #endif @@ -30,7 +30,8 @@ * Typedef for callback function launched by an injection point. */ typedef void (*InjectionPointCallback) (const char *name, - const void *private_data); + const void *private_data, + void *arg); extern Size InjectionPointShmemSize(void); extern void InjectionPointShmemInit(void); @@ -41,8 +42,8 @@ extern void InjectionPointAttach(const char *name, const void *private_data, int private_data_size); extern void InjectionPointLoad(const char *name); -extern void InjectionPointRun(const char *name); -extern void InjectionPointCached(const char *name); +extern void InjectionPointRun(const char *name, void *arg); +extern void InjectionPointCached(const char *name, void *arg); extern bool IsInjectionPointAttached(const char *name); extern bool InjectionPointDetach(const char *name); diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h index 24695facf2218..9b871caef622f 100644 --- a/src/include/utils/inval.h +++ b/src/include/utils/inval.h @@ -4,7 +4,7 @@ * POSTGRES cache invalidation dispatcher definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/inval.h @@ -22,12 +22,17 @@ extern PGDLLIMPORT int debug_discard_caches; typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, uint32 hashvalue); typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid); +typedef void (*RelSyncCallbackFunction) (Datum arg, Oid relid); extern void AcceptInvalidationMessages(void); extern void AtEOXact_Inval(bool isCommit); +extern void PreInplace_Inval(void); +extern void AtInplace_Inval(void); +extern void ForgetInplace_Inval(void); + extern void AtEOSubXact_Inval(bool isCommit); extern void PostPrepare_Inval(void); @@ -37,6 +42,9 @@ extern void CommandEndInvalidationMessages(void); extern void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple); +extern void CacheInvalidateHeapTupleInplace(Relation relation, + HeapTuple tuple, + HeapTuple newtuple); extern void CacheInvalidateCatalog(Oid catalogId); @@ -48,6 +56,10 @@ extern void CacheInvalidateRelcacheByTuple(HeapTuple classTuple); extern void CacheInvalidateRelcacheByRelid(Oid relid); +extern void CacheInvalidateRelSync(Oid relid); + +extern void CacheInvalidateRelSyncAll(void); + extern void CacheInvalidateSmgr(RelFileLocatorBackend rlocator); extern void CacheInvalidateRelmap(Oid databaseId); @@ -59,8 +71,13 @@ extern void CacheRegisterSyscacheCallback(int cacheid, extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg); +extern void CacheRegisterRelSyncCallback(RelSyncCallbackFunction func, + Datum arg); + extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue); +extern void CallRelSyncCallbacks(Oid relid); + extern void InvalidateSystemCaches(void); extern void InvalidateSystemCachesExtended(bool debug_discard); diff --git a/src/include/utils/json.h b/src/include/utils/json.h index 79c1062e1bf2c..49bbda7ac06a5 100644 --- a/src/include/utils/json.h +++ b/src/include/utils/json.h @@ -3,7 +3,7 @@ * json.h * Declarations for JSON data type support. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/json.h diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h index d589ace5a21e2..fecb33b9c671e 100644 --- a/src/include/utils/jsonb.h +++ b/src/include/utils/jsonb.h @@ -3,7 +3,7 @@ * jsonb.h * Declarations for jsonb data type support. * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/utils/jsonb.h * diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h index 93384d900a098..ebbab6f461615 100644 --- a/src/include/utils/jsonfuncs.h +++ b/src/include/utils/jsonfuncs.h @@ -3,7 +3,7 @@ * jsonfuncs.h * Functions to process JSON data types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/jsonfuncs.h @@ -41,7 +41,7 @@ typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, extern JsonLexContext *makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes); /* try to parse json, and errsave(escontext) on failure */ -extern bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, +extern bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, struct Node *escontext); #define pg_parse_json_or_ereport(lex, sem) \ diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h index ee35698d083ef..23a76d233e932 100644 --- a/src/include/utils/jsonpath.h +++ b/src/include/utils/jsonpath.h @@ -3,7 +3,7 @@ * jsonpath.h * Definitions for jsonpath datatype * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/include/utils/jsonpath.h diff --git a/src/include/utils/logtape.h b/src/include/utils/logtape.h index d310b974f92df..0eedece4741cd 100644 --- a/src/include/utils/logtape.h +++ b/src/include/utils/logtape.h @@ -5,7 +5,7 @@ * * See logtape.c for explanations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/logtape.h diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 20446f6f8368d..fa7c7e0323b10 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -3,7 +3,7 @@ * lsyscache.h * Convenience routines for common queries in the system catalog cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/lsyscache.h @@ -14,20 +14,21 @@ #define LSYSCACHE_H #include "access/attnum.h" +#include "access/cmptype.h" #include "access/htup.h" #include "nodes/pg_list.h" /* avoid including subscripting.h here */ struct SubscriptRoutines; -/* Result list element for get_op_btree_interpretation */ -typedef struct OpBtreeInterpretation +/* Result list element for get_op_index_interpretation */ +typedef struct OpIndexInterpretation { - Oid opfamily_id; /* btree opfamily containing operator */ - int strategy; /* its strategy number */ + Oid opfamily_id; /* opfamily containing operator */ + CompareType cmptype; /* its generic comparison type */ Oid oplefttype; /* declared left input datatype */ Oid oprighttype; /* declared right input datatype */ -} OpBtreeInterpretation; +} OpIndexInterpretation; /* I/O function selector for get_type_io_data */ typedef enum IOFuncSelector @@ -74,8 +75,10 @@ extern void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, Oid *righttype); extern Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy); +extern Oid get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, + CompareType cmptype); extern bool get_ordering_op_properties(Oid opno, - Oid *opfamily, Oid *opcintype, int16 *strategy); + Oid *opfamily, Oid *opcintype, CompareType *cmptype); extern Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse); extern Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type); extern List *get_mergejoin_opfamilies(Oid opno); @@ -83,7 +86,7 @@ extern bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno); extern bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno); -extern List *get_op_btree_interpretation(Oid opno); +extern List *get_op_index_interpretation(Oid opno); extern bool equality_ops_are_compatible(Oid opno1, Oid opno2); extern bool comparison_ops_are_compatible(Oid opno1, Oid opno2); extern Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, @@ -108,6 +111,8 @@ extern Oid get_opclass_input_type(Oid opclass); extern bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype); extern Oid get_opclass_method(Oid opclass); +extern Oid get_opfamily_method(Oid opfid); +extern char *get_opfamily_name(Oid opfid, bool missing_ok); extern RegProcedure get_opcode(Oid opno); extern char *get_opname(Oid opno); extern Oid get_op_rettype(Oid opno); diff --git a/src/include/utils/memdebug.h b/src/include/utils/memdebug.h index f62b10cbbd161..7309271834b9f 100644 --- a/src/include/utils/memdebug.h +++ b/src/include/utils/memdebug.h @@ -7,7 +7,7 @@ * empty definitions for Valgrind client request macros we use. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/memdebug.h diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index cd9596ff21930..8abc26abce272 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -7,7 +7,7 @@ * of the API of the memory management subsystem. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/memutils.h @@ -189,4 +189,134 @@ extern MemoryContext BumpContextCreate(MemoryContext parent, #define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024) #define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024) +/* + * pg_memory_is_all_zeros + * + * Test if a memory region starting at "ptr" and of size "len" is full of + * zeroes. + * + * The test is divided into multiple cases for safety reason and multiple + * phases for efficiency. + * + * Case 1: len < sizeof(size_t) bytes, then byte-by-byte comparison. + * Case 2: len < (sizeof(size_t) * 8 - 1) bytes: + * - Phase 1: byte-by-byte comparison, until the pointer is aligned. + * - Phase 2: size_t comparisons, with aligned pointers, up to the last + * location possible. + * - Phase 3: byte-by-byte comparison, until the end location. + * Case 3: len >= (sizeof(size_t) * 8) bytes, same as case 2 except that an + * additional phase is placed between Phase 1 and Phase 2, with + * (8 * sizeof(size_t)) comparisons using bitwise OR to encourage + * compilers to use SIMD instructions if available, up to the last + * aligned location possible. + * + * Case 1 and Case 2 are mandatory to ensure that we won't read beyond the + * memory area. This is portable for 32-bit and 64-bit architectures. + * + * Caller must ensure that "ptr" is not NULL. + */ +static inline bool +pg_memory_is_all_zeros(const void *ptr, size_t len) +{ + const unsigned char *p = (const unsigned char *) ptr; + const unsigned char *end = &p[len]; + const unsigned char *aligned_end = (const unsigned char *) + ((uintptr_t) end & (~(sizeof(size_t) - 1))); + + if (len < sizeof(size_t)) + { + while (p < end) + { + if (*p++ != 0) + return false; + } + return true; + } + + /* "len" in the [sizeof(size_t), sizeof(size_t) * 8 - 1] range */ + if (len < sizeof(size_t) * 8) + { + /* Compare bytes until the pointer "p" is aligned */ + while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0) + { + if (p == end) + return true; + if (*p++ != 0) + return false; + } + + /* + * Compare remaining size_t-aligned chunks. + * + * There is no risk to read beyond the memory area, as "aligned_end" + * cannot be higher than "end". + */ + for (; p < aligned_end; p += sizeof(size_t)) + { + if (*(size_t *) p != 0) + return false; + } + + /* Compare remaining bytes until the end */ + while (p < end) + { + if (*p++ != 0) + return false; + } + return true; + } + + /* "len" in the [sizeof(size_t) * 8, inf) range */ + + /* Compare bytes until the pointer "p" is aligned */ + while (((uintptr_t) p & (sizeof(size_t) - 1)) != 0) + { + if (p == end) + return true; + + if (*p++ != 0) + return false; + } + + /* + * Compare 8 * sizeof(size_t) chunks at once. + * + * For performance reasons, we manually unroll this loop and purposefully + * use bitwise-ORs to combine each comparison. This prevents boolean + * short-circuiting and lets the compiler know that it's safe to access + * all 8 elements regardless of the result of the other comparisons. This + * seems to be enough to coax a few compilers into using SIMD + * instructions. + */ + for (; p < aligned_end - (sizeof(size_t) * 7); p += sizeof(size_t) * 8) + { + if ((((size_t *) p)[0] != 0) | (((size_t *) p)[1] != 0) | + (((size_t *) p)[2] != 0) | (((size_t *) p)[3] != 0) | + (((size_t *) p)[4] != 0) | (((size_t *) p)[5] != 0) | + (((size_t *) p)[6] != 0) | (((size_t *) p)[7] != 0)) + return false; + } + + /* + * Compare remaining size_t-aligned chunks. + * + * There is no risk to read beyond the memory area, as "aligned_end" + * cannot be higher than "end". + */ + for (; p < aligned_end; p += sizeof(size_t)) + { + if (*(size_t *) p != 0) + return false; + } + + /* Compare remaining bytes until the end */ + while (p < end) + { + if (*p++ != 0) + return false; + } + + return true; +} + #endif /* MEMUTILS_H */ diff --git a/src/include/utils/memutils_internal.h b/src/include/utils/memutils_internal.h index 5ce2d9b5877a5..a6caa6335e34a 100644 --- a/src/include/utils/memutils_internal.h +++ b/src/include/utils/memutils_internal.h @@ -5,7 +5,7 @@ * functions for internal use. * * - * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2022-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/memutils_internal.h @@ -160,8 +160,8 @@ extern void MemoryContextCreate(MemoryContext node, extern void *MemoryContextAllocationFailure(MemoryContext context, Size size, int flags); -extern void MemoryContextSizeFailure(MemoryContext context, Size size, - int flags) pg_attribute_noreturn(); +pg_noreturn extern void MemoryContextSizeFailure(MemoryContext context, Size size, + int flags); static inline void MemoryContextCheckSize(MemoryContext context, Size size, int flags) diff --git a/src/include/utils/memutils_memorychunk.h b/src/include/utils/memutils_memorychunk.h index 56c49d604c395..36f9e4df1cbdb 100644 --- a/src/include/utils/memutils_memorychunk.h +++ b/src/include/utils/memutils_memorychunk.h @@ -76,7 +76,7 @@ * PointerGetMemoryChunk * MemoryChunkGetPointer * - * Portions Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2022-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/memutils_memorychunk.h diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build index 8d0cd4565369b..78c6b9b0a232a 100644 --- a/src/include/utils/meson.build +++ b/src/include/utils/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group wait_event_output = ['wait_event_types.h', 'pgstat_wait_event.c', 'wait_event_funcs_data.c'] wait_event_target = custom_target('wait_event_names', diff --git a/src/include/utils/multirangetypes.h b/src/include/utils/multirangetypes.h index 845254395b671..6e336170f53ab 100644 --- a/src/include/utils/multirangetypes.h +++ b/src/include/utils/multirangetypes.h @@ -4,7 +4,7 @@ * Declarations for Postgres multirange types. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/multirangetypes.h diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h index 43c75c436fe6b..9e79fc376cbea 100644 --- a/src/include/utils/numeric.h +++ b/src/include/utils/numeric.h @@ -5,7 +5,7 @@ * * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane. * - * Copyright (c) 1998-2024, PostgreSQL Global Development Group + * Copyright (c) 1998-2025, PostgreSQL Global Development Group * * src/include/utils/numeric.h * diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index 773a5d2c34738..e1b42267b22aa 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -18,7 +18,7 @@ * everything that should be freed. See utils/mmgr/README for more info. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/palloc.h @@ -79,10 +79,10 @@ extern void *palloc(Size size); extern void *palloc0(Size size); extern void *palloc_extended(Size size, int flags); extern void *palloc_aligned(Size size, Size alignto, int flags); -extern pg_nodiscard void *repalloc(void *pointer, Size size); -extern pg_nodiscard void *repalloc_extended(void *pointer, +pg_nodiscard extern void *repalloc(void *pointer, Size size); +pg_nodiscard extern void *repalloc_extended(void *pointer, Size size, int flags); -extern pg_nodiscard void *repalloc0(void *pointer, Size oldsize, Size size); +pg_nodiscard extern void *repalloc0(void *pointer, Size oldsize, Size size); extern void pfree(void *pointer); /* @@ -110,7 +110,7 @@ extern void pfree(void *pointer); /* Higher-limit allocators. */ extern void *MemoryContextAllocHuge(MemoryContext context, Size size); -extern pg_nodiscard void *repalloc_huge(void *pointer, Size size); +pg_nodiscard extern void *repalloc_huge(void *pointer, Size size); /* * Although this header file is nominally backend-only, certain frontend diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index a4ffa03622469..0fb6fc1c808ef 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -2,7 +2,7 @@ * * partcache.h * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/include/utils/partcache.h * diff --git a/src/include/utils/pg_crc.h b/src/include/utils/pg_crc.h index 6d76ce977192c..7900147ea82ff 100644 --- a/src/include/utils/pg_crc.h +++ b/src/include/utils/pg_crc.h @@ -26,7 +26,7 @@ * * The CRC-32C variant is in port/pg_crc32c.h. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/pg_crc.h diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index 040968d6ff295..7b8cbf58d2c43 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -4,7 +4,7 @@ * * src/include/utils/pg_locale.h * - * Copyright (c) 2002-2024, PostgreSQL Global Development Group + * Copyright (c) 2002-2025, PostgreSQL Global Development Group * *----------------------------------------------------------------------- */ @@ -12,26 +12,10 @@ #ifndef _PG_LOCALE_ #define _PG_LOCALE_ -#if defined(LOCALE_T_IN_XLOCALE) || defined(WCSTOMBS_L_IN_XLOCALE) -#include -#endif #ifdef USE_ICU #include #endif -#ifdef USE_ICU -/* - * ucol_strcollUTF8() was introduced in ICU 50, but it is buggy before ICU 53. - * (see - * ) - */ -#if U_ICU_VERSION_MAJOR_NUM >= 53 -#define HAVE_UCOL_STRCOLLUTF8 1 -#else -#undef HAVE_UCOL_STRCOLLUTF8 -#endif -#endif - /* use for libc locale names */ #define LOCALE_NAME_BUFLEN 128 @@ -54,9 +38,6 @@ extern PGDLLIMPORT bool database_ctype_is_c; extern bool check_locale(int category, const char *locale, char **canonname); extern char *pg_perm_setlocale(int category, const char *locale); -extern bool lc_collate_is_c(Oid collation); -extern bool lc_ctype_is_c(Oid collation); - /* * Return the POSIX lconv struct (contains number/money formatting * information) with locale information for all categories. @@ -66,19 +47,68 @@ extern struct lconv *PGLC_localeconv(void); extern void cache_locale_time(void); +struct pg_locale_struct; +typedef struct pg_locale_struct *pg_locale_t; + +/* methods that define collation behavior */ +struct collate_methods +{ + /* required */ + int (*strncoll) (const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, + pg_locale_t locale); + + /* required */ + size_t (*strnxfrm) (char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); + + /* optional */ + size_t (*strnxfrm_prefix) (char *dest, size_t destsize, + const char *src, ssize_t srclen, + pg_locale_t locale); + + /* + * If the strnxfrm method is not trusted to return the correct results, + * set strxfrm_is_safe to false. It set to false, the method will not be + * used in most cases, but the planner still expects it to be there for + * estimation purposes (where incorrect results are acceptable). + */ + bool strxfrm_is_safe; +}; + /* * We use a discriminated union to hold either a locale_t or an ICU collator. * pg_locale_t is occasionally checked for truth, so make it a pointer. + * + * Also, hold two flags: whether the collation's LC_COLLATE or LC_CTYPE is C + * (or POSIX), so we can optimize a few code paths in various places. For the + * built-in C and POSIX collations, we can know that without even doing a + * cache lookup, but we want to support aliases for C/POSIX too. For the + * "default" collation, there are separate static cache variables, since + * consulting the pg_collation catalog doesn't tell us what we need. + * + * Note that some code relies on the flags not reporting false negatives + * (that is, saying it's not C when it is). For example, char2wchar() + * could fail if the locale is C, so str_tolower() shouldn't call it + * in that case. */ struct pg_locale_struct { char provider; bool deterministic; + bool collate_is_c; + bool ctype_is_c; + bool is_default; + + const struct collate_methods *collate; /* NULL if collate_is_c */ + union { struct { const char *locale; + bool casemap_full; } builtin; locale_t lt; #ifdef USE_ICU @@ -91,41 +121,41 @@ struct pg_locale_struct } info; }; -typedef struct pg_locale_struct *pg_locale_t; - -extern PGDLLIMPORT struct pg_locale_struct default_locale; - -extern void make_icu_collator(const char *iculocstr, - const char *icurules, - struct pg_locale_struct *resultp); - -extern bool pg_locale_deterministic(pg_locale_t locale); +extern void init_database_collation(void); extern pg_locale_t pg_newlocale_from_collation(Oid collid); extern char *get_collation_actual_version(char collprovider, const char *collcollate); +extern size_t pg_strlower(char *dst, size_t dstsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +extern size_t pg_strtitle(char *dst, size_t dstsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +extern size_t pg_strupper(char *dst, size_t dstsize, + const char *src, ssize_t srclen, + pg_locale_t locale); +extern size_t pg_strfold(char *dst, size_t dstsize, + const char *src, ssize_t srclen, + pg_locale_t locale); extern int pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale); -extern int pg_strncoll(const char *arg1, size_t len1, - const char *arg2, size_t len2, pg_locale_t locale); +extern int pg_strncoll(const char *arg1, ssize_t len1, + const char *arg2, ssize_t len2, pg_locale_t locale); extern bool pg_strxfrm_enabled(pg_locale_t locale); extern size_t pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale); extern size_t pg_strnxfrm(char *dest, size_t destsize, const char *src, - size_t srclen, pg_locale_t locale); + ssize_t srclen, pg_locale_t locale); extern bool pg_strxfrm_prefix_enabled(pg_locale_t locale); extern size_t pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, pg_locale_t locale); extern size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, - size_t srclen, pg_locale_t locale); + ssize_t srclen, pg_locale_t locale); extern int builtin_locale_encoding(const char *locale); extern const char *builtin_validate_locale(int encoding, const char *locale); extern void icu_validate_locale(const char *loc_str); extern char *icu_language_tag(const char *loc_str, int elevel); - -#ifdef USE_ICU -extern int32_t icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes); -extern int32_t icu_from_uchar(char **result, const UChar *buff_uchar, int32_t len_uchar); -#endif +extern void report_newlocale_failure(const char *localename); /* These functions convert from/to libc's wchar_t, *not* pg_wchar_t */ extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen, diff --git a/src/include/utils/pg_lsn.h b/src/include/utils/pg_lsn.h index e885ecdb1e132..ae198af745029 100644 --- a/src/include/utils/pg_lsn.h +++ b/src/include/utils/pg_lsn.h @@ -5,7 +5,7 @@ * PostgreSQL. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/pg_lsn.h diff --git a/src/include/utils/pg_rusage.h b/src/include/utils/pg_rusage.h index a299c19fb8b89..31fb532f5aea3 100644 --- a/src/include/utils/pg_rusage.h +++ b/src/include/utils/pg_rusage.h @@ -4,7 +4,7 @@ * header file for resource usage measurement support routines * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/pg_rusage.h diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index 778f625ca1de4..d5557e6e998cd 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -5,7 +5,7 @@ * only be needed by files implementing statistics support (rather than ones * reporting / querying stats). * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/utils/pgstat_internal.h * ---------- @@ -53,7 +53,8 @@ typedef struct PgStat_HashKey { PgStat_Kind kind; /* statistics entry kind */ Oid dboid; /* database ID. InvalidOid for shared objects. */ - Oid objoid; /* object ID, either table or function. */ + uint64 objid; /* object ID (table, function, etc.), or + * identifier. */ } PgStat_HashKey; /* @@ -93,6 +94,19 @@ typedef struct PgStatShared_HashEntry */ pg_atomic_uint32 refcount; + /* + * Counter tracking the number of times the entry has been reused. + * + * Set to 0 when the entry is created, and incremented by one each time + * the shared entry is reinitialized with pgstat_reinit_entry(). + * + * May only be incremented / decremented while holding at least a shared + * lock on the dshash partition containing the entry. Like refcount, it + * needs to be an atomic variable because multiple backends can increment + * the generation with just a shared lock. + */ + pg_atomic_uint32 generation; + /* * Pointer to shared stats. The stats entry always starts with * PgStatShared_Common, embedded in a larger struct containing the @@ -132,12 +146,18 @@ typedef struct PgStat_EntryRef */ PgStatShared_Common *shared_stats; + /* + * Copy of PgStatShared_HashEntry->generation, keeping locally track of + * the shared stats entry "generation" retrieved (number of times reused). + */ + uint32 generation; + /* * Pending statistics data that will need to be flushed to shared memory * stats eventually. Each stats kind utilizing pending data defines what * format its pending data has and needs to provide a - * PgStat_KindInfo->flush_pending_cb callback to merge pending into shared - * stats. + * PgStat_KindInfo->flush_pending_cb callback to merge pending entries + * into the shared stats hash table. */ void *pending; dlist_node pending_node; /* membership in pgStatPending list */ @@ -193,9 +213,13 @@ typedef struct PgStat_KindInfo */ bool accessed_across_databases:1; + /* Should stats be written to the on-disk stats file? */ + bool write_to_file:1; + /* * The size of an entry in the shared stats hash table (pointed to by - * PgStatShared_HashEntry->body). + * PgStatShared_HashEntry->body). For fixed-numbered statistics, this is + * the size of an entry in PgStat_ShmemControl->custom_data. */ uint32 shared_size; @@ -228,9 +252,16 @@ typedef struct PgStat_KindInfo */ uint32 pending_size; + /* + * Perform custom actions when initializing a backend (standalone or under + * postmaster). Optional. + */ + void (*init_backend_cb) (void); + /* * For variable-numbered stats: flush pending stats. Required if pending - * data is used. + * data is used. See flush_static_cb when dealing with stats data that + * that cannot use PgStat_EntryRef->pending. */ bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait); @@ -258,6 +289,25 @@ typedef struct PgStat_KindInfo */ void (*init_shmem_cb) (void *stats); + /* + * For fixed-numbered or variable-numbered statistics: Flush pending stats + * entries, for stats kinds that do not use PgStat_EntryRef->pending. + * + * Returns true if some of the stats could not be flushed, due to lock + * contention for example. Optional. + */ + bool (*flush_static_cb) (bool nowait); + + /* + * For fixed-numbered or variable-numbered statistics: Check for pending + * stats in need of flush with flush_static_cb, when these do not use + * PgStat_EntryRef->pending. + * + * Returns true if there are any stats pending for flush, triggering + * flush_static_cb. Optional. + */ + bool (*have_static_pending_cb) (void); + /* * For fixed-numbered statistics: Reset All. */ @@ -407,6 +457,11 @@ typedef struct PgStatShared_ReplSlot PgStat_StatReplSlotEntry stats; } PgStatShared_ReplSlot; +typedef struct PgStatShared_Backend +{ + PgStatShared_Common header; + PgStat_Backend stats; +} PgStatShared_Backend; /* * Central shared memory entry for the cumulative stats system. @@ -446,6 +501,13 @@ typedef struct PgStat_ShmemControl PgStatShared_IO io; PgStatShared_SLRU slru; PgStatShared_Wal wal; + + /* + * Custom stats data with fixed-numbered objects, indexed by (PgStat_Kind + * - PGSTAT_KIND_CUSTOM_MIN). + */ + void *custom_data[PGSTAT_KIND_CUSTOM_SIZE]; + } PgStat_ShmemControl; @@ -459,7 +521,7 @@ typedef struct PgStat_Snapshot /* time at which snapshot was taken */ TimestampTz snapshot_timestamp; - bool fixed_valid[PGSTAT_NUM_KINDS]; + bool fixed_valid[PGSTAT_KIND_BUILTIN_SIZE]; PgStat_ArchiverStats archiver; @@ -473,6 +535,14 @@ typedef struct PgStat_Snapshot PgStat_WalStats wal; + /* + * Data in snapshot for custom fixed-numbered statistics, indexed by + * (PgStat_Kind - PGSTAT_KIND_CUSTOM_MIN). Each entry is allocated in + * TopMemoryContext, for a size of PgStat_KindInfo->shared_data_len. + */ + bool custom_valid[PGSTAT_KIND_CUSTOM_SIZE]; + void *custom_data[PGSTAT_KIND_CUSTOM_SIZE]; + /* to free snapshot in bulk */ MemoryContext context; struct pgstat_snapshot_hash *stats; @@ -509,6 +579,8 @@ static inline int pgstat_cmp_hash_key(const void *a, const void *b, size_t size, static inline uint32 pgstat_hash_hash_key(const void *d, size_t size, void *arg); static inline size_t pgstat_get_entry_len(PgStat_Kind kind); static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry); +static inline void *pgstat_get_custom_shmem_data(PgStat_Kind kind); +static inline void *pgstat_get_custom_snapshot_data(PgStat_Kind kind); /* @@ -516,6 +588,8 @@ static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common */ extern const PgStat_KindInfo *pgstat_get_kind_info(PgStat_Kind kind); +extern void pgstat_register_kind(PgStat_Kind kind, + const PgStat_KindInfo *kind_info); #ifdef USE_ASSERT_CHECKING extern void pgstat_assert_is_up(void); @@ -524,10 +598,13 @@ extern void pgstat_assert_is_up(void); #endif extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref); -extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry); -extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid); +extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, + uint64 objid, + bool *created_entry); +extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, + Oid dboid, uint64 objid); -extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid); +extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid); extern void pgstat_snapshot_fixed(PgStat_Kind kind); @@ -539,6 +616,20 @@ extern void pgstat_archiver_init_shmem_cb(void *stats); extern void pgstat_archiver_reset_all_cb(TimestampTz ts); extern void pgstat_archiver_snapshot_cb(void); +/* + * Functions in pgstat_backend.c + */ + +/* flags for pgstat_flush_backend() */ +#define PGSTAT_BACKEND_FLUSH_IO (1 << 0) /* Flush I/O statistics */ +#define PGSTAT_BACKEND_FLUSH_WAL (1 << 1) /* Flush WAL statistics */ +#define PGSTAT_BACKEND_FLUSH_ALL (PGSTAT_BACKEND_FLUSH_IO | PGSTAT_BACKEND_FLUSH_WAL) + +extern bool pgstat_flush_backend(bool nowait, bits32 flags); +extern bool pgstat_backend_flush_cb(bool nowait); +extern bool pgstat_backend_have_pending_cb(void); +extern void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, + TimestampTz ts); /* * Functions in pgstat_bgwriter.c @@ -583,7 +674,10 @@ extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait); * Functions in pgstat_io.c */ -extern bool pgstat_flush_io(bool nowait); +extern void pgstat_flush_io(bool nowait); + +extern bool pgstat_io_have_pending_cb(void); +extern bool pgstat_io_flush_cb(bool nowait); extern void pgstat_io_init_shmem_cb(void *stats); extern void pgstat_io_reset_all_cb(TimestampTz ts); extern void pgstat_io_snapshot_cb(void); @@ -618,16 +712,18 @@ extern bool pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat extern void pgstat_attach_shmem(void); extern void pgstat_detach_shmem(void); -extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, +extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry); extern bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait); extern bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait); extern void pgstat_unlock_entry(PgStat_EntryRef *entry_ref); -extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid); +extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid); extern void pgstat_drop_all_entries(void); -extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid, +extern void pgstat_drop_matching_entries(bool (*do_drop) (PgStatShared_HashEntry *, Datum), + Datum match_data); +extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait); -extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts); +extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, uint64 objid, TimestampTz ts); extern void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts); extern void pgstat_reset_matching_entries(bool (*do_reset) (PgStatShared_HashEntry *, Datum), Datum match_data, @@ -642,7 +738,8 @@ extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind, * Functions in pgstat_slru.c */ -extern bool pgstat_slru_flush(bool nowait); +extern bool pgstat_slru_have_pending_cb(void); +extern bool pgstat_slru_flush_cb(bool nowait); extern void pgstat_slru_init_shmem_cb(void *stats); extern void pgstat_slru_reset_all_cb(TimestampTz ts); extern void pgstat_slru_snapshot_cb(void); @@ -652,10 +749,9 @@ extern void pgstat_slru_snapshot_cb(void); * Functions in pgstat_wal.c */ -extern bool pgstat_flush_wal(bool nowait); -extern void pgstat_init_wal(void); -extern bool pgstat_have_pending_wal(void); - +extern void pgstat_wal_init_backend_cb(void); +extern bool pgstat_wal_have_pending_cb(void); +extern bool pgstat_wal_flush_cb(bool nowait); extern void pgstat_wal_init_shmem_cb(void *stats); extern void pgstat_wal_reset_all_cb(TimestampTz ts); extern void pgstat_wal_snapshot_cb(void); @@ -674,8 +770,8 @@ extern void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header, */ extern PgStat_SubXactStatus *pgstat_get_xact_stack_level(int nest_level); -extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid); -extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid); +extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, uint64 objid); +extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, uint64 objid); /* @@ -685,20 +781,6 @@ extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid) extern PGDLLIMPORT PgStat_LocalState pgStatLocal; -/* - * Variables in pgstat_io.c - */ - -extern PGDLLIMPORT bool have_iostats; - - -/* - * Variables in pgstat_slru.c - */ - -extern PGDLLIMPORT bool have_slrustats; - - /* * Implementation of inline functions declared above. */ @@ -824,4 +906,34 @@ pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry) return ((char *) (entry)) + off; } +/* + * Returns a pointer to the shared memory area of custom stats for + * fixed-numbered statistics. + */ +static inline void * +pgstat_get_custom_shmem_data(PgStat_Kind kind) +{ + int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + Assert(pgstat_is_kind_custom(kind)); + Assert(pgstat_get_kind_info(kind)->fixed_amount); + + return pgStatLocal.shmem->custom_data[idx]; +} + +/* + * Returns a pointer to the portion of custom data for fixed-numbered + * statistics in the current snapshot. + */ +static inline void * +pgstat_get_custom_snapshot_data(PgStat_Kind kind) +{ + int idx = kind - PGSTAT_KIND_CUSTOM_MIN; + + Assert(pgstat_is_kind_custom(kind)); + Assert(pgstat_get_kind_info(kind)->fixed_amount); + + return pgStatLocal.snapshot.custom_data[idx]; +} + #endif /* PGSTAT_INTERNAL_H */ diff --git a/src/include/utils/pgstat_kind.h b/src/include/utils/pgstat_kind.h new file mode 100644 index 0000000000000..f44169fd5a3c7 --- /dev/null +++ b/src/include/utils/pgstat_kind.h @@ -0,0 +1,72 @@ +/* ---------- + * pgstat_kind.h + * + * Definitions related to the statistics kinds for the PostgreSQL + * cumulative statistics system. Can be included in backend or + * frontend code. + * + * Copyright (c) 2001-2025, PostgreSQL Global Development Group + * + * src/include/utils/pgstat_kind.h + * ---------- + */ +#ifndef PGSTAT_KIND_H +#define PGSTAT_KIND_H + +/* The types of statistics entries */ +#define PgStat_Kind uint32 + +/* Range of IDs allowed, for built-in and custom kinds */ +#define PGSTAT_KIND_MIN 1 /* Minimum ID allowed */ +#define PGSTAT_KIND_MAX 256 /* Maximum ID allowed */ + +/* use 0 for INVALID, to catch zero-initialized data */ +#define PGSTAT_KIND_INVALID 0 + +/* stats for variable-numbered objects */ +#define PGSTAT_KIND_DATABASE 1 /* database-wide statistics */ +#define PGSTAT_KIND_RELATION 2 /* per-table statistics */ +#define PGSTAT_KIND_FUNCTION 3 /* per-function statistics */ +#define PGSTAT_KIND_REPLSLOT 4 /* per-slot statistics */ +#define PGSTAT_KIND_SUBSCRIPTION 5 /* per-subscription statistics */ +#define PGSTAT_KIND_BACKEND 6 /* per-backend statistics */ + +/* stats for fixed-numbered objects */ +#define PGSTAT_KIND_ARCHIVER 7 +#define PGSTAT_KIND_BGWRITER 8 +#define PGSTAT_KIND_CHECKPOINTER 9 +#define PGSTAT_KIND_IO 10 +#define PGSTAT_KIND_SLRU 11 +#define PGSTAT_KIND_WAL 12 + +#define PGSTAT_KIND_BUILTIN_MIN PGSTAT_KIND_DATABASE +#define PGSTAT_KIND_BUILTIN_MAX PGSTAT_KIND_WAL +#define PGSTAT_KIND_BUILTIN_SIZE (PGSTAT_KIND_BUILTIN_MAX + 1) + +/* Custom stats kinds */ + +/* Range of IDs allowed for custom stats kinds */ +#define PGSTAT_KIND_CUSTOM_MIN 128 +#define PGSTAT_KIND_CUSTOM_MAX PGSTAT_KIND_MAX +#define PGSTAT_KIND_CUSTOM_SIZE (PGSTAT_KIND_CUSTOM_MAX - PGSTAT_KIND_CUSTOM_MIN + 1) + +/* + * PgStat_Kind to use for extensions that require an ID, but are still in + * development and have not reserved their own unique kind ID yet. See: + * https://wiki.postgresql.org/wiki/CustomCumulativeStats + */ +#define PGSTAT_KIND_EXPERIMENTAL 128 + +static inline bool +pgstat_is_kind_builtin(PgStat_Kind kind) +{ + return kind >= PGSTAT_KIND_BUILTIN_MIN && kind <= PGSTAT_KIND_BUILTIN_MAX; +} + +static inline bool +pgstat_is_kind_custom(PgStat_Kind kind) +{ + return kind >= PGSTAT_KIND_CUSTOM_MIN && kind <= PGSTAT_KIND_CUSTOM_MAX; +} + +#endif /* PGSTAT_KIND_H */ diff --git a/src/include/utils/pidfile.h b/src/include/utils/pidfile.h index f0d00d398fd47..c8f248fd92493 100644 --- a/src/include/utils/pidfile.h +++ b/src/include/utils/pidfile.h @@ -3,7 +3,7 @@ * pidfile.h * Declarations describing the data directory lock file (postmaster.pid) * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/pidfile.h diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h index a90dfdf9067a4..1baa6d50bfd7a 100644 --- a/src/include/utils/plancache.h +++ b/src/include/utils/plancache.h @@ -5,7 +5,7 @@ * * See plancache.c for comments. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/plancache.h @@ -23,7 +23,8 @@ #include "utils/resowner.h" -/* Forward declaration, to avoid including parsenodes.h here */ +/* Forward declarations, to avoid including parsenodes.h here */ +struct Query; struct RawStmt; /* possible values for plan_cache_mode */ @@ -37,18 +38,31 @@ typedef enum /* GUC parameter */ extern PGDLLIMPORT int plan_cache_mode; +/* Optional callback to editorialize on rewritten parse trees */ +typedef void (*PostRewriteHook) (List *querytree_list, void *arg); + #define CACHEDPLANSOURCE_MAGIC 195726186 #define CACHEDPLAN_MAGIC 953717834 #define CACHEDEXPR_MAGIC 838275847 /* * CachedPlanSource (which might better have been called CachedQuery) - * represents a SQL query that we expect to use multiple times. It stores - * the query source text, the raw parse tree, and the analyzed-and-rewritten + * represents a SQL query that we expect to use multiple times. It stores the + * query source text, the source parse tree, and the analyzed-and-rewritten * query tree, as well as adjunct data. Cache invalidation can happen as a * result of DDL affecting objects used by the query. In that case we discard * the analyzed-and-rewritten query tree, and rebuild it when next needed. * + * There are two ways in which the source query can be represented: either + * as a raw parse tree, or as an analyzed-but-not-rewritten parse tree. + * In the latter case we expect that cache invalidation need not affect + * the parse-analysis results, only the rewriting and planning steps. + * Only one of raw_parse_tree and analyzed_parse_tree can be non-NULL. + * (If both are NULL, the CachedPlanSource represents an empty query.) + * Note that query_string is typically just an empty string when the + * source query is an analyzed parse tree; also, param_types, num_params, + * parserSetup, and parserSetupArg will not be used. + * * An actual execution plan, represented by CachedPlan, is derived from the * CachedPlanSource when we need to execute the query. The plan could be * either generic (usable with any set of plan parameters) or custom (for a @@ -76,7 +90,7 @@ extern PGDLLIMPORT int plan_cache_mode; * though it may be useful if the CachedPlan can be discarded early.) * * A CachedPlanSource has two associated memory contexts: one that holds the - * struct itself, the query source text and the raw parse tree, and another + * struct itself, the query source text and the source parse tree, and another * context that holds the rewritten query tree and associated data. This * allows the query tree to be discarded easily when it is invalidated. * @@ -87,22 +101,20 @@ extern PGDLLIMPORT int plan_cache_mode; * all subsidiary data live in the caller's CurrentMemoryContext, and there * is no way to free memory short of clearing that entire context. A oneshot * plan is always treated as unsaved. - * - * Note: the string referenced by commandTag is not subsidiary storage; - * it is assumed to be a compile-time-constant string. As with portals, - * commandTag shall be NULL if and only if the original query string (before - * rewriting) was an empty string. */ typedef struct CachedPlanSource { int magic; /* should equal CACHEDPLANSOURCE_MAGIC */ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */ + struct Query *analyzed_parse_tree; /* analyzed parse tree, or NULL */ const char *query_string; /* source text of query */ - CommandTag commandTag; /* 'nuff said */ + CommandTag commandTag; /* command tag for query */ Oid *param_types; /* array of parameter type OIDs, or NULL */ int num_params; /* length of param_types array */ ParserSetupHook parserSetup; /* alternative parameter spec method */ void *parserSetupArg; + PostRewriteHook postRewrite; /* see SetPostRewriteHook */ + void *postRewriteArg; int cursor_options; /* cursor options used for planning */ bool fixed_result; /* disallow change in result tupdesc? */ TupleDesc resultDesc; /* result type; NULL = doesn't return tuples */ @@ -193,6 +205,9 @@ extern void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner); extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag); +extern CachedPlanSource *CreateCachedPlanForQuery(struct Query *analyzed_parse_tree, + const char *query_string, + CommandTag commandTag); extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag); @@ -205,6 +220,9 @@ extern void CompleteCachedPlan(CachedPlanSource *plansource, void *parserSetupArg, int cursor_options, bool fixed_result); +extern void SetPostRewriteHook(CachedPlanSource *plansource, + PostRewriteHook postRewrite, + void *postRewriteArg); extern void SaveCachedPlan(CachedPlanSource *plansource); extern void DropCachedPlan(CachedPlanSource *plansource); diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index 11419faecaa8a..0b62143af8bcf 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -36,7 +36,7 @@ * to look like NO SCROLL cursors. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/portal.h @@ -145,7 +145,6 @@ typedef struct PortalData /* Features/options */ PortalStrategy strategy; /* see above */ int cursorOptions; /* DECLARE CURSOR option bits */ - bool run_once; /* portal will only be run once */ /* Status data */ PortalStatus status; /* see above */ @@ -170,9 +169,9 @@ typedef struct PortalData Snapshot portalSnapshot; /* active snapshot, or NULL if none */ /* - * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or - * PORTAL_UTIL_SELECT query. (A cursor held past the end of its - * transaction no longer has any active executor state.) + * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING, + * PORTAL_ONE_MOD_WITH, or PORTAL_UTIL_SELECT query. (A cursor held past + * the end of its transaction no longer has any active executor state.) */ Tuplestorestate *holdStore; /* store for holdable cursors */ MemoryContext holdContext; /* memory containing holdStore */ diff --git a/src/include/utils/queryenvironment.h b/src/include/utils/queryenvironment.h index 10a9b6d553017..d44b20a778cea 100644 --- a/src/include/utils/queryenvironment.h +++ b/src/include/utils/queryenvironment.h @@ -4,7 +4,7 @@ * Access to functions to mutate the query environment and retrieve the * actual data related to entries (if any). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/queryenvironment.h diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h index 2b574873cefde..50adb3c8c1391 100644 --- a/src/include/utils/rangetypes.h +++ b/src/include/utils/rangetypes.h @@ -4,7 +4,7 @@ * Declarations for Postgres range types. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/rangetypes.h diff --git a/src/include/utils/regproc.h b/src/include/utils/regproc.h index 53e0298fb307a..81bf59fba54b7 100644 --- a/src/include/utils/regproc.h +++ b/src/include/utils/regproc.h @@ -3,7 +3,7 @@ * regproc.h * Functions for the built-in types regproc, regclass, regtype, etc. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/regproc.h diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 87002049538a8..b552359915f19 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -4,7 +4,7 @@ * POSTGRES relation descriptor (a/k/a relcache entry) definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/rel.h @@ -284,6 +284,9 @@ typedef struct ForeignKeyCacheInfo /* number of columns in the foreign key */ int nkeys; + /* Is enforced ? */ + bool conenforced; + /* * these arrays each have nkeys valid entries: */ @@ -309,6 +312,7 @@ typedef struct AutoVacOpts { bool enabled; int vacuum_threshold; + int vacuum_max_threshold; int vacuum_ins_threshold; int analyze_threshold; int vacuum_cost_limit; @@ -343,6 +347,13 @@ typedef struct StdRdOptions int parallel_workers; /* max number of parallel workers */ StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */ bool vacuum_truncate; /* enables vacuum to truncate a relation */ + bool vacuum_truncate_set; /* whether vacuum_truncate is set */ + + /* + * Fraction of pages in a relation that vacuum can eagerly scan and fail + * to freeze. 0 if disabled, -1 if unspecified. + */ + double vacuum_max_eager_freeze_failure_rate; } StdRdOptions; #define HEAP_MIN_FILLFACTOR 10 diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 18c32ea7008d4..3561c6bef0bfc 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -4,7 +4,7 @@ * Relation descriptor cache definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/relcache.h @@ -37,6 +37,14 @@ typedef Relation *RelationPtr; /* * Routines to open (lookup) and close a relcache entry */ +#ifdef USE_ASSERT_CHECKING +extern void AssertCouldGetRelation(void); +#else +static inline void +AssertCouldGetRelation(void) +{ +} +#endif extern Relation RelationIdGetRelation(Oid relationId); extern void RelationClose(Relation relation); @@ -46,7 +54,7 @@ extern void RelationClose(Relation relation); extern List *RelationGetFKeyList(Relation relation); extern List *RelationGetIndexList(Relation relation); extern List *RelationGetStatExtList(Relation relation); -extern Oid RelationGetPrimaryKeyIndex(Relation relation); +extern Oid RelationGetPrimaryKeyIndex(Relation relation, bool deferrable_ok); extern Oid RelationGetReplicaIndex(Relation relation); extern List *RelationGetIndexExpressions(Relation relation); extern List *RelationGetDummyIndexExpressions(Relation relation); diff --git a/src/include/utils/relfilenumbermap.h b/src/include/utils/relfilenumbermap.h index 0ca89e452adb9..86fadefe499a7 100644 --- a/src/include/utils/relfilenumbermap.h +++ b/src/include/utils/relfilenumbermap.h @@ -3,7 +3,7 @@ * relfilenumbermap.h * relfilenumber to oid mapping cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/relfilenumbermap.h diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h index 4c1a74743d87e..ae1a7567d948f 100644 --- a/src/include/utils/relmapper.h +++ b/src/include/utils/relmapper.h @@ -4,7 +4,7 @@ * Catalog-to-filenumber mapping * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/relmapper.h diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h index 622039e87e885..ea340fee6576a 100644 --- a/src/include/utils/relptr.h +++ b/src/include/utils/relptr.h @@ -3,7 +3,7 @@ * relptr.h * This file contains basic declarations for relative pointers. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/relptr.h diff --git a/src/include/utils/reltrigger.h b/src/include/utils/reltrigger.h index dfef4c055a48e..5fda290eb40ef 100644 --- a/src/include/utils/reltrigger.h +++ b/src/include/utils/reltrigger.h @@ -4,7 +4,7 @@ * POSTGRES relation trigger definitions. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/reltrigger.h diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h index 4e534bc3e709c..aede4bfc820a3 100644 --- a/src/include/utils/resowner.h +++ b/src/include/utils/resowner.h @@ -9,7 +9,7 @@ * See utils/resowner/README for more info. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/resowner.h @@ -164,4 +164,9 @@ struct LOCALLOCK; extern void ResourceOwnerRememberLock(ResourceOwner owner, struct LOCALLOCK *locallock); extern void ResourceOwnerForgetLock(ResourceOwner owner, struct LOCALLOCK *locallock); +/* special support for AIO */ +struct dlist_node; +extern void ResourceOwnerRememberAioHandle(ResourceOwner owner, struct dlist_node *ioh_node); +extern void ResourceOwnerForgetAioHandle(ResourceOwner owner, struct dlist_node *ioh_node); + #endif /* RESOWNER_H */ diff --git a/src/include/utils/rls.h b/src/include/utils/rls.h index fafc4ee89caab..d18ac368b4d8f 100644 --- a/src/include/utils/rls.h +++ b/src/include/utils/rls.h @@ -4,7 +4,7 @@ * Header file for Row Level Security (RLS) utility commands to be used * with the rowsecurity feature. * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/include/utils/rls.h * diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h index 6d860806221ed..5f2ea2e4d0ebf 100644 --- a/src/include/utils/ruleutils.h +++ b/src/include/utils/ruleutils.h @@ -3,7 +3,7 @@ * ruleutils.h * Declarations for ruleutils.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/ruleutils.h @@ -43,12 +43,15 @@ extern List *set_deparse_context_plan(List *dpcontext, struct Plan *plan, List *ancestors); extern List *select_rtable_names_for_explain(List *rtable, Bitmapset *rels_used); +extern char *get_window_frame_options_for_explain(int frameOptions, + Node *startOffset, + Node *endOffset, + List *dpcontext, + bool forceprefix); extern char *generate_collation_name(Oid collid); extern char *generate_opclass_name(Oid opclass); extern char *get_range_partbound_string(List *bound_datums); extern char *pg_get_statisticsobjdef_string(Oid statextid); -extern char *get_list_partvalue_string(Const *val); - #endif /* RULEUTILS_H */ diff --git a/src/include/utils/sampling.h b/src/include/utils/sampling.h index be48ee52bac4b..02c550aabd568 100644 --- a/src/include/utils/sampling.h +++ b/src/include/utils/sampling.h @@ -3,7 +3,7 @@ * sampling.h * definitions for sampling functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/sampling.h diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h index f2563ad1cb3a8..013049b3098ac 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -5,7 +5,7 @@ * infrastructure for selectivity and cost estimation. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/selfuncs.h @@ -94,7 +94,8 @@ typedef struct VariableStatData Oid vartype; /* exposed type of expression */ Oid atttype; /* actual type (after stripping relabel) */ int32 atttypmod; /* actual typmod (after stripping relabel) */ - bool isunique; /* matches unique index or DISTINCT clause */ + bool isunique; /* matches unique index, DISTINCT or GROUP-BY + * clause */ bool acl_ok; /* result of ACL check on table or column */ } VariableStatData; @@ -209,7 +210,7 @@ extern Selectivity rowcomparesel(PlannerInfo *root, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo); extern void mergejoinscansel(PlannerInfo *root, Node *clause, - Oid opfamily, int strategy, bool nulls_first, + Oid opfamily, CompareType cmptype, bool nulls_first, Selectivity *leftstart, Selectivity *leftend, Selectivity *rightstart, Selectivity *rightend); @@ -217,6 +218,10 @@ extern double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo); +extern List *estimate_multivariate_bucketsize(PlannerInfo *root, + RelOptInfo *inner, + List *hashclauses, + Selectivity *innerbucketsize); extern void estimate_hash_bucket_stats(PlannerInfo *root, Node *hashkey, double nbuckets, Selectivity *mcv_freq, diff --git a/src/include/utils/sharedtuplestore.h b/src/include/utils/sharedtuplestore.h index dcf676ff5fbb9..9cc6514214773 100644 --- a/src/include/utils/sharedtuplestore.h +++ b/src/include/utils/sharedtuplestore.h @@ -3,7 +3,7 @@ * sharedtuplestore.h * Simple mechanism for sharing tuples between backends. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/sharedtuplestore.h diff --git a/src/include/utils/skipsupport.h b/src/include/utils/skipsupport.h new file mode 100644 index 0000000000000..c42be001fb546 --- /dev/null +++ b/src/include/utils/skipsupport.h @@ -0,0 +1,98 @@ +/*------------------------------------------------------------------------- + * + * skipsupport.h + * Support routines for B-Tree skip scan. + * + * B-Tree operator classes for discrete types can optionally provide a support + * function for skipping. This is used during skip scans. + * + * A B-tree operator class that implements skip support provides B-tree index + * scans with a way of enumerating and iterating through every possible value + * from the domain of indexable values. This gives scans a way to determine + * the next value in line for a given skip array/scan key/skipped attribute. + * Scans request the next (or previous) value whenever they run out of tuples + * matching the skip array's current element value. The next (or previous) + * value can be used to relocate the scan; it is applied in combination with + * at least one additional lower-order non-skip key, taken from the query. + * + * Skip support is used by discrete type (e.g., integer and date) opclasses. + * Indexes with an attribute whose input opclass is of one of these types tend + * to store adjacent values in adjoining groups of index tuples. Each time a + * skip scan with skip support successfully guesses that the next value in the + * index (for a given skipped column) is indeed the value that skip support + * just incremented its skip array to, it will have saved the scan some work. + * The scan will have avoided an index probe that directly finds the next + * value that appears in the index. (When skip support guesses wrong, then it + * won't have saved any work, but it also won't have added any useless work. + * The failed attempt to locate exactly-matching index tuples acts just like + * an explicit probe would; it'll still find the index's true next value.) + * + * It usually isn't feasible to implement skip support for an opclass whose + * input type is continuous. The B-Tree code falls back on next-key sentinel + * values for any opclass that doesn't provide its own skip support function. + * This isn't really an implementation restriction; there is no benefit to + * providing skip support for an opclass where guessing that the next indexed + * value is the next possible indexable value never (or hardly ever) works out. + * + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/utils/skipsupport.h + * + *------------------------------------------------------------------------- + */ +#ifndef SKIPSUPPORT_H +#define SKIPSUPPORT_H + +#include "utils/relcache.h" + +typedef struct SkipSupportData *SkipSupport; +typedef Datum (*SkipSupportIncDec) (Relation rel, + Datum existing, + bool *overflow); + +/* + * State/callbacks used by skip arrays to procedurally generate elements. + * + * A BTSKIPSUPPORT_PROC function must set each and every field when called + * (there are no optional fields). + */ +typedef struct SkipSupportData +{ + /* + * low_elem and high_elem must be set with the lowest and highest possible + * values from the domain of indexable values (assuming ascending order) + */ + Datum low_elem; /* lowest sorting/leftmost non-NULL value */ + Datum high_elem; /* highest sorting/rightmost non-NULL value */ + + /* + * Decrement/increment functions. + * + * Returns a decremented/incremented copy of caller's existing datum, + * allocated in caller's memory context (for pass-by-reference types). + * It's not okay for these functions to leak any memory. + * + * When the decrement function (or increment function) is called with a + * value that already matches low_elem (or high_elem), function must set + * the *overflow argument. The return value is treated as undefined by + * the B-Tree code; it shouldn't need to be (and won't be) pfree'd. + * + * The B-Tree code's "existing" datum argument is often just a straight + * copy of a value from an index tuple. Operator classes must accept + * every possible representational variation within the underlying type. + * On the other hand, opclasses are _not_ required to preserve information + * that doesn't affect how datums are sorted (e.g., skip support for a + * fixed precision numeric type needn't preserve datum display scale). + * Operator class decrement/increment functions will never be called with + * a NULL "existing" argument, either. + */ + SkipSupportIncDec decrement; + SkipSupportIncDec increment; +} SkipSupportData; + +extern SkipSupport PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype, + bool reverse); + +#endif /* SKIPSUPPORT_H */ diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h index 9398a84051c5e..d346be716423e 100644 --- a/src/include/utils/snapmgr.h +++ b/src/include/utils/snapmgr.h @@ -3,7 +3,7 @@ * snapmgr.h * POSTGRES snapshot manager * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/snapmgr.h @@ -27,11 +27,13 @@ extern PGDLLIMPORT TransactionId RecentXmin; /* Variables representing various special snapshot semantics */ extern PGDLLIMPORT SnapshotData SnapshotSelfData; extern PGDLLIMPORT SnapshotData SnapshotAnyData; -extern PGDLLIMPORT SnapshotData CatalogSnapshotData; +extern PGDLLIMPORT SnapshotData SnapshotToastData; #define SnapshotSelf (&SnapshotSelfData) #define SnapshotAny (&SnapshotAnyData) +/* Use get_toast_snapshot() for the TOAST snapshot */ + /* * We don't provide a static SnapshotDirty variable because it would be * non-reentrant. Instead, users of that snapshot type should declare a @@ -49,15 +51,6 @@ extern PGDLLIMPORT SnapshotData CatalogSnapshotData; ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \ (snapshotdata).vistest = (vistestp)) -/* - * Similarly, some initialization is required for SnapshotToast. We need - * to set lsn and whenTaken correctly to support snapshot_too_old. - */ -#define InitToastSnapshot(snapshotdata, l, w) \ - ((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \ - (snapshotdata).lsn = (l), \ - (snapshotdata).whenTaken = (w)) - /* This macro encodes the knowledge of which snapshots are MVCC-safe */ #define IsMVCCSnapshot(snapshot) \ ((snapshot)->snapshot_type == SNAPSHOT_MVCC || \ @@ -66,7 +59,6 @@ extern PGDLLIMPORT SnapshotData CatalogSnapshotData; extern Snapshot GetTransactionSnapshot(void); extern Snapshot GetLatestSnapshot(void); extern void SnapshotSetCommandId(CommandId curcid); -extern Snapshot GetOldestSnapshot(void); extern Snapshot GetCatalogSnapshot(Oid relid); extern Snapshot GetNonHistoricCatalogSnapshot(Oid relid); diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h index 8d1e31e888eea..0e546ec14974f 100644 --- a/src/include/utils/snapshot.h +++ b/src/include/utils/snapshot.h @@ -3,7 +3,7 @@ * snapshot.h * POSTGRES snapshot definition * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/snapshot.h @@ -13,11 +13,7 @@ #ifndef SNAPSHOT_H #define SNAPSHOT_H -#include "access/htup.h" -#include "access/xlogdefs.h" -#include "datatype/timestamp.h" #include "lib/pairingheap.h" -#include "storage/buf.h" /* @@ -205,9 +201,6 @@ typedef struct SnapshotData uint32 regd_count; /* refcount on RegisteredSnapshots */ pairingheap_node ph_node; /* link in the RegisteredSnapshots heap */ - TimestampTz whenTaken; /* timestamp when snapshot was taken */ - XLogRecPtr lsn; /* position in the WAL stream when taken */ - /* * The transaction completion count at the time GetSnapshotData() built * this snapshot. Allows to avoid re-computing static snapshots when no diff --git a/src/include/utils/sortsupport.h b/src/include/utils/sortsupport.h index 4bf99584f8881..b7abaf7802de0 100644 --- a/src/include/utils/sortsupport.h +++ b/src/include/utils/sortsupport.h @@ -42,7 +42,7 @@ * function for such cases, but probably not any other acceleration method. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/sortsupport.h @@ -384,7 +384,7 @@ extern int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup); /* Other functions in utils/sort/sortsupport.c */ extern void PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup); extern void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup); -extern void PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy, +extern void PrepareSortSupportFromIndexRel(Relation indexRel, bool reverse, SortSupport ssup); extern void PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup); diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h index 11cfa719955ed..d7edd79b18d10 100644 --- a/src/include/utils/spccache.h +++ b/src/include/utils/spccache.h @@ -3,7 +3,7 @@ * spccache.h * Tablespace cache. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/spccache.h diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 03a27dd0a83f4..3039713259ecd 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -6,7 +6,7 @@ * See also lsyscache.h, which provides convenience routines for * common cache-lookup operations. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/syscache.h @@ -20,7 +20,7 @@ #include "access/htup.h" /* we intentionally do not include utils/catcache.h here */ -#include "catalog/syscache_ids.h" +#include "catalog/syscache_ids.h" /* IWYU pragma: export */ extern void InitCatalogCache(void); extern void InitCatalogCachePhase2(void); @@ -43,9 +43,14 @@ extern HeapTuple SearchSysCache4(int cacheId, extern void ReleaseSysCache(HeapTuple tuple); +extern HeapTuple SearchSysCacheLocked1(int cacheId, + Datum key1); + /* convenience routines */ extern HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4); +extern HeapTuple SearchSysCacheLockedCopy1(int cacheId, + Datum key1); extern bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4); extern Oid GetSysCacheOid(int cacheId, AttrNumber oidcol, diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h index a5d8f078246fc..7b19beafdc950 100644 --- a/src/include/utils/timeout.h +++ b/src/include/utils/timeout.h @@ -4,7 +4,7 @@ * Routines to multiplex SIGALRM interrupts for multiple timeout reasons. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/timeout.h diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index a6ce03ed46045..8c205859c3be5 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -3,7 +3,7 @@ * timestamp.h * Definitions for the SQL "timestamp" and "interval" types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/timestamp.h @@ -85,6 +85,15 @@ IntervalPGetDatum(const Interval *X) #define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000)) #define TimestampTzPlusSeconds(tz,s) ((tz) + ((s) * (int64) 1000000)) +/* Helper for simple subtraction between two timestamps */ +static inline uint64 +TimestampDifferenceMicroseconds(TimestampTz start_time, + TimestampTz stop_time) +{ + if (start_time >= stop_time) + return 0; + return (uint64) stop_time - start_time; +} /* Set at postmaster start */ extern PGDLLIMPORT TimestampTz PgStartTime; @@ -107,6 +116,9 @@ extern long TimestampDifferenceMilliseconds(TimestampTz start_time, extern bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec); +extern bool TimestampDifferenceExceedsSeconds(TimestampTz start_time, + TimestampTz stop_time, + int threshold_sec); extern TimestampTz time_t_to_timestamptz(pg_time_t tm); extern pg_time_t timestamptz_to_time_t(TimestampTz t); diff --git a/src/include/utils/tuplesort.h b/src/include/utils/tuplesort.h index cde83f6201525..ef79f259f935f 100644 --- a/src/include/utils/tuplesort.h +++ b/src/include/utils/tuplesort.h @@ -11,7 +11,7 @@ * algorithm. Parallel sorts use a variant of this external sort * algorithm, and are typically only used for large amounts of data. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/tuplesort.h @@ -22,6 +22,7 @@ #define TUPLESORT_H #include "access/brin_tuple.h" +#include "access/gin_tuple.h" #include "access/itup.h" #include "executor/tuptable.h" #include "storage/dsm.h" @@ -443,6 +444,10 @@ extern Tuplesortstate *tuplesort_begin_index_gist(Relation heapRel, int sortopt); extern Tuplesortstate *tuplesort_begin_index_brin(int workMem, SortCoordinate coordinate, int sortopt); +extern Tuplesortstate *tuplesort_begin_index_gin(Relation heapRel, + Relation indexRel, + int workMem, SortCoordinate coordinate, + int sortopt); extern Tuplesortstate *tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, @@ -456,6 +461,7 @@ extern void tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel, ItemPointer self, const Datum *values, const bool *isnull); extern void tuplesort_putbrintuple(Tuplesortstate *state, BrinTuple *tuple, Size size); +extern void tuplesort_putgintuple(Tuplesortstate *state, GinTuple *tuple, Size size); extern void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull); @@ -465,6 +471,8 @@ extern HeapTuple tuplesort_getheaptuple(Tuplesortstate *state, bool forward); extern IndexTuple tuplesort_getindextuple(Tuplesortstate *state, bool forward); extern BrinTuple *tuplesort_getbrintuple(Tuplesortstate *state, Size *len, bool forward); +extern GinTuple *tuplesort_getgintuple(Tuplesortstate *state, Size *len, + bool forward); extern bool tuplesort_getdatum(Tuplesortstate *state, bool forward, bool copy, Datum *val, bool *isNull, Datum *abbrev); diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h index 3d8a90caaf93f..865ba7b826551 100644 --- a/src/include/utils/tuplestore.h +++ b/src/include/utils/tuplestore.h @@ -21,7 +21,7 @@ * Also, we have changed the API to return tuples in TupleTableSlots, * so that there is a check to prevent attempted access to system columns. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/tuplestore.h @@ -65,9 +65,8 @@ extern void tuplestore_copy_read_pointer(Tuplestorestate *state, extern void tuplestore_trim(Tuplestorestate *state); -extern const char *tuplestore_storage_type_name(Tuplestorestate *state); - -extern int64 tuplestore_space_used(Tuplestorestate *state); +extern void tuplestore_get_stats(Tuplestorestate *state, char **max_storage_type, + int64 *max_space); extern bool tuplestore_in_memory(Tuplestorestate *state); diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h index f506cc4aa35d4..1cb30f1818c2b 100644 --- a/src/include/utils/typcache.h +++ b/src/include/utils/typcache.h @@ -6,7 +6,7 @@ * The type cache exists to speed lookup of certain information about data * types that is not directly available from a type's pg_type row. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/typcache.h @@ -44,6 +44,7 @@ typedef struct TypeCacheEntry Oid typrelid; Oid typsubscript; Oid typelem; + Oid typarray; Oid typcollation; /* @@ -207,4 +208,8 @@ extern void SharedRecordTypmodRegistryInit(SharedRecordTypmodRegistry *, extern void SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *); +extern void AtEOXact_TypeCache(void); + +extern void AtEOSubXact_TypeCache(void); + #endif /* TYPCACHE_H */ diff --git a/src/include/utils/tzparser.h b/src/include/utils/tzparser.h index 5d5edfff2baa6..6b93fc6c6d56d 100644 --- a/src/include/utils/tzparser.h +++ b/src/include/utils/tzparser.h @@ -3,7 +3,7 @@ * tzparser.h * Timezone offset file parsing definitions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/tzparser.h diff --git a/src/include/utils/uuid.h b/src/include/utils/uuid.h index ae631e75d557d..239f365a54728 100644 --- a/src/include/utils/uuid.h +++ b/src/include/utils/uuid.h @@ -5,7 +5,7 @@ * to avoid conflicts with any uuid_t type that might be defined by * the system headers. * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * src/include/utils/uuid.h * diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index 312062cac6456..2f525aaa2af9a 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -5,7 +5,7 @@ * * Code originally contributed by Adriaan Joubert. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/varbit.h diff --git a/src/include/utils/varlena.h b/src/include/utils/varlena.h index e6d90b94be81a..db9fdf72941dd 100644 --- a/src/include/utils/varlena.h +++ b/src/include/utils/varlena.h @@ -3,7 +3,7 @@ * varlena.h * Functions for the variable-length built-in types. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/varlena.h diff --git a/src/include/utils/wait_classes.h b/src/include/utils/wait_classes.h new file mode 100644 index 0000000000000..51ee68397d595 --- /dev/null +++ b/src/include/utils/wait_classes.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * wait_classes.h + * Definitions related to wait event classes + * + * Copyright (c) 2001-2025, PostgreSQL Global Development Group + * + * src/include/utils/wait_classes.h + * ---------- + */ +#ifndef WAIT_CLASSES_H +#define WAIT_CLASSES_H + + +/* ---------- + * Wait Classes + * ---------- + */ +#define PG_WAIT_LWLOCK 0x01000000U +#define PG_WAIT_LOCK 0x03000000U +#define PG_WAIT_BUFFERPIN 0x04000000U +#define PG_WAIT_ACTIVITY 0x05000000U +#define PG_WAIT_CLIENT 0x06000000U +#define PG_WAIT_EXTENSION 0x07000000U +#define PG_WAIT_IPC 0x08000000U +#define PG_WAIT_TIMEOUT 0x09000000U +#define PG_WAIT_IO 0x0A000000U +#define PG_WAIT_INJECTIONPOINT 0x0B000000U + +#endif /* WAIT_CLASSES_H */ diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h index 9f18a753d47ef..f5815b4994ab4 100644 --- a/src/include/utils/wait_event.h +++ b/src/include/utils/wait_event.h @@ -2,7 +2,7 @@ * wait_event.h * Definitions related to wait event reporting * - * Copyright (c) 2001-2024, PostgreSQL Global Development Group + * Copyright (c) 2001-2025, PostgreSQL Global Development Group * * src/include/utils/wait_event.h * ---------- @@ -10,22 +10,6 @@ #ifndef WAIT_EVENT_H #define WAIT_EVENT_H - -/* ---------- - * Wait Classes - * ---------- - */ -#define PG_WAIT_LWLOCK 0x01000000U -#define PG_WAIT_LOCK 0x03000000U -#define PG_WAIT_BUFFERPIN 0x04000000U -#define PG_WAIT_ACTIVITY 0x05000000U -#define PG_WAIT_CLIENT 0x06000000U -#define PG_WAIT_EXTENSION 0x07000000U -#define PG_WAIT_IPC 0x08000000U -#define PG_WAIT_TIMEOUT 0x09000000U -#define PG_WAIT_IO 0x0A000000U -#define PG_WAIT_INJECTIONPOINT 0x0B000000U - /* enums for wait events */ #include "utils/wait_event_types.h" diff --git a/src/include/utils/xid8.h b/src/include/utils/xid8.h index e8f887c633331..35399b7f6fbb8 100644 --- a/src/include/utils/xid8.h +++ b/src/include/utils/xid8.h @@ -3,7 +3,7 @@ * xid8.h * Header file for the "xid8" ADT. * - * Copyright (c) 2020-2024, PostgreSQL Global Development Group + * Copyright (c) 2020-2025, PostgreSQL Global Development Group * * src/include/utils/xid8.h * diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index ed20e213753ac..0d7a816b9f933 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -4,7 +4,7 @@ * Declarations for XML data type support. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/xml.h diff --git a/src/include/varatt.h b/src/include/varatt.h index f04435e9ef340..2e8564d49980b 100644 --- a/src/include/varatt.h +++ b/src/include/varatt.h @@ -4,7 +4,7 @@ * variable-length datatypes (TOAST support) * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California * * src/include/varatt.h diff --git a/src/include/windowapi.h b/src/include/windowapi.h index 5c39b4f1cbab3..cb2ece166b6e9 100644 --- a/src/include/windowapi.h +++ b/src/include/windowapi.h @@ -19,7 +19,7 @@ * function in nodeWindowAgg.c for details. * * - * Portions Copyright (c) 2000-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2000-2025, PostgreSQL Global Development Group * * src/include/windowapi.h * diff --git a/src/interfaces/Makefile b/src/interfaces/Makefile index 7d56b29d28f56..e6822caa206a0 100644 --- a/src/interfaces/Makefile +++ b/src/interfaces/Makefile @@ -14,7 +14,19 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = libpq ecpg +ifeq ($(with_libcurl), yes) +SUBDIRS += libpq-oauth +else +ALWAYS_SUBDIRS += libpq-oauth +endif + $(recurse) +$(recurse_always) all-ecpg-recurse: all-libpq-recurse install-ecpg-recurse: install-libpq-recurse + +ifeq ($(with_libcurl), yes) +all-libpq-oauth-recurse: all-libpq-recurse +install-libpq-oauth-recurse: install-libpq-recurse +endif diff --git a/src/interfaces/ecpg/compatlib/Makefile b/src/interfaces/ecpg/compatlib/Makefile index 229a1bcaa05e3..457f1a81212b3 100644 --- a/src/interfaces/ecpg/compatlib/Makefile +++ b/src/interfaces/ecpg/compatlib/Makefile @@ -2,7 +2,7 @@ # # Makefile for ecpg compatibility library # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/interfaces/ecpg/compatlib/Makefile diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index 8ea89e640a083..e829d722f2228 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -175,6 +175,25 @@ deccopy(decimal *src, decimal *target) memcpy(target, src, sizeof(decimal)); } +static char * +ecpg_strndup(const char *str, size_t len) +{ + size_t real_len = strlen(str); + int use_len = (int) ((real_len > len) ? len : real_len); + + char *new = malloc(use_len + 1); + + if (new) + { + memcpy(new, str, use_len); + new[use_len] = '\0'; + } + else + errno = ENOMEM; + + return new; +} + int deccvasc(const char *cp, int len, decimal *np) { @@ -186,8 +205,8 @@ deccvasc(const char *cp, int len, decimal *np) if (risnull(CSTRINGTYPE, cp)) return 0; - str = pnstrdup(cp, len); /* decimal_in always converts the complete - * string */ + str = ecpg_strndup(cp, len); /* decimal_in always converts the complete + * string */ if (!str) ret = ECPG_INFORMIX_NUM_UNDERFLOW; else @@ -1016,7 +1035,7 @@ ECPG_informix_reset_sqlca(void) if (sqlca == NULL) return; - memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t)); + memcpy(sqlca, &sqlca_init, sizeof(struct sqlca_t)); } int diff --git a/src/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build index 3c57dd6508b23..56e0a21651b7a 100644 --- a/src/interfaces/ecpg/compatlib/meson.build +++ b/src/interfaces/ecpg/compatlib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpg_compat_sources = files( 'informix.c', diff --git a/src/interfaces/ecpg/ecpglib/Makefile b/src/interfaces/ecpg/ecpglib/Makefile index 5e159eb2a492b..3c99715273bd3 100644 --- a/src/interfaces/ecpg/ecpglib/Makefile +++ b/src/interfaces/ecpg/ecpglib/Makefile @@ -2,7 +2,7 @@ # # Makefile for ecpg library # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/interfaces/ecpg/ecpglib/Makefile diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index 8afb1f0a26fba..2bbb70333dcb4 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -579,7 +579,10 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p * The options string contains "keyword=value" pairs separated by * '&'s. We must break this up into keywords and values to pass to * libpq (it's okay to scribble on the options string). We ignore - * spaces just before each keyword or value. + * spaces just before each keyword or value. (The preprocessor used + * to add spaces around '&'s, making it necessary to ignore spaces + * before keywords here. While it no longer does that, we still must + * skip spaces to support code compiled with older preprocessors.) */ for (str = options; *str;) { @@ -664,7 +667,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p this->autocommit = autocommit; - PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, (void *) this); + PQsetNoticeReceiver(this->connection, &ECPGnoticeReceiver, this); return true; } diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c index ad279e245c4ac..651d5c8b2ed3c 100644 --- a/src/interfaces/ecpg/ecpglib/descriptor.c +++ b/src/interfaces/ecpg/ecpglib/descriptor.c @@ -198,7 +198,7 @@ get_char_item(int lineno, void *var, enum ECPGttype vartype, char *value, int va case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_string: - strncpy((char *) var, value, varcharsize); + strncpy(var, value, varcharsize); break; case ECPGt_varchar: { @@ -435,7 +435,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) /* allocate storage if needed */ if (arrsize == 0 && *(void **) var == NULL) { - void *mem = (void *) ecpg_auto_alloc(offset * ntuples, lineno); + void *mem = ecpg_auto_alloc(offset * ntuples, lineno); if (!mem) { @@ -490,7 +490,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) Assert(ecpg_clocale); stmt.oldlocale = uselocale(ecpg_clocale); #else -#ifdef HAVE__CONFIGTHREADLOCALE +#ifdef WIN32 stmt.oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); #endif stmt.oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno); @@ -510,9 +510,9 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) setlocale(LC_NUMERIC, stmt.oldlocale); ecpg_free(stmt.oldlocale); } -#ifdef HAVE__CONFIGTHREADLOCALE +#ifdef WIN32 if (stmt.oldthreadlocale != -1) - (void) _configthreadlocale(stmt.oldthreadlocale); + _configthreadlocale(stmt.oldthreadlocale); #endif #endif } @@ -540,7 +540,7 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) /* allocate storage if needed */ if (data_var.ind_arrsize == 0 && data_var.ind_value == NULL) { - void *mem = (void *) ecpg_auto_alloc(data_var.ind_offset * ntuples, lineno); + void *mem = ecpg_auto_alloc(data_var.ind_offset * ntuples, lineno); if (!mem) { @@ -597,7 +597,7 @@ set_desc_attr(struct descriptor_item *desc_item, struct variable *var, } ecpg_free(desc_item->data); /* free() takes care of a potential NULL value */ - desc_item->data = (char *) tobeinserted; + desc_item->data = tobeinserted; } diff --git a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h index 01b4309a71049..75cc68275bdac 100644 --- a/src/interfaces/ecpg/ecpglib/ecpglib_extern.h +++ b/src/interfaces/ecpg/ecpglib/ecpglib_extern.h @@ -13,9 +13,6 @@ #ifndef CHAR_BIT #include #endif -#ifdef LOCALE_T_IN_XLOCALE -#include -#endif enum COMPAT_MODE { @@ -80,7 +77,7 @@ struct statement locale_t oldlocale; #else char *oldlocale; -#ifdef HAVE__CONFIGTHREADLOCALE +#ifdef WIN32 int oldthreadlocale; #endif #endif diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 04d0b40c5376b..f52da06de9a1d 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -278,7 +278,7 @@ ecpg_is_type_an_array(int type, const struct statement *stmt, const struct varia isarray = ECPG_ARRAY_NONE; else { - isarray = (atol((char *) PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR; + isarray = (atoi(PQgetvalue(query, 0, 0)) == -1) ? ECPG_ARRAY_ARRAY : ECPG_ARRAY_VECTOR; if (ecpg_dynamic_type(type) == SQL3_CHARACTER || ecpg_dynamic_type(type) == SQL3_CHARACTER_VARYING) { @@ -1977,9 +1977,7 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator, * Make sure we do NOT honor the locale for numeric input/output since the * database wants the standard decimal point. If available, use * uselocale() for this because it's thread-safe. Windows doesn't have - * that, but it usually does have _configthreadlocale(). In some versions - * of MinGW, _configthreadlocale() exists but always returns -1 --- so - * treat that situation as if the function doesn't exist. + * that, but it does have _configthreadlocale(). */ #ifdef HAVE_USELOCALE @@ -1995,8 +1993,13 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator, return false; } #else -#ifdef HAVE__CONFIGTHREADLOCALE +#ifdef WIN32 stmt->oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); + if (stmt->oldthreadlocale == -1) + { + ecpg_do_epilogue(stmt); + return false; + } #endif stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno); if (stmt->oldlocale == NULL) @@ -2218,17 +2221,12 @@ ecpg_do_epilogue(struct statement *stmt) uselocale(stmt->oldlocale); #else if (stmt->oldlocale) + { setlocale(LC_NUMERIC, stmt->oldlocale); -#ifdef HAVE__CONFIGTHREADLOCALE - - /* - * This is a bit trickier than it looks: if we failed partway through - * statement initialization, oldthreadlocale could still be 0. But that's - * okay because a call with 0 is defined to be a no-op. - */ - if (stmt->oldthreadlocale != -1) - (void) _configthreadlocale(stmt->oldthreadlocale); +#ifdef WIN32 + _configthreadlocale(stmt->oldthreadlocale); #endif + } #endif free_statement(stmt); diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c index a83637ac75836..6979be2c988ac 100644 --- a/src/interfaces/ecpg/ecpglib/memory.c +++ b/src/interfaces/ecpg/ecpglib/memory.c @@ -100,7 +100,7 @@ set_auto_allocs(struct auto_mem *am) char * ecpg_auto_alloc(long size, int lineno) { - void *ptr = (void *) ecpg_alloc(size, lineno); + void *ptr = ecpg_alloc(size, lineno); if (!ptr) return NULL; diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build index 8e030a794336a..8f478c6a73ee4 100644 --- a/src/interfaces/ecpg/ecpglib/meson.build +++ b/src/interfaces/ecpg/ecpglib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpglib_sources = files( 'connect.c', diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index 2ae989e3e5d82..1885732a65203 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -66,7 +66,7 @@ static FILE *debugstream = NULL; void ecpg_init_sqlca(struct sqlca_t *sqlca) { - memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t)); + memcpy(sqlca, &sqlca_init, sizeof(struct sqlca_t)); } bool @@ -232,10 +232,10 @@ void ecpg_log(const char *format,...) { va_list ap; - struct sqlca_t *sqlca = ECPGget_sqlca(); const char *intl_format; int bufsize; char *fmt; + struct sqlca_t *sqlca; /* * For performance reasons, inspect simple_debug without taking the mutex. @@ -262,6 +262,8 @@ ecpg_log(const char *format,...) else snprintf(fmt, bufsize, "[%d]: %s", (int) getpid(), intl_format); + sqlca = ECPGget_sqlca(); + pthread_mutex_lock(&debug_mutex); /* Now that we hold the mutex, recheck simple_debug */ @@ -314,10 +316,10 @@ ECPGset_noind_null(enum ECPGttype type, void *ptr) *((long long *) ptr) = LONG_LONG_MIN; break; case ECPGt_float: - memset((char *) ptr, 0xff, sizeof(float)); + memset(ptr, 0xff, sizeof(float)); break; case ECPGt_double: - memset((char *) ptr, 0xff, sizeof(double)); + memset(ptr, 0xff, sizeof(double)); break; case ECPGt_varchar: *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00; @@ -327,18 +329,18 @@ ECPGset_noind_null(enum ECPGttype type, void *ptr) ((struct ECPGgeneric_bytea *) ptr)->len = 0; break; case ECPGt_decimal: - memset((char *) ptr, 0, sizeof(decimal)); + memset(ptr, 0, sizeof(decimal)); ((decimal *) ptr)->sign = NUMERIC_NULL; break; case ECPGt_numeric: - memset((char *) ptr, 0, sizeof(numeric)); + memset(ptr, 0, sizeof(numeric)); ((numeric *) ptr)->sign = NUMERIC_NULL; break; case ECPGt_interval: - memset((char *) ptr, 0xff, sizeof(interval)); + memset(ptr, 0xff, sizeof(interval)); break; case ECPGt_timestamp: - memset((char *) ptr, 0xff, sizeof(timestamp)); + memset(ptr, 0xff, sizeof(timestamp)); break; default: break; diff --git a/src/interfaces/ecpg/ecpglib/po/es.po b/src/interfaces/ecpg/ecpglib/po/es.po index 8dec975e62ef0..0a957e220c5ab 100644 --- a/src/interfaces/ecpg/ecpglib/po/es.po +++ b/src/interfaces/ecpg/ecpglib/po/es.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: ecpglib (PostgreSQL) 16\n" +"Project-Id-Version: ecpglib (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:09+0000\n" -"PO-Revision-Date: 2023-05-22 12:04+0200\n" +"POT-Creation-Date: 2025-02-16 19:40+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Emanuel Calvo Franco \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -18,15 +18,15 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: connect.c:243 +#: connect.c:221 msgid "empty message text" msgstr "mensaje de texto vacío" -#: connect.c:410 connect.c:675 +#: connect.c:386 connect.c:645 msgid "" msgstr "" -#: descriptor.c:876 misc.c:119 +#: descriptor.c:866 misc.c:88 msgid "NULL" msgstr "NULL" @@ -195,6 +195,6 @@ msgstr "se ha perdido la conexión al servidor" msgid "SQL error: %s\n" msgstr "error SQL: %s\n" -#: execute.c:2188 execute.c:2195 +#: execute.c:2186 execute.c:2193 msgid "" msgstr "" diff --git a/src/interfaces/ecpg/ecpglib/po/fr.po b/src/interfaces/ecpg/ecpglib/po/fr.po index e976d5cb0ef7f..8bdd59b1f2ebd 100644 --- a/src/interfaces/ecpg/ecpglib/po/fr.po +++ b/src/interfaces/ecpg/ecpglib/po/fr.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" #: connect.c:237 msgid "empty message text" @@ -74,7 +74,7 @@ msgstr "syntaxe invalide en entrée pour le type int : « %s » sur la ligne %d" #: error.c:75 #, c-format msgid "invalid input syntax for type unsigned int: \"%s\", on line %d" -msgstr "syntaxe invalide en entrée pour le type unisgned int : « %s » sur la ligne %d" +msgstr "syntaxe invalide en entrée pour le type unsigned int : « %s » sur la ligne %d" #. translator: this string will be truncated at 149 characters expanded. #: error.c:82 diff --git a/src/interfaces/ecpg/ecpglib/po/meson.build b/src/interfaces/ecpg/ecpglib/po/meson.build index 8d6c0e69a0497..420363f108a52 100644 --- a/src/interfaces/ecpg/ecpglib/po/meson.build +++ b/src/interfaces/ecpg/ecpglib/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('ecpglib' + '6' + '-' + pg_version_major.to_string())] diff --git a/src/interfaces/ecpg/ecpglib/po/ru.po b/src/interfaces/ecpg/ecpglib/po/ru.po index 16560ed8d3b6c..91b23dbc9fc07 100644 --- a/src/interfaces/ecpg/ecpglib/po/ru.po +++ b/src/interfaces/ecpg/ecpglib/po/ru.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: ecpglib (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" "PO-Revision-Date: 2019-09-09 13:30+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" @@ -17,15 +17,15 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: connect.c:243 +#: connect.c:221 msgid "empty message text" msgstr "пустое сообщение" -#: connect.c:410 connect.c:675 +#: connect.c:386 connect.c:645 msgid "" msgstr "<ПО_УМОЛЧАНИЮ>" -#: descriptor.c:876 misc.c:119 +#: descriptor.c:866 misc.c:88 msgid "NULL" msgstr "NULL" @@ -196,7 +196,7 @@ msgstr "подключение к серверу потеряно" msgid "SQL error: %s\n" msgstr "ошибка SQL: %s\n" -#: execute.c:2188 execute.c:2195 +#: execute.c:2186 execute.c:2193 msgid "" msgstr "<>" diff --git a/src/interfaces/ecpg/ecpglib/po/sv.po b/src/interfaces/ecpg/ecpglib/po/sv.po index 7ccde101caf21..9e499cc68d36d 100644 --- a/src/interfaces/ecpg/ecpglib/po/sv.po +++ b/src/interfaces/ecpg/ecpglib/po/sv.po @@ -1,14 +1,14 @@ # SWEDISH message translation file for ecpglib # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 14\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2020-04-10 02:39+0000\n" -"PO-Revision-Date: 2021-11-07 10:36+0100\n" +"POT-Creation-Date: 2024-07-12 11:10+0000\n" +"PO-Revision-Date: 2024-07-12 15:08+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,15 +17,15 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: connect.c:237 +#: connect.c:221 msgid "empty message text" msgstr "tom meddelandetext" -#: connect.c:401 connect.c:430 connect.c:653 +#: connect.c:386 connect.c:645 msgid "" msgstr "" -#: descriptor.c:871 misc.c:119 +#: descriptor.c:866 misc.c:88 msgid "NULL" msgstr "NULL" @@ -185,15 +185,15 @@ msgstr "kunde inte ansluta till databas \"%s\" på rad %d" msgid "SQL error %d on line %d" msgstr "SQL-fel %d på rad %d" -#: error.c:254 +#: error.c:253 msgid "the connection to the server was lost" msgstr "anslutningen till servern tappades" -#: error.c:347 +#: error.c:345 #, c-format msgid "SQL error: %s\n" msgstr "SQL-fel: %s\n" -#: execute.c:2196 execute.c:2203 +#: execute.c:2186 execute.c:2193 msgid "" msgstr "" diff --git a/src/interfaces/ecpg/ecpglib/po/uk.po b/src/interfaces/ecpg/ecpglib/po/uk.po index dcb1738702c9b..e1ca3efd440b7 100644 --- a/src/interfaces/ecpg/ecpglib/po/uk.po +++ b/src/interfaces/ecpg/ecpglib/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:39+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-02-24 00:09+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,18 +14,18 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/ecpglib.pot\n" -"X-Crowdin-File-ID: 890\n" +"X-Crowdin-File: /REL_17_STABLE/ecpglib.pot\n" +"X-Crowdin-File-ID: 1022\n" -#: connect.c:243 +#: connect.c:221 msgid "empty message text" msgstr "пусте повідомлення" -#: connect.c:410 connect.c:675 +#: connect.c:386 connect.c:645 msgid "" msgstr "<ЗА_ЗАМОВЧУВАННЯМ>" -#: descriptor.c:876 misc.c:119 +#: descriptor.c:866 misc.c:88 msgid "NULL" msgstr "NULL" @@ -194,7 +194,7 @@ msgstr "з'єднання із сервером втрачено" msgid "SQL error: %s\n" msgstr "помилка SQL: %s\n" -#: execute.c:2189 execute.c:2196 +#: execute.c:2186 execute.c:2193 msgid "" msgstr "<пусто>" diff --git a/src/interfaces/ecpg/ecpglib/typename.c b/src/interfaces/ecpg/ecpglib/typename.c index 1d482c4fa61ca..1fb9860371bf8 100644 --- a/src/interfaces/ecpg/ecpglib/typename.c +++ b/src/interfaces/ecpg/ecpglib/typename.c @@ -131,11 +131,12 @@ sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat) case INTERVALOID: return ECPGt_interval; case INT8OID: -#ifdef HAVE_LONG_LONG_INT_64 - return ECPGt_long_long; -#endif -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_LONG == 8 return ECPGt_long; +#elif SIZEOF_LONG_LONG == 8 + return ECPGt_long_long; +#else +#error "cannot find integer type of the same size as INT8OID" #endif /* Unhandled types always return a string */ default: diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in index 824617b917528..4af45930b6115 100644 --- a/src/interfaces/ecpg/include/ecpg_config.h.in +++ b/src/interfaces/ecpg/include/ecpg_config.h.in @@ -1,14 +1,8 @@ /* Define to 1 to build client libraries as thread-safe code. */ #define ENABLE_THREAD_SAFETY 1 -/* Define to 1 if the system has the type `int64'. */ -#undef HAVE_INT64 +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG -/* Define to 1 if `long int' works and is 64 bits. */ -#undef HAVE_LONG_INT_64 - -/* Define to 1 if `long long int' works and is 64 bits. */ -#undef HAVE_LONG_LONG_INT_64 - -/* Define to 1 to use to define type bool. */ -#undef PG_USE_STDBOOL +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index 771761ffe4969..dbf3cc3a0c265 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -7,6 +7,7 @@ #ifndef _ECPGLIB_H #define _ECPGLIB_H +#include #include #include "ecpg_config.h" @@ -14,35 +15,6 @@ #include "libpq-fe.h" #include "sqlca.h" -/* - * This is a small extract from c.h since we don't want to leak all postgres - * definitions into ecpg programs; but we need to know what bool is. - */ -#ifndef __cplusplus - -#ifdef PG_USE_STDBOOL -#include -#else - -/* - * We assume bool has been defined if true and false are. This avoids - * duplicate-typedef errors if this file is included after c.h. - */ -#if !(defined(true) && defined(false)) -typedef unsigned char bool; -#endif - -#ifndef true -#define true ((bool) 1) -#endif - -#ifndef false -#define false ((bool) 0) -#endif - -#endif /* not PG_USE_STDBOOL */ -#endif /* not C++ */ - #ifdef __cplusplus extern "C" diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build index 31610fef58929..a6541e1a68657 100644 --- a/src/interfaces/ecpg/include/meson.build +++ b/src/interfaces/ecpg/include/meson.build @@ -1,12 +1,10 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpg_inc = include_directories('.') ecpg_conf_keys = [ - 'HAVE_INT64', - 'HAVE_LONG_INT_64', - 'HAVE_LONG_LONG_INT_64', - 'PG_USE_STDBOOL', + 'SIZEOF_LONG', + 'SIZEOF_LONG_LONG', ] ecpg_conf_data = configuration_data() diff --git a/src/interfaces/ecpg/include/pgtypes_interval.h b/src/interfaces/ecpg/include/pgtypes_interval.h index 2809b356f7353..f0acbb4512aff 100644 --- a/src/interfaces/ecpg/include/pgtypes_interval.h +++ b/src/interfaces/ecpg/include/pgtypes_interval.h @@ -3,25 +3,17 @@ #ifndef PGTYPES_INTERVAL #define PGTYPES_INTERVAL +#include + #include #include #ifndef C_H -#ifdef HAVE_LONG_INT_64 -#ifndef HAVE_INT64 -typedef long int int64; -#endif -#elif defined(HAVE_LONG_LONG_INT_64) -#ifndef HAVE_INT64 -typedef long long int int64; -#endif -#else -/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */ -#error must have a working 64-bit integer datatype -#endif +typedef int64_t int64; #define HAVE_INT64_TIMESTAMP + #endif /* C_H */ typedef struct diff --git a/src/interfaces/ecpg/include/sqltypes.h b/src/interfaces/ecpg/include/sqltypes.h index e7cbfa479567d..498840458c4a1 100644 --- a/src/interfaces/ecpg/include/sqltypes.h +++ b/src/interfaces/ecpg/include/sqltypes.h @@ -46,12 +46,14 @@ #define SQLINTERVAL ECPGt_interval #define SQLNCHAR ECPGt_char #define SQLNVCHAR ECPGt_char -#ifdef HAVE_LONG_LONG_INT_64 +#if SIZEOF_LONG == 8 +#define SQLINT8 ECPGt_long +#define SQLSERIAL8 ECPGt_long +#elif SIZEOF_LONG_LONG == 8 #define SQLINT8 ECPGt_long_long #define SQLSERIAL8 ECPGt_long_long #else -#define SQLINT8 ECPGt_long -#define SQLSERIAL8 ECPGt_long +#error "cannot find integer type of the same size as SQLINT8" #endif #endif /* ndef ECPG_SQLTYPES_H */ diff --git a/src/interfaces/ecpg/meson.build b/src/interfaces/ecpg/meson.build index ac42a70a31f8d..2d173ce376f8c 100644 --- a/src/interfaces/ecpg/meson.build +++ b/src/interfaces/ecpg/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpg_targets = [] diff --git a/src/interfaces/ecpg/pgtypeslib/Makefile b/src/interfaces/ecpg/pgtypeslib/Makefile index a10b0b584bc91..c993888c61df8 100644 --- a/src/interfaces/ecpg/pgtypeslib/Makefile +++ b/src/interfaces/ecpg/pgtypeslib/Makefile @@ -2,7 +2,7 @@ # # Makefile for ecpg pgtypes library # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/interfaces/ecpg/pgtypeslib/Makefile diff --git a/src/interfaces/ecpg/pgtypeslib/common.c b/src/interfaces/ecpg/pgtypeslib/common.c index 8972229ca2f40..c9e9a55c6a726 100644 --- a/src/interfaces/ecpg/pgtypeslib/common.c +++ b/src/interfaces/ecpg/pgtypeslib/common.c @@ -19,7 +19,7 @@ pgtypes_alloc(long size) char * pgtypes_strdup(const char *str) { - char *new = (char *) strdup(str); + char *new = strdup(str); if (!new) errno = ENOMEM; diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c index ed08088bfe132..c4119ab79320a 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -949,9 +949,10 @@ int GetEpochTime(struct tm *tm) { struct tm *t0; + struct tm tmbuf; time_t epoch = 0; - t0 = gmtime(&epoch); + t0 = gmtime_r(&epoch, &tmbuf); if (t0) { @@ -973,12 +974,13 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct tm *tm, char **tzn) { time_t time = (time_t) _time; struct tm *tx; + struct tm tmbuf; errno = 0; if (tzp != NULL) - tx = localtime((time_t *) &time); + tx = localtime_r(&time, &tmbuf); else - tx = gmtime((time_t *) &time); + tx = gmtime_r(&time, &tmbuf); if (!tx) { @@ -2325,10 +2327,10 @@ DecodeDateTime(char **field, int *ftype, int nf, return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1; /* - * check for valid day of month, now that we know for sure the month - * and year... + * check for valid day of month and month, now that we know for sure + * the month and year... */ - if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) + if (tm->tm_mon < 1 || tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) return -1; /* @@ -2810,9 +2812,10 @@ PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d, /* number of seconds in scan_val.luint_val */ { struct tm *tms; + struct tm tmbuf; time_t et = (time_t) scan_val.luint_val; - tms = gmtime(&et); + tms = gmtime_r(&et, &tmbuf); if (tms) { diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build index 04a1ba379278d..02301ec9acb90 100644 --- a/src/interfaces/ecpg/pgtypeslib/meson.build +++ b/src/interfaces/ecpg/pgtypeslib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpg_pgtypes_sources = files( 'common.c', diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index 35e7b92da405e..bb2a86981caa6 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -232,7 +232,7 @@ get_str_from_var(numeric *var, int dscale) if (var->sign == NUMERIC_NAN) { - str = (char *) pgtypes_alloc(4); + str = pgtypes_alloc(4); if (str == NULL) return NULL; sprintf(str, "NaN"); @@ -269,7 +269,7 @@ get_str_from_var(numeric *var, int dscale) /* * Allocate space for the result */ - if ((str = (char *) pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL) + if ((str = pgtypes_alloc(Max(0, dscale) + Max(0, var->weight) + 4)) == NULL) return NULL; cp = str; diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c index f1b143fbd2e4e..7cf433266f458 100644 --- a/src/interfaces/ecpg/pgtypeslib/timestamp.c +++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c @@ -11,6 +11,7 @@ #error -ffast-math is known to break this code #endif +#include "common/int.h" #include "dt.h" #include "pgtypes_date.h" #include "pgtypes_timestamp.h" @@ -48,14 +49,8 @@ tm2timestamp(struct tm *tm, fsec_t fsec, int *tzp, timestamp * result) dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); - *result = (dDate * USECS_PER_DAY) + time; - /* check for major overflow */ - if ((*result - time) / USECS_PER_DAY != dDate) - return -1; - /* check for just-barely overflow (okay except time-of-day wraps) */ - /* caution: we want to allow 1999-12-31 24:00:00 */ - if ((*result < 0 && dDate > 0) || - (*result > 0 && dDate < -1)) + if (unlikely(pg_mul_s64_overflow(dDate, USECS_PER_DAY, result) || + pg_add_s64_overflow(*result, time, result))) return -1; if (tzp != NULL) *result = dt2local(*result, -(*tzp)); @@ -134,11 +129,12 @@ timestamp2tm(timestamp dt, int *tzp, struct tm *tm, fsec_t *fsec, const char **t if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) { #if defined(HAVE_STRUCT_TM_TM_ZONE) || defined(HAVE_INT_TIMEZONE) + struct tm tmbuf; utime = dt / USECS_PER_SEC + ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400)); - tx = localtime(&utime); + tx = localtime_r(&utime, &tmbuf); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; tm->tm_mday = tx->tm_mday; diff --git a/src/interfaces/ecpg/preproc/.gitignore b/src/interfaces/ecpg/preproc/.gitignore index 958a826f9e83a..7759f6c53a90e 100644 --- a/src/interfaces/ecpg/preproc/.gitignore +++ b/src/interfaces/ecpg/preproc/.gitignore @@ -6,3 +6,4 @@ /ecpg_kwlist_d.h /typename.c /ecpg +/tmp_check/ diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 934b7cef1b0f5..f2ac885047969 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/interfaces/ecpg/preproc # -# Copyright (c) 1998-2024, PostgreSQL Global Development Group +# Copyright (c) 1998-2025, PostgreSQL Global Development Group # # src/interfaces/ecpg/preproc/Makefile # @@ -36,6 +36,7 @@ OBJS = \ preproc.o \ type.o \ typename.o \ + util.o \ variable.o # where to find gen_keywordlist.pl and subsidiary files @@ -64,8 +65,7 @@ preproc.h: preproc.c preproc.c: BISONFLAGS += -d -preproc.y: ../../../backend/parser/gram.y parse.pl check_rules.pl ecpg.addons ecpg.header ecpg.tokens ecpg.trailer ecpg.type - $(PERL) $(srcdir)/check_rules.pl --srcdir $(srcdir) --parser $< +preproc.y: ../../../backend/parser/gram.y parse.pl ecpg.addons ecpg.header ecpg.tokens ecpg.trailer ecpg.type $(PERL) $(srcdir)/parse.pl --srcdir $(srcdir) --parser $< --output $@ # generate keyword headers @@ -81,6 +81,9 @@ ecpg_keywords.o: ecpg_kwlist_d.h c_keywords.o: c_kwlist_d.h keywords.o: $(top_srcdir)/src/include/parser/kwlist.h +check: + $(prove_check) + install: all installdirs $(INSTALL_PROGRAM) ecpg$(X) '$(DESTDIR)$(bindir)' @@ -94,3 +97,4 @@ clean distclean: rm -f *.o ecpg$(X) rm -f typename.c rm -f preproc.y preproc.c preproc.h pgc.c c_kwlist_d.h ecpg_kwlist_d.h + rm -rf tmp_check diff --git a/src/interfaces/ecpg/preproc/README.parser b/src/interfaces/ecpg/preproc/README.parser index ddc3061d486b1..85ecc803e0916 100644 --- a/src/interfaces/ecpg/preproc/README.parser +++ b/src/interfaces/ecpg/preproc/README.parser @@ -1,42 +1,97 @@ -ECPG modifies and extends the core grammar in a way that -1) every token in ECPG is type. New tokens are - defined in ecpg.tokens, types are defined in ecpg.type -2) most tokens from the core grammar are simply converted - to literals concatenated together to form the SQL string - passed to the server, this is done by parse.pl. -3) some rules need side-effects, actions are either added - or completely overridden (compared to the basic token - concatenation) for them, these are defined in ecpg.addons, - the rules for ecpg.addons are explained below. -4) new grammar rules are needed for ECPG metacommands. - These are in ecpg.trailer. -5) ecpg.header contains common functions, etc. used by - actions for grammar rules. - -In "ecpg.addons", every modified rule follows this pattern: - ECPG: dumpedtokens postfix -where "dumpedtokens" is simply tokens from core gram.y's -rules concatenated together. e.g. if gram.y has this: - ruleA: tokenA tokenB tokenC {...} -then "dumpedtokens" is "ruleAtokenAtokenBtokenC". -"postfix" above can be: -a) "block" - the automatic rule created by parse.pl is completely - overridden, the code block has to be written completely as - it were in a plain bison grammar -b) "rule" - the automatic rule is extended on, so new syntaxes - are accepted for "ruleA". E.g.: - ECPG: ruleAtokenAtokenBtokenC rule - | tokenD tokenE { action_code; } - ... - It will be substituted with: - ruleA: - | tokenD tokenE { action_code; } - ... -c) "addon" - the automatic action for the rule (SQL syntax constructed - from the tokens concatenated together) is prepended with a new - action code part. This code part is written as is's already inside - the { ... } - -Multiple "addon" or "block" lines may appear together with the -new code block if the code block is common for those rules. +ECPG's grammar (preproc.y) is built by parse.pl from the +backend's grammar (gram.y) plus various add-on rules. +Some notes: + +1) Most input matching core grammar productions is simply converted + to strings and concatenated together to form the SQL string + passed to the server. This is handled mostly automatically, + as described below. +2) Some grammar rules need special actions that are added to or + completely override the default token-concatenation behavior. + This is controlled by ecpg.addons as explained below. +3) Additional grammar rules are needed for ECPG's own commands. + These are in ecpg.trailer, as is the "epilogue" part of preproc.y. +4) ecpg.header contains the "prologue" part of preproc.y, including + support functions, Bison options, etc. +5) Additional terminals added by ECPG must be defined in ecpg.tokens. + Additional nonterminals added by ECPG must be defined in ecpg.type, + but only if they have non-void result type, which most don't. + +ecpg.header, ecpg.tokens, ecpg.type, and ecpg.trailer are just +copied verbatim into preproc.y at appropriate points. + + +In the pre-v18 implementation of ecpg, the strings constructed +by grammar rules were returned as the Bison result of each rule. +This led to a large number of effectively-identical rule actions, +which caused compilation-time problems with some versions of clang. +Now, rules that need to return a string are declared as having +void type (which in Bison means leaving out any %type declaration +for them). Instead, we abuse Bison's "location tracking" mechanism +to carry the string results, which allows a single YYLLOC_DEFAULT +call to handle the standard token-concatenation behavior for the +vast majority of the rules. Rules that don't need to do anything +else can omit a semantic action altogether. Rules that need to +construct an output string specially can do so, but they should +assign it to "@$" rather than the usual "$$"; also, to reference +the string value of the N'th input token, write "@N" not "$N". +(But rules that return something other than a simple string +continue to use the normal Bison notations.) + + +ecpg.addons contains entries that begin with a line like + ECPG: ruletype tokenlist +and typically have one or more following lines that are the code +for a grammar action. Any line not starting with "ECPG:" is taken +to be part of the code block for the preceding "ECPG:" line. + +"tokenlist" identifies which gram.y production this entry affects. +It is simply a list of the target nonterminal and the input tokens +from the gram.y rule. For example, to modify the action for a +gram.y rule like this: + target: tokenA tokenB tokenC {...} +"tokenlist" would be "target tokenA tokenB tokenC". If we want to +modify a non-first alternative for a nonterminal, we still write the +nonterminal. For example, "tokenlist" should be "target tokenD tokenE" +to affect the second alternative in: + target: tokenA tokenB tokenC {...} + | tokenD tokenE {...} + +"ruletype" is one of: + +a) "block" - the automatic action that parse.pl would create is + completely overridden. Instead the entry's code block is emitted. + The code block must include the braces ({}) needed for a Bison action. + +b) "addon" - the entry's code block is inserted into the generated + action, ahead of the automatic token-concatenation code. + In this case the code block need not contain braces, since + it will be inserted within braces. + +c) "rule" - the automatic action is emitted, but then the entry's + code block is added verbatim afterwards. This typically is + used to add new alternatives to a nonterminal of the core grammar. + For example, given the entry: + ECPG: rule target tokenA tokenB tokenC + | tokenD tokenE { custom_action; } + what will be emitted is + target: tokenA tokenB tokenC { automatic_action; } + | tokenD tokenE { custom_action; } + +Multiple "ECPG:" entries can share the same code block, if the +same action is needed for all. When an "ECPG:" line is immediately +followed by another one, it is not assigned an empty code block; +rather the next nonempty code block is assumed to apply to all +immediately preceding "ECPG:" entries. + +In addition to the modifications specified by ecpg.addons, +parse.pl contains some tables that list backend grammar +productions to be ignored or modified. + +Nonterminals that construct strings (as described above) should be +given void type, which is parse.pl's default assumption for +nonterminals found in gram.y. If the result should be of some other +type, make an entry in parse.pl's %replace_types table. %replace_types +can also be used to suppress output of a nonterminal's rules +altogether (in which case ecpg.trailer had better provide replacement +rules, since the nonterminal will still be referred to elsewhere). diff --git a/src/interfaces/ecpg/preproc/c_kwlist.h b/src/interfaces/ecpg/preproc/c_kwlist.h index 701de8e2b19c0..82a7c0a592d92 100644 --- a/src/interfaces/ecpg/preproc/c_kwlist.h +++ b/src/interfaces/ecpg/preproc/c_kwlist.h @@ -7,7 +7,7 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/ecpg/preproc/c_kwlist.h diff --git a/src/interfaces/ecpg/preproc/check_rules.pl b/src/interfaces/ecpg/preproc/check_rules.pl deleted file mode 100644 index 1ee1aed2f67c9..0000000000000 --- a/src/interfaces/ecpg/preproc/check_rules.pl +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/perl -# src/interfaces/ecpg/preproc/check_rules.pl -# test parser generator for ecpg -# call with backend grammar as stdin -# -# Copyright (c) 2009-2024, PostgreSQL Global Development Group -# -# Written by Michael Meskes -# Andy Colson -# -# Placed under the same license as PostgreSQL. -# -# Command line: [-v] [path only to ecpg.addons] [full filename of gram.y] -# -v enables verbose mode... show's some stats... thought it might be interesting -# -# This script loads rule names from gram.y and sets $found{rule} = 1 for each. -# Then it checks to make sure each rule in ecpg.addons was found in gram.y - -use strict; -use warnings FATAL => 'all'; -use Getopt::Long; - -my $srcdir = '.'; -my $parser = '../../../backend/parser/gram.y'; -my $stamp = ''; -my $verbose = 0; - -GetOptions( - 'srcdir=s' => \$srcdir, - 'parser=s' => \$parser, - 'stamp=s' => \$stamp, - 'verbose' => \$verbose,) or die "wrong arguments"; - -my $filename = "$srcdir/ecpg.addons"; -if ($verbose) -{ - print "parser: $parser\n"; - print "addons: $filename\n"; -} - -my %replace_line = ( - 'ExecuteStmtEXECUTEnameexecute_param_clause' => - 'EXECUTE prepared_name execute_param_clause execute_rest', - - 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' - => 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', - - 'ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' - => 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', - - 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' => - 'PREPARE prepared_name prep_type_clause AS PreparableStmt'); - -my $block = ''; -my $yaccmode = 0; -my $in_rule = 0; -my $brace_indent = 0; -my (@arr, %found); -my $comment = 0; -my $non_term_id = ''; -my $cc = 0; - -open my $parser_fh, '<', $parser or die $!; -while (<$parser_fh>) -{ - if (/^%%/) - { - $yaccmode++; - } - - if ($yaccmode != 1) - { - next; - } - - chomp; # strip record separator - - next if ($_ eq ''); - - # Make sure any braces are split - s/{/ { /g; - s/}/ } /g; - - # Any comments are split - s|\/\*| /* |g; - s|\*\/| */ |g; - - # Now split the line into individual fields - my $n = (@arr = split(' ')); - - # Go through each field in turn - for (my $fieldIndexer = 0; $fieldIndexer < $n; $fieldIndexer++) - { - if ($arr[$fieldIndexer] eq '*/' && $comment) - { - $comment = 0; - next; - } - elsif ($comment) - { - next; - } - elsif ($arr[$fieldIndexer] eq '/*') - { - - # start of a multiline comment - $comment = 1; - next; - } - elsif ($arr[$fieldIndexer] eq '//') - { - next; - } - elsif ($arr[$fieldIndexer] eq '}') - { - $brace_indent--; - next; - } - elsif ($arr[$fieldIndexer] eq '{') - { - $brace_indent++; - next; - } - - if ($brace_indent > 0) - { - next; - } - - if ($arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|') - { - $block = $non_term_id . $block; - if ($replace_line{$block}) - { - $block = $non_term_id . $replace_line{$block}; - $block =~ tr/ |//d; - } - $found{$block} = 1; - $cc++; - $block = ''; - $in_rule = 0 if $arr[$fieldIndexer] eq ';'; - } - elsif ( - ($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:') - || ( $fieldIndexer + 1 < $n - && $arr[ $fieldIndexer + 1 ] eq ':')) - { - die "unterminated rule at grammar line $.\n" - if $in_rule; - $in_rule = 1; - $non_term_id = $arr[$fieldIndexer]; - $non_term_id =~ tr/://d; - } - else - { - $block = $block . $arr[$fieldIndexer]; - } - } -} - -die "unterminated rule at end of grammar\n" - if $in_rule; - -close $parser_fh; -if ($verbose) -{ - print "$cc rules loaded\n"; -} - -my $ret = 0; -$cc = 0; - -open my $ecpg_fh, '<', $filename or die $!; -while (<$ecpg_fh>) -{ - if (!/^ECPG:/) - { - next; - } - - my @Fld = split(' ', $_, 3); - $cc++; - if (not exists $found{ $Fld[1] }) - { - print $Fld[1], " is not used for building parser!\n"; - $ret = 1; - } -} -close $ecpg_fh; - -if ($verbose) -{ - print "$cc rules checked\n"; -} - -if ($stamp) -{ - open my $stampfh, '>', $stamp or die $!; - close $stampfh; -} - -exit $ret; diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index f4b1878289cb1..e8c7016bdc11f 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -18,13 +18,12 @@ static struct assignment *assignments; void -push_assignment(char *var, enum ECPGdtype value) +push_assignment(const char *var, enum ECPGdtype value) { struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment)); new->next = assignments; - new->variable = mm_alloc(strlen(var) + 1); - strcpy(new->variable, var); + new->variable = mm_strdup(var); new->value = value; assignments = new; } @@ -73,7 +72,7 @@ ECPGnumeric_lvalue(char *name) static struct descriptor *descriptors; void -add_descriptor(char *name, char *connection) +add_descriptor(const char *name, const char *connection) { struct descriptor *new; @@ -83,20 +82,16 @@ add_descriptor(char *name, char *connection) new = (struct descriptor *) mm_alloc(sizeof(struct descriptor)); new->next = descriptors; - new->name = mm_alloc(strlen(name) + 1); - strcpy(new->name, name); + new->name = mm_strdup(name); if (connection) - { - new->connection = mm_alloc(strlen(connection) + 1); - strcpy(new->connection, connection); - } + new->connection = mm_strdup(connection); else - new->connection = connection; + new->connection = NULL; descriptors = new; } void -drop_descriptor(char *name, char *connection) +drop_descriptor(const char *name, const char *connection) { struct descriptor *i; struct descriptor **lastptr = &descriptors; @@ -126,9 +121,8 @@ drop_descriptor(char *name, char *connection) mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); } -struct descriptor - * -lookup_descriptor(char *name, char *connection) +struct descriptor * +lookup_descriptor(const char *name, const char *connection) { struct descriptor *i; @@ -159,7 +153,7 @@ lookup_descriptor(char *name, char *connection) } void -output_get_descr_header(char *desc_name) +output_get_descr_header(const char *desc_name) { struct assignment *results; @@ -178,7 +172,7 @@ output_get_descr_header(char *desc_name) } void -output_get_descr(char *desc_name, char *index) +output_get_descr(const char *desc_name, const char *index) { struct assignment *results; @@ -211,7 +205,7 @@ output_get_descr(char *desc_name, char *index) } void -output_set_descr_header(char *desc_name) +output_set_descr_header(const char *desc_name) { struct assignment *results; @@ -272,7 +266,7 @@ descriptor_item_name(enum ECPGdtype itemcode) } void -output_set_descr(char *desc_name, char *index) +output_set_descr(const char *desc_name, const char *index) { struct assignment *results; @@ -350,11 +344,17 @@ descriptor_variable(const char *name, int input) struct variable * sqlda_variable(const char *name) { - struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable)); - - p->name = mm_strdup(name); - p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); + /* + * Presently, sqlda variables are only needed for the duration of the + * current statement. Rather than add infrastructure to manage them, + * let's just loc_alloc them. + */ + struct variable *p = (struct variable *) loc_alloc(sizeof(struct variable)); + + p->name = loc_strdup(name); + p->type = (struct ECPGtype *) loc_alloc(sizeof(struct ECPGtype)); p->type->type = ECPGt_sqlda; + p->type->type_name = NULL; p->type->size = NULL; p->type->struct_sizeof = NULL; p->type->u.element = NULL; diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons index e94da2a3f8d4c..b732f1a35513f 100644 --- a/src/interfaces/ecpg/preproc/ecpg.addons +++ b/src/interfaces/ecpg/preproc/ecpg.addons @@ -1,37 +1,38 @@ /* src/interfaces/ecpg/preproc/ecpg.addons */ -ECPG: stmtClosePortalStmt block +ECPG: block stmt ClosePortalStmt { if (INFORMIX_MODE) { - if (pg_strcasecmp($1+strlen("close "), "database") == 0) + if (pg_strcasecmp(@1 + strlen("close "), "database") == 0) { if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in CLOSE DATABASE statement"); fprintf(base_yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");"); whenever_action(2); - free($1); break; } } - output_statement($1, 0, ECPGst_normal); + output_statement(@1, 0, ECPGst_normal); } -ECPG: stmtDeallocateStmt block +ECPG: block stmt DeallocateStmt { - output_deallocate_prepare_statement($1); + output_deallocate_prepare_statement(@1); } -ECPG: stmtDeclareCursorStmt block - { output_simple_statement($1, (strncmp($1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0); } -ECPG: stmtDiscardStmt block -ECPG: stmtFetchStmt block - { output_statement($1, 1, ECPGst_normal); } -ECPG: stmtDeleteStmt block -ECPG: stmtInsertStmt block -ECPG: stmtSelectStmt block -ECPG: stmtUpdateStmt block - { output_statement($1, 1, ECPGst_prepnormal); } -ECPG: stmtExecuteStmt block +ECPG: block stmt DeclareCursorStmt + { + output_simple_statement(@1, (strncmp(@1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0); + } +ECPG: block stmt DiscardStmt +ECPG: block stmt FetchStmt + { output_statement(@1, 1, ECPGst_normal); } +ECPG: block stmt DeleteStmt +ECPG: block stmt InsertStmt +ECPG: block stmt SelectStmt +ECPG: block stmt UpdateStmt + { output_statement(@1, 1, ECPGst_prepnormal); } +ECPG: block stmt ExecuteStmt { check_declared_list($1.name); if ($1.type == NULL || strlen($1.type) == 0) @@ -44,25 +45,27 @@ ECPG: stmtExecuteStmt block else { /* case of ecpg_ident or CSTRING */ - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *str = mm_strdup($1.name + 1); + char length[32]; + char *str; - /* It must be cut off double quotation because new_variable() double-quotes. */ + /* Remove double quotes from name */ + str = loc_strdup($1.name + 1); str[strlen(str) - 1] = '\0'; - sprintf(length, "%zu", strlen(str)); + snprintf(length, sizeof(length), "%zu", strlen(str)); add_variable_to_tail(&argsinsert, new_variable(str, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } - output_statement(cat_str(3, mm_strdup("execute"), mm_strdup("$0"), $1.type), 0, ECPGst_exec_with_exprlist); + output_statement(cat_str(3, "execute", "$0", $1.type), 0, ECPGst_exec_with_exprlist); } } -ECPG: stmtPrepareStmt block +ECPG: block stmt PrepareStmt { check_declared_list($1.name); if ($1.type == NULL) output_prepare_statement($1.name, $1.stmt); else if (strlen($1.type) == 0) { - char *stmt = cat_str(3, mm_strdup("\""), $1.stmt, mm_strdup("\"")); + char *stmt = cat_str(3, "\"", $1.stmt, "\""); + output_prepare_statement($1.name, stmt); } else @@ -72,63 +75,59 @@ ECPG: stmtPrepareStmt block add_variable_to_tail(&argsinsert, find_variable($1.name), &no_indicator); else { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *str = mm_strdup($1.name + 1); + char length[32]; + char *str; - /* It must be cut off double quotation because new_variable() double-quotes. */ + /* Remove double quotes from name */ + str = loc_strdup($1.name + 1); str[strlen(str) - 1] = '\0'; - sprintf(length, "%zu", strlen(str)); + snprintf(length, sizeof(length), "%zu", strlen(str)); add_variable_to_tail(&argsinsert, new_variable(str, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } - output_statement(cat_str(5, mm_strdup("prepare"), mm_strdup("$0"), $1.type, mm_strdup("as"), $1.stmt), 0, ECPGst_prepare); + output_statement(cat_str(5, "prepare", "$0", $1.type, "as", $1.stmt), 0, ECPGst_prepare); } } -ECPG: stmtTransactionStmt block +ECPG: block stmt TransactionStmt { - fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); + fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", @1); whenever_action(2); - free($1); } -ECPG: toplevel_stmtTransactionStmtLegacy block +ECPG: block toplevel_stmt TransactionStmtLegacy { - fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); + fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", @1); whenever_action(2); - free($1); } -ECPG: stmtViewStmt rule +ECPG: rule stmt ViewStmt | ECPGAllocateDescr { - fprintf(base_yyout,"ECPGallocate_desc(__LINE__, %s);",$1); + fprintf(base_yyout, "ECPGallocate_desc(__LINE__, %s);", @1); whenever_action(0); - free($1); } | ECPGConnect { if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in CONNECT statement"); - fprintf(base_yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit); + fprintf(base_yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, @1, autocommit); reset_variables(); whenever_action(2); - free($1); } | ECPGDeclareStmt { - output_simple_statement($1, 0); + output_simple_statement(@1, 0); } | ECPGCursorStmt { - output_simple_statement($1, (strncmp($1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0); + output_simple_statement(@1, (strncmp(@1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0); } | ECPGDeallocateDescr { - fprintf(base_yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1); + fprintf(base_yyout, "ECPGdeallocate_desc(__LINE__, %s);", @1); whenever_action(0); - free($1); } | ECPGDeclare { - output_simple_statement($1, 0); + output_simple_statement(@1, 0); } | ECPGDescribe { @@ -136,11 +135,10 @@ ECPG: stmtViewStmt rule fprintf(base_yyout, "{ ECPGdescribe(__LINE__, %d, %d, %s, %s,", compat, $1.input, connection ? connection : "NULL", $1.stmt_name); dump_variables(argsresult, 1); + argsresult = NULL; fputs("ECPGt_EORT);", base_yyout); fprintf(base_yyout, "}"); output_line_number(); - - free($1.stmt_name); } | ECPGDisconnect { @@ -148,84 +146,77 @@ ECPG: stmtViewStmt rule mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in DISCONNECT statement"); fprintf(base_yyout, "{ ECPGdisconnect(__LINE__, %s);", - $1 ? $1 : "\"CURRENT\""); + @1 ? @1 : "\"CURRENT\""); whenever_action(2); - free($1); } - | ECPGExecuteImmediateStmt { output_statement($1, 0, ECPGst_exec_immediate); } + | ECPGExecuteImmediateStmt + { + output_statement(@1, 0, ECPGst_exec_immediate); + } | ECPGFree { const char *con = connection ? connection : "NULL"; - if (strcmp($1, "all") == 0) + if (strcmp(@1, "all") == 0) fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con); - else if ($1[0] == ':') - fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, %s);", compat, con, $1+1); + else if (@1[0] == ':') + fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, %s);", compat, con, @1 + 1); else - fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1); + fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, @1); whenever_action(2); - free($1); } | ECPGGetDescriptor { lookup_descriptor($1.name, connection); output_get_descr($1.name, $1.str); - free($1.name); - free($1.str); } | ECPGGetDescriptorHeader { - lookup_descriptor($1, connection); - output_get_descr_header($1); - free($1); + lookup_descriptor(@1, connection); + output_get_descr_header(@1); } | ECPGOpen { struct cursor *ptr; - if ((ptr = add_additional_variables($1, true)) != NULL) + if ((ptr = add_additional_variables(@1, true)) != NULL) { + free(connection); connection = ptr->connection ? mm_strdup(ptr->connection) : NULL; - output_statement(mm_strdup(ptr->command), 0, ECPGst_normal); + output_statement(ptr->command, 0, ECPGst_normal); ptr->opened = true; } } | ECPGSetAutocommit { - fprintf(base_yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL"); + fprintf(base_yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", @1, connection ? connection : "NULL"); whenever_action(2); - free($1); } | ECPGSetConnection { if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in SET CONNECTION statement"); - fprintf(base_yyout, "{ ECPGsetconn(__LINE__, %s);", $1); + fprintf(base_yyout, "{ ECPGsetconn(__LINE__, %s);", @1); whenever_action(2); - free($1); } | ECPGSetDescriptor { lookup_descriptor($1.name, connection); output_set_descr($1.name, $1.str); - free($1.name); - free($1.str); } | ECPGSetDescriptorHeader { - lookup_descriptor($1, connection); - output_set_descr_header($1); - free($1); + lookup_descriptor(@1, connection); + output_set_descr_header(@1); } | ECPGTypedef { if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in TYPE statement"); - fprintf(base_yyout, "%s", $1); - free($1); + fprintf(base_yyout, "%s", @1); output_line_number(); } | ECPGVar @@ -233,175 +224,163 @@ ECPG: stmtViewStmt rule if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in VAR statement"); - output_simple_statement($1, 0); + output_simple_statement(@1, 0); } | ECPGWhenever { if (connection) mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in WHENEVER statement"); - output_simple_statement($1, 0); - } -ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block - { - char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; - $$ = cat_str(2,mm_strdup("where current of"), cursor_marker); - } -ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_optionswhere_clause addon - if (strcmp($6, "from") == 0 && - (strcmp($7, "stdin") == 0 || strcmp($7, "stdout") == 0)) - mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented"); -ECPG: var_valueNumericOnly addon - if ($1[0] == '$') - { - free($1); - $1 = mm_strdup("$0"); - } -ECPG: fetch_argscursor_name addon - struct cursor *ptr = add_additional_variables($1, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($1[0] == ':') + output_simple_statement(@1, 0); + } +ECPG: block where_or_current_clause WHERE CURRENT_P OF cursor_name + { + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; + + @$ = cat_str(2, "where current of", cursor_marker); + } +ECPG: addon CopyStmt COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause + if (strcmp(@5, "from") == 0 && + (strcmp(@7, "stdin") == 0 || strcmp(@7, "stdout") == 0)) + mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented"); +ECPG: addon var_value NumericOnly + if (@1[0] == '$') + @$ = "$0"; +ECPG: addon fetch_args cursor_name + struct cursor *ptr = add_additional_variables(@1, false); + + update_connection(ptr->connection); + if (@1[0] == ':') + @$ = "$0"; +ECPG: addon fetch_args from_in cursor_name + struct cursor *ptr = add_additional_variables(@2, false); + + update_connection(ptr->connection); + if (@2[0] == ':') + @$ = cat2_str(@1, "$0"); +ECPG: addon fetch_args NEXT opt_from_in cursor_name +ECPG: addon fetch_args PRIOR opt_from_in cursor_name +ECPG: addon fetch_args FIRST_P opt_from_in cursor_name +ECPG: addon fetch_args LAST_P opt_from_in cursor_name +ECPG: addon fetch_args ALL opt_from_in cursor_name + struct cursor *ptr = add_additional_variables(@3, false); + + update_connection(ptr->connection); + if (@3[0] == ':') + @$ = cat_str(3, @1, @2, "$0"); +ECPG: addon fetch_args SignedIconst opt_from_in cursor_name + struct cursor *ptr = add_additional_variables(@3, false); + bool replace = false; + + update_connection(ptr->connection); + if (@3[0] == ':') { - free($1); - $1 = mm_strdup("$0"); + @3 = "$0"; + replace = true; } -ECPG: fetch_argsfrom_incursor_name addon - struct cursor *ptr = add_additional_variables($2, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($2[0] == ':') + if (@1[0] == '$') { - free($2); - $2 = mm_strdup("$0"); + @1 = "$0"; + replace = true; } -ECPG: fetch_argsNEXTopt_from_incursor_name addon -ECPG: fetch_argsPRIORopt_from_incursor_name addon -ECPG: fetch_argsFIRST_Popt_from_incursor_name addon -ECPG: fetch_argsLAST_Popt_from_incursor_name addon -ECPG: fetch_argsALLopt_from_incursor_name addon - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($3[0] == ':') + if (replace) + @$ = cat_str(3, @1, @2, @3); +ECPG: addon fetch_args FORWARD ALL opt_from_in cursor_name +ECPG: addon fetch_args BACKWARD ALL opt_from_in cursor_name + struct cursor *ptr = add_additional_variables(@4, false); + + update_connection(ptr->connection); + if (@4[0] == ':') + @$ = cat_str(4, @1, @2, @3, "$0"); +ECPG: addon fetch_args ABSOLUTE_P SignedIconst opt_from_in cursor_name +ECPG: addon fetch_args RELATIVE_P SignedIconst opt_from_in cursor_name +ECPG: addon fetch_args FORWARD SignedIconst opt_from_in cursor_name +ECPG: addon fetch_args BACKWARD SignedIconst opt_from_in cursor_name + struct cursor *ptr = add_additional_variables(@4, false); + bool replace = false; + + update_connection(ptr->connection); + if (@4[0] == ':') { - free($3); - $3 = mm_strdup("$0"); + @4 = "$0"; + replace = true; } -ECPG: fetch_argsSignedIconstopt_from_incursor_name addon - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($3[0] == ':') + if (@2[0] == '$') { - free($3); - $3 = mm_strdup("$0"); + @2 = "$0"; + replace = true; } - if ($1[0] == '$') - { - free($1); - $1 = mm_strdup("$0"); - } -ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon -ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($4[0] == ':') - { - free($4); - $4 = mm_strdup("$0"); - } -ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon -ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon -ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon -ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - - if ($4[0] == ':') - { - free($4); - $4 = mm_strdup("$0"); - } - if ($2[0] == '$') - { - free($2); - $2 = mm_strdup("$0"); - } -ECPG: cursor_namename rule + if (replace) + @$ = cat_str(4, @1, @2, @3, @4); +ECPG: block cursor_name name | char_civar - { - char *curname = mm_alloc(strlen($1) + 2); - sprintf(curname, ":%s", $1); - free($1); - $1 = curname; - $$ = $1; - } -ECPG: ExplainableStmtExecuteStmt block { - $$ = $1.name; + char *curname = loc_alloc(strlen(@1) + 2); + + sprintf(curname, ":%s", @1); + @$ = curname; } -ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block +ECPG: block ExplainableStmt ExecuteStmt { - $$.name = $2; - $$.type = $3; - $$.stmt = $5; + @$ = $1.name; + } +ECPG: block PrepareStmt PREPARE prepared_name prep_type_clause AS PreparableStmt + { + $$.name = @2; + $$.type = @3; + $$.stmt = @5; } | PREPARE prepared_name FROM execstring { - $$.name = $2; + $$.name = @2; $$.type = NULL; - $$.stmt = $4; + $$.stmt = @4; } -ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block +ECPG: block ExecuteStmt EXECUTE prepared_name execute_param_clause execute_rest { - $$.name = $2; - $$.type = $3; + $$.name = @2; + $$.type = @3; } -ECPG: ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block +ECPG: block ExecuteStmt CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest { - $$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table"),$4,mm_strdup("as execute"),$7,$8,$9); + $$.name = @$; } -ECPG: ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block +ECPG: block ExecuteStmt CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest { - $$.name = cat_str(8,mm_strdup("create"),$2,mm_strdup("table if not exists"),$7,mm_strdup("as execute"),$10,$11,$12); + $$.name = @$; } -ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block +ECPG: block DeclareCursorStmt DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt { - struct cursor *ptr, *this; - char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2); - char *comment, *c1, *c2; - int (* strcmp_fn)(const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp); + struct cursor *ptr, + *this; + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; + char *comment, + *c1, + *c2; + int (*strcmp_fn) (const char *, const char *) = ((@2[0] == ':' || @2[0] == '"') ? strcmp : pg_strcasecmp); - if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0) - mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode"); + if (INFORMIX_MODE && pg_strcasecmp(@2, "database") == 0) + mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode"); for (ptr = cur; ptr != NULL; ptr = ptr->next) { - if (strcmp_fn($2, ptr->name) == 0) + if (strcmp_fn(@2, ptr->name) == 0) { - if ($2[0] == ':') - mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2+1); + if (@2[0] == ':') + mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", @2 + 1); else - mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2); + mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", @2); } } this = (struct cursor *) mm_alloc(sizeof(struct cursor)); this->next = cur; - this->name = $2; + this->name = mm_strdup(@2); this->function = (current_function ? mm_strdup(current_function) : NULL); this->connection = connection ? mm_strdup(connection) : NULL; this->opened = false; - this->command = cat_str(7, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for"), $7); + this->command = mm_strdup(cat_str(7, "declare", cursor_marker, @3, "cursor", @5, "for", @7)); this->argsinsert = argsinsert; this->argsinsert_oos = NULL; this->argsresult = argsresult; @@ -409,176 +388,166 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt argsinsert = argsresult = NULL; cur = this; - c1 = mm_strdup(this->command); - if ((c2 = strstr(c1, "*/")) != NULL) + c1 = loc_strdup(this->command); + while ((c2 = strstr(c1, "*/")) != NULL) { /* We put this text into a comment, so we better remove [*][/]. */ c2[0] = '.'; c2[1] = '.'; } - comment = cat_str(3, mm_strdup("/*"), c1, mm_strdup("*/")); + comment = cat_str(3, "/*", c1, "*/"); - $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment); + @$ = cat2_str(adjust_outofscope_cursor_vars(this), comment); } -ECPG: ClosePortalStmtCLOSEcursor_name block +ECPG: block ClosePortalStmt CLOSE cursor_name { - char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : $2; + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; struct cursor *ptr = NULL; - for (ptr = cur; ptr != NULL; ptr = ptr -> next) + + for (ptr = cur; ptr != NULL; ptr = ptr->next) { - if (strcmp($2, ptr -> name) == 0) + if (strcmp(@2, ptr->name) == 0) { - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); - + update_connection(ptr->connection); break; } } - $$ = cat2_str(mm_strdup("close"), cursor_marker); + @$ = cat2_str("close", cursor_marker); } -ECPG: opt_hold block +ECPG: block opt_hold { if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit) - $$ = mm_strdup("with hold"); + @$ = "with hold"; else - $$ = EMPTY; - } -ECPG: into_clauseINTOOptTempTableName block - { - FoundInto = 1; - $$= cat2_str(mm_strdup("into"), $2); - } - | ecpg_into { $$ = EMPTY; } -ECPG: TypenameSimpleTypenameopt_array_bounds block - { $$ = cat2_str($1, $2.str); } -ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block - { $$ = cat_str(3, mm_strdup("setof"), $2, $3.str); } -ECPG: opt_array_boundsopt_array_bounds'['']' block + @$ = ""; + } +ECPG: block into_clause INTO OptTempTableName + { + FoundInto = 1; + @$ = cat2_str("into", @2); + } + | ecpg_into + { + @$ = ""; + } +ECPG: block Typename SimpleTypename opt_array_bounds + { + @$ = cat2_str(@1, $2.str); + } +ECPG: block Typename SETOF SimpleTypename opt_array_bounds + { + @$ = cat_str(3, "setof", @2, $3.str); + } +ECPG: block opt_array_bounds opt_array_bounds '[' ']' { $$.index1 = $1.index1; $$.index2 = $1.index2; if (strcmp($$.index1, "-1") == 0) - $$.index1 = mm_strdup("0"); + $$.index1 = "0"; else if (strcmp($1.index2, "-1") == 0) - $$.index2 = mm_strdup("0"); - $$.str = cat_str(2, $1.str, mm_strdup("[]")); + $$.index2 = "0"; + $$.str = cat_str(2, $1.str, "[]"); } | opt_array_bounds '[' Iresult ']' { $$.index1 = $1.index1; $$.index2 = $1.index2; if (strcmp($1.index1, "-1") == 0) - $$.index1 = mm_strdup($3); + $$.index1 = @3; else if (strcmp($1.index2, "-1") == 0) - $$.index2 = mm_strdup($3); - $$.str = cat_str(4, $1.str, mm_strdup("["), $3, mm_strdup("]")); - } -ECPG: opt_array_bounds - { - $$.index1 = mm_strdup("-1"); - $$.index2 = mm_strdup("-1"); - $$.str= EMPTY; - } -ECPG: IconstICONST block - { $$ = make_name(); } -ECPG: AexprConstNULL_P rule - | civar { $$ = $1; } - | civarind { $$ = $1; } -ECPG: ColIdcol_name_keyword rule - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - | CHAR_P { $$ = mm_strdup("char"); } - | VALUES { $$ = mm_strdup("values"); } -ECPG: type_function_nametype_func_name_keyword rule - | ECPGKeywords { $$ = $1; } - | ECPGTypeName { $$ = $1; } - | ECPGCKeywords { $$ = $1; } -ECPG: VariableShowStmtSHOWALL block + $$.index2 = @3; + $$.str = cat_str(4, $1.str, "[", @3, "]"); + } +ECPG: block opt_array_bounds { - mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented"); - $$ = EMPTY; + $$.index1 = "-1"; + $$.index2 = "-1"; + $$.str = ""; } -ECPG: FetchStmtMOVEfetch_args rule - | FETCH fetch_args ecpg_fetch_into +ECPG: rule AexprConst NULL_P + | civar + | civarind +ECPG: block VariableShowStmt SHOW ALL { - $$ = cat2_str(mm_strdup("fetch"), $2); + mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented"); } +ECPG: rule FetchStmt MOVE fetch_args + | FETCH fetch_args ecpg_fetch_into | FETCH FORWARD cursor_name opt_ecpg_fetch_into { - char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3; - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; + struct cursor *ptr = add_additional_variables(@3, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("fetch forward"), cursor_marker); + @$ = cat_str(2, "fetch forward", cursor_marker); } | FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into { - char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; + struct cursor *ptr = add_additional_variables(@4, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("fetch forward from"), cursor_marker); + @$ = cat_str(2, "fetch forward from", cursor_marker); } | FETCH BACKWARD cursor_name opt_ecpg_fetch_into { - char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3; - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; + struct cursor *ptr = add_additional_variables(@3, false); - $$ = cat_str(2, mm_strdup("fetch backward"), cursor_marker); + update_connection(ptr->connection); + + @$ = cat_str(2, "fetch backward", cursor_marker); } | FETCH BACKWARD from_in cursor_name opt_ecpg_fetch_into { - char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; + struct cursor *ptr = add_additional_variables(@4, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("fetch backward from"), cursor_marker); + @$ = cat_str(2, "fetch backward from", cursor_marker); } | MOVE FORWARD cursor_name { - char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3; - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; + struct cursor *ptr = add_additional_variables(@3, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("move forward"), cursor_marker); + @$ = cat_str(2, "move forward", cursor_marker); } | MOVE FORWARD from_in cursor_name { - char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; + struct cursor *ptr = add_additional_variables(@4, false); - $$ = cat_str(2, mm_strdup("move forward from"), cursor_marker); + update_connection(ptr->connection); + + @$ = cat_str(2, "move forward from", cursor_marker); } | MOVE BACKWARD cursor_name { - char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3; - struct cursor *ptr = add_additional_variables($3, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; + struct cursor *ptr = add_additional_variables(@3, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("move backward"), cursor_marker); + @$ = cat_str(2, "move backward", cursor_marker); } | MOVE BACKWARD from_in cursor_name { - char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4; - struct cursor *ptr = add_additional_variables($4, false); - if (ptr -> connection) - connection = mm_strdup(ptr -> connection); + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; + struct cursor *ptr = add_additional_variables(@4, false); + + update_connection(ptr->connection); - $$ = cat_str(2, mm_strdup("move backward from"), cursor_marker); + @$ = cat_str(2, "move backward from", cursor_marker); } -ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block +ECPG: block limit_clause LIMIT select_limit_value ',' select_offset_value { mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server"); - $$ = cat_str(4, mm_strdup("limit"), $2, mm_strdup(","), $4); } -ECPG: SignedIconstIconst rule - | civar { $$ = $1; } +ECPG: rule SignedIconst Iconst + | civar diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 73c37631acc6e..3f0f10e654afc 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -1,7 +1,7 @@ /* src/interfaces/ecpg/preproc/ecpg.c */ /* Main for ecpg, the PostgreSQL embedded SQL precompiler. */ -/* Copyright (c) 1996-2024, PostgreSQL Global Development Group */ +/* Copyright (c) 1996-2025, PostgreSQL Global Development Group */ #include "postgres_fe.h" @@ -20,6 +20,7 @@ bool autocommit = false, regression_mode = false, auto_prepare = false; +static const char *progname; char *output_filename; enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL; @@ -139,7 +140,6 @@ main(int argc, char *const argv[]) bool verbose = false, header_mode = false; struct _include_path *ip; - const char *progname; char my_exec_path[MAXPGPATH]; char include_path[MAXPGPATH]; diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header index 571b92f643461..dde69a3969598 100644 --- a/src/interfaces/ecpg/preproc/ecpg.header +++ b/src/interfaces/ecpg/preproc/ecpg.header @@ -5,6 +5,7 @@ #include "postgres_fe.h" #include "preproc_extern.h" +#include "preproc.h" #include "ecpg_config.h" #include @@ -12,14 +13,6 @@ extern int base_yychar; extern int base_yynerrs; -/* Location tracking support --- simpler than bison's default */ -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do { \ - if (N) \ - (Current) = (Rhs)[1]; \ - else \ - (Current) = (Rhs)[0]; \ - } while (0) /* * The %name-prefix option below will make bison call base_yylex, but we @@ -36,24 +29,35 @@ extern int base_yynerrs; /* * Variables containing simple states. */ -int struct_level = 0; -int braces_open; /* brace level counter */ -char *current_function; -int ecpg_internal_var = 0; -char *connection = NULL; -char *input_filename = NULL; +int struct_level = 0; +int braces_open; /* brace level counter */ +char *current_function; +int ecpg_internal_var = 0; +char *connection = NULL; +char *input_filename = NULL; static int FoundInto = 0; static int initializer = 0; static int pacounter = 1; -static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */ static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_startline[STRUCT_DEPTH]; static int varchar_counter = 1; static int bytea_counter = 1; -/* temporarily store struct members while creating the data structure */ -struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL }; +/* + * We temporarily store struct members here while parsing struct declarations. + * The struct_member_list (at a given nesting depth) is constructed while + * scanning the fields within "struct { .... }", but we can't remove it upon + * seeing the right brace. It's kept around and copied into the variables + * or typedefs that follow, in order to handle cases like + * "struct foo { ... } foovar1, foovar2;". We recycle the storage only + * upon closing the current nesting level or starting the next struct + * declaration within the same nesting level. + * For cases like "struct foo foovar1, foovar2;", we copy the saved struct + * field list for the typedef or struct tag into the struct_member_list + * global variable, and then copy it again to the newly-declared variables. + */ +struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = {NULL}; /* also store struct type so we can do a sizeof() later */ static char *ECPGstruct_sizeof = NULL; @@ -66,156 +70,85 @@ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; static struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NULL}, 0}; -static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0); - static bool check_declared_list(const char *name); +static void update_connection(const char *newconn); + /* - * Handle parsing errors and warnings + * "Location tracking" support. We commandeer Bison's location tracking + * mechanism to manage the output string for productions that ordinarily would + * return a result. This allows the majority of those productions to + * have default semantic actions, reducing the size of the parser, and also + * greatly reducing its compilation time on some versions of clang. + * + * To do this, we make YYLTYPE be a pointer to a malloc'd string, and then + * merge the location strings of the input tokens in the default YYLLOC + * computation. Productions that are okay with the standard merge need not + * do anything more; otherwise, they can override it by assigning to @$. */ +#define YYLLOC_DEFAULT(Current, Rhs, N) yylloc_default(&(Current), Rhs, N) + static void -vmmerror(int error_code, enum errortype type, const char *error, va_list ap) +yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N) { - /* localize the error message string */ - error = _(error); - - fprintf(stderr, "%s:%d: ", input_filename, base_yylineno); - - switch(type) + if (N > 1) { - case ET_WARNING: - fprintf(stderr, _("WARNING: ")); - break; - case ET_ERROR: - fprintf(stderr, _("ERROR: ")); - break; - } + /* Concatenate non-empty inputs with one space between them */ + char *result, + *ptr; + size_t needed = 0; - vfprintf(stderr, error, ap); + for (int i = 1; i <= N; i++) + { + size_t thislen = strlen(rhs[i]); - fprintf(stderr, "\n"); + if (needed > 0 && thislen > 0) + needed++; + needed += thislen; + } + result = (char *) loc_alloc(needed + 1); + ptr = result; + for (int i = 1; i <= N; i++) + { + size_t thislen = strlen(rhs[i]); - switch(type) + if (ptr > result && thislen > 0) + *ptr++ = ' '; + memcpy(ptr, rhs[i], thislen); + ptr += thislen; + } + *ptr = '\0'; + *target = result; + } + else if (N == 1) { - case ET_WARNING: - break; - case ET_ERROR: - ret_value = error_code; - break; + /* Just re-use the single input */ + *target = rhs[1]; + } + else + { + /* No need to allocate any space */ + *target = ""; } -} - -void -mmerror(int error_code, enum errortype type, const char *error, ...) -{ - va_list ap; - - va_start(ap, error); - vmmerror(error_code, type, error, ap); - va_end(ap); -} - -void -mmfatal(int error_code, const char *error, ...) -{ - va_list ap; - - va_start(ap, error); - vmmerror(error_code, ET_ERROR, error, ap); - va_end(ap); - - if (base_yyin) - fclose(base_yyin); - if (base_yyout) - fclose(base_yyout); - - if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0) - fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename); - exit(error_code); -} - -/* - * string concatenation - */ - -static char * -cat2_str(char *str1, char *str2) -{ - char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2); - - strcpy(res_str, str1); - if (strlen(str1) != 0 && strlen(str2) != 0) - strcat(res_str, " "); - strcat(res_str, str2); - free(str1); - free(str2); - return res_str; -} - -static char * -cat_str(int count, ...) -{ - va_list args; - int i; - char *res_str; - - va_start(args, count); - - res_str = va_arg(args, char *); - - /* now add all other strings */ - for (i = 1; i < count; i++) - res_str = cat2_str(res_str, va_arg(args, char *)); - - va_end(args); - - return res_str; -} - -static char * -make2_str(char *str1, char *str2) -{ - char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1); - - strcpy(res_str, str1); - strcat(res_str, str2); - free(str1); - free(str2); - return res_str; -} - -static char * -make3_str(char *str1, char *str2, char *str3) -{ - char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1); - - strcpy(res_str, str1); - strcat(res_str, str2); - strcat(res_str, str3); - free(str1); - free(str2); - free(str3); - return res_str; } /* and the rest */ static char * -make_name(void) -{ - return mm_strdup(base_yytext); -} - -static char * -create_questionmarks(char *name, bool array) +create_questionmarks(const char *name, bool array) { struct variable *p = find_variable(name); - int count; - char *result = EMPTY; + int count; + char *result = ""; - /* In case we have a struct, we have to print as many "?" as there are attributes in the struct + /* + * In case we have a struct, we have to print as many "?" as there are + * attributes in the struct + * * An array is only allowed together with an element argument - * This is essentially only used for inserts, but using a struct as input parameter is an error anywhere else - * so we don't have to worry here. */ + * + * This is essentially only used for inserts, but using a struct as input + * parameter is an error anywhere else so we don't have to worry here. + */ if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct)) { @@ -226,59 +159,62 @@ create_questionmarks(char *name, bool array) else m = p->type->u.element->u.members; - for (count = 0; m != NULL; m=m->next, count++); + for (count = 0; m != NULL; m = m->next, count++); } else count = 1; - for (; count > 0; count --) + for (; count > 0; count--) { - sprintf(pacounter_buffer, "$%d", pacounter++); - result = cat_str(3, result, mm_strdup(pacounter_buffer), mm_strdup(" , ")); - } + char buf[32]; - /* removed the trailing " ," */ + snprintf(buf, sizeof(buf), "$%d", pacounter++); + result = cat_str(3, result, buf, " , "); + } - result[strlen(result)-3] = '\0'; + /* remove the trailing " ," */ + result[strlen(result) - 3] = '\0'; return result; } static char * adjust_outofscope_cursor_vars(struct cursor *cur) { - /* Informix accepts DECLARE with variables that are out of scope when OPEN is called. - * For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE - * it in another functions. This is very useful for e.g. event-driver programming, - * but may also lead to dangerous programming. The limitation when this is allowed - * and doesn't cause problems have to be documented, like the allocated variables - * must not be realloc()'ed. + /* + * Informix accepts DECLARE with variables that are out of scope when OPEN + * is called. For instance you can DECLARE a cursor in one function, and + * OPEN/FETCH/CLOSE it in another functions. This is very useful for e.g. + * event-driver programming, but may also lead to dangerous programming. + * The limitation when this is allowed and doesn't cause problems have to + * be documented, like the allocated variables must not be realloc()'ed. * - * We have to change the variables to our own struct and just store the pointer - * instead of the variable. Do it only for local variables, not for globals. + * We have to change the variables to our own struct and just store the + * pointer instead of the variable. Do it only for local variables, not + * for globals. */ - - char *result = EMPTY; - int insert; + char *result = ""; + int insert; for (insert = 1; insert >= 0; insert--) { struct arguments *list; struct arguments *ptr; struct arguments *newlist = NULL; - struct variable *newvar, *newind; + struct variable *newvar, + *newind; list = (insert ? cur->argsinsert : cur->argsresult); for (ptr = list; ptr != NULL; ptr = ptr->next) { - char var_text[20]; - char *original_var; - bool skip_set_var = false; - bool var_ptr = false; + char var_text[20]; + char *original_var; + bool skip_set_var = false; + bool var_ptr = false; /* change variable name to "ECPGget_var()" */ original_var = ptr->variable->name; - sprintf(var_text, "%d))", ecpg_internal_var); + snprintf(var_text, sizeof(var_text), "%d))", ecpg_internal_var); /* Don't emit ECPGset_var() calls for global variables */ if (ptr->variable->brace_level == 0) @@ -299,12 +235,12 @@ adjust_outofscope_cursor_vars(struct cursor *cur) && ptr->variable->type->type != ECPGt_bytea) && atoi(ptr->variable->type->size) > 1) { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, - mm_strdup("1"), + "1", ptr->variable->type->u.element->counter), ptr->variable->type->size), 0); @@ -316,10 +252,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) || ptr->variable->type->type == ECPGt_bytea) && atoi(ptr->variable->type->size) > 1) { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), @@ -331,11 +267,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union) { - newvar = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->variable->type->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newvar = new_variable(cat_str(5, "(*(", + ptr->variable->type->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->variable->type->u.members, ptr->variable->type->type, ptr->variable->type->type_name, @@ -348,11 +284,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) if (ptr->variable->type->u.element->type == ECPGt_struct || ptr->variable->type->u.element->type == ECPGt_union) { - newvar = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->variable->type->u.element->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newvar = new_variable(cat_str(5, "(*(", + ptr->variable->type->u.element->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->variable->type->u.element->u.members, ptr->variable->type->u.element->type, ptr->variable->type->u.element->type_name, @@ -361,10 +297,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, ptr->variable->type->u.element->size, ptr->variable->type->u.element->counter), @@ -375,10 +311,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newvar = new_variable(cat_str(4, mm_strdup("*("), - mm_strdup(ecpg_type_name(ptr->variable->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "*(", + ecpg_type_name(ptr->variable->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), @@ -386,16 +322,23 @@ adjust_outofscope_cursor_vars(struct cursor *cur) var_ptr = true; } - /* create call to "ECPGset_var(, , . )" */ + /* + * create call to "ECPGset_var(, , . + * )" + */ if (!skip_set_var) { - sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "("); - result = cat_str(5, result, mm_strdup("ECPGset_var("), - mm_strdup(var_text), mm_strdup(original_var), - mm_strdup("), __LINE__);\n")); + snprintf(var_text, sizeof(var_text), "%d, %s", + ecpg_internal_var++, var_ptr ? "&(" : "("); + result = cat_str(5, result, "ECPGset_var(", + var_text, original_var, + "), __LINE__);\n"); } - /* now the indicator if there is one and it's not a global variable */ + /* + * now the indicator if there is one and it's not a global + * variable + */ if ((ptr->indicator->type->type == ECPGt_NO_INDICATOR) || (ptr->indicator->brace_level == 0)) { newind = ptr->indicator; @@ -404,17 +347,17 @@ adjust_outofscope_cursor_vars(struct cursor *cur) { /* change variable name to "ECPGget_var()" */ original_var = ptr->indicator->name; - sprintf(var_text, "%d))", ecpg_internal_var); + snprintf(var_text, sizeof(var_text), "%d))", ecpg_internal_var); var_ptr = false; if (ptr->indicator->type->type == ECPGt_struct || ptr->indicator->type->type == ECPGt_union) { - newind = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->indicator->type->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newind = new_variable(cat_str(5, "(*(", + ptr->indicator->type->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->indicator->type->u.members, ptr->indicator->type->type, ptr->indicator->type->type_name, @@ -427,11 +370,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) if (ptr->indicator->type->u.element->type == ECPGt_struct || ptr->indicator->type->u.element->type == ECPGt_union) { - newind = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->indicator->type->u.element->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newind = new_variable(cat_str(5, "(*(", + ptr->indicator->type->u.element->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->indicator->type->u.element->u.members, ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->type_name, @@ -440,9 +383,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newind = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), mm_strdup(var_text)), + newind = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->indicator->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->size, ptr->indicator->type->u.element->counter), @@ -453,10 +397,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else if (atoi(ptr->indicator->type->size) > 1) { - newind = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->indicator->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newind = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->indicator->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), @@ -464,10 +408,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newind = new_variable(cat_str(4, mm_strdup("*("), - mm_strdup(ecpg_type_name(ptr->indicator->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newind = new_variable(cat_str(4, "*(", + ecpg_type_name(ptr->indicator->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), @@ -475,11 +419,15 @@ adjust_outofscope_cursor_vars(struct cursor *cur) var_ptr = true; } - /* create call to "ECPGset_var(, . )" */ - sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "("); - result = cat_str(5, result, mm_strdup("ECPGset_var("), - mm_strdup(var_text), mm_strdup(original_var), - mm_strdup("), __LINE__);\n")); + /* + * create call to "ECPGset_var(, . )" + */ + snprintf(var_text, sizeof(var_text), "%d, %s", + ecpg_internal_var++, var_ptr ? "&(" : "("); + result = cat_str(5, result, "ECPGset_var(", + var_text, original_var, + "), __LINE__);\n"); } add_variable_to_tail(&newlist, newvar, newind); @@ -497,16 +445,17 @@ adjust_outofscope_cursor_vars(struct cursor *cur) /* This tests whether the cursor was declared and opened in the same function. */ #define SAMEFUNC(cur) \ ((cur->function == NULL) || \ - (cur->function != NULL && strcmp(cur->function, current_function) == 0)) + (cur->function != NULL && current_function != NULL && \ + strcmp(cur->function, current_function) == 0)) static struct cursor * -add_additional_variables(char *name, bool insert) +add_additional_variables(const char *name, bool insert) { struct cursor *ptr; struct arguments *p; - int (* strcmp_fn)(const char *, const char *) = ((name[0] == ':' || name[0] == '"') ? strcmp : pg_strcasecmp); + int (*strcmp_fn) (const char *, const char *) = ((name[0] == ':' || name[0] == '"') ? strcmp : pg_strcasecmp); - for (ptr = cur; ptr != NULL; ptr=ptr->next) + for (ptr = cur; ptr != NULL; ptr = ptr->next) { if (strcmp_fn(ptr->name, name) == 0) break; @@ -520,8 +469,12 @@ add_additional_variables(char *name, bool insert) if (insert) { - /* add all those input variables that were given earlier - * note that we have to append here but have to keep the existing order */ + /* + * add all those input variables that were given earlier + * + * note that we have to append here but have to keep the existing + * order + */ for (p = (SAMEFUNC(ptr) ? ptr->argsinsert : ptr->argsinsert_oos); p; p = p->next) add_variable_to_tail(&argsinsert, p->variable, p->indicator); } @@ -534,11 +487,14 @@ add_additional_variables(char *name, bool insert) } static void -add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum, - char *type_dimension, char *type_index, int initializer, int array) +add_typedef(const char *name, const char *dimension, const char *length, + enum ECPGttype type_enum, + const char *type_dimension, const char *type_index, + int initializer, int array) { /* add entry to list */ - struct typedefs *ptr, *this; + struct typedefs *ptr, + *this; if ((type_enum == ECPGt_struct || type_enum == ECPGt_union) && @@ -554,22 +510,24 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum, /* re-definition is a bug */ mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name); } - adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true); + adjust_array(type_enum, &dimension, &length, + type_dimension, type_index, array, true); this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); /* initial definition */ this->next = types; - this->name = name; + this->name = mm_strdup(name); this->brace_level = braces_open; this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); + this->type->type_storage = NULL; this->type->type_enum = type_enum; this->type->type_str = mm_strdup(name); - this->type->type_dimension = dimension; /* dimension of array */ - this->type->type_index = length; /* length of string */ - this->type->type_sizeof = ECPGstruct_sizeof; + this->type->type_dimension = mm_strdup(dimension); /* dimension of array */ + this->type->type_index = mm_strdup(length); /* length of string */ + this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL; this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ? - ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; + ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; if (type_enum != ECPGt_varchar && type_enum != ECPGt_bytea && @@ -592,20 +550,35 @@ static bool check_declared_list(const char *name) { struct declared_list *ptr = NULL; - for (ptr = g_declared_list; ptr != NULL; ptr = ptr -> next) + + for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next) { if (!ptr->connection) continue; - if (strcmp(name, ptr -> name) == 0) + if (strcmp(name, ptr->name) == 0) { if (connection && strcmp(ptr->connection, connection) != 0) mmerror(PARSE_ERROR, ET_WARNING, "connection %s is overwritten with %s by DECLARE statement %s", connection, ptr->connection, name); - connection = mm_strdup(ptr -> connection); + update_connection(ptr->connection); return true; } } return false; } + +/* + * If newconn isn't NULL, update the global "connection" variable to that; + * otherwise do nothing. + */ +static void +update_connection(const char *newconn) +{ + if (newconn) + { + free(connection); + connection = mm_strdup(newconn); + } +} %} %expect 0 @@ -613,18 +586,18 @@ check_declared_list(const char *name) %locations %union { - double dval; - char *str; - int ival; - struct when action; - struct index index; - int tagname; - struct this_type type; - enum ECPGttype type_enum; - enum ECPGdtype dtype_enum; - struct fetch_desc descriptor; - struct su_symbol struct_union; - struct prep prep; - struct exec exec; - struct describe describe; + double dval; + char *str; + int ival; + struct when action; + struct index index; + int tagname; + struct this_type type; + enum ECPGttype type_enum; + enum ECPGdtype dtype_enum; + struct fetch_desc descriptor; + struct su_symbol struct_union; + struct prep prep; + struct exec exec; + struct describe describe; } diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer index b2aa44f36ddc3..6f94b832a037f 100644 --- a/src/interfaces/ecpg/preproc/ecpg.trailer +++ b/src/interfaces/ecpg/preproc/ecpg.trailer @@ -1,465 +1,547 @@ /* src/interfaces/ecpg/preproc/ecpg.trailer */ -statements: /*EMPTY*/ - | statements statement - ; +statements: /* EMPTY */ + | statements statement + { + /* Reclaim local storage used while processing statement */ + reclaim_local_storage(); + /* Clean up now-dangling location pointer */ + @$ = ""; + } + ; statement: ecpgstart at toplevel_stmt ';' - { - if (connection) - free(connection); - connection = NULL; - } - | ecpgstart toplevel_stmt ';' - { - if (connection) - free(connection); - connection = NULL; - } - | ecpgstart ECPGVarDeclaration - { - fprintf(base_yyout, "%s", $2); - free($2); - output_line_number(); - } - | ECPGDeclaration - | c_thing { fprintf(base_yyout, "%s", $1); free($1); } - | CPP_LINE { fprintf(base_yyout, "%s", $1); free($1); } - | '{' { braces_open++; fputs("{", base_yyout); } - | '}' + { + if (connection) + free(connection); + connection = NULL; + } + | ecpgstart toplevel_stmt ';' + { + if (connection) + free(connection); + connection = NULL; + } + | ecpgstart ECPGVarDeclaration + { + fprintf(base_yyout, "%s", @$); + output_line_number(); + } + | ECPGDeclaration + | c_thing + { + fprintf(base_yyout, "%s", @$); + } + | CPP_LINE + { + fprintf(base_yyout, "%s", @$); + } + | '{' + { + braces_open++; + fputs("{", base_yyout); + } + | '}' + { + if (braces_open > 0) { remove_typedefs(braces_open); - remove_variables(braces_open--); - if (braces_open == 0) + remove_variables(braces_open); + if (--braces_open == 0) { free(current_function); current_function = NULL; } - fputs("}", base_yyout); } - ; - -CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data - { - if (FoundInto == 1) - mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); - - $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table"), $4, mm_strdup("as"), $7, $8); - } - | CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data - { - if (FoundInto == 1) - mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); + fputs("}", base_yyout); + } + ; - $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table if not exists"), $7, mm_strdup("as"), $10, $11); - } - ; +CreateAsStmt: CREATE OptTemp TABLE create_as_target AS + { + FoundInto = 0; + } SelectStmt opt_with_data + { + if (FoundInto == 1) + mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); + } + | CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS + { + FoundInto = 0; + } SelectStmt opt_with_data + { + if (FoundInto == 1) + mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); + } + ; at: AT connection_object - { - connection = $2; - /* - * Do we have a variable as connection target? Remove the variable - * from the variable list or else it will be used twice. - */ - if (argsinsert != NULL) - argsinsert = NULL; - } - ; + { + if (connection) + free(connection); + connection = mm_strdup(@2); + + /* + * Do we have a variable as connection target? Remove the variable + * from the variable list or else it will be used twice. + */ + if (argsinsert != NULL) + argsinsert = NULL; + } + ; /* * the exec sql connect statement: connect to the given database */ ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user - { $$ = cat_str(5, $3, mm_strdup(","), $5, mm_strdup(","), $4); } - | SQL_CONNECT TO DEFAULT - { $$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\""); } - /* also allow ORACLE syntax */ - | SQL_CONNECT ora_user - { $$ = cat_str(3, mm_strdup("NULL,"), $2, mm_strdup(", NULL")); } - | DATABASE connection_target - { $$ = cat2_str($2, mm_strdup(", NULL, NULL, NULL")); } - ; + { + @$ = cat_str(5, @3, ",", @5, ",", @4); + } + | SQL_CONNECT TO DEFAULT + { + @$ = "NULL, NULL, NULL, \"DEFAULT\""; + } + /* also allow ORACLE syntax */ + | SQL_CONNECT ora_user + { + @$ = cat_str(3, "NULL,", @2, ", NULL"); + } + | DATABASE connection_target + { + @$ = cat2_str(@2, ", NULL, NULL, NULL"); + } + ; connection_target: opt_database_name opt_server opt_port - { - /* old style: dbname[@server][:port] */ - if (strlen($2) > 0 && *($2) != '@') - mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2); - - /* C strings need to be handled differently */ - if ($1[0] == '\"') - $$ = $1; - else - $$ = make3_str(mm_strdup("\""), make3_str($1, $2, $3), mm_strdup("\"")); - } - | db_prefix ':' server opt_port '/' opt_database_name opt_options - { - /* new style: :postgresql://server[:port][/dbname] */ - if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0) - mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported"); + { + /* old style: dbname[@server][:port] */ + if (strlen(@2) > 0 && *(@2) != '@') + mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", @2); + + /* C strings need to be handled differently */ + if (@1[0] == '\"') + @$ = @1; + else + @$ = make3_str("\"", make3_str(@1, @2, @3), "\""); + } + | db_prefix ':' server opt_port '/' opt_database_name opt_options + { + /* new style: :postgresql://server[:port][/dbname] */ + if (strncmp(@1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp(@1, "tcp:postgresql", strlen("tcp:postgresql")) != 0) + mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported"); - if (strncmp($3, "//", strlen("//")) != 0) - mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3); + if (strncmp(@3, "//", strlen("//")) != 0) + mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", @3); - if (strncmp($1, "unix", strlen("unix")) == 0 && - strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 && - strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0) - mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//")); + if (strncmp(@1, "unix", strlen("unix")) == 0 && + strncmp(@3 + strlen("//"), "localhost", strlen("localhost")) != 0 && + strncmp(@3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0) + mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", @3 + strlen("//")); - $$ = make3_str(make3_str(mm_strdup("\""), $1, mm_strdup(":")), $3, make3_str(make3_str($4, mm_strdup("/"), $6), $7, mm_strdup("\""))); - } - | char_variable - { - $$ = $1; - } - | ecpg_sconst - { - /* We can only process double quoted strings not single quotes ones, - * so we change the quotes. - * Note, that the rule for ecpg_sconst adds these single quotes. */ - $1[0] = '\"'; - $1[strlen($1)-1] = '\"'; - $$ = $1; - } - ; + @$ = make3_str(make3_str("\"", @1, ":"), @3, make3_str(make3_str(@4, "/", @6), @7, "\"")); + } + | char_variable + | ecpg_sconst + { + /* + * We can only process double quoted strings not single quoted ones, + * so we change the quotes. Note that the rule for ecpg_sconst adds + * these single quotes. + */ + char *str = loc_strdup(@1); + + str[0] = '\"'; + str[strlen(str) - 1] = '\"'; + @$ = str; + } + ; -opt_database_name: name { $$ = $1; } - | /*EMPTY*/ { $$ = EMPTY; } - ; +opt_database_name: name + | /* EMPTY */ + ; db_prefix: ecpg_ident cvariable - { - if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2); + { + if (strcmp(@2, "postgresql") != 0 && strcmp(@2, "postgres") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", @2); - if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", $1); + if (strcmp(@1, "tcp") != 0 && strcmp(@1, "unix") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", @1); - $$ = make3_str($1, mm_strdup(":"), $2); - } - ; + @$ = make3_str(@1, ":", @2); + } + ; server: Op server_name - { - if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1); + { + if (strcmp(@1, "@") != 0 && strcmp(@1, "//") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", @1); - $$ = make2_str($1, $2); - } - ; + @$ = make2_str(@1, @2); + } + ; -opt_server: server { $$ = $1; } - | /*EMPTY*/ { $$ = EMPTY; } - ; +opt_server: server + | /* EMPTY */ + ; -server_name: ColId { $$ = $1; } - | ColId '.' server_name { $$ = make3_str($1, mm_strdup("."), $3); } - | IP { $$ = make_name(); } - ; +server_name: ColId + | ColId '.' server_name + | IP + ; -opt_port: ':' Iconst { $$ = make2_str(mm_strdup(":"), $2); } - | /*EMPTY*/ { $$ = EMPTY; } - ; +opt_port: ':' Iconst + { + @$ = make2_str(":", @2); + } + | /* EMPTY */ + ; -opt_connection_name: AS connection_object { $$ = $2; } - | /*EMPTY*/ { $$ = mm_strdup("NULL"); } - ; +opt_connection_name: AS connection_object + { + @$ = @2; + } + | /* EMPTY */ + { + @$ = "NULL"; + } + ; -opt_user: USER ora_user { $$ = $2; } - | /*EMPTY*/ { $$ = mm_strdup("NULL, NULL"); } - ; +opt_user: USER ora_user + { + @$ = @2; + } + | /* EMPTY */ + { + @$ = "NULL, NULL"; + } + ; ora_user: user_name - { $$ = cat2_str($1, mm_strdup(", NULL")); } - | user_name '/' user_name - { $$ = cat_str(3, $1, mm_strdup(","), $3); } - | user_name SQL_IDENTIFIED BY user_name - { $$ = cat_str(3, $1, mm_strdup(","), $4); } - | user_name USING user_name - { $$ = cat_str(3, $1, mm_strdup(","), $3); } - ; + { + @$ = cat2_str(@1, ", NULL"); + } + | user_name '/' user_name + { + @$ = cat_str(3, @1, ",", @3); + } + | user_name SQL_IDENTIFIED BY user_name + { + @$ = cat_str(3, @1, ",", @4); + } + | user_name USING user_name + { + @$ = cat_str(3, @1, ",", @3); + } + ; user_name: RoleId - { - if ($1[0] == '\"') - $$ = $1; - else - $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); - } - | ecpg_sconst - { - if ($1[0] == '\"') - $$ = $1; - else - $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); - } - | civar - { - enum ECPGttype type = argsinsert->variable->type->type; + { + if (@1[0] == '\"') + @$ = @1; + else + @$ = make3_str("\"", @1, "\""); + } + | ecpg_sconst + { + if (@1[0] == '\"') + @$ = @1; + else + @$ = make3_str("\"", @1, "\""); + } + | civar + { + enum ECPGttype type = argsinsert->variable->type->type; - /* if array see what's inside */ - if (type == ECPGt_array) - type = argsinsert->variable->type->u.element->type; + /* if array see what's inside */ + if (type == ECPGt_array) + type = argsinsert->variable->type->u.element->type; - /* handle varchars */ - if (type == ECPGt_varchar) - $$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr")); - else - $$ = mm_strdup(argsinsert->variable->name); - } - ; + /* handle varchars */ + if (type == ECPGt_varchar) + @$ = make2_str(argsinsert->variable->name, ".arr"); + else + @$ = argsinsert->variable->name; + } + ; char_variable: cvariable + { + /* check if we have a string variable */ + struct variable *p = find_variable(@1); + enum ECPGttype type = p->type->type; + + /* If we have just one character this is not a string */ + if (atol(p->type->size) == 1) + mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); + else { - /* check if we have a string variable */ - struct variable *p = find_variable($1); - enum ECPGttype type = p->type->type; + /* if array see what's inside */ + if (type == ECPGt_array) + type = p->type->u.element->type; - /* If we have just one character this is not a string */ - if (atol(p->type->size) == 1) - mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); - else + switch (type) { - /* if array see what's inside */ - if (type == ECPGt_array) - type = p->type->u.element->type; - - switch (type) - { - case ECPGt_char: - case ECPGt_unsigned_char: - case ECPGt_string: - $$ = $1; - break; - case ECPGt_varchar: - $$ = make2_str($1, mm_strdup(".arr")); - break; - default: - mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); - $$ = $1; - break; - } + case ECPGt_char: + case ECPGt_unsigned_char: + case ECPGt_string: + @$ = @1; + break; + case ECPGt_varchar: + @$ = make2_str(@1, ".arr"); + break; + default: + mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); + @$ = @1; + break; } } - ; + } + ; opt_options: Op connect_options - { - if (strlen($1) == 0) - mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); + { + if (strlen(@1) == 0) + mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); - if (strcmp($1, "?") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1); + if (strcmp(@1, "?") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", @1); - $$ = make2_str(mm_strdup("?"), $2); - } - | /*EMPTY*/ { $$ = EMPTY; } - ; + @$ = make2_str("?", @2); + } + | /* EMPTY */ + ; -connect_options: ColId opt_opt_value - { - $$ = make2_str($1, $2); - } - | ColId opt_opt_value Op connect_options - { - if (strlen($3) == 0) - mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); +connect_options: ColId opt_opt_value + { + @$ = make2_str(@1, @2); + } + | ColId opt_opt_value Op connect_options + { + if (strlen(@3) == 0) + mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); - if (strcmp($3, "&") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3); + if (strcmp(@3, "&") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", @3); - $$ = cat_str(3, make2_str($1, $2), $3, $4); - } - ; - -opt_opt_value: /*EMPTY*/ - { $$ = EMPTY; } - | '=' Iconst - { $$ = make2_str(mm_strdup("="), $2); } - | '=' ecpg_ident - { $$ = make2_str(mm_strdup("="), $2); } - | '=' civar - { $$ = make2_str(mm_strdup("="), $2); } - ; + @$ = make3_str(make2_str(@1, @2), @3, @4); + } + ; + +opt_opt_value: /* EMPTY */ + | '=' Iconst + { + @$ = make2_str("=", @2); + } + | '=' ecpg_ident + { + @$ = make2_str("=", @2); + } + | '=' civar + { + @$ = make2_str("=", @2); + } + ; prepared_name: name - { - if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */ - $$ = $1; - else /* not quoted => convert to lowercase */ - { - size_t i; + { + size_t slen = strlen(@1); - for (i = 0; i< strlen($1); i++) - $1[i] = tolower((unsigned char) $1[i]); + if (@1[0] == '\"' && @1[slen - 1] == '\"') /* already quoted? */ + @$ = @1; + else /* not quoted => convert to lowercase */ + { + char *str = loc_alloc(slen + 3); - $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); - } + str[0] = '\"'; + for (size_t i = 0; i < slen; i++) + str[i + 1] = tolower((unsigned char) @1[i]); + str[slen + 1] = '\"'; + str[slen + 2] = '\0'; + @$ = str; } - | char_variable { $$ = $1; } - ; + } + | char_variable + ; /* * Declare Statement */ ECPGDeclareStmt: DECLARE prepared_name STATEMENT + { + struct declared_list *ptr; + + /* Check whether the declared name has been defined or not */ + for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next) { - struct declared_list *ptr = NULL; - /* Check whether the declared name has been defined or not */ - for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next) + if (strcmp(@2, ptr->name) == 0) { - if (strcmp($2, ptr->name) == 0) - { - /* re-definition is not allowed */ - mmerror(PARSE_ERROR, ET_ERROR, "name \"%s\" is already declared", ptr->name); - } + /* re-definition is not allowed */ + mmerror(PARSE_ERROR, ET_ERROR, "name \"%s\" is already declared", ptr->name); } + } - /* Add a new declared name into the g_declared_list */ - ptr = NULL; - ptr = (struct declared_list *)mm_alloc(sizeof(struct declared_list)); - if (ptr) - { - /* initial definition */ - ptr -> name = $2; - if (connection) - ptr -> connection = mm_strdup(connection); - else - ptr -> connection = NULL; - - ptr -> next = g_declared_list; - g_declared_list = ptr; - } + /* Add a new declared name into the g_declared_list */ + ptr = (struct declared_list *) mm_alloc(sizeof(struct declared_list)); + if (ptr) + { + /* initial definition */ + ptr->name = mm_strdup(@2); + if (connection) + ptr->connection = mm_strdup(connection); + else + ptr->connection = NULL; - $$ = cat_str(3 , mm_strdup("/* declare "), mm_strdup($2), mm_strdup(" as an SQL identifier */")); + ptr->next = g_declared_list; + g_declared_list = ptr; } -; + + @$ = cat_str(3, "/* declare ", @2, " as an SQL identifier */"); + } + ; /* * Declare a prepared cursor. The syntax is different from the standard * declare statement, so we create a new rule. */ -ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name - { - struct cursor *ptr, *this; - char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2); - int (* strcmp_fn)(const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp); - struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); - char *comment; - char *con; - - if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0) - mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode"); - - check_declared_list($7); - con = connection ? connection : "NULL"; - for (ptr = cur; ptr != NULL; ptr = ptr->next) +ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name + { + struct cursor *ptr, + *this; + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; + int (*strcmp_fn) (const char *, const char *) = ((@2[0] == ':' || @2[0] == '"') ? strcmp : pg_strcasecmp); + struct variable *thisquery = (struct variable *) mm_alloc(sizeof(struct variable)); + char *comment; + char *con; + + if (INFORMIX_MODE && pg_strcasecmp(@2, "database") == 0) + mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode"); + + check_declared_list(@7); + con = connection ? connection : "NULL"; + for (ptr = cur; ptr != NULL; ptr = ptr->next) + { + if (strcmp_fn(@2, ptr->name) == 0) { - if (strcmp_fn($2, ptr->name) == 0) - { - /* re-definition is a bug */ - if ($2[0] == ':') - mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2+1); - else - mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2); - } + /* re-definition is a bug */ + if (@2[0] == ':') + mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", @2 + 1); + else + mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", @2); } + } - this = (struct cursor *) mm_alloc(sizeof(struct cursor)); + this = (struct cursor *) mm_alloc(sizeof(struct cursor)); - /* initial definition */ - this->next = cur; - this->name = $2; - this->function = (current_function ? mm_strdup(current_function) : NULL); - this->connection = connection ? mm_strdup(connection) : NULL; - this->command = cat_str(6, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for $1")); - this->argsresult = NULL; - this->argsresult_oos = NULL; - - thisquery->type = &ecpg_query; - thisquery->brace_level = 0; - thisquery->next = NULL; - thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7)); - sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7); - - this->argsinsert = NULL; - this->argsinsert_oos = NULL; - if ($2[0] == ':') - { - struct variable *var = find_variable($2 + 1); - remove_variable_from_list(&argsinsert, var); - add_variable_to_head(&(this->argsinsert), var, &no_indicator); - } - add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); + /* initial definition */ + this->next = cur; + this->name = mm_strdup(@2); + this->function = (current_function ? mm_strdup(current_function) : NULL); + this->connection = connection ? mm_strdup(connection) : NULL; + this->opened = false; + this->command = mm_strdup(cat_str(6, "declare", cursor_marker, @3, "cursor", @5, "for $1")); + this->argsresult = NULL; + this->argsresult_oos = NULL; - cur = this; + thisquery->type = &ecpg_query; + thisquery->brace_level = 0; + thisquery->next = NULL; + thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen(@7)); + sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, @7); - comment = cat_str(3, mm_strdup("/*"), mm_strdup(this->command), mm_strdup("*/")); + this->argsinsert = NULL; + this->argsinsert_oos = NULL; + if (@2[0] == ':') + { + struct variable *var = find_variable(@2 + 1); - $$ = cat_str(2, adjust_outofscope_cursor_vars(this), - comment); + remove_variable_from_list(&argsinsert, var); + add_variable_to_head(&(this->argsinsert), var, &no_indicator); } - ; + add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); + + cur = this; + + comment = cat_str(3, "/*", this->command, "*/"); + + @$ = cat_str(2, adjust_outofscope_cursor_vars(this), + comment); + } + ; ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring - { - /* execute immediate means prepare the statement and - * immediately execute it */ - $$ = $3; - }; + { + /* + * execute immediate means prepare the statement and immediately + * execute it + */ + @$ = @3; + } + ; + /* * variable declaration outside exec sql declare block */ ECPGVarDeclaration: single_vt_declaration; -single_vt_declaration: type_declaration { $$ = $1; } - | var_declaration { $$ = $1; } - ; +single_vt_declaration: type_declaration + | var_declaration + ; -precision: NumericOnly { $$ = $1; }; +precision: NumericOnly + ; -opt_scale: ',' NumericOnly { $$ = $2; } - | /* EMPTY */ { $$ = EMPTY; } - ; +opt_scale: ',' NumericOnly + { + @$ = @2; + } + | /* EMPTY */ + ; -ecpg_interval: opt_interval { $$ = $1; } - | YEAR_P TO MINUTE_P { $$ = mm_strdup("year to minute"); } - | YEAR_P TO SECOND_P { $$ = mm_strdup("year to second"); } - | DAY_P TO DAY_P { $$ = mm_strdup("day to day"); } - | MONTH_P TO MONTH_P { $$ = mm_strdup("month to month"); } - ; +ecpg_interval: opt_interval + | YEAR_P TO MINUTE_P + | YEAR_P TO SECOND_P + | DAY_P TO DAY_P + | MONTH_P TO MONTH_P + ; /* * variable declaration inside exec sql declare block */ ECPGDeclaration: sql_startdeclare - { fputs("/* exec sql begin declare section */", base_yyout); } - var_type_declarations sql_enddeclare - { - fprintf(base_yyout, "%s/* exec sql end declare section */", $3); - free($3); - output_line_number(); - } - ; + { + fputs("/* exec sql begin declare section */", base_yyout); + } + var_type_declarations sql_enddeclare + { + fprintf(base_yyout, "%s/* exec sql end declare section */", @3); + output_line_number(); + } + ; -sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {}; +sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' + { + } + ; -sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {}; +sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' + { + } + ; -var_type_declarations: /*EMPTY*/ { $$ = EMPTY; } - | vt_declarations { $$ = $1; } - ; +var_type_declarations: /* EMPTY */ + | vt_declarations + ; -vt_declarations: single_vt_declaration { $$ = $1; } - | CPP_LINE { $$ = $1; } - | vt_declarations single_vt_declaration { $$ = cat2_str($1, $2); } - | vt_declarations CPP_LINE { $$ = cat2_str($1, $2); } - ; +vt_declarations: single_vt_declaration + | CPP_LINE + | vt_declarations single_vt_declaration + | vt_declarations CPP_LINE + ; -variable_declarations: var_declaration { $$ = $1; } - | variable_declarations var_declaration { $$ = cat2_str($1, $2); } - ; +variable_declarations: var_declaration + | variable_declarations var_declaration + ; type_declaration: S_TYPEDEF { @@ -467,750 +549,806 @@ type_declaration: S_TYPEDEF /* an initializer specified */ initializer = 0; } - var_type opt_pointer ECPGColLabel opt_array_bounds ';' + var_type opt_pointer ECPGColLabel opt_array_bounds ';' { - add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0); + add_typedef(@5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *@4 ? 1 : 0); - fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str); + fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *@4 ? "*" : "", @5, $6.str); output_line_number(); - $$ = mm_strdup(""); - }; + @$ = ""; + } + ; var_declaration: - storage_declaration var_type + storage_declaration var_type + { + actual_type[struct_level].type_storage = loc_strdup(@1); + actual_type[struct_level].type_enum = $2.type_enum; + actual_type[struct_level].type_str = $2.type_str; + actual_type[struct_level].type_dimension = $2.type_dimension; + actual_type[struct_level].type_index = $2.type_index; + actual_type[struct_level].type_sizeof = $2.type_sizeof; + + actual_startline[struct_level] = hashline_number(); + } + variable_list ';' + { + @$ = cat_str(5, actual_startline[struct_level], @1, $2.type_str, @4, ";\n"); + } + | var_type + { + actual_type[struct_level].type_storage = loc_strdup(""); + actual_type[struct_level].type_enum = $1.type_enum; + actual_type[struct_level].type_str = $1.type_str; + actual_type[struct_level].type_dimension = $1.type_dimension; + actual_type[struct_level].type_index = $1.type_index; + actual_type[struct_level].type_sizeof = $1.type_sizeof; + + actual_startline[struct_level] = hashline_number(); + } + variable_list ';' + { + @$ = cat_str(4, actual_startline[struct_level], $1.type_str, @3, ";\n"); + } + | struct_union_type_with_symbol ';' + ; + +opt_bit_field: ':' Iconst + | /* EMPTY */ + ; + +storage_declaration: storage_clause storage_modifier + | storage_clause + | storage_modifier + ; + +storage_clause: S_EXTERN + | S_STATIC + | S_REGISTER + | S_AUTO + ; + +storage_modifier: S_CONST + | S_VOLATILE + ; + +var_type: simple_type + { + $$.type_enum = $1; + $$.type_str = loc_strdup(ecpg_type_name($1)); + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | struct_union_type + { + $$.type_str = loc_strdup(@1); + $$.type_dimension = "-1"; + $$.type_index = "-1"; + + if (strncmp(@1, "struct", sizeof("struct") - 1) == 0) { - actual_type[struct_level].type_storage = $1; - actual_type[struct_level].type_enum = $2.type_enum; - actual_type[struct_level].type_str = $2.type_str; - actual_type[struct_level].type_dimension = $2.type_dimension; - actual_type[struct_level].type_index = $2.type_index; - actual_type[struct_level].type_sizeof = $2.type_sizeof; - - actual_startline[struct_level] = hashline_number(); + $$.type_enum = ECPGt_struct; + $$.type_sizeof = ECPGstruct_sizeof; } - variable_list ';' + else { - $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, mm_strdup(";\n")); + $$.type_enum = ECPGt_union; + $$.type_sizeof = NULL; } - | var_type + } + | enum_type + { + $$.type_str = loc_strdup(@1); + $$.type_enum = ECPGt_int; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | NUMERIC '(' precision opt_scale ')' + { + $$.type_enum = ECPGt_numeric; + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | DECIMAL_P '(' precision opt_scale ')' + { + $$.type_enum = ECPGt_decimal; + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | IDENT '(' precision opt_scale ')' + { + /* + * In C parsing mode, NUMERIC and DECIMAL are not keywords, so they + * will show up here as a plain identifier, and we need this duplicate + * code to recognize them. + */ + if (strcmp(@1, "numeric") == 0) { - actual_type[struct_level].type_storage = EMPTY; - actual_type[struct_level].type_enum = $1.type_enum; - actual_type[struct_level].type_str = $1.type_str; - actual_type[struct_level].type_dimension = $1.type_dimension; - actual_type[struct_level].type_index = $1.type_index; - actual_type[struct_level].type_sizeof = $1.type_sizeof; - - actual_startline[struct_level] = hashline_number(); + $$.type_enum = ECPGt_numeric; + $$.type_str = "numeric"; } - variable_list ';' + else if (strcmp(@1, "decimal") == 0) { - $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, mm_strdup(";\n")); + $$.type_enum = ECPGt_decimal; + $$.type_str = "decimal"; } - | struct_union_type_with_symbol ';' + else { - $$ = cat2_str($1, mm_strdup(";")); + mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and decimal have precision/scale argument"); + $$.type_enum = ECPGt_numeric; + $$.type_str = "numeric"; } - ; - -opt_bit_field: ':' Iconst { $$ =cat2_str(mm_strdup(":"), $2); } - | /* EMPTY */ { $$ = EMPTY; } - ; -storage_declaration: storage_clause storage_modifier - {$$ = cat2_str ($1, $2); } - | storage_clause {$$ = $1; } - | storage_modifier {$$ = $1; } - ; - -storage_clause : S_EXTERN { $$ = mm_strdup("extern"); } - | S_STATIC { $$ = mm_strdup("static"); } - | S_REGISTER { $$ = mm_strdup("register"); } - | S_AUTO { $$ = mm_strdup("auto"); } - ; - -storage_modifier : S_CONST { $$ = mm_strdup("const"); } - | S_VOLATILE { $$ = mm_strdup("volatile"); } - ; - -var_type: simple_type + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | VARCHAR + { + $$.type_enum = ECPGt_varchar; + $$.type_str = ""; /* "varchar"; */ + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | FLOAT_P + { + /* Note: DOUBLE is handled in simple_type */ + $$.type_enum = ECPGt_float; + $$.type_str = "float"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | NUMERIC + { + $$.type_enum = ECPGt_numeric; + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | DECIMAL_P + { + $$.type_enum = ECPGt_decimal; + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | TIMESTAMP + { + $$.type_enum = ECPGt_timestamp; + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | STRING_P + { + if (INFORMIX_MODE) { - $$.type_enum = $1; - $$.type_str = mm_strdup(ecpg_type_name($1)); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + /* In Informix mode, "string" is automatically a typedef */ + $$.type_enum = ECPGt_string; + $$.type_str = "char"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | struct_union_type + else { - $$.type_str = $1; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + /* Otherwise, legal only if user typedef'ed it */ + struct typedefs *this = get_typedef("string", false); - if (strncmp($1, "struct", sizeof("struct")-1) == 0) - { - $$.type_enum = ECPGt_struct; - $$.type_sizeof = ECPGstruct_sizeof; - } + $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? mm_strdup("") : mm_strdup(this->name); + $$.type_enum = this->type->type_enum; + $$.type_dimension = this->type->type_dimension; + $$.type_index = this->type->type_index; + if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) + $$.type_sizeof = this->type->type_sizeof; else - { - $$.type_enum = ECPGt_union; - $$.type_sizeof = NULL; - } - } - | enum_type - { - $$.type_str = $1; - $$.type_enum = ECPGt_int; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - | NUMERIC '(' precision opt_scale ')' - { - $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; + $$.type_sizeof = cat_str(3, "sizeof(", this->name, ")"); + + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } - | DECIMAL_P '(' precision opt_scale ')' + } + | INTERVAL ecpg_interval + { + $$.type_enum = ECPGt_interval; + $$.type_str = "interval"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + | IDENT ecpg_interval + { + /* + * In C parsing mode, the above SQL type names are not keywords, so + * they will show up here as a plain identifier, and we need this + * duplicate code to recognize them. + * + * Note that we also handle the type names bytea, date, and datetime + * here, but not above because those are not currently SQL keywords. + * If they ever become so, they must gain duplicate productions above. + */ + if (strlen(@2) != 0 && strcmp(@1, "datetime") != 0 && strcmp(@1, "interval") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "interval specification not allowed here"); + + if (strcmp(@1, "varchar") == 0) { - $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_enum = ECPGt_varchar; + $$.type_str = ""; /* "varchar"; */ + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | IDENT '(' precision opt_scale ')' + else if (strcmp(@1, "bytea") == 0) { - /* - * In C parsing mode, NUMERIC and DECIMAL are not keywords, so - * they will show up here as a plain identifier, and we need - * this duplicate code to recognize them. - */ - if (strcmp($1, "numeric") == 0) - { - $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - } - else if (strcmp($1, "decimal") == 0) - { - $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - } - else - { - mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and decimal have precision/scale argument"); - $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - } - - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_enum = ECPGt_bytea; + $$.type_str = ""; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | VARCHAR + else if (strcmp(@1, "float") == 0) { - $$.type_enum = ECPGt_varchar; - $$.type_str = EMPTY; /*mm_strdup("varchar");*/ - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_enum = ECPGt_float; + $$.type_str = "float"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | FLOAT_P + else if (strcmp(@1, "double") == 0) { - /* Note: DOUBLE is handled in simple_type */ - $$.type_enum = ECPGt_float; - $$.type_str = mm_strdup("float"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_enum = ECPGt_double; + $$.type_str = "double"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | NUMERIC + else if (strcmp(@1, "numeric") == 0) { $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | DECIMAL_P + else if (strcmp(@1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | TIMESTAMP + else if (strcmp(@1, "date") == 0) { - $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_enum = ECPGt_date; + $$.type_str = "date"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | STRING_P + else if (strcmp(@1, "timestamp") == 0) { - if (INFORMIX_MODE) - { - /* In Informix mode, "string" is automatically a typedef */ - $$.type_enum = ECPGt_string; - $$.type_str = mm_strdup("char"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else - { - /* Otherwise, legal only if user typedef'ed it */ - struct typedefs *this = get_typedef("string", false); - - $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name); - $$.type_enum = this->type->type_enum; - $$.type_dimension = this->type->type_dimension; - $$.type_index = this->type->type_index; - if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) - $$.type_sizeof = this->type->type_sizeof; - else - $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")")); - - struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); - } + $$.type_enum = ECPGt_timestamp; + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; } - | INTERVAL ecpg_interval + else if (strcmp(@1, "interval") == 0) { $$.type_enum = ECPGt_interval; - $$.type_str = mm_strdup("interval"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "interval"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } - | IDENT ecpg_interval - { - /* - * In C parsing mode, the above SQL type names are not keywords, - * so they will show up here as a plain identifier, and we need - * this duplicate code to recognize them. - * - * Note that we also handle the type names bytea, date, and - * datetime here, but not above because those are not currently - * SQL keywords. If they ever become so, they must gain duplicate - * productions above. - */ - if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0) - mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here"); - - if (strcmp($1, "varchar") == 0) - { - $$.type_enum = ECPGt_varchar; - $$.type_str = EMPTY; /*mm_strdup("varchar");*/ - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "bytea") == 0) - { - $$.type_enum = ECPGt_bytea; - $$.type_str = EMPTY; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "float") == 0) - { - $$.type_enum = ECPGt_float; - $$.type_str = mm_strdup("float"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "double") == 0) - { - $$.type_enum = ECPGt_double; - $$.type_str = mm_strdup("double"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "numeric") == 0) - { - $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "decimal") == 0) - { - $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "date") == 0) - { - $$.type_enum = ECPGt_date; - $$.type_str = mm_strdup("date"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "timestamp") == 0) - { - $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "interval") == 0) - { - $$.type_enum = ECPGt_interval; - $$.type_str = mm_strdup("interval"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if (strcmp($1, "datetime") == 0) - { - $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else if ((strcmp($1, "string") == 0) && INFORMIX_MODE) - { - $$.type_enum = ECPGt_string; - $$.type_str = mm_strdup("char"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = NULL; - } - else - { - /* Otherwise, it must be a user-defined typedef name */ - struct typedefs *this = get_typedef($1, false); - - $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name); - $$.type_enum = this->type->type_enum; - $$.type_dimension = this->type->type_dimension; - $$.type_index = this->type->type_index; - if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) - $$.type_sizeof = this->type->type_sizeof; - else - $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")")); - - struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); - } - } - | s_struct_union_symbol - { - /* this is for named structs/unions */ - char *name; - struct typedefs *this; - bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0); - - name = cat2_str($1.su, $1.symbol); - /* Do we have a forward definition? */ - if (!forward) - { - /* No */ - - this = get_typedef(name, false); - $$.type_str = mm_strdup(this->name); - $$.type_enum = this->type->type_enum; - $$.type_dimension = this->type->type_dimension; - $$.type_index = this->type->type_index; - $$.type_sizeof = this->type->type_sizeof; - struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); - free(name); - } - else - { - $$.type_str = name; - $$.type_enum = ECPGt_long; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = mm_strdup(""); - struct_member_list[struct_level] = NULL; - } - } - ; - -enum_type: ENUM_P symbol enum_definition - { $$ = cat_str(3, mm_strdup("enum"), $2, $3); } - | ENUM_P enum_definition - { $$ = cat2_str(mm_strdup("enum"), $2); } - | ENUM_P symbol - { $$ = cat2_str(mm_strdup("enum"), $2); } - ; - -enum_definition: '{' c_list '}' - { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); }; - -struct_union_type_with_symbol: s_struct_union_symbol + else if (strcmp(@1, "datetime") == 0) { - struct_member_list[struct_level++] = NULL; - if (struct_level >= STRUCT_DEPTH) - mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); - forward_name = mm_strdup($1.symbol); + $$.type_enum = ECPGt_timestamp; + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; + } + else if ((strcmp(@1, "string") == 0) && INFORMIX_MODE) + { + $$.type_enum = ECPGt_string; + $$.type_str = "char"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = NULL; } - '{' variable_declarations '}' + else { - struct typedefs *ptr, *this; - struct this_type su_type; + /* Otherwise, it must be a user-defined typedef name */ + struct typedefs *this = get_typedef(@1, false); - ECPGfree_struct_member(struct_member_list[struct_level]); - struct_member_list[struct_level] = NULL; - struct_level--; - if (strncmp($1.su, "struct", sizeof("struct")-1) == 0) - su_type.type_enum = ECPGt_struct; + $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? "" : this->name; + $$.type_enum = this->type->type_enum; + $$.type_dimension = this->type->type_dimension; + $$.type_index = this->type->type_index; + if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) + $$.type_sizeof = this->type->type_sizeof; else - su_type.type_enum = ECPGt_union; - su_type.type_str = cat2_str($1.su, $1.symbol); - free(forward_name); - forward_name = NULL; - - /* This is essentially a typedef but needs the keyword struct/union as well. - * So we create the typedef for each struct definition with symbol */ - for (ptr = types; ptr != NULL; ptr = ptr->next) - { - if (strcmp(su_type.type_str, ptr->name) == 0) - /* re-definition is a bug */ - mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", su_type.type_str); - } + $$.type_sizeof = cat_str(3, "sizeof(", this->name, ")"); - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); - - /* initial definition */ - this->next = types; - this->name = mm_strdup(su_type.type_str); - this->brace_level = braces_open; - this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); - this->type->type_enum = su_type.type_enum; - this->type->type_str = mm_strdup(su_type.type_str); - this->type->type_dimension = mm_strdup("-1"); /* dimension of array */ - this->type->type_index = mm_strdup("-1"); /* length of string */ - this->type->type_sizeof = ECPGstruct_sizeof; - this->struct_member_list = struct_member_list[struct_level]; - - types = this; - $$ = cat_str(4, su_type.type_str, mm_strdup("{"), $4, mm_strdup("}")); + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } - ; - -struct_union_type: struct_union_type_with_symbol { $$ = $1; } - | s_struct_union - { - struct_member_list[struct_level++] = NULL; - if (struct_level >= STRUCT_DEPTH) - mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); + } + | s_struct_union_symbol + { + /* this is for named structs/unions */ + char *name; + struct typedefs *this; + bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0); + + name = cat2_str($1.su, $1.symbol); + /* Do we have a forward definition? */ + if (!forward) + { + /* No */ + + this = get_typedef(name, false); + $$.type_str = this->name; + $$.type_enum = this->type->type_enum; + $$.type_dimension = this->type->type_dimension; + $$.type_index = this->type->type_index; + $$.type_sizeof = this->type->type_sizeof; + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } - '{' variable_declarations '}' + else { + $$.type_str = name; + $$.type_enum = ECPGt_long; + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = ""; ECPGfree_struct_member(struct_member_list[struct_level]); struct_member_list[struct_level] = NULL; - struct_level--; - $$ = cat_str(4, $1, mm_strdup("{"), $4, mm_strdup("}")); } - ; + } + ; + +enum_type: ENUM_P symbol enum_definition + | ENUM_P enum_definition + | ENUM_P symbol + ; + +enum_definition: '{' c_list '}' + ; + +struct_union_type_with_symbol: s_struct_union_symbol + { + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level++] = NULL; + if (struct_level >= STRUCT_DEPTH) + mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); + forward_name = mm_strdup($1.symbol); + } + '{' variable_declarations '}' + { + struct typedefs *ptr, + *this; + struct this_type su_type; + + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level] = NULL; + struct_level--; + if (strcmp($1.su, "struct") == 0) + su_type.type_enum = ECPGt_struct; + else + su_type.type_enum = ECPGt_union; + su_type.type_str = cat2_str($1.su, $1.symbol); + free(forward_name); + forward_name = NULL; + + /* + * This is essentially a typedef but needs the keyword struct/union as + * well. So we create the typedef for each struct definition with + * symbol + */ + for (ptr = types; ptr != NULL; ptr = ptr->next) + { + if (strcmp(su_type.type_str, ptr->name) == 0) + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", su_type.type_str); + } + + this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); + + /* initial definition */ + this->next = types; + this->name = mm_strdup(su_type.type_str); + this->brace_level = braces_open; + this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); + this->type->type_storage = NULL; + this->type->type_enum = su_type.type_enum; + this->type->type_str = mm_strdup(su_type.type_str); + this->type->type_dimension = mm_strdup("-1"); /* dimension of array */ + this->type->type_index = mm_strdup("-1"); /* length of string */ + this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL; + this->struct_member_list = ECPGstruct_member_dup(struct_member_list[struct_level]); + + types = this; + @$ = cat_str(4, su_type.type_str, "{", @4, "}"); + } + ; + +struct_union_type: struct_union_type_with_symbol + | s_struct_union + { + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level++] = NULL; + if (struct_level >= STRUCT_DEPTH) + mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); + } + '{' variable_declarations '}' + { + ECPGfree_struct_member(struct_member_list[struct_level]); + struct_member_list[struct_level] = NULL; + struct_level--; + @$ = cat_str(4, @1, "{", @4, "}"); + } + ; s_struct_union_symbol: SQL_STRUCT symbol - { - $$.su = mm_strdup("struct"); - $$.symbol = $2; - ECPGstruct_sizeof = cat_str(3, mm_strdup("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), mm_strdup(")")); - } - | UNION symbol - { - $$.su = mm_strdup("union"); - $$.symbol = $2; - } - ; + { + $$.su = "struct"; + $$.symbol = @2; + free(ECPGstruct_sizeof); + ECPGstruct_sizeof = mm_strdup(cat_str(3, "sizeof(", + cat2_str($$.su, $$.symbol), + ")")); + } + | UNION symbol + { + $$.su = "union"; + $$.symbol = @2; + } + ; s_struct_union: SQL_STRUCT - { - ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to distinguish from simple types. */ - $$ = mm_strdup("struct"); - } - | UNION - { - $$ = mm_strdup("union"); - } - ; - -simple_type: unsigned_type { $$=$1; } - | opt_signed signed_type { $$=$2; } - ; - -unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } - | SQL_UNSIGNED SQL_SHORT INT_P { $$ = ECPGt_unsigned_short; } - | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; } - | SQL_UNSIGNED INT_P { $$ = ECPGt_unsigned_int; } - | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; } - | SQL_UNSIGNED SQL_LONG INT_P { $$ = ECPGt_unsigned_long; } - | SQL_UNSIGNED SQL_LONG SQL_LONG { $$ = ECPGt_unsigned_long_long; } - | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P { $$ = ECPGt_unsigned_long_long; } - | SQL_UNSIGNED CHAR_P { $$ = ECPGt_unsigned_char; } - ; - -signed_type: SQL_SHORT { $$ = ECPGt_short; } - | SQL_SHORT INT_P { $$ = ECPGt_short; } - | INT_P { $$ = ECPGt_int; } - | SQL_LONG { $$ = ECPGt_long; } - | SQL_LONG INT_P { $$ = ECPGt_long; } - | SQL_LONG SQL_LONG { $$ = ECPGt_long_long; } - | SQL_LONG SQL_LONG INT_P { $$ = ECPGt_long_long; } - | SQL_BOOL { $$ = ECPGt_bool; } - | CHAR_P { $$ = ECPGt_char; } - | DOUBLE_P { $$ = ECPGt_double; } - ; + { + free(ECPGstruct_sizeof); + ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to + * distinguish from simple types. */ + @$ = "struct"; + } + | UNION + { + @$ = "union"; + } + ; + +simple_type: unsigned_type + | opt_signed signed_type { $$ = $2; } + ; + +unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } + | SQL_UNSIGNED SQL_SHORT INT_P { $$ = ECPGt_unsigned_short; } + | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; } + | SQL_UNSIGNED INT_P { $$ = ECPGt_unsigned_int; } + | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; } + | SQL_UNSIGNED SQL_LONG INT_P { $$ = ECPGt_unsigned_long; } + | SQL_UNSIGNED SQL_LONG SQL_LONG { $$ = ECPGt_unsigned_long_long; } + | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P { $$ = ECPGt_unsigned_long_long; } + | SQL_UNSIGNED CHAR_P { $$ = ECPGt_unsigned_char; } + ; + +signed_type: SQL_SHORT { $$ = ECPGt_short; } + | SQL_SHORT INT_P { $$ = ECPGt_short; } + | INT_P { $$ = ECPGt_int; } + | SQL_LONG { $$ = ECPGt_long; } + | SQL_LONG INT_P { $$ = ECPGt_long; } + | SQL_LONG SQL_LONG { $$ = ECPGt_long_long; } + | SQL_LONG SQL_LONG INT_P { $$ = ECPGt_long_long; } + | SQL_BOOL { $$ = ECPGt_bool; } + | CHAR_P { $$ = ECPGt_char; } + | DOUBLE_P { $$ = ECPGt_double; } + ; opt_signed: SQL_SIGNED - | /* EMPTY */ - ; + | /* EMPTY */ + ; variable_list: variable - { $$ = $1; } - | variable_list ',' variable - { - if (actual_type[struct_level].type_enum == ECPGt_varchar || actual_type[struct_level].type_enum == ECPGt_bytea) - $$ = cat_str(4, $1, mm_strdup(";"), mm_strdup(actual_type[struct_level].type_storage), $3); - else - $$ = cat_str(3, $1, mm_strdup(","), $3); - } - ; + | variable_list ',' variable + { + if (actual_type[struct_level].type_enum == ECPGt_varchar || actual_type[struct_level].type_enum == ECPGt_bytea) + @$ = cat_str(4, @1, ";", actual_type[struct_level].type_storage, @3); + else + @$ = cat_str(3, @1, ",", @3); + } + ; variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer - { - struct ECPGtype * type; - char *dimension = $3.index1; /* dimension of array */ - char *length = $3.index2; /* length of string */ - char *dim_str; - char *vcn; - int *varlen_type_counter; - char *struct_name; - - adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false); - switch (actual_type[struct_level].type_enum) - { - case ECPGt_struct: - case ECPGt_union: - if (atoi(dimension) < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof); - else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension); + { + struct ECPGtype *type; + const char *dimension = $3.index1; /* dimension of array */ + const char *length = $3.index2; /* length of string */ + char *dim_str; + char vcn[32]; + int *varlen_type_counter; + char *struct_name; + + adjust_array(actual_type[struct_level].type_enum, + &dimension, &length, + actual_type[struct_level].type_dimension, + actual_type[struct_level].type_index, + strlen(@1), false); + switch (actual_type[struct_level].type_enum) + { + case ECPGt_struct: + case ECPGt_union: + if (atoi(dimension) < 0) + type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof); + else + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension); - $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); - break; + @$ = cat_str(5, @1, @2, $3.str, @4, @5); + break; - case ECPGt_varchar: - case ECPGt_bytea: - if (actual_type[struct_level].type_enum == ECPGt_varchar) - { - varlen_type_counter = &varchar_counter; - struct_name = " struct varchar_"; - } - else - { - varlen_type_counter = &bytea_counter; - struct_name = " struct bytea_"; - } - if (atoi(dimension) < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter); - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter), dimension); + case ECPGt_varchar: + case ECPGt_bytea: + if (actual_type[struct_level].type_enum == ECPGt_varchar) + { + varlen_type_counter = &varchar_counter; + struct_name = " struct varchar_"; + } + else + { + varlen_type_counter = &bytea_counter; + struct_name = " struct bytea_"; + } + if (atoi(dimension) < 0) + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter); + else + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter), dimension); - if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1) - dim_str=mm_strdup(""); - else - dim_str=cat_str(3, mm_strdup("["), mm_strdup(dimension), mm_strdup("]")); - /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */ - if (atoi(length) < 0 || strcmp(length, "0") == 0) - mmerror(PARSE_ERROR, ET_ERROR, "pointers to varchar are not implemented"); - - /* make sure varchar struct name is unique by adding a unique counter to its definition */ - vcn = (char *) mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - sprintf(vcn, "%d", *varlen_type_counter); - if (strcmp(dimension, "0") == 0) - $$ = cat_str(7, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5); - else - $$ = cat_str(8, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5); - (*varlen_type_counter)++; - break; + if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1) + dim_str = ""; + else + dim_str = cat_str(3, "[", dimension, "]"); + + /* + * cannot check for atoi <= 0 because a defined constant will + * yield 0 here as well + */ + if (atoi(length) < 0 || strcmp(length, "0") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "pointers to varchar are not implemented"); + + /* + * make sure varchar struct name is unique by adding a unique + * counter to its definition + */ + snprintf(vcn, sizeof(vcn), "%d", *varlen_type_counter); + if (strcmp(dimension, "0") == 0) + @$ = cat_str(7, make2_str(struct_name, vcn), " { int len; char arr[", length, "]; } *", @2, @4, @5); + else + @$ = cat_str(8, make2_str(struct_name, vcn), " { int len; char arr[", length, "]; } ", @2, dim_str, @4, @5); + (*varlen_type_counter)++; + break; + + case ECPGt_char: + case ECPGt_unsigned_char: + case ECPGt_string: + if (atoi(dimension) == -1) + { + int i = strlen(@5); - case ECPGt_char: - case ECPGt_unsigned_char: - case ECPGt_string: - if (atoi(dimension) == -1) + if (atoi(length) == -1 && i > 0) /* char [] = + * "string" */ { - int i = strlen($5); - - if (atoi(length) == -1 && i > 0) /* char [] = "string" */ - { - /* if we have an initializer but no string size set, let's use the initializer's length */ - free(length); - length = mm_alloc(i+sizeof("sizeof()")); - sprintf(length, "sizeof(%s)", $5+2); - } - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0); + /* + * if we have an initializer but no string size set, + * let's use the initializer's length + */ + char *buf = loc_alloc(32); + + snprintf(buf, 32, "sizeof(%s)", @5 + 2); + length = buf; } - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension); - - $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); - break; - - default: - if (atoi(dimension) < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0); - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0), dimension); + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0); + } + else + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension); - $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); - break; - } + @$ = cat_str(5, @1, @2, $3.str, @4, @5); + break; - if (struct_level == 0) - new_variable($2, type, braces_open); - else - ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1])); + default: + if (atoi(dimension) < 0) + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, "1", 0); + else + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, "1", 0), dimension); - free($2); + @$ = cat_str(5, @1, @2, $3.str, @4, @5); + break; } - ; -opt_initializer: /*EMPTY*/ - { $$ = EMPTY; } - | '=' c_term - { - initializer = 1; - $$ = cat2_str(mm_strdup("="), $2); - } - ; + if (struct_level == 0) + new_variable(@2, type, braces_open); + else + ECPGmake_struct_member(@2, type, &(struct_member_list[struct_level - 1])); + } + ; + +opt_initializer: /* EMPTY */ + | '=' c_term + { + initializer = 1; + } + ; -opt_pointer: /*EMPTY*/ { $$ = EMPTY; } - | '*' { $$ = mm_strdup("*"); } - | '*' '*' { $$ = mm_strdup("**"); } - ; +opt_pointer: /* EMPTY */ + | '*' + | '*' '*' + { + @$ = "**"; + } + ; /* * We try to simulate the correct DECLARE syntax here so we get dynamic SQL */ ECPGDeclare: DECLARE STATEMENT ecpg_ident - { - /* this is only supported for compatibility */ - $$ = cat_str(3, mm_strdup("/* declare statement"), $3, mm_strdup("*/")); - } - ; + { + /* this is only supported for compatibility */ + @$ = cat_str(3, "/* declare statement", @3, "*/"); + } + ; /* * the exec sql disconnect statement: disconnect from the given database */ -ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } - ; +ECPGDisconnect: SQL_DISCONNECT dis_name + { + @$ = @2; + } + ; -dis_name: connection_object { $$ = $1; } - | CURRENT_P { $$ = mm_strdup("\"CURRENT\""); } - | ALL { $$ = mm_strdup("\"ALL\""); } - | /* EMPTY */ { $$ = mm_strdup("\"CURRENT\""); } - ; +dis_name: connection_object + | CURRENT_P + { + @$ = "\"CURRENT\""; + } + | ALL + { + @$ = "\"ALL\""; + } + | /* EMPTY */ + { + @$ = "\"CURRENT\""; + } + ; -connection_object: name { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } - | DEFAULT { $$ = mm_strdup("\"DEFAULT\""); } - | char_variable { $$ = $1; } - ; +connection_object: name + { + @$ = make3_str("\"", @1, "\""); + } + | DEFAULT + { + @$ = "\"DEFAULT\""; + } + | char_variable + ; execstring: char_variable - { $$ = $1; } - | CSTRING - { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } - ; + | CSTRING + { + @$ = make3_str("\"", @1, "\""); + } + ; /* * the exec sql free command to deallocate a previously * prepared statement */ -ECPGFree: SQL_FREE cursor_name { $$ = $2; } - | SQL_FREE ALL { $$ = mm_strdup("all"); } - ; +ECPGFree: SQL_FREE cursor_name + { + @$ = @2; + } + | SQL_FREE ALL + { + @$ = "all"; + } + ; /* * open is an open cursor, at the moment this has to be removed */ ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using - { - if ($2[0] == ':') - remove_variable_from_list(&argsinsert, find_variable($2 + 1)); - $$ = $2; - } - ; + { + if (@2[0] == ':') + remove_variable_from_list(&argsinsert, find_variable(@2 + 1)); + @$ = @2; + } + ; -opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; } - | ecpg_using { $$ = $1; } - ; +opt_ecpg_using: /* EMPTY */ + | ecpg_using + ; -ecpg_using: USING using_list { $$ = EMPTY; } - | using_descriptor { $$ = $1; } - ; +ecpg_using: USING using_list + { + @$ = ""; + } + | using_descriptor + ; using_descriptor: USING SQL_P SQL_DESCRIPTOR quoted_ident_stringvar - { - add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator); - $$ = EMPTY; - } - | USING SQL_DESCRIPTOR name - { - add_variable_to_head(&argsinsert, sqlda_variable($3), &no_indicator); - $$ = EMPTY; - } - ; + { + add_variable_to_head(&argsinsert, descriptor_variable(@4, 0), &no_indicator); + @$ = ""; + } + | USING SQL_DESCRIPTOR name + { + add_variable_to_head(&argsinsert, sqlda_variable(@3), &no_indicator); + @$ = ""; + } + ; into_descriptor: INTO SQL_P SQL_DESCRIPTOR quoted_ident_stringvar - { - add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator); - $$ = EMPTY; - } - | INTO SQL_DESCRIPTOR name - { - add_variable_to_head(&argsresult, sqlda_variable($3), &no_indicator); - $$ = EMPTY; - } - ; + { + add_variable_to_head(&argsresult, descriptor_variable(@4, 1), &no_indicator); + @$ = ""; + } + | INTO SQL_DESCRIPTOR name + { + add_variable_to_head(&argsresult, sqlda_variable(@3), &no_indicator); + @$ = ""; + } + ; into_sqlda: INTO name - { - add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator); - $$ = EMPTY; - } - ; + { + add_variable_to_head(&argsresult, sqlda_variable(@2), &no_indicator); + @$ = ""; + } + ; -using_list: UsingValue | UsingValue ',' using_list; +using_list: UsingValue | UsingValue ',' using_list + ; UsingValue: UsingConst - { - char *length = mm_alloc(32); + { + char length[32]; - sprintf(length, "%zu", strlen($1)); - add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); - } - | civar { $$ = EMPTY; } - | civarind { $$ = EMPTY; } - ; - -UsingConst: Iconst { $$ = $1; } - | '+' Iconst { $$ = cat_str(2, mm_strdup("+"), $2); } - | '-' Iconst { $$ = cat_str(2, mm_strdup("-"), $2); } - | ecpg_fconst { $$ = $1; } - | '+' ecpg_fconst { $$ = cat_str(2, mm_strdup("+"), $2); } - | '-' ecpg_fconst { $$ = cat_str(2, mm_strdup("-"), $2); } - | ecpg_sconst { $$ = $1; } - | ecpg_bconst { $$ = $1; } - | ecpg_xconst { $$ = $1; } - ; + snprintf(length, sizeof(length), "%zu", strlen(@1)); + add_variable_to_head(&argsinsert, new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); + } + | civar + { + @$ = ""; + } + | civarind + { + @$ = ""; + } + ; + +UsingConst: Iconst + | '+' Iconst + | '-' Iconst + | ecpg_fconst + | '+' ecpg_fconst + | '-' ecpg_fconst + | ecpg_sconst + | ecpg_bconst + | ecpg_xconst + ; /* * We accept DESCRIBE [OUTPUT] but do nothing with DESCRIBE INPUT so far. @@ -1218,37 +1356,38 @@ UsingConst: Iconst { $$ = $1; } ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor { $$.input = 1; - $$.stmt_name = $3; + $$.stmt_name = @3; } | SQL_DESCRIBE opt_output prepared_name using_descriptor { struct variable *var; + var = argsinsert->variable; remove_variable_from_list(&argsinsert, var); add_variable_to_head(&argsresult, var, &no_indicator); $$.input = 0; - $$.stmt_name = $3; + $$.stmt_name = @3; } | SQL_DESCRIBE opt_output prepared_name into_descriptor { $$.input = 0; - $$.stmt_name = $3; + $$.stmt_name = @3; } | SQL_DESCRIBE INPUT_P prepared_name into_sqlda { $$.input = 1; - $$.stmt_name = $3; + $$.stmt_name = @3; } | SQL_DESCRIBE opt_output prepared_name into_sqlda { $$.input = 0; - $$.stmt_name = $3; + $$.stmt_name = @3; } ; -opt_output: SQL_OUTPUT { $$ = mm_strdup("output"); } - | /* EMPTY */ { $$ = EMPTY; } +opt_output: SQL_OUTPUT + | /* EMPTY */ ; /* @@ -1261,425 +1400,451 @@ opt_output: SQL_OUTPUT { $$ = mm_strdup("output"); } * allocate a descriptor */ ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar - { - add_descriptor($3,connection); - $$ = $3; - } - ; + { + add_descriptor(@3, connection); + @$ = @3; + } + ; /* * deallocate a descriptor */ -ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar - { - drop_descriptor($3,connection); - $$ = $3; - } - ; +ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar + { + drop_descriptor(@3, connection); + @$ = @3; + } + ; /* * manipulate a descriptor header */ ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems - { $$ = $3; } - ; + { + @$ = @3; + } + ; ECPGGetDescHeaderItems: ECPGGetDescHeaderItem - | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem - ; + | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem + ; ECPGGetDescHeaderItem: cvariable '=' desc_header_item - { push_assignment($1, $3); } - ; - + { + push_assignment(@1, $3); + } + ; ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems - { $$ = $3; } - ; + { + @$ = @3; + } + ; ECPGSetDescHeaderItems: ECPGSetDescHeaderItem - | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem - ; + | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem + ; ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar - { - push_assignment($3, $1); - } - ; + { + push_assignment(@3, $1); + } + ; IntConstVar: Iconst - { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + { + char length[32]; - sprintf(length, "%zu", strlen($1)); - new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); - $$ = $1; - } - | cvariable - { - $$ = $1; - } - ; + snprintf(length, sizeof(length), "%zu", strlen(@1)); + new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + } + | cvariable + ; -desc_header_item: SQL_COUNT { $$ = ECPGd_count; } - ; +desc_header_item: SQL_COUNT + { + $$ = ECPGd_count; + } + ; /* * manipulate a descriptor */ -ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems - { $$.str = $5; $$.name = $3; } - ; +ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems + { + $$.str = @5; + $$.name = @3; + } + ; ECPGGetDescItems: ECPGGetDescItem - | ECPGGetDescItems ',' ECPGGetDescItem - ; - -ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); }; - - -ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems - { $$.str = $5; $$.name = $3; } - ; - -ECPGSetDescItems: ECPGSetDescItem - | ECPGSetDescItems ',' ECPGSetDescItem - ; - -ECPGSetDescItem: descriptor_item '=' AllConstVar - { - push_assignment($3, $1); - } - ; + | ECPGGetDescItems ',' ECPGGetDescItem + ; -AllConstVar: ecpg_fconst - { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); +ECPGGetDescItem: cvariable '=' descriptor_item + { + push_assignment(@1, $3); + } + ; - sprintf(length, "%zu", strlen($1)); - new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); - $$ = $1; - } +ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems + { + $$.str = @5; + $$.name = @3; + } + ; - | IntConstVar - { - $$ = $1; - } +ECPGSetDescItems: ECPGSetDescItem + | ECPGSetDescItems ',' ECPGSetDescItem + ; - | '-' ecpg_fconst - { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = cat2_str(mm_strdup("-"), $2); +ECPGSetDescItem: descriptor_item '=' AllConstVar + { + push_assignment(@3, $1); + } + ; - sprintf(length, "%zu", strlen(var)); - new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); - $$ = var; - } +AllConstVar: ecpg_fconst + { + char length[32]; - | '-' Iconst - { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = cat2_str(mm_strdup("-"), $2); + snprintf(length, sizeof(length), "%zu", strlen(@1)); + new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + } + | IntConstVar + | '-' ecpg_fconst + { + char length[32]; + char *var = cat2_str("-", @2); - sprintf(length, "%zu", strlen(var)); - new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); - $$ = var; - } + snprintf(length, sizeof(length), "%zu", strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + @$ = var; + } + | '-' Iconst + { + char length[32]; + char *var = cat2_str("-", @2); - | ecpg_sconst - { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = $1 + 1; + snprintf(length, sizeof(length), "%zu", strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + @$ = var; + } + | ecpg_sconst + { + char length[32]; + char *var; + + /* Strip single quotes from ecpg_sconst */ + var = loc_strdup(@1 + 1); + var[strlen(var) - 1] = '\0'; + snprintf(length, sizeof(length), "%zu", strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + @$ = var; + } + ; - var[strlen(var) - 1] = '\0'; - sprintf(length, "%zu", strlen(var)); - new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); - $$ = var; - } - ; - -descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } - | DATA_P { $$ = ECPGd_data; } - | SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; } - | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; } - | SQL_INDICATOR { $$ = ECPGd_indicator; } - | SQL_KEY_MEMBER { $$ = ECPGd_key_member; } - | SQL_LENGTH { $$ = ECPGd_length; } - | NAME_P { $$ = ECPGd_name; } - | SQL_NULLABLE { $$ = ECPGd_nullable; } - | SQL_OCTET_LENGTH { $$ = ECPGd_octet; } - | PRECISION { $$ = ECPGd_precision; } - | SQL_RETURNED_LENGTH { $$ = ECPGd_length; } - | SQL_RETURNED_OCTET_LENGTH { $$ = ECPGd_ret_octet; } - | SQL_SCALE { $$ = ECPGd_scale; } - | TYPE_P { $$ = ECPGd_type; } - ; +descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } + | DATA_P { $$ = ECPGd_data; } + | SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; } + | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; } + | SQL_INDICATOR { $$ = ECPGd_indicator; } + | SQL_KEY_MEMBER { $$ = ECPGd_key_member; } + | SQL_LENGTH { $$ = ECPGd_length; } + | NAME_P { $$ = ECPGd_name; } + | SQL_NULLABLE { $$ = ECPGd_nullable; } + | SQL_OCTET_LENGTH { $$ = ECPGd_octet; } + | PRECISION { $$ = ECPGd_precision; } + | SQL_RETURNED_LENGTH { $$ = ECPGd_length; } + | SQL_RETURNED_OCTET_LENGTH { $$ = ECPGd_ret_octet; } + | SQL_SCALE { $$ = ECPGd_scale; } + | TYPE_P { $$ = ECPGd_type; } + ; /* * set/reset the automatic transaction mode, this needs a different handling * as the other set commands */ -ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off { $$ = $4; } - | SET SQL_AUTOCOMMIT TO on_off { $$ = $4; } - ; +ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off + { + @$ = @4; + } + | SET SQL_AUTOCOMMIT TO on_off + { + @$ = @4; + } + ; -on_off: ON { $$ = mm_strdup("on"); } - | OFF { $$ = mm_strdup("off"); } - ; +on_off: ON + | OFF + ; /* * set the actual connection, this needs a different handling as the other * set commands */ -ECPGSetConnection: SET CONNECTION TO connection_object { $$ = $4; } - | SET CONNECTION '=' connection_object { $$ = $4; } - | SET CONNECTION connection_object { $$ = $3; } - ; +ECPGSetConnection: SET CONNECTION TO connection_object + { + @$ = @4; + } + | SET CONNECTION '=' connection_object + { + @$ = @4; + } + | SET CONNECTION connection_object + { + @$ = @3; + } + ; /* * define a new type for embedded SQL */ ECPGTypedef: TYPE_P - { - /* reset this variable so we see if there was */ - /* an initializer specified */ - initializer = 0; - } - ECPGColLabel IS var_type opt_array_bounds opt_reference - { - add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0); + { + /* reset this variable so we see if there was */ + /* an initializer specified */ + initializer = 0; + } + ECPGColLabel IS var_type opt_array_bounds opt_reference + { + add_typedef(@3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *@7 ? 1 : 0); - if (auto_create_c == false) - $$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/")); - else - $$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *$7?mm_strdup("*"):mm_strdup(""), mm_strdup($3), mm_strdup($6.str), mm_strdup(";")); - } - ; + if (auto_create_c == false) + @$ = cat_str(7, "/* exec sql type", @3, "is", $5.type_str, $6.str, @7, "*/"); + else + @$ = cat_str(6, "typedef ", $5.type_str, *@7 ? "*" : "", @3, $6.str, ";"); + } + ; -opt_reference: SQL_REFERENCE { $$ = mm_strdup("reference"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; +opt_reference: SQL_REFERENCE + | /* EMPTY */ + ; /* * define the type of one variable for embedded SQL */ ECPGVar: SQL_VAR + { + /* reset this variable so we see if there was */ + /* an initializer specified */ + initializer = 0; + } + ColLabel IS var_type opt_array_bounds opt_reference + { + struct variable *p = find_variable(@3); + const char *dimension = $6.index1; + const char *length = $6.index2; + struct ECPGtype *type; + + if (($5.type_enum == ECPGt_struct || + $5.type_enum == ECPGt_union) && + initializer == 1) + mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command"); + else { - /* reset this variable so we see if there was */ - /* an initializer specified */ - initializer = 0; - } - ColLabel IS var_type opt_array_bounds opt_reference - { - struct variable *p = find_variable($3); - char *dimension = $6.index1; - char *length = $6.index2; - struct ECPGtype * type; - - if (($5.type_enum == ECPGt_struct || - $5.type_enum == ECPGt_union) && - initializer == 1) - mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command"); - else - { - adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); + adjust_array($5.type_enum, &dimension, &length, + $5.type_dimension, $5.type_index, *@7 ? 1 : 0, false); - switch ($5.type_enum) - { + switch ($5.type_enum) + { case ECPGt_struct: case ECPGt_union: - if (atoi(dimension) < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof); - else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension); - break; + if (atoi(dimension) < 0) + type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof); + else + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension); + break; case ECPGt_varchar: case ECPGt_bytea: - if (atoi(dimension) == -1) - type = ECPGmake_simple_type($5.type_enum, length, 0); - else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); - break; + if (atoi(dimension) == -1) + type = ECPGmake_simple_type($5.type_enum, length, 0); + else + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); + break; case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_string: - if (atoi(dimension) == -1) - type = ECPGmake_simple_type($5.type_enum, length, 0); - else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); - break; + if (atoi(dimension) == -1) + type = ECPGmake_simple_type($5.type_enum, length, 0); + else + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); + break; default: - if (atoi(length) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported"); - - if (atoi(dimension) < 0) - type = ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0); - else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0), dimension); - break; - } + if (atoi(length) >= 0) + mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported"); - ECPGfree_type(p->type); - p->type = type; + if (atoi(dimension) < 0) + type = ECPGmake_simple_type($5.type_enum, "1", 0); + else + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, "1", 0), dimension); + break; } - $$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/")); + ECPGfree_type(p->type); + p->type = type; } - ; + + @$ = cat_str(7, "/* exec sql var", @3, "is", $5.type_str, $6.str, @7, "*/"); + } + ; /* * whenever statement: decide what to do in case of error/no data found * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION */ ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action - { - when_error.code = $3.code; - when_error.command = $3.command; - $$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */")); - } - | SQL_WHENEVER NOT SQL_FOUND action - { - when_nf.code = $4.code; - when_nf.command = $4.command; - $$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */")); - } - | SQL_WHENEVER SQL_SQLWARNING action - { - when_warn.code = $3.code; - when_warn.command = $3.command; - $$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */")); - } - ; + { + when_error.code = $3.code; + free(when_error.command); + when_error.command = $3.command ? mm_strdup($3.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever sqlerror ", $3.str, "; */"); + } + | SQL_WHENEVER NOT SQL_FOUND action + { + when_nf.code = $4.code; + free(when_nf.command); + when_nf.command = $4.command ? mm_strdup($4.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever not found ", $4.str, "; */"); + } + | SQL_WHENEVER SQL_SQLWARNING action + { + when_warn.code = $3.code; + free(when_warn.command); + when_warn.command = $3.command ? mm_strdup($3.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever sql_warning ", $3.str, "; */"); + } + ; -action : CONTINUE_P - { - $$.code = W_NOTHING; - $$.command = NULL; - $$.str = mm_strdup("continue"); - } - | SQL_SQLPRINT - { - $$.code = W_SQLPRINT; - $$.command = NULL; - $$.str = mm_strdup("sqlprint"); - } - | SQL_STOP - { - $$.code = W_STOP; - $$.command = NULL; - $$.str = mm_strdup("stop"); - } - | SQL_GOTO name - { - $$.code = W_GOTO; - $$.command = mm_strdup($2); - $$.str = cat2_str(mm_strdup("goto "), $2); - } - | SQL_GO TO name - { - $$.code = W_GOTO; - $$.command = mm_strdup($3); - $$.str = cat2_str(mm_strdup("goto "), $3); - } - | DO name '(' c_args ')' - { - $$.code = W_DO; - $$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")")); - $$.str = cat2_str(mm_strdup("do"), mm_strdup($$.command)); - } - | DO SQL_BREAK - { - $$.code = W_BREAK; - $$.command = NULL; - $$.str = mm_strdup("break"); - } - | DO CONTINUE_P - { - $$.code = W_CONTINUE; - $$.command = NULL; - $$.str = mm_strdup("continue"); - } - | CALL name '(' c_args ')' - { - $$.code = W_DO; - $$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")")); - $$.str = cat2_str(mm_strdup("call"), mm_strdup($$.command)); - } - | CALL name - { - $$.code = W_DO; - $$.command = cat2_str($2, mm_strdup("()")); - $$.str = cat2_str(mm_strdup("call"), mm_strdup($$.command)); - } - ; +action: CONTINUE_P + { + $$.code = W_NOTHING; + $$.command = NULL; + $$.str = "continue"; + } + | SQL_SQLPRINT + { + $$.code = W_SQLPRINT; + $$.command = NULL; + $$.str = "sqlprint"; + } + | SQL_STOP + { + $$.code = W_STOP; + $$.command = NULL; + $$.str = "stop"; + } + | SQL_GOTO name + { + $$.code = W_GOTO; + $$.command = loc_strdup(@2); + $$.str = cat2_str("goto ", @2); + } + | SQL_GO TO name + { + $$.code = W_GOTO; + $$.command = loc_strdup(@3); + $$.str = cat2_str("goto ", @3); + } + | DO name '(' c_args ')' + { + $$.code = W_DO; + $$.command = cat_str(4, @2, "(", @4, ")"); + $$.str = cat2_str("do", $$.command); + } + | DO SQL_BREAK + { + $$.code = W_BREAK; + $$.command = NULL; + $$.str = "break"; + } + | DO CONTINUE_P + { + $$.code = W_CONTINUE; + $$.command = NULL; + $$.str = "continue"; + } + | CALL name '(' c_args ')' + { + $$.code = W_DO; + $$.command = cat_str(4, @2, "(", @4, ")"); + $$.str = cat2_str("call", $$.command); + } + | CALL name + { + $$.code = W_DO; + $$.command = cat2_str(@2, "()"); + $$.str = cat2_str("call", $$.command); + } + ; /* some other stuff for ecpg */ /* additional unreserved keywords */ -ECPGKeywords: ECPGKeywords_vanames { $$ = $1; } - | ECPGKeywords_rest { $$ = $1; } - ; - -ECPGKeywords_vanames: SQL_BREAK { $$ = mm_strdup("break"); } - | SQL_CARDINALITY { $$ = mm_strdup("cardinality"); } - | SQL_COUNT { $$ = mm_strdup("count"); } - | SQL_DATETIME_INTERVAL_CODE { $$ = mm_strdup("datetime_interval_code"); } - | SQL_DATETIME_INTERVAL_PRECISION { $$ = mm_strdup("datetime_interval_precision"); } - | SQL_FOUND { $$ = mm_strdup("found"); } - | SQL_GO { $$ = mm_strdup("go"); } - | SQL_GOTO { $$ = mm_strdup("goto"); } - | SQL_IDENTIFIED { $$ = mm_strdup("identified"); } - | SQL_INDICATOR { $$ = mm_strdup("indicator"); } - | SQL_KEY_MEMBER { $$ = mm_strdup("key_member"); } - | SQL_LENGTH { $$ = mm_strdup("length"); } - | SQL_NULLABLE { $$ = mm_strdup("nullable"); } - | SQL_OCTET_LENGTH { $$ = mm_strdup("octet_length"); } - | SQL_RETURNED_LENGTH { $$ = mm_strdup("returned_length"); } - | SQL_RETURNED_OCTET_LENGTH { $$ = mm_strdup("returned_octet_length"); } - | SQL_SCALE { $$ = mm_strdup("scale"); } - | SQL_SECTION { $$ = mm_strdup("section"); } - | SQL_SQLERROR { $$ = mm_strdup("sqlerror"); } - | SQL_SQLPRINT { $$ = mm_strdup("sqlprint"); } - | SQL_SQLWARNING { $$ = mm_strdup("sqlwarning"); } - | SQL_STOP { $$ = mm_strdup("stop"); } - ; - -ECPGKeywords_rest: SQL_CONNECT { $$ = mm_strdup("connect"); } - | SQL_DESCRIBE { $$ = mm_strdup("describe"); } - | SQL_DISCONNECT { $$ = mm_strdup("disconnect"); } - | SQL_OPEN { $$ = mm_strdup("open"); } - | SQL_VAR { $$ = mm_strdup("var"); } - | SQL_WHENEVER { $$ = mm_strdup("whenever"); } - ; +ECPGKeywords: ECPGKeywords_vanames + | ECPGKeywords_rest + ; + +ECPGKeywords_vanames: SQL_BREAK + | SQL_CARDINALITY + | SQL_COUNT + | SQL_DATETIME_INTERVAL_CODE + | SQL_DATETIME_INTERVAL_PRECISION + | SQL_FOUND + | SQL_GO + | SQL_GOTO + | SQL_IDENTIFIED + | SQL_INDICATOR + | SQL_KEY_MEMBER + | SQL_LENGTH + | SQL_NULLABLE + | SQL_OCTET_LENGTH + | SQL_RETURNED_LENGTH + | SQL_RETURNED_OCTET_LENGTH + | SQL_SCALE + | SQL_SECTION + | SQL_SQLERROR + | SQL_SQLPRINT + | SQL_SQLWARNING + | SQL_STOP + ; + +ECPGKeywords_rest: SQL_CONNECT + | SQL_DESCRIBE + | SQL_DISCONNECT + | SQL_OPEN + | SQL_VAR + | SQL_WHENEVER + ; /* additional keywords that can be SQL type names (but not ECPGColLabels) */ -ECPGTypeName: SQL_BOOL { $$ = mm_strdup("bool"); } - | SQL_LONG { $$ = mm_strdup("long"); } - | SQL_OUTPUT { $$ = mm_strdup("output"); } - | SQL_SHORT { $$ = mm_strdup("short"); } - | SQL_STRUCT { $$ = mm_strdup("struct"); } - | SQL_SIGNED { $$ = mm_strdup("signed"); } - | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); } - ; - -symbol: ColLabel { $$ = $1; } - ; - -ECPGColId: ecpg_ident { $$ = $1; } - | unreserved_keyword { $$ = $1; } - | col_name_keyword { $$ = $1; } - | ECPGunreserved_interval { $$ = $1; } - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - | CHAR_P { $$ = mm_strdup("char"); } - | VALUES { $$ = mm_strdup("values"); } - ; +ECPGTypeName: SQL_BOOL + | SQL_LONG + | SQL_OUTPUT + | SQL_SHORT + | SQL_STRUCT + | SQL_SIGNED + | SQL_UNSIGNED + ; + +symbol: ColLabel + ; + +ECPGColId: ecpg_ident + | unreserved_keyword + | col_name_keyword + | ECPGunreserved_interval + | ECPGKeywords + | ECPGCKeywords + | CHAR_P + | VALUES + ; /* * Name classification hierarchy. @@ -1691,59 +1856,59 @@ ECPGColId: ecpg_ident { $$ = $1; } /* Column identifier --- names that can be column, table, etc names. */ -ColId: ecpg_ident { $$ = $1; } - | all_unreserved_keyword { $$ = $1; } - | col_name_keyword { $$ = $1; } - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - | CHAR_P { $$ = mm_strdup("char"); } - | VALUES { $$ = mm_strdup("values"); } - ; +ColId: ecpg_ident + | all_unreserved_keyword + | col_name_keyword + | ECPGKeywords + | ECPGCKeywords + | CHAR_P + | VALUES + ; /* Type/function identifier --- names that can be type or function names. */ -type_function_name: ecpg_ident { $$ = $1; } - | all_unreserved_keyword { $$ = $1; } - | type_func_name_keyword { $$ = $1; } - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - | ECPGTypeName { $$ = $1; } - ; +type_function_name: ecpg_ident + | all_unreserved_keyword + | type_func_name_keyword + | ECPGKeywords + | ECPGCKeywords + | ECPGTypeName + ; /* Column label --- allowed labels in "AS" clauses. * This presently includes *all* Postgres keywords. */ -ColLabel: ECPGColLabel { $$ = $1; } - | ECPGTypeName { $$ = $1; } - | CHAR_P { $$ = mm_strdup("char"); } - | CURRENT_P { $$ = mm_strdup("current"); } - | INPUT_P { $$ = mm_strdup("input"); } - | INT_P { $$ = mm_strdup("int"); } - | TO { $$ = mm_strdup("to"); } - | UNION { $$ = mm_strdup("union"); } - | VALUES { $$ = mm_strdup("values"); } - | ECPGCKeywords { $$ = $1; } - | ECPGunreserved_interval { $$ = $1; } - ; - -ECPGColLabel: ecpg_ident { $$ = $1; } - | unreserved_keyword { $$ = $1; } - | col_name_keyword { $$ = $1; } - | type_func_name_keyword { $$ = $1; } - | reserved_keyword { $$ = $1; } - | ECPGKeywords_vanames { $$ = $1; } - | ECPGKeywords_rest { $$ = $1; } - | CONNECTION { $$ = mm_strdup("connection"); } - ; - -ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); } - | S_CONST { $$ = mm_strdup("const"); } - | S_EXTERN { $$ = mm_strdup("extern"); } - | S_REGISTER { $$ = mm_strdup("register"); } - | S_STATIC { $$ = mm_strdup("static"); } - | S_TYPEDEF { $$ = mm_strdup("typedef"); } - | S_VOLATILE { $$ = mm_strdup("volatile"); } - ; +ColLabel: ECPGColLabel + | ECPGTypeName + | CHAR_P + | CURRENT_P + | INPUT_P + | INT_P + | TO + | UNION + | VALUES + | ECPGCKeywords + | ECPGunreserved_interval + ; + +ECPGColLabel: ecpg_ident + | unreserved_keyword + | col_name_keyword + | type_func_name_keyword + | reserved_keyword + | ECPGKeywords_vanames + | ECPGKeywords_rest + | CONNECTION + ; + +ECPGCKeywords: S_AUTO + | S_CONST + | S_EXTERN + | S_REGISTER + | S_STATIC + | S_TYPEDEF + | S_VOLATILE + ; /* "Unreserved" keywords --- available for use as any kind of name. */ @@ -1759,251 +1924,307 @@ ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); } * * The mentioned exclusions are done by $replace_line settings in parse.pl. */ -all_unreserved_keyword: unreserved_keyword { $$ = $1; } - | ECPGunreserved_interval { $$ = $1; } - | CONNECTION { $$ = mm_strdup("connection"); } - ; - -ECPGunreserved_interval: DAY_P { $$ = mm_strdup("day"); } - | HOUR_P { $$ = mm_strdup("hour"); } - | MINUTE_P { $$ = mm_strdup("minute"); } - | MONTH_P { $$ = mm_strdup("month"); } - | SECOND_P { $$ = mm_strdup("second"); } - | YEAR_P { $$ = mm_strdup("year"); } - ; - - -into_list : coutputvariable | into_list ',' coutputvariable - ; - -ecpgstart: SQL_START { - reset_variables(); - pacounter = 1; - } - ; +all_unreserved_keyword: unreserved_keyword + | ECPGunreserved_interval + | CONNECTION + ; + +ECPGunreserved_interval: DAY_P + | HOUR_P + | MINUTE_P + | MONTH_P + | SECOND_P + | YEAR_P + ; + +into_list: coutputvariable | into_list ',' coutputvariable + ; -c_args: /*EMPTY*/ { $$ = EMPTY; } - | c_list { $$ = $1; } - ; +ecpgstart: SQL_START + { + reset_variables(); + pacounter = 1; + @$ = ""; + } + ; + +c_args: /* EMPTY */ + | c_list + ; coutputvariable: cvariable indicator - { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); } - | cvariable - { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); } - ; + { + add_variable_to_head(&argsresult, find_variable(@1), find_variable(@2)); + } + | cvariable + { + add_variable_to_head(&argsresult, find_variable(@1), &no_indicator); + } + ; civarind: cvariable indicator - { - if (find_variable($2)->type->type == ECPGt_array) - mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); + { + if (find_variable(@2)->type->type == ECPGt_array) + mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); - add_variable_to_head(&argsinsert, find_variable($1), find_variable($2)); - $$ = create_questionmarks($1, false); - } - ; + add_variable_to_head(&argsinsert, find_variable(@1), find_variable(@2)); + @$ = create_questionmarks(@1, false); + } + ; char_civar: char_variable - { - char *ptr = strstr($1, ".arr"); + { + char *ptr = strstr(@1, ".arr"); - if (ptr) /* varchar, we need the struct name here, not the struct element */ - *ptr = '\0'; - add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); - $$ = $1; - } - ; + if (ptr) /* varchar, we need the struct name here, not + * the struct element */ + *ptr = '\0'; + add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator); + } + ; civar: cvariable - { - add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); - $$ = create_questionmarks($1, false); - } - ; + { + add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator); + @$ = create_questionmarks(@1, false); + } + ; + +indicator: cvariable + { + check_indicator((find_variable(@1))->type); + } + | SQL_INDICATOR cvariable + { + check_indicator((find_variable(@2))->type); + @$ = @2; + } + | SQL_INDICATOR name + { + check_indicator((find_variable(@2))->type); + @$ = @2; + } + ; -indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; } - | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } - | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } - ; +cvariable: CVARIABLE + { + /* + * As long as multidimensional arrays are not implemented we have to + * check for those here + */ + const char *ptr = @1; + int brace_open = 0, + brace = false; -cvariable: CVARIABLE + for (; *ptr; ptr++) { - /* As long as multidimensional arrays are not implemented we have to check for those here */ - char *ptr = $1; - int brace_open=0, brace = false; - - for (; *ptr; ptr++) + switch (*ptr) { - switch (*ptr) - { - case '[': - if (brace) - mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported"); - brace_open++; - break; - case ']': - brace_open--; - if (brace_open == 0) - brace = true; - break; - case '\t': - case ' ': - break; - default: - if (brace_open == 0) - brace = false; - break; - } + case '[': + if (brace) + mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported"); + brace_open++; + break; + case ']': + brace_open--; + if (brace_open == 0) + brace = true; + break; + case '\t': + case ' ': + break; + default: + if (brace_open == 0) + brace = false; + break; } - $$ = $1; } - ; + } + ; -ecpg_param: PARAM { $$ = make_name(); } ; +ecpg_param: PARAM + ; -ecpg_bconst: BCONST { $$ = $1; } ; +ecpg_bconst: BCONST + ; -ecpg_fconst: FCONST { $$ = make_name(); } ; +ecpg_fconst: FCONST + ; -ecpg_sconst: SCONST { $$ = $1; } ; +ecpg_sconst: SCONST + ; -ecpg_xconst: XCONST { $$ = $1; } ; +ecpg_xconst: XCONST + ; -ecpg_ident: IDENT { $$ = $1; } - | CSTRING { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } - ; +ecpg_ident: IDENT + | CSTRING + { + @$ = make3_str("\"", @1, "\""); + } + ; quoted_ident_stringvar: name - { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } - | char_variable - { $$ = make3_str(mm_strdup("("), $1, mm_strdup(")")); } - ; + { + @$ = make3_str("\"", @1, "\""); + } + | char_variable + { + @$ = make3_str("(", @1, ")"); + } + ; /* * C stuff */ -c_stuff_item: c_anything { $$ = $1; } - | '(' ')' { $$ = mm_strdup("()"); } - | '(' c_stuff ')' - { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); } - ; - -c_stuff: c_stuff_item { $$ = $1; } - | c_stuff c_stuff_item - { $$ = cat2_str($1, $2); } - ; - -c_list: c_term { $$ = $1; } - | c_list ',' c_term { $$ = cat_str(3, $1, mm_strdup(","), $3); } - ; - -c_term: c_stuff { $$ = $1; } - | '{' c_list '}' { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); } - ; - -c_thing: c_anything { $$ = $1; } - | '(' { $$ = mm_strdup("("); } - | ')' { $$ = mm_strdup(")"); } - | ',' { $$ = mm_strdup(","); } - | ';' { $$ = mm_strdup(";"); } - ; - -c_anything: ecpg_ident { $$ = $1; } - | Iconst { $$ = $1; } - | ecpg_fconst { $$ = $1; } - | ecpg_sconst { $$ = $1; } - | '*' { $$ = mm_strdup("*"); } - | '+' { $$ = mm_strdup("+"); } - | '-' { $$ = mm_strdup("-"); } - | '/' { $$ = mm_strdup("/"); } - | '%' { $$ = mm_strdup("%"); } - | NULL_P { $$ = mm_strdup("NULL"); } - | S_ADD { $$ = mm_strdup("+="); } - | S_AND { $$ = mm_strdup("&&"); } - | S_ANYTHING { $$ = make_name(); } - | S_AUTO { $$ = mm_strdup("auto"); } - | S_CONST { $$ = mm_strdup("const"); } - | S_DEC { $$ = mm_strdup("--"); } - | S_DIV { $$ = mm_strdup("/="); } - | S_DOTPOINT { $$ = mm_strdup(".*"); } - | S_EQUAL { $$ = mm_strdup("=="); } - | S_EXTERN { $$ = mm_strdup("extern"); } - | S_INC { $$ = mm_strdup("++"); } - | S_LSHIFT { $$ = mm_strdup("<<"); } - | S_MEMBER { $$ = mm_strdup("->"); } - | S_MEMPOINT { $$ = mm_strdup("->*"); } - | S_MOD { $$ = mm_strdup("%="); } - | S_MUL { $$ = mm_strdup("*="); } - | S_NEQUAL { $$ = mm_strdup("!="); } - | S_OR { $$ = mm_strdup("||"); } - | S_REGISTER { $$ = mm_strdup("register"); } - | S_RSHIFT { $$ = mm_strdup(">>"); } - | S_STATIC { $$ = mm_strdup("static"); } - | S_SUB { $$ = mm_strdup("-="); } - | S_TYPEDEF { $$ = mm_strdup("typedef"); } - | S_VOLATILE { $$ = mm_strdup("volatile"); } - | SQL_BOOL { $$ = mm_strdup("bool"); } - | ENUM_P { $$ = mm_strdup("enum"); } - | HOUR_P { $$ = mm_strdup("hour"); } - | INT_P { $$ = mm_strdup("int"); } - | SQL_LONG { $$ = mm_strdup("long"); } - | MINUTE_P { $$ = mm_strdup("minute"); } - | MONTH_P { $$ = mm_strdup("month"); } - | SECOND_P { $$ = mm_strdup("second"); } - | SQL_SHORT { $$ = mm_strdup("short"); } - | SQL_SIGNED { $$ = mm_strdup("signed"); } - | SQL_STRUCT { $$ = mm_strdup("struct"); } - | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); } - | YEAR_P { $$ = mm_strdup("year"); } - | CHAR_P { $$ = mm_strdup("char"); } - | FLOAT_P { $$ = mm_strdup("float"); } - | TO { $$ = mm_strdup("to"); } - | UNION { $$ = mm_strdup("union"); } - | VARCHAR { $$ = mm_strdup("varchar"); } - | '[' { $$ = mm_strdup("["); } - | ']' { $$ = mm_strdup("]"); } - | '=' { $$ = mm_strdup("="); } - | ':' { $$ = mm_strdup(":"); } - ; - -DeallocateStmt: DEALLOCATE prepared_name { check_declared_list($2); $$ = $2; } - | DEALLOCATE PREPARE prepared_name { check_declared_list($3); $$ = $3; } - | DEALLOCATE ALL { $$ = mm_strdup("all"); } - | DEALLOCATE PREPARE ALL { $$ = mm_strdup("all"); } - ; - -Iresult: Iconst { $$ = $1; } - | '(' Iresult ')' { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); } - | Iresult '+' Iresult { $$ = cat_str(3, $1, mm_strdup("+"), $3); } - | Iresult '-' Iresult { $$ = cat_str(3, $1, mm_strdup("-"), $3); } - | Iresult '*' Iresult { $$ = cat_str(3, $1, mm_strdup("*"), $3); } - | Iresult '/' Iresult { $$ = cat_str(3, $1, mm_strdup("/"), $3); } - | Iresult '%' Iresult { $$ = cat_str(3, $1, mm_strdup("%"), $3); } - | ecpg_sconst { $$ = $1; } - | ColId { $$ = $1; } - | ColId '(' var_type ')' { if (pg_strcasecmp($1, "sizeof") != 0) - mmerror(PARSE_ERROR, ET_ERROR, "operator not allowed in variable definition"); - else - $$ = cat_str(4, $1, mm_strdup("("), $3.type_str, mm_strdup(")")); - } - ; - -execute_rest: /* EMPTY */ { $$ = EMPTY; } - | ecpg_using opt_ecpg_into { $$ = EMPTY; } - | ecpg_into ecpg_using { $$ = EMPTY; } - | ecpg_into { $$ = EMPTY; } - ; - -ecpg_into: INTO into_list { $$ = EMPTY; } - | into_descriptor { $$ = $1; } - ; - -opt_ecpg_into: /* EMPTY */ { $$ = EMPTY; } - | ecpg_into { $$ = $1; } - ; - -ecpg_fetch_into: ecpg_into { $$ = $1; } +c_stuff_item: c_anything + | '(' ')' + { + @$ = "()"; + } + | '(' c_stuff ')' + ; + +c_stuff: c_stuff_item + | c_stuff c_stuff_item + ; + +c_list: c_term + | c_list ',' c_term + ; + +c_term: c_stuff + | '{' c_list '}' + ; + +c_thing: c_anything + | '(' + | ')' + | ',' + | ';' + ; + +/* + * Note: NULL_P is treated specially to force it to be output in upper case, + * since it's likely meant as a reference to the standard C macro NULL. + */ +c_anything: ecpg_ident + | Iconst + | ecpg_fconst + | ecpg_sconst + | '*' + | '+' + | '-' + | '/' + | '%' + | NULL_P { @$ = "NULL"; } + | S_ADD + | S_AND + | S_ANYTHING + | S_AUTO + | S_CONST + | S_DEC + | S_DIV + | S_DOTPOINT + | S_EQUAL + | S_EXTERN + | S_INC + | S_LSHIFT + | S_MEMBER + | S_MEMPOINT + | S_MOD + | S_MUL + | S_NEQUAL + | S_OR + | S_REGISTER + | S_RSHIFT + | S_STATIC + | S_SUB + | S_TYPEDEF + | S_VOLATILE + | SQL_BOOL + | ENUM_P + | HOUR_P + | INT_P + | SQL_LONG + | MINUTE_P + | MONTH_P + | SECOND_P + | SQL_SHORT + | SQL_SIGNED + | SQL_STRUCT + | SQL_UNSIGNED + | YEAR_P + | CHAR_P + | FLOAT_P + | TO + | UNION + | VARCHAR + | '[' + | ']' + | '=' + | ':' + ; + +DeallocateStmt: DEALLOCATE prepared_name + { + check_declared_list(@2); + @$ = @2; + } + | DEALLOCATE PREPARE prepared_name + { + check_declared_list(@3); + @$ = @3; + } + | DEALLOCATE ALL + { + @$ = "all"; + } + | DEALLOCATE PREPARE ALL + { + @$ = "all"; + } + ; + +Iresult: Iconst + | '(' Iresult ')' + | Iresult '+' Iresult + | Iresult '-' Iresult + | Iresult '*' Iresult + | Iresult '/' Iresult + | Iresult '%' Iresult + | ecpg_sconst + | ColId + | ColId '(' var_type ')' + { + if (pg_strcasecmp(@1, "sizeof") != 0) + mmerror(PARSE_ERROR, ET_ERROR, "operator not allowed in variable definition"); + else + @$ = cat_str(4, @1, "(", $3.type_str, ")"); + } + ; + +execute_rest: /* EMPTY */ + | ecpg_using opt_ecpg_into + | ecpg_into ecpg_using + | ecpg_into + ; + +ecpg_into: INTO into_list + { + /* always suppress this from the constructed string */ + @$ = ""; + } + | into_descriptor + ; + +opt_ecpg_into: /* EMPTY */ + | ecpg_into + ; + +ecpg_fetch_into: ecpg_into | using_descriptor { struct variable *var; @@ -2011,24 +2232,28 @@ ecpg_fetch_into: ecpg_into { $$ = $1; } var = argsinsert->variable; remove_variable_from_list(&argsinsert, var); add_variable_to_head(&argsresult, var, &no_indicator); - $$ = $1; } ; -opt_ecpg_fetch_into: /* EMPTY */ { $$ = EMPTY; } - | ecpg_fetch_into { $$ = $1; } +opt_ecpg_fetch_into: /* EMPTY */ + | ecpg_fetch_into ; %% -void base_yyerror(const char *error) +void +base_yyerror(const char *error) { /* translator: %s is typically the translation of "syntax error" */ mmerror(PARSE_ERROR, ET_ERROR, "%s at or near \"%s\"", _(error), token_start ? token_start : base_yytext); } -void parser_init(void) +void +parser_init(void) { - /* This function is empty. It only exists for compatibility with the backend parser right now. */ + /* + * This function is empty. It only exists for compatibility with the + * backend parser right now. + */ } diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type index 4fe80a5a4bea2..2929f358ff4ae 100644 --- a/src/interfaces/ecpg/preproc/ecpg.type +++ b/src/interfaces/ecpg/preproc/ecpg.type @@ -1,131 +1,4 @@ /* src/interfaces/ecpg/preproc/ecpg.type */ -%type ECPGAllocateDescr -%type ECPGCKeywords -%type ECPGColId -%type ECPGColLabel -%type ECPGConnect -%type ECPGCursorStmt -%type ECPGDeallocateDescr -%type ECPGDeclaration -%type ECPGDeclare -%type ECPGDeclareStmt -%type ECPGDisconnect -%type ECPGExecuteImmediateStmt -%type ECPGFree -%type ECPGGetDescHeaderItem -%type ECPGGetDescItem -%type ECPGGetDescriptorHeader -%type ECPGKeywords -%type ECPGKeywords_rest -%type ECPGKeywords_vanames -%type ECPGOpen -%type ECPGSetAutocommit -%type ECPGSetConnection -%type ECPGSetDescHeaderItem -%type ECPGSetDescItem -%type ECPGSetDescriptorHeader -%type ECPGTypeName -%type ECPGTypedef -%type ECPGVar -%type ECPGVarDeclaration -%type ECPGWhenever -%type ECPGunreserved_interval -%type UsingConst -%type UsingValue -%type all_unreserved_keyword -%type c_anything -%type c_args -%type c_list -%type c_stuff -%type c_stuff_item -%type c_term -%type c_thing -%type char_variable -%type char_civar -%type civar -%type civarind -%type ColId -%type ColLabel -%type connect_options -%type connection_object -%type connection_target -%type coutputvariable -%type cvariable -%type db_prefix -%type CreateAsStmt -%type DeallocateStmt -%type dis_name -%type ecpg_bconst -%type ecpg_fconst -%type ecpg_ident -%type ecpg_interval -%type ecpg_into -%type ecpg_fetch_into -%type ecpg_param -%type ecpg_sconst -%type ecpg_using -%type ecpg_xconst -%type enum_definition -%type enum_type -%type execstring -%type execute_rest -%type indicator -%type into_descriptor -%type into_sqlda -%type Iresult -%type on_off -%type opt_bit_field -%type opt_connection_name -%type opt_database_name -%type opt_ecpg_into -%type opt_ecpg_fetch_into -%type opt_ecpg_using -%type opt_initializer -%type opt_options -%type opt_output -%type opt_pointer -%type opt_port -%type opt_reference -%type opt_scale -%type opt_server -%type opt_user -%type opt_opt_value -%type ora_user -%type precision -%type prepared_name -%type quoted_ident_stringvar -%type s_struct_union -%type server -%type server_name -%type single_vt_declaration -%type storage_clause -%type storage_declaration -%type storage_modifier -%type struct_union_type -%type struct_union_type_with_symbol -%type symbol -%type type_declaration -%type type_function_name -%type user_name -%type using_descriptor -%type var_declaration -%type var_type_declarations -%type variable -%type variable_declarations -%type variable_list -%type vt_declarations - -%type Op -%type IntConstVar -%type AllConstVar -%type CSTRING -%type CPP_LINE -%type CVARIABLE -%type BCONST -%type SCONST -%type XCONST -%type IDENT - %type s_struct_union_symbol %type ECPGGetDescriptor diff --git a/src/interfaces/ecpg/preproc/ecpg_kwlist.h b/src/interfaces/ecpg/preproc/ecpg_kwlist.h index 7244fbab1b33a..3ab4655386e5b 100644 --- a/src/interfaces/ecpg/preproc/ecpg_kwlist.h +++ b/src/interfaces/ecpg/preproc/ecpg_kwlist.h @@ -7,7 +7,7 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/ecpg/preproc/ecpg_kwlist.h diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index bdaa454e4a7a9..cc861897d2a41 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -4,7 +4,7 @@ * lexical token lookup for key words in PostgreSQL * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build index ddd7a66547f54..aa948efc0dce8 100644 --- a/src/interfaces/ecpg/preproc/meson.build +++ b/src/interfaces/ecpg/preproc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ecpg_sources = files( '../ecpglib/typename.c', @@ -10,6 +10,7 @@ ecpg_sources = files( 'output.c', 'parser.c', 'type.c', + 'util.c', 'variable.c', ) @@ -44,20 +45,6 @@ preproc_y = custom_target('preproc.y', ) generated_sources += preproc_y -check_rules = custom_target('preproc.y.check_rules', - input: [ - '../../../backend/parser/gram.y', - ecpg_files, - ], - output: 'preproc.y.check_rules', - command: [ - perl, files('check_rules.pl'), - '--srcdir', '@CURRENT_SOURCE_DIR@', - '--parser', '@INPUT0@', - '--stamp', '@OUTPUT0@', - ], -) - preproc = custom_target('preproc.c', input: preproc_y, kwargs: bison_kw, @@ -68,7 +55,6 @@ ecpg_sources += preproc c_kwlist = custom_target('c_kwlist_d.h', input: ['c_kwlist.h'], output: ['c_kwlist_d.h'], - depends: check_rules, depend_files: gen_kwlist_deps, command: [gen_kwlist_cmd, '--varname', 'ScanCKeywords', '--no-case-fold'], ) @@ -100,3 +86,16 @@ ecpg_exe = executable('ecpg', ecpg_targets += ecpg_exe subdir('po', if_found: libintl) + +tests += { + 'name': 'ecpg', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_ecpg_err_warn_msg.pl', + 't/002_ecpg_err_warn_msg_informix.pl', + ], + 'deps': [ecpg_exe], + }, +} diff --git a/src/interfaces/ecpg/preproc/nls.mk b/src/interfaces/ecpg/preproc/nls.mk index 55ea19a44ed98..34d6caa210324 100644 --- a/src/interfaces/ecpg/preproc/nls.mk +++ b/src/interfaces/ecpg/preproc/nls.mk @@ -1,5 +1,5 @@ # src/interfaces/ecpg/preproc/nls.mk CATALOG_NAME = ecpg -GETTEXT_FILES = descriptor.c ecpg.c pgc.c preproc.c type.c variable.c +GETTEXT_FILES = descriptor.c ecpg.c pgc.c preproc.c type.c util.c variable.c GETTEXT_TRIGGERS = mmerror:3 mmfatal:2 GETTEXT_FLAGS = mmerror:3:c-format mmfatal:2:c-format diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c index 6c0b8a27b1eb4..b190e9f0cea2a 100644 --- a/src/interfaces/ecpg/preproc/output.c +++ b/src/interfaces/ecpg/preproc/output.c @@ -4,7 +4,7 @@ #include "preproc_extern.h" -static void output_escaped_str(char *str, bool quoted); +static void output_escaped_str(const char *str, bool quoted); void output_line_number(void) @@ -12,17 +12,15 @@ output_line_number(void) char *line = hashline_number(); fprintf(base_yyout, "%s", line); - free(line); } void -output_simple_statement(char *stmt, int whenever_mode) +output_simple_statement(const char *stmt, int whenever_mode) { output_escaped_str(stmt, false); if (whenever_mode) whenever_action(whenever_mode); output_line_number(); - free(stmt); } @@ -101,7 +99,7 @@ hashline_number(void) ) { /* "* 2" here is for escaping '\' and '"' below */ - char *line = mm_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2); + char *line = loc_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2); char *src, *dest; @@ -120,7 +118,7 @@ hashline_number(void) return line; } - return EMPTY; + return ""; } static char *ecpg_statement_type_name[] = { @@ -133,7 +131,7 @@ static char *ecpg_statement_type_name[] = { }; void -output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st) +output_statement(const char *stmt, int whenever_mode, enum ECPG_statement_type st) { fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks); @@ -157,17 +155,17 @@ output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st) /* dump variables to C file */ dump_variables(argsinsert, 1); + argsinsert = NULL; fputs("ECPGt_EOIT, ", base_yyout); dump_variables(argsresult, 1); + argsresult = NULL; fputs("ECPGt_EORT);", base_yyout); - reset_variables(); whenever_action(whenever_mode | 2); - free(stmt); } void -output_prepare_statement(char *name, char *stmt) +output_prepare_statement(const char *name, const char *stmt) { fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks); output_escaped_str(name, true); @@ -175,11 +173,10 @@ output_prepare_statement(char *name, char *stmt) output_escaped_str(stmt, true); fputs(");", base_yyout); whenever_action(2); - free(name); } void -output_deallocate_prepare_statement(char *name) +output_deallocate_prepare_statement(const char *name) { const char *con = connection ? connection : "NULL"; @@ -193,11 +190,10 @@ output_deallocate_prepare_statement(char *name) fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con); whenever_action(2); - free(name); } static void -output_escaped_str(char *str, bool quoted) +output_escaped_str(const char *str, bool quoted) { int i = 0; int len = strlen(str); diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl index fe8d3e5178058..f22ca213c21a7 100644 --- a/src/interfaces/ecpg/preproc/parse.pl +++ b/src/interfaces/ecpg/preproc/parse.pl @@ -1,9 +1,15 @@ #!/usr/bin/perl # src/interfaces/ecpg/preproc/parse.pl -# parser generator for ecpg version 2 -# call with backend parser as stdin +# parser generator for ecpg # -# Copyright (c) 2007-2024, PostgreSQL Global Development Group +# See README.parser for some explanation of what this does. +# +# Command-line options: +# --srcdir: where to find ecpg-provided input files (default ".") +# --parser: the backend gram.y file to read (required, no default) +# --output: where to write preproc.y (required, no default) +# +# Copyright (c) 2007-2025, PostgreSQL Global Development Group # # Written by Mike Aubury # Michael Meskes @@ -25,27 +31,13 @@ 'output=s' => \$outfile, 'parser=s' => \$parser,) or die "wrong arguments"; -# open parser / output file early, to raise errors early -open(my $parserfh, '<', $parser) or die "could not open parser file $parser"; -open(my $outfh, '>', $outfile) or die "could not open output file $outfile"; - -my $copymode = 0; -my $brace_indent = 0; -my $yaccmode = 0; -my $in_rule = 0; -my $header_included = 0; -my $has_feature_not_supported = 0; -my $has_if_command = 0; -my $tokenmode = 0; - -my (%buff, $infield, $comment, %tokens, %addons); -my ($stmt_mode, @fields); -my $line = ''; -my $non_term_id; +# These hash tables define additional transformations to apply to +# grammar rules. For bug-detection purposes, we count usages of +# each hash table entry in a second hash table, and verify that +# all the entries get used. -# some token have to be replaced by other symbols -# either in the rule +# Substitutions to apply to tokens whenever they are seen in a rule. my %replace_token = ( 'BCONST' => 'ecpg_bconst', 'FCONST' => 'ecpg_fconst', @@ -54,29 +46,18 @@ 'IDENT' => 'ecpg_ident', 'PARAM' => 'ecpg_param',); -# or in the block -my %replace_string = ( - 'FORMAT_LA' => 'format', - 'NOT_LA' => 'not', - 'NULLS_LA' => 'nulls', - 'WITH_LA' => 'with', - 'WITHOUT_LA' => 'without', - 'TYPECAST' => '::', - 'DOT_DOT' => '..', - 'COLON_EQUALS' => ':=', - 'EQUALS_GREATER' => '=>', - 'LESS_EQUALS' => '<=', - 'GREATER_EQUALS' => '>=', - 'NOT_EQUALS' => '<>',); - -# specific replace_types for specific non-terminals - never include the ':' -# ECPG-only replace_types are defined in ecpg-replace_types +my %replace_token_used; + +# This hash can provide a result type to override "void" for nonterminals +# that need that, or it can specify 'ignore' to cause us to skip the rule +# for that nonterminal. (In either case, ecpg.trailer had better provide +# a substitute rule, since the default won't do.) my %replace_types = ( 'PrepareStmt' => '', 'ExecuteStmt' => '', 'opt_array_bounds' => '', - # "ignore" means: do not create type and rules for this non-term-id + # "ignore" means: do not create type and rules for this nonterminal 'parse_toplevel' => 'ignore', 'stmtmulti' => 'ignore', 'CreateAsStmt' => 'ignore', @@ -91,50 +72,121 @@ 'plassign_target' => 'ignore', 'plassign_equals' => 'ignore',); -# these replace_line commands excise certain keywords from the core keyword -# lists. Be sure to account for these in ColLabel and related productions. +my %replace_types_used; + +# This hash provides an "ignore" option or substitute expansion for any +# rule or rule alternative. The hash key is the same "tokenlist" tag +# used for lookup in ecpg.addons. my %replace_line = ( - 'unreserved_keywordCONNECTION' => 'ignore', - 'unreserved_keywordCURRENT_P' => 'ignore', - 'unreserved_keywordDAY_P' => 'ignore', - 'unreserved_keywordHOUR_P' => 'ignore', - 'unreserved_keywordINPUT_P' => 'ignore', - 'unreserved_keywordMINUTE_P' => 'ignore', - 'unreserved_keywordMONTH_P' => 'ignore', - 'unreserved_keywordSECOND_P' => 'ignore', - 'unreserved_keywordYEAR_P' => 'ignore', - 'col_name_keywordCHAR_P' => 'ignore', - 'col_name_keywordINT_P' => 'ignore', - 'col_name_keywordVALUES' => 'ignore', - 'reserved_keywordTO' => 'ignore', - 'reserved_keywordUNION' => 'ignore', + # These entries excise certain keywords from the core keyword lists. + # Be sure to account for these in ColLabel and related productions. + 'unreserved_keyword CONNECTION' => 'ignore', + 'unreserved_keyword CURRENT_P' => 'ignore', + 'unreserved_keyword DAY_P' => 'ignore', + 'unreserved_keyword HOUR_P' => 'ignore', + 'unreserved_keyword INPUT_P' => 'ignore', + 'unreserved_keyword MINUTE_P' => 'ignore', + 'unreserved_keyword MONTH_P' => 'ignore', + 'unreserved_keyword SECOND_P' => 'ignore', + 'unreserved_keyword YEAR_P' => 'ignore', + 'col_name_keyword CHAR_P' => 'ignore', + 'col_name_keyword INT_P' => 'ignore', + 'col_name_keyword VALUES' => 'ignore', + 'reserved_keyword TO' => 'ignore', + 'reserved_keyword UNION' => 'ignore', # some other production rules have to be ignored or replaced - 'fetch_argsFORWARDopt_from_incursor_name' => 'ignore', - 'fetch_argsBACKWARDopt_from_incursor_name' => 'ignore', - "opt_array_boundsopt_array_bounds'['Iconst']'" => 'ignore', - 'VariableShowStmtSHOWvar_name' => 'SHOW var_name ecpg_into', - 'VariableShowStmtSHOWTIMEZONE' => 'SHOW TIME ZONE ecpg_into', - 'VariableShowStmtSHOWTRANSACTIONISOLATIONLEVEL' => + 'fetch_args FORWARD opt_from_in cursor_name' => 'ignore', + 'fetch_args BACKWARD opt_from_in cursor_name' => 'ignore', + "opt_array_bounds opt_array_bounds '[' Iconst ']'" => 'ignore', + 'VariableShowStmt SHOW var_name' => 'SHOW var_name ecpg_into', + 'VariableShowStmt SHOW TIME ZONE' => 'SHOW TIME ZONE ecpg_into', + 'VariableShowStmt SHOW TRANSACTION ISOLATION LEVEL' => 'SHOW TRANSACTION ISOLATION LEVEL ecpg_into', - 'VariableShowStmtSHOWSESSIONAUTHORIZATION' => + 'VariableShowStmt SHOW SESSION AUTHORIZATION' => 'SHOW SESSION AUTHORIZATION ecpg_into', - 'returning_clauseRETURNINGtarget_list' => - 'RETURNING target_list opt_ecpg_into', - 'ExecuteStmtEXECUTEnameexecute_param_clause' => + 'returning_clause RETURNING returning_with_clause target_list' => + 'RETURNING returning_with_clause target_list opt_ecpg_into', + 'ExecuteStmt EXECUTE name execute_param_clause' => 'EXECUTE prepared_name execute_param_clause execute_rest', - 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' + 'ExecuteStmt CREATE OptTemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data' => 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', - 'ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data' + 'ExecuteStmt CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data' => 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest', - 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' => + 'PrepareStmt PREPARE name prep_type_clause AS PreparableStmt' => 'PREPARE prepared_name prep_type_clause AS PreparableStmt', - 'var_nameColId' => 'ECPGColId'); + 'var_name ColId' => 'ECPGColId'); + +my %replace_line_used; + +# Declare assorted state variables. + +# yaccmode counts the '%%' separator lines we have seen, so that we can +# distinguish prologue, rules, and epilogue sections of gram.y. +my $yaccmode = 0; +# in /* ... */ comment? +my $comment = 0; +# in { ... } braced text? +my $brace_indent = 0; +# within a rule (production)? +my $in_rule = 0; +# count of alternatives processed within the current rule. +my $alt_count = 0; +# copymode = 1 when we want to emit the current rule to preproc.y. +# If it's 0, we have decided to ignore the current rule, and should +# skip all output until we get to the ending semicolon. +my $copymode = 0; +# tokenmode = 1 indicates we are processing %token and following declarations. +my $tokenmode = 0; +# stmt_mode = 1 indicates that we are processing the 'stmt:' rule. +my $stmt_mode = 0; +# Hacky state for emitting feature-not-supported warnings. +my $has_feature_not_supported = 0; +my $has_if_command = 0; + +# %addons holds the rules loaded from ecpg.addons. +my %addons; + +# %buff holds various named "buffers", which are just strings that accumulate +# the output destined for different sections of the preproc.y file. This +# allows us to process the input in one pass even though the resulting output +# needs to appear in various places. See dump_buffer calls below for the +# set of buffer names and the order in which they'll be dumped. +my %buff; + +# %tokens contains an entry for every name we have discovered to be a token. +my %tokens; + +# $non_term_id is the name of the nonterminal that is the target of the +# current rule. +my $non_term_id; + +# $line holds the reconstructed rule text (that is, RHS token list) that +# we plan to emit for the current rule. +my $line = ''; + +# count of tokens included in $line. +my $line_count = 0; + + +# Open parser / output file early, to raise errors early. +open(my $parserfh, '<', $parser) or die "could not open parser file $parser"; +open(my $outfh, '>', $outfile) or die "could not open output file $outfile"; + +# Read the various ecpg-supplied input files. +# ecpg.addons is loaded into the %addons hash, while the other files +# are just copied into buffers for verbatim output later. preload_addons(); +include_file('header', 'ecpg.header'); +include_file('tokens', 'ecpg.tokens'); +include_file('ecpgtype', 'ecpg.type'); +include_file('trailer', 'ecpg.trailer'); +# Read gram.y, and do the bulk of the processing. main(); +# Emit data from the various buffers we filled. dump_buffer('header'); dump_buffer('tokens'); dump_buffer('types'); @@ -143,88 +195,99 @@ print $outfh '%%', "\n"; print $outfh 'prog: statements;', "\n"; dump_buffer('rules'); -include_file('trailer', 'ecpg.trailer'); dump_buffer('trailer'); close($parserfh); +# Cross-check that we don't have dead or ambiguous addon rules. +foreach (keys %addons) +{ + die "addon rule $_ was never used\n" if $addons{$_}{used} == 0; + die "addon rule $_ was matched multiple times\n" if $addons{$_}{used} > 1; +} + +# Likewise cross-check that entries in our internal hash tables match something. +foreach (keys %replace_token) +{ + die "replace_token entry $_ was never used\n" + if !defined($replace_token_used{$_}); + # multiple use of a replace_token entry is fine +} + +foreach (keys %replace_types) +{ + die "replace_types entry $_ was never used\n" + if !defined($replace_types_used{$_}); + die "replace_types entry $_ was matched multiple times\n" + if $replace_types_used{$_} > 1; +} + +foreach (keys %replace_line) +{ + die "replace_line entry $_ was never used\n" + if !defined($replace_line_used{$_}); + die "replace_line entry $_ was matched multiple times\n" + if $replace_line_used{$_} > 1; +} + + +# Read the backend grammar. sub main { line: while (<$parserfh>) { chomp; - # comment out the line below to make the result file match (blank line wise) - # the prior version. - #next if ($_ eq ''); - - # Dump the action for a rule - - # stmt_mode indicates if we are processing the 'stmt:' - # rule (mode==0 means normal, mode==1 means stmt:) - # flds are the fields to use. These may start with a '$' - in - # which case they are the result of a previous non-terminal - # - # if they don't start with a '$' then they are token name - # - # len is the number of fields in flds... - # leadin is the padding to apply at the beginning (just use for formatting) - if (/^%%/) { - $tokenmode = 2; - $copymode = 1; + # New file section, so advance yaccmode. $yaccmode++; - $infield = 0; + # We are no longer examining %token and related commands. + $tokenmode = 0; + # Shouldn't be anything else on the line. + next line; } + # Hacky check for rules that throw FEATURE_NOT_SUPPORTED + # (do this before $_ has a chance to get clobbered) if ($yaccmode == 1) { - # Check for rules that throw FEATURE_NOT_SUPPORTED $has_feature_not_supported = 1 if /ERRCODE_FEATURE_NOT_SUPPORTED/; $has_if_command = 1 if /^\s*if/; } - my $prec = 0; - - # Make sure any braces are split + # Make sure any braces are split into separate fields s/{/ { /g; s/}/ } /g; - # Any comments are split + # Likewise for comment start/end markers s|\/\*| /* |g; s|\*\/| */ |g; # Now split the line into individual fields my @arr = split(' '); + # Ignore empty lines if (!@arr) { - # empty line: in tokenmode 1, emit an empty line, else ignore - if ($tokenmode == 1) - { - add_to_buffer('orig_tokens', ''); - } next line; } - if ($arr[0] eq '%token' && $tokenmode == 0) + # Once we have seen %token in the prologue, we assume all that follows + # up to the '%%' separator is %token and associativity declarations. + # Collect and process that as necessary. + if ($arr[0] eq '%token' && $yaccmode == 0) { $tokenmode = 1; - include_file('tokens', 'ecpg.tokens'); - } - elsif ($arr[0] eq '%type' && $header_included == 0) - { - include_file('header', 'ecpg.header'); - include_file('ecpgtype', 'ecpg.type'); - $header_included = 1; } if ($tokenmode == 1) { + # Collect everything of interest on this line into $str. my $str = ''; - my $prior = ''; for my $a (@arr) { + # Skip comments. if ($a eq '/*') { $comment++; @@ -239,40 +302,49 @@ sub main { next; } + + # If it's "", it's a type in a %token declaration, + # which we should just drop so that the tokens have void type. if (substr($a, 0, 1) eq '<') { next; - - # its a type } + + # Remember that this is a token. This will also make entries + # for "%token" and the associativity keywords such as "%left", + # which should be harmless so it's not worth the trouble to + # avoid it. If a token appears both in %token and in an + # associativity declaration, we'll redundantly re-set its + # entry, which is also OK. $tokens{$a} = 1; + # Accumulate the line in $str. $str = $str . ' ' . $a; - if ($a eq 'IDENT' && $prior eq '%nonassoc') - { - # add more tokens to the list - $str = $str . "\n%nonassoc CSTRING"; + # Give our token CSTRING the same precedence as IDENT. + if ($a eq 'IDENT' && $arr[0] eq '%nonassoc') + { + $str = $str . " CSTRING"; } - $prior = $a; } + # Save the lightly-processed line in orig_tokens. add_to_buffer('orig_tokens', $str); next line; } - # Don't worry about anything if we're not in the right section of gram.y + # The rest is only appropriate if we're in the rules section of gram.y if ($yaccmode != 1) { next line; } - - # Go through each field in turn + # Go through each word of the rule in turn for ( my $fieldIndexer = 0; $fieldIndexer < scalar(@arr); $fieldIndexer++) { + # Detect and ignore comments and braced action text if ($arr[$fieldIndexer] eq '*/' && $comment) { $comment = 0; @@ -284,15 +356,10 @@ sub main } elsif ($arr[$fieldIndexer] eq '/*') { - - # start of a multiline comment + # start of a possibly-multiline comment $comment = 1; next; } - elsif ($arr[$fieldIndexer] eq '//') - { - next line; - } elsif ($arr[$fieldIndexer] eq '}') { $brace_indent--; @@ -303,29 +370,35 @@ sub main $brace_indent++; next; } - if ($brace_indent > 0) { next; } + + # OK, it's not a comment or part of an action. + # Check for ';' ending the current rule, or '|' ending the + # current alternative. if ($arr[$fieldIndexer] eq ';') { if ($copymode) { - if ($infield) - { - dump_line($stmt_mode, \@fields); - } + # Print the accumulated rule. + emit_rule(); add_to_buffer('rules', ";\n\n"); } else { + # End of an ignored rule; revert to copymode = 1. $copymode = 1; } - @fields = (); - $infield = 0; + + # Reset for the next rule. $line = ''; + $line_count = 0; $in_rule = 0; + $alt_count = 0; + $has_feature_not_supported = 0; + $has_if_command = 0; next; } @@ -333,56 +406,66 @@ sub main { if ($copymode) { - if ($infield) - { - $infield = $infield + dump_line($stmt_mode, \@fields); - } - if ($infield > 1) - { - $line = '| '; - } + # Print the accumulated alternative. + # Increment $alt_count for each non-ignored alternative. + $alt_count += emit_rule(); } - @fields = (); + + # Reset for the next alternative. + # Start the next line with '|' if we've printed at least one + # alternative. + if ($alt_count > 1) + { + $line = '| '; + } + else + { + $line = ''; + } + $line_count = 0; + $has_feature_not_supported = 0; + $has_if_command = 0; next; } + # Apply replace_token substitution if we have one. if (exists $replace_token{ $arr[$fieldIndexer] }) { + $replace_token_used{ $arr[$fieldIndexer] }++; $arr[$fieldIndexer] = $replace_token{ $arr[$fieldIndexer] }; } - # Are we looking at a declaration of a non-terminal ? - if (($arr[$fieldIndexer] =~ /[A-Za-z0-9]+:/) + # Are we looking at a declaration of a non-terminal? + # We detect that by seeing ':' on the end of the token or + # as the next token. + if (($arr[$fieldIndexer] =~ /[A-Za-z0-9]+:$/) || ( $fieldIndexer + 1 < scalar(@arr) && $arr[ $fieldIndexer + 1 ] eq ':')) { + # Extract the non-terminal, sans : if any $non_term_id = $arr[$fieldIndexer]; $non_term_id =~ tr/://d; - if (not defined $replace_types{$non_term_id}) + # Consume the ':' if it's separate + if (!($arr[$fieldIndexer] =~ /[A-Za-z0-9]+:$/)) { - $replace_types{$non_term_id} = ''; - $copymode = 1; + $fieldIndexer++; } - elsif ($replace_types{$non_term_id} eq 'ignore') + + # Check for %replace_types entry indicating to ignore it. + if (defined $replace_types{$non_term_id} + && $replace_types{$non_term_id} eq 'ignore') { + # We'll ignore this nonterminal and rule altogether. + $replace_types_used{$non_term_id}++; $copymode = 0; - $line = ''; next line; } - $line = $line . ' ' . $arr[$fieldIndexer]; - - # Do we have the : attached already ? - # If yes, we'll have already printed the ':' - if (!($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:')) - { - # Consume the ':' which is next... - $line = $line . ':'; - $fieldIndexer++; - } + # OK, we want this rule. + $copymode = 1; - # Special mode? + # Set special mode for the "stmt:" rule. if ($non_term_id eq 'stmt') { $stmt_mode = 1; @@ -391,71 +474,39 @@ sub main { $stmt_mode = 0; } - my $tstr = - '%type ' - . $replace_types{$non_term_id} . ' ' - . $non_term_id; - add_to_buffer('types', $tstr); - if ($copymode) + # Emit appropriate %type declaration for this nonterminal, + # if it has a type; otherwise omit that. + if (defined $replace_types{$non_term_id}) { - add_to_buffer('rules', $line); + my $tstr = + '%type ' + . $replace_types{$non_term_id} . ' ' + . $non_term_id; + add_to_buffer('types', $tstr); + $replace_types_used{$non_term_id}++; } + + # Emit the target part of the rule. + # Note: the leading space is just to match + # the rather weird pre-v18 output logic. + my $tstr = ' ' . $non_term_id . ':'; + add_to_buffer('rules', $tstr); + + # Prepare for reading the tokens of the rule. $line = ''; - @fields = (); - $infield = 1; + $line_count = 0; die "unterminated rule at grammar line $.\n" if $in_rule; $in_rule = 1; + $alt_count = 1; next; } elsif ($copymode) { + # Not a nonterminal declaration, so just add it to $line. $line = $line . ' ' . $arr[$fieldIndexer]; - } - if ($arr[$fieldIndexer] eq '%prec') - { - $prec = 1; - next; - } - - if ( $copymode - && !$prec - && !$comment - && $fieldIndexer < scalar(@arr) - && length($arr[$fieldIndexer]) - && $infield) - { - if ($arr[$fieldIndexer] ne 'Op' - && (( defined $tokens{ $arr[$fieldIndexer] } - && $tokens{ $arr[$fieldIndexer] } > 0) - || $arr[$fieldIndexer] =~ /'.+'/) - || $stmt_mode == 1) - { - my $S; - if (exists $replace_string{ $arr[$fieldIndexer] }) - { - $S = $replace_string{ $arr[$fieldIndexer] }; - } - else - { - $S = $arr[$fieldIndexer]; - } - $S =~ s/_P//g; - $S =~ tr/'//d; - if ($stmt_mode == 1) - { - push(@fields, $S); - } - else - { - push(@fields, lc($S)); - } - } - else - { - push(@fields, '$' . (scalar(@fields) + 1)); - } + $line_count++; } } } @@ -481,172 +532,136 @@ sub include_file return; } -sub include_addon +# Emit the semantic action for the current rule. +# This function mainly accounts for any modifications specified +# by an ecpg.addons entry. +sub emit_rule_action { - my ($buffer, $block, $fields, $stmt_mode) = @_; - my $rec = $addons{$block}; - return 0 unless $rec; + my ($tag) = @_; + + # See if we have an addons entry; if not, just emit default action + my $rec = $addons{$tag}; + if (!$rec) + { + emit_default_action(0); + return; + } + + # Track addons entry usage for later cross-check + $rec->{used}++; - my $rectype = (defined $rec->{type}) ? $rec->{type} : ''; + my $rectype = $rec->{type}; if ($rectype eq 'rule') { - dump_fields($stmt_mode, $fields, ' { '); + # Emit default action and then the code block. + emit_default_action(0); } elsif ($rectype eq 'addon') { + # Emit the code block wrapped in the same braces as the default action. add_to_buffer('rules', ' { '); } - #add_to_buffer( $stream, $_ ); - #We have an array to add to the buffer, we'll add it ourself instead of - #calling add_to_buffer, which does not know about arrays - - push(@{ $buff{$buffer} }, @{ $rec->{lines} }); + # Emit the addons entry's code block. + # We have an array to add to the buffer, we'll add it directly instead of + # calling add_to_buffer, which does not know about arrays. + push(@{ $buff{'rules'} }, @{ $rec->{lines} }); if ($rectype eq 'addon') { - dump_fields($stmt_mode, $fields, ''); + emit_default_action(1); } - - - # if we added something (ie there are lines in our array), return 1 - return 1 if (scalar(@{ $rec->{lines} }) > 0); - return 0; + return; } - -# include_addon does this same thing, but does not call this -# sub... so if you change this, you need to fix include_addon too +# Add the given line to the specified buffer. # Pass: buffer_name, string_to_append +# Note we add a newline automatically. sub add_to_buffer { push(@{ $buff{ $_[0] } }, "$_[1]\n"); return; } +# Dump the specified buffer to the output file. sub dump_buffer { my ($buffer) = @_; + # Label the output for debugging purposes. print $outfh '/* ', $buffer, ' */', "\n"; my $ref = $buff{$buffer}; print $outfh @$ref; return; } -sub dump_fields +# Emit the default action (usually token concatenation) for the current rule. +# Pass: brace_printed boolean +# brace_printed should be true if caller already printed action's open brace. +sub emit_default_action { - my ($mode, $flds, $ln) = @_; - my $len = scalar(@$flds); + my ($brace_printed) = @_; - if ($mode == 0) + if ($stmt_mode == 0) { - - #Normal - add_to_buffer('rules', $ln); + # Normal rule if ($has_feature_not_supported and not $has_if_command) { # The backend unconditionally reports # FEATURE_NOT_SUPPORTED in this rule, so let's emit # a warning on the ecpg side. + if (!$brace_printed) + { + add_to_buffer('rules', ' { '); + $brace_printed = 1; + } add_to_buffer('rules', 'mmerror(PARSE_ERROR, ET_WARNING, "unsupported feature will be passed to server");' ); } - $has_feature_not_supported = 0; - $has_if_command = 0; - - if ($len == 0) - { - - # We have no fields ? - add_to_buffer('rules', ' $$=EMPTY; }'); - } - else - { - # Go through each field and try to 'aggregate' the tokens - # into a single 'mm_strdup' where possible - my @flds_new; - my $str; - for (my $z = 0; $z < $len; $z++) - { - if (substr($flds->[$z], 0, 1) eq '$') - { - push(@flds_new, $flds->[$z]); - next; - } - - $str = $flds->[$z]; - - while (1) - { - if ($z >= $len - 1 - || substr($flds->[ $z + 1 ], 0, 1) eq '$') - { - - # We're at the end... - push(@flds_new, "mm_strdup(\"$str\")"); - last; - } - $z++; - $str = $str . ' ' . $flds->[$z]; - } - } - - # So - how many fields did we end up with ? - $len = scalar(@flds_new); - if ($len == 1) - { - - # Straight assignment - $str = ' $$ = ' . $flds_new[0] . ';'; - add_to_buffer('rules', $str); - } - else - { - - # Need to concatenate the results to form - # our final string - $str = - ' $$ = cat_str(' . $len . ',' . join(',', @flds_new) . ');'; - add_to_buffer('rules', $str); - } - add_to_buffer('rules', '}'); - } + add_to_buffer('rules', '}') if ($brace_printed); } else { - - # we're in the stmt: rule - if ($len) + # We're in the "stmt:" rule, where we need to output special actions. + # This code assumes that no ecpg.addons entry applies. + if ($line_count) { - - # or just the statement ... + # Any regular kind of statement calls output_statement add_to_buffer('rules', - ' { output_statement($1, 0, ECPGst_normal); }'); + ' { output_statement(@1, 0, ECPGst_normal); }'); } else { - add_to_buffer('rules', ' { $$ = NULL; }'); + # The empty production for stmt: do nothing } } return; } - -sub dump_line +# Print the accumulated rule text (in $line) and the appropriate action. +# Ordinarily return 1. However, if the rule matches an "ignore" +# entry in %replace_line, then do nothing and return 0. +sub emit_rule { - my ($stmt_mode, $fields) = @_; - my $block = $non_term_id . $line; - $block =~ tr/ |//d; - my $rep = $replace_line{$block}; - if ($rep) + # compute tag to be used as lookup key in %replace_line and %addons + my $tag = $non_term_id . ' ' . $line; + $tag =~ tr/|//d; + $tag = join(' ', split(/\s+/, $tag)); + + # apply replace_line substitution if any + my $rep = $replace_line{$tag}; + if (defined $rep) { + $replace_line_used{$tag}++; + if ($rep eq 'ignore') { return 0; } + # non-ignore entries replace the line, but we'd better keep any '|'; + # we don't bother to update $line_count here. if (index($line, '|') != -1) { $line = '| ' . $rep; @@ -655,23 +670,24 @@ sub dump_line { $line = $rep; } - $block = $non_term_id . $line; - $block =~ tr/ |//d; + + # recompute tag for use in emit_rule_action + $tag = $non_term_id . ' ' . $line; + $tag =~ tr/|//d; + $tag = join(' ', split(/\s+/, $tag)); } + + # Emit $line, then print the appropriate action. add_to_buffer('rules', $line); - my $i = include_addon('rules', $block, $fields, $stmt_mode); - if ($i == 0) - { - dump_fields($stmt_mode, $fields, ' { '); - } + emit_rule_action($tag); return 1; } =top - load addons into cache + load ecpg.addons into %addons hash. The result is something like %addons = { - stmtClosePortalStmt => { 'type' => 'block', 'lines' => [ "{", "if (INFORMIX_MODE)" ..., "}" ] }, - stmtViewStmt => { 'type' => 'rule', 'lines' => [ "| ECPGAllocateDescr", ... ] } + 'stmt ClosePortalStmt' => { 'type' => 'block', 'lines' => [ "{", "if (INFORMIX_MODE)" ..., "}" ], 'used' => 0 }, + 'stmt ViewStmt' => { 'type' => 'rule', 'lines' => [ "| ECPGAllocateDescr", ... ], 'used' => 0 } } =cut @@ -681,17 +697,32 @@ sub preload_addons my $filename = $srcdir . "/ecpg.addons"; open(my $fh, '<', $filename) or die; - # there may be multiple lines starting ECPG: and then multiple lines of code. - # the code need to be add to all prior ECPG records. - my (@needsRules, @code, $record); + # There may be multiple "ECPG:" lines and then multiple lines of code. + # The block of code needs to be added to each of the consecutively- + # preceding "ECPG:" records. + my (@needsRules, @code); - # there may be comments before the first ECPG line, skip them + # there may be comments before the first "ECPG:" line, skip them my $skip = 1; while (<$fh>) { - if (/^ECPG:\s(\S+)\s?(\w+)?/) + if (/^ECPG:\s+(\w+)\s+(.*)$/) { + # Found an "ECPG:" line, so we're done skipping the header $skip = 0; + my $type = $1; + my $target = $2; + # Normalize target so there's exactly one space between tokens + $target = join(' ', split(/\s+/, $target)); + # Validate record type and target + die "invalid record type $type in addon rule for $target\n" + unless ($type eq 'block' + or $type eq 'addon' + or $type eq 'rule'); + die "duplicate addon rule for $target\n" + if (exists $addons{$target}); + # If we had some preceding code lines, attach them to all + # as-yet-unfinished records. if (@code) { for my $x (@needsRules) @@ -701,20 +732,27 @@ sub preload_addons @code = (); @needsRules = (); } - $record = {}; - $record->{type} = $2; + my $record = {}; + $record->{type} = $type; $record->{lines} = []; - if (exists $addons{$1}) { die "Ga! there are dups!\n"; } - $addons{$1} = $record; + $record->{used} = 0; + $addons{$target} = $record; push(@needsRules, $record); } + elsif (/^ECPG:/) + { + # Complain if preceding regex failed to match + die "incorrect syntax in ECPG line: $_\n"; + } else { + # Non-ECPG line: add to @code unless we're still skipping next if $skip; push(@code, $_); } } close($fh); + # Deal with final code block if (@code) { for my $x (@needsRules) diff --git a/src/interfaces/ecpg/preproc/parser.c b/src/interfaces/ecpg/preproc/parser.c index 9daeee330344a..a8455f1a1917e 100644 --- a/src/interfaces/ecpg/preproc/parser.c +++ b/src/interfaces/ecpg/preproc/parser.c @@ -10,7 +10,7 @@ * This file will need work if we ever want it to. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -31,6 +31,7 @@ static YYSTYPE lookahead_yylval; /* yylval for lookahead token */ static YYLTYPE lookahead_yylloc; /* yylloc for lookahead token */ static char *lookahead_yytext; /* start current token */ +static int base_yylex_location(void); static bool check_uescapechar(unsigned char escape); static bool ecpg_isspace(char ch); @@ -71,7 +72,7 @@ filtered_base_yylex(void) have_lookahead = false; } else - cur_token = base_yylex(); + cur_token = base_yylex_location(); /* * If this token isn't one that requires lookahead, just return it. @@ -96,7 +97,7 @@ filtered_base_yylex(void) cur_yytext = base_yytext; /* Get next token, saving outputs into lookahead variables */ - next_token = base_yylex(); + next_token = base_yylex_location(); lookahead_token = next_token; lookahead_yylval = base_yylval; @@ -184,7 +185,7 @@ filtered_base_yylex(void) cur_yytext = base_yytext; /* Get third token */ - next_token = base_yylex(); + next_token = base_yylex_location(); if (next_token != SCONST) mmerror(PARSE_ERROR, ET_ERROR, "UESCAPE must be followed by a simple string literal"); @@ -202,7 +203,10 @@ filtered_base_yylex(void) base_yytext = cur_yytext; /* Combine 3 tokens into 1 */ - base_yylval.str = psprintf("%s UESCAPE %s", base_yylval.str, escstr); + base_yylval.str = make3_str(base_yylval.str, + " UESCAPE ", + escstr); + base_yylloc = loc_strdup(base_yylval.str); /* Clear have_lookahead, thereby consuming all three tokens */ have_lookahead = false; @@ -218,6 +222,56 @@ filtered_base_yylex(void) return cur_token; } +/* + * Call base_yylex() and fill in base_yylloc. + * + * pgc.l does not worry about setting yylloc, and given what we want for + * that, trying to set it there would be pretty inconvenient. What we + * want is: if the returned token has type , then duplicate its + * string value as yylloc; otherwise, make a downcased copy of yytext. + * The downcasing is ASCII-only because all that we care about there + * is producing uniformly-cased output of keywords. (That's mostly + * cosmetic, but there are places in ecpglib that expect to receive + * downcased keywords, plus it keeps us regression-test-compatible + * with the pre-v18 implementation of ecpg.) + */ +static int +base_yylex_location(void) +{ + int token = base_yylex(); + + switch (token) + { + /* List a token here if pgc.l assigns to base_yylval.str for it */ + case Op: + case CSTRING: + case CPP_LINE: + case CVARIABLE: + case BCONST: + case SCONST: + case USCONST: + case XCONST: + case FCONST: + case IDENT: + case UIDENT: + case IP: + /* Duplicate the value */ + base_yylloc = loc_strdup(base_yylval.str); + break; + default: + /* Else just use the input, i.e., yytext */ + base_yylloc = loc_strdup(base_yytext); + /* Apply an ASCII-only downcasing */ + for (unsigned char *ptr = (unsigned char *) base_yylloc; *ptr; ptr++) + { + if (*ptr >= 'A' && *ptr <= 'Z') + *ptr += 'a' - 'A'; + } + break; + } + return token; +} + /* * check_uescapechar() and ecpg_isspace() should match their equivalents * in pgc.l. diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 27261f42d8d50..63283a4a1e5a4 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -10,7 +10,7 @@ * only here to simplify syncing this file with scan.l. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -35,8 +35,8 @@ extern YYSTYPE base_yylval; -static int xcdepth = 0; /* depth of nesting in slash-star comments */ -static char *dolqstart = NULL; /* current $foo$ quote start string */ +static int xcdepth = 0; /* depth of nesting in slash-star comments */ +static char *dolqstart = NULL; /* current $foo$ quote start string */ /* * literalbuf is used to accumulate literal values when multiple rules @@ -44,15 +44,15 @@ static char *dolqstart = NULL; /* current $foo$ quote start string */ * to empty, addlit to add text. Note that the buffer is permanently * malloc'd to the largest size needed so far in the current run. */ -static char *literalbuf = NULL; /* expandable buffer */ -static int literallen; /* actual current length */ -static int literalalloc; /* current allocated buffer size */ +static char *literalbuf = NULL; /* expandable buffer */ +static int literallen; /* actual current length */ +static int literalalloc; /* current allocated buffer size */ /* Used for detecting global state together with braces_open */ -static int parenths_open; +static int parenths_open; /* Used to tell parse_include() whether the command was #include or #include_next */ -static bool include_next; +static bool include_next; #define startlit() (literalbuf[0] = '\0', literallen = 0) static void addlit(char *ytext, int yleng); @@ -63,11 +63,11 @@ static bool ecpg_isspace(char ch); static bool isdefine(void); static bool isinformixdefine(void); -char *token_start; +char *token_start; /* vars to keep track of start conditions when scanning literals */ -static int state_before_str_start; -static int state_before_str_stop; +static int state_before_str_start; +static int state_before_str_stop; /* * State for handling include files and macro expansion. We use a new @@ -78,10 +78,10 @@ static int state_before_str_stop; */ static struct _yy_buffer { - YY_BUFFER_STATE buffer; - long lineno; - char *filename; - struct _yy_buffer *next; + YY_BUFFER_STATE buffer; + long lineno; + char *filename; + struct _yy_buffer *next; } *yy_buffer = NULL; /* @@ -381,16 +381,30 @@ numericfail {decinteger}\.\. real ({decinteger}|{numeric})[Ee][-+]?{decinteger} realfail ({decinteger}|{numeric})[Ee][-+] -decinteger_junk {decinteger}{ident_start} -hexinteger_junk {hexinteger}{ident_start} -octinteger_junk {octinteger}{ident_start} -bininteger_junk {bininteger}{ident_start} -numeric_junk {numeric}{ident_start} -real_junk {real}{ident_start} - /* Positional parameters don't accept underscores. */ param \${decdigit}+ -param_junk \${decdigit}+{ident_start} + +/* + * An identifier immediately following an integer literal is disallowed because + * in some cases it's ambiguous what is meant: for example, 0x1234 could be + * either a hexinteger or a decinteger "0" and an identifier "x1234". We can + * detect such problems by seeing if integer_junk matches a longer substring + * than any of the XXXinteger patterns (decinteger, hexinteger, octinteger, + * bininteger). One "junk" pattern is sufficient because + * {decinteger}{identifier} will match all the same strings we'd match with + * {hexinteger}{identifier} etc. + * + * Note that the rule for integer_junk must appear after the ones for + * XXXinteger to make this work correctly: 0x1234 will match both hexinteger + * and integer_junk, and we need hexinteger to be chosen in that case. + * + * Also disallow strings matched by numeric_junk, real_junk and param_junk + * for consistency. + */ +integer_junk {decinteger}{identifier} +numeric_junk {numeric}{identifier} +real_junk {real}{identifier} +param_junk \${decdigit}+{identifier} /* special characters for other dbms */ /* we have to react differently in compat mode */ @@ -541,7 +555,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ {xbinside} { addlit(yytext, yyleng); } -<> { mmfatal(PARSE_ERROR, "unterminated bit string literal"); } +<> { + mmfatal(PARSE_ERROR, "unterminated bit string literal"); + } {xhstart} { token_start = yytext; @@ -549,7 +565,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ BEGIN(xh); startlit(); } -<> { mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); } +<> { + mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); + } {xqstart} { token_start = yytext; @@ -560,9 +578,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { {xnstart} { - /* National character. - * Transfer it as-is to the backend. - */ + /* National character. Transfer it as-is to the backend. */ token_start = yytext; state_before_str_start = YYSTATE; BEGIN(xn); @@ -625,55 +641,63 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ case xb: if (literalbuf[strspn(literalbuf, "01")] != '\0') mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string literal"); - base_yylval.str = psprintf("b'%s'", literalbuf); + base_yylval.str = make3_str("b'", literalbuf, "'"); return BCONST; case xh: if (literalbuf[strspn(literalbuf, "0123456789abcdefABCDEF")] != '\0') mmerror(PARSE_ERROR, ET_ERROR, "invalid hexadecimal string literal"); - base_yylval.str = psprintf("x'%s'", literalbuf); + base_yylval.str = make3_str("x'", literalbuf, "'"); return XCONST; case xq: /* fallthrough */ case xqc: - base_yylval.str = psprintf("'%s'", literalbuf); + base_yylval.str = make3_str("'", literalbuf, "'"); return SCONST; case xe: - base_yylval.str = psprintf("E'%s'", literalbuf); + base_yylval.str = make3_str("E'", literalbuf, "'"); return SCONST; case xn: - base_yylval.str = psprintf("N'%s'", literalbuf); + base_yylval.str = make3_str("N'", literalbuf, "'"); return SCONST; case xus: - base_yylval.str = psprintf("U&'%s'", literalbuf); + base_yylval.str = make3_str("U&'", literalbuf, "'"); return USCONST; default: mmfatal(PARSE_ERROR, "unhandled previous state in xqs\n"); } } -{xqdouble} { addlit(yytext, yyleng); } -{xqcquote} { addlit(yytext, yyleng); } -{xqinside} { addlit(yytext, yyleng); } -{xeinside} { +{xqdouble} { + addlit(yytext, yyleng); + } +{xqcquote} { addlit(yytext, yyleng); } -{xeunicode} { +{xqinside} { addlit(yytext, yyleng); } -{xeescape} { +{xeinside} { addlit(yytext, yyleng); } -{xeoctesc} { +{xeunicode} { addlit(yytext, yyleng); } -{xehexesc} { +{xeescape} { + addlit(yytext, yyleng); + } +{xeoctesc} { + addlit(yytext, yyleng); + } +{xehexesc} { addlit(yytext, yyleng); } . { /* This is only needed for \ just before EOF */ addlitchar(yytext[0]); } -<> { mmfatal(PARSE_ERROR, "unterminated quoted string"); } +<> { + mmfatal(PARSE_ERROR, "unterminated quoted string"); + } { {dolqdelim} { @@ -693,14 +717,14 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } } /* */ -{dolqdelim} { +{dolqdelim} { if (strcmp(yytext, dolqstart) == 0) { addlit(yytext, yyleng); free(dolqstart); dolqstart = NULL; BEGIN(SQL); - base_yylval.str = mm_strdup(literalbuf); + base_yylval.str = loc_strdup(literalbuf); return SCONST; } else @@ -724,7 +748,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ /* single quote or dollar sign */ addlitchar(yytext[0]); } -<> { mmfatal(PARSE_ERROR, "unterminated dollar-quoted string"); } +<> { + mmfatal(PARSE_ERROR, "unterminated dollar-quoted string"); + } { {xdstart} { @@ -743,6 +769,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ BEGIN(state_before_str_start); if (literallen == 0) mmerror(PARSE_ERROR, ET_ERROR, "zero-length delimited identifier"); + /* * The server will truncate the identifier here. We do * not, as (1) it does not change the result; (2) we don't @@ -751,38 +778,46 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ * PREPARE and EXECUTE IMMEDIATE, which can certainly be * longer than NAMEDATALEN. */ - base_yylval.str = mm_strdup(literalbuf); + base_yylval.str = loc_strdup(literalbuf); return CSTRING; } {xdstop} { BEGIN(state_before_str_start); - base_yylval.str = mm_strdup(literalbuf); + base_yylval.str = loc_strdup(literalbuf); return CSTRING; } {dquote} { BEGIN(state_before_str_start); if (literallen == 0) mmerror(PARSE_ERROR, ET_ERROR, "zero-length delimited identifier"); - /* The backend will truncate the identifier here. We do not as it does not change the result. */ - base_yylval.str = psprintf("U&\"%s\"", literalbuf); + + /* + * The backend will truncate the identifier here. We do + * not as it does not change the result. + */ + base_yylval.str = make3_str("U&\"", literalbuf, "\""); return UIDENT; } -{xddouble} { +{xddouble} { addlit(yytext, yyleng); } -{xdinside} { +{xdinside} { addlit(yytext, yyleng); } -<> { mmfatal(PARSE_ERROR, "unterminated quoted identifier"); } +<> { + mmfatal(PARSE_ERROR, "unterminated quoted identifier"); + } {xdstart} { state_before_str_start = YYSTATE; BEGIN(xdc); startlit(); } -{xdcinside} { +{xdcinside} { addlit(yytext, yyleng); } -<> { mmfatal(PARSE_ERROR, "unterminated quoted string"); } +<> { + mmfatal(PARSE_ERROR, "unterminated quoted string"); + } { {typecast} { @@ -819,21 +854,20 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return NOT_EQUALS; } -{informix_special} { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - unput(':'); - } - else - return yytext[0]; +{informix_special} { + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + unput(':'); + } + else + return yytext[0]; } {self} { /* - * We may find a ';' inside a structure - * definition in a TYPE or VAR statement. - * This is not an EOL marker. + * We may find a ';' inside a structure definition in a + * TYPE or VAR statement. This is not an EOL marker. */ if (yytext[0] == ';' && struct_level == 0) BEGIN(C); @@ -878,7 +912,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ for (ic = nchars - 2; ic >= 0; ic--) { - char c = yytext[ic]; + char c = yytext[ic]; + if (c == '~' || c == '!' || c == '@' || c == '#' || c == '^' || c == '&' || c == '|' || c == '`' || c == '?' || @@ -891,11 +926,12 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ * didn't find a qualifying character, so remove * all trailing [+-] */ - do { + do + { nchars--; } while (nchars > 1 && - (yytext[nchars - 1] == '+' || - yytext[nchars - 1] == '-')); + (yytext[nchars - 1] == '+' || + yytext[nchars - 1] == '-')); } } @@ -903,6 +939,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { /* Strip the unwanted chars from the token */ yyless(nchars); + /* * If what we have left is only one char, and it's * one of the characters matching "self", then @@ -912,6 +949,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ if (nchars == 1 && strchr(",()[].;:+-*/%^<>=", yytext[0])) return yytext[0]; + /* * Likewise, if what we have left is two chars, and * those match the tokens ">=", "<=", "=>", "<>" or @@ -933,7 +971,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } } - base_yylval.str = mm_strdup(yytext); + base_yylval.str = loc_strdup(yytext); return Op; } @@ -952,7 +990,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } {ip} { - base_yylval.str = mm_strdup(yytext); + base_yylval.str = loc_strdup(yytext); return IP; } } /* */ @@ -965,7 +1003,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return process_integer_literal(yytext, &base_yylval, 16); } {numeric} { - base_yylval.str = mm_strdup(yytext); + base_yylval.str = loc_strdup(yytext); return FCONST; } {numericfail} { @@ -974,7 +1012,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ return process_integer_literal(yytext, &base_yylval, 10); } {real} { - base_yylval.str = mm_strdup(yytext); + base_yylval.str = loc_strdup(yytext); return FCONST; } {realfail} { @@ -999,16 +1037,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ * Note that some trailing junk is valid in C (such as 100LL), so we * contain this to SQL mode. */ -{decinteger_junk} { - mmfatal(PARSE_ERROR, "trailing junk after numeric literal"); - } -{hexinteger_junk} { - mmfatal(PARSE_ERROR, "trailing junk after numeric literal"); - } -{octinteger_junk} { - mmfatal(PARSE_ERROR, "trailing junk after numeric literal"); - } -{bininteger_junk} { +{integer_junk} { mmfatal(PARSE_ERROR, "trailing junk after numeric literal"); } {numeric_junk} { @@ -1019,7 +1048,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } :{identifier}((("->"|\.){identifier})|(\[{array}\]))* { - base_yylval.str = mm_strdup(yytext+1); + base_yylval.str = loc_strdup(yytext + 1); return CVARIABLE; } @@ -1027,7 +1056,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ /* First check to see if it's a define symbol to expand */ if (!isdefine()) { - int kwvalue; + int kwvalue; /* * User-defined typedefs override SQL keywords, but @@ -1053,10 +1082,10 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ * * The backend will attempt to truncate and case-fold * the identifier, but I see no good reason for ecpg - * to do so; that's just another way that ecpg could get - * out of step with the backend. + * to do so; that's just another way that ecpg could + * get out of step with the backend. */ - base_yylval.str = mm_strdup(yytext); + base_yylval.str = loc_strdup(yytext); return IDENT; } } @@ -1070,75 +1099,82 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ * Begin ECPG-specific rules */ -{exec_sql} { BEGIN(SQL); return SQL_START; } +{exec_sql} { + BEGIN(SQL); + return SQL_START; + } {informix_special} { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - BEGIN(SQL); - return SQL_START; - } - else - return S_ANYTHING; - } -{ccomment} { ECHO; } -{cppinclude} { - if (system_includes) - { - include_next = false; - BEGIN(incl); - } - else - { - base_yylval.str = mm_strdup(yytext); - return CPP_LINE; - } + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + BEGIN(SQL); + return SQL_START; } -{cppinclude_next} { - if (system_includes) - { - include_next = true; - BEGIN(incl); - } - else - { - base_yylval.str = mm_strdup(yytext); - return CPP_LINE; - } + else + return S_ANYTHING; + } +{ccomment} { + ECHO; + } +{cppinclude} { + if (system_includes) + { + include_next = false; + BEGIN(incl); } -{cppline} { - base_yylval.str = mm_strdup(yytext); + else + { + base_yylval.str = loc_strdup(yytext); return CPP_LINE; } -{identifier} { - /* - * Try to detect a function name: - * look for identifiers at the global scope - * keep the last identifier before the first '(' and '{' - */ - if (braces_open == 0 && parenths_open == 0) - { - if (current_function) - free(current_function); - current_function = mm_strdup(yytext); - } - /* Informix uses SQL defines only in SQL space */ - /* however, some defines have to be taken care of for compatibility */ - if ((!INFORMIX_MODE || !isinformixdefine()) && !isdefine()) - { - int kwvalue; + } +{cppinclude_next} { + if (system_includes) + { + include_next = true; + BEGIN(incl); + } + else + { + base_yylval.str = loc_strdup(yytext); + return CPP_LINE; + } + } +{cppline} { + base_yylval.str = loc_strdup(yytext); + return CPP_LINE; + } +{identifier} { + /* + * Try to detect a function name: + * look for identifiers at the global scope + * keep the last identifier before the first '(' and '{' + */ + if (braces_open == 0 && parenths_open == 0) + { + if (current_function) + free(current_function); + current_function = mm_strdup(yytext); + } + /* Informix uses SQL defines only in SQL space */ + /* however, some defines have to be taken care of for compatibility */ + if ((!INFORMIX_MODE || !isinformixdefine()) && !isdefine()) + { + int kwvalue; - kwvalue = ScanCKeywordLookup(yytext); - if (kwvalue >= 0) - return kwvalue; - else - { - base_yylval.str = mm_strdup(yytext); - return IDENT; - } + kwvalue = ScanCKeywordLookup(yytext); + if (kwvalue >= 0) + return kwvalue; + else + { + base_yylval.str = loc_strdup(yytext); + return IDENT; } } -{xcstop} { mmerror(PARSE_ERROR, ET_ERROR, "nested /* ... */ comments"); } + } +{xcstop} { + mmerror(PARSE_ERROR, ET_ERROR, "nested /* ... */ comments"); + } ":" { return ':'; } ";" { return ';'; } "," { return ','; } @@ -1174,44 +1210,46 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ {other} { return S_ANYTHING; } {exec_sql}{define}{space}* { BEGIN(def_ident); } {informix_special}{define}{space}* { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - BEGIN(def_ident); - } - else - { - yyless(1); - return S_ANYTHING; - } + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + BEGIN(def_ident); } -{exec_sql}{undef}{space}* { BEGIN(undef); } + else + { + yyless(1); + return S_ANYTHING; + } + } +{exec_sql}{undef}{space}* { + BEGIN(undef); + } {informix_special}{undef}{space}* { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - BEGIN(undef); - } - else - { - yyless(1); - return S_ANYTHING; - } + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + BEGIN(undef); + } + else + { + yyless(1); + return S_ANYTHING; } + } {identifier}{space}*";" { - struct _defines *ptr, *ptr2 = NULL; - int i; + struct _defines *ptr, + *ptr2 = NULL; + int i; /* - * Skip the ";" and trailing whitespace. Note that yytext - * contains at least one non-space character plus the ";" + * Skip the ";" and trailing whitespace. Note that yytext + * contains at least one non-space character plus the ";" */ - for (i = strlen(yytext)-2; + for (i = strlen(yytext) - 2; i > 0 && ecpg_isspace(yytext[i]); i--) ; - yytext[i+1] = '\0'; - + yytext[i + 1] = '\0'; /* Find and unset any matching define; should be only 1 */ for (ptr = defines; ptr; ptr2 = ptr, ptr = ptr->next) @@ -1237,88 +1275,90 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ BEGIN(C); } {other}|\n { - mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL UNDEF command"); - yyterminate(); + mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL UNDEF command"); + yyterminate(); + } +{exec_sql}{include}{space}* { + BEGIN(incl); } -{exec_sql}{include}{space}* { BEGIN(incl); } {informix_special}{include}{space}* { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - BEGIN(incl); - } - else - { - yyless(1); - return S_ANYTHING; - } + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + BEGIN(incl); } -{exec_sql}{ifdef}{space}* { - if (preproc_tos >= MAX_NESTED_IF-1) - mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); - preproc_tos++; - stacked_if_value[preproc_tos].active = false; - stacked_if_value[preproc_tos].saw_active = false; - stacked_if_value[preproc_tos].else_branch = false; - ifcond = true; - BEGIN(xcond); + else + { + yyless(1); + return S_ANYTHING; } + } +{exec_sql}{ifdef}{space}* { + if (preproc_tos >= MAX_NESTED_IF - 1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = true; + BEGIN(xcond); + } {informix_special}{ifdef}{space}* { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - if (preproc_tos >= MAX_NESTED_IF-1) - mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); - preproc_tos++; - stacked_if_value[preproc_tos].active = false; - stacked_if_value[preproc_tos].saw_active = false; - stacked_if_value[preproc_tos].else_branch = false; - ifcond = true; - BEGIN(xcond); - } - else - { - yyless(1); - return S_ANYTHING; - } + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + if (preproc_tos >= MAX_NESTED_IF - 1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = true; + BEGIN(xcond); } -{exec_sql}{ifndef}{space}* { - if (preproc_tos >= MAX_NESTED_IF-1) - mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); - preproc_tos++; - stacked_if_value[preproc_tos].active = false; - stacked_if_value[preproc_tos].saw_active = false; - stacked_if_value[preproc_tos].else_branch = false; - ifcond = false; - BEGIN(xcond); + else + { + yyless(1); + return S_ANYTHING; } + } +{exec_sql}{ifndef}{space}* { + if (preproc_tos >= MAX_NESTED_IF - 1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = false; + BEGIN(xcond); + } {informix_special}{ifndef}{space}* { - /* are we simulating Informix? */ - if (INFORMIX_MODE) - { - if (preproc_tos >= MAX_NESTED_IF-1) - mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); - preproc_tos++; - stacked_if_value[preproc_tos].active = false; - stacked_if_value[preproc_tos].saw_active = false; - stacked_if_value[preproc_tos].else_branch = false; - ifcond = false; - BEGIN(xcond); - } - else - { - yyless(1); - return S_ANYTHING; - } - } -{exec_sql}{elif}{space}* { - if (preproc_tos == 0) - mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\""); - if (stacked_if_value[preproc_tos].else_branch) - mmfatal(PARSE_ERROR, "missing \"EXEC SQL ENDIF;\""); - ifcond = true; + /* are we simulating Informix? */ + if (INFORMIX_MODE) + { + if (preproc_tos >= MAX_NESTED_IF - 1) + mmfatal(PARSE_ERROR, "too many nested EXEC SQL IFDEF conditions"); + preproc_tos++; + stacked_if_value[preproc_tos].active = false; + stacked_if_value[preproc_tos].saw_active = false; + stacked_if_value[preproc_tos].else_branch = false; + ifcond = false; BEGIN(xcond); } + else + { + yyless(1); + return S_ANYTHING; + } + } +{exec_sql}{elif}{space}* { + if (preproc_tos == 0) + mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\""); + if (stacked_if_value[preproc_tos].else_branch) + mmfatal(PARSE_ERROR, "missing \"EXEC SQL ENDIF;\""); + ifcond = true; + BEGIN(xcond); + } {informix_special}{elif}{space}* { /* are we simulating Informix? */ if (INFORMIX_MODE) @@ -1337,7 +1377,8 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } } -{exec_sql}{else}{space}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ +{exec_sql}{else}{space}*";" { + /* only exec sql endif pops the stack, so take care of duplicated 'else' */ if (preproc_tos == 0) mmfatal(PARSE_ERROR, "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\""); else if (stacked_if_value[preproc_tos].else_branch) @@ -1346,7 +1387,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { stacked_if_value[preproc_tos].else_branch = true; stacked_if_value[preproc_tos].active = - (stacked_if_value[preproc_tos-1].active && + (stacked_if_value[preproc_tos - 1].active && !stacked_if_value[preproc_tos].saw_active); stacked_if_value[preproc_tos].saw_active = true; @@ -1356,7 +1397,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ BEGIN(xskip); } } -{informix_special}{else}{space}*";" { +{informix_special}{else}{space}*";" { /* are we simulating Informix? */ if (INFORMIX_MODE) { @@ -1368,7 +1409,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { stacked_if_value[preproc_tos].else_branch = true; stacked_if_value[preproc_tos].active = - (stacked_if_value[preproc_tos-1].active && + (stacked_if_value[preproc_tos - 1].active && !stacked_if_value[preproc_tos].saw_active); stacked_if_value[preproc_tos].saw_active = true; @@ -1391,11 +1432,11 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ preproc_tos--; if (stacked_if_value[preproc_tos].active) - BEGIN(C); + BEGIN(C); else - BEGIN(xskip); + BEGIN(xskip); } -{informix_special}{endif}{space}*";" { +{informix_special}{endif}{space}*";" { /* are we simulating Informix? */ if (INFORMIX_MODE) { @@ -1416,23 +1457,24 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ } } -{other} { /* ignore */ } +{other} { /* ignore */ } {identifier}{space}*";" { { struct _defines *defptr; unsigned int i; - bool this_active; + bool this_active; /* - * Skip the ";" and trailing whitespace. Note that yytext - * contains at least one non-space character plus the ";" + * Skip the ";" and trailing whitespace. Note that + * yytext contains at least one non-space character + * plus the ";" */ - for (i = strlen(yytext)-2; + for (i = strlen(yytext) - 2; i > 0 && ecpg_isspace(yytext[i]); i--) - ; - yytext[i+1] = '\0'; + /* skip */ ; + yytext[i + 1] = '\0'; /* Does a definition exist? */ for (defptr = defines; defptr; defptr = defptr->next) @@ -1448,7 +1490,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ this_active = (defptr ? ifcond : !ifcond); stacked_if_value[preproc_tos].active = - (stacked_if_value[preproc_tos-1].active && + (stacked_if_value[preproc_tos - 1].active && !stacked_if_value[preproc_tos].saw_active && this_active); stacked_if_value[preproc_tos].saw_active |= this_active; @@ -1460,59 +1502,59 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ BEGIN(xskip); } -{other}|\n { - mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL IFDEF command"); - yyterminate(); - } +{other}|\n { + mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL IFDEF command"); + yyterminate(); + } {identifier} { - newdefsymbol = mm_strdup(yytext); - BEGIN(def); - startlit(); - } -{other}|\n { - mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL DEFINE command"); - yyterminate(); - } -{space}*";" { - struct _defines *ptr; + newdefsymbol = mm_strdup(yytext); + BEGIN(def); + startlit(); + } +{other}|\n { + mmfatal(PARSE_ERROR, "missing identifier in EXEC SQL DEFINE command"); + yyterminate(); + } +{space}*";" { + struct _defines *ptr; - /* Does it already exist? */ - for (ptr = defines; ptr != NULL; ptr = ptr->next) - { - if (strcmp(newdefsymbol, ptr->name) == 0) - { - free(ptr->value); - ptr->value = mm_strdup(literalbuf); - /* Don't leak newdefsymbol */ - free(newdefsymbol); - break; - } - } - if (ptr == NULL) + /* Does it already exist? */ + for (ptr = defines; ptr != NULL; ptr = ptr->next) + { + if (strcmp(newdefsymbol, ptr->name) == 0) { - /* Not present, make a new entry */ - ptr = (struct _defines *) mm_alloc(sizeof(struct _defines)); - - ptr->name = newdefsymbol; + free(ptr->value); ptr->value = mm_strdup(literalbuf); - ptr->cmdvalue = NULL; - ptr->used = NULL; - ptr->next = defines; - defines = ptr; + /* Don't leak newdefsymbol */ + free(newdefsymbol); + break; } - - BEGIN(C); } -[^;] { addlit(yytext, yyleng); } -\<[^\>]+\>{space}*";"? { parse_include(); } + if (ptr == NULL) + { + /* Not present, make a new entry */ + ptr = (struct _defines *) mm_alloc(sizeof(struct _defines)); + + ptr->name = newdefsymbol; + ptr->value = mm_strdup(literalbuf); + ptr->cmdvalue = NULL; + ptr->used = NULL; + ptr->next = defines; + defines = ptr; + } + + BEGIN(C); + } +[^;] { addlit(yytext, yyleng); } +\<[^\>]+\>{space}*";"? { parse_include(); } {dquote}{xdinside}{dquote}{space}*";"? { parse_include(); } -[^;\<\>\"]+";" { parse_include(); } -{other}|\n { +[^;\<\>\"]+";" { parse_include(); } +{other}|\n { mmfatal(PARSE_ERROR, "syntax error in EXEC SQL INCLUDE command"); yyterminate(); } -<> { +<> { if (yy_buffer == NULL) { /* No more input */ @@ -1527,7 +1569,7 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ { /* Revert to previous input source */ struct _yy_buffer *yb = yy_buffer; - int i; + int i; struct _defines *ptr; /* Check to see if we are exiting a macro value */ @@ -1559,11 +1601,12 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+ if (i != 0) output_line_number(); - } } -{other}|\n { mmfatal(PARSE_ERROR, "internal error: unreachable state; please report this to <%s>", PACKAGE_BUGREPORT); } +{other}|\n { + mmfatal(PARSE_ERROR, "internal error: unreachable state; please report this to <%s>", PACKAGE_BUGREPORT); + } %% @@ -1599,15 +1642,15 @@ static void addlit(char *ytext, int yleng) { /* enlarge buffer if needed */ - if ((literallen+yleng) >= literalalloc) + if ((literallen + yleng) >= literalalloc) { do literalalloc *= 2; - while ((literallen+yleng) >= literalalloc); + while ((literallen + yleng) >= literalalloc); literalbuf = (char *) realloc(literalbuf, literalalloc); } /* append new data, add trailing null */ - memcpy(literalbuf+literallen, ytext, yleng); + memcpy(literalbuf + literallen, ytext, yleng); literallen += yleng; literalbuf[literallen] = '\0'; } @@ -1616,7 +1659,7 @@ static void addlitchar(unsigned char ychar) { /* enlarge buffer if needed */ - if ((literallen+1) >= literalalloc) + if ((literallen + 1) >= literalalloc) { literalalloc *= 2; literalbuf = (char *) realloc(literalbuf, literalalloc); @@ -1642,7 +1685,7 @@ process_integer_literal(const char *token, YYSTYPE *lval, int base) if (*endptr != '\0' || errno == ERANGE) { /* integer too large (or contains decimal pt), treat it as a float */ - lval->str = mm_strdup(token); + lval->str = loc_strdup(token); return FCONST; } lval->ival = val; @@ -1655,12 +1698,12 @@ parse_include(void) /* got the include file name */ struct _yy_buffer *yb; struct _include_path *ip; - char inc_file[MAXPGPATH]; + char inc_file[MAXPGPATH]; unsigned int i; yb = mm_alloc(sizeof(struct _yy_buffer)); - yb->buffer = YY_CURRENT_BUFFER; + yb->buffer = YY_CURRENT_BUFFER; yb->lineno = yylineno; yb->filename = input_filename; yb->next = yy_buffer; @@ -1668,10 +1711,10 @@ parse_include(void) yy_buffer = yb; /* - * skip the ";" if there is one and trailing whitespace. Note that - * yytext contains at least one non-space character plus the ";" + * skip the ";" if there is one and trailing whitespace. Note that yytext + * contains at least one non-space character plus the ";" */ - for (i = strlen(yytext)-2; + for (i = strlen(yytext) - 2; i > 0 && ecpg_isspace(yytext[i]); i--) ; @@ -1679,17 +1722,21 @@ parse_include(void) if (yytext[i] == ';') i--; - yytext[i+1] = '\0'; + yytext[i + 1] = '\0'; yyin = NULL; /* If file name is enclosed in '"' remove these and look only in '.' */ - /* Informix does look into all include paths though, except filename starts with '/' */ + + /* + * Informix does look into all include paths though, except filename + * starts with '/' + */ if (yytext[0] == '"' && yytext[i] == '"' && ((compat != ECPG_COMPAT_INFORMIX && compat != ECPG_COMPAT_INFORMIX_SE) || yytext[1] == '/')) { yytext[i] = '\0'; - memmove(yytext, yytext+1, strlen(yytext)); + memmove(yytext, yytext + 1, strlen(yytext)); strlcpy(inc_file, yytext, sizeof(inc_file)); yyin = fopen(inc_file, "r"); @@ -1708,7 +1755,7 @@ parse_include(void) if ((yytext[0] == '"' && yytext[i] == '"') || (yytext[0] == '<' && yytext[i] == '>')) { yytext[i] = '\0'; - memmove(yytext, yytext+1, strlen(yytext)); + memmove(yytext, yytext + 1, strlen(yytext)); } for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next) @@ -1718,7 +1765,7 @@ parse_include(void) fprintf(stderr, _("Error: include path \"%s/%s\" is too long on line %d, skipping\n"), ip->path, yytext, yylineno); continue; } - snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext); + snprintf(inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext); yyin = fopen(inc_file, "r"); if (!yyin) { @@ -1728,10 +1775,14 @@ parse_include(void) yyin = fopen(inc_file, "r"); } } - /* if the command was "include_next" we have to disregard the first hit */ + + /* + * if the command was "include_next" we have to disregard the + * first hit + */ if (yyin && include_next) { - fclose (yyin); + fclose(yyin); yyin = NULL; include_next = false; } @@ -1741,7 +1792,7 @@ parse_include(void) mmfatal(NO_INCLUDE_FILE, "could not open include file \"%s\" on line %d", yytext, yylineno); input_filename = mm_strdup(inc_file); - yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE)); + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); yylineno = 1; output_line_number(); @@ -1786,7 +1837,7 @@ isdefine(void) yb = mm_alloc(sizeof(struct _yy_buffer)); - yb->buffer = YY_CURRENT_BUFFER; + yb->buffer = YY_CURRENT_BUFFER; yb->lineno = yylineno; yb->filename = mm_strdup(input_filename); yb->next = yy_buffer; @@ -1796,9 +1847,9 @@ isdefine(void) ptr->used = yb; /* - * We use yy_scan_string which will copy the value, so there's - * no need to worry about a possible undef happening while we - * are still scanning it. + * We use yy_scan_string which will copy the value, so there's no + * need to worry about a possible undef happening while we are + * still scanning it. */ yy_scan_string(ptr->value); return true; @@ -1830,7 +1881,7 @@ isinformixdefine(void) yb = mm_alloc(sizeof(struct _yy_buffer)); - yb->buffer = YY_CURRENT_BUFFER; + yb->buffer = YY_CURRENT_BUFFER; yb->lineno = yylineno; yb->filename = mm_strdup(input_filename); yb->next = yy_buffer; diff --git a/src/interfaces/ecpg/preproc/po/de.po b/src/interfaces/ecpg/preproc/po/de.po index cf9fa6aaee452..43101dd665a47 100644 --- a/src/interfaces/ecpg/preproc/po/de.po +++ b/src/interfaces/ecpg/preproc/po/de.po @@ -1,15 +1,15 @@ # German message translation file for ecpg -# Copyright (C) 2009-2024 PostgreSQL Global Development Group +# Copyright (C) 2009-2025 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-12 17:10+0000\n" -"PO-Revision-Date: 2024-03-12 21:11+0100\n" +"POT-Creation-Date: 2025-04-26 03:40+0000\n" +"PO-Revision-Date: 2025-04-26 12:54+0200\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -18,47 +18,47 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: descriptor.c:64 +#: descriptor.c:63 #, c-format msgid "variable \"%s\" must have a numeric type" msgstr "Variable »%s« muss einen numerischen Typ haben" -#: descriptor.c:124 descriptor.c:155 +#: descriptor.c:119 descriptor.c:149 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "Deskriptor %s gebunden an Verbindung %s existiert nicht" -#: descriptor.c:126 descriptor.c:157 +#: descriptor.c:121 descriptor.c:151 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "Deskriptor %s gebunden an die Standardverbindung existiert nicht" -#: descriptor.c:172 descriptor.c:224 +#: descriptor.c:166 descriptor.c:218 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "Deskriptorkopfelement »%d« existiert nicht" -#: descriptor.c:194 +#: descriptor.c:188 #, c-format msgid "nullable is always 1" msgstr "nullable ist immer 1" -#: descriptor.c:197 +#: descriptor.c:191 #, c-format msgid "key_member is always 0" msgstr "key_member ist immer 0" -#: descriptor.c:291 +#: descriptor.c:285 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "Deskriptorelement »%s« ist nicht implementiert" -#: descriptor.c:301 +#: descriptor.c:295 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "Deskriptorelement »%s« kann nicht gesetzt werden" -#: ecpg.c:36 +#: ecpg.c:37 #, c-format msgid "" "%s is the PostgreSQL embedded SQL preprocessor for C programs.\n" @@ -67,7 +67,7 @@ msgstr "" "%s ist der Embedded-SQL-Präprozessor von PostgreSQL für C-Programme.\n" "\n" -#: ecpg.c:38 +#: ecpg.c:39 #, c-format msgid "" "Usage:\n" @@ -78,12 +78,12 @@ msgstr "" " %s [OPTION]... DATEI...\n" "\n" -#: ecpg.c:41 +#: ecpg.c:42 #, c-format msgid "Options:\n" msgstr "Optionen:\n" -#: ecpg.c:42 +#: ecpg.c:43 #, c-format msgid "" " -c automatically generate C code from embedded SQL code;\n" @@ -92,7 +92,7 @@ msgstr "" " -c automatisch C-Code aus eingebettetem SQL-Code erzeugen;\n" " betrifft EXEC SQL TYPE\n" -#: ecpg.c:44 +#: ecpg.c:45 #, c-format msgid "" " -C MODE set compatibility mode; MODE can be one of\n" @@ -101,37 +101,37 @@ msgstr "" " -C MODUS Kompatibilitätsmodus setzen; MODUS kann sein:\n" " »INFORMIX«, »INFORMIX_SE«, »ORACLE«\n" -#: ecpg.c:47 +#: ecpg.c:48 #, c-format msgid " -d generate parser debug output\n" msgstr " -d Parser-Debug-Ausgabe erzeugen\n" -#: ecpg.c:49 +#: ecpg.c:50 #, c-format msgid " -D SYMBOL define SYMBOL\n" msgstr " -D SYMBOL SYMBOL definieren\n" -#: ecpg.c:50 +#: ecpg.c:51 #, c-format msgid " -h parse a header file, this option includes option \"-c\"\n" msgstr " -h eine Headerdatei parsen, schließt Option »-c« ein\n" -#: ecpg.c:51 +#: ecpg.c:52 #, c-format msgid " -i parse system include files as well\n" msgstr " -i Systemheaderdateien ebenfalls parsen\n" -#: ecpg.c:52 +#: ecpg.c:53 #, c-format msgid " -I DIRECTORY search DIRECTORY for include files\n" msgstr " -I VERZ VERZ nach Include-Dateien durchsuchen\n" -#: ecpg.c:53 +#: ecpg.c:54 #, c-format msgid " -o OUTFILE write result to OUTFILE\n" msgstr " -o DATEI Ausgabe in DATEI schreiben\n" -#: ecpg.c:54 +#: ecpg.c:55 #, c-format msgid "" " -r OPTION specify run-time behavior; OPTION can be:\n" @@ -140,27 +140,27 @@ msgstr "" " -r OPTION Laufzeitverhalten bestimmen; OPTION kann sein:\n" " »no_indicator«, »prepare«, »questionmarks«\n" -#: ecpg.c:56 +#: ecpg.c:57 #, c-format msgid " --regression run in regression testing mode\n" msgstr " --regression Regressiontestmodus verwenden\n" -#: ecpg.c:57 +#: ecpg.c:58 #, c-format msgid " -t turn on autocommit of transactions\n" msgstr " -t Autocommit von Transaktionen anschalten\n" -#: ecpg.c:58 +#: ecpg.c:59 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n" -#: ecpg.c:59 +#: ecpg.c:60 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n" -#: ecpg.c:60 +#: ecpg.c:61 #, c-format msgid "" "\n" @@ -171,7 +171,7 @@ msgstr "" "Wenn keine Ausgabedatei angegeben ist, dann wird .c an den Namen der\n" "Eingabedatei angehängt und vorher .pgc, falls vorhanden, entfernt.\n" -#: ecpg.c:62 +#: ecpg.c:63 #, c-format msgid "" "\n" @@ -180,474 +180,478 @@ msgstr "" "\n" "Berichten Sie Fehler an <%s>.\n" -#: ecpg.c:63 +#: ecpg.c:64 #, c-format msgid "%s home page: <%s>\n" msgstr "%s Homepage: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: konnte Pfad des eigenen Programs nicht finden\n" -#: ecpg.c:184 ecpg.c:235 ecpg.c:249 ecpg.c:275 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n" -#: ecpg.c:192 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: Unterstützung für Parserdebugging (-d) nicht verfügbar\n" -#: ecpg.c:219 ecpg.c:334 ecpg.c:345 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format msgid "%s: could not open file \"%s\": %m\n" msgstr "%s: konnte Datei »%s« nicht öffnen: %m\n" -#: ecpg.c:263 +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, der PostgreSQL-Embedded-C-Präprozessor, Version %s\n" -#: ecpg.c:265 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... Suche beginnt hier:\n" -#: ecpg.c:268 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "Ende der Suchliste\n" -#: ecpg.c:274 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: keine Eingabedateien angegeben\n" -#: ecpg.c:478 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "Cursor »%s« wurde deklariert aber nicht geöffnet" -#: ecpg.c:491 preproc.y:130 +#: ecpg.c:504 util.c:75 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "konnte Ausgabedatei »%s« nicht entfernen\n" -#: pgc.l:520 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "/*-Kommentar nicht abgeschlossen" -#: pgc.l:537 +#: pgc.l:560 #, c-format msgid "unterminated bit string literal" msgstr "Bitkettenkonstante nicht abgeschlossen" -#: pgc.l:545 +#: pgc.l:570 #, c-format msgid "unterminated hexadecimal string literal" msgstr "hexadezimale Zeichenkette nicht abgeschlossen" -#: pgc.l:620 +#: pgc.l:644 #, c-format msgid "invalid bit string literal" msgstr "ungültige Bitkettenkonstante" -#: pgc.l:625 +#: pgc.l:649 #, c-format msgid "invalid hexadecimal string literal" msgstr "ungültige hexadezimale Zeichenkettenkonstante" -#: pgc.l:643 +#: pgc.l:667 #, c-format msgid "unhandled previous state in xqs\n" msgstr "unbehandelter vorheriger Zustand in xqs\n" -#: pgc.l:669 pgc.l:778 +#: pgc.l:700 pgc.l:820 #, c-format msgid "unterminated quoted string" msgstr "Zeichenkette in Anführungszeichen nicht abgeschlossen" -#: pgc.l:720 +#: pgc.l:753 #, c-format msgid "unterminated dollar-quoted string" msgstr "Dollar-Quotes nicht abgeschlossen" -#: pgc.l:738 pgc.l:758 +#: pgc.l:772 pgc.l:793 #, c-format msgid "zero-length delimited identifier" msgstr "Bezeichner in Anführungszeichen hat Länge null" -#: pgc.l:769 +#: pgc.l:809 #, c-format msgid "unterminated quoted identifier" msgstr "Bezeichner in Anführungszeichen nicht abgeschlossen" -#: pgc.l:938 +#: pgc.l:985 +#, c-format +msgid "parameter number too large" +msgstr "Parameternummer zu groß" + +#: pgc.l:990 #, c-format msgid "trailing junk after parameter" msgstr "Müll folgt auf Parameter" -#: pgc.l:990 pgc.l:993 pgc.l:996 pgc.l:999 pgc.l:1002 pgc.l:1005 +#: pgc.l:1042 pgc.l:1045 pgc.l:1048 #, c-format msgid "trailing junk after numeric literal" msgstr "Müll folgt auf numerische Konstante" -#: pgc.l:1127 +#: pgc.l:1177 #, c-format msgid "nested /* ... */ comments" msgstr "geschachtelte /* ... */-Kommentare" -#: pgc.l:1220 +#: pgc.l:1279 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "fehlender Bezeichner im Befehl EXEC SQL UNDEF" -#: pgc.l:1238 pgc.l:1251 pgc.l:1267 pgc.l:1280 +#: pgc.l:1299 pgc.l:1312 pgc.l:1328 pgc.l:1341 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "zu viele verschachtelte EXEC SQL IFDEF-Bedingungen" -#: pgc.l:1296 pgc.l:1307 pgc.l:1322 pgc.l:1344 +#: pgc.l:1357 pgc.l:1368 pgc.l:1384 pgc.l:1406 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "passendes »EXEC SQL IFDEF« / »EXEC SQL IFNDEF« fehlt" -#: pgc.l:1298 pgc.l:1309 pgc.l:1490 +#: pgc.l:1359 pgc.l:1370 pgc.l:1565 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "»EXEC SQL ENDIF;« fehlt" -#: pgc.l:1324 pgc.l:1346 +#: pgc.l:1386 pgc.l:1408 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "mehr als ein EXEC SQL ENDIF" -#: pgc.l:1369 pgc.l:1383 +#: pgc.l:1431 pgc.l:1445 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "unzusammenhängendes EXEC SQL ENDIF" -#: pgc.l:1438 +#: pgc.l:1507 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "fehlender Bezeichner im Befehl EXEC SQL IFDEF" -#: pgc.l:1447 +#: pgc.l:1516 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "fehlender Bezeichner im Befehl EXEC SQL DEFINE" -#: pgc.l:1480 +#: pgc.l:1554 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "Syntaxfehler im Befehl EXEC SQL INCLUDE" -#: pgc.l:1530 +#: pgc.l:1609 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "interner Fehler: unerreichbarer Zustand; bitte an <%s> berichten" -#: pgc.l:1682 +#: pgc.l:1766 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "Fehler: Include-Pfad »%s/%s« ist zu lang auf Zeile %d, wird übersprungen\n" -#: pgc.l:1705 +#: pgc.l:1793 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "konnte Include-Datei »%s« nicht öffnen auf Zeile %d" -#: preproc.y:31 +#: preproc.y:28 msgid "syntax error" msgstr "Syntaxfehler" -#: preproc.y:84 -#, c-format -msgid "WARNING: " -msgstr "WARNUNG: " - -#: preproc.y:87 -#, c-format -msgid "ERROR: " -msgstr "FEHLER: " - -#: preproc.y:514 +#: preproc.y:467 #, c-format msgid "cursor \"%s\" does not exist" msgstr "Cursor »%s« existiert nicht" -#: preproc.y:543 +#: preproc.y:503 #, c-format msgid "initializer not allowed in type definition" msgstr "Initialisierungswert nicht erlaubt in Typdefinition" -#: preproc.y:545 +#: preproc.y:505 #, c-format msgid "type name \"string\" is reserved in Informix mode" msgstr "Typname »string« ist im Informix-Modus reserviert" -#: preproc.y:552 preproc.y:18523 +#: preproc.y:512 preproc.y:8822 #, c-format msgid "type \"%s\" is already defined" msgstr "Typ »%s« ist bereits definiert" -#: preproc.y:577 preproc.y:19158 preproc.y:19480 variable.c:625 +#: preproc.y:539 preproc.y:9536 preproc.y:9881 variable.c:652 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "mehrdimensionale Arrays für einfache Datentypen werden nicht unterstützt" -#: preproc.y:599 +#: preproc.y:562 #, c-format msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "Verbindung %s wird mit %s überschrieben, durch DECLARE-Anweisung %s" -#: preproc.y:1810 +#: preproc.y:932 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "AT-Option ist nicht erlaubt im Befehl CLOSE DATABASE" -#: preproc.y:2060 +#: preproc.y:1184 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "AT-Option ist nicht erlaubt im Befehl CONNECT" -#: preproc.y:2100 +#: preproc.y:1221 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "AT-Option ist nicht erlaubt im Befehl DISCONNECT" -#: preproc.y:2155 +#: preproc.y:1274 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "AT-Option ist nicht erlaubt im Befehl SET CONNECTION" -#: preproc.y:2177 +#: preproc.y:1292 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "AT-Option ist nicht erlaubt im TYPE-Befehl" -#: preproc.y:2186 +#: preproc.y:1300 #, c-format msgid "AT option not allowed in VAR statement" msgstr "AT-Option ist nicht erlaubt im VAR-Befehl" -#: preproc.y:2193 +#: preproc.y:1307 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "AT-Option ist nicht erlaubt im WHENEVER-Befehl" -#: preproc.y:2318 preproc.y:2490 preproc.y:2495 preproc.y:2607 preproc.y:4317 -#: preproc.y:4391 preproc.y:4982 preproc.y:5515 preproc.y:5853 preproc.y:6057 -#: preproc.y:6158 preproc.y:7722 preproc.y:9330 preproc.y:9335 preproc.y:12308 +#: preproc.y:1375 preproc.y:1498 preproc.y:2259 preproc.y:2585 preproc.y:3016 +#: preproc.y:3103 preproc.y:6086 #, c-format msgid "unsupported feature will be passed to server" msgstr "nicht mehr unterstütztes Feature wird an Server weitergereicht werden" -#: preproc.y:2865 +#: preproc.y:1610 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL ist nicht implementiert" -#: preproc.y:3577 +#: preproc.y:1895 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN ist nicht implementiert" -#: preproc.y:10385 preproc.y:18020 +#: preproc.y:5146 preproc.y:8273 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "»database« kann im INFORMIX-Modus nicht als Cursorname verwendet werden" -#: preproc.y:10392 preproc.y:18030 +#: preproc.y:5153 preproc.y:8283 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "Verwendung der Variable »%s« in verschiedenen DECLARE-Anweisungen wird nicht unterstützt" -#: preproc.y:10394 preproc.y:18032 +#: preproc.y:5155 preproc.y:8285 #, c-format msgid "cursor \"%s\" is already defined" msgstr "Cursor »%s« ist bereits definiert" -#: preproc.y:10868 +#: preproc.y:5402 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "nicht mehr unterstützte Syntax LIMIT x,y wird an Server weitergereicht" -#: preproc.y:17712 preproc.y:17719 +#: preproc.y:7921 preproc.y:7929 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS kann INTO nicht verwenden" -#: preproc.y:17755 +#: preproc.y:7974 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "»@« erwartet, »%s« gefunden" -#: preproc.y:17767 +#: preproc.y:7986 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "er werden nur die Protokolle »tcp« und »unix« und der Datenbanktyp »postgresql« unterstützt" -#: preproc.y:17770 +#: preproc.y:7989 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "»://« erwartet, »%s« gefunden" -#: preproc.y:17775 +#: preproc.y:7994 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unix-Domain-Sockets funktionieren nur mit »localhost«, aber nicht mit »%s«" -#: preproc.y:17801 +#: preproc.y:8021 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "»postgresql« erwartet, »%s« gefunden" -#: preproc.y:17804 +#: preproc.y:8024 #, c-format msgid "invalid connection type: %s" msgstr "ungültiger Verbindungstyp: %s" -#: preproc.y:17813 +#: preproc.y:8033 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "»@« oder »://« erwartet, »%s« gefunden" -#: preproc.y:17888 preproc.y:17906 +#: preproc.y:8131 preproc.y:8149 #, c-format msgid "invalid data type" msgstr "ungültiger Datentyp" -#: preproc.y:17917 preproc.y:17934 +#: preproc.y:8160 preproc.y:8177 #, c-format msgid "incomplete statement" msgstr "unvollständige Anweisung" -#: preproc.y:17920 preproc.y:17937 +#: preproc.y:8163 preproc.y:8180 #, c-format msgid "unrecognized token \"%s\"" msgstr "nicht erkanntes Token »%s«" -#: preproc.y:17982 +#: preproc.y:8235 #, c-format msgid "name \"%s\" is already declared" msgstr "Name »%s« ist bereits deklariert" -#: preproc.y:18271 +#: preproc.y:8538 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "nur die Datentypen NUMERIC und DECIMAL haben Argumente für Präzision und Skala" -#: preproc.y:18342 +#: preproc.y:8637 #, c-format msgid "interval specification not allowed here" msgstr "Intervallangabe hier nicht erlaubt" -#: preproc.y:18498 preproc.y:18550 +#: preproc.y:8793 preproc.y:8851 #, c-format msgid "too many levels in nested structure/union definition" msgstr "zu viele Ebenen in verschachtelter Definition von Struktur/Union" -#: preproc.y:18673 +#: preproc.y:8986 #, c-format msgid "pointers to varchar are not implemented" msgstr "Zeiger auf varchar sind nicht implementiert" -#: preproc.y:19124 +#: preproc.y:9501 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "Initialisierungswert nicht erlaubt in Befehl EXEC SQL VAR" -#: preproc.y:19438 +#: preproc.y:9824 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "Array aus Indikatoren bei der Eingabe nicht erlaubt" -#: preproc.y:19625 +#: preproc.y:10058 #, c-format msgid "operator not allowed in variable definition" msgstr "Operator nicht erlaubt in Variablendefinition" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19666 +#: preproc.y:10103 #, c-format msgid "%s at or near \"%s\"" msgstr "%s bei »%s«" -#: type.c:18 type.c:30 -#, c-format -msgid "out of memory" -msgstr "Speicher aufgebraucht" - -#: type.c:214 type.c:685 +#: type.c:191 type.c:661 #, c-format msgid "unrecognized variable type code %d" msgstr "unbekannter Variablentypcode %d" -#: type.c:263 +#: type.c:240 #, c-format msgid "variable \"%s\" is hidden by a local variable of a different type" msgstr "Variable »%s« wird durch eine lokale Variable eines anderen Typs versteckt" -#: type.c:265 +#: type.c:242 #, c-format msgid "variable \"%s\" is hidden by a local variable" msgstr "Variable »%s« wird durch eine lokale Variable versteckt" -#: type.c:277 +#: type.c:254 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable of a different type" msgstr "Indikatorvariable »%s« wird durch eine lokale Variable eines anderen Typs versteckt" -#: type.c:279 +#: type.c:256 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable" msgstr "Indikatorvariable »%s« wird durch eine lokale Variable versteckt" -#: type.c:287 +#: type.c:264 #, c-format msgid "indicator for array/pointer has to be array/pointer" msgstr "Indikator für Array/Zeiger muss Array/Zeiger sein" -#: type.c:291 +#: type.c:268 #, c-format msgid "nested arrays are not supported (except strings)" msgstr "verschachtelte Arrays werden nicht unterstützt (außer Zeichenketten)" -#: type.c:333 +#: type.c:310 #, c-format msgid "indicator for struct has to be a struct" msgstr "Indikator für struct muss ein struct sein" -#: type.c:353 type.c:374 type.c:394 +#: type.c:330 type.c:351 type.c:371 #, c-format msgid "indicator for simple data type has to be simple" msgstr "Indikator für einfachen Typ muss einfachen Typ haben" -#: type.c:625 +#: type.c:602 #, c-format msgid "indicator struct \"%s\" has too few members" msgstr "Indikator-Struct »%s« hat zu wenige Mitglieder" -#: type.c:633 +#: type.c:610 #, c-format msgid "indicator struct \"%s\" has too many members" msgstr "Indikator-Struct »%s« hat zu viele Mitglieder" -#: type.c:744 +#: type.c:723 #, c-format msgid "unrecognized descriptor item code %d" msgstr "unbekannter Deskriptorelementcode %d" +#: util.c:26 +#, c-format +msgid "WARNING: " +msgstr "WARNUNG: " + +#: util.c:29 +#, c-format +msgid "ERROR: " +msgstr "FEHLER: " + +#: util.c:90 util.c:102 +#, c-format +msgid "out of memory" +msgstr "Speicher aufgebraucht" + #: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "falsch geformte Variable »%s«" -#: variable.c:138 +#: variable.c:138 variable.c:237 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "Variable »%s« ist kein Zeiger" @@ -667,39 +671,44 @@ msgstr "Variable »%s« ist keine Struktur oder Union" msgid "variable \"%s\" is not an array" msgstr "Variable »%s« ist kein Array" -#: variable.c:232 variable.c:254 +#: variable.c:220 +#, c-format +msgid "unmatched bracket in variable \"%s\"" +msgstr "eckige Klammer ohne Gegenstück in Variable »%s«" + +#: variable.c:235 variable.c:258 #, c-format msgid "variable \"%s\" is not declared" msgstr "Variable »%s« ist nicht deklariert" -#: variable.c:493 +#: variable.c:517 #, c-format msgid "indicator variable must have an integer type" msgstr "Indikatorvariable muss einen ganzzahligen Typ haben" -#: variable.c:510 +#: variable.c:534 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "unbekannter Datentypname »%s«" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:548 variable.c:556 variable.c:573 variable.c:576 #, c-format msgid "multidimensional arrays are not supported" msgstr "mehrdimensionale Arrays werden nicht unterstützt" -#: variable.c:538 +#: variable.c:565 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "Zeiger mit mehr als 2 Ebenen werden nicht unterstützt; %d Ebene gefunden" msgstr[1] "Zeiger mit mehr als 2 Ebenen werden nicht unterstützt; %d Ebenen gefunden" -#: variable.c:543 +#: variable.c:570 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "Zeiger auf Zeiger wird für diesen Datentyp nicht unterstützt" -#: variable.c:563 +#: variable.c:590 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "mehrdimensionale Arrays für Strukturen werden nicht unterstützt" diff --git a/src/interfaces/ecpg/preproc/po/es.po b/src/interfaces/ecpg/preproc/po/es.po index 5a550b56e1882..f8e3c4a34ecc1 100644 --- a/src/interfaces/ecpg/preproc/po/es.po +++ b/src/interfaces/ecpg/preproc/po/es.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: ecpg (PostgreSQL) 16\n" +"Project-Id-Version: ecpg (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:10+0000\n" -"PO-Revision-Date: 2023-05-22 12:05+0200\n" +"POT-Creation-Date: 2025-02-16 19:40+0000\n" +"PO-Revision-Date: 2024-11-16 14:23+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -191,177 +191,177 @@ msgstr "" msgid "%s home page: <%s>\n" msgstr "Sitio web de %s: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: no se pudo localizar la ruta de mi propio ejecutable\n" -#: ecpg.c:184 ecpg.c:235 ecpg.c:249 ecpg.c:275 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Utilice «%s --help» para obtener mayor información.\n" -#: ecpg.c:192 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: la depuración del analizador (parser, -d) no está disponible)\n" -#: ecpg.c:219 ecpg.c:334 ecpg.c:345 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s: no se pudo abrir el archivo «%s»: %s\n" +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s: no se pudo abrir el archivo «%s»: %m\n" -#: ecpg.c:263 +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, el preprocesador de C incrustado de PostgreSQL, versión %s\n" -#: ecpg.c:265 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... la búsqueda comienza aquí:\n" -#: ecpg.c:268 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "fin de la lista de búsqueda\n" -#: ecpg.c:274 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: no se especificaron archivos de entrada\n" -#: ecpg.c:478 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "el cursor «%s» fue declarado pero no abierto" -#: ecpg.c:491 preproc.y:130 +#: ecpg.c:504 preproc.y:130 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "no se pudo eliminar el archivo de salida «%s»\n" -#: pgc.l:520 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "comentario /* no cerrado" -#: pgc.l:537 +#: pgc.l:559 #, c-format msgid "unterminated bit string literal" msgstr "una cadena de bits está inconclusa" -#: pgc.l:545 +#: pgc.l:567 #, c-format msgid "unterminated hexadecimal string literal" msgstr "una cadena hexadecimal está inconclusa" -#: pgc.l:620 +#: pgc.l:642 #, c-format msgid "invalid bit string literal" msgstr "cadena de bits no válida" -#: pgc.l:625 +#: pgc.l:647 #, c-format msgid "invalid hexadecimal string literal" msgstr "cadena hexadecimal no válida" -#: pgc.l:643 +#: pgc.l:665 #, c-format msgid "unhandled previous state in xqs\n" msgstr "estado previo no manejado en xqs\n" -#: pgc.l:669 pgc.l:778 +#: pgc.l:691 pgc.l:800 #, c-format msgid "unterminated quoted string" msgstr "una cadena en comillas está inconclusa" -#: pgc.l:720 +#: pgc.l:742 #, c-format msgid "unterminated dollar-quoted string" msgstr "una cadena separada por $ está inconclusa" -#: pgc.l:738 pgc.l:758 +#: pgc.l:760 pgc.l:780 #, c-format msgid "zero-length delimited identifier" msgstr "identificador delimitado de longitud cero" -#: pgc.l:769 +#: pgc.l:791 #, c-format msgid "unterminated quoted identifier" msgstr "un identificador en comillas está inconcluso" -#: pgc.l:938 +#: pgc.l:960 #, c-format msgid "trailing junk after parameter" msgstr "basura sigue después de un parámetro" -#: pgc.l:990 pgc.l:993 pgc.l:996 pgc.l:999 pgc.l:1002 pgc.l:1005 +#: pgc.l:1012 pgc.l:1015 pgc.l:1018 #, c-format msgid "trailing junk after numeric literal" msgstr "basura sigue después de un literal numérico" -#: pgc.l:1127 +#: pgc.l:1141 #, c-format msgid "nested /* ... */ comments" msgstr "comentarios /* ... */ anidados" -#: pgc.l:1220 +#: pgc.l:1240 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "falta un identificador en la orden EXEC SQL UNDEF" -#: pgc.l:1238 pgc.l:1251 pgc.l:1267 pgc.l:1280 +#: pgc.l:1258 pgc.l:1271 pgc.l:1287 pgc.l:1300 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "demasiadas condiciones EXEC SQL IFDEF anidadas" -#: pgc.l:1296 pgc.l:1307 pgc.l:1322 pgc.l:1344 +#: pgc.l:1316 pgc.l:1327 pgc.l:1342 pgc.l:1364 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "falta el «EXEC SQL IFDEF» / «EXEC SQL IFNDEF»" -#: pgc.l:1298 pgc.l:1309 pgc.l:1490 +#: pgc.l:1318 pgc.l:1329 pgc.l:1522 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "falta el «EXEC SQL ENDIF;»" -#: pgc.l:1324 pgc.l:1346 +#: pgc.l:1344 pgc.l:1366 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "hay más de un EXEC SQL ELSE" -#: pgc.l:1369 pgc.l:1383 +#: pgc.l:1389 pgc.l:1403 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "EXEC SQL ENDIF sin coincidencia" -#: pgc.l:1438 +#: pgc.l:1464 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "identificador faltante en la orden EXEC SQL IFDEF" -#: pgc.l:1447 +#: pgc.l:1473 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "identificador faltante en la orden EXEC SQL DEFINE" -#: pgc.l:1480 +#: pgc.l:1511 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "error de sintaxis en orden EXEC SQL INCLUDE" -#: pgc.l:1530 +#: pgc.l:1566 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "error interno: estado no esperado; por favor reporte a <%s>" -#: pgc.l:1682 +#: pgc.l:1718 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "Error: ruta de inclusión «%s/%s» es demasiada larga en la línea %d, omitiendo\n" -#: pgc.l:1705 +#: pgc.l:1741 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "no se pudo abrir el archivo a incluir «%s» en la línea %d" @@ -395,12 +395,12 @@ msgstr "inicializador no permitido en definición de tipo" msgid "type name \"string\" is reserved in Informix mode" msgstr "el nombre de tipo «string» está reservado en modo Informix" -#: preproc.y:552 preproc.y:18392 +#: preproc.y:552 preproc.y:19034 #, c-format msgid "type \"%s\" is already defined" msgstr "el tipo «%s» ya está definido" -#: preproc.y:577 preproc.y:19027 preproc.y:19349 variable.c:625 +#: preproc.y:577 preproc.y:19669 preproc.y:19991 variable.c:624 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "los arrays multidimensionales para tipos de datos simples no están soportados" @@ -410,175 +410,174 @@ msgstr "los arrays multidimensionales para tipos de datos simples no están sopo msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "la conexión %s es sobrescrita con %s por la sentencia DECLARE %s" -#: preproc.y:1792 +#: preproc.y:1831 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "la opción AT no está permitida en la sentencia CLOSE DATABASE" -#: preproc.y:2042 +#: preproc.y:2081 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "la opción AT no está permitida en la sentencia CONNECT" -#: preproc.y:2082 +#: preproc.y:2121 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "la opción AT no está permitida en la sentencia DISCONNECT" -#: preproc.y:2137 +#: preproc.y:2176 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "la opción AT no está permitida en la sentencia SET CONNECTION" -#: preproc.y:2159 +#: preproc.y:2198 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "la opción AT no está permitida en la sentencia TYPE" -#: preproc.y:2168 +#: preproc.y:2207 #, c-format msgid "AT option not allowed in VAR statement" msgstr "la opción AT no está permitida en la sentencia VAR" -#: preproc.y:2175 +#: preproc.y:2214 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "la opción AT no está permitida en la sentencia WHENEVER" -#: preproc.y:2300 preproc.y:2472 preproc.y:2477 preproc.y:2589 preproc.y:4248 -#: preproc.y:4322 preproc.y:4913 preproc.y:5446 preproc.y:5784 preproc.y:6084 -#: preproc.y:7648 preproc.y:9252 preproc.y:9257 preproc.y:12206 +#: preproc.y:2339 preproc.y:2626 preproc.y:4349 preproc.y:5021 preproc.y:5891 +#: preproc.y:6095 preproc.y:6196 preproc.y:12460 #, c-format msgid "unsupported feature will be passed to server" msgstr "característica no soportada será pasada al servidor" -#: preproc.y:2847 +#: preproc.y:2884 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL no está implementado" -#: preproc.y:3531 +#: preproc.y:3596 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN no está implementado" -#: preproc.y:10303 preproc.y:17889 +#: preproc.y:10444 preproc.y:18503 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "no se puede usar «database» como nombre de cursor en modo INFORMIX" -#: preproc.y:10310 preproc.y:17899 +#: preproc.y:10451 preproc.y:18513 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "el uso de la variable «%s» en diferentes sentencias declare no está soportado" -#: preproc.y:10312 preproc.y:17901 +#: preproc.y:10453 preproc.y:18515 #, c-format msgid "cursor \"%s\" is already defined" msgstr "el cursor «%s» ya está definido" -#: preproc.y:10786 +#: preproc.y:10927 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "la sintaxis LIMIT #,# que ya no está soportada ha sido pasada al servidor" -#: preproc.y:17581 preproc.y:17588 +#: preproc.y:18195 preproc.y:18202 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS no puede especificar INTO" -#: preproc.y:17624 +#: preproc.y:18238 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "se esperaba «@», se encontró «%s»" -#: preproc.y:17636 +#: preproc.y:18250 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "sólo los protocolos «tcp» y «unix» y tipo de bases de datos «postgresql» están soportados" -#: preproc.y:17639 +#: preproc.y:18253 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "se esperaba «://», se encontró «%s»" -#: preproc.y:17644 +#: preproc.y:18258 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "los sockets de dominio unix sólo trabajan en «localhost» pero no en «%s»" -#: preproc.y:17670 +#: preproc.y:18284 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "se esperaba «postgresql», se encontró «%s»" -#: preproc.y:17673 +#: preproc.y:18287 #, c-format msgid "invalid connection type: %s" msgstr "tipo de conexión no válido: %s" -#: preproc.y:17682 +#: preproc.y:18296 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "se esperaba «@» o «://», se encontró «%s»" -#: preproc.y:17757 preproc.y:17775 +#: preproc.y:18371 preproc.y:18389 #, c-format msgid "invalid data type" msgstr "tipo de dato no válido" -#: preproc.y:17786 preproc.y:17803 +#: preproc.y:18400 preproc.y:18417 #, c-format msgid "incomplete statement" msgstr "sentencia incompleta" -#: preproc.y:17789 preproc.y:17806 +#: preproc.y:18403 preproc.y:18420 #, c-format msgid "unrecognized token \"%s\"" msgstr "elemento «%s» no reconocido" -#: preproc.y:17851 +#: preproc.y:18465 #, c-format msgid "name \"%s\" is already declared" msgstr "el nombre «%s» ya está declarado" -#: preproc.y:18140 +#: preproc.y:18754 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "sólo los tipos de dato numeric y decimal tienen argumento de precisión/escala" -#: preproc.y:18211 +#: preproc.y:18853 #, c-format msgid "interval specification not allowed here" msgstr "la especificación de intervalo no está permitida aquí" -#: preproc.y:18367 preproc.y:18419 +#: preproc.y:19009 preproc.y:19061 #, c-format msgid "too many levels in nested structure/union definition" msgstr "demasiados niveles en la definición anidada de estructura/unión" -#: preproc.y:18542 +#: preproc.y:19184 #, c-format msgid "pointers to varchar are not implemented" msgstr "los punteros a varchar no están implementados" -#: preproc.y:18993 +#: preproc.y:19635 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "inicializador no permitido en la orden EXEC SQL VAR" -#: preproc.y:19307 +#: preproc.y:19949 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "no se permiten los arrays de indicadores en la entrada" -#: preproc.y:19494 +#: preproc.y:20136 #, c-format msgid "operator not allowed in variable definition" msgstr "operador no permitido en definición de variable" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19535 +#: preproc.y:20177 #, c-format msgid "%s at or near \"%s\"" msgstr "%s en o cerca de «%s»" @@ -678,34 +677,34 @@ msgstr "la variable «%s» no es un array" msgid "variable \"%s\" is not declared" msgstr "la variable «%s» no está declarada" -#: variable.c:493 +#: variable.c:492 #, c-format msgid "indicator variable must have an integer type" msgstr "la variable de un indicador debe ser de algún tipo numérico entero" -#: variable.c:510 +#: variable.c:509 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "nombre de tipo de datos «%s» no reconocido" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:520 variable.c:528 variable.c:545 variable.c:548 #, c-format msgid "multidimensional arrays are not supported" msgstr "los arrays multidimensionales no están soportados" -#: variable.c:538 +#: variable.c:537 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "no se soportan los punteros multinivel (más de 2); se encontró 1 nivel" msgstr[1] "no se soportan los punteros multinivel (más de 2); se encontraron %d niveles" -#: variable.c:543 +#: variable.c:542 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "los punteros a puntero no están soportados para este tipo de dato" -#: variable.c:563 +#: variable.c:562 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "los arrays multidimensionales para estructuras no están soportados" diff --git a/src/interfaces/ecpg/preproc/po/fr.po b/src/interfaces/ecpg/preproc/po/fr.po index ca4aa527eea65..6d841e85359fd 100644 --- a/src/interfaces/ecpg/preproc/po/fr.po +++ b/src/interfaces/ecpg/preproc/po/fr.po @@ -9,10 +9,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-07-20 21:10+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -20,44 +20,44 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" #: descriptor.c:64 #, c-format msgid "variable \"%s\" must have a numeric type" msgstr "la variable « %s » doit avoir un type numeric" -#: descriptor.c:125 descriptor.c:156 +#: descriptor.c:124 descriptor.c:155 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "le descripteur %s lié à la connexion %s n'existe pas" -#: descriptor.c:127 descriptor.c:158 +#: descriptor.c:126 descriptor.c:157 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "le descripteur %s lié à la connexion par défaut n'existe pas" -#: descriptor.c:173 descriptor.c:225 +#: descriptor.c:172 descriptor.c:224 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "l'élément d'en-tête du descripteur « %d » n'existe pas" -#: descriptor.c:195 +#: descriptor.c:194 #, c-format msgid "nullable is always 1" msgstr "nullable vaut toujours 1" -#: descriptor.c:198 +#: descriptor.c:197 #, c-format msgid "key_member is always 0" msgstr "key_member vaut toujours 0" -#: descriptor.c:292 +#: descriptor.c:291 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "l'élément du descripteur « %s » n'est pas implanté" -#: descriptor.c:302 +#: descriptor.c:301 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "l'élément du descripteur « %s » ne peut pas être initialisé" @@ -192,179 +192,179 @@ msgstr "" msgid "%s home page: <%s>\n" msgstr "Page d'accueil de %s : <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s : n'a pas pu localiser le chemin de mon propre exécutable\n" -#: ecpg.c:176 ecpg.c:333 ecpg.c:344 -#, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %s\n" - -#: ecpg.c:219 ecpg.c:232 ecpg.c:248 ecpg.c:274 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Essayer « %s --help » pour plus d'informations.\n" -#: ecpg.c:243 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s : support de débogage de l'analyseur (-d) non disponible\n" -#: ecpg.c:262 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 +#, c-format +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s : n'a pas pu ouvrir le fichier « %s » : %m\n" + +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, le préprocesseur C embarqué de PostgreSQL, version %s\n" -#: ecpg.c:264 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "la recherche EXEC SQL INCLUDE ... commence ici :\n" -#: ecpg.c:267 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "fin de la liste de recherche\n" -#: ecpg.c:273 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s : aucun fichier précisé en entrée\n" -#: ecpg.c:477 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "le curseur « %s » est déclaré mais non ouvert" -#: ecpg.c:490 preproc.y:130 +#: ecpg.c:504 preproc.y:130 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "n'a pas pu supprimer le fichier « %s » en sortie\n" -#: pgc.l:508 +#: pgc.l:528 #, c-format msgid "unterminated /* comment" msgstr "commentaire /* non terminé" -#: pgc.l:525 +#: pgc.l:545 #, c-format msgid "unterminated bit string literal" -msgstr "chaîne bit litéral non terminée" +msgstr "chaîne bit littéral non terminée" -#: pgc.l:533 +#: pgc.l:553 #, c-format msgid "unterminated hexadecimal string literal" -msgstr "chaîne hexadécimale litérale non terminée" +msgstr "chaîne hexadécimale littérale non terminée" -#: pgc.l:608 +#: pgc.l:628 #, c-format msgid "invalid bit string literal" -msgstr "chaîne bit litéral invalide" +msgstr "chaîne bit littéral invalide" -#: pgc.l:613 +#: pgc.l:633 #, c-format msgid "invalid hexadecimal string literal" msgstr "chaîne hexadécimale invalide" -#: pgc.l:631 +#: pgc.l:651 #, c-format msgid "unhandled previous state in xqs\n" msgstr "état précédent non géré dans xqs\n" -#: pgc.l:657 pgc.l:766 +#: pgc.l:677 pgc.l:786 #, c-format msgid "unterminated quoted string" msgstr "chaîne entre guillemets non terminée" -#: pgc.l:708 +#: pgc.l:728 #, c-format msgid "unterminated dollar-quoted string" msgstr "chaîne entre guillemets dollars non terminée" -#: pgc.l:726 pgc.l:746 +#: pgc.l:746 pgc.l:766 #, c-format msgid "zero-length delimited identifier" msgstr "identifiant délimité de longueur nulle" -#: pgc.l:757 +#: pgc.l:777 #, c-format msgid "unterminated quoted identifier" msgstr "identifiant entre guillemets non terminé" -#: pgc.l:926 +#: pgc.l:946 #, c-format msgid "trailing junk after parameter" msgstr "élément indésirable après le paramètre" -#: pgc.l:968 pgc.l:971 pgc.l:974 +#: pgc.l:998 pgc.l:1001 pgc.l:1004 pgc.l:1007 pgc.l:1010 pgc.l:1013 #, c-format msgid "trailing junk after numeric literal" msgstr "élément indésirable après la valeur numérique" -#: pgc.l:1100 +#: pgc.l:1136 #, c-format msgid "nested /* ... */ comments" msgstr "commentaires /* ... */ imbriqués" -#: pgc.l:1193 +#: pgc.l:1235 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "identifiant manquant dans la commande EXEC SQL UNDEF" -#: pgc.l:1211 pgc.l:1224 pgc.l:1240 pgc.l:1253 +#: pgc.l:1253 pgc.l:1266 pgc.l:1282 pgc.l:1295 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "trop de conditions EXEC SQL IFDEF imbriquées" -#: pgc.l:1269 pgc.l:1280 pgc.l:1295 pgc.l:1317 +#: pgc.l:1311 pgc.l:1322 pgc.l:1337 pgc.l:1359 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "correspondance manquante « EXEC SQL IFDEF » / « EXEC SQL IFNDEF »" -#: pgc.l:1271 pgc.l:1282 pgc.l:1463 +#: pgc.l:1313 pgc.l:1324 pgc.l:1517 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "« EXEC SQL ENDIF; » manquant" -#: pgc.l:1297 pgc.l:1319 +#: pgc.l:1339 pgc.l:1361 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "plusieurs EXEC SQL ELSE" -#: pgc.l:1342 pgc.l:1356 +#: pgc.l:1384 pgc.l:1398 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "EXEC SQL ENDIF différent" -#: pgc.l:1411 +#: pgc.l:1459 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "identifiant manquant dans la commande EXEC SQL IFDEF" -#: pgc.l:1420 +#: pgc.l:1468 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "identifiant manquant dans la commande EXEC SQL DEFINE" -#: pgc.l:1453 +#: pgc.l:1506 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "erreur de syntaxe dans la commande EXEC SQL INCLUDE" -#: pgc.l:1503 +#: pgc.l:1561 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "erreur interne : l'état ne peut être atteint ; merci de rapporter ceci à <%s>" -#: pgc.l:1655 +#: pgc.l:1713 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "" "Erreur : le chemin d'en-tête « %s/%s » est trop long sur la ligne %d,\n" "ignoré\n" -#: pgc.l:1678 +#: pgc.l:1736 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "n'a pas pu ouvrir le fichier d'en-tête « %s » sur la ligne %d" @@ -398,12 +398,12 @@ msgstr "initialiseur non autorisé dans la définition du type" msgid "type name \"string\" is reserved in Informix mode" msgstr "le nom du type « string » est réservé dans le mode Informix" -#: preproc.y:552 preproc.y:19317 +#: preproc.y:552 preproc.y:19072 #, c-format msgid "type \"%s\" is already defined" msgstr "le type « %s » est déjà défini" -#: preproc.y:577 preproc.y:19952 preproc.y:20277 variable.c:621 +#: preproc.y:577 preproc.y:19707 preproc.y:20029 variable.c:625 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "" @@ -415,186 +415,180 @@ msgstr "" msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "la connexion %s est surchargée avec %s par l'instruction DECLARE %s" -#: preproc.y:1872 +#: preproc.y:1833 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "option AT non autorisée dans une instruction CLOSE DATABASE" -#: preproc.y:2122 +#: preproc.y:2083 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "option AT non autorisée dans une instruction CONNECT" -#: preproc.y:2162 +#: preproc.y:2123 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "option AT non autorisée dans une instruction DISCONNECT" -#: preproc.y:2217 +#: preproc.y:2178 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "option AT non autorisée dans une instruction SET CONNECTION" -#: preproc.y:2239 +#: preproc.y:2200 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "option AT non autorisée dans une instruction TYPE" -#: preproc.y:2248 +#: preproc.y:2209 #, c-format msgid "AT option not allowed in VAR statement" msgstr "option AT non autorisée dans une instruction VAR" -#: preproc.y:2255 +#: preproc.y:2216 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "option AT non autorisée dans une instruction WHENEVER" -#: preproc.y:2332 preproc.y:2504 preproc.y:2509 preproc.y:2632 preproc.y:4283 preproc.y:4357 -#: preproc.y:4948 preproc.y:5481 preproc.y:5819 preproc.y:6119 preproc.y:7687 preproc.y:9288 -#: preproc.y:9293 preproc.y:12272 +#: preproc.y:2341 preproc.y:2628 preproc.y:4379 preproc.y:5043 preproc.y:5913 preproc.y:6117 +#: preproc.y:6218 preproc.y:12482 #, c-format msgid "unsupported feature will be passed to server" msgstr "la fonctionnalité non supportée sera passée au serveur" -#: preproc.y:2890 +#: preproc.y:2886 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL n'est pas implanté" -#: preproc.y:3589 +#: preproc.y:3626 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN n'est pas implanté" -#: preproc.y:10335 preproc.y:18892 +#: preproc.y:10466 preproc.y:18541 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "« database » ne peut pas être utilisé comme nom de curseur dans le mode INFORMIX" -#: preproc.y:10342 preproc.y:18902 +#: preproc.y:10473 preproc.y:18551 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "" "l'utilisation de la variable « %s » dans différentes instructions de déclaration\n" "n'est pas supportée" -#: preproc.y:10344 preproc.y:18904 +#: preproc.y:10475 preproc.y:18553 #, c-format msgid "cursor \"%s\" is already defined" msgstr "le curseur « %s » est déjà défini" -#: preproc.y:10818 +#: preproc.y:10949 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "la syntaxe obsolète LIMIT #,# a été passée au serveur" -#: preproc.y:11151 preproc.y:11158 -#, c-format -msgid "subquery in FROM must have an alias" -msgstr "la sous-requête du FROM doit avoir un alias" - -#: preproc.y:18584 preproc.y:18591 +#: preproc.y:18233 preproc.y:18240 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS ne peut pas indiquer INTO" -#: preproc.y:18627 +#: preproc.y:18276 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "« @ » attendu, « %s » trouvé" -#: preproc.y:18639 +#: preproc.y:18288 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "" "seuls les protocoles « tcp » et « unix » et les types de base de données\n" "« postgresql » sont supportés" -#: preproc.y:18642 +#: preproc.y:18291 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "« :// » attendu, « %s » trouvé" -#: preproc.y:18647 +#: preproc.y:18296 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "les sockets de domaine Unix fonctionnent seulement sur « localhost », mais pas sur « %s »" -#: preproc.y:18673 +#: preproc.y:18322 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "« postgresql » attendu, « %s » trouvé" -#: preproc.y:18676 +#: preproc.y:18325 #, c-format msgid "invalid connection type: %s" msgstr "type de connexion invalide : %s" -#: preproc.y:18685 +#: preproc.y:18334 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "« @ » ou « :// » attendu, « %s » trouvé" -#: preproc.y:18760 preproc.y:18778 +#: preproc.y:18409 preproc.y:18427 #, c-format msgid "invalid data type" msgstr "type de données invalide" -#: preproc.y:18789 preproc.y:18806 +#: preproc.y:18438 preproc.y:18455 #, c-format msgid "incomplete statement" msgstr "instruction incomplète" -#: preproc.y:18792 preproc.y:18809 +#: preproc.y:18441 preproc.y:18458 #, c-format msgid "unrecognized token \"%s\"" msgstr "jeton « %s » non reconnu" -#: preproc.y:18854 +#: preproc.y:18503 #, c-format msgid "name \"%s\" is already declared" msgstr "le nom « %s » est déjà défini" -#: preproc.y:19120 +#: preproc.y:18792 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "" "seuls les types de données numeric et decimal ont des arguments de\n" "précision et d'échelle" -#: preproc.y:19132 +#: preproc.y:18891 #, c-format msgid "interval specification not allowed here" msgstr "interval de spécification non autorisé ici" -#: preproc.y:19292 preproc.y:19344 +#: preproc.y:19047 preproc.y:19099 #, c-format msgid "too many levels in nested structure/union definition" msgstr "trop de niveaux dans la définition de structure/union imbriquée" -#: preproc.y:19467 +#: preproc.y:19222 #, c-format msgid "pointers to varchar are not implemented" msgstr "les pointeurs sur des chaînes de caractères (varchar) ne sont pas implantés" -#: preproc.y:19918 +#: preproc.y:19673 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "initialiseur non autorisé dans la commande EXEC SQL VAR" -#: preproc.y:20235 +#: preproc.y:19987 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "les tableaux d'indicateurs ne sont pas autorisés en entrée" -#: preproc.y:20422 +#: preproc.y:20174 #, c-format msgid "operator not allowed in variable definition" msgstr "opérateur non autorisé dans la définition de la variable" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:20463 +#: preproc.y:20215 #, c-format msgid "%s at or near \"%s\"" msgstr "%s sur ou près de « %s »" @@ -668,52 +662,52 @@ msgstr "le struct indicateur « %s » a trop de membres" msgid "unrecognized descriptor item code %d" msgstr "code %d de l'élément du descripteur non reconnu" -#: variable.c:89 variable.c:116 +#: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "variable « %s » mal formée" -#: variable.c:139 +#: variable.c:138 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "la variable « %s » n'est pas un pointeur" -#: variable.c:142 variable.c:167 +#: variable.c:141 variable.c:166 #, c-format msgid "variable \"%s\" is not a pointer to a structure or a union" msgstr "la variable « %s » n'est pas un pointeur vers une structure ou une union" -#: variable.c:154 +#: variable.c:153 #, c-format msgid "variable \"%s\" is neither a structure nor a union" msgstr "la variable « %s » n'est ni une structure ni une union" -#: variable.c:164 +#: variable.c:163 #, c-format msgid "variable \"%s\" is not an array" msgstr "la variable « %s » n'est pas un tableau" -#: variable.c:233 variable.c:255 +#: variable.c:232 variable.c:254 #, c-format msgid "variable \"%s\" is not declared" msgstr "la variable « %s » n'est pas déclarée" -#: variable.c:494 +#: variable.c:493 #, c-format msgid "indicator variable must have an integer type" msgstr "la variable d'indicateur doit avoir un type integer" -#: variable.c:506 +#: variable.c:510 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "nom « %s » non reconnu pour un type de données" -#: variable.c:517 variable.c:525 variable.c:542 variable.c:545 +#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 #, c-format msgid "multidimensional arrays are not supported" msgstr "les tableaux multidimensionnels ne sont pas supportés" -#: variable.c:534 +#: variable.c:538 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" @@ -724,46 +718,12 @@ msgstr[1] "" "les pointeurs multi-niveaux (plus de deux) ne sont pas supportés :\n" "%d niveaux trouvés" -#: variable.c:539 +#: variable.c:543 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "ce type de données ne supporte pas les pointeurs de pointeur" -#: variable.c:559 +#: variable.c:563 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "les tableaux multidimensionnels ne sont pas supportés pour les structures" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "Rapporter les bogues à .\n" - -#~ msgid " --version output version information, then exit\n" -#~ msgstr " --version affiche la version et quitte\n" - -#~ msgid "AT option not allowed in DEALLOCATE statement" -#~ msgstr "option AT non autorisée dans une instruction DEALLOCATE" - -#~ msgid "COPY FROM STDOUT is not possible" -#~ msgstr "COPY FROM STDOUT n'est pas possible" - -#~ msgid "COPY TO STDIN is not possible" -#~ msgstr "COPY TO STDIN n'est pas possible" - -#~ msgid "NEW used in query that is not in a rule" -#~ msgstr "NEW utilisé dans une requête qui n'est pas dans une règle" - -#~ msgid "OLD used in query that is not in a rule" -#~ msgstr "OLD utilisé dans une requête qui n'est pas dans une règle" - -#~ msgid "constraint declared INITIALLY DEFERRED must be DEFERRABLE" -#~ msgstr "une contrainte déclarée INITIALLY DEFERRED doit être DEFERRABLE" - -#~ msgid "declared name %s is already defined" -#~ msgstr "le nom déclaré %s est déjà défini" - -#~ msgid "using unsupported DESCRIBE statement" -#~ msgstr "utilisation de l'instruction DESCRIBE non supporté" diff --git a/src/interfaces/ecpg/preproc/po/ja.po b/src/interfaces/ecpg/preproc/po/ja.po index ac539c39f0ddb..2509435666af6 100644 --- a/src/interfaces/ecpg/preproc/po/ja.po +++ b/src/interfaces/ecpg/preproc/po/ja.po @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: ecpg (PostgreSQL 17)\n" +"Project-Id-Version: ecpg (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-13 10:06+0900\n" -"PO-Revision-Date: 2024-03-13 10:42+0900\n" +"POT-Creation-Date: 2025-03-12 11:10+0900\n" +"PO-Revision-Date: 2025-03-31 16:23+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: jpug-doc \n" "Language: ja\n" @@ -17,47 +17,47 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: descriptor.c:64 +#: descriptor.c:63 #, c-format msgid "variable \"%s\" must have a numeric type" msgstr "変数\"%s\"は数値型でなければなりません" -#: descriptor.c:124 descriptor.c:155 +#: descriptor.c:119 descriptor.c:149 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "接続%2$sに関連付けられている記述子%1$sは存在しません" -#: descriptor.c:126 descriptor.c:157 +#: descriptor.c:121 descriptor.c:151 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "デフォルト接続に関連付けられている記述子%sは存在しません" -#: descriptor.c:172 descriptor.c:224 +#: descriptor.c:166 descriptor.c:218 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "記述子ヘッダ項目%dは存在しません" -#: descriptor.c:194 +#: descriptor.c:188 #, c-format msgid "nullable is always 1" msgstr "nullableは常に1です" -#: descriptor.c:197 +#: descriptor.c:191 #, c-format msgid "key_member is always 0" msgstr "key_memberは常に0です" -#: descriptor.c:291 +#: descriptor.c:285 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "記述子項目%sは実装されていません" -#: descriptor.c:301 +#: descriptor.c:295 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "記述子項目%sは設定できません" -#: ecpg.c:36 +#: ecpg.c:37 #, c-format msgid "" "%s is the PostgreSQL embedded SQL preprocessor for C programs.\n" @@ -66,7 +66,7 @@ msgstr "" "%sはCプログラム用のPostgreSQL埋込みSQLプリプロセッサです。\n" "\n" -#: ecpg.c:38 +#: ecpg.c:39 #, c-format msgid "" "Usage:\n" @@ -77,12 +77,12 @@ msgstr "" " %s [オプション]... ファイル...\n" "\n" -#: ecpg.c:41 +#: ecpg.c:42 #, c-format msgid "Options:\n" msgstr "オプション:\n" -#: ecpg.c:42 +#: ecpg.c:43 #, c-format msgid "" " -c automatically generate C code from embedded SQL code;\n" @@ -91,7 +91,7 @@ msgstr "" " -c 埋め込まれたSQLコードを元にC言語コードを自動的に生成。\n" " これはEXEC SQL TYPEに影響を与える\n" -#: ecpg.c:44 +#: ecpg.c:45 #, c-format msgid "" " -C MODE set compatibility mode; MODE can be one of\n" @@ -100,39 +100,39 @@ msgstr "" " -C MODE 互換モードを設定; MODEは\"INFORMIX\"、 \"INFORMIX_SE\"、\n" " \"ORACLE\"のいずれか\n" -#: ecpg.c:47 +#: ecpg.c:48 #, c-format msgid " -d generate parser debug output\n" msgstr " -d パーサのデバッグ出力を有効にする\n" -#: ecpg.c:49 +#: ecpg.c:50 #, c-format msgid " -D SYMBOL define SYMBOL\n" msgstr " -D SYMBOL シンボル SYMBOL を定義する\n" -#: ecpg.c:50 +#: ecpg.c:51 #, c-format msgid " -h parse a header file, this option includes option \"-c\"\n" msgstr "" " -h ヘッダファイルをパースする。このオプションには\"-c\"オプション\n" " が含まれる\n" -#: ecpg.c:51 +#: ecpg.c:52 #, c-format msgid " -i parse system include files as well\n" msgstr " -i システムインクルードファイルもパースする\n" -#: ecpg.c:52 +#: ecpg.c:53 #, c-format msgid " -I DIRECTORY search DIRECTORY for include files\n" msgstr " -I DIRECTORY DIRECTORYからインクルードファイルを検索\n" -#: ecpg.c:53 +#: ecpg.c:54 #, c-format msgid " -o OUTFILE write result to OUTFILE\n" msgstr " -o OUTFILE 結果をOUTFILEに出力\n" -#: ecpg.c:54 +#: ecpg.c:55 #, c-format msgid "" " -r OPTION specify run-time behavior; OPTION can be:\n" @@ -141,27 +141,27 @@ msgstr "" " -r OPTION 実行時の動作を指定。オプションは次のいずれか\n" " \"no_indicator\"、\"prepare\"、\"questionmarks\"\n" -#: ecpg.c:56 +#: ecpg.c:57 #, c-format msgid " --regression run in regression testing mode\n" msgstr " --regression リグレッション試験モードで実行\n" -#: ecpg.c:57 +#: ecpg.c:58 #, c-format msgid " -t turn on autocommit of transactions\n" msgstr " -t トランザクションの自動コミットを有効にする\n" -#: ecpg.c:58 +#: ecpg.c:59 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version バージョン情報を出力して終了\n" -#: ecpg.c:59 +#: ecpg.c:60 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help このヘルプを表示して終了\n" -#: ecpg.c:60 +#: ecpg.c:61 #, c-format msgid "" "\n" @@ -172,7 +172,7 @@ msgstr "" "出力ファイルの指定がない場合は、入力ファイルの名前に.cを付けた名前になります。\n" "ただし、もし.pgcがある場合はこれを取り除いてから.cが付けられます。\n" -#: ecpg.c:62 +#: ecpg.c:63 #, c-format msgid "" "\n" @@ -181,474 +181,478 @@ msgstr "" "\n" "バグは<%s>に報告してください。\n" -#: ecpg.c:63 +#: ecpg.c:64 #, c-format msgid "%s home page: <%s>\n" msgstr "%s ホームページ: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: 自身の実行ファイルの場所がわかりません\n" -#: ecpg.c:184 ecpg.c:235 ecpg.c:249 ecpg.c:275 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "詳細は\"%s --help\"を実行してください。\n" -#: ecpg.c:192 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: パーサデバッグのサポート(-d)を利用できません\n" -#: ecpg.c:219 ecpg.c:334 ecpg.c:345 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format msgid "%s: could not open file \"%s\": %m\n" msgstr "%s: ファイル\"%s\"をオープンできませんでした: %m\n" -#: ecpg.c:263 +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, PostgreSQL埋込みC言語プリプロセッサ, バージョン%s\n" -#: ecpg.c:265 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... 検索が始まります\n" -#: ecpg.c:268 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "検索リストの終端です\n" -#: ecpg.c:274 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: 入力ファイルが指定されていません\n" -#: ecpg.c:478 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "カーソル%sは宣言されましたが、オープンされていません" -#: ecpg.c:491 preproc.y:130 +#: ecpg.c:504 util.c:75 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "出力ファイル\"%s\"を削除できませんでした\n" -#: pgc.l:520 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "/*コメントが閉じていません" -#: pgc.l:537 +#: pgc.l:560 #, c-format msgid "unterminated bit string literal" msgstr "ビット文字列リテラルの終端がありません" -#: pgc.l:545 +#: pgc.l:570 #, c-format msgid "unterminated hexadecimal string literal" msgstr "16進数文字列リテラルの終端がありません" -#: pgc.l:620 +#: pgc.l:644 #, c-format msgid "invalid bit string literal" msgstr "無効なビット列リテラルです" -#: pgc.l:625 +#: pgc.l:649 #, c-format msgid "invalid hexadecimal string literal" msgstr "不正な16進数文字列リテラル" -#: pgc.l:643 +#: pgc.l:667 #, c-format msgid "unhandled previous state in xqs\n" msgstr "xqsの中で処理されない前ステート\n" -#: pgc.l:669 pgc.l:778 +#: pgc.l:700 pgc.l:820 #, c-format msgid "unterminated quoted string" msgstr "文字列の引用符が閉じていません" -#: pgc.l:720 +#: pgc.l:753 #, c-format msgid "unterminated dollar-quoted string" msgstr "文字列のドル引用符が閉じていません" -#: pgc.l:738 pgc.l:758 +#: pgc.l:772 pgc.l:793 #, c-format msgid "zero-length delimited identifier" msgstr "区切りつき識別子の長さがゼロです" -#: pgc.l:769 +#: pgc.l:809 #, c-format msgid "unterminated quoted identifier" msgstr "識別子の引用符が閉じていません" -#: pgc.l:938 +#: pgc.l:985 +#, c-format +msgid "parameter number too large" +msgstr "パラメータ数が多すぎます" + +#: pgc.l:990 #, c-format msgid "trailing junk after parameter" msgstr "パラメータの後に余分な文字" -#: pgc.l:990 pgc.l:993 pgc.l:996 pgc.l:999 pgc.l:1002 pgc.l:1005 +#: pgc.l:1042 pgc.l:1045 pgc.l:1048 #, c-format msgid "trailing junk after numeric literal" msgstr "数値リテラルの後ろにゴミがあります" -#: pgc.l:1127 +#: pgc.l:1177 #, c-format msgid "nested /* ... */ comments" msgstr "入れ子状の /* ... */ コメント" -#: pgc.l:1220 +#: pgc.l:1279 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "EXEC SQL UNDEFコマンドにおいて識別子がありません" -#: pgc.l:1238 pgc.l:1251 pgc.l:1267 pgc.l:1280 +#: pgc.l:1299 pgc.l:1312 pgc.l:1328 pgc.l:1341 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "入れ子状のEXEC SQL IFDEF条件が多すぎます" -#: pgc.l:1296 pgc.l:1307 pgc.l:1322 pgc.l:1344 +#: pgc.l:1357 pgc.l:1368 pgc.l:1384 pgc.l:1406 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "対応する\"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"がありません" -#: pgc.l:1298 pgc.l:1309 pgc.l:1490 +#: pgc.l:1359 pgc.l:1370 pgc.l:1565 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "\"EXEC SQL ENDIF;\"がありません" -#: pgc.l:1324 pgc.l:1346 +#: pgc.l:1386 pgc.l:1408 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "1つ以上のEXEC SQL ELSE\"が存在します" -#: pgc.l:1369 pgc.l:1383 +#: pgc.l:1431 pgc.l:1445 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "EXEC SQL ENDIFに対応するものがありません" -#: pgc.l:1438 +#: pgc.l:1507 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "EXEC SQL IFDEFコマンドにおいて識別子がありません" -#: pgc.l:1447 +#: pgc.l:1516 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "EXEC SQL DEFINEコマンドにおいて識別子がありません" -#: pgc.l:1480 +#: pgc.l:1554 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "EXEC SQL INCLUDEコマンドにおいて構文エラーがあります" -#: pgc.l:1530 +#: pgc.l:1609 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "内部エラー: 到達しないはずの状態です。<%s>まで報告してください" -#: pgc.l:1682 +#: pgc.l:1766 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "エラー:行番号%3$dのインクルードパス\"%1$s/%2$s\"が長すぎます。無視しました。\n" -#: pgc.l:1705 +#: pgc.l:1793 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "行番号%2$dのインクルードファイル\"%1$s\"をオープンすることができませんでした" -#: preproc.y:31 +#: preproc.y:28 msgid "syntax error" msgstr "構文エラー" -#: preproc.y:84 -#, c-format -msgid "WARNING: " -msgstr "警告: " - -#: preproc.y:87 -#, c-format -msgid "ERROR: " -msgstr "エラー: " - -#: preproc.y:514 +#: preproc.y:467 #, c-format msgid "cursor \"%s\" does not exist" msgstr "カーソル\"%s\"は存在しません" -#: preproc.y:543 +#: preproc.y:503 #, c-format msgid "initializer not allowed in type definition" msgstr "型定義では初期化子は許されません" -#: preproc.y:545 +#: preproc.y:505 #, c-format msgid "type name \"string\" is reserved in Informix mode" msgstr "型名\"string\"はInformixモードですでに予約されています" -#: preproc.y:552 preproc.y:18523 +#: preproc.y:512 preproc.y:8820 #, c-format msgid "type \"%s\" is already defined" msgstr "\"%s\"型はすでに定義されています" -#: preproc.y:577 preproc.y:19158 preproc.y:19480 variable.c:625 +#: preproc.y:539 preproc.y:9534 preproc.y:9879 variable.c:652 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "単純なデータ型の多次元配列はサポートされていません" -#: preproc.y:599 +#: preproc.y:562 #, c-format msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "DECLARE文%3$sにより接続%1$sは%2$sで上書きされます" -#: preproc.y:1810 +#: preproc.y:932 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "CLOSE DATABASE文ではATオプションは許されません" -#: preproc.y:2060 +#: preproc.y:1184 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "CONNECT文ではATオプションは許されません" -#: preproc.y:2100 +#: preproc.y:1221 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "DISCONNECT文ではATオプションは許されません" -#: preproc.y:2155 +#: preproc.y:1274 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "SET CONNECTION文ではATオプションは許されません" -#: preproc.y:2177 +#: preproc.y:1292 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "TYPE文ではATオプションは許されません" -#: preproc.y:2186 +#: preproc.y:1300 #, c-format msgid "AT option not allowed in VAR statement" msgstr "VAR文ではATオプションは許されません" -#: preproc.y:2193 +#: preproc.y:1307 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "WHENEVER文ではATオプションは許されません" -#: preproc.y:2318 preproc.y:2490 preproc.y:2495 preproc.y:2607 preproc.y:4317 -#: preproc.y:4391 preproc.y:4982 preproc.y:5515 preproc.y:5853 preproc.y:6057 -#: preproc.y:6158 preproc.y:7722 preproc.y:9330 preproc.y:9335 preproc.y:12308 +#: preproc.y:1375 preproc.y:1498 preproc.y:2260 preproc.y:2586 preproc.y:3017 +#: preproc.y:3104 preproc.y:6086 #, c-format msgid "unsupported feature will be passed to server" msgstr "非サポートの機能がサーバーに渡されます" -#: preproc.y:2865 +#: preproc.y:1610 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALLは実装されていません" -#: preproc.y:3577 +#: preproc.y:1896 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDINは実装されていません" -#: preproc.y:10385 preproc.y:18020 +#: preproc.y:5146 preproc.y:8271 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "INFORMIXモードでは\"database\"をカーソル名として使用できません" -#: preproc.y:10392 preproc.y:18030 +#: preproc.y:5153 preproc.y:8281 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "異なったdeclareステートメントにおける変数\"%s\"の使用はサポートされていません" -#: preproc.y:10394 preproc.y:18032 +#: preproc.y:5155 preproc.y:8283 #, c-format msgid "cursor \"%s\" is already defined" msgstr "カーソル\"%s\"はすでに定義されています" -#: preproc.y:10868 +#: preproc.y:5402 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "サーバーに渡されるLIMIT #,#構文はもはやサポートされていません" -#: preproc.y:17712 preproc.y:17719 +#: preproc.y:7919 preproc.y:7927 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE ASはINTOを指定できません" -#: preproc.y:17755 +#: preproc.y:7972 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "想定では\"@\"、結果では\"%s\"" -#: preproc.y:17767 +#: preproc.y:7984 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "プロトコルでは\"tcp\"および\"unix\"のみ、データベースの種類では\"postgresql\"のみがサポートされています" -#: preproc.y:17770 +#: preproc.y:7987 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "想定では\"://\"、結果では\"%s\"" -#: preproc.y:17775 +#: preproc.y:7992 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unixドメインソケットは\"localhost\"でのみで動作し、\"%s\"では動作しません" -#: preproc.y:17801 +#: preproc.y:8019 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "想定では\"postgresql\"、結果では\"%s\"" -#: preproc.y:17804 +#: preproc.y:8022 #, c-format msgid "invalid connection type: %s" msgstr "無効な接続種類: %s" -#: preproc.y:17813 +#: preproc.y:8031 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "想定では\"@または\"\"://\"、結果では\"%s\"" -#: preproc.y:17888 preproc.y:17906 +#: preproc.y:8129 preproc.y:8147 #, c-format msgid "invalid data type" msgstr "無効なデータ型" -#: preproc.y:17917 preproc.y:17934 +#: preproc.y:8158 preproc.y:8175 #, c-format msgid "incomplete statement" msgstr "不完全な文" -#: preproc.y:17920 preproc.y:17937 +#: preproc.y:8161 preproc.y:8178 #, c-format msgid "unrecognized token \"%s\"" msgstr "認識できないトークン\"%s\"" -#: preproc.y:17982 +#: preproc.y:8233 #, c-format msgid "name \"%s\" is already declared" msgstr "名前\"%s\"はすでに定義されています" -#: preproc.y:18271 +#: preproc.y:8536 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "数値データ型または10進数データ型のみが精度/位取り引数と取ることができます" -#: preproc.y:18342 +#: preproc.y:8635 #, c-format msgid "interval specification not allowed here" msgstr "時間間隔の指定はここでは許されません" -#: preproc.y:18498 preproc.y:18550 +#: preproc.y:8791 preproc.y:8849 #, c-format msgid "too many levels in nested structure/union definition" msgstr "構造体/ユニオンの定義の入れ子レベルが深すぎます" -#: preproc.y:18673 +#: preproc.y:8984 #, c-format msgid "pointers to varchar are not implemented" msgstr "varcharを指し示すポインタは実装されていません" -#: preproc.y:19124 +#: preproc.y:9499 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "EXEC SQL VARコマンドでは初期化子は許されません" -#: preproc.y:19438 +#: preproc.y:9822 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "指示子配列は入力として許されません" -#: preproc.y:19625 +#: preproc.y:10056 #, c-format msgid "operator not allowed in variable definition" msgstr "変数定義では演算子は許されません" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19666 +#: preproc.y:10101 #, c-format msgid "%s at or near \"%s\"" msgstr "\"%2$s\"またはその近辺で%1$s" -#: type.c:18 type.c:30 -#, c-format -msgid "out of memory" -msgstr "メモリ不足です" - -#: type.c:214 type.c:685 +#: type.c:191 type.c:661 #, c-format msgid "unrecognized variable type code %d" msgstr "認識できない変数型コード%d" -#: type.c:263 +#: type.c:240 #, c-format msgid "variable \"%s\" is hidden by a local variable of a different type" msgstr "変数\"%s\"は、異なった型を持つローカル変数により隠蔽されています" -#: type.c:265 +#: type.c:242 #, c-format msgid "variable \"%s\" is hidden by a local variable" msgstr "変数\"%s\"はローカル変数により隠蔽されています" -#: type.c:277 +#: type.c:254 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable of a different type" msgstr "指示子変数\"%s\"は、異なった型を持つローカル変数により隠蔽されています" -#: type.c:279 +#: type.c:256 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable" msgstr "指示子変数\"%s\"はローカル変数により隠蔽されています" -#: type.c:287 +#: type.c:264 #, c-format msgid "indicator for array/pointer has to be array/pointer" msgstr "配列/ポインタ用の指示子は配列/ポインタでなければなりません" -#: type.c:291 +#: type.c:268 #, c-format msgid "nested arrays are not supported (except strings)" msgstr "入れ子状の配列はサポートされません (文字列は除きます)" -#: type.c:333 +#: type.c:310 #, c-format msgid "indicator for struct has to be a struct" msgstr "構造体用の指示子は構造体でなければなりません" -#: type.c:353 type.c:374 type.c:394 +#: type.c:330 type.c:351 type.c:371 #, c-format msgid "indicator for simple data type has to be simple" msgstr "単純なデータ型用の指示子は単純型でなければなりません" -#: type.c:625 +#: type.c:602 #, c-format msgid "indicator struct \"%s\" has too few members" msgstr "指示子構造体\"%s\"のメンバが足りません" -#: type.c:633 +#: type.c:610 #, c-format msgid "indicator struct \"%s\" has too many members" msgstr "指示子構造体\"%s\"のメンバが多すぎます" -#: type.c:744 +#: type.c:723 #, c-format msgid "unrecognized descriptor item code %d" msgstr "認識できない記述子項目コード%dです" +#: util.c:26 +#, c-format +msgid "WARNING: " +msgstr "警告: " + +#: util.c:29 +#, c-format +msgid "ERROR: " +msgstr "エラー: " + +#: util.c:90 util.c:102 +#, c-format +msgid "out of memory" +msgstr "メモリ不足です" + #: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "正しく成形されていない変数\"%s\"です" -#: variable.c:138 +#: variable.c:138 variable.c:237 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "変数\"%s\"はポインタではありません" @@ -668,58 +672,43 @@ msgstr "変数\"%s\"は構造体でもユニオンでもありません" msgid "variable \"%s\" is not an array" msgstr "変数\"%s\"は配列ではありません" -#: variable.c:232 variable.c:254 +#: variable.c:220 +#, c-format +msgid "unmatched brace in variable \"%s\"" +msgstr "変数\"%s\"に閉じられていないブレースがあります" + +#: variable.c:235 variable.c:258 #, c-format msgid "variable \"%s\" is not declared" msgstr "変数\"%s\"は宣言されていません" -#: variable.c:493 +#: variable.c:517 #, c-format msgid "indicator variable must have an integer type" msgstr "指示子変数は整数型でなければなりません" -#: variable.c:510 +#: variable.c:534 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "データ型名\"%s\"は認識できません" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:548 variable.c:556 variable.c:573 variable.c:576 #, c-format msgid "multidimensional arrays are not supported" msgstr "多次元配列はサポートされません" -#: variable.c:538 +#: variable.c:565 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "複数レベルのポインタ(2レベル以上)はサポートされません。%dレベルあります" -#: variable.c:543 +#: variable.c:570 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "このデータ型では、ポインタを指し示すポインタはサポートされていません" -#: variable.c:563 +#: variable.c:590 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "構造体の多次元配列はサポートされていません" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "不具合はまで報告してください。\n" - -#~ msgid "" -#~ "\n" -#~ "Report bugs to .\n" -#~ msgstr "" -#~ "\n" -#~ "不具合はに報告してください。\n" - -#~ msgid "subquery in FROM must have an alias" -#~ msgstr "FROM句の副問い合わせは別名を持たなければなりません" - -#~ msgid "using unsupported DESCRIBE statement" -#~ msgstr "未サポートのDESCRIBE文の使用" diff --git a/src/interfaces/ecpg/preproc/po/ka.po b/src/interfaces/ecpg/preproc/po/ka.po index 604fb6758bd4d..04151f7a3c352 100644 --- a/src/interfaces/ecpg/preproc/po/ka.po +++ b/src/interfaces/ecpg/preproc/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: ecpg (PostgreSQL) 17\n" +"Project-Id-Version: ecpg (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-03-13 00:40+0000\n" -"PO-Revision-Date: 2024-03-13 02:00+0100\n" +"POT-Creation-Date: 2025-04-25 17:40+0000\n" +"PO-Revision-Date: 2025-04-26 05:04+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,49 +16,49 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: descriptor.c:64 +#: descriptor.c:63 #, c-format msgid "variable \"%s\" must have a numeric type" msgstr "ცვლად \"%s\"-ს რიცხვობრივი ტიპი უნდა გააჩნდეს" -#: descriptor.c:124 descriptor.c:155 +#: descriptor.c:119 descriptor.c:149 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "დესკრიპტორი %s მიბმულია შეერთებაზე %s, არ არსებობს" -#: descriptor.c:126 descriptor.c:157 +#: descriptor.c:121 descriptor.c:151 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "ნაგულისხმებ შეერთებაზე მიბმული დესკრიპტორი (\"%s\") არ არსებობს" -#: descriptor.c:172 descriptor.c:224 +#: descriptor.c:166 descriptor.c:218 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "დესკრიპტორის თავსართის ჩანაწერი \"%d\" არ არსებობს" -#: descriptor.c:194 +#: descriptor.c:188 #, c-format msgid "nullable is always 1" msgstr "განულებადი ყოველთვის 1-ს უდრის" -#: descriptor.c:197 +#: descriptor.c:191 #, c-format msgid "key_member is always 0" msgstr "key_member ყოველთვის 0-ს უდრის" -#: descriptor.c:291 +#: descriptor.c:285 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "დესკრიპტორის ჩანაწერი \"%s\" განხორციელებული არაა" -#: descriptor.c:301 +#: descriptor.c:295 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "დესკრიპტორის ჩანაწერის (\"%s\") დაყენების შეცდომა" -#: ecpg.c:36 +#: ecpg.c:37 #, c-format msgid "" "%s is the PostgreSQL embedded SQL preprocessor for C programs.\n" @@ -67,7 +67,7 @@ msgstr "" "%s PostgreSQL-ში ჩაშენებული SQL პრეპროცესორია C-ზე დაწერილი პროგრამებისთვის.\n" "\n" -#: ecpg.c:38 +#: ecpg.c:39 #, c-format msgid "" "Usage:\n" @@ -78,12 +78,12 @@ msgstr "" " %s [პარამეტრი]... ფაილი...\n" "\n" -#: ecpg.c:41 +#: ecpg.c:42 #, c-format msgid "Options:\n" msgstr "პარამეტრები:\n" -#: ecpg.c:42 +#: ecpg.c:43 #, c-format msgid "" " -c automatically generate C code from embedded SQL code;\n" @@ -92,7 +92,7 @@ msgstr "" " -c ჩადგმული SQL კოდიდან C-ის კოდის ავტომატური გენერაცია;\n" " ეს გავლენას ახდენს EXEC SQL TYPE-ზე\n" -#: ecpg.c:44 +#: ecpg.c:45 #, c-format msgid "" " -C MODE set compatibility mode; MODE can be one of\n" @@ -101,37 +101,37 @@ msgstr "" " -C რეჟიმი თავსებადობის დაყენება. რეჟიმი შეიძლება იყოს:\n" " \"INFORMIX\", \"INFORMIX_SE\", \"ORACLE\"\n" -#: ecpg.c:47 +#: ecpg.c:48 #, c-format msgid " -d generate parser debug output\n" msgstr " -d დამმუშავებლის გასამართი ინფორმაციის გენერაცია\n" -#: ecpg.c:49 +#: ecpg.c:50 #, c-format msgid " -D SYMBOL define SYMBOL\n" msgstr " -D ფუნქცია ფუნქციის აღწერა\n" -#: ecpg.c:50 +#: ecpg.c:51 #, c-format msgid " -h parse a header file, this option includes option \"-c\"\n" msgstr " -h თავსართის ფაილის დამუშავება. ეს პარამეტრი ასევე შეიცავს პარამეტრს \"-c\"\n" -#: ecpg.c:51 +#: ecpg.c:52 #, c-format msgid " -i parse system include files as well\n" msgstr " -i დამუშავებისას სისტემური ფაილების ჩართვა\n" -#: ecpg.c:52 +#: ecpg.c:53 #, c-format msgid " -I DIRECTORY search DIRECTORY for include files\n" msgstr " -I საქაღალდე თავსართის ფაილების ძებნისას მათი ალტერნატიული მდებარეობა\n" -#: ecpg.c:53 +#: ecpg.c:54 #, c-format msgid " -o OUTFILE write result to OUTFILE\n" msgstr " -o გამოსატანიფაილი გამოტანილი ინფორმაციის მითითებულ ფაილში ჩაწერა\n" -#: ecpg.c:54 +#: ecpg.c:55 #, c-format msgid "" " -r OPTION specify run-time behavior; OPTION can be:\n" @@ -140,27 +140,27 @@ msgstr "" " -r პარამეტრი გაშვების ქცევა; პარამეტრი შეიძლება იყოს:\n" " \"no_indicator\", \"prepare\", \"questionmarks\"\n" -#: ecpg.c:56 +#: ecpg.c:57 #, c-format msgid " --regression run in regression testing mode\n" msgstr " --regression რეგრესიის ტესტირების რეჟიმში გაშვება\n" -#: ecpg.c:57 +#: ecpg.c:58 #, c-format msgid " -t turn on autocommit of transactions\n" msgstr " -t ტრანზაქციების ავტომატური გადაცემის ჩართვა\n" -#: ecpg.c:58 +#: ecpg.c:59 #, c-format msgid " -V, --version output version information, then exit\n" msgstr " -V, --version ვერსიის ჩვენება და გასვლა\n" -#: ecpg.c:59 +#: ecpg.c:60 #, c-format msgid " -?, --help show this help, then exit\n" msgstr " -?, --help ამ დახმარების ჩვენება და გასვლა\n" -#: ecpg.c:60 +#: ecpg.c:61 #, c-format msgid "" "\n" @@ -171,7 +171,7 @@ msgstr "" "თუ გამოსატანი ფაილი მითითებული არაა, სახელი იქმნება \n" "შეყვანის ფაილის სახელისთვის .c- ს დამატებით, წარდგენის შემთხვევაში .pgc- ის მოშლის შემდეგ.\n" -#: ecpg.c:62 +#: ecpg.c:63 #, c-format msgid "" "\n" @@ -180,474 +180,478 @@ msgstr "" "\n" "შეცდომების შესახებ მიწერეთ: %s\n" -#: ecpg.c:63 +#: ecpg.c:64 #, c-format msgid "%s home page: <%s>\n" msgstr "%s-ის საწყისი გვერდია: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: ჩემი საკუთარი გამშვები ფაილის ბილიკის მოძებნა შეუძლებელია\n" -#: ecpg.c:184 ecpg.c:235 ecpg.c:249 ecpg.c:275 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "მეტი ინფორმაციისთვის სცადეთ '%s --help'.\n" -#: ecpg.c:192 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: დამმუშავებლის გამართვის მხარდაჭერა (-d) არ არსებობს\n" -#: ecpg.c:219 ecpg.c:334 ecpg.c:345 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format msgid "%s: could not open file \"%s\": %m\n" msgstr "%s: ფაილის გახსნის შეცდომა \"%s\": %m\n" -#: ecpg.c:263 +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, PostgreSQL-ის ჩაშენებული C პრეპროცესორი, ვერსია %s\n" -#: ecpg.c:265 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... ძებნა იწყება აქ:\n" -#: ecpg.c:268 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "ძებნის სიის დასასრული\n" -#: ecpg.c:274 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: შეყვანის ფაილები მითითებული არაა\n" -#: ecpg.c:478 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "კურსორი \"%s\" აღწერილია, მაგრამ არა გახსნილი" -#: ecpg.c:491 preproc.y:130 +#: ecpg.c:504 util.c:75 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "გამოტანის ფაილის წაშლის შეცდომა: \"%s\"\n" -#: pgc.l:520 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "დაუსრულებელი /* კომენტარი" -#: pgc.l:537 +#: pgc.l:560 #, c-format msgid "unterminated bit string literal" msgstr "გაწყვეტილი ბიტური სტრიქონი" -#: pgc.l:545 +#: pgc.l:570 #, c-format msgid "unterminated hexadecimal string literal" msgstr "გაწყვეტილი თექვსმეტობითი სტრიქონი" -#: pgc.l:620 +#: pgc.l:644 #, c-format msgid "invalid bit string literal" msgstr "არასწორი ბიტური სტრიქონი" -#: pgc.l:625 +#: pgc.l:649 #, c-format msgid "invalid hexadecimal string literal" msgstr "არასწორი თექვსმეტობითი სტრიქონი" -#: pgc.l:643 +#: pgc.l:667 #, c-format msgid "unhandled previous state in xqs\n" msgstr "დაუმუშავებელი წინა მდგომარეობა დაუხურავი ბრჭყალის აღმოჩენისას\n" -#: pgc.l:669 pgc.l:778 +#: pgc.l:700 pgc.l:820 #, c-format msgid "unterminated quoted string" msgstr "ბრჭყალებში ჩასმული ციტატის დაუსრულებელი სტრიქონი" -#: pgc.l:720 +#: pgc.l:753 #, c-format msgid "unterminated dollar-quoted string" msgstr "$-ით დაწყებული სტრიქონ დაუმთავრებელია" -#: pgc.l:738 pgc.l:758 +#: pgc.l:772 pgc.l:793 #, c-format msgid "zero-length delimited identifier" msgstr "გამყოფის ნულოვანი სიგრძის იდენტიფიკატორი" -#: pgc.l:769 +#: pgc.l:809 #, c-format msgid "unterminated quoted identifier" msgstr "დაუსრულებელი იდენტიფიკატორი ბრჭყალებში" -#: pgc.l:938 +#: pgc.l:985 +#, c-format +msgid "parameter number too large" +msgstr "პარამეტრების რაოდენობა მეტისმეტად დიდია" + +#: pgc.l:990 #, c-format msgid "trailing junk after parameter" msgstr "პარამეტრის შემდეგ მოყოლილი მონაცემები ნაგავია" -#: pgc.l:990 pgc.l:993 pgc.l:996 pgc.l:999 pgc.l:1002 pgc.l:1005 +#: pgc.l:1042 pgc.l:1045 pgc.l:1048 #, c-format msgid "trailing junk after numeric literal" msgstr "რიცხვითი მნიშვნელობის შემდეგ მონაცემები ნაგავია" -#: pgc.l:1127 +#: pgc.l:1177 #, c-format msgid "nested /* ... */ comments" msgstr "ჩადგმული /* ... */ კომენტარები" -#: pgc.l:1220 +#: pgc.l:1279 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "ბრძანებაში EXEC SQL UNDEF იდენტიფიკატორი აკლია" -#: pgc.l:1238 pgc.l:1251 pgc.l:1267 pgc.l:1280 +#: pgc.l:1299 pgc.l:1312 pgc.l:1328 pgc.l:1341 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "\"EXEC SQL IFDEF\"-ის მეტისმეტად ბევრი ჩადგმული პირობა" -#: pgc.l:1296 pgc.l:1307 pgc.l:1322 pgc.l:1344 +#: pgc.l:1357 pgc.l:1368 pgc.l:1384 pgc.l:1406 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "შესატყვისი \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\" არ არსებობს" -#: pgc.l:1298 pgc.l:1309 pgc.l:1490 +#: pgc.l:1359 pgc.l:1370 pgc.l:1565 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "აკლია \"EXEC SQL ENDIF;\"" -#: pgc.l:1324 pgc.l:1346 +#: pgc.l:1386 pgc.l:1408 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "ერთზე მეტი EXEC SQL ELSE" -#: pgc.l:1369 pgc.l:1383 +#: pgc.l:1431 pgc.l:1445 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "უწყვილო EXEC SQL ENDIF" -#: pgc.l:1438 +#: pgc.l:1507 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "ბრძანებას: EXEC SQL IFDEFიდენტიფიკატორი აკლია" -#: pgc.l:1447 +#: pgc.l:1516 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "ბრძანებას: EXEC SQL DEFINE იდენტიფიკატორი აკლია" -#: pgc.l:1480 +#: pgc.l:1554 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "სინტაქსური შეცდომა ბრძანებაში: EXEC SQL INCLUDE" -#: pgc.l:1530 +#: pgc.l:1609 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "შიდა შეცდომა: მდგომარეობა მიუწვდომელია; მისწერეთ ეს <%s>-ს" -#: pgc.l:1682 +#: pgc.l:1766 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "შეცდომა: ჩასართავი ბილიკი \"%s/%s\" ძალიან გრძელია, ხაზზე %d. გამოტოვება\n" -#: pgc.l:1705 +#: pgc.l:1793 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "ჩასასმელი ფაილის (\"%s\") გახსნის შეცდომა. ხაზზე %d" -#: preproc.y:31 +#: preproc.y:28 msgid "syntax error" msgstr "სინტაქსური შეცდომა" -#: preproc.y:84 -#, c-format -msgid "WARNING: " -msgstr "გაფრთხილება: " - -#: preproc.y:87 -#, c-format -msgid "ERROR: " -msgstr "შეცდომა: " - -#: preproc.y:514 +#: preproc.y:467 #, c-format msgid "cursor \"%s\" does not exist" msgstr "კურსორი \"%s\" არ არსებობს" -#: preproc.y:543 +#: preproc.y:503 #, c-format msgid "initializer not allowed in type definition" msgstr "ტიპის აღწერისას ინიციალიზატორი დაუშვებელია" -#: preproc.y:545 +#: preproc.y:505 #, c-format msgid "type name \"string\" is reserved in Informix mode" msgstr "informix-ის რეჟიმში ტიპის სახელი \"string\" დაცულია" -#: preproc.y:552 preproc.y:18523 +#: preproc.y:512 preproc.y:8822 #, c-format msgid "type \"%s\" is already defined" msgstr "ტიპი უკვე აღწერილია: %s" -#: preproc.y:577 preproc.y:19158 preproc.y:19480 variable.c:625 +#: preproc.y:539 preproc.y:9536 preproc.y:9881 variable.c:652 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "მრავალგანზომილებიანი მასივები მონაცემების მარტივი ტიპებისთვის მხარდაჭერილი არაა" -#: preproc.y:599 +#: preproc.y:562 #, c-format msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "კავშირი %s გადაწერილია %s-სთან ერთად DECLARE ბრძანების მიერ %s" -#: preproc.y:1810 +#: preproc.y:932 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "ოპერატორში \"CLOSE DATABASE\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2060 +#: preproc.y:1184 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "ოპერატორში \"CONNECT\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2100 +#: preproc.y:1221 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "ოპერატორში \"DISCONNECT\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2155 +#: preproc.y:1274 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "ოპერატორში \"SET CONNECTION\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2177 +#: preproc.y:1292 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "ოპერატორში \"TYPE\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2186 +#: preproc.y:1300 #, c-format msgid "AT option not allowed in VAR statement" msgstr "ოპერატორში \"VAR\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2193 +#: preproc.y:1307 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "ოპერატორში \"WHENEVER\" პარამეტრი \"AT\" დაუშვებელია" -#: preproc.y:2318 preproc.y:2490 preproc.y:2495 preproc.y:2607 preproc.y:4317 -#: preproc.y:4391 preproc.y:4982 preproc.y:5515 preproc.y:5853 preproc.y:6057 -#: preproc.y:6158 preproc.y:7722 preproc.y:9330 preproc.y:9335 preproc.y:12308 +#: preproc.y:1375 preproc.y:1498 preproc.y:2259 preproc.y:2585 preproc.y:3016 +#: preproc.y:3103 preproc.y:6086 #, c-format msgid "unsupported feature will be passed to server" msgstr "მხარდაუჭერელი ფუნქცია სერვერს გადაეცემა" -#: preproc.y:2865 +#: preproc.y:1610 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL განხორციელებული არაა" -#: preproc.y:3577 +#: preproc.y:1895 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN განხორციელებული არაა" -#: preproc.y:10385 preproc.y:18020 +#: preproc.y:5146 preproc.y:8273 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "\"database\" არ შეიძლება გამოყენებულ იქნას როგორც კურსორის სახელი INFORMIX რეჟიმში" -#: preproc.y:10392 preproc.y:18030 +#: preproc.y:5153 preproc.y:8283 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "\"%s\"ცვლადის სხვადასხვა პირობებში აღწერა მხარდაუჭერელია" -#: preproc.y:10394 preproc.y:18032 +#: preproc.y:5155 preproc.y:8285 #, c-format msgid "cursor \"%s\" is already defined" msgstr "კურსორი უკვე აღწერილია: \"%s\"" -#: preproc.y:10868 +#: preproc.y:5402 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "სერვერზე გადაცემული LIMIT #.# სინტაქსი მხარდაჭერილი აღარაა" -#: preproc.y:17712 preproc.y:17719 +#: preproc.y:7921 preproc.y:7929 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS არ შეიძლება INTO მიეთითოს" -#: preproc.y:17755 +#: preproc.y:7974 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "მოველოდი \"@\", მივიღე \"%s\"" -#: preproc.y:17767 +#: preproc.y:7986 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "მხარდაჭერილია მხოლოდ პროტოკოლები \"tcp\" და \"unix\" და მონაცემთა ბაზის ტიპი \"postgresql\"" -#: preproc.y:17770 +#: preproc.y:7989 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "მოველოდი \"://\", მივიღე \"%s\"" -#: preproc.y:17775 +#: preproc.y:7994 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unix-დომენის სოკეტები მხოლოდ \"localhost\"-ზე მუშაობს. მაგრამ არა \"%s\"-ზე" -#: preproc.y:17801 +#: preproc.y:8021 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "მოველოდი \"postgresql\", მივიღე \"%s\"" -#: preproc.y:17804 +#: preproc.y:8024 #, c-format msgid "invalid connection type: %s" msgstr "შეერთების არასწორი ტიპი: %s" -#: preproc.y:17813 +#: preproc.y:8033 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "მოველოდი \"@\"-ს ან \"://\"-ს, მივიღე \"%s\"" -#: preproc.y:17888 preproc.y:17906 +#: preproc.y:8131 preproc.y:8149 #, c-format msgid "invalid data type" msgstr "მონაცემების არასწორი ტიპი" -#: preproc.y:17917 preproc.y:17934 +#: preproc.y:8160 preproc.y:8177 #, c-format msgid "incomplete statement" msgstr "არასწორი პირობა" -#: preproc.y:17920 preproc.y:17937 +#: preproc.y:8163 preproc.y:8180 #, c-format msgid "unrecognized token \"%s\"" msgstr "უცნობი კოდი \"%s\"" -#: preproc.y:17982 +#: preproc.y:8235 #, c-format msgid "name \"%s\" is already declared" msgstr "სახელი \"%s\" უკვე აღწერილია" -#: preproc.y:18271 +#: preproc.y:8538 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "სიზუსტის / მასშტაბის არგუმენტი მხოლოდ მონაცემთა ტიპებს numeric და decimal აქვთ" -#: preproc.y:18342 +#: preproc.y:8637 #, c-format msgid "interval specification not allowed here" msgstr "აქ ინტერვალის სპეციფიკაცია დაუშვებელია" -#: preproc.y:18498 preproc.y:18550 +#: preproc.y:8793 preproc.y:8851 #, c-format msgid "too many levels in nested structure/union definition" msgstr "ჩადგმული სტრუქტურის/გაერთიანების მეტისმეტად ბევრი დონე" -#: preproc.y:18673 +#: preproc.y:8986 #, c-format msgid "pointers to varchar are not implemented" msgstr "varchar-ზე მაჩვენებლები მხარდაუჭერელია" -#: preproc.y:19124 +#: preproc.y:9501 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "ინიციალიზატორი დაუშვებელია EXEC SQL VAR ბრძანებაში" -#: preproc.y:19438 +#: preproc.y:9824 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "შესაყვანად ინდიკატორების მასივები დაუშვებელია" -#: preproc.y:19625 +#: preproc.y:10058 #, c-format msgid "operator not allowed in variable definition" msgstr "ცვლადის აღწერისას ოპერატორს ვერ გამოიყენებთ" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19666 +#: preproc.y:10103 #, c-format msgid "%s at or near \"%s\"" msgstr "%s \"%s\"-სთან ან ახლოს" -#: type.c:18 type.c:30 -#, c-format -msgid "out of memory" -msgstr "არასაკმარისი მეხსიერება" - -#: type.c:214 type.c:685 +#: type.c:191 type.c:661 #, c-format msgid "unrecognized variable type code %d" msgstr "ცვლადის ტიპის უცნობი კოდი: %d" -#: type.c:263 +#: type.c:240 #, c-format msgid "variable \"%s\" is hidden by a local variable of a different type" msgstr "ცვლადი \"%s\" დამალულია სხვა ტიპის ლოკალური ცხვლადის მიერ" -#: type.c:265 +#: type.c:242 #, c-format msgid "variable \"%s\" is hidden by a local variable" msgstr "ცვლადი \"%s\" დამალულია ლოკალური ცვლადის მიერ" -#: type.c:277 +#: type.c:254 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable of a different type" msgstr "ინდიკატორის ცვლადი \"%s\" იმალება სხვა ტიპის ლოკალური ცვლადის მიერ" -#: type.c:279 +#: type.c:256 #, c-format msgid "indicator variable \"%s\" is hidden by a local variable" msgstr "ინდიკატორის ცვლადი \"%s\" სხვა ტიპის ლოკალური ცვლადის მიერ იმალება" -#: type.c:287 +#: type.c:264 #, c-format msgid "indicator for array/pointer has to be array/pointer" msgstr "მასივის/მაჩვენებლის ინდიკატორი მასივი/მაჩვენებელი უნდა იყოს" -#: type.c:291 +#: type.c:268 #, c-format msgid "nested arrays are not supported (except strings)" msgstr "ჩადგმული მასივები მხარდაუჭერელია (სტრიქონების გარდა)" -#: type.c:333 +#: type.c:310 #, c-format msgid "indicator for struct has to be a struct" msgstr "სტრუქტურის ინდიკატორი სტრუქტურა უნდა იყოს" -#: type.c:353 type.c:374 type.c:394 +#: type.c:330 type.c:351 type.c:371 #, c-format msgid "indicator for simple data type has to be simple" msgstr "მარტივი მონაცემების ინდიკატორი მარტივი უნდა იყოს" -#: type.c:625 +#: type.c:602 #, c-format msgid "indicator struct \"%s\" has too few members" msgstr "ინდიკატორის სტრუქტურას ძალიან ცოტა წევრი ჰყავს: %s" -#: type.c:633 +#: type.c:610 #, c-format msgid "indicator struct \"%s\" has too many members" msgstr "ინდიკატორის სტრუქტურას ძალიან ბევრი წევრი ჰყავს: %s" -#: type.c:744 +#: type.c:723 #, c-format msgid "unrecognized descriptor item code %d" msgstr "დესკრიპტორის ჩანაწერის უცნობი კოდი: %d" +#: util.c:26 +#, c-format +msgid "WARNING: " +msgstr "გაფრთხილება: " + +#: util.c:29 +#, c-format +msgid "ERROR: " +msgstr "შეცდომა: " + +#: util.c:90 util.c:102 +#, c-format +msgid "out of memory" +msgstr "არასაკმარისი მეხსიერება" + #: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "არასწორად ჩამოყალიბებული ცვლადი \"%s\"" -#: variable.c:138 +#: variable.c:138 variable.c:237 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "ცვლადი %s მაჩვენებელი არაა" @@ -667,39 +671,44 @@ msgstr "ცვლადი \"%s\" არც სტრუქტურაა, ა msgid "variable \"%s\" is not an array" msgstr "ცვლადი %s მასივი არაა" -#: variable.c:232 variable.c:254 +#: variable.c:220 +#, c-format +msgid "unmatched bracket in variable \"%s\"" +msgstr "ფრჩხილი წყვილის გარეშე ცვლადში \"%s\"" + +#: variable.c:235 variable.c:258 #, c-format msgid "variable \"%s\" is not declared" msgstr "ცვლადი %s აღწერილი არაა" -#: variable.c:493 +#: variable.c:517 #, c-format msgid "indicator variable must have an integer type" msgstr "ინდიკატორ ცვლადს მთელი რიცხვის ტიპი უნდა ჰქონდეს" -#: variable.c:510 +#: variable.c:534 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "მონაცემების ტიპის უცნობი სახელი \"%s\"" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:548 variable.c:556 variable.c:573 variable.c:576 #, c-format msgid "multidimensional arrays are not supported" msgstr "მრავალგანზომილებიანი მასივები მხარდაჭერილი არაა" -#: variable.c:538 +#: variable.c:565 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "მრავალდონიანი მაჩვენებლები (2-ზე მეტი დონე) მხარდაუჭერელია; ნაპოვნია %d დონე" msgstr[1] "მრავალდონიანი მაჩვენებლები (2-ზე მეტი დონე) მხარდაუჭერელია; ნაპოვნია %d დონე" -#: variable.c:543 +#: variable.c:570 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "მონაცემების ამ ტიპისთვის მაჩვენებელი მაჩვენებელზე მხარდაჭერილი არაა" -#: variable.c:563 +#: variable.c:590 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "სტრუქტურების მრავალგანზომილებიანი მასივები მხარდაუჭერელია" diff --git a/src/interfaces/ecpg/preproc/po/ko.po b/src/interfaces/ecpg/preproc/po/ko.po index 6b55d4eb4e24d..77d4029a5866b 100644 --- a/src/interfaces/ecpg/preproc/po/ko.po +++ b/src/interfaces/ecpg/preproc/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: ecpg (PostgreSQL) 16\n" +"Project-Id-Version: ecpg (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:40+0000\n" -"PO-Revision-Date: 2023-05-30 12:36+0900\n" +"POT-Creation-Date: 2025-01-17 04:40+0000\n" +"PO-Revision-Date: 2025-01-16 10:32+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -187,178 +187,178 @@ msgstr "" msgid "%s home page: <%s>\n" msgstr "%s 홈페이지: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: 실행 가능한 경로를 지정할 수 없습니다\n" -#: ecpg.c:184 ecpg.c:235 ecpg.c:249 ecpg.c:275 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "자제한 사항은 \"%s --help\" 명령으로 살펴보십시오.\n" -#: ecpg.c:192 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: 파서 디버그 지원(-d)을 사용할 수 없음\n" -#: ecpg.c:219 ecpg.c:334 ecpg.c:345 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s: \"%s\" 파일 열 수 없음: %s\n" +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s: \"%s\" 파일 열 수 없음: %m\n" -#: ecpg.c:263 +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, PostgreSQL 포함 C 전처리기, 버전 %s\n" -#: ecpg.c:265 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... 여기서 검색 시작:\n" -#: ecpg.c:268 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "검색 목록의 끝\n" -#: ecpg.c:274 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: 지정된 입력 파일 없음\n" -#: ecpg.c:478 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "\"%s\" 커서가 선언되었지만 열리지 않음" -#: ecpg.c:491 preproc.y:130 +#: ecpg.c:504 preproc.y:130 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "출력 파일 \"%s\"을(를) 제거할 수 없음\n" -#: pgc.l:520 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "마무리 안된 /* 주석" -#: pgc.l:537 +#: pgc.l:559 #, c-format msgid "unterminated bit string literal" msgstr "마무리 안된 비트 문자열 문자" -#: pgc.l:545 +#: pgc.l:567 #, c-format msgid "unterminated hexadecimal string literal" msgstr "마무리 안된 16진수 문자열 문자" -#: pgc.l:620 +#: pgc.l:642 #, c-format msgid "invalid bit string literal" msgstr "잘못된 비트 문자열 리터럴" -#: pgc.l:625 +#: pgc.l:647 #, c-format msgid "invalid hexadecimal string literal" msgstr "잘못된 16진수 문자열 문자" -#: pgc.l:643 +#: pgc.l:665 #, c-format msgid "unhandled previous state in xqs\n" msgstr "xqs 안에 다룰 수 없는 이전 상태값 있음\n" -#: pgc.l:669 pgc.l:778 +#: pgc.l:691 pgc.l:800 #, c-format msgid "unterminated quoted string" msgstr "마무리 안된 따옴표 안의 문자열" -#: pgc.l:720 +#: pgc.l:742 #, c-format msgid "unterminated dollar-quoted string" msgstr "마무리 안된 따옴표 안의 문자열" -#: pgc.l:738 pgc.l:758 +#: pgc.l:760 pgc.l:780 #, c-format msgid "zero-length delimited identifier" msgstr "길이가 0인 구분 식별자" -#: pgc.l:769 +#: pgc.l:791 #, c-format msgid "unterminated quoted identifier" msgstr "마무리 안된 따옴표 안의 식별자" -#: pgc.l:938 +#: pgc.l:960 #, c-format msgid "trailing junk after parameter" msgstr "매개 변수 뒤에 뭔가 붙었음" -#: pgc.l:990 pgc.l:993 pgc.l:996 pgc.l:999 pgc.l:1002 pgc.l:1005 +#: pgc.l:1012 pgc.l:1015 pgc.l:1018 #, c-format msgid "trailing junk after numeric literal" msgstr "숫자 뒤에 문자가 붙었습니다" -#: pgc.l:1127 +#: pgc.l:1141 #, c-format msgid "nested /* ... */ comments" msgstr "중첩된 /* ... */ 주석" -#: pgc.l:1220 +#: pgc.l:1240 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "EXEC SQL UNDEF 명령에 식별자 누락" -#: pgc.l:1238 pgc.l:1251 pgc.l:1267 pgc.l:1280 +#: pgc.l:1258 pgc.l:1271 pgc.l:1287 pgc.l:1300 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "중첩된 EXEC SQL IFDEF 조건이 너무 많음" -#: pgc.l:1296 pgc.l:1307 pgc.l:1322 pgc.l:1344 +#: pgc.l:1316 pgc.l:1327 pgc.l:1342 pgc.l:1364 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "일치하는 \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\" 누락" -#: pgc.l:1298 pgc.l:1309 pgc.l:1490 +#: pgc.l:1318 pgc.l:1329 pgc.l:1522 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "\"EXEC SQL ENDIF;\" 누락" -#: pgc.l:1324 pgc.l:1346 +#: pgc.l:1344 pgc.l:1366 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "두 개 이상의 EXEC SQL ELSE" -#: pgc.l:1369 pgc.l:1383 +#: pgc.l:1389 pgc.l:1403 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "일치하지 않는 EXEC SQL ENDIF" -#: pgc.l:1438 +#: pgc.l:1464 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "EXEC SQL IFDEF 명령에 식별자 누락" -#: pgc.l:1447 +#: pgc.l:1473 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "EXEC SQL DEFINE 명령에 식별자 누락" -#: pgc.l:1480 +#: pgc.l:1511 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "EXEC SQL INCLUDE 명령에 구문 오류 발생" -#: pgc.l:1530 +#: pgc.l:1566 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "" "내부 오류: 상태값을 알 수 없습니다. 이 문제를 <%s> 주소로 알려주십시오." -#: pgc.l:1682 +#: pgc.l:1718 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "오류: 포함 경로 \"%s/%s\"이(가) %d줄에서 너무 길어서 건너뜀\n" -#: pgc.l:1705 +#: pgc.l:1741 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "포함 파일 \"%s\"을(를) %d줄에서 열 수 없음" @@ -392,12 +392,12 @@ msgstr "형식 정의에 이니셜라이저가 허용되지 않음" msgid "type name \"string\" is reserved in Informix mode" msgstr "\"string\" 자료형 이름은 인포믹스 모드에서 예약어로 쓰입니다" -#: preproc.y:552 preproc.y:18392 +#: preproc.y:552 preproc.y:19034 #, c-format msgid "type \"%s\" is already defined" msgstr "\"%s\" 형식이 이미 정의됨" -#: preproc.y:577 preproc.y:19027 preproc.y:19349 variable.c:625 +#: preproc.y:577 preproc.y:19669 preproc.y:19991 variable.c:624 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "단순 데이터 형식에 다차원 배열이 지원되지 않음" @@ -407,89 +407,88 @@ msgstr "단순 데이터 형식에 다차원 배열이 지원되지 않음" msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "%s 연결은 %s 연결로 바뀌었음, 해당 DECLARE 구문: %s" -#: preproc.y:1792 +#: preproc.y:1831 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "CLOSE DATABASE 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2042 +#: preproc.y:2081 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "CONNECT 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2082 +#: preproc.y:2121 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "DISCONNECT 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2137 +#: preproc.y:2176 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "SET CONNECTION 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2159 +#: preproc.y:2198 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "TYPE 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2168 +#: preproc.y:2207 #, c-format msgid "AT option not allowed in VAR statement" msgstr "VAR 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2175 +#: preproc.y:2214 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "WHENEVER 문에 AT 옵션이 허용되지 않음" -#: preproc.y:2300 preproc.y:2472 preproc.y:2477 preproc.y:2589 preproc.y:4248 -#: preproc.y:4322 preproc.y:4913 preproc.y:5446 preproc.y:5784 preproc.y:6084 -#: preproc.y:7648 preproc.y:9252 preproc.y:9257 preproc.y:12206 +#: preproc.y:2339 preproc.y:2626 preproc.y:4349 preproc.y:5021 preproc.y:5891 +#: preproc.y:6095 preproc.y:6196 preproc.y:12460 #, c-format msgid "unsupported feature will be passed to server" msgstr "지원되지 않는 기능이 서버에 전달됨" -#: preproc.y:2847 +#: preproc.y:2884 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL이 구현되지 않음" -#: preproc.y:3531 +#: preproc.y:3596 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN이 구현되지 않음" -#: preproc.y:10303 preproc.y:17889 +#: preproc.y:10444 preproc.y:18503 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "INFORMIX 모드에서는 \"database\"를 커서 이름으로 사용할 수 없음" -#: preproc.y:10310 preproc.y:17899 +#: preproc.y:10451 preproc.y:18513 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "서로 다른 선언 구문에서 \"%s\" 변수 사용은 지원하지 않습니다" -#: preproc.y:10312 preproc.y:17901 +#: preproc.y:10453 preproc.y:18515 #, c-format msgid "cursor \"%s\" is already defined" msgstr "\"%s\" 커서가 이미 정의됨" -#: preproc.y:10786 +#: preproc.y:10927 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "더 이상 지원되지 않는 LIMIT #,# 구문이 서버에 전달됨" -#: preproc.y:17581 preproc.y:17588 +#: preproc.y:18195 preproc.y:18202 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS에서 INTO를 지정할 수 없음" -#: preproc.y:17624 +#: preproc.y:18238 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "\"@\"이 필요한데 \"%s\"이(가) 있음" -#: preproc.y:17636 +#: preproc.y:18250 #, c-format msgid "" "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are " @@ -497,89 +496,89 @@ msgid "" msgstr "" "\"tcp\" 및 \"unix\" 프로토콜과 데이터베이스 형식 \"postgresql\"만 지원됨" -#: preproc.y:17639 +#: preproc.y:18253 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "\"://\"가 필요한데 \"%s\"이(가) 있음" -#: preproc.y:17644 +#: preproc.y:18258 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "" "Unix-domain 소켓은 \"localhost\"에서만 작동하며 \"%s\"에서는 작동하지 않음" -#: preproc.y:17670 +#: preproc.y:18284 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "\"postgresql\"이 필요한데 \"%s\"이(가) 있음" -#: preproc.y:17673 +#: preproc.y:18287 #, c-format msgid "invalid connection type: %s" msgstr "잘못된 연결 형식: %s" -#: preproc.y:17682 +#: preproc.y:18296 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "\"@\" 또는 \"://\"가 필요한데 \"%s\"이(가) 있음" -#: preproc.y:17757 preproc.y:17775 +#: preproc.y:18371 preproc.y:18389 #, c-format msgid "invalid data type" msgstr "잘못된 데이터 형식" -#: preproc.y:17786 preproc.y:17803 +#: preproc.y:18400 preproc.y:18417 #, c-format msgid "incomplete statement" msgstr "불완전한 문" -#: preproc.y:17789 preproc.y:17806 +#: preproc.y:18403 preproc.y:18420 #, c-format msgid "unrecognized token \"%s\"" msgstr "인식할 수 없는 토큰 \"%s\"" -#: preproc.y:17851 +#: preproc.y:18465 #, c-format msgid "name \"%s\" is already declared" msgstr "\"%s\" 이름이 이미 정의됨" -#: preproc.y:18140 +#: preproc.y:18754 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "숫자 및 10진수 데이터 형식에만 전체 자릿수/소수 자릿수 인수 포함" -#: preproc.y:18211 +#: preproc.y:18853 #, c-format msgid "interval specification not allowed here" msgstr "여기에는 간격 지정이 허용되지 않음" -#: preproc.y:18367 preproc.y:18419 +#: preproc.y:19009 preproc.y:19061 #, c-format msgid "too many levels in nested structure/union definition" msgstr "중첩된 구조/union 정의에 수준이 너무 많음" -#: preproc.y:18542 +#: preproc.y:19184 #, c-format msgid "pointers to varchar are not implemented" msgstr "varchar에 대한 포인터가 구현되지 않음" -#: preproc.y:18993 +#: preproc.y:19635 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "EXEC SQL VAR 명령에 이니셜라이저가 허용되지 않음" -#: preproc.y:19307 +#: preproc.y:19949 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "입력에서 표시기의 배열이 허용되지 않음" -#: preproc.y:19494 +#: preproc.y:20136 #, c-format msgid "operator not allowed in variable definition" msgstr "연산자는 동적 정의 영역에서는 사용할 수 없음" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19535 +#: preproc.y:20177 #, c-format msgid "%s at or near \"%s\"" msgstr "%s, \"%s\" 부근" @@ -680,22 +679,22 @@ msgstr "\"%s\" 변수가 배열이 아님" msgid "variable \"%s\" is not declared" msgstr "\"%s\" 변수가 선언되지 않음" -#: variable.c:493 +#: variable.c:492 #, c-format msgid "indicator variable must have an integer type" msgstr "표시기 변수에 정수 형식이 있어야 함" -#: variable.c:510 +#: variable.c:509 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "인식할 수 없는 데이터 형식 이름 \"%s\"" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:520 variable.c:528 variable.c:545 variable.c:548 #, c-format msgid "multidimensional arrays are not supported" msgstr "다차원 배열이 지원되지 않음" -#: variable.c:538 +#: variable.c:537 #, c-format msgid "" "multilevel pointers (more than 2 levels) are not supported; found %d level" @@ -703,12 +702,12 @@ msgid_plural "" "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "다중단계 포인터(2단계 이상)는 지원하지 않음; 발견된 레벨: %d" -#: variable.c:543 +#: variable.c:542 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "이 데이터 형식에는 포인터에 대한 포인터가 지원되지 않음" -#: variable.c:563 +#: variable.c:562 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "구조에는 다차원 배열이 지원되지 않음" diff --git a/src/interfaces/ecpg/preproc/po/meson.build b/src/interfaces/ecpg/preproc/po/meson.build index c37de37037dc5..208861ade7234 100644 --- a/src/interfaces/ecpg/preproc/po/meson.build +++ b/src/interfaces/ecpg/preproc/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('ecpg-' + pg_version_major.to_string())] diff --git a/src/interfaces/ecpg/preproc/po/ru.po b/src/interfaces/ecpg/preproc/po/ru.po index b72b5cd79eadc..874da38e6428d 100644 --- a/src/interfaces/ecpg/preproc/po/ru.po +++ b/src/interfaces/ecpg/preproc/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for ecpg # Copyright (C) 2012-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: ecpg (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2022-09-05 13:32+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-09-04 07:22+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -203,8 +203,8 @@ msgstr "%s: отладочные сообщения при разборе (-d) #: ecpg.c:230 ecpg.c:345 ecpg.c:356 #, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s: не удалось открыть файл \"%s\": %s\n" +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s: не удалось открыть файл \"%s\": %m\n" #: ecpg.c:274 #, c-format @@ -236,131 +236,131 @@ msgstr "курсор \"%s\" был объявлен, но не открыт" msgid "could not remove output file \"%s\"\n" msgstr "ошибка при удалении выходного файла \"%s\"\n" -#: pgc.l:527 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "незавершённый комментарий /*" -#: pgc.l:544 +#: pgc.l:559 #, c-format msgid "unterminated bit string literal" msgstr "оборванная битовая строка" -#: pgc.l:552 +#: pgc.l:567 #, c-format msgid "unterminated hexadecimal string literal" msgstr "оборванная шестнадцатеричная строка" -#: pgc.l:627 +#: pgc.l:642 #, c-format msgid "invalid bit string literal" msgstr "неверная битовая строка" -#: pgc.l:632 +#: pgc.l:647 #, c-format msgid "invalid hexadecimal string literal" msgstr "неверная шестнадцатеричная строка" -#: pgc.l:650 +#: pgc.l:665 #, c-format msgid "unhandled previous state in xqs\n" msgstr "" "необрабатываемое предыдущее состояние при обнаружении закрывающего " "апострофа\n" -#: pgc.l:676 pgc.l:785 +#: pgc.l:691 pgc.l:800 #, c-format msgid "unterminated quoted string" msgstr "незавершённая строка в кавычках" -#: pgc.l:727 +#: pgc.l:742 #, c-format msgid "unterminated dollar-quoted string" msgstr "незавершённая строка с $" -#: pgc.l:745 pgc.l:765 +#: pgc.l:760 pgc.l:780 #, c-format msgid "zero-length delimited identifier" msgstr "пустой идентификатор в кавычках" -#: pgc.l:776 +#: pgc.l:791 #, c-format msgid "unterminated quoted identifier" msgstr "незавершённый идентификатор в кавычках" -#: pgc.l:945 +#: pgc.l:960 #, c-format msgid "trailing junk after parameter" msgstr "мусорное содержимое после параметра" -#: pgc.l:997 pgc.l:1000 pgc.l:1003 pgc.l:1006 pgc.l:1009 pgc.l:1012 +#: pgc.l:1012 pgc.l:1015 pgc.l:1018 #, c-format msgid "trailing junk after numeric literal" msgstr "мусорное содержимое после числовой константы" -#: pgc.l:1135 +#: pgc.l:1141 #, c-format msgid "nested /* ... */ comments" msgstr "вложенные комментарии /* ... */" -#: pgc.l:1234 +#: pgc.l:1240 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "в команде EXEC SQL UNDEF отсутствует идентификатор" -#: pgc.l:1252 pgc.l:1265 pgc.l:1281 pgc.l:1294 +#: pgc.l:1258 pgc.l:1271 pgc.l:1287 pgc.l:1300 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "слишком много вложенных условий EXEC SQL IFDEF" -#: pgc.l:1310 pgc.l:1321 pgc.l:1336 pgc.l:1358 +#: pgc.l:1316 pgc.l:1327 pgc.l:1342 pgc.l:1364 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "нет соответствующего \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" -#: pgc.l:1312 pgc.l:1323 pgc.l:1516 +#: pgc.l:1318 pgc.l:1329 pgc.l:1522 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "отсутствует \"EXEC SQL ENDIF;\"" -#: pgc.l:1338 pgc.l:1360 +#: pgc.l:1344 pgc.l:1366 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "неоднократная команда EXEC SQL ELSE" -#: pgc.l:1383 pgc.l:1397 +#: pgc.l:1389 pgc.l:1403 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "непарная команда EXEC SQL ENDIF" -#: pgc.l:1458 +#: pgc.l:1464 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "в команде EXEC SQL IFDEF отсутствует идентификатор" -#: pgc.l:1467 +#: pgc.l:1473 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "в команде EXEC SQL DEFINE отсутствует идентификатор" -#: pgc.l:1505 +#: pgc.l:1511 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "ошибка синтаксиса в команде EXEC SQL INCLUDE" -#: pgc.l:1560 +#: pgc.l:1566 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "внутренняя ошибка: недостижимое состояние; пожалуйста, сообщите в <%s>" -#: pgc.l:1712 +#: pgc.l:1718 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "" "Ошибка: путь включаемых файлов \"%s/%s\" в строке %d слишком длинный, " "пропускается\n" -#: pgc.l:1735 +#: pgc.l:1741 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "не удалось открыть включаемый файл \"%s\" (строка %d)" @@ -394,12 +394,12 @@ msgstr "определение типа не может включать ини msgid "type name \"string\" is reserved in Informix mode" msgstr "имя типа \"string\" в режиме Informix зарезервировано" -#: preproc.y:552 preproc.y:18385 +#: preproc.y:552 preproc.y:19034 #, c-format msgid "type \"%s\" is already defined" msgstr "тип \"%s\" уже определён" -#: preproc.y:577 preproc.y:19020 preproc.y:19342 variable.c:625 +#: preproc.y:577 preproc.y:19669 preproc.y:19991 variable.c:624 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "многомерные массивы с простыми типами данных не поддерживаются" @@ -409,90 +409,90 @@ msgstr "многомерные массивы с простыми типами msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "подключение %s заменяется на %s оператором DECLARE %s" -#: preproc.y:1792 +#: preproc.y:1831 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "оператор CLOSE DATABASE с параметром AT не поддерживается" -#: preproc.y:2042 +#: preproc.y:2081 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "оператор CONNECT с параметром AT не поддерживается" -#: preproc.y:2082 +#: preproc.y:2121 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "оператор DISCONNECT с параметром AT не поддерживается" -#: preproc.y:2137 +#: preproc.y:2176 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "оператор SET CONNECTION с параметром AT не поддерживается" -#: preproc.y:2159 +#: preproc.y:2198 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "оператор TYPE с параметром AT не поддерживается" -#: preproc.y:2168 +#: preproc.y:2207 #, c-format msgid "AT option not allowed in VAR statement" msgstr "оператор VAR с параметром AT не поддерживается" -#: preproc.y:2175 +#: preproc.y:2214 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "оператор WHENEVER с параметром AT не поддерживается" -#: preproc.y:2300 preproc.y:2587 preproc.y:4246 preproc.y:4910 preproc.y:5780 -#: preproc.y:6080 preproc.y:12199 +#: preproc.y:2339 preproc.y:2626 preproc.y:4349 preproc.y:5021 preproc.y:5891 +#: preproc.y:6095 preproc.y:6196 preproc.y:12460 #, c-format msgid "unsupported feature will be passed to server" msgstr "неподдерживаемая функция будет передана серверу" -#: preproc.y:2845 +#: preproc.y:2884 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL не реализовано" -#: preproc.y:3529 +#: preproc.y:3596 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "операция COPY FROM STDIN не реализована" -#: preproc.y:10296 preproc.y:17882 +#: preproc.y:10444 preproc.y:18503 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "" "в режиме INFORMIX нельзя использовать \"database\" в качестве имени курсора" -#: preproc.y:10303 preproc.y:17892 +#: preproc.y:10451 preproc.y:18513 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "" "использование переменной \"%s\" в разных операторах DECLARE не поддерживается" -#: preproc.y:10305 preproc.y:17894 +#: preproc.y:10453 preproc.y:18515 #, c-format msgid "cursor \"%s\" is already defined" msgstr "курсор \"%s\" уже определён" -#: preproc.y:10779 +#: preproc.y:10927 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "не поддерживаемое более предложение LIMIT #,# передано на сервер" -#: preproc.y:17574 preproc.y:17581 +#: preproc.y:18195 preproc.y:18202 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "в CREATE TABLE AS нельзя указать INTO" -#: preproc.y:17617 +#: preproc.y:18238 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "ожидался знак \"@\", но на этом месте \"%s\"" -#: preproc.y:17629 +#: preproc.y:18250 #, c-format msgid "" "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are " @@ -501,89 +501,89 @@ msgstr "" "поддерживаются только протоколы \"tcp\" и \"unix\", а тип базы данных - " "\"postgresql\"" -#: preproc.y:17632 +#: preproc.y:18253 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "ожидалось \"://\", но на этом месте \"%s\"" -#: preproc.y:17637 +#: preproc.y:18258 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unix-сокеты работают только с \"localhost\", но не с адресом \"%s\"" -#: preproc.y:17663 +#: preproc.y:18284 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "ожидался тип \"postgresql\", но на этом месте \"%s\"" -#: preproc.y:17666 +#: preproc.y:18287 #, c-format msgid "invalid connection type: %s" msgstr "неверный тип подключения: %s" -#: preproc.y:17675 +#: preproc.y:18296 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "ожидалось \"@\" или \"://\", но на этом месте \"%s\"" -#: preproc.y:17750 preproc.y:17768 +#: preproc.y:18371 preproc.y:18389 #, c-format msgid "invalid data type" msgstr "неверный тип данных" -#: preproc.y:17779 preproc.y:17796 +#: preproc.y:18400 preproc.y:18417 #, c-format msgid "incomplete statement" msgstr "неполный оператор" -#: preproc.y:17782 preproc.y:17799 +#: preproc.y:18403 preproc.y:18420 #, c-format msgid "unrecognized token \"%s\"" msgstr "нераспознанное ключевое слово \"%s\"" -#: preproc.y:17844 +#: preproc.y:18465 #, c-format msgid "name \"%s\" is already declared" msgstr "имя \"%s\" уже объявлено" -#: preproc.y:18133 +#: preproc.y:18754 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "" "точность/масштаб можно указать только для типов данных numeric и decimal" -#: preproc.y:18204 +#: preproc.y:18853 #, c-format msgid "interval specification not allowed here" msgstr "определение интервала здесь не допускается" -#: preproc.y:18360 preproc.y:18412 +#: preproc.y:19009 preproc.y:19061 #, c-format msgid "too many levels in nested structure/union definition" msgstr "слишком много уровней в определении вложенной структуры/объединения" -#: preproc.y:18535 +#: preproc.y:19184 #, c-format msgid "pointers to varchar are not implemented" msgstr "указатели на varchar не реализованы" -#: preproc.y:18986 +#: preproc.y:19635 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "команда EXEC SQL VAR не может включать инициализатор" -#: preproc.y:19300 +#: preproc.y:19949 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "массивы индикаторов на входе недопустимы" -#: preproc.y:19487 +#: preproc.y:20136 #, c-format msgid "operator not allowed in variable definition" msgstr "недопустимый оператор в определении переменной" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:19528 +#: preproc.y:20177 #, c-format msgid "%s at or near \"%s\"" msgstr "%s (примерное положение: \"%s\")" @@ -684,22 +684,22 @@ msgstr "переменная \"%s\" - не массив" msgid "variable \"%s\" is not declared" msgstr "переменная \"%s\" не объявлена" -#: variable.c:493 +#: variable.c:492 #, c-format msgid "indicator variable must have an integer type" msgstr "переменная-индикатор должна быть целочисленной" -#: variable.c:510 +#: variable.c:509 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "нераспознанное имя типа данных \"%s\"" -#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 +#: variable.c:520 variable.c:528 variable.c:545 variable.c:548 #, c-format msgid "multidimensional arrays are not supported" msgstr "многомерные массивы не поддерживаются" -#: variable.c:538 +#: variable.c:537 #, c-format msgid "" "multilevel pointers (more than 2 levels) are not supported; found %d level" @@ -715,12 +715,12 @@ msgstr[2] "" "многоуровневые указатели (больше 2 уровней) не поддерживаются, обнаружено %d " "уровней" -#: variable.c:543 +#: variable.c:542 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "для этого типа данных указатели на указатели не поддерживаются" -#: variable.c:563 +#: variable.c:562 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "многомерные массивы структур не поддерживаются" diff --git a/src/interfaces/ecpg/preproc/po/sv.po b/src/interfaces/ecpg/preproc/po/sv.po index 3b8d67c61ddd6..2fb7e68894a3b 100644 --- a/src/interfaces/ecpg/preproc/po/sv.po +++ b/src/interfaces/ecpg/preproc/po/sv.po @@ -1,14 +1,14 @@ # SWEDISHE message translation file for ecpg # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 09:09+0000\n" -"PO-Revision-Date: 2022-04-11 14:39+0200\n" +"POT-Creation-Date: 2024-07-12 11:10+0000\n" +"PO-Revision-Date: 2024-07-12 15:07+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -22,37 +22,37 @@ msgstr "" msgid "variable \"%s\" must have a numeric type" msgstr "variabel \"%s\" måste ha en numerisk typ" -#: descriptor.c:125 descriptor.c:156 +#: descriptor.c:124 descriptor.c:155 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "deskriptor %s kopplad till anslutning %s finns inte" -#: descriptor.c:127 descriptor.c:158 +#: descriptor.c:126 descriptor.c:157 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "deskriptor %s kopplad till standardanslutning finns inte" -#: descriptor.c:173 descriptor.c:225 +#: descriptor.c:172 descriptor.c:224 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "deskriptor-header-post \"%d\" finns inte" -#: descriptor.c:195 +#: descriptor.c:194 #, c-format msgid "nullable is always 1" msgstr "nullable är alltid 1" -#: descriptor.c:198 +#: descriptor.c:197 #, c-format msgid "key_member is always 0" msgstr "key_member är alltid 0" -#: descriptor.c:292 +#: descriptor.c:291 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "deskriptor-post \"%s\" är inte implementerad" -#: descriptor.c:302 +#: descriptor.c:301 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "deskriptor-post \"%s\" kan inte sättas" @@ -184,177 +184,177 @@ msgstr "" msgid "%s home page: <%s>\n" msgstr "hemsida för %s: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: kunde inte hitta min egna körbara fils sökväg\n" -#: ecpg.c:176 ecpg.c:333 ecpg.c:344 -#, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s: kunde inte öppna fil \"%s\": %s\n" - -#: ecpg.c:219 ecpg.c:232 ecpg.c:248 ecpg.c:274 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Försök med \"%s --help\" för mer information.\n" -#: ecpg.c:243 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: parser-debug-stöd (-d) är inte tillgängligt\n" -#: ecpg.c:262 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 +#, c-format +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s: kunde inte öppna fil \"%s\": %m\n" + +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, PostgreSQLs inbäddade C-preprocessor, version %s\n" -#: ecpg.c:264 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... sökning startar här:\n" -#: ecpg.c:267 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "slut på söklista\n" -#: ecpg.c:273 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: inga indatafiler angivna\n" -#: ecpg.c:477 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "markören \"%s\" har deklarerats men inte öppnats" -#: ecpg.c:490 preproc.y:130 +#: ecpg.c:504 preproc.y:130 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "kunde inte ta bort utdatafil \"%s\"\n" -#: pgc.l:508 +#: pgc.l:528 #, c-format msgid "unterminated /* comment" msgstr "ej avslutad /*-kommentar" -#: pgc.l:525 +#: pgc.l:545 #, c-format msgid "unterminated bit string literal" msgstr "ej avslutad bitsträngslitteral" -#: pgc.l:533 +#: pgc.l:553 #, c-format msgid "unterminated hexadecimal string literal" msgstr "ej avslutad hexadecimal stränglitteral" -#: pgc.l:608 +#: pgc.l:628 #, c-format msgid "invalid bit string literal" msgstr "ogiltig bit-sträng-literal" -#: pgc.l:613 +#: pgc.l:633 #, c-format msgid "invalid hexadecimal string literal" msgstr "ogiltig hexdecimal sträng-literal" -#: pgc.l:631 +#: pgc.l:651 #, c-format msgid "unhandled previous state in xqs\n" msgstr "tidigare state i xqs som ej kan hanteras\n" -#: pgc.l:657 pgc.l:766 +#: pgc.l:677 pgc.l:786 #, c-format msgid "unterminated quoted string" msgstr "icketerminerad citerad sträng" -#: pgc.l:708 +#: pgc.l:728 #, c-format msgid "unterminated dollar-quoted string" msgstr "icke terminerad dollarciterad sträng" -#: pgc.l:726 pgc.l:746 +#: pgc.l:746 pgc.l:766 #, c-format msgid "zero-length delimited identifier" msgstr "noll-längds avdelad identifierare" -#: pgc.l:757 +#: pgc.l:777 #, c-format msgid "unterminated quoted identifier" msgstr "ej avslutad citerad identifierare" -#: pgc.l:926 +#: pgc.l:946 #, c-format msgid "trailing junk after parameter" msgstr "efterföljande skräp efter parameter" -#: pgc.l:968 pgc.l:971 pgc.l:974 +#: pgc.l:998 pgc.l:1001 pgc.l:1004 pgc.l:1007 pgc.l:1010 pgc.l:1013 #, c-format msgid "trailing junk after numeric literal" msgstr "efterföljande skräp efter numerisk literal" -#: pgc.l:1100 +#: pgc.l:1136 #, c-format msgid "nested /* ... */ comments" msgstr "nästlade /* ... */-kommentarer" -#: pgc.l:1193 +#: pgc.l:1235 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "saknar identifierare i EXEC SQL UNDEF-kommando" -#: pgc.l:1211 pgc.l:1224 pgc.l:1240 pgc.l:1253 +#: pgc.l:1253 pgc.l:1266 pgc.l:1282 pgc.l:1295 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "för många nästlade EXEC SQL IFDEF-villkor" -#: pgc.l:1269 pgc.l:1280 pgc.l:1295 pgc.l:1317 +#: pgc.l:1311 pgc.l:1322 pgc.l:1337 pgc.l:1359 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "saknar matchande \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" -#: pgc.l:1271 pgc.l:1282 pgc.l:1463 +#: pgc.l:1313 pgc.l:1324 pgc.l:1517 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "saknar \"EXEC SQL ENDIF;\"" -#: pgc.l:1297 pgc.l:1319 +#: pgc.l:1339 pgc.l:1361 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "mer än en EXEC SQL ELSE" -#: pgc.l:1342 pgc.l:1356 +#: pgc.l:1384 pgc.l:1398 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "ej matchad EXEC SQL ENDIF" -#: pgc.l:1411 +#: pgc.l:1459 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "saknar identifierare i EXEC SQL IFDEF-kommando" -#: pgc.l:1420 +#: pgc.l:1468 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "saknar identifierare i EXEC SQL DEFINE-kommando" -#: pgc.l:1453 +#: pgc.l:1506 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "syntaxfel i EXEC SQL INCLUDE-kommando" -#: pgc.l:1503 +#: pgc.l:1561 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "internt fel: state som ej skall kunna nås; vänligen rapportera detta till <%s>" -#: pgc.l:1655 +#: pgc.l:1713 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "Fel: include-sökväg \"%s/%s\" är för lång på rad %d, hoppar över\n" -#: pgc.l:1678 +#: pgc.l:1736 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "kunde inte öppna inkludefil \"%s\" på rad %d" @@ -388,12 +388,12 @@ msgstr "initialiserare tillåts inte i typdefinition" msgid "type name \"string\" is reserved in Informix mode" msgstr "typnamn \"string\" är reserverat i Informix-läge" -#: preproc.y:552 preproc.y:19317 +#: preproc.y:552 preproc.y:19072 #, c-format msgid "type \"%s\" is already defined" msgstr "typen \"%s\" är redan definierad" -#: preproc.y:577 preproc.y:19952 preproc.y:20277 variable.c:621 +#: preproc.y:577 preproc.y:19707 preproc.y:20029 variable.c:625 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "multidimensionella array:er för enkla datatyper stöds inte" @@ -403,180 +403,174 @@ msgstr "multidimensionella array:er för enkla datatyper stöds inte" msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "anslutning %s överskriven med %s av DECLARE-sats %s" -#: preproc.y:1872 +#: preproc.y:1833 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "AT-flaggan tillåts inte i CLOSE DATABASE-sats" -#: preproc.y:2122 +#: preproc.y:2083 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "AT-flaggan tillåts inte i CONNECT-sats" -#: preproc.y:2162 +#: preproc.y:2123 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "AT-flaggan tillåts inte i DISCONNECT-sats" -#: preproc.y:2217 +#: preproc.y:2178 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "AT-flaggan tillåts inte i SET CONNECTION-sats" -#: preproc.y:2239 +#: preproc.y:2200 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "AT-flaggan tillåts inte i TYPE-sats" -#: preproc.y:2248 +#: preproc.y:2209 #, c-format msgid "AT option not allowed in VAR statement" msgstr "AT-flaggan tillåts inte i VAR-sats" -#: preproc.y:2255 +#: preproc.y:2216 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "AT-flaggan tillåts inte i WHENEVER-sats" -#: preproc.y:2332 preproc.y:2504 preproc.y:2509 preproc.y:2632 preproc.y:4283 -#: preproc.y:4357 preproc.y:4948 preproc.y:5481 preproc.y:5819 preproc.y:6119 -#: preproc.y:7687 preproc.y:9288 preproc.y:9293 preproc.y:12272 +#: preproc.y:2341 preproc.y:2628 preproc.y:4379 preproc.y:5043 preproc.y:5913 +#: preproc.y:6117 preproc.y:6218 preproc.y:12482 #, c-format msgid "unsupported feature will be passed to server" msgstr "ej stödd funktion skickass till servern" -#: preproc.y:2890 +#: preproc.y:2886 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL är inte implementerad" -#: preproc.y:3589 +#: preproc.y:3626 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN är inte implementerad" -#: preproc.y:10335 preproc.y:18892 +#: preproc.y:10466 preproc.y:18541 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "\"database\" kan inte användas som markörsnamn i INFORMIX-läge" -#: preproc.y:10342 preproc.y:18902 +#: preproc.y:10473 preproc.y:18551 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "använda variabel \"%s\" i olika deklarationssatser stöds inte" -#: preproc.y:10344 preproc.y:18904 +#: preproc.y:10475 preproc.y:18553 #, c-format msgid "cursor \"%s\" is already defined" msgstr "markören \"%s\" är redan definierad" -#: preproc.y:10818 +#: preproc.y:10949 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "ej längre stödd syntax LIMIT #,# har skickats till servern" -#: preproc.y:11151 preproc.y:11158 -#, c-format -msgid "subquery in FROM must have an alias" -msgstr "subfråga i FROM måste ha ett alias" - -#: preproc.y:18584 preproc.y:18591 +#: preproc.y:18233 preproc.y:18240 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS kan inte ange INTO" -#: preproc.y:18627 +#: preproc.y:18276 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "förväntade \"@\", hittade \"%s\"" -#: preproc.y:18639 +#: preproc.y:18288 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "bara protokoll \"tcp\" och \"unix\" samt databastyp \"postgresql\" stöds" -#: preproc.y:18642 +#: preproc.y:18291 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "förväntade \"://\", hittade \"%s\"" -#: preproc.y:18647 +#: preproc.y:18296 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unix-domän-socket fungerart bara på \"localhost\" men inte på \"%s\"" -#: preproc.y:18673 +#: preproc.y:18322 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "förväntade \"postgresql\", hittade \"%s\"" -#: preproc.y:18676 +#: preproc.y:18325 #, c-format msgid "invalid connection type: %s" msgstr "ogiltig anslutningstyp: %s" -#: preproc.y:18685 +#: preproc.y:18334 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "förväntade \"@\" eller \"://\", hittade \"%s\"" -#: preproc.y:18760 preproc.y:18778 +#: preproc.y:18409 preproc.y:18427 #, c-format msgid "invalid data type" msgstr "ogiltig datatyp" -#: preproc.y:18789 preproc.y:18806 +#: preproc.y:18438 preproc.y:18455 #, c-format msgid "incomplete statement" msgstr "ofullständig sats" -#: preproc.y:18792 preproc.y:18809 +#: preproc.y:18441 preproc.y:18458 #, c-format msgid "unrecognized token \"%s\"" msgstr "okänd symbol \"%s\"" -#: preproc.y:18854 +#: preproc.y:18503 #, c-format msgid "name \"%s\" is already declared" msgstr "namnet \"%s\" är redan deklarerat" -#: preproc.y:19120 +#: preproc.y:18792 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "bara datatyperna numeric och decimal har precision/skala-argument" -#: preproc.y:19132 +#: preproc.y:18891 #, c-format msgid "interval specification not allowed here" msgstr "intervallspecifikation tillåts inte här" -#: preproc.y:19292 preproc.y:19344 +#: preproc.y:19047 preproc.y:19099 #, c-format msgid "too many levels in nested structure/union definition" msgstr "för många nästlade nivåer i struktur/union-definition" -#: preproc.y:19467 +#: preproc.y:19222 #, c-format msgid "pointers to varchar are not implemented" msgstr "pekare till varchar är inte implementerat" -#: preproc.y:19918 +#: preproc.y:19673 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "initialiserare tillåts inte i EXEC SQL VAR-kommando" -#: preproc.y:20235 +#: preproc.y:19987 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "array:er av indikatorer tillåts inte vid indata" -#: preproc.y:20422 +#: preproc.y:20174 #, c-format msgid "operator not allowed in variable definition" msgstr "operator tillåts inte i variabeldefinition" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:20463 +#: preproc.y:20215 #, c-format msgid "%s at or near \"%s\"" msgstr "%s vid eller nära \"%s\"" @@ -646,64 +640,64 @@ msgstr "indikatorstruktur \"%s\" har för många medlemmar" msgid "unrecognized descriptor item code %d" msgstr "okänd deskriptor-post-kod %d" -#: variable.c:89 variable.c:116 +#: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "inkorrekt formatterad variabel \"%s\"" -#: variable.c:139 +#: variable.c:138 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "variabel \"%s\" är inte en pekare" -#: variable.c:142 variable.c:167 +#: variable.c:141 variable.c:166 #, c-format msgid "variable \"%s\" is not a pointer to a structure or a union" msgstr "variabel \"%s\" är inte en pekare till en struktur eller union" -#: variable.c:154 +#: variable.c:153 #, c-format msgid "variable \"%s\" is neither a structure nor a union" msgstr "variabel \"%s\" är varken en struktur eller en union" -#: variable.c:164 +#: variable.c:163 #, c-format msgid "variable \"%s\" is not an array" msgstr "variabel \"%s\" är inte en array" -#: variable.c:233 variable.c:255 +#: variable.c:232 variable.c:254 #, c-format msgid "variable \"%s\" is not declared" msgstr "variabel \"%s\" är inte deklarerad" -#: variable.c:494 +#: variable.c:493 #, c-format msgid "indicator variable must have an integer type" msgstr "indikatorvariabel måste ha en heltalstyp" -#: variable.c:506 +#: variable.c:510 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "okänt datatypsnamn \"%s\"" -#: variable.c:517 variable.c:525 variable.c:542 variable.c:545 +#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 #, c-format msgid "multidimensional arrays are not supported" msgstr "multidimensionella array:er stöds inte" -#: variable.c:534 +#: variable.c:538 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" msgstr[0] "multinivåpekare (mer än 2 nivåer) stöds inte; hittade %d nivå" msgstr[1] "multinivåpekare (mer än 2 nivåer) stöds inte; hittade %d nivåer" -#: variable.c:539 +#: variable.c:543 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "pekare till pekare stöds inte för denna datatyp" -#: variable.c:559 +#: variable.c:563 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "multidimensionella array:er av strukturer stöds inte" diff --git a/src/interfaces/ecpg/preproc/po/uk.po b/src/interfaces/ecpg/preproc/po/uk.po index f5c64240c6bf3..27ca851c33dd9 100644 --- a/src/interfaces/ecpg/preproc/po/uk.po +++ b/src/interfaces/ecpg/preproc/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:40+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-09-23 10:40+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,45 +14,45 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/ecpg.pot\n" -"X-Crowdin-File-ID: 906\n" +"X-Crowdin-File: /REL_17_STABLE/ecpg.pot\n" +"X-Crowdin-File-ID: 990\n" #: descriptor.c:64 #, c-format msgid "variable \"%s\" must have a numeric type" msgstr "змінна \"%s\" повинна мати числовий тип" -#: descriptor.c:125 descriptor.c:156 +#: descriptor.c:124 descriptor.c:155 #, c-format msgid "descriptor %s bound to connection %s does not exist" msgstr "дескриптор %s, прив'язаний до підключення %s, не існує" -#: descriptor.c:127 descriptor.c:158 +#: descriptor.c:126 descriptor.c:157 #, c-format msgid "descriptor %s bound to the default connection does not exist" msgstr "дескриптор %s, прив'язаний до підключення за замовчуванням, не існує" -#: descriptor.c:173 descriptor.c:225 +#: descriptor.c:172 descriptor.c:224 #, c-format msgid "descriptor header item \"%d\" does not exist" msgstr "елемент заголовка дескриптору \"%d\" не існує" -#: descriptor.c:195 +#: descriptor.c:194 #, c-format msgid "nullable is always 1" msgstr "nullable завжди 1" -#: descriptor.c:198 +#: descriptor.c:197 #, c-format msgid "key_member is always 0" msgstr "key_member завжди 0" -#: descriptor.c:292 +#: descriptor.c:291 #, c-format msgid "descriptor item \"%s\" is not implemented" msgstr "елемент дескриптору \"%s\" не реалізовано" -#: descriptor.c:302 +#: descriptor.c:301 #, c-format msgid "descriptor item \"%s\" cannot be set" msgstr "елемент дескриптору \"%s\" не можна встановити" @@ -165,177 +165,177 @@ msgstr "\n" msgid "%s home page: <%s>\n" msgstr "Домашня сторінка %s: <%s>\n" -#: ecpg.c:141 +#: ecpg.c:152 #, c-format msgid "%s: could not locate my own executable path\n" msgstr "%s: не вдалося знайти свій власний шлях для виконання\n" -#: ecpg.c:176 ecpg.c:333 ecpg.c:344 -#, c-format -msgid "%s: could not open file \"%s\": %s\n" -msgstr "%s: не вдалося відкрити файл \"%s\": %s\n" - -#: ecpg.c:219 ecpg.c:232 ecpg.c:248 ecpg.c:274 +#: ecpg.c:195 ecpg.c:246 ecpg.c:260 ecpg.c:286 #, c-format msgid "Try \"%s --help\" for more information.\n" msgstr "Спробуйте \"%s --help\" для додаткової інформації.\n" -#: ecpg.c:243 +#: ecpg.c:203 #, c-format msgid "%s: parser debug support (-d) not available\n" msgstr "%s: налагоджувальні повідомлення під час аналізу (-d) не підтримуються\n" -#: ecpg.c:262 +#: ecpg.c:230 ecpg.c:345 ecpg.c:356 +#, c-format +msgid "%s: could not open file \"%s\": %m\n" +msgstr "%s: не вдалося відкрити файл \"%s\": %m\n" + +#: ecpg.c:274 #, c-format msgid "%s, the PostgreSQL embedded C preprocessor, version %s\n" msgstr "%s, вбудований препроцесор PostgreSQL, версія %s\n" -#: ecpg.c:264 +#: ecpg.c:276 #, c-format msgid "EXEC SQL INCLUDE ... search starts here:\n" msgstr "EXEC SQL INCLUDE ... пошук починається тут:\n" -#: ecpg.c:267 +#: ecpg.c:279 #, c-format msgid "end of search list\n" msgstr "кінець списку пошуку\n" -#: ecpg.c:273 +#: ecpg.c:285 #, c-format msgid "%s: no input files specified\n" msgstr "%s: не вказано вхідні файли\n" -#: ecpg.c:477 +#: ecpg.c:491 #, c-format msgid "cursor \"%s\" has been declared but not opened" msgstr "курсор \"%s\" був оголошений, але не відкритий" -#: ecpg.c:490 preproc.y:130 +#: ecpg.c:504 preproc.y:130 #, c-format msgid "could not remove output file \"%s\"\n" msgstr "не вдалося видалити файл виводу \"%s\"\n" -#: pgc.l:508 +#: pgc.l:542 #, c-format msgid "unterminated /* comment" msgstr "незавершений коментар /*" -#: pgc.l:525 +#: pgc.l:559 #, c-format msgid "unterminated bit string literal" msgstr "незавершений бітовий рядок" -#: pgc.l:533 +#: pgc.l:567 #, c-format msgid "unterminated hexadecimal string literal" msgstr "незавершений шістнадцятковий рядок" -#: pgc.l:608 +#: pgc.l:642 #, c-format msgid "invalid bit string literal" msgstr "неприпустимий літерал бітового рядка" -#: pgc.l:613 +#: pgc.l:647 #, c-format msgid "invalid hexadecimal string literal" msgstr "неприпустимий шістнадцятковий рядок" -#: pgc.l:631 +#: pgc.l:665 #, c-format msgid "unhandled previous state in xqs\n" msgstr "необроблений попередній стан у xqs\n" -#: pgc.l:657 pgc.l:766 +#: pgc.l:691 pgc.l:800 #, c-format msgid "unterminated quoted string" msgstr "незавершений рядок в лапках" -#: pgc.l:708 +#: pgc.l:742 #, c-format msgid "unterminated dollar-quoted string" msgstr "незавершений рядок з $" -#: pgc.l:726 pgc.l:746 +#: pgc.l:760 pgc.l:780 #, c-format msgid "zero-length delimited identifier" msgstr "пустий ідентифікатор із роздільниками" -#: pgc.l:757 +#: pgc.l:791 #, c-format msgid "unterminated quoted identifier" msgstr "незавершений ідентифікатор в лапках" -#: pgc.l:926 +#: pgc.l:960 #, c-format msgid "trailing junk after parameter" msgstr "сміття після параметру" -#: pgc.l:968 pgc.l:971 pgc.l:974 +#: pgc.l:1012 pgc.l:1015 pgc.l:1018 #, c-format msgid "trailing junk after numeric literal" msgstr "сміття після числового літерала" -#: pgc.l:1100 +#: pgc.l:1141 #, c-format msgid "nested /* ... */ comments" msgstr "вкладені /* ... */ коменарі" -#: pgc.l:1193 +#: pgc.l:1240 #, c-format msgid "missing identifier in EXEC SQL UNDEF command" msgstr "відсутній ідентифікатор у команді EXEC SQL UNDEF" -#: pgc.l:1211 pgc.l:1224 pgc.l:1240 pgc.l:1253 +#: pgc.l:1258 pgc.l:1271 pgc.l:1287 pgc.l:1300 #, c-format msgid "too many nested EXEC SQL IFDEF conditions" msgstr "забагато вкладених умов EXEC SQL IFDEF" -#: pgc.l:1269 pgc.l:1280 pgc.l:1295 pgc.l:1317 +#: pgc.l:1316 pgc.l:1327 pgc.l:1342 pgc.l:1364 #, c-format msgid "missing matching \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" msgstr "немає відповідного \"EXEC SQL IFDEF\" / \"EXEC SQL IFNDEF\"" -#: pgc.l:1271 pgc.l:1282 pgc.l:1463 +#: pgc.l:1318 pgc.l:1329 pgc.l:1522 #, c-format msgid "missing \"EXEC SQL ENDIF;\"" msgstr "відсутній \"EXEC SQL ENDIF;\"" -#: pgc.l:1297 pgc.l:1319 +#: pgc.l:1344 pgc.l:1366 #, c-format msgid "more than one EXEC SQL ELSE" msgstr "більше ніж один EXEC SQL ELSE" -#: pgc.l:1342 pgc.l:1356 +#: pgc.l:1389 pgc.l:1403 #, c-format msgid "unmatched EXEC SQL ENDIF" msgstr "невідповідний EXEC SQL ENDIF" -#: pgc.l:1411 +#: pgc.l:1464 #, c-format msgid "missing identifier in EXEC SQL IFDEF command" msgstr "відсутній ідентифікатор у команді EXEC SQL IFDEF" -#: pgc.l:1420 +#: pgc.l:1473 #, c-format msgid "missing identifier in EXEC SQL DEFINE command" msgstr "відсутній ідентифікатор у команді EXEC SQL DEFINE" -#: pgc.l:1453 +#: pgc.l:1511 #, c-format msgid "syntax error in EXEC SQL INCLUDE command" msgstr "синтаксична помилка у команді EXEC SQL INCLUDE" -#: pgc.l:1503 +#: pgc.l:1566 #, c-format msgid "internal error: unreachable state; please report this to <%s>" msgstr "внутрішня помилка: недосяжний стан; будь ласка, повідомте про це на <%s>" -#: pgc.l:1655 +#: pgc.l:1718 #, c-format msgid "Error: include path \"%s/%s\" is too long on line %d, skipping\n" msgstr "Помилка: шлях включення \"%s/%s\" занадто довгий у рядку %d, пропускається\n" -#: pgc.l:1678 +#: pgc.l:1741 #, c-format msgid "could not open include file \"%s\" on line %d" msgstr "не вдалося відкрити файл включення \"%s\" у рядку %d" @@ -369,12 +369,12 @@ msgstr "ініціалізація заборонена у визначенні msgid "type name \"string\" is reserved in Informix mode" msgstr "ім’я типу \"string\" зарезервовано у режимі Informix" -#: preproc.y:552 preproc.y:19354 +#: preproc.y:552 preproc.y:19034 #, c-format msgid "type \"%s\" is already defined" msgstr "тип \"%s\" вже визначений" -#: preproc.y:577 preproc.y:19989 preproc.y:20314 variable.c:621 +#: preproc.y:577 preproc.y:19669 preproc.y:19991 variable.c:625 #, c-format msgid "multidimensional arrays for simple data types are not supported" msgstr "багатовимірні масиви для простих типів даних не підтримуються" @@ -384,180 +384,174 @@ msgstr "багатовимірні масиви для простих типів msgid "connection %s is overwritten with %s by DECLARE statement %s" msgstr "підключення %s було перезаписано з %s командою DECLARE %s" -#: preproc.y:1872 +#: preproc.y:1831 #, c-format msgid "AT option not allowed in CLOSE DATABASE statement" msgstr "Параметр AT не дозволений в інструкції CLOSE DATABASE" -#: preproc.y:2122 +#: preproc.y:2081 #, c-format msgid "AT option not allowed in CONNECT statement" msgstr "Параметр AT не дозволений в інструкції CONNECT" -#: preproc.y:2162 +#: preproc.y:2121 #, c-format msgid "AT option not allowed in DISCONNECT statement" msgstr "Параметр AT не дозволений в інструкції DISCONNECT" -#: preproc.y:2217 +#: preproc.y:2176 #, c-format msgid "AT option not allowed in SET CONNECTION statement" msgstr "Параметр AT не дозволений в інструкції SET CONNECTION" -#: preproc.y:2239 +#: preproc.y:2198 #, c-format msgid "AT option not allowed in TYPE statement" msgstr "Параметр AT не дозволений в інструкції TYPE" -#: preproc.y:2248 +#: preproc.y:2207 #, c-format msgid "AT option not allowed in VAR statement" msgstr "Параметр AT не дозволений в інструкції VAR" -#: preproc.y:2255 +#: preproc.y:2214 #, c-format msgid "AT option not allowed in WHENEVER statement" msgstr "Параметр AT не дозволений в інструкції WHENEVER" -#: preproc.y:2332 preproc.y:2504 preproc.y:2509 preproc.y:2632 preproc.y:4283 -#: preproc.y:4357 preproc.y:4948 preproc.y:5481 preproc.y:5819 preproc.y:6119 -#: preproc.y:7687 preproc.y:9288 preproc.y:9293 preproc.y:12272 +#: preproc.y:2339 preproc.y:2626 preproc.y:4349 preproc.y:5021 preproc.y:5891 +#: preproc.y:6095 preproc.y:6196 preproc.y:12460 #, c-format msgid "unsupported feature will be passed to server" msgstr "непідтримувана функція буде передана до сервера" -#: preproc.y:2890 +#: preproc.y:2884 #, c-format msgid "SHOW ALL is not implemented" msgstr "SHOW ALL не реалізовано" -#: preproc.y:3589 +#: preproc.y:3596 #, c-format msgid "COPY FROM STDIN is not implemented" msgstr "COPY FROM STDIN не реалізовано" -#: preproc.y:10335 preproc.y:18892 +#: preproc.y:10444 preproc.y:18503 #, c-format msgid "\"database\" cannot be used as cursor name in INFORMIX mode" msgstr "\"database\" не може використовуватись як назва курсора в режимі INFORMIX" -#: preproc.y:10342 preproc.y:18902 +#: preproc.y:10451 preproc.y:18513 #, c-format msgid "using variable \"%s\" in different declare statements is not supported" msgstr "використання змінної \"%s\" у різних інструкціях declare не підтримується" -#: preproc.y:10344 preproc.y:18904 +#: preproc.y:10453 preproc.y:18515 #, c-format msgid "cursor \"%s\" is already defined" msgstr "курсор \"%s\" вже визначено" -#: preproc.y:10818 +#: preproc.y:10927 #, c-format msgid "no longer supported LIMIT #,# syntax passed to server" msgstr "непідтримуваний синтаксис LIMIT #,# передано до сервера" -#: preproc.y:11151 preproc.y:11158 -#, c-format -msgid "subquery in FROM must have an alias" -msgstr "підзапит в FROM повинен мати псевдонім" - -#: preproc.y:18584 preproc.y:18591 +#: preproc.y:18195 preproc.y:18202 #, c-format msgid "CREATE TABLE AS cannot specify INTO" msgstr "CREATE TABLE AS не може містити INTO" -#: preproc.y:18627 +#: preproc.y:18238 #, c-format msgid "expected \"@\", found \"%s\"" msgstr "очікувалося \"@\", знайдено \"%s\"" -#: preproc.y:18639 +#: preproc.y:18250 #, c-format msgid "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported" msgstr "підтримуються лише протоколи \"tcp\" та \"unix\" і тип бази даних \"postgresql\"" -#: preproc.y:18642 +#: preproc.y:18253 #, c-format msgid "expected \"://\", found \"%s\"" msgstr "очікувалося \"://\", знайдено \"%s\"" -#: preproc.y:18647 +#: preproc.y:18258 #, c-format msgid "Unix-domain sockets only work on \"localhost\" but not on \"%s\"" msgstr "Unix-сокети працюють лише з \"localhost\", але не з \"%s\"" -#: preproc.y:18673 +#: preproc.y:18284 #, c-format msgid "expected \"postgresql\", found \"%s\"" msgstr "очікувалось \"postgresql\", знайдено \"%s\"" -#: preproc.y:18676 +#: preproc.y:18287 #, c-format msgid "invalid connection type: %s" msgstr "неприпустимий тип підключення: %s" -#: preproc.y:18685 +#: preproc.y:18296 #, c-format msgid "expected \"@\" or \"://\", found \"%s\"" msgstr "очікувалось \"@\" або \"://\", знайдено \"%s\"" -#: preproc.y:18760 preproc.y:18778 +#: preproc.y:18371 preproc.y:18389 #, c-format msgid "invalid data type" msgstr "неприпустимий тип даних" -#: preproc.y:18789 preproc.y:18806 +#: preproc.y:18400 preproc.y:18417 #, c-format msgid "incomplete statement" msgstr "неповний оператор" -#: preproc.y:18792 preproc.y:18809 +#: preproc.y:18403 preproc.y:18420 #, c-format msgid "unrecognized token \"%s\"" msgstr "нерозпізнаний токен \"%s\"" -#: preproc.y:18854 +#: preproc.y:18465 #, c-format msgid "name \"%s\" is already declared" msgstr "ім'я \"%s\" вже оголошена" -#: preproc.y:19120 +#: preproc.y:18754 #, c-format msgid "only data types numeric and decimal have precision/scale argument" msgstr "точність/масштаб можна вказати лише для типів даних numeric і decimal" -#: preproc.y:19132 +#: preproc.y:18853 #, c-format msgid "interval specification not allowed here" msgstr "специфікація інтервалу тут не допускається" -#: preproc.y:19329 preproc.y:19381 +#: preproc.y:19009 preproc.y:19061 #, c-format msgid "too many levels in nested structure/union definition" msgstr "занадто багато рівнів у визначенні вкладеної структури/об'єднання" -#: preproc.y:19504 +#: preproc.y:19184 #, c-format msgid "pointers to varchar are not implemented" msgstr "вказівників на varchar не реалізовано" -#: preproc.y:19955 +#: preproc.y:19635 #, c-format msgid "initializer not allowed in EXEC SQL VAR command" msgstr "команда EXEC SQL VAR не допускає ініціалізатор" -#: preproc.y:20272 +#: preproc.y:19949 #, c-format msgid "arrays of indicators are not allowed on input" msgstr "вхідні масиви індикаторів не допускаються" -#: preproc.y:20459 +#: preproc.y:20136 #, c-format msgid "operator not allowed in variable definition" msgstr "у визначенні змінної оператор не допускається" #. translator: %s is typically the translation of "syntax error" -#: preproc.y:20500 +#: preproc.y:20177 #, c-format msgid "%s at or near \"%s\"" msgstr "%s в або поблизу \"%s\"" @@ -627,52 +621,52 @@ msgstr "індикатор структури \"%s\" має занадто ба msgid "unrecognized descriptor item code %d" msgstr "нерозпізнаний код елементу дескриптора %d" -#: variable.c:89 variable.c:116 +#: variable.c:89 variable.c:115 #, c-format msgid "incorrectly formed variable \"%s\"" msgstr "неправильно створена змінна \"%s\"" -#: variable.c:139 +#: variable.c:138 #, c-format msgid "variable \"%s\" is not a pointer" msgstr "змінна \"%s\" не є вказівником" -#: variable.c:142 variable.c:167 +#: variable.c:141 variable.c:166 #, c-format msgid "variable \"%s\" is not a pointer to a structure or a union" msgstr "змінна \"%s\" не є вказівником на структуру або об'єднання" -#: variable.c:154 +#: variable.c:153 #, c-format msgid "variable \"%s\" is neither a structure nor a union" msgstr "змінна \"%s\" не є структурою або об'єднанням" -#: variable.c:164 +#: variable.c:163 #, c-format msgid "variable \"%s\" is not an array" msgstr "змінна \"%s\" не є масивом" -#: variable.c:233 variable.c:255 +#: variable.c:232 variable.c:254 #, c-format msgid "variable \"%s\" is not declared" msgstr "змінна \"%s\" не проголошена" -#: variable.c:494 +#: variable.c:493 #, c-format msgid "indicator variable must have an integer type" msgstr "змінна-індикатор повинна бути цілим числом" -#: variable.c:506 +#: variable.c:510 #, c-format msgid "unrecognized data type name \"%s\"" msgstr "нерозпізнане ім'я типу даних \"%s\"" -#: variable.c:517 variable.c:525 variable.c:542 variable.c:545 +#: variable.c:521 variable.c:529 variable.c:546 variable.c:549 #, c-format msgid "multidimensional arrays are not supported" msgstr "багатовимірні масиви не підтримуються" -#: variable.c:534 +#: variable.c:538 #, c-format msgid "multilevel pointers (more than 2 levels) are not supported; found %d level" msgid_plural "multilevel pointers (more than 2 levels) are not supported; found %d levels" @@ -681,12 +675,12 @@ msgstr[1] "багаторівневі вказівники (більше 2 рі msgstr[2] "багаторівневі вказівники (більше 2 рівнів) не підтримуються; знайдено %d рівнів" msgstr[3] "багаторівневі вказівники (більше 2 рівнів) не підтримуються; знайдено %d рівень" -#: variable.c:539 +#: variable.c:543 #, c-format msgid "pointer to pointer is not supported for this data type" msgstr "для цього типу даних вказівники на вказівники не підтримуються" -#: variable.c:559 +#: variable.c:563 #, c-format msgid "multidimensional arrays for structures are not supported" msgstr "багатовимірні масиви структур не підтримуються" diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h index c5fd07fbd8b52..2c89e30621ed0 100644 --- a/src/interfaces/ecpg/preproc/preproc_extern.h +++ b/src/interfaces/ecpg/preproc/preproc_extern.h @@ -13,7 +13,13 @@ /* defines */ #define STRUCT_DEPTH 128 -#define EMPTY mm_strdup("") + +/* + * "Location tracking" support --- see ecpg.header for more comments. + */ +typedef const char *YYLTYPE; + +#define YYLTYPE_IS_DECLARED 1 /* variables */ @@ -65,28 +71,35 @@ extern const uint16 SQLScanKeywordTokens[]; extern const char *get_dtype(enum ECPGdtype); extern void lex_init(void); extern void output_line_number(void); -extern void output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st); -extern void output_prepare_statement(char *name, char *stmt); -extern void output_deallocate_prepare_statement(char *name); -extern void output_simple_statement(char *stmt, int whenever_mode); +extern void output_statement(const char *stmt, int whenever_mode, enum ECPG_statement_type st); +extern void output_prepare_statement(const char *name, const char *stmt); +extern void output_deallocate_prepare_statement(const char *name); +extern void output_simple_statement(const char *stmt, int whenever_mode); extern char *hashline_number(void); extern int base_yyparse(void); extern int base_yylex(void); extern void base_yyerror(const char *error); extern void *mm_alloc(size_t size); extern char *mm_strdup(const char *string); +extern void *loc_alloc(size_t size); +extern char *loc_strdup(const char *string); +extern void reclaim_local_storage(void); +extern char *cat2_str(const char *str1, const char *str2); +extern char *cat_str(int count,...); +extern char *make2_str(const char *str1, const char *str2); +extern char *make3_str(const char *str1, const char *str2, const char *str3); extern void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3, 4); -extern void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2, 3) pg_attribute_noreturn(); -extern void output_get_descr_header(char *desc_name); -extern void output_get_descr(char *desc_name, char *index); -extern void output_set_descr_header(char *desc_name); -extern void output_set_descr(char *desc_name, char *index); -extern void push_assignment(char *var, enum ECPGdtype value); -extern struct variable *find_variable(char *name); +pg_noreturn extern void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2, 3); +extern void output_get_descr_header(const char *desc_name); +extern void output_get_descr(const char *desc_name, const char *index); +extern void output_set_descr_header(const char *desc_name); +extern void output_set_descr(const char *desc_name, const char *index); +extern void push_assignment(const char *var, enum ECPGdtype value); +extern struct variable *find_variable(const char *name); extern void whenever_action(int mode); -extern void add_descriptor(char *name, char *connection); -extern void drop_descriptor(char *name, char *connection); -extern struct descriptor *lookup_descriptor(char *name, char *connection); +extern void add_descriptor(const char *name, const char *connection); +extern void drop_descriptor(const char *name, const char *connection); +extern struct descriptor *lookup_descriptor(const char *name, const char *connection); extern struct variable *descriptor_variable(const char *name, int input); extern struct variable *sqlda_variable(const char *name); extern void add_variable_to_head(struct arguments **list, @@ -98,9 +111,9 @@ extern void add_variable_to_tail(struct arguments **list, extern void remove_variable_from_list(struct arguments **list, struct variable *var); extern void dump_variables(struct arguments *list, int mode); extern struct typedefs *get_typedef(const char *name, bool noerror); -extern void adjust_array(enum ECPGttype type_enum, char **dimension, - char **length, char *type_dimension, - char *type_index, int pointer_len, +extern void adjust_array(enum ECPGttype type_enum, const char **dimension, + const char **length, const char *type_dimension, + const char *type_index, int pointer_len, bool type_definition); extern void reset_variables(void); extern void check_indicator(struct ECPGtype *var); diff --git a/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl new file mode 100644 index 0000000000000..a18e09e6ee859 --- /dev/null +++ b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl @@ -0,0 +1,40 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use Test::More; + +program_help_ok('ecpg'); +program_version_ok('ecpg'); +program_options_handling_ok('ecpg'); +command_fails(['ecpg'], 'ecpg without arguments fails'); + +# Test that the ecpg command correctly detects unsupported or disallowed +# statements in the input file and reports the appropriate error or +# warning messages. +command_checks_all( + [ 'ecpg', 't/err_warn_msg.pgc' ], + 3, + [qr//], + [ + qr/ERROR: AT option not allowed in CONNECT statement/, + qr/ERROR: AT option not allowed in DISCONNECT statement/, + qr/ERROR: AT option not allowed in SET CONNECTION statement/, + qr/ERROR: AT option not allowed in TYPE statement/, + qr/ERROR: AT option not allowed in WHENEVER statement/, + qr/ERROR: AT option not allowed in VAR statement/, + qr/WARNING: COPY FROM STDIN is not implemented/, + qr/ERROR: using variable "cursor_var" in different declare statements is not supported/, + qr/ERROR: cursor "duplicate_cursor" is already defined/, + qr/ERROR: SHOW ALL is not implemented/, + qr/WARNING: no longer supported LIMIT/, + qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/, + qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/, + qr/WARNING: cursor ":cursor_var" has been declared but not opened/, + qr/WARNING: cursor ":cursor_var" has been declared but not opened/ + ], + 'ecpg with errors and warnings'); + +done_testing(); diff --git a/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl new file mode 100644 index 0000000000000..cb0502dfc2b06 --- /dev/null +++ b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl @@ -0,0 +1,22 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use Test::More; + +# Test that the ecpg command in INFORMIX mode correctly detects +# unsupported or disallowed statements in the input file and reports +# the appropriate error or warning messages. +command_checks_all( + [ 'ecpg', '-C', 'INFORMIX', 't/err_warn_msg_informix.pgc' ], + 3, + [qr//], + [ + qr/ERROR: AT option not allowed in CLOSE DATABASE statement/, + qr/ERROR: "database" cannot be used as cursor name in INFORMIX mode/ + ], + 'ecpg in INFORMIX mode with errors and warnings'); + +done_testing(); diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc new file mode 100644 index 0000000000000..5ab0a76186635 --- /dev/null +++ b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc @@ -0,0 +1,42 @@ +/* Test ECPG warning/error messages */ + +#include + +int +main(void) +{ + EXEC SQL BEGIN DECLARE SECTION; + char *cursor_var = "mycursor"; + short a; + EXEC SQL END DECLARE SECTION; + + /* For consistency with other tests */ + EXEC SQL CONNECT TO testdb AS con1; + + /* Test AT option errors */ + EXEC SQL AT con1 CONNECT TO testdb2; + EXEC SQL AT con1 DISCONNECT; + EXEC SQL AT con1 SET CONNECTION TO testdb2; + EXEC SQL AT con1 TYPE string IS char[11]; + EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE; + EXEC SQL AT con1 VAR a IS int; + + /* Test COPY FROM STDIN warning */ + EXEC SQL COPY test FROM stdin; + + /* Test same variable in multi declare statement */ + EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test; + EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test; + + /* Test duplicate cursor declarations */ + EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test; + EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test; + + /* Test SHOW ALL error */ + EXEC SQL SHOW ALL; + + /* Test deprecated LIMIT syntax warning */ + EXEC SQL SELECT * FROM test LIMIT 10, 5; + + return 0; +} diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc new file mode 100644 index 0000000000000..e8db65eefa1d6 --- /dev/null +++ b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc @@ -0,0 +1,18 @@ +/* Test ECPG warning/error messages in INFORMIX mode */ + +#include + +int +main(void) +{ + /* For consistency with other tests */ + $CONNECT TO testdb AS con1; + + /* Test AT option usage at CLOSE DATABASE statement in INFORMIX mode */ + $AT con1 CLOSE DATABASE; + + /* Test cursor name errors in INFORMIX mode */ + $DECLARE database CURSOR FOR SELECT * FROM test; + + return 0; +} diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index a842bb6a1fed7..9f6dacd2aea55 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -8,30 +8,6 @@ static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL}; -/* malloc + error check */ -void * -mm_alloc(size_t size) -{ - void *ptr = malloc(size); - - if (ptr == NULL) - mmfatal(OUT_OF_MEMORY, "out of memory"); - - return ptr; -} - -/* strdup + error check */ -char * -mm_strdup(const char *string) -{ - char *new = strdup(string); - - if (new == NULL) - mmfatal(OUT_OF_MEMORY, "out of memory"); - - return new; -} - /* duplicate memberlist */ struct ECPGstruct_member * ECPGstruct_member_dup(struct ECPGstruct_member *rm) @@ -93,13 +69,13 @@ ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruc } struct ECPGtype * -ECPGmake_simple_type(enum ECPGttype type, char *size, int counter) +ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter) { struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); ne->type = type; ne->type_name = NULL; - ne->size = size; + ne->size = mm_strdup(size); ne->u.element = NULL; ne->struct_sizeof = NULL; ne->counter = counter; /* only needed for varchar and bytea */ @@ -108,7 +84,7 @@ ECPGmake_simple_type(enum ECPGttype type, char *size, int counter) } struct ECPGtype * -ECPGmake_array_type(struct ECPGtype *type, char *size) +ECPGmake_array_type(struct ECPGtype *type, const char *size) { struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0); @@ -118,13 +94,14 @@ ECPGmake_array_type(struct ECPGtype *type, char *size) } struct ECPGtype * -ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof) +ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, + const char *type_name, const char *struct_sizeof) { - struct ECPGtype *ne = ECPGmake_simple_type(type, mm_strdup("1"), 0); + struct ECPGtype *ne = ECPGmake_simple_type(type, "1", 0); ne->type_name = mm_strdup(type_name); ne->u.members = ECPGstruct_member_dup(rm); - ne->struct_sizeof = struct_sizeof; + ne->struct_sizeof = mm_strdup(struct_sizeof); return ne; } @@ -646,7 +623,7 @@ ECPGfree_struct_member(struct ECPGstruct_member *rm) rm = rm->next; free(p->name); - free(p->type); + ECPGfree_type(p->type); free(p); } } @@ -667,14 +644,13 @@ ECPGfree_type(struct ECPGtype *type) case ECPGt_struct: case ECPGt_union: /* Array of structs. */ - ECPGfree_struct_member(type->u.element->u.members); - free(type->u.element); + ECPGfree_type(type->u.element); break; default: if (!IS_SIMPLE_TYPE(type->u.element->type)) base_yyerror("internal error: unknown datatype, please report this to <" PACKAGE_BUGREPORT ">"); - free(type->u.element); + ECPGfree_type(type->u.element); } break; case ECPGt_struct: @@ -686,6 +662,9 @@ ECPGfree_type(struct ECPGtype *type) break; } } + free(type->type_name); + free(type->size); + free(type->struct_sizeof); free(type); } diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index ce2124361fd0a..3d99e1703de45 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -35,11 +35,12 @@ struct ECPGtype /* Everything is malloced. */ void ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruct_member **start); -struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, char *size, int counter); -struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, char *size); +struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter); +struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, const char *size); struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm, - enum ECPGttype type, char *type_name, - char *struct_sizeof); + enum ECPGttype type, + const char *type_name, + const char *struct_sizeof); struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *rm); /* Frees a type. */ @@ -93,28 +94,28 @@ struct when struct index { - char *index1; - char *index2; - char *str; + const char *index1; + const char *index2; + const char *str; }; struct su_symbol { - char *su; - char *symbol; + const char *su; + const char *symbol; }; struct prep { - char *name; - char *stmt; - char *type; + const char *name; + const char *stmt; + const char *type; }; struct exec { - char *name; - char *type; + const char *name; + const char *type; }; struct this_type @@ -221,14 +222,14 @@ enum errortype struct fetch_desc { - char *str; - char *name; + const char *str; + const char *name; }; struct describe { int input; - char *stmt_name; + const char *stmt_name; }; #endif /* _ECPG_PREPROC_TYPE_H */ diff --git a/src/interfaces/ecpg/preproc/util.c b/src/interfaces/ecpg/preproc/util.c new file mode 100644 index 0000000000000..f177df32488ce --- /dev/null +++ b/src/interfaces/ecpg/preproc/util.c @@ -0,0 +1,264 @@ +/* src/interfaces/ecpg/preproc/util.c */ + +#include "postgres_fe.h" + +#include + +#include "preproc_extern.h" + +static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0); + + +/* + * Handle preprocessor errors and warnings + */ +static void +vmmerror(int error_code, enum errortype type, const char *error, va_list ap) +{ + /* localize the error message string */ + error = _(error); + + fprintf(stderr, "%s:%d: ", input_filename, base_yylineno); + + switch (type) + { + case ET_WARNING: + fprintf(stderr, _("WARNING: ")); + break; + case ET_ERROR: + fprintf(stderr, _("ERROR: ")); + break; + } + + vfprintf(stderr, error, ap); + + fprintf(stderr, "\n"); + + /* If appropriate, set error code to be inspected by ecpg.c */ + switch (type) + { + case ET_WARNING: + break; + case ET_ERROR: + ret_value = error_code; + break; + } +} + +/* Report an error or warning */ +void +mmerror(int error_code, enum errortype type, const char *error,...) +{ + va_list ap; + + va_start(ap, error); + vmmerror(error_code, type, error, ap); + va_end(ap); +} + +/* Report an error and abandon execution */ +void +mmfatal(int error_code, const char *error,...) +{ + va_list ap; + + va_start(ap, error); + vmmerror(error_code, ET_ERROR, error, ap); + va_end(ap); + + if (base_yyin) + fclose(base_yyin); + if (base_yyout) + fclose(base_yyout); + + if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0) + fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename); + exit(error_code); +} + +/* + * Basic memory management support + */ + +/* malloc + error check */ +void * +mm_alloc(size_t size) +{ + void *ptr = malloc(size); + + if (ptr == NULL) + mmfatal(OUT_OF_MEMORY, "out of memory"); + + return ptr; +} + +/* strdup + error check */ +char * +mm_strdup(const char *string) +{ + char *new = strdup(string); + + if (new == NULL) + mmfatal(OUT_OF_MEMORY, "out of memory"); + + return new; +} + + +/* + * "Local" memory management support + * + * These functions manage memory that is only needed for a short time + * (processing of one input statement) within the ecpg grammar. + * Data allocated with these is not meant to be freed separately; + * rather it's freed by calling reclaim_local_storage() at the end + * of each statement cycle. + */ + +typedef struct loc_chunk +{ + struct loc_chunk *next; /* list link */ + unsigned int chunk_used; /* index of first unused byte in data[] */ + unsigned int chunk_avail; /* # bytes still available in data[] */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* actual storage */ +} loc_chunk; + +#define LOC_CHUNK_OVERHEAD MAXALIGN(offsetof(loc_chunk, data)) +#define LOC_CHUNK_MIN_SIZE 8192 + +/* Head of list of loc_chunks */ +static loc_chunk *loc_chunks = NULL; + +/* + * Allocate local space of the requested size. + * + * Exits on OOM. + */ +void * +loc_alloc(size_t size) +{ + void *result; + loc_chunk *cur_chunk = loc_chunks; + + /* Ensure all allocations are adequately aligned */ + size = MAXALIGN(size); + + /* Need a new chunk? */ + if (cur_chunk == NULL || size > cur_chunk->chunk_avail) + { + size_t chunk_size = Max(size, LOC_CHUNK_MIN_SIZE); + + cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD); + /* Depending on alignment rules, we could waste a bit here */ + cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data); + cur_chunk->chunk_avail = chunk_size; + /* New chunk becomes the head of the list */ + cur_chunk->next = loc_chunks; + loc_chunks = cur_chunk; + } + + result = cur_chunk->data + cur_chunk->chunk_used; + cur_chunk->chunk_used += size; + cur_chunk->chunk_avail -= size; + return result; +} + +/* + * Copy given string into local storage + */ +char * +loc_strdup(const char *string) +{ + char *result = loc_alloc(strlen(string) + 1); + + strcpy(result, string); + return result; +} + +/* + * Reclaim local storage when appropriate + */ +void +reclaim_local_storage(void) +{ + loc_chunk *cur_chunk, + *next_chunk; + + for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk) + { + next_chunk = cur_chunk->next; + free(cur_chunk); + } + loc_chunks = NULL; +} + + +/* + * String concatenation support routines. These return "local" (transient) + * storage. + */ + +/* + * Concatenate 2 strings, inserting a space between them unless either is empty + */ +char * +cat2_str(const char *str1, const char *str2) +{ + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2); + + strcpy(res_str, str1); + if (strlen(str1) != 0 && strlen(str2) != 0) + strcat(res_str, " "); + strcat(res_str, str2); + return res_str; +} + +/* + * Concatenate N strings, inserting spaces between them unless they are empty + */ +char * +cat_str(int count,...) +{ + va_list args; + int i; + char *res_str; + + va_start(args, count); + + res_str = va_arg(args, char *); + + /* now add all other strings */ + for (i = 1; i < count; i++) + res_str = cat2_str(res_str, va_arg(args, char *)); + + va_end(args); + + return res_str; +} + +/* + * Concatenate 2 strings, with no space between + */ +char * +make2_str(const char *str1, const char *str2) +{ + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1); + + strcpy(res_str, str1); + strcat(res_str, str2); + return res_str; +} + +/* + * Concatenate 3 strings, with no space between + */ +char * +make3_str(const char *str1, const char *str2, const char *str3) +{ + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1); + + strcpy(res_str, str1); + strcat(res_str, str2); + strcat(res_str, str3); + return res_str; +} diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index b23ed5edf460f..2c67e33e92e6a 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -22,7 +22,7 @@ new_variable(const char *name, struct ECPGtype *type, int brace_level) } static struct variable * -find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int brace_level) +find_struct_member(const char *name, char *str, struct ECPGstruct_member *members, int brace_level) { char *next = strpbrk(++str, ".-["), *end, @@ -60,7 +60,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int int count; /* - * We don't care about what's inside the array braces so + * We don't care about what's inside the array brackets so * just eat up the character */ for (count = 1, end = next + 1; count; end++) @@ -123,7 +123,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int } static struct variable * -find_struct(char *name, char *next, char *end) +find_struct(const char *name, char *next, char *end) { struct variable *p; char c = *next; @@ -174,7 +174,7 @@ find_struct(char *name, char *next, char *end) } static struct variable * -find_simple(char *name) +find_simple(const char *name) { struct variable *p; @@ -190,7 +190,7 @@ find_simple(char *name) /* Note that this function will end the program in case of an unknown */ /* variable */ struct variable * -find_variable(char *name) +find_variable(const char *name) { char *next, *end; @@ -203,8 +203,8 @@ find_variable(char *name) if (*next == '[') { /* - * We don't care about what's inside the array braces so just eat - * up the characters + * We don't care about what's inside the array brackets so just + * eat up the characters */ for (count = 1, end = next + 1; count; end++) { @@ -216,6 +216,9 @@ find_variable(char *name) case ']': count--; break; + case '\0': + mmfatal(PARSE_ERROR, "unmatched bracket in variable \"%s\"", name); + break; default: break; } @@ -230,7 +233,8 @@ find_variable(char *name) p = find_simple(name); if (p == NULL) mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name); - + if (p->type->type != ECPGt_array) + mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", name); *next = c; switch (p->type->u.element->type) { @@ -260,33 +264,33 @@ void remove_typedefs(int brace_level) { struct typedefs *p, - *prev; + *prev, + *next; - for (p = prev = types; p;) + for (p = types, prev = NULL; p; p = next) { + next = p->next; if (p->brace_level >= brace_level) { /* remove it */ - if (p == types) - prev = types = p->next; + if (prev) + prev->next = next; else - prev->next = p->next; + types = next; if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union) - free(p->struct_member_list); + ECPGfree_struct_member(p->struct_member_list); + free(p->type->type_storage); + free(p->type->type_str); + free(p->type->type_dimension); + free(p->type->type_index); + free(p->type->type_sizeof); free(p->type); free(p->name); free(p); - if (prev == types) - p = types; - else - p = prev ? prev->next : NULL; } else - { prev = p; - p = prev->next; - } } } @@ -294,63 +298,69 @@ void remove_variables(int brace_level) { struct variable *p, - *prev; + *prev, + *next; - for (p = prev = allvariables; p;) + for (p = allvariables, prev = NULL; p; p = next) { + next = p->next; if (p->brace_level >= brace_level) { - /* is it still referenced by a cursor? */ + /* remove it, but first remove any references from cursors */ struct cursor *ptr; for (ptr = cur; ptr != NULL; ptr = ptr->next) { struct arguments *varptr, - *prevvar; + *prevvar, + *nextvar; - for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = varptr->next) + for (varptr = ptr->argsinsert, prevvar = NULL; + varptr != NULL; varptr = nextvar) { + nextvar = varptr->next; if (p == varptr->variable) { /* remove from list */ - if (varptr == ptr->argsinsert) - ptr->argsinsert = varptr->next; + if (prevvar) + prevvar->next = nextvar; else - prevvar->next = varptr->next; + ptr->argsinsert = nextvar; + free(varptr); } + else + prevvar = varptr; } - for (varptr = prevvar = ptr->argsresult; varptr != NULL; varptr = varptr->next) + for (varptr = ptr->argsresult, prevvar = NULL; + varptr != NULL; varptr = nextvar) { + nextvar = varptr->next; if (p == varptr->variable) { /* remove from list */ - if (varptr == ptr->argsresult) - ptr->argsresult = varptr->next; + if (prevvar) + prevvar->next = nextvar; else - prevvar->next = varptr->next; + ptr->argsresult = nextvar; + free(varptr); } + else + prevvar = varptr; } } /* remove it */ - if (p == allvariables) - prev = allvariables = p->next; + if (prev) + prev->next = next; else - prev->next = p->next; + allvariables = next; ECPGfree_type(p->type); free(p->name); free(p); - if (prev == allvariables) - p = allvariables; - else - p = prev ? prev->next : NULL; } else - { prev = p; - p = prev->next; - } } } @@ -367,7 +377,20 @@ struct arguments *argsresult = NULL; void reset_variables(void) { + struct arguments *p, + *next; + + for (p = argsinsert; p; p = next) + { + next = p->next; + free(p); + } argsinsert = NULL; + for (p = argsresult; p; p = next) + { + next = p->next; + free(p); + } argsresult = NULL; } @@ -426,6 +449,7 @@ remove_variable_from_list(struct arguments **list, struct variable *var) prev->next = p->next; else *list = p->next; + free(p); } } @@ -513,7 +537,10 @@ get_typedef(const char *name, bool noerror) } void -adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *type_dimension, char *type_index, int pointer_len, bool type_definition) +adjust_array(enum ECPGttype type_enum, + const char **dimension, const char **length, + const char *type_dimension, const char *type_index, + int pointer_len, bool type_definition) { if (atoi(type_index) >= 0) { @@ -556,7 +583,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty if (pointer_len) { *length = *dimension; - *dimension = mm_strdup("0"); + *dimension = "0"; } if (atoi(*length) >= 0) @@ -567,13 +594,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty case ECPGt_bytea: /* pointer has to get dimension 0 */ if (pointer_len) - *dimension = mm_strdup("0"); + *dimension = "0"; /* one index is the string length */ if (atoi(*length) < 0) { *length = *dimension; - *dimension = mm_strdup("-1"); + *dimension = "-1"; } break; @@ -583,13 +610,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty /* char ** */ if (pointer_len == 2) { - *length = *dimension = mm_strdup("0"); + *length = *dimension = "0"; break; } /* pointer has to get length 0 */ if (pointer_len == 1) - *length = mm_strdup("0"); + *length = "0"; /* one index is the string length */ if (atoi(*length) < 0) @@ -604,13 +631,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty * do not change this for typedefs since it will be * changed later on when the variable is defined */ - *length = mm_strdup("1"); + *length = "1"; else if (strcmp(*dimension, "0") == 0) - *length = mm_strdup("-1"); + *length = "-1"; else *length = *dimension; - *dimension = mm_strdup("-1"); + *dimension = "-1"; } break; default: @@ -618,7 +645,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty if (pointer_len) { *length = *dimension; - *dimension = mm_strdup("0"); + *dimension = "0"; } if (atoi(*length) >= 0) diff --git a/src/interfaces/ecpg/test/Makefile.regress b/src/interfaces/ecpg/test/Makefile.regress index b0647cd2c5fdf..9bf0efa40b946 100644 --- a/src/interfaces/ecpg/test/Makefile.regress +++ b/src/interfaces/ecpg/test/Makefile.regress @@ -3,7 +3,7 @@ override CPPFLAGS := -I../../include -I$(top_srcdir)/src/interfaces/ecpg/include \ -I$(libpq_srcdir) $(CPPFLAGS) -override CFLAGS += $(PTHREAD_CFLAGS) +override CFLAGS += $(PTHREAD_CFLAGS) $(PERMIT_MISSING_VARIABLE_DECLARATIONS) LDFLAGS_INTERNAL += -L../../ecpglib -lecpg -L../../pgtypeslib -lpgtypes $(libpq) diff --git a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc index f6a9f425d6f1d..830ab5890b24d 100644 --- a/src/interfaces/ecpg/test/compat_informix/dec_test.pgc +++ b/src/interfaces/ecpg/test/compat_informix/dec_test.pgc @@ -142,6 +142,16 @@ main(void) c = deccmp(decarr[i], decarr[j]); printf("dec[c,%d,%d]: %d\n", i, j, c); + /* + * decarr[count-1] is risnull(), which makes these functions + * return 0 without changing the output parameter. Make that + * clear by initializing each output parameter. + */ + deccvint(7654321, &a); + deccvint(7654321, &s); + deccvint(7654321, &m); + deccvint(7654321, &d); + r = decadd(decarr[i], decarr[j], &a); if (r) { diff --git a/src/interfaces/ecpg/test/compat_informix/meson.build b/src/interfaces/ecpg/test/compat_informix/meson.build index c6ed52f51c557..fdf810115cdeb 100644 --- a/src/interfaces/ecpg/test/compat_informix/meson.build +++ b/src/interfaces/ecpg/test/compat_informix/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'charfuncs', diff --git a/src/interfaces/ecpg/test/compat_oracle/meson.build b/src/interfaces/ecpg/test/compat_oracle/meson.build index e1202e5abaa02..43084e5b8ef86 100644 --- a/src/interfaces/ecpg/test/compat_oracle/meson.build +++ b/src/interfaces/ecpg/test/compat_oracle/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'char_array', diff --git a/src/interfaces/ecpg/test/connect/meson.build b/src/interfaces/ecpg/test/connect/meson.build index 3e1469d51cccf..5154167663d0d 100644 --- a/src/interfaces/ecpg/test/connect/meson.build +++ b/src/interfaces/ecpg/test/connect/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'test1', diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c index 8586650e879be..3e68b2e026797 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.c @@ -195,6 +195,16 @@ main(void) c = deccmp(decarr[i], decarr[j]); printf("dec[c,%d,%d]: %d\n", i, j, c); + /* + * decarr[count-1] is risnull(), which makes these functions + * return 0 without changing the output parameter. Make that + * clear by initializing each output parameter. + */ + deccvint(7654321, &a); + deccvint(7654321, &s); + deccvint(7654321, &m); + deccvint(7654321, &d); + r = decadd(decarr[i], decarr[j], &a); if (r) { diff --git a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout index 71a5afa4a7ad5..7e50493868b34 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout +++ b/src/interfaces/ecpg/test/expected/compat_informix-dec_test.stdout @@ -222,10 +222,10 @@ dec[s,0,13]: dec[m,0,13]: * dec[d,0,13]: dec[c,0,14]: 2147483647 -dec[a,0,14]: -dec[s,0,14]: -dec[m,0,14]: * -dec[d,0,14]: +dec[a,0,14]: 7654321.0 +dec[s,0,14]: 7654321.0 +dec[m,0,14]: 7654321.0 +dec[d,0,14]: 7654321.0 dec[c,1,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,1,0]: @@ -297,10 +297,10 @@ dec[s,1,13]: -1234567890123456789012345680.91 dec[m,1,13]: -2469135780246913578024691357.82 dec[d,1,13]: -0.0000000000000000000000000016200000145800001 dec[c,1,14]: 2147483647 -dec[a,1,14]: 1234567890123456789012345676.91 -dec[s,1,14]: -1234567890123456789012345680.91 -dec[m,1,14]: -2469135780246913578024691357.82 -dec[d,1,14]: -0.0000000000000000000000000016200000145800001 +dec[a,1,14]: 7654321.0 +dec[s,1,14]: 7654321.0 +dec[m,1,14]: 7654321.0 +dec[d,1,14]: 7654321.0 dec[c,2,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,2,0]: @@ -372,10 +372,10 @@ dec[s,2,13]: dec[m,2,13]: dec[d,2,13]: 0.00000000000000000000000000064314000578826005 dec[c,2,14]: 2147483647 -dec[a,2,14]: -dec[s,2,14]: -dec[m,2,14]: -dec[d,2,14]: 0.00000000000000000000000000064314000578826005 +dec[a,2,14]: 7654321.0 +dec[s,2,14]: 7654321.0 +dec[m,2,14]: 7654321.0 +dec[d,2,14]: 7654321.0 dec[c,3,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,3,0]: @@ -447,10 +447,10 @@ dec[s,3,13]: -1234567890123456789012345675.47 dec[m,3,13]: dec[d,3,13]: 0.0000000000000000000000000027864000250776002 dec[c,3,14]: 2147483647 -dec[a,3,14]: 1234567890123456789012345682.35 -dec[s,3,14]: -1234567890123456789012345675.47 -dec[m,3,14]: -dec[d,3,14]: 0.0000000000000000000000000027864000250776002 +dec[a,3,14]: 7654321.0 +dec[s,3,14]: 7654321.0 +dec[m,3,14]: 7654321.0 +dec[d,3,14]: 7654321.0 dec[c,4,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,4,0]: @@ -522,10 +522,10 @@ dec[s,4,13]: -1233975400123456789012345678.91 dec[m,4,13]: dec[d,4,13]: 0.00047991690431925214 dec[c,4,14]: 2147483647 -dec[a,4,14]: 1235160380123456789012345678.91 -dec[s,4,14]: -1233975400123456789012345678.91 -dec[m,4,14]: -dec[d,4,14]: 0.00047991690431925214 +dec[a,4,14]: 7654321.0 +dec[s,4,14]: 7654321.0 +dec[m,4,14]: 7654321.0 +dec[d,4,14]: 7654321.0 dec[c,5,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,5,0]: @@ -597,10 +597,10 @@ dec[s,5,13]: -1234567890123456789012674078.91 dec[m,5,13]: dec[d,5,13]: -0.00000000000000000000026600400239403602 dec[c,5,14]: 2147483647 -dec[a,5,14]: 1234567890123456789012017278.91 -dec[s,5,14]: -1234567890123456789012674078.91 -dec[m,5,14]: -dec[d,5,14]: -0.00000000000000000000026600400239403602 +dec[a,5,14]: 7654321.0 +dec[s,5,14]: 7654321.0 +dec[m,5,14]: 7654321.0 +dec[d,5,14]: 7654321.0 dec[c,6,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,6,0]: @@ -672,10 +672,10 @@ dec[s,6,13]: dec[m,6,13]: * dec[d,6,13]: * dec[c,6,14]: 2147483647 -dec[a,6,14]: -dec[s,6,14]: -dec[m,6,14]: * -dec[d,6,14]: * +dec[a,6,14]: 7654321.0 +dec[s,6,14]: 7654321.0 +dec[m,6,14]: 7654321.0 +dec[d,6,14]: 7654321.0 dec[c,7,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,7,0]: @@ -747,10 +747,10 @@ dec[s,7,13]: dec[m,7,13]: 1234567890123456789012345.67891 dec[d,7,13]: 0.00000000000000000000000000000081000000729000007 dec[c,7,14]: 2147483647 -dec[a,7,14]: -dec[s,7,14]: -dec[m,7,14]: 1234567890123456789012345.67891 -dec[d,7,14]: 0.00000000000000000000000000000081000000729000007 +dec[a,7,14]: 7654321.0 +dec[s,7,14]: 7654321.0 +dec[m,7,14]: 7654321.0 +dec[d,7,14]: 7654321.0 dec[c,8,0]: -1 dec[a,8,0]: * dec[s,8,0]: * @@ -822,10 +822,10 @@ dec[s,8,13]: -1234567890123456789012345678.91 dec[m,8,13]: 0.000 dec[d,8,13]: 0 dec[c,8,14]: 2147483647 -dec[a,8,14]: 1234567890123456789012345678.91 -dec[s,8,14]: -1234567890123456789012345678.91 -dec[m,8,14]: 0.000 -dec[d,8,14]: 0 +dec[a,8,14]: 7654321.0 +dec[s,8,14]: 7654321.0 +dec[m,8,14]: 7654321.0 +dec[d,8,14]: 7654321.0 dec[c,9,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,9,0]: @@ -897,10 +897,10 @@ dec[s,9,13]: dec[m,9,13]: dec[d,9,13]: -0.000000000000000000000000000000047991690431925214 dec[c,9,14]: 2147483647 -dec[a,9,14]: -dec[s,9,14]: -dec[m,9,14]: -dec[d,9,14]: -0.000000000000000000000000000000047991690431925214 +dec[a,9,14]: 7654321.0 +dec[s,9,14]: 7654321.0 +dec[m,9,14]: 7654321.0 +dec[d,9,14]: 7654321.0 dec[c,10,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,10,0]: @@ -972,10 +972,10 @@ dec[s,10,13]: dec[m,10,13]: dec[d,10,13]: 0.0000000000000000000000000000026600400239403602 dec[c,10,14]: 2147483647 -dec[a,10,14]: -dec[s,10,14]: -dec[m,10,14]: -dec[d,10,14]: 0.0000000000000000000000000000026600400239403602 +dec[a,10,14]: 7654321.0 +dec[s,10,14]: 7654321.0 +dec[m,10,14]: 7654321.0 +dec[d,10,14]: 7654321.0 dec[c,11,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,11,0]: @@ -1047,10 +1047,10 @@ dec[s,11,13]: dec[m,11,13]: dec[d,11,13]: 0.00000000000000000000000000040500081364500732 dec[c,11,14]: 2147483647 -dec[a,11,14]: -dec[s,11,14]: -dec[m,11,14]: -dec[d,11,14]: 0.00000000000000000000000000040500081364500732 +dec[a,11,14]: 7654321.0 +dec[s,11,14]: 7654321.0 +dec[m,11,14]: 7654321.0 +dec[d,11,14]: 7654321.0 dec[c,12,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,12,0]: @@ -1122,10 +1122,10 @@ dec[s,12,13]: dec[m,12,13]: dec[d,12,13]: -0.00000000000000000000000000040500008464500076 dec[c,12,14]: 2147483647 -dec[a,12,14]: -dec[s,12,14]: -dec[m,12,14]: -dec[d,12,14]: -0.00000000000000000000000000040500008464500076 +dec[a,12,14]: 7654321.0 +dec[s,12,14]: 7654321.0 +dec[m,12,14]: 7654321.0 +dec[d,12,14]: 7654321.0 dec[c,13,0]: -1 (errno == PGTYPES_NUM_OVERFLOW) - r: -1200 dec[s,13,0]: @@ -1197,85 +1197,85 @@ dec[s,13,13]: 0.00 dec[m,13,13]: dec[d,13,13]: 1.00000000000000000 dec[c,13,14]: 2147483647 -dec[a,13,14]: 2469135780246913578024691357.82 -dec[s,13,14]: 0.00 -dec[m,13,14]: -dec[d,13,14]: 1.00000000000000000 +dec[a,13,14]: 7654321.0 +dec[s,13,14]: 7654321.0 +dec[m,13,14]: 7654321.0 +dec[d,13,14]: 7654321.0 dec[c,14,0]: 2147483647 -dec[a,14,0]: 2469135780246913578024691357.82 -dec[s,14,0]: 0.00 -dec[m,14,0]: -dec[d,14,0]: 1.00000000000000000 +dec[a,14,0]: 7654321.0 +dec[s,14,0]: 7654321.0 +dec[m,14,0]: 7654321.0 +dec[d,14,0]: 7654321.0 dec[c,14,1]: 2147483647 -dec[a,14,1]: 2469135780246913578024691357.82 -dec[s,14,1]: 0.00 -dec[m,14,1]: -dec[d,14,1]: 1.00000000000000000 +dec[a,14,1]: 7654321.0 +dec[s,14,1]: 7654321.0 +dec[m,14,1]: 7654321.0 +dec[d,14,1]: 7654321.0 dec[c,14,2]: 2147483647 -dec[a,14,2]: 2469135780246913578024691357.82 -dec[s,14,2]: 0.00 -dec[m,14,2]: -dec[d,14,2]: 1.00000000000000000 +dec[a,14,2]: 7654321.0 +dec[s,14,2]: 7654321.0 +dec[m,14,2]: 7654321.0 +dec[d,14,2]: 7654321.0 dec[c,14,3]: 2147483647 -dec[a,14,3]: 2469135780246913578024691357.82 -dec[s,14,3]: 0.00 -dec[m,14,3]: -dec[d,14,3]: 1.00000000000000000 +dec[a,14,3]: 7654321.0 +dec[s,14,3]: 7654321.0 +dec[m,14,3]: 7654321.0 +dec[d,14,3]: 7654321.0 dec[c,14,4]: 2147483647 -dec[a,14,4]: 2469135780246913578024691357.82 -dec[s,14,4]: 0.00 -dec[m,14,4]: -dec[d,14,4]: 1.00000000000000000 +dec[a,14,4]: 7654321.0 +dec[s,14,4]: 7654321.0 +dec[m,14,4]: 7654321.0 +dec[d,14,4]: 7654321.0 dec[c,14,5]: 2147483647 -dec[a,14,5]: 2469135780246913578024691357.82 -dec[s,14,5]: 0.00 -dec[m,14,5]: -dec[d,14,5]: 1.00000000000000000 +dec[a,14,5]: 7654321.0 +dec[s,14,5]: 7654321.0 +dec[m,14,5]: 7654321.0 +dec[d,14,5]: 7654321.0 dec[c,14,6]: 2147483647 -dec[a,14,6]: 2469135780246913578024691357.82 -dec[s,14,6]: 0.00 -dec[m,14,6]: -dec[d,14,6]: 1.00000000000000000 +dec[a,14,6]: 7654321.0 +dec[s,14,6]: 7654321.0 +dec[m,14,6]: 7654321.0 +dec[d,14,6]: 7654321.0 dec[c,14,7]: 2147483647 -dec[a,14,7]: 2469135780246913578024691357.82 -dec[s,14,7]: 0.00 -dec[m,14,7]: -dec[d,14,7]: 1.00000000000000000 +dec[a,14,7]: 7654321.0 +dec[s,14,7]: 7654321.0 +dec[m,14,7]: 7654321.0 +dec[d,14,7]: 7654321.0 dec[c,14,8]: 2147483647 -dec[a,14,8]: 2469135780246913578024691357.82 -dec[s,14,8]: 0.00 -dec[m,14,8]: -dec[d,14,8]: 1.00000000000000000 +dec[a,14,8]: 7654321.0 +dec[s,14,8]: 7654321.0 +dec[m,14,8]: 7654321.0 +dec[d,14,8]: 7654321.0 dec[c,14,9]: 2147483647 -dec[a,14,9]: 2469135780246913578024691357.82 -dec[s,14,9]: 0.00 -dec[m,14,9]: -dec[d,14,9]: 1.00000000000000000 +dec[a,14,9]: 7654321.0 +dec[s,14,9]: 7654321.0 +dec[m,14,9]: 7654321.0 +dec[d,14,9]: 7654321.0 dec[c,14,10]: 2147483647 -dec[a,14,10]: 2469135780246913578024691357.82 -dec[s,14,10]: 0.00 -dec[m,14,10]: -dec[d,14,10]: 1.00000000000000000 +dec[a,14,10]: 7654321.0 +dec[s,14,10]: 7654321.0 +dec[m,14,10]: 7654321.0 +dec[d,14,10]: 7654321.0 dec[c,14,11]: 2147483647 -dec[a,14,11]: 2469135780246913578024691357.82 -dec[s,14,11]: 0.00 -dec[m,14,11]: -dec[d,14,11]: 1.00000000000000000 +dec[a,14,11]: 7654321.0 +dec[s,14,11]: 7654321.0 +dec[m,14,11]: 7654321.0 +dec[d,14,11]: 7654321.0 dec[c,14,12]: 2147483647 -dec[a,14,12]: 2469135780246913578024691357.82 -dec[s,14,12]: 0.00 -dec[m,14,12]: -dec[d,14,12]: 1.00000000000000000 +dec[a,14,12]: 7654321.0 +dec[s,14,12]: 7654321.0 +dec[m,14,12]: 7654321.0 +dec[d,14,12]: 7654321.0 dec[c,14,13]: 2147483647 -dec[a,14,13]: 2469135780246913578024691357.82 -dec[s,14,13]: 0.00 -dec[m,14,13]: -dec[d,14,13]: 1.00000000000000000 +dec[a,14,13]: 7654321.0 +dec[s,14,13]: 7654321.0 +dec[m,14,13]: 7654321.0 +dec[d,14,13]: 7654321.0 dec[c,14,14]: 2147483647 -dec[a,14,14]: 2469135780246913578024691357.82 -dec[s,14,14]: 0.00 -dec[m,14,14]: -dec[d,14,14]: 1.00000000000000000 +dec[a,14,14]: 7654321.0 +dec[s,14,14]: 7654321.0 +dec[m,14,14]: 7654321.0 +dec[d,14,14]: 7654321.0 0: * 1: -2 2: 0.794 diff --git a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c index 7e19319d27f88..8eebc51664ee9 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c @@ -97,12 +97,14 @@ typedef struct sqlda_struct sqlda_t; #define SQLINTERVAL ECPGt_interval #define SQLNCHAR ECPGt_char #define SQLNVCHAR ECPGt_char -#ifdef HAVE_LONG_LONG_INT_64 +#if SIZEOF_LONG == 8 +#define SQLINT8 ECPGt_long +#define SQLSERIAL8 ECPGt_long +#elif SIZEOF_LONG_LONG == 8 #define SQLINT8 ECPGt_long_long #define SQLSERIAL8 ECPGt_long_long #else -#define SQLINT8 ECPGt_long -#define SQLSERIAL8 ECPGt_long +#error "cannot find integer type of the same size as SQLINT8" #endif #endif /* ndef ECPG_SQLTYPES_H */ diff --git a/src/interfaces/ecpg/test/expected/connect-test5.c b/src/interfaces/ecpg/test/expected/connect-test5.c index ec1514ed9abe4..fc650f5cd57cb 100644 --- a/src/interfaces/ecpg/test/expected/connect-test5.c +++ b/src/interfaces/ecpg/test/expected/connect-test5.c @@ -117,7 +117,7 @@ main(void) #line 56 "test5.pgc" - { ECPGconnect(__LINE__, 0, "unix:postgresql://localhost/ecpg2_regression?connect_timeout=180 & client_encoding=sql_ascii" , "regress_ecpg_user1" , "connectpw" , "main", 0); } + { ECPGconnect(__LINE__, 0, "unix:postgresql://localhost/ecpg2_regression?connect_timeout=180&client_encoding=sql_ascii" , "regress_ecpg_user1" , "connectpw" , "main", 0); } #line 58 "test5.pgc" { ECPGdisconnect(__LINE__, "main");} diff --git a/src/interfaces/ecpg/test/expected/connect-test5.stderr b/src/interfaces/ecpg/test/expected/connect-test5.stderr index 51cc18916a1fc..037db217586dd 100644 --- a/src/interfaces/ecpg/test/expected/connect-test5.stderr +++ b/src/interfaces/ecpg/test/expected/connect-test5.stderr @@ -50,7 +50,7 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection main closed [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGconnect: opening database ecpg2_regression on port with options connect_timeout=180 & client_encoding=sql_ascii for user regress_ecpg_user1 +[NO_PID]: ECPGconnect: opening database ecpg2_regression on port with options connect_timeout=180&client_encoding=sql_ascii for user regress_ecpg_user1 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection main closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c index ee867b6dd862e..1f1d341a4acca 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -22,9 +23,11 @@ -#line 8 "dt_test.pgc" +#line 9 "dt_test.pgc" +static void check_errno(void); + int main(void) { @@ -34,19 +37,19 @@ main(void) -#line 14 "dt_test.pgc" +#line 17 "dt_test.pgc" date date1 ; -#line 15 "dt_test.pgc" +#line 18 "dt_test.pgc" timestamp ts1 ; -#line 16 "dt_test.pgc" +#line 19 "dt_test.pgc" interval * iv1 , iv2 ; -#line 17 "dt_test.pgc" +#line 20 "dt_test.pgc" char * text ; /* exec sql end declare section */ -#line 18 "dt_test.pgc" +#line 21 "dt_test.pgc" date date2; int mdy[3] = { 4, 19, 1998 }; @@ -57,31 +60,31 @@ main(void) ECPGdebug(1, stderr); /* exec sql whenever sqlerror do sqlprint ( ) ; */ -#line 27 "dt_test.pgc" +#line 30 "dt_test.pgc" { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , NULL, 0); -#line 28 "dt_test.pgc" +#line 31 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 28 "dt_test.pgc" +#line 31 "dt_test.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table date_test ( d date , ts timestamp )", ECPGt_EOIT, ECPGt_EORT); -#line 29 "dt_test.pgc" +#line 32 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 29 "dt_test.pgc" +#line 32 "dt_test.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT); -#line 30 "dt_test.pgc" +#line 33 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 30 "dt_test.pgc" +#line 33 "dt_test.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set intervalstyle to postgres_verbose", ECPGt_EOIT, ECPGt_EORT); -#line 31 "dt_test.pgc" +#line 34 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 31 "dt_test.pgc" +#line 34 "dt_test.pgc" date1 = PGTYPESdate_from_asc(d1, NULL); @@ -92,10 +95,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 36 "dt_test.pgc" +#line 39 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 36 "dt_test.pgc" +#line 39 "dt_test.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select * from date_test where d = $1 ", @@ -105,10 +108,10 @@ if (sqlca.sqlcode < 0) sqlprint ( );} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_timestamp,&(ts1),(long)1,(long)1,sizeof(timestamp), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 38 "dt_test.pgc" +#line 41 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 38 "dt_test.pgc" +#line 41 "dt_test.pgc" text = PGTYPESdate_to_asc(date1); @@ -263,10 +266,19 @@ if (sqlca.sqlcode < 0) sqlprint ( );} PGTYPESchar_free(text); ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL); + /* failure, check error code */ + check_errno(); text = PGTYPEStimestamp_to_asc(ts1); printf("timestamp_to_asc3: %s\n", text); PGTYPESchar_free(text); + ts1 = PGTYPEStimestamp_from_asc("AM95000062", NULL); + /* failure, check error code */ + check_errno(); + text = PGTYPEStimestamp_to_asc(ts1); + printf("timestamp_to_asc4: %s\n", text); + PGTYPESchar_free(text); + /* abc-03:10:35-def-02/11/94-gh */ /* 12345678901234567890123456789 */ @@ -453,17 +465,35 @@ if (sqlca.sqlcode < 0) sqlprint ( );} free(out); { ECPGtrans(__LINE__, NULL, "rollback"); -#line 381 "dt_test.pgc" +#line 393 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 381 "dt_test.pgc" +#line 393 "dt_test.pgc" { ECPGdisconnect(__LINE__, "CURRENT"); -#line 382 "dt_test.pgc" +#line 394 "dt_test.pgc" if (sqlca.sqlcode < 0) sqlprint ( );} -#line 382 "dt_test.pgc" +#line 394 "dt_test.pgc" return 0; } + +static void +check_errno(void) +{ + switch(errno) + { + case 0: + printf("(no errno set) - "); + break; + case PGTYPES_TS_BAD_TIMESTAMP: + printf("(errno == PGTYPES_TS_BAD_TIMESTAMP) - "); + break; + default: + printf("(unknown errno (%d))\n", errno); + printf("(libc: (%s)) ", strerror(errno)); + break; + } +} diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr index 6e9ed3d3dbad3..2a109ee7fa145 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stderr @@ -2,47 +2,47 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGconnect: opening database ecpg1_regression on port [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 29: query: create table date_test ( d date , ts timestamp ); with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 32: query: create table date_test ( d date , ts timestamp ); with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 29: using PQexec +[NO_PID]: ecpg_execute on line 32: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 29: OK: CREATE TABLE +[NO_PID]: ecpg_process_output on line 32: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 30: query: set datestyle to iso; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 33: query: set datestyle to iso; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 30: using PQexec +[NO_PID]: ecpg_execute on line 33: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 30: OK: SET +[NO_PID]: ecpg_process_output on line 33: OK: SET [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 31: query: set intervalstyle to postgres_verbose; with 0 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 34: query: set intervalstyle to postgres_verbose; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 31: using PQexec +[NO_PID]: ecpg_execute on line 34: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 31: OK: SET +[NO_PID]: ecpg_process_output on line 34: OK: SET [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 36: query: insert into date_test ( d , ts ) values ( $1 , $2 ); with 2 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 39: query: insert into date_test ( d , ts ) values ( $1 , $2 ); with 2 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 36: using PQexecParams +[NO_PID]: ecpg_execute on line 39: using PQexecParams [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 36: parameter 1 = 1966-01-17 +[NO_PID]: ecpg_free_params on line 39: parameter 1 = 1966-01-17 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 36: parameter 2 = 2000-07-12 17:34:29 +[NO_PID]: ecpg_free_params on line 39: parameter 2 = 2000-07-12 17:34:29 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 36: OK: INSERT 0 1 +[NO_PID]: ecpg_process_output on line 39: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 38: query: select * from date_test where d = $1 ; with 1 parameter(s) on connection ecpg1_regression +[NO_PID]: ecpg_execute on line 41: query: select * from date_test where d = $1 ; with 1 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 38: using PQexecParams +[NO_PID]: ecpg_execute on line 41: using PQexecParams [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 38: parameter 1 = 1966-01-17 +[NO_PID]: ecpg_free_params on line 41: parameter 1 = 1966-01-17 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 38: correctly got 1 tuples with 2 fields +[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 38: RESULT: 1966-01-17 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: 1966-01-17 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 38: RESULT: 2000-07-12 17:34:29 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 41: RESULT: 2000-07-12 17:34:29 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 381: action "rollback"; connection "ecpg1_regression" +[NO_PID]: ECPGtrans on line 393: action "rollback"; connection "ecpg1_regression" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection ecpg1_regression closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout index 4b582fd7a2802..6b8bcc9fc2737 100644 --- a/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-dt_test.stdout @@ -20,7 +20,8 @@ date_defmt_asc10: 1995-12-25 date_defmt_asc12: 0095-12-25 timestamp_to_asc1: 1996-02-29 00:00:00 timestamp_to_asc2: 1994-02-11 03:10:35 -timestamp_to_asc3: 2000-01-01 00:00:00 +(errno == PGTYPES_TS_BAD_TIMESTAMP) - timestamp_to_asc3: 2000-01-01 00:00:00 +(errno == PGTYPES_TS_BAD_TIMESTAMP) - timestamp_to_asc4: 2000-01-01 00:00:00 timestamp_fmt_asc: 0: abc-00:00:00-def-01/01/00-ghi% timestamp_defmt_asc(This is a 4/12/80 3-39l12test, This is a %m/%d/%y %H-%Ml%Stest) = 1980-04-12 03:39:12, error: 0 timestamp_defmt_asc(Tue Jul 22 17:28:44 +0200 2003, %a %b %d %H:%M:%S %z %Y) = 2003-07-22 15:28:44, error: 0 diff --git a/src/interfaces/ecpg/test/expected/sql-sqlda.c b/src/interfaces/ecpg/test/expected/sql-sqlda.c index ee1a674271f57..10ebba3cbb791 100644 --- a/src/interfaces/ecpg/test/expected/sql-sqlda.c +++ b/src/interfaces/ecpg/test/expected/sql-sqlda.c @@ -155,13 +155,8 @@ dump_sqlda(sqlda_t *sqlda) printf("name sqlda descriptor: '%s' value %ld\n", sqlda->sqlvar[i].sqlname.data, *(long int *)sqlda->sqlvar[i].sqldata); break; case ECPGt_long_long: - printf( -#ifdef _WIN32 - "name sqlda descriptor: '%s' value %I64d\n", -#else - "name sqlda descriptor: '%s' value %lld\n", -#endif - sqlda->sqlvar[i].sqlname.data, *(long long int *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %lld\n", + sqlda->sqlvar[i].sqlname.data, *(long long int *)sqlda->sqlvar[i].sqldata); break; case ECPGt_double: printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqlname.data, *(double *)sqlda->sqlvar[i].sqldata); @@ -188,19 +183,19 @@ main (void) -#line 71 "sqlda.pgc" +#line 66 "sqlda.pgc" char * stmt1 = "SELECT * FROM t1" ; -#line 72 "sqlda.pgc" +#line 67 "sqlda.pgc" char * stmt2 = "SELECT * FROM t1 WHERE id = ?" ; -#line 73 "sqlda.pgc" +#line 68 "sqlda.pgc" int rec ; -#line 74 "sqlda.pgc" +#line 69 "sqlda.pgc" int id ; /* exec sql end declare section */ -#line 75 "sqlda.pgc" +#line 70 "sqlda.pgc" char msg[128]; @@ -209,42 +204,42 @@ main (void) strcpy(msg, "connect"); { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "regress1", 0); -#line 82 "sqlda.pgc" +#line 77 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 82 "sqlda.pgc" +#line 77 "sqlda.pgc" strcpy(msg, "set"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT); -#line 85 "sqlda.pgc" +#line 80 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 85 "sqlda.pgc" +#line 80 "sqlda.pgc" strcpy(msg, "create"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table t1 ( id integer , t text , d1 numeric , d2 float8 , c char ( 10 ) , big bigint )", ECPGt_EOIT, ECPGt_EORT); -#line 95 "sqlda.pgc" +#line 90 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 95 "sqlda.pgc" +#line 90 "sqlda.pgc" strcpy(msg, "insert"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 )", ECPGt_EOIT, ECPGt_EORT); -#line 103 "sqlda.pgc" +#line 98 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 103 "sqlda.pgc" +#line 98 "sqlda.pgc" strcpy(msg, "commit"); { ECPGtrans(__LINE__, NULL, "commit"); -#line 106 "sqlda.pgc" +#line 101 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 106 "sqlda.pgc" +#line 101 "sqlda.pgc" /* SQLDA test for getting all records from a table */ @@ -253,29 +248,29 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "prepare"); { ECPGprepare(__LINE__, NULL, 0, "st_id1", stmt1); -#line 113 "sqlda.pgc" +#line 108 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 113 "sqlda.pgc" +#line 108 "sqlda.pgc" strcpy(msg, "declare"); /* declare mycur1 cursor for $1 */ -#line 116 "sqlda.pgc" +#line 111 "sqlda.pgc" strcpy(msg, "open"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur1 cursor for $1", ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id1", __LINE__)),(long)1,(long)1,(1)*sizeof(char), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 119 "sqlda.pgc" +#line 114 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 119 "sqlda.pgc" +#line 114 "sqlda.pgc" /* exec sql whenever not found break ; */ -#line 121 "sqlda.pgc" +#line 116 "sqlda.pgc" rec = 0; @@ -285,13 +280,13 @@ if (sqlca.sqlcode < 0) exit (1);} { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from mycur1", ECPGt_EOIT, ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L, ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 127 "sqlda.pgc" +#line 122 "sqlda.pgc" if (sqlca.sqlcode == ECPG_NOT_FOUND) break; -#line 127 "sqlda.pgc" +#line 122 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 127 "sqlda.pgc" +#line 122 "sqlda.pgc" printf("FETCH RECORD %d\n", ++rec); @@ -299,23 +294,23 @@ if (sqlca.sqlcode < 0) exit (1);} } /* exec sql whenever not found continue ; */ -#line 133 "sqlda.pgc" +#line 128 "sqlda.pgc" strcpy(msg, "close"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur1", ECPGt_EOIT, ECPGt_EORT); -#line 136 "sqlda.pgc" +#line 131 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 136 "sqlda.pgc" +#line 131 "sqlda.pgc" strcpy(msg, "deallocate"); { ECPGdeallocate(__LINE__, 0, NULL, "st_id1"); -#line 139 "sqlda.pgc" +#line 134 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 139 "sqlda.pgc" +#line 134 "sqlda.pgc" free(outp_sqlda); @@ -326,35 +321,35 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "prepare"); { ECPGprepare(__LINE__, NULL, 0, "st_id2", stmt1); -#line 148 "sqlda.pgc" +#line 143 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 148 "sqlda.pgc" +#line 143 "sqlda.pgc" strcpy(msg, "declare"); /* declare mycur2 cursor for $1 */ -#line 151 "sqlda.pgc" +#line 146 "sqlda.pgc" strcpy(msg, "open"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur2 cursor for $1", ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id2", __LINE__)),(long)1,(long)1,(1)*sizeof(char), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); -#line 154 "sqlda.pgc" +#line 149 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 154 "sqlda.pgc" +#line 149 "sqlda.pgc" strcpy(msg, "fetch"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch all from mycur2", ECPGt_EOIT, ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L, ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 157 "sqlda.pgc" +#line 152 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 157 "sqlda.pgc" +#line 152 "sqlda.pgc" outp_sqlda1 = outp_sqlda; @@ -372,18 +367,18 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "close"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur2", ECPGt_EOIT, ECPGt_EORT); -#line 173 "sqlda.pgc" +#line 168 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 173 "sqlda.pgc" +#line 168 "sqlda.pgc" strcpy(msg, "deallocate"); { ECPGdeallocate(__LINE__, 0, NULL, "st_id2"); -#line 176 "sqlda.pgc" +#line 171 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 176 "sqlda.pgc" +#line 171 "sqlda.pgc" /* SQLDA test for getting one record using an input descriptor */ @@ -407,10 +402,10 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "prepare"); { ECPGprepare(__LINE__, NULL, 0, "st_id3", stmt2); -#line 198 "sqlda.pgc" +#line 193 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 198 "sqlda.pgc" +#line 193 "sqlda.pgc" strcpy(msg, "execute"); @@ -419,20 +414,20 @@ if (sqlca.sqlcode < 0) exit (1);} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L, ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 201 "sqlda.pgc" +#line 196 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 201 "sqlda.pgc" +#line 196 "sqlda.pgc" dump_sqlda(outp_sqlda); strcpy(msg, "deallocate"); { ECPGdeallocate(__LINE__, 0, NULL, "st_id3"); -#line 206 "sqlda.pgc" +#line 201 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 206 "sqlda.pgc" +#line 201 "sqlda.pgc" free(inp_sqlda); @@ -443,10 +438,10 @@ if (sqlca.sqlcode < 0) exit (1);} */ { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "con2", 0); -#line 215 "sqlda.pgc" +#line 210 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 215 "sqlda.pgc" +#line 210 "sqlda.pgc" /* @@ -468,10 +463,10 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "prepare"); { ECPGprepare(__LINE__, "con2", 0, "st_id4", stmt2); -#line 235 "sqlda.pgc" +#line 230 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 235 "sqlda.pgc" +#line 230 "sqlda.pgc" strcpy(msg, "execute"); @@ -480,28 +475,28 @@ if (sqlca.sqlcode < 0) exit (1);} ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_sqlda, &outp_sqlda, 0L, 0L, 0L, ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); -#line 238 "sqlda.pgc" +#line 233 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 238 "sqlda.pgc" +#line 233 "sqlda.pgc" dump_sqlda(outp_sqlda); strcpy(msg, "commit"); { ECPGtrans(__LINE__, "con2", "commit"); -#line 243 "sqlda.pgc" +#line 238 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 243 "sqlda.pgc" +#line 238 "sqlda.pgc" strcpy(msg, "deallocate"); { ECPGdeallocate(__LINE__, 0, NULL, "st_id4"); -#line 246 "sqlda.pgc" +#line 241 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 246 "sqlda.pgc" +#line 241 "sqlda.pgc" free(inp_sqlda); @@ -509,36 +504,36 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "disconnect"); { ECPGdisconnect(__LINE__, "con2"); -#line 252 "sqlda.pgc" +#line 247 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 252 "sqlda.pgc" +#line 247 "sqlda.pgc" /* End test */ strcpy(msg, "drop"); { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table t1", ECPGt_EOIT, ECPGt_EORT); -#line 257 "sqlda.pgc" +#line 252 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 257 "sqlda.pgc" +#line 252 "sqlda.pgc" strcpy(msg, "commit"); { ECPGtrans(__LINE__, NULL, "commit"); -#line 260 "sqlda.pgc" +#line 255 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 260 "sqlda.pgc" +#line 255 "sqlda.pgc" strcpy(msg, "disconnect"); { ECPGdisconnect(__LINE__, "CURRENT"); -#line 263 "sqlda.pgc" +#line 258 "sqlda.pgc" if (sqlca.sqlcode < 0) exit (1);} -#line 263 "sqlda.pgc" +#line 258 "sqlda.pgc" return 0; diff --git a/src/interfaces/ecpg/test/expected/sql-sqlda.stderr b/src/interfaces/ecpg/test/expected/sql-sqlda.stderr index dfe6b13055f94..51ef236a50e2c 100644 --- a/src/interfaces/ecpg/test/expected/sql-sqlda.stderr +++ b/src/interfaces/ecpg/test/expected/sql-sqlda.stderr @@ -2,459 +2,459 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGconnect: opening database ecpg1_regression on port [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 85: query: set datestyle to iso; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 80: query: set datestyle to iso; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 85: using PQexec +[NO_PID]: ecpg_execute on line 80: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 85: OK: SET +[NO_PID]: ecpg_process_output on line 80: OK: SET [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 88: query: create table t1 ( id integer , t text , d1 numeric , d2 float8 , c char ( 10 ) , big bigint ); with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 83: query: create table t1 ( id integer , t text , d1 numeric , d2 float8 , c char ( 10 ) , big bigint ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 88: using PQexec +[NO_PID]: ecpg_execute on line 83: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 88: OK: CREATE TABLE +[NO_PID]: ecpg_process_output on line 83: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 98: query: insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 ); with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 93: query: insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 98: using PQexec +[NO_PID]: ecpg_execute on line 93: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 98: OK: INSERT 0 5 +[NO_PID]: ecpg_process_output on line 93: OK: INSERT 0 5 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 106: action "commit"; connection "regress1" +[NO_PID]: ECPGtrans on line 101: action "commit"; connection "regress1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: prepare_common on line 113: name st_id1; query: "SELECT * FROM t1" +[NO_PID]: prepare_common on line 108: name st_id1; query: "SELECT * FROM t1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 119: query: declare mycur1 cursor for SELECT * FROM t1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 114: query: declare mycur1 cursor for SELECT * FROM t1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 119: using PQexec +[NO_PID]: ecpg_execute on line 114: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 119: OK: DECLARE CURSOR +[NO_PID]: ecpg_process_output on line 114: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 127 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 122 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: new sqlda was built +[NO_PID]: ecpg_process_output on line 122: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 1 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: a offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: a offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 1 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: a offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: a offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 1111111111111111111 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 1111111111111111111 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 122: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 127 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 122 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: new sqlda was built +[NO_PID]: ecpg_process_output on line 122: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 2 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 2 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 1 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 1 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 2 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 2 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 3 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 3 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 4 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 4 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 5 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 5 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 122: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 127 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 122 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: new sqlda was built +[NO_PID]: ecpg_process_output on line 122: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 3 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 3 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: c offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: c offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 3 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 3 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: c offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: c offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 3333333333333333333 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 3333333333333333333 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 122: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 127 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 122 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: new sqlda was built +[NO_PID]: ecpg_process_output on line 122: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 4444444444444444444 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 4444444444444444444 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 122: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 127 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 122 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: new sqlda was built +[NO_PID]: ecpg_process_output on line 122: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 5 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 5 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: e offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: e offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 5 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 5 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: e offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: e offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 127 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 122 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 127: RESULT: 5555555555555555555 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 122: RESULT: 5555555555555555555 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 122: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 122: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 127: using PQexec +[NO_PID]: ecpg_execute on line 122: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 127: correctly got 0 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 122: correctly got 0 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlcode 100 on line 127: no data found on line 127 +[NO_PID]: raising sqlcode 100 on line 122: no data found on line 122 [NO_PID]: sqlca: code: 100, state: 02000 -[NO_PID]: ecpg_execute on line 136: query: close mycur1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 131: query: close mycur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 136: using PQexec +[NO_PID]: ecpg_execute on line 131: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 136: OK: CLOSE CURSOR +[NO_PID]: ecpg_process_output on line 131: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 139: name st_id1 +[NO_PID]: deallocate_one on line 134: name st_id1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: prepare_common on line 148: name st_id2; query: "SELECT * FROM t1" +[NO_PID]: prepare_common on line 143: name st_id2; query: "SELECT * FROM t1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 154: query: declare mycur2 cursor for SELECT * FROM t1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 149: query: declare mycur2 cursor for SELECT * FROM t1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 154: using PQexec +[NO_PID]: ecpg_execute on line 149: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 154: OK: DECLARE CURSOR +[NO_PID]: ecpg_process_output on line 149: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 157: query: fetch all from mycur2; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 152: query: fetch all from mycur2; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 157: using PQexec +[NO_PID]: ecpg_execute on line 152: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: correctly got 5 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 152: correctly got 5 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 157 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 152 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: new sqlda was built +[NO_PID]: ecpg_process_output on line 152: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 5 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 5 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: e offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: e offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 5 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 5 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: e offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: e offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 4 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 4 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 5555555555555555555 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 5555555555555555555 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 152: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 157 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 152 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: new sqlda was built +[NO_PID]: ecpg_process_output on line 152: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 3 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 3 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 4444444444444444444 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 4444444444444444444 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 152: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 157 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 152 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: new sqlda was built +[NO_PID]: ecpg_process_output on line 152: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 3 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 3 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: c offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: c offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 3 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 3 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: c offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: c offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 2 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 2 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 3333333333333333333 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 3333333333333333333 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 152: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 157 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 152 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: new sqlda was built +[NO_PID]: ecpg_process_output on line 152: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 2 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 2 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 1 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 1 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 2 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 2 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 3 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 3 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 4 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 4 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 1 col 5 IS NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 1 col 5 IS NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 152: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 157 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 152 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: new sqlda was built +[NO_PID]: ecpg_process_output on line 152: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 1 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: a offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: a offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 1 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 1 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: a offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: a offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 157 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 152 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 157: RESULT: 1111111111111111111 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 152: RESULT: 1111111111111111111 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 157: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 152: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 173: query: close mycur2; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 168: query: close mycur2; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 173: using PQexec +[NO_PID]: ecpg_execute on line 168: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 173: OK: CLOSE CURSOR +[NO_PID]: ecpg_process_output on line 168: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 176: name st_id2 +[NO_PID]: deallocate_one on line 171: name st_id2 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: prepare_common on line 198: name st_id3; query: "SELECT * FROM t1 WHERE id = $1" +[NO_PID]: prepare_common on line 193: name st_id3; query: "SELECT * FROM t1 WHERE id = $1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 201: query: SELECT * FROM t1 WHERE id = $1; with 1 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 196: query: SELECT * FROM t1 WHERE id = $1; with 1 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 201: using PQexecPrepared for "SELECT * FROM t1 WHERE id = $1" +[NO_PID]: ecpg_execute on line 196: using PQexecPrepared for "SELECT * FROM t1 WHERE id = $1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 201: parameter 1 = 4 +[NO_PID]: ecpg_free_params on line 196: parameter 1 = 4 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 201: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 196: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 201 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 196 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 201: new sqlda was built +[NO_PID]: ecpg_process_output on line 196: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 201: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 196: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 201: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 196: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 201: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 196: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 201: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 196: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 201 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 196 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 201: RESULT: 4444444444444444444 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 196: RESULT: 4444444444444444444 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 201: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 196: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 206: name st_id3 +[NO_PID]: deallocate_one on line 201: name st_id3 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGconnect: opening database ecpg1_regression on port [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: prepare_common on line 235: name st_id4; query: "SELECT * FROM t1 WHERE id = $1" +[NO_PID]: prepare_common on line 230: name st_id4; query: "SELECT * FROM t1 WHERE id = $1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 238: query: SELECT * FROM t1 WHERE id = $1; with 1 parameter(s) on connection con2 +[NO_PID]: ecpg_execute on line 233: query: SELECT * FROM t1 WHERE id = $1; with 1 parameter(s) on connection con2 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 238: using PQexecPrepared for "SELECT * FROM t1 WHERE id = $1" +[NO_PID]: ecpg_execute on line 233: using PQexecPrepared for "SELECT * FROM t1 WHERE id = $1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_free_params on line 238: parameter 1 = 4 +[NO_PID]: ecpg_free_params on line 233: parameter 1 = 4 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 238: correctly got 1 tuples with 6 fields +[NO_PID]: ecpg_process_output on line 233: correctly got 1 tuples with 6 fields [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_build_native_sqlda on line 238 sqld = 6 +[NO_PID]: ecpg_build_native_sqlda on line 233 sqld = 6 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 238: new sqlda was built +[NO_PID]: ecpg_process_output on line 233: new sqlda was built [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 0 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 0 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 238: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 233: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 1 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 1 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 238: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 233: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 2 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 2 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 3 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 3 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 238: RESULT: 4 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 233: RESULT: 4 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 4 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 4 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 238: RESULT: d offset: -1; array: no +[NO_PID]: ecpg_get_data on line 233: RESULT: d offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_set_native_sqlda on line 238 row 0 col 5 IS NOT NULL +[NO_PID]: ecpg_set_native_sqlda on line 233 row 0 col 5 IS NOT NULL [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_get_data on line 238: RESULT: 4444444444444444444 offset: -1; array: no +[NO_PID]: ecpg_get_data on line 233: RESULT: 4444444444444444444 offset: -1; array: no [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 238: putting result (1 tuple 6 fields) into sqlda descriptor +[NO_PID]: ecpg_process_output on line 233: putting result (1 tuple 6 fields) into sqlda descriptor [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 243: action "commit"; connection "con2" +[NO_PID]: ECPGtrans on line 238: action "commit"; connection "con2" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 246: name st_id4 +[NO_PID]: deallocate_one on line 241: name st_id4 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection con2 closed [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 257: query: drop table t1; with 0 parameter(s) on connection regress1 +[NO_PID]: ecpg_execute on line 252: query: drop table t1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_execute on line 257: using PQexec +[NO_PID]: ecpg_execute on line 252: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_process_output on line 257: OK: DROP TABLE +[NO_PID]: ecpg_process_output on line 252: OK: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 260: action "commit"; connection "regress1" +[NO_PID]: ECPGtrans on line 255: action "commit"; connection "regress1" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection regress1 closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-sqljson.stderr b/src/interfaces/ecpg/test/expected/sql-sqljson.stderr index c030fe3a986cc..e55a95dd711a4 100644 --- a/src/interfaces/ecpg/test/expected/sql-sqljson.stderr +++ b/src/interfaces/ecpg/test/expected/sql-sqljson.stderr @@ -240,12 +240,12 @@ SQL error: null value without indicator on line 84 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 99: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ecpg_check_PQresult on line 99: bad response - ERROR: cannot use RETURNING type jsonb in JSON_SERIALIZE() +[NO_PID]: ecpg_check_PQresult on line 99: bad response - ERROR: cannot use type jsonb in RETURNING clause of JSON_SERIALIZE() HINT: Try returning a string type or bytea. [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlstate 42804 (sqlcode -400): cannot use RETURNING type jsonb in JSON_SERIALIZE() on line 99 +[NO_PID]: raising sqlstate 42804 (sqlcode -400): cannot use type jsonb in RETURNING clause of JSON_SERIALIZE() on line 99 [NO_PID]: sqlca: code: -400, state: 42804 -SQL error: cannot use RETURNING type jsonb in JSON_SERIALIZE() on line 99 +SQL error: cannot use type jsonb in RETURNING clause of JSON_SERIALIZE() on line 99 [NO_PID]: ecpg_execute on line 102: query: with val ( js ) as ( values ( '{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] }' ) ) select js is json "IS JSON" , js is not json "IS NOT JSON" , js is json value "IS VALUE" , js is json object "IS OBJECT" , js is json array "IS ARRAY" , js is json scalar "IS SCALAR" , js is json without unique keys "WITHOUT UNIQUE" , js is json with unique keys "WITH UNIQUE" from val; with 0 parameter(s) on connection ecpg1_regression [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 102: using PQexec diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build index c1e508ccc82b1..4ccdf9d295a70 100644 --- a/src/interfaces/ecpg/test/meson.build +++ b/src/interfaces/ecpg/test/meson.build @@ -1,10 +1,12 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # can't run ecpg to build test dependencies, at least not without an emulator if meson.is_cross_build() subdir_done() endif +ecpg_test_dependencies = [] + pg_regress_ecpg_sources = pg_regress_c + files( 'pg_regress_ecpg.c', ) @@ -23,10 +25,11 @@ pg_regress_ecpg = executable('pg_regress_ecpg', 'install': false }, ) -testprep_targets += pg_regress_ecpg +ecpg_test_dependencies += pg_regress_ecpg # create .c files and executables from .pgc files ecpg_test_exec_kw = { + 'c_args': cflags_no_missing_var_decls, 'dependencies': [frontend_code, libpq], 'include_directories': [ecpg_inc], 'link_with': [ecpglib_so, ecpg_compat_so, ecpg_pgtypes_so], @@ -50,8 +53,6 @@ ecpg_preproc_test_command_end = [ '-o', '@OUTPUT@', '@INPUT@' ] -ecpg_test_dependencies = [] - subdir('compat_informix') subdir('compat_oracle') subdir('connect') diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c index c9960b8d202ab..ba3477f9dd8b7 100644 --- a/src/interfaces/ecpg/test/pg_regress_ecpg.c +++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c @@ -8,7 +8,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/ecpg/test/pg_regress_ecpg.c diff --git a/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc b/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc index f81a392665505..645c273e503cd 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc +++ b/src/interfaces/ecpg/test/pgtypeslib/dt_test.pgc @@ -2,11 +2,14 @@ #include #include #include +#include #include #include exec sql include ../regression; +static void check_errno(void); + int main(void) { @@ -189,10 +192,19 @@ main(void) PGTYPESchar_free(text); ts1 = PGTYPEStimestamp_from_asc("1994-02-11 26:10:35", NULL); + /* failure, check error code */ + check_errno(); text = PGTYPEStimestamp_to_asc(ts1); printf("timestamp_to_asc3: %s\n", text); PGTYPESchar_free(text); + ts1 = PGTYPEStimestamp_from_asc("AM95000062", NULL); + /* failure, check error code */ + check_errno(); + text = PGTYPEStimestamp_to_asc(ts1); + printf("timestamp_to_asc4: %s\n", text); + PGTYPESchar_free(text); + /* abc-03:10:35-def-02/11/94-gh */ /* 12345678901234567890123456789 */ @@ -383,3 +395,21 @@ main(void) return 0; } + +static void +check_errno(void) +{ + switch(errno) + { + case 0: + printf("(no errno set) - "); + break; + case PGTYPES_TS_BAD_TIMESTAMP: + printf("(errno == PGTYPES_TS_BAD_TIMESTAMP) - "); + break; + default: + printf("(unknown errno (%d))\n", errno); + printf("(libc: (%s)) ", strerror(errno)); + break; + } +} diff --git a/src/interfaces/ecpg/test/pgtypeslib/meson.build b/src/interfaces/ecpg/test/pgtypeslib/meson.build index 6266dc6b364db..499ad68aab610 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/meson.build +++ b/src/interfaces/ecpg/test/pgtypeslib/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'dt_test', diff --git a/src/interfaces/ecpg/test/preproc/meson.build b/src/interfaces/ecpg/test/preproc/meson.build index 949bbbb57cb03..775502e010266 100644 --- a/src/interfaces/ecpg/test/preproc/meson.build +++ b/src/interfaces/ecpg/test/preproc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'array_of_struct', diff --git a/src/interfaces/ecpg/test/sql/meson.build b/src/interfaces/ecpg/test/sql/meson.build index 4da6e19f5f13e..c0608173e4ba7 100644 --- a/src/interfaces/ecpg/test/sql/meson.build +++ b/src/interfaces/ecpg/test/sql/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'array', diff --git a/src/interfaces/ecpg/test/sql/sqlda.pgc b/src/interfaces/ecpg/test/sql/sqlda.pgc index e551385eaa4f6..f7aa296ebf942 100644 --- a/src/interfaces/ecpg/test/sql/sqlda.pgc +++ b/src/interfaces/ecpg/test/sql/sqlda.pgc @@ -40,13 +40,8 @@ dump_sqlda(sqlda_t *sqlda) printf("name sqlda descriptor: '%s' value %ld\n", sqlda->sqlvar[i].sqlname.data, *(long int *)sqlda->sqlvar[i].sqldata); break; case ECPGt_long_long: - printf( -#ifdef _WIN32 - "name sqlda descriptor: '%s' value %I64d\n", -#else - "name sqlda descriptor: '%s' value %lld\n", -#endif - sqlda->sqlvar[i].sqlname.data, *(long long int *)sqlda->sqlvar[i].sqldata); + printf("name sqlda descriptor: '%s' value %lld\n", + sqlda->sqlvar[i].sqlname.data, *(long long int *)sqlda->sqlvar[i].sqldata); break; case ECPGt_double: printf("name sqlda descriptor: '%s' value %f\n", sqlda->sqlvar[i].sqlname.data, *(double *)sqlda->sqlvar[i].sqldata); diff --git a/src/interfaces/ecpg/test/thread/meson.build b/src/interfaces/ecpg/test/thread/meson.build index 5ed67ccbcd14e..6a6745ce0fc4e 100644 --- a/src/interfaces/ecpg/test/thread/meson.build +++ b/src/interfaces/ecpg/test/thread/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgc_files = [ 'thread_implicit', diff --git a/src/interfaces/libpq-oauth/.gitignore b/src/interfaces/libpq-oauth/.gitignore new file mode 100644 index 0000000000000..a4afe7c1c6858 --- /dev/null +++ b/src/interfaces/libpq-oauth/.gitignore @@ -0,0 +1 @@ +/exports.list diff --git a/src/interfaces/libpq-oauth/Makefile b/src/interfaces/libpq-oauth/Makefile new file mode 100644 index 0000000000000..270fc0cf2d9d9 --- /dev/null +++ b/src/interfaces/libpq-oauth/Makefile @@ -0,0 +1,83 @@ +#------------------------------------------------------------------------- +# +# Makefile for libpq-oauth +# +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/interfaces/libpq-oauth/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/interfaces/libpq-oauth +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +PGFILEDESC = "libpq-oauth - device authorization OAuth support" + +# This is an internal module; we don't want an SONAME and therefore do not set +# SO_MAJOR_VERSION. +NAME = pq-oauth-$(MAJORVERSION) + +# Force the name "libpq-oauth" for both the static and shared libraries. The +# staticlib doesn't need version information in its name. +override shlib := lib$(NAME)$(DLSUFFIX) +override stlib := libpq-oauth.a + +override CPPFLAGS := -I$(libpq_srcdir) -I$(top_builddir)/src/port $(LIBCURL_CPPFLAGS) $(CPPFLAGS) + +OBJS = \ + $(WIN32RES) + +OBJS_STATIC = oauth-curl.o + +# The shared library needs additional glue symbols. +OBJS_SHLIB = \ + oauth-curl_shlib.o \ + oauth-utils.o \ + +oauth-utils.o: override CPPFLAGS += -DUSE_DYNAMIC_OAUTH +oauth-curl_shlib.o: override CPPFLAGS_SHLIB += -DUSE_DYNAMIC_OAUTH + +# Add shlib-/stlib-specific objects. +$(shlib): override OBJS += $(OBJS_SHLIB) +$(shlib): $(OBJS_SHLIB) + +$(stlib): override OBJS += $(OBJS_STATIC) +$(stlib): $(OBJS_STATIC) + +SHLIB_LINK_INTERNAL = $(libpq_pgport_shlib) +SHLIB_LINK = $(LIBCURL_LDFLAGS) $(LIBCURL_LDLIBS) $(filter -lintl, $(LIBS)) +SHLIB_PREREQS = submake-libpq +SHLIB_EXPORTS = exports.txt + +# Disable -bundle_loader on macOS. +BE_DLLLIBS = + +# By default, a library without an SONAME doesn't get a static library, so we +# add it to the build explicitly. +all: all-lib all-static-lib + +# Shared library stuff +include $(top_srcdir)/src/Makefile.shlib + +# Use src/common/Makefile's trick for tracking dependencies of shlib-specific +# objects. +%_shlib.o: %.c %.o + $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) $(CPPFLAGS_SHLIB) -c $< -o $@ + +# Ignore the standard rules for SONAME-less installation; we want both the +# static and shared libraries to go into libdir. +install: all installdirs $(stlib) $(shlib) + $(INSTALL_SHLIB) $(shlib) '$(DESTDIR)$(libdir)/$(shlib)' + $(INSTALL_STLIB) $(stlib) '$(DESTDIR)$(libdir)/$(stlib)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(libdir)' + +uninstall: + rm -f '$(DESTDIR)$(libdir)/$(stlib)' + rm -f '$(DESTDIR)$(libdir)/$(shlib)' + +clean distclean: clean-lib + rm -f $(OBJS) $(OBJS_STATIC) $(OBJS_SHLIB) diff --git a/src/interfaces/libpq-oauth/README b/src/interfaces/libpq-oauth/README new file mode 100644 index 0000000000000..553962d644e94 --- /dev/null +++ b/src/interfaces/libpq-oauth/README @@ -0,0 +1,57 @@ +libpq-oauth is an optional module implementing the Device Authorization flow for +OAuth clients (RFC 8628). It is maintained as its own shared library in order to +isolate its dependency on libcurl. (End users who don't want the Curl dependency +can simply choose not to install this module.) + +If a connection string allows the use of OAuth, and the server asks for it, and +a libpq client has not installed its own custom OAuth flow, libpq will attempt +to delay-load this module using dlopen() and the following ABI. Failure to load +results in a failed connection. + += Load-Time ABI = + +This module ABI is an internal implementation detail, so it's subject to change +across major releases; the name of the module (libpq-oauth-MAJOR) reflects this. +The module exports the following symbols: + +- PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn); +- void pg_fe_cleanup_oauth_flow(PGconn *conn); + +pg_fe_run_oauth_flow and pg_fe_cleanup_oauth_flow are implementations of +conn->async_auth and conn->cleanup_async_auth, respectively. + +At the moment, pg_fe_run_oauth_flow() relies on libpq's pg_g_threadlock and +libpq_gettext(), which must be injected by libpq using this initialization +function before the flow is run: + +- void libpq_oauth_init(pgthreadlock_t threadlock, + libpq_gettext_func gettext_impl, + conn_errorMessage_func errmsg_impl, + conn_oauth_client_id_func clientid_impl, + conn_oauth_client_secret_func clientsecret_impl, + conn_oauth_discovery_uri_func discoveryuri_impl, + conn_oauth_issuer_id_func issuerid_impl, + conn_oauth_scope_func scope_impl, + conn_sasl_state_func saslstate_impl, + set_conn_altsock_func setaltsock_impl, + set_conn_oauth_token_func settoken_impl); + +It also relies on access to several members of the PGconn struct. Not only can +these change positions across minor versions, but the offsets aren't necessarily +stable within a single minor release (conn->errorMessage, for instance, can +change offsets depending on configure-time options). Therefore the necessary +accessors (named conn_*) and mutators (set_conn_*) are injected here. With this +approach, we can safely search the standard dlopen() paths (e.g. RPATH, +LD_LIBRARY_PATH, the SO cache) for an implementation module to use, even if that +module wasn't compiled at the same time as libpq -- which becomes especially +important during "live upgrade" situations where a running libpq application has +the libpq-oauth module updated out from under it before it's first loaded from +disk. + += Static Build = + +The static library libpq.a does not perform any dynamic loading. If the builtin +flow is enabled, the application is expected to link against libpq-oauth.a +directly to provide the necessary symbols. (libpq.a and libpq-oauth.a must be +part of the same build. Unlike the dynamic module, there are no translation +shims provided.) diff --git a/src/interfaces/libpq-oauth/exports.txt b/src/interfaces/libpq-oauth/exports.txt new file mode 100644 index 0000000000000..6891a83dbf998 --- /dev/null +++ b/src/interfaces/libpq-oauth/exports.txt @@ -0,0 +1,4 @@ +# src/interfaces/libpq-oauth/exports.txt +libpq_oauth_init 1 +pg_fe_run_oauth_flow 2 +pg_fe_cleanup_oauth_flow 3 diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build new file mode 100644 index 0000000000000..df064c59a4070 --- /dev/null +++ b/src/interfaces/libpq-oauth/meson.build @@ -0,0 +1,49 @@ +# Copyright (c) 2022-2025, PostgreSQL Global Development Group + +if not oauth_flow_supported + subdir_done() +endif + +libpq_oauth_sources = files( + 'oauth-curl.c', +) + +# The shared library needs additional glue symbols. +libpq_oauth_so_sources = files( + 'oauth-utils.c', +) +libpq_oauth_so_c_args = ['-DUSE_DYNAMIC_OAUTH'] + +export_file = custom_target('libpq-oauth.exports', + kwargs: gen_export_kwargs, +) + +# port needs to be in include path due to pthread-win32.h +libpq_oauth_inc = include_directories('.', '../libpq', '../../port') + +libpq_oauth_st = static_library('libpq-oauth', + libpq_oauth_sources, + include_directories: [libpq_oauth_inc, postgres_inc], + c_pch: pch_postgres_fe_h, + dependencies: [ + frontend_stlib_code, + libpq_oauth_deps, + ssl, # libpq-int.h includes OpenSSL headers + ], + kwargs: default_lib_args, +) + +# This is an internal module; we don't want an SONAME and therefore do not set +# SO_MAJOR_VERSION. +libpq_oauth_name = 'libpq-oauth-@0@'.format(pg_version_major) + +libpq_oauth_so = shared_module(libpq_oauth_name, + libpq_oauth_sources + libpq_oauth_so_sources, + include_directories: [libpq_oauth_inc, postgres_inc], + c_args: libpq_so_c_args, + c_pch: pch_postgres_fe_h, + dependencies: [frontend_shlib_code, libpq, libpq_oauth_deps], + link_depends: export_file, + link_args: export_fmt.format(export_file.full_path()), + kwargs: default_lib_args, +) diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c new file mode 100644 index 0000000000000..dba9a684fa8a5 --- /dev/null +++ b/src/interfaces/libpq-oauth/oauth-curl.c @@ -0,0 +1,2975 @@ +/*------------------------------------------------------------------------- + * + * oauth-curl.c + * The libcurl implementation of OAuth/OIDC authentication, using the + * OAuth Device Authorization Grant (RFC 8628). + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq-oauth/oauth-curl.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include +#include +#include + +#if defined(HAVE_SYS_EPOLL_H) +#include +#include +#elif defined(HAVE_SYS_EVENT_H) +#include +#else +#error libpq-oauth is not supported on this platform +#endif + +#include "common/jsonapi.h" +#include "fe-auth-oauth.h" +#include "mb/pg_wchar.h" +#include "oauth-curl.h" + +#ifdef USE_DYNAMIC_OAUTH + +/* + * The module build is decoupled from libpq-int.h, to try to avoid inadvertent + * ABI breaks during minor version bumps. Replacements for the missing internals + * are provided by oauth-utils. + */ +#include "oauth-utils.h" + +#else /* !USE_DYNAMIC_OAUTH */ + +/* + * Static builds may rely on PGconn offsets directly. Keep these aligned with + * the bank of callbacks in oauth-utils.h. + */ +#include "libpq-int.h" + +#define conn_errorMessage(CONN) (&CONN->errorMessage) +#define conn_oauth_client_id(CONN) (CONN->oauth_client_id) +#define conn_oauth_client_secret(CONN) (CONN->oauth_client_secret) +#define conn_oauth_discovery_uri(CONN) (CONN->oauth_discovery_uri) +#define conn_oauth_issuer_id(CONN) (CONN->oauth_issuer_id) +#define conn_oauth_scope(CONN) (CONN->oauth_scope) +#define conn_sasl_state(CONN) (CONN->sasl_state) + +#define set_conn_altsock(CONN, VAL) do { CONN->altsock = VAL; } while (0) +#define set_conn_oauth_token(CONN, VAL) do { CONN->oauth_token = VAL; } while (0) + +#endif /* USE_DYNAMIC_OAUTH */ + +/* One final guardrail against accidental inclusion... */ +#if defined(USE_DYNAMIC_OAUTH) && defined(LIBPQ_INT_H) +#error do not rely on libpq-int.h in dynamic builds of libpq-oauth +#endif + +/* + * It's generally prudent to set a maximum response size to buffer in memory, + * but it's less clear what size to choose. The biggest of our expected + * responses is the server metadata JSON, which will only continue to grow in + * size; the number of IANA-registered parameters in that document is up to 78 + * as of February 2025. + * + * Even if every single parameter were to take up 2k on average (a previously + * common limit on the size of a URL), 256k gives us 128 parameter values before + * we give up. (That's almost certainly complete overkill in practice; 2-4k + * appears to be common among popular providers at the moment.) + */ +#define MAX_OAUTH_RESPONSE_SIZE (256 * 1024) + +/* + * Similarly, a limit on the maximum JSON nesting level keeps a server from + * running us out of stack space. A common nesting level in practice is 2 (for a + * top-level object containing arrays of strings). As of May 2025, the maximum + * depth for standard server metadata appears to be 6, if the document contains + * a full JSON Web Key Set in its "jwks" parameter. + * + * Since it's easy to nest JSON, and the number of parameters and key types + * keeps growing, take a healthy buffer of 16. (If this ever proves to be a + * problem in practice, we may want to switch over to the incremental JSON + * parser instead of playing with this parameter.) + */ +#define MAX_OAUTH_NESTING_LEVEL 16 + +/* + * Parsed JSON Representations + * + * As a general rule, we parse and cache only the fields we're currently using. + * When adding new fields, ensure the corresponding free_*() function is updated + * too. + */ + +/* + * The OpenID Provider configuration (alternatively named "authorization server + * metadata") jointly described by OpenID Connect Discovery 1.0 and RFC 8414: + * + * https://openid.net/specs/openid-connect-discovery-1_0.html + * https://www.rfc-editor.org/rfc/rfc8414#section-3.2 + */ +struct provider +{ + char *issuer; + char *token_endpoint; + char *device_authorization_endpoint; + struct curl_slist *grant_types_supported; +}; + +static void +free_provider(struct provider *provider) +{ + free(provider->issuer); + free(provider->token_endpoint); + free(provider->device_authorization_endpoint); + curl_slist_free_all(provider->grant_types_supported); +} + +/* + * The Device Authorization response, described by RFC 8628: + * + * https://www.rfc-editor.org/rfc/rfc8628#section-3.2 + */ +struct device_authz +{ + char *device_code; + char *user_code; + char *verification_uri; + char *verification_uri_complete; + char *expires_in_str; + char *interval_str; + + /* Fields below are parsed from the corresponding string above. */ + int expires_in; + int interval; +}; + +static void +free_device_authz(struct device_authz *authz) +{ + free(authz->device_code); + free(authz->user_code); + free(authz->verification_uri); + free(authz->verification_uri_complete); + free(authz->expires_in_str); + free(authz->interval_str); +} + +/* + * The Token Endpoint error response, as described by RFC 6749: + * + * https://www.rfc-editor.org/rfc/rfc6749#section-5.2 + * + * Note that this response type can also be returned from the Device + * Authorization Endpoint. + */ +struct token_error +{ + char *error; + char *error_description; +}; + +static void +free_token_error(struct token_error *err) +{ + free(err->error); + free(err->error_description); +} + +/* + * The Access Token response, as described by RFC 6749: + * + * https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4 + * + * During the Device Authorization flow, several temporary errors are expected + * as part of normal operation. To make it easy to handle these in the happy + * path, this contains an embedded token_error that is filled in if needed. + */ +struct token +{ + /* for successful responses */ + char *access_token; + char *token_type; + + /* for error responses */ + struct token_error err; +}; + +static void +free_token(struct token *tok) +{ + free(tok->access_token); + free(tok->token_type); + free_token_error(&tok->err); +} + +/* + * Asynchronous State + */ + +/* States for the overall async machine. */ +enum OAuthStep +{ + OAUTH_STEP_INIT = 0, + OAUTH_STEP_DISCOVERY, + OAUTH_STEP_DEVICE_AUTHORIZATION, + OAUTH_STEP_TOKEN_REQUEST, + OAUTH_STEP_WAIT_INTERVAL, +}; + +/* + * The async_ctx holds onto state that needs to persist across multiple calls + * to pg_fe_run_oauth_flow(). Almost everything interacts with this in some + * way. + */ +struct async_ctx +{ + enum OAuthStep step; /* where are we in the flow? */ + + int timerfd; /* descriptor for signaling async timeouts */ + pgsocket mux; /* the multiplexer socket containing all + * descriptors tracked by libcurl, plus the + * timerfd */ + CURLM *curlm; /* top-level multi handle for libcurl + * operations */ + CURL *curl; /* the (single) easy handle for serial + * requests */ + + struct curl_slist *headers; /* common headers for all requests */ + PQExpBufferData work_data; /* scratch buffer for general use (remember to + * clear out prior contents first!) */ + + /*------ + * Since a single logical operation may stretch across multiple calls to + * our entry point, errors have three parts: + * + * - errctx: an optional static string, describing the global operation + * currently in progress. It'll be translated for you. + * + * - errbuf: contains the actual error message. Generally speaking, use + * actx_error[_str] to manipulate this. This must be filled + * with something useful on an error. + * + * - curl_err: an optional static error buffer used by libcurl to put + * detailed information about failures. Unfortunately + * untranslatable. + * + * These pieces will be combined into a single error message looking + * something like the following, with errctx and/or curl_err omitted when + * absent: + * + * connection to server ... failed: errctx: errbuf (libcurl: curl_err) + */ + const char *errctx; /* not freed; must point to static allocation */ + PQExpBufferData errbuf; + char curl_err[CURL_ERROR_SIZE]; + + /* + * These documents need to survive over multiple calls, and are therefore + * cached directly in the async_ctx. + */ + struct provider provider; + struct device_authz authz; + + int running; /* is asynchronous work in progress? */ + bool user_prompted; /* have we already sent the authz prompt? */ + bool used_basic_auth; /* did we send a client secret? */ + bool debugging; /* can we give unsafe developer assistance? */ +}; + +/* + * Tears down the Curl handles and frees the async_ctx. + */ +static void +free_async_ctx(PGconn *conn, struct async_ctx *actx) +{ + /* + * In general, none of the error cases below should ever happen if we have + * no bugs above. But if we do hit them, surfacing those errors somehow + * might be the only way to have a chance to debug them. + * + * TODO: At some point it'd be nice to have a standard way to warn about + * teardown failures. Appending to the connection's error message only + * helps if the bug caused a connection failure; otherwise it'll be + * buried... + */ + + if (actx->curlm && actx->curl) + { + CURLMcode err = curl_multi_remove_handle(actx->curlm, actx->curl); + + if (err) + libpq_append_conn_error(conn, + "libcurl easy handle removal failed: %s", + curl_multi_strerror(err)); + } + + if (actx->curl) + { + /* + * curl_multi_cleanup() doesn't free any associated easy handles; we + * need to do that separately. We only ever have one easy handle per + * multi handle. + */ + curl_easy_cleanup(actx->curl); + } + + if (actx->curlm) + { + CURLMcode err = curl_multi_cleanup(actx->curlm); + + if (err) + libpq_append_conn_error(conn, + "libcurl multi handle cleanup failed: %s", + curl_multi_strerror(err)); + } + + free_provider(&actx->provider); + free_device_authz(&actx->authz); + + curl_slist_free_all(actx->headers); + termPQExpBuffer(&actx->work_data); + termPQExpBuffer(&actx->errbuf); + + if (actx->mux != PGINVALID_SOCKET) + close(actx->mux); + if (actx->timerfd >= 0) + close(actx->timerfd); + + free(actx); +} + +/* + * Release resources used for the asynchronous exchange and disconnect the + * altsock. + * + * This is called either at the end of a successful authentication, or during + * pqDropConnection(), so we won't leak resources even if PQconnectPoll() never + * calls us back. + */ +void +pg_fe_cleanup_oauth_flow(PGconn *conn) +{ + fe_oauth_state *state = conn_sasl_state(conn); + + if (state->async_ctx) + { + free_async_ctx(conn, state->async_ctx); + state->async_ctx = NULL; + } + + set_conn_altsock(conn, PGINVALID_SOCKET); +} + +/* + * Macros for manipulating actx->errbuf. actx_error() translates and formats a + * string for you; actx_error_str() appends a string directly without + * translation. + */ + +#define actx_error(ACTX, FMT, ...) \ + appendPQExpBuffer(&(ACTX)->errbuf, libpq_gettext(FMT), ##__VA_ARGS__) + +#define actx_error_str(ACTX, S) \ + appendPQExpBufferStr(&(ACTX)->errbuf, S) + +/* + * Macros for getting and setting state for the connection's two libcurl + * handles, so you don't have to write out the error handling every time. + */ + +#define CHECK_MSETOPT(ACTX, OPT, VAL, FAILACTION) \ + do { \ + struct async_ctx *_actx = (ACTX); \ + CURLMcode _setopterr = curl_multi_setopt(_actx->curlm, OPT, VAL); \ + if (_setopterr) { \ + actx_error(_actx, "failed to set %s on OAuth connection: %s",\ + #OPT, curl_multi_strerror(_setopterr)); \ + FAILACTION; \ + } \ + } while (0) + +#define CHECK_SETOPT(ACTX, OPT, VAL, FAILACTION) \ + do { \ + struct async_ctx *_actx = (ACTX); \ + CURLcode _setopterr = curl_easy_setopt(_actx->curl, OPT, VAL); \ + if (_setopterr) { \ + actx_error(_actx, "failed to set %s on OAuth connection: %s",\ + #OPT, curl_easy_strerror(_setopterr)); \ + FAILACTION; \ + } \ + } while (0) + +#define CHECK_GETINFO(ACTX, INFO, OUT, FAILACTION) \ + do { \ + struct async_ctx *_actx = (ACTX); \ + CURLcode _getinfoerr = curl_easy_getinfo(_actx->curl, INFO, OUT); \ + if (_getinfoerr) { \ + actx_error(_actx, "failed to get %s from OAuth response: %s",\ + #INFO, curl_easy_strerror(_getinfoerr)); \ + FAILACTION; \ + } \ + } while (0) + +/* + * General JSON Parsing for OAuth Responses + */ + +/* + * Represents a single name/value pair in a JSON object. This is the primary + * interface to parse_oauth_json(). + * + * All fields are stored internally as strings or lists of strings, so clients + * have to explicitly parse other scalar types (though they will have gone + * through basic lexical validation). Storing nested objects is not currently + * supported, nor is parsing arrays of anything other than strings. + */ +struct json_field +{ + const char *name; /* name (key) of the member */ + + JsonTokenType type; /* currently supports JSON_TOKEN_STRING, + * JSON_TOKEN_NUMBER, and + * JSON_TOKEN_ARRAY_START */ + union + { + char **scalar; /* for all scalar types */ + struct curl_slist **array; /* for type == JSON_TOKEN_ARRAY_START */ + } target; + + bool required; /* REQUIRED field, or just OPTIONAL? */ +}; + +/* Documentation macros for json_field.required. */ +#define PG_OAUTH_REQUIRED true +#define PG_OAUTH_OPTIONAL false + +/* Parse state for parse_oauth_json(). */ +struct oauth_parse +{ + PQExpBuffer errbuf; /* detail message for JSON_SEM_ACTION_FAILED */ + int nested; /* nesting level (zero is the top) */ + + const struct json_field *fields; /* field definition array */ + const struct json_field *active; /* points inside the fields array */ +}; + +#define oauth_parse_set_error(ctx, fmt, ...) \ + appendPQExpBuffer((ctx)->errbuf, libpq_gettext(fmt), ##__VA_ARGS__) + +static void +report_type_mismatch(struct oauth_parse *ctx) +{ + char *msgfmt; + + Assert(ctx->active); + + /* + * At the moment, the only fields we're interested in are strings, + * numbers, and arrays of strings. + */ + switch (ctx->active->type) + { + case JSON_TOKEN_STRING: + msgfmt = "field \"%s\" must be a string"; + break; + + case JSON_TOKEN_NUMBER: + msgfmt = "field \"%s\" must be a number"; + break; + + case JSON_TOKEN_ARRAY_START: + msgfmt = "field \"%s\" must be an array of strings"; + break; + + default: + Assert(false); + msgfmt = "field \"%s\" has unexpected type"; + } + + oauth_parse_set_error(ctx, msgfmt, ctx->active->name); +} + +static JsonParseErrorType +oauth_json_object_start(void *state) +{ + struct oauth_parse *ctx = state; + + if (ctx->active) + { + /* + * Currently, none of the fields we're interested in can be or contain + * objects, so we can reject this case outright. + */ + report_type_mismatch(ctx); + return JSON_SEM_ACTION_FAILED; + } + + ++ctx->nested; + if (ctx->nested > MAX_OAUTH_NESTING_LEVEL) + { + oauth_parse_set_error(ctx, "JSON is too deeply nested"); + return JSON_SEM_ACTION_FAILED; + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_object_field_start(void *state, char *name, bool isnull) +{ + struct oauth_parse *ctx = state; + + /* We care only about the top-level fields. */ + if (ctx->nested == 1) + { + const struct json_field *field = ctx->fields; + + /* + * We should never start parsing a new field while a previous one is + * still active. + */ + if (ctx->active) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: started field '%s' before field '%s' was finished", + name, ctx->active->name); + return JSON_SEM_ACTION_FAILED; + } + + while (field->name) + { + if (strcmp(name, field->name) == 0) + { + ctx->active = field; + break; + } + + ++field; + } + + /* + * We don't allow duplicate field names; error out if the target has + * already been set. + */ + if (ctx->active) + { + field = ctx->active; + + if ((field->type == JSON_TOKEN_ARRAY_START && *field->target.array) + || (field->type != JSON_TOKEN_ARRAY_START && *field->target.scalar)) + { + oauth_parse_set_error(ctx, "field \"%s\" is duplicated", + field->name); + return JSON_SEM_ACTION_FAILED; + } + } + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_object_end(void *state) +{ + struct oauth_parse *ctx = state; + + --ctx->nested; + + /* + * All fields should be fully processed by the end of the top-level + * object. + */ + if (!ctx->nested && ctx->active) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: field '%s' still active at end of object", + ctx->active->name); + return JSON_SEM_ACTION_FAILED; + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_array_start(void *state) +{ + struct oauth_parse *ctx = state; + + if (!ctx->nested) + { + oauth_parse_set_error(ctx, "top-level element must be an object"); + return JSON_SEM_ACTION_FAILED; + } + + if (ctx->active) + { + if (ctx->active->type != JSON_TOKEN_ARRAY_START + /* The arrays we care about must not have arrays as values. */ + || ctx->nested > 1) + { + report_type_mismatch(ctx); + return JSON_SEM_ACTION_FAILED; + } + } + + ++ctx->nested; + if (ctx->nested > MAX_OAUTH_NESTING_LEVEL) + { + oauth_parse_set_error(ctx, "JSON is too deeply nested"); + return JSON_SEM_ACTION_FAILED; + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_array_end(void *state) +{ + struct oauth_parse *ctx = state; + + if (ctx->active) + { + /* + * Clear the target (which should be an array inside the top-level + * object). For this to be safe, no target arrays can contain other + * arrays; we check for that in the array_start callback. + */ + if (ctx->nested != 2 || ctx->active->type != JSON_TOKEN_ARRAY_START) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: found unexpected array end while parsing field '%s'", + ctx->active->name); + return JSON_SEM_ACTION_FAILED; + } + + ctx->active = NULL; + } + + --ctx->nested; + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_scalar(void *state, char *token, JsonTokenType type) +{ + struct oauth_parse *ctx = state; + + if (!ctx->nested) + { + oauth_parse_set_error(ctx, "top-level element must be an object"); + return JSON_SEM_ACTION_FAILED; + } + + if (ctx->active) + { + const struct json_field *field = ctx->active; + JsonTokenType expected = field->type; + + /* Make sure this matches what the active field expects. */ + if (expected == JSON_TOKEN_ARRAY_START) + { + /* Are we actually inside an array? */ + if (ctx->nested < 2) + { + report_type_mismatch(ctx); + return JSON_SEM_ACTION_FAILED; + } + + /* Currently, arrays can only contain strings. */ + expected = JSON_TOKEN_STRING; + } + + if (type != expected) + { + report_type_mismatch(ctx); + return JSON_SEM_ACTION_FAILED; + } + + if (field->type != JSON_TOKEN_ARRAY_START) + { + /* Ensure that we're parsing the top-level keys... */ + if (ctx->nested != 1) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: scalar target found at nesting level %d", + ctx->nested); + return JSON_SEM_ACTION_FAILED; + } + + /* ...and that a result has not already been set. */ + if (*field->target.scalar) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: scalar field '%s' would be assigned twice", + ctx->active->name); + return JSON_SEM_ACTION_FAILED; + } + + *field->target.scalar = strdup(token); + if (!*field->target.scalar) + return JSON_OUT_OF_MEMORY; + + ctx->active = NULL; + + return JSON_SUCCESS; + } + else + { + struct curl_slist *temp; + + /* The target array should be inside the top-level object. */ + if (ctx->nested != 2) + { + Assert(false); + oauth_parse_set_error(ctx, + "internal error: array member found at nesting level %d", + ctx->nested); + return JSON_SEM_ACTION_FAILED; + } + + /* Note that curl_slist_append() makes a copy of the token. */ + temp = curl_slist_append(*field->target.array, token); + if (!temp) + return JSON_OUT_OF_MEMORY; + + *field->target.array = temp; + } + } + else + { + /* otherwise we just ignore it */ + } + + return JSON_SUCCESS; +} + +/* + * Checks the Content-Type header against the expected type. Parameters are + * allowed but ignored. + */ +static bool +check_content_type(struct async_ctx *actx, const char *type) +{ + const size_t type_len = strlen(type); + char *content_type; + + CHECK_GETINFO(actx, CURLINFO_CONTENT_TYPE, &content_type, return false); + + if (!content_type) + { + actx_error(actx, "no content type was provided"); + return false; + } + + /* + * We need to perform a length limited comparison and not compare the + * whole string. + */ + if (pg_strncasecmp(content_type, type, type_len) != 0) + goto fail; + + /* On an exact match, we're done. */ + Assert(strlen(content_type) >= type_len); + if (content_type[type_len] == '\0') + return true; + + /* + * Only a semicolon (optionally preceded by HTTP optional whitespace) is + * acceptable after the prefix we checked. This marks the start of media + * type parameters, which we currently have no use for. + */ + for (size_t i = type_len; content_type[i]; ++i) + { + switch (content_type[i]) + { + case ';': + return true; /* success! */ + + case ' ': + case '\t': + /* HTTP optional whitespace allows only spaces and htabs. */ + break; + + default: + goto fail; + } + } + +fail: + actx_error(actx, "unexpected content type: \"%s\"", content_type); + return false; +} + +/* + * A helper function for general JSON parsing. fields is the array of field + * definitions with their backing pointers. The response will be parsed from + * actx->curl and actx->work_data (as set up by start_request()), and any + * parsing errors will be placed into actx->errbuf. + */ +static bool +parse_oauth_json(struct async_ctx *actx, const struct json_field *fields) +{ + PQExpBuffer resp = &actx->work_data; + JsonLexContext lex = {0}; + JsonSemAction sem = {0}; + JsonParseErrorType err; + struct oauth_parse ctx = {0}; + bool success = false; + + if (!check_content_type(actx, "application/json")) + return false; + + if (strlen(resp->data) != resp->len) + { + actx_error(actx, "response contains embedded NULLs"); + return false; + } + + /* + * pg_parse_json doesn't validate the incoming UTF-8, so we have to check + * that up front. + */ + if (pg_encoding_verifymbstr(PG_UTF8, resp->data, resp->len) != resp->len) + { + actx_error(actx, "response is not valid UTF-8"); + return false; + } + + makeJsonLexContextCstringLen(&lex, resp->data, resp->len, PG_UTF8, true); + setJsonLexContextOwnsTokens(&lex, true); /* must not leak on error */ + + ctx.errbuf = &actx->errbuf; + ctx.fields = fields; + sem.semstate = &ctx; + + sem.object_start = oauth_json_object_start; + sem.object_field_start = oauth_json_object_field_start; + sem.object_end = oauth_json_object_end; + sem.array_start = oauth_json_array_start; + sem.array_end = oauth_json_array_end; + sem.scalar = oauth_json_scalar; + + err = pg_parse_json(&lex, &sem); + + if (err != JSON_SUCCESS) + { + /* + * For JSON_SEM_ACTION_FAILED, we've already written the error + * message. Other errors come directly from pg_parse_json(), already + * translated. + */ + if (err != JSON_SEM_ACTION_FAILED) + actx_error_str(actx, json_errdetail(err, &lex)); + + goto cleanup; + } + + /* Check all required fields. */ + while (fields->name) + { + if (fields->required + && !*fields->target.scalar + && !*fields->target.array) + { + actx_error(actx, "field \"%s\" is missing", fields->name); + goto cleanup; + } + + fields++; + } + + success = true; + +cleanup: + freeJsonLexContext(&lex); + return success; +} + +/* + * JSON Parser Definitions + */ + +/* + * Parses authorization server metadata. Fields are defined by OIDC Discovery + * 1.0 and RFC 8414. + */ +static bool +parse_provider(struct async_ctx *actx, struct provider *provider) +{ + struct json_field fields[] = { + {"issuer", JSON_TOKEN_STRING, {&provider->issuer}, PG_OAUTH_REQUIRED}, + {"token_endpoint", JSON_TOKEN_STRING, {&provider->token_endpoint}, PG_OAUTH_REQUIRED}, + + /*---- + * The following fields are technically REQUIRED, but we don't use + * them anywhere yet: + * + * - jwks_uri + * - response_types_supported + * - subject_types_supported + * - id_token_signing_alg_values_supported + */ + + {"device_authorization_endpoint", JSON_TOKEN_STRING, {&provider->device_authorization_endpoint}, PG_OAUTH_OPTIONAL}, + {"grant_types_supported", JSON_TOKEN_ARRAY_START, {.array = &provider->grant_types_supported}, PG_OAUTH_OPTIONAL}, + + {0}, + }; + + return parse_oauth_json(actx, fields); +} + +/* + * Parses a valid JSON number into a double. The input must have come from + * pg_parse_json(), so that we know the lexer has validated it; there's no + * in-band signal for invalid formats. + */ +static double +parse_json_number(const char *s) +{ + double parsed; + int cnt; + + /* + * The JSON lexer has already validated the number, which is stricter than + * the %f format, so we should be good to use sscanf(). + */ + cnt = sscanf(s, "%lf", &parsed); + + if (cnt != 1) + { + /* + * Either the lexer screwed up or our assumption above isn't true, and + * either way a developer needs to take a look. + */ + Assert(false); + return 0; + } + + return parsed; +} + +/* + * Parses the "interval" JSON number, corresponding to the number of seconds to + * wait between token endpoint requests. + * + * RFC 8628 is pretty silent on sanity checks for the interval. As a matter of + * practicality, round any fractional intervals up to the next second, and clamp + * the result at a minimum of one. (Zero-second intervals would result in an + * expensive network polling loop.) Tests may remove the lower bound with + * PGOAUTHDEBUG, for improved performance. + */ +static int +parse_interval(struct async_ctx *actx, const char *interval_str) +{ + double parsed; + + parsed = parse_json_number(interval_str); + parsed = ceil(parsed); + + if (parsed < 1) + return actx->debugging ? 0 : 1; + + else if (parsed >= INT_MAX) + return INT_MAX; + + return parsed; +} + +/* + * Parses the "expires_in" JSON number, corresponding to the number of seconds + * remaining in the lifetime of the device code request. + * + * Similar to parse_interval, but we have even fewer requirements for reasonable + * values since we don't use the expiration time directly (it's passed to the + * PQAUTHDATA_PROMPT_OAUTH_DEVICE hook, in case the application wants to do + * something with it). We simply round down and clamp to int range. + */ +static int +parse_expires_in(struct async_ctx *actx, const char *expires_in_str) +{ + double parsed; + + parsed = parse_json_number(expires_in_str); + parsed = floor(parsed); + + if (parsed >= INT_MAX) + return INT_MAX; + else if (parsed <= INT_MIN) + return INT_MIN; + + return parsed; +} + +/* + * Parses the Device Authorization Response (RFC 8628, Sec. 3.2). + */ +static bool +parse_device_authz(struct async_ctx *actx, struct device_authz *authz) +{ + struct json_field fields[] = { + {"device_code", JSON_TOKEN_STRING, {&authz->device_code}, PG_OAUTH_REQUIRED}, + {"user_code", JSON_TOKEN_STRING, {&authz->user_code}, PG_OAUTH_REQUIRED}, + {"verification_uri", JSON_TOKEN_STRING, {&authz->verification_uri}, PG_OAUTH_REQUIRED}, + {"expires_in", JSON_TOKEN_NUMBER, {&authz->expires_in_str}, PG_OAUTH_REQUIRED}, + + /* + * Some services (Google, Azure) spell verification_uri differently. + * We accept either. + */ + {"verification_url", JSON_TOKEN_STRING, {&authz->verification_uri}, PG_OAUTH_REQUIRED}, + + /* + * There is no evidence of verification_uri_complete being spelled + * with "url" instead with any service provider, so only support + * "uri". + */ + {"verification_uri_complete", JSON_TOKEN_STRING, {&authz->verification_uri_complete}, PG_OAUTH_OPTIONAL}, + {"interval", JSON_TOKEN_NUMBER, {&authz->interval_str}, PG_OAUTH_OPTIONAL}, + + {0}, + }; + + if (!parse_oauth_json(actx, fields)) + return false; + + /* + * Parse our numeric fields. Lexing has already completed by this time, so + * we at least know they're valid JSON numbers. + */ + if (authz->interval_str) + authz->interval = parse_interval(actx, authz->interval_str); + else + { + /* + * RFC 8628 specifies 5 seconds as the default value if the server + * doesn't provide an interval. + */ + authz->interval = 5; + } + + Assert(authz->expires_in_str); /* ensured by parse_oauth_json() */ + authz->expires_in = parse_expires_in(actx, authz->expires_in_str); + + return true; +} + +/* + * Parses the device access token error response (RFC 8628, Sec. 3.5, which + * uses the error response defined in RFC 6749, Sec. 5.2). + */ +static bool +parse_token_error(struct async_ctx *actx, struct token_error *err) +{ + bool result; + struct json_field fields[] = { + {"error", JSON_TOKEN_STRING, {&err->error}, PG_OAUTH_REQUIRED}, + + {"error_description", JSON_TOKEN_STRING, {&err->error_description}, PG_OAUTH_OPTIONAL}, + + {0}, + }; + + result = parse_oauth_json(actx, fields); + + /* + * Since token errors are parsed during other active error paths, only + * override the errctx if parsing explicitly fails. + */ + if (!result) + actx->errctx = "failed to parse token error response"; + + return result; +} + +/* + * Constructs a message from the token error response and puts it into + * actx->errbuf. + */ +static void +record_token_error(struct async_ctx *actx, const struct token_error *err) +{ + if (err->error_description) + appendPQExpBuffer(&actx->errbuf, "%s ", err->error_description); + else + { + /* + * Try to get some more helpful detail into the error string. A 401 + * status in particular implies that the oauth_client_secret is + * missing or wrong. + */ + long response_code; + + CHECK_GETINFO(actx, CURLINFO_RESPONSE_CODE, &response_code, response_code = 0); + + if (response_code == 401) + { + actx_error(actx, actx->used_basic_auth + ? "provider rejected the oauth_client_secret" + : "provider requires client authentication, and no oauth_client_secret is set"); + actx_error_str(actx, " "); + } + } + + appendPQExpBuffer(&actx->errbuf, "(%s)", err->error); +} + +/* + * Parses the device access token response (RFC 8628, Sec. 3.5, which uses the + * success response defined in RFC 6749, Sec. 5.1). + */ +static bool +parse_access_token(struct async_ctx *actx, struct token *tok) +{ + struct json_field fields[] = { + {"access_token", JSON_TOKEN_STRING, {&tok->access_token}, PG_OAUTH_REQUIRED}, + {"token_type", JSON_TOKEN_STRING, {&tok->token_type}, PG_OAUTH_REQUIRED}, + + /*--- + * We currently have no use for the following OPTIONAL fields: + * + * - expires_in: This will be important for maintaining a token cache, + * but we do not yet implement one. + * + * - refresh_token: Ditto. + * + * - scope: This is only sent when the authorization server sees fit to + * change our scope request. It's not clear what we should do + * about this; either it's been done as a matter of policy, or + * the user has explicitly denied part of the authorization, + * and either way the server-side validator is in a better + * place to complain if the change isn't acceptable. + */ + + {0}, + }; + + return parse_oauth_json(actx, fields); +} + +/* + * libcurl Multi Setup/Callbacks + */ + +/* + * Sets up the actx->mux, which is the altsock that PQconnectPoll clients will + * select() on instead of the Postgres socket during OAuth negotiation. + * + * This is just an epoll set or kqueue abstracting multiple other descriptors. + * For epoll, the timerfd is always part of the set; it's just disabled when + * we're not using it. For kqueue, the "timerfd" is actually a second kqueue + * instance which is only added to the set when needed. + */ +static bool +setup_multiplexer(struct async_ctx *actx) +{ +#if defined(HAVE_SYS_EPOLL_H) + struct epoll_event ev = {.events = EPOLLIN}; + + actx->mux = epoll_create1(EPOLL_CLOEXEC); + if (actx->mux < 0) + { + actx_error(actx, "failed to create epoll set: %m"); + return false; + } + + actx->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (actx->timerfd < 0) + { + actx_error(actx, "failed to create timerfd: %m"); + return false; + } + + if (epoll_ctl(actx->mux, EPOLL_CTL_ADD, actx->timerfd, &ev) < 0) + { + actx_error(actx, "failed to add timerfd to epoll set: %m"); + return false; + } + + return true; +#elif defined(HAVE_SYS_EVENT_H) + actx->mux = kqueue(); + if (actx->mux < 0) + { + /*- translator: the term "kqueue" (kernel queue) should not be translated */ + actx_error(actx, "failed to create kqueue: %m"); + return false; + } + + /* + * Originally, we set EVFILT_TIMER directly on the top-level multiplexer. + * This makes it difficult to implement timer_expired(), though, so now we + * set EVFILT_TIMER on a separate actx->timerfd, which is chained to + * actx->mux while the timer is active. + */ + actx->timerfd = kqueue(); + if (actx->timerfd < 0) + { + actx_error(actx, "failed to create timer kqueue: %m"); + return false; + } + + return true; +#else +#error setup_multiplexer is not implemented on this platform +#endif +} + +/* + * Adds and removes sockets from the multiplexer set, as directed by the + * libcurl multi handle. + */ +static int +register_socket(CURL *curl, curl_socket_t socket, int what, void *ctx, + void *socketp) +{ + struct async_ctx *actx = ctx; + +#if defined(HAVE_SYS_EPOLL_H) + struct epoll_event ev = {0}; + int res; + int op = EPOLL_CTL_ADD; + + switch (what) + { + case CURL_POLL_IN: + ev.events = EPOLLIN; + break; + + case CURL_POLL_OUT: + ev.events = EPOLLOUT; + break; + + case CURL_POLL_INOUT: + ev.events = EPOLLIN | EPOLLOUT; + break; + + case CURL_POLL_REMOVE: + op = EPOLL_CTL_DEL; + break; + + default: + actx_error(actx, "unknown libcurl socket operation: %d", what); + return -1; + } + + res = epoll_ctl(actx->mux, op, socket, &ev); + if (res < 0 && errno == EEXIST) + { + /* We already had this socket in the poll set. */ + op = EPOLL_CTL_MOD; + res = epoll_ctl(actx->mux, op, socket, &ev); + } + + if (res < 0) + { + switch (op) + { + case EPOLL_CTL_ADD: + actx_error(actx, "could not add to epoll set: %m"); + break; + + case EPOLL_CTL_DEL: + actx_error(actx, "could not delete from epoll set: %m"); + break; + + default: + actx_error(actx, "could not update epoll set: %m"); + } + + return -1; + } + + return 0; +#elif defined(HAVE_SYS_EVENT_H) + struct kevent ev[2] = {0}; + struct kevent ev_out[2]; + struct timespec timeout = {0}; + int nev = 0; + int res; + + switch (what) + { + case CURL_POLL_IN: + EV_SET(&ev[nev], socket, EVFILT_READ, EV_ADD | EV_RECEIPT, 0, 0, 0); + nev++; + break; + + case CURL_POLL_OUT: + EV_SET(&ev[nev], socket, EVFILT_WRITE, EV_ADD | EV_RECEIPT, 0, 0, 0); + nev++; + break; + + case CURL_POLL_INOUT: + EV_SET(&ev[nev], socket, EVFILT_READ, EV_ADD | EV_RECEIPT, 0, 0, 0); + nev++; + EV_SET(&ev[nev], socket, EVFILT_WRITE, EV_ADD | EV_RECEIPT, 0, 0, 0); + nev++; + break; + + case CURL_POLL_REMOVE: + + /* + * We don't know which of these is currently registered, perhaps + * both, so we try to remove both. This means we need to tolerate + * ENOENT below. + */ + EV_SET(&ev[nev], socket, EVFILT_READ, EV_DELETE | EV_RECEIPT, 0, 0, 0); + nev++; + EV_SET(&ev[nev], socket, EVFILT_WRITE, EV_DELETE | EV_RECEIPT, 0, 0, 0); + nev++; + break; + + default: + actx_error(actx, "unknown libcurl socket operation: %d", what); + return -1; + } + + res = kevent(actx->mux, ev, nev, ev_out, lengthof(ev_out), &timeout); + if (res < 0) + { + actx_error(actx, "could not modify kqueue: %m"); + return -1; + } + + /* + * We can't use the simple errno version of kevent, because we need to + * skip over ENOENT while still allowing a second change to be processed. + * So we need a longer-form error checking loop. + */ + for (int i = 0; i < res; ++i) + { + /* + * EV_RECEIPT should guarantee one EV_ERROR result for every change, + * whether successful or not. Failed entries contain a non-zero errno + * in the data field. + */ + Assert(ev_out[i].flags & EV_ERROR); + + errno = ev_out[i].data; + if (errno && errno != ENOENT) + { + switch (what) + { + case CURL_POLL_REMOVE: + actx_error(actx, "could not delete from kqueue: %m"); + break; + default: + actx_error(actx, "could not add to kqueue: %m"); + } + return -1; + } + } + + return 0; +#else +#error register_socket is not implemented on this platform +#endif +} + +/* + * Enables or disables the timer in the multiplexer set. The timeout value is + * in milliseconds (negative values disable the timer). + * + * For epoll, rather than continually adding and removing the timer, we keep it + * in the set at all times and just disarm it when it's not needed. For kqueue, + * the timer is removed completely when disabled to prevent stale timeouts from + * remaining in the queue. + * + * To meet Curl requirements for the CURLMOPT_TIMERFUNCTION, implementations of + * set_timer must handle repeated calls by fully discarding any previous running + * or expired timer. + */ +static bool +set_timer(struct async_ctx *actx, long timeout) +{ +#if defined(HAVE_SYS_EPOLL_H) + struct itimerspec spec = {0}; + + if (timeout < 0) + { + /* the zero itimerspec will disarm the timer below */ + } + else if (timeout == 0) + { + /* + * A zero timeout means libcurl wants us to call back immediately. + * That's not technically an option for timerfd, but we can make the + * timeout ridiculously short. + */ + spec.it_value.tv_nsec = 1; + } + else + { + spec.it_value.tv_sec = timeout / 1000; + spec.it_value.tv_nsec = (timeout % 1000) * 1000000; + } + + if (timerfd_settime(actx->timerfd, 0 /* no flags */ , &spec, NULL) < 0) + { + actx_error(actx, "setting timerfd to %ld: %m", timeout); + return false; + } + + return true; +#elif defined(HAVE_SYS_EVENT_H) + struct kevent ev; + +#ifdef __NetBSD__ + + /* + * Work around NetBSD's rejection of zero timeouts (EINVAL), a bit like + * timerfd above. + */ + if (timeout == 0) + timeout = 1; +#endif + + /* + * Always disable the timer, and remove it from the multiplexer, to clear + * out any already-queued events. (On some BSDs, adding an EVFILT_TIMER to + * a kqueue that already has one will clear stale events, but not on + * macOS.) + * + * If there was no previous timer set, the kevent calls will result in + * ENOENT, which is fine. + */ + EV_SET(&ev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, 0); + if (kevent(actx->timerfd, &ev, 1, NULL, 0, NULL) < 0 && errno != ENOENT) + { + actx_error(actx, "deleting kqueue timer: %m"); + return false; + } + + EV_SET(&ev, actx->timerfd, EVFILT_READ, EV_DELETE, 0, 0, 0); + if (kevent(actx->mux, &ev, 1, NULL, 0, NULL) < 0 && errno != ENOENT) + { + actx_error(actx, "removing kqueue timer from multiplexer: %m"); + return false; + } + + /* If we're not adding a timer, we're done. */ + if (timeout < 0) + return true; + + EV_SET(&ev, 1, EVFILT_TIMER, (EV_ADD | EV_ONESHOT), 0, timeout, 0); + if (kevent(actx->timerfd, &ev, 1, NULL, 0, NULL) < 0) + { + actx_error(actx, "setting kqueue timer to %ld: %m", timeout); + return false; + } + + EV_SET(&ev, actx->timerfd, EVFILT_READ, EV_ADD, 0, 0, 0); + if (kevent(actx->mux, &ev, 1, NULL, 0, NULL) < 0) + { + actx_error(actx, "adding kqueue timer to multiplexer: %m"); + return false; + } + + return true; +#else +#error set_timer is not implemented on this platform +#endif +} + +/* + * Returns 1 if the timeout in the multiplexer set has expired since the last + * call to set_timer(), 0 if the timer is still running, or -1 (with an + * actx_error() report) if the timer cannot be queried. + */ +static int +timer_expired(struct async_ctx *actx) +{ +#if defined(HAVE_SYS_EPOLL_H) + struct itimerspec spec = {0}; + + if (timerfd_gettime(actx->timerfd, &spec) < 0) + { + actx_error(actx, "getting timerfd value: %m"); + return -1; + } + + /* + * This implementation assumes we're using single-shot timers. If you + * change to using intervals, you'll need to reimplement this function + * too, possibly with the read() or select() interfaces for timerfd. + */ + Assert(spec.it_interval.tv_sec == 0 + && spec.it_interval.tv_nsec == 0); + + /* If the remaining time to expiration is zero, we're done. */ + return (spec.it_value.tv_sec == 0 + && spec.it_value.tv_nsec == 0); +#elif defined(HAVE_SYS_EVENT_H) + int res; + + /* Is the timer queue ready? */ + res = PQsocketPoll(actx->timerfd, 1 /* forRead */ , 0, 0); + if (res < 0) + { + actx_error(actx, "checking kqueue for timeout: %m"); + return -1; + } + + return (res > 0); +#else +#error timer_expired is not implemented on this platform +#endif +} + +/* + * Adds or removes timeouts from the multiplexer set, as directed by the + * libcurl multi handle. + */ +static int +register_timer(CURLM *curlm, long timeout, void *ctx) +{ + struct async_ctx *actx = ctx; + + /* + * There might be an optimization opportunity here: if timeout == 0, we + * could signal drive_request to immediately call + * curl_multi_socket_action, rather than returning all the way up the + * stack only to come right back. But it's not clear that the additional + * code complexity is worth it. + */ + if (!set_timer(actx, timeout)) + return -1; /* actx_error already called */ + + return 0; +} + +/* + * Prints Curl request debugging information to stderr. + * + * Note that this will expose a number of critical secrets, so users have to opt + * into this (see PGOAUTHDEBUG). + */ +static int +debug_callback(CURL *handle, curl_infotype type, char *data, size_t size, + void *clientp) +{ + const char *prefix; + bool printed_prefix = false; + PQExpBufferData buf; + + /* Prefixes are modeled off of the default libcurl debug output. */ + switch (type) + { + case CURLINFO_TEXT: + prefix = "*"; + break; + + case CURLINFO_HEADER_IN: /* fall through */ + case CURLINFO_DATA_IN: + prefix = "<"; + break; + + case CURLINFO_HEADER_OUT: /* fall through */ + case CURLINFO_DATA_OUT: + prefix = ">"; + break; + + default: + return 0; + } + + initPQExpBuffer(&buf); + + /* + * Split the output into lines for readability; sometimes multiple headers + * are included in a single call. We also don't allow unprintable ASCII + * through without a basic escape. + */ + for (int i = 0; i < size; i++) + { + char c = data[i]; + + if (!printed_prefix) + { + appendPQExpBuffer(&buf, "[libcurl] %s ", prefix); + printed_prefix = true; + } + + if (c >= 0x20 && c <= 0x7E) + appendPQExpBufferChar(&buf, c); + else if ((type == CURLINFO_HEADER_IN + || type == CURLINFO_HEADER_OUT + || type == CURLINFO_TEXT) + && (c == '\r' || c == '\n')) + { + /* + * Don't bother emitting <0D><0A> for headers and text; it's not + * helpful noise. + */ + } + else + appendPQExpBuffer(&buf, "<%02X>", c); + + if (c == '\n') + { + appendPQExpBufferChar(&buf, c); + printed_prefix = false; + } + } + + if (printed_prefix) + appendPQExpBufferChar(&buf, '\n'); /* finish the line */ + + fprintf(stderr, "%s", buf.data); + termPQExpBuffer(&buf); + return 0; +} + +/* + * Initializes the two libcurl handles in the async_ctx. The multi handle, + * actx->curlm, is what drives the asynchronous engine and tells us what to do + * next. The easy handle, actx->curl, encapsulates the state for a single + * request/response. It's added to the multi handle as needed, during + * start_request(). + */ +static bool +setup_curl_handles(struct async_ctx *actx) +{ + /* + * Create our multi handle. This encapsulates the entire conversation with + * libcurl for this connection. + */ + actx->curlm = curl_multi_init(); + if (!actx->curlm) + { + /* We don't get a lot of feedback on the failure reason. */ + actx_error(actx, "failed to create libcurl multi handle"); + return false; + } + + /* + * The multi handle tells us what to wait on using two callbacks. These + * will manipulate actx->mux as needed. + */ + CHECK_MSETOPT(actx, CURLMOPT_SOCKETFUNCTION, register_socket, return false); + CHECK_MSETOPT(actx, CURLMOPT_SOCKETDATA, actx, return false); + CHECK_MSETOPT(actx, CURLMOPT_TIMERFUNCTION, register_timer, return false); + CHECK_MSETOPT(actx, CURLMOPT_TIMERDATA, actx, return false); + + /* + * Set up an easy handle. All of our requests are made serially, so we + * only ever need to keep track of one. + */ + actx->curl = curl_easy_init(); + if (!actx->curl) + { + actx_error(actx, "failed to create libcurl handle"); + return false; + } + + /* + * Multi-threaded applications must set CURLOPT_NOSIGNAL. This requires us + * to handle the possibility of SIGPIPE ourselves using pq_block_sigpipe; + * see pg_fe_run_oauth_flow(). + * + * NB: If libcurl is not built against a friendly DNS resolver (c-ares or + * threaded), setting this option prevents DNS lookups from timing out + * correctly. We warn about this situation at configure time. + * + * TODO: Perhaps there's a clever way to warn the user about synchronous + * DNS at runtime too? It's not immediately clear how to do that in a + * helpful way: for many standard single-threaded use cases, the user + * might not care at all, so spraying warnings to stderr would probably do + * more harm than good. + */ + CHECK_SETOPT(actx, CURLOPT_NOSIGNAL, 1L, return false); + + if (actx->debugging) + { + /* + * Set a callback for retrieving error information from libcurl, the + * function only takes effect when CURLOPT_VERBOSE has been set so + * make sure the order is kept. + */ + CHECK_SETOPT(actx, CURLOPT_DEBUGFUNCTION, debug_callback, return false); + CHECK_SETOPT(actx, CURLOPT_VERBOSE, 1L, return false); + } + + CHECK_SETOPT(actx, CURLOPT_ERRORBUFFER, actx->curl_err, return false); + + /* + * Only HTTPS is allowed. (Debug mode additionally allows HTTP; this is + * intended for testing only.) + * + * There's a bit of unfortunate complexity around the choice of + * CURLoption. CURLOPT_PROTOCOLS is deprecated in modern Curls, but its + * replacement didn't show up until relatively recently. + */ + { +#if CURL_AT_LEAST_VERSION(7, 85, 0) + const CURLoption popt = CURLOPT_PROTOCOLS_STR; + const char *protos = "https"; + const char *const unsafe = "https,http"; +#else + const CURLoption popt = CURLOPT_PROTOCOLS; + long protos = CURLPROTO_HTTPS; + const long unsafe = CURLPROTO_HTTPS | CURLPROTO_HTTP; +#endif + + if (actx->debugging) + protos = unsafe; + + CHECK_SETOPT(actx, popt, protos, return false); + } + + /* + * If we're in debug mode, allow the developer to change the trusted CA + * list. For now, this is not something we expose outside of the UNSAFE + * mode, because it's not clear that it's useful in production: both libpq + * and the user's browser must trust the same authorization servers for + * the flow to work at all, so any changes to the roots are likely to be + * done system-wide. + */ + if (actx->debugging) + { + const char *env; + + if ((env = getenv("PGOAUTHCAFILE")) != NULL) + CHECK_SETOPT(actx, CURLOPT_CAINFO, env, return false); + } + + /* + * Suppress the Accept header to make our request as minimal as possible. + * (Ideally we would set it to "application/json" instead, but OpenID is + * pretty strict when it comes to provider behavior, so we have to check + * what comes back anyway.) + */ + actx->headers = curl_slist_append(actx->headers, "Accept:"); + if (actx->headers == NULL) + { + actx_error(actx, "out of memory"); + return false; + } + CHECK_SETOPT(actx, CURLOPT_HTTPHEADER, actx->headers, return false); + + return true; +} + +/* + * Generic HTTP Request Handlers + */ + +/* + * Response callback from libcurl which appends the response body into + * actx->work_data (see start_request()). The maximum size of the data is + * defined by CURL_MAX_WRITE_SIZE which by default is 16kb (and can only be + * changed by recompiling libcurl). + */ +static size_t +append_data(char *buf, size_t size, size_t nmemb, void *userdata) +{ + struct async_ctx *actx = userdata; + PQExpBuffer resp = &actx->work_data; + size_t len = size * nmemb; + + /* In case we receive data over the threshold, abort the transfer */ + if ((resp->len + len) > MAX_OAUTH_RESPONSE_SIZE) + { + actx_error(actx, "response is too large"); + return 0; + } + + /* The data passed from libcurl is not null-terminated */ + appendBinaryPQExpBuffer(resp, buf, len); + + /* + * Signal an error in order to abort the transfer in case we ran out of + * memory in accepting the data. + */ + if (PQExpBufferBroken(resp)) + { + actx_error(actx, "out of memory"); + return 0; + } + + return len; +} + +/* + * Begins an HTTP request on the multi handle. The caller should have set up all + * request-specific options on actx->curl first. The server's response body will + * be accumulated in actx->work_data (which will be reset, so don't store + * anything important there across this call). + * + * Once a request is queued, it can be driven to completion via drive_request(). + * If actx->running is zero upon return, the request has already finished and + * drive_request() can be called without returning control to the client. + */ +static bool +start_request(struct async_ctx *actx) +{ + CURLMcode err; + + resetPQExpBuffer(&actx->work_data); + CHECK_SETOPT(actx, CURLOPT_WRITEFUNCTION, append_data, return false); + CHECK_SETOPT(actx, CURLOPT_WRITEDATA, actx, return false); + + err = curl_multi_add_handle(actx->curlm, actx->curl); + if (err) + { + actx_error(actx, "failed to queue HTTP request: %s", + curl_multi_strerror(err)); + return false; + } + + /* + * actx->running tracks the number of running handles, so we can + * immediately call back if no waiting is needed. + * + * Even though this is nominally an asynchronous process, there are some + * operations that can synchronously fail by this point (e.g. connections + * to closed local ports) or even synchronously succeed if the stars align + * (all the libcurl connection caches hit and the server is fast). + */ + err = curl_multi_socket_action(actx->curlm, CURL_SOCKET_TIMEOUT, 0, &actx->running); + if (err) + { + actx_error(actx, "asynchronous HTTP request failed: %s", + curl_multi_strerror(err)); + return false; + } + + return true; +} + +/* + * CURL_IGNORE_DEPRECATION was added in 7.87.0. If it's not defined, we can make + * it a no-op. + */ +#ifndef CURL_IGNORE_DEPRECATION +#define CURL_IGNORE_DEPRECATION(x) x +#endif + +/* + * Drives the multi handle towards completion. The caller should have already + * set up an asynchronous request via start_request(). + */ +static PostgresPollingStatusType +drive_request(struct async_ctx *actx) +{ + CURLMcode err; + CURLMsg *msg; + int msgs_left; + bool done; + + if (actx->running) + { + /*--- + * There's an async request in progress. Pump the multi handle. + * + * curl_multi_socket_all() is officially deprecated, because it's + * inefficient and pointless if your event loop has already handed you + * the exact sockets that are ready. But that's not our use case -- + * our client has no way to tell us which sockets are ready. (They + * don't even know there are sockets to begin with.) + * + * We can grab the list of triggered events from the multiplexer + * ourselves, but that's effectively what curl_multi_socket_all() is + * going to do. And there are currently no plans for the Curl project + * to remove or break this API, so ignore the deprecation. See + * + * https://curl.se/mail/lib-2024-11/0028.html + * + */ + CURL_IGNORE_DEPRECATION( + err = curl_multi_socket_all(actx->curlm, &actx->running); + ) + + if (err) + { + actx_error(actx, "asynchronous HTTP request failed: %s", + curl_multi_strerror(err)); + return PGRES_POLLING_FAILED; + } + + if (actx->running) + { + /* We'll come back again. */ + return PGRES_POLLING_READING; + } + } + + done = false; + while ((msg = curl_multi_info_read(actx->curlm, &msgs_left)) != NULL) + { + if (msg->msg != CURLMSG_DONE) + { + /* + * Future libcurl versions may define new message types; we don't + * know how to handle them, so we'll ignore them. + */ + continue; + } + + /* First check the status of the request itself. */ + if (msg->data.result != CURLE_OK) + { + /* + * If a more specific error hasn't already been reported, use + * libcurl's description. + */ + if (actx->errbuf.len == 0) + actx_error_str(actx, curl_easy_strerror(msg->data.result)); + + return PGRES_POLLING_FAILED; + } + + /* Now remove the finished handle; we'll add it back later if needed. */ + err = curl_multi_remove_handle(actx->curlm, msg->easy_handle); + if (err) + { + actx_error(actx, "libcurl easy handle removal failed: %s", + curl_multi_strerror(err)); + return PGRES_POLLING_FAILED; + } + + done = true; + } + + /* Sanity check. */ + if (!done) + { + actx_error(actx, "no result was retrieved for the finished handle"); + return PGRES_POLLING_FAILED; + } + + return PGRES_POLLING_OK; +} + +/* + * URL-Encoding Helpers + */ + +/* + * Encodes a string using the application/x-www-form-urlencoded format, and + * appends it to the given buffer. + */ +static void +append_urlencoded(PQExpBuffer buf, const char *s) +{ + char *escaped; + char *haystack; + char *match; + + /* The first parameter to curl_easy_escape is deprecated by Curl */ + escaped = curl_easy_escape(NULL, s, 0); + if (!escaped) + { + termPQExpBuffer(buf); /* mark the buffer broken */ + return; + } + + /* + * curl_easy_escape() almost does what we want, but we need the + * query-specific flavor which uses '+' instead of '%20' for spaces. The + * Curl command-line tool does this with a simple search-and-replace, so + * follow its lead. + */ + haystack = escaped; + + while ((match = strstr(haystack, "%20")) != NULL) + { + /* Append the unmatched portion, followed by the plus sign. */ + appendBinaryPQExpBuffer(buf, haystack, match - haystack); + appendPQExpBufferChar(buf, '+'); + + /* Keep searching after the match. */ + haystack = match + 3 /* strlen("%20") */ ; + } + + /* Push the remainder of the string onto the buffer. */ + appendPQExpBufferStr(buf, haystack); + + curl_free(escaped); +} + +/* + * Convenience wrapper for encoding a single string. Returns NULL on allocation + * failure. + */ +static char * +urlencode(const char *s) +{ + PQExpBufferData buf; + + initPQExpBuffer(&buf); + append_urlencoded(&buf, s); + + return PQExpBufferDataBroken(buf) ? NULL : buf.data; +} + +/* + * Appends a key/value pair to the end of an application/x-www-form-urlencoded + * list. + */ +static void +build_urlencoded(PQExpBuffer buf, const char *key, const char *value) +{ + if (buf->len) + appendPQExpBufferChar(buf, '&'); + + append_urlencoded(buf, key); + appendPQExpBufferChar(buf, '='); + append_urlencoded(buf, value); +} + +/* + * Specific HTTP Request Handlers + * + * This is finally the beginning of the actual application logic. Generally + * speaking, a single request consists of a start_* and a finish_* step, with + * drive_request() pumping the machine in between. + */ + +/* + * Queue an OpenID Provider Configuration Request: + * + * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest + * https://www.rfc-editor.org/rfc/rfc8414#section-3.1 + * + * This is done first to get the endpoint URIs we need to contact and to make + * sure the provider provides a device authorization flow. finish_discovery() + * will fill in actx->provider. + */ +static bool +start_discovery(struct async_ctx *actx, const char *discovery_uri) +{ + CHECK_SETOPT(actx, CURLOPT_HTTPGET, 1L, return false); + CHECK_SETOPT(actx, CURLOPT_URL, discovery_uri, return false); + + return start_request(actx); +} + +static bool +finish_discovery(struct async_ctx *actx) +{ + long response_code; + + /*---- + * Now check the response. OIDC Discovery 1.0 is pretty strict: + * + * A successful response MUST use the 200 OK HTTP status code and + * return a JSON object using the application/json content type that + * contains a set of Claims as its members that are a subset of the + * Metadata values defined in Section 3. + * + * Compared to standard HTTP semantics, this makes life easy -- we don't + * need to worry about redirections (which would call the Issuer host + * validation into question), or non-authoritative responses, or any other + * complications. + */ + CHECK_GETINFO(actx, CURLINFO_RESPONSE_CODE, &response_code, return false); + + if (response_code != 200) + { + actx_error(actx, "unexpected response code %ld", response_code); + return false; + } + + /* + * Pull the fields we care about from the document. + */ + actx->errctx = "failed to parse OpenID discovery document"; + if (!parse_provider(actx, &actx->provider)) + return false; /* error message already set */ + + /* + * Fill in any defaults for OPTIONAL/RECOMMENDED fields we care about. + */ + if (!actx->provider.grant_types_supported) + { + /* + * Per Section 3, the default is ["authorization_code", "implicit"]. + */ + struct curl_slist *temp = actx->provider.grant_types_supported; + + temp = curl_slist_append(temp, "authorization_code"); + if (temp) + { + temp = curl_slist_append(temp, "implicit"); + } + + if (!temp) + { + actx_error(actx, "out of memory"); + return false; + } + + actx->provider.grant_types_supported = temp; + } + + return true; +} + +/* + * Ensure that the discovery document is provided by the expected issuer. + * Currently, issuers are statically configured in the connection string. + */ +static bool +check_issuer(struct async_ctx *actx, PGconn *conn) +{ + const struct provider *provider = &actx->provider; + const char *oauth_issuer_id = conn_oauth_issuer_id(conn); + + Assert(oauth_issuer_id); /* ensured by setup_oauth_parameters() */ + Assert(provider->issuer); /* ensured by parse_provider() */ + + /*--- + * We require strict equality for issuer identifiers -- no path or case + * normalization, no substitution of default ports and schemes, etc. This + * is done to match the rules in OIDC Discovery Sec. 4.3 for config + * validation: + * + * The issuer value returned MUST be identical to the Issuer URL that + * was used as the prefix to /.well-known/openid-configuration to + * retrieve the configuration information. + * + * as well as the rules set out in RFC 9207 for avoiding mix-up attacks: + * + * Clients MUST then [...] compare the result to the issuer identifier + * of the authorization server where the authorization request was + * sent to. This comparison MUST use simple string comparison as defined + * in Section 6.2.1 of [RFC3986]. + */ + if (strcmp(oauth_issuer_id, provider->issuer) != 0) + { + actx_error(actx, + "the issuer identifier (%s) does not match oauth_issuer (%s)", + provider->issuer, oauth_issuer_id); + return false; + } + + return true; +} + +#define HTTPS_SCHEME "https://" +#define OAUTH_GRANT_TYPE_DEVICE_CODE "urn:ietf:params:oauth:grant-type:device_code" + +/* + * Ensure that the provider supports the Device Authorization flow (i.e. it + * provides an authorization endpoint, and both the token and authorization + * endpoint URLs seem reasonable). + */ +static bool +check_for_device_flow(struct async_ctx *actx) +{ + const struct provider *provider = &actx->provider; + + Assert(provider->issuer); /* ensured by parse_provider() */ + Assert(provider->token_endpoint); /* ensured by parse_provider() */ + + if (!provider->device_authorization_endpoint) + { + actx_error(actx, + "issuer \"%s\" does not provide a device authorization endpoint", + provider->issuer); + return false; + } + + /* + * The original implementation checked that OAUTH_GRANT_TYPE_DEVICE_CODE + * was present in the discovery document's grant_types_supported list. MS + * Entra does not advertise this grant type, though, and since it doesn't + * make sense to stand up a device_authorization_endpoint without also + * accepting device codes at the token_endpoint, that's the only thing we + * currently require. + */ + + /* + * Although libcurl will fail later if the URL contains an unsupported + * scheme, that error message is going to be a bit opaque. This is a + * decent time to bail out if we're not using HTTPS for the endpoints + * we'll use for the flow. + */ + if (!actx->debugging) + { + if (pg_strncasecmp(provider->device_authorization_endpoint, + HTTPS_SCHEME, strlen(HTTPS_SCHEME)) != 0) + { + actx_error(actx, + "device authorization endpoint \"%s\" must use HTTPS", + provider->device_authorization_endpoint); + return false; + } + + if (pg_strncasecmp(provider->token_endpoint, + HTTPS_SCHEME, strlen(HTTPS_SCHEME)) != 0) + { + actx_error(actx, + "token endpoint \"%s\" must use HTTPS", + provider->token_endpoint); + return false; + } + } + + return true; +} + +/* + * Adds the client ID (and secret, if provided) to the current request, using + * either HTTP headers or the request body. + */ +static bool +add_client_identification(struct async_ctx *actx, PQExpBuffer reqbody, PGconn *conn) +{ + const char *oauth_client_id = conn_oauth_client_id(conn); + const char *oauth_client_secret = conn_oauth_client_secret(conn); + + bool success = false; + char *username = NULL; + char *password = NULL; + + if (oauth_client_secret) /* Zero-length secrets are permitted! */ + { + /*---- + * Use HTTP Basic auth to send the client_id and secret. Per RFC 6749, + * Sec. 2.3.1, + * + * Including the client credentials in the request-body using the + * two parameters is NOT RECOMMENDED and SHOULD be limited to + * clients unable to directly utilize the HTTP Basic authentication + * scheme (or other password-based HTTP authentication schemes). + * + * Additionally: + * + * The client identifier is encoded using the + * "application/x-www-form-urlencoded" encoding algorithm per Appendix + * B, and the encoded value is used as the username; the client + * password is encoded using the same algorithm and used as the + * password. + * + * (Appendix B modifies application/x-www-form-urlencoded by requiring + * an initial UTF-8 encoding step. Since the client ID and secret must + * both be 7-bit ASCII -- RFC 6749 Appendix A -- we don't worry about + * that in this function.) + * + * client_id is not added to the request body in this case. Not only + * would it be redundant, but some providers in the wild (e.g. Okta) + * refuse to accept it. + */ + username = urlencode(oauth_client_id); + password = urlencode(oauth_client_secret); + + if (!username || !password) + { + actx_error(actx, "out of memory"); + goto cleanup; + } + + CHECK_SETOPT(actx, CURLOPT_HTTPAUTH, CURLAUTH_BASIC, goto cleanup); + CHECK_SETOPT(actx, CURLOPT_USERNAME, username, goto cleanup); + CHECK_SETOPT(actx, CURLOPT_PASSWORD, password, goto cleanup); + + actx->used_basic_auth = true; + } + else + { + /* + * If we're not otherwise authenticating, client_id is REQUIRED in the + * request body. + */ + build_urlencoded(reqbody, "client_id", oauth_client_id); + + CHECK_SETOPT(actx, CURLOPT_HTTPAUTH, CURLAUTH_NONE, goto cleanup); + actx->used_basic_auth = false; + } + + success = true; + +cleanup: + free(username); + free(password); + + return success; +} + +/* + * Queue a Device Authorization Request: + * + * https://www.rfc-editor.org/rfc/rfc8628#section-3.1 + * + * This is the second step. We ask the provider to verify the end user out of + * band and authorize us to act on their behalf; it will give us the required + * nonces for us to later poll the request status, which we'll grab in + * finish_device_authz(). + */ +static bool +start_device_authz(struct async_ctx *actx, PGconn *conn) +{ + const char *oauth_scope = conn_oauth_scope(conn); + const char *device_authz_uri = actx->provider.device_authorization_endpoint; + PQExpBuffer work_buffer = &actx->work_data; + + Assert(conn_oauth_client_id(conn)); /* ensured by setup_oauth_parameters() */ + Assert(device_authz_uri); /* ensured by check_for_device_flow() */ + + /* Construct our request body. */ + resetPQExpBuffer(work_buffer); + if (oauth_scope && oauth_scope[0]) + build_urlencoded(work_buffer, "scope", oauth_scope); + + if (!add_client_identification(actx, work_buffer, conn)) + return false; + + if (PQExpBufferBroken(work_buffer)) + { + actx_error(actx, "out of memory"); + return false; + } + + /* Make our request. */ + CHECK_SETOPT(actx, CURLOPT_URL, device_authz_uri, return false); + CHECK_SETOPT(actx, CURLOPT_COPYPOSTFIELDS, work_buffer->data, return false); + + return start_request(actx); +} + +static bool +finish_device_authz(struct async_ctx *actx) +{ + long response_code; + + CHECK_GETINFO(actx, CURLINFO_RESPONSE_CODE, &response_code, return false); + + /* + * Per RFC 8628, Section 3, a successful device authorization response + * uses 200 OK. + */ + if (response_code == 200) + { + actx->errctx = "failed to parse device authorization"; + if (!parse_device_authz(actx, &actx->authz)) + return false; /* error message already set */ + + return true; + } + + /* + * The device authorization endpoint uses the same error response as the + * token endpoint, so the error handling roughly follows + * finish_token_request(). The key difference is that an error here is + * immediately fatal. + */ + if (response_code == 400 || response_code == 401) + { + struct token_error err = {0}; + + if (!parse_token_error(actx, &err)) + { + free_token_error(&err); + return false; + } + + /* Copy the token error into the context error buffer */ + record_token_error(actx, &err); + + free_token_error(&err); + return false; + } + + /* Any other response codes are considered invalid */ + actx_error(actx, "unexpected response code %ld", response_code); + return false; +} + +/* + * Queue an Access Token Request: + * + * https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 + * + * This is the final step. We continually poll the token endpoint to see if the + * user has authorized us yet. finish_token_request() will pull either the token + * or a (ideally temporary) error status from the provider. + */ +static bool +start_token_request(struct async_ctx *actx, PGconn *conn) +{ + const char *token_uri = actx->provider.token_endpoint; + const char *device_code = actx->authz.device_code; + PQExpBuffer work_buffer = &actx->work_data; + + Assert(conn_oauth_client_id(conn)); /* ensured by setup_oauth_parameters() */ + Assert(token_uri); /* ensured by parse_provider() */ + Assert(device_code); /* ensured by parse_device_authz() */ + + /* Construct our request body. */ + resetPQExpBuffer(work_buffer); + build_urlencoded(work_buffer, "device_code", device_code); + build_urlencoded(work_buffer, "grant_type", OAUTH_GRANT_TYPE_DEVICE_CODE); + + if (!add_client_identification(actx, work_buffer, conn)) + return false; + + if (PQExpBufferBroken(work_buffer)) + { + actx_error(actx, "out of memory"); + return false; + } + + /* Make our request. */ + CHECK_SETOPT(actx, CURLOPT_URL, token_uri, return false); + CHECK_SETOPT(actx, CURLOPT_COPYPOSTFIELDS, work_buffer->data, return false); + + return start_request(actx); +} + +static bool +finish_token_request(struct async_ctx *actx, struct token *tok) +{ + long response_code; + + CHECK_GETINFO(actx, CURLINFO_RESPONSE_CODE, &response_code, return false); + + /* + * Per RFC 6749, Section 5, a successful response uses 200 OK. + */ + if (response_code == 200) + { + actx->errctx = "failed to parse access token response"; + if (!parse_access_token(actx, tok)) + return false; /* error message already set */ + + return true; + } + + /* + * An error response uses either 400 Bad Request or 401 Unauthorized. + * There are references online to implementations using 403 for error + * return which would violate the specification. For now we stick to the + * specification but we might have to revisit this. + */ + if (response_code == 400 || response_code == 401) + { + if (!parse_token_error(actx, &tok->err)) + return false; + + return true; + } + + /* Any other response codes are considered invalid */ + actx_error(actx, "unexpected response code %ld", response_code); + return false; +} + +/* + * Finishes the token request and examines the response. If the flow has + * completed, a valid token will be returned via the parameter list. Otherwise, + * the token parameter remains unchanged, and the caller needs to wait for + * another interval (which will have been increased in response to a slow_down + * message from the server) before starting a new token request. + * + * False is returned only for permanent error conditions. + */ +static bool +handle_token_response(struct async_ctx *actx, char **token) +{ + bool success = false; + struct token tok = {0}; + const struct token_error *err; + + if (!finish_token_request(actx, &tok)) + goto token_cleanup; + + /* A successful token request gives either a token or an in-band error. */ + Assert(tok.access_token || tok.err.error); + + if (tok.access_token) + { + *token = tok.access_token; + tok.access_token = NULL; + + success = true; + goto token_cleanup; + } + + /* + * authorization_pending and slow_down are the only acceptable errors; + * anything else and we bail. These are defined in RFC 8628, Sec. 3.5. + */ + err = &tok.err; + if (strcmp(err->error, "authorization_pending") != 0 && + strcmp(err->error, "slow_down") != 0) + { + record_token_error(actx, err); + goto token_cleanup; + } + + /* + * A slow_down error requires us to permanently increase our retry + * interval by five seconds. + */ + if (strcmp(err->error, "slow_down") == 0) + { + int prev_interval = actx->authz.interval; + + actx->authz.interval += 5; + if (actx->authz.interval < prev_interval) + { + actx_error(actx, "slow_down interval overflow"); + goto token_cleanup; + } + } + + success = true; + +token_cleanup: + free_token(&tok); + return success; +} + +/* + * Displays a device authorization prompt for action by the end user, either via + * the PQauthDataHook, or by a message on standard error if no hook is set. + */ +static bool +prompt_user(struct async_ctx *actx, PGconn *conn) +{ + int res; + PGpromptOAuthDevice prompt = { + .verification_uri = actx->authz.verification_uri, + .user_code = actx->authz.user_code, + .verification_uri_complete = actx->authz.verification_uri_complete, + .expires_in = actx->authz.expires_in, + }; + PQauthDataHook_type hook = PQgetAuthDataHook(); + + res = hook(PQAUTHDATA_PROMPT_OAUTH_DEVICE, conn, &prompt); + + if (!res) + { + /* + * translator: The first %s is a URL for the user to visit in a + * browser, and the second %s is a code to be copy-pasted there. + */ + fprintf(stderr, libpq_gettext("Visit %s and enter the code: %s\n"), + prompt.verification_uri, prompt.user_code); + } + else if (res < 0) + { + actx_error(actx, "device prompt failed"); + return false; + } + + return true; +} + +/* + * Calls curl_global_init() in a thread-safe way. + * + * libcurl has stringent requirements for the thread context in which you call + * curl_global_init(), because it's going to try initializing a bunch of other + * libraries (OpenSSL, Winsock, etc). Recent versions of libcurl have improved + * the thread-safety situation, but there's a chicken-and-egg problem at + * runtime: you can't check the thread safety until you've initialized libcurl, + * which you can't do from within a thread unless you know it's thread-safe... + * + * Returns true if initialization was successful. Successful or not, this + * function will not try to reinitialize Curl on successive calls. + */ +static bool +initialize_curl(PGconn *conn) +{ + /* + * Don't let the compiler play tricks with this variable. In the + * HAVE_THREADSAFE_CURL_GLOBAL_INIT case, we don't care if two threads + * enter simultaneously, but we do care if this gets set transiently to + * PG_BOOL_YES/NO in cases where that's not the final answer. + */ + static volatile PGTernaryBool init_successful = PG_BOOL_UNKNOWN; +#if HAVE_THREADSAFE_CURL_GLOBAL_INIT + curl_version_info_data *info; +#endif + +#if !HAVE_THREADSAFE_CURL_GLOBAL_INIT + + /* + * Lock around the whole function. If a libpq client performs its own work + * with libcurl, it must either ensure that Curl is initialized safely + * before calling us (in which case our call will be a no-op), or else it + * must guard its own calls to curl_global_init() with a registered + * threadlock handler. See PQregisterThreadLock(). + */ + pglock_thread(); +#endif + + /* + * Skip initialization if we've already done it. (Curl tracks the number + * of calls; there's no point in incrementing the counter every time we + * connect.) + */ + if (init_successful == PG_BOOL_YES) + goto done; + else if (init_successful == PG_BOOL_NO) + { + libpq_append_conn_error(conn, + "curl_global_init previously failed during OAuth setup"); + goto done; + } + + /* + * We know we've already initialized Winsock by this point (see + * pqMakeEmptyPGconn()), so we should be able to safely skip that bit. But + * we have to tell libcurl to initialize everything else, because other + * pieces of our client executable may already be using libcurl for their + * own purposes. If we initialize libcurl with only a subset of its + * features, we could break those other clients nondeterministically, and + * that would probably be a nightmare to debug. + * + * If some other part of the program has already called this, it's a + * no-op. + */ + if (curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_WIN32) != CURLE_OK) + { + libpq_append_conn_error(conn, + "curl_global_init failed during OAuth setup"); + init_successful = PG_BOOL_NO; + goto done; + } + +#if HAVE_THREADSAFE_CURL_GLOBAL_INIT + + /* + * If we determined at configure time that the Curl installation is + * thread-safe, our job here is much easier. We simply initialize above + * without any locking (concurrent or duplicated calls are fine in that + * situation), then double-check to make sure the runtime setting agrees, + * to try to catch silent downgrades. + */ + info = curl_version_info(CURLVERSION_NOW); + if (!(info->features & CURL_VERSION_THREADSAFE)) + { + /* + * In a downgrade situation, the damage is already done. Curl global + * state may be corrupted. Be noisy. + */ + libpq_append_conn_error(conn, "libcurl is no longer thread-safe\n" + "\tCurl initialization was reported thread-safe when libpq\n" + "\twas compiled, but the currently installed version of\n" + "\tlibcurl reports that it is not. Recompile libpq against\n" + "\tthe installed version of libcurl."); + init_successful = PG_BOOL_NO; + goto done; + } +#endif + + init_successful = PG_BOOL_YES; + +done: +#if !HAVE_THREADSAFE_CURL_GLOBAL_INIT + pgunlock_thread(); +#endif + return (init_successful == PG_BOOL_YES); +} + +/* + * The core nonblocking libcurl implementation. This will be called several + * times to pump the async engine. + * + * The architecture is based on PQconnectPoll(). The first half drives the + * connection state forward as necessary, returning if we're not ready to + * proceed to the next step yet. The second half performs the actual transition + * between states. + * + * You can trace the overall OAuth flow through the second half. It's linear + * until we get to the end, where we flip back and forth between + * OAUTH_STEP_TOKEN_REQUEST and OAUTH_STEP_WAIT_INTERVAL to regularly ping the + * provider. + */ +static PostgresPollingStatusType +pg_fe_run_oauth_flow_impl(PGconn *conn) +{ + fe_oauth_state *state = conn_sasl_state(conn); + struct async_ctx *actx; + char *oauth_token = NULL; + PQExpBuffer errbuf; + + if (!initialize_curl(conn)) + return PGRES_POLLING_FAILED; + + if (!state->async_ctx) + { + /* + * Create our asynchronous state, and hook it into the upper-level + * OAuth state immediately, so any failures below won't leak the + * context allocation. + */ + actx = calloc(1, sizeof(*actx)); + if (!actx) + { + libpq_append_conn_error(conn, "out of memory"); + return PGRES_POLLING_FAILED; + } + + actx->mux = PGINVALID_SOCKET; + actx->timerfd = -1; + + /* Should we enable unsafe features? */ + actx->debugging = oauth_unsafe_debugging_enabled(); + + state->async_ctx = actx; + + initPQExpBuffer(&actx->work_data); + initPQExpBuffer(&actx->errbuf); + + if (!setup_multiplexer(actx)) + goto error_return; + + if (!setup_curl_handles(actx)) + goto error_return; + } + + actx = state->async_ctx; + + do + { + /* By default, the multiplexer is the altsock. Reassign as desired. */ + set_conn_altsock(conn, actx->mux); + + switch (actx->step) + { + case OAUTH_STEP_INIT: + break; + + case OAUTH_STEP_DISCOVERY: + case OAUTH_STEP_DEVICE_AUTHORIZATION: + case OAUTH_STEP_TOKEN_REQUEST: + { + PostgresPollingStatusType status; + + status = drive_request(actx); + + if (status == PGRES_POLLING_FAILED) + goto error_return; + else if (status != PGRES_POLLING_OK) + { + /* not done yet */ + return status; + } + + break; + } + + case OAUTH_STEP_WAIT_INTERVAL: + + /* + * The client application is supposed to wait until our timer + * expires before calling PQconnectPoll() again, but that + * might not happen. To avoid sending a token request early, + * check the timer before continuing. + */ + if (!timer_expired(actx)) + { + set_conn_altsock(conn, actx->timerfd); + return PGRES_POLLING_READING; + } + + /* Disable the expired timer. */ + if (!set_timer(actx, -1)) + goto error_return; + + break; + } + + /* + * Each case here must ensure that actx->running is set while we're + * waiting on some asynchronous work. Most cases rely on + * start_request() to do that for them. + */ + switch (actx->step) + { + case OAUTH_STEP_INIT: + actx->errctx = "failed to fetch OpenID discovery document"; + if (!start_discovery(actx, conn_oauth_discovery_uri(conn))) + goto error_return; + + actx->step = OAUTH_STEP_DISCOVERY; + break; + + case OAUTH_STEP_DISCOVERY: + if (!finish_discovery(actx)) + goto error_return; + + if (!check_issuer(actx, conn)) + goto error_return; + + actx->errctx = "cannot run OAuth device authorization"; + if (!check_for_device_flow(actx)) + goto error_return; + + actx->errctx = "failed to obtain device authorization"; + if (!start_device_authz(actx, conn)) + goto error_return; + + actx->step = OAUTH_STEP_DEVICE_AUTHORIZATION; + break; + + case OAUTH_STEP_DEVICE_AUTHORIZATION: + if (!finish_device_authz(actx)) + goto error_return; + + actx->errctx = "failed to obtain access token"; + if (!start_token_request(actx, conn)) + goto error_return; + + actx->step = OAUTH_STEP_TOKEN_REQUEST; + break; + + case OAUTH_STEP_TOKEN_REQUEST: + if (!handle_token_response(actx, &oauth_token)) + goto error_return; + + /* + * Hook any oauth_token into the PGconn immediately so that + * the allocation isn't lost in case of an error. + */ + set_conn_oauth_token(conn, oauth_token); + + if (!actx->user_prompted) + { + /* + * Now that we know the token endpoint isn't broken, give + * the user the login instructions. + */ + if (!prompt_user(actx, conn)) + goto error_return; + + actx->user_prompted = true; + } + + if (oauth_token) + break; /* done! */ + + /* + * Wait for the required interval before issuing the next + * request. + */ + if (!set_timer(actx, actx->authz.interval * 1000)) + goto error_return; + + /* + * No Curl requests are running, so we can simplify by having + * the client wait directly on the timerfd rather than the + * multiplexer. + */ + set_conn_altsock(conn, actx->timerfd); + + actx->step = OAUTH_STEP_WAIT_INTERVAL; + actx->running = 1; + break; + + case OAUTH_STEP_WAIT_INTERVAL: + actx->errctx = "failed to obtain access token"; + if (!start_token_request(actx, conn)) + goto error_return; + + actx->step = OAUTH_STEP_TOKEN_REQUEST; + break; + } + + /* + * The vast majority of the time, if we don't have a token at this + * point, actx->running will be set. But there are some corner cases + * where we can immediately loop back around; see start_request(). + */ + } while (!oauth_token && !actx->running); + + /* If we've stored a token, we're done. Otherwise come back later. */ + return oauth_token ? PGRES_POLLING_OK : PGRES_POLLING_READING; + +error_return: + errbuf = conn_errorMessage(conn); + + /* + * Assemble the three parts of our error: context, body, and detail. See + * also the documentation for struct async_ctx. + */ + if (actx->errctx) + appendPQExpBuffer(errbuf, "%s: ", libpq_gettext(actx->errctx)); + + if (PQExpBufferDataBroken(actx->errbuf)) + appendPQExpBufferStr(errbuf, libpq_gettext("out of memory")); + else + appendPQExpBufferStr(errbuf, actx->errbuf.data); + + if (actx->curl_err[0]) + { + appendPQExpBuffer(errbuf, " (libcurl: %s)", actx->curl_err); + + /* Sometimes libcurl adds a newline to the error buffer. :( */ + if (errbuf->len >= 2 && errbuf->data[errbuf->len - 2] == '\n') + { + errbuf->data[errbuf->len - 2] = ')'; + errbuf->data[errbuf->len - 1] = '\0'; + errbuf->len--; + } + } + + appendPQExpBufferChar(errbuf, '\n'); + + return PGRES_POLLING_FAILED; +} + +/* + * The top-level entry point. This is a convenient place to put necessary + * wrapper logic before handing off to the true implementation, above. + */ +PostgresPollingStatusType +pg_fe_run_oauth_flow(PGconn *conn) +{ + PostgresPollingStatusType result; +#ifndef WIN32 + sigset_t osigset; + bool sigpipe_pending; + bool masked; + + /*--- + * Ignore SIGPIPE on this thread during all Curl processing. + * + * Because we support multiple threads, we have to set up libcurl with + * CURLOPT_NOSIGNAL, which disables its default global handling of + * SIGPIPE. From the Curl docs: + * + * libcurl makes an effort to never cause such SIGPIPE signals to + * trigger, but some operating systems have no way to avoid them and + * even on those that have there are some corner cases when they may + * still happen, contrary to our desire. + * + * Note that libcurl is also at the mercy of its DNS resolution and SSL + * libraries; if any of them forget a MSG_NOSIGNAL then we're in trouble. + * Modern platforms and libraries seem to get it right, so this is a + * difficult corner case to exercise in practice, and unfortunately it's + * not really clear whether it's necessary in all cases. + */ + masked = (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0); +#endif + + result = pg_fe_run_oauth_flow_impl(conn); + +#ifndef WIN32 + if (masked) + { + /* + * Undo the SIGPIPE mask. Assume we may have gotten EPIPE (we have no + * way of knowing at this level). + */ + pq_reset_sigpipe(&osigset, sigpipe_pending, true /* EPIPE, maybe */ ); + } +#endif + + return result; +} diff --git a/src/interfaces/libpq-oauth/oauth-curl.h b/src/interfaces/libpq-oauth/oauth-curl.h new file mode 100644 index 0000000000000..248d0424ad0d6 --- /dev/null +++ b/src/interfaces/libpq-oauth/oauth-curl.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * oauth-curl.h + * + * Definitions for OAuth Device Authorization module + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq-oauth/oauth-curl.h + * + *------------------------------------------------------------------------- + */ + +#ifndef OAUTH_CURL_H +#define OAUTH_CURL_H + +#include "libpq-fe.h" + +/* Exported async-auth callbacks. */ +extern PGDLLEXPORT PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn); +extern PGDLLEXPORT void pg_fe_cleanup_oauth_flow(PGconn *conn); + +#endif /* OAUTH_CURL_H */ diff --git a/src/interfaces/libpq-oauth/oauth-utils.c b/src/interfaces/libpq-oauth/oauth-utils.c new file mode 100644 index 0000000000000..45fdc7579f285 --- /dev/null +++ b/src/interfaces/libpq-oauth/oauth-utils.c @@ -0,0 +1,233 @@ +/*------------------------------------------------------------------------- + * + * oauth-utils.c + * + * "Glue" helpers providing a copy of some internal APIs from libpq. At + * some point in the future, we might be able to deduplicate. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq-oauth/oauth-utils.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include + +#include "oauth-utils.h" + +#ifndef USE_DYNAMIC_OAUTH +#error oauth-utils.c is not supported in static builds +#endif + +#ifdef LIBPQ_INT_H +#error do not rely on libpq-int.h in dynamic builds of libpq-oauth +#endif + +/* + * Function pointers set by libpq_oauth_init(). + */ + +pgthreadlock_t pg_g_threadlock; +static libpq_gettext_func libpq_gettext_impl; + +conn_errorMessage_func conn_errorMessage; +conn_oauth_client_id_func conn_oauth_client_id; +conn_oauth_client_secret_func conn_oauth_client_secret; +conn_oauth_discovery_uri_func conn_oauth_discovery_uri; +conn_oauth_issuer_id_func conn_oauth_issuer_id; +conn_oauth_scope_func conn_oauth_scope; +conn_sasl_state_func conn_sasl_state; + +set_conn_altsock_func set_conn_altsock; +set_conn_oauth_token_func set_conn_oauth_token; + +/*- + * Initializes libpq-oauth by setting necessary callbacks. + * + * The current implementation relies on the following private implementation + * details of libpq: + * + * - pg_g_threadlock: protects libcurl initialization if the underlying Curl + * installation is not threadsafe + * + * - libpq_gettext: translates error messages using libpq's message domain + * + * The implementation also needs access to several members of the PGconn struct, + * which are not guaranteed to stay in place across minor versions. Accessors + * (named conn_*) and mutators (named set_conn_*) are injected here. + */ +void +libpq_oauth_init(pgthreadlock_t threadlock_impl, + libpq_gettext_func gettext_impl, + conn_errorMessage_func errmsg_impl, + conn_oauth_client_id_func clientid_impl, + conn_oauth_client_secret_func clientsecret_impl, + conn_oauth_discovery_uri_func discoveryuri_impl, + conn_oauth_issuer_id_func issuerid_impl, + conn_oauth_scope_func scope_impl, + conn_sasl_state_func saslstate_impl, + set_conn_altsock_func setaltsock_impl, + set_conn_oauth_token_func settoken_impl) +{ + pg_g_threadlock = threadlock_impl; + libpq_gettext_impl = gettext_impl; + conn_errorMessage = errmsg_impl; + conn_oauth_client_id = clientid_impl; + conn_oauth_client_secret = clientsecret_impl; + conn_oauth_discovery_uri = discoveryuri_impl; + conn_oauth_issuer_id = issuerid_impl; + conn_oauth_scope = scope_impl; + conn_sasl_state = saslstate_impl; + set_conn_altsock = setaltsock_impl; + set_conn_oauth_token = settoken_impl; +} + +/* + * Append a formatted string to the error message buffer of the given + * connection, after translating it. This is a copy of libpq's internal API. + */ +void +libpq_append_conn_error(PGconn *conn, const char *fmt,...) +{ + int save_errno = errno; + bool done; + va_list args; + PQExpBuffer errorMessage = conn_errorMessage(conn); + + Assert(fmt[strlen(fmt) - 1] != '\n'); + + if (PQExpBufferBroken(errorMessage)) + return; /* already failed */ + + /* Loop in case we have to retry after enlarging the buffer. */ + do + { + errno = save_errno; + va_start(args, fmt); + done = appendPQExpBufferVA(errorMessage, libpq_gettext(fmt), args); + va_end(args); + } while (!done); + + appendPQExpBufferChar(errorMessage, '\n'); +} + +#ifdef ENABLE_NLS + +/* + * A shim that defers to the actual libpq_gettext(). + */ +char * +libpq_gettext(const char *msgid) +{ + if (!libpq_gettext_impl) + { + /* + * Possible if the libpq build didn't enable NLS but the libpq-oauth + * build did. That's an odd mismatch, but we can handle it. + * + * Note that callers of libpq_gettext() have to treat the return value + * as if it were const, because builds without NLS simply pass through + * their argument. + */ + return unconstify(char *, msgid); + } + + return libpq_gettext_impl(msgid); +} + +#endif /* ENABLE_NLS */ + +/* + * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment. + */ +bool +oauth_unsafe_debugging_enabled(void) +{ + const char *env = getenv("PGOAUTHDEBUG"); + + return (env && strcmp(env, "UNSAFE") == 0); +} + +/* + * Duplicate SOCK_ERRNO* definitions from libpq-int.h, for use by + * pq_block/reset_sigpipe(). + */ +#ifdef WIN32 +#define SOCK_ERRNO (WSAGetLastError()) +#define SOCK_ERRNO_SET(e) WSASetLastError(e) +#else +#define SOCK_ERRNO errno +#define SOCK_ERRNO_SET(e) (errno = (e)) +#endif + +/* + * Block SIGPIPE for this thread. This is a copy of libpq's internal API. + */ +int +pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending) +{ + sigset_t sigpipe_sigset; + sigset_t sigset; + + sigemptyset(&sigpipe_sigset); + sigaddset(&sigpipe_sigset, SIGPIPE); + + /* Block SIGPIPE and save previous mask for later reset */ + SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset)); + if (SOCK_ERRNO) + return -1; + + /* We can have a pending SIGPIPE only if it was blocked before */ + if (sigismember(osigset, SIGPIPE)) + { + /* Is there a pending SIGPIPE? */ + if (sigpending(&sigset) != 0) + return -1; + + if (sigismember(&sigset, SIGPIPE)) + *sigpipe_pending = true; + else + *sigpipe_pending = false; + } + else + *sigpipe_pending = false; + + return 0; +} + +/* + * Discard any pending SIGPIPE and reset the signal mask. This is a copy of + * libpq's internal API. + */ +void +pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe) +{ + int save_errno = SOCK_ERRNO; + int signo; + sigset_t sigset; + + /* Clear SIGPIPE only if none was pending */ + if (got_epipe && !sigpipe_pending) + { + if (sigpending(&sigset) == 0 && + sigismember(&sigset, SIGPIPE)) + { + sigset_t sigpipe_sigset; + + sigemptyset(&sigpipe_sigset); + sigaddset(&sigpipe_sigset, SIGPIPE); + + sigwait(&sigpipe_sigset, &signo); + } + } + + /* Restore saved block mask */ + pthread_sigmask(SIG_SETMASK, osigset, NULL); + + SOCK_ERRNO_SET(save_errno); +} diff --git a/src/interfaces/libpq-oauth/oauth-utils.h b/src/interfaces/libpq-oauth/oauth-utils.h new file mode 100644 index 0000000000000..f4ffefef208f5 --- /dev/null +++ b/src/interfaces/libpq-oauth/oauth-utils.h @@ -0,0 +1,94 @@ +/*------------------------------------------------------------------------- + * + * oauth-utils.h + * + * Definitions providing missing libpq internal APIs + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq-oauth/oauth-utils.h + * + *------------------------------------------------------------------------- + */ + +#ifndef OAUTH_UTILS_H +#define OAUTH_UTILS_H + +#include "fe-auth-oauth.h" +#include "libpq-fe.h" +#include "pqexpbuffer.h" + +/* + * A bank of callbacks to safely access members of PGconn, which are all passed + * to libpq_oauth_init() by libpq. + * + * Keep these aligned with the definitions in fe-auth-oauth.c as well as the + * static declarations in oauth-curl.c. + */ +#define DECLARE_GETTER(TYPE, MEMBER) \ + typedef TYPE (*conn_ ## MEMBER ## _func) (PGconn *conn); \ + extern conn_ ## MEMBER ## _func conn_ ## MEMBER; + +#define DECLARE_SETTER(TYPE, MEMBER) \ + typedef void (*set_conn_ ## MEMBER ## _func) (PGconn *conn, TYPE val); \ + extern set_conn_ ## MEMBER ## _func set_conn_ ## MEMBER; + +DECLARE_GETTER(PQExpBuffer, errorMessage); +DECLARE_GETTER(char *, oauth_client_id); +DECLARE_GETTER(char *, oauth_client_secret); +DECLARE_GETTER(char *, oauth_discovery_uri); +DECLARE_GETTER(char *, oauth_issuer_id); +DECLARE_GETTER(char *, oauth_scope); +DECLARE_GETTER(fe_oauth_state *, sasl_state); + +DECLARE_SETTER(pgsocket, altsock); +DECLARE_SETTER(char *, oauth_token); + +#undef DECLARE_GETTER +#undef DECLARE_SETTER + +typedef char *(*libpq_gettext_func) (const char *msgid); + +/* Initializes libpq-oauth. */ +extern PGDLLEXPORT void libpq_oauth_init(pgthreadlock_t threadlock, + libpq_gettext_func gettext_impl, + conn_errorMessage_func errmsg_impl, + conn_oauth_client_id_func clientid_impl, + conn_oauth_client_secret_func clientsecret_impl, + conn_oauth_discovery_uri_func discoveryuri_impl, + conn_oauth_issuer_id_func issuerid_impl, + conn_oauth_scope_func scope_impl, + conn_sasl_state_func saslstate_impl, + set_conn_altsock_func setaltsock_impl, + set_conn_oauth_token_func settoken_impl); + +/* + * Duplicated APIs, copied from libpq (primarily libpq-int.h, which we cannot + * depend on here). + */ + +typedef enum +{ + PG_BOOL_UNKNOWN = 0, /* Currently unknown */ + PG_BOOL_YES, /* Yes (true) */ + PG_BOOL_NO /* No (false) */ +} PGTernaryBool; + +extern void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3); +extern bool oauth_unsafe_debugging_enabled(void); +extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending); +extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe); + +#ifdef ENABLE_NLS +extern char *libpq_gettext(const char *msgid) pg_attribute_format_arg(1); +#else +#define libpq_gettext(x) (x) +#endif + +extern pgthreadlock_t pg_g_threadlock; + +#define pglock_thread() pg_g_threadlock(true) +#define pgunlock_thread() pg_g_threadlock(false) + +#endif /* OAUTH_UTILS_H */ diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index 27f8499d8a7ef..853aab4b1b886 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/interfaces/libpq library # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/interfaces/libpq/Makefile @@ -15,7 +15,7 @@ subdir = src/interfaces/libpq top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -export with_ssl with_gssapi with_krb_srvnam enable_injection_points +export with_ssl with_gssapi with_krb_srvnam PGFILEDESC = "PostgreSQL Access Library" @@ -63,6 +63,12 @@ OBJS += \ fe-secure-gssapi.o endif +# The OAuth implementation differs depending on the type of library being built. +OBJS_STATIC = fe-auth-oauth.o + +fe-auth-oauth_shlib.o: override CPPFLAGS_SHLIB += -DUSE_DYNAMIC_OAUTH +OBJS_SHLIB = fe-auth-oauth_shlib.o + ifeq ($(PORTNAME), cygwin) override shlib = cyg$(NAME)$(DLSUFFIX) endif @@ -86,14 +92,28 @@ else SHLIB_LINK += $(filter -lcrypt -ldes -lcom_err -lcrypto -lk5crypto -lkrb5 -lgssapi32 -lssl -lsocket -lnsl -lresolv -lintl -lm $(PTHREAD_LIBS), $(LIBS)) $(LDAP_LIBS_FE) endif ifeq ($(PORTNAME), win32) -SHLIB_LINK += -lshell32 -lws2_32 -lsecur32 $(filter -leay32 -lssleay32 -lcomerr32 -lkrb5_32, $(LIBS)) +SHLIB_LINK += -lshell32 -lws2_32 -lsecur32 $(filter -lcomerr32 -lkrb5_32, $(LIBS)) endif SHLIB_PREREQS = submake-libpgport SHLIB_EXPORTS = exports.txt +# Appends to a comma-separated list. +comma := , +define add_to_list +$(eval $1 := $(if $($1),$($1)$(comma) $2,$2)) +endef + ifeq ($(with_ssl),openssl) -PKG_CONFIG_REQUIRES_PRIVATE = libssl, libcrypto +$(call add_to_list,PKG_CONFIG_REQUIRES_PRIVATE,libssl) +$(call add_to_list,PKG_CONFIG_REQUIRES_PRIVATE,libcrypto) +endif + +ifeq ($(with_libcurl),yes) +# libpq.so doesn't link against libcurl, but libpq.a needs libpq-oauth, and +# libpq-oauth needs libcurl. Put both into *.private. +$(call add_to_list,PKG_CONFIG_REQUIRES_PRIVATE,libcurl) +%.pc: override SHLIB_LINK_INTERNAL += -lpq-oauth endif all: all-lib libpq-refs-stamp @@ -102,6 +122,13 @@ all: all-lib libpq-refs-stamp include $(top_srcdir)/src/Makefile.shlib backend_src = $(top_srcdir)/src/backend +# Add shlib-/stlib-specific objects. +$(shlib): override OBJS += $(OBJS_SHLIB) +$(shlib): $(OBJS_SHLIB) + +$(stlib): override OBJS += $(OBJS_STATIC) +$(stlib): $(OBJS_STATIC) + # Check for functions that libpq must not call, currently just exit(). # (Ideally we'd reject abort() too, but there are various scenarios where # build toolchains insert abort() calls, e.g. to implement assert().) @@ -131,6 +158,11 @@ fe-misc.o: fe-misc.c $(top_builddir)/src/port/pg_config_paths.h $(top_builddir)/src/port/pg_config_paths.h: $(MAKE) -C $(top_builddir)/src/port pg_config_paths.h +# Use src/common/Makefile's trick for tracking dependencies of shlib-specific +# objects. +%_shlib.o: %.c %.o + $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) $(CPPFLAGS_SHLIB) -c $< -o $@ + install: all installdirs install-lib $(INSTALL_DATA) $(srcdir)/libpq-fe.h '$(DESTDIR)$(includedir)' $(INSTALL_DATA) $(srcdir)/libpq-events.h '$(DESTDIR)$(includedir)' @@ -164,6 +196,6 @@ uninstall: uninstall-lib clean distclean: clean-lib $(MAKE) -C test $@ rm -rf tmp_check - rm -f $(OBJS) pthread.h libpq-refs-stamp + rm -f $(OBJS) $(OBJS_SHLIB) $(OBJS_STATIC) pthread.h libpq-refs-stamp # Might be left over from a Win32 client-only build rm -f pg_config_paths.h diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index 5d8213e0b571a..0625cf39e9af3 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -205,3 +205,9 @@ PQcancelFinish 202 PQsocketPoll 203 PQsetChunkedRowsMode 204 PQgetCurrentTimeUSec 205 +PQservice 206 +PQsetAuthDataHook 207 +PQgetAuthDataHook 208 +PQdefaultAuthDataHook 209 +PQfullProtocolVersion 210 +appendPQExpBufferVA 211 diff --git a/src/interfaces/libpq/fe-auth-oauth.c b/src/interfaces/libpq/fe-auth-oauth.c new file mode 100644 index 0000000000000..d146c5f567c29 --- /dev/null +++ b/src/interfaces/libpq/fe-auth-oauth.c @@ -0,0 +1,1397 @@ +/*------------------------------------------------------------------------- + * + * fe-auth-oauth.c + * The front-end (client) implementation of OAuth/OIDC authentication + * using the SASL OAUTHBEARER mechanism. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/interfaces/libpq/fe-auth-oauth.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#ifdef USE_DYNAMIC_OAUTH +#include +#endif + +#include "common/base64.h" +#include "common/hmac.h" +#include "common/jsonapi.h" +#include "common/oauth-common.h" +#include "fe-auth.h" +#include "fe-auth-oauth.h" +#include "mb/pg_wchar.h" +#include "pg_config_paths.h" + +/* The exported OAuth callback mechanism. */ +static void *oauth_init(PGconn *conn, const char *password, + const char *sasl_mechanism); +static SASLStatus oauth_exchange(void *opaq, bool final, + char *input, int inputlen, + char **output, int *outputlen); +static bool oauth_channel_bound(void *opaq); +static void oauth_free(void *opaq); + +const pg_fe_sasl_mech pg_oauth_mech = { + oauth_init, + oauth_exchange, + oauth_channel_bound, + oauth_free, +}; + +/* + * Initializes mechanism state for OAUTHBEARER. + * + * For a full description of the API, see libpq/fe-auth-sasl.h. + */ +static void * +oauth_init(PGconn *conn, const char *password, + const char *sasl_mechanism) +{ + fe_oauth_state *state; + + /* + * We only support one SASL mechanism here; anything else is programmer + * error. + */ + Assert(sasl_mechanism != NULL); + Assert(strcmp(sasl_mechanism, OAUTHBEARER_NAME) == 0); + + state = calloc(1, sizeof(*state)); + if (!state) + return NULL; + + state->step = FE_OAUTH_INIT; + state->conn = conn; + + return state; +} + +/* + * Frees the state allocated by oauth_init(). + * + * This handles only mechanism state tied to the connection lifetime; state + * stored in state->async_ctx is freed up either immediately after the + * authentication handshake succeeds, or before the mechanism is cleaned up on + * failure. See pg_fe_cleanup_oauth_flow() and cleanup_user_oauth_flow(). + */ +static void +oauth_free(void *opaq) +{ + fe_oauth_state *state = opaq; + + /* Any async authentication state should have been cleaned up already. */ + Assert(!state->async_ctx); + + free(state); +} + +#define kvsep "\x01" + +/* + * Constructs an OAUTHBEARER client initial response (RFC 7628, Sec. 3.1). + * + * If discover is true, the initial response will contain a request for the + * server's required OAuth parameters (Sec. 4.3). Otherwise, conn->token must + * be set; it will be sent as the connection's bearer token. + * + * Returns the response as a null-terminated string, or NULL on error. + */ +static char * +client_initial_response(PGconn *conn, bool discover) +{ + static const char *const resp_format = "n,," kvsep "auth=%s%s" kvsep kvsep; + + PQExpBufferData buf; + const char *authn_scheme; + char *response = NULL; + const char *token = conn->oauth_token; + + if (discover) + { + /* Parameter discovery uses a completely empty auth value. */ + authn_scheme = token = ""; + } + else + { + /* + * Use a Bearer authentication scheme (RFC 6750, Sec. 2.1). A trailing + * space is used as a separator. + */ + authn_scheme = "Bearer "; + + /* conn->token must have been set in this case. */ + if (!token) + { + Assert(false); + libpq_append_conn_error(conn, + "internal error: no OAuth token was set for the connection"); + return NULL; + } + } + + initPQExpBuffer(&buf); + appendPQExpBuffer(&buf, resp_format, authn_scheme, token); + + if (!PQExpBufferDataBroken(buf)) + response = strdup(buf.data); + termPQExpBuffer(&buf); + + if (!response) + libpq_append_conn_error(conn, "out of memory"); + + return response; +} + +/* + * JSON Parser (for the OAUTHBEARER error result) + */ + +/* Relevant JSON fields in the error result object. */ +#define ERROR_STATUS_FIELD "status" +#define ERROR_SCOPE_FIELD "scope" +#define ERROR_OPENID_CONFIGURATION_FIELD "openid-configuration" + +/* + * Limit the maximum number of nested objects/arrays. Because OAUTHBEARER + * doesn't have any defined extensions for its JSON yet, we can be much more + * conservative here than with libpq-oauth's MAX_OAUTH_NESTING_LEVEL; we expect + * a nesting level of 1 in practice. + */ +#define MAX_SASL_NESTING_LEVEL 8 + +struct json_ctx +{ + char *errmsg; /* any non-NULL value stops all processing */ + PQExpBufferData errbuf; /* backing memory for errmsg */ + int nested; /* nesting level (zero is the top) */ + + const char *target_field_name; /* points to a static allocation */ + char **target_field; /* see below */ + + /* target_field, if set, points to one of the following: */ + char *status; + char *scope; + char *discovery_uri; +}; + +#define oauth_json_has_error(ctx) \ + (PQExpBufferDataBroken((ctx)->errbuf) || (ctx)->errmsg) + +#define oauth_json_set_error(ctx, ...) \ + do { \ + appendPQExpBuffer(&(ctx)->errbuf, __VA_ARGS__); \ + (ctx)->errmsg = (ctx)->errbuf.data; \ + } while (0) + +static JsonParseErrorType +oauth_json_object_start(void *state) +{ + struct json_ctx *ctx = state; + + if (ctx->target_field) + { + Assert(ctx->nested == 1); + + oauth_json_set_error(ctx, + libpq_gettext("field \"%s\" must be a string"), + ctx->target_field_name); + } + + ++ctx->nested; + if (ctx->nested > MAX_SASL_NESTING_LEVEL) + oauth_json_set_error(ctx, libpq_gettext("JSON is too deeply nested")); + + return oauth_json_has_error(ctx) ? JSON_SEM_ACTION_FAILED : JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_object_end(void *state) +{ + struct json_ctx *ctx = state; + + --ctx->nested; + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_object_field_start(void *state, char *name, bool isnull) +{ + struct json_ctx *ctx = state; + + /* Only top-level keys are considered. */ + if (ctx->nested == 1) + { + if (strcmp(name, ERROR_STATUS_FIELD) == 0) + { + ctx->target_field_name = ERROR_STATUS_FIELD; + ctx->target_field = &ctx->status; + } + else if (strcmp(name, ERROR_SCOPE_FIELD) == 0) + { + ctx->target_field_name = ERROR_SCOPE_FIELD; + ctx->target_field = &ctx->scope; + } + else if (strcmp(name, ERROR_OPENID_CONFIGURATION_FIELD) == 0) + { + ctx->target_field_name = ERROR_OPENID_CONFIGURATION_FIELD; + ctx->target_field = &ctx->discovery_uri; + } + } + + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_array_start(void *state) +{ + struct json_ctx *ctx = state; + + if (!ctx->nested) + { + ctx->errmsg = libpq_gettext("top-level element must be an object"); + } + else if (ctx->target_field) + { + Assert(ctx->nested == 1); + + oauth_json_set_error(ctx, + libpq_gettext("field \"%s\" must be a string"), + ctx->target_field_name); + } + + ++ctx->nested; + if (ctx->nested > MAX_SASL_NESTING_LEVEL) + oauth_json_set_error(ctx, libpq_gettext("JSON is too deeply nested")); + + return oauth_json_has_error(ctx) ? JSON_SEM_ACTION_FAILED : JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_array_end(void *state) +{ + struct json_ctx *ctx = state; + + --ctx->nested; + return JSON_SUCCESS; +} + +static JsonParseErrorType +oauth_json_scalar(void *state, char *token, JsonTokenType type) +{ + struct json_ctx *ctx = state; + + if (!ctx->nested) + { + ctx->errmsg = libpq_gettext("top-level element must be an object"); + return JSON_SEM_ACTION_FAILED; + } + + if (ctx->target_field) + { + if (ctx->nested != 1) + { + /* + * ctx->target_field should not have been set for nested keys. + * Assert and don't continue any further for production builds. + */ + Assert(false); + oauth_json_set_error(ctx, + "internal error: target scalar found at nesting level %d during OAUTHBEARER parsing", + ctx->nested); + return JSON_SEM_ACTION_FAILED; + } + + /* + * We don't allow duplicate field names; error out if the target has + * already been set. + */ + if (*ctx->target_field) + { + oauth_json_set_error(ctx, + libpq_gettext("field \"%s\" is duplicated"), + ctx->target_field_name); + return JSON_SEM_ACTION_FAILED; + } + + /* The only fields we support are strings. */ + if (type != JSON_TOKEN_STRING) + { + oauth_json_set_error(ctx, + libpq_gettext("field \"%s\" must be a string"), + ctx->target_field_name); + return JSON_SEM_ACTION_FAILED; + } + + *ctx->target_field = strdup(token); + if (!*ctx->target_field) + return JSON_OUT_OF_MEMORY; + + ctx->target_field = NULL; + ctx->target_field_name = NULL; + } + else + { + /* otherwise we just ignore it */ + } + + return JSON_SUCCESS; +} + +#define HTTPS_SCHEME "https://" +#define HTTP_SCHEME "http://" + +/* We support both well-known suffixes defined by RFC 8414. */ +#define WK_PREFIX "/.well-known/" +#define OPENID_WK_SUFFIX "openid-configuration" +#define OAUTH_WK_SUFFIX "oauth-authorization-server" + +/* + * Derives an issuer identifier from one of our recognized .well-known URIs, + * using the rules in RFC 8414. + */ +static char * +issuer_from_well_known_uri(PGconn *conn, const char *wkuri) +{ + const char *authority_start = NULL; + const char *wk_start; + const char *wk_end; + char *issuer; + ptrdiff_t start_offset, + end_offset; + size_t end_len; + + /* + * https:// is required for issuer identifiers (RFC 8414, Sec. 2; OIDC + * Discovery 1.0, Sec. 3). This is a case-insensitive comparison at this + * level (but issuer identifier comparison at the level above this is + * case-sensitive, so in practice it's probably moot). + */ + if (pg_strncasecmp(wkuri, HTTPS_SCHEME, strlen(HTTPS_SCHEME)) == 0) + authority_start = wkuri + strlen(HTTPS_SCHEME); + + if (!authority_start + && oauth_unsafe_debugging_enabled() + && pg_strncasecmp(wkuri, HTTP_SCHEME, strlen(HTTP_SCHEME)) == 0) + { + /* Allow http:// for testing only. */ + authority_start = wkuri + strlen(HTTP_SCHEME); + } + + if (!authority_start) + { + libpq_append_conn_error(conn, + "OAuth discovery URI \"%s\" must use HTTPS", + wkuri); + return NULL; + } + + /* + * Well-known URIs in general may support queries and fragments, but the + * two types we support here do not. (They must be constructed from the + * components of issuer identifiers, which themselves may not contain any + * queries or fragments.) + * + * It's important to check this first, to avoid getting tricked later by a + * prefix buried inside a query or fragment. + */ + if (strpbrk(authority_start, "?#") != NULL) + { + libpq_append_conn_error(conn, + "OAuth discovery URI \"%s\" must not contain query or fragment components", + wkuri); + return NULL; + } + + /* + * Find the start of the .well-known prefix. IETF rules (RFC 8615) state + * this must be at the beginning of the path component, but OIDC defined + * it at the end instead (OIDC Discovery 1.0, Sec. 4), so we have to + * search for it anywhere. + */ + wk_start = strstr(authority_start, WK_PREFIX); + if (!wk_start) + { + libpq_append_conn_error(conn, + "OAuth discovery URI \"%s\" is not a .well-known URI", + wkuri); + return NULL; + } + + /* + * Now find the suffix type. We only support the two defined in OIDC + * Discovery 1.0 and RFC 8414. + */ + wk_end = wk_start + strlen(WK_PREFIX); + + if (strncmp(wk_end, OPENID_WK_SUFFIX, strlen(OPENID_WK_SUFFIX)) == 0) + wk_end += strlen(OPENID_WK_SUFFIX); + else if (strncmp(wk_end, OAUTH_WK_SUFFIX, strlen(OAUTH_WK_SUFFIX)) == 0) + wk_end += strlen(OAUTH_WK_SUFFIX); + else + wk_end = NULL; + + /* + * Even if there's a match, we still need to check to make sure the suffix + * takes up the entire path segment, to weed out constructions like + * "/.well-known/openid-configuration-bad". + */ + if (!wk_end || (*wk_end != '/' && *wk_end != '\0')) + { + libpq_append_conn_error(conn, + "OAuth discovery URI \"%s\" uses an unsupported .well-known suffix", + wkuri); + return NULL; + } + + /* + * Finally, make sure the .well-known components are provided either as a + * prefix (IETF style) or as a postfix (OIDC style). In other words, + * "https://localhost/a/.well-known/openid-configuration/b" is not allowed + * to claim association with "https://localhost/a/b". + */ + if (*wk_end != '\0') + { + /* + * It's not at the end, so it's required to be at the beginning at the + * path. Find the starting slash. + */ + const char *path_start; + + path_start = strchr(authority_start, '/'); + Assert(path_start); /* otherwise we wouldn't have found WK_PREFIX */ + + if (wk_start != path_start) + { + libpq_append_conn_error(conn, + "OAuth discovery URI \"%s\" uses an invalid format", + wkuri); + return NULL; + } + } + + /* Checks passed! Now build the issuer. */ + issuer = strdup(wkuri); + if (!issuer) + { + libpq_append_conn_error(conn, "out of memory"); + return NULL; + } + + /* + * The .well-known components are from [wk_start, wk_end). Remove those to + * form the issuer ID, by shifting the path suffix (which may be empty) + * leftwards. + */ + start_offset = wk_start - wkuri; + end_offset = wk_end - wkuri; + end_len = strlen(wk_end) + 1; /* move the NULL terminator too */ + + memmove(issuer + start_offset, issuer + end_offset, end_len); + + return issuer; +} + +/* + * Parses the server error result (RFC 7628, Sec. 3.2.2) contained in msg and + * stores any discovered openid_configuration and scope settings for the + * connection. + */ +static bool +handle_oauth_sasl_error(PGconn *conn, const char *msg, int msglen) +{ + JsonLexContext *lex; + JsonSemAction sem = {0}; + JsonParseErrorType err; + struct json_ctx ctx = {0}; + char *errmsg = NULL; + bool success = false; + + Assert(conn->oauth_issuer_id); /* ensured by setup_oauth_parameters() */ + + /* Sanity check. */ + if (strlen(msg) != msglen) + { + libpq_append_conn_error(conn, + "server's error message contained an embedded NULL, and was discarded"); + return false; + } + + /* + * pg_parse_json doesn't validate the incoming UTF-8, so we have to check + * that up front. + */ + if (pg_encoding_verifymbstr(PG_UTF8, msg, msglen) != msglen) + { + libpq_append_conn_error(conn, + "server's error response is not valid UTF-8"); + return false; + } + + lex = makeJsonLexContextCstringLen(NULL, msg, msglen, PG_UTF8, true); + setJsonLexContextOwnsTokens(lex, true); /* must not leak on error */ + + initPQExpBuffer(&ctx.errbuf); + sem.semstate = &ctx; + + sem.object_start = oauth_json_object_start; + sem.object_end = oauth_json_object_end; + sem.object_field_start = oauth_json_object_field_start; + sem.array_start = oauth_json_array_start; + sem.array_end = oauth_json_array_end; + sem.scalar = oauth_json_scalar; + + err = pg_parse_json(lex, &sem); + + if (err == JSON_SEM_ACTION_FAILED) + { + if (PQExpBufferDataBroken(ctx.errbuf)) + errmsg = libpq_gettext("out of memory"); + else if (ctx.errmsg) + errmsg = ctx.errmsg; + else + { + /* + * Developer error: one of the action callbacks didn't call + * oauth_json_set_error() before erroring out. + */ + Assert(oauth_json_has_error(&ctx)); + errmsg = ""; + } + } + else if (err != JSON_SUCCESS) + errmsg = json_errdetail(err, lex); + + if (errmsg) + libpq_append_conn_error(conn, + "failed to parse server's error response: %s", + errmsg); + + /* Don't need the error buffer or the JSON lexer anymore. */ + termPQExpBuffer(&ctx.errbuf); + freeJsonLexContext(lex); + + if (errmsg) + goto cleanup; + + if (ctx.discovery_uri) + { + char *discovery_issuer; + + /* + * The URI MUST correspond to our existing issuer, to avoid mix-ups. + * + * Issuer comparison is done byte-wise, rather than performing any URL + * normalization; this follows the suggestions for issuer comparison + * in RFC 9207 Sec. 2.4 (which requires simple string comparison) and + * vastly simplifies things. Since this is the key protection against + * a rogue server sending the client to an untrustworthy location, + * simpler is better. + */ + discovery_issuer = issuer_from_well_known_uri(conn, ctx.discovery_uri); + if (!discovery_issuer) + goto cleanup; /* error message already set */ + + if (strcmp(conn->oauth_issuer_id, discovery_issuer) != 0) + { + libpq_append_conn_error(conn, + "server's discovery document at %s (issuer \"%s\") is incompatible with oauth_issuer (%s)", + ctx.discovery_uri, discovery_issuer, + conn->oauth_issuer_id); + + free(discovery_issuer); + goto cleanup; + } + + free(discovery_issuer); + + if (!conn->oauth_discovery_uri) + { + conn->oauth_discovery_uri = ctx.discovery_uri; + ctx.discovery_uri = NULL; + } + else + { + /* This must match the URI we'd previously determined. */ + if (strcmp(conn->oauth_discovery_uri, ctx.discovery_uri) != 0) + { + libpq_append_conn_error(conn, + "server's discovery document has moved to %s (previous location was %s)", + ctx.discovery_uri, + conn->oauth_discovery_uri); + goto cleanup; + } + } + } + + if (ctx.scope) + { + /* Servers may not override a previously set oauth_scope. */ + if (!conn->oauth_scope) + { + conn->oauth_scope = ctx.scope; + ctx.scope = NULL; + } + } + + if (!ctx.status) + { + libpq_append_conn_error(conn, + "server sent error response without a status"); + goto cleanup; + } + + if (strcmp(ctx.status, "invalid_token") != 0) + { + /* + * invalid_token is the only error code we'll automatically retry for; + * otherwise, just bail out now. + */ + libpq_append_conn_error(conn, + "server rejected OAuth bearer token: %s", + ctx.status); + goto cleanup; + } + + success = true; + +cleanup: + free(ctx.status); + free(ctx.scope); + free(ctx.discovery_uri); + + return success; +} + +/* + * Callback implementation of conn->async_auth() for a user-defined OAuth flow. + * Delegates the retrieval of the token to the application's async callback. + * + * This will be called multiple times as needed; the application is responsible + * for setting an altsock to signal and returning the correct PGRES_POLLING_* + * statuses for use by PQconnectPoll(). + */ +static PostgresPollingStatusType +run_user_oauth_flow(PGconn *conn) +{ + fe_oauth_state *state = conn->sasl_state; + PGoauthBearerRequest *request = state->async_ctx; + PostgresPollingStatusType status; + + if (!request->async) + { + libpq_append_conn_error(conn, + "user-defined OAuth flow provided neither a token nor an async callback"); + return PGRES_POLLING_FAILED; + } + + status = request->async(conn, request, &conn->altsock); + if (status == PGRES_POLLING_FAILED) + { + libpq_append_conn_error(conn, "user-defined OAuth flow failed"); + return status; + } + else if (status == PGRES_POLLING_OK) + { + /* + * We already have a token, so copy it into the conn. (We can't hold + * onto the original string, since it may not be safe for us to free() + * it.) + */ + if (!request->token) + { + libpq_append_conn_error(conn, + "user-defined OAuth flow did not provide a token"); + return PGRES_POLLING_FAILED; + } + + conn->oauth_token = strdup(request->token); + if (!conn->oauth_token) + { + libpq_append_conn_error(conn, "out of memory"); + return PGRES_POLLING_FAILED; + } + + return PGRES_POLLING_OK; + } + + /* The hook wants the client to poll the altsock. Make sure it set one. */ + if (conn->altsock == PGINVALID_SOCKET) + { + libpq_append_conn_error(conn, + "user-defined OAuth flow did not provide a socket for polling"); + return PGRES_POLLING_FAILED; + } + + return status; +} + +/* + * Cleanup callback for the async user flow. Delegates most of its job to the + * user-provided cleanup implementation, then disconnects the altsock. + */ +static void +cleanup_user_oauth_flow(PGconn *conn) +{ + fe_oauth_state *state = conn->sasl_state; + PGoauthBearerRequest *request = state->async_ctx; + + Assert(request); + + if (request->cleanup) + request->cleanup(conn, request); + conn->altsock = PGINVALID_SOCKET; + + free(request); + state->async_ctx = NULL; +} + +/*------------- + * Builtin Flow + * + * There are three potential implementations of use_builtin_flow: + * + * 1) If the OAuth client is disabled at configuration time, return false. + * Dependent clients must provide their own flow. + * 2) If the OAuth client is enabled and USE_DYNAMIC_OAUTH is defined, dlopen() + * the libpq-oauth plugin and use its implementation. + * 3) Otherwise, use flow callbacks that are statically linked into the + * executable. + */ + +#if !defined(USE_LIBCURL) + +/* + * This configuration doesn't support the builtin flow. + */ + +bool +use_builtin_flow(PGconn *conn, fe_oauth_state *state) +{ + return false; +} + +#elif defined(USE_DYNAMIC_OAUTH) + +/* + * Use the builtin flow in the libpq-oauth plugin, which is loaded at runtime. + */ + +typedef char *(*libpq_gettext_func) (const char *msgid); + +/* + * Define accessor/mutator shims to inject into libpq-oauth, so that it doesn't + * depend on the offsets within PGconn. (These have changed during minor version + * updates in the past.) + */ + +#define DEFINE_GETTER(TYPE, MEMBER) \ + typedef TYPE (*conn_ ## MEMBER ## _func) (PGconn *conn); \ + static TYPE conn_ ## MEMBER(PGconn *conn) { return conn->MEMBER; } + +/* Like DEFINE_GETTER, but returns a pointer to the member. */ +#define DEFINE_GETTER_P(TYPE, MEMBER) \ + typedef TYPE (*conn_ ## MEMBER ## _func) (PGconn *conn); \ + static TYPE conn_ ## MEMBER(PGconn *conn) { return &conn->MEMBER; } + +#define DEFINE_SETTER(TYPE, MEMBER) \ + typedef void (*set_conn_ ## MEMBER ## _func) (PGconn *conn, TYPE val); \ + static void set_conn_ ## MEMBER(PGconn *conn, TYPE val) { conn->MEMBER = val; } + +DEFINE_GETTER_P(PQExpBuffer, errorMessage); +DEFINE_GETTER(char *, oauth_client_id); +DEFINE_GETTER(char *, oauth_client_secret); +DEFINE_GETTER(char *, oauth_discovery_uri); +DEFINE_GETTER(char *, oauth_issuer_id); +DEFINE_GETTER(char *, oauth_scope); +DEFINE_GETTER(fe_oauth_state *, sasl_state); + +DEFINE_SETTER(pgsocket, altsock); +DEFINE_SETTER(char *, oauth_token); + +/* + * Loads the libpq-oauth plugin via dlopen(), initializes it, and plugs its + * callbacks into the connection's async auth handlers. + * + * Failure to load here results in a relatively quiet connection error, to + * handle the use case where the build supports loading a flow but a user does + * not want to install it. Troubleshooting of linker/loader failures can be done + * via PGOAUTHDEBUG. + */ +bool +use_builtin_flow(PGconn *conn, fe_oauth_state *state) +{ + static bool initialized = false; + static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; + int lockerr; + + void (*init) (pgthreadlock_t threadlock, + libpq_gettext_func gettext_impl, + conn_errorMessage_func errmsg_impl, + conn_oauth_client_id_func clientid_impl, + conn_oauth_client_secret_func clientsecret_impl, + conn_oauth_discovery_uri_func discoveryuri_impl, + conn_oauth_issuer_id_func issuerid_impl, + conn_oauth_scope_func scope_impl, + conn_sasl_state_func saslstate_impl, + set_conn_altsock_func setaltsock_impl, + set_conn_oauth_token_func settoken_impl); + PostgresPollingStatusType (*flow) (PGconn *conn); + void (*cleanup) (PGconn *conn); + + /* + * On macOS only, load the module using its absolute install path; the + * standard search behavior is not very helpful for this use case. Unlike + * on other platforms, DYLD_LIBRARY_PATH is used as a fallback even with + * absolute paths (modulo SIP effects), so tests can continue to work. + * + * On the other platforms, load the module using only the basename, to + * rely on the runtime linker's standard search behavior. + */ + const char *const module_name = +#if defined(__darwin__) + LIBDIR "/libpq-oauth-" PG_MAJORVERSION DLSUFFIX; +#else + "libpq-oauth-" PG_MAJORVERSION DLSUFFIX; +#endif + + state->builtin_flow = dlopen(module_name, RTLD_NOW | RTLD_LOCAL); + if (!state->builtin_flow) + { + /* + * For end users, this probably isn't an error condition, it just + * means the flow isn't installed. Developers and package maintainers + * may want to debug this via the PGOAUTHDEBUG envvar, though. + * + * Note that POSIX dlerror() isn't guaranteed to be threadsafe. + */ + if (oauth_unsafe_debugging_enabled()) + fprintf(stderr, "failed dlopen for libpq-oauth: %s\n", dlerror()); + + return false; + } + + if ((init = dlsym(state->builtin_flow, "libpq_oauth_init")) == NULL + || (flow = dlsym(state->builtin_flow, "pg_fe_run_oauth_flow")) == NULL + || (cleanup = dlsym(state->builtin_flow, "pg_fe_cleanup_oauth_flow")) == NULL) + { + /* + * This is more of an error condition than the one above, but due to + * the dlerror() threadsafety issue, lock it behind PGOAUTHDEBUG too. + */ + if (oauth_unsafe_debugging_enabled()) + fprintf(stderr, "failed dlsym for libpq-oauth: %s\n", dlerror()); + + dlclose(state->builtin_flow); + return false; + } + + /* + * Past this point, we do not unload the module. It stays in the process + * permanently. + */ + + /* + * We need to inject necessary function pointers into the module. This + * only needs to be done once -- even if the pointers are constant, + * assigning them while another thread is executing the flows feels like + * tempting fate. + */ + if ((lockerr = pthread_mutex_lock(&init_mutex)) != 0) + { + /* Should not happen... but don't continue if it does. */ + Assert(false); + + libpq_append_conn_error(conn, "failed to lock mutex (%d)", lockerr); + return false; + } + + if (!initialized) + { + init(pg_g_threadlock, +#ifdef ENABLE_NLS + libpq_gettext, +#else + NULL, +#endif + conn_errorMessage, + conn_oauth_client_id, + conn_oauth_client_secret, + conn_oauth_discovery_uri, + conn_oauth_issuer_id, + conn_oauth_scope, + conn_sasl_state, + set_conn_altsock, + set_conn_oauth_token); + + initialized = true; + } + + pthread_mutex_unlock(&init_mutex); + + /* Set our asynchronous callbacks. */ + conn->async_auth = flow; + conn->cleanup_async_auth = cleanup; + + return true; +} + +#else + +/* + * Use the builtin flow in libpq-oauth.a (see libpq-oauth/oauth-curl.h). + */ + +extern PostgresPollingStatusType pg_fe_run_oauth_flow(PGconn *conn); +extern void pg_fe_cleanup_oauth_flow(PGconn *conn); + +bool +use_builtin_flow(PGconn *conn, fe_oauth_state *state) +{ + /* Set our asynchronous callbacks. */ + conn->async_auth = pg_fe_run_oauth_flow; + conn->cleanup_async_auth = pg_fe_cleanup_oauth_flow; + + return true; +} + +#endif /* USE_LIBCURL */ + + +/* + * Chooses an OAuth client flow for the connection, which will retrieve a Bearer + * token for presentation to the server. + * + * If the application has registered a custom flow handler using + * PQAUTHDATA_OAUTH_BEARER_TOKEN, it may either return a token immediately (e.g. + * if it has one cached for immediate use), or set up for a series of + * asynchronous callbacks which will be managed by run_user_oauth_flow(). + * + * If the default handler is used instead, a Device Authorization flow is used + * for the connection if support has been compiled in. (See + * fe-auth-oauth-curl.c for implementation details.) + * + * If neither a custom handler nor the builtin flow is available, the connection + * fails here. + */ +static bool +setup_token_request(PGconn *conn, fe_oauth_state *state) +{ + int res; + PGoauthBearerRequest request = { + .openid_configuration = conn->oauth_discovery_uri, + .scope = conn->oauth_scope, + }; + + Assert(request.openid_configuration); + + /* The client may have overridden the OAuth flow. */ + res = PQauthDataHook(PQAUTHDATA_OAUTH_BEARER_TOKEN, conn, &request); + if (res > 0) + { + PGoauthBearerRequest *request_copy; + + if (request.token) + { + /* + * We already have a token, so copy it into the conn. (We can't + * hold onto the original string, since it may not be safe for us + * to free() it.) + */ + conn->oauth_token = strdup(request.token); + if (!conn->oauth_token) + { + libpq_append_conn_error(conn, "out of memory"); + goto fail; + } + + /* short-circuit */ + if (request.cleanup) + request.cleanup(conn, &request); + return true; + } + + request_copy = malloc(sizeof(*request_copy)); + if (!request_copy) + { + libpq_append_conn_error(conn, "out of memory"); + goto fail; + } + + *request_copy = request; + + conn->async_auth = run_user_oauth_flow; + conn->cleanup_async_auth = cleanup_user_oauth_flow; + state->async_ctx = request_copy; + } + else if (res < 0) + { + libpq_append_conn_error(conn, "user-defined OAuth flow failed"); + goto fail; + } + else if (!use_builtin_flow(conn, state)) + { + libpq_append_conn_error(conn, "no OAuth flows are available (try installing the libpq-oauth package)"); + goto fail; + } + + return true; + +fail: + if (request.cleanup) + request.cleanup(conn, &request); + return false; +} + +/* + * Fill in our issuer identifier (and discovery URI, if possible) using the + * connection parameters. If conn->oauth_discovery_uri can't be populated in + * this function, it will be requested from the server. + */ +static bool +setup_oauth_parameters(PGconn *conn) +{ + /* + * This is the only function that sets conn->oauth_issuer_id. If a + * previous connection attempt has already computed it, don't overwrite it + * or the discovery URI. (There's no reason for them to change once + * they're set, and handle_oauth_sasl_error() will fail the connection if + * the server attempts to switch them on us later.) + */ + if (conn->oauth_issuer_id) + return true; + + /*--- + * To talk to a server, we require the user to provide issuer and client + * identifiers. + * + * While it's possible for an OAuth client to support multiple issuers, it + * requires additional effort to make sure the flows in use are safe -- to + * quote RFC 9207, + * + * OAuth clients that interact with only one authorization server are + * not vulnerable to mix-up attacks. However, when such clients decide + * to add support for a second authorization server in the future, they + * become vulnerable and need to apply countermeasures to mix-up + * attacks. + * + * For now, we allow only one. + */ + if (!conn->oauth_issuer || !conn->oauth_client_id) + { + libpq_append_conn_error(conn, + "server requires OAuth authentication, but oauth_issuer and oauth_client_id are not both set"); + return false; + } + + /* + * oauth_issuer is interpreted differently if it's a well-known discovery + * URI rather than just an issuer identifier. + */ + if (strstr(conn->oauth_issuer, WK_PREFIX) != NULL) + { + /* + * Convert the URI back to an issuer identifier. (This also performs + * validation of the URI format.) + */ + conn->oauth_issuer_id = issuer_from_well_known_uri(conn, + conn->oauth_issuer); + if (!conn->oauth_issuer_id) + return false; /* error message already set */ + + conn->oauth_discovery_uri = strdup(conn->oauth_issuer); + if (!conn->oauth_discovery_uri) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + } + else + { + /* + * Treat oauth_issuer as an issuer identifier. We'll ask the server + * for the discovery URI. + */ + conn->oauth_issuer_id = strdup(conn->oauth_issuer); + if (!conn->oauth_issuer_id) + { + libpq_append_conn_error(conn, "out of memory"); + return false; + } + } + + return true; +} + +/* + * Implements the OAUTHBEARER SASL exchange (RFC 7628, Sec. 3.2). + * + * If the necessary OAuth parameters are set up on the connection, this will run + * the client flow asynchronously and present the resulting token to the server. + * Otherwise, an empty discovery response will be sent and any parameters sent + * back by the server will be stored for a second attempt. + * + * For a full description of the API, see libpq/sasl.h. + */ +static SASLStatus +oauth_exchange(void *opaq, bool final, + char *input, int inputlen, + char **output, int *outputlen) +{ + fe_oauth_state *state = opaq; + PGconn *conn = state->conn; + bool discover = false; + + *output = NULL; + *outputlen = 0; + + switch (state->step) + { + case FE_OAUTH_INIT: + /* We begin in the initial response phase. */ + Assert(inputlen == -1); + + if (!setup_oauth_parameters(conn)) + return SASL_FAILED; + + if (conn->oauth_token) + { + /* + * A previous connection already fetched the token; we'll use + * it below. + */ + } + else if (conn->oauth_discovery_uri) + { + /* + * We don't have a token, but we have a discovery URI already + * stored. Decide whether we're using a user-provided OAuth + * flow or the one we have built in. + */ + if (!setup_token_request(conn, state)) + return SASL_FAILED; + + if (conn->oauth_token) + { + /* + * A really smart user implementation may have already + * given us the token (e.g. if there was an unexpired copy + * already cached), and we can use it immediately. + */ + } + else + { + /* + * Otherwise, we'll have to hand the connection over to + * our OAuth implementation. + * + * This could take a while, since it generally involves a + * user in the loop. To avoid consuming the server's + * authentication timeout, we'll continue this handshake + * to the end, so that the server can close its side of + * the connection. We'll open a second connection later + * once we've retrieved a token. + */ + discover = true; + } + } + else + { + /* + * If we don't have a token, and we don't have a discovery URI + * to be able to request a token, we ask the server for one + * explicitly. + */ + discover = true; + } + + /* + * Generate an initial response. This either contains a token, if + * we have one, or an empty discovery response which is doomed to + * fail. + */ + *output = client_initial_response(conn, discover); + if (!*output) + return SASL_FAILED; + + *outputlen = strlen(*output); + state->step = FE_OAUTH_BEARER_SENT; + + if (conn->oauth_token) + { + /* + * For the purposes of require_auth, our side of + * authentication is done at this point; the server will + * either accept the connection or send an error. Unlike + * SCRAM, there is no additional server data to check upon + * success. + */ + conn->client_finished_auth = true; + } + + return SASL_CONTINUE; + + case FE_OAUTH_BEARER_SENT: + if (final) + { + /* + * OAUTHBEARER does not make use of additional data with a + * successful SASL exchange, so we shouldn't get an + * AuthenticationSASLFinal message. + */ + libpq_append_conn_error(conn, + "server sent unexpected additional OAuth data"); + return SASL_FAILED; + } + + /* + * An error message was sent by the server. Respond with the + * required dummy message (RFC 7628, sec. 3.2.3). + */ + *output = strdup(kvsep); + if (unlikely(!*output)) + { + libpq_append_conn_error(conn, "out of memory"); + return SASL_FAILED; + } + *outputlen = strlen(*output); /* == 1 */ + + /* Grab the settings from discovery. */ + if (!handle_oauth_sasl_error(conn, input, inputlen)) + return SASL_FAILED; + + if (conn->oauth_token) + { + /* + * The server rejected our token. Continue onwards towards the + * expected FATAL message, but mark our state to catch any + * unexpected "success" from the server. + */ + state->step = FE_OAUTH_SERVER_ERROR; + return SASL_CONTINUE; + } + + if (!conn->async_auth) + { + /* + * No OAuth flow is set up yet. Did we get enough information + * from the server to create one? + */ + if (!conn->oauth_discovery_uri) + { + libpq_append_conn_error(conn, + "server requires OAuth authentication, but no discovery metadata was provided"); + return SASL_FAILED; + } + + /* Yes. Set up the flow now. */ + if (!setup_token_request(conn, state)) + return SASL_FAILED; + + if (conn->oauth_token) + { + /* + * A token was available in a custom flow's cache. Skip + * the asynchronous processing. + */ + goto reconnect; + } + } + + /* + * Time to retrieve a token. This involves a number of HTTP + * connections and timed waits, so we escape the synchronous auth + * processing and tell PQconnectPoll to transfer control to our + * async implementation. + */ + Assert(conn->async_auth); /* should have been set already */ + state->step = FE_OAUTH_REQUESTING_TOKEN; + return SASL_ASYNC; + + case FE_OAUTH_REQUESTING_TOKEN: + + /* + * We've returned successfully from token retrieval. Double-check + * that we have what we need for the next connection. + */ + if (!conn->oauth_token) + { + Assert(false); /* should have failed before this point! */ + libpq_append_conn_error(conn, + "internal error: OAuth flow did not set a token"); + return SASL_FAILED; + } + + goto reconnect; + + case FE_OAUTH_SERVER_ERROR: + + /* + * After an error, the server should send an error response to + * fail the SASL handshake, which is handled in higher layers. + * + * If we get here, the server either sent *another* challenge + * which isn't defined in the RFC, or completed the handshake + * successfully after telling us it was going to fail. Neither is + * acceptable. + */ + libpq_append_conn_error(conn, + "server sent additional OAuth data after error"); + return SASL_FAILED; + + default: + libpq_append_conn_error(conn, "invalid OAuth exchange state"); + break; + } + + Assert(false); /* should never get here */ + return SASL_FAILED; + +reconnect: + + /* + * Despite being a failure from the point of view of SASL, we have enough + * information to restart with a new connection. + */ + libpq_append_conn_error(conn, "retrying connection with new bearer token"); + conn->oauth_want_retry = true; + return SASL_FAILED; +} + +static bool +oauth_channel_bound(void *opaq) +{ + /* This mechanism does not support channel binding. */ + return false; +} + +/* + * Fully clears out any stored OAuth token. This is done proactively upon + * successful connection as well as during pqClosePGconn(). + */ +void +pqClearOAuthToken(PGconn *conn) +{ + if (!conn->oauth_token) + return; + + explicit_bzero(conn->oauth_token, strlen(conn->oauth_token)); + free(conn->oauth_token); + conn->oauth_token = NULL; +} + +/* + * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment. + */ +bool +oauth_unsafe_debugging_enabled(void) +{ + const char *env = getenv("PGOAUTHDEBUG"); + + return (env && strcmp(env, "UNSAFE") == 0); +} diff --git a/src/interfaces/libpq/fe-auth-oauth.h b/src/interfaces/libpq/fe-auth-oauth.h new file mode 100644 index 0000000000000..0d59e91605bbe --- /dev/null +++ b/src/interfaces/libpq/fe-auth-oauth.h @@ -0,0 +1,52 @@ +/*------------------------------------------------------------------------- + * + * fe-auth-oauth.h + * + * Definitions for OAuth authentication implementations + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/fe-auth-oauth.h + * + *------------------------------------------------------------------------- + */ + +#ifndef FE_AUTH_OAUTH_H +#define FE_AUTH_OAUTH_H + +#include "fe-auth-sasl.h" +#include "libpq-fe.h" + + +enum fe_oauth_step +{ + FE_OAUTH_INIT, + FE_OAUTH_BEARER_SENT, + FE_OAUTH_REQUESTING_TOKEN, + FE_OAUTH_SERVER_ERROR, +}; + +/* + * This struct is exported to the libpq-oauth module. If changes are needed + * during backports to stable branches, please keep ABI compatibility (no + * changes to existing members, add new members at the end, etc.). + */ +typedef struct +{ + enum fe_oauth_step step; + + PGconn *conn; + void *async_ctx; + + void *builtin_flow; +} fe_oauth_state; + +extern void pqClearOAuthToken(PGconn *conn); +extern bool oauth_unsafe_debugging_enabled(void); +extern bool use_builtin_flow(PGconn *conn, fe_oauth_state *state); + +/* Mechanisms in fe-auth-oauth.c */ +extern const pg_fe_sasl_mech pg_oauth_mech; + +#endif /* FE_AUTH_OAUTH_H */ diff --git a/src/interfaces/libpq/fe-auth-sasl.h b/src/interfaces/libpq/fe-auth-sasl.h index 4eecf53a15030..f06f547c07dab 100644 --- a/src/interfaces/libpq/fe-auth-sasl.h +++ b/src/interfaces/libpq/fe-auth-sasl.h @@ -8,7 +8,7 @@ * * See src/include/libpq/sasl.h for the backend counterpart. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/fe-auth-sasl.h @@ -30,12 +30,13 @@ typedef enum SASL_COMPLETE = 0, SASL_FAILED, SASL_CONTINUE, + SASL_ASYNC, } SASLStatus; /* * Frontend SASL mechanism callbacks. * - * To implement a frontend mechanism, declare a pg_be_sasl_mech struct with + * To implement a frontend mechanism, declare a pg_fe_sasl_mech struct with * appropriate callback implementations, then hook it into conn->sasl during * pg_SASL_init()'s mechanism negotiation. */ @@ -77,6 +78,8 @@ typedef struct pg_fe_sasl_mech * * state: The opaque mechanism state returned by init() * + * final: true if the server has sent a final exchange outcome + * * input: The challenge data sent by the server, or NULL when * generating a client-first initial response (that is, when * the server expects the client to send a message to start @@ -101,12 +104,18 @@ typedef struct pg_fe_sasl_mech * * SASL_CONTINUE: The output buffer is filled with a client response. * Additional server challenge is expected + * SASL_ASYNC: Some asynchronous processing external to the + * connection needs to be done before a response can be + * generated. The mechanism is responsible for setting up + * conn->async_auth/cleanup_async_auth appropriately + * before returning. * SASL_COMPLETE: The SASL exchange has completed successfully. * SASL_FAILED: The exchange has failed and the connection should be * dropped. *-------- */ - SASLStatus (*exchange) (void *state, char *input, int inputlen, + SASLStatus (*exchange) (void *state, bool final, + char *input, int inputlen, char **output, int *outputlen); /*-------- diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c index 0bb820e0d9741..f6d6a5aa977b8 100644 --- a/src/interfaces/libpq/fe-auth-scram.c +++ b/src/interfaces/libpq/fe-auth-scram.c @@ -3,7 +3,7 @@ * fe-auth-scram.c * The front-end (client) implementation of SCRAM authentication. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -24,7 +24,8 @@ /* The exported SCRAM callback mechanism. */ static void *scram_init(PGconn *conn, const char *password, const char *sasl_mechanism); -static SASLStatus scram_exchange(void *opaq, char *input, int inputlen, +static SASLStatus scram_exchange(void *opaq, bool final, + char *input, int inputlen, char **output, int *outputlen); static bool scram_channel_bound(void *opaq); static void scram_free(void *opaq); @@ -69,14 +70,14 @@ typedef struct /* These come from the server-first message */ char *server_first_message; - char *salt; + uint8 *salt; int saltlen; int iterations; char *nonce; /* These come from the server-final message */ char *server_final_message; - char ServerSignature[SCRAM_MAX_KEY_LEN]; + uint8 ServerSignature[SCRAM_MAX_KEY_LEN]; } fe_scram_state; static bool read_server_first_message(fe_scram_state *state, char *input); @@ -119,25 +120,28 @@ scram_init(PGconn *conn, return NULL; } - /* Normalize the password with SASLprep, if possible */ - rc = pg_saslprep(password, &prep_password); - if (rc == SASLPREP_OOM) - { - free(state->sasl_mechanism); - free(state); - return NULL; - } - if (rc != SASLPREP_SUCCESS) + if (password) { - prep_password = strdup(password); - if (!prep_password) + /* Normalize the password with SASLprep, if possible */ + rc = pg_saslprep(password, &prep_password); + if (rc == SASLPREP_OOM) { free(state->sasl_mechanism); free(state); return NULL; } + if (rc != SASLPREP_SUCCESS) + { + prep_password = strdup(password); + if (!prep_password) + { + free(state->sasl_mechanism); + free(state); + return NULL; + } + } + state->password = prep_password; } - state->password = prep_password; return state; } @@ -202,7 +206,8 @@ scram_free(void *opaq) * Exchange a SCRAM message with backend. */ static SASLStatus -scram_exchange(void *opaq, char *input, int inputlen, +scram_exchange(void *opaq, bool final, + char *input, int inputlen, char **output, int *outputlen) { fe_scram_state *state = (fe_scram_state *) opaq; @@ -345,7 +350,7 @@ static char * build_client_first_message(fe_scram_state *state) { PGconn *conn = state->conn; - char raw_nonce[SCRAM_RAW_NONCE_LEN + 1]; + uint8 raw_nonce[SCRAM_RAW_NONCE_LEN + 1]; char *result; int channel_info_len; int encoded_len; @@ -508,7 +513,7 @@ build_client_final_message(fe_scram_state *state) free(cbind_input); goto oom_error; } - encoded_cbind_len = pg_b64_encode(cbind_input, cbind_input_len, + encoded_cbind_len = pg_b64_encode((uint8 *) cbind_input, cbind_input_len, buf.data + buf.len, encoded_cbind_len); if (encoded_cbind_len < 0) @@ -569,7 +574,7 @@ build_client_final_message(fe_scram_state *state) encoded_len = pg_b64_enc_len(state->key_length); if (!enlargePQExpBuffer(&buf, encoded_len)) goto oom_error; - encoded_len = pg_b64_encode((char *) client_proof, + encoded_len = pg_b64_encode(client_proof, state->key_length, buf.data + buf.len, encoded_len); @@ -689,7 +694,7 @@ read_server_final_message(fe_scram_state *state, char *input) { PGconn *conn = state->conn; char *encoded_server_signature; - char *decoded_server_signature; + uint8 *decoded_server_signature; int server_signature_len; state->server_final_message = strdup(input); @@ -775,20 +780,31 @@ calculate_client_proof(fe_scram_state *state, return false; } - /* - * Calculate SaltedPassword, and store it in 'state' so that we can reuse - * it later in verify_server_signature. - */ - if (scram_SaltedPassword(state->password, state->hash_type, - state->key_length, state->salt, state->saltlen, - state->iterations, state->SaltedPassword, - errstr) < 0 || - scram_ClientKey(state->SaltedPassword, state->hash_type, - state->key_length, ClientKey, errstr) < 0 || - scram_H(ClientKey, state->hash_type, state->key_length, - StoredKey, errstr) < 0) - { - /* errstr is already filled here */ + if (state->conn->scram_client_key_binary) + { + memcpy(ClientKey, state->conn->scram_client_key_binary, SCRAM_MAX_KEY_LEN); + } + else + { + /* + * Calculate SaltedPassword, and store it in 'state' so that we can + * reuse it later in verify_server_signature. + */ + if (scram_SaltedPassword(state->password, state->hash_type, + state->key_length, state->salt, state->saltlen, + state->iterations, state->SaltedPassword, + errstr) < 0 || + scram_ClientKey(state->SaltedPassword, state->hash_type, + state->key_length, ClientKey, errstr) < 0) + { + /* errstr is already filled here */ + pg_hmac_free(ctx); + return false; + } + } + + if (scram_H(ClientKey, state->hash_type, state->key_length, StoredKey, errstr) < 0) + { pg_hmac_free(ctx); return false; } @@ -841,12 +857,19 @@ verify_server_signature(fe_scram_state *state, bool *match, return false; } - if (scram_ServerKey(state->SaltedPassword, state->hash_type, - state->key_length, ServerKey, errstr) < 0) + if (state->conn->scram_server_key_binary) { - /* errstr is filled already */ - pg_hmac_free(ctx); - return false; + memcpy(ServerKey, state->conn->scram_server_key_binary, SCRAM_MAX_KEY_LEN); + } + else + { + if (scram_ServerKey(state->SaltedPassword, state->hash_type, + state->key_length, ServerKey, errstr) < 0) + { + /* errstr is filled already */ + pg_hmac_free(ctx); + return false; + } } /* calculate ServerSignature */ @@ -893,7 +916,7 @@ pg_fe_scram_build_secret(const char *password, int iterations, const char **errs { char *prep_password; pg_saslprep_rc rc; - char saltbuf[SCRAM_DEFAULT_SALT_LEN]; + uint8 saltbuf[SCRAM_DEFAULT_SALT_LEN]; char *result; /* diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 3b25d8afda475..84a042269dec9 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -3,7 +3,7 @@ * fe-auth.c * The front-end (client) authorization routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -28,6 +28,7 @@ #include #include #include +#include #include /* for MAXHOSTNAMELEN on most */ #include #ifdef HAVE_SYS_UCRED_H @@ -39,9 +40,11 @@ #endif #include "common/md5.h" +#include "common/oauth-common.h" #include "common/scram-common.h" #include "fe-auth.h" #include "fe-auth-sasl.h" +#include "fe-auth-oauth.h" #include "libpq-fe.h" #ifdef ENABLE_GSS @@ -94,6 +97,10 @@ pg_GSS_continue(PGconn *conn, int payloadlen) ginbuf.value = NULL; } + /* finished parsing, trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + /* Only try to acquire credentials if GSS delegation isn't disabled. */ if (!pg_GSS_have_cred_cache(&conn->gcred)) conn->gcred = GSS_C_NO_CREDENTIAL; @@ -124,6 +131,7 @@ pg_GSS_continue(PGconn *conn, int payloadlen) * first or subsequent packet, just send the same kind of password * packet. */ + conn->current_auth_response = AUTH_RESPONSE_GSS; if (pqPacketSend(conn, PqMsg_GSSResponse, goutbuf.value, goutbuf.length) != STATUS_OK) { @@ -257,6 +265,10 @@ pg_SSPI_continue(PGconn *conn, int payloadlen) InBuffers[0].BufferType = SECBUFFER_TOKEN; } + /* finished parsing, trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; @@ -324,6 +336,7 @@ pg_SSPI_continue(PGconn *conn, int payloadlen) */ if (outbuf.pBuffers[0].cbBuffer > 0) { + conn->current_auth_response = AUTH_RESPONSE_GSS; if (pqPacketSend(conn, PqMsg_GSSResponse, outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer)) { @@ -419,7 +432,7 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen) * Initialize SASL authentication exchange. */ static int -pg_SASL_init(PGconn *conn, int payloadlen) +pg_SASL_init(PGconn *conn, int payloadlen, bool *async) { char *initialresponse = NULL; int initialresponselen; @@ -437,7 +450,7 @@ pg_SASL_init(PGconn *conn, int payloadlen) goto error; } - if (conn->sasl_state) + if (conn->sasl_state && !conn->async_auth) { libpq_append_conn_error(conn, "duplicate SASL authentication request"); goto error; @@ -524,6 +537,13 @@ pg_SASL_init(PGconn *conn, int payloadlen) conn->sasl = &pg_scram_mech; conn->password_needed = true; } + else if (strcmp(mechanism_buf.data, OAUTHBEARER_NAME) == 0 && + !selected_mechanism) + { + selected_mechanism = OAUTHBEARER_NAME; + conn->sasl = &pg_oauth_mech; + conn->password_needed = false; + } } if (!selected_mechanism) @@ -532,6 +552,28 @@ pg_SASL_init(PGconn *conn, int payloadlen) goto error; } + /* Make sure require_auth is satisfied. */ + if (conn->require_auth) + { + bool allowed = false; + + for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++) + { + if (conn->sasl == conn->allowed_sasl_mechs[i]) + { + allowed = true; + break; + } + } + + if (!allowed) + { + libpq_append_conn_error(conn, "authentication method requirement \"%s\" failed: server requested %s authentication", + conn->require_auth, selected_mechanism); + goto error; + } + } + if (conn->channel_binding[0] == 'r' && /* require */ strcmp(selected_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0) { @@ -548,7 +590,7 @@ pg_SASL_init(PGconn *conn, int payloadlen) * First, select the password to use for the exchange, complaining if * there isn't one and the selected SASL mechanism needs it. */ - if (conn->password_needed) + if (conn->password_needed && !conn->scram_client_key_binary) { password = conn->connhost[conn->whichhost].password; if (password == NULL) @@ -561,28 +603,60 @@ pg_SASL_init(PGconn *conn, int payloadlen) } } + /* finished parsing, trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + Assert(conn->sasl); - /* - * Initialize the SASL state information with all the information gathered - * during the initial exchange. - * - * Note: Only tls-unique is supported for the moment. - */ - conn->sasl_state = conn->sasl->init(conn, - password, - selected_mechanism); if (!conn->sasl_state) - goto oom_error; + { + /* + * Initialize the SASL state information with all the information + * gathered during the initial exchange. + * + * Note: Only tls-unique is supported for the moment. + */ + conn->sasl_state = conn->sasl->init(conn, + password, + selected_mechanism); + if (!conn->sasl_state) + goto oom_error; + } + else + { + /* + * This is only possible if we're returning from an async loop. + * Disconnect it now. + */ + Assert(conn->async_auth); + conn->async_auth = NULL; + } /* Get the mechanism-specific Initial Client Response, if any */ - status = conn->sasl->exchange(conn->sasl_state, + status = conn->sasl->exchange(conn->sasl_state, false, NULL, -1, &initialresponse, &initialresponselen); if (status == SASL_FAILED) goto error; + if (status == SASL_ASYNC) + { + /* + * The mechanism should have set up the necessary callbacks; all we + * need to do is signal the caller. + * + * In non-assertion builds, this postcondition is enforced at time of + * use in PQconnectPoll(). + */ + Assert(conn->async_auth); + Assert(conn->cleanup_async_auth); + + *async = true; + return STATUS_OK; + } + /* * Build a SASLInitialResponse message, and send it. */ @@ -597,8 +671,10 @@ pg_SASL_init(PGconn *conn, int payloadlen) if (pqPutnchar(initialresponse, initialresponselen, conn)) goto error; } + conn->current_auth_response = AUTH_RESPONSE_SASL_INITIAL; if (pqPutMsgEnd(conn)) goto error; + if (pqFlush(conn)) goto error; @@ -625,7 +701,7 @@ pg_SASL_init(PGconn *conn, int payloadlen) * the protocol. */ static int -pg_SASL_continue(PGconn *conn, int payloadlen, bool final) +pg_SASL_continue(PGconn *conn, int payloadlen, bool final, bool *async) { char *output; int outputlen; @@ -647,14 +723,33 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final) free(challenge); return STATUS_ERROR; } + + /* finished parsing, trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + /* For safety and convenience, ensure the buffer is NULL-terminated. */ challenge[payloadlen] = '\0'; - status = conn->sasl->exchange(conn->sasl_state, + status = conn->sasl->exchange(conn->sasl_state, final, challenge, payloadlen, &output, &outputlen); free(challenge); /* don't need the input anymore */ + if (status == SASL_ASYNC) + { + /* + * The mechanism should have set up the necessary callbacks; all we + * need to do is signal the caller. + */ + *async = true; + + /* + * The mechanism may optionally generate some output to send before + * switching over to async auth, so continue onwards. + */ + } + if (final && status == SASL_CONTINUE) { if (outputlen != 0) @@ -683,6 +778,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final) /* * Send the SASL response to the server. */ + conn->current_auth_response = AUTH_RESPONSE_SASL; res = pqPacketSend(conn, PqMsg_SASLResponse, output, outputlen); free(output); @@ -702,7 +798,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) int ret; char *crypt_pwd = NULL; const char *pwd_to_send; - char md5Salt[4]; + uint8 md5Salt[4]; /* Read the salt from the AuthenticationMD5Password message. */ if (areq == AUTH_REQ_MD5) @@ -711,6 +807,10 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) return STATUS_ERROR; /* shouldn't happen */ } + /* finished parsing, trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + /* Encrypt the password if needed. */ switch (areq) @@ -729,7 +829,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) } crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1; - if (!pg_md5_encrypt(password, conn->pguser, + if (!pg_md5_encrypt(password, (uint8 *) conn->pguser, strlen(conn->pguser), crypt_pwd2, &errstr)) { @@ -754,6 +854,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) default: return STATUS_ERROR; } + conn->current_auth_response = AUTH_RESPONSE_PASSWORD; ret = pqPacketSend(conn, PqMsg_PasswordMessage, pwd_to_send, strlen(pwd_to_send) + 1); free(crypt_pwd); @@ -956,12 +1057,18 @@ check_expected_areq(AuthRequest areq, PGconn *conn) * it. We are responsible for reading any remaining extra data, specific * to the authentication method. 'payloadlen' is the remaining length in * the message. + * + * If *async is set to true on return, the client doesn't yet have enough + * information to respond, and the caller must temporarily switch to + * conn->async_auth() to continue driving the exchange. */ int -pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn) +pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn, bool *async) { int oldmsglen; + *async = false; + if (!check_expected_areq(areq, conn)) return STATUS_ERROR; @@ -1119,7 +1226,7 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn) * The request contains the name (as assigned by IANA) of the * authentication mechanism. */ - if (pg_SASL_init(conn, payloadlen) != STATUS_OK) + if (pg_SASL_init(conn, payloadlen, async) != STATUS_OK) { /* pg_SASL_init already set the error message */ return STATUS_ERROR; @@ -1128,23 +1235,33 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn) case AUTH_REQ_SASL_CONT: case AUTH_REQ_SASL_FIN: - if (conn->sasl_state == NULL) - { - appendPQExpBufferStr(&conn->errorMessage, - "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n"); - return STATUS_ERROR; - } - oldmsglen = conn->errorMessage.len; - if (pg_SASL_continue(conn, payloadlen, - (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK) { - /* Use this message if pg_SASL_continue didn't supply one */ - if (conn->errorMessage.len == oldmsglen) + bool final = false; + + if (conn->sasl_state == NULL) + { appendPQExpBufferStr(&conn->errorMessage, - "fe_sendauth: error in SASL authentication\n"); - return STATUS_ERROR; + "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n"); + return STATUS_ERROR; + } + oldmsglen = conn->errorMessage.len; + + if (areq == AUTH_REQ_SASL_FIN) + final = true; + + if (pg_SASL_continue(conn, payloadlen, final, async) != STATUS_OK) + { + /* + * Append a generic error message unless pg_SASL_continue + * did set a more specific one already. + */ + if (conn->errorMessage.len == oldmsglen) + appendPQExpBufferStr(&conn->errorMessage, + "fe_sendauth: error in SASL authentication\n"); + return STATUS_ERROR; + } + break; } - break; default: libpq_append_conn_error(conn, "authentication method %u not supported", areq); @@ -1176,7 +1293,10 @@ pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage) char username[256 + 1]; DWORD namesize = sizeof(username); #else - char pwdbuf[BUFSIZ]; + struct passwd pwbuf; + struct passwd *pw = NULL; + char buf[1024]; + int rc; #endif #ifdef WIN32 @@ -1187,10 +1307,20 @@ pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage) "user name lookup failure: error code %lu", GetLastError()); #else - if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf))) - name = pwdbuf; - else if (errorMessage) - appendPQExpBuffer(errorMessage, "%s\n", pwdbuf); + rc = getpwuid_r(user_id, &pwbuf, buf, sizeof buf, &pw); + if (rc != 0) + { + errno = rc; + if (errorMessage) + libpq_append_error(errorMessage, "could not look up local user ID %ld: %m", (long) user_id); + } + else if (!pw) + { + if (errorMessage) + libpq_append_error(errorMessage, "local user with ID %ld does not exist", (long) user_id); + } + else + name = pw->pw_name; #endif if (name) @@ -1239,7 +1369,7 @@ PQencryptPassword(const char *passwd, const char *user) if (!crypt_pwd) return NULL; - if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr)) + if (!pg_md5_encrypt(passwd, (uint8 *) user, strlen(user), crypt_pwd, &errstr)) { free(crypt_pwd); return NULL; @@ -1352,7 +1482,7 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, { const char *errstr = NULL; - if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd, &errstr)) + if (!pg_md5_encrypt(passwd, (uint8 *) user, strlen(user), crypt_pwd, &errstr)) { libpq_append_conn_error(conn, "could not encrypt password: %s", errstr); free(crypt_pwd); @@ -1452,3 +1582,23 @@ PQchangePassword(PGconn *conn, const char *user, const char *passwd) } } } + +PQauthDataHook_type PQauthDataHook = PQdefaultAuthDataHook; + +PQauthDataHook_type +PQgetAuthDataHook(void) +{ + return PQauthDataHook; +} + +void +PQsetAuthDataHook(PQauthDataHook_type hook) +{ + PQauthDataHook = hook ? hook : PQdefaultAuthDataHook; +} + +int +PQdefaultAuthDataHook(PGauthData type, PGconn *conn, void *data) +{ + return 0; /* handle nothing */ +} diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h index a18c5086882f0..de98e0d20c4b4 100644 --- a/src/interfaces/libpq/fe-auth.h +++ b/src/interfaces/libpq/fe-auth.h @@ -4,7 +4,7 @@ * * Definitions for network authentication routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/fe-auth.h @@ -18,8 +18,12 @@ #include "libpq-int.h" +extern PQauthDataHook_type PQauthDataHook; + + /* Prototypes for functions in fe-auth.c */ -extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn); +extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn, + bool *async); extern char *pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage); extern char *pg_fe_getauthname(PQExpBuffer errorMessage); diff --git a/src/interfaces/libpq/fe-cancel.c b/src/interfaces/libpq/fe-cancel.c index 213a6f43c2d76..cd3102346bfa7 100644 --- a/src/interfaces/libpq/fe-cancel.c +++ b/src/interfaces/libpq/fe-cancel.c @@ -1,9 +1,9 @@ /*------------------------------------------------------------------------- * * fe-cancel.c - * functions related to setting up a connection to the backend + * functions related to query cancellation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -41,7 +41,6 @@ struct pg_cancel { SockAddr raddr; /* Remote address */ int be_pid; /* PID of to-be-canceled backend */ - int be_key; /* cancel key of to-be-canceled backend */ int pgtcp_user_timeout; /* tcp user timeout */ int keepalives; /* use TCP keepalives? */ int keepalives_idle; /* time between TCP keepalives */ @@ -49,6 +48,10 @@ struct pg_cancel * retransmits */ int keepalives_count; /* maximum number of TCP keepalive * retransmits */ + + /* Pre-constructed cancel request packet starts here */ + int32 cancel_pkt_len; /* in network byte order */ + char cancel_req[FLEXIBLE_ARRAY_MEMBER]; /* CancelRequestPacket */ }; @@ -83,6 +86,13 @@ PQcancelCreate(PGconn *conn) return (PGcancelConn *) cancelConn; } + /* Check that we have received a cancellation key */ + if (conn->be_cancel_key_len == 0) + { + libpq_append_conn_error(cancelConn, "no cancellation key received"); + return (PGcancelConn *) cancelConn; + } + /* * Indicate that this connection is used to send a cancellation */ @@ -101,7 +111,15 @@ PQcancelCreate(PGconn *conn) * Copy cancellation token data from the original connection */ cancelConn->be_pid = conn->be_pid; - cancelConn->be_key = conn->be_key; + if (conn->be_cancel_key != NULL) + { + cancelConn->be_cancel_key = malloc(conn->be_cancel_key_len); + if (cancelConn->be_cancel_key == NULL) + goto oom_error; + memcpy(cancelConn->be_cancel_key, conn->be_cancel_key, conn->be_cancel_key_len); + } + cancelConn->be_cancel_key_len = conn->be_cancel_key_len; + cancelConn->pversion = conn->pversion; /* * Cancel requests should not iterate over all possible hosts. The request @@ -349,6 +367,8 @@ PGcancel * PQgetCancel(PGconn *conn) { PGcancel *cancel; + int cancel_req_len; + CancelRequestPacket *req; if (!conn) return NULL; @@ -356,13 +376,17 @@ PQgetCancel(PGconn *conn) if (conn->sock == PGINVALID_SOCKET) return NULL; - cancel = malloc(sizeof(PGcancel)); + /* Check that we have received a cancellation key */ + if (conn->be_cancel_key_len == 0) + return NULL; + + cancel_req_len = offsetof(CancelRequestPacket, cancelAuthCode) + conn->be_cancel_key_len; + cancel = malloc(offsetof(PGcancel, cancel_req) + cancel_req_len); if (cancel == NULL) return NULL; memcpy(&cancel->raddr, &conn->raddr, sizeof(SockAddr)); - cancel->be_pid = conn->be_pid; - cancel->be_key = conn->be_key; + /* We use -1 to indicate an unset connection option */ cancel->pgtcp_user_timeout = -1; cancel->keepalives = -1; @@ -405,6 +429,13 @@ PQgetCancel(PGconn *conn) goto fail; } + req = (CancelRequestPacket *) &cancel->cancel_req; + req->cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); + req->backendPID = pg_hton32(conn->be_pid); + memcpy(req->cancelAuthCode, conn->be_cancel_key, conn->be_cancel_key_len); + /* include the length field itself in the length */ + cancel->cancel_pkt_len = pg_hton32(cancel_req_len + 4); + return cancel; fail: @@ -412,6 +443,42 @@ PQgetCancel(PGconn *conn) return NULL; } +/* + * PQsendCancelRequest + * Submit a CancelRequest message, but don't wait for it to finish + * + * Returns: 1 if successfully submitted + * 0 if error (conn->errorMessage is set) + */ +int +PQsendCancelRequest(PGconn *cancelConn) +{ + CancelRequestPacket req; + + /* Start the message. */ + if (pqPutMsgStart(0, cancelConn)) + return STATUS_ERROR; + + /* Send the message body. */ + memset(&req, 0, offsetof(CancelRequestPacket, cancelAuthCode)); + req.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); + req.backendPID = pg_hton32(cancelConn->be_pid); + if (pqPutnchar(&req, offsetof(CancelRequestPacket, cancelAuthCode), cancelConn)) + return STATUS_ERROR; + if (pqPutnchar(cancelConn->be_cancel_key, cancelConn->be_cancel_key_len, cancelConn)) + return STATUS_ERROR; + + /* Finish the message. */ + if (pqPutMsgEnd(cancelConn)) + return STATUS_ERROR; + + /* Flush to ensure backend gets it. */ + if (pqFlush(cancelConn)) + return STATUS_ERROR; + + return STATUS_OK; +} + /* PQfreeCancel: free a cancel structure */ void PQfreeCancel(PGcancel *cancel) @@ -465,11 +532,8 @@ PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) int save_errno = SOCK_ERRNO; pgsocket tmpsock = PGINVALID_SOCKET; int maxlen; - struct - { - uint32 packetlen; - CancelRequestPacket cp; - } crp; + char recvbuf; + int cancel_pkt_len; if (!cancel) { @@ -571,15 +635,15 @@ PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) goto cancel_errReturn; } - /* Create and send the cancel request packet. */ - - crp.packetlen = pg_hton32((uint32) sizeof(crp)); - crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); - crp.cp.backendPID = pg_hton32(cancel->be_pid); - crp.cp.cancelAuthCode = pg_hton32(cancel->be_key); + cancel_pkt_len = pg_ntoh32(cancel->cancel_pkt_len); retry4: - if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) + + /* + * Send the cancel request packet. It starts with the message length at + * cancel_pkt_len, followed by the actual packet. + */ + if (send(tmpsock, (char *) &cancel->cancel_pkt_len, cancel_pkt_len, 0) != cancel_pkt_len) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ @@ -596,7 +660,7 @@ PQcancel(PGcancel *cancel, char *errbuf, int errbufsize) * read to obtain any data, we are just waiting for EOF to be signaled. */ retry5: - if (recv(tmpsock, (char *) &crp, 1, 0) < 0) + if (recv(tmpsock, &recvbuf, 1, 0) < 0) { if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 360d9a454760f..ccb01aad36109 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3,7 +3,7 @@ * fe-connect.c * functions related to setting up a connection to the backend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -22,11 +22,13 @@ #include #include +#include "common/base64.h" #include "common/ip.h" #include "common/link-canary.h" #include "common/scram-common.h" #include "common/string.h" #include "fe-auth.h" +#include "fe-auth-oauth.h" #include "libpq-fe.h" #include "libpq-int.h" #include "mb/pg_wchar.h" @@ -50,6 +52,7 @@ #include #include #include +#include #endif #ifdef WIN32 @@ -155,6 +158,12 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options, * "*" Password field - hide value * "D" Debug option - don't show by default * + * NB: Server-side clients -- dblink, postgres_fdw, libpqrcv -- use dispchar to + * determine which options to expose to end users, and how. Changing dispchar + * has compatibility and security implications for those clients. For example, + * postgres_fdw will attach a "*" option to USER MAPPING instead of the default + * SERVER, and it disallows setting "D" options entirely. + * * PQconninfoOptions[] is a constant static array that we use to initialize * a dynamically allocated working copy. All the "val" fields in * PQconninfoOptions[] *must* be NULL. In a working copy, non-null "val" @@ -189,7 +198,8 @@ typedef struct _internalPQconninfoOption static const internalPQconninfoOption PQconninfoOptions[] = { {"service", "PGSERVICE", NULL, NULL, - "Database-Service", "", 20, -1}, + "Database-Service", "", 20, + offsetof(struct pg_conn, pgservice)}, {"user", "PGUSER", NULL, NULL, "Database-User", "", 20, @@ -321,6 +331,16 @@ static const internalPQconninfoOption PQconninfoOptions[] = { "Require-Auth", "", 14, /* sizeof("scram-sha-256") == 14 */ offsetof(struct pg_conn, require_auth)}, + {"min_protocol_version", "PGMINPROTOCOLVERSION", + NULL, NULL, + "Min-Protocol-Version", "", 6, /* sizeof("latest") = 6 */ + offsetof(struct pg_conn, min_protocol_version)}, + + {"max_protocol_version", "PGMAXPROTOCOLVERSION", + NULL, NULL, + "Max-Protocol-Version", "", 6, /* sizeof("latest") = 6 */ + offsetof(struct pg_conn, max_protocol_version)}, + {"ssl_min_protocol_version", "PGSSLMINPROTOCOLVERSION", "TLSv1.2", NULL, "SSL-Minimum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */ offsetof(struct pg_conn, ssl_min_protocol_version)}, @@ -364,6 +384,33 @@ static const internalPQconninfoOption PQconninfoOptions[] = { "Load-Balance-Hosts", "", 8, /* sizeof("disable") = 8 */ offsetof(struct pg_conn, load_balance_hosts)}, + {"scram_client_key", NULL, NULL, NULL, "SCRAM-Client-Key", "D", SCRAM_MAX_KEY_LEN * 2, + offsetof(struct pg_conn, scram_client_key)}, + + {"scram_server_key", NULL, NULL, NULL, "SCRAM-Server-Key", "D", SCRAM_MAX_KEY_LEN * 2, + offsetof(struct pg_conn, scram_server_key)}, + + /* OAuth v2 */ + {"oauth_issuer", NULL, NULL, NULL, + "OAuth-Issuer", "", 40, + offsetof(struct pg_conn, oauth_issuer)}, + + {"oauth_client_id", NULL, NULL, NULL, + "OAuth-Client-ID", "", 40, + offsetof(struct pg_conn, oauth_client_id)}, + + {"oauth_client_secret", NULL, NULL, NULL, + "OAuth-Client-Secret", "*", 40, + offsetof(struct pg_conn, oauth_client_secret)}, + + {"oauth_scope", NULL, NULL, NULL, + "OAuth-Scope", "", 15, + offsetof(struct pg_conn, oauth_scope)}, + + {"sslkeylogfile", NULL, NULL, NULL, + "SSL-Key-Log-File", "D", 64, + offsetof(struct pg_conn, sslkeylogfile)}, + /* Terminating entry --- MUST BE LAST */ {NULL, NULL, NULL, NULL, NULL, NULL, 0} @@ -387,6 +434,13 @@ static const PQEnvironmentOption EnvironmentOptions[] = } }; +static const pg_fe_sasl_mech *supported_sasl_mechs[] = +{ + &pg_scram_mech, + &pg_oauth_mech, +}; +#define SASL_MECHANISM_COUNT lengthof(supported_sasl_mechs) + /* The connection URI must start with either of the following designators: */ static const char uri_designator[] = "postgresql://"; static const char short_uri_designator[] = "postgres://"; @@ -449,6 +503,7 @@ static void pgpassfileWarning(PGconn *conn); static void default_threadlock(int acquire); static bool sslVerifyProtocolVersion(const char *version); static bool sslVerifyProtocolRange(const char *min, const char *max); +static bool pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn, const char *context); /* global variable because fe-auth.c needs to access it */ @@ -492,6 +547,19 @@ pqDropConnection(PGconn *conn, bool flushInput) conn->cmd_queue_recycle = NULL; /* Free authentication/encryption state */ + if (conn->cleanup_async_auth) + { + /* + * Any in-progress async authentication should be torn down first so + * that cleanup_async_auth() can depend on the other authentication + * state if necessary. + */ + conn->cleanup_async_auth(conn); + conn->cleanup_async_auth = NULL; + } + conn->async_auth = NULL; + /* cleanup_async_auth() should have done this, but make sure */ + conn->altsock = PGINVALID_SOCKET; #ifdef ENABLE_GSS { OM_uint32 min_s; @@ -620,6 +688,7 @@ pqDropServerData(PGconn *conn) /* Reset assorted other per-connection state */ conn->last_sqlstate[0] = '\0'; + conn->pversion_negotiated = false; conn->auth_req_received = false; conn->client_finished_auth = false; conn->password_needed = false; @@ -627,16 +696,22 @@ pqDropServerData(PGconn *conn) conn->write_failed = false; free(conn->write_err_msg); conn->write_err_msg = NULL; + conn->oauth_want_retry = false; /* - * Cancel connections need to retain their be_pid and be_key across + * Cancel connections need to retain their be_pid and be_cancel_key across * PQcancelReset invocations, otherwise they would not have access to the * secret token of the connection they are supposed to cancel. */ if (!conn->cancelRequest) { conn->be_pid = 0; - conn->be_key = 0; + if (conn->be_cancel_key != NULL) + { + free(conn->be_cancel_key); + conn->be_cancel_key = NULL; + } + conn->be_cancel_key_len = 0; } } @@ -947,7 +1022,7 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions) * Copy over option values from srcConn to dstConn * * Don't put anything cute here --- intelligence should be in - * connectOptions2 ... + * pqConnectOptions2 ... * * Returns true on success. On failure, returns false and sets error message of * dstConn. @@ -1108,6 +1183,57 @@ libpq_prng_init(PGconn *conn) pg_prng_seed(&conn->prng_state, rseed); } +/* + * Fills the connection's allowed_sasl_mechs list with all supported SASL + * mechanisms. + */ +static inline void +fill_allowed_sasl_mechs(PGconn *conn) +{ + /*--- + * We only support two mechanisms at the moment, so rather than deal with a + * linked list, conn->allowed_sasl_mechs is an array of static length. We + * rely on the compile-time assertion here to keep us honest. + * + * To add a new mechanism to require_auth, + * - add it to supported_sasl_mechs, + * - update the length of conn->allowed_sasl_mechs, + * - handle the new mechanism name in the require_auth portion of + * pqConnectOptions2(), below. + */ + StaticAssertDecl(lengthof(conn->allowed_sasl_mechs) == SASL_MECHANISM_COUNT, + "conn->allowed_sasl_mechs[] is not sufficiently large for holding all supported SASL mechanisms"); + + for (int i = 0; i < SASL_MECHANISM_COUNT; i++) + conn->allowed_sasl_mechs[i] = supported_sasl_mechs[i]; +} + +/* + * Clears the connection's allowed_sasl_mechs list. + */ +static inline void +clear_allowed_sasl_mechs(PGconn *conn) +{ + for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++) + conn->allowed_sasl_mechs[i] = NULL; +} + +/* + * Helper routine that searches the static allowed_sasl_mechs list for a + * specific mechanism. + */ +static inline int +index_of_allowed_sasl_mech(PGconn *conn, const pg_fe_sasl_mech *mech) +{ + for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++) + { + if (conn->allowed_sasl_mechs[i] == mech) + return i; + } + + return -1; +} + /* * pqConnectOptions2 * @@ -1349,17 +1475,19 @@ pqConnectOptions2(PGconn *conn) bool negated = false; /* - * By default, start from an empty set of allowed options and add to - * it. + * By default, start from an empty set of allowed methods and + * mechanisms, and add to it. */ conn->auth_required = true; conn->allowed_auth_methods = 0; + clear_allowed_sasl_mechs(conn); for (first = true, more = true; more; first = false) { char *method, *part; - uint32 bits; + uint32 bits = 0; + const pg_fe_sasl_mech *mech = NULL; part = parse_comma_separated_list(&s, &more); if (part == NULL) @@ -1375,11 +1503,12 @@ pqConnectOptions2(PGconn *conn) if (first) { /* - * Switch to a permissive set of allowed options, and - * subtract from it. + * Switch to a permissive set of allowed methods and + * mechanisms, and subtract from it. */ conn->auth_required = false; conn->allowed_auth_methods = -1; + fill_allowed_sasl_mechs(conn); } else if (!negated) { @@ -1404,6 +1533,10 @@ pqConnectOptions2(PGconn *conn) return false; } + /* + * First group: methods that can be handled solely with the + * authentication request codes. + */ if (strcmp(method, "password") == 0) { bits = (1 << AUTH_REQ_PASSWORD); @@ -1422,13 +1555,25 @@ pqConnectOptions2(PGconn *conn) bits = (1 << AUTH_REQ_SSPI); bits |= (1 << AUTH_REQ_GSS_CONT); } + + /* + * Next group: SASL mechanisms. All of these use the same request + * codes, so the list of allowed mechanisms is tracked separately. + * + * supported_sasl_mechs must contain all mechanisms handled here. + */ else if (strcmp(method, "scram-sha-256") == 0) { - /* This currently assumes that SCRAM is the only SASL method. */ - bits = (1 << AUTH_REQ_SASL); - bits |= (1 << AUTH_REQ_SASL_CONT); - bits |= (1 << AUTH_REQ_SASL_FIN); + mech = &pg_scram_mech; + } + else if (strcmp(method, "oauth") == 0) + { + mech = &pg_oauth_mech; } + + /* + * Final group: meta-options. + */ else if (strcmp(method, "none") == 0) { /* @@ -1464,20 +1609,68 @@ pqConnectOptions2(PGconn *conn) return false; } - /* Update the bitmask. */ - if (negated) + if (mech) { - if ((conn->allowed_auth_methods & bits) == 0) - goto duplicate; + /* + * Update the mechanism set only. The method bitmask will be + * updated for SASL further down. + */ + Assert(!bits); + + if (negated) + { + /* Remove the existing mechanism from the list. */ + i = index_of_allowed_sasl_mech(conn, mech); + if (i < 0) + goto duplicate; + + conn->allowed_sasl_mechs[i] = NULL; + } + else + { + /* + * Find a space to put the new mechanism (after making + * sure it's not already there). + */ + i = index_of_allowed_sasl_mech(conn, mech); + if (i >= 0) + goto duplicate; + + i = index_of_allowed_sasl_mech(conn, NULL); + if (i < 0) + { + /* Should not happen; the pointer list is corrupted. */ + Assert(false); + + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, + "internal error: no space in allowed_sasl_mechs"); + free(part); + return false; + } - conn->allowed_auth_methods &= ~bits; + conn->allowed_sasl_mechs[i] = mech; + } } else { - if ((conn->allowed_auth_methods & bits) == bits) - goto duplicate; + /* Update the method bitmask. */ + Assert(bits); + + if (negated) + { + if ((conn->allowed_auth_methods & bits) == 0) + goto duplicate; - conn->allowed_auth_methods |= bits; + conn->allowed_auth_methods &= ~bits; + } + else + { + if ((conn->allowed_auth_methods & bits) == bits) + goto duplicate; + + conn->allowed_auth_methods |= bits; + } } free(part); @@ -1496,6 +1689,36 @@ pqConnectOptions2(PGconn *conn) free(part); return false; } + + /* + * Finally, allow SASL authentication requests if (and only if) we've + * allowed any mechanisms. + */ + { + bool allowed = false; + const uint32 sasl_bits = + (1 << AUTH_REQ_SASL) + | (1 << AUTH_REQ_SASL_CONT) + | (1 << AUTH_REQ_SASL_FIN); + + for (i = 0; i < lengthof(conn->allowed_sasl_mechs); i++) + { + if (conn->allowed_sasl_mechs[i]) + { + allowed = true; + break; + } + } + + /* + * For the standard case, add the SASL bits to the (default-empty) + * set if needed. For the negated case, remove them. + */ + if (!negated && allowed) + conn->allowed_auth_methods |= sasl_bits; + else if (negated && !allowed) + conn->allowed_auth_methods &= ~sasl_bits; + } } /* @@ -1616,7 +1839,7 @@ pqConnectOptions2(PGconn *conn) * sslmode='allow' or sslmode='disable' either. If a user goes through * the trouble of setting sslnegotiation='direct', they probably * intend to use SSL, and sslmode=disable or allow is probably a user - * user mistake anyway. + * mistake anyway. */ if (conn->sslnegotiation[0] == 'd' && conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v') @@ -1791,6 +2014,52 @@ pqConnectOptions2(PGconn *conn) else conn->target_server_type = SERVER_TYPE_ANY; + if (conn->scram_client_key) + { + int len; + + len = pg_b64_dec_len(strlen(conn->scram_client_key)); + conn->scram_client_key_binary = malloc(len); + if (!conn->scram_client_key_binary) + goto oom_error; + len = pg_b64_decode(conn->scram_client_key, strlen(conn->scram_client_key), + conn->scram_client_key_binary, len); + if (len < 0) + { + libpq_append_conn_error(conn, "invalid SCRAM client key"); + return false; + } + if (len != SCRAM_MAX_KEY_LEN) + { + libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len); + return false; + } + conn->scram_client_key_len = len; + } + + if (conn->scram_server_key) + { + int len; + + len = pg_b64_dec_len(strlen(conn->scram_server_key)); + conn->scram_server_key_binary = malloc(len); + if (!conn->scram_server_key_binary) + goto oom_error; + len = pg_b64_decode(conn->scram_server_key, strlen(conn->scram_server_key), + conn->scram_server_key_binary, len); + if (len < 0) + { + libpq_append_conn_error(conn, "invalid SCRAM server key"); + return false; + } + if (len != SCRAM_MAX_KEY_LEN) + { + libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len); + return false; + } + conn->scram_server_key_len = len; + } + /* * validate load_balance_hosts option, and set load_balance_type */ @@ -1834,6 +2103,48 @@ pqConnectOptions2(PGconn *conn) } } + if (conn->min_protocol_version) + { + if (!pqParseProtocolVersion(conn->min_protocol_version, &conn->min_pversion, conn, "min_protocol_version")) + { + conn->status = CONNECTION_BAD; + return false; + } + } + else + { + conn->min_pversion = PG_PROTOCOL_EARLIEST; + } + + if (conn->max_protocol_version) + { + if (!pqParseProtocolVersion(conn->max_protocol_version, &conn->max_pversion, conn, "max_protocol_version")) + { + conn->status = CONNECTION_BAD; + return false; + } + } + else + { + /* + * To not break connecting to older servers/poolers that do not yet + * support NegotiateProtocolVersion, default to the 3.0 protocol at + * least for a while longer. Except when min_protocol_version is set + * to something larger, then we might as well default to the latest. + */ + if (conn->min_pversion > PG_PROTOCOL(3, 0)) + conn->max_pversion = PG_PROTOCOL_LATEST; + else + conn->max_pversion = PG_PROTOCOL(3, 0); + } + + if (conn->min_pversion > conn->max_pversion) + { + conn->status = CONNECTION_BAD; + libpq_append_conn_error(conn, "min_protocol_version is greater than max_protocol_version"); + return false; + } + /* * Resolve special "auto" client_encoding from the locale */ @@ -2168,14 +2479,14 @@ connectFailureMessage(PGconn *conn, int errorno) static int useKeepalives(PGconn *conn) { - char *ep; int val; if (conn->keepalives == NULL) return 1; - val = strtol(conn->keepalives, &ep, 10); - if (*ep) + + if (!pqParseIntParam(conn->keepalives, &val, conn, "keepalives")) return -1; + return val != 0 ? 1 : 0; } @@ -2644,6 +2955,7 @@ PQconnectPoll(PGconn *conn) case CONNECTION_NEEDED: case CONNECTION_GSS_STARTUP: case CONNECTION_CHECK_TARGET: + case CONNECTION_AUTHENTICATING: break; default: @@ -2836,7 +3148,7 @@ PQconnectPoll(PGconn *conn) * must persist across individual connection attempts, but we must * reset them when we start to consider a new server. */ - conn->pversion = PG_PROTOCOL(3, 0); + conn->pversion = conn->max_pversion; conn->send_appname = true; conn->failed_enc_methods = 0; conn->current_enc_method = 0; @@ -3083,7 +3395,7 @@ PQconnectPoll(PGconn *conn) if (usekeepalives < 0) { - libpq_append_conn_error(conn, "keepalives parameter must be an integer"); + /* error is already reported */ err = 1; } else if (usekeepalives == 0) @@ -3341,16 +3653,6 @@ PQconnectPoll(PGconn *conn) #ifdef USE_SSL - /* - * Enable the libcrypto callbacks before checking if SSL needs - * to be done. This is done before sending the startup packet - * as depending on the type of authentication done, like MD5 - * or SCRAM that use cryptohashes, the callbacks would be - * required even without a SSL connection - */ - if (pqsecure_initialize(conn, false, true) < 0) - goto error_return; - /* * If SSL is enabled, start the SSL negotiation. We will come * back here after SSL encryption has been established, with @@ -3401,13 +3703,7 @@ PQconnectPoll(PGconn *conn) */ if (conn->cancelRequest) { - CancelRequestPacket cancelpacket; - - packetlen = sizeof(cancelpacket); - cancelpacket.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE); - cancelpacket.backendPID = pg_hton32(conn->be_pid); - cancelpacket.cancelAuthCode = pg_hton32(conn->be_key); - if (pqPacketSend(conn, 0, &cancelpacket, packetlen) != STATUS_OK) + if (PQsendCancelRequest(conn) != STATUS_OK) { libpq_append_conn_error(conn, "could not send cancel packet: %s", SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); @@ -3493,11 +3789,17 @@ PQconnectPoll(PGconn *conn) } if (SSLok == 'S') { + if (conn->Pfdebug) + pqTraceOutputCharResponse(conn, "SSLResponse", + SSLok); /* mark byte consumed */ conn->inStart = conn->inCursor; } else if (SSLok == 'N') { + if (conn->Pfdebug) + pqTraceOutputCharResponse(conn, "SSLResponse", + SSLok); /* mark byte consumed */ conn->inStart = conn->inCursor; @@ -3512,22 +3814,12 @@ PQconnectPoll(PGconn *conn) { /* * Server failure of some sort, such as failure to - * fork a backend process. We need to process and - * report the error message, which might be formatted - * according to either protocol 2 or protocol 3. - * Rather than duplicate the code for that, we flip - * into AWAITING_RESPONSE state and let the code there - * deal with it. Note we have *not* consumed the "E" - * byte here. - */ - conn->status = CONNECTION_AWAITING_RESPONSE; - - /* - * Don't fall back to a plaintext connection after - * reading the error. + * fork a backend process. Don't bother retrieving + * the error message; we should not trust it as the + * server has not been authenticated yet. */ - conn->failed_enc_methods |= conn->allowed_enc_methods & (~conn->current_enc_method); - goto keep_going; + libpq_append_conn_error(conn, "server sent an error response during SSL exchange"); + goto error_return; } else { @@ -3537,14 +3829,6 @@ PQconnectPoll(PGconn *conn) } } - /* - * Set up global SSL state if required. The crypto state has - * already been set if libpq took care of doing that, so there - * is no need to make that happen again. - */ - if (pqsecure_initialize(conn, true, false) != 0) - goto error_return; - /* * Begin or continue the SSL negotiation process. */ @@ -3611,13 +3895,9 @@ PQconnectPoll(PGconn *conn) { /* * Server failure of some sort, possibly protocol - * version support failure. We need to process and - * report the error message, which might be formatted - * according to either protocol 2 or protocol 3. - * Rather than duplicate the code for that, we flip - * into AWAITING_RESPONSE state and let the code there - * deal with it. Note we have *not* consumed the "E" - * byte here. + * version support failure. Don't bother retrieving + * the error message; we should not trust it anyway as + * the server has not authenticated yet. * * Note that unlike on an error response to * SSLRequest, we allow falling back to SSL or @@ -3626,8 +3906,8 @@ PQconnectPoll(PGconn *conn) * response might mean that we are connecting to a * pre-v12 server. */ - conn->status = CONNECTION_AWAITING_RESPONSE; - goto keep_going; + libpq_append_conn_error(conn, "server sent an error response during GSS encryption exchange"); + CONNECTION_FAILED(); } /* mark byte consumed */ @@ -3635,6 +3915,10 @@ PQconnectPoll(PGconn *conn) if (gss_ok == 'N') { + if (conn->Pfdebug) + pqTraceOutputCharResponse(conn, "GSSENCResponse", + gss_ok); + /* * The connection is still valid, so if it's OK to * continue without GSS, we can proceed using this @@ -3648,6 +3932,10 @@ PQconnectPoll(PGconn *conn) gss_ok); goto error_return; } + + if (conn->Pfdebug) + pqTraceOutputCharResponse(conn, "GSSENCResponse", + gss_ok); } /* Begin or continue GSSAPI negotiation */ @@ -3697,6 +3985,7 @@ PQconnectPoll(PGconn *conn) int avail; AuthRequest areq; int res; + bool async; /* * Scan the message from current point (note that if we find @@ -3783,7 +4072,7 @@ PQconnectPoll(PGconn *conn) return PGRES_POLLING_READING; } /* OK, we read the message; mark data consumed */ - conn->inStart = conn->inCursor; + pqParseDone(conn, conn->inCursor); /* * Before 7.2, the postmaster didn't always end its @@ -3833,7 +4122,7 @@ PQconnectPoll(PGconn *conn) goto error_return; } /* OK, we read the message; mark data consumed */ - conn->inStart = conn->inCursor; + pqParseDone(conn, conn->inCursor); /* * If error is "cannot connect now", try the next host if @@ -3854,16 +4143,25 @@ PQconnectPoll(PGconn *conn) CONNECTION_FAILED(); } + /* Handle NegotiateProtocolVersion */ else if (beresp == PqMsg_NegotiateProtocolVersion) { + if (conn->pversion_negotiated) + { + libpq_append_conn_error(conn, "received duplicate protocol negotiation message"); + goto error_return; + } if (pqGetNegotiateProtocolVersion3(conn)) { - libpq_append_conn_error(conn, "received invalid protocol negotiation message"); + /* pqGetNegotiateProtocolVersion3 set error already */ goto error_return; } + conn->pversion_negotiated = true; + /* OK, we read the message; mark data consumed */ - conn->inStart = conn->inCursor; - goto error_return; + pqParseDone(conn, conn->inCursor); + + goto keep_going; } /* It is an authentication request. */ @@ -3885,13 +4183,39 @@ PQconnectPoll(PGconn *conn) * Note that conn->pghost must be non-NULL if we are going to * avoid the Kerberos code doing a hostname look-up. */ - res = pg_fe_sendauth(areq, msgLength, conn); + res = pg_fe_sendauth(areq, msgLength, conn, &async); - /* OK, we have processed the message; mark data consumed */ + if (async && (res == STATUS_OK)) + { + /* + * We'll come back later once we're ready to respond. + * Don't consume the request yet. + */ + conn->status = CONNECTION_AUTHENTICATING; + goto keep_going; + } + + /* + * OK, we have processed the message; mark data consumed. We + * don't call pqParseDone here because we already traced this + * message inside pg_fe_sendauth. + */ conn->inStart = conn->inCursor; if (res != STATUS_OK) + { + /* + * OAuth connections may perform two-step discovery, where + * the first connection is a dummy. + */ + if (conn->sasl == &pg_oauth_mech && conn->oauth_want_retry) + { + need_new_connection = true; + goto keep_going; + } + goto error_return; + } /* * Just make sure that any data sent by pg_fe_sendauth is @@ -3918,6 +4242,69 @@ PQconnectPoll(PGconn *conn) goto keep_going; } + case CONNECTION_AUTHENTICATING: + { + PostgresPollingStatusType status; + + if (!conn->async_auth || !conn->cleanup_async_auth) + { + /* programmer error; should not happen */ + libpq_append_conn_error(conn, + "internal error: async authentication has no handler"); + goto error_return; + } + + /* Drive some external authentication work. */ + status = conn->async_auth(conn); + + if (status == PGRES_POLLING_FAILED) + goto error_return; + + if (status == PGRES_POLLING_OK) + { + /* Done. Tear down the async implementation. */ + conn->cleanup_async_auth(conn); + conn->cleanup_async_auth = NULL; + + /* + * Cleanup must unset altsock, both as an indication that + * it's been released, and to stop pqSocketCheck from + * looking at the wrong socket after async auth is done. + */ + if (conn->altsock != PGINVALID_SOCKET) + { + Assert(false); + libpq_append_conn_error(conn, + "internal error: async cleanup did not release polling socket"); + goto error_return; + } + + /* + * Reenter the authentication exchange with the server. We + * didn't consume the message that started external + * authentication, so it'll be reprocessed as if we just + * received it. + */ + conn->status = CONNECTION_AWAITING_RESPONSE; + + goto keep_going; + } + + /* + * Caller needs to poll some more. conn->async_auth() should + * have assigned an altsock to poll on. + */ + if (conn->altsock == PGINVALID_SOCKET) + { + Assert(false); + libpq_append_conn_error(conn, + "internal error: async authentication did not set a socket for polling"); + goto error_return; + } + + return status; + } + case CONNECTION_AUTH_OK: { /* @@ -4107,6 +4494,9 @@ PQconnectPoll(PGconn *conn) } } + /* Don't hold onto any OAuth tokens longer than necessary. */ + pqClearOAuthToken(conn); + /* * For non cancel requests we can release the address list * now. For cancel requests we never actually resolve @@ -4599,6 +4989,7 @@ pqMakeEmptyPGconn(void) conn->verbosity = PQERRORS_DEFAULT; conn->show_context = PQSHOW_CONTEXT_ERRORS; conn->sock = PGINVALID_SOCKET; + conn->altsock = PGINVALID_SOCKET; conn->Pfdebug = NULL; /* @@ -4658,21 +5049,19 @@ freePGconn(PGconn *conn) free(conn->events[i].name); } - release_conn_addrinfo(conn); - pqReleaseConnHosts(conn); - - free(conn->client_encoding_initial); - free(conn->events); + /* free everything not freed in pqClosePGconn */ free(conn->pghost); free(conn->pghostaddr); free(conn->pgport); free(conn->connect_timeout); free(conn->pgtcp_user_timeout); + free(conn->client_encoding_initial); free(conn->pgoptions); free(conn->appname); free(conn->fbappname); free(conn->dbName); free(conn->replication); + free(conn->pgservice); free(conn->pguser); if (conn->pgpass) { @@ -4687,8 +5076,9 @@ freePGconn(PGconn *conn) free(conn->keepalives_count); free(conn->sslmode); free(conn->sslnegotiation); - free(conn->sslcert); + free(conn->sslcompression); free(conn->sslkey); + free(conn->sslcert); if (conn->sslpassword) { explicit_bzero(conn->sslpassword, strlen(conn->sslpassword)); @@ -4698,24 +5088,40 @@ freePGconn(PGconn *conn) free(conn->sslrootcert); free(conn->sslcrl); free(conn->sslcrldir); - free(conn->sslcompression); free(conn->sslsni); free(conn->requirepeer); - free(conn->require_auth); - free(conn->ssl_min_protocol_version); - free(conn->ssl_max_protocol_version); free(conn->gssencmode); free(conn->krbsrvname); free(conn->gsslib); free(conn->gssdelegation); - free(conn->connip); + free(conn->min_protocol_version); + free(conn->max_protocol_version); + free(conn->ssl_min_protocol_version); + free(conn->ssl_max_protocol_version); + free(conn->target_session_attrs); + free(conn->require_auth); + free(conn->load_balance_hosts); + free(conn->scram_client_key); + free(conn->scram_server_key); + free(conn->sslkeylogfile); + free(conn->oauth_issuer); + free(conn->oauth_issuer_id); + free(conn->oauth_discovery_uri); + free(conn->oauth_client_id); + free(conn->oauth_client_secret); + free(conn->oauth_scope); /* Note that conn->Pfdebug is not ours to close or free */ - free(conn->write_err_msg); + free(conn->events); + pqReleaseConnHosts(conn); + free(conn->connip); + release_conn_addrinfo(conn); + free(conn->scram_client_key_binary); + free(conn->scram_server_key_binary); + /* if this is a cancel connection, be_cancel_key may still be allocated */ + free(conn->be_cancel_key); free(conn->inBuffer); free(conn->outBuffer); free(conn->rowBuf); - free(conn->target_session_attrs); - free(conn->load_balance_hosts); termPQExpBuffer(&conn->errorMessage); termPQExpBuffer(&conn->workBuffer); @@ -4744,6 +5150,7 @@ pqReleaseConnHosts(PGconn *conn) } } free(conn->connhost); + conn->connhost = NULL; } } @@ -4869,6 +5276,7 @@ pqClosePGconn(PGconn *conn) conn->asyncStatus = PGASYNC_IDLE; conn->xactStatus = PQTRANS_IDLE; conn->pipelineStatus = PQ_PIPELINE_OFF; + pqClearOAuthToken(conn); pqClearAsyncResult(conn); /* deallocate result */ pqClearConnErrorState(conn); @@ -6762,9 +7170,9 @@ conninfo_uri_parse_params(char *params, static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) { - char *buf; - char *p; - const char *q = str; + char *buf; /* result */ + char *p; /* output location */ + const char *q = str; /* input location */ buf = malloc(strlen(str) + 1); if (buf == NULL) @@ -6774,13 +7182,23 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) } p = buf; + /* skip leading whitespaces */ + for (const char *s = q; *s == ' '; s++) + { + q++; + continue; + } + for (;;) { if (*q != '%') { - /* copy and check for NUL terminator */ - if (!(*(p++) = *(q++))) - break; + /* if found a whitespace or NUL, the string ends */ + if (*q == ' ' || *q == '\0') + goto end; + + /* copy character */ + *(p++) = *(q++); } else { @@ -6816,6 +7234,28 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) } } +end: + + /* skip trailing whitespaces */ + for (const char *s = q; *s == ' '; s++) + { + q++; + continue; + } + + /* Not at the end of the string yet? Fail. */ + if (*q != '\0') + { + libpq_append_error(errorMessage, + "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead", + str); + free(buf); + return NULL; + } + + /* Copy NUL terminator */ + *p = '\0'; + return buf; } @@ -7021,6 +7461,14 @@ PQdb(const PGconn *conn) return conn->dbName; } +char * +PQservice(const PGconn *conn) +{ + if (!conn) + return NULL; + return conn->pgservice; +} + char * PQuser(const PGconn *conn) { @@ -7157,6 +7605,16 @@ PQprotocolVersion(const PGconn *conn) return PG_PROTOCOL_MAJOR(conn->pversion); } +int +PQfullProtocolVersion(const PGconn *conn) +{ + if (!conn) + return 0; + if (conn->status == CONNECTION_BAD) + return 0; + return PG_PROTOCOL_FULL(conn->pversion); +} + int PQserverVersion(const PGconn *conn) { @@ -7198,6 +7656,8 @@ PQsocket(const PGconn *conn) { if (!conn) return -1; + if (conn->altsock != PGINVALID_SOCKET) + return conn->altsock; return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1; } @@ -7438,7 +7898,9 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile) { FILE *fp; +#ifndef WIN32 struct stat stat_buf; +#endif PQExpBufferData buf; if (dbname == NULL || dbname[0] == '\0') @@ -7463,15 +7925,23 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname, port = DEF_PGPORT_STR; /* If password file cannot be opened, ignore it. */ - if (stat(pgpassfile, &stat_buf) != 0) + fp = fopen(pgpassfile, "r"); + if (fp == NULL) return NULL; #ifndef WIN32 + if (fstat(fileno(fp), &stat_buf) != 0) + { + fclose(fp); + return NULL; + } + if (!S_ISREG(stat_buf.st_mode)) { fprintf(stderr, libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"), pgpassfile); + fclose(fp); return NULL; } @@ -7481,6 +7951,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname, fprintf(stderr, libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"), pgpassfile); + fclose(fp); return NULL; } #else @@ -7491,10 +7962,6 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname, */ #endif - fp = fopen(pgpassfile, "r"); - if (fp == NULL) - return NULL; - /* Use an expansible buffer to accommodate any reasonable line length */ initPQExpBuffer(&buf); @@ -7682,10 +8149,24 @@ pqGetHomeDirectory(char *buf, int bufsize) const char *home; home = getenv("HOME"); - if (home == NULL || home[0] == '\0') - return pg_get_user_home_dir(geteuid(), buf, bufsize); - strlcpy(buf, home, bufsize); - return true; + if (home && home[0]) + { + strlcpy(buf, home, bufsize); + return true; + } + else + { + struct passwd pwbuf; + struct passwd *pw; + char tmpbuf[1024]; + int rc; + + rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw); + if (rc != 0 || !pw) + return false; + strlcpy(buf, pw->pw_dir, bufsize); + return true; + } #else char tmppath[MAX_PATH]; @@ -7743,6 +8224,38 @@ pqParseIntParam(const char *value, int *result, PGconn *conn, return false; } +/* + * Parse and try to interpret "value" as a ProtocolVersion value, and if + * successful, store it in *result. + */ +static bool +pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn, + const char *context) +{ + if (strcmp(value, "latest") == 0) + { + *result = PG_PROTOCOL_LATEST; + return true; + } + if (strcmp(value, "3.0") == 0) + { + *result = PG_PROTOCOL(3, 0); + return true; + } + + /* 3.1 never existed, we went straight from 3.0 to 3.2 */ + + if (strcmp(value, "3.2") == 0) + { + *result = PG_PROTOCOL(3, 2); + return true; + } + + libpq_append_conn_error(conn, "invalid %s value: \"%s\"", + context, value); + return false; +} + /* * To keep the API consistent, the locking stubs are always provided, even * if they are not required. diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 0d224a8524ed4..4256ae5c0cc5f 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -3,7 +3,7 @@ * fe-exec.c * functions related to sending a query down to the backend * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -4075,15 +4075,16 @@ PQescapeStringInternal(PGconn *conn, { const char *source = from; char *target = to; - size_t remaining = length; + size_t remaining = strnlen(from, length); + bool already_complained = false; if (error) *error = 0; - while (remaining > 0 && *source != '\0') + while (remaining > 0) { char c = *source; - int len; + int charlen; int i; /* Fast path for plain ASCII */ @@ -4100,38 +4101,69 @@ PQescapeStringInternal(PGconn *conn, } /* Slow path for possible multibyte characters */ - len = pg_encoding_mblen(encoding, source); + charlen = pg_encoding_mblen_or_incomplete(encoding, + source, remaining); - /* Copy the character */ - for (i = 0; i < len; i++) + if (remaining < charlen || + pg_encoding_verifymbchar(encoding, source, charlen) == -1) { - if (remaining == 0 || *source == '\0') - break; - *target++ = *source++; + /* + * Multibyte character is invalid. It's important to verify that + * as invalid multibyte characters could e.g. be used to "skip" + * over quote characters, e.g. when parsing + * character-by-character. + * + * Report an error if possible, and replace the character's first + * byte with an invalid sequence. The invalid sequence ensures + * that the escaped string will trigger an error on the + * server-side, even if we can't directly report an error here. + * + * This isn't *that* crucial when we can report an error to the + * caller; but if we can't or the caller ignores it, the caller + * will use this string unmodified and it needs to be safe for + * parsing. + * + * We know there's enough space for the invalid sequence because + * the "to" buffer needs to be at least 2 * length + 1 long, and + * at worst we're replacing a single input byte with two invalid + * bytes. + * + * It would be a bit faster to verify the whole string the first + * time we encounter a set highbit, but this way we can replace + * just the invalid data, which probably makes it easier for users + * to find the invalidly encoded portion of a larger string. + */ + if (error) + *error = 1; + if (conn && !already_complained) + { + if (remaining < charlen) + libpq_append_conn_error(conn, "incomplete multibyte character"); + else + libpq_append_conn_error(conn, "invalid multibyte character"); + /* Issue a complaint only once per string */ + already_complained = true; + } + + pg_encoding_set_invalid(encoding, target); + target += 2; + + /* + * Handle the following bytes as if this byte didn't exist. That's + * safer in case the subsequent bytes contain important characters + * for the caller (e.g. '>' in html). + */ + source++; remaining--; } - - /* - * If we hit premature end of string (ie, incomplete multibyte - * character), try to pad out to the correct length with spaces. We - * may not be able to pad completely, but we will always be able to - * insert at least one pad space (since we'd not have quoted a - * multibyte character). This should be enough to make a string that - * the server will error out on. - */ - if (i < len) + else { - if (error) - *error = 1; - if (conn) - libpq_append_conn_error(conn, "incomplete multibyte character"); - for (; i < len; i++) + /* Copy the character */ + for (i = 0; i < charlen; i++) { - if (((size_t) (target - to)) / 2 >= length) - break; - *target++ = ' '; + *target++ = *source++; + remaining--; } - break; } } @@ -4186,9 +4218,10 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) char *rp; int num_quotes = 0; /* single or double, depending on as_ident */ int num_backslashes = 0; - int input_len; - int result_size; + size_t input_len = strnlen(str, len); + size_t result_size; char quote_char = as_ident ? '"' : '\''; + bool validated_mb = false; /* We must have a connection, else fail immediately. */ if (!conn) @@ -4197,8 +4230,12 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) if (conn->cmd_queue_head == NULL) pqClearConnErrorState(conn); - /* Scan the string for characters that must be escaped. */ - for (s = str; (s - str) < len && *s != '\0'; ++s) + /* + * Scan the string for characters that must be escaped and for invalidly + * encoded data. + */ + s = str; + for (size_t remaining = input_len; remaining > 0; remaining--, s++) { if (*s == quote_char) ++num_quotes; @@ -4209,22 +4246,44 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) int charlen; /* Slow path for possible multibyte characters */ - charlen = pg_encoding_mblen(conn->client_encoding, s); + charlen = pg_encoding_mblen_or_incomplete(conn->client_encoding, + s, remaining); - /* Multibyte character overruns allowable length. */ - if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL) + if (charlen > remaining) { + /* Multibyte character overruns allowable length. */ libpq_append_conn_error(conn, "incomplete multibyte character"); return NULL; } + /* + * If we haven't already, check that multibyte characters are + * valid. It's important to verify that as invalid multi-byte + * characters could e.g. be used to "skip" over quote characters, + * e.g. when parsing character-by-character. + * + * We check validity once, for the whole remainder of the string, + * when we first encounter any multi-byte character. Some + * encodings have optimized implementations for longer strings. + */ + if (!validated_mb) + { + if (pg_encoding_verifymbstr(conn->client_encoding, s, remaining) + != remaining) + { + libpq_append_conn_error(conn, "invalid multibyte character"); + return NULL; + } + validated_mb = true; + } + /* Adjust s, bearing in mind that for loop will increment it. */ s += charlen - 1; + remaining -= charlen - 1; } } /* Allocate output buffer. */ - input_len = s - str; result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */ if (!as_ident && num_backslashes > 0) result_size += num_backslashes + 2; @@ -4269,7 +4328,8 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) } else { - for (s = str; s - str < input_len; ++s) + s = str; + for (size_t remaining = input_len; remaining > 0; remaining--, s++) { if (*s == quote_char || (!as_ident && *s == '\\')) { @@ -4287,6 +4347,7 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) *rp++ = *s; if (--i == 0) break; + remaining--; ++s; /* for loop will provide the final increment */ } } diff --git a/src/interfaces/libpq/fe-gssapi-common.c b/src/interfaces/libpq/fe-gssapi-common.c index 29d8fea6290c9..1ae2bd24c1dc3 100644 --- a/src/interfaces/libpq/fe-gssapi-common.c +++ b/src/interfaces/libpq/fe-gssapi-common.c @@ -3,7 +3,7 @@ * fe-gssapi-common.c * The front-end (client) GSSAPI common code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/interfaces/libpq/fe-gssapi-common.h b/src/interfaces/libpq/fe-gssapi-common.h index e3504811eb597..fe96b491bc26b 100644 --- a/src/interfaces/libpq/fe-gssapi-common.h +++ b/src/interfaces/libpq/fe-gssapi-common.h @@ -4,7 +4,7 @@ * * Definitions for GSSAPI common routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/fe-gssapi-common.h diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index c17585e38b784..05e17bed508ff 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -3,7 +3,7 @@ * fe-lobj.c * Front-end large object interface * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -43,8 +43,8 @@ static int lo_initialize(PGconn *conn); static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid); -static pg_int64 lo_hton64(pg_int64 host64); -static pg_int64 lo_ntoh64(pg_int64 net64); +static int64_t lo_hton64(int64_t host64); +static int64_t lo_ntoh64(int64_t net64); /* * lo_open @@ -192,7 +192,7 @@ lo_truncate(PGconn *conn, int fd, size_t len) * returns -1 upon failure */ int -lo_truncate64(PGconn *conn, int fd, pg_int64 len) +lo_truncate64(PGconn *conn, int fd, int64_t len) { PQArgBlock argv[2]; PGresult *res; @@ -381,12 +381,12 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence) * lo_lseek64 * change the current read or write location on a large object */ -pg_int64 -lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence) +int64_t +lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence) { PQArgBlock argv[3]; PGresult *res; - pg_int64 retval; + int64 retval; int result_len; if (lo_initialize(conn) < 0) @@ -544,10 +544,10 @@ lo_tell(PGconn *conn, int fd) * lo_tell64 * returns the current seek location of the large object */ -pg_int64 +int64_t lo_tell64(PGconn *conn, int fd) { - pg_int64 retval; + int64 retval; PQArgBlock argv[1]; PGresult *res; int result_len; @@ -870,7 +870,7 @@ lo_initialize(PGconn *conn) libpq_append_conn_error(conn, "out of memory"); return -1; } - MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs)); + MemSet(lobjfuncs, 0, sizeof(PGlobjfuncs)); /* * Execute the query to get all the functions at once. (Not all of them @@ -1019,12 +1019,12 @@ lo_initialize(PGconn *conn) * lo_hton64 * converts a 64-bit integer from host byte order to network byte order */ -static pg_int64 -lo_hton64(pg_int64 host64) +static int64_t +lo_hton64(int64_t host64) { union { - pg_int64 i64; + int64 i64; uint32 i32[2]; } swap; uint32 t; @@ -1044,15 +1044,15 @@ lo_hton64(pg_int64 host64) * lo_ntoh64 * converts a 64-bit integer from network byte order to host byte order */ -static pg_int64 -lo_ntoh64(pg_int64 net64) +static int64_t +lo_ntoh64(int64_t net64) { union { - pg_int64 i64; + int64 i64; uint32 i32[2]; } swap; - pg_int64 result; + int64 result; swap.i64 = net64; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index f235bfbb41fb5..dca44fdc5d2f3 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -19,7 +19,7 @@ * routines. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -67,7 +67,7 @@ PQlibVersion(void) /* - * pqGetc: get 1 character from the connection + * pqGetc: read 1 character from the connection * * All these routines return 0 on success, EOF on error. * Note that for the Get routines, EOF only means there is not enough @@ -100,7 +100,7 @@ pqPutc(char c, PGconn *conn) /* * pqGets[_append]: - * get a null-terminated string from the connection, + * read a null-terminated string from the connection, * and store it in an expansible PQExpBuffer. * If we run out of memory, all of the string is still read, * but the excess characters are silently discarded. @@ -159,10 +159,10 @@ pqPuts(const char *s, PGconn *conn) /* * pqGetnchar: - * get a string of exactly len bytes in buffer s, no null termination + * read exactly len bytes in buffer s, no null termination */ int -pqGetnchar(char *s, size_t len, PGconn *conn) +pqGetnchar(void *s, size_t len, PGconn *conn) { if (len > (size_t) (conn->inEnd - conn->inCursor)) return EOF; @@ -199,7 +199,7 @@ pqSkipnchar(size_t len, PGconn *conn) * write exactly len bytes to the current message */ int -pqPutnchar(const char *s, size_t len, PGconn *conn) +pqPutnchar(const void *s, size_t len, PGconn *conn) { if (pqPutMsgBytes(s, len, conn)) return EOF; @@ -435,6 +435,21 @@ pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn) return EOF; } +/* + * pqParseDone: after a server-to-client message has successfully + * been parsed, advance conn->inStart to account for it. + */ +void +pqParseDone(PGconn *conn, int newInStart) +{ + /* trace server-to-client message */ + if (conn->Pfdebug) + pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); + + /* Mark message as done */ + conn->inStart = newInStart; +} + /* * pqPutMsgStart: begin construction of a message to the server * @@ -538,9 +553,35 @@ pqPutMsgEnd(PGconn *conn) /* Make message eligible to send */ conn->outCount = conn->outMsgEnd; + /* If appropriate, try to push out some data */ if (conn->outCount >= 8192) { - int toSend = conn->outCount - (conn->outCount % 8192); + int toSend = conn->outCount; + + /* + * On Unix-pipe connections, it seems profitable to prefer sending + * pipe-buffer-sized packets not randomly-sized ones, so retain the + * last partial-8K chunk in our buffer for now. On TCP connections, + * the advantage of that is far less clear. Moreover, it flat out + * isn't safe when using SSL or GSSAPI, because those code paths have + * API stipulations that if they fail to send all the data that was + * offered in the previous write attempt, we mustn't offer less data + * in this write attempt. The previous write attempt might've been + * pqFlush attempting to send everything in the buffer, so we mustn't + * offer less now. (Presently, we won't try to use SSL or GSSAPI on + * Unix connections, so those checks are just Asserts. They'll have + * to become part of the regular if-test if we ever change that.) + */ + if (conn->raddr.addr.ss_family == AF_UNIX) + { +#ifdef USE_SSL + Assert(!conn->ssl_in_use); +#endif +#ifdef ENABLE_GSS + Assert(!conn->gssenc); +#endif + toSend -= toSend % 8192; + } if (pqSendSome(conn, toSend) < 0) return EOF; @@ -1034,34 +1075,43 @@ pqWriteReady(PGconn *conn) * or both. Returns >0 if one or more conditions are met, 0 if it timed * out, -1 if an error occurred. * - * If SSL is in use, the SSL buffer is checked prior to checking the socket - * for read data directly. + * If an altsock is set for asynchronous authentication, that will be used in + * preference to the "server" socket. Otherwise, if SSL is in use, the SSL + * buffer is checked prior to checking the socket for read data directly. */ static int pqSocketCheck(PGconn *conn, int forRead, int forWrite, pg_usec_time_t end_time) { int result; + pgsocket sock; if (!conn) return -1; - if (conn->sock == PGINVALID_SOCKET) + + if (conn->altsock != PGINVALID_SOCKET) + sock = conn->altsock; + else { - libpq_append_conn_error(conn, "invalid socket"); - return -1; - } + sock = conn->sock; + if (sock == PGINVALID_SOCKET) + { + libpq_append_conn_error(conn, "invalid socket"); + return -1; + } #ifdef USE_SSL - /* Check for SSL library buffering read bytes */ - if (forRead && conn->ssl_in_use && pgtls_read_pending(conn)) - { - /* short-circuit the select */ - return 1; - } + /* Check for SSL library buffering read bytes */ + if (forRead && conn->ssl_in_use && pgtls_read_pending(conn)) + { + /* short-circuit the select */ + return 1; + } #endif + } /* We will retry as long as we get EINTR */ do - result = PQsocketPoll(conn->sock, forRead, forWrite, end_time); + result = PQsocketPoll(sock, forRead, forWrite, end_time); while (result < 0 && SOCK_ERRNO == EINTR); if (result < 0) @@ -1197,13 +1247,9 @@ PQgetCurrentTimeUSec(void) */ /* - * Returns the byte length of the character beginning at s, using the - * specified encoding. - * - * Caution: when dealing with text that is not certainly valid in the - * specified encoding, the result may exceed the actual remaining - * string length. Callers that are not prepared to deal with that - * should use PQmblenBounded() instead. + * Like pg_encoding_mblen(). Use this in callers that want the + * dynamically-linked libpq's stance on encodings, even if that means + * different behavior in different startups of the executable. */ int PQmblen(const char *s, int encoding) @@ -1212,8 +1258,9 @@ PQmblen(const char *s, int encoding) } /* - * Returns the byte length of the character beginning at s, using the - * specified encoding; but not more than the distance to end of string. + * Like pg_encoding_mblen_bounded(). Use this in callers that want the + * dynamically-linked libpq's stance on encodings, even if that means + * different behavior in different startups of the executable. */ int PQmblenBounded(const char *s, int encoding) diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c index df95f059efa94..6a4de16fe4e9e 100644 --- a/src/interfaces/libpq/fe-print.c +++ b/src/interfaces/libpq/fe-print.c @@ -3,7 +3,7 @@ * fe-print.c * functions for pretty-printing query results * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * These functions were formerly part of fe-exec.c, but they diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 3170d484f026a..beb1c889aad73 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -3,7 +3,7 @@ * fe-protocol3.c * functions that are specific to frontend/backend protocol version 3 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -48,6 +48,7 @@ static int getRowDescriptions(PGconn *conn, int msgLength); static int getParamDescriptions(PGconn *conn, int msgLength); static int getAnotherTuple(PGconn *conn, int msgLength); static int getParameterStatus(PGconn *conn); +static int getBackendKeyData(PGconn *conn, int msgLength); static int getNotify(PGconn *conn); static int getCopyStart(PGconn *conn, ExecStatusType copytype); static int getReadyForQuery(PGconn *conn); @@ -308,9 +309,7 @@ pqParseInput3(PGconn *conn) * just as easy to handle it as part of the main loop. * Save the data and continue processing. */ - if (pqGetInt(&(conn->be_pid), 4, conn)) - return; - if (pqGetInt(&(conn->be_key), 4, conn)) + if (getBackendKeyData(conn, msgLength)) return; break; case PqMsg_RowDescription: @@ -454,12 +453,8 @@ pqParseInput3(PGconn *conn) /* Successfully consumed this message */ if (conn->inCursor == conn->inStart + 5 + msgLength) { - /* trace server-to-client message */ - if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); - /* Normal case: parsing agrees with specified length */ - conn->inStart = conn->inCursor; + pqParseDone(conn, conn->inCursor); } else { @@ -874,6 +869,7 @@ getAnotherTuple(PGconn *conn, int msgLength) /* * Attempt to read an Error or Notice response message. * This is possible in several places, so we break it out as a subroutine. + * * Entry: 'E' or 'N' message type and length have already been consumed. * Exit: returns 0 if successfully consumed message. * returns EOF if not enough data. @@ -1403,64 +1399,105 @@ reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding) /* - * Attempt to read a NegotiateProtocolVersion message. + * Attempt to read a NegotiateProtocolVersion message. Sets conn->pversion + * to the version that's negotiated by the server. + * * Entry: 'v' message type and length have already been consumed. * Exit: returns 0 if successfully consumed message. - * returns EOF if not enough data. + * returns 1 on failure. The error message is filled in. */ int pqGetNegotiateProtocolVersion3(PGconn *conn) { - int tmp; - ProtocolVersion their_version; + int their_version; int num; - PQExpBufferData buf; - if (pqGetInt(&tmp, 4, conn) != 0) - return EOF; - their_version = tmp; + if (pqGetInt(&their_version, 4, conn) != 0) + goto eof; if (pqGetInt(&num, 4, conn) != 0) - return EOF; + goto eof; - initPQExpBuffer(&buf); - for (int i = 0; i < num; i++) + /* Check the protocol version */ + if (their_version > conn->pversion) { - if (pqGets(&conn->workBuffer, conn)) - { - termPQExpBuffer(&buf); - return EOF; - } - if (buf.len > 0) - appendPQExpBufferChar(&buf, ' '); - appendPQExpBufferStr(&buf, conn->workBuffer.data); + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version"); + goto failure; + } + + if (their_version < PG_PROTOCOL(3, 0)) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version"); + goto failure; + } + + /* 3.1 never existed, we went straight from 3.0 to 3.2 */ + if (their_version == PG_PROTOCOL(3, 1)) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requests downgrade to non-existent 3.1 protocol version"); + goto failure; + } + + if (num < 0) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported negative number of unsupported parameters"); + goto failure; } - if (their_version < conn->pversion) - libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u", - PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion), - PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version)); - if (num > 0) + if (their_version == conn->pversion && num == 0) { - appendPQExpBuffer(&conn->errorMessage, - libpq_ngettext("protocol extension not supported by server: %s", - "protocol extensions not supported by server: %s", num), - buf.data); - appendPQExpBufferChar(&conn->errorMessage, '\n'); + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server negotiated but asks for no changes"); + goto failure; + } + + if (their_version < conn->min_pversion) + { + libpq_append_conn_error(conn, "server only supports protocol version %d.%d, but min_protocol_version was set to %d.%d", + PG_PROTOCOL_MAJOR(their_version), + PG_PROTOCOL_MINOR(their_version), + PG_PROTOCOL_MAJOR(conn->min_pversion), + PG_PROTOCOL_MINOR(conn->min_pversion)); + + goto failure; } - /* neither -- server shouldn't have sent it */ - if (!(their_version < conn->pversion) && !(num > 0)) - libpq_append_conn_error(conn, "invalid %s message", "NegotiateProtocolVersion"); + /* the version is acceptable */ + conn->pversion = their_version; + + /* + * We don't currently request any protocol extensions, so we don't expect + * the server to reply with any either. + */ + for (int i = 0; i < num; i++) + { + if (pqGets(&conn->workBuffer, conn)) + { + goto eof; + } + if (strncmp(conn->workBuffer.data, "_pq_.", 5) != 0) + { + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported unsupported parameter name without a _pq_. prefix (\"%s\")", conn->workBuffer.data); + goto failure; + } + libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")", conn->workBuffer.data); + goto failure; + } - termPQExpBuffer(&buf); return 0; + +eof: + libpq_append_conn_error(conn, "received invalid protocol negotiation message: message too short"); +failure: + conn->asyncStatus = PGASYNC_READY; + pqSaveErrorResult(conn); + return 1; } /* * Attempt to read a ParameterStatus message. * This is possible in several places, so we break it out as a subroutine. + * * Entry: 'S' message type and length have already been consumed. * Exit: returns 0 if successfully consumed message. * returns EOF if not enough data. @@ -1486,10 +1523,51 @@ getParameterStatus(PGconn *conn) return 0; } +/* + * parseInput subroutine to read a BackendKeyData message. + * Entry: 'v' message type and length have already been consumed. + * Exit: returns 0 if successfully consumed message. + * returns EOF if not enough data. + */ +static int +getBackendKeyData(PGconn *conn, int msgLength) +{ + int cancel_key_len; + + if (conn->be_cancel_key) + { + free(conn->be_cancel_key); + conn->be_cancel_key = NULL; + conn->be_cancel_key_len = 0; + } + + if (pqGetInt(&(conn->be_pid), 4, conn)) + return EOF; + + cancel_key_len = 5 + msgLength - (conn->inCursor - conn->inStart); + + conn->be_cancel_key = malloc(cancel_key_len); + if (conn->be_cancel_key == NULL) + { + libpq_append_conn_error(conn, "out of memory"); + /* discard the message */ + return EOF; + } + if (pqGetnchar(conn->be_cancel_key, cancel_key_len, conn)) + { + free(conn->be_cancel_key); + conn->be_cancel_key = NULL; + return EOF; + } + conn->be_cancel_key_len = cancel_key_len; + return 0; +} + /* * Attempt to read a Notify response message. * This is possible in several places, so we break it out as a subroutine. + * * Entry: 'A' message type and length have already been consumed. * Exit: returns 0 if successfully consumed Notify message. * returns EOF if not enough data. @@ -1728,12 +1806,8 @@ getCopyDataMessage(PGconn *conn) return -1; } - /* trace server-to-client message */ - if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); - /* Drop the processed message and loop around for another */ - conn->inStart = conn->inCursor; + pqParseDone(conn, conn->inCursor); } } @@ -1791,13 +1865,13 @@ pqGetCopyData3(PGconn *conn, char **buffer, int async) (*buffer)[msgLength] = '\0'; /* Add terminating null */ /* Mark message consumed */ - conn->inStart = conn->inCursor + msgLength; + pqParseDone(conn, conn->inCursor + msgLength); return msgLength; } /* Empty, so drop it and loop around for another */ - conn->inStart = conn->inCursor; + pqParseDone(conn, conn->inCursor); } } @@ -2047,7 +2121,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid, } else { - if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn)) + if (pqPutnchar(args[i].u.ptr, args[i].len, conn)) return NULL; } } @@ -2141,7 +2215,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid, } else { - if (pqGetnchar((char *) result_buf, + if (pqGetnchar(result_buf, *actual_result_len, conn)) continue; @@ -2168,8 +2242,9 @@ pqFunctionCall3(PGconn *conn, Oid fnid, case 'Z': /* backend is ready for new query */ if (getReadyForQuery(conn)) continue; - /* consume the message and exit */ - conn->inStart += 5 + msgLength; + + /* consume the message */ + pqParseDone(conn, conn->inStart + 5 + msgLength); /* * If we already have a result object (probably an error), use @@ -2194,6 +2269,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid, pqSaveErrorResult(conn); } } + /* and we're out */ return pqPrepareAsyncResult(conn); case 'S': /* parameter status */ if (getParameterStatus(conn)) @@ -2203,18 +2279,18 @@ pqFunctionCall3(PGconn *conn, Oid fnid, /* The backend violates the protocol. */ libpq_append_conn_error(conn, "protocol error: id=0x%x", id); pqSaveErrorResult(conn); - /* trust the specified message length as what to skip */ + + /* + * We can't call parsing done due to the protocol violation + * (so message tracing wouldn't work), but trust the specified + * message length as what to skip. + */ conn->inStart += 5 + msgLength; return pqPrepareAsyncResult(conn); } - /* trace server-to-client message */ - if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false); - - /* Completed this message, keep going */ - /* trust the specified message length as what to skip */ - conn->inStart += 5 + msgLength; + /* Completed parsing this message, keep going */ + pqParseDone(conn, conn->inStart + 5 + msgLength); needInput = false; } diff --git a/src/interfaces/libpq/fe-secure-common.c b/src/interfaces/libpq/fe-secure-common.c index a21376e85128a..56d0d612eed4e 100644 --- a/src/interfaces/libpq/fe-secure-common.c +++ b/src/interfaces/libpq/fe-secure-common.c @@ -8,7 +8,7 @@ * file contains support routines that are used by the library-specific * implementations such as fe-secure-openssl.c. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/interfaces/libpq/fe-secure-common.h b/src/interfaces/libpq/fe-secure-common.h index ecd5ab6ac356d..f65edb8e1da92 100644 --- a/src/interfaces/libpq/fe-secure-common.h +++ b/src/interfaces/libpq/fe-secure-common.h @@ -4,7 +4,7 @@ * * common implementation-independent SSL support code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/interfaces/libpq/fe-secure-gssapi.c b/src/interfaces/libpq/fe-secure-gssapi.c index 98b314613c36c..bc9e1ce06fa4d 100644 --- a/src/interfaces/libpq/fe-secure-gssapi.c +++ b/src/interfaces/libpq/fe-secure-gssapi.c @@ -3,7 +3,7 @@ * fe-secure-gssapi.c * The front-end (client) encryption support for GSSAPI * - * Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/interfaces/libpq/fe-secure-gssapi.c @@ -47,11 +47,18 @@ * don't want the other side to send arbitrarily huge packets as we * would have to allocate memory for them to then pass them to GSSAPI. * - * Therefore, these two #define's are effectively part of the protocol + * Therefore, this #define is effectively part of the protocol * spec and can't ever be changed. */ -#define PQ_GSS_SEND_BUFFER_SIZE 16384 -#define PQ_GSS_RECV_BUFFER_SIZE 16384 +#define PQ_GSS_MAX_PACKET_SIZE 16384 /* includes uint32 header word */ + +/* + * However, during the authentication exchange we must cope with whatever + * message size the GSSAPI library wants to send (because our protocol + * doesn't support splitting those messages). Depending on configuration + * those messages might be as much as 64kB. + */ +#define PQ_GSS_AUTH_BUFFER_SIZE 65536 /* includes uint32 header word */ /* * We need these state variables per-connection. To allow the functions @@ -105,9 +112,9 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len) * again, so if it offers a len less than that, something is wrong. * * Note: it may seem attractive to report partial write completion once - * we've successfully sent any encrypted packets. However, that can cause - * problems for callers; notably, pqPutMsgEnd's heuristic to send only - * full 8K blocks interacts badly with such a hack. We won't save much, + * we've successfully sent any encrypted packets. However, doing that + * expands the state space of this processing and has been responsible for + * bugs in the past (cf. commit d053a879b). We won't save much, * typically, by letting callers discard data early, so don't risk it. */ if (len < PqGSSSendConsumed) @@ -203,11 +210,11 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len) goto cleanup; } - if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + if (output.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)) { libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)", (size_t) output.length, - PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)); + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)); errno = EIO; /* for lack of a better idea */ goto cleanup; } @@ -342,11 +349,11 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len) /* Decode the packet length and check for overlength packet */ input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer); - if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)) + if (input.length > PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)) { libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)", (size_t) input.length, - PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)); + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32)); errno = EIO; /* for lack of a better idea */ return -1; } @@ -485,12 +492,15 @@ pqsecure_open_gss(PGconn *conn) * initialize state variables. By malloc'ing the buffers separately, we * ensure that they are sufficiently aligned for the length-word accesses * that we do in some places in this file. + * + * We'll use PQ_GSS_AUTH_BUFFER_SIZE-sized buffers until transport + * negotiation is complete, then switch to PQ_GSS_MAX_PACKET_SIZE. */ if (PqGSSSendBuffer == NULL) { - PqGSSSendBuffer = malloc(PQ_GSS_SEND_BUFFER_SIZE); - PqGSSRecvBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); - PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE); + PqGSSSendBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); + PqGSSRecvBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); + PqGSSResultBuffer = malloc(PQ_GSS_AUTH_BUFFER_SIZE); if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) { libpq_append_conn_error(conn, "out of memory"); @@ -564,13 +574,13 @@ pqsecure_open_gss(PGconn *conn) * so leave a spot at the end for a NULL byte too) and report that * back to the caller. */ - result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_RECV_BUFFER_SIZE - PqGSSRecvLength - 1, &ret); + result = gss_read(conn, PqGSSRecvBuffer + PqGSSRecvLength, PQ_GSS_AUTH_BUFFER_SIZE - PqGSSRecvLength - 1, &ret); if (result != PGRES_POLLING_OK) return result; PqGSSRecvLength += ret; - Assert(PqGSSRecvLength < PQ_GSS_RECV_BUFFER_SIZE); + Assert(PqGSSRecvLength < PQ_GSS_AUTH_BUFFER_SIZE); PqGSSRecvBuffer[PqGSSRecvLength] = '\0'; appendPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1); @@ -584,11 +594,11 @@ pqsecure_open_gss(PGconn *conn) /* Get the length and check for over-length packet */ input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer); - if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)) + if (input.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)) { libpq_append_conn_error(conn, "oversize GSSAPI packet sent by the server (%zu > %zu)", (size_t) input.length, - PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32)); + PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)); return PGRES_POLLING_FAILED; } @@ -668,12 +678,33 @@ pqsecure_open_gss(PGconn *conn) conn->gcred = GSS_C_NO_CREDENTIAL; gss_release_buffer(&minor, &output); + /* + * Release the large authentication buffers and allocate the ones we + * want for normal operation. (This maneuver is safe only because + * pqDropConnection will drop the buffers; otherwise, during a + * reconnection we'd be at risk of using undersized buffers during + * negotiation.) + */ + free(PqGSSSendBuffer); + free(PqGSSRecvBuffer); + free(PqGSSResultBuffer); + PqGSSSendBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + PqGSSRecvBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + PqGSSResultBuffer = malloc(PQ_GSS_MAX_PACKET_SIZE); + if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer) + { + libpq_append_conn_error(conn, "out of memory"); + return PGRES_POLLING_FAILED; + } + PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0; + PqGSSRecvLength = PqGSSResultLength = PqGSSResultNext = 0; + /* * Determine the max packet size which will fit in our buffer, after * accounting for the length. pg_GSS_write will need this. */ major = gss_wrap_size_limit(&minor, conn->gctx, 1, GSS_C_QOP_DEFAULT, - PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32), + PQ_GSS_MAX_PACKET_SIZE - sizeof(uint32), &PqGSSMaxPktSize); if (GSS_ERROR(major)) @@ -687,10 +718,11 @@ pqsecure_open_gss(PGconn *conn) } /* Must have output.length > 0 */ - if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32)) + if (output.length > PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)) { - pg_GSS_error(libpq_gettext("GSSAPI context establishment error"), - conn, major, minor); + libpq_append_conn_error(conn, "client tried to send oversize GSSAPI packet (%zu > %zu)", + (size_t) output.length, + PQ_GSS_AUTH_BUFFER_SIZE - sizeof(uint32)); gss_release_buffer(&minor, &output); return PGRES_POLLING_FAILED; } @@ -698,7 +730,7 @@ pqsecure_open_gss(PGconn *conn) /* Queue the token for writing */ netlen = pg_hton32(output.length); - memcpy(PqGSSSendBuffer, (char *) &netlen, sizeof(uint32)); + memcpy(PqGSSSendBuffer, &netlen, sizeof(uint32)); PqGSSSendLength += sizeof(uint32); memcpy(PqGSSSendBuffer + PqGSSSendLength, output.value, output.length); diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index 5c867106fb0d2..78f9e84eb353b 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -4,7 +4,7 @@ * OpenSSL support * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -57,6 +57,7 @@ * include , but some other Windows headers do.) */ #include "common/openssl.h" +#include #include #ifdef USE_SSL_ENGINE #include @@ -71,25 +72,16 @@ static int openssl_verify_peer_name_matches_certificate_name(PGconn *conn, static int openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, ASN1_OCTET_STRING *addr_entry, char **store_name); -static void destroy_ssl_system(void); static int initialize_SSL(PGconn *conn); static PostgresPollingStatusType open_client_SSL(PGconn *conn); static char *SSLerrmessage(unsigned long ecode); static void SSLerrfree(char *buf); static int PQssl_passwd_cb(char *buf, int size, int rwflag, void *userdata); -static int my_sock_read(BIO *h, char *buf, int size); -static int my_sock_write(BIO *h, const char *buf, int size); -static BIO_METHOD *my_BIO_s_socket(void); -static int my_SSL_set_fd(PGconn *conn, int fd); - - -static bool pq_init_ssl_lib = true; -static bool pq_init_crypto_lib = true; - -static bool ssl_lib_initialized = false; - -static long crypto_open_connections = 0; +static int pgconn_bio_read(BIO *h, char *buf, int size); +static int pgconn_bio_write(BIO *h, const char *buf, int size); +static BIO_METHOD *pgconn_bio_method(void); +static int ssl_set_pgconn_bio(PGconn *conn); static pthread_mutex_t ssl_config_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -100,20 +92,6 @@ static int ssl_protocol_version_to_openssl(const char *protocol); /* Procedures common to all secure sessions */ /* ------------------------------------------------------------ */ -void -pgtls_init_library(bool do_ssl, int do_crypto) -{ - /* - * Disallow changing the flags while we have open connections, else we'd - * get completely confused. - */ - if (crypto_open_connections != 0) - return; - - pq_init_ssl_lib = do_ssl; - pq_init_crypto_lib = do_crypto; -} - PostgresPollingStatusType pgtls_open_client(PGconn *conn) { @@ -505,11 +483,7 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam /* * GEN_DNS can be only IA5String, equivalent to US ASCII. */ -#ifdef HAVE_ASN1_STRING_GET0_DATA namedata = ASN1_STRING_get0_data(name_entry); -#else - namedata = ASN1_STRING_data(name_entry); -#endif len = ASN1_STRING_length(name_entry); /* OK to cast from unsigned to plain char, since it's all ASCII. */ @@ -540,11 +514,7 @@ openssl_verify_peer_name_matches_certificate_ip(PGconn *conn, * GEN_IPADD is an OCTET STRING containing an IP address in network byte * order. */ -#ifdef HAVE_ASN1_STRING_GET0_DATA addrdata = ASN1_STRING_get0_data(addr_entry); -#else - addrdata = ASN1_STRING_data(addr_entry); -#endif len = ASN1_STRING_length(addr_entry); return pq_verify_peer_name_matches_certificate_ip(conn, addrdata, len, store_name); @@ -712,181 +682,51 @@ pgtls_verify_peer_name_matches_certificate_guts(PGconn *conn, return rc; } -#if defined(HAVE_CRYPTO_LOCK) -/* - * Callback functions for OpenSSL internal locking. (OpenSSL 1.1.0 - * does its own locking, and doesn't need these anymore. The - * CRYPTO_lock() function was removed in 1.1.0, when the callbacks - * were made obsolete, so we assume that if CRYPTO_lock() exists, - * the callbacks are still required.) - */ - -static unsigned long -pq_threadidcallback(void) -{ - /* - * This is not standards-compliant. pthread_self() returns pthread_t, and - * shouldn't be cast to unsigned long, but CRYPTO_set_id_callback requires - * it, so we have to do it. - */ - return (unsigned long) pthread_self(); -} - -static pthread_mutex_t *pq_lockarray; - -static void -pq_lockingcallback(int mode, int n, const char *file, int line) -{ - /* - * There's no way to report a mutex-primitive failure, so we just Assert - * in development builds, and ignore any errors otherwise. Fortunately - * this is all obsolete in modern OpenSSL. - */ - if (mode & CRYPTO_LOCK) - { - if (pthread_mutex_lock(&pq_lockarray[n])) - Assert(false); - } - else - { - if (pthread_mutex_unlock(&pq_lockarray[n])) - Assert(false); - } -} -#endif /* HAVE_CRYPTO_LOCK */ - -/* - * Initialize SSL library. - * - * In threadsafe mode, this includes setting up libcrypto callback functions - * to do thread locking. - * - * If the caller has told us (through PQinitOpenSSL) that he's taking care - * of libcrypto, we expect that callbacks are already set, and won't try to - * override it. - */ -int -pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto) -{ - if (pthread_mutex_lock(&ssl_config_mutex)) - return -1; - -#ifdef HAVE_CRYPTO_LOCK - if (pq_init_crypto_lib) - { - /* - * If necessary, set up an array to hold locks for libcrypto. - * libcrypto will tell us how big to make this array. - */ - if (pq_lockarray == NULL) - { - int i; - - pq_lockarray = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - if (!pq_lockarray) - { - pthread_mutex_unlock(&ssl_config_mutex); - return -1; - } - for (i = 0; i < CRYPTO_num_locks(); i++) - { - if (pthread_mutex_init(&pq_lockarray[i], NULL)) - { - free(pq_lockarray); - pq_lockarray = NULL; - pthread_mutex_unlock(&ssl_config_mutex); - return -1; - } - } - } - - if (do_crypto && !conn->crypto_loaded) - { - if (crypto_open_connections++ == 0) - { - /* - * These are only required for threaded libcrypto - * applications, but make sure we don't stomp on them if - * they're already set. - */ - if (CRYPTO_get_id_callback() == NULL) - CRYPTO_set_id_callback(pq_threadidcallback); - if (CRYPTO_get_locking_callback() == NULL) - CRYPTO_set_locking_callback(pq_lockingcallback); - } - - conn->crypto_loaded = true; - } - } -#endif /* HAVE_CRYPTO_LOCK */ - - if (!ssl_lib_initialized && do_ssl) - { - if (pq_init_ssl_lib) - { -#ifdef HAVE_OPENSSL_INIT_SSL - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); -#else - OPENSSL_config(NULL); - SSL_library_init(); - SSL_load_error_strings(); -#endif - } - ssl_lib_initialized = true; - } - - pthread_mutex_unlock(&ssl_config_mutex); - return 0; -} +/* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ +static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; +#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK /* - * This function is needed because if the libpq library is unloaded - * from the application, the callback functions will no longer exist when - * libcrypto is used by other parts of the system. For this reason, - * we unregister the callback functions when the last libpq - * connection is closed. (The same would apply for OpenSSL callbacks - * if we had any.) + * SSL Key Logging callback * - * Callbacks are only set when we're compiled in threadsafe mode, so - * we only need to remove them in this case. They are also not needed - * with OpenSSL 1.1.0 anymore. + * This callback lets the user store all key material to a file for debugging + * purposes. The file will be written using the NSS keylog format. LibreSSL + * 3.5 introduced stub function to set the callback for OpenSSL compatibility + * but the callback is never invoked. */ static void -destroy_ssl_system(void) +SSL_CTX_keylog_cb(const SSL *ssl, const char *line) { -#if defined(HAVE_CRYPTO_LOCK) - if (pthread_mutex_lock(&ssl_config_mutex)) + int fd; + mode_t old_umask; + ssize_t rc; + PGconn *conn = SSL_get_app_data(ssl); + + if (conn == NULL) return; - if (pq_init_crypto_lib && crypto_open_connections > 0) - --crypto_open_connections; + old_umask = umask(077); + fd = open(conn->sslkeylogfile, O_WRONLY | O_APPEND | O_CREAT, 0600); + umask(old_umask); - if (pq_init_crypto_lib && crypto_open_connections == 0) + if (fd == -1) { - /* - * No connections left, unregister libcrypto callbacks, if no one - * registered different ones in the meantime. - */ - if (CRYPTO_get_locking_callback() == pq_lockingcallback) - CRYPTO_set_locking_callback(NULL); - if (CRYPTO_get_id_callback() == pq_threadidcallback) - CRYPTO_set_id_callback(NULL); - - /* - * We don't free the lock array. If we get another connection in this - * process, we will just re-use them with the existing mutexes. - * - * This means we leak a little memory on repeated load/unload of the - * library. - */ + libpq_append_conn_error(conn, "could not open ssl keylog file \"%s\": %s", + conn->sslkeylogfile, pg_strerror(errno)); + return; } - pthread_mutex_unlock(&ssl_config_mutex); -#endif + /* line is guaranteed by OpenSSL to be NUL terminated */ + rc = write(fd, line, strlen(line)); + if (rc < 0) + libpq_append_conn_error(conn, "could not write to ssl keylog file \"%s\": %s", + conn->sslkeylogfile, pg_strerror(errno)); + else + rc = write(fd, "\n", 1); + (void) rc; /* silence compiler warnings */ + close(fd); } - -/* See pqcomm.h comments on OpenSSL implementation of ALPN (RFC 7301) */ -static unsigned char alpn_protos[] = PG_ALPN_PROTOCOL_VECTOR; +#endif /* * Create per-connection SSL object, and load the client certificate, @@ -1193,7 +1033,7 @@ initialize_SSL(PGconn *conn) */ if (!(conn->ssl = SSL_new(SSL_context)) || !SSL_set_app_data(conn->ssl, conn) || - !my_SSL_set_fd(conn, conn->sock)) + !ssl_set_pgconn_bio(conn)) { char *err = SSLerrmessage(ERR_get_error()); @@ -1204,6 +1044,20 @@ initialize_SSL(PGconn *conn) } conn->ssl_in_use = true; + if (conn->sslkeylogfile && strlen(conn->sslkeylogfile) > 0) + { +#ifdef HAVE_SSL_CTX_SET_KEYLOG_CALLBACK + SSL_CTX_set_keylog_callback(SSL_context, SSL_CTX_keylog_cb); +#else +#ifdef LIBRESSL_VERSION_NUMBER + fprintf(stderr, libpq_gettext("WARNING: sslkeylogfile support requires OpenSSL\n")); +#else + fprintf(stderr, libpq_gettext("WARNING: libpq was not built with sslkeylogfile support\n")); +#endif +#endif + } + + /* * SSL contexts are reference counted by OpenSSL. We can free it as soon * as we have created the SSL object, and it will stick around for as long @@ -1643,8 +1497,6 @@ open_client_SSL(PGconn *conn) void pgtls_close(PGconn *conn) { - bool destroy_needed = false; - if (conn->ssl_in_use) { if (conn->ssl) @@ -1660,8 +1512,6 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; - - destroy_needed = true; } if (conn->peer) @@ -1679,30 +1529,6 @@ pgtls_close(PGconn *conn) } #endif } - else - { - /* - * In the non-SSL case, just remove the crypto callbacks if the - * connection has them loaded. This code path has no dependency on - * any pending SSL calls. - */ - if (conn->crypto_loaded) - destroy_needed = true; - } - - /* - * This will remove our crypto locking hooks if this is the last - * connection using libcrypto which means we must wait to call it until - * after all the potential SSL calls have been made, otherwise we can end - * up with a race condition and possible deadlocks. - * - * See comments above destroy_ssl_system(). - */ - if (destroy_needed) - { - destroy_ssl_system(); - conn->crypto_loaded = false; - } } @@ -1759,15 +1585,16 @@ SSLerrmessage(unsigned long ecode) #endif /* - * In OpenSSL 3.0.0 and later, ERR_reason_error_string randomly refuses to - * map system errno values. We can cover that shortcoming with this bit - * of code. Older OpenSSL versions don't have the ERR_SYSTEM_ERROR macro, - * but that's okay because they don't have the shortcoming either. + * In OpenSSL 3.0.0 and later, ERR_reason_error_string does not map system + * errno values anymore. (See OpenSSL source code for the explanation.) + * We can cover that shortcoming with this bit of code. Older OpenSSL + * versions don't have the ERR_SYSTEM_ERROR macro, but that's okay because + * they don't have the shortcoming either. */ #ifdef ERR_SYSTEM_ERROR if (ERR_SYSTEM_ERROR(ecode)) { - strlcpy(errbuf, strerror(ERR_GET_REASON(ecode)), SSL_ERR_LEN); + strerror_r(ERR_GET_REASON(ecode), errbuf, SSL_ERR_LEN); return errbuf; } #endif @@ -1901,16 +1728,17 @@ PQsslAttribute(PGconn *conn, const char *attribute_name) */ /* protected by ssl_config_mutex */ -static BIO_METHOD *my_bio_methods; +static BIO_METHOD *pgconn_bio_method_ptr; static int -my_sock_read(BIO *h, char *buf, int size) +pgconn_bio_read(BIO *h, char *buf, int size) { - PGconn *conn = (PGconn *) BIO_get_app_data(h); + PGconn *conn = (PGconn *) BIO_get_data(h); int res; res = pqsecure_raw_read(conn, buf, size); BIO_clear_retry_flags(h); + conn->last_read_was_eof = res == 0; if (res < 0) { /* If we were interrupted, tell caller to retry */ @@ -1938,11 +1766,11 @@ my_sock_read(BIO *h, char *buf, int size) } static int -my_sock_write(BIO *h, const char *buf, int size) +pgconn_bio_write(BIO *h, const char *buf, int size) { int res; - res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size); + res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size); BIO_clear_retry_flags(h); if (res < 0) { @@ -1967,26 +1795,54 @@ my_sock_write(BIO *h, const char *buf, int size) return res; } +static long +pgconn_bio_ctrl(BIO *h, int cmd, long num, void *ptr) +{ + long res; + PGconn *conn = (PGconn *) BIO_get_data(h); + + switch (cmd) + { + case BIO_CTRL_EOF: + + /* + * This should not be needed. pgconn_bio_read already has a way to + * signal EOF to OpenSSL. However, OpenSSL made an undocumented, + * backwards-incompatible change and now expects EOF via BIO_ctrl. + * See https://github.com/openssl/openssl/issues/8208 + */ + res = conn->last_read_was_eof; + break; + case BIO_CTRL_FLUSH: + /* libssl expects all BIOs to support BIO_flush. */ + res = 1; + break; + default: + res = 0; + break; + } + + return res; +} + static BIO_METHOD * -my_BIO_s_socket(void) +pgconn_bio_method(void) { BIO_METHOD *res; if (pthread_mutex_lock(&ssl_config_mutex)) return NULL; - res = my_bio_methods; + res = pgconn_bio_method_ptr; - if (!my_bio_methods) + if (!pgconn_bio_method_ptr) { - BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); -#ifdef HAVE_BIO_METH_NEW int my_bio_index; my_bio_index = BIO_get_new_index(); if (my_bio_index == -1) goto err; - my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK); + my_bio_index |= BIO_TYPE_SOURCE_SINK; res = BIO_meth_new(my_bio_index, "libpq socket"); if (!res) goto err; @@ -1995,70 +1851,44 @@ my_BIO_s_socket(void) * As of this writing, these functions never fail. But check anyway, * like OpenSSL's own examples do. */ - if (!BIO_meth_set_write(res, my_sock_write) || - !BIO_meth_set_read(res, my_sock_read) || - !BIO_meth_set_gets(res, BIO_meth_get_gets(biom)) || - !BIO_meth_set_puts(res, BIO_meth_get_puts(biom)) || - !BIO_meth_set_ctrl(res, BIO_meth_get_ctrl(biom)) || - !BIO_meth_set_create(res, BIO_meth_get_create(biom)) || - !BIO_meth_set_destroy(res, BIO_meth_get_destroy(biom)) || - !BIO_meth_set_callback_ctrl(res, BIO_meth_get_callback_ctrl(biom))) + if (!BIO_meth_set_write(res, pgconn_bio_write) || + !BIO_meth_set_read(res, pgconn_bio_read) || + !BIO_meth_set_ctrl(res, pgconn_bio_ctrl)) { goto err; } -#else - res = malloc(sizeof(BIO_METHOD)); - if (!res) - goto err; - memcpy(res, biom, sizeof(BIO_METHOD)); - res->bread = my_sock_read; - res->bwrite = my_sock_write; -#endif } - my_bio_methods = res; + pgconn_bio_method_ptr = res; pthread_mutex_unlock(&ssl_config_mutex); return res; err: -#ifdef HAVE_BIO_METH_NEW if (res) BIO_meth_free(res); -#else - if (res) - free(res); -#endif pthread_mutex_unlock(&ssl_config_mutex); return NULL; } -/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */ static int -my_SSL_set_fd(PGconn *conn, int fd) +ssl_set_pgconn_bio(PGconn *conn) { - int ret = 0; BIO *bio; BIO_METHOD *bio_method; - bio_method = my_BIO_s_socket(); + bio_method = pgconn_bio_method(); if (bio_method == NULL) - { - SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); - goto err; - } + return 0; + bio = BIO_new(bio_method); if (bio == NULL) - { - SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); - goto err; - } - BIO_set_app_data(bio, conn); + return 0; + + BIO_set_data(bio, conn); + BIO_set_init(bio, 1); SSL_set_bio(conn->ssl, bio, bio); - BIO_set_fd(bio, fd, BIO_NOCLOSE); - ret = 1; -err: - return ret; + return 1; } /* diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index f628082337ebc..e686681ba155b 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -6,7 +6,7 @@ * message integrity and endpoint authentication. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -108,42 +108,27 @@ PQsslInUse(PGconn *conn) } /* - * Exported function to allow application to tell us it's already - * initialized OpenSSL. + * Exported function to allow application to tell us it's already initialized + * OpenSSL. Since OpenSSL 1.1.0 it is no longer required to explicitly + * initialize libssl and libcrypto, so this is a no-op. This function remains + * for backwards API compatibility. */ void PQinitSSL(int do_init) { -#ifdef USE_SSL - pgtls_init_library(do_init, do_init); -#endif + /* no-op */ } /* - * Exported function to allow application to tell us it's already - * initialized OpenSSL and/or libcrypto. + * Exported function to allow application to tell us it's already initialized + * OpenSSL. Since OpenSSL 1.1.0 it is no longer required to explicitly + * initialize libssl and libcrypto, so this is a no-op. This function remains + * for backwards API compatibility. */ void PQinitOpenSSL(int do_ssl, int do_crypto) { -#ifdef USE_SSL - pgtls_init_library(do_ssl, do_crypto); -#endif -} - -/* - * Initialize global SSL context - */ -int -pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto) -{ - int r = 0; - -#ifdef USE_SSL - r = pgtls_init(conn, do_ssl, do_crypto); -#endif - - return r; + /* no-op */ } /* diff --git a/src/interfaces/libpq/fe-trace.c b/src/interfaces/libpq/fe-trace.c index d7a61ec9cc172..a45f0d855871b 100644 --- a/src/interfaces/libpq/fe-trace.c +++ b/src/interfaces/libpq/fe-trace.c @@ -3,7 +3,7 @@ * fe-trace.c * functions for libpq protocol tracing * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -81,6 +81,7 @@ pqTraceFormatTimestamp(char *timestr, size_t ts_len) { struct timeval tval; time_t now; + struct tm tmbuf; gettimeofday(&tval, NULL); @@ -93,7 +94,7 @@ pqTraceFormatTimestamp(char *timestr, size_t ts_len) now = tval.tv_sec; strftime(timestr, ts_len, "%Y-%m-%d %H:%M:%S", - localtime(&now)); + localtime_r(&now, &tmbuf)); /* append microseconds */ snprintf(timestr + strlen(timestr), ts_len - strlen(timestr), ".%06u", (unsigned int) (tval.tv_usec)); @@ -158,6 +159,8 @@ pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress) /* * pqTraceOutputString: output a string message to the log + * + * If 'suppress' is true, print a literal "SSSS" instead of the actual string. */ static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress) @@ -183,14 +186,23 @@ pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress) /* * pqTraceOutputNchar: output a string of exactly len bytes message to the log + * + * If 'suppress' is true, print a literal 'BBBB' instead of the actual bytes. */ static void -pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor) +pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor, bool suppress) { int i, next; /* first char not yet printed */ const char *v = data + *cursor; + if (suppress) + { + fprintf(pfdebug, " 'BBBB'"); + *cursor += len; + return; + } + fprintf(pfdebug, " \'"); for (next = i = 0; i < len; ++i) @@ -246,7 +258,7 @@ pqTraceOutput_Bind(FILE *f, const char *message, int *cursor) nbytes = pqTraceOutputInt32(f, message, cursor, false); if (nbytes == -1) continue; - pqTraceOutputNchar(f, nbytes, message, cursor); + pqTraceOutputNchar(f, nbytes, message, cursor, false); } nparams = pqTraceOutputInt16(f, message, cursor); @@ -269,6 +281,14 @@ pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor) pqTraceOutputString(f, message, cursor, false); } +static void +pqTraceOutput_CopyData(FILE *f, const char *message, int *cursor, int length, + bool suppress) +{ + fprintf(f, "CopyData\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, suppress); +} + static void pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor) { @@ -283,7 +303,7 @@ pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor) len = pqTraceOutputInt32(f, message, cursor, false); if (len == -1) continue; - pqTraceOutputNchar(f, len, message, cursor); + pqTraceOutputNchar(f, len, message, cursor, false); } } @@ -343,6 +363,42 @@ pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor) pqTraceOutputString(f, message, cursor, false); } +static void +pqTraceOutput_GSSResponse(FILE *f, const char *message, int *cursor, + int length, bool regress) +{ + fprintf(f, "GSSResponse\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, regress); +} + +static void +pqTraceOutput_PasswordMessage(FILE *f, const char *message, int *cursor) +{ + fprintf(f, "PasswordMessage\t"); + pqTraceOutputString(f, message, cursor, false); +} + +static void +pqTraceOutput_SASLInitialResponse(FILE *f, const char *message, int *cursor, + bool regress) +{ + int initialResponse; + + fprintf(f, "SASLInitialResponse\t"); + pqTraceOutputString(f, message, cursor, false); + initialResponse = pqTraceOutputInt32(f, message, cursor, false); + if (initialResponse != -1) + pqTraceOutputNchar(f, initialResponse, message, cursor, regress); +} + +static void +pqTraceOutput_SASLResponse(FILE *f, const char *message, int *cursor, + int length, bool regress) +{ + fprintf(f, "SASLResponse\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, regress); +} + static void pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress) { @@ -363,7 +419,7 @@ pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regre nbytes = pqTraceOutputInt32(f, message, cursor, false); if (nbytes == -1) continue; - pqTraceOutputNchar(f, nbytes, message, cursor); + pqTraceOutputNchar(f, nbytes, message, cursor, false); } pqTraceOutputInt16(f, message, cursor); @@ -425,10 +481,58 @@ pqTraceOutput_Query(FILE *f, const char *message, int *cursor) } static void -pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor) +pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor, + int length, bool suppress) { - fprintf(f, "Authentication\t"); - pqTraceOutputInt32(f, message, cursor, false); + int authType = 0; + + memcpy(&authType, message + *cursor, 4); + authType = (int) pg_ntoh32(authType); + *cursor += 4; + switch (authType) + { + case AUTH_REQ_OK: + fprintf(f, "AuthenticationOk"); + break; + /* AUTH_REQ_KRB4 not supported */ + /* AUTH_REQ_KRB5 not supported */ + case AUTH_REQ_PASSWORD: + fprintf(f, "AuthenticationCleartextPassword"); + break; + /* AUTH_REQ_CRYPT not supported */ + case AUTH_REQ_MD5: + fprintf(f, "AuthenticationMD5Password"); + break; + case AUTH_REQ_GSS: + fprintf(f, "AuthenticationGSS"); + break; + case AUTH_REQ_GSS_CONT: + fprintf(f, "AuthenticationGSSContinue\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, + suppress); + break; + case AUTH_REQ_SSPI: + fprintf(f, "AuthenticationSSPI"); + break; + case AUTH_REQ_SASL: + fprintf(f, "AuthenticationSASL\t"); + while (message[*cursor] != '\0') + pqTraceOutputString(f, message, cursor, false); + pqTraceOutputString(f, message, cursor, false); + break; + case AUTH_REQ_SASL_CONT: + fprintf(f, "AuthenticationSASLContinue\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, + suppress); + break; + case AUTH_REQ_SASL_FIN: + fprintf(f, "AuthenticationSASLFinal\t"); + pqTraceOutputNchar(f, length - *cursor + 1, message, cursor, + suppress); + break; + default: + fprintf(f, "Unknown authentication message %d", authType); + } } static void @@ -474,9 +578,15 @@ pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool reg static void pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor) { + int nparams; + fprintf(f, "NegotiateProtocolVersion\t"); pqTraceOutputInt32(f, message, cursor, false); - pqTraceOutputInt32(f, message, cursor, false); + nparams = pqTraceOutputInt32(f, message, cursor, false); + for (int i = 0; i < nparams; i++) + { + pqTraceOutputString(f, message, cursor, false); + } } static void @@ -487,7 +597,7 @@ pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor) fprintf(f, "FunctionCallResponse\t"); len = pqTraceOutputInt32(f, message, cursor, false); if (len != -1) - pqTraceOutputNchar(f, len, message, cursor); + pqTraceOutputNchar(f, len, message, cursor, false); } static void @@ -578,7 +688,8 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) pqTraceOutput_CommandComplete(conn->Pfdebug, message, &logCursor); break; case PqMsg_CopyData: - /* Drop COPY data to reduce the overhead of logging. */ + pqTraceOutput_CopyData(conn->Pfdebug, message, &logCursor, + length, regress); break; case PqMsg_Describe: /* Describe(F) and DataRow(B) use the same identifier. */ @@ -599,6 +710,39 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) case PqMsg_CopyFail: pqTraceOutput_CopyFail(conn->Pfdebug, message, &logCursor); break; + case PqMsg_GSSResponse: + Assert(PqMsg_GSSResponse == PqMsg_PasswordMessage); + Assert(PqMsg_GSSResponse == PqMsg_SASLInitialResponse); + Assert(PqMsg_GSSResponse == PqMsg_SASLResponse); + + /* + * These messages share a common type byte, so we discriminate by + * having the code store the auth type separately. + */ + switch (conn->current_auth_response) + { + case AUTH_RESPONSE_GSS: + pqTraceOutput_GSSResponse(conn->Pfdebug, message, + &logCursor, length, regress); + break; + case AUTH_RESPONSE_PASSWORD: + pqTraceOutput_PasswordMessage(conn->Pfdebug, message, + &logCursor); + break; + case AUTH_RESPONSE_SASL_INITIAL: + pqTraceOutput_SASLInitialResponse(conn->Pfdebug, message, + &logCursor, regress); + break; + case AUTH_RESPONSE_SASL: + pqTraceOutput_SASLResponse(conn->Pfdebug, message, + &logCursor, length, regress); + break; + default: + fprintf(conn->Pfdebug, "UnknownAuthenticationResponse"); + break; + } + conn->current_auth_response = '\0'; + break; case PqMsg_FunctionCall: pqTraceOutput_FunctionCall(conn->Pfdebug, message, &logCursor, regress); break; @@ -634,7 +778,8 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) pqTraceOutput_Query(conn->Pfdebug, message, &logCursor); break; case PqMsg_AuthenticationRequest: - pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor); + pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor, + length, regress); break; case PqMsg_PortalSuspended: fprintf(conn->Pfdebug, "PortalSuspended"); @@ -696,8 +841,12 @@ void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message) { int length; + int version; + bool regress; int logCursor = 0; + regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0; + if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0) { char timestr[128]; @@ -712,20 +861,67 @@ pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message) fprintf(conn->Pfdebug, "F\t%d\t", length); - switch (length) + if (length < 8) { - case 16: /* CancelRequest */ - fprintf(conn->Pfdebug, "CancelRequest\t"); - pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); - pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); - pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false); - break; - case 8: /* GSSENCRequest or SSLRequest */ - /* These messages do not reach here. */ - default: - fprintf(conn->Pfdebug, "Unknown message: length is %d", length); - break; + fprintf(conn->Pfdebug, "Unknown message\n"); + return; + } + + memcpy(&version, message + logCursor, 4); + version = (int) pg_ntoh32(version); + + if (version == CANCEL_REQUEST_CODE && length >= 16) + { + fprintf(conn->Pfdebug, "CancelRequest\t"); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, regress); + pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, regress); + } + else if (version == NEGOTIATE_SSL_CODE) + { + fprintf(conn->Pfdebug, "SSLRequest\t"); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + } + else if (version == NEGOTIATE_GSS_CODE) + { + fprintf(conn->Pfdebug, "GSSENCRequest\t"); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + } + else + { + fprintf(conn->Pfdebug, "StartupMessage\t"); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + pqTraceOutputInt16(conn->Pfdebug, message, &logCursor); + while (message[logCursor] != '\0') + { + /* XXX should we suppress anything in regress mode? */ + pqTraceOutputString(conn->Pfdebug, message, &logCursor, false); + pqTraceOutputString(conn->Pfdebug, message, &logCursor, false); + } } fputc('\n', conn->Pfdebug); } + +/* + * Trace a single-byte backend response received for a known request + * type the frontend previously sent. Only useful for the simplest of + * FE/BE interaction workflows such as SSL/GSS encryption requests. + */ +void +pqTraceOutputCharResponse(PGconn *conn, const char *responseType, + char response) +{ + if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0) + { + char timestr[128]; + + pqTraceFormatTimestamp(timestr, sizeof(timestr)); + fprintf(conn->Pfdebug, "%s\t", timestr); + } + + fprintf(conn->Pfdebug, "B\t1\t%s\t %c\n", responseType, response); +} diff --git a/src/interfaces/libpq/legacy-pqsignal.c b/src/interfaces/libpq/legacy-pqsignal.c index e8c716ad0fc06..ebd1695bf074f 100644 --- a/src/interfaces/libpq/legacy-pqsignal.c +++ b/src/interfaces/libpq/legacy-pqsignal.c @@ -4,7 +4,7 @@ * reliable BSD-style signal(2) routine stolen from RWW who stole it * from Stevens... * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -28,8 +28,16 @@ * with the semantics it had in 9.2; in particular, this has different * behavior for SIGALRM than the version in src/port/pqsignal.c. * - * libpq itself does not use this. + * libpq itself does not use this, nor does anything else in our code. + * + * src/include/port.h #define's pqsignal as pqsignal_fe or pqsignal_be, + * but here we want to export just plain "pqsignal". We can't rely on + * port.h's extern declaration either. (The point of those #define's + * is to ensure that no in-tree code accidentally calls this version.) */ +#undef pqsignal +extern pqsigfunc pqsignal(int signo, pqsigfunc func); + pqsigfunc pqsignal(int signo, pqsigfunc func) { diff --git a/src/interfaces/libpq/libpq-events.c b/src/interfaces/libpq/libpq-events.c index c9d156ac35abb..a96e3694f1fa5 100644 --- a/src/interfaces/libpq/libpq-events.c +++ b/src/interfaces/libpq/libpq-events.c @@ -3,7 +3,7 @@ * libpq-events.c * functions for supporting the libpq "events" API * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/interfaces/libpq/libpq-events.h b/src/interfaces/libpq/libpq-events.h index 21af13b34d81f..38dba297ae8bd 100644 --- a/src/interfaces/libpq/libpq-events.h +++ b/src/interfaces/libpq/libpq-events.h @@ -5,7 +5,7 @@ * that invoke the libpq "events" API, but are not interesting to * ordinary users of libpq. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/libpq-events.h diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index 87a6f3df07440..7d3a9df6fd559 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -4,7 +4,7 @@ * This file contains definitions for structures and * externs for functions used by frontend postgres applications. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/libpq-fe.h @@ -20,6 +20,7 @@ extern "C" { #endif +#include #include /* @@ -30,15 +31,38 @@ extern "C" /* * These symbols may be used in compile-time #ifdef tests for the availability - * of newer libpq features. + * of v14-and-newer libpq features. */ +/* Features added in PostgreSQL v14: */ /* Indicates presence of PQenterPipelineMode and friends */ #define LIBPQ_HAS_PIPELINING 1 /* Indicates presence of PQsetTraceFlags; also new PQtrace output format */ #define LIBPQ_HAS_TRACE_FLAGS 1 + +/* Features added in PostgreSQL v15: */ /* Indicates that PQsslAttribute(NULL, "library") is useful */ #define LIBPQ_HAS_SSL_LIBRARY_DETECTION 1 +/* Features added in PostgreSQL v17: */ +/* Indicates presence of PGcancelConn typedef and associated routines */ +#define LIBPQ_HAS_ASYNC_CANCEL 1 +/* Indicates presence of PQchangePassword */ +#define LIBPQ_HAS_CHANGE_PASSWORD 1 +/* Indicates presence of PQsetChunkedRowsMode, PGRES_TUPLES_CHUNK */ +#define LIBPQ_HAS_CHUNK_MODE 1 +/* Indicates presence of PQclosePrepared, PQclosePortal, etc */ +#define LIBPQ_HAS_CLOSE_PREPARED 1 +/* Indicates presence of PQsendPipelineSync */ +#define LIBPQ_HAS_SEND_PIPELINE_SYNC 1 +/* Indicates presence of PQsocketPoll, PQgetCurrentTimeUSec */ +#define LIBPQ_HAS_SOCKET_POLL 1 + +/* Features added in PostgreSQL v18: */ +/* Indicates presence of PQfullProtocolVersion */ +#define LIBPQ_HAS_FULL_PROTOCOL_VERSION 1 +/* Indicates presence of the PQAUTHDATA_PROMPT_OAUTH_DEVICE authdata hook */ +#define LIBPQ_HAS_PROMPT_OAUTH_DEVICE 1 + /* * Option flags for PQcopyResult */ @@ -82,6 +106,8 @@ typedef enum CONNECTION_CHECK_STANDBY, /* Checking if server is in standby mode. */ CONNECTION_ALLOCATED, /* Waiting for connection attempt to be * started. */ + CONNECTION_AUTHENTICATING, /* Authentication is in progress with some + * external system. */ } ConnStatusType; typedef enum @@ -163,6 +189,13 @@ typedef enum PQ_PIPELINE_ABORTED } PGpipelineStatus; +typedef enum +{ + PQAUTHDATA_PROMPT_OAUTH_DEVICE, /* user must visit a device-authorization + * URL */ + PQAUTHDATA_OAUTH_BEARER_TOKEN, /* server requests an OAuth Bearer token */ +} PGauthData; + /* PGconn encapsulates a connection to the backend. * The contents of this struct are not supposed to be known to applications. */ @@ -201,8 +234,11 @@ typedef struct pgNotify struct pgNotify *next; /* list link */ } PGnotify; +/* deprecated name for int64_t */ +typedef int64_t pg_int64; + /* pg_usec_time_t is like time_t, but with microsecond resolution */ -typedef pg_int64 pg_usec_time_t; +typedef int64_t pg_usec_time_t; /* Function types for notice-handling callbacks */ typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); @@ -364,6 +400,7 @@ extern int PQrequestCancel(PGconn *conn); /* Accessor functions for PGconn objects */ extern char *PQdb(const PGconn *conn); +extern char *PQservice(const PGconn *conn); extern char *PQuser(const PGconn *conn); extern char *PQpass(const PGconn *conn); extern char *PQhost(const PGconn *conn); @@ -376,6 +413,7 @@ extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn); extern const char *PQparameterStatus(const PGconn *conn, const char *paramName); extern int PQprotocolVersion(const PGconn *conn); +extern int PQfullProtocolVersion(const PGconn *conn); extern int PQserverVersion(const PGconn *conn); extern char *PQerrorMessage(const PGconn *conn); extern int PQsocket(const PGconn *conn); @@ -657,13 +695,13 @@ extern int lo_close(PGconn *conn, int fd); extern int lo_read(PGconn *conn, int fd, char *buf, size_t len); extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len); extern int lo_lseek(PGconn *conn, int fd, int offset, int whence); -extern pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence); +extern int64_t lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence); extern Oid lo_creat(PGconn *conn, int mode); extern Oid lo_create(PGconn *conn, Oid lobjId); extern int lo_tell(PGconn *conn, int fd); -extern pg_int64 lo_tell64(PGconn *conn, int fd); +extern int64_t lo_tell64(PGconn *conn, int fd); extern int lo_truncate(PGconn *conn, int fd, size_t len); -extern int lo_truncate64(PGconn *conn, int fd, pg_int64 len); +extern int lo_truncate64(PGconn *conn, int fd, int64_t len); extern int lo_unlink(PGconn *conn, Oid lobjId); extern Oid lo_import(PGconn *conn, const char *filename); extern Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId); @@ -695,10 +733,86 @@ extern int PQenv2encoding(void); /* === in fe-auth.c === */ +typedef struct _PGpromptOAuthDevice +{ + const char *verification_uri; /* verification URI to visit */ + const char *user_code; /* user code to enter */ + const char *verification_uri_complete; /* optional combination of URI and + * code, or NULL */ + int expires_in; /* seconds until user code expires */ +} PGpromptOAuthDevice; + +/* for PGoauthBearerRequest.async() */ +#ifdef _WIN32 +#define SOCKTYPE uintptr_t /* avoids depending on winsock2.h for SOCKET */ +#else +#define SOCKTYPE int +#endif + +typedef struct PGoauthBearerRequest +{ + /* Hook inputs (constant across all calls) */ + const char *openid_configuration; /* OIDC discovery URI */ + const char *scope; /* required scope(s), or NULL */ + + /* Hook outputs */ + + /*--------- + * Callback implementing a custom asynchronous OAuth flow. + * + * The callback may return + * - PGRES_POLLING_READING/WRITING, to indicate that a socket descriptor + * has been stored in *altsock and libpq should wait until it is + * readable or writable before calling back; + * - PGRES_POLLING_OK, to indicate that the flow is complete and + * request->token has been set; or + * - PGRES_POLLING_FAILED, to indicate that token retrieval has failed. + * + * This callback is optional. If the token can be obtained without + * blocking during the original call to the PQAUTHDATA_OAUTH_BEARER_TOKEN + * hook, it may be returned directly, but one of request->async or + * request->token must be set by the hook. + */ + PostgresPollingStatusType (*async) (PGconn *conn, + struct PGoauthBearerRequest *request, + SOCKTYPE * altsock); + + /* + * Callback to clean up custom allocations. A hook implementation may use + * this to free request->token and any resources in request->user. + * + * This is technically optional, but highly recommended, because there is + * no other indication as to when it is safe to free the token. + */ + void (*cleanup) (PGconn *conn, struct PGoauthBearerRequest *request); + + /* + * The hook should set this to the Bearer token contents for the + * connection, once the flow is completed. The token contents must remain + * available to libpq until the hook's cleanup callback is called. + */ + char *token; + + /* + * Hook-defined data. libpq will not modify this pointer across calls to + * the async callback, so it can be used to keep track of + * application-specific state. Resources allocated here should be freed by + * the cleanup callback. + */ + void *user; +} PGoauthBearerRequest; + +#undef SOCKTYPE + extern char *PQencryptPassword(const char *passwd, const char *user); extern char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm); extern PGresult *PQchangePassword(PGconn *conn, const char *user, const char *passwd); +typedef int (*PQauthDataHook_type) (PGauthData type, PGconn *conn, void *data); +extern void PQsetAuthDataHook(PQauthDataHook_type hook); +extern PQauthDataHook_type PQgetAuthDataHook(void); +extern int PQdefaultAuthDataHook(PGauthData type, PGconn *conn, void *data); + /* === in encnames.c === */ extern int pg_char_to_encoding(const char *name); diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index f36d76bf3fedf..a6cfd7f5c9d83 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -9,7 +9,7 @@ * more likely to break across PostgreSQL releases than code that uses * only the official API. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/libpq-int.h @@ -44,13 +44,7 @@ #include "fe-auth-sasl.h" #include "pqexpbuffer.h" -#ifdef ENABLE_GSS -#if defined(HAVE_GSSAPI_H) -#include -#else -#include -#endif -#endif +#include "libpq/pg-gssapi.h" #ifdef ENABLE_SSPI #define SECURITY_WIN32 @@ -331,6 +325,18 @@ typedef enum PGQUERY_CLOSE /* Close Statement or Portal */ } PGQueryClass; + +/* + * valid values for pg_conn->current_auth_response. These are just for + * libpq internal use: since authentication response types all use the + * protocol byte 'p', fe-trace.c needs a way to distinguish them in order + * to print them correctly. + */ +#define AUTH_RESPONSE_GSS 'G' +#define AUTH_RESPONSE_PASSWORD 'P' +#define AUTH_RESPONSE_SASL_INITIAL 'I' +#define AUTH_RESPONSE_SASL 'S' + /* * An entry in the pending command queue. */ @@ -382,6 +388,7 @@ struct pg_conn char *fbappname; /* fallback application name */ char *dbName; /* database name */ char *replication; /* connect as the replication standby? */ + char *pgservice; /* Postgres service, if any */ char *pguser; /* Postgres username and password, if any */ char *pgpass; char *pgpassfile; /* path to a file containing password(s) */ @@ -410,16 +417,32 @@ struct pg_conn char *gsslib; /* What GSS library to use ("gssapi" or * "sspi") */ char *gssdelegation; /* Try to delegate GSS credentials? (0 or 1) */ + char *min_protocol_version; /* minimum used protocol version */ + char *max_protocol_version; /* maximum used protocol version */ char *ssl_min_protocol_version; /* minimum TLS protocol version */ char *ssl_max_protocol_version; /* maximum TLS protocol version */ char *target_session_attrs; /* desired session properties */ char *require_auth; /* name of the expected auth method */ char *load_balance_hosts; /* load balance over hosts */ + char *scram_client_key; /* base64-encoded SCRAM client key */ + char *scram_server_key; /* base64-encoded SCRAM server key */ + char *sslkeylogfile; /* where should the client write ssl keylogs */ bool cancelRequest; /* true if this connection is used to send a * cancel request, instead of being a normal * connection that's used for queries */ + /* OAuth v2 */ + char *oauth_issuer; /* token issuer/URL */ + char *oauth_issuer_id; /* token issuer identifier */ + char *oauth_discovery_uri; /* URI of the issuer's discovery + * document */ + char *oauth_client_id; /* client identifier */ + char *oauth_client_secret; /* client secret */ + char *oauth_scope; /* access token scope */ + char *oauth_token; /* access token */ + bool oauth_want_retry; /* should we retry on failure? */ + /* Optional file to write trace info to */ FILE *Pfdebug; int traceFlags; @@ -476,6 +499,8 @@ struct pg_conn SockAddr raddr; /* Remote address */ ProtocolVersion pversion; /* FE/BE protocol version in use */ int sversion; /* server version, e.g. 70401 for 7.4.1 */ + bool pversion_negotiated; /* true if NegotiateProtocolVersion + * was received */ bool auth_req_received; /* true if any type of auth req received */ bool password_needed; /* true if server demanded a password */ bool gssapi_used; /* true if authenticated via gssapi */ @@ -488,8 +513,18 @@ struct pg_conn * the server? */ uint32 allowed_auth_methods; /* bitmask of acceptable AuthRequest * codes */ + const pg_fe_sasl_mech *allowed_sasl_mechs[2]; /* and acceptable SASL + * mechanisms */ bool client_finished_auth; /* have we finished our half of the * authentication exchange? */ + char current_auth_response; /* used by pqTraceOutputMessage to + * know which auth response we're + * sending */ + + /* Callbacks for external async authentication */ + PostgresPollingStatusType (*async_auth) (PGconn *conn); + void (*cleanup_async_auth) (PGconn *conn); + pgsocket altsock; /* alternative socket for client to poll */ /* Transient state needed while establishing connection */ @@ -503,10 +538,17 @@ struct pg_conn AddrInfo *addr; /* the array of addresses for the currently * tried host */ bool send_appname; /* okay to send application_name? */ + size_t scram_client_key_len; + uint8 *scram_client_key_binary; /* binary SCRAM client key */ + size_t scram_server_key_len; + uint8 *scram_server_key_binary; /* binary SCRAM server key */ + ProtocolVersion min_pversion; /* protocol version to request */ + ProtocolVersion max_pversion; /* protocol version to request */ /* Miscellaneous stuff */ int be_pid; /* PID of backend --- needed for cancels */ - int be_key; /* key of backend --- needed for cancels */ + int be_cancel_key_len; + uint8 *be_cancel_key; /* query cancellation key */ pgParameterStatus *pstatus; /* ParameterStatus data */ int client_encoding; /* encoding id */ bool std_strings; /* standard_conforming_strings */ @@ -567,6 +609,7 @@ struct pg_conn bool ssl_handshake_started; bool ssl_cert_requested; /* Did the server ask us for a cert? */ bool ssl_cert_sent; /* Did we send one in reply? */ + bool last_read_was_eof; #ifdef USE_SSL #ifdef USE_OPENSSL @@ -578,11 +621,6 @@ struct pg_conn void *engine; /* dummy field to keep struct the same if * OpenSSL version changes */ #endif - bool crypto_loaded; /* Track if libcrypto locking callbacks have - * been done for this connection. This can be - * removed once support for OpenSSL 1.0.2 is - * removed as this locking is handled - * internally in OpenSSL >= 1.1.0. */ #endif /* USE_OPENSSL */ #endif /* USE_SSL */ @@ -730,6 +768,10 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid, int result_is_int, const PQArgBlock *args, int nargs); +/* === in fe-cancel.c === */ + +extern int PQsendCancelRequest(PGconn *cancelConn); + /* === in fe-misc.c === */ /* @@ -739,14 +781,15 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid, */ extern int pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn); extern int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn); +extern void pqParseDone(PGconn *conn, int newInStart); extern int pqGetc(char *result, PGconn *conn); extern int pqPutc(char c, PGconn *conn); extern int pqGets(PQExpBuffer buf, PGconn *conn); extern int pqGets_append(PQExpBuffer buf, PGconn *conn); extern int pqPuts(const char *s, PGconn *conn); -extern int pqGetnchar(char *s, size_t len, PGconn *conn); +extern int pqGetnchar(void *s, size_t len, PGconn *conn); extern int pqSkipnchar(size_t len, PGconn *conn); -extern int pqPutnchar(const char *s, size_t len, PGconn *conn); +extern int pqPutnchar(const void *s, size_t len, PGconn *conn); extern int pqGetInt(int *result, size_t bytes, PGconn *conn); extern int pqPutInt(int value, size_t bytes, PGconn *conn); extern int pqPutMsgStart(char msg_type, PGconn *conn); @@ -761,7 +804,6 @@ extern int pqWriteReady(PGconn *conn); /* === in fe-secure.c === */ -extern int pqsecure_initialize(PGconn *, bool, bool); extern PostgresPollingStatusType pqsecure_open_client(PGconn *); extern void pqsecure_close(PGconn *); extern ssize_t pqsecure_read(PGconn *, void *ptr, size_t len); @@ -781,23 +823,6 @@ extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, * The SSL implementation provides these functions. */ -/* - * Implementation of PQinitSSL(). - */ -extern void pgtls_init_library(bool do_ssl, int do_crypto); - -/* - * Initialize SSL library. - * - * The conn parameter is only used to be able to pass back an error - * message - no connection-local setup is made here. do_ssl controls - * if SSL is initialized, and do_crypto does the same for the crypto - * part. - * - * Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage). - */ -extern int pgtls_init(PGconn *conn, bool do_ssl, bool do_crypto); - /* * Begin or continue negotiating a secure session. */ @@ -875,6 +900,8 @@ extern ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len); extern void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer); extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message); +extern void pqTraceOutputCharResponse(PGconn *conn, const char *responseType, + char response); /* === miscellaneous macros === */ diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build index 7623aeadab740..a74e885b169d7 100644 --- a/src/interfaces/libpq/meson.build +++ b/src/interfaces/libpq/meson.build @@ -1,9 +1,7 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group - -# test/ is entered via top-level meson.build, that way it can use the default -# args for executables (which depend on libpq). +# Copyright (c) 2022-2025, PostgreSQL Global Development Group libpq_sources = files( + 'fe-auth-oauth.c', 'fe-auth-scram.c', 'fe-auth.c', 'fe-cancel.c', @@ -48,6 +46,9 @@ export_file = custom_target('libpq.exports', libpq_inc = include_directories('.', '../../port') libpq_c_args = ['-DSO_MAJOR_VERSION=5'] +# The OAuth implementation differs depending on the type of library being built. +libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH'] + # Not using both_libraries() here as # 1) resource files should only be in the shared library # 2) we want the .pc file to include a dependency to {pgport,common}_static for @@ -68,7 +69,7 @@ libpq_st = static_library('libpq', libpq_so = shared_library('libpq', libpq_sources + libpq_so_sources, include_directories: [libpq_inc, postgres_inc], - c_args: libpq_c_args, + c_args: libpq_c_args + libpq_so_c_args, c_pch: pch_postgres_fe_h, version: '5.' + pg_version_major.to_string(), soversion: host_system != 'windows' ? '5' : '', @@ -84,12 +85,26 @@ libpq = declare_dependency( include_directories: [include_directories('.')] ) +private_deps = [ + frontend_stlib_code, + libpq_deps, +] + +if oauth_flow_supported + # libpq.so doesn't link against libcurl, but libpq.a needs libpq-oauth, and + # libpq-oauth needs libcurl. Put both into *.private. + private_deps += [ + libpq_oauth_deps, + '-lpq-oauth', + ] +endif + pkgconfig.generate( name: 'libpq', description: 'PostgreSQL libpq library', url: pg_url, libraries: libpq, - libraries_private: [frontend_stlib_code, libpq_deps], + libraries_private: private_deps, ) install_headers( @@ -107,6 +122,7 @@ install_data('pg_service.conf.sample', install_dir: dir_data, ) +subdir('test') tests += { 'name': 'libpq', @@ -119,13 +135,14 @@ tests += { 't/003_load_balance_host_list.pl', 't/004_load_balance_dns.pl', 't/005_negotiate_encryption.pl', + 't/006_service.pl', ], 'env': { - 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', 'with_ssl': ssl_library, 'with_gssapi': gssapi.found() ? 'yes' : 'no', 'with_krb_srvnam': 'postgres', }, + 'deps': libpq_test_deps, }, } diff --git a/src/interfaces/libpq/nls.mk b/src/interfaces/libpq/nls.mk index 4788088eb9365..b87df277d930d 100644 --- a/src/interfaces/libpq/nls.mk +++ b/src/interfaces/libpq/nls.mk @@ -14,15 +14,20 @@ GETTEXT_FILES = fe-auth.c \ fe-secure-gssapi.c \ fe-secure-openssl.c \ win32.c \ - ../../port/user.c -GETTEXT_TRIGGERS = libpq_append_conn_error:2 \ + ../libpq-oauth/oauth-curl.c \ + ../libpq-oauth/oauth-utils.c +GETTEXT_TRIGGERS = actx_error:2 \ + libpq_append_conn_error:2 \ libpq_append_error:2 \ libpq_gettext \ libpq_ngettext:1,2 \ + oauth_parse_set_error:2 \ pqInternalNotice:2 -GETTEXT_FLAGS = libpq_append_conn_error:2:c-format \ +GETTEXT_FLAGS = actx_error:2:c-format \ + libpq_append_conn_error:2:c-format \ libpq_append_error:2:c-format \ libpq_gettext:1:pass-c-format \ libpq_ngettext:1:pass-c-format \ libpq_ngettext:2:pass-c-format \ + oauth_parse_set_error:2:c-format \ pqInternalNotice:2:c-format diff --git a/src/interfaces/libpq/po/de.po b/src/interfaces/libpq/po/de.po index e04de1db57cda..ca479767fe135 100644 --- a/src/interfaces/libpq/po/de.po +++ b/src/interfaces/libpq/po/de.po @@ -1,14 +1,14 @@ # German message translation file for libpq -# Peter Eisentraut , 2001 - 2024. +# Peter Eisentraut , 2001 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-13 05:40+0000\n" -"PO-Revision-Date: 2024-06-13 10:33+0200\n" +"POT-Creation-Date: 2025-03-07 09:40+0000\n" +"PO-Revision-Date: 2025-03-07 11:51+0100\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -17,317 +17,322 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../../port/user.c:43 ../../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "konnte lokale Benutzer-ID %d nicht nachschlagen: %s" - -#: ../../port/user.c:48 ../../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "lokaler Benutzer mit ID %d existiert nicht" - -#: fe-auth-scram.c:223 +#: fe-auth-scram.c:228 #, c-format msgid "malformed SCRAM message (empty message)" msgstr "fehlerhafte SCRAM-Nachricht (leere Nachricht)" -#: fe-auth-scram.c:228 +#: fe-auth-scram.c:233 #, c-format msgid "malformed SCRAM message (length mismatch)" msgstr "fehlerhafte SCRAM-Nachricht (Länge stimmt nicht überein)" -#: fe-auth-scram.c:272 +#: fe-auth-scram.c:277 #, c-format msgid "could not verify server signature: %s" msgstr "konnte Serversignatur nicht überprüfen: %s" -#: fe-auth-scram.c:278 +#: fe-auth-scram.c:283 #, c-format msgid "incorrect server signature" msgstr "falsche Serversignatur" -#: fe-auth-scram.c:287 +#: fe-auth-scram.c:292 #, c-format msgid "invalid SCRAM exchange state" msgstr "ungültiger Zustand des SCRAM-Austauschs" -#: fe-auth-scram.c:311 +#: fe-auth-scram.c:316 #, c-format msgid "malformed SCRAM message (attribute \"%c\" expected)" msgstr "fehlerhafte SCRAM-Nachricht (Attribut »%c« erwartet)" -#: fe-auth-scram.c:320 +#: fe-auth-scram.c:325 #, c-format msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" msgstr "fehlerhafte SCRAM-Nachricht (Zeichen »=« für Attribut »%c« erwartet)" -#: fe-auth-scram.c:360 +#: fe-auth-scram.c:365 #, c-format msgid "could not generate nonce" msgstr "konnte Nonce nicht erzeugen" -#: fe-auth-scram.c:369 fe-auth-scram.c:442 fe-auth-scram.c:594 -#: fe-auth-scram.c:614 fe-auth-scram.c:638 fe-auth-scram.c:652 -#: fe-auth-scram.c:698 fe-auth-scram.c:734 fe-auth-scram.c:908 fe-auth.c:296 -#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:727 fe-auth.c:1199 -#: fe-auth.c:1362 fe-cancel.c:159 fe-connect.c:936 fe-connect.c:976 -#: fe-connect.c:1860 fe-connect.c:2022 fe-connect.c:3443 fe-connect.c:4771 -#: fe-connect.c:5083 fe-connect.c:5338 fe-connect.c:5456 fe-connect.c:5703 -#: fe-connect.c:5783 fe-connect.c:5881 fe-connect.c:6132 fe-connect.c:6159 -#: fe-connect.c:6235 fe-connect.c:6258 fe-connect.c:6282 fe-connect.c:6317 -#: fe-connect.c:6403 fe-connect.c:6411 fe-connect.c:6768 fe-connect.c:6918 -#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4234 fe-exec.c:4398 +#: fe-auth-scram.c:374 fe-auth-scram.c:447 fe-auth-scram.c:599 +#: fe-auth-scram.c:619 fe-auth-scram.c:643 fe-auth-scram.c:657 +#: fe-auth-scram.c:703 fe-auth-scram.c:739 fe-auth-scram.c:931 fe-auth.c:308 +#: fe-auth.c:382 fe-auth.c:416 fe-auth.c:694 fe-auth.c:827 fe-auth.c:1330 +#: fe-auth.c:1493 fe-cancel.c:159 fe-connect.c:984 fe-connect.c:1024 +#: fe-connect.c:2106 fe-connect.c:2268 fe-connect.c:3667 fe-connect.c:5106 +#: fe-connect.c:5419 fe-connect.c:5674 fe-connect.c:5792 fe-connect.c:6039 +#: fe-connect.c:6119 fe-connect.c:6217 fe-connect.c:6468 fe-connect.c:6495 +#: fe-connect.c:6571 fe-connect.c:6594 fe-connect.c:6618 fe-connect.c:6653 +#: fe-connect.c:6739 fe-connect.c:6747 fe-connect.c:7104 fe-connect.c:7286 +#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4291 fe-exec.c:4457 #: fe-gssapi-common.c:109 fe-lobj.c:870 fe-protocol3.c:209 fe-protocol3.c:232 #: fe-protocol3.c:255 fe-protocol3.c:272 fe-protocol3.c:293 fe-protocol3.c:369 -#: fe-protocol3.c:737 fe-protocol3.c:976 fe-protocol3.c:1787 -#: fe-protocol3.c:2187 fe-secure-common.c:110 fe-secure-gssapi.c:496 -#: fe-secure-openssl.c:427 fe-secure-openssl.c:1277 +#: fe-protocol3.c:733 fe-protocol3.c:972 fe-protocol3.c:1779 +#: fe-protocol3.c:2180 fe-secure-common.c:110 fe-secure-gssapi.c:496 +#: fe-secure-openssl.c:404 fe-secure-openssl.c:1073 #, c-format msgid "out of memory" msgstr "Speicher aufgebraucht" -#: fe-auth-scram.c:376 +#: fe-auth-scram.c:381 #, c-format msgid "could not encode nonce" msgstr "konnte Nonce nicht kodieren" -#: fe-auth-scram.c:564 +#: fe-auth-scram.c:569 #, c-format msgid "could not calculate client proof: %s" msgstr "konnte Client-Proof nicht berechnen: %s" -#: fe-auth-scram.c:579 +#: fe-auth-scram.c:584 #, c-format msgid "could not encode client proof" msgstr "konnte Client-Proof nicht kodieren" -#: fe-auth-scram.c:631 +#: fe-auth-scram.c:636 #, c-format msgid "invalid SCRAM response (nonce mismatch)" msgstr "ungültige SCRAM-Antwort (Nonce stimmt nicht überein)" -#: fe-auth-scram.c:661 +#: fe-auth-scram.c:666 #, c-format msgid "malformed SCRAM message (invalid salt)" msgstr "fehlerhafte SCRAM-Nachricht (ungültiges Salt)" -#: fe-auth-scram.c:674 +#: fe-auth-scram.c:679 #, c-format msgid "malformed SCRAM message (invalid iteration count)" msgstr "fehlerhafte SCRAM-Nachricht (ungültige Iterationszahl)" -#: fe-auth-scram.c:679 +#: fe-auth-scram.c:684 #, c-format msgid "malformed SCRAM message (garbage at end of server-first-message)" msgstr "fehlerhafte SCRAM-Nachricht (Müll am Ende der »server-first-message«)" -#: fe-auth-scram.c:713 +#: fe-auth-scram.c:718 #, c-format msgid "error received from server in SCRAM exchange: %s" msgstr "Fehler vom Server empfangen im SCRAM-Austausch: %s" -#: fe-auth-scram.c:728 +#: fe-auth-scram.c:733 #, c-format msgid "malformed SCRAM message (garbage at end of server-final-message)" msgstr "fehlerhafte SCRAM-Nachricht (Müll am Ende der »server-final-message«)" -#: fe-auth-scram.c:745 +#: fe-auth-scram.c:750 #, c-format msgid "malformed SCRAM message (invalid server signature)" msgstr "fehlerhafte SCRAM-Nachricht (ungültige Serversignatur)" -#: fe-auth-scram.c:917 +#: fe-auth-scram.c:940 msgid "could not generate random salt" msgstr "konnte zufälliges Salt nicht erzeugen" -#: fe-auth.c:77 +#: fe-auth.c:80 #, c-format msgid "out of memory allocating GSSAPI buffer (%d)" msgstr "Speicher aufgebraucht beim Anlegen des GSSAPI-Puffers (%d)" -#: fe-auth.c:138 +#: fe-auth.c:146 msgid "GSSAPI continuation error" msgstr "GSSAPI-Fortsetzungsfehler" -#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-auth.c:176 fe-auth.c:410 fe-gssapi-common.c:97 fe-secure-common.c:99 #: fe-secure-common.c:173 #, c-format msgid "host name must be specified" msgstr "Hostname muss angegeben werden" -#: fe-auth.c:174 +#: fe-auth.c:182 #, c-format msgid "duplicate GSS authentication request" msgstr "doppelte GSSAPI-Authentifizierungsanfrage" -#: fe-auth.c:238 +#: fe-auth.c:246 #, c-format msgid "out of memory allocating SSPI buffer (%d)" msgstr "Speicher aufgebraucht beim Anlegen des SSPI-Puffers (%d)" -#: fe-auth.c:285 +#: fe-auth.c:297 msgid "SSPI continuation error" msgstr "SSPI-Fortsetzungsfehler" -#: fe-auth.c:359 +#: fe-auth.c:372 #, c-format msgid "duplicate SSPI authentication request" msgstr "doppelte SSPI-Authentifizierungsanfrage" -#: fe-auth.c:384 +#: fe-auth.c:397 msgid "could not acquire SSPI credentials" msgstr "konnte SSPI-Credentials nicht erhalten" -#: fe-auth.c:436 +#: fe-auth.c:449 #, c-format msgid "channel binding required, but SSL not in use" msgstr "Channel-Binding wurde verlangt, aber SSL wird nicht verwendet" -#: fe-auth.c:442 +#: fe-auth.c:455 #, c-format msgid "duplicate SASL authentication request" msgstr "doppelte SASL-Authentifizierungsanfrage" -#: fe-auth.c:500 +#: fe-auth.c:513 #, c-format msgid "channel binding is required, but client does not support it" msgstr "Channel-Binding wurde verlangt, aber der Client unterstützt es nicht" -#: fe-auth.c:516 +#: fe-auth.c:529 #, c-format msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" msgstr "Server hat Authentifizierung mit SCRAM-SHA-256-PLUS über eine Verbindung ohne SSL angeboten" -#: fe-auth.c:531 +#: fe-auth.c:551 #, c-format msgid "none of the server's SASL authentication mechanisms are supported" msgstr "keine der SASL-Authentifizierungsmechanismen des Servers werden unterstützt" -#: fe-auth.c:538 +#: fe-auth.c:571 +#, c-format +msgid "authentication method requirement \"%s\" failed: server requested %s authentication" +msgstr "Authentifizierungsmethodenanforderung »%s« fehlgeschlagen: Server hat »%s«-Authentifizierung verlangt" + +#: fe-auth.c:580 #, c-format msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" msgstr "Channel-Binding wurde verlangt, aber der Server hat keine Authentifizierungsmethode mit Channel-Binding angeboten" -#: fe-auth.c:640 +#: fe-auth.c:716 #, c-format msgid "out of memory allocating SASL buffer (%d)" msgstr "Speicher aufgebraucht beim Anlegen des SASL-Puffers (%d)" -#: fe-auth.c:663 +#: fe-auth.c:758 #, c-format msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" msgstr "AuthenticationSASLFinal vom Server empfangen, aber SASL-Authentifizierung war noch nicht abgeschlossen" -#: fe-auth.c:673 +#: fe-auth.c:768 #, c-format msgid "no client response found after SASL exchange success" msgstr "keine Client-Antwort gefunden nach Erfolg des SASL-Austauschs" -#: fe-auth.c:736 fe-auth.c:743 fe-auth.c:1345 fe-auth.c:1356 +#: fe-auth.c:836 fe-auth.c:843 fe-auth.c:1476 fe-auth.c:1487 #, c-format msgid "could not encrypt password: %s" msgstr "konnte Passwort nicht verschlüsseln: %s" -#: fe-auth.c:771 +#: fe-auth.c:873 msgid "server requested a cleartext password" msgstr "Server hat ein Passwort im Klartext verlangt" -#: fe-auth.c:773 +#: fe-auth.c:875 msgid "server requested a hashed password" msgstr "Server hat ein gehashtes Passwort verlangt" -#: fe-auth.c:776 +#: fe-auth.c:878 msgid "server requested GSSAPI authentication" msgstr "Server hat GSSAPI-Authentifizierung verlangt" -#: fe-auth.c:778 +#: fe-auth.c:880 msgid "server requested SSPI authentication" msgstr "Server hat SSPI-Authentifizierung verlangt" -#: fe-auth.c:782 +#: fe-auth.c:884 msgid "server requested SASL authentication" msgstr "Server hat SASL-Authentifizierung verlangt" -#: fe-auth.c:785 +#: fe-auth.c:887 msgid "server requested an unknown authentication type" msgstr "Server hat einen unbekannten Authentifizierungstyp verlangt" -#: fe-auth.c:818 +#: fe-auth.c:920 #, c-format msgid "server did not request an SSL certificate" msgstr "Server hat kein SSL-Zertifikat verlangt" -#: fe-auth.c:823 +#: fe-auth.c:925 #, c-format msgid "server accepted connection without a valid SSL certificate" msgstr "Server hat Verbindung ohne gültiges SSL-Zertifikat angenommen" -#: fe-auth.c:877 +#: fe-auth.c:979 msgid "server did not complete authentication" msgstr "Server hat Authentifizierung nicht abgeschlossen" -#: fe-auth.c:911 +#: fe-auth.c:1013 #, c-format msgid "authentication method requirement \"%s\" failed: %s" msgstr "Authentifizierungsmethodenanforderung »%s« fehlgeschlagen: %s" -#: fe-auth.c:934 +#: fe-auth.c:1036 #, c-format msgid "channel binding required, but server authenticated client without channel binding" msgstr "Channel-Binding wurde verlangt, aber der Server hat den Client ohne Channel-Binding authentifiziert" -#: fe-auth.c:939 +#: fe-auth.c:1041 #, c-format msgid "channel binding required but not supported by server's authentication request" msgstr "Channel-Binding wurde verlangt aber von der Authentifizierungsanfrage des Servers nicht unterstützt" -#: fe-auth.c:973 +#: fe-auth.c:1081 #, c-format msgid "Kerberos 4 authentication not supported" msgstr "Authentifizierung mit Kerberos 4 nicht unterstützt" -#: fe-auth.c:977 +#: fe-auth.c:1085 #, c-format msgid "Kerberos 5 authentication not supported" msgstr "Authentifizierung mit Kerberos 5 nicht unterstützt" -#: fe-auth.c:1047 +#: fe-auth.c:1155 #, c-format msgid "GSSAPI authentication not supported" msgstr "Authentifizierung mit GSSAPI nicht unterstützt" -#: fe-auth.c:1078 +#: fe-auth.c:1186 #, c-format msgid "SSPI authentication not supported" msgstr "Authentifizierung mit SSPI nicht unterstützt" -#: fe-auth.c:1085 +#: fe-auth.c:1193 #, c-format msgid "Crypt authentication not supported" msgstr "Authentifizierung mit Crypt nicht unterstützt" -#: fe-auth.c:1149 +#: fe-auth.c:1267 #, c-format msgid "authentication method %u not supported" msgstr "Authentifizierungsmethode %u nicht unterstützt" -#: fe-auth.c:1186 +#: fe-auth.c:1307 #, c-format msgid "user name lookup failure: error code %lu" msgstr "Fehler beim Nachschlagen des Benutzernamens: Fehlercode %lu" -#: fe-auth.c:1308 +#: fe-auth.c:1315 +#, c-format +msgid "could not look up local user ID %ld: %m" +msgstr "konnte lokale Benutzer-ID %ld nicht nachschlagen: %m" + +#: fe-auth.c:1320 +#, c-format +msgid "local user with ID %ld does not exist" +msgstr "lokaler Benutzer mit ID %ld existiert nicht" + +#: fe-auth.c:1439 #, c-format msgid "unexpected shape of result set returned for SHOW" msgstr "unerwartete Form der Ergebnismenge von SHOW" -#: fe-auth.c:1316 +#: fe-auth.c:1447 #, c-format msgid "\"password_encryption\" value too long" msgstr "Wert von »password_encryption« ist zu lang" -#: fe-auth.c:1366 +#: fe-auth.c:1497 #, c-format msgid "unrecognized password encryption algorithm \"%s\"" msgstr "unbekannter Passwortverschlüsselungsalgorithmus »%s«" @@ -337,7 +342,7 @@ msgstr "unbekannter Passwortverschlüsselungsalgorithmus »%s«" msgid "connection pointer is NULL" msgstr "Verbindung ist ein NULL-Zeiger" -#: fe-cancel.c:82 fe-misc.c:572 +#: fe-cancel.c:82 fe-misc.c:587 #, c-format msgid "connection not open" msgstr "Verbindung nicht offen" @@ -352,466 +357,516 @@ msgstr "Stornierungsanfrage wird auf dieser Verbindung bereits gesendet" msgid "unexpected response from server" msgstr "unerwartete Antwort vom Server" -#: fe-connect.c:1182 +#: fe-connect.c:1281 #, c-format msgid "could not match %d host names to %d hostaddr values" msgstr "fehlerhafte Angabe: %d Hostnamen und %d hostaddr-Angaben" -#: fe-connect.c:1262 +#: fe-connect.c:1361 #, c-format msgid "could not match %d port numbers to %d hosts" msgstr "fehlerhafte Angabe: %d Portnummern und %d Hosts" -#: fe-connect.c:1387 +#: fe-connect.c:1489 #, c-format msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" msgstr "negative require_auth-Methode »%s« kann nicht mit nicht-negativen Methoden vermischt werden" -#: fe-connect.c:1400 +#: fe-connect.c:1502 #, c-format msgid "require_auth method \"%s\" cannot be mixed with negative methods" msgstr "require_auth-Methode »%s« kann nicht mit negativen Methoden vermischt werden" -#: fe-connect.c:1460 fe-connect.c:1511 fe-connect.c:1553 fe-connect.c:1596 -#: fe-connect.c:1699 fe-connect.c:1745 fe-connect.c:1785 fe-connect.c:1806 +#: fe-connect.c:1578 fe-connect.c:1707 fe-connect.c:1749 fe-connect.c:1792 +#: fe-connect.c:1895 fe-connect.c:1941 fe-connect.c:1981 fe-connect.c:2052 #, c-format msgid "invalid %s value: \"%s\"" msgstr "ungültiger %s-Wert: »%s«" -#: fe-connect.c:1493 +#: fe-connect.c:1620 +#, c-format +msgid "internal error: no space in allowed_sasl_mechs" +msgstr "" + +#: fe-connect.c:1659 #, c-format msgid "require_auth method \"%s\" is specified more than once" msgstr "require_auth-Methode »%s« ist mehrmals angegeben" -#: fe-connect.c:1534 fe-connect.c:1573 fe-connect.c:1605 fe-connect.c:1707 +#: fe-connect.c:1730 fe-connect.c:1769 fe-connect.c:1801 fe-connect.c:1903 #, c-format msgid "%s value \"%s\" invalid when SSL support is not compiled in" msgstr "%s-Wert »%s« ist ungültig, wenn SSL-Unterstützung nicht einkompiliert worden ist" -#: fe-connect.c:1625 +#: fe-connect.c:1821 #, c-format msgid "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")" msgstr "schwacher sslmode »%s« darf nicht mit sslnegotiation=direct verwendet werden (»require«, »verify-ca« oder »verify-full« verwenden)" -#: fe-connect.c:1647 +#: fe-connect.c:1843 #, c-format msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" msgstr "schwacher sslmode »%s« darf nicht mit sslrootcert=system verwendet werden (»verify-full« verwenden)" -#: fe-connect.c:1660 fe-connect.c:1668 +#: fe-connect.c:1856 fe-connect.c:1864 #, c-format msgid "invalid \"%s\" value: \"%s\"" msgstr "ungültiger »%s«-Wert: »%s«" -#: fe-connect.c:1685 +#: fe-connect.c:1881 #, c-format msgid "invalid SSL protocol version range" msgstr "ungültiges SSL-Protokollsintervall" -#: fe-connect.c:1722 +#: fe-connect.c:1918 #, c-format msgid "%s value \"%s\" is not supported (check OpenSSL version)" msgstr "%s-Wert »%s« wird nicht unterstützt (OpenSSL-Version prüfen)" -#: fe-connect.c:1752 +#: fe-connect.c:1948 #, c-format msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" msgstr "gssencmode-Wert »%s« ist ungültig, wenn GSSAPI-Unterstützung nicht einkompiliert worden ist" -#: fe-connect.c:2045 +#: fe-connect.c:2002 +#, c-format +msgid "invalid SCRAM client key" +msgstr "ungültiger SCRAM-Client-Schlüssel" + +#: fe-connect.c:2008 +#, c-format +msgid "invalid SCRAM client key length: %d" +msgstr "ungültige SCRAM-Client-Schlüssel-Länge: %d" + +#: fe-connect.c:2027 +#, c-format +msgid "invalid SCRAM server key" +msgstr "ungültiger SCRAM-Server-Schlüssel" + +#: fe-connect.c:2033 +#, c-format +msgid "invalid SCRAM server key length: %d" +msgstr "ungültige SCRAM-Server-Schlüssel-Länge: %d" + +#: fe-connect.c:2291 #, c-format msgid "could not set socket to TCP no delay mode: %s" msgstr "konnte Socket nicht auf TCP »No Delay«-Modus umstellen: %s" -#: fe-connect.c:2104 +#: fe-connect.c:2350 #, c-format msgid "connection to server on socket \"%s\" failed: " msgstr "Verbindung zum Server auf Socket »%s« fehlgeschlagen: " -#: fe-connect.c:2130 +#: fe-connect.c:2376 #, c-format msgid "connection to server at \"%s\" (%s), port %s failed: " msgstr "Verbindung zum Server auf »%s« (%s), Port %s fehlgeschlagen: " -#: fe-connect.c:2135 +#: fe-connect.c:2381 #, c-format msgid "connection to server at \"%s\", port %s failed: " msgstr "Verbindung zum Server auf »%s«, Port %s fehlgeschlagen: " -#: fe-connect.c:2158 +#: fe-connect.c:2404 #, c-format msgid "\tIs the server running locally and accepting connections on that socket?" msgstr "\tLäuft der Server lokal und akzeptiert er Verbindungen auf diesem Socket?" -#: fe-connect.c:2160 +#: fe-connect.c:2406 #, c-format msgid "\tIs the server running on that host and accepting TCP/IP connections?" msgstr "\tLäuft der Server auf diesem Host und akzeptiert er TCP/IP-Verbindungen?" -#: fe-connect.c:2206 fe-connect.c:2240 fe-connect.c:2275 fe-connect.c:2373 -#: fe-connect.c:3111 +#: fe-connect.c:2452 fe-connect.c:2486 fe-connect.c:2521 fe-connect.c:2619 +#: fe-connect.c:3345 #, c-format msgid "%s(%s) failed: %s" msgstr "%s(%s) fehlgeschlagen: %s" -#: fe-connect.c:2339 +#: fe-connect.c:2585 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) fehlgeschlagen: Fehlercode %d" -#: fe-connect.c:2663 +#: fe-connect.c:2897 #, c-format msgid "invalid connection state, probably indicative of memory corruption" msgstr "ungültiger Verbindungszustand, möglicherweise ein Speicherproblem" -#: fe-connect.c:2746 +#: fe-connect.c:2980 #, c-format msgid "invalid port number: \"%s\"" msgstr "ungültige Portnummer: »%s«" -#: fe-connect.c:2760 +#: fe-connect.c:2994 #, c-format msgid "could not translate host name \"%s\" to address: %s" msgstr "konnte Hostnamen »%s« nicht in Adresse übersetzen: %s" -#: fe-connect.c:2772 +#: fe-connect.c:3006 #, c-format msgid "could not parse network address \"%s\": %s" msgstr "konnte Netzwerkadresse »%s« nicht interpretieren: %s" -#: fe-connect.c:2783 +#: fe-connect.c:3017 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Unix-Domain-Socket-Pfad »%s« ist zu lang (maximal %d Bytes)" -#: fe-connect.c:2797 +#: fe-connect.c:3031 #, c-format msgid "could not translate Unix-domain socket path \"%s\" to address: %s" msgstr "konnte Unix-Domain-Socket-Pfad »%s« nicht in Adresse übersetzen: %s" -#: fe-connect.c:2963 fe-connect.c:4315 +#: fe-connect.c:3197 fe-connect.c:4641 #, c-format msgid "GSSAPI encryption required but it is not supported over a local socket" msgstr "GSSAPI-Verschlüsselung war gefordert aber wird über lokales Socket nicht unterstützt" -#: fe-connect.c:2971 fe-connect.c:4444 +#: fe-connect.c:3205 fe-connect.c:4770 #, c-format msgid "GSSAPI encryption required but no credential cache" msgstr "GSSAPI-Verschlüsselung war gefordert aber kein Credential-Cache" -#: fe-connect.c:3039 +#: fe-connect.c:3273 #, c-format msgid "could not create socket: %s" msgstr "konnte Socket nicht erzeugen: %s" -#: fe-connect.c:3070 +#: fe-connect.c:3304 #, c-format msgid "could not set socket to nonblocking mode: %s" msgstr "konnte Socket nicht auf nicht-blockierenden Modus umstellen: %s" -#: fe-connect.c:3081 +#: fe-connect.c:3315 #, c-format msgid "could not set socket to close-on-exec mode: %s" msgstr "konnte Socket nicht auf »Close on exec«-Modus umstellen: %s" -#: fe-connect.c:3099 -#, c-format -msgid "keepalives parameter must be an integer" -msgstr "Parameter »keepalives« muss eine ganze Zahl sein" - -#: fe-connect.c:3238 +#: fe-connect.c:3472 #, c-format msgid "could not get socket error status: %s" msgstr "konnte Socket-Fehlerstatus nicht ermitteln: %s" -#: fe-connect.c:3265 +#: fe-connect.c:3499 #, c-format msgid "could not get client address from socket: %s" msgstr "konnte Client-Adresse vom Socket nicht ermitteln: %s" -#: fe-connect.c:3291 +#: fe-connect.c:3525 #, c-format msgid "requirepeer parameter is not supported on this platform" msgstr "Parameter »requirepeer« wird auf dieser Plattform nicht unterstützt" -#: fe-connect.c:3293 +#: fe-connect.c:3527 #, c-format msgid "could not get peer credentials: %s" msgstr "konnte Credentials von Gegenstelle nicht ermitteln: %s" -#: fe-connect.c:3306 +#: fe-connect.c:3540 #, c-format msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" msgstr "requirepeer gibt »%s« an, aber tatsächlicher Benutzername der Gegenstelle ist »%s«" -#: fe-connect.c:3344 +#: fe-connect.c:3578 #, c-format msgid "could not send GSSAPI negotiation packet: %s" msgstr "konnte Paket zur GSSAPI-Verhandlung nicht senden: %s" -#: fe-connect.c:3393 +#: fe-connect.c:3617 #, c-format msgid "could not send SSL negotiation packet: %s" msgstr "konnte Paket zur SSL-Verhandlung nicht senden: %s" -#: fe-connect.c:3425 +#: fe-connect.c:3649 #, c-format msgid "could not send cancel packet: %s" msgstr "konnte Cancel-Paket nicht senden: %s" -#: fe-connect.c:3455 +#: fe-connect.c:3679 #, c-format msgid "could not send startup packet: %s" msgstr "konnte Startpaket nicht senden: %s" -#: fe-connect.c:3522 +#: fe-connect.c:3752 msgid "server does not support SSL, but SSL was required" msgstr "Server unterstützt kein SSL, aber SSL wurde verlangt" -#: fe-connect.c:3541 +#: fe-connect.c:3762 +#, c-format +msgid "server sent an error response during SSL exchange" +msgstr "Server hat während des SSL-Austauschs eine Fehlermeldung gesendet" + +#: fe-connect.c:3767 #, c-format msgid "received invalid response to SSL negotiation: %c" msgstr "ungültige Antwort auf SSL-Verhandlungspaket empfangen: %c" -#: fe-connect.c:3569 +#: fe-connect.c:3787 #, c-format msgid "received unencrypted data after SSL response" msgstr "unverschlüsselte Daten nach SSL-Antwort empfangen" -#: fe-connect.c:3643 +#: fe-connect.c:3850 +#, c-format +msgid "server sent an error response during GSS encryption exchange" +msgstr "Server hat während des GSS-Verschlüsselungsaustauschs eine Fehlermeldung gesendet" + +#: fe-connect.c:3868 msgid "server doesn't support GSSAPI encryption, but it was required" msgstr "Server unterstützt keine GSSAPI-Verschlüsselung, sie wurde aber verlangt" -#: fe-connect.c:3647 +#: fe-connect.c:3872 #, c-format msgid "received invalid response to GSSAPI negotiation: %c" msgstr "ungültige Antwort auf GSSAPI-Verhandlungspaket empfangen: %c" -#: fe-connect.c:3665 +#: fe-connect.c:3894 #, c-format msgid "received unencrypted data after GSSAPI encryption response" msgstr "unverschlüsselte Daten nach GSSAPI-Verschlüsselungsantwort empfangen" -#: fe-connect.c:3721 +#: fe-connect.c:3955 #, c-format msgid "expected authentication request from server, but received %c" msgstr "Authentifizierungsanfrage wurde vom Server erwartet, aber %c wurde empfangen" -#: fe-connect.c:3749 fe-connect.c:3872 +#: fe-connect.c:3983 fe-connect.c:4106 #, c-format msgid "received invalid authentication request" msgstr "ungültige Authentifizierungsanforderung empfangen" -#: fe-connect.c:3755 fe-connect.c:3857 +#: fe-connect.c:3989 fe-connect.c:4091 #, c-format msgid "received invalid protocol negotiation message" msgstr "ungültige Protokollverhandlungsnachricht empfangen" -#: fe-connect.c:3774 fe-connect.c:3828 +#: fe-connect.c:4008 fe-connect.c:4062 #, c-format msgid "received invalid error message" msgstr "ungültige Fehlermeldung empfangen" -#: fe-connect.c:3943 +#: fe-connect.c:4185 +#, c-format +msgid "internal error: async authentication has no handler" +msgstr "" + +#: fe-connect.c:4210 +#, c-format +msgid "internal error: async cleanup did not release polling socket" +msgstr "" + +#: fe-connect.c:4233 +#, c-format +msgid "internal error: async authentication did not set a socket for polling" +msgstr "" + +#: fe-connect.c:4266 #, c-format msgid "unexpected message from server during startup" msgstr "unerwartete Nachricht vom Server beim Start" -#: fe-connect.c:4034 +#: fe-connect.c:4357 #, c-format msgid "session is read-only" msgstr "Sitzung ist read-only" -#: fe-connect.c:4036 +#: fe-connect.c:4359 #, c-format msgid "session is not read-only" msgstr "Sitzung ist nicht read-only" -#: fe-connect.c:4089 +#: fe-connect.c:4412 #, c-format msgid "server is in hot standby mode" msgstr "Server ist im Hot-Standby-Modus" -#: fe-connect.c:4091 +#: fe-connect.c:4414 #, c-format msgid "server is not in hot standby mode" msgstr "Server ist nicht im Hot-Standby-Modus" -#: fe-connect.c:4213 fe-connect.c:4263 +#: fe-connect.c:4539 fe-connect.c:4589 #, c-format msgid "\"%s\" failed" msgstr "»%s« fehlgeschlagen" -#: fe-connect.c:4277 +#: fe-connect.c:4603 #, c-format msgid "invalid connection state %d, probably indicative of memory corruption" msgstr "ungültiger Verbindungszustand %d, möglicherweise ein Speicherproblem" -#: fe-connect.c:5096 +#: fe-connect.c:5432 #, c-format msgid "invalid LDAP URL \"%s\": scheme must be ldap://" msgstr "ungültige LDAP-URL »%s«: Schema muss ldap:// sein" -#: fe-connect.c:5111 +#: fe-connect.c:5447 #, c-format msgid "invalid LDAP URL \"%s\": missing distinguished name" msgstr "ungültige LDAP-URL »%s«: Distinguished Name fehlt" -#: fe-connect.c:5123 fe-connect.c:5181 +#: fe-connect.c:5459 fe-connect.c:5517 #, c-format msgid "invalid LDAP URL \"%s\": must have exactly one attribute" msgstr "ungültige LDAP-URL »%s«: muss genau ein Attribut haben" -#: fe-connect.c:5135 fe-connect.c:5197 +#: fe-connect.c:5471 fe-connect.c:5533 #, c-format msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" msgstr "ungültige LDAP-URL »%s«: Suchbereich fehlt (base/one/sub)" -#: fe-connect.c:5147 +#: fe-connect.c:5483 #, c-format msgid "invalid LDAP URL \"%s\": no filter" msgstr "ungültige LDAP-URL »%s«: kein Filter" -#: fe-connect.c:5169 +#: fe-connect.c:5505 #, c-format msgid "invalid LDAP URL \"%s\": invalid port number" msgstr "ungültige LDAP-URL »%s«: ungültige Portnummer" -#: fe-connect.c:5206 +#: fe-connect.c:5542 #, c-format msgid "could not create LDAP structure" msgstr "konnte LDAP-Struktur nicht erzeugen" -#: fe-connect.c:5281 +#: fe-connect.c:5617 #, c-format msgid "lookup on LDAP server failed: %s" msgstr "Suche auf LDAP-Server fehlgeschlagen: %s" -#: fe-connect.c:5291 +#: fe-connect.c:5627 #, c-format msgid "more than one entry found on LDAP lookup" msgstr "LDAP-Suche ergab mehr als einen Eintrag" -#: fe-connect.c:5293 fe-connect.c:5304 +#: fe-connect.c:5629 fe-connect.c:5640 #, c-format msgid "no entry found on LDAP lookup" msgstr "kein Eintrag gefunden bei LDAP-Suche" -#: fe-connect.c:5314 fe-connect.c:5326 +#: fe-connect.c:5650 fe-connect.c:5662 #, c-format msgid "attribute has no values on LDAP lookup" msgstr "Attribut hat keine Werte bei LDAP-Suche" -#: fe-connect.c:5377 fe-connect.c:5396 fe-connect.c:5920 +#: fe-connect.c:5713 fe-connect.c:5732 fe-connect.c:6256 #, c-format msgid "missing \"=\" after \"%s\" in connection info string" msgstr "fehlendes »=« nach »%s« in der Zeichenkette der Verbindungsdaten" -#: fe-connect.c:5467 fe-connect.c:6103 fe-connect.c:6901 +#: fe-connect.c:5803 fe-connect.c:6439 fe-connect.c:7269 #, c-format msgid "invalid connection option \"%s\"" msgstr "ungültige Verbindungsoption »%s«" -#: fe-connect.c:5482 fe-connect.c:5968 +#: fe-connect.c:5818 fe-connect.c:6304 #, c-format msgid "unterminated quoted string in connection info string" msgstr "fehlendes schließendes Anführungszeichen (\") in der Zeichenkette der Verbindungsdaten" -#: fe-connect.c:5562 +#: fe-connect.c:5898 #, c-format msgid "definition of service \"%s\" not found" msgstr "Definition von Service »%s« nicht gefunden" -#: fe-connect.c:5588 +#: fe-connect.c:5924 #, c-format msgid "service file \"%s\" not found" msgstr "Servicedatei »%s« nicht gefunden" -#: fe-connect.c:5601 +#: fe-connect.c:5937 #, c-format msgid "line %d too long in service file \"%s\"" msgstr "Zeile %d zu lang in Servicedatei »%s«" -#: fe-connect.c:5672 fe-connect.c:5715 +#: fe-connect.c:6008 fe-connect.c:6051 #, c-format msgid "syntax error in service file \"%s\", line %d" msgstr "Syntaxfehler in Servicedatei »%s«, Zeile %d" -#: fe-connect.c:5683 +#: fe-connect.c:6019 #, c-format msgid "nested service specifications not supported in service file \"%s\", line %d" msgstr "geschachtelte »service«-Definitionen werden nicht unterstützt in Servicedatei »%s«, Zeile %d" -#: fe-connect.c:6422 +#: fe-connect.c:6758 #, c-format msgid "invalid URI propagated to internal parser routine: \"%s\"" msgstr "ungültige URI an interne Parserroutine weitergeleitet: »%s«" -#: fe-connect.c:6499 +#: fe-connect.c:6835 #, c-format msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" msgstr "Ende der Eingabezeichenkette gefunden beim Suchen nach passendem »]« in IPv6-Hostadresse in URI: »%s«" -#: fe-connect.c:6506 +#: fe-connect.c:6842 #, c-format msgid "IPv6 host address may not be empty in URI: \"%s\"" msgstr "IPv6-Hostadresse darf nicht leer sein in URI: »%s«" -#: fe-connect.c:6521 +#: fe-connect.c:6857 #, c-format msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" msgstr "unerwartetes Zeichen »%c« an Position %d in URI (»:« oder »/« erwartet): »%s«" -#: fe-connect.c:6650 +#: fe-connect.c:6986 #, c-format msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "zusätzliches Schlüssel/Wert-Trennzeichen »=« in URI-Query-Parameter: »%s«" -#: fe-connect.c:6670 +#: fe-connect.c:7006 #, c-format msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "fehlendes Schlüssel/Wert-Trennzeichen »=« in URI-Query-Parameter: »%s«" -#: fe-connect.c:6722 +#: fe-connect.c:7058 #, c-format msgid "invalid URI query parameter: \"%s\"" msgstr "ungültiger URI-Query-Parameter: »%s«" -#: fe-connect.c:6796 +#: fe-connect.c:7142 #, c-format msgid "invalid percent-encoded token: \"%s\"" msgstr "ungültiges Prozent-kodiertes Token: »%s«" -#: fe-connect.c:6806 +#: fe-connect.c:7152 #, c-format msgid "forbidden value %%00 in percent-encoded value: \"%s\"" msgstr "verbotener Wert %%00 in Prozent-kodiertem Wert: »%s«" -#: fe-connect.c:7170 +#: fe-connect.c:7174 +#, c-format +msgid "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead" +msgstr "unerwartete Leerzeichen in »%s« gefunden, verwenden Sie stattdessen Prozent-kodierte Leerzeichen (%%20)" + +#: fe-connect.c:7556 msgid "connection pointer is NULL\n" msgstr "Verbindung ist ein NULL-Zeiger\n" -#: fe-connect.c:7178 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 -#: fe-protocol3.c:991 fe-protocol3.c:1024 +#: fe-connect.c:7564 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 +#: fe-protocol3.c:987 fe-protocol3.c:1020 msgid "out of memory\n" msgstr "Speicher aufgebraucht\n" -#: fe-connect.c:7469 +#: fe-connect.c:7866 #, c-format msgid "WARNING: password file \"%s\" is not a plain file\n" msgstr "WARNUNG: Passwortdatei »%s« ist keine normale Datei\n" -#: fe-connect.c:7478 +#: fe-connect.c:7876 #, c-format msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" msgstr "WARNUNG: Passwortdatei »%s« erlaubt Lesezugriff für Gruppe oder Andere; Rechte sollten u=rw (0600) oder weniger sein\n" -#: fe-connect.c:7585 +#: fe-connect.c:7980 #, c-format msgid "password retrieved from file \"%s\"" msgstr "Passwort wurde aus Datei »%s« gelesen" -#: fe-connect.c:7737 +#: fe-connect.c:8146 #, c-format msgid "invalid integer value \"%s\" for connection option \"%s\"" msgstr "ungültiger Zahlenwert »%s« für Verbindungsoption »%s«" @@ -821,7 +876,7 @@ msgstr "ungültiger Zahlenwert »%s« für Verbindungsoption »%s«" msgid "row number %d is out of range 0..%d" msgstr "Zeilennummer %d ist außerhalb des zulässigen Bereichs 0..%d" -#: fe-exec.c:531 fe-protocol3.c:1993 +#: fe-exec.c:531 fe-protocol3.c:1985 #, c-format msgid "%s" msgstr "%s" @@ -912,7 +967,7 @@ msgstr "PQexec ist während COPY BOTH nicht erlaubt" msgid "unrecognized message type \"%c\"" msgstr "unbekannter Message-Typ »%c«" -#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1924 +#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1916 #, c-format msgid "no COPY in progress" msgstr "keine COPY in Ausführung" @@ -970,11 +1025,16 @@ msgstr "Parameternummer %d ist außerhalb des zulässigen Bereichs 0..%d" msgid "could not interpret result from server: %s" msgstr "konnte Ergebnis vom Server nicht interpretieren: %s" -#: fe-exec.c:4127 fe-exec.c:4217 +#: fe-exec.c:4140 fe-exec.c:4253 #, c-format msgid "incomplete multibyte character" msgstr "unvollständiges Mehrbyte-Zeichen" +#: fe-exec.c:4142 fe-exec.c:4272 +#, c-format +msgid "invalid multibyte character" +msgstr "ungültiges Mehrbytezeichen" + #: fe-gssapi-common.c:122 msgid "GSSAPI name import error" msgstr "GSSAPI-Namensimportfehler" @@ -1031,8 +1091,8 @@ msgstr "Integer der Größe %lu wird von pqGetInt nicht unterstützt" msgid "integer of size %lu not supported by pqPutInt" msgstr "Integer der Größe %lu wird von pqPutInt nicht unterstützt" -#: fe-misc.c:750 fe-secure-openssl.c:203 fe-secure-openssl.c:309 -#: fe-secure.c:237 fe-secure.c:404 +#: fe-misc.c:765 fe-secure-openssl.c:180 fe-secure-openssl.c:286 +#: fe-secure.c:222 fe-secure.c:389 #, c-format msgid "" "server closed the connection unexpectedly\n" @@ -1043,21 +1103,21 @@ msgstr "" "\tDas heißt wahrscheinlich, dass der Server abnormal beendete\n" "\tbevor oder während die Anweisung bearbeitet wurde." -#: fe-misc.c:817 +#: fe-misc.c:832 msgid "connection not open\n" msgstr "Verbindung nicht offen\n" -#: fe-misc.c:1002 +#: fe-misc.c:1020 #, c-format msgid "timeout expired" msgstr "Timeout abgelaufen" -#: fe-misc.c:1046 +#: fe-misc.c:1072 #, c-format msgid "invalid socket" msgstr "ungültiges Socket" -#: fe-misc.c:1068 +#: fe-misc.c:1095 #, c-format msgid "%s() failed: %s" msgstr "%s() fehlgeschlagen: %s" @@ -1077,138 +1137,138 @@ msgstr "Server sendete Daten (»D«-Nachricht) ohne vorherige Zeilenbeschreibung msgid "unexpected response from server; first received character was \"%c\"" msgstr "unerwartete Antwort vom Server; erstes empfangenes Zeichen war »%c«" -#: fe-protocol3.c:467 +#: fe-protocol3.c:463 #, c-format msgid "message contents do not agree with length in message type \"%c\"" msgstr "Nachrichteninhalt stimmt nicht mit Länge in Nachrichtentyp »%c« überein" -#: fe-protocol3.c:485 +#: fe-protocol3.c:481 #, c-format msgid "lost synchronization with server: got message type \"%c\", length %d" msgstr "Synchronisation mit Server verloren: Nachrichtentyp »%c« empfangen, Länge %d" -#: fe-protocol3.c:537 fe-protocol3.c:577 +#: fe-protocol3.c:533 fe-protocol3.c:573 msgid "insufficient data in \"T\" message" msgstr "nicht genug Daten in »T«-Nachricht" -#: fe-protocol3.c:648 fe-protocol3.c:854 +#: fe-protocol3.c:644 fe-protocol3.c:850 msgid "out of memory for query result" msgstr "Speicher für Anfrageergebnis aufgebraucht" -#: fe-protocol3.c:717 +#: fe-protocol3.c:713 msgid "insufficient data in \"t\" message" msgstr "nicht genug Daten in »t«-Nachricht" -#: fe-protocol3.c:776 fe-protocol3.c:808 fe-protocol3.c:826 +#: fe-protocol3.c:772 fe-protocol3.c:804 fe-protocol3.c:822 msgid "insufficient data in \"D\" message" msgstr "nicht genug Daten in »D«-Nachricht" -#: fe-protocol3.c:782 +#: fe-protocol3.c:778 msgid "unexpected field count in \"D\" message" msgstr "unerwartete Feldzahl in »D«-Nachricht" -#: fe-protocol3.c:1037 +#: fe-protocol3.c:1033 msgid "no error message available\n" msgstr "keine Fehlermeldung verfügbar\n" #. translator: %s represents a digit string -#: fe-protocol3.c:1085 fe-protocol3.c:1104 +#: fe-protocol3.c:1081 fe-protocol3.c:1100 #, c-format msgid " at character %s" msgstr " bei Zeichen %s" -#: fe-protocol3.c:1117 +#: fe-protocol3.c:1113 #, c-format msgid "DETAIL: %s\n" msgstr "DETAIL: %s\n" -#: fe-protocol3.c:1120 +#: fe-protocol3.c:1116 #, c-format msgid "HINT: %s\n" msgstr "TIP: %s\n" -#: fe-protocol3.c:1123 +#: fe-protocol3.c:1119 #, c-format msgid "QUERY: %s\n" msgstr "ANFRAGE: %s\n" -#: fe-protocol3.c:1130 +#: fe-protocol3.c:1126 #, c-format msgid "CONTEXT: %s\n" msgstr "KONTEXT: %s\n" -#: fe-protocol3.c:1139 +#: fe-protocol3.c:1135 #, c-format msgid "SCHEMA NAME: %s\n" msgstr "SCHEMANAME: %s\n" -#: fe-protocol3.c:1143 +#: fe-protocol3.c:1139 #, c-format msgid "TABLE NAME: %s\n" msgstr "TABELLENNAME: %s\n" -#: fe-protocol3.c:1147 +#: fe-protocol3.c:1143 #, c-format msgid "COLUMN NAME: %s\n" msgstr "SPALTENNAME: %s\n" -#: fe-protocol3.c:1151 +#: fe-protocol3.c:1147 #, c-format msgid "DATATYPE NAME: %s\n" msgstr "DATENTYPNAME: %s\n" -#: fe-protocol3.c:1155 +#: fe-protocol3.c:1151 #, c-format msgid "CONSTRAINT NAME: %s\n" msgstr "CONSTRAINT-NAME: %s\n" -#: fe-protocol3.c:1167 +#: fe-protocol3.c:1163 msgid "LOCATION: " msgstr "ORT: " -#: fe-protocol3.c:1169 +#: fe-protocol3.c:1165 #, c-format msgid "%s, " msgstr "%s, " -#: fe-protocol3.c:1171 +#: fe-protocol3.c:1167 #, c-format msgid "%s:%s" msgstr "%s:%s" -#: fe-protocol3.c:1366 +#: fe-protocol3.c:1362 #, c-format msgid "LINE %d: " msgstr "ZEILE %d: " -#: fe-protocol3.c:1440 +#: fe-protocol3.c:1436 #, c-format msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" msgstr "Protokollversion nicht vom Server unterstützt: Client verwendet %u.%u, Server unterstützt bis %u.%u" -#: fe-protocol3.c:1446 +#: fe-protocol3.c:1442 #, c-format msgid "protocol extension not supported by server: %s" msgid_plural "protocol extensions not supported by server: %s" msgstr[0] "Protokollerweiterung nicht vom Server unterstützt: %s" msgstr[1] "Protokollerweiterungen nicht vom Server unterstützt: %s" -#: fe-protocol3.c:1454 +#: fe-protocol3.c:1450 #, c-format msgid "invalid %s message" msgstr "ungültige %s-Nachricht" -#: fe-protocol3.c:1819 +#: fe-protocol3.c:1811 #, c-format msgid "PQgetline: not doing text COPY OUT" msgstr "PQgetline: Text COPY OUT nicht ausgeführt" -#: fe-protocol3.c:2193 +#: fe-protocol3.c:2186 #, c-format msgid "protocol error: no function result" msgstr "Protokollfehler: kein Funktionsergebnis" -#: fe-protocol3.c:2204 +#: fe-protocol3.c:2198 #, c-format msgid "protocol error: id=0x%x" msgstr "Protokollfehler: id=0x%x" @@ -1290,92 +1350,92 @@ msgstr "GSSAPI-Fehler bei der Größenprüfung" msgid "GSSAPI context establishment error" msgstr "GSSAPI-Fehler beim Einrichten des Kontexts" -#: fe-secure-openssl.c:207 fe-secure-openssl.c:313 fe-secure-openssl.c:1524 +#: fe-secure-openssl.c:184 fe-secure-openssl.c:290 fe-secure-openssl.c:1320 #, c-format msgid "SSL SYSCALL error: %s" msgstr "SSL-SYSCALL-Fehler: %s" -#: fe-secure-openssl.c:213 fe-secure-openssl.c:319 fe-secure-openssl.c:1527 +#: fe-secure-openssl.c:190 fe-secure-openssl.c:296 fe-secure-openssl.c:1323 #, c-format msgid "SSL SYSCALL error: EOF detected" msgstr "SSL-SYSCALL-Fehler: Dateiende entdeckt" -#: fe-secure-openssl.c:223 fe-secure-openssl.c:329 fe-secure-openssl.c:1535 +#: fe-secure-openssl.c:200 fe-secure-openssl.c:306 fe-secure-openssl.c:1331 #, c-format msgid "SSL error: %s" msgstr "SSL-Fehler: %s" -#: fe-secure-openssl.c:237 fe-secure-openssl.c:343 +#: fe-secure-openssl.c:214 fe-secure-openssl.c:320 #, c-format msgid "SSL connection has been closed unexpectedly" msgstr "SSL-Verbindung wurde unerwartet geschlossen" -#: fe-secure-openssl.c:242 fe-secure-openssl.c:348 fe-secure-openssl.c:1582 +#: fe-secure-openssl.c:219 fe-secure-openssl.c:325 fe-secure-openssl.c:1378 #, c-format msgid "unrecognized SSL error code: %d" msgstr "unbekannter SSL-Fehlercode: %d" -#: fe-secure-openssl.c:390 +#: fe-secure-openssl.c:367 #, c-format msgid "could not determine server certificate signature algorithm" msgstr "konnte Signaturalgorithmus des Serverzertifikats nicht ermitteln" -#: fe-secure-openssl.c:410 +#: fe-secure-openssl.c:387 #, c-format msgid "could not find digest for NID %s" msgstr "konnte Digest für NID %s nicht finden" -#: fe-secure-openssl.c:419 +#: fe-secure-openssl.c:396 #, c-format msgid "could not generate peer certificate hash" msgstr "konnte Hash des Zertifikats der Gegenstelle nicht erzeugen" -#: fe-secure-openssl.c:501 +#: fe-secure-openssl.c:478 #, c-format msgid "SSL certificate's name entry is missing" msgstr "Namenseintrag fehlt im SSL-Zertifikat" -#: fe-secure-openssl.c:535 +#: fe-secure-openssl.c:508 #, c-format msgid "SSL certificate's address entry is missing" msgstr "Adresseintrag fehlt im SSL-Zertifikat" -#: fe-secure-openssl.c:935 +#: fe-secure-openssl.c:731 #, c-format msgid "could not create SSL context: %s" msgstr "konnte SSL-Kontext nicht erzeugen: %s" -#: fe-secure-openssl.c:977 +#: fe-secure-openssl.c:773 #, c-format msgid "invalid value \"%s\" for minimum SSL protocol version" msgstr "ungültiger Wert »%s« für minimale SSL-Protokollversion" -#: fe-secure-openssl.c:987 +#: fe-secure-openssl.c:783 #, c-format msgid "could not set minimum SSL protocol version: %s" msgstr "konnte minimale SSL-Protokollversion nicht setzen: %s" -#: fe-secure-openssl.c:1003 +#: fe-secure-openssl.c:799 #, c-format msgid "invalid value \"%s\" for maximum SSL protocol version" msgstr "ungültiger Wert »%s« für maximale SSL-Protokollversion" -#: fe-secure-openssl.c:1013 +#: fe-secure-openssl.c:809 #, c-format msgid "could not set maximum SSL protocol version: %s" msgstr "konnte maximale SSL-Protokollversion nicht setzen: %s" -#: fe-secure-openssl.c:1051 +#: fe-secure-openssl.c:847 #, c-format msgid "could not load system root certificate paths: %s" msgstr "konnte System-Root-Zertifikat-Pfade nicht laden: %s" -#: fe-secure-openssl.c:1068 +#: fe-secure-openssl.c:864 #, c-format msgid "could not read root certificate file \"%s\": %s" msgstr "konnte Root-Zertifikat-Datei »%s« nicht lesen: %s" -#: fe-secure-openssl.c:1120 +#: fe-secure-openssl.c:916 #, c-format msgid "" "could not get home directory to locate root certificate file\n" @@ -1384,7 +1444,7 @@ msgstr "" "konnte Home-Verzeichnis nicht ermitteln, um Root-Zertifikat-Datei zu finden\n" "Legen Sie entweder die Datei an, verwenden Sie die vertrauenswürdigen Roots des Systems mit sslrootcert=system, oder ändern Sie sslmode, um die Überprüfung der Serverzertifikate abzuschalten." -#: fe-secure-openssl.c:1123 +#: fe-secure-openssl.c:919 #, c-format msgid "" "root certificate file \"%s\" does not exist\n" @@ -1393,127 +1453,127 @@ msgstr "" "Root-Zertifikat-Datei »%s« existiert nicht\n" "Legen Sie entweder die Datei an, verwenden Sie die vertrauenswürdigen Roots des Systems mit sslrootcert=system, oder ändern Sie sslmode, um die Überprüfung der Serverzertifikate abzuschalten." -#: fe-secure-openssl.c:1158 +#: fe-secure-openssl.c:954 #, c-format msgid "could not open certificate file \"%s\": %s" msgstr "konnte Zertifikatdatei »%s« nicht öffnen: %s" -#: fe-secure-openssl.c:1176 +#: fe-secure-openssl.c:972 #, c-format msgid "could not read certificate file \"%s\": %s" msgstr "konnte Zertifikatdatei »%s« nicht lesen: %s" -#: fe-secure-openssl.c:1200 +#: fe-secure-openssl.c:996 #, c-format msgid "could not establish SSL connection: %s" msgstr "konnte SSL-Verbindung nicht aufbauen: %s" -#: fe-secure-openssl.c:1232 +#: fe-secure-openssl.c:1028 #, c-format msgid "could not set SSL Server Name Indication (SNI): %s" msgstr "konnte SSL-Server-Name-Indication (SNI) nicht setzen: %s" -#: fe-secure-openssl.c:1249 +#: fe-secure-openssl.c:1045 #, c-format msgid "could not set SSL ALPN extension: %s" msgstr "konnte SSL-ALPN-Erweiterung nicht setzen: %s" -#: fe-secure-openssl.c:1292 +#: fe-secure-openssl.c:1088 #, c-format msgid "could not load SSL engine \"%s\": %s" msgstr "konnte SSL-Engine »%s« nicht laden: %s" -#: fe-secure-openssl.c:1303 +#: fe-secure-openssl.c:1099 #, c-format msgid "could not initialize SSL engine \"%s\": %s" msgstr "konnte SSL-Engine »%s« nicht initialisieren: %s" -#: fe-secure-openssl.c:1318 +#: fe-secure-openssl.c:1114 #, c-format msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" msgstr "konnte privaten SSL-Schlüssel »%s« nicht von Engine »%s« lesen: %s" -#: fe-secure-openssl.c:1331 +#: fe-secure-openssl.c:1127 #, c-format msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" msgstr "konnte privaten SSL-Schlüssel »%s« nicht von Engine »%s« laden: %s" -#: fe-secure-openssl.c:1368 +#: fe-secure-openssl.c:1164 #, c-format msgid "certificate present, but not private key file \"%s\"" msgstr "Zertifikat vorhanden, aber keine private Schlüsseldatei »%s«" -#: fe-secure-openssl.c:1371 +#: fe-secure-openssl.c:1167 #, c-format msgid "could not stat private key file \"%s\": %m" msgstr "konnte »stat« für private Schlüsseldatei »%s« nicht ausführen: %m" -#: fe-secure-openssl.c:1379 +#: fe-secure-openssl.c:1175 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "private Schlüsseldatei »%s« ist keine normale Datei" -#: fe-secure-openssl.c:1412 +#: fe-secure-openssl.c:1208 #, c-format msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" msgstr "private Schlüsseldatei »%s« erlaubt Lesezugriff für Gruppe oder Andere; Dateirechte müssen u=rw (0600) oder weniger sein, wenn der Eigentümer der aktuelle Benutzer ist, oder u=rw,g=r (0640) oder weniger, wenn der Eigentümer »root« ist" -#: fe-secure-openssl.c:1436 +#: fe-secure-openssl.c:1232 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "konnte private Schlüsseldatei »%s« nicht laden: %s" -#: fe-secure-openssl.c:1452 +#: fe-secure-openssl.c:1248 #, c-format msgid "certificate does not match private key file \"%s\": %s" msgstr "Zertifikat passt nicht zur privaten Schlüsseldatei »%s«: %s" -#: fe-secure-openssl.c:1521 +#: fe-secure-openssl.c:1317 #, c-format msgid "SSL error: certificate verify failed: %s" msgstr "SSL-Fehler: Zertifikatsüberprüfung fehlgeschlagen: %s" -#: fe-secure-openssl.c:1566 +#: fe-secure-openssl.c:1362 #, c-format msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." msgstr "Das zeigt möglicherweise an, dass der Server keine SSL-Protokollversion zwischen %s und %s unterstützt." -#: fe-secure-openssl.c:1598 +#: fe-secure-openssl.c:1394 #, c-format msgid "direct SSL connection was established without ALPN protocol negotiation extension" msgstr "direkte SSL-Verbindung wurde ohne ALPN-Erweiterung zur Protokollverhandlung aufgebaut" -#: fe-secure-openssl.c:1610 +#: fe-secure-openssl.c:1406 #, c-format msgid "SSL connection was established with unexpected ALPN protocol" msgstr "SSL-Verbindung wurde mit unerwartetem ALPN-Protokoll aufgebaut" -#: fe-secure-openssl.c:1627 +#: fe-secure-openssl.c:1423 #, c-format msgid "certificate could not be obtained: %s" msgstr "Zertifikat konnte nicht ermittelt werden: %s" -#: fe-secure-openssl.c:1734 +#: fe-secure-openssl.c:1502 #, c-format msgid "no SSL error reported" msgstr "kein SSL-Fehler berichtet" -#: fe-secure-openssl.c:1776 +#: fe-secure-openssl.c:1545 #, c-format msgid "SSL error code %lu" msgstr "SSL-Fehlercode %lu" -#: fe-secure-openssl.c:2075 +#: fe-secure-openssl.c:1847 #, c-format msgid "WARNING: sslpassword truncated\n" msgstr "WARNUNG: sslpassword abgeschnitten\n" -#: fe-secure.c:248 +#: fe-secure.c:233 #, c-format msgid "could not receive data from server: %s" msgstr "konnte keine Daten vom Server empfangen: %s" -#: fe-secure.c:419 +#: fe-secure.c:404 #, c-format msgid "could not send data to server: %s" msgstr "konnte keine Daten an den Server senden: %s" diff --git a/src/interfaces/libpq/po/ja.po b/src/interfaces/libpq/po/ja.po index ad13b824638c1..4972a66682671 100644 --- a/src/interfaces/libpq/po/ja.po +++ b/src/interfaces/libpq/po/ja.po @@ -7,10 +7,10 @@ # msgid "" msgstr "" -"Project-Id-Version: libpq (PostgreSQL 17)\n" +"Project-Id-Version: libpq (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 11:23+0900\n" -"PO-Revision-Date: 2024-06-14 11:34+0900\n" +"POT-Creation-Date: 2025-04-07 09:45+0900\n" +"PO-Revision-Date: 2025-04-07 15:59+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -20,801 +20,872 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: ../../port/user.c:43 ../../port/user.c:79 -#, c-format -msgid "could not look up local user ID %d: %s" -msgstr "ローカルユーザーID %dの参照に失敗しました: %s" - -#: ../../port/user.c:48 ../../port/user.c:84 -#, c-format -msgid "local user with ID %d does not exist" -msgstr "ID %d を持つローカルユーザーは存在しません" - -#: fe-auth-scram.c:223 +#: fe-auth-scram.c:228 #, c-format msgid "malformed SCRAM message (empty message)" msgstr "SCRAMメッセージのフォーマット異常 (空のメッセージ)" -#: fe-auth-scram.c:228 +#: fe-auth-scram.c:233 #, c-format msgid "malformed SCRAM message (length mismatch)" msgstr "SCRAMメッセージのフォーマット異常 (長さの不整合)" -#: fe-auth-scram.c:272 +#: fe-auth-scram.c:277 #, c-format msgid "could not verify server signature: %s" msgstr "サーバー署名を検証できませんでした: %s" -#: fe-auth-scram.c:278 +#: fe-auth-scram.c:283 #, c-format msgid "incorrect server signature" msgstr "正しくないサーバー署名" -#: fe-auth-scram.c:287 +#: fe-auth-scram.c:292 #, c-format msgid "invalid SCRAM exchange state" msgstr "不正なSCRAM交換状態" -#: fe-auth-scram.c:311 +#: fe-auth-scram.c:316 #, c-format msgid "malformed SCRAM message (attribute \"%c\" expected)" msgstr "SCRAMメッセージのフォーマット異常 (属性 \"%c\" が必要)" -#: fe-auth-scram.c:320 +#: fe-auth-scram.c:325 #, c-format msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" msgstr "SCRAMメッセージのフォーマット異常 (属性 \"%c\" に文字 \"=\" が必要)" -#: fe-auth-scram.c:360 +#: fe-auth-scram.c:365 #, c-format msgid "could not generate nonce" msgstr "nonce を生成できませんでした" -#: fe-auth-scram.c:369 fe-auth-scram.c:442 fe-auth-scram.c:594 -#: fe-auth-scram.c:614 fe-auth-scram.c:638 fe-auth-scram.c:652 -#: fe-auth-scram.c:698 fe-auth-scram.c:734 fe-auth-scram.c:908 fe-auth.c:296 -#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:727 fe-auth.c:1199 -#: fe-auth.c:1362 fe-cancel.c:159 fe-connect.c:936 fe-connect.c:976 -#: fe-connect.c:1860 fe-connect.c:2022 fe-connect.c:3430 fe-connect.c:4758 -#: fe-connect.c:5070 fe-connect.c:5325 fe-connect.c:5443 fe-connect.c:5690 -#: fe-connect.c:5770 fe-connect.c:5868 fe-connect.c:6119 fe-connect.c:6146 -#: fe-connect.c:6222 fe-connect.c:6245 fe-connect.c:6269 fe-connect.c:6304 -#: fe-connect.c:6390 fe-connect.c:6398 fe-connect.c:6755 fe-connect.c:6905 -#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4234 fe-exec.c:4398 -#: fe-gssapi-common.c:109 fe-lobj.c:870 fe-protocol3.c:209 fe-protocol3.c:232 -#: fe-protocol3.c:255 fe-protocol3.c:272 fe-protocol3.c:293 fe-protocol3.c:369 -#: fe-protocol3.c:737 fe-protocol3.c:976 fe-protocol3.c:1787 -#: fe-protocol3.c:2187 fe-secure-common.c:110 fe-secure-gssapi.c:496 -#: fe-secure-openssl.c:427 fe-secure-openssl.c:1277 +#: fe-auth-scram.c:374 fe-auth-scram.c:447 fe-auth-scram.c:599 +#: fe-auth-scram.c:619 fe-auth-scram.c:643 fe-auth-scram.c:657 +#: fe-auth-scram.c:703 fe-auth-scram.c:739 fe-auth-scram.c:931 fe-auth.c:308 +#: fe-auth.c:382 fe-auth.c:416 fe-auth.c:694 fe-auth.c:827 fe-auth.c:1330 +#: fe-auth.c:1493 fe-cancel.c:177 fe-connect.c:1005 fe-connect.c:1045 +#: fe-connect.c:2169 fe-connect.c:2331 fe-connect.c:3724 fe-connect.c:5172 +#: fe-connect.c:5485 fe-connect.c:5740 fe-connect.c:5858 fe-connect.c:6105 +#: fe-connect.c:6185 fe-connect.c:6283 fe-connect.c:6534 fe-connect.c:6561 +#: fe-connect.c:6637 fe-connect.c:6660 fe-connect.c:6684 fe-connect.c:6719 +#: fe-connect.c:6805 fe-connect.c:6813 fe-connect.c:7170 fe-connect.c:7352 +#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4291 fe-exec.c:4457 +#: fe-gssapi-common.c:109 fe-lobj.c:870 fe-protocol3.c:210 fe-protocol3.c:233 +#: fe-protocol3.c:256 fe-protocol3.c:273 fe-protocol3.c:294 fe-protocol3.c:368 +#: fe-protocol3.c:732 fe-protocol3.c:972 fe-protocol3.c:1552 +#: fe-protocol3.c:1861 fe-protocol3.c:2262 fe-secure-common.c:110 +#: fe-secure-gssapi.c:496 fe-secure-openssl.c:405 fe-secure-openssl.c:1131 #, c-format msgid "out of memory" msgstr "メモリ不足です" -#: fe-auth-scram.c:376 +#: fe-auth-scram.c:381 #, c-format msgid "could not encode nonce" msgstr "nonceをエンコードできませんでした" -#: fe-auth-scram.c:564 +#: fe-auth-scram.c:569 #, c-format msgid "could not calculate client proof: %s" msgstr "クライアント証明の算出に失敗しました: %s" -#: fe-auth-scram.c:579 +#: fe-auth-scram.c:584 #, c-format msgid "could not encode client proof" msgstr "クライアントの証明のエンコードに失敗しました" -#: fe-auth-scram.c:631 +#: fe-auth-scram.c:636 #, c-format msgid "invalid SCRAM response (nonce mismatch)" msgstr "不正なSCRAM応答 (nonce の不一致)" -#: fe-auth-scram.c:661 +#: fe-auth-scram.c:666 #, c-format msgid "malformed SCRAM message (invalid salt)" msgstr "SCRAMメッセージのフォーマット異常 (不正なソルト)" -#: fe-auth-scram.c:674 +#: fe-auth-scram.c:679 #, c-format msgid "malformed SCRAM message (invalid iteration count)" msgstr "SCRAMメッセージのフォーマット異常 (不正な繰り返し回数)" -#: fe-auth-scram.c:679 +#: fe-auth-scram.c:684 #, c-format msgid "malformed SCRAM message (garbage at end of server-first-message)" msgstr "SCRAMメッセージのフォーマット異常 (server-first-message 終端の余分なデータ)" -#: fe-auth-scram.c:713 +#: fe-auth-scram.c:718 #, c-format msgid "error received from server in SCRAM exchange: %s" msgstr "SCRAM交換中にサーバーからのエラーを受信しました: %s" -#: fe-auth-scram.c:728 +#: fe-auth-scram.c:733 #, c-format msgid "malformed SCRAM message (garbage at end of server-final-message)" msgstr "SCRAMメッセージのフォーマット異常 (server-final-message 終端の余分なデータ)" -#: fe-auth-scram.c:745 +#: fe-auth-scram.c:750 #, c-format msgid "malformed SCRAM message (invalid server signature)" msgstr "SCRAMメッセージのフォーマット異常 (不正なサーバー署名)" -#: fe-auth-scram.c:917 +#: fe-auth-scram.c:940 msgid "could not generate random salt" msgstr "乱数ソルトを生成できませんでした" -#: fe-auth.c:77 +#: fe-auth.c:80 #, c-format msgid "out of memory allocating GSSAPI buffer (%d)" msgstr "GSSAPIバッファの割り当ての際のメモリ不足(%d)" -#: fe-auth.c:138 +#: fe-auth.c:146 msgid "GSSAPI continuation error" msgstr "GSSAI続行エラー" -#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-auth.c:176 fe-auth.c:410 fe-gssapi-common.c:97 fe-secure-common.c:99 #: fe-secure-common.c:173 #, c-format msgid "host name must be specified" msgstr "ホスト名を指定しなければなりません" -#: fe-auth.c:174 +#: fe-auth.c:182 #, c-format msgid "duplicate GSS authentication request" msgstr "重複するGSS認証要求" -#: fe-auth.c:238 +#: fe-auth.c:246 #, c-format msgid "out of memory allocating SSPI buffer (%d)" msgstr "SSPIバッファの割り当ての際のメモリ不足(%d)" -#: fe-auth.c:285 +#: fe-auth.c:297 msgid "SSPI continuation error" msgstr "SSPI続行エラー" -#: fe-auth.c:359 +#: fe-auth.c:372 #, c-format msgid "duplicate SSPI authentication request" msgstr "重複したSSPI認証要求" -#: fe-auth.c:384 +#: fe-auth.c:397 msgid "could not acquire SSPI credentials" msgstr "SSPI資格を入手できませんでした" -#: fe-auth.c:436 +#: fe-auth.c:449 #, c-format msgid "channel binding required, but SSL not in use" msgstr "チャネルバインディングが要求されていますが、SSLが使用されていません" -#: fe-auth.c:442 +#: fe-auth.c:455 #, c-format msgid "duplicate SASL authentication request" msgstr "重複するSASL認証要求" -#: fe-auth.c:500 +#: fe-auth.c:513 #, c-format msgid "channel binding is required, but client does not support it" msgstr "チャネルバインディングが要求されていますが、クライアントがサポートしていません" -#: fe-auth.c:516 +#: fe-auth.c:529 #, c-format msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" msgstr "サーバーが非SSL接続上で SCRAM-SHA-256-PLUS 認証を提示してきました" -#: fe-auth.c:531 +#: fe-auth.c:551 #, c-format msgid "none of the server's SASL authentication mechanisms are supported" msgstr "サーバー側のいずれのSASL認証機構もサポートされていません" -#: fe-auth.c:538 +#: fe-auth.c:571 +#, c-format +msgid "authentication method requirement \"%s\" failed: server requested %s authentication" +msgstr "必須の認証方式\"%s\"を満たせませんでした: サーバーは %s 認証を要求しました" + +#: fe-auth.c:580 #, c-format msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" msgstr "チャネルバインディングが要求されていますが、サーバーがチャネルバインディングをサポートする認証方式を提供しませんでした" -#: fe-auth.c:640 +#: fe-auth.c:716 #, c-format msgid "out of memory allocating SASL buffer (%d)" msgstr "SASLバッファの割り当ての際のメモリ不足(%d)" -#: fe-auth.c:663 +#: fe-auth.c:758 #, c-format msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" msgstr "サーバーからAuthenticationSASLFinalを受信しました、しかしSASL認証は完了していません" -#: fe-auth.c:673 +#: fe-auth.c:768 #, c-format msgid "no client response found after SASL exchange success" msgstr "SASL交換の成功後にクライアントからの応答がありません" -#: fe-auth.c:736 fe-auth.c:743 fe-auth.c:1345 fe-auth.c:1356 +#: fe-auth.c:836 fe-auth.c:843 fe-auth.c:1476 fe-auth.c:1487 #, c-format msgid "could not encrypt password: %s" msgstr "パスワードを暗号化できませんでした: %s" -#: fe-auth.c:771 +#: fe-auth.c:873 msgid "server requested a cleartext password" msgstr "サーバーが平文パスワードを要求してきました" -#: fe-auth.c:773 +#: fe-auth.c:875 msgid "server requested a hashed password" msgstr "サーバーがハッシュ化パスワードを要求してきました" -#: fe-auth.c:776 +#: fe-auth.c:878 msgid "server requested GSSAPI authentication" msgstr "サーバーがGSSAPI認証を要求してきました" -#: fe-auth.c:778 +#: fe-auth.c:880 msgid "server requested SSPI authentication" msgstr "サーバーがSSPI認証を要求してきました" -#: fe-auth.c:782 +#: fe-auth.c:884 msgid "server requested SASL authentication" msgstr "サーバーがSASL認証を要求してきました" -#: fe-auth.c:785 +#: fe-auth.c:887 msgid "server requested an unknown authentication type" msgstr "サーバーが不明な認証タイプを要求してきました" -#: fe-auth.c:818 +#: fe-auth.c:920 #, c-format msgid "server did not request an SSL certificate" msgstr "サーバーがSSL証明書を要求してきませんでした" -#: fe-auth.c:823 +#: fe-auth.c:925 #, c-format msgid "server accepted connection without a valid SSL certificate" msgstr "サーバーは有効なSSL証明書なしで接続を受け付けました" -#: fe-auth.c:877 +#: fe-auth.c:979 msgid "server did not complete authentication" msgstr "サーバーが認証を完了しませんでした" -#: fe-auth.c:911 +#: fe-auth.c:1013 #, c-format msgid "authentication method requirement \"%s\" failed: %s" msgstr "必須の認証方式\"%s\"が失敗しました: %s" -#: fe-auth.c:934 +#: fe-auth.c:1036 #, c-format msgid "channel binding required, but server authenticated client without channel binding" msgstr "チャネルバインディングが要求されていますが、サーバーはチャネルバインディングを使用せずに認証を行いました" -#: fe-auth.c:939 +#: fe-auth.c:1041 #, c-format msgid "channel binding required but not supported by server's authentication request" msgstr "チャネルバインディングが要求されていますが、サーバーの認証要求ではサポートされていません" -#: fe-auth.c:973 +#: fe-auth.c:1081 #, c-format msgid "Kerberos 4 authentication not supported" msgstr "Kerberos 4認証はサポートされていません" -#: fe-auth.c:977 +#: fe-auth.c:1085 #, c-format msgid "Kerberos 5 authentication not supported" msgstr "Kerberos 5認証はサポートされていません" -#: fe-auth.c:1047 +#: fe-auth.c:1155 #, c-format msgid "GSSAPI authentication not supported" msgstr "GSSAPI認証はサポートされていません" -#: fe-auth.c:1078 +#: fe-auth.c:1186 #, c-format msgid "SSPI authentication not supported" msgstr "SSPI認証はサポートされていません" -#: fe-auth.c:1085 +#: fe-auth.c:1193 #, c-format msgid "Crypt authentication not supported" msgstr "Crypt認証はサポートされていません" -#: fe-auth.c:1149 +#: fe-auth.c:1267 #, c-format msgid "authentication method %u not supported" msgstr "認証方式%uはサポートされていません" -#: fe-auth.c:1186 +#: fe-auth.c:1307 #, c-format msgid "user name lookup failure: error code %lu" msgstr "ユーザー名の参照に失敗: エラーコード %lu" -#: fe-auth.c:1308 +#: fe-auth.c:1315 +#, c-format +msgid "could not look up local user ID %ld: %m" +msgstr "ローカルユーザーID %ldの参照に失敗しました: %m" + +#: fe-auth.c:1320 +#, c-format +msgid "local user with ID %ld does not exist" +msgstr "ID %ld を持つローカルユーザーは存在しません" + +#: fe-auth.c:1439 #, c-format msgid "unexpected shape of result set returned for SHOW" msgstr "SHOW に対する予期しない形のリザルトセット" -#: fe-auth.c:1316 +#: fe-auth.c:1447 #, c-format msgid "\"password_encryption\" value too long" msgstr "\"password_encryption\"の値が長すぎます" -#: fe-auth.c:1366 +#: fe-auth.c:1497 #, c-format msgid "unrecognized password encryption algorithm \"%s\"" msgstr "認識できないパスワード暗号化アルゴリズム \"%s\"" -#: fe-cancel.c:76 +#: fe-cancel.c:79 #, c-format msgid "connection pointer is NULL" msgstr "接続ポインタはNULLです" -#: fe-cancel.c:82 fe-misc.c:572 +#: fe-cancel.c:85 fe-misc.c:587 #, c-format msgid "connection not open" msgstr "接続はオープンされていません" -#: fe-cancel.c:193 +#: fe-cancel.c:92 +#, c-format +msgid "no cancellation key received" +msgstr "キャンセルキーを受信していません" + +#: fe-cancel.c:211 #, c-format msgid "cancel request is already being sent on this connection" msgstr "このセッションではすでにキャンセル要求を送出済みです" -#: fe-cancel.c:263 +#: fe-cancel.c:281 #, c-format msgid "unexpected response from server" msgstr "サーバーからの想定外の応答" -#: fe-connect.c:1182 +#: fe-connect.c:1302 #, c-format msgid "could not match %d host names to %d hostaddr values" msgstr "%d個のホスト名と%d個のhostaddrの値との突き合せはできません" -#: fe-connect.c:1262 +#: fe-connect.c:1382 #, c-format msgid "could not match %d port numbers to %d hosts" msgstr "%d個のポート番号と%d個のホストとの突き合せはできません" -#: fe-connect.c:1387 +#: fe-connect.c:1510 #, c-format msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" msgstr "require_authの方式否定\"%s\"は方式要求と同時に指定することはできません" -#: fe-connect.c:1400 +#: fe-connect.c:1523 #, c-format msgid "require_auth method \"%s\" cannot be mixed with negative methods" msgstr "require_authの方式要求\"%s\"は方式否定と同時に指定することはできません" -#: fe-connect.c:1460 fe-connect.c:1511 fe-connect.c:1553 fe-connect.c:1596 -#: fe-connect.c:1699 fe-connect.c:1745 fe-connect.c:1785 fe-connect.c:1806 +#: fe-connect.c:1599 fe-connect.c:1728 fe-connect.c:1770 fe-connect.c:1813 +#: fe-connect.c:1916 fe-connect.c:1962 fe-connect.c:2002 fe-connect.c:2073 +#: fe-connect.c:8244 #, c-format msgid "invalid %s value: \"%s\"" msgstr "%s の値が不正: \"%s\"" -#: fe-connect.c:1493 +#: fe-connect.c:1641 +#, c-format +msgid "internal error: no space in allowed_sasl_mechs" +msgstr "内部エラー: allowed_sasl_mechs に空きがありません" + +#: fe-connect.c:1680 #, c-format msgid "require_auth method \"%s\" is specified more than once" msgstr "require_authで方式\"%s\"が複数回指定されました" -#: fe-connect.c:1534 fe-connect.c:1573 fe-connect.c:1605 fe-connect.c:1707 +#: fe-connect.c:1751 fe-connect.c:1790 fe-connect.c:1822 fe-connect.c:1924 #, c-format msgid "%s value \"%s\" invalid when SSL support is not compiled in" msgstr "%s 値\"%s\"はSSLサポートがコンパイルされていない場合は無効です" -#: fe-connect.c:1625 +#: fe-connect.c:1842 #, c-format msgid "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")" msgstr "弱いsslmode\"%s\"はsslnegotiation=direct とともには使用できません( \"require\", \"verify-ca\"または\"verify-full\"を使用してください)" -#: fe-connect.c:1647 +#: fe-connect.c:1864 #, c-format msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" msgstr "弱いsslmode\"%s\"はsslrootcert=systemとともには使用できません(\"verify-full\"を使用してください)" -#: fe-connect.c:1660 fe-connect.c:1668 +#: fe-connect.c:1877 fe-connect.c:1885 #, c-format msgid "invalid \"%s\" value: \"%s\"" msgstr "\"%s\"の値が不正: \"%s\"" -#: fe-connect.c:1685 +#: fe-connect.c:1902 #, c-format msgid "invalid SSL protocol version range" msgstr "不正なSSLプロトコルバージョン範囲" -#: fe-connect.c:1722 +#: fe-connect.c:1939 #, c-format msgid "%s value \"%s\" is not supported (check OpenSSL version)" msgstr "%s 値\"%s\"はサポートされていません(OpenSSLのバージョンを確認してください)" -#: fe-connect.c:1752 +#: fe-connect.c:1969 #, c-format msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" msgstr "gssencmodeの値\"%s\"はGSSAPIサポートがコンパイルされていない場合は不正" -#: fe-connect.c:2045 +#: fe-connect.c:2023 +#, c-format +msgid "invalid SCRAM client key" +msgstr "不正なSCRAMクライアントキー" + +#: fe-connect.c:2029 +#, c-format +msgid "invalid SCRAM client key length: %d" +msgstr "不正なSCRAMクライアントキー長: %d" + +#: fe-connect.c:2048 +#, c-format +msgid "invalid SCRAM server key" +msgstr "不正なSCRAMサーバーキー" + +#: fe-connect.c:2054 +#, c-format +msgid "invalid SCRAM server key length: %d" +msgstr "不正なSCRAMサーバーキー長: %d" + +#: fe-connect.c:2142 +#, c-format +msgid "min_protocol_version is greater than max_protocol_version" +msgstr "min_protocol_version が max_protocol_version よりも大きいです" + +#: fe-connect.c:2354 #, c-format msgid "could not set socket to TCP no delay mode: %s" msgstr "TCPソケットを非遅延モードに設定できませんでした: %s" -#: fe-connect.c:2104 +#: fe-connect.c:2413 #, c-format msgid "connection to server on socket \"%s\" failed: " msgstr "ソケット\"%s\"のサーバーへの接続に失敗しました: " -#: fe-connect.c:2130 +#: fe-connect.c:2439 #, c-format msgid "connection to server at \"%s\" (%s), port %s failed: " msgstr "\"%s\"(%s)、ポート%sのサーバーへの接続に失敗しました: " -#: fe-connect.c:2135 +#: fe-connect.c:2444 #, c-format msgid "connection to server at \"%s\", port %s failed: " msgstr "\"%s\"、ポート%sのサーバーへの接続に失敗しました: " -#: fe-connect.c:2158 +#: fe-connect.c:2467 #, c-format msgid "\tIs the server running locally and accepting connections on that socket?" msgstr "\tサーバーはローカルで稼働していてそのソケットで接続を受け付けていますか?" -#: fe-connect.c:2160 +#: fe-connect.c:2469 #, c-format msgid "\tIs the server running on that host and accepting TCP/IP connections?" msgstr "\tサーバーはそのホスト上で稼働していてTCP/IP接続を受け付けていますか?" -#: fe-connect.c:2206 fe-connect.c:2240 fe-connect.c:2275 fe-connect.c:2373 -#: fe-connect.c:3098 +#: fe-connect.c:2515 fe-connect.c:2549 fe-connect.c:2584 fe-connect.c:2682 +#: fe-connect.c:3408 #, c-format msgid "%s(%s) failed: %s" msgstr "%s(%s)が失敗しました: %s" -#: fe-connect.c:2339 +#: fe-connect.c:2648 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s)が失敗しました: エラーコード %d" -#: fe-connect.c:2650 +#: fe-connect.c:2960 #, c-format msgid "invalid connection state, probably indicative of memory corruption" msgstr "接続状態が不正です。メモリ障害の可能性があります" -#: fe-connect.c:2733 +#: fe-connect.c:3043 #, c-format msgid "invalid port number: \"%s\"" msgstr "不正なポート番号です: \"%s\"" -#: fe-connect.c:2747 +#: fe-connect.c:3057 #, c-format msgid "could not translate host name \"%s\" to address: %s" msgstr "ホスト名\"%s\"をアドレスに変換できませんでした: %s" -#: fe-connect.c:2759 +#: fe-connect.c:3069 #, c-format msgid "could not parse network address \"%s\": %s" msgstr "ネットワークアドレス\"%s\"をパースできませんでした: %s" -#: fe-connect.c:2770 +#: fe-connect.c:3080 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Unixドメインソケットのパス\"%s\"が長すぎます(最大 %d バイト)" -#: fe-connect.c:2784 +#: fe-connect.c:3094 #, c-format msgid "could not translate Unix-domain socket path \"%s\" to address: %s" msgstr "Unixドメインソケットのパス\"%s\"をアドレスに変換できませんでした: %s" -#: fe-connect.c:2950 fe-connect.c:4302 +#: fe-connect.c:3260 fe-connect.c:4707 #, c-format msgid "GSSAPI encryption required but it is not supported over a local socket" msgstr "GSSAPI暗号化が要求されていますが、ローカルソケットではサポートされません" -#: fe-connect.c:2958 fe-connect.c:4431 +#: fe-connect.c:3268 fe-connect.c:4836 #, c-format msgid "GSSAPI encryption required but no credential cache" msgstr "GSSAPI暗号化が要求されましたが、資格証明キャッシュがありません" -#: fe-connect.c:3026 +#: fe-connect.c:3336 #, c-format msgid "could not create socket: %s" msgstr "ソケットを作成できませんでした: %s" -#: fe-connect.c:3057 +#: fe-connect.c:3367 #, c-format msgid "could not set socket to nonblocking mode: %s" msgstr "ソケットを非ブロッキングモードに設定できませんでした: %s\\" -#: fe-connect.c:3068 +#: fe-connect.c:3378 #, c-format msgid "could not set socket to close-on-exec mode: %s" msgstr "ソケットをclose-on-execモードに設定できませんでした: %s" -#: fe-connect.c:3086 -#, c-format -msgid "keepalives parameter must be an integer" -msgstr "keepaliveのパラメータは整数でなければなりません" - -#: fe-connect.c:3225 +#: fe-connect.c:3535 #, c-format msgid "could not get socket error status: %s" msgstr "ソケットのエラー状態を取得できませんでした: %s" -#: fe-connect.c:3252 +#: fe-connect.c:3562 #, c-format msgid "could not get client address from socket: %s" msgstr "ソケットからクライアントアドレスを取得できませんでした: %s" -#: fe-connect.c:3278 +#: fe-connect.c:3588 #, c-format msgid "requirepeer parameter is not supported on this platform" msgstr "このプラットフォームでは requirepeer パラメータはサポートされていません" -#: fe-connect.c:3280 +#: fe-connect.c:3590 #, c-format msgid "could not get peer credentials: %s" msgstr "接続先の資格証明を取得できませんでした: %s" -#: fe-connect.c:3293 +#: fe-connect.c:3603 #, c-format msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" msgstr "requirepeerは\"%s\"を指定していますが、実際の接続先名は\"%s\"です" -#: fe-connect.c:3331 +#: fe-connect.c:3641 #, c-format msgid "could not send GSSAPI negotiation packet: %s" msgstr "GSSAPIネゴシエーションパケットを送信できませんでした: %s" -#: fe-connect.c:3380 +#: fe-connect.c:3680 #, c-format msgid "could not send SSL negotiation packet: %s" msgstr "SSLネゴシエーションパケットを送信できませんでした: %s" -#: fe-connect.c:3412 +#: fe-connect.c:3706 #, c-format msgid "could not send cancel packet: %s" msgstr "キャンセルパケットを送信できませんでした: %s" -#: fe-connect.c:3442 +#: fe-connect.c:3736 #, c-format msgid "could not send startup packet: %s" msgstr "開始パケットを送信できませんでした: %s" -#: fe-connect.c:3509 +#: fe-connect.c:3809 msgid "server does not support SSL, but SSL was required" msgstr "サーバーはSSLをサポートしていませんが、要求されています" -#: fe-connect.c:3528 +#: fe-connect.c:3819 +#, c-format +msgid "server sent an error response during SSL exchange" +msgstr "SSLハンドシェイク中にサーバーからエラー応答が返されました" + +#: fe-connect.c:3824 #, c-format msgid "received invalid response to SSL negotiation: %c" msgstr "SSLネゴシエーションに対して不正な応答を受信しました: %c" -#: fe-connect.c:3556 +#: fe-connect.c:3844 #, c-format msgid "received unencrypted data after SSL response" msgstr "SSL応答の後に非暗号化データを受信しました" -#: fe-connect.c:3630 +#: fe-connect.c:3907 +#, c-format +msgid "server sent an error response during GSS encryption exchange" +msgstr "GSS暗号化ハンドシェイク中にサーバーからエラー応答が返されました" + +#: fe-connect.c:3925 msgid "server doesn't support GSSAPI encryption, but it was required" msgstr "サーバーがGSSAPI暗号化サポートしていませんが、要求されてます" -#: fe-connect.c:3634 +#: fe-connect.c:3929 #, c-format msgid "received invalid response to GSSAPI negotiation: %c" msgstr "GSSAPIネゴシエーションに対して不正な応答を受信しました: %c" -#: fe-connect.c:3652 +#: fe-connect.c:3951 #, c-format msgid "received unencrypted data after GSSAPI encryption response" msgstr "GSSAPI暗号化応答の後に非暗号化データを受信しました" -#: fe-connect.c:3708 +#: fe-connect.c:4012 #, c-format msgid "expected authentication request from server, but received %c" msgstr "サーバーからの認証要求を想定していましたが、%cを受信しました" -#: fe-connect.c:3736 fe-connect.c:3859 +#: fe-connect.c:4040 fe-connect.c:4172 #, c-format msgid "received invalid authentication request" msgstr "不正な認証要求を受信しました" -#: fe-connect.c:3742 fe-connect.c:3844 +#: fe-connect.c:4046 #, c-format msgid "received invalid protocol negotiation message" msgstr "不正なプロトコルネゴシエーションメッセージを受信しました" -#: fe-connect.c:3761 fe-connect.c:3815 +#: fe-connect.c:4065 fe-connect.c:4119 #, c-format msgid "received invalid error message" msgstr "不正なエラーメッセージを受信しました" -#: fe-connect.c:3930 +#: fe-connect.c:4149 +#, c-format +msgid "received duplicate protocol negotiation message" +msgstr "重複したプロトコルネゴシエーションメッセージを受信しました" + +#: fe-connect.c:4251 +#, c-format +msgid "internal error: async authentication has no handler" +msgstr "内部エラー: 非同期認証のハンドラーがありません" + +#: fe-connect.c:4276 +#, c-format +msgid "internal error: async cleanup did not release polling socket" +msgstr "内部エラー: 非同期クリーンアップがポーリング中のソケットを解放しませんでした" + +#: fe-connect.c:4299 +#, c-format +msgid "internal error: async authentication did not set a socket for polling" +msgstr "内部エラー: 非同期認証がポーリング対象のソケットを設定しませんでした" + +#: fe-connect.c:4332 #, c-format msgid "unexpected message from server during startup" msgstr "起動中にサーバーから想定外のメッセージがありました" -#: fe-connect.c:4021 +#: fe-connect.c:4423 #, c-format msgid "session is read-only" msgstr "セッションは読み取り専用です" -#: fe-connect.c:4023 +#: fe-connect.c:4425 #, c-format msgid "session is not read-only" msgstr "セッションは読み取り専用ではありません" -#: fe-connect.c:4076 +#: fe-connect.c:4478 #, c-format msgid "server is in hot standby mode" msgstr "サーバーはホットスタンバイモードです" -#: fe-connect.c:4078 +#: fe-connect.c:4480 #, c-format msgid "server is not in hot standby mode" msgstr "サーバーはスタンバイモードではありません" -#: fe-connect.c:4200 fe-connect.c:4250 +#: fe-connect.c:4605 fe-connect.c:4655 #, c-format msgid "\"%s\" failed" msgstr "\"%s\"が失敗しました" -#: fe-connect.c:4264 +#: fe-connect.c:4669 #, c-format msgid "invalid connection state %d, probably indicative of memory corruption" msgstr "接続状態%dは不正です。メモリ障害の可能性があります" -#: fe-connect.c:5083 +#: fe-connect.c:5498 #, c-format msgid "invalid LDAP URL \"%s\": scheme must be ldap://" msgstr "不正なLDAP URL\"%s\":スキームはldap://でなければなりません" -#: fe-connect.c:5098 +#: fe-connect.c:5513 #, c-format msgid "invalid LDAP URL \"%s\": missing distinguished name" msgstr "不正なLDAP URL \"%s\": 識別名がありません" -#: fe-connect.c:5110 fe-connect.c:5168 +#: fe-connect.c:5525 fe-connect.c:5583 #, c-format msgid "invalid LDAP URL \"%s\": must have exactly one attribute" msgstr "不正なLDAP URL \"%s\": ちょうど1つの属性を持たなければなりません" -#: fe-connect.c:5122 fe-connect.c:5184 +#: fe-connect.c:5537 fe-connect.c:5599 #, c-format msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" msgstr "不正なLDAP URL \"%s\": 検索スコープ(base/one/sub)を持たなければなりません" -#: fe-connect.c:5134 +#: fe-connect.c:5549 #, c-format msgid "invalid LDAP URL \"%s\": no filter" msgstr "不正なLDAP URL \"%s\": フィルタがありません" -#: fe-connect.c:5156 +#: fe-connect.c:5571 #, c-format msgid "invalid LDAP URL \"%s\": invalid port number" msgstr "不正なLDAP URL \"%s\": ポート番号が不正です" -#: fe-connect.c:5193 +#: fe-connect.c:5608 #, c-format msgid "could not create LDAP structure" msgstr "LDAP構造体を作成できませんでした" -#: fe-connect.c:5268 +#: fe-connect.c:5683 #, c-format msgid "lookup on LDAP server failed: %s" msgstr "LDAPサーバーで検索に失敗しました: %s" -#: fe-connect.c:5278 +#: fe-connect.c:5693 #, c-format msgid "more than one entry found on LDAP lookup" msgstr "LDAP参照で複数のエントリが見つかりました" -#: fe-connect.c:5280 fe-connect.c:5291 +#: fe-connect.c:5695 fe-connect.c:5706 #, c-format msgid "no entry found on LDAP lookup" msgstr "LDAP参照でエントリが見つかりません" -#: fe-connect.c:5301 fe-connect.c:5313 +#: fe-connect.c:5716 fe-connect.c:5728 #, c-format msgid "attribute has no values on LDAP lookup" msgstr "LDAP参照で属性に値がありません" -#: fe-connect.c:5364 fe-connect.c:5383 fe-connect.c:5907 +#: fe-connect.c:5779 fe-connect.c:5798 fe-connect.c:6322 #, c-format msgid "missing \"=\" after \"%s\" in connection info string" msgstr "接続情報文字列において\"%s\"の後に\"=\"がありませんでした" -#: fe-connect.c:5454 fe-connect.c:6090 fe-connect.c:6888 +#: fe-connect.c:5869 fe-connect.c:6505 fe-connect.c:7335 #, c-format msgid "invalid connection option \"%s\"" msgstr "不正な接続オプション\"%s\"" -#: fe-connect.c:5469 fe-connect.c:5955 +#: fe-connect.c:5884 fe-connect.c:6370 #, c-format msgid "unterminated quoted string in connection info string" msgstr "接続情報文字列内の閉じていない引用符" -#: fe-connect.c:5549 +#: fe-connect.c:5964 #, c-format msgid "definition of service \"%s\" not found" msgstr "サービス定義\"%s\"がみつかりません" -#: fe-connect.c:5575 +#: fe-connect.c:5990 #, c-format msgid "service file \"%s\" not found" msgstr "サービスファイル\"%s\"がみつかりません" -#: fe-connect.c:5588 +#: fe-connect.c:6003 #, c-format msgid "line %d too long in service file \"%s\"" msgstr "サービスファイル\"%2$s\"の行%1$dが長すぎます" -#: fe-connect.c:5659 fe-connect.c:5702 +#: fe-connect.c:6074 fe-connect.c:6117 #, c-format msgid "syntax error in service file \"%s\", line %d" msgstr "サービスファイル\"%s\"の行%dで構文エラー" -#: fe-connect.c:5670 +#: fe-connect.c:6085 #, c-format msgid "nested service specifications not supported in service file \"%s\", line %d" msgstr "サービスファイル\"%s\"、行%dでのネストしたサービス指定はサポートされていません" -#: fe-connect.c:6409 +#: fe-connect.c:6824 #, c-format msgid "invalid URI propagated to internal parser routine: \"%s\"" msgstr "内部パーサ処理へ伝播した不正なURI: \"%s\"" -#: fe-connect.c:6486 +#: fe-connect.c:6901 #, c-format msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" msgstr "URI \"%s\"内のIPv6ホストアドレスにおいて対応する\"]\"を探している間に文字列が終わりました" -#: fe-connect.c:6493 +#: fe-connect.c:6908 #, c-format msgid "IPv6 host address may not be empty in URI: \"%s\"" msgstr "URI内ではIPv6ホストアドレスは空であってはなりません: \"%s\"" -#: fe-connect.c:6508 +#: fe-connect.c:6923 #, c-format msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" msgstr "URI内の位置%2$dに想定外の文字\"%1$c\"があります(\":\"または\"/\"を期待していました): \"%3$s\"" -#: fe-connect.c:6637 +#: fe-connect.c:7052 #, c-format msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "URI問い合わせパラメータ内にキーと値を分ける\"=\"が余分にあります: \"%s\"" -#: fe-connect.c:6657 +#: fe-connect.c:7072 #, c-format msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "URI問い合わせパラメータ内にキーと値を分ける\\\"=\\\"がありません: \"%s\"" -#: fe-connect.c:6709 +#: fe-connect.c:7124 #, c-format msgid "invalid URI query parameter: \"%s\"" msgstr "不正なURI問い合わせパラメータ:\"%s\"" -#: fe-connect.c:6783 +#: fe-connect.c:7208 #, c-format msgid "invalid percent-encoded token: \"%s\"" msgstr "不正なパーセント符号化トークン: \"%s\"" -#: fe-connect.c:6793 +#: fe-connect.c:7218 #, c-format msgid "forbidden value %%00 in percent-encoded value: \"%s\"" msgstr "パーセント符号化された値では値%%00は許されません: \"%s\"" -#: fe-connect.c:7157 +#: fe-connect.c:7240 +#, c-format +msgid "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead" +msgstr "\"%s\"に予期しない空白文字があります、代わりにパーセントエンコードされた空白文字(%%20)を使用してください" + +#: fe-connect.c:7622 msgid "connection pointer is NULL\n" msgstr "接続ポインタはNULLです\n" -#: fe-connect.c:7165 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 -#: fe-protocol3.c:991 fe-protocol3.c:1024 +#: fe-connect.c:7630 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 +#: fe-protocol3.c:987 fe-protocol3.c:1020 msgid "out of memory\n" msgstr "メモリ不足\n" -#: fe-connect.c:7456 +#: fe-connect.c:7932 #, c-format msgid "WARNING: password file \"%s\" is not a plain file\n" msgstr "WARNING: パスワードファイル\"%s\"がテキストファイルではありません\n" -#: fe-connect.c:7465 +#: fe-connect.c:7942 #, c-format msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" msgstr "警告: パスワードファイル \"%s\" がグループメンバもしくは他のユーザーから読める状態になっています。この権限はu=rw (0600)以下にすべきです\n" -#: fe-connect.c:7572 +#: fe-connect.c:8046 #, c-format msgid "password retrieved from file \"%s\"" msgstr "パスワードはファイル\"%s\"から取り出しました" -#: fe-connect.c:7724 +#: fe-connect.c:8212 #, c-format msgid "invalid integer value \"%s\" for connection option \"%s\"" msgstr "接続オプション\"%2$s\"に対する不正な整数値\"%1$s\"" @@ -824,7 +895,7 @@ msgstr "接続オプション\"%2$s\"に対する不正な整数値\"%1$s\"" msgid "row number %d is out of range 0..%d" msgstr "行番号%dは0..%dの範囲を超えています" -#: fe-exec.c:531 fe-protocol3.c:1993 +#: fe-exec.c:531 fe-protocol3.c:2067 #, c-format msgid "%s" msgstr "%s" @@ -915,7 +986,7 @@ msgstr "COPY BOTH 実行中の PQexec は許可されていません" msgid "unrecognized message type \"%c\"" msgstr "認識できないメッセージタイプ\"%c\"" -#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1924 +#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1998 #, c-format msgid "no COPY in progress" msgstr "実行中のCOPYはありません" @@ -973,11 +1044,16 @@ msgstr "パラメータ%dは0..%dの範囲を超えています" msgid "could not interpret result from server: %s" msgstr "サーバーからの結果を解釈できませんでした: %s" -#: fe-exec.c:4127 fe-exec.c:4217 +#: fe-exec.c:4140 fe-exec.c:4253 #, c-format msgid "incomplete multibyte character" msgstr "不完全なマルチバイト文字" +#: fe-exec.c:4142 fe-exec.c:4272 +#, c-format +msgid "invalid multibyte character" +msgstr "不正なマルチバイト文字" + #: fe-gssapi-common.c:122 msgid "GSSAPI name import error" msgstr "GSSAPI名のインポートエラー" @@ -1034,8 +1110,8 @@ msgstr "サイズ%luの整数はpqGetIntでサポートされていません" msgid "integer of size %lu not supported by pqPutInt" msgstr "サイズ%luの整数はpqPutIntでサポートされていません" -#: fe-misc.c:750 fe-secure-openssl.c:203 fe-secure-openssl.c:309 -#: fe-secure.c:237 fe-secure.c:404 +#: fe-misc.c:765 fe-secure-openssl.c:181 fe-secure-openssl.c:287 +#: fe-secure.c:222 fe-secure.c:389 #, c-format msgid "" "server closed the connection unexpectedly\n" @@ -1046,171 +1122,200 @@ msgstr "" " おそらく要求の処理前または処理中にサーバーが異常終了\n" " したことを意味しています。" -#: fe-misc.c:817 +#: fe-misc.c:832 msgid "connection not open\n" msgstr "接続はオープンされていません\n" -#: fe-misc.c:1005 +#: fe-misc.c:1020 #, c-format msgid "timeout expired" msgstr "タイムアウト期間が過ぎました" -#: fe-misc.c:1049 +#: fe-misc.c:1072 #, c-format msgid "invalid socket" msgstr "不正なソケットです" -#: fe-misc.c:1071 +#: fe-misc.c:1095 #, c-format msgid "%s() failed: %s" msgstr "%s() が失敗しました: %s" -#: fe-protocol3.c:187 +#: fe-protocol3.c:188 #, c-format msgid "message type 0x%02x arrived from server while idle" msgstr "待機中にサーバーからメッセージ種類0x%02xが届きました" -#: fe-protocol3.c:402 +#: fe-protocol3.c:401 #, c-format msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" msgstr "サーバーが先行の行記述(\"T\"メッセージ)なしでデータ(\"D\"メッセージ)を送信しました" -#: fe-protocol3.c:444 +#: fe-protocol3.c:443 #, c-format msgid "unexpected response from server; first received character was \"%c\"" msgstr "サーバーから想定外の応答がありました。受け付けた先頭文字は\"%c\"です" -#: fe-protocol3.c:467 +#: fe-protocol3.c:462 #, c-format msgid "message contents do not agree with length in message type \"%c\"" msgstr "メッセージの内容がメッセージタイプ\"%c\"での長さと合っていません" -#: fe-protocol3.c:485 +#: fe-protocol3.c:480 #, c-format msgid "lost synchronization with server: got message type \"%c\", length %d" msgstr "サーバーとの同期が失われました。受信したメッセージタイプは\"%c\"、長さは%d" -#: fe-protocol3.c:537 fe-protocol3.c:577 +#: fe-protocol3.c:532 fe-protocol3.c:572 msgid "insufficient data in \"T\" message" msgstr "\"T\"メッセージ内のデータが不十分です" -#: fe-protocol3.c:648 fe-protocol3.c:854 +#: fe-protocol3.c:643 fe-protocol3.c:849 msgid "out of memory for query result" msgstr "問い合わせ結果用のメモリが不足しています" -#: fe-protocol3.c:717 +#: fe-protocol3.c:712 msgid "insufficient data in \"t\" message" msgstr "\"t\"メッセージ内のデータが足りません" -#: fe-protocol3.c:776 fe-protocol3.c:808 fe-protocol3.c:826 +#: fe-protocol3.c:771 fe-protocol3.c:803 fe-protocol3.c:821 msgid "insufficient data in \"D\" message" msgstr "\"D\"\"メッセージ内のデータが不十分です" -#: fe-protocol3.c:782 +#: fe-protocol3.c:777 msgid "unexpected field count in \"D\" message" msgstr "\"D\"メッセージ内のフィールド数が想定外です。" -#: fe-protocol3.c:1037 +#: fe-protocol3.c:1033 msgid "no error message available\n" msgstr "エラーメッセージがありません\n" #. translator: %s represents a digit string -#: fe-protocol3.c:1085 fe-protocol3.c:1104 +#: fe-protocol3.c:1081 fe-protocol3.c:1100 #, c-format msgid " at character %s" msgstr "(文字位置: %s)" -#: fe-protocol3.c:1117 +#: fe-protocol3.c:1113 #, c-format msgid "DETAIL: %s\n" msgstr "DETAIL: %s\n" -#: fe-protocol3.c:1120 +#: fe-protocol3.c:1116 #, c-format msgid "HINT: %s\n" msgstr "HINT: %s\n" -#: fe-protocol3.c:1123 +#: fe-protocol3.c:1119 #, c-format msgid "QUERY: %s\n" msgstr "QUERY: %s\n" -#: fe-protocol3.c:1130 +#: fe-protocol3.c:1126 #, c-format msgid "CONTEXT: %s\n" msgstr "CONTEXT: %s\n" -#: fe-protocol3.c:1139 +#: fe-protocol3.c:1135 #, c-format msgid "SCHEMA NAME: %s\n" msgstr "SCHEMA NAME: %s\n" -#: fe-protocol3.c:1143 +#: fe-protocol3.c:1139 #, c-format msgid "TABLE NAME: %s\n" msgstr "TABLE NAME: %s\n" -#: fe-protocol3.c:1147 +#: fe-protocol3.c:1143 #, c-format msgid "COLUMN NAME: %s\n" msgstr "COLUMN NAME: %s\n" -#: fe-protocol3.c:1151 +#: fe-protocol3.c:1147 #, c-format msgid "DATATYPE NAME: %s\n" msgstr "DATATYPE NAME: %s\n" -#: fe-protocol3.c:1155 +#: fe-protocol3.c:1151 #, c-format msgid "CONSTRAINT NAME: %s\n" msgstr "CONSTRAINT NAME: %s\n" -#: fe-protocol3.c:1167 +#: fe-protocol3.c:1163 msgid "LOCATION: " msgstr "LOCATION: " -#: fe-protocol3.c:1169 +#: fe-protocol3.c:1165 #, c-format msgid "%s, " msgstr "%s, " -#: fe-protocol3.c:1171 +#: fe-protocol3.c:1167 #, c-format msgid "%s:%s" msgstr "%s:%s" -#: fe-protocol3.c:1366 +#: fe-protocol3.c:1362 #, c-format msgid "LINE %d: " msgstr "行 %d: " -#: fe-protocol3.c:1440 +#: fe-protocol3.c:1424 #, c-format -msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" -msgstr "サーバーはこのプロトコルバージョンをサポートしていません。クライアントは%u.%uを使用、 サーバーは%u.%uまでをサポートします" +msgid "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーがより大きなバージョン番号へのダウングレードを要求しました" -#: fe-protocol3.c:1446 +#: fe-protocol3.c:1430 #, c-format -msgid "protocol extension not supported by server: %s" -msgid_plural "protocol extensions not supported by server: %s" -msgstr[0] "サーバーでサポートされていないプロトコル拡張: %s" +msgid "received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーが3.0より前のプロトコルバージョンへのダウングレードを要求しました" -#: fe-protocol3.c:1454 +#: fe-protocol3.c:1437 #, c-format -msgid "invalid %s message" -msgstr "不正な%sメッセージ" +msgid "received invalid protocol negotiation message: server requests downgrade to non-existent 3.1 protocol version" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーが存在しない 3.1 プロトコルバージョンを要求しました" -#: fe-protocol3.c:1819 +#: fe-protocol3.c:1443 +#, c-format +msgid "received invalid protocol negotiation message: server reported negative number of unsupported parameters" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーがサポート外パラメータの数として負数を通知しました" + +#: fe-protocol3.c:1449 +#, c-format +msgid "received invalid protocol negotiation message: server negotiated but asks for no changes" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーがネゴシエーションを行いましたが、変更要求がありませんでした" + +#: fe-protocol3.c:1455 +#, c-format +msgid "server only supports protocol version %d.%d, but min_protocol_version was set to %d.%d" +msgstr "サーバーはプロトコルバージョン %d.%d のみサポートしていますが、min_protocol_version は %d.%d に設定されています" + +#: fe-protocol3.c:1479 +#, c-format +msgid "received invalid protocol negotiation message: server reported unsupported parameter name without a _pq_. prefix (\"%s\")" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーが _pq_. プレフィクスのないサポートされていないパラメータ名(\"%s\")を報告しました" + +#: fe-protocol3.c:1482 +#, c-format +msgid "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: サーバーが要求されていないサポート外のパラメータ(\"%s\")を通知しました" + +#: fe-protocol3.c:1489 +#, c-format +msgid "received invalid protocol negotation message: message too short" +msgstr "不正なプロトコルネゴシエーションメッセージを受信: メッセージが短すぎます" + +#: fe-protocol3.c:1893 #, c-format msgid "PQgetline: not doing text COPY OUT" msgstr "PQgetline: テキストのCOPY OUTを行っていません" -#: fe-protocol3.c:2193 +#: fe-protocol3.c:2268 #, c-format msgid "protocol error: no function result" msgstr "プロトコルエラー: 関数の結果がありません" -#: fe-protocol3.c:2204 +#: fe-protocol3.c:2280 #, c-format msgid "protocol error: id=0x%x" msgstr "プロトコルエラー: id=0x%x" @@ -1291,92 +1396,102 @@ msgstr "GSSAPIサイズチェックエラー" msgid "GSSAPI context establishment error" msgstr "GSSAPIコンテクスト確立エラー" -#: fe-secure-openssl.c:207 fe-secure-openssl.c:313 fe-secure-openssl.c:1524 +#: fe-secure-openssl.c:185 fe-secure-openssl.c:291 fe-secure-openssl.c:1378 #, c-format msgid "SSL SYSCALL error: %s" msgstr "SSL SYSCALLエラー: %s" -#: fe-secure-openssl.c:213 fe-secure-openssl.c:319 fe-secure-openssl.c:1527 +#: fe-secure-openssl.c:191 fe-secure-openssl.c:297 fe-secure-openssl.c:1381 #, c-format msgid "SSL SYSCALL error: EOF detected" msgstr "SSL SYSCALLエラー: EOFを検出" -#: fe-secure-openssl.c:223 fe-secure-openssl.c:329 fe-secure-openssl.c:1535 +#: fe-secure-openssl.c:201 fe-secure-openssl.c:307 fe-secure-openssl.c:1389 #, c-format msgid "SSL error: %s" msgstr "SSLエラー: %s" -#: fe-secure-openssl.c:237 fe-secure-openssl.c:343 +#: fe-secure-openssl.c:215 fe-secure-openssl.c:321 #, c-format msgid "SSL connection has been closed unexpectedly" msgstr "SSL接続が意図せずにクローズされました" -#: fe-secure-openssl.c:242 fe-secure-openssl.c:348 fe-secure-openssl.c:1582 +#: fe-secure-openssl.c:220 fe-secure-openssl.c:326 fe-secure-openssl.c:1436 #, c-format msgid "unrecognized SSL error code: %d" msgstr "認識できないSSLエラーコード: %d" -#: fe-secure-openssl.c:390 +#: fe-secure-openssl.c:368 #, c-format msgid "could not determine server certificate signature algorithm" msgstr "サーバー証明書の署名アルゴリズムを特定できませんでした" -#: fe-secure-openssl.c:410 +#: fe-secure-openssl.c:388 #, c-format msgid "could not find digest for NID %s" msgstr "NID %sのダイジェストが見つかりませんでした" -#: fe-secure-openssl.c:419 +#: fe-secure-openssl.c:397 #, c-format msgid "could not generate peer certificate hash" msgstr "接続先の証明書ハッシュの生成に失敗しました" -#: fe-secure-openssl.c:501 +#: fe-secure-openssl.c:479 #, c-format msgid "SSL certificate's name entry is missing" msgstr "SSL証明書に名前のエントリがありません" -#: fe-secure-openssl.c:535 +#: fe-secure-openssl.c:509 #, c-format msgid "SSL certificate's address entry is missing" msgstr "SSL証明書のアドレスのエントリがありません" -#: fe-secure-openssl.c:935 +#: fe-secure-openssl.c:714 +#, c-format +msgid "could not open ssl keylog file \"%s\": %s" +msgstr "SSLキーログファイル \"%s\" をオープンできませんでした: %s" + +#: fe-secure-openssl.c:722 +#, c-format +msgid "could not write to ssl keylog file \"%s\": %s" +msgstr "SSLキーログファイル \"%s\" に書き込めませんでした: %s" + +#: fe-secure-openssl.c:775 #, c-format msgid "could not create SSL context: %s" msgstr "SSLコンテキストを作成できませんでした: %s" -#: fe-secure-openssl.c:977 +#: fe-secure-openssl.c:817 #, c-format msgid "invalid value \"%s\" for minimum SSL protocol version" msgstr "SSLプロトコル最小バージョンに対する不正な値\"%s\"" -#: fe-secure-openssl.c:987 +#: fe-secure-openssl.c:827 #, c-format msgid "could not set minimum SSL protocol version: %s" msgstr "SSLプロトコル最小バージョンを設定できませんでした: %s" -#: fe-secure-openssl.c:1003 +#: fe-secure-openssl.c:843 #, c-format msgid "invalid value \"%s\" for maximum SSL protocol version" msgstr "SSLプロトコル最大バージョンに対する不正な値\"%s\"" -#: fe-secure-openssl.c:1013 +#: fe-secure-openssl.c:853 #, c-format msgid "could not set maximum SSL protocol version: %s" msgstr "SSLプロトコル最大バージョンを設定できませんでした: %s" -#: fe-secure-openssl.c:1051 +#: fe-secure-openssl.c:891 #, c-format msgid "could not load system root certificate paths: %s" msgstr "システムルート証明書パスをロードできませんでした: %s" -#: fe-secure-openssl.c:1068 +#: fe-secure-openssl.c:908 #, c-format msgid "could not read root certificate file \"%s\": %s" msgstr "ルート証明書ファイル\"%s\"を読み取れませんでした: %s" -#: fe-secure-openssl.c:1120 +#: fe-secure-openssl.c:960 #, c-format msgid "" "could not get home directory to locate root certificate file\n" @@ -1385,7 +1500,7 @@ msgstr "" "ルート証明書ファイルを特定するためのホームディレクトリが取得できませんでした\n" "ファイルを用意する、 sslrootcert=systemでシステムの信頼済みルート証明書を使用する、または sslmode を変更してサーバー証明書の検証を無効にしてください。" -#: fe-secure-openssl.c:1123 +#: fe-secure-openssl.c:963 #, c-format msgid "" "root certificate file \"%s\" does not exist\n" @@ -1394,127 +1509,137 @@ msgstr "" "ルート証明書ファイル\"%s\"が存在しません\n" "ファイルを用意する、sslrootcert=systemでシステムの信頼済みルート証明書を使用する、またはsslmodeを変更してサーバー証明書の検証を無効にしてください。" -#: fe-secure-openssl.c:1158 +#: fe-secure-openssl.c:998 #, c-format msgid "could not open certificate file \"%s\": %s" msgstr "証明書ファイル\"%s\"をオープンできませんでした: %s" -#: fe-secure-openssl.c:1176 +#: fe-secure-openssl.c:1016 #, c-format msgid "could not read certificate file \"%s\": %s" msgstr "証明書ファイル\"%s\"を読み込めませんでした: %s" -#: fe-secure-openssl.c:1200 +#: fe-secure-openssl.c:1040 #, c-format msgid "could not establish SSL connection: %s" msgstr "SSL接続を確立できませんでした: %s" -#: fe-secure-openssl.c:1232 +#: fe-secure-openssl.c:1053 +#, c-format +msgid "WARNING: sslkeylogfile support requires OpenSSL\n" +msgstr "警告: sslkeylogfile をサポートするにはOpenSSLが必要です\n" + +#: fe-secure-openssl.c:1055 +#, c-format +msgid "WARNING: libpq was not built with sslkeylogfile support\n" +msgstr "警告: libpq は sslkeylogfile のサポート無しでビルドされています\n" + +#: fe-secure-openssl.c:1086 #, c-format msgid "could not set SSL Server Name Indication (SNI): %s" msgstr "SSLサーバー名表示(SNI)を設定できませんでした: %s" -#: fe-secure-openssl.c:1249 +#: fe-secure-openssl.c:1103 #, c-format msgid "could not set SSL ALPN extension: %s" msgstr "SSL ALPN拡張を設定できませんでした: %s" -#: fe-secure-openssl.c:1292 +#: fe-secure-openssl.c:1146 #, c-format msgid "could not load SSL engine \"%s\": %s" msgstr "SSLエンジン\"%s\"を読み込みできませんでした: %s" -#: fe-secure-openssl.c:1303 +#: fe-secure-openssl.c:1157 #, c-format msgid "could not initialize SSL engine \"%s\": %s" msgstr "SSLエンジン\"%s\"を初期化できませんでした: %s" -#: fe-secure-openssl.c:1318 +#: fe-secure-openssl.c:1172 #, c-format msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" msgstr "SSL秘密鍵\"%s\"をエンジン\"%s\"から読み取れませんでした: %s" -#: fe-secure-openssl.c:1331 +#: fe-secure-openssl.c:1185 #, c-format msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" msgstr "SSL秘密鍵\"%s\"をエンジン\"%s\"から読み取れませんでした: %s" -#: fe-secure-openssl.c:1368 +#: fe-secure-openssl.c:1222 #, c-format msgid "certificate present, but not private key file \"%s\"" msgstr "証明書はありますが、秘密鍵ファイル\"%s\"はありません" -#: fe-secure-openssl.c:1371 +#: fe-secure-openssl.c:1225 #, c-format msgid "could not stat private key file \"%s\": %m" msgstr "秘密鍵ファイル\"%s\"をstatできませんでした: %m" -#: fe-secure-openssl.c:1379 +#: fe-secure-openssl.c:1233 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "秘密鍵ファイル\"%s\"は通常のファイルではありません" -#: fe-secure-openssl.c:1412 +#: fe-secure-openssl.c:1266 #, c-format msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" msgstr "秘密鍵ファイル\"%s\"はグループに対して、もしくは無制限にアクセスを許可しています; ファイルのパーミッションは u=rw (0600) かそれよりも狭い必要があります、rootが所有している場合は u=rw,g=r (0640) かそれよりも狭い必要があります" -#: fe-secure-openssl.c:1436 +#: fe-secure-openssl.c:1290 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "秘密鍵ファイル\"%s\"をロードできませんでした: %s" -#: fe-secure-openssl.c:1452 +#: fe-secure-openssl.c:1306 #, c-format msgid "certificate does not match private key file \"%s\": %s" msgstr "証明書と秘密鍵ファイル\"%s\"が一致しません: %s" -#: fe-secure-openssl.c:1521 +#: fe-secure-openssl.c:1375 #, c-format msgid "SSL error: certificate verify failed: %s" msgstr "SSLエラー: 証明書の検証に失敗しました: %s" -#: fe-secure-openssl.c:1566 +#: fe-secure-openssl.c:1420 #, c-format msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." msgstr "このことは、クライアントがSSLプロトコルのバージョン%sから%sの間のいずれもサポートしていないことを示唆しているかもしれません。" -#: fe-secure-openssl.c:1598 +#: fe-secure-openssl.c:1452 #, c-format msgid "direct SSL connection was established without ALPN protocol negotiation extension" msgstr "直接SSL接続がALPNプロトコルネゴシエーション拡張なしで確立されました" -#: fe-secure-openssl.c:1610 +#: fe-secure-openssl.c:1464 #, c-format msgid "SSL connection was established with unexpected ALPN protocol" msgstr "SSL接続が想定外のALPNプロトコルで確立されました" -#: fe-secure-openssl.c:1627 +#: fe-secure-openssl.c:1481 #, c-format msgid "certificate could not be obtained: %s" msgstr "証明書を取得できませんでした: %s" -#: fe-secure-openssl.c:1734 +#: fe-secure-openssl.c:1560 #, c-format msgid "no SSL error reported" msgstr "SSLエラーはありませんでした" -#: fe-secure-openssl.c:1776 +#: fe-secure-openssl.c:1603 #, c-format msgid "SSL error code %lu" msgstr "SSLエラーコード: %lu" -#: fe-secure-openssl.c:2075 +#: fe-secure-openssl.c:1905 #, c-format msgid "WARNING: sslpassword truncated\n" msgstr "警告: sslpasswordが切り詰められました\n" -#: fe-secure.c:248 +#: fe-secure.c:233 #, c-format msgid "could not receive data from server: %s" msgstr "サーバーからデータを受信できませんでした: %s" -#: fe-secure.c:419 +#: fe-secure.c:404 #, c-format msgid "could not send data to server: %s" msgstr "サーバーにデータを送信できませんでした: %s" diff --git a/src/interfaces/libpq/po/ka.po b/src/interfaces/libpq/po/ka.po index eabec3f420cb9..16268bc7b94f3 100644 --- a/src/interfaces/libpq/po/ka.po +++ b/src/interfaces/libpq/po/ka.po @@ -1,14 +1,14 @@ # Georgian message translation file for libpq # Copyright (C) 2022 PostgreSQL Global Development Group # This file is distributed under the same license as the libpq (PostgreSQL) package. -# Temuri Doghonadze , 2022. +# Temuri Doghonadze , 2022-2025. # msgid "" msgstr "" -"Project-Id-Version: libpq (PostgreSQL) 17\n" +"Project-Id-Version: libpq (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-14 02:10+0000\n" -"PO-Revision-Date: 2024-06-14 06:12+0200\n" +"POT-Creation-Date: 2025-05-02 22:10+0000\n" +"PO-Revision-Date: 2025-05-03 01:49+0200\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,803 +16,1165 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: ../../port/user.c:43 ../../port/user.c:79 +#: ../libpq-oauth/oauth-curl.c:292 ../libpq-oauth/oauth-curl.c:1910 #, c-format -msgid "could not look up local user ID %d: %s" -msgstr "ლოკალური მომხმარებლის ID-ის (%d) ამოხსნა შეუძლებელია: %s" +#| msgid "database removal failed: %s" +msgid "libcurl easy handle removal failed: %s" +msgstr "libcurl-ის ადვილი დამმუშავებლის წაშლა ჩავარდა: %s" -#: ../../port/user.c:48 ../../port/user.c:84 +#: ../libpq-oauth/oauth-curl.c:312 #, c-format -msgid "local user with ID %d does not exist" -msgstr "ლოკალური მომხმარებელი ID-ით %d არ არსებობს" +#| msgid "creation of new role failed: %s" +msgid "libcurl multi handle cleanup failed: %s" +msgstr "libcurl-ის დამმუშავებლების მოსუფთავება ჩავარდა: %s" -#: fe-auth-scram.c:223 +#: ../libpq-oauth/oauth-curl.c:375 ../libpq-oauth/oauth-curl.c:386 +#, c-format +msgid "failed to set %s on OAuth connection: %s" +msgstr "%s-ის დაყენება OAuth კავშირზე ჩავარდა: %s" + +#: ../libpq-oauth/oauth-curl.c:397 +#, c-format +msgid "failed to get %s from OAuth response: %s" +msgstr "OAuth-ის პასუხიდან %s-ის მიღება ჩავარდა: %s" + +#: ../libpq-oauth/oauth-curl.c:519 +#, c-format +msgid "internal error: started field '%s' before field '%s' was finished" +msgstr "შიდა შეცდომა: დაიწყო ველი '%s' მანამდე, სანამ დასრულდა ველი '%s'" + +#: ../libpq-oauth/oauth-curl.c:546 +#, c-format +msgid "field \"%s\" is duplicated" +msgstr "ველი \"%s\" დუბლირებულია" + +#: ../libpq-oauth/oauth-curl.c:571 +#, c-format +msgid "internal error: field '%s' still active at end of object" +msgstr "შიდა შეცდომა: ველი '%s' ჯერ კიდევ აქტიურია ობიექტის ბოლოში" + +#: ../libpq-oauth/oauth-curl.c:586 ../libpq-oauth/oauth-curl.c:640 +#, c-format +msgid "top-level element must be an object" +msgstr "უმაღლესი დონის ელემენტი ობიექტი უნდა იყოს" + +#: ../libpq-oauth/oauth-curl.c:621 +#, c-format +msgid "internal error: found unexpected array end while parsing field '%s'" +msgstr "შიდა შეცდომა: აღმოჩენილია მოულოდნელი მასივის დასასრული '%s' ველის დამუშავებისას" + +#: ../libpq-oauth/oauth-curl.c:676 +#, c-format +msgid "internal error: scalar target found at nesting level %d" +msgstr "შიდა შეცდომა: აღმოჩენილია სკალარული სამიზნე ერთმანეთში ჩალაგების დონეზე %d" + +#: ../libpq-oauth/oauth-curl.c:686 +#, c-format +msgid "internal error: scalar field '%s' would be assigned twice" +msgstr "შიდა შეცდომა: შეიძლება, სკალარული ველი '%s' ორჯერაა მინიჭებული" + +#: ../libpq-oauth/oauth-curl.c:708 +#, c-format +msgid "internal error: array member found at nesting level %d" +msgstr "შიდა შეცდომა: ერთმანეთში ჩალაგების დონეზე %d აღმოჩენილია მასივის წევრი" + +#: ../libpq-oauth/oauth-curl.c:743 +#, c-format +msgid "no content type was provided" +msgstr "შემცველობის ტიპი მოწოდებული არაა" + +#: ../libpq-oauth/oauth-curl.c:782 +#, c-format +msgid "unexpected content type: \"%s\"" +msgstr "მოულოდნელი შემცველობის ტიპი: \"%s\"" + +#: ../libpq-oauth/oauth-curl.c:807 +#, c-format +msgid "response contains embedded NULLs" +msgstr "პასუხი ჩაშენებულ NULL-ებს შეიცავს" + +#: ../libpq-oauth/oauth-curl.c:817 +#, c-format +msgid "response is not valid UTF-8" +msgstr "პასუხი არასწორი UTF-8-ა" + +#: ../libpq-oauth/oauth-curl.c:857 +#, c-format +msgid "field \"%s\" is missing" +msgstr "ველი \"%s\" აკლია" + +#: ../libpq-oauth/oauth-curl.c:1091 +#, c-format +msgid "provider rejected the oauth_client_secret" +msgstr "პროვაიდერმა უარჰყო oauth_client_secret" + +#: ../libpq-oauth/oauth-curl.c:1155 +#, c-format +msgid "failed to create epoll set: %m" +msgstr "epoll-ის ნაკრების შექმნა ჩავარდა: %m" + +#: ../libpq-oauth/oauth-curl.c:1162 +#, c-format +msgid "failed to create timerfd: %m" +msgstr "timerfd-ის შექმნა ჩავარდა: %m" + +#: ../libpq-oauth/oauth-curl.c:1168 +#, c-format +msgid "failed to add timerfd to epoll set: %m" +msgstr "epoll-ის ნაკრებში timerfd-ის ჩამატება ჩავარდა; %m" + +#. translator: the term "kqueue" (kernel queue) should not be translated +#: ../libpq-oauth/oauth-curl.c:1178 +#, c-format +msgid "failed to create kqueue: %m" +msgstr "kqueue-ის შექმნა ჩავარდა: %m" + +#: ../libpq-oauth/oauth-curl.c:1191 +#, c-format +msgid "failed to create timer kqueue: %m" +msgstr "ტაიმერის kqueue-ის შექმნა ჩავარდა: %m" + +#: ../libpq-oauth/oauth-curl.c:1235 ../libpq-oauth/oauth-curl.c:1307 +#, c-format +msgid "unknown libcurl socket operation: %d" +msgstr "libcurl-ის სოკეტის უცნობი ოპერაცია: %d" + +#: ../libpq-oauth/oauth-curl.c:1252 +#, c-format +msgid "could not add to epoll set: %m" +msgstr "epoll-ის ნაკრებში ჩამატება შეუძლებელია: %m" + +#: ../libpq-oauth/oauth-curl.c:1256 +#, c-format +msgid "could not delete from epoll set: %m" +msgstr "epoll-ის ნაკრებიდან წაშლა შეუძლებელია: %m" + +#: ../libpq-oauth/oauth-curl.c:1260 +#, c-format +msgid "could not update epoll set: %m" +msgstr "epoll-ების ნაკრების განახლება ჩავარდა: %m" + +#: ../libpq-oauth/oauth-curl.c:1314 +#, c-format +msgid "could not modify kqueue: %m" +msgstr "kqueue-ის შეცვლა შეუძლებელია: %m" + +#: ../libpq-oauth/oauth-curl.c:1338 +#, c-format +msgid "could not delete from kqueue: %m" +msgstr "kqueue-დან წაშლა შეუძლებელია: %m" + +#: ../libpq-oauth/oauth-curl.c:1341 +#, c-format +msgid "could not add to kqueue: %m" +msgstr "kqueue-ში ჩამატება შეუძლებელია: %m" + +#: ../libpq-oauth/oauth-curl.c:1393 +#, c-format +msgid "setting timerfd to %ld: %m" +msgstr "%ld-ზე timerfd-ის დაყენება: %m" + +#: ../libpq-oauth/oauth-curl.c:1423 +#, c-format +msgid "deleting kqueue timer: %m" +msgstr "kqueue-ის ტაიმერის წაშლა: %m" + +#: ../libpq-oauth/oauth-curl.c:1430 +#, c-format +msgid "removing kqueue timer from multiplexer: %m" +msgstr "kqueue-ის ტაიმერის წაშლა მულტიპლექსერიდან: %m" + +#: ../libpq-oauth/oauth-curl.c:1441 +#, c-format +msgid "setting kqueue timer to %ld: %m" +msgstr "kqueue-ის ტაიმერის დაყენება %ld-ზე: %m" + +#: ../libpq-oauth/oauth-curl.c:1448 +#, c-format +msgid "adding kqueue timer to multiplexer: %m" +msgstr "kqueue-ის ტაიმერის დამატება მულტიპლექსერზე: %m" + +#: ../libpq-oauth/oauth-curl.c:1471 +#, c-format +msgid "getting timerfd value: %m" +msgstr "timerfd-ის მნიშვნელობის მიღება: %m" + +#: ../libpq-oauth/oauth-curl.c:1493 +#, c-format +msgid "checking kqueue for timeout: %m" +msgstr "kqueue-ის შემოწმება მოლოდინის დროის ამოწურვაზე: %m" + +#: ../libpq-oauth/oauth-curl.c:1625 +#, c-format +msgid "failed to create libcurl multi handle" +msgstr "libcurl-ის ერთზე მეტი დამმუშავებლის შექმნა ჩავარდა" + +#: ../libpq-oauth/oauth-curl.c:1645 +#, c-format +msgid "failed to create libcurl handle" +msgstr "libcurl-ის დამმუშავებლის შექმნა ჩავარდა" + +#: ../libpq-oauth/oauth-curl.c:1729 ../libpq-oauth/oauth-curl.c:1770 +#: ../libpq-oauth/oauth-curl.c:2083 ../libpq-oauth/oauth-curl.c:2244 +#: ../libpq-oauth/oauth-curl.c:2305 ../libpq-oauth/oauth-curl.c:2394 +#: ../libpq-oauth/oauth-curl.c:2688 ../libpq-oauth/oauth-curl.c:2879 +#: fe-auth-scram.c:374 fe-auth-scram.c:447 fe-auth-scram.c:599 +#: fe-auth-scram.c:619 fe-auth-scram.c:643 fe-auth-scram.c:657 +#: fe-auth-scram.c:703 fe-auth-scram.c:739 fe-auth-scram.c:931 fe-auth.c:308 +#: fe-auth.c:382 fe-auth.c:416 fe-auth.c:694 fe-auth.c:827 fe-auth.c:1330 +#: fe-auth.c:1493 fe-cancel.c:177 fe-connect.c:1011 fe-connect.c:1051 +#: fe-connect.c:2175 fe-connect.c:2337 fe-connect.c:3730 fe-connect.c:5178 +#: fe-connect.c:5491 fe-connect.c:5746 fe-connect.c:5864 fe-connect.c:6111 +#: fe-connect.c:6191 fe-connect.c:6289 fe-connect.c:6540 fe-connect.c:6567 +#: fe-connect.c:6643 fe-connect.c:6666 fe-connect.c:6690 fe-connect.c:6725 +#: fe-connect.c:6811 fe-connect.c:6819 fe-connect.c:7176 fe-connect.c:7358 +#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4291 fe-exec.c:4457 +#: fe-gssapi-common.c:109 fe-lobj.c:870 fe-protocol3.c:210 fe-protocol3.c:233 +#: fe-protocol3.c:256 fe-protocol3.c:273 fe-protocol3.c:294 fe-protocol3.c:368 +#: fe-protocol3.c:732 fe-protocol3.c:972 fe-protocol3.c:1552 +#: fe-protocol3.c:1861 fe-protocol3.c:2262 fe-secure-common.c:110 +#: fe-secure-gssapi.c:496 fe-secure-openssl.c:405 fe-secure-openssl.c:1131 +#, c-format +msgid "out of memory" +msgstr "არასაკმარისი მეხსიერება" + +#: ../libpq-oauth/oauth-curl.c:1757 +#, c-format +msgid "response is too large" +msgstr "პასუხი მეტისმეტად დიდია" + +#: ../libpq-oauth/oauth-curl.c:1799 +#, c-format +msgid "failed to queue HTTP request: %s" +msgstr "HTTP მოთხოვნის რიგში ჩამატება ჩავარდა: %s" + +#: ../libpq-oauth/oauth-curl.c:1816 ../libpq-oauth/oauth-curl.c:1869 +#, c-format +msgid "asynchronous HTTP request failed: %s" +msgstr "ასინქრონული HTTP მოთხოვნა ჩავარდა: %s" + +#: ../libpq-oauth/oauth-curl.c:1921 +#, c-format +msgid "no result was retrieved for the finished handle" +msgstr "დასრულებული დამმუშავებლიდან შედეგი მიღებული არაა" + +#: ../libpq-oauth/oauth-curl.c:2054 ../libpq-oauth/oauth-curl.c:2360 +#: ../libpq-oauth/oauth-curl.c:2439 +#, c-format +msgid "unexpected response code %ld" +msgstr "მოულოდნელი პასუხის კოდი %ld" + +#: ../libpq-oauth/oauth-curl.c:2126 +#, c-format +msgid "the issuer identifier (%s) does not match oauth_issuer (%s)" +msgstr "გამომცემლის იდენტიფიკატორი (%s) oauth_issuer-ს (%s) არ ემთხვევა" + +#: ../libpq-oauth/oauth-curl.c:2153 +#, c-format +msgid "issuer \"%s\" does not provide a device authorization endpoint" +msgstr "გამომცემელმა \"%s\" არ მოგვაწოდა მოწყობილობის ავტორიზაციის ბოლოწერტილი" + +#: ../libpq-oauth/oauth-curl.c:2179 +#, c-format +msgid "device authorization endpoint \"%s\" must use HTTPS" +msgstr "მოწყობილობის ავტორიზაციის ბოლოწერტილი \"%s\" HTTPS-ს უნდა იყენებდეს" + +#: ../libpq-oauth/oauth-curl.c:2188 +#, c-format +msgid "token endpoint \"%s\" must use HTTPS" +msgstr "კოდის ბოლოწერტილი \"%s\" HTTPS-ს უნდა იყენებდეს" + +#: ../libpq-oauth/oauth-curl.c:2497 +#, c-format +msgid "slow_down interval overflow" +msgstr "slow_down-ის ინტერვალის გადავსება" + +#. translator: The first %s is a URL for the user to visit in a +#. browser, and the second %s is a code to be copy-pasted there. +#. +#: ../libpq-oauth/oauth-curl.c:2533 +#, c-format +msgid "Visit %s and enter the code: %s\n" +msgstr "გადადით %s-ზე და შეიყვანეთ კოდი: %s\n" + +#: ../libpq-oauth/oauth-curl.c:2538 +#, c-format +msgid "device prompt failed" +msgstr "მოწყობილობის მოთხოვნა ჩავარდა" + +#: ../libpq-oauth/oauth-curl.c:2594 +#, c-format +msgid "curl_global_init previously failed during OAuth setup" +msgstr "curl_global_init უკვე ჩავარდა OAuth-ის მორგებისას" + +#: ../libpq-oauth/oauth-curl.c:2613 +#, c-format +msgid "curl_global_init failed during OAuth setup" +msgstr "curl_global_init ჩავარდა OAuth-ის მორგებისას" + +#: ../libpq-oauth/oauth-curl.c:2634 +#, c-format +msgid "" +"libcurl is no longer thread-safe\n" +"\tCurl initialization was reported thread-safe when libpq\n" +"\twas compiled, but the currently installed version of\n" +"\tlibcurl reports that it is not. Recompile libpq against\n" +"\tthe installed version of libcurl." +msgstr "" +"libcurl ნაკადებისთვის უსაფრთხო აღარაა\n" +"\tCurl-ის ინიციალიზაცია libpq-ის აგების დროს მითითებული იყო,\n" +"\tროგორც ნაკადებისთვის უსაფრთხო, მაგრამ libcurl-ის ვერსია, რომელიც\n" +"\tამჟამადაა დაყენებული, როგორც ჩანს, არაა. ააგეთ libpq-ი libcurl-ით, რომელიც\n" +"\tახლა გაქვთ დაყენებული." + +#: fe-auth-scram.c:228 #, c-format msgid "malformed SCRAM message (empty message)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (ცარიელი შეტყობინება)" -#: fe-auth-scram.c:228 +#: fe-auth-scram.c:233 #, c-format msgid "malformed SCRAM message (length mismatch)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (სიგრძე არ ემთხვევა)" -#: fe-auth-scram.c:272 +#: fe-auth-scram.c:277 #, c-format msgid "could not verify server signature: %s" msgstr "სერვერის ხელმოწერის შემოწმება შეუძლებელია: %s" -#: fe-auth-scram.c:278 +#: fe-auth-scram.c:283 #, c-format msgid "incorrect server signature" msgstr "სერვერის არასწორი ხელმოწერა" -#: fe-auth-scram.c:287 +#: fe-auth-scram.c:292 #, c-format msgid "invalid SCRAM exchange state" msgstr "არასწორი SCRAM-ის გაცვლის მდგომარეობა" -#: fe-auth-scram.c:311 +#: fe-auth-scram.c:316 #, c-format msgid "malformed SCRAM message (attribute \"%c\" expected)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (აკლია ატრიბუტი \"%c\")" -#: fe-auth-scram.c:320 +#: fe-auth-scram.c:325 #, c-format msgid "malformed SCRAM message (expected character \"=\" for attribute \"%c\")" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (აკლია \"=\" ატრიბუტი \"%c\"-სთვის)" -#: fe-auth-scram.c:360 +#: fe-auth-scram.c:365 #, c-format msgid "could not generate nonce" msgstr "ერთჯერადი კოდის გენერაციის შეცდომა" -#: fe-auth-scram.c:369 fe-auth-scram.c:442 fe-auth-scram.c:594 -#: fe-auth-scram.c:614 fe-auth-scram.c:638 fe-auth-scram.c:652 -#: fe-auth-scram.c:698 fe-auth-scram.c:734 fe-auth-scram.c:908 fe-auth.c:296 -#: fe-auth.c:369 fe-auth.c:403 fe-auth.c:618 fe-auth.c:727 fe-auth.c:1199 -#: fe-auth.c:1362 fe-cancel.c:159 fe-connect.c:936 fe-connect.c:976 -#: fe-connect.c:1860 fe-connect.c:2022 fe-connect.c:3430 fe-connect.c:4758 -#: fe-connect.c:5070 fe-connect.c:5325 fe-connect.c:5443 fe-connect.c:5690 -#: fe-connect.c:5770 fe-connect.c:5868 fe-connect.c:6119 fe-connect.c:6146 -#: fe-connect.c:6222 fe-connect.c:6245 fe-connect.c:6269 fe-connect.c:6304 -#: fe-connect.c:6390 fe-connect.c:6398 fe-connect.c:6755 fe-connect.c:6905 -#: fe-exec.c:530 fe-exec.c:1315 fe-exec.c:3254 fe-exec.c:4234 fe-exec.c:4398 -#: fe-gssapi-common.c:109 fe-lobj.c:870 fe-protocol3.c:209 fe-protocol3.c:232 -#: fe-protocol3.c:255 fe-protocol3.c:272 fe-protocol3.c:293 fe-protocol3.c:369 -#: fe-protocol3.c:737 fe-protocol3.c:976 fe-protocol3.c:1787 -#: fe-protocol3.c:2187 fe-secure-common.c:110 fe-secure-gssapi.c:496 -#: fe-secure-openssl.c:427 fe-secure-openssl.c:1277 -#, c-format -msgid "out of memory" -msgstr "მეხსიერებას გარეთ" - -#: fe-auth-scram.c:376 +#: fe-auth-scram.c:381 #, c-format msgid "could not encode nonce" msgstr "ერთჯერადი კოდის კოდირების შეცდომა" -#: fe-auth-scram.c:564 +#: fe-auth-scram.c:569 #, c-format msgid "could not calculate client proof: %s" msgstr "კლიენტის მტკიცებულების გამოთვლის შეცდომა: %s" -#: fe-auth-scram.c:579 +#: fe-auth-scram.c:584 #, c-format msgid "could not encode client proof" msgstr "კლიენტის მტკიცებულების კოდირების შეცდომა" -#: fe-auth-scram.c:631 +#: fe-auth-scram.c:636 #, c-format msgid "invalid SCRAM response (nonce mismatch)" msgstr "არასწორი SCRAM-ის პასუხი (ერთჯერადი კოდი არ ემთხვევა)" -#: fe-auth-scram.c:661 +#: fe-auth-scram.c:666 #, c-format msgid "malformed SCRAM message (invalid salt)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (არასწორი მარილი)" -#: fe-auth-scram.c:674 +#: fe-auth-scram.c:679 #, c-format msgid "malformed SCRAM message (invalid iteration count)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (იტერაციების არასწორი რიცხვი)" -#: fe-auth-scram.c:679 +#: fe-auth-scram.c:684 #, c-format msgid "malformed SCRAM message (garbage at end of server-first-message)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (ნაპოვნია ნაგავი სერვერისთვის გასაგზავნი პირველი შეტყობინების ბოლოში)" -#: fe-auth-scram.c:713 +#: fe-auth-scram.c:718 #, c-format msgid "error received from server in SCRAM exchange: %s" msgstr "მიღებულია სერვერის შეცდომა SCRAM გგაცვლაში: %s" -#: fe-auth-scram.c:728 +#: fe-auth-scram.c:733 #, c-format msgid "malformed SCRAM message (garbage at end of server-final-message)" msgstr "დამახინჯებული SCRAM შეტყობინება (ნაგავი სერვერის-საბოლოო-შეტყობინების ბოლოში)" -#: fe-auth-scram.c:745 +#: fe-auth-scram.c:750 #, c-format msgid "malformed SCRAM message (invalid server signature)" msgstr "დამახინჯებული SCRAM-ის შეტყობინება (სერვერის არასწორი ხელმოწერა)" -#: fe-auth-scram.c:917 +#: fe-auth-scram.c:940 msgid "could not generate random salt" msgstr "შემთხვევითი მარილის გენერაციის შეცდომა" -#: fe-auth.c:77 +#: fe-auth.c:80 #, c-format msgid "out of memory allocating GSSAPI buffer (%d)" msgstr "არასაკმარისი მეხსიერება GSSAPI-ის ბაფერის გამოყოფისას (%d)" -#: fe-auth.c:138 +#: fe-auth.c:146 msgid "GSSAPI continuation error" msgstr "GSSAPI-ის განგრძობადობის შეცდომა" -#: fe-auth.c:168 fe-auth.c:397 fe-gssapi-common.c:97 fe-secure-common.c:99 +#: fe-auth.c:176 fe-auth.c:410 fe-gssapi-common.c:97 fe-secure-common.c:99 #: fe-secure-common.c:173 #, c-format msgid "host name must be specified" msgstr "ჰოსტის სახელის მითითება აუცილებელია" -#: fe-auth.c:174 +#: fe-auth.c:182 #, c-format msgid "duplicate GSS authentication request" msgstr "დუბლირებული GSS ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:238 +#: fe-auth.c:246 #, c-format msgid "out of memory allocating SSPI buffer (%d)" msgstr "არასაკმარისი მეხსიერება SSPI-ის ბაფერის გამოყოფისას (%d)" -#: fe-auth.c:285 +#: fe-auth.c:297 msgid "SSPI continuation error" msgstr "SSPI-ის განგრძობადობის შეცდომა" -#: fe-auth.c:359 +#: fe-auth.c:372 #, c-format msgid "duplicate SSPI authentication request" msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:384 +#: fe-auth.c:397 msgid "could not acquire SSPI credentials" msgstr "შეცდომა SSPI-ის მომხმ./პაროლის მიღებისას" -#: fe-auth.c:436 +#: fe-auth.c:449 #, c-format msgid "channel binding required, but SSL not in use" msgstr "მითითებულია არხის მიბმა, მაგრამ SSL არ გამოიყენება" -#: fe-auth.c:442 +#: fe-auth.c:455 #, c-format msgid "duplicate SASL authentication request" msgstr "დუბლირებული SASL ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:500 +#: fe-auth.c:513 #, c-format msgid "channel binding is required, but client does not support it" msgstr "არხის მიბმა აუცილებელია, მაგრამ კლიენტს მხარდაჭერა არ გააჩნია" -#: fe-auth.c:516 +#: fe-auth.c:529 #, c-format msgid "server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection" msgstr "სერვერი გვთავაზობს SCRAM-SHA-256-PLUS ავთენტიკაციას მაშინ, როცა SSL გამორთულია" -#: fe-auth.c:531 +#: fe-auth.c:551 #, c-format msgid "none of the server's SASL authentication mechanisms are supported" msgstr "სერვერის SASL ავთენტიკაციის არც ერთი მექანიზმი მხარდაჭერილი არაა" -#: fe-auth.c:538 +#: fe-auth.c:571 +#, c-format +msgid "authentication method requirement \"%s\" failed: server requested %s authentication" +msgstr "ავთენტიკაციის მეთოდის მოთხოვნა \"%s\" ჩავარდა: სერვერმა %s ავთენტიკაცია მოითხოვა" + +#: fe-auth.c:580 #, c-format msgid "channel binding is required, but server did not offer an authentication method that supports channel binding" msgstr "მოთხოვნილია არხზე მიბმა, მაგრამ სერვერმა არ შემოგვთავაზა ავთენტიკაციის მექანიზმი, რომელსაც არხზე მიბმის მხარდაჭერა გააჩნია" -#: fe-auth.c:640 +#: fe-auth.c:716 #, c-format msgid "out of memory allocating SASL buffer (%d)" msgstr "არასაკმარისი მეხსიერება SASL ბაფერის გამოყოფისას (%d)" -#: fe-auth.c:663 +#: fe-auth.c:758 #, c-format msgid "AuthenticationSASLFinal received from server, but SASL authentication was not completed" msgstr "სერვერიდან AuthenticationSASLFinal მიღებულია, მაგრამ SASL ავთენტიკაცია არ დასრულებულა" -#: fe-auth.c:673 +#: fe-auth.c:768 #, c-format msgid "no client response found after SASL exchange success" msgstr "კლიენტის SASL გაცვლის წარმატების შემდეგ პასუხი არ გამოუგზავნია" -#: fe-auth.c:736 fe-auth.c:743 fe-auth.c:1345 fe-auth.c:1356 +#: fe-auth.c:836 fe-auth.c:843 fe-auth.c:1476 fe-auth.c:1487 #, c-format msgid "could not encrypt password: %s" msgstr "პაროლის დაშიფვრის შეცდომა: %s" -#: fe-auth.c:771 +#: fe-auth.c:873 msgid "server requested a cleartext password" msgstr "სერვერმა ღია პაროლი მოითხოვა" -#: fe-auth.c:773 +#: fe-auth.c:875 msgid "server requested a hashed password" msgstr "სერვერმა დაჰეშილი პაროლი მოითხოვა" -#: fe-auth.c:776 +#: fe-auth.c:878 msgid "server requested GSSAPI authentication" msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:778 +#: fe-auth.c:880 msgid "server requested SSPI authentication" msgstr "დუბლირებული SSPI ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:782 +#: fe-auth.c:884 msgid "server requested SASL authentication" msgstr "დუბლირებული SASL ავთენტიკაციის მოთხოვნა" -#: fe-auth.c:785 +#: fe-auth.c:887 msgid "server requested an unknown authentication type" msgstr "სერვერმა უცნობი ავთენტიკაციის ტიპი მოითხოვა" -#: fe-auth.c:818 +#: fe-auth.c:920 #, c-format msgid "server did not request an SSL certificate" msgstr "სერვერს SSL სერტიფიკატი არ მოუთხოვია" -#: fe-auth.c:823 +#: fe-auth.c:925 #, c-format msgid "server accepted connection without a valid SSL certificate" msgstr "სერვერი მიერთების მცდელობას სწორი SSL სერტიფიკატის გარეშე დაეთანხმა" -#: fe-auth.c:877 +#: fe-auth.c:979 msgid "server did not complete authentication" msgstr "სერვერმა ავთენტიკაცია არ დაასრულა" -#: fe-auth.c:911 +#: fe-auth.c:1013 #, c-format msgid "authentication method requirement \"%s\" failed: %s" msgstr "ავთენტიკაციის მეთოდის (\"%s\") მოთხოვნის შეცდომა: %s" -#: fe-auth.c:934 +#: fe-auth.c:1036 #, c-format msgid "channel binding required, but server authenticated client without channel binding" msgstr "არხზე მიბმა მოთხოვნილია, მაგრამ სერვერმა კლიენტის ავთენტიკაცია არხზე მიბმის გარეშე მოახდინა" -#: fe-auth.c:939 +#: fe-auth.c:1041 #, c-format msgid "channel binding required but not supported by server's authentication request" msgstr "არხზე მიბმა მოთხოვნილია, მაგრამ მხარდაუჭერელია სერვერის ავთენტიკაციის მოთხოვნის მიერ" -#: fe-auth.c:973 +#: fe-auth.c:1081 #, c-format msgid "Kerberos 4 authentication not supported" msgstr "Kerberos 4 ავთენტიკაცია მხარდაჭერილი არაა" -#: fe-auth.c:977 +#: fe-auth.c:1085 #, c-format msgid "Kerberos 5 authentication not supported" msgstr "Kerberos 5 ავთენტიკაცია მხარდაჭერილი არაა" -#: fe-auth.c:1047 +#: fe-auth.c:1155 #, c-format msgid "GSSAPI authentication not supported" msgstr "GSSAPI ავთენტიკაცია მხარდაჭერილი არაა" -#: fe-auth.c:1078 +#: fe-auth.c:1186 #, c-format msgid "SSPI authentication not supported" msgstr "SSPI ავთენტიკაცია მხარდაუჭერელია" -#: fe-auth.c:1085 +#: fe-auth.c:1193 #, c-format msgid "Crypt authentication not supported" msgstr "Crypt ავთენტიკაცია მხარდაჭერილი არაა" -#: fe-auth.c:1149 +#: fe-auth.c:1267 #, c-format msgid "authentication method %u not supported" msgstr "ავთენტიკაციის მეთოდი მხარდაუჭერელია: %u" -#: fe-auth.c:1186 +#: fe-auth.c:1307 #, c-format msgid "user name lookup failure: error code %lu" msgstr "მომხარებლის სახელის ამოხსნის პრობლემა: შეცდომის კოდი: %lu" -#: fe-auth.c:1308 +#: fe-auth.c:1315 +#, c-format +msgid "could not look up local user ID %ld: %m" +msgstr "ლოკალური მომხმარებლის ID-ით %ld მოძებნა შეუძლებელია: %m" + +#: fe-auth.c:1320 +#, c-format +msgid "local user with ID %ld does not exist" +msgstr "ლოკალური მომხმარებელი ID-ით %ld არ არსებობს" + +#: fe-auth.c:1439 #, c-format msgid "unexpected shape of result set returned for SHOW" msgstr "ბრძანებისთვის SHOW დაბრუნებული შედეგის მოხაზულობა მოულოდნელია" -#: fe-auth.c:1316 +#: fe-auth.c:1447 #, c-format msgid "\"password_encryption\" value too long" msgstr "\"password_encryption\"-ის მნიშვნელობა ძალიან გრძელია" -#: fe-auth.c:1366 +#: fe-auth.c:1497 #, c-format msgid "unrecognized password encryption algorithm \"%s\"" msgstr "პაროლის დაშიფვრის უცნობი ალგორითმი: \"%s\"" -#: fe-cancel.c:76 +#: fe-cancel.c:79 #, c-format msgid "connection pointer is NULL" msgstr "შეერთების მაჩვენებელი ნულოვანია" -#: fe-cancel.c:82 fe-misc.c:572 +#: fe-cancel.c:85 fe-misc.c:587 #, c-format msgid "connection not open" msgstr "შეერთება ღია არაა" -#: fe-cancel.c:193 +#: fe-cancel.c:92 +#, c-format +msgid "no cancellation key received" +msgstr "გაუქმების გასაღები არ მიმიღია" + +#: fe-cancel.c:211 #, c-format msgid "cancel request is already being sent on this connection" msgstr "ამ მიერთებით გაუქმების მოთხოვნის გაგზავნა უკვე მიმდინარეობს" -#: fe-cancel.c:263 +#: fe-cancel.c:281 #, c-format msgid "unexpected response from server" msgstr "მოულოდნელი პასუხი სერვერიდან" -#: fe-connect.c:1182 +#: fe-connect.c:1308 #, c-format msgid "could not match %d host names to %d hostaddr values" msgstr "%d ჰოსტის სახელები %d ჰოსტის მისამართების მნიშვნელობებს არ ემთხვევა" -#: fe-connect.c:1262 +#: fe-connect.c:1388 #, c-format msgid "could not match %d port numbers to %d hosts" msgstr "%d პორტის ნომრები %d ჰოსტს არ ემთხვევა" -#: fe-connect.c:1387 +#: fe-connect.c:1516 #, c-format msgid "negative require_auth method \"%s\" cannot be mixed with non-negative methods" msgstr "უარყოფითი require_auth მეთოდი \"%s\" არ შეიძლება სხვა არაუარყოფით მეთოდებს შეურიოთ" -#: fe-connect.c:1400 +#: fe-connect.c:1529 #, c-format msgid "require_auth method \"%s\" cannot be mixed with negative methods" msgstr "require_auth-ის მეთოდს \"%s\" უარყოფით მეთოდებს ვერ შეურევთ" -#: fe-connect.c:1460 fe-connect.c:1511 fe-connect.c:1553 fe-connect.c:1596 -#: fe-connect.c:1699 fe-connect.c:1745 fe-connect.c:1785 fe-connect.c:1806 +#: fe-connect.c:1605 fe-connect.c:1734 fe-connect.c:1776 fe-connect.c:1819 +#: fe-connect.c:1922 fe-connect.c:1968 fe-connect.c:2008 fe-connect.c:2079 +#: fe-connect.c:8250 #, c-format msgid "invalid %s value: \"%s\"" msgstr "%s-ის არასწორი მნიშვნელობა: \"%s\"" -#: fe-connect.c:1493 +#: fe-connect.c:1647 +#, c-format +msgid "internal error: no space in allowed_sasl_mechs" +msgstr "შიდა შეცდომა: 'allowed_sasl_merchs'-ში ჰარე არაა" + +#: fe-connect.c:1686 #, c-format msgid "require_auth method \"%s\" is specified more than once" msgstr "პარამეტრი \"%s\" ერთზე მეტჯერაა მითითებული" -#: fe-connect.c:1534 fe-connect.c:1573 fe-connect.c:1605 fe-connect.c:1707 +#: fe-connect.c:1757 fe-connect.c:1796 fe-connect.c:1828 fe-connect.c:1930 #, c-format msgid "%s value \"%s\" invalid when SSL support is not compiled in" msgstr "%s-ის მნიშვნელობა \"%s\" არასწორია, როცა SSL-ის მხარდაჭერა გამორთული იყო აგების დროს" -#: fe-connect.c:1625 +#: fe-connect.c:1848 #, c-format msgid "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")" msgstr "სუსტი sslmode \"%s\" არ შეიძლება გამოყენებული იქნას sslrootcert=system-თან ერთად (გამოიყენეთ \"require\", \"verify-ca\", ან \"verify-full\")" -#: fe-connect.c:1647 +#: fe-connect.c:1870 #, c-format msgid "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")" msgstr "სუსტი sslmode \"%s\" არ შეიძლება გამოყენებული იქნას sslrootcert=system-თან ერთად (გამოიყენეთ \"verify-full\")" -#: fe-connect.c:1660 fe-connect.c:1668 +#: fe-connect.c:1883 fe-connect.c:1891 #, c-format msgid "invalid \"%s\" value: \"%s\"" msgstr "\"%s\"-ის არასწორი მნიშვნელობა: \"%s\"" -#: fe-connect.c:1685 +#: fe-connect.c:1908 #, c-format msgid "invalid SSL protocol version range" msgstr "არასწორი SSL პროტოკოლის ვერსიის დიაპაზონი" -#: fe-connect.c:1722 +#: fe-connect.c:1945 #, c-format msgid "%s value \"%s\" is not supported (check OpenSSL version)" msgstr "%s-ის მნიშვნელობა \"%s\" მხარდაჭერილი არაა (შეამოწმეთ OpenSSL-ის ვერსია)" -#: fe-connect.c:1752 +#: fe-connect.c:1975 #, c-format msgid "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in" msgstr "gssencmode -ის მნიშვნელობა \"%s\" არასწორია. GSSAPI-ის მხარდაჭერა გამორთული იყო აგების დროს" -#: fe-connect.c:2045 +#: fe-connect.c:2029 +#, c-format +msgid "invalid SCRAM client key" +msgstr "არასწორი SCRAM კლიენტის გასაღები" + +#: fe-connect.c:2035 +#, c-format +msgid "invalid SCRAM client key length: %d" +msgstr "არასწორი SCRAM კლიენტის გასაღების სიგრძე: %d" + +#: fe-connect.c:2054 +#, c-format +msgid "invalid SCRAM server key" +msgstr "არასწორი SCRAM სერვერის გასაღები" + +#: fe-connect.c:2060 +#, c-format +msgid "invalid SCRAM server key length: %d" +msgstr "არასწორი SCRAM სერვერის გასაღების სიგრძე: %d" + +#: fe-connect.c:2148 +#, c-format +msgid "min_protocol_version is greater than max_protocol_version" +msgstr "min_protocol_version უფრო დიდია, ვიდრე max_protocol_version" + +#: fe-connect.c:2360 #, c-format msgid "could not set socket to TCP no delay mode: %s" msgstr "სოკეტის TCP no_delay რეჟიმის ჩართვის შეცდომა: %s" -#: fe-connect.c:2104 +#: fe-connect.c:2419 #, c-format msgid "connection to server on socket \"%s\" failed: " msgstr "სოკეტით (\"%s\")სერვერთან მიერთების შეცდომა: " -#: fe-connect.c:2130 +#: fe-connect.c:2445 #, c-format msgid "connection to server at \"%s\" (%s), port %s failed: " msgstr "სერვერის (\"%s\" (%s)) %s-ე პორტზე მიერთების შეცდომა: " -#: fe-connect.c:2135 +#: fe-connect.c:2450 #, c-format msgid "connection to server at \"%s\", port %s failed: " msgstr "სერვერის (\"%s\" ) %s-ე პორტზე მიერთების შეცდომა: " -#: fe-connect.c:2158 +#: fe-connect.c:2473 #, c-format msgid "\tIs the server running locally and accepting connections on that socket?" msgstr "\tარს სერვერი ლოკალურად გაშვებული და მზადაა სოკეტითა დასაკავშირებლად?" -#: fe-connect.c:2160 +#: fe-connect.c:2475 #, c-format msgid "\tIs the server running on that host and accepting TCP/IP connections?" msgstr "\tარის სერვერი გაშვებული ამ ჰოსტზე და ეთანხმება TCP/IP შეერთებებს?" -#: fe-connect.c:2206 fe-connect.c:2240 fe-connect.c:2275 fe-connect.c:2373 -#: fe-connect.c:3098 +#: fe-connect.c:2521 fe-connect.c:2555 fe-connect.c:2590 fe-connect.c:2688 +#: fe-connect.c:3414 #, c-format msgid "%s(%s) failed: %s" msgstr "%s(%s) -ის შეცდომა: %s" -#: fe-connect.c:2339 +#: fe-connect.c:2654 #, c-format msgid "%s(%s) failed: error code %d" msgstr "%s(%s) -ის შეცდომა: შეცდომის კოდი %d" -#: fe-connect.c:2650 +#: fe-connect.c:2966 #, c-format msgid "invalid connection state, probably indicative of memory corruption" msgstr "შეერთების არასწორი მდგომარეობა. დიდი შანსით ნიშნავს მეხსიერების დაზიანებას" -#: fe-connect.c:2733 +#: fe-connect.c:3049 #, c-format msgid "invalid port number: \"%s\"" msgstr "პორტის არასწორი ნომერი: \"%s\"" -#: fe-connect.c:2747 +#: fe-connect.c:3063 #, c-format msgid "could not translate host name \"%s\" to address: %s" msgstr "ჰოსტის სახელის (%s) მისამართში თარგმნის შეცდომა: %s" -#: fe-connect.c:2759 +#: fe-connect.c:3075 #, c-format msgid "could not parse network address \"%s\": %s" msgstr "ქსელური მისამართის (\"%s\") დამუშავების პრობლემა: %s" -#: fe-connect.c:2770 +#: fe-connect.c:3086 #, c-format msgid "Unix-domain socket path \"%s\" is too long (maximum %d bytes)" msgstr "Unix-დომენის სოკეტის მისამართი \"%s\" ძალიან გრძელია (დასაშვებია %d ბაიტი)" -#: fe-connect.c:2784 +#: fe-connect.c:3100 #, c-format msgid "could not translate Unix-domain socket path \"%s\" to address: %s" msgstr "unix-დომენის სოკეტის ბილიკის (\"%s\") მისამართად თარგმნის შეცდომა: %s" -#: fe-connect.c:2950 fe-connect.c:4302 +#: fe-connect.c:3266 fe-connect.c:4713 #, c-format msgid "GSSAPI encryption required but it is not supported over a local socket" msgstr "GSSAPI დაშიფვრა მოთხოვნილია, მაგრამ შეუძლებელია ლოკალური სოკეტის გამოყენებით" -#: fe-connect.c:2958 fe-connect.c:4431 +#: fe-connect.c:3274 fe-connect.c:4842 #, c-format msgid "GSSAPI encryption required but no credential cache" msgstr "GSSAPI დაშიფვრა მოთხოვნილია, მაგრამ ავტორიზაციის დეტალების კეში არ არსებობს" -#: fe-connect.c:3026 +#: fe-connect.c:3342 #, c-format msgid "could not create socket: %s" msgstr "სოკეტის შექმნის შეცდომა: %s" -#: fe-connect.c:3057 +#: fe-connect.c:3373 #, c-format msgid "could not set socket to nonblocking mode: %s" msgstr "სოკეტის არაბლოკირებული რეჟიმის დაყენების შეცდომა: %s" -#: fe-connect.c:3068 +#: fe-connect.c:3384 #, c-format msgid "could not set socket to close-on-exec mode: %s" msgstr "სოკეტის დახურვა-შესრულებისას რეჟიმის დაყენების შეცდომა: %s" -#: fe-connect.c:3086 -#, c-format -msgid "keepalives parameter must be an integer" -msgstr "პარამეტრი keepalives მთელი რიცხვი უნდა იყოს" - -#: fe-connect.c:3225 +#: fe-connect.c:3541 #, c-format msgid "could not get socket error status: %s" msgstr "სოკეტის შეცდომის სტატუსის მიღების შეცდომა: %s" -#: fe-connect.c:3252 +#: fe-connect.c:3568 #, c-format msgid "could not get client address from socket: %s" msgstr "კლიენტის მისამართის სოკეტიდან მიღების შეცდომა: %s" -#: fe-connect.c:3278 +#: fe-connect.c:3594 #, c-format msgid "requirepeer parameter is not supported on this platform" msgstr "პარამეტრი requirepeer ამ პლატფორმაზე მხარდაჭერილი არაა" -#: fe-connect.c:3280 +#: fe-connect.c:3596 #, c-format msgid "could not get peer credentials: %s" msgstr "პარტნიორის ავტორიზაციის დეტალების მიღების შეცდომა: %s" -#: fe-connect.c:3293 +#: fe-connect.c:3609 #, c-format msgid "requirepeer specifies \"%s\", but actual peer user name is \"%s\"" msgstr "requrepeer-ის მნიშვნელობაა \"%s\", მაგრამ პარტნიორის მომხმარებლის ნამდვილი ასხელია: \"%s\"" -#: fe-connect.c:3331 +#: fe-connect.c:3647 #, c-format msgid "could not send GSSAPI negotiation packet: %s" msgstr "შეცდომა GSSAPI-ის მიმოცვლის პაკეტის გაგზავნისას: %s" -#: fe-connect.c:3380 +#: fe-connect.c:3686 #, c-format msgid "could not send SSL negotiation packet: %s" msgstr "შეცდომა SSL მიმოცვლის პაკეტის გაგზავნისას: %s" -#: fe-connect.c:3412 +#: fe-connect.c:3712 #, c-format msgid "could not send cancel packet: %s" msgstr "გაუქმების პაკეტის გაგზავნა შეუძლებელია: %s" -#: fe-connect.c:3442 +#: fe-connect.c:3742 #, c-format msgid "could not send startup packet: %s" msgstr "გაშვების პაკეტის გაგზავნის შეცდომა: %s" -#: fe-connect.c:3509 +#: fe-connect.c:3815 msgid "server does not support SSL, but SSL was required" msgstr "სერვერს SSL-ის მხარდაჭერა არ გააჩნია, მაგრამ SSL-ი აუცილებელია" -#: fe-connect.c:3528 +#: fe-connect.c:3825 +#, c-format +msgid "server sent an error response during SSL exchange" +msgstr "სერვერმა გამოაგზავნა შეცდომის შემცველი პასუხი SSL მიმოცვლის დროს" + +#: fe-connect.c:3830 #, c-format msgid "received invalid response to SSL negotiation: %c" msgstr "არასწორი პასუხი SSL მიმოცვლისას: %c" -#: fe-connect.c:3556 +#: fe-connect.c:3850 #, c-format msgid "received unencrypted data after SSL response" msgstr "'SSL' პასუხის შემდეგ მიღებული მონაცემები დაუშიფრავია" -#: fe-connect.c:3630 +#: fe-connect.c:3913 +#, c-format +msgid "server sent an error response during GSS encryption exchange" +msgstr "სერვერმა გამოაგზავნა შეცდომის შემცველი პასუხი GSS დაშიფვრის მიმოცვლის დროს" + +#: fe-connect.c:3931 msgid "server doesn't support GSSAPI encryption, but it was required" msgstr "სერვერს GSSAPI დაშიფვრის მხარდაჭერა არ გააჩნა, მაგრამ ის მოთხოვილია" -#: fe-connect.c:3634 +#: fe-connect.c:3935 #, c-format msgid "received invalid response to GSSAPI negotiation: %c" msgstr "'GSSAPI' მიმოცვლის არასწორი პასუხი: %c" -#: fe-connect.c:3652 +#: fe-connect.c:3957 #, c-format msgid "received unencrypted data after GSSAPI encryption response" msgstr "'GSSAPI' პასუხის შემდეგ მიღებული მონაცემები დაუშიფრავია" -#: fe-connect.c:3708 +#: fe-connect.c:4018 #, c-format msgid "expected authentication request from server, but received %c" msgstr "სერვერიდან მოსალოდნელი იყო ავთენტიკაციის მოთხოვნა, მაგრამ მიღებულია %c" -#: fe-connect.c:3736 fe-connect.c:3859 +#: fe-connect.c:4046 fe-connect.c:4178 #, c-format msgid "received invalid authentication request" msgstr "დუბლირებული GSS ავთენტიკაციის მოთხოვნა" -#: fe-connect.c:3742 fe-connect.c:3844 +#: fe-connect.c:4052 #, c-format msgid "received invalid protocol negotiation message" msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება" -#: fe-connect.c:3761 fe-connect.c:3815 +#: fe-connect.c:4071 fe-connect.c:4125 #, c-format msgid "received invalid error message" msgstr "მიღებულია არასწორი შეცდომის შეტყობინება" -#: fe-connect.c:3930 +#: fe-connect.c:4155 +#, c-format +msgid "received duplicate protocol negotiation message" +msgstr "მიღებულია გამეორებული პროტოკოლის მიმოცვლის შეტყობინება" + +#: fe-connect.c:4257 +#, c-format +msgid "internal error: async authentication has no handler" +msgstr "შიდა შეცდომა: ასინქრონულ ავთენტიკატორს დამმუშავებელი არ აქვს" + +#: fe-connect.c:4282 +#, c-format +msgid "internal error: async cleanup did not release polling socket" +msgstr "შიდა შეცდომა: ასინქრონულმა მოსუფთავებამ სოკეტი არ გაათავისუფლა" + +#: fe-connect.c:4305 +#, c-format +msgid "internal error: async authentication did not set a socket for polling" +msgstr "შიდა შეცდომა: ასინქრონულმა ავთენტიკაციამ პოლინგისთვის სოკეტი არ დააყენა" + +#: fe-connect.c:4338 #, c-format msgid "unexpected message from server during startup" msgstr "სერვერის გაშვებისას მიღებულია მოულოდნელი შეტყობინება" -#: fe-connect.c:4021 +#: fe-connect.c:4429 #, c-format msgid "session is read-only" msgstr "სესია მხოლოდ კითხვადია" -#: fe-connect.c:4023 +#: fe-connect.c:4431 #, c-format msgid "session is not read-only" msgstr "სესია მხოლოდ კითხვადი არა" -#: fe-connect.c:4076 +#: fe-connect.c:4484 #, c-format msgid "server is in hot standby mode" msgstr "სერვერი მზა-უქმე რეჟიმშია" -#: fe-connect.c:4078 +#: fe-connect.c:4486 #, c-format msgid "server is not in hot standby mode" msgstr "სერვერი მზა-უქმე რეჟიმში არაა" -#: fe-connect.c:4200 fe-connect.c:4250 +#: fe-connect.c:4611 fe-connect.c:4661 #, c-format msgid "\"%s\" failed" msgstr "\"%s\"-ის შეცდომა" -#: fe-connect.c:4264 +#: fe-connect.c:4675 #, c-format msgid "invalid connection state %d, probably indicative of memory corruption" msgstr "შეერთების არასწორი მდგომარეობა (%d). დიდი შანსით ნიშნავს მეხსიერების დაზიანებას" -#: fe-connect.c:5083 +#: fe-connect.c:5504 #, c-format msgid "invalid LDAP URL \"%s\": scheme must be ldap://" msgstr "'LDAP'-ის არასწორი URL: \"%s\": სქემა ldap:// უნდა იყოს" -#: fe-connect.c:5098 +#: fe-connect.c:5519 #, c-format msgid "invalid LDAP URL \"%s\": missing distinguished name" msgstr "'LDAP'-ის არასწორი URL: \"%s\": აკლია გამოყოფილი სახელი" -#: fe-connect.c:5110 fe-connect.c:5168 +#: fe-connect.c:5531 fe-connect.c:5589 #, c-format msgid "invalid LDAP URL \"%s\": must have exactly one attribute" msgstr "'LDAP'-ის არასწორი URL \"%s\": ზუსტად ერთი ატრიბუტი უნდა ჰქონდეს" -#: fe-connect.c:5122 fe-connect.c:5184 +#: fe-connect.c:5543 fe-connect.c:5605 #, c-format msgid "invalid LDAP URL \"%s\": must have search scope (base/one/sub)" msgstr "'LDAP'-ის არასწორი URL: \"%s\": საჭიროა ძებნის ფარგლების ქონა (საბაზისო/ერთი/ქვე)" -#: fe-connect.c:5134 +#: fe-connect.c:5555 #, c-format msgid "invalid LDAP URL \"%s\": no filter" msgstr "'LDAP'-ის არასწორი URL: \"%s\":ფილტრი არ არსებობს" -#: fe-connect.c:5156 +#: fe-connect.c:5577 #, c-format msgid "invalid LDAP URL \"%s\": invalid port number" msgstr "'LDAP'-ის არასწორი URL: \"%s\": პორტის არასწორი ნომერი" -#: fe-connect.c:5193 +#: fe-connect.c:5614 #, c-format msgid "could not create LDAP structure" msgstr "შეცდომა LDAP-ის სტრუქტურის შექმნისას" -#: fe-connect.c:5268 +#: fe-connect.c:5689 #, c-format msgid "lookup on LDAP server failed: %s" msgstr "'LDAP' სერვერის მოძებნის შეცდომა: %s" -#: fe-connect.c:5278 +#: fe-connect.c:5699 #, c-format msgid "more than one entry found on LDAP lookup" msgstr "ძებნისას (LDAP) ნაპოვნია ერთზე მეტი ჩანაწერი" -#: fe-connect.c:5280 fe-connect.c:5291 +#: fe-connect.c:5701 fe-connect.c:5712 #, c-format msgid "no entry found on LDAP lookup" msgstr "ძებნისას (LDAP) ჩანაწერები ნაპოვნი არაა" -#: fe-connect.c:5301 fe-connect.c:5313 +#: fe-connect.c:5722 fe-connect.c:5734 #, c-format msgid "attribute has no values on LDAP lookup" msgstr "'LDAP' ძებნის ატრიბუტს მნიშვნელობა არ გააჩნია" -#: fe-connect.c:5364 fe-connect.c:5383 fe-connect.c:5907 +#: fe-connect.c:5785 fe-connect.c:5804 fe-connect.c:6328 #, c-format msgid "missing \"=\" after \"%s\" in connection info string" msgstr "შეერთების სტრიქონში \"%s\"-ის შემდეგ \"=\" აკლია" -#: fe-connect.c:5454 fe-connect.c:6090 fe-connect.c:6888 +#: fe-connect.c:5875 fe-connect.c:6511 fe-connect.c:7341 #, c-format msgid "invalid connection option \"%s\"" msgstr "შეერთების არასწორი პარამეტრი: \"%s\"" -#: fe-connect.c:5469 fe-connect.c:5955 +#: fe-connect.c:5890 fe-connect.c:6376 #, c-format msgid "unterminated quoted string in connection info string" msgstr "შეერთების ინფორმაციის სტრიქონში ბრჭყალებში ჩასმული სტრიქონი დაუსრულებელია" -#: fe-connect.c:5549 +#: fe-connect.c:5970 #, c-format msgid "definition of service \"%s\" not found" msgstr "სერვისის აღწერა არ არსებობს: \"%s\"" -#: fe-connect.c:5575 +#: fe-connect.c:5996 #, c-format msgid "service file \"%s\" not found" msgstr "სერვისის ფაილი არ არსებობს: \"%s\"" -#: fe-connect.c:5588 +#: fe-connect.c:6009 #, c-format msgid "line %d too long in service file \"%s\"" msgstr "ძალიან გრძელი ხაზი (%d) სერვისის ფაილში \"%s\"" -#: fe-connect.c:5659 fe-connect.c:5702 +#: fe-connect.c:6080 fe-connect.c:6123 #, c-format msgid "syntax error in service file \"%s\", line %d" msgstr "სინტაქსის შეცდომა სერვისის ფაილში \"%s\" ხაზზე %d" -#: fe-connect.c:5670 +#: fe-connect.c:6091 #, c-format msgid "nested service specifications not supported in service file \"%s\", line %d" msgstr "სერვისის ფაილში \"%s\" ჩადგმული სერვისის მითითება მხარდაუჭერელია. ხაზი %d" -#: fe-connect.c:6409 +#: fe-connect.c:6830 #, c-format msgid "invalid URI propagated to internal parser routine: \"%s\"" msgstr "დამუშავებს შიდა ფუნქციაში გადაცემული URI არასწორია: %s" -#: fe-connect.c:6486 +#: fe-connect.c:6907 #, c-format msgid "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"" msgstr "სტრიქონის დასასრული \"]\"-ს IPv6 ჰოსტის მისამართში URI-ში ძებნისას: \"%s\"" -#: fe-connect.c:6493 +#: fe-connect.c:6914 #, c-format msgid "IPv6 host address may not be empty in URI: \"%s\"" msgstr "ჰოსტის IPv6 მისამართი URI-ში ცარიელი ვერ იქნება: \"%s\"" -#: fe-connect.c:6508 +#: fe-connect.c:6929 #, c-format msgid "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"" msgstr "უცნობი სიმბოლო (\"%c\") URI-ში პოზიციაზე %d (მოველოდი \":\"-ს ან \"/\"-ს): \"%s\"" -#: fe-connect.c:6637 +#: fe-connect.c:7058 #, c-format msgid "extra key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "მოთხოვნის URI არამეტრში მითითებულია გასაღები/მნიშვნელობის ზედმეტი \"=\": \"%s\"" -#: fe-connect.c:6657 +#: fe-connect.c:7078 #, c-format msgid "missing key/value separator \"=\" in URI query parameter: \"%s\"" msgstr "მოთხოვნის URI პარამეტრში მითითებულია გასაღები/მნიშვნელობის წყვილს \"=\" აკლია: \"%s\"" -#: fe-connect.c:6709 +#: fe-connect.c:7130 #, c-format msgid "invalid URI query parameter: \"%s\"" msgstr "მოთხოვნის არასწორი პარამეტრი: \"%s\"" -#: fe-connect.c:6783 +#: fe-connect.c:7214 #, c-format msgid "invalid percent-encoded token: \"%s\"" msgstr "არასწორი პროცენტულად-კოდირებული კოდი: \"%s\"" -#: fe-connect.c:6793 +#: fe-connect.c:7224 #, c-format msgid "forbidden value %%00 in percent-encoded value: \"%s\"" msgstr "პროცენტში კოდირებული მნიშვნელობის აკრძალული მნიშვნელობა %%00: \"%s\"" -#: fe-connect.c:7157 +#: fe-connect.c:7246 +#, c-format +msgid "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead" +msgstr "\"%s\"-ში აღმოჩენილია მოულოდნელი ჰარეები. მათ მაგიერ გამოიყენეთ პროცენტით კოდირებული (%%20)" + +#: fe-connect.c:7628 msgid "connection pointer is NULL\n" msgstr "შეერთების მაჩვენებელი ნულოვანია\n" -#: fe-connect.c:7165 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 -#: fe-protocol3.c:991 fe-protocol3.c:1024 +#: fe-connect.c:7636 fe-exec.c:713 fe-exec.c:975 fe-exec.c:3459 +#: fe-protocol3.c:987 fe-protocol3.c:1020 msgid "out of memory\n" msgstr "არასაკმარისი მეხსიერება\n" -#: fe-connect.c:7456 +#: fe-connect.c:7938 #, c-format msgid "WARNING: password file \"%s\" is not a plain file\n" msgstr "გაფრთხილება. პაროლის ფაილი \"%s\" უბრალოდ ფაილს არ წარმოადგენს\n" -#: fe-connect.c:7465 +#: fe-connect.c:7948 #, c-format msgid "WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n" msgstr "გაფრთხილება: პაროლების ფაილს \"%s\" ჯგუფზე ან დანარჩენ ყველაზე წვდომა გააჩნია. წვდომა 0600 ან ნაკლები უნდა იყოს\n" -#: fe-connect.c:7572 +#: fe-connect.c:8052 #, c-format msgid "password retrieved from file \"%s\"" msgstr "პაროლი მიღებულია ფაილიდან \"%s\"" -#: fe-connect.c:7724 +#: fe-connect.c:8218 #, c-format msgid "invalid integer value \"%s\" for connection option \"%s\"" msgstr "არასწორი მნიშვნელობა: \"%s\" (უნდა იყოს მთელი რიცხვი) შეერთების პარამეტრისთვის \"%s\"" @@ -822,7 +1184,7 @@ msgstr "არასწორი მნიშვნელობა: \"%s\" (უ msgid "row number %d is out of range 0..%d" msgstr "მწკრივების რაოდენობა %d ზღვარს (0..%d) გარეთაა" -#: fe-exec.c:531 fe-protocol3.c:1993 +#: fe-exec.c:531 fe-protocol3.c:2067 #, c-format msgid "%s" msgstr "%s" @@ -913,7 +1275,7 @@ msgstr "COPY BOTH-ის დროს PQexec დაუშვებელია" msgid "unrecognized message type \"%c\"" msgstr "შეტყობინების უცნობი ტიპი: \"%c\"" -#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1924 +#: fe-exec.c:2702 fe-exec.c:2756 fe-exec.c:2824 fe-protocol3.c:1998 #, c-format msgid "no COPY in progress" msgstr "ბრძანება COPY გაშვებული არაა" @@ -971,11 +1333,16 @@ msgstr "პარამეტრების რაოდენობა %d ზ msgid "could not interpret result from server: %s" msgstr "სერვერის პასუხის გაურკვეველია: %s" -#: fe-exec.c:4127 fe-exec.c:4217 +#: fe-exec.c:4140 fe-exec.c:4253 #, c-format msgid "incomplete multibyte character" msgstr "დაუსრულებელი მრავალბაიტიანი სიმბოლო" +#: fe-exec.c:4142 fe-exec.c:4272 +#, c-format +msgid "invalid multibyte character" +msgstr "არასწორი მრავალბაიტიანი სიმბოლო" + #: fe-gssapi-common.c:122 msgid "GSSAPI name import error" msgstr "GSSAPI-ის სახელის შემოტანის შეცდომა" @@ -1032,8 +1399,8 @@ msgstr "%lu-ის მთელი რიცხვის ზომა მხა msgid "integer of size %lu not supported by pqPutInt" msgstr "%lu-ის მთელი რიცხვის ზომა მხარდაუჭერელია pqPutInt-is მიერ" -#: fe-misc.c:750 fe-secure-openssl.c:203 fe-secure-openssl.c:309 -#: fe-secure.c:237 fe-secure.c:404 +#: fe-misc.c:765 fe-secure-openssl.c:181 fe-secure-openssl.c:287 +#: fe-secure.c:222 fe-secure.c:389 #, c-format msgid "" "server closed the connection unexpectedly\n" @@ -1044,172 +1411,200 @@ msgstr "" "\tეს დიდი ალბათობით ნიშნავს, რომ სერვერის პროცესი \n" "\tმოულოდნელად, მოთხოვნამდე ან მოთხოვნის შესრულებსას დასრულდა." -#: fe-misc.c:817 +#: fe-misc.c:832 msgid "connection not open\n" msgstr "შეერთება ღია არაა\n" -#: fe-misc.c:1005 +#: fe-misc.c:1020 #, c-format msgid "timeout expired" msgstr "მოლოდინის დრო გავიდა" -#: fe-misc.c:1049 +#: fe-misc.c:1072 #, c-format msgid "invalid socket" msgstr "არასწორი სოკეტი" -#: fe-misc.c:1071 +#: fe-misc.c:1095 #, c-format msgid "%s() failed: %s" msgstr "%s()-ის შეცდომა: %s" -#: fe-protocol3.c:187 +#: fe-protocol3.c:188 #, c-format msgid "message type 0x%02x arrived from server while idle" msgstr "შეტყობინების ტიპი 0x%02x მოვიდა სერვერიდან, როცა უქმე ვიყავი" -#: fe-protocol3.c:402 +#: fe-protocol3.c:401 #, c-format msgid "server sent data (\"D\" message) without prior row description (\"T\" message)" msgstr "სერვერმა მონაცემები (\"D\" შეტყობინება) მწკრივების წინასწარი აღწერის (\"T\" შეტყობინება) გარეშე გამოაგზავნა" -#: fe-protocol3.c:444 +#: fe-protocol3.c:443 #, c-format msgid "unexpected response from server; first received character was \"%c\"" msgstr "სერვერის მოულოდნელი პასუხი; პირველი მიღებული სიმბოლოა \"%c\"" -#: fe-protocol3.c:467 +#: fe-protocol3.c:462 #, c-format msgid "message contents do not agree with length in message type \"%c\"" msgstr "შეტყობინების შიგთავსი შეტყობინების ამ ტიპის (%c) სიგრძეს არ ემთხვევა" -#: fe-protocol3.c:485 +#: fe-protocol3.c:480 #, c-format msgid "lost synchronization with server: got message type \"%c\", length %d" msgstr "სერვერთან სინქრონიზაციის შეცდომა: შეტყობინების ტიპი: \"%c\", სიგრძე %d" -#: fe-protocol3.c:537 fe-protocol3.c:577 +#: fe-protocol3.c:532 fe-protocol3.c:572 msgid "insufficient data in \"T\" message" msgstr "არასაკმარისი მონაცემები \"T\" შეტყობინებაში" -#: fe-protocol3.c:648 fe-protocol3.c:854 +#: fe-protocol3.c:643 fe-protocol3.c:849 msgid "out of memory for query result" msgstr "არასაკმარისი მეხსიერება მოთხოვნის შედეგისთვის" -#: fe-protocol3.c:717 +#: fe-protocol3.c:712 msgid "insufficient data in \"t\" message" msgstr "არასაკმარისი მონაცემები \"t\" შეტყობინებაში" -#: fe-protocol3.c:776 fe-protocol3.c:808 fe-protocol3.c:826 +#: fe-protocol3.c:771 fe-protocol3.c:803 fe-protocol3.c:821 msgid "insufficient data in \"D\" message" msgstr "არასაკმარისი მონაცემები \"D\" შეტყობინებაში" -#: fe-protocol3.c:782 +#: fe-protocol3.c:777 msgid "unexpected field count in \"D\" message" msgstr "ველების მოულოდნელი რაოდენობა \"D\" შეტყობინებაში" -#: fe-protocol3.c:1037 +#: fe-protocol3.c:1033 msgid "no error message available\n" msgstr "შეცდომის შეტყობინების გარეშე\n" #. translator: %s represents a digit string -#: fe-protocol3.c:1085 fe-protocol3.c:1104 +#: fe-protocol3.c:1081 fe-protocol3.c:1100 #, c-format msgid " at character %s" msgstr " სიმბოლოსთან %s" -#: fe-protocol3.c:1117 +#: fe-protocol3.c:1113 #, c-format msgid "DETAIL: %s\n" msgstr "დეტალი: %s\n" -#: fe-protocol3.c:1120 +#: fe-protocol3.c:1116 #, c-format msgid "HINT: %s\n" msgstr "მინიშნება: %s\n" -#: fe-protocol3.c:1123 +#: fe-protocol3.c:1119 #, c-format msgid "QUERY: %s\n" msgstr "მოთხოვნა: %s\n" -#: fe-protocol3.c:1130 +#: fe-protocol3.c:1126 #, c-format msgid "CONTEXT: %s\n" msgstr "კონტექსტი: %s\n" -#: fe-protocol3.c:1139 +#: fe-protocol3.c:1135 #, c-format msgid "SCHEMA NAME: %s\n" msgstr "სქემის სახელი: %s\n" -#: fe-protocol3.c:1143 +#: fe-protocol3.c:1139 #, c-format msgid "TABLE NAME: %s\n" msgstr "ცხრილის სახელი: %s\n" -#: fe-protocol3.c:1147 +#: fe-protocol3.c:1143 #, c-format msgid "COLUMN NAME: %s\n" msgstr "სვეტის სახელი: %s\n" -#: fe-protocol3.c:1151 +#: fe-protocol3.c:1147 #, c-format msgid "DATATYPE NAME: %s\n" msgstr "მონ. ტიპის სახელი: %s\n" -#: fe-protocol3.c:1155 +#: fe-protocol3.c:1151 #, c-format msgid "CONSTRAINT NAME: %s\n" msgstr "შეზღუდვის სახელი: %s\n" -#: fe-protocol3.c:1167 +#: fe-protocol3.c:1163 msgid "LOCATION: " msgstr "მდებარეობა: " -#: fe-protocol3.c:1169 +#: fe-protocol3.c:1165 #, c-format msgid "%s, " msgstr "%s, " -#: fe-protocol3.c:1171 +#: fe-protocol3.c:1167 #, c-format msgid "%s:%s" msgstr "%s:%s" -#: fe-protocol3.c:1366 +#: fe-protocol3.c:1362 #, c-format msgid "LINE %d: " msgstr "ხაზი %d: " -#: fe-protocol3.c:1440 +#: fe-protocol3.c:1424 #, c-format -msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" -msgstr "პროტოკოლის ვერსია სერვერის მიერ მხარდაჭერილი არაა: კლიენტი იყენებს %u.%u, სერვერის მხარდაჭერილი ვერსიის მაქსიმუმია %u.%u" +msgid "received invalid protocol negotiation message: server requested downgrade to a higher-numbered version" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება: სერვერმა მოითხოვა ვერსიის ჩამოწევა უფრო მაღალ ვერსიაზე" -#: fe-protocol3.c:1446 +#: fe-protocol3.c:1430 #, c-format -msgid "protocol extension not supported by server: %s" -msgid_plural "protocol extensions not supported by server: %s" -msgstr[0] "პროტოკოლის გაფართოება სერვერის მიერ მხარდაჭერილი არაა: %s" -msgstr[1] "პროტოკოლის გაფართოებები სერვერის მიერ მხარდაჭერილი არაა: %s" +msgid "received invalid protocol negotiation message: server requested downgrade to pre-3.0 protocol version" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება: სერვერმა მოითხოვა ვერსიის ჩამოწევა 3.0-მდელ ვერსიაზე" -#: fe-protocol3.c:1454 +#: fe-protocol3.c:1437 #, c-format -msgid "invalid %s message" -msgstr "არასწორი %s შეტყობინება" +msgid "received invalid protocol negotiation message: server requests downgrade to non-existent 3.1 protocol version" +msgstr "მიღებულია არასწორი პროტოკოლის ხელის ჩამორთმევის შეტყობინება: სერვერი ითხოვს ვერსიის ჩამოწევას არარსებულ პროტოკოლის ვერსიაზე 3.1" -#: fe-protocol3.c:1819 +#: fe-protocol3.c:1443 +#, c-format +msgid "received invalid protocol negotiation message: server reported negative number of unsupported parameters" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება: სერვერმა მხარდაუჭერელი პარამეტრების უარყოფითი რაოდენობა გადმოგვცა" + +#: fe-protocol3.c:1449 +#, c-format +msgid "received invalid protocol negotiation message: server negotiated but asks for no changes" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება: სერვერთან კავშირი დამყარდა, მაგრამ ის ცვლილებებს არ ითხოვს" + +#: fe-protocol3.c:1455 +#, c-format +msgid "server only supports protocol version %d.%d, but min_protocol_version was set to %d.%d" +msgstr "სერვერს, მხოლოდ, %d.%d ვერსიის პროტოკოლის მხარდაჭერა აქვს, მაგრამ min_protocol-ის მნიშვნელობაა %d.%d" + +#: fe-protocol3.c:1479 +#, c-format +msgid "received invalid protocol negotiation message: server reported unsupported parameter name without a _pq_. prefix (\"%s\")" +msgstr "მიღებულია არასწორი პროტოკოლის მოლაპარაკების შეტყობინება: სერვერმა მოიწერა მხარდაუჭერელი პარამეტრის სახელი _pq_. პრეფიქსის გარეშე (\"%s\")" + +#: fe-protocol3.c:1482 +#, c-format +msgid "received invalid protocol negotiation message: server reported an unsupported parameter that was not requested (\"%s\")" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება: სერვერმა მოიწერა მხარდაუჭერელი პარამეტრი, რომელიც მას არ მოუთხოვია (\"%s\")" + +#: fe-protocol3.c:1489 +#, c-format +msgid "received invalid protocol negotiation message: message too short" +msgstr "მიღებულია არასწორი პროტოკოლის მიმოცვლის შეტყობინება; შეტყობინება მეტისმეტად მოკლეა" + +#: fe-protocol3.c:1893 #, c-format msgid "PQgetline: not doing text COPY OUT" msgstr "PQgetline: ტექსტის COPY OUT-ს არ გავაკეთებ" -#: fe-protocol3.c:2193 +#: fe-protocol3.c:2268 #, c-format msgid "protocol error: no function result" msgstr "პროტოკოლის შეცდომა: ფუნქციის შედეგის გარეშე" -#: fe-protocol3.c:2204 +#: fe-protocol3.c:2280 #, c-format msgid "protocol error: id=0x%x" msgstr "პროტოკოლის შეცდომა: id=0x%x" @@ -1291,92 +1686,102 @@ msgstr "GSSAPI-ის ზომის შემოწმების შეც msgid "GSSAPI context establishment error" msgstr "GSSAPI-ის კონტექსტის დამყარებულობის შეცდომა" -#: fe-secure-openssl.c:207 fe-secure-openssl.c:313 fe-secure-openssl.c:1524 +#: fe-secure-openssl.c:185 fe-secure-openssl.c:291 fe-secure-openssl.c:1378 #, c-format msgid "SSL SYSCALL error: %s" msgstr "SSL SYSCALL-ის შეცდომა: %s" -#: fe-secure-openssl.c:213 fe-secure-openssl.c:319 fe-secure-openssl.c:1527 +#: fe-secure-openssl.c:191 fe-secure-openssl.c:297 fe-secure-openssl.c:1381 #, c-format msgid "SSL SYSCALL error: EOF detected" msgstr "SSL SYSCALL -ის შეცდომა: ნაპოვნია EOF" -#: fe-secure-openssl.c:223 fe-secure-openssl.c:329 fe-secure-openssl.c:1535 +#: fe-secure-openssl.c:201 fe-secure-openssl.c:307 fe-secure-openssl.c:1389 #, c-format msgid "SSL error: %s" msgstr "SSL-ის შეცდომა: %s" -#: fe-secure-openssl.c:237 fe-secure-openssl.c:343 +#: fe-secure-openssl.c:215 fe-secure-openssl.c:321 #, c-format msgid "SSL connection has been closed unexpectedly" msgstr "SSL შეერთება მოულოდნელად დაიხურა" -#: fe-secure-openssl.c:242 fe-secure-openssl.c:348 fe-secure-openssl.c:1582 +#: fe-secure-openssl.c:220 fe-secure-openssl.c:326 fe-secure-openssl.c:1436 #, c-format msgid "unrecognized SSL error code: %d" msgstr "უცნობი SSL-ის შეცდომის კოდი: %d" -#: fe-secure-openssl.c:390 +#: fe-secure-openssl.c:368 #, c-format msgid "could not determine server certificate signature algorithm" msgstr "სერვერის სერტიფიკატის ხელმოწერის ალგორითმის დადგენა შეუძლებელია" -#: fe-secure-openssl.c:410 +#: fe-secure-openssl.c:388 #, c-format msgid "could not find digest for NID %s" msgstr "'NID'-ისთვის (%s) დაიჯესტის პოვნა შეუძლებელია" -#: fe-secure-openssl.c:419 +#: fe-secure-openssl.c:397 #, c-format msgid "could not generate peer certificate hash" msgstr "პარტნიორის სერტიფიკატის ჰეშის გენერირების შეცდომა" -#: fe-secure-openssl.c:501 +#: fe-secure-openssl.c:479 #, c-format msgid "SSL certificate's name entry is missing" msgstr "SSL სერტიფიკატის სახელის ჩანაწერი არ არსებობს" -#: fe-secure-openssl.c:535 +#: fe-secure-openssl.c:509 #, c-format msgid "SSL certificate's address entry is missing" msgstr "SSL სერტიფიკატის მისამართის ჩანაწერი არ არსებობს" -#: fe-secure-openssl.c:935 +#: fe-secure-openssl.c:714 +#, c-format +msgid "could not open ssl keylog file \"%s\": %s" +msgstr "ვერ გავხსენი sslkeylogfile \"%s\": %s" + +#: fe-secure-openssl.c:722 +#, c-format +msgid "could not write to ssl keylog file \"%s\": %s" +msgstr "sslkeylogfile \"%s\"-ში ჩაწერის შეცდომა: %s" + +#: fe-secure-openssl.c:775 #, c-format msgid "could not create SSL context: %s" msgstr "შეცდომა SSL კონტექსტის შექმნისას: %s" -#: fe-secure-openssl.c:977 +#: fe-secure-openssl.c:817 #, c-format msgid "invalid value \"%s\" for minimum SSL protocol version" msgstr "'SSL' პროტოკოლის ვერსიის არასწორი მინიმალური მნიშვნელობა: %s" -#: fe-secure-openssl.c:987 +#: fe-secure-openssl.c:827 #, c-format msgid "could not set minimum SSL protocol version: %s" msgstr "'SSL' პროტოკოლის ვერსიის მინიმალური მნიშვნელობის დაყენების შეცდომა: %s" -#: fe-secure-openssl.c:1003 +#: fe-secure-openssl.c:843 #, c-format msgid "invalid value \"%s\" for maximum SSL protocol version" msgstr "'SSL' პროტოკოლის ვერსიის არასწორი მაქსიმალური მნიშვნელობა: %s" -#: fe-secure-openssl.c:1013 +#: fe-secure-openssl.c:853 #, c-format msgid "could not set maximum SSL protocol version: %s" msgstr "'SSL' პროტოკოლის ვერსიის მაქსიმალური მნიშვნელობის დაყენების შეცდომა: %s" -#: fe-secure-openssl.c:1051 +#: fe-secure-openssl.c:891 #, c-format msgid "could not load system root certificate paths: %s" msgstr "სისტემური root სერტიფიკატების ბილიკების ჩატვირთვის შეცდომა: %s" -#: fe-secure-openssl.c:1068 +#: fe-secure-openssl.c:908 #, c-format msgid "could not read root certificate file \"%s\": %s" msgstr "root სერტიფიკატის ფაილის (\"%s\") წაკითხვის შეცდომა: %s" -#: fe-secure-openssl.c:1120 +#: fe-secure-openssl.c:960 #, c-format msgid "" "could not get home directory to locate root certificate file\n" @@ -1385,7 +1790,7 @@ msgstr "" "root სერტიფიკატის ფაილის მოსაძებნად საწყისი საქაღალდის მიღება შეუძლებელია\n" "ამ წარმოადგინეთ ფაილი, ან გამოიყენეთ სისტემის სანდო root-ები პარამეტრით sslrootcert=system, ან sslmode სერვერის სერტიფიკატის შემოწმება გამორთეთ." -#: fe-secure-openssl.c:1123 +#: fe-secure-openssl.c:963 #, c-format msgid "" "root certificate file \"%s\" does not exist\n" @@ -1394,127 +1799,137 @@ msgstr "" "root სერტიფიკატის ფაილი \"%s\" არ არსებობს\n" "წარმოადგინეთ ფაილი ან გამორთეთ sslmode სერვერის სერტიფიკატის შემოწმება." -#: fe-secure-openssl.c:1158 +#: fe-secure-openssl.c:998 #, c-format msgid "could not open certificate file \"%s\": %s" msgstr "სერტიფიკატის ფაილის გახსნის შეცდომა \"%s\": %s" -#: fe-secure-openssl.c:1176 +#: fe-secure-openssl.c:1016 #, c-format msgid "could not read certificate file \"%s\": %s" msgstr "სერტიფიკატის ფაილის წაკითხვის შეცდომა \"%s\": %s" -#: fe-secure-openssl.c:1200 +#: fe-secure-openssl.c:1040 #, c-format msgid "could not establish SSL connection: %s" msgstr "'SSL' შეერთების დამყარების შეცდომა: %s" -#: fe-secure-openssl.c:1232 +#: fe-secure-openssl.c:1053 +#, c-format +msgid "WARNING: sslkeylogfile support requires OpenSSL\n" +msgstr "გაფრთხილება: sslkeylogfile-ის მხარდაჭერას OpenSSL სჭირდება\n" + +#: fe-secure-openssl.c:1055 +#, c-format +msgid "WARNING: libpq was not built with sslkeylogfile support\n" +msgstr "გაფრთხილება: libpq არ იყო აგებული sslkeylogfile-ის მხარდაჭერით\n" + +#: fe-secure-openssl.c:1086 #, c-format msgid "could not set SSL Server Name Indication (SNI): %s" msgstr "'SSL' სერვერის სახელის ინდიკაციის (SNI) დაყენების შეცდომა: %s" -#: fe-secure-openssl.c:1249 +#: fe-secure-openssl.c:1103 #, c-format msgid "could not set SSL ALPN extension: %s" msgstr "\"SSL ALPN\" გაფართოების დაყენების შეცდომა: %s" -#: fe-secure-openssl.c:1292 +#: fe-secure-openssl.c:1146 #, c-format msgid "could not load SSL engine \"%s\": %s" msgstr "'SSL' ძრავის (\"%s\") ჩატვირთვის შეცდომა: %s" -#: fe-secure-openssl.c:1303 +#: fe-secure-openssl.c:1157 #, c-format msgid "could not initialize SSL engine \"%s\": %s" msgstr "'SSL' ძრავის (\"%s\") ინიციალიზაციის შეცდომა: %s" -#: fe-secure-openssl.c:1318 +#: fe-secure-openssl.c:1172 #, c-format msgid "could not read private SSL key \"%s\" from engine \"%s\": %s" msgstr "'SSL'-ის პირადი გასაღების (\"%s\") ძრავიდან (\"%s\") წაკითხვის შეცდომა: %s" -#: fe-secure-openssl.c:1331 +#: fe-secure-openssl.c:1185 #, c-format msgid "could not load private SSL key \"%s\" from engine \"%s\": %s" msgstr "'SSL'-ის პირადი გასაღების (\"%s\") ძრავიდან (\"%s\") წაკითხვის შეცდომა: %s" -#: fe-secure-openssl.c:1368 +#: fe-secure-openssl.c:1222 #, c-format msgid "certificate present, but not private key file \"%s\"" msgstr "სერტიფიკატისგან განსხვავებით, პირადი გასაღების ფაილი \"%s\" არ არსებობს" -#: fe-secure-openssl.c:1371 +#: fe-secure-openssl.c:1225 #, c-format msgid "could not stat private key file \"%s\": %m" msgstr "პირადი გასაღების ფაილი \"%s\" არ არსებობს: %m" -#: fe-secure-openssl.c:1379 +#: fe-secure-openssl.c:1233 #, c-format msgid "private key file \"%s\" is not a regular file" msgstr "პირადი გასაღების ფაილი \"%s\" ჩვეულებრივი ფაილი არაა" -#: fe-secure-openssl.c:1412 +#: fe-secure-openssl.c:1266 #, c-format msgid "private key file \"%s\" has group or world access; file must have permissions u=rw (0600) or less if owned by the current user, or permissions u=rw,g=r (0640) or less if owned by root" msgstr "პირადი გასაღების ფაილს \"%s\" აქვს ჯგუფური ან ყველა სხვაზე წვდომა; ფაილს უნდა ჰქონდეს ნებართვები u=rw (0600) ან ნაკლები, თუ ეკუთვნის ამჟამინდელ მომხმარებელს, ან ნებართვები u=rw,g=r (0640) ან ნაკლები, თუ ეკუთვნის root-ს" -#: fe-secure-openssl.c:1436 +#: fe-secure-openssl.c:1290 #, c-format msgid "could not load private key file \"%s\": %s" msgstr "პირადი გასაღების ფაილის \"%s\" ჩატვირთვის შეცდომა: %s" -#: fe-secure-openssl.c:1452 +#: fe-secure-openssl.c:1306 #, c-format msgid "certificate does not match private key file \"%s\": %s" msgstr "სერტიფიკატი პირადი გასაღების ფაილს (\"%s\") არ ემთხვევა: %s" -#: fe-secure-openssl.c:1521 +#: fe-secure-openssl.c:1375 #, c-format msgid "SSL error: certificate verify failed: %s" msgstr "SSL-ის შეცდომა: სერტიფიკატის გადამოწმების შეცდომა: %s" -#: fe-secure-openssl.c:1566 +#: fe-secure-openssl.c:1420 #, c-format msgid "This may indicate that the server does not support any SSL protocol version between %s and %s." msgstr "ეს შეიძლება ნიშნავდეს, რომ სერვერს SSL პროტოკოლის %s-სა და %s-ს შორის ვერსიების მხარდაჭერა არ გააჩნია." -#: fe-secure-openssl.c:1598 +#: fe-secure-openssl.c:1452 #, c-format msgid "direct SSL connection was established without ALPN protocol negotiation extension" -msgstr "პირდაპირი SSL მიერთება დამყარდა ALPN პროტოკოლის შეთანხმების გაფართოების გარეშე" +msgstr "პირდაპირი SSL მიერთება დამყარდა ALPN პროტოკოლის მიმოცვლის გაფართოების გარეშე" -#: fe-secure-openssl.c:1610 +#: fe-secure-openssl.c:1464 #, c-format msgid "SSL connection was established with unexpected ALPN protocol" msgstr "SSL შეერთება დამყარდა მოულოდნელი ALPN პროტოკოლით" -#: fe-secure-openssl.c:1627 +#: fe-secure-openssl.c:1481 #, c-format msgid "certificate could not be obtained: %s" msgstr "სერტიფიკატის მიღების შეცდომა: %s" -#: fe-secure-openssl.c:1734 +#: fe-secure-openssl.c:1560 #, c-format msgid "no SSL error reported" msgstr "'SSL'-ის შეცდომების გარეშე" -#: fe-secure-openssl.c:1776 +#: fe-secure-openssl.c:1603 #, c-format msgid "SSL error code %lu" msgstr "SSL-ის შეცდომის კოდი %lu" -#: fe-secure-openssl.c:2075 +#: fe-secure-openssl.c:1905 #, c-format msgid "WARNING: sslpassword truncated\n" msgstr "გაფრთხილება: sslpasswrord შეკვეცილია\n" -#: fe-secure.c:248 +#: fe-secure.c:233 #, c-format msgid "could not receive data from server: %s" msgstr "სერვერიდან მონაცემების მიღების შეცდომა: %s" -#: fe-secure.c:419 +#: fe-secure.c:404 #, c-format msgid "could not send data to server: %s" msgstr "სერვერისთვის მონაცემების გაგზავნის შეცდომა: %s" @@ -1551,6 +1966,10 @@ msgstr "სოკეტის უცნობი შეცდომა: 0x%08X/% #~ msgid "could not load private key file \"%s\": %s\n" #~ msgstr "პირადი გასაღების ფაილის \"%s\" ჩატვირთვის შეცდომა: %s\n" +#, c-format +#~ msgid "could not look up local user ID %d: %s" +#~ msgstr "ლოკალური მომხმარებლის ID-ის (%d) ამოხსნა შეუძლებელია: %s" + #, c-format #~ msgid "could not open file \"%s\": %s\n" #~ msgstr "ფაილის გახსნის შეცდომა \"%s\": %s\n" @@ -1558,10 +1977,18 @@ msgstr "სოკეტის უცნობი შეცდომა: 0x%08X/% #~ msgid "incoming GSSAPI message did not use confidentiality\n" #~ msgstr "შემომავალი GSSAPI შეტყობინება კონფიდენციალობას არ იყენებს\n" +#, c-format +#~ msgid "invalid %s message" +#~ msgstr "არასწორი %s შეტყობინება" + #, c-format #~ msgid "invalid require_auth method: \"%s\"" #~ msgstr "require_auth-ის არასწორი მეთოდი: \"%s\"" +#, c-format +#~ msgid "keepalives parameter must be an integer" +#~ msgstr "პარამეტრი keepalives მთელი რიცხვი უნდა იყოს" + #, c-format #~ msgid "no application protocol" #~ msgstr "აპლიკაციის პროტოკოლის გარეშე" @@ -1581,6 +2008,16 @@ msgstr "სოკეტის უცნობი შეცდომა: 0x%08X/% #~ msgid "private key file \"%s\" is not a regular file\n" #~ msgstr "პირადი გასაღების ფაილი \"%s\" ჩვეულებრივი ფაილი არაა\n" +#, c-format +#~ msgid "protocol extension not supported by server: %s" +#~ msgid_plural "protocol extensions not supported by server: %s" +#~ msgstr[0] "პროტოკოლის გაფართოება სერვერის მიერ მხარდაჭერილი არაა: %s" +#~ msgstr[1] "პროტოკოლის გაფართოებები სერვერის მიერ მხარდაჭერილი არაა: %s" + +#, c-format +#~ msgid "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u" +#~ msgstr "პროტოკოლის ვერსია სერვერის მიერ მხარდაჭერილი არაა: კლიენტი იყენებს %u.%u, სერვერის მხარდაჭერილი ვერსიის მაქსიმუმია %u.%u" + #, c-format #~ msgid "sslnegotiation value \"%s\" invalid when SSL support is not compiled in" #~ msgstr "sslnegotiation-ის მნიშვნელობა \"%s\" არასწორია, როცა SSL-ის მხარდაჭერა გამორთული იყო აგების დროს" diff --git a/src/interfaces/libpq/po/meson.build b/src/interfaces/libpq/po/meson.build index 20b5795e89bf4..527379c5ce627 100644 --- a/src/interfaces/libpq/po/meson.build +++ b/src/interfaces/libpq/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('libpq' + '5' + '-' + pg_version_major.to_string())] diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c index 037875c523696..51ef4d591dad1 100644 --- a/src/interfaces/libpq/pqexpbuffer.c +++ b/src/interfaces/libpq/pqexpbuffer.c @@ -15,7 +15,7 @@ * a usable vsnprintf(), then a copy of our own implementation of it will * be linked into libpq. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/pqexpbuffer.c diff --git a/src/interfaces/libpq/pqexpbuffer.h b/src/interfaces/libpq/pqexpbuffer.h index d05010066b2f9..a0af7ad6adff1 100644 --- a/src/interfaces/libpq/pqexpbuffer.h +++ b/src/interfaces/libpq/pqexpbuffer.h @@ -15,7 +15,7 @@ * a usable vsnprintf(), then a copy of our own implementation of it will * be linked into libpq. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/interfaces/libpq/pqexpbuffer.h diff --git a/src/interfaces/libpq/pthread-win32.c b/src/interfaces/libpq/pthread-win32.c index b40872898d15e..db75d491b90d4 100644 --- a/src/interfaces/libpq/pthread-win32.c +++ b/src/interfaces/libpq/pthread-win32.c @@ -3,7 +3,7 @@ * pthread-win32.c * partial pthread implementation for win32 * -* Copyright (c) 2004-2024, PostgreSQL Global Development Group +* Copyright (c) 2004-2025, PostgreSQL Global Development Group * IDENTIFICATION * src/interfaces/libpq/pthread-win32.c * diff --git a/src/interfaces/libpq/t/001_uri.pl b/src/interfaces/libpq/t/001_uri.pl index 49ea5377e0315..b0edcb3be8846 100644 --- a/src/interfaces/libpq/t/001_uri.pl +++ b/src/interfaces/libpq/t/001_uri.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -86,6 +86,24 @@ q{user='uri-user' host='host' (inet)}, q{}, ], + [ + # Leading and trailing spaces, works. + q{postgresql://host? user = uri-user & port = 12345 }, + q{user='uri-user' host='host' port='12345' (inet)}, + q{}, + ], + [ + # Trailing data in parameter. + q{postgresql://host? user user = uri & port = 12345 12 }, + q{}, + q{libpq_uri_regress: unexpected spaces found in " user user ", use percent-encoded spaces (%20) instead}, + ], + [ + # Trailing data in value. + q{postgresql://host? user = uri-user & port = 12345 12 }, + q{}, + q{libpq_uri_regress: unexpected spaces found in " 12345 12 ", use percent-encoded spaces (%20) instead}, + ], [ q{postgresql://host?}, q{host='host' (inet)}, q{}, ], [ q{postgresql://[::1]:12345/db}, @@ -250,8 +268,9 @@ sub test_uri %ENV = (%ENV, %envvars); my $cmd = [ 'libpq_uri_regress', $uri ]; - $result{exit} = IPC::Run::run $cmd, '>', \$result{stdout}, '2>', - \$result{stderr}; + $result{exit} = IPC::Run::run $cmd, + '>' => \$result{stdout}, + '2>' => \$result{stderr}; chomp($result{stdout}); chomp($result{stderr}); diff --git a/src/interfaces/libpq/t/002_api.pl b/src/interfaces/libpq/t/002_api.pl index 785f3c9c8f867..3202c87ebe79d 100644 --- a/src/interfaces/libpq/t/002_api.pl +++ b/src/interfaces/libpq/t/002_api.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/interfaces/libpq/t/003_load_balance_host_list.pl b/src/interfaces/libpq/t/003_load_balance_host_list.pl index 8567c38388346..6e859c49351ff 100644 --- a/src/interfaces/libpq/t/003_load_balance_host_list.pl +++ b/src/interfaces/libpq/t/003_load_balance_host_list.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; use Config; diff --git a/src/interfaces/libpq/t/004_load_balance_dns.pl b/src/interfaces/libpq/t/004_load_balance_dns.pl index 198a11fcf4a34..19a4f80fd7f14 100644 --- a/src/interfaces/libpq/t/004_load_balance_dns.pl +++ b/src/interfaces/libpq/t/004_load_balance_dns.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; use Config; diff --git a/src/interfaces/libpq/t/005_negotiate_encryption.pl b/src/interfaces/libpq/t/005_negotiate_encryption.pl index 157f23b8e831b..ac6d8bcb4a648 100644 --- a/src/interfaces/libpq/t/005_negotiate_encryption.pl +++ b/src/interfaces/libpq/t/005_negotiate_encryption.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # OVERVIEW # -------- @@ -90,8 +90,6 @@ $ENV{PG_TEST_EXTRA} && $ENV{PG_TEST_EXTRA} =~ /\bkerberos\b/; my $ssl_supported = $ENV{with_ssl} eq 'openssl'; -my $injection_points_supported = $ENV{enable_injection_points} eq 'yes'; - ### ### Prepare test server for GSSAPI and SSL authentication, with a few ### different test users and helper functions. We don't actually @@ -109,7 +107,7 @@ listen_addresses = '$hostaddr' # Capturing the EVENTS that occur during tests requires these settings -log_connections = on +log_connections = 'receipt,authentication,authorization' log_disconnections = on trace_connection_negotiation = on lc_messages = 'C' @@ -151,6 +149,11 @@ $node->start; +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +my $injection_points_supported = $node->check_extension('injection_points'); + $node->safe_psql('postgres', 'CREATE USER localuser;'); $node->safe_psql('postgres', 'CREATE USER testuser;'); $node->safe_psql('postgres', 'CREATE USER ssluser;'); @@ -240,7 +243,7 @@ BEGIN . . require postgres connect, sslreject -> fail . . . direct connect, directsslreject -> fail -# sslnegotiation=direct is not acccepted unless sslmode=require or stronger +# sslnegotiation=direct is not accepted unless sslmode=require or stronger * * disable direct - -> fail * * allow direct - -> fail * * prefer direct - -> fail @@ -303,7 +306,7 @@ BEGIN . . require postgres connect, sslaccept, authfail -> fail . . require direct connect, directsslaccept, authfail -> fail -# sslnegotiation=direct is not acccepted unless sslmode=require or stronger +# sslnegotiation=direct is not accepted unless sslmode=require or stronger * * disable direct - -> fail * * allow direct - -> fail * * prefer direct - -> fail @@ -405,7 +408,7 @@ BEGIN . . require postgres connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail . . . direct connect, gssaccept, authfail -> fail # If both GSSAPI and sslmode are required, and GSS is not available -> fail -# sslnegotiation=direct is not acccepted unless sslmode=require or stronger +# sslnegotiation=direct is not accepted unless sslmode=require or stronger * * disable direct - -> fail * * allow direct - -> fail * * prefer direct - -> fail @@ -452,7 +455,7 @@ BEGIN connect_test( $node, "user=testuser gssencmode=prefer sslmode=disable", - 'connect, v2error -> fail'); + 'connect, v2error, reconnect, v2error -> fail'); $node->restart; $node->safe_psql( @@ -562,7 +565,7 @@ BEGIN . require * postgres connect, gssaccept, authok -> gss . . require direct connect, gssaccept, authok -> gss -# sslnegotiation=direct is not acccepted unless sslmode=require or stronger +# sslnegotiation=direct is not accepted unless sslmode=require or stronger * * disable direct - -> fail * * allow direct - -> fail * * prefer direct - -> fail @@ -670,7 +673,9 @@ sub connect_test my ($ret, $stdout, $stderr) = $node->psql( 'postgres', '', - extra_params => [ '-w', '-c', 'SELECT current_enc()' ], + extra_params => [ + '--no-password', '--command' => 'SELECT current_enc()', + ], connstr => "$connstr_full", on_error_stop => 0); diff --git a/src/interfaces/libpq/t/006_service.pl b/src/interfaces/libpq/t/006_service.pl new file mode 100644 index 0000000000000..4fe5adc5c2acd --- /dev/null +++ b/src/interfaces/libpq/t/006_service.pl @@ -0,0 +1,151 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group +use strict; +use warnings FATAL => 'all'; +use File::Copy; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +# This tests scenarios related to the service name and the service file, +# for the connection options and their environment variables. + +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->start; + +# Set up a dummy node used for the connection tests, but do not start it. +# This ensures that the environment variables used for the connection do +# not interfere with the connection attempts, and that the service file's +# contents are used. +my $dummy_node = PostgreSQL::Test::Cluster->new('dummy_node'); +$dummy_node->init; + +my $td = PostgreSQL::Test::Utils::tempdir; + +# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on +# the fact that libpq uses fgets() when reading the lines of a service file. +my $newline = $windows_os ? "\r\n" : "\n"; + +# Create the set of service files used in the tests. +# File that includes a valid service name, and uses a decomposed connection +# string for its contents, split on spaces. +my $srvfile_valid = "$td/pg_service_valid.conf"; +append_to_file($srvfile_valid, "[my_srv]" . $newline); +foreach my $param (split(/\s+/, $node->connstr)) +{ + append_to_file($srvfile_valid, $param . $newline); +} + +# File defined with no contents, used as default value for PGSERVICEFILE, +# so as no lookup is attempted in the user's home directory. +my $srvfile_empty = "$td/pg_service_empty.conf"; +append_to_file($srvfile_empty, ''); + +# Default service file in PGSYSCONFDIR. +my $srvfile_default = "$td/pg_service.conf"; + +# Missing service file. +my $srvfile_missing = "$td/pg_service_missing.conf"; + +# Set the fallback directory lookup of the service file to the temporary +# directory of this test. PGSYSCONFDIR is used if the service file +# defined in PGSERVICEFILE cannot be found, or when a service file is +# found but not the service name. +local $ENV{PGSYSCONFDIR} = $td; +# Force PGSERVICEFILE to a default location, so as this test never +# tries to look at a home directory. This value needs to remain +# at the top of this script before running any tests, and should never +# be changed. +local $ENV{PGSERVICEFILE} = "$srvfile_empty"; + +# Checks combinations of service name and a valid service file. +{ + local $ENV{PGSERVICEFILE} = $srvfile_valid; + $dummy_node->connect_ok( + 'service=my_srv', + 'connection with correct "service" string and PGSERVICEFILE', + sql => "SELECT 'connect1_1'", + expected_stdout => qr/connect1_1/); + + $dummy_node->connect_ok( + 'postgres://?service=my_srv', + 'connection with correct "service" URI and PGSERVICEFILE', + sql => "SELECT 'connect1_2'", + expected_stdout => qr/connect1_2/); + + $dummy_node->connect_fails( + 'service=undefined-service', + 'connection with incorrect "service" string and PGSERVICEFILE', + expected_stderr => + qr/definition of service "undefined-service" not found/); + + local $ENV{PGSERVICE} = 'my_srv'; + $dummy_node->connect_ok( + '', + 'connection with correct PGSERVICE and PGSERVICEFILE', + sql => "SELECT 'connect1_3'", + expected_stdout => qr/connect1_3/); + + local $ENV{PGSERVICE} = 'undefined-service'; + $dummy_node->connect_fails( + '', + 'connection with incorrect PGSERVICE and PGSERVICEFILE', + expected_stdout => + qr/definition of service "undefined-service" not found/); +} + +# Checks case of incorrect service file. +{ + local $ENV{PGSERVICEFILE} = $srvfile_missing; + $dummy_node->connect_fails( + 'service=my_srv', + 'connection with correct "service" string and incorrect PGSERVICEFILE', + expected_stderr => + qr/service file ".*pg_service_missing.conf" not found/); +} + +# Checks case of service file named "pg_service.conf" in PGSYSCONFDIR. +{ + # Create copy of valid file + my $srvfile_default = "$td/pg_service.conf"; + copy($srvfile_valid, $srvfile_default); + + $dummy_node->connect_ok( + 'service=my_srv', + 'connection with correct "service" string and pg_service.conf', + sql => "SELECT 'connect2_1'", + expected_stdout => qr/connect2_1/); + + $dummy_node->connect_ok( + 'postgres://?service=my_srv', + 'connection with correct "service" URI and default pg_service.conf', + sql => "SELECT 'connect2_2'", + expected_stdout => qr/connect2_2/); + + $dummy_node->connect_fails( + 'service=undefined-service', + 'connection with incorrect "service" string and default pg_service.conf', + expected_stderr => + qr/definition of service "undefined-service" not found/); + + local $ENV{PGSERVICE} = 'my_srv'; + $dummy_node->connect_ok( + '', + 'connection with correct PGSERVICE and default pg_service.conf', + sql => "SELECT 'connect2_3'", + expected_stdout => qr/connect2_3/); + + local $ENV{PGSERVICE} = 'undefined-service'; + $dummy_node->connect_fails( + '', + 'connection with incorrect PGSERVICE and default pg_service.conf', + expected_stdout => + qr/definition of service "undefined-service" not found/); + + # Remove default pg_service.conf. + unlink($srvfile_default); +} + +$node->teardown_node; + +done_testing(); diff --git a/src/interfaces/libpq/test/libpq_testclient.c b/src/interfaces/libpq/test/libpq_testclient.c index 4a286ddb9c3cf..44aff6c0f911b 100644 --- a/src/interfaces/libpq/test/libpq_testclient.c +++ b/src/interfaces/libpq/test/libpq_testclient.c @@ -2,7 +2,7 @@ * libpq_testclient.c * A test program for the libpq public API * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/interfaces/libpq/test/libpq_testclient.c diff --git a/src/interfaces/libpq/test/libpq_uri_regress.c b/src/interfaces/libpq/test/libpq_uri_regress.c index eaab7bbe8bbf8..bb12cf65537d4 100644 --- a/src/interfaces/libpq/test/libpq_uri_regress.c +++ b/src/interfaces/libpq/test/libpq_uri_regress.c @@ -7,7 +7,7 @@ * prints out the values from the parsed PQconninfoOption struct that differ * from the defaults (obtained from PQconndefaults). * - * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2012-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/interfaces/libpq/test/libpq_uri_regress.c diff --git a/src/interfaces/libpq/test/meson.build b/src/interfaces/libpq/test/meson.build index 21dd37f69bc7f..07a5facc321c7 100644 --- a/src/interfaces/libpq/test/meson.build +++ b/src/interfaces/libpq/test/meson.build @@ -1,4 +1,6 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group + +libpq_test_deps = [] libpq_uri_regress_sources = files( 'libpq_uri_regress.c', @@ -10,9 +12,9 @@ if host_system == 'windows' '--FILEDESC', 'libpq test program',]) endif -testprep_targets += executable('libpq_uri_regress', +libpq_test_deps += executable('libpq_uri_regress', libpq_uri_regress_sources, - dependencies: [frontend_code, libpq], + dependencies: [frontend_no_fe_utils_code, libpq], kwargs: default_bin_args + { 'install': false, } @@ -29,10 +31,12 @@ if host_system == 'windows' '--FILEDESC', 'libpq test program',]) endif -testprep_targets += executable('libpq_testclient', +libpq_test_deps += executable('libpq_testclient', libpq_testclient_sources, - dependencies: [frontend_code, libpq], + dependencies: [frontend_no_fe_utils_code, libpq], kwargs: default_bin_args + { 'install': false, } ) + +testprep_targets += libpq_test_deps diff --git a/src/interfaces/libpq/win32.c b/src/interfaces/libpq/win32.c index c738dee69119c..0adae19c1f567 100644 --- a/src/interfaces/libpq/win32.c +++ b/src/interfaces/libpq/win32.c @@ -15,7 +15,7 @@ * The error constants are taken from the Frambak Bakfram LGSOCKET * library guys who in turn took them from the Winsock FAQ. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * */ @@ -231,7 +231,7 @@ LookupWSErrorMessage(DWORD err, char *dest) } -struct MessageDLL +static struct MessageDLL { const char *dll_name; void *handle; diff --git a/src/interfaces/meson.build b/src/interfaces/meson.build index bf87332888b2d..50623b31b6907 100644 --- a/src/interfaces/meson.build +++ b/src/interfaces/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # NB: libpq is entered directly from the toplevel meson file subdir('ecpg') diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build index 5618050b30630..91a8de1ee9b9d 100644 --- a/src/makefiles/meson.build +++ b/src/makefiles/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group ### Compute pgxs_data, used in src/meson.build to generate Makefile.global ### etc, that's complete enough for PGXS to work. @@ -98,12 +98,12 @@ pgxs_kv = { 'CXXFLAGS_SL_MODULE': ' '.join(cxxflags_mod), 'PERMIT_DECLARATION_AFTER_STATEMENT': ' '.join(cflags_no_decl_after_statement), + 'PERMIT_MISSING_VARIABLE_DECLARATIONS': + ' '.join(cflags_no_missing_var_decls), 'CFLAGS_CRC': ' '.join(cflags_crc), - 'CFLAGS_POPCNT': ' '.join(cflags_popcnt), 'CFLAGS_UNROLL_LOOPS': ' '.join(unroll_loops_cflags), 'CFLAGS_VECTORIZE': ' '.join(vectorize_cflags), - 'CFLAGS_XSAVE': ' '.join(cflags_xsave), 'LDFLAGS': var_ldflags, 'LDFLAGS_EX': var_ldflags_ex, @@ -179,7 +179,8 @@ pgxs_empty = [ 'WANTED_LANGUAGES', # Not needed because we don't build the server / PLs with the generated makefile - 'LIBOBJS', 'PG_CRC32C_OBJS', 'PG_POPCNT_OBJS', 'TAS', + 'LIBOBJS', 'PG_CRC32C_OBJS', 'TAS', + 'PG_TEST_EXTRA', 'DTRACEFLAGS', # only server has dtrace probes 'perl_archlibexp', 'perl_embed_ccflags', 'perl_embed_ldflags', 'perl_includespec', 'perl_privlibexp', @@ -198,6 +199,12 @@ pgxs_empty = [ 'PTHREAD_CFLAGS', 'PTHREAD_LIBS', 'ICU_LIBS', + + 'LIBNUMA_CFLAGS', 'LIBNUMA_LIBS', + + 'LIBURING_CFLAGS', 'LIBURING_LIBS', + + 'LIBCURL_CPPFLAGS', 'LIBCURL_LDFLAGS', 'LIBCURL_LDLIBS', ] if host_system == 'windows' and cc.get_argument_syntax() != 'msvc' @@ -228,6 +235,9 @@ pgxs_deps = { 'gssapi': gssapi, 'icu': icu, 'ldap': ldap, + 'libcurl': libcurl, + 'libnuma': libnuma, + 'liburing': liburing, 'libxml': libxml, 'libxslt': libxslt, 'llvm': llvm, diff --git a/src/meson.build b/src/meson.build index 65c7d17d08f09..f098f9f164e5b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # libraries that other subsystems might depend upon first, in their respective # dependency order diff --git a/src/pl/meson.build b/src/pl/meson.build index 0d62a758661af..f8ff0671b4381 100644 --- a/src/pl/meson.build +++ b/src/pl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('plpgsql') diff --git a/src/pl/plperl/GNUmakefile b/src/pl/plperl/GNUmakefile index 31fb212bf170a..558c764aadb2a 100644 --- a/src/pl/plperl/GNUmakefile +++ b/src/pl/plperl/GNUmakefile @@ -60,10 +60,10 @@ ifeq ($(PORTNAME), cygwin) SHLIB_LINK += -Wl,--export-all-symbols endif -REGRESS_OPTS = --dbname=$(PL_TESTDB) +REGRESS_OPTS = --dbname=$(PL_TESTDB) --dlpath=$(top_builddir)/src/test/regress REGRESS = plperl_setup plperl plperl_lc plperl_trigger plperl_shared \ plperl_elog plperl_util plperl_init plperlu plperl_array \ - plperl_call plperl_transaction + plperl_call plperl_transaction plperl_env # if Perl can support two interpreters in one backend, # test plperl-and-plperlu cases ifneq ($(PERL),) @@ -85,7 +85,7 @@ plperl_opmask.h: plperl_opmask.pl perlchunks.h: $(PERLCHUNKS) @if [ x"$(perl_privlibexp)" = x"" ]; then echo "configure switch --with-perl was not specified."; exit 1; fi - $(PERL) $(srcdir)/text2macro.pl --strip='^(\#.*|\s*)$$' $^ > $@ + $(PERL) $(srcdir)/text2macro.pl $^ > $@ all: all-lib diff --git a/src/pl/plperl/expected/plperl_env.out b/src/pl/plperl/expected/plperl_env.out new file mode 100644 index 0000000000000..f777c072b5690 --- /dev/null +++ b/src/pl/plperl/expected/plperl_env.out @@ -0,0 +1,55 @@ +-- +-- Test the environment setting +-- +-- directory path and dlsuffix are passed to us in environment variables +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX +\set regresslib :libdir '/regress' :dlsuffix +CREATE FUNCTION get_environ() + RETURNS text[] + AS :'regresslib', 'get_environ' + LANGUAGE C STRICT; +-- fetch the process environment +CREATE FUNCTION process_env () RETURNS text[] +LANGUAGE plpgsql AS +$$ + +declare + res text[]; + tmp text[]; + f record; +begin + for f in select unnest(get_environ()) as t loop + tmp := regexp_split_to_array(f.t, '='); + if array_length(tmp, 1) = 2 then + res := res || tmp; + end if; + end loop; + return res; +end + +$$; +-- plperl should not be able to affect the process environment +DO +$$ + $ENV{TEST_PLPERL_ENV_FOO} = "shouldfail"; + untie %ENV; + $ENV{TEST_PLPERL_ENV_FOO} = "testval"; + my $penv = spi_exec_query("select unnest(process_env()) as pe"); + my %received; + for (my $f = 0; $f < $penv->{processed}; $f += 2) + { + my $k = $penv->{rows}[$f]->{pe}; + my $v = $penv->{rows}[$f+1]->{pe}; + $received{$k} = $v; + } + unless (exists $received{TEST_PLPERL_ENV_FOO}) + { + elog(NOTICE, "environ unaffected") + } + +$$ LANGUAGE plperl; +WARNING: attempted alteration of $ENV{TEST_PLPERL_ENV_FOO} at line 12. +NOTICE: environ unaffected +-- clean up to simplify cross-version upgrade testing +DROP FUNCTION get_environ(); diff --git a/src/pl/plperl/expected/plperl_trigger.out b/src/pl/plperl/expected/plperl_trigger.out index d4879e2f03b04..42c52ecbba839 100644 --- a/src/pl/plperl/expected/plperl_trigger.out +++ b/src/pl/plperl/expected/plperl_trigger.out @@ -8,7 +8,8 @@ CREATE TABLE trigger_test ( ); CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger LANGUAGE plperl AS $$ @@ -386,7 +387,7 @@ INSERT INTO trigger_test_generated (i) VALUES (1); ERROR: cannot set generated column "j" CONTEXT: PL/Perl function "generated_test_func1" SELECT * FROM trigger_test_generated; - i | j ----+--- + i | j | k +---+---+--- (0 rows) diff --git a/src/pl/plperl/meson.build b/src/pl/plperl/meson.build index 8d2d72ff37e54..b463d4d56c5b3 100644 --- a/src/pl/plperl/meson.build +++ b/src/pl/plperl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not perl_dep.found() subdir_done() @@ -17,7 +17,7 @@ plperl_sources += custom_target('perlchunks.h', input: files('plc_perlboot.pl', 'plc_trusted.pl'), output: 'perlchunks.h', capture: true, - command: [perl, files('text2macro.pl'), '--strip=^(\#.*|\s*)$', '@INPUT@'] + command: [perl, files('text2macro.pl'), '@INPUT@'] ) plperl_sources += custom_target('plperl_opmask.h', @@ -94,7 +94,9 @@ tests += { 'plperl_array', 'plperl_call', 'plperl_transaction', + 'plperl_env', ], + 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], }, } diff --git a/src/pl/plperl/plc_perlboot.pl b/src/pl/plperl/plc_perlboot.pl index f6593f032a9fc..28a1a4cd6f2b9 100644 --- a/src/pl/plperl/plc_perlboot.pl +++ b/src/pl/plperl/plc_perlboot.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # src/pl/plperl/plc_perlboot.pl diff --git a/src/pl/plperl/plc_trusted.pl b/src/pl/plperl/plc_trusted.pl index b326482700e49..1fc94259a0b11 100644 --- a/src/pl/plperl/plc_trusted.pl +++ b/src/pl/plperl/plc_trusted.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # src/pl/plperl/plc_trusted.pl @@ -30,3 +30,27 @@ package PostgreSQL::InServer::safe; ## no critic (RequireFilenameMatchesPackage) require Carp::Heavy; require warnings; require feature if $] >= 5.010000; + +#<<< protect next line from perltidy so perlcritic annotation works +package PostgreSQL::InServer::WarnEnv; ## no critic (RequireFilenameMatchesPackage) +#>>> + +use strict; +use warnings; +use Tie::Hash; +our @ISA = qw(Tie::StdHash); + +sub STORE { warn "attempted alteration of \$ENV{$_[1]}"; } +sub DELETE { warn "attempted deletion of \$ENV{$_[1]}"; } +sub CLEAR { warn "attempted clearance of ENV hash"; } + +# Remove magic property of %ENV. Changes to this will now not be reflected in +# the process environment. +*main::ENV = {%ENV}; + +# Block %ENV changes from trusted PL/Perl, and warn. We changed %ENV to just a +# normal hash, yet the application may be expecting the usual Perl %ENV +# magic. Blocking and warning avoids silent application breakage. The user can +# untie or otherwise disable this, e.g. if the lost mutation is unimportant +# and modifying the code to stop that mutation would be onerous. +tie %main::ENV, 'PostgreSQL::InServer::WarnEnv', %ENV or die $!; diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index d68ad7be34556..29cb4d7e47f80 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -24,7 +24,6 @@ #include "executor/spi.h" #include "funcapi.h" #include "miscadmin.h" -#include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "storage/ipc.h" #include "tcop/tcopprot.h" @@ -53,7 +52,10 @@ EXTERN_C void boot_DynaLoader(pTHX_ CV *cv); EXTERN_C void boot_PostgreSQL__InServer__Util(pTHX_ CV *cv); EXTERN_C void boot_PostgreSQL__InServer__SPI(pTHX_ CV *cv); -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "plperl", + .version = PG_VERSION +); /********************************************************************** * Information associated with a Perl interpreter. We have one interpreter @@ -1947,8 +1949,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS) current_call_data = &this_call_data; - if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC); select_perl_context(desc.lanpltrusted); @@ -2412,8 +2413,7 @@ plperl_func_handler(PG_FUNCTION_ARGS) IsA(fcinfo->context, CallContext) && !castNode(CallContext, fcinfo->context)->atomic; - if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0); prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false, false); current_call_data->prodesc = prodesc; @@ -2530,8 +2530,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) int rc PG_USED_FOR_ASSERTS_ONLY; /* Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect(); /* Make transition tables visible to this SPI connection */ tdata = (TriggerData *) fcinfo->context; @@ -2638,8 +2637,7 @@ plperl_event_trigger_handler(PG_FUNCTION_ARGS) ErrorContextCallback pl_error_context; /* Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect(); /* Find or compile the function */ prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false, true); @@ -3052,6 +3050,9 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generate /* don't include unless requested */ if (!include_generated) continue; + /* never include virtual columns */ + if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + continue; } attname = NameStr(att->attname); diff --git a/src/pl/plperl/plperl.h b/src/pl/plperl/plperl.h index 3ee278ff02944..5c4c3ac577074 100644 --- a/src/pl/plperl/plperl.h +++ b/src/pl/plperl/plperl.h @@ -6,7 +6,7 @@ * This should be included _AFTER_ postgres.h and system include files, as * well as headers that could in turn include system headers. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California * * src/pl/plperl/plperl.h diff --git a/src/pl/plperl/plperl_opmask.pl b/src/pl/plperl/plperl_opmask.pl index e935aab5f8697..c64c7041a5a55 100644 --- a/src/pl/plperl/plperl_opmask.pl +++ b/src/pl/plperl/plperl_opmask.pl @@ -1,6 +1,6 @@ #!perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/pl/plperl/plperl_system.h b/src/pl/plperl/plperl_system.h index 48f6575e513b7..4c09a5cc1592b 100644 --- a/src/pl/plperl/plperl_system.h +++ b/src/pl/plperl/plperl_system.h @@ -8,7 +8,7 @@ * declarations should be put here. However, we do include some stuff * that is meant to prevent conflicts between our code and Perl. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California * * src/pl/plperl/plperl_system.h @@ -72,24 +72,18 @@ #endif /* - * Regarding bool, both PostgreSQL and Perl might use stdbool.h or not, - * depending on configuration. If both agree, things are relatively harmless. - * If not, things get tricky. If PostgreSQL does but Perl does not, define - * HAS_BOOL here so that Perl does not redefine bool; this avoids compiler - * warnings. If PostgreSQL does not but Perl does, we need to undefine bool - * after we include the Perl headers; see below. + * Define HAS_BOOL here so that Perl does not redefine bool. We included + * in c.h. */ -#ifdef PG_USE_STDBOOL #define HAS_BOOL 1 -#endif /* * Get the basic Perl API. We use PERL_NO_GET_CONTEXT mode so that our code * can compile against MULTIPLICITY Perl builds without including XSUB.h. */ #define PERL_NO_GET_CONTEXT -#include "EXTERN.h" -#include "perl.h" +#include +#include /* * We want to include XSUB.h only within .xs files, because on some platforms @@ -109,6 +103,7 @@ #undef fstat #undef kill #undef listen +#undef lseek #undef lstat #undef mkdir #undef open @@ -122,7 +117,7 @@ #undef unlink #endif -#include "XSUB.h" +#include #endif /* put back our *printf macros ... this must match src/include/port.h */ @@ -180,19 +175,6 @@ /* perl version and platform portability */ #include "ppport.h" -/* - * perl might have included stdbool.h. If we also did that earlier (see c.h), - * then that's fine. If not, we probably rejected it for some reason. In - * that case, undef bool and proceed with our own bool. (Note that stdbool.h - * makes bool a macro, but our own replacement is a typedef, so the undef - * makes ours visible again). - */ -#ifndef PG_USE_STDBOOL -#ifdef bool -#undef bool -#endif -#endif - /* supply HeUTF8 if it's missing - ppport.h doesn't supply it, unfortunately */ #ifndef HeUTF8 #define HeUTF8(he) ((HeKLEN(he) == HEf_SVKEY) ? \ diff --git a/src/pl/plperl/po/es.po b/src/pl/plperl/po/es.po index f0ca724b25a58..4846603c139c7 100644 --- a/src/pl/plperl/po/es.po +++ b/src/pl/plperl/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: plperl (PostgreSQL) 15\n" +"Project-Id-Version: plperl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:09+0000\n" -"PO-Revision-Date: 2022-10-20 09:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:39+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -100,8 +100,8 @@ msgstr "los arrays multidimensionales deben tener expresiones de arrays con dime #: plperl.c:1204 #, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "el número de dimensiones del array (%d) excede el máximo permitido (%d)" +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "el número de dimensiones del array excede el máximo permitido (%d)" #: plperl.c:1274 #, c-format diff --git a/src/pl/plperl/po/fr.po b/src/pl/plperl/po/fr.po index fcb6d67fa051a..ab1859f557e30 100644 --- a/src/pl/plperl/po/fr.po +++ b/src/pl/plperl/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-08-22 10:09+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,246 +19,226 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: plperl.c:408 +#: plperl.c:405 msgid "If true, trusted and untrusted Perl code will be compiled in strict mode." msgstr "" "Si true, le code Perl de confiance et sans confiance sera compilé en mode\n" "strict." -#: plperl.c:422 +#: plperl.c:419 msgid "Perl initialization code to execute when a Perl interpreter is initialized." msgstr "" "Code d'initialisation Perl à exécuter lorsque un interpréteur Perl est\n" "initialisé." -#: plperl.c:444 +#: plperl.c:441 msgid "Perl initialization code to execute once when plperl is first used." msgstr "Code d'initialisation Perl à exécuter lorsque plperl est utilisé pour la première fois." -#: plperl.c:452 +#: plperl.c:449 msgid "Perl initialization code to execute once when plperlu is first used." msgstr "Code d'initialisation Perl à exécuter lorsque plperlu est utilisé pour la première fois." -#: plperl.c:646 +#: plperl.c:643 #, c-format msgid "cannot allocate multiple Perl interpreters on this platform" msgstr "ne peut pas allouer plusieurs interpréteurs Perl sur cette plateforme" -#: plperl.c:669 plperl.c:853 plperl.c:859 plperl.c:976 plperl.c:988 -#: plperl.c:1031 plperl.c:1054 plperl.c:2138 plperl.c:2246 plperl.c:2314 -#: plperl.c:2377 +#: plperl.c:666 plperl.c:850 plperl.c:856 plperl.c:973 plperl.c:985 +#: plperl.c:1028 plperl.c:1051 plperl.c:2151 plperl.c:2259 plperl.c:2327 +#: plperl.c:2390 #, c-format msgid "%s" msgstr "%s" -#: plperl.c:670 +#: plperl.c:667 #, c-format msgid "while executing PostgreSQL::InServer::SPI::bootstrap" msgstr "lors de l'exécution de PostgreSQL::InServer::SPI::bootstrap" -#: plperl.c:854 +#: plperl.c:851 #, c-format msgid "while parsing Perl initialization" msgstr "lors de l'analyse de l'initialisation de perl" -#: plperl.c:860 +#: plperl.c:857 #, c-format msgid "while running Perl initialization" msgstr "lors de l'exécution de l'initialisation de perl" -#: plperl.c:977 +#: plperl.c:974 #, c-format msgid "while executing PLC_TRUSTED" msgstr "lors de l'exécution de PLC_TRUSTED" -#: plperl.c:989 +#: plperl.c:986 #, c-format msgid "while executing utf8fix" msgstr "lors de l'exécution de utf8fix" -#: plperl.c:1032 +#: plperl.c:1029 #, c-format msgid "while executing plperl.on_plperl_init" msgstr "lors de l'exécution de plperl.on_plperl_init" -#: plperl.c:1055 +#: plperl.c:1052 #, c-format msgid "while executing plperl.on_plperlu_init" msgstr "lors de l'exécution de plperl.on_plperlu_init" -#: plperl.c:1101 plperl.c:1791 +#: plperl.c:1098 plperl.c:1804 #, c-format msgid "Perl hash contains nonexistent column \"%s\"" msgstr "Le hachage Perl contient la colonne « %s » inexistante" -#: plperl.c:1106 plperl.c:1796 +#: plperl.c:1103 plperl.c:1809 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "ne peut pas initialiser l'attribut système « %s »" -#: plperl.c:1194 -#, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "le nombre de dimensions du tableau (%d) dépasse le maximum autorisé (%d)" - -#: plperl.c:1206 plperl.c:1223 +#: plperl.c:1199 plperl.c:1214 plperl.c:1231 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "" "les tableaux multidimensionnels doivent avoir des expressions de tableaux\n" "avec les dimensions correspondantes" -#: plperl.c:1259 +#: plperl.c:1204 +#, c-format +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "le nombre de dimensions du tableau dépasse le maximum autorisé (%d)" + +#: plperl.c:1274 #, c-format msgid "cannot convert Perl array to non-array type %s" msgstr "ne peut pas convertir le tableau Perl en un type %s qui n'est pas un tableau" -#: plperl.c:1362 +#: plperl.c:1375 #, c-format msgid "cannot convert Perl hash to non-composite type %s" msgstr "ne peut pas convertir le hachage Perl en un type %s non composite" -#: plperl.c:1384 plperl.c:3304 +#: plperl.c:1397 plperl.c:3315 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "" "fonction renvoyant le type record appelée dans un contexte qui ne peut pas\n" "accepter le type record" -#: plperl.c:1445 +#: plperl.c:1458 #, c-format msgid "lookup failed for type %s" msgstr "recherche échouée pour le type %s" -#: plperl.c:1766 +#: plperl.c:1779 #, c-format msgid "$_TD->{new} does not exist" msgstr "$_TD->{new} n'existe pas" -#: plperl.c:1770 +#: plperl.c:1783 #, c-format msgid "$_TD->{new} is not a hash reference" msgstr "$_TD->{new} n'est pas une référence de hachage" -#: plperl.c:1801 +#: plperl.c:1814 #, c-format msgid "cannot set generated column \"%s\"" msgstr "ne peut pas initialiser la colonne générée « %s »" -#: plperl.c:2013 plperl.c:2854 +#: plperl.c:2026 plperl.c:2867 #, c-format msgid "PL/Perl functions cannot return type %s" msgstr "Les fonctions PL/perl ne peuvent pas renvoyer le type %s" -#: plperl.c:2026 plperl.c:2893 +#: plperl.c:2039 plperl.c:2906 #, c-format msgid "PL/Perl functions cannot accept type %s" msgstr "Les fonctions PL/perl ne peuvent pas accepter le type %s" -#: plperl.c:2143 +#: plperl.c:2156 #, c-format msgid "didn't get a CODE reference from compiling function \"%s\"" msgstr "n'a pas obtenu une référence CODE lors de la compilation de la fonction « %s »" -#: plperl.c:2234 +#: plperl.c:2247 #, c-format msgid "didn't get a return item from function" msgstr "n'a pas obtenu un élément en retour de la fonction" -#: plperl.c:2278 plperl.c:2345 +#: plperl.c:2291 plperl.c:2358 #, c-format msgid "couldn't fetch $_TD" msgstr "n'a pas pu récupérer $_TD" -#: plperl.c:2302 plperl.c:2365 +#: plperl.c:2315 plperl.c:2378 #, c-format msgid "didn't get a return item from trigger function" msgstr "n'a pas obtenu un élément en retour de la fonction trigger" -#: plperl.c:2423 +#: plperl.c:2436 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "la fonction renvoyant un ensemble a été appelée dans un contexte qui n'accepte pas un ensemble" -#: plperl.c:2428 +#: plperl.c:2441 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "mode matérialisé requis mais interdit dans ce contexte" -#: plperl.c:2472 +#: plperl.c:2485 #, c-format msgid "set-returning PL/Perl function must return reference to array or use return_next" msgstr "" "la fonction PL/perl renvoyant des ensembles doit renvoyer la référence à\n" "un tableau ou utiliser return_next" -#: plperl.c:2593 +#: plperl.c:2606 #, c-format msgid "ignoring modified row in DELETE trigger" msgstr "ignore la ligne modifiée dans le trigger DELETE" -#: plperl.c:2601 +#: plperl.c:2614 #, c-format msgid "result of PL/Perl trigger function must be undef, \"SKIP\", or \"MODIFY\"" msgstr "" "le résultat de la fonction trigger PL/perl doit être undef, « SKIP » ou\n" "« MODIFY »" -#: plperl.c:2849 +#: plperl.c:2862 #, c-format msgid "trigger functions can only be called as triggers" msgstr "les fonctions trigger peuvent seulement être appelées par des triggers" -#: plperl.c:3209 +#: plperl.c:3220 #, c-format msgid "query result has too many rows to fit in a Perl array" msgstr "le résultat de la requête contient trop de lignes pour être intégré dans un tableau Perl" -#: plperl.c:3281 +#: plperl.c:3292 #, c-format msgid "cannot use return_next in a non-SETOF function" msgstr "ne peut pas utiliser return_next dans une fonction non SETOF" -#: plperl.c:3355 +#: plperl.c:3366 #, c-format msgid "SETOF-composite-returning PL/Perl function must call return_next with reference to hash" msgstr "" "une fonction PL/perl renvoyant des lignes composites doit appeler\n" "return_next avec la référence à un hachage" -#: plperl.c:4137 +#: plperl.c:4148 #, c-format msgid "PL/Perl function \"%s\"" msgstr "fonction PL/Perl « %s »" -#: plperl.c:4149 +#: plperl.c:4160 #, c-format msgid "compilation of PL/Perl function \"%s\"" msgstr "compilation de la fonction PL/Perl « %s »" -#: plperl.c:4158 +#: plperl.c:4169 #, c-format msgid "PL/Perl anonymous code block" msgstr "bloc de code PL/Perl anonyme" - -#~ msgid "PL/Perl function must return reference to hash or array" -#~ msgstr "la fonction PL/perl doit renvoyer la référence à un hachage ou à un tableau" - -#~ msgid "composite-returning PL/Perl function must return reference to hash" -#~ msgstr "" -#~ "la fonction PL/perl renvoyant des valeurs composites doit renvoyer la\n" -#~ "référence à un hachage" - -#~ msgid "creation of Perl function \"%s\" failed: %s" -#~ msgstr "échec de la création de la fonction Perl « %s » : %s" - -#~ msgid "error from Perl function \"%s\": %s" -#~ msgstr "échec dans la fonction Perl « %s » : %s" - -#~ msgid "out of memory" -#~ msgstr "mémoire épuisée" - -#~ msgid "while executing PLC_SAFE_OK" -#~ msgstr "lors de l'exécution de PLC_SAFE_OK" diff --git a/src/pl/plperl/po/ko.po b/src/pl/plperl/po/ko.po index 31c5f907b78d6..4d4cba5912f91 100644 --- a/src/pl/plperl/po/ko.po +++ b/src/pl/plperl/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: plperl (PostgreSQL) 16\n" +"Project-Id-Version: plperl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:39+0000\n" -"PO-Revision-Date: 2023-05-30 12:40+0900\n" +"POT-Creation-Date: 2025-01-17 04:39+0000\n" +"PO-Revision-Date: 2025-01-16 10:37+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -99,8 +99,8 @@ msgstr "다차원 배열에는 일치하는 차원이 포함된 배열 식이 #: plperl.c:1204 #, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "지정한 배열 크기(%d)가 최대치(%d)를 초과했습니다" +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "배열은 %d 차원 배열까지만 허용함" #: plperl.c:1274 #, c-format diff --git a/src/pl/plperl/po/meson.build b/src/pl/plperl/po/meson.build index 5e7c8523a011c..d0c3f62b780a5 100644 --- a/src/pl/plperl/po/meson.build +++ b/src/pl/plperl/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('plperl-' + pg_version_major.to_string())] diff --git a/src/pl/plperl/po/ru.po b/src/pl/plperl/po/ru.po index 75bf0ae67c5c9..8b47276a62056 100644 --- a/src/pl/plperl/po/ru.po +++ b/src/pl/plperl/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for plperl # Copyright (C) 2012-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2012-2017, 2019, 2022. +# Alexander Lakhin , 2012-2017, 2019, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: plperl (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2022-09-05 13:38+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 20:00+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -110,8 +110,8 @@ msgstr "" #: plperl.c:1204 #, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "число размерностей массива (%d) превышает предел (%d)" +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "число размерностей массива превышает предел (%d)" #: plperl.c:1274 #, c-format diff --git a/src/pl/plperl/po/sv.po b/src/pl/plperl/po/sv.po index 9494466513352..f16de78b9dfc0 100644 --- a/src/pl/plperl/po/sv.po +++ b/src/pl/plperl/po/sv.po @@ -2,14 +2,14 @@ # Copyright (C) 2014 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. # Mats Erik Andersson , 2014. -# Dennis Björklund 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 13:38+0000\n" -"PO-Revision-Date: 2023-03-09 22:40+0100\n" +"POT-Creation-Date: 2024-07-12 17:39+0000\n" +"PO-Revision-Date: 2024-07-12 22:07+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -18,210 +18,210 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: plperl.c:408 +#: plperl.c:405 msgid "If true, trusted and untrusted Perl code will be compiled in strict mode." msgstr "Om sant, tillförlitlig och otillförlitlig Perl-kod kommer kompileras i strikt läge." -#: plperl.c:422 +#: plperl.c:419 msgid "Perl initialization code to execute when a Perl interpreter is initialized." msgstr "Perl-kod för initialisering, utföres när perl-tolken förbereds." -#: plperl.c:444 +#: plperl.c:441 msgid "Perl initialization code to execute once when plperl is first used." msgstr "Perl-kod för engångs-initialisering då plperl används första gången." -#: plperl.c:452 +#: plperl.c:449 msgid "Perl initialization code to execute once when plperlu is first used." msgstr "Perl-kod för engångs-initialisering då plperlu används första gången." -#: plperl.c:646 +#: plperl.c:643 #, c-format msgid "cannot allocate multiple Perl interpreters on this platform" msgstr "kan inte utnyttja flera Perl-interpretorer på denna plattform" -#: plperl.c:669 plperl.c:853 plperl.c:859 plperl.c:976 plperl.c:988 -#: plperl.c:1031 plperl.c:1054 plperl.c:2138 plperl.c:2246 plperl.c:2314 -#: plperl.c:2377 +#: plperl.c:666 plperl.c:850 plperl.c:856 plperl.c:973 plperl.c:985 +#: plperl.c:1028 plperl.c:1051 plperl.c:2151 plperl.c:2259 plperl.c:2327 +#: plperl.c:2390 #, c-format msgid "%s" msgstr "%s" -#: plperl.c:670 +#: plperl.c:667 #, c-format msgid "while executing PostgreSQL::InServer::SPI::bootstrap" msgstr "vid utförande av PostgreSQL::InServer::SPI::bootstrap" -#: plperl.c:854 +#: plperl.c:851 #, c-format msgid "while parsing Perl initialization" msgstr "vid tolkning av perls initieringssteg" -#: plperl.c:860 +#: plperl.c:857 #, c-format msgid "while running Perl initialization" msgstr "vid utförande av perls initieringssteg" -#: plperl.c:977 +#: plperl.c:974 #, c-format msgid "while executing PLC_TRUSTED" msgstr "vid utförande av PLC_TRUSTED" -#: plperl.c:989 +#: plperl.c:986 #, c-format msgid "while executing utf8fix" msgstr "vid utförande av utf8fix" -#: plperl.c:1032 +#: plperl.c:1029 #, c-format msgid "while executing plperl.on_plperl_init" msgstr "vid utförande av plperl.on_plperl_init" -#: plperl.c:1055 +#: plperl.c:1052 #, c-format msgid "while executing plperl.on_plperlu_init" msgstr "vid utförande av plperl.on_plperlu_init" -#: plperl.c:1101 plperl.c:1791 +#: plperl.c:1098 plperl.c:1804 #, c-format msgid "Perl hash contains nonexistent column \"%s\"" msgstr "Perlhash innehåller en okänd kolumn \"%s\"." -#: plperl.c:1106 plperl.c:1796 +#: plperl.c:1103 plperl.c:1809 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "kan inte sätta systemattribut \"%s\"" -#: plperl.c:1194 -#, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "antalet array-dimensioner (%d) överskrider det maximalt tillåtna (%d)" - -#: plperl.c:1206 plperl.c:1223 +#: plperl.c:1199 plperl.c:1214 plperl.c:1231 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "flerdimensionella vektorer måste ha array-uttryck av passande dimensioner" -#: plperl.c:1259 +#: plperl.c:1204 +#, c-format +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "antal array-dimensioner överskriver maximalt tillåtna (%d)" + +#: plperl.c:1274 #, c-format msgid "cannot convert Perl array to non-array type %s" msgstr "kan inte omvandla perlvektor till icke-array av typ \"%s\"." -#: plperl.c:1362 +#: plperl.c:1375 #, c-format msgid "cannot convert Perl hash to non-composite type %s" msgstr "kan inte omvandla en perlhash till icke-composite-typ \"%s\"." -#: plperl.c:1384 plperl.c:3304 +#: plperl.c:1397 plperl.c:3315 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "en funktion med post som värde anropades i sammanhang där poster inte kan godtagas." -#: plperl.c:1445 +#: plperl.c:1458 #, c-format msgid "lookup failed for type %s" msgstr "uppslag misslyckades för typen \"%s\"" -#: plperl.c:1766 +#: plperl.c:1779 #, c-format msgid "$_TD->{new} does not exist" msgstr "$_TD->{new} finns inte." -#: plperl.c:1770 +#: plperl.c:1783 #, c-format msgid "$_TD->{new} is not a hash reference" msgstr "$_TD->{new} är inte en hash-referens." -#: plperl.c:1801 +#: plperl.c:1814 #, c-format msgid "cannot set generated column \"%s\"" msgstr "kan inte sätta genererad kolumn \"%s\"" -#: plperl.c:2013 plperl.c:2854 +#: plperl.c:2026 plperl.c:2867 #, c-format msgid "PL/Perl functions cannot return type %s" msgstr "Funktioner i PL/Perl kan inte svara med typ \"%s\"." -#: plperl.c:2026 plperl.c:2893 +#: plperl.c:2039 plperl.c:2906 #, c-format msgid "PL/Perl functions cannot accept type %s" msgstr "Funktioner i PL/Perl kan inte hantera typ \"%s\"." -#: plperl.c:2143 +#: plperl.c:2156 #, c-format msgid "didn't get a CODE reference from compiling function \"%s\"" msgstr "fick inte en CODE-referens vid kompilering av funktionen \"%s\"." -#: plperl.c:2234 +#: plperl.c:2247 #, c-format msgid "didn't get a return item from function" msgstr "fick inget returnvärde från funktion" -#: plperl.c:2278 plperl.c:2345 +#: plperl.c:2291 plperl.c:2358 #, c-format msgid "couldn't fetch $_TD" msgstr "kunde inte hämta $_TD" -#: plperl.c:2302 plperl.c:2365 +#: plperl.c:2315 plperl.c:2378 #, c-format msgid "didn't get a return item from trigger function" msgstr "fick inget returvärde från triggerfunktion" -#: plperl.c:2423 +#: plperl.c:2436 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "en funktion som returnerar en mängd anropades i kontext som inte godtar en mängd" -#: plperl.c:2428 +#: plperl.c:2441 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialiserat läge krävs, men stöds inte i detta kontext" -#: plperl.c:2472 +#: plperl.c:2485 #, c-format msgid "set-returning PL/Perl function must return reference to array or use return_next" msgstr "En mängd-returnerande funktion i PL/Perl måste göra det som referens eller med return_next." -#: plperl.c:2593 +#: plperl.c:2606 #, c-format msgid "ignoring modified row in DELETE trigger" msgstr "Lämnar ändrad rad orörd i en DELETE-triggning" -#: plperl.c:2601 +#: plperl.c:2614 #, c-format msgid "result of PL/Perl trigger function must be undef, \"SKIP\", or \"MODIFY\"" msgstr "resultat av en triggningsfunktion i PL/Perl måste vara undef, \"SKIP\" eller \"MODIFY\"." -#: plperl.c:2849 +#: plperl.c:2862 #, c-format msgid "trigger functions can only be called as triggers" msgstr "Triggningsfunktioner kan bara anropas vid triggning." -#: plperl.c:3209 +#: plperl.c:3220 #, c-format msgid "query result has too many rows to fit in a Perl array" msgstr "frågeresultatet har för många rader för att få plats i en Perl-array" -#: plperl.c:3281 +#: plperl.c:3292 #, c-format msgid "cannot use return_next in a non-SETOF function" msgstr "får inte nyttja return_next i funktion som ej är SETOF" -#: plperl.c:3355 +#: plperl.c:3366 #, c-format msgid "SETOF-composite-returning PL/Perl function must call return_next with reference to hash" msgstr "En funktion i PL/Perl med värderetur som SETOF måste anropa return_next med en hashreferens" -#: plperl.c:4137 +#: plperl.c:4148 #, c-format msgid "PL/Perl function \"%s\"" msgstr "PL/Perl-funktion \"%s\"." -#: plperl.c:4149 +#: plperl.c:4160 #, c-format msgid "compilation of PL/Perl function \"%s\"" msgstr "kompilering av PL/Perl-funktion \"%s\"" -#: plperl.c:4158 +#: plperl.c:4169 #, c-format msgid "PL/Perl anonymous code block" msgstr "Anonymt kodblock i PL/Perl." diff --git a/src/pl/plperl/po/uk.po b/src/pl/plperl/po/uk.po index 7951649694e8b..fcb64b7d80a99 100644 --- a/src/pl/plperl/po/uk.po +++ b/src/pl/plperl/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:39+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-02-24 00:09+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,213 +14,213 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/plperl.pot\n" -"X-Crowdin-File-ID: 920\n" +"X-Crowdin-File: /REL_17_STABLE/plperl.pot\n" +"X-Crowdin-File-ID: 1012\n" -#: plperl.c:408 +#: plperl.c:405 msgid "If true, trusted and untrusted Perl code will be compiled in strict mode." msgstr "Якщо увімкнено, надійний і ненадійний код Perl буде скомпільований в суворому режимі." -#: plperl.c:422 +#: plperl.c:419 msgid "Perl initialization code to execute when a Perl interpreter is initialized." msgstr "Виконати ініціалізаційний код під час ініціалізації інтерпретатора Perl." -#: plperl.c:444 +#: plperl.c:441 msgid "Perl initialization code to execute once when plperl is first used." msgstr "Виконати код ініціалізації один раз під час першого використання plperl." -#: plperl.c:452 +#: plperl.c:449 msgid "Perl initialization code to execute once when plperlu is first used." msgstr "Виконати код ініціалізації один раз під час першого використання plperlu." -#: plperl.c:646 +#: plperl.c:643 #, c-format msgid "cannot allocate multiple Perl interpreters on this platform" msgstr "не можна розмістити декілька Perl інтерпретаторів на цій платформі" -#: plperl.c:669 plperl.c:853 plperl.c:859 plperl.c:976 plperl.c:988 -#: plperl.c:1031 plperl.c:1054 plperl.c:2138 plperl.c:2246 plperl.c:2314 -#: plperl.c:2377 +#: plperl.c:666 plperl.c:850 plperl.c:856 plperl.c:973 plperl.c:985 +#: plperl.c:1028 plperl.c:1051 plperl.c:2151 plperl.c:2259 plperl.c:2327 +#: plperl.c:2390 #, c-format msgid "%s" msgstr "%s" -#: plperl.c:670 +#: plperl.c:667 #, c-format msgid "while executing PostgreSQL::InServer::SPI::bootstrap" msgstr "під час виконання PostgreSQL::InServer::SPI::bootstrap" -#: plperl.c:854 +#: plperl.c:851 #, c-format msgid "while parsing Perl initialization" msgstr "під час обробки ініціалізації Perl" -#: plperl.c:860 +#: plperl.c:857 #, c-format msgid "while running Perl initialization" msgstr "під час запуску Perl ініціалізації" -#: plperl.c:977 +#: plperl.c:974 #, c-format msgid "while executing PLC_TRUSTED" msgstr "під час виконання PLC_TRUSTED" -#: plperl.c:989 +#: plperl.c:986 #, c-format msgid "while executing utf8fix" msgstr "під час виконання utf8fix" -#: plperl.c:1032 +#: plperl.c:1029 #, c-format msgid "while executing plperl.on_plperl_init" msgstr "під час виконання plperl.on_plperl_init" -#: plperl.c:1055 +#: plperl.c:1052 #, c-format msgid "while executing plperl.on_plperlu_init" msgstr "під час виконання plperl.on_plperlu_init" -#: plperl.c:1101 plperl.c:1791 +#: plperl.c:1098 plperl.c:1804 #, c-format msgid "Perl hash contains nonexistent column \"%s\"" msgstr "хеш Perl містить неіснуючу колонку \"%s\"" -#: plperl.c:1106 plperl.c:1796 +#: plperl.c:1103 plperl.c:1809 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "не вдалося встановити системний атрибут \"%s\"" -#: plperl.c:1194 -#, c-format -msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -msgstr "число вимірів масива (%d) перевищує ліміт (%d)" - -#: plperl.c:1206 plperl.c:1223 +#: plperl.c:1199 plperl.c:1214 plperl.c:1231 #, c-format msgid "multidimensional arrays must have array expressions with matching dimensions" msgstr "для багатовимірних масивів повинні задаватись вирази з відповідними вимірами" -#: plperl.c:1259 +#: plperl.c:1204 +#, c-format +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "кількість вимірів масиву перевищує максимально дозволену (%d)" + +#: plperl.c:1274 #, c-format msgid "cannot convert Perl array to non-array type %s" msgstr "неможливо конвертувати масив Perl у тип не масиву %s" -#: plperl.c:1362 +#: plperl.c:1375 #, c-format msgid "cannot convert Perl hash to non-composite type %s" msgstr "неможливо конвертувати хеш Perl у нескладений тип %s" -#: plperl.c:1384 plperl.c:3304 +#: plperl.c:1397 plperl.c:3315 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "функція, що повертає набір, викликана у контексті, що не приймає тип запис" -#: plperl.c:1445 +#: plperl.c:1458 #, c-format msgid "lookup failed for type %s" msgstr "неможливо фільтрувати для типу %s" -#: plperl.c:1766 +#: plperl.c:1779 #, c-format msgid "$_TD->{new} does not exist" msgstr "$_TD->{new} не існує" -#: plperl.c:1770 +#: plperl.c:1783 #, c-format msgid "$_TD->{new} is not a hash reference" msgstr "$_TD->{new} не є посиланням на хеш" -#: plperl.c:1801 +#: plperl.c:1814 #, c-format msgid "cannot set generated column \"%s\"" msgstr "неможливо оновити згенерований стовпець \"%s\"" -#: plperl.c:2013 plperl.c:2854 +#: plperl.c:2026 plperl.c:2867 #, c-format msgid "PL/Perl functions cannot return type %s" msgstr "функції PL/Perl не можуть повертати тип %s" -#: plperl.c:2026 plperl.c:2893 +#: plperl.c:2039 plperl.c:2906 #, c-format msgid "PL/Perl functions cannot accept type %s" msgstr "функції PL/Perl не можуть приймати тип %s" -#: plperl.c:2143 +#: plperl.c:2156 #, c-format msgid "didn't get a CODE reference from compiling function \"%s\"" msgstr "не отримано посилання CODE з функції компіляції \"%s\"" -#: plperl.c:2234 +#: plperl.c:2247 #, c-format msgid "didn't get a return item from function" msgstr "не отримано елемент результату з функції" -#: plperl.c:2278 plperl.c:2345 +#: plperl.c:2291 plperl.c:2358 #, c-format msgid "couldn't fetch $_TD" msgstr "не вдалось отримати $_TD" -#: plperl.c:2302 plperl.c:2365 +#: plperl.c:2315 plperl.c:2378 #, c-format msgid "didn't get a return item from trigger function" msgstr "не отримано елемент результату з функції-тригеру" -#: plperl.c:2423 +#: plperl.c:2436 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "функція \"set-valued\" викликана в контексті, де йому немає місця" -#: plperl.c:2428 +#: plperl.c:2441 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "необхідний режим матеріалізації (materialize mode), але він неприпустимий у цьому контексті" -#: plperl.c:2472 +#: plperl.c:2485 #, c-format msgid "set-returning PL/Perl function must return reference to array or use return_next" msgstr "функція PL/Perl, що вертає набір значень, повинна посилатися на масив або використовувати return_next" -#: plperl.c:2593 +#: plperl.c:2606 #, c-format msgid "ignoring modified row in DELETE trigger" msgstr "ігнорується змінений рядок у тригері DELETE" -#: plperl.c:2601 +#: plperl.c:2614 #, c-format msgid "result of PL/Perl trigger function must be undef, \"SKIP\", or \"MODIFY\"" msgstr "результат тригерної функції PL/Perl повинен бути undef, \"SKIP\" або \"MODIFY\"" -#: plperl.c:2849 +#: plperl.c:2862 #, c-format msgid "trigger functions can only be called as triggers" msgstr "тригер-функція може викликатися лише як тригер" -#: plperl.c:3209 +#: plperl.c:3220 #, c-format msgid "query result has too many rows to fit in a Perl array" msgstr "результат запиту має забагато рядків для відповідності в масиві Perl" -#: plperl.c:3281 +#: plperl.c:3292 #, c-format msgid "cannot use return_next in a non-SETOF function" msgstr "не можна використовувати return_next в функціях, що не повертають набори даних" -#: plperl.c:3355 +#: plperl.c:3366 #, c-format msgid "SETOF-composite-returning PL/Perl function must call return_next with reference to hash" msgstr "Функція PL/Perl, що повертає набір композитних даних, повинна викликати return_next з посиланням на хеш" -#: plperl.c:4137 +#: plperl.c:4148 #, c-format msgid "PL/Perl function \"%s\"" msgstr "PL/Perl функція \"%s\"" -#: plperl.c:4149 +#: plperl.c:4160 #, c-format msgid "compilation of PL/Perl function \"%s\"" msgstr "компіляція функції PL/Perl \"%s\"" -#: plperl.c:4158 +#: plperl.c:4169 #, c-format msgid "PL/Perl anonymous code block" msgstr "анонімний блок коду PL/Perl" diff --git a/src/pl/plperl/sql/plperl_env.sql b/src/pl/plperl/sql/plperl_env.sql new file mode 100644 index 0000000000000..fa5f04146cccb --- /dev/null +++ b/src/pl/plperl/sql/plperl_env.sql @@ -0,0 +1,61 @@ +-- +-- Test the environment setting +-- + +-- directory path and dlsuffix are passed to us in environment variables +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX + +\set regresslib :libdir '/regress' :dlsuffix + +CREATE FUNCTION get_environ() + RETURNS text[] + AS :'regresslib', 'get_environ' + LANGUAGE C STRICT; + +-- fetch the process environment + +CREATE FUNCTION process_env () RETURNS text[] +LANGUAGE plpgsql AS +$$ + +declare + res text[]; + tmp text[]; + f record; +begin + for f in select unnest(get_environ()) as t loop + tmp := regexp_split_to_array(f.t, '='); + if array_length(tmp, 1) = 2 then + res := res || tmp; + end if; + end loop; + return res; +end + +$$; + +-- plperl should not be able to affect the process environment + +DO +$$ + $ENV{TEST_PLPERL_ENV_FOO} = "shouldfail"; + untie %ENV; + $ENV{TEST_PLPERL_ENV_FOO} = "testval"; + my $penv = spi_exec_query("select unnest(process_env()) as pe"); + my %received; + for (my $f = 0; $f < $penv->{processed}; $f += 2) + { + my $k = $penv->{rows}[$f]->{pe}; + my $v = $penv->{rows}[$f+1]->{pe}; + $received{$k} = $v; + } + unless (exists $received{TEST_PLPERL_ENV_FOO}) + { + elog(NOTICE, "environ unaffected") + } + +$$ LANGUAGE plperl; + +-- clean up to simplify cross-version upgrade testing +DROP FUNCTION get_environ(); diff --git a/src/pl/plperl/sql/plperl_trigger.sql b/src/pl/plperl/sql/plperl_trigger.sql index 4adddeb80ac58..2798a02fa12ea 100644 --- a/src/pl/plperl/sql/plperl_trigger.sql +++ b/src/pl/plperl/sql/plperl_trigger.sql @@ -10,7 +10,8 @@ CREATE TABLE trigger_test ( CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger LANGUAGE plperl AS $$ diff --git a/src/pl/plperl/text2macro.pl b/src/pl/plperl/text2macro.pl index c6240af69c7d7..3c9c70ae223c8 100644 --- a/src/pl/plperl/text2macro.pl +++ b/src/pl/plperl/text2macro.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # src/pl/plperl/text2macro.pl @@ -15,14 +15,13 @@ =head1 SYNOPSIS --prefix=S - add prefix S to the names of the macros --name=S - use S as the macro name (assumes only one file) - --strip=S - don't include lines that match perl regex S =head1 DESCRIPTION Reads one or more text files and outputs a corresponding series of C pre-processor macro definitions. Each macro defines a string literal that contains the contents of the corresponding text file. The basename of the text -file as capitalized and used as the name of the macro, along with an optional prefix. +file is capitalized and used as the name of the macro, along with an optional prefix. =cut @@ -34,9 +33,12 @@ =head1 DESCRIPTION GetOptions( 'prefix=s' => \my $opt_prefix, 'name=s' => \my $opt_name, - 'strip=s' => \my $opt_strip, 'selftest!' => sub { exit selftest() },) or exit 1; +# This was once a command-line option, but meson is obstreperous +# about passing backslashes through custom targets. +my $opt_strip = '^(#.*|\s*)$'; + die "No text files specified" unless @ARGV; diff --git a/src/pl/plpgsql/meson.build b/src/pl/plpgsql/meson.build index 2f787d6387896..db9a73fd77175 100644 --- a/src/pl/plpgsql/meson.build +++ b/src/pl/plpgsql/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('src') diff --git a/src/pl/plpgsql/src/expected/plpgsql_array.out b/src/pl/plpgsql/src/expected/plpgsql_array.out index ad60e0e8be37a..4c6b3ce998ab8 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_array.out +++ b/src/pl/plpgsql/src/expected/plpgsql_array.out @@ -52,6 +52,16 @@ NOTICE: a = ("{""(,11)""}",), a.c1[1].i = 11 do $$ declare a int[]; begin a := array_agg(x) from (values(1),(2),(3)) v(x); raise notice 'a = %', a; end$$; NOTICE: a = {1,2,3} +do $$ declare a int[] := array[1,2,3]; +begin + -- test scenarios for optimization of updates of R/W expanded objects + a := array_append(a, 42); -- optimizable using "transfer" method + a := a || a[3]; -- optimizable using "inplace" method + a := a[1] || a; -- ditto, but let's test array_prepend + a := a || a; -- not optimizable + raise notice 'a = %', a; +end$$; +NOTICE: a = {1,1,2,3,42,3,1,1,2,3,42,3} create temp table onecol as select array[1,2] as f1; do $$ declare a int[]; begin a := f1 from onecol; raise notice 'a = %', a; end$$; diff --git a/src/pl/plpgsql/src/expected/plpgsql_call.out b/src/pl/plpgsql/src/expected/plpgsql_call.out index 0a63b1d44ef16..ea7107dca0d90 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_call.out +++ b/src/pl/plpgsql/src/expected/plpgsql_call.out @@ -597,6 +597,26 @@ NOTICE: f_get_x(1) NOTICE: f_print_x(1) NOTICE: f_get_x(2) NOTICE: f_print_x(2) +-- test in non-atomic context, except exception block is locally atomic +DO $$ +BEGIN + BEGIN + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + EXCEPTION WHEN division_by_zero THEN + RAISE NOTICE '%', SQLERRM; + END; + ROLLBACK; +END +$$; +NOTICE: f_get_x(1) +NOTICE: f_print_x(1) +NOTICE: f_get_x(2) +NOTICE: f_print_x(2) -- test in atomic context BEGIN; DO $$ diff --git a/src/pl/plpgsql/src/expected/plpgsql_record.out b/src/pl/plpgsql/src/expected/plpgsql_record.out index a9b5b778efcc7..e5de7143606ab 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_record.out +++ b/src/pl/plpgsql/src/expected/plpgsql_record.out @@ -28,7 +28,7 @@ create or replace function retc(int) returns two_int8s language plpgsql as $$ begin return row($1,1); end $$; select retc(42); ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 1. +DETAIL: Returned type integer does not match expected type bigint in column "q1" (position 1). CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type -- nor extra columns create or replace function retc(int) returns two_int8s language plpgsql as @@ -50,7 +50,7 @@ create or replace function retc(int) returns two_int8s language plpgsql as $$ declare r record; begin r := row($1,1); return r; end $$; select retc(42); ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 1. +DETAIL: Returned type integer does not match expected type bigint in column "q1" (position 1). CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type create or replace function retc(int) returns two_int8s language plpgsql as $$ declare r record; begin r := row($1::int8, 1::int8, 42); return r; end $$; @@ -272,7 +272,7 @@ NOTICE: r1.q1 = NOTICE: r1.q2 = NOTICE: r1 = ERROR: record "r1" has no field "nosuchfield" -CONTEXT: SQL expression "r1.nosuchfield" +CONTEXT: PL/pgSQL expression "r1.nosuchfield" PL/pgSQL function inline_code_block line 7 at RAISE -- records, not so much do $$ @@ -286,7 +286,7 @@ end$$; NOTICE: r1 = ERROR: record "r1" is not assigned yet DETAIL: The tuple structure of a not-yet-assigned record is indeterminate. -CONTEXT: SQL expression "r1.f1" +CONTEXT: PL/pgSQL expression "r1.f1" PL/pgSQL function inline_code_block line 5 at RAISE -- but OK if you assign first do $$ @@ -304,7 +304,7 @@ NOTICE: r1.f1 = 1 NOTICE: r1.f2 = 2 NOTICE: r1 = (1,2) ERROR: record "r1" has no field "nosuchfield" -CONTEXT: SQL expression "r1.nosuchfield" +CONTEXT: PL/pgSQL expression "r1.nosuchfield" PL/pgSQL function inline_code_block line 9 at RAISE -- check %type with block-qualified variable names do $$ @@ -386,7 +386,7 @@ DETAIL: Number of returned columns (2) does not match expected column count (3) CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type select * from returnsrecord(42) as r(x int, y bigint); -- fail ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 2. +DETAIL: Returned type integer does not match expected type bigint in column "y" (position 2). CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type -- same with an intermediate record variable create or replace function returnsrecord(int) returns record language plpgsql as @@ -409,7 +409,7 @@ DETAIL: Number of returned columns (2) does not match expected column count (3) CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type select * from returnsrecord(42) as r(x int, y bigint); -- fail ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 2. +DETAIL: Returned type integer does not match expected type bigint in column "y" (position 2). CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type -- should work the same with a missing column in the actual result value create table has_hole(f1 int, f2 int, f3 int); @@ -434,7 +434,7 @@ DETAIL: Number of returned columns (2) does not match expected column count (3) CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type select * from returnsrecord(42) as r(x int, y bigint); -- fail ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 2. +DETAIL: Returned type integer does not match expected type bigint in column "y" (position 2). CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type -- same with an intermediate record variable create or replace function returnsrecord(int) returns record language plpgsql as @@ -457,7 +457,7 @@ DETAIL: Number of returned columns (2) does not match expected column count (3) CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type select * from returnsrecord(42) as r(x int, y bigint); -- fail ERROR: returned record type does not match expected record type -DETAIL: Returned type integer does not match expected type bigint in column 2. +DETAIL: Returned type integer does not match expected type bigint in column "y" (position 2). CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type -- check access to a field of an argument declared "record" create function getf1(x record) returns int language plpgsql as @@ -545,6 +545,7 @@ begin return next h; return next row(5,6); return next row(7,8)::has_hole; + return query select 9, 10; end$$; select returnssetofholes(); returnssetofholes @@ -554,7 +555,8 @@ select returnssetofholes(); (3,4) (5,6) (7,8) -(5 rows) + (9,10) +(6 rows) create or replace function returnssetofholes() returns setof has_hole language plpgsql as $$ @@ -575,6 +577,16 @@ select returnssetofholes(); ERROR: returned record type does not match expected record type DETAIL: Number of returned columns (3) does not match expected column count (2). CONTEXT: PL/pgSQL function returnssetofholes() line 3 at RETURN NEXT +create or replace function returnssetofholes() returns setof has_hole language plpgsql as +$$ +begin + return query select 1, 2.0; -- fails +end$$; +select returnssetofholes(); +ERROR: structure of query does not match function result type +DETAIL: Returned type numeric does not match expected type integer in column "f3" (position 2). +CONTEXT: SQL statement "select 1, 2.0" +PL/pgSQL function returnssetofholes() line 3 at RETURN QUERY -- check behavior with changes of a named rowtype create table mutable(f1 int, f2 text); create function sillyaddone(int) returns int language plpgsql as @@ -598,7 +610,7 @@ create function getf3(x mutable) returns int language plpgsql as $$ begin return x.f3; end $$; select getf3(null::mutable); -- doesn't work yet ERROR: record "x" has no field "f3" -CONTEXT: SQL expression "x.f3" +CONTEXT: PL/pgSQL expression "x.f3" PL/pgSQL function getf3(mutable) line 1 at RETURN alter table mutable add column f3 int; select getf3(null::mutable); -- now it works diff --git a/src/pl/plpgsql/src/expected/plpgsql_simple.out b/src/pl/plpgsql/src/expected/plpgsql_simple.out index 7b22e60f1984f..da351873e742e 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_simple.out +++ b/src/pl/plpgsql/src/expected/plpgsql_simple.out @@ -118,3 +118,14 @@ select simplecaller(); 44 (1 row) +-- Check handling of simple expression in a scrollable cursor (bug #18859) +do $$ +declare + p_CurData refcursor; + val int; +begin + open p_CurData scroll for select 42; + fetch p_CurData into val; + raise notice 'val = %', val; +end; $$; +NOTICE: val = 42 diff --git a/src/pl/plpgsql/src/expected/plpgsql_varprops.out b/src/pl/plpgsql/src/expected/plpgsql_varprops.out index 25115a02bd85f..958d7bca9a772 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_varprops.out +++ b/src/pl/plpgsql/src/expected/plpgsql_varprops.out @@ -76,7 +76,7 @@ begin raise notice 'x = %', x; end$$; ERROR: division by zero -CONTEXT: SQL expression "1/0" +CONTEXT: PL/pgSQL expression "1/0" PL/pgSQL function inline_code_block line 2 during statement block local variable initialization do $$ declare x bigint[] := array[1,3,5]; diff --git a/src/pl/plpgsql/src/generate-plerrcodes.pl b/src/pl/plpgsql/src/generate-plerrcodes.pl index 1c662bc967c4d..7719432325375 100644 --- a/src/pl/plpgsql/src/generate-plerrcodes.pl +++ b/src/pl/plpgsql/src/generate-plerrcodes.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the plerrcodes.h header from errcodes.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/pl/plpgsql/src/meson.build b/src/pl/plpgsql/src/meson.build index 3dd734b776b1b..33c49ac25d946 100644 --- a/src/pl/plpgsql/src/meson.build +++ b/src/pl/plpgsql/src/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group plpgsql_sources = files( 'pl_comp.c', diff --git a/src/pl/plpgsql/src/nls.mk b/src/pl/plpgsql/src/nls.mk index e1d3bde6c373a..dd1c1e1440f4b 100644 --- a/src/pl/plpgsql/src/nls.mk +++ b/src/pl/plpgsql/src/nls.mk @@ -6,5 +6,5 @@ GETTEXT_FILES = pl_comp.c \ pl_funcs.c \ pl_handler.c \ pl_scanner.c -GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS) yyerror plpgsql_yyerror +GETTEXT_TRIGGERS = $(BACKEND_COMMON_GETTEXT_TRIGGERS) yyerror:4 plpgsql_yyerror:4 GETTEXT_FLAGS = $(BACKEND_COMMON_GETTEXT_FLAGS) diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index f1bce708d62d1..b80c59447fb57 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -3,7 +3,7 @@ * pl_comp.c - Compiler part of the PL/pgSQL * procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -23,7 +23,7 @@ #include "catalog/pg_type.h" #include "funcapi.h" #include "nodes/makefuncs.h" -#include "parser/parse_type.h" +#include "parser/parse_node.h" #include "plpgsql.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -31,7 +31,6 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/regproc.h" -#include "utils/rel.h" #include "utils/syscache.h" #include "utils/typcache.h" @@ -39,8 +38,6 @@ * Our own local and global variables * ---------- */ -PLpgSQL_stmt_block *plpgsql_parse_result; - static int datums_alloc; int plpgsql_nDatums; PLpgSQL_datum **plpgsql_Datums; @@ -55,20 +52,6 @@ PLpgSQL_function *plpgsql_curr_compile; /* A context appropriate for short-term allocs during compilation */ MemoryContext plpgsql_compile_tmp_cxt; -/* ---------- - * Hash table for compiled functions - * ---------- - */ -static HTAB *plpgsql_HashTable = NULL; - -typedef struct plpgsql_hashent -{ - PLpgSQL_func_hashkey key; - PLpgSQL_function *function; -} plpgsql_HashEnt; - -#define FUNCS_PER_USER 128 /* initial table size */ - /* ---------- * Lookup table for EXCEPTION condition names * ---------- @@ -80,7 +63,7 @@ typedef struct } ExceptionLabelMap; static const ExceptionLabelMap exception_label_map[] = { -#include "plerrcodes.h" /* pgrminclude ignore */ +#include "plerrcodes.h" {NULL, 0} }; @@ -89,11 +72,11 @@ static const ExceptionLabelMap exception_label_map[] = { * static prototypes * ---------- */ -static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo, - HeapTuple procTup, - PLpgSQL_function *function, - PLpgSQL_func_hashkey *hashkey, - bool forValidator); +static void plpgsql_compile_callback(FunctionCallInfo fcinfo, + HeapTuple procTup, + const CachedFunctionHashKey *hashkey, + CachedFunction *cfunc, + bool forValidator); static void plpgsql_compile_error_callback(void *arg); static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name); static void add_dummy_return(PLpgSQL_function *function); @@ -108,19 +91,6 @@ static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname); static void plpgsql_start_datums(void); static void plpgsql_finish_datums(PLpgSQL_function *function); -static void compute_function_hashkey(FunctionCallInfo fcinfo, - Form_pg_proc procStruct, - PLpgSQL_func_hashkey *hashkey, - bool forValidator); -static void plpgsql_resolve_polymorphic_argtypes(int numargs, - Oid *argtypes, char *argmodes, - Node *call_expr, bool forValidator, - const char *proname); -static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key); -static void plpgsql_HashTableInsert(PLpgSQL_function *function, - PLpgSQL_func_hashkey *func_key); -static void plpgsql_HashTableDelete(PLpgSQL_function *function); -static void delete_function(PLpgSQL_function *func); /* ---------- * plpgsql_compile Make an execution tree for a PL/pgSQL function. @@ -135,102 +105,29 @@ static void delete_function(PLpgSQL_function *func); PLpgSQL_function * plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator) { - Oid funcOid = fcinfo->flinfo->fn_oid; - HeapTuple procTup; - Form_pg_proc procStruct; PLpgSQL_function *function; - PLpgSQL_func_hashkey hashkey; - bool function_valid = false; - bool hashkey_valid = false; /* - * Lookup the pg_proc tuple by Oid; we'll need it in any case + * funccache.c manages re-use of existing PLpgSQL_function caches. + * + * In PL/pgSQL we use fn_extra directly as the pointer to the long-lived + * function cache entry; we have no need for any query-lifespan cache. + * Also, we don't need to make the cache key depend on composite result + * type (at least for now). */ - procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid)); - if (!HeapTupleIsValid(procTup)) - elog(ERROR, "cache lookup failed for function %u", funcOid); - procStruct = (Form_pg_proc) GETSTRUCT(procTup); - - /* - * See if there's already a cache entry for the current FmgrInfo. If not, - * try to find one in the hash table. - */ - function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra; - -recheck: - if (!function) - { - /* Compute hashkey using function signature and actual arg types */ - compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator); - hashkey_valid = true; - - /* And do the lookup */ - function = plpgsql_HashTableLookup(&hashkey); - } - - if (function) - { - /* We have a compiled function, but is it still valid? */ - if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) && - ItemPointerEquals(&function->fn_tid, &procTup->t_self)) - function_valid = true; - else - { - /* - * Nope, so remove it from hashtable and try to drop associated - * storage (if not done already). - */ - delete_function(function); - - /* - * If the function isn't in active use then we can overwrite the - * func struct with new data, allowing any other existing fn_extra - * pointers to make use of the new definition on their next use. - * If it is in use then just leave it alone and make a new one. - * (The active invocations will run to completion using the - * previous definition, and then the cache entry will just be - * leaked; doesn't seem worth adding code to clean it up, given - * what a corner case this is.) - * - * If we found the function struct via fn_extra then it's possible - * a replacement has already been made, so go back and recheck the - * hashtable. - */ - if (function->use_count != 0) - { - function = NULL; - if (!hashkey_valid) - goto recheck; - } - } - } - - /* - * If the function wasn't found or was out-of-date, we have to compile it - */ - if (!function_valid) - { - /* - * Calculate hashkey if we didn't already; we'll need it to store the - * completed function. - */ - if (!hashkey_valid) - compute_function_hashkey(fcinfo, procStruct, &hashkey, - forValidator); - - /* - * Do the hard part. - */ - function = do_compile(fcinfo, procTup, function, - &hashkey, forValidator); - } - - ReleaseSysCache(procTup); + function = (PLpgSQL_function *) + cached_function_compile(fcinfo, + fcinfo->flinfo->fn_extra, + plpgsql_compile_callback, + plpgsql_delete_callback, + sizeof(PLpgSQL_function), + false, + forValidator); /* * Save pointer in FmgrInfo to avoid search on subsequent calls */ - fcinfo->flinfo->fn_extra = (void *) function; + fcinfo->flinfo->fn_extra = function; /* * Finally return the compiled function @@ -238,11 +135,17 @@ plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator) return function; } +struct compile_error_callback_arg +{ + const char *proc_source; + yyscan_t yyscanner; +}; + /* * This is the slow part of plpgsql_compile(). * - * The passed-in "function" pointer is either NULL or an already-allocated - * function struct to overwrite. + * The passed-in "cfunc" struct is expected to be zeroes, except + * for the CachedFunction fields, which we don't touch here. * * While compiling a function, the CurrentMemoryContext is the * per-function memory context of the function we are compiling. That @@ -260,16 +163,18 @@ plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator) * NB: this code is not re-entrant. We assume that nothing we do here could * result in the invocation of another plpgsql function. */ -static PLpgSQL_function * -do_compile(FunctionCallInfo fcinfo, - HeapTuple procTup, - PLpgSQL_function *function, - PLpgSQL_func_hashkey *hashkey, - bool forValidator) +static void +plpgsql_compile_callback(FunctionCallInfo fcinfo, + HeapTuple procTup, + const CachedFunctionHashKey *hashkey, + CachedFunction *cfunc, + bool forValidator) { + PLpgSQL_function *function = (PLpgSQL_function *) cfunc; Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup); bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo); bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo); + yyscan_t scanner; Datum prosrcdatum; char *proc_source; HeapTuple typeTup; @@ -277,6 +182,7 @@ do_compile(FunctionCallInfo fcinfo, PLpgSQL_variable *var; PLpgSQL_rec *rec; int i; + struct compile_error_callback_arg cbarg; ErrorContextCallback plerrcontext; int parse_rc; Oid rettypeid; @@ -291,21 +197,21 @@ do_compile(FunctionCallInfo fcinfo, MemoryContext func_cxt; /* - * Setup the scanner input and error info. We assume that this function - * cannot be invoked recursively, so there's no need to save and restore - * the static variables used here. + * Setup the scanner input and error info. */ prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup, Anum_pg_proc_prosrc); proc_source = TextDatumGetCString(prosrcdatum); - plpgsql_scanner_init(proc_source); + scanner = plpgsql_scanner_init(proc_source); plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname)); /* * Setup error traceback support for ereport() */ + cbarg.proc_source = forValidator ? proc_source : NULL; + cbarg.yyscanner = scanner; plerrcontext.callback = plpgsql_compile_error_callback; - plerrcontext.arg = forValidator ? proc_source : NULL; + plerrcontext.arg = &cbarg; plerrcontext.previous = error_context_stack; error_context_stack = &plerrcontext; @@ -315,28 +221,18 @@ do_compile(FunctionCallInfo fcinfo, * reasons. */ plpgsql_check_syntax = forValidator; - - /* - * Create the new function struct, if not done already. The function - * structs are never thrown away, so keep them in TopMemoryContext. - */ - if (function == NULL) - { - function = (PLpgSQL_function *) - MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function)); - } - else - { - /* re-using a previously existing struct, so clear it out */ - memset(function, 0, sizeof(PLpgSQL_function)); - } plpgsql_curr_compile = function; /* * All the permanent output of compilation (e.g. parse tree) is kept in a * per-function memory context, so it can be reclaimed easily. + * + * While the func_cxt needs to be long-lived, we initially make it a child + * of the assumed-short-lived caller's context, and reparent it under + * CacheMemoryContext only upon success. This arrangement avoids memory + * leakage during compilation of a faulty function. */ - func_cxt = AllocSetContextCreate(TopMemoryContext, + func_cxt = AllocSetContextCreate(CurrentMemoryContext, "PL/pgSQL function", ALLOCSET_DEFAULT_SIZES); plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt); @@ -344,8 +240,6 @@ do_compile(FunctionCallInfo fcinfo, function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid); MemoryContextSetIdentifier(func_cxt, function->fn_signature); function->fn_oid = fcinfo->flinfo->fn_oid; - function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data); - function->fn_tid = procTup->t_self; function->fn_input_collation = fcinfo->fncollation; function->fn_cxt = func_cxt; function->out_param_varno = -1; /* set up for no OUT param */ @@ -366,6 +260,7 @@ do_compile(FunctionCallInfo fcinfo, function->nstatements = 0; function->requires_procedure_resowner = false; + function->has_exception_block = false; /* * Initialize the compiler, particularly the namespace stack. The @@ -394,10 +289,10 @@ do_compile(FunctionCallInfo fcinfo, numargs = get_func_arg_info(procTup, &argtypes, &argnames, &argmodes); - plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes, - fcinfo->flinfo->fn_expr, - forValidator, - plpgsql_error_funcname); + cfunc_resolve_polymorphic_argtypes(numargs, argtypes, argmodes, + fcinfo->flinfo->fn_expr, + forValidator, + plpgsql_error_funcname); in_arg_varnos = (int *) palloc(numargs * sizeof(int)); out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *)); @@ -780,12 +675,11 @@ do_compile(FunctionCallInfo fcinfo, /* * Now parse the function's text */ - parse_rc = plpgsql_yyparse(); + parse_rc = plpgsql_yyparse(&function->action, scanner); if (parse_rc != 0) elog(ERROR, "plpgsql parser returned %d", parse_rc); - function->action = plpgsql_parse_result; - plpgsql_scanner_finish(); + plpgsql_scanner_finish(scanner); pfree(proc_source); /* @@ -807,14 +701,17 @@ do_compile(FunctionCallInfo fcinfo, plpgsql_finish_datums(function); + if (function->has_exception_block) + plpgsql_mark_local_assignment_targets(function); + /* Debug dump for completed functions */ if (plpgsql_DumpExecTree) plpgsql_dumptree(function); /* - * add it to the hash table + * All is well, so make the func_cxt long-lived */ - plpgsql_HashTableInsert(function, hashkey); + MemoryContextSetParent(func_cxt, CacheMemoryContext); /* * Pop the error context stack @@ -826,14 +723,13 @@ do_compile(FunctionCallInfo fcinfo, MemoryContextSwitchTo(plpgsql_compile_tmp_cxt); plpgsql_compile_tmp_cxt = NULL; - return function; } /* ---------- * plpgsql_compile_inline Make an execution tree for an anonymous code block. * - * Note: this is generally parallel to do_compile(); is it worth trying to - * merge the two? + * Note: this is generally parallel to plpgsql_compile_callback(); is it worth + * trying to merge the two? * * Note: we assume the block will be thrown away so there is no need to build * persistent data structures. @@ -842,27 +738,29 @@ do_compile(FunctionCallInfo fcinfo, PLpgSQL_function * plpgsql_compile_inline(char *proc_source) { + yyscan_t scanner; char *func_name = "inline_code_block"; PLpgSQL_function *function; + struct compile_error_callback_arg cbarg; ErrorContextCallback plerrcontext; PLpgSQL_variable *var; int parse_rc; MemoryContext func_cxt; /* - * Setup the scanner input and error info. We assume that this function - * cannot be invoked recursively, so there's no need to save and restore - * the static variables used here. + * Setup the scanner input and error info. */ - plpgsql_scanner_init(proc_source); + scanner = plpgsql_scanner_init(proc_source); plpgsql_error_funcname = func_name; /* * Setup error traceback support for ereport() */ + cbarg.proc_source = proc_source; + cbarg.yyscanner = scanner; plerrcontext.callback = plpgsql_compile_error_callback; - plerrcontext.arg = proc_source; + plerrcontext.arg = &cbarg; plerrcontext.previous = error_context_stack; error_context_stack = &plerrcontext; @@ -900,6 +798,7 @@ plpgsql_compile_inline(char *proc_source) function->nstatements = 0; function->requires_procedure_resowner = false; + function->has_exception_block = false; plpgsql_ns_init(); plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK); @@ -936,12 +835,11 @@ plpgsql_compile_inline(char *proc_source) /* * Now parse the function's text */ - parse_rc = plpgsql_yyparse(); + parse_rc = plpgsql_yyparse(&function->action, scanner); if (parse_rc != 0) elog(ERROR, "plpgsql parser returned %d", parse_rc); - function->action = plpgsql_parse_result; - plpgsql_scanner_finish(); + plpgsql_scanner_finish(scanner); /* * If it returns VOID (always true at the moment), we allow control to @@ -957,6 +855,13 @@ plpgsql_compile_inline(char *proc_source) plpgsql_finish_datums(function); + if (function->has_exception_block) + plpgsql_mark_local_assignment_targets(function); + + /* Debug dump for completed functions */ + if (plpgsql_DumpExecTree) + plpgsql_dumptree(function); + /* * Pop the error context stack */ @@ -979,13 +884,16 @@ plpgsql_compile_inline(char *proc_source) static void plpgsql_compile_error_callback(void *arg) { - if (arg) + struct compile_error_callback_arg *cbarg = (struct compile_error_callback_arg *) arg; + yyscan_t yyscanner = cbarg->yyscanner; + + if (cbarg->proc_source) { /* * Try to convert syntax error position to reference text of original * CREATE FUNCTION or DO command. */ - if (function_parse_error_transpose((const char *) arg)) + if (function_parse_error_transpose(cbarg->proc_source)) return; /* @@ -996,7 +904,7 @@ plpgsql_compile_error_callback(void *arg) if (plpgsql_error_funcname) errcontext("compilation of PL/pgSQL function \"%s\" near line %d", - plpgsql_error_funcname, plpgsql_latest_lineno()); + plpgsql_error_funcname, plpgsql_latest_lineno(yyscanner)); } @@ -1080,7 +988,7 @@ plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr) pstate->p_post_columnref_hook = plpgsql_post_column_ref; pstate->p_paramref_hook = plpgsql_param_ref; /* no need to use p_coerce_param_hook */ - pstate->p_ref_hook_state = (void *) expr; + pstate->p_ref_hook_state = expr; } /* @@ -2253,14 +2161,10 @@ plpgsql_parse_err_condition(char *condname) * here. */ - /* - * OTHERS is represented as code 0 (which would map to '00000', but we - * have no need to represent that as an exception condition). - */ if (strcmp(condname, "others") == 0) { new = palloc(sizeof(PLpgSQL_condition)); - new->sqlerrstate = 0; + new->sqlerrstate = PLPGSQL_OTHERS; new->condname = condname; new->next = NULL; return new; @@ -2421,242 +2325,3 @@ plpgsql_add_initdatums(int **varnos) datums_last = plpgsql_nDatums; return n; } - - -/* - * Compute the hashkey for a given function invocation - * - * The hashkey is returned into the caller-provided storage at *hashkey. - */ -static void -compute_function_hashkey(FunctionCallInfo fcinfo, - Form_pg_proc procStruct, - PLpgSQL_func_hashkey *hashkey, - bool forValidator) -{ - /* Make sure any unused bytes of the struct are zero */ - MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey)); - - /* get function OID */ - hashkey->funcOid = fcinfo->flinfo->fn_oid; - - /* get call context */ - hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo); - hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo); - - /* - * If DML trigger, include trigger's OID in the hash, so that each trigger - * usage gets a different hash entry, allowing for e.g. different relation - * rowtypes or transition table names. In validation mode we do not know - * what relation or transition table names are intended to be used, so we - * leave trigOid zero; the hash entry built in this case will never be - * used for any actual calls. - * - * We don't currently need to distinguish different event trigger usages - * in the same way, since the special parameter variables don't vary in - * type in that case. - */ - if (hashkey->isTrigger && !forValidator) - { - TriggerData *trigdata = (TriggerData *) fcinfo->context; - - hashkey->trigOid = trigdata->tg_trigger->tgoid; - } - - /* get input collation, if known */ - hashkey->inputCollation = fcinfo->fncollation; - - if (procStruct->pronargs > 0) - { - /* get the argument types */ - memcpy(hashkey->argtypes, procStruct->proargtypes.values, - procStruct->pronargs * sizeof(Oid)); - - /* resolve any polymorphic argument types */ - plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs, - hashkey->argtypes, - NULL, - fcinfo->flinfo->fn_expr, - forValidator, - NameStr(procStruct->proname)); - } -} - -/* - * This is the same as the standard resolve_polymorphic_argtypes() function, - * except that: - * 1. We go ahead and report the error if we can't resolve the types. - * 2. We treat RECORD-type input arguments (not output arguments) as if - * they were polymorphic, replacing their types with the actual input - * types if we can determine those. This allows us to create a separate - * function cache entry for each named composite type passed to such an - * argument. - * 3. In validation mode, we have no inputs to look at, so assume that - * polymorphic arguments are integer, integer-array or integer-range. - */ -static void -plpgsql_resolve_polymorphic_argtypes(int numargs, - Oid *argtypes, char *argmodes, - Node *call_expr, bool forValidator, - const char *proname) -{ - int i; - - if (!forValidator) - { - int inargno; - - /* normal case, pass to standard routine */ - if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes, - call_expr)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("could not determine actual argument " - "type for polymorphic function \"%s\"", - proname))); - /* also, treat RECORD inputs (but not outputs) as polymorphic */ - inargno = 0; - for (i = 0; i < numargs; i++) - { - char argmode = argmodes ? argmodes[i] : PROARGMODE_IN; - - if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE) - continue; - if (argtypes[i] == RECORDOID || argtypes[i] == RECORDARRAYOID) - { - Oid resolvedtype = get_call_expr_argtype(call_expr, - inargno); - - if (OidIsValid(resolvedtype)) - argtypes[i] = resolvedtype; - } - inargno++; - } - } - else - { - /* special validation case (no need to do anything for RECORD) */ - for (i = 0; i < numargs; i++) - { - switch (argtypes[i]) - { - case ANYELEMENTOID: - case ANYNONARRAYOID: - case ANYENUMOID: /* XXX dubious */ - case ANYCOMPATIBLEOID: - case ANYCOMPATIBLENONARRAYOID: - argtypes[i] = INT4OID; - break; - case ANYARRAYOID: - case ANYCOMPATIBLEARRAYOID: - argtypes[i] = INT4ARRAYOID; - break; - case ANYRANGEOID: - case ANYCOMPATIBLERANGEOID: - argtypes[i] = INT4RANGEOID; - break; - case ANYMULTIRANGEOID: - argtypes[i] = INT4MULTIRANGEOID; - break; - default: - break; - } - } - } -} - -/* - * delete_function - clean up as much as possible of a stale function cache - * - * We can't release the PLpgSQL_function struct itself, because of the - * possibility that there are fn_extra pointers to it. We can release - * the subsidiary storage, but only if there are no active evaluations - * in progress. Otherwise we'll just leak that storage. Since the - * case would only occur if a pg_proc update is detected during a nested - * recursive call on the function, a leak seems acceptable. - * - * Note that this can be called more than once if there are multiple fn_extra - * pointers to the same function cache. Hence be careful not to do things - * twice. - */ -static void -delete_function(PLpgSQL_function *func) -{ - /* remove function from hash table (might be done already) */ - plpgsql_HashTableDelete(func); - - /* release the function's storage if safe and not done already */ - if (func->use_count == 0) - plpgsql_free_function_memory(func); -} - -/* exported so we can call it from _PG_init() */ -void -plpgsql_HashTableInit(void) -{ - HASHCTL ctl; - - /* don't allow double-initialization */ - Assert(plpgsql_HashTable == NULL); - - ctl.keysize = sizeof(PLpgSQL_func_hashkey); - ctl.entrysize = sizeof(plpgsql_HashEnt); - plpgsql_HashTable = hash_create("PLpgSQL function hash", - FUNCS_PER_USER, - &ctl, - HASH_ELEM | HASH_BLOBS); -} - -static PLpgSQL_function * -plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key) -{ - plpgsql_HashEnt *hentry; - - hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable, - func_key, - HASH_FIND, - NULL); - if (hentry) - return hentry->function; - else - return NULL; -} - -static void -plpgsql_HashTableInsert(PLpgSQL_function *function, - PLpgSQL_func_hashkey *func_key) -{ - plpgsql_HashEnt *hentry; - bool found; - - hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable, - func_key, - HASH_ENTER, - &found); - if (found) - elog(WARNING, "trying to insert a function that already exists"); - - hentry->function = function; - /* prepare back link from function to hashtable key */ - function->fn_hashkey = &hentry->key; -} - -static void -plpgsql_HashTableDelete(PLpgSQL_function *function) -{ - plpgsql_HashEnt *hentry; - - /* do nothing if not in table */ - if (function->fn_hashkey == NULL) - return; - - hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable, - function->fn_hashkey, - HASH_REMOVE, - NULL); - if (hentry == NULL) - elog(WARNING, "trying to delete function that does not exist"); - - /* remove back link, which no longer points to allocated storage */ - function->fn_hashkey = NULL; -} diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 239b3250a954a..bb99781c56e39 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * pl_exec.c - Executor for the PL/pgSQL * procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,11 +19,9 @@ #include "access/detoast.h" #include "access/htup_details.h" -#include "access/transam.h" #include "access/tupconvert.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" -#include "commands/defrem.h" #include "executor/execExpr.h" #include "executor/spi.h" #include "executor/tstoreReceiver.h" @@ -31,16 +29,14 @@ #include "mb/stringinfo_mb.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" +#include "nodes/supportnodes.h" #include "optimizer/optimizer.h" #include "parser/parse_coerce.h" #include "parser/parse_type.h" -#include "parser/scansup.h" #include "plpgsql.h" #include "storage/proc.h" #include "tcop/cmdtag.h" #include "tcop/pquery.h" -#include "tcop/tcopprot.h" -#include "tcop/utility.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/datum.h" @@ -256,6 +252,15 @@ static HTAB *shared_cast_hash = NULL; else \ Assert(rc == PLPGSQL_RC_OK) +/* State struct for count_param_references */ +typedef struct count_param_references_context +{ + int paramid; + int count; + Param *last_param; +} count_param_references_context; + + /************************************************************ * Local function forward declarations ************************************************************/ @@ -341,7 +346,9 @@ static void exec_prepare_plan(PLpgSQL_execstate *estate, static void exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr); static bool exec_is_simple_query(PLpgSQL_expr *expr); static void exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan); -static void exec_check_rw_parameter(PLpgSQL_expr *expr); +static void exec_check_rw_parameter(PLpgSQL_expr *expr, int paramid); +static bool count_param_references(Node *node, + count_param_references_context *context); static void exec_check_assignable(PLpgSQL_execstate *estate, int dno); static bool exec_eval_simple_expr(PLpgSQL_execstate *estate, PLpgSQL_expr *expr, @@ -389,6 +396,10 @@ static ParamExternData *plpgsql_param_fetch(ParamListInfo params, static void plpgsql_param_compile(ParamListInfo params, Param *param, ExprState *state, Datum *resv, bool *resnull); +static void plpgsql_param_eval_var_check(ExprState *state, ExprEvalStep *op, + ExprContext *econtext); +static void plpgsql_param_eval_var_transfer(ExprState *state, ExprEvalStep *op, + ExprContext *econtext); static void plpgsql_param_eval_var(ExprState *state, ExprEvalStep *op, ExprContext *econtext); static void plpgsql_param_eval_var_ro(ExprState *state, ExprEvalStep *op, @@ -532,21 +543,22 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, false); /* - * Force any array-valued parameter to be stored in + * If it's a varlena type, check to see if we received a + * R/W expanded-object pointer. If so, we can commandeer + * the object rather than having to copy it. If passed a + * R/O expanded pointer, just keep it as the value of the + * variable for the moment. (We can change it to R/W if + * the variable gets modified, but that may very well + * never happen.) + * + * Also, force any flat array value to be stored in * expanded form in our local variable, in hopes of * improving efficiency of uses of the variable. (This is * a hack, really: why only arrays? Need more thought * about which cases are likely to win. See also * typisarray-specific heuristic in exec_assign_value.) - * - * Special cases: If passed a R/W expanded pointer, assume - * we can commandeer the object rather than having to copy - * it. If passed a R/O expanded pointer, just keep it as - * the value of the variable for the moment. (We'll force - * it to R/W if the variable gets modified, but that may - * very well never happen.) */ - if (!var->isnull && var->datatype->typisarray) + if (!var->isnull && var->datatype->typlen == -1) { if (VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value))) { @@ -561,7 +573,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, { /* R/O pointer, keep it as-is until assigned to */ } - else + else if (var->datatype->typisarray) { /* flat array, so force to expanded form */ assign_simple_var(&estate, var, @@ -867,7 +879,7 @@ coerce_function_result_tuple(PLpgSQL_execstate *estate, TupleDesc tupdesc) resultsize = EOH_get_flat_size(&erh->hdr); tuphdr = (HeapTupleHeader) SPI_palloc(resultsize); - EOH_flatten_into(&erh->hdr, (void *) tuphdr, resultsize); + EOH_flatten_into(&erh->hdr, tuphdr, resultsize); HeapTupleHeaderSetTypeId(tuphdr, tupdesc->tdtypeid); HeapTupleHeaderSetTypMod(tuphdr, tupdesc->tdtypmod); estate->retval = PointerGetDatum(tuphdr); @@ -1591,7 +1603,7 @@ exception_matches_conditions(ErrorData *edata, PLpgSQL_condition *cond) * assert-failure. If you're foolish enough, you can match those * explicitly. */ - if (sqlerrstate == 0) + if (sqlerrstate == PLPGSQL_OTHERS) { if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED && edata->sqlerrcode != ERRCODE_ASSERT_FAILURE) @@ -2276,8 +2288,8 @@ exec_stmt_call(PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt) static PLpgSQL_variable * make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) { - List *plansources; - CachedPlanSource *plansource; + CachedPlan *cplan; + PlannedStmt *pstmt; CallStmt *stmt; FuncExpr *funcexpr; HeapTuple func_tuple; @@ -2294,16 +2306,15 @@ make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate)); /* - * Get the parsed CallStmt, and look up the called procedure + * Get the parsed CallStmt, and look up the called procedure. We use + * SPI_plan_get_cached_plan to cover the edge case where expr->plan is + * already stale and needs to be updated. */ - plansources = SPI_plan_get_plan_sources(expr->plan); - if (list_length(plansources) != 1) - elog(ERROR, "query for CALL statement is not a CallStmt"); - plansource = (CachedPlanSource *) linitial(plansources); - if (list_length(plansource->query_list) != 1) + cplan = SPI_plan_get_cached_plan(expr->plan); + if (cplan == NULL || list_length(cplan->stmt_list) != 1) elog(ERROR, "query for CALL statement is not a CallStmt"); - stmt = (CallStmt *) linitial_node(Query, - plansource->query_list)->utilityStmt; + pstmt = linitial_node(PlannedStmt, cplan->stmt_list); + stmt = (CallStmt *) pstmt->utilityStmt; if (stmt == NULL || !IsA(stmt, CallStmt)) elog(ERROR, "query for CALL statement is not a CallStmt"); @@ -2383,6 +2394,8 @@ make_callstmt_target(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) row->nfields = nfields; + ReleaseCachedPlan(cplan, CurrentResourceOwner); + MemoryContextSwitchTo(oldcontext); return (PLpgSQL_variable *) row; @@ -4029,7 +4042,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate, /* initialize our ParamListInfo with appropriate hook functions */ estate->paramLI = makeParamList(0); estate->paramLI->paramFetch = plpgsql_param_fetch; - estate->paramLI->paramFetchArg = (void *) estate; + estate->paramLI->paramFetchArg = estate; estate->paramLI->paramCompile = plpgsql_param_compile; estate->paramLI->paramCompileArg = NULL; /* not needed */ estate->paramLI->parserSetup = (ParserSetupHook) plpgsql_parser_setup; @@ -4177,18 +4190,12 @@ exec_prepare_plan(PLpgSQL_execstate *estate, SPIPlanPtr plan; SPIPrepareOptions options; - /* - * The grammar can't conveniently set expr->func while building the parse - * tree, so make sure it's set before parser hooks need it. - */ - expr->func = estate->func; - /* * Generate and save the plan */ memset(&options, 0, sizeof(options)); options.parserSetup = (ParserSetupHook) plpgsql_parser_setup; - options.parserSetupArg = (void *) expr; + options.parserSetupArg = expr; options.parseMode = expr->parseMode; options.cursorOptions = cursorOptions; plan = SPI_prepare_extended(expr->query, &options); @@ -4245,8 +4252,9 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, /* * We could look at the raw_parse_tree, but it seems simpler to * check the command tag. Note we should *not* look at the Query - * tree(s), since those are the result of rewriting and could have - * been transmogrified into something else entirely. + * tree(s), since those are the result of rewriting and could be + * stale, or could have been transmogrified into something else + * entirely. */ if (plansource->commandTag == CMDTAG_INSERT || plansource->commandTag == CMDTAG_UPDATE || @@ -4692,7 +4700,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt) } /* ---------- - * Process the OPEN according to it's type. + * Process the OPEN according to its type. * ---------- */ if (stmt->query != NULL) @@ -5018,21 +5026,7 @@ exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target, * If first time through, create a plan for this expression. */ if (expr->plan == NULL) - { - /* - * Mark the expression as being an assignment source, if target is a - * simple variable. (This is a bit messy, but it seems cleaner than - * modifying the API of exec_prepare_plan for the purpose. We need to - * stash the target dno into the expr anyway, so that it will be - * available if we have to replan.) - */ - if (target->dtype == PLPGSQL_DTYPE_VAR) - expr->target_param = target->dno; - else - expr->target_param = -1; /* should be that already */ - exec_prepare_plan(estate, expr, 0); - } value = exec_eval_expr(estate, expr, &isnull, &valtype, &valtypmod); exec_assign_value(estate, target, value, isnull, valtype, valtypmod); @@ -6100,10 +6094,13 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate, /* * Reset to "not simple" to leave sane state (with no dangling - * pointers) in case we fail while replanning. expr_simple_plansource - * can be left alone however, as that cannot move. + * pointers) in case we fail while replanning. We'll need to + * re-determine simplicity and R/W optimizability anyway, since those + * could change with the new plan. expr_simple_plansource can be left + * alone however, as that cannot move. */ expr->expr_simple_expr = NULL; + expr->expr_rwopt = PLPGSQL_RWOPT_UNKNOWN; expr->expr_rw_param = NULL; expr->expr_simple_plan = NULL; expr->expr_simple_plan_lxid = InvalidLocalTransactionId; @@ -6174,7 +6171,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate, * possibly setting ecxt_param_list_info to NULL; we've already forced use * of a generic plan. */ - paramLI->parserSetupArg = (void *) expr; + paramLI->parserSetupArg = expr; econtext->ecxt_param_list_info = paramLI; /* @@ -6283,14 +6280,7 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) * Callers must save and restore parserSetupArg if there is any chance * that they are interrupting an active use of parameters. */ - paramLI->parserSetupArg = (void *) expr; - - /* - * Also make sure this is set before parser hooks need it. There is - * no need to save and restore, since the value is always correct once - * set. (Should be set already, but let's be sure.) - */ - expr->func = estate->func; + paramLI->parserSetupArg = expr; } else { @@ -6468,16 +6458,27 @@ plpgsql_param_compile(ParamListInfo params, Param *param, scratch.resnull = resnull; /* - * Select appropriate eval function. It seems worth special-casing - * DTYPE_VAR and DTYPE_RECFIELD for performance. Also, we can determine - * in advance whether MakeExpandedObjectReadOnly() will be required. - * Currently, only VAR/PROMISE and REC datums could contain read/write - * expanded objects. + * Select appropriate eval function. + * + * First, if this Param references the same varlena-type DTYPE_VAR datum + * that is the target of the assignment containing this simple expression, + * then it's possible we will be able to optimize handling of R/W expanded + * datums. We don't want to do the work needed to determine that unless + * we actually see a R/W expanded datum at runtime, so install a checking + * function that will figure that out when needed. + * + * Otherwise, it seems worth special-casing DTYPE_VAR and DTYPE_RECFIELD + * for performance. Also, we can determine in advance whether + * MakeExpandedObjectReadOnly() will be required. Currently, only + * VAR/PROMISE and REC datums could contain read/write expanded objects. */ if (datum->dtype == PLPGSQL_DTYPE_VAR) { - if (param != expr->expr_rw_param && - ((PLpgSQL_var *) datum)->datatype->typlen == -1) + bool isvarlena = (((PLpgSQL_var *) datum)->datatype->typlen == -1); + + if (isvarlena && dno == expr->target_param && expr->expr_simple_expr) + scratch.d.cparam.paramfunc = plpgsql_param_eval_var_check; + else if (isvarlena) scratch.d.cparam.paramfunc = plpgsql_param_eval_var_ro; else scratch.d.cparam.paramfunc = plpgsql_param_eval_var; @@ -6486,14 +6487,12 @@ plpgsql_param_compile(ParamListInfo params, Param *param, scratch.d.cparam.paramfunc = plpgsql_param_eval_recfield; else if (datum->dtype == PLPGSQL_DTYPE_PROMISE) { - if (param != expr->expr_rw_param && - ((PLpgSQL_var *) datum)->datatype->typlen == -1) + if (((PLpgSQL_var *) datum)->datatype->typlen == -1) scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro; else scratch.d.cparam.paramfunc = plpgsql_param_eval_generic; } - else if (datum->dtype == PLPGSQL_DTYPE_REC && - param != expr->expr_rw_param) + else if (datum->dtype == PLPGSQL_DTYPE_REC) scratch.d.cparam.paramfunc = plpgsql_param_eval_generic_ro; else scratch.d.cparam.paramfunc = plpgsql_param_eval_generic; @@ -6502,14 +6501,177 @@ plpgsql_param_compile(ParamListInfo params, Param *param, * Note: it's tempting to use paramarg to store the estate pointer and * thereby save an indirection or two in the eval functions. But that * doesn't work because the compiled expression might be used with - * different estates for the same PL/pgSQL function. + * different estates for the same PL/pgSQL function. Instead, store + * pointers to the PLpgSQL_expr as well as this specific Param, to support + * plpgsql_param_eval_var_check(). */ - scratch.d.cparam.paramarg = NULL; + scratch.d.cparam.paramarg = expr; + scratch.d.cparam.paramarg2 = param; scratch.d.cparam.paramid = param->paramid; scratch.d.cparam.paramtype = param->paramtype; ExprEvalPushStep(state, &scratch); } +/* + * plpgsql_param_eval_var_check evaluation of EEOP_PARAM_CALLBACK step + * + * This is specialized to the case of DTYPE_VAR variables for which + * we may need to determine the applicability of a read/write optimization, + * but we've not done that yet. The work to determine applicability will + * be done at most once (per construction of the PL/pgSQL function's cache + * entry) when we first see that the target variable's old value is a R/W + * expanded object. If we never do see that, nothing is lost: the amount + * of work done by this function in that case is just about the same as + * what would be done by plpgsql_param_eval_var_ro, which is what we'd + * have used otherwise. + */ +static void +plpgsql_param_eval_var_check(ExprState *state, ExprEvalStep *op, + ExprContext *econtext) +{ + ParamListInfo params; + PLpgSQL_execstate *estate; + int dno = op->d.cparam.paramid - 1; + PLpgSQL_var *var; + + /* fetch back the hook data */ + params = econtext->ecxt_param_list_info; + estate = (PLpgSQL_execstate *) params->paramFetchArg; + Assert(dno >= 0 && dno < estate->ndatums); + + /* now we can access the target datum */ + var = (PLpgSQL_var *) estate->datums[dno]; + Assert(var->dtype == PLPGSQL_DTYPE_VAR); + + /* + * If the variable's current value is a R/W expanded object, it's time to + * decide whether/how to optimize the assignment. + */ + if (!var->isnull && + VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value))) + { + PLpgSQL_expr *expr = (PLpgSQL_expr *) op->d.cparam.paramarg; + Param *param = (Param *) op->d.cparam.paramarg2; + + /* + * We might have already figured this out while evaluating some other + * Param referencing the same variable, so check expr_rwopt first. + */ + if (expr->expr_rwopt == PLPGSQL_RWOPT_UNKNOWN) + exec_check_rw_parameter(expr, op->d.cparam.paramid); + + /* + * Update the callback pointer to match what we decided to do, so that + * this function will not be called again. Then pass off this + * execution to the newly-selected function. + */ + switch (expr->expr_rwopt) + { + case PLPGSQL_RWOPT_UNKNOWN: + Assert(false); + break; + case PLPGSQL_RWOPT_NOPE: + /* Force the value to read-only in all future executions */ + op->d.cparam.paramfunc = plpgsql_param_eval_var_ro; + plpgsql_param_eval_var_ro(state, op, econtext); + break; + case PLPGSQL_RWOPT_TRANSFER: + /* There can be only one matching Param in this case */ + Assert(param == expr->expr_rw_param); + /* When the value is read/write, transfer to exec context */ + op->d.cparam.paramfunc = plpgsql_param_eval_var_transfer; + plpgsql_param_eval_var_transfer(state, op, econtext); + break; + case PLPGSQL_RWOPT_INPLACE: + if (param == expr->expr_rw_param) + { + /* When the value is read/write, deliver it as-is */ + op->d.cparam.paramfunc = plpgsql_param_eval_var; + plpgsql_param_eval_var(state, op, econtext); + } + else + { + /* Not the optimizable reference, so force to read-only */ + op->d.cparam.paramfunc = plpgsql_param_eval_var_ro; + plpgsql_param_eval_var_ro(state, op, econtext); + } + break; + } + return; + } + + /* + * Otherwise, continue to postpone that decision, and execute an inlined + * version of exec_eval_datum(). Although this value could potentially + * need MakeExpandedObjectReadOnly, we know it doesn't right now. + */ + *op->resvalue = var->value; + *op->resnull = var->isnull; + + /* safety check -- an assertion should be sufficient */ + Assert(var->datatype->typoid == op->d.cparam.paramtype); +} + +/* + * plpgsql_param_eval_var_transfer evaluation of EEOP_PARAM_CALLBACK step + * + * This is specialized to the case of DTYPE_VAR variables for which + * we have determined that a read/write expanded value can be handed off + * into execution of the expression (and then possibly returned to our + * function's ownership afterwards). We have to test though, because the + * variable might not contain a read/write expanded value during this + * execution. + */ +static void +plpgsql_param_eval_var_transfer(ExprState *state, ExprEvalStep *op, + ExprContext *econtext) +{ + ParamListInfo params; + PLpgSQL_execstate *estate; + int dno = op->d.cparam.paramid - 1; + PLpgSQL_var *var; + + /* fetch back the hook data */ + params = econtext->ecxt_param_list_info; + estate = (PLpgSQL_execstate *) params->paramFetchArg; + Assert(dno >= 0 && dno < estate->ndatums); + + /* now we can access the target datum */ + var = (PLpgSQL_var *) estate->datums[dno]; + Assert(var->dtype == PLPGSQL_DTYPE_VAR); + + /* + * If the variable's current value is a R/W expanded object, transfer its + * ownership into the expression execution context, then drop our own + * reference to the value by setting the variable to NULL. That'll be + * overwritten (perhaps with this same object) when control comes back + * from the expression. + */ + if (!var->isnull && + VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(var->value))) + { + *op->resvalue = TransferExpandedObject(var->value, + get_eval_mcontext(estate)); + *op->resnull = false; + + var->value = (Datum) 0; + var->isnull = true; + var->freeval = false; + } + else + { + /* + * Otherwise we can pass the variable's value directly; we now know + * that MakeExpandedObjectReadOnly isn't needed. + */ + *op->resvalue = var->value; + *op->resnull = var->isnull; + } + + /* safety check -- an assertion should be sufficient */ + Assert(var->datatype->typoid == op->d.cparam.paramtype); +} + /* * plpgsql_param_eval_var evaluation of EEOP_PARAM_CALLBACK step * @@ -7986,9 +8148,10 @@ exec_simple_check_plan(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) MemoryContext oldcontext; /* - * Initialize to "not simple". + * Initialize to "not simple", and reset R/W optimizability. */ expr->expr_simple_expr = NULL; + expr->expr_rwopt = PLPGSQL_RWOPT_UNKNOWN; expr->expr_rw_param = NULL; /* @@ -8139,10 +8302,11 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) /* * Ordinarily, the plan node should be a simple Result. However, if * debug_parallel_query is on, the planner might've stuck a Gather node - * atop that. The simplest way to deal with this is to look through the - * Gather node. The Gather node's tlist would normally contain a Var - * referencing the child node's output, but it could also be a Param, or - * it could be a Const that setrefs.c copied as-is. + * atop that; and/or if this plan is for a scrollable cursor, the planner + * might've stuck a Material node atop it. The simplest way to deal with + * this is to look through the Gather and/or Material nodes. The upper + * node's tlist would normally contain a Var referencing the child node's + * output ... but setrefs.c might also have copied a Const as-is. */ plan = stmt->planTree; for (;;) @@ -8160,7 +8324,7 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) ((Result *) plan)->resconstantqual == NULL); break; } - else if (IsA(plan, Gather)) + else if (IsA(plan, Gather) || IsA(plan, Material)) { Assert(plan->lefttree != NULL && plan->righttree == NULL && @@ -8169,9 +8333,9 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) /* If setrefs.c copied up a Const, no need to look further */ if (IsA(tle_expr, Const)) break; - /* Otherwise, it had better be a Param or an outer Var */ - Assert(IsA(tle_expr, Param) || (IsA(tle_expr, Var) && - ((Var *) tle_expr)->varno == OUTER_VAR)); + /* Otherwise, it better be an outer Var */ + Assert(IsA(tle_expr, Var)); + Assert(((Var *) tle_expr)->varno == OUTER_VAR); /* Descend to the child node */ plan = plan->lefttree; } @@ -8193,143 +8357,206 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan) expr->expr_simple_typmod = exprTypmod((Node *) tle_expr); /* We also want to remember if it is immutable or not */ expr->expr_simple_mutable = contain_mutable_functions((Node *) tle_expr); - - /* - * Lastly, check to see if there's a possibility of optimizing a - * read/write parameter. - */ - exec_check_rw_parameter(expr); } /* * exec_check_rw_parameter --- can we pass expanded object as read/write param? * - * If we have an assignment like "x := array_append(x, foo)" in which the + * There are two separate cases in which we can optimize an update to a + * variable that has a read/write expanded value by letting the called + * expression operate directly on the expanded value. In both cases we + * are considering assignments like "var := array_append(var, foo)" where + * the assignment target is also an input to the RHS expression. + * + * Case 1 (RWOPT_TRANSFER rule): if the variable is "local" in the sense that + * its declaration is not outside any BEGIN...EXCEPTION block surrounding the + * assignment, then we do not need to worry about preserving its value if the + * RHS expression throws an error. If in addition the variable is referenced + * exactly once in the RHS expression, then we can optimize by converting the + * read/write expanded value into a transient value within the expression + * evaluation context, and then setting the variable's recorded value to NULL + * to prevent double-free attempts. This works regardless of any other + * details of the RHS expression. If the expression eventually returns that + * same expanded object (possibly modified) then the variable will re-acquire + * ownership; while if it returns something else or throws an error, the + * expanded object will be discarded as part of cleanup of the evaluation + * context. + * + * Case 2 (RWOPT_INPLACE rule): if we have a non-local assignment or if + * it looks like "var := array_append(var, var[1])" with multiple references + * to the target variable, then we can't use case 1. Nonetheless, if the * top-level function is trusted not to corrupt its argument in case of an - * error, then when x has an expanded object as value, it is safe to pass the - * value as a read/write pointer and let the function modify the value - * in-place. + * error, then when the var has an expanded object as value, it is safe to + * pass the value as a read/write pointer to the top-level function and let + * the function modify the value in-place. (Any other references have to be + * passed as read-only pointers as usual.) Only the top-level function has to + * be trusted, since if anything further down fails, the object hasn't been + * modified yet. * - * This function checks for a safe expression, and sets expr->expr_rw_param - * to the address of any Param within the expression that can be passed as - * read/write (there can be only one); or to NULL when there is no safe Param. + * This function checks to see if the assignment is optimizable according + * to either rule, and updates expr->expr_rwopt accordingly. In addition, + * it sets expr->expr_rw_param to the address of the Param within the + * expression that can be passed as read/write (there can be only one); + * or to NULL when there is no safe Param. * - * Note that this mechanism intentionally applies the safety labeling to just - * one Param; the expression could contain other Params referencing the target - * variable, but those must still be treated as read-only. + * Note that this mechanism intentionally allows just one Param to emit a + * read/write pointer; in case 2, the expression could contain other Params + * referencing the target variable, but those must be treated as read-only. * * Also note that we only apply this optimization within simple expressions. * There's no point in it for non-simple expressions, because the * exec_run_select code path will flatten any expanded result anyway. - * Also, it's safe to assume that an expr_simple_expr tree won't get copied - * somewhere before it gets compiled, so that looking for pointer equality - * to expr_rw_param will work for matching the target Param. That'd be much - * shakier in the general case. */ static void -exec_check_rw_parameter(PLpgSQL_expr *expr) +exec_check_rw_parameter(PLpgSQL_expr *expr, int paramid) { - int target_dno; + Expr *sexpr = expr->expr_simple_expr; Oid funcid; List *fargs; - ListCell *lc; + Oid prosupport; /* Assume unsafe */ + expr->expr_rwopt = PLPGSQL_RWOPT_NOPE; expr->expr_rw_param = NULL; - /* Done if expression isn't an assignment source */ - target_dno = expr->target_param; - if (target_dno < 0) - return; + /* Shouldn't be here for non-simple expression */ + Assert(sexpr != NULL); + + /* Param should match the expression's assignment target, too */ + Assert(paramid == expr->target_param + 1); /* - * If target variable isn't referenced by expression, no need to look - * further. + * If the assignment is to a "local" variable (one whose value won't + * matter anymore if expression evaluation fails), and this Param is the + * only reference to that variable in the expression, then we can + * unconditionally optimize using the "transfer" method. */ - if (!bms_is_member(target_dno, expr->paramnos)) - return; + if (expr->target_is_local) + { + count_param_references_context context; - /* Shouldn't be here for non-simple expression */ - Assert(expr->expr_simple_expr != NULL); + /* See how many references there are, and find one of them */ + context.paramid = paramid; + context.count = 0; + context.last_param = NULL; + (void) count_param_references((Node *) sexpr, &context); + + /* If we're here, the expr must contain some reference to the var */ + Assert(context.count > 0); + + /* If exactly one reference, success! */ + if (context.count == 1) + { + expr->expr_rwopt = PLPGSQL_RWOPT_TRANSFER; + expr->expr_rw_param = context.last_param; + return; + } + } /* + * Otherwise, see if we can trust the expression's top-level function to + * apply the "inplace" method. + * * Top level of expression must be a simple FuncExpr, OpExpr, or - * SubscriptingRef, else we can't optimize. + * SubscriptingRef, else we can't identify which function is relevant. But + * it's okay to look through any RelabelType above that, since that can't + * fail. */ - if (IsA(expr->expr_simple_expr, FuncExpr)) + if (IsA(sexpr, RelabelType)) + sexpr = ((RelabelType *) sexpr)->arg; + if (IsA(sexpr, FuncExpr)) { - FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr; + FuncExpr *fexpr = (FuncExpr *) sexpr; funcid = fexpr->funcid; fargs = fexpr->args; } - else if (IsA(expr->expr_simple_expr, OpExpr)) + else if (IsA(sexpr, OpExpr)) { - OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr; + OpExpr *opexpr = (OpExpr *) sexpr; funcid = opexpr->opfuncid; fargs = opexpr->args; } - else if (IsA(expr->expr_simple_expr, SubscriptingRef)) + else if (IsA(sexpr, SubscriptingRef)) { - SubscriptingRef *sbsref = (SubscriptingRef *) expr->expr_simple_expr; - - /* We only trust standard varlena arrays to be safe */ - if (get_typsubscript(sbsref->refcontainertype, NULL) != - F_ARRAY_SUBSCRIPT_HANDLER) - return; + SubscriptingRef *sbsref = (SubscriptingRef *) sexpr; - /* We can optimize the refexpr if it's the target, otherwise not */ - if (sbsref->refexpr && IsA(sbsref->refexpr, Param)) - { - Param *param = (Param *) sbsref->refexpr; + funcid = get_typsubscript(sbsref->refcontainertype, NULL); - if (param->paramkind == PARAM_EXTERN && - param->paramid == target_dno + 1) - { - /* Found the Param we want to pass as read/write */ - expr->expr_rw_param = param; - return; - } - } - - return; + /* + * We assume that only the refexpr and refassgnexpr (if any) are + * relevant to the support function's decision. If that turns out to + * be a bad idea, we could incorporate the subscript expressions into + * the fargs list somehow. + */ + fargs = list_make2(sbsref->refexpr, sbsref->refassgnexpr); } else return; /* - * The top-level function must be one that we trust to be "safe". - * Currently we hard-wire the list, but it would be very desirable to - * allow extensions to mark their functions as safe ... + * The top-level function must be one that can handle in-place update + * safely. We allow functions to declare their ability to do that via a + * support function request. */ - if (!(funcid == F_ARRAY_APPEND || - funcid == F_ARRAY_PREPEND)) + prosupport = get_func_support(funcid); + if (OidIsValid(prosupport)) + { + SupportRequestModifyInPlace req; + Param *param; + + req.type = T_SupportRequestModifyInPlace; + req.funcid = funcid; + req.args = fargs; + req.paramid = paramid; + + param = (Param *) + DatumGetPointer(OidFunctionCall1(prosupport, + PointerGetDatum(&req))); + + if (param == NULL) + return; /* support function fails */ + + /* Verify support function followed the API */ + Assert(IsA(param, Param)); + Assert(param->paramkind == PARAM_EXTERN); + Assert(param->paramid == paramid); + + /* Found the Param we want to pass as read/write */ + expr->expr_rwopt = PLPGSQL_RWOPT_INPLACE; + expr->expr_rw_param = param; return; + } +} - /* - * The target variable (in the form of a Param) must appear as a direct - * argument of the top-level function. References further down in the - * tree can't be optimized; but on the other hand, they don't invalidate - * optimizing the top-level call, since that will be executed last. - */ - foreach(lc, fargs) +/* + * Count Params referencing the specified paramid, and return one of them + * if there are any. + * + * We actually only need to distinguish 0, 1, and N references; so we can + * abort the tree traversal as soon as we've found two. + */ +static bool +count_param_references(Node *node, count_param_references_context *context) +{ + if (node == NULL) + return false; + else if (IsA(node, Param)) { - Node *arg = (Node *) lfirst(lc); + Param *param = (Param *) node; - if (arg && IsA(arg, Param)) + if (param->paramkind == PARAM_EXTERN && + param->paramid == context->paramid) { - Param *param = (Param *) arg; - - if (param->paramkind == PARAM_EXTERN && - param->paramid == target_dno + 1) - { - /* Found the Param we want to pass as read/write */ - expr->expr_rw_param = param; - return; - } + context->last_param = param; + if (++(context->count) > 1) + return true; /* abort tree traversal */ } + return false; } + else + return expression_tree_walker(node, count_param_references, context); } /* diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index eeb7c4d7c04af..bc7a61feb4d23 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -3,7 +3,7 @@ * pl_funcs.c - Misc functions for the PL/pgSQL * procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -334,387 +334,376 @@ plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind) /********************************************************************** - * Release memory when a PL/pgSQL function is no longer needed + * Support for recursing through a PL/pgSQL statement tree * - * The code for recursing through the function tree is really only - * needed to locate PLpgSQL_expr nodes, which may contain references - * to saved SPI Plans that must be freed. The function tree itself, - * along with subsidiary data, is freed in one swoop by freeing the - * function's permanent memory context. + * The point of this code is to encapsulate knowledge of where the + * sub-statements and expressions are in a statement tree, avoiding + * duplication of code. The caller supplies two callbacks, one to + * be invoked on statements and one to be invoked on expressions. + * (The recursion should be started by invoking the statement callback + * on function->action.) The statement callback should do any + * statement-type-specific action it needs, then recurse by calling + * plpgsql_statement_tree_walker(). The expression callback can be a + * no-op if no per-expression behavior is needed. **********************************************************************/ -static void free_stmt(PLpgSQL_stmt *stmt); -static void free_block(PLpgSQL_stmt_block *block); -static void free_assign(PLpgSQL_stmt_assign *stmt); -static void free_if(PLpgSQL_stmt_if *stmt); -static void free_case(PLpgSQL_stmt_case *stmt); -static void free_loop(PLpgSQL_stmt_loop *stmt); -static void free_while(PLpgSQL_stmt_while *stmt); -static void free_fori(PLpgSQL_stmt_fori *stmt); -static void free_fors(PLpgSQL_stmt_fors *stmt); -static void free_forc(PLpgSQL_stmt_forc *stmt); -static void free_foreach_a(PLpgSQL_stmt_foreach_a *stmt); -static void free_exit(PLpgSQL_stmt_exit *stmt); -static void free_return(PLpgSQL_stmt_return *stmt); -static void free_return_next(PLpgSQL_stmt_return_next *stmt); -static void free_return_query(PLpgSQL_stmt_return_query *stmt); -static void free_raise(PLpgSQL_stmt_raise *stmt); -static void free_assert(PLpgSQL_stmt_assert *stmt); -static void free_execsql(PLpgSQL_stmt_execsql *stmt); -static void free_dynexecute(PLpgSQL_stmt_dynexecute *stmt); -static void free_dynfors(PLpgSQL_stmt_dynfors *stmt); -static void free_getdiag(PLpgSQL_stmt_getdiag *stmt); -static void free_open(PLpgSQL_stmt_open *stmt); -static void free_fetch(PLpgSQL_stmt_fetch *stmt); -static void free_close(PLpgSQL_stmt_close *stmt); -static void free_perform(PLpgSQL_stmt_perform *stmt); -static void free_call(PLpgSQL_stmt_call *stmt); -static void free_commit(PLpgSQL_stmt_commit *stmt); -static void free_rollback(PLpgSQL_stmt_rollback *stmt); -static void free_expr(PLpgSQL_expr *expr); +typedef void (*plpgsql_stmt_walker_callback) (PLpgSQL_stmt *stmt, + void *context); +typedef void (*plpgsql_expr_walker_callback) (PLpgSQL_expr *expr, + void *context); +/* + * As in nodeFuncs.h, we respectfully decline to support the C standard's + * position that a pointer to struct is incompatible with "void *". Instead, + * silence related compiler warnings using casts in this macro wrapper. + */ +#define plpgsql_statement_tree_walker(s, sw, ew, c) \ + plpgsql_statement_tree_walker_impl(s, (plpgsql_stmt_walker_callback) (sw), \ + (plpgsql_expr_walker_callback) (ew), c) static void -free_stmt(PLpgSQL_stmt *stmt) +plpgsql_statement_tree_walker_impl(PLpgSQL_stmt *stmt, + plpgsql_stmt_walker_callback stmt_callback, + plpgsql_expr_walker_callback expr_callback, + void *context) { +#define S_WALK(st) stmt_callback(st, context) +#define E_WALK(ex) expr_callback(ex, context) +#define S_LIST_WALK(lst) foreach_ptr(PLpgSQL_stmt, st, lst) S_WALK(st) +#define E_LIST_WALK(lst) foreach_ptr(PLpgSQL_expr, ex, lst) E_WALK(ex) + switch (stmt->cmd_type) { case PLPGSQL_STMT_BLOCK: - free_block((PLpgSQL_stmt_block *) stmt); - break; + { + PLpgSQL_stmt_block *bstmt = (PLpgSQL_stmt_block *) stmt; + + S_LIST_WALK(bstmt->body); + if (bstmt->exceptions) + { + foreach_ptr(PLpgSQL_exception, exc, bstmt->exceptions->exc_list) + { + /* conditions list has no interesting sub-structure */ + S_LIST_WALK(exc->action); + } + } + break; + } case PLPGSQL_STMT_ASSIGN: - free_assign((PLpgSQL_stmt_assign *) stmt); - break; + { + PLpgSQL_stmt_assign *astmt = (PLpgSQL_stmt_assign *) stmt; + + E_WALK(astmt->expr); + break; + } case PLPGSQL_STMT_IF: - free_if((PLpgSQL_stmt_if *) stmt); - break; + { + PLpgSQL_stmt_if *ifstmt = (PLpgSQL_stmt_if *) stmt; + + E_WALK(ifstmt->cond); + S_LIST_WALK(ifstmt->then_body); + foreach_ptr(PLpgSQL_if_elsif, elif, ifstmt->elsif_list) + { + E_WALK(elif->cond); + S_LIST_WALK(elif->stmts); + } + S_LIST_WALK(ifstmt->else_body); + break; + } case PLPGSQL_STMT_CASE: - free_case((PLpgSQL_stmt_case *) stmt); - break; + { + PLpgSQL_stmt_case *cstmt = (PLpgSQL_stmt_case *) stmt; + + E_WALK(cstmt->t_expr); + foreach_ptr(PLpgSQL_case_when, cwt, cstmt->case_when_list) + { + E_WALK(cwt->expr); + S_LIST_WALK(cwt->stmts); + } + S_LIST_WALK(cstmt->else_stmts); + break; + } case PLPGSQL_STMT_LOOP: - free_loop((PLpgSQL_stmt_loop *) stmt); - break; + { + PLpgSQL_stmt_loop *lstmt = (PLpgSQL_stmt_loop *) stmt; + + S_LIST_WALK(lstmt->body); + break; + } case PLPGSQL_STMT_WHILE: - free_while((PLpgSQL_stmt_while *) stmt); - break; + { + PLpgSQL_stmt_while *wstmt = (PLpgSQL_stmt_while *) stmt; + + E_WALK(wstmt->cond); + S_LIST_WALK(wstmt->body); + break; + } case PLPGSQL_STMT_FORI: - free_fori((PLpgSQL_stmt_fori *) stmt); - break; + { + PLpgSQL_stmt_fori *fori = (PLpgSQL_stmt_fori *) stmt; + + E_WALK(fori->lower); + E_WALK(fori->upper); + E_WALK(fori->step); + S_LIST_WALK(fori->body); + break; + } case PLPGSQL_STMT_FORS: - free_fors((PLpgSQL_stmt_fors *) stmt); - break; + { + PLpgSQL_stmt_fors *fors = (PLpgSQL_stmt_fors *) stmt; + + S_LIST_WALK(fors->body); + E_WALK(fors->query); + break; + } case PLPGSQL_STMT_FORC: - free_forc((PLpgSQL_stmt_forc *) stmt); - break; + { + PLpgSQL_stmt_forc *forc = (PLpgSQL_stmt_forc *) stmt; + + S_LIST_WALK(forc->body); + E_WALK(forc->argquery); + break; + } case PLPGSQL_STMT_FOREACH_A: - free_foreach_a((PLpgSQL_stmt_foreach_a *) stmt); - break; + { + PLpgSQL_stmt_foreach_a *fstmt = (PLpgSQL_stmt_foreach_a *) stmt; + + E_WALK(fstmt->expr); + S_LIST_WALK(fstmt->body); + break; + } case PLPGSQL_STMT_EXIT: - free_exit((PLpgSQL_stmt_exit *) stmt); - break; + { + PLpgSQL_stmt_exit *estmt = (PLpgSQL_stmt_exit *) stmt; + + E_WALK(estmt->cond); + break; + } case PLPGSQL_STMT_RETURN: - free_return((PLpgSQL_stmt_return *) stmt); - break; + { + PLpgSQL_stmt_return *rstmt = (PLpgSQL_stmt_return *) stmt; + + E_WALK(rstmt->expr); + break; + } case PLPGSQL_STMT_RETURN_NEXT: - free_return_next((PLpgSQL_stmt_return_next *) stmt); - break; + { + PLpgSQL_stmt_return_next *rstmt = (PLpgSQL_stmt_return_next *) stmt; + + E_WALK(rstmt->expr); + break; + } case PLPGSQL_STMT_RETURN_QUERY: - free_return_query((PLpgSQL_stmt_return_query *) stmt); - break; + { + PLpgSQL_stmt_return_query *rstmt = (PLpgSQL_stmt_return_query *) stmt; + + E_WALK(rstmt->query); + E_WALK(rstmt->dynquery); + E_LIST_WALK(rstmt->params); + break; + } case PLPGSQL_STMT_RAISE: - free_raise((PLpgSQL_stmt_raise *) stmt); - break; + { + PLpgSQL_stmt_raise *rstmt = (PLpgSQL_stmt_raise *) stmt; + + E_LIST_WALK(rstmt->params); + foreach_ptr(PLpgSQL_raise_option, opt, rstmt->options) + { + E_WALK(opt->expr); + } + break; + } case PLPGSQL_STMT_ASSERT: - free_assert((PLpgSQL_stmt_assert *) stmt); - break; + { + PLpgSQL_stmt_assert *astmt = (PLpgSQL_stmt_assert *) stmt; + + E_WALK(astmt->cond); + E_WALK(astmt->message); + break; + } case PLPGSQL_STMT_EXECSQL: - free_execsql((PLpgSQL_stmt_execsql *) stmt); - break; + { + PLpgSQL_stmt_execsql *xstmt = (PLpgSQL_stmt_execsql *) stmt; + + E_WALK(xstmt->sqlstmt); + break; + } case PLPGSQL_STMT_DYNEXECUTE: - free_dynexecute((PLpgSQL_stmt_dynexecute *) stmt); - break; + { + PLpgSQL_stmt_dynexecute *dstmt = (PLpgSQL_stmt_dynexecute *) stmt; + + E_WALK(dstmt->query); + E_LIST_WALK(dstmt->params); + break; + } case PLPGSQL_STMT_DYNFORS: - free_dynfors((PLpgSQL_stmt_dynfors *) stmt); - break; + { + PLpgSQL_stmt_dynfors *dstmt = (PLpgSQL_stmt_dynfors *) stmt; + + S_LIST_WALK(dstmt->body); + E_WALK(dstmt->query); + E_LIST_WALK(dstmt->params); + break; + } case PLPGSQL_STMT_GETDIAG: - free_getdiag((PLpgSQL_stmt_getdiag *) stmt); - break; + { + /* no interesting sub-structure */ + break; + } case PLPGSQL_STMT_OPEN: - free_open((PLpgSQL_stmt_open *) stmt); - break; + { + PLpgSQL_stmt_open *ostmt = (PLpgSQL_stmt_open *) stmt; + + E_WALK(ostmt->argquery); + E_WALK(ostmt->query); + E_WALK(ostmt->dynquery); + E_LIST_WALK(ostmt->params); + break; + } case PLPGSQL_STMT_FETCH: - free_fetch((PLpgSQL_stmt_fetch *) stmt); - break; + { + PLpgSQL_stmt_fetch *fstmt = (PLpgSQL_stmt_fetch *) stmt; + + E_WALK(fstmt->expr); + break; + } case PLPGSQL_STMT_CLOSE: - free_close((PLpgSQL_stmt_close *) stmt); - break; + { + /* no interesting sub-structure */ + break; + } case PLPGSQL_STMT_PERFORM: - free_perform((PLpgSQL_stmt_perform *) stmt); - break; + { + PLpgSQL_stmt_perform *pstmt = (PLpgSQL_stmt_perform *) stmt; + + E_WALK(pstmt->expr); + break; + } case PLPGSQL_STMT_CALL: - free_call((PLpgSQL_stmt_call *) stmt); - break; + { + PLpgSQL_stmt_call *cstmt = (PLpgSQL_stmt_call *) stmt; + + E_WALK(cstmt->expr); + break; + } case PLPGSQL_STMT_COMMIT: - free_commit((PLpgSQL_stmt_commit *) stmt); - break; case PLPGSQL_STMT_ROLLBACK: - free_rollback((PLpgSQL_stmt_rollback *) stmt); - break; + { + /* no interesting sub-structure */ + break; + } default: elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type); break; } } -static void -free_stmts(List *stmts) -{ - ListCell *s; - foreach(s, stmts) - { - free_stmt((PLpgSQL_stmt *) lfirst(s)); - } -} +/********************************************************************** + * Mark assignment source expressions that have local target variables, + * that is, the target variable is declared within the exception block + * most closely containing the assignment itself. (Such target variables + * need not be preserved if the assignment's source expression raises an + * error, since the variable will no longer be accessible afterwards. + * Detecting this allows better optimization.) + * + * This code need not be called if the plpgsql function contains no exception + * blocks, because mark_expr_as_assignment_source will have set all the flags + * to true already. Also, we need not reconsider default-value expressions + * for variables, because variable declarations are necessarily within the + * nearest exception block. (In DECLARE ... BEGIN ... EXCEPTION ... END, the + * variable initializations are done before entering the exception scope.) + * + * Within the recursion, local_dnos is a Bitmapset of dnos of variables + * known to be declared within the current exception level. + **********************************************************************/ +static void mark_stmt(PLpgSQL_stmt *stmt, Bitmapset *local_dnos); +static void mark_expr(PLpgSQL_expr *expr, Bitmapset *local_dnos); static void -free_block(PLpgSQL_stmt_block *block) +mark_stmt(PLpgSQL_stmt *stmt, Bitmapset *local_dnos) { - free_stmts(block->body); - if (block->exceptions) + if (stmt == NULL) + return; + if (stmt->cmd_type == PLPGSQL_STMT_BLOCK) { - ListCell *e; + PLpgSQL_stmt_block *block = (PLpgSQL_stmt_block *) stmt; - foreach(e, block->exceptions->exc_list) + if (block->exceptions) { - PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e); - - free_stmts(exc->action); + /* + * The block creates a new exception scope, so variables declared + * at outer levels are nonlocal. For that matter, so are any + * variables declared in the block's DECLARE section. Hence, we + * must pass down empty local_dnos. + */ + plpgsql_statement_tree_walker(stmt, mark_stmt, mark_expr, NULL); + } + else + { + /* + * Otherwise, the block does not create a new exception scope, and + * any variables it declares can also be considered local within + * it. Note that only initializable datum types (VAR, REC) are + * included in initvarnos; but that's sufficient for our purposes. + */ + local_dnos = bms_copy(local_dnos); + for (int i = 0; i < block->n_initvars; i++) + local_dnos = bms_add_member(local_dnos, block->initvarnos[i]); + plpgsql_statement_tree_walker(stmt, mark_stmt, mark_expr, + local_dnos); + bms_free(local_dnos); } } + else + plpgsql_statement_tree_walker(stmt, mark_stmt, mark_expr, local_dnos); } static void -free_assign(PLpgSQL_stmt_assign *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_if(PLpgSQL_stmt_if *stmt) -{ - ListCell *l; - - free_expr(stmt->cond); - free_stmts(stmt->then_body); - foreach(l, stmt->elsif_list) - { - PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l); - - free_expr(elif->cond); - free_stmts(elif->stmts); - } - free_stmts(stmt->else_body); -} - -static void -free_case(PLpgSQL_stmt_case *stmt) -{ - ListCell *l; - - free_expr(stmt->t_expr); - foreach(l, stmt->case_when_list) - { - PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l); - - free_expr(cwt->expr); - free_stmts(cwt->stmts); - } - free_stmts(stmt->else_stmts); -} - -static void -free_loop(PLpgSQL_stmt_loop *stmt) -{ - free_stmts(stmt->body); -} - -static void -free_while(PLpgSQL_stmt_while *stmt) -{ - free_expr(stmt->cond); - free_stmts(stmt->body); -} - -static void -free_fori(PLpgSQL_stmt_fori *stmt) -{ - free_expr(stmt->lower); - free_expr(stmt->upper); - free_expr(stmt->step); - free_stmts(stmt->body); -} - -static void -free_fors(PLpgSQL_stmt_fors *stmt) -{ - free_stmts(stmt->body); - free_expr(stmt->query); -} - -static void -free_forc(PLpgSQL_stmt_forc *stmt) -{ - free_stmts(stmt->body); - free_expr(stmt->argquery); -} - -static void -free_foreach_a(PLpgSQL_stmt_foreach_a *stmt) -{ - free_expr(stmt->expr); - free_stmts(stmt->body); -} - -static void -free_open(PLpgSQL_stmt_open *stmt) -{ - ListCell *lc; - - free_expr(stmt->argquery); - free_expr(stmt->query); - free_expr(stmt->dynquery); - foreach(lc, stmt->params) - { - free_expr((PLpgSQL_expr *) lfirst(lc)); - } -} - -static void -free_fetch(PLpgSQL_stmt_fetch *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_close(PLpgSQL_stmt_close *stmt) -{ -} - -static void -free_perform(PLpgSQL_stmt_perform *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_call(PLpgSQL_stmt_call *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_commit(PLpgSQL_stmt_commit *stmt) -{ -} - -static void -free_rollback(PLpgSQL_stmt_rollback *stmt) -{ -} - -static void -free_exit(PLpgSQL_stmt_exit *stmt) -{ - free_expr(stmt->cond); -} - -static void -free_return(PLpgSQL_stmt_return *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_return_next(PLpgSQL_stmt_return_next *stmt) -{ - free_expr(stmt->expr); -} - -static void -free_return_query(PLpgSQL_stmt_return_query *stmt) -{ - ListCell *lc; - - free_expr(stmt->query); - free_expr(stmt->dynquery); - foreach(lc, stmt->params) - { - free_expr((PLpgSQL_expr *) lfirst(lc)); - } -} - -static void -free_raise(PLpgSQL_stmt_raise *stmt) -{ - ListCell *lc; - - foreach(lc, stmt->params) - { - free_expr((PLpgSQL_expr *) lfirst(lc)); - } - foreach(lc, stmt->options) - { - PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc); - - free_expr(opt->expr); - } -} - -static void -free_assert(PLpgSQL_stmt_assert *stmt) -{ - free_expr(stmt->cond); - free_expr(stmt->message); -} - -static void -free_execsql(PLpgSQL_stmt_execsql *stmt) +mark_expr(PLpgSQL_expr *expr, Bitmapset *local_dnos) { - free_expr(stmt->sqlstmt); + /* + * If this expression has an assignment target, check whether the target + * is local, and mark the expression accordingly. + */ + if (expr && expr->target_param >= 0) + expr->target_is_local = bms_is_member(expr->target_param, local_dnos); } -static void -free_dynexecute(PLpgSQL_stmt_dynexecute *stmt) +void +plpgsql_mark_local_assignment_targets(PLpgSQL_function *func) { - ListCell *lc; + Bitmapset *local_dnos; - free_expr(stmt->query); - foreach(lc, stmt->params) - { - free_expr((PLpgSQL_expr *) lfirst(lc)); - } + /* Function parameters can be treated as local targets at outer level */ + local_dnos = NULL; + for (int i = 0; i < func->fn_nargs; i++) + local_dnos = bms_add_member(local_dnos, func->fn_argvarnos[i]); + mark_stmt((PLpgSQL_stmt *) func->action, local_dnos); + bms_free(local_dnos); } -static void -free_dynfors(PLpgSQL_stmt_dynfors *stmt) -{ - ListCell *lc; - free_stmts(stmt->body); - free_expr(stmt->query); - foreach(lc, stmt->params) - { - free_expr((PLpgSQL_expr *) lfirst(lc)); - } -} +/********************************************************************** + * Release memory when a PL/pgSQL function is no longer needed + * + * This code only needs to deal with cleaning up PLpgSQL_expr nodes, + * which may contain references to saved SPI Plans that must be freed. + * The function tree itself, along with subsidiary data, is freed in + * one swoop by freeing the function's permanent memory context. + **********************************************************************/ +static void free_stmt(PLpgSQL_stmt *stmt, void *context); +static void free_expr(PLpgSQL_expr *expr, void *context); static void -free_getdiag(PLpgSQL_stmt_getdiag *stmt) +free_stmt(PLpgSQL_stmt *stmt, void *context) { + if (stmt == NULL) + return; + plpgsql_statement_tree_walker(stmt, free_stmt, free_expr, NULL); } static void -free_expr(PLpgSQL_expr *expr) +free_expr(PLpgSQL_expr *expr, void *context) { if (expr && expr->plan) { @@ -729,7 +718,7 @@ plpgsql_free_function_memory(PLpgSQL_function *func) int i; /* Better not call this on an in-use function */ - Assert(func->use_count == 0); + Assert(func->cfunc.use_count == 0); /* Release plans associated with variable declarations */ for (i = 0; i < func->ndatums; i++) @@ -743,8 +732,8 @@ plpgsql_free_function_memory(PLpgSQL_function *func) { PLpgSQL_var *var = (PLpgSQL_var *) d; - free_expr(var->default_val); - free_expr(var->cursor_explicit_expr); + free_expr(var->default_val, NULL); + free_expr(var->cursor_explicit_expr, NULL); } break; case PLPGSQL_DTYPE_ROW: @@ -753,7 +742,7 @@ plpgsql_free_function_memory(PLpgSQL_function *func) { PLpgSQL_rec *rec = (PLpgSQL_rec *) d; - free_expr(rec->default_val); + free_expr(rec->default_val, NULL); } break; case PLPGSQL_DTYPE_RECFIELD: @@ -765,8 +754,7 @@ plpgsql_free_function_memory(PLpgSQL_function *func) func->ndatums = 0; /* Release plans in statement tree */ - if (func->action) - free_block(func->action); + free_stmt((PLpgSQL_stmt *) func->action, NULL); func->action = NULL; /* @@ -779,9 +767,19 @@ plpgsql_free_function_memory(PLpgSQL_function *func) func->fn_cxt = NULL; } +/* Deletion callback used by funccache.c */ +void +plpgsql_delete_callback(CachedFunction *cfunc) +{ + plpgsql_free_function_memory((PLpgSQL_function *) cfunc); +} + /********************************************************************** * Debug functions for analyzing the compiled code + * + * Sadly, there doesn't seem to be any way to let plpgsql_statement_tree_walker + * bear some of the burden for this. **********************************************************************/ static int dump_indent; @@ -1594,6 +1592,9 @@ static void dump_expr(PLpgSQL_expr *expr) { printf("'%s'", expr->query); + if (expr->target_param >= 0) + printf(" target %d%s", expr->target_param, + expr->target_is_local ? " (local)" : ""); } void diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index 0671ff787229e..5612e66d0239d 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -3,7 +3,7 @@ * * pl_gram.y - Parser for the PL/pgSQL procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -26,10 +26,7 @@ #include "plpgsql.h" - -/* silence -Wmissing-variable-declarations */ -extern int plpgsql_yychar; -extern int plpgsql_yynerrs; +#include "pl_gram.h" /* Location tracking support --- simpler than bison's default */ #define YYLLOC_DEFAULT(Current, Rhs, N) \ @@ -52,17 +49,22 @@ extern int plpgsql_yynerrs; typedef struct { int location; + yyscan_t yyscanner; } sql_error_callback_arg; -#define parser_errposition(pos) plpgsql_scanner_errposition(pos) +#define parser_errposition(pos) plpgsql_scanner_errposition(pos, yyscanner) union YYSTYPE; /* need forward reference for tok_is_keyword */ static bool tok_is_keyword(int token, union YYSTYPE *lval, int kw_token, const char *kw_str); -static void word_is_not_variable(PLword *word, int location); -static void cword_is_not_variable(PLcword *cword, int location); -static void current_token_is_not_variable(int tok); +static void word_is_not_variable(PLword *word, int location, yyscan_t yyscanner); +static void cword_is_not_variable(PLcword *cword, int location, yyscan_t yyscanner); +static void current_token_is_not_variable(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_expr *make_plpgsql_expr(const char *query, + RawParseMode parsemode); +static void mark_expr_as_assignment_source(PLpgSQL_expr *expr, + PLpgSQL_datum *target); static PLpgSQL_expr *read_sql_construct(int until, int until2, int until3, @@ -71,48 +73,57 @@ static PLpgSQL_expr *read_sql_construct(int until, bool isexpression, bool valid_sql, int *startloc, - int *endtoken); -static PLpgSQL_expr *read_sql_expression(int until, - const char *expected); + int *endtoken, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, + yyscan_t yyscanner); +static PLpgSQL_expr *read_sql_expression(int until, const char *expected, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static PLpgSQL_expr *read_sql_expression2(int until, int until2, - const char *expected, - int *endtoken); -static PLpgSQL_expr *read_sql_stmt(void); -static PLpgSQL_type *read_datatype(int tok); + const char *expected, int *endtoken, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_expr *read_sql_stmt(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_type *read_datatype(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static PLpgSQL_stmt *make_execsql_stmt(int firsttoken, int location, - PLword *word); -static PLpgSQL_stmt_fetch *read_fetch_direction(void); + PLword *word, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_stmt_fetch *read_fetch_direction(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static void complete_direction(PLpgSQL_stmt_fetch *fetch, - bool *check_FROM); -static PLpgSQL_stmt *make_return_stmt(int location); -static PLpgSQL_stmt *make_return_next_stmt(int location); -static PLpgSQL_stmt *make_return_query_stmt(int location); + bool *check_FROM, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_stmt *make_return_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_stmt *make_return_next_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static PLpgSQL_stmt *make_return_query_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static PLpgSQL_stmt *make_case(int location, PLpgSQL_expr *t_expr, - List *case_when_list, List *else_stmts); + List *case_when_list, List *else_stmts, yyscan_t yyscanner); static char *NameOfDatum(PLwdatum *wdatum); -static void check_assignable(PLpgSQL_datum *datum, int location); -static void read_into_target(PLpgSQL_variable **target, - bool *strict); +static void check_assignable(PLpgSQL_datum *datum, int location, yyscan_t yyscanner); +static void read_into_target(PLpgSQL_variable **target, bool *strict, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static PLpgSQL_row *read_into_scalar_list(char *initial_name, PLpgSQL_datum *initial_datum, - int initial_location); + int initial_location, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, + yyscan_t yyscanner); static PLpgSQL_row *make_scalar_list1(char *initial_name, PLpgSQL_datum *initial_datum, - int lineno, int location); + int lineno, int location, yyscan_t yyscanner); static void check_sql_expr(const char *stmt, - RawParseMode parseMode, int location); + RawParseMode parseMode, int location, yyscan_t yyscanner); static void plpgsql_sql_error_callback(void *arg); -static PLpgSQL_type *parse_datatype(const char *string, int location); +static PLpgSQL_type *parse_datatype(const char *string, int location, yyscan_t yyscanner); static void check_labels(const char *start_label, const char *end_label, - int end_location); -static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor, - int until); -static List *read_raise_options(void); + int end_location, + yyscan_t yyscanner); +static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor, int until, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +static List *read_raise_options(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); %} +%parse-param {PLpgSQL_stmt_block **plpgsql_parse_result_p} +%parse-param {yyscan_t yyscanner} +%lex-param {yyscan_t yyscanner} +%pure-parser %expect 0 %name-prefix="plpgsql_yy" %locations @@ -362,7 +373,8 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); pl_function : comp_options pl_block opt_semi { - plpgsql_parse_result = (PLpgSQL_stmt_block *) $2; + *plpgsql_parse_result_p = (PLpgSQL_stmt_block *) $2; + (void) yynerrs; /* suppress compiler warning */ } ; @@ -417,7 +429,7 @@ pl_block : decl_sect K_BEGIN proc_sect exception_sect K_END opt_label new = palloc0(sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->label = $1.label; new->n_initvars = $1.n_initvars; @@ -425,7 +437,7 @@ pl_block : decl_sect K_BEGIN proc_sect exception_sect K_END opt_label new->body = $3; new->exceptions = $4; - check_labels($1.label, $6, @6); + check_labels($1.label, $6, @6, yyscanner); plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *) new; @@ -528,6 +540,10 @@ decl_statement : decl_varname decl_const decl_datatype decl_collate decl_notnull errmsg("variable \"%s\" must have a default value, since it's declared NOT NULL", var->refname), parser_errposition(@5))); + + if (var->default_val != NULL) + mark_expr_as_assignment_source(var->default_val, + (PLpgSQL_datum *) var); } | decl_varname K_ALIAS K_FOR decl_aliasitem ';' { @@ -576,7 +592,7 @@ opt_scrollable : decl_cursor_query : { - $$ = read_sql_stmt(); + $$ = read_sql_stmt(&yylval, &yylloc, yyscanner); } ; @@ -593,7 +609,7 @@ decl_cursor_args : new = palloc0(sizeof(PLpgSQL_row)); new->dtype = PLPGSQL_DTYPE_ROW; new->refname = "(unnamed row)"; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->rowtupdesc = NULL; new->nfields = list_length($2); new->fieldnames = palloc(new->nfields * sizeof(char *)); @@ -697,7 +713,7 @@ decl_aliasitem : T_WORD decl_varname : T_WORD { $$.name = $1.ident; - $$.lineno = plpgsql_location_to_lineno(@1); + $$.lineno = plpgsql_location_to_lineno(@1, yyscanner); /* * Check to make sure name isn't already declared * in the current block. @@ -705,7 +721,7 @@ decl_varname : T_WORD if (plpgsql_ns_lookup(plpgsql_ns_top(), true, $1.ident, NULL, NULL, NULL) != NULL) - yyerror("duplicate declaration"); + yyerror(&yylloc, NULL, yyscanner, "duplicate declaration"); if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR || plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR) @@ -725,7 +741,7 @@ decl_varname : T_WORD | unreserved_keyword { $$.name = pstrdup($1); - $$.lineno = plpgsql_location_to_lineno(@1); + $$.lineno = plpgsql_location_to_lineno(@1, yyscanner); /* * Check to make sure name isn't already declared * in the current block. @@ -733,7 +749,7 @@ decl_varname : T_WORD if (plpgsql_ns_lookup(plpgsql_ns_top(), true, $1, NULL, NULL, NULL) != NULL) - yyerror("duplicate declaration"); + yyerror(&yylloc, NULL, yyscanner, "duplicate declaration"); if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR || plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR) @@ -765,7 +781,7 @@ decl_datatype : * consume it, and then we must tell bison to forget * it. */ - $$ = read_datatype(yychar); + $$ = read_datatype(yychar, &yylval, &yylloc, yyscanner); yyclearin; } ; @@ -798,7 +814,7 @@ decl_defval : ';' { $$ = NULL; } | decl_defkey { - $$ = read_sql_expression(';', ";"); + $$ = read_sql_expression(';', ";", &yylval, &yylloc, yyscanner); } ; @@ -884,9 +900,9 @@ stmt_perform : K_PERFORM new = palloc0(sizeof(PLpgSQL_stmt_perform)); new->cmd_type = PLPGSQL_STMT_PERFORM; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; - plpgsql_push_back_token(K_PERFORM); + plpgsql_push_back_token(K_PERFORM, &yylval, &yylloc, yyscanner); /* * Since PERFORM isn't legal SQL, we have to cheat to @@ -899,7 +915,8 @@ stmt_perform : K_PERFORM new->expr = read_sql_construct(';', 0, 0, ";", RAW_PARSE_DEFAULT, false, false, - &startloc, NULL); + &startloc, NULL, + &yylval, &yylloc, yyscanner); /* overwrite "perform" ... */ memcpy(new->expr->query, " SELECT", 7); /* left-justify to get rid of the leading space */ @@ -907,7 +924,7 @@ stmt_perform : K_PERFORM strlen(new->expr->query)); /* offset syntax error position to account for that */ check_sql_expr(new->expr->query, new->expr->parseMode, - startloc + 1); + startloc + 1, yyscanner); $$ = (PLpgSQL_stmt *) new; } @@ -919,10 +936,10 @@ stmt_call : K_CALL new = palloc0(sizeof(PLpgSQL_stmt_call)); new->cmd_type = PLPGSQL_STMT_CALL; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; - plpgsql_push_back_token(K_CALL); - new->expr = read_sql_stmt(); + plpgsql_push_back_token(K_CALL, &yylval, &yylloc, yyscanner); + new->expr = read_sql_stmt(&yylval, &yylloc, yyscanner); new->is_call = true; /* Remember we may need a procedure resource owner */ @@ -938,10 +955,10 @@ stmt_call : K_CALL new = palloc0(sizeof(PLpgSQL_stmt_call)); new->cmd_type = PLPGSQL_STMT_CALL; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; - plpgsql_push_back_token(K_DO); - new->expr = read_sql_stmt(); + plpgsql_push_back_token(K_DO, &yylval, &yylloc, yyscanner); + new->expr = read_sql_stmt(&yylval, &yylloc, yyscanner); new->is_call = false; /* Remember we may need a procedure resource owner */ @@ -974,18 +991,20 @@ stmt_assign : T_DATUM pmode = 0; /* keep compiler quiet */ } - check_assignable($1.datum, @1); + check_assignable($1.datum, @1, yyscanner); new = palloc0(sizeof(PLpgSQL_stmt_assign)); new->cmd_type = PLPGSQL_STMT_ASSIGN; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->varno = $1.datum->dno; /* Push back the head name to include it in the stmt */ - plpgsql_push_back_token(T_DATUM); + plpgsql_push_back_token(T_DATUM, &yylval, &yylloc, yyscanner); new->expr = read_sql_construct(';', 0, 0, ";", pmode, false, true, - NULL, NULL); + NULL, NULL, + &yylval, &yylloc, yyscanner); + mark_expr_as_assignment_source(new->expr, $1.datum); $$ = (PLpgSQL_stmt *) new; } @@ -998,7 +1017,7 @@ stmt_getdiag : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';' new = palloc0(sizeof(PLpgSQL_stmt_getdiag)); new->cmd_type = PLPGSQL_STMT_GETDIAG; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->is_stacked = $2; new->diag_items = $4; @@ -1092,7 +1111,7 @@ getdiag_list_item : getdiag_target assign_operator getdiag_item getdiag_item : { - int tok = yylex(); + int tok = yylex(&yylval, &yylloc, yyscanner); if (tok_is_keyword(tok, &yylval, K_ROW_COUNT, "row_count")) @@ -1134,7 +1153,7 @@ getdiag_item : K_RETURNED_SQLSTATE, "returned_sqlstate")) $$ = PLPGSQL_GETDIAG_RETURNED_SQLSTATE; else - yyerror("unrecognized GET DIAGNOSTICS item"); + yyerror(&yylloc, NULL, yyscanner, "unrecognized GET DIAGNOSTICS item"); } ; @@ -1147,24 +1166,24 @@ getdiag_target : T_DATUM */ if ($1.datum->dtype == PLPGSQL_DTYPE_ROW || $1.datum->dtype == PLPGSQL_DTYPE_REC || - plpgsql_peek() == '[') + plpgsql_peek(yyscanner) == '[') ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("\"%s\" is not a scalar variable", NameOfDatum(&($1))), parser_errposition(@1))); - check_assignable($1.datum, @1); + check_assignable($1.datum, @1, yyscanner); $$ = $1.datum; } | T_WORD { /* just to give a better message than "syntax error" */ - word_is_not_variable(&($1), @1); + word_is_not_variable(&($1), @1, yyscanner); } | T_CWORD { /* just to give a better message than "syntax error" */ - cword_is_not_variable(&($1), @1); + cword_is_not_variable(&($1), @1, yyscanner); } ; @@ -1174,7 +1193,7 @@ stmt_if : K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';' new = palloc0(sizeof(PLpgSQL_stmt_if)); new->cmd_type = PLPGSQL_STMT_IF; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->cond = $2; new->then_body = $3; @@ -1194,7 +1213,7 @@ stmt_elsifs : PLpgSQL_if_elsif *new; new = palloc0(sizeof(PLpgSQL_if_elsif)); - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->cond = $3; new->stmts = $4; @@ -1214,21 +1233,21 @@ stmt_else : stmt_case : K_CASE opt_expr_until_when case_when_list opt_case_else K_END K_CASE ';' { - $$ = make_case(@1, $2, $3, $4); + $$ = make_case(@1, $2, $3, $4, yyscanner); } ; opt_expr_until_when : { PLpgSQL_expr *expr = NULL; - int tok = yylex(); + int tok = yylex(&yylval, &yylloc, yyscanner); if (tok != K_WHEN) { - plpgsql_push_back_token(tok); - expr = read_sql_expression(K_WHEN, "WHEN"); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); + expr = read_sql_expression(K_WHEN, "WHEN", &yylval, &yylloc, yyscanner); } - plpgsql_push_back_token(K_WHEN); + plpgsql_push_back_token(K_WHEN, &yylval, &yylloc, yyscanner); $$ = expr; } ; @@ -1247,7 +1266,7 @@ case_when : K_WHEN expr_until_then proc_sect { PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when)); - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->expr = $2; new->stmts = $3; $$ = new; @@ -1279,12 +1298,12 @@ stmt_loop : opt_loop_label K_LOOP loop_body new = palloc0(sizeof(PLpgSQL_stmt_loop)); new->cmd_type = PLPGSQL_STMT_LOOP; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->label = $1; new->body = $3.stmts; - check_labels($1, $3.end_label, $3.end_label_location); + check_labels($1, $3.end_label, $3.end_label_location, yyscanner); plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *) new; @@ -1297,13 +1316,13 @@ stmt_while : opt_loop_label K_WHILE expr_until_loop loop_body new = palloc0(sizeof(PLpgSQL_stmt_while)); new->cmd_type = PLPGSQL_STMT_WHILE; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->label = $1; new->cond = $3; new->body = $4.stmts; - check_labels($1, $4.end_label, $4.end_label_location); + check_labels($1, $4.end_label, $4.end_label_location, yyscanner); plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *) new; @@ -1318,7 +1337,7 @@ stmt_for : opt_loop_label K_FOR for_control loop_body PLpgSQL_stmt_fori *new; new = (PLpgSQL_stmt_fori *) $3; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->label = $1; new->body = $4.stmts; $$ = (PLpgSQL_stmt *) new; @@ -1332,13 +1351,13 @@ stmt_for : opt_loop_label K_FOR for_control loop_body $3->cmd_type == PLPGSQL_STMT_DYNFORS); /* forq is the common supertype of all three */ new = (PLpgSQL_stmt_forq *) $3; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->label = $1; new->body = $4.stmts; $$ = (PLpgSQL_stmt *) new; } - check_labels($1, $4.end_label, $4.end_label_location); + check_labels($1, $4.end_label, $4.end_label_location, yyscanner); /* close namespace started in opt_loop_label */ plpgsql_ns_pop(); } @@ -1346,7 +1365,7 @@ stmt_for : opt_loop_label K_FOR for_control loop_body for_control : for_variable K_IN { - int tok = yylex(); + int tok = yylex(&yylval, &yylloc, yyscanner); int tokloc = yylloc; if (tok == K_EXECUTE) @@ -1358,7 +1377,7 @@ for_control : for_variable K_IN expr = read_sql_expression2(K_LOOP, K_USING, "LOOP or USING", - &term); + &term, &yylval, &yylloc, yyscanner); new = palloc0(sizeof(PLpgSQL_stmt_dynfors)); new->cmd_type = PLPGSQL_STMT_DYNFORS; @@ -1366,14 +1385,14 @@ for_control : for_variable K_IN if ($1.row) { new->var = (PLpgSQL_variable *) $1.row; - check_assignable($1.row, @1); + check_assignable($1.row, @1, yyscanner); } else if ($1.scalar) { /* convert single scalar to list */ new->var = (PLpgSQL_variable *) make_scalar_list1($1.name, $1.scalar, - $1.lineno, @1); + $1.lineno, @1, yyscanner); /* make_scalar_list1 did check_assignable */ } else @@ -1391,7 +1410,7 @@ for_control : for_variable K_IN { expr = read_sql_expression2(',', K_LOOP, ", or LOOP", - &term); + &term, &yylval, &yylloc, yyscanner); new->params = lappend(new->params, expr); } while (term == ','); } @@ -1426,8 +1445,7 @@ for_control : for_variable K_IN parser_errposition(tokloc))); /* collect cursor's parameters if any */ - new->argquery = read_cursor_args(cursor, - K_LOOP); + new->argquery = read_cursor_args(cursor, K_LOOP, &yylval, &yylloc, yyscanner); /* create loop's private RECORD variable */ new->var = (PLpgSQL_variable *) @@ -1461,7 +1479,7 @@ for_control : for_variable K_IN K_REVERSE, "reverse")) reverse = true; else - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); /* * Read tokens until we see either a ".." @@ -1478,7 +1496,8 @@ for_control : for_variable K_IN true, false, &expr1loc, - &tok); + &tok, + &yylval, &yylloc, yyscanner); if (tok == DOT_DOT) { @@ -1494,17 +1513,17 @@ for_control : for_variable K_IN */ expr1->parseMode = RAW_PARSE_PLPGSQL_EXPR; check_sql_expr(expr1->query, expr1->parseMode, - expr1loc); + expr1loc, yyscanner); /* Read and check the second one */ expr2 = read_sql_expression2(K_LOOP, K_BY, "LOOP", - &tok); + &tok, &yylval, &yylloc, yyscanner); /* Get the BY clause if any */ if (tok == K_BY) expr_by = read_sql_expression(K_LOOP, - "LOOP"); + "LOOP", &yylval, &yylloc, yyscanner); else expr_by = NULL; @@ -1551,7 +1570,7 @@ for_control : for_variable K_IN /* Check syntax as a regular query */ check_sql_expr(expr1->query, expr1->parseMode, - expr1loc); + expr1loc, yyscanner); new = palloc0(sizeof(PLpgSQL_stmt_fors)); new->cmd_type = PLPGSQL_STMT_FORS; @@ -1559,14 +1578,14 @@ for_control : for_variable K_IN if ($1.row) { new->var = (PLpgSQL_variable *) $1.row; - check_assignable($1.row, @1); + check_assignable($1.row, @1, yyscanner); } else if ($1.scalar) { /* convert single scalar to list */ new->var = (PLpgSQL_variable *) make_scalar_list1($1.name, $1.scalar, - $1.lineno, @1); + $1.lineno, @1, yyscanner); /* make_scalar_list1 did check_assignable */ } else @@ -1605,7 +1624,7 @@ for_control : for_variable K_IN for_variable : T_DATUM { $$.name = NameOfDatum(&($1)); - $$.lineno = plpgsql_location_to_lineno(@1); + $$.lineno = plpgsql_location_to_lineno(@1, yyscanner); if ($1.datum->dtype == PLPGSQL_DTYPE_ROW || $1.datum->dtype == PLPGSQL_DTYPE_REC) { @@ -1619,13 +1638,15 @@ for_variable : T_DATUM $$.scalar = $1.datum; $$.row = NULL; /* check for comma-separated list */ - tok = yylex(); - plpgsql_push_back_token(tok); + tok = yylex(&yylval, &yylloc, yyscanner); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); if (tok == ',') $$.row = (PLpgSQL_datum *) read_into_scalar_list($$.name, $$.scalar, - @1); + @1, + &yylval, &yylloc, + yyscanner); } } | T_WORD @@ -1633,19 +1654,19 @@ for_variable : T_DATUM int tok; $$.name = $1.ident; - $$.lineno = plpgsql_location_to_lineno(@1); + $$.lineno = plpgsql_location_to_lineno(@1, yyscanner); $$.scalar = NULL; $$.row = NULL; /* check for comma-separated list */ - tok = yylex(); - plpgsql_push_back_token(tok); + tok = yylex(&yylval, &yylloc, yyscanner); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); if (tok == ',') - word_is_not_variable(&($1), @1); + word_is_not_variable(&($1), @1, yyscanner); } | T_CWORD { /* just to give a better message than "syntax error" */ - cword_is_not_variable(&($1), @1); + cword_is_not_variable(&($1), @1, yyscanner); } ; @@ -1655,7 +1676,7 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA new = palloc0(sizeof(PLpgSQL_stmt_foreach_a)); new->cmd_type = PLPGSQL_STMT_FOREACH_A; - new->lineno = plpgsql_location_to_lineno(@2); + new->lineno = plpgsql_location_to_lineno(@2, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->label = $1; new->slice = $4; @@ -1665,12 +1686,12 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA if ($3.row) { new->varno = $3.row->dno; - check_assignable($3.row, @3); + check_assignable($3.row, @3, yyscanner); } else if ($3.scalar) { new->varno = $3.scalar->dno; - check_assignable($3.scalar, @3); + check_assignable($3.scalar, @3, yyscanner); } else { @@ -1680,7 +1701,7 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA parser_errposition(@3))); } - check_labels($1, $8.end_label, $8.end_label_location); + check_labels($1, $8.end_label, $8.end_label_location, yyscanner); plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *) new; @@ -1705,7 +1726,7 @@ stmt_exit : exit_type opt_label opt_exitcond new->cmd_type = PLPGSQL_STMT_EXIT; new->stmtid = ++plpgsql_curr_compile->nstatements; new->is_exit = $1; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->label = $2; new->cond = $3; @@ -1764,24 +1785,24 @@ stmt_return : K_RETURN { int tok; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition"); if (tok_is_keyword(tok, &yylval, K_NEXT, "next")) { - $$ = make_return_next_stmt(@1); + $$ = make_return_next_stmt(@1, &yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_QUERY, "query")) { - $$ = make_return_query_stmt(@1); + $$ = make_return_query_stmt(@1, &yylval, &yylloc, yyscanner); } else { - plpgsql_push_back_token(tok); - $$ = make_return_stmt(@1); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); + $$ = make_return_stmt(@1, &yylval, &yylloc, yyscanner); } } ; @@ -1794,7 +1815,7 @@ stmt_raise : K_RAISE new = palloc(sizeof(PLpgSQL_stmt_raise)); new->cmd_type = PLPGSQL_STMT_RAISE; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->elog_level = ERROR; /* default */ new->condname = NULL; @@ -1802,9 +1823,9 @@ stmt_raise : K_RAISE new->params = NIL; new->options = NIL; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition"); /* * We could have just RAISE, meaning to re-throw @@ -1819,40 +1840,40 @@ stmt_raise : K_RAISE K_EXCEPTION, "exception")) { new->elog_level = ERROR; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_WARNING, "warning")) { new->elog_level = WARNING; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_NOTICE, "notice")) { new->elog_level = NOTICE; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_INFO, "info")) { new->elog_level = INFO; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_LOG, "log")) { new->elog_level = LOG; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } else if (tok_is_keyword(tok, &yylval, K_DEBUG, "debug")) { new->elog_level = DEBUG1; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(&yylloc, NULL, yyscanner, "unexpected end of function definition"); /* * Next we can have a condition name, or @@ -1870,9 +1891,9 @@ stmt_raise : K_RAISE * begins the list of parameter expressions, * or USING to begin the options list. */ - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok != ',' && tok != ';' && tok != K_USING) - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); while (tok == ',') { @@ -1882,7 +1903,8 @@ stmt_raise : K_RAISE ", or ; or USING", RAW_PARSE_PLPGSQL_EXPR, true, true, - NULL, &tok); + NULL, &tok, + &yylval, &yylloc, yyscanner); new->params = lappend(new->params, expr); } } @@ -1895,14 +1917,14 @@ stmt_raise : K_RAISE /* next token should be a string literal */ char *sqlstatestr; - if (yylex() != SCONST) - yyerror("syntax error"); + if (yylex(&yylval, &yylloc, yyscanner) != SCONST) + yyerror(&yylloc, NULL, yyscanner, "syntax error"); sqlstatestr = yylval.str; if (strlen(sqlstatestr) != 5) - yyerror("invalid SQLSTATE code"); + yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code"); if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5) - yyerror("invalid SQLSTATE code"); + yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code"); new->condname = sqlstatestr; } else @@ -1912,17 +1934,17 @@ stmt_raise : K_RAISE else if (plpgsql_token_is_unreserved_keyword(tok)) new->condname = pstrdup(yylval.keyword); else - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); plpgsql_recognize_err_condition(new->condname, false); } - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok != ';' && tok != K_USING) - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); } if (tok == K_USING) - new->options = read_raise_options(); + new->options = read_raise_options(&yylval, &yylloc, yyscanner); } check_raise_parameters(new); @@ -1939,15 +1961,15 @@ stmt_assert : K_ASSERT new = palloc(sizeof(PLpgSQL_stmt_assert)); new->cmd_type = PLPGSQL_STMT_ASSERT; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->cond = read_sql_expression2(',', ';', ", or ;", - &tok); + &tok, &yylval, &yylloc, yyscanner); if (tok == ',') - new->message = read_sql_expression(';', ";"); + new->message = read_sql_expression(';', ";", &yylval, &yylloc, yyscanner); else new->message = NULL; @@ -1975,37 +1997,37 @@ loop_body : proc_sect K_END K_LOOP opt_label ';' */ stmt_execsql : K_IMPORT { - $$ = make_execsql_stmt(K_IMPORT, @1, NULL); + $$ = make_execsql_stmt(K_IMPORT, @1, NULL, &yylval, &yylloc, yyscanner); } | K_INSERT { - $$ = make_execsql_stmt(K_INSERT, @1, NULL); + $$ = make_execsql_stmt(K_INSERT, @1, NULL, &yylval, &yylloc, yyscanner); } | K_MERGE { - $$ = make_execsql_stmt(K_MERGE, @1, NULL); + $$ = make_execsql_stmt(K_MERGE, @1, NULL, &yylval, &yylloc, yyscanner); } | T_WORD { int tok; - tok = yylex(); - plpgsql_push_back_token(tok); + tok = yylex(&yylval, &yylloc, yyscanner); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); if (tok == '=' || tok == COLON_EQUALS || tok == '[' || tok == '.') - word_is_not_variable(&($1), @1); - $$ = make_execsql_stmt(T_WORD, @1, &($1)); + word_is_not_variable(&($1), @1, yyscanner); + $$ = make_execsql_stmt(T_WORD, @1, &($1), &yylval, &yylloc, yyscanner); } | T_CWORD { int tok; - tok = yylex(); - plpgsql_push_back_token(tok); + tok = yylex(&yylval, &yylloc, yyscanner); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); if (tok == '=' || tok == COLON_EQUALS || tok == '[' || tok == '.') - cword_is_not_variable(&($1), @1); - $$ = make_execsql_stmt(T_CWORD, @1, NULL); + cword_is_not_variable(&($1), @1, yyscanner); + $$ = make_execsql_stmt(T_CWORD, @1, NULL, &yylval, &yylloc, yyscanner); } ; @@ -2019,11 +2041,12 @@ stmt_dynexecute : K_EXECUTE "INTO or USING or ;", RAW_PARSE_PLPGSQL_EXPR, true, true, - NULL, &endtoken); + NULL, &endtoken, + &yylval, &yylloc, yyscanner); new = palloc(sizeof(PLpgSQL_stmt_dynexecute)); new->cmd_type = PLPGSQL_STMT_DYNEXECUTE; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->query = expr; new->into = false; @@ -2043,29 +2066,30 @@ stmt_dynexecute : K_EXECUTE if (endtoken == K_INTO) { if (new->into) /* multiple INTO */ - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); new->into = true; - read_into_target(&new->target, &new->strict); - endtoken = yylex(); + read_into_target(&new->target, &new->strict, &yylval, &yylloc, yyscanner); + endtoken = yylex(&yylval, &yylloc, yyscanner); } else if (endtoken == K_USING) { if (new->params) /* multiple USING */ - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); do { expr = read_sql_construct(',', ';', K_INTO, ", or ; or INTO", RAW_PARSE_PLPGSQL_EXPR, true, true, - NULL, &endtoken); + NULL, &endtoken, + &yylval, &yylloc, yyscanner); new->params = lappend(new->params, expr); } while (endtoken == ','); } else if (endtoken == ';') break; else - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); } $$ = (PLpgSQL_stmt *) new; @@ -2080,7 +2104,7 @@ stmt_open : K_OPEN cursor_variable new = palloc0(sizeof(PLpgSQL_stmt_open)); new->cmd_type = PLPGSQL_STMT_OPEN; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->curvar = $2->dno; new->cursor_options = CURSOR_OPT_FAST_PLAN; @@ -2088,29 +2112,29 @@ stmt_open : K_OPEN cursor_variable if ($2->cursor_explicit_expr == NULL) { /* be nice if we could use opt_scrollable here */ - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok_is_keyword(tok, &yylval, K_NO, "no")) { - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok_is_keyword(tok, &yylval, K_SCROLL, "scroll")) { new->cursor_options |= CURSOR_OPT_NO_SCROLL; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } } else if (tok_is_keyword(tok, &yylval, K_SCROLL, "scroll")) { new->cursor_options |= CURSOR_OPT_SCROLL; - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); } if (tok != K_FOR) - yyerror("syntax error, expected \"FOR\""); + yyerror(&yylloc, NULL, yyscanner, "syntax error, expected \"FOR\""); - tok = yylex(); + tok = yylex(&yylval, &yylloc, yyscanner); if (tok == K_EXECUTE) { int endtoken; @@ -2118,7 +2142,7 @@ stmt_open : K_OPEN cursor_variable new->dynquery = read_sql_expression2(K_USING, ';', "USING or ;", - &endtoken); + &endtoken, &yylval, &yylloc, yyscanner); /* If we found "USING", collect argument(s) */ if (endtoken == K_USING) @@ -2129,7 +2153,7 @@ stmt_open : K_OPEN cursor_variable { expr = read_sql_expression2(',', ';', ", or ;", - &endtoken); + &endtoken, &yylval, &yylloc, yyscanner); new->params = lappend(new->params, expr); } while (endtoken == ','); @@ -2137,14 +2161,14 @@ stmt_open : K_OPEN cursor_variable } else { - plpgsql_push_back_token(tok); - new->query = read_sql_stmt(); + plpgsql_push_back_token(tok, &yylval, &yylloc, yyscanner); + new->query = read_sql_stmt(&yylval, &yylloc, yyscanner); } } else { /* predefined cursor query, so read args */ - new->argquery = read_cursor_args($2, ';'); + new->argquery = read_cursor_args($2, ';', &yylval, &yylloc, yyscanner); } $$ = (PLpgSQL_stmt *) new; @@ -2157,10 +2181,10 @@ stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO PLpgSQL_variable *target; /* We have already parsed everything through the INTO keyword */ - read_into_target(&target, NULL); + read_into_target(&target, NULL, &yylval, &yylloc, yyscanner); - if (yylex() != ';') - yyerror("syntax error"); + if (yylex(&yylval, &yylloc, yyscanner) != ';') + yyerror(&yylloc, NULL, yyscanner, "syntax error"); /* * We don't allow multiple rows in PL/pgSQL's FETCH @@ -2172,7 +2196,7 @@ stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO errmsg("FETCH statement cannot return multiple rows"), parser_errposition(@1))); - fetch->lineno = plpgsql_location_to_lineno(@1); + fetch->lineno = plpgsql_location_to_lineno(@1, yyscanner); fetch->target = target; fetch->curvar = $3->dno; fetch->is_move = false; @@ -2185,7 +2209,7 @@ stmt_move : K_MOVE opt_fetch_direction cursor_variable ';' { PLpgSQL_stmt_fetch *fetch = $2; - fetch->lineno = plpgsql_location_to_lineno(@1); + fetch->lineno = plpgsql_location_to_lineno(@1, yyscanner); fetch->curvar = $3->dno; fetch->is_move = true; @@ -2195,7 +2219,7 @@ stmt_move : K_MOVE opt_fetch_direction cursor_variable ';' opt_fetch_direction : { - $$ = read_fetch_direction(); + $$ = read_fetch_direction(&yylval, &yylloc, yyscanner); } ; @@ -2205,7 +2229,7 @@ stmt_close : K_CLOSE cursor_variable ';' new = palloc(sizeof(PLpgSQL_stmt_close)); new->cmd_type = PLPGSQL_STMT_CLOSE; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->curvar = $2->dno; @@ -2226,7 +2250,7 @@ stmt_commit : K_COMMIT opt_transaction_chain ';' new = palloc(sizeof(PLpgSQL_stmt_commit)); new->cmd_type = PLPGSQL_STMT_COMMIT; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->chain = $2; @@ -2240,7 +2264,7 @@ stmt_rollback : K_ROLLBACK opt_transaction_chain ';' new = palloc(sizeof(PLpgSQL_stmt_rollback)); new->cmd_type = PLPGSQL_STMT_ROLLBACK; - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->chain = $2; @@ -2263,7 +2287,7 @@ cursor_variable : T_DATUM * just throw an error if next token is '['. */ if ($1.datum->dtype != PLPGSQL_DTYPE_VAR || - plpgsql_peek() == '[') + plpgsql_peek(yyscanner) == '[') ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cursor variable must be a simple variable"), @@ -2280,12 +2304,12 @@ cursor_variable : T_DATUM | T_WORD { /* just to give a better message than "syntax error" */ - word_is_not_variable(&($1), @1); + word_is_not_variable(&($1), @1, yyscanner); } | T_CWORD { /* just to give a better message than "syntax error" */ - cword_is_not_variable(&($1), @1); + cword_is_not_variable(&($1), @1, yyscanner); } ; @@ -2300,10 +2324,12 @@ exception_sect : * scope of the names extends to the end of the * current block. */ - int lineno = plpgsql_location_to_lineno(@1); + int lineno = plpgsql_location_to_lineno(@1, yyscanner); PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block)); PLpgSQL_variable *var; + plpgsql_curr_compile->has_exception_block = true; + var = plpgsql_build_variable("sqlstate", lineno, plpgsql_build_datatype(TEXTOID, -1, @@ -2348,7 +2374,7 @@ proc_exception : K_WHEN proc_conditions K_THEN proc_sect PLpgSQL_exception *new; new = palloc0(sizeof(PLpgSQL_exception)); - new->lineno = plpgsql_location_to_lineno(@1); + new->lineno = plpgsql_location_to_lineno(@1, yyscanner); new->conditions = $2; new->action = $4; @@ -2383,14 +2409,14 @@ proc_condition : any_identifier char *sqlstatestr; /* next token should be a string literal */ - if (yylex() != SCONST) - yyerror("syntax error"); + if (yylex(&yylval, &yylloc, yyscanner) != SCONST) + yyerror(&yylloc, NULL, yyscanner, "syntax error"); sqlstatestr = yylval.str; if (strlen(sqlstatestr) != 5) - yyerror("invalid SQLSTATE code"); + yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code"); if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5) - yyerror("invalid SQLSTATE code"); + yyerror(&yylloc, NULL, yyscanner, "invalid SQLSTATE code"); new = palloc(sizeof(PLpgSQL_condition)); new->sqlerrstate = @@ -2408,15 +2434,15 @@ proc_condition : any_identifier ; expr_until_semi : - { $$ = read_sql_expression(';', ";"); } + { $$ = read_sql_expression(';', ";", &yylval, &yylloc, yyscanner); } ; expr_until_then : - { $$ = read_sql_expression(K_THEN, "THEN"); } + { $$ = read_sql_expression(K_THEN, "THEN", &yylval, &yylloc, yyscanner); } ; expr_until_loop : - { $$ = read_sql_expression(K_LOOP, "LOOP"); } + { $$ = read_sql_expression(K_LOOP, "LOOP", &yylval, &yylloc, yyscanner); } ; opt_block_label : @@ -2474,7 +2500,7 @@ any_identifier : T_WORD | T_DATUM { if ($1.ident == NULL) /* composite name not OK */ - yyerror("syntax error"); + yyerror(&yylloc, NULL, yyscanner, "syntax error"); $$ = $1.ident; } ; @@ -2600,7 +2626,7 @@ tok_is_keyword(int token, union YYSTYPE *lval, * ie, unrecognized variable. */ static void -word_is_not_variable(PLword *word, int location) +word_is_not_variable(PLword *word, int location, yyscan_t yyscanner) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -2611,7 +2637,7 @@ word_is_not_variable(PLword *word, int location) /* Same, for a CWORD */ static void -cword_is_not_variable(PLcword *cword, int location) +cword_is_not_variable(PLcword *cword, int location, yyscan_t yyscanner) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -2626,42 +2652,90 @@ cword_is_not_variable(PLcword *cword, int location) * look at yylval and yylloc. */ static void -current_token_is_not_variable(int tok) +current_token_is_not_variable(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { if (tok == T_WORD) - word_is_not_variable(&(yylval.word), yylloc); + word_is_not_variable(&(yylvalp->word), *yyllocp, yyscanner); else if (tok == T_CWORD) - cword_is_not_variable(&(yylval.cword), yylloc); + cword_is_not_variable(&(yylvalp->cword), *yyllocp, yyscanner); + else + yyerror(yyllocp, NULL, yyscanner, "syntax error"); +} + +/* Convenience routine to construct a PLpgSQL_expr struct */ +static PLpgSQL_expr * +make_plpgsql_expr(const char *query, + RawParseMode parsemode) +{ + PLpgSQL_expr *expr = palloc0(sizeof(PLpgSQL_expr)); + + expr->query = pstrdup(query); + expr->parseMode = parsemode; + expr->func = plpgsql_curr_compile; + expr->ns = plpgsql_ns_top(); + /* might get changed later during parsing: */ + expr->target_param = -1; + expr->target_is_local = false; + /* other fields are left as zeroes until first execution */ + return expr; +} + +/* Mark a PLpgSQL_expr as being the source of an assignment to target */ +static void +mark_expr_as_assignment_source(PLpgSQL_expr *expr, PLpgSQL_datum *target) +{ + /* + * Mark the expression as being an assignment source, if target is a + * simple variable. We don't currently support optimized assignments to + * other DTYPEs, so no need to mark in other cases. + */ + if (target->dtype == PLPGSQL_DTYPE_VAR) + { + expr->target_param = target->dno; + + /* + * For now, assume the target is local to the nearest enclosing + * exception block. That's correct if the function contains no + * exception blocks; otherwise we'll update this later. + */ + expr->target_is_local = true; + } else - yyerror("syntax error"); + { + expr->target_param = -1; /* should be that already */ + expr->target_is_local = false; /* ditto */ + } } /* Convenience routine to read an expression with one possible terminator */ static PLpgSQL_expr * -read_sql_expression(int until, const char *expected) +read_sql_expression(int until, const char *expected, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { return read_sql_construct(until, 0, 0, expected, RAW_PARSE_PLPGSQL_EXPR, - true, true, NULL, NULL); + true, true, NULL, NULL, + yylvalp, yyllocp, yyscanner); } /* Convenience routine to read an expression with two possible terminators */ static PLpgSQL_expr * read_sql_expression2(int until, int until2, const char *expected, - int *endtoken) + int *endtoken, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { return read_sql_construct(until, until2, 0, expected, RAW_PARSE_PLPGSQL_EXPR, - true, true, NULL, endtoken); + true, true, NULL, endtoken, + yylvalp, yyllocp, yyscanner); } /* Convenience routine to read a SQL statement that must end with ';' */ static PLpgSQL_expr * -read_sql_stmt(void) +read_sql_stmt(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { return read_sql_construct(';', 0, 0, ";", RAW_PARSE_DEFAULT, - false, true, NULL, NULL); + false, true, NULL, NULL, + yylvalp, yyllocp, yyscanner); } /* @@ -2687,7 +2761,9 @@ read_sql_construct(int until, bool isexpression, bool valid_sql, int *startloc, - int *endtoken) + int *endtoken, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, + yyscan_t yyscanner) { int tok; StringInfoData ds; @@ -2705,9 +2781,9 @@ read_sql_construct(int until, for (;;) { - tok = yylex(); - if (startlocation < 0) /* remember loc of first token */ - startlocation = yylloc; + tok = yylex(yylvalp, yyllocp, yyscanner); + if (startlocation < 0) /* remember loc of first token */ + startlocation = *yyllocp; if (tok == until && parenlevel == 0) break; if (tok == until2 && parenlevel == 0) @@ -2720,32 +2796,33 @@ read_sql_construct(int until, { parenlevel--; if (parenlevel < 0) - yyerror("mismatched parentheses"); + yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses"); } + /* - * End of function definition is an error, and we don't expect to - * hit a semicolon either (unless it's the until symbol, in which - * case we should have fallen out above). + * End of function definition is an error, and we don't expect to hit + * a semicolon either (unless it's the until symbol, in which case we + * should have fallen out above). */ if (tok == 0 || tok == ';') { if (parenlevel != 0) - yyerror("mismatched parentheses"); + yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses"); if (isexpression) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("missing \"%s\" at end of SQL expression", expected), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("missing \"%s\" at end of SQL statement", expected), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); } /* Remember end+1 location of last accepted token */ - endlocation = yylloc + plpgsql_token_length(); + endlocation = *yyllocp + plpgsql_token_length(yyscanner); } plpgsql_IdentifierLookup = save_IdentifierLookup; @@ -2759,9 +2836,9 @@ read_sql_construct(int until, if (startlocation >= endlocation) { if (isexpression) - yyerror("missing expression"); + yyerror(yyllocp, NULL, yyscanner, "missing expression"); else - yyerror("missing SQL statement"); + yyerror(yyllocp, NULL, yyscanner, "missing SQL statement"); } /* @@ -2771,19 +2848,13 @@ read_sql_construct(int until, * whitespace by hand, but that causes problems if there's a "-- comment" * in front of said whitespace.) */ - plpgsql_append_source_text(&ds, startlocation, endlocation); + plpgsql_append_source_text(&ds, startlocation, endlocation, yyscanner); - expr = palloc0(sizeof(PLpgSQL_expr)); - expr->query = pstrdup(ds.data); - expr->parseMode = parsemode; - expr->plan = NULL; - expr->paramnos = NULL; - expr->target_param = -1; - expr->ns = plpgsql_ns_top(); + expr = make_plpgsql_expr(ds.data, parsemode); pfree(ds.data); if (valid_sql) - check_sql_expr(expr->query, expr->parseMode, startlocation); + check_sql_expr(expr->query, expr->parseMode, startlocation, yyscanner); return expr; } @@ -2793,7 +2864,7 @@ read_sql_construct(int until, * Returns a PLpgSQL_type struct. */ static PLpgSQL_type * -read_datatype(int tok) +read_datatype(int tok, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { StringInfoData ds; char *type_name; @@ -2806,10 +2877,10 @@ read_datatype(int tok) /* Often there will be a lookahead token, but if not, get one */ if (tok == YYEMPTY) - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); /* The current token is the start of what we'll pass to parse_datatype */ - startlocation = yylloc; + startlocation = *yyllocp; /* * If we have a simple or composite identifier, check for %TYPE and @@ -2817,48 +2888,48 @@ read_datatype(int tok) */ if (tok == T_WORD) { - char *dtname = yylval.word.ident; + char *dtname = yylvalp->word.ident; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == '%') { - tok = yylex(); - if (tok_is_keyword(tok, &yylval, + tok = yylex(yylvalp, yyllocp, yyscanner); + if (tok_is_keyword(tok, yylvalp, K_TYPE, "type")) result = plpgsql_parse_wordtype(dtname); - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_ROWTYPE, "rowtype")) result = plpgsql_parse_wordrowtype(dtname); } } else if (plpgsql_token_is_unreserved_keyword(tok)) { - char *dtname = pstrdup(yylval.keyword); + char *dtname = pstrdup(yylvalp->keyword); - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == '%') { - tok = yylex(); - if (tok_is_keyword(tok, &yylval, + tok = yylex(yylvalp, yyllocp, yyscanner); + if (tok_is_keyword(tok, yylvalp, K_TYPE, "type")) result = plpgsql_parse_wordtype(dtname); - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_ROWTYPE, "rowtype")) result = plpgsql_parse_wordrowtype(dtname); } } else if (tok == T_CWORD) { - List *dtnames = yylval.cword.idents; + List *dtnames = yylvalp->cword.idents; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == '%') { - tok = yylex(); - if (tok_is_keyword(tok, &yylval, + tok = yylex(yylvalp, yyllocp, yyscanner); + if (tok_is_keyword(tok, yylvalp, K_TYPE, "type")) result = plpgsql_parse_cwordtype(dtnames); - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_ROWTYPE, "rowtype")) result = plpgsql_parse_cwordrowtype(dtnames); } @@ -2876,24 +2947,24 @@ read_datatype(int tok) { bool is_array = false; - tok = yylex(); - if (tok_is_keyword(tok, &yylval, + tok = yylex(yylvalp, yyllocp, yyscanner); + if (tok_is_keyword(tok, yylvalp, K_ARRAY, "array")) { is_array = true; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); } while (tok == '[') { is_array = true; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == ICONST) - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok != ']') - yyerror("syntax error, expected \"]\""); - tok = yylex(); + yyerror(yyllocp, NULL, yyscanner, "syntax error, expected \"]\""); + tok = yylex(yylvalp, yyllocp, yyscanner); } - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); if (is_array) result = plpgsql_build_datatype_arrayof(result); @@ -2912,9 +2983,9 @@ read_datatype(int tok) if (tok == 0) { if (parenlevel != 0) - yyerror("mismatched parentheses"); + yyerror(yyllocp, NULL, yyscanner, "mismatched parentheses"); else - yyerror("incomplete data type declaration"); + yyerror(yyllocp, NULL, yyscanner, "incomplete data type declaration"); } /* Possible followers for datatype in a declaration */ if (tok == K_COLLATE || tok == K_NOT || @@ -2928,22 +2999,22 @@ read_datatype(int tok) else if (tok == ')') parenlevel--; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); } /* set up ds to contain complete typename text */ initStringInfo(&ds); - plpgsql_append_source_text(&ds, startlocation, yylloc); + plpgsql_append_source_text(&ds, startlocation, *yyllocp, yyscanner); type_name = ds.data; if (type_name[0] == '\0') - yyerror("missing data type declaration"); + yyerror(yyllocp, NULL, yyscanner, "missing data type declaration"); - result = parse_datatype(type_name, startlocation); + result = parse_datatype(type_name, startlocation, yyscanner); pfree(ds.data); - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); return result; } @@ -2954,7 +3025,7 @@ read_datatype(int tok) * If firsttoken == T_WORD, pass its yylval value as "word", else pass NULL. */ static PLpgSQL_stmt * -make_execsql_stmt(int firsttoken, int location, PLword *word) +make_execsql_stmt(int firsttoken, int location, PLword *word, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { StringInfoData ds; IdentifierLookup save_IdentifierLookup; @@ -2982,8 +3053,8 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR; /* - * Scan to the end of the SQL command. Identify any INTO-variables - * clause lurking within it, and parse that via read_into_target(). + * Scan to the end of the SQL command. Identify any INTO-variables clause + * lurking within it, and parse that via read_into_target(). * * The end of the statement is defined by a semicolon ... except that * semicolons within parentheses or BEGIN/END blocks don't terminate a @@ -3005,12 +3076,12 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) * but it's not very likely. * * 3. IMPORT FOREIGN SCHEMA ... INTO. This is not allowed in CREATE RULE - * or WITH, so we just check for IMPORT as the command's first token. - * (If IMPORT FOREIGN SCHEMA returned data someone might wish to capture - * with an INTO-variables clause, we'd have to work much harder here.) + * or WITH, so we just check for IMPORT as the command's first token. (If + * IMPORT FOREIGN SCHEMA returned data someone might wish to capture with + * an INTO-variables clause, we'd have to work much harder here.) * - * Fortunately, INTO is a fully reserved word in the main grammar, so - * at least we need not worry about it appearing as an identifier. + * Fortunately, INTO is a fully reserved word in the main grammar, so at + * least we need not worry about it appearing as an identifier. * * Any future additional uses of INTO in the main grammar will doubtless * break this logic again ... beware! @@ -3023,22 +3094,22 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) for (;;) { prev_tok = tok; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (have_into && into_end_loc < 0) - into_end_loc = yylloc; /* token after the INTO part */ + into_end_loc = *yyllocp; /* token after the INTO part */ /* Detect CREATE [OR REPLACE] {FUNCTION|PROCEDURE} */ if (tokens[0] == 'c' && token_count < sizeof(tokens)) { if (tok == K_OR) tokens[token_count] = 'o'; else if (tok == T_WORD && - strcmp(yylval.word.ident, "replace") == 0) + strcmp(yylvalp->word.ident, "replace") == 0) tokens[token_count] = 'r'; else if (tok == T_WORD && - strcmp(yylval.word.ident, "function") == 0) + strcmp(yylvalp->word.ident, "function") == 0) tokens[token_count] = 'f'; else if (tok == T_WORD && - strcmp(yylval.word.ident, "procedure") == 0) + strcmp(yylvalp->word.ident, "procedure") == 0) tokens[token_count] = 'f'; /* treat same as "function" */ if (tokens[1] == 'f' || (tokens[1] == 'o' && tokens[2] == 'r' && tokens[3] == 'f')) @@ -3062,7 +3133,7 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) if (tok == ';' && paren_depth == 0 && begin_depth == 0) break; if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition"); if (tok == K_INTO) { if (prev_tok == K_INSERT) @@ -3072,11 +3143,11 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) if (firsttoken == K_IMPORT) continue; /* IMPORT ... INTO is not an INTO-target */ if (have_into) - yyerror("INTO specified more than once"); + yyerror(yyllocp, NULL, yyscanner, "INTO specified more than once"); have_into = true; - into_start_loc = yylloc; + into_start_loc = *yyllocp; plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL; - read_into_target(&target, &have_strict); + read_into_target(&target, &have_strict, yylvalp, yyllocp, yyscanner); plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR; } } @@ -3086,35 +3157,29 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) if (have_into) { /* - * Insert an appropriate number of spaces corresponding to the - * INTO text, so that locations within the redacted SQL statement - * still line up with those in the original source text. + * Insert an appropriate number of spaces corresponding to the INTO + * text, so that locations within the redacted SQL statement still + * line up with those in the original source text. */ - plpgsql_append_source_text(&ds, location, into_start_loc); + plpgsql_append_source_text(&ds, location, into_start_loc, yyscanner); appendStringInfoSpaces(&ds, into_end_loc - into_start_loc); - plpgsql_append_source_text(&ds, into_end_loc, yylloc); + plpgsql_append_source_text(&ds, into_end_loc, *yyllocp, yyscanner); } else - plpgsql_append_source_text(&ds, location, yylloc); + plpgsql_append_source_text(&ds, location, *yyllocp, yyscanner); /* trim any trailing whitespace, for neatness */ while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1])) ds.data[--ds.len] = '\0'; - expr = palloc0(sizeof(PLpgSQL_expr)); - expr->query = pstrdup(ds.data); - expr->parseMode = RAW_PARSE_DEFAULT; - expr->plan = NULL; - expr->paramnos = NULL; - expr->target_param = -1; - expr->ns = plpgsql_ns_top(); + expr = make_plpgsql_expr(ds.data, RAW_PARSE_DEFAULT); pfree(ds.data); - check_sql_expr(expr->query, expr->parseMode, location); + check_sql_expr(expr->query, expr->parseMode, location, yyscanner); execsql = palloc0(sizeof(PLpgSQL_stmt_execsql)); execsql->cmd_type = PLPGSQL_STMT_EXECSQL; - execsql->lineno = plpgsql_location_to_lineno(location); + execsql->lineno = plpgsql_location_to_lineno(location, yyscanner); execsql->stmtid = ++plpgsql_curr_compile->nstatements; execsql->sqlstmt = expr; execsql->into = have_into; @@ -3129,15 +3194,15 @@ make_execsql_stmt(int firsttoken, int location, PLword *word) * Read FETCH or MOVE direction clause (everything through FROM/IN). */ static PLpgSQL_stmt_fetch * -read_fetch_direction(void) +read_fetch_direction(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { PLpgSQL_stmt_fetch *fetch; int tok; bool check_FROM = true; /* - * We create the PLpgSQL_stmt_fetch struct here, but only fill in - * the fields arising from the optional direction clause + * We create the PLpgSQL_stmt_fetch struct here, but only fill in the + * fields arising from the optional direction clause */ fetch = (PLpgSQL_stmt_fetch *) palloc0(sizeof(PLpgSQL_stmt_fetch)); fetch->cmd_type = PLPGSQL_STMT_FETCH; @@ -3148,65 +3213,65 @@ read_fetch_direction(void) fetch->expr = NULL; fetch->returns_multiple_rows = false; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition"); - if (tok_is_keyword(tok, &yylval, + if (tok_is_keyword(tok, yylvalp, K_NEXT, "next")) { /* use defaults */ } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_PRIOR, "prior")) { fetch->direction = FETCH_BACKWARD; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_FIRST, "first")) { fetch->direction = FETCH_ABSOLUTE; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_LAST, "last")) { fetch->direction = FETCH_ABSOLUTE; - fetch->how_many = -1; + fetch->how_many = -1; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_ABSOLUTE, "absolute")) { fetch->direction = FETCH_ABSOLUTE; fetch->expr = read_sql_expression2(K_FROM, K_IN, "FROM or IN", - NULL); + NULL, yylvalp, yyllocp, yyscanner); check_FROM = false; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_RELATIVE, "relative")) { fetch->direction = FETCH_RELATIVE; fetch->expr = read_sql_expression2(K_FROM, K_IN, "FROM or IN", - NULL); + NULL, yylvalp, yyllocp, yyscanner); check_FROM = false; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_ALL, "all")) { fetch->how_many = FETCH_ALL; fetch->returns_multiple_rows = true; } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_FORWARD, "forward")) { - complete_direction(fetch, &check_FROM); + complete_direction(fetch, &check_FROM, yylvalp, yyllocp, yyscanner); } - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_BACKWARD, "backward")) { fetch->direction = FETCH_BACKWARD; - complete_direction(fetch, &check_FROM); + complete_direction(fetch, &check_FROM, yylvalp, yyllocp, yyscanner); } else if (tok == K_FROM || tok == K_IN) { @@ -3216,23 +3281,23 @@ read_fetch_direction(void) else if (tok == T_DATUM) { /* Assume there's no direction clause and tok is a cursor name */ - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); check_FROM = false; } else { /* - * Assume it's a count expression with no preceding keyword. - * Note: we allow this syntax because core SQL does, but it's - * ambiguous with the case of an omitted direction clause; for - * instance, "MOVE n IN c" will fail if n is a variable, because the - * preceding else-arm will trigger. Perhaps this can be improved - * someday, but it hardly seems worth a lot of work. + * Assume it's a count expression with no preceding keyword. Note: we + * allow this syntax because core SQL does, but it's ambiguous with + * the case of an omitted direction clause; for instance, "MOVE n IN + * c" will fail if n is a variable, because the preceding else-arm + * will trigger. Perhaps this can be improved someday, but it hardly + * seems worth a lot of work. */ - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); fetch->expr = read_sql_expression2(K_FROM, K_IN, "FROM or IN", - NULL); + NULL, yylvalp, yyllocp, yyscanner); fetch->returns_multiple_rows = true; check_FROM = false; } @@ -3240,9 +3305,9 @@ read_fetch_direction(void) /* check FROM or IN keyword after direction's specification */ if (check_FROM) { - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok != K_FROM && tok != K_IN) - yyerror("expected FROM or IN"); + yyerror(yyllocp, NULL, yyscanner, "expected FROM or IN"); } return fetch; @@ -3255,13 +3320,13 @@ read_fetch_direction(void) * BACKWARD expr, BACKWARD ALL, BACKWARD */ static void -complete_direction(PLpgSQL_stmt_fetch *fetch, bool *check_FROM) +complete_direction(PLpgSQL_stmt_fetch *fetch, bool *check_FROM, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { int tok; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok == 0) - yyerror("unexpected end of function definition"); + yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition"); if (tok == K_FROM || tok == K_IN) { @@ -3277,59 +3342,59 @@ complete_direction(PLpgSQL_stmt_fetch *fetch, bool *check_FROM) return; } - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); fetch->expr = read_sql_expression2(K_FROM, K_IN, "FROM or IN", - NULL); + NULL, yylvalp, yyllocp, yyscanner); fetch->returns_multiple_rows = true; *check_FROM = false; } static PLpgSQL_stmt * -make_return_stmt(int location) +make_return_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { PLpgSQL_stmt_return *new; new = palloc0(sizeof(PLpgSQL_stmt_return)); new->cmd_type = PLPGSQL_STMT_RETURN; - new->lineno = plpgsql_location_to_lineno(location); - new->stmtid = ++plpgsql_curr_compile->nstatements; + new->lineno = plpgsql_location_to_lineno(location, yyscanner); + new->stmtid = ++plpgsql_curr_compile->nstatements; new->expr = NULL; new->retvarno = -1; if (plpgsql_curr_compile->fn_retset) { - if (yylex() != ';') + if (yylex(yylvalp, yyllocp, yyscanner) != ';') ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("RETURN cannot have a parameter in function returning set"), errhint("Use RETURN NEXT or RETURN QUERY."), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); } else if (plpgsql_curr_compile->fn_rettype == VOIDOID) { - if (yylex() != ';') + if (yylex(yylvalp, yyllocp, yyscanner) != ';') { if (plpgsql_curr_compile->fn_prokind == PROKIND_PROCEDURE) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("RETURN cannot have a parameter in a procedure"), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); else ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("RETURN cannot have a parameter in function returning void"), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); } } else if (plpgsql_curr_compile->out_param_varno >= 0) { - if (yylex() != ';') + if (yylex(yylvalp, yyllocp, yyscanner) != ';') ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("RETURN cannot have a parameter in function with OUT parameters"), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); new->retvarno = plpgsql_curr_compile->out_param_varno; } else @@ -3338,17 +3403,17 @@ make_return_stmt(int location) * We want to special-case simple variable references for efficiency. * So peek ahead to see if that's what we have. */ - int tok = yylex(); + int tok = yylex(yylvalp, yyllocp, yyscanner); - if (tok == T_DATUM && plpgsql_peek() == ';' && - (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)) + if (tok == T_DATUM && plpgsql_peek(yyscanner) == ';' && + (yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_VAR || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_REC)) { - new->retvarno = yylval.wdatum.datum->dno; + new->retvarno = yylvalp->wdatum.datum->dno; /* eat the semicolon token that we only peeked at above */ - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); Assert(tok == ';'); } else @@ -3356,11 +3421,11 @@ make_return_stmt(int location) /* * Not (just) a variable name, so treat as expression. * - * Note that a well-formed expression is _required_ here; - * anything else is a compile-time error. + * Note that a well-formed expression is _required_ here; anything + * else is a compile-time error. */ - plpgsql_push_back_token(tok); - new->expr = read_sql_expression(';', ";"); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); + new->expr = read_sql_expression(';', ";", yylvalp, yyllocp, yyscanner); } } @@ -3369,7 +3434,7 @@ make_return_stmt(int location) static PLpgSQL_stmt * -make_return_next_stmt(int location) +make_return_next_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { PLpgSQL_stmt_return_next *new; @@ -3381,18 +3446,18 @@ make_return_next_stmt(int location) new = palloc0(sizeof(PLpgSQL_stmt_return_next)); new->cmd_type = PLPGSQL_STMT_RETURN_NEXT; - new->lineno = plpgsql_location_to_lineno(location); + new->lineno = plpgsql_location_to_lineno(location, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->expr = NULL; new->retvarno = -1; if (plpgsql_curr_compile->out_param_varno >= 0) { - if (yylex() != ';') + if (yylex(yylvalp, yyllocp, yyscanner) != ';') ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("RETURN NEXT cannot have a parameter in function with OUT parameters"), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); new->retvarno = plpgsql_curr_compile->out_param_varno; } else @@ -3401,17 +3466,17 @@ make_return_next_stmt(int location) * We want to special-case simple variable references for efficiency. * So peek ahead to see if that's what we have. */ - int tok = yylex(); + int tok = yylex(yylvalp, yyllocp, yyscanner); - if (tok == T_DATUM && plpgsql_peek() == ';' && - (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)) + if (tok == T_DATUM && plpgsql_peek(yyscanner) == ';' && + (yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_VAR || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_REC)) { - new->retvarno = yylval.wdatum.datum->dno; + new->retvarno = yylvalp->wdatum.datum->dno; /* eat the semicolon token that we only peeked at above */ - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); Assert(tok == ';'); } else @@ -3419,11 +3484,11 @@ make_return_next_stmt(int location) /* * Not (just) a variable name, so treat as expression. * - * Note that a well-formed expression is _required_ here; - * anything else is a compile-time error. + * Note that a well-formed expression is _required_ here; anything + * else is a compile-time error. */ - plpgsql_push_back_token(tok); - new->expr = read_sql_expression(';', ";"); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); + new->expr = read_sql_expression(';', ";", yylvalp, yyllocp, yyscanner); } } @@ -3432,7 +3497,7 @@ make_return_next_stmt(int location) static PLpgSQL_stmt * -make_return_query_stmt(int location) +make_return_query_stmt(int location, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { PLpgSQL_stmt_return_query *new; int tok; @@ -3445,15 +3510,15 @@ make_return_query_stmt(int location) new = palloc0(sizeof(PLpgSQL_stmt_return_query)); new->cmd_type = PLPGSQL_STMT_RETURN_QUERY; - new->lineno = plpgsql_location_to_lineno(location); + new->lineno = plpgsql_location_to_lineno(location, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; /* check for RETURN QUERY EXECUTE */ - if ((tok = yylex()) != K_EXECUTE) + if ((tok = yylex(yylvalp, yyllocp, yyscanner)) != K_EXECUTE) { /* ordinary static query */ - plpgsql_push_back_token(tok); - new->query = read_sql_stmt(); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); + new->query = read_sql_stmt(yylvalp, yyllocp, yyscanner); } else { @@ -3461,14 +3526,14 @@ make_return_query_stmt(int location) int term; new->dynquery = read_sql_expression2(';', K_USING, "; or USING", - &term); + &term, yylvalp, yyllocp, yyscanner); if (term == K_USING) { do { PLpgSQL_expr *expr; - expr = read_sql_expression2(',', ';', ", or ;", &term); + expr = read_sql_expression2(',', ';', ", or ;", &term, yylvalp, yyllocp, yyscanner); new->params = lappend(new->params, expr); } while (term == ','); } @@ -3489,7 +3554,7 @@ NameOfDatum(PLwdatum *wdatum) } static void -check_assignable(PLpgSQL_datum *datum, int location) +check_assignable(PLpgSQL_datum *datum, int location, yyscan_t yyscanner) { switch (datum->dtype) { @@ -3509,7 +3574,7 @@ check_assignable(PLpgSQL_datum *datum, int location) case PLPGSQL_DTYPE_RECFIELD: /* assignable if parent record is */ check_assignable(plpgsql_Datums[((PLpgSQL_recfield *) datum)->recparentno], - location); + location, yyscanner); break; default: elog(ERROR, "unrecognized dtype: %d", datum->dtype); @@ -3522,7 +3587,7 @@ check_assignable(PLpgSQL_datum *datum, int location) * INTO keyword. */ static void -read_into_target(PLpgSQL_variable **target, bool *strict) +read_into_target(PLpgSQL_variable **target, bool *strict, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { int tok; @@ -3531,47 +3596,47 @@ read_into_target(PLpgSQL_variable **target, bool *strict) if (strict) *strict = false; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (strict && tok == K_STRICT) { *strict = true; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); } /* - * Currently, a row or record variable can be the single INTO target, - * but not a member of a multi-target list. So we throw error if there - * is a comma after it, because that probably means the user tried to - * write a multi-target list. If this ever gets generalized, we should - * probably refactor read_into_scalar_list so it handles all cases. + * Currently, a row or record variable can be the single INTO target, but + * not a member of a multi-target list. So we throw error if there is a + * comma after it, because that probably means the user tried to write a + * multi-target list. If this ever gets generalized, we should probably + * refactor read_into_scalar_list so it handles all cases. */ switch (tok) { case T_DATUM: - if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC) + if (yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_REC) { - check_assignable(yylval.wdatum.datum, yylloc); - *target = (PLpgSQL_variable *) yylval.wdatum.datum; + check_assignable(yylvalp->wdatum.datum, *yyllocp, yyscanner); + *target = (PLpgSQL_variable *) yylvalp->wdatum.datum; - if ((tok = yylex()) == ',') + if ((tok = yylex(yylvalp, yyllocp, yyscanner)) == ',') ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("record variable cannot be part of multiple-item INTO list"), - parser_errposition(yylloc))); - plpgsql_push_back_token(tok); + parser_errposition(*yyllocp))); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); } else { *target = (PLpgSQL_variable *) - read_into_scalar_list(NameOfDatum(&(yylval.wdatum)), - yylval.wdatum.datum, yylloc); + read_into_scalar_list(NameOfDatum(&(yylvalp->wdatum)), + yylvalp->wdatum.datum, *yyllocp, yylvalp, yyllocp, yyscanner); } break; default: /* just to give a better message than "syntax error" */ - current_token_is_not_variable(tok); + current_token_is_not_variable(tok, yylvalp, yyllocp, yyscanner); } } @@ -3584,60 +3649,62 @@ read_into_target(PLpgSQL_variable **target, bool *strict) static PLpgSQL_row * read_into_scalar_list(char *initial_name, PLpgSQL_datum *initial_datum, - int initial_location) + int initial_location, + YYSTYPE *yylvalp, YYLTYPE *yyllocp, + yyscan_t yyscanner) { int nfields; char *fieldnames[1024]; int varnos[1024]; - PLpgSQL_row *row; + PLpgSQL_row *row; int tok; - check_assignable(initial_datum, initial_location); + check_assignable(initial_datum, initial_location, yyscanner); fieldnames[0] = initial_name; varnos[0] = initial_datum->dno; nfields = 1; - while ((tok = yylex()) == ',') + while ((tok = yylex(yylvalp, yyllocp, yyscanner)) == ',') { /* Check for array overflow */ if (nfields >= 1024) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many INTO variables specified"), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); switch (tok) { case T_DATUM: - check_assignable(yylval.wdatum.datum, yylloc); - if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || - yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC) + check_assignable(yylvalp->wdatum.datum, *yyllocp, yyscanner); + if (yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_ROW || + yylvalp->wdatum.datum->dtype == PLPGSQL_DTYPE_REC) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("\"%s\" is not a scalar variable", - NameOfDatum(&(yylval.wdatum))), - parser_errposition(yylloc))); - fieldnames[nfields] = NameOfDatum(&(yylval.wdatum)); - varnos[nfields++] = yylval.wdatum.datum->dno; + NameOfDatum(&(yylvalp->wdatum))), + parser_errposition(*yyllocp))); + fieldnames[nfields] = NameOfDatum(&(yylvalp->wdatum)); + varnos[nfields++] = yylvalp->wdatum.datum->dno; break; default: /* just to give a better message than "syntax error" */ - current_token_is_not_variable(tok); + current_token_is_not_variable(tok, yylvalp, yyllocp, yyscanner); } } /* - * We read an extra, non-comma token from yylex(), so push it - * back onto the input stream + * We read an extra, non-comma token from yylex(), so push it back onto + * the input stream */ - plpgsql_push_back_token(tok); + plpgsql_push_back_token(tok, yylvalp, yyllocp, yyscanner); row = palloc0(sizeof(PLpgSQL_row)); row->dtype = PLPGSQL_DTYPE_ROW; row->refname = "(unnamed row)"; - row->lineno = plpgsql_location_to_lineno(initial_location); + row->lineno = plpgsql_location_to_lineno(initial_location, yyscanner); row->rowtupdesc = NULL; row->nfields = nfields; row->fieldnames = palloc(sizeof(char *) * nfields); @@ -3663,11 +3730,11 @@ read_into_scalar_list(char *initial_name, static PLpgSQL_row * make_scalar_list1(char *initial_name, PLpgSQL_datum *initial_datum, - int lineno, int location) + int lineno, int location, yyscan_t yyscanner) { PLpgSQL_row *row; - check_assignable(initial_datum, location); + check_assignable(initial_datum, location, yyscanner); row = palloc0(sizeof(PLpgSQL_row)); row->dtype = PLPGSQL_DTYPE_ROW; @@ -3708,16 +3775,17 @@ make_scalar_list1(char *initial_name, * If no error cursor is provided, we'll just point at "location". */ static void -check_sql_expr(const char *stmt, RawParseMode parseMode, int location) +check_sql_expr(const char *stmt, RawParseMode parseMode, int location, yyscan_t yyscanner) { sql_error_callback_arg cbarg; - ErrorContextCallback syntax_errcontext; + ErrorContextCallback syntax_errcontext; MemoryContext oldCxt; if (!plpgsql_check_syntax) return; cbarg.location = location; + cbarg.yyscanner = yyscanner; syntax_errcontext.callback = plpgsql_sql_error_callback; syntax_errcontext.arg = &cbarg; @@ -3736,18 +3804,19 @@ static void plpgsql_sql_error_callback(void *arg) { sql_error_callback_arg *cbarg = (sql_error_callback_arg *) arg; + yyscan_t yyscanner = cbarg->yyscanner; int errpos; /* * First, set up internalerrposition to point to the start of the - * statement text within the function text. Note this converts - * location (a byte offset) to a character number. + * statement text within the function text. Note this converts location + * (a byte offset) to a character number. */ parser_errposition(cbarg->location); /* - * If the core parser provided an error position, transpose it. - * Note we are dealing with 1-based character numbers at this point. + * If the core parser provided an error position, transpose it. Note we + * are dealing with 1-based character numbers at this point. */ errpos = geterrposition(); if (errpos > 0) @@ -3772,15 +3841,16 @@ plpgsql_sql_error_callback(void *arg) * expect that the given string is a copy from the source text. */ static PLpgSQL_type * -parse_datatype(const char *string, int location) +parse_datatype(const char *string, int location, yyscan_t yyscanner) { TypeName *typeName; Oid type_id; int32 typmod; sql_error_callback_arg cbarg; - ErrorContextCallback syntax_errcontext; + ErrorContextCallback syntax_errcontext; cbarg.location = location; + cbarg.yyscanner = yyscanner; syntax_errcontext.callback = plpgsql_sql_error_callback; syntax_errcontext.arg = &cbarg; @@ -3804,7 +3874,7 @@ parse_datatype(const char *string, int location) * Check block starting and ending labels match. */ static void -check_labels(const char *start_label, const char *end_label, int end_location) +check_labels(const char *start_label, const char *end_label, int end_location, yyscan_t yyscanner) { if (end_label) { @@ -3835,7 +3905,7 @@ check_labels(const char *start_label, const char *end_label, int end_location) * parens). */ static PLpgSQL_expr * -read_cursor_args(PLpgSQL_var *cursor, int until) +read_cursor_args(PLpgSQL_var *cursor, int until, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { PLpgSQL_expr *expr; PLpgSQL_row *row; @@ -3845,7 +3915,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until) StringInfoData ds; bool any_named = false; - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (cursor->cursor_explicit_argrow < 0) { /* No arguments expected */ @@ -3854,10 +3924,10 @@ read_cursor_args(PLpgSQL_var *cursor, int until) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cursor \"%s\" has no arguments", cursor->refname), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); if (tok != until) - yyerror("syntax error"); + yyerror(yyllocp, NULL, yyscanner, "syntax error"); return NULL; } @@ -3868,7 +3938,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cursor \"%s\" has arguments", cursor->refname), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); /* * Read the arguments, one by one. @@ -3885,18 +3955,21 @@ read_cursor_args(PLpgSQL_var *cursor, int until) tok2; int arglocation; - /* Check if it's a named parameter: "param := value" */ - plpgsql_peek2(&tok1, &tok2, &arglocation, NULL); - if (tok1 == IDENT && tok2 == COLON_EQUALS) + /* + * Check if it's a named parameter: "param := value" + * or "param => value" + */ + plpgsql_peek2(&tok1, &tok2, &arglocation, NULL, yyscanner); + if (tok1 == IDENT && (tok2 == COLON_EQUALS || tok2 == EQUALS_GREATER)) { - char *argname; + char *argname; IdentifierLookup save_IdentifierLookup; /* Read the argument name, ignoring any matching variable */ save_IdentifierLookup = plpgsql_IdentifierLookup; plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_DECLARE; - yylex(); - argname = yylval.str; + yylex(yylvalp, yyllocp, yyscanner); + argname = yylvalp->str; plpgsql_IdentifierLookup = save_IdentifierLookup; /* Match argument name to cursor arguments */ @@ -3910,15 +3983,15 @@ read_cursor_args(PLpgSQL_var *cursor, int until) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cursor \"%s\" has no argument named \"%s\"", cursor->refname, argname), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); /* - * Eat the ":=". We already peeked, so the error should never - * happen. + * Eat the ":=" or "=>". We already peeked, so the error should + * never happen. */ - tok2 = yylex(); - if (tok2 != COLON_EQUALS) - yyerror("syntax error"); + tok2 = yylex(yylvalp, yyllocp, yyscanner); + if (tok2 != COLON_EQUALS && tok2 != EQUALS_GREATER) + yyerror(yyllocp, NULL, yyscanner, "syntax error"); any_named = true; } @@ -3942,7 +4015,8 @@ read_cursor_args(PLpgSQL_var *cursor, int until) ",\" or \")", RAW_PARSE_PLPGSQL_EXPR, true, true, - NULL, &endtoken); + NULL, &endtoken, + yylvalp, yyllocp, yyscanner); argv[argpos] = item->query; @@ -3951,14 +4025,14 @@ read_cursor_args(PLpgSQL_var *cursor, int until) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("not enough arguments for cursor \"%s\"", cursor->refname), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); if (endtoken == ',' && (argc == row->nfields - 1)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("too many arguments for cursor \"%s\"", cursor->refname), - parser_errposition(yylloc))); + parser_errposition(*yyllocp))); } /* Make positional argument list */ @@ -3979,19 +4053,13 @@ read_cursor_args(PLpgSQL_var *cursor, int until) appendStringInfoString(&ds, ", "); } - expr = palloc0(sizeof(PLpgSQL_expr)); - expr->query = pstrdup(ds.data); - expr->parseMode = RAW_PARSE_PLPGSQL_EXPR; - expr->plan = NULL; - expr->paramnos = NULL; - expr->target_param = -1; - expr->ns = plpgsql_ns_top(); + expr = make_plpgsql_expr(ds.data, RAW_PARSE_PLPGSQL_EXPR); pfree(ds.data); /* Next we'd better find the until token */ - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok != until) - yyerror("syntax error"); + yyerror(yyllocp, NULL, yyscanner, "syntax error"); return expr; } @@ -4000,7 +4068,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until) * Parse RAISE ... USING options */ static List * -read_raise_options(void) +read_raise_options(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { List *result = NIL; @@ -4009,46 +4077,46 @@ read_raise_options(void) PLpgSQL_raise_option *opt; int tok; - if ((tok = yylex()) == 0) - yyerror("unexpected end of function definition"); + if ((tok = yylex(yylvalp, yyllocp, yyscanner)) == 0) + yyerror(yyllocp, NULL, yyscanner, "unexpected end of function definition"); opt = (PLpgSQL_raise_option *) palloc(sizeof(PLpgSQL_raise_option)); - if (tok_is_keyword(tok, &yylval, + if (tok_is_keyword(tok, yylvalp, K_ERRCODE, "errcode")) opt->opt_type = PLPGSQL_RAISEOPTION_ERRCODE; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_MESSAGE, "message")) opt->opt_type = PLPGSQL_RAISEOPTION_MESSAGE; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_DETAIL, "detail")) opt->opt_type = PLPGSQL_RAISEOPTION_DETAIL; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_HINT, "hint")) opt->opt_type = PLPGSQL_RAISEOPTION_HINT; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_COLUMN, "column")) opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_CONSTRAINT, "constraint")) opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_DATATYPE, "datatype")) opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_TABLE, "table")) opt->opt_type = PLPGSQL_RAISEOPTION_TABLE; - else if (tok_is_keyword(tok, &yylval, + else if (tok_is_keyword(tok, yylvalp, K_SCHEMA, "schema")) opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA; else - yyerror("unrecognized RAISE statement option"); + yyerror(yyllocp, NULL, yyscanner, "unrecognized RAISE statement option"); - tok = yylex(); + tok = yylex(yylvalp, yyllocp, yyscanner); if (tok != '=' && tok != COLON_EQUALS) - yyerror("syntax error, expected \"=\""); + yyerror(yyllocp, NULL, yyscanner, "syntax error, expected \"=\""); - opt->expr = read_sql_expression2(',', ';', ", or ;", &tok); + opt->expr = read_sql_expression2(',', ';', ", or ;", &tok, yylvalp, yyllocp, yyscanner); result = lappend(result, opt); @@ -4087,11 +4155,11 @@ check_raise_parameters(PLpgSQL_stmt_raise *stmt) if (expected_nparams < list_length(stmt->params)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("too many parameters specified for RAISE"))); + errmsg("too many parameters specified for RAISE"))); if (expected_nparams > list_length(stmt->params)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("too few parameters specified for RAISE"))); + errmsg("too few parameters specified for RAISE"))); } /* @@ -4099,13 +4167,13 @@ check_raise_parameters(PLpgSQL_stmt_raise *stmt) */ static PLpgSQL_stmt * make_case(int location, PLpgSQL_expr *t_expr, - List *case_when_list, List *else_stmts) + List *case_when_list, List *else_stmts, yyscan_t yyscanner) { PLpgSQL_stmt_case *new; new = palloc(sizeof(PLpgSQL_stmt_case)); new->cmd_type = PLPGSQL_STMT_CASE; - new->lineno = plpgsql_location_to_lineno(location); + new->lineno = plpgsql_location_to_lineno(location, yyscanner); new->stmtid = ++plpgsql_curr_compile->nstatements; new->t_expr = t_expr; new->t_varno = 0; @@ -4120,9 +4188,9 @@ make_case(int location, PLpgSQL_expr *t_expr, /* * When test expression is present, we create a var for it and then * convert all the WHEN expressions to "VAR IN (original_expression)". - * This is a bit klugy, but okay since we haven't yet done more than - * read the expressions as text. (Note that previous parsing won't - * have complained if the WHEN ... THEN expression contained multiple + * This is a bit klugy, but okay since we haven't yet done more than read + * the expressions as text. (Note that previous parsing won't have + * complained if the WHEN ... THEN expression contained multiple * comma-separated values.) */ if (t_expr) diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index 980f0961bc8ca..e9a729299470e 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -3,7 +3,7 @@ * pl_handler.c - Handler for the PL/pgSQL * procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -31,7 +31,10 @@ static bool plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSo static void plpgsql_extra_warnings_assign_hook(const char *newvalue, void *extra); static void plpgsql_extra_errors_assign_hook(const char *newvalue, void *extra); -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "plpgsql", + .version = PG_VERSION +); /* Custom GUC variable */ static const struct config_enum_entry variable_conflict_options[] = { @@ -118,7 +121,7 @@ plpgsql_extra_checks_check_hook(char **newvalue, void **extra, GucSource source) if (!myextra) return false; *myextra = extrachecks; - *extra = (void *) myextra; + *extra = myextra; return true; } @@ -199,7 +202,6 @@ _PG_init(void) MarkGUCPrefixReserved("plpgsql"); - plpgsql_HashTableInit(); RegisterXactCallback(plpgsql_xact_cb, NULL); RegisterSubXactCallback(plpgsql_subxact_cb, NULL); @@ -235,8 +237,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) /* * Connect to SPI manager */ - if ((rc = SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0)) != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc)); + SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0); /* Find or compile the function */ func = plpgsql_compile(fcinfo, false); @@ -245,7 +246,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) save_cur_estate = func->cur_estate; /* Mark the function as busy, so it can't be deleted from under us */ - func->use_count++; + func->cfunc.use_count++; /* * If we'll need a procedure-lifespan resowner to execute any CALL or DO @@ -282,7 +283,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) PG_FINALLY(); { /* Decrement use-count, restore cur_estate */ - func->use_count--; + func->cfunc.use_count--; func->cur_estate = save_cur_estate; /* Be sure to release the procedure resowner if any */ @@ -326,14 +327,13 @@ plpgsql_inline_handler(PG_FUNCTION_ARGS) /* * Connect to SPI manager */ - if ((rc = SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC)) != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc)); + SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC); /* Compile the anonymous code block */ func = plpgsql_compile_inline(codeblock->source_text); /* Mark the function as busy, just pro forma */ - func->use_count++; + func->cfunc.use_count++; /* * Set up a fake fcinfo with just enough info to satisfy @@ -397,8 +397,8 @@ plpgsql_inline_handler(PG_FUNCTION_ARGS) ResourceOwnerDelete(simple_eval_resowner); /* Function should now have no remaining use-counts ... */ - func->use_count--; - Assert(func->use_count == 0); + func->cfunc.use_count--; + Assert(func->cfunc.use_count == 0); /* ... so we can free subsidiary storage */ plpgsql_free_function_memory(func); @@ -414,8 +414,8 @@ plpgsql_inline_handler(PG_FUNCTION_ARGS) ResourceOwnerDelete(simple_eval_resowner); /* Function should now have no remaining use-counts ... */ - func->use_count--; - Assert(func->use_count == 0); + func->cfunc.use_count--; + Assert(func->cfunc.use_count == 0); /* ... so we can free subsidiary storage */ plpgsql_free_function_memory(func); @@ -510,8 +510,7 @@ plpgsql_validator(PG_FUNCTION_ARGS) /* * Connect to SPI manager (is this needed for compilation?) */ - if ((rc = SPI_connect()) != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc)); + SPI_connect(); /* * Set up a fake fcinfo with just enough info to satisfy diff --git a/src/pl/plpgsql/src/pl_reserved_kwlist.h b/src/pl/plpgsql/src/pl_reserved_kwlist.h index d338e9f637467..ce7b0c9d33121 100644 --- a/src/pl/plpgsql/src/pl_reserved_kwlist.h +++ b/src/pl/plpgsql/src/pl_reserved_kwlist.h @@ -7,7 +7,7 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/pl/plpgsql/src/pl_reserved_kwlist.h diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c index 9407da51efa6b..d08187dafcb4c 100644 --- a/src/pl/plpgsql/src/pl_scanner.c +++ b/src/pl/plpgsql/src/pl_scanner.c @@ -4,7 +4,7 @@ * lexical scanning for PL/pgSQL * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -95,42 +95,56 @@ typedef struct int leng; /* length in bytes */ } TokenAuxData; +#define MAX_PUSHBACKS 4 + /* - * Scanner working state. At some point we might wish to fold all this - * into a YY_EXTRA struct. For the moment, there is no need for plpgsql's - * lexer to be re-entrant, and the notational burden of passing a yyscanner - * pointer around is great enough to not want to do it without need. + * Scanner working state. */ +struct plpgsql_yy_extra_type +{ + /* The stuff the core lexer needs */ + core_yy_extra_type core_yy_extra; -/* The stuff the core lexer needs */ -static core_yyscan_t yyscanner = NULL; -static core_yy_extra_type core_yy; + /* The original input string */ + const char *scanorig; -/* The original input string */ -static const char *scanorig; + /* + * Current token's length (corresponds to plpgsql_yylval and + * plpgsql_yylloc) + */ + int plpgsql_yyleng; -/* Current token's length (corresponds to plpgsql_yylval and plpgsql_yylloc) */ -static int plpgsql_yyleng; + /* Current token's code (corresponds to plpgsql_yylval and plpgsql_yylloc) */ + int plpgsql_yytoken; -/* Current token's code (corresponds to plpgsql_yylval and plpgsql_yylloc) */ -static int plpgsql_yytoken; + /* Token pushback stack */ + int num_pushbacks; + int pushback_token[MAX_PUSHBACKS]; + TokenAuxData pushback_auxdata[MAX_PUSHBACKS]; -/* Token pushback stack */ -#define MAX_PUSHBACKS 4 + /* State for plpgsql_location_to_lineno() */ + const char *cur_line_start; + const char *cur_line_end; + int cur_line_num; +}; -static int num_pushbacks; -static int pushback_token[MAX_PUSHBACKS]; -static TokenAuxData pushback_auxdata[MAX_PUSHBACKS]; +/* Internal functions */ +static int internal_yylex(TokenAuxData *auxdata, yyscan_t yyscanner); +static void push_back_token(int token, TokenAuxData *auxdata, yyscan_t yyscanner); +static void location_lineno_init(yyscan_t yyscanner); -/* State for plpgsql_location_to_lineno() */ -static const char *cur_line_start; -static const char *cur_line_end; -static int cur_line_num; +/* + * This is normally provided by the generated flex code, but we don't have + * that here, so we make a minimal version ourselves. + */ +struct yyguts_t +{ + struct plpgsql_yy_extra_type *yyextra_r; +}; -/* Internal functions */ -static int internal_yylex(TokenAuxData *auxdata); -static void push_back_token(int token, TokenAuxData *auxdata); -static void location_lineno_init(void); +/* see scan.l */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) /* @@ -143,37 +157,37 @@ static void location_lineno_init(void); * matches one of those. */ int -plpgsql_yylex(void) +plpgsql_yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { int tok1; TokenAuxData aux1; int kwnum; - tok1 = internal_yylex(&aux1); + tok1 = internal_yylex(&aux1, yyscanner); if (tok1 == IDENT || tok1 == PARAM) { int tok2; TokenAuxData aux2; - tok2 = internal_yylex(&aux2); + tok2 = internal_yylex(&aux2, yyscanner); if (tok2 == '.') { int tok3; TokenAuxData aux3; - tok3 = internal_yylex(&aux3); + tok3 = internal_yylex(&aux3, yyscanner); if (tok3 == IDENT) { int tok4; TokenAuxData aux4; - tok4 = internal_yylex(&aux4); + tok4 = internal_yylex(&aux4, yyscanner); if (tok4 == '.') { int tok5; TokenAuxData aux5; - tok5 = internal_yylex(&aux5); + tok5 = internal_yylex(&aux5, yyscanner); if (tok5 == IDENT) { if (plpgsql_parse_tripword(aux1.lval.str, @@ -190,8 +204,8 @@ plpgsql_yylex(void) else { /* not A.B.C, so just process A.B */ - push_back_token(tok5, &aux5); - push_back_token(tok4, &aux4); + push_back_token(tok5, &aux5, yyscanner); + push_back_token(tok4, &aux4, yyscanner); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, @@ -206,7 +220,7 @@ plpgsql_yylex(void) else { /* not A.B.C, so just process A.B */ - push_back_token(tok4, &aux4); + push_back_token(tok4, &aux4, yyscanner); if (plpgsql_parse_dblword(aux1.lval.str, aux3.lval.str, &aux1.lval.wdatum, @@ -221,10 +235,10 @@ plpgsql_yylex(void) else { /* not A.B, so just process A */ - push_back_token(tok3, &aux3); - push_back_token(tok2, &aux2); + push_back_token(tok3, &aux3, yyscanner); + push_back_token(tok2, &aux2, yyscanner); if (plpgsql_parse_word(aux1.lval.str, - core_yy.scanbuf + aux1.lloc, + yyextra->core_yy_extra.scanbuf + aux1.lloc, true, &aux1.lval.wdatum, &aux1.lval.word)) @@ -244,7 +258,7 @@ plpgsql_yylex(void) else { /* not A.B, so just process A */ - push_back_token(tok2, &aux2); + push_back_token(tok2, &aux2, yyscanner); /* * See if it matches a variable name, except in the context where @@ -264,8 +278,8 @@ plpgsql_yylex(void) * non-variable cases. */ if (plpgsql_parse_word(aux1.lval.str, - core_yy.scanbuf + aux1.lloc, - (!AT_STMT_START(plpgsql_yytoken) || + yyextra->core_yy_extra.scanbuf + aux1.lloc, + (!AT_STMT_START(yyextra->plpgsql_yytoken) || (tok2 == '=' || tok2 == COLON_EQUALS || tok2 == '[')), &aux1.lval.wdatum, @@ -297,10 +311,10 @@ plpgsql_yylex(void) */ } - plpgsql_yylval = aux1.lval; - plpgsql_yylloc = aux1.lloc; - plpgsql_yyleng = aux1.leng; - plpgsql_yytoken = tok1; + *yylvalp = aux1.lval; + *yyllocp = aux1.lloc; + yyextra->plpgsql_yyleng = aux1.leng; + yyextra->plpgsql_yytoken = tok1; return tok1; } @@ -310,9 +324,9 @@ plpgsql_yylex(void) * In the case of compound tokens, the length includes all the parts. */ int -plpgsql_token_length(void) +plpgsql_token_length(yyscan_t yyscanner) { - return plpgsql_yyleng; + return yyextra->plpgsql_yyleng; } /* @@ -322,16 +336,16 @@ plpgsql_token_length(void) * interfacing from the core_YYSTYPE to YYSTYPE union. */ static int -internal_yylex(TokenAuxData *auxdata) +internal_yylex(TokenAuxData *auxdata, yyscan_t yyscanner) { int token; const char *yytext; - if (num_pushbacks > 0) + if (yyextra->num_pushbacks > 0) { - num_pushbacks--; - token = pushback_token[num_pushbacks]; - *auxdata = pushback_auxdata[num_pushbacks]; + yyextra->num_pushbacks--; + token = yyextra->pushback_token[yyextra->num_pushbacks]; + *auxdata = yyextra->pushback_auxdata[yyextra->num_pushbacks]; } else { @@ -340,7 +354,7 @@ internal_yylex(TokenAuxData *auxdata) yyscanner); /* remember the length of yytext before it gets changed */ - yytext = core_yy.scanbuf + auxdata->lloc; + yytext = yyextra->core_yy_extra.scanbuf + auxdata->lloc; auxdata->leng = strlen(yytext); /* Check for << >> and #, which the core considers operators */ @@ -368,13 +382,13 @@ internal_yylex(TokenAuxData *auxdata) * Push back a token to be re-read by next internal_yylex() call. */ static void -push_back_token(int token, TokenAuxData *auxdata) +push_back_token(int token, TokenAuxData *auxdata, yyscan_t yyscanner) { - if (num_pushbacks >= MAX_PUSHBACKS) + if (yyextra->num_pushbacks >= MAX_PUSHBACKS) elog(ERROR, "too many tokens pushed back"); - pushback_token[num_pushbacks] = token; - pushback_auxdata[num_pushbacks] = *auxdata; - num_pushbacks++; + yyextra->pushback_token[yyextra->num_pushbacks] = token; + yyextra->pushback_auxdata[yyextra->num_pushbacks] = *auxdata; + yyextra->num_pushbacks++; } /* @@ -384,14 +398,14 @@ push_back_token(int token, TokenAuxData *auxdata) * is not a good idea to push back a token code other than what you read. */ void -plpgsql_push_back_token(int token) +plpgsql_push_back_token(int token, YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner) { TokenAuxData auxdata; - auxdata.lval = plpgsql_yylval; - auxdata.lloc = plpgsql_yylloc; - auxdata.leng = plpgsql_yyleng; - push_back_token(token, &auxdata); + auxdata.lval = *yylvalp; + auxdata.lloc = *yyllocp; + auxdata.leng = yyextra->plpgsql_yyleng; + push_back_token(token, &auxdata, yyscanner); } /* @@ -419,10 +433,11 @@ plpgsql_token_is_unreserved_keyword(int token) */ void plpgsql_append_source_text(StringInfo buf, - int startlocation, int endlocation) + int startlocation, int endlocation, + yyscan_t yyscanner) { Assert(startlocation <= endlocation); - appendBinaryStringInfo(buf, scanorig + startlocation, + appendBinaryStringInfo(buf, yyextra->scanorig + startlocation, endlocation - startlocation); } @@ -434,13 +449,13 @@ plpgsql_append_source_text(StringInfo buf, * be returned as IDENT. Reserved keywords are resolved as usual. */ int -plpgsql_peek(void) +plpgsql_peek(yyscan_t yyscanner) { int tok1; TokenAuxData aux1; - tok1 = internal_yylex(&aux1); - push_back_token(tok1, &aux1); + tok1 = internal_yylex(&aux1, yyscanner); + push_back_token(tok1, &aux1, yyscanner); return tok1; } @@ -453,15 +468,15 @@ plpgsql_peek(void) * be returned as IDENT. Reserved keywords are resolved as usual. */ void -plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) +plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc, yyscan_t yyscanner) { int tok1, tok2; TokenAuxData aux1, aux2; - tok1 = internal_yylex(&aux1); - tok2 = internal_yylex(&aux2); + tok1 = internal_yylex(&aux1, yyscanner); + tok2 = internal_yylex(&aux2, yyscanner); *tok1_p = tok1; if (tok1_loc) @@ -470,8 +485,8 @@ plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) if (tok2_loc) *tok2_loc = aux2.lloc; - push_back_token(tok2, &aux2); - push_back_token(tok1, &aux1); + push_back_token(tok2, &aux2, yyscanner); + push_back_token(tok1, &aux1, yyscanner); } /* @@ -486,19 +501,19 @@ plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc) * to still be available. */ int -plpgsql_scanner_errposition(int location) +plpgsql_scanner_errposition(int location, yyscan_t yyscanner) { int pos; - if (location < 0 || scanorig == NULL) + if (location < 0 || yyextra->scanorig == NULL) return 0; /* no-op if location is unknown */ /* Convert byte offset to character number */ - pos = pg_mbstrlen_with_len(scanorig, location) + 1; + pos = pg_mbstrlen_with_len(yyextra->scanorig, location) + 1; /* And pass it to the ereport mechanism */ (void) internalerrposition(pos); /* Also pass the function body string */ - return internalerrquery(scanorig); + return internalerrquery(yyextra->scanorig); } /* @@ -511,11 +526,14 @@ plpgsql_scanner_errposition(int location) * parsers report error as soon as the first unparsable token is reached. * Beware of using yyerror for other purposes, as the cursor position might * be misleading! + * + * (The second argument is enforced by Bison to match the second argument of + * yyparse(), but it is not used here.) */ void -plpgsql_yyerror(const char *message) +plpgsql_yyerror(YYLTYPE *yyllocp, PLpgSQL_stmt_block **plpgsql_parse_result_p, yyscan_t yyscanner, const char *message) { - char *yytext = core_yy.scanbuf + plpgsql_yylloc; + char *yytext = yyextra->core_yy_extra.scanbuf + *yyllocp; if (*yytext == '\0') { @@ -523,7 +541,7 @@ plpgsql_yyerror(const char *message) (errcode(ERRCODE_SYNTAX_ERROR), /* translator: %s is typically the translation of "syntax error" */ errmsg("%s at end of input", _(message)), - plpgsql_scanner_errposition(plpgsql_yylloc))); + plpgsql_scanner_errposition(*yyllocp, yyscanner))); } else { @@ -533,13 +551,13 @@ plpgsql_yyerror(const char *message) * only the single token here. This modifies scanbuf but we no longer * care about that. */ - yytext[plpgsql_yyleng] = '\0'; + yytext[yyextra->plpgsql_yyleng] = '\0'; ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), /* translator: first %s is typically the translation of "syntax error" */ errmsg("%s at or near \"%s\"", _(message), yytext), - plpgsql_scanner_errposition(plpgsql_yylloc))); + plpgsql_scanner_errposition(*yyllocp, yyscanner))); } } @@ -552,43 +570,43 @@ plpgsql_yyerror(const char *message) * of the "current" line. */ int -plpgsql_location_to_lineno(int location) +plpgsql_location_to_lineno(int location, yyscan_t yyscanner) { const char *loc; - if (location < 0 || scanorig == NULL) + if (location < 0 || yyextra->scanorig == NULL) return 0; /* garbage in, garbage out */ - loc = scanorig + location; + loc = yyextra->scanorig + location; /* be correct, but not fast, if input location goes backwards */ - if (loc < cur_line_start) - location_lineno_init(); + if (loc < yyextra->cur_line_start) + location_lineno_init(yyscanner); - while (cur_line_end != NULL && loc > cur_line_end) + while (yyextra->cur_line_end != NULL && loc > yyextra->cur_line_end) { - cur_line_start = cur_line_end + 1; - cur_line_num++; - cur_line_end = strchr(cur_line_start, '\n'); + yyextra->cur_line_start = yyextra->cur_line_end + 1; + yyextra->cur_line_num++; + yyextra->cur_line_end = strchr(yyextra->cur_line_start, '\n'); } - return cur_line_num; + return yyextra->cur_line_num; } /* initialize or reset the state for plpgsql_location_to_lineno */ static void -location_lineno_init(void) +location_lineno_init(yyscan_t yyscanner) { - cur_line_start = scanorig; - cur_line_num = 1; + yyextra->cur_line_start = yyextra->scanorig; + yyextra->cur_line_num = 1; - cur_line_end = strchr(cur_line_start, '\n'); + yyextra->cur_line_end = strchr(yyextra->cur_line_start, '\n'); } /* return the most recently computed lineno */ int -plpgsql_latest_lineno(void) +plpgsql_latest_lineno(yyscan_t yyscanner) { - return cur_line_num; + return yyextra->cur_line_num; } @@ -599,11 +617,14 @@ plpgsql_latest_lineno(void) * Although it is not fed directly to flex, we need the original string * to cite in error messages. */ -void +yyscan_t plpgsql_scanner_init(const char *str) { + yyscan_t yyscanner; + struct plpgsql_yy_extra_type *yyext = palloc0_object(struct plpgsql_yy_extra_type); + /* Start up the core scanner */ - yyscanner = scanner_init(str, &core_yy, + yyscanner = scanner_init(str, (core_yy_extra_type *) yyext, &ReservedPLKeywords, ReservedPLKeywordTokens); /* @@ -612,26 +633,25 @@ plpgsql_scanner_init(const char *str) * yytext points into scanbuf, we rely on being able to apply locations * (offsets from string start) to scanorig as well. */ - scanorig = str; + yyext->scanorig = str; /* Other setup */ plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL; - plpgsql_yytoken = 0; + yyext->plpgsql_yytoken = 0; + + yyext->num_pushbacks = 0; - num_pushbacks = 0; + location_lineno_init(yyscanner); - location_lineno_init(); + return yyscanner; } /* * Called after parsing is done to clean up after plpgsql_scanner_init() */ void -plpgsql_scanner_finish(void) +plpgsql_scanner_finish(yyscan_t yyscanner) { /* release storage */ scanner_finish(yyscanner); - /* avoid leaving any dangling pointers */ - yyscanner = NULL; - scanorig = NULL; } diff --git a/src/pl/plpgsql/src/pl_unreserved_kwlist.h b/src/pl/plpgsql/src/pl_unreserved_kwlist.h index 670b4cf0c1e0d..98f99ec470cf4 100644 --- a/src/pl/plpgsql/src/pl_unreserved_kwlist.h +++ b/src/pl/plpgsql/src/pl_unreserved_kwlist.h @@ -7,7 +7,7 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/pl/plpgsql/src/pl_unreserved_kwlist.h diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 50c3b28472b54..41e52b8ce7183 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -3,7 +3,7 @@ * plpgsql.h - Definitions for the PL/pgSQL * procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -21,6 +21,7 @@ #include "commands/trigger.h" #include "executor/spi.h" #include "utils/expandedrecord.h" +#include "utils/funccache.h" #include "utils/typcache.h" @@ -187,6 +188,17 @@ typedef enum PLpgSQL_resolve_option PLPGSQL_RESOLVE_COLUMN, /* prefer table column to plpgsql var */ } PLpgSQL_resolve_option; +/* + * Status of optimization of assignment to a read/write expanded object + */ +typedef enum PLpgSQL_rwopt +{ + PLPGSQL_RWOPT_UNKNOWN = 0, /* applicability not determined yet */ + PLPGSQL_RWOPT_NOPE, /* cannot do any optimization */ + PLPGSQL_RWOPT_TRANSFER, /* transfer the old value into expr state */ + PLPGSQL_RWOPT_INPLACE, /* pass value as R/W to top-level function */ +} PLpgSQL_rwopt; + /********************************************************************** * Node and structure definitions @@ -219,14 +231,25 @@ typedef struct PLpgSQL_expr { char *query; /* query string, verbatim from function body */ RawParseMode parseMode; /* raw_parser() mode to use */ - SPIPlanPtr plan; /* plan, or NULL if not made yet */ - Bitmapset *paramnos; /* all dnos referenced by this query */ + struct PLpgSQL_function *func; /* function containing this expr */ + struct PLpgSQL_nsitem *ns; /* namespace chain visible to this expr */ - /* function containing this expr (not set until we first parse query) */ - struct PLpgSQL_function *func; + /* + * These fields are used to help optimize assignments to expanded-datum + * variables. If this expression is the source of an assignment to a + * simple variable, target_param holds that variable's dno (else it's -1), + * and target_is_local indicates whether the target is declared inside the + * closest exception block containing the assignment. + */ + int target_param; /* dno of assign target, or -1 if none */ + bool target_is_local; /* is it within nearest exception block? */ - /* namespace chain visible to this expr */ - struct PLpgSQL_nsitem *ns; + /* + * Fields above are set during plpgsql parsing. Remaining fields are left + * as zeroes/NULLs until we first parse/plan the query. + */ + SPIPlanPtr plan; /* plan, or NULL if not made yet */ + Bitmapset *paramnos; /* all dnos referenced by this query */ /* fields for "simple expression" fast-path execution: */ Expr *expr_simple_expr; /* NULL means not a simple expr */ @@ -235,14 +258,14 @@ typedef struct PLpgSQL_expr bool expr_simple_mutable; /* true if simple expr is mutable */ /* - * These fields are used to optimize assignments to expanded-datum - * variables. If this expression is the source of an assignment to a - * simple variable, target_param holds that variable's dno; else it's -1. - * If we match a Param within expr_simple_expr to such a variable, that - * Param's address is stored in expr_rw_param; then expression code - * generation will allow the value for that Param to be passed read/write. + * expr_rwopt tracks whether we have determined that assignment to a + * read/write expanded object (stored in the target_param datum) can be + * optimized by passing it to the expr as a read/write expanded-object + * pointer. If so, expr_rw_param identifies the specific Param that + * should emit a read/write pointer; any others will emit read-only + * pointers. */ - int target_param; /* dno of assign target, or -1 if none */ + PLpgSQL_rwopt expr_rwopt; /* can we apply R/W optimization? */ Param *expr_rw_param; /* read/write Param within expr, if any */ /* @@ -468,11 +491,14 @@ typedef struct PLpgSQL_stmt */ typedef struct PLpgSQL_condition { - int sqlerrstate; /* SQLSTATE code */ + int sqlerrstate; /* SQLSTATE code, or PLPGSQL_OTHERS */ char *condname; /* condition name (for debugging) */ struct PLpgSQL_condition *next; } PLpgSQL_condition; +/* This value mustn't match any possible output of MAKE_SQLSTATE() */ +#define PLPGSQL_OTHERS (-1) + /* * EXCEPTION block */ @@ -916,40 +942,6 @@ typedef struct PLpgSQL_stmt_dynexecute List *params; /* USING expressions */ } PLpgSQL_stmt_dynexecute; -/* - * Hash lookup key for functions - */ -typedef struct PLpgSQL_func_hashkey -{ - Oid funcOid; - - bool isTrigger; /* true if called as a DML trigger */ - bool isEventTrigger; /* true if called as an event trigger */ - - /* be careful that pad bytes in this struct get zeroed! */ - - /* - * For a trigger function, the OID of the trigger is part of the hash key - * --- we want to compile the trigger function separately for each trigger - * it is used with, in case the rowtype or transition table names are - * different. Zero if not called as a DML trigger. - */ - Oid trigOid; - - /* - * We must include the input collation as part of the hash key too, - * because we have to generate different plans (with different Param - * collations) for different collation settings. - */ - Oid inputCollation; - - /* - * We include actual argument types in the hash key to support polymorphic - * PLpgSQL functions. Be careful that extra positions are zeroed! - */ - Oid argtypes[FUNC_MAX_ARGS]; -} PLpgSQL_func_hashkey; - /* * Trigger type */ @@ -965,13 +957,12 @@ typedef enum PLpgSQL_trigtype */ typedef struct PLpgSQL_function { + CachedFunction cfunc; /* fields managed by funccache.c */ + char *fn_signature; Oid fn_oid; - TransactionId fn_xmin; - ItemPointerData fn_tid; PLpgSQL_trigtype fn_is_trigger; Oid fn_input_collation; - PLpgSQL_func_hashkey *fn_hashkey; /* back-link to hashtable key */ MemoryContext fn_cxt; Oid fn_rettype; @@ -1009,10 +1000,10 @@ typedef struct PLpgSQL_function /* data derived while parsing body */ unsigned int nstatements; /* counter for assigning stmtids */ bool requires_procedure_resowner; /* contains CALL or DO? */ + bool has_exception_block; /* contains BEGIN...EXCEPTION? */ - /* these fields change when the function is used */ + /* this field changes when the function is used */ struct PLpgSQL_execstate *cur_estate; - unsigned long use_count; } PLpgSQL_function; /* @@ -1212,8 +1203,6 @@ extern int plpgsql_extra_errors; extern bool plpgsql_check_syntax; extern bool plpgsql_DumpExecTree; -extern PLpgSQL_stmt_block *plpgsql_parse_result; - extern int plpgsql_nDatums; extern PLpgSQL_datum **plpgsql_Datums; @@ -1263,7 +1252,6 @@ extern PGDLLEXPORT int plpgsql_recognize_err_condition(const char *condname, extern PLpgSQL_condition *plpgsql_parse_err_condition(char *condname); extern void plpgsql_adddatum(PLpgSQL_datum *newdatum); extern int plpgsql_add_initdatums(int **varnos); -extern void plpgsql_HashTableInit(void); /* * Functions in pl_exec.c @@ -1309,32 +1297,40 @@ extern PLpgSQL_nsitem *plpgsql_ns_find_nearest_loop(PLpgSQL_nsitem *ns_cur); */ extern PGDLLEXPORT const char *plpgsql_stmt_typename(PLpgSQL_stmt *stmt); extern const char *plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind); +extern void plpgsql_mark_local_assignment_targets(PLpgSQL_function *func); extern void plpgsql_free_function_memory(PLpgSQL_function *func); +extern void plpgsql_delete_callback(CachedFunction *cfunc); extern void plpgsql_dumptree(PLpgSQL_function *func); /* * Scanner functions in pl_scanner.c */ -extern int plpgsql_base_yylex(void); -extern int plpgsql_yylex(void); -extern int plpgsql_token_length(void); -extern void plpgsql_push_back_token(int token); +union YYSTYPE; +#define YYLTYPE int +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void *yyscan_t; +#endif +extern int plpgsql_yylex(union YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); +extern int plpgsql_token_length(yyscan_t yyscanner); +extern void plpgsql_push_back_token(int token, union YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t yyscanner); extern bool plpgsql_token_is_unreserved_keyword(int token); extern void plpgsql_append_source_text(StringInfo buf, - int startlocation, int endlocation); -extern int plpgsql_peek(void); + int startlocation, int endlocation, + yyscan_t yyscanner); +extern int plpgsql_peek(yyscan_t yyscanner); extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, - int *tok2_loc); -extern int plpgsql_scanner_errposition(int location); -extern void plpgsql_yyerror(const char *message) pg_attribute_noreturn(); -extern int plpgsql_location_to_lineno(int location); -extern int plpgsql_latest_lineno(void); -extern void plpgsql_scanner_init(const char *str); -extern void plpgsql_scanner_finish(void); + int *tok2_loc, yyscan_t yyscanner); +extern int plpgsql_scanner_errposition(int location, yyscan_t yyscanner); +pg_noreturn extern void plpgsql_yyerror(YYLTYPE *yyllocp, PLpgSQL_stmt_block **plpgsql_parse_result_p, yyscan_t yyscanner, const char *message); +extern int plpgsql_location_to_lineno(int location, yyscan_t yyscanner); +extern int plpgsql_latest_lineno(yyscan_t yyscanner); +extern yyscan_t plpgsql_scanner_init(const char *str); +extern void plpgsql_scanner_finish(yyscan_t yyscanner); /* - * Externs in gram.y + * Externs in pl_gram.y */ -extern int plpgsql_yyparse(void); +extern int plpgsql_yyparse(PLpgSQL_stmt_block **plpgsql_parse_result_p, yyscan_t yyscanner); #endif /* PLPGSQL_H */ diff --git a/src/pl/plpgsql/src/po/es.po b/src/pl/plpgsql/src/po/es.po index 1c12451409bfd..c045415aa326c 100644 --- a/src/pl/plpgsql/src/po/es.po +++ b/src/pl/plpgsql/src/po/es.po @@ -10,10 +10,10 @@ # msgid "" msgstr "" -"Project-Id-Version: plpgsql (PostgreSQL) 16\n" +"Project-Id-Version: plpgsql (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:09+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:39+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -78,104 +78,119 @@ msgstr "la referencia a la columna «%s» es ambigua" msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "Podría referirse tanto a una variable PL/pgSQL como a una columna de una tabla." -#: pl_comp.c:1314 pl_exec.c:5255 pl_exec.c:5428 pl_exec.c:5515 pl_exec.c:5606 -#: pl_exec.c:6624 +#: pl_comp.c:1314 pl_exec.c:5260 pl_exec.c:5433 pl_exec.c:5520 pl_exec.c:5611 +#: pl_exec.c:6636 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "el registro «%s» no tiene un campo «%s»" -#: pl_comp.c:1808 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "no existe la variable «%s»" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "no existe la columna «%s» en la relación «%s»" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "no existe la relación «%s»" -#: pl_comp.c:1815 pl_comp.c:1857 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "la relación «%s» no contiene un tipo compuesto" -#: pl_comp.c:1923 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "la variable «%s» tiene pseudotipo %s" -#: pl_comp.c:2112 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "el tipo «%s» está inconcluso" -#: pl_comp.c:2194 pl_exec.c:6925 +#: pl_comp.c:2157 pl_exec.c:6937 #, c-format msgid "type %s is not composite" msgstr "el tipo %s no es compuesto" -#: pl_comp.c:2242 pl_comp.c:2295 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "no se pudo encontrar un tipo de array para el tipo de dato %s" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "no se reconoce la condición de excepción «%s»" -#: pl_comp.c:2524 +#: pl_comp.c:2514 #, c-format msgid "could not determine actual argument type for polymorphic function \"%s\"" msgstr "no se pudo determinar el verdadero tipo de argumento para la función polimórfica «%s»" -#: pl_exec.c:511 pl_exec.c:950 pl_exec.c:1185 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "durante la inicialización del estado de ejecución" -#: pl_exec.c:517 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "mientras se almacenaban los argumentos de invocación en variables locales" -#: pl_exec.c:605 pl_exec.c:1023 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "durante el ingreso a la función" -#: pl_exec.c:628 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "la ejecución alcanzó el fin de la función sin encontrar RETURN" -#: pl_exec.c:634 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "mientras se hacía la conversión del valor de retorno al tipo de retorno de la función" -#: pl_exec.c:646 pl_exec.c:3681 +#: pl_exec.c:647 pl_exec.c:3683 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "se llamó una función que retorna un conjunto en un contexto que no puede aceptarlo" -#: pl_exec.c:651 pl_exec.c:3687 +#: pl_exec.c:652 pl_exec.c:3689 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "se requiere un nodo «materialize», pero no está permitido en este contexto" -#: pl_exec.c:778 pl_exec.c:1049 pl_exec.c:1207 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "durante la salida de la función" -#: pl_exec.c:833 pl_exec.c:897 pl_exec.c:3480 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3482 msgid "returned record type does not match expected record type" msgstr "el tipo de registro retornado no coincide con el tipo de registro esperado" -#: pl_exec.c:1046 pl_exec.c:1204 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "la ejecución alcanzó el fin del procedimiento disparador sin encontrar RETURN" -#: pl_exec.c:1054 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "los procedimientos disparadores no pueden retornar conjuntos" -#: pl_exec.c:1093 pl_exec.c:1121 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "returned row structure does not match the structure of the triggering table" msgstr "la estructura de fila retornada no coincide con la estructura de la tabla que generó el evento de disparador" #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1262 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "función PL/pgSQL %s en la línea %d %s" @@ -183,35 +198,35 @@ msgstr "función PL/pgSQL %s en la línea %d %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1273 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "función PL/pgSQL %s %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1281 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "función PL/pgSQL %s en la línea %d en %s" -#: pl_exec.c:1287 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "función PL/pgSQL %s" -#: pl_exec.c:1658 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "durante inicialización de variables locales en el bloque de sentencias" -#: pl_exec.c:1763 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "durante la entrada al bloque de sentencias" -#: pl_exec.c:1795 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "durante la salida del bloque de sentencias" -#: pl_exec.c:1833 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "durante la finalización por excepción" @@ -225,294 +240,294 @@ msgstr "el parámetro de procedimiento «%s» es un parámetro de salida pero el msgid "procedure parameter %d is an output parameter but corresponding argument is not writable" msgstr "el parámetro de procedimiento %d es un parámetro de salida pero el argumento correspondiente no es escribible" -#: pl_exec.c:2409 +#: pl_exec.c:2411 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "GET STACKED DIAGNOSTICS no puede ser usado fuera de un manejador de excepción" -#: pl_exec.c:2615 +#: pl_exec.c:2617 #, c-format msgid "case not found" msgstr "caso no encontrado" -#: pl_exec.c:2616 +#: pl_exec.c:2618 #, c-format msgid "CASE statement is missing ELSE part." msgstr "A la sentencia CASE le falta la parte ELSE." -#: pl_exec.c:2709 +#: pl_exec.c:2711 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "el límite inferior de un ciclo FOR no puede ser null" -#: pl_exec.c:2725 +#: pl_exec.c:2727 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "el límite superior de un ciclo FOR no puede ser null" -#: pl_exec.c:2743 +#: pl_exec.c:2745 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "el valor BY de un ciclo FOR no puede ser null" -#: pl_exec.c:2749 +#: pl_exec.c:2751 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "el valor BY de un ciclo FOR debe ser mayor que cero" -#: pl_exec.c:2883 pl_exec.c:4688 +#: pl_exec.c:2885 pl_exec.c:4693 #, c-format msgid "cursor \"%s\" already in use" msgstr "el cursor «%s» ya está en uso" -#: pl_exec.c:2906 pl_exec.c:4758 +#: pl_exec.c:2908 pl_exec.c:4763 #, c-format msgid "arguments given for cursor without arguments" msgstr "se dieron argumentos a un cursor sin argumentos" -#: pl_exec.c:2925 pl_exec.c:4777 +#: pl_exec.c:2927 pl_exec.c:4782 #, c-format msgid "arguments required for cursor" msgstr "se requieren argumentos para el cursor" -#: pl_exec.c:3016 +#: pl_exec.c:3018 #, c-format msgid "FOREACH expression must not be null" msgstr "la expresión FOREACH no debe ser nula" -#: pl_exec.c:3031 +#: pl_exec.c:3033 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "una expresión FOREACH debe retornar un array, no tipo %s" -#: pl_exec.c:3048 +#: pl_exec.c:3050 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "la dimensión del slice (%d) está fuera de rango 0..%d" -#: pl_exec.c:3075 +#: pl_exec.c:3077 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "las variables de bucles FOREACH ... SLICE deben ser de un tipo array" -#: pl_exec.c:3079 +#: pl_exec.c:3081 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "la variable de bucle FOREACH no debe ser de tipo array" -#: pl_exec.c:3241 pl_exec.c:3298 pl_exec.c:3473 +#: pl_exec.c:3243 pl_exec.c:3300 pl_exec.c:3475 #, c-format msgid "cannot return non-composite value from function returning composite type" msgstr "no se puede retornar un valor no-compuesto desde una función que retorne tipos compuestos" -#: pl_exec.c:3337 pl_gram.y:3295 +#: pl_exec.c:3339 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "no se puede usar RETURN NEXT en una función que no es SETOF" -#: pl_exec.c:3378 pl_exec.c:3510 +#: pl_exec.c:3380 pl_exec.c:3512 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "se pasó un tipo incorrecto de resultado a RETURN NEXT" -#: pl_exec.c:3416 pl_exec.c:3437 +#: pl_exec.c:3418 pl_exec.c:3439 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "se pasó un tipo de registro incorrecto a RETURN NEXT" -#: pl_exec.c:3529 +#: pl_exec.c:3531 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "RETURN NEXT debe tener un parámetro" -#: pl_exec.c:3557 pl_gram.y:3359 +#: pl_exec.c:3559 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "no se puede usar RETURN QUERY en una función que no ha sido declarada SETOF" -#: pl_exec.c:3575 +#: pl_exec.c:3577 msgid "structure of query does not match function result type" msgstr "la estructura de la consulta no coincide con el tipo del resultado de la función" -#: pl_exec.c:3630 pl_exec.c:4465 pl_exec.c:8724 +#: pl_exec.c:3632 pl_exec.c:4469 pl_exec.c:8759 #, c-format msgid "query string argument of EXECUTE is null" msgstr "el argumento de consulta a ejecutar en EXECUTE es null" -#: pl_exec.c:3715 pl_exec.c:3853 +#: pl_exec.c:3717 pl_exec.c:3855 #, c-format msgid "RAISE option already specified: %s" msgstr "la opción de RAISE ya se especificó: %s" -#: pl_exec.c:3749 +#: pl_exec.c:3751 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "RAISE sin parámetros no puede ser usado fuera de un manejador de excepción" -#: pl_exec.c:3843 +#: pl_exec.c:3845 #, c-format msgid "RAISE statement option cannot be null" msgstr "la opción de sentencia en RAISE no puede ser null" -#: pl_exec.c:3913 +#: pl_exec.c:3915 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3968 +#: pl_exec.c:3970 #, c-format msgid "assertion failed" msgstr "aseveración falló" -#: pl_exec.c:4338 pl_exec.c:4527 +#: pl_exec.c:4342 pl_exec.c:4532 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "no se puede ejecutar COPY desde/a un cliente en PL/pgSQL" -#: pl_exec.c:4344 +#: pl_exec.c:4348 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "orden de transacción no soportada en PL/pgSQL" -#: pl_exec.c:4367 pl_exec.c:4556 +#: pl_exec.c:4371 pl_exec.c:4561 #, c-format msgid "INTO used with a command that cannot return data" msgstr "INTO es utilizado con una orden que no puede retornar datos" -#: pl_exec.c:4390 pl_exec.c:4579 +#: pl_exec.c:4394 pl_exec.c:4584 #, c-format msgid "query returned no rows" msgstr "la consulta no regresó filas" -#: pl_exec.c:4412 pl_exec.c:4598 pl_exec.c:5750 +#: pl_exec.c:4416 pl_exec.c:4603 pl_exec.c:5755 #, c-format msgid "query returned more than one row" msgstr "la consulta regresó más de una fila" -#: pl_exec.c:4414 +#: pl_exec.c:4418 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "Asegúrese que la consulta retorne una única fila, o use LIMIT 1." -#: pl_exec.c:4430 +#: pl_exec.c:4434 #, c-format msgid "query has no destination for result data" msgstr "la consulta no tiene un destino para los datos de resultado" -#: pl_exec.c:4431 +#: pl_exec.c:4435 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "Si quiere descartar los resultados de un SELECT, utilice PERFORM." -#: pl_exec.c:4519 +#: pl_exec.c:4524 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" msgstr "no está implementado EXECUTE de un SELECT ... INTO" -#: pl_exec.c:4520 +#: pl_exec.c:4525 #, c-format msgid "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead." msgstr "Puede desear usar EXECUTE ... INTO o EXECUTE CREATE TABLE ... AS en su lugar." -#: pl_exec.c:4533 +#: pl_exec.c:4538 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "no está implementado EXECUTE de órdenes de transacción" -#: pl_exec.c:4843 pl_exec.c:4931 +#: pl_exec.c:4848 pl_exec.c:4936 #, c-format msgid "cursor variable \"%s\" is null" msgstr "variable cursor «%s» es null" -#: pl_exec.c:4854 pl_exec.c:4942 +#: pl_exec.c:4859 pl_exec.c:4947 #, c-format msgid "cursor \"%s\" does not exist" msgstr "no existe el cursor «%s»" -#: pl_exec.c:4867 +#: pl_exec.c:4872 #, c-format msgid "relative or absolute cursor position is null" msgstr "la posición relativa o absoluta del cursor es null" -#: pl_exec.c:5105 pl_exec.c:5200 +#: pl_exec.c:5110 pl_exec.c:5205 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "no puede asignarse un valor null a la variable «%s» que fue declarada NOT NULL" -#: pl_exec.c:5181 +#: pl_exec.c:5186 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "no se puede asignar un valor no compuesto a una variable de tipo row" -#: pl_exec.c:5213 +#: pl_exec.c:5218 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "no se puede asignar un valor no compuesto a una variable de tipo record" -#: pl_exec.c:5264 +#: pl_exec.c:5269 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "no se puede asignar a la columna de sistema «%s»" -#: pl_exec.c:5713 +#: pl_exec.c:5718 #, c-format msgid "query did not return data" msgstr "la consulta no retornó datos" -#: pl_exec.c:5714 pl_exec.c:5726 pl_exec.c:5751 pl_exec.c:5827 pl_exec.c:5832 +#: pl_exec.c:5719 pl_exec.c:5731 pl_exec.c:5756 pl_exec.c:5832 pl_exec.c:5837 #, c-format msgid "query: %s" msgstr "consulta: %s" -#: pl_exec.c:5722 +#: pl_exec.c:5727 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" msgstr[0] "la consulta retornó %d columna" msgstr[1] "la consulta retornó %d columnas" -#: pl_exec.c:5826 +#: pl_exec.c:5831 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "la consulta es SELECT INTO, pero debería ser un SELECT simple" -#: pl_exec.c:5831 +#: pl_exec.c:5836 #, c-format msgid "query is not a SELECT" msgstr "la consulta no es un SELECT" -#: pl_exec.c:6638 pl_exec.c:6678 pl_exec.c:6718 +#: pl_exec.c:6650 pl_exec.c:6690 pl_exec.c:6730 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "el tipo del parámetro %d (%s) no coincide aquel con que fue preparado el plan (%s)" -#: pl_exec.c:7129 pl_exec.c:7163 pl_exec.c:7237 pl_exec.c:7263 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "no coincide el número de campos de origen y destino en la asignación" #. translator: %s represents a name of an extra check -#: pl_exec.c:7131 pl_exec.c:7165 pl_exec.c:7239 pl_exec.c:7265 +#: pl_exec.c:7143 pl_exec.c:7177 pl_exec.c:7251 pl_exec.c:7277 #, c-format msgid "%s check of %s is active." msgstr "El chequeo %s de %s está activo." -#: pl_exec.c:7135 pl_exec.c:7169 pl_exec.c:7243 pl_exec.c:7269 +#: pl_exec.c:7147 pl_exec.c:7181 pl_exec.c:7255 pl_exec.c:7281 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "Asegúrese que la consulta retorna la lista exacta de columnas." -#: pl_exec.c:7656 +#: pl_exec.c:7668 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "el registro «%s» no ha sido asignado aún" -#: pl_exec.c:7657 +#: pl_exec.c:7669 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "La estructura de fila de un registro aún no asignado no está determinado." -#: pl_exec.c:8322 pl_gram.y:3418 +#: pl_exec.c:8357 pl_gram.y:3498 #, c-format msgid "variable \"%s\" is declared CONSTANT" msgstr "la variable «%s» esta declarada como CONSTANT" @@ -564,11 +579,6 @@ msgstr "los ordenamientos (collation) no están soportados por el tipo %s" msgid "variable \"%s\" must have a default value, since it's declared NOT NULL" msgstr "la variable «%s» debe tener valor por omisión, puesto que está declarado NOT NULL" -#: pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "no existe la variable «%s»" - #: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "declaración duplicada" @@ -578,36 +588,36 @@ msgstr "declaración duplicada" msgid "variable \"%s\" shadows a previously defined variable" msgstr "la variable «%s» oculta una variable definida anteriormente" -#: pl_gram.y:1016 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "elemento de diagnóstico %s no se permite en GET STACKED DIAGNOSTICS" -#: pl_gram.y:1034 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "elemento de diagnóstico %s no se permite en GET STACKED DIAGNOSTICS" -#: pl_gram.y:1132 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "elemento de GET DIAGNOSTICS no reconocido" -#: pl_gram.y:1148 pl_gram.y:3534 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "«%s» no es una variable escalar" -#: pl_gram.y:1378 pl_gram.y:1572 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "loop variable of loop over rows must be a record variable or list of scalar variables" msgstr "la variable de bucle de un bucle sobre filas debe ser una variable de tipo record o una lista de variables escalares" -#: pl_gram.y:1413 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "un bucle FOR de un cursor debe tener sólo una variable de destino" -#: pl_gram.y:1420 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "un bucle FOR en torno a un cursor debe usar un cursor enlazado (bound)" @@ -647,14 +657,14 @@ msgstr "EXIT no puede usarse fuera de un bucle, a menos que tenga una etiqueta" msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE no puede usarse fuera de un bucle" -#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:2981 pl_gram.y:3069 -#: pl_gram.y:3180 pl_gram.y:3933 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "fin inesperado de la definición de la función" #: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 #: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 -#: pl_gram.y:2632 pl_gram.y:3776 pl_gram.y:3837 pl_gram.y:3914 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "error de sintaxis" @@ -686,138 +696,142 @@ msgstr "la variable «%s» debe ser de tipo cursor o refcursor" msgid "\"%s\" is not a known variable" msgstr "«%s» no es una variable conocida" -#: pl_gram.y:2720 pl_gram.y:2730 pl_gram.y:2886 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "no coinciden los paréntesis" -#: pl_gram.y:2734 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "falta «%s» al final de la expresión SQL" -#: pl_gram.y:2740 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "falta «%s» al final de la sentencia SQL" -#: pl_gram.y:2757 +#: pl_gram.y:2758 msgid "missing expression" msgstr "expresión faltante" -#: pl_gram.y:2759 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "sentencia SQL faltante" -#: pl_gram.y:2888 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "error de sintaxis, se esperaba «]»" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "declaración de tipo de dato incompleta" -#: pl_gram.y:2911 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "declaración de tipo de dato faltante" -#: pl_gram.y:2991 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO fue especificado más de una vez" -#: pl_gram.y:3161 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "se espera FROM o IN" -#: pl_gram.y:3222 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "RETURN no puede tener un parámetro en una función que retorna un conjunto" -#: pl_gram.y:3223 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "Use RETURN NEXT o RETURN QUERY." -#: pl_gram.y:3233 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "RETURN no puede tener un parámetro un procedimiento" -#: pl_gram.y:3238 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "RETURN no puede tener parámetro en una función que retorna void" -#: pl_gram.y:3247 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "RETURN no puede tener parámetros en una función con parámetros OUT" -#: pl_gram.y:3310 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "RETURN NEXT no puede tener parámetros en una función con parámetros OUT" -#: pl_gram.y:3476 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "una variable de tipo record no puede ser parte de una lista INTO de múltiples elementos" -#: pl_gram.y:3522 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "se especificaron demasiadas variables INTO" -#: pl_gram.y:3730 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "etiqueta de término «%s» especificada para un bloque sin etiqueta" -#: pl_gram.y:3737 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "etiqueta de término «%s» difiere de la etiqueta de bloque «%s»" -#: pl_gram.y:3771 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "el cursor «%s» no tiene argumentos" -#: pl_gram.y:3785 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "el cursor «%s» tiene argumentos" -#: pl_gram.y:3827 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "el cursor «%s» no tiene un argumento llamado «%s»" -#: pl_gram.y:3847 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "el valor para el parámetro «%s» del cursor «%s» fue especificado más de una vez" -#: pl_gram.y:3872 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "no hay suficientes argumentos para el cursor «%s»" -#: pl_gram.y:3879 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "demasiados argumentos para el cursor «%s»" -#: pl_gram.y:3965 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "no se reconoce la opción de sentencia RAISE" -#: pl_gram.y:3969 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "error de sintaxis, se esperaba «=»" -#: pl_gram.y:4010 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "se especificaron demasiados parámetros a RAISE" -#: pl_gram.y:4014 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "se especificaron muy pocos parámetros a RAISE" @@ -843,13 +857,13 @@ msgid "List of programming constructs that should produce an error." msgstr "Listado de estructuras de programación que deben dar un error." #. translator: %s is typically the translation of "syntax error" -#: pl_scanner.c:508 +#: pl_scanner.c:525 #, c-format msgid "%s at end of input" msgstr "%s al final de la entrada" #. translator: first %s is typically the translation of "syntax error" -#: pl_scanner.c:524 +#: pl_scanner.c:541 #, c-format msgid "%s at or near \"%s\"" msgstr "%s en o cerca de «%s»" diff --git a/src/pl/plpgsql/src/po/fr.po b/src/pl/plpgsql/src/po/fr.po index 19676ff681cb8..f2b93ddb884d0 100644 --- a/src/pl/plpgsql/src/po/fr.po +++ b/src/pl/plpgsql/src/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-08-22 10:09+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,161 +19,176 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: pl_comp.c:438 pl_handler.c:496 +#: pl_comp.c:434 pl_handler.c:496 #, c-format msgid "PL/pgSQL functions cannot accept type %s" msgstr "les fonctions PL/pgSQL ne peuvent pas accepter le type %s" -#: pl_comp.c:530 +#: pl_comp.c:526 #, c-format msgid "could not determine actual return type for polymorphic function \"%s\"" msgstr "n'a pas pu déterminer le type de retour pour la fonction polymorphique « %s »" -#: pl_comp.c:560 +#: pl_comp.c:556 #, c-format msgid "trigger functions can only be called as triggers" msgstr "les fonctions trigger peuvent seulement être appelées par des triggers" -#: pl_comp.c:564 pl_handler.c:480 +#: pl_comp.c:560 pl_handler.c:480 #, c-format msgid "PL/pgSQL functions cannot return type %s" msgstr "les fonctions PL/pgSQL ne peuvent pas renvoyer le type %s" -#: pl_comp.c:604 +#: pl_comp.c:600 #, c-format msgid "trigger functions cannot have declared arguments" msgstr "les fonctions triggers ne peuvent pas avoir d'arguments déclarés" -#: pl_comp.c:605 +#: pl_comp.c:601 #, c-format msgid "The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead." msgstr "À la place, on peut accéder aux arguments du trigger par TG_NARGS et TG_ARGV." -#: pl_comp.c:738 +#: pl_comp.c:734 #, c-format msgid "event trigger functions cannot have declared arguments" msgstr "les fonctions triggers sur événement ne peuvent pas avoir des arguments déclarés" -#: pl_comp.c:1002 +#: pl_comp.c:998 #, c-format msgid "compilation of PL/pgSQL function \"%s\" near line %d" msgstr "compilation de la fonction PL/pgSQL « %s » près de la ligne %d" -#: pl_comp.c:1025 +#: pl_comp.c:1021 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "le nom du paramètre « %s » est utilisé plus d'une fois" -#: pl_comp.c:1139 +#: pl_comp.c:1135 #, c-format msgid "column reference \"%s\" is ambiguous" -msgstr "la référence à la colonne « %s » est ambigüe" +msgstr "la référence à la colonne « %s » est ambiguë" -#: pl_comp.c:1141 +#: pl_comp.c:1137 #, c-format msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "Cela pourrait faire référence à une variable PL/pgSQL ou à la colonne d'une table." -#: pl_comp.c:1324 pl_exec.c:5216 pl_exec.c:5389 pl_exec.c:5476 pl_exec.c:5567 -#: pl_exec.c:6588 +#: pl_comp.c:1314 pl_exec.c:5260 pl_exec.c:5433 pl_exec.c:5520 pl_exec.c:5611 +#: pl_exec.c:6636 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "l'enregistrement « %s » n'a pas de champs « %s »" -#: pl_comp.c:1818 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "la variable « %s » n'existe pas" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "la colonne « %s » de la relation « %s » n'existe pas" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "la relation « %s » n'existe pas" -#: pl_comp.c:1825 pl_comp.c:1867 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "la relation « %s » n'a pas un type composite" -#: pl_comp.c:1933 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "la variable « %s » a le pseudo-type %s" -#: pl_comp.c:2122 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "le type « %s » n'est qu'une coquille" -#: pl_comp.c:2204 pl_exec.c:6889 +#: pl_comp.c:2157 pl_exec.c:6937 #, c-format msgid "type %s is not composite" msgstr "le type %s n'est pas un type composite" -#: pl_comp.c:2252 pl_comp.c:2305 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "n'a pas pu trouver de type tableau pour le type de données %s" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "condition d'exception non reconnue « %s »" -#: pl_comp.c:2526 +#: pl_comp.c:2514 #, c-format msgid "could not determine actual argument type for polymorphic function \"%s\"" msgstr "n'a pas pu déterminer le type d'argument pour la fonction polymorphique « %s »" -#: pl_exec.c:500 pl_exec.c:939 pl_exec.c:1174 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "durant l'initialisation de l'état de la fonction" -#: pl_exec.c:506 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "lors du stockage des arguments dans les variables locales" -#: pl_exec.c:594 pl_exec.c:1012 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "durant l'entrée d'une fonction" -#: pl_exec.c:617 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "le contrôle a atteint la fin de la fonction sans RETURN" -#: pl_exec.c:623 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "lors de la conversion de la valeur de retour au type de retour de la fonction" -#: pl_exec.c:635 pl_exec.c:3656 +#: pl_exec.c:647 pl_exec.c:3683 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "la fonction renvoyant un ensemble a été appelée dans un contexte qui n'accepte pas un ensemble" -#: pl_exec.c:640 pl_exec.c:3662 +#: pl_exec.c:652 pl_exec.c:3689 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "mode matérialisé requis mais interdit dans ce contexte" -#: pl_exec.c:767 pl_exec.c:1038 pl_exec.c:1196 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "lors de la sortie de la fonction" -#: pl_exec.c:822 pl_exec.c:886 pl_exec.c:3455 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3482 msgid "returned record type does not match expected record type" msgstr "le type d'enregistrement renvoyé ne correspond pas au type d'enregistrement attendu" -#: pl_exec.c:1035 pl_exec.c:1193 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "le contrôle a atteint la fin de la procédure trigger sans RETURN" -#: pl_exec.c:1043 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "une procédure trigger ne peut pas renvoyer un ensemble" -#: pl_exec.c:1082 pl_exec.c:1110 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "returned row structure does not match the structure of the triggering table" msgstr "la structure de ligne renvoyée ne correspond pas à la structure de la table du trigger" #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1251 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "fonction PL/pgSQL %s, ligne %d, %s" @@ -181,49 +196,49 @@ msgstr "fonction PL/pgSQL %s, ligne %d, %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1262 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "fonction PL/pgSQL %s, %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1270 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "fonction PL/pgSQL %s, ligne %d à %s" -#: pl_exec.c:1276 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "fonction PL/pgSQL %s" -#: pl_exec.c:1647 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "lors de l'initialisation des variables locales du bloc d'instructions" -#: pl_exec.c:1752 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "lors de l'entrée dans le bloc d'instructions" -#: pl_exec.c:1784 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "lors de la sortie du bloc d'instructions" -#: pl_exec.c:1822 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "lors du nettoyage de l'exception" -#: pl_exec.c:2355 +#: pl_exec.c:2370 #, c-format msgid "procedure parameter \"%s\" is an output parameter but corresponding argument is not writable" msgstr "le paramètre de la procédure « %s » est un argument en sortie mais l'argument correspondant n'est pas modifiable" -#: pl_exec.c:2360 +#: pl_exec.c:2375 #, c-format msgid "procedure parameter %d is an output parameter but corresponding argument is not writable" msgstr "le paramètre de la procédure %d est un paramètre en sortie mais l'argument correspondant n'est pas modifiable" -#: pl_exec.c:2394 +#: pl_exec.c:2411 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "GET STACKED DIAGNOSTICS ne peut pas être utilisé à l'extérieur d'un gestionnaire d'exception" @@ -234,288 +249,293 @@ msgstr "GET STACKED DIAGNOSTICS ne peut pas être utilisé à l'extérieur d'un # (errcode(ERRCODE_CASE_NOT_FOUND), # errmsg("case not found"), # errhint("CASE statement is missing ELSE part."))); -#: pl_exec.c:2594 +#: pl_exec.c:2617 #, c-format msgid "case not found" msgstr "cas introuvable" -#: pl_exec.c:2595 +#: pl_exec.c:2618 #, c-format msgid "CASE statement is missing ELSE part." msgstr "l'instruction CASE n'a pas de partie ELSE." -#: pl_exec.c:2688 +#: pl_exec.c:2711 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "la limite inférieure d'une boucle FOR ne peut pas être NULL" -#: pl_exec.c:2704 +#: pl_exec.c:2727 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "la limite supérieure de la boucle FOR ne peut pas être NULL" -#: pl_exec.c:2722 +#: pl_exec.c:2745 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "la valeur BY d'une boucle FOR ne peut pas être NULL" -#: pl_exec.c:2728 +#: pl_exec.c:2751 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "la valeur BY d'une boucle FOR doit être plus grande que zéro" -#: pl_exec.c:2862 pl_exec.c:4658 +#: pl_exec.c:2885 pl_exec.c:4693 #, c-format msgid "cursor \"%s\" already in use" msgstr "curseur « %s » déjà en cours d'utilisation" -#: pl_exec.c:2885 pl_exec.c:4723 +#: pl_exec.c:2908 pl_exec.c:4763 #, c-format msgid "arguments given for cursor without arguments" msgstr "arguments fournis pour un curseur sans argument" -#: pl_exec.c:2904 pl_exec.c:4742 +#: pl_exec.c:2927 pl_exec.c:4782 #, c-format msgid "arguments required for cursor" msgstr "arguments requis pour le curseur" -#: pl_exec.c:2991 +#: pl_exec.c:3018 #, c-format msgid "FOREACH expression must not be null" msgstr "l'expression FOREACH ne doit pas être NULL" -#: pl_exec.c:3006 +#: pl_exec.c:3033 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "l'expression FOREACH doit renvoyer un tableau, pas un type %s" -#: pl_exec.c:3023 +#: pl_exec.c:3050 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "la dimension de la partie (%d) est en dehors des valeurs valides (0..%d)" -#: pl_exec.c:3050 +#: pl_exec.c:3077 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "la variable d'une boucle FOREACH ... SLICE doit être d'un type tableau" -#: pl_exec.c:3054 +#: pl_exec.c:3081 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "la valeur d'une boucle FOREACH ne doit pas être de type tableau" -#: pl_exec.c:3216 pl_exec.c:3273 pl_exec.c:3448 +#: pl_exec.c:3243 pl_exec.c:3300 pl_exec.c:3475 #, c-format msgid "cannot return non-composite value from function returning composite type" msgstr "ne peut pas renvoyer de valeurs non composites à partir d'une fonction renvoyant un type composite" -#: pl_exec.c:3312 pl_gram.y:3318 +#: pl_exec.c:3339 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "ne peut pas utiliser RETURN NEXT dans une fonction non SETOF" -#: pl_exec.c:3353 pl_exec.c:3485 +#: pl_exec.c:3380 pl_exec.c:3512 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "mauvais type de résultat fourni dans RETURN NEXT" -#: pl_exec.c:3391 pl_exec.c:3412 +#: pl_exec.c:3418 pl_exec.c:3439 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "mauvais type d'enregistrement fourni à RETURN NEXT" -#: pl_exec.c:3504 +#: pl_exec.c:3531 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "RETURN NEXT doit avoir un paramètre" -#: pl_exec.c:3532 pl_gram.y:3382 +#: pl_exec.c:3559 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "ne peut pas utiliser RETURN QUERY dans une fonction non SETOF" -#: pl_exec.c:3550 +#: pl_exec.c:3577 msgid "structure of query does not match function result type" msgstr "la structure de la requête ne correspond pas au type de résultat de la fonction" -#: pl_exec.c:3605 pl_exec.c:4435 pl_exec.c:8630 +#: pl_exec.c:3632 pl_exec.c:4469 pl_exec.c:8759 #, c-format msgid "query string argument of EXECUTE is null" msgstr "l'argument de la requête d'EXECUTE est NULL" -#: pl_exec.c:3690 pl_exec.c:3828 +#: pl_exec.c:3717 pl_exec.c:3855 #, c-format msgid "RAISE option already specified: %s" msgstr "option RAISE déjà spécifiée : %s" -#: pl_exec.c:3724 +#: pl_exec.c:3751 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "RAISE sans paramètre ne peut pas être utilisé sans un gestionnaire d'exceptions" -#: pl_exec.c:3818 +#: pl_exec.c:3845 #, c-format msgid "RAISE statement option cannot be null" msgstr "l'option de l'instruction RAISE ne peut pas être NULL" -#: pl_exec.c:3888 +#: pl_exec.c:3915 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3943 +#: pl_exec.c:3970 #, c-format msgid "assertion failed" msgstr "échec de l'assertion" -#: pl_exec.c:4308 pl_exec.c:4497 +#: pl_exec.c:4342 pl_exec.c:4532 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "ne peut pas utiliser COPY vers/depuis un client en PL/pgSQL" -#: pl_exec.c:4314 +#: pl_exec.c:4348 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "commande de transaction non supportée dans PL/pgSQL" -#: pl_exec.c:4337 pl_exec.c:4526 +#: pl_exec.c:4371 pl_exec.c:4561 #, c-format msgid "INTO used with a command that cannot return data" msgstr "INTO utilisé dans une commande qui ne peut pas envoyer de données" -#: pl_exec.c:4360 pl_exec.c:4549 +#: pl_exec.c:4394 pl_exec.c:4584 #, c-format msgid "query returned no rows" msgstr "la requête n'a renvoyé aucune ligne" -#: pl_exec.c:4382 pl_exec.c:4568 pl_exec.c:5711 +#: pl_exec.c:4416 pl_exec.c:4603 pl_exec.c:5755 #, c-format msgid "query returned more than one row" msgstr "la requête a renvoyé plus d'une ligne" -#: pl_exec.c:4384 +#: pl_exec.c:4418 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "Assurez-vous que la requête ne renvoie qu'une seule ligne ou utilisez LIMIT 1." -#: pl_exec.c:4400 +#: pl_exec.c:4434 #, c-format msgid "query has no destination for result data" msgstr "la requête n'a pas de destination pour les données résultantes" -#: pl_exec.c:4401 +#: pl_exec.c:4435 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "Si vous voulez ignorer le résultat d'un SELECT, utilisez PERFORM à la place." -#: pl_exec.c:4489 +#: pl_exec.c:4524 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" -msgstr "EXECUTE n'est pas implementé pour SELECT ... INTO" +msgstr "EXECUTE n'est pas implémenté pour SELECT ... INTO" -#: pl_exec.c:4490 +#: pl_exec.c:4525 #, c-format msgid "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead." msgstr "Vous pouvez aussi utiliser EXECUTE ... INTO ou EXECUTE CREATE TABLE ... AS à la place." -#: pl_exec.c:4503 +#: pl_exec.c:4538 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "EXECUTE pour les commandes de transactions n'est pas implémenté" -#: pl_exec.c:4804 pl_exec.c:4892 +#: pl_exec.c:4848 pl_exec.c:4936 #, c-format msgid "cursor variable \"%s\" is null" msgstr "la variable du curseur « %s » est NULL" -#: pl_exec.c:4815 pl_exec.c:4903 +#: pl_exec.c:4859 pl_exec.c:4947 #, c-format msgid "cursor \"%s\" does not exist" msgstr "le curseur « %s » n'existe pas" -#: pl_exec.c:4828 +#: pl_exec.c:4872 #, c-format msgid "relative or absolute cursor position is null" msgstr "la position relative ou absolue du curseur est NULL" -#: pl_exec.c:5066 pl_exec.c:5161 +#: pl_exec.c:5110 pl_exec.c:5205 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "une valeur NULL ne peut pas être affectée à la variable « %s » déclarée non NULL" -#: pl_exec.c:5142 +#: pl_exec.c:5186 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "ne peut pas affecter une valeur non composite à une variable de type ROW" -#: pl_exec.c:5174 +#: pl_exec.c:5218 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "ne peut pas affecter une valeur non composite à une variable RECORD" -#: pl_exec.c:5225 +#: pl_exec.c:5269 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "ne peut pas affecter à une colonne système « %s »" -#: pl_exec.c:5674 +#: pl_exec.c:5718 #, c-format msgid "query did not return data" msgstr "la requête n'a pas renvoyé de données" -#: pl_exec.c:5675 pl_exec.c:5687 pl_exec.c:5712 pl_exec.c:5788 pl_exec.c:5793 +#: pl_exec.c:5719 pl_exec.c:5731 pl_exec.c:5756 pl_exec.c:5832 pl_exec.c:5837 #, c-format msgid "query: %s" msgstr "requête : %s" -#: pl_exec.c:5683 +#: pl_exec.c:5727 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" msgstr[0] "la requête a renvoyé %d colonne" msgstr[1] "la requête a renvoyé %d colonnes" -#: pl_exec.c:5787 +#: pl_exec.c:5831 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "la requête est SELECT INTO, alors qu'elle devrait être un simple SELECT" -#: pl_exec.c:5792 +#: pl_exec.c:5836 #, c-format msgid "query is not a SELECT" msgstr "la requête n'est pas un SELECT" -#: pl_exec.c:6602 pl_exec.c:6642 pl_exec.c:6682 +#: pl_exec.c:6650 pl_exec.c:6690 pl_exec.c:6730 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "le type de paramètre %d (%s) ne correspond pas à celui préparé dans le plan (%s)" -#: pl_exec.c:7093 pl_exec.c:7127 pl_exec.c:7201 pl_exec.c:7227 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "le nombre de champs source et celui de champs cible dans l'affectation ne correspondent pas" #. translator: %s represents a name of an extra check -#: pl_exec.c:7095 pl_exec.c:7129 pl_exec.c:7203 pl_exec.c:7229 +#: pl_exec.c:7143 pl_exec.c:7177 pl_exec.c:7251 pl_exec.c:7277 #, c-format msgid "%s check of %s is active." msgstr "%s vérification de %s est active." -#: pl_exec.c:7099 pl_exec.c:7133 pl_exec.c:7207 pl_exec.c:7233 +#: pl_exec.c:7147 pl_exec.c:7181 pl_exec.c:7255 pl_exec.c:7281 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "Assurez-vous que la requête renvoie la liste exacte des colonnes." -#: pl_exec.c:7620 +#: pl_exec.c:7668 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "l'enregistrement « %s » n'est pas encore affecté" -#: pl_exec.c:7621 +#: pl_exec.c:7669 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "La structure de ligne d'un enregistrement pas encore affecté est indéterminée." +#: pl_exec.c:8357 pl_gram.y:3498 +#, c-format +msgid "variable \"%s\" is declared CONSTANT" +msgstr "la variable « %s » est déclarée CONSTANT" + #: pl_funcs.c:237 msgid "statement block" msgstr "bloc d'instructions" @@ -548,280 +568,274 @@ msgstr "instruction SQL" msgid "FOR over EXECUTE statement" msgstr "FOR sur une instruction EXECUTE" -#: pl_gram.y:486 +#: pl_gram.y:485 #, c-format msgid "block label must be placed before DECLARE, not after" msgstr "le label du bloc doit être placé avant DECLARE, et non pas après" -#: pl_gram.y:506 +#: pl_gram.y:505 #, c-format msgid "collations are not supported by type %s" msgstr "les collationnements ne sont pas supportés par le type %s" -#: pl_gram.y:525 +#: pl_gram.y:524 #, c-format msgid "variable \"%s\" must have a default value, since it's declared NOT NULL" msgstr "la variable « %s » doit avoir une valeur par défaut car elle est déclarée NOT NULL" -#: pl_gram.y:673 pl_gram.y:688 pl_gram.y:714 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "la variable « %s » n'existe pas" - -#: pl_gram.y:732 pl_gram.y:760 +#: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "déclaration dupliquée" -#: pl_gram.y:743 pl_gram.y:771 +#: pl_gram.y:715 pl_gram.y:743 #, c-format msgid "variable \"%s\" shadows a previously defined variable" msgstr "la variable « %s » cache une variable définie précédemment" -#: pl_gram.y:1043 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "l'élément %s de diagnostique n'est pas autorisé dans GET STACKED DIAGNOSTICS" -#: pl_gram.y:1061 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "l'élément %s de diagnostique n'est pas autorisé dans GET CURRENT DIAGNOSTICS" -#: pl_gram.y:1156 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "élément GET DIAGNOSTICS non reconnu" -#: pl_gram.y:1172 pl_gram.y:3557 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "« %s » n'est pas une variable scalaire" -#: pl_gram.y:1402 pl_gram.y:1596 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "loop variable of loop over rows must be a record variable or list of scalar variables" msgstr "la variable d'une boucle sur des lignes doit être une variable de type record ou une liste de variables scalaires" -#: pl_gram.y:1437 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "le curseur de la boucle FOR ne doit avoir qu'une seule variable cible" -#: pl_gram.y:1444 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "le curseur de la boucle FOR doit utiliser une variable d'un curseur lié" -#: pl_gram.y:1535 +#: pl_gram.y:1511 #, c-format msgid "integer FOR loop must have only one target variable" msgstr "une boucle FOR de type entier ne doit avoir qu'une seule variable cible" -#: pl_gram.y:1569 +#: pl_gram.y:1545 #, c-format msgid "cannot specify REVERSE in query FOR loop" msgstr "ne peut pas spécifier REVERSE dans la requête d'une boucle FOR" -#: pl_gram.y:1699 +#: pl_gram.y:1675 #, c-format msgid "loop variable of FOREACH must be a known variable or list of variables" msgstr "la variable d'une boucle FOREACH doit être une variable connue ou une liste de variables" -#: pl_gram.y:1741 +#: pl_gram.y:1717 #, c-format msgid "there is no label \"%s\" attached to any block or loop enclosing this statement" msgstr "il n'existe pas de label « %s » attaché à un bloc ou à une boucle englobant cette instruction" -#: pl_gram.y:1749 +#: pl_gram.y:1725 #, c-format msgid "block label \"%s\" cannot be used in CONTINUE" msgstr "le label de bloc « %s » ne peut pas être utilisé avec CONTINUE" -#: pl_gram.y:1764 +#: pl_gram.y:1740 #, c-format msgid "EXIT cannot be used outside a loop, unless it has a label" msgstr "EXIT ne peut pas être utilisé à l'extérieur d'une boucle, sauf s'il a un label" -#: pl_gram.y:1765 +#: pl_gram.y:1741 #, c-format msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE ne peut pas être utilisé à l'extérieur d'une boucle" -#: pl_gram.y:1789 pl_gram.y:1827 pl_gram.y:1875 pl_gram.y:3004 pl_gram.y:3092 -#: pl_gram.y:3203 pl_gram.y:3956 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "fin inattendue de la définition de la fonction" -#: pl_gram.y:1895 pl_gram.y:1919 pl_gram.y:1935 pl_gram.y:1941 pl_gram.y:2066 -#: pl_gram.y:2074 pl_gram.y:2088 pl_gram.y:2183 pl_gram.y:2407 pl_gram.y:2497 -#: pl_gram.y:2655 pl_gram.y:3799 pl_gram.y:3860 pl_gram.y:3937 +#: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 +#: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "erreur de syntaxe" -#: pl_gram.y:1923 pl_gram.y:1925 pl_gram.y:2411 pl_gram.y:2413 +#: pl_gram.y:1899 pl_gram.y:1901 pl_gram.y:2387 pl_gram.y:2389 msgid "invalid SQLSTATE code" msgstr "code SQLSTATE invalide" -#: pl_gram.y:2131 +#: pl_gram.y:2107 msgid "syntax error, expected \"FOR\"" msgstr "erreur de syntaxe, « FOR » attendu" -#: pl_gram.y:2192 +#: pl_gram.y:2168 #, c-format msgid "FETCH statement cannot return multiple rows" msgstr "l'instruction FETCH ne peut pas renvoyer plusieurs lignes" -#: pl_gram.y:2289 +#: pl_gram.y:2265 #, c-format msgid "cursor variable must be a simple variable" msgstr "la variable de curseur doit être une variable simple" -#: pl_gram.y:2295 +#: pl_gram.y:2271 #, c-format msgid "variable \"%s\" must be of type cursor or refcursor" msgstr "la variable « %s » doit être de type cursor ou refcursor" -#: pl_gram.y:2626 pl_gram.y:2637 +#: pl_gram.y:2603 pl_gram.y:2614 #, c-format msgid "\"%s\" is not a known variable" msgstr "« %s » n'est pas une variable connue" -#: pl_gram.y:2743 pl_gram.y:2753 pl_gram.y:2909 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "parenthèses non correspondantes" -#: pl_gram.y:2757 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "« %s » manquant à la fin de l'expression SQL" -#: pl_gram.y:2763 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "« %s » manquant à la fin de l'instruction SQL" -#: pl_gram.y:2780 +#: pl_gram.y:2758 msgid "missing expression" msgstr "expression manquante" -#: pl_gram.y:2782 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "instruction SQL manquante" -#: pl_gram.y:2911 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "erreur de syntaxe, « ] » attendu" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "déclaration incomplète d'un type de données" -#: pl_gram.y:2934 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "déclaration manquante d'un type de données" -#: pl_gram.y:3014 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO spécifié plus d'une fois" -#: pl_gram.y:3184 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "attendait FROM ou IN" -#: pl_gram.y:3245 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "RETURN ne peut pas avoir de paramètre dans une fonction renvoyant un ensemble" -#: pl_gram.y:3246 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "Utilisez RETURN NEXT ou RETURN QUERY." -#: pl_gram.y:3256 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "RETURN ne peut pas avoir de paramètre dans une procédure" -#: pl_gram.y:3261 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "RETURN ne peut pas avoir de paramètre dans une fonction renvoyant void" -#: pl_gram.y:3270 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "RETURN ne peut pas avoir de paramètre dans une fonction avec des paramètres OUT" -#: pl_gram.y:3333 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "RETURN NEXT ne peut pas avoir de paramètre dans une fonction avec des paramètres OUT" -#: pl_gram.y:3441 -#, c-format -msgid "variable \"%s\" is declared CONSTANT" -msgstr "la variable « %s » est déclarée CONSTANT" - -#: pl_gram.y:3499 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "la variable de type record ne peut pas faire partie d'une liste INTO à plusieurs éléments" -#: pl_gram.y:3545 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "trop de variables INTO indiquées" -#: pl_gram.y:3753 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "label de fin « %s » spécifié pour un bloc sans label" -#: pl_gram.y:3760 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "le label de fin « %s » est différent du label « %s » du bloc" -#: pl_gram.y:3794 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "le curseur « %s » n'a pas d'argument" -#: pl_gram.y:3808 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "le curseur « %s » a des arguments" -#: pl_gram.y:3850 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "le curseur « %s » n'a pas d'argument nommé « %s »" -#: pl_gram.y:3870 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "la valeur du paramètre « %s » pour le curseur « %s » est spécifiée plus d'une fois" -#: pl_gram.y:3895 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "pas assez d'arguments pour le curseur « %s »" -#: pl_gram.y:3902 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "trop d'arguments pour le curseur « %s »" -#: pl_gram.y:3988 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "option de l'instruction RAISE inconnue" -#: pl_gram.y:3992 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "erreur de syntaxe, « = » attendu" -#: pl_gram.y:4033 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "trop de paramètres spécifiés pour RAISE" -#: pl_gram.y:4037 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "trop peu de paramètres pour RAISE" @@ -847,158 +861,13 @@ msgid "List of programming constructs that should produce an error." msgstr "Liste des constructions de programmation qui devraient produire une erreur." #. translator: %s is typically the translation of "syntax error" -#: pl_scanner.c:508 +#: pl_scanner.c:525 #, c-format msgid "%s at end of input" msgstr "%s à la fin de l'entrée" #. translator: first %s is typically the translation of "syntax error" -#: pl_scanner.c:524 +#: pl_scanner.c:541 #, c-format msgid "%s at or near \"%s\"" msgstr "%s sur ou près de « %s »" - -#~ msgid "EXECUTE statement" -#~ msgstr "instruction EXECUTE" - -#~ msgid "Expected \"FOR\", to open a cursor for an unbound cursor variable." -#~ msgstr "Attendait « FOR » pour ouvrir un curseur pour une variable sans limite." - -#~ msgid "Expected record variable, row variable, or list of scalar variables following INTO." -#~ msgstr "" -#~ "Attendait une variable RECORD, ROW ou une liste de variables scalaires\n" -#~ "suivant INTO." - -#~ msgid "N/A (dropped column)" -#~ msgstr "N/A (colonne supprimée)" - -#~ msgid "Number of returned columns (%d) does not match expected column count (%d)." -#~ msgstr "" -#~ "Le nombre de colonnes renvoyées (%d) ne correspond pas au nombre de colonnes\n" -#~ "attendues (%d)." - -#~ msgid "RETURN NEXT must specify a record or row variable in function returning row" -#~ msgstr "" -#~ "RETURN NEXT doit indiquer une variable RECORD ou ROW dans une fonction\n" -#~ "renvoyant une ligne" - -#~ msgid "RETURN cannot have a parameter in function returning set; use RETURN NEXT or RETURN QUERY" -#~ msgstr "" -#~ "RETURN ne peut pas avoir un paramètre dans une fonction renvoyant des\n" -#~ "lignes ; utilisez RETURN NEXT ou RETURN QUERY" - -#~ msgid "RETURN must specify a record or row variable in function returning row" -#~ msgstr "" -#~ "RETURN ne peut pas indiquer une variable RECORD ou ROW dans une fonction\n" -#~ "renvoyant une ligne" - -#~ msgid "Returned type %s does not match expected type %s in column \"%s\"." -#~ msgstr "Le type %s renvoyé ne correspond pas au type %s attendu dans la colonne « %s »." - -#~ msgid "SQL statement in PL/PgSQL function \"%s\" near line %d" -#~ msgstr "instruction SQL dans la fonction PL/pgsql « %s » près de la ligne %d" - -#~ msgid "Use a BEGIN block with an EXCEPTION clause instead." -#~ msgstr "Utiliser un bloc BEGIN dans une clause EXCEPTION à la place." - -#~ msgid "array subscript in assignment must not be null" -#~ msgstr "un indice de tableau dans une affectation ne peut pas être NULL" - -#~ msgid "cannot assign to tg_argv" -#~ msgstr "ne peut pas affecter à tg_argv" - -#~ msgid "cursor \"%s\" closed unexpectedly" -#~ msgstr "le curseur « %s » a été fermé de façon inattendu" - -#~ msgid "default value for row or record variable is not supported" -#~ msgstr "la valeur par défaut de variable ROW ou RECORD n'est pas supportée" - -#~ msgid "expected \")\"" -#~ msgstr "« ) » attendu" - -#~ msgid "expected \"[\"" -#~ msgstr "« [ » attendu" - -#~ msgid "expected a cursor or refcursor variable" -#~ msgstr "attendait une variable de type cursor ou refcursor" - -#~ msgid "expected an integer variable" -#~ msgstr "attend une variable entière" - -#~ msgid "function has no parameter \"%s\"" -#~ msgstr "la fonction n'a pas de paramètre « %s »" - -#~ msgid "label does not exist" -#~ msgstr "le label n'existe pas" - -#~ msgid "number of array dimensions (%d) exceeds the maximum allowed (%d)" -#~ msgstr "le nombre de dimensions du tableau (%d) dépasse la maximum autorisé (%d)" - -#~ msgid "only positional parameters can be aliased" -#~ msgstr "seuls les paramètres de position peuvent avoir un alias" - -#~ msgid "qualified identifier cannot be used here: %s" -#~ msgstr "l'identifiant qualifié ne peut pas être utilisé ici : %s" - -#~ msgid "query \"%s\" returned more than one row" -#~ msgstr "la requête « %s » a renvoyé plus d'une ligne" - -#~ msgid "relation \"%s\" is not a table" -#~ msgstr "la relation « %s » n'est pas une table" - -#~ msgid "relation \"%s.%s\" does not exist" -#~ msgstr "la relation « %s.%s » n'existe pas" - -#~ msgid "row \"%s\" has no field \"%s\"" -#~ msgstr "la ligne « %s » n'a aucun champ « %s »" - -#~ msgid "row \"%s.%s\" has no field \"%s\"" -#~ msgstr "la ligne « %s.%s » n'a aucun champ « %s »" - -#~ msgid "row or record variable cannot be CONSTANT" -#~ msgstr "la variable ROW ou RECORD ne peut pas être CONSTANT" - -#~ msgid "row or record variable cannot be NOT NULL" -#~ msgstr "la variable ROW ou RECORD ne peut pas être NOT NULL" - -#~ msgid "string literal in PL/PgSQL function \"%s\" near line %d" -#~ msgstr "chaîne littérale dans la fonction PL/pgsql « %s » près de la ligne %d" - -#~ msgid "subscripted object is not an array" -#~ msgstr "l'objet souscrit n'est pas un tableau" - -#~ msgid "syntax error at \"%s\"" -#~ msgstr "erreur de syntaxe à « %s »" - -#~ msgid "too many variables specified in SQL statement" -#~ msgstr "trop de variables spécifiées dans l'instruction SQL" - -#~ msgid "type of \"%s\" does not match that when preparing the plan" -#~ msgstr "le type de « %s » ne correspond pas à ce qui est préparé dans le plan" - -#~ msgid "type of \"%s.%s\" does not match that when preparing the plan" -#~ msgstr "le type de « %s.%s » ne correspond pas à ce qui est préparé dans le plan" - -#~ msgid "type of tg_argv[%d] does not match that when preparing the plan" -#~ msgstr "le type de tg_argv[%d] ne correspond pas à ce qui est préparé dans le plan" - -#~ msgid "unterminated \" in identifier: %s" -#~ msgstr "\" non terminé dans l'identifiant : %s" - -#~ msgid "unterminated /* comment" -#~ msgstr "commentaire /* non terminé" - -#~ msgid "unterminated dollar-quoted string" -#~ msgstr "chaîne entre dollars non terminée" - -#~ msgid "unterminated quoted identifier" -#~ msgstr "identifiant entre guillemets non terminé" - -#~ msgid "unterminated quoted string" -#~ msgstr "chaîne entre guillemets non terminée" - -#~ msgid "variable \"%s\" declared NOT NULL cannot default to NULL" -#~ msgstr "la variable « %s » déclarée NOT NULL ne peut pas valoir NULL par défaut" - -#~ msgid "variable \"%s\" does not exist in the current block" -#~ msgstr "la variable « %s » n'existe pas dans le bloc actuel" diff --git a/src/pl/plpgsql/src/po/ko.po b/src/pl/plpgsql/src/po/ko.po index 567aec9e1727f..596410785157c 100644 --- a/src/pl/plpgsql/src/po/ko.po +++ b/src/pl/plpgsql/src/po/ko.po @@ -4,10 +4,10 @@ # Ioseph Kim , 2010 msgid "" msgstr "" -"Project-Id-Version: plpgsql (PostgreSQL) 16\n" +"Project-Id-Version: plpgsql (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:39+0000\n" -"PO-Revision-Date: 2023-05-30 12:40+0900\n" +"POT-Creation-Date: 2025-01-17 04:39+0000\n" +"PO-Revision-Date: 2025-01-16 10:40+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean \n" "Language: ko\n" @@ -73,100 +73,115 @@ msgstr "열 참조 \"%s\" 가 명확하지 않습니다." msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "PL/pgSQL 변수명도, 테이블 칼럼 이름도 아니여야 함" -#: pl_comp.c:1314 pl_exec.c:5255 pl_exec.c:5428 pl_exec.c:5515 pl_exec.c:5606 -#: pl_exec.c:6624 +#: pl_comp.c:1314 pl_exec.c:5260 pl_exec.c:5433 pl_exec.c:5520 pl_exec.c:5611 +#: pl_exec.c:6636 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "\"%s\" 레코드에 \"%s\" 필드가 없음" -#: pl_comp.c:1808 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "\"%s\" 변수가 없음" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "\"%s\" 칼럼이 \"%s\" 릴레이션에 없음" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "\"%s\" 이름의 릴레이션(relation)이 없습니다" -#: pl_comp.c:1815 pl_comp.c:1857 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "\"%s\" 릴레이션에는 복합 자료형이 없습니다" -#: pl_comp.c:1923 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "\"%s\" 변수에 의사 형식 %s이(가) 있음" -#: pl_comp.c:2112 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "자료형 \"%s\" 는 오로지 shell 에만 있습니다. " -#: pl_comp.c:2194 pl_exec.c:6925 +#: pl_comp.c:2157 pl_exec.c:6937 #, c-format msgid "type %s is not composite" msgstr "%s 자료형은 복합 자료형이 아님" -#: pl_comp.c:2242 pl_comp.c:2295 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "%s 자료형을 사용하는 배열 자료형이 없음" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "인식할 수 없는 예외 조건 \"%s\"" -#: pl_comp.c:2524 +#: pl_comp.c:2514 #, c-format msgid "" "could not determine actual argument type for polymorphic function \"%s\"" msgstr "다형적 함수 \"%s\"의 실제 인수 형식을 확인할 수 없음" -#: pl_exec.c:511 pl_exec.c:950 pl_exec.c:1185 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "실행 상태를 초기화하는 동안" -#: pl_exec.c:517 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "호출 인수를 로컬 변수에 저장하는 동안" -#: pl_exec.c:605 pl_exec.c:1023 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "함수를 시작하는 동안" -#: pl_exec.c:628 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "컨트롤이 RETURN 없이 함수 끝에 도달함" -#: pl_exec.c:634 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "함수의 반환 형식으로 반환 값을 형변환하는 동안" -#: pl_exec.c:646 pl_exec.c:3681 +#: pl_exec.c:647 pl_exec.c:3683 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "" "set-values 함수(테이블 리턴 함수)가 set 정의 없이 사용되었습니다 (테이블과 해" "당 열 alias 지정하세요)" -#: pl_exec.c:651 pl_exec.c:3687 +#: pl_exec.c:652 pl_exec.c:3689 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialize 모드가 필요합니다만, 이 구문에서는 허용되지 않습니다" -#: pl_exec.c:778 pl_exec.c:1049 pl_exec.c:1207 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "함수를 종료하는 동안" -#: pl_exec.c:833 pl_exec.c:897 pl_exec.c:3480 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3482 msgid "returned record type does not match expected record type" msgstr "반환된 레코드 형식이 필요한 레코드 형식과 일치하지 않음" -#: pl_exec.c:1046 pl_exec.c:1204 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "컨트롤이 RETURN 없이 트리거 프로시저 끝에 도달함" -#: pl_exec.c:1054 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "트리거 프로시저는 집합을 반환할 수 없음" -#: pl_exec.c:1093 pl_exec.c:1121 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "" "returned row structure does not match the structure of the triggering table" msgstr "반환된 행 구조가 트리거하는 테이블의 구조와 일치하지 않음" @@ -174,7 +189,7 @@ msgstr "반환된 행 구조가 트리거하는 테이블의 구조와 일치하 #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1262 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "PL/pgSQL 함수 \"%s\" 의 %d번째 줄 %s" @@ -182,35 +197,35 @@ msgstr "PL/pgSQL 함수 \"%s\" 의 %d번째 줄 %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1273 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "PL/pgSQL 함수 %s %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1281 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "PL/pgSQL 함수 \"%s\" 의 %d번째 %s" -#: pl_exec.c:1287 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "PL/pgSQL 함수 %s" -#: pl_exec.c:1658 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "문 블록 로컬 변수를 초기화하는 동안" -#: pl_exec.c:1763 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "문 블록을 시작하는 동안" -#: pl_exec.c:1795 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "문 블록을 종료하는 동안" -#: pl_exec.c:1833 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "예외를 정리하는 동안" @@ -228,299 +243,299 @@ msgid "" "not writable" msgstr "%d 프로시져 인자는 출력 인자인데, 값 변경이 불가능 함" -#: pl_exec.c:2409 +#: pl_exec.c:2411 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "GET STACKED DIAGNOSTICS 구문은 예외처리 헨들러 밖에서 사용할 수 없음" -#: pl_exec.c:2615 +#: pl_exec.c:2617 #, c-format msgid "case not found" msgstr "사례를 찾지 못함" -#: pl_exec.c:2616 +#: pl_exec.c:2618 #, c-format msgid "CASE statement is missing ELSE part." msgstr "CASE 문에 ELSE 부분이 누락되었습니다." -#: pl_exec.c:2709 +#: pl_exec.c:2711 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "FOR 루프의 하한은 null일 수 없음" -#: pl_exec.c:2725 +#: pl_exec.c:2727 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "FOR 루프의 상한은 null일 수 없음" -#: pl_exec.c:2743 +#: pl_exec.c:2745 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "FOR 루프의 BY 값은 null일 수 없음" -#: pl_exec.c:2749 +#: pl_exec.c:2751 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "FOR 루프의 BY 값은 0보다 커야 함" -#: pl_exec.c:2883 pl_exec.c:4688 +#: pl_exec.c:2885 pl_exec.c:4693 #, c-format msgid "cursor \"%s\" already in use" msgstr "\"%s\" 커서가 이미 사용 중임" -#: pl_exec.c:2906 pl_exec.c:4758 +#: pl_exec.c:2908 pl_exec.c:4763 #, c-format msgid "arguments given for cursor without arguments" msgstr "인수가 없는 커서에 인수가 제공됨" -#: pl_exec.c:2925 pl_exec.c:4777 +#: pl_exec.c:2927 pl_exec.c:4782 #, c-format msgid "arguments required for cursor" msgstr "커서에 인수 필요" -#: pl_exec.c:3016 +#: pl_exec.c:3018 #, c-format msgid "FOREACH expression must not be null" msgstr "FOREACH 구문은 null 이 아니여야 함" -#: pl_exec.c:3031 +#: pl_exec.c:3033 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "FOREACH 구문에서는 배열이 사용됩니다. 사용된 자료형 %s" -#: pl_exec.c:3048 +#: pl_exec.c:3050 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "slice dimension (%d) 값이 범위를 벗어남, 0..%d" -#: pl_exec.c:3075 +#: pl_exec.c:3077 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "FOREACH ... SLICE 루프 변수는 배열 자료형이어야 함" -#: pl_exec.c:3079 +#: pl_exec.c:3081 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "FOREACH 반복 변수는 배열형이 아니여야 함" -#: pl_exec.c:3241 pl_exec.c:3298 pl_exec.c:3473 +#: pl_exec.c:3243 pl_exec.c:3300 pl_exec.c:3475 #, c-format msgid "" "cannot return non-composite value from function returning composite type" msgstr "" "함수의 반환값이 복합 자료형인데, 복합 자료형아닌 자료형을 반환하려고 함" -#: pl_exec.c:3337 pl_gram.y:3295 +#: pl_exec.c:3339 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "SETOF 함수가 아닌 함수에서 RETURN NEXT를 사용할 수 없음" -#: pl_exec.c:3378 pl_exec.c:3510 +#: pl_exec.c:3380 pl_exec.c:3512 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "RETURN NEXT에 잘못된 결과 형식이 제공됨" -#: pl_exec.c:3416 pl_exec.c:3437 +#: pl_exec.c:3418 pl_exec.c:3439 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "RETURN NEXT에 잘못된 레코드 형식이 제공됨" -#: pl_exec.c:3529 +#: pl_exec.c:3531 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "RETURN NEXT에 매개 변수 필요" -#: pl_exec.c:3557 pl_gram.y:3359 +#: pl_exec.c:3559 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "SETOF 함수가 아닌 함수에서 RETURN QUERY를 사용할 수 없음" -#: pl_exec.c:3575 +#: pl_exec.c:3577 msgid "structure of query does not match function result type" msgstr "쿼리 구조가 함수 결과 형식과 일치하지 않음" -#: pl_exec.c:3630 pl_exec.c:4465 pl_exec.c:8724 +#: pl_exec.c:3632 pl_exec.c:4469 pl_exec.c:8759 #, c-format msgid "query string argument of EXECUTE is null" msgstr "EXECUTE의 쿼리 문자열 인수가 null임" -#: pl_exec.c:3715 pl_exec.c:3853 +#: pl_exec.c:3717 pl_exec.c:3855 #, c-format msgid "RAISE option already specified: %s" msgstr "RAISE 옵션이 이미 지정됨: %s" -#: pl_exec.c:3749 +#: pl_exec.c:3751 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "매개 변수 없는 RAISE를 예외 처리기 외부에 사용할 수 없음" -#: pl_exec.c:3843 +#: pl_exec.c:3845 #, c-format msgid "RAISE statement option cannot be null" msgstr "RAISE 문 옵션이 null일 수 없음" -#: pl_exec.c:3913 +#: pl_exec.c:3915 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3968 +#: pl_exec.c:3970 #, c-format msgid "assertion failed" msgstr "assertion 실패" -#: pl_exec.c:4338 pl_exec.c:4527 +#: pl_exec.c:4342 pl_exec.c:4532 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "PL/pgSQL의 클라이언트와 상호 복사할 수 없음" -#: pl_exec.c:4344 +#: pl_exec.c:4348 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "PL/pgSQL 안에서는 지원하지 않는 트랜잭션 명령" -#: pl_exec.c:4367 pl_exec.c:4556 +#: pl_exec.c:4371 pl_exec.c:4561 #, c-format msgid "INTO used with a command that cannot return data" msgstr "데이터를 반환할 수 없는 명령과 함께 INTO가 사용됨" -#: pl_exec.c:4390 pl_exec.c:4579 +#: pl_exec.c:4394 pl_exec.c:4584 #, c-format msgid "query returned no rows" msgstr "쿼리에서 행을 반환하지 않음" -#: pl_exec.c:4412 pl_exec.c:4598 pl_exec.c:5750 +#: pl_exec.c:4416 pl_exec.c:4603 pl_exec.c:5755 #, c-format msgid "query returned more than one row" msgstr "쿼리에서 두 개 이상의 행을 반환" -#: pl_exec.c:4414 +#: pl_exec.c:4418 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "하나의 로우만 반환하도록 쿼리를 바꾸거나 LIMIT 1 옵션을 추가하세요." -#: pl_exec.c:4430 +#: pl_exec.c:4434 #, c-format msgid "query has no destination for result data" msgstr "쿼리에 결과 데이터의 대상이 없음" -#: pl_exec.c:4431 +#: pl_exec.c:4435 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "SELECT의 결과를 취소하려면 대신 PERFORM을 사용하십시오." -#: pl_exec.c:4519 +#: pl_exec.c:4524 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" msgstr "SELECT의 EXECUTE... INTO가 구현되지 않음" -#: pl_exec.c:4520 +#: pl_exec.c:4525 #, c-format msgid "" "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS " "instead." msgstr "EXECUTE ... INTO 또는 EXECUTE CREATE TABLE ... AS 구문을 사용하세요." -#: pl_exec.c:4533 +#: pl_exec.c:4538 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "트랜잭션 명령들의 EXECUTE 기능은 구현되지 않았음" -#: pl_exec.c:4843 pl_exec.c:4931 +#: pl_exec.c:4848 pl_exec.c:4936 #, c-format msgid "cursor variable \"%s\" is null" msgstr "커서 변수 \"%s\"이(가) null임" -#: pl_exec.c:4854 pl_exec.c:4942 +#: pl_exec.c:4859 pl_exec.c:4947 #, c-format msgid "cursor \"%s\" does not exist" msgstr "\"%s\" 이름의 커서가 없음" -#: pl_exec.c:4867 +#: pl_exec.c:4872 #, c-format msgid "relative or absolute cursor position is null" msgstr "상대 또는 절대 커서 위치가 null임" -#: pl_exec.c:5105 pl_exec.c:5200 +#: pl_exec.c:5110 pl_exec.c:5205 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "NOT NULL이 선언된 \"%s\" 변수에 null 값을 할당할 수 없음" -#: pl_exec.c:5181 +#: pl_exec.c:5186 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "행 변수에 비복합 값을 할당할 수 없음" -#: pl_exec.c:5213 +#: pl_exec.c:5218 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "레코드 변수에 비복합 값을 할당할 수 없음" -#: pl_exec.c:5264 +#: pl_exec.c:5269 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "시스템 열 \"%s\"에 할당할 수 없습니다." -#: pl_exec.c:5713 +#: pl_exec.c:5718 #, c-format msgid "query did not return data" msgstr "쿼리 실행 결과 자료가 없음" -#: pl_exec.c:5714 pl_exec.c:5726 pl_exec.c:5751 pl_exec.c:5827 pl_exec.c:5832 +#: pl_exec.c:5719 pl_exec.c:5731 pl_exec.c:5756 pl_exec.c:5832 pl_exec.c:5837 #, c-format msgid "query: %s" msgstr "쿼리: %s" -#: pl_exec.c:5722 +#: pl_exec.c:5727 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" msgstr[0] "쿼리가 %d 개의 칼럼을 반환함" -#: pl_exec.c:5826 +#: pl_exec.c:5831 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "쿼리는 SELECT INTO 이지만, 일반 SELECT 구문이어야 함" -#: pl_exec.c:5831 +#: pl_exec.c:5836 #, c-format msgid "query is not a SELECT" msgstr "SELECT 쿼리가 아님" -#: pl_exec.c:6638 pl_exec.c:6678 pl_exec.c:6718 +#: pl_exec.c:6650 pl_exec.c:6690 pl_exec.c:6730 #, c-format msgid "" "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "" "%d번째 매개 변수의 자료형(%s)이 미리 준비된 실행계획의 자료형(%s)과 다릅니다" -#: pl_exec.c:7129 pl_exec.c:7163 pl_exec.c:7237 pl_exec.c:7263 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "원본과 대상 필드 수가 같지 않습니다." #. translator: %s represents a name of an extra check -#: pl_exec.c:7131 pl_exec.c:7165 pl_exec.c:7239 pl_exec.c:7265 +#: pl_exec.c:7143 pl_exec.c:7177 pl_exec.c:7251 pl_exec.c:7277 #, c-format msgid "%s check of %s is active." msgstr "%s 검사(해당 변수이름: %s)가 활성화 되어있습니다." -#: pl_exec.c:7135 pl_exec.c:7169 pl_exec.c:7243 pl_exec.c:7269 +#: pl_exec.c:7147 pl_exec.c:7181 pl_exec.c:7255 pl_exec.c:7281 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "쿼리 결과가 정확한 칼럼 목록을 반환하도록 수정하세요." -#: pl_exec.c:7656 +#: pl_exec.c:7668 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "\"%s\" 레코드가 아직 할당되지 않음" -#: pl_exec.c:7657 +#: pl_exec.c:7669 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "아직 할당되지 않은 레코드의 튜플 구조는 미정입니다." -#: pl_exec.c:8322 pl_gram.y:3418 +#: pl_exec.c:8357 pl_gram.y:3498 #, c-format msgid "variable \"%s\" is declared CONSTANT" msgstr "\"%s\" 변수는 CONSTANT로 선언됨" @@ -572,11 +587,6 @@ msgstr "%s 자료형은 collation 지원 안함" msgid "variable \"%s\" must have a default value, since it's declared NOT NULL" msgstr "\"%s\" 변수는 NOT NULL 설정이 있어 기본값을 가져야 합니다" -#: pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "\"%s\" 변수가 없음" - #: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "중복 선언" @@ -586,26 +596,26 @@ msgstr "중복 선언" msgid "variable \"%s\" shadows a previously defined variable" msgstr "variable \"%s\" shadows a previously defined variable" -#: pl_gram.y:1016 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "GET STACKED DIAGNOSTICS 에서 %s 항목을 사용할 수 없음" -#: pl_gram.y:1034 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "GET CURRENT DIAGNOSTICS 에서 %s 항목을 사용할 수 없음" -#: pl_gram.y:1132 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "알 수 없는 GET DIAGNOSTICS 항목" -#: pl_gram.y:1148 pl_gram.y:3534 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "\"%s\"은(는) 스칼라 변수가 아님" -#: pl_gram.y:1378 pl_gram.y:1572 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "" "loop variable of loop over rows must be a record variable or list of scalar " @@ -613,12 +623,12 @@ msgid "" msgstr "" "행에 있는 루프의 루프 변수는 레코드 변수이거나 스칼라 변수의 목록이어야 함" -#: pl_gram.y:1413 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "커서 FOR 루프에 대상 변수가 한 개만 있어야 함" -#: pl_gram.y:1420 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "커서 FOR 루프는 바인딩된 커서 변수를 한 개만 사용해야 함" @@ -660,14 +670,14 @@ msgstr "루프 외부에 라벨 지정 없이 EXIT 사용할 수 없음" msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE를 루프 외부에 사용할 수 없음" -#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:2981 pl_gram.y:3069 -#: pl_gram.y:3180 pl_gram.y:3933 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "예기치 않은 함수 정의의 끝" #: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 #: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 -#: pl_gram.y:2632 pl_gram.y:3776 pl_gram.y:3837 pl_gram.y:3914 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "구문 오류" @@ -699,138 +709,142 @@ msgstr "\"%s\" 변수는 커서 또는 ref 커서 형식이어야 함" msgid "\"%s\" is not a known variable" msgstr "\"%s\" (은)는 알려진 변수가 아님" -#: pl_gram.y:2720 pl_gram.y:2730 pl_gram.y:2886 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "괄호의 짝이 맞지 않음" -#: pl_gram.y:2734 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "SQL 식 끝에 \"%s\" 누락" -#: pl_gram.y:2740 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "SQL 문 끝에 \"%s\" 누락" -#: pl_gram.y:2757 +#: pl_gram.y:2758 msgid "missing expression" msgstr "표현식 빠졌음" -#: pl_gram.y:2759 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "SQL 문이 빠졌음" -#: pl_gram.y:2888 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "구문 오류, \"]\" 필요" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "불완전한 데이터 형식 선언" -#: pl_gram.y:2911 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "데이터 형식 선언 누락" -#: pl_gram.y:2991 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO가 여러 번 지정됨" -#: pl_gram.y:3161 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "FROM 또는 IN 필요" -#: pl_gram.y:3222 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "집합을 반환하는 함수에서 RETURN 구문에는 인자가 없음" -#: pl_gram.y:3223 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "RETURN NEXT 나 RETURN QUERY 구문을 사용하세요." -#: pl_gram.y:3233 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "프로시져에서는 RETURN 문의 매개 변수를 사용할 수 없음" -#: pl_gram.y:3238 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "RETURN은 void를 반환하는 함수에 매개 변수를 포함할 수 없음" -#: pl_gram.y:3247 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "RETURN은 OUT 매개 변수가 있는 함수에 매개 변수를 포함할 수 없음" -#: pl_gram.y:3310 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "RETURN NEXT는 OUT 매개 변수가 있는 함수에 매개 변수를 포함할 수 없음" -#: pl_gram.y:3476 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "다중 아이템 INTO 목록의 부분으로 record 변수가 사용될 수 없음" -#: pl_gram.y:3522 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "너무 많은 INTO 변수가 지정됨" -#: pl_gram.y:3730 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "레이블이 없는 블록에 끝 레이블 \"%s\"이(가) 지정됨" -#: pl_gram.y:3737 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "끝 레이블 \"%s\"이(가) 블록의 \"%s\" 레이블과 다름" -#: pl_gram.y:3771 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "\"%s\" 커서에 인수가 없음" -#: pl_gram.y:3785 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "\"%s\" 커서에 인수가 있음" -#: pl_gram.y:3827 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "\"%s\" 커서는 \"%s\" 이름의 인자가 없음" -#: pl_gram.y:3847 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "\"%s\" 이름의 인자가 \"%s\" 커서에서 중복됨" -#: pl_gram.y:3872 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "\"%s\" 커서를 위한 충분하지 않은 인자" -#: pl_gram.y:3879 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "\"%s\" 커서를 위한 인자가 너무 많음" -#: pl_gram.y:3965 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "인식할 수 없는 RAISE 문 옵션" -#: pl_gram.y:3969 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "구문 오류, \"=\" 필요" -#: pl_gram.y:4010 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "RAISE에 지정된 매개 변수가 너무 많음" -#: pl_gram.y:4014 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "RAISE에 지정된 매개 변수가 너무 적음" @@ -863,13 +877,13 @@ msgid "List of programming constructs that should produce an error." msgstr "오류로 처리할 프로그래밍 컨스트럭트 목록" #. translator: %s is typically the translation of "syntax error" -#: pl_scanner.c:508 +#: pl_scanner.c:525 #, c-format msgid "%s at end of input" msgstr "%s, 입력 끝부분" #. translator: first %s is typically the translation of "syntax error" -#: pl_scanner.c:524 +#: pl_scanner.c:541 #, c-format msgid "%s at or near \"%s\"" msgstr "%s, \"%s\" 부근" diff --git a/src/pl/plpgsql/src/po/meson.build b/src/pl/plpgsql/src/po/meson.build index e9ec37ebc8c4b..7808a20ba8436 100644 --- a/src/pl/plpgsql/src/po/meson.build +++ b/src/pl/plpgsql/src/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('plpgsql-' + pg_version_major.to_string())] diff --git a/src/pl/plpgsql/src/po/ru.po b/src/pl/plpgsql/src/po/ru.po index befc3125ba003..99ba5ac7e11d4 100644 --- a/src/pl/plpgsql/src/po/ru.po +++ b/src/pl/plpgsql/src/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for plpgsql # Copyright (C) 2012-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022. +# Alexander Lakhin , 2012-2017, 2018, 2019, 2020, 2021, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: plpgsql (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" -"PO-Revision-Date: 2022-09-05 13:38+0300\n" +"POT-Creation-Date: 2024-09-02 09:29+0300\n" +"PO-Revision-Date: 2024-09-04 20:00+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -78,43 +78,58 @@ msgstr "неоднозначная ссылка на столбец \"%s\"" msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "Подразумевается ссылка на переменную PL/pgSQL или столбец таблицы." -#: pl_comp.c:1314 pl_exec.c:5255 pl_exec.c:5428 pl_exec.c:5515 pl_exec.c:5606 -#: pl_exec.c:6624 +#: pl_comp.c:1314 pl_exec.c:5260 pl_exec.c:5433 pl_exec.c:5520 pl_exec.c:5611 +#: pl_exec.c:6636 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "в записи \"%s\" нет поля \"%s\"" -#: pl_comp.c:1808 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "переменная \"%s\" не существует" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "столбец \"%s\" в таблице \"%s\" не существует" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "отношение \"%s\" не существует" -#: pl_comp.c:1815 pl_comp.c:1857 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "отношение \"%s\" не имеет составного типа" -#: pl_comp.c:1923 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "переменная \"%s\" имеет псевдотип %s" -#: pl_comp.c:2112 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "тип \"%s\" является пустышкой" -#: pl_comp.c:2194 pl_exec.c:6925 +#: pl_comp.c:2157 pl_exec.c:6937 #, c-format msgid "type %s is not composite" msgstr "тип %s не является составным" -#: pl_comp.c:2242 pl_comp.c:2295 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "тип массива для типа данных %s не найден" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "нераспознанное условие исключения \"%s\"" -#: pl_comp.c:2524 +#: pl_comp.c:2514 #, c-format msgid "" "could not determine actual argument type for polymorphic function \"%s\"" @@ -122,57 +137,57 @@ msgstr "" "не удалось определить фактический тип аргумента для полиморфной функции " "\"%s\"" -#: pl_exec.c:511 pl_exec.c:950 pl_exec.c:1185 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "в процессе инициализации состояния выполнения" -#: pl_exec.c:517 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "при сохранении аргументов вызова в локальных переменных" -#: pl_exec.c:605 pl_exec.c:1023 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "при входе в функцию" -#: pl_exec.c:628 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "конец функции достигнут без RETURN" -#: pl_exec.c:634 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "при приведении возвращаемого значения к типу результата функции" -#: pl_exec.c:646 pl_exec.c:3681 +#: pl_exec.c:647 pl_exec.c:3683 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "" "функция, возвращающая множество, вызвана в контексте, где ему нет места" -#: pl_exec.c:651 pl_exec.c:3687 +#: pl_exec.c:652 pl_exec.c:3689 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "требуется режим материализации, но он недопустим в этом контексте" -#: pl_exec.c:778 pl_exec.c:1049 pl_exec.c:1207 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "при выходе из функции" -#: pl_exec.c:833 pl_exec.c:897 pl_exec.c:3480 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3482 msgid "returned record type does not match expected record type" msgstr "возвращаемый тип записи не соответствует ожидаемому" -#: pl_exec.c:1046 pl_exec.c:1204 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "конец триггерной процедуры достигнут без RETURN" -#: pl_exec.c:1054 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "триггерная процедура не может возвращать множество" -#: pl_exec.c:1093 pl_exec.c:1121 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "" "returned row structure does not match the structure of the triggering table" msgstr "" @@ -182,7 +197,7 @@ msgstr "" #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1262 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "функция PL/pgSQL %s, строка %d, %s" @@ -190,35 +205,35 @@ msgstr "функция PL/pgSQL %s, строка %d, %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1273 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "функция PL/pgSQL %s, %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1281 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "функция PL/pgSQL %s, строка %d, оператор %s" -#: pl_exec.c:1287 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "функция PL/pgSQL %s" -#: pl_exec.c:1658 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "при инициализации локальной переменной в блоке операторов" -#: pl_exec.c:1763 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "при входе в блок операторов" -#: pl_exec.c:1795 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "при выходе из блока операторов" -#: pl_exec.c:1833 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "при очистке после исключения" @@ -240,199 +255,199 @@ msgstr "" "параметр процедуры %d является выходным, но соответствующий аргумент не " "допускает запись" -#: pl_exec.c:2409 +#: pl_exec.c:2411 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "" "GET STACKED DIAGNOSTICS нельзя использовать вне блока обработчика исключения" -#: pl_exec.c:2615 +#: pl_exec.c:2617 #, c-format msgid "case not found" msgstr "неправильный CASE" -#: pl_exec.c:2616 +#: pl_exec.c:2618 #, c-format msgid "CASE statement is missing ELSE part." msgstr "В операторе CASE не хватает части ELSE." -#: pl_exec.c:2709 +#: pl_exec.c:2711 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "нижняя граница цикла FOR не может быть равна NULL" -#: pl_exec.c:2725 +#: pl_exec.c:2727 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "верхняя граница цикла FOR не может быть равна NULL" -#: pl_exec.c:2743 +#: pl_exec.c:2745 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "значение BY в цикле FOR не может быть равно NULL" -#: pl_exec.c:2749 +#: pl_exec.c:2751 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "значение BY в цикле FOR должно быть больше нуля" -#: pl_exec.c:2883 pl_exec.c:4688 +#: pl_exec.c:2885 pl_exec.c:4693 #, c-format msgid "cursor \"%s\" already in use" msgstr "курсор \"%s\" уже используется" -#: pl_exec.c:2906 pl_exec.c:4758 +#: pl_exec.c:2908 pl_exec.c:4763 #, c-format msgid "arguments given for cursor without arguments" msgstr "курсору без аргументов были переданы аргументы" -#: pl_exec.c:2925 pl_exec.c:4777 +#: pl_exec.c:2927 pl_exec.c:4782 #, c-format msgid "arguments required for cursor" msgstr "курсору требуются аргументы" -#: pl_exec.c:3016 +#: pl_exec.c:3018 #, c-format msgid "FOREACH expression must not be null" msgstr "выражение FOREACH не может быть равно NULL" -#: pl_exec.c:3031 +#: pl_exec.c:3033 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "выражение в FOREACH должно быть массивом, но не типом %s" -#: pl_exec.c:3048 +#: pl_exec.c:3050 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "размерность среза (%d) вне допустимого диапазона 0..%d" -#: pl_exec.c:3075 +#: pl_exec.c:3077 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "переменная цикла FOREACH ... SLICE должна быть массивом" -#: pl_exec.c:3079 +#: pl_exec.c:3081 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "переменная цикла FOREACH не должна быть массивом" -#: pl_exec.c:3241 pl_exec.c:3298 pl_exec.c:3473 +#: pl_exec.c:3243 pl_exec.c:3300 pl_exec.c:3475 #, c-format msgid "" "cannot return non-composite value from function returning composite type" msgstr "" "функция, возвращающая составной тип, не может вернуть несоставное значение" -#: pl_exec.c:3337 pl_gram.y:3350 +#: pl_exec.c:3339 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "" "RETURN NEXT можно использовать только в функциях, возвращающих множества" -#: pl_exec.c:3378 pl_exec.c:3510 +#: pl_exec.c:3380 pl_exec.c:3512 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "в RETURN NEXT передан неправильный тип результата" -#: pl_exec.c:3416 pl_exec.c:3437 +#: pl_exec.c:3418 pl_exec.c:3439 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "в RETURN NEXT передан неправильный тип записи" -#: pl_exec.c:3529 +#: pl_exec.c:3531 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "у оператора RETURN NEXT должен быть параметр" -#: pl_exec.c:3557 pl_gram.y:3414 +#: pl_exec.c:3559 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "" "RETURN QUERY можно использовать только в функциях, возвращающих множества" -#: pl_exec.c:3575 +#: pl_exec.c:3577 msgid "structure of query does not match function result type" msgstr "структура запроса не соответствует типу результата функции" -#: pl_exec.c:3630 pl_exec.c:4465 pl_exec.c:8724 +#: pl_exec.c:3632 pl_exec.c:4469 pl_exec.c:8759 #, c-format msgid "query string argument of EXECUTE is null" msgstr "в качестве текста запроса в EXECUTE передан NULL" -#: pl_exec.c:3715 pl_exec.c:3853 +#: pl_exec.c:3717 pl_exec.c:3855 #, c-format msgid "RAISE option already specified: %s" msgstr "этот параметр RAISE уже указан: %s" -#: pl_exec.c:3749 +#: pl_exec.c:3751 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "" "RAISE без параметров нельзя использовать вне блока обработчика исключения" -#: pl_exec.c:3843 +#: pl_exec.c:3845 #, c-format msgid "RAISE statement option cannot be null" msgstr "параметром оператора RAISE не может быть NULL" -#: pl_exec.c:3913 +#: pl_exec.c:3915 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3968 +#: pl_exec.c:3970 #, c-format msgid "assertion failed" msgstr "нарушение истинности" -#: pl_exec.c:4338 pl_exec.c:4527 +#: pl_exec.c:4342 pl_exec.c:4532 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "в PL/pgSQL нельзя выполнить COPY с участием клиента" -#: pl_exec.c:4344 +#: pl_exec.c:4348 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "неподдерживаемая транзакционная команда в PL/pgSQL" -#: pl_exec.c:4367 pl_exec.c:4556 +#: pl_exec.c:4371 pl_exec.c:4561 #, c-format msgid "INTO used with a command that cannot return data" msgstr "INTO с командой не может возвращать данные" -#: pl_exec.c:4390 pl_exec.c:4579 +#: pl_exec.c:4394 pl_exec.c:4584 #, c-format msgid "query returned no rows" msgstr "запрос не вернул строк" -#: pl_exec.c:4412 pl_exec.c:4598 pl_exec.c:5750 +#: pl_exec.c:4416 pl_exec.c:4603 pl_exec.c:5755 #, c-format msgid "query returned more than one row" msgstr "запрос вернул несколько строк" -#: pl_exec.c:4414 +#: pl_exec.c:4418 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "" "Измените запрос, чтобы он выбирал одну строку, или используйте LIMIT 1." -#: pl_exec.c:4430 +#: pl_exec.c:4434 #, c-format msgid "query has no destination for result data" msgstr "в запросе нет назначения для данных результата" -#: pl_exec.c:4431 +#: pl_exec.c:4435 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "Если вам нужно отбросить результаты SELECT, используйте PERFORM." -#: pl_exec.c:4519 +#: pl_exec.c:4524 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" msgstr "возможность выполнения SELECT ... INTO в EXECUTE не реализована" # skip-rule: space-before-ellipsis -#: pl_exec.c:4520 +#: pl_exec.c:4525 #, c-format msgid "" "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS " @@ -441,57 +456,57 @@ msgstr "" "Альтернативой может стать EXECUTE ... INTO или EXECUTE CREATE TABLE ... " "AS ..." -#: pl_exec.c:4533 +#: pl_exec.c:4538 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "EXECUTE с транзакционными командами не поддерживается" -#: pl_exec.c:4843 pl_exec.c:4931 +#: pl_exec.c:4848 pl_exec.c:4936 #, c-format msgid "cursor variable \"%s\" is null" msgstr "переменная курсора \"%s\" равна NULL" -#: pl_exec.c:4854 pl_exec.c:4942 +#: pl_exec.c:4859 pl_exec.c:4947 #, c-format msgid "cursor \"%s\" does not exist" msgstr "курсор \"%s\" не существует" -#: pl_exec.c:4867 +#: pl_exec.c:4872 #, c-format msgid "relative or absolute cursor position is null" msgstr "относительная или абсолютная позиция курсора равна NULL" -#: pl_exec.c:5105 pl_exec.c:5200 +#: pl_exec.c:5110 pl_exec.c:5205 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "значение NULL нельзя присвоить переменной \"%s\", объявленной NOT NULL" -#: pl_exec.c:5181 +#: pl_exec.c:5186 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "переменной типа кортеж можно присвоить только составное значение" -#: pl_exec.c:5213 +#: pl_exec.c:5218 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "переменной типа запись можно присвоить только составное значение" -#: pl_exec.c:5264 +#: pl_exec.c:5269 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "присвоить значение системному столбцу \"%s\" нельзя" -#: pl_exec.c:5713 +#: pl_exec.c:5718 #, c-format msgid "query did not return data" msgstr "запрос не вернул данные" -#: pl_exec.c:5714 pl_exec.c:5726 pl_exec.c:5751 pl_exec.c:5827 pl_exec.c:5832 +#: pl_exec.c:5719 pl_exec.c:5731 pl_exec.c:5756 pl_exec.c:5832 pl_exec.c:5837 #, c-format msgid "query: %s" msgstr "запрос: %s" -#: pl_exec.c:5722 +#: pl_exec.c:5727 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" @@ -499,17 +514,17 @@ msgstr[0] "запрос вернул %d столбец" msgstr[1] "запрос вернул %d столбца" msgstr[2] "запрос вернул %d столбцов" -#: pl_exec.c:5826 +#: pl_exec.c:5831 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "запрос - не просто SELECT, а SELECT INTO" -#: pl_exec.c:5831 +#: pl_exec.c:5836 #, c-format msgid "query is not a SELECT" msgstr "запрос - не SELECT" -#: pl_exec.c:6638 pl_exec.c:6678 pl_exec.c:6718 +#: pl_exec.c:6650 pl_exec.c:6690 pl_exec.c:6730 #, c-format msgid "" "type of parameter %d (%s) does not match that when preparing the plan (%s)" @@ -517,35 +532,35 @@ msgstr "" "тип параметра %d (%s) не соответствует тому, с которым подготавливался план " "(%s)" -#: pl_exec.c:7129 pl_exec.c:7163 pl_exec.c:7237 pl_exec.c:7263 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "в левой и правой части присваивания разное количество полей" #. translator: %s represents a name of an extra check -#: pl_exec.c:7131 pl_exec.c:7165 pl_exec.c:7239 pl_exec.c:7265 +#: pl_exec.c:7143 pl_exec.c:7177 pl_exec.c:7251 pl_exec.c:7277 #, c-format msgid "%s check of %s is active." msgstr "Включена проверка %s (с %s)." -#: pl_exec.c:7135 pl_exec.c:7169 pl_exec.c:7243 pl_exec.c:7269 +#: pl_exec.c:7147 pl_exec.c:7181 pl_exec.c:7255 pl_exec.c:7281 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "" "Измените запрос, чтобы он возвращал в точности требуемый список столбцов." -#: pl_exec.c:7656 +#: pl_exec.c:7668 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "записи \"%s\" не присвоено значение" -#: pl_exec.c:7657 +#: pl_exec.c:7669 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "" "Для записи, которой не присвоено значение, структура кортежа не определена." -#: pl_exec.c:8322 pl_gram.y:3473 +#: pl_exec.c:8357 pl_gram.y:3498 #, c-format msgid "variable \"%s\" is declared CONSTANT" msgstr "переменная \"%s\" объявлена как CONSTANT" @@ -599,11 +614,6 @@ msgstr "" "у переменной \"%s\" должно быть значение по умолчанию, так как она объявлена " "как NOT NULL" -#: pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "переменная \"%s\" не существует" - #: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "повторяющееся объявление" @@ -613,26 +623,26 @@ msgstr "повторяющееся объявление" msgid "variable \"%s\" shadows a previously defined variable" msgstr "переменная \"%s\" скрывает ранее определённую переменную" -#: pl_gram.y:1016 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "команда GET STACKED DIAGNOSTICS не принимает элемент %s" -#: pl_gram.y:1034 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "команда GET CURRENT DIAGNOSTICS не принимает элемент %s" -#: pl_gram.y:1132 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "нераспознанный элемент GET DIAGNOSTICS" -#: pl_gram.y:1148 pl_gram.y:3589 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "\"%s\" - не скалярная переменная" -#: pl_gram.y:1378 pl_gram.y:1571 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "" "loop variable of loop over rows must be a record variable or list of scalar " @@ -641,229 +651,233 @@ msgstr "" "переменная цикла по кортежам должна быть переменной типа запись или списком " "скалярных переменных" -#: pl_gram.y:1413 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "в цикле FOR с курсором должна быть только одна переменная" -#: pl_gram.y:1420 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "" "в цикле FOR с курсором должен использоваться курсор, привязанный к запросу" -#: pl_gram.y:1510 +#: pl_gram.y:1511 #, c-format msgid "integer FOR loop must have only one target variable" msgstr "в целочисленном цикле FOR должна быть только одна переменная" -#: pl_gram.y:1544 +#: pl_gram.y:1545 #, c-format msgid "cannot specify REVERSE in query FOR loop" msgstr "в цикле FOR с запросом нельзя указать REVERSE" -#: pl_gram.y:1674 +#: pl_gram.y:1675 #, c-format msgid "loop variable of FOREACH must be a known variable or list of variables" msgstr "" "переменной цикла FOREACH должна быть известная переменная или список " "переменных" -#: pl_gram.y:1716 +#: pl_gram.y:1717 #, c-format msgid "" "there is no label \"%s\" attached to any block or loop enclosing this " "statement" msgstr "в блоке или цикле, окружающем этот оператор, нет метки \"%s\"" -#: pl_gram.y:1724 +#: pl_gram.y:1725 #, c-format msgid "block label \"%s\" cannot be used in CONTINUE" msgstr "метку блока \"%s\" нельзя использовать в CONTINUE" -#: pl_gram.y:1739 +#: pl_gram.y:1740 #, c-format msgid "EXIT cannot be used outside a loop, unless it has a label" msgstr "EXIT можно использовать вне цикла только с указанием метки" -#: pl_gram.y:1740 +#: pl_gram.y:1741 #, c-format msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE нельзя использовать вне цикла" -#: pl_gram.y:1764 pl_gram.y:1802 pl_gram.y:1850 pl_gram.y:3036 pl_gram.y:3124 -#: pl_gram.y:3235 pl_gram.y:3984 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "неожиданный конец определения функции" -#: pl_gram.y:1870 pl_gram.y:1894 pl_gram.y:1910 pl_gram.y:1916 pl_gram.y:2041 -#: pl_gram.y:2049 pl_gram.y:2063 pl_gram.y:2158 pl_gram.y:2382 pl_gram.y:2472 -#: pl_gram.y:2631 pl_gram.y:3831 pl_gram.y:3892 pl_gram.y:3965 +#: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 +#: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "ошибка синтаксиса" -#: pl_gram.y:1898 pl_gram.y:1900 pl_gram.y:2386 pl_gram.y:2388 +#: pl_gram.y:1899 pl_gram.y:1901 pl_gram.y:2387 pl_gram.y:2389 msgid "invalid SQLSTATE code" msgstr "неверный код SQLSTATE" -#: pl_gram.y:2106 +#: pl_gram.y:2107 msgid "syntax error, expected \"FOR\"" msgstr "ошибка синтаксиса, ожидался \"FOR\"" -#: pl_gram.y:2167 +#: pl_gram.y:2168 #, c-format msgid "FETCH statement cannot return multiple rows" msgstr "оператор FETCH не может вернуть несколько строк" -#: pl_gram.y:2264 +#: pl_gram.y:2265 #, c-format msgid "cursor variable must be a simple variable" msgstr "переменная-курсор должна быть простой переменной" -#: pl_gram.y:2270 +#: pl_gram.y:2271 #, c-format msgid "variable \"%s\" must be of type cursor or refcursor" msgstr "переменная \"%s\" должна быть типа cursor или refcursor" -#: pl_gram.y:2602 pl_gram.y:2613 +#: pl_gram.y:2603 pl_gram.y:2614 #, c-format msgid "\"%s\" is not a known variable" msgstr "\"%s\" - не известная переменная" -#: pl_gram.y:2718 pl_gram.y:2728 pl_gram.y:2886 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "непарные скобки" -#: pl_gram.y:2732 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "отсутствует \"%s\" в конце выражения SQL" -#: pl_gram.y:2738 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "отсутствует \"%s\" в конце оператора SQL" -#: pl_gram.y:2757 +#: pl_gram.y:2758 msgid "missing expression" msgstr "отсутствует выражение" -#: pl_gram.y:2759 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "отсутствует оператор SQL" -#: pl_gram.y:2888 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "ошибка синтаксиса, ожидалась \"]\"" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "неполное определение типа данных" -#: pl_gram.y:2911 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "отсутствует определение типа данных" -#: pl_gram.y:3046 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO указано неоднократно" -#: pl_gram.y:3216 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "ожидалось FROM или IN" -#: pl_gram.y:3277 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "в функции, возвращающей множество, RETURN должен быть без параметров" -#: pl_gram.y:3278 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "Используйте RETURN NEXT или RETURN QUERY." -#: pl_gram.y:3288 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "в процедуре RETURN должен быть без параметров" -#: pl_gram.y:3293 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "в функции, не возвращающей ничего, RETURN не должен иметь параметров" -#: pl_gram.y:3302 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "RETURN должен быть без параметров в функции с параметрами OUT" -#: pl_gram.y:3365 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "RETURN NEXT должен быть без параметров в функции с параметрами OUT" -#: pl_gram.y:3531 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "" "переменная типа запись не может быть частью списка INTO с несколькими " "элементами" -#: pl_gram.y:3577 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "указано слишком много переменных INTO" -#: pl_gram.y:3785 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "конечная метка \"%s\" указана для непомеченного блока" -#: pl_gram.y:3792 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "конечная метка \"%s\" отличается от метки блока \"%s\"" -#: pl_gram.y:3826 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "курсор \"%s\" не имеет аргументов" -#: pl_gram.y:3840 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "курсор \"%s\" имеет аргументы" -#: pl_gram.y:3882 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "курсор \"%s\" не имеет аргумента \"%s\"" -#: pl_gram.y:3902 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "значение параметра \"%s\" курсора \"%s\" указано неоднократно" -#: pl_gram.y:3923 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "недостаточно аргументов для курсора \"%s\"" -#: pl_gram.y:3930 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "слишком много аргументов для курсора \"%s\"" -#: pl_gram.y:4016 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "нераспознанный параметр оператора RAISE" -#: pl_gram.y:4020 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "ошибка синтаксиса, ожидалось \"=\"" -#: pl_gram.y:4061 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "слишком много параметров для RAISE" -#: pl_gram.y:4065 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "недостаточно параметров для RAISE" diff --git a/src/pl/plpgsql/src/po/sv.po b/src/pl/plpgsql/src/po/sv.po index 4ba613826a826..9f78dd5633e80 100644 --- a/src/pl/plpgsql/src/po/sv.po +++ b/src/pl/plpgsql/src/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for plpgsql # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 13:39+0000\n" -"PO-Revision-Date: 2023-03-09 22:40+0100\n" +"POT-Creation-Date: 2024-07-12 17:39+0000\n" +"PO-Revision-Date: 2024-07-12 22:07+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,159 +17,174 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: pl_comp.c:438 pl_handler.c:496 +#: pl_comp.c:434 pl_handler.c:496 #, c-format msgid "PL/pgSQL functions cannot accept type %s" msgstr "PL/pgSQL-funktioner kan inte acceptera typ %s" -#: pl_comp.c:530 +#: pl_comp.c:526 #, c-format msgid "could not determine actual return type for polymorphic function \"%s\"" msgstr "kunde inte bestämma aktuell returtyp för polymorfisk funktion \"%s\"" -#: pl_comp.c:560 +#: pl_comp.c:556 #, c-format msgid "trigger functions can only be called as triggers" msgstr "triggerfunktioner kan bara anropas som triggrar" -#: pl_comp.c:564 pl_handler.c:480 +#: pl_comp.c:560 pl_handler.c:480 #, c-format msgid "PL/pgSQL functions cannot return type %s" msgstr "PL/pgSQL-funktioner kan inte returnera typ %s" -#: pl_comp.c:604 +#: pl_comp.c:600 #, c-format msgid "trigger functions cannot have declared arguments" msgstr "triggerfunktioner kan inte ha deklarerade argument" -#: pl_comp.c:605 +#: pl_comp.c:601 #, c-format msgid "The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead." msgstr "Argumenten till triggern kan accessas via TG_NARGS och TG_ARGV istället." -#: pl_comp.c:738 +#: pl_comp.c:734 #, c-format msgid "event trigger functions cannot have declared arguments" msgstr "händelsetriggerfunktioner kan inte ha deklarerade argument" -#: pl_comp.c:1002 +#: pl_comp.c:998 #, c-format msgid "compilation of PL/pgSQL function \"%s\" near line %d" msgstr "kompilering av PL/pgSQL-funktion \"%s\" nära rad %d" -#: pl_comp.c:1025 +#: pl_comp.c:1021 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "parameternamn \"%s\" angivet mer än en gång" -#: pl_comp.c:1139 +#: pl_comp.c:1135 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "kolumnreferens \"%s\" är tvetydig" -#: pl_comp.c:1141 +#: pl_comp.c:1137 #, c-format msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "Det kan referera till antingen en PL/pgSQL-variabel eller en tabellkolumn." -#: pl_comp.c:1324 pl_exec.c:5216 pl_exec.c:5389 pl_exec.c:5476 pl_exec.c:5567 -#: pl_exec.c:6588 +#: pl_comp.c:1314 pl_exec.c:5258 pl_exec.c:5431 pl_exec.c:5518 pl_exec.c:5609 +#: pl_exec.c:6634 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "post \"%s\" saknar fält \"%s\"" -#: pl_comp.c:1818 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "variabel \"%s\" finns inte" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "kolumn \"%s\" i relation \"%s\" existerar inte" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "relationen \"%s\" existerar inte" -#: pl_comp.c:1825 pl_comp.c:1867 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "relationen \"%s\" har inte en composite-typ" -#: pl_comp.c:1933 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "variabel \"%s\" har pseudotyp %s" -#: pl_comp.c:2122 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "typ \"%s\" är bara ett skal" -#: pl_comp.c:2204 pl_exec.c:6889 +#: pl_comp.c:2157 pl_exec.c:6935 #, c-format msgid "type %s is not composite" msgstr "typen %s är inte composite" -#: pl_comp.c:2252 pl_comp.c:2305 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "kunde inte hitta array-typ för datatyp %s" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "okänt avbrottsvillkor \"%s\"" -#: pl_comp.c:2526 +#: pl_comp.c:2514 #, c-format msgid "could not determine actual argument type for polymorphic function \"%s\"" msgstr "kunde inte bestämma argumenttyp för polymorfisk funktion function \"%s\"" -#: pl_exec.c:500 pl_exec.c:939 pl_exec.c:1174 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "unde initiering av körtillstånd" -#: pl_exec.c:506 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "under sparande av anropsargument till lokala variabler" -#: pl_exec.c:594 pl_exec.c:1012 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "under funktionsingången" -#: pl_exec.c:617 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "kontrollen nådde slutet av funktionen utan RETURN" -#: pl_exec.c:623 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "under typomvandling av returvärde till funktionens returtyp" -#: pl_exec.c:635 pl_exec.c:3656 +#: pl_exec.c:647 pl_exec.c:3682 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "en funktion som returnerar en mängd anropades i kontext som inte godtar en mängd" -#: pl_exec.c:640 pl_exec.c:3662 +#: pl_exec.c:652 pl_exec.c:3688 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialiserat läge krävs, men stöds inte i detta kontext" -#: pl_exec.c:767 pl_exec.c:1038 pl_exec.c:1196 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "under funktionsavslutning" -#: pl_exec.c:822 pl_exec.c:886 pl_exec.c:3455 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3481 msgid "returned record type does not match expected record type" msgstr "returnerad posttyp matchar inte förväntad posttyp" -#: pl_exec.c:1035 pl_exec.c:1193 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "programflödet nådde slutet på triggerprocedur utan RETURN" -#: pl_exec.c:1043 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "triggerprocedur kan inte returnera en mängd" -#: pl_exec.c:1082 pl_exec.c:1110 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "returned row structure does not match the structure of the triggering table" msgstr "returnerad radstruktur matchar inte strukturen på triggad tabell" #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1251 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "PL/pgSQL-funktion %s rad %d %s" @@ -177,335 +192,340 @@ msgstr "PL/pgSQL-funktion %s rad %d %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1262 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "PL/pgSQL-funktion %s %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1270 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "PL/pgSQL-funktion %s rad %d vid %s" -#: pl_exec.c:1276 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "PL/pgSQL-funktion %s" -#: pl_exec.c:1647 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "under initiering av lokala variabler i satsblock" -#: pl_exec.c:1752 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "under ingång till satsblock" -#: pl_exec.c:1784 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "under satsblockavslutning" -#: pl_exec.c:1822 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "under avbrottsuppstädning" -#: pl_exec.c:2355 +#: pl_exec.c:2371 #, c-format msgid "procedure parameter \"%s\" is an output parameter but corresponding argument is not writable" msgstr "procedurparameter \"%s\" är en utdataparameter men motsvarande argument är inte skrivbar" -#: pl_exec.c:2360 +#: pl_exec.c:2376 #, c-format msgid "procedure parameter %d is an output parameter but corresponding argument is not writable" msgstr "procedurparameter %d är en utdataparameter men motsvarande argument är inte skrivbar" -#: pl_exec.c:2394 +#: pl_exec.c:2410 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "GET STACKED DIAGNOSTICS kan inte användas utanför en avbrottshanterare" -#: pl_exec.c:2594 +#: pl_exec.c:2616 #, c-format msgid "case not found" msgstr "hittade inte alternativ" -#: pl_exec.c:2595 +#: pl_exec.c:2617 #, c-format msgid "CASE statement is missing ELSE part." msgstr "CASE-sats saknar ELSE-del." -#: pl_exec.c:2688 +#: pl_exec.c:2710 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "lägre gräns i FOR-loop kan inte vara null" -#: pl_exec.c:2704 +#: pl_exec.c:2726 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "övre gräns i FOR-loop kan inte vara null" -#: pl_exec.c:2722 +#: pl_exec.c:2744 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "BY-värde i FOR-loop kan inte vara null" -#: pl_exec.c:2728 +#: pl_exec.c:2750 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "BY-värde i FOR-loop måste vara större än noll" -#: pl_exec.c:2862 pl_exec.c:4658 +#: pl_exec.c:2884 pl_exec.c:4691 #, c-format msgid "cursor \"%s\" already in use" msgstr "markören \"%s\" används redan" -#: pl_exec.c:2885 pl_exec.c:4723 +#: pl_exec.c:2907 pl_exec.c:4761 #, c-format msgid "arguments given for cursor without arguments" msgstr "argument angivna till markör utan argumnet" -#: pl_exec.c:2904 pl_exec.c:4742 +#: pl_exec.c:2926 pl_exec.c:4780 #, c-format msgid "arguments required for cursor" msgstr "argument krävs för markör" -#: pl_exec.c:2991 +#: pl_exec.c:3017 #, c-format msgid "FOREACH expression must not be null" msgstr "FOREACH-uttryck får inte vara null" -#: pl_exec.c:3006 +#: pl_exec.c:3032 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "FOREACH-uttryck måste ge en array, inte typ %s" -#: pl_exec.c:3023 +#: pl_exec.c:3049 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "slice-storlek (%d) är utanför giltigt intervall 0..%d" -#: pl_exec.c:3050 +#: pl_exec.c:3076 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "FOREACH ... SLICE-loop-variabel måste ha typen array" -#: pl_exec.c:3054 +#: pl_exec.c:3080 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "FOREACH-loop-variable får inte ha typen array" -#: pl_exec.c:3216 pl_exec.c:3273 pl_exec.c:3448 +#: pl_exec.c:3242 pl_exec.c:3299 pl_exec.c:3474 #, c-format msgid "cannot return non-composite value from function returning composite type" msgstr "kan inte returnera icke-composit-värde från funktion med returtyp composit" -#: pl_exec.c:3312 pl_gram.y:3318 +#: pl_exec.c:3338 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "kan inte använda RETURN NEXT i en icke-SETOF-funktion" -#: pl_exec.c:3353 pl_exec.c:3485 +#: pl_exec.c:3379 pl_exec.c:3511 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "fel resultattyp given i RETURN NEXT" -#: pl_exec.c:3391 pl_exec.c:3412 +#: pl_exec.c:3417 pl_exec.c:3438 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "fel posttyp given i RETURN NEXT" -#: pl_exec.c:3504 +#: pl_exec.c:3530 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "RETURN NEXT måste ha en parameter" -#: pl_exec.c:3532 pl_gram.y:3382 +#: pl_exec.c:3558 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "kan inte använda RETURN QUERY i en icke-SETOF-funktion" -#: pl_exec.c:3550 +#: pl_exec.c:3576 msgid "structure of query does not match function result type" msgstr "strukturen på frågan matchar inte funktionens resultattyp" -#: pl_exec.c:3605 pl_exec.c:4435 pl_exec.c:8630 +#: pl_exec.c:3631 pl_exec.c:4467 pl_exec.c:8757 #, c-format msgid "query string argument of EXECUTE is null" msgstr "frågesträngargumentet till EXECUTE är null" -#: pl_exec.c:3690 pl_exec.c:3828 +#: pl_exec.c:3716 pl_exec.c:3854 #, c-format msgid "RAISE option already specified: %s" msgstr "RAISE-flagga redan angiven: %s" -#: pl_exec.c:3724 +#: pl_exec.c:3750 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "RAISE utan parametrar kan inte användas utanför en avbrottshanterare" -#: pl_exec.c:3818 +#: pl_exec.c:3844 #, c-format msgid "RAISE statement option cannot be null" msgstr "RAISE-satsens flagga får inte vare null" -#: pl_exec.c:3888 +#: pl_exec.c:3914 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3943 +#: pl_exec.c:3969 #, c-format msgid "assertion failed" msgstr "assert misslyckades" -#: pl_exec.c:4308 pl_exec.c:4497 +#: pl_exec.c:4340 pl_exec.c:4530 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "kan inte COPY till/från klient i PL/pgSQL" -#: pl_exec.c:4314 +#: pl_exec.c:4346 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "transaktionskommando saknar stöd i PL/pgSQL" -#: pl_exec.c:4337 pl_exec.c:4526 +#: pl_exec.c:4369 pl_exec.c:4559 #, c-format msgid "INTO used with a command that cannot return data" msgstr "INTO använd med ett kommando som inte returnerar data" -#: pl_exec.c:4360 pl_exec.c:4549 +#: pl_exec.c:4392 pl_exec.c:4582 #, c-format msgid "query returned no rows" msgstr "frågan returnerade inga rader" -#: pl_exec.c:4382 pl_exec.c:4568 pl_exec.c:5711 +#: pl_exec.c:4414 pl_exec.c:4601 pl_exec.c:5753 #, c-format msgid "query returned more than one row" msgstr "frågan returnerade mer än en rad" -#: pl_exec.c:4384 +#: pl_exec.c:4416 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "Se till att frågan returerar exakt en rad eller använd LIMIT 1." -#: pl_exec.c:4400 +#: pl_exec.c:4432 #, c-format msgid "query has no destination for result data" msgstr "frågan har ingen destination för resultatdatan" -#: pl_exec.c:4401 +#: pl_exec.c:4433 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "Om du vill slänga resultatet av en SELECT, använd PERFORM istället." -#: pl_exec.c:4489 +#: pl_exec.c:4522 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" msgstr "EXECUTE för SELECT ... INTO är inte implementerad" -#: pl_exec.c:4490 +#: pl_exec.c:4523 #, c-format msgid "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead." msgstr "Du vill nog använda EXECUTE ... INTO eller EXECUTE CREATE TABLE ... AS istället." -#: pl_exec.c:4503 +#: pl_exec.c:4536 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "EXECUTE på transaktionskommanon är inte implementerat" -#: pl_exec.c:4804 pl_exec.c:4892 +#: pl_exec.c:4846 pl_exec.c:4934 #, c-format msgid "cursor variable \"%s\" is null" msgstr "markörvariabel \"%s\" är null" -#: pl_exec.c:4815 pl_exec.c:4903 +#: pl_exec.c:4857 pl_exec.c:4945 #, c-format msgid "cursor \"%s\" does not exist" msgstr "markör \"%s\" existerar inte" -#: pl_exec.c:4828 +#: pl_exec.c:4870 #, c-format msgid "relative or absolute cursor position is null" msgstr "relativ eller absolut markörposition är null" -#: pl_exec.c:5066 pl_exec.c:5161 +#: pl_exec.c:5108 pl_exec.c:5203 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "null-value kan inte tilldelas till variabel \"%s\" som deklarerats NOT NULL" -#: pl_exec.c:5142 +#: pl_exec.c:5184 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "kan inte tilldela icke-composite-värde till radvariabel" -#: pl_exec.c:5174 +#: pl_exec.c:5216 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "kan inte tilldela icke-composite-värde till en post-variabel" -#: pl_exec.c:5225 +#: pl_exec.c:5267 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "kan inte skriva till systemkolumn \"%s\"" -#: pl_exec.c:5674 +#: pl_exec.c:5716 #, c-format msgid "query did not return data" msgstr "frågan returnerade ingen data" -#: pl_exec.c:5675 pl_exec.c:5687 pl_exec.c:5712 pl_exec.c:5788 pl_exec.c:5793 +#: pl_exec.c:5717 pl_exec.c:5729 pl_exec.c:5754 pl_exec.c:5830 pl_exec.c:5835 #, c-format msgid "query: %s" msgstr "fråga: %s" -#: pl_exec.c:5683 +#: pl_exec.c:5725 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" msgstr[0] "frågan returnerade %d kolumn" msgstr[1] "frågan returnerade %d kolumner" -#: pl_exec.c:5787 +#: pl_exec.c:5829 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "frågan är SELECT INTO men skall vara en vanlig SELECT" -#: pl_exec.c:5792 +#: pl_exec.c:5834 #, c-format msgid "query is not a SELECT" msgstr "frågan är inte en SELECT" -#: pl_exec.c:6602 pl_exec.c:6642 pl_exec.c:6682 +#: pl_exec.c:6648 pl_exec.c:6688 pl_exec.c:6728 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "typen av parameter %d (%s) matchar inte det som var vid preparerande av plan (%s)" -#: pl_exec.c:7093 pl_exec.c:7127 pl_exec.c:7201 pl_exec.c:7227 +#: pl_exec.c:7139 pl_exec.c:7173 pl_exec.c:7247 pl_exec.c:7273 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "antal käll- och mål-fält i tilldelningen matchar inte" #. translator: %s represents a name of an extra check -#: pl_exec.c:7095 pl_exec.c:7129 pl_exec.c:7203 pl_exec.c:7229 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "%s check of %s is active." msgstr "%s kontroll av %s är aktiv." -#: pl_exec.c:7099 pl_exec.c:7133 pl_exec.c:7207 pl_exec.c:7233 +#: pl_exec.c:7145 pl_exec.c:7179 pl_exec.c:7253 pl_exec.c:7279 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "Se till att frågan returerar exakt rätt lista med kolumner." -#: pl_exec.c:7620 +#: pl_exec.c:7666 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "posten \"%s\" är inte tilldelad än" -#: pl_exec.c:7621 +#: pl_exec.c:7667 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "Tuple-strukturen av en ej-ännu-tilldelad post är obestämd." +#: pl_exec.c:8355 pl_gram.y:3498 +#, c-format +msgid "variable \"%s\" is declared CONSTANT" +msgstr "variabel \"%s\" är deklarerad CONSTANT" + #: pl_funcs.c:237 msgid "statement block" msgstr "satsblock" @@ -538,280 +558,274 @@ msgstr "SQL-sats" msgid "FOR over EXECUTE statement" msgstr "FOR över EXECUTE-sats" -#: pl_gram.y:486 +#: pl_gram.y:485 #, c-format msgid "block label must be placed before DECLARE, not after" msgstr "blocketikett måste anges före DECLARE, inte efter" -#: pl_gram.y:506 +#: pl_gram.y:505 #, c-format msgid "collations are not supported by type %s" msgstr "jämförelser stöds inte för typ %s" -#: pl_gram.y:525 +#: pl_gram.y:524 #, c-format msgid "variable \"%s\" must have a default value, since it's declared NOT NULL" msgstr "variabel \"%s\" måste ha ett default-värde då det inte deklarerats som NOT NULL" -#: pl_gram.y:673 pl_gram.y:688 pl_gram.y:714 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "variabel \"%s\" finns inte" - -#: pl_gram.y:732 pl_gram.y:760 +#: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "duplicerad deklaration" -#: pl_gram.y:743 pl_gram.y:771 +#: pl_gram.y:715 pl_gram.y:743 #, c-format msgid "variable \"%s\" shadows a previously defined variable" msgstr "variabeln \"%s\" döljer en tidigare definierad variabel" -#: pl_gram.y:1043 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "diagnostikdel %s tillåts inte i GET STACKED DIAGNOSTICS" -#: pl_gram.y:1061 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "diagnostikdel %s tillåts inte i GET CURRENT DIAGNOSTICS" -#: pl_gram.y:1156 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "okänd GET DIAGNOSTICS-del" -#: pl_gram.y:1172 pl_gram.y:3557 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "\"%s\" är inte ett skalärt värde" -#: pl_gram.y:1402 pl_gram.y:1596 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "loop variable of loop over rows must be a record variable or list of scalar variables" msgstr "loop-variabeln för loop över rader måste vara en postvariabel eller en lista av skalärvariabler" -#: pl_gram.y:1437 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "markör-FOR-loop måste ha exakt en målvariabel" -#: pl_gram.y:1444 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "markör-FOR-loop måste använda en bunden markörvariabel" -#: pl_gram.y:1535 +#: pl_gram.y:1511 #, c-format msgid "integer FOR loop must have only one target variable" msgstr "heltals-FOR-loop måste ha exakt en målvariabel" -#: pl_gram.y:1569 +#: pl_gram.y:1545 #, c-format msgid "cannot specify REVERSE in query FOR loop" msgstr "kan inte ange REVERSE i fråge-FOR-loop" -#: pl_gram.y:1699 +#: pl_gram.y:1675 #, c-format msgid "loop variable of FOREACH must be a known variable or list of variables" msgstr "loop-variabel för FOREACH måste vara en känd variabel eller lista av variabler" -#: pl_gram.y:1741 +#: pl_gram.y:1717 #, c-format msgid "there is no label \"%s\" attached to any block or loop enclosing this statement" msgstr "det finns ingen etikett \"%s\" kopplad till något block eller loop-omslutning i denna sats" -#: pl_gram.y:1749 +#: pl_gram.y:1725 #, c-format msgid "block label \"%s\" cannot be used in CONTINUE" msgstr "blocketikett \"%s\" kan inte användas i CONTINUE" -#: pl_gram.y:1764 +#: pl_gram.y:1740 #, c-format msgid "EXIT cannot be used outside a loop, unless it has a label" msgstr "EXIT kan inte användas utanför en loop, om den inte har en etikett" -#: pl_gram.y:1765 +#: pl_gram.y:1741 #, c-format msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE kan inte användas utanför en loop" -#: pl_gram.y:1789 pl_gram.y:1827 pl_gram.y:1875 pl_gram.y:3004 pl_gram.y:3092 -#: pl_gram.y:3203 pl_gram.y:3956 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "oväntat slut på funktionsdefinitionen" -#: pl_gram.y:1895 pl_gram.y:1919 pl_gram.y:1935 pl_gram.y:1941 pl_gram.y:2066 -#: pl_gram.y:2074 pl_gram.y:2088 pl_gram.y:2183 pl_gram.y:2407 pl_gram.y:2497 -#: pl_gram.y:2655 pl_gram.y:3799 pl_gram.y:3860 pl_gram.y:3937 +#: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 +#: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "syntaxfel" -#: pl_gram.y:1923 pl_gram.y:1925 pl_gram.y:2411 pl_gram.y:2413 +#: pl_gram.y:1899 pl_gram.y:1901 pl_gram.y:2387 pl_gram.y:2389 msgid "invalid SQLSTATE code" msgstr "ogiltig SQLSTATE-kod" -#: pl_gram.y:2131 +#: pl_gram.y:2107 msgid "syntax error, expected \"FOR\"" msgstr "syntaxfel, förväntade \"FOR\"" -#: pl_gram.y:2192 +#: pl_gram.y:2168 #, c-format msgid "FETCH statement cannot return multiple rows" msgstr "FETCH-sats kan inte returnera multipla rader" -#: pl_gram.y:2289 +#: pl_gram.y:2265 #, c-format msgid "cursor variable must be a simple variable" msgstr "markörvariabel måste vara en enkel variabel" -#: pl_gram.y:2295 +#: pl_gram.y:2271 #, c-format msgid "variable \"%s\" must be of type cursor or refcursor" msgstr "variabel \"%s\" måste ha typen cursor eller refcursor" -#: pl_gram.y:2626 pl_gram.y:2637 +#: pl_gram.y:2603 pl_gram.y:2614 #, c-format msgid "\"%s\" is not a known variable" msgstr "\"%s\" är inte en känd variabel" -#: pl_gram.y:2743 pl_gram.y:2753 pl_gram.y:2909 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "missmatchade parenteser" -#: pl_gram.y:2757 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "saknar \"%s\" vid slutet av SQL-uttryck" -#: pl_gram.y:2763 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "saknar \"%s\" vid slutet av SQL-sats" -#: pl_gram.y:2780 +#: pl_gram.y:2758 msgid "missing expression" msgstr "saknar uttryck" -#: pl_gram.y:2782 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "saknars SQL-sats" -#: pl_gram.y:2911 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "syntaxfel, förväntade \"]\"" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "inkomplett datatypdeklaration" -#: pl_gram.y:2934 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "saknar datatypdeklaration" -#: pl_gram.y:3014 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO angiven mer än en gång" -#: pl_gram.y:3184 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "förväntade FROM eller IN" -#: pl_gram.y:3245 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "RETURN kan inte ha en parameter i funktion som returnerar en mängd" -#: pl_gram.y:3246 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "Använd RETURN NEXT eller RETURN QUERY." -#: pl_gram.y:3256 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "RETURN kan inte ha en parameter i en procedur" -#: pl_gram.y:3261 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "RETURN kan inte ha en parameter i funktion som returnerar void" -#: pl_gram.y:3270 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "RETURN kan inte ha en parameter i en funktion med OUT-parameterar" -#: pl_gram.y:3333 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "RETURN NEXT kan inte ha en parameter i funktion med OUT-parametrar" -#: pl_gram.y:3441 -#, c-format -msgid "variable \"%s\" is declared CONSTANT" -msgstr "variabel \"%s\" är deklarerad CONSTANT" - -#: pl_gram.y:3499 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "postvariabel kan inte vara del av en multipel-INTO-lista" -#: pl_gram.y:3545 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "för många INTO-variabler angivna" -#: pl_gram.y:3753 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "slutetikett \"%s\" angiven för block utan etikett" -#: pl_gram.y:3760 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "slutetikett \"%s\" stämmer inte med blockets etikett \"%s\"" -#: pl_gram.y:3794 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "markör \"%s\" har inga argument" -#: pl_gram.y:3808 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "markör \"%s\" har argument" -#: pl_gram.y:3850 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "markör \"%s\" har inga argument med namn \"%s\"" -#: pl_gram.y:3870 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "värdet för parameter \"%s\" i markör \"%s\" är angivet mer än en gång" -#: pl_gram.y:3895 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "ej tillräckligt med argument för markör \"%s\"" -#: pl_gram.y:3902 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "fär många argument för markör \"%s\"" -#: pl_gram.y:3988 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "okänd RAISE-sats-flagga" -#: pl_gram.y:3992 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "syntaxfel, förväntade \"=\"" -#: pl_gram.y:4033 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "för många parametrar angivna för RAISE" -#: pl_gram.y:4037 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "för få parametrar angivna för RAISE" @@ -837,13 +851,13 @@ msgid "List of programming constructs that should produce an error." msgstr "Lista av programmeringskonstruktioner som skall ge ett fel" #. translator: %s is typically the translation of "syntax error" -#: pl_scanner.c:508 +#: pl_scanner.c:525 #, c-format msgid "%s at end of input" msgstr "%s vid slutet av indatan" #. translator: first %s is typically the translation of "syntax error" -#: pl_scanner.c:524 +#: pl_scanner.c:541 #, c-format msgid "%s at or near \"%s\"" msgstr "%s vid eller nära \"%s\"" diff --git a/src/pl/plpgsql/src/po/uk.po b/src/pl/plpgsql/src/po/uk.po index 77510da01b8ad..044dd5fa4c385 100644 --- a/src/pl/plpgsql/src/po/uk.po +++ b/src/pl/plpgsql/src/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:39+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:09+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,162 +14,177 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/plpgsql.pot\n" -"X-Crowdin-File-ID: 894\n" +"X-Crowdin-File: /REL_17_STABLE/plpgsql.pot\n" +"X-Crowdin-File-ID: 998\n" -#: pl_comp.c:438 pl_handler.c:496 +#: pl_comp.c:434 pl_handler.c:496 #, c-format msgid "PL/pgSQL functions cannot accept type %s" msgstr "Функції PL/pgSQL не можуть приймати тип %s" -#: pl_comp.c:530 +#: pl_comp.c:526 #, c-format msgid "could not determine actual return type for polymorphic function \"%s\"" msgstr "не вдалося визначити фактичний тип результату поліморфної функції \"%s\"" -#: pl_comp.c:560 +#: pl_comp.c:556 #, c-format msgid "trigger functions can only be called as triggers" msgstr "тригер-функція може викликатися лише як тригер" -#: pl_comp.c:564 pl_handler.c:480 +#: pl_comp.c:560 pl_handler.c:480 #, c-format msgid "PL/pgSQL functions cannot return type %s" msgstr "Функції PL/pgSQL не можуть повертати тип %s" -#: pl_comp.c:604 +#: pl_comp.c:600 #, c-format msgid "trigger functions cannot have declared arguments" msgstr "тригер-функції не можуть мати задекларованих аргументи" -#: pl_comp.c:605 +#: pl_comp.c:601 #, c-format msgid "The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead." msgstr "Аргументи тригеру доступні через TG_NARGS та TG_ARGV замість цього." -#: pl_comp.c:738 +#: pl_comp.c:734 #, c-format msgid "event trigger functions cannot have declared arguments" msgstr "функції тригерів подій не можуть мати задекларовані аргументи" -#: pl_comp.c:1002 +#: pl_comp.c:998 #, c-format msgid "compilation of PL/pgSQL function \"%s\" near line %d" msgstr "компіляція функції PL/pgSQL \"%s\" біля рядка %d" -#: pl_comp.c:1025 +#: pl_comp.c:1021 #, c-format msgid "parameter name \"%s\" used more than once" msgstr "ім'я параметру «%s» використано декілька разів" -#: pl_comp.c:1139 +#: pl_comp.c:1135 #, c-format msgid "column reference \"%s\" is ambiguous" msgstr "посилання на стовпець \"%s\" є неоднозначним" -#: pl_comp.c:1141 +#: pl_comp.c:1137 #, c-format msgid "It could refer to either a PL/pgSQL variable or a table column." msgstr "Це може відноситися до змінної PL/pgSQL або стовпця таблиці." -#: pl_comp.c:1324 pl_exec.c:5234 pl_exec.c:5407 pl_exec.c:5494 pl_exec.c:5585 -#: pl_exec.c:6606 +#: pl_comp.c:1314 pl_exec.c:5260 pl_exec.c:5433 pl_exec.c:5520 pl_exec.c:5611 +#: pl_exec.c:6636 #, c-format msgid "record \"%s\" has no field \"%s\"" msgstr "запис \"%s\" не має поля \"%s\"" -#: pl_comp.c:1818 +#: pl_comp.c:1633 pl_gram.y:645 pl_gram.y:660 pl_gram.y:686 +#, c-format +msgid "variable \"%s\" does not exist" +msgstr "змінної \"%s\" не існує" + +#: pl_comp.c:1722 +#, c-format +msgid "column \"%s\" of relation \"%s\" does not exist" +msgstr "стовпець \"%s\" зв'язку \"%s\" не існує" + +#: pl_comp.c:1775 #, c-format msgid "relation \"%s\" does not exist" msgstr "відношення \"%s\" не існує" -#: pl_comp.c:1825 pl_comp.c:1867 +#: pl_comp.c:1782 pl_comp.c:1820 #, c-format msgid "relation \"%s\" does not have a composite type" msgstr "відношення \"%s\" не має складеного типу" -#: pl_comp.c:1933 +#: pl_comp.c:1886 #, c-format msgid "variable \"%s\" has pseudo-type %s" msgstr "змінна \"%s\" має псевдотип %s" -#: pl_comp.c:2122 +#: pl_comp.c:2075 #, c-format msgid "type \"%s\" is only a shell" msgstr "тип \"%s\" є лише оболонкою" -#: pl_comp.c:2204 pl_exec.c:6907 +#: pl_comp.c:2157 pl_exec.c:6937 #, c-format msgid "type %s is not composite" msgstr "тип %s не є складеним" -#: pl_comp.c:2252 pl_comp.c:2305 +#: pl_comp.c:2193 +#, c-format +msgid "could not find array type for data type %s" +msgstr "не вдалося знайти тип масиву для типу даних %s" + +#: pl_comp.c:2232 pl_comp.c:2285 #, c-format msgid "unrecognized exception condition \"%s\"" msgstr "нерозпізнана умова виключення \"%s\"" -#: pl_comp.c:2526 +#: pl_comp.c:2514 #, c-format msgid "could not determine actual argument type for polymorphic function \"%s\"" msgstr "не вдалося визначити фактичний тип аргумента поліморфної функції \"%s\"" -#: pl_exec.c:501 pl_exec.c:940 pl_exec.c:1175 +#: pl_exec.c:512 pl_exec.c:951 pl_exec.c:1186 msgid "during initialization of execution state" msgstr "під час ініціалізації стану виконання" -#: pl_exec.c:507 +#: pl_exec.c:518 msgid "while storing call arguments into local variables" msgstr "під час зберігання аргументів виклику до локальних змінних" -#: pl_exec.c:595 pl_exec.c:1013 +#: pl_exec.c:606 pl_exec.c:1024 msgid "during function entry" msgstr "під час входу до функції" -#: pl_exec.c:618 +#: pl_exec.c:629 #, c-format msgid "control reached end of function without RETURN" msgstr "досягнуто кінця функції без RETURN" -#: pl_exec.c:624 +#: pl_exec.c:635 msgid "while casting return value to function's return type" msgstr "під час приведення значення, що повертається, до типу результата функції" -#: pl_exec.c:636 pl_exec.c:3665 +#: pl_exec.c:647 pl_exec.c:3683 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "функція \"set-valued\" викликана в контексті, де йому немає місця" -#: pl_exec.c:641 pl_exec.c:3671 +#: pl_exec.c:652 pl_exec.c:3689 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "необхідний режим матеріалізації (materialize mode), але він неприпустимий у цьому контексті" -#: pl_exec.c:768 pl_exec.c:1039 pl_exec.c:1197 +#: pl_exec.c:779 pl_exec.c:1050 pl_exec.c:1208 msgid "during function exit" msgstr "під час виходу з функції" -#: pl_exec.c:823 pl_exec.c:887 pl_exec.c:3464 +#: pl_exec.c:834 pl_exec.c:898 pl_exec.c:3482 msgid "returned record type does not match expected record type" msgstr "тип запису, що повертається, не відповідає очікуваному типу" -#: pl_exec.c:1036 pl_exec.c:1194 +#: pl_exec.c:1047 pl_exec.c:1205 #, c-format msgid "control reached end of trigger procedure without RETURN" msgstr "досягнуто кінця тригерної процедури без RETURN" -#: pl_exec.c:1044 +#: pl_exec.c:1055 #, c-format msgid "trigger procedure cannot return a set" msgstr "тригерна процедура не може повернути набір" -#: pl_exec.c:1083 pl_exec.c:1111 +#: pl_exec.c:1094 pl_exec.c:1122 msgid "returned row structure does not match the structure of the triggering table" msgstr "структура рядка, що повертається, не відповідає структурі таблиці, яка викликала тригер" #. translator: last %s is a phrase such as "during statement block #. local variable initialization" #. -#: pl_exec.c:1252 +#: pl_exec.c:1263 #, c-format msgid "PL/pgSQL function %s line %d %s" msgstr "Функція PL/pgSQL %s рядок %d %s" @@ -177,288 +192,288 @@ msgstr "Функція PL/pgSQL %s рядок %d %s" #. translator: last %s is a phrase such as "while storing call #. arguments into local variables" #. -#: pl_exec.c:1263 +#: pl_exec.c:1274 #, c-format msgid "PL/pgSQL function %s %s" msgstr "Функція PL/pgSQL %s %s" #. translator: last %s is a plpgsql statement type name -#: pl_exec.c:1271 +#: pl_exec.c:1282 #, c-format msgid "PL/pgSQL function %s line %d at %s" msgstr "Функція PL/pgSQL %s рядок %d в %s" -#: pl_exec.c:1277 +#: pl_exec.c:1288 #, c-format msgid "PL/pgSQL function %s" msgstr "Функція PL/pgSQL %s" -#: pl_exec.c:1648 +#: pl_exec.c:1659 msgid "during statement block local variable initialization" msgstr "під час ініціалізації локальної змінної в блоці операторів" -#: pl_exec.c:1753 +#: pl_exec.c:1764 msgid "during statement block entry" msgstr "під час входу в блок операторів" -#: pl_exec.c:1785 +#: pl_exec.c:1796 msgid "during statement block exit" msgstr "під час виходу з блоку операторів" -#: pl_exec.c:1823 +#: pl_exec.c:1834 msgid "during exception cleanup" msgstr "під час очищення винятку" -#: pl_exec.c:2360 +#: pl_exec.c:2370 #, c-format msgid "procedure parameter \"%s\" is an output parameter but corresponding argument is not writable" msgstr "параметр процедури \"%s\" є вихідним, але відповідний аргумент не допускає запис" -#: pl_exec.c:2365 +#: pl_exec.c:2375 #, c-format msgid "procedure parameter %d is an output parameter but corresponding argument is not writable" msgstr "параметр процедури %d є вихідним, але відповідний аргумент не допускає запис" -#: pl_exec.c:2399 +#: pl_exec.c:2411 #, c-format msgid "GET STACKED DIAGNOSTICS cannot be used outside an exception handler" msgstr "GET STACKED DIAGNOSTICS не може використовуватись поза блоком обробника винятків" -#: pl_exec.c:2599 +#: pl_exec.c:2617 #, c-format msgid "case not found" msgstr "гілку не знайдено" -#: pl_exec.c:2600 +#: pl_exec.c:2618 #, c-format msgid "CASE statement is missing ELSE part." msgstr "В операторі CASE пропущено частину ELSE." -#: pl_exec.c:2693 +#: pl_exec.c:2711 #, c-format msgid "lower bound of FOR loop cannot be null" msgstr "нижня границя циклу FOR не може бути null" -#: pl_exec.c:2709 +#: pl_exec.c:2727 #, c-format msgid "upper bound of FOR loop cannot be null" msgstr "верхня границя циклу FOR не може бути null" -#: pl_exec.c:2727 +#: pl_exec.c:2745 #, c-format msgid "BY value of FOR loop cannot be null" msgstr "Значення BY циклу FOR не може бути null" -#: pl_exec.c:2733 +#: pl_exec.c:2751 #, c-format msgid "BY value of FOR loop must be greater than zero" msgstr "Значення BY циклу FOR повинно бути більше нуля" -#: pl_exec.c:2867 pl_exec.c:4667 +#: pl_exec.c:2885 pl_exec.c:4693 #, c-format msgid "cursor \"%s\" already in use" msgstr "курсор \"%s\" вже використовується" -#: pl_exec.c:2890 pl_exec.c:4737 +#: pl_exec.c:2908 pl_exec.c:4763 #, c-format msgid "arguments given for cursor without arguments" msgstr "аргументи, надані курсору без аргументів" -#: pl_exec.c:2909 pl_exec.c:4756 +#: pl_exec.c:2927 pl_exec.c:4782 #, c-format msgid "arguments required for cursor" msgstr "аргументи, необхідні для курсора" -#: pl_exec.c:3000 +#: pl_exec.c:3018 #, c-format msgid "FOREACH expression must not be null" msgstr "Вираз FOREACH не може бути null" -#: pl_exec.c:3015 +#: pl_exec.c:3033 #, c-format msgid "FOREACH expression must yield an array, not type %s" msgstr "Вираз в FOREACH повинен бути масивом, не типом %s" -#: pl_exec.c:3032 +#: pl_exec.c:3050 #, c-format msgid "slice dimension (%d) is out of the valid range 0..%d" msgstr "розмір зрізу (%d) поза припустимим діапазоном 0..%d" -#: pl_exec.c:3059 +#: pl_exec.c:3077 #, c-format msgid "FOREACH ... SLICE loop variable must be of an array type" msgstr "Змінна циклу FOREACH ... SLICE повинна бути масивом" -#: pl_exec.c:3063 +#: pl_exec.c:3081 #, c-format msgid "FOREACH loop variable must not be of an array type" msgstr "Змінна циклу FOREACH не повинна бути масивом" -#: pl_exec.c:3225 pl_exec.c:3282 pl_exec.c:3457 +#: pl_exec.c:3243 pl_exec.c:3300 pl_exec.c:3475 #, c-format msgid "cannot return non-composite value from function returning composite type" msgstr "функція, що повертає складений тип, не може повернути не складене значення" -#: pl_exec.c:3321 pl_gram.y:3319 +#: pl_exec.c:3339 pl_gram.y:3375 #, c-format msgid "cannot use RETURN NEXT in a non-SETOF function" msgstr "не можна використовувати RETURN NEXT в функціях, що не повертають набори даних" -#: pl_exec.c:3362 pl_exec.c:3494 +#: pl_exec.c:3380 pl_exec.c:3512 #, c-format msgid "wrong result type supplied in RETURN NEXT" msgstr "в RETURN NEXT вказано неправильний тип результату" -#: pl_exec.c:3400 pl_exec.c:3421 +#: pl_exec.c:3418 pl_exec.c:3439 #, c-format msgid "wrong record type supplied in RETURN NEXT" msgstr "в RETURN NEXT вказано неправильний тип запису" -#: pl_exec.c:3513 +#: pl_exec.c:3531 #, c-format msgid "RETURN NEXT must have a parameter" msgstr "RETURN NEXT повинен мати параметр" -#: pl_exec.c:3541 pl_gram.y:3383 +#: pl_exec.c:3559 pl_gram.y:3439 #, c-format msgid "cannot use RETURN QUERY in a non-SETOF function" msgstr "не можна використовувати RETURN QUERY в функціях, що не повертають набір" -#: pl_exec.c:3559 +#: pl_exec.c:3577 msgid "structure of query does not match function result type" msgstr "структура запиту не відповідає типу результата функції" -#: pl_exec.c:3614 pl_exec.c:4444 pl_exec.c:8685 +#: pl_exec.c:3632 pl_exec.c:4469 pl_exec.c:8759 #, c-format msgid "query string argument of EXECUTE is null" msgstr "текстовий аргумент запиту EXECUTE є null" -#: pl_exec.c:3699 pl_exec.c:3837 +#: pl_exec.c:3717 pl_exec.c:3855 #, c-format msgid "RAISE option already specified: %s" msgstr "Параметр RAISE вже вказано: %s" -#: pl_exec.c:3733 +#: pl_exec.c:3751 #, c-format msgid "RAISE without parameters cannot be used outside an exception handler" msgstr "RAISE без параметрів не можна використовувати поза блоком обробника винятків" -#: pl_exec.c:3827 +#: pl_exec.c:3845 #, c-format msgid "RAISE statement option cannot be null" msgstr "Параметром оператора RAISE не може бути null" -#: pl_exec.c:3897 +#: pl_exec.c:3915 #, c-format msgid "%s" msgstr "%s" -#: pl_exec.c:3952 +#: pl_exec.c:3970 #, c-format msgid "assertion failed" msgstr "порушення істинності" -#: pl_exec.c:4317 pl_exec.c:4506 +#: pl_exec.c:4342 pl_exec.c:4532 #, c-format msgid "cannot COPY to/from client in PL/pgSQL" msgstr "в PL/pgSQL не можна виконати COPY за участю клієнта" -#: pl_exec.c:4323 +#: pl_exec.c:4348 #, c-format msgid "unsupported transaction command in PL/pgSQL" msgstr "непідтримувана транзакційна команда в PL/pgSQL" -#: pl_exec.c:4346 pl_exec.c:4535 +#: pl_exec.c:4371 pl_exec.c:4561 #, c-format msgid "INTO used with a command that cannot return data" msgstr "INTO використаний з командою, що не може повертати дані" -#: pl_exec.c:4369 pl_exec.c:4558 +#: pl_exec.c:4394 pl_exec.c:4584 #, c-format msgid "query returned no rows" msgstr "запит не повернув рядки" -#: pl_exec.c:4391 pl_exec.c:4577 pl_exec.c:5729 +#: pl_exec.c:4416 pl_exec.c:4603 pl_exec.c:5755 #, c-format msgid "query returned more than one row" msgstr "запит повернув декілька рядків" -#: pl_exec.c:4393 +#: pl_exec.c:4418 #, c-format msgid "Make sure the query returns a single row, or use LIMIT 1." msgstr "Переконайтеся, що запит повертає один рядок, або використовуйте LIMIT 1." -#: pl_exec.c:4409 +#: pl_exec.c:4434 #, c-format msgid "query has no destination for result data" msgstr "запит не має призначення для даних результату" -#: pl_exec.c:4410 +#: pl_exec.c:4435 #, c-format msgid "If you want to discard the results of a SELECT, use PERFORM instead." msgstr "Якщо ви хочете відкинути результати SELECT, використайте PERFORM." -#: pl_exec.c:4498 +#: pl_exec.c:4524 #, c-format msgid "EXECUTE of SELECT ... INTO is not implemented" msgstr "EXECUTE виразу SELECT ... INTO не реалізовано" -#: pl_exec.c:4499 +#: pl_exec.c:4525 #, c-format msgid "You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead." msgstr "Альтернативою може стати EXECUTE ... INTO або EXECUTE CREATE TABLE ... AS." -#: pl_exec.c:4512 +#: pl_exec.c:4538 #, c-format msgid "EXECUTE of transaction commands is not implemented" msgstr "EXECUTE з транзакційними командами не реалізовано" -#: pl_exec.c:4822 pl_exec.c:4910 +#: pl_exec.c:4848 pl_exec.c:4936 #, c-format msgid "cursor variable \"%s\" is null" msgstr "змінна курсора \"%s\" дорівнює null" -#: pl_exec.c:4833 pl_exec.c:4921 +#: pl_exec.c:4859 pl_exec.c:4947 #, c-format msgid "cursor \"%s\" does not exist" msgstr "курсор \"%s\" не існує" -#: pl_exec.c:4846 +#: pl_exec.c:4872 #, c-format msgid "relative or absolute cursor position is null" msgstr "відносна або абсолютна позиція курсора дорівнює null" -#: pl_exec.c:5084 pl_exec.c:5179 +#: pl_exec.c:5110 pl_exec.c:5205 #, c-format msgid "null value cannot be assigned to variable \"%s\" declared NOT NULL" msgstr "значення null не можна призначити змінній \"%s\", оголошеній NOT NULL" -#: pl_exec.c:5160 +#: pl_exec.c:5186 #, c-format msgid "cannot assign non-composite value to a row variable" msgstr "змінній типу кортеж можна призначити лише складене значення" -#: pl_exec.c:5192 +#: pl_exec.c:5218 #, c-format msgid "cannot assign non-composite value to a record variable" msgstr "змінній типу запис можна призначити лише складене значення" -#: pl_exec.c:5243 +#: pl_exec.c:5269 #, c-format msgid "cannot assign to system column \"%s\"" msgstr "призначити значення системному стовпцю \"%s\" не можна" -#: pl_exec.c:5692 +#: pl_exec.c:5718 #, c-format msgid "query did not return data" msgstr "запит не повернув даних" -#: pl_exec.c:5693 pl_exec.c:5705 pl_exec.c:5730 pl_exec.c:5806 pl_exec.c:5811 +#: pl_exec.c:5719 pl_exec.c:5731 pl_exec.c:5756 pl_exec.c:5832 pl_exec.c:5837 #, c-format msgid "query: %s" msgstr "запит: %s" -#: pl_exec.c:5701 +#: pl_exec.c:5727 #, c-format msgid "query returned %d column" msgid_plural "query returned %d columns" @@ -467,48 +482,48 @@ msgstr[1] "запит повернув %d колонки" msgstr[2] "запит повернув %d колонок" msgstr[3] "запит повернув %d колонок" -#: pl_exec.c:5805 +#: pl_exec.c:5831 #, c-format msgid "query is SELECT INTO, but it should be plain SELECT" msgstr "запит є SELECT INTO, але має бути звичайним SELECT" -#: pl_exec.c:5810 +#: pl_exec.c:5836 #, c-format msgid "query is not a SELECT" msgstr "запит не є SELECT" -#: pl_exec.c:6620 pl_exec.c:6660 pl_exec.c:6700 +#: pl_exec.c:6650 pl_exec.c:6690 pl_exec.c:6730 #, c-format msgid "type of parameter %d (%s) does not match that when preparing the plan (%s)" msgstr "тип параметру %d (%s) не відповідає тому, з котрим тривала підготовка плану (%s)" -#: pl_exec.c:7111 pl_exec.c:7145 pl_exec.c:7219 pl_exec.c:7245 +#: pl_exec.c:7141 pl_exec.c:7175 pl_exec.c:7249 pl_exec.c:7275 #, c-format msgid "number of source and target fields in assignment does not match" msgstr "кількість вихідних і цільових полів у присвоюванні не збігається" #. translator: %s represents a name of an extra check -#: pl_exec.c:7113 pl_exec.c:7147 pl_exec.c:7221 pl_exec.c:7247 +#: pl_exec.c:7143 pl_exec.c:7177 pl_exec.c:7251 pl_exec.c:7277 #, c-format msgid "%s check of %s is active." msgstr "%s перевірка %s активна." -#: pl_exec.c:7117 pl_exec.c:7151 pl_exec.c:7225 pl_exec.c:7251 +#: pl_exec.c:7147 pl_exec.c:7181 pl_exec.c:7255 pl_exec.c:7281 #, c-format msgid "Make sure the query returns the exact list of columns." msgstr "Переконайтеся, що запит повертає точний список стовпців." -#: pl_exec.c:7638 +#: pl_exec.c:7668 #, c-format msgid "record \"%s\" is not assigned yet" msgstr "запис \"%s\" ще не призначено" -#: pl_exec.c:7639 +#: pl_exec.c:7669 #, c-format msgid "The tuple structure of a not-yet-assigned record is indeterminate." msgstr "Для запису, котрому не призначене значення, структура кортежа не визначена." -#: pl_exec.c:8283 pl_gram.y:3442 +#: pl_exec.c:8357 pl_gram.y:3498 #, c-format msgid "variable \"%s\" is declared CONSTANT" msgstr "змінна \"%s\" оголошена як CONSTANT" @@ -545,275 +560,274 @@ msgstr "SQL-оператор" msgid "FOR over EXECUTE statement" msgstr "FOR за результатами EXECUTE" -#: pl_gram.y:487 +#: pl_gram.y:485 #, c-format msgid "block label must be placed before DECLARE, not after" msgstr "мітка блоку повинна бути розміщена до DECLARE, а не після" -#: pl_gram.y:507 +#: pl_gram.y:505 #, c-format msgid "collations are not supported by type %s" msgstr "тип %s не підтримує правила сортування" -#: pl_gram.y:526 +#: pl_gram.y:524 #, c-format msgid "variable \"%s\" must have a default value, since it's declared NOT NULL" msgstr "змінна \"%s\" повинна мати значення за замовчуванням після того, як вона оголошена як NOT NULL" -#: pl_gram.y:674 pl_gram.y:689 pl_gram.y:715 -#, c-format -msgid "variable \"%s\" does not exist" -msgstr "змінної \"%s\" не існує" - -#: pl_gram.y:733 pl_gram.y:761 +#: pl_gram.y:704 pl_gram.y:732 msgid "duplicate declaration" msgstr "дублікат оголошення" -#: pl_gram.y:744 pl_gram.y:772 +#: pl_gram.y:715 pl_gram.y:743 #, c-format msgid "variable \"%s\" shadows a previously defined variable" msgstr "змінна \"%s\" приховує раніше оголошену змінну" -#: pl_gram.y:1044 +#: pl_gram.y:1017 #, c-format msgid "diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS" msgstr "команда GET STACKED DIAGNOSTICS не дозволяє елемент діагностування %s" -#: pl_gram.y:1062 +#: pl_gram.y:1035 #, c-format msgid "diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS" msgstr "команда GET CURRENT DIAGNOSTICS не дозволяє елемент діагностування %s" -#: pl_gram.y:1157 +#: pl_gram.y:1133 msgid "unrecognized GET DIAGNOSTICS item" msgstr "нерозпізнаний елемент GET DIAGNOSTICS" -#: pl_gram.y:1173 pl_gram.y:3558 +#: pl_gram.y:1149 pl_gram.y:3614 #, c-format msgid "\"%s\" is not a scalar variable" msgstr "\"%s\" не є скалярною змінною" -#: pl_gram.y:1403 pl_gram.y:1597 +#: pl_gram.y:1379 pl_gram.y:1572 #, c-format msgid "loop variable of loop over rows must be a record variable or list of scalar variables" msgstr "змінна циклу по кортежах повинна бути змінною типу запис або списком скалярних змінних" -#: pl_gram.y:1438 +#: pl_gram.y:1414 #, c-format msgid "cursor FOR loop must have only one target variable" msgstr "курсор в циклі FOR повинен мати лише одну цільову змінну" -#: pl_gram.y:1445 +#: pl_gram.y:1421 #, c-format msgid "cursor FOR loop must use a bound cursor variable" msgstr "цикл курсора FOR повинен використовувати обмежуючу змінну курсора" -#: pl_gram.y:1536 +#: pl_gram.y:1511 #, c-format msgid "integer FOR loop must have only one target variable" msgstr "цілочисельний цикл FOR повинен мати лише одну цільову змінну" -#: pl_gram.y:1570 +#: pl_gram.y:1545 #, c-format msgid "cannot specify REVERSE in query FOR loop" msgstr "в циклі FOR з запитом не можна вказати REVERSE" -#: pl_gram.y:1700 +#: pl_gram.y:1675 #, c-format msgid "loop variable of FOREACH must be a known variable or list of variables" msgstr "змінній циклу FOREACH повинна бути відома змінна або список змінних" -#: pl_gram.y:1742 +#: pl_gram.y:1717 #, c-format msgid "there is no label \"%s\" attached to any block or loop enclosing this statement" msgstr "в блоку або циклу, розділеному цим оператором, немає мітки \"%s\"" -#: pl_gram.y:1750 +#: pl_gram.y:1725 #, c-format msgid "block label \"%s\" cannot be used in CONTINUE" msgstr "мітку блока \"%s\" не можна використовувати в CONTINUE" -#: pl_gram.y:1765 +#: pl_gram.y:1740 #, c-format msgid "EXIT cannot be used outside a loop, unless it has a label" msgstr "EXIT можна використовувати поза циклом, тільки з зазначенням мітки" -#: pl_gram.y:1766 +#: pl_gram.y:1741 #, c-format msgid "CONTINUE cannot be used outside a loop" msgstr "CONTINUE не можна використовувати поза циклом" -#: pl_gram.y:1790 pl_gram.y:1828 pl_gram.y:1876 pl_gram.y:3005 pl_gram.y:3093 -#: pl_gram.y:3204 pl_gram.y:3957 +#: pl_gram.y:1765 pl_gram.y:1803 pl_gram.y:1851 pl_gram.y:3061 pl_gram.y:3149 +#: pl_gram.y:3260 pl_gram.y:4009 msgid "unexpected end of function definition" msgstr "неочікуваний кінец визначення функції" -#: pl_gram.y:1896 pl_gram.y:1920 pl_gram.y:1936 pl_gram.y:1942 pl_gram.y:2067 -#: pl_gram.y:2075 pl_gram.y:2089 pl_gram.y:2184 pl_gram.y:2408 pl_gram.y:2498 -#: pl_gram.y:2656 pl_gram.y:3800 pl_gram.y:3861 pl_gram.y:3938 +#: pl_gram.y:1871 pl_gram.y:1895 pl_gram.y:1911 pl_gram.y:1917 pl_gram.y:2042 +#: pl_gram.y:2050 pl_gram.y:2064 pl_gram.y:2159 pl_gram.y:2383 pl_gram.y:2473 +#: pl_gram.y:2632 pl_gram.y:3856 pl_gram.y:3917 pl_gram.y:3990 msgid "syntax error" msgstr "синтаксична помилка" -#: pl_gram.y:1924 pl_gram.y:1926 pl_gram.y:2412 pl_gram.y:2414 +#: pl_gram.y:1899 pl_gram.y:1901 pl_gram.y:2387 pl_gram.y:2389 msgid "invalid SQLSTATE code" msgstr "неприпустимий код SQLSTATE" -#: pl_gram.y:2132 +#: pl_gram.y:2107 msgid "syntax error, expected \"FOR\"" msgstr "помилка синтаксису, очікувався \"FOR\"" -#: pl_gram.y:2193 +#: pl_gram.y:2168 #, c-format msgid "FETCH statement cannot return multiple rows" msgstr "Оператор FETCH не може повернути декілька рядків" -#: pl_gram.y:2290 +#: pl_gram.y:2265 #, c-format msgid "cursor variable must be a simple variable" msgstr "змінна-курсор повинна бути простою змінною" -#: pl_gram.y:2296 +#: pl_gram.y:2271 #, c-format msgid "variable \"%s\" must be of type cursor or refcursor" msgstr "змінна \"%s\" повинна бути типу cursor або refcursor" -#: pl_gram.y:2627 pl_gram.y:2638 +#: pl_gram.y:2603 pl_gram.y:2614 #, c-format msgid "\"%s\" is not a known variable" msgstr "\"%s\" - невідома змінна" -#: pl_gram.y:2744 pl_gram.y:2754 pl_gram.y:2910 +#: pl_gram.y:2719 pl_gram.y:2729 pl_gram.y:2911 msgid "mismatched parentheses" msgstr "неузгоджені дужки" -#: pl_gram.y:2758 +#: pl_gram.y:2733 #, c-format msgid "missing \"%s\" at end of SQL expression" msgstr "пропущено \"%s\" в кінці виразу SQL" -#: pl_gram.y:2764 +#: pl_gram.y:2739 #, c-format msgid "missing \"%s\" at end of SQL statement" msgstr "пропущено \"%s\" в кінці оператора SQL" -#: pl_gram.y:2781 +#: pl_gram.y:2758 msgid "missing expression" msgstr "пропущено вираз" -#: pl_gram.y:2783 +#: pl_gram.y:2760 msgid "missing SQL statement" msgstr "пропущений оператор SQL" -#: pl_gram.y:2912 +#: pl_gram.y:2889 +msgid "syntax error, expected \"]\"" +msgstr "помилка синтаксису, очікувалось \"]\"" + +#: pl_gram.y:2913 msgid "incomplete data type declaration" msgstr "неповне оголошення типу даних" -#: pl_gram.y:2935 +#: pl_gram.y:2936 msgid "missing data type declaration" msgstr "пропущено оголошення типу даних" -#: pl_gram.y:3015 +#: pl_gram.y:3071 msgid "INTO specified more than once" msgstr "INTO вказано неодноразово" -#: pl_gram.y:3185 +#: pl_gram.y:3241 msgid "expected FROM or IN" msgstr "очікувалось FROM або IN" -#: pl_gram.y:3246 +#: pl_gram.y:3302 #, c-format msgid "RETURN cannot have a parameter in function returning set" msgstr "В функції, яка повертає набір, RETURN не може мати параметр" -#: pl_gram.y:3247 +#: pl_gram.y:3303 #, c-format msgid "Use RETURN NEXT or RETURN QUERY." msgstr "Використайте RETURN NEXT або RETURN QUERY." -#: pl_gram.y:3257 +#: pl_gram.y:3313 #, c-format msgid "RETURN cannot have a parameter in a procedure" msgstr "В процедурі RETURN не може мати параметр" -#: pl_gram.y:3262 +#: pl_gram.y:3318 #, c-format msgid "RETURN cannot have a parameter in function returning void" msgstr "В функції, яка не повертає нічого, RETURN не може мати параметр" -#: pl_gram.y:3271 +#: pl_gram.y:3327 #, c-format msgid "RETURN cannot have a parameter in function with OUT parameters" msgstr "В функції з параметрами OUT, RETURN не може мати параметр" -#: pl_gram.y:3334 +#: pl_gram.y:3390 #, c-format msgid "RETURN NEXT cannot have a parameter in function with OUT parameters" msgstr "В функції з параметрами OUT, RETURN NEXT не може мати параметр" -#: pl_gram.y:3500 +#: pl_gram.y:3556 #, c-format msgid "record variable cannot be part of multiple-item INTO list" msgstr "змінна типу запис не може бути частиною списка INTO з декількома елементами" -#: pl_gram.y:3546 +#: pl_gram.y:3602 #, c-format msgid "too many INTO variables specified" msgstr "вказано занадто багато змінних INTO" -#: pl_gram.y:3754 +#: pl_gram.y:3810 #, c-format msgid "end label \"%s\" specified for unlabeled block" msgstr "кінцева мітка \"%s\" вказана для невідміченого блоку" -#: pl_gram.y:3761 +#: pl_gram.y:3817 #, c-format msgid "end label \"%s\" differs from block's label \"%s\"" msgstr "кінцева мітка \"%s\" відрізняється від мітки блоку \"%s\"" -#: pl_gram.y:3795 +#: pl_gram.y:3851 #, c-format msgid "cursor \"%s\" has no arguments" msgstr "курсор \"%s\" не має аргументів" -#: pl_gram.y:3809 +#: pl_gram.y:3865 #, c-format msgid "cursor \"%s\" has arguments" msgstr "курсор \"%s\" має аргументи" -#: pl_gram.y:3851 +#: pl_gram.y:3907 #, c-format msgid "cursor \"%s\" has no argument named \"%s\"" msgstr "курсор \"%s\" не має аргументу \"%s\"" -#: pl_gram.y:3871 +#: pl_gram.y:3927 #, c-format msgid "value for parameter \"%s\" of cursor \"%s\" specified more than once" msgstr "значення параметра \"%s\" курсора \"%s\" вказано неодноразово" -#: pl_gram.y:3896 +#: pl_gram.y:3948 #, c-format msgid "not enough arguments for cursor \"%s\"" msgstr "недостатньо аргументів для курсора \"%s\"" -#: pl_gram.y:3903 +#: pl_gram.y:3955 #, c-format msgid "too many arguments for cursor \"%s\"" msgstr "занадто багато аргументів для курсора \"%s\"" -#: pl_gram.y:3989 +#: pl_gram.y:4041 msgid "unrecognized RAISE statement option" msgstr "нерозпізнаний параметр оператора RAISE" -#: pl_gram.y:3993 +#: pl_gram.y:4045 msgid "syntax error, expected \"=\"" msgstr "помилка синтаксису, очікувалось \"=\"" -#: pl_gram.y:4034 +#: pl_gram.y:4086 #, c-format msgid "too many parameters specified for RAISE" msgstr "занадто багато параметрів вказано для RAISE" -#: pl_gram.y:4038 +#: pl_gram.y:4090 #, c-format msgid "too few parameters specified for RAISE" msgstr "занадто мало параметрів вказано для RAISE" @@ -839,13 +853,13 @@ msgid "List of programming constructs that should produce an error." msgstr "Список програмних конструкцій, які повинні видавати помилку." #. translator: %s is typically the translation of "syntax error" -#: pl_scanner.c:508 +#: pl_scanner.c:525 #, c-format msgid "%s at end of input" msgstr "%s в кінці введення" #. translator: first %s is typically the translation of "syntax error" -#: pl_scanner.c:524 +#: pl_scanner.c:541 #, c-format msgid "%s at or near \"%s\"" msgstr "%s в або поблизу \"%s\"" diff --git a/src/pl/plpgsql/src/sql/plpgsql_array.sql b/src/pl/plpgsql/src/sql/plpgsql_array.sql index 4b9ff51594899..da984a99414d9 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_array.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_array.sql @@ -48,6 +48,16 @@ begin a.c1[1].i := 11; raise notice 'a = %, a.c1[1].i = %', a, a.c1[1].i; end$$; do $$ declare a int[]; begin a := array_agg(x) from (values(1),(2),(3)) v(x); raise notice 'a = %', a; end$$; +do $$ declare a int[] := array[1,2,3]; +begin + -- test scenarios for optimization of updates of R/W expanded objects + a := array_append(a, 42); -- optimizable using "transfer" method + a := a || a[3]; -- optimizable using "inplace" method + a := a[1] || a; -- ditto, but let's test array_prepend + a := a || a; -- not optimizable + raise notice 'a = %', a; +end$$; + create temp table onecol as select array[1,2] as f1; do $$ declare a int[]; diff --git a/src/pl/plpgsql/src/sql/plpgsql_call.sql b/src/pl/plpgsql/src/sql/plpgsql_call.sql index 4cbda0382e957..08c1659ef1564 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_call.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_call.sql @@ -557,6 +557,23 @@ BEGIN END $$; +-- test in non-atomic context, except exception block is locally atomic +DO $$ +BEGIN + BEGIN + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + EXCEPTION WHEN division_by_zero THEN + RAISE NOTICE '%', SQLERRM; + END; + ROLLBACK; +END +$$; + -- test in atomic context BEGIN; diff --git a/src/pl/plpgsql/src/sql/plpgsql_record.sql b/src/pl/plpgsql/src/sql/plpgsql_record.sql index 96dcc414e9205..4fbed38b8bbb9 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_record.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_record.sql @@ -338,6 +338,7 @@ begin return next h; return next row(5,6); return next row(7,8)::has_hole; + return query select 9, 10; end$$; select returnssetofholes(); @@ -356,6 +357,13 @@ begin end$$; select returnssetofholes(); +create or replace function returnssetofholes() returns setof has_hole language plpgsql as +$$ +begin + return query select 1, 2.0; -- fails +end$$; +select returnssetofholes(); + -- check behavior with changes of a named rowtype create table mutable(f1 int, f2 text); diff --git a/src/pl/plpgsql/src/sql/plpgsql_simple.sql b/src/pl/plpgsql/src/sql/plpgsql_simple.sql index 143bf09dce469..72d8afe4500d1 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_simple.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_simple.sql @@ -102,3 +102,15 @@ as $$select 22 + 22$$; select simplecaller(); select simplecaller(); + +-- Check handling of simple expression in a scrollable cursor (bug #18859) + +do $$ +declare + p_CurData refcursor; + val int; +begin + open p_CurData scroll for select 42; + fetch p_CurData into val; + raise notice 'val = %', val; +end; $$; diff --git a/src/pl/plpython/expected/README b/src/pl/plpython/expected/README deleted file mode 100644 index 388c553a5890a..0000000000000 --- a/src/pl/plpython/expected/README +++ /dev/null @@ -1,3 +0,0 @@ -Guide to alternative expected files: - -plpython_error_5.out Python 3.5 and newer diff --git a/src/pl/plpython/expected/plpython_error.out b/src/pl/plpython/expected/plpython_error.out index 68722b00097ed..fd9cd73be743a 100644 --- a/src/pl/plpython/expected/plpython_error.out +++ b/src/pl/plpython/expected/plpython_error.out @@ -243,7 +243,7 @@ $$ plpy.nonexistent $$ LANGUAGE plpython3u; SELECT toplevel_attribute_error(); -ERROR: AttributeError: 'module' object has no attribute 'nonexistent' +ERROR: AttributeError: module 'plpy' has no attribute 'nonexistent' CONTEXT: Traceback (most recent call last): PL/Python function "toplevel_attribute_error", line 2, in plpy.nonexistent diff --git a/src/pl/plpython/expected/plpython_error_5.out b/src/pl/plpython/expected/plpython_error_5.out deleted file mode 100644 index fd9cd73be743a..0000000000000 --- a/src/pl/plpython/expected/plpython_error_5.out +++ /dev/null @@ -1,460 +0,0 @@ --- test error handling, i forgot to restore Warn_restart in --- the trigger handler once. the errors and subsequent core dump were --- interesting. -/* Flat out Python syntax error - */ -CREATE FUNCTION python_syntax_error() RETURNS text - AS -'.syntaxerror' - LANGUAGE plpython3u; -ERROR: could not compile PL/Python function "python_syntax_error" -DETAIL: SyntaxError: invalid syntax (, line 2) -/* With check_function_bodies = false the function should get defined - * and the error reported when called - */ -SET check_function_bodies = false; -CREATE FUNCTION python_syntax_error() RETURNS text - AS -'.syntaxerror' - LANGUAGE plpython3u; -SELECT python_syntax_error(); -ERROR: could not compile PL/Python function "python_syntax_error" -DETAIL: SyntaxError: invalid syntax (, line 2) -/* Run the function twice to check if the hashtable entry gets cleaned up */ -SELECT python_syntax_error(); -ERROR: could not compile PL/Python function "python_syntax_error" -DETAIL: SyntaxError: invalid syntax (, line 2) -RESET check_function_bodies; -/* Flat out syntax error - */ -CREATE FUNCTION sql_syntax_error() RETURNS text - AS -'plpy.execute("syntax error")' - LANGUAGE plpython3u; -SELECT sql_syntax_error(); -ERROR: spiexceptions.SyntaxError: syntax error at or near "syntax" -LINE 1: syntax error - ^ -QUERY: syntax error -CONTEXT: Traceback (most recent call last): - PL/Python function "sql_syntax_error", line 1, in - plpy.execute("syntax error") -PL/Python function "sql_syntax_error" -/* check the handling of uncaught python exceptions - */ -CREATE FUNCTION exception_index_invalid(text) RETURNS text - AS -'return args[1]' - LANGUAGE plpython3u; -SELECT exception_index_invalid('test'); -ERROR: IndexError: list index out of range -CONTEXT: Traceback (most recent call last): - PL/Python function "exception_index_invalid", line 1, in - return args[1] -PL/Python function "exception_index_invalid" -/* check handling of nested exceptions - */ -CREATE FUNCTION exception_index_invalid_nested() RETURNS text - AS -'rv = plpy.execute("SELECT test5(''foo'')") -return rv[0]' - LANGUAGE plpython3u; -SELECT exception_index_invalid_nested(); -ERROR: spiexceptions.UndefinedFunction: function test5(unknown) does not exist -LINE 1: SELECT test5('foo') - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. -QUERY: SELECT test5('foo') -CONTEXT: Traceback (most recent call last): - PL/Python function "exception_index_invalid_nested", line 1, in - rv = plpy.execute("SELECT test5('foo')") -PL/Python function "exception_index_invalid_nested" -/* a typo - */ -CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text - AS -'if "plan" not in SD: - q = "SELECT fname FROM users WHERE lname = $1" - SD["plan"] = plpy.prepare(q, [ "test" ]) -rv = plpy.execute(SD["plan"], [ a ]) -if len(rv): - return rv[0]["fname"] -return None -' - LANGUAGE plpython3u; -SELECT invalid_type_uncaught('rick'); -ERROR: spiexceptions.UndefinedObject: type "test" does not exist -CONTEXT: Traceback (most recent call last): - PL/Python function "invalid_type_uncaught", line 3, in - SD["plan"] = plpy.prepare(q, [ "test" ]) -PL/Python function "invalid_type_uncaught" -/* for what it's worth catch the exception generated by - * the typo, and return None - */ -CREATE FUNCTION invalid_type_caught(a text) RETURNS text - AS -'if "plan" not in SD: - q = "SELECT fname FROM users WHERE lname = $1" - try: - SD["plan"] = plpy.prepare(q, [ "test" ]) - except plpy.SPIError as ex: - plpy.notice(str(ex)) - return None -rv = plpy.execute(SD["plan"], [ a ]) -if len(rv): - return rv[0]["fname"] -return None -' - LANGUAGE plpython3u; -SELECT invalid_type_caught('rick'); -NOTICE: type "test" does not exist - invalid_type_caught ---------------------- - -(1 row) - -/* for what it's worth catch the exception generated by - * the typo, and reraise it as a plain error - */ -CREATE FUNCTION invalid_type_reraised(a text) RETURNS text - AS -'if "plan" not in SD: - q = "SELECT fname FROM users WHERE lname = $1" - try: - SD["plan"] = plpy.prepare(q, [ "test" ]) - except plpy.SPIError as ex: - plpy.error(str(ex)) -rv = plpy.execute(SD["plan"], [ a ]) -if len(rv): - return rv[0]["fname"] -return None -' - LANGUAGE plpython3u; -SELECT invalid_type_reraised('rick'); -ERROR: plpy.Error: type "test" does not exist -CONTEXT: Traceback (most recent call last): - PL/Python function "invalid_type_reraised", line 6, in - plpy.error(str(ex)) -PL/Python function "invalid_type_reraised" -/* no typo no messing about - */ -CREATE FUNCTION valid_type(a text) RETURNS text - AS -'if "plan" not in SD: - SD["plan"] = plpy.prepare("SELECT fname FROM users WHERE lname = $1", [ "text" ]) -rv = plpy.execute(SD["plan"], [ a ]) -if len(rv): - return rv[0]["fname"] -return None -' - LANGUAGE plpython3u; -SELECT valid_type('rick'); - valid_type ------------- - -(1 row) - -/* error in nested functions to get a traceback -*/ -CREATE FUNCTION nested_error() RETURNS text - AS -'def fun1(): - plpy.error("boom") - -def fun2(): - fun1() - -def fun3(): - fun2() - -fun3() -return "not reached" -' - LANGUAGE plpython3u; -SELECT nested_error(); -ERROR: plpy.Error: boom -CONTEXT: Traceback (most recent call last): - PL/Python function "nested_error", line 10, in - fun3() - PL/Python function "nested_error", line 8, in fun3 - fun2() - PL/Python function "nested_error", line 5, in fun2 - fun1() - PL/Python function "nested_error", line 2, in fun1 - plpy.error("boom") -PL/Python function "nested_error" -/* raising plpy.Error is just like calling plpy.error -*/ -CREATE FUNCTION nested_error_raise() RETURNS text - AS -'def fun1(): - raise plpy.Error("boom") - -def fun2(): - fun1() - -def fun3(): - fun2() - -fun3() -return "not reached" -' - LANGUAGE plpython3u; -SELECT nested_error_raise(); -ERROR: plpy.Error: boom -CONTEXT: Traceback (most recent call last): - PL/Python function "nested_error_raise", line 10, in - fun3() - PL/Python function "nested_error_raise", line 8, in fun3 - fun2() - PL/Python function "nested_error_raise", line 5, in fun2 - fun1() - PL/Python function "nested_error_raise", line 2, in fun1 - raise plpy.Error("boom") -PL/Python function "nested_error_raise" -/* using plpy.warning should not produce a traceback -*/ -CREATE FUNCTION nested_warning() RETURNS text - AS -'def fun1(): - plpy.warning("boom") - -def fun2(): - fun1() - -def fun3(): - fun2() - -fun3() -return "you''ve been warned" -' - LANGUAGE plpython3u; -SELECT nested_warning(); -WARNING: boom - nested_warning --------------------- - you've been warned -(1 row) - -/* AttributeError at toplevel used to give segfaults with the traceback -*/ -CREATE FUNCTION toplevel_attribute_error() RETURNS void AS -$$ -plpy.nonexistent -$$ LANGUAGE plpython3u; -SELECT toplevel_attribute_error(); -ERROR: AttributeError: module 'plpy' has no attribute 'nonexistent' -CONTEXT: Traceback (most recent call last): - PL/Python function "toplevel_attribute_error", line 2, in - plpy.nonexistent -PL/Python function "toplevel_attribute_error" -/* Calling PL/Python functions from SQL and vice versa should not lose context. - */ -CREATE OR REPLACE FUNCTION python_traceback() RETURNS void AS $$ -def first(): - second() - -def second(): - third() - -def third(): - plpy.execute("select sql_error()") - -first() -$$ LANGUAGE plpython3u; -CREATE OR REPLACE FUNCTION sql_error() RETURNS void AS $$ -begin - select 1/0; -end -$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION python_from_sql_error() RETURNS void AS $$ -begin - select python_traceback(); -end -$$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION sql_from_python_error() RETURNS void AS $$ -plpy.execute("select sql_error()") -$$ LANGUAGE plpython3u; -SELECT python_traceback(); -ERROR: spiexceptions.DivisionByZero: division by zero -CONTEXT: Traceback (most recent call last): - PL/Python function "python_traceback", line 11, in - first() - PL/Python function "python_traceback", line 3, in first - second() - PL/Python function "python_traceback", line 6, in second - third() - PL/Python function "python_traceback", line 9, in third - plpy.execute("select sql_error()") -PL/Python function "python_traceback" -SELECT sql_error(); -ERROR: division by zero -CONTEXT: SQL statement "select 1/0" -PL/pgSQL function sql_error() line 3 at SQL statement -SELECT python_from_sql_error(); -ERROR: spiexceptions.DivisionByZero: division by zero -CONTEXT: Traceback (most recent call last): - PL/Python function "python_traceback", line 11, in - first() - PL/Python function "python_traceback", line 3, in first - second() - PL/Python function "python_traceback", line 6, in second - third() - PL/Python function "python_traceback", line 9, in third - plpy.execute("select sql_error()") -PL/Python function "python_traceback" -SQL statement "select python_traceback()" -PL/pgSQL function python_from_sql_error() line 3 at SQL statement -SELECT sql_from_python_error(); -ERROR: spiexceptions.DivisionByZero: division by zero -CONTEXT: Traceback (most recent call last): - PL/Python function "sql_from_python_error", line 2, in - plpy.execute("select sql_error()") -PL/Python function "sql_from_python_error" -/* check catching specific types of exceptions - */ -CREATE TABLE specific ( - i integer PRIMARY KEY -); -CREATE FUNCTION specific_exception(i integer) RETURNS void AS -$$ -from plpy import spiexceptions -try: - plpy.execute("insert into specific values (%s)" % (i or "NULL")); -except spiexceptions.NotNullViolation as e: - plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate) -except spiexceptions.UniqueViolation as e: - plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate) -$$ LANGUAGE plpython3u; -SELECT specific_exception(2); - specific_exception --------------------- - -(1 row) - -SELECT specific_exception(NULL); -NOTICE: Violated the NOT NULL constraint, sqlstate 23502 - specific_exception --------------------- - -(1 row) - -SELECT specific_exception(2); -NOTICE: Violated the UNIQUE constraint, sqlstate 23505 - specific_exception --------------------- - -(1 row) - -/* SPI errors in PL/Python functions should preserve the SQLSTATE value - */ -CREATE FUNCTION python_unique_violation() RETURNS void AS $$ -plpy.execute("insert into specific values (1)") -plpy.execute("insert into specific values (1)") -$$ LANGUAGE plpython3u; -CREATE FUNCTION catch_python_unique_violation() RETURNS text AS $$ -begin - begin - perform python_unique_violation(); - exception when unique_violation then - return 'ok'; - end; - return 'not reached'; -end; -$$ language plpgsql; -SELECT catch_python_unique_violation(); - catch_python_unique_violation -------------------------------- - ok -(1 row) - -/* manually starting subtransactions - a bad idea - */ -CREATE FUNCTION manual_subxact() RETURNS void AS $$ -plpy.execute("savepoint save") -plpy.execute("create table foo(x integer)") -plpy.execute("rollback to save") -$$ LANGUAGE plpython3u; -SELECT manual_subxact(); -ERROR: plpy.SPIError: SPI_execute failed: SPI_ERROR_TRANSACTION -CONTEXT: Traceback (most recent call last): - PL/Python function "manual_subxact", line 2, in - plpy.execute("savepoint save") -PL/Python function "manual_subxact" -/* same for prepared plans - */ -CREATE FUNCTION manual_subxact_prepared() RETURNS void AS $$ -save = plpy.prepare("savepoint save") -rollback = plpy.prepare("rollback to save") -plpy.execute(save) -plpy.execute("create table foo(x integer)") -plpy.execute(rollback) -$$ LANGUAGE plpython3u; -SELECT manual_subxact_prepared(); -ERROR: plpy.SPIError: SPI_execute_plan failed: SPI_ERROR_TRANSACTION -CONTEXT: Traceback (most recent call last): - PL/Python function "manual_subxact_prepared", line 4, in - plpy.execute(save) -PL/Python function "manual_subxact_prepared" -/* raising plpy.spiexception.* from python code should preserve sqlstate - */ -CREATE FUNCTION plpy_raise_spiexception() RETURNS void AS $$ -raise plpy.spiexceptions.DivisionByZero() -$$ LANGUAGE plpython3u; -DO $$ -BEGIN - SELECT plpy_raise_spiexception(); -EXCEPTION WHEN division_by_zero THEN - -- NOOP -END -$$ LANGUAGE plpgsql; -/* setting a custom sqlstate should be handled - */ -CREATE FUNCTION plpy_raise_spiexception_override() RETURNS void AS $$ -exc = plpy.spiexceptions.DivisionByZero() -exc.sqlstate = 'SILLY' -raise exc -$$ LANGUAGE plpython3u; -DO $$ -BEGIN - SELECT plpy_raise_spiexception_override(); -EXCEPTION WHEN SQLSTATE 'SILLY' THEN - -- NOOP -END -$$ LANGUAGE plpgsql; -/* test the context stack trace for nested execution levels - */ -CREATE FUNCTION notice_innerfunc() RETURNS int AS $$ -plpy.execute("DO LANGUAGE plpython3u $x$ plpy.notice('inside DO') $x$") -return 1 -$$ LANGUAGE plpython3u; -CREATE FUNCTION notice_outerfunc() RETURNS int AS $$ -plpy.execute("SELECT notice_innerfunc()") -return 1 -$$ LANGUAGE plpython3u; -\set SHOW_CONTEXT always -SELECT notice_outerfunc(); -NOTICE: inside DO -CONTEXT: PL/Python anonymous code block -SQL statement "DO LANGUAGE plpython3u $x$ plpy.notice('inside DO') $x$" -PL/Python function "notice_innerfunc" -SQL statement "SELECT notice_innerfunc()" -PL/Python function "notice_outerfunc" - notice_outerfunc ------------------- - 1 -(1 row) - -/* test error logged with an underlying exception that includes a detail - * string (bug #18070). - */ -CREATE FUNCTION python_error_detail() RETURNS SETOF text AS $$ - plan = plpy.prepare("SELECT to_date('xy', 'DD') d") - for row in plpy.cursor(plan): - yield row['d'] -$$ LANGUAGE plpython3u; -SELECT python_error_detail(); -ERROR: error fetching next item from iterator -DETAIL: spiexceptions.InvalidDatetimeFormat: invalid value "xy" for "DD" -CONTEXT: Traceback (most recent call last): -PL/Python function "python_error_detail" diff --git a/src/pl/plpython/expected/plpython_setof.out b/src/pl/plpython/expected/plpython_setof.out index 3940940029035..c4461ac276252 100644 --- a/src/pl/plpython/expected/plpython_setof.out +++ b/src/pl/plpython/expected/plpython_setof.out @@ -17,6 +17,12 @@ for i in range(count): t += ( content, ) return t $$ LANGUAGE plpython3u; +CREATE FUNCTION test_setof_as_set(count integer, content text) RETURNS SETOF text AS $$ +s = set() +for i in range(count): + s.add(content * (i + 1) if content is not None else None) +return s +$$ LANGUAGE plpython3u; CREATE FUNCTION test_setof_as_iterator(count integer, content text) RETURNS SETOF text AS $$ class producer: def __init__ (self, icount, icontent): @@ -90,6 +96,30 @@ SELECT test_setof_as_tuple(2, null); (2 rows) +SELECT * FROM test_setof_as_set(0, 'set') ORDER BY 1; + test_setof_as_set +------------------- +(0 rows) + +SELECT * FROM test_setof_as_set(1, 'set') ORDER BY 1; + test_setof_as_set +------------------- + set +(1 row) + +SELECT * FROM test_setof_as_set(2, 'set') ORDER BY 1; + test_setof_as_set +------------------- + set + setset +(2 rows) + +SELECT * FROM test_setof_as_set(2, null) ORDER BY 1; + test_setof_as_set +------------------- + +(1 row) + SELECT test_setof_as_iterator(0, 'list'); test_setof_as_iterator ------------------------ diff --git a/src/pl/plpython/expected/plpython_spi.out b/src/pl/plpython/expected/plpython_spi.out index 8853e2540d3c2..b572f9bf73bcb 100644 --- a/src/pl/plpython/expected/plpython_spi.out +++ b/src/pl/plpython/expected/plpython_spi.out @@ -319,12 +319,9 @@ assert len(res.fetch(3)) == 1 assert len(res.fetch(3)) == 0 assert len(res.fetch(3)) == 0 try: - # use next() or __next__(), the method name changed in + # use next() and not __next__(), the method name changed in # http://www.python.org/dev/peps/pep-3114/ - try: - res.next() - except AttributeError: - res.__next__() + next(res) except StopIteration: pass else: @@ -334,11 +331,7 @@ CREATE FUNCTION cursor_mix_next_and_fetch() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users order by fname") assert len(res.fetch(2)) == 2 -item = None -try: - item = res.next() -except AttributeError: - item = res.__next__() +item = next(res) assert item['fname'] == 'rick' assert len(res.fetch(2)) == 1 @@ -357,10 +350,7 @@ CREATE FUNCTION next_after_close() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users") res.close() try: - try: - res.next() - except AttributeError: - res.__next__() + next(res) except ValueError: pass else: @@ -370,10 +360,7 @@ CREATE FUNCTION cursor_fetch_next_empty() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users where false") assert len(res.fetch(1)) == 0 try: - try: - res.next() - except AttributeError: - res.__next__() + next(res) except StopIteration: pass else: diff --git a/src/pl/plpython/expected/plpython_trigger.out b/src/pl/plpython/expected/plpython_trigger.out index 4cb90cb520493..64eab2fa3f4b5 100644 --- a/src/pl/plpython/expected/plpython_trigger.out +++ b/src/pl/plpython/expected/plpython_trigger.out @@ -69,7 +69,8 @@ CREATE TABLE trigger_test (i int, v text ); CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE FUNCTION trigger_data() RETURNS trigger LANGUAGE plpython3u AS $$ @@ -614,8 +615,8 @@ ERROR: cannot set generated column "j" CONTEXT: while modifying trigger row PL/Python function "generated_test_func1" SELECT * FROM trigger_test_generated; - i | j ----+--- + i | j | k +---+---+--- (0 rows) -- recursive call of a trigger mustn't corrupt TD (bug #18456) diff --git a/src/pl/plpython/generate-spiexceptions.pl b/src/pl/plpython/generate-spiexceptions.pl index f0c5142be3c60..a0df785c725ed 100644 --- a/src/pl/plpython/generate-spiexceptions.pl +++ b/src/pl/plpython/generate-spiexceptions.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the spiexceptions.h header from errcodes.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/pl/plpython/meson.build b/src/pl/plpython/meson.build index a2787da649bfd..709e5932a93a8 100644 --- a/src/pl/plpython/meson.build +++ b/src/pl/plpython/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not python3_dep.found() subdir_done() diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c index 57e8f8ec2170b..cc74c4df6ba67 100644 --- a/src/pl/plpython/plpy_cursorobject.c +++ b/src/pl/plpython/plpy_cursorobject.c @@ -8,26 +8,24 @@ #include -#include "access/xact.h" #include "catalog/pg_type.h" #include "mb/pg_wchar.h" #include "plpy_cursorobject.h" #include "plpy_elog.h" #include "plpy_main.h" #include "plpy_planobject.h" -#include "plpy_procedure.h" #include "plpy_resultobject.h" #include "plpy_spi.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/memutils.h" static PyObject *PLy_cursor_query(const char *query); -static void PLy_cursor_dealloc(PyObject *arg); +static void PLy_cursor_dealloc(PLyCursorObject *self); static PyObject *PLy_cursor_iternext(PyObject *self); static PyObject *PLy_cursor_fetch(PyObject *self, PyObject *args); static PyObject *PLy_cursor_close(PyObject *self, PyObject *unused); -static char PLy_cursor_doc[] = "Wrapper around a PostgreSQL cursor"; +static const char PLy_cursor_doc[] = "Wrapper around a PostgreSQL cursor"; static PyMethodDef PLy_cursor_methods[] = { {"fetch", PLy_cursor_fetch, METH_VARARGS, NULL}, @@ -35,22 +33,43 @@ static PyMethodDef PLy_cursor_methods[] = { {NULL, NULL, 0, NULL} }; -static PyTypeObject PLy_CursorType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "PLyCursor", - .tp_basicsize = sizeof(PLyCursorObject), - .tp_dealloc = PLy_cursor_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = PLy_cursor_doc, - .tp_iter = PyObject_SelfIter, - .tp_iternext = PLy_cursor_iternext, - .tp_methods = PLy_cursor_methods, +static PyType_Slot PLyCursor_slots[] = +{ + { + Py_tp_dealloc, PLy_cursor_dealloc + }, + { + Py_tp_doc, (char *) PLy_cursor_doc + }, + { + Py_tp_iter, PyObject_SelfIter + }, + { + Py_tp_iternext, PLy_cursor_iternext + }, + { + Py_tp_methods, PLy_cursor_methods + }, + { + 0, NULL + } +}; + +static PyType_Spec PLyCursor_spec = +{ + .name = "PLyCursor", + .basicsize = sizeof(PLyCursorObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = PLyCursor_slots, }; +static PyTypeObject *PLy_CursorType; + void PLy_cursor_init_type(void) { - if (PyType_Ready(&PLy_CursorType) < 0) + PLy_CursorType = (PyTypeObject *) PyType_FromSpec(&PLyCursor_spec); + if (!PLy_CursorType) elog(ERROR, "could not initialize PLy_CursorType"); } @@ -82,8 +101,12 @@ PLy_cursor_query(const char *query) volatile MemoryContext oldcontext; volatile ResourceOwner oldowner; - if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL) + if ((cursor = PyObject_New(PLyCursorObject, PLy_CursorType)) == NULL) return NULL; +#if PY_VERSION_HEX < 0x03080000 + /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */ + Py_INCREF(PLy_CursorType); +#endif cursor->portalname = NULL; cursor->closed = false; cursor->mcxt = AllocSetContextCreate(TopMemoryContext, @@ -142,7 +165,6 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) { PLyCursorObject *cursor; volatile int nargs; - int i; PLyPlanObject *plan; PLyExecutionContext *exec_ctx = PLy_current_execution_context(); volatile MemoryContext oldcontext; @@ -180,8 +202,12 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) return NULL; } - if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL) + if ((cursor = PyObject_New(PLyCursorObject, PLy_CursorType)) == NULL) return NULL; +#if PY_VERSION_HEX < 0x03080000 + /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */ + Py_INCREF(PLy_CursorType); +#endif cursor->portalname = NULL; cursor->closed = false; cursor->mcxt = AllocSetContextCreate(TopMemoryContext, @@ -201,13 +227,30 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) PG_TRY(); { Portal portal; + MemoryContext tmpcontext; + Datum *volatile values; char *volatile nulls; volatile int j; + /* + * Converted arguments and associated cruft will be in this context, + * which is local to our subtransaction. + */ + tmpcontext = AllocSetContextCreate(CurTransactionContext, + "PL/Python temporary context", + ALLOCSET_SMALL_SIZES); + MemoryContextSwitchTo(tmpcontext); + if (nargs > 0) - nulls = palloc(nargs * sizeof(char)); + { + values = (Datum *) palloc(nargs * sizeof(Datum)); + nulls = (char *) palloc(nargs * sizeof(char)); + } else + { + values = NULL; nulls = NULL; + } for (j = 0; j < nargs; j++) { @@ -219,7 +262,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) { bool isnull; - plan->values[j] = PLy_output_convert(arg, elem, &isnull); + values[j] = PLy_output_convert(arg, elem, &isnull); nulls[j] = isnull ? 'n' : ' '; } PG_FINALLY(2); @@ -229,7 +272,9 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) PG_END_TRY(2); } - portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls, + MemoryContextSwitchTo(oldcontext); + + portal = SPI_cursor_open(NULL, plan->plan, values, nulls, exec_ctx->curr_proc->fn_readonly); if (portal == NULL) elog(ERROR, "SPI_cursor_open() failed: %s", @@ -239,69 +284,52 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) PinPortal(portal); + MemoryContextDelete(tmpcontext); PLy_spi_subtransaction_commit(oldcontext, oldowner); } PG_CATCH(); { - int k; - - /* cleanup plan->values array */ - for (k = 0; k < nargs; k++) - { - if (!plan->args[k].typbyval && - (plan->values[k] != PointerGetDatum(NULL))) - { - pfree(DatumGetPointer(plan->values[k])); - plan->values[k] = PointerGetDatum(NULL); - } - } - Py_DECREF(cursor); - + /* Subtransaction abort will remove the tmpcontext */ PLy_spi_subtransaction_abort(oldcontext, oldowner); return NULL; } PG_END_TRY(); - for (i = 0; i < nargs; i++) - { - if (!plan->args[i].typbyval && - (plan->values[i] != PointerGetDatum(NULL))) - { - pfree(DatumGetPointer(plan->values[i])); - plan->values[i] = PointerGetDatum(NULL); - } - } - Assert(cursor->portalname != NULL); return (PyObject *) cursor; } static void -PLy_cursor_dealloc(PyObject *arg) +PLy_cursor_dealloc(PLyCursorObject *self) { - PLyCursorObject *cursor; +#if PY_VERSION_HEX >= 0x03080000 + PyTypeObject *tp = Py_TYPE(self); +#endif Portal portal; - cursor = (PLyCursorObject *) arg; - - if (!cursor->closed) + if (!self->closed) { - portal = GetPortalByName(cursor->portalname); + portal = GetPortalByName(self->portalname); if (PortalIsValid(portal)) { UnpinPortal(portal); SPI_cursor_close(portal); } - cursor->closed = true; + self->closed = true; } - if (cursor->mcxt) + if (self->mcxt) { - MemoryContextDelete(cursor->mcxt); - cursor->mcxt = NULL; + MemoryContextDelete(self->mcxt); + self->mcxt = NULL; } - arg->ob_type->tp_free(arg); + + PyObject_Free(self); +#if PY_VERSION_HEX >= 0x03080000 + /* This was not needed before Python 3.8 (Python issue 35810) */ + Py_DECREF(tp); +#endif } static PyObject * diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c index 70de5ba13d74b..f6d10045e5cea 100644 --- a/src/pl/plpython/plpy_elog.c +++ b/src/pl/plpython/plpy_elog.c @@ -10,7 +10,7 @@ #include "plpy_elog.h" #include "plpy_main.h" #include "plpy_procedure.h" -#include "plpython.h" +#include "plpy_util.h" PyObject *PLy_exc_error = NULL; PyObject *PLy_exc_fatal = NULL; @@ -18,7 +18,8 @@ PyObject *PLy_exc_spi_error = NULL; static void PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, - char **xmsg, char **tbmsg, int *tb_depth); + char *volatile *xmsg, char *volatile *tbmsg, + int *tb_depth); static void PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hint, char **query, int *position, char **schema_name, char **table_name, char **column_name, @@ -43,78 +44,82 @@ void PLy_elog_impl(int elevel, const char *fmt,...) { int save_errno = errno; - char *xmsg; - char *tbmsg; + char *volatile xmsg = NULL; + char *volatile tbmsg = NULL; int tb_depth; StringInfoData emsg; PyObject *exc, *val, *tb; - const char *primary = NULL; - int sqlerrcode = 0; - char *detail = NULL; - char *hint = NULL; - char *query = NULL; - int position = 0; - char *schema_name = NULL; - char *table_name = NULL; - char *column_name = NULL; - char *datatype_name = NULL; - char *constraint_name = NULL; + + /* If we'll need emsg, must initialize it before entering PG_TRY */ + if (fmt) + initStringInfo(&emsg); PyErr_Fetch(&exc, &val, &tb); - if (exc != NULL) + /* Use a PG_TRY block to ensure we release the PyObjects just acquired */ + PG_TRY(); { - PyErr_NormalizeException(&exc, &val, &tb); - - if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error)) - PLy_get_spi_error_data(val, &sqlerrcode, - &detail, &hint, &query, &position, + const char *primary = NULL; + int sqlerrcode = 0; + char *detail = NULL; + char *hint = NULL; + char *query = NULL; + int position = 0; + char *schema_name = NULL; + char *table_name = NULL; + char *column_name = NULL; + char *datatype_name = NULL; + char *constraint_name = NULL; + + if (exc != NULL) + { + PyErr_NormalizeException(&exc, &val, &tb); + + if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error)) + PLy_get_spi_error_data(val, &sqlerrcode, + &detail, &hint, &query, &position, + &schema_name, &table_name, &column_name, + &datatype_name, &constraint_name); + else if (PyErr_GivenExceptionMatches(val, PLy_exc_error)) + PLy_get_error_data(val, &sqlerrcode, &detail, &hint, &schema_name, &table_name, &column_name, &datatype_name, &constraint_name); - else if (PyErr_GivenExceptionMatches(val, PLy_exc_error)) - PLy_get_error_data(val, &sqlerrcode, &detail, &hint, - &schema_name, &table_name, &column_name, - &datatype_name, &constraint_name); - else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal)) - elevel = FATAL; - } + else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal)) + elevel = FATAL; + } - /* this releases our refcount on tb! */ - PLy_traceback(exc, val, tb, - &xmsg, &tbmsg, &tb_depth); + PLy_traceback(exc, val, tb, + &xmsg, &tbmsg, &tb_depth); - if (fmt) - { - initStringInfo(&emsg); - for (;;) + if (fmt) { - va_list ap; - int needed; - - errno = save_errno; - va_start(ap, fmt); - needed = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap); - va_end(ap); - if (needed == 0) - break; - enlargeStringInfo(&emsg, needed); - } - primary = emsg.data; + for (;;) + { + va_list ap; + int needed; + + errno = save_errno; + va_start(ap, fmt); + needed = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap); + va_end(ap); + if (needed == 0) + break; + enlargeStringInfo(&emsg, needed); + } + primary = emsg.data; - /* If there's an exception message, it goes in the detail. */ - if (xmsg) - detail = xmsg; - } - else - { - if (xmsg) - primary = xmsg; - } + /* If there's an exception message, it goes in the detail. */ + if (xmsg) + detail = xmsg; + } + else + { + if (xmsg) + primary = xmsg; + } - PG_TRY(); - { ereport(elevel, (errcode(sqlerrcode ? sqlerrcode : ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), errmsg_internal("%s", primary ? primary : "no exception data"), @@ -136,14 +141,23 @@ PLy_elog_impl(int elevel, const char *fmt,...) } PG_FINALLY(); { + Py_XDECREF(exc); + Py_XDECREF(val); + /* Must release all the objects in the traceback stack */ + while (tb != NULL && tb != Py_None) + { + PyObject *tb_prev = tb; + + tb = PyObject_GetAttrString(tb, "tb_next"); + Py_DECREF(tb_prev); + } + /* For neatness' sake, also release our string buffers */ if (fmt) pfree(emsg.data); if (xmsg) pfree(xmsg); if (tbmsg) pfree(tbmsg); - Py_XDECREF(exc); - Py_XDECREF(val); } PG_END_TRY(); } @@ -154,21 +168,14 @@ PLy_elog_impl(int elevel, const char *fmt,...) * The exception error message is returned in xmsg, the traceback in * tbmsg (both as palloc'd strings) and the traceback depth in * tb_depth. - * - * We release refcounts on all the Python objects in the traceback stack, - * but not on e or v. */ static void PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, - char **xmsg, char **tbmsg, int *tb_depth) + char *volatile *xmsg, char *volatile *tbmsg, int *tb_depth) { - PyObject *e_type_o; - PyObject *e_module_o; - char *e_type_s = NULL; - char *e_module_s = NULL; - PyObject *vob = NULL; - char *vstr; - StringInfoData xstr; + PyObject *volatile e_type_o = NULL; + PyObject *volatile e_module_o = NULL; + PyObject *volatile vob = NULL; StringInfoData tbstr; /* @@ -186,47 +193,59 @@ PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, /* * Format the exception and its value and put it in xmsg. */ - - e_type_o = PyObject_GetAttrString(e, "__name__"); - e_module_o = PyObject_GetAttrString(e, "__module__"); - if (e_type_o) - e_type_s = PLyUnicode_AsString(e_type_o); - if (e_type_s) - e_module_s = PLyUnicode_AsString(e_module_o); - - if (v && ((vob = PyObject_Str(v)) != NULL)) - vstr = PLyUnicode_AsString(vob); - else - vstr = "unknown"; - - initStringInfo(&xstr); - if (!e_type_s || !e_module_s) + PG_TRY(); { - /* shouldn't happen */ - appendStringInfoString(&xstr, "unrecognized exception"); + char *e_type_s = NULL; + char *e_module_s = NULL; + const char *vstr; + StringInfoData xstr; + + e_type_o = PyObject_GetAttrString(e, "__name__"); + e_module_o = PyObject_GetAttrString(e, "__module__"); + if (e_type_o) + e_type_s = PLyUnicode_AsString(e_type_o); + if (e_module_o) + e_module_s = PLyUnicode_AsString(e_module_o); + + if (v && ((vob = PyObject_Str(v)) != NULL)) + vstr = PLyUnicode_AsString(vob); + else + vstr = "unknown"; + + initStringInfo(&xstr); + if (!e_type_s || !e_module_s) + { + /* shouldn't happen */ + appendStringInfoString(&xstr, "unrecognized exception"); + } + /* mimics behavior of traceback.format_exception_only */ + else if (strcmp(e_module_s, "builtins") == 0 + || strcmp(e_module_s, "__main__") == 0 + || strcmp(e_module_s, "exceptions") == 0) + appendStringInfoString(&xstr, e_type_s); + else + appendStringInfo(&xstr, "%s.%s", e_module_s, e_type_s); + appendStringInfo(&xstr, ": %s", vstr); + + *xmsg = xstr.data; } - /* mimics behavior of traceback.format_exception_only */ - else if (strcmp(e_module_s, "builtins") == 0 - || strcmp(e_module_s, "__main__") == 0 - || strcmp(e_module_s, "exceptions") == 0) - appendStringInfoString(&xstr, e_type_s); - else - appendStringInfo(&xstr, "%s.%s", e_module_s, e_type_s); - appendStringInfo(&xstr, ": %s", vstr); - - *xmsg = xstr.data; + PG_FINALLY(); + { + Py_XDECREF(e_type_o); + Py_XDECREF(e_module_o); + Py_XDECREF(vob); + } + PG_END_TRY(); /* * Now format the traceback and put it in tbmsg. */ - *tb_depth = 0; initStringInfo(&tbstr); /* Mimic Python traceback reporting as close as possible. */ appendStringInfoString(&tbstr, "Traceback (most recent call last):"); while (tb != NULL && tb != Py_None) { - PyObject *volatile tb_prev = NULL; PyObject *volatile frame = NULL; PyObject *volatile code = NULL; PyObject *volatile name = NULL; @@ -254,84 +273,74 @@ PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, filename = PyObject_GetAttrString(code, "co_filename"); if (filename == NULL) elog(ERROR, "could not get file name from Python code object"); + + /* The first frame always points at , skip it. */ + if (*tb_depth > 0) + { + PLyExecutionContext *exec_ctx = PLy_current_execution_context(); + char *proname; + char *fname; + char *line; + char *plain_filename; + long plain_lineno; + + /* + * The second frame points at the internal function, but to + * mimic Python error reporting we want to say . + */ + if (*tb_depth == 1) + fname = ""; + else + fname = PLyUnicode_AsString(name); + + proname = PLy_procedure_name(exec_ctx->curr_proc); + plain_filename = PLyUnicode_AsString(filename); + plain_lineno = PyLong_AsLong(lineno); + + if (proname == NULL) + appendStringInfo(&tbstr, "\n PL/Python anonymous code block, line %ld, in %s", + plain_lineno - 1, fname); + else + appendStringInfo(&tbstr, "\n PL/Python function \"%s\", line %ld, in %s", + proname, plain_lineno - 1, fname); + + /* + * function code object was compiled with "" as the + * filename + */ + if (exec_ctx->curr_proc && plain_filename != NULL && + strcmp(plain_filename, "") == 0) + { + /* + * If we know the current procedure, append the exact line + * from the source, again mimicking Python's traceback.py + * module behavior. We could store the already line-split + * source to avoid splitting it every time, but producing + * a traceback is not the most important scenario to + * optimize for. But we do not go as far as traceback.py + * in reading the source of imported modules. + */ + line = get_source_line(exec_ctx->curr_proc->src, plain_lineno); + if (line) + { + appendStringInfo(&tbstr, "\n %s", line); + pfree(line); + } + } + } } - PG_CATCH(); + PG_FINALLY(); { Py_XDECREF(frame); Py_XDECREF(code); Py_XDECREF(name); Py_XDECREF(lineno); Py_XDECREF(filename); - PG_RE_THROW(); } PG_END_TRY(); - /* The first frame always points at , skip it. */ - if (*tb_depth > 0) - { - PLyExecutionContext *exec_ctx = PLy_current_execution_context(); - char *proname; - char *fname; - char *line; - char *plain_filename; - long plain_lineno; - - /* - * The second frame points at the internal function, but to mimic - * Python error reporting we want to say . - */ - if (*tb_depth == 1) - fname = ""; - else - fname = PLyUnicode_AsString(name); - - proname = PLy_procedure_name(exec_ctx->curr_proc); - plain_filename = PLyUnicode_AsString(filename); - plain_lineno = PyLong_AsLong(lineno); - - if (proname == NULL) - appendStringInfo(&tbstr, "\n PL/Python anonymous code block, line %ld, in %s", - plain_lineno - 1, fname); - else - appendStringInfo(&tbstr, "\n PL/Python function \"%s\", line %ld, in %s", - proname, plain_lineno - 1, fname); - - /* - * function code object was compiled with "" as the - * filename - */ - if (exec_ctx->curr_proc && plain_filename != NULL && - strcmp(plain_filename, "") == 0) - { - /* - * If we know the current procedure, append the exact line - * from the source, again mimicking Python's traceback.py - * module behavior. We could store the already line-split - * source to avoid splitting it every time, but producing a - * traceback is not the most important scenario to optimize - * for. But we do not go as far as traceback.py in reading - * the source of imported modules. - */ - line = get_source_line(exec_ctx->curr_proc->src, plain_lineno); - if (line) - { - appendStringInfo(&tbstr, "\n %s", line); - pfree(line); - } - } - } - - Py_DECREF(frame); - Py_DECREF(code); - Py_DECREF(name); - Py_DECREF(lineno); - Py_DECREF(filename); - - /* Release the current frame and go to the next one. */ - tb_prev = tb; + /* Advance to the next frame. */ tb = PyObject_GetAttrString(tb, "tb_next"); - Assert(tb_prev != Py_None); - Py_DECREF(tb_prev); if (tb == NULL) elog(ERROR, "could not traverse Python traceback"); (*tb_depth)++; @@ -339,10 +348,6 @@ PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, /* Return the traceback. */ *tbmsg = tbstr.data; - - Py_XDECREF(e_type_o); - Py_XDECREF(e_module_o); - Py_XDECREF(vob); } /* diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c index 157229e96f6a3..28fbd443b98c9 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -17,11 +17,9 @@ #include "plpy_main.h" #include "plpy_procedure.h" #include "plpy_subxactobject.h" -#include "plpython.h" -#include "utils/builtins.h" -#include "utils/lsyscache.h" +#include "plpy_util.h" +#include "utils/fmgrprotos.h" #include "utils/rel.h" -#include "utils/typcache.h" /* saved state for a set-returning function */ typedef struct PLySRFState @@ -82,10 +80,10 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc) sizeof(PLySRFState)); /* Immediately register cleanup callback */ srfstate->callback.func = plpython_srf_cleanup_callback; - srfstate->callback.arg = (void *) srfstate; + srfstate->callback.arg = srfstate; MemoryContextRegisterResetCallback(funcctx->multi_call_memory_ctx, &srfstate->callback); - funcctx->user_fctx = (void *) srfstate; + funcctx->user_fctx = srfstate; } /* Every call setup */ funcctx = SRF_PERCALL_SETUP(); @@ -1068,13 +1066,7 @@ PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs) PG_TRY(); { -#if PY_VERSION_HEX >= 0x03020000 - rv = PyEval_EvalCode(proc->code, - proc->globals, proc->globals); -#else - rv = PyEval_EvalCode((PyCodeObject *) proc->code, - proc->globals, proc->globals); -#endif + rv = PyEval_EvalCode(proc->code, proc->globals, proc->globals); /* * Since plpy will only let you close subtransactions that you diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c index 010a97378c908..f36eadbadc66d 100644 --- a/src/pl/plpython/plpy_main.c +++ b/src/pl/plpython/plpy_main.c @@ -18,7 +18,7 @@ #include "plpy_plpymodule.h" #include "plpy_procedure.h" #include "plpy_subxactobject.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -28,7 +28,10 @@ * exported functions */ -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "plpython", + .version = PG_VERSION +); PG_FUNCTION_INFO_V1(plpython3_validator); PG_FUNCTION_INFO_V1(plpython3_call_handler); @@ -202,8 +205,7 @@ plpython3_call_handler(PG_FUNCTION_ARGS) !castNode(CallContext, fcinfo->context)->atomic; /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */ - if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0); /* * Push execution context onto stack. It is important that this get @@ -272,8 +274,7 @@ plpython3_inline_handler(PG_FUNCTION_ARGS) PLy_initialize(); /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */ - if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC); MemSet(fcinfo, 0, SizeForFunctionCallInfo(0)); MemSet(&flinfo, 0, sizeof(flinfo)); diff --git a/src/pl/plpython/plpy_planobject.c b/src/pl/plpython/plpy_planobject.c index ec2439c6a1fac..edfb76c877020 100644 --- a/src/pl/plpython/plpy_planobject.c +++ b/src/pl/plpython/plpy_planobject.c @@ -7,13 +7,12 @@ #include "postgres.h" #include "plpy_cursorobject.h" -#include "plpy_elog.h" #include "plpy_planobject.h" #include "plpy_spi.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/memutils.h" -static void PLy_plan_dealloc(PyObject *arg); +static void PLy_plan_dealloc(PLyPlanObject *self); static PyObject *PLy_plan_cursor(PyObject *self, PyObject *args); static PyObject *PLy_plan_execute(PyObject *self, PyObject *args); static PyObject *PLy_plan_status(PyObject *self, PyObject *args); @@ -27,20 +26,37 @@ static PyMethodDef PLy_plan_methods[] = { {NULL, NULL, 0, NULL} }; -static PyTypeObject PLy_PlanType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "PLyPlan", - .tp_basicsize = sizeof(PLyPlanObject), - .tp_dealloc = PLy_plan_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = PLy_plan_doc, - .tp_methods = PLy_plan_methods, +static PyType_Slot PLyPlan_slots[] = +{ + { + Py_tp_dealloc, PLy_plan_dealloc + }, + { + Py_tp_doc, (char *) PLy_plan_doc + }, + { + Py_tp_methods, PLy_plan_methods + }, + { + 0, NULL + } }; +static PyType_Spec PLyPlan_spec = +{ + .name = "PLyPlan", + .basicsize = sizeof(PLyPlanObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = PLyPlan_slots, +}; + +static PyTypeObject *PLy_PlanType; + void PLy_plan_init_type(void) { - if (PyType_Ready(&PLy_PlanType) < 0) + PLy_PlanType = (PyTypeObject *) PyType_FromSpec(&PLyPlan_spec); + if (!PLy_PlanType) elog(ERROR, "could not initialize PLy_PlanType"); } @@ -49,13 +65,16 @@ PLy_plan_new(void) { PLyPlanObject *ob; - if ((ob = PyObject_New(PLyPlanObject, &PLy_PlanType)) == NULL) + if ((ob = PyObject_New(PLyPlanObject, PLy_PlanType)) == NULL) return NULL; +#if PY_VERSION_HEX < 0x03080000 + /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */ + Py_INCREF(PLy_PlanType); +#endif ob->plan = NULL; ob->nargs = 0; ob->types = NULL; - ob->values = NULL; ob->args = NULL; ob->mcxt = NULL; @@ -65,25 +84,32 @@ PLy_plan_new(void) bool is_PLyPlanObject(PyObject *ob) { - return ob->ob_type == &PLy_PlanType; + return ob->ob_type == PLy_PlanType; } static void -PLy_plan_dealloc(PyObject *arg) +PLy_plan_dealloc(PLyPlanObject *self) { - PLyPlanObject *ob = (PLyPlanObject *) arg; +#if PY_VERSION_HEX >= 0x03080000 + PyTypeObject *tp = Py_TYPE(self); +#endif - if (ob->plan) + if (self->plan) { - SPI_freeplan(ob->plan); - ob->plan = NULL; + SPI_freeplan(self->plan); + self->plan = NULL; } - if (ob->mcxt) + if (self->mcxt) { - MemoryContextDelete(ob->mcxt); - ob->mcxt = NULL; + MemoryContextDelete(self->mcxt); + self->mcxt = NULL; } - arg->ob_type->tp_free(arg); + + PyObject_Free(self); +#if PY_VERSION_HEX >= 0x03080000 + /* This was not needed before Python 3.8 (Python issue 35810) */ + Py_DECREF(tp); +#endif } diff --git a/src/pl/plpython/plpy_planobject.h b/src/pl/plpython/plpy_planobject.h index 729effb1631da..a6b34fae199b1 100644 --- a/src/pl/plpython/plpy_planobject.h +++ b/src/pl/plpython/plpy_planobject.h @@ -15,7 +15,6 @@ typedef struct PLyPlanObject SPIPlanPtr plan; int nargs; Oid *types; - Datum *values; PLyObToDatum *args; MemoryContext mcxt; } PLyPlanObject; diff --git a/src/pl/plpython/plpy_plpymodule.c b/src/pl/plpython/plpy_plpymodule.c index fa08f0dbfb37a..1f980b44b2a31 100644 --- a/src/pl/plpython/plpy_plpymodule.c +++ b/src/pl/plpython/plpy_plpymodule.c @@ -6,19 +6,16 @@ #include "postgres.h" -#include "access/xact.h" #include "mb/pg_wchar.h" #include "plpy_cursorobject.h" #include "plpy_elog.h" -#include "plpy_main.h" #include "plpy_planobject.h" #include "plpy_plpymodule.h" #include "plpy_resultobject.h" #include "plpy_spi.h" #include "plpy_subxactobject.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/builtins.h" -#include "utils/snapmgr.h" HTAB *PLy_spi_exceptions = NULL; diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c index ba7786d31c31b..c176d24e80118 100644 --- a/src/pl/plpython/plpy_procedure.c +++ b/src/pl/plpython/plpy_procedure.c @@ -7,18 +7,15 @@ #include "postgres.h" #include "access/htup_details.h" -#include "access/transam.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "plpy_elog.h" #include "plpy_main.h" #include "plpy_procedure.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/builtins.h" #include "utils/hsearch.h" -#include "utils/inval.h" -#include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/syscache.h" @@ -353,6 +350,7 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src) { PyObject *crv = NULL; char *msrc; + PyObject *code0; proc->globals = PyDict_Copy(PLy_interp_globals); @@ -371,7 +369,9 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src) msrc = PLy_procedure_munge_source(proc->pyname, src); /* Save the mangled source for later inclusion in tracebacks */ proc->src = MemoryContextStrdup(proc->mcxt, msrc); - crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL); + code0 = Py_CompileString(msrc, "", Py_file_input); + if (code0) + crv = PyEval_EvalCode(code0, proc->globals, NULL); pfree(msrc); if (crv != NULL) diff --git a/src/pl/plpython/plpy_resultobject.c b/src/pl/plpython/plpy_resultobject.c index 95acce654935c..d433929b36039 100644 --- a/src/pl/plpython/plpy_resultobject.c +++ b/src/pl/plpython/plpy_resultobject.c @@ -8,9 +8,9 @@ #include "plpy_elog.h" #include "plpy_resultobject.h" -#include "plpython.h" +#include "plpy_util.h" -static void PLy_result_dealloc(PyObject *arg); +static void PLy_result_dealloc(PLyResultObject *self); static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused); static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused); static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused); @@ -24,17 +24,6 @@ static int PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *val static char PLy_result_doc[] = "Results of a PostgreSQL query"; -static PySequenceMethods PLy_result_as_sequence = { - .sq_length = PLy_result_length, - .sq_item = PLy_result_item, -}; - -static PyMappingMethods PLy_result_as_mapping = { - .mp_length = PLy_result_length, - .mp_subscript = PLy_result_subscript, - .mp_ass_subscript = PLy_result_ass_subscript, -}; - static PyMethodDef PLy_result_methods[] = { {"colnames", PLy_result_colnames, METH_NOARGS, NULL}, {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL}, @@ -44,23 +33,55 @@ static PyMethodDef PLy_result_methods[] = { {NULL, NULL, 0, NULL} }; -static PyTypeObject PLy_ResultType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "PLyResult", - .tp_basicsize = sizeof(PLyResultObject), - .tp_dealloc = PLy_result_dealloc, - .tp_as_sequence = &PLy_result_as_sequence, - .tp_as_mapping = &PLy_result_as_mapping, - .tp_str = &PLy_result_str, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = PLy_result_doc, - .tp_methods = PLy_result_methods, +static PyType_Slot PLyResult_slots[] = +{ + { + Py_tp_dealloc, PLy_result_dealloc + }, + { + Py_sq_length, PLy_result_length + }, + { + Py_sq_item, PLy_result_item + }, + { + Py_mp_length, PLy_result_length + }, + { + Py_mp_subscript, PLy_result_subscript + }, + { + Py_mp_ass_subscript, PLy_result_ass_subscript + }, + { + Py_tp_str, PLy_result_str + }, + { + Py_tp_doc, (char *) PLy_result_doc + }, + { + Py_tp_methods, PLy_result_methods + }, + { + 0, NULL + } +}; + +static PyType_Spec PLyResult_spec = +{ + .name = "PLyResult", + .basicsize = sizeof(PLyResultObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = PLyResult_slots, }; +static PyTypeObject *PLy_ResultType; + void PLy_result_init_type(void) { - if (PyType_Ready(&PLy_ResultType) < 0) + PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec); + if (!PLy_ResultType) elog(ERROR, "could not initialize PLy_ResultType"); } @@ -69,8 +90,12 @@ PLy_result_new(void) { PLyResultObject *ob; - if ((ob = PyObject_New(PLyResultObject, &PLy_ResultType)) == NULL) + if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL) return NULL; +#if PY_VERSION_HEX < 0x03080000 + /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */ + Py_INCREF(PLy_ResultType); +#endif /* ob->tuples = NULL; */ @@ -89,20 +114,26 @@ PLy_result_new(void) } static void -PLy_result_dealloc(PyObject *arg) +PLy_result_dealloc(PLyResultObject *self) { - PLyResultObject *ob = (PLyResultObject *) arg; - - Py_XDECREF(ob->nrows); - Py_XDECREF(ob->rows); - Py_XDECREF(ob->status); - if (ob->tupdesc) +#if PY_VERSION_HEX >= 0x03080000 + PyTypeObject *tp = Py_TYPE(self); +#endif + + Py_XDECREF(self->nrows); + Py_XDECREF(self->rows); + Py_XDECREF(self->status); + if (self->tupdesc) { - FreeTupleDesc(ob->tupdesc); - ob->tupdesc = NULL; + FreeTupleDesc(self->tupdesc); + self->tupdesc = NULL; } - arg->ob_type->tp_free(arg); + PyObject_Free(self); +#if PY_VERSION_HEX >= 0x03080000 + /* This was not needed before Python 3.8 (Python issue 35810) */ + Py_DECREF(tp); +#endif } static PyObject * @@ -125,7 +156,7 @@ PLy_result_colnames(PyObject *self, PyObject *unused) { Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); - PyList_SET_ITEM(list, i, PLyUnicode_FromString(NameStr(attr->attname))); + PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname))); } return list; @@ -151,7 +182,7 @@ PLy_result_coltypes(PyObject *self, PyObject *unused) { Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); - PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypid)); + PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid)); } return list; @@ -177,7 +208,7 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused) { Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); - PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypmod)); + PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod)); } return list; @@ -227,7 +258,7 @@ PLy_result_str(PyObject *arg) PLyResultObject *ob = (PLyResultObject *) arg; return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>", - Py_TYPE(ob)->tp_name, + "PLyResult", ob->status, ob->nrows, ob->rows); diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c index ff87b27de0903..1e386aadcca2b 100644 --- a/src/pl/plpython/plpy_spi.c +++ b/src/pl/plpython/plpy_spi.c @@ -8,7 +8,6 @@ #include -#include "access/htup_details.h" #include "access/xact.h" #include "catalog/pg_type.h" #include "executor/spi.h" @@ -18,12 +17,10 @@ #include "plpy_main.h" #include "plpy_planobject.h" #include "plpy_plpymodule.h" -#include "plpy_procedure.h" #include "plpy_resultobject.h" #include "plpy_spi.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/memutils.h" -#include "utils/syscache.h" static PyObject *PLy_spi_execute_query(char *query, long limit); static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, @@ -69,7 +66,6 @@ PLy_spi_prepare(PyObject *self, PyObject *args) plan->nargs = nargs; plan->types = nargs ? palloc0(sizeof(Oid) * nargs) : NULL; - plan->values = nargs ? palloc0(sizeof(Datum) * nargs) : NULL; plan->args = nargs ? palloc0(sizeof(PLyObToDatum) * nargs) : NULL; MemoryContextSwitchTo(oldcontext); @@ -175,8 +171,7 @@ PyObject * PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) { volatile int nargs; - int i, - rv; + int rv; PLyPlanObject *plan; volatile MemoryContext oldcontext; volatile ResourceOwner oldowner; @@ -222,13 +217,30 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) PG_TRY(); { PLyExecutionContext *exec_ctx = PLy_current_execution_context(); + MemoryContext tmpcontext; + Datum *volatile values; char *volatile nulls; volatile int j; + /* + * Converted arguments and associated cruft will be in this context, + * which is local to our subtransaction. + */ + tmpcontext = AllocSetContextCreate(CurTransactionContext, + "PL/Python temporary context", + ALLOCSET_SMALL_SIZES); + MemoryContextSwitchTo(tmpcontext); + if (nargs > 0) - nulls = palloc(nargs * sizeof(char)); + { + values = (Datum *) palloc(nargs * sizeof(Datum)); + nulls = (char *) palloc(nargs * sizeof(char)); + } else + { + values = NULL; nulls = NULL; + } for (j = 0; j < nargs; j++) { @@ -240,7 +252,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) { bool isnull; - plan->values[j] = PLy_output_convert(arg, elem, &isnull); + values[j] = PLy_output_convert(arg, elem, &isnull); nulls[j] = isnull ? 'n' : ' '; } PG_FINALLY(2); @@ -250,47 +262,23 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) PG_END_TRY(2); } - rv = SPI_execute_plan(plan->plan, plan->values, nulls, + MemoryContextSwitchTo(oldcontext); + + rv = SPI_execute_plan(plan->plan, values, nulls, exec_ctx->curr_proc->fn_readonly, limit); ret = PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv); - if (nargs > 0) - pfree(nulls); - + MemoryContextDelete(tmpcontext); PLy_spi_subtransaction_commit(oldcontext, oldowner); } PG_CATCH(); { - int k; - - /* - * cleanup plan->values array - */ - for (k = 0; k < nargs; k++) - { - if (!plan->args[k].typbyval && - (plan->values[k] != PointerGetDatum(NULL))) - { - pfree(DatumGetPointer(plan->values[k])); - plan->values[k] = PointerGetDatum(NULL); - } - } - + /* Subtransaction abort will remove the tmpcontext */ PLy_spi_subtransaction_abort(oldcontext, oldowner); return NULL; } PG_END_TRY(); - for (i = 0; i < nargs; i++) - { - if (!plan->args[i].typbyval && - (plan->values[i] != PointerGetDatum(NULL))) - { - pfree(DatumGetPointer(plan->values[i])); - plan->values[i] = PointerGetDatum(NULL); - } - } - if (rv < 0) { PLy_exception_set(PLy_exc_spi_error, diff --git a/src/pl/plpython/plpy_subxactobject.c b/src/pl/plpython/plpy_subxactobject.c index 5c92a0e089a1b..c225b652ab4a5 100644 --- a/src/pl/plpython/plpy_subxactobject.c +++ b/src/pl/plpython/plpy_subxactobject.c @@ -9,13 +9,12 @@ #include "access/xact.h" #include "plpy_elog.h" #include "plpy_subxactobject.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/memutils.h" List *explicit_subtransactions = NIL; -static void PLy_subtransaction_dealloc(PyObject *subxact); static PyObject *PLy_subtransaction_enter(PyObject *self, PyObject *unused); static PyObject *PLy_subtransaction_exit(PyObject *self, PyObject *args); @@ -31,21 +30,35 @@ static PyMethodDef PLy_subtransaction_methods[] = { {NULL, NULL, 0, NULL} }; -static PyTypeObject PLy_SubtransactionType = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "PLySubtransaction", - .tp_basicsize = sizeof(PLySubtransactionObject), - .tp_dealloc = PLy_subtransaction_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = PLy_subtransaction_doc, - .tp_methods = PLy_subtransaction_methods, +static PyType_Slot PLySubtransaction_slots[] = +{ + { + Py_tp_doc, (char *) PLy_subtransaction_doc + }, + { + Py_tp_methods, PLy_subtransaction_methods + }, + { + 0, NULL + } }; +static PyType_Spec PLySubtransaction_spec = +{ + .name = "PLySubtransaction", + .basicsize = sizeof(PLySubtransactionObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = PLySubtransaction_slots, +}; + +static PyTypeObject *PLy_SubtransactionType; + void PLy_subtransaction_init_type(void) { - if (PyType_Ready(&PLy_SubtransactionType) < 0) + PLy_SubtransactionType = (PyTypeObject *) PyType_FromSpec(&PLySubtransaction_spec); + if (!PLy_SubtransactionType) elog(ERROR, "could not initialize PLy_SubtransactionType"); } @@ -55,10 +68,13 @@ PLy_subtransaction_new(PyObject *self, PyObject *unused) { PLySubtransactionObject *ob; - ob = PyObject_New(PLySubtransactionObject, &PLy_SubtransactionType); - + ob = PyObject_New(PLySubtransactionObject, PLy_SubtransactionType); if (ob == NULL) return NULL; +#if PY_VERSION_HEX < 0x03080000 + /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */ + Py_INCREF(PLy_SubtransactionType); +#endif ob->started = false; ob->exited = false; @@ -66,12 +82,6 @@ PLy_subtransaction_new(PyObject *self, PyObject *unused) return (PyObject *) ob; } -/* Python requires a dealloc function to be defined */ -static void -PLy_subtransaction_dealloc(PyObject *subxact) -{ -} - /* * subxact.__enter__() or subxact.enter() * diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c index db14c5f8dae7f..f6509a4190282 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -14,7 +14,7 @@ #include "plpy_elog.h" #include "plpy_main.h" #include "plpy_typeio.h" -#include "plpython.h" +#include "plpy_util.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -723,7 +723,7 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1, dataptr_p, bitmap_p, bitmask_p); - PyList_SET_ITEM(list, i, sublist); + PyList_SetItem(list, i, sublist); } } else @@ -742,14 +742,14 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, if (bitmap && (*bitmap & bitmask) == 0) { Py_INCREF(Py_None); - PyList_SET_ITEM(list, i, Py_None); + PyList_SetItem(list, i, Py_None); } else { Datum itemvalue; itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen); - PyList_SET_ITEM(list, i, elm->func(elm, itemvalue)); + PyList_SetItem(list, i, elm->func(elm, itemvalue)); dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr); dataptr = (char *) att_align_nominal(dataptr, elm->typalign); } @@ -844,6 +844,9 @@ PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool inclu /* don't include unless requested */ if (!include_generated) continue; + /* never include virtual columns */ + if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + continue; } key = NameStr(attr->attname); diff --git a/src/pl/plpython/plpy_util.c b/src/pl/plpython/plpy_util.c index 22e2a599ad968..ef710aa371eac 100644 --- a/src/pl/plpython/plpy_util.c +++ b/src/pl/plpython/plpy_util.c @@ -9,8 +9,6 @@ #include "mb/pg_wchar.h" #include "plpy_elog.h" #include "plpy_util.h" -#include "plpython.h" -#include "utils/memutils.h" /* * Convert a Python unicode object to a Python string/bytes object in diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h index d929afefc33e8..118b3100840f6 100644 --- a/src/pl/plpython/plpython.h +++ b/src/pl/plpython/plpython.h @@ -2,7 +2,11 @@ * * plpython.h - Python as a procedural language for PostgreSQL * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Note: this file is #include'd by each of the sub-module header files + * (plpy_elog.h, etc). It's therefore unnecessary for any plpython *.c + * files to include it directly. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/pl/plpython/plpython.h @@ -19,6 +23,15 @@ #error Python.h must be included via plpython.h #endif +/* + * Enable Python Limited API + * + * XXX currently not enabled on MSVC because of build failures + */ +#if !defined(_MSC_VER) +#define Py_LIMITED_API 0x03020000 +#endif + /* * Pull in Python headers via a wrapper header, to control the scope of * the system_header pragma therein. @@ -29,9 +42,4 @@ #undef TEXTDOMAIN #define TEXTDOMAIN PG_TEXTDOMAIN("plpython") -/* - * Used throughout, so it's easier to just include it everywhere. - */ -#include "plpy_util.h" - #endif /* PLPYTHON_H */ diff --git a/src/pl/plpython/plpython_system.h b/src/pl/plpython/plpython_system.h index 036d339bf83d0..ace9fc631b224 100644 --- a/src/pl/plpython/plpython_system.h +++ b/src/pl/plpython/plpython_system.h @@ -7,7 +7,7 @@ * declarations should be put here. However, we do include some stuff * that is meant to prevent conflicts between our code and Python. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/pl/plpython/plpython_system.h diff --git a/src/pl/plpython/po/es.po b/src/pl/plpython/po/es.po index 8186ef8622b49..bae86f7219b13 100644 --- a/src/pl/plpython/po/es.po +++ b/src/pl/plpython/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: plpython (PostgreSQL) 16\n" +"Project-Id-Version: plpython (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:08+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:39+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -26,49 +26,49 @@ msgstr "" msgid "plpy.cursor expected a query or a plan" msgstr "plpy.cursor espera una consulta o un plan" -#: plpy_cursorobject.c:155 +#: plpy_cursorobject.c:154 #, c-format msgid "plpy.cursor takes a sequence as its second argument" msgstr "plpy.cursor lleva una secuencia como segundo argumento" -#: plpy_cursorobject.c:171 plpy_spi.c:205 +#: plpy_cursorobject.c:170 plpy_spi.c:204 #, c-format msgid "could not execute plan" msgstr "no se pudo ejecutar el plan" -#: plpy_cursorobject.c:174 plpy_spi.c:208 +#: plpy_cursorobject.c:173 plpy_spi.c:207 #, c-format msgid "Expected sequence of %d argument, got %d: %s" msgid_plural "Expected sequence of %d arguments, got %d: %s" msgstr[0] "Se esperaba una secuencia de %d argumento, se obtuvo %d: %s" msgstr[1] "Se esperaba una secuencia de %d argumentos, se obtuvo %d: %s" -#: plpy_cursorobject.c:321 +#: plpy_cursorobject.c:317 #, c-format msgid "iterating a closed cursor" msgstr "iterando un cursor cerrado" -#: plpy_cursorobject.c:329 plpy_cursorobject.c:395 +#: plpy_cursorobject.c:325 plpy_cursorobject.c:391 #, c-format msgid "iterating a cursor in an aborted subtransaction" msgstr "iterando un cursor en una subtransacción abortada" -#: plpy_cursorobject.c:387 +#: plpy_cursorobject.c:383 #, c-format msgid "fetch from a closed cursor" msgstr "haciendo «fetch» en un cursor cerrado" -#: plpy_cursorobject.c:430 plpy_spi.c:401 +#: plpy_cursorobject.c:426 plpy_spi.c:393 #, c-format msgid "query result has too many rows to fit in a Python list" msgstr "el resultado de la consulta tiene demasiados registros y no entran en una lista de Python" -#: plpy_cursorobject.c:482 +#: plpy_cursorobject.c:478 #, c-format msgid "closing a cursor in an aborted subtransaction" msgstr "cerrando un cursor en una subtransacción abortada" -#: plpy_elog.c:125 plpy_elog.c:126 plpy_plpymodule.c:530 +#: plpy_elog.c:122 plpy_elog.c:123 plpy_plpymodule.c:530 #, c-format msgid "%s" msgstr "%s" @@ -108,83 +108,83 @@ msgstr "procedimiento PL/Python no returnó None" msgid "PL/Python function with return type \"void\" did not return None" msgstr "función PL/Python con tipo de retorno «void» no retorna None" -#: plpy_exec.c:369 plpy_exec.c:393 +#: plpy_exec.c:246 +#, c-format +msgid "function returning record called in context that cannot accept type record" +msgstr "se llamó una función que retorna un registro en un contexto que no puede aceptarlo" + +#: plpy_exec.c:392 plpy_exec.c:416 #, c-format msgid "unexpected return value from trigger procedure" msgstr "valor de retorno no esperado desde el procedimiento disparador" -#: plpy_exec.c:370 +#: plpy_exec.c:393 #, c-format msgid "Expected None or a string." msgstr "Se esperaba None o una cadena." -#: plpy_exec.c:383 +#: plpy_exec.c:406 #, c-format msgid "PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored" msgstr "función de disparador de PL/Python retorno «MODIFY» en un disparador de tipo DELETE -- ignorado" -#: plpy_exec.c:394 +#: plpy_exec.c:417 #, c-format msgid "Expected None, \"OK\", \"SKIP\", or \"MODIFY\"." msgstr "Se esperaba None, «OK», «SKIP» o «MODIFY»." -#: plpy_exec.c:444 +#: plpy_exec.c:468 #, c-format msgid "PyList_SetItem() failed, while setting up arguments" msgstr "PyList_SetItem() falló, mientras se inicializaban los argumentos" -#: plpy_exec.c:448 +#: plpy_exec.c:472 #, c-format msgid "PyDict_SetItemString() failed, while setting up arguments" msgstr "PyDict_SetItemString() falló, mientras se inicializaban los argumentos" -#: plpy_exec.c:460 -#, c-format -msgid "function returning record called in context that cannot accept type record" -msgstr "se llamó una función que retorna un registro en un contexto que no puede aceptarlo" - -#: plpy_exec.c:677 +#: plpy_exec.c:701 #, c-format msgid "while creating return value" msgstr "mientras se creaba el valor de retorno" -#: plpy_exec.c:924 +#: plpy_exec.c:952 #, c-format msgid "TD[\"new\"] deleted, cannot modify row" msgstr "TD[\"new\"] borrado, no se puede modicar el registro" -#: plpy_exec.c:929 +#: plpy_exec.c:957 #, c-format msgid "TD[\"new\"] is not a dictionary" msgstr "TD[\"new\"] no es un diccionario" -#: plpy_exec.c:954 +#: plpy_exec.c:982 #, c-format msgid "TD[\"new\"] dictionary key at ordinal position %d is not a string" msgstr "el nombre del atributo de TD[\"new\"] en la posición %d no es una cadena" -#: plpy_exec.c:961 +#: plpy_exec.c:989 #, c-format msgid "key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row" msgstr "la llave «%s» en TD[\"new\"] no existe como columna en la fila disparadora" -#: plpy_exec.c:966 +#: plpy_exec.c:994 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "no se puede definir el atributo de sistema «%s»" -#: plpy_exec.c:971 +#: plpy_exec.c:999 #, c-format msgid "cannot set generated column \"%s\"" msgstr "no se puede definir el atributo generado «%s»" -#: plpy_exec.c:1029 +#: plpy_exec.c:1057 #, c-format msgid "while modifying trigger row" msgstr "mientras se modificaba la fila de disparador" # FIXME not very happy with this -#: plpy_exec.c:1087 +#: plpy_exec.c:1115 #, c-format msgid "forcibly aborting a subtransaction that has not been exited" msgstr "abortando una subtransacción que no se ha cerrado" @@ -273,27 +273,27 @@ msgstr "«%s» no es un argumento válido para esta función" msgid "invalid SQLSTATE code" msgstr "código SQLSTATE no válido" -#: plpy_procedure.c:225 +#: plpy_procedure.c:226 #, c-format msgid "trigger functions can only be called as triggers" msgstr "las funciones disparadoras sólo pueden ser llamadas como disparadores" -#: plpy_procedure.c:229 +#: plpy_procedure.c:230 #, c-format msgid "PL/Python functions cannot return type %s" msgstr "las funciones PL/Python no pueden retornar el tipo %s" -#: plpy_procedure.c:307 +#: plpy_procedure.c:308 #, c-format msgid "PL/Python functions cannot accept type %s" msgstr "la funciones PL/Python no pueden aceptar el tipo %s" -#: plpy_procedure.c:395 +#: plpy_procedure.c:396 #, c-format msgid "could not compile PL/Python function \"%s\"" msgstr "no se pudo compilar la función PL/Python «%s»" -#: plpy_procedure.c:398 +#: plpy_procedure.c:399 #, c-format msgid "could not compile anonymous PL/Python code block" msgstr "no se pudo compilar el bloque anónimo PL/Python" @@ -318,17 +318,17 @@ msgstr "plpy.prepare: el nombre de tipo en la posición %d no es una cadena" msgid "plpy.execute expected a query or a plan" msgstr "plpy.execute espera una consulta o un plan" -#: plpy_spi.c:189 +#: plpy_spi.c:188 #, c-format msgid "plpy.execute takes a sequence as its second argument" msgstr "plpy.execute lleva una secuencia como segundo argumento" -#: plpy_spi.c:297 +#: plpy_spi.c:289 #, c-format msgid "SPI_execute_plan failed: %s" msgstr "falló SPI_execute_plan: %s" -#: plpy_spi.c:339 +#: plpy_spi.c:331 #, c-format msgid "SPI_execute failed: %s" msgstr "falló SPI_execute: %s" diff --git a/src/pl/plpython/po/fr.po b/src/pl/plpython/po/fr.po index 2922a28b09a24..ec9faf0a957b1 100644 --- a/src/pl/plpython/po/fr.po +++ b/src/pl/plpython/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" "POT-Creation-Date: 2023-07-30 09:08+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" #: plpy_cursorobject.c:72 #, c-format @@ -390,7 +390,7 @@ msgstr "n'a pas pu créer une représentation chaîne de caractères de l'objet #: plpy_typeio.c:1060 #, c-format msgid "could not convert Python object into cstring: Python string representation appears to contain null bytes" -msgstr "n'a pas pu convertir l'objet Python en csting : la représentation de la chaîne Python contient des octets nuls" +msgstr "n'a pas pu convertir l'objet Python en cstring : la représentation de la chaîne Python contient des octets nuls" #: plpy_typeio.c:1157 #, c-format @@ -417,7 +417,7 @@ msgstr "le nombre de dimensions du tableau dépasse le maximum autorisé (%d)" #: plpy_typeio.c:1329 #, c-format msgid "malformed record literal: \"%s\"" -msgstr "enregistrement litéral invalide : « %s »" +msgstr "enregistrement littéral invalide : « %s »" #: plpy_typeio.c:1330 #, c-format @@ -469,122 +469,3 @@ msgstr "n'a pas pu convertir l'objet Unicode Python en octets" #, c-format msgid "could not extract bytes from encoded string" msgstr "n'a pas pu extraire les octets de la chaîne encodée" - -#~ msgid "PL/Python does not support conversion to arrays of row types." -#~ msgstr "PL/Python ne supporte pas les conversions vers des tableaux de types row." - -#~ msgid "PL/Python function \"%s\" could not execute plan" -#~ msgstr "la fonction PL/python « %s » n'a pas pu exécuter un plan" - -#~ msgid "PL/Python function \"%s\" failed" -#~ msgstr "échec de la fonction PL/python « %s »" - -#~ msgid "PL/Python only supports one-dimensional arrays." -#~ msgstr "PL/Python supporte seulement les tableaux uni-dimensionnels." - -#~ msgid "PL/Python: %s" -#~ msgstr "PL/python : %s" - -#~ msgid "PyCObject_AsVoidPtr() failed" -#~ msgstr "échec de PyCObject_AsVoidPtr()" - -#~ msgid "PyCObject_FromVoidPtr() failed" -#~ msgstr "échec de PyCObject_FromVoidPtr()" - -#~ msgid "Python major version mismatch in session" -#~ msgstr "Différence de version majeure de Python dans la session" - -#~ msgid "Start a new session to use a different Python major version." -#~ msgstr "" -#~ "Lancez une nouvelle session pour utiliser une version majeure différente de\n" -#~ "Python." - -#~ msgid "This session has previously used Python major version %d, and it is now attempting to use Python major version %d." -#~ msgstr "" -#~ "Cette session a auparavant utilisé la version majeure %d de Python et elle\n" -#~ "essaie maintenant d'utiliser la version majeure %d." - -#, c-format -#~ msgid "To construct a multidimensional array, the inner sequences must all have the same length." -#~ msgstr "Pour construire un tableau multidimensionnel, les séquences internes doivent toutes avoir la même longueur." - -#, c-format -#~ msgid "array size exceeds the maximum allowed" -#~ msgstr "la taille du tableau dépasse le maximum permis" - -#~ msgid "cannot convert multidimensional array to Python list" -#~ msgstr "ne peut pas convertir un tableau multidimensionnel en liste Python" - -#~ msgid "could not compute string representation of Python object in PL/Python function \"%s\" while modifying trigger row" -#~ msgstr "" -#~ "n'a pas pu traiter la représentation de la chaîne d'un objet Python dans\n" -#~ "la fonction PL/Python « %s » lors de la modification de la ligne du trigger" - -#~ msgid "could not create exception \"%s\"" -#~ msgstr "n'a pas pu créer l'exception « %s »" - -#~ msgid "could not create globals" -#~ msgstr "n'a pas pu créer les globales" - -#~ msgid "could not create new Python list" -#~ msgstr "n'a pas pu créer la nouvelle liste Python" - -#~ msgid "could not create new dictionary" -#~ msgstr "n'a pas pu créer le nouveau dictionnaire" - -#~ msgid "could not create new dictionary while building trigger arguments" -#~ msgstr "" -#~ "n'a pas pu créer un nouveau dictionnaire lors de la construction des\n" -#~ "arguments du trigger" - -#~ msgid "could not create procedure cache" -#~ msgstr "n'a pas pu créer le cache de procédure" - -#~ msgid "could not create string representation of Python object in PL/Python function \"%s\" while creating return value" -#~ msgstr "" -#~ "n'a pas pu créer la représentation en chaîne de caractère de l'objet\n" -#~ "Python dans la fonction PL/python « %s » lors de la création de la valeur\n" -#~ "de retour" - -#~ msgid "could not create the base SPI exceptions" -#~ msgstr "n'a pas pu créer les exceptions SPI de base" - -#~ msgid "invalid arguments for plpy.prepare" -#~ msgstr "arguments invalides pour plpy.prepare" - -#~ msgid "multidimensional arrays must have array expressions with matching dimensions. PL/Python function return value has sequence length %d while expected %d" -#~ msgstr "" -#~ "les tableaux multidimensionnels doivent avoir des expressions de tableaux\n" -#~ "avec des dimensions correspondantes. La valeur de retour de la fonction\n" -#~ "PL/Python a une longueur de séquence %d alors que %d est attendue" - -#~ msgid "out of memory" -#~ msgstr "mémoire épuisée" - -#~ msgid "plan.status takes no arguments" -#~ msgstr "plan.status ne prends pas d'arguments" - -#~ msgid "plpy.prepare does not support composite types" -#~ msgstr "plpy.prepare ne supporte pas les types composites" - -#~ msgid "the message is already specified" -#~ msgstr "le message est déjà spécifié" - -#~ msgid "transaction aborted" -#~ msgstr "transaction annulée" - -#~ msgid "unrecognized error in PLy_spi_execute_fetch_result" -#~ msgstr "erreur inconnue dans PLy_spi_execute_fetch_result" - -#~ msgid "unrecognized error in PLy_spi_execute_plan" -#~ msgstr "erreur inconnue dans PLy_spi_execute_plan" - -#~ msgid "unrecognized error in PLy_spi_execute_query" -#~ msgstr "erreur inconnue dans PLy_spi_execute_query" - -#~ msgid "unrecognized error in PLy_spi_prepare" -#~ msgstr "erreur inconnue dans PLy_spi_prepare" - -#, c-format -#~ msgid "wrong length of inner sequence: has length %d, but %d was expected" -#~ msgstr "mauvaise longueur de la séquence interne : a une longueur %d, mais %d était attendu" diff --git a/src/pl/plpython/po/meson.build b/src/pl/plpython/po/meson.build index ce93b43d682de..1843641e1990e 100644 --- a/src/pl/plpython/po/meson.build +++ b/src/pl/plpython/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('plpython-' + pg_version_major.to_string())] diff --git a/src/pl/plpython/po/ru.po b/src/pl/plpython/po/ru.po index c8ba4ad1a3413..0b57951c61093 100644 --- a/src/pl/plpython/po/ru.po +++ b/src/pl/plpython/po/ru.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: plpython (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-05-04 10:36+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" "PO-Revision-Date: 2019-08-29 15:42+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" @@ -22,17 +22,17 @@ msgstr "" msgid "plpy.cursor expected a query or a plan" msgstr "plpy.cursor ожидает запрос или план" -#: plpy_cursorobject.c:155 +#: plpy_cursorobject.c:154 #, c-format msgid "plpy.cursor takes a sequence as its second argument" msgstr "plpy.cursor принимает в качестве второго аргумента последовательность" -#: plpy_cursorobject.c:171 plpy_spi.c:205 +#: plpy_cursorobject.c:170 plpy_spi.c:204 #, c-format msgid "could not execute plan" msgstr "нельзя выполнить план" -#: plpy_cursorobject.c:174 plpy_spi.c:208 +#: plpy_cursorobject.c:173 plpy_spi.c:207 #, c-format msgid "Expected sequence of %d argument, got %d: %s" msgid_plural "Expected sequence of %d arguments, got %d: %s" @@ -40,28 +40,28 @@ msgstr[0] "Ожидалась последовательность из %d ар msgstr[1] "Ожидалась последовательность из %d аргументов, получено %d: %s" msgstr[2] "Ожидалась последовательность из %d аргументов, получено %d: %s" -#: plpy_cursorobject.c:321 +#: plpy_cursorobject.c:317 #, c-format msgid "iterating a closed cursor" msgstr "перемещение закрытого курсора" -#: plpy_cursorobject.c:329 plpy_cursorobject.c:395 +#: plpy_cursorobject.c:325 plpy_cursorobject.c:391 #, c-format msgid "iterating a cursor in an aborted subtransaction" msgstr "перемещение курсора в прерванной подтранзакции" -#: plpy_cursorobject.c:387 +#: plpy_cursorobject.c:383 #, c-format msgid "fetch from a closed cursor" msgstr "выборка из закрытого курсора" -#: plpy_cursorobject.c:430 plpy_spi.c:401 +#: plpy_cursorobject.c:426 plpy_spi.c:393 #, c-format msgid "query result has too many rows to fit in a Python list" msgstr "" "результат запроса содержит слишком много строк для передачи в списке Python" -#: plpy_cursorobject.c:482 +#: plpy_cursorobject.c:478 #, c-format msgid "closing a cursor in an aborted subtransaction" msgstr "закрытие курсора в прерванной подтранзакции" @@ -111,17 +111,24 @@ msgstr "процедура PL/Python вернула не None" msgid "PL/Python function with return type \"void\" did not return None" msgstr "функция PL/Python с типом результата \"void\" вернула не None" -#: plpy_exec.c:369 plpy_exec.c:393 +#: plpy_exec.c:246 +#, c-format +msgid "" +"function returning record called in context that cannot accept type record" +msgstr "" +"функция, возвращающая запись, вызвана в контексте, не допускающем этот тип" + +#: plpy_exec.c:392 plpy_exec.c:416 #, c-format msgid "unexpected return value from trigger procedure" msgstr "триггерная процедура вернула недопустимое значение" -#: plpy_exec.c:370 +#: plpy_exec.c:393 #, c-format msgid "Expected None or a string." msgstr "Ожидалось None или строка." -#: plpy_exec.c:383 +#: plpy_exec.c:406 #, c-format msgid "" "PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored" @@ -129,49 +136,42 @@ msgstr "" "триггерная функция PL/Python вернула \"MODIFY\" в триггере DELETE -- " "игнорируется" -#: plpy_exec.c:394 +#: plpy_exec.c:417 #, c-format msgid "Expected None, \"OK\", \"SKIP\", or \"MODIFY\"." msgstr "Ожидалось None, \"OK\", \"SKIP\" или \"MODIFY\"." -#: plpy_exec.c:444 +#: plpy_exec.c:468 #, c-format msgid "PyList_SetItem() failed, while setting up arguments" msgstr "ошибка в PyList_SetItem() при настройке аргументов" -#: plpy_exec.c:448 +#: plpy_exec.c:472 #, c-format msgid "PyDict_SetItemString() failed, while setting up arguments" msgstr "ошибка в PyDict_SetItemString() при настройке аргументов" -#: plpy_exec.c:460 -#, c-format -msgid "" -"function returning record called in context that cannot accept type record" -msgstr "" -"функция, возвращающая запись, вызвана в контексте, не допускающем этот тип" - -#: plpy_exec.c:677 +#: plpy_exec.c:701 #, c-format msgid "while creating return value" msgstr "при создании возвращаемого значения" -#: plpy_exec.c:928 +#: plpy_exec.c:952 #, c-format msgid "TD[\"new\"] deleted, cannot modify row" msgstr "элемент TD[\"new\"] удалён -- изменить строку нельзя" -#: plpy_exec.c:933 +#: plpy_exec.c:957 #, c-format msgid "TD[\"new\"] is not a dictionary" msgstr "TD[\"new\"] - не словарь" -#: plpy_exec.c:958 +#: plpy_exec.c:982 #, c-format msgid "TD[\"new\"] dictionary key at ordinal position %d is not a string" msgstr "ключ словаря TD[\"new\"] с порядковым номером %d не является строкой" -#: plpy_exec.c:965 +#: plpy_exec.c:989 #, c-format msgid "" "key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering " @@ -180,22 +180,22 @@ msgstr "" "ключу \"%s\", найденному в TD[\"new\"], не соответствует столбец в строке, " "обрабатываемой триггером" -#: plpy_exec.c:970 +#: plpy_exec.c:994 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "присвоить значение системному атрибуту \"%s\" нельзя" -#: plpy_exec.c:975 +#: plpy_exec.c:999 #, c-format msgid "cannot set generated column \"%s\"" msgstr "присвоить значение генерируемому столбцу \"%s\" нельзя" -#: plpy_exec.c:1033 +#: plpy_exec.c:1057 #, c-format msgid "while modifying trigger row" msgstr "при изменении строки в триггере" -#: plpy_exec.c:1091 +#: plpy_exec.c:1115 #, c-format msgid "forcibly aborting a subtransaction that has not been exited" msgstr "принудительное прерывание незавершённой подтранзакции" @@ -284,27 +284,27 @@ msgstr "'%s' - недопустимое ключевое слово (аргум msgid "invalid SQLSTATE code" msgstr "неверный код SQLSTATE" -#: plpy_procedure.c:225 +#: plpy_procedure.c:226 #, c-format msgid "trigger functions can only be called as triggers" msgstr "триггерные функции могут вызываться только в триггерах" -#: plpy_procedure.c:229 +#: plpy_procedure.c:230 #, c-format msgid "PL/Python functions cannot return type %s" msgstr "функции PL/Python не могут возвращать тип %s" -#: plpy_procedure.c:307 +#: plpy_procedure.c:308 #, c-format msgid "PL/Python functions cannot accept type %s" msgstr "функции PL/Python не могут принимать тип %s" -#: plpy_procedure.c:395 +#: plpy_procedure.c:396 #, c-format msgid "could not compile PL/Python function \"%s\"" msgstr "не удалось скомпилировать функцию PL/Python \"%s\"" -#: plpy_procedure.c:398 +#: plpy_procedure.c:399 #, c-format msgid "could not compile anonymous PL/Python code block" msgstr "не удалось скомпилировать анонимный блок кода PL/Python" @@ -329,17 +329,17 @@ msgstr "plpy.prepare: имя типа с порядковым номером %d msgid "plpy.execute expected a query or a plan" msgstr "plpy.execute ожидает запрос или план" -#: plpy_spi.c:189 +#: plpy_spi.c:188 #, c-format msgid "plpy.execute takes a sequence as its second argument" msgstr "plpy.execute принимает в качестве второго аргумента последовательность" -#: plpy_spi.c:297 +#: plpy_spi.c:289 #, c-format msgid "SPI_execute_plan failed: %s" msgstr "ошибка в SPI_execute_plan: %s" -#: plpy_spi.c:339 +#: plpy_spi.c:331 #, c-format msgid "SPI_execute failed: %s" msgstr "ошибка в SPI_execute: %s" diff --git a/src/pl/plpython/po/sv.po b/src/pl/plpython/po/sv.po index 8642c20402beb..54f3db92ff479 100644 --- a/src/pl/plpython/po/sv.po +++ b/src/pl/plpython/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for plpython # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 16\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-02 08:08+0000\n" -"PO-Revision-Date: 2023-08-02 12:03+0200\n" +"POT-Creation-Date: 2024-07-13 15:38+0000\n" +"PO-Revision-Date: 2024-07-13 18:15+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -64,7 +64,7 @@ msgstr "frågeresultet har för många rader för att få plats i en Python-list msgid "closing a cursor in an aborted subtransaction" msgstr "stänger en markör i en avbruten subtransaktion" -#: plpy_elog.c:125 plpy_elog.c:126 plpy_plpymodule.c:530 +#: plpy_elog.c:122 plpy_elog.c:123 plpy_plpymodule.c:530 #, c-format msgid "%s" msgstr "%s" @@ -104,82 +104,82 @@ msgstr "PL/Python-procedur returnerade inte None" msgid "PL/Python function with return type \"void\" did not return None" msgstr "PL/Python-funktion med returtyp \"void\" returnerade inte None" -#: plpy_exec.c:369 plpy_exec.c:393 +#: plpy_exec.c:246 +#, c-format +msgid "function returning record called in context that cannot accept type record" +msgstr "en funktion med post som värde anropades i sammanhang där poster inte kan godtagas." + +#: plpy_exec.c:392 plpy_exec.c:416 #, c-format msgid "unexpected return value from trigger procedure" msgstr "oväntat returvärde från triggerprocedur" -#: plpy_exec.c:370 +#: plpy_exec.c:393 #, c-format msgid "Expected None or a string." msgstr "Förväntade None eller en sträng." -#: plpy_exec.c:383 +#: plpy_exec.c:406 #, c-format msgid "PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored" msgstr "PL/Python-triggerfunktion returnerade \"MODIFY\" i en DELETE-trigger -- ignorerad" -#: plpy_exec.c:394 +#: plpy_exec.c:417 #, c-format msgid "Expected None, \"OK\", \"SKIP\", or \"MODIFY\"." msgstr "Förväntade None, \"OK\", \"SKIP\" eller \"MODIFY\"." -#: plpy_exec.c:444 +#: plpy_exec.c:468 #, c-format msgid "PyList_SetItem() failed, while setting up arguments" msgstr "PyList_SetItem() misslyckades vid uppsättning av argument" -#: plpy_exec.c:448 +#: plpy_exec.c:472 #, c-format msgid "PyDict_SetItemString() failed, while setting up arguments" msgstr "PyDict_SetItemString() misslyckades vid uppsättning av argument" -#: plpy_exec.c:460 -#, c-format -msgid "function returning record called in context that cannot accept type record" -msgstr "en funktion med post som värde anropades i sammanhang där poster inte kan godtagas." - -#: plpy_exec.c:677 +#: plpy_exec.c:701 #, c-format msgid "while creating return value" msgstr "vid skapande av returvärde" -#: plpy_exec.c:924 +#: plpy_exec.c:952 #, c-format msgid "TD[\"new\"] deleted, cannot modify row" msgstr "TD[\"new\"] raderad, kan inte modifiera rad" -#: plpy_exec.c:929 +#: plpy_exec.c:957 #, c-format msgid "TD[\"new\"] is not a dictionary" msgstr "TD[\"new\"] är inte en dictionary" -#: plpy_exec.c:954 +#: plpy_exec.c:982 #, c-format msgid "TD[\"new\"] dictionary key at ordinal position %d is not a string" msgstr "TD[\"new\"] dictionary-nyckel vid numerisk position %d är inte en sträng" -#: plpy_exec.c:961 +#: plpy_exec.c:989 #, c-format msgid "key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row" msgstr "nyckel \"%s\" hittad i TD[\"new\"] finns inte som en kolumn i den triggande raden" -#: plpy_exec.c:966 +#: plpy_exec.c:994 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "kan inte sätta systemattribut \"%s\"" -#: plpy_exec.c:971 +#: plpy_exec.c:999 #, c-format msgid "cannot set generated column \"%s\"" msgstr "kan inte sätta genererad kolumn \"%s\"" -#: plpy_exec.c:1029 +#: plpy_exec.c:1057 #, c-format msgid "while modifying trigger row" msgstr "vid modifiering av triggerrad" -#: plpy_exec.c:1087 +#: plpy_exec.c:1115 #, c-format msgid "forcibly aborting a subtransaction that has not been exited" msgstr "tvingar avbrytande av subtransaktion som inte har avslutats" @@ -268,27 +268,27 @@ msgstr "'%s' är ett ogiltigt nyckelordsargument för denna funktion" msgid "invalid SQLSTATE code" msgstr "ogiltig SQLSTATE-kod" -#: plpy_procedure.c:225 +#: plpy_procedure.c:226 #, c-format msgid "trigger functions can only be called as triggers" msgstr "Triggningsfunktioner kan bara anropas vid triggning." -#: plpy_procedure.c:229 +#: plpy_procedure.c:230 #, c-format msgid "PL/Python functions cannot return type %s" msgstr "PL/Python-funktioner kan inte returnera typ %s" -#: plpy_procedure.c:307 +#: plpy_procedure.c:308 #, c-format msgid "PL/Python functions cannot accept type %s" msgstr "PL/Python-funktioner kan inte ta emot typ %s" -#: plpy_procedure.c:395 +#: plpy_procedure.c:396 #, c-format msgid "could not compile PL/Python function \"%s\"" msgstr "kunde inte kompilera PL/Python-funktion \"%s\"" -#: plpy_procedure.c:398 +#: plpy_procedure.c:399 #, c-format msgid "could not compile anonymous PL/Python code block" msgstr "kunde inte kompilera anonymt PL/Python-kodblock" @@ -447,15 +447,3 @@ msgstr "kunde inte konvertera Python-unicode-objekt till bytes" #, c-format msgid "could not extract bytes from encoded string" msgstr "kunde inte extrahera bytes från kodad sträng" - -#, c-format -#~ msgid "To construct a multidimensional array, the inner sequences must all have the same length." -#~ msgstr "För att skapa en multidimensionell array så skall alla de inre sekvenserna ha samma längd." - -#, c-format -#~ msgid "array size exceeds the maximum allowed" -#~ msgstr "array-storlek överskrider maximalt tillåtna" - -#, c-format -#~ msgid "wrong length of inner sequence: has length %d, but %d was expected" -#~ msgstr "fel längd på inre sekvens: har längd %d, men %d förväntades" diff --git a/src/pl/plpython/po/uk.po b/src/pl/plpython/po/uk.po index 0388016c9ceee..22ef7bc349bf0 100644 --- a/src/pl/plpython/po/uk.po +++ b/src/pl/plpython/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-12-17 22:08+0000\n" -"PO-Revision-Date: 2023-12-20 11:53\n" +"POT-Creation-Date: 2024-08-31 06:09+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,8 +14,8 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_16_STABLE/plpython.pot\n" -"X-Crowdin-File-ID: 933\n" +"X-Crowdin-File: /REL_17_STABLE/plpython.pot\n" +"X-Crowdin-File-ID: 1014\n" #: plpy_cursorobject.c:72 #, c-format @@ -106,82 +106,82 @@ msgstr "процедура PL/Python не повернула None" msgid "PL/Python function with return type \"void\" did not return None" msgstr "PL/Python функція з типом результату \"void\" не повернули None" -#: plpy_exec.c:369 plpy_exec.c:393 +#: plpy_exec.c:246 +#, c-format +msgid "function returning record called in context that cannot accept type record" +msgstr "функція, що повертає набір, викликана у контексті, що не приймає тип запис" + +#: plpy_exec.c:392 plpy_exec.c:416 #, c-format msgid "unexpected return value from trigger procedure" msgstr "неочікуване значення процедури тригера" -#: plpy_exec.c:370 +#: plpy_exec.c:393 #, c-format msgid "Expected None or a string." msgstr "Очікувалось None або рядок." -#: plpy_exec.c:383 +#: plpy_exec.c:406 #, c-format msgid "PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored" msgstr "Тригерна функція PL/Python повернула \"MODIFY\" в тригері DELETE -- проігноровано" -#: plpy_exec.c:394 +#: plpy_exec.c:417 #, c-format msgid "Expected None, \"OK\", \"SKIP\", or \"MODIFY\"." msgstr "Очікувалось None, \"OK\", \"SKIP\" або \"MODIFY\"." -#: plpy_exec.c:444 +#: plpy_exec.c:468 #, c-format msgid "PyList_SetItem() failed, while setting up arguments" msgstr "помилка PyList_SetItem() під час встановлення параметрів" -#: plpy_exec.c:448 +#: plpy_exec.c:472 #, c-format msgid "PyDict_SetItemString() failed, while setting up arguments" msgstr "помилка PyDict_SetItemString() під час встановлення параметрів" -#: plpy_exec.c:460 -#, c-format -msgid "function returning record called in context that cannot accept type record" -msgstr "функція, що повертає набір, викликана у контексті, що не приймає тип запис" - -#: plpy_exec.c:677 +#: plpy_exec.c:701 #, c-format msgid "while creating return value" msgstr "під час створення значення результату" -#: plpy_exec.c:924 +#: plpy_exec.c:952 #, c-format msgid "TD[\"new\"] deleted, cannot modify row" msgstr "TD[\"new\"] видалено, неможливо змінити рядок" -#: plpy_exec.c:929 +#: plpy_exec.c:957 #, c-format msgid "TD[\"new\"] is not a dictionary" msgstr "TD[\"new\"] не є словником" -#: plpy_exec.c:954 +#: plpy_exec.c:982 #, c-format msgid "TD[\"new\"] dictionary key at ordinal position %d is not a string" msgstr "ключ словника TD[\"new\"] на порядковий позиції %d не є рядком" -#: plpy_exec.c:961 +#: plpy_exec.c:989 #, c-format msgid "key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row" msgstr "ключ \"%s\" знайдений у TD[\"new\"] не існує як стовпець у рядку тригера" -#: plpy_exec.c:966 +#: plpy_exec.c:994 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "не вдалося встановити системний атрибут \"%s\"" -#: plpy_exec.c:971 +#: plpy_exec.c:999 #, c-format msgid "cannot set generated column \"%s\"" msgstr "неможливо оновити згенерований стовпець \"%s\"" -#: plpy_exec.c:1029 +#: plpy_exec.c:1057 #, c-format msgid "while modifying trigger row" msgstr "під час зміни рядка тригера" -#: plpy_exec.c:1087 +#: plpy_exec.c:1115 #, c-format msgid "forcibly aborting a subtransaction that has not been exited" msgstr "примусове переривання субтранзакції, яка не вийшла" @@ -270,27 +270,27 @@ msgstr "'%s' є неприпустимим ключовим словом-арг msgid "invalid SQLSTATE code" msgstr "неприпустимий код SQLSTATE" -#: plpy_procedure.c:225 +#: plpy_procedure.c:226 #, c-format msgid "trigger functions can only be called as triggers" msgstr "тригер-функція може викликатися лише як тригер" -#: plpy_procedure.c:229 +#: plpy_procedure.c:230 #, c-format msgid "PL/Python functions cannot return type %s" msgstr "PL/Python функції не можуть повернути тип %s" -#: plpy_procedure.c:307 +#: plpy_procedure.c:308 #, c-format msgid "PL/Python functions cannot accept type %s" msgstr "PL/Python функції не можуть прийняти тип %s" -#: plpy_procedure.c:395 +#: plpy_procedure.c:396 #, c-format msgid "could not compile PL/Python function \"%s\"" msgstr "не вдалося скомпілювати функцію PL/Python \"%s\"" -#: plpy_procedure.c:398 +#: plpy_procedure.c:399 #, c-format msgid "could not compile anonymous PL/Python code block" msgstr "не вдалося скомпілювати анонімні коди блоку PL/Python" diff --git a/src/pl/plpython/po/zh_CN.po b/src/pl/plpython/po/zh_CN.po index 264d4f52f6f4b..50b34ebe847dd 100644 --- a/src/pl/plpython/po/zh_CN.po +++ b/src/pl/plpython/po/zh_CN.po @@ -1,43 +1,43 @@ # LANGUAGE message translation file for plpython # Copyright (C) 2010 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# FIRST AUTHOR , 2010. +# Dianjin Wang , 2024 # msgid "" msgstr "" -"Project-Id-Version: plpython (PostgreSQL) 14\n" +"Project-Id-Version: plpython (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 05:38+0000\n" -"PO-Revision-Date: 2021-08-16 18:00+0800\n" -"Last-Translator: Jie Zhang \n" +"POT-Creation-Date: 2024-09-13 22:40+0000\n" +"PO-Revision-Date: 2024-09-14 14:12+0800\n" +"Last-Translator: Dianjin Wang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 1.5.7\n" +"X-Generator: Poedit 3.4.4\n" #: plpy_cursorobject.c:72 #, c-format msgid "plpy.cursor expected a query or a plan" -msgstr "plpy.cursor期望一个查询或一个计划" +msgstr "plpy.cursor 期望一个查询或一个计划" #: plpy_cursorobject.c:155 #, c-format msgid "plpy.cursor takes a sequence as its second argument" -msgstr "plpy.cursor将一个序列作为它的第二个参数" +msgstr "plpy.cursor 将一个序列作为它的第二个参数" -#: plpy_cursorobject.c:171 plpy_spi.c:207 +#: plpy_cursorobject.c:171 plpy_spi.c:205 #, c-format msgid "could not execute plan" msgstr "无法执行计划" -#: plpy_cursorobject.c:174 plpy_spi.c:210 +#: plpy_cursorobject.c:174 plpy_spi.c:208 #, c-format msgid "Expected sequence of %d argument, got %d: %s" msgid_plural "Expected sequence of %d arguments, got %d: %s" -msgstr[0] "期望%d序列参数,但是得到%d: %s" +msgstr[0] "期望 %d 参数序列, 但是得到 %d: %s" #: plpy_cursorobject.c:321 #, c-format @@ -54,17 +54,17 @@ msgstr "在终止的子事务里遍历一个游标" msgid "fetch from a closed cursor" msgstr "从关闭的游标里获取结果" -#: plpy_cursorobject.c:430 plpy_spi.c:403 +#: plpy_cursorobject.c:430 plpy_spi.c:401 #, c-format msgid "query result has too many rows to fit in a Python list" -msgstr "查询结果中的行太多,无法放在一个Python列表中" +msgstr "查询结果中的行太多,无法放在一个 Python 列表中" #: plpy_cursorobject.c:482 #, c-format msgid "closing a cursor in an aborted subtransaction" msgstr "在终止的子事务里关闭一个游标" -#: plpy_elog.c:125 plpy_elog.c:126 plpy_plpymodule.c:548 +#: plpy_elog.c:122 plpy_elog.c:123 plpy_plpymodule.c:530 #, c-format msgid "%s" msgstr "%s" @@ -77,221 +77,221 @@ msgstr "不支持集合函数返回模式" #: plpy_exec.c:140 #, c-format msgid "PL/Python set-returning functions only support returning one value per call." -msgstr "PL/Python集合返回函数只支持在每次调用时返回一个值。" +msgstr "PL/Python 集合返回函数只支持在每次调用时返回一个值." #: plpy_exec.c:153 #, c-format msgid "returned object cannot be iterated" -msgstr "所返回的对象无法迭代" +msgstr "所返回的对象无法进行遍历" #: plpy_exec.c:154 #, c-format msgid "PL/Python set-returning functions must return an iterable object." -msgstr "PL/Python集合返回函数必须返回一个可迭代的对象." +msgstr "PL/Python 集合返回函数必须返回一个可遍历的对象." #: plpy_exec.c:168 #, c-format msgid "error fetching next item from iterator" -msgstr "当从迭代器中取回下一个成员时出现错误" +msgstr "当从迭代器中获取下一个成员时出现错误" #: plpy_exec.c:211 #, c-format msgid "PL/Python procedure did not return None" -msgstr "PL/Python过程没有返回None" +msgstr "PL/Python 过程没有返回 None" #: plpy_exec.c:215 #, c-format msgid "PL/Python function with return type \"void\" did not return None" -msgstr "返回类型为\"void\"的PL/Python函数不返回None" +msgstr "返回类型为 \"void\" 的 PL/Python 函数不返回 None" -#: plpy_exec.c:371 plpy_exec.c:397 +#: plpy_exec.c:246 +#, c-format +msgid "function returning record called in context that cannot accept type record" +msgstr "返回值类型是记录的函数在不接受使用记录类型的环境中调用" + +#: plpy_exec.c:392 plpy_exec.c:416 #, c-format msgid "unexpected return value from trigger procedure" msgstr "在触发器存储过程出现非期望的返回值" -#: plpy_exec.c:372 +#: plpy_exec.c:393 #, c-format msgid "Expected None or a string." -msgstr "期望空值或一个字符串" +msgstr "期望 None 或一个字符串." -#: plpy_exec.c:387 +#: plpy_exec.c:406 #, c-format msgid "PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored" -msgstr "在DELETE触发器中的PL/Python 触发器函数返回 \"MODIFY\" -- 忽略" +msgstr "在 DELETE 触发器中的 PL/Python 触发器函数返回 \"MODIFY\" -- 忽略" -#: plpy_exec.c:398 +#: plpy_exec.c:417 #, c-format msgid "Expected None, \"OK\", \"SKIP\", or \"MODIFY\"." -msgstr "期望None, \"OK\", \"SKIP\", 或\"MODIFY\"" +msgstr "期望 None, \"OK\", \"SKIP\", 或\"MODIFY”." -#: plpy_exec.c:443 +#: plpy_exec.c:468 #, c-format msgid "PyList_SetItem() failed, while setting up arguments" -msgstr "当设置参数的同时, 执行PyList_SetItem()失败" +msgstr "当设置参数的同时, 执行 PyList_SetItem() 失败" -#: plpy_exec.c:447 +#: plpy_exec.c:472 #, c-format msgid "PyDict_SetItemString() failed, while setting up arguments" -msgstr "当设置参数的同时, 执行PyDict_SetItemString()失败" - -#: plpy_exec.c:459 -#, c-format -msgid "function returning record called in context that cannot accept type record" -msgstr "返回值类型是记录的函数在不接受使用记录类型的环境中调用" +msgstr "当设置参数的同时, 执行 PyDict_SetItemString() 失败" -#: plpy_exec.c:676 +#: plpy_exec.c:701 #, c-format msgid "while creating return value" msgstr "同时在创建返回值" -#: plpy_exec.c:910 +#: plpy_exec.c:952 #, c-format msgid "TD[\"new\"] deleted, cannot modify row" msgstr "TD[\"new\"] 已删除,无法修改记录" -#: plpy_exec.c:915 +#: plpy_exec.c:957 #, c-format msgid "TD[\"new\"] is not a dictionary" -msgstr "TD[\"new\"]不是一个字典" +msgstr "TD[\"new\"] 不是一个字典" -#: plpy_exec.c:942 +#: plpy_exec.c:982 #, c-format msgid "TD[\"new\"] dictionary key at ordinal position %d is not a string" -msgstr "在顺序位置%d的TD[\"new\"]字典键值不是字符串" +msgstr "在顺序位置 %d 的 TD[\"new\"] 字典键值不是字符串" -#: plpy_exec.c:949 +#: plpy_exec.c:989 #, c-format msgid "key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row" -msgstr "在 TD[\"new\"]中找到的键 \"%s\"在正在触发的记录中不是作为列而存在." +msgstr "在 TD[\"new\"] 中找到的键 \"%s\" 在正在触发的记录中不是作为列而存在" -#: plpy_exec.c:954 +#: plpy_exec.c:994 #, c-format msgid "cannot set system attribute \"%s\"" -msgstr "不能设置系统属性\"%s\"" +msgstr "无法设置系统属性 \"%s\"" -#: plpy_exec.c:959 +#: plpy_exec.c:999 #, c-format msgid "cannot set generated column \"%s\"" msgstr "无法设置生成的列 \"%s\"" -#: plpy_exec.c:1017 +#: plpy_exec.c:1057 #, c-format msgid "while modifying trigger row" msgstr "同时正在修改触发器记录" -#: plpy_exec.c:1075 +#: plpy_exec.c:1115 #, c-format msgid "forcibly aborting a subtransaction that has not been exited" msgstr "强行终止一个还未退出的子事务" -#: plpy_main.c:121 +#: plpy_main.c:109 #, c-format msgid "multiple Python libraries are present in session" -msgstr "会话中存在多个Python库" +msgstr "会话中存在多个 Python 库" -#: plpy_main.c:122 +#: plpy_main.c:110 #, c-format msgid "Only one Python major version can be used in one session." -msgstr "一个会话中只能使用一个Python主版本." +msgstr "一个会话中只能使用一个 Python 主版本." -#: plpy_main.c:138 +#: plpy_main.c:122 #, c-format msgid "untrapped error in initialization" msgstr "在初始化过程中出现无法捕获的错误" -#: plpy_main.c:161 +#: plpy_main.c:145 #, c-format msgid "could not import \"__main__\" module" -msgstr "无法导入模块\"__main__\" " +msgstr "无法导入 \"__main__\" 模块" -#: plpy_main.c:170 +#: plpy_main.c:154 #, c-format msgid "could not initialize globals" msgstr "无法初始化全局变量" -#: plpy_main.c:393 +#: plpy_main.c:352 #, c-format msgid "PL/Python procedure \"%s\"" -msgstr "PL/Python过程\"%s\"" +msgstr "PL/Python 过程 \"%s\"" -#: plpy_main.c:396 +#: plpy_main.c:355 #, c-format msgid "PL/Python function \"%s\"" -msgstr "PL/Python函数\"%s\"" +msgstr "PL/Python 函数\"%s\"" -#: plpy_main.c:404 +#: plpy_main.c:363 #, c-format msgid "PL/Python anonymous code block" -msgstr "PL/Python匿名代码块" +msgstr "PL/Python 匿名代码块" -#: plpy_plpymodule.c:182 plpy_plpymodule.c:185 +#: plpy_plpymodule.c:168 plpy_plpymodule.c:171 #, c-format msgid "could not import \"plpy\" module" -msgstr "无法导入模块\"plpy\" " +msgstr "无法导入 \"plpy\" 模块" -#: plpy_plpymodule.c:200 +#: plpy_plpymodule.c:182 #, c-format msgid "could not create the spiexceptions module" -msgstr "无法创建spiexceptions模块" +msgstr "无法创建 spiexceptions 模块" -#: plpy_plpymodule.c:208 +#: plpy_plpymodule.c:190 #, c-format msgid "could not add the spiexceptions module" -msgstr "无法添加spiexceptions模块 " +msgstr "无法添加 spiexceptions 模块" -#: plpy_plpymodule.c:275 +#: plpy_plpymodule.c:257 #, c-format msgid "could not generate SPI exceptions" -msgstr "无法产生SPI异常" +msgstr "无法产生 SPI 异常" -#: plpy_plpymodule.c:443 +#: plpy_plpymodule.c:425 #, c-format msgid "could not unpack arguments in plpy.elog" -msgstr "无法解析plpy.elog中的参数" +msgstr "无法解包 plpy.elog 中的参数" -#: plpy_plpymodule.c:452 +#: plpy_plpymodule.c:434 msgid "could not parse error message in plpy.elog" -msgstr "无法解析在plpy.elog中的错误消息" +msgstr "无法解析 plpy.elog 中的错误消息" -#: plpy_plpymodule.c:469 +#: plpy_plpymodule.c:451 #, c-format msgid "argument 'message' given by name and position" -msgstr "由名称和位置提供的参数'message'" +msgstr "由名称和位置提供的参数 'message'" -#: plpy_plpymodule.c:496 +#: plpy_plpymodule.c:478 #, c-format msgid "'%s' is an invalid keyword argument for this function" -msgstr "对于这个函数,'%s'是一个无效的关键词参数" +msgstr "对于这个函数,'%s' 是一个无效的关键词参数" -#: plpy_plpymodule.c:507 plpy_plpymodule.c:513 +#: plpy_plpymodule.c:489 plpy_plpymodule.c:495 #, c-format msgid "invalid SQLSTATE code" -msgstr "无效的SQLSTATE代码" +msgstr "无效的 SQLSTATE 代码" -#: plpy_procedure.c:225 +#: plpy_procedure.c:226 #, c-format msgid "trigger functions can only be called as triggers" -msgstr "触发器函数只能以触发器的形式调用" +msgstr "触发器函数只能以触发器的形式被调用" -#: plpy_procedure.c:229 +#: plpy_procedure.c:230 #, c-format msgid "PL/Python functions cannot return type %s" -msgstr "PL/Python函数不能返回类型%s" +msgstr "PL/Python 函数不能返回类型 %s" -#: plpy_procedure.c:307 +#: plpy_procedure.c:308 #, c-format msgid "PL/Python functions cannot accept type %s" -msgstr "PL/Python函数不能接受类型%s" +msgstr "PL/Python 函数不能接受类型 %s" -#: plpy_procedure.c:397 +#: plpy_procedure.c:396 #, c-format msgid "could not compile PL/Python function \"%s\"" -msgstr "无法编译PL/Python函数\"%s\"" +msgstr "无法编译 PL/Python 函数 \"%s\"" -#: plpy_procedure.c:400 +#: plpy_procedure.c:399 #, c-format msgid "could not compile anonymous PL/Python code block" -msgstr "无法编译PL/Python中的匿名代码块" +msgstr "无法编译 PL/Python 中的匿名代码块" #: plpy_resultobject.c:117 plpy_resultobject.c:143 plpy_resultobject.c:169 #, c-format @@ -301,32 +301,32 @@ msgstr "命令没有产生结果集" #: plpy_spi.c:56 #, c-format msgid "second argument of plpy.prepare must be a sequence" -msgstr "plpy.prepare的第二个参数必须是一个序列" +msgstr "plpy.prepare 的第二个参数必须是一个序列" -#: plpy_spi.c:100 +#: plpy_spi.c:98 #, c-format msgid "plpy.prepare: type name at ordinal position %d is not a string" -msgstr "plpy.prepare: 在顺序位置%d的类型名称不是string" +msgstr "plpy.prepare: 在顺序位置 %d 的类型名称不是一个字符串" -#: plpy_spi.c:172 +#: plpy_spi.c:170 #, c-format msgid "plpy.execute expected a query or a plan" -msgstr "plpy.execute期望一个查询或一个计划" +msgstr "plpy.execute 期望一个查询或一个计划" -#: plpy_spi.c:191 +#: plpy_spi.c:189 #, c-format msgid "plpy.execute takes a sequence as its second argument" -msgstr "plpy.execute将一个序列作为它的第二个参数" +msgstr "plpy.execute 将一个序列作为它的第二个参数" -#: plpy_spi.c:299 +#: plpy_spi.c:297 #, c-format msgid "SPI_execute_plan failed: %s" -msgstr "执行SPI_execute_plan失败: %s" +msgstr "SPI_execute_plan 执行失败: %s" -#: plpy_spi.c:341 +#: plpy_spi.c:339 #, c-format msgid "SPI_execute failed: %s" -msgstr "SPI_execute执行失败: %s" +msgstr "SPI_execute 执行失败: %s" #: plpy_subxactobject.c:92 #, c-format @@ -348,112 +348,114 @@ msgstr "该子事务仍没有进入" msgid "there is no subtransaction to exit from" msgstr "没有子事务可以退出" -#: plpy_typeio.c:587 +#: plpy_typeio.c:588 #, c-format msgid "could not import a module for Decimal constructor" msgstr "无法为十进制构造函数导入模块" -#: plpy_typeio.c:591 +#: plpy_typeio.c:592 #, c-format msgid "no Decimal attribute in module" msgstr "模块中没有小数位属性" -#: plpy_typeio.c:597 +#: plpy_typeio.c:598 #, c-format msgid "conversion from numeric to Decimal failed" -msgstr "由numeric数值到Decimal小数转换失败" +msgstr "由 numeric 数值到 Decimal 小数转换失败" -#: plpy_typeio.c:911 +#: plpy_typeio.c:912 #, c-format msgid "could not create bytes representation of Python object" -msgstr "无法创建Python对象的字节表达式" +msgstr "无法创建 Python 对象的字节表达式" -#: plpy_typeio.c:1056 +#: plpy_typeio.c:1049 #, c-format msgid "could not create string representation of Python object" -msgstr "无法创建Python对象的字符串表达式" +msgstr "无法创建 Python 对象的字符串表达式" -#: plpy_typeio.c:1067 +#: plpy_typeio.c:1060 #, c-format msgid "could not convert Python object into cstring: Python string representation appears to contain null bytes" -msgstr "无法将Python对象转换为cstring: Python字符串表达式可能包含空字节" +msgstr "无法将 Python 对象转换为 cstring: Python 字符串表达式可能包含空字节" -#: plpy_typeio.c:1178 +#: plpy_typeio.c:1157 #, c-format -msgid "number of array dimensions exceeds the maximum allowed (%d)" -msgstr "数组的维数超过最大允许值(%d)" +msgid "return value of function with array return type is not a Python sequence" +msgstr "带有数组返回类型的函数返回值不是一个 Python 序列" -#: plpy_typeio.c:1183 +#: plpy_typeio.c:1202 #, c-format msgid "could not determine sequence length for function return value" msgstr "无法确定函数返回值的序列长度" -#: plpy_typeio.c:1188 plpy_typeio.c:1194 +#: plpy_typeio.c:1222 plpy_typeio.c:1237 plpy_typeio.c:1253 #, c-format -msgid "array size exceeds the maximum allowed" -msgstr "数组的大小超过了最大允许值" +msgid "multidimensional arrays must have array expressions with matching dimensions" +msgstr "多维数组必须有符合维度的数组表达式" -#: plpy_typeio.c:1222 +#: plpy_typeio.c:1227 #, c-format -msgid "return value of function with array return type is not a Python sequence" -msgstr "带有数组返回类型的函数返回值不是一个Python序列" - -#: plpy_typeio.c:1269 -#, c-format -msgid "wrong length of inner sequence: has length %d, but %d was expected" -msgstr "内部序列的长度错误:长度为%d,但应为%d" - -#: plpy_typeio.c:1271 -#, c-format -msgid "To construct a multidimensional array, the inner sequences must all have the same length." -msgstr "要构造多维数组,内部序列的长度必须相同." +msgid "number of array dimensions exceeds the maximum allowed (%d)" +msgstr "数组的维数超过最大允许值 (%d)" -#: plpy_typeio.c:1350 +#: plpy_typeio.c:1329 #, c-format msgid "malformed record literal: \"%s\"" msgstr "有缺陷的记录常量: \"%s\"" -#: plpy_typeio.c:1351 +#: plpy_typeio.c:1330 #, c-format msgid "Missing left parenthesis." -msgstr "缺少一个左括弧" +msgstr "缺少一个左括弧." -#: plpy_typeio.c:1352 plpy_typeio.c:1553 +#: plpy_typeio.c:1331 plpy_typeio.c:1532 #, c-format msgid "To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\"." -msgstr "要返回数组中的复合类型,请将复合类型作为Python元组返回,例如 \"[('foo',)]\"." +msgstr "要返回数组中的复合类型,请将复合类型作为 Python 元组返回,例如 \"[('foo',)]\"." -#: plpy_typeio.c:1399 +#: plpy_typeio.c:1378 #, c-format msgid "key \"%s\" not found in mapping" -msgstr "在映射中没有找到键\"%s\"" +msgstr "在映射中没有找到键 \"%s\"" -#: plpy_typeio.c:1400 +#: plpy_typeio.c:1379 #, c-format msgid "To return null in a column, add the value None to the mapping with the key named after the column." -msgstr "为了在一列中返回空值, 需要在列的后面对带有已命名键的映射添加值None" +msgstr "为了在一列中返回空值, 需要在列的后面对带有已命名键的映射添加值 None." -#: plpy_typeio.c:1453 +#: plpy_typeio.c:1432 #, c-format msgid "length of returned sequence did not match number of columns in row" msgstr "所返回序列的长度与在记录中列的数量不匹配" -#: plpy_typeio.c:1551 +#: plpy_typeio.c:1530 #, c-format msgid "attribute \"%s\" does not exist in Python object" -msgstr "在Python对象中不存在属性\"%s\"" +msgstr "在 Python 对象中不存在属性 \"%s\"" -#: plpy_typeio.c:1554 +#: plpy_typeio.c:1533 #, c-format msgid "To return null in a column, let the returned object have an attribute named after column with value None." -msgstr "为了在一列中返回空值, 需要让返回的对象在带有值None的列后面的带有已命名属性" +msgstr "为了在一列中返回空值, 需要让返回的对象在带有值 None 的列后面的带有已命名属性." #: plpy_util.c:31 #, c-format msgid "could not convert Python Unicode object to bytes" -msgstr "无法将Python中以Unicode编码的对象转换为PostgreSQL服务器字节码" +msgstr "无法将 Python 中的 Unicode 编码对象转换为 PostgreSQL 服务器字节码" #: plpy_util.c:37 #, c-format msgid "could not extract bytes from encoded string" -msgstr "无法从已编码字符串里提取相应字节码值" +msgstr "无法从已编码字符串里提取相应字节" + +#, c-format +#~ msgid "To construct a multidimensional array, the inner sequences must all have the same length." +#~ msgstr "要构造多维数组,内部序列的长度必须相同." + +#, c-format +#~ msgid "array size exceeds the maximum allowed" +#~ msgstr "数组的大小超过了最大允许值" + +#, c-format +#~ msgid "wrong length of inner sequence: has length %d, but %d was expected" +#~ msgstr "内部序列的长度错误:长度为%d,但应为%d" diff --git a/src/pl/plpython/sql/plpython_setof.sql b/src/pl/plpython/sql/plpython_setof.sql index 4cfb10192c052..1a0472b7a3ba9 100644 --- a/src/pl/plpython/sql/plpython_setof.sql +++ b/src/pl/plpython/sql/plpython_setof.sql @@ -20,6 +20,13 @@ for i in range(count): return t $$ LANGUAGE plpython3u; +CREATE FUNCTION test_setof_as_set(count integer, content text) RETURNS SETOF text AS $$ +s = set() +for i in range(count): + s.add(content * (i + 1) if content is not None else None) +return s +$$ LANGUAGE plpython3u; + CREATE FUNCTION test_setof_as_iterator(count integer, content text) RETURNS SETOF text AS $$ class producer: def __init__ (self, icount, icontent): @@ -56,6 +63,11 @@ SELECT test_setof_as_tuple(1, 'tuple'); SELECT test_setof_as_tuple(2, 'tuple'); SELECT test_setof_as_tuple(2, null); +SELECT * FROM test_setof_as_set(0, 'set') ORDER BY 1; +SELECT * FROM test_setof_as_set(1, 'set') ORDER BY 1; +SELECT * FROM test_setof_as_set(2, 'set') ORDER BY 1; +SELECT * FROM test_setof_as_set(2, null) ORDER BY 1; + SELECT test_setof_as_iterator(0, 'list'); SELECT test_setof_as_iterator(1, 'list'); SELECT test_setof_as_iterator(2, 'list'); diff --git a/src/pl/plpython/sql/plpython_spi.sql b/src/pl/plpython/sql/plpython_spi.sql index fcd113acaa35c..00dcc8bb66937 100644 --- a/src/pl/plpython/sql/plpython_spi.sql +++ b/src/pl/plpython/sql/plpython_spi.sql @@ -218,12 +218,9 @@ assert len(res.fetch(3)) == 1 assert len(res.fetch(3)) == 0 assert len(res.fetch(3)) == 0 try: - # use next() or __next__(), the method name changed in + # use next() and not __next__(), the method name changed in # http://www.python.org/dev/peps/pep-3114/ - try: - res.next() - except AttributeError: - res.__next__() + next(res) except StopIteration: pass else: @@ -234,11 +231,7 @@ CREATE FUNCTION cursor_mix_next_and_fetch() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users order by fname") assert len(res.fetch(2)) == 2 -item = None -try: - item = res.next() -except AttributeError: - item = res.__next__() +item = next(res) assert item['fname'] == 'rick' assert len(res.fetch(2)) == 1 @@ -259,10 +252,7 @@ CREATE FUNCTION next_after_close() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users") res.close() try: - try: - res.next() - except AttributeError: - res.__next__() + next(res) except ValueError: pass else: @@ -273,10 +263,7 @@ CREATE FUNCTION cursor_fetch_next_empty() RETURNS int AS $$ res = plpy.cursor("select fname, lname from users where false") assert len(res.fetch(1)) == 0 try: - try: - res.next() - except AttributeError: - res.__next__() + next(res) except StopIteration: pass else: diff --git a/src/pl/plpython/sql/plpython_trigger.sql b/src/pl/plpython/sql/plpython_trigger.sql index f6c2ef8d6a0c4..440549c0785da 100644 --- a/src/pl/plpython/sql/plpython_trigger.sql +++ b/src/pl/plpython/sql/plpython_trigger.sql @@ -69,7 +69,8 @@ CREATE TABLE trigger_test CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE FUNCTION trigger_data() RETURNS trigger LANGUAGE plpython3u AS $$ diff --git a/src/pl/tcl/expected/pltcl_trigger.out b/src/pl/tcl/expected/pltcl_trigger.out index 129abd5ba67b2..5298e50a5ec5e 100644 --- a/src/pl/tcl/expected/pltcl_trigger.out +++ b/src/pl/tcl/expected/pltcl_trigger.out @@ -63,7 +63,8 @@ CREATE TABLE trigger_test ( ALTER TABLE trigger_test DROP dropme; CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE VIEW trigger_test_view AS SELECT i, v FROM trigger_test; CREATE FUNCTION trigger_data() returns trigger language pltcl as $_$ @@ -647,7 +648,7 @@ NOTICE: OLD: {} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_before NOTICE: TG_op: INSERT -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -658,7 +659,7 @@ NOTICE: OLD: {} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_after NOTICE: TG_op: INSERT -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -670,7 +671,7 @@ NOTICE: OLD: {i: 1, j: 2} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_before NOTICE: TG_op: UPDATE -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -681,7 +682,7 @@ NOTICE: OLD: {i: 1, j: 2} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_after NOTICE: TG_op: UPDATE -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -693,7 +694,7 @@ NOTICE: OLD: {i: 11, j: 22} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_before NOTICE: TG_op: DELETE -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -704,7 +705,7 @@ NOTICE: OLD: {i: 11, j: 22} NOTICE: TG_level: ROW NOTICE: TG_name: show_trigger_data_trig_after NOTICE: TG_op: DELETE -NOTICE: TG_relatts: {{} i j} +NOTICE: TG_relatts: {{} i j k} NOTICE: TG_relid: bogus:12345 NOTICE: TG_table_name: trigger_test_generated NOTICE: TG_table_schema: public @@ -882,7 +883,7 @@ TRUNCATE trigger_test_generated; INSERT INTO trigger_test_generated (i) VALUES (1); ERROR: cannot set generated column "j" SELECT * FROM trigger_test_generated; - i | j ----+--- + i | j | k +---+---+--- (0 rows) diff --git a/src/pl/tcl/generate-pltclerrcodes.pl b/src/pl/tcl/generate-pltclerrcodes.pl index fcac4d00a6679..25da160c97f7d 100644 --- a/src/pl/tcl/generate-pltclerrcodes.pl +++ b/src/pl/tcl/generate-pltclerrcodes.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Generate the pltclerrcodes.h header from errcodes.txt -# Copyright (c) 2000-2024, PostgreSQL Global Development Group +# Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/pl/tcl/meson.build b/src/pl/tcl/meson.build index 2080304b22932..5ab40f7f1d8d9 100644 --- a/src/pl/tcl/meson.build +++ b/src/pl/tcl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not tcl_dep.found() subdir_done() diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 21b2b045933ea..73d660e88a693 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -25,13 +25,12 @@ #include "funcapi.h" #include "mb/pg_wchar.h" #include "miscadmin.h" -#include "nodes/makefuncs.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "pgstat.h" -#include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/regproc.h" @@ -40,7 +39,10 @@ #include "utils/typcache.h" -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "pltcl", + .version = PG_VERSION +); #define HAVE_TCL_VERSION(maj,min) \ ((TCL_MAJOR_VERSION > maj) || \ @@ -56,6 +58,10 @@ PG_MODULE_MAGIC; #define CONST86 #endif +#if !HAVE_TCL_VERSION(8,7) +typedef int Tcl_Size; +#endif + /* define our text domain for translations */ #undef TEXTDOMAIN #define TEXTDOMAIN PG_TEXTDOMAIN("pltcl") @@ -256,7 +262,7 @@ typedef struct } TclExceptionNameMap; static const TclExceptionNameMap exception_name_map[] = { -#include "pltclerrcodes.h" /* pgrminclude ignore */ +#include "pltclerrcodes.h" {NULL, 0} }; @@ -808,8 +814,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, !castNode(CallContext, fcinfo->context)->atomic; /* Connect to SPI manager */ - if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0); /* Find or compile the function */ prodesc = compile_pltcl_function(fcinfo->flinfo->fn_oid, InvalidOid, @@ -989,7 +994,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, HeapTuple tup; Tcl_Obj *resultObj; Tcl_Obj **resultObjv; - int resultObjc; + Tcl_Size resultObjc; /* * Set up data about result type. XXX it's tempting to consider @@ -1065,15 +1070,14 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, int tcl_rc; int i; const char *result; - int result_Objc; + Tcl_Size result_Objc; Tcl_Obj **result_Objv; int rc PG_USED_FOR_ASSERTS_ONLY; call_state->trigdata = trigdata; /* Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect(); /* Make transition tables visible to this SPI connection */ rc = SPI_register_trigger_data(trigdata); @@ -1321,8 +1325,7 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, int tcl_rc; /* Connect to SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect(); /* Find or compile the function */ prodesc = compile_pltcl_function(fcinfo->flinfo->fn_oid, @@ -2093,7 +2096,7 @@ pltcl_quote(ClientData cdata, Tcl_Interp *interp, char *tmp; const char *cp1; char *cp2; - int length; + Tcl_Size length; /************************************************************ * Check call syntax @@ -2287,7 +2290,7 @@ pltcl_returnnext(ClientData cdata, Tcl_Interp *interp, if (prodesc->fn_retistuple) { Tcl_Obj **rowObjv; - int rowObjc; + Tcl_Size rowObjc; /* result should be a list, so break it down */ if (Tcl_ListObjGetElements(interp, objv[1], &rowObjc, &rowObjv) == TCL_ERROR) @@ -2629,7 +2632,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { volatile MemoryContext plan_cxt = NULL; - int nargs; + Tcl_Size nargs; Tcl_Obj **argsObj; pltcl_query_desc *qdesc; int i; @@ -2767,7 +2770,7 @@ pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp, const char *arrayname = NULL; Tcl_Obj *loop_body = NULL; int count = 0; - int callObjc; + Tcl_Size callObjc; Tcl_Obj **callObjv = NULL; Datum *argvalues; MemoryContext oldcontext = CurrentMemoryContext; @@ -3206,6 +3209,9 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc, bool include_gene /* don't include unless requested */ if (!include_generated) continue; + /* never include virtual columns */ + if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL) + continue; } /************************************************************ diff --git a/src/pl/tcl/po/de.po b/src/pl/tcl/po/de.po index aea4172bf763d..7594353d58e38 100644 --- a/src/pl/tcl/po/de.po +++ b/src/pl/tcl/po/de.po @@ -1,14 +1,14 @@ # German message translation file for PL/Tcl -# Peter Eisentraut , 2009 - 2024. +# Peter Eisentraut , 2009 - 2025. # # Use these quotes: »%s« # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 17\n" +"Project-Id-Version: PostgreSQL 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-18 04:38+0000\n" -"PO-Revision-Date: 2024-06-18 14:44+0200\n" +"POT-Creation-Date: 2025-03-07 09:38+0000\n" +"PO-Revision-Date: 2025-03-07 11:55+0100\n" "Last-Translator: Peter Eisentraut \n" "Language-Team: German \n" "Language: de\n" @@ -16,105 +16,105 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: pltcl.c:462 +#: pltcl.c:467 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "PL/Tcl-Funktion, die einmal aufgerufen wird, wenn pltcl zum ersten Mal benutzt wird." -#: pltcl.c:469 +#: pltcl.c:474 msgid "PL/TclU function to call once when pltclu is first used." msgstr "PL/Tcl-Funktion, die einmal aufgerufen wird, wenn pltclu zum ersten Mal benutzt wird." -#: pltcl.c:636 +#: pltcl.c:641 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "Funktion »%s« ist in der falschen Sprache" -#: pltcl.c:647 +#: pltcl.c:652 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "Funktion »%s« darf nicht SECURITY DEFINER sein" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:686 #, c-format msgid "processing %s parameter" msgstr "Verarbeiten von Parameter von %s" -#: pltcl.c:834 +#: pltcl.c:838 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "Funktion mit Mengenergebnis in einem Zusammenhang aufgerufen, der keine Mengenergebnisse verarbeiten kann" -#: pltcl.c:839 +#: pltcl.c:843 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "Materialisierungsmodus wird benötigt, ist aber in diesem Zusammenhang nicht erlaubt" -#: pltcl.c:1012 +#: pltcl.c:1016 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "Funktion, die einen Record zurückgibt, in einem Zusammenhang aufgerufen, der Typ record nicht verarbeiten kann" -#: pltcl.c:1031 +#: pltcl.c:1035 #, c-format msgid "could not parse function return value: %s" msgstr "konnte Rückgabewert der Funktion nicht parsen: %s" -#: pltcl.c:1298 +#: pltcl.c:1301 #, c-format msgid "could not parse trigger return value: %s" msgstr "konnte Rückgabewert des Triggers nicht parsen: %s" -#: pltcl.c:1383 pltcl.c:1810 +#: pltcl.c:1401 pltcl.c:1895 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1384 +#: pltcl.c:1402 #, c-format msgid "" "%s\n" -"in PL/Tcl function \"%s\"" +"in PL/Tcl function %s" msgstr "" "%s\n" -"in PL/Tcl-Funktion »%s«" +"in PL/Tcl-Funktion %s" -#: pltcl.c:1547 +#: pltcl.c:1630 #, c-format msgid "trigger functions can only be called as triggers" msgstr "Triggerfunktionen können nur als Trigger aufgerufen werden" -#: pltcl.c:1551 +#: pltcl.c:1634 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "PL/Tcl-Funktionen können keinen Rückgabetyp %s haben" -#: pltcl.c:1590 +#: pltcl.c:1673 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "PL/Tcl-Funktionen können Typ %s nicht annehmen" -#: pltcl.c:1702 +#: pltcl.c:1785 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "konnte interne Prozedur »%s« nicht erzeugen: %s" -#: pltcl.c:3207 +#: pltcl.c:3295 #, c-format msgid "column name/value list must have even number of elements" msgstr "Liste der Spaltennamen/-werte muss gerade Anzahl Elemente haben" -#: pltcl.c:3225 +#: pltcl.c:3313 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "Liste der Spaltennamen/-werte enthält nicht existierenden Spaltennamen »%s«" -#: pltcl.c:3232 +#: pltcl.c:3320 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "Systemattribut »%s« kann nicht gesetzt werden" -#: pltcl.c:3238 +#: pltcl.c:3326 #, c-format msgid "cannot set generated column \"%s\"" msgstr "kann generierte Spalte »%s« nicht setzen" diff --git a/src/pl/tcl/po/es.po b/src/pl/tcl/po/es.po index ff271b4046100..5020e4ffb189a 100644 --- a/src/pl/tcl/po/es.po +++ b/src/pl/tcl/po/es.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pltcl (PostgreSQL) 16\n" +"Project-Id-Version: pltcl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-05-22 07:08+0000\n" -"PO-Revision-Date: 2023-05-22 12:06+0200\n" +"POT-Creation-Date: 2025-02-16 19:38+0000\n" +"PO-Revision-Date: 2024-11-16 14:24+0100\n" "Last-Translator: Carlos Chapi \n" "Language-Team: PgSQL-es-Ayuda \n" "Language: es\n" @@ -20,56 +20,61 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.0.2\n" -#: pltcl.c:462 +#: pltcl.c:466 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "función PL/Tcl a ejecutar cuando se use pltcl por primera vez." -#: pltcl.c:469 +#: pltcl.c:473 msgid "PL/TclU function to call once when pltclu is first used." msgstr "función PL/TclU a ejecutar cuando se use pltclu por primera vez." -#: pltcl.c:636 +#: pltcl.c:640 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "la función «%s» está en el lenguaje equivocado" -#: pltcl.c:647 +#: pltcl.c:651 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "la función «%s» no debe ser SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:685 #, c-format msgid "processing %s parameter" msgstr "procesando el parámetro %s" -#: pltcl.c:834 +#: pltcl.c:838 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "se llamó una función que retorna un conjunto en un contexto que no puede aceptarlo" -#: pltcl.c:839 +#: pltcl.c:843 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "se requiere un nodo «materialize», pero no está permitido en este contexto" -#: pltcl.c:1012 +#: pltcl.c:1016 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "se llamó una función que retorna un registro en un contexto que no puede aceptarlo" -#: pltcl.c:1295 +#: pltcl.c:1035 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "no se pudo separar el valor de retorno del disparador: %s" +msgid "could not parse function return value: %s" +msgstr "no se pudo interpretar el valor de retorno de la función: %s" -#: pltcl.c:1376 pltcl.c:1803 +#: pltcl.c:1302 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "no se pudo interpretar el valor de retorno del trigger: «%s»" + +#: pltcl.c:1387 pltcl.c:1814 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1377 +#: pltcl.c:1388 #, c-format msgid "" "%s\n" @@ -78,42 +83,42 @@ msgstr "" "%s\n" "en función PL/Tcl \"%s\"" -#: pltcl.c:1540 +#: pltcl.c:1551 #, c-format msgid "trigger functions can only be called as triggers" msgstr "las funciones disparadoras sólo pueden ser invocadas como disparadores" -#: pltcl.c:1544 +#: pltcl.c:1555 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "las funciones PL/Tcl no pueden retornar tipo %s" -#: pltcl.c:1583 +#: pltcl.c:1594 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "las funciones PL/Tcl no pueden aceptar el tipog%s" -#: pltcl.c:1695 +#: pltcl.c:1706 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "no se pudo crear procedimiento interno «%s»: %s" -#: pltcl.c:3199 +#: pltcl.c:3211 #, c-format msgid "column name/value list must have even number of elements" msgstr "la lista de nombres de columnas y valores debe tener un número par de elementos" -#: pltcl.c:3217 +#: pltcl.c:3229 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "la lista de nombres de columnas y valores contiene el nombre de columna no existente «%s»" -#: pltcl.c:3224 +#: pltcl.c:3236 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "no se puede definir el atributo de sistema «%s»" -#: pltcl.c:3230 +#: pltcl.c:3242 #, c-format msgid "cannot set generated column \"%s\"" msgstr "no se puede definir el atributo generado «%s»" diff --git a/src/pl/tcl/po/fr.po b/src/pl/tcl/po/fr.po index 2af48d874a974..e7ab5bc05e70e 100644 --- a/src/pl/tcl/po/fr.po +++ b/src/pl/tcl/po/fr.po @@ -8,10 +8,10 @@ # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-12 05:16+0000\n" -"PO-Revision-Date: 2022-04-12 17:29+0200\n" +"POT-Creation-Date: 2024-08-23 14:08+0000\n" +"PO-Revision-Date: 2024-09-16 16:28+0200\n" "Last-Translator: Guillaume Lelarge \n" "Language-Team: French \n" "Language: fr\n" @@ -19,60 +19,65 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0.1\n" +"X-Generator: Poedit 3.5\n" -#: pltcl.c:463 +#: pltcl.c:462 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "Fonction PL/Tcl à appeler une fois quand pltcl est utilisé pour la première fois." -#: pltcl.c:470 +#: pltcl.c:469 msgid "PL/TclU function to call once when pltclu is first used." msgstr "Fonction PL/TclU à appeler une fois quand pltcl est utilisé pour la première fois." -#: pltcl.c:637 +#: pltcl.c:636 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "la fonction « %s » est dans le mauvais langage" -#: pltcl.c:648 +#: pltcl.c:647 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "la fonction « %s » doit être définie en SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:682 +#: pltcl.c:681 #, c-format msgid "processing %s parameter" msgstr "traitement du paramètre %s" -#: pltcl.c:835 +#: pltcl.c:834 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "la fonction renvoyant un ensemble a été appelée dans un contexte qui n'accepte pas un ensemble" -#: pltcl.c:840 +#: pltcl.c:839 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "mode matérialisé requis mais interdit dans ce contexte" -#: pltcl.c:1013 +#: pltcl.c:1012 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "" "fonction renvoyant le type record appelée dans un contexte qui ne peut pas\n" "accepter le type record" -#: pltcl.c:1297 +#: pltcl.c:1031 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "n'a pas pu séparer la valeur de retour du trigger : %s" +msgid "could not parse function return value: %s" +msgstr "n'a pas pu analyser la valeur de retour de la fonction : %s" -#: pltcl.c:1378 pltcl.c:1808 +#: pltcl.c:1298 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "n'a pas pu analyser la valeur de retour du trigger : %s" + +#: pltcl.c:1383 pltcl.c:1810 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1379 +#: pltcl.c:1384 #, c-format msgid "" "%s\n" @@ -81,60 +86,42 @@ msgstr "" "%s\n" "dans la fonction PL/Tcl « %s »" -#: pltcl.c:1543 +#: pltcl.c:1547 #, c-format msgid "trigger functions can only be called as triggers" msgstr "les fonctions trigger peuvent seulement être appelées par des triggers" -#: pltcl.c:1547 +#: pltcl.c:1551 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "les fonctions PL/Tcl ne peuvent pas renvoyer le type %s" -#: pltcl.c:1586 +#: pltcl.c:1590 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "les fonctions PL/Tcl ne peuvent pas accepter le type %s" -#: pltcl.c:1700 +#: pltcl.c:1702 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "n'a pas pu créer la procédure interne « %s » : %s" -#: pltcl.c:3202 +#: pltcl.c:3207 #, c-format msgid "column name/value list must have even number of elements" msgstr "la liste de nom de colonne/valeur doit avoir un nombre pair d'éléments" -#: pltcl.c:3220 +#: pltcl.c:3225 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "la liste de nom de colonne/valeur contient des noms de colonne inexistantes (« %s »)" -#: pltcl.c:3227 +#: pltcl.c:3232 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "ne peut pas initialiser l'attribut système « %s »" -#: pltcl.c:3233 +#: pltcl.c:3238 #, c-format msgid "cannot set generated column \"%s\"" msgstr "ne peut pas initialiser la colonne générée « %s »" - -#~ msgid "PL/Tcl functions cannot return composite types" -#~ msgstr "les fonctions PL/Tcl ne peuvent pas renvoyer des types composites" - -#~ msgid "could not load module \"unknown\": %s" -#~ msgstr "n'a pas pu charger le module « unknown » : %s" - -#~ msgid "module \"unknown\" not found in pltcl_modules" -#~ msgstr "module « unkown » introuvable dans pltcl_modules" - -#~ msgid "out of memory" -#~ msgstr "mémoire épuisée" - -#~ msgid "trigger's return list must have even number of elements" -#~ msgstr "la liste de retour du trigger doit avoir un nombre pair d'éléments" - -#~ msgid "unrecognized attribute \"%s\"" -#~ msgstr "attribut « %s » non reconnu" diff --git a/src/pl/tcl/po/ja.po b/src/pl/tcl/po/ja.po index 997c675ad76b9..981ecbea20e6b 100644 --- a/src/pl/tcl/po/ja.po +++ b/src/pl/tcl/po/ja.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pltcl (PostgreSQL 17)\n" +"Project-Id-Version: pltcl (PostgreSQL 18)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-06 10:49+0900\n" -"PO-Revision-Date: 2024-06-06 16:12+0900\n" +"POT-Creation-Date: 2024-07-08 10:16+0900\n" +"PO-Revision-Date: 2025-03-31 16:27+0900\n" "Last-Translator: Kyotaro Horiguchi \n" "Language-Team: Japan PostgreSQL Users Group \n" "Language: ja\n" @@ -18,108 +18,105 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 1.8.13\n" -#: pltcl.c:462 +#: pltcl.c:464 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "pltcl が最初に使用される際に一度だけ呼び出される PL/Tcl 関数。" -#: pltcl.c:469 +#: pltcl.c:471 msgid "PL/TclU function to call once when pltclu is first used." msgstr "pltclu が最初に使用される際に一度だけ呼び出される PL/TclU 関数。" -#: pltcl.c:636 +#: pltcl.c:638 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "関数\"%s\"は言語が異なります" -#: pltcl.c:647 +#: pltcl.c:649 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "関数\"%s\"はSECURITY DEFINERであってはなりません" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:683 #, c-format msgid "processing %s parameter" msgstr "%sパラメーターを処理しています" -#: pltcl.c:834 +#: pltcl.c:836 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "このコンテキストでは、集合値の関数は集合を受け付けられません" -#: pltcl.c:839 +#: pltcl.c:841 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "マテリアライズモードが必要ですが、現在のコンテクストで禁止されています" -#: pltcl.c:1012 +#: pltcl.c:1014 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "レコード型を受け付けられないコンテキストでレコードを返す関数が呼び出されました" -#: pltcl.c:1031 +#: pltcl.c:1033 #, c-format msgid "could not parse function return value: %s" msgstr "関数の戻り値をパースできませんでした: %s" -#: pltcl.c:1298 +#: pltcl.c:1300 #, c-format msgid "could not parse trigger return value: %s" msgstr "トリガの戻り値をパースできませんでした: %s" -#: pltcl.c:1383 pltcl.c:1810 +#: pltcl.c:1401 pltcl.c:1895 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1384 +#: pltcl.c:1402 #, c-format msgid "" "%s\n" -"in PL/Tcl function \"%s\"" +"in PL/Tcl function %s" msgstr "" "%s\n" -"PL/Tcl 関数 \"%s\"" +"PL/Tcl 関数 %s 内" -#: pltcl.c:1547 +#: pltcl.c:1630 #, c-format msgid "trigger functions can only be called as triggers" msgstr "トリガー関数はトリガーとしてのみコールできます" -#: pltcl.c:1551 +#: pltcl.c:1634 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "PL/Tcl 関数は%s型の戻り値を返せません" -#: pltcl.c:1590 +#: pltcl.c:1673 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "PL/Tcl 関数は%s型を受け付けません" -#: pltcl.c:1702 +#: pltcl.c:1785 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "内部プロシージャ\"%s\"を作成できませんでした: %s" -#: pltcl.c:3207 +#: pltcl.c:3292 #, c-format msgid "column name/value list must have even number of elements" msgstr "列名/値のリストの要素は偶数個でなければなりません" -#: pltcl.c:3225 +#: pltcl.c:3310 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "列名/値のリストの中に、存在しない列名\"%s\"が含まれています" -#: pltcl.c:3232 +#: pltcl.c:3317 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "システム属性\"%s\"は設定できません" -#: pltcl.c:3238 +#: pltcl.c:3323 #, c-format msgid "cannot set generated column \"%s\"" msgstr "生成列\"%s\"を変更できません" - -#~ msgid "could not split return value from trigger: %s" -#~ msgstr "トリガーからの戻り値を分割できませんでした: %s" diff --git a/src/pl/tcl/po/ka.po b/src/pl/tcl/po/ka.po index 6047d595a7ac5..94b739a609d46 100644 --- a/src/pl/tcl/po/ka.po +++ b/src/pl/tcl/po/ka.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pltcl (PostgreSQL) 15\n" +"Project-Id-Version: pltcl (PostgreSQL) 18\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2024-06-04 22:08+0000\n" -"PO-Revision-Date: 2024-06-05 01:38+0200\n" +"POT-Creation-Date: 2025-02-27 09:39+0000\n" +"PO-Revision-Date: 2025-02-27 12:14+0100\n" "Last-Translator: Temuri Doghonadze \n" "Language-Team: Georgian \n" "Language: ka\n" @@ -16,107 +16,107 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.3.2\n" +"X-Generator: Poedit 3.5\n" -#: pltcl.c:462 +#: pltcl.c:467 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "PL/Tcl ფუნქცია, როლის გამოძახებაც ერთხელ, pltcl-ის პირველი გამოყენებისას ხდება." -#: pltcl.c:469 +#: pltcl.c:474 msgid "PL/TclU function to call once when pltclu is first used." msgstr "PL/TclU ფუნქცია, როლის გამოძახებაც ერთხელ, pltclu -ის პირველი გამოყენებისას ხდება." -#: pltcl.c:636 +#: pltcl.c:641 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "ფუნქცია \"%s\" არასწორ ენაზეა" -#: pltcl.c:647 +#: pltcl.c:652 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "ფუნქცია \"%s\" არ უნდა იყოს SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:686 #, c-format msgid "processing %s parameter" msgstr "პარამეტრის დამუშავება: %s" -#: pltcl.c:834 +#: pltcl.c:838 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "სეტ-ღირებული ფუნქცია, რომელსაც ეწოდება კონტექსტში, რომელსაც არ შეუძლია მიიღოს ნაკრები" -#: pltcl.c:839 +#: pltcl.c:843 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "საჭიროა მატერიალიზებული რეჟიმი, მაგრამ ამ კონტექსტში ეს დაუშვებელია" -#: pltcl.c:1012 +#: pltcl.c:1016 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "ფუნქცია, რომელიც ჩანაწერს აბრუნებს, გამოძახებულია კონტექსტში, რომელსაც ჩანაწერის მიღება არ შეუძლია" -#: pltcl.c:1031 +#: pltcl.c:1035 #, c-format msgid "could not parse function return value: %s" msgstr "ფუნქციიდან დაბრუნებული მნიშვნელობის დამუშავება შეუძლებელია: %s" -#: pltcl.c:1298 +#: pltcl.c:1301 #, c-format msgid "could not parse trigger return value: %s" msgstr "ტრიგერიდან დაბრუნებული მნიშვნელობის დამუშავება შეუძლებელია: %s" -#: pltcl.c:1383 pltcl.c:1810 +#: pltcl.c:1401 pltcl.c:1895 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1384 +#: pltcl.c:1402 #, c-format msgid "" "%s\n" -"in PL/Tcl function \"%s\"" +"in PL/Tcl function %s" msgstr "" "%s\n" -"PL/Tcl-ის ფუნქციაში\"%s\"" +"PL/Tcl-ის ფუნქციაში %s" -#: pltcl.c:1547 +#: pltcl.c:1630 #, c-format msgid "trigger functions can only be called as triggers" msgstr "ტრიგერის ფუნქციების გამოძახება მხოლოდ ტრიგერებად შეიძლება" -#: pltcl.c:1551 +#: pltcl.c:1634 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "PL/Tcl ფუნქციას %s ტიპის დაბრუნება არ შეუძლია" -#: pltcl.c:1590 +#: pltcl.c:1673 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "PL/Tcl ფუნქციას %s ტიპის მიღება არ შეუძლია" -#: pltcl.c:1702 +#: pltcl.c:1785 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "შიდა პროცედურის (\"%s\") შექმნის შეცდომა: %s" -#: pltcl.c:3207 +#: pltcl.c:3295 #, c-format msgid "column name/value list must have even number of elements" msgstr "სვეტის სახელი/მნიშვნელობების სიას ელემენტების ლუწი რაოდენობა უნდა ჰქონდეს" -#: pltcl.c:3225 +#: pltcl.c:3313 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "სვეტის სახელი/მნიშვნელობების სია შეიცავს სვეტის არარსებულ სახელს „%s“" -#: pltcl.c:3232 +#: pltcl.c:3320 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "სისტემური ატრიბუტის დაყენების შეცდომა: \"%s\"" -#: pltcl.c:3238 +#: pltcl.c:3326 #, c-format msgid "cannot set generated column \"%s\"" msgstr "გენერირებული სვეტის დაყენება შეუძლებელია: %s" diff --git a/src/pl/tcl/po/ko.po b/src/pl/tcl/po/ko.po index 1b8c5c7a6442e..63d744f6c2113 100644 --- a/src/pl/tcl/po/ko.po +++ b/src/pl/tcl/po/ko.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: pltcl (PostgreSQL) 16\n" +"Project-Id-Version: pltcl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-09-07 05:38+0000\n" -"PO-Revision-Date: 2023-05-30 12:40+0900\n" +"POT-Creation-Date: 2025-01-17 04:38+0000\n" +"PO-Revision-Date: 2025-01-16 11:03+0900\n" "Last-Translator: Ioseph Kim \n" "Language-Team: Korean Team \n" "Language: ko\n" @@ -17,58 +17,63 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: pltcl.c:462 +#: pltcl.c:466 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "pltcl 언어가 처음 사용될 때 한번 호출 될 PL/Tcl 함수" -#: pltcl.c:469 +#: pltcl.c:473 msgid "PL/TclU function to call once when pltclu is first used." msgstr "pltclu 언어가 처음 사용될 때 한번 호출 될 PL/Tcl 함수" -#: pltcl.c:636 +#: pltcl.c:640 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "\"%s\" 함수에 잘못된 언어가 있음" -#: pltcl.c:647 +#: pltcl.c:651 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "\"%s\" 함수는 SECURITY DEFINER 속성이 없어야 합니다" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:685 #, c-format msgid "processing %s parameter" msgstr "%s 매개 변수 처리 중" -#: pltcl.c:834 +#: pltcl.c:838 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "집합이 값이 함수가 집합을 사용할 수 없는 구문에서 호출 되었음" -#: pltcl.c:839 +#: pltcl.c:843 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialize 모드가 필요합니다만, 이 구문에서는 허용되지 않습니다" -#: pltcl.c:1012 +#: pltcl.c:1016 #, c-format msgid "" "function returning record called in context that cannot accept type record" msgstr "" "레코드를 반환하는 함수가 레코드 형을 사용할 수 없는 구문에서 호출 되었음" -#: pltcl.c:1295 +#: pltcl.c:1035 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "트리거에서 반환값을 분리할 수 없음: %s" +msgid "could not parse function return value: %s" +msgstr "함수 반환값을 분석할 수 없음: %s" -#: pltcl.c:1376 pltcl.c:1803 +#: pltcl.c:1302 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "트리거 반환값을 분석할 수 없음: %s" + +#: pltcl.c:1387 pltcl.c:1814 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1377 +#: pltcl.c:1388 #, c-format msgid "" "%s\n" @@ -77,42 +82,46 @@ msgstr "" "%s\n" "해당 PL/Tcl 함수: \"%s\"" -#: pltcl.c:1540 +#: pltcl.c:1551 #, c-format msgid "trigger functions can only be called as triggers" msgstr "트리거 함수는 트리거로만 호출될 수 있음" -#: pltcl.c:1544 +#: pltcl.c:1555 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "PL/Tcl 함수는 %s 자료형을 반환할 수 없음" -#: pltcl.c:1583 +#: pltcl.c:1594 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "PL/Tcl 함수는 %s 자료형을 사용할 수 없음" -#: pltcl.c:1695 +#: pltcl.c:1706 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "\"%s\" 내부 프로시져를 만들 수 없음: %s" -#: pltcl.c:3199 +#: pltcl.c:3211 #, c-format msgid "column name/value list must have even number of elements" msgstr "칼럼 이름/값 목록은 그 요소의 개수가 짝수여야 함" -#: pltcl.c:3217 +#: pltcl.c:3229 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "칼럼 이름/값 목록에 \"%s\" 칼럼에 대한 값이 없음" -#: pltcl.c:3224 +#: pltcl.c:3236 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "\"%s\" 시스템 속성을 지정할 수 없음" -#: pltcl.c:3230 +#: pltcl.c:3242 #, c-format msgid "cannot set generated column \"%s\"" msgstr "\"%s\" 계산된 칼럼을 지정할 수 없음" + +#, c-format +#~ msgid "could not split return value from trigger: %s" +#~ msgstr "트리거에서 반환값을 분리할 수 없음: %s" diff --git a/src/pl/tcl/po/meson.build b/src/pl/tcl/po/meson.build index 382af4a880475..1f8fac8810e0a 100644 --- a/src/pl/tcl/po/meson.build +++ b/src/pl/tcl/po/meson.build @@ -1,3 +1,3 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group nls_targets += [i18n.gettext('pltcl-' + pg_version_major.to_string())] diff --git a/src/pl/tcl/po/ru.po b/src/pl/tcl/po/ru.po index 8d136272242ca..1f15520c8cba6 100644 --- a/src/pl/tcl/po/ru.po +++ b/src/pl/tcl/po/ru.po @@ -1,13 +1,13 @@ # Russian message translation file for pltcl # Copyright (C) 2012-2016 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Alexander Lakhin , 2012-2017, 2019, 2022. +# Alexander Lakhin , 2012-2017, 2019, 2022, 2024. msgid "" msgstr "" "Project-Id-Version: pltcl (PostgreSQL current)\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2023-08-28 07:59+0300\n" -"PO-Revision-Date: 2022-09-05 13:38+0300\n" +"POT-Creation-Date: 2025-02-08 07:44+0200\n" +"PO-Revision-Date: 2024-08-01 13:03+0300\n" "Last-Translator: Alexander Lakhin \n" "Language-Team: Russian \n" "Language: ru\n" @@ -17,59 +17,64 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: pltcl.c:462 +#: pltcl.c:466 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "Функция на PL/Tcl, вызываемая при первом использовании pltcl." -#: pltcl.c:469 +#: pltcl.c:473 msgid "PL/TclU function to call once when pltclu is first used." msgstr "Функция на PL/TclU, вызываемая при первом использовании pltclu." -#: pltcl.c:636 +#: pltcl.c:640 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "Функция \"%s\" объявлена на другом языке" -#: pltcl.c:647 +#: pltcl.c:651 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "функция \"%s\" не должна иметь характеристику SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:681 +#: pltcl.c:685 #, c-format msgid "processing %s parameter" msgstr "обработка параметра %s" -#: pltcl.c:834 +#: pltcl.c:838 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "" "функция, возвращающая множество, вызвана в контексте, где ему нет места" -#: pltcl.c:839 +#: pltcl.c:843 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "требуется режим материализации, но он недопустим в этом контексте" -#: pltcl.c:1012 +#: pltcl.c:1016 #, c-format msgid "" "function returning record called in context that cannot accept type record" msgstr "" "функция, возвращающая запись, вызвана в контексте, не допускающем этот тип" -#: pltcl.c:1295 +#: pltcl.c:1035 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "разложить возвращаемое из триггера значение не удалось: %s" +msgid "could not parse function return value: %s" +msgstr "разобрать возвращаемое функцией значение не удалось: %s" -#: pltcl.c:1376 pltcl.c:1803 +#: pltcl.c:1302 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "разобрать возвращаемое триггером значение не удалось: %s" + +#: pltcl.c:1387 pltcl.c:1814 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1377 +#: pltcl.c:1388 #, c-format msgid "" "%s\n" @@ -78,43 +83,43 @@ msgstr "" "%s\n" "в функции PL/Tcl \"%s\"" -#: pltcl.c:1540 +#: pltcl.c:1551 #, c-format msgid "trigger functions can only be called as triggers" msgstr "триггерные функции могут вызываться только в триггерах" -#: pltcl.c:1544 +#: pltcl.c:1555 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "функции PL/Tcl не могут возвращать тип %s" -#: pltcl.c:1583 +#: pltcl.c:1594 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "функции PL/Tcl не могут принимать тип %s" -#: pltcl.c:1695 +#: pltcl.c:1706 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "не удалось создать внутреннюю процедуру \"%s\": %s" -#: pltcl.c:3199 +#: pltcl.c:3211 #, c-format msgid "column name/value list must have even number of elements" msgstr "в списке имён/значений столбцов должно быть чётное число элементов" -#: pltcl.c:3217 +#: pltcl.c:3229 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "" "список имён/значений столбцов содержит имя несуществующего столбца \"%s\"" -#: pltcl.c:3224 +#: pltcl.c:3236 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "присвоить значение системному атрибуту \"%s\" нельзя" -#: pltcl.c:3230 +#: pltcl.c:3242 #, c-format msgid "cannot set generated column \"%s\"" msgstr "присвоить значение генерируемому столбцу \"%s\" нельзя" diff --git a/src/pl/tcl/po/sv.po b/src/pl/tcl/po/sv.po index 5d140445206d9..d6fce1b82cbcd 100644 --- a/src/pl/tcl/po/sv.po +++ b/src/pl/tcl/po/sv.po @@ -1,14 +1,14 @@ # Swedish message translation file for pltcl # Copyright (C) 2017 PostgreSQL Global Development Group # This file is distributed under the same license as the PostgreSQL package. -# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023. +# Dennis Björklund , 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024. # msgid "" msgstr "" -"Project-Id-Version: PostgreSQL 15\n" +"Project-Id-Version: PostgreSQL 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-04-11 13:38+0000\n" -"PO-Revision-Date: 2023-03-09 22:42+0100\n" +"POT-Creation-Date: 2024-07-12 17:38+0000\n" +"PO-Revision-Date: 2024-07-12 22:05+0200\n" "Last-Translator: Dennis Björklund \n" "Language-Team: Swedish \n" "Language: sv\n" @@ -17,56 +17,61 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: pltcl.c:463 +#: pltcl.c:462 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "PL/Tcl-funktion att anropa en gång när pltcl först används." -#: pltcl.c:470 +#: pltcl.c:469 msgid "PL/TclU function to call once when pltclu is first used." msgstr "PL/TclU-funktion att anrop en gång när pltclu först används." -#: pltcl.c:637 +#: pltcl.c:636 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "funktionen \"%s\" är skriven i fel språk" -#: pltcl.c:648 +#: pltcl.c:647 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "funktionen \"%s\" får ej vara SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:682 +#: pltcl.c:681 #, c-format msgid "processing %s parameter" msgstr "processar parameter %s" -#: pltcl.c:835 +#: pltcl.c:834 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "en funktion som returnerar en mängd anropades i kontext som inte godtar en mängd" -#: pltcl.c:840 +#: pltcl.c:839 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "materialiserat läge krävs, men stöds inte i detta kontext" -#: pltcl.c:1013 +#: pltcl.c:1012 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "en funktion med post som värde anropades i sammanhang där poster inte kan godtagas." -#: pltcl.c:1297 +#: pltcl.c:1031 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "kunde inte dela på returvärde från trigger: %s" +msgid "could not parse function return value: %s" +msgstr "kunde inte parsa funktions returvärde: %s" -#: pltcl.c:1378 pltcl.c:1808 +#: pltcl.c:1298 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "kunde inte parsa triggers returvärde: %s" + +#: pltcl.c:1383 pltcl.c:1810 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1379 +#: pltcl.c:1384 #, c-format msgid "" "%s\n" @@ -75,42 +80,42 @@ msgstr "" "%s\n" "i PL/Tcl-funktion \"%s\"" -#: pltcl.c:1543 +#: pltcl.c:1547 #, c-format msgid "trigger functions can only be called as triggers" msgstr "Triggningsfunktioner kan bara anropas vid triggning." -#: pltcl.c:1547 +#: pltcl.c:1551 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "PL/Tcl-funktioner kan inte returnera typ %s" -#: pltcl.c:1586 +#: pltcl.c:1590 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "PL/Tcl-funktioner kan inte ta emot typ %s" -#: pltcl.c:1700 +#: pltcl.c:1702 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "kunde inte skapa en intern procedur \"%s\": %s" -#: pltcl.c:3202 +#: pltcl.c:3207 #, c-format msgid "column name/value list must have even number of elements" msgstr "kolumn-namn/-värde måste ha ett jämt antal element" -#: pltcl.c:3220 +#: pltcl.c:3225 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "listan med kolumn-namn/-värde innehåller det icke existerande kolumnnamnet \"%s\"" -#: pltcl.c:3227 +#: pltcl.c:3232 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "kan inte sätta systemattribut \"%s\"" -#: pltcl.c:3233 +#: pltcl.c:3238 #, c-format msgid "cannot set generated column \"%s\"" msgstr "kan inte sätta genererad kolumn \"%s\"" diff --git a/src/pl/tcl/po/uk.po b/src/pl/tcl/po/uk.po index ceb1e782e6539..6caba5446ef7e 100644 --- a/src/pl/tcl/po/uk.po +++ b/src/pl/tcl/po/uk.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: postgresql\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2022-08-12 10:38+0000\n" -"PO-Revision-Date: 2022-09-13 11:52\n" +"POT-Creation-Date: 2024-08-31 06:08+0000\n" +"PO-Revision-Date: 2024-09-23 19:38\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" "Language: uk_UA\n" @@ -14,101 +14,106 @@ msgstr "" "X-Crowdin-Project: postgresql\n" "X-Crowdin-Project-ID: 324573\n" "X-Crowdin-Language: uk\n" -"X-Crowdin-File: /REL_15_STABLE/pltcl.pot\n" -"X-Crowdin-File-ID: 914\n" +"X-Crowdin-File: /REL_17_STABLE/pltcl.pot\n" +"X-Crowdin-File-ID: 1016\n" -#: pltcl.c:463 +#: pltcl.c:462 msgid "PL/Tcl function to call once when pltcl is first used." msgstr "Функція PL/Tcl використовується для виклику коли pltcl вперше використаний." -#: pltcl.c:470 +#: pltcl.c:469 msgid "PL/TclU function to call once when pltclu is first used." msgstr "Функція PL/TclU використовується для виклику коли pltclu вперше використаний." -#: pltcl.c:637 +#: pltcl.c:636 #, c-format msgid "function \"%s\" is in the wrong language" msgstr "функція «%s» написана неправильною мовою" -#: pltcl.c:648 +#: pltcl.c:647 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" msgstr "функція \"%s\" не має бути SECURITY DEFINER" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:682 +#: pltcl.c:681 #, c-format msgid "processing %s parameter" msgstr "обробляється параметр %s" -#: pltcl.c:835 +#: pltcl.c:834 #, c-format msgid "set-valued function called in context that cannot accept a set" msgstr "функція \"set-valued\" викликана в контексті, де йому немає місця" -#: pltcl.c:840 +#: pltcl.c:839 #, c-format msgid "materialize mode required, but it is not allowed in this context" msgstr "необхідний режим матеріалізації (materialize mode), але він неприпустимий у цьому контексті" -#: pltcl.c:1013 +#: pltcl.c:1012 #, c-format msgid "function returning record called in context that cannot accept type record" msgstr "функція, що повертає набір, викликана у контексті, що не приймає тип запис" -#: pltcl.c:1296 +#: pltcl.c:1031 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "не вдалося розділити повернене значення з тригера: %s" +msgid "could not parse function return value: %s" +msgstr "не вдалося проаналізувати значення функції: %s" -#: pltcl.c:1377 pltcl.c:1807 +#: pltcl.c:1298 +#, c-format +msgid "could not parse trigger return value: %s" +msgstr "не вдалося проаналізувати значення тригера: %s" + +#: pltcl.c:1383 pltcl.c:1810 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1378 +#: pltcl.c:1384 #, c-format msgid "%s\n" "in PL/Tcl function \"%s\"" msgstr "%s\n" "у функції PL/Tcl \"%s\"" -#: pltcl.c:1542 +#: pltcl.c:1547 #, c-format msgid "trigger functions can only be called as triggers" msgstr "тригер-функція може викликатися лише як тригер" -#: pltcl.c:1546 +#: pltcl.c:1551 #, c-format msgid "PL/Tcl functions cannot return type %s" msgstr "Функції PL/Tcl не можуть повертати тип %s" -#: pltcl.c:1585 +#: pltcl.c:1590 #, c-format msgid "PL/Tcl functions cannot accept type %s" msgstr "Функції PL/Tcl не можуть приймати тип %s" -#: pltcl.c:1699 +#: pltcl.c:1702 #, c-format msgid "could not create internal procedure \"%s\": %s" msgstr "не вдалося створити внутрішню процедуру \"%s\": %s" -#: pltcl.c:3201 +#: pltcl.c:3207 #, c-format msgid "column name/value list must have even number of elements" msgstr "список імен і значень стовпців повинен мати парну кількість елементів" -#: pltcl.c:3219 +#: pltcl.c:3225 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" msgstr "список імен і значень стовпців містить неіснуєче ім'я стовпця \"%s\"" -#: pltcl.c:3226 +#: pltcl.c:3232 #, c-format msgid "cannot set system attribute \"%s\"" msgstr "не вдалося встановити системний атрибут \"%s\"" -#: pltcl.c:3232 +#: pltcl.c:3238 #, c-format msgid "cannot set generated column \"%s\"" msgstr "неможливо оновити згенерований стовпець \"%s\"" diff --git a/src/pl/tcl/po/zh_CN.po b/src/pl/tcl/po/zh_CN.po index d9e49a74ce8d6..d7c8cc5cac877 100644 --- a/src/pl/tcl/po/zh_CN.po +++ b/src/pl/tcl/po/zh_CN.po @@ -1,111 +1,125 @@ # LANGUAGE message translation file for pltcl # Copyright (C) 2019 PostgreSQL Global Development Group # This file is distributed under the same license as the pltcl (PostgreSQL) package. -# FIRST AUTHOR , 2019. +# Dianjin Wang , 2024 # msgid "" msgstr "" -"Project-Id-Version: pltcl (PostgreSQL) 14\n" +"Project-Id-Version: pltcl (PostgreSQL) 17\n" "Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n" -"POT-Creation-Date: 2021-08-14 05:38+0000\n" -"PO-Revision-Date: 2021-08-16 18:00+0800\n" -"Last-Translator: Jie Zhang \n" +"POT-Creation-Date: 2024-09-13 22:40+0000\n" +"PO-Revision-Date: 2024-09-14 13:50+0800\n" +"Last-Translator: Dianjin Wang \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.7\n" +"X-Generator: Poedit 3.4.4\n" -#: pltcl.c:463 +#: pltcl.c:462 msgid "PL/Tcl function to call once when pltcl is first used." -msgstr "PL/Tcl函数在首次使用pltcl时调用一次." +msgstr "PL/Tcl 函数在首次使用 pltcl 时调用一次." -#: pltcl.c:470 +#: pltcl.c:469 msgid "PL/TclU function to call once when pltclu is first used." -msgstr "PL/TclU函数在首次使用pltcl时调用一次." +msgstr "PL/TclU 函数在首次使用 pltclu 时调用一次." -#: pltcl.c:634 +#: pltcl.c:636 #, c-format msgid "function \"%s\" is in the wrong language" -msgstr "函数\"%s\"的语言错误" +msgstr "函数 \"%s\" 所用语言错误" -#: pltcl.c:645 +#: pltcl.c:647 #, c-format msgid "function \"%s\" must not be SECURITY DEFINER" -msgstr "函数\"%s\"不能是安全定义者" +msgstr "函数 \"%s\" 不能是安全定义者" #. translator: %s is "pltcl.start_proc" or "pltclu.start_proc" -#: pltcl.c:679 +#: pltcl.c:681 #, c-format msgid "processing %s parameter" -msgstr "正在处理%s参数" +msgstr "正在处理 %s 参数" -#: pltcl.c:833 +#: pltcl.c:834 #, c-format msgid "set-valued function called in context that cannot accept a set" -msgstr "在不能接受使用集合的环境中调用set-valued函数" +msgstr "在不能接受使用集合的环境中调用 set-valued 函数" -#: pltcl.c:1006 +#: pltcl.c:839 +#, c-format +msgid "materialize mode required, but it is not allowed in this context" +msgstr "要求物化模式,但是在这种环境下不允许使用" + +#: pltcl.c:1012 #, c-format msgid "function returning record called in context that cannot accept type record" -msgstr "返回值类型是记录的函数在不接受使用记录类型的环境中调用" +msgstr "在不接受记录类型的环境中调用返回记录的函数" + +#: pltcl.c:1031 +#, c-format +msgid "could not parse function return value: %s" +msgstr "无法解析函数返回值: %s" -#: pltcl.c:1290 +#: pltcl.c:1298 #, c-format -msgid "could not split return value from trigger: %s" -msgstr "无法分离来自触发器的返回值:%s" +msgid "could not parse trigger return value: %s" +msgstr "无法解析触发器返回值: %s" -#: pltcl.c:1371 pltcl.c:1801 +#: pltcl.c:1383 pltcl.c:1810 #, c-format msgid "%s" msgstr "%s" -#: pltcl.c:1372 +#: pltcl.c:1384 #, c-format msgid "" "%s\n" "in PL/Tcl function \"%s\"" msgstr "" "%s\n" -"在PL/Tcl函数\"%s\"中" +"在 PL/Tcl 函数 \"%s\" 中" -#: pltcl.c:1536 +#: pltcl.c:1547 #, c-format msgid "trigger functions can only be called as triggers" msgstr "触发器函数只能以触发器的形式调用" -#: pltcl.c:1540 +#: pltcl.c:1551 #, c-format msgid "PL/Tcl functions cannot return type %s" -msgstr "PL/Tcl函数不能返回类型%s" +msgstr "PL/Tcl 函数无法返回类型 %s" -#: pltcl.c:1579 +#: pltcl.c:1590 #, c-format msgid "PL/Tcl functions cannot accept type %s" -msgstr "PL/Tcl函数不能使用类型 %s" +msgstr "PL/Tcl 函数无法接受类型 %s" -#: pltcl.c:1693 +#: pltcl.c:1702 #, c-format msgid "could not create internal procedure \"%s\": %s" -msgstr "无法创建内部过程\"%s\":%s" +msgstr "无法创建内部过程 \"%s\":%s" -#: pltcl.c:3197 +#: pltcl.c:3207 #, c-format msgid "column name/value list must have even number of elements" msgstr "列名/值列表必须具有偶数个元素" -#: pltcl.c:3215 +#: pltcl.c:3225 #, c-format msgid "column name/value list contains nonexistent column name \"%s\"" -msgstr "列名/值列表包含不存在的列名\"%s\"" +msgstr "列名/值列表包含不存在的列名 \"%s\"" -#: pltcl.c:3222 +#: pltcl.c:3232 #, c-format msgid "cannot set system attribute \"%s\"" -msgstr "不能设置系统属性\"%s\"" +msgstr "不能设置系统属性 \"%s\"" -#: pltcl.c:3228 +#: pltcl.c:3238 #, c-format msgid "cannot set generated column \"%s\"" msgstr "无法设置生成的列 \"%s\"" + +#, c-format +#~ msgid "could not split return value from trigger: %s" +#~ msgstr "无法分离来自触发器的返回值:%s" diff --git a/src/pl/tcl/sql/pltcl_trigger.sql b/src/pl/tcl/sql/pltcl_trigger.sql index 2a244de83bcab..0ed00f495263b 100644 --- a/src/pl/tcl/sql/pltcl_trigger.sql +++ b/src/pl/tcl/sql/pltcl_trigger.sql @@ -73,7 +73,8 @@ ALTER TABLE trigger_test DROP dropme; CREATE TABLE trigger_test_generated ( i int, - j int GENERATED ALWAYS AS (i * 2) STORED + j int GENERATED ALWAYS AS (i * 2) STORED, + k int GENERATED ALWAYS AS (i * 3) VIRTUAL ); CREATE VIEW trigger_test_view AS SELECT i, v FROM trigger_test; diff --git a/src/port/Makefile b/src/port/Makefile index db7c02117b02d..4274949dfa4c1 100644 --- a/src/port/Makefile +++ b/src/port/Makefile @@ -38,13 +38,16 @@ LIBS += $(PTHREAD_LIBS) OBJS = \ $(LIBOBJS) \ $(PG_CRC32C_OBJS) \ - $(PG_POPCNT_OBJS) \ bsearch_arg.o \ chklocale.o \ inet_net_ntop.o \ noblock.o \ path.o \ pg_bitutils.o \ + pg_localeconv_r.o \ + pg_numa.o \ + pg_popcount_aarch64.o \ + pg_popcount_avx512.o \ pg_strong_random.o \ pgcheckdir.o \ pgmkdirp.o \ @@ -57,8 +60,7 @@ OBJS = \ quotes.o \ snprintf.o \ strerror.o \ - tar.o \ - user.o + tar.o # libpgport.a, libpgport_shlib.a, and libpgport_srv.a contain the same files # foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c @@ -83,26 +85,11 @@ libpgport.a: $(OBJS) rm -f $@ $(AR) $(AROPT) $@ $^ -# all versions of pg_crc32c_sse42.o need CFLAGS_CRC -pg_crc32c_sse42.o: CFLAGS+=$(CFLAGS_CRC) -pg_crc32c_sse42_shlib.o: CFLAGS+=$(CFLAGS_CRC) -pg_crc32c_sse42_srv.o: CFLAGS+=$(CFLAGS_CRC) - # all versions of pg_crc32c_armv8.o need CFLAGS_CRC pg_crc32c_armv8.o: CFLAGS+=$(CFLAGS_CRC) pg_crc32c_armv8_shlib.o: CFLAGS+=$(CFLAGS_CRC) pg_crc32c_armv8_srv.o: CFLAGS+=$(CFLAGS_CRC) -# all versions of pg_popcount_avx512_choose.o need CFLAGS_XSAVE -pg_popcount_avx512_choose.o: CFLAGS+=$(CFLAGS_XSAVE) -pg_popcount_avx512_choose_shlib.o: CFLAGS+=$(CFLAGS_XSAVE) -pg_popcount_avx512_choose_srv.o: CFLAGS+=$(CFLAGS_XSAVE) - -# all versions of pg_popcount_avx512.o need CFLAGS_POPCNT -pg_popcount_avx512.o: CFLAGS+=$(CFLAGS_POPCNT) -pg_popcount_avx512_shlib.o: CFLAGS+=$(CFLAGS_POPCNT) -pg_popcount_avx512_srv.o: CFLAGS+=$(CFLAGS_POPCNT) - # # Shared library versions of object files # diff --git a/src/port/bsearch_arg.c b/src/port/bsearch_arg.c index f0de467beeeaa..e9798aa8ee66a 100644 --- a/src/port/bsearch_arg.c +++ b/src/port/bsearch_arg.c @@ -1,7 +1,7 @@ /* * bsearch_arg.c: bsearch variant with a user-supplied pointer * - * Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Copyright (c) 2021-2025, PostgreSQL Global Development Group * Copyright (c) 1990 Regents of the University of California. * All rights reserved. * @@ -58,8 +58,8 @@ bsearch_arg(const void *key, const void *base0, void *arg) { const char *base = (const char *) base0; - int lim, - cmp; + size_t lim; + int cmp; const void *p; for (lim = nmemb; lim != 0; lim >>= 1) diff --git a/src/port/chklocale.c b/src/port/chklocale.c index 8cb81c8640eee..034939f7fd2c0 100644 --- a/src/port/chklocale.c +++ b/src/port/chklocale.c @@ -4,7 +4,7 @@ * Functions for handling locale-related info * * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -19,7 +19,7 @@ #include "postgres_fe.h" #endif -#ifdef HAVE_LANGINFO_H +#ifndef WIN32 #include #endif @@ -189,7 +189,7 @@ static const struct encoding_match encoding_match_list[] = { #ifdef WIN32 /* - * On Windows, use CP instead of the nl_langinfo() result + * On Windows, use CP instead of CODESET. * * This routine uses GetLocaleInfoEx() to parse short locale names like * "de-DE", "fr-FR", etc. If those cannot be parsed correctly process falls @@ -199,12 +199,10 @@ static const struct encoding_match encoding_match_list[] = { * Returns a malloc()'d string for the caller to free. */ static char * -win32_langinfo(const char *ctype) +win32_get_codeset(const char *ctype) { char *r = NULL; char *codepage; - -#if defined(_MSC_VER) uint32 cp; WCHAR wctype[LOCALE_NAME_MAX_LENGTH]; @@ -229,7 +227,6 @@ win32_langinfo(const char *ctype) } } else -#endif { /* * Locale format on Win32 is _.. For @@ -287,8 +284,6 @@ pg_codepage_to_encoding(UINT cp) #endif #endif /* WIN32 */ -#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) || defined(WIN32) - /* * Given a setting for LC_CTYPE, return the Postgres ID of the associated * encoding, if we can determine it. Return -1 if we can't determine it. @@ -308,63 +303,34 @@ pg_get_encoding_from_locale(const char *ctype, bool write_message) char *sys; int i; - /* Get the CODESET property, and also LC_CTYPE if not passed in */ - if (ctype) - { - char *save; - char *name; - - /* If locale is C or POSIX, we can allow all encodings */ - if (pg_strcasecmp(ctype, "C") == 0 || - pg_strcasecmp(ctype, "POSIX") == 0) - return PG_SQL_ASCII; - - save = setlocale(LC_CTYPE, NULL); - if (!save) - return -1; /* setlocale() broken? */ - /* must copy result, or it might change after setlocale */ - save = strdup(save); - if (!save) - return -1; /* out of memory; unlikely */ - - name = setlocale(LC_CTYPE, ctype); - if (!name) - { - free(save); - return -1; /* bogus ctype passed in? */ - } - #ifndef WIN32 - sys = nl_langinfo(CODESET); - if (sys) - sys = strdup(sys); -#else - sys = win32_langinfo(name); + locale_t loc; #endif - setlocale(LC_CTYPE, save); - free(save); - } - else - { - /* much easier... */ + /* Get the CODESET property, and also LC_CTYPE if not passed in */ + if (!ctype) ctype = setlocale(LC_CTYPE, NULL); - if (!ctype) - return -1; /* setlocale() broken? */ - /* If locale is C or POSIX, we can allow all encodings */ - if (pg_strcasecmp(ctype, "C") == 0 || - pg_strcasecmp(ctype, "POSIX") == 0) - return PG_SQL_ASCII; + + /* If locale is C or POSIX, we can allow all encodings */ + if (pg_strcasecmp(ctype, "C") == 0 || + pg_strcasecmp(ctype, "POSIX") == 0) + return PG_SQL_ASCII; + #ifndef WIN32 - sys = nl_langinfo(CODESET); - if (sys) - sys = strdup(sys); + loc = newlocale(LC_CTYPE_MASK, ctype, (locale_t) 0); + if (loc == (locale_t) 0) + return -1; /* bogus ctype passed in? */ + + sys = nl_langinfo_l(CODESET, loc); + if (sys) + sys = strdup(sys); + + freelocale(loc); #else - sys = win32_langinfo(ctype); + sys = win32_get_codeset(ctype); #endif - } if (!sys) return -1; /* out of memory; unlikely */ @@ -415,19 +381,3 @@ pg_get_encoding_from_locale(const char *ctype, bool write_message) free(sys); return -1; } -#else /* (HAVE_LANGINFO_H && CODESET) || WIN32 */ - -/* - * stub if no multi-language platform support - * - * Note: we could return -1 here, but that would have the effect of - * forcing users to specify an encoding to initdb on such platforms. - * It seems better to silently default to SQL_ASCII. - */ -int -pg_get_encoding_from_locale(const char *ctype, bool write_message) -{ - return PG_SQL_ASCII; -} - -#endif /* (HAVE_LANGINFO_H && CODESET) || WIN32 */ diff --git a/src/port/dirent.c b/src/port/dirent.c index 1f47ea65756c2..a10484ea32cc2 100644 --- a/src/port/dirent.c +++ b/src/port/dirent.c @@ -3,7 +3,7 @@ * dirent.c * opendir/readdir/closedir for win32/msvc * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/dirmod.c b/src/port/dirmod.c index f98d5a7bf2864..c1187d249deca 100644 --- a/src/port/dirmod.c +++ b/src/port/dirmod.c @@ -3,7 +3,7 @@ * dirmod.c * directory handling functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * This includes replacement versions of functions that work on diff --git a/src/port/explicit_bzero.c b/src/port/explicit_bzero.c index 735e21c8b36da..53766e86e940d 100644 --- a/src/port/explicit_bzero.c +++ b/src/port/explicit_bzero.c @@ -2,7 +2,7 @@ * * explicit_bzero.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -12,9 +12,11 @@ *------------------------------------------------------------------------- */ +#define __STDC_WANT_LIB_EXT1__ 1 /* needed to access memset_s() */ + #include "c.h" -#if defined(HAVE_MEMSET_S) +#if HAVE_DECL_MEMSET_S void explicit_bzero(void *buf, size_t len) diff --git a/src/port/getopt.c b/src/port/getopt.c index 207c2836d354b..655fef3b0c771 100644 --- a/src/port/getopt.c +++ b/src/port/getopt.c @@ -26,6 +26,7 @@ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include "c.h" diff --git a/src/port/getpeereid.c b/src/port/getpeereid.c index f1fef91631735..345478599a014 100644 --- a/src/port/getpeereid.c +++ b/src/port/getpeereid.c @@ -3,7 +3,7 @@ * getpeereid.c * get peer userid for UNIX-domain socket connection * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/port/kill.c b/src/port/kill.c index 412c2f19c15d0..72fac20d50715 100644 --- a/src/port/kill.c +++ b/src/port/kill.c @@ -3,7 +3,7 @@ * kill.c * kill() * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * This is a replacement version of kill for Win32 which sends * signals that the backend can recognize. diff --git a/src/port/meson.build b/src/port/meson.build index ff54b7b53e9c5..fc7b059fee50f 100644 --- a/src/port/meson.build +++ b/src/port/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pgport_sources = [ 'bsearch_arg.c', @@ -7,6 +7,10 @@ pgport_sources = [ 'noblock.c', 'path.c', 'pg_bitutils.c', + 'pg_localeconv_r.c', + 'pg_numa.c', + 'pg_popcount_aarch64.c', + 'pg_popcount_avx512.c', 'pg_strong_random.c', 'pgcheckdir.c', 'pgmkdirp.c', @@ -20,7 +24,6 @@ pgport_sources = [ 'snprintf.c', 'strerror.c', 'tar.c', - 'user.c', ] if host_system == 'windows' @@ -71,6 +74,7 @@ replace_funcs_neg = [ ['strlcpy'], ['strnlen'], ['strsep'], + ['timingsafe_bcmp'], ] if host_system != 'windows' @@ -82,11 +86,10 @@ endif replace_funcs_pos = [ # x86/x64 ['pg_crc32c_sse42', 'USE_SSE42_CRC32C'], - ['pg_crc32c_sse42', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 'crc'], + ['pg_crc32c_sse42', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'], + ['pg_crc32c_sse42_choose', 'USE_SSE42_CRC32C'], ['pg_crc32c_sse42_choose', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'], ['pg_crc32c_sb8', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'], - ['pg_popcount_avx512', 'USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 'popcnt'], - ['pg_popcount_avx512_choose', 'USE_AVX512_POPCNT_WITH_RUNTIME_CHECK', 'xsave'], # arm / aarch64 ['pg_crc32c_armv8', 'USE_ARMV8_CRC32C'], @@ -101,8 +104,8 @@ replace_funcs_pos = [ ['pg_crc32c_sb8', 'USE_SLICING_BY_8_CRC32C'], ] -pgport_cflags = {'crc': cflags_crc, 'popcnt': cflags_popcnt, 'xsave': cflags_xsave} -pgport_sources_cflags = {'crc': [], 'popcnt': [], 'xsave': []} +pgport_cflags = {'crc': cflags_crc} +pgport_sources_cflags = {'crc': []} foreach f : replace_funcs_neg func = f.get(0) @@ -186,6 +189,7 @@ foreach name, opts : pgport_variants lib = static_library('libpgport@0@'.format(name), pgport_sources, link_with: cflag_libs, + link_whole: cflag_libs, c_pch: pch_c_h, kwargs: opts + { 'dependencies': opts['dependencies'] + [ssl], diff --git a/src/port/mkdtemp.c b/src/port/mkdtemp.c index 65ba193758bf7..027b95723fee7 100644 --- a/src/port/mkdtemp.c +++ b/src/port/mkdtemp.c @@ -3,7 +3,7 @@ * mkdtemp.c * create a mode-0700 temporary directory * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/port/noblock.c b/src/port/noblock.c index 29a04bb000c8b..eee4d42d861d7 100644 --- a/src/port/noblock.c +++ b/src/port/noblock.c @@ -3,7 +3,7 @@ * noblock.c * set a file descriptor as blocking or non-blocking * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/port/open.c b/src/port/open.c index 13e49af8d4fba..4a31c5d7b778b 100644 --- a/src/port/open.c +++ b/src/port/open.c @@ -4,7 +4,7 @@ * Win32 open() replacement * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/port/open.c * diff --git a/src/port/path.c b/src/port/path.c index 330b3f90332b0..63503409d5a8c 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -3,7 +3,7 @@ * path.c * portable path handling routines * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -32,9 +32,11 @@ #define near #include #else +#include #include #endif +#include "mb/pg_wchar.h" #include "pg_config_paths.h" @@ -44,6 +46,10 @@ #define IS_PATH_VAR_SEP(ch) ((ch) == ';') #endif +#ifdef WIN32 +static void debackslash_path(char *path, int encoding); +static int pg_sjis_mblen(const unsigned char *s); +#endif static void make_relative_path(char *ret_path, const char *target_path, const char *bin_path, const char *my_exec_path); static char *trim_directory(char *path); @@ -148,10 +154,73 @@ last_dir_separator(const char *filename) } +#ifdef WIN32 + +/* + * Convert '\' to '/' within the given path, assuming the path + * is in the specified encoding. + */ +static void +debackslash_path(char *path, int encoding) +{ + char *p; + + /* + * Of the supported encodings, only Shift-JIS has multibyte characters + * that can include a byte equal to '\' (0x5C). So rather than implement + * a fully encoding-aware conversion, we special-case SJIS. (Invoking the + * general encoding-aware logic in wchar.c is impractical here for + * assorted reasons.) + */ + if (encoding == PG_SJIS) + { + for (p = path; *p; p += pg_sjis_mblen((const unsigned char *) p)) + { + if (*p == '\\') + *p = '/'; + } + } + else + { + for (p = path; *p; p++) + { + if (*p == '\\') + *p = '/'; + } + } +} + /* - * make_native_path - on WIN32, change / to \ in the path + * SJIS character length * - * This effectively undoes canonicalize_path. + * This must match the behavior of + * pg_encoding_mblen_bounded(PG_SJIS, s) + * In particular, unlike the version of pg_sjis_mblen in src/common/wchar.c, + * do not allow caller to accidentally step past end-of-string. + */ +static int +pg_sjis_mblen(const unsigned char *s) +{ + int len; + + if (*s >= 0xa1 && *s <= 0xdf) + len = 1; /* 1 byte kana? */ + else if (IS_HIGHBIT_SET(*s) && s[1] != '\0') + len = 2; /* kanji? */ + else + len = 1; /* should be ASCII */ + return len; +} + +#endif /* WIN32 */ + + +/* + * make_native_path - on WIN32, change '/' to '\' in the path + * + * This reverses the '\'-to-'/' transformation of debackslash_path. + * We need not worry about encodings here, since '/' does not appear + * as a byte of a multibyte character in any supported encoding. * * This is required because WIN32 COPY is an internal CMD.EXE * command and doesn't process forward slashes in the same way @@ -181,13 +250,14 @@ make_native_path(char *filename) * on Windows. We need them to use filenames without spaces, for which a * short filename is the safest equivalent, eg: * C:/Progra~1/ + * + * Presently, this is only used on paths that we can assume are in a + * server-safe encoding, so there's no need for an encoding-aware variant. */ void cleanup_path(char *path) { #ifdef WIN32 - char *ptr; - /* * GetShortPathName() will fail if the path does not exist, or short names * are disabled on this file system. In both cases, we just return the @@ -197,11 +267,8 @@ cleanup_path(char *path) GetShortPathName(path, path, MAXPGPATH - 1); /* Replace '\' with '/' */ - for (ptr = path; *ptr; ptr++) - { - if (*ptr == '\\') - *ptr = '/'; - } + /* All server-safe encodings are alike here, so just use PG_SQL_ASCII */ + debackslash_path(path, PG_SQL_ASCII); #endif } @@ -252,6 +319,8 @@ typedef enum } canonicalize_state; /* + * canonicalize_path() + * * Clean up path by: * o make Win32 path use Unix slashes * o remove trailing quote on Win32 @@ -259,9 +328,20 @@ typedef enum * o remove duplicate (adjacent) separators * o remove '.' (unless path reduces to only '.') * o process '..' ourselves, removing it if possible + * Modifies path in-place. + * + * This comes in two variants: encoding-aware and not. The non-aware version + * is only safe to use on strings that are in a server-safe encoding. */ void canonicalize_path(char *path) +{ + /* All server-safe encodings are alike here, so just use PG_SQL_ASCII */ + canonicalize_path_enc(path, PG_SQL_ASCII); +} + +void +canonicalize_path_enc(char *path, int encoding) { char *p, *to_p; @@ -277,17 +357,15 @@ canonicalize_path(char *path) /* * The Windows command processor will accept suitably quoted paths with * forward slashes, but barfs badly with mixed forward and back slashes. + * Hence, start by converting all back slashes to forward slashes. */ - for (p = path; *p; p++) - { - if (*p == '\\') - *p = '/'; - } + debackslash_path(path, encoding); /* * In Win32, if you do: prog.exe "a b" "\c\d\" the system will pass \c\d" * as argv[2], so trim off trailing quote. */ + p = path + strlen(path); if (p > path && *(p - 1) == '"') *(p - 1) = '/'; #endif @@ -934,10 +1012,24 @@ get_home_path(char *ret_path) const char *home; home = getenv("HOME"); - if (home == NULL || home[0] == '\0') - return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH); - strlcpy(ret_path, home, MAXPGPATH); - return true; + if (home && home[0]) + { + strlcpy(ret_path, home, MAXPGPATH); + return true; + } + else + { + struct passwd pwbuf; + struct passwd *pw; + char buf[1024]; + int rc; + + rc = getpwuid_r(geteuid(), &pwbuf, buf, sizeof buf, &pw); + if (rc != 0 || !pw) + return false; + strlcpy(ret_path, pw->pw_dir, MAXPGPATH); + return true; + } #else char *tmppath; diff --git a/src/port/pg_bitutils.c b/src/port/pg_bitutils.c index 87f56e82b8010..61c7388f47477 100644 --- a/src/port/pg_bitutils.c +++ b/src/port/pg_bitutils.c @@ -3,7 +3,7 @@ * pg_bitutils.c * Miscellaneous functions for bit-wise operations. * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/pg_bitutils.c @@ -103,12 +103,17 @@ const uint8 pg_number_of_ones[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; +/* + * If we are building the Neon versions, we don't need the "slow" fallbacks. + */ +#ifndef POPCNT_AARCH64 static inline int pg_popcount32_slow(uint32 word); static inline int pg_popcount64_slow(uint64 word); static uint64 pg_popcount_slow(const char *buf, int bytes); static uint64 pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask); +#endif -#ifdef TRY_POPCNT_FAST +#ifdef TRY_POPCNT_X86_64 static bool pg_popcount_available(void); static int pg_popcount32_choose(uint32 word); static int pg_popcount64_choose(uint64 word); @@ -123,9 +128,9 @@ int (*pg_popcount32) (uint32 word) = pg_popcount32_choose; int (*pg_popcount64) (uint64 word) = pg_popcount64_choose; uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; -#endif /* TRY_POPCNT_FAST */ +#endif /* TRY_POPCNT_X86_64 */ -#ifdef TRY_POPCNT_FAST +#ifdef TRY_POPCNT_X86_64 /* * Return true if CPUID indicates that the POPCNT instruction is available. @@ -337,8 +342,12 @@ pg_popcount_masked_fast(const char *buf, int bytes, bits8 mask) return popcnt; } -#endif /* TRY_POPCNT_FAST */ +#endif /* TRY_POPCNT_X86_64 */ +/* + * If we are building the Neon versions, we don't need the "slow" fallbacks. + */ +#ifndef POPCNT_AARCH64 /* * pg_popcount32_slow @@ -370,12 +379,12 @@ static inline int pg_popcount64_slow(uint64 word) { #ifdef HAVE__BUILTIN_POPCOUNT -#if defined(HAVE_LONG_INT_64) +#if SIZEOF_LONG == 8 return __builtin_popcountl(word); -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_LONG_LONG == 8 return __builtin_popcountll(word); #else -#error must have a working 64-bit integer datatype +#error "cannot find integer of the same size as uint64_t" #endif #else /* !HAVE__BUILTIN_POPCOUNT */ int result = 0; @@ -486,14 +495,15 @@ pg_popcount_masked_slow(const char *buf, int bytes, bits8 mask) return popcnt; } -#ifndef TRY_POPCNT_FAST +#endif /* ! POPCNT_AARCH64 */ + +#if !defined(TRY_POPCNT_X86_64) && !defined(POPCNT_AARCH64) /* - * When the POPCNT instruction is not available, there's no point in using + * When special CPU instructions are not available, there's no point in using * function pointers to vary the implementation between the fast and slow - * method. We instead just make these actual external functions when - * TRY_POPCNT_FAST is not defined. The compiler should be able to inline - * the slow versions here. + * method. We instead just make these actual external functions. The compiler + * should be able to inline the slow versions here. */ int pg_popcount32(uint32 word) @@ -527,4 +537,4 @@ pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask) return pg_popcount_masked_slow(buf, bytes, mask); } -#endif /* !TRY_POPCNT_FAST */ +#endif /* ! TRY_POPCNT_X86_64 && ! POPCNT_AARCH64 */ diff --git a/src/port/pg_crc32c_armv8.c b/src/port/pg_crc32c_armv8.c index d47d838c50b2b..5ba070bb99d8b 100644 --- a/src/port/pg_crc32c_armv8.c +++ b/src/port/pg_crc32c_armv8.c @@ -3,7 +3,7 @@ * pg_crc32c_armv8.c * Compute CRC-32C checksum using ARMv8 CRC Extension instructions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/pg_crc32c_armv8_choose.c b/src/port/pg_crc32c_armv8_choose.c index eaf39cf3e8176..ec12be1bbc393 100644 --- a/src/port/pg_crc32c_armv8_choose.c +++ b/src/port/pg_crc32c_armv8_choose.c @@ -8,7 +8,7 @@ * computation. Otherwise, fall back to the pure software implementation * (slicing-by-8). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -24,57 +24,87 @@ #include "postgres_fe.h" #endif -#include -#include - -#include "port/pg_crc32c.h" - +#if defined(HAVE_ELF_AUX_INFO) || defined(HAVE_GETAUXVAL) +#include +#if defined(__linux__) && !defined(__aarch64__) && !defined(HWCAP2_CRC32) +#include +#endif +#endif -static sigjmp_buf illegal_instruction_jump; +#if defined(__NetBSD__) +#include +#if defined(__aarch64__) +#include +#endif +#endif -/* - * Probe by trying to execute pg_comp_crc32c_armv8(). If the instruction - * isn't available, we expect to get SIGILL, which we can trap. - */ -static void -illegal_instruction_handler(SIGNAL_ARGS) -{ - siglongjmp(illegal_instruction_jump, 1); -} +#include "port/pg_crc32c.h" static bool pg_crc32c_armv8_available(void) { - uint64 data = 42; - int result; +#if defined(HAVE_ELF_AUX_INFO) + unsigned long value; +#ifdef __aarch64__ + return elf_aux_info(AT_HWCAP, &value, sizeof(value)) == 0 && + (value & HWCAP_CRC32) != 0; +#else + return elf_aux_info(AT_HWCAP2, &value, sizeof(value)) == 0 && + (value & HWCAP2_CRC32) != 0; +#endif +#elif defined(HAVE_GETAUXVAL) +#ifdef __aarch64__ + return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0; +#else + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0; +#endif +#elif defined(__NetBSD__) /* - * Be careful not to do anything that might throw an error while we have - * the SIGILL handler set to a nonstandard value. + * On NetBSD we can read the Instruction Set Attribute Registers via + * sysctl. For doubtless-historical reasons the sysctl interface is + * completely different on 64-bit than 32-bit, but the underlying + * registers contain the same fields. */ - pqsignal(SIGILL, illegal_instruction_handler); - if (sigsetjmp(illegal_instruction_jump, 1) == 0) - { - /* Rather than hard-wiring an expected result, compare to SB8 code */ - result = (pg_comp_crc32c_armv8(0, &data, sizeof(data)) == - pg_comp_crc32c_sb8(0, &data, sizeof(data))); - } - else - { - /* We got the SIGILL trap */ - result = -1; - } - pqsignal(SIGILL, SIG_DFL); +#define ISAR0_CRC32_BITPOS 16 +#define ISAR0_CRC32_BITWIDTH 4 +#define WIDTHMASK(w) ((1 << (w)) - 1) +#define SYSCTL_CPU_ID_MAXSIZE 64 -#ifndef FRONTEND - /* We don't expect this case, so complain loudly */ - if (result == 0) - elog(ERROR, "crc32 hardware and software results disagree"); - - elog(DEBUG1, "using armv8 crc32 hardware = %d", (result > 0)); + size_t len; + uint64 sysctlbuf[SYSCTL_CPU_ID_MAXSIZE]; +#if defined(__aarch64__) + /* We assume cpu0 is representative of all the machine's CPUs. */ + const char *path = "machdep.cpu0.cpu_id"; + size_t expected_len = sizeof(struct aarch64_sysctl_cpu_id); +#define ISAR0 ((struct aarch64_sysctl_cpu_id *) sysctlbuf)->ac_aa64isar0 +#else + const char *path = "machdep.id_isar"; + size_t expected_len = 6 * sizeof(int); +#define ISAR0 ((int *) sysctlbuf)[5] #endif + uint64 fld; - return (result > 0); + /* Fetch the appropriate set of register values. */ + len = sizeof(sysctlbuf); + memset(sysctlbuf, 0, len); + if (sysctlbyname(path, sysctlbuf, &len, NULL, 0) != 0) + return false; /* perhaps kernel is 64-bit and we aren't? */ + if (len != expected_len) + return false; /* kernel API change? */ + + /* Fetch the CRC32 field from ISAR0. */ + fld = (ISAR0 >> ISAR0_CRC32_BITPOS) & WIDTHMASK(ISAR0_CRC32_BITWIDTH); + + /* + * Current documentation defines only the field values 0 (No CRC32) and 1 + * (CRC32B/CRC32H/CRC32W/CRC32X/CRC32CB/CRC32CH/CRC32CW/CRC32CX). Assume + * that any future nonzero value will be a superset of 1. + */ + return (fld != 0); +#else + return false; +#endif } /* diff --git a/src/port/pg_crc32c_loongarch.c b/src/port/pg_crc32c_loongarch.c index 2004b840c8ddf..90679ce0d0cf3 100644 --- a/src/port/pg_crc32c_loongarch.c +++ b/src/port/pg_crc32c_loongarch.c @@ -3,7 +3,7 @@ * pg_crc32c_loongarch.c * Compute CRC-32C checksum using LoongArch CRCC instructions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/pg_crc32c_sb8.c b/src/port/pg_crc32c_sb8.c index eda20fa747fa9..19659d186a00b 100644 --- a/src/port/pg_crc32c_sb8.c +++ b/src/port/pg_crc32c_sb8.c @@ -8,7 +8,7 @@ * Generation", IEEE Transactions on Computers, vol.57, no. 11, * pp. 1550-1560, November 2008, doi:10.1109/TC.2008.85 * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/pg_crc32c_sse42.c b/src/port/pg_crc32c_sse42.c index 7f88c1148009b..9af3474a6ca95 100644 --- a/src/port/pg_crc32c_sse42.c +++ b/src/port/pg_crc32c_sse42.c @@ -1,9 +1,9 @@ /*------------------------------------------------------------------------- * * pg_crc32c_sse42.c - * Compute CRC-32C checksum using Intel SSE 4.2 instructions. + * Compute CRC-32C checksum using Intel SSE 4.2 or AVX-512 instructions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -15,10 +15,14 @@ #include "c.h" #include +#ifdef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK +#include +#endif #include "port/pg_crc32c.h" pg_attribute_no_sanitize_alignment() +pg_attribute_target("sse4.2") pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len) { @@ -67,3 +71,91 @@ pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len) return crc; } + +#ifdef USE_AVX512_CRC32C_WITH_RUNTIME_CHECK + +/* + * Note: There is no copyright notice in the following generated code. + * + * We have modified the output to + * - match our function declaration + * - match whitespace to our project style + * - add a threshold for the alignment stanza + */ + +/* Generated by https://github.com/corsix/fast-crc32/ using: */ +/* ./generate -i avx512_vpclmulqdq -p crc32c -a v1e */ +/* MIT licensed */ + +#define clmul_lo(a, b) (_mm512_clmulepi64_epi128((a), (b), 0)) +#define clmul_hi(a, b) (_mm512_clmulepi64_epi128((a), (b), 17)) + +pg_attribute_target("vpclmulqdq,avx512vl") +pg_crc32c +pg_comp_crc32c_avx512(pg_crc32c crc, const void *data, size_t len) +{ + /* adjust names to match generated code */ + pg_crc32c crc0 = crc; + const char *buf = data; + + /* Align on cacheline boundary. The threshold is somewhat arbitrary. */ + if (unlikely(len > 256)) + { + for (; len && ((uintptr_t) buf & 7); --len) + crc0 = _mm_crc32_u8(crc0, *buf++); + while (((uintptr_t) buf & 56) && len >= 8) + { + crc0 = _mm_crc32_u64(crc0, *(const uint64_t *) buf); + buf += 8; + len -= 8; + } + } + + if (len >= 64) + { + const char *end = buf + len; + const char *limit = buf + len - 64; + __m128i z0; + + /* First vector chunk. */ + __m512i x0 = _mm512_loadu_si512((const void *) buf), + y0; + __m512i k; + + k = _mm512_broadcast_i32x4(_mm_setr_epi32(0x740eef02, 0, 0x9e4addf8, 0)); + x0 = _mm512_xor_si512(_mm512_castsi128_si512(_mm_cvtsi32_si128(crc0)), x0); + buf += 64; + + /* Main loop. */ + while (buf <= limit) + { + y0 = clmul_lo(x0, k), x0 = clmul_hi(x0, k); + x0 = _mm512_ternarylogic_epi64(x0, y0, + _mm512_loadu_si512((const void *) buf), + 0x96); + buf += 64; + } + + /* Reduce 512 bits to 128 bits. */ + k = _mm512_setr_epi32(0x1c291d04, 0, 0xddc0152b, 0, + 0x3da6d0cb, 0, 0xba4fc28e, 0, + 0xf20c0dfe, 0, 0x493c7d27, 0, + 0, 0, 0, 0); + y0 = clmul_lo(x0, k), k = clmul_hi(x0, k); + y0 = _mm512_xor_si512(y0, k); + z0 = _mm_ternarylogic_epi64(_mm512_castsi512_si128(y0), + _mm512_extracti32x4_epi32(y0, 1), + _mm512_extracti32x4_epi32(y0, 2), + 0x96); + z0 = _mm_xor_si128(z0, _mm512_extracti32x4_epi32(x0, 3)); + + /* Reduce 128 bits to 32 bits, and multiply by x^32. */ + crc0 = _mm_crc32_u64(0, _mm_extract_epi64(z0, 0)); + crc0 = _mm_crc32_u64(crc0, _mm_extract_epi64(z0, 1)); + len = end - buf; + } + + return pg_comp_crc32c_sse42(crc0, buf, len); +} + +#endif diff --git a/src/port/pg_crc32c_sse42_choose.c b/src/port/pg_crc32c_sse42_choose.c index 56d600f3a932b..802e47788c10c 100644 --- a/src/port/pg_crc32c_sse42_choose.c +++ b/src/port/pg_crc32c_sse42_choose.c @@ -8,7 +8,7 @@ * computation. Otherwise, fall back to the pure software implementation * (slicing-by-8). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -20,30 +20,37 @@ #include "c.h" -#ifdef HAVE__GET_CPUID +#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) #include #endif -#ifdef HAVE__CPUID +#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) #include #endif +#ifdef HAVE_XSAVE_INTRINSICS +#include +#endif + #include "port/pg_crc32c.h" +/* + * Does XGETBV say the ZMM registers are enabled? + * + * NB: Caller is responsible for verifying that osxsave is available + * before calling this. + */ +#ifdef HAVE_XSAVE_INTRINSICS +pg_attribute_target("xsave") +#endif static bool -pg_crc32c_sse42_available(void) +zmm_regs_available(void) { - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); +#ifdef HAVE_XSAVE_INTRINSICS + return (_xgetbv(0) & 0xe6) == 0xe6; #else -#error cpuid instruction not available + return false; #endif - - return (exx[2] & (1 << 20)) != 0; /* SSE 4.2 */ } /* @@ -53,10 +60,50 @@ pg_crc32c_sse42_available(void) static pg_crc32c pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len) { - if (pg_crc32c_sse42_available()) + unsigned int exx[4] = {0, 0, 0, 0}; + + /* + * Set fallback. We must guard since slicing-by-8 is not visible + * everywhere. + */ +#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK + pg_comp_crc32c = pg_comp_crc32c_sb8; +#endif + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + + if ((exx[2] & (1 << 20)) != 0) /* SSE 4.2 */ + { pg_comp_crc32c = pg_comp_crc32c_sse42; - else - pg_comp_crc32c = pg_comp_crc32c_sb8; + + if (exx[2] & (1 << 27) && /* OSXSAVE */ + zmm_regs_available()) + { + /* second cpuid call on leaf 7 to check extended AVX-512 support */ + + memset(exx, 0, 4 * sizeof(exx[0])); + +#if defined(HAVE__GET_CPUID_COUNT) + __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUIDEX) + __cpuidex(exx, 7, 0); +#endif + +#if defined(__clang__) && !defined(__OPTIMIZE__) + /* Some versions of clang are broken at -O0 */ +#elif defined(USE_AVX512_CRC32C_WITH_RUNTIME_CHECK) + if (exx[2] & (1 << 10) && /* VPCLMULQDQ */ + exx[1] & (1 << 31)) /* AVX512-VL */ + pg_comp_crc32c = pg_comp_crc32c_avx512; +#endif + } + } return pg_comp_crc32c(crc, data, len); } diff --git a/src/port/pg_localeconv_r.c b/src/port/pg_localeconv_r.c new file mode 100644 index 0000000000000..61510b2e0ea37 --- /dev/null +++ b/src/port/pg_localeconv_r.c @@ -0,0 +1,368 @@ +/*------------------------------------------------------------------------- + * + * pg_localeconv_r.c + * Thread-safe implementations of localeconv() + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/port/pg_localeconv_r.c + * + *------------------------------------------------------------------------- + */ + +#include "c.h" + +#if !defined(WIN32) +#include +#include +#endif + +#include + +#ifdef MON_THOUSANDS_SEP +/* + * One of glibc's extended langinfo items detected. Assume that the full set + * is present, which means we can use nl_langinfo_l() instead of localeconv(). + */ +#define TRANSLATE_FROM_LANGINFO +#endif + +struct lconv_member_info +{ + bool is_string; + int category; + size_t offset; +#ifdef TRANSLATE_FROM_LANGINFO + nl_item item; +#endif +}; + +/* Some macros to declare the lconv members compactly. */ +#ifdef TRANSLATE_FROM_LANGINFO +#define LCONV_M(is_string, category, name, item) \ + { is_string, category, offsetof(struct lconv, name), item } +#else +#define LCONV_M(is_string, category, name, item) \ + { is_string, category, offsetof(struct lconv, name) } +#endif +#define LCONV_S(c, n, i) LCONV_M(true, c, n, i) +#define LCONV_C(c, n, i) LCONV_M(false, c, n, i) + +/* + * The work of populating lconv objects is driven by this table. Since we + * tolerate non-matching encodings in LC_NUMERIC and LC_MONETARY, we have to + * call the underlying OS routine multiple times, with the correct locales. + * The first column of this table says which locale category applies to each struct + * member. The second column is the name of the struct member. The third + * column is the name of the nl_item, if translating from nl_langinfo_l() (it's + * always the member name, in upper case). + */ +static const struct lconv_member_info table[] = { + /* String fields. */ + LCONV_S(LC_NUMERIC, decimal_point, DECIMAL_POINT), + LCONV_S(LC_NUMERIC, thousands_sep, THOUSANDS_SEP), + LCONV_S(LC_NUMERIC, grouping, GROUPING), + LCONV_S(LC_MONETARY, int_curr_symbol, INT_CURR_SYMBOL), + LCONV_S(LC_MONETARY, currency_symbol, CURRENCY_SYMBOL), + LCONV_S(LC_MONETARY, mon_decimal_point, MON_DECIMAL_POINT), + LCONV_S(LC_MONETARY, mon_thousands_sep, MON_THOUSANDS_SEP), + LCONV_S(LC_MONETARY, mon_grouping, MON_GROUPING), + LCONV_S(LC_MONETARY, positive_sign, POSITIVE_SIGN), + LCONV_S(LC_MONETARY, negative_sign, NEGATIVE_SIGN), + + /* Character fields. */ + LCONV_C(LC_MONETARY, int_frac_digits, INT_FRAC_DIGITS), + LCONV_C(LC_MONETARY, frac_digits, FRAC_DIGITS), + LCONV_C(LC_MONETARY, p_cs_precedes, P_CS_PRECEDES), + LCONV_C(LC_MONETARY, p_sep_by_space, P_SEP_BY_SPACE), + LCONV_C(LC_MONETARY, n_cs_precedes, N_CS_PRECEDES), + LCONV_C(LC_MONETARY, n_sep_by_space, N_SEP_BY_SPACE), + LCONV_C(LC_MONETARY, p_sign_posn, P_SIGN_POSN), + LCONV_C(LC_MONETARY, n_sign_posn, N_SIGN_POSN), +}; + +static inline char ** +lconv_string_member(struct lconv *lconv, int i) +{ + return (char **) ((char *) lconv + table[i].offset); +} + +static inline char * +lconv_char_member(struct lconv *lconv, int i) +{ + return (char *) lconv + table[i].offset; +} + +/* + * Free the members of a struct lconv populated by pg_localeconv_r(). The + * struct itself is in storage provided by the caller of pg_localeconv_r(). + */ +void +pg_localeconv_free(struct lconv *lconv) +{ + for (int i = 0; i < lengthof(table); ++i) + if (table[i].is_string) + free(*lconv_string_member(lconv, i)); +} + +#ifdef TRANSLATE_FROM_LANGINFO +/* + * Fill in struct lconv members using the equivalent nl_langinfo_l() items. + */ +static int +pg_localeconv_from_langinfo(struct lconv *dst, + locale_t monetary_locale, + locale_t numeric_locale) +{ + for (int i = 0; i < lengthof(table); ++i) + { + locale_t locale; + + locale = table[i].category == LC_NUMERIC ? + numeric_locale : monetary_locale; + + if (table[i].is_string) + { + char *string; + + string = nl_langinfo_l(table[i].item, locale); + if (!(string = strdup(string))) + { + pg_localeconv_free(dst); + errno = ENOMEM; + return -1; + } + *lconv_string_member(dst, i) = string; + } + else + { + *lconv_char_member(dst, i) = + *nl_langinfo_l(table[i].item, locale); + } + } + + return 0; +} +#else /* not TRANSLATE_FROM_LANGINFO */ +/* + * Copy members from a given category. Note that you have to call this twice + * to copy the LC_MONETARY and then LC_NUMERIC members. + */ +static int +pg_localeconv_copy_members(struct lconv *dst, + struct lconv *src, + int category) +{ + for (int i = 0; i < lengthof(table); ++i) + { + if (table[i].category != category) + continue; + + if (table[i].is_string) + { + char *string; + + string = *lconv_string_member(src, i); + if (!(string = strdup(string))) + { + pg_localeconv_free(dst); + errno = ENOMEM; + return -1; + } + *lconv_string_member(dst, i) = string; + } + else + { + *lconv_char_member(dst, i) = *lconv_char_member(src, i); + } + } + + return 0; +} +#endif /* not TRANSLATE_FROM_LANGINFO */ + +/* + * A thread-safe routine to get a copy of the lconv struct for a given + * LC_NUMERIC and LC_MONETARY. Different approaches are used on different + * OSes, because the standard interface is so multi-threading unfriendly. + * + * 1. On Windows, there is no uselocale(), but there is a way to put + * setlocale() into a thread-local mode temporarily. Its localeconv() is + * documented as returning a pointer to thread-local storage, so we don't have + * to worry about concurrent callers. + * + * 2. On Glibc, as an extension, all the information required to populate + * struct lconv is also available via nl_langpath_l(), which is thread-safe. + * + * 3. On macOS and *BSD, there is localeconv_l(), so we can create a temporary + * locale_t to pass in, and the result is a pointer to storage associated with + * the locale_t so we control its lifetime and we don't have to worry about + * concurrent calls clobbering it. + * + * 4. Otherwise, we wrap plain old localeconv() in uselocale() to avoid + * touching the global locale, but the output buffer is allowed by the standard + * to be overwritten by concurrent calls to localeconv(). We protect against + * _this_ function doing that with a Big Lock, but there isn't much we can do + * about code outside our tree that might call localeconv(), given such a poor + * interface. + * + * The POSIX standard explicitly says that it is undefined what happens if + * LC_MONETARY or LC_NUMERIC imply an encoding (codeset) different from that + * implied by LC_CTYPE. In practice, all Unix-ish platforms seem to believe + * that localeconv() should return strings that are encoded in the codeset + * implied by the LC_MONETARY or LC_NUMERIC locale name. On Windows, LC_CTYPE + * has to match to get sane results. + * + * To get predictable results on all platforms, we'll call the underlying + * routines with LC_ALL set to the appropriate locale for each set of members, + * and merge the results. Three members of the resulting object are therefore + * guaranteed to be encoded with LC_NUMERIC's codeset: "decimal_point", + * "thousands_sep" and "grouping". All other members are encoded with + * LC_MONETARY's codeset. + * + * Returns 0 on success. Returns non-zero on failure, and sets errno. On + * success, the caller is responsible for calling pg_localeconv_free() on the + * output struct to free the string members it contains. + */ +int +pg_localeconv_r(const char *lc_monetary, + const char *lc_numeric, + struct lconv *output) +{ +#ifdef WIN32 + wchar_t *save_lc_ctype = NULL; + wchar_t *save_lc_monetary = NULL; + wchar_t *save_lc_numeric = NULL; + int save_config_thread_locale; + int result = -1; + + /* Put setlocale() into thread-local mode. */ + save_config_thread_locale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); + + /* + * Capture the current values as wide strings. Otherwise, we might not be + * able to restore them if their names contain non-ASCII characters and + * the intermediate locale changes the expected encoding. We don't want + * to leave the caller in an unexpected state by failing to restore, or + * crash the runtime library. + */ + save_lc_ctype = _wsetlocale(LC_CTYPE, NULL); + if (!save_lc_ctype || !(save_lc_ctype = wcsdup(save_lc_ctype))) + goto exit; + save_lc_monetary = _wsetlocale(LC_MONETARY, NULL); + if (!save_lc_monetary || !(save_lc_monetary = wcsdup(save_lc_monetary))) + goto exit; + save_lc_numeric = _wsetlocale(LC_NUMERIC, NULL); + if (!save_lc_numeric || !(save_lc_numeric = wcsdup(save_lc_numeric))) + goto exit; + + memset(output, 0, sizeof(*output)); + + /* Copy the LC_MONETARY members. */ + if (!setlocale(LC_ALL, lc_monetary)) + goto exit; + result = pg_localeconv_copy_members(output, localeconv(), LC_MONETARY); + if (result != 0) + goto exit; + + /* Copy the LC_NUMERIC members. */ + if (!setlocale(LC_ALL, lc_numeric)) + goto exit; + result = pg_localeconv_copy_members(output, localeconv(), LC_NUMERIC); + +exit: + /* Restore everything we changed. */ + if (save_lc_ctype) + { + _wsetlocale(LC_CTYPE, save_lc_ctype); + free(save_lc_ctype); + } + if (save_lc_monetary) + { + _wsetlocale(LC_MONETARY, save_lc_monetary); + free(save_lc_monetary); + } + if (save_lc_numeric) + { + _wsetlocale(LC_NUMERIC, save_lc_numeric); + free(save_lc_numeric); + } + _configthreadlocale(save_config_thread_locale); + + return result; + +#else /* !WIN32 */ + locale_t monetary_locale; + locale_t numeric_locale; + int result; + + /* + * All variations on Unix require locale_t objects for LC_MONETARY and + * LC_NUMERIC. We'll set all locale categories, so that we can don't have + * to worry about POSIX's undefined behavior if LC_CTYPE's encoding + * doesn't match. + */ + errno = ENOENT; + monetary_locale = newlocale(LC_ALL_MASK, lc_monetary, 0); + if (monetary_locale == 0) + return -1; + numeric_locale = newlocale(LC_ALL_MASK, lc_numeric, 0); + if (numeric_locale == 0) + { + freelocale(monetary_locale); + return -1; + } + + memset(output, 0, sizeof(*output)); +#if defined(TRANSLATE_FROM_LANGINFO) + /* Copy from non-standard nl_langinfo_l() extended items. */ + result = pg_localeconv_from_langinfo(output, + monetary_locale, + numeric_locale); +#elif defined(HAVE_LOCALECONV_L) + /* Copy the LC_MONETARY members from a thread-safe lconv object. */ + result = pg_localeconv_copy_members(output, + localeconv_l(monetary_locale), + LC_MONETARY); + if (result == 0) + { + /* Copy the LC_NUMERIC members from a thread-safe lconv object. */ + result = pg_localeconv_copy_members(output, + localeconv_l(numeric_locale), + LC_NUMERIC); + } +#else + /* We have nothing better than standard POSIX facilities. */ + { + static pthread_mutex_t big_lock = PTHREAD_MUTEX_INITIALIZER; + locale_t save_locale; + + pthread_mutex_lock(&big_lock); + /* Copy the LC_MONETARY members. */ + save_locale = uselocale(monetary_locale); + result = pg_localeconv_copy_members(output, + localeconv(), + LC_MONETARY); + if (result == 0) + { + /* Copy the LC_NUMERIC members. */ + uselocale(numeric_locale); + result = pg_localeconv_copy_members(output, + localeconv(), + LC_NUMERIC); + } + pthread_mutex_unlock(&big_lock); + + uselocale(save_locale); + } +#endif + + freelocale(monetary_locale); + freelocale(numeric_locale); + + return result; +#endif /* !WIN32 */ +} diff --git a/src/port/pg_numa.c b/src/port/pg_numa.c new file mode 100644 index 0000000000000..4b487a2a4e814 --- /dev/null +++ b/src/port/pg_numa.c @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------- + * + * pg_numa.c + * Basic NUMA portability routines + * + * + * Copyright (c) 2025, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/port/pg_numa.c + * + *------------------------------------------------------------------------- + */ + +#include "c.h" +#include + +#include "port/pg_numa.h" + +/* + * At this point we provide support only for Linux thanks to libnuma, but in + * future support for other platforms e.g. Win32 or FreeBSD might be possible + * too. For Win32 NUMA APIs see + * https://learn.microsoft.com/en-us/windows/win32/procthread/numa-support + */ +#ifdef USE_LIBNUMA + +#include +#include + +/* libnuma requires initialization as per numa(3) on Linux */ +int +pg_numa_init(void) +{ + int r = numa_available(); + + return r; +} + +/* + * We use move_pages(2) syscall here - instead of get_mempolicy(2) - as the + * first one allows us to batch and query about many memory pages in one single + * giant system call that is way faster. + */ +int +pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status) +{ + return numa_move_pages(pid, count, pages, NULL, status, 0); +} + +int +pg_numa_get_max_node(void) +{ + return numa_max_node(); +} + +#else + +/* Empty wrappers */ +int +pg_numa_init(void) +{ + /* We state that NUMA is not available */ + return -1; +} + +int +pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status) +{ + return 0; +} + +int +pg_numa_get_max_node(void) +{ + return 0; +} + +#endif diff --git a/src/port/pg_popcount_aarch64.c b/src/port/pg_popcount_aarch64.c new file mode 100644 index 0000000000000..e515e4d45b8c4 --- /dev/null +++ b/src/port/pg_popcount_aarch64.c @@ -0,0 +1,477 @@ +/*------------------------------------------------------------------------- + * + * pg_popcount_aarch64.c + * Holds the AArch64 popcount implementations. + * + * Copyright (c) 2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/port/pg_popcount_aarch64.c + * + *------------------------------------------------------------------------- + */ +#include "c.h" + +#include "port/pg_bitutils.h" + +#ifdef POPCNT_AARCH64 + +#include + +#ifdef USE_SVE_POPCNT_WITH_RUNTIME_CHECK +#include + +#if defined(HAVE_ELF_AUX_INFO) || defined(HAVE_GETAUXVAL) +#include +#endif +#endif + +/* + * The Neon versions are built regardless of whether we are building the SVE + * versions. + */ +static uint64 pg_popcount_neon(const char *buf, int bytes); +static uint64 pg_popcount_masked_neon(const char *buf, int bytes, bits8 mask); + +#ifdef USE_SVE_POPCNT_WITH_RUNTIME_CHECK + +/* + * These are the SVE implementations of the popcount functions. + */ +static uint64 pg_popcount_sve(const char *buf, int bytes); +static uint64 pg_popcount_masked_sve(const char *buf, int bytes, bits8 mask); + +/* + * The function pointers are initially set to "choose" functions. These + * functions will first set the pointers to the right implementations (based on + * what the current CPU supports) and then will call the pointer to fulfill the + * caller's request. + */ +static uint64 pg_popcount_choose(const char *buf, int bytes); +static uint64 pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask); +uint64 (*pg_popcount_optimized) (const char *buf, int bytes) = pg_popcount_choose; +uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask) = pg_popcount_masked_choose; + +static inline bool +pg_popcount_sve_available(void) +{ +#ifdef HAVE_ELF_AUX_INFO + unsigned long value; + + return elf_aux_info(AT_HWCAP, &value, sizeof(value)) == 0 && + (value & HWCAP_SVE) != 0; +#elif defined(HAVE_GETAUXVAL) + return (getauxval(AT_HWCAP) & HWCAP_SVE) != 0; +#else + return false; +#endif +} + +static inline void +choose_popcount_functions(void) +{ + if (pg_popcount_sve_available()) + { + pg_popcount_optimized = pg_popcount_sve; + pg_popcount_masked_optimized = pg_popcount_masked_sve; + } + else + { + pg_popcount_optimized = pg_popcount_neon; + pg_popcount_masked_optimized = pg_popcount_masked_neon; + } +} + +static uint64 +pg_popcount_choose(const char *buf, int bytes) +{ + choose_popcount_functions(); + return pg_popcount_optimized(buf, bytes); +} + +static uint64 +pg_popcount_masked_choose(const char *buf, int bytes, bits8 mask) +{ + choose_popcount_functions(); + return pg_popcount_masked_optimized(buf, bytes, mask); +} + +/* + * pg_popcount_sve + * Returns number of 1 bits in buf + */ +pg_attribute_target("arch=armv8-a+sve") +static uint64 +pg_popcount_sve(const char *buf, int bytes) +{ + svbool_t pred = svptrue_b64(); + svuint64_t accum1 = svdup_u64(0), + accum2 = svdup_u64(0), + accum3 = svdup_u64(0), + accum4 = svdup_u64(0); + uint32 vec_len = svcntb(), + bytes_per_iteration = 4 * vec_len; + uint64 popcnt = 0; + + /* + * For better instruction-level parallelism, each loop iteration operates + * on a block of four registers. + */ + for (; bytes >= bytes_per_iteration; bytes -= bytes_per_iteration) + { + svuint64_t vec; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum3 = svadd_u64_x(pred, accum3, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum4 = svadd_u64_x(pred, accum4, svcnt_u64_x(pred, vec)); + buf += vec_len; + } + + /* + * If enough data remains, do another iteration on a block of two + * registers. + */ + bytes_per_iteration = 2 * vec_len; + if (bytes >= bytes_per_iteration) + { + svuint64_t vec; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svld1_u64(pred, (const uint64 *) buf); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec)); + buf += vec_len; + + bytes -= bytes_per_iteration; + } + + /* + * Add the accumulators. + */ + popcnt += svaddv_u64(pred, svadd_u64_x(pred, accum1, accum2)); + popcnt += svaddv_u64(pred, svadd_u64_x(pred, accum3, accum4)); + + /* + * Process any remaining data. + */ + for (; bytes > 0; bytes -= vec_len) + { + svuint8_t vec; + + pred = svwhilelt_b8_s32(0, bytes); + vec = svld1_u8(pred, (const uint8 *) buf); + popcnt += svaddv_u8(pred, svcnt_u8_x(pred, vec)); + buf += vec_len; + } + + return popcnt; +} + +/* + * pg_popcount_masked_sve + * Returns number of 1 bits in buf after applying the mask to each byte + */ +pg_attribute_target("arch=armv8-a+sve") +static uint64 +pg_popcount_masked_sve(const char *buf, int bytes, bits8 mask) +{ + svbool_t pred = svptrue_b64(); + svuint64_t accum1 = svdup_u64(0), + accum2 = svdup_u64(0), + accum3 = svdup_u64(0), + accum4 = svdup_u64(0); + uint32 vec_len = svcntb(), + bytes_per_iteration = 4 * vec_len; + uint64 popcnt = 0, + mask64 = ~UINT64CONST(0) / 0xFF * mask; + + /* + * For better instruction-level parallelism, each loop iteration operates + * on a block of four registers. + */ + for (; bytes >= bytes_per_iteration; bytes -= bytes_per_iteration) + { + svuint64_t vec; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum3 = svadd_u64_x(pred, accum3, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum4 = svadd_u64_x(pred, accum4, svcnt_u64_x(pred, vec)); + buf += vec_len; + } + + /* + * If enough data remains, do another iteration on a block of two + * registers. + */ + bytes_per_iteration = 2 * vec_len; + if (bytes >= bytes_per_iteration) + { + svuint64_t vec; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum1 = svadd_u64_x(pred, accum1, svcnt_u64_x(pred, vec)); + buf += vec_len; + + vec = svand_n_u64_x(pred, svld1_u64(pred, (const uint64 *) buf), mask64); + accum2 = svadd_u64_x(pred, accum2, svcnt_u64_x(pred, vec)); + buf += vec_len; + + bytes -= bytes_per_iteration; + } + + /* + * Add the accumulators. + */ + popcnt += svaddv_u64(pred, svadd_u64_x(pred, accum1, accum2)); + popcnt += svaddv_u64(pred, svadd_u64_x(pred, accum3, accum4)); + + /* + * Process any remaining data. + */ + for (; bytes > 0; bytes -= vec_len) + { + svuint8_t vec; + + pred = svwhilelt_b8_s32(0, bytes); + vec = svand_n_u8_x(pred, svld1_u8(pred, (const uint8 *) buf), mask); + popcnt += svaddv_u8(pred, svcnt_u8_x(pred, vec)); + buf += vec_len; + } + + return popcnt; +} + +#else /* USE_SVE_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * When the SVE version isn't available, there's no point in using function + * pointers to vary the implementation. We instead just make these actual + * external functions when USE_SVE_POPCNT_WITH_RUNTIME_CHECK is not defined. + * The compiler should be able to inline the Neon versions here. + */ +uint64 +pg_popcount_optimized(const char *buf, int bytes) +{ + return pg_popcount_neon(buf, bytes); +} + +uint64 +pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask) +{ + return pg_popcount_masked_neon(buf, bytes, mask); +} + +#endif /* ! USE_SVE_POPCNT_WITH_RUNTIME_CHECK */ + +/* + * pg_popcount32 + * Return number of 1 bits in word + */ +int +pg_popcount32(uint32 word) +{ + return pg_popcount64((uint64) word); +} + +/* + * pg_popcount64 + * Return number of 1 bits in word + */ +int +pg_popcount64(uint64 word) +{ + /* + * For some compilers, __builtin_popcountl() already emits Neon + * instructions. The line below should compile to the same code on those + * systems. + */ + return vaddv_u8(vcnt_u8(vld1_u8((const uint8 *) &word))); +} + +/* + * pg_popcount_neon + * Returns number of 1 bits in buf + */ +static uint64 +pg_popcount_neon(const char *buf, int bytes) +{ + uint8x16_t vec; + uint64x2_t accum1 = vdupq_n_u64(0), + accum2 = vdupq_n_u64(0), + accum3 = vdupq_n_u64(0), + accum4 = vdupq_n_u64(0); + uint32 bytes_per_iteration = 4 * sizeof(uint8x16_t); + uint64 popcnt = 0; + + /* + * For better instruction-level parallelism, each loop iteration operates + * on a block of four registers. + */ + for (; bytes >= bytes_per_iteration; bytes -= bytes_per_iteration) + { + vec = vld1q_u8((const uint8 *) buf); + accum1 = vpadalq_u32(accum1, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vld1q_u8((const uint8 *) buf); + accum2 = vpadalq_u32(accum2, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vld1q_u8((const uint8 *) buf); + accum3 = vpadalq_u32(accum3, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vld1q_u8((const uint8 *) buf); + accum4 = vpadalq_u32(accum4, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + } + + /* + * If enough data remains, do another iteration on a block of two + * registers. + */ + bytes_per_iteration = 2 * sizeof(uint8x16_t); + if (bytes >= bytes_per_iteration) + { + vec = vld1q_u8((const uint8 *) buf); + accum1 = vpadalq_u32(accum1, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vld1q_u8((const uint8 *) buf); + accum2 = vpadalq_u32(accum2, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + bytes -= bytes_per_iteration; + } + + /* + * Add the accumulators. + */ + popcnt += vaddvq_u64(vaddq_u64(accum1, accum2)); + popcnt += vaddvq_u64(vaddq_u64(accum3, accum4)); + + /* + * Process remaining 8-byte blocks. + */ + for (; bytes >= sizeof(uint64); bytes -= sizeof(uint64)) + { + popcnt += pg_popcount64(*((uint64 *) buf)); + buf += sizeof(uint64); + } + + /* + * Process any remaining data byte-by-byte. + */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++]; + + return popcnt; +} + +/* + * pg_popcount_masked_neon + * Returns number of 1 bits in buf after applying the mask to each byte + */ +static uint64 +pg_popcount_masked_neon(const char *buf, int bytes, bits8 mask) +{ + uint8x16_t vec, + maskv = vdupq_n_u8(mask); + uint64x2_t accum1 = vdupq_n_u64(0), + accum2 = vdupq_n_u64(0), + accum3 = vdupq_n_u64(0), + accum4 = vdupq_n_u64(0); + uint32 bytes_per_iteration = 4 * sizeof(uint8x16_t); + uint64 popcnt = 0, + mask64 = ~UINT64CONST(0) / 0xFF * mask; + + /* + * For better instruction-level parallelism, each loop iteration operates + * on a block of four registers. + */ + for (; bytes >= bytes_per_iteration; bytes -= bytes_per_iteration) + { + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum1 = vpadalq_u32(accum1, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum2 = vpadalq_u32(accum2, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum3 = vpadalq_u32(accum3, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum4 = vpadalq_u32(accum4, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + } + + /* + * If enough data remains, do another iteration on a block of two + * registers. + */ + bytes_per_iteration = 2 * sizeof(uint8x16_t); + if (bytes >= bytes_per_iteration) + { + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum1 = vpadalq_u32(accum1, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + vec = vandq_u8(vld1q_u8((const uint8 *) buf), maskv); + accum2 = vpadalq_u32(accum2, vpaddlq_u16(vpaddlq_u8(vcntq_u8(vec)))); + buf += sizeof(uint8x16_t); + + bytes -= bytes_per_iteration; + } + + /* + * Add the accumulators. + */ + popcnt += vaddvq_u64(vaddq_u64(accum1, accum2)); + popcnt += vaddvq_u64(vaddq_u64(accum3, accum4)); + + /* + * Process remaining 8-byte blocks. + */ + for (; bytes >= sizeof(uint64); bytes -= sizeof(uint64)) + { + popcnt += pg_popcount64(*((uint64 *) buf) & mask64); + buf += sizeof(uint64); + } + + /* + * Process any remaining data byte-by-byte. + */ + while (bytes--) + popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask]; + + return popcnt; +} + +#endif /* POPCNT_AARCH64 */ diff --git a/src/port/pg_popcount_avx512.c b/src/port/pg_popcount_avx512.c index 9d3149e2d002b..80c0aee3e73fa 100644 --- a/src/port/pg_popcount_avx512.c +++ b/src/port/pg_popcount_avx512.c @@ -3,7 +3,7 @@ * pg_popcount_avx512.c * Holds the AVX-512 pg_popcount() implementation. * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/pg_popcount_avx512.c @@ -12,21 +12,101 @@ */ #include "c.h" +#ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK + +#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) +#include +#endif + #include +#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) +#include +#endif + #include "port/pg_bitutils.h" /* - * It's probably unlikely that TRY_POPCNT_FAST won't be set if we are able to + * It's probably unlikely that TRY_POPCNT_X86_64 won't be set if we are able to * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_FAST is set. + * the function pointers that are only used when TRY_POPCNT_X86_64 is set. + */ +#ifdef TRY_POPCNT_X86_64 + +/* + * Does CPUID say there's support for XSAVE instructions? + */ +static inline bool +xsave_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID) + __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUID) + __cpuid(exx, 1); +#else +#error cpuid instruction not available +#endif + return (exx[2] & (1 << 27)) != 0; /* osxsave */ +} + +/* + * Does XGETBV say the ZMM registers are enabled? + * + * NB: Caller is responsible for verifying that xsave_available() returns true + * before calling this. */ -#ifdef TRY_POPCNT_FAST +#ifdef HAVE_XSAVE_INTRINSICS +pg_attribute_target("xsave") +#endif +static inline bool +zmm_regs_available(void) +{ +#ifdef HAVE_XSAVE_INTRINSICS + return (_xgetbv(0) & 0xe6) == 0xe6; +#else + return false; +#endif +} + +/* + * Does CPUID say there's support for AVX-512 popcount and byte-and-word + * instructions? + */ +static inline bool +avx512_popcnt_available(void) +{ + unsigned int exx[4] = {0, 0, 0, 0}; + +#if defined(HAVE__GET_CPUID_COUNT) + __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]); +#elif defined(HAVE__CPUIDEX) + __cpuidex(exx, 7, 0); +#else +#error cpuid instruction not available +#endif + return (exx[2] & (1 << 14)) != 0 && /* avx512-vpopcntdq */ + (exx[1] & (1 << 30)) != 0; /* avx512-bw */ +} + +/* + * Returns true if the CPU supports the instructions required for the AVX-512 + * pg_popcount() implementation. + */ +bool +pg_popcount_avx512_available(void) +{ + return xsave_available() && + zmm_regs_available() && + avx512_popcnt_available(); +} /* * pg_popcount_avx512 * Returns the number of 1-bits in buf */ +pg_attribute_target("avx512vpopcntdq,avx512bw") uint64 pg_popcount_avx512(const char *buf, int bytes) { @@ -82,6 +162,7 @@ pg_popcount_avx512(const char *buf, int bytes) * pg_popcount_masked_avx512 * Returns the number of 1-bits in buf after applying the mask to each byte */ +pg_attribute_target("avx512vpopcntdq,avx512bw") uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) { @@ -138,4 +219,5 @@ pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask) return _mm512_reduce_add_epi64(accum); } -#endif /* TRY_POPCNT_FAST */ +#endif /* TRY_POPCNT_X86_64 */ +#endif /* USE_AVX512_POPCNT_WITH_RUNTIME_CHECK */ diff --git a/src/port/pg_popcount_avx512_choose.c b/src/port/pg_popcount_avx512_choose.c deleted file mode 100644 index b37107803a8c3..0000000000000 --- a/src/port/pg_popcount_avx512_choose.c +++ /dev/null @@ -1,102 +0,0 @@ -/*------------------------------------------------------------------------- - * - * pg_popcount_avx512_choose.c - * Test whether we can use the AVX-512 pg_popcount() implementation. - * - * Copyright (c) 2024, PostgreSQL Global Development Group - * - * IDENTIFICATION - * src/port/pg_popcount_avx512_choose.c - * - *------------------------------------------------------------------------- - */ -#include "c.h" - -#if defined(HAVE__GET_CPUID) || defined(HAVE__GET_CPUID_COUNT) -#include -#endif - -#ifdef HAVE_XSAVE_INTRINSICS -#include -#endif - -#if defined(HAVE__CPUID) || defined(HAVE__CPUIDEX) -#include -#endif - -#include "port/pg_bitutils.h" - -/* - * It's probably unlikely that TRY_POPCNT_FAST won't be set if we are able to - * use AVX-512 intrinsics, but we check it anyway to be sure. We piggy-back on - * the function pointers that are only used when TRY_POPCNT_FAST is set. - */ -#ifdef TRY_POPCNT_FAST - -/* - * Does CPUID say there's support for XSAVE instructions? - */ -static inline bool -xsave_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID) - __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUID) - __cpuid(exx, 1); -#else -#error cpuid instruction not available -#endif - return (exx[2] & (1 << 27)) != 0; /* osxsave */ -} - -/* - * Does XGETBV say the ZMM registers are enabled? - * - * NB: Caller is responsible for verifying that xsave_available() returns true - * before calling this. - */ -static inline bool -zmm_regs_available(void) -{ -#ifdef HAVE_XSAVE_INTRINSICS - return (_xgetbv(0) & 0xe6) == 0xe6; -#else - return false; -#endif -} - -/* - * Does CPUID say there's support for AVX-512 popcount and byte-and-word - * instructions? - */ -static inline bool -avx512_popcnt_available(void) -{ - unsigned int exx[4] = {0, 0, 0, 0}; - -#if defined(HAVE__GET_CPUID_COUNT) - __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]); -#elif defined(HAVE__CPUIDEX) - __cpuidex(exx, 7, 0); -#else -#error cpuid instruction not available -#endif - return (exx[2] & (1 << 14)) != 0 && /* avx512-vpopcntdq */ - (exx[1] & (1 << 30)) != 0; /* avx512-bw */ -} - -/* - * Returns true if the CPU supports the instructions required for the AVX-512 - * pg_popcount() implementation. - */ -bool -pg_popcount_avx512_available(void) -{ - return xsave_available() && - zmm_regs_available() && - avx512_popcnt_available(); -} - -#endif /* TRY_POPCNT_FAST */ diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 5f2b248425282..ea6780dcc9f1c 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -10,7 +10,7 @@ * therefore, even when built for backend, it cannot rely on backend * infrastructure such as elog() or palloc(). * - * Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/pg_strong_random.c @@ -31,7 +31,9 @@ * cryptographically secure, suitable for use e.g. in authentication. * * Before pg_strong_random is called in any process, the generator must first - * be initialized by calling pg_strong_random_init(). + * be initialized by calling pg_strong_random_init(). Initialization is a no- + * op for all supported randomness sources, it is kept to maintain backwards + * compatibility with extensions. * * We rely on system facilities for actually generating the numbers. * We support a number of sources: @@ -55,12 +57,7 @@ void pg_strong_random_init(void) { - /* - * Make sure processes do not share OpenSSL randomness state. This is no - * longer required in OpenSSL 1.1.1 and later versions, but until we drop - * support for version < 1.1.1 we need to do this. - */ - RAND_poll(); + /* No initialization needed */ } bool diff --git a/src/port/pgcheckdir.c b/src/port/pgcheckdir.c index 8fa347b4e0e96..8333051610744 100644 --- a/src/port/pgcheckdir.c +++ b/src/port/pgcheckdir.c @@ -5,7 +5,7 @@ * A simple subroutine to check whether a directory exists and is empty or not. * Useful in both initdb and the backend. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/port/pgsleep.c b/src/port/pgsleep.c index 1284458bfce3a..dfe824fe46266 100644 --- a/src/port/pgsleep.c +++ b/src/port/pgsleep.c @@ -4,7 +4,7 @@ * Portable delay handling. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/port/pgsleep.c * diff --git a/src/port/pgstrcasecmp.c b/src/port/pgstrcasecmp.c index 60b3137e45a08..ec2b3a75c3dcd 100644 --- a/src/port/pgstrcasecmp.c +++ b/src/port/pgstrcasecmp.c @@ -18,7 +18,7 @@ * C library thinks the locale is. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/port/pgstrcasecmp.c * diff --git a/src/port/pgstrsignal.c b/src/port/pgstrsignal.c index bd4add8249f3c..4e6bb878dbc08 100644 --- a/src/port/pgstrsignal.c +++ b/src/port/pgstrsignal.c @@ -6,7 +6,7 @@ * On platforms compliant with modern POSIX, this just wraps strsignal(3). * Elsewhere, we do the best we can. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/port/pqsignal.c b/src/port/pqsignal.c index 6ca2d4e20a840..26943845e2179 100644 --- a/src/port/pqsignal.c +++ b/src/port/pqsignal.c @@ -4,7 +4,7 @@ * reliable BSD-style signal(2) routine stolen from RWW who stole it * from Stevens... * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -74,8 +74,7 @@ static volatile pqsigfunc pqsignal_handlers[PG_NSIG]; /* * Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function * as the handler for all signals. This wrapper handler function checks that - * it is called within a process that the server knows about (i.e., any process - * that has called InitProcessGlobals(), such as a client backend), and not a + * it is called within a process that knew to maintain MyProcPid, and not a * child process forked by system(3), etc. This check ensures that such child * processes do not modify shared memory, which is often detrimental. If the * check succeeds, the function originally provided to pqsignal() is called. @@ -88,6 +87,9 @@ wrapper_handler(SIGNAL_ARGS) { int save_errno = errno; + Assert(postgres_signal_arg > 0); + Assert(postgres_signal_arg < PG_NSIG); + #ifndef FRONTEND /* @@ -113,29 +115,18 @@ wrapper_handler(SIGNAL_ARGS) /* * Set up a signal handler, with SA_RESTART, for signal "signo" * - * Returns the previous handler. - * - * NB: If called within a signal handler, race conditions may lead to bogus - * return values. You should either avoid calling this within signal handlers - * or ignore the return value. - * - * XXX: Since no in-tree callers use the return value, and there is little - * reason to do so, it would be nice if we could convert this to a void - * function instead of providing potentially-bogus return values. - * Unfortunately, that requires modifying the pqsignal() in legacy-pqsignal.c, - * which in turn requires an SONAME bump, which is probably not worth it. + * Note: the actual name of this function is either pqsignal_fe when + * compiled with -DFRONTEND, or pqsignal_be when compiled without that. + * This is to avoid a name collision with libpq's legacy-pqsignal.c. */ -pqsigfunc +void pqsignal(int signo, pqsigfunc func) { - pqsigfunc orig_func = pqsignal_handlers[signo]; /* assumed atomic */ #if !(defined(WIN32) && defined(FRONTEND)) - struct sigaction act, - oact; -#else - pqsigfunc ret; + struct sigaction act; #endif + Assert(signo > 0); Assert(signo < PG_NSIG); if (func != SIG_IGN && func != SIG_DFL) @@ -152,17 +143,11 @@ pqsignal(int signo, pqsigfunc func) if (signo == SIGCHLD) act.sa_flags |= SA_NOCLDSTOP; #endif - if (sigaction(signo, &act, &oact) < 0) - return SIG_ERR; - else if (oact.sa_handler == wrapper_handler) - return orig_func; - else - return oact.sa_handler; + if (sigaction(signo, &act, NULL) < 0) + Assert(false); /* probably indicates coding error */ #else /* Forward to Windows native signal system. */ - if ((ret = signal(signo, func)) == wrapper_handler) - return orig_func; - else - return ret; + if (signal(signo, func) == SIG_ERR) + Assert(false); /* probably indicates coding error */ #endif } diff --git a/src/port/pthread_barrier_wait.c b/src/port/pthread_barrier_wait.c index 835dbf1c7afb5..2387a2acb24bf 100644 --- a/src/port/pthread_barrier_wait.c +++ b/src/port/pthread_barrier_wait.c @@ -3,7 +3,7 @@ * pthread_barrier_wait.c * Implementation of pthread_barrier_t support for platforms lacking it. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/pthread_barrier_wait.c diff --git a/src/port/quotes.c b/src/port/quotes.c index e75dfa5924076..3d3884036b82c 100644 --- a/src/port/quotes.c +++ b/src/port/quotes.c @@ -3,7 +3,7 @@ * quotes.c * string quoting and escaping functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/snprintf.c b/src/port/snprintf.c index 884f0262dd15c..d7f18b42d19ac 100644 --- a/src/port/snprintf.c +++ b/src/port/snprintf.c @@ -2,7 +2,7 @@ * Copyright (c) 1983, 1995, 1996 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -338,13 +338,22 @@ static void leading_pad(int zpad, int signvalue, int *padlen, static void trailing_pad(int padlen, PrintfTarget *target); /* - * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the - * equivalent manual loop. If it doesn't exist, provide a replacement. + * If strchrnul exists (it's a glibc-ism, but since adopted by some other + * platforms), it's a good bit faster than the equivalent manual loop. + * Use it if possible, and if it doesn't exist, use this replacement. * * Note: glibc declares this as returning "char *", but that would require * casting away const internally, so we don't follow that detail. + * + * Note: macOS has this too as of Sequoia 15.4, but it's hidden behind + * a deployment-target check that causes compile errors if the deployment + * target isn't high enough. So !HAVE_DECL_STRCHRNUL may mean "yes it's + * declared, but it doesn't compile". To avoid failing in that scenario, + * use a macro to avoid matching 's name. */ -#ifndef HAVE_STRCHRNUL +#if !HAVE_DECL_STRCHRNUL + +#define strchrnul pg_strchrnul static inline const char * strchrnul(const char *s, int c) @@ -354,19 +363,7 @@ strchrnul(const char *s, int c) return s; } -#else - -/* - * glibc's declares strchrnul only if _GNU_SOURCE is defined. - * While we typically use that on glibc platforms, configure will set - * HAVE_STRCHRNUL whether it's used or not. Fill in the missing declaration - * so that this file will compile cleanly with or without _GNU_SOURCE. - */ -#ifndef _GNU_SOURCE -extern char *strchrnul(const char *s, int c); -#endif - -#endif /* HAVE_STRCHRNUL */ +#endif /* !HAVE_DECL_STRCHRNUL */ /* @@ -560,6 +557,28 @@ dopr(PrintfTarget *target, const char *format, va_list args) fmtpos = accum; accum = 0; goto nextch2; +#ifdef WIN32 + case 'I': + /* Windows PRI*{32,64,PTR} size */ + if (format[0] == '3' && format[1] == '2') + format += 2; + else if (format[0] == '6' && format[1] == '4') + { + format += 2; + longlongflag = 1; + } + else + { +#if SIZEOF_VOID_P == SIZEOF_LONG + longflag = 1; +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG + longlongflag = 1; +#else +#error "cannot find integer type of the same size as intptr_t" +#endif + } + goto nextch2; +#endif case 'l': if (longflag) longlongflag = 1; @@ -567,16 +586,12 @@ dopr(PrintfTarget *target, const char *format, va_list args) longflag = 1; goto nextch2; case 'z': -#if SIZEOF_SIZE_T == 8 -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_SIZE_T == SIZEOF_LONG longflag = 1; -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG longlongflag = 1; #else -#error "Don't know how to print 64bit integers" -#endif -#else - /* assume size_t is same size as int */ +#error "cannot find integer type of the same size as size_t" #endif goto nextch2; case 'h': @@ -827,6 +842,28 @@ find_arguments(const char *format, va_list args, fmtpos = accum; accum = 0; goto nextch1; +#ifdef WIN32 + case 'I': + /* Windows PRI*{32,64,PTR} size */ + if (format[0] == '3' && format[1] == '2') + format += 2; + else if (format[0] == '6' && format[1] == '4') + { + format += 2; + longlongflag = 1; + } + else + { +#if SIZEOF_VOID_P == SIZEOF_LONG + longflag = 1; +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG + longlongflag = 1; +#else +#error "cannot find integer type of the same size as intptr_t" +#endif + } + goto nextch1; +#endif case 'l': if (longflag) longlongflag = 1; @@ -834,16 +871,12 @@ find_arguments(const char *format, va_list args, longflag = 1; goto nextch1; case 'z': -#if SIZEOF_SIZE_T == 8 -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_SIZE_T == SIZEOF_LONG longflag = 1; -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG longlongflag = 1; #else -#error "Don't know how to print 64bit integers" -#endif -#else - /* assume size_t is same size as int */ +#error "cannot find integer type of the same size as size_t" #endif goto nextch1; case 'h': diff --git a/src/port/strerror.c b/src/port/strerror.c index 4918ba821c12e..f07465177702c 100644 --- a/src/port/strerror.c +++ b/src/port/strerror.c @@ -3,7 +3,7 @@ * strerror.c * Replacements for standard strerror() and strerror_r() functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/strlcpy.c b/src/port/strlcpy.c index 268c91de8f20f..d07b6536adbfa 100644 --- a/src/port/strlcpy.c +++ b/src/port/strlcpy.c @@ -3,7 +3,7 @@ * strlcpy.c * strncpy done right * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/port/strnlen.c b/src/port/strnlen.c index f635f03e3be61..60c3b458c6bf8 100644 --- a/src/port/strnlen.c +++ b/src/port/strnlen.c @@ -4,7 +4,7 @@ * Fallback implementation of strnlen(). * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/port/strtof.c b/src/port/strtof.c index b93bafd1dfa6d..e7258b3d6dbe6 100644 --- a/src/port/strtof.c +++ b/src/port/strtof.c @@ -2,7 +2,7 @@ * * strtof.c * - * Portions Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2019-2025, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -31,15 +31,18 @@ pg_strtof(const char *nptr, char **endptr) { int caller_errno = errno; float fresult; + char *myendptr; errno = 0; - fresult = (strtof) (nptr, endptr); + fresult = (strtof) (nptr, &myendptr); + if (endptr) + *endptr = myendptr; if (errno) { /* On error, just return the error to the caller. */ return fresult; } - else if ((*endptr == nptr) || isnan(fresult) || + else if ((myendptr == nptr) || isnan(fresult) || ((fresult >= FLT_MIN || fresult <= -FLT_MIN) && !isinf(fresult))) { /* @@ -53,7 +56,8 @@ pg_strtof(const char *nptr, char **endptr) else { /* - * Try again. errno is already 0 here. + * Try again. errno is already 0 here, and we assume that the endptr + * won't be any different. */ double dresult = strtod(nptr, NULL); diff --git a/src/port/system.c b/src/port/system.c index 6877c4edd8407..a55946e056380 100644 --- a/src/port/system.c +++ b/src/port/system.c @@ -29,7 +29,7 @@ * quote character on the command line, preserving any text after the last * quote character. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/port/system.c * diff --git a/src/port/timingsafe_bcmp.c b/src/port/timingsafe_bcmp.c new file mode 100644 index 0000000000000..288865f50d179 --- /dev/null +++ b/src/port/timingsafe_bcmp.c @@ -0,0 +1,43 @@ +/* + * src/port/timingsafe_bcmp.c + * + * $OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $ + */ + +/* + * Copyright (c) 2010 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "c.h" + +#ifdef USE_SSL +#include +#endif + +int +timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ +#ifdef USE_SSL + return CRYPTO_memcmp(b1, b2, n); +#else + const unsigned char *p1 = b1, + *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +#endif +} diff --git a/src/port/user.c b/src/port/user.c deleted file mode 100644 index 7444aeb64b287..0000000000000 --- a/src/port/user.c +++ /dev/null @@ -1,89 +0,0 @@ -/*------------------------------------------------------------------------- - * - * user.c - * - * Wrapper functions for user and home directory lookup. - * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group - * - * src/port/user.c - * - *------------------------------------------------------------------------- - */ - -#include "c.h" - -#include - -#ifndef WIN32 - -/* - * pg_get_user_name - get the name of the user with the given ID - * - * On success, the user name is returned into the buffer (of size buflen), - * and "true" is returned. On failure, a localized error message is - * returned into the buffer, and "false" is returned. - */ -bool -pg_get_user_name(uid_t user_id, char *buffer, size_t buflen) -{ - char pwdbuf[BUFSIZ]; - struct passwd pwdstr; - struct passwd *pw = NULL; - int pwerr; - - pwerr = getpwuid_r(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw); - if (pw != NULL) - { - strlcpy(buffer, pw->pw_name, buflen); - return true; - } - if (pwerr != 0) - snprintf(buffer, buflen, - _("could not look up local user ID %d: %s"), - (int) user_id, - strerror_r(pwerr, pwdbuf, sizeof(pwdbuf))); - else - snprintf(buffer, buflen, - _("local user with ID %d does not exist"), - (int) user_id); - return false; -} - -/* - * pg_get_user_home_dir - get the home directory of the user with the given ID - * - * On success, the directory path is returned into the buffer (of size buflen), - * and "true" is returned. On failure, a localized error message is - * returned into the buffer, and "false" is returned. - * - * Note that this does not incorporate the common behavior of checking - * $HOME first, since it's independent of which user_id is queried. - */ -bool -pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen) -{ - char pwdbuf[BUFSIZ]; - struct passwd pwdstr; - struct passwd *pw = NULL; - int pwerr; - - pwerr = getpwuid_r(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw); - if (pw != NULL) - { - strlcpy(buffer, pw->pw_dir, buflen); - return true; - } - if (pwerr != 0) - snprintf(buffer, buflen, - _("could not look up local user ID %d: %s"), - (int) user_id, - strerror_r(pwerr, pwdbuf, sizeof(pwdbuf))); - else - snprintf(buffer, buflen, - _("local user with ID %d does not exist"), - (int) user_id); - return false; -} - -#endif /* !WIN32 */ diff --git a/src/port/win32common.c b/src/port/win32common.c index dc83396236d7d..d43d5d5324f66 100644 --- a/src/port/win32common.c +++ b/src/port/win32common.c @@ -3,7 +3,7 @@ * win32common.c * Common routines shared among the win32*.c ports. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32dlopen.c b/src/port/win32dlopen.c index 11823bbae0f26..cc34846596915 100644 --- a/src/port/win32dlopen.c +++ b/src/port/win32dlopen.c @@ -3,7 +3,7 @@ * win32dlopen.c * dynamic loader for Windows * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32env.c b/src/port/win32env.c index fdc5537fb4e9c..b22fbafde4012 100644 --- a/src/port/win32env.c +++ b/src/port/win32env.c @@ -6,7 +6,7 @@ * These functions update both the process environment and caches in * (potentially multiple) C run-time library (CRT) versions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32error.c b/src/port/win32error.c index a7cd6fb4e0260..7ea99738bdbc3 100644 --- a/src/port/win32error.c +++ b/src/port/win32error.c @@ -3,7 +3,7 @@ * win32error.c * Map win32 error codes to errno values * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32error.c diff --git a/src/port/win32fdatasync.c b/src/port/win32fdatasync.c index 1cf9c15955153..66d759770138c 100644 --- a/src/port/win32fdatasync.c +++ b/src/port/win32fdatasync.c @@ -4,7 +4,7 @@ * Win32 fdatasync() replacement * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * src/port/win32fdatasync.c * diff --git a/src/port/win32fseek.c b/src/port/win32fseek.c index 9ae3653e812e5..a75e488ce21d6 100644 --- a/src/port/win32fseek.c +++ b/src/port/win32fseek.c @@ -3,7 +3,7 @@ * win32fseek.c * Replacements for fseeko() and ftello(). * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32fseek.c diff --git a/src/port/win32gai_strerror.c b/src/port/win32gai_strerror.c index 5b47d1722df34..d52e9a1ef37d3 100644 --- a/src/port/win32gai_strerror.c +++ b/src/port/win32gai_strerror.c @@ -3,7 +3,7 @@ * win32gai_strerror.c * Thread-safe gai_strerror() for Windows. * - * Portions Copyright (c) 2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32gai_strerror.c diff --git a/src/port/win32getrusage.c b/src/port/win32getrusage.c index a2cf1828fb9e5..6a197c94376f9 100644 --- a/src/port/win32getrusage.c +++ b/src/port/win32getrusage.c @@ -3,7 +3,7 @@ * win32getrusage.c * get information about resource utilisation * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32link.c b/src/port/win32link.c index b9fe89eb6cd94..ee4d6c96c99d5 100644 --- a/src/port/win32link.c +++ b/src/port/win32link.c @@ -2,7 +2,7 @@ * * win32link.c * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32ntdll.c b/src/port/win32ntdll.c index bf8bce7f1a130..ab6820fb8e5b8 100644 --- a/src/port/win32ntdll.c +++ b/src/port/win32ntdll.c @@ -3,7 +3,7 @@ * win32ntdll.c * Dynamically loaded Windows NT functions. * - * Portions Copyright (c) 2021-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2021-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32pread.c b/src/port/win32pread.c index 2d022e6d3784e..32d56c462ecb9 100644 --- a/src/port/win32pread.c +++ b/src/port/win32pread.c @@ -3,7 +3,7 @@ * win32pread.c * Implementation of pread(2) for Windows. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32pread.c diff --git a/src/port/win32pwrite.c b/src/port/win32pwrite.c index b37bb2f92e0ab..249aa6c468537 100644 --- a/src/port/win32pwrite.c +++ b/src/port/win32pwrite.c @@ -3,7 +3,7 @@ * win32pwrite.c * Implementation of pwrite(2) for Windows. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32pwrite.c diff --git a/src/port/win32security.c b/src/port/win32security.c index bca62ab2fba8d..a46b82dd0482b 100644 --- a/src/port/win32security.c +++ b/src/port/win32security.c @@ -3,7 +3,7 @@ * win32security.c * Microsoft Windows Win32 Security Support Functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32security.c diff --git a/src/port/win32setlocale.c b/src/port/win32setlocale.c index 9e2ab8cc3ad01..7c0982439dbcd 100644 --- a/src/port/win32setlocale.c +++ b/src/port/win32setlocale.c @@ -3,7 +3,7 @@ * win32setlocale.c * Wrapper to work around bugs in Windows setlocale() implementation * - * Copyright (c) 2011-2024, PostgreSQL Global Development Group + * Copyright (c) 2011-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/port/win32setlocale.c diff --git a/src/port/win32stat.c b/src/port/win32stat.c index 7ab35024af3e0..d9bad97b113b8 100644 --- a/src/port/win32stat.c +++ b/src/port/win32stat.c @@ -3,7 +3,7 @@ * win32stat.c * Replacements for functions using GetFileInformationByHandle * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/port/win32ver.rc b/src/port/win32ver.rc index 31f8fc2e5d913..e62020e72a163 100644 --- a/src/port/win32ver.rc +++ b/src/port/win32ver.rc @@ -20,7 +20,7 @@ BEGIN VALUE "FileDescription", FILEDESC VALUE "FileVersion", PG_VERSION VALUE "InternalName", _INTERNAL_NAME_ - VALUE "LegalCopyright", "Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group. Portions Copyright (c) 1994, Regents of the University of California." + VALUE "LegalCopyright", "Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group. Portions Copyright (c) 1994, Regents of the University of California." VALUE "OriginalFileName", _ORIGINAL_NAME_ VALUE "ProductName", "PostgreSQL" VALUE "ProductVersion", PG_VERSION diff --git a/src/template/win32 b/src/template/win32 index 1895f067a889b..4f8b0923fe041 100644 --- a/src/template/win32 +++ b/src/template/win32 @@ -1,5 +1,8 @@ # src/template/win32 +# define before including for getting localtime_r() etc. on MinGW +CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE" + # Extra CFLAGS for code that will go into a shared library CFLAGS_SL="" diff --git a/src/test/Makefile b/src/test/Makefile index dbd3192874d33..511a72e6238a5 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -12,7 +12,7 @@ subdir = src/test top_builddir = ../.. include $(top_builddir)/src/Makefile.global -SUBDIRS = perl regress isolation modules authentication recovery subscription +SUBDIRS = perl postmaster regress isolation modules authentication recovery subscription ifeq ($(with_icu),yes) SUBDIRS += icu @@ -27,11 +27,6 @@ ifeq ($(with_ssl),openssl) SUBDIRS += ssl endif -# Test suites that are not safe by default but can be run if selected -# by the user via the whitespace-separated list in variable PG_TEST_EXTRA. -# Export PG_TEST_EXTRA to check it in individual tap tests. -export PG_TEST_EXTRA - # We don't build or execute these by default, but we do want "make # clean" etc to recurse into them. (We must filter out those that we # have conditionally included into SUBDIRS above, else there will be diff --git a/src/test/authentication/Makefile b/src/test/authentication/Makefile index da0b71873abf1..8b5beced08061 100644 --- a/src/test/authentication/Makefile +++ b/src/test/authentication/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/authentication # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/authentication/Makefile @@ -13,6 +13,10 @@ subdir = src/test/authentication top_builddir = ../../.. include $(top_builddir)/src/Makefile.global +EXTRA_INSTALL = src/test/modules/injection_points + +export enable_injection_points + check: $(prove_check) diff --git a/src/test/authentication/meson.build b/src/test/authentication/meson.build index 8f5688dcc1392..800b3a5ff40fb 100644 --- a/src/test/authentication/meson.build +++ b/src/test/authentication/meson.build @@ -1,10 +1,13 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'authentication', 'sd': meson.current_source_dir(), 'bd': meson.current_build_dir(), 'tap': { + 'env': { + 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', + }, 'tests': [ 't/001_password.pl', 't/002_saslprep.pl', @@ -12,6 +15,7 @@ tests += { 't/004_file_inclusion.pl', 't/005_sspi.pl', 't/006_login_trigger.pl', + 't/007_pre_auth.pl', ], }, } diff --git a/src/test/authentication/t/001_password.pl b/src/test/authentication/t/001_password.pl index 87e180af3d37d..37d96d95a1aeb 100644 --- a/src/test/authentication/t/001_password.pl +++ b/src/test/authentication/t/001_password.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Set of tests for authentication and pg_hba.conf. The following password # methods are checked through this test: @@ -7,6 +7,8 @@ # - MD5-encrypted # - SCRAM-encrypted # This test can only run with Unix-domain sockets. +# +# There's also a few tests of the log_connections GUC here. use strict; use warnings FATAL => 'all'; @@ -64,8 +66,62 @@ sub test_conn my $node = PostgreSQL::Test::Cluster->new('primary'); $node->init; $node->append_conf('postgresql.conf', "log_connections = on\n"); +# Needed to allow connect_fails to inspect postmaster log: +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); $node->start; +# Test behavior of log_connections GUC +# +# There wasn't another test file where these tests obviously fit, and we don't +# want to incur the cost of spinning up a new cluster just to test one GUC. + +# Make a database for the log_connections tests to avoid test fragility if +# other tests are added to this file in the future +$node->safe_psql('postgres', "CREATE DATABASE test_log_connections"); + +my $log_connections = $node->safe_psql('test_log_connections', q(SHOW log_connections;)); +is($log_connections, 'on', qq(check log connections has expected value 'on')); + +$node->connect_ok('test_log_connections', + qq(log_connections 'on' works as expected for backwards compatibility), + log_like => [ + qr/connection received/, + qr/connection authenticated/, + qr/connection authorized: user=\S+ database=test_log_connections/, + ], + log_unlike => [ + qr/connection ready/, + ],); + +$node->safe_psql('test_log_connections', + q[ALTER SYSTEM SET log_connections = receipt,authorization,setup_durations; + SELECT pg_reload_conf();]); + +$node->connect_ok('test_log_connections', + q(log_connections with subset of specified options logs only those aspects), + log_like => [ + qr/connection received/, + qr/connection authorized: user=\S+ database=test_log_connections/, + qr/connection ready/, + ], + log_unlike => [ + qr/connection authenticated/, + ],); + +$node->safe_psql('test_log_connections', + qq(ALTER SYSTEM SET log_connections = 'all'; SELECT pg_reload_conf();)); + +$node->connect_ok('test_log_connections', + qq(log_connections 'all' logs all available connection aspects), + log_like => [ + qr/connection received/, + qr/connection authenticated/, + qr/connection authorized: user=\S+ database=test_log_connections/, + qr/connection ready/, + ],); + +# Authentication tests + # could fail in FIPS mode my $md5_works = ($node->psql('postgres', "select md5('')") == 0); @@ -277,6 +333,16 @@ sub test_conn "require_auth methods cannot be duplicated, !none case", expected_stderr => qr/require_auth method "!none" is specified more than once/); +$node->connect_fails( + "user=scram_role require_auth=scram-sha-256,scram-sha-256", + "require_auth methods cannot be duplicated, scram-sha-256 case", + expected_stderr => + qr/require_auth method "scram-sha-256" is specified more than once/); +$node->connect_fails( + "user=scram_role require_auth=!scram-sha-256,!scram-sha-256", + "require_auth methods cannot be duplicated, !scram-sha-256 case", + expected_stderr => + qr/require_auth method "!scram-sha-256" is specified more than once/); # Unknown value defined in require_auth. $node->connect_fails( @@ -360,7 +426,7 @@ sub test_conn test_conn($node, 'user=md5_role', 'scram-sha-256', 2, log_unlike => [qr/connection authenticated:/]); -# require_auth should succeeds with SCRAM when it is required. +# require_auth should succeed with SCRAM when it is required. $node->connect_ok( "user=scram_role require_auth=scram-sha-256", "SCRAM authentication required, works with SCRAM auth"); @@ -394,11 +460,11 @@ sub test_conn $node->connect_fails( "user=scram_role require_auth=!scram-sha-256", "SCRAM authentication forbidden, fails with SCRAM auth", - expected_stderr => qr/server requested SASL authentication/); + expected_stderr => qr/server requested SCRAM-SHA-256 authentication/); $node->connect_fails( "user=scram_role require_auth=!password,!md5,!scram-sha-256", "multiple authentication types forbidden, fails with SCRAM auth", - expected_stderr => qr/server requested SASL authentication/); + expected_stderr => qr/server requested SCRAM-SHA-256 authentication/); # Test that bad passwords are rejected. $ENV{"PGPASSWORD"} = 'badpass'; @@ -455,13 +521,13 @@ sub test_conn "user=scram_role require_auth=!scram-sha-256", "password authentication forbidden, fails with SCRAM auth", expected_stderr => - qr/authentication method requirement "!scram-sha-256" failed: server requested SASL authentication/ + qr/authentication method requirement "!scram-sha-256" failed: server requested SCRAM-SHA-256 authentication/ ); $node->connect_fails( "user=scram_role require_auth=!password,!md5,!scram-sha-256", "multiple authentication types forbidden, fails with SCRAM auth", expected_stderr => - qr/authentication method requirement "!password,!md5,!scram-sha-256" failed: server requested SASL authentication/ + qr/authentication method requirement "!password,!md5,!scram-sha-256" failed: server requested SCRAM-SHA-256 authentication/ ); # Test SYSTEM_USER <> NULL with parallel workers. diff --git a/src/test/authentication/t/002_saslprep.pl b/src/test/authentication/t/002_saslprep.pl index 4d8f44534d845..cdf0f96525231 100644 --- a/src/test/authentication/t/002_saslprep.pl +++ b/src/test/authentication/t/002_saslprep.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test password normalization in SCRAM. # diff --git a/src/test/authentication/t/003_peer.pl b/src/test/authentication/t/003_peer.pl index 97d6776fa953c..f2320b62c8721 100644 --- a/src/test/authentication/t/003_peer.pl +++ b/src/test/authentication/t/003_peer.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for peer authentication and user name map. # The test is skipped if the platform does not support peer authentication, @@ -71,7 +71,9 @@ sub test_role my $node = PostgreSQL::Test::Cluster->new('node'); $node->init; -$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->append_conf('postgresql.conf', "log_connections = authentication\n"); +# Needed to allow connect_fails to inspect postmaster log: +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); $node->start; # Set pg_hba.conf with the peer authentication. diff --git a/src/test/authentication/t/004_file_inclusion.pl b/src/test/authentication/t/004_file_inclusion.pl index f7a86a2bcf4c5..b9d3663542daf 100644 --- a/src/test/authentication/t/004_file_inclusion.pl +++ b/src/test/authentication/t/004_file_inclusion.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for include directives in HBA and ident files. This test can # only run with Unix-domain sockets. diff --git a/src/test/authentication/t/005_sspi.pl b/src/test/authentication/t/005_sspi.pl index c9a99af4e2242..cb3e169002f36 100644 --- a/src/test/authentication/t/005_sspi.pl +++ b/src/test/authentication/t/005_sspi.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests targeting SSPI on Windows. @@ -18,7 +18,7 @@ # Initialize primary node my $node = PostgreSQL::Test::Cluster->new('primary'); $node->init; -$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->append_conf('postgresql.conf', "log_connections = authentication\n"); $node->start; my $huge_pages_status = diff --git a/src/test/authentication/t/006_login_trigger.pl b/src/test/authentication/t/006_login_trigger.pl index 30d852a96ad6f..b06de1706ae14 100644 --- a/src/test/authentication/t/006_login_trigger.pl +++ b/src/test/authentication/t/006_login_trigger.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests of authentication via login trigger. Mostly for rejection via # exception, because this scenario cannot be covered with *.sql/*.out regress diff --git a/src/test/authentication/t/007_pre_auth.pl b/src/test/authentication/t/007_pre_auth.pl new file mode 100644 index 0000000000000..7b3765e6d253b --- /dev/null +++ b/src/test/authentication/t/007_pre_auth.pl @@ -0,0 +1,85 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Tests for connection behavior prior to authentication. + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Time::HiRes qw(usleep); +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; +$node->append_conf( + 'postgresql.conf', q[ +log_connections = 'receipt,authentication' +]); + +$node->start; + +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points'); + +# Connect to the server and inject a waitpoint. +my $psql = $node->background_psql('postgres'); +$psql->query_safe("SELECT injection_points_attach('init-pre-auth', 'wait')"); + +# From this point on, all new connections will hang during startup, just before +# authentication. Use the $psql connection handle for server interaction. +my $conn = $node->background_psql('postgres', wait => 0); + +# Wait for the connection to show up in pg_stat_activity, with the wait_event +# of the injection point. +my $pid; +while (1) +{ + $pid = $psql->query( + qq{SELECT pid FROM pg_stat_activity + WHERE backend_type = 'client backend' + AND state = 'starting' + AND wait_event = 'init-pre-auth';}); + last if $pid ne ""; + + usleep(100_000); +} + +note "backend $pid is authenticating"; +ok(1, 'authenticating connections are recorded in pg_stat_activity'); + +# Detach the waitpoint and wait for the connection to complete. +$psql->query_safe("SELECT injection_points_wakeup('init-pre-auth');"); +$conn->wait_connect(); + +# Make sure the pgstat entry is updated eventually. +while (1) +{ + my $state = + $psql->query("SELECT state FROM pg_stat_activity WHERE pid = $pid;"); + last if $state eq "idle"; + + note "state for backend $pid is '$state'; waiting for 'idle'..."; + usleep(100_000); +} + +ok(1, 'authenticated connections reach idle state in pg_stat_activity'); + +$psql->query_safe("SELECT injection_points_detach('init-pre-auth');"); +$psql->quit(); +$conn->quit(); + +done_testing(); diff --git a/src/test/examples/testlo.c b/src/test/examples/testlo.c index 1db41df728479..2277000eddb58 100644 --- a/src/test/examples/testlo.c +++ b/src/test/examples/testlo.c @@ -3,7 +3,7 @@ * testlo.c * test using large objects with libpq * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/test/examples/testlo64.c b/src/test/examples/testlo64.c index f0636a47961d7..c303db92e5bae 100644 --- a/src/test/examples/testlo64.c +++ b/src/test/examples/testlo64.c @@ -3,7 +3,7 @@ * testlo64.c * test using large objects with libpq using 64-bit APIs * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -12,6 +12,7 @@ * *------------------------------------------------------------------------- */ +#include #include #include @@ -75,7 +76,7 @@ importFile(PGconn *conn, char *filename) } static void -pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len) +pickout(PGconn *conn, Oid lobjId, int64_t start, int len) { int lobj_fd; char *buf; @@ -110,7 +111,7 @@ pickout(PGconn *conn, Oid lobjId, pg_int64 start, int len) } static void -overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len) +overwrite(PGconn *conn, Oid lobjId, int64_t start, int len) { int lobj_fd; char *buf; @@ -148,7 +149,7 @@ overwrite(PGconn *conn, Oid lobjId, pg_int64 start, int len) } static void -my_truncate(PGconn *conn, Oid lobjId, pg_int64 len) +my_truncate(PGconn *conn, Oid lobjId, int64_t len) { int lobj_fd; diff --git a/src/test/icu/Makefile b/src/test/icu/Makefile index e32855eda8637..5383c0b30017a 100644 --- a/src/test/icu/Makefile +++ b/src/test/icu/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/icu # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/icu/Makefile diff --git a/src/test/icu/meson.build b/src/test/icu/meson.build index 0a474aa0c0709..bc6c318fcbe91 100644 --- a/src/test/icu/meson.build +++ b/src/test/icu/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'icu', diff --git a/src/test/icu/t/010_database.pl b/src/test/icu/t/010_database.pl index 88d91cca39d47..6ab8b15431987 100644 --- a/src/test/icu/t/010_database.pl +++ b/src/test/icu/t/010_database.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/test/isolation/expected/detach-partition-concurrently-2.out b/src/test/isolation/expected/detach-partition-concurrently-2.out index 6f025d81f5e04..10cce9044f3ce 100644 --- a/src/test/isolation/expected/detach-partition-concurrently-2.out +++ b/src/test/isolation/expected/detach-partition-concurrently-2.out @@ -41,7 +41,7 @@ a step s3i1: INSERT INTO d_lp_fk_r VALUES (1); step s2d: ALTER TABLE d_lp_fk DETACH PARTITION d_lp_fk_1 CONCURRENTLY; -ERROR: removing partition "d_lp_fk_1" violates foreign key constraint "d_lp_fk_r_a_fkey1" +ERROR: removing partition "d_lp_fk_1" violates foreign key constraint "d_lp_fk_r_a_fkey_1" step s1c: COMMIT; starting permutation: s1b s1s s3i2 s2d s1c diff --git a/src/test/isolation/expected/detach-partition-concurrently-4.out b/src/test/isolation/expected/detach-partition-concurrently-4.out index b652522e4248c..79b29ae4c1033 100644 --- a/src/test/isolation/expected/detach-partition-concurrently-4.out +++ b/src/test/isolation/expected/detach-partition-concurrently-4.out @@ -298,7 +298,7 @@ step s1updcur: update d4_fk set a = 1 where current of f; step s2detach: alter table d4_primary detach partition d4_primary1 concurrently; step s1c: commit; step s2detach: <... completed> -ERROR: removing partition "d4_primary1" violates foreign key constraint "d4_fk_a_fkey1" +ERROR: removing partition "d4_primary1" violates foreign key constraint "d4_fk_a_fkey_1" starting permutation: s2snitch s1b s1s s2detach s3insert s1c step s2snitch: insert into d4_pid select pg_backend_pid(); diff --git a/src/test/isolation/expected/fk-partitioned-1.out b/src/test/isolation/expected/fk-partitioned-1.out index 45f2f8cba710d..686f7184d0b71 100644 --- a/src/test/isolation/expected/fk-partitioned-1.out +++ b/src/test/isolation/expected/fk-partitioned-1.out @@ -54,7 +54,7 @@ step s2a: alter table pfk attach partition pfk1 for values in (1); step s1d: delete from ppk1 where a = 1; step s2c: commit; step s1d: <... completed> -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s1b s2b s2a s2c s1d s1c @@ -63,7 +63,7 @@ step s2b: begin; step s2a: alter table pfk attach partition pfk1 for values in (1); step s2c: commit; step s1d: delete from ppk1 where a = 1; -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s2b s1b s1d s1c s2a s2c @@ -92,7 +92,7 @@ step s2a: alter table pfk attach partition pfk1 for values in (1); step s1d: delete from ppk1 where a = 1; step s2c: commit; step s1d: <... completed> -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s2b s1b s2a s2c s1d s1c @@ -101,7 +101,7 @@ step s1b: begin; step s2a: alter table pfk attach partition pfk1 for values in (1); step s2c: commit; step s1d: delete from ppk1 where a = 1; -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s2b s2a s1b s1d s2c s1c @@ -111,7 +111,7 @@ step s1b: begin; step s1d: delete from ppk1 where a = 1; step s2c: commit; step s1d: <... completed> -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s2b s2a s1b s2c s1d s1c @@ -120,7 +120,7 @@ step s2a: alter table pfk attach partition pfk1 for values in (1); step s1b: begin; step s2c: commit; step s1d: delete from ppk1 where a = 1; -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s2b s2a s2c s1b s1d s1c @@ -129,5 +129,5 @@ step s2a: alter table pfk attach partition pfk1 for values in (1); step s2c: commit; step s1b: begin; step s1d: delete from ppk1 where a = 1; -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; diff --git a/src/test/isolation/expected/fk-partitioned-2.out b/src/test/isolation/expected/fk-partitioned-2.out index 8c6c714d0597f..db621bee2d67e 100644 --- a/src/test/isolation/expected/fk-partitioned-2.out +++ b/src/test/isolation/expected/fk-partitioned-2.out @@ -57,7 +57,7 @@ step s2i: insert into pfk values (1); step s1d: delete from ppk where a = 1; step s2c: commit; step s1d: <... completed> -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; starting permutation: s1b s2bs s2i s1d s2c s1c @@ -72,5 +72,5 @@ step s2i: insert into pfk values (1); step s1d: delete from ppk where a = 1; step s2c: commit; step s1d: <... completed> -ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey1" on table "pfk" +ERROR: update or delete on table "ppk1" violates foreign key constraint "pfk_a_fkey_1" on table "pfk" step s1c: commit; diff --git a/src/test/isolation/expected/index-only-bitmapscan.out b/src/test/isolation/expected/index-only-bitmapscan.out new file mode 100644 index 0000000000000..9f27df201537c --- /dev/null +++ b/src/test/isolation/expected/index-only-bitmapscan.out @@ -0,0 +1,48 @@ +Parsed test spec with 2 sessions + +starting permutation: s2_vacuum s2_mod s1_explain s1_begin s1_prepare s1_fetch_1 s2_vacuum s1_fetch_all s1_commit +step s2_vacuum: + VACUUM (TRUNCATE false) ios_bitmap; + +step s2_mod: + DELETE FROM ios_bitmap WHERE a > 1; + +step s1_explain: + EXPlAIN (COSTS OFF) DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0; + +QUERY PLAN +--------------------------------------------------- +WindowAgg + Window: w1 AS (ROWS UNBOUNDED PRECEDING) + -> Bitmap Heap Scan on ios_bitmap + Recheck Cond: ((a > 0) OR (b > 0)) + -> BitmapOr + -> Bitmap Index Scan on ios_bitmap_a + Index Cond: (a > 0) + -> Bitmap Index Scan on ios_bitmap_b + Index Cond: (b > 0) +(9 rows) + +step s1_begin: BEGIN; +step s1_prepare: + DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0; + +step s1_fetch_1: + FETCH FROM foo; + +row_number +---------- + 1 +(1 row) + +step s2_vacuum: + VACUUM (TRUNCATE false) ios_bitmap; + +step s1_fetch_all: + FETCH ALL FROM foo; + +row_number +---------- +(0 rows) + +step s1_commit: COMMIT; diff --git a/src/test/isolation/expected/inplace-inval.out b/src/test/isolation/expected/inplace-inval.out index e68eca5de98dd..c35895a8aa7b0 100644 --- a/src/test/isolation/expected/inplace-inval.out +++ b/src/test/isolation/expected/inplace-inval.out @@ -1,6 +1,6 @@ Parsed test spec with 3 sessions -starting permutation: cachefill3 cir1 cic2 ddl3 +starting permutation: cachefill3 cir1 cic2 ddl3 read1 step cachefill3: TABLE newly_indexed; c - @@ -9,6 +9,14 @@ c step cir1: BEGIN; CREATE INDEX i1 ON newly_indexed (c); ROLLBACK; step cic2: CREATE INDEX i2 ON newly_indexed (c); step ddl3: ALTER TABLE newly_indexed ADD extra int; +step read1: + SELECT relhasindex FROM pg_class WHERE oid = 'newly_indexed'::regclass; + +relhasindex +----------- +t +(1 row) + starting permutation: cir1 cic2 ddl3 read1 step cir1: BEGIN; CREATE INDEX i1 ON newly_indexed (c); ROLLBACK; diff --git a/src/test/isolation/expected/intra-grant-inplace-db.out b/src/test/isolation/expected/intra-grant-inplace-db.out index 432ece5636153..a91402ccb8f38 100644 --- a/src/test/isolation/expected/intra-grant-inplace-db.out +++ b/src/test/isolation/expected/intra-grant-inplace-db.out @@ -9,20 +9,20 @@ step b1: BEGIN; step grant1: GRANT TEMP ON DATABASE isolation_regression TO regress_temp_grantee; -step vac2: VACUUM (FREEZE); +step vac2: VACUUM (FREEZE); step snap3: INSERT INTO frozen_witness SELECT datfrozenxid FROM pg_database WHERE datname = current_catalog; step c1: COMMIT; +step vac2: <... completed> step cmp3: SELECT 'datfrozenxid retreated' FROM pg_database WHERE datname = current_catalog AND age(datfrozenxid) > (SELECT min(age(x)) FROM frozen_witness); -?column? ----------------------- -datfrozenxid retreated -(1 row) +?column? +-------- +(0 rows) diff --git a/src/test/isolation/expected/intra-grant-inplace.out b/src/test/isolation/expected/intra-grant-inplace.out index cc1e47a302c9e..1aa9da622da05 100644 --- a/src/test/isolation/expected/intra-grant-inplace.out +++ b/src/test/isolation/expected/intra-grant-inplace.out @@ -14,15 +14,16 @@ relhasindex f (1 row) -step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); +step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); step c1: COMMIT; +step addk2: <... completed> step read2: SELECT relhasindex FROM pg_class WHERE oid = 'intra_grant_inplace'::regclass; relhasindex ----------- -f +t (1 row) @@ -58,8 +59,33 @@ relhasindex f (1 row) -step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); +step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); step r3: ROLLBACK; +step addk2: <... completed> + +starting permutation: b3 sfnku3 keyshr5 addk2 r3 +step b3: BEGIN ISOLATION LEVEL READ COMMITTED; +step sfnku3: + SELECT relhasindex FROM pg_class + WHERE oid = 'intra_grant_inplace'::regclass FOR NO KEY UPDATE; + +relhasindex +----------- +f +(1 row) + +step keyshr5: + SELECT relhasindex FROM pg_class + WHERE oid = 'intra_grant_inplace'::regclass FOR KEY SHARE; + +relhasindex +----------- +f +(1 row) + +step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); +step r3: ROLLBACK; +step addk2: <... completed> starting permutation: b2 sfnku2 addk2 c2 step b2: BEGIN; @@ -122,17 +148,18 @@ relhasindex f (1 row) -step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); +step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); step r3: ROLLBACK; step grant1: <... completed> step c1: COMMIT; +step addk2: <... completed> step read2: SELECT relhasindex FROM pg_class WHERE oid = 'intra_grant_inplace'::regclass; relhasindex ----------- -f +t (1 row) @@ -151,9 +178,11 @@ step b1: BEGIN; step grant1: GRANT SELECT ON intra_grant_inplace TO PUBLIC; -step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); -step c2: COMMIT; +step addk2: ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); +step addk2: <... completed> +ERROR: deadlock detected step grant1: <... completed> +step c2: COMMIT; step c1: COMMIT; step read2: SELECT relhasindex FROM pg_class @@ -191,9 +220,8 @@ relhasindex f (1 row) -s4: WARNING: got: tuple concurrently updated -step revoke4: <... completed> step r3: ROLLBACK; +step revoke4: <... completed> starting permutation: b1 drop1 b3 sfu3 revoke4 c1 r3 step b1: BEGIN; @@ -220,6 +248,6 @@ relhasindex ----------- (0 rows) -s4: WARNING: got: tuple concurrently deleted +s4: WARNING: got: relation "intra_grant_inplace" does not exist step revoke4: <... completed> step r3: ROLLBACK; diff --git a/src/test/isolation/expected/merge-update.out b/src/test/isolation/expected/merge-update.out index 3063c0c6ab1c5..677263d1ec1b8 100644 --- a/src/test/isolation/expected/merge-update.out +++ b/src/test/isolation/expected/merge-update.out @@ -40,12 +40,12 @@ step merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; -merge_action|key|val -------------+---+------------------------------------------------------ -UPDATE | 3|setup1 updated by merge1 source not matched by merge2a -INSERT | 1|merge2a +merge_action|old |new |key|val +------------+------------------------------+------------------------------------------------------------+---+------------------------------------------------------ +UPDATE |(2,"setup1 updated by merge1")|(3,"setup1 updated by merge1 source not matched by merge2a")| 3|setup1 updated by merge1 source not matched by merge2a +INSERT | |(1,merge2a) | 1|merge2a (2 rows) step select2: SELECT * FROM target; @@ -98,14 +98,14 @@ step merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; step c1: COMMIT; step merge2a: <... completed> -merge_action|key|val -------------+---+------------------------------------------------------ -UPDATE | 3|setup1 updated by merge1 source not matched by merge2a -INSERT | 1|merge2a +merge_action|old |new |key|val +------------+------------------------------+------------------------------------------------------------+---+------------------------------------------------------ +UPDATE |(2,"setup1 updated by merge1")|(3,"setup1 updated by merge1 source not matched by merge2a")| 3|setup1 updated by merge1 source not matched by merge2a +INSERT | |(1,merge2a) | 1|merge2a (2 rows) step select2: SELECT * FROM target; @@ -137,13 +137,13 @@ step merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; step a1: ABORT; step merge2a: <... completed> -merge_action|key|val -------------+---+------------------------- -UPDATE | 2|setup1 updated by merge2a +merge_action|old |new |key|val +------------+----------+-------------------------------+---+------------------------- +UPDATE |(1,setup1)|(2,"setup1 updated by merge2a")| 2|setup1 updated by merge2a (1 row) step select2: SELECT * FROM target; @@ -234,14 +234,14 @@ step pa_merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by pa_merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; step c1: COMMIT; step pa_merge2a: <... completed> -merge_action|key|val -------------+---+-------------------------------------------------- -UPDATE | 2|initial updated by pa_merge1 updated by pa_merge2a -UPDATE | 3|initial source not matched by pa_merge2a +merge_action|old |new |key|val +------------+----------------------------------+--------------------------------------------------------+---+-------------------------------------------------- +UPDATE |(1,"initial updated by pa_merge1")|(2,"initial updated by pa_merge1 updated by pa_merge2a")| 2|initial updated by pa_merge1 updated by pa_merge2a +UPDATE |(2,initial) |(3,"initial source not matched by pa_merge2a") | 3|initial source not matched by pa_merge2a (2 rows) step pa_select2: SELECT * FROM pa_target; @@ -273,7 +273,7 @@ step pa_merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by pa_merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; step c1: COMMIT; step pa_merge2a: <... completed> @@ -303,13 +303,13 @@ step pa_merge2a: UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by pa_merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; -merge_action|key|val -------------+---+------------------------------------------------------------- -UPDATE | 3|initial source not matched by pa_merge2a -UPDATE | 3|initial updated by pa_merge2 source not matched by pa_merge2a -INSERT | 1|pa_merge2a +merge_action|old |new |key|val +------------+----------------------------------+-------------------------------------------------------------------+---+------------------------------------------------------------- +UPDATE |(2,initial) |(3,"initial source not matched by pa_merge2a") | 3|initial source not matched by pa_merge2a +UPDATE |(2,"initial updated by pa_merge2")|(3,"initial updated by pa_merge2 source not matched by pa_merge2a")| 3|initial updated by pa_merge2 source not matched by pa_merge2a +INSERT | |(1,pa_merge2a) | 1|pa_merge2a (3 rows) step pa_select2: SELECT * FROM pa_target; diff --git a/src/test/isolation/expected/partition-merge.out b/src/test/isolation/expected/partition-merge.out deleted file mode 100644 index 98446aaab5aab..0000000000000 --- a/src/test/isolation/expected/partition-merge.out +++ /dev/null @@ -1,199 +0,0 @@ -Parsed test spec with 2 sessions - -starting permutation: s2b s2i s2c s1b s1merg s2b s2u s1c s2c s2s -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1b: BEGIN; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2b s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2b s2i s2c s1bs s1merg s2b s2u s1c s2c s2s -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2brr s2i s2c s1b s1merg s2b s2u s1c s2c s2s -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1b: BEGIN; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2brr s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2brr s2i s2c s1bs s1merg s2b s2u s1c s2c s2s -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2bs s2i s2c s1b s1merg s2b s2u s1c s2c s2s -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1b: BEGIN; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2bs s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - - -starting permutation: s2bs s2i s2c s1bs s1merg s2b s2u s1c s2c s2s -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s2c: COMMIT; -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1merg: ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; -step s2b: BEGIN; -step s2u: UPDATE tpart SET t = 'text01modif' where i = 1; -step s1c: COMMIT; -step s2u: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+----------- - 5|text05 -15|text15 - 1|text01modif -25|text25 -35|text35 -(5 rows) - diff --git a/src/test/isolation/expected/partition-split.out b/src/test/isolation/expected/partition-split.out deleted file mode 100644 index 5d9e8b0925f3c..0000000000000 --- a/src/test/isolation/expected/partition-split.out +++ /dev/null @@ -1,190 +0,0 @@ -Parsed test spec with 2 sessions - -starting permutation: s1b s1splt s2b s2i s1c s2c s2s -step s1b: BEGIN; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1b s1splt s2brr s2i s1c s2c s2s -step s1b: BEGIN; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1b s1splt s2bs s2i s1c s2c s2s -step s1b: BEGIN; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1brr s1splt s2b s2i s1c s2c s2s -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1brr s1splt s2brr s2i s1c s2c s2s -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1brr s1splt s2bs s2i s1c s2c s2s -step s1brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1bs s1splt s2b s2i s1c s2c s2s -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2b: BEGIN; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1bs s1splt s2brr s2i s1c s2c s2s -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2brr: BEGIN ISOLATION LEVEL REPEATABLE READ; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - - -starting permutation: s1bs s1splt s2bs s2i s1c s2c s2s -step s1bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s1splt: ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); -step s2bs: BEGIN ISOLATION LEVEL SERIALIZABLE; -step s2i: INSERT INTO tpart VALUES (1, 'text01'); -step s1c: COMMIT; -step s2i: <... completed> -step s2c: COMMIT; -step s2s: SELECT * FROM tpart; - i|t ---+------ - 5|text05 - 1|text01 -15|text15 -25|text25 -35|text35 -(5 rows) - diff --git a/src/test/isolation/isolation_main.c b/src/test/isolation/isolation_main.c index 8b108a31b11f7..a13f9cdcaf773 100644 --- a/src/test/isolation/isolation_main.c +++ b/src/test/isolation/isolation_main.c @@ -2,7 +2,7 @@ * * isolation_main --- pg_regress test launcher for isolation tests * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/test/isolation/isolation_main.c diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 6da98cffacad7..e3c669a29c7aa 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -17,6 +17,7 @@ test: partial-index test: two-ids test: multiple-row-versions test: index-only-scan +test: index-only-bitmapscan test: predicate-lock-hot-tuple test: update-conflict-out test: deadlock-simple @@ -106,8 +107,6 @@ test: partition-key-update-1 test: partition-key-update-2 test: partition-key-update-3 test: partition-key-update-4 -test: partition-merge -test: partition-split test: plpgsql-toast test: cluster-conflict test: cluster-conflict-partition diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index 0b342b5c2bbba..e01c0c9de936e 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -178,7 +178,7 @@ main(int argc, char **argv) if (i != 0) PQsetNoticeProcessor(conns[i].conn, isotesterNoticeProcessor, - (void *) &conns[i]); + &conns[i]); else PQsetNoticeProcessor(conns[i].conn, blackholeNoticeProcessor, diff --git a/src/test/isolation/isolationtester.h b/src/test/isolation/isolationtester.h index fca67106153e2..1ef14dc990970 100644 --- a/src/test/isolation/isolationtester.h +++ b/src/test/isolation/isolationtester.h @@ -3,7 +3,7 @@ * isolationtester.h * include file for isolation tests * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/test/isolation/meson.build b/src/test/isolation/meson.build index 1082887a44afe..a180e4e2741ad 100644 --- a/src/test/isolation/meson.build +++ b/src/test/isolation/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # pg_regress_c helpfully provided by regress/meson.build diff --git a/src/test/isolation/specparse.y b/src/test/isolation/specparse.y index 282a750455651..98949a446e5c6 100644 --- a/src/test/isolation/specparse.y +++ b/src/test/isolation/specparse.y @@ -4,7 +4,7 @@ * specparse.y * bison grammar for the isolation test file format * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *------------------------------------------------------------------------- @@ -13,6 +13,7 @@ #include "postgres_fe.h" #include "isolationtester.h" +#include "specparse.h" /* silence -Wmissing-variable-declarations */ extern int spec_yychar; diff --git a/src/test/isolation/specs/deadlock-parallel.spec b/src/test/isolation/specs/deadlock-parallel.spec index 2016bcddae927..8b2c47afcaebc 100644 --- a/src/test/isolation/specs/deadlock-parallel.spec +++ b/src/test/isolation/specs/deadlock-parallel.spec @@ -2,8 +2,9 @@ # It's fairly hard to get parallel worker processes to block on locks, # since generally they don't want any locks their leader didn't already -# take. We cheat like mad here by making a function that takes a lock, -# and is incorrectly marked parallel-safe so that it can execute in a worker. +# take. We cheat like mad here by creating aliases for advisory-lock +# functions that are incorrectly marked parallel-safe so that they can +# execute in a worker. # Note that we explicitly override any global settings of isolation level # or debug_parallel_query, to ensure we're testing what we intend to. @@ -36,11 +37,21 @@ setup { +-- The alias functions themselves. Really these return "void", but +-- the implementation is such that we can declare them to return "int", +-- and we will get a zero result. + create function lock_share(bigint) returns int language internal as + 'pg_advisory_xact_lock_shared_int8' strict parallel safe; + + create function lock_excl(bigint) returns int language internal as + 'pg_advisory_xact_lock_int8' strict parallel safe; + +-- Inline-able wrappers that will produce an integer "1" result: create function lock_share(int,int) returns int language sql as - 'select pg_advisory_xact_lock_shared($1); select 1;' parallel safe; + 'select 1 - lock_share($1)' parallel safe; create function lock_excl(int,int) returns int language sql as - 'select pg_advisory_xact_lock($1); select 1;' parallel safe; + 'select 1 - lock_excl($1)' parallel safe; create table bigt as select x from generate_series(1, 10000) x; analyze bigt; diff --git a/src/test/isolation/specs/eval-plan-qual.spec b/src/test/isolation/specs/eval-plan-qual.spec index 3a74406f4d98a..07307e623e473 100644 --- a/src/test/isolation/specs/eval-plan-qual.spec +++ b/src/test/isolation/specs/eval-plan-qual.spec @@ -194,7 +194,7 @@ step simplepartupdate_noroute { update parttbl set b = 2 where c = 1 returning *; } -# test system class updates +# test system class LockTuple() step sys1 { UPDATE pg_class SET reltuples = 123 WHERE oid = 'accounts'::regclass; diff --git a/src/test/isolation/specs/horizons.spec b/src/test/isolation/specs/horizons.spec index d5239ff22870d..3f987f943df10 100644 --- a/src/test/isolation/specs/horizons.spec +++ b/src/test/isolation/specs/horizons.spec @@ -40,7 +40,6 @@ session pruner setup { SET enable_seqscan = false; - SET enable_indexscan = false; SET enable_bitmapscan = false; } diff --git a/src/test/isolation/specs/index-only-bitmapscan.spec b/src/test/isolation/specs/index-only-bitmapscan.spec new file mode 100644 index 0000000000000..4cd8b3ccdef01 --- /dev/null +++ b/src/test/isolation/specs/index-only-bitmapscan.spec @@ -0,0 +1,108 @@ +# In the past we supported index-only bitmap heapscans. However the +# implementation was unsound, see +# https://postgr.es/m/873c33c5-ef9e-41f6-80b2-2f5e11869f1c%40garret.ru +# +# This test reliably triggered the problem before we removed the +# optimization. We keep the test around to make it less likely for a similar +# problem to be re-introduced. + +setup +{ + -- by using a low fillfactor and a wide tuple we can get multiple blocks + -- with just few rows + CREATE TABLE ios_bitmap (a int NOT NULL, b int not null, pad char(1024) default '') + WITH (AUTOVACUUM_ENABLED = false, FILLFACTOR = 10); + + INSERT INTO ios_bitmap SELECT g.i, g.i FROM generate_series(1, 10) g(i); + + CREATE INDEX ios_bitmap_a ON ios_bitmap(a); + CREATE INDEX ios_bitmap_b ON ios_bitmap(b); +} + +teardown +{ + DROP TABLE ios_bitmap; +} + + +session s1 + +setup +{ + SET enable_seqscan = false; +} + +step s1_begin { BEGIN; } +step s1_commit { COMMIT; } + + +# The test query uses an or between two indexes to ensure make it more likely +# to use a bitmap index scan +# +# The row_number() hack is a way to have something returned (isolationtester +# doesn't display empty rows) while still allowing for the index-only scan +# optimization in bitmap heap scans, which requires an empty targetlist. +step s1_prepare +{ + DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0; +} + +step s1_explain +{ + EXPlAIN (COSTS OFF) DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0; +} + +step s1_fetch_1 +{ + FETCH FROM foo; +} + +step s1_fetch_all +{ + FETCH ALL FROM foo; +} + + +session s2 + +# Don't delete row 1 so we have a row for the cursor to "rest" on. +step s2_mod +{ + DELETE FROM ios_bitmap WHERE a > 1; +} + +# Disable truncation, as otherwise we'll just wait for a timeout while trying +# to acquire the lock +step s2_vacuum +{ + VACUUM (TRUNCATE false) ios_bitmap; +} + +permutation + # Vacuum first, to ensure VM exists, otherwise the bitmapscan will consider + # VM to be size 0, due to caching. Can't do that in setup because + s2_vacuum + + # Delete nearly all rows, to make issue visible + s2_mod + + # Verify that the appropriate plan is chosen + s1_explain + + # Create a cursor + s1_begin + s1_prepare + + # Fetch one row from the cursor, that ensures the index scan portion is done + # before the vacuum in the next step + s1_fetch_1 + + # With the bug this vacuum would have marked pages as all-visible that the + # scan in the next step then would have considered all-visible, despite all + # rows from those pages having been removed. + s2_vacuum + + # If this returns any rows, the bug is present + s1_fetch_all + + s1_commit diff --git a/src/test/isolation/specs/inplace-inval.spec b/src/test/isolation/specs/inplace-inval.spec index 96954fd86c439..b99112ddb8818 100644 --- a/src/test/isolation/specs/inplace-inval.spec +++ b/src/test/isolation/specs/inplace-inval.spec @@ -1,7 +1,7 @@ -# If a heap_update() caller retrieves its oldtup from a cache, it's possible -# for that cache entry to predate an inplace update, causing loss of that -# inplace update. This arises because the transaction may abort before -# sending the inplace invalidation message to the shared queue. +# An inplace update had been able to abort before sending the inplace +# invalidation message to the shared queue. If a heap_update() caller then +# retrieved its oldtup from a cache, the heap_update() could revert the +# inplace update. setup { @@ -27,14 +27,12 @@ step cachefill3 { TABLE newly_indexed; } step ddl3 { ALTER TABLE newly_indexed ADD extra int; } -# XXX shows an extant bug. Adding step read1 at the end would usually print -# relhasindex=f (not wanted). This does not reach the unwanted behavior under -# -DCATCACHE_FORCE_RELEASE and friends. permutation cachefill3 # populates the pg_class row in the catcache cir1 # sets relhasindex=true; rollback discards cache inval cic2 # sees relhasindex=true, skips changing it (so no inval) ddl3 # cached row as the oldtup of an update, losing relhasindex + read1 # observe damage # without cachefill3, no bug permutation cir1 cic2 ddl3 read1 diff --git a/src/test/isolation/specs/intra-grant-inplace-db.spec b/src/test/isolation/specs/intra-grant-inplace-db.spec index bbecd5ddde51f..9de40ec5c949b 100644 --- a/src/test/isolation/specs/intra-grant-inplace-db.spec +++ b/src/test/isolation/specs/intra-grant-inplace-db.spec @@ -42,5 +42,4 @@ step cmp3 { } -# XXX extant bug permutation snap3 b1 grant1 vac2(c1) snap3 c1 cmp3 diff --git a/src/test/isolation/specs/intra-grant-inplace.spec b/src/test/isolation/specs/intra-grant-inplace.spec index 3cd696b81f272..9936d389359e5 100644 --- a/src/test/isolation/specs/intra-grant-inplace.spec +++ b/src/test/isolation/specs/intra-grant-inplace.spec @@ -14,6 +14,7 @@ teardown # heap_update() session s1 +setup { SET deadlock_timeout = '100s'; } step b1 { BEGIN; } step grant1 { GRANT SELECT ON intra_grant_inplace TO PUBLIC; @@ -25,6 +26,7 @@ step c1 { COMMIT; } # inplace update session s2 +setup { SET deadlock_timeout = '10ms'; } step read2 { SELECT relhasindex FROM pg_class WHERE oid = 'intra_grant_inplace'::regclass; @@ -73,8 +75,6 @@ step keyshr5 { teardown { ROLLBACK; } -# XXX extant bugs: permutation comments refer to planned post-bugfix behavior - permutation b1 grant1 @@ -96,6 +96,14 @@ permutation addk2(r3) r3 +# reproduce bug in DoesMultiXactIdConflict() call +permutation + b3 + sfnku3 + keyshr5 + addk2(r3) + r3 + # same-xact rowmark permutation b2 @@ -126,8 +134,8 @@ permutation b2 sfnku2 b1 - grant1(c2) # acquire LockTuple(), await sfnku2 xmax - addk2 # block in LockTuple() behind grant1 = deadlock + grant1(addk2) # acquire LockTuple(), await sfnku2 xmax + addk2(*) # block in LockTuple() behind grant1 = deadlock c2 c1 read2 @@ -138,7 +146,7 @@ permutation grant1 b3 sfu3(c1) # acquire LockTuple(), await grant1 xmax - revoke4(sfu3) # block in LockTuple() behind sfu3 + revoke4(r3) # block in LockTuple() behind sfu3 c1 r3 # revoke4 unlocks old tuple and finds new diff --git a/src/test/isolation/specs/merge-match-recheck.spec b/src/test/isolation/specs/merge-match-recheck.spec index 298b2bfdcd609..26266b8c2978e 100644 --- a/src/test/isolation/specs/merge-match-recheck.spec +++ b/src/test/isolation/specs/merge-match-recheck.spec @@ -1,4 +1,4 @@ -# MERGE MATCHED RECHECK +# MERGE MATCHED recheck # # This test looks at what happens when we have complex # WHEN MATCHED AND conditions and a concurrent UPDATE causes a diff --git a/src/test/isolation/specs/merge-update.spec b/src/test/isolation/specs/merge-update.spec index a33dcdba53711..c718ff646b2d1 100644 --- a/src/test/isolation/specs/merge-update.spec +++ b/src/test/isolation/specs/merge-update.spec @@ -95,7 +95,7 @@ step "merge2a" UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; } step "merge2b" { @@ -128,7 +128,7 @@ step "pa_merge2a" UPDATE set key = t.key + 1, val = t.val || ' updated by ' || s.val WHEN NOT MATCHED BY SOURCE THEN UPDATE set key = t.key + 1, val = t.val || ' source not matched by pa_merge2a' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; } # MERGE proceeds only if 'val' unchanged step "pa_merge2b_when" diff --git a/src/test/isolation/specs/partition-merge.spec b/src/test/isolation/specs/partition-merge.spec deleted file mode 100644 index dc2b9d3445f3f..0000000000000 --- a/src/test/isolation/specs/partition-merge.spec +++ /dev/null @@ -1,54 +0,0 @@ -# Verify that MERGE operation locks DML operations with partitioned table - -setup -{ - DROP TABLE IF EXISTS tpart; - CREATE TABLE tpart(i int, t text) partition by range(i); - CREATE TABLE tpart_00_10 PARTITION OF tpart FOR VALUES FROM (0) TO (10); - CREATE TABLE tpart_10_20 PARTITION OF tpart FOR VALUES FROM (10) TO (20); - CREATE TABLE tpart_20_30 PARTITION OF tpart FOR VALUES FROM (20) TO (30); - CREATE TABLE tpart_default PARTITION OF tpart DEFAULT; - INSERT INTO tpart VALUES (5, 'text05'); - INSERT INTO tpart VALUES (15, 'text15'); - INSERT INTO tpart VALUES (25, 'text25'); - INSERT INTO tpart VALUES (35, 'text35'); -} - -teardown -{ - DROP TABLE tpart; -} - -session s1 -step s1b { BEGIN; } -step s1brr { BEGIN ISOLATION LEVEL REPEATABLE READ; } -step s1bs { BEGIN ISOLATION LEVEL SERIALIZABLE; } -step s1merg { ALTER TABLE tpart MERGE PARTITIONS (tpart_00_10, tpart_10_20) INTO tpart_00_20; } -step s1c { COMMIT; } - - -session s2 -step s2b { BEGIN; } -step s2brr { BEGIN ISOLATION LEVEL REPEATABLE READ; } -step s2bs { BEGIN ISOLATION LEVEL SERIALIZABLE; } -step s2i { INSERT INTO tpart VALUES (1, 'text01'); } -step s2u { UPDATE tpart SET t = 'text01modif' where i = 1; } -step s2c { COMMIT; } -step s2s { SELECT * FROM tpart; } - - -# s2 inserts row into table. s1 starts MERGE PARTITIONS then -# s2 is trying to update inserted row and waits until s1 finishes -# MERGE operation. - -permutation s2b s2i s2c s1b s1merg s2b s2u s1c s2c s2s -permutation s2b s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -permutation s2b s2i s2c s1bs s1merg s2b s2u s1c s2c s2s - -permutation s2brr s2i s2c s1b s1merg s2b s2u s1c s2c s2s -permutation s2brr s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -permutation s2brr s2i s2c s1bs s1merg s2b s2u s1c s2c s2s - -permutation s2bs s2i s2c s1b s1merg s2b s2u s1c s2c s2s -permutation s2bs s2i s2c s1brr s1merg s2b s2u s1c s2c s2s -permutation s2bs s2i s2c s1bs s1merg s2b s2u s1c s2c s2s diff --git a/src/test/isolation/specs/partition-split.spec b/src/test/isolation/specs/partition-split.spec deleted file mode 100644 index 087239a4a19ef..0000000000000 --- a/src/test/isolation/specs/partition-split.spec +++ /dev/null @@ -1,54 +0,0 @@ -# Verify that SPLIT operation locks DML operations with partitioned table - -setup -{ - DROP TABLE IF EXISTS tpart; - CREATE TABLE tpart(i int, t text) partition by range(i); - CREATE TABLE tpart_00_10 PARTITION OF tpart FOR VALUES FROM (0) TO (10); - CREATE TABLE tpart_10_20 PARTITION OF tpart FOR VALUES FROM (10) TO (20); - CREATE TABLE tpart_20_30 PARTITION OF tpart FOR VALUES FROM (20) TO (30); - CREATE TABLE tpart_default PARTITION OF tpart DEFAULT; - INSERT INTO tpart VALUES (5, 'text05'); - INSERT INTO tpart VALUES (15, 'text15'); - INSERT INTO tpart VALUES (25, 'text25'); - INSERT INTO tpart VALUES (35, 'text35'); -} - -teardown -{ - DROP TABLE tpart; -} - -session s1 -step s1b { BEGIN; } -step s1brr { BEGIN ISOLATION LEVEL REPEATABLE READ; } -step s1bs { BEGIN ISOLATION LEVEL SERIALIZABLE; } -step s1splt { ALTER TABLE tpart SPLIT PARTITION tpart_10_20 INTO - (PARTITION tpart_10_15 FOR VALUES FROM (10) TO (15), - PARTITION tpart_15_20 FOR VALUES FROM (15) TO (20)); } -step s1c { COMMIT; } - - -session s2 -step s2b { BEGIN; } -step s2brr { BEGIN ISOLATION LEVEL REPEATABLE READ; } -step s2bs { BEGIN ISOLATION LEVEL SERIALIZABLE; } -step s2i { INSERT INTO tpart VALUES (1, 'text01'); } -step s2c { COMMIT; } -step s2s { SELECT * FROM tpart; } - - -# s1 starts SPLIT PARTITION then s2 trying to insert row and -# waits until s1 finished SPLIT operation. - -permutation s1b s1splt s2b s2i s1c s2c s2s -permutation s1b s1splt s2brr s2i s1c s2c s2s -permutation s1b s1splt s2bs s2i s1c s2c s2s - -permutation s1brr s1splt s2b s2i s1c s2c s2s -permutation s1brr s1splt s2brr s2i s1c s2c s2s -permutation s1brr s1splt s2bs s2i s1c s2c s2s - -permutation s1bs s1splt s2b s2i s1c s2c s2s -permutation s1bs s1splt s2brr s2i s1c s2c s2s -permutation s1bs s1splt s2bs s2i s1c s2c s2s diff --git a/src/test/isolation/specscanner.l b/src/test/isolation/specscanner.l index a643002804a2c..068a77836c962 100644 --- a/src/test/isolation/specscanner.l +++ b/src/test/isolation/specscanner.l @@ -4,7 +4,7 @@ * specscanner.l * a lexical scanner for an isolation test specification * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * *------------------------------------------------------------------------- diff --git a/src/test/kerberos/Makefile b/src/test/kerberos/Makefile index 3bb85b95431c5..ddaa6deaa6793 100644 --- a/src/test/kerberos/Makefile +++ b/src/test/kerberos/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/kerberos # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/kerberos/Makefile diff --git a/src/test/kerberos/meson.build b/src/test/kerberos/meson.build index b5a18c8df2d08..509e993558500 100644 --- a/src/test/kerberos/meson.build +++ b/src/test/kerberos/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'kerberos', diff --git a/src/test/kerberos/t/001_auth.pl b/src/test/kerberos/t/001_auth.pl index d4f1ec5809215..b0be96f2beba6 100644 --- a/src/test/kerberos/t/001_auth.pl +++ b/src/test/kerberos/t/001_auth.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Sets up a KDC and then runs a variety of tests to make sure that the # GSSAPI/Kerberos authentication and encryption are working properly, @@ -65,7 +65,8 @@ 'postgresql.conf', qq{ listen_addresses = '$hostaddr' krb_server_keyfile = '$krb->{keytab}' -log_connections = on +log_connections = all +log_min_messages = debug2 lc_messages = 'C' }); $node->start; diff --git a/src/test/ldap/LdapServer.pm b/src/test/ldap/LdapServer.pm index 3866a56e0a6b4..58619a3db0a4d 100644 --- a/src/test/ldap/LdapServer.pm +++ b/src/test/ldap/LdapServer.pm @@ -5,7 +5,7 @@ # # Module to set up an LDAP server for testing pg_hba.conf ldap authentication # -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # ############################################################################ diff --git a/src/test/ldap/Makefile b/src/test/ldap/Makefile index 72953cc3f627f..e852069d7fbbc 100644 --- a/src/test/ldap/Makefile +++ b/src/test/ldap/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/ldap # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/ldap/Makefile diff --git a/src/test/ldap/meson.build b/src/test/ldap/meson.build index b8602e752f1cf..7eaa393212ad0 100644 --- a/src/test/ldap/meson.build +++ b/src/test/ldap/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'ldap', diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl index 43e029921ca79..440c30b7ddd1d 100644 --- a/src/test/ldap/t/001_auth.pl +++ b/src/test/ldap/t/001_auth.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -47,7 +47,9 @@ my $node = PostgreSQL::Test::Cluster->new('node'); $node->init; -$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->append_conf('postgresql.conf', "log_connections = all\n"); +# Needed to allow connect_fails to inspect postmaster log: +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); $node->start; $node->safe_psql('postgres', 'CREATE USER test0;'); diff --git a/src/test/ldap/t/002_bindpasswd.pl b/src/test/ldap/t/002_bindpasswd.pl index a89e363546f6f..642bb2d9a7759 100644 --- a/src/test/ldap/t/002_bindpasswd.pl +++ b/src/test/ldap/t/002_bindpasswd.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -43,7 +43,7 @@ my $node = PostgreSQL::Test::Cluster->new('node'); $node->init; -$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->append_conf('postgresql.conf', "log_connections = all\n"); $node->start; $node->safe_psql('postgres', 'CREATE USER test0;'); diff --git a/src/test/locale/sort-test.pl b/src/test/locale/sort-test.pl index 78b58b1cdcc66..7f0b6edeb771d 100755 --- a/src/test/locale/sort-test.pl +++ b/src/test/locale/sort-test.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/test/meson.build b/src/test/meson.build index c3d0dfedf1c5f..ccc31d6a86a1b 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -1,9 +1,10 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('regress') subdir('isolation') subdir('authentication') +subdir('postmaster') subdir('recovery') subdir('subscription') subdir('modules') diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile index 256799f520a1c..aa1d27bbed310 100644 --- a/src/test/modules/Makefile +++ b/src/test/modules/Makefile @@ -11,14 +11,17 @@ SUBDIRS = \ dummy_index_am \ dummy_seclabel \ libpq_pipeline \ + oauth_validator \ plsample \ spgist_name_ops \ + test_aio \ test_bloomfilter \ test_copy_callbacks \ test_custom_rmgrs \ test_ddl_deparse \ test_dsa \ test_dsm_registry \ + test_escape \ test_extensions \ test_ginpostinglist \ test_integerset \ @@ -43,9 +46,9 @@ SUBDIRS = \ ifeq ($(enable_injection_points),yes) -SUBDIRS += injection_points gin +SUBDIRS += injection_points gin typcache else -ALWAYS_SUBDIRS += injection_points gin +ALWAYS_SUBDIRS += injection_points gin typcache endif ifeq ($(with_ssl),openssl) diff --git a/src/test/modules/brin/meson.build b/src/test/modules/brin/meson.build index 7703ce4236bed..e88a7c39c90b2 100644 --- a/src/test/modules/brin/meson.build +++ b/src/test/modules/brin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'brin', diff --git a/src/test/modules/brin/t/01_workitems.pl b/src/test/modules/brin/t/01_workitems.pl index b56e40d2d416c..c3b1fb517062d 100644 --- a/src/test/modules/brin/t/01_workitems.pl +++ b/src/test/modules/brin/t/01_workitems.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify that work items work correctly diff --git a/src/test/modules/brin/t/02_wal_consistency.pl b/src/test/modules/brin/t/02_wal_consistency.pl index 8325400bffa02..66919ab391cdc 100644 --- a/src/test/modules/brin/t/02_wal_consistency.pl +++ b/src/test/modules/brin/t/02_wal_consistency.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify WAL consistency diff --git a/src/test/modules/commit_ts/meson.build b/src/test/modules/commit_ts/meson.build index b99401bb0987d..27598253e020a 100644 --- a/src/test/modules/commit_ts/meson.build +++ b/src/test/modules/commit_ts/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'commit_ts', diff --git a/src/test/modules/commit_ts/t/001_base.pl b/src/test/modules/commit_ts/t/001_base.pl index e608ec67704af..1953b18f6b3c3 100644 --- a/src/test/modules/commit_ts/t/001_base.pl +++ b/src/test/modules/commit_ts/t/001_base.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Single-node test: value can be set, and is still present after recovery diff --git a/src/test/modules/commit_ts/t/002_standby.pl b/src/test/modules/commit_ts/t/002_standby.pl index bc4f1b05c64bc..f76d474270bd0 100644 --- a/src/test/modules/commit_ts/t/002_standby.pl +++ b/src/test/modules/commit_ts/t/002_standby.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test simple scenario involving a standby diff --git a/src/test/modules/commit_ts/t/003_standby_2.pl b/src/test/modules/commit_ts/t/003_standby_2.pl index 2bf606732ba2e..3b27da6b23752 100644 --- a/src/test/modules/commit_ts/t/003_standby_2.pl +++ b/src/test/modules/commit_ts/t/003_standby_2.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test primary/standby scenario where the track_commit_timestamp GUC is # repeatedly toggled on and off. @@ -57,7 +57,7 @@ $primary->append_conf('postgresql.conf', 'track_commit_timestamp = off'); $primary->restart; -system_or_bail('pg_ctl', '-D', $standby->data_dir, 'promote'); +system_or_bail('pg_ctl', '--pgdata' => $standby->data_dir, 'promote'); $standby->safe_psql('postgres', "create table t11()"); my $standby_ts = $standby->safe_psql('postgres', diff --git a/src/test/modules/commit_ts/t/004_restart.pl b/src/test/modules/commit_ts/t/004_restart.pl index 7383bd6e9a501..b31bbbe24ed0c 100644 --- a/src/test/modules/commit_ts/t/004_restart.pl +++ b/src/test/modules/commit_ts/t/004_restart.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Testing of commit timestamps preservation across restarts use strict; diff --git a/src/test/modules/delay_execution/delay_execution.c b/src/test/modules/delay_execution/delay_execution.c index 155c8a8d556b4..7bc97f84a1c3c 100644 --- a/src/test/modules/delay_execution/delay_execution.c +++ b/src/test/modules/delay_execution/delay_execution.c @@ -10,7 +10,7 @@ * test behaviors where some specified action happens in another backend * between parsing and execution of any desired query. * - * Copyright (c) 2020-2024, PostgreSQL Global Development Group + * Copyright (c) 2020-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/delay_execution/delay_execution.c @@ -23,7 +23,7 @@ #include #include "optimizer/planner.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/guc.h" #include "utils/inval.h" diff --git a/src/test/modules/delay_execution/meson.build b/src/test/modules/delay_execution/meson.build index 41f3ac0b8949e..b53488f76d2ad 100644 --- a/src/test/modules/delay_execution/meson.build +++ b/src/test/modules/delay_execution/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group delay_execution_sources = files( 'delay_execution.c', diff --git a/src/test/modules/dummy_index_am/dummy_index_am.c b/src/test/modules/dummy_index_am/dummy_index_am.c index 0b4771160672d..94ef639b6fcdb 100644 --- a/src/test/modules/dummy_index_am/dummy_index_am.c +++ b/src/test/modules/dummy_index_am/dummy_index_am.c @@ -3,7 +3,7 @@ * dummy_index_am.c * Index AM template main file. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,8 +18,6 @@ #include "catalog/index.h" #include "commands/vacuum.h" #include "nodes/pathnodes.h" -#include "utils/guc.h" -#include "utils/rel.h" PG_MODULE_MAGIC; @@ -284,6 +282,9 @@ dihandler(PG_FUNCTION_ARGS) amroutine->amsupport = 1; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amcanhash = false; + amroutine->amconsistentequality = false; + amroutine->amconsistentordering = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = false; @@ -308,6 +309,7 @@ dihandler(PG_FUNCTION_ARGS) amroutine->amvacuumcleanup = divacuumcleanup; amroutine->amcanreturn = NULL; amroutine->amcostestimate = dicostestimate; + amroutine->amgettreeheight = NULL; amroutine->amoptions = dioptions; amroutine->amproperty = NULL; amroutine->ambuildphasename = NULL; diff --git a/src/test/modules/dummy_index_am/meson.build b/src/test/modules/dummy_index_am/meson.build index f23787c732f1f..6430eefc81e47 100644 --- a/src/test/modules/dummy_index_am/meson.build +++ b/src/test/modules/dummy_index_am/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dummy_index_am_sources = files( 'dummy_index_am.c', diff --git a/src/test/modules/dummy_seclabel/dummy_seclabel.c b/src/test/modules/dummy_seclabel/dummy_seclabel.c index aded20e1bede7..0b09f8a9c243d 100644 --- a/src/test/modules/dummy_seclabel/dummy_seclabel.c +++ b/src/test/modules/dummy_seclabel/dummy_seclabel.c @@ -7,7 +7,7 @@ * perspective, but allows regression testing independent of platform-specific * features like SELinux. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California */ #include "postgres.h" diff --git a/src/test/modules/dummy_seclabel/meson.build b/src/test/modules/dummy_seclabel/meson.build index 2e0e8741b99de..9269a02d8aa0f 100644 --- a/src/test/modules/dummy_seclabel/meson.build +++ b/src/test/modules/dummy_seclabel/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group dummy_seclabel_sources = files( 'dummy_seclabel.c', diff --git a/src/test/modules/gin/meson.build b/src/test/modules/gin/meson.build index 9734b51de2d4b..12465ce187bec 100644 --- a/src/test/modules/gin/meson.build +++ b/src/test/modules/gin/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not get_option('injection_points') subdir_done() diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile index 2ffd2f77ed174..e680991f8d4f0 100644 --- a/src/test/modules/injection_points/Makefile +++ b/src/test/modules/injection_points/Makefile @@ -1,19 +1,28 @@ # src/test/modules/injection_points/Makefile -MODULES = injection_points - +MODULE_big = injection_points +OBJS = \ + $(WIN32RES) \ + injection_points.o \ + injection_stats.o \ + injection_stats_fixed.o \ + regress_injection.o EXTENSION = injection_points DATA = injection_points--1.0.sql PGFILEDESC = "injection_points - facility for injection points" -REGRESS = injection_points +REGRESS = injection_points hashagg reindex_conc REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress -ISOLATION = inplace +ISOLATION = basic inplace syscache-update-pruned + +TAP_TESTS = 1 # The injection points are cluster-wide, so disable installcheck NO_INSTALLCHECK = 1 +export enable_injection_points + ifdef USE_PGXS PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) diff --git a/src/test/modules/injection_points/expected/basic.out b/src/test/modules/injection_points/expected/basic.out new file mode 100644 index 0000000000000..4fc218ed00dd0 --- /dev/null +++ b/src/test/modules/injection_points/expected/basic.out @@ -0,0 +1,75 @@ +Parsed test spec with 2 sessions + +starting permutation: wait1 wakeup2 noop1 detach2 +injection_points_attach +----------------------- + +(1 row) + +step wait1: SELECT injection_points_run('injection-points-wait'); +step wakeup2: SELECT injection_points_wakeup('injection-points-wait'); +injection_points_wakeup +----------------------- + +(1 row) + +step wait1: <... completed> +injection_points_run +-------------------- + +(1 row) + +step noop1: +step detach2: SELECT injection_points_detach('injection-points-wait'); +injection_points_detach +----------------------- + +(1 row) + + +starting permutation: wait1 detach2 wakeup2 +injection_points_attach +----------------------- + +(1 row) + +step wait1: SELECT injection_points_run('injection-points-wait'); +step detach2: SELECT injection_points_detach('injection-points-wait'); +injection_points_detach +----------------------- + +(1 row) + +step wakeup2: SELECT injection_points_wakeup('injection-points-wait'); +injection_points_wakeup +----------------------- + +(1 row) + +step wait1: <... completed> +injection_points_run +-------------------- + +(1 row) + + +starting permutation: detach2 wait1 wakeup2 +injection_points_attach +----------------------- + +(1 row) + +step detach2: SELECT injection_points_detach('injection-points-wait'); +injection_points_detach +----------------------- + +(1 row) + +step wait1: SELECT injection_points_run('injection-points-wait'); +injection_points_run +-------------------- + +(1 row) + +step wakeup2: SELECT injection_points_wakeup('injection-points-wait'); +ERROR: could not find injection point injection-points-wait to wake up diff --git a/src/test/modules/injection_points/expected/hashagg.out b/src/test/modules/injection_points/expected/hashagg.out new file mode 100644 index 0000000000000..cc4247af97d08 --- /dev/null +++ b/src/test/modules/injection_points/expected/hashagg.out @@ -0,0 +1,68 @@ +-- Test for hash aggregation +CREATE EXTENSION injection_points; +SELECT injection_points_set_local(); + injection_points_set_local +---------------------------- + +(1 row) + +SELECT injection_points_attach('hash-aggregate-enter-spill-mode', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +SELECT injection_points_attach('hash-aggregate-process-batch', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +-- force partition fan-out to 1 +SELECT injection_points_attach('hash-aggregate-single-partition', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +-- force spilling after 1000 groups +SELECT injection_points_attach('hash-aggregate-spill-1000', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +CREATE TABLE hashagg_ij(x INTEGER); +INSERT INTO hashagg_ij SELECT g FROM generate_series(1,5100) g; +SET max_parallel_workers=0; +SET max_parallel_workers_per_gather=0; +SET enable_sort=FALSE; +SET work_mem='4MB'; +SELECT COUNT(*) FROM (SELECT DISTINCT x FROM hashagg_ij) s; +NOTICE: notice triggered for injection point hash-aggregate-spill-1000 +NOTICE: notice triggered for injection point hash-aggregate-enter-spill-mode +NOTICE: notice triggered for injection point hash-aggregate-single-partition +NOTICE: notice triggered for injection point hash-aggregate-process-batch +NOTICE: notice triggered for injection point hash-aggregate-spill-1000 +NOTICE: notice triggered for injection point hash-aggregate-enter-spill-mode +NOTICE: notice triggered for injection point hash-aggregate-single-partition +NOTICE: notice triggered for injection point hash-aggregate-process-batch +NOTICE: notice triggered for injection point hash-aggregate-spill-1000 +NOTICE: notice triggered for injection point hash-aggregate-enter-spill-mode +NOTICE: notice triggered for injection point hash-aggregate-single-partition +NOTICE: notice triggered for injection point hash-aggregate-process-batch +NOTICE: notice triggered for injection point hash-aggregate-spill-1000 +NOTICE: notice triggered for injection point hash-aggregate-enter-spill-mode +NOTICE: notice triggered for injection point hash-aggregate-single-partition +NOTICE: notice triggered for injection point hash-aggregate-process-batch +NOTICE: notice triggered for injection point hash-aggregate-spill-1000 +NOTICE: notice triggered for injection point hash-aggregate-enter-spill-mode +NOTICE: notice triggered for injection point hash-aggregate-single-partition +NOTICE: notice triggered for injection point hash-aggregate-process-batch + count +------- + 5100 +(1 row) + +DROP TABLE hashagg_ij; +DROP EXTENSION injection_points; diff --git a/src/test/modules/injection_points/expected/injection_points.out b/src/test/modules/injection_points/expected/injection_points.out index f25bbe4966ee6..43bcdd01582f7 100644 --- a/src/test/modules/injection_points/expected/injection_points.out +++ b/src/test/modules/injection_points/expected/injection_points.out @@ -6,6 +6,19 @@ CREATE FUNCTION wait_pid(int) RETURNS void AS :'regresslib' LANGUAGE C STRICT; +-- Non-strict checks +SELECT injection_points_run(NULL); + injection_points_run +---------------------- + +(1 row) + +SELECT injection_points_cached(NULL); + injection_points_cached +------------------------- + +(1 row) + SELECT injection_points_attach('TestInjectionBooh', 'booh'); ERROR: incorrect action "booh" for injection point creation SELECT injection_points_attach('TestInjectionError', 'error'); @@ -39,6 +52,20 @@ NOTICE: notice triggered for injection point TestInjectionLog2 (1 row) +SELECT injection_points_run('TestInjectionLog2', NULL); -- notice +NOTICE: notice triggered for injection point TestInjectionLog2 + injection_points_run +---------------------- + +(1 row) + +SELECT injection_points_run('TestInjectionLog2', 'foobar'); -- notice + arg +NOTICE: notice triggered for injection point TestInjectionLog2 (foobar) + injection_points_run +---------------------- + +(1 row) + SELECT injection_points_run('TestInjectionLog'); -- notice NOTICE: notice triggered for injection point TestInjectionLog injection_points_run @@ -48,6 +75,10 @@ NOTICE: notice triggered for injection point TestInjectionLog SELECT injection_points_run('TestInjectionError'); -- error ERROR: error triggered for injection point TestInjectionError +SELECT injection_points_run('TestInjectionError', NULL); -- error +ERROR: error triggered for injection point TestInjectionError +SELECT injection_points_run('TestInjectionError', 'foobar2'); -- error + arg +ERROR: error triggered for injection point TestInjectionError (foobar2) -- Re-load cache and run again. \c SELECT injection_points_run('TestInjectionLog2'); -- notice @@ -160,6 +191,20 @@ NOTICE: notice triggered for injection point TestInjectionLogLoad (1 row) +SELECT injection_points_cached('TestInjectionLogLoad', NULL); -- runs from cache +NOTICE: notice triggered for injection point TestInjectionLogLoad + injection_points_cached +------------------------- + +(1 row) + +SELECT injection_points_cached('TestInjectionLogLoad', 'foobar'); -- runs from cache +NOTICE: notice triggered for injection point TestInjectionLogLoad (foobar) + injection_points_cached +------------------------- + +(1 row) + SELECT injection_points_run('TestInjectionLogLoad'); -- runs from cache NOTICE: notice triggered for injection point TestInjectionLogLoad injection_points_run diff --git a/src/test/modules/injection_points/expected/inplace.out b/src/test/modules/injection_points/expected/inplace.out index 123f45a688d9d..db7dab66c92b9 100644 --- a/src/test/modules/injection_points/expected/inplace.out +++ b/src/test/modules/injection_points/expected/inplace.out @@ -40,4 +40,301 @@ step read1: SELECT reltuples = -1 AS reltuples_unknown FROM pg_class WHERE oid = 'vactest.orig50'::regclass; -ERROR: could not create unique index "pg_class_oid_index" +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: begin2 grant2 vac1 c2 vac3 mkrels3 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step c2: COMMIT; +step vac3: VACUUM pg_class; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: begin2 grant2 vac1 r2 vac3 mkrels3 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step r2: ROLLBACK; +step vac3: VACUUM pg_class; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: begin2 grant2 vac1 c2 revoke2 grant2 vac3 mkrels3 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step c2: COMMIT; +step revoke2: REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac3: VACUUM pg_class; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: vac1 begin2 grant2 revoke2 mkrels3 c2 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step revoke2: REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step c2: COMMIT; +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: begin2 grant2 vac1 r2 grant2 revoke2 vac3 mkrels3 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step r2: ROLLBACK; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step revoke2: REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; +step vac3: VACUUM pg_class; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + + +starting permutation: begin2 grant2 vac1 c2 revoke2 vac3 mkrels3 read1 +mkrels +------ + +(1 row) + +injection_points_attach +----------------------- + +(1 row) + +step begin2: BEGIN; +step grant2: GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; +step vac1: VACUUM vactest.orig50; -- wait during inplace update +step c2: COMMIT; +step revoke2: REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; +step vac3: VACUUM pg_class; +step mkrels3: + SELECT vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + SELECT injection_points_detach('inplace-before-pin'); + SELECT injection_points_wakeup('inplace-before-pin'); + +mkrels +------ + +(1 row) + +injection_points_detach +----------------------- + +(1 row) + +injection_points_wakeup +----------------------- + +(1 row) + +step vac1: <... completed> +step read1: + REINDEX TABLE pg_class; -- look for duplicates + SELECT reltuples = -1 AS reltuples_unknown + FROM pg_class WHERE oid = 'vactest.orig50'::regclass; + +reltuples_unknown +----------------- +f +(1 row) + diff --git a/src/test/modules/injection_points/expected/reindex_conc.out b/src/test/modules/injection_points/expected/reindex_conc.out new file mode 100644 index 0000000000000..db8de4bbe85c1 --- /dev/null +++ b/src/test/modules/injection_points/expected/reindex_conc.out @@ -0,0 +1,51 @@ +-- Tests for REINDEX CONCURRENTLY +CREATE EXTENSION injection_points; +-- Check safety of indexes with predicates and expressions. +SELECT injection_points_set_local(); + injection_points_set_local +---------------------------- + +(1 row) + +SELECT injection_points_attach('reindex-conc-index-safe', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +SELECT injection_points_attach('reindex-conc-index-not-safe', 'notice'); + injection_points_attach +------------------------- + +(1 row) + +CREATE SCHEMA reindex_inj; +CREATE TABLE reindex_inj.tbl(i int primary key, updated_at timestamp); +CREATE UNIQUE INDEX ind_simple ON reindex_inj.tbl(i); +CREATE UNIQUE INDEX ind_expr ON reindex_inj.tbl(ABS(i)); +CREATE UNIQUE INDEX ind_pred ON reindex_inj.tbl(i) WHERE mod(i, 2) = 0; +CREATE UNIQUE INDEX ind_expr_pred ON reindex_inj.tbl(abs(i)) WHERE mod(i, 2) = 0; +REINDEX INDEX CONCURRENTLY reindex_inj.ind_simple; +NOTICE: notice triggered for injection point reindex-conc-index-safe +REINDEX INDEX CONCURRENTLY reindex_inj.ind_expr; +NOTICE: notice triggered for injection point reindex-conc-index-not-safe +REINDEX INDEX CONCURRENTLY reindex_inj.ind_pred; +NOTICE: notice triggered for injection point reindex-conc-index-not-safe +REINDEX INDEX CONCURRENTLY reindex_inj.ind_expr_pred; +NOTICE: notice triggered for injection point reindex-conc-index-not-safe +-- Cleanup +SELECT injection_points_detach('reindex-conc-index-safe'); + injection_points_detach +------------------------- + +(1 row) + +SELECT injection_points_detach('reindex-conc-index-not-safe'); + injection_points_detach +------------------------- + +(1 row) + +DROP TABLE reindex_inj.tbl; +DROP SCHEMA reindex_inj; +DROP EXTENSION injection_points; diff --git a/src/test/modules/injection_points/expected/syscache-update-pruned.out b/src/test/modules/injection_points/expected/syscache-update-pruned.out new file mode 100644 index 0000000000000..a6a4e8db996b1 --- /dev/null +++ b/src/test/modules/injection_points/expected/syscache-update-pruned.out @@ -0,0 +1,87 @@ +Parsed test spec with 4 sessions + +starting permutation: cachefill1 at2 waitprunable4 vac4 grant1 wakeinval4 wakegrant4 +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +ERROR: tuple concurrently deleted +step wakegrant4: <... completed> + +starting permutation: cachefill1 at2 waitprunable4 vac4 grant1 wakeinval4 mkrels4 wakegrant4 +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step mkrels4: + SELECT FROM vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +ERROR: duplicate key value violates unique constraint "pg_class_oid_index" +step wakegrant4: <... completed> + +starting permutation: snap3 cachefill1 at2 mkrels4 r3 waitprunable4 vac4 grant1 wakeinval4 at4 wakegrant4 inspect4 +step snap3: BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT; +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step mkrels4: + SELECT FROM vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + +step r3: ROLLBACK; +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step at4: ALTER TABLE vactest.child50 INHERIT vactest.orig50; +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +step wakegrant4: <... completed> +step inspect4: + SELECT relhastriggers, relhassubclass FROM pg_class + WHERE oid = 'vactest.orig50'::regclass; + +relhastriggers|relhassubclass +--------------+-------------- +f |f +(1 row) + diff --git a/src/test/modules/injection_points/expected/syscache-update-pruned_1.out b/src/test/modules/injection_points/expected/syscache-update-pruned_1.out new file mode 100644 index 0000000000000..4dca2b86bc888 --- /dev/null +++ b/src/test/modules/injection_points/expected/syscache-update-pruned_1.out @@ -0,0 +1,86 @@ +Parsed test spec with 4 sessions + +starting permutation: cachefill1 at2 waitprunable4 vac4 grant1 wakeinval4 wakegrant4 +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +step wakegrant4: <... completed> + +starting permutation: cachefill1 at2 waitprunable4 vac4 grant1 wakeinval4 mkrels4 wakegrant4 +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step mkrels4: + SELECT FROM vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +step wakegrant4: <... completed> + +starting permutation: snap3 cachefill1 at2 mkrels4 r3 waitprunable4 vac4 grant1 wakeinval4 at4 wakegrant4 inspect4 +step snap3: BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT; +step cachefill1: SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); +step at2: + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +step mkrels4: + SELECT FROM vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED + +step r3: ROLLBACK; +step waitprunable4: CALL vactest.wait_prunable(); +step vac4: VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; +step grant1: GRANT SELECT ON vactest.orig50 TO PUBLIC; +step wakeinval4: + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); + +step at2: <... completed> +step wakeinval4: <... completed> +step at4: ALTER TABLE vactest.child50 INHERIT vactest.orig50; +step wakegrant4: + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); + +step grant1: <... completed> +ERROR: tuple concurrently updated +step wakegrant4: <... completed> +step inspect4: + SELECT relhastriggers, relhassubclass FROM pg_class + WHERE oid = 'vactest.orig50'::regclass; + +relhastriggers|relhassubclass +--------------+-------------- +t |t +(1 row) + diff --git a/src/test/modules/injection_points/injection_points--1.0.sql b/src/test/modules/injection_points/injection_points--1.0.sql index 0f280419a5581..cc76b1bf99ae6 100644 --- a/src/test/modules/injection_points/injection_points--1.0.sql +++ b/src/test/modules/injection_points/injection_points--1.0.sql @@ -29,20 +29,22 @@ LANGUAGE C STRICT PARALLEL UNSAFE; -- -- Executes the action attached to the injection point. -- -CREATE FUNCTION injection_points_run(IN point_name TEXT) +CREATE FUNCTION injection_points_run(IN point_name TEXT, + IN arg TEXT DEFAULT NULL) RETURNS void AS 'MODULE_PATHNAME', 'injection_points_run' -LANGUAGE C STRICT PARALLEL UNSAFE; +LANGUAGE C PARALLEL UNSAFE; -- -- injection_points_cached() -- -- Executes the action attached to the injection point, from local cache. -- -CREATE FUNCTION injection_points_cached(IN point_name TEXT) +CREATE FUNCTION injection_points_cached(IN point_name TEXT, + IN arg TEXT DEFAULT NULL) RETURNS void AS 'MODULE_PATHNAME', 'injection_points_cached' -LANGUAGE C STRICT PARALLEL UNSAFE; +LANGUAGE C PARALLEL UNSAFE; -- -- injection_points_wakeup() @@ -74,3 +76,44 @@ CREATE FUNCTION injection_points_detach(IN point_name TEXT) RETURNS void AS 'MODULE_PATHNAME', 'injection_points_detach' LANGUAGE C STRICT PARALLEL UNSAFE; + +-- +-- injection_points_stats_numcalls() +-- +-- Reports statistics, if any, related to the given injection point. +-- +CREATE FUNCTION injection_points_stats_numcalls(IN point_name TEXT) +RETURNS bigint +AS 'MODULE_PATHNAME', 'injection_points_stats_numcalls' +LANGUAGE C STRICT; + +-- +-- injection_points_stats_drop() +-- +-- Drop all statistics of injection points. +-- +CREATE FUNCTION injection_points_stats_drop() +RETURNS void +AS 'MODULE_PATHNAME', 'injection_points_stats_drop' +LANGUAGE C STRICT; + +-- +-- injection_points_stats_fixed() +-- +-- Reports fixed-numbered statistics for injection points. +CREATE FUNCTION injection_points_stats_fixed(OUT numattach int8, + OUT numdetach int8, + OUT numrun int8, + OUT numcached int8, + OUT numloaded int8) +RETURNS record +AS 'MODULE_PATHNAME', 'injection_points_stats_fixed' +LANGUAGE C STRICT; + +-- +-- regress_injection.c functions +-- +CREATE FUNCTION removable_cutoff(rel regclass) +RETURNS xid8 +AS 'MODULE_PATHNAME' +LANGUAGE C CALLED ON NULL INPUT; diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c index 15f9d0233c3cf..3da0cbc10e08f 100644 --- a/src/test/modules/injection_points/injection_points.c +++ b/src/test/modules/injection_points/injection_points.c @@ -6,7 +6,7 @@ * Injection points are able to trigger user-defined callbacks in pre-defined * code paths. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -18,6 +18,7 @@ #include "postgres.h" #include "fmgr.h" +#include "injection_stats.h" #include "miscadmin.h" #include "nodes/pg_list.h" #include "nodes/value.h" @@ -27,6 +28,7 @@ #include "storage/lwlock.h" #include "storage/shmem.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/injection_point.h" #include "utils/memutils.h" #include "utils/wait_event.h" @@ -67,7 +69,12 @@ typedef struct InjectionPointCondition */ static List *inj_list_local = NIL; -/* Shared state information for injection points. */ +/* + * Shared state information for injection points. + * + * This state data can be initialized in two ways: dynamically with a DSM + * or when loading the module. + */ typedef struct InjectionPointSharedState { /* Protects access to other fields */ @@ -87,17 +94,34 @@ typedef struct InjectionPointSharedState static InjectionPointSharedState *inj_state = NULL; extern PGDLLEXPORT void injection_error(const char *name, - const void *private_data); + const void *private_data, + void *arg); extern PGDLLEXPORT void injection_notice(const char *name, - const void *private_data); + const void *private_data, + void *arg); extern PGDLLEXPORT void injection_wait(const char *name, - const void *private_data); + const void *private_data, + void *arg); /* track if injection points attached in this process are linked to it */ static bool injection_point_local = false; /* - * Callback for shared memory area initialization. + * GUC variable + * + * This GUC is useful to control if statistics should be enabled or not + * during a test with injection points, like for example if a test relies + * on a callback run in a critical section where no allocation should happen. + */ +bool inj_stats_enabled = false; + +/* Shared memory init callbacks */ +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; + +/* + * Routine for shared memory area initialization, used as a callback + * when initializing dynamically with a DSM or when loading the module. */ static void injection_point_init_state(void *ptr) @@ -110,8 +134,48 @@ injection_point_init_state(void *ptr) ConditionVariableInit(&state->wait_point); } +/* Shared memory initialization when loading module */ +static void +injection_shmem_request(void) +{ + Size size; + + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + size = MAXALIGN(sizeof(InjectionPointSharedState)); + RequestAddinShmemSpace(size); +} + +static void +injection_shmem_startup(void) +{ + bool found; + + if (prev_shmem_startup_hook) + prev_shmem_startup_hook(); + + /* Create or attach to the shared memory state */ + LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); + + inj_state = ShmemInitStruct("injection_points", + sizeof(InjectionPointSharedState), + &found); + + if (!found) + { + /* + * First time through, so initialize. This is shared with the dynamic + * initialization using a DSM. + */ + injection_point_init_state(inj_state); + } + + LWLockRelease(AddinShmemInitLock); +} + /* - * Initialize shared memory area for this module. + * Initialize shared memory area for this module through DSM. */ static void injection_init_shmem(void) @@ -170,35 +234,52 @@ injection_points_cleanup(int code, Datum arg) char *name = strVal(lfirst(lc)); (void) InjectionPointDetach(name); + + /* Remove stats entry */ + pgstat_drop_inj(name); } } /* Set of callbacks available to be attached to an injection point. */ void -injection_error(const char *name, const void *private_data) +injection_error(const char *name, const void *private_data, void *arg) { InjectionPointCondition *condition = (InjectionPointCondition *) private_data; + char *argstr = (char *) arg; if (!injection_point_allowed(condition)) return; - elog(ERROR, "error triggered for injection point %s", name); + pgstat_report_inj(name); + + if (argstr) + elog(ERROR, "error triggered for injection point %s (%s)", + name, argstr); + else + elog(ERROR, "error triggered for injection point %s", name); } void -injection_notice(const char *name, const void *private_data) +injection_notice(const char *name, const void *private_data, void *arg) { InjectionPointCondition *condition = (InjectionPointCondition *) private_data; + char *argstr = (char *) arg; if (!injection_point_allowed(condition)) return; - elog(NOTICE, "notice triggered for injection point %s", name); + pgstat_report_inj(name); + + if (argstr) + elog(NOTICE, "notice triggered for injection point %s (%s)", + name, argstr); + else + elog(NOTICE, "notice triggered for injection point %s", name); } /* Wait on a condition variable, awaken by injection_points_wakeup() */ void -injection_wait(const char *name, const void *private_data) +injection_wait(const char *name, const void *private_data, void *arg) { uint32 old_wait_counts = 0; int index = -1; @@ -211,6 +292,8 @@ injection_wait(const char *name, const void *private_data) if (!injection_point_allowed(condition)) return; + pgstat_report_inj(name); + /* * Use the injection point name for this custom wait event. Note that * this custom wait event name is not released, but we don't care much for @@ -287,6 +370,7 @@ injection_points_attach(PG_FUNCTION_ARGS) condition.pid = MyProcPid; } + pgstat_report_inj_fixed(1, 0, 0, 0, 0); InjectionPointAttach(name, "injection_points", function, &condition, sizeof(InjectionPointCondition)); @@ -299,6 +383,10 @@ injection_points_attach(PG_FUNCTION_ARGS) inj_list_local = lappend(inj_list_local, makeString(pstrdup(name))); MemoryContextSwitchTo(oldctx); } + + /* Add entry for stats */ + pgstat_create_inj(name); + PG_RETURN_VOID(); } @@ -314,6 +402,7 @@ injection_points_load(PG_FUNCTION_ARGS) if (inj_state == NULL) injection_init_shmem(); + pgstat_report_inj_fixed(0, 0, 0, 0, 1); INJECTION_POINT_LOAD(name); PG_RETURN_VOID(); @@ -326,9 +415,18 @@ PG_FUNCTION_INFO_V1(injection_points_run); Datum injection_points_run(PG_FUNCTION_ARGS) { - char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *name; + char *arg = NULL; + + if (PG_ARGISNULL(0)) + PG_RETURN_VOID(); + name = text_to_cstring(PG_GETARG_TEXT_PP(0)); - INJECTION_POINT(name); + if (!PG_ARGISNULL(1)) + arg = text_to_cstring(PG_GETARG_TEXT_PP(1)); + + pgstat_report_inj_fixed(0, 0, 1, 0, 0); + INJECTION_POINT(name, arg); PG_RETURN_VOID(); } @@ -340,9 +438,18 @@ PG_FUNCTION_INFO_V1(injection_points_cached); Datum injection_points_cached(PG_FUNCTION_ARGS) { - char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *name; + char *arg = NULL; + + if (PG_ARGISNULL(0)) + PG_RETURN_VOID(); + name = text_to_cstring(PG_GETARG_TEXT_PP(0)); - INJECTION_POINT_CACHED(name); + if (!PG_ARGISNULL(1)) + arg = text_to_cstring(PG_GETARG_TEXT_PP(1)); + + pgstat_report_inj_fixed(0, 0, 0, 1, 0); + INJECTION_POINT_CACHED(name, arg); PG_RETURN_VOID(); } @@ -418,6 +525,7 @@ injection_points_detach(PG_FUNCTION_ARGS) { char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + pgstat_report_inj_fixed(0, 1, 0, 0, 0); if (!InjectionPointDetach(name)) elog(ERROR, "could not detach injection point \"%s\"", name); @@ -431,5 +539,38 @@ injection_points_detach(PG_FUNCTION_ARGS) MemoryContextSwitchTo(oldctx); } + /* Remove stats entry */ + pgstat_drop_inj(name); + PG_RETURN_VOID(); } + + +void +_PG_init(void) +{ + if (!process_shared_preload_libraries_in_progress) + return; + + DefineCustomBoolVariable("injection_points.stats", + "Enables statistics for injection points.", + NULL, + &inj_stats_enabled, + false, + PGC_POSTMASTER, + 0, + NULL, + NULL, + NULL); + + MarkGUCPrefixReserved("injection_points"); + + /* Shared memory initialization */ + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = injection_shmem_request; + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = injection_shmem_startup; + + pgstat_register_inj(); + pgstat_register_inj_fixed(); +} diff --git a/src/test/modules/injection_points/injection_stats.c b/src/test/modules/injection_points/injection_stats.c new file mode 100644 index 0000000000000..14903c629e0d1 --- /dev/null +++ b/src/test/modules/injection_points/injection_stats.c @@ -0,0 +1,218 @@ +/*-------------------------------------------------------------------------- + * + * injection_stats.c + * Code for statistics of injection points. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/test/modules/injection_points/injection_stats.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" + +#include "common/hashfn.h" +#include "injection_stats.h" +#include "pgstat.h" +#include "utils/builtins.h" +#include "utils/pgstat_internal.h" + +/* Structures for statistics of injection points */ +typedef struct PgStat_StatInjEntry +{ + PgStat_Counter numcalls; /* number of times point has been run */ +} PgStat_StatInjEntry; + +typedef struct PgStatShared_InjectionPoint +{ + PgStatShared_Common header; + PgStat_StatInjEntry stats; +} PgStatShared_InjectionPoint; + +static bool injection_stats_flush_cb(PgStat_EntryRef *entry_ref, bool nowait); + +static const PgStat_KindInfo injection_stats = { + .name = "injection_points", + .fixed_amount = false, /* Bounded by the number of points */ + .write_to_file = true, + + /* Injection points are system-wide */ + .accessed_across_databases = true, + + .shared_size = sizeof(PgStatShared_InjectionPoint), + .shared_data_off = offsetof(PgStatShared_InjectionPoint, stats), + .shared_data_len = sizeof(((PgStatShared_InjectionPoint *) 0)->stats), + .pending_size = sizeof(PgStat_StatInjEntry), + .flush_pending_cb = injection_stats_flush_cb, +}; + +/* + * Compute stats entry idx from point name with an 8-byte hash. + */ +#define PGSTAT_INJ_IDX(name) hash_bytes_extended((const unsigned char *) name, strlen(name), 0) + +/* + * Kind ID reserved for statistics of injection points. + */ +#define PGSTAT_KIND_INJECTION 129 + +/* Track if stats are loaded */ +static bool inj_stats_loaded = false; + +/* + * Callback for stats handling + */ +static bool +injection_stats_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) +{ + PgStat_StatInjEntry *localent; + PgStatShared_InjectionPoint *shfuncent; + + localent = (PgStat_StatInjEntry *) entry_ref->pending; + shfuncent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats; + + if (!pgstat_lock_entry(entry_ref, nowait)) + return false; + + shfuncent->stats.numcalls += localent->numcalls; + + pgstat_unlock_entry(entry_ref); + + return true; +} + +/* + * Support function for the SQL-callable pgstat* functions. Returns + * a pointer to the injection point statistics struct. + */ +static PgStat_StatInjEntry * +pgstat_fetch_stat_injentry(const char *name) +{ + PgStat_StatInjEntry *entry = NULL; + + if (!inj_stats_loaded || !inj_stats_enabled) + return NULL; + + /* Compile the lookup key as a hash of the point name */ + entry = (PgStat_StatInjEntry *) pgstat_fetch_entry(PGSTAT_KIND_INJECTION, + InvalidOid, + PGSTAT_INJ_IDX(name)); + return entry; +} + +/* + * Workhorse to do the registration work, called in _PG_init(). + */ +void +pgstat_register_inj(void) +{ + pgstat_register_kind(PGSTAT_KIND_INJECTION, &injection_stats); + + /* mark stats as loaded */ + inj_stats_loaded = true; +} + +/* + * Report injection point creation. + */ +void +pgstat_create_inj(const char *name) +{ + PgStat_EntryRef *entry_ref; + PgStatShared_InjectionPoint *shstatent; + + /* leave if disabled */ + if (!inj_stats_loaded || !inj_stats_enabled) + return; + + entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INJECTION, InvalidOid, + PGSTAT_INJ_IDX(name), NULL); + + shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats; + + /* initialize shared memory data */ + memset(&shstatent->stats, 0, sizeof(shstatent->stats)); +} + +/* + * Report injection point drop. + */ +void +pgstat_drop_inj(const char *name) +{ + /* leave if disabled */ + if (!inj_stats_loaded || !inj_stats_enabled) + return; + + if (!pgstat_drop_entry(PGSTAT_KIND_INJECTION, InvalidOid, + PGSTAT_INJ_IDX(name))) + pgstat_request_entry_refs_gc(); +} + +/* + * Report statistics for injection point. + * + * This is simple because the set of stats to report currently is simple: + * track the number of times a point has been run. + */ +void +pgstat_report_inj(const char *name) +{ + PgStat_EntryRef *entry_ref; + PgStatShared_InjectionPoint *shstatent; + PgStat_StatInjEntry *statent; + + /* leave if disabled */ + if (!inj_stats_loaded || !inj_stats_enabled) + return; + + entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INJECTION, InvalidOid, + PGSTAT_INJ_IDX(name), NULL); + + shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats; + statent = &shstatent->stats; + + /* Update the injection point statistics */ + statent->numcalls++; +} + +/* + * SQL function returning the number of times an injection point + * has been called. + */ +PG_FUNCTION_INFO_V1(injection_points_stats_numcalls); +Datum +injection_points_stats_numcalls(PG_FUNCTION_ARGS) +{ + char *name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + PgStat_StatInjEntry *entry = pgstat_fetch_stat_injentry(name); + + if (entry == NULL) + PG_RETURN_NULL(); + + PG_RETURN_INT64(entry->numcalls); +} + +/* Only used by injection_points_stats_drop() */ +static bool +match_inj_entries(PgStatShared_HashEntry *entry, Datum match_data) +{ + return entry->key.kind == PGSTAT_KIND_INJECTION; +} + +/* + * SQL function that drops all injection point statistics. + */ +PG_FUNCTION_INFO_V1(injection_points_stats_drop); +Datum +injection_points_stats_drop(PG_FUNCTION_ARGS) +{ + pgstat_drop_matching_entries(match_inj_entries, 0); + + PG_RETURN_VOID(); +} diff --git a/src/test/modules/injection_points/injection_stats.h b/src/test/modules/injection_points/injection_stats.h new file mode 100644 index 0000000000000..ba310c52c7f0c --- /dev/null +++ b/src/test/modules/injection_points/injection_stats.h @@ -0,0 +1,35 @@ +/*-------------------------------------------------------------------------- + * + * injection_stats.h + * Definitions for statistics of injection points. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/test/modules/injection_points/injection_stats.h + * + * ------------------------------------------------------------------------- + */ + +#ifndef INJECTION_STATS +#define INJECTION_STATS + +/* GUC variable */ +extern bool inj_stats_enabled; + +/* injection_stats.c */ +extern void pgstat_register_inj(void); +extern void pgstat_create_inj(const char *name); +extern void pgstat_drop_inj(const char *name); +extern void pgstat_report_inj(const char *name); + +/* injection_stats_fixed.c */ +extern void pgstat_register_inj_fixed(void); +extern void pgstat_report_inj_fixed(uint32 numattach, + uint32 numdetach, + uint32 numrun, + uint32 numcached, + uint32 numloaded); + +#endif diff --git a/src/test/modules/injection_points/injection_stats_fixed.c b/src/test/modules/injection_points/injection_stats_fixed.c new file mode 100644 index 0000000000000..3d0c01bdd05ab --- /dev/null +++ b/src/test/modules/injection_points/injection_stats_fixed.c @@ -0,0 +1,209 @@ +/*-------------------------------------------------------------------------- + * + * injection_stats_fixed.c + * Code for fixed-numbered statistics of injection points. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/test/modules/injection_points/injection_stats_fixed.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" + +#include "common/hashfn.h" +#include "funcapi.h" +#include "injection_stats.h" +#include "pgstat.h" +#include "utils/builtins.h" +#include "utils/pgstat_internal.h" + +/* Structures for statistics of injection points, fixed-size */ +typedef struct PgStat_StatInjFixedEntry +{ + PgStat_Counter numattach; /* number of points attached */ + PgStat_Counter numdetach; /* number of points detached */ + PgStat_Counter numrun; /* number of points run */ + PgStat_Counter numcached; /* number of points cached */ + PgStat_Counter numloaded; /* number of points loaded */ + TimestampTz stat_reset_timestamp; +} PgStat_StatInjFixedEntry; + +typedef struct PgStatShared_InjectionPointFixed +{ + LWLock lock; /* protects all the counters */ + uint32 changecount; + PgStat_StatInjFixedEntry stats; + PgStat_StatInjFixedEntry reset_offset; +} PgStatShared_InjectionPointFixed; + +/* Callbacks for fixed-numbered stats */ +static void injection_stats_fixed_init_shmem_cb(void *stats); +static void injection_stats_fixed_reset_all_cb(TimestampTz ts); +static void injection_stats_fixed_snapshot_cb(void); + +static const PgStat_KindInfo injection_stats_fixed = { + .name = "injection_points_fixed", + .fixed_amount = true, + .write_to_file = true, + + .shared_size = sizeof(PgStat_StatInjFixedEntry), + .shared_data_off = offsetof(PgStatShared_InjectionPointFixed, stats), + .shared_data_len = sizeof(((PgStatShared_InjectionPointFixed *) 0)->stats), + + .init_shmem_cb = injection_stats_fixed_init_shmem_cb, + .reset_all_cb = injection_stats_fixed_reset_all_cb, + .snapshot_cb = injection_stats_fixed_snapshot_cb, +}; + +/* + * Kind ID reserved for statistics of injection points. + */ +#define PGSTAT_KIND_INJECTION_FIXED 130 + +/* Track if fixed-numbered stats are loaded */ +static bool inj_fixed_loaded = false; + +static void +injection_stats_fixed_init_shmem_cb(void *stats) +{ + PgStatShared_InjectionPointFixed *stats_shmem = + (PgStatShared_InjectionPointFixed *) stats; + + LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA); +} + +static void +injection_stats_fixed_reset_all_cb(TimestampTz ts) +{ + PgStatShared_InjectionPointFixed *stats_shmem = + pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); + + LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE); + pgstat_copy_changecounted_stats(&stats_shmem->reset_offset, + &stats_shmem->stats, + sizeof(stats_shmem->stats), + &stats_shmem->changecount); + stats_shmem->stats.stat_reset_timestamp = ts; + LWLockRelease(&stats_shmem->lock); +} + +static void +injection_stats_fixed_snapshot_cb(void) +{ + PgStatShared_InjectionPointFixed *stats_shmem = + pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); + PgStat_StatInjFixedEntry *stat_snap = + pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED); + PgStat_StatInjFixedEntry *reset_offset = &stats_shmem->reset_offset; + PgStat_StatInjFixedEntry reset; + + pgstat_copy_changecounted_stats(stat_snap, + &stats_shmem->stats, + sizeof(stats_shmem->stats), + &stats_shmem->changecount); + + LWLockAcquire(&stats_shmem->lock, LW_SHARED); + memcpy(&reset, reset_offset, sizeof(stats_shmem->stats)); + LWLockRelease(&stats_shmem->lock); + + /* compensate by reset offsets */ +#define FIXED_COMP(fld) stat_snap->fld -= reset.fld; + FIXED_COMP(numattach); + FIXED_COMP(numdetach); + FIXED_COMP(numrun); + FIXED_COMP(numcached); + FIXED_COMP(numloaded); +#undef FIXED_COMP +} + +/* + * Workhorse to do the registration work, called in _PG_init(). + */ +void +pgstat_register_inj_fixed(void) +{ + pgstat_register_kind(PGSTAT_KIND_INJECTION_FIXED, &injection_stats_fixed); + + /* mark stats as loaded */ + inj_fixed_loaded = true; +} + +/* + * Report fixed number of statistics for an injection point. + */ +void +pgstat_report_inj_fixed(uint32 numattach, + uint32 numdetach, + uint32 numrun, + uint32 numcached, + uint32 numloaded) +{ + PgStatShared_InjectionPointFixed *stats_shmem; + + /* leave if disabled */ + if (!inj_fixed_loaded || !inj_stats_enabled) + return; + + stats_shmem = pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); + + pgstat_begin_changecount_write(&stats_shmem->changecount); + stats_shmem->stats.numattach += numattach; + stats_shmem->stats.numdetach += numdetach; + stats_shmem->stats.numrun += numrun; + stats_shmem->stats.numcached += numcached; + stats_shmem->stats.numloaded += numloaded; + pgstat_end_changecount_write(&stats_shmem->changecount); +} + +/* + * SQL function returning fixed-numbered statistics for injection points. + */ +PG_FUNCTION_INFO_V1(injection_points_stats_fixed); +Datum +injection_points_stats_fixed(PG_FUNCTION_ARGS) +{ + TupleDesc tupdesc; + Datum values[5] = {0}; + bool nulls[5] = {0}; + PgStat_StatInjFixedEntry *stats; + + if (!inj_fixed_loaded || !inj_stats_enabled) + PG_RETURN_NULL(); + + pgstat_snapshot_fixed(PGSTAT_KIND_INJECTION_FIXED); + stats = pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED); + + /* Initialise attributes information in the tuple descriptor */ + tupdesc = CreateTemplateTupleDesc(5); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "numattach", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "numdetach", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "numrun", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "numcached", + INT8OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "numloaded", + INT8OID, -1, 0); + BlessTupleDesc(tupdesc); + + values[0] = Int64GetDatum(stats->numattach); + values[1] = Int64GetDatum(stats->numdetach); + values[2] = Int64GetDatum(stats->numrun); + values[3] = Int64GetDatum(stats->numcached); + values[4] = Int64GetDatum(stats->numloaded); + nulls[0] = false; + nulls[1] = false; + nulls[2] = false; + nulls[3] = false; + nulls[4] = false; + + /* Returns the record as Datum */ + PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); +} diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build index 3c23c14d812a5..d61149712fd7d 100644 --- a/src/test/modules/injection_points/meson.build +++ b/src/test/modules/injection_points/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not get_option('injection_points') subdir_done() @@ -6,6 +6,9 @@ endif injection_points_sources = files( 'injection_points.c', + 'injection_stats.c', + 'injection_stats_fixed.c', + 'regress_injection.c', ) if host_system == 'windows' @@ -32,6 +35,8 @@ tests += { 'regress': { 'sql': [ 'injection_points', + 'hashagg', + 'reindex_conc', ], 'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'], # The injection points are cluster-wide, so disable installcheck @@ -39,7 +44,18 @@ tests += { }, 'isolation': { 'specs': [ + 'basic', 'inplace', + 'syscache-update-pruned', + ], + 'runningcheck': false, # see syscache-update-pruned + }, + 'tap': { + 'env': { + 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', + }, + 'tests': [ + 't/001_stats.pl', ], }, } diff --git a/src/test/modules/injection_points/regress_injection.c b/src/test/modules/injection_points/regress_injection.c new file mode 100644 index 0000000000000..7bba1c97d0f26 --- /dev/null +++ b/src/test/modules/injection_points/regress_injection.c @@ -0,0 +1,78 @@ +/*-------------------------------------------------------------------------- + * + * regress_injection.c + * Functions supporting test-specific subject matter. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/test/modules/injection_points/regress_injection.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/table.h" +#include "fmgr.h" +#include "miscadmin.h" +#include "postmaster/autovacuum.h" +#include "storage/procarray.h" +#include "utils/rel.h" +#include "utils/xid8.h" + +/* + * removable_cutoff - for syscache-update-pruned.spec + * + * Wrapper around GetOldestNonRemovableTransactionId(). In general, this can + * move backward. runningcheck=false isolation tests can reasonably prevent + * that. For the causes of backward movement, see + * postgr.es/m/CAEze2Wj%2BV0kTx86xB_YbyaqTr5hnE_igdWAwuhSyjXBYscf5-Q%40mail.gmail.com + * and the header comment for ComputeXidHorizons(). One can assume this + * doesn't move backward if one (a) passes a shared catalog as the argument + * and (b) arranges for concurrent activity not to reach AbortTransaction(). + * Non-runningcheck tests can control most concurrent activity, except + * autovacuum and the isolationtester control connection. AbortTransaction() + * in those would justify test failure. Seeing autoanalyze can allocate an + * XID in any database, (a) ensures we'll consistently not ignore those XIDs. + */ +PG_FUNCTION_INFO_V1(removable_cutoff); +Datum +removable_cutoff(PG_FUNCTION_ARGS) +{ + Relation rel = NULL; + TransactionId xid; + FullTransactionId next_fxid_before, + next_fxid; + + /* could take other relkinds callee takes, but we've not yet needed it */ + if (!PG_ARGISNULL(0)) + rel = table_open(PG_GETARG_OID(0), AccessShareLock); + + if (!rel->rd_rel->relisshared && autovacuum_start_daemon) + elog(WARNING, + "removable_cutoff(non-shared-rel) can move backward under autovacuum=on"); + + /* + * No lock or snapshot necessarily prevents oldestXid from advancing past + * "xid" while this function runs. That concerns us only in that we must + * not ascribe "xid" to the wrong epoch. (That may never arise in + * isolation testing, but let's set a good example.) As a crude solution, + * retry until nextXid doesn't change. + */ + next_fxid = ReadNextFullTransactionId(); + do + { + CHECK_FOR_INTERRUPTS(); + next_fxid_before = next_fxid; + xid = GetOldestNonRemovableTransactionId(rel); + next_fxid = ReadNextFullTransactionId(); + } while (!FullTransactionIdEquals(next_fxid, next_fxid_before)); + + if (rel) + table_close(rel, AccessShareLock); + + PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromAllowableAt(next_fxid, + xid)); +} diff --git a/src/test/modules/injection_points/specs/basic.spec b/src/test/modules/injection_points/specs/basic.spec new file mode 100644 index 0000000000000..13d2793f6e4cc --- /dev/null +++ b/src/test/modules/injection_points/specs/basic.spec @@ -0,0 +1,39 @@ +# Basic isolation test for injection points. +# +# This checks the interactions between wakeup, wait and detach. +# Feel free to use it as a template when implementing an isolation +# test with injection points. + +setup +{ + CREATE EXTENSION injection_points; +} +teardown +{ + DROP EXTENSION injection_points; +} + +# Wait happens in the first session, wakeup in the second session. +session s1 +setup { + SELECT injection_points_set_local(); + SELECT injection_points_attach('injection-points-wait', 'wait'); +} +step wait1 { SELECT injection_points_run('injection-points-wait'); } +step noop1 { } + +session s2 +step wakeup2 { SELECT injection_points_wakeup('injection-points-wait'); } +step detach2 { SELECT injection_points_detach('injection-points-wait'); } + +# Detach after wait and wakeup. Note that the detach may finish before +# the SQL function doing the wait returns its result. In order to avoid +# any ordering issues, a no-op step is added after the wait, so as the +# detach is not launched until the wait has completed. +permutation wait1 wakeup2 noop1 detach2 + +# Detach before wakeup. s1 waits until wakeup, ignores the detach. +permutation wait1 detach2 wakeup2 + +# Detach before wait does not cause a wait, wakeup produces an error. +permutation detach2 wait1 wakeup2 diff --git a/src/test/modules/injection_points/specs/inplace.spec b/src/test/modules/injection_points/specs/inplace.spec index e9577137512e9..86539a5bd2f11 100644 --- a/src/test/modules/injection_points/specs/inplace.spec +++ b/src/test/modules/injection_points/specs/inplace.spec @@ -32,12 +32,9 @@ setup CREATE TABLE vactest.orig50 (); SELECT vactest.mkrels('orig', 51, 100); } - -# XXX DROP causes an assertion failure; adopt DROP once fixed teardown { - --DROP SCHEMA vactest CASCADE; - DO $$BEGIN EXECUTE 'ALTER SCHEMA vactest RENAME TO schema' || oid FROM pg_namespace where nspname = 'vactest'; END$$; + DROP SCHEMA vactest CASCADE; DROP EXTENSION injection_points; } @@ -56,11 +53,13 @@ step read1 { FROM pg_class WHERE oid = 'vactest.orig50'::regclass; } - # Transactional updates of the tuple vac1 is waiting to inplace-update. session s2 step grant2 { GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; } - +step revoke2 { REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; } +step begin2 { BEGIN; } +step c2 { COMMIT; } +step r2 { ROLLBACK; } # Non-blocking actions. session s3 @@ -74,10 +73,69 @@ step mkrels3 { } -# XXX extant bug +# target gains a successor at the last moment permutation vac1(mkrels3) # reads pg_class tuple T0 for vactest.orig50, xmax invalid grant2 # T0 becomes eligible for pruning, T1 is successor vac3 # T0 becomes LP_UNUSED - mkrels3 # T0 reused; vac1 wakes and overwrites the reused T0 + mkrels3 # vac1 wakes, scans to T1 + read1 + +# target already has a successor, which commits +permutation + begin2 + grant2 # T0.t_ctid = T1 + vac1(mkrels3) # reads T0 for vactest.orig50 + c2 # T0 becomes eligible for pruning + vac3 # T0 becomes LP_UNUSED + mkrels3 # vac1 wakes, scans to T1 + read1 + +# target already has a successor, which becomes LP_UNUSED at the last moment +permutation + begin2 + grant2 # T0.t_ctid = T1 + vac1(mkrels3) # reads T0 for vactest.orig50 + r2 # T1 becomes eligible for pruning + vac3 # T1 becomes LP_UNUSED + mkrels3 # reuse T1; vac1 scans to T0 read1 + +# target already has a successor, which becomes LP_REDIRECT at the last moment +permutation + begin2 + grant2 # T0.t_ctid = T1, non-HOT due to filled page + vac1(mkrels3) # reads T0 + c2 + revoke2 # HOT update to T2 + grant2 # HOT update to T3 + vac3 # T1 becomes LP_REDIRECT + mkrels3 # reuse T2; vac1 scans to T3 + read1 + +# waiting for updater to end +permutation + vac1(c2) # reads pg_class tuple T0 for vactest.orig50, xmax invalid + begin2 + grant2 # T0.t_ctid = T1, non-HOT due to filled page + revoke2 # HOT update to T2 + mkrels3 # vac1 awakes briefly, then waits for s2 + c2 + read1 + +# Another LP_UNUSED. This time, do change the live tuple. Final live tuple +# body is identical to original, at a different TID. +permutation + begin2 + grant2 # T0.t_ctid = T1, non-HOT due to filled page + vac1(mkrels3) # reads T0 + r2 # T1 becomes eligible for pruning + grant2 # T0.t_ctid = T2; T0 becomes eligible for pruning + revoke2 # T2.t_ctid = T3; T2 becomes eligible for pruning + vac3 # T0, T1 & T2 become LP_UNUSED + mkrels3 # reuse T0, T1 & T2; vac1 scans to T3 + read1 + +# Another LP_REDIRECT. Compared to the earlier test, omit the last grant2. +# Hence, final live tuple body is identical to original, at a different TID. +permutation begin2 grant2 vac1(mkrels3) c2 revoke2 vac3 mkrels3 read1 diff --git a/src/test/modules/injection_points/specs/syscache-update-pruned.spec b/src/test/modules/injection_points/specs/syscache-update-pruned.spec new file mode 100644 index 0000000000000..e3a4295bd12e8 --- /dev/null +++ b/src/test/modules/injection_points/specs/syscache-update-pruned.spec @@ -0,0 +1,197 @@ +# Test race conditions involving: +# - s1: heap_update($FROM_SYSCACHE), without a snapshot or pin +# - s2: ALTER TABLE making $FROM_SYSCACHE a dead tuple +# - s3: "VACUUM pg_class" making $FROM_SYSCACHE become LP_UNUSED + +# This is a derivative work of inplace.spec, which exercises the corresponding +# race condition for inplace updates. + +# Despite local injection points, this is incompatible with runningcheck. +# First, removable_cutoff() could move backward, per its header comment. +# Second, other activity could trigger sinval queue overflow, negating our +# efforts to delay inval. Third, this deadlock emerges: +# +# - step at2 waits at an injection point, with interrupts held +# - an unrelated backend waits for at2 to do PROCSIGNAL_BARRIER_SMGRRELEASE +# - step waitprunable4 waits for the unrelated backend to release its xmin + +# The alternative expected output is for -DCATCACHE_FORCE_RELEASE, a setting +# that thwarts testing the race conditions this spec seeks. + + +# Need s2 to make a non-HOT update. Otherwise, "VACUUM pg_class" would leave +# an LP_REDIRECT that persists. To get non-HOT, make rels so the pg_class row +# for vactest.orig50 is on a filled page (assuming BLCKSZ=8192). Just to save +# on filesystem syscalls, use relkind=c for every other rel. +setup +{ + CREATE EXTENSION injection_points; + CREATE SCHEMA vactest; + -- Ensure a leader RELOID catcache entry. PARALLEL RESTRICTED since a + -- parallel worker running pg_relation_filenode() would lack that effect. + CREATE FUNCTION vactest.reloid_catcache_set(regclass) RETURNS int + LANGUAGE sql PARALLEL RESTRICTED + AS 'SELECT 0 FROM pg_relation_filenode($1)'; + CREATE FUNCTION vactest.mkrels(text, int, int) RETURNS void + LANGUAGE plpgsql SET search_path = vactest AS $$ + DECLARE + tname text; + BEGIN + FOR i in $2 .. $3 LOOP + tname := $1 || i; + EXECUTE FORMAT('CREATE TYPE ' || tname || ' AS ()'); + RAISE DEBUG '% at %', tname, ctid + FROM pg_class WHERE oid = tname::regclass; + END LOOP; + END + $$; + CREATE PROCEDURE vactest.wait_prunable() LANGUAGE plpgsql AS $$ + DECLARE + barrier xid8; + cutoff xid8; + BEGIN + barrier := pg_current_xact_id(); + -- autovacuum worker RelationCacheInitializePhase3() or the + -- isolationtester control connection might hold a snapshot that + -- limits pruning. Sleep until that clears. See comments at + -- removable_cutoff() for why we pass a shared catalog rather than + -- pg_class, the table we'll prune. + LOOP + ROLLBACK; -- release MyProc->xmin, which could be the oldest + cutoff := removable_cutoff('pg_database'); + EXIT WHEN cutoff >= barrier; + RAISE LOG 'removable cutoff %; waiting for %', cutoff, barrier; + PERFORM pg_sleep(.1); + END LOOP; + END + $$; +} +# Eliminate HEAPTUPLE_DEAD and HEAPTUPLE_RECENTLY_DEAD from pg_class. +# Minimize free space. +# +# If we kept HEAPTUPLE_RECENTLY_DEAD, step vac4 could prune what we missed, +# breaking some permutation assumptions. Specifically, the next pg_class +# tuple could end up in free space we failed to liberate here, instead of +# going in the specific free space vac4 intended to liberate for it. +setup { CALL vactest.wait_prunable(); -- maximize VACUUM FULL } +setup { VACUUM FULL pg_class; -- reduce free space } +# Remove the one tuple that VACUUM FULL makes dead, a tuple pertaining to +# pg_class itself. Populate the FSM for pg_class. +# +# wait_prunable waits for snapshots that would thwart pruning, while FREEZE +# waits for buffer pins that would thwart pruning. DISABLE_PAGE_SKIPPING +# isn't actually needed, but other pruning-dependent tests use it. If those +# tests remove it, remove it here. +setup { CALL vactest.wait_prunable(); -- maximize lazy VACUUM } +setup { VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; -- fill fsm etc. } +setup +{ + SELECT FROM vactest.mkrels('orig', 1, 49); + CREATE TABLE vactest.orig50 (c int) WITH (autovacuum_enabled = off); + CREATE TABLE vactest.child50 (c int) WITH (autovacuum_enabled = off); + SELECT FROM vactest.mkrels('orig', 51, 100); +} +teardown +{ + DROP SCHEMA vactest CASCADE; + DROP EXTENSION injection_points; +} + +# Wait during GRANT. Disable debug_discard_caches, since we're here to +# exercise an outcome that happens under permissible cache staleness. +session s1 +setup { + SET debug_discard_caches = 0; + SELECT FROM injection_points_set_local(); + SELECT FROM injection_points_attach('heap_update-before-pin', 'wait'); +} +step cachefill1 { SELECT FROM vactest.reloid_catcache_set('vactest.orig50'); } +step grant1 { GRANT SELECT ON vactest.orig50 TO PUBLIC; } + +# Update of the tuple that grant1 will update. Wait before sending invals, so +# s1 will not get a cache miss. Choose the commands for making such updates +# from among those whose heavyweight locking does not conflict with GRANT's +# heavyweight locking. (GRANT will see our XID as committed, so observing +# that XID in the tuple xmax also won't block GRANT.) +session s2 +setup { + SELECT FROM injection_points_set_local(); + SELECT FROM + injection_points_attach('transaction-end-process-inval', 'wait'); +} +step at2 { + CREATE TRIGGER to_set_relhastriggers BEFORE UPDATE ON vactest.orig50 + FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); +} + +# Hold snapshot to block pruning. +session s3 +step snap3 { BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT; } +step r3 { ROLLBACK; } + +# Non-blocking actions. +session s4 +step waitprunable4 { CALL vactest.wait_prunable(); } +# Eliminate HEAPTUPLE_DEAD. See above discussion of FREEZE. +step vac4 { VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) pg_class; } +# Reuse the lp that s1 is waiting to change. I've observed reuse at the 1st +# or 18th CREATE, so create excess. +step mkrels4 { + SELECT FROM vactest.mkrels('intruder', 1, 100); -- repopulate LP_UNUSED +} +step wakegrant4 { + SELECT FROM injection_points_detach('heap_update-before-pin'); + SELECT FROM injection_points_wakeup('heap_update-before-pin'); +} +step at4 { ALTER TABLE vactest.child50 INHERIT vactest.orig50; } +step wakeinval4 { + SELECT FROM injection_points_detach('transaction-end-process-inval'); + SELECT FROM injection_points_wakeup('transaction-end-process-inval'); +} +# Witness effects of steps at2 and/or at4. +step inspect4 { + SELECT relhastriggers, relhassubclass FROM pg_class + WHERE oid = 'vactest.orig50'::regclass; +} + +# TID from syscache becomes LP_UNUSED. Before the bug fix, this permutation +# made s1 fail with "attempted to update invisible tuple" or an assert. +# However, suppose a pd_lsn value such that (pd_lsn.xlogid, pd_lsn.xrecoff) +# passed for (xmin, xmax) with xmin known-committed and xmax known-aborted. +# Persistent page header corruption ensued. For example, s1 overwrote +# pd_lower, pd_upper, and pd_special as though they were t_ctid. +permutation + cachefill1 # reads pg_class tuple T0, xmax invalid + at2 # T0 dead, T1 live + waitprunable4 # T0 prunable + vac4 # T0 becomes LP_UNUSED + grant1 # pauses at heap_update(T0) + wakeinval4(at2) # at2 sends inval message + wakegrant4(grant1) # s1 wakes: "tuple concurrently deleted" + +# add mkrels4: LP_UNUSED becomes a different rel's row +permutation + cachefill1 # reads pg_class tuple T0, xmax invalid + at2 # T0 dead, T1 live + waitprunable4 # T0 prunable + vac4 # T0 becomes LP_UNUSED + grant1 # pauses at heap_update(T0) + wakeinval4(at2) # at2 sends inval message + mkrels4 # T0 becomes a new rel + wakegrant4(grant1) # s1 wakes: "duplicate key value violates unique" + +# TID from syscache becomes LP_UNUSED, then becomes a newer version of the +# original rel's row. +permutation + snap3 # sets MyProc->xmin + cachefill1 # reads pg_class tuple T0, xmax invalid + at2 # T0 dead, T1 live + mkrels4 # T1's page becomes full + r3 # clears MyProc->xmin + waitprunable4 # T0 prunable + vac4 # T0 becomes LP_UNUSED + grant1 # pauses at heap_update(T0) + wakeinval4(at2) # at2 sends inval message + at4 # T1 dead, T0 live + wakegrant4(grant1) # s1 wakes: T0 dead, T2 live + inspect4 # observe loss of at2+at4 changes XXX is an extant bug diff --git a/src/test/modules/injection_points/sql/hashagg.sql b/src/test/modules/injection_points/sql/hashagg.sql new file mode 100644 index 0000000000000..51d814623fcb3 --- /dev/null +++ b/src/test/modules/injection_points/sql/hashagg.sql @@ -0,0 +1,26 @@ +-- Test for hash aggregation +CREATE EXTENSION injection_points; + +SELECT injection_points_set_local(); + +SELECT injection_points_attach('hash-aggregate-enter-spill-mode', 'notice'); +SELECT injection_points_attach('hash-aggregate-process-batch', 'notice'); + +-- force partition fan-out to 1 +SELECT injection_points_attach('hash-aggregate-single-partition', 'notice'); + +-- force spilling after 1000 groups +SELECT injection_points_attach('hash-aggregate-spill-1000', 'notice'); + +CREATE TABLE hashagg_ij(x INTEGER); +INSERT INTO hashagg_ij SELECT g FROM generate_series(1,5100) g; + +SET max_parallel_workers=0; +SET max_parallel_workers_per_gather=0; +SET enable_sort=FALSE; +SET work_mem='4MB'; + +SELECT COUNT(*) FROM (SELECT DISTINCT x FROM hashagg_ij) s; + +DROP TABLE hashagg_ij; +DROP EXTENSION injection_points; diff --git a/src/test/modules/injection_points/sql/injection_points.sql b/src/test/modules/injection_points/sql/injection_points.sql index e3a481d604492..d9748331c7715 100644 --- a/src/test/modules/injection_points/sql/injection_points.sql +++ b/src/test/modules/injection_points/sql/injection_points.sql @@ -9,6 +9,10 @@ CREATE FUNCTION wait_pid(int) AS :'regresslib' LANGUAGE C STRICT; +-- Non-strict checks +SELECT injection_points_run(NULL); +SELECT injection_points_cached(NULL); + SELECT injection_points_attach('TestInjectionBooh', 'booh'); SELECT injection_points_attach('TestInjectionError', 'error'); SELECT injection_points_attach('TestInjectionLog', 'notice'); @@ -16,8 +20,12 @@ SELECT injection_points_attach('TestInjectionLog2', 'notice'); SELECT injection_points_run('TestInjectionBooh'); -- nothing SELECT injection_points_run('TestInjectionLog2'); -- notice +SELECT injection_points_run('TestInjectionLog2', NULL); -- notice +SELECT injection_points_run('TestInjectionLog2', 'foobar'); -- notice + arg SELECT injection_points_run('TestInjectionLog'); -- notice SELECT injection_points_run('TestInjectionError'); -- error +SELECT injection_points_run('TestInjectionError', NULL); -- error +SELECT injection_points_run('TestInjectionError', 'foobar2'); -- error + arg -- Re-load cache and run again. \c @@ -47,6 +55,8 @@ SELECT injection_points_load('TestInjectionLogLoad'); -- nothing SELECT injection_points_attach('TestInjectionLogLoad', 'notice'); SELECT injection_points_load('TestInjectionLogLoad'); -- nothing happens SELECT injection_points_cached('TestInjectionLogLoad'); -- runs from cache +SELECT injection_points_cached('TestInjectionLogLoad', NULL); -- runs from cache +SELECT injection_points_cached('TestInjectionLogLoad', 'foobar'); -- runs from cache SELECT injection_points_run('TestInjectionLogLoad'); -- runs from cache SELECT injection_points_detach('TestInjectionLogLoad'); diff --git a/src/test/modules/injection_points/sql/reindex_conc.sql b/src/test/modules/injection_points/sql/reindex_conc.sql new file mode 100644 index 0000000000000..6cf211e6d5dd0 --- /dev/null +++ b/src/test/modules/injection_points/sql/reindex_conc.sql @@ -0,0 +1,28 @@ +-- Tests for REINDEX CONCURRENTLY +CREATE EXTENSION injection_points; + +-- Check safety of indexes with predicates and expressions. +SELECT injection_points_set_local(); +SELECT injection_points_attach('reindex-conc-index-safe', 'notice'); +SELECT injection_points_attach('reindex-conc-index-not-safe', 'notice'); + +CREATE SCHEMA reindex_inj; +CREATE TABLE reindex_inj.tbl(i int primary key, updated_at timestamp); + +CREATE UNIQUE INDEX ind_simple ON reindex_inj.tbl(i); +CREATE UNIQUE INDEX ind_expr ON reindex_inj.tbl(ABS(i)); +CREATE UNIQUE INDEX ind_pred ON reindex_inj.tbl(i) WHERE mod(i, 2) = 0; +CREATE UNIQUE INDEX ind_expr_pred ON reindex_inj.tbl(abs(i)) WHERE mod(i, 2) = 0; + +REINDEX INDEX CONCURRENTLY reindex_inj.ind_simple; +REINDEX INDEX CONCURRENTLY reindex_inj.ind_expr; +REINDEX INDEX CONCURRENTLY reindex_inj.ind_pred; +REINDEX INDEX CONCURRENTLY reindex_inj.ind_expr_pred; + +-- Cleanup +SELECT injection_points_detach('reindex-conc-index-safe'); +SELECT injection_points_detach('reindex-conc-index-not-safe'); +DROP TABLE reindex_inj.tbl; +DROP SCHEMA reindex_inj; + +DROP EXTENSION injection_points; diff --git a/src/test/modules/injection_points/t/001_stats.pl b/src/test/modules/injection_points/t/001_stats.pl new file mode 100644 index 0000000000000..25de5fc46fe4a --- /dev/null +++ b/src/test/modules/injection_points/t/001_stats.pl @@ -0,0 +1,91 @@ + +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# Tests for Custom Cumulative Statistics. + +use strict; +use warnings FATAL => 'all'; +use locale; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Test persistency of statistics generated for injection points. +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +# Node initialization +my $node = PostgreSQL::Test::Cluster->new('master'); +$node->init; +$node->append_conf( + 'postgresql.conf', qq( +shared_preload_libraries = 'injection_points' +injection_points.stats = true +)); +$node->start; +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); + +# This should count for two calls. +$node->safe_psql('postgres', + "SELECT injection_points_attach('stats-notice', 'notice');"); +$node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');"); +$node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');"); +my $numcalls = $node->safe_psql('postgres', + "SELECT injection_points_stats_numcalls('stats-notice');"); +is($numcalls, '2', 'number of stats calls'); +my $fixedstats = $node->safe_psql('postgres', + "SELECT * FROM injection_points_stats_fixed();"); +is($fixedstats, '1|0|2|0|0', 'fixed stats after some calls'); + +# Loading and caching. +$node->safe_psql( + 'postgres', " +SELECT injection_points_load('stats-notice'); +SELECT injection_points_cached('stats-notice'); +"); +$fixedstats = $node->safe_psql('postgres', + "SELECT * FROM injection_points_stats_fixed();"); +is($fixedstats, '1|0|2|1|1', 'fixed stats after loading and caching'); + +# Restart the node cleanly, stats should still be around. +$node->restart; +$numcalls = $node->safe_psql('postgres', + "SELECT injection_points_stats_numcalls('stats-notice');"); +is($numcalls, '3', 'number of stats after clean restart'); +$fixedstats = $node->safe_psql('postgres', + "SELECT * FROM injection_points_stats_fixed();"); +is($fixedstats, '1|0|2|1|1', 'fixed stats after clean restart'); + +# On crash the stats are gone. +$node->stop('immediate'); +$node->start; +$numcalls = $node->safe_psql('postgres', + "SELECT injection_points_stats_numcalls('stats-notice');"); +is($numcalls, '', 'number of stats after crash'); +$fixedstats = $node->safe_psql('postgres', + "SELECT * FROM injection_points_stats_fixed();"); +is($fixedstats, '0|0|0|0|0', 'fixed stats after crash'); + +# On drop all stats are gone +$node->safe_psql('postgres', + "SELECT injection_points_attach('stats-notice', 'notice');"); +$node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');"); +$node->safe_psql('postgres', "SELECT injection_points_run('stats-notice');"); +$numcalls = $node->safe_psql('postgres', + "SELECT injection_points_stats_numcalls('stats-notice');"); +is($numcalls, '2', 'number of stats calls'); +$node->safe_psql('postgres', "SELECT injection_points_stats_drop();"); +$numcalls = $node->safe_psql('postgres', + "SELECT injection_points_stats_numcalls('stats-notice');"); +is($numcalls, '', 'no stats after drop via SQL function'); + +# Stop the server, disable the module, then restart. The server +# should be able to come up. +$node->stop; +$node->adjust_conf('postgresql.conf', 'shared_preload_libraries', "''"); +$node->start; + +done_testing(); diff --git a/src/test/modules/ldap_password_func/Makefile b/src/test/modules/ldap_password_func/Makefile index 5bd50f0b4864a..bb080135454dc 100644 --- a/src/test/modules/ldap_password_func/Makefile +++ b/src/test/modules/ldap_password_func/Makefile @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # ldap_password_func Makefile diff --git a/src/test/modules/ldap_password_func/ldap_password_func.c b/src/test/modules/ldap_password_func/ldap_password_func.c index 99c18a8f1c89a..79c023bfc68c9 100644 --- a/src/test/modules/ldap_password_func/ldap_password_func.c +++ b/src/test/modules/ldap_password_func/ldap_password_func.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * ldap_password_func.c * @@ -15,15 +15,12 @@ #include #include +#include "fmgr.h" #include "libpq/auth.h" -#include "libpq/libpq.h" -#include "libpq/libpq-be.h" -#include "utils/guc.h" PG_MODULE_MAGIC; void _PG_init(void); -void _PG_fini(void); /* hook function */ static char *rot13_passphrase(char *password); @@ -37,12 +34,6 @@ _PG_init(void) ldap_password_hook = rot13_passphrase; } -void -_PG_fini(void) -{ - /* do nothing yet */ -} - static char * rot13_passphrase(char *pw) { diff --git a/src/test/modules/ldap_password_func/t/001_mutated_bindpasswd.pl b/src/test/modules/ldap_password_func/t/001_mutated_bindpasswd.pl index 82b1cb88e9f06..5dc1e442d299f 100644 --- a/src/test/modules/ldap_password_func/t/001_mutated_bindpasswd.pl +++ b/src/test/modules/ldap_password_func/t/001_mutated_bindpasswd.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -42,7 +42,8 @@ my $node = PostgreSQL::Test::Cluster->new('node'); $node->init; -$node->append_conf('postgresql.conf', "log_connections = on\n"); +$node->append_conf('postgresql.conf', + "log_connections = 'receipt,authentication,authorization'\n"); $node->append_conf('postgresql.conf', "shared_preload_libraries = 'ldap_password_func'"); $node->start; diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c index 999a7f57a7efc..9a3c0236325c6 100644 --- a/src/test/modules/libpq_pipeline/libpq_pipeline.c +++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c @@ -3,7 +3,7 @@ * libpq_pipeline.c * Verify libpq pipeline execution functionality * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -19,14 +19,12 @@ #include #include "catalog/pg_type_d.h" -#include "common/fe_memutils.h" #include "libpq-fe.h" #include "pg_getopt.h" -#include "portability/instr_time.h" static void exit_nicely(PGconn *conn); -static void pg_attribute_noreturn() pg_fatal_impl(int line, const char *fmt,...) +pg_noreturn static void pg_fatal_impl(int line, const char *fmt,...) pg_attribute_printf(2, 3); static bool process_result(PGconn *conn, PGresult *res, int results, int numsent); @@ -73,8 +71,7 @@ exit_nicely(PGconn *conn) * Print an error to stderr and terminate the program. */ #define pg_fatal(...) pg_fatal_impl(__LINE__, __VA_ARGS__) -static void -pg_attribute_noreturn() +pg_noreturn static void pg_fatal_impl(int line, const char *fmt,...) { va_list args; @@ -209,15 +206,17 @@ copy_connection(PGconn *conn) PQconninfoOption *opts = PQconninfo(conn); const char **keywords; const char **vals; - int nopts = 1; - int i = 0; + int nopts = 0; + int i; for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt) nopts++; + nopts++; /* for the NULL terminator */ keywords = pg_malloc(sizeof(char *) * nopts); vals = pg_malloc(sizeof(char *) * nopts); + i = 0; for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt) { if (opt->val) @@ -1408,6 +1407,110 @@ test_prepared(PGconn *conn) fprintf(stderr, "ok\n"); } +/* + * Test max_protocol_version options. + */ +static void +test_protocol_version(PGconn *conn) +{ + const char **keywords; + const char **vals; + int nopts; + PQconninfoOption *opts = PQconninfo(conn); + int protocol_version; + int max_protocol_version_index; + int i; + + /* + * Prepare keywords/vals arrays, copied from the existing connection, with + * an extra slot for 'max_protocol_version'. + */ + nopts = 0; + for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt) + nopts++; + nopts++; /* max_protocol_version */ + nopts++; /* NULL terminator */ + + keywords = pg_malloc0(sizeof(char *) * nopts); + vals = pg_malloc0(sizeof(char *) * nopts); + + i = 0; + for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt) + { + if (opt->val) + { + keywords[i] = opt->keyword; + vals[i] = opt->val; + i++; + } + } + + max_protocol_version_index = i; + keywords[i] = "max_protocol_version"; /* value is filled in below */ + i++; + keywords[i] = vals[i] = NULL; + + /* + * Test max_protocol_version=3.0 + */ + vals[max_protocol_version_index] = "3.0"; + conn = PQconnectdbParams(keywords, vals, false); + + if (PQstatus(conn) != CONNECTION_OK) + pg_fatal("Connection to database failed: %s", + PQerrorMessage(conn)); + + protocol_version = PQfullProtocolVersion(conn); + if (protocol_version != 30000) + pg_fatal("expected 30000, got %d", protocol_version); + + PQfinish(conn); + + /* + * Test max_protocol_version=3.1. It's not valid, we went straight from + * 3.0 to 3.2. + */ + vals[max_protocol_version_index] = "3.1"; + conn = PQconnectdbParams(keywords, vals, false); + + if (PQstatus(conn) != CONNECTION_BAD) + pg_fatal("Connecting with max_protocol_version 3.1 should have failed."); + + PQfinish(conn); + + /* + * Test max_protocol_version=3.2 + */ + vals[max_protocol_version_index] = "3.2"; + conn = PQconnectdbParams(keywords, vals, false); + + if (PQstatus(conn) != CONNECTION_OK) + pg_fatal("Connection to database failed: %s", + PQerrorMessage(conn)); + + protocol_version = PQfullProtocolVersion(conn); + if (protocol_version != 30002) + pg_fatal("expected 30002, got %d", protocol_version); + + PQfinish(conn); + + /* + * Test max_protocol_version=latest. 'latest' currently means '3.2'. + */ + vals[max_protocol_version_index] = "latest"; + conn = PQconnectdbParams(keywords, vals, false); + + if (PQstatus(conn) != CONNECTION_OK) + pg_fatal("Connection to database failed: %s", + PQerrorMessage(conn)); + + protocol_version = PQfullProtocolVersion(conn); + if (protocol_version != 30002) + pg_fatal("expected 30002, got %d", protocol_version); + + PQfinish(conn); +} + /* Notice processor: print notices, and count how many we got */ static void notice_processor(void *arg, const char *message) @@ -2156,6 +2259,7 @@ print_test_list(void) printf("pipeline_idle\n"); printf("pipelined_insert\n"); printf("prepared\n"); + printf("protocol_version\n"); printf("simple_pipeline\n"); printf("singlerow\n"); printf("transaction\n"); @@ -2266,6 +2370,8 @@ main(int argc, char **argv) test_pipelined_insert(conn, numrows); else if (strcmp(testname, "prepared") == 0) test_prepared(conn); + else if (strcmp(testname, "protocol_version") == 0) + test_protocol_version(conn); else if (strcmp(testname, "simple_pipeline") == 0) test_simple_pipeline(conn); else if (strcmp(testname, "singlerow") == 0) diff --git a/src/test/modules/libpq_pipeline/meson.build b/src/test/modules/libpq_pipeline/meson.build index 727963ee68674..3fd70a04a38d9 100644 --- a/src/test/modules/libpq_pipeline/meson.build +++ b/src/test/modules/libpq_pipeline/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group libpq_pipeline_sources = files( 'libpq_pipeline.c', @@ -27,5 +27,6 @@ tests += { 'tests': [ 't/001_libpq_pipeline.pl', ], + 'deps': [libpq_pipeline], }, } diff --git a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl index f9e6d07fc0b94..61524bdbd8f28 100644 --- a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl +++ b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -35,7 +35,7 @@ BEGIN for my $testname (@tests) { - my @extraargs = ('-r', $numrows); + my @extraargs = ('-r' => $numrows); my $cmptrace = grep(/^$testname$/, qw(simple_pipeline nosync multi_pipelines prepared singlerow pipeline_abort pipeline_idle transaction @@ -46,14 +46,14 @@ BEGIN "$PostgreSQL::Test::Utils::tmp_check/traces/$testname.trace"; if ($cmptrace) { - push @extraargs, "-t", $traceout; + push @extraargs, "-t" => $traceout; } - # Execute the test + # Execute the test using the latest protocol version. $node->command_ok( [ 'libpq_pipeline', @extraargs, - $testname, $node->connstr('postgres') + $testname, $node->connstr('postgres') . " max_protocol_version=latest" ], "libpq_pipeline $testname"); @@ -72,6 +72,14 @@ BEGIN } } +# There were changes to query cancellation in protocol version 3.2, so +# test separately that it still works the old protocol version too. +$node->command_ok( + [ + 'libpq_pipeline', 'cancel', $node->connstr('postgres') . " max_protocol_version=3.0" + ], + "libpq_pipeline cancel with protocol 3.0"); + $node->stop('fast'); done_testing(); diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build index d8fe059d23610..9de0057bd1d43 100644 --- a/src/test/modules/meson.build +++ b/src/test/modules/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group subdir('brin') subdir('commit_ts') @@ -9,15 +9,18 @@ subdir('gin') subdir('injection_points') subdir('ldap_password_func') subdir('libpq_pipeline') +subdir('oauth_validator') subdir('plsample') subdir('spgist_name_ops') subdir('ssl_passphrase_callback') +subdir('test_aio') subdir('test_bloomfilter') subdir('test_copy_callbacks') subdir('test_custom_rmgrs') subdir('test_ddl_deparse') subdir('test_dsa') subdir('test_dsm_registry') +subdir('test_escape') subdir('test_extensions') subdir('test_ginpostinglist') subdir('test_integerset') @@ -36,6 +39,7 @@ subdir('test_rls_hooks') subdir('test_shm_mq') subdir('test_slru') subdir('test_tidstore') +subdir('typcache') subdir('unsafe_tests') subdir('worker_spi') subdir('xid_wraparound') diff --git a/src/test/modules/oauth_validator/.gitignore b/src/test/modules/oauth_validator/.gitignore new file mode 100644 index 0000000000000..8f18bcd2e1c99 --- /dev/null +++ b/src/test/modules/oauth_validator/.gitignore @@ -0,0 +1,5 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ +/oauth_hook_client diff --git a/src/test/modules/oauth_validator/Makefile b/src/test/modules/oauth_validator/Makefile new file mode 100644 index 0000000000000..05b9f06ed7387 --- /dev/null +++ b/src/test/modules/oauth_validator/Makefile @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/test/modules/oauth_validator +# +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/test/modules/oauth_validator/Makefile +# +#------------------------------------------------------------------------- + +MODULES = validator fail_validator magic_validator +PGFILEDESC = "validator - test OAuth validator module" + +PROGRAM = oauth_hook_client +PGAPPICON = win32 +OBJS = $(WIN32RES) oauth_hook_client.o + +PG_CPPFLAGS = -I$(libpq_srcdir) +PG_LIBS_INTERNAL += $(libpq_pgport) + +NO_INSTALLCHECK = 1 + +TAP_TESTS = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/oauth_validator +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk + +export PYTHON +export with_libcurl +export with_python + +endif diff --git a/src/test/modules/oauth_validator/README b/src/test/modules/oauth_validator/README new file mode 100644 index 0000000000000..54eac5b117e09 --- /dev/null +++ b/src/test/modules/oauth_validator/README @@ -0,0 +1,13 @@ +Test programs and libraries for OAuth +------------------------------------- + +This folder contains tests for the client- and server-side OAuth +implementations. Most tests are run end-to-end to test both simultaneously. The +tests in t/001_server use a mock OAuth authorization server, implemented jointly +by t/OAuth/Server.pm and t/oauth_server.py, to run the libpq Device +Authorization flow. The tests in t/002_client exercise custom OAuth flows and +don't need an authorization server. + +Tests in this folder require 'oauth' to be present in PG_TEST_EXTRA, since +HTTPS servers listening on localhost with TCP/IP sockets will be started. A +Python installation is required to run the mock authorization server. diff --git a/src/test/modules/oauth_validator/fail_validator.c b/src/test/modules/oauth_validator/fail_validator.c new file mode 100644 index 0000000000000..bf04182a48612 --- /dev/null +++ b/src/test/modules/oauth_validator/fail_validator.c @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * fail_validator.c + * Test module for serverside OAuth token validation callbacks, which is + * guaranteed to always fail in the validation callback + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/test/modules/oauth_validator/fail_validator.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "libpq/oauth.h" + +PG_MODULE_MAGIC; + +static bool fail_token(const ValidatorModuleState *state, + const char *token, + const char *role, + ValidatorModuleResult *res); + +/* Callback implementations (we only need the main one) */ +static const OAuthValidatorCallbacks validator_callbacks = { + PG_OAUTH_VALIDATOR_MAGIC, + + .validate_cb = fail_token, +}; + +const OAuthValidatorCallbacks * +_PG_oauth_validator_module_init(void) +{ + return &validator_callbacks; +} + +static bool +fail_token(const ValidatorModuleState *state, + const char *token, const char *role, + ValidatorModuleResult *res) +{ + elog(FATAL, "fail_validator: sentinel error"); + pg_unreachable(); +} diff --git a/src/test/modules/oauth_validator/magic_validator.c b/src/test/modules/oauth_validator/magic_validator.c new file mode 100644 index 0000000000000..e0547caf22f3c --- /dev/null +++ b/src/test/modules/oauth_validator/magic_validator.c @@ -0,0 +1,48 @@ +/*------------------------------------------------------------------------- + * + * magic_validator.c + * Test module for serverside OAuth token validation callbacks, which + * should fail due to using the wrong PG_OAUTH_VALIDATOR_MAGIC marker + * and thus the wrong ABI version + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/test/modules/oauth_validator/magic_validator.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "libpq/oauth.h" + +PG_MODULE_MAGIC; + +static bool validate_token(const ValidatorModuleState *state, + const char *token, + const char *role, + ValidatorModuleResult *res); + +/* Callback implementations (we only need the main one) */ +static const OAuthValidatorCallbacks validator_callbacks = { + 0xdeadbeef, + + .validate_cb = validate_token, +}; + +const OAuthValidatorCallbacks * +_PG_oauth_validator_module_init(void) +{ + return &validator_callbacks; +} + +static bool +validate_token(const ValidatorModuleState *state, + const char *token, const char *role, + ValidatorModuleResult *res) +{ + elog(FATAL, "magic_validator: this should be unreachable"); + pg_unreachable(); +} diff --git a/src/test/modules/oauth_validator/meson.build b/src/test/modules/oauth_validator/meson.build new file mode 100644 index 0000000000000..e190f9cf15a4a --- /dev/null +++ b/src/test/modules/oauth_validator/meson.build @@ -0,0 +1,85 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +validator_sources = files( + 'validator.c', +) + +if host_system == 'windows' + validator_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'validator', + '--FILEDESC', 'validator - test OAuth validator module',]) +endif + +validator = shared_module('validator', + validator_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += validator + +fail_validator_sources = files( + 'fail_validator.c', +) + +if host_system == 'windows' + fail_validator_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'fail_validator', + '--FILEDESC', 'fail_validator - failing OAuth validator module',]) +endif + +fail_validator = shared_module('fail_validator', + fail_validator_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += fail_validator + +magic_validator_sources = files( + 'magic_validator.c', +) + +if host_system == 'windows' + magic_validator_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'magic_validator', + '--FILEDESC', 'magic_validator - ABI incompatible OAuth validator module',]) +endif + +magic_validator = shared_module('magic_validator', + magic_validator_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += magic_validator + +oauth_hook_client_sources = files( + 'oauth_hook_client.c', +) + +if host_system == 'windows' + oauth_hook_client_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'oauth_hook_client', + '--FILEDESC', 'oauth_hook_client - test program for libpq OAuth hooks',]) +endif + +oauth_hook_client = executable('oauth_hook_client', + oauth_hook_client_sources, + dependencies: [frontend_code, libpq], + kwargs: default_bin_args + { + 'install': false, + }, +) +testprep_targets += oauth_hook_client + +tests += { + 'name': 'oauth_validator', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_server.pl', + 't/002_client.pl', + ], + 'env': { + 'PYTHON': python.path(), + 'with_libcurl': oauth_flow_supported ? 'yes' : 'no', + 'with_python': 'yes', + }, + }, +} diff --git a/src/test/modules/oauth_validator/oauth_hook_client.c b/src/test/modules/oauth_validator/oauth_hook_client.c new file mode 100644 index 0000000000000..15d0cf938a824 --- /dev/null +++ b/src/test/modules/oauth_validator/oauth_hook_client.c @@ -0,0 +1,293 @@ +/*------------------------------------------------------------------------- + * + * oauth_hook_client.c + * Test driver for t/002_client.pl, which verifies OAuth hook + * functionality in libpq. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/test/modules/oauth_validator/oauth_hook_client.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres_fe.h" + +#include + +#include "getopt_long.h" +#include "libpq-fe.h" + +static int handle_auth_data(PGauthData type, PGconn *conn, void *data); +static PostgresPollingStatusType async_cb(PGconn *conn, + PGoauthBearerRequest *req, + pgsocket *altsock); +static PostgresPollingStatusType misbehave_cb(PGconn *conn, + PGoauthBearerRequest *req, + pgsocket *altsock); + +static void +usage(char *argv[]) +{ + printf("usage: %s [flags] CONNINFO\n\n", argv[0]); + + printf("recognized flags:\n"); + printf(" -h, --help show this message\n"); + printf(" --expected-scope SCOPE fail if received scopes do not match SCOPE\n"); + printf(" --expected-uri URI fail if received configuration link does not match URI\n"); + printf(" --misbehave=MODE have the hook fail required postconditions\n" + " (MODEs: no-hook, fail-async, no-token, no-socket)\n"); + printf(" --no-hook don't install OAuth hooks\n"); + printf(" --hang-forever don't ever return a token (combine with connect_timeout)\n"); + printf(" --token TOKEN use the provided TOKEN value\n"); + printf(" --stress-async busy-loop on PQconnectPoll rather than polling\n"); +} + +/* --options */ +static bool no_hook = false; +static bool hang_forever = false; +static bool stress_async = false; +static const char *expected_uri = NULL; +static const char *expected_scope = NULL; +static const char *misbehave_mode = NULL; +static char *token = NULL; + +int +main(int argc, char *argv[]) +{ + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + + {"expected-scope", required_argument, NULL, 1000}, + {"expected-uri", required_argument, NULL, 1001}, + {"no-hook", no_argument, NULL, 1002}, + {"token", required_argument, NULL, 1003}, + {"hang-forever", no_argument, NULL, 1004}, + {"misbehave", required_argument, NULL, 1005}, + {"stress-async", no_argument, NULL, 1006}, + {0} + }; + + const char *conninfo; + PGconn *conn; + int c; + + while ((c = getopt_long(argc, argv, "h", long_options, NULL)) != -1) + { + switch (c) + { + case 'h': + usage(argv); + return 0; + + case 1000: /* --expected-scope */ + expected_scope = optarg; + break; + + case 1001: /* --expected-uri */ + expected_uri = optarg; + break; + + case 1002: /* --no-hook */ + no_hook = true; + break; + + case 1003: /* --token */ + token = optarg; + break; + + case 1004: /* --hang-forever */ + hang_forever = true; + break; + + case 1005: /* --misbehave */ + misbehave_mode = optarg; + break; + + case 1006: /* --stress-async */ + stress_async = true; + break; + + default: + usage(argv); + return 1; + } + } + + if (argc != optind + 1) + { + usage(argv); + return 1; + } + + conninfo = argv[optind]; + + /* Set up our OAuth hooks. */ + PQsetAuthDataHook(handle_auth_data); + + /* Connect. (All the actual work is in the hook.) */ + if (stress_async) + { + /* + * Perform an asynchronous connection, busy-looping on PQconnectPoll() + * without actually waiting on socket events. This stresses code paths + * that rely on asynchronous work to be done before continuing with + * the next step in the flow. + */ + PostgresPollingStatusType res; + + conn = PQconnectStart(conninfo); + + do + { + res = PQconnectPoll(conn); + } while (res != PGRES_POLLING_FAILED && res != PGRES_POLLING_OK); + } + else + { + /* Perform a standard synchronous connection. */ + conn = PQconnectdb(conninfo); + } + + if (PQstatus(conn) != CONNECTION_OK) + { + fprintf(stderr, "connection to database failed: %s\n", + PQerrorMessage(conn)); + PQfinish(conn); + return 1; + } + + printf("connection succeeded\n"); + PQfinish(conn); + return 0; +} + +/* + * PQauthDataHook implementation. Replaces the default client flow by handling + * PQAUTHDATA_OAUTH_BEARER_TOKEN. + */ +static int +handle_auth_data(PGauthData type, PGconn *conn, void *data) +{ + PGoauthBearerRequest *req = data; + + if (no_hook || (type != PQAUTHDATA_OAUTH_BEARER_TOKEN)) + return 0; + + if (hang_forever) + { + /* Start asynchronous processing. */ + req->async = async_cb; + return 1; + } + + if (misbehave_mode) + { + if (strcmp(misbehave_mode, "no-hook") != 0) + req->async = misbehave_cb; + return 1; + } + + if (expected_uri) + { + if (!req->openid_configuration) + { + fprintf(stderr, "expected URI \"%s\", got NULL\n", expected_uri); + return -1; + } + + if (strcmp(expected_uri, req->openid_configuration) != 0) + { + fprintf(stderr, "expected URI \"%s\", got \"%s\"\n", expected_uri, req->openid_configuration); + return -1; + } + } + + if (expected_scope) + { + if (!req->scope) + { + fprintf(stderr, "expected scope \"%s\", got NULL\n", expected_scope); + return -1; + } + + if (strcmp(expected_scope, req->scope) != 0) + { + fprintf(stderr, "expected scope \"%s\", got \"%s\"\n", expected_scope, req->scope); + return -1; + } + } + + req->token = token; + return 1; +} + +static PostgresPollingStatusType +async_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock) +{ + if (hang_forever) + { + /* + * This code tests that nothing is interfering with libpq's handling + * of connect_timeout. + */ + static pgsocket sock = PGINVALID_SOCKET; + + if (sock == PGINVALID_SOCKET) + { + /* First call. Create an unbound socket to wait on. */ +#ifdef WIN32 + WSADATA wsaData; + int err; + + err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err) + { + perror("WSAStartup failed"); + return PGRES_POLLING_FAILED; + } +#endif + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == PGINVALID_SOCKET) + { + perror("failed to create datagram socket"); + return PGRES_POLLING_FAILED; + } + } + + /* Make libpq wait on the (unreadable) socket. */ + *altsock = sock; + return PGRES_POLLING_READING; + } + + req->token = token; + return PGRES_POLLING_OK; +} + +static PostgresPollingStatusType +misbehave_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock) +{ + if (strcmp(misbehave_mode, "fail-async") == 0) + { + /* Just fail "normally". */ + return PGRES_POLLING_FAILED; + } + else if (strcmp(misbehave_mode, "no-token") == 0) + { + /* Callbacks must assign req->token before returning OK. */ + return PGRES_POLLING_OK; + } + else if (strcmp(misbehave_mode, "no-socket") == 0) + { + /* Callbacks must assign *altsock before asking for polling. */ + return PGRES_POLLING_READING; + } + else + { + fprintf(stderr, "unrecognized --misbehave mode: %s\n", misbehave_mode); + exit(1); + } +} diff --git a/src/test/modules/oauth_validator/t/001_server.pl b/src/test/modules/oauth_validator/t/001_server.pl new file mode 100644 index 0000000000000..41672ebd5c6dc --- /dev/null +++ b/src/test/modules/oauth_validator/t/001_server.pl @@ -0,0 +1,618 @@ + +# +# Tests the libpq builtin OAuth flow, as well as server-side HBA and validator +# setup. +# +# Copyright (c) 2021-2025, PostgreSQL Global Development Group +# + +use strict; +use warnings FATAL => 'all'; + +use JSON::PP qw(encode_json); +use MIME::Base64 qw(encode_base64); +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +use FindBin; +use lib $FindBin::RealBin; + +use OAuth::Server; + +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\boauth\b/) +{ + plan skip_all => + 'Potentially unsafe test oauth not enabled in PG_TEST_EXTRA'; +} + +unless (check_pg_config("#define HAVE_SYS_EVENT_H 1") + or check_pg_config("#define HAVE_SYS_EPOLL_H 1")) +{ + plan skip_all => + 'OAuth server-side tests are not supported on this platform'; +} + +if ($ENV{with_libcurl} ne 'yes') +{ + plan skip_all => 'client-side OAuth not supported by this build'; +} + +if ($ENV{with_python} ne 'yes') +{ + plan skip_all => 'OAuth tests require --with-python to run'; +} + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; +$node->append_conf('postgresql.conf', "log_connections = all\n"); +$node->append_conf('postgresql.conf', + "oauth_validator_libraries = 'validator'\n"); +# Needed to allow connect_fails to inspect postmaster log: +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); +$node->start; + +$node->safe_psql('postgres', 'CREATE USER test;'); +$node->safe_psql('postgres', 'CREATE USER testalt;'); +$node->safe_psql('postgres', 'CREATE USER testparam;'); + +# Save a background connection for later configuration changes. +my $bgconn = $node->background_psql('postgres'); + +my $webserver = OAuth::Server->new(); +$webserver->run(); + +END +{ + my $exit_code = $?; + + $webserver->stop() if defined $webserver; # might have been SKIP'd + + $? = $exit_code; +} + +my $port = $webserver->port(); +my $issuer = "http://127.0.0.1:$port"; + +unlink($node->data_dir . '/pg_hba.conf'); +$node->append_conf( + 'pg_hba.conf', qq{ +local all test oauth issuer="$issuer" scope="openid postgres" +local all testalt oauth issuer="$issuer/.well-known/oauth-authorization-server/alternate" scope="openid postgres alt" +local all testparam oauth issuer="$issuer/param" scope="openid postgres" +}); +$node->reload; + +my $log_start = $node->wait_for_log(qr/reloading configuration files/); + +# Check pg_hba_file_rules() support. +my $contents = $bgconn->query_safe( + qq(SELECT rule_number, auth_method, options + FROM pg_hba_file_rules + ORDER BY rule_number;)); +is( $contents, + qq{1|oauth|\{issuer=$issuer,"scope=openid postgres",validator=validator\} +2|oauth|\{issuer=$issuer/.well-known/oauth-authorization-server/alternate,"scope=openid postgres alt",validator=validator\} +3|oauth|\{issuer=$issuer/param,"scope=openid postgres",validator=validator\}}, + "pg_hba_file_rules recreates OAuth HBA settings"); + +# To test against HTTP rather than HTTPS, we need to enable PGOAUTHDEBUG. But +# first, check to make sure the client refuses such connections by default. +$node->connect_fails( + "user=test dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0635", + "HTTPS is required without debug mode", + expected_stderr => + qr@OAuth discovery URI "\Q$issuer\E/.well-known/openid-configuration" must use HTTPS@ +); + +$ENV{PGOAUTHDEBUG} = "UNSAFE"; + +my $user = "test"; +$node->connect_ok( + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0635", + "connect as test", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@, + log_like => [ + qr/oauth_validator: token="9243959234", role="$user"/, + qr/oauth_validator: issuer="\Q$issuer\E", scope="openid postgres"/, + qr/connection authenticated: identity="test" method=oauth/, + qr/connection authorized/, + ]); + +# The /alternate issuer uses slightly different parameters, along with an +# OAuth-style discovery document. +$user = "testalt"; +$node->connect_ok( + "user=$user dbname=postgres oauth_issuer=$issuer/alternate oauth_client_id=f02c6361-0636", + "connect as testalt", + expected_stderr => + qr@Visit https://example\.org/ and enter the code: postgresuser@, + log_like => [ + qr/oauth_validator: token="9243959234-alt", role="$user"/, + qr|oauth_validator: issuer="\Q$issuer/.well-known/oauth-authorization-server/alternate\E", scope="openid postgres alt"|, + qr/connection authenticated: identity="testalt" method=oauth/, + qr/connection authorized/, + ]); + +# The issuer linked by the server must match the client's oauth_issuer setting. +$node->connect_fails( + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0636", + "oauth_issuer must match discovery", + expected_stderr => + qr@server's discovery document at \Q$issuer/.well-known/oauth-authorization-server/alternate\E \(issuer "\Q$issuer/alternate\E"\) is incompatible with oauth_issuer \(\Q$issuer\E\)@ +); + +# Test require_auth settings against OAUTHBEARER. +my @cases = ( + { require_auth => "oauth" }, + { require_auth => "oauth,scram-sha-256" }, + { require_auth => "password,oauth" }, + { require_auth => "none,oauth" }, + { require_auth => "!scram-sha-256" }, + { require_auth => "!none" }, + + { + require_auth => "!oauth", + failure => qr/server requested OAUTHBEARER authentication/ + }, + { + require_auth => "scram-sha-256", + failure => qr/server requested OAUTHBEARER authentication/ + }, + { + require_auth => "!password,!oauth", + failure => qr/server requested OAUTHBEARER authentication/ + }, + { + require_auth => "none", + failure => qr/server requested SASL authentication/ + }, + { + require_auth => "!oauth,!scram-sha-256", + failure => qr/server requested SASL authentication/ + }); + +$user = "test"; +foreach my $c (@cases) +{ + my $connstr = + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0635 require_auth=$c->{'require_auth'}"; + + if (defined $c->{'failure'}) + { + $node->connect_fails( + $connstr, + "require_auth=$c->{'require_auth'} fails", + expected_stderr => $c->{'failure'}); + } + else + { + $node->connect_ok( + $connstr, + "require_auth=$c->{'require_auth'} succeeds", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@ + ); + } +} + +# Make sure the client_id and secret are correctly encoded. $vschars contains +# every allowed character for a client_id/_secret (the "VSCHAR" class). +# $vschars_esc is additionally backslash-escaped for inclusion in a +# single-quoted connection string. +my $vschars = + " !\"#\$%&'()*+,-./0123456789:;<=>?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; +my $vschars_esc = + " !\"#\$%&\\'()*+,-./0123456789:;<=>?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + +$node->connect_ok( + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id='$vschars_esc'", + "escapable characters: client_id", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id='$vschars_esc' oauth_client_secret='$vschars_esc'", + "escapable characters: client_id and secret", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +# +# Further tests rely on support for specific behaviors in oauth_server.py. To +# trigger these behaviors, we ask for the special issuer .../param (which is set +# up in HBA for the testparam user) and encode magic instructions into the +# oauth_client_id. +# + +my $common_connstr = + "user=testparam dbname=postgres oauth_issuer=$issuer/param "; +my $base_connstr = $common_connstr; + +sub connstr +{ + my (%params) = @_; + + my $json = encode_json(\%params); + my $encoded = encode_base64($json, ""); + + return "$base_connstr oauth_client_id=$encoded"; +} + +# Make sure the param system works end-to-end first. +$node->connect_ok( + connstr(), + "connect to /param", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$node->connect_ok( + connstr(stage => 'token', retries => 1), + "token retry", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + connstr(stage => 'token', retries => 2), + "token retry (twice)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + connstr(stage => 'all', retries => 1, interval => 2), + "token retry (two second interval)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + connstr(stage => 'all', retries => 1, interval => JSON::PP::null), + "token retry (default interval)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$node->connect_ok( + connstr(stage => 'all', content_type => 'application/json;charset=utf-8'), + "content type with charset", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + connstr( + stage => 'all', + content_type => "application/json \t;\t charset=utf-8"), + "content type with charset (whitespace)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_ok( + connstr(stage => 'device', uri_spelling => "verification_url"), + "alternative spelling of verification_uri", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$node->connect_fails( + connstr(stage => 'device', huge_response => JSON::PP::true), + "bad device authz response: overlarge JSON", + expected_stderr => + qr/failed to obtain device authorization: response is too large/); +$node->connect_fails( + connstr(stage => 'token', huge_response => JSON::PP::true), + "bad token response: overlarge JSON", + expected_stderr => + qr/failed to obtain access token: response is too large/); + +my $nesting_limit = 16; +$node->connect_ok( + connstr( + stage => 'device', + nested_array => $nesting_limit, + nested_object => $nesting_limit), + "nested arrays and objects, up to parse limit", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_fails( + connstr(stage => 'device', nested_array => $nesting_limit + 1), + "bad discovery response: overly nested JSON array", + expected_stderr => + qr/failed to parse device authorization: JSON is too deeply nested/); +$node->connect_fails( + connstr(stage => 'device', nested_object => $nesting_limit + 1), + "bad discovery response: overly nested JSON object", + expected_stderr => + qr/failed to parse device authorization: JSON is too deeply nested/); + +$node->connect_fails( + connstr(stage => 'device', content_type => 'text/plain'), + "bad device authz response: wrong content type", + expected_stderr => + qr/failed to parse device authorization: unexpected content type/); +$node->connect_fails( + connstr(stage => 'token', content_type => 'text/plain'), + "bad token response: wrong content type", + expected_stderr => + qr/failed to parse access token response: unexpected content type/); +$node->connect_fails( + connstr(stage => 'token', content_type => 'application/jsonx'), + "bad token response: wrong content type (correct prefix)", + expected_stderr => + qr/failed to parse access token response: unexpected content type/); + +$node->connect_fails( + connstr( + stage => 'all', + interval => ~0, + retries => 1, + retry_code => "slow_down"), + "bad token response: server overflows the device authz interval", + expected_stderr => + qr/failed to obtain access token: slow_down interval overflow/); + +$node->connect_fails( + connstr(stage => 'token', error_code => "invalid_grant"), + "bad token response: invalid_grant, no description", + expected_stderr => qr/failed to obtain access token: \(invalid_grant\)/); +$node->connect_fails( + connstr( + stage => 'token', + error_code => "invalid_grant", + error_desc => "grant expired"), + "bad token response: expired grant", + expected_stderr => + qr/failed to obtain access token: grant expired \(invalid_grant\)/); +$node->connect_fails( + connstr( + stage => 'token', + error_code => "invalid_client", + error_status => 401), + "bad token response: client authentication failure, default description", + expected_stderr => + qr/failed to obtain access token: provider requires client authentication, and no oauth_client_secret is set \(invalid_client\)/ +); +$node->connect_fails( + connstr( + stage => 'token', + error_code => "invalid_client", + error_status => 401, + error_desc => "authn failure"), + "bad token response: client authentication failure, provided description", + expected_stderr => + qr/failed to obtain access token: authn failure \(invalid_client\)/); + +$node->connect_fails( + connstr(stage => 'token', token => ""), + "server rejects access: empty token", + expected_stderr => qr/bearer authentication failed/); +$node->connect_fails( + connstr(stage => 'token', token => "****"), + "server rejects access: invalid token contents", + expected_stderr => qr/bearer authentication failed/); + +# Test behavior of the oauth_client_secret. +$base_connstr = "$common_connstr oauth_client_secret=''"; + +$node->connect_ok( + connstr(stage => 'all', expected_secret => ''), + "empty oauth_client_secret", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$base_connstr = "$common_connstr oauth_client_secret='$vschars_esc'"; + +$node->connect_ok( + connstr(stage => 'all', expected_secret => $vschars), + "nonempty oauth_client_secret", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$node->connect_fails( + connstr( + stage => 'token', + error_code => "invalid_client", + error_status => 401), + "bad token response: client authentication failure, default description with oauth_client_secret", + expected_stderr => + qr/failed to obtain access token: provider rejected the oauth_client_secret \(invalid_client\)/ +); +$node->connect_fails( + connstr( + stage => 'token', + error_code => "invalid_client", + error_status => 401, + error_desc => "mutual TLS required for client"), + "bad token response: client authentication failure, provided description with oauth_client_secret", + expected_stderr => + qr/failed to obtain access token: mutual TLS required for client \(invalid_client\)/ +); + +# Stress test: make sure our builtin flow operates correctly even if the client +# application isn't respecting PGRES_POLLING_READING/WRITING signals returned +# from PQconnectPoll(). +$base_connstr = + "$common_connstr port=" . $node->port . " host=" . $node->host; +my @cmd = ( + "oauth_hook_client", "--no-hook", "--stress-async", + connstr(stage => 'all', retries => 1, interval => 1)); + +note "running '" . join("' '", @cmd) . "'"; +my ($stdout, $stderr) = run_command(\@cmd); + +like($stdout, qr/connection succeeded/, "stress-async: stdout matches"); +unlike( + $stderr, + qr/connection to database failed/, + "stress-async: stderr matches"); + +# +# This section of tests reconfigures the validator module itself, rather than +# the OAuth server. +# + +# Searching the logs is easier if OAuth parameter discovery isn't cluttering +# things up; hardcode the discovery URI. (Scope is hardcoded to empty to cover +# that case as well.) +$common_connstr = + "dbname=postgres oauth_issuer=$issuer/.well-known/openid-configuration oauth_scope='' oauth_client_id=f02c6361-0635"; + +# Misbehaving validators must fail shut. +$bgconn->query_safe("ALTER SYSTEM SET oauth_validator.authn_id TO ''"); +$node->reload; +$log_start = + $node->wait_for_log(qr/reloading configuration files/, $log_start); + +$node->connect_fails( + "$common_connstr user=test", + "validator must set authn_id", + expected_stderr => qr/OAuth bearer authentication failed/, + log_like => [ + qr/connection authenticated: identity=""/, + qr/DETAIL:\s+Validator provided no identity/, + qr/FATAL:\s+OAuth bearer authentication failed/, + ]); + +# Even if a validator authenticates the user, if the token isn't considered +# valid, the connection fails. +$bgconn->query_safe( + "ALTER SYSTEM SET oauth_validator.authn_id TO 'test\@example.org'"); +$bgconn->query_safe( + "ALTER SYSTEM SET oauth_validator.authorize_tokens TO false"); +$node->reload; +$log_start = + $node->wait_for_log(qr/reloading configuration files/, $log_start); + +$node->connect_fails( + "$common_connstr user=test", + "validator must authorize token explicitly", + expected_stderr => qr/OAuth bearer authentication failed/, + log_like => [ + qr/connection authenticated: identity="test\@example\.org"/, + qr/DETAIL:\s+Validator failed to authorize the provided token/, + qr/FATAL:\s+OAuth bearer authentication failed/, + ]); + +# +# Test user mapping. +# + +# Allow "user@example.com" to log in under the test role. +unlink($node->data_dir . '/pg_ident.conf'); +$node->append_conf( + 'pg_ident.conf', qq{ +oauthmap user\@example.com test +}); + +# test and testalt use the map; testparam uses ident delegation. +unlink($node->data_dir . '/pg_hba.conf'); +$node->append_conf( + 'pg_hba.conf', qq{ +local all test oauth issuer="$issuer" scope="" map=oauthmap +local all testalt oauth issuer="$issuer" scope="" map=oauthmap +local all testparam oauth issuer="$issuer" scope="" delegate_ident_mapping=1 +}); + +# To start, have the validator use the role names as authn IDs. +$bgconn->query_safe("ALTER SYSTEM RESET oauth_validator.authn_id"); +$bgconn->query_safe("ALTER SYSTEM RESET oauth_validator.authorize_tokens"); + +$node->reload; +$log_start = + $node->wait_for_log(qr/reloading configuration files/, $log_start); + +# The test and testalt roles should no longer map correctly. +$node->connect_fails( + "$common_connstr user=test", + "mismatched username map (test)", + expected_stderr => qr/OAuth bearer authentication failed/); +$node->connect_fails( + "$common_connstr user=testalt", + "mismatched username map (testalt)", + expected_stderr => qr/OAuth bearer authentication failed/); + +# Have the validator identify the end user as user@example.com. +$bgconn->query_safe( + "ALTER SYSTEM SET oauth_validator.authn_id TO 'user\@example.com'"); +$node->reload; +$log_start = + $node->wait_for_log(qr/reloading configuration files/, $log_start); + +# Now the test role can be logged into. (testalt still can't be mapped.) +$node->connect_ok( + "$common_connstr user=test", + "matched username map (test)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); +$node->connect_fails( + "$common_connstr user=testalt", + "mismatched username map (testalt)", + expected_stderr => qr/OAuth bearer authentication failed/); + +# testparam ignores the map entirely. +$node->connect_ok( + "$common_connstr user=testparam", + "delegated ident (testparam)", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@); + +$bgconn->query_safe("ALTER SYSTEM RESET oauth_validator.authn_id"); +$node->reload; +$log_start = + $node->wait_for_log(qr/reloading configuration files/, $log_start); + +# +# Test multiple validators. +# + +$node->append_conf('postgresql.conf', + "oauth_validator_libraries = 'validator, fail_validator'\n"); + +# With multiple validators, every HBA line must explicitly declare one. +my $result = $node->restart(fail_ok => 1); +is($result, 0, + 'restart fails without explicit validators in oauth HBA entries'); + +$log_start = $node->wait_for_log( + qr/authentication method "oauth" requires argument "validator" to be set/, + $log_start); + +unlink($node->data_dir . '/pg_hba.conf'); +$node->append_conf( + 'pg_hba.conf', qq{ +local all test oauth validator=validator issuer="$issuer" scope="openid postgres" +local all testalt oauth validator=fail_validator issuer="$issuer/.well-known/oauth-authorization-server/alternate" scope="openid postgres alt" +}); +$node->restart; + +$log_start = $node->wait_for_log(qr/ready to accept connections/, $log_start); + +# The test user should work as before. +$user = "test"; +$node->connect_ok( + "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0635", + "validator is used for $user", + expected_stderr => + qr@Visit https://example\.com/ and enter the code: postgresuser@, + log_like => [qr/connection authorized/]); + +# testalt should be routed through the fail_validator. +$user = "testalt"; +$node->connect_fails( + "user=$user dbname=postgres oauth_issuer=$issuer/.well-known/oauth-authorization-server/alternate oauth_client_id=f02c6361-0636", + "fail_validator is used for $user", + expected_stderr => qr/FATAL:\s+fail_validator: sentinel error/); + +# +# Test ABI compatibility magic marker +# +$node->append_conf('postgresql.conf', + "oauth_validator_libraries = 'magic_validator'\n"); +unlink($node->data_dir . '/pg_hba.conf'); +$node->append_conf( + 'pg_hba.conf', qq{ +local all test oauth validator=magic_validator issuer="$issuer" scope="openid postgres" +}); +$node->restart; + +$log_start = $node->wait_for_log(qr/ready to accept connections/, $log_start); + +$node->connect_fails( + "user=test dbname=postgres oauth_issuer=$issuer/.well-known/oauth-authorization-server/alternate oauth_client_id=f02c6361-0636", + "magic_validator is used for $user", + expected_stderr => + qr/FATAL:\s+OAuth validator module "magic_validator": magic number mismatch/ +); +$node->stop; + +done_testing(); diff --git a/src/test/modules/oauth_validator/t/002_client.pl b/src/test/modules/oauth_validator/t/002_client.pl new file mode 100644 index 0000000000000..aac0220d2152d --- /dev/null +++ b/src/test/modules/oauth_validator/t/002_client.pl @@ -0,0 +1,156 @@ +# +# Exercises the API for custom OAuth client flows, using the oauth_hook_client +# test driver. +# +# Copyright (c) 2021-2025, PostgreSQL Global Development Group +# + +use strict; +use warnings FATAL => 'all'; + +use JSON::PP qw(encode_json); +use MIME::Base64 qw(encode_base64); +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\boauth\b/) +{ + plan skip_all => + 'Potentially unsafe test oauth not enabled in PG_TEST_EXTRA'; +} + +# +# Cluster Setup +# + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; +$node->append_conf('postgresql.conf', "log_connections = all\n"); +$node->append_conf('postgresql.conf', + "oauth_validator_libraries = 'validator'\n"); +$node->start; + +$node->safe_psql('postgres', 'CREATE USER test;'); + +# These tests don't use the builtin flow, and we don't have an authorization +# server running, so the address used here shouldn't matter. Use an invalid IP +# address, so if there's some cascade of errors that causes the client to +# attempt a connection, we'll fail noisily. +my $issuer = "https://256.256.256.256"; +my $scope = "openid postgres"; + +unlink($node->data_dir . '/pg_hba.conf'); +$node->append_conf( + 'pg_hba.conf', qq{ +local all test oauth issuer="$issuer" scope="$scope" +}); +$node->reload; + +my $log_start = $node->wait_for_log(qr/reloading configuration files/); + +$ENV{PGOAUTHDEBUG} = "UNSAFE"; + +# +# Tests +# + +my $user = "test"; +my $base_connstr = $node->connstr() . " user=$user"; +my $common_connstr = + "$base_connstr oauth_issuer=$issuer oauth_client_id=myID"; + +sub test +{ + my ($test_name, %params) = @_; + + my $flags = []; + if (defined($params{flags})) + { + $flags = $params{flags}; + } + + my @cmd = ("oauth_hook_client", @{$flags}, $common_connstr); + note "running '" . join("' '", @cmd) . "'"; + + my ($stdout, $stderr) = run_command(\@cmd); + + if (defined($params{expected_stdout})) + { + like($stdout, $params{expected_stdout}, "$test_name: stdout matches"); + } + + if (defined($params{expected_stderr})) + { + like($stderr, $params{expected_stderr}, "$test_name: stderr matches"); + } + else + { + is($stderr, "", "$test_name: no stderr"); + } +} + +test( + "basic synchronous hook can provide a token", + flags => [ + "--token", "my-token", + "--expected-uri", "$issuer/.well-known/openid-configuration", + "--expected-scope", $scope, + ], + expected_stdout => qr/connection succeeded/); + +$node->log_check("validator receives correct token", + $log_start, + log_like => [ qr/oauth_validator: token="my-token", role="$user"/, ]); + +if ($ENV{with_libcurl} ne 'yes') +{ + # libpq should help users out if no OAuth support is built in. + test( + "fails without custom hook installed", + flags => ["--no-hook"], + expected_stderr => + qr/no OAuth flows are available \(try installing the libpq-oauth package\)/ + ); +} + +# connect_timeout should work if the flow doesn't respond. +$common_connstr = "$common_connstr connect_timeout=1"; +test( + "connect_timeout interrupts hung client flow", + flags => ["--hang-forever"], + expected_stderr => qr/failed: timeout expired/); + +# Remove the timeout for later tests. +$common_connstr = "$base_connstr oauth_issuer=$issuer oauth_client_id=myID"; + +# Test various misbehaviors of the client hook. +my @cases = ( + { + flag => "--misbehave=no-hook", + expected_error => + qr/user-defined OAuth flow provided neither a token nor an async callback/, + }, + { + flag => "--misbehave=fail-async", + expected_error => qr/user-defined OAuth flow failed/, + }, + { + flag => "--misbehave=no-token", + expected_error => qr/user-defined OAuth flow did not provide a token/, + }, + { + flag => "--misbehave=no-socket", + expected_error => + qr/user-defined OAuth flow did not provide a socket for polling/, + }); + +foreach my $c (@cases) +{ + test( + "hook misbehavior: $c->{'flag'}", + flags => [ $c->{'flag'} ], + expected_stderr => $c->{'expected_error'}); +} + +done_testing(); diff --git a/src/test/modules/oauth_validator/t/OAuth/Server.pm b/src/test/modules/oauth_validator/t/OAuth/Server.pm new file mode 100644 index 0000000000000..52ae7afa991c3 --- /dev/null +++ b/src/test/modules/oauth_validator/t/OAuth/Server.pm @@ -0,0 +1,140 @@ + +# Copyright (c) 2025, PostgreSQL Global Development Group + +=pod + +=head1 NAME + +OAuth::Server - runs a mock OAuth authorization server for testing + +=head1 SYNOPSIS + + use OAuth::Server; + + my $server = OAuth::Server->new(); + $server->run; + + my $port = $server->port; + my $issuer = "http://127.0.0.1:$port"; + + # test against $issuer... + + $server->stop; + +=head1 DESCRIPTION + +This is glue API between the Perl tests and the Python authorization server +daemon implemented in t/oauth_server.py. (Python has a fairly usable HTTP server +in its standard library, so the implementation was ported from Perl.) + +This authorization server does not use TLS (it implements a nonstandard, unsafe +issuer at "http://127.0.0.1:"), so libpq in particular will need to set +PGOAUTHDEBUG=UNSAFE to be able to talk to it. + +=cut + +package OAuth::Server; + +use warnings; +use strict; +use Scalar::Util; +use Test::More; + +=pod + +=head1 METHODS + +=over + +=item OAuth::Server->new() + +Create a new OAuth Server object. + +=cut + +sub new +{ + my $class = shift; + + my $self = {}; + bless($self, $class); + + return $self; +} + +=pod + +=item $server->port() + +Returns the port in use by the server. + +=cut + +sub port +{ + my $self = shift; + + return $self->{'port'}; +} + +=pod + +=item $server->run() + +Runs the authorization server daemon in t/oauth_server.py. + +=cut + +sub run +{ + my $self = shift; + my $port; + + my $pid = open(my $read_fh, "-|", $ENV{PYTHON}, "t/oauth_server.py") + or die "failed to start OAuth server: $!"; + + # Get the port number from the daemon. It closes stdout afterwards; that way + # we can slurp in the entire contents here rather than worrying about the + # number of bytes to read. + $port = do { local $/ = undef; <$read_fh> } + // die "failed to read port number: $!"; + chomp $port; + die "server did not advertise a valid port" + unless Scalar::Util::looks_like_number($port); + + $self->{'pid'} = $pid; + $self->{'port'} = $port; + $self->{'child'} = $read_fh; + + note("OAuth provider (PID $pid) is listening on port $port\n"); +} + +=pod + +=item $server->stop() + +Sends SIGTERM to the authorization server and waits for it to exit. + +=cut + +sub stop +{ + my $self = shift; + + note("Sending SIGTERM to OAuth provider PID: $self->{'pid'}\n"); + + kill(15, $self->{'pid'}); + $self->{'pid'} = undef; + + # Closing the popen() handle waits for the process to exit. + close($self->{'child'}); + $self->{'child'} = undef; +} + +=pod + +=back + +=cut + +1; diff --git a/src/test/modules/oauth_validator/t/oauth_server.py b/src/test/modules/oauth_validator/t/oauth_server.py new file mode 100755 index 0000000000000..0f8836aadf372 --- /dev/null +++ b/src/test/modules/oauth_validator/t/oauth_server.py @@ -0,0 +1,418 @@ +#! /usr/bin/env python3 +# +# A mock OAuth authorization server, designed to be invoked from +# OAuth/Server.pm. This listens on an ephemeral port number (printed to stdout +# so that the Perl tests can contact it) and runs as a daemon until it is +# signaled. +# + +import base64 +import functools +import http.server +import json +import os +import sys +import time +import urllib.parse +from collections import defaultdict +from typing import Dict + + +class OAuthHandler(http.server.BaseHTTPRequestHandler): + """ + Core implementation of the authorization server. The API is + inheritance-based, with entry points at do_GET() and do_POST(). See the + documentation for BaseHTTPRequestHandler. + """ + + JsonObject = Dict[str, object] # TypeAlias is not available until 3.10 + + def _check_issuer(self): + """ + Switches the behavior of the provider depending on the issuer URI. + """ + self._alt_issuer = ( + self.path.startswith("/alternate/") + or self.path == "/.well-known/oauth-authorization-server/alternate" + ) + self._parameterized = self.path.startswith("/param/") + + # Strip off the magic path segment. (The more readable + # str.removeprefix()/removesuffix() aren't available until Py3.9.) + if self._alt_issuer: + # The /alternate issuer uses IETF-style .well-known URIs. + if self.path.startswith("/.well-known/"): + self.path = self.path[: -len("/alternate")] + else: + self.path = self.path[len("/alternate") :] + elif self._parameterized: + self.path = self.path[len("/param") :] + + def _check_authn(self): + """ + Checks the expected value of the Authorization header, if any. + """ + secret = self._get_param("expected_secret", None) + if secret is None: + return + + assert "Authorization" in self.headers + method, creds = self.headers["Authorization"].split() + + if method != "Basic": + raise RuntimeError(f"client used {method} auth; expected Basic") + + # TODO: Remove "~" from the safe list after Py3.6 support is removed. + # 3.7 does this by default. + username = urllib.parse.quote_plus(self.client_id, safe="~") + password = urllib.parse.quote_plus(secret, safe="~") + expected_creds = f"{username}:{password}" + + if creds.encode() != base64.b64encode(expected_creds.encode()): + raise RuntimeError( + f"client sent '{creds}'; expected b64encode('{expected_creds}')" + ) + + def do_GET(self): + self._response_code = 200 + self._check_issuer() + + config_path = "/.well-known/openid-configuration" + if self._alt_issuer: + config_path = "/.well-known/oauth-authorization-server" + + if self.path == config_path: + resp = self.config() + else: + self.send_error(404, "Not Found") + return + + self._send_json(resp) + + def _parse_params(self) -> Dict[str, str]: + """ + Parses apart the form-urlencoded request body and returns the resulting + dict. For use by do_POST(). + """ + size = int(self.headers["Content-Length"]) + form = self.rfile.read(size) + + assert self.headers["Content-Type"] == "application/x-www-form-urlencoded" + return urllib.parse.parse_qs( + form.decode("utf-8"), + strict_parsing=True, + keep_blank_values=True, + encoding="utf-8", + errors="strict", + ) + + @property + def client_id(self) -> str: + """ + Returns the client_id sent in the POST body or the Authorization header. + self._parse_params() must have been called first. + """ + if "client_id" in self._params: + return self._params["client_id"][0] + + if "Authorization" not in self.headers: + raise RuntimeError("client did not send any client_id") + + _, creds = self.headers["Authorization"].split() + + decoded = base64.b64decode(creds).decode("utf-8") + username, _ = decoded.split(":", 1) + + return urllib.parse.unquote_plus(username) + + def do_POST(self): + self._response_code = 200 + self._check_issuer() + + self._params = self._parse_params() + if self._parameterized: + # Pull encoded test parameters out of the peer's client_id field. + # This is expected to be Base64-encoded JSON. + js = base64.b64decode(self.client_id) + self._test_params = json.loads(js) + + self._check_authn() + + if self.path == "/authorize": + resp = self.authorization() + elif self.path == "/token": + resp = self.token() + else: + self.send_error(404) + return + + self._send_json(resp) + + def _should_modify(self) -> bool: + """ + Returns True if the client has requested a modification to this stage of + the exchange. + """ + if not hasattr(self, "_test_params"): + return False + + stage = self._test_params.get("stage") + + return ( + stage == "all" + or ( + stage == "discovery" + and self.path == "/.well-known/openid-configuration" + ) + or (stage == "device" and self.path == "/authorize") + or (stage == "token" and self.path == "/token") + ) + + def _get_param(self, name, default): + """ + If the client has requested a modification to this stage (see + _should_modify()), this method searches the provided test parameters for + a key of the given name, and returns it if found. Otherwise the provided + default is returned. + """ + if self._should_modify() and name in self._test_params: + return self._test_params[name] + + return default + + @property + def _content_type(self) -> str: + """ + Returns "application/json" unless the test has requested something + different. + """ + return self._get_param("content_type", "application/json") + + @property + def _interval(self) -> int: + """ + Returns 0 unless the test has requested something different. + """ + return self._get_param("interval", 0) + + @property + def _retry_code(self) -> str: + """ + Returns "authorization_pending" unless the test has requested something + different. + """ + return self._get_param("retry_code", "authorization_pending") + + @property + def _uri_spelling(self) -> str: + """ + Returns "verification_uri" unless the test has requested something + different. + """ + return self._get_param("uri_spelling", "verification_uri") + + @property + def _response_padding(self): + """ + Returns a dict with any additional entries that should be folded into a + JSON response, as determined by test parameters provided by the client: + + - huge_response: if set to True, the dict will contain a gigantic string + value + + - nested_array: if set to nonzero, the dict will contain a deeply nested + array so that the top-level object has the given depth + + - nested_object: if set to nonzero, the dict will contain a deeply + nested JSON object so that the top-level object has the given depth + """ + ret = dict() + + if self._get_param("huge_response", False): + ret["_pad_"] = "x" * 1024 * 1024 + + depth = self._get_param("nested_array", 0) + if depth: + ret["_arr_"] = functools.reduce(lambda x, _: [x], range(depth)) + + depth = self._get_param("nested_object", 0) + if depth: + ret["_obj_"] = functools.reduce(lambda x, _: {"": x}, range(depth)) + + return ret + + @property + def _access_token(self): + """ + The actual Bearer token sent back to the client on success. Tests may + override this with the "token" test parameter. + """ + token = self._get_param("token", None) + if token is not None: + return token + + token = "9243959234" + if self._alt_issuer: + token += "-alt" + + return token + + def _send_json(self, js: JsonObject) -> None: + """ + Sends the provided JSON dict as an application/json response. + self._response_code can be modified to send JSON error responses. + """ + resp = json.dumps(js).encode("ascii") + self.log_message("sending JSON response: %s", resp) + + self.send_response(self._response_code) + self.send_header("Content-Type", self._content_type) + self.send_header("Content-Length", str(len(resp))) + self.end_headers() + + self.wfile.write(resp) + + def config(self) -> JsonObject: + port = self.server.socket.getsockname()[1] + + issuer = f"http://127.0.0.1:{port}" + if self._alt_issuer: + issuer += "/alternate" + elif self._parameterized: + issuer += "/param" + + return { + "issuer": issuer, + "token_endpoint": issuer + "/token", + "device_authorization_endpoint": issuer + "/authorize", + "response_types_supported": ["token"], + "subject_types_supported": ["public"], + "id_token_signing_alg_values_supported": ["RS256"], + "grant_types_supported": [ + "authorization_code", + "urn:ietf:params:oauth:grant-type:device_code", + ], + } + + @property + def _token_state(self): + """ + A cached _TokenState object for the connected client (as determined by + the request's client_id), or a new one if it doesn't already exist. + + This relies on the existence of a defaultdict attached to the server; + see main() below. + """ + return self.server.token_state[self.client_id] + + def _remove_token_state(self): + """ + Removes any cached _TokenState for the current client_id. Call this + after the token exchange ends to get rid of unnecessary state. + """ + if self.client_id in self.server.token_state: + del self.server.token_state[self.client_id] + + def authorization(self) -> JsonObject: + uri = "https://example.com/" + if self._alt_issuer: + uri = "https://example.org/" + + resp = { + "device_code": "postgres", + "user_code": "postgresuser", + self._uri_spelling: uri, + "expires_in": 5, + **self._response_padding, + } + + interval = self._interval + if interval is not None: + resp["interval"] = interval + self._token_state.min_delay = interval + else: + self._token_state.min_delay = 5 # default + + # Check the scope. + if "scope" in self._params: + assert self._params["scope"][0], "empty scopes should be omitted" + + return resp + + def token(self) -> JsonObject: + err = self._get_param("error_code", None) + if err: + self._response_code = self._get_param("error_status", 400) + + resp = {"error": err} + + desc = self._get_param("error_desc", "") + if desc: + resp["error_description"] = desc + + return resp + + if self._should_modify() and "retries" in self._test_params: + retries = self._test_params["retries"] + + # Check to make sure the token interval is being respected. + now = time.monotonic() + if self._token_state.last_try is not None: + delay = now - self._token_state.last_try + assert ( + delay > self._token_state.min_delay + ), f"client waited only {delay} seconds between token requests (expected {self._token_state.min_delay})" + + self._token_state.last_try = now + + # If we haven't reached the required number of retries yet, return a + # "pending" response. + if self._token_state.retries < retries: + self._token_state.retries += 1 + + self._response_code = 400 + return {"error": self._retry_code} + + # Clean up any retry tracking state now that the exchange is ending. + self._remove_token_state() + + return { + "access_token": self._access_token, + "token_type": "bearer", + **self._response_padding, + } + + +def main(): + """ + Starts the authorization server on localhost. The ephemeral port in use will + be printed to stdout. + """ + + s = http.server.HTTPServer(("127.0.0.1", 0), OAuthHandler) + + # Attach a "cache" dictionary to the server to allow the OAuthHandlers to + # track state across token requests. The use of defaultdict ensures that new + # entries will be created automatically. + class _TokenState: + retries = 0 + min_delay = None + last_try = None + + s.token_state = defaultdict(_TokenState) + + # Give the parent the port number to contact (this is also the signal that + # we're ready to receive requests). + port = s.socket.getsockname()[1] + print(port) + + # stdout is closed to allow the parent to just "read to the end". + stdout = sys.stdout.fileno() + sys.stdout.close() + os.close(stdout) + + s.serve_forever() # we expect our parent to send a termination signal + + +if __name__ == "__main__": + main() diff --git a/src/test/modules/oauth_validator/validator.c b/src/test/modules/oauth_validator/validator.c new file mode 100644 index 0000000000000..42b69646fbb9c --- /dev/null +++ b/src/test/modules/oauth_validator/validator.c @@ -0,0 +1,143 @@ +/*------------------------------------------------------------------------- + * + * validator.c + * Test module for serverside OAuth token validation callbacks + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/test/modules/oauth_validator/validator.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "libpq/oauth.h" +#include "miscadmin.h" +#include "utils/guc.h" +#include "utils/memutils.h" + +PG_MODULE_MAGIC; + +static void validator_startup(ValidatorModuleState *state); +static void validator_shutdown(ValidatorModuleState *state); +static bool validate_token(const ValidatorModuleState *state, + const char *token, + const char *role, + ValidatorModuleResult *res); + +/* Callback implementations (exercise all three) */ +static const OAuthValidatorCallbacks validator_callbacks = { + PG_OAUTH_VALIDATOR_MAGIC, + + .startup_cb = validator_startup, + .shutdown_cb = validator_shutdown, + .validate_cb = validate_token +}; + +/* GUCs */ +static char *authn_id = NULL; +static bool authorize_tokens = true; + +/*--- + * Extension entry point. Sets up GUCs for use by tests: + * + * - oauth_validator.authn_id Sets the user identifier to return during token + * validation. Defaults to the username in the + * startup packet. + * + * - oauth_validator.authorize_tokens + * Sets whether to successfully validate incoming + * tokens. Defaults to true. + */ +void +_PG_init(void) +{ + DefineCustomStringVariable("oauth_validator.authn_id", + "Authenticated identity to use for future connections", + NULL, + &authn_id, + NULL, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + DefineCustomBoolVariable("oauth_validator.authorize_tokens", + "Should tokens be marked valid?", + NULL, + &authorize_tokens, + true, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + MarkGUCPrefixReserved("oauth_validator"); +} + +/* + * Validator module entry point. + */ +const OAuthValidatorCallbacks * +_PG_oauth_validator_module_init(void) +{ + return &validator_callbacks; +} + +#define PRIVATE_COOKIE ((void *) 13579) + +/* + * Startup callback, to set up private data for the validator. + */ +static void +validator_startup(ValidatorModuleState *state) +{ + /* + * Make sure the server is correctly setting sversion. (Real modules + * should not do this; it would defeat upgrade compatibility.) + */ + if (state->sversion != PG_VERSION_NUM) + elog(ERROR, "oauth_validator: sversion set to %d", state->sversion); + + state->private_data = PRIVATE_COOKIE; +} + +/* + * Shutdown callback, to tear down the validator. + */ +static void +validator_shutdown(ValidatorModuleState *state) +{ + /* Check to make sure our private state still exists. */ + if (state->private_data != PRIVATE_COOKIE) + elog(PANIC, "oauth_validator: private state cookie changed to %p in shutdown", + state->private_data); +} + +/* + * Validator implementation. Logs the incoming data and authorizes the token by + * default; the behavior can be modified via the module's GUC settings. + */ +static bool +validate_token(const ValidatorModuleState *state, + const char *token, const char *role, + ValidatorModuleResult *res) +{ + /* Check to make sure our private state still exists. */ + if (state->private_data != PRIVATE_COOKIE) + elog(ERROR, "oauth_validator: private state cookie changed to %p in validate", + state->private_data); + + elog(LOG, "oauth_validator: token=\"%s\", role=\"%s\"", token, role); + elog(LOG, "oauth_validator: issuer=\"%s\", scope=\"%s\"", + MyProcPort->hba->oauth_issuer, + MyProcPort->hba->oauth_scope); + + res->authorized = authorize_tokens; + if (authn_id) + res->authn_id = pstrdup(authn_id); + else + res->authn_id = pstrdup(role); + + return true; +} diff --git a/src/test/modules/plsample/meson.build b/src/test/modules/plsample/meson.build index 9a1f16a20f2d5..bb3e1bcb96a4b 100644 --- a/src/test/modules/plsample/meson.build +++ b/src/test/modules/plsample/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group plsample_sources = files( 'plsample.c', diff --git a/src/test/modules/plsample/plsample.c b/src/test/modules/plsample/plsample.c index 40c462e84e03a..78802a94f6284 100644 --- a/src/test/modules/plsample/plsample.c +++ b/src/test/modules/plsample/plsample.c @@ -3,7 +3,7 @@ * plsample.c * Handler for the PL/Sample procedural language * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -21,7 +21,7 @@ #include "commands/trigger.h" #include "executor/spi.h" #include "funcapi.h" -#include "utils/builtins.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -220,8 +220,7 @@ plsample_trigger_handler(PG_FUNCTION_ARGS) elog(ERROR, "not called by trigger manager"); /* Connect to the SPI manager */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "could not connect to SPI manager"); + SPI_connect(); rc = SPI_register_trigger_data(trigdata); Assert(rc >= 0); diff --git a/src/test/modules/spgist_name_ops/meson.build b/src/test/modules/spgist_name_ops/meson.build index 81c0de0a1a24a..a9596a8a12df6 100644 --- a/src/test/modules/spgist_name_ops/meson.build +++ b/src/test/modules/spgist_name_ops/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group spgist_name_ops_sources = files( 'spgist_name_ops.c', diff --git a/src/test/modules/spgist_name_ops/spgist_name_ops.c b/src/test/modules/spgist_name_ops/spgist_name_ops.c index 322881ba78e24..bcc16ce366ec5 100644 --- a/src/test/modules/spgist_name_ops/spgist_name_ops.c +++ b/src/test/modules/spgist_name_ops/spgist_name_ops.c @@ -11,7 +11,7 @@ * Unlike spgtextproc.c, we don't bother with collation-aware logic. * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/test/modules/ssl_passphrase_callback/Makefile b/src/test/modules/ssl_passphrase_callback/Makefile index 40ed38dc7073c..7f977dbabf036 100644 --- a/src/test/modules/ssl_passphrase_callback/Makefile +++ b/src/test/modules/ssl_passphrase_callback/Makefile @@ -19,7 +19,7 @@ include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif -SHLIB_LINK += $(filter -lssl -lcrypto -lssleay32 -leay32, $(LIBS)) +SHLIB_LINK += $(filter -lssl -lcrypto, $(LIBS)) # Targets to generate or remove the ssl certificate and key # Normally not needed. Don't run these targets in a vpath build, the results diff --git a/src/test/modules/ssl_passphrase_callback/meson.build b/src/test/modules/ssl_passphrase_callback/meson.build index fd322d925c6ce..9cc893dc1e411 100644 --- a/src/test/modules/ssl_passphrase_callback/meson.build +++ b/src/test/modules/ssl_passphrase_callback/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group if not ssl.found() subdir_done() diff --git a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl index f71d0ff3e05ae..c16ff25718095 100644 --- a/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl +++ b/src/test/modules/ssl_passphrase_callback/t/001_testfunc.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -62,9 +62,11 @@ $node->append_conf('postgresql.conf', "ssl_passphrase.passphrase = 'blurfl'"); # try to start the server again -my $ret = - PostgreSQL::Test::Utils::system_log('pg_ctl', '-D', $node->data_dir, '-l', - $node->logfile, 'start'); +my $ret = PostgreSQL::Test::Utils::system_log( + 'pg_ctl', + '--pgdata' => $node->data_dir, + '--log' => $node->logfile, + 'start'); # with a bad passphrase the server should not start diff --git a/src/test/modules/test_aio/.gitignore b/src/test/modules/test_aio/.gitignore new file mode 100644 index 0000000000000..716e17f5a2ad4 --- /dev/null +++ b/src/test/modules/test_aio/.gitignore @@ -0,0 +1,2 @@ +# Generated subdirectories +/tmp_check/ diff --git a/src/test/modules/test_aio/Makefile b/src/test/modules/test_aio/Makefile new file mode 100644 index 0000000000000..f53cc64671a82 --- /dev/null +++ b/src/test/modules/test_aio/Makefile @@ -0,0 +1,26 @@ +# src/test/modules/test_aio/Makefile + +PGFILEDESC = "test_aio - test code for AIO" + +MODULE_big = test_aio +OBJS = \ + $(WIN32RES) \ + test_aio.o + +EXTENSION = test_aio +DATA = test_aio--1.0.sql + +TAP_TESTS = 1 + +export enable_injection_points + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/test_aio +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/src/test/modules/test_aio/meson.build b/src/test/modules/test_aio/meson.build new file mode 100644 index 0000000000000..73d2fd68eaa19 --- /dev/null +++ b/src/test/modules/test_aio/meson.build @@ -0,0 +1,37 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +test_aio_sources = files( + 'test_aio.c', +) + +if host_system == 'windows' + test_aio_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'test_aio', + '--FILEDESC', 'test_aio - test code for AIO',]) +endif + +test_aio = shared_module('test_aio', + test_aio_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += test_aio + +test_install_data += files( + 'test_aio.control', + 'test_aio--1.0.sql', +) + +tests += { + 'name': 'test_aio', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'env': { + 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', + }, + 'tests': [ + 't/001_aio.pl', + 't/002_io_workers.pl', + ], + }, +} diff --git a/src/test/modules/test_aio/t/001_aio.pl b/src/test/modules/test_aio/t/001_aio.pl new file mode 100644 index 0000000000000..4527c70785d34 --- /dev/null +++ b/src/test/modules/test_aio/t/001_aio.pl @@ -0,0 +1,1525 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + + +### +# Test io_method=worker +### +my $node_worker = create_node('worker'); +$node_worker->start(); + +test_generic('worker', $node_worker); +SKIP: +{ + skip 'Injection points not supported by this build', 1 + unless $ENV{enable_injection_points} eq 'yes'; + test_inject_worker('worker', $node_worker); +} + +$node_worker->stop(); + + +### +# Test io_method=io_uring +### + +if (have_io_uring()) +{ + my $node_uring = create_node('io_uring'); + $node_uring->start(); + test_generic('io_uring', $node_uring); + $node_uring->stop(); +} + + +### +# Test io_method=sync +### + +my $node_sync = create_node('sync'); + +# just to have one test not use the default auto-tuning + +$node_sync->append_conf( + 'postgresql.conf', qq( +io_max_concurrency=4 +)); + +$node_sync->start(); +test_generic('sync', $node_sync); +$node_sync->stop(); + +done_testing(); + + +### +# Test Helpers +### + +sub create_node +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my $io_method = shift; + + my $node = PostgreSQL::Test::Cluster->new($io_method); + + # Want to test initdb for each IO method, otherwise we could just reuse + # the cluster. + # + # Unfortunately Cluster::init() puts PG_TEST_INITDB_EXTRA_OPTS after the + # options specified by ->extra, if somebody puts -c io_method=xyz in + # PG_TEST_INITDB_EXTRA_OPTS it would break this test. Fix that up if we + # detect it. + local $ENV{PG_TEST_INITDB_EXTRA_OPTS} = $ENV{PG_TEST_INITDB_EXTRA_OPTS}; + if (defined $ENV{PG_TEST_INITDB_EXTRA_OPTS} + && $ENV{PG_TEST_INITDB_EXTRA_OPTS} =~ m/io_method=/) + { + $ENV{PG_TEST_INITDB_EXTRA_OPTS} .= " -c io_method=$io_method"; + } + + $node->init(extra => [ '-c', "io_method=$io_method" ]); + + $node->append_conf( + 'postgresql.conf', qq( +shared_preload_libraries=test_aio +log_min_messages = 'DEBUG3' +log_statement=all +log_error_verbosity=default +restart_after_crash=false +temp_buffers=100 +)); + + # Even though we used -c io_method=... above, if TEMP_CONFIG sets + # io_method, it'd override the setting persisted at initdb time. While + # using (and later verifying) the setting from initdb provides some + # verification of having used the io_method during initdb, it's probably + # not worth the complication of only appending if the variable is set in + # in TEMP_CONFIG. + $node->append_conf( + 'postgresql.conf', qq( +io_method=$io_method +)); + + ok(1, "$io_method: initdb"); + + return $node; +} + +sub have_io_uring +{ + # To detect if io_uring is supported, we look at the error message for + # assigning an invalid value to an enum GUC, which lists all the valid + # options. We need to use -C to deal with running as administrator on + # windows, the superuser check is omitted if -C is used. + my ($stdout, $stderr) = + run_command [qw(postgres -C invalid -c io_method=invalid)]; + die "can't determine supported io_method values" + unless $stderr =~ m/Available values: ([^\.]+)\./; + my $methods = $1; + note "supported io_method values are: $methods"; + + return ($methods =~ m/io_uring/) ? 1 : 0; +} + +sub psql_like +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my $io_method = shift; + my $psql = shift; + my $name = shift; + my $sql = shift; + my $expected_stdout = shift; + my $expected_stderr = shift; + my ($cmdret, $output); + + ($output, $cmdret) = $psql->query($sql); + + like($output, $expected_stdout, "$io_method: $name: expected stdout"); + like($psql->{stderr}, $expected_stderr, + "$io_method: $name: expected stderr"); + $psql->{stderr} = ''; + + return $output; +} + +sub query_wait_block +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my $io_method = shift; + my $node = shift; + my $psql = shift; + my $name = shift; + my $sql = shift; + my $waitfor = shift; + + my $pid = $psql->query_safe('SELECT pg_backend_pid()'); + + $psql->{stdin} .= qq($sql;\n); + $psql->{run}->pump_nb(); + ok(1, "$io_method: $name: issued sql"); + + $node->poll_query_until('postgres', + qq(SELECT wait_event FROM pg_stat_activity WHERE pid = $pid), + $waitfor); + ok(1, "$io_method: $name: observed $waitfor wait event"); +} + +# Returns count of checksum failures for the specified database or for shared +# relations, if $datname is undefined. +sub checksum_failures +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my $psql = shift; + my $datname = shift; + my $checksum_count; + my $checksum_last_failure; + + if (defined $datname) + { + $checksum_count = $psql->query_safe( + qq( +SELECT checksum_failures FROM pg_stat_database WHERE datname = '$datname'; +)); + $checksum_last_failure = $psql->query_safe( + qq( +SELECT checksum_last_failure FROM pg_stat_database WHERE datname = '$datname'; +)); + } + else + { + $checksum_count = $psql->query_safe( + qq( +SELECT checksum_failures FROM pg_stat_database WHERE datname IS NULL; +)); + $checksum_last_failure = $psql->query_safe( + qq( +SELECT checksum_last_failure FROM pg_stat_database WHERE datname IS NULL; +)); + } + + return $checksum_count, $checksum_last_failure; +} + +### +# Sub-tests +### + +# Sanity checks for the IO handle API +sub test_handle +{ + my $io_method = shift; + my $node = shift; + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + # leak warning: implicit xact + psql_like( + $io_method, + $psql, + "handle_get() leak in implicit xact", + qq(SELECT handle_get()), + qr/^$/, + qr/leaked AIO handle/, + "$io_method: leaky handle_get() warns"); + + # leak warning: explicit xact + psql_like( + $io_method, $psql, + "handle_get() leak in explicit xact", + qq(BEGIN; SELECT handle_get(); COMMIT), + qr/^$/, qr/leaked AIO handle/); + + + # leak warning: explicit xact, rollback + psql_like( + $io_method, + $psql, + "handle_get() leak in explicit xact, rollback", + qq(BEGIN; SELECT handle_get(); ROLLBACK;), + qr/^$/, + qr/leaked AIO handle/); + + # leak warning: subtrans + psql_like( + $io_method, + $psql, + "handle_get() leak in subxact", + qq(BEGIN; SAVEPOINT foo; SELECT handle_get(); COMMIT;), + qr/^$/, + qr/leaked AIO handle/); + + # leak warning + error: released in different command (thus resowner) + psql_like( + $io_method, + $psql, + "handle_release() in different command", + qq(BEGIN; SELECT handle_get(); SELECT handle_release_last(); COMMIT;), + qr/^$/, + qr/leaked AIO handle.*release in unexpected state/ms); + + # no leak, release in same command + psql_like( + $io_method, + $psql, + "handle_release() in same command", + qq(BEGIN; SELECT handle_get() UNION ALL SELECT handle_release_last(); COMMIT;), + qr/^$/, + qr/^$/); + + # normal handle use + psql_like($io_method, $psql, "handle_get_release()", + qq(SELECT handle_get_release()), + qr/^$/, qr/^$/); + + # should error out, API violation + psql_like( + $io_method, + $psql, + "handle_get_twice()", + qq(SELECT handle_get_twice()), + qr/^$/, + qr/ERROR: API violation: Only one IO can be handed out$/); + + # recover after error in implicit xact + psql_like( + $io_method, + $psql, + "handle error recovery in implicit xact", + qq(SELECT handle_get_and_error(); SELECT 'ok', handle_get_release()), + qr/^|ok$/, + qr/ERROR.*as you command/); + + # recover after error in implicit xact + psql_like( + $io_method, + $psql, + "handle error recovery in explicit xact", + qq(BEGIN; SELECT handle_get_and_error(); SELECT handle_get_release(), 'ok'; COMMIT;), + qr/^|ok$/, + qr/ERROR.*as you command/); + + # recover after error in subtrans + psql_like( + $io_method, + $psql, + "handle error recovery in explicit subxact", + qq(BEGIN; SAVEPOINT foo; SELECT handle_get_and_error(); ROLLBACK TO SAVEPOINT foo; SELECT handle_get_release(); ROLLBACK;), + qr/^|ok$/, + qr/ERROR.*as you command/); + + $psql->quit(); +} + +# Sanity checks for the batchmode API +sub test_batchmode +{ + my $io_method = shift; + my $node = shift; + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + # In a build with RELCACHE_FORCE_RELEASE and CATCACHE_FORCE_RELEASE, just + # using SELECT batch_start() causes spurious test failures, because the + # lookup of the type information when printing the result tuple also + # starts a batch. The easiest way around is to not print a result tuple. + my $batch_start_sql = qq(SELECT WHERE batch_start() IS NULL); + + # leak warning & recovery: implicit xact + psql_like( + $io_method, + $psql, + "batch_start() leak & cleanup in implicit xact", + $batch_start_sql, + qr/^$/, + qr/open AIO batch at end/, + "$io_method: leaky batch_start() warns"); + + # leak warning & recovery: explicit xact + psql_like( + $io_method, + $psql, + "batch_start() leak & cleanup in explicit xact", + qq(BEGIN; $batch_start_sql; COMMIT;), + qr/^$/, + qr/open AIO batch at end/, + "$io_method: leaky batch_start() warns"); + + + # leak warning & recovery: explicit xact, rollback + # + # XXX: This doesn't fail right now, due to not getting a chance to do + # something at transaction command commit. That's not a correctness issue, + # it just means it's a bit harder to find buggy code. + #psql_like($io_method, $psql, + # "batch_start() leak & cleanup after abort", + # qq(BEGIN; $batch_start_sql; ROLLBACK;), + # qr/^$/, + # qr/open AIO batch at end/, "$io_method: leaky batch_start() warns"); + + # no warning, batch closed in same command + psql_like( + $io_method, + $psql, + "batch_start(), batch_end() works", + qq($batch_start_sql UNION ALL SELECT WHERE batch_end() IS NULL), + qr/^$/, + qr/^$/, + "$io_method: batch_start(), batch_end()"); + + $psql->quit(); +} + +# Test that simple cases of invalid pages are reported +sub test_io_error +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + $psql->query_safe( + qq( +CREATE TEMPORARY TABLE tmp_corr(data int not null); +INSERT INTO tmp_corr SELECT generate_series(1, 10000); +SELECT modify_rel_block('tmp_corr', 1, corrupt_header=>true); +)); + + foreach my $tblname (qw(tbl_corr tmp_corr)) + { + my $invalid_page_re = + $tblname eq 'tbl_corr' + ? qr/invalid page in block 1 of relation base\/\d+\/\d+/ + : qr/invalid page in block 1 of relation base\/\d+\/t\d+_\d+/; + + # verify the error is reported in custom C code + psql_like( + $io_method, + $psql, + "read_rel_block_ll() of $tblname page", + qq(SELECT read_rel_block_ll('$tblname', 1)), + qr/^$/, + $invalid_page_re); + + # verify the error is reported for bufmgr reads, seq scan + psql_like( + $io_method, $psql, + "sequential scan of $tblname block fails", + qq(SELECT count(*) FROM $tblname), + qr/^$/, $invalid_page_re); + + # verify the error is reported for bufmgr reads, tid scan + psql_like( + $io_method, + $psql, + "tid scan of $tblname block fails", + qq(SELECT count(*) FROM $tblname WHERE ctid = '(1, 1)'), + qr/^$/, + $invalid_page_re); + } + + $psql->quit(); +} + +# Test interplay between StartBufferIO and TerminateBufferIO +sub test_startwait_io +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql_a = $node->background_psql('postgres', on_error_stop => 0); + my $psql_b = $node->background_psql('postgres', on_error_stop => 0); + + + ### Verify behavior for normal tables + + # create a buffer we can play around with + my $buf_id = psql_like( + $io_method, $psql_a, + "creation of toy buffer succeeds", + qq(SELECT buffer_create_toy('tbl_ok', 1)), + qr/^\d+$/, qr/^$/); + + # check that one backend can perform StartBufferIO + psql_like( + $io_method, + $psql_a, + "first StartBufferIO", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>false);), + qr/^t$/, + qr/^$/); + + # but not twice on the same buffer (non-waiting) + psql_like( + $io_method, + $psql_a, + "second StartBufferIO fails, same session", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>true);), + qr/^f$/, + qr/^$/); + psql_like( + $io_method, + $psql_b, + "second StartBufferIO fails, other session", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>true);), + qr/^f$/, + qr/^$/); + + # start io in a different session, will block + query_wait_block( + $io_method, + $node, + $psql_b, + "blocking start buffer io", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>false);), + "BufferIo"); + + # Terminate the IO, without marking it as success, this should trigger the + # waiting session to be able to start the io + psql_like( + $io_method, + $psql_a, + "blocking start buffer io, terminating io, not valid", + qq(SELECT buffer_call_terminate_io($buf_id, for_input=>true, succeed=>false, io_error=>false, release_aio=>false)), + qr/^$/, + qr/^$/); + + + # Because the IO was terminated, but not marked as valid, second session should get the right to start io + pump_until($psql_b->{run}, $psql_b->{timeout}, \$psql_b->{stdout}, qr/t/); + ok(1, "$io_method: blocking start buffer io, can start io"); + + # terminate the IO again + $psql_b->query_safe( + qq(SELECT buffer_call_terminate_io($buf_id, for_input=>true, succeed=>false, io_error=>false, release_aio=>false);) + ); + + + # same as the above scenario, but mark IO as having succeeded + psql_like( + $io_method, + $psql_a, + "blocking buffer io w/ success: first start buffer io", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>false);), + qr/^t$/, + qr/^$/); + + # start io in a different session, will block + query_wait_block( + $io_method, + $node, + $psql_b, + "blocking start buffer io", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>false);), + "BufferIo"); + + # Terminate the IO, marking it as success + psql_like( + $io_method, + $psql_a, + "blocking start buffer io, terminating io, valid", + qq(SELECT buffer_call_terminate_io($buf_id, for_input=>true, succeed=>true, io_error=>false, release_aio=>false)), + qr/^$/, + qr/^$/); + + # Because the IO was terminated, and marked as valid, second session should complete but not need io + pump_until($psql_b->{run}, $psql_b->{timeout}, \$psql_b->{stdout}, qr/f/); + ok(1, "$io_method: blocking start buffer io, no need to start io"); + + # buffer is valid now, make it invalid again + $psql_a->query_safe(qq(SELECT buffer_create_toy('tbl_ok', 1);)); + + + ### Verify behavior for temporary tables + + # Can't unfortunately share the code with the normal table case, there are + # too many behavioral differences. + + # create a buffer we can play around with + $psql_a->query_safe( + qq( +CREATE TEMPORARY TABLE tmp_ok(data int not null); +INSERT INTO tmp_ok SELECT generate_series(1, 10000); +)); + $buf_id = $psql_a->query_safe(qq(SELECT buffer_create_toy('tmp_ok', 3);)); + + # check that one backend can perform StartLocalBufferIO + psql_like( + $io_method, + $psql_a, + "first StartLocalBufferIO", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>true);), + qr/^t$/, + qr/^$/); + + # Because local buffers don't use IO_IN_PROGRESS, a second StartLocalBufferIO + # succeeds as well. This test mostly serves as a documentation of that + # fact. If we had actually started IO, it'd be different. + psql_like( + $io_method, + $psql_a, + "second StartLocalBufferIO succeeds, same session", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>true);), + qr/^t$/, + qr/^$/); + + # Terminate the IO again, without marking it as a success + $psql_a->query_safe( + qq(SELECT buffer_call_terminate_io($buf_id, for_input=>true, succeed=>false, io_error=>false, release_aio=>false);) + ); + psql_like( + $io_method, + $psql_a, + "StartLocalBufferIO after not marking valid succeeds, same session", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>true);), + qr/^t$/, + qr/^$/); + + # Terminate the IO again, marking it as a success + $psql_a->query_safe( + qq(SELECT buffer_call_terminate_io($buf_id, for_input=>true, succeed=>true, io_error=>false, release_aio=>false);) + ); + + # Now another StartLocalBufferIO should fail, this time because the buffer + # is already valid. + psql_like( + $io_method, + $psql_a, + "StartLocalBufferIO after marking valid fails", + qq(SELECT buffer_call_start_io($buf_id, for_input=>true, nowait=>false);), + qr/^f$/, + qr/^$/); + + $psql_a->quit(); + $psql_b->quit(); +} + +# Test that if the backend issuing a read doesn't wait for the IO's +# completion, another backend can complete the IO +sub test_complete_foreign +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql_a = $node->background_psql('postgres', on_error_stop => 0); + my $psql_b = $node->background_psql('postgres', on_error_stop => 0); + + # Issue IO without waiting for completion, then sleep + $psql_a->query_safe( + qq(SELECT read_rel_block_ll('tbl_ok', 1, wait_complete=>false);)); + + # Check that another backend can read the relevant block + psql_like( + $io_method, + $psql_b, + "completing read started by sleeping backend", + qq(SELECT count(*) FROM tbl_ok WHERE ctid = '(1,1)' LIMIT 1), + qr/^1$/, + qr/^$/); + + # Issue IO without waiting for completion, then exit. + $psql_a->query_safe( + qq(SELECT read_rel_block_ll('tbl_ok', 1, wait_complete=>false);)); + $psql_a->reconnect_and_clear(); + + # Check that another backend can read the relevant block. This verifies + # that the exiting backend left the AIO in a sane state. + psql_like( + $io_method, + $psql_b, + "read buffer started by exited backend", + qq(SELECT count(*) FROM tbl_ok WHERE ctid = '(1,1)' LIMIT 1), + qr/^1$/, + qr/^$/); + + # Read a tbl_corr block, then sleep. The other session will retry the IO + # and also fail. The easiest thing to verify that seems to be to check + # that both are in the log. + my $log_location = -s $node->logfile; + $psql_a->query_safe( + qq(SELECT read_rel_block_ll('tbl_corr', 1, wait_complete=>false);)); + + psql_like( + $io_method, + $psql_b, + "completing read of tbl_corr block started by other backend", + qq(SELECT count(*) FROM tbl_corr WHERE ctid = '(1,1)' LIMIT 1), + qr/^$/, + qr/invalid page in block/); + + # The log message issued for the read_rel_block_ll() should be logged as a LOG + $node->wait_for_log(qr/LOG[^\n]+invalid page in/, $log_location); + ok(1, + "$io_method: completing read of tbl_corr block started by other backend: LOG message for background read" + ); + + # But for the SELECT, it should be an ERROR + $log_location = + $node->wait_for_log(qr/ERROR[^\n]+invalid page in/, $log_location); + ok(1, + "$io_method: completing read of tbl_corr block started by other backend: ERROR message for foreground read" + ); + + $psql_a->quit(); + $psql_b->quit(); +} + +# Test that we deal correctly with FDs being closed while IO is in progress +sub test_close_fd +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + psql_like( + $io_method, + $psql, + "close all FDs after read, waiting for results", + qq( + SELECT read_rel_block_ll('tbl_ok', 1, + wait_complete=>true, + batchmode_enter=>true, + smgrreleaseall=>true, + batchmode_exit=>true + );), + qr/^$/, + qr/^$/); + + psql_like( + $io_method, + $psql, + "close all FDs after read, no waiting", + qq( + SELECT read_rel_block_ll('tbl_ok', 1, + wait_complete=>false, + batchmode_enter=>true, + smgrreleaseall=>true, + batchmode_exit=>true + );), + qr/^$/, + qr/^$/); + + # Check that another backend can read the relevant block + psql_like( + $io_method, + $psql, + "close all FDs after read, no waiting, query works", + qq(SELECT count(*) FROM tbl_ok WHERE ctid = '(1,1)' LIMIT 1), + qr/^1$/, + qr/^$/); + + $psql->quit(); +} + +# Tests using injection points. Mostly to exercise hard IO errors that are +# hard to trigger without using injection points. +sub test_inject +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + # injected what we'd expect + $psql->query_safe(qq(SELECT inj_io_short_read_attach(8192);)); + $psql->query_safe(qq(SELECT invalidate_rel_block('tbl_ok', 2);)); + psql_like( + $io_method, $psql, + "injection point not triggering failure", + qq(SELECT count(*) FROM tbl_ok WHERE ctid = '(2, 1)'), + qr/^1$/, qr/^$/); + + # injected a read shorter than a single block, expecting error + $psql->query_safe(qq(SELECT inj_io_short_read_attach(17);)); + $psql->query_safe(qq(SELECT invalidate_rel_block('tbl_ok', 2);)); + psql_like( + $io_method, + $psql, + "single block short read fails", + qq(SELECT count(*) FROM tbl_ok WHERE ctid = '(2, 1)'), + qr/^$/, + qr/ERROR:.*could not read blocks 2\.\.2 in file "base\/.*": read only 0 of 8192 bytes/ + ); + + # shorten multi-block read to a single block, should retry + my $inval_query = qq(SELECT invalidate_rel_block('tbl_ok', 0); +SELECT invalidate_rel_block('tbl_ok', 1); +SELECT invalidate_rel_block('tbl_ok', 2); +SELECT invalidate_rel_block('tbl_ok', 3); +/* gap */ +SELECT invalidate_rel_block('tbl_ok', 5); +SELECT invalidate_rel_block('tbl_ok', 6); +SELECT invalidate_rel_block('tbl_ok', 7); +SELECT invalidate_rel_block('tbl_ok', 8);); + + $psql->query_safe($inval_query); + $psql->query_safe(qq(SELECT inj_io_short_read_attach(8192);)); + psql_like( + $io_method, $psql, + "multi block short read (1 block) is retried", + qq(SELECT count(*) FROM tbl_ok), + qr/^10000$/, qr/^$/); + + # shorten multi-block read to two blocks, should retry + $psql->query_safe($inval_query); + $psql->query_safe(qq(SELECT inj_io_short_read_attach(8192*2);)); + + psql_like( + $io_method, $psql, + "multi block short read (2 blocks) is retried", + qq(SELECT count(*) FROM tbl_ok), + qr/^10000$/, qr/^$/); + + # verify that page verification errors are detected even as part of a + # shortened multi-block read (tbl_corr, block 1 is corrupted) + $psql->query_safe( + qq( +SELECT invalidate_rel_block('tbl_corr', 0); +SELECT invalidate_rel_block('tbl_corr', 1); +SELECT invalidate_rel_block('tbl_corr', 2); +SELECT inj_io_short_read_attach(8192); + )); + + psql_like( + $io_method, + $psql, + "shortened multi-block read detects invalid page", + qq(SELECT count(*) FROM tbl_corr WHERE ctid < '(2, 1)'), + qr/^$/, + qr/ERROR:.*invalid page in block 1 of relation base\/.*/); + + # trigger a hard error, should error out + $psql->query_safe( + qq( +SELECT inj_io_short_read_attach(-errno_from_string('EIO')); +SELECT invalidate_rel_block('tbl_ok', 2); + )); + + psql_like( + $io_method, + $psql, + "first hard IO error is reported", + qq(SELECT count(*) FROM tbl_ok), + qr/^$/, + qr!ERROR:.*could not read blocks 2\.\.2 in file "base/.*": (?:I/O|Input/output) error! + ); + + psql_like( + $io_method, + $psql, + "second hard IO error is reported", + qq(SELECT count(*) FROM tbl_ok), + qr/^$/, + qr!ERROR:.*could not read blocks 2\.\.2 in file "base/.*": (?:I/O|Input/output) error! + ); + + $psql->query_safe(qq(SELECT inj_io_short_read_detach())); + + # now the IO should be ok. + psql_like( + $io_method, $psql, + "recovers after hard error", + qq(SELECT count(*) FROM tbl_ok), + qr/^10000$/, qr/^$/); + + # trigger a different hard error, should error out + $psql->query_safe( + qq( +SELECT inj_io_short_read_attach(-errno_from_string('EROFS')); +SELECT invalidate_rel_block('tbl_ok', 2); + )); + psql_like( + $io_method, + $psql, + "different hard IO error is reported", + qq(SELECT count(*) FROM tbl_ok), + qr/^$/, + qr/ERROR:.*could not read blocks 2\.\.2 in file \"base\/.*\": Read-only file system/ + ); + $psql->query_safe(qq(SELECT inj_io_short_read_detach())); + + $psql->quit(); +} + +# Tests using injection points, only for io_method=worker. +# +# io_method=worker has the special case of needing to reopen files. That can +# in theory fail, because the file could be gone. That's a hard path to test +# for real, so we use an injection point to trigger it. +sub test_inject_worker +{ + my $io_method = shift; + my $node = shift; + my ($ret, $output); + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + # trigger a failure to reopen, should error out, but should recover + $psql->query_safe( + qq( +SELECT inj_io_reopen_attach(); +SELECT invalidate_rel_block('tbl_ok', 1); + )); + + psql_like( + $io_method, + $psql, + "failure to open: detected", + qq(SELECT count(*) FROM tbl_ok), + qr/^$/, + qr/ERROR:.*could not read blocks 1\.\.1 in file "base\/.*": No such file or directory/ + ); + + $psql->query_safe(qq(SELECT inj_io_reopen_detach();)); + + # check that we indeed recover + psql_like( + $io_method, $psql, + "failure to open: recovers", + qq(SELECT count(*) FROM tbl_ok), + qr/^10000$/, qr/^$/); + + $psql->quit(); +} + +# Verify that we handle a relation getting removed (due to a rollback or a +# DROP TABLE) while IO is ongoing for that table. +sub test_invalidate +{ + my $io_method = shift; + my $node = shift; + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + foreach my $persistency (qw(normal unlogged temporary)) + { + my $sql_persistency = $persistency eq 'normal' ? '' : $persistency; + my $tblname = $persistency . '_transactional'; + + my $create_sql = qq( +CREATE $sql_persistency TABLE $tblname (id int not null, data text not null) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO $tblname(id, data) SELECT generate_series(1, 10000) as id, repeat('a', 200); +); + + # Verify that outstanding read IO does not cause problems with + # AbortTransaction -> smgrDoPendingDeletes -> smgrdounlinkall -> ... + # -> Invalidate[Local]Buffer. + $psql->query_safe("BEGIN; $create_sql;"); + $psql->query_safe( + qq( +SELECT read_rel_block_ll('$tblname', 1, wait_complete=>false); +)); + psql_like( + $io_method, + $psql, + "rollback of newly created $persistency table with outstanding IO", + qq(ROLLBACK), + qr/^$/, + qr/^$/); + + # Verify that outstanding read IO does not cause problems with + # CommitTransaction -> smgrDoPendingDeletes -> smgrdounlinkall -> ... + # -> Invalidate[Local]Buffer. + $psql->query_safe("BEGIN; $create_sql; COMMIT;"); + $psql->query_safe( + qq( +BEGIN; +SELECT read_rel_block_ll('$tblname', 1, wait_complete=>false); +)); + + psql_like( + $io_method, $psql, + "drop $persistency table with outstanding IO", + qq(DROP TABLE $tblname), + qr/^$/, qr/^$/); + + psql_like($io_method, $psql, + "commit after drop $persistency table with outstanding IO", + qq(COMMIT), qr/^$/, qr/^$/); + } + + $psql->quit(); +} + +# Test behavior related to ZERO_ON_ERROR and zero_damaged_pages +sub test_zero +{ + my $io_method = shift; + my $node = shift; + + my $psql_a = $node->background_psql('postgres', on_error_stop => 0); + my $psql_b = $node->background_psql('postgres', on_error_stop => 0); + + foreach my $persistency (qw(normal temporary)) + { + my $sql_persistency = $persistency eq 'normal' ? '' : $persistency; + + $psql_a->query_safe( + qq( +CREATE $sql_persistency TABLE tbl_zero(id int) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO tbl_zero SELECT generate_series(1, 10000); +)); + + $psql_a->query_safe( + qq( +SELECT modify_rel_block('tbl_zero', 0, corrupt_header=>true); +)); + + # Check that page validity errors are detected + psql_like( + $io_method, + $psql_a, + "$persistency: test reading of invalid block 0", + qq( +SELECT read_rel_block_ll('tbl_zero', 0, zero_on_error=>false)), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 0 of relation base\/.*\/.*$/ + ); + + # Check that page validity errors are zeroed + psql_like( + $io_method, + $psql_a, + "$persistency: test zeroing of invalid block 0", + qq( +SELECT read_rel_block_ll('tbl_zero', 0, zero_on_error=>true)), + qr/^$/, + qr/^psql::\d+: WARNING: invalid page in block 0 of relation base\/.*\/.*; zeroing out page$/ + ); + + # And that once the corruption is fixed, we can read again + $psql_a->query( + qq( +SELECT modify_rel_block('tbl_zero', 0, zero=>true); +)); + $psql_a->{stderr} = ''; + + psql_like( + $io_method, + $psql_a, + "$persistency: test re-read of block 0", + qq( +SELECT read_rel_block_ll('tbl_zero', 0, zero_on_error=>false)), + qr/^$/, + qr/^$/); + + # Check a page validity error in another block, to ensure we report + # the correct block number + $psql_a->query_safe( + qq( +SELECT modify_rel_block('tbl_zero', 3, corrupt_header=>true); +)); + psql_like( + $io_method, + $psql_a, + "$persistency: test zeroing of invalid block 3", + qq(SELECT read_rel_block_ll('tbl_zero', 3, zero_on_error=>true);), + qr/^$/, + qr/^psql::\d+: WARNING: invalid page in block 3 of relation base\/.*\/.*; zeroing out page$/ + ); + + + # Check one read reporting multiple invalid blocks + $psql_a->query_safe( + qq( +SELECT modify_rel_block('tbl_zero', 2, corrupt_header=>true); +SELECT modify_rel_block('tbl_zero', 3, corrupt_header=>true); +)); + # First test error + psql_like( + $io_method, + $psql_a, + "$persistency: test reading of invalid block 2,3 in larger read", + qq(SELECT read_rel_block_ll('tbl_zero', 1, nblocks=>4, zero_on_error=>false)), + qr/^$/, + qr/^psql::\d+: ERROR: 2 invalid pages among blocks 1..4 of relation base\/.*\/.*\nDETAIL: Block 2 held first invalid page\.\nHINT:[^\n]+$/ + ); + + # Then test zeroing via ZERO_ON_ERROR flag + psql_like( + $io_method, + $psql_a, + "$persistency: test zeroing of invalid block 2,3 in larger read, ZERO_ON_ERROR", + qq(SELECT read_rel_block_ll('tbl_zero', 1, nblocks=>4, zero_on_error=>true)), + qr/^$/, + qr/^psql::\d+: WARNING: zeroing out 2 invalid pages among blocks 1..4 of relation base\/.*\/.*\nDETAIL: Block 2 held first zeroed page\.\nHINT:[^\n]+$/ + ); + + # Then test zeroing via zero_damaged_pages + psql_like( + $io_method, + $psql_a, + "$persistency: test zeroing of invalid block 2,3 in larger read, zero_damaged_pages", + qq( +BEGIN; +SET LOCAL zero_damaged_pages = true; +SELECT read_rel_block_ll('tbl_zero', 1, nblocks=>4, zero_on_error=>false) +COMMIT; +), + qr/^$/, + qr/^psql::\d+: WARNING: zeroing out 2 invalid pages among blocks 1..4 of relation base\/.*\/.*\nDETAIL: Block 2 held first zeroed page\.\nHINT:[^\n]+$/ + ); + + $psql_a->query_safe(qq(COMMIT)); + + + # Verify that bufmgr.c IO detects page validity errors + $psql_a->query( + qq( +SELECT invalidate_rel_block('tbl_zero', g.i) +FROM generate_series(0, 15) g(i); +SELECT modify_rel_block('tbl_zero', 3, zero=>true); +)); + $psql_a->{stderr} = ''; + + psql_like( + $io_method, + $psql_a, + "$persistency: verify reading zero_damaged_pages=off", + qq( +SELECT count(*) FROM tbl_zero), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 2 of relation base\/.*\/.*$/ + ); + + # Verify that bufmgr.c IO zeroes out pages with page validity errors + psql_like( + $io_method, + $psql_a, + "$persistency: verify zero_damaged_pages=on", + qq( +BEGIN; +SET LOCAL zero_damaged_pages = true; +SELECT count(*) FROM tbl_zero; +COMMIT; +), + qr/^\d+$/, + qr/^psql::\d+: WARNING: invalid page in block 2 of relation base\/.*\/.*$/ + ); + + # Check that warnings/errors about page validity in an IO started by + # session A that session B might complete aren't logged visibly to + # session B. + # + # This will only ever trigger for io_method's like io_uring, that can + # complete IO's in a client backend. But it doesn't seem worth + # restricting to that. + # + # This requires cross-session access to the same relation, hence the + # restriction to non-temporary table. + if ($sql_persistency ne 'temporary') + { + # Create a corruption and then read the block without waiting for + # completion. + $psql_a->query(qq( +SELECT modify_rel_block('tbl_zero', 1, corrupt_header=>true); +SELECT read_rel_block_ll('tbl_zero', 1, wait_complete=>false, zero_on_error=>true) +)); + + psql_like( + $io_method, + $psql_b, + "$persistency: test completing read by other session doesn't generate warning", + qq(SELECT count(*) > 0 FROM tbl_zero;), + qr/^t$/, qr/^$/); + } + + # Clean up + $psql_a->query_safe( + qq( +DROP TABLE tbl_zero; +)); + } + + $psql_a->{stderr} = ''; + + $psql_a->quit(); + $psql_b->quit(); +} + +# Test that we detect checksum failures and report them +sub test_checksum +{ + my $io_method = shift; + my $node = shift; + + my $psql_a = $node->background_psql('postgres', on_error_stop => 0); + + $psql_a->query_safe( + qq( +CREATE TABLE tbl_normal(id int) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO tbl_normal SELECT generate_series(1, 5000); +SELECT modify_rel_block('tbl_normal', 3, corrupt_checksum=>true); + +CREATE TEMPORARY TABLE tbl_temp(id int) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO tbl_temp SELECT generate_series(1, 5000); +SELECT modify_rel_block('tbl_temp', 3, corrupt_checksum=>true); +SELECT modify_rel_block('tbl_temp', 4, corrupt_checksum=>true); +)); + + # To be able to test checksum failures on shared rels we need a shared rel + # with invalid pages - which is a bit scary. pg_shseclabel seems like a + # good bet, as it's not accessed in a default configuration. + $psql_a->query_safe( + qq( +SELECT grow_rel('pg_shseclabel', 4); +SELECT modify_rel_block('pg_shseclabel', 2, corrupt_checksum=>true); +SELECT modify_rel_block('pg_shseclabel', 3, corrupt_checksum=>true); +)); + + + # Check that page validity errors are detected, checksums stats increase, normal rel + my ($cs_count_before, $cs_ts_before) = + checksum_failures($psql_a, 'postgres'); + psql_like( + $io_method, + $psql_a, + "normal rel: test reading of invalid block 3", + qq( +SELECT read_rel_block_ll('tbl_normal', 3, nblocks=>1, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 3 of relation base\/\d+\/\d+$/ + ); + + my ($cs_count_after, $cs_ts_after) = + checksum_failures($psql_a, 'postgres'); + + cmp_ok($cs_count_before + 1, + '<=', $cs_count_after, + "$io_method: normal rel: checksum count increased"); + cmp_ok($cs_ts_after, 'ne', '', + "$io_method: normal rel: checksum timestamp is not null"); + + + # Check that page validity errors are detected, checksums stats increase, temp rel + ($cs_count_after, $cs_ts_after) = checksum_failures($psql_a, 'postgres'); + psql_like( + $io_method, + $psql_a, + "temp rel: test reading of invalid block 4, valid block 5", + qq( +SELECT read_rel_block_ll('tbl_temp', 4, nblocks=>2, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 4 of relation base\/\d+\/t\d+_\d+$/ + ); + + ($cs_count_after, $cs_ts_after) = checksum_failures($psql_a, 'postgres'); + + cmp_ok($cs_count_before + 1, + '<=', $cs_count_after, + "$io_method: temp rel: checksum count increased"); + cmp_ok($cs_ts_after, 'ne', '', + "$io_method: temp rel: checksum timestamp is not null"); + + + # Check that page validity errors are detected, checksums stats increase, shared rel + ($cs_count_before, $cs_ts_after) = checksum_failures($psql_a); + psql_like( + $io_method, + $psql_a, + "shared rel: reading of invalid blocks 2+3", + qq( +SELECT read_rel_block_ll('pg_shseclabel', 2, nblocks=>2, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: ERROR: 2 invalid pages among blocks 2..3 of relation global\/\d+\nDETAIL: Block 2 held first invalid page\.\nHINT:[^\n]+$/ + ); + + ($cs_count_after, $cs_ts_after) = checksum_failures($psql_a); + + cmp_ok($cs_count_before + 1, + '<=', $cs_count_after, + "$io_method: shared rel: checksum count increased"); + cmp_ok($cs_ts_after, 'ne', '', + "$io_method: shared rel: checksum timestamp is not null"); + + + # and restore sanity + $psql_a->query( + qq( +SELECT modify_rel_block('pg_shseclabel', 1, zero=>true); +DROP TABLE tbl_normal; +)); + $psql_a->{stderr} = ''; + + $psql_a->quit(); +} + +# Verify checksum handling when creating database from a database with an +# invalid block. This also serves as a minimal check that cross-database IO is +# handled reasonably. +sub test_checksum_createdb +{ + my $io_method = shift; + my $node = shift; + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + $node->safe_psql('postgres', + 'CREATE DATABASE regression_createdb_source'); + + $node->safe_psql( + 'regression_createdb_source', qq( +CREATE EXTENSION test_aio; +CREATE TABLE tbl_cs_fail(data int not null) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO tbl_cs_fail SELECT generate_series(1, 1000); +SELECT modify_rel_block('tbl_cs_fail', 1, corrupt_checksum=>true); +)); + + my $createdb_sql = qq( +CREATE DATABASE regression_createdb_target +TEMPLATE regression_createdb_source +STRATEGY wal_log; +); + + # Verify that CREATE DATABASE of an invalid database fails and is + # accounted for accurately. + # + # Note: On windows additional WARNING messages might be printed, due to + # "some useless files may be left behind" warnings. While we probably + # should prevent those from occurring, they're independent of AIO, so we + # shouldn't fail because of them here. + my ($cs_count_before, $cs_ts_before) = + checksum_failures($psql, 'regression_createdb_source'); + psql_like( + $io_method, + $psql, + "create database w/ wal strategy, invalid source", + $createdb_sql, + qr/^$/, + qr/psql::\d+: ERROR: invalid page in block 1 of relation base\/\d+\/\d+$/ + ); + my ($cs_count_after, $cs_ts_after) = + checksum_failures($psql, 'regression_createdb_source'); + cmp_ok($cs_count_before + 1, '<=', $cs_count_after, + "$io_method: create database w/ wal strategy, invalid source: checksum count increased" + ); + + # Verify that CREATE DATABASE of the fixed database succeeds. + $node->safe_psql( + 'regression_createdb_source', qq( +SELECT modify_rel_block('tbl_cs_fail', 1, zero=>true); +)); + psql_like($io_method, $psql, + "create database w/ wal strategy, valid source", + $createdb_sql, qr/^$/, qr/^$/); + + $psql->quit(); +} + +# Test that we detect checksum failures and report them +# +# In several places we make sure that the server log actually contains +# individual information for each block involved in the IO. +sub test_ignore_checksum +{ + my $io_method = shift; + my $node = shift; + + my $psql = $node->background_psql('postgres', on_error_stop => 0); + + # Test setup + $psql->query_safe( + qq( +CREATE TABLE tbl_cs_fail(id int) WITH (AUTOVACUUM_ENABLED = false); +INSERT INTO tbl_cs_fail SELECT generate_series(1, 10000); +)); + + my $count_sql = "SELECT count(*) FROM tbl_cs_fail"; + my $invalidate_sql = qq( +SELECT invalidate_rel_block('tbl_cs_fail', g.i) +FROM generate_series(0, 6) g(i); +); + + my $expect = $psql->query_safe($count_sql); + + + # Very basic tests for ignore_checksum_failure=off / on + + $psql->query_safe( + qq( +SELECT modify_rel_block('tbl_cs_fail', 1, corrupt_checksum=>true); +SELECT modify_rel_block('tbl_cs_fail', 5, corrupt_checksum=>true); +SELECT modify_rel_block('tbl_cs_fail', 6, corrupt_checksum=>true); +)); + + $psql->query_safe($invalidate_sql); + psql_like($io_method, $psql, + "reading block w/ wrong checksum with ignore_checksum_failure=off fails", + $count_sql, qr/^$/, qr/ERROR: invalid page in block/); + + $psql->query_safe("SET ignore_checksum_failure=on"); + + $psql->query_safe($invalidate_sql); + psql_like($io_method, $psql, + "reading block w/ wrong checksum with ignore_checksum_failure=off succeeds", + $count_sql, + qr/^$expect$/, + qr/WARNING: ignoring (checksum failure|\d checksum failures)/); + + + # Verify that ignore_checksum_failure=off works in multi-block reads + + $psql->query_safe( + qq( +SELECT modify_rel_block('tbl_cs_fail', 2, zero=>true); +SELECT modify_rel_block('tbl_cs_fail', 3, corrupt_checksum=>true); +SELECT modify_rel_block('tbl_cs_fail', 4, corrupt_header=>true); +)); + + my $log_location = -s $node->logfile; + psql_like( + $io_method, + $psql, + "test reading of checksum failed block 3, with ignore", + qq( +SELECT read_rel_block_ll('tbl_cs_fail', 3, nblocks=>1, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: WARNING: ignoring checksum failure in block 3/ + ); + + # Check that the log contains a LOG message about the failure + $log_location = + $node->wait_for_log(qr/LOG: ignoring checksum failure/, $log_location); + + # check that we error + psql_like( + $io_method, + $psql, + "test reading of valid block 2, checksum failed 3, invalid 4, zero=false with ignore", + qq( +SELECT read_rel_block_ll('tbl_cs_fail', 2, nblocks=>3, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 4 of relation base\/\d+\/\d+$/ + ); + + # Test multi-block read with different problems in different blocks + $psql->query( + qq( +SELECT modify_rel_block('tbl_cs_fail', 1, zero=>true); +SELECT modify_rel_block('tbl_cs_fail', 2, corrupt_checksum=>true); +SELECT modify_rel_block('tbl_cs_fail', 3, corrupt_checksum=>true, corrupt_header=>true); +SELECT modify_rel_block('tbl_cs_fail', 4, corrupt_header=>true); +SELECT modify_rel_block('tbl_cs_fail', 5, corrupt_header=>true); +)); + $psql->{stderr} = ''; + + $log_location = -s $node->logfile; + psql_like( + $io_method, + $psql, + "test reading of valid block 1, checksum failed 2, 3, invalid 3-5, zero=true", + qq( +SELECT read_rel_block_ll('tbl_cs_fail', 1, nblocks=>5, zero_on_error=>true);), + qr/^$/, + qr/^psql::\d+: WARNING: zeroing 3 page\(s\) and ignoring 2 checksum failure\(s\) among blocks 1..5 of relation/ + ); + + + # Unfortunately have to scan the whole log since determining $log_location + # above in each of the tests, as wait_for_log() returns the size of the + # file. + + $node->wait_for_log(qr/LOG: ignoring checksum failure in block 2/, + $log_location); + ok(1, "$io_method: found information about checksum failure in block 2"); + + $node->wait_for_log(qr/LOG: invalid page in block 3 of relation base.*; zeroing out page/, + $log_location); + ok(1, "$io_method: found information about invalid page in block 3"); + + $node->wait_for_log(qr/LOG: invalid page in block 4 of relation base.*; zeroing out page/, + $log_location); + ok(1, "$io_method: found information about checksum failure in block 4"); + + $node->wait_for_log(qr/LOG: invalid page in block 5 of relation base.*; zeroing out page/, + $log_location); + ok(1, "$io_method: found information about checksum failure in block 5"); + + + # Reading a page with both an invalid header and an invalid checksum + $psql->query( + qq( +SELECT modify_rel_block('tbl_cs_fail', 3, corrupt_checksum=>true, corrupt_header=>true); +)); + $psql->{stderr} = ''; + + psql_like( + $io_method, + $psql, + "test reading of block with both invalid header and invalid checksum, zero=false", + qq( +SELECT read_rel_block_ll('tbl_cs_fail', 3, nblocks=>1, zero_on_error=>false);), + qr/^$/, + qr/^psql::\d+: ERROR: invalid page in block 3 of relation/ + ); + + psql_like( + $io_method, + $psql, + "test reading of block 3 with both invalid header and invalid checksum, zero=true", + qq( +SELECT read_rel_block_ll('tbl_cs_fail', 3, nblocks=>1, zero_on_error=>true);), + qr/^$/, + qr/^psql::\d+: WARNING: invalid page in block 3 of relation base\/.*; zeroing out page/ + ); + + + $psql->quit(); +} + + +# Run all tests that are supported for all io_methods +sub test_generic +{ + my $io_method = shift; + my $node = shift; + + is($node->safe_psql('postgres', 'SHOW io_method'), + $io_method, "$io_method: io_method set correctly"); + + $node->safe_psql( + 'postgres', qq( +CREATE EXTENSION test_aio; +CREATE TABLE tbl_corr(data int not null) WITH (AUTOVACUUM_ENABLED = false); +CREATE TABLE tbl_ok(data int not null) WITH (AUTOVACUUM_ENABLED = false); + +INSERT INTO tbl_corr SELECT generate_series(1, 10000); +INSERT INTO tbl_ok SELECT generate_series(1, 10000); +SELECT grow_rel('tbl_corr', 16); +SELECT grow_rel('tbl_ok', 16); + +SELECT modify_rel_block('tbl_corr', 1, corrupt_header=>true); +CHECKPOINT; +)); + + test_handle($io_method, $node); + test_io_error($io_method, $node); + test_batchmode($io_method, $node); + test_startwait_io($io_method, $node); + test_complete_foreign($io_method, $node); + test_close_fd($io_method, $node); + test_invalidate($io_method, $node); + test_zero($io_method, $node); + test_checksum($io_method, $node); + test_ignore_checksum($io_method, $node); + test_checksum_createdb($io_method, $node); + + SKIP: + { + skip 'Injection points not supported by this build', 1 + unless $ENV{enable_injection_points} eq 'yes'; + test_inject($io_method, $node); + } +} diff --git a/src/test/modules/test_aio/t/002_io_workers.pl b/src/test/modules/test_aio/t/002_io_workers.pl new file mode 100644 index 0000000000000..af5fae15ea78e --- /dev/null +++ b/src/test/modules/test_aio/t/002_io_workers.pl @@ -0,0 +1,125 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; +use List::Util qw(shuffle); + + +my $node = PostgreSQL::Test::Cluster->new('worker'); +$node->init(); +$node->append_conf( + 'postgresql.conf', qq( +io_method=worker +)); + +$node->start(); + +# Test changing the number of I/O worker processes while also evaluating the +# handling of their termination. +test_number_of_io_workers_dynamic($node); + +$node->stop(); + +done_testing(); + + +sub test_number_of_io_workers_dynamic +{ + my $node = shift; + + my $prev_worker_count = $node->safe_psql('postgres', 'SHOW io_workers'); + + # Verify that worker count can't be set to 0 + change_number_of_io_workers($node, 0, $prev_worker_count, 1); + + # Verify that worker count can't be set to 33 (above the max) + change_number_of_io_workers($node, 33, $prev_worker_count, 1); + + # Try changing IO workers to a random value and verify that the worker + # count ends up as expected. Always test the min/max of workers. + # + # Valid range for io_workers is [1, 32]. 8 tests in total seems + # reasonable. + my @io_workers_range = shuffle(1 ... 32); + foreach my $worker_count (1, 32, @io_workers_range[ 0, 6 ]) + { + $prev_worker_count = + change_number_of_io_workers($node, $worker_count, + $prev_worker_count, 0); + } +} + +sub change_number_of_io_workers +{ + my $node = shift; + my $worker_count = shift; + my $prev_worker_count = shift; + my $expect_failure = shift; + my ($result, $stdout, $stderr); + + ($result, $stdout, $stderr) = + $node->psql('postgres', "ALTER SYSTEM SET io_workers = $worker_count"); + $node->safe_psql('postgres', 'SELECT pg_reload_conf()'); + + if ($expect_failure) + { + ok( $stderr =~ + /$worker_count is outside the valid range for parameter "io_workers"/, + "updating number of io_workers to $worker_count failed, as expected" + ); + + return $prev_worker_count; + } + else + { + is( $node->safe_psql('postgres', 'SHOW io_workers'), + $worker_count, + "updating number of io_workers from $prev_worker_count to $worker_count" + ); + + check_io_worker_count($node, $worker_count); + terminate_io_worker($node, $worker_count); + check_io_worker_count($node, $worker_count); + + return $worker_count; + } +} + +sub terminate_io_worker +{ + my $node = shift; + my $worker_count = shift; + my ($pid, $ret); + + # Select a random io worker + $pid = $node->safe_psql( + 'postgres', + qq(SELECT pid FROM pg_stat_activity WHERE + backend_type = 'io worker' ORDER BY RANDOM() LIMIT 1)); + + # terminate IO worker with SIGINT + is(PostgreSQL::Test::Utils::system_log('pg_ctl', 'kill', 'INT', $pid), + 0, "random io worker process signalled with INT"); + + # Check that worker exits + ok( $node->poll_query_until( + 'postgres', + qq(SELECT COUNT(*) FROM pg_stat_activity WHERE pid = $pid), '0'), + "random io worker process exited after signal"); +} + +sub check_io_worker_count +{ + my $node = shift; + my $worker_count = shift; + + ok( $node->poll_query_until( + 'postgres', + qq(SELECT COUNT(*) FROM pg_stat_activity WHERE backend_type = 'io worker'), + $worker_count), + "io worker count is $worker_count"); +} diff --git a/src/test/modules/test_aio/test_aio--1.0.sql b/src/test/modules/test_aio/test_aio--1.0.sql new file mode 100644 index 0000000000000..e495481c41e43 --- /dev/null +++ b/src/test/modules/test_aio/test_aio--1.0.sql @@ -0,0 +1,108 @@ +/* src/test/modules/test_aio/test_aio--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION test_aio" to load this file. \quit + + +CREATE FUNCTION errno_from_string(sym text) +RETURNS pg_catalog.int4 STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + + +CREATE FUNCTION grow_rel(rel regclass, nblocks int) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + + +CREATE FUNCTION modify_rel_block(rel regclass, blockno int, + zero bool DEFAULT false, + corrupt_header bool DEFAULT false, + corrupt_checksum bool DEFAULT false) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION read_rel_block_ll( + rel regclass, + blockno int, + nblocks int DEFAULT 1, + wait_complete bool DEFAULT true, + batchmode_enter bool DEFAULT false, + smgrreleaseall bool DEFAULT false, + batchmode_exit bool DEFAULT false, + zero_on_error bool DEFAULT false) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION invalidate_rel_block(rel regclass, blockno int) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION buffer_create_toy(rel regclass, blockno int4) +RETURNS pg_catalog.int4 STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION buffer_call_start_io(buffer int, for_input bool, nowait bool) +RETURNS pg_catalog.bool STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION buffer_call_terminate_io(buffer int, for_input bool, succeed bool, io_error bool, release_aio bool) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + + + +/* + * Handle related functions + */ +CREATE FUNCTION handle_get_and_error() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION handle_get_twice() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION handle_get() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION handle_get_release() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION handle_release_last() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + + +/* + * Batchmode related functions + */ +CREATE FUNCTION batch_start() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION batch_end() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + + + +/* + * Injection point related functions + */ +CREATE FUNCTION inj_io_short_read_attach(result int) +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION inj_io_short_read_detach() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION inj_io_reopen_attach() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION inj_io_reopen_detach() +RETURNS pg_catalog.void STRICT +AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_aio/test_aio.c b/src/test/modules/test_aio/test_aio.c new file mode 100644 index 0000000000000..c55cf6c0aac05 --- /dev/null +++ b/src/test/modules/test_aio/test_aio.c @@ -0,0 +1,810 @@ +/*------------------------------------------------------------------------- + * + * test_aio.c + * Helpers to write tests for AIO + * + * This module provides interface functions for C functionality to SQL, to + * make it possible to test AIO related behavior in a targeted way from SQL. + * It'd not generally be safe to export these functions to SQL, but for a test + * that's fine. + * + * Copyright (c) 2020-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/test_aio/test_aio.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/relation.h" +#include "fmgr.h" +#include "storage/aio.h" +#include "storage/aio_internal.h" +#include "storage/buf_internals.h" +#include "storage/bufmgr.h" +#include "storage/checksum.h" +#include "storage/ipc.h" +#include "storage/lwlock.h" +#include "utils/builtins.h" +#include "utils/injection_point.h" +#include "utils/rel.h" + + +PG_MODULE_MAGIC; + + +typedef struct InjIoErrorState +{ + bool enabled_short_read; + bool enabled_reopen; + + bool short_read_result_set; + int short_read_result; +} InjIoErrorState; + +static InjIoErrorState *inj_io_error_state; + +/* Shared memory init callbacks */ +static shmem_request_hook_type prev_shmem_request_hook = NULL; +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; + + +static PgAioHandle *last_handle; + + + +static void +test_aio_shmem_request(void) +{ + if (prev_shmem_request_hook) + prev_shmem_request_hook(); + + RequestAddinShmemSpace(sizeof(InjIoErrorState)); +} + +static void +test_aio_shmem_startup(void) +{ + bool found; + + if (prev_shmem_startup_hook) + prev_shmem_startup_hook(); + + /* Create or attach to the shared memory state */ + LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); + + inj_io_error_state = ShmemInitStruct("injection_points", + sizeof(InjIoErrorState), + &found); + + if (!found) + { + /* First time through, initialize */ + inj_io_error_state->enabled_short_read = false; + inj_io_error_state->enabled_reopen = false; + +#ifdef USE_INJECTION_POINTS + InjectionPointAttach("aio-process-completion-before-shared", + "test_aio", + "inj_io_short_read", + NULL, + 0); + InjectionPointLoad("aio-process-completion-before-shared"); + + InjectionPointAttach("aio-worker-after-reopen", + "test_aio", + "inj_io_reopen", + NULL, + 0); + InjectionPointLoad("aio-worker-after-reopen"); + +#endif + } + else + { + /* + * Pre-load the injection points now, so we can call them in a + * critical section. + */ +#ifdef USE_INJECTION_POINTS + InjectionPointLoad("aio-process-completion-before-shared"); + InjectionPointLoad("aio-worker-after-reopen"); + elog(LOG, "injection point loaded"); +#endif + } + + LWLockRelease(AddinShmemInitLock); +} + +void +_PG_init(void) +{ + if (!process_shared_preload_libraries_in_progress) + return; + + prev_shmem_request_hook = shmem_request_hook; + shmem_request_hook = test_aio_shmem_request; + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = test_aio_shmem_startup; +} + + +PG_FUNCTION_INFO_V1(errno_from_string); +Datum +errno_from_string(PG_FUNCTION_ARGS) +{ + const char *sym = text_to_cstring(PG_GETARG_TEXT_PP(0)); + + if (strcmp(sym, "EIO") == 0) + PG_RETURN_INT32(EIO); + else if (strcmp(sym, "EAGAIN") == 0) + PG_RETURN_INT32(EAGAIN); + else if (strcmp(sym, "EINTR") == 0) + PG_RETURN_INT32(EINTR); + else if (strcmp(sym, "ENOSPC") == 0) + PG_RETURN_INT32(ENOSPC); + else if (strcmp(sym, "EROFS") == 0) + PG_RETURN_INT32(EROFS); + + ereport(ERROR, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg_internal("%s is not a supported errno value", sym)); + PG_RETURN_INT32(0); +} + +PG_FUNCTION_INFO_V1(grow_rel); +Datum +grow_rel(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + uint32 nblocks = PG_GETARG_UINT32(1); + Relation rel; +#define MAX_BUFFERS_TO_EXTEND_BY 64 + Buffer victim_buffers[MAX_BUFFERS_TO_EXTEND_BY]; + + rel = relation_open(relid, AccessExclusiveLock); + + while (nblocks > 0) + { + uint32 extend_by_pages; + + extend_by_pages = Min(nblocks, MAX_BUFFERS_TO_EXTEND_BY); + + ExtendBufferedRelBy(BMR_REL(rel), + MAIN_FORKNUM, + NULL, + 0, + extend_by_pages, + victim_buffers, + &extend_by_pages); + + nblocks -= extend_by_pages; + + for (uint32 i = 0; i < extend_by_pages; i++) + { + ReleaseBuffer(victim_buffers[i]); + } + } + + relation_close(rel, NoLock); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(modify_rel_block); +Datum +modify_rel_block(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + BlockNumber blkno = PG_GETARG_UINT32(1); + bool zero = PG_GETARG_BOOL(2); + bool corrupt_header = PG_GETARG_BOOL(3); + bool corrupt_checksum = PG_GETARG_BOOL(4); + Page page = palloc_aligned(BLCKSZ, PG_IO_ALIGN_SIZE, 0); + bool flushed; + Relation rel; + Buffer buf; + PageHeader ph; + + rel = relation_open(relid, AccessExclusiveLock); + + buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, + RBM_ZERO_ON_ERROR, NULL); + + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + + /* + * copy the page to local memory, seems nicer than to directly modify in + * the buffer pool. + */ + memcpy(page, BufferGetPage(buf), BLCKSZ); + + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + + ReleaseBuffer(buf); + + /* + * Don't want to have a buffer in-memory that's marked valid where the + * on-disk contents are invalid. Particularly not if the in-memory buffer + * could be dirty... + * + * While we hold an AEL on the relation nobody else should be able to read + * the buffer in. + * + * NB: This is probably racy, better don't copy this to non-test code. + */ + if (BufferIsLocal(buf)) + InvalidateLocalBuffer(GetLocalBufferDescriptor(-buf - 1), true); + else + EvictUnpinnedBuffer(buf, &flushed); + + /* + * Now modify the page as asked for by the caller. + */ + if (zero) + memset(page, 0, BufferGetPageSize(buf)); + + if (PageIsEmpty(page) && (corrupt_header || corrupt_checksum)) + PageInit(page, BufferGetPageSize(buf), 0); + + ph = (PageHeader) page; + + if (corrupt_header) + ph->pd_special = BLCKSZ + 1; + + if (corrupt_checksum) + { + bool successfully_corrupted = 0; + + /* + * Any single modification of the checksum could just end up being + * valid again, due to e.g. corrupt_header changing the data in a way + * that'd result in the "corrupted" checksum, or the checksum already + * being invalid. Retry in that, unlikely, case. + */ + for (int i = 0; i < 100; i++) + { + uint16 verify_checksum; + uint16 old_checksum; + + old_checksum = ph->pd_checksum; + ph->pd_checksum = old_checksum + 1; + + elog(LOG, "corrupting checksum of blk %u from %u to %u", + blkno, old_checksum, ph->pd_checksum); + + verify_checksum = pg_checksum_page(page, blkno); + if (verify_checksum != ph->pd_checksum) + { + successfully_corrupted = true; + break; + } + } + + if (!successfully_corrupted) + elog(ERROR, "could not corrupt checksum, what's going on?"); + } + else + { + PageSetChecksumInplace(page, blkno); + } + + smgrwrite(RelationGetSmgr(rel), + MAIN_FORKNUM, blkno, page, true); + + relation_close(rel, NoLock); + + PG_RETURN_VOID(); +} + +/* + * Ensures a buffer for rel & blkno is in shared buffers, without actually + * caring about the buffer contents. Used to set up test scenarios. + */ +static Buffer +create_toy_buffer(Relation rel, BlockNumber blkno) +{ + Buffer buf; + BufferDesc *buf_hdr; + uint32 buf_state; + bool was_pinned = false; + + /* place buffer in shared buffers without erroring out */ + buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_ZERO_AND_LOCK, NULL); + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + + if (RelationUsesLocalBuffers(rel)) + { + buf_hdr = GetLocalBufferDescriptor(-buf - 1); + buf_state = pg_atomic_read_u32(&buf_hdr->state); + } + else + { + buf_hdr = GetBufferDescriptor(buf - 1); + buf_state = LockBufHdr(buf_hdr); + } + + /* + * We should be the only backend accessing this buffer. This is just a + * small bit of belt-and-suspenders defense, none of this code should ever + * run in a cluster with real data. + */ + if (BUF_STATE_GET_REFCOUNT(buf_state) > 1) + was_pinned = true; + else + buf_state &= ~(BM_VALID | BM_DIRTY); + + if (RelationUsesLocalBuffers(rel)) + pg_atomic_unlocked_write_u32(&buf_hdr->state, buf_state); + else + UnlockBufHdr(buf_hdr, buf_state); + + if (was_pinned) + elog(ERROR, "toy buffer %d was already pinned", + buf); + + return buf; +} + +/* + * A "low level" read. This does similar things to what + * StartReadBuffers()/WaitReadBuffers() do, but provides more control (and + * less sanity). + */ +PG_FUNCTION_INFO_V1(read_rel_block_ll); +Datum +read_rel_block_ll(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + BlockNumber blkno = PG_GETARG_UINT32(1); + int nblocks = PG_GETARG_INT32(2); + bool wait_complete = PG_GETARG_BOOL(3); + bool batchmode_enter = PG_GETARG_BOOL(4); + bool call_smgrreleaseall = PG_GETARG_BOOL(5); + bool batchmode_exit = PG_GETARG_BOOL(6); + bool zero_on_error = PG_GETARG_BOOL(7); + Relation rel; + Buffer bufs[PG_IOV_MAX]; + BufferDesc *buf_hdrs[PG_IOV_MAX]; + Page pages[PG_IOV_MAX]; + uint8 srb_flags = 0; + PgAioReturn ior; + PgAioHandle *ioh; + PgAioWaitRef iow; + SMgrRelation smgr; + + if (nblocks <= 0 || nblocks > PG_IOV_MAX) + elog(ERROR, "nblocks is out of range"); + + rel = relation_open(relid, AccessExclusiveLock); + + for (int i = 0; i < nblocks; i++) + { + bufs[i] = create_toy_buffer(rel, blkno + i); + pages[i] = BufferGetBlock(bufs[i]); + buf_hdrs[i] = BufferIsLocal(bufs[i]) ? + GetLocalBufferDescriptor(-bufs[i] - 1) : + GetBufferDescriptor(bufs[i] - 1); + } + + smgr = RelationGetSmgr(rel); + + pgstat_prepare_report_checksum_failure(smgr->smgr_rlocator.locator.dbOid); + + ioh = pgaio_io_acquire(CurrentResourceOwner, &ior); + pgaio_io_get_wref(ioh, &iow); + + if (RelationUsesLocalBuffers(rel)) + { + for (int i = 0; i < nblocks; i++) + StartLocalBufferIO(buf_hdrs[i], true, false); + pgaio_io_set_flag(ioh, PGAIO_HF_REFERENCES_LOCAL); + } + else + { + for (int i = 0; i < nblocks; i++) + StartBufferIO(buf_hdrs[i], true, false); + } + + pgaio_io_set_handle_data_32(ioh, (uint32 *) bufs, nblocks); + + if (zero_on_error | zero_damaged_pages) + srb_flags |= READ_BUFFERS_ZERO_ON_ERROR; + if (ignore_checksum_failure) + srb_flags |= READ_BUFFERS_IGNORE_CHECKSUM_FAILURES; + + pgaio_io_register_callbacks(ioh, + RelationUsesLocalBuffers(rel) ? + PGAIO_HCB_LOCAL_BUFFER_READV : + PGAIO_HCB_SHARED_BUFFER_READV, + srb_flags); + + if (batchmode_enter) + pgaio_enter_batchmode(); + + smgrstartreadv(ioh, smgr, MAIN_FORKNUM, blkno, + (void *) pages, nblocks); + + if (call_smgrreleaseall) + smgrreleaseall(); + + if (batchmode_exit) + pgaio_exit_batchmode(); + + for (int i = 0; i < nblocks; i++) + ReleaseBuffer(bufs[i]); + + if (wait_complete) + { + pgaio_wref_wait(&iow); + + if (ior.result.status != PGAIO_RS_OK) + pgaio_result_report(ior.result, + &ior.target_data, + ior.result.status == PGAIO_RS_ERROR ? + ERROR : WARNING); + } + + relation_close(rel, NoLock); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(invalidate_rel_block); +Datum +invalidate_rel_block(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + BlockNumber blkno = PG_GETARG_UINT32(1); + Relation rel; + PrefetchBufferResult pr; + Buffer buf; + + rel = relation_open(relid, AccessExclusiveLock); + + /* + * This is a gross hack, but there's no other API exposed that allows to + * get a buffer ID without actually reading the block in. + */ + pr = PrefetchBuffer(rel, MAIN_FORKNUM, blkno); + buf = pr.recent_buffer; + + if (BufferIsValid(buf)) + { + /* if the buffer contents aren't valid, this'll return false */ + if (ReadRecentBuffer(rel->rd_locator, MAIN_FORKNUM, blkno, buf)) + { + BufferDesc *buf_hdr = BufferIsLocal(buf) ? + GetLocalBufferDescriptor(-buf - 1) + : GetBufferDescriptor(buf - 1); + bool flushed; + + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + + if (pg_atomic_read_u32(&buf_hdr->state) & BM_DIRTY) + { + if (BufferIsLocal(buf)) + FlushLocalBuffer(buf_hdr, NULL); + else + FlushOneBuffer(buf); + } + LockBuffer(buf, BUFFER_LOCK_UNLOCK); + ReleaseBuffer(buf); + + if (BufferIsLocal(buf)) + InvalidateLocalBuffer(GetLocalBufferDescriptor(-buf - 1), true); + else if (!EvictUnpinnedBuffer(buf, &flushed)) + elog(ERROR, "couldn't evict"); + } + } + + relation_close(rel, AccessExclusiveLock); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(buffer_create_toy); +Datum +buffer_create_toy(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + BlockNumber blkno = PG_GETARG_UINT32(1); + Relation rel; + Buffer buf; + + rel = relation_open(relid, AccessExclusiveLock); + + buf = create_toy_buffer(rel, blkno); + ReleaseBuffer(buf); + + relation_close(rel, NoLock); + + PG_RETURN_INT32(buf); +} + +PG_FUNCTION_INFO_V1(buffer_call_start_io); +Datum +buffer_call_start_io(PG_FUNCTION_ARGS) +{ + Buffer buf = PG_GETARG_INT32(0); + bool for_input = PG_GETARG_BOOL(1); + bool nowait = PG_GETARG_BOOL(2); + bool can_start; + + if (BufferIsLocal(buf)) + can_start = StartLocalBufferIO(GetLocalBufferDescriptor(-buf - 1), + for_input, nowait); + else + can_start = StartBufferIO(GetBufferDescriptor(buf - 1), + for_input, nowait); + + /* + * For tests we don't want the resowner release preventing us from + * orchestrating odd scenarios. + */ + if (can_start && !BufferIsLocal(buf)) + ResourceOwnerForgetBufferIO(CurrentResourceOwner, + buf); + + ereport(LOG, + errmsg("buffer %d after StartBufferIO: %s", + buf, DebugPrintBufferRefcount(buf)), + errhidestmt(true), errhidecontext(true)); + + PG_RETURN_BOOL(can_start); +} + +PG_FUNCTION_INFO_V1(buffer_call_terminate_io); +Datum +buffer_call_terminate_io(PG_FUNCTION_ARGS) +{ + Buffer buf = PG_GETARG_INT32(0); + bool for_input = PG_GETARG_BOOL(1); + bool succeed = PG_GETARG_BOOL(2); + bool io_error = PG_GETARG_BOOL(3); + bool release_aio = PG_GETARG_BOOL(4); + bool clear_dirty = false; + uint32 set_flag_bits = 0; + + if (io_error) + set_flag_bits |= BM_IO_ERROR; + + if (for_input) + { + clear_dirty = false; + + if (succeed) + set_flag_bits |= BM_VALID; + } + else + { + if (succeed) + clear_dirty = true; + } + + ereport(LOG, + errmsg("buffer %d before Terminate[Local]BufferIO: %s", + buf, DebugPrintBufferRefcount(buf)), + errhidestmt(true), errhidecontext(true)); + + if (BufferIsLocal(buf)) + TerminateLocalBufferIO(GetLocalBufferDescriptor(-buf - 1), + clear_dirty, set_flag_bits, release_aio); + else + TerminateBufferIO(GetBufferDescriptor(buf - 1), + clear_dirty, set_flag_bits, false, release_aio); + + ereport(LOG, + errmsg("buffer %d after Terminate[Local]BufferIO: %s", + buf, DebugPrintBufferRefcount(buf)), + errhidestmt(true), errhidecontext(true)); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(handle_get); +Datum +handle_get(PG_FUNCTION_ARGS) +{ + last_handle = pgaio_io_acquire(CurrentResourceOwner, NULL); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(handle_release_last); +Datum +handle_release_last(PG_FUNCTION_ARGS) +{ + if (!last_handle) + elog(ERROR, "no handle"); + + pgaio_io_release(last_handle); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(handle_get_and_error); +Datum +handle_get_and_error(PG_FUNCTION_ARGS) +{ + pgaio_io_acquire(CurrentResourceOwner, NULL); + + elog(ERROR, "as you command"); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(handle_get_twice); +Datum +handle_get_twice(PG_FUNCTION_ARGS) +{ + pgaio_io_acquire(CurrentResourceOwner, NULL); + pgaio_io_acquire(CurrentResourceOwner, NULL); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(handle_get_release); +Datum +handle_get_release(PG_FUNCTION_ARGS) +{ + PgAioHandle *handle; + + handle = pgaio_io_acquire(CurrentResourceOwner, NULL); + pgaio_io_release(handle); + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(batch_start); +Datum +batch_start(PG_FUNCTION_ARGS) +{ + pgaio_enter_batchmode(); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(batch_end); +Datum +batch_end(PG_FUNCTION_ARGS) +{ + pgaio_exit_batchmode(); + PG_RETURN_VOID(); +} + +#ifdef USE_INJECTION_POINTS +extern PGDLLEXPORT void inj_io_short_read(const char *name, + const void *private_data, + void *arg); +extern PGDLLEXPORT void inj_io_reopen(const char *name, + const void *private_data, + void *arg); + +void +inj_io_short_read(const char *name, const void *private_data, void *arg) +{ + PgAioHandle *ioh = (PgAioHandle *) arg; + + ereport(LOG, + errmsg("short read injection point called, is enabled: %d", + inj_io_error_state->enabled_reopen), + errhidestmt(true), errhidecontext(true)); + + if (inj_io_error_state->enabled_short_read) + { + /* + * Only shorten reads that are actually longer than the target size, + * otherwise we can trigger over-reads. + */ + if (inj_io_error_state->short_read_result_set + && ioh->op == PGAIO_OP_READV + && inj_io_error_state->short_read_result <= ioh->result) + { + struct iovec *iov = &pgaio_ctl->iovecs[ioh->iovec_off]; + int32 old_result = ioh->result; + int32 new_result = inj_io_error_state->short_read_result; + int32 processed = 0; + + ereport(LOG, + errmsg("short read inject point, changing result from %d to %d", + old_result, new_result), + errhidestmt(true), errhidecontext(true)); + + /* + * The underlying IO actually completed OK, and thus the "invalid" + * portion of the IOV actually contains valid data. That can hide + * a lot of problems, e.g. if we were to wrongly mark a buffer, + * that wasn't read according to the shortened-read, IO as valid, + * the contents would look valid and we might miss a bug. + * + * To avoid that, iterate through the IOV and zero out the + * "failed" portion of the IO. + */ + for (int i = 0; i < ioh->op_data.read.iov_length; i++) + { + if (processed + iov[i].iov_len <= new_result) + processed += iov[i].iov_len; + else if (processed <= new_result) + { + uint32 ok_part = new_result - processed; + + memset((char *) iov[i].iov_base + ok_part, 0, iov[i].iov_len - ok_part); + processed += iov[i].iov_len; + } + else + { + memset((char *) iov[i].iov_base, 0, iov[i].iov_len); + } + } + + ioh->result = new_result; + } + } +} + +void +inj_io_reopen(const char *name, const void *private_data, void *arg) +{ + ereport(LOG, + errmsg("reopen injection point called, is enabled: %d", + inj_io_error_state->enabled_reopen), + errhidestmt(true), errhidecontext(true)); + + if (inj_io_error_state->enabled_reopen) + elog(ERROR, "injection point triggering failure to reopen "); +} +#endif + +PG_FUNCTION_INFO_V1(inj_io_short_read_attach); +Datum +inj_io_short_read_attach(PG_FUNCTION_ARGS) +{ +#ifdef USE_INJECTION_POINTS + inj_io_error_state->enabled_short_read = true; + inj_io_error_state->short_read_result_set = !PG_ARGISNULL(0); + if (inj_io_error_state->short_read_result_set) + inj_io_error_state->short_read_result = PG_GETARG_INT32(0); +#else + elog(ERROR, "injection points not supported"); +#endif + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(inj_io_short_read_detach); +Datum +inj_io_short_read_detach(PG_FUNCTION_ARGS) +{ +#ifdef USE_INJECTION_POINTS + inj_io_error_state->enabled_short_read = false; +#else + elog(ERROR, "injection points not supported"); +#endif + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(inj_io_reopen_attach); +Datum +inj_io_reopen_attach(PG_FUNCTION_ARGS) +{ +#ifdef USE_INJECTION_POINTS + inj_io_error_state->enabled_reopen = true; +#else + elog(ERROR, "injection points not supported"); +#endif + + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(inj_io_reopen_detach); +Datum +inj_io_reopen_detach(PG_FUNCTION_ARGS) +{ +#ifdef USE_INJECTION_POINTS + inj_io_error_state->enabled_reopen = false; +#else + elog(ERROR, "injection points not supported"); +#endif + PG_RETURN_VOID(); +} diff --git a/src/test/modules/test_aio/test_aio.control b/src/test/modules/test_aio/test_aio.control new file mode 100644 index 0000000000000..cd91c3ed16b9e --- /dev/null +++ b/src/test/modules/test_aio/test_aio.control @@ -0,0 +1,3 @@ +comment = 'Test code for AIO' +default_version = '1.0' +module_pathname = '$libdir/test_aio' diff --git a/src/test/modules/test_bloomfilter/meson.build b/src/test/modules/test_bloomfilter/meson.build index 5136aea96257a..3326e37c31d2e 100644 --- a/src/test/modules/test_bloomfilter/meson.build +++ b/src/test/modules/test_bloomfilter/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_bloomfilter_sources = files( 'test_bloomfilter.c', diff --git a/src/test/modules/test_bloomfilter/test_bloomfilter.c b/src/test/modules/test_bloomfilter/test_bloomfilter.c index b0633a8fa73c9..499d437a9c4da 100644 --- a/src/test/modules/test_bloomfilter/test_bloomfilter.c +++ b/src/test/modules/test_bloomfilter/test_bloomfilter.c @@ -3,7 +3,7 @@ * test_bloomfilter.c * Test false positive rate of Bloom filter. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_bloomfilter/test_bloomfilter.c @@ -76,7 +76,7 @@ create_and_test_bloom(int power, int64 nelements, int callerseed) int64 nfalsepos; bloom_filter *filter; - bloom_work_mem = (1L << power) / 8L / 1024L; + bloom_work_mem = ((int64) 1 << power) / (8 * 1024); elog(DEBUG1, "bloom_work_mem (KB): %d", bloom_work_mem); diff --git a/src/test/modules/test_copy_callbacks/meson.build b/src/test/modules/test_copy_callbacks/meson.build index 7620b8bde36f1..2af31b19f254e 100644 --- a/src/test/modules/test_copy_callbacks/meson.build +++ b/src/test/modules/test_copy_callbacks/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_copy_callbacks_sources = files( 'test_copy_callbacks.c', diff --git a/src/test/modules/test_copy_callbacks/test_copy_callbacks.c b/src/test/modules/test_copy_callbacks/test_copy_callbacks.c index 0bbd2aa6bb9d2..41113a8acdcff 100644 --- a/src/test/modules/test_copy_callbacks/test_copy_callbacks.c +++ b/src/test/modules/test_copy_callbacks/test_copy_callbacks.c @@ -3,7 +3,7 @@ * test_copy_callbacks.c * Code for testing COPY callbacks. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -42,8 +42,8 @@ test_copy_to_callback(PG_FUNCTION_ARGS) processed = DoCopyTo(cstate); EndCopyTo(cstate); - ereport(NOTICE, (errmsg("COPY TO callback has processed %lld rows", - (long long) processed))); + ereport(NOTICE, (errmsg("COPY TO callback has processed %" PRId64 " rows", + processed))); table_close(rel, NoLock); diff --git a/src/test/modules/test_custom_rmgrs/meson.build b/src/test/modules/test_custom_rmgrs/meson.build index 6e707d6f5458a..6869c534c7421 100644 --- a/src/test/modules/test_custom_rmgrs/meson.build +++ b/src/test/modules/test_custom_rmgrs/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_custom_rmgrs_sources = files( 'test_custom_rmgrs.c', diff --git a/src/test/modules/test_custom_rmgrs/t/001_basic.pl b/src/test/modules/test_custom_rmgrs/t/001_basic.pl index 686431fba8d50..a1e0e1ba678e9 100644 --- a/src/test/modules/test_custom_rmgrs/t/001_basic.pl +++ b/src/test/modules/test_custom_rmgrs/t/001_basic.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c b/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c index 85038f549db49..1a424ad55a8d8 100644 --- a/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c +++ b/src/test/modules/test_custom_rmgrs/test_custom_rmgrs.c @@ -3,7 +3,7 @@ * test_custom_rmgrs.c * Code for testing custom WAL resource managers. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -128,8 +128,8 @@ test_custom_rmgrs_insert_wal_record(PG_FUNCTION_ARGS) xlrec.message_size = len; XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, SizeOfTestCustomRmgrsMessage); - XLogRegisterData((char *) payload, len); + XLogRegisterData(&xlrec, SizeOfTestCustomRmgrsMessage); + XLogRegisterData(payload, len); /* Let's mark this record as unimportant, just in case. */ XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT); diff --git a/src/test/modules/test_ddl_deparse/expected/alter_table.out b/src/test/modules/test_ddl_deparse/expected/alter_table.out index 6daa186a8420e..50d0354a3417b 100644 --- a/src/test/modules/test_ddl_deparse/expected/alter_table.out +++ b/src/test/modules/test_ddl_deparse/expected/alter_table.out @@ -28,6 +28,7 @@ ALTER TABLE parent ADD COLUMN b serial; NOTICE: DDL test: type simple, tag CREATE SEQUENCE NOTICE: DDL test: type alter table, tag ALTER TABLE NOTICE: subcommand: type ADD COLUMN (and recurse) desc column b of table parent +NOTICE: subcommand: type ADD CONSTRAINT (and recurse) desc constraint parent_b_not_null on table parent NOTICE: DDL test: type simple, tag ALTER SEQUENCE ALTER TABLE parent RENAME COLUMN b TO c; NOTICE: DDL test: type simple, tag ALTER TABLE @@ -57,24 +58,17 @@ NOTICE: subcommand: type DETACH PARTITION desc table part2 DROP TABLE part2; ALTER TABLE part ADD PRIMARY KEY (a); NOTICE: DDL test: type alter table, tag ALTER TABLE -NOTICE: subcommand: type SET NOT NULL desc column a of table part -NOTICE: subcommand: type SET NOT NULL desc column a of table part1 +NOTICE: subcommand: type ADD CONSTRAINT (and recurse) desc constraint part_a_not_null on table part NOTICE: subcommand: type ADD INDEX desc index part_pkey ALTER TABLE parent ALTER COLUMN a SET NOT NULL; NOTICE: DDL test: type alter table, tag ALTER TABLE -NOTICE: subcommand: type SET NOT NULL desc column a of table parent -NOTICE: subcommand: type SET NOT NULL desc column a of table child -NOTICE: subcommand: type SET NOT NULL desc column a of table grandchild +NOTICE: subcommand: type SET NOT NULL (and recurse) desc constraint parent_a_not_null on table parent ALTER TABLE parent ALTER COLUMN a DROP NOT NULL; NOTICE: DDL test: type alter table, tag ALTER TABLE -NOTICE: subcommand: type DROP NOT NULL desc column a of table parent -NOTICE: subcommand: type DROP NOT NULL desc column a of table child -NOTICE: subcommand: type DROP NOT NULL desc column a of table grandchild +NOTICE: subcommand: type DROP NOT NULL (and recurse) desc column a of table parent ALTER TABLE parent ALTER COLUMN a SET NOT NULL; NOTICE: DDL test: type alter table, tag ALTER TABLE -NOTICE: subcommand: type SET NOT NULL desc column a of table parent -NOTICE: subcommand: type SET NOT NULL desc column a of table child -NOTICE: subcommand: type SET NOT NULL desc column a of table grandchild +NOTICE: subcommand: type SET NOT NULL (and recurse) desc constraint parent_a_not_null on table parent ALTER TABLE parent ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; NOTICE: DDL test: type simple, tag CREATE SEQUENCE NOTICE: DDL test: type simple, tag ALTER SEQUENCE @@ -116,6 +110,7 @@ NOTICE: DDL test: type alter table, tag ALTER TABLE NOTICE: subcommand: type ALTER COLUMN SET TYPE desc column c of table parent NOTICE: subcommand: type ALTER COLUMN SET TYPE desc column c of table child NOTICE: subcommand: type ALTER COLUMN SET TYPE desc column c of table grandchild +NOTICE: subcommand: type (re) ADD CONSTRAINT desc constraint parent_b_not_null on table parent NOTICE: subcommand: type (re) ADD STATS desc statistics object parent_stat ALTER TABLE parent ALTER COLUMN c SET DEFAULT 0; NOTICE: DDL test: type alter table, tag ALTER TABLE diff --git a/src/test/modules/test_ddl_deparse/expected/create_table.out b/src/test/modules/test_ddl_deparse/expected/create_table.out index 2178ce83e9dca..14915f661a894 100644 --- a/src/test/modules/test_ddl_deparse/expected/create_table.out +++ b/src/test/modules/test_ddl_deparse/expected/create_table.out @@ -85,8 +85,6 @@ CREATE TABLE employees OF employee_type ( salary WITH OPTIONS DEFAULT 1000 ); NOTICE: DDL test: type simple, tag CREATE TABLE -NOTICE: DDL test: type alter table, tag ALTER TABLE -NOTICE: subcommand: type SET NOT NULL desc column name of table employees NOTICE: DDL test: type simple, tag CREATE INDEX -- Inheritance CREATE TABLE person ( diff --git a/src/test/modules/test_ddl_deparse/expected/create_type.out b/src/test/modules/test_ddl_deparse/expected/create_type.out index dadbc8f7f034f..b754455e2b890 100644 --- a/src/test/modules/test_ddl_deparse/expected/create_type.out +++ b/src/test/modules/test_ddl_deparse/expected/create_type.out @@ -13,6 +13,8 @@ CREATE FUNCTION text_w_default_out(text_w_default) AS 'textout' LANGUAGE internal STABLE STRICT ; NOTICE: argument type text_w_default is only a shell +LINE 1: CREATE FUNCTION text_w_default_out(text_w_default) + ^ NOTICE: DDL test: type simple, tag CREATE FUNCTION CREATE TYPE employee_type AS (name TEXT, salary NUMERIC); NOTICE: DDL test: type simple, tag CREATE TYPE diff --git a/src/test/modules/test_ddl_deparse/expected/opfamily.out b/src/test/modules/test_ddl_deparse/expected/opfamily.out index c7e3a23ef70e0..4e1cc747cb80d 100644 --- a/src/test/modules/test_ddl_deparse/expected/opfamily.out +++ b/src/test/modules/test_ddl_deparse/expected/opfamily.out @@ -8,6 +8,8 @@ NOTICE: DDL test: type simple, tag CREATE FUNCTION create function int8alias1out(int8alias1) returns cstring strict immutable language internal as 'int8out'; NOTICE: argument type int8alias1 is only a shell +LINE 1: create function int8alias1out(int8alias1) returns cstring + ^ NOTICE: DDL test: type simple, tag CREATE FUNCTION create type int8alias1 ( input = int8alias1in, @@ -24,6 +26,8 @@ NOTICE: DDL test: type simple, tag CREATE FUNCTION create function int8alias2out(int8alias2) returns cstring strict immutable language internal as 'int8out'; NOTICE: argument type int8alias2 is only a shell +LINE 1: create function int8alias2out(int8alias2) returns cstring + ^ NOTICE: DDL test: type simple, tag CREATE FUNCTION create type int8alias2 ( input = int8alias2in, diff --git a/src/test/modules/test_ddl_deparse/meson.build b/src/test/modules/test_ddl_deparse/meson.build index 640c022641354..bff65ba6333d8 100644 --- a/src/test/modules/test_ddl_deparse/meson.build +++ b/src/test/modules/test_ddl_deparse/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_ddl_deparse_sources = files( 'test_ddl_deparse.c', diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c index 67ff2b6367570..193669f2bc1eb 100644 --- a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c +++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c @@ -2,7 +2,7 @@ * test_ddl_deparse.c * Support functions for the test_ddl_deparse module * - * Copyright (c) 2014-2024, PostgreSQL Global Development Group + * Copyright (c) 2014-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_ddl_deparse/test_ddl_deparse.c @@ -10,7 +10,6 @@ */ #include "postgres.h" -#include "catalog/pg_type.h" #include "funcapi.h" #include "nodes/execnodes.h" #include "tcop/deparse_utility.h" @@ -135,9 +134,6 @@ get_altertable_subcmdinfo(PG_FUNCTION_ARGS) case AT_DropExpression: strtype = "DROP EXPRESSION"; break; - case AT_CheckNotNull: - strtype = "CHECK NOT NULL"; - break; case AT_SetStatistics: strtype = "SET STATS"; break; @@ -300,12 +296,6 @@ get_altertable_subcmdinfo(PG_FUNCTION_ARGS) case AT_DetachPartitionFinalize: strtype = "DETACH PARTITION ... FINALIZE"; break; - case AT_SplitPartition: - strtype = "SPLIT PARTITION"; - break; - case AT_MergePartitions: - strtype = "MERGE PARTITIONS"; - break; case AT_AddIdentity: strtype = "ADD IDENTITY"; break; diff --git a/src/test/modules/test_dsa/meson.build b/src/test/modules/test_dsa/meson.build index 854dc18232d83..d72913a4a88fb 100644 --- a/src/test/modules/test_dsa/meson.build +++ b/src/test/modules/test_dsa/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_dsa_sources = files( 'test_dsa.c', diff --git a/src/test/modules/test_dsa/test_dsa.c b/src/test/modules/test_dsa/test_dsa.c index c78af68f61b99..cd24d0f48736d 100644 --- a/src/test/modules/test_dsa/test_dsa.c +++ b/src/test/modules/test_dsa/test_dsa.c @@ -3,7 +3,7 @@ * test_dsa.c * Test dynamic shared memory areas (DSAs) * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_dsa/test_dsa.c diff --git a/src/test/modules/test_dsm_registry/meson.build b/src/test/modules/test_dsm_registry/meson.build index a4045fea37e8f..7411b7f79d206 100644 --- a/src/test/modules/test_dsm_registry/meson.build +++ b/src/test/modules/test_dsm_registry/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group test_dsm_registry_sources = files( 'test_dsm_registry.c', diff --git a/src/test/modules/test_dsm_registry/test_dsm_registry.c b/src/test/modules/test_dsm_registry/test_dsm_registry.c index 96eaa850bfa92..96a890be22826 100644 --- a/src/test/modules/test_dsm_registry/test_dsm_registry.c +++ b/src/test/modules/test_dsm_registry/test_dsm_registry.c @@ -3,7 +3,7 @@ * test_dsm_registry.c * Test the dynamic shared memory registry. * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_dsm_registry/test_dsm_registry.c @@ -54,7 +54,7 @@ set_val_in_shmem(PG_FUNCTION_ARGS) tdr_attach_shmem(); LWLockAcquire(&tdr_state->lck, LW_EXCLUSIVE); - tdr_state->val = PG_GETARG_UINT32(0); + tdr_state->val = PG_GETARG_INT32(0); LWLockRelease(&tdr_state->lck); PG_RETURN_VOID(); @@ -72,5 +72,5 @@ get_val_in_shmem(PG_FUNCTION_ARGS) ret = tdr_state->val; LWLockRelease(&tdr_state->lck); - PG_RETURN_UINT32(ret); + PG_RETURN_INT32(ret); } diff --git a/src/test/modules/test_escape/.gitignore b/src/test/modules/test_escape/.gitignore new file mode 100644 index 0000000000000..e498d6b7efa2a --- /dev/null +++ b/src/test/modules/test_escape/.gitignore @@ -0,0 +1,2 @@ +/tmp_check/ +/test_escape diff --git a/src/test/modules/test_escape/Makefile b/src/test/modules/test_escape/Makefile new file mode 100644 index 0000000000000..786db4cbae452 --- /dev/null +++ b/src/test/modules/test_escape/Makefile @@ -0,0 +1,27 @@ +# src/test/modules/test_escape/Makefile + +PGFILEDESC = "test escape program" +PGAPPICON = win32 + +PROGRAM = test_escape +OBJS = $(WIN32RES) test_escape.o + +PG_CPPFLAGS = -I$(libpq_srcdir) +PG_LIBS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport) + +NO_INSTALL = 1 +TAP_TESTS = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/test_escape +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +test_escape$(X): | submake-libpgfeutils +check: test_escape$(X) diff --git a/src/test/modules/test_escape/meson.build b/src/test/modules/test_escape/meson.build new file mode 100644 index 0000000000000..a21341d5067cb --- /dev/null +++ b/src/test/modules/test_escape/meson.build @@ -0,0 +1,31 @@ +test_escape_sources = files( + 'test_escape.c', +) + +if host_system == 'windows' + test_escape_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'test_escape', + '--FILEDESC', 'test escape program',]) +endif + +test_escape = executable('test_escape', + test_escape_sources, + dependencies: [frontend_code, libpq], + kwargs: default_bin_args + { + 'install': false, + } +) +testprep_targets += test_escape + + +tests += { + 'name': 'test_escape', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_test_escape.pl', + ], + 'deps': [test_escape], + }, +} diff --git a/src/test/modules/test_escape/t/001_test_escape.pl b/src/test/modules/test_escape/t/001_test_escape.pl new file mode 100644 index 0000000000000..0d5aec3ed748f --- /dev/null +++ b/src/test/modules/test_escape/t/001_test_escape.pl @@ -0,0 +1,53 @@ +# Copyright (c) 2023-2025, PostgreSQL Global Development Group +use strict; +use warnings FATAL => 'all'; +use Config; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('node'); + +$node->init(); +$node->start(); + +$node->safe_psql('postgres', + q(CREATE DATABASE db_sql_ascii ENCODING "sql_ascii" TEMPLATE template0;)); + +my $cmd = + [ 'test_escape', '--conninfo', $node->connstr . " dbname=db_sql_ascii" ]; + +# There currently is no good other way to transport test results from a C +# program that requires just the node being set-up... +my ($stderr, $stdout); +my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr; + +is($result, 1, "test_escape returns 0"); +is($stderr, '', "test_escape stderr is empty"); + +foreach my $line (split('\n', $stdout)) +{ + if ($line =~ m/^ok \d+ ?(.*)/) + { + ok(1, $1); + } + + elsif ($line =~ m/^not ok \d+ ?(.*)/) + { + ok(0, $1); + } + + elsif ($line =~ m/^# ?(.*)/) + { + note $1; + } + elsif ($line =~ m/^\d+..\d+$/) + { + } + else + { + BAIL_OUT("no unmapped lines, got $line"); + } +} + +done_testing(); diff --git a/src/test/modules/test_escape/test_escape.c b/src/test/modules/test_escape/test_escape.c new file mode 100644 index 0000000000000..59430ed46c484 --- /dev/null +++ b/src/test/modules/test_escape/test_escape.c @@ -0,0 +1,970 @@ +/* + * test_escape.c Test escape functions + * + * Copyright (c) 2022-2025, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/test/modules/test_escape/test_escape.c + */ + +#include "postgres_fe.h" + +#include +#include + +#include "common/jsonapi.h" +#include "fe_utils/psqlscan.h" +#include "fe_utils/string_utils.h" +#include "getopt_long.h" +#include "libpq-fe.h" +#include "mb/pg_wchar.h" +#include "utils/memdebug.h" + + +typedef struct pe_test_config +{ + int verbosity; + bool force_unsupported; + const char *conninfo; + PGconn *conn; + + int test_count; + int failure_count; +} pe_test_config; + +#define NEVER_ACCESS_STR "\xff never-to-be-touched" + + +/* + * An escape function to be tested by this test. + */ +typedef struct pe_test_escape_func +{ + const char *name; + + /* + * Can the escape method report errors? If so, we validate that it does in + * case of various invalid inputs. + */ + bool reports_errors; + + /* + * Is the escape method known to not handle invalidly encoded input? If + * so, we don't run the test unless --force-unsupported is used. + */ + bool supports_only_valid; + + /* + * Is the escape method known to only handle encodings where no byte in a + * multi-byte characters are valid ascii. + */ + bool supports_only_ascii_overlap; + + /* + * Does the escape function have a length input? + */ + bool supports_input_length; + + bool (*escape) (PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err); +} pe_test_escape_func; + +/* + * A single test input for this test. + */ +typedef struct pe_test_vector +{ + const char *client_encoding; + size_t escape_len; + const char *escape; +} pe_test_vector; + + +/* + * Callback functions from flex lexer. Not currently used by the test. + */ +static const PsqlScanCallbacks test_scan_callbacks = { + NULL +}; + + +/* + * Print the string into buf, making characters outside of plain ascii + * somewhat easier to recognize. + * + * The output format could stand to be improved significantly, it's not at all + * unambiguous. + */ +static void +escapify(PQExpBuffer buf, const char *str, size_t len) +{ + for (size_t i = 0; i < len; i++) + { + char c = *str; + + if (c == '\n') + appendPQExpBufferStr(buf, "\\n"); + else if (c == '\0') + appendPQExpBufferStr(buf, "\\0"); + else if (c < ' ' || c > '~') + appendPQExpBuffer(buf, "\\x%2x", (uint8_t) c); + else + appendPQExpBufferChar(buf, c); + str++; + } +} + +static void +report_result(pe_test_config *tc, + bool success, + const char *testname, + const char *details, + const char *subname, + const char *resultdesc) +{ + int test_id = ++tc->test_count; + bool print_details = true; + bool print_result = true; + + if (success) + { + if (tc->verbosity <= 0) + print_details = false; + if (tc->verbosity < 0) + print_result = false; + } + else + tc->failure_count++; + + if (print_details) + printf("%s", details); + + if (print_result) + printf("%s %d - %s: %s: %s\n", + success ? "ok" : "not ok", + test_id, testname, + subname, + resultdesc); +} + +/* + * Return true for encodings in which bytes in a multi-byte character look + * like valid ascii characters. + */ +static bool +encoding_conflicts_ascii(int encoding) +{ + /* + * We don't store this property directly anywhere, but whether an encoding + * is a client-only encoding is a good proxy. + */ + if (encoding > PG_ENCODING_BE_LAST) + return true; + return false; +} + + +/* + * Confirm escaping doesn't read past the end of an allocation. Consider the + * result of malloc(4096), in the absence of freelist entries satisfying the + * allocation. On OpenBSD, reading one byte past the end of that object + * yields SIGSEGV. + * + * Run this test before the program's other tests, so freelists are minimal. + * len=4096 didn't SIGSEGV, likely due to free() calls in libpq. len=8192 + * did. Use 128 KiB, to somewhat insulate the outcome from distant new free() + * calls and libc changes. + */ +static void +test_gb18030_page_multiple(pe_test_config *tc) +{ + PQExpBuffer testname; + size_t input_len = 0x20000; + char *input; + + /* prepare input */ + input = pg_malloc(input_len); + memset(input, '-', input_len - 1); + input[input_len - 1] = 0xfe; + + /* name to describe the test */ + testname = createPQExpBuffer(); + appendPQExpBuffer(testname, ">repeat(%c, %zu)", input[0], input_len - 1); + escapify(testname, input + input_len - 1, 1); + appendPQExpBuffer(testname, "< - GB18030 - PQescapeLiteral"); + + /* test itself */ + PQsetClientEncoding(tc->conn, "GB18030"); + report_result(tc, PQescapeLiteral(tc->conn, input, input_len) == NULL, + testname->data, "", + "input validity vs escape success", "ok"); + + destroyPQExpBuffer(testname); + pg_free(input); +} + +/* + * Confirm json parsing doesn't read past the end of an allocation. This + * exercises wchar.c infrastructure like the true "escape" tests do, but this + * isn't an "escape" test. + */ +static void +test_gb18030_json(pe_test_config *tc) +{ + PQExpBuffer raw_buf; + PQExpBuffer testname; + const char input[] = "{\"\\u\xFE"; + size_t input_len = sizeof(input) - 1; + JsonLexContext *lex; + JsonSemAction sem = {0}; /* no callbacks */ + JsonParseErrorType json_error; + + /* prepare input like test_one_vector_escape() does */ + raw_buf = createPQExpBuffer(); + appendBinaryPQExpBuffer(raw_buf, input, input_len); + appendPQExpBufferStr(raw_buf, NEVER_ACCESS_STR); + VALGRIND_MAKE_MEM_NOACCESS(&raw_buf->data[input_len], + raw_buf->len - input_len); + + /* name to describe the test */ + testname = createPQExpBuffer(); + appendPQExpBuffer(testname, ">"); + escapify(testname, input, input_len); + appendPQExpBuffer(testname, "< - GB18030 - pg_parse_json"); + + /* test itself */ + lex = makeJsonLexContextCstringLen(NULL, raw_buf->data, input_len, + PG_GB18030, false); + json_error = pg_parse_json(lex, &sem); + report_result(tc, json_error == JSON_UNICODE_ESCAPE_FORMAT, + testname->data, "", + "diagnosed", json_errdetail(json_error, lex)); + + freeJsonLexContext(lex); + destroyPQExpBuffer(testname); + destroyPQExpBuffer(raw_buf); +} + + +static bool +escape_literal(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + char *escaped; + + escaped = PQescapeLiteral(conn, unescaped, unescaped_len); + if (!escaped) + { + appendPQExpBufferStr(escape_err, PQerrorMessage(conn)); + escape_err->data[escape_err->len - 1] = 0; + escape_err->len--; + return false; + } + else + { + appendPQExpBufferStr(target, escaped); + PQfreemem(escaped); + return true; + } +} + +static bool +escape_identifier(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + char *escaped; + + escaped = PQescapeIdentifier(conn, unescaped, unescaped_len); + if (!escaped) + { + appendPQExpBufferStr(escape_err, PQerrorMessage(conn)); + escape_err->data[escape_err->len - 1] = 0; + escape_err->len--; + return false; + } + else + { + appendPQExpBufferStr(target, escaped); + PQfreemem(escaped); + return true; + } +} + +static bool +escape_string_conn(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + int error; + size_t sz; + + appendPQExpBufferChar(target, '\''); + enlargePQExpBuffer(target, unescaped_len * 2 + 1); + sz = PQescapeStringConn(conn, target->data + target->len, + unescaped, unescaped_len, + &error); + + target->len += sz; + appendPQExpBufferChar(target, '\''); + + if (error) + { + appendPQExpBufferStr(escape_err, PQerrorMessage(conn)); + escape_err->data[escape_err->len - 1] = 0; + escape_err->len--; + return false; + } + else + { + return true; + } +} + +static bool +escape_string(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + size_t sz; + + appendPQExpBufferChar(target, '\''); + enlargePQExpBuffer(target, unescaped_len * 2 + 1); + sz = PQescapeString(target->data + target->len, + unescaped, unescaped_len); + target->len += sz; + appendPQExpBufferChar(target, '\''); + + + return true; +} + +/* + * Escape via s/'/''/. Non-core drivers invariably wrap libpq or use this + * method. It suffices iff the input passes encoding validation, so it's + * marked as supports_only_valid. + */ +static bool +escape_replace(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + const char *s = unescaped; + + appendPQExpBufferChar(target, '\''); + + for (int i = 0; i < unescaped_len; i++) + { + char c = *s; + + if (c == '\'') + { + appendPQExpBufferStr(target, "''"); + } + else + appendPQExpBufferChar(target, c); + s++; + } + appendPQExpBufferChar(target, '\''); + + return true; +} + +static bool +escape_append_literal(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + appendStringLiteral(target, unescaped, PQclientEncoding(conn), 1); + + return true; +} + +static bool +escape_fmt_id(PGconn *conn, PQExpBuffer target, + const char *unescaped, size_t unescaped_len, + PQExpBuffer escape_err) +{ + setFmtEncoding(PQclientEncoding(conn)); + appendPQExpBufferStr(target, fmtId(unescaped)); + + return true; +} + +static pe_test_escape_func pe_test_escape_funcs[] = +{ + { + .name = "PQescapeLiteral", + .reports_errors = true, + .supports_input_length = true, + .escape = escape_literal, + }, + { + .name = "PQescapeIdentifier", + .reports_errors = true, + .supports_input_length = true, + .escape = escape_identifier + }, + { + .name = "PQescapeStringConn", + .reports_errors = true, + .supports_input_length = true, + .escape = escape_string_conn + }, + { + .name = "PQescapeString", + .reports_errors = false, + .supports_input_length = true, + .escape = escape_string + }, + { + .name = "replace", + .reports_errors = false, + .supports_only_valid = true, + .supports_only_ascii_overlap = true, + .supports_input_length = true, + .escape = escape_replace + }, + { + .name = "appendStringLiteral", + .reports_errors = false, + .escape = escape_append_literal + }, + { + .name = "fmtId", + .reports_errors = false, + .escape = escape_fmt_id + }, +}; + + +#define TV(enc, string) {.client_encoding = (enc), .escape=string, .escape_len=sizeof(string) - 1, } +#define TV_LEN(enc, string, len) {.client_encoding = (enc), .escape=string, .escape_len=len, } +static pe_test_vector pe_test_vectors[] = +{ + /* expected to work sanity checks */ + TV("UTF-8", "1"), + TV("UTF-8", "'"), + TV("UTF-8", "\""), + + TV("UTF-8", "\'"), + TV("UTF-8", "\""), + + TV("UTF-8", "\\"), + + TV("UTF-8", "\\'"), + TV("UTF-8", "\\\""), + + /* trailing multi-byte character, paddable in available space */ + TV("UTF-8", "1\xC0"), + TV("UTF-8", "1\xE0 "), + TV("UTF-8", "1\xF0 "), + TV("UTF-8", "1\xF0 "), + TV("UTF-8", "1\xF0 "), + + /* trailing multi-byte character, not enough space to pad */ + TV("UTF-8", "1\xE0"), + TV("UTF-8", "1\xF0"), + TV("UTF-8", "\xF0"), + + /* try to smuggle in something in invalid characters */ + TV("UTF-8", "1\xE0'"), + TV("UTF-8", "1\xE0\""), + TV("UTF-8", "1\xF0'"), + TV("UTF-8", "1\xF0\""), + TV("UTF-8", "1\xF0'; "), + TV("UTF-8", "1\xF0\"; "), + TV("UTF-8", "1\xF0';;;;"), + TV("UTF-8", "1\xF0 ';;;;"), + TV("UTF-8", "1\xF0 \";;;;"), + TV("UTF-8", "1\xE0'; \\l ; "), + TV("UTF-8", "1\xE0\"; \\l ; "), + + /* null byte handling */ + TV("UTF-8", "some\0thing"), + TV("UTF-8", "some\0"), + TV("UTF-8", "some\xF0'\0"), + TV("UTF-8", "some\xF0'\0'"), + TV("UTF-8", "some\xF0" "ab\0'"), + + /* GB18030's 4 byte encoding requires a 2nd byte limited values */ + TV("GB18030", "\x90\x31"), + TV("GB18030", "\\\x81\x5c'"), + TV("GB18030", "\\\x81\x5c\""), + TV("GB18030", "\\\x81\x5c\0'"), + + /* + * \x81 indicates a 2 byte char. ' and " are not a valid second byte, but + * that requires encoding verification to know. E.g. replace_string() + * doesn't cope. + */ + TV("GB18030", "\\\x81';"), + TV("GB18030", "\\\x81\";"), + + /* + * \x81 indicates a 2 byte char. \ is a valid second character. + */ + TV("GB18030", "\\\x81\\';"), + TV("GB18030", "\\\x81\\\";"), + TV("GB18030", "\\\x81\0;"), + TV("GB18030", "\\\x81\0'"), + TV("GB18030", "\\\x81'\0"), + + TV("SJIS", "\xF0\x40;"), + + TV("SJIS", "\xF0';"), + TV("SJIS", "\xF0\";"), + TV("SJIS", "\xF0\0'"), + TV("SJIS", "\\\xF0\\';"), + TV("SJIS", "\\\xF0\\\";"), + + TV("gbk", "\x80';"), + TV("gbk", "\x80"), + TV("gbk", "\x80'"), + TV("gbk", "\x80\""), + TV("gbk", "\x80\\"), + + TV("mule_internal", "\\\x9c';\0;"), + + TV("sql_ascii", "1\xC0'"), + + /* + * Testcases that are not null terminated for the specified input length. + * That's interesting to verify that escape functions don't read beyond + * the intended input length. + * + * One interesting special case is GB18030, which has the odd behaviour + * needing to read beyond the first byte to determine the length of a + * multi-byte character. + */ + TV_LEN("gbk", "\x80", 1), + TV_LEN("GB18030", "\x80", 1), + TV_LEN("GB18030", "\x80\0", 2), + TV_LEN("GB18030", "\x80\x30", 2), + TV_LEN("GB18030", "\x80\x30\0", 3), + TV_LEN("GB18030", "\x80\x30\x30", 3), + TV_LEN("GB18030", "\x80\x30\x30\0", 4), + TV_LEN("UTF-8", "\xC3\xb6 ", 1), + TV_LEN("UTF-8", "\xC3\xb6 ", 2), +}; + + +static const char * +scan_res_s(PsqlScanResult res) +{ +#define TOSTR_CASE(sym) case sym: return #sym + + switch (res) + { + TOSTR_CASE(PSCAN_SEMICOLON); + TOSTR_CASE(PSCAN_BACKSLASH); + TOSTR_CASE(PSCAN_INCOMPLETE); + TOSTR_CASE(PSCAN_EOL); + } + + pg_unreachable(); + return ""; /* silence compiler */ +} + +/* + * Verify that psql parses the input as a single statement. If this property + * is violated, the escape function does not effectively protect against + * smuggling in a second statement. + */ +static void +test_psql_parse(pe_test_config *tc, PQExpBuffer testname, + PQExpBuffer input_buf, PQExpBuffer details) +{ + PsqlScanState scan_state; + PsqlScanResult scan_result; + PQExpBuffer query_buf; + promptStatus_t prompt_status = PROMPT_READY; + int matches = 0; + bool test_fails; + const char *resdesc; + + query_buf = createPQExpBuffer(); + + scan_state = psql_scan_create(&test_scan_callbacks); + + /* + * TODO: This hardcodes standard conforming strings, it would be useful to + * test without as well. + */ + psql_scan_setup(scan_state, input_buf->data, input_buf->len, + PQclientEncoding(tc->conn), 1); + + do + { + resetPQExpBuffer(query_buf); + + scan_result = psql_scan(scan_state, query_buf, + &prompt_status); + + appendPQExpBuffer(details, + "#\t\t %d: scan_result: %s prompt: %u, query_buf: ", + matches, scan_res_s(scan_result), prompt_status); + escapify(details, query_buf->data, query_buf->len); + appendPQExpBufferChar(details, '\n'); + + matches++; + } + while (scan_result != PSCAN_INCOMPLETE && scan_result != PSCAN_EOL); + + psql_scan_destroy(scan_state); + destroyPQExpBuffer(query_buf); + + test_fails = matches > 1 || scan_result != PSCAN_EOL; + + if (matches > 1) + resdesc = "more than one match"; + else if (scan_result != PSCAN_EOL) + resdesc = "unexpected end state"; + else + resdesc = "ok"; + + report_result(tc, !test_fails, testname->data, details->data, + "psql parse", + resdesc); +} + +static void +test_one_vector_escape(pe_test_config *tc, const pe_test_vector *tv, const pe_test_escape_func *ef) +{ + PQExpBuffer testname; + PQExpBuffer details; + PQExpBuffer raw_buf; + PQExpBuffer escape_buf; + PQExpBuffer escape_err; + size_t input_encoding_validlen; + bool input_encoding_valid; + size_t input_encoding0_validlen; + bool input_encoding0_valid; + bool escape_success; + size_t escape_encoding_length; + bool escape_encoding_valid; + + escape_err = createPQExpBuffer(); + testname = createPQExpBuffer(); + details = createPQExpBuffer(); + raw_buf = createPQExpBuffer(); + escape_buf = createPQExpBuffer(); + + if (ef->supports_only_ascii_overlap && + encoding_conflicts_ascii(PQclientEncoding(tc->conn))) + { + goto out; + } + + /* name to describe the test */ + appendPQExpBufferChar(testname, '>'); + escapify(testname, tv->escape, tv->escape_len); + appendPQExpBuffer(testname, "< - %s - %s", + tv->client_encoding, ef->name); + + /* details to describe the test, to allow for debugging */ + appendPQExpBuffer(details, "#\t input: %zd bytes: ", + tv->escape_len); + escapify(details, tv->escape, tv->escape_len); + appendPQExpBufferChar(details, '\n'); + appendPQExpBuffer(details, "#\t encoding: %s\n", + tv->client_encoding); + + + /* check encoding of input, to compare with after the test */ + input_encoding_validlen = pg_encoding_verifymbstr(PQclientEncoding(tc->conn), + tv->escape, + tv->escape_len); + input_encoding_valid = input_encoding_validlen == tv->escape_len; + appendPQExpBuffer(details, "#\t input encoding valid: %d\n", + input_encoding_valid); + + input_encoding0_validlen = pg_encoding_verifymbstr(PQclientEncoding(tc->conn), + tv->escape, + strnlen(tv->escape, tv->escape_len)); + input_encoding0_valid = input_encoding0_validlen == strnlen(tv->escape, tv->escape_len); + appendPQExpBuffer(details, "#\t input encoding valid till 0: %d\n", + input_encoding0_valid); + + appendPQExpBuffer(details, "#\t escape func: %s\n", + ef->name); + + if (!input_encoding_valid && ef->supports_only_valid + && !tc->force_unsupported) + goto out; + + + /* + * Put the to-be-escaped data into a buffer, so that we + * + * a) can mark memory beyond end of the string as inaccessible when using + * valgrind + * + * b) can append extra data beyond the length passed to the escape + * function, to verify that that data is not processed. + * + * TODO: Should we instead/additionally escape twice, once with unmodified + * and once with appended input? That way we could compare the two. + */ + appendBinaryPQExpBuffer(raw_buf, tv->escape, tv->escape_len); + + if (ef->supports_input_length) + { + /* + * Append likely invalid string that does *not* contain a null byte + * (which'd prevent some invalid accesses to later memory). + */ + appendPQExpBufferStr(raw_buf, NEVER_ACCESS_STR); + + VALGRIND_MAKE_MEM_NOACCESS(&raw_buf->data[tv->escape_len], + raw_buf->len - tv->escape_len); + } + else + { + /* append invalid string, after \0 */ + appendPQExpBufferChar(raw_buf, 0); + appendPQExpBufferStr(raw_buf, NEVER_ACCESS_STR); + + VALGRIND_MAKE_MEM_NOACCESS(&raw_buf->data[tv->escape_len + 1], + raw_buf->len - tv->escape_len - 1); + } + + /* call the to-be-tested escape function */ + escape_success = ef->escape(tc->conn, escape_buf, + raw_buf->data, tv->escape_len, + escape_err); + if (!escape_success) + { + appendPQExpBuffer(details, "#\t escape error: %s\n", + escape_err->data); + } + + if (escape_buf->len > 0) + { + bool contains_never; + + appendPQExpBuffer(details, "#\t escaped string: %zd bytes: ", escape_buf->len); + escapify(details, escape_buf->data, escape_buf->len); + appendPQExpBufferChar(details, '\n'); + + escape_encoding_length = pg_encoding_verifymbstr(PQclientEncoding(tc->conn), + escape_buf->data, + escape_buf->len); + escape_encoding_valid = escape_encoding_length == escape_buf->len; + + appendPQExpBuffer(details, "#\t escape encoding valid: %d\n", + escape_encoding_valid); + + /* + * Verify that no data beyond the end of the input is included in the + * escaped string. It'd be better to use something like memmem() + * here, but that's not available everywhere. + */ + contains_never = strstr(escape_buf->data, NEVER_ACCESS_STR) == NULL; + report_result(tc, contains_never, testname->data, details->data, + "escaped data beyond end of input", + contains_never ? "no" : "all secrets revealed"); + } + else + { + escape_encoding_length = 0; + escape_encoding_valid = 1; + } + + /* + * If the test reports errors, and the input was invalidly encoded, + * escaping should fail. One edge-case that we accept for now is that the + * input could have an embedded null byte, which the escape functions will + * just treat as a shorter string. If the encoding error is after the zero + * byte, the output thus won't contain it. + */ + if (ef->reports_errors) + { + bool ok = true; + const char *resdesc = "ok"; + + if (escape_success) + { + if (!input_encoding0_valid) + { + ok = false; + resdesc = "invalid input escaped successfully"; + } + else if (!input_encoding_valid) + resdesc = "invalid input escaped successfully, due to zero byte"; + } + else + { + if (input_encoding0_valid) + { + ok = false; + resdesc = "valid input failed to escape"; + } + else if (input_encoding_valid) + resdesc = "valid input failed to escape, due to zero byte"; + } + + report_result(tc, ok, testname->data, details->data, + "input validity vs escape success", + resdesc); + } + + /* + * If the input is invalidly encoded, the output should also be invalidly + * encoded. We accept the same zero-byte edge case as above. + */ + { + bool ok = true; + const char *resdesc = "ok"; + + if (input_encoding0_valid && !input_encoding_valid && escape_encoding_valid) + { + resdesc = "invalid input produced valid output, due to zero byte"; + } + else if (input_encoding0_valid && !escape_encoding_valid) + { + ok = false; + resdesc = "valid input produced invalid output"; + } + else if (!input_encoding0_valid && + (!ef->reports_errors || escape_success) && + escape_encoding_valid) + { + ok = false; + resdesc = "invalid input produced valid output"; + } + + report_result(tc, ok, testname->data, details->data, + "input and escaped encoding validity", + resdesc); + } + + /* + * Test psql parsing whenever we get any string back, even if the escape + * function returned a failure. + */ + if (escape_buf->len > 0) + { + test_psql_parse(tc, testname, + escape_buf, details); + } + +out: + destroyPQExpBuffer(escape_err); + destroyPQExpBuffer(details); + destroyPQExpBuffer(testname); + destroyPQExpBuffer(escape_buf); + destroyPQExpBuffer(raw_buf); +} + +static void +test_one_vector(pe_test_config *tc, const pe_test_vector *tv) +{ + if (PQsetClientEncoding(tc->conn, tv->client_encoding)) + { + fprintf(stderr, "failed to set encoding to %s:\n%s\n", + tv->client_encoding, PQerrorMessage(tc->conn)); + exit(1); + } + + for (int escoff = 0; escoff < lengthof(pe_test_escape_funcs); escoff++) + { + const pe_test_escape_func *ef = &pe_test_escape_funcs[escoff]; + + test_one_vector_escape(tc, tv, ef); + } +} + +static void +usage(const char *hint) +{ + if (hint) + fprintf(stderr, "Error: %s\n\n", hint); + + printf("PostgreSQL escape function test\n" + "\n" + "Usage:\n" + " test_escape --conninfo=CONNINFO [OPTIONS]\n" + "\n" + "Options:\n" + " -h, --help show this help\n" + " -c, --conninfo=CONNINFO connection information to use\n" + " -v, --verbose show test details even for successes\n" + " -q, --quiet only show failures\n" + " -f, --force-unsupported test invalid input even if unsupported\n" + ); + + if (hint) + exit(1); +} + +int +main(int argc, char *argv[]) +{ + pe_test_config tc = {0}; + int c; + int option_index; + + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"conninfo", required_argument, NULL, 'c'}, + {"verbose", no_argument, NULL, 'v'}, + {"quiet", no_argument, NULL, 'q'}, + {"force-unsupported", no_argument, NULL, 'f'}, + {NULL, 0, NULL, 0}, + }; + + while ((c = getopt_long(argc, argv, "c:fhqv", long_options, &option_index)) != -1) + { + switch (c) + { + case 'h': + usage(NULL); + exit(0); + break; + case 'c': + tc.conninfo = optarg; + break; + case 'v': + tc.verbosity++; + break; + case 'q': + tc.verbosity--; + break; + case 'f': + tc.force_unsupported = true; + break; + } + } + + if (argc - optind >= 1) + usage("unused option(s) specified"); + + if (tc.conninfo == NULL) + usage("--conninfo needs to be specified"); + + tc.conn = PQconnectdb(tc.conninfo); + + if (!tc.conn || PQstatus(tc.conn) != CONNECTION_OK) + { + fprintf(stderr, "could not connect: %s\n", + PQerrorMessage(tc.conn)); + exit(1); + } + + test_gb18030_page_multiple(&tc); + test_gb18030_json(&tc); + + for (int i = 0; i < lengthof(pe_test_vectors); i++) + { + test_one_vector(&tc, &pe_test_vectors[i]); + } + + PQfinish(tc.conn); + + printf("# %d failures\n", tc.failure_count); + printf("1..%d\n", tc.test_count); + return tc.failure_count > 0; +} diff --git a/src/test/modules/test_extensions/Makefile b/src/test/modules/test_extensions/Makefile index 05272e6a40b93..a3591bf3d2f35 100644 --- a/src/test/modules/test_extensions/Makefile +++ b/src/test/modules/test_extensions/Makefile @@ -13,7 +13,9 @@ EXTENSION = test_ext1 test_ext2 test_ext3 test_ext4 test_ext5 test_ext6 \ DATA = test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \ test_ext4--1.0.sql test_ext5--1.0.sql test_ext6--1.0.sql \ - test_ext7--1.0.sql test_ext7--1.0--2.0.sql test_ext8--1.0.sql \ + test_ext7--1.0.sql test_ext7--1.0--2.0.sql \ + test_ext7--2.0--2.1bad.sql test_ext7--2.0--2.2bad.sql \ + test_ext8--1.0.sql \ test_ext9--1.0.sql \ test_ext_cine--1.0.sql test_ext_cine--1.0--1.1.sql \ test_ext_cor--1.0.sql \ @@ -26,6 +28,7 @@ DATA = test_ext1--1.0.sql test_ext2--1.0.sql test_ext3--1.0.sql \ test_ext_req_schema3--1.0.sql REGRESS = test_extensions test_extdepend +TAP_TESTS = 1 # force C locale for output stability NO_LOCALE = 1 diff --git a/src/test/modules/test_extensions/expected/test_extensions.out b/src/test/modules/test_extensions/expected/test_extensions.out index f357cc21aaab4..72bae1bf254b5 100644 --- a/src/test/modules/test_extensions/expected/test_extensions.out +++ b/src/test/modules/test_extensions/expected/test_extensions.out @@ -72,6 +72,22 @@ Objects in extension "test_ext7" type ext7_table2[] (4 rows) +-- test reporting of errors in extension scripts +alter extension test_ext7 update to '2.1bad'; +ERROR: syntax error at or near "FUNCTIN" +LINE 1: CREATE FUNCTIN my_erroneous_func(int) RETURNS int LANGUAGE S... + ^ +QUERY: CREATE FUNCTIN my_erroneous_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + 1 $$; +CONTEXT: extension script file "test_ext7--2.0--2.1bad.sql", near line 10 +alter extension test_ext7 update to '2.2bad'; +ERROR: syntax error at or near "," +LINE 1: SELECT $1 + , 1 + ^ +QUERY: SELECT $1 + , 1 +CONTEXT: SQL statement "CREATE FUNCTION my_erroneous_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + , 1 $$" +extension script file "test_ext7--2.0--2.2bad.sql", near line 9 -- test handling of temp objects created by extensions create extension test_ext8; -- \dx+ would expose a variable pg_temp_nn schema name, so we can't use it here @@ -295,6 +311,9 @@ CREATE FUNCTION ext_cor_func() RETURNS text CREATE EXTENSION test_ext_cor; -- fail ERROR: function ext_cor_func() is not a member of extension "test_ext_cor" DETAIL: An extension is not allowed to replace an object that it does not own. +CONTEXT: SQL statement "CREATE OR REPLACE FUNCTION ext_cor_func() RETURNS text + AS $$ SELECT 'ext_cor_func: from extension'::text $$ LANGUAGE sql" +extension script file "test_ext_cor--1.0.sql", near line 8 SELECT ext_cor_func(); ext_cor_func ------------------------ @@ -307,6 +326,9 @@ CREATE VIEW ext_cor_view AS CREATE EXTENSION test_ext_cor; -- fail ERROR: view ext_cor_view is not a member of extension "test_ext_cor" DETAIL: An extension is not allowed to replace an object that it does not own. +CONTEXT: SQL statement "CREATE OR REPLACE VIEW ext_cor_view AS + SELECT 'ext_cor_view: from extension'::text AS col" +extension script file "test_ext_cor--1.0.sql", near line 11 SELECT ext_cor_func(); ERROR: function ext_cor_func() does not exist LINE 1: SELECT ext_cor_func(); @@ -323,6 +345,8 @@ CREATE TYPE test_ext_type; CREATE EXTENSION test_ext_cor; -- fail ERROR: type test_ext_type is not a member of extension "test_ext_cor" DETAIL: An extension is not allowed to replace an object that it does not own. +CONTEXT: SQL statement "CREATE TYPE test_ext_type AS ENUM('x', 'y')" +extension script file "test_ext_cor--1.0.sql", near line 17 DROP TYPE test_ext_type; -- this makes a shell "point <<@@ polygon" operator too CREATE OPERATOR @@>> ( PROCEDURE = poly_contain_pt, @@ -331,6 +355,9 @@ CREATE OPERATOR @@>> ( PROCEDURE = poly_contain_pt, CREATE EXTENSION test_ext_cor; -- fail ERROR: operator <<@@(point,polygon) is not a member of extension "test_ext_cor" DETAIL: An extension is not allowed to replace an object that it does not own. +CONTEXT: SQL statement "CREATE OPERATOR <<@@ ( PROCEDURE = pt_contained_poly, + LEFTARG = point, RIGHTARG = polygon )" +extension script file "test_ext_cor--1.0.sql", near line 19 DROP OPERATOR <<@@ (point, polygon); CREATE EXTENSION test_ext_cor; -- now it should work SELECT ext_cor_func(); @@ -379,37 +406,52 @@ CREATE COLLATION ext_cine_coll CREATE EXTENSION test_ext_cine; -- fail ERROR: collation ext_cine_coll is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE COLLATION IF NOT EXISTS ext_cine_coll + ( LC_COLLATE = "POSIX", LC_CTYPE = "POSIX" )" +extension script file "test_ext_cine--1.0.sql", near line 10 DROP COLLATION ext_cine_coll; CREATE MATERIALIZED VIEW ext_cine_mv AS SELECT 11 AS f1; CREATE EXTENSION test_ext_cine; -- fail ERROR: materialized view ext_cine_mv is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE MATERIALIZED VIEW IF NOT EXISTS ext_cine_mv AS SELECT 42 AS f1" +extension script file "test_ext_cine--1.0.sql", near line 13 DROP MATERIALIZED VIEW ext_cine_mv; CREATE FOREIGN DATA WRAPPER dummy; CREATE SERVER ext_cine_srv FOREIGN DATA WRAPPER dummy; CREATE EXTENSION test_ext_cine; -- fail ERROR: server ext_cine_srv is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE SERVER IF NOT EXISTS ext_cine_srv FOREIGN DATA WRAPPER ext_cine_fdw" +extension script file "test_ext_cine--1.0.sql", near line 17 DROP SERVER ext_cine_srv; CREATE SCHEMA ext_cine_schema; CREATE EXTENSION test_ext_cine; -- fail ERROR: schema ext_cine_schema is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE SCHEMA IF NOT EXISTS ext_cine_schema" +extension script file "test_ext_cine--1.0.sql", near line 19 DROP SCHEMA ext_cine_schema; CREATE SEQUENCE ext_cine_seq; CREATE EXTENSION test_ext_cine; -- fail ERROR: sequence ext_cine_seq is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE SEQUENCE IF NOT EXISTS ext_cine_seq" +extension script file "test_ext_cine--1.0.sql", near line 21 DROP SEQUENCE ext_cine_seq; CREATE TABLE ext_cine_tab1 (x int); CREATE EXTENSION test_ext_cine; -- fail ERROR: table ext_cine_tab1 is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE TABLE IF NOT EXISTS ext_cine_tab1 (x int)" +extension script file "test_ext_cine--1.0.sql", near line 23 DROP TABLE ext_cine_tab1; CREATE TABLE ext_cine_tab2 AS SELECT 42 AS y; CREATE EXTENSION test_ext_cine; -- fail ERROR: table ext_cine_tab2 is not a member of extension "test_ext_cine" DETAIL: An extension may only use CREATE ... IF NOT EXISTS to skip object creation if the conflicting object is one that it already owns. +CONTEXT: SQL statement "CREATE TABLE IF NOT EXISTS ext_cine_tab2 AS SELECT 42 AS y" +extension script file "test_ext_cine--1.0.sql", near line 25 DROP TABLE ext_cine_tab2; CREATE EXTENSION test_ext_cine; \dx+ test_ext_cine @@ -609,7 +651,7 @@ LINE 1: SELECT public.dep_req2() || ' req3b' ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. QUERY: SELECT public.dep_req2() || ' req3b' -CONTEXT: SQL function "dep_req3b" during startup +CONTEXT: SQL function "dep_req3b" statement 1 DROP EXTENSION test_ext_req_schema3; ALTER EXTENSION test_ext_req_schema1 SET SCHEMA test_s_dep2; -- now ok SELECT test_s_dep2.dep_req1(); diff --git a/src/test/modules/test_extensions/meson.build b/src/test/modules/test_extensions/meson.build index c5f3424da5159..3c7e378bf3595 100644 --- a/src/test/modules/test_extensions/meson.build +++ b/src/test/modules/test_extensions/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_install_data += files( 'test_ext1--1.0.sql', @@ -15,6 +15,8 @@ test_install_data += files( 'test_ext6.control', 'test_ext7--1.0--2.0.sql', 'test_ext7--1.0.sql', + 'test_ext7--2.0--2.1bad.sql', + 'test_ext7--2.0--2.2bad.sql', 'test_ext7.control', 'test_ext8--1.0.sql', 'test_ext8.control', @@ -55,4 +57,9 @@ tests += { ], 'regress_args': ['--no-locale'], }, + 'tap': { + 'tests': [ + 't/001_extension_control_path.pl', + ], + }, } diff --git a/src/test/modules/test_extensions/sql/test_extensions.sql b/src/test/modules/test_extensions/sql/test_extensions.sql index 642c82ff5d381..b5878f6f80f14 100644 --- a/src/test/modules/test_extensions/sql/test_extensions.sql +++ b/src/test/modules/test_extensions/sql/test_extensions.sql @@ -28,6 +28,10 @@ create extension test_ext7; alter extension test_ext7 update to '2.0'; \dx+ test_ext7 +-- test reporting of errors in extension scripts +alter extension test_ext7 update to '2.1bad'; +alter extension test_ext7 update to '2.2bad'; + -- test handling of temp objects created by extensions create extension test_ext8; diff --git a/src/test/modules/test_extensions/t/001_extension_control_path.pl b/src/test/modules/test_extensions/t/001_extension_control_path.pl new file mode 100644 index 0000000000000..1a9c97bbf4dcc --- /dev/null +++ b/src/test/modules/test_extensions/t/001_extension_control_path.pl @@ -0,0 +1,125 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; +use File::Path qw(mkpath); +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('node'); + +$node->init; + +# Create a temporary directory for the extension control file +my $ext_dir = PostgreSQL::Test::Utils::tempdir(); +mkpath("$ext_dir/extension"); + +my $ext_name = "test_custom_ext_paths"; +create_extension($ext_name, $ext_dir); + +my $ext_name2 = "test_custom_ext_paths_using_directory"; +mkpath("$ext_dir/$ext_name2"); +create_extension($ext_name2, $ext_dir, $ext_name2); + +# Use the correct separator and escape \ when running on Windows. +my $sep = $windows_os ? ";" : ":"; +$node->append_conf( + 'postgresql.conf', qq{ +extension_control_path = '\$system$sep@{[ $windows_os ? ($ext_dir =~ s/\\/\\\\/gr) : $ext_dir ]}' +}); + +# Start node +$node->start; + +my $ecp = $node->safe_psql('postgres', 'show extension_control_path;'); + +is($ecp, "\$system$sep$ext_dir", + "custom extension control directory path configured"); + +$node->safe_psql('postgres', "CREATE EXTENSION $ext_name"); +$node->safe_psql('postgres', "CREATE EXTENSION $ext_name2"); + +my $ret = $node->safe_psql('postgres', + "select * from pg_available_extensions where name = '$ext_name'"); +is( $ret, + "test_custom_ext_paths|1.0|1.0|Test extension_control_path", + "extension is installed correctly on pg_available_extensions"); + +$ret = $node->safe_psql('postgres', + "select * from pg_available_extension_versions where name = '$ext_name'"); +is( $ret, + "test_custom_ext_paths|1.0|t|t|f|t|||Test extension_control_path", + "extension is installed correctly on pg_available_extension_versions"); + +$ret = $node->safe_psql('postgres', + "select * from pg_available_extensions where name = '$ext_name2'"); +is( $ret, + "test_custom_ext_paths_using_directory|1.0|1.0|Test extension_control_path", + "extension is installed correctly on pg_available_extensions"); + +$ret = $node->safe_psql('postgres', + "select * from pg_available_extension_versions where name = '$ext_name2'" +); +is( $ret, + "test_custom_ext_paths_using_directory|1.0|t|t|f|t|||Test extension_control_path", + "extension is installed correctly on pg_available_extension_versions"); + +# Ensure that extensions installed on $system is still visible when using with +# custom extension control path. +$ret = $node->safe_psql('postgres', + "select count(*) > 0 as ok from pg_available_extensions where name = 'plpgsql'" +); +is($ret, "t", + "\$system extension is installed correctly on pg_available_extensions"); + + +$ret = $node->safe_psql('postgres', + "set extension_control_path = ''; select count(*) > 0 as ok from pg_available_extensions where name = 'plpgsql'" +); +is($ret, "t", + "\$system extension is installed correctly on pg_available_extensions with empty extension_control_path" +); + +# Test with an extension that does not exists +my ($code, $stdout, $stderr) = + $node->psql('postgres', "CREATE EXTENSION invalid"); +is($code, 3, 'error to create an extension that does not exists'); +like($stderr, qr/ERROR: extension "invalid" is not available/); + +sub create_extension +{ + my ($ext_name, $ext_dir, $directory) = @_; + + my $control_file = "$ext_dir/extension/$ext_name.control"; + my $sql_file; + + if (defined $directory) + { + $sql_file = "$ext_dir/$directory/$ext_name--1.0.sql"; + } + else + { + $sql_file = "$ext_dir/extension/$ext_name--1.0.sql"; + } + + # Create .control .sql file + open my $cf, '>', $control_file + or die "Could not create control file: $!"; + print $cf "comment = 'Test extension_control_path'\n"; + print $cf "default_version = '1.0'\n"; + print $cf "relocatable = true\n"; + print $cf "directory = $directory" if defined $directory; + close $cf; + + # Create --1.0.sql file + open my $sqlf, '>', $sql_file or die "Could not create sql file: $!"; + print $sqlf "/* $sql_file */\n"; + print $sqlf + "-- complain if script is sourced in psql, rather than via CREATE EXTENSION\n"; + print $sqlf + qq'\\echo Use "CREATE EXTENSION $ext_name" to load this file. \\quit\n'; + close $sqlf; +} + +done_testing(); diff --git a/src/test/modules/test_extensions/test_ext7--2.0--2.1bad.sql b/src/test/modules/test_extensions/test_ext7--2.0--2.1bad.sql new file mode 100644 index 0000000000000..a055a2dbb2600 --- /dev/null +++ b/src/test/modules/test_extensions/test_ext7--2.0--2.1bad.sql @@ -0,0 +1,14 @@ +/* src/test/modules/test_extensions/test_ext7--2.0--2.1bad.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION test_ext7 UPDATE TO '2.1bad'" to load this file. \quit + +-- test reporting of a simple syntax error in an extension script +CREATE FUNCTION my_okay_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + 1 $$; + +CREATE FUNCTIN my_erroneous_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + 1 $$; + +CREATE FUNCTION my_other_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + 1 $$; diff --git a/src/test/modules/test_extensions/test_ext7--2.0--2.2bad.sql b/src/test/modules/test_extensions/test_ext7--2.0--2.2bad.sql new file mode 100644 index 0000000000000..19aa9bf264d1c --- /dev/null +++ b/src/test/modules/test_extensions/test_ext7--2.0--2.2bad.sql @@ -0,0 +1,13 @@ +/* src/test/modules/test_extensions/test_ext7--2.0--2.2bad.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION test_ext7 UPDATE TO '2.2bad'" to load this file. \quit + +-- test reporting of a nested syntax error in an extension script +SET LOCAL check_function_bodies = on; + +CREATE FUNCTION my_erroneous_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + , 1 $$; + +CREATE FUNCTION my_other_func(int) RETURNS int LANGUAGE SQL +AS $$ SELECT $1 + 1 $$; diff --git a/src/test/modules/test_ginpostinglist/meson.build b/src/test/modules/test_ginpostinglist/meson.build index e120071e86cc8..08ddf009723e0 100644 --- a/src/test/modules/test_ginpostinglist/meson.build +++ b/src/test/modules/test_ginpostinglist/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_ginpostinglist_sources = files( 'test_ginpostinglist.c', diff --git a/src/test/modules/test_ginpostinglist/test_ginpostinglist.c b/src/test/modules/test_ginpostinglist/test_ginpostinglist.c index 04215cadd998c..e1161bdfbfacf 100644 --- a/src/test/modules/test_ginpostinglist/test_ginpostinglist.c +++ b/src/test/modules/test_ginpostinglist/test_ginpostinglist.c @@ -3,7 +3,7 @@ * test_ginpostinglist.c * Test varbyte-encoding in ginpostinglist.c * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_ginpostinglist/test_ginpostinglist.c diff --git a/src/test/modules/test_integerset/meson.build b/src/test/modules/test_integerset/meson.build index afb1db09cd391..16e32e6e8916e 100644 --- a/src/test/modules/test_integerset/meson.build +++ b/src/test/modules/test_integerset/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_integerset_sources = files( 'test_integerset.c', diff --git a/src/test/modules/test_integerset/test_integerset.c b/src/test/modules/test_integerset/test_integerset.c index 61f8d0b663a9a..cfdc6762785de 100644 --- a/src/test/modules/test_integerset/test_integerset.c +++ b/src/test/modules/test_integerset/test_integerset.c @@ -3,7 +3,7 @@ * test_integerset.c * Test integer set data structure. * - * Copyright (c) 2019-2024, PostgreSQL Global Development Group + * Copyright (c) 2019-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_integerset/test_integerset.c @@ -15,10 +15,6 @@ #include "common/pg_prng.h" #include "fmgr.h" #include "lib/integerset.h" -#include "miscadmin.h" -#include "nodes/bitmapset.h" -#include "storage/block.h" -#include "storage/itemptr.h" #include "utils/memutils.h" #include "utils/timestamp.h" diff --git a/src/test/modules/test_json_parser/.gitignore b/src/test/modules/test_json_parser/.gitignore index 2c176672db770..f032d1e4f9042 100644 --- a/src/test/modules/test_json_parser/.gitignore +++ b/src/test/modules/test_json_parser/.gitignore @@ -1,3 +1,4 @@ tmp_check test_json_parser_perf test_json_parser_incremental +test_json_parser_incremental_shlib diff --git a/src/test/modules/test_json_parser/Makefile b/src/test/modules/test_json_parser/Makefile index 2dc7175b7c8fe..af3f19424ed88 100644 --- a/src/test/modules/test_json_parser/Makefile +++ b/src/test/modules/test_json_parser/Makefile @@ -6,7 +6,7 @@ TAP_TESTS = 1 OBJS = test_json_parser_incremental.o test_json_parser_perf.o $(WIN32RES) -EXTRA_CLEAN = test_json_parser_incremental$(X) test_json_parser_perf$(X) +EXTRA_CLEAN = test_json_parser_incremental$(X) test_json_parser_incremental_shlib$(X) test_json_parser_perf$(X) ifdef USE_PGXS PG_CONFIG = pg_config @@ -19,13 +19,16 @@ include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif -all: test_json_parser_incremental$(X) test_json_parser_perf$(X) +all: test_json_parser_incremental$(X) test_json_parser_incremental_shlib$(X) test_json_parser_perf$(X) %.o: $(top_srcdir)/$(subdir)/%.c test_json_parser_incremental$(X): test_json_parser_incremental.o $(WIN32RES) $(CC) $(CFLAGS) $^ $(PG_LIBS_INTERNAL) $(LDFLAGS) $(LDFLAGS_EX) $(PG_LIBS) $(LIBS) -o $@ +test_json_parser_incremental_shlib$(X): test_json_parser_incremental.o $(WIN32RES) + $(CC) $(CFLAGS) $^ $(LDFLAGS) -lpgcommon_excluded_shlib $(libpq_pgport_shlib) $(filter -lintl, $(LIBS)) -o $@ + test_json_parser_perf$(X): test_json_parser_perf.o $(WIN32RES) $(CC) $(CFLAGS) $^ $(PG_LIBS_INTERNAL) $(LDFLAGS) $(LDFLAGS_EX) $(PG_LIBS) $(LIBS) -o $@ diff --git a/src/test/modules/test_json_parser/meson.build b/src/test/modules/test_json_parser/meson.build index b224f3e07e2b8..5672045f4964d 100644 --- a/src/test/modules/test_json_parser/meson.build +++ b/src/test/modules/test_json_parser/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group test_json_parser_incremental_sources = files( 'test_json_parser_incremental.c', @@ -19,6 +19,18 @@ test_json_parser_incremental = executable('test_json_parser_incremental', }, ) +# A second version of test_json_parser_incremental, this time compiled against +# the shared-library flavor of jsonapi. +test_json_parser_incremental_shlib = executable('test_json_parser_incremental_shlib', + test_json_parser_incremental_sources, + dependencies: [frontend_shlib_code, libpq], + c_args: ['-DJSONAPI_SHLIB_ALLOC'], + link_with: [common_excluded_shlib], + kwargs: default_bin_args + { + 'install': false, + }, +) + test_json_parser_perf_sources = files( 'test_json_parser_perf.c', ) @@ -49,5 +61,10 @@ tests += { 't/003_test_semantic.pl', 't/004_test_parser_perf.pl' ], + 'deps': [ + test_json_parser_incremental, + test_json_parser_incremental_shlib, + test_json_parser_perf, + ], }, } diff --git a/src/test/modules/test_json_parser/t/001_test_json_parser_incremental.pl b/src/test/modules/test_json_parser/t/001_test_json_parser_incremental.pl index abf0d7a2375d1..80b01abd00e6e 100644 --- a/src/test/modules/test_json_parser/t/001_test_json_parser_incremental.pl +++ b/src/test/modules/test_json_parser/t/001_test_json_parser_incremental.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Test the incremental (table-driven) json parser. @@ -13,20 +13,28 @@ my $test_file = "$FindBin::RealBin/../tiny.json"; -my $exe = "test_json_parser_incremental"; +my @exes = ( + [ "test_json_parser_incremental", ], + [ "test_json_parser_incremental", "-o", ], + [ "test_json_parser_incremental_shlib", ], + [ "test_json_parser_incremental_shlib", "-o", ]); -# Test the usage error -my ($stdout, $stderr) = run_command([ $exe, "-c", 10 ]); -like($stderr, qr/Usage:/, 'error message if not enough arguments'); +foreach my $exe (@exes) +{ + note "testing executable @$exe"; -# Test that we get success for small chunk sizes from 64 down to 1. + # Test the usage error + my ($stdout, $stderr) = run_command([ @$exe, "-c", 10 ]); + like($stderr, qr/Usage:/, 'error message if not enough arguments'); -for (my $size = 64; $size > 0; $size--) -{ - ($stdout, $stderr) = run_command([ $exe, "-c", $size, $test_file ]); + # Test that we get success for small chunk sizes from 64 down to 1. + for (my $size = 64; $size > 0; $size--) + { + ($stdout, $stderr) = run_command([ @$exe, "-c", $size, $test_file ]); - like($stdout, qr/SUCCESS/, "chunk size $size: test succeeds"); - is($stderr, "", "chunk size $size: no error output"); + like($stdout, qr/SUCCESS/, "chunk size $size: test succeeds"); + is($stderr, "", "chunk size $size: no error output"); + } } done_testing(); diff --git a/src/test/modules/test_json_parser/t/002_inline.pl b/src/test/modules/test_json_parser/t/002_inline.pl index 8d62eb44c8cfa..7c8b64977ec7d 100644 --- a/src/test/modules/test_json_parser/t/002_inline.pl +++ b/src/test/modules/test_json_parser/t/002_inline.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test success or failure of the incremental (table-driven) JSON parser # for a variety of small inputs. @@ -13,13 +13,13 @@ use File::Temp qw(tempfile); my $dir = PostgreSQL::Test::Utils::tempdir; +my @exe; sub test { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($name, $json, %params) = @_; - my $exe = "test_json_parser_incremental"; my $chunk = length($json); # Test the input with chunk sizes from max(input_size, 64) down to 1 @@ -35,7 +35,7 @@ sub test foreach my $size (reverse(1 .. $chunk)) { - my ($stdout, $stderr) = run_command([ $exe, "-c", $size, $fname ]); + my ($stdout, $stderr) = run_command([ @exe, "-c", $size, $fname ]); if (defined($params{error})) { @@ -53,86 +53,102 @@ sub test } } -test("number", "12345"); -test("string", '"hello"'); -test("false", "false"); -test("true", "true"); -test("null", "null"); -test("empty object", "{}"); -test("empty array", "[]"); -test("array with number", "[12345]"); -test("array with numbers", "[12345,67890]"); -test("array with null", "[null]"); -test("array with string", '["hello"]'); -test("array with boolean", '[false]'); -test("single pair", '{"key": "value"}'); -test("heavily nested array", "[" x 3200 . "]" x 3200); -test("serial escapes", '"\\\\\\\\\\\\\\\\"'); -test("interrupted escapes", '"\\\\\\"\\\\\\\\\\"\\\\"'); -test("whitespace", ' "" '); - -test("unclosed empty object", - "{", error => qr/input string ended unexpectedly/); -test("bad key", "{{", error => qr/Expected string or "}", but found "\{"/); -test("bad key", "{{}", error => qr/Expected string or "}", but found "\{"/); -test("numeric key", "{1234: 2}", - error => qr/Expected string or "}", but found "1234"/); -test( - "second numeric key", - '{"a": "a", 1234: 2}', - error => qr/Expected string, but found "1234"/); -test( - "unclosed object with pair", - '{"key": "value"', - error => qr/input string ended unexpectedly/); -test("missing key value", - '{"key": }', error => qr/Expected JSON value, but found "}"/); -test( - "missing colon", - '{"key" 12345}', - error => qr/Expected ":", but found "12345"/); -test( - "missing comma", - '{"key": 12345 12345}', - error => qr/Expected "," or "}", but found "12345"/); -test("overnested array", - "[" x 6401, error => qr/maximum permitted depth is 6400/); -test("overclosed array", - "[]]", error => qr/Expected end of input, but found "]"/); -test("unexpected token in array", - "[ }}} ]", error => qr/Expected array element or "]", but found "}"/); -test("junk punctuation", "[ ||| ]", error => qr/Token "|" is invalid/); -test("missing comma in array", - "[123 123]", error => qr/Expected "," or "]", but found "123"/); -test("misspelled boolean", "tru", error => qr/Token "tru" is invalid/); -test( - "misspelled boolean in array", - "[tru]", - error => qr/Token "tru" is invalid/); -test("smashed top-level scalar", "12zz", - error => qr/Token "12zz" is invalid/); -test( - "smashed scalar in array", - "[12zz]", - error => qr/Token "12zz" is invalid/); -test( - "unknown escape sequence", - '"hello\vworld"', - error => qr/Escape sequence "\\v" is invalid/); -test("unescaped control", - "\"hello\tworld\"", - error => qr/Character with value 0x09 must be escaped/); -test( - "incorrect escape count", - '"\\\\\\\\\\\\\\"', - error => qr/Token ""\\\\\\\\\\\\\\"" is invalid/); - -# Case with three bytes: double-quote, backslash and . -# Both invalid-token and invalid-escape are possible errors, because for -# smaller chunk sizes the incremental parser skips the string parsing when -# it cannot find an ending quote. -test("incomplete UTF-8 sequence", - "\"\\\x{F5}", - error => qr/(Token|Escape sequence) ""?\\\x{F5}" is invalid/); +my @exes = ( + [ "test_json_parser_incremental", ], + [ "test_json_parser_incremental", "-o", ], + [ "test_json_parser_incremental_shlib", ], + [ "test_json_parser_incremental_shlib", "-o", ]); + +foreach (@exes) +{ + @exe = @$_; + note "testing executable @exe"; + + test("number", "12345"); + test("string", '"hello"'); + test("false", "false"); + test("true", "true"); + test("null", "null"); + test("empty object", "{}"); + test("empty array", "[]"); + test("array with number", "[12345]"); + test("array with numbers", "[12345,67890]"); + test("array with null", "[null]"); + test("array with string", '["hello"]'); + test("array with boolean", '[false]'); + test("single pair", '{"key": "value"}'); + test("heavily nested array", "[" x 3200 . "]" x 3200); + test("serial escapes", '"\\\\\\\\\\\\\\\\"'); + test("interrupted escapes", '"\\\\\\"\\\\\\\\\\"\\\\"'); + test("whitespace", ' "" '); + + test("unclosed empty object", + "{", error => qr/input string ended unexpectedly/); + test("bad key", "{{", + error => qr/Expected string or "}", but found "\{"/); + test("bad key", "{{}", + error => qr/Expected string or "}", but found "\{"/); + test("numeric key", "{1234: 2}", + error => qr/Expected string or "}", but found "1234"/); + test( + "second numeric key", + '{"a": "a", 1234: 2}', + error => qr/Expected string, but found "1234"/); + test( + "unclosed object with pair", + '{"key": "value"', + error => qr/input string ended unexpectedly/); + test("missing key value", + '{"key": }', error => qr/Expected JSON value, but found "}"/); + test( + "missing colon", + '{"key" 12345}', + error => qr/Expected ":", but found "12345"/); + test( + "missing comma", + '{"key": 12345 12345}', + error => qr/Expected "," or "}", but found "12345"/); + test("overnested array", + "[" x 6401, error => qr/maximum permitted depth is 6400/); + test("overclosed array", + "[]]", error => qr/Expected end of input, but found "]"/); + test("unexpected token in array", + "[ }}} ]", error => qr/Expected array element or "]", but found "}"/); + test("junk punctuation", "[ ||| ]", error => qr/Token "|" is invalid/); + test("missing comma in array", + "[123 123]", error => qr/Expected "," or "]", but found "123"/); + test("misspelled boolean", "tru", error => qr/Token "tru" is invalid/); + test( + "misspelled boolean in array", + "[tru]", + error => qr/Token "tru" is invalid/); + test( + "smashed top-level scalar", + "12zz", + error => qr/Token "12zz" is invalid/); + test( + "smashed scalar in array", + "[12zz]", + error => qr/Token "12zz" is invalid/); + test( + "unknown escape sequence", + '"hello\vworld"', + error => qr/Escape sequence "\\v" is invalid/); + test("unescaped control", + "\"hello\tworld\"", + error => qr/Character with value 0x09 must be escaped/); + test( + "incorrect escape count", + '"\\\\\\\\\\\\\\"', + error => qr/Token ""\\\\\\\\\\\\\\"" is invalid/); + + # Case with three bytes: double-quote, backslash and . + # Both invalid-token and invalid-escape are possible errors, because for + # smaller chunk sizes the incremental parser skips the string parsing when + # it cannot find an ending quote. + test("incomplete UTF-8 sequence", + "\"\\\x{F5}", + error => qr/(Token|Escape sequence) ""?\\\x{F5}" is invalid/); +} done_testing(); diff --git a/src/test/modules/test_json_parser/t/003_test_semantic.pl b/src/test/modules/test_json_parser/t/003_test_semantic.pl index b6553bbcddf05..7ba8b63467c82 100644 --- a/src/test/modules/test_json_parser/t/003_test_semantic.pl +++ b/src/test/modules/test_json_parser/t/003_test_semantic.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test the incremental JSON parser with semantic routines, and compare the # output with the expected output. @@ -16,24 +16,34 @@ my $test_file = "$FindBin::RealBin/../tiny.json"; my $test_out = "$FindBin::RealBin/../tiny.out"; -my $exe = "test_json_parser_incremental"; +my @exes = ( + [ "test_json_parser_incremental", ], + [ "test_json_parser_incremental", "-o", ], + [ "test_json_parser_incremental_shlib", ], + [ "test_json_parser_incremental_shlib", "-o", ]); -my ($stdout, $stderr) = run_command([ $exe, "-s", $test_file ]); +foreach my $exe (@exes) +{ + note "testing executable @$exe"; -is($stderr, "", "no error output"); + my ($stdout, $stderr) = run_command([ @$exe, "-s", $test_file ]); -my $dir = PostgreSQL::Test::Utils::tempdir; -my ($fh, $fname) = tempfile(DIR => $dir); + is($stderr, "", "no error output"); -print $fh $stdout, "\n"; + my $dir = PostgreSQL::Test::Utils::tempdir; + my ($fh, $fname) = tempfile(DIR => $dir); -close($fh); + print $fh $stdout, "\n"; -my @diffopts = ("-u"); -push(@diffopts, "--strip-trailing-cr") if $windows_os; -($stdout, $stderr) = run_command([ "diff", @diffopts, $fname, $test_out ]); + close($fh); -is($stdout, "", "no output diff"); -is($stderr, "", "no diff error"); + my @diffopts = ("-u"); + push(@diffopts, "--strip-trailing-cr") if $windows_os; + ($stdout, $stderr) = + run_command([ "diff", @diffopts, $fname, $test_out ]); + + is($stdout, "", "no output diff"); + is($stderr, "", "no diff error"); +} done_testing(); diff --git a/src/test/modules/test_json_parser/t/004_test_parser_perf.pl b/src/test/modules/test_json_parser/t/004_test_parser_perf.pl index 81b8c8ae42849..9ea21ee89907a 100644 --- a/src/test/modules/test_json_parser/t/004_test_parser_perf.pl +++ b/src/test/modules/test_json_parser/t/004_test_parser_perf.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test the JSON parser performance tester. Here we are just checking that # the performance tester can run, both with the standard parser and the diff --git a/src/test/modules/test_json_parser/test_json_parser_incremental.c b/src/test/modules/test_json_parser/test_json_parser_incremental.c index 47040e1e4217d..d1e3e4ab4ea59 100644 --- a/src/test/modules/test_json_parser/test_json_parser_incremental.c +++ b/src/test/modules/test_json_parser/test_json_parser_incremental.c @@ -3,7 +3,7 @@ * test_json_parser_incremental.c * Test program for incremental JSON parser * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_json_parser/test_json_parser_incremental.c @@ -18,6 +18,10 @@ * If the -s flag is given, the program does semantic processing. This should * just mirror back the json, albeit with white space changes. * + * If the -o flag is given, the JSONLEX_CTX_OWNS_TOKENS flag is set. (This can + * be used in combination with a leak sanitizer; without the option, the parser + * may leak memory with invalid JSON.) + * * The argument specifies the file containing the JSON input. * *------------------------------------------------------------------------- @@ -72,26 +76,33 @@ static JsonSemAction sem = { .scalar = do_scalar }; +static bool lex_owns_tokens = false; + int main(int argc, char **argv) { char buff[BUFSIZE]; FILE *json_file; JsonParseErrorType result; - JsonLexContext lex; + JsonLexContext *lex; StringInfoData json; int n_read; size_t chunk_size = DEFAULT_CHUNK_SIZE; struct stat statbuf; off_t bytes_left; - JsonSemAction *testsem = &nullSemAction; + const JsonSemAction *testsem = &nullSemAction; char *testfile; int c; bool need_strings = false; + int ret = 0; pg_logging_init(argv[0]); - while ((c = getopt(argc, argv, "c:s")) != -1) + lex = calloc(1, sizeof(JsonLexContext)); + if (!lex) + pg_fatal("out of memory"); + + while ((c = getopt(argc, argv, "c:os")) != -1) { switch (c) { @@ -100,10 +111,13 @@ main(int argc, char **argv) if (chunk_size > BUFSIZE) pg_fatal("chunk size cannot exceed %d", BUFSIZE); break; + case 'o': /* switch token ownership */ + lex_owns_tokens = true; + break; case 's': /* do semantic processing */ testsem = &sem; sem.semstate = palloc(sizeof(struct DoState)); - ((struct DoState *) sem.semstate)->lex = &lex; + ((struct DoState *) sem.semstate)->lex = lex; ((struct DoState *) sem.semstate)->buf = makeStringInfo(); need_strings = true; break; @@ -112,7 +126,7 @@ main(int argc, char **argv) if (optind < argc) { - testfile = pg_strdup(argv[optind]); + testfile = argv[optind]; optind++; } else @@ -121,7 +135,8 @@ main(int argc, char **argv) exit(1); } - makeJsonLexContextIncremental(&lex, PG_UTF8, need_strings); + makeJsonLexContextIncremental(lex, PG_UTF8, need_strings); + setJsonLexContextOwnsTokens(lex, lex_owns_tokens); initStringInfo(&json); if ((json_file = fopen(testfile, PG_BINARY_R)) == NULL) @@ -154,33 +169,41 @@ main(int argc, char **argv) bytes_left -= n_read; if (bytes_left > 0) { - result = pg_parse_json_incremental(&lex, testsem, + result = pg_parse_json_incremental(lex, testsem, json.data, n_read, false); if (result != JSON_INCOMPLETE) { - fprintf(stderr, "%s\n", json_errdetail(result, &lex)); - exit(1); + fprintf(stderr, "%s\n", json_errdetail(result, lex)); + ret = 1; + goto cleanup; } resetStringInfo(&json); } else { - result = pg_parse_json_incremental(&lex, testsem, + result = pg_parse_json_incremental(lex, testsem, json.data, n_read, true); if (result != JSON_SUCCESS) { - fprintf(stderr, "%s\n", json_errdetail(result, &lex)); - exit(1); + fprintf(stderr, "%s\n", json_errdetail(result, lex)); + ret = 1; + goto cleanup; } if (!need_strings) printf("SUCCESS!\n"); break; } } + +cleanup: fclose(json_file); - exit(0); + freeJsonLexContext(lex); + free(json.data); + free(lex); + + return ret; } /* @@ -230,7 +253,8 @@ do_object_field_start(void *state, char *fname, bool isnull) static JsonParseErrorType do_object_field_end(void *state, char *fname, bool isnull) { - /* nothing to do really */ + if (!lex_owns_tokens) + free(fname); return JSON_SUCCESS; } @@ -291,6 +315,9 @@ do_scalar(void *state, char *token, JsonTokenType tokentype) else printf("%s", token); + if (!lex_owns_tokens) + free(token); + return JSON_SUCCESS; } @@ -343,7 +370,8 @@ usage(const char *progname) { fprintf(stderr, "Usage: %s [OPTION ...] testfile\n", progname); fprintf(stderr, "Options:\n"); - fprintf(stderr, " -c chunksize size of piece fed to parser (default 64)n"); + fprintf(stderr, " -c chunksize size of piece fed to parser (default 64)\n"); + fprintf(stderr, " -o set JSONLEX_CTX_OWNS_TOKENS for leak checking\n"); fprintf(stderr, " -s do semantic processing\n"); } diff --git a/src/test/modules/test_json_parser/test_json_parser_perf.c b/src/test/modules/test_json_parser/test_json_parser_perf.c index 74cc5f3f54875..e48360b6daae3 100644 --- a/src/test/modules/test_json_parser/test_json_parser_perf.c +++ b/src/test/modules/test_json_parser/test_json_parser_perf.c @@ -3,7 +3,7 @@ * test_json_parser_perf.c * Performance test program for both flavors of the JSON parser * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_json_parser/test_json_parser_perf.c diff --git a/src/test/modules/test_lfind/meson.build b/src/test/modules/test_lfind/meson.build index fe6bc9ecb7fa1..6ae9b3c95eaf0 100644 --- a/src/test/modules/test_lfind/meson.build +++ b/src/test/modules/test_lfind/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_lfind_sources = files( 'test_lfind.c', diff --git a/src/test/modules/test_lfind/test_lfind.c b/src/test/modules/test_lfind/test_lfind.c index c04bc2f6b420e..8dcaa8f9fdaec 100644 --- a/src/test/modules/test_lfind/test_lfind.c +++ b/src/test/modules/test_lfind/test_lfind.c @@ -3,7 +3,7 @@ * test_lfind.c * Test correctness of optimized linear search functions. * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_lfind/test_lfind.c diff --git a/src/test/modules/test_misc/Makefile b/src/test/modules/test_misc/Makefile index a958d156f47fd..919a25fc67fd3 100644 --- a/src/test/modules/test_misc/Makefile +++ b/src/test/modules/test_misc/Makefile @@ -4,7 +4,7 @@ TAP_TESTS = 1 EXTRA_INSTALL=src/test/modules/injection_points -export enable_injection_points enable_injection_points +export enable_injection_points ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build index 283ffa751aa29..9c50de7efb0f7 100644 --- a/src/test/modules/test_misc/meson.build +++ b/src/test/modules/test_misc/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'test_misc', @@ -15,6 +15,7 @@ tests += { 't/004_io_direct.pl', 't/005_timeouts.pl', 't/006_signal_autovacuum.pl', + 't/007_catcache_inval.pl', ], }, } diff --git a/src/test/modules/test_misc/t/001_constraint_validation.pl b/src/test/modules/test_misc/t/001_constraint_validation.pl index 9e5ff3a5f5695..1d86936ec6947 100644 --- a/src/test/modules/test_misc/t/001_constraint_validation.pl +++ b/src/test/modules/test_misc/t/001_constraint_validation.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Verify that ALTER TABLE optimizes certain operations as expected diff --git a/src/test/modules/test_misc/t/002_tablespace.pl b/src/test/modules/test_misc/t/002_tablespace.pl index 3f258fd69a2b5..b8a5617c78817 100644 --- a/src/test/modules/test_misc/t/002_tablespace.pl +++ b/src/test/modules/test_misc/t/002_tablespace.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Simple tablespace tests that can't be replicated on the same host # due to the use of absolute paths, so we keep them out of the regular diff --git a/src/test/modules/test_misc/t/003_check_guc.pl b/src/test/modules/test_misc/t/003_check_guc.pl index 3ae4bb1cd9ddd..5ae23192a47c9 100644 --- a/src/test/modules/test_misc/t/003_check_guc.pl +++ b/src/test/modules/test_misc/t/003_check_guc.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Tests to cross-check the consistency of GUC parameters with # postgresql.conf.sample. @@ -56,7 +56,7 @@ # file. # - Valid configuration options are followed immediately by " = ", # with one space before and after the equal sign. - if ($line =~ m/^#?([_[:alpha:]]+) = .*/) + if ($line =~ m/^#?([_[:alnum:]]+) = .*/) { # Lower-case conversion matters for some of the GUCs. my $param_name = lc($1); diff --git a/src/test/modules/test_misc/t/004_io_direct.pl b/src/test/modules/test_misc/t/004_io_direct.pl index b79ceba000c02..44984e5fd42a5 100644 --- a/src/test/modules/test_misc/t/004_io_direct.pl +++ b/src/test/modules/test_misc/t/004_io_direct.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Very simple exercise of direct I/O GUC. diff --git a/src/test/modules/test_misc/t/005_timeouts.pl b/src/test/modules/test_misc/t/005_timeouts.pl index 9e1ff9e5c1c66..cdce2afd93569 100644 --- a/src/test/modules/test_misc/t/005_timeouts.pl +++ b/src/test/modules/test_misc/t/005_timeouts.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -24,6 +24,15 @@ my $node = PostgreSQL::Test::Cluster->new('master'); $node->init(); $node->start; + +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + $node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); # diff --git a/src/test/modules/test_misc/t/006_signal_autovacuum.pl b/src/test/modules/test_misc/t/006_signal_autovacuum.pl index 51bdefe24aaa5..e868510931787 100644 --- a/src/test/modules/test_misc/t/006_signal_autovacuum.pl +++ b/src/test/modules/test_misc/t/006_signal_autovacuum.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Test signaling autovacuum worker with pg_signal_autovacuum_worker. # @@ -7,7 +7,7 @@ # at the beginning of the autovacuum worker startup. use strict; -use warnings; +use warnings FATAL => 'all'; use PostgreSQL::Test::Cluster; use Test::More; @@ -25,6 +25,15 @@ # This ensures a quick worker spawn. $node->append_conf('postgresql.conf', 'autovacuum_naptime = 1'); $node->start; + +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + $node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); $node->safe_psql( @@ -67,7 +76,7 @@ my $offset = -s $node->logfile; -# Role with pg_signal_autovacuum can terminate autovacuum worker. +# Role with pg_signal_autovacuum_worker can terminate autovacuum worker. my $terminate_with_pg_signal_av = $node->psql( 'postgres', qq( SET ROLE regress_worker_role; diff --git a/src/test/modules/test_misc/t/007_catcache_inval.pl b/src/test/modules/test_misc/t/007_catcache_inval.pl new file mode 100644 index 0000000000000..422301b534222 --- /dev/null +++ b/src/test/modules/test_misc/t/007_catcache_inval.pl @@ -0,0 +1,98 @@ + +# Copyright (c) 2025, PostgreSQL Global Development Group + +# Test recursive catalog cache invalidation, i.e. invalidation while a +# catalog cache entry is being built. + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +# Node initialization +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init(); +$node->start; + +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); + + +sub randStr +{ + my $len = shift; + my @chars = ("A" .. "Z", "a" .. "z", "0" .. "9"); + return join '', map { @chars[ rand @chars ] } 1 .. $len; +} + +# Create a function with a large body, so that it is toasted. +my $longtext = randStr(10000); +$node->safe_psql( + 'postgres', qq[ + CREATE FUNCTION foofunc(dummy integer) RETURNS integer AS \$\$ SELECT 1; /* $longtext */ \$\$ LANGUAGE SQL +]); + +my $psql_session = $node->background_psql('postgres'); +my $psql_session2 = $node->background_psql('postgres'); + +# Set injection point in the session, to pause while populating the +# catcache list +$psql_session->query_safe( + qq[ + SELECT injection_points_set_local(); + SELECT injection_points_attach('catcache-list-miss-systable-scan-started', 'wait'); +]); + +# This pauses on the injection point while populating catcache list +# for functions with name "foofunc" +$psql_session->query_until( + qr/starting_bg_psql/, q( + \echo starting_bg_psql + SELECT foofunc(1); +)); + +# While the first session is building the catcache list, create a new +# function that overloads the same name. This sends a catcache +# invalidation. +$node->safe_psql( + 'postgres', qq[ + CREATE FUNCTION foofunc() RETURNS integer AS \$\$ SELECT 123 \$\$ LANGUAGE SQL +]); + +# Continue the paused session. It will continue to construct the +# catcache list, and will accept invalidations while doing that. +# +# (The fact that the first function has a large body is crucial, +# because the cache invalidation is accepted during detoasting. If +# the body is not toasted, the invalidation is processed after +# building the catcache list, which avoids the recursion that we are +# trying to exercise here.) +# +# The "SELECT foofunc(1)" query will now finish. +$psql_session2->query_safe( + qq[ + SELECT injection_points_wakeup('catcache-list-miss-systable-scan-started'); + SELECT injection_points_detach('catcache-list-miss-systable-scan-started'); +]); + +# Test that the new function is visible to the session. +$psql_session->query_safe("SELECT foofunc();"); + +ok($psql_session->quit); +ok($psql_session2->quit); + +done_testing(); diff --git a/src/test/modules/test_oat_hooks/meson.build b/src/test/modules/test_oat_hooks/meson.build index 02c9c790ecd9c..1e600b0f4c7d0 100644 --- a/src/test/modules/test_oat_hooks/meson.build +++ b/src/test/modules/test_oat_hooks/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_oat_hooks_sources = files( 'test_oat_hooks.c', diff --git a/src/test/modules/test_oat_hooks/test_oat_hooks.c b/src/test/modules/test_oat_hooks/test_oat_hooks.c index 05c33712254c7..447cbbd03dee5 100644 --- a/src/test/modules/test_oat_hooks/test_oat_hooks.c +++ b/src/test/modules/test_oat_hooks/test_oat_hooks.c @@ -3,7 +3,7 @@ * test_oat_hooks.c * Code for testing mandatory access control (MAC) using object access hooks. * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_oat_hooks/test_oat_hooks.c @@ -16,7 +16,6 @@ #include "access/parallel.h" #include "catalog/dependency.h" #include "catalog/objectaccess.h" -#include "catalog/pg_proc.h" #include "executor/executor.h" #include "fmgr.h" #include "miscadmin.h" diff --git a/src/test/modules/test_parser/meson.build b/src/test/modules/test_parser/meson.build index d66c23334f8af..0e13469fafc2a 100644 --- a/src/test/modules/test_parser/meson.build +++ b/src/test/modules/test_parser/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_parser_sources = files( 'test_parser.c', diff --git a/src/test/modules/test_parser/test_parser.c b/src/test/modules/test_parser/test_parser.c index f3de7d8abf721..15ed3617cb50e 100644 --- a/src/test/modules/test_parser/test_parser.c +++ b/src/test/modules/test_parser/test_parser.c @@ -3,7 +3,7 @@ * test_parser.c * Simple example of a text search parser * - * Copyright (c) 2007-2024, PostgreSQL Global Development Group + * Copyright (c) 2007-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_parser/test_parser.c diff --git a/src/test/modules/test_pg_dump/expected/test_pg_dump.out b/src/test/modules/test_pg_dump/expected/test_pg_dump.out index 3536d636d8ea2..98c9cd481e7f8 100644 --- a/src/test/modules/test_pg_dump/expected/test_pg_dump.out +++ b/src/test/modules/test_pg_dump/expected/test_pg_dump.out @@ -36,6 +36,8 @@ CREATE FUNCTION casttesttype_out(casttesttype) AS 'textout' LANGUAGE internal STRICT IMMUTABLE; NOTICE: argument type casttesttype is only a shell +LINE 1: CREATE FUNCTION casttesttype_out(casttesttype) + ^ CREATE TYPE casttesttype ( internallength = variable, input = casttesttype_in, diff --git a/src/test/modules/test_pg_dump/meson.build b/src/test/modules/test_pg_dump/meson.build index 9b29ec20b6627..d8e1719586aee 100644 --- a/src/test/modules/test_pg_dump/meson.build +++ b/src/test/modules/test_pg_dump/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_install_data += files( 'test_pg_dump.control', diff --git a/src/test/modules/test_pg_dump/t/001_base.pl b/src/test/modules/test_pg_dump/t/001_base.pl index e2579e29cd866..adcaa419616cd 100644 --- a/src/test/modules/test_pg_dump/t/001_base.pl +++ b/src/test/modules/test_pg_dump/t/001_base.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -47,131 +47,149 @@ binary_upgrade => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/binary_upgrade.sql", '--schema-only', - '--binary-upgrade', '--dbname=postgres', + '--file' => "$tempdir/binary_upgrade.sql", + '--schema-only', '--sequence-data', '--binary-upgrade', + '--dbname' => 'postgres', ], }, clean => { dump_cmd => [ - 'pg_dump', "--file=$tempdir/clean.sql", - '-c', '--no-sync', - '--dbname=postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/clean.sql", + '--clean', + '--dbname' => 'postgres', ], }, clean_if_exists => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/clean_if_exists.sql", - '-c', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/clean_if_exists.sql", + '--clean', '--if-exists', - '--encoding=UTF8', # no-op, just tests that option is accepted + '--encoding' => 'UTF8', # no-op, just tests that it is accepted 'postgres', ], }, createdb => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/createdb.sql", - '-C', - '-R', # no-op, just for testing + 'pg_dump', '--no-sync', + '--file' => "$tempdir/createdb.sql", + '--create', + '--no-reconnect', # no-op, just for testing 'postgres', ], }, data_only => { dump_cmd => [ - 'pg_dump', - '--no-sync', - "--file=$tempdir/data_only.sql", - '-a', - '-v', # no-op, just make sure it works + 'pg_dump', '--no-sync', + '--file' => "$tempdir/data_only.sql", + '--data-only', + '--verbose', # no-op, just make sure it works 'postgres', ], }, defaults => { - dump_cmd => [ 'pg_dump', '-f', "$tempdir/defaults.sql", 'postgres', ], + dump_cmd => [ + 'pg_dump', + '--file' => "$tempdir/defaults.sql", + 'postgres', + ], }, defaults_custom_format => { test_key => 'defaults', compile_option => 'gzip', dump_cmd => [ - 'pg_dump', '--no-sync', '-Fc', '-Z6', - "--file=$tempdir/defaults_custom_format.dump", 'postgres', + 'pg_dump', '--no-sync', + '--format' => 'custom', + '--compress' => 6, + '--file' => "$tempdir/defaults_custom_format.dump", + 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/defaults_custom_format.sql", + '--file' => "$tempdir/defaults_custom_format.sql", "$tempdir/defaults_custom_format.dump", ], }, defaults_dir_format => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '--no-sync', '-Fd', - "--file=$tempdir/defaults_dir_format", 'postgres', + 'pg_dump', '--no-sync', + '--format' => 'directory', + '--file' => "$tempdir/defaults_dir_format", + 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/defaults_dir_format.sql", + '--file' => "$tempdir/defaults_dir_format.sql", "$tempdir/defaults_dir_format", ], }, defaults_parallel => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '--no-sync', '-Fd', '-j2', - "--file=$tempdir/defaults_parallel", 'postgres', + 'pg_dump', '--no-sync', + '--format' => 'directory', + '--jobs' => 2, + '--file' => "$tempdir/defaults_parallel", + 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/defaults_parallel.sql", + '--file' => "$tempdir/defaults_parallel.sql", "$tempdir/defaults_parallel", ], }, defaults_tar_format => { test_key => 'defaults', dump_cmd => [ - 'pg_dump', '--no-sync', '-Ft', - "--file=$tempdir/defaults_tar_format.tar", 'postgres', + 'pg_dump', '--no-sync', + '--format' => 'tar', + '--file' => "$tempdir/defaults_tar_format.tar", + 'postgres', ], restore_cmd => [ 'pg_restore', - "--file=$tempdir/defaults_tar_format.sql", + '--file' => "$tempdir/defaults_tar_format.sql", "$tempdir/defaults_tar_format.tar", ], }, exclude_table => { dump_cmd => [ 'pg_dump', - '--exclude-table=regress_table_dumpable', - "--file=$tempdir/exclude_table.sql", + '--exclude-table' => 'regress_table_dumpable', + '--file' => "$tempdir/exclude_table.sql", 'postgres', ], }, extension_schema => { dump_cmd => [ - 'pg_dump', '--schema=public', - "--file=$tempdir/extension_schema.sql", 'postgres', + 'pg_dump', + '--schema' => 'public', + '--file' => "$tempdir/extension_schema.sql", + 'postgres', ], }, pg_dumpall_globals => { dump_cmd => [ 'pg_dumpall', '--no-sync', - "--file=$tempdir/pg_dumpall_globals.sql", '-g', + '--file' => "$tempdir/pg_dumpall_globals.sql", + '--globals-only', ], }, no_privs => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_privs.sql", '-x', + '--file' => "$tempdir/no_privs.sql", + '--no-privileges', 'postgres', ], }, no_owner => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/no_owner.sql", '-O', + '--file' => "$tempdir/no_owner.sql", + '--no-owner', 'postgres', ], }, @@ -181,59 +199,68 @@ privileged_internals => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/privileged_internals.sql", + '--file' => "$tempdir/privileged_internals.sql", # these two tables are irrelevant to the test case - '--exclude-table=regress_pg_dump_schema.external_tab', - '--exclude-table=regress_pg_dump_schema.extdependtab', - '--username=regress_dump_login_role', 'postgres', + '--exclude-table' => 'regress_pg_dump_schema.external_tab', + '--exclude-table' => 'regress_pg_dump_schema.extdependtab', + '--username' => 'regress_dump_login_role', + 'postgres', ], }, schema_only => { dump_cmd => [ - 'pg_dump', '--no-sync', "--file=$tempdir/schema_only.sql", - '-s', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/schema_only.sql", + '--schema-only', 'postgres', ], }, section_pre_data => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/section_pre_data.sql", '--section=pre-data', + '--file' => "$tempdir/section_pre_data.sql", + '--section' => 'pre-data', 'postgres', ], }, section_data => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/section_data.sql", '--section=data', + '--file' => "$tempdir/section_data.sql", + '--section' => 'data', 'postgres', ], }, section_post_data => { dump_cmd => [ - 'pg_dump', '--no-sync', "--file=$tempdir/section_post_data.sql", - '--section=post-data', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/section_post_data.sql", + '--section' => 'post-data', + 'postgres', ], }, with_extension => { dump_cmd => [ - 'pg_dump', '--no-sync', "--file=$tempdir/with_extension.sql", - '--extension=test_pg_dump', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/with_extension.sql", + '--extension' => 'test_pg_dump', + 'postgres', ], }, exclude_extension => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/exclude_extension.sql", - '--exclude-extension=test_pg_dump', 'postgres', + '--file' => "$tempdir/exclude_extension.sql", + '--exclude-extension' => 'test_pg_dump', + 'postgres', ], }, exclude_extension_filter => { dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/exclude_extension_filter.sql", - "--filter=$tempdir/exclude_extension_filter.txt", + '--file' => "$tempdir/exclude_extension_filter.sql", + '--filter' => "$tempdir/exclude_extension_filter.txt", 'postgres', ], }, @@ -241,8 +268,10 @@ # plpgsql in the list blocks the dump of extension test_pg_dump without_extension => { dump_cmd => [ - 'pg_dump', '--no-sync', "--file=$tempdir/without_extension.sql", - '--extension=plpgsql', 'postgres', + 'pg_dump', '--no-sync', + '--file' => "$tempdir/without_extension.sql", + '--extension' => 'plpgsql', + 'postgres', ], }, @@ -253,9 +282,9 @@ dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/without_extension_explicit_schema.sql", - '--extension=plpgsql', - '--schema=public', + '--file' => "$tempdir/without_extension_explicit_schema.sql", + '--extension' => 'plpgsql', + '--schema' => 'public', 'postgres', ], }, @@ -267,9 +296,9 @@ dump_cmd => [ 'pg_dump', '--no-sync', - "--file=$tempdir/without_extension_internal_schema.sql", - '--extension=plpgsql', - '--schema=regress_pg_dump_schema', + '--file' => "$tempdir/without_extension_internal_schema.sql", + '--extension' => 'plpgsql', + '--schema' => 'regress_pg_dump_schema', 'postgres', ], },); @@ -840,7 +869,7 @@ # Create a PG instance to test actually dumping from my $node = PostgreSQL::Test::Cluster->new('main'); -$node->init('auth_extra' => [ '--create-role', 'regress_dump_login_role' ]); +$node->init(auth_extra => [ '--create-role' => 'regress_dump_login_role' ]); $node->start; my $port = $node->port; diff --git a/src/test/modules/test_predtest/meson.build b/src/test/modules/test_predtest/meson.build index 05c71b5b79fd6..738b76b6ab842 100644 --- a/src/test/modules/test_predtest/meson.build +++ b/src/test/modules/test_predtest/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_predtest_sources = files( 'test_predtest.c', diff --git a/src/test/modules/test_predtest/test_predtest.c b/src/test/modules/test_predtest/test_predtest.c index 27ac136ca5d46..be5b8c409146b 100644 --- a/src/test/modules/test_predtest/test_predtest.c +++ b/src/test/modules/test_predtest/test_predtest.c @@ -3,7 +3,7 @@ * test_predtest.c * Test correctness of optimizer's predicate proof logic. * - * Copyright (c) 2018-2024, PostgreSQL Global Development Group + * Copyright (c) 2018-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_predtest/test_predtest.c @@ -54,8 +54,7 @@ test_predtest(PG_FUNCTION_ARGS) int i; /* We use SPI to parse, plan, and execute the test query */ - if (SPI_connect() != SPI_OK_CONNECT) - elog(ERROR, "SPI_connect failed"); + SPI_connect(); /* * First, plan and execute the query, and inspect the results. To the diff --git a/src/test/modules/test_radixtree/meson.build b/src/test/modules/test_radixtree/meson.build index 4a541a78ca48b..02b77c37d497c 100644 --- a/src/test/modules/test_radixtree/meson.build +++ b/src/test/modules/test_radixtree/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group test_radixtree_sources = files( 'test_radixtree.c', diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c index 1d9165a3a234c..32de6a3123e4d 100644 --- a/src/test/modules/test_radixtree/test_radixtree.c +++ b/src/test/modules/test_radixtree/test_radixtree.c @@ -3,7 +3,7 @@ * test_radixtree.c * Test module for adaptive radix tree. * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_radixtree/test_radixtree.c @@ -15,16 +15,12 @@ #include "common/int.h" #include "common/pg_prng.h" #include "fmgr.h" -#include "miscadmin.h" -#include "storage/lwlock.h" #include "utils/memutils.h" #include "utils/timestamp.h" /* uncomment to use shared memory for the tree */ /* #define TEST_SHARED_RT */ -#define UINT64_HEX_FORMAT "%" INT64_MODIFIER "X" - /* Convenient macros to test results */ #define EXPECT_TRUE(expr) \ do { \ @@ -124,25 +120,22 @@ PG_FUNCTION_INFO_V1(test_radixtree); static void test_empty(void) { - MemoryContext radixtree_ctx; rt_radix_tree *radixtree; rt_iter *iter; uint64 key; #ifdef TEST_SHARED_RT int tranche_id = LWLockNewTrancheId(); dsa_area *dsa; -#endif - - radixtree_ctx = AllocSetContextCreate(CurrentMemoryContext, - "test_radix_tree", - ALLOCSET_SMALL_SIZES); -#ifdef TEST_SHARED_RT LWLockRegisterTranche(tranche_id, "test_radix_tree"); dsa = dsa_create(tranche_id); - - radixtree = rt_create(radixtree_ctx, dsa, tranche_id); + radixtree = rt_create(dsa, tranche_id); #else + MemoryContext radixtree_ctx; + + radixtree_ctx = AllocSetContextCreate(CurrentMemoryContext, + "test_radix_tree", + ALLOCSET_SMALL_SIZES); radixtree = rt_create(radixtree_ctx); #endif @@ -169,7 +162,6 @@ test_empty(void) static void test_basic(rt_node_class_test_elem *test_info, int shift, bool asc) { - MemoryContext radixtree_ctx; rt_radix_tree *radixtree; rt_iter *iter; uint64 *keys; @@ -177,18 +169,16 @@ test_basic(rt_node_class_test_elem *test_info, int shift, bool asc) #ifdef TEST_SHARED_RT int tranche_id = LWLockNewTrancheId(); dsa_area *dsa; -#endif - radixtree_ctx = AllocSetContextCreate(CurrentMemoryContext, - "test_radix_tree", - ALLOCSET_SMALL_SIZES); - -#ifdef TEST_SHARED_RT LWLockRegisterTranche(tranche_id, "test_radix_tree"); dsa = dsa_create(tranche_id); - - radixtree = rt_create(radixtree_ctx, dsa, tranche_id); + radixtree = rt_create(dsa, tranche_id); #else + MemoryContext radixtree_ctx; + + radixtree_ctx = AllocSetContextCreate(CurrentMemoryContext, + "test_radix_tree", + ALLOCSET_SMALL_SIZES); radixtree = rt_create(radixtree_ctx); #endif @@ -304,7 +294,6 @@ key_cmp(const void *a, const void *b) static void test_random(void) { - MemoryContext radixtree_ctx; rt_radix_tree *radixtree; rt_iter *iter; pg_prng_state state; @@ -317,18 +306,17 @@ test_random(void) #ifdef TEST_SHARED_RT int tranche_id = LWLockNewTrancheId(); dsa_area *dsa; -#endif - - radixtree_ctx = AllocSetContextCreate(CurrentMemoryContext, - "test_radix_tree", - ALLOCSET_SMALL_SIZES); -#ifdef TEST_SHARED_RT LWLockRegisterTranche(tranche_id, "test_radix_tree"); dsa = dsa_create(tranche_id); - - radixtree = rt_create(radixtree_ctx, dsa, tranche_id); + radixtree = rt_create(dsa, tranche_id); #else + MemoryContext radixtree_ctx; + + radixtree_ctx = SlabContextCreate(CurrentMemoryContext, + "test_radix_tree", + SLAB_DEFAULT_BLOCK_SIZE, + sizeof(TestValueType)); radixtree = rt_create(radixtree_ctx); #endif diff --git a/src/test/modules/test_rbtree/meson.build b/src/test/modules/test_rbtree/meson.build index baa7665349685..f98e4b2bc6ef8 100644 --- a/src/test/modules/test_rbtree/meson.build +++ b/src/test/modules/test_rbtree/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_rbtree_sources = files( 'test_rbtree.c', diff --git a/src/test/modules/test_rbtree/test_rbtree.c b/src/test/modules/test_rbtree/test_rbtree.c index 3e76d27bf101e..9113f1c8d52a0 100644 --- a/src/test/modules/test_rbtree/test_rbtree.c +++ b/src/test/modules/test_rbtree/test_rbtree.c @@ -3,7 +3,7 @@ * test_rbtree.c * Test correctness of red-black tree operations. * - * Copyright (c) 2009-2024, PostgreSQL Global Development Group + * Copyright (c) 2009-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_rbtree/test_rbtree.c diff --git a/src/test/modules/test_regex/expected/test_regex.out b/src/test/modules/test_regex/expected/test_regex.out index 731ba506d3545..c44c717edf4cf 100644 --- a/src/test/modules/test_regex/expected/test_regex.out +++ b/src/test/modules/test_regex/expected/test_regex.out @@ -2071,6 +2071,20 @@ select * from test_regex('[\s\S]*', '012 3456789abc_*', 'LNPE'); {"012 3456789abc_*"} (2 rows) +-- bug #18708: +select * from test_regex('(?:[^\d\D]){0}', '0123456789abc*', 'LNPQE'); + test_regex +-------------------------------------------------------------------- + {0,REG_UBOUNDS,REG_UBBS,REG_UNONPOSIX,REG_ULOCALE,REG_UEMPTYMATCH} + {""} +(2 rows) + +select * from test_regex('[^\d\D]', '0123456789abc*', 'ILPE'); + test_regex +-------------------------------------------------------- + {0,REG_UBBS,REG_UNONPOSIX,REG_ULOCALE,REG_UIMPOSSIBLE} +(1 row) + -- check char classes' handling of newlines select * from test_regex('\s+', E'abc \n def', 'LP'); test_regex diff --git a/src/test/modules/test_regex/meson.build b/src/test/modules/test_regex/meson.build index 254d29834ff3b..a3e20fa3c9464 100644 --- a/src/test/modules/test_regex/meson.build +++ b/src/test/modules/test_regex/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_regex_sources = files( 'test_regex.c', diff --git a/src/test/modules/test_regex/sql/test_regex.sql b/src/test/modules/test_regex/sql/test_regex.sql index 478fa2c547528..b2a847577e805 100644 --- a/src/test/modules/test_regex/sql/test_regex.sql +++ b/src/test/modules/test_regex/sql/test_regex.sql @@ -619,6 +619,9 @@ select * from test_regex('[^1\D0]', 'abc0123456789*', 'LPE'); select * from test_regex('\W', '0123456789abc_*', 'LP'); select * from test_regex('[\W]', '0123456789abc_*', 'LPE'); select * from test_regex('[\s\S]*', '012 3456789abc_*', 'LNPE'); +-- bug #18708: +select * from test_regex('(?:[^\d\D]){0}', '0123456789abc*', 'LNPQE'); +select * from test_regex('[^\d\D]', '0123456789abc*', 'ILPE'); -- check char classes' handling of newlines select * from test_regex('\s+', E'abc \n def', 'LP'); diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c index c4ef15d7425bf..2548a0ef7b159 100644 --- a/src/test/modules/test_regex/test_regex.c +++ b/src/test/modules/test_regex/test_regex.c @@ -3,7 +3,7 @@ * test_regex.c * Test harness for the regular expression package. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -15,7 +15,6 @@ #include "postgres.h" #include "funcapi.h" -#include "miscadmin.h" #include "regex/regex.h" #include "utils/array.h" #include "utils/builtins.h" @@ -114,7 +113,7 @@ test_regex(PG_FUNCTION_ARGS) (matchctx->npatterns + 1)); MemoryContextSwitchTo(oldcontext); - funcctx->user_fctx = (void *) matchctx; + funcctx->user_fctx = matchctx; /* * Return the first result row, which is info equivalent to Tcl's diff --git a/src/test/modules/test_resowner/meson.build b/src/test/modules/test_resowner/meson.build index 6ab2eec0b2f8e..b1ae1fc76ea3c 100644 --- a/src/test/modules/test_resowner/meson.build +++ b/src/test/modules/test_resowner/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_resowner_sources = files( 'test_resowner_basic.c', diff --git a/src/test/modules/test_resowner/test_resowner_basic.c b/src/test/modules/test_resowner/test_resowner_basic.c index 558cf1de56ebd..8f7949963719f 100644 --- a/src/test/modules/test_resowner/test_resowner_basic.c +++ b/src/test/modules/test_resowner/test_resowner_basic.c @@ -3,7 +3,7 @@ * test_resowner_basic.c * Test basic ResourceOwner functionality * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_resowner/test_resowner_basic.c @@ -13,8 +13,6 @@ #include "postgres.h" #include "fmgr.h" -#include "lib/ilist.h" -#include "utils/memutils.h" #include "utils/resowner.h" PG_MODULE_MAGIC; diff --git a/src/test/modules/test_resowner/test_resowner_many.c b/src/test/modules/test_resowner/test_resowner_many.c index 7808c9e5df336..1f64939404f48 100644 --- a/src/test/modules/test_resowner/test_resowner_many.c +++ b/src/test/modules/test_resowner/test_resowner_many.c @@ -3,7 +3,7 @@ * test_resowner_many.c * Test ResourceOwner functionality with lots of resources * - * Copyright (c) 2022-2024, PostgreSQL Global Development Group + * Copyright (c) 2022-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_resowner/test_resowner_many.c @@ -14,7 +14,6 @@ #include "fmgr.h" #include "lib/ilist.h" -#include "utils/memutils.h" #include "utils/resowner.h" /* diff --git a/src/test/modules/test_rls_hooks/meson.build b/src/test/modules/test_rls_hooks/meson.build index 2ea478024de45..77c1f3ee586fd 100644 --- a/src/test/modules/test_rls_hooks/meson.build +++ b/src/test/modules/test_rls_hooks/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_rls_hooks_sources = files( 'test_rls_hooks.c', diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.c b/src/test/modules/test_rls_hooks/test_rls_hooks.c index 358e28edb4590..b1f161cf7bbf7 100644 --- a/src/test/modules/test_rls_hooks/test_rls_hooks.c +++ b/src/test/modules/test_rls_hooks/test_rls_hooks.c @@ -3,7 +3,7 @@ * test_rls_hooks.c * Code for testing RLS hooks. * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_rls_hooks/test_rls_hooks.c @@ -15,7 +15,6 @@ #include "catalog/pg_type.h" #include "fmgr.h" -#include "miscadmin.h" #include "nodes/makefuncs.h" #include "parser/parse_clause.h" #include "parser/parse_collate.h" diff --git a/src/test/modules/test_rls_hooks/test_rls_hooks.h b/src/test/modules/test_rls_hooks/test_rls_hooks.h index 306a0adeba342..ff4141ea6b60d 100644 --- a/src/test/modules/test_rls_hooks/test_rls_hooks.h +++ b/src/test/modules/test_rls_hooks/test_rls_hooks.h @@ -3,7 +3,7 @@ * test_rls_hooks.h * Definitions for RLS hooks * - * Copyright (c) 2015-2024, PostgreSQL Global Development Group + * Copyright (c) 2015-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_rls_hooks/test_rls_hooks.h @@ -14,7 +14,7 @@ #ifndef TEST_RLS_HOOKS_H #define TEST_RLS_HOOKS_H -#include +#include "rewrite/rowsecurity.h" /* Return set of permissive hooks based on CmdType and Relation */ extern List *test_rls_hooks_permissive(CmdType cmdtype, Relation relation); diff --git a/src/test/modules/test_shm_mq/meson.build b/src/test/modules/test_shm_mq/meson.build index 1dd2db125d780..eb2406897262f 100644 --- a/src/test/modules/test_shm_mq/meson.build +++ b/src/test/modules/test_shm_mq/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_shm_mq_sources = files( 'setup.c', diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index b3dac44d97a80..2a20ffb12736c 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -5,7 +5,7 @@ * number of background workers for shared memory message queue * testing. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_shm_mq/setup.c @@ -18,7 +18,6 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/bgworker.h" -#include "storage/procsignal.h" #include "storage/shm_toc.h" #include "test_shm_mq.h" #include "utils/memutils.h" diff --git a/src/test/modules/test_shm_mq/test.c b/src/test/modules/test_shm_mq/test.c index 3d235568b81d4..443281addd06b 100644 --- a/src/test/modules/test_shm_mq/test.c +++ b/src/test/modules/test_shm_mq/test.c @@ -3,7 +3,7 @@ * test.c * Test harness code for shared memory message queues. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_shm_mq/test.c diff --git a/src/test/modules/test_shm_mq/test_shm_mq.h b/src/test/modules/test_shm_mq/test_shm_mq.h index 0ae7bd64cd0b3..5346557d473c4 100644 --- a/src/test/modules/test_shm_mq/test_shm_mq.h +++ b/src/test/modules/test_shm_mq/test_shm_mq.h @@ -3,7 +3,7 @@ * test_shm_mq.h * Definitions for shared memory message queues * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_shm_mq/test_shm_mq.h @@ -40,6 +40,6 @@ extern void test_shm_mq_setup(int64 queue_size, int32 nworkers, shm_mq_handle **input); /* Main entrypoint for a worker. */ -extern PGDLLEXPORT void test_shm_mq_main(Datum) pg_attribute_noreturn(); +pg_noreturn extern PGDLLEXPORT void test_shm_mq_main(Datum); #endif diff --git a/src/test/modules/test_shm_mq/worker.c b/src/test/modules/test_shm_mq/worker.c index 6c4fbc7827471..96cd304dbbc83 100644 --- a/src/test/modules/test_shm_mq/worker.c +++ b/src/test/modules/test_shm_mq/worker.c @@ -9,7 +9,7 @@ * but it should be possible to use much of the control logic just * as presented here. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_shm_mq/worker.c diff --git a/src/test/modules/test_slru/Makefile b/src/test/modules/test_slru/Makefile index 936886753b7e4..fe4e739043792 100644 --- a/src/test/modules/test_slru/Makefile +++ b/src/test/modules/test_slru/Makefile @@ -3,9 +3,14 @@ MODULE_big = test_slru OBJS = \ $(WIN32RES) \ - test_slru.o + test_slru.o \ + test_multixact.o PGFILEDESC = "test_slru - test module for SLRUs" +EXTRA_INSTALL=src/test/modules/injection_points +export enable_injection_points +TAP_TESTS = 1 + EXTENSION = test_slru DATA = test_slru--1.0.sql diff --git a/src/test/modules/test_slru/meson.build b/src/test/modules/test_slru/meson.build index ce91e606313f6..e58bbdf75ac7b 100644 --- a/src/test/modules/test_slru/meson.build +++ b/src/test/modules/test_slru/meson.build @@ -1,7 +1,8 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_slru_sources = files( 'test_slru.c', + 'test_multixact.c', ) if host_system == 'windows' @@ -32,4 +33,12 @@ tests += { 'regress_args': ['--temp-config', files('test_slru.conf')], 'runningcheck': false, }, + 'tap': { + 'env': { + 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', + }, + 'tests': [ + 't/001_multixact.pl' + ], + }, } diff --git a/src/test/modules/test_slru/t/001_multixact.pl b/src/test/modules/test_slru/t/001_multixact.pl new file mode 100644 index 0000000000000..e2b567a603d31 --- /dev/null +++ b/src/test/modules/test_slru/t/001_multixact.pl @@ -0,0 +1,123 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# This test verifies edge case of reading a multixact: +# when we have multixact that is followed by exactly one another multixact, +# and another multixact have no offset yet, we must wait until this offset +# becomes observable. Previously we used to wait for 1ms in a loop in this +# case, but now we use CV for this. This test is exercising such a sleep. + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +my ($node, $result); + +$node = PostgreSQL::Test::Cluster->new('mike'); +$node->init; +$node->append_conf('postgresql.conf', + "shared_preload_libraries = 'test_slru,injection_points'"); +$node->start; +$node->safe_psql('postgres', q(CREATE EXTENSION injection_points)); +$node->safe_psql('postgres', q(CREATE EXTENSION test_slru)); + +# Test for Multixact generation edge case +$node->safe_psql('postgres', + q{select injection_points_attach('test-multixact-read','wait')}); +$node->safe_psql('postgres', + q{select injection_points_attach('multixact-get-members-cv-sleep','wait')} +); + +# This session must observe sleep on the condition variable while generating a +# multixact. To achieve this it first will create a multixact, then pause +# before reading it. +my $observer = $node->background_psql('postgres'); + +# This query will create a multixact, and hang just before reading it. +$observer->query_until( + qr/start/, + q{ + \echo start + SELECT test_read_multixact(test_create_multixact()); +}); +$node->wait_for_event('client backend', 'test-multixact-read'); + +# This session will create the next Multixact. This is necessary to avoid +# multixact.c's non-sleeping edge case 1. +my $creator = $node->background_psql('postgres'); +$node->safe_psql('postgres', + q{SELECT injection_points_attach('multixact-create-from-members','wait');} +); + +# We expect this query to hang in the critical section after generating new +# multixact, but before filling its offset into SLRU. +# Running an injection point inside a critical section requires it to be +# loaded beforehand. +$creator->query_until( + qr/start/, q{ + \echo start + SELECT test_create_multixact(); +}); + +$node->wait_for_event('client backend', 'multixact-create-from-members'); + +# Ensure we have the backends waiting that we expect +is( $node->safe_psql( + 'postgres', + q{SELECT string_agg(wait_event, ', ' ORDER BY wait_event) + FROM pg_stat_activity WHERE wait_event_type = 'InjectionPoint'} + ), + 'multixact-create-from-members, test-multixact-read', + "matching injection point waits"); + +# Now wake observer to get it to read the initial multixact. A subsequent +# multixact already exists, but that one doesn't have an offset assigned, so +# this will hit multixact.c's edge case 2. +$node->safe_psql('postgres', + q{SELECT injection_points_wakeup('test-multixact-read')}); +$node->wait_for_event('client backend', 'multixact-get-members-cv-sleep'); + +# Ensure we have the backends waiting that we expect +is( $node->safe_psql( + 'postgres', + q{SELECT string_agg(wait_event, ', ' ORDER BY wait_event) + FROM pg_stat_activity WHERE wait_event_type = 'InjectionPoint'} + ), + 'multixact-create-from-members, multixact-get-members-cv-sleep', + "matching injection point waits"); + +# Now we have two backends waiting in multixact-create-from-members and +# multixact-get-members-cv-sleep. Also we have 3 injections points set to wait. +# If we wakeup multixact-get-members-cv-sleep it will happen again, so we must +# detach it first. So let's detach all injection points, then wake up all +# backends. + +$node->safe_psql('postgres', + q{SELECT injection_points_detach('test-multixact-read')}); +$node->safe_psql('postgres', + q{SELECT injection_points_detach('multixact-create-from-members')}); +$node->safe_psql('postgres', + q{SELECT injection_points_detach('multixact-get-members-cv-sleep')}); + +$node->safe_psql('postgres', + q{SELECT injection_points_wakeup('multixact-create-from-members')}); +$node->safe_psql('postgres', + q{SELECT injection_points_wakeup('multixact-get-members-cv-sleep')}); + +# Background psql will now be able to read the result and disconnect. +$observer->quit; +$creator->quit; + +$node->stop; + +# If we reached this point - everything is OK. +ok(1); +done_testing(); diff --git a/src/test/modules/test_slru/test_multixact.c b/src/test/modules/test_slru/test_multixact.c new file mode 100644 index 0000000000000..6c9b0420717cc --- /dev/null +++ b/src/test/modules/test_slru/test_multixact.c @@ -0,0 +1,57 @@ +/*-------------------------------------------------------------------------- + * + * test_multixact.c + * Support code for multixact testing + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/test/modules/test_slru/test_multixact.c + * + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/multixact.h" +#include "access/xact.h" +#include "fmgr.h" +#include "utils/injection_point.h" + +PG_FUNCTION_INFO_V1(test_create_multixact); +PG_FUNCTION_INFO_V1(test_read_multixact); + +/* + * Produces multixact with 2 current xids + */ +Datum +test_create_multixact(PG_FUNCTION_ARGS) +{ + MultiXactId id; + + MultiXactIdSetOldestMember(); + id = MultiXactIdCreate(GetCurrentTransactionId(), MultiXactStatusUpdate, + GetCurrentTransactionId(), MultiXactStatusForShare); + PG_RETURN_TRANSACTIONID(id); +} + +/* + * Reads given multixact after running an injection point. Discards local cache + * to make a real read. Tailored for multixact testing. + */ +Datum +test_read_multixact(PG_FUNCTION_ARGS) +{ + MultiXactId id = PG_GETARG_TRANSACTIONID(0); + MultiXactMember *members; + + INJECTION_POINT("test-multixact-read", NULL); + /* discard caches */ + AtEOXact_MultiXact(); + + if (GetMultiXactIdMembers(id, &members, false, false) == -1) + elog(ERROR, "MultiXactId not found"); + + PG_RETURN_VOID(); +} diff --git a/src/test/modules/test_slru/test_slru--1.0.sql b/src/test/modules/test_slru/test_slru--1.0.sql index 202e8da3fdeeb..abecb5e21838f 100644 --- a/src/test/modules/test_slru/test_slru--1.0.sql +++ b/src/test/modules/test_slru/test_slru--1.0.sql @@ -19,3 +19,9 @@ CREATE OR REPLACE FUNCTION test_slru_page_truncate(bigint) RETURNS VOID AS 'MODULE_PATHNAME', 'test_slru_page_truncate' LANGUAGE C; CREATE OR REPLACE FUNCTION test_slru_delete_all() RETURNS VOID AS 'MODULE_PATHNAME', 'test_slru_delete_all' LANGUAGE C; + + +CREATE OR REPLACE FUNCTION test_create_multixact() RETURNS xid + AS 'MODULE_PATHNAME', 'test_create_multixact' LANGUAGE C; +CREATE OR REPLACE FUNCTION test_read_multixact(xid) RETURNS VOID + AS 'MODULE_PATHNAME', 'test_read_multixact'LANGUAGE C; diff --git a/src/test/modules/test_slru/test_slru.c b/src/test/modules/test_slru/test_slru.c index d227b0670342a..32750930e433d 100644 --- a/src/test/modules/test_slru/test_slru.c +++ b/src/test/modules/test_slru/test_slru.c @@ -3,7 +3,7 @@ * test_slru.c * Test correctness of SLRU functions. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -151,8 +151,8 @@ test_slru_page_sync(PG_FUNCTION_ARGS) ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT; SlruSyncFileTag(TestSlruCtl, &ftag, path); - elog(NOTICE, "Called SlruSyncFileTag() for segment %lld on path %s", - (long long) ftag.segno, path); + elog(NOTICE, "Called SlruSyncFileTag() for segment %" PRIu64 " on path %s", + ftag.segno, path); PG_RETURN_VOID(); } @@ -166,8 +166,8 @@ test_slru_page_delete(PG_FUNCTION_ARGS) ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT; SlruDeleteSegment(TestSlruCtl, ftag.segno); - elog(NOTICE, "Called SlruDeleteSegment() for segment %lld", - (long long) ftag.segno); + elog(NOTICE, "Called SlruDeleteSegment() for segment %" PRIu64, + ftag.segno); PG_RETURN_VOID(); } diff --git a/src/test/modules/test_tidstore/meson.build b/src/test/modules/test_tidstore/meson.build index 0ed3ea2ef33aa..8f259078b87ea 100644 --- a/src/test/modules/test_tidstore/meson.build +++ b/src/test/modules/test_tidstore/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group test_tidstore_sources = files( 'test_tidstore.c', diff --git a/src/test/modules/test_tidstore/test_tidstore.c b/src/test/modules/test_tidstore/test_tidstore.c index 94ddcf1de826a..eb16e0fbfa647 100644 --- a/src/test/modules/test_tidstore/test_tidstore.c +++ b/src/test/modules/test_tidstore/test_tidstore.c @@ -7,7 +7,7 @@ * a single process to use the TidStore. It is meant to be an example of * usage. * - * Copyright (c) 2024, PostgreSQL Global Development Group + * Copyright (c) 2024-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/test_tidstore/test_tidstore.c @@ -18,7 +18,6 @@ #include "access/tidstore.h" #include "fmgr.h" -#include "funcapi.h" #include "storage/block.h" #include "storage/itemptr.h" #include "storage/lwlock.h" @@ -293,13 +292,13 @@ check_set_block_offsets(PG_FUNCTION_ARGS) qsort(items.lookup_tids, items.num_tids, sizeof(ItemPointerData), itemptr_cmp); for (int i = 0; i < items.num_tids; i++) { - if (itemptr_cmp((const void *) &items.insert_tids[i], (const void *) &items.iter_tids[i]) != 0) + if (itemptr_cmp(&items.insert_tids[i], &items.iter_tids[i]) != 0) elog(ERROR, "TID iter array doesn't match verification array, got (%u,%u) expected (%u,%u)", ItemPointerGetBlockNumber(&items.iter_tids[i]), ItemPointerGetOffsetNumber(&items.iter_tids[i]), ItemPointerGetBlockNumber(&items.insert_tids[i]), ItemPointerGetOffsetNumber(&items.insert_tids[i])); - if (itemptr_cmp((const void *) &items.insert_tids[i], (const void *) &items.lookup_tids[i]) != 0) + if (itemptr_cmp(&items.insert_tids[i], &items.lookup_tids[i]) != 0) elog(ERROR, "TID lookup array doesn't match verification array, got (%u,%u) expected (%u,%u)", ItemPointerGetBlockNumber(&items.lookup_tids[i]), ItemPointerGetOffsetNumber(&items.lookup_tids[i]), diff --git a/src/test/modules/typcache/.gitignore b/src/test/modules/typcache/.gitignore new file mode 100644 index 0000000000000..5dcb3ff972350 --- /dev/null +++ b/src/test/modules/typcache/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/src/test/modules/typcache/Makefile b/src/test/modules/typcache/Makefile new file mode 100644 index 0000000000000..1f03de8389053 --- /dev/null +++ b/src/test/modules/typcache/Makefile @@ -0,0 +1,28 @@ +# src/test/modules/typcache/Makefile + +EXTRA_INSTALL = src/test/modules/injection_points + +REGRESS = typcache_rel_type_cache + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/typcache +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +# XXX: This test is conditional on enable_injection_points in the +# parent Makefile, so we should never get here in the first place if +# injection points are not enabled. But the buildfarm 'misc-check' +# step doesn't pay attention to the if-condition in the parent +# Makefile. To work around that, disable running the test here too. +ifeq ($(enable_injection_points),yes) +include $(top_srcdir)/contrib/contrib-global.mk +else +check: + @echo "injection points are disabled in this build" +endif + +endif diff --git a/src/test/modules/typcache/expected/typcache_rel_type_cache.out b/src/test/modules/typcache/expected/typcache_rel_type_cache.out new file mode 100644 index 0000000000000..a91bd72b9bd4d --- /dev/null +++ b/src/test/modules/typcache/expected/typcache_rel_type_cache.out @@ -0,0 +1,41 @@ +-- +-- This test checks that lookup_type_cache() can correctly handle an +-- interruption. We use the injection point to simulate an error but note +-- that a similar situation could happen due to user query interruption. +-- Despite the interruption, a map entry from the relation oid to type cache +-- entry should be created. This is validated by subsequent modification of +-- the table schema, then type casts which use new schema implying +-- successful type cache invalidation by relation oid. +-- +CREATE EXTENSION injection_points; +-- Make all injection points local to this process, for concurrency. +SELECT injection_points_set_local(); + injection_points_set_local +---------------------------- + +(1 row) + +CREATE TABLE t (i int); +SELECT injection_points_attach('typecache-before-rel-type-cache-insert', 'error'); + injection_points_attach +------------------------- + +(1 row) + +SELECT '(1)'::t; +ERROR: error triggered for injection point typecache-before-rel-type-cache-insert +LINE 1: SELECT '(1)'::t; + ^ +SELECT injection_points_detach('typecache-before-rel-type-cache-insert'); + injection_points_detach +------------------------- + +(1 row) + +ALTER TABLE t ADD COLUMN j int; +SELECT '(1,2)'::t; + t +------- + (1,2) +(1 row) + diff --git a/src/test/modules/typcache/meson.build b/src/test/modules/typcache/meson.build new file mode 100644 index 0000000000000..6f30cda11ea83 --- /dev/null +++ b/src/test/modules/typcache/meson.build @@ -0,0 +1,16 @@ +# Copyright (c) 2022-2025, PostgreSQL Global Development Group + +if not get_option('injection_points') + subdir_done() +endif + +tests += { + 'name': 'typcache', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'typcache_rel_type_cache', + ], + }, +} diff --git a/src/test/modules/typcache/sql/typcache_rel_type_cache.sql b/src/test/modules/typcache/sql/typcache_rel_type_cache.sql new file mode 100644 index 0000000000000..c1a3af509c018 --- /dev/null +++ b/src/test/modules/typcache/sql/typcache_rel_type_cache.sql @@ -0,0 +1,21 @@ +-- +-- This test checks that lookup_type_cache() can correctly handle an +-- interruption. We use the injection point to simulate an error but note +-- that a similar situation could happen due to user query interruption. +-- Despite the interruption, a map entry from the relation oid to type cache +-- entry should be created. This is validated by subsequent modification of +-- the table schema, then type casts which use new schema implying +-- successful type cache invalidation by relation oid. +-- + +CREATE EXTENSION injection_points; + +-- Make all injection points local to this process, for concurrency. +SELECT injection_points_set_local(); + +CREATE TABLE t (i int); +SELECT injection_points_attach('typecache-before-rel-type-cache-insert', 'error'); +SELECT '(1)'::t; +SELECT injection_points_detach('typecache-before-rel-type-cache-insert'); +ALTER TABLE t ADD COLUMN j int; +SELECT '(1,2)'::t; diff --git a/src/test/modules/unsafe_tests/Makefile b/src/test/modules/unsafe_tests/Makefile index 90d19791871c7..a85c854392de7 100644 --- a/src/test/modules/unsafe_tests/Makefile +++ b/src/test/modules/unsafe_tests/Makefile @@ -1,6 +1,11 @@ # src/test/modules/unsafe_tests/Makefile -REGRESS = rolenames alter_system_table guc_privs +REGRESS = rolenames setconfig alter_system_table guc_privs +REGRESS_OPTS = \ + --create-role=regress_authenticated_user_db_sr \ + --create-role=regress_authenticated_user_db_ssa \ + --create-role=regress_authenticated_user_sr \ + --create-role=regress_authenticated_user_ssa # the whole point of these tests is to not run installcheck NO_INSTALLCHECK = 1 diff --git a/src/test/modules/unsafe_tests/expected/alter_system_table.out b/src/test/modules/unsafe_tests/expected/alter_system_table.out index be0559503b6ff..b73b9442b8d4d 100644 --- a/src/test/modules/unsafe_tests/expected/alter_system_table.out +++ b/src/test/modules/unsafe_tests/expected/alter_system_table.out @@ -91,6 +91,9 @@ ERROR: permission denied: "pg_description" is a system catalog SET allow_system_table_mods TO on; DROP RULE r2 ON pg_description; RESET allow_system_table_mods; +-- Reloptions on TOAST tables +ALTER TABLE pg_toast.pg_toast_2615 SET (fillfactor = '90'); +ERROR: permission denied: "pg_toast_2615" is a system catalog SET allow_system_table_mods = on; -- create new table in pg_catalog BEGIN; @@ -173,6 +176,10 @@ DROP TRIGGER t2 ON pg_description; CREATE RULE r1 AS ON INSERT TO pg_description DO INSTEAD NOTHING; ALTER RULE r1 ON pg_description RENAME TO r2; DROP RULE r2 ON pg_description; +-- Reloptions on TOAST tables +ALTER TABLE pg_toast.pg_toast_2615 SET (fillfactor = '90'); +ERROR: ALTER action SET cannot be performed on relation "pg_toast_2615" +DETAIL: This operation is not supported for TOAST tables. -- cleanup REVOKE ALL ON pg_description FROM regress_user_ast; DROP USER regress_user_ast; diff --git a/src/test/modules/unsafe_tests/expected/setconfig.out b/src/test/modules/unsafe_tests/expected/setconfig.out new file mode 100644 index 0000000000000..5f42443e144b9 --- /dev/null +++ b/src/test/modules/unsafe_tests/expected/setconfig.out @@ -0,0 +1,99 @@ +-- This is borderline unsafe in that an additional login-capable user exists +-- during the test run. Under installcheck, a too-permissive pg_hba.conf +-- might allow unwanted logins as regress_authenticated_user_ssa. +-- Setup catalog state. +ALTER USER regress_authenticated_user_db_ssa superuser; +ALTER USER regress_authenticated_user_ssa superuser; +CREATE ROLE regress_session_user; +CREATE ROLE regress_current_user; +GRANT regress_current_user TO regress_authenticated_user_db_sr; +GRANT regress_current_user TO regress_authenticated_user_sr; +GRANT regress_session_user TO regress_authenticated_user_db_ssa; +GRANT regress_session_user TO regress_authenticated_user_ssa; +DO $$BEGIN EXECUTE format( + 'ALTER DATABASE %I SET session_authorization = regress_session_user', + current_catalog); END$$; +ALTER ROLE regress_authenticated_user_ssa + SET session_authorization = regress_session_user; +ALTER ROLE regress_authenticated_user_sr SET ROLE = regress_current_user; +-- Test ALTER DATABASE consequences +-- The longstanding historical behavior is that session_authorization in +-- setconfig has no effect. Hence, session_user remains +-- regress_authenticated_user_ssa. See comment in InitializeSessionUserId(). +\c - regress_authenticated_user_db_ssa +SELECT current_user, session_user; + current_user | session_user +-----------------------------------+----------------------------------- + regress_authenticated_user_db_ssa | regress_authenticated_user_db_ssa +(1 row) + +-- We document "The DEFAULT and RESET forms reset the session and current user +-- identifiers to be the originally authenticated user name." If we let +-- session_authorization in setconfig have an effect, we'll need to decide +-- whether to make RESET differ from DEFAULT. +RESET SESSION AUTHORIZATION; +SELECT current_user, session_user; + current_user | session_user +-----------------------------------+----------------------------------- + regress_authenticated_user_db_ssa | regress_authenticated_user_db_ssa +(1 row) + +DO $$BEGIN + EXECUTE format( + 'ALTER DATABASE %I RESET session_authorization', current_catalog); + EXECUTE format( + 'ALTER DATABASE %I SET role = regress_current_user', current_catalog); +END$$; +\c - regress_authenticated_user_db_sr +SELECT current_user, session_user; + current_user | session_user +----------------------+---------------------------------- + regress_current_user | regress_authenticated_user_db_sr +(1 row) + +-- Back to superuser, to reverse ALTER DATABASE +\c - regress_authenticated_user_db_ssa +SELECT current_user, session_user; + current_user | session_user +----------------------+----------------------------------- + regress_current_user | regress_authenticated_user_db_ssa +(1 row) + +SET ROLE NONE; +DO $$BEGIN EXECUTE format( + 'ALTER DATABASE %I RESET role', current_catalog); END$$; +-- Test connection string options +\c -reuse-previous=on "user=regress_authenticated_user_db_sr options=-crole=regress_current_user" +SELECT current_user, session_user; + current_user | session_user +----------------------+---------------------------------- + regress_current_user | regress_authenticated_user_db_sr +(1 row) + +-- As above, session_authorization has no effect. +\c -reuse-previous=on "user=regress_authenticated_user_db_ssa options=-csession_authorization=regress_session_user" +SELECT current_user, session_user; + current_user | session_user +-----------------------------------+----------------------------------- + regress_authenticated_user_db_ssa | regress_authenticated_user_db_ssa +(1 row) + +-- Test ALTER ROLE consequences +\c -reuse-previous=on "user=regress_authenticated_user_sr options=" +SELECT current_user, session_user; + current_user | session_user +----------------------+------------------------------- + regress_current_user | regress_authenticated_user_sr +(1 row) + +-- As above, session_authorization has no effect. +\c - regress_authenticated_user_ssa +SELECT current_user, session_user; + current_user | session_user +--------------------------------+-------------------------------- + regress_authenticated_user_ssa | regress_authenticated_user_ssa +(1 row) + +RESET SESSION AUTHORIZATION; +DROP USER regress_session_user; +DROP USER regress_current_user; diff --git a/src/test/modules/unsafe_tests/meson.build b/src/test/modules/unsafe_tests/meson.build index 3b0f606084677..af9bbf5b9fdc0 100644 --- a/src/test/modules/unsafe_tests/meson.build +++ b/src/test/modules/unsafe_tests/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'unsafe_tests', @@ -7,9 +7,14 @@ tests += { 'regress': { 'sql': [ 'rolenames', + 'setconfig', 'alter_system_table', 'guc_privs', ], + 'regress_args': ['--create-role=regress_authenticated_user_db_sr', + '--create-role=regress_authenticated_user_db_ssa', + '--create-role=regress_authenticated_user_sr', + '--create-role=regress_authenticated_user_ssa'], 'runningcheck': false, }, } diff --git a/src/test/modules/unsafe_tests/sql/alter_system_table.sql b/src/test/modules/unsafe_tests/sql/alter_system_table.sql index b77b68c946a10..c1515100845cd 100644 --- a/src/test/modules/unsafe_tests/sql/alter_system_table.sql +++ b/src/test/modules/unsafe_tests/sql/alter_system_table.sql @@ -89,6 +89,8 @@ SET allow_system_table_mods TO on; DROP RULE r2 ON pg_description; RESET allow_system_table_mods; +-- Reloptions on TOAST tables +ALTER TABLE pg_toast.pg_toast_2615 SET (fillfactor = '90'); SET allow_system_table_mods = on; @@ -187,6 +189,8 @@ CREATE RULE r1 AS ON INSERT TO pg_description DO INSTEAD NOTHING; ALTER RULE r1 ON pg_description RENAME TO r2; DROP RULE r2 ON pg_description; +-- Reloptions on TOAST tables +ALTER TABLE pg_toast.pg_toast_2615 SET (fillfactor = '90'); -- cleanup REVOKE ALL ON pg_description FROM regress_user_ast; diff --git a/src/test/modules/unsafe_tests/sql/setconfig.sql b/src/test/modules/unsafe_tests/sql/setconfig.sql new file mode 100644 index 0000000000000..81296d1091b47 --- /dev/null +++ b/src/test/modules/unsafe_tests/sql/setconfig.sql @@ -0,0 +1,73 @@ +-- This is borderline unsafe in that an additional login-capable user exists +-- during the test run. Under installcheck, a too-permissive pg_hba.conf +-- might allow unwanted logins as regress_authenticated_user_ssa. + +-- Setup catalog state. +ALTER USER regress_authenticated_user_db_ssa superuser; +ALTER USER regress_authenticated_user_ssa superuser; +CREATE ROLE regress_session_user; +CREATE ROLE regress_current_user; +GRANT regress_current_user TO regress_authenticated_user_db_sr; +GRANT regress_current_user TO regress_authenticated_user_sr; +GRANT regress_session_user TO regress_authenticated_user_db_ssa; +GRANT regress_session_user TO regress_authenticated_user_ssa; +DO $$BEGIN EXECUTE format( + 'ALTER DATABASE %I SET session_authorization = regress_session_user', + current_catalog); END$$; +ALTER ROLE regress_authenticated_user_ssa + SET session_authorization = regress_session_user; +ALTER ROLE regress_authenticated_user_sr SET ROLE = regress_current_user; + + +-- Test ALTER DATABASE consequences + +-- The longstanding historical behavior is that session_authorization in +-- setconfig has no effect. Hence, session_user remains +-- regress_authenticated_user_ssa. See comment in InitializeSessionUserId(). +\c - regress_authenticated_user_db_ssa +SELECT current_user, session_user; +-- We document "The DEFAULT and RESET forms reset the session and current user +-- identifiers to be the originally authenticated user name." If we let +-- session_authorization in setconfig have an effect, we'll need to decide +-- whether to make RESET differ from DEFAULT. +RESET SESSION AUTHORIZATION; +SELECT current_user, session_user; +DO $$BEGIN + EXECUTE format( + 'ALTER DATABASE %I RESET session_authorization', current_catalog); + EXECUTE format( + 'ALTER DATABASE %I SET role = regress_current_user', current_catalog); +END$$; + +\c - regress_authenticated_user_db_sr +SELECT current_user, session_user; + +-- Back to superuser, to reverse ALTER DATABASE +\c - regress_authenticated_user_db_ssa +SELECT current_user, session_user; +SET ROLE NONE; +DO $$BEGIN EXECUTE format( + 'ALTER DATABASE %I RESET role', current_catalog); END$$; + + +-- Test connection string options + +\c -reuse-previous=on "user=regress_authenticated_user_db_sr options=-crole=regress_current_user" +SELECT current_user, session_user; + +-- As above, session_authorization has no effect. +\c -reuse-previous=on "user=regress_authenticated_user_db_ssa options=-csession_authorization=regress_session_user" +SELECT current_user, session_user; + + +-- Test ALTER ROLE consequences + +\c -reuse-previous=on "user=regress_authenticated_user_sr options=" +SELECT current_user, session_user; + +-- As above, session_authorization has no effect. +\c - regress_authenticated_user_ssa +SELECT current_user, session_user; +RESET SESSION AUTHORIZATION; +DROP USER regress_session_user; +DROP USER regress_current_user; diff --git a/src/test/modules/worker_spi/meson.build b/src/test/modules/worker_spi/meson.build index 34e4ee0b12e1d..d673ece48a052 100644 --- a/src/test/modules/worker_spi/meson.build +++ b/src/test/modules/worker_spi/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group test_worker_spi_sources = files( 'worker_spi.c', diff --git a/src/test/modules/worker_spi/t/001_worker_spi.pl b/src/test/modules/worker_spi/t/001_worker_spi.pl index fcd76b43e8e48..76fe7e63ac38f 100644 --- a/src/test/modules/worker_spi/t/001_worker_spi.pl +++ b/src/test/modules/worker_spi/t/001_worker_spi.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Test worker_spi module. diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 7e1042f4ab6c3..9c53d896b6ae5 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -13,7 +13,7 @@ * "delta" type. Delta rows will be deleted by this worker and their values * aggregated into the total. * - * Copyright (c) 2013-2024, PostgreSQL Global Development Group + * Copyright (c) 2013-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/test/modules/worker_spi/worker_spi.c @@ -26,11 +26,7 @@ #include "miscadmin.h" #include "postmaster/bgworker.h" #include "postmaster/interrupt.h" -#include "storage/ipc.h" #include "storage/latch.h" -#include "storage/lwlock.h" -#include "storage/proc.h" -#include "storage/shmem.h" /* these headers are used by this particular worker's code */ #include "access/xact.h" @@ -48,7 +44,7 @@ PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(worker_spi_launch); -PGDLLEXPORT void worker_spi_main(Datum main_arg) pg_attribute_noreturn(); +PGDLLEXPORT pg_noreturn void worker_spi_main(Datum main_arg); /* GUC variables */ static int worker_spi_naptime = 10; @@ -173,15 +169,6 @@ worker_spi_main(Datum main_arg) BackgroundWorkerInitializeConnection(worker_spi_database, worker_spi_role, flags); - /* - * Disable parallel query for workers started with BYPASS_ALLOWCONN or - * BGWORKER_BYPASS_ALLOWCONN so as these don't attempt connections using a - * database or a role that may not allow that. - */ - if ((flags & (BGWORKER_BYPASS_ALLOWCONN | BGWORKER_BYPASS_ROLELOGINCHECK))) - SetConfigOption("max_parallel_workers_per_gather", "0", - PGC_USERSET, PGC_S_OVERRIDE); - elog(LOG, "%s initialized with %s.%s", MyBgworkerEntry->bgw_name, table->schema, table->name); initialize_worker_spi(table); diff --git a/src/test/modules/xid_wraparound/meson.build b/src/test/modules/xid_wraparound/meson.build index 2e5248131b5e1..f7dada67f678a 100644 --- a/src/test/modules/xid_wraparound/meson.build +++ b/src/test/modules/xid_wraparound/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group xid_wraparound_sources = files( 'xid_wraparound.c', diff --git a/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl b/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl index 37550b67a4d67..73d1ec4af19a7 100644 --- a/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl +++ b/src/test/modules/xid_wraparound/t/001_emergency_vacuum.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Test wraparound emergency autovacuum. use strict; @@ -18,7 +18,6 @@ $node->init; $node->append_conf( 'postgresql.conf', qq[ -autovacuum = off # run autovacuum only when to anti wraparound autovacuum_naptime = 1s # so it's easier to verify the order of operations autovacuum_max_workers = 1 @@ -27,23 +26,25 @@ $node->start; $node->safe_psql('postgres', 'CREATE EXTENSION xid_wraparound'); -# Create tables for a few different test scenarios +# Create tables for a few different test scenarios. We disable autovacuum +# on these tables to run it only to prevent wraparound. $node->safe_psql( 'postgres', qq[ -CREATE TABLE large(id serial primary key, data text, filler text default repeat(random()::text, 10)); +CREATE TABLE large(id serial primary key, data text, filler text default repeat(random()::text, 10)) + WITH (autovacuum_enabled = off); INSERT INTO large(data) SELECT generate_series(1,30000); -CREATE TABLE large_trunc(id serial primary key, data text, filler text default repeat(random()::text, 10)); +CREATE TABLE large_trunc(id serial primary key, data text, filler text default repeat(random()::text, 10)) + WITH (autovacuum_enabled = off); INSERT INTO large_trunc(data) SELECT generate_series(1,30000); -CREATE TABLE small(id serial primary key, data text, filler text default repeat(random()::text, 10)); +CREATE TABLE small(id serial primary key, data text, filler text default repeat(random()::text, 10)) + WITH (autovacuum_enabled = off); INSERT INTO small(data) SELECT generate_series(1,15000); -CREATE TABLE small_trunc(id serial primary key, data text, filler text default repeat(random()::text, 10)); +CREATE TABLE small_trunc(id serial primary key, data text, filler text default repeat(random()::text, 10)) + WITH (autovacuum_enabled = off); INSERT INTO small_trunc(data) SELECT generate_series(1,15000); - -CREATE TABLE autovacuum_disabled(id serial primary key, data text) WITH (autovacuum_enabled=false); -INSERT INTO autovacuum_disabled(data) SELECT generate_series(1,1000); ]); # Bump the query timeout to avoid false negatives on slow test systems. @@ -63,7 +64,6 @@ DELETE FROM large_trunc WHERE id > 10000; DELETE FROM small WHERE id % 2 = 0; DELETE FROM small_trunc WHERE id > 1000; - DELETE FROM autovacuum_disabled WHERE id % 2 = 0; ]); # Consume 2 billion XIDs, to get us very close to wraparound @@ -107,20 +107,18 @@ 'postgres', qq[ SELECT relname, age(relfrozenxid) > current_setting('autovacuum_freeze_max_age')::int FROM pg_class -WHERE relname IN ('large', 'large_trunc', 'small', 'small_trunc', 'autovacuum_disabled') +WHERE relname IN ('large', 'large_trunc', 'small', 'small_trunc') ORDER BY 1 ]); -is( $ret, "autovacuum_disabled|f -large|f +is( $ret, "large|f large_trunc|f small|f small_trunc|f", "all tables are vacuumed"); # Check if vacuum failsafe was triggered for each table. my $log_contents = slurp_file($node->logfile, $log_offset); -foreach my $tablename ('large', 'large_trunc', 'small', 'small_trunc', - 'autovacuum_disabled') +foreach my $tablename ('large', 'large_trunc', 'small', 'small_trunc') { like( $log_contents, diff --git a/src/test/modules/xid_wraparound/t/002_limits.pl b/src/test/modules/xid_wraparound/t/002_limits.pl index c02c287167856..aa1d8765d3a0f 100644 --- a/src/test/modules/xid_wraparound/t/002_limits.pl +++ b/src/test/modules/xid_wraparound/t/002_limits.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # Test XID wraparound limits. # @@ -27,17 +27,17 @@ $node->init; $node->append_conf( 'postgresql.conf', qq[ -autovacuum = off # run autovacuum only to prevent wraparound autovacuum_naptime = 1s log_autovacuum_min_duration = 0 ]); $node->start; $node->safe_psql('postgres', 'CREATE EXTENSION xid_wraparound'); -# Create a test table +# Create a test table. We disable autovacuum on the table to run it only +# to prevent wraparound. $node->safe_psql( 'postgres', qq[ -CREATE TABLE wraparoundtest(t text); +CREATE TABLE wraparoundtest(t text) WITH (autovacuum_enabled = off); INSERT INTO wraparoundtest VALUES ('start'); ]); @@ -103,7 +103,7 @@ stderr => \$stderr); like( $stderr, - qr/ERROR: database is not accepting commands that assign new XIDs to avoid wraparound data loss in database "postgres"/, + qr/ERROR: database is not accepting commands that assign new transaction IDs to avoid wraparound data loss in database "postgres"/, "stop-limit"); # Finish the old transaction, to allow vacuum freezing to advance diff --git a/src/test/modules/xid_wraparound/t/003_wraparounds.pl b/src/test/modules/xid_wraparound/t/003_wraparounds.pl index 88063b4b52d61..2aeaee8769c7d 100644 --- a/src/test/modules/xid_wraparound/t/003_wraparounds.pl +++ b/src/test/modules/xid_wraparound/t/003_wraparounds.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # Consume a lot of XIDs, wrapping around a few times. # @@ -21,7 +21,6 @@ $node->init; $node->append_conf( 'postgresql.conf', qq[ -autovacuum = off # run autovacuum only when to anti wraparound autovacuum_naptime = 1s # so it's easier to verify the order of operations autovacuum_max_workers = 1 @@ -30,10 +29,11 @@ $node->start; $node->safe_psql('postgres', 'CREATE EXTENSION xid_wraparound'); -# Create a test table +# Create a test table. We disable autovacuum on the table to run +# it only to prevent wraparound. $node->safe_psql( 'postgres', qq[ -CREATE TABLE wraparoundtest(t text); +CREATE TABLE wraparoundtest(t text) WITH (autovacuum_enabled = off); INSERT INTO wraparoundtest VALUES ('beginning'); ]); diff --git a/src/test/modules/xid_wraparound/xid_wraparound--1.0.sql b/src/test/modules/xid_wraparound/xid_wraparound--1.0.sql index 51d25fc4c6343..96356b4b97450 100644 --- a/src/test/modules/xid_wraparound/xid_wraparound--1.0.sql +++ b/src/test/modules/xid_wraparound/xid_wraparound--1.0.sql @@ -4,9 +4,9 @@ \echo Use "CREATE EXTENSION xid_wraparound" to load this file. \quit CREATE FUNCTION consume_xids(nxids bigint) -RETURNS xid8 IMMUTABLE PARALLEL SAFE STRICT +RETURNS xid8 VOLATILE PARALLEL UNSAFE STRICT AS 'MODULE_PATHNAME' LANGUAGE C; CREATE FUNCTION consume_xids_until(targetxid xid8) -RETURNS xid8 IMMUTABLE PARALLEL SAFE STRICT +RETURNS xid8 VOLATILE PARALLEL UNSAFE STRICT AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/xid_wraparound/xid_wraparound.c b/src/test/modules/xid_wraparound/xid_wraparound.c index dce81c0c6d69e..e27a5fa576954 100644 --- a/src/test/modules/xid_wraparound/xid_wraparound.c +++ b/src/test/modules/xid_wraparound/xid_wraparound.c @@ -4,7 +4,7 @@ * Utilities for testing XID wraparound * * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -35,7 +35,7 @@ consume_xids(PG_FUNCTION_ARGS) FullTransactionId lastxid; if (nxids < 0) - elog(ERROR, "invalid nxids argument: %lld", (long long) nxids); + elog(ERROR, "invalid nxids argument: %" PRId64, nxids); if (nxids == 0) lastxid = ReadNextFullTransactionId(); @@ -56,8 +56,8 @@ consume_xids_until(PG_FUNCTION_ARGS) FullTransactionId lastxid; if (!FullTransactionIdIsNormal(targetxid)) - elog(ERROR, "targetxid %llu is not normal", - (unsigned long long) U64FromFullTransactionId(targetxid)); + elog(ERROR, "targetxid %" PRIu64 " is not normal", + U64FromFullTransactionId(targetxid)); lastxid = consume_xids_common(targetxid, 0); @@ -136,8 +136,8 @@ consume_xids_common(FullTransactionId untilxid, uint64 nxids) if (consumed - last_reported_at >= REPORT_INTERVAL) { if (nxids > 0) - elog(NOTICE, "consumed %llu / %llu XIDs, latest %u:%u", - (unsigned long long) consumed, (unsigned long long) nxids, + elog(NOTICE, "consumed %" PRIu64 " / %" PRIu64 " XIDs, latest %u:%u", + consumed, nxids, EpochFromFullTransactionId(lastxid), XidFromFullTransactionId(lastxid)); else diff --git a/src/test/perl/Makefile b/src/test/perl/Makefile index 82ea63b08e2dd..3c179005c30d8 100644 --- a/src/test/perl/Makefile +++ b/src/test/perl/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/perl # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/perl/Makefile @@ -22,16 +22,22 @@ install: all installdirs $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/Utils.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Utils.pm' $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/SimpleTee.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/SimpleTee.pm' $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/RecursiveCopy.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/RecursiveCopy.pm' + $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/Kerberos.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Kerberos.pm' $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/Cluster.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Cluster.pm' $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/BackgroundPsql.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/BackgroundPsql.pm' + $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/AdjustDump.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/AdjustDump.pm' + $(INSTALL_DATA) $(srcdir)/PostgreSQL/Test/AdjustUpgrade.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/AdjustUpgrade.pm' $(INSTALL_DATA) $(srcdir)/PostgreSQL/Version.pm '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Version.pm' uninstall: rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Utils.pm' rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/SimpleTee.pm' rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/RecursiveCopy.pm' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Kerberos.pm' rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/Cluster.pm' rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/BackgroundPsql.pm' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/AdjustDump.pm' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Test/AdjustUpgrade.pm' rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/PostgreSQL/Version.pm' endif diff --git a/src/test/perl/PostgreSQL/Test/AdjustDump.pm b/src/test/perl/PostgreSQL/Test/AdjustDump.pm new file mode 100644 index 0000000000000..5b642396ac7ec --- /dev/null +++ b/src/test/perl/PostgreSQL/Test/AdjustDump.pm @@ -0,0 +1,157 @@ +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +=pod + +=head1 NAME + +PostgreSQL::Test::AdjustDump - helper module for dump/restore tests + +=head1 SYNOPSIS + + use PostgreSQL::Test::AdjustDump; + + # Adjust contents of dump output file so that dump output from original + # regression database and that from the restored regression database match + $dump = adjust_regress_dumpfile($dump, $adjust_child_columns); + +=head1 DESCRIPTION + +C encapsulates various hacks needed to +compare the results of dump/restore tests. + +=cut + +package PostgreSQL::Test::AdjustDump; + +use strict; +use warnings FATAL => 'all'; + +use Exporter 'import'; +use Test::More; + +our @EXPORT = qw( + adjust_regress_dumpfile +); + +=pod + +=head1 ROUTINES + +=over + +=item $dump = adjust_regress_dumpfile($dump, $adjust_child_columns) + +Edit a dump output file, taken from the source regression database, +to remove the known differences to a dump taken after restoring the +same database. + +Arguments: + +=over + +=item C: Contents of dump file + +=item C: 1 indicates that the given dump file requires +adjusting columns in the child tables; usually when the dump is from original +database. 0 indicates no such adjustment is needed; usually when the dump is +from restored database. + +=back + +Returns the adjusted dump text. + +Adjustments Applied: + +=over + +=item Column reordering on child table creation + +This rearranges the column declarations in the C +statements in the dump file from original database so that they match those +from the restored database. + +Only executed if C is true. + +Context: some regression tests purposefully create child tables in such a way +that the order of their inherited columns differ from column orders of their +respective parents. In the restored database, however, the order of their +inherited columns are same as that of their respective parents. Thus the column +orders of these child tables in the original database and those in the restored +database differ, causing difference in the dump outputs. See +C and C for details. + +=item Removal of problematic C statements + +Remove COPY statements to abnormal children tables. + +Context: This difference is caused because of columns that are added to parent +tables that already have children; because recreating the children tables puts +the columns from the parent ahead of columns declared locally in children, +these extra columns are in earlier position compared to the original database. +Reordering columns on the entire C data is impractical, so we just remove +them. + +=item Newline adjustment + +Windows-style newlines are changed to Unix-style. Empty lines are trimmed. + +=back + +=cut + +sub adjust_regress_dumpfile +{ + my ($dump, $adjust_child_columns) = @_; + + # use Unix newlines + $dump =~ s/\r\n/\n/g; + + # Adjust the CREATE TABLE ... INHERITS statements. + if ($adjust_child_columns) + { + $dump =~ s/(^CREATE\sTABLE\sgenerated_stored_tests\.gtestxx_4\s\() + (\n\s+b\sinteger), + (\n\s+a\sinteger\sNOT\sNULL)/$1$3,$2/mgx; + + $dump =~ s/(^CREATE\sTABLE\sgenerated_virtual_tests\.gtestxx_4\s\() + (\n\s+b\sinteger), + (\n\s+a\sinteger\sNOT\sNULL)/$1$3,$2/mgx; + + $dump =~ s/(^CREATE\sTABLE\spublic\.test_type_diff2_c1\s\() + (\n\s+int_four\sbigint), + (\n\s+int_eight\sbigint), + (\n\s+int_two\ssmallint)/$1$4,$2,$3/mgx; + + $dump =~ s/(^CREATE\sTABLE\spublic\.test_type_diff2_c2\s\() + (\n\s+int_eight\sbigint), + (\n\s+int_two\ssmallint), + (\n\s+int_four\sbigint)/$1$3,$4,$2/mgx; + } + + # Remove COPY statements with differing column order + for my $table ( + 'public\.b_star', 'public\.c_star', + 'public\.cc2', 'public\.d_star', + 'public\.e_star', 'public\.f_star', + 'public\.renamecolumnanother', 'public\.renamecolumnchild', + 'public\.test_type_diff2_c1', 'public\.test_type_diff2_c2', + 'public\.test_type_diff_c') + { + # This multiline pattern matches the whole COPY, up to the + # terminating "\." + $dump =~ s/^COPY $table \(.+?^\\\.$//sm; + } + + # Suppress blank lines, as some places in pg_dump emit more or fewer. + $dump =~ s/\n\n+/\n/g; + + return $dump; +} + +=pod + +=back + +=cut + +1; diff --git a/src/test/perl/PostgreSQL/Test/AdjustUpgrade.pm b/src/test/perl/PostgreSQL/Test/AdjustUpgrade.pm index 239c17aced953..1725fe2f94871 100644 --- a/src/test/perl/PostgreSQL/Test/AdjustUpgrade.pm +++ b/src/test/perl/PostgreSQL/Test/AdjustUpgrade.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group =pod @@ -112,6 +112,16 @@ sub adjust_database_contents 'drop extension if exists test_ext7'); } + # we removed these test-support functions in v18 + if ($old_version < 18) + { + _add_st($result, 'regression', 'drop function ttdummy()'); + _add_st($result, 'regression', 'drop function set_ttdummy(integer)'); + _add_st($result, 'regression', 'drop function autoinc()'); + _add_st($result, 'regression', 'drop function check_foreign_key()'); + _add_st($result, 'regression', 'drop function check_primary_key()'); + } + # we removed this test-support function in v17 if ($old_version >= 15 && $old_version < 17) { @@ -294,6 +304,11 @@ sub adjust_old_dumpfile # Version comments will certainly not match. $dump =~ s/^-- Dumped from database version.*\n//mg; + # Same with version argument to pg_restore_relation_stats() or + # pg_restore_attribute_stats(). + $dump =~ s {\n(\s+'version',) '\d+'::integer,$} + {$1 '000000'::integer,}mg; + if ($old_version < 16) { # Fix up some view queries that no longer require table-qualification. @@ -333,6 +348,18 @@ sub adjust_old_dumpfile /$1 EXECUTE FUNCTION/mgx; } + # During pg_upgrade, we reindex hash indexes if the source is pre-v10. + # This may change their tables' relallvisible values, so don't compare + # those. + if ($old_version < 10) + { + $dump =~ s/ + (^SELECT\s\*\sFROM\spg_catalog\.pg_restore_relation_stats\( + [^;]*'relation',\s'public\.hash_[a-z0-9]*_heap'::regclass, + [^;]*'relallvisible',)\s'\d+'::integer + /$1 ''::integer/mgx; + } + if ($old_version lt '9.6') { # adjust some places where we don't print so many parens anymore @@ -511,6 +538,7 @@ my @_unused_view_qualifiers = ( { obj => 'VIEW public.limit_thousand_v_2', qual => 'onek' }, { obj => 'VIEW public.limit_thousand_v_3', qual => 'onek' }, { obj => 'VIEW public.limit_thousand_v_4', qual => 'onek' }, + { obj => 'VIEW public.limit_thousand_v_5', qual => 'onek' }, # Since 14 { obj => 'MATERIALIZED VIEW public.compressmv', qual => 'cmdata1' }); @@ -626,6 +654,22 @@ sub adjust_new_dumpfile # Version comments will certainly not match. $dump =~ s/^-- Dumped from database version.*\n//mg; + # Same with version argument to pg_restore_relation_stats() or + # pg_restore_attribute_stats(). + $dump =~ s {\n(\s+'version',) '\d+'::integer,$} + {$1 '000000'::integer,}mg; + + if ($old_version < 18) + { + $dump =~ s {,\n(\s+'relallfrozen',) '-?\d+'::integer$}{}mg; + } + + # pre-v16 dumps do not know about XMLSERIALIZE(NO INDENT). + if ($old_version < 16) + { + $dump =~ s/XMLSERIALIZE\((.*)? NO INDENT\)/XMLSERIALIZE\($1\)/mg; + } + if ($old_version < 14) { # Suppress noise-word uses of IN in CREATE/ALTER PROCEDURE. @@ -657,6 +701,18 @@ sub adjust_new_dumpfile $dump =~ s/^SET default_table_access_method = heap;\n//mg; } + # During pg_upgrade, we reindex hash indexes if the source is pre-v10. + # This may change their tables' relallvisible values, so don't compare + # those. + if ($old_version < 10) + { + $dump =~ s/ + (^SELECT\s\*\sFROM\spg_catalog\.pg_restore_relation_stats\( + [^;]*'relation',\s'public\.hash_[a-z0-9]*_heap'::regclass, + [^;]*'relallvisible',)\s'\d+'::integer + /$1 ''::integer/mgx; + } + # dumps from pre-9.6 dblink may include redundant ACL settings if ($old_version lt '9.6') { diff --git a/src/test/perl/PostgreSQL/Test/BackgroundPsql.pm b/src/test/perl/PostgreSQL/Test/BackgroundPsql.pm index 3c2aca1c5d7bc..60bbd5dd445b3 100644 --- a/src/test/perl/PostgreSQL/Test/BackgroundPsql.pm +++ b/src/test/perl/PostgreSQL/Test/BackgroundPsql.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod @@ -68,7 +68,7 @@ use Test::More; =over -=item PostgreSQL::Test::BackgroundPsql->new(interactive, @psql_params, timeout) +=item PostgreSQL::Test::BackgroundPsql->new(interactive, @psql_params, timeout, wait) Builds a new object of class C for either an interactive or background session and starts it. If C is @@ -76,17 +76,21 @@ true then a PTY will be attached. C should contain the full command to run psql with all desired parameters and a complete connection string. For C sessions, IO::Pty is required. +This routine will not return until psql has started up and is ready to +consume input. Set B to 0 to return immediately instead. + =cut sub new { my $class = shift; - my ($interactive, $psql_params, $timeout) = @_; + my ($interactive, $psql_params, $timeout, $wait) = @_; my $psql = { 'stdin' => '', 'stdout' => '', 'stderr' => '', - 'query_timer_restart' => undef + 'query_timer_restart' => undef, + 'query_cnt' => 1, }; my $run; @@ -104,14 +108,17 @@ sub new if ($interactive) { $run = IPC::Run::start $psql_params, - '{stdin}, '>pty>', \$psql->{stdout}, '2>', - \$psql->{stderr}, + ' \$psql->{stdin}, + '>pty>' => \$psql->{stdout}, + '2>' => \$psql->{stderr}, $psql->{timeout}; } else { $run = IPC::Run::start $psql_params, - '<', \$psql->{stdin}, '>', \$psql->{stdout}, '2>', \$psql->{stderr}, + '<' => \$psql->{stdin}, + '>' => \$psql->{stdout}, + '2>' => \$psql->{stderr}, $psql->{timeout}; } @@ -119,14 +126,25 @@ sub new my $self = bless $psql, $class; - $self->_wait_connect(); + $wait = 1 unless defined($wait); + if ($wait) + { + $self->wait_connect(); + } return $self; } -# Internal routine for awaiting psql starting up and being ready to consume -# input. -sub _wait_connect +=pod + +=item $session->wait_connect + +Returns once psql has started up and is ready to consume input. This is called +automatically for clients unless requested otherwise in the constructor. + +=cut + +sub wait_connect { my ($self) = @_; @@ -134,11 +152,25 @@ sub _wait_connect # connection failures are caught here, relieving callers of the need to # handle those. (Right now, we have no particularly good handling for # errors anyway, but that might be added later.) + # + # See query() for details about why/how the banner is used. my $banner = "background_psql: ready"; - $self->{stdin} .= "\\echo $banner\n"; + my $banner_match = qr/(^|\n)$banner\r?\n/; + $self->{stdin} .= "\\echo $banner\n\\warn $banner\n"; $self->{run}->pump() - until $self->{stdout} =~ /$banner/ || $self->{timeout}->is_expired; - $self->{stdout} = ''; # clear out banner + until ($self->{stdout} =~ /$banner_match/ + && $self->{stderr} =~ /$banner\r?\n/) + || $self->{timeout}->is_expired; + + note "connect output:\n", + explain { + stdout => $self->{stdout}, + stderr => $self->{stderr}, + }; + + # clear out banners + $self->{stdout} = ''; + $self->{stderr} = ''; die "psql startup timed out" if $self->{timeout}->is_expired; } @@ -187,7 +219,7 @@ sub reconnect_and_clear $self->{stdin} = ''; $self->{stdout} = ''; - $self->_wait_connect(); + $self->wait_connect(); } =pod @@ -205,25 +237,57 @@ sub query my ($self, $query) = @_; my $ret; my $output; + my $query_cnt = $self->{query_cnt}++; + local $Test::Builder::Level = $Test::Builder::Level + 1; - note "issuing query via background psql: $query"; + note "issuing query $query_cnt via background psql: $query"; $self->{timeout}->start() if (defined($self->{query_timer_restart})); # Feed the query to psql's stdin, followed by \n (so psql processes the # line), by a ; (so that psql issues the query, if it doesn't include a ; - # itself), and a separator echoed with \echo, that we can wait on. - my $banner = "background_psql: QUERY_SEPARATOR"; - $self->{stdin} .= "$query\n;\n\\echo $banner\n"; - - pump_until($self->{run}, $self->{timeout}, \$self->{stdout}, qr/$banner/); + # itself), and a separator echoed both with \echo and \warn, that we can + # wait on. + # + # To avoid somehow confusing the separator from separately issued queries, + # and to make it easier to debug, we include a per-psql query counter in + # the separator. + # + # We need both \echo (printing to stdout) and \warn (printing to stderr), + # because on windows we can get data on stdout before seeing data on + # stderr (or vice versa), even if psql printed them in the opposite + # order. We therefore wait on both. + # + # We need to match for the newline, because we try to remove it below, and + # it's possible to consume just the input *without* the newline. In + # interactive psql we emit \r\n, so we need to allow for that. Also need + # to be careful that we don't e.g. match the echoed \echo command, rather + # than its output. + my $banner = "background_psql: QUERY_SEPARATOR $query_cnt:"; + my $banner_match = qr/(^|\n)$banner\r?\n/; + $self->{stdin} .= "$query\n;\n\\echo $banner\n\\warn $banner\n"; + pump_until( + $self->{run}, $self->{timeout}, + \$self->{stdout}, qr/$banner_match/); + pump_until( + $self->{run}, $self->{timeout}, + \$self->{stderr}, qr/$banner_match/); die "psql query timed out" if $self->{timeout}->is_expired; - $output = $self->{stdout}; - # remove banner again, our caller doesn't care - $output =~ s/\n$banner\n$//s; + note "results query $query_cnt:\n", + explain { + stdout => $self->{stdout}, + stderr => $self->{stderr}, + }; + + # Remove banner from stdout and stderr, our caller doesn't care. The + # first newline is optional, as there would not be one if consuming an + # empty query result. + $output = $self->{stdout}; + $output =~ s/$banner_match//; + $self->{stderr} =~ s/$banner_match//; # clear out output for the next query $self->{stdout} = ''; diff --git a/src/test/perl/PostgreSQL/Test/Cluster.pm b/src/test/perl/PostgreSQL/Test/Cluster.pm index 32ee98aebccd1..1c11750ac1d07 100644 --- a/src/test/perl/PostgreSQL/Test/Cluster.pm +++ b/src/test/perl/PostgreSQL/Test/Cluster.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod @@ -104,6 +104,7 @@ use File::Path qw(rmtree mkpath); use File::Spec; use File::stat qw(stat); use File::Temp (); +use IO::Socket::INET; use IPC::Run; use PostgreSQL::Version; use PostgreSQL::Test::RecursiveCopy; @@ -167,14 +168,17 @@ INIT $portdir = $ENV{PG_TEST_PORT_DIR}; # Otherwise, try to use a directory at the top of the build tree # or as a last resort use the tmp_check directory - my $build_dir = - $ENV{MESON_BUILD_ROOT} - || $ENV{top_builddir} + my $build_dir = $ENV{top_builddir} || $PostgreSQL::Test::Utils::tmp_check; $portdir ||= "$build_dir/portlock"; $portdir =~ s!\\!/!g; # Make sure the directory exists mkpath($portdir) unless -d $portdir; + + # + # Signal handlers + # + $SIG{TERM} = $SIG{INT} = sub { die "death by signal"; }; } =pod @@ -286,6 +290,82 @@ sub connstr =pod +=item $node->raw_connect() + +Open a raw TCP or Unix domain socket connection to the server. This is +used by low-level protocol and connection limit tests. + +=cut + +sub raw_connect +{ + my ($self) = @_; + my $pgport = $self->port; + my $pghost = $self->host; + + my $socket; + if ($PostgreSQL::Test::Utils::use_unix_sockets) + { + require IO::Socket::UNIX; + my $path = "$pghost/.s.PGSQL.$pgport"; + + $socket = IO::Socket::UNIX->new( + Type => SOCK_STREAM(), + Peer => $path, + ) or die "Cannot create socket - $IO::Socket::errstr\n"; + } + else + { + $socket = IO::Socket::INET->new( + PeerHost => $pghost, + PeerPort => $pgport, + Proto => 'tcp' + ) or die "Cannot create socket - $IO::Socket::errstr\n"; + } + return $socket; +} + +=pod + +=item $node->raw_connect_works() + +Check if raw_connect() function works on this platform. This should +be called to SKIP any tests that require raw_connect(). + +This tries to connect to the server, to test whether it works or not,, +so the server is up and running. Otherwise this can return 0 even if +there's nothing wrong with raw_connect() itself. + +Notably, raw_connect() does not work on Unix domain sockets on +Strawberry perl 5.26.3.1 on Windows, which we use in Cirrus CI images +as of this writing. It dies with "not implemented on this +architecture". + +=cut + +sub raw_connect_works +{ + my ($self) = @_; + + # If we're using Unix domain sockets, we need a working + # IO::Socket::UNIX implementation. + if ($PostgreSQL::Test::Utils::use_unix_sockets) + { + eval { + my $sock = $self->raw_connect(); + $sock->close(); + }; + if ($@ =~ /not implemented/) + { + diag "IO::Socket::UNIX does not work: $@"; + return 0; + } + } + return 1; +} + +=pod + =item $node->group_access() Does the data dir allow group access? @@ -504,6 +584,8 @@ On Windows, we use SSPI authentication to ensure the same (by pg_regress WAL archiving can be enabled on this node by passing the keyword parameter has_archiving => 1. This is disabled by default. +Data checksums can be forced off by passing no_data_checksums => 1. + postgresql.conf can be set up for replication by passing the keyword parameter allows_streaming => 'logical' or 'physical' (passing 1 will also suffice for physical replication) depending on type of replication that @@ -536,6 +618,12 @@ sub init push @{ $params{extra} }, shellwords($initdb_extra_opts_env); } + # This should override user-supplied initdb options. + if ($params{no_data_checksums}) + { + push @{ $params{extra} }, '--no-data-checksums'; + } + mkdir $self->backup_dir; mkdir $self->archive_dir; @@ -552,8 +640,11 @@ sub init or !defined $ENV{INITDB_TEMPLATE}) { note("initializing database system by running initdb"); - PostgreSQL::Test::Utils::system_or_bail('initdb', '-D', $pgdata, '-A', - 'trust', '-N', @{ $params{extra} }); + PostgreSQL::Test::Utils::system_or_bail( + 'initdb', '--no-sync', + '--pgdata' => $pgdata, + '--auth' => 'trust', + @{ $params{extra} }); } else { @@ -617,6 +708,7 @@ sub init } print $conf "max_wal_senders = 10\n"; print $conf "max_replication_slots = 10\n"; + print $conf "autovacuum_worker_slots = 3\n"; print $conf "wal_log_hints = on\n"; print $conf "hot_standby = on\n"; # conservative settings to ensure we can run multiple postmasters: @@ -749,11 +841,11 @@ sub backup print "# Taking pg_basebackup $backup_name from node \"$name\"\n"; PostgreSQL::Test::Utils::system_or_bail( - 'pg_basebackup', '-D', - $backup_path, '-h', - $self->host, '-p', - $self->port, '--checkpoint', - 'fast', '--no-sync', + 'pg_basebackup', '--no-sync', + '--pgdata' => $backup_path, + '--host' => $self->host, + '--port' => $self->port, + '--checkpoint' => 'fast', @{ $params{backup_options} }); print "# Backup finished\n"; return; @@ -857,7 +949,7 @@ sub init_from_backup } local %ENV = $self->_get_env(); - my @combineargs = ('pg_combinebackup', '-d'); + my @combineargs = ('pg_combinebackup', '--debug'); if (exists $params{tablespace_map}) { while (my ($olddir, $newdir) = each %{ $params{tablespace_map} }) @@ -870,19 +962,21 @@ sub init_from_backup { push @combineargs, $params{combine_mode}; } - push @combineargs, @prior_backup_path, $backup_path, '-o', $data_path; + push @combineargs, @prior_backup_path, $backup_path, + '--output' => $data_path; PostgreSQL::Test::Utils::system_or_bail(@combineargs); } elsif (defined $params{tar_program}) { mkdir($data_path) || die "mkdir $data_path: $!"; - PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf', - $backup_path . '/base.tar', - '-C', $data_path); PostgreSQL::Test::Utils::system_or_bail( - $params{tar_program}, 'xf', - $backup_path . '/pg_wal.tar', '-C', - $data_path . '/pg_wal'); + $params{tar_program}, + 'xf' => $backup_path . '/base.tar', + '-C' => $data_path); + PostgreSQL::Test::Utils::system_or_bail( + $params{tar_program}, + 'xf' => $backup_path . '/pg_wal.tar', + '-C' => $data_path . '/pg_wal'); # We need to generate a tablespace_map file. open(my $tsmap, ">", "$data_path/tablespace_map") @@ -902,9 +996,10 @@ sub init_from_backup my $newdir = $params{tablespace_map}{$tsoid}; mkdir($newdir) || die "mkdir $newdir: $!"; - PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, - 'xf', $backup_path . '/' . $tstar, - '-C', $newdir); + PostgreSQL::Test::Utils::system_or_bail( + $params{tar_program}, + 'xf' => $backup_path . '/' . $tstar, + '-C' => $newdir); my $escaped_newdir = $newdir; $escaped_newdir =~ s/\\/\\\\/g; @@ -924,7 +1019,7 @@ sub init_from_backup PostgreSQL::Test::RecursiveCopy::copypath( $backup_path, $data_path, - 'filterfn' => sub { + filterfn => sub { my ($path) = @_; if ($path =~ /^pg_tblspc\/(\d+)$/ && exists $params{tablespace_map}{$1}) @@ -1044,8 +1139,10 @@ sub start # -w is now the default but having it here does no harm and helps # compatibility with older versions. $ret = PostgreSQL::Test::Utils::system_log( - 'pg_ctl', '-w', '-D', $self->data_dir, - '-l', $self->logfile, '-o', "--cluster-name=$name", + 'pg_ctl', '--wait', + '--pgdata' => $self->data_dir, + '--log' => $self->logfile, + '--options' => "--cluster-name=$name", 'start'); if ($ret != 0) @@ -1104,6 +1201,9 @@ this to fail. Otherwise, tests might fail to detect server crashes. With optional extra param fail_ok => 1, returns 0 for failure instead of bailing out. +The optional extra param timeout can be used to pass the pg_ctl +--timeout option. + =cut sub stop @@ -1119,8 +1219,12 @@ sub stop return 1 unless defined $self->{_pid}; print "### Stopping node \"$name\" using mode $mode\n"; - $ret = PostgreSQL::Test::Utils::system_log('pg_ctl', '-D', $pgdata, - '-m', $mode, 'stop'); + my @cmd = ('pg_ctl', '--pgdata' => $pgdata, '--mode' => $mode, 'stop'); + if ($params{timeout}) + { + push(@cmd, ('--timeout' => $params{timeout})); + } + $ret = PostgreSQL::Test::Utils::system_log(@cmd); if ($ret != 0) { @@ -1155,7 +1259,9 @@ sub reload local %ENV = $self->_get_env(); print "### Reloading node \"$name\"\n"; - PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata, + PostgreSQL::Test::Utils::system_or_bail( + 'pg_ctl', + '--pgdata' => $pgdata, 'reload'); return; } @@ -1183,8 +1289,11 @@ sub restart # -w is now the default but having it here does no harm and helps # compatibility with older versions. - $ret = PostgreSQL::Test::Utils::system_log('pg_ctl', '-w', '-D', - $self->data_dir, '-l', $self->logfile, 'restart'); + $ret = PostgreSQL::Test::Utils::system_log( + 'pg_ctl', '--wait', + '--pgdata' => $self->data_dir, + '--log' => $self->logfile, + 'restart'); if ($ret != 0) { @@ -1222,8 +1331,11 @@ sub promote local %ENV = $self->_get_env(); print "### Promoting node \"$name\"\n"; - PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata, '-l', - $logfile, 'promote'); + PostgreSQL::Test::Utils::system_or_bail( + 'pg_ctl', + '--pgdata' => $pgdata, + '--log' => $logfile, + 'promote'); return; } @@ -1246,8 +1358,11 @@ sub logrotate local %ENV = $self->_get_env(); print "### Rotating log in node \"$name\"\n"; - PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata, '-l', - $logfile, 'logrotate'); + PostgreSQL::Test::Utils::system_or_bail( + 'pg_ctl', + '--pgdata' => $pgdata, + '--log' => $logfile, + 'logrotate'); return; } @@ -2024,7 +2139,9 @@ sub psql my @psql_params = ( $self->installed_command('psql'), - '-XAtq', '-d', $psql_connstr, '-f', '-'); + '--no-psqlrc', '--no-align', '--tuples-only', '--quiet', + '--dbname' => $psql_connstr, + '--file' => '-'); # If the caller wants an array and hasn't passed stdout/stderr # references, allocate temporary ones to capture them so we @@ -2046,7 +2163,8 @@ sub psql $params{on_error_stop} = 1 unless defined $params{on_error_stop}; $params{on_error_die} = 0 unless defined $params{on_error_die}; - push @psql_params, '-v', 'ON_ERROR_STOP=1' if $params{on_error_stop}; + push @psql_params, '--variable' => 'ON_ERROR_STOP=1' + if $params{on_error_stop}; push @psql_params, @{ $params{extra_params} } if defined $params{extra_params}; @@ -2072,9 +2190,9 @@ sub psql { local $@; eval { - my @ipcrun_opts = (\@psql_params, '<', \$sql); - push @ipcrun_opts, '>', $stdout if defined $stdout; - push @ipcrun_opts, '2>', $stderr if defined $stderr; + my @ipcrun_opts = (\@psql_params, '<' => \$sql); + push @ipcrun_opts, '>' => $stdout if defined $stdout; + push @ipcrun_opts, '2>' => $stderr if defined $stderr; push @ipcrun_opts, $timeout if defined $timeout; IPC::Run::run @ipcrun_opts; @@ -2181,6 +2299,11 @@ returned. Set B to 0 to ignore errors instead. Set a timeout for a background psql session. By default, timeout of $PostgreSQL::Test::Utils::timeout_default is set up. +=item connstr => B + +If set, use this as the connection string for the connection to the +backend. + =item replication => B If set, add B to the conninfo string. @@ -2191,6 +2314,12 @@ connection. If given, it must be an array reference containing additional parameters to B. +=item wait => 1 + +By default, this method will not return until connection has completed (or +failed). Set B to 0 to return immediately instead. (Clients can call the +session's C method manually when needed.) + =back =cut @@ -2204,23 +2333,35 @@ sub background_psql my $replication = $params{replication}; my $timeout = undef; + # Build the connection string. + my $psql_connstr; + if (defined $params{connstr}) + { + $psql_connstr = $params{connstr}; + } + else + { + $psql_connstr = $self->connstr($dbname); + } + $psql_connstr .= defined $replication ? " replication=$replication" : ""; + my @psql_params = ( $self->installed_command('psql'), - '-XAtq', - '-d', - $self->connstr($dbname) - . (defined $replication ? " replication=$replication" : ""), - '-f', - '-'); + '--no-psqlrc', '--no-align', + '--tuples-only', '--quiet', + '--dbname' => $psql_connstr, + '--file' => '-'); $params{on_error_stop} = 1 unless defined $params{on_error_stop}; + $params{wait} = 1 unless defined $params{wait}; $timeout = $params{timeout} if defined $params{timeout}; - push @psql_params, '-v', 'ON_ERROR_STOP=1' if $params{on_error_stop}; + push @psql_params, '--set' => 'ON_ERROR_STOP=1' if $params{on_error_stop}; push @psql_params, @{ $params{extra_params} } if defined $params{extra_params}; - return PostgreSQL::Test::BackgroundPsql->new(0, \@psql_params, $timeout); + return PostgreSQL::Test::BackgroundPsql->new(0, \@psql_params, $timeout, + $params{wait}); } =pod @@ -2286,7 +2427,8 @@ sub interactive_psql my @psql_params = ( $self->installed_command('psql'), - '-XAt', '-d', $self->connstr($dbname)); + '--no-psqlrc', '--no-align', '--tuples-only', + '--dbname' => $self->connstr($dbname)); push @psql_params, @{ $params{extra_params} } if defined $params{extra_params}; @@ -2308,7 +2450,7 @@ sub _pgbench_make_files for my $fn (sort keys %$files) { my $filename = $self->basedir . '/' . $fn; - push @file_opts, '-f', $filename; + push @file_opts, '--file' => $filename; # cleanup file weight $filename =~ s/\@\d+$//; @@ -2397,6 +2539,11 @@ instead of the default. If this regular expression is set, matches it with the output generated. +=item expected_stderr => B + +If this regular expression is set, matches it against the standard error +stream; otherwise stderr must be empty. + =item log_like => [ qr/required message/ ] =item log_unlike => [ qr/prohibited message/ ] @@ -2440,7 +2587,22 @@ sub connect_ok like($stdout, $params{expected_stdout}, "$test_name: stdout matches"); } - is($stderr, "", "$test_name: no stderr"); + if (defined($params{expected_stderr})) + { + if (like( + $stderr, $params{expected_stderr}, + "$test_name: stderr matches") + && ($ret != 0)) + { + # In this case (failing test but matching stderr) we'll have + # swallowed the output needed to debug. Put it back into the logs. + diag("$test_name: full stderr:\n" . $stderr); + } + } + else + { + is($stderr, "", "$test_name: no stderr"); + } $self->log_check($test_name, $log_location, %params); } @@ -2456,13 +2618,19 @@ to fail. =item expected_stderr => B -If this regular expression is set, matches it with the output generated. +If this regular expression is set, matches it to the output generated +by B. =item log_like => [ qr/required message/ ] =item log_unlike => [ qr/prohibited message/ ] -See C. +See C. CAUTION: use of either option requires that +the server's log_min_messages be at least DEBUG2, and that no other +client backend is launched concurrently. These requirements allow +C to wait to see the postmaster-log report of backend +exit, without which there is a race condition as to whether we will +see the expected backend log output. =back @@ -2490,7 +2658,14 @@ sub connect_fails like($stderr, $params{expected_stderr}, "$test_name: matches"); } - $self->log_check($test_name, $log_location, %params); + if (defined($params{log_like}) or defined($params{log_unlike})) + { + $self->wait_for_log( + qr/DEBUG: (?:00000: )?forked new client backend, pid=(\d+) socket.*DEBUG: (?:00000: )?client backend \(PID \1\) exited with exit code \d/s, + $log_location); + + $self->log_check($test_name, $log_location, %params); + } } =pod @@ -2514,8 +2689,9 @@ sub poll_query_until $expected = 't' unless defined($expected); # default value my $cmd = [ - $self->installed_command('psql'), '-XAt', - '-d', $self->connstr($dbname) + $self->installed_command('psql'), '--no-psqlrc', + '--no-align', '--tuples-only', + '--dbname' => $self->connstr($dbname) ]; my ($stdout, $stderr); my $max_attempts = 10 * $PostgreSQL::Test::Utils::timeout_default; @@ -2523,8 +2699,10 @@ sub poll_query_until while ($attempts < $max_attempts) { - my $result = IPC::Run::run $cmd, '<', \$query, - '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run $cmd, + '<' => \$query, + '>' => \$stdout, + '2>' => \$stderr; chomp($stdout); chomp($stderr); @@ -2636,6 +2814,25 @@ sub command_fails_like =pod +=item $node->command_ok_or_fails_like(...) + +PostgreSQL::Test::Utils::command_ok_or_fails_like with our connection parameters. See command_ok(...) + +=cut + +sub command_ok_or_fails_like +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my $self = shift; + + local %ENV = $self->_get_env(); + + return PostgreSQL::Test::Utils::command_ok_or_fails_like(@_); +} + +=pod + =item $node->command_checks_all(...) PostgreSQL::Test::Utils::command_checks_all with our connection parameters. See @@ -2684,6 +2881,33 @@ sub issues_sql_like =pod +=item $node->issues_sql_unlike(cmd, unexpected_sql, test_name) + +Run a command on the node, then verify that $unexpected_sql does not appear in +the server log file. + +=cut + +sub issues_sql_unlike +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + + my ($self, $cmd, $unexpected_sql, $test_name) = @_; + + local %ENV = $self->_get_env(); + + my $log_location = -s $self->logfile; + + my $result = PostgreSQL::Test::Utils::run_log($cmd); + ok($result, "@$cmd exit code 0"); + my $log = + PostgreSQL::Test::Utils::slurp_file($self->logfile, $log_location); + unlike($log, $unexpected_sql, "$test_name: SQL not found in server log"); + return; +} + +=pod + =item $node->log_content() Returns the contents of log of the node @@ -2698,7 +2922,7 @@ sub log_content =pod -=item $node->log_check($offset, $test_name, %parameters) +=item $node->log_check($test_name, $offset, %params) Check contents of server logs. @@ -2837,7 +3061,177 @@ sub lsn =pod -=item $node->wait_for_event(wait_event_name, backend_type) +=item $node->write_wal($tli, $lsn, $segment_size, $data) + +Write some arbitrary data in WAL for the given segment at $lsn (in bytes). +This should be called while the cluster is not running. + +Returns the path of the WAL segment written to. + +=cut + +sub write_wal +{ + my ($self, $tli, $lsn, $segment_size, $data) = @_; + + # Calculate segment number and offset position in segment based on the + # input LSN. + my $segment = $lsn / $segment_size; + my $offset = $lsn % $segment_size; + my $path = + sprintf("%s/pg_wal/%08X%08X%08X", $self->data_dir, $tli, 0, $segment); + + open my $fh, "+<:raw", $path or die "could not open WAL segment $path"; + seek($fh, $offset, SEEK_SET) or die "could not seek WAL segment $path"; + print $fh $data; + close $fh; + + return $path; +} + +=pod + +=item $node->emit_wal($size) + +Emit a WAL record of arbitrary size, using pg_logical_emit_message(). + +Returns the end LSN of the record inserted, in bytes. + +=cut + +sub emit_wal +{ + my ($self, $size) = @_; + + return int( + $self->safe_psql( + 'postgres', + "SELECT pg_logical_emit_message(true, '', repeat('a', $size)) - '0/0'" + )); +} + + +# Private routine returning the current insert LSN of a node, in bytes. +# Used by the routines below in charge of advancing WAL to arbitrary +# positions. The insert LSN is returned in bytes. +sub _get_insert_lsn +{ + my ($self) = @_; + return int( + $self->safe_psql( + 'postgres', "SELECT pg_current_wal_insert_lsn() - '0/0'")); +} + +=pod + +=item $node->advance_wal_out_of_record_splitting_zone($wal_block_size) + +Advance WAL at the end of a page, making sure that we are far away enough +from the end of a page that we could insert a couple of small records. + +This inserts a few records of a fixed size, until the threshold gets close +enough to the end of the WAL page inserting records to. + +Returns the end LSN up to which WAL has advanced, in bytes. + +=cut + +sub advance_wal_out_of_record_splitting_zone +{ + my ($self, $wal_block_size) = @_; + + my $page_threshold = $wal_block_size / 4; + my $end_lsn = $self->_get_insert_lsn(); + my $page_offset = $end_lsn % $wal_block_size; + while ($page_offset >= $wal_block_size - $page_threshold) + { + $self->emit_wal($page_threshold); + $end_lsn = $self->_get_insert_lsn(); + $page_offset = $end_lsn % $wal_block_size; + } + return $end_lsn; +} + +=pod + +=item $node->advance_wal_to_record_splitting_zone($wal_block_size) + +Advance WAL so close to the end of a page that an XLogRecordHeader would not +fit on it. + +Returns the end LSN up to which WAL has advanced, in bytes. + +=cut + +sub advance_wal_to_record_splitting_zone +{ + my ($self, $wal_block_size) = @_; + + # Size of record header. + my $RECORD_HEADER_SIZE = 24; + + my $end_lsn = $self->_get_insert_lsn(); + my $page_offset = $end_lsn % $wal_block_size; + + # Get fairly close to the end of a page in big steps + while ($page_offset <= $wal_block_size - 512) + { + $self->emit_wal($wal_block_size - $page_offset - 256); + $end_lsn = $self->_get_insert_lsn(); + $page_offset = $end_lsn % $wal_block_size; + } + + # Calibrate our message size so that we can get closer 8 bytes at + # a time. + my $message_size = $wal_block_size - 80; + while ($page_offset <= $wal_block_size - $RECORD_HEADER_SIZE) + { + $self->emit_wal($message_size); + $end_lsn = $self->_get_insert_lsn(); + + my $old_offset = $page_offset; + $page_offset = $end_lsn % $wal_block_size; + + # Adjust the message size until it causes 8 bytes changes in + # offset, enough to be able to split a record header. + my $delta = $page_offset - $old_offset; + if ($delta > 8) + { + $message_size -= 8; + } + elsif ($delta <= 0) + { + $message_size += 8; + } + } + return $end_lsn; +} + +=pod + +=item $node->check_extension(extension_name) + +Scan pg_available_extensions to check that an extension is available in an +installation. + +Returns 1 if the extension is available, 0 otherwise. + +=cut + +sub check_extension +{ + my ($self, $extension_name) = @_; + + my $result = $self->safe_psql('postgres', + "SELECT count(*) > 0 FROM pg_available_extensions WHERE name = '$extension_name';" + ); + + return $result eq 't' ? 1 : 0; +} + +=pod + +=item $node->wait_for_event(backend_type, wait_event_name) Poll pg_stat_activity until backend_type reaches wait_event_name. @@ -2948,6 +3342,11 @@ sub wait_for_catchup } else { + # Fetch additional detail for debugging purposes + $query = qq[SELECT * FROM pg_catalog.pg_stat_replication]; + my $details = $self->safe_psql('postgres', $query); + diag qq(Last pg_stat_replication contents: +${details}); croak "timed out waiting for catchup"; } } @@ -3015,8 +3414,15 @@ sub wait_for_slot_catchup . $self->name . "\n"; my $query = qq[SELECT '$target_lsn' <= ${mode}_lsn FROM pg_catalog.pg_replication_slots WHERE slot_name = '$slot_name';]; - $self->poll_query_until('postgres', $query) - or croak "timed out waiting for catchup"; + if (!$self->poll_query_until('postgres', $query)) + { + # Fetch additional detail for debugging purposes + $query = qq[SELECT * FROM pg_catalog.pg_replication_slots]; + my $details = $self->safe_psql('postgres', $query); + diag qq(Last pg_replication_slots contents: +${details}); + croak "timed out waiting for catchup"; + } print "done\n"; return; } @@ -3051,8 +3457,15 @@ sub wait_for_subscription_sync print "Waiting for all subscriptions in \"$name\" to synchronize data\n"; my $query = qq[SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');]; - $self->poll_query_until($dbname, $query) - or croak "timed out waiting for subscriber to synchronize data"; + if (!$self->poll_query_until($dbname, $query)) + { + # Fetch additional detail for debugging purposes + $query = qq[SELECT * FROM pg_subscription_rel]; + my $details = $self->safe_psql($dbname, $query); + diag qq(Last pg_subscription_rel contents: +${details}); + croak "timed out waiting for subscriber to synchronize data"; + } # Then, wait for the replication to catchup if required. if (defined($publisher)) @@ -3209,15 +3622,17 @@ sub pg_recvlogical_upto my @cmd = ( $self->installed_command('pg_recvlogical'), - '-S', $slot_name, '--dbname', $self->connstr($dbname)); - push @cmd, '--endpos', $endpos; - push @cmd, '-f', '-', '--no-loop', '--start'; + '--slot' => $slot_name, + '--dbname' => $self->connstr($dbname), + '--endpos' => $endpos, + '--file' => '-', + '--no-loop', '--start'); while (my ($k, $v) = each %plugin_options) { croak "= is not permitted to appear in replication option name" if ($k =~ qr/=/); - push @cmd, "-o", "$k=$v"; + push @cmd, "--option" => "$k=$v"; } my $timeout; @@ -3230,7 +3645,7 @@ sub pg_recvlogical_upto { local $@; eval { - IPC::Run::run(\@cmd, ">", \$stdout, "2>", \$stderr, $timeout); + IPC::Run::run(\@cmd, '>' => \$stdout, '2>' => \$stderr, $timeout); $ret = $?; }; my $exc_save = $@; @@ -3297,13 +3712,6 @@ sub corrupt_page_checksum return; } -# -# Signal handlers -# -$SIG{TERM} = $SIG{INT} = sub { - die "death by signal"; -}; - =pod =item $node->log_standby_snapshot(self, standby, slot_name) @@ -3351,15 +3759,14 @@ sub create_logical_slot_on_standby $handle = IPC::Run::start( [ - 'pg_recvlogical', '-d', - $self->connstr($dbname), '-P', - 'test_decoding', '-S', - $slot_name, '--create-slot' + 'pg_recvlogical', + '--dbname' => $self->connstr($dbname), + '--plugin' => 'test_decoding', + '--slot' => $slot_name, + '--create-slot' ], - '>', - \$stdout, - '2>', - \$stderr); + '>' => \$stdout, + '2>' => \$stderr); # Arrange for the xl_running_xacts record for which pg_recvlogical is # waiting. diff --git a/src/test/perl/PostgreSQL/Test/Kerberos.pm b/src/test/perl/PostgreSQL/Test/Kerberos.pm index f76d765368e27..b72dd2fbaf414 100644 --- a/src/test/perl/PostgreSQL/Test/Kerberos.pm +++ b/src/test/perl/PostgreSQL/Test/Kerberos.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Sets up a stand-alone KDC for testing PostgreSQL GSSAPI / Kerberos # functionality. @@ -104,7 +104,7 @@ sub new my ($host, $hostaddr, $realm) = @_; my ($stdout, $krb5_version); - run_log [ $krb5_config, '--version' ], '>', \$stdout + run_log [ $krb5_config, '--version' ], '>' => \$stdout or BAIL_OUT("could not execute krb5-config"); BAIL_OUT("Heimdal is not supported") if $stdout =~ m/heimdal/; $stdout =~ m/Kerberos 5 release ([0-9]+\.[0-9]+)/ diff --git a/src/test/perl/PostgreSQL/Test/RecursiveCopy.pm b/src/test/perl/PostgreSQL/Test/RecursiveCopy.pm index 8b9701ed987a2..3363aeef87005 100644 --- a/src/test/perl/PostgreSQL/Test/RecursiveCopy.pm +++ b/src/test/perl/PostgreSQL/Test/RecursiveCopy.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod diff --git a/src/test/perl/PostgreSQL/Test/SimpleTee.pm b/src/test/perl/PostgreSQL/Test/SimpleTee.pm index 65e8ee054e3a5..52bdae4180679 100644 --- a/src/test/perl/PostgreSQL/Test/SimpleTee.pm +++ b/src/test/perl/PostgreSQL/Test/SimpleTee.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # A simple 'tee' implementation, using perl tie. # diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm index 022b44ba22bc9..7d7ca83495f49 100644 --- a/src/test/perl/PostgreSQL/Test/Utils.pm +++ b/src/test/perl/PostgreSQL/Test/Utils.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod @@ -20,7 +20,7 @@ PostgreSQL::Test::Utils - helper module for writing PostgreSQL's C tests. command_fails(['initdb', '--invalid-option'], 'command fails with invalid option'); my $tempdir = PostgreSQL::Test::Utils::tempdir; - command_ok('initdb', '-D', $tempdir); + command_ok('initdb', '--pgdata' => $tempdir); # Miscellanea print "on Windows" if $PostgreSQL::Test::Utils::windows_os; @@ -50,6 +50,7 @@ use Cwd; use Exporter 'import'; use Fcntl qw(:mode :seek); use File::Basename; +use File::Compare; use File::Find; use File::Spec; use File::stat qw(stat); @@ -70,6 +71,7 @@ our @EXPORT = qw( check_mode_recursive chmod_recursive check_pg_config + compare_files dir_symlink scan_server_header system_or_bail @@ -87,6 +89,7 @@ our @EXPORT = qw( command_like command_like_safe command_fails_like + command_ok_or_fails_like command_checks_all $windows_os @@ -331,7 +334,7 @@ sub has_wal_read_bug return $Config{osname} eq 'linux' && $Config{archname} =~ /^sparc/ - && !run_log([ qw(df -x ext4), $tmp_check ], '>', '/dev/null', '2>&1'); + && !run_log([ qw(df -x ext4), $tmp_check ], '&>' => '/dev/null'); } =pod @@ -417,7 +420,7 @@ sub run_command { my ($cmd) = @_; my ($stdout, $stderr); - my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run $cmd, '>' => \$stdout, '2>' => \$stderr; chomp($stdout); chomp($stderr); return ($stdout, $stderr); @@ -721,8 +724,9 @@ sub scan_server_header my ($header_path, $regexp) = @_; my ($stdout, $stderr); - my $result = IPC::Run::run [ 'pg_config', '--includedir-server' ], '>', - \$stdout, '2>', \$stderr + my $result = IPC::Run::run [ 'pg_config', '--includedir-server' ], + '>' => \$stdout, + '2>' => \$stderr or die "could not execute pg_config"; chomp($stdout); $stdout =~ s/\r$//; @@ -759,8 +763,9 @@ sub check_pg_config { my ($regexp) = @_; my ($stdout, $stderr); - my $result = IPC::Run::run [ 'pg_config', '--includedir' ], '>', - \$stdout, '2>', \$stderr + my $result = IPC::Run::run [ 'pg_config', '--includedir' ], + '>' => \$stdout, + '2>' => \$stderr or die "could not execute pg_config"; chomp($stdout); $stdout =~ s/\r$//; @@ -773,6 +778,45 @@ sub check_pg_config =pod +=item compare_files(file1, file2, testname) + +Check that two files match, printing the difference if any. + +C is an optional CODE reference to a line comparison +function, passed down as-is to File::Compare::compare_text. + +=cut + +sub compare_files +{ + my ($file1, $file2, $testname, $line_comp_function) = @_; + + # If nothing is given, all lines should be equal. + $line_comp_function = sub { $_[0] ne $_[1] } + unless defined $line_comp_function; + + my $compare_res = + File::Compare::compare_text($file1, $file2, $line_comp_function); + is($compare_res, 0, $testname); + + # Provide more context if the files do not match. + if ($compare_res != 0) + { + my ($stdout, $stderr) = + run_command([ 'diff', '-u', $file1, $file2 ]); + print "=== diff of $file1 and $file2\n"; + print "=== stdout ===\n"; + print $stdout; + print "=== stderr ===\n"; + print $stderr; + print "=== EOF ===\n"; + } + + return; +} + +=pod + =item dir_symlink(oldname, newname) Portably create a symlink for a directory. On Windows this creates a junction @@ -884,8 +928,9 @@ sub program_help_ok my ($cmd) = @_; my ($stdout, $stderr); print("# Running: $cmd --help\n"); - my $result = IPC::Run::run [ $cmd, '--help' ], '>', \$stdout, '2>', - \$stderr; + my $result = IPC::Run::run [ $cmd, '--help' ], + '>' => \$stdout, + '2>' => \$stderr; ok($result, "$cmd --help exit code 0"); isnt($stdout, '', "$cmd --help goes to stdout"); is($stderr, '', "$cmd --help nothing to stderr"); @@ -915,8 +960,9 @@ sub program_version_ok my ($cmd) = @_; my ($stdout, $stderr); print("# Running: $cmd --version\n"); - my $result = IPC::Run::run [ $cmd, '--version' ], '>', \$stdout, '2>', - \$stderr; + my $result = IPC::Run::run [ $cmd, '--version' ], + '>' => \$stdout, + '2>' => \$stderr; ok($result, "$cmd --version exit code 0"); isnt($stdout, '', "$cmd --version goes to stdout"); is($stderr, '', "$cmd --version nothing to stderr"); @@ -938,9 +984,9 @@ sub program_options_handling_ok my ($cmd) = @_; my ($stdout, $stderr); print("# Running: $cmd --not-a-valid-option\n"); - my $result = IPC::Run::run [ $cmd, '--not-a-valid-option' ], '>', - \$stdout, - '2>', \$stderr; + my $result = IPC::Run::run [ $cmd, '--not-a-valid-option' ], + '>' => \$stdout, + '2>' => \$stderr; ok(!$result, "$cmd with invalid option nonzero exit code"); isnt($stderr, '', "$cmd with invalid option prints error message"); return; @@ -961,7 +1007,7 @@ sub command_like my ($cmd, $expected_stdout, $test_name) = @_; my ($stdout, $stderr); print("# Running: " . join(" ", @{$cmd}) . "\n"); - my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run $cmd, '>' => \$stdout, '2>' => \$stderr; ok($result, "$test_name: exit code 0"); is($stderr, '', "$test_name: no stderr"); like($stdout, $expected_stdout, "$test_name: matches"); @@ -990,7 +1036,7 @@ sub command_like_safe my $stdoutfile = File::Temp->new(); my $stderrfile = File::Temp->new(); print("# Running: " . join(" ", @{$cmd}) . "\n"); - my $result = IPC::Run::run $cmd, '>', $stdoutfile, '2>', $stderrfile; + my $result = IPC::Run::run $cmd, '>' => $stdoutfile, '2>' => $stderrfile; $stdout = slurp_file($stdoutfile); $stderr = slurp_file($stderrfile); ok($result, "$test_name: exit code 0"); @@ -1014,7 +1060,7 @@ sub command_fails_like my ($cmd, $expected_stderr, $test_name) = @_; my ($stdout, $stderr); print("# Running: " . join(" ", @{$cmd}) . "\n"); - my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr; + my $result = IPC::Run::run $cmd, '>' => \$stdout, '2>' => \$stderr; ok(!$result, "$test_name: exit code not 0"); like($stderr, $expected_stderr, "$test_name: matches"); return; @@ -1022,6 +1068,30 @@ sub command_fails_like =pod +=item command_ok_or_fails_like(cmd, expected_stdout, expected_stderr, test_name) + +Check that the command either succeeds or fails with an error that matches the +given regular expressions. + +=cut + +sub command_ok_or_fails_like +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my ($cmd, $expected_stdout, $expected_stderr, $test_name) = @_; + my ($stdout, $stderr); + print("# Running: " . join(" ", @{$cmd}) . "\n"); + my $result = IPC::Run::run $cmd, '>' => \$stdout, '2>' => \$stderr; + if (!$result) + { + like($stdout, $expected_stdout, "$test_name: stdout matches"); + like($stderr, $expected_stderr, "$test_name: stderr matches"); + } + return $result; +} + +=pod + =item command_checks_all(cmd, ret, out, err, test_name) Run a command and check its status and outputs. @@ -1052,7 +1122,7 @@ sub command_checks_all # run command my ($stdout, $stderr); print("# Running: " . join(" ", @{$cmd}) . "\n"); - IPC::Run::run($cmd, '>', \$stdout, '2>', \$stderr); + IPC::Run::run($cmd, '>' => \$stdout, '2>' => \$stderr); # See http://perldoc.perl.org/perlvar.html#%24CHILD_ERROR my $ret = $?; diff --git a/src/test/perl/PostgreSQL/Version.pm b/src/test/perl/PostgreSQL/Version.pm index b8c0f642ca5e9..d8625bc9ef2d5 100644 --- a/src/test/perl/PostgreSQL/Version.pm +++ b/src/test/perl/PostgreSQL/Version.pm @@ -4,7 +4,7 @@ # # Module encapsulating Postgres Version numbers # -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # ############################################################################ diff --git a/src/test/perl/meson.build b/src/test/perl/meson.build index 4f0d928a6f3f0..e9726d54283bf 100644 --- a/src/test/perl/meson.build +++ b/src/test/perl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # could use install_data's preserve_path option in >=0.64.0 @@ -10,6 +10,9 @@ install_data( 'PostgreSQL/Test/Utils.pm', 'PostgreSQL/Test/SimpleTee.pm', 'PostgreSQL/Test/RecursiveCopy.pm', + 'PostgreSQL/Test/Kerberos.pm', 'PostgreSQL/Test/Cluster.pm', 'PostgreSQL/Test/BackgroundPsql.pm', + 'PostgreSQL/Test/AdjustDump.pm', + 'PostgreSQL/Test/AdjustUpgrade.pm', install_dir: dir_pgxs / 'src/test/perl/PostgreSQL/Test') diff --git a/src/test/postmaster/.gitignore b/src/test/postmaster/.gitignore new file mode 100644 index 0000000000000..871e943d50e1a --- /dev/null +++ b/src/test/postmaster/.gitignore @@ -0,0 +1,2 @@ +# Generated by test suite +/tmp_check/ diff --git a/src/test/postmaster/Makefile b/src/test/postmaster/Makefile new file mode 100644 index 0000000000000..e06b81f8c47fc --- /dev/null +++ b/src/test/postmaster/Makefile @@ -0,0 +1,23 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/test/postmaster +# +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/test/postmaster/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/test/postmaster +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +clean distclean: + rm -rf tmp_check diff --git a/src/test/postmaster/README b/src/test/postmaster/README new file mode 100644 index 0000000000000..7e47bf5cff0be --- /dev/null +++ b/src/test/postmaster/README @@ -0,0 +1,27 @@ +src/test/postmaster/README + +Regression tests for postmaster +=============================== + +This directory contains a test suite for postmaster's handling of +connections, connection limits, and startup/shutdown sequence. + + +Running the tests +================= + +NOTE: You must have given the --enable-tap-tests argument to configure. + +Run + make check +or + make installcheck +You can use "make installcheck" if you previously did "make install". +In that case, the code in the installation tree is tested. With +"make check", a temporary installation tree is built from the current +sources and then tested. + +Either way, this test initializes, starts, and stops a test Postgres +cluster. + +See src/test/perl/README for more info about running these tests. diff --git a/src/test/postmaster/meson.build b/src/test/postmaster/meson.build new file mode 100644 index 0000000000000..0ab32b42f2e0e --- /dev/null +++ b/src/test/postmaster/meson.build @@ -0,0 +1,14 @@ +# Copyright (c) 2022-2025, PostgreSQL Global Development Group + +tests += { + 'name': 'postmaster', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_basic.pl', + 't/002_connection_limits.pl', + 't/003_start_stop.pl', + ], + }, +} diff --git a/src/test/postmaster/t/001_basic.pl b/src/test/postmaster/t/001_basic.pl new file mode 100644 index 0000000000000..fb3984bb287ea --- /dev/null +++ b/src/test/postmaster/t/001_basic.pl @@ -0,0 +1,13 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; +use Test::More; + +program_help_ok('postgres'); +program_version_ok('postgres'); +program_options_handling_ok('postgres'); + +done_testing(); diff --git a/src/test/postmaster/t/002_connection_limits.pl b/src/test/postmaster/t/002_connection_limits.pl new file mode 100644 index 0000000000000..6442500fc379a --- /dev/null +++ b/src/test/postmaster/t/002_connection_limits.pl @@ -0,0 +1,154 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Test connection limits, i.e. max_connections, reserved_connections +# and superuser_reserved_connections. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Initialize the server with specific low connection limits +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init( + auth_extra => [ + '--create-role' => + 'regress_regular,regress_reserved,regress_superuser', + ]); +$node->append_conf('postgresql.conf', "max_connections = 6"); +$node->append_conf('postgresql.conf', "reserved_connections = 2"); +$node->append_conf('postgresql.conf', "superuser_reserved_connections = 1"); +$node->append_conf('postgresql.conf', + "log_connections = 'receipt,authentication,authorization'"); +$node->append_conf('postgresql.conf', "log_min_messages=debug2"); +$node->start; + +$node->safe_psql( + 'postgres', qq{ +CREATE USER regress_regular LOGIN; +CREATE USER regress_reserved LOGIN; +GRANT pg_use_reserved_connections TO regress_reserved; +CREATE USER regress_superuser LOGIN SUPERUSER; +}); + +# With the limits we set in postgresql.conf, we can establish: +# - 3 connections for any user with no special privileges +# - 2 more connections for users belonging to "pg_use_reserved_connections" +# - 1 more connection for superuser + +sub background_psql_as_user +{ + my $user = shift; + + return $node->background_psql( + 'postgres', + on_error_die => 1, + extra_params => [ '--username' => $user ]); +} + +# Like connect_fails(), except that we also wait for the failed backend to +# have exited. +# +# This tests needs to wait for client processes to exit because the error +# message for a failed connection is reported before the backend has detached +# from shared memory. If we didn't wait, subsequent tests might hit connection +# limits spuriously. +# +# This can't easily be generalized, as detecting process exit requires +# log_min_messages to be at least DEBUG2 and is not concurrency safe, as we +# can't easily be sure the right process exited. In this test that's not a +# problem though, we only have one new connection at a time. +sub connect_fails_wait +{ + local $Test::Builder::Level = $Test::Builder::Level + 1; + my ($node, $connstr, $test_name, %params) = @_; + + my $log_location = -s $node->logfile; + + $node->connect_fails($connstr, $test_name, %params); + $node->wait_for_log(qr/DEBUG: (00000: )?client backend.*exited with exit code 1/, + $log_location); + ok(1, "$test_name: client backend process exited"); +} + +my @sessions = (); +my @raw_connections = (); + +push(@sessions, background_psql_as_user('regress_regular')); +push(@sessions, background_psql_as_user('regress_regular')); +push(@sessions, background_psql_as_user('regress_regular')); +connect_fails_wait( + $node, + "dbname=postgres user=regress_regular", + "regular connections limit", + expected_stderr => + qr/FATAL: remaining connection slots are reserved for roles with privileges of the "pg_use_reserved_connections" role/ +); + +push(@sessions, background_psql_as_user('regress_reserved')); +push(@sessions, background_psql_as_user('regress_reserved')); +connect_fails_wait( + $node, + "dbname=postgres user=regress_reserved", + "reserved_connections limit", + expected_stderr => + qr/FATAL: remaining connection slots are reserved for roles with the SUPERUSER attribute/ +); + +push(@sessions, background_psql_as_user('regress_superuser')); +connect_fails_wait( + $node, + "dbname=postgres user=regress_superuser", + "superuser_reserved_connections limit", + expected_stderr => qr/FATAL: sorry, too many clients already/); + +# We can still open TCP (or Unix domain socket) connections, but +# beyond a certain number (roughly 2x max_connections), they will be +# "dead-end backends". +SKIP: +{ + skip "this test requires working raw_connect()" + unless $node->raw_connect_works(); + + for (my $i = 0; $i <= 20; $i++) + { + my $sock = $node->raw_connect(); + + # On a busy system, the server might reject connections if + # postmaster cannot accept() them fast enough. The exact limit + # and behavior depends on the platform. To make this reliable, + # we attempt SSL negotiation on each connection before opening + # next one. The server will reject the SSL negotiations, but + # when it does so, we know that the backend has been launched + # and we should be able to open another connection. + + # SSLRequest packet consists of packet length followed by + # NEGOTIATE_SSL_CODE. + my $negotiate_ssl_code = pack("Nnn", 8, 1234, 5679); + my $sent = $sock->send($negotiate_ssl_code); + + # Read reply. We expect the server to reject it with 'N' + my $reply = ""; + $sock->recv($reply, 1); + is($reply, "N", "dead-end connection $i"); + + push(@raw_connections, $sock); + } +} + +# TODO: test that query cancellation is still possible. A dead-end +# backend can process a query cancellation packet. + +# Clean up +foreach my $session (@sessions) +{ + $session->quit; +} +foreach my $socket (@raw_connections) +{ + $socket->close(); +} + +done_testing(); diff --git a/src/test/postmaster/t/003_start_stop.pl b/src/test/postmaster/t/003_start_stop.pl new file mode 100644 index 0000000000000..58e7ba6cc425e --- /dev/null +++ b/src/test/postmaster/t/003_start_stop.pl @@ -0,0 +1,103 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Test postmaster start and stop state machine. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# +# Test that dead-end backends don't prevent the server from shutting +# down. +# +# Dead-end backends can linger until they reach +# authentication_timeout. We use a long authentication_timeout and a +# much shorter timeout for the "pg_ctl stop" operation, to test that +# if dead-end backends are killed at fast shut down. If they're not, +# "pg_ctl stop" will error out before the authentication timeout kicks +# in and cleans up the dead-end backends. +my $authentication_timeout = $PostgreSQL::Test::Utils::timeout_default; + +# Don't fail due to hitting the max value allowed for authentication_timeout. +$authentication_timeout = 600 unless $authentication_timeout < 600; + +my $stop_timeout = $authentication_timeout / 2; + +# Initialize the server with low connection limits, to test dead-end backends +my $node = PostgreSQL::Test::Cluster->new('main'); +$node->init; +$node->append_conf('postgresql.conf', "max_connections = 5"); +$node->append_conf('postgresql.conf', "max_wal_senders = 0"); +$node->append_conf('postgresql.conf', "autovacuum_max_workers = 1"); +$node->append_conf('postgresql.conf', "max_worker_processes = 1"); +$node->append_conf('postgresql.conf', + "log_connections = 'receipt,authentication,authorization'"); +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); +$node->append_conf('postgresql.conf', + "authentication_timeout = '$authentication_timeout s'"); +$node->append_conf('postgresql.conf', 'trace_connection_negotiation=on'); +$node->start; + +if (!$node->raw_connect_works()) +{ + plan skip_all => "this test requires working raw_connect()"; +} + +my @raw_connections = (); + +# Open a lot of TCP (or Unix domain socket) connections to use up all +# the connection slots. Beyond a certain number (roughly 2x +# max_connections), they will be "dead-end backends". +for (my $i = 0; $i <= 20; $i++) +{ + my $sock = $node->raw_connect(); + + # On a busy system, the server might reject connections if + # postmaster cannot accept() them fast enough. The exact limit + # and behavior depends on the platform. To make this reliable, + # we attempt SSL negotiation on each connection before opening + # next one. The server will reject the SSL negotiations, but + # when it does so, we know that the backend has been launched + # and we should be able to open another connection. + + # SSLRequest packet consists of packet length followed by + # NEGOTIATE_SSL_CODE. + my $negotiate_ssl_code = pack("Nnn", 8, 1234, 5679); + my $sent = $sock->send($negotiate_ssl_code); + + # Read reply. We expect the server to reject it with 'N' + my $reply = ""; + $sock->recv($reply, 1); + is($reply, "N", "dead-end connection $i"); + + push(@raw_connections, $sock); +} + +# When all the connection slots are in use, new connections will fail +# before even looking up the user. Hence you now get "sorry, too many +# clients already" instead of "role does not exist" error. Test that +# to ensure that we have used up all the slots. +$node->connect_fails("dbname=postgres user=invalid_user", + "connect ", + expected_stderr => qr/FATAL: sorry, too many clients already/); + +# Open one more connection, to really ensure that we have at least one +# dead-end backend. +my $sock = $node->raw_connect(); + +# Test that the dead-end backends don't prevent the server from stopping. +$node->stop('fast', timeout => $stop_timeout); + +$node->start(); +$node->connect_ok("dbname=postgres", "works after restart"); + +# Clean up +foreach my $socket (@raw_connections) +{ + $socket->close(); +} + +done_testing(); diff --git a/src/test/recovery/Makefile b/src/test/recovery/Makefile index f57baba5e89ab..f6e4bc8d1a7cd 100644 --- a/src/test/recovery/Makefile +++ b/src/test/recovery/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/recovery # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/recovery/Makefile @@ -18,7 +18,7 @@ subdir = src/test/recovery top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -export enable_injection_points enable_injection_points +export enable_injection_points # required for 017_shm.pl and 027_stream_regress.pl REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX) diff --git a/src/test/recovery/meson.build b/src/test/recovery/meson.build index b1eb77b1ec107..92429d2840257 100644 --- a/src/test/recovery/meson.build +++ b/src/test/recovery/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'recovery', @@ -51,6 +51,11 @@ tests += { 't/040_standby_failover_slots_sync.pl', 't/041_checkpoint_at_promote.pl', 't/042_low_level_backup.pl', + 't/043_no_contrecord_switch.pl', + 't/044_invalidate_inactive_slots.pl', + 't/045_archive_restartpoint.pl', + 't/046_checkpoint_logical_slot.pl', + 't/047_checkpoint_physical_slot.pl' ], }, } diff --git a/src/test/recovery/t/001_stream_rep.pl b/src/test/recovery/t/001_stream_rep.pl index f3ea45ac4a289..2cbcc509d7665 100644 --- a/src/test/recovery/t/001_stream_rep.pl +++ b/src/test/recovery/t/001_stream_rep.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Minimal test testing streaming replication use strict; @@ -14,7 +14,7 @@ # and it needs proper authentication configuration. $node_primary->init( allows_streaming => 1, - auth_extra => [ '--create-role', 'repl_role' ]); + auth_extra => [ '--create-role' => 'repl_role' ]); $node_primary->start; my $backup_name = 'my_backup'; @@ -42,6 +42,9 @@ has_streaming => 1); $node_standby_2->start; +# Reset IO statistics, for the WAL sender check with pg_stat_io. +$node_primary->safe_psql('postgres', "SELECT pg_stat_reset_shared('io')"); + # Create some content on primary and check its presence in standby nodes $node_primary->safe_psql('postgres', "CREATE TABLE tab_int AS SELECT generate_series(1,1002) AS a"); @@ -146,9 +149,13 @@ sub test_target_session_attrs # we connected to. Note we must pass the SQL command via the command # line not stdin, else Perl may spit up trying to write to stdin of # an already-failed psql process. - my ($ret, $stdout, $stderr) = - $node1->psql('postgres', undef, - extra_params => [ '-d', $connstr, '-c', 'SHOW port;' ]); + my ($ret, $stdout, $stderr) = $node1->psql( + 'postgres', + undef, + extra_params => [ + '--dbname' => $connstr, + '--command' => 'SHOW port;', + ]); if ($status == 0) { is( $status == $ret && $stdout eq $target_port, @@ -257,26 +264,26 @@ sub test_target_session_attrs my ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW ALL;', on_error_die => 1, - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ok($ret == 0, "SHOW ALL with replication role and physical replication"); ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW ALL;', on_error_die => 1, - extra_params => [ '-d', $connstr_db ]); + extra_params => [ '--dbname' => $connstr_db ]); ok($ret == 0, "SHOW ALL with replication role and logical replication"); # Test SHOW with a user-settable parameter ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW work_mem;', on_error_die => 1, - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ok( $ret == 0, "SHOW with user-settable parameter, replication role and physical replication" ); ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW work_mem;', on_error_die => 1, - extra_params => [ '-d', $connstr_db ]); + extra_params => [ '--dbname' => $connstr_db ]); ok( $ret == 0, "SHOW with user-settable parameter, replication role and logical replication" ); @@ -285,14 +292,14 @@ sub test_target_session_attrs ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW primary_conninfo;', on_error_die => 1, - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ok( $ret == 0, "SHOW with superuser-settable parameter, replication role and physical replication" ); ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'SHOW primary_conninfo;', on_error_die => 1, - extra_params => [ '-d', $connstr_db ]); + extra_params => [ '--dbname' => $connstr_db ]); ok( $ret == 0, "SHOW with superuser-settable parameter, replication role and logical replication" ); @@ -304,7 +311,7 @@ sub test_target_session_attrs ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', 'READ_REPLICATION_SLOT non_existent_slot;', - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ok($ret == 0, "READ_REPLICATION_SLOT exit code 0 on success"); like($stdout, qr/^\|\|$/, "READ_REPLICATION_SLOT returns NULL values if slot does not exist"); @@ -312,12 +319,12 @@ sub test_target_session_attrs $node_primary->psql( 'postgres', "CREATE_REPLICATION_SLOT $slotname PHYSICAL RESERVE_WAL;", - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ($ret, $stdout, $stderr) = $node_primary->psql( 'postgres', "READ_REPLICATION_SLOT $slotname;", - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); ok($ret == 0, "READ_REPLICATION_SLOT success with existing slot"); like($stdout, qr/^physical\|[^|]*\|1$/, "READ_REPLICATION_SLOT returns tuple with slot information"); @@ -325,10 +332,23 @@ sub test_target_session_attrs $node_primary->psql( 'postgres', "DROP_REPLICATION_SLOT $slotname;", - extra_params => [ '-d', $connstr_rep ]); + extra_params => [ '--dbname' => $connstr_rep ]); note "switching to physical replication slot"; +# Wait for the physical WAL sender to update its IO statistics. This is +# done before the next restart, which would force a flush of its stats, and +# far enough from the reset done above to not impact the run time. +$node_primary->poll_query_until( + 'postgres', + qq[SELECT sum(reads) > 0 + FROM pg_catalog.pg_stat_io + WHERE backend_type = 'walsender' + AND object = 'wal'] + ) + or die + "Timed out while waiting for the walsender to update its IO statistics"; + # Switch to using a physical replication slot. We can do this without a new # backup since physical slots can go backwards if needed. Do so on both # standbys. Since we're going to be testing things that affect the slot state, @@ -506,6 +526,13 @@ sub replay_check $node_standby_2->enable_streaming($node_primary); $node_standby_2->reload; +# The WAL receiver should have generated some IO statistics. +my $stats_reads = $node_standby_1->safe_psql( + 'postgres', + qq{SELECT sum(writes) > 0 FROM pg_stat_io + WHERE backend_type = 'walreceiver' AND object = 'wal'}); +is($stats_reads, 't', "WAL receiver generates statistics for WAL writes"); + # be sure do not streaming from cascade $node_standby_1->stop; @@ -566,8 +593,11 @@ sub replay_check # a replication command and a SQL command. $node_primary->command_fails_like( [ - 'psql', '-X', '-c', "SELECT pg_backup_start('backup', true)", - '-c', 'BASE_BACKUP', '-d', $connstr + 'psql', + '--no-psqlrc', + '--command' => "SELECT pg_backup_start('backup', true)", + '--command' => 'BASE_BACKUP', + '--dbname' => $connstr ], qr/a backup is already in progress in this session/, 'BASE_BACKUP cannot run in session already running backup'); @@ -584,16 +614,14 @@ sub replay_check my ($sigchld_bb_stdin, $sigchld_bb_stdout, $sigchld_bb_stderr) = ('', '', ''); my $sigchld_bb = IPC::Run::start( [ - 'psql', '-X', '-c', "BASE_BACKUP (CHECKPOINT 'fast', MAX_RATE 32);", - '-c', 'SELECT pg_backup_stop()', - '-d', $connstr + 'psql', '--no-psqlrc', + '--command' => "BASE_BACKUP (CHECKPOINT 'fast', MAX_RATE 32);", + '--command' => 'SELECT pg_backup_stop()', + '--dbname' => $connstr ], - '<', - \$sigchld_bb_stdin, - '>', - \$sigchld_bb_stdout, - '2>', - \$sigchld_bb_stderr, + '<' => \$sigchld_bb_stdin, + '>' => \$sigchld_bb_stdout, + '2>' => \$sigchld_bb_stderr, $sigchld_bb_timeout); # The cancellation is issued once the database files are streamed and diff --git a/src/test/recovery/t/002_archiving.pl b/src/test/recovery/t/002_archiving.pl index bc447330e155a..3acdb9ff1ebe7 100644 --- a/src/test/recovery/t/002_archiving.pl +++ b/src/test/recovery/t/002_archiving.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # test for archiving with hot standby use strict; diff --git a/src/test/recovery/t/003_recovery_targets.pl b/src/test/recovery/t/003_recovery_targets.pl index 58241a68f0afd..0ae2e98272709 100644 --- a/src/test/recovery/t/003_recovery_targets.pl +++ b/src/test/recovery/t/003_recovery_targets.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for recovery targets: name, timestamp, XID use strict; @@ -57,7 +57,7 @@ sub test_recovery_standby # Bump the transaction ID epoch. This is useful to stress the portability # of recovery_target_xid parsing. -system_or_bail('pg_resetwal', '--epoch', '1', $node_primary->data_dir); +system_or_bail('pg_resetwal', '--epoch' => '1', $node_primary->data_dir); # Start it $node_primary->start; @@ -147,8 +147,10 @@ sub test_recovery_standby my $res = run_log( [ - 'pg_ctl', '-D', $node_standby->data_dir, '-l', - $node_standby->logfile, 'start' + 'pg_ctl', + '--pgdata' => $node_standby->data_dir, + '--log' => $node_standby->logfile, + 'start', ]); ok(!$res, 'invalid recovery startup fails'); @@ -168,8 +170,10 @@ sub test_recovery_standby run_log( [ - 'pg_ctl', '-D', $node_standby->data_dir, '-l', - $node_standby->logfile, 'start' + 'pg_ctl', + '--pgdata' => $node_standby->data_dir, + '--log' => $node_standby->logfile, + 'start', ]); # wait for postgres to terminate diff --git a/src/test/recovery/t/004_timeline_switch.pl b/src/test/recovery/t/004_timeline_switch.pl index 684838cbab7ce..9c8334cf278f8 100644 --- a/src/test/recovery/t/004_timeline_switch.pl +++ b/src/test/recovery/t/004_timeline_switch.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for timeline switch use strict; diff --git a/src/test/recovery/t/005_replay_delay.pl b/src/test/recovery/t/005_replay_delay.pl index fc0e165d850cb..be05fcea8a792 100644 --- a/src/test/recovery/t/005_replay_delay.pl +++ b/src/test/recovery/t/005_replay_delay.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Checks for recovery_min_apply_delay and recovery pause use strict; diff --git a/src/test/recovery/t/006_logical_decoding.pl b/src/test/recovery/t/006_logical_decoding.pl index b95d95c06f942..2137c4e5e305f 100644 --- a/src/test/recovery/t/006_logical_decoding.pl +++ b/src/test/recovery/t/006_logical_decoding.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Testing of logical decoding using SQL interface and/or pg_recvlogical # @@ -149,8 +149,11 @@ my $pg_recvlogical = IPC::Run::start( [ - 'pg_recvlogical', '-d', $node_primary->connstr('otherdb'), - '-S', 'otherdb_slot', '-f', '-', '--start' + 'pg_recvlogical', + '--dbname' => $node_primary->connstr('otherdb'), + '--slot' => 'otherdb_slot', + '--file' => '-', + '--start' ]); $node_primary->poll_query_until('otherdb', "SELECT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name = 'otherdb_slot' AND active_pid IS NOT NULL)" @@ -158,8 +161,8 @@ is($node_primary->psql('postgres', 'DROP DATABASE otherdb'), 3, 'dropping a DB with active logical slots fails'); $pg_recvlogical->kill_kill; - is($node_primary->slot('otherdb_slot')->{'slot_name'}, - undef, 'logical slot still exists'); + is($node_primary->slot('otherdb_slot')->{'plugin'}, + 'test_decoding', 'logical slot still exists'); } $node_primary->poll_query_until('otherdb', @@ -168,8 +171,8 @@ is($node_primary->psql('postgres', 'DROP DATABASE otherdb'), 0, 'dropping a DB with inactive logical slots succeeds'); -is($node_primary->slot('otherdb_slot')->{'slot_name'}, - undef, 'logical slot was actually dropped with DB'); +is($node_primary->slot('otherdb_slot')->{'plugin'}, + '', 'logical slot was actually dropped with DB'); # Test logical slot advancing and its durability. # Passing failover=true (last arg) should not have any impact on advancing. diff --git a/src/test/recovery/t/007_sync_rep.pl b/src/test/recovery/t/007_sync_rep.pl index 4bc96a3ac9ff3..602652a76386d 100644 --- a/src/test/recovery/t/007_sync_rep.pl +++ b/src/test/recovery/t/007_sync_rep.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Minimal test testing synchronous replication sync_state transition use strict; diff --git a/src/test/recovery/t/008_fsm_truncation.pl b/src/test/recovery/t/008_fsm_truncation.pl index 4412fe2896299..37e6c55f3a165 100644 --- a/src/test/recovery/t/008_fsm_truncation.pl +++ b/src/test/recovery/t/008_fsm_truncation.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test FSM-driven INSERT just after truncation clears FSM slots indicating # free space in removed blocks. diff --git a/src/test/recovery/t/009_twophase.pl b/src/test/recovery/t/009_twophase.pl index 12c2f0e40d145..1a662ebe499dc 100644 --- a/src/test/recovery/t/009_twophase.pl +++ b/src/test/recovery/t/009_twophase.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests dedicated to two-phase commit in recovery use strict; @@ -319,6 +319,7 @@ sub configure_and_reload $cur_primary->psql( 'postgres', " + SET synchronous_commit='remote_apply'; -- To ensure the standby is caught up CREATE TABLE t_009_tbl_standby_mvcc (id int, msg text); BEGIN; INSERT INTO t_009_tbl_standby_mvcc VALUES (1, 'issued to ${cur_primary_name}'); diff --git a/src/test/recovery/t/010_logical_decoding_timelines.pl b/src/test/recovery/t/010_logical_decoding_timelines.pl index afcd5241aa665..351a9ef7bddd4 100644 --- a/src/test/recovery/t/010_logical_decoding_timelines.pl +++ b/src/test/recovery/t/010_logical_decoding_timelines.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Demonstrate that logical can follow timeline switches. # @@ -94,8 +94,8 @@ 'postgres', q[SELECT 1 FROM pg_database WHERE datname = 'dropme']), '', 'dropped DB dropme on standby'); -is($node_primary->slot('dropme_slot')->{'slot_name'}, - undef, 'logical slot was actually dropped on standby'); +is($node_replica->slot('dropme_slot')->{'plugin'}, + '', 'logical slot was actually dropped on standby'); # Back to testing failover... $node_primary->safe_psql('postgres', diff --git a/src/test/recovery/t/012_subtransactions.pl b/src/test/recovery/t/012_subtransactions.pl index 2f74bfc9a5af5..25df73463b795 100644 --- a/src/test/recovery/t/012_subtransactions.pl +++ b/src/test/recovery/t/012_subtransactions.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests dedicated to subtransactions in recovery use strict; diff --git a/src/test/recovery/t/013_crash_restart.pl b/src/test/recovery/t/013_crash_restart.pl index d5d24e31d90ef..debfa635c36fe 100644 --- a/src/test/recovery/t/013_crash_restart.pl +++ b/src/test/recovery/t/013_crash_restart.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Tests restarts of postgres due to crashes of a subprocess. @@ -27,37 +27,34 @@ $node->safe_psql( 'postgres', q[ALTER SYSTEM SET restart_after_crash = 1; - ALTER SYSTEM SET log_connections = 1; + ALTER SYSTEM SET log_connections = receipt; SELECT pg_reload_conf();]); # Run psql, keeping session alive, so we have an alive backend to kill. my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); my $killme = IPC::Run::start( [ - 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', - $node->connstr('postgres') + 'psql', '--no-psqlrc', '--quiet', '--no-align', '--tuples-only', + '--set' => 'ON_ERROR_STOP=1', + '--file' => '-', + '--dbname' => $node->connstr('postgres') ], - '<', - \$killme_stdin, - '>', - \$killme_stdout, - '2>', - \$killme_stderr, + '<' => \$killme_stdin, + '>' => \$killme_stdout, + '2>' => \$killme_stderr, $psql_timeout); # Need a second psql to check if crash-restart happened. my ($monitor_stdin, $monitor_stdout, $monitor_stderr) = ('', '', ''); my $monitor = IPC::Run::start( [ - 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', - $node->connstr('postgres') + 'psql', '--no-psqlrc', '--quiet', '--no-align', '--tuples-only', + '--set' => 'ON_ERROR_STOP=1', + '--file', '-', '--dbname' => $node->connstr('postgres') ], - '<', - \$monitor_stdin, - '>', - \$monitor_stdout, - '2>', - \$monitor_stderr, + '<' => \$monitor_stdin, + '>' => \$monitor_stdout, + '2>' => \$monitor_stderr, $psql_timeout); #create table, insert row that should survive diff --git a/src/test/recovery/t/014_unlogged_reinit.pl b/src/test/recovery/t/014_unlogged_reinit.pl index a37fc9249b5dd..c19242146f229 100644 --- a/src/test/recovery/t/014_unlogged_reinit.pl +++ b/src/test/recovery/t/014_unlogged_reinit.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests that unlogged tables are properly reinitialized after a crash. # diff --git a/src/test/recovery/t/015_promotion_pages.pl b/src/test/recovery/t/015_promotion_pages.pl index 7972fc7b77b00..ae0849256f04e 100644 --- a/src/test/recovery/t/015_promotion_pages.pl +++ b/src/test/recovery/t/015_promotion_pages.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for promotion handling with WAL records generated post-promotion # before the first checkpoint is generated. This test case checks for diff --git a/src/test/recovery/t/016_min_consistency.pl b/src/test/recovery/t/016_min_consistency.pl index 23d161aebc771..9a3b4866fce4a 100644 --- a/src/test/recovery/t/016_min_consistency.pl +++ b/src/test/recovery/t/016_min_consistency.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for checking consistency of on-disk pages for a cluster with # the minimum recovery LSN, ensuring that the updates happen across diff --git a/src/test/recovery/t/017_shm.pl b/src/test/recovery/t/017_shm.pl index 50ee5cdee21ae..c73aa3f0c2c4a 100644 --- a/src/test/recovery/t/017_shm.pl +++ b/src/test/recovery/t/017_shm.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Tests of pg_shmem.h functions @@ -29,11 +29,11 @@ # Log "ipcs" diffs on a best-effort basis, swallowing any error. my $ipcs_before = "$tempdir/ipcs_before"; -eval { run_log [ 'ipcs', '-am' ], '>', $ipcs_before; }; +eval { run_log [ 'ipcs', '-am' ], '>' => $ipcs_before; }; sub log_ipcs { - eval { run_log [ 'ipcs', '-am' ], '|', [ 'diff', $ipcs_before, '-' ] }; + eval { run_log [ 'ipcs', '-am' ], '|' => [ 'diff', $ipcs_before, '-' ] }; return; } @@ -122,15 +122,13 @@ sub log_ipcs my ($stdout, $stderr); my $slow_client = IPC::Run::start( [ - 'psql', '-X', '-qAt', '-d', $gnat->connstr('postgres'), - '-c', $slow_query + 'psql', '--no-psqlrc', '--quiet', '--no-align', '--tuples-only', + '--dbname' => $gnat->connstr('postgres'), + '--command' => $slow_query ], - '<', - \undef, - '>', - \$stdout, - '2>', - \$stderr, + '<' => \undef, + '>' => \$stdout, + '2>' => \$stderr, IPC::Run::timeout(5 * $PostgreSQL::Test::Utils::timeout_default)); ok( $gnat->poll_query_until( 'postgres', @@ -160,13 +158,13 @@ sub log_ipcs like(slurp_file($gnat->logfile), $pre_existing_msg, 'detected live backend via shared memory'); # Reject single-user startup. -my $single_stderr; -ok( !run_log( - [ 'postgres', '--single', '-D', $gnat->data_dir, 'template1' ], - '<', \undef, '2>', \$single_stderr), - 'live query blocks --single'); -print STDERR $single_stderr; -like($single_stderr, $pre_existing_msg, +command_fails_like( + [ + 'postgres', '--single', + '-D' => $gnat->data_dir, + 'template1' + ], + $pre_existing_msg, 'single-user mode detected live backend via shared memory'); log_ipcs(); diff --git a/src/test/recovery/t/018_wal_optimize.pl b/src/test/recovery/t/018_wal_optimize.pl index 3fb31e643b69d..4b3667b98a38b 100644 --- a/src/test/recovery/t/018_wal_optimize.pl +++ b/src/test/recovery/t/018_wal_optimize.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test WAL replay when some operation has skipped WAL. # diff --git a/src/test/recovery/t/019_replslot_limit.pl b/src/test/recovery/t/019_replslot_limit.pl index efb4ba3af1e6c..6468784b83d6f 100644 --- a/src/test/recovery/t/019_replslot_limit.pl +++ b/src/test/recovery/t/019_replslot_limit.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for replication slot limit # Ensure that max_slot_wal_keep_size limits the number of WAL files to @@ -234,7 +234,7 @@ for (my $i = 0; $i < 10 * $PostgreSQL::Test::Utils::timeout_default; $i++) { if ($node_standby->log_contains( - "requested WAL segment [0-9A-F]+ has already been removed", + "This replication slot has been invalidated due to \"wal_removed\".", $logstart)) { $failed = 1; diff --git a/src/test/recovery/t/020_archive_status.pl b/src/test/recovery/t/020_archive_status.pl index 9cb178950f82f..5d1fd19124324 100644 --- a/src/test/recovery/t/020_archive_status.pl +++ b/src/test/recovery/t/020_archive_status.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # Tests related to WAL archiving and recovery. diff --git a/src/test/recovery/t/021_row_visibility.pl b/src/test/recovery/t/021_row_visibility.pl index d0461376014fe..42740745bfd9f 100644 --- a/src/test/recovery/t/021_row_visibility.pl +++ b/src/test/recovery/t/021_row_visibility.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Checks that snapshots on standbys behave in a minimally reasonable # way. @@ -38,24 +38,26 @@ # to check uncommitted changes being replicated and such. my %psql_primary = (stdin => '', stdout => '', stderr => ''); $psql_primary{run} = IPC::Run::start( - [ 'psql', '-XA', '-f', '-', '-d', $node_primary->connstr('postgres') ], - '<', - \$psql_primary{stdin}, - '>', - \$psql_primary{stdout}, - '2>', - \$psql_primary{stderr}, + [ + 'psql', '--no-psqlrc', '--no-align', + '--file' => '-', + '--dbname' => $node_primary->connstr('postgres'), + ], + '<' => \$psql_primary{stdin}, + '>' => \$psql_primary{stdout}, + '2>' => \$psql_primary{stderr}, $psql_timeout); my %psql_standby = ('stdin' => '', 'stdout' => '', 'stderr' => ''); $psql_standby{run} = IPC::Run::start( - [ 'psql', '-XA', '-f', '-', '-d', $node_standby->connstr('postgres') ], - '<', - \$psql_standby{stdin}, - '>', - \$psql_standby{stdout}, - '2>', - \$psql_standby{stderr}, + [ + 'psql', '--no-psqlrc', '--no-align', + '--file' => '-', + '--dbname' => $node_standby->connstr('postgres'), + ], + '<' => \$psql_standby{stdin}, + '>' => \$psql_standby{stdout}, + '2>' => \$psql_standby{stderr}, $psql_timeout); # diff --git a/src/test/recovery/t/022_crash_temp_files.pl b/src/test/recovery/t/022_crash_temp_files.pl index 769b6a6627d06..0b68860bd3e94 100644 --- a/src/test/recovery/t/022_crash_temp_files.pl +++ b/src/test/recovery/t/022_crash_temp_files.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test remove of temporary files after a crash. use strict; @@ -26,7 +26,7 @@ $node->safe_psql( 'postgres', q[ALTER SYSTEM SET remove_temp_files_after_crash = on; - ALTER SYSTEM SET log_connections = 1; + ALTER SYSTEM SET log_connections = receipt; ALTER SYSTEM SET work_mem = '64kB'; ALTER SYSTEM SET restart_after_crash = on; SELECT pg_reload_conf();]); @@ -38,15 +38,14 @@ my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); my $killme = IPC::Run::start( [ - 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', - $node->connstr('postgres') + 'psql', '--no-psqlrc', '--quiet', '--no-align', '--tuples-only', + '--set' => 'ON_ERROR_STOP=1', + '--file' => '-', + '--dbname' => $node->connstr('postgres') ], - '<', - \$killme_stdin, - '>', - \$killme_stdout, - '2>', - \$killme_stderr, + '<' => \$killme_stdin, + '>' => \$killme_stdout, + '2>' => \$killme_stderr, $psql_timeout); # Get backend pid @@ -66,15 +65,14 @@ my ($killme_stdin2, $killme_stdout2, $killme_stderr2) = ('', '', ''); my $killme2 = IPC::Run::start( [ - 'psql', '-X', '-qAt', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', - $node->connstr('postgres') + 'psql', '--no-psqlrc', '--quiet', '--no-align', '--tuples-only', + '--set' => 'ON_ERROR_STOP=1', + '--file' => '-', + '--dbname' => $node->connstr('postgres') ], - '<', - \$killme_stdin2, - '>', - \$killme_stdout2, - '2>', - \$killme_stderr2, + '<' => \$killme_stdin2, + '>' => \$killme_stdout2, + '2>' => \$killme_stderr2, $psql_timeout); # Insert one tuple and leave the transaction open diff --git a/src/test/recovery/t/023_pitr_prepared_xact.pl b/src/test/recovery/t/023_pitr_prepared_xact.pl index da6804f9a4940..592b7bc013b64 100644 --- a/src/test/recovery/t/023_pitr_prepared_xact.pl +++ b/src/test/recovery/t/023_pitr_prepared_xact.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for point-in-time recovery (PITR) with prepared transactions use strict; diff --git a/src/test/recovery/t/024_archive_recovery.pl b/src/test/recovery/t/024_archive_recovery.pl index c6480bbdcd61b..b4527ec084325 100644 --- a/src/test/recovery/t/024_archive_recovery.pl +++ b/src/test/recovery/t/024_archive_recovery.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test for archive recovery of WAL generated with wal_level=minimal use strict; @@ -76,9 +76,10 @@ sub test_recovery_wal_level_minimal # that the server ends with an error during recovery. run_log( [ - 'pg_ctl', '-D', - $recovery_node->data_dir, '-l', - $recovery_node->logfile, 'start' + 'pg_ctl', + '--pgdata' => $recovery_node->data_dir, + '--log' => $recovery_node->logfile, + 'start', ]); # wait for postgres to terminate diff --git a/src/test/recovery/t/025_stuck_on_old_timeline.pl b/src/test/recovery/t/025_stuck_on_old_timeline.pl index 67085c4bac39f..f52ac9678e0e2 100644 --- a/src/test/recovery/t/025_stuck_on_old_timeline.pl +++ b/src/test/recovery/t/025_stuck_on_old_timeline.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Testing streaming replication where standby is promoted and a new cascading # standby (without WAL) is connected to the promoted standby. Both archiving diff --git a/src/test/recovery/t/026_overwrite_contrecord.pl b/src/test/recovery/t/026_overwrite_contrecord.pl index f3e27c19af53f..f408d4f69b6ef 100644 --- a/src/test/recovery/t/026_overwrite_contrecord.pl +++ b/src/test/recovery/t/026_overwrite_contrecord.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for already-propagated WAL segments ending in incomplete WAL records. diff --git a/src/test/recovery/t/027_stream_regress.pl b/src/test/recovery/t/027_stream_regress.pl index d1ae32d97d603..83def062d11e1 100644 --- a/src/test/recovery/t/027_stream_regress.pl +++ b/src/test/recovery/t/027_stream_regress.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Run the standard regression tests with streaming replication use strict; @@ -105,19 +105,24 @@ # Perform a logical dump of primary and standby, and check that they match command_ok( [ - 'pg_dumpall', '-f', $outputdir . '/primary.dump', - '--no-sync', '-p', $node_primary->port, - '--no-unlogged-table-data' # if unlogged, standby has schema only + 'pg_dumpall', + '--file' => $outputdir . '/primary.dump', + '--no-sync', '--no-statistics', + '--port' => $node_primary->port, + '--no-unlogged-table-data', # if unlogged, standby has schema only ], 'dump primary server'); command_ok( [ - 'pg_dumpall', '-f', $outputdir . '/standby.dump', - '--no-sync', '-p', $node_standby_1->port + 'pg_dumpall', + '--file' => $outputdir . '/standby.dump', + '--no-sync', '--no-statistics', + '--port' => $node_standby_1->port, ], 'dump standby server'); -command_ok( - [ 'diff', $outputdir . '/primary.dump', $outputdir . '/standby.dump' ], +compare_files( + $outputdir . '/primary.dump', + $outputdir . '/standby.dump', 'compare primary and standby dumps'); # Likewise for the catalogs of the regression database, after disabling @@ -128,30 +133,27 @@ command_ok( [ 'pg_dump', - ('--schema', 'pg_catalog'), - ('-f', $outputdir . '/catalogs_primary.dump'), + '--schema' => 'pg_catalog', + '--file' => $outputdir . '/catalogs_primary.dump', '--no-sync', - ('-p', $node_primary->port), + '--port', $node_primary->port, '--no-unlogged-table-data', - 'regression' + 'regression', ], 'dump catalogs of primary server'); command_ok( [ 'pg_dump', - ('--schema', 'pg_catalog'), - ('-f', $outputdir . '/catalogs_standby.dump'), + '--schema' => 'pg_catalog', + '--file' => $outputdir . '/catalogs_standby.dump', '--no-sync', - ('-p', $node_standby_1->port), - 'regression' + '--port' => $node_standby_1->port, + 'regression', ], 'dump catalogs of standby server'); -command_ok( - [ - 'diff', - $outputdir . '/catalogs_primary.dump', - $outputdir . '/catalogs_standby.dump' - ], +compare_files( + $outputdir . '/catalogs_primary.dump', + $outputdir . '/catalogs_standby.dump', 'compare primary and standby catalog dumps'); # Check some data from pg_stat_statements. diff --git a/src/test/recovery/t/028_pitr_timelines.pl b/src/test/recovery/t/028_pitr_timelines.pl index 4b7d825b71386..184ce15c0b6f1 100644 --- a/src/test/recovery/t/028_pitr_timelines.pl +++ b/src/test/recovery/t/028_pitr_timelines.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Test recovering to a point-in-time using WAL archive, such that the # target point is physically in a WAL segment with a higher TLI than diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl index 93a7209f69aac..021e2bf361ff8 100644 --- a/src/test/recovery/t/029_stats_restart.pl +++ b/src/test/recovery/t/029_stats_restart.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests statistics handling around restarts, including handling of crashes and # invalid stats files, as well as restoring stats after "normal" restarts. @@ -18,6 +18,21 @@ my $connect_db = 'postgres'; my $db_under_test = 'test'; +my $sect = "startup"; + +# Check some WAL statistics after a fresh startup. The startup process +# should have done WAL reads, and initialization some WAL writes. +my $standalone_io_stats = io_stats('init', 'wal', 'standalone backend'); +my $startup_io_stats = io_stats('normal', 'wal', 'startup'); +cmp_ok( + '0', '<', + $standalone_io_stats->{writes}, + "$sect: increased standalone backend IO writes"); +cmp_ok( + '0', '<', + $startup_io_stats->{reads}, + "$sect: increased startup IO reads"); + # create test objects $node->safe_psql($connect_db, "CREATE DATABASE $db_under_test"); $node->safe_psql($db_under_test, @@ -39,7 +54,7 @@ trigger_funcrel_stat(); # verify stats objects exist -my $sect = "initial"; +$sect = "initial"; is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist"); is(have_stats('function', $dboid, $funcoid), 't', "$sect: function stats do exist"); @@ -292,10 +307,10 @@ sub trigger_funcrel_stat sub have_stats { - my ($kind, $dboid, $objoid) = @_; + my ($kind, $dboid, $objid) = @_; return $node->safe_psql($connect_db, - "SELECT pg_stat_have_stats('$kind', $dboid, $objoid)"); + "SELECT pg_stat_have_stats('$kind', $dboid, $objid)"); } sub overwrite_file @@ -342,3 +357,20 @@ sub wal_stats return \%results; } + +sub io_stats +{ + my ($context, $object, $backend_type) = @_; + my %results; + + $results{writes} = $node->safe_psql( + $connect_db, qq{SELECT writes FROM pg_stat_io + WHERE context = '$context' AND object = '$object' AND + backend_type = '$backend_type'}); + $results{reads} = $node->safe_psql( + $connect_db, qq{SELECT reads FROM pg_stat_io + WHERE context = '$context' AND object = '$object' AND + backend_type = '$backend_type'}); + + return \%results; +} diff --git a/src/test/recovery/t/030_stats_cleanup_replica.pl b/src/test/recovery/t/030_stats_cleanup_replica.pl index 74b516cc7cce6..20629e80c34e3 100644 --- a/src/test/recovery/t/030_stats_cleanup_replica.pl +++ b/src/test/recovery/t/030_stats_cleanup_replica.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests that standbys: # - drop stats for objects when the those records are replayed diff --git a/src/test/recovery/t/031_recovery_conflict.pl b/src/test/recovery/t/031_recovery_conflict.pl index d87efa823fd9e..028b0b5f0e15d 100644 --- a/src/test/recovery/t/031_recovery_conflict.pl +++ b/src/test/recovery/t/031_recovery_conflict.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test that connections to a hot standby are correctly canceled when a # recovery conflict is detected Also, test that statistics in diff --git a/src/test/recovery/t/032_relfilenode_reuse.pl b/src/test/recovery/t/032_relfilenode_reuse.pl index d473cd167c132..0c44883cc34b1 100644 --- a/src/test/recovery/t/032_relfilenode_reuse.pl +++ b/src/test/recovery/t/032_relfilenode_reuse.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -14,7 +14,7 @@ $node_primary->append_conf( 'postgresql.conf', q[ allow_in_place_tablespaces = true -log_connections=on +log_connections=receipt # to avoid "repairing" corruption full_page_writes=off log_min_messages=debug2 @@ -36,24 +36,26 @@ my %psql_primary = (stdin => '', stdout => '', stderr => ''); $psql_primary{run} = IPC::Run::start( - [ 'psql', '-XA', '-f', '-', '-d', $node_primary->connstr('postgres') ], - '<', - \$psql_primary{stdin}, - '>', - \$psql_primary{stdout}, - '2>', - \$psql_primary{stderr}, + [ + 'psql', '--no-psqlrc', '--no-align', + '--file' => '-', + '--dbname' => $node_primary->connstr('postgres') + ], + '<' => \$psql_primary{stdin}, + '>' => \$psql_primary{stdout}, + '2>' => \$psql_primary{stderr}, $psql_timeout); my %psql_standby = ('stdin' => '', 'stdout' => '', 'stderr' => ''); $psql_standby{run} = IPC::Run::start( - [ 'psql', '-XA', '-f', '-', '-d', $node_standby->connstr('postgres') ], - '<', - \$psql_standby{stdin}, - '>', - \$psql_standby{stdout}, - '2>', - \$psql_standby{stderr}, + [ + 'psql', '--no-psqlrc', '--no-align', + '--file' => '-', + '--dbname' => $node_standby->connstr('postgres') + ], + '<' => \$psql_standby{stdin}, + '>' => \$psql_standby{stdout}, + '2>' => \$psql_standby{stderr}, $psql_timeout); diff --git a/src/test/recovery/t/033_replay_tsp_drops.pl b/src/test/recovery/t/033_replay_tsp_drops.pl index d17551dcf2d5f..56c7d6b2137e4 100644 --- a/src/test/recovery/t/033_replay_tsp_drops.pl +++ b/src/test/recovery/t/033_replay_tsp_drops.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test replay of tablespace/database creation/drop diff --git a/src/test/recovery/t/034_create_database.pl b/src/test/recovery/t/034_create_database.pl index e1a24ad06cf0b..351d085e8ddf8 100644 --- a/src/test/recovery/t/034_create_database.pl +++ b/src/test/recovery/t/034_create_database.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Test WAL replay for CREATE DATABASE .. STRATEGY WAL_LOG. diff --git a/src/test/recovery/t/035_standby_logical_decoding.pl b/src/test/recovery/t/035_standby_logical_decoding.pl index 4185b803b2582..921813483e37c 100644 --- a/src/test/recovery/t/035_standby_logical_decoding.pl +++ b/src/test/recovery/t/035_standby_logical_decoding.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # logical decoding on standby : test logical decoding, # recovery conflict and standby promotion. @@ -10,6 +10,11 @@ use PostgreSQL::Test::Utils; use Test::More; +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + my ($stdout, $stderr, $cascading_stdout, $cascading_stderr, $handle); my $node_primary = PostgreSQL::Test::Cluster->new('primary'); @@ -75,18 +80,17 @@ sub make_slot_active my $active_slot = $slot_prefix . 'activeslot'; $slot_user_handle = IPC::Run::start( [ - 'pg_recvlogical', '-d', - $node->connstr('testdb'), '-S', - qq($active_slot), '-o', - 'include-xids=0', '-o', - 'skip-empty-xacts=1', '--no-loop', - '--start', '-f', - '-' + 'pg_recvlogical', + '--dbname' => $node->connstr('testdb'), + '--slot' => $active_slot, + '--option' => 'include-xids=0', + '--option' => 'skip-empty-xacts=1', + '--file' => '-', + '--no-loop', + '--start', ], - '>', - $to_stdout, - '2>', - $to_stderr, + '>' => $to_stdout, + '2>' => $to_stderr, IPC::Run::timeout($default_timeout)); if ($wait) @@ -242,16 +246,19 @@ sub check_for_invalidation # VACUUM command, $sql the sql to launch before triggering the vacuum and # $to_vac the relation to vacuum. # -# Note that pg_current_snapshot() is used to get the horizon. It does -# not generate a Transaction/COMMIT WAL record, decreasing the risk of -# seeing a xl_running_xacts that would advance an active replication slot's -# catalog_xmin. Advancing the active replication slot's catalog_xmin -# would break some tests that expect the active slot to conflict with -# the catalog xmin horizon. +# Note that the injection_point avoids seeing a xl_running_xacts that could +# advance an active replication slot's catalog_xmin. Advancing the active +# replication slot's catalog_xmin would break some tests that expect the +# active slot to conflict with the catalog xmin horizon. sub wait_until_vacuum_can_remove { my ($vac_option, $sql, $to_vac) = @_; + # Note that from this point the checkpointer and bgwriter will skip writing + # xl_running_xacts record. + $node_primary->safe_psql('testdb', + "SELECT injection_points_attach('skip-log-running-xacts', 'error');"); + # Get the current xid horizon, my $xid_horizon = $node_primary->safe_psql('testdb', qq[select pg_snapshot_xmin(pg_current_snapshot());]); @@ -269,6 +276,12 @@ sub wait_until_vacuum_can_remove $node_primary->safe_psql( 'testdb', qq[VACUUM $vac_option verbose $to_vac; INSERT INTO flush_wal DEFAULT VALUES;]); + + $node_primary->wait_for_replay_catchup($node_standby); + + # Resume generating the xl_running_xacts record + $node_primary->safe_psql('testdb', + "SELECT injection_points_detach('skip-log-running-xacts');"); } ######################## @@ -286,6 +299,14 @@ sub wait_until_vacuum_can_remove $node_primary->dump_info; $node_primary->start; +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node_primary->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + $node_primary->psql('postgres', q[CREATE DATABASE testdb]); $node_primary->safe_psql('testdb', @@ -333,15 +354,54 @@ sub wait_until_vacuum_can_remove 'subscriber_stdout' => '', 'subscriber_stderr' => ''); $psql_subscriber{run} = IPC::Run::start( - [ 'psql', '-XA', '-f', '-', '-d', $node_subscriber->connstr('postgres') ], - '<', - \$psql_subscriber{subscriber_stdin}, - '>', - \$psql_subscriber{subscriber_stdout}, - '2>', - \$psql_subscriber{subscriber_stderr}, + [ + 'psql', '--no-psqlrc', '--no-align', + '--file' => '-', + '--dbname' => $node_subscriber->connstr('postgres') + ], + '<' => \$psql_subscriber{subscriber_stdin}, + '>' => \$psql_subscriber{subscriber_stdout}, + '2>' => \$psql_subscriber{subscriber_stderr}, IPC::Run::timeout($default_timeout)); +################################################## +# Test that the standby requires hot_standby to be +# enabled for pre-existing logical slots. +################################################## + +# create the logical slots +$node_standby->create_logical_slot_on_standby($node_primary, 'restart_test'); +$node_standby->stop; +$node_standby->append_conf('postgresql.conf', qq[hot_standby = off]); + +# Use run_log instead of $node_standby->start because this test expects +# that the server ends with an error during startup. +run_log( + [ + 'pg_ctl', + '--pgdata' => $node_standby->data_dir, + '--log' => $node_standby->logfile, + 'start', + ]); + +# wait for postgres to terminate +foreach my $i (0 .. 10 * $PostgreSQL::Test::Utils::timeout_default) +{ + last if !-f $node_standby->data_dir . '/postmaster.pid'; + usleep(100_000); +} + +# Confirm that the server startup fails with an expected error +my $logfile = slurp_file($node_standby->logfile()); +ok( $logfile =~ + qr/FATAL: .* logical replication slot ".*" exists on the standby, but "hot_standby" = "off"/, + "the standby ends with an error during startup because hot_standby was disabled" +); +$node_standby->adjust_conf('postgresql.conf', 'hot_standby', 'on'); +$node_standby->start; +$node_standby->safe_psql('postgres', + qq[SELECT pg_drop_replication_slot('restart_test')]); + ################################################## # Test that logical decoding on the standby # behaves correctly. @@ -490,12 +550,16 @@ sub wait_until_vacuum_can_remove $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub"); $node_subscriber->stop; +# Create the injection_points extension +$node_primary->safe_psql('testdb', 'CREATE EXTENSION injection_points;'); + ################################################## # Recovery conflict: Invalidate conflicting slots, including in-use slots # Scenario 1: hot_standby_feedback off and vacuum FULL # # In passing, ensure that replication slot stats are not removed when the -# active slot is invalidated. +# active slot is invalidated, and check that an error occurs when +# attempting to alter the invalid slot. ################################################## # One way to produce recovery conflict is to create/drop a relation and @@ -518,14 +582,23 @@ sub wait_until_vacuum_can_remove 'full', 'CREATE TABLE conflict_test(x integer, y text); DROP TABLE conflict_test;', 'pg_class'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('vacuum_full_', 1, 'with vacuum FULL on pg_class'); # Verify reason for conflict is 'rows_removed' in pg_replication_slots check_slots_conflict_reason('vacuum_full_', 'rows_removed'); +# Attempting to alter an invalidated slot should result in an error +($result, $stdout, $stderr) = $node_standby->psql( + 'postgres', + qq[ALTER_REPLICATION_SLOT vacuum_full_inactiveslot (failover);], + replication => 'database'); +ok( $stderr =~ + /ERROR: can no longer access replication slot "vacuum_full_inactiveslot"/ + && $stderr =~ + /DETAIL: This replication slot has been invalidated due to "rows_removed"./, + "invalidated slot cannot be altered"); + # Ensure that replication slot stats are not removed after invalidation. is( $node_standby->safe_psql( 'testdb', @@ -539,8 +612,16 @@ sub wait_until_vacuum_can_remove # We are not able to read from the slot as it has been invalidated check_pg_recvlogical_stderr($handle, - "can no longer get changes from replication slot \"vacuum_full_activeslot\"" -); + "can no longer access replication slot \"vacuum_full_activeslot\""); + +# Attempt to copy an invalidated logical replication slot +($result, $stdout, $stderr) = $node_standby->psql( + 'postgres', + qq[select pg_copy_logical_replication_slot('vacuum_full_inactiveslot', 'vacuum_full_inactiveslot_copy');], + replication => 'database'); +ok( $stderr =~ + /ERROR: cannot copy invalidated replication slot "vacuum_full_inactiveslot"/, + "invalidated slot cannot be copied"); # Turn hot_standby_feedback back on change_hot_standby_feedback_and_wait_for_xmins(1, 1); @@ -607,8 +688,6 @@ sub wait_until_vacuum_can_remove '', 'CREATE TABLE conflict_test(x integer, y text); DROP TABLE conflict_test;', 'pg_class'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('row_removal_', $logstart, 'with vacuum on pg_class'); @@ -620,8 +699,7 @@ sub wait_until_vacuum_can_remove # We are not able to read from the slot as it has been invalidated check_pg_recvlogical_stderr($handle, - "can no longer get changes from replication slot \"row_removal_activeslot\"" -); + "can no longer access replication slot \"row_removal_activeslot\""); ################################################## # Recovery conflict: Same as Scenario 2 but on a shared catalog table @@ -642,8 +720,6 @@ sub wait_until_vacuum_can_remove '', 'CREATE ROLE create_trash; DROP ROLE create_trash;', 'pg_authid'); -$node_primary->wait_for_replay_catchup($node_standby); - # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('shared_row_removal_', $logstart, 'with vacuum on pg_authid'); @@ -656,7 +732,7 @@ sub wait_until_vacuum_can_remove # We are not able to read from the slot as it has been invalidated check_pg_recvlogical_stderr($handle, - "can no longer get changes from replication slot \"shared_row_removal_activeslot\"" + "can no longer access replication slot \"shared_row_removal_activeslot\"" ); ################################################## @@ -676,8 +752,6 @@ sub wait_until_vacuum_can_remove INSERT INTO conflict_test(x,y) SELECT s, s::text FROM generate_series(1,4) s; UPDATE conflict_test set x=1, y=1;', 'conflict_test'); -$node_primary->wait_for_replay_catchup($node_standby); - # message should not be issued ok( !$node_standby->log_contains( "invalidating obsolete slot \"no_conflict_inactiveslot\"", $logstart), @@ -725,6 +799,13 @@ sub wait_until_vacuum_can_remove reactive_slots_change_hfs_and_wait_for_xmins('no_conflict_', 'pruning_', 0, 0); +# Injection point avoids seeing a xl_running_xacts. This is required because if +# it is generated between the last two updates, then the catalog_xmin of the +# active slot could be updated, and hence, the conflict won't occur. See +# comments atop wait_until_vacuum_can_remove. +$node_primary->safe_psql('testdb', + "SELECT injection_points_attach('skip-log-running-xacts', 'error');"); + # This should trigger the conflict $node_primary->safe_psql('testdb', qq[CREATE TABLE prun(id integer, s char(2000)) WITH (fillfactor = 75, user_catalog_table = true);] @@ -737,6 +818,10 @@ sub wait_until_vacuum_can_remove $node_primary->wait_for_replay_catchup($node_standby); +# Resume generating the xl_running_xacts record +$node_primary->safe_psql('testdb', + "SELECT injection_points_detach('skip-log-running-xacts');"); + # Check invalidation in the logfile and in pg_stat_database_conflicts check_for_invalidation('pruning_', $logstart, 'with on-access pruning'); @@ -747,7 +832,7 @@ sub wait_until_vacuum_can_remove # We are not able to read from the slot as it has been invalidated check_pg_recvlogical_stderr($handle, - "can no longer get changes from replication slot \"pruning_activeslot\""); + "can no longer access replication slot \"pruning_activeslot\""); # Turn hot_standby_feedback back on change_hot_standby_feedback_and_wait_for_xmins(1, 1); @@ -806,11 +891,10 @@ sub wait_until_vacuum_can_remove make_slot_active($node_standby, 'wal_level_', 0, \$stdout, \$stderr); # as the slot has been invalidated we should not be able to read check_pg_recvlogical_stderr($handle, - "can no longer get changes from replication slot \"wal_level_activeslot\"" -); + "can no longer access replication slot \"wal_level_activeslot\""); ################################################## -# DROP DATABASE should drops it's slots, including active slots. +# DROP DATABASE should drop its slots, including active slots. ################################################## # drop the logical slots diff --git a/src/test/recovery/t/036_truncated_dropped.pl b/src/test/recovery/t/036_truncated_dropped.pl index e205d8b9fba2b..db2303ae771ad 100644 --- a/src/test/recovery/t/036_truncated_dropped.pl +++ b/src/test/recovery/t/036_truncated_dropped.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests recovery scenarios where the files are shorter than in the common # cases, e.g. due to replaying WAL records of a relation that was subsequently diff --git a/src/test/recovery/t/037_invalid_database.pl b/src/test/recovery/t/037_invalid_database.pl index 47f524be4ccda..dc52c55c7af8d 100644 --- a/src/test/recovery/t/037_invalid_database.pl +++ b/src/test/recovery/t/037_invalid_database.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # Test we handle interrupted DROP DATABASE correctly. @@ -15,7 +15,7 @@ autovacuum = off max_prepared_transactions=5 log_min_duration_statement=0 -log_connections=on +log_connections=receipt log_disconnections=on )); @@ -88,30 +88,37 @@ # Test that interruption of DROP DATABASE is handled properly. To ensure the # interruption happens at the appropriate moment, we lock pg_tablespace. DROP # DATABASE scans pg_tablespace once it has reached the "irreversible" part of -# dropping the database, making it a suitable point to wait. +# dropping the database, making it a suitable point to wait. Since relcache +# init reads pg_tablespace, establish each connection before locking. This +# avoids a connection-time hang with debug_discard_caches. +my $cancel = $node->background_psql('postgres', on_error_stop => 1); my $bgpsql = $node->background_psql('postgres', on_error_stop => 0); my $pid = $bgpsql->query('SELECT pg_backend_pid()'); # create the database, prevent drop database via lock held by a 2PC transaction -ok( $bgpsql->query_safe( - qq( +$bgpsql->query_safe( + qq( CREATE DATABASE regression_invalid_interrupt; BEGIN; LOCK pg_tablespace; - PREPARE TRANSACTION 'lock_tblspc';)), - "blocked DROP DATABASE completion"); + PREPARE TRANSACTION 'lock_tblspc';)); # Try to drop. This will wait due to the still held lock. $bgpsql->query_until(qr//, "DROP DATABASE regression_invalid_interrupt;\n"); -# Ensure we're waiting for the lock -$node->poll_query_until('postgres', - qq(SELECT EXISTS(SELECT * FROM pg_locks WHERE NOT granted AND relation = 'pg_tablespace'::regclass AND mode = 'AccessShareLock');) -); -# and finally interrupt the DROP DATABASE -ok($node->safe_psql('postgres', "SELECT pg_cancel_backend($pid)"), +# Once the DROP DATABASE is waiting for the lock, interrupt it. +ok( $cancel->query_safe( + qq( + DO \$\$ + BEGIN + WHILE NOT EXISTS(SELECT * FROM pg_locks WHERE NOT granted AND relation = 'pg_tablespace'::regclass AND mode = 'AccessShareLock') LOOP + PERFORM pg_sleep(.1); + END LOOP; + END\$\$; + SELECT pg_cancel_backend($pid);)), "canceling DROP DATABASE"); +$cancel->quit(); # wait for cancellation to be processed ok( pump_until( @@ -120,17 +127,15 @@ "cancel processed"); $bgpsql->{stderr} = ''; -# verify that connection to the database aren't allowed +# Verify that connections to the database aren't allowed. The backend checks +# this before relcache init, so the lock won't interfere. is($node->psql('regression_invalid_interrupt', ''), 2, "can't connect to invalid_interrupt database"); # To properly drop the database, we need to release the lock previously preventing # doing so. -ok($bgpsql->query_safe(qq(ROLLBACK PREPARED 'lock_tblspc')), - "unblock DROP DATABASE"); - -ok($bgpsql->query(qq(DROP DATABASE regression_invalid_interrupt)), - "DROP DATABASE invalid_interrupt"); +$bgpsql->query_safe(qq(ROLLBACK PREPARED 'lock_tblspc')); +$bgpsql->query_safe(qq(DROP DATABASE regression_invalid_interrupt)); $bgpsql->quit(); diff --git a/src/test/recovery/t/038_save_logical_slots_shutdown.pl b/src/test/recovery/t/038_save_logical_slots_shutdown.pl index 2a3bf1f8da9f8..a47b2d9230303 100644 --- a/src/test/recovery/t/038_save_logical_slots_shutdown.pl +++ b/src/test/recovery/t/038_save_logical_slots_shutdown.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # Test logical replication slots are always flushed to disk during a shutdown # checkpoint. diff --git a/src/test/recovery/t/039_end_of_wal.pl b/src/test/recovery/t/039_end_of_wal.pl index f9acc83c7d092..47f9bb15e0335 100644 --- a/src/test/recovery/t/039_end_of_wal.pl +++ b/src/test/recovery/t/039_end_of_wal.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, PostgreSQL Global Development Group +# Copyright (c) 2023-2025, PostgreSQL Global Development Group # # Test detecting end-of-WAL conditions. This test suite generates # fake defective page and record headers to trigger various failure @@ -20,9 +20,6 @@ # we need to know the endianness to do that. my $BIG_ENDIAN = pack("L", 0x12345678) eq pack("N", 0x12345678); -# Header size of record header. -my $RECORD_HEADER_SIZE = 24; - # Fields retrieved from code headers. my @scan_result = scan_server_header('access/xlog_internal.h', '#define\s+XLOG_PAGE_MAGIC\s+(\w+)'); @@ -36,64 +33,6 @@ my $WAL_BLOCK_SIZE; my $TLI; -# Build path of a WAL segment. -sub wal_segment_path -{ - my $node = shift; - my $tli = shift; - my $segment = shift; - my $wal_path = - sprintf("%s/pg_wal/%08X%08X%08X", $node->data_dir, $tli, 0, $segment); - return $wal_path; -} - -# Calculate from a LSN (in bytes) its segment number and its offset. -sub lsn_to_segment_and_offset -{ - my $lsn = shift; - return ($lsn / $WAL_SEGMENT_SIZE, $lsn % $WAL_SEGMENT_SIZE); -} - -# Write some arbitrary data in WAL for the given segment at LSN. -# This should be called while the cluster is not running. -sub write_wal -{ - my $node = shift; - my $tli = shift; - my $lsn = shift; - my $data = shift; - - my ($segment, $offset) = lsn_to_segment_and_offset($lsn); - my $path = wal_segment_path($node, $tli, $segment); - - open my $fh, "+<:raw", $path or die; - seek($fh, $offset, SEEK_SET) or die; - print $fh $data; - close $fh; -} - -# Emit a WAL record of arbitrary size. Returns the end LSN of the -# record inserted, in bytes. -sub emit_message -{ - my $node = shift; - my $size = shift; - return int( - $node->safe_psql( - 'postgres', - "SELECT pg_logical_emit_message(true, '', repeat('a', $size)) - '0/0'" - )); -} - -# Get the current insert LSN of a node, in bytes. -sub get_insert_lsn -{ - my $node = shift; - return int( - $node->safe_psql( - 'postgres', "SELECT pg_current_wal_insert_lsn() - '0/0'")); -} - # Get GUC value, converted to an int. sub get_int_setting { @@ -167,69 +106,6 @@ sub build_page_header $BIG_ENDIAN ? $xlp_pageaddr : 0, $xlp_rem_len); } -# Make sure we are far away enough from the end of a page that we could insert -# a couple of small records. This inserts a few records of a fixed size, until -# the threshold gets close enough to the end of the WAL page inserting records -# to. -sub advance_out_of_record_splitting_zone -{ - my $node = shift; - - my $page_threshold = $WAL_BLOCK_SIZE / 4; - my $end_lsn = get_insert_lsn($node); - my $page_offset = $end_lsn % $WAL_BLOCK_SIZE; - while ($page_offset >= $WAL_BLOCK_SIZE - $page_threshold) - { - emit_message($node, $page_threshold); - $end_lsn = get_insert_lsn($node); - $page_offset = $end_lsn % $WAL_BLOCK_SIZE; - } - return $end_lsn; -} - -# Advance so close to the end of a page that an XLogRecordHeader would not -# fit on it. -sub advance_to_record_splitting_zone -{ - my $node = shift; - - my $end_lsn = get_insert_lsn($node); - my $page_offset = $end_lsn % $WAL_BLOCK_SIZE; - - # Get fairly close to the end of a page in big steps - while ($page_offset <= $WAL_BLOCK_SIZE - 512) - { - emit_message($node, $WAL_BLOCK_SIZE - $page_offset - 256); - $end_lsn = get_insert_lsn($node); - $page_offset = $end_lsn % $WAL_BLOCK_SIZE; - } - - # Calibrate our message size so that we can get closer 8 bytes at - # a time. - my $message_size = $WAL_BLOCK_SIZE - 80; - while ($page_offset <= $WAL_BLOCK_SIZE - $RECORD_HEADER_SIZE) - { - emit_message($node, $message_size); - $end_lsn = get_insert_lsn($node); - - my $old_offset = $page_offset; - $page_offset = $end_lsn % $WAL_BLOCK_SIZE; - - # Adjust the message size until it causes 8 bytes changes in - # offset, enough to be able to split a record header. - my $delta = $page_offset - $old_offset; - if ($delta > 8) - { - $message_size -= 8; - } - elsif ($delta <= 0) - { - $message_size += 8; - } - } - return $end_lsn; -} - # Setup a new node. The configuration chosen here minimizes the number # of arbitrary records that could get generated in a cluster. Enlarging # checkpoint_timeout avoids noise with checkpoint activity. wal_level @@ -251,6 +127,12 @@ sub advance_to_record_splitting_zone $TLI = $node->safe_psql('postgres', "SELECT timeline_id FROM pg_control_checkpoint();"); +# Initial LSN may vary across systems due to different catalog contents set up +# by initdb. Switch to a new WAL file so all systems start out in the same +# place. The first test depends on trailing zeroes on a page with a valid +# header. +$node->safe_psql('postgres', "SELECT pg_switch_wal();"); + my $end_lsn; my $prev_lsn; @@ -259,8 +141,8 @@ sub advance_to_record_splitting_zone ########################################################################### # xl_tot_len is 0 (a common case, we hit trailing zeroes). -emit_message($node, 0); -$end_lsn = advance_out_of_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); my $log_size = -s $node->logfile; $node->start; @@ -270,10 +152,10 @@ sub advance_to_record_splitting_zone "xl_tot_len zero"); # xl_tot_len is < 24 (presumably recycled garbage). -emit_message($node, 0); -$end_lsn = advance_out_of_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, build_record_header(23)); +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(23)); $log_size = -s $node->logfile; $node->start; ok( $node->log_contains( @@ -283,10 +165,10 @@ sub advance_to_record_splitting_zone # xl_tot_len in final position, not big enough to span into a new page but # also not eligible for regular record header validation -emit_message($node, 0); -$end_lsn = advance_to_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_to_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, build_record_header(1)); +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(1)); $log_size = -s $node->logfile; $node->start; ok( $node->log_contains( @@ -295,10 +177,10 @@ sub advance_to_record_splitting_zone "xl_tot_len short at end-of-page"); # Need more pages, but xl_prev check fails first. -emit_message($node, 0); -$end_lsn = advance_out_of_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, 0xdeadbeef)); $log_size = -s $node->logfile; $node->start; @@ -307,12 +189,12 @@ sub advance_to_record_splitting_zone "xl_prev bad"); # xl_crc check fails. -emit_message($node, 0); -advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 10); +$node->emit_wal(0); +$node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(10); $node->stop('immediate'); # Corrupt a byte in that record, breaking its CRC. -write_wal($node, $TLI, $end_lsn - 8, '!'); +$node->write_wal($TLI, $end_lsn - 8, $WAL_SEGMENT_SIZE, '!'); $log_size = -s $node->logfile; $node->start; ok( $node->log_contains( @@ -329,11 +211,11 @@ sub advance_to_record_splitting_zone # written to WAL. # Good xl_prev, we hit zero page next (zero magic). -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, $prev_lsn)); $log_size = -s $node->logfile; $node->start; @@ -341,16 +223,14 @@ sub advance_to_record_splitting_zone "xlp_magic zero"); # Good xl_prev, we hit garbage page next (bad magic). -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, $prev_lsn)); -write_wal( - $node, $TLI, - start_of_next_page($end_lsn), - build_page_header(0xcafe, 0, 1, 0)); +$node->write_wal($TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header(0xcafe, 0, 1, 0)); $log_size = -s $node->logfile; $node->start; ok($node->log_contains("invalid magic number CAFE .* LSN .*", $log_size), @@ -358,16 +238,14 @@ sub advance_to_record_splitting_zone # Good xl_prev, we hit typical recycled page (good xlp_magic, bad # xlp_pageaddr). -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, $prev_lsn)); -write_wal( - $node, $TLI, - start_of_next_page($end_lsn), - build_page_header($XLP_PAGE_MAGIC, 0, 1, 0xbaaaaaad)); +$node->write_wal($TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header($XLP_PAGE_MAGIC, 0, 1, 0xbaaaaaad)); $log_size = -s $node->logfile; $node->start; ok( $node->log_contains( @@ -375,15 +253,16 @@ sub advance_to_record_splitting_zone "xlp_pageaddr bad"); # Good xl_prev, xlp_magic, xlp_pageaddr, but bogus xlp_info. -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 42, $prev_lsn)); -write_wal( - $node, $TLI, +$node->write_wal( + $TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header( $XLP_PAGE_MAGIC, 0x1234, 1, start_of_next_page($end_lsn))); $log_size = -s $node->logfile; @@ -393,15 +272,14 @@ sub advance_to_record_splitting_zone # Good xl_prev, xlp_magic, xlp_pageaddr, but xlp_info doesn't mention # continuation record. -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 42, $prev_lsn)); -write_wal( - $node, $TLI, - start_of_next_page($end_lsn), +$node->write_wal($TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header($XLP_PAGE_MAGIC, 0, 1, start_of_next_page($end_lsn))); $log_size = -s $node->logfile; $node->start; @@ -410,15 +288,16 @@ sub advance_to_record_splitting_zone # Good xl_prev, xlp_magic, xlp_pageaddr, xlp_info but xlp_rem_len doesn't add # up. -emit_message($node, 0); -$prev_lsn = advance_out_of_record_splitting_zone($node); -$end_lsn = emit_message($node, 0); +$node->emit_wal(0); +$prev_lsn = $node->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); +$end_lsn = $node->emit_wal(0); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 42, $prev_lsn)); -write_wal( - $node, $TLI, +$node->write_wal( + $TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header( $XLP_PAGE_MAGIC, $XLP_FIRST_IS_CONTRECORD, 1, start_of_next_page($end_lsn), @@ -435,10 +314,10 @@ sub advance_to_record_splitting_zone ########################################################################### # xl_prev is bad and xl_tot_len is too big, but we'll check xlp_magic first. -emit_message($node, 0); -$end_lsn = advance_to_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_to_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, 0xdeadbeef)); $log_size = -s $node->logfile; $node->start; @@ -446,14 +325,15 @@ sub advance_to_record_splitting_zone "xlp_magic zero (split record header)"); # And we'll also check xlp_pageaddr before any header checks. -emit_message($node, 0); -$end_lsn = advance_to_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_to_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, 0xdeadbeef)); -write_wal( - $node, $TLI, +$node->write_wal( + $TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header( $XLP_PAGE_MAGIC, $XLP_FIRST_IS_CONTRECORD, 1, 0xbaaaaaad)); $log_size = -s $node->logfile; @@ -464,14 +344,15 @@ sub advance_to_record_splitting_zone # We'll also discover that xlp_rem_len doesn't add up before any # header checks, -emit_message($node, 0); -$end_lsn = advance_to_record_splitting_zone($node); +$node->emit_wal(0); +$end_lsn = $node->advance_wal_to_record_splitting_zone($WAL_BLOCK_SIZE); $node->stop('immediate'); -write_wal($node, $TLI, $end_lsn, +$node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE, build_record_header(2 * 1024 * 1024 * 1024, 0, 0xdeadbeef)); -write_wal( - $node, $TLI, +$node->write_wal( + $TLI, start_of_next_page($end_lsn), + $WAL_SEGMENT_SIZE, build_page_header( $XLP_PAGE_MAGIC, $XLP_FIRST_IS_CONTRECORD, 1, start_of_next_page($end_lsn), diff --git a/src/test/recovery/t/040_standby_failover_slots_sync.pl b/src/test/recovery/t/040_standby_failover_slots_sync.pl index 2c51cfc3c864a..9c8b49e942d88 100644 --- a/src/test/recovery/t/040_standby_failover_slots_sync.pl +++ b/src/test/recovery/t/040_standby_failover_slots_sync.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -18,11 +18,15 @@ # This is only needed on Windows machines that don't use UNIX sockets. $publisher->init( allows_streaming => 'logical', - auth_extra => [ '--create-role', 'repl_role' ]); + auth_extra => [ '--create-role' => 'repl_role' ]); # Disable autovacuum to avoid generating xid during stats update as otherwise # the new XID could then be replicated to standby at some random point making # slots at primary lag behind standby during slot sync. -$publisher->append_conf('postgresql.conf', 'autovacuum = off'); +$publisher->append_conf( + 'postgresql.conf', qq{ +autovacuum = off +max_prepared_transactions = 1 +}); $publisher->start; $publisher->safe_psql('postgres', @@ -33,6 +37,7 @@ # Create a subscriber node, wait for sync to complete my $subscriber1 = PostgreSQL::Test::Cluster->new('subscriber1'); $subscriber1->init; +$subscriber1->append_conf('postgresql.conf', 'max_prepared_transactions = 1'); $subscriber1->start; # Capture the time before the logical failover slot is created on the @@ -95,7 +100,8 @@ # Disable failover for enabled subscription my ($result, $stdout, $stderr) = $subscriber1->psql('postgres', "ALTER SUBSCRIPTION regress_mysub1 SET (failover = false)"); -ok( $stderr =~ /ERROR: cannot set failover for enabled subscription/, +ok( $stderr =~ + /ERROR: cannot set option "failover" for enabled subscription/, "altering failover is not allowed for enabled subscription"); ################################################## @@ -280,7 +286,8 @@ # Confirm that the invalidated slot has been dropped. $standby1->wait_for_log( - qr/dropped replication slot "lsub1_slot" of dbid [0-9]+/, $log_offset); + qr/dropped replication slot "lsub1_slot" of database with OID [0-9]+/, + $log_offset); # Confirm that the logical slot has been re-created on the standby and is # flagged as 'synced' @@ -335,7 +342,7 @@ ($result, $stdout, $stderr) = $standby1->psql('postgres', "SELECT pg_sync_replication_slots();"); ok( $stderr =~ - /ERROR: slot synchronization requires dbname to be specified in primary_conninfo/, + /ERROR: replication slot synchronization requires "dbname" to be specified in "primary_conninfo"/, "cannot sync slots if dbname is not specified in primary_conninfo"); # Add the dbname back to the primary_conninfo for further tests @@ -526,10 +533,10 @@ # Confirm that slot sync worker acknowledge the GUC change and logs the msg # about wrong configuration. $standby1->wait_for_log( - qr/slot sync worker will restart because of a parameter change/, + qr/slot synchronization worker will restart because of a parameter change/, $log_offset); $standby1->wait_for_log( - qr/slot synchronization requires hot_standby_feedback to be enabled/, + qr/slot synchronization requires "hot_standby_feedback" to be enabled/, $log_offset); $log_offset = -s $standby1->logfile; @@ -678,7 +685,7 @@ # Wait until the primary server logs a warning indicating that it is waiting # for the sb1_slot to catch up. $primary->wait_for_log( - qr/replication slot \"sb1_slot\" specified in parameter synchronized_standby_slots does not have active_pid/, + qr/replication slot \"sb1_slot\" specified in parameter "synchronized_standby_slots" does not have active_pid/, $offset); # The regress_mysub1 was enabled for failover so it doesn't get the data from @@ -757,7 +764,7 @@ # Wait until the primary server logs a warning indicating that it is waiting # for the sb1_slot to catch up. $primary->wait_for_log( - qr/replication slot \"sb1_slot\" specified in parameter synchronized_standby_slots does not have active_pid/, + qr/replication slot \"sb1_slot\" specified in parameter "synchronized_standby_slots" does not have active_pid/, $offset); # Remove the standby from the synchronized_standby_slots list and reload the @@ -798,7 +805,7 @@ # Wait until the primary server logs a warning indicating that it is waiting # for the sb1_slot to catch up. $primary->wait_for_log( - qr/replication slot \"sb1_slot\" specified in parameter synchronized_standby_slots does not have active_pid/, + qr/replication slot \"sb1_slot\" specified in parameter "synchronized_standby_slots" does not have active_pid/, $offset); # The regress_mysub1 doesn't get the data from primary because the specified @@ -828,13 +835,72 @@ "'sb1_slot'"); $primary->reload; +################################################## +# Test the synchronization of the two_phase setting for a subscription with the +# standby. Additionally, prepare a transaction before enabling the two_phase +# option; subsequent tests will verify if it can be correctly replicated to the +# subscriber after committing it on the promoted standby. +################################################## + +$standby1->start; + +# Prepare a transaction +$primary->safe_psql( + 'postgres', qq[ + BEGIN; + INSERT INTO tab_int values(0); + PREPARE TRANSACTION 'test_twophase_slotsync'; +]); + +$primary->wait_for_replay_catchup($standby1); +$primary->wait_for_catchup('regress_mysub1'); + +# Disable the subscription to allow changing the two_phase option. +$subscriber1->safe_psql('postgres', + "ALTER SUBSCRIPTION regress_mysub1 DISABLE"); + +# Wait for the replication slot to become inactive on the publisher +$primary->poll_query_until( + 'postgres', + "SELECT COUNT(*) FROM pg_catalog.pg_replication_slots WHERE slot_name = 'lsub1_slot' AND active='f'", + 1); + +# Set two_phase to true and enable the subscription +$subscriber1->safe_psql( + 'postgres', qq[ + ALTER SUBSCRIPTION regress_mysub1 SET (two_phase = true); + ALTER SUBSCRIPTION regress_mysub1 ENABLE; +]); + +$primary->wait_for_catchup('regress_mysub1'); + +my $two_phase_at = $primary->safe_psql('postgres', + "SELECT two_phase_at from pg_replication_slots WHERE slot_name = 'lsub1_slot';" +); + +# Confirm that two_phase setting of lsub1_slot slot is synced to the standby +ok( $standby1->poll_query_until( + 'postgres', + "SELECT two_phase AND '$two_phase_at' = two_phase_at from pg_replication_slots WHERE slot_name = 'lsub1_slot' AND synced AND NOT temporary;" + ), + 'two_phase setting of slot lsub1_slot synced to standby'); + +# Confirm that the prepared transaction is not yet replicated to the +# subscriber. +$result = $subscriber1->safe_psql('postgres', + "SELECT count(*) = 0 FROM pg_prepared_xacts;"); +is($result, 't', + "the prepared transaction is not replicated to the subscriber"); + ################################################## # Promote the standby1 to primary. Confirm that: # a) the slot 'lsub1_slot' and 'snap_test_slot' are retained on the new primary # b) logical replication for regress_mysub1 is resumed successfully after failover -# c) changes can be consumed from the synced slot 'snap_test_slot' +# c) changes from the transaction prepared 'test_twophase_slotsync' can be +# consumed from the synced slot 'snap_test_slot' once committed on the new +# primary. +# d) changes can be consumed from the synced slot 'snap_test_slot' ################################################## -$standby1->start; $primary->wait_for_replay_catchup($standby1); # Capture the time before the standby is promoted @@ -874,6 +940,15 @@ 't', 'synced slot retained on the new primary'); +# Commit the prepared transaction +$standby1->safe_psql('postgres', + "COMMIT PREPARED 'test_twophase_slotsync';"); +$standby1->wait_for_catchup('regress_mysub1'); + +# Confirm that the prepared transaction is replicated to the subscriber +is($subscriber1->safe_psql('postgres', q{SELECT count(*) FROM tab_int;}), + "11", 'prepared data replicated from the new primary'); + # Insert data on the new primary $standby1->safe_psql('postgres', "INSERT INTO tab_int SELECT generate_series(11, 20);"); @@ -881,7 +956,7 @@ # Confirm that data in tab_int replicated on the subscriber is($subscriber1->safe_psql('postgres', q{SELECT count(*) FROM tab_int;}), - "20", 'data replicated from the new primary'); + "21", 'data replicated from the new primary'); # Consume the data from the snap_test_slot. The synced slot should reach a # consistent point by restoring the snapshot at the restart_lsn serialized diff --git a/src/test/recovery/t/041_checkpoint_at_promote.pl b/src/test/recovery/t/041_checkpoint_at_promote.pl index 5aa05b456ca22..cb63ac8d5c9b0 100644 --- a/src/test/recovery/t/041_checkpoint_at_promote.pl +++ b/src/test/recovery/t/041_checkpoint_at_promote.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -35,6 +35,14 @@ ]); $node_primary->start; +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node_primary->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + my $backup_name = 'my_backup'; $node_primary->backup($backup_name); @@ -102,7 +110,7 @@ my $checkpoint_complete = 0; foreach my $i (0 .. 10 * $PostgreSQL::Test::Utils::timeout_default) { - if ($node_standby->log_contains("restartpoint complete"), $logstart) + if ($node_standby->log_contains("restartpoint complete", $logstart)) { $checkpoint_complete = 1; last; @@ -116,15 +124,14 @@ my ($killme_stdin, $killme_stdout, $killme_stderr) = ('', '', ''); my $killme = IPC::Run::start( [ - 'psql', '-XAtq', '-v', 'ON_ERROR_STOP=1', '-f', '-', '-d', - $node_standby->connstr('postgres') + 'psql', '--no-psqlrc', '--no-align', '--tuples-only', '--quiet', + '--set' => 'ON_ERROR_STOP=1', + '--file' => '-', + '--dbname' => $node_standby->connstr('postgres') ], - '<', - \$killme_stdin, - '>', - \$killme_stdout, - '2>', - \$killme_stderr, + '<' => \$killme_stdin, + '>' => \$killme_stdout, + '2>' => \$killme_stderr, $psql_timeout); $killme_stdin .= q[ SELECT pg_backend_pid(); diff --git a/src/test/recovery/t/042_low_level_backup.pl b/src/test/recovery/t/042_low_level_backup.pl index 61d23187e0f90..5749a1df53303 100644 --- a/src/test/recovery/t/042_low_level_backup.pl +++ b/src/test/recovery/t/042_low_level_backup.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group # Test low-level backup method by using pg_backup_start() and pg_backup_stop() # to create backups. diff --git a/src/test/recovery/t/043_no_contrecord_switch.pl b/src/test/recovery/t/043_no_contrecord_switch.pl new file mode 100644 index 0000000000000..ead41e6f40bed --- /dev/null +++ b/src/test/recovery/t/043_no_contrecord_switch.pl @@ -0,0 +1,154 @@ +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Tests for already-propagated WAL segments ending in incomplete WAL records. + +use strict; +use warnings; + +use File::Copy; +use PostgreSQL::Test::Cluster; +use Test::More; +use Fcntl qw(SEEK_SET); + +use integer; # causes / operator to use integer math + +# Values queried from the server +my $WAL_SEGMENT_SIZE; +my $WAL_BLOCK_SIZE; +my $TLI; + +# Build name of a WAL segment, used when filtering the contents of the server +# logs. +sub wal_segment_name +{ + my $tli = shift; + my $segment = shift; + return sprintf("%08X%08X%08X", $tli, 0, $segment); +} + +# Calculate from a LSN (in bytes) its segment number and its offset, used +# when filtering the contents of the server logs. +sub lsn_to_segment_and_offset +{ + my $lsn = shift; + return ($lsn / $WAL_SEGMENT_SIZE, $lsn % $WAL_SEGMENT_SIZE); +} + +# Get GUC value, converted to an int. +sub get_int_setting +{ + my $node = shift; + my $name = shift; + return int( + $node->safe_psql( + 'postgres', + "SELECT setting FROM pg_settings WHERE name = '$name'")); +} + +# Find the start of a WAL page, based on an LSN in bytes. +sub start_of_page +{ + my $lsn = shift; + return $lsn & ~($WAL_BLOCK_SIZE - 1); +} + +my $primary = PostgreSQL::Test::Cluster->new('primary'); +$primary->init(allows_streaming => 1, has_archiving => 1); + +# The configuration is chosen here to minimize the friction with +# concurrent WAL activity. checkpoint_timeout avoids noise with +# checkpoint activity, and autovacuum is disabled to avoid any +# WAL activity generated by it. +$primary->append_conf( + 'postgresql.conf', qq( +autovacuum = off +checkpoint_timeout = '30min' +wal_keep_size = 1GB +)); + +$primary->start; +$primary->backup('backup'); + +$primary->safe_psql('postgres', "CREATE TABLE t AS SELECT 0"); + +$WAL_SEGMENT_SIZE = get_int_setting($primary, 'wal_segment_size'); +$WAL_BLOCK_SIZE = get_int_setting($primary, 'wal_block_size'); +$TLI = $primary->safe_psql('postgres', + "SELECT timeline_id FROM pg_control_checkpoint()"); + +# Get close to the end of the current WAL page, enough to fit the +# beginning of a record that spans on two pages, generating a +# continuation record. +$primary->emit_wal(0); +my $end_lsn = + $primary->advance_wal_out_of_record_splitting_zone($WAL_BLOCK_SIZE); + +# Do some math to find the record size that will overflow the page, and +# write it. +my $overflow_size = $WAL_BLOCK_SIZE - ($end_lsn % $WAL_BLOCK_SIZE); +$end_lsn = $primary->emit_wal($overflow_size); +$primary->stop('immediate'); + +# Find the beginning of the page with the continuation record and fill +# the entire page with zero bytes to simulate broken replication. +my $start_page = start_of_page($end_lsn); +my $wal_file = $primary->write_wal($TLI, $start_page, $WAL_SEGMENT_SIZE, + "\x00" x $WAL_BLOCK_SIZE); + +# Copy the file we just "hacked" to the archives. +copy($wal_file, $primary->archive_dir); + +# Start standby nodes and make sure they replay the file "hacked" from +# the archives of the primary. +my $standby1 = PostgreSQL::Test::Cluster->new('standby1'); +$standby1->init_from_backup( + $primary, 'backup', + standby => 1, + has_restoring => 1); + +my $standby2 = PostgreSQL::Test::Cluster->new('standby2'); +$standby2->init_from_backup( + $primary, 'backup', + standby => 1, + has_restoring => 1); + +my $log_size1 = -s $standby1->logfile; +my $log_size2 = -s $standby2->logfile; + +$standby1->start; +$standby2->start; + +my ($segment, $offset) = lsn_to_segment_and_offset($start_page); +my $segment_name = wal_segment_name($TLI, $segment); +my $pattern = + qq(invalid magic number 0000 .* segment $segment_name.* offset $offset); + +# We expect both standby nodes to complain about an empty page when trying to +# assemble the record that spans over two pages, so wait for such reports in +# their logs. +$standby1->wait_for_log($pattern, $log_size1); +$standby2->wait_for_log($pattern, $log_size2); + +# Now check the case of a promotion with a timeline jump handled at +# page boundary with a continuation record. +$standby1->promote; + +# This command forces standby2 to read a continuation record from the page +# that is filled with zero bytes. +$standby1->safe_psql('postgres', 'SELECT pg_switch_wal()'); + +# Make sure WAL moves forward. +$standby1->safe_psql('postgres', + 'INSERT INTO t SELECT * FROM generate_series(1, 1000)'); + +# Configure standby2 to stream from just promoted standby1 (it also pulls WAL +# files from the archive). It should be able to catch up. +$standby2->enable_streaming($standby1); +$standby2->reload; +$standby1->wait_for_replay_catchup($standby2); + +my $result = $standby2->safe_psql('postgres', "SELECT count(*) FROM t"); +print "standby2: $result\n"; +is($result, qq(1001), 'check streamed content on standby2'); + +done_testing(); diff --git a/src/test/recovery/t/044_invalidate_inactive_slots.pl b/src/test/recovery/t/044_invalidate_inactive_slots.pl new file mode 100644 index 0000000000000..ccace14b4dd80 --- /dev/null +++ b/src/test/recovery/t/044_invalidate_inactive_slots.pl @@ -0,0 +1,105 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +# Test for replication slots invalidation due to idle_timeout +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +# This test depends on injection point that forces slot invalidation +# due to idle_timeout. +# https://www.postgresql.org/docs/current/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +# Wait for slot to first become idle and then get invalidated +sub wait_for_slot_invalidation +{ + my ($node, $slot_name, $offset) = @_; + my $node_name = $node->name; + + # The slot's invalidation should be logged + $node->wait_for_log( + qr/invalidating obsolete replication slot \"$slot_name\"/, $offset); + + # Check that the invalidation reason is 'idle_timeout' + $node->poll_query_until( + 'postgres', qq[ + SELECT COUNT(slot_name) = 1 FROM pg_replication_slots + WHERE slot_name = '$slot_name' AND + invalidation_reason = 'idle_timeout'; + ]) + or die + "Timed out while waiting for invalidation reason of slot $slot_name to be set on node $node_name"; +} + +# ======================================================================== +# Testcase start +# +# Test invalidation of physical replication slot and logical replication slot +# due to idle timeout. + +# Initialize the node +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init(allows_streaming => 'logical'); + +# Avoid unpredictability +$node->append_conf( + 'postgresql.conf', qq{ +checkpoint_timeout = 1h +idle_replication_slot_timeout = 1min +}); +$node->start; + +# Check if the 'injection_points' extension is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + +# Create both physical and logical replication slots +$node->safe_psql( + 'postgres', qq[ + SELECT pg_create_physical_replication_slot(slot_name := 'physical_slot', immediately_reserve := true); + SELECT pg_create_logical_replication_slot('logical_slot', 'test_decoding'); +]); + +my $log_offset = -s $node->logfile; + +# Register an injection point on the node to forcibly cause a slot +# invalidation due to idle_timeout +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); + +$node->safe_psql('postgres', + "SELECT injection_points_attach('slot-timeout-inval', 'error');"); + +# Slot invalidation occurs during a checkpoint, so perform a checkpoint to +# invalidate the slots. +$node->safe_psql('postgres', "CHECKPOINT"); + +# Wait for slots to become inactive. Since nobody has acquired the slot yet, +# it can only be due to the idle timeout mechanism. +wait_for_slot_invalidation($node, 'physical_slot', $log_offset); +wait_for_slot_invalidation($node, 'logical_slot', $log_offset); + +# Check that the invalidated slot cannot be acquired +my ($result, $stdout, $stderr); +($result, $stdout, $stderr) = $node->psql( + 'postgres', qq[ + SELECT pg_replication_slot_advance('logical_slot', '0/1'); +]); +ok( $stderr =~ /can no longer access replication slot "logical_slot"/, + "detected error upon trying to acquire invalidated slot on node") + or die + "could not detect error upon trying to acquire invalidated slot \"logical_slot\" on node"; + +# Testcase end +# ============================================================================= + +done_testing(); diff --git a/src/test/recovery/t/045_archive_restartpoint.pl b/src/test/recovery/t/045_archive_restartpoint.pl new file mode 100644 index 0000000000000..b143bc4e1d4e7 --- /dev/null +++ b/src/test/recovery/t/045_archive_restartpoint.pl @@ -0,0 +1,57 @@ + +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# Test restartpoints during archive recovery. +use strict; +use warnings; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $archive_max_mb = 320; +my $wal_segsize = 1; + +# Initialize primary node +my $node_primary = PostgreSQL::Test::Cluster->new('primary'); +$node_primary->init( + has_archiving => 1, + allows_streaming => 1, + extra => [ '--wal-segsize' => $wal_segsize ]); +$node_primary->start; +my $backup_name = 'my_backup'; +$node_primary->backup($backup_name); + +$node_primary->safe_psql('postgres', + ('DO $$BEGIN FOR i IN 1..' . $archive_max_mb / $wal_segsize) + . ' LOOP CHECKPOINT; PERFORM pg_switch_wal(); END LOOP; END$$;'); + +# Force archiving of WAL file containing recovery target +my $until_lsn = $node_primary->lsn('write'); +$node_primary->safe_psql('postgres', "SELECT pg_switch_wal()"); +$node_primary->stop; + +# Archive recovery +my $node_restore = PostgreSQL::Test::Cluster->new('restore'); +$node_restore->init_from_backup($node_primary, $backup_name, + has_restoring => 1); +$node_restore->append_conf('postgresql.conf', + "recovery_target_lsn = '$until_lsn'"); +$node_restore->append_conf('postgresql.conf', + 'recovery_target_action = pause'); +$node_restore->append_conf('postgresql.conf', + 'max_wal_size = ' . 2 * $wal_segsize); +$node_restore->append_conf('postgresql.conf', 'log_checkpoints = on'); + +$node_restore->start; + +# Wait until restore has replayed enough data +my $caughtup_query = + "SELECT '$until_lsn'::pg_lsn <= pg_last_wal_replay_lsn()"; +$node_restore->poll_query_until('postgres', $caughtup_query) + or die "Timed out while waiting for restore to catch up"; + +$node_restore->stop; +ok(1, 'restore caught up'); + +done_testing(); diff --git a/src/test/recovery/t/046_checkpoint_logical_slot.pl b/src/test/recovery/t/046_checkpoint_logical_slot.pl new file mode 100644 index 0000000000000..b4265c4a6a53f --- /dev/null +++ b/src/test/recovery/t/046_checkpoint_logical_slot.pl @@ -0,0 +1,139 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group +# +# This test verifies the case when the logical slot is advanced during +# checkpoint. The test checks that the logical slot's restart_lsn still refers +# to an existed WAL segment after immediate restart. +# +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +my ($node, $result); + +$node = PostgreSQL::Test::Cluster->new('mike'); +$node->init; +$node->append_conf('postgresql.conf', + "shared_preload_libraries = 'injection_points'"); +$node->append_conf('postgresql.conf', "wal_level = 'logical'"); +$node->start; +$node->safe_psql('postgres', q(CREATE EXTENSION injection_points)); + +# Create a simple table to generate data into. +$node->safe_psql('postgres', + q{create table t (id serial primary key, b text)}); + +# Create the two slots we'll need. +$node->safe_psql('postgres', + q{select pg_create_logical_replication_slot('slot_logical', 'test_decoding')} +); +$node->safe_psql('postgres', + q{select pg_create_physical_replication_slot('slot_physical', true)}); + +# Advance both slots to the current position just to have everything "valid". +$node->safe_psql('postgres', + q{select count(*) from pg_logical_slot_get_changes('slot_logical', null, null)} +); +$node->safe_psql('postgres', + q{select pg_replication_slot_advance('slot_physical', pg_current_wal_lsn())} +); + +# Run checkpoint to flush current state to disk and set a baseline. +$node->safe_psql('postgres', q{checkpoint}); + +# Generate some transactions to get RUNNING_XACTS. +my $xacts = $node->background_psql('postgres'); +$xacts->query_until( + qr/run_xacts/, + q(\echo run_xacts +SELECT 1 \watch 0.1 +\q +)); + +# Insert 2M rows; that's about 260MB (~20 segments) worth of WAL. +$node->safe_psql('postgres', + q{insert into t (b) select md5(i::text) from generate_series(1,1000000) s(i)} +); + +# Run another checkpoint to set a new restore LSN. +$node->safe_psql('postgres', q{checkpoint}); + +# Another 2M rows; that's about 260MB (~20 segments) worth of WAL. +$node->safe_psql('postgres', + q{insert into t (b) select md5(i::text) from generate_series(1,1000000) s(i)} +); + +# Run another checkpoint, this time in the background, and make it wait +# on the injection point) so that the checkpoint stops right before +# removing old WAL segments. +note('starting checkpoint\n'); + +my $checkpoint = $node->background_psql('postgres'); +$checkpoint->query_safe( + q(select injection_points_attach('checkpoint-before-old-wal-removal','wait')) +); +$checkpoint->query_until( + qr/starting_checkpoint/, + q(\echo starting_checkpoint +checkpoint; +\q +)); + +# Wait until the checkpoint stops right before removing WAL segments. +note('waiting for injection_point\n'); +$node->wait_for_event('checkpointer', 'checkpoint-before-old-wal-removal'); +note('injection_point is reached'); + +# Try to advance the logical slot, but make it stop when it moves to the next +# WAL segment (this has to happen in the background, too). +my $logical = $node->background_psql('postgres'); +$logical->query_safe( + q{select injection_points_attach('logical-replication-slot-advance-segment','wait');} +); +$logical->query_until( + qr/get_changes/, + q( +\echo get_changes +select count(*) from pg_logical_slot_get_changes('slot_logical', null, null) \watch 1 +\q +)); + +# Wait until the slot's restart_lsn points to the next WAL segment. +note('waiting for injection_point\n'); +$node->wait_for_event('client backend', + 'logical-replication-slot-advance-segment'); +note('injection_point is reached'); + +# OK, we're in the right situation: time to advance the physical slot, which +# recalculates the required LSN, and then unblock the checkpoint, which +# removes the WAL still needed by the logical slot. +$node->safe_psql('postgres', + q{select pg_replication_slot_advance('slot_physical', pg_current_wal_lsn())} +); + +# Continue the checkpoint. +$node->safe_psql('postgres', + q{select injection_points_wakeup('checkpoint-before-old-wal-removal')}); + +# Abruptly stop the server (1 second should be enough for the checkpoint +# to finish; it would be better). +$node->stop('immediate'); + +$node->start; + +eval { + $node->safe_psql('postgres', + q{select count(*) from pg_logical_slot_get_changes('slot_logical', null, null);} + ); +}; +is($@, '', "Logical slot still valid"); + +done_testing(); diff --git a/src/test/recovery/t/047_checkpoint_physical_slot.pl b/src/test/recovery/t/047_checkpoint_physical_slot.pl new file mode 100644 index 0000000000000..454e56b9bd2da --- /dev/null +++ b/src/test/recovery/t/047_checkpoint_physical_slot.pl @@ -0,0 +1,133 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group +# +# This test verifies the case when the physical slot is advanced during +# checkpoint. The test checks that the physical slot's restart_lsn still refers +# to an existed WAL segment after immediate restart. +# +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +my ($node, $result); + +$node = PostgreSQL::Test::Cluster->new('mike'); +$node->init; +$node->append_conf('postgresql.conf', + "shared_preload_libraries = 'injection_points'"); +$node->append_conf('postgresql.conf', "wal_level = 'replica'"); +$node->start; +$node->safe_psql('postgres', q(CREATE EXTENSION injection_points)); + +# Create a simple table to generate data into. +$node->safe_psql('postgres', + q{create table t (id serial primary key, b text)}); + +# Create a physical replication slot. +$node->safe_psql('postgres', + q{select pg_create_physical_replication_slot('slot_physical', true)}); + +# Advance slot to the current position, just to have everything "valid". +$node->safe_psql('postgres', + q{select pg_replication_slot_advance('slot_physical', pg_current_wal_lsn())} +); + +# Run checkpoint to flush current state to disk and set a baseline. +$node->safe_psql('postgres', q{checkpoint}); + +# Insert 2M rows; that's about 260MB (~20 segments) worth of WAL. +$node->safe_psql('postgres', + q{insert into t (b) select md5(i::text) from generate_series(1,100000) s(i)} +); + +# Advance slot to the current position, just to have everything "valid". +$node->safe_psql('postgres', + q{select pg_replication_slot_advance('slot_physical', pg_current_wal_lsn())} +); + +# Run another checkpoint to set a new restore LSN. +$node->safe_psql('postgres', q{checkpoint}); + +# Another 2M rows; that's about 260MB (~20 segments) worth of WAL. +$node->safe_psql('postgres', + q{insert into t (b) select md5(i::text) from generate_series(1,1000000) s(i)} +); + +my $restart_lsn_init = $node->safe_psql('postgres', + q{select restart_lsn from pg_replication_slots where slot_name = 'slot_physical'} +); +chomp($restart_lsn_init); +note("restart lsn before checkpoint: $restart_lsn_init"); + +# Run another checkpoint, this time in the background, and make it wait +# on the injection point) so that the checkpoint stops right before +# removing old WAL segments. +note('starting checkpoint'); + +my $checkpoint = $node->background_psql('postgres'); +$checkpoint->query_safe( + q{select injection_points_attach('checkpoint-before-old-wal-removal','wait')} +); +$checkpoint->query_until( + qr/starting_checkpoint/, + q(\echo starting_checkpoint +checkpoint; +\q +)); + +# Wait until the checkpoint stops right before removing WAL segments. +note('waiting for injection_point'); +$node->wait_for_event('checkpointer', 'checkpoint-before-old-wal-removal'); +note('injection_point is reached'); + +# OK, we're in the right situation: time to advance the physical slot, which +# recalculates the required LSN and then unblock the checkpoint, which +# removes the WAL still needed by the physical slot. +$node->safe_psql('postgres', + q{select pg_replication_slot_advance('slot_physical', pg_current_wal_lsn())} +); + +# Continue the checkpoint. +$node->safe_psql('postgres', + q{select injection_points_wakeup('checkpoint-before-old-wal-removal')}); + +my $restart_lsn_old = $node->safe_psql('postgres', + q{select restart_lsn from pg_replication_slots where slot_name = 'slot_physical'} +); +chomp($restart_lsn_old); +note("restart lsn before stop: $restart_lsn_old"); + +# Abruptly stop the server (1 second should be enough for the checkpoint +# to finish; it would be better). +$node->stop('immediate'); + +$node->start; + +# Get the restart_lsn of the slot right after restarting. +my $restart_lsn = $node->safe_psql('postgres', + q{select restart_lsn from pg_replication_slots where slot_name = 'slot_physical'} +); +chomp($restart_lsn); +note("restart lsn: $restart_lsn"); + +# Get the WAL segment name for the slot's restart_lsn. +my $restart_lsn_segment = $node->safe_psql('postgres', + "SELECT pg_walfile_name('$restart_lsn'::pg_lsn)"); +chomp($restart_lsn_segment); + +# Check if the required wal segment exists. +note("required by slot segment name: $restart_lsn_segment"); +my $datadir = $node->data_dir; +ok( -f "$datadir/pg_wal/$restart_lsn_segment", + "WAL segment $restart_lsn_segment for physical slot's restart_lsn $restart_lsn exists" +); + +done_testing(); diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile index 9003435aabeef..ef2bddf42cabf 100644 --- a/src/test/regress/GNUmakefile +++ b/src/test/regress/GNUmakefile @@ -3,7 +3,7 @@ # GNUmakefile-- # Makefile for src/test/regress (the regression tests) # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/regress/GNUmakefile @@ -40,7 +40,7 @@ pg_regress$(X): pg_regress.o pg_regress_main.o $(WIN32RES) | submake-libpgport # dependencies ensure that path changes propagate pg_regress.o: pg_regress.c $(top_builddir)/src/port/pg_config_paths.h -pg_regress.o: override CPPFLAGS += -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS) +pg_regress.o: override CPPFLAGS := -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS) $(CPPFLAGS) # note: because of the submake dependency, this rule's action is really a no-op $(top_builddir)/src/port/pg_config_paths.h: | submake-libpgport @@ -87,26 +87,6 @@ installdirs-tests: installdirs $(MKDIR_P) $(patsubst $(srcdir)/%/,'$(DESTDIR)$(pkglibdir)/regress/%',$(sort $(dir $(regress_data_files)))) -# Get some extra C modules from contrib/spi - -all: refint$(DLSUFFIX) autoinc$(DLSUFFIX) - -refint$(DLSUFFIX): $(top_builddir)/contrib/spi/refint$(DLSUFFIX) - cp $< $@ - -autoinc$(DLSUFFIX): $(top_builddir)/contrib/spi/autoinc$(DLSUFFIX) - cp $< $@ - -$(top_builddir)/contrib/spi/refint$(DLSUFFIX): | submake-contrib-spi ; - -$(top_builddir)/contrib/spi/autoinc$(DLSUFFIX): | submake-contrib-spi ; - -submake-contrib-spi: | submake-libpgport submake-generated-headers - $(MAKE) -C $(top_builddir)/contrib/spi - -.PHONY: submake-contrib-spi - - ## ## Run tests ## @@ -148,7 +128,7 @@ bigcheck: all | temp-install clean distclean: clean-lib # things built by `all' target - rm -f $(OBJS) refint$(DLSUFFIX) autoinc$(DLSUFFIX) + rm -f $(OBJS) rm -f pg_regress_main.o pg_regress.o pg_regress$(X) # things created by various check targets rm -rf $(pg_regress_clean_files) diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index a5596ab2106c7..1f1ce2380af68 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1448,6 +1448,73 @@ explain (costs off) select * from p_t1 group by a,b,c,d; -> Seq Scan on p_t1_2 (5 rows) +create unique index t2_z_uidx on t2(z); +-- Ensure we don't remove any columns from the GROUP BY for a unique +-- index on a NULLable column. +explain (costs off) select y,z from t2 group by y,z; + QUERY PLAN +---------------------- + HashAggregate + Group Key: y, z + -> Seq Scan on t2 +(3 rows) + +-- Make the column NOT NULL and ensure we remove the redundant column +alter table t2 alter column z set not null; +explain (costs off) select y,z from t2 group by y,z; + QUERY PLAN +---------------------- + HashAggregate + Group Key: z + -> Seq Scan on t2 +(3 rows) + +-- When there are multiple supporting unique indexes and the GROUP BY contains +-- columns to cover all of those, ensure we pick the index with the least +-- number of columns so that we can remove more columns from the GROUP BY. +explain (costs off) select x,y,z from t2 group by x,y,z; + QUERY PLAN +---------------------- + HashAggregate + Group Key: z + -> Seq Scan on t2 +(3 rows) + +-- As above but try ordering the columns differently to ensure we get the +-- same result. +explain (costs off) select x,y,z from t2 group by z,x,y; + QUERY PLAN +---------------------- + HashAggregate + Group Key: z + -> Seq Scan on t2 +(3 rows) + +-- Ensure we don't use a partial index as proof of functional dependency +drop index t2_z_uidx; +create index t2_z_uidx on t2 (z) where z > 0; +explain (costs off) select y,z from t2 group by y,z; + QUERY PLAN +---------------------- + HashAggregate + Group Key: y, z + -> Seq Scan on t2 +(3 rows) + +-- A unique index defined as NULLS NOT DISTINCT does not need a supporting NOT +-- NULL constraint on the indexed columns. Ensure the redundant columns are +-- removed from the GROUP BY for such a table. +drop index t2_z_uidx; +alter table t2 alter column z drop not null; +create unique index t2_z_uidx on t2(z) nulls not distinct; +explain (costs off) select y,z from t2 group by y,z; + QUERY PLAN +---------------------- + HashAggregate + Group Key: z + -> Seq Scan on t2 +(3 rows) + drop table t1 cascade; NOTICE: drop cascades to table t1c drop table t2; @@ -1611,6 +1678,43 @@ select sum(two order by two) from tenk1; (2 rows) reset enable_presorted_aggregate; +-- +-- Test cases with FILTER clause +-- +-- Ensure we presort when the aggregate contains plain Vars +explain (costs off) +select sum(two order by two) filter (where two > 1) from tenk1; + QUERY PLAN +------------------------------- + Aggregate + -> Sort + Sort Key: two + -> Seq Scan on tenk1 +(4 rows) + +-- Ensure we presort for RelabelType'd Vars +explain (costs off) +select string_agg(distinct f1, ',') filter (where length(f1) > 1) +from varchar_tbl; + QUERY PLAN +------------------------------------- + Aggregate + -> Sort + Sort Key: f1 + -> Seq Scan on varchar_tbl +(4 rows) + +-- Ensure we don't presort when the aggregate's argument contains an +-- explicit cast. +explain (costs off) +select string_agg(distinct f1::varchar(2), ',') filter (where length(f1) > 1) +from varchar_tbl; + QUERY PLAN +------------------------------- + Aggregate + -> Seq Scan on varchar_tbl +(2 rows) + -- -- Test combinations of DISTINCT and/or ORDER BY -- @@ -1950,7 +2054,7 @@ select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; - a,ab,abcd (1 row) --- string_agg bytea tests +-- string_agg, min, max bytea tests create table bytea_test_table(v bytea); select string_agg(v, '') from bytea_test_table; string_agg @@ -1984,6 +2088,32 @@ select string_agg(v, decode('ee', 'hex')) from bytea_test_table; \xffeeaa (1 row) +select min(v) from bytea_test_table; + min +------ + \xaa +(1 row) + +select max(v) from bytea_test_table; + max +------ + \xff +(1 row) + +insert into bytea_test_table values(decode('ffff','hex')); +insert into bytea_test_table values(decode('aaaa','hex')); +select min(v) from bytea_test_table; + min +------ + \xaa +(1 row) + +select max(v) from bytea_test_table; + max +-------- + \xffff +(1 row) + drop table bytea_test_table; -- Test parallel string_agg and array_agg create table pagg_test (x int, y int) with (autovacuum_enabled = off); @@ -2058,8 +2188,8 @@ explain (costs off) select * from v_pagg_test order by y; -> Parallel Seq Scan on pagg_test (13 rows) -set max_parallel_workers_per_gather = 0; -- Ensure results are the same without parallel aggregation. +set max_parallel_workers_per_gather = 0; select * from v_pagg_test order by y; y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- @@ -2075,6 +2205,24 @@ select * from v_pagg_test order by y; 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 (10 rows) +-- Check that we don't fail on anonymous record types. +set max_parallel_workers_per_gather = 2; +explain (costs off) +select array_dims(array_agg(s)) from (select * from pagg_test) s; + QUERY PLAN +-------------------------------------------- + Aggregate + -> Gather + Workers Planned: 2 + -> Parallel Seq Scan on pagg_test +(4 rows) + +select array_dims(array_agg(s)) from (select * from pagg_test) s; + array_dims +------------ + [1:5000] +(1 row) + -- Clean up reset max_parallel_workers_per_gather; reset bytea_output; @@ -2832,29 +2980,27 @@ GROUP BY w, x, z, y; -> Index Scan using btg_x_y_idx on btg (6 rows) --- Utilize the ordering of merge join to avoid a full Sort operation +-- Utilize the ordering of merge join to avoid a Sort operation SET enable_hashjoin = off; SET enable_nestloop = off; EXPLAIN (COSTS OFF) SELECT count(*) - FROM btg t1 JOIN btg t2 ON t1.z = t2.z AND t1.w = t2.w AND t1.x = t2.x - GROUP BY t1.x, t1.y, t1.z, t1.w; - QUERY PLAN -------------------------------------------------------------------------------- + FROM btg t1 JOIN btg t2 ON t1.w = t2.w AND t1.x = t2.x AND t1.z = t2.z + GROUP BY t1.w, t1.z, t1.x; + QUERY PLAN +------------------------------------------------------------------------- GroupAggregate - Group Key: t1.z, t1.w, t1.x, t1.y - -> Incremental Sort - Sort Key: t1.z, t1.w, t1.x, t1.y - Presorted Key: t1.z, t1.w, t1.x - -> Merge Join - Merge Cond: ((t1.z = t2.z) AND (t1.w = t2.w) AND (t1.x = t2.x)) - -> Sort - Sort Key: t1.z, t1.w, t1.x - -> Index Scan using btg_x_y_idx on btg t1 - -> Sort - Sort Key: t2.z, t2.w, t2.x - -> Index Scan using btg_x_y_idx on btg t2 -(13 rows) + Group Key: t1.x, t1.w, t1.z + -> Merge Join + Merge Cond: ((t1.x = t2.x) AND (t1.w = t2.w) AND (t1.z = t2.z)) + -> Incremental Sort + Sort Key: t1.x, t1.w, t1.z + Presorted Key: t1.x + -> Index Scan using btg_x_y_idx on btg t1 + -> Sort + Sort Key: t2.x, t2.w, t2.z + -> Index Scan using btg_x_y_idx on btg t2 +(11 rows) RESET enable_nestloop; RESET enable_hashjoin; @@ -2928,10 +3074,12 @@ GROUP BY c1.w, c1.z; -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(12 rows) + Disabled: true +(14 rows) SELECT avg(c1.f ORDER BY c1.x, c1.y) FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x @@ -2962,10 +3110,12 @@ GROUP BY c1.y,c1.x,c2.x; -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(13 rows) + Disabled: true +(15 rows) EXPLAIN (COSTS OFF) SELECT c1.y,c1.x FROM group_agg_pk c1 @@ -2984,10 +3134,12 @@ GROUP BY c1.y,c2.x,c1.x; -> Sort Sort Key: c1.x -> Seq Scan on group_agg_pk c1 + Disabled: true -> Sort Sort Key: c2.x -> Seq Scan on group_agg_pk c2 -(13 rows) + Disabled: true +(15 rows) RESET enable_nestloop; RESET enable_hashjoin; diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out index ae54cb254f908..23bf33f10a919 100644 --- a/src/test/regress/expected/alter_generic.out +++ b/src/test/regress/expected/alter_generic.out @@ -362,9 +362,9 @@ ERROR: invalid operator number 0, must be between 1 and 5 ALTER OPERATOR FAMILY alt_opf4 USING btree ADD OPERATOR 1 < ; -- operator without argument types ERROR: operator argument types must be specified in ALTER OPERATOR FAMILY ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 0 btint42cmp(int4, int2); -- invalid options parsing function -ERROR: invalid function number 0, must be between 1 and 5 -ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 6 btint42cmp(int4, int2); -- function number should be between 1 and 5 -ERROR: invalid function number 6, must be between 1 and 5 +ERROR: invalid function number 0, must be between 1 and 6 +ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 7 btint42cmp(int4, int2); -- function number should be between 1 and 6 +ERROR: invalid function number 7, must be between 1 and 6 ALTER OPERATOR FAMILY alt_opf4 USING btree ADD STORAGE invalid_storage; -- Ensure STORAGE is not a part of ALTER OPERATOR FAMILY ERROR: STORAGE cannot be specified in ALTER OPERATOR FAMILY DROP OPERATOR FAMILY alt_opf4 USING btree; @@ -420,7 +420,7 @@ BEGIN TRANSACTION; CREATE OPERATOR FAMILY alt_opf12 USING btree; CREATE FUNCTION fn_opf12 (int4, int2) RETURNS BIGINT AS 'SELECT NULL::BIGINT;' LANGUAGE SQL; ALTER OPERATOR FAMILY alt_opf12 USING btree ADD FUNCTION 1 fn_opf12(int4, int2); -ERROR: btree comparison functions must return integer +ERROR: ordering comparison functions must return integer DROP OPERATOR FAMILY alt_opf12 USING btree; ERROR: current transaction is aborted, commands ignored until end of transaction block ROLLBACK; @@ -438,7 +438,7 @@ BEGIN TRANSACTION; CREATE OPERATOR FAMILY alt_opf14 USING btree; CREATE FUNCTION fn_opf14 (int4) RETURNS BIGINT AS 'SELECT NULL::BIGINT;' LANGUAGE SQL; ALTER OPERATOR FAMILY alt_opf14 USING btree ADD FUNCTION 1 fn_opf14(int4); -ERROR: btree comparison functions must have two arguments +ERROR: ordering comparison functions must have two arguments DROP OPERATOR FAMILY alt_opf14 USING btree; ERROR: current transaction is aborted, commands ignored until end of transaction block ROLLBACK; @@ -504,7 +504,11 @@ ALTER OPERATOR FAMILY alt_opf18 USING btree ADD -- Should fail. Not allowed to have cross-type equalimage function. ALTER OPERATOR FAMILY alt_opf18 USING btree ADD FUNCTION 4 (int4, int2) btequalimage(oid); -ERROR: btree equal image functions must not be cross-type +ERROR: ordering equal image functions must not be cross-type +-- Should fail. Not allowed to have cross-type skip support function. +ALTER OPERATOR FAMILY alt_opf18 USING btree + ADD FUNCTION 6 (int4, int2) btint4skipsupport(internal); +ERROR: btree skip support functions must not be cross-type ALTER OPERATOR FAMILY alt_opf18 USING btree DROP FUNCTION 2 (int4, int4); ERROR: function 2(integer,integer) does not exist in operator family "alt_opf18" DROP OPERATOR FAMILY alt_opf18 USING btree; diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 79cf82b5aed12..476266e3f4b03 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -507,11 +507,14 @@ ALTER TABLE attmp3 validate constraint attmpconstr; ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds +ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten_not_enforced CHECK (b > 10) NOT ENFORCED; -- succeeds ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails ERROR: check constraint "b_greater_than_ten" of relation "attmp3" is violated by some row DELETE FROM attmp3 WHERE NOT b > 10; ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds +ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten_not_enforced; -- fail +ERROR: cannot validate NOT ENFORCED constraint -- Test inherited NOT VALID CHECK constraints select * from attmp3; a | b @@ -659,12 +662,12 @@ CREATE TEMP TABLE FKTABLE (ftest1 inet); -- This next should fail, because int=inet does not exist ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- This should also fail for the same reason, but here we -- give the column name ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. DROP TABLE FKTABLE; -- This should succeed, even though they are different types, -- because int=int8 exists and is a member of the integer opfamily @@ -682,7 +685,7 @@ DROP TABLE FKTABLE; CREATE TEMP TABLE FKTABLE (ftest1 numeric); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: numeric and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: numeric and integer. DROP TABLE FKTABLE; DROP TABLE PKTABLE; -- On the other hand, this should work because int implicitly promotes to @@ -704,26 +707,26 @@ CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet, CREATE TEMP TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable; ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: cidr and integer. DROP TABLE FKTABLE; -- Again, so should this... CREATE TEMP TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest1, ptest2); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: cidr and integer. DROP TABLE FKTABLE; -- This fails because we mixed up the column ordering CREATE TEMP TABLE FKTABLE (ftest1 int, ftest2 inet); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable(ptest2, ptest1); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest2" are of incompatible types: integer and inet. +DETAIL: Key columns "ftest1" of the referencing table and "ptest2" of the referenced table are of incompatible types: integer and inet. -- As does this... ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1) references pktable(ptest1, ptest2); ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest2" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. DROP TABLE FKTABLE; DROP TABLE PKTABLE; -- Test that ALTER CONSTRAINT updates trigger deferrability properly @@ -1199,6 +1202,75 @@ alter table atacc1 alter test_a drop not null, alter test_b drop not null; alter table atacc1 add constraint atacc1_constr_b_valid check(test_b is not null); alter table atacc1 alter test_b set not null, alter test_a set not null; drop table atacc1; +-- not null not valid with partitions +CREATE TABLE atnnparted (id int, col1 int) PARTITION BY LIST (id); +ALTER TABLE atnnparted ADD CONSTRAINT dummy_constr NOT NULL id NOT VALID; +CREATE TABLE atnnpart1 (col1 int, id int); +ALTER TABLE atnnpart1 ADD CONSTRAINT another_constr NOT NULL id; +ALTER TABLE atnnpart1 ADD PRIMARY KEY (id); +ALTER TABLE atnnparted ATTACH PARTITION atnnpart1 FOR VALUES IN ('1'); +\d+ atnnpart* + Table "public.atnnpart1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + col1 | integer | | | | plain | | + id | integer | | not null | | plain | | +Partition of: atnnparted FOR VALUES IN (1) +Partition constraint: ((id IS NOT NULL) AND (id = 1)) +Indexes: + "atnnpart1_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "another_constr" NOT NULL "id" (inherited) + + Index "public.atnnpart1_pkey" + Column | Type | Key? | Definition | Storage | Stats target +--------+---------+------+------------+---------+-------------- + id | integer | yes | id | plain | +primary key, btree, for table "public.atnnpart1" + + Partitioned table "public.atnnparted" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + id | integer | | not null | | plain | | + col1 | integer | | | | plain | | +Partition key: LIST (id) +Not-null constraints: + "dummy_constr" NOT NULL "id" NOT VALID +Partitions: atnnpart1 FOR VALUES IN (1) + +BEGIN; +ALTER TABLE atnnparted VALIDATE CONSTRAINT dummy_constr; +\d+ atnnpart* + Table "public.atnnpart1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + col1 | integer | | | | plain | | + id | integer | | not null | | plain | | +Partition of: atnnparted FOR VALUES IN (1) +Partition constraint: ((id IS NOT NULL) AND (id = 1)) +Indexes: + "atnnpart1_pkey" PRIMARY KEY, btree (id) +Not-null constraints: + "another_constr" NOT NULL "id" (inherited) + + Index "public.atnnpart1_pkey" + Column | Type | Key? | Definition | Storage | Stats target +--------+---------+------+------------+---------+-------------- + id | integer | yes | id | plain | +primary key, btree, for table "public.atnnpart1" + + Partitioned table "public.atnnparted" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + id | integer | | not null | | plain | | + col1 | integer | | | | plain | | +Partition key: LIST (id) +Not-null constraints: + "dummy_constr" NOT NULL "id" +Partitions: atnnpart1 FOR VALUES IN (1) + +ROLLBACK; +-- leave a table in this state for the pg_upgrade test -- test inheritance create table parent (a int); create table child (b varchar(255)) inherits (parent); @@ -1216,20 +1288,6 @@ alter table only parent alter a set not null; ERROR: column "a" of relation "parent" contains null values alter table child alter a set not null; ERROR: column "a" of relation "child" contains null values -delete from parent; -alter table only parent alter a set not null; -insert into parent values (NULL); -ERROR: null value in column "a" of relation "parent" violates not-null constraint -DETAIL: Failing row contains (null). -alter table child alter a set not null; -insert into child (a, b) values (NULL, 'foo'); -ERROR: null value in column "a" of relation "child" violates not-null constraint -DETAIL: Failing row contains (null, foo). -delete from child; -alter table child alter a set not null; -insert into child (a, b) values (NULL, 'foo'); -ERROR: null value in column "a" of relation "child" violates not-null constraint -DETAIL: Failing row contains (null, foo). drop table child; drop table parent; -- test setting and removing default values @@ -1703,6 +1761,13 @@ alter table renameColumn add column w int; -- this should fail alter table only renameColumn add column x int; ERROR: column must be added to child tables too +-- this should work +alter table renameColumn add column x int check (x > 0) not enforced; +-- this should fail +alter table renameColumn add column y int check (x > 0) not enforced enforced; +ERROR: multiple ENFORCED/NOT ENFORCED clauses not allowed +LINE 1: ...Column add column y int check (x > 0) not enforced enforced; + ^ -- Test corner cases in dropping of inherited columns create table p1 (f1 int, f2 int); create table c1 (f1 int not null) inherits(p1); @@ -2215,7 +2280,6 @@ select conname, obj_description(oid, 'pg_constraint') as desc (3 rows) alter table at_partitioned alter column name type varchar(127); --- Note: these tests currently show the wrong behavior for comments :-( select relname, c.oid = oldoid as orig_oid, case relfilenode @@ -2232,9 +2296,9 @@ select relname, ------------------------------+----------+---------+-------------- at_partitioned | t | none | at_partitioned_0 | t | own | - at_partitioned_0_id_name_key | f | own | parent index + at_partitioned_0_id_name_key | f | own | at_partitioned_1 | t | own | - at_partitioned_1_id_name_key | f | own | parent index + at_partitioned_1_id_name_key | f | own | at_partitioned_id_name_key | f | none | parent index (6 rows) @@ -2834,6 +2898,8 @@ select * from my_locks order by 1; rollback; begin; +create function ttdummy () returns trigger language plpgsql as +$$ begin return new; end $$; create trigger ttdummy before delete or update on alterlock for each row @@ -3386,6 +3452,7 @@ DROP TABLE tt9; -- Check that comments on constraints and indexes are not lost at ALTER TABLE. CREATE TABLE comment_test ( id int, + constraint id_notnull_constraint not null id, positive_col int CHECK (positive_col > 0), indexed_col int, CONSTRAINT comment_test_pk PRIMARY KEY (id)); @@ -3394,6 +3461,7 @@ COMMENT ON COLUMN comment_test.id IS 'Column ''id'' on comment_test'; COMMENT ON INDEX comment_test_index IS 'Simple index on comment_test'; COMMENT ON CONSTRAINT comment_test_positive_col_check ON comment_test IS 'CHECK constraint on comment_test.positive_col'; COMMENT ON CONSTRAINT comment_test_pk ON comment_test IS 'PRIMARY KEY constraint of comment_test'; +COMMENT ON CONSTRAINT id_notnull_constraint ON comment_test IS 'NOT NULL constraint of comment_test'; COMMENT ON INDEX comment_test_pk IS 'Index backing the PRIMARY KEY of comment_test'; SELECT col_description('comment_test'::regclass, 1) as comment; comment @@ -3413,7 +3481,8 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F ---------------------------------+----------------------------------------------- comment_test_pk | PRIMARY KEY constraint of comment_test comment_test_positive_col_check | CHECK constraint on comment_test.positive_col -(2 rows) + id_notnull_constraint | NOT NULL constraint of comment_test +(3 rows) -- Change the datatype of all the columns. ALTER TABLE is optimized to not -- rebuild an index if the new data type is binary compatible with the old @@ -3425,6 +3494,19 @@ ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE int; ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE text; ALTER TABLE comment_test ALTER COLUMN positive_col SET DATA TYPE int; ALTER TABLE comment_test ALTER COLUMN positive_col SET DATA TYPE bigint; +-- Some error cases. +ALTER TABLE comment_test ALTER COLUMN xmin SET DATA TYPE x; +ERROR: cannot alter system column "xmin" +LINE 1: ALTER TABLE comment_test ALTER COLUMN xmin SET DATA TYPE x; + ^ +ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE x; +ERROR: type "x" does not exist +LINE 1: ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE x; + ^ +ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE int COLLATE "C"; +ERROR: collations are not supported by type integer +LINE 1: ...LE comment_test ALTER COLUMN id SET DATA TYPE int COLLATE "C... + ^ -- Check that the comments are intact. SELECT col_description('comment_test'::regclass, 1) as comment; comment @@ -3444,7 +3526,8 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F ---------------------------------+----------------------------------------------- comment_test_pk | PRIMARY KEY constraint of comment_test comment_test_positive_col_check | CHECK constraint on comment_test.positive_col -(2 rows) + id_notnull_constraint | NOT NULL constraint of comment_test +(3 rows) -- Check compatibility for foreign keys and comments. This is done -- separately as rebuilding the column type of the parent leads @@ -3459,7 +3542,7 @@ COMMENT ON CONSTRAINT comment_test_child_fk ON comment_test_child IS 'FOREIGN KE ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE text; ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE int USING id::integer; ERROR: foreign key constraint "comment_test_child_fk" cannot be implemented -DETAIL: Key columns "id" and "id" are of incompatible types: text and integer. +DETAIL: Key columns "id" of the referencing table and "id" of the referenced table are of incompatible types: text and integer. -- Comments should be intact SELECT col_description('comment_test_child'::regclass, 1) as comment; comment @@ -3860,6 +3943,9 @@ CREATE TABLE atnotnull1 (); ALTER TABLE atnotnull1 ADD COLUMN a INT, ALTER a SET NOT NULL; +ALTER TABLE atnotnull1 + ADD COLUMN b INT, + ADD NOT NULL b; ALTER TABLE atnotnull1 ADD COLUMN c INT, ADD PRIMARY KEY (c); @@ -3868,9 +3954,14 @@ ALTER TABLE atnotnull1 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description --------+---------+-----------+----------+---------+---------+--------------+------------- a | integer | | not null | | plain | | + b | integer | | not null | | plain | | c | integer | | not null | | plain | | Indexes: "atnotnull1_pkey" PRIMARY KEY, btree (c) +Not-null constraints: + "atnotnull1_a_not_null" NOT NULL "a" + "atnotnull1_b_not_null" NOT NULL "b" + "atnotnull1_c_not_null" NOT NULL "c" -- cannot drop column that is part of the partition key CREATE TABLE partitioned ( @@ -3881,10 +3972,14 @@ ALTER TABLE partitioned DROP COLUMN a; ERROR: cannot drop column "a" because it is part of the partition key of relation "partitioned" ALTER TABLE partitioned ALTER COLUMN a TYPE char(5); ERROR: cannot alter column "a" because it is part of the partition key of relation "partitioned" +LINE 1: ALTER TABLE partitioned ALTER COLUMN a TYPE char(5); + ^ ALTER TABLE partitioned DROP COLUMN b; ERROR: cannot drop column "b" because it is part of the partition key of relation "partitioned" ALTER TABLE partitioned ALTER COLUMN b TYPE char(5); ERROR: cannot alter column "b" because it is part of the partition key of relation "partitioned" +LINE 1: ALTER TABLE partitioned ALTER COLUMN b TYPE char(5); + ^ -- specifying storage parameters for partitioned tables is not supported ALTER TABLE partitioned SET (fillfactor=100); ERROR: cannot specify storage parameters for a partitioned table @@ -3911,7 +4006,8 @@ CREATE TABLE unparted ( ); CREATE TABLE fail_part (like unparted); ALTER TABLE unparted ATTACH PARTITION fail_part FOR VALUES IN ('a'); -ERROR: table "unparted" is not partitioned +ERROR: ALTER action ATTACH PARTITION cannot be performed on relation "unparted" +DETAIL: This operation is not supported for tables. DROP TABLE unparted, fail_part; -- check that partition bound is compatible CREATE TABLE list_parted ( @@ -4028,6 +4124,14 @@ SELECT conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_1'::reg f | 1 (1 row) +-- check that NOT NULL NO INHERIT cannot be merged to a normal NOT NULL +CREATE TABLE part_fail (a int NOT NULL NO INHERIT, + b char(2) COLLATE "C", + CONSTRAINT check_a CHECK (a > 0) +); +ALTER TABLE list_parted ATTACH PARTITION part_fail FOR VALUES IN (2); +ERROR: constraint "part_fail_a_not_null" conflicts with non-inherited constraint on child table "part_fail" +DROP TABLE part_fail; -- check that the new partition won't overlap with an existing partition CREATE TABLE fail_part (LIKE part_1 INCLUDING CONSTRAINTS); ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); @@ -4281,7 +4385,14 @@ DROP TABLE fail_part; -- check that the table is partitioned at all CREATE TABLE regular_table (a int); ALTER TABLE regular_table DETACH PARTITION any_name; -ERROR: table "regular_table" is not partitioned +ERROR: ALTER action DETACH PARTITION cannot be performed on relation "regular_table" +DETAIL: This operation is not supported for tables. +ALTER TABLE regular_table DETACH PARTITION any_name CONCURRENTLY; +ERROR: ALTER action DETACH PARTITION cannot be performed on relation "regular_table" +DETAIL: This operation is not supported for tables. +ALTER TABLE regular_table DETACH PARTITION any_name FINALIZE; +ERROR: ALTER action DETACH PARTITION ... FINALIZE cannot be performed on relation "regular_table" +DETAIL: This operation is not supported for tables. DROP TABLE regular_table; -- check that the partition being detached exists at all ALTER TABLE list_parted2 DETACH PARTITION part_4; @@ -4393,28 +4504,38 @@ ALTER TABLE part_2 RENAME COLUMN b to c; ERROR: cannot rename inherited column "b" ALTER TABLE part_2 ALTER COLUMN b TYPE text; ERROR: cannot alter inherited column "b" --- cannot add/drop NOT NULL or check constraints to *only* the parent, when +LINE 1: ALTER TABLE part_2 ALTER COLUMN b TYPE text; + ^ +-- cannot add NOT NULL or check constraints to *only* the parent, when -- partitions exist ALTER TABLE ONLY list_parted2 ALTER b SET NOT NULL; ERROR: constraint must be added to child tables too -DETAIL: Column "b" of relation "part_2" is not already NOT NULL. HINT: Do not specify the ONLY keyword. ALTER TABLE ONLY list_parted2 ADD CONSTRAINT check_b CHECK (b <> 'zz'); ERROR: constraint must be added to child tables too +-- dropping them is ok though ALTER TABLE list_parted2 ALTER b SET NOT NULL; ALTER TABLE ONLY list_parted2 ALTER b DROP NOT NULL; -ERROR: cannot remove constraint from only the partitioned table when partitions exist -HINT: Do not specify the ONLY keyword. ALTER TABLE list_parted2 ADD CONSTRAINT check_b CHECK (b <> 'zz'); ALTER TABLE ONLY list_parted2 DROP CONSTRAINT check_b; -ERROR: cannot remove constraint from only the partitioned table when partitions exist -HINT: Do not specify the ONLY keyword. +-- ... and the partitions should still have both +\d+ part_2 + Table "public.part_2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+--------------+-----------+----------+---------+----------+--------------+------------- + a | integer | | | | plain | | + b | character(1) | | not null | | extended | | +Partition of: list_parted2 FOR VALUES IN (2) +Partition constraint: ((a IS NOT NULL) AND (a = 2)) +Check constraints: + "check_b" CHECK (b <> 'zz'::bpchar) +Not-null constraints: + "list_parted2_b_not_null" NOT NULL "b" + -- It's alright though, if no partitions are yet created CREATE TABLE parted_no_parts (a int) PARTITION BY LIST (a); ALTER TABLE ONLY parted_no_parts ALTER a SET NOT NULL; ALTER TABLE ONLY parted_no_parts ADD CONSTRAINT check_a CHECK (a > 0); -ALTER TABLE ONLY parted_no_parts ALTER a DROP NOT NULL; -ALTER TABLE ONLY parted_no_parts DROP CONSTRAINT check_a; DROP TABLE parted_no_parts; -- cannot drop inherited NOT NULL or check constraints from partition ALTER TABLE list_parted2 ALTER b SET NOT NULL, ADD CONSTRAINT check_a2 CHECK (a > 0); @@ -4422,6 +4543,12 @@ ALTER TABLE part_2 ALTER b DROP NOT NULL; ERROR: column "b" is marked NOT NULL in parent table ALTER TABLE part_2 DROP CONSTRAINT check_a2; ERROR: cannot drop inherited constraint "check_a2" of relation "part_2" +-- can't drop NOT NULL from under an invalid PK +CREATE TABLE list_parted3 (a int NOT NULL) PARTITION BY LIST (a); +CREATE TABLE list_parted3_1 PARTITION OF list_parted3 FOR VALUES IN (1); +ALTER TABLE ONLY list_parted3 ADD PRIMARY KEY (a); +ALTER TABLE ONLY list_parted3 DROP CONSTRAINT list_parted3_a_not_null; +ERROR: column "a" is in a primary key -- Doesn't make sense to add NO INHERIT constraints on partitioned tables ALTER TABLE list_parted2 add constraint check_b2 check (b <> 'zz') NO INHERIT; ERROR: cannot add NO INHERIT constraint to partitioned table "list_parted2" @@ -4440,6 +4567,8 @@ ALTER TABLE list_parted2 DROP COLUMN b; ERROR: cannot drop column "b" because it is part of the partition key of relation "part_5" ALTER TABLE list_parted2 ALTER COLUMN b TYPE text; ERROR: cannot alter column "b" because it is part of the partition key of relation "part_5" +LINE 1: ALTER TABLE list_parted2 ALTER COLUMN b TYPE text; + ^ -- dropping non-partition key columns should be allowed on the parent table. ALTER TABLE list_parted DROP COLUMN b; SELECT * FROM list_parted; @@ -4448,7 +4577,7 @@ SELECT * FROM list_parted; (0 rows) -- cleanup -DROP TABLE list_parted, list_parted2, range_parted; +DROP TABLE list_parted, list_parted2, range_parted, list_parted3; DROP TABLE fail_def_part; DROP TABLE hash_parted; -- more tests for certain multi-level partitioning scenarios diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index a6d81fd5f9284..b815473f414b2 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -2457,6 +2457,132 @@ select array(select array['Hello', i::text] from generate_series(9,11) i); {{Hello,9},{Hello,10},{Hello,11}} (1 row) +-- int2vector and oidvector should be treated as scalar types for this purpose +select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5))); + pg_typeof +-------------- + int2vector[] +(1 row) + +select array(select '11 22 33'::int2vector from generate_series(1,5)); + array +---------------------------------------------------------- + {"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"} +(1 row) + +select unnest(array(select '11 22 33'::int2vector from generate_series(1,5))); + unnest +---------- + 11 22 33 + 11 22 33 + 11 22 33 + 11 22 33 + 11 22 33 +(5 rows) + +select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5))); + pg_typeof +------------- + oidvector[] +(1 row) + +select array(select '11 22 33'::oidvector from generate_series(1,5)); + array +---------------------------------------------------------- + {"11 22 33","11 22 33","11 22 33","11 22 33","11 22 33"} +(1 row) + +select unnest(array(select '11 22 33'::oidvector from generate_series(1,5))); + unnest +---------- + 11 22 33 + 11 22 33 + 11 22 33 + 11 22 33 + 11 22 33 +(5 rows) + +-- array[] should do the same +select pg_typeof(array['11 22 33'::int2vector]); + pg_typeof +-------------- + int2vector[] +(1 row) + +select array['11 22 33'::int2vector]; + array +-------------- + {"11 22 33"} +(1 row) + +select pg_typeof(unnest(array['11 22 33'::int2vector])); + pg_typeof +------------ + int2vector +(1 row) + +select unnest(array['11 22 33'::int2vector]); + unnest +---------- + 11 22 33 +(1 row) + +select pg_typeof(unnest('11 22 33'::int2vector)); + pg_typeof +----------- + smallint + smallint + smallint +(3 rows) + +select unnest('11 22 33'::int2vector); + unnest +-------- + 11 + 22 + 33 +(3 rows) + +select pg_typeof(array['11 22 33'::oidvector]); + pg_typeof +------------- + oidvector[] +(1 row) + +select array['11 22 33'::oidvector]; + array +-------------- + {"11 22 33"} +(1 row) + +select pg_typeof(unnest(array['11 22 33'::oidvector])); + pg_typeof +----------- + oidvector +(1 row) + +select unnest(array['11 22 33'::oidvector]); + unnest +---------- + 11 22 33 +(1 row) + +select pg_typeof(unnest('11 22 33'::oidvector)); + pg_typeof +----------- + oid + oid + oid +(3 rows) + +select unnest('11 22 33'::oidvector); + unnest +-------- + 11 + 22 + 33 +(3 rows) + -- Insert/update on a column that is array of composite create temp table t1 (f1 int8_tbl[]); insert into t1 (f1[5].q1) values(42); @@ -2703,3 +2829,176 @@ SELECT array_sample('{1,2,3,4,5,6}'::int[], -1); -- fail ERROR: sample size must be between 0 and 6 SELECT array_sample('{1,2,3,4,5,6}'::int[], 7); --fail ERROR: sample size must be between 0 and 6 +-- array_reverse +SELECT array_reverse('{}'::int[]); + array_reverse +--------------- + {} +(1 row) + +SELECT array_reverse('{1}'::int[]); + array_reverse +--------------- + {1} +(1 row) + +SELECT array_reverse('{1,2}'::int[]); + array_reverse +--------------- + {2,1} +(1 row) + +SELECT array_reverse('{1,2,3,NULL,4,5,6}'::int[]); + array_reverse +-------------------- + {6,5,4,NULL,3,2,1} +(1 row) + +SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); + array_reverse +--------------------------- + {{7,8},{5,6},{3,4},{1,2}} +(1 row) + +-- array_sort +SELECT array_sort('{}'::int[]); + array_sort +------------ + {} +(1 row) + +SELECT array_sort('{1}'::int[]); + array_sort +------------ + {1} +(1 row) + +SELECT array_sort('{1,3,5,2,4,6}'::int[]); + array_sort +--------------- + {1,2,3,4,5,6} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,4.4,6.6}'::numeric[]); + array_sort +--------------------------- + {1.1,2.2,3.3,4.4,5.5,6.6} +(1 row) + +SELECT array_sort('{foo,bar,CCC,Abc,bbc}'::text[] COLLATE "C"); + array_sort +----------------------- + {Abc,CCC,bar,bbc,foo} +(1 row) + +SELECT array_sort('{foo,bar,null,CCC,Abc,bbc}'::text[] COLLATE "C"); + array_sort +---------------------------- + {Abc,CCC,bar,bbc,foo,NULL} +(1 row) + +SELECT array_sort(ARRAY(SELECT '1 4'::int2vector UNION ALL SELECT '1 2'::int2vector)); + array_sort +--------------- + {"1 2","1 4"} +(1 row) + +-- array_sort with order specified +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true); + array_sort +-------------------------------- + {NULL,6.6,5.5,4.4,3.3,2.2,1.1} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false); + array_sort +-------------------------------- + {1.1,2.2,3.3,4.4,5.5,6.6,NULL} +(1 row) + +-- array_sort with order and nullsfirst flag specified +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true, true); + array_sort +-------------------------------- + {NULL,6.6,5.5,4.4,3.3,2.2,1.1} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true, false); + array_sort +-------------------------------- + {6.6,5.5,4.4,3.3,2.2,1.1,NULL} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false, true); + array_sort +-------------------------------- + {NULL,1.1,2.2,3.3,4.4,5.5,6.6} +(1 row) + +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false, false); + array_sort +-------------------------------- + {1.1,2.2,3.3,4.4,5.5,6.6,NULL} +(1 row) + +-- multidimensional array tests +SELECT array_sort('{{1}}'::int[]); + array_sort +------------ + {{1}} +(1 row) + +SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); + array_sort +--------------------- + {{2,1},{2,4},{6,5}} +(1 row) + +SELECT array_sort('{{"1 2","3 4"}, {"1 -2","-1 4"}}'::int2vector[]); + array_sort +--------------------------------- + {{"1 -2","-1 4"},{"1 2","3 4"}} +(1 row) + +-- no ordering operator tests +SELECT array_sort('{1}'::xid[]); -- no error because no sort is required + array_sort +------------ + {1} +(1 row) + +SELECT array_sort('{1,2,3}'::xid[]); +ERROR: could not identify a comparison function for type xid +SELECT array_sort('{{1,2,3},{2,3,4}}'::xid[]); +ERROR: could not identify a comparison function for type xid +-- bounds preservation tests +SELECT array_sort(a) FROM (VALUES ('[10:12][20:21]={{1,2},{10,20},{3,4}}'::int[])) v(a); + array_sort +-------------------------------------- + [10:12][20:21]={{1,2},{3,4},{10,20}} +(1 row) + +SELECT array_sort(a) FROM (VALUES ('[-1:0]={7,1}'::int[])) v(a); + array_sort +-------------- + [-1:0]={1,7} +(1 row) + +SELECT array_sort(a) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); + array_sort +-------------------------------------- + [-2:0][20:21]={{1,-4},{1,2},{10,20}} +(1 row) + +SELECT array_sort(a [-1:0]) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); + array_sort +------------------ + {{1,-4},{10,20}} +(1 row) + +SELECT array_sort(a [-1:0][20:20]) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); + array_sort +------------ + {{1},{10}} +(1 row) + diff --git a/src/test/regress/expected/bitmapops.out b/src/test/regress/expected/bitmapops.out index 3570973e3caa5..64068e0469c52 100644 --- a/src/test/regress/expected/bitmapops.out +++ b/src/test/regress/expected/bitmapops.out @@ -8,7 +8,7 @@ -- there's a maximum number of a,b combinations in the table. -- That allows us to test all the different combinations of -- lossy and non-lossy pages with the minimum amount of data -CREATE TABLE bmscantest (a int, b int, t text); +CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false); INSERT INTO bmscantest SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' FROM generate_series(1,70000) r; @@ -20,7 +20,17 @@ set enable_indexscan=false; set enable_seqscan=false; -- Lower work_mem to trigger use of lossy bitmaps set work_mem = 64; --- Test bitmap-and. +-- Test bitmap-and without the skip fetch optimization. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + count +------- + 23 +(1 row) + +-- Test that we return correct results when using the skip fetch optimization +-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling +-- the optimization. +VACUUM (FREEZE) bmscantest; SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; count ------- diff --git a/src/test/regress/expected/box.out b/src/test/regress/expected/box.out index 8c9e9e3935561..10760870ce7ce 100644 --- a/src/test/regress/expected/box.out +++ b/src/test/regress/expected/box.out @@ -594,12 +594,13 @@ SET enable_bitmapscan = OFF; EXPLAIN (COSTS OFF) SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id FROM quad_box_tbl; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (b <-> '(123,456)'::point) ROWS UNBOUNDED PRECEDING) -> Index Scan using quad_box_tbl_idx on quad_box_tbl Order By: (b <-> '(123,456)'::point) -(3 rows) +(4 rows) CREATE TEMP TABLE quad_box_tbl_ord_idx1 AS SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id @@ -616,13 +617,14 @@ WHERE seq.id IS NULL OR idx.id IS NULL; EXPLAIN (COSTS OFF) SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id FROM quad_box_tbl WHERE b <@ box '((200,300),(500,600))'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (b <-> '(123,456)'::point) ROWS UNBOUNDED PRECEDING) -> Index Scan using quad_box_tbl_idx on quad_box_tbl Index Cond: (b <@ '(500,600),(200,300)'::box) Order By: (b <-> '(123,456)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE quad_box_tbl_ord_idx2 AS SELECT rank() OVER (ORDER BY b <-> point '123,456') n, b <-> point '123,456' dist, id diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out index d6779d8c7d21a..e1db2280cf92e 100644 --- a/src/test/regress/expected/brin.out +++ b/src/test/regress/expected/brin.out @@ -567,6 +567,16 @@ SELECT * FROM brintest_3 WHERE b < '0'; DROP TABLE brintest_3; RESET enable_seqscan; +-- test parallel build with immutable function. +CREATE TABLE brintest_expr (n int); +CREATE FUNCTION brintest_func() RETURNS int LANGUAGE sql IMMUTABLE RETURN 0; +BEGIN; +SET LOCAL min_parallel_table_scan_size = 0; +SET LOCAL max_parallel_maintenance_workers = 4; +CREATE INDEX brintest_expr_idx ON brintest_expr USING brin (brintest_func()); +COMMIT; +DROP TABLE brintest_expr; +DROP FUNCTION brintest_func(); -- test an unlogged table, mostly to get coverage of brinbuildempty CREATE UNLOGGED TABLE brintest_unlogged (n numrange); CREATE INDEX brinidx_unlogged ON brintest_unlogged USING brin (n); diff --git a/src/test/regress/expected/brin_multi.out b/src/test/regress/expected/brin_multi.out index ae9ce9d8ecfe2..cb5b5e53e867c 100644 --- a/src/test/regress/expected/brin_multi.out +++ b/src/test/regress/expected/brin_multi.out @@ -845,15 +845,16 @@ INSERT INTO brin_date_test SELECT '5874897-12-01'::date + i FROM generate_series CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_per_range=1); SET enable_seqscan = off; -- make sure the ranges were built correctly and 2023-01-01 eliminates all -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; - QUERY PLAN -------------------------------------------------------------------------- - Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1) Recheck Cond: (a = '2023-01-01'::date) - -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '2023-01-01'::date) -(4 rows) + Index Searches: 1 +(5 rows) DROP TABLE brin_date_test; RESET enable_seqscan; @@ -864,25 +865,27 @@ INSERT INTO brin_timestamp_test SELECT i FROM generate_series('2000-01-01'::timestamp, '2000-02-09'::timestamp, '1 day'::interval) s(i); CREATE INDEX ON brin_timestamp_test USING brin (a timestamp_minmax_multi_ops) WITH (pages_per_range=1); SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_timestamp_test WHERE a = '2023-01-01'::timestamp; - QUERY PLAN ------------------------------------------------------------------------------- - Bitmap Heap Scan on brin_timestamp_test (actual rows=0 loops=1) + QUERY PLAN +--------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_timestamp_test (actual rows=0.00 loops=1) Recheck Cond: (a = '2023-01-01 00:00:00'::timestamp without time zone) - -> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '2023-01-01 00:00:00'::timestamp without time zone) -(4 rows) + Index Searches: 1 +(5 rows) -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_timestamp_test WHERE a = '1900-01-01'::timestamp; - QUERY PLAN ------------------------------------------------------------------------------- - Bitmap Heap Scan on brin_timestamp_test (actual rows=0 loops=1) + QUERY PLAN +--------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_timestamp_test (actual rows=0.00 loops=1) Recheck Cond: (a = '1900-01-01 00:00:00'::timestamp without time zone) - -> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_timestamp_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '1900-01-01 00:00:00'::timestamp without time zone) -(4 rows) + Index Searches: 1 +(5 rows) DROP TABLE brin_timestamp_test; RESET enable_seqscan; @@ -892,25 +895,27 @@ INSERT INTO brin_date_test VALUES ('-infinity'), ('infinity'); INSERT INTO brin_date_test SELECT '2000-01-01'::date + i FROM generate_series(1, 40) s(i); CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_per_range=1); SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; - QUERY PLAN -------------------------------------------------------------------------- - Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1) Recheck Cond: (a = '2023-01-01'::date) - -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '2023-01-01'::date) -(4 rows) + Index Searches: 1 +(5 rows) -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '1900-01-01'::date; - QUERY PLAN -------------------------------------------------------------------------- - Bitmap Heap Scan on brin_date_test (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Bitmap Heap Scan on brin_date_test (actual rows=0.00 loops=1) Recheck Cond: (a = '1900-01-01'::date) - -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_date_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '1900-01-01'::date) -(4 rows) + Index Searches: 1 +(5 rows) DROP TABLE brin_date_test; RESET enable_seqscan; @@ -921,25 +926,27 @@ INSERT INTO brin_interval_test SELECT (i || ' years')::interval FROM generate_se INSERT INTO brin_interval_test SELECT (i || ' years')::interval FROM generate_series( 177999980, 178000000) s(i); CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH (pages_per_range=1); SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval; - QUERY PLAN ------------------------------------------------------------------------------ - Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1) Recheck Cond: (a = '@ 30 years ago'::interval) - -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '@ 30 years ago'::interval) -(4 rows) + Index Searches: 1 +(5 rows) -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '30 years'::interval; - QUERY PLAN ------------------------------------------------------------------------------ - Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1) Recheck Cond: (a = '@ 30 years'::interval) - -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '@ 30 years'::interval) -(4 rows) + Index Searches: 1 +(5 rows) DROP TABLE brin_interval_test; RESET enable_seqscan; @@ -949,25 +956,27 @@ INSERT INTO brin_interval_test VALUES ('-infinity'), ('infinity'); INSERT INTO brin_interval_test SELECT (i || ' days')::interval FROM generate_series(100, 140) s(i); CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH (pages_per_range=1); SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval; - QUERY PLAN ------------------------------------------------------------------------------ - Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1) Recheck Cond: (a = '@ 30 years ago'::interval) - -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '@ 30 years ago'::interval) -(4 rows) + Index Searches: 1 +(5 rows) -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '30 years'::interval; - QUERY PLAN ------------------------------------------------------------------------------ - Bitmap Heap Scan on brin_interval_test (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------------------------- + Bitmap Heap Scan on brin_interval_test (actual rows=0.00 loops=1) Recheck Cond: (a = '@ 30 years'::interval) - -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on brin_interval_test_a_idx (actual rows=0.00 loops=1) Index Cond: (a = '@ 30 years'::interval) -(4 rows) + Index Searches: 1 +(5 rows) DROP TABLE brin_interval_test; RESET enable_seqscan; diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out index 510646cbce71b..bfb1a286ea4ad 100644 --- a/src/test/regress/expected/btree_index.out +++ b/src/test/regress/expected/btree_index.out @@ -142,6 +142,133 @@ SELECT b.* 4500 | 2080851358 (1 row) +-- +-- Add coverage of RowCompare quals whose row omits a column ("proargtypes") +-- that's after the first column, but before the final column. The scan's +-- initial positioning strategy must become >= here (it's not the > strategy, +-- since the absence of "proargtypes" makes that tighter constraint unsafe). +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) > ('abs', 0) +ORDER BY proname, proargtypes, pronamespace LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------- + Limit + -> Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc + Index Cond: (ROW(proname, pronamespace) > ROW('abs'::name, '0'::oid)) +(3 rows) + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) > ('abs', 0) +ORDER BY proname, proargtypes, pronamespace LIMIT 1; + proname | proargtypes | pronamespace +---------+-------------+-------------- + abs | 20 | 11 +(1 row) + +-- +-- Similar to the previous test case, but this time it's a backwards scan +-- using a < RowCompare. Must use the <= strategy (and not the < strategy). +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) < ('abs', 1_000_000) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------- + Limit + -> Index Only Scan Backward using pg_proc_proname_args_nsp_index on pg_proc + Index Cond: (ROW(proname, pronamespace) < ROW('abs'::name, '1000000'::oid)) +(3 rows) + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) < ('abs', 1_000_000) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1; + proname | proargtypes | pronamespace +---------+-------------+-------------- + abs | 1700 | 11 +(1 row) + +-- +-- Add coverage for RowCompare quals whose rhs row has a NULL that ends scan +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL) +ORDER BY proname, proargtypes, pronamespace; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc + Index Cond: ((ROW(proname, proargtypes) < ROW('abs'::name, NULL::oidvector)) AND (proname = 'abs'::name)) +(2 rows) + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL) +ORDER BY proname, proargtypes, pronamespace; + proname | proargtypes | pronamespace +---------+-------------+-------------- +(0 rows) + +-- +-- Add coverage for backwards scan RowCompare quals whose rhs row has a NULL +-- that ends scan +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Index Only Scan Backward using pg_proc_proname_args_nsp_index on pg_proc + Index Cond: ((ROW(proname, proargtypes) > ROW('abs'::name, NULL::oidvector)) AND (proname = 'abs'::name)) +(2 rows) + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC; + proname | proargtypes | pronamespace +---------+-------------+-------------- +(0 rows) + +-- +-- Add coverage for recheck of > key following array advancement on previous +-- (left sibling) page that used a high key whose attribute value corresponding +-- to the > key was -inf (due to being truncated when the high key was created). +-- +-- XXX This relies on the assumption that tenk1_thous_tenthous has a truncated +-- high key "(183, -inf)" on the first page that we'll scan. The test will only +-- provide useful coverage when the default 8K BLCKSZ is in use. +-- +explain (costs off) +SELECT thousand, tenthous + FROM tenk1 + WHERE thousand IN (182, 183) AND tenthous > 7550; + QUERY PLAN +--------------------------------------------------------------------------------- + Index Only Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand = ANY ('{182,183}'::integer[])) AND (tenthous > 7550)) +(2 rows) + +SELECT thousand, tenthous + FROM tenk1 + WHERE thousand IN (182, 183) AND tenthous > 7550; + thousand | tenthous +----------+---------- + 182 | 8182 + 182 | 9182 + 183 | 8183 + 183 | 9183 +(4 rows) + -- -- Add coverage for optimization of backwards scan index descents -- @@ -332,11 +459,14 @@ select proname from pg_proc where proname ilike '00%foo' order by 1; explain (costs off) select proname from pg_proc where proname ilike 'ri%foo' order by 1; - QUERY PLAN ------------------------------------------------------------------ - Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc - Filter: (proname ~~* 'ri%foo'::text) -(2 rows) + QUERY PLAN +---------------------------------------------- + Sort + Sort Key: proname + -> Seq Scan on pg_proc + Disabled: true + Filter: (proname ~~* 'ri%foo'::text) +(5 rows) reset enable_seqscan; reset enable_indexscan; @@ -451,6 +581,47 @@ alter table btree_tall_tbl alter COLUMN t set storage plain; create index btree_tall_idx on btree_tall_tbl (t, id) with (fillfactor = 10); insert into btree_tall_tbl select g, repeat('x', 250) from generate_series(1, 130) g; +insert into btree_tall_tbl select g, NULL +from generate_series(50, 60) g; +-- +-- Test for skip scan with type that lacks skip support (text) +-- +set enable_seqscan to false; +set enable_bitmapscan to false; +-- Forwards scan +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t, id; + id +---- + 55 + 55 +(2 rows) + +explain (costs off) +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t, id; + QUERY PLAN +-------------------------------------------------------- + Index Only Scan using btree_tall_idx on btree_tall_tbl + Index Cond: (id = 55) +(2 rows) + +-- Backwards scan +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t DESC, id DESC; + id +---- + 55 + 55 +(2 rows) + +explain (costs off) +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t DESC, id DESC; + QUERY PLAN +----------------------------------------------------------------- + Index Only Scan Backward using btree_tall_idx on btree_tall_tbl + Index Cond: (id = 55) +(2 rows) + +reset enable_seqscan; +reset enable_bitmapscan; -- -- Test for multilevel page deletion -- @@ -472,6 +643,16 @@ INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,1000) i; -- Test unsupported btree opclass parameters create index on btree_tall_tbl (id int4_ops(foo=1)); ERROR: operator class int4_ops has no options +-- test parallel build with immutable function. +CREATE TABLE btree_test_expr (n int); +CREATE FUNCTION btree_test_func() RETURNS int LANGUAGE sql IMMUTABLE RETURN 0; +BEGIN; +SET LOCAL min_parallel_table_scan_size = 0; +SET LOCAL max_parallel_maintenance_workers = 4; +CREATE INDEX btree_test_expr_idx ON btree_test_expr USING btree (btree_test_func()); +COMMIT; +DROP TABLE btree_test_expr; +DROP FUNCTION btree_test_func(); -- Test case of ALTER INDEX with abuse of column names for indexes. -- This grammar is not officially supported, but the parser allows it. CREATE INDEX btree_tall_idx2 ON btree_tall_tbl (id); diff --git a/src/test/regress/expected/case.out b/src/test/regress/expected/case.out index f5136c17abbf0..efee7fc43173b 100644 --- a/src/test/regress/expected/case.out +++ b/src/test/regress/expected/case.out @@ -397,6 +397,14 @@ SELECT CASE make_ad(1,2) right (1 row) +-- While we're here, also test handling of a NULLIF arg that is a read/write +-- object (bug #18722) +SELECT NULLIF(make_ad(1,2), array[2,3]::arrdomain); + nullif +-------- + {1,2} +(1 row) + ROLLBACK; -- Test interaction of CASE with ArrayCoerceExpr (bug #15471) BEGIN; diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out index a13aafff0b69e..4d40a6809ab46 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -247,11 +247,12 @@ ERROR: insert or update on table "clstr_tst" violates foreign key constraint "c DETAIL: Key (b)=(1111) is not present in table "clstr_tst_s". SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass ORDER BY 1; - conname ----------------- + conname +---------------------- + clstr_tst_a_not_null clstr_tst_con clstr_tst_pkey -(2 rows) +(3 rows) SELECT relname, relkind, EXISTS(SELECT 1 FROM pg_class WHERE oid = c.reltoastrelid) AS hastoast diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index 7d59fb4431657..69805d4b9ec53 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -120,6 +120,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e... CREATE DOMAIN testdomain_sv AS text COLLATE "sv-x-icu"; CREATE DOMAIN testdomain_i AS int COLLATE "sv-x-icu"; -- fails ERROR: collations are not supported by type integer +LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv-x-icu"; + ^ CREATE TABLE collate_test4 ( a int, b testdomain_sv @@ -253,6 +255,30 @@ SELECT a, x, y FROM collate_test10 ORDER BY lower(y), a; 1 | hij | hij (2 rows) +SELECT lower('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "en-x-icu"); + lower +------------------------------- + abcd 123 #$% ıiii̇ ß ß dždždž σσς +(1 row) + +SELECT casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "en-x-icu"); + casefold +--------------------------------- + abcd 123 #$% ıiii̇ ss ss dždždž σσσ +(1 row) + +SELECT lower('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "tr-x-icu"); + lower +------------------------------- + abcd 123 #$% ıiıi ß ß dždždž σσς +(1 row) + +SELECT casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "tr-x-icu"); + casefold +--------------------------------- + abcd 123 #$% ıiıi ss ss dždždž σσσ +(1 row) + -- LIKE/ILIKE SELECT * FROM collate_test1 WHERE b LIKE 'abc'; a | b @@ -989,8 +1015,9 @@ select * from collate_test1 where b ilike 'abc'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 + Disabled: true Filter: (b ~~* 'abc'::text) -(2 rows) +(3 rows) select * from collate_test1 where b ilike 'abc'; a | b @@ -1004,8 +1031,9 @@ select * from collate_test1 where b ilike 'ABC'; QUERY PLAN ------------------------------- Seq Scan on collate_test1 + Disabled: true Filter: (b ~~* 'ABC'::text) -(2 rows) +(3 rows) select * from collate_test1 where b ilike 'ABC'; a | b @@ -1272,28 +1300,135 @@ CREATE COLLATION ctest_det (provider = icu, locale = '', deterministic = true); NOTICE: using standard form "und" for ICU locale "" CREATE COLLATION ctest_nondet (provider = icu, locale = '', deterministic = false); NOTICE: using standard form "und" for ICU locale "" +SELECT 'abc' LIKE 'abc' COLLATE ctest_det; + ?column? +---------- + t +(1 row) + +SELECT 'abc' LIKE 'a\bc' COLLATE ctest_det; + ?column? +---------- + t +(1 row) + +SELECT 'abc' LIKE 'abc' COLLATE ctest_nondet; + ?column? +---------- + t +(1 row) + +SELECT 'abc' LIKE 'a\bc' COLLATE ctest_nondet; + ?column? +---------- + t +(1 row) + CREATE TABLE test6 (a int, b text); -- same string in different normal forms -INSERT INTO test6 VALUES (1, U&'\00E4bc'); -INSERT INTO test6 VALUES (2, U&'\0061\0308bc'); +INSERT INTO test6 VALUES (1, U&'zy\00E4bc'); +INSERT INTO test6 VALUES (2, U&'zy\0061\0308bc'); SELECT * FROM test6; - a | b ----+----- - 1 | äbc - 2 | äbc + a | b +---+------- + 1 | zyäbc + 2 | zyäbc (2 rows) -SELECT * FROM test6 WHERE b = 'äbc' COLLATE ctest_det; - a | b ----+----- - 1 | äbc +SELECT * FROM test6 WHERE b = 'zyäbc' COLLATE ctest_det; + a | b +---+------- + 1 | zyäbc (1 row) -SELECT * FROM test6 WHERE b = 'äbc' COLLATE ctest_nondet; - a | b ----+----- - 1 | äbc - 2 | äbc +SELECT * FROM test6 WHERE b = 'zyäbc' COLLATE ctest_nondet; + a | b +---+------- + 1 | zyäbc + 2 | zyäbc +(2 rows) + +SELECT strpos(b COLLATE ctest_det, 'bc') FROM test6; + strpos +-------- + 4 + 5 +(2 rows) + +SELECT strpos(b COLLATE ctest_nondet, 'bc') FROM test6; + strpos +-------- + 4 + 5 +(2 rows) + +SELECT replace(b COLLATE ctest_det, U&'\00E4b', 'X') FROM test6; + replace +--------- + zyXc + zyäbc +(2 rows) + +SELECT replace(b COLLATE ctest_nondet, U&'\00E4b', 'X') FROM test6; + replace +--------- + zyXc + zyXc +(2 rows) + +SELECT a, split_part(b COLLATE ctest_det, U&'\00E4b', 2) FROM test6; + a | split_part +---+------------ + 1 | c + 2 | +(2 rows) + +SELECT a, split_part(b COLLATE ctest_nondet, U&'\00E4b', 2) FROM test6; + a | split_part +---+------------ + 1 | c + 2 | c +(2 rows) + +SELECT a, split_part(b COLLATE ctest_det, U&'\00E4b', -1) FROM test6; + a | split_part +---+------------ + 1 | c + 2 | zyäbc +(2 rows) + +SELECT a, split_part(b COLLATE ctest_nondet, U&'\00E4b', -1) FROM test6; + a | split_part +---+------------ + 1 | c + 2 | c +(2 rows) + +SELECT a, string_to_array(b COLLATE ctest_det, U&'\00E4b') FROM test6; + a | string_to_array +---+----------------- + 1 | {zy,c} + 2 | {zyäbc} +(2 rows) + +SELECT a, string_to_array(b COLLATE ctest_nondet, U&'\00E4b') FROM test6; + a | string_to_array +---+----------------- + 1 | {zy,c} + 2 | {zy,c} +(2 rows) + +SELECT * FROM test6 WHERE b LIKE 'zyäbc' COLLATE ctest_det; + a | b +---+------- + 1 | zyäbc +(1 row) + +SELECT * FROM test6 WHERE b LIKE 'zyäbc' COLLATE ctest_nondet; + a | b +---+------- + 1 | zyäbc + 2 | zyäbc (2 rows) -- same with arrays @@ -1336,6 +1471,19 @@ SELECT 'abc' <= 'ABC' COLLATE case_insensitive, 'abc' >= 'ABC' COLLATE case_inse t | t (1 row) +-- tests with array_sort +SELECT array_sort('{a,B}'::text[] COLLATE case_insensitive); + array_sort +------------ + {a,B} +(1 row) + +SELECT array_sort('{a,B}'::text[] COLLATE "C"); + array_sort +------------ + {B,a} +(1 row) + -- test language tags CREATE COLLATION lt_insensitive (provider = icu, locale = 'en-u-ks-level1', deterministic = false); SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; @@ -1512,7 +1660,12 @@ SELECT x FROM test3ci WHERE x <> 'abc'; (2 rows) SELECT x FROM test3ci WHERE x LIKE 'a%'; -ERROR: nondeterministic collations are not supported for LIKE + x +----- + abc + ABC +(2 rows) + SELECT x FROM test3ci WHERE x ILIKE 'a%'; ERROR: nondeterministic collations are not supported for ILIKE SELECT x FROM test3ci WHERE x SIMILAR TO 'a%'; @@ -1599,7 +1752,11 @@ CREATE UNIQUE INDEX ON test3ci (x); -- error ERROR: could not create unique index "test3ci_x_idx" DETAIL: Key (x)=(abc) is duplicated. SELECT string_to_array('ABC,DEF,GHI' COLLATE case_insensitive, ',', 'abc'); -ERROR: nondeterministic collations are not supported for substring searches + string_to_array +----------------- + {NULL,DEF,GHI} +(1 row) + SELECT string_to_array('ABCDEFGHI' COLLATE case_insensitive, NULL, 'b'); string_to_array ------------------------ @@ -1630,7 +1787,12 @@ SELECT x FROM test3bpci WHERE x <> 'abc'; (2 rows) SELECT x FROM test3bpci WHERE x LIKE 'a%'; -ERROR: nondeterministic collations are not supported for LIKE + x +----- + abc + ABC +(2 rows) + SELECT x FROM test3bpci WHERE x ILIKE 'a%'; ERROR: nondeterministic collations are not supported for ILIKE SELECT x FROM test3bpci WHERE x SIMILAR TO 'a%'; @@ -1717,7 +1879,11 @@ CREATE UNIQUE INDEX ON test3bpci (x); -- error ERROR: could not create unique index "test3bpci_x_idx" DETAIL: Key (x)=(abc) is duplicated. SELECT string_to_array('ABC,DEF,GHI'::char(11) COLLATE case_insensitive, ',', 'abc'); -ERROR: nondeterministic collations are not supported for substring searches + string_to_array +----------------- + {NULL,DEF,GHI} +(1 row) + SELECT string_to_array('ABCDEFGHI'::char(9) COLLATE case_insensitive, NULL, 'b'); string_to_array ------------------------ @@ -1727,7 +1893,7 @@ SELECT string_to_array('ABCDEFGHI'::char(9) COLLATE case_insensitive, NULL, 'b') -- This tests the issue described in match_pattern_prefix(). In the -- absence of that check, the case_insensitive tests below would -- return no rows where they should logically return one. -CREATE TABLE test4c (x text COLLATE "C"); +CREATE TABLE test4c (x text COLLATE case_insensitive); INSERT INTO test4c VALUES ('abc'); CREATE INDEX ON test4c (x); SET enable_seqscan = off; @@ -1741,10 +1907,18 @@ SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_sensitive; -- ok, no rows --- (0 rows) -SELECT x FROM test4c WHERE x LIKE 'ABC' COLLATE case_insensitive; -- error -ERROR: nondeterministic collations are not supported for LIKE -SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_insensitive; -- error -ERROR: nondeterministic collations are not supported for LIKE +SELECT x FROM test4c WHERE x LIKE 'ABC' COLLATE case_insensitive; -- ok + x +----- + abc +(1 row) + +SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_insensitive; -- ok + x +----- + abc +(1 row) + RESET enable_seqscan; -- Unicode special case: different variants of Greek lower case sigma. -- A naive implementation like citext that just does lower(x) = @@ -1838,101 +2012,221 @@ SELECT * FROM test4 WHERE b = 'Cote' COLLATE case_insensitive; 1 | cote (1 row) --- foreign keys (should use collation of primary key) --- PK is case-sensitive, FK is case-insensitive -CREATE TABLE test10pk (x text COLLATE case_sensitive PRIMARY KEY); -INSERT INTO test10pk VALUES ('abc'), ('def'), ('ghi'); -CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -INSERT INTO test10fk VALUES ('abc'); -- ok -INSERT INTO test10fk VALUES ('ABC'); -- error -ERROR: insert or update on table "test10fk" violates foreign key constraint "test10fk_x_fkey" -DETAIL: Key (x)=(ABC) is not present in table "test10pk". -INSERT INTO test10fk VALUES ('xyz'); -- error -ERROR: insert or update on table "test10fk" violates foreign key constraint "test10fk_x_fkey" -DETAIL: Key (x)=(xyz) is not present in table "test10pk". -SELECT * FROM test10pk; - x ------ - abc - def - ghi -(3 rows) +CREATE TABLE test4nfd (a int, b text); +INSERT INTO test4nfd VALUES (1, 'cote'), (2, 'côte'), (3, 'coté'), (4, 'côté'); +UPDATE test4nfd SET b = normalize(b, nfd); +-- This shows why replace should be greedy. Otherwise, in the NFD +-- case, the match would stop before the decomposed accents, which +-- would leave the accents in the results. +SELECT a, b, replace(b COLLATE ignore_accents, 'co', 'ma') FROM test4; + a | b | replace +---+------+--------- + 1 | cote | mate + 2 | côte | mate + 3 | coté | maté + 4 | côté | maté +(4 rows) -SELECT * FROM test10fk; - x ------ - abc +SELECT a, b, replace(b COLLATE ignore_accents, 'co', 'ma') FROM test4nfd; + a | b | replace +---+------+--------- + 1 | cote | mate + 2 | côte | mate + 3 | coté | maté + 4 | côté | maté +(4 rows) + +-- This is a tricky one. A naive implementation would first test +-- \00E4 matches \0061, which is true under ignore_accents, but then +-- the rest of the string won't match anymore. Therefore, the +-- algorithm has to test whether the rest of the string matches, and +-- if not try matching \00E4 against a longer substring like +-- \0061\0308, which will then work out. +SELECT U&'\0061\0308bc' LIKE U&'\00E4_c' COLLATE ignore_accents; + ?column? +---------- + t (1 row) --- restrict update even though the values are "equal" in the FK table -UPDATE test10fk SET x = 'ABC' WHERE x = 'abc'; -- error -ERROR: insert or update on table "test10fk" violates foreign key constraint "test10fk_x_fkey" -DETAIL: Key (x)=(ABC) is not present in table "test10pk". -SELECT * FROM test10fk; - x ------ - abc +-- and in reverse: +SELECT U&'\00E4bc' LIKE U&'\0061\0308_c' COLLATE ignore_accents; + ?column? +---------- + t (1 row) -DELETE FROM test10pk WHERE x = 'abc'; -SELECT * FROM test10pk; - x ------ - def - ghi -(2 rows) +-- inner % matches b: +SELECT U&'\0061\0308bc' LIKE U&'\00E4%c' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) -SELECT * FROM test10fk; - x ---- -(0 rows) +-- inner %% matches b then zero: +SELECT U&'\0061\0308bc' LIKE U&'\00E4%%c' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- inner %% matches b then zero: +SELECT U&'cb\0061\0308' LIKE U&'c%%\00E4' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- trailing _ matches two codepoints that form one grapheme: +SELECT U&'cb\0061\0308' LIKE U&'cb_' COLLATE ignore_accents; + ?column? +---------- + f +(1 row) + +-- trailing __ matches two codepoints that form one grapheme: +SELECT U&'cb\0061\0308' LIKE U&'cb__' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- leading % matches zero: +SELECT U&'\0061\0308bc' LIKE U&'%\00E4bc' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- leading % matches zero (with later %): +SELECT U&'\0061\0308bc' LIKE U&'%\00E4%c' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- trailing % matches zero: +SELECT U&'\0061\0308bc' LIKE U&'\00E4bc%' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- trailing % matches zero (with previous %): +SELECT U&'\0061\0308bc' LIKE U&'\00E4%c%' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- _ versus two codepoints that form one grapheme: +SELECT U&'\0061\0308bc' LIKE U&'_bc' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- (actually this matches because) +SELECT U&'\0308bc' = 'bc' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- __ matches two codepoints that form one grapheme: +SELECT U&'\0061\0308bc' LIKE U&'__bc' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- _ matches one codepoint that forms half a grapheme: +SELECT U&'\0061\0308bc' LIKE U&'_\0308bc' COLLATE ignore_accents; + ?column? +---------- + t +(1 row) + +-- doesn't match because \00e4 doesn't match only \0308 +SELECT U&'\0061\0308bc' LIKE U&'_\00e4bc' COLLATE ignore_accents; + ?column? +---------- + f +(1 row) --- PK is case-insensitive, FK is case-sensitive +-- escape character at end of pattern +SELECT 'foox' LIKE 'foo\' COLLATE ignore_accents; +ERROR: LIKE pattern must not end with escape character +-- foreign keys (mixing different nondeterministic collations not allowed) +CREATE TABLE test10pk (x text COLLATE case_sensitive PRIMARY KEY); +CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -- error +ERROR: foreign key constraint "test10fk_x_fkey" cannot be implemented +DETAIL: Key columns "x" of the referencing table and "x" of the referenced table have incompatible collations: "case_insensitive" and "case_sensitive". If either collation is nondeterministic, then both collations have to be the same. CREATE TABLE test11pk (x text COLLATE case_insensitive PRIMARY KEY); -INSERT INTO test11pk VALUES ('abc'), ('def'), ('ghi'); -CREATE TABLE test11fk (x text COLLATE case_sensitive REFERENCES test11pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -INSERT INTO test11fk VALUES ('abc'); -- ok -INSERT INTO test11fk VALUES ('ABC'); -- ok -INSERT INTO test11fk VALUES ('xyz'); -- error -ERROR: insert or update on table "test11fk" violates foreign key constraint "test11fk_x_fkey" -DETAIL: Key (x)=(xyz) is not present in table "test11pk". -SELECT * FROM test11pk; +CREATE TABLE test11fk (x text COLLATE case_sensitive REFERENCES test11pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -- error +ERROR: foreign key constraint "test11fk_x_fkey" cannot be implemented +DETAIL: Key columns "x" of the referencing table and "x" of the referenced table have incompatible collations: "case_sensitive" and "case_insensitive". If either collation is nondeterministic, then both collations have to be the same. +-- foreign key actions +-- Some of the behaviors are most easily visible with a +-- case-insensitive collation. +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE NO ACTION); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- ok +SELECT * FROM test12pk; x ----- - abc - def - ghi -(3 rows) + ABC +(1 row) -SELECT * FROM test11fk; +SELECT * FROM test12fk; -- no updates here + a | b +---+----- + 1 | abc + 2 | ABC +(2 rows) + +DROP TABLE test12pk, test12fk; +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE RESTRICT); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- restrict violation +ERROR: update or delete on table "test12pk" violates RESTRICT setting of foreign key constraint "test12fk_b_fkey" on table "test12fk" +DETAIL: Key (x)=(abc) is referenced from table "test12fk". +SELECT * FROM test12pk; x ----- abc - ABC +(1 row) + +SELECT * FROM test12fk; + a | b +---+----- + 1 | abc + 2 | ABC (2 rows) --- cascade update even though the values are "equal" in the PK table -UPDATE test11pk SET x = 'ABC' WHERE x = 'abc'; -SELECT * FROM test11fk; +DROP TABLE test12pk, test12fk; +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE CASCADE); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- ok +SELECT * FROM test12pk; x ----- ABC - ABC -(2 rows) +(1 row) -DELETE FROM test11pk WHERE x = 'abc'; -SELECT * FROM test11pk; - x ------ - def - ghi +SELECT * FROM test12fk; -- was updated + a | b +---+----- + 1 | ABC + 2 | ABC (2 rows) -SELECT * FROM test11fk; - x ---- -(0 rows) - +DROP TABLE test12pk, test12fk; -- partitioning CREATE TABLE test20 (a int, b text COLLATE case_insensitive) PARTITION BY LIST (b); CREATE TABLE test20_1 PARTITION OF test20 FOR VALUES IN ('abc'); @@ -2052,6 +2346,350 @@ SELECT (SELECT count(*) FROM test33_0) <> (SELECT count(*) FROM test33_1); t (1 row) +-- +-- Bug #18568 +-- +-- Partitionwise aggregate (full or partial) should not be used when a +-- partition key's collation doesn't match that of the GROUP BY column it is +-- matched with. +SET max_parallel_workers_per_gather TO 0; +SET enable_incremental_sort TO off; +CREATE TABLE pagg_tab3 (a text, c text collate case_insensitive) PARTITION BY LIST(c collate "C"); +CREATE TABLE pagg_tab3_p1 PARTITION OF pagg_tab3 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab3_p2 PARTITION OF pagg_tab3 FOR VALUES IN ('B', 'A'); +INSERT INTO pagg_tab3 SELECT i % 4 + 1, substr('abAB', (i % 4) + 1 , 1) FROM generate_series(0, 19) i; +ANALYZE pagg_tab3; +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + QUERY PLAN +----------------------------------------------------------- + Sort + Sort Key: (upper(pagg_tab3.c)) COLLATE case_insensitive + -> HashAggregate + Group Key: pagg_tab3.c + -> Append + -> Seq Scan on pagg_tab3_p2 pagg_tab3_1 + -> Seq Scan on pagg_tab3_p1 pagg_tab3_2 +(7 rows) + +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + upper | count +-------+------- + A | 10 + B | 10 +(2 rows) + +-- No "full" partitionwise aggregation allowed, though "partial" is allowed. +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------- + Sort + Sort Key: (upper(pagg_tab3.c)) COLLATE case_insensitive + -> Finalize HashAggregate + Group Key: pagg_tab3.c + -> Append + -> Partial HashAggregate + Group Key: pagg_tab3.c + -> Seq Scan on pagg_tab3_p2 pagg_tab3 + -> Partial HashAggregate + Group Key: pagg_tab3_1.c + -> Seq Scan on pagg_tab3_p1 pagg_tab3_1 +(11 rows) + +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + upper | count +-------+------- + A | 10 + B | 10 +(2 rows) + +-- OK to use full partitionwise aggregate after changing the GROUP BY column's +-- collation to be the same as that of the partition key. +EXPLAIN (COSTS OFF) +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; + QUERY PLAN +-------------------------------------------------------- + Sort + Sort Key: ((pagg_tab3.c)::text) COLLATE "C" + -> Append + -> HashAggregate + Group Key: (pagg_tab3.c)::text + -> Seq Scan on pagg_tab3_p2 pagg_tab3 + -> HashAggregate + Group Key: (pagg_tab3_1.c)::text + -> Seq Scan on pagg_tab3_p1 pagg_tab3_1 +(9 rows) + +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; + c | count +---+------- + A | 5 + B | 5 + a | 5 + b | 5 +(4 rows) + +-- Partitionwise join should not be allowed too when the collation used by the +-- join keys doesn't match the partition key collation. +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: t1.c COLLATE "C" + -> HashAggregate + Group Key: t1.c + -> Hash Join + Hash Cond: (t1.c = t2.c) + -> Append + -> Seq Scan on pagg_tab3_p2 t1_1 + -> Seq Scan on pagg_tab3_p1 t1_2 + -> Hash + -> Append + -> Seq Scan on pagg_tab3_p2 t2_1 + -> Seq Scan on pagg_tab3_p1 t2_2 +(13 rows) + +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + c | count +---+------- + A | 100 + B | 100 +(2 rows) + +SET enable_partitionwise_join TO true; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: t1.c COLLATE "C" + -> HashAggregate + Group Key: t1.c + -> Hash Join + Hash Cond: (t1.c = t2.c) + -> Append + -> Seq Scan on pagg_tab3_p2 t1_1 + -> Seq Scan on pagg_tab3_p1 t1_2 + -> Hash + -> Append + -> Seq Scan on pagg_tab3_p2 t2_1 + -> Seq Scan on pagg_tab3_p1 t2_2 +(13 rows) + +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + c | count +---+------- + A | 100 + B | 100 +(2 rows) + +-- OK when the join clause uses the same collation as the partition key. +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------------ + Sort + Sort Key: ((t1.c)::text) COLLATE "C" + -> Append + -> HashAggregate + Group Key: (t1.c)::text + -> Hash Join + Hash Cond: ((t1.c)::text = (t2.c)::text) + -> Seq Scan on pagg_tab3_p2 t1 + -> Hash + -> Seq Scan on pagg_tab3_p2 t2 + -> HashAggregate + Group Key: (t1_1.c)::text + -> Hash Join + Hash Cond: ((t1_1.c)::text = (t2_1.c)::text) + -> Seq Scan on pagg_tab3_p1 t1_1 + -> Hash + -> Seq Scan on pagg_tab3_p1 t2_1 +(17 rows) + +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + c | count +---+------- + A | 25 + B | 25 + a | 25 + b | 25 +(4 rows) + +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: ((t1.c)::text) COLLATE "C" + -> HashAggregate + Group Key: (t1.c)::text + -> Hash Join + Hash Cond: ((t1.c)::text = (t2.c)::text) + -> Append + -> Seq Scan on pagg_tab3_p2 t1_1 + -> Seq Scan on pagg_tab3_p1 t1_2 + -> Hash + -> Append + -> Seq Scan on pagg_tab3_p2 t2_1 + -> Seq Scan on pagg_tab3_p1 t2_2 +(13 rows) + +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + c | count +---+------- + A | 25 + B | 25 + a | 25 + b | 25 +(4 rows) + +-- Few other cases where the joined partition keys are matched via equivalence +-- class, not a join restriction clause. +-- Collations of joined columns match, but the partition keys collation is different +SET enable_partitionwise_join TO true; +CREATE TABLE pagg_tab4 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (b collate "C"); +CREATE TABLE pagg_tab4_p1 PARTITION OF pagg_tab4 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab4_p2 PARTITION OF pagg_tab4 FOR VALUES IN ('B', 'A'); +INSERT INTO pagg_tab4 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 11) i; +ANALYZE pagg_tab4; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab4 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: t1.c COLLATE "C" + -> HashAggregate + Group Key: t1.c + -> Hash Join + Hash Cond: (t1.c = t2.c) + -> Append + -> Seq Scan on pagg_tab3_p2 t1_1 + -> Seq Scan on pagg_tab3_p1 t1_2 + -> Hash + -> Append + -> Seq Scan on pagg_tab4_p2 t2_1 + Filter: (c = b) + -> Seq Scan on pagg_tab4_p1 t2_2 + Filter: (c = b) +(15 rows) + +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab4 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + c | count +---+------- + A | 60 + B | 60 +(2 rows) + +-- OK when the partition key collation is same as that of the join columns +CREATE TABLE pagg_tab5 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (c collate case_insensitive); +CREATE TABLE pagg_tab5_p1 PARTITION OF pagg_tab5 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab5_p2 PARTITION OF pagg_tab5 FOR VALUES IN ('c', 'd'); +INSERT INTO pagg_tab5 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +INSERT INTO pagg_tab5 (b, c) SELECT substr('cdCD', (i % 4) + 1 , 1), substr('cdCD', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +ANALYZE pagg_tab5; +CREATE TABLE pagg_tab6 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (b collate case_insensitive); +CREATE TABLE pagg_tab6_p1 PARTITION OF pagg_tab6 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab6_p2 PARTITION OF pagg_tab6 FOR VALUES IN ('c', 'd'); +INSERT INTO pagg_tab6 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +INSERT INTO pagg_tab6 (b, c) SELECT substr('cdCD', (i % 4) + 1 , 1), substr('cdCD', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +ANALYZE pagg_tab6; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------- + Sort + Sort Key: t1.c COLLATE "C" + -> Append + -> HashAggregate + Group Key: t1.c + -> Nested Loop + Join Filter: (t1.c = t2.c) + -> Seq Scan on pagg_tab6_p1 t2 + Filter: (c = b) + -> Seq Scan on pagg_tab5_p1 t1 + -> HashAggregate + Group Key: t1_1.c + -> Nested Loop + Join Filter: (t1_1.c = t2_1.c) + -> Seq Scan on pagg_tab6_p2 t2_1 + Filter: (c = b) + -> Seq Scan on pagg_tab5_p2 t1_1 +(17 rows) + +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + c | count +---+------- + a | 9 + b | 9 + c | 9 + d | 9 +(4 rows) + +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: t1.c COLLATE "C" + -> HashAggregate + Group Key: t1.c + -> Hash Join + Hash Cond: (t1.c = t2.c) + -> Append + -> Seq Scan on pagg_tab5_p1 t1_1 + -> Seq Scan on pagg_tab5_p2 t1_2 + -> Hash + -> Append + -> Seq Scan on pagg_tab6_p1 t2_1 + Filter: (c = b) + -> Seq Scan on pagg_tab6_p2 t2_2 + Filter: (c = b) +(15 rows) + +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + c | count +---+------- + a | 9 + b | 9 + c | 9 + d | 9 +(4 rows) + +DROP TABLE pagg_tab3; +DROP TABLE pagg_tab4; +DROP TABLE pagg_tab5; +DROP TABLE pagg_tab6; +RESET enable_partitionwise_aggregate; +RESET max_parallel_workers_per_gather; +RESET enable_incremental_sort; +-- virtual generated columns +CREATE TABLE t5 ( + a int, + b text collate "C", + c text collate "C" GENERATED ALWAYS AS (b COLLATE case_insensitive) +); +INSERT INTO t5 (a, b) values (1, 'D1'), (2, 'D2'), (3, 'd1'); +-- Collation of c should be the one defined for the column ("C"), not +-- the one of the generation expression. (Note that we cannot just +-- test with, say, using COLLATION FOR, because the collation of +-- function calls is already determined in the parser before +-- rewriting.) +SELECT * FROM t5 ORDER BY c ASC, a ASC; + a | b | c +---+----+---- + 1 | D1 | D1 + 2 | D2 | D2 + 3 | d1 | d1 +(3 rows) + -- cleanup RESET search_path; SET client_min_messages TO warning; diff --git a/src/test/regress/expected/collate.linux.utf8.out b/src/test/regress/expected/collate.linux.utf8.out index 01664f7c1b544..fbaab7cdf8330 100644 --- a/src/test/regress/expected/collate.linux.utf8.out +++ b/src/test/regress/expected/collate.linux.utf8.out @@ -122,6 +122,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e... CREATE DOMAIN testdomain_sv AS text COLLATE "sv_SE"; CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; -- fails ERROR: collations are not supported by type integer +LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; + ^ CREATE TABLE collate_test4 ( a int, b testdomain_sv diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out index 593a622637666..bf72908fbd39b 100644 --- a/src/test/regress/expected/collate.out +++ b/src/test/regress/expected/collate.out @@ -73,6 +73,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "P... CREATE DOMAIN testdomain_p AS text COLLATE "POSIX"; CREATE DOMAIN testdomain_i AS int COLLATE "POSIX"; -- fail ERROR: collations are not supported by type integer +LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "POSIX"; + ^ CREATE TABLE collate_test4 ( a int, b testdomain_p diff --git a/src/test/regress/expected/collate.utf8.out b/src/test/regress/expected/collate.utf8.out index eff0ef21ac5b1..0c3ab5c89b284 100644 --- a/src/test/regress/expected/collate.utf8.out +++ b/src/test/regress/expected/collate.utf8.out @@ -9,6 +9,32 @@ SELECT getdatabaseencoding() <> 'UTF8' AS skip_test \gset \endif SET client_encoding TO UTF8; -- +-- Test builtin "C" +-- +CREATE COLLATION regress_builtin_c ( + provider = builtin, locale = 'C'); +-- non-ASCII characters are unchanged +SELECT LOWER(U&'\00C1' COLLATE regress_builtin_c) = U&'\00C1'; + ?column? +---------- + t +(1 row) + +SELECT UPPER(U&'\00E1' COLLATE regress_builtin_c) = U&'\00E1'; + ?column? +---------- + t +(1 row) + +-- non-ASCII characters are not alphabetic +SELECT U&'\00C1\00E1' !~ '[[:alpha:]]' COLLATE regress_builtin_c; + ?column? +---------- + t +(1 row) + +DROP COLLATION regress_builtin_c; +-- -- Test PG_C_UTF8 -- CREATE COLLATION regress_pg_c_utf8 ( @@ -26,6 +52,7 @@ INSERT INTO test_pg_c_utf8 VALUES ('abc DEF 123abc'), ('ábc sßs ßss DÉF'), ('DŽxxDŽ džxxDž Džxxdž'), + (U&'Λλ 1a \FF11a'), ('ȺȺȺ'), ('ⱥⱥⱥ'), ('ⱥȺ'); @@ -41,10 +68,11 @@ SELECT abc DEF 123abc | abc def 123abc | Abc Def 123abc | ABC DEF 123ABC | 14 | 14 | 14 | 14 ábc sßs ßss DÉF | ábc sßs ßss déf | Ábc Sßs ßss Déf | ÁBC SßS ßSS DÉF | 19 | 19 | 19 | 19 DŽxxDŽ džxxDž Džxxdž | džxxdž džxxdž džxxdž | DŽxxdž DŽxxdž DŽxxdž | DŽXXDŽ DŽXXDŽ DŽXXDŽ | 20 | 20 | 20 | 20 + Λλ 1a 1a | λλ 1a 1a | Λλ 1a 1A | ΛΛ 1A 1A | 12 | 12 | 12 | 12 ȺȺȺ | ⱥⱥⱥ | Ⱥⱥⱥ | ȺȺȺ | 6 | 9 | 8 | 6 ⱥⱥⱥ | ⱥⱥⱥ | Ⱥⱥⱥ | ȺȺȺ | 9 | 9 | 8 | 6 ⱥȺ | ⱥⱥ | Ⱥⱥ | ȺȺ | 5 | 6 | 5 | 4 -(6 rows) +(7 rows) DROP TABLE test_pg_c_utf8; -- negative test: Final_Sigma not used for builtin locale C.UTF-8 @@ -134,3 +162,179 @@ SELECT 'δ' ~* '[Γ-Λ]' COLLATE PG_C_UTF8; -- same as above with cases reversed t (1 row) +-- case folding +select casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' collate PG_C_UTF8); + casefold +------------------------------- + abcd 123 #$% ıiiİ ß ß dždždž σσσ +(1 row) + +-- +-- Test PG_UNICODE_FAST +-- +CREATE COLLATION regress_pg_unicode_fast ( + provider = builtin, locale = 'unicode'); -- fails +ERROR: invalid locale name "unicode" for builtin provider +CREATE COLLATION regress_pg_unicode_fast ( + provider = builtin, locale = 'PG_UNICODE_FAST'); +CREATE TABLE test_pg_unicode_fast ( + t TEXT COLLATE PG_UNICODE_FAST +); +INSERT INTO test_pg_unicode_fast VALUES + ('abc DEF 123abc'), + ('ábc sßs ßss DÉF'), + ('DŽxxDŽ džxxDž Džxxdž'), + (U&'Λλ 1a \FF11a'), + ('ȺȺȺ'), + ('ⱥⱥⱥ'), + ('ⱥȺ'); +SELECT + t, lower(t), initcap(t), upper(t), + length(convert_to(t, 'UTF8')) AS t_bytes, + length(convert_to(lower(t), 'UTF8')) AS lower_t_bytes, + length(convert_to(initcap(t), 'UTF8')) AS initcap_t_bytes, + length(convert_to(upper(t), 'UTF8')) AS upper_t_bytes + FROM test_pg_unicode_fast; + t | lower | initcap | upper | t_bytes | lower_t_bytes | initcap_t_bytes | upper_t_bytes +-----------------+-----------------+------------------+-------------------+---------+---------------+-----------------+--------------- + abc DEF 123abc | abc def 123abc | Abc Def 123abc | ABC DEF 123ABC | 14 | 14 | 14 | 14 + ábc sßs ßss DÉF | ábc sßs ßss déf | Ábc Sßs Ssss Déf | ÁBC SSSS SSSS DÉF | 19 | 19 | 19 | 19 + DŽxxDŽ džxxDž Džxxdž | džxxdž džxxdž džxxdž | Džxxdž Džxxdž Džxxdž | DŽXXDŽ DŽXXDŽ DŽXXDŽ | 20 | 20 | 20 | 20 + Λλ 1a 1a | λλ 1a 1a | Λλ 1a 1a | ΛΛ 1A 1A | 12 | 12 | 12 | 12 + ȺȺȺ | ⱥⱥⱥ | Ⱥⱥⱥ | ȺȺȺ | 6 | 9 | 8 | 6 + ⱥⱥⱥ | ⱥⱥⱥ | Ⱥⱥⱥ | ȺȺȺ | 9 | 9 | 8 | 6 + ⱥȺ | ⱥⱥ | Ⱥⱥ | ȺȺ | 5 | 6 | 5 | 4 +(7 rows) + +DROP TABLE test_pg_unicode_fast; +-- test Final_Sigma +SELECT lower('ΑΣ' COLLATE PG_UNICODE_FAST); -- 0391 03A3 + lower +------- + ας +(1 row) + +SELECT lower('ΑΣ0' COLLATE PG_UNICODE_FAST); -- 0391 03A3 0030 + lower +------- + ας0 +(1 row) + +SELECT lower('ἈΣ̓' COLLATE PG_UNICODE_FAST); -- 0391 0343 03A3 0343 + lower +------- + ἀς̓ +(1 row) + +SELECT lower('ᾼΣͅ' COLLATE PG_UNICODE_FAST); -- 0391 0345 03A3 0345 + lower +------- + ᾳςͅ +(1 row) + +-- test !Final_Sigma +SELECT lower('Σ' COLLATE PG_UNICODE_FAST); -- 03A3 + lower +------- + σ +(1 row) + +SELECT lower('0Σ' COLLATE PG_UNICODE_FAST); -- 0030 03A3 + lower +------- + 0σ +(1 row) + +SELECT lower('ΑΣΑ' COLLATE PG_UNICODE_FAST); -- 0391 03A3 0391 + lower +------- + ασα +(1 row) + +SELECT lower('ἈΣ̓Α' COLLATE PG_UNICODE_FAST); -- 0391 0343 03A3 0343 0391 + lower +------- + ἀσ̓α +(1 row) + +SELECT lower('ᾼΣͅΑ' COLLATE PG_UNICODE_FAST); -- 0391 0345 03A3 0345 0391 + lower +------- + ᾳσͅα +(1 row) + +-- properties +SELECT 'xyz' ~ '[[:alnum:]]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT 'xyz' !~ '[[:upper:]]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT '@' !~ '[[:alnum:]]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT '=' !~ '[[:punct:]]' COLLATE PG_UNICODE_FAST; -- symbols are not punctuation + ?column? +---------- + t +(1 row) + +SELECT 'a8a' ~ '[[:digit:]]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT '൧' ~ '\d' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +-- case mapping +SELECT 'xYz' ~* 'XyZ' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT 'xAb' ~* '[W-Y]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT 'xAb' !~* '[c-d]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT 'Δ' ~* '[γ-λ]' COLLATE PG_UNICODE_FAST; + ?column? +---------- + t +(1 row) + +SELECT 'δ' ~* '[Γ-Λ]' COLLATE PG_UNICODE_FAST; -- same as above with cases reversed + ?column? +---------- + t +(1 row) + +-- case folding +select casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' collate PG_UNICODE_FAST); + casefold +--------------------------------- + abcd 123 #$% ıiii̇ ss ss dždždž σσσ +(1 row) + diff --git a/src/test/regress/expected/collate.windows.win1252.out b/src/test/regress/expected/collate.windows.win1252.out index 31f794988b3c0..4644f56b31dc1 100644 --- a/src/test/regress/expected/collate.windows.win1252.out +++ b/src/test/regress/expected/collate.windows.win1252.out @@ -124,6 +124,8 @@ LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e... CREATE DOMAIN testdomain_sv AS text COLLATE "sv_SE"; CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; -- fails ERROR: collations are not supported by type integer +LINE 1: CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE"; + ^ CREATE TABLE collate_test4 ( a int, b testdomain_sv diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out index cf0b80d616965..ad6aaab738538 100644 --- a/src/test/regress/expected/constraints.out +++ b/src/test/regress/expected/constraints.out @@ -6,6 +6,7 @@ -- - PRIMARY KEY clauses -- - UNIQUE clauses -- - EXCLUDE clauses +-- - NOT NULL clauses -- -- directory paths are passed to us in environment variables \getenv abs_srcdir PG_ABS_SRCDIR @@ -86,6 +87,25 @@ SELECT * FROM CHECK_TBL; 6 (3 rows) +CREATE TABLE NE_CHECK_TBL (x int, + CONSTRAINT CHECK_CON CHECK (x > 3) NOT ENFORCED); +INSERT INTO NE_CHECK_TBL VALUES (5); +INSERT INTO NE_CHECK_TBL VALUES (4); +INSERT INTO NE_CHECK_TBL VALUES (3); +INSERT INTO NE_CHECK_TBL VALUES (2); +INSERT INTO NE_CHECK_TBL VALUES (6); +INSERT INTO NE_CHECK_TBL VALUES (1); +SELECT * FROM NE_CHECK_TBL; + x +--- + 5 + 4 + 3 + 2 + 6 + 1 +(6 rows) + CREATE SEQUENCE CHECK_SEQ; CREATE TABLE CHECK2_TBL (x int, y text, z int, CONSTRAINT SEQUENCE_CON @@ -119,7 +139,8 @@ CREATE TABLE INSERT_TBL (x INT DEFAULT nextval('insert_seq'), y TEXT DEFAULT '-NULL-', z INT DEFAULT -1 * currval('insert_seq'), CONSTRAINT INSERT_TBL_CON CHECK (x >= 3 AND y <> 'check failed' AND x < 8), - CHECK (x + z = 0)); + CHECK (x + z = 0) ENFORCED, /* no change it is a default */ + CONSTRAINT NE_INSERT_TBL_CON CHECK (x + z = 1) NOT ENFORCED); INSERT INTO INSERT_TBL(x,z) VALUES (2, -2); ERROR: new row for relation "insert_tbl" violates check constraint "insert_tbl_con" DETAIL: Failing row contains (2, -NULL-, -2). @@ -620,9 +641,9 @@ CREATE TABLE parted_fk_naming_1 ( ); ALTER TABLE parted_fk_naming ATTACH PARTITION parted_fk_naming_1 FOR VALUES IN ('1'); SELECT conname FROM pg_constraint WHERE conrelid = 'parted_fk_naming_1'::regclass AND contype = 'f'; - conname --------------------------------- - parted_fk_naming_1_id_abc_fkey + conname +---------------- + dummy_constr_1 (1 row) DROP TABLE parted_fk_naming; @@ -714,6 +735,19 @@ SELECT * FROM unique_tbl; 3 | threex (5 rows) +-- enforceability cannot be specified or set for unique constraint +CREATE TABLE UNIQUE_EN_TBL(i int UNIQUE ENFORCED); +ERROR: misplaced ENFORCED clause +LINE 1: CREATE TABLE UNIQUE_EN_TBL(i int UNIQUE ENFORCED); + ^ +CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED); +ERROR: misplaced NOT ENFORCED clause +LINE 1: CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED); + ^ +ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED; +ERROR: cannot alter enforceability of constraint "unique_tbl_i_key" of relation "unique_tbl" +ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORCED; +ERROR: cannot alter enforceability of constraint "unique_tbl_i_key" of relation "unique_tbl" DROP TABLE unique_tbl; -- -- EXCLUDE constraints @@ -797,6 +831,836 @@ ALTER TABLE deferred_excl ADD EXCLUDE (f1 WITH =); ERROR: could not create exclusion constraint "deferred_excl_f1_excl" DETAIL: Key (f1)=(3) conflicts with key (f1)=(3). DROP TABLE deferred_excl; +-- verify constraints created for NOT NULL clauses +CREATE TABLE notnull_tbl1 (a INTEGER NOT NULL NOT NULL); +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "notnull_tbl1_a_not_null" NOT NULL "a" + +-- no-op +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "notnull_tbl1_a_not_null" NOT NULL "a" + +-- duplicate name +ALTER TABLE notnull_tbl1 ADD COLUMN b INT CONSTRAINT notnull_tbl1_a_not_null NOT NULL; +ERROR: constraint "notnull_tbl1_a_not_null" for relation "notnull_tbl1" already exists +-- DROP NOT NULL gets rid of both the attnotnull flag and the constraint itself +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + +-- SET NOT NULL puts both back +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "notnull_tbl1_a_not_null" NOT NULL "a" + +-- Doing it twice doesn't create a redundant constraint +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +select conname, contype, conkey from pg_constraint where conrelid = 'notnull_tbl1'::regclass; + conname | contype | conkey +-------------------------+---------+-------- + notnull_tbl1_a_not_null | n | {1} +(1 row) + +-- Using the "table constraint" syntax also works +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +ALTER TABLE notnull_tbl1 ADD CONSTRAINT foobar NOT NULL a; +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "foobar" NOT NULL "a" + +DROP TABLE notnull_tbl1; +-- Verify that constraint names and NO INHERIT are properly considered when +-- multiple constraint are specified, either explicitly or via SERIAL/PK/etc, +-- and that conflicting cases are rejected. Mind that table constraints +-- handle this separately from column constraints. +create table notnull_tbl1 (a int primary key constraint foo not null); +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl1_pkey" PRIMARY KEY, btree (a) +Not-null constraints: + "foo" NOT NULL "a" + +create table notnull_tbl2 (a serial, constraint foo not null a); +\d+ notnull_tbl2 + Table "public.notnull_tbl2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+-----------------------------------------+---------+--------------+------------- + a | integer | | not null | nextval('notnull_tbl2_a_seq'::regclass) | plain | | +Not-null constraints: + "foo" NOT NULL "a" + +create table notnull_tbl3 (constraint foo not null a, a int generated by default as identity); +\d+ notnull_tbl3 + Table "public.notnull_tbl3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+----------------------------------+---------+--------------+------------- + a | integer | | not null | generated by default as identity | plain | | +Not-null constraints: + "foo" NOT NULL "a" + +create table notnull_tbl4 (a int not null constraint foo not null); +\d+ notnull_tbl4 + Table "public.notnull_tbl4" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "foo" NOT NULL "a" + +create table notnull_tbl5 (a int constraint foo not null constraint foo not null); +\d+ notnull_tbl5 + Table "public.notnull_tbl5" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "foo" NOT NULL "a" + +create table notnull_tbl6 (like notnull_tbl1, constraint foo not null a); +\d+ notnull_tbl6 + Table "public.notnull_tbl6" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "foo" NOT NULL "a" + +drop table notnull_tbl2, notnull_tbl3, notnull_tbl4, notnull_tbl5, notnull_tbl6; +-- error cases: +create table notnull_tbl_fail (a serial constraint foo not null constraint bar not null); +ERROR: conflicting not-null constraint names "foo" and "bar" +create table notnull_tbl_fail (a serial constraint foo not null no inherit constraint foo not null); +ERROR: conflicting NO INHERIT declarations for not-null constraints on column "a" +create table notnull_tbl_fail (a int constraint foo not null, constraint foo not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +create table notnull_tbl_fail (a serial constraint foo not null, constraint bar not null a); +ERROR: conflicting not-null constraint names "foo" and "bar" +create table notnull_tbl_fail (a serial, constraint foo not null a, constraint bar not null a); +ERROR: conflicting not-null constraint names "foo" and "bar" +create table notnull_tbl_fail (a serial, constraint foo not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +create table notnull_tbl_fail (a serial not null no inherit); +ERROR: conflicting NO INHERIT declarations for not-null constraints on column "a" +create table notnull_tbl_fail (like notnull_tbl1, constraint foo2 not null a); +ERROR: conflicting not-null constraint names "foo" and "foo2" +create table notnull_tbl_fail (a int primary key constraint foo not null no inherit); +ERROR: conflicting NO INHERIT declarations for not-null constraints on column "a" +create table notnull_tbl_fail (a int not null no inherit primary key); +ERROR: conflicting NO INHERIT declarations for not-null constraints on column "a" +create table notnull_tbl_fail (a int primary key, not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +create table notnull_tbl_fail (a int, primary key(a), not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +create table notnull_tbl_fail (a int generated by default as identity, constraint foo not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +create table notnull_tbl_fail (a int generated by default as identity not null no inherit); +ERROR: conflicting NO INHERIT declarations for not-null constraints on column "a" +drop table notnull_tbl1; +-- NOT NULL NO INHERIT +CREATE TABLE ATACC1 (a int, NOT NULL a NO INHERIT); +CREATE TABLE ATACC2 () INHERITS (ATACC1); +\d+ ATACC2 + Table "public.atacc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Inherits: atacc1 + +DROP TABLE ATACC1, ATACC2; +CREATE TABLE ATACC1 (a int); +ALTER TABLE ATACC1 ADD NOT NULL a NO INHERIT; +CREATE TABLE ATACC2 () INHERITS (ATACC1); +\d+ ATACC2 + Table "public.atacc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Inherits: atacc1 + +DROP TABLE ATACC1, ATACC2; +CREATE TABLE ATACC1 (a int); +CREATE TABLE ATACC2 () INHERITS (ATACC1); +ALTER TABLE ATACC1 ADD NOT NULL a NO INHERIT; +\d+ ATACC2 + Table "public.atacc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Inherits: atacc1 + +CREATE TABLE ATACC3 (PRIMARY KEY (a)) INHERITS (ATACC1); +\d+ ATACC3 + Table "public.atacc3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "atacc3_pkey" PRIMARY KEY, btree (a) +Not-null constraints: + "atacc3_a_not_null" NOT NULL "a" +Inherits: atacc1 + +DROP TABLE ATACC1, ATACC2, ATACC3; +-- NOT NULL NO INHERIT is not possible on partitioned tables +CREATE TABLE ATACC1 (a int NOT NULL NO INHERIT) PARTITION BY LIST (a); +ERROR: not-null constraints on partitioned tables cannot be NO INHERIT +CREATE TABLE ATACC1 (a int, NOT NULL a NO INHERIT) PARTITION BY LIST (a); +ERROR: not-null constraints on partitioned tables cannot be NO INHERIT +-- it's not possible to override a no-inherit constraint with an inheritable one +CREATE TABLE ATACC2 (a int, CONSTRAINT a_is_not_null NOT NULL a NO INHERIT); +CREATE TABLE ATACC1 (a int); +CREATE TABLE ATACC3 (a int) INHERITS (ATACC2); +NOTICE: merging column "a" with inherited definition +ALTER TABLE ATACC2 INHERIT ATACC1; +-- can't override +ALTER TABLE ATACC1 ADD CONSTRAINT ditto NOT NULL a; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "a_is_not_null" on relation "atacc2" +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +-- dropping the NO INHERIT constraint allows this to work +ALTER TABLE ATACC2 DROP CONSTRAINT a_is_not_null; +ALTER TABLE ATACC1 ADD CONSTRAINT ditto NOT NULL a; +\d+ ATACC3 + Table "public.atacc3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "ditto" NOT NULL "a" (inherited) +Inherits: atacc2 + +DROP TABLE ATACC1, ATACC2, ATACC3; +-- Can't have two constraints with the same name +CREATE TABLE notnull_tbl2 (a INTEGER CONSTRAINT blah NOT NULL, b INTEGER CONSTRAINT blah NOT NULL); +ERROR: constraint "blah" for relation "notnull_tbl2" already exists +-- can't drop not-null in primary key +CREATE TABLE notnull_tbl2 (a INTEGER PRIMARY KEY); +ALTER TABLE notnull_tbl2 ALTER a DROP NOT NULL; +ERROR: column "a" is in a primary key +DROP TABLE notnull_tbl2; +CREATE TABLE notnull_tbl3 (a INTEGER NOT NULL, CHECK (a IS NOT NULL)); +ALTER TABLE notnull_tbl3 ALTER A DROP NOT NULL; +ALTER TABLE notnull_tbl3 ADD b int, ADD CONSTRAINT pk PRIMARY KEY (a, b); +\d notnull_tbl3 + Table "public.notnull_tbl3" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + a | integer | | not null | + b | integer | | not null | +Indexes: + "pk" PRIMARY KEY, btree (a, b) +Check constraints: + "notnull_tbl3_a_check" CHECK (a IS NOT NULL) + +ALTER TABLE notnull_tbl3 DROP CONSTRAINT pk; +\d notnull_tbl3 + Table "public.notnull_tbl3" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + a | integer | | not null | + b | integer | | not null | +Check constraints: + "notnull_tbl3_a_check" CHECK (a IS NOT NULL) + +-- Primary keys cause not-null constraints to be created. +CREATE TABLE cnn_pk (a int, b int); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +ALTER TABLE cnn_pk ADD CONSTRAINT cnn_primarykey PRIMARY KEY (b); +\d+ cnn_pk* + Table "public.cnn_pk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Indexes: + "cnn_primarykey" PRIMARY KEY, btree (b) +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" +Child tables: cnn_pk_child + + Table "public.cnn_pk_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" (inherited) +Inherits: cnn_pk + +ALTER TABLE cnn_pk DROP CONSTRAINT cnn_primarykey; +\d+ cnn_pk* + Table "public.cnn_pk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" +Child tables: cnn_pk_child + + Table "public.cnn_pk_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" (inherited) +Inherits: cnn_pk + +DROP TABLE cnn_pk, cnn_pk_child; +-- As above, but create the primary key ahead of time +CREATE TABLE cnn_pk (a int, b int, CONSTRAINT cnn_primarykey PRIMARY KEY (b)); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +\d+ cnn_pk* + Table "public.cnn_pk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Indexes: + "cnn_primarykey" PRIMARY KEY, btree (b) +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" +Child tables: cnn_pk_child + + Table "public.cnn_pk_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" (inherited) +Inherits: cnn_pk + +ALTER TABLE cnn_pk DROP CONSTRAINT cnn_primarykey; +\d+ cnn_pk* + Table "public.cnn_pk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" +Child tables: cnn_pk_child + + Table "public.cnn_pk_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" (inherited) +Inherits: cnn_pk + +DROP TABLE cnn_pk, cnn_pk_child; +-- As above, but create the primary key using a UNIQUE index +CREATE TABLE cnn_pk (a int, b int); +CREATE UNIQUE INDEX cnn_uq ON cnn_pk (b); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +ALTER TABLE cnn_pk ADD CONSTRAINT cnn_primarykey PRIMARY KEY USING INDEX cnn_uq; +NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "cnn_uq" to "cnn_primarykey" +\d+ cnn_pk* + Table "public.cnn_pk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Indexes: + "cnn_primarykey" PRIMARY KEY, btree (b) +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" +Child tables: cnn_pk_child + + Table "public.cnn_pk_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "cnn_pk_b_not_null" NOT NULL "b" (inherited) +Inherits: cnn_pk + +DROP TABLE cnn_pk, cnn_pk_child; +-- Unique constraints don't give raise to not-null constraints, however. +create table cnn_uq (a int); +alter table cnn_uq add unique (a); +\d+ cnn_uq + Table "public.cnn_uq" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Indexes: + "cnn_uq_a_key" UNIQUE CONSTRAINT, btree (a) + +drop table cnn_uq; +create table cnn_uq (a int); +create unique index cnn_uq_idx on cnn_uq (a); +alter table cnn_uq add unique using index cnn_uq_idx; +\d+ cnn_uq + Table "public.cnn_uq" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Indexes: + "cnn_uq_idx" UNIQUE CONSTRAINT, btree (a) + +-- can't create a primary key on a noinherit not-null +create table cnn_pk (a int not null no inherit); +alter table cnn_pk add primary key (a); +ERROR: cannot create primary key on column "a" +DETAIL: The constraint "cnn_pk_a_not_null" on column "a" of table "cnn_pk", marked NO INHERIT, is incompatible with a primary key. +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +drop table cnn_pk; +-- Ensure partitions are scanned for null values when adding a PK +create table cnn2_parted(a int) partition by list (a); +create table cnn_part1 partition of cnn2_parted for values in (1, null); +insert into cnn_part1 values (null); +alter table cnn2_parted add primary key (a); +ERROR: column "a" of relation "cnn_part1" contains null values +drop table cnn2_parted; +-- columns in regular and LIKE inheritance should be marked not-nullable +-- for primary keys, even if those are deferred +CREATE TABLE notnull_tbl4 (a INTEGER PRIMARY KEY INITIALLY DEFERRED); +CREATE TABLE notnull_tbl4_lk (LIKE notnull_tbl4); +CREATE TABLE notnull_tbl4_lk2 (LIKE notnull_tbl4 INCLUDING INDEXES); +CREATE TABLE notnull_tbl4_lk3 (LIKE notnull_tbl4 INCLUDING INDEXES, NOT NULL a); +ALTER TABLE notnull_tbl4_lk3 RENAME CONSTRAINT notnull_tbl4_a_not_null TO a_nn; +CREATE TABLE notnull_tbl4_cld () INHERITS (notnull_tbl4); +CREATE TABLE notnull_tbl4_cld2 (PRIMARY KEY (a) DEFERRABLE) INHERITS (notnull_tbl4); +CREATE TABLE notnull_tbl4_cld3 (PRIMARY KEY (a) DEFERRABLE, CONSTRAINT a_nn NOT NULL a) INHERITS (notnull_tbl4); +\d+ notnull_tbl4 + Table "public.notnull_tbl4" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl4_pkey" PRIMARY KEY, btree (a) DEFERRABLE INITIALLY DEFERRED +Not-null constraints: + "notnull_tbl4_a_not_null" NOT NULL "a" +Child tables: notnull_tbl4_cld, + notnull_tbl4_cld2, + notnull_tbl4_cld3 + +\d+ notnull_tbl4_lk + Table "public.notnull_tbl4_lk" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "notnull_tbl4_a_not_null" NOT NULL "a" + +\d+ notnull_tbl4_lk2 + Table "public.notnull_tbl4_lk2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl4_lk2_pkey" PRIMARY KEY, btree (a) DEFERRABLE INITIALLY DEFERRED +Not-null constraints: + "notnull_tbl4_a_not_null" NOT NULL "a" + +\d+ notnull_tbl4_lk3 + Table "public.notnull_tbl4_lk3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl4_lk3_pkey" PRIMARY KEY, btree (a) DEFERRABLE INITIALLY DEFERRED +Not-null constraints: + "a_nn" NOT NULL "a" + +\d+ notnull_tbl4_cld + Table "public.notnull_tbl4_cld" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "notnull_tbl4_a_not_null" NOT NULL "a" (inherited) +Inherits: notnull_tbl4 + +\d+ notnull_tbl4_cld2 + Table "public.notnull_tbl4_cld2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl4_cld2_pkey" PRIMARY KEY, btree (a) DEFERRABLE +Not-null constraints: + "notnull_tbl4_cld2_a_not_null" NOT NULL "a" (local, inherited) +Inherits: notnull_tbl4 + +\d+ notnull_tbl4_cld3 + Table "public.notnull_tbl4_cld3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Indexes: + "notnull_tbl4_cld3_pkey" PRIMARY KEY, btree (a) DEFERRABLE +Not-null constraints: + "a_nn" NOT NULL "a" (local, inherited) +Inherits: notnull_tbl4 + +-- leave these tables around for pg_upgrade testing +-- It's possible to remove a constraint from parents without affecting children +CREATE TABLE notnull_tbl5 (a int CONSTRAINT ann NOT NULL, + b int CONSTRAINT bnn NOT NULL); +CREATE TABLE notnull_tbl5_child () INHERITS (notnull_tbl5); +ALTER TABLE ONLY notnull_tbl5 DROP CONSTRAINT ann; +ALTER TABLE ONLY notnull_tbl5 ALTER b DROP NOT NULL; +\d+ notnull_tbl5_child + Table "public.notnull_tbl5_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "ann" NOT NULL "a" + "bnn" NOT NULL "b" +Inherits: notnull_tbl5 + +CREATE TABLE notnull_tbl6 (a int CONSTRAINT ann NOT NULL, + b int CONSTRAINT bnn NOT NULL, check (a > 0)) PARTITION BY LIST (a); +CREATE TABLE notnull_tbl6_1 PARTITION OF notnull_tbl6 FOR VALUES IN (1); +ALTER TABLE ONLY notnull_tbl6 DROP CONSTRAINT ann; +ALTER TABLE ONLY notnull_tbl6 ALTER b DROP NOT NULL; +\d+ notnull_tbl6_1 + Table "public.notnull_tbl6_1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | not null | | plain | | +Partition of: notnull_tbl6 FOR VALUES IN (1) +Partition constraint: ((a IS NOT NULL) AND (a = 1)) +Check constraints: + "notnull_tbl6_a_check" CHECK (a > 0) +Not-null constraints: + "ann" NOT NULL "a" + "bnn" NOT NULL "b" + +-- NOT NULL NOT VALID +PREPARE get_nnconstraint_info(regclass[]) AS +SELECT conrelid::regclass as tabname, conname, convalidated, conislocal, coninhcount +FROM pg_constraint +WHERE conrelid = ANY($1) +ORDER BY conrelid::regclass::text COLLATE "C", conname; +CREATE TABLE notnull_tbl1 (a int, b int); +INSERT INTO notnull_tbl1 VALUES (NULL, 1), (300, 3); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; -- error +ERROR: column "a" of relation "notnull_tbl1" contains null values +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a NOT VALID; -- ok +-- even an invalid not-null forbids new nulls +INSERT INTO notnull_tbl1 VALUES (NULL, 4); +ERROR: null value in column "a" of relation "notnull_tbl1" violates not-null constraint +DETAIL: Failing row contains (null, 4). +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | | | plain | | +Not-null constraints: + "nn" NOT NULL "a" NOT VALID + +-- If we have an invalid constraint, we can't have another +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn1 NOT NULL a NOT VALID NO INHERIT; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "nn" on relation "notnull_tbl1" +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; +ERROR: incompatible NOT VALID constraint "nn" on relation "notnull_tbl1" +HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT. +-- cannot add primary key on a column with an invalid not-null +ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a); +ERROR: cannot create primary key on column "a" +DETAIL: The constraint "nn" on column "a" of table "notnull_tbl1", marked NOT VALID, is incompatible with a primary key. +HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT. +-- ALTER column SET NOT NULL validates an invalid constraint (but this fails +-- because of rows with null values) +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +ERROR: column "a" of relation "notnull_tbl1" contains null values +\d+ notnull_tbl1 + Table "public.notnull_tbl1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | | | plain | | +Not-null constraints: + "nn" NOT NULL "a" NOT VALID + +-- Creating a derived table using LIKE gets the constraint, but it's valid +CREATE TABLE notnull_tbl1_copy (LIKE notnull_tbl1); +EXECUTE get_nnconstraint_info('{notnull_tbl1_copy}'); + tabname | conname | convalidated | conislocal | coninhcount +-------------------+---------+--------------+------------+------------- + notnull_tbl1_copy | nn | t | t | 0 +(1 row) + +-- An inheritance child table gets the constraint, but it's valid +CREATE TABLE notnull_tbl1_child (a int, b int) INHERITS (notnull_tbl1); +NOTICE: merging column "a" with inherited definition +NOTICE: merging column "b" with inherited definition +EXECUTE get_nnconstraint_info('{notnull_tbl1_child, notnull_tbl1}'); + tabname | conname | convalidated | conislocal | coninhcount +--------------------+---------+--------------+------------+------------- + notnull_tbl1 | nn | f | t | 0 + notnull_tbl1_child | nn | t | f | 1 +(2 rows) + +-- Also try inheritance added after table creation +CREATE TABLE notnull_tbl1_child2 (c int, b int, a int); +ALTER TABLE notnull_tbl1_child2 INHERIT notnull_tbl1; -- nope +ERROR: column "a" in child table "notnull_tbl1_child2" must be marked NOT NULL +ALTER TABLE notnull_tbl1_child2 ADD NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1_child2 INHERIT notnull_tbl1; +EXECUTE get_nnconstraint_info('{notnull_tbl1_child2}'); + tabname | conname | convalidated | conislocal | coninhcount +---------------------+--------------------------------+--------------+------------+------------- + notnull_tbl1_child2 | notnull_tbl1_child2_a_not_null | f | t | 1 +(1 row) + +--table rewrite won't validate invalid constraint +ALTER TABLE notnull_tbl1 ADD column d float8 default random(); +-- VALIDATE CONSTRAINT scans the table +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- error, nulls exist +ERROR: column "a" of relation "notnull_tbl1" contains null values +UPDATE notnull_tbl1 SET a = 100 WHERE b = 1; +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- now ok +EXECUTE get_nnconstraint_info('{notnull_tbl1}'); + tabname | conname | convalidated | conislocal | coninhcount +--------------+---------+--------------+------------+------------- + notnull_tbl1 | nn | t | t | 0 +(1 row) + +--- now we can add primary key +ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a); +DROP TABLE notnull_tbl1, notnull_tbl1_child, notnull_tbl1_child2; +-- dropping an invalid constraint is possible +CREATE TABLE notnull_tbl1 (a int, b int); +ALTER TABLE notnull_tbl1 ADD NOT NULL a NOT VALID, + ADD NOT NULL b NOT VALID; +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +ALTER TABLE notnull_tbl1 DROP CONSTRAINT notnull_tbl1_b_not_null; +DROP TABLE notnull_tbl1; +-- ALTER .. NO INHERIT works for invalid constraints +CREATE TABLE notnull_tbl1 (a int); +CREATE TABLE notnull_tbl1_chld () INHERITS (notnull_tbl1); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nntbl1_a NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1 ALTER CONSTRAINT nntbl1_a NO INHERIT; +-- DROP CONSTRAINT recurses correctly on invalid constraints +ALTER TABLE notnull_tbl1 ALTER CONSTRAINT nntbl1_a INHERIT; +ALTER TABLE notnull_tbl1 DROP CONSTRAINT nntbl1_a; +DROP TABLE notnull_tbl1, notnull_tbl1_chld; +-- if a parent has a valid not null constraint then a child table cannot +-- have an invalid one +CREATE TABLE notnull_tbl1 (a int); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn_parent NOT NULL a not valid; +CREATE TABLE notnull_chld0 (a int, CONSTRAINT nn_chld0 NOT NULL a); +ALTER TABLE notnull_tbl1 INHERIT notnull_chld0; --error +ERROR: constraint "nn_parent" conflicts with NOT VALID constraint on child table "notnull_tbl1" +ALTER TABLE notnull_chld0 DROP CONSTRAINT nn_chld0; +ALTER TABLE notnull_chld0 ADD CONSTRAINT nn_chld0 NOT NULL a not valid; +ALTER TABLE notnull_tbl1 INHERIT notnull_chld0; --now ok +-- parents and child not-null will all be validated. +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn_parent; +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_chld0}'); + tabname | conname | convalidated | conislocal | coninhcount +---------------+-----------+--------------+------------+------------- + notnull_chld0 | nn_chld0 | f | t | 0 + notnull_tbl1 | nn_parent | t | t | 1 +(2 rows) + +DROP TABLE notnull_tbl1, notnull_chld0; +-- Test invalid not null on inheritance table. +CREATE TABLE notnull_inhparent (i int); +CREATE TABLE notnull_inhchild (i int) INHERITS (notnull_inhparent); +NOTICE: merging column "i" with inherited definition +CREATE TABLE notnull_inhgrand () INHERITS (notnull_inhparent, notnull_inhchild); +NOTICE: merging multiple inherited definitions of column "i" +ALTER TABLE notnull_inhparent ADD CONSTRAINT nn NOT NULL i NOT VALID; +ALTER TABLE notnull_inhchild ADD CONSTRAINT nn1 NOT NULL i; -- error +ERROR: incompatible NOT VALID constraint "nn" on relation "notnull_inhchild" +HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT. +EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); + tabname | conname | convalidated | conislocal | coninhcount +-------------------+---------+--------------+------------+------------- + notnull_inhchild | nn | f | f | 1 + notnull_inhgrand | nn | f | f | 2 + notnull_inhparent | nn | f | t | 0 +(3 rows) + +ALTER TABLE notnull_inhparent ALTER i SET NOT NULL; -- ok +EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); + tabname | conname | convalidated | conislocal | coninhcount +-------------------+---------+--------------+------------+------------- + notnull_inhchild | nn | t | f | 1 + notnull_inhgrand | nn | t | f | 2 + notnull_inhparent | nn | t | t | 0 +(3 rows) + +DROP TABLE notnull_inhparent, notnull_inhchild, notnull_inhgrand; +-- Verify NOT NULL VALID/NOT VALID with partition table. +DROP TABLE notnull_tbl1; +ERROR: table "notnull_tbl1" does not exist +CREATE TABLE notnull_tbl1 (a int, b int) PARTITION BY LIST (a); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT notnull_con NOT NULL a NOT VALID; --ok +CREATE TABLE notnull_tbl1_1 PARTITION OF notnull_tbl1 FOR VALUES IN (1,2); +CREATE TABLE notnull_tbl1_2(a int, CONSTRAINT nn2 NOT NULL a, b int); +ALTER TABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_2 FOR VALUES IN (3,4); +CREATE TABLE notnull_tbl1_3(a int, b int); +INSERT INTO notnull_tbl1_3 values(NULL,1); +ALTER TABLE notnull_tbl1_3 add CONSTRAINT nn3 NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_3 FOR VALUES IN (NULL,5); +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_tbl1_1, notnull_tbl1_2, notnull_tbl1_3}'); + tabname | conname | convalidated | conislocal | coninhcount +----------------+-------------+--------------+------------+------------- + notnull_tbl1 | notnull_con | f | t | 0 + notnull_tbl1_1 | notnull_con | t | f | 1 + notnull_tbl1_2 | nn2 | t | f | 1 + notnull_tbl1_3 | nn3 | f | f | 1 +(4 rows) + +ALTER TABLE notnull_tbl1 ALTER COLUMN a SET NOT NULL; --error, notnull_tbl1_3 have null values +ERROR: column "a" of relation "notnull_tbl1_3" contains null values +ALTER TABLE notnull_tbl1_3 VALIDATE CONSTRAINT nn3; --error +ERROR: column "a" of relation "notnull_tbl1_3" contains null values +TRUNCATE notnull_tbl1; +ALTER TABLE notnull_tbl1 ALTER COLUMN a SET NOT NULL; --OK +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_tbl1_1, notnull_tbl1_2, notnull_tbl1_3}'); + tabname | conname | convalidated | conislocal | coninhcount +----------------+-------------+--------------+------------+------------- + notnull_tbl1 | notnull_con | t | t | 0 + notnull_tbl1_1 | notnull_con | t | f | 1 + notnull_tbl1_2 | nn2 | t | f | 1 + notnull_tbl1_3 | nn3 | t | f | 1 +(4 rows) + +DROP TABLE notnull_tbl1; +-- partitioned table have not-null, then the partitions can not be NOT NULL NOT VALID. +CREATE TABLE pp_nn (a int, b int, NOT NULL a) PARTITION BY LIST (a); +CREATE TABLE pp_nn_1(a int, b int); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn1 NOT NULL a NOT VALID; +ALTER TABLE pp_nn ATTACH PARTITION pp_nn_1 FOR VALUES IN (NULL,5); --error +ERROR: constraint "nn1" conflicts with NOT VALID constraint on child table "pp_nn_1" +ALTER TABLE pp_nn_1 VALIDATE CONSTRAINT nn1; +ALTER TABLE pp_nn ATTACH PARTITION pp_nn_1 FOR VALUES IN (NULL,5); --ok +DROP TABLE pp_nn; +-- Try a partition with an invalid constraint and create a PK on the parent. +CREATE TABLE pp_nn (a int) PARTITION BY HASH (a); +CREATE TABLE pp_nn_1 PARTITION OF pp_nn FOR VALUES WITH (MODULUS 2, REMAINDER 0); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn NOT NULL a NOT VALID; +ALTER TABLE ONLY pp_nn ADD PRIMARY KEY (a); +ERROR: cannot create primary key on column "a" +DETAIL: The constraint "nn" on column "a" of table "pp_nn_1", marked NOT VALID, is incompatible with a primary key. +HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT. +DROP TABLE pp_nn; +-- same as above, but the constraint is NO INHERIT +CREATE TABLE pp_nn (a int) PARTITION BY HASH (a); +CREATE TABLE pp_nn_1 PARTITION OF pp_nn FOR VALUES WITH (MODULUS 2, REMAINDER 0); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn NOT NULL a NO INHERIT; +ALTER TABLE ONLY pp_nn ADD PRIMARY KEY (a); +ERROR: cannot create primary key on column "a" +DETAIL: The constraint "nn" on column "a" of table "pp_nn_1", marked NO INHERIT, is incompatible with a primary key. +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +DROP TABLE pp_nn; +-- Create table with NOT NULL INVALID constraint, for pg_upgrade. +CREATE TABLE notnull_tbl1_upg (a int, b int); +INSERT INTO notnull_tbl1_upg VALUES (NULL, 1), (NULL, 2), (300, 3); +ALTER TABLE notnull_tbl1_upg ADD CONSTRAINT nn NOT NULL a NOT VALID; +-- Inherit test for pg_upgrade +CREATE TABLE notnull_parent_upg (a int); +CREATE TABLE notnull_child_upg () INHERITS (notnull_parent_upg); +ALTER TABLE notnull_child_upg ADD CONSTRAINT nn NOT NULL a; +ALTER TABLE notnull_parent_upg ADD CONSTRAINT nn NOT NULL a NOT VALID; +SELECT conrelid::regclass, contype, convalidated, conislocal +FROM pg_catalog.pg_constraint +WHERE conrelid in ('notnull_parent_upg'::regclass, 'notnull_child_upg'::regclass) +ORDER BY 1; + conrelid | contype | convalidated | conislocal +--------------------+---------+--------------+------------ + notnull_parent_upg | n | f | t + notnull_child_upg | n | t | t +(2 rows) + +-- Partition table test, for pg_upgrade +CREATE TABLE notnull_part1_upg (a int, b int) PARTITION BY LIST (a); +ALTER TABLE notnull_part1_upg ADD CONSTRAINT notnull_con NOT NULL a NOT VALID; --ok +CREATE TABLE notnull_part1_1_upg PARTITION OF notnull_part1_upg FOR VALUES IN (1,2); +CREATE TABLE notnull_part1_2_upg (a int, CONSTRAINT nn2 NOT NULL a, b int); +ALTER TABLE notnull_part1_upg ATTACH PARTITION notnull_part1_2_upg FOR VALUES IN (3,4); +CREATE TABLE notnull_part1_3_upg (a int, b int); +INSERT INTO notnull_part1_3_upg values(NULL,1); +ALTER TABLE notnull_part1_3_upg add CONSTRAINT nn3 NOT NULL a NOT VALID; +ALTER TABLE notnull_part1_upg ATTACH PARTITION notnull_part1_3_upg FOR VALUES IN (NULL,5); +EXECUTE get_nnconstraint_info('{notnull_part1_upg, notnull_part1_1_upg, notnull_part1_2_upg, notnull_part1_3_upg}'); + tabname | conname | convalidated | conislocal | coninhcount +---------------------+-------------+--------------+------------+------------- + notnull_part1_1_upg | notnull_con | t | f | 1 + notnull_part1_2_upg | nn2 | t | f | 1 + notnull_part1_3_upg | nn3 | f | f | 1 + notnull_part1_upg | notnull_con | f | t | 0 +(4 rows) + +-- Inheritance test tables for pg_upgrade +create table constr_parent (a int); +create table constr_child (a int) inherits (constr_parent); +NOTICE: merging column "a" with inherited definition +alter table constr_parent add not null a not valid; +alter table constr_child validate constraint constr_parent_a_not_null; +EXECUTE get_nnconstraint_info('{constr_parent, constr_child}'); + tabname | conname | convalidated | conislocal | coninhcount +---------------+--------------------------+--------------+------------+------------- + constr_child | constr_parent_a_not_null | t | f | 1 + constr_parent | constr_parent_a_not_null | f | t | 0 +(2 rows) + +create table constr_parent2 (a int); +create table constr_child2 () inherits (constr_parent2); +alter table constr_parent2 add not null a not valid; +alter table constr_child2 validate constraint constr_parent2_a_not_null; +EXECUTE get_nnconstraint_info('{constr_parent2, constr_child2}'); + tabname | conname | convalidated | conislocal | coninhcount +----------------+---------------------------+--------------+------------+------------- + constr_child2 | constr_parent2_a_not_null | t | f | 1 + constr_parent2 | constr_parent2_a_not_null | f | t | 0 +(2 rows) + +create table constr_parent3 (a int not null); +create table constr_child3 () inherits (constr_parent2, constr_parent3); +NOTICE: merging multiple inherited definitions of column "a" +EXECUTE get_nnconstraint_info('{constr_parent3, constr_child3}'); + tabname | conname | convalidated | conislocal | coninhcount +----------------+---------------------------+--------------+------------+------------- + constr_child3 | constr_parent2_a_not_null | t | f | 2 + constr_parent3 | constr_parent3_a_not_null | t | t | 0 +(2 rows) + +DEALLOCATE get_nnconstraint_info; +-- end NOT NULL NOT VALID -- Comments -- Setup a low-level role to enforce non-superuser checks. CREATE ROLE regress_constraint_comments; diff --git a/src/test/regress/expected/conversion.out b/src/test/regress/expected/conversion.out index 442e7aff2b2c1..7dd1ef6161f06 100644 --- a/src/test/regress/expected/conversion.out +++ b/src/test/regress/expected/conversion.out @@ -5,6 +5,13 @@ \getenv libdir PG_LIBDIR \getenv dlsuffix PG_DLSUFFIX \set regresslib :libdir '/regress' :dlsuffix +CREATE FUNCTION test_enc_setup() RETURNS void + AS :'regresslib', 'test_enc_setup' + LANGUAGE C STRICT; +SELECT FROM test_enc_setup(); +-- +(1 row) + CREATE FUNCTION test_enc_conversion(bytea, name, name, bool, validlen OUT int, result OUT bytea) AS :'regresslib', 'test_enc_conversion' LANGUAGE C STRICT; @@ -501,10 +508,13 @@ insert into gb18030_inputs values ('\x666f6f84309c38', 'valid, translates to UTF-8 by mapping function'), ('\x666f6f84309c', 'incomplete char '), ('\x666f6f84309c0a', 'incomplete char, followed by newline '), + ('\x666f6f84', 'incomplete char at end'), ('\x666f6f84309c3800', 'invalid, NUL byte'), ('\x666f6f84309c0038', 'invalid, NUL byte'); --- Test GB18030 verification -select description, inbytes, (test_conv(inbytes, 'gb18030', 'gb18030')).* from gb18030_inputs; +-- Test GB18030 verification. Round-trip through text so the backing of the +-- bytea values is palloc, not shared_buffers. This lets Valgrind detect +-- reads past the end. +select description, inbytes, (test_conv(inbytes::text::bytea, 'gb18030', 'gb18030')).* from gb18030_inputs; description | inbytes | result | errorat | error ------------------------------------------------+--------------------+------------------+--------------+------------------------------------------------------------------- valid, pure ASCII | \x666f6f | \x666f6f | | @@ -513,9 +523,10 @@ select description, inbytes, (test_conv(inbytes, 'gb18030', 'gb18030')).* from g valid, translates to UTF-8 by mapping function | \x666f6f84309c38 | \x666f6f84309c38 | | incomplete char | \x666f6f84309c | \x666f6f | \x84309c | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c incomplete char, followed by newline | \x666f6f84309c0a | \x666f6f | \x84309c0a | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c 0x0a + incomplete char at end | \x666f6f84 | \x666f6f | \x84 | invalid byte sequence for encoding "GB18030": 0x84 invalid, NUL byte | \x666f6f84309c3800 | \x666f6f84309c38 | \x00 | invalid byte sequence for encoding "GB18030": 0x00 invalid, NUL byte | \x666f6f84309c0038 | \x666f6f | \x84309c0038 | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c 0x00 -(8 rows) +(9 rows) -- Test conversions from GB18030 select description, inbytes, (test_conv(inbytes, 'gb18030', 'utf8')).* from gb18030_inputs; @@ -527,9 +538,10 @@ select description, inbytes, (test_conv(inbytes, 'gb18030', 'utf8')).* from gb18 valid, translates to UTF-8 by mapping function | \x666f6f84309c38 | \x666f6fefa8aa | | incomplete char | \x666f6f84309c | \x666f6f | \x84309c | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c incomplete char, followed by newline | \x666f6f84309c0a | \x666f6f | \x84309c0a | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c 0x0a + incomplete char at end | \x666f6f84 | \x666f6f | \x84 | invalid byte sequence for encoding "GB18030": 0x84 invalid, NUL byte | \x666f6f84309c3800 | \x666f6fefa8aa | \x00 | invalid byte sequence for encoding "GB18030": 0x00 invalid, NUL byte | \x666f6f84309c0038 | \x666f6f | \x84309c0038 | invalid byte sequence for encoding "GB18030": 0x84 0x30 0x9c 0x00 -(8 rows) +(9 rows) -- -- ISO-8859-5 diff --git a/src/test/regress/expected/copy.out b/src/test/regress/expected/copy.out index 44114089a6dce..8d5a06563c44a 100644 --- a/src/test/regress/expected/copy.out +++ b/src/test/regress/expected/copy.out @@ -32,6 +32,37 @@ select * from copytest except select * from copytest2; -------+------+-------- (0 rows) +--- test unquoted \. as data inside CSV +-- do not use copy out to export the data, as it would quote \. +\o :filename +\qecho line1 +\qecho '\\.' +\qecho line2 +\o +-- get the data back in with copy +truncate copytest2; +copy copytest2(test) from :'filename' csv; +select test from copytest2 order by test collate "C"; + test +------- + \. + line1 + line2 +(3 rows) + +-- in text mode, \. must be alone on its line +truncate copytest2; +copy copytest2(test) from stdin; +ERROR: end-of-copy marker is not alone on its line +CONTEXT: COPY copytest2, line 3 +copy copytest2(test) from stdin; +ERROR: end-of-copy marker is not alone on its line +CONTEXT: COPY copytest2, line 3 +select test from copytest2; + test +------ +(0 rows) + -- test header line feature create temp table copytest3 ( c1 int, @@ -150,7 +181,8 @@ begin bytes_processed > 0 as has_bytes_processed, bytes_total > 0 as has_bytes_total, tuples_processed, - tuples_excluded + tuples_excluded, + tuples_skipped from pg_stat_progress_copy where pid = pg_backend_pid()) select into report (to_jsonb(r)) as value @@ -166,13 +198,17 @@ create trigger check_after_tab_progress_reporting execute function notice_after_tab_progress_reporting(); -- Generate COPY FROM report with PIPE. copy tab_progress_reporting from stdin; -INFO: progress: {"type": "PIPE", "command": "COPY FROM", "relname": "tab_progress_reporting", "has_bytes_total": false, "tuples_excluded": 0, "tuples_processed": 3, "has_bytes_processed": true} +INFO: progress: {"type": "PIPE", "command": "COPY FROM", "relname": "tab_progress_reporting", "tuples_skipped": 0, "has_bytes_total": false, "tuples_excluded": 0, "tuples_processed": 3, "has_bytes_processed": true} -- Generate COPY FROM report with FILE, with some excluded tuples. truncate tab_progress_reporting; \set filename :abs_srcdir '/data/emp.data' copy tab_progress_reporting from :'filename' where (salary < 2000); -INFO: progress: {"type": "FILE", "command": "COPY FROM", "relname": "tab_progress_reporting", "has_bytes_total": true, "tuples_excluded": 1, "tuples_processed": 2, "has_bytes_processed": true} +INFO: progress: {"type": "FILE", "command": "COPY FROM", "relname": "tab_progress_reporting", "tuples_skipped": 0, "has_bytes_total": true, "tuples_excluded": 1, "tuples_processed": 2, "has_bytes_processed": true} +-- Generate COPY FROM report with PIPE, with some skipped tuples. +copy tab_progress_reporting from stdin(on_error ignore); +NOTICE: 2 rows were skipped due to data type incompatibility +INFO: progress: {"type": "PIPE", "command": "COPY FROM", "relname": "tab_progress_reporting", "tuples_skipped": 2, "has_bytes_total": false, "tuples_excluded": 0, "tuples_processed": 1, "has_bytes_processed": true} drop trigger check_after_tab_progress_reporting on tab_progress_reporting; drop function notice_after_tab_progress_reporting(); drop table tab_progress_reporting; @@ -294,3 +330,23 @@ SELECT tableoid::regclass, id % 2 = 0 is_even, count(*) from parted_si GROUP BY (2 rows) DROP TABLE parted_si; +-- ensure COPY FREEZE errors for foreign tables +begin; +create foreign data wrapper copytest_wrapper; +create server copytest_server foreign data wrapper copytest_wrapper; +create foreign table copytest_foreign_table (a int) server copytest_server; +copy copytest_foreign_table from stdin (freeze); +ERROR: cannot perform COPY FREEZE on a foreign table +rollback; +-- Tests for COPY TO with materialized views. +-- COPY TO should fail for an unpopulated materialized view +-- but succeed for a populated one. +CREATE MATERIALIZED VIEW copytest_mv AS SELECT 1 AS id WITH NO DATA; +COPY copytest_mv(id) TO stdout WITH (header); +ERROR: cannot copy from unpopulated materialized view "copytest_mv" +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW copytest_mv; +COPY copytest_mv(id) TO stdout WITH (header); +id +1 +DROP MATERIALIZED VIEW copytest_mv; diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out index 931542f2689c7..64ea33aeae8fd 100644 --- a/src/test/regress/expected/copy2.out +++ b/src/test/regress/expected/copy2.out @@ -86,9 +86,9 @@ ERROR: conflicting or redundant options LINE 1: COPY x from stdin (log_verbosity default, log_verbosity verb... ^ -- incorrect options -COPY x to stdin (format BINARY, delimiter ','); +COPY x from stdin (format BINARY, delimiter ','); ERROR: cannot specify DELIMITER in BINARY mode -COPY x to stdin (format BINARY, null 'x'); +COPY x from stdin (format BINARY, null 'x'); ERROR: cannot specify NULL in BINARY mode COPY x from stdin (format BINARY, on_error ignore); ERROR: only ON_ERROR STOP is allowed in BINARY mode @@ -96,26 +96,42 @@ COPY x from stdin (on_error unsupported); ERROR: COPY ON_ERROR "unsupported" not recognized LINE 1: COPY x from stdin (on_error unsupported); ^ -COPY x to stdin (format TEXT, force_quote(a)); +COPY x from stdin (format TEXT, force_quote(a)); +ERROR: COPY FORCE_QUOTE requires CSV mode +COPY x from stdin (format TEXT, force_quote *); ERROR: COPY FORCE_QUOTE requires CSV mode COPY x from stdin (format CSV, force_quote(a)); ERROR: COPY FORCE_QUOTE cannot be used with COPY FROM -COPY x to stdout (format TEXT, force_not_null(a)); +COPY x from stdin (format CSV, force_quote *); +ERROR: COPY FORCE_QUOTE cannot be used with COPY FROM +COPY x from stdin (format TEXT, force_not_null(a)); +ERROR: COPY FORCE_NOT_NULL requires CSV mode +COPY x from stdin (format TEXT, force_not_null *); ERROR: COPY FORCE_NOT_NULL requires CSV mode -COPY x to stdin (format CSV, force_not_null(a)); +COPY x to stdout (format CSV, force_not_null(a)); ERROR: COPY FORCE_NOT_NULL cannot be used with COPY TO -COPY x to stdout (format TEXT, force_null(a)); +COPY x to stdout (format CSV, force_not_null *); +ERROR: COPY FORCE_NOT_NULL cannot be used with COPY TO +COPY x from stdin (format TEXT, force_null(a)); +ERROR: COPY FORCE_NULL requires CSV mode +COPY x from stdin (format TEXT, force_null *); ERROR: COPY FORCE_NULL requires CSV mode -COPY x to stdin (format CSV, force_null(a)); +COPY x to stdout (format CSV, force_null(a)); ERROR: COPY FORCE_NULL cannot be used with COPY TO -COPY x to stdin (format BINARY, on_error unsupported); +COPY x to stdout (format CSV, force_null *); +ERROR: COPY FORCE_NULL cannot be used with COPY TO +COPY x to stdout (format BINARY, on_error unsupported); ERROR: COPY ON_ERROR cannot be used with COPY TO -LINE 1: COPY x to stdin (format BINARY, on_error unsupported); - ^ -COPY x to stdout (log_verbosity unsupported); +LINE 1: COPY x to stdout (format BINARY, on_error unsupported); + ^ +COPY x from stdin (log_verbosity unsupported); ERROR: COPY LOG_VERBOSITY "unsupported" not recognized -LINE 1: COPY x to stdout (log_verbosity unsupported); - ^ +LINE 1: COPY x from stdin (log_verbosity unsupported); + ^ +COPY x from stdin with (reject_limit 1); +ERROR: COPY REJECT_LIMIT requires ON_ERROR to be set to IGNORE +COPY x from stdin with (on_error ignore, reject_limit 0); +ERROR: REJECT_LIMIT (0) must be greater than zero -- too many columns in column list: should fail COPY x (a, b, c, d, e, d, c) from stdin; ERROR: column "d" specified more than once @@ -740,26 +756,27 @@ CONTEXT: COPY check_ign_err, line 2, column n: "a" -- want context for notices \set SHOW_CONTEXT always COPY check_ign_err FROM STDIN WITH (on_error ignore, log_verbosity verbose); -NOTICE: skipping row due to data type incompatibility at line 2 for column n: "a" +NOTICE: skipping row due to data type incompatibility at line 2 for column "n": "a" CONTEXT: COPY check_ign_err -NOTICE: skipping row due to data type incompatibility at line 3 for column k: "3333333333" +NOTICE: skipping row due to data type incompatibility at line 3 for column "k": "3333333333" CONTEXT: COPY check_ign_err -NOTICE: skipping row due to data type incompatibility at line 4 for column m: "{a, 4}" +NOTICE: skipping row due to data type incompatibility at line 4 for column "m": "{a, 4}" CONTEXT: COPY check_ign_err -NOTICE: skipping row due to data type incompatibility at line 5 for column n: "" +NOTICE: skipping row due to data type incompatibility at line 5 for column "n": "" CONTEXT: COPY check_ign_err -NOTICE: skipping row due to data type incompatibility at line 7 for column m: "a" +NOTICE: skipping row due to data type incompatibility at line 7 for column "m": "a" CONTEXT: COPY check_ign_err -NOTICE: skipping row due to data type incompatibility at line 8 for column k: "a" +NOTICE: skipping row due to data type incompatibility at line 8 for column "k": "a" CONTEXT: COPY check_ign_err NOTICE: 6 rows were skipped due to data type incompatibility -- tests for on_error option with log_verbosity and null constraint via domain CREATE DOMAIN dcheck_ign_err2 varchar(15) NOT NULL; CREATE TABLE check_ign_err2 (n int, m int[], k int, l dcheck_ign_err2); COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity verbose); -NOTICE: skipping row due to data type incompatibility at line 2 for column l: null input +NOTICE: skipping row due to data type incompatibility at line 2 for column "l": null input CONTEXT: COPY check_ign_err2 NOTICE: 1 row was skipped due to data type incompatibility +COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity silent); -- reset context choice \set SHOW_CONTEXT errors SELECT * FROM check_ign_err; @@ -774,7 +791,8 @@ SELECT * FROM check_ign_err2; n | m | k | l ---+-----+---+------- 1 | {1} | 1 | 'foo' -(1 row) + 3 | {3} | 3 | 'bar' +(2 rows) -- test datatype error that can't be handled as soft: should fail CREATE TABLE hard_err(foo widget); @@ -789,6 +807,12 @@ CONTEXT: COPY check_ign_err, line 1: "1 {1}" COPY check_ign_err FROM STDIN WITH (on_error ignore); ERROR: extra data after last expected column CONTEXT: COPY check_ign_err, line 1: "1 {1} 3 abc" +-- tests for reject_limit option +COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 3); +ERROR: skipped more than REJECT_LIMIT (3) rows due to data type incompatibility +CONTEXT: COPY check_ign_err, line 5, column n: "" +COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 4); +NOTICE: 4 rows were skipped due to data type incompatibility -- clean up DROP TABLE forcetest; DROP TABLE vistest; @@ -844,7 +868,7 @@ copy copy_default from stdin with (default E'\r'); ERROR: COPY default representation cannot use newline or carriage return -- DELIMITER cannot appear in DEFAULT spec copy copy_default from stdin with (delimiter ';', default 'test;test'); -ERROR: COPY delimiter must not appear in the DEFAULT specification +ERROR: COPY delimiter character must not appear in the DEFAULT specification -- CSV quote cannot appear in DEFAULT spec copy copy_default from stdin with (format csv, quote '"', default 'test"test'); ERROR: CSV quote character must not appear in the DEFAULT specification @@ -904,4 +928,4 @@ select id, text_value, ts_value from copy_default; truncate copy_default; -- DEFAULT cannot be used in COPY TO copy (select 1 as test) TO stdout with (default '\D'); -ERROR: COPY DEFAULT only available using COPY FROM +ERROR: COPY DEFAULT cannot be used with COPY TO diff --git a/src/test/regress/expected/copydml.out b/src/test/regress/expected/copydml.out index b5a225628f46e..e91e83260aa05 100644 --- a/src/test/regress/expected/copydml.out +++ b/src/test/regress/expected/copydml.out @@ -38,7 +38,7 @@ ERROR: DO INSTEAD NOTHING rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on insert to copydml_test do also delete from copydml_test; copy (insert into copydml_test default values) to stdout; -ERROR: DO ALSO rules are not supported for the COPY +ERROR: DO ALSO rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on insert to copydml_test do instead (delete from copydml_test; delete from copydml_test); copy (insert into copydml_test default values) to stdout; @@ -54,7 +54,7 @@ ERROR: DO INSTEAD NOTHING rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on update to copydml_test do also delete from copydml_test; copy (update copydml_test set t = 'f') to stdout; -ERROR: DO ALSO rules are not supported for the COPY +ERROR: DO ALSO rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on update to copydml_test do instead (delete from copydml_test; delete from copydml_test); copy (update copydml_test set t = 'f') to stdout; @@ -70,7 +70,7 @@ ERROR: DO INSTEAD NOTHING rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on delete to copydml_test do also insert into copydml_test default values; copy (delete from copydml_test) to stdout; -ERROR: DO ALSO rules are not supported for the COPY +ERROR: DO ALSO rules are not supported for COPY drop rule qqq on copydml_test; create rule qqq as on delete to copydml_test do instead (insert into copydml_test default values; insert into copydml_test default values); copy (delete from copydml_test) to stdout; @@ -80,6 +80,10 @@ create rule qqq as on delete to copydml_test where old.t <> 'f' do instead inser copy (delete from copydml_test) to stdout; ERROR: conditional DO INSTEAD rules are not supported for COPY drop rule qqq on copydml_test; +create rule qqq as on insert to copydml_test do instead notify copydml_test; +copy (insert into copydml_test default values) to stdout; +ERROR: COPY query must not be a utility command +drop rule qqq on copydml_test; -- triggers create function qqq_trig() returns trigger as $$ begin diff --git a/src/test/regress/expected/copyencoding.out b/src/test/regress/expected/copyencoding.out new file mode 100644 index 0000000000000..cfa2ed6df0081 --- /dev/null +++ b/src/test/regress/expected/copyencoding.out @@ -0,0 +1,46 @@ +-- +-- Test cases for encoding with COPY commands +-- +-- skip test if not UTF8 server encoding +SELECT getdatabaseencoding() <> 'UTF8' + AS skip_test \gset +\if :skip_test +\quit +\endif +-- directory paths are passed to us in environment variables +\getenv abs_builddir PG_ABS_BUILDDIR +\set utf8_csv :abs_builddir '/results/copyencoding_utf8.csv' +CREATE TABLE copy_encoding_tab (t text); +-- Valid cases +-- Use ENCODING option +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv, ENCODING 'UTF8'); +-- Read UTF8 data as LATIN1: no error +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv, ENCODING 'LATIN1'); +-- Use client_encoding +SET client_encoding TO UTF8; +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv); +-- Read UTF8 data as LATIN1: no error +SET client_encoding TO LATIN1; +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv); +RESET client_encoding; +-- Invalid cases +-- Use ENCODING explicitly +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv, ENCODING 'UTF8'); +-- Read UTF8 data as EUC_JP: no error +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv, ENCODING 'EUC_JP'); +ERROR: invalid byte sequence for encoding "EUC_JP": 0xe3 0x81 +CONTEXT: COPY copy_encoding_tab, line 1 +-- Use client_encoding +SET client_encoding TO UTF8; +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv); +-- Read UTF8 data as EUC_JP: no error +SET client_encoding TO EUC_JP; +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv); +ERROR: invalid byte sequence for encoding "EUC_JP": 0xe3 0x81 +CONTEXT: COPY copy_encoding_tab, line 1 +RESET client_encoding; +DROP TABLE copy_encoding_tab; diff --git a/src/test/regress/expected/copyencoding_1.out b/src/test/regress/expected/copyencoding_1.out new file mode 100644 index 0000000000000..a85ee2dbd1844 --- /dev/null +++ b/src/test/regress/expected/copyencoding_1.out @@ -0,0 +1,8 @@ +-- +-- Test cases for encoding with COPY commands +-- +-- skip test if not UTF8 server encoding +SELECT getdatabaseencoding() <> 'UTF8' + AS skip_test \gset +\if :skip_test +\quit diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out index 35d4cf1d46719..c1a951572512c 100644 --- a/src/test/regress/expected/create_am.out +++ b/src/test/regress/expected/create_am.out @@ -343,6 +343,20 @@ ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2; ERROR: cannot have multiple SET ACCESS METHOD subcommands DROP MATERIALIZED VIEW heapmv; DROP TABLE heaptable; +-- Partitioned table with USING +CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2; +SELECT pg_describe_object(classid, objid, objsubid) AS obj, + pg_describe_object(refclassid, refobjid, refobjsubid) as refobj + FROM pg_depend, pg_am + WHERE pg_depend.refclassid = 'pg_am'::regclass + AND pg_am.oid = pg_depend.refobjid + AND pg_depend.objid = 'am_partitioned'::regclass; + obj | refobj +----------------------+--------------------- + table am_partitioned | access method heap2 +(1 row) + +DROP TABLE am_partitioned; -- Partition hierarchies with access methods BEGIN; SET LOCAL default_table_access_method = 'heap'; diff --git a/src/test/regress/expected/create_cast.out b/src/test/regress/expected/create_cast.out index 9a56fe3f0fd9d..fd4871d94db72 100644 --- a/src/test/regress/expected/create_cast.out +++ b/src/test/regress/expected/create_cast.out @@ -13,6 +13,8 @@ CREATE FUNCTION casttesttype_out(casttesttype) AS 'textout' LANGUAGE internal STRICT IMMUTABLE; NOTICE: argument type casttesttype is only a shell +LINE 1: CREATE FUNCTION casttesttype_out(casttesttype) + ^ CREATE TYPE casttesttype ( internallength = variable, input = casttesttype_in, diff --git a/src/test/regress/expected/create_function_sql.out b/src/test/regress/expected/create_function_sql.out index 50aca5940ff7d..963b6f863ff95 100644 --- a/src/test/regress/expected/create_function_sql.out +++ b/src/test/regress/expected/create_function_sql.out @@ -563,6 +563,20 @@ CREATE OR REPLACE PROCEDURE functest1(a int) LANGUAGE SQL AS 'SELECT $1'; ERROR: cannot change routine kind DETAIL: "functest1" is a function. DROP FUNCTION functest1(a int); +-- early shutdown of set-returning functions +CREATE FUNCTION functest_srf0() RETURNS SETOF int +LANGUAGE SQL +AS $$ SELECT i FROM generate_series(1, 100) i $$; +SELECT functest_srf0() LIMIT 5; + functest_srf0 +--------------- + 1 + 2 + 3 + 4 + 5 +(5 rows) + -- inlining of set-returning functions CREATE TABLE functest3 (a int); INSERT INTO functest3 VALUES (1), (2), (3); @@ -666,6 +680,43 @@ SELECT * FROM voidtest5(3); ----------- (0 rows) +-- DDL within a SQL function can now affect later statements in the function; +-- though that doesn't work if check_function_bodies is on. +SET check_function_bodies TO off; +CREATE FUNCTION create_and_insert() RETURNS VOID LANGUAGE sql AS $$ + create table ddl_test (f1 int); + insert into ddl_test values (1.2); +$$; +SELECT create_and_insert(); + create_and_insert +------------------- + +(1 row) + +TABLE ddl_test; + f1 +---- + 1 +(1 row) + +CREATE FUNCTION alter_and_insert() RETURNS VOID LANGUAGE sql AS $$ + alter table ddl_test alter column f1 type numeric; + insert into ddl_test values (1.2); +$$; +SELECT alter_and_insert(); + alter_and_insert +------------------ + +(1 row) + +TABLE ddl_test; + f1 +----- + 1 + 1.2 +(2 rows) + +RESET check_function_bodies; -- Regression tests for bugs: -- Check that arguments that are R/W expanded datums aren't corrupted by -- multiple uses. This test knows that array_append() returns a R/W datum @@ -706,9 +757,23 @@ LINE 2: AS 'SELECT $2;'; CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL AS 'a', 'b'; ERROR: only one AS item needed for language "sql" +CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL + AS ''; +ERROR: return type mismatch in function declared to return integer +DETAIL: Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING. +CONTEXT: SQL function "test1" +-- make sure empty-body case is handled at execution time, too +SET check_function_bodies = off; +CREATE FUNCTION test1 (anyelement) RETURNS anyarray LANGUAGE SQL + AS ''; +SELECT test1(0); +ERROR: return type mismatch in function declared to return integer[] +DETAIL: Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING. +CONTEXT: SQL function "test1" during startup +RESET check_function_bodies; -- Cleanup DROP SCHEMA temp_func_test CASCADE; -NOTICE: drop cascades to 30 other objects +NOTICE: drop cascades to 35 other objects DETAIL: drop cascades to function functest_a_1(text,date) drop cascades to function functest_a_2(text[]) drop cascades to function functest_a_3() @@ -732,12 +797,17 @@ drop cascades to function functest_s_10(text,date) drop cascades to function functest_s_13() drop cascades to function functest_s_15(integer) drop cascades to function functest_b_2(bigint) +drop cascades to function functest_srf0() drop cascades to function functest_sri1() drop cascades to function voidtest1(integer) drop cascades to function voidtest2(integer,integer) drop cascades to function voidtest3(integer) drop cascades to function voidtest4(integer) drop cascades to function voidtest5(integer) +drop cascades to function create_and_insert() +drop cascades to table ddl_test +drop cascades to function alter_and_insert() drop cascades to function double_append(anyarray,anyelement) +drop cascades to function test1(anyelement) DROP USER regress_unpriv_user; RESET search_path; diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index cf6eac57349a0..9ade7b835e69f 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -1233,6 +1233,24 @@ SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA'; 14 (1 row) +-- OR-clauses shouldn't be transformed into SAOP because hash indexes don't +-- support SAOP scans. +SET enable_seqscan = off; +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 WHERE stringu1 = 'TVAAAA' OR stringu1 = 'TVAAAB'; + QUERY PLAN +------------------------------------------------------------------------------------ + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: ((stringu1 = 'TVAAAA'::name) OR (stringu1 = 'TVAAAB'::name)) + -> BitmapOr + -> Bitmap Index Scan on hash_tuplesort_idx + Index Cond: (stringu1 = 'TVAAAA'::name) + -> Bitmap Index Scan on hash_tuplesort_idx + Index Cond: (stringu1 = 'TVAAAB'::name) +(8 rows) + +RESET enable_seqscan; DROP INDEX hash_tuplesort_idx; RESET maintenance_work_mem; -- @@ -1619,7 +1637,9 @@ DROP TABLE syscol_table; -- Tests for IS NULL/IS NOT NULL with b-tree indexes -- CREATE TABLE onek_with_null AS SELECT unique1, unique2 FROM onek; -INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL); +INSERT INTO onek_with_null(unique1, unique2) +VALUES (NULL, -1), (NULL, 2_147_483_647), (NULL, NULL), + (100, NULL), (500, NULL); CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1); SET enable_seqscan = OFF; SET enable_indexscan = ON; @@ -1627,7 +1647,7 @@ SET enable_bitmapscan = ON; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; count ------- - 2 + 3 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; @@ -1639,13 +1659,13 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; count ------- - 1000 + 1002 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; count ------- - 1 + 2 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; @@ -1660,12 +1680,18 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; 0 (1 row) +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; + unique1 | unique2 +---------+--------- + 500 | +(1 row) + DROP INDEX onek_nulltest; CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc,unique1); SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; count ------- - 2 + 3 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; @@ -1677,13 +1703,13 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; count ------- - 1000 + 1002 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; count ------- - 1 + 2 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; @@ -1704,12 +1730,18 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IN (-1, 0, 1 (1 row) +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; + unique1 | unique2 +---------+--------- + 500 | +(1 row) + DROP INDEX onek_nulltest; CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc nulls last,unique1); SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; count ------- - 2 + 3 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; @@ -1721,13 +1753,13 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; count ------- - 1000 + 1002 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; count ------- - 1 + 2 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; @@ -1742,12 +1774,18 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; 0 (1 row) +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; + unique1 | unique2 +---------+--------- + 500 | +(1 row) + DROP INDEX onek_nulltest; CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 nulls first,unique1); SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; count ------- - 2 + 3 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; @@ -1759,13 +1797,13 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; count ------- - 1000 + 1002 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; count ------- - 1 + 2 (1 row) SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; @@ -1780,6 +1818,12 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; 0 (1 row) +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; + unique1 | unique2 +---------+--------- + 500 | +(1 row) + DROP INDEX onek_nulltest; -- Check initial-positioning logic too CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2); @@ -1811,20 +1855,24 @@ SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= 0 (2 rows) SELECT unique1, unique2 FROM onek_with_null - ORDER BY unique2 DESC LIMIT 2; - unique1 | unique2 ----------+--------- - | - 278 | 999 -(2 rows) + ORDER BY unique2 DESC LIMIT 5; + unique1 | unique2 +---------+------------ + 500 | + 100 | + | + | 2147483647 + 278 | 999 +(5 rows) SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 - ORDER BY unique2 DESC LIMIT 2; - unique1 | unique2 ----------+--------- - 278 | 999 - 0 | 998 -(2 rows) + ORDER BY unique2 DESC LIMIT 3; + unique1 | unique2 +---------+------------ + | 2147483647 + 278 | 999 + 0 | 998 +(3 rows) SELECT unique1, unique2 FROM onek_with_null WHERE unique2 < 999 ORDER BY unique2 DESC LIMIT 2; @@ -1843,19 +1891,122 @@ DROP TABLE onek_with_null; -- EXPLAIN (COSTS OFF) SELECT * FROM tenk1 - WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous = 0); + QUERY PLAN +-------------------------------------------------------------------------------- + Index Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand = 42) AND (tenthous = ANY ('{1,3,42,0}'::integer[]))) +(2 rows) + +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous = 0); + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- + 42 | 5530 | 0 | 2 | 2 | 2 | 42 | 42 | 42 | 42 | 42 | 84 | 85 | QBAAAA | SEIAAA | OOOOxx +(1 row) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = (SELECT 1 + 2) OR tenthous = 42); + QUERY PLAN +---------------------------------------------------------------------------------------- + Index Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand = 42) AND (tenthous = ANY (ARRAY[1, (InitPlan 1).col1, 42]))) + InitPlan 1 + -> Result +(4 rows) + +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = (SELECT 1 + 2) OR tenthous = 42); + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- + 42 | 5530 | 0 | 2 | 2 | 2 | 42 | 42 | 42 | 42 | 42 | 84 | 85 | QBAAAA | SEIAAA | OOOOxx +(1 row) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous IS NULL); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on tenk1 - Recheck Cond: (((thousand = 42) AND (tenthous = 1)) OR ((thousand = 42) AND (tenthous = 3)) OR ((thousand = 42) AND (tenthous = 42))) + Recheck Cond: (((thousand = 42) AND ((tenthous = 1) OR (tenthous = 3) OR (tenthous = 42))) OR ((thousand = 42) AND (tenthous IS NULL))) + Filter: ((tenthous = 1) OR (tenthous = 3) OR (tenthous = 42) OR (tenthous IS NULL)) -> BitmapOr -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: ((thousand = 42) AND (tenthous = 1)) + Index Cond: ((thousand = 42) AND (tenthous = ANY ('{1,3,42}'::integer[]))) -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: ((thousand = 42) AND (tenthous = 3)) + Index Cond: ((thousand = 42) AND (tenthous IS NULL)) +(8 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous::int2 = 3::int8 OR tenthous = 42::int8); + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: (thousand = 42) + Filter: ((tenthous = '1'::smallint) OR ((tenthous)::smallint = '3'::bigint) OR (tenthous = '42'::bigint)) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = 42) +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous::int2 = 3::int8 OR tenthous::int2 = 42::int8); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: (thousand = 42) + Filter: ((tenthous = '1'::smallint) OR ((tenthous)::smallint = '3'::bigint) OR ((tenthous)::smallint = '42'::bigint)) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = 42) +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous = 3::int8 OR tenthous = 42::int8); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: (((thousand = 42) AND (tenthous = '1'::smallint)) OR ((thousand = 42) AND ((tenthous = '3'::bigint) OR (tenthous = '42'::bigint)))) + Filter: ((tenthous = '1'::smallint) OR (tenthous = '3'::bigint) OR (tenthous = '42'::bigint)) + -> BitmapOr -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: ((thousand = 42) AND (tenthous = 42)) -(9 rows) + Index Cond: ((thousand = 42) AND (tenthous = '1'::smallint)) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: ((thousand = 42) AND (tenthous = ANY ('{3,42}'::bigint[]))) +(8 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + QUERY PLAN +--------------------------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: ((hundred = 42) AND ((thousand = 42) OR (thousand = 99))) + -> BitmapAnd + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 42) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = ANY ('{42,99}'::integer[])) +(8 rows) + +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); + QUERY PLAN +------------------------------------------------------------------------------ + Index Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand = 42) AND (tenthous = ANY ('{1,3,42}'::integer[]))) +(2 rows) SELECT * FROM tenk1 WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); @@ -1864,6 +2015,48 @@ SELECT * FROM tenk1 42 | 5530 | 0 | 2 | 2 | 2 | 42 | 42 | 42 | 42 | 42 | 84 | 85 | QBAAAA | SEIAAA | OOOOxx (1 row) +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::numeric OR tenthous = 3::int4 OR tenthous = 42::numeric); + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: (thousand = 42) + Filter: (((tenthous)::numeric = '1'::numeric) OR (tenthous = 3) OR ((tenthous)::numeric = '42'::numeric)) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = 42) +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE tenthous = 1::numeric OR tenthous = 3::int4 OR tenthous = 42::numeric; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Seq Scan on tenk1 + Filter: (((tenthous)::numeric = '1'::numeric) OR (tenthous = 3) OR ((tenthous)::numeric = '42'::numeric)) +(2 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + QUERY PLAN +---------------------------------------------------------------------------- + Aggregate + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t1 + Filter: ((thousand = 42) OR (thousand = (SubPlan 1))) + SubPlan 1 + -> Limit + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = (t1.tenthous + 1)) +(7 rows) + +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + count +------- + 10 +(1 row) + EXPLAIN (COSTS OFF) SELECT count(*) FROM tenk1 WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); @@ -1872,23 +2065,191 @@ SELECT count(*) FROM tenk1 Aggregate -> Bitmap Heap Scan on tenk1 Recheck Cond: ((hundred = 42) AND ((thousand = 42) OR (thousand = 99))) + -> BitmapAnd + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 42) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = ANY ('{42,99}'::integer[])) +(8 rows) + +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand < 42 OR thousand < 99 OR 43 > thousand OR 42 > thousand); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: ((hundred = 42) AND ((thousand < 42) OR (thousand < 99) OR (43 > thousand) OR (42 > thousand))) + -> BitmapAnd + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 42) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand < ANY ('{42,99,43,42}'::integer[])) +(8 rows) + +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand < 42 OR thousand < 99 OR 43 > thousand OR 42 > thousand); + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3) OR thousand = 41; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: (((thousand = 42) AND ((tenthous = 1) OR (tenthous = 3))) OR (thousand = 41)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: ((thousand = 42) AND (tenthous = ANY ('{1,3}'::integer[]))) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = 41) +(8 rows) + +SELECT count(*) FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3) OR thousand = 41; + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99 OR tenthous < 2) OR thousand = 41; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: (((hundred = 42) AND (((thousand = 42) OR (thousand = 99)) OR (tenthous < 2))) OR (thousand = 41)) + Filter: (((hundred = 42) AND ((thousand = 42) OR (thousand = 99) OR (tenthous < 2))) OR (thousand = 41)) + -> BitmapOr + -> BitmapAnd + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 42) + -> BitmapOr + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = ANY ('{42,99}'::integer[])) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (tenthous < 2) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = 41) +(15 rows) + +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99 OR tenthous < 2) OR thousand = 41; + count +------- + 20 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 41 OR thousand = 99 AND tenthous = 2); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tenk1 + Recheck Cond: ((hundred = 42) AND (((thousand = 42) OR (thousand = 41)) OR ((thousand = 99) AND (tenthous = 2)))) + Filter: ((thousand = 42) OR (thousand = 41) OR ((thousand = 99) AND (tenthous = 2))) -> BitmapAnd -> Bitmap Index Scan on tenk1_hundred Index Cond: (hundred = 42) -> BitmapOr -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = 42) + Index Cond: (thousand = ANY ('{42,41}'::integer[])) -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = 99) -(11 rows) + Index Cond: ((thousand = 99) AND (tenthous = 2)) +(12 rows) SELECT count(*) FROM tenk1 - WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + WHERE hundred = 42 AND (thousand = 42 OR thousand = 41 OR thousand = 99 AND tenthous = 2); count ------- 10 (1 row) +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1, tenk2 + WHERE tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk1.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Aggregate + -> Nested Loop + Join Filter: ((tenk2.thousand = 42) OR (tenk1.thousand = 41) OR (tenk2.tenthous = 2)) + -> Bitmap Heap Scan on tenk1 + Recheck Cond: (hundred = 42) + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 42) + -> Materialize + -> Bitmap Heap Scan on tenk2 + Recheck Cond: (hundred = 42) + -> Bitmap Index Scan on tenk2_hundred + Index Cond: (hundred = 42) +(12 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1, tenk2 + WHERE tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + QUERY PLAN +------------------------------------------------------------------------------ + Aggregate + -> Nested Loop + -> Bitmap Heap Scan on tenk2 + Recheck Cond: (hundred = 42) + Filter: ((thousand = 42) OR (thousand = 41) OR (tenthous = 2)) + -> Bitmap Index Scan on tenk2_hundred + Index Cond: (hundred = 42) + -> Index Only Scan using tenk1_hundred on tenk1 + Index Cond: (hundred = 42) +(9 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 JOIN tenk2 ON + tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + QUERY PLAN +------------------------------------------------------------------------------ + Aggregate + -> Nested Loop + -> Bitmap Heap Scan on tenk2 + Recheck Cond: (hundred = 42) + Filter: ((thousand = 42) OR (thousand = 41) OR (tenthous = 2)) + -> Bitmap Index Scan on tenk2_hundred + Index Cond: (hundred = 42) + -> Index Only Scan using tenk1_hundred on tenk1 + Index Cond: (hundred = 42) +(9 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 LEFT JOIN tenk2 ON + tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + QUERY PLAN +------------------------------------------------------------------------------------ + Aggregate + -> Nested Loop Left Join + Join Filter: (tenk1.hundred = 42) + -> Index Only Scan using tenk1_hundred on tenk1 + -> Memoize + Cache Key: tenk1.hundred + Cache Mode: logical + -> Index Scan using tenk2_hundred on tenk2 + Index Cond: (hundred = tenk1.hundred) + Filter: ((thousand = 42) OR (thousand = 41) OR (tenthous = 2)) +(10 rows) + -- -- Check behavior with duplicate index column contents -- @@ -1916,7 +2277,8 @@ SELECT count(*) FROM dupindexcols (1 row) -- --- Check that index scans with =ANY indexquals return rows in index order +-- Check that index scans with SAOP array and/or skip array indexquals +-- return rows in index order -- explain (costs off) SELECT unique1 FROM tenk1 @@ -1938,7 +2300,7 @@ ORDER BY unique1; 42 (3 rows) --- Non-required array scan key on "tenthous": +-- Skip array on "thousand", SAOP array on "tenthous": explain (costs off) SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) @@ -1958,7 +2320,7 @@ ORDER BY thousand; 1 | 1001 (2 rows) --- Non-required array scan key on "tenthous", backward scan: +-- Skip array on "thousand", SAOP array on "tenthous", backward scan: explain (costs off) SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) @@ -1978,6 +2340,25 @@ ORDER BY thousand DESC, tenthous DESC; 0 | 3000 (2 rows) +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > 995 and tenthous in (998, 999) +ORDER BY thousand desc; + QUERY PLAN +-------------------------------------------------------------------------------- + Index Only Scan Backward using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand > 995) AND (tenthous = ANY ('{998,999}'::integer[]))) +(2 rows) + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > 995 and tenthous in (998, 999) +ORDER BY thousand desc; + thousand | tenthous +----------+---------- + 999 | 999 + 998 | 998 +(2 rows) + -- -- Check elimination of redundant and contradictory index quals -- @@ -2008,6 +2389,45 @@ SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY(' --------- (0 rows) +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 = ANY(NULL); + QUERY PLAN +------------------------------------------------- + Index Only Scan using tenk1_unique1 on tenk1 + Index Cond: (unique1 = ANY (NULL::integer[])) +(2 rows) + +SELECT unique1 FROM tenk1 WHERE unique1 = ANY(NULL); + unique1 +--------- +(0 rows) + +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{NULL,NULL,NULL}'); + QUERY PLAN +--------------------------------------------------------------- + Index Only Scan using tenk1_unique1 on tenk1 + Index Cond: (unique1 = ANY ('{NULL,NULL,NULL}'::integer[])) +(2 rows) + +SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{NULL,NULL,NULL}'); + unique1 +--------- +(0 rows) + +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 IS NULL AND unique1 IS NULL; + QUERY PLAN +--------------------------------------------------------- + Index Only Scan using tenk1_unique1 on tenk1 + Index Cond: ((unique1 IS NULL) AND (unique1 IS NULL)) +(2 rows) + +SELECT unique1 FROM tenk1 WHERE unique1 IS NULL AND unique1 IS NULL; + unique1 +--------- +(0 rows) + explain (costs off) SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 1; QUERY PLAN @@ -2118,6 +2538,78 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint --------- (0 rows) +explain (costs off) +SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5); + QUERY PLAN +----------------------------------------------------------------- + Index Scan using tenk1_thous_tenthous on tenk1 + Index Cond: (ROW(thousand, tenthous) > ROW(NULL::integer, 5)) +(2 rows) + +SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5); + unique1 +--------- +(0 rows) + +-- Skip array redundancy (pair of redundant low_compare inequalities) +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 and thousand >= 0 AND tenthous = 3000 +ORDER BY thousand; + QUERY PLAN +-------------------------------------------------------------------------------------- + Index Only Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand > '-1'::integer) AND (thousand >= 0) AND (tenthous = 3000)) +(2 rows) + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 and thousand >= 0 AND tenthous = 3000 +ORDER BY thousand; + thousand | tenthous +----------+---------- + 0 | 3000 +(1 row) + +-- Skip array redundancy (pair of redundant high_compare inequalities) +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand < 3 and thousand <= 2 AND tenthous = 1001 +ORDER BY thousand; + QUERY PLAN +-------------------------------------------------------------------------- + Index Only Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand < 3) AND (thousand <= 2) AND (tenthous = 1001)) +(2 rows) + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand < 3 and thousand <= 2 AND tenthous = 1001 +ORDER BY thousand; + thousand | tenthous +----------+---------- + 1 | 1001 +(1 row) + +-- Skip array preprocessing increments "thousand > -1" to "thousand >= 0" +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 AND tenthous IN (1001,3000) +ORDER BY thousand limit 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------- + Limit + -> Index Only Scan using tenk1_thous_tenthous on tenk1 + Index Cond: ((thousand > '-1'::integer) AND (tenthous = ANY ('{1001,3000}'::integer[]))) +(3 rows) + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 AND tenthous IN (1001,3000) +ORDER BY thousand limit 2; + thousand | tenthous +----------+---------- + 0 | 3000 + 1 | 1001 +(2 rows) + -- -- Check elimination of constant-NULL subexpressions -- @@ -2664,10 +3156,10 @@ REINDEX TABLE CONCURRENTLY pg_class; -- no catalog relation ERROR: cannot reindex system catalogs concurrently REINDEX INDEX CONCURRENTLY pg_class_oid_index; -- no catalog index ERROR: cannot reindex system catalogs concurrently --- These are the toast table and index of pg_authid. -REINDEX TABLE CONCURRENTLY pg_toast.pg_toast_1260; -- no catalog toast table +-- These are the toast table and index of pg_database. +REINDEX TABLE CONCURRENTLY pg_toast.pg_toast_1262; -- no catalog toast table ERROR: cannot reindex system catalogs concurrently -REINDEX INDEX CONCURRENTLY pg_toast.pg_toast_1260_index; -- no catalog toast index +REINDEX INDEX CONCURRENTLY pg_toast.pg_toast_1262_index; -- no catalog toast index ERROR: cannot reindex system catalogs concurrently REINDEX SYSTEM CONCURRENTLY postgres; -- not allowed for SYSTEM ERROR: cannot reindex system catalogs concurrently @@ -2904,6 +3396,91 @@ SELECT b.relname, (2 rows) DROP TABLE concur_temp_tab_1, concur_temp_tab_2, reindex_temp_before; +-- No OR-clause groupings should happen, and there should be no clause +-- permutations in the filtering conditions we could see in the EXPLAIN. +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 WHERE unique1 < 1 OR hundred < 2; + QUERY PLAN +-------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: ((unique1 < 1) OR (hundred < 2)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 < 1) + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred < 2) +(7 rows) + +-- OR clauses in the 'unique1' column are grouped, so clause permutation +-- occurs. W e can see it in the 'Recheck Cond': the second clause involving +-- the 'unique1' column goes just after the first one. +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 WHERE unique1 < 1 OR unique1 < 3 OR hundred < 2; + QUERY PLAN +--------------------------------------------------------------------- + Bitmap Heap Scan on tenk1 + Recheck Cond: (((unique1 < 1) OR (unique1 < 3)) OR (hundred < 2)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 < ANY ('{1,3}'::integer[])) + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred < 2) +(7 rows) + +-- Check bitmap scan can consider similar OR arguments separately without +-- grouping them into SAOP. +CREATE TABLE bitmap_split_or (a int NOT NULL, b int NOT NULL, c int NOT NULL); +INSERT INTO bitmap_split_or (SELECT 1, 1, i FROM generate_series(1, 1000) i); +INSERT INTO bitmap_split_or (select i, 2, 2 FROM generate_series(1, 1000) i); +VACUUM ANALYZE bitmap_split_or; +CREATE INDEX t_b_partial_1_idx ON bitmap_split_or (b) WHERE a = 1; +CREATE INDEX t_b_partial_2_idx ON bitmap_split_or (b) WHERE a = 2; +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or WHERE (a = 1 OR a = 2) AND b = 2; + QUERY PLAN +------------------------------------------------------------------ + Bitmap Heap Scan on bitmap_split_or + Recheck Cond: (((b = 2) AND (a = 1)) OR ((b = 2) AND (a = 2))) + -> BitmapOr + -> Bitmap Index Scan on t_b_partial_1_idx + Index Cond: (b = 2) + -> Bitmap Index Scan on t_b_partial_2_idx + Index Cond: (b = 2) +(7 rows) + +DROP INDEX t_b_partial_1_idx; +DROP INDEX t_b_partial_2_idx; +CREATE INDEX t_a_b_idx ON bitmap_split_or (a, b); +CREATE INDEX t_b_c_idx ON bitmap_split_or (b, c); +CREATE STATISTICS t_a_b_stat (mcv) ON a, b FROM bitmap_split_or; +CREATE STATISTICS t_b_c_stat (mcv) ON b, c FROM bitmap_split_or; +ANALYZE bitmap_split_or; +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or t1, bitmap_split_or t2 +WHERE t1.a = t2.b OR t1.a = 2; + QUERY PLAN +-------------------------------------------------------- + Nested Loop + -> Seq Scan on bitmap_split_or t2 + -> Index Scan using t_a_b_idx on bitmap_split_or t1 + Index Cond: (a = ANY (ARRAY[t2.b, 2])) +(4 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or WHERE a = 1 AND (b = 1 OR b = 2) AND c = 2; + QUERY PLAN +------------------------------------------------------------------ + Bitmap Heap Scan on bitmap_split_or + Recheck Cond: (((b = 1) AND (c = 2)) OR ((a = 1) AND (b = 2))) + Filter: ((a = 1) AND (c = 2)) + -> BitmapOr + -> Bitmap Index Scan on t_b_c_idx + Index Cond: ((b = 1) AND (c = 2)) + -> Bitmap Index Scan on t_a_b_idx + Index Cond: ((a = 1) AND (b = 2)) +(8 rows) + +DROP TABLE bitmap_split_or; -- -- REINDEX SCHEMA -- @@ -2974,10 +3551,10 @@ ERROR: must be owner of schema schema_to_reindex RESET ROLE; GRANT USAGE ON SCHEMA pg_toast TO regress_reindexuser; SET SESSION ROLE regress_reindexuser; -REINDEX TABLE pg_toast.pg_toast_1260; -ERROR: permission denied for table pg_toast_1260 -REINDEX INDEX pg_toast.pg_toast_1260_index; -ERROR: permission denied for index pg_toast_1260_index +REINDEX TABLE pg_toast.pg_toast_1262; +ERROR: permission denied for table pg_toast_1262 +REINDEX INDEX pg_toast.pg_toast_1262_index; +ERROR: permission denied for index pg_toast_1262_index -- Clean up RESET ROLE; REVOKE USAGE ON SCHEMA pg_toast FROM regress_reindexuser; diff --git a/src/test/regress/expected/create_index_spgist.out b/src/test/regress/expected/create_index_spgist.out index 5c04df9c01b14..c6beb0efaffa2 100644 --- a/src/test/regress/expected/create_index_spgist.out +++ b/src/test/regress/expected/create_index_spgist.out @@ -329,12 +329,13 @@ SELECT count(*) FROM quad_point_tbl WHERE p ~= '(4585, 365)'; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM quad_point_tbl; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(0,0)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_quad_ind on quad_point_tbl Order By: (p <-> '(0,0)'::point) -(3 rows) +(4 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx1 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -349,13 +350,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(0,0)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) Order By: (p <-> '(0,0)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx2 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -370,13 +372,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p FROM quad_point_tbl WHERE p IS NOT NULL; - QUERY PLAN ------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(333,400)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_quad_ind on quad_point_tbl Index Cond: (p IS NOT NULL) Order By: (p <-> '(333,400)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE quad_point_tbl_ord_idx3 AS SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p @@ -496,12 +499,13 @@ SELECT count(*) FROM kd_point_tbl WHERE p ~= '(4585, 365)'; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM kd_point_tbl; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(0,0)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_kd_ind on kd_point_tbl Order By: (p <-> '(0,0)'::point) -(3 rows) +(4 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx1 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -516,13 +520,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p FROM kd_point_tbl WHERE p <@ box '(200,200,1000,1000)'; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(0,0)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p <@ '(1000,1000),(200,200)'::box) Order By: (p <-> '(0,0)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx2 AS SELECT row_number() OVER (ORDER BY p <-> '0,0') n, p <-> '0,0' dist, p @@ -537,13 +542,14 @@ WHERE seq.dist IS DISTINCT FROM idx.dist; EXPLAIN (COSTS OFF) SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p FROM kd_point_tbl WHERE p IS NOT NULL; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(333,400)'::point) ROWS UNBOUNDED PRECEDING) -> Index Only Scan using sp_kd_ind on kd_point_tbl Index Cond: (p IS NOT NULL) Order By: (p <-> '(333,400)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE kd_point_tbl_ord_idx3 AS SELECT row_number() OVER (ORDER BY p <-> '333,400') n, p <-> '333,400' dist, p diff --git a/src/test/regress/expected/create_procedure.out b/src/test/regress/expected/create_procedure.out index 2177ba3509007..45b402e25e79c 100644 --- a/src/test/regress/expected/create_procedure.out +++ b/src/test/regress/expected/create_procedure.out @@ -401,9 +401,13 @@ LINE 1: CREATE PROCEDURE ptestx() LANGUAGE SQL STRICT AS $$ INSERT I... CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL AS $$ SELECT a[1] $$; ERROR: VARIADIC parameter must be the last parameter +LINE 1: CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAG... + ^ CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAGE SQL AS $$ SELECT a $$; ERROR: procedure OUT parameters cannot appear after one with a default value +LINE 1: CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAG... + ^ ALTER PROCEDURE ptest1(text) STRICT; ERROR: invalid attribute in procedure definition LINE 1: ALTER PROCEDURE ptest1(text) STRICT; diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 284a7fb85c8f9..76604705a93cc 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -50,6 +50,16 @@ ERROR: cannot create temporary relation in non-temporary schema LINE 1: CREATE TEMP TABLE public.temp_to_perm (a int primary key); ^ DROP TABLE unlogged1, public.unlogged2; +CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail +ERROR: partitioned tables cannot be unlogged +CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok +ALTER TABLE unlogged1 SET LOGGED; -- fails +ERROR: ALTER action SET LOGGED cannot be performed on relation "unlogged1" +DETAIL: This operation is not supported for partitioned tables. +ALTER TABLE unlogged1 SET UNLOGGED; -- fails +ERROR: ALTER action SET UNLOGGED cannot be performed on relation "unlogged1" +DETAIL: This operation is not supported for partitioned tables. +DROP TABLE unlogged1; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; ERROR: relation "as_select1" already exists @@ -188,6 +198,8 @@ CREATE TABLE partitioned ( a int ) PARTITION BY MAGIC (a); ERROR: unrecognized partitioning strategy "magic" +LINE 3: ) PARTITION BY MAGIC (a); + ^ -- specified column must be present in the table CREATE TABLE partitioned ( a int @@ -759,21 +771,23 @@ CREATE TABLE part_b PARTITION OF parted ( NOTICE: merging constraint "check_a" with inherited definition -- conislocal should be false for any merged constraints, true otherwise SELECT conname, conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::regclass ORDER BY coninhcount DESC, conname; - conname | conislocal | coninhcount ----------+------------+------------- - check_a | f | 1 - check_b | t | 0 -(2 rows) + conname | conislocal | coninhcount +-------------------+------------+------------- + check_a | f | 1 + part_b_b_not_null | t | 1 + check_b | t | 0 +(3 rows) -- Once check_b is added to the parent, it should be made non-local for part_b ALTER TABLE parted ADD CONSTRAINT check_b CHECK (b >= 0); NOTICE: merging constraint "check_b" with inherited definition SELECT conname, conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::regclass ORDER BY coninhcount DESC, conname; - conname | conislocal | coninhcount ----------+------------+------------- - check_a | f | 1 - check_b | f | 1 -(2 rows) + conname | conislocal | coninhcount +-------------------+------------+------------- + check_a | f | 1 + check_b | f | 1 + part_b_b_not_null | t | 1 +(3 rows) -- Neither check_a nor check_b are droppable from part_b ALTER TABLE part_b DROP CONSTRAINT check_a; @@ -785,9 +799,10 @@ ERROR: cannot drop inherited constraint "check_b" of relation "part_b" -- be local constraints. ALTER TABLE parted DROP CONSTRAINT check_a, DROP CONSTRAINT check_b; SELECT conname, conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_b'::regclass ORDER BY coninhcount DESC, conname; - conname | conislocal | coninhcount ----------+------------+------------- -(0 rows) + conname | conislocal | coninhcount +-------------------+------------+------------- + part_b_b_not_null | t | 1 +(1 row) -- specify PARTITION BY for a partition CREATE TABLE fail_part_col_not_found PARTITION OF parted FOR VALUES IN ('c') PARTITION BY RANGE (c); @@ -851,6 +866,8 @@ drop table test_part_coll_posix; b | integer | | not null | 1 | plain | | Partition of: parted FOR VALUES IN ('b') Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text)) +Not-null constraints: + "part_b_b_not_null" NOT NULL "b" (local, inherited) -- Both partition bound and partition key in describe output \d+ part_c @@ -862,6 +879,8 @@ Partition constraint: ((a IS NOT NULL) AND (a = 'b'::text)) Partition of: parted FOR VALUES IN ('c') Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text)) Partition key: RANGE (b) +Not-null constraints: + "part_c_b_not_null" NOT NULL "b" (local, inherited) Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10) -- a level-2 partition's constraint will include the parent's expressions @@ -873,6 +892,8 @@ Partitions: part_c_1_10 FOR VALUES FROM (1) TO (10) b | integer | | not null | 0 | plain | | Partition of: part_c FOR VALUES FROM (1) TO (10) Partition constraint: ((a IS NOT NULL) AND (a = 'c'::text) AND (b IS NOT NULL) AND (b >= 1) AND (b < 10)) +Not-null constraints: + "part_c_b_not_null" NOT NULL "b" (inherited) -- Show partition count in the parent's describe output -- Tempted to include \d+ output listing partitions with bound info but diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index 6bfc6d040ff8e..bf34289e9842b 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -113,19 +113,20 @@ SELECT * FROM test_like_id_3; -- identity was copied and applied (1 row) DROP TABLE test_like_id_1, test_like_id_2, test_like_id_3; -CREATE TABLE test_like_gen_1 (a int, b int GENERATED ALWAYS AS (a * 2) STORED); +CREATE TABLE test_like_gen_1 (a int, b int GENERATED ALWAYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (a * 3) VIRTUAL); \d test_like_gen_1 Table "public.test_like_gen_1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | b | integer | | | generated always as (a * 2) stored + c | integer | | | generated always as (a * 3) INSERT INTO test_like_gen_1 (a) VALUES (1); SELECT * FROM test_like_gen_1; - a | b ----+--- - 1 | 2 + a | b | c +---+---+--- + 1 | 2 | 3 (1 row) CREATE TABLE test_like_gen_2 (LIKE test_like_gen_1); @@ -135,12 +136,13 @@ CREATE TABLE test_like_gen_2 (LIKE test_like_gen_1); --------+---------+-----------+----------+--------- a | integer | | | b | integer | | | + c | integer | | | INSERT INTO test_like_gen_2 (a) VALUES (1); SELECT * FROM test_like_gen_2; - a | b ----+--- - 1 | + a | b | c +---+---+--- + 1 | | (1 row) CREATE TABLE test_like_gen_3 (LIKE test_like_gen_1 INCLUDING GENERATED); @@ -150,12 +152,13 @@ CREATE TABLE test_like_gen_3 (LIKE test_like_gen_1 INCLUDING GENERATED); --------+---------+-----------+----------+------------------------------------ a | integer | | | b | integer | | | generated always as (a * 2) stored + c | integer | | | generated always as (a * 3) INSERT INTO test_like_gen_3 (a) VALUES (1); SELECT * FROM test_like_gen_3; - a | b ----+--- - 1 | 2 + a | b | c +---+---+--- + 1 | 2 | 3 (1 row) DROP TABLE test_like_gen_1, test_like_gen_2, test_like_gen_3; @@ -315,7 +318,8 @@ Referenced by: DROP TABLE inhz; -- including storage and comments -CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text); +CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) ENFORCED PRIMARY KEY, + b text CHECK (length(b) > 100) NOT ENFORCED); CREATE INDEX ctlt1_b_key ON ctlt1 (b); CREATE INDEX ctlt1_fnidx ON ctlt1 ((a || b)); CREATE STATISTICS ctlt1_a_b_stat ON a,b FROM ctlt1; @@ -348,6 +352,8 @@ CREATE TABLE ctlt12_storage (LIKE ctlt1 INCLUDING STORAGE, LIKE ctlt2 INCLUDING a | text | | not null | | main | | b | text | | | | extended | | c | text | | | | external | | +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" CREATE TABLE ctlt12_comments (LIKE ctlt1 INCLUDING COMMENTS, LIKE ctlt2 INCLUDING COMMENTS); \d+ ctlt12_comments @@ -357,11 +363,14 @@ CREATE TABLE ctlt12_comments (LIKE ctlt1 INCLUDING COMMENTS, LIKE ctlt2 INCLUDIN a | text | | not null | | extended | | A b | text | | | | extended | | B c | text | | | | extended | | C +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" CREATE TABLE ctlt1_inh (LIKE ctlt1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) INHERITS (ctlt1); NOTICE: merging column "a" with inherited definition NOTICE: merging column "b" with inherited definition NOTICE: merging constraint "ctlt1_a_check" with inherited definition +NOTICE: merging constraint "ctlt1_b_check" with inherited definition \d+ ctlt1_inh Table "public.ctlt1_inh" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description @@ -370,6 +379,9 @@ NOTICE: merging constraint "ctlt1_a_check" with inherited definition b | text | | | | extended | | B Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" (local, inherited) Inherits: ctlt1 SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt1_inh'::regclass; @@ -389,8 +401,11 @@ NOTICE: merging multiple inherited definitions of column "a" c | text | | | | external | | Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED "ctlt3_a_check" CHECK (length(a) < 5) "ctlt3_c_check" CHECK (length(c) < 7) +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" (inherited) Inherits: ctlt1, ctlt3 @@ -407,8 +422,11 @@ Indexes: "ctlt13_like_expr_idx" btree ((a || c)) Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED "ctlt3_a_check" CHECK (length(a) < 5) "ctlt3_c_check" CHECK (length(c) < 7) +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" (inherited) Inherits: ctlt1 SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_like'::regclass; @@ -430,9 +448,12 @@ Indexes: "ctlt_all_expr_idx" btree ((a || b)) Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED Statistics objects: "public.ctlt_all_a_b_stat" ON a, b FROM ctlt_all "public.ctlt_all_expr_stat" ON (a || b) FROM ctlt_all +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 'ctlt_all'::regclass ORDER BY c.relname, objsubid; relname | objsubid | description @@ -470,9 +491,12 @@ Indexes: "pg_attrdef_expr_idx" btree ((a || b)) Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED Statistics objects: "public.pg_attrdef_a_b_stat" ON a, b FROM public.pg_attrdef "public.pg_attrdef_expr_stat" ON (a || b) FROM public.pg_attrdef +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" DROP TABLE public.pg_attrdef; -- Check that LIKE isn't confused when new table masks the old, either @@ -492,23 +516,32 @@ Indexes: "ctlt1_expr_idx" btree ((a || b)) Check constraints: "ctlt1_a_check" CHECK (length(a) > 2) + "ctlt1_b_check" CHECK (length(b) > 100) NOT ENFORCED Statistics objects: "ctl_schema.ctlt1_a_b_stat" ON a, b FROM ctlt1 "ctl_schema.ctlt1_expr_stat" ON (a || b) FROM ctlt1 +Not-null constraints: + "ctlt1_a_not_null" NOT NULL "a" ROLLBACK; DROP TABLE ctlt1, ctlt2, ctlt3, ctlt4, ctlt12_storage, ctlt12_comments, ctlt1_inh, ctlt13_inh, ctlt13_like, ctlt_all, ctla, ctlb CASCADE; NOTICE: drop cascades to table inhe -- LIKE must respect NO INHERIT property of constraints -CREATE TABLE noinh_con_copy (a int CHECK (a > 0) NO INHERIT); +CREATE TABLE noinh_con_copy (a int CHECK (a > 0) NO INHERIT, b int not null, + c int not null no inherit); CREATE TABLE noinh_con_copy1 (LIKE noinh_con_copy INCLUDING CONSTRAINTS); -\d noinh_con_copy1 - Table "public.noinh_con_copy1" - Column | Type | Collation | Nullable | Default ---------+---------+-----------+----------+--------- - a | integer | | | +\d+ noinh_con_copy1 + Table "public.noinh_con_copy1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | + b | integer | | not null | | plain | | + c | integer | | not null | | plain | | Check constraints: "noinh_con_copy_a_check" CHECK (a > 0) NO INHERIT +Not-null constraints: + "noinh_con_copy_b_not_null" NOT NULL "b" + "noinh_con_copy_c_not_null" NOT NULL "c" NO INHERIT -- fail, as partitioned tables don't allow NO INHERIT constraints CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL) @@ -533,3 +566,106 @@ DROP TYPE ctlty1; DROP VIEW ctlv1; DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12; NOTICE: table "ctlt10" does not exist, skipping +-- +-- CREATE FOREIGN TABLE LIKE +-- +CREATE FOREIGN DATA WRAPPER ctl_dummy; +CREATE SERVER ctl_s0 FOREIGN DATA WRAPPER ctl_dummy; +CREATE TABLE ctl_table(a int PRIMARY KEY, + b varchar COMPRESSION pglz, + c int GENERATED ALWAYS AS (a * 2) STORED, + d bigint GENERATED ALWAYS AS IDENTITY, + e int DEFAULT 1); +CREATE INDEX ctl_table_a_key ON ctl_table(a); +COMMENT ON COLUMN ctl_table.b IS 'Column b'; +CREATE STATISTICS ctl_table_stat ON a,b FROM ctl_table; +ALTER TABLE ctl_table ADD CONSTRAINT foo CHECK (b = 'text'); +ALTER TABLE ctl_table ALTER COLUMN b SET STORAGE MAIN; +\d+ ctl_table + Table "public.ctl_table" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+-------------------+-----------+----------+------------------------------------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | character varying | | | | main | | Column b + c | integer | | | generated always as (a * 2) stored | plain | | + d | bigint | | not null | generated always as identity | plain | | + e | integer | | | 1 | plain | | +Indexes: + "ctl_table_pkey" PRIMARY KEY, btree (a) + "ctl_table_a_key" btree (a) +Check constraints: + "foo" CHECK (b::text = 'text'::text) +Statistics objects: + "public.ctl_table_stat" ON a, b FROM ctl_table +Not-null constraints: + "ctl_table_a_not_null" NOT NULL "a" + "ctl_table_d_not_null" NOT NULL "d" + +-- Test EXCLUDING ALL +CREATE FOREIGN TABLE ctl_foreign_table1(LIKE ctl_table EXCLUDING ALL) SERVER ctl_s0; +\d+ ctl_foreign_table1 + Foreign table "public.ctl_foreign_table1" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+-------------------+-----------+----------+---------+-------------+----------+--------------+------------- + a | integer | | not null | | | plain | | + b | character varying | | | | | extended | | + c | integer | | | | | plain | | + d | bigint | | not null | | | plain | | + e | integer | | | | | plain | | +Not-null constraints: + "ctl_table_a_not_null" NOT NULL "a" + "ctl_table_d_not_null" NOT NULL "d" +Server: ctl_s0 + +-- \d+ does not report the value of attcompression for a foreign table, so +-- check separately. +SELECT attname, attcompression FROM pg_attribute + WHERE attrelid = 'ctl_foreign_table1'::regclass and attnum > 0 ORDER BY attnum; + attname | attcompression +---------+---------------- + a | + b | + c | + d | + e | +(5 rows) + +-- Test INCLUDING ALL +-- INDEXES, IDENTITY, COMPRESSION, STORAGE are not copied. +CREATE FOREIGN TABLE ctl_foreign_table2(LIKE ctl_table INCLUDING ALL) SERVER ctl_s0; +\d+ ctl_foreign_table2 + Foreign table "public.ctl_foreign_table2" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+-------------------+-----------+----------+------------------------------------+-------------+----------+--------------+------------- + a | integer | | not null | | | plain | | + b | character varying | | | | | extended | | Column b + c | integer | | | generated always as (a * 2) stored | | plain | | + d | bigint | | not null | | | plain | | + e | integer | | | 1 | | plain | | +Check constraints: + "foo" CHECK (b::text = 'text'::text) +Statistics objects: + "public.ctl_foreign_table2_a_b_stat" ON a, b FROM ctl_foreign_table2 +Not-null constraints: + "ctl_table_a_not_null" NOT NULL "a" + "ctl_table_d_not_null" NOT NULL "d" +Server: ctl_s0 + +-- \d+ does not report the value of attcompression for a foreign table, so +-- check separately. +SELECT attname, attcompression FROM pg_attribute + WHERE attrelid = 'ctl_foreign_table2'::regclass and attnum > 0 ORDER BY attnum; + attname | attcompression +---------+---------------- + a | + b | + c | + d | + e | +(5 rows) + +DROP TABLE ctl_table; +DROP FOREIGN TABLE ctl_foreign_table1; +DROP FOREIGN TABLE ctl_foreign_table2; +DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE; +NOTICE: drop cascades to server ctl_s0 diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out index 7383fcdbb1294..5181c4290b4cd 100644 --- a/src/test/regress/expected/create_type.out +++ b/src/test/regress/expected/create_type.out @@ -20,6 +20,8 @@ CREATE FUNCTION widget_out(widget) AS :'regresslib' LANGUAGE C STRICT IMMUTABLE; NOTICE: argument type widget is only a shell +LINE 1: CREATE FUNCTION widget_out(widget) + ^ CREATE FUNCTION int44in(cstring) RETURNS city_budget AS :'regresslib' @@ -31,6 +33,8 @@ CREATE FUNCTION int44out(city_budget) AS :'regresslib' LANGUAGE C STRICT IMMUTABLE; NOTICE: argument type city_budget is only a shell +LINE 1: CREATE FUNCTION int44out(city_budget) + ^ CREATE TYPE widget ( internallength = 24, input = widget_in, @@ -75,6 +79,8 @@ CREATE FUNCTION int42_out(int42) AS 'int4out' LANGUAGE internal STRICT IMMUTABLE; NOTICE: argument type int42 is only a shell +LINE 1: CREATE FUNCTION int42_out(int42) + ^ CREATE FUNCTION text_w_default_in(cstring) RETURNS text_w_default AS 'textin' @@ -85,6 +91,8 @@ CREATE FUNCTION text_w_default_out(text_w_default) AS 'textout' LANGUAGE internal STRICT IMMUTABLE; NOTICE: argument type text_w_default is only a shell +LINE 1: CREATE FUNCTION text_w_default_out(text_w_default) + ^ CREATE TYPE int42 ( internallength = 4, input = int42_in, @@ -186,6 +194,8 @@ NOTICE: return type base_type is only a shell CREATE FUNCTION base_fn_out(base_type) RETURNS cstring AS 'boolout' LANGUAGE internal IMMUTABLE STRICT; NOTICE: argument type base_type is only a shell +LINE 1: CREATE FUNCTION base_fn_out(base_type) RETURNS cstring AS 'b... + ^ CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out); DROP FUNCTION base_fn_in(cstring); -- error ERROR: cannot drop function base_fn_in(cstring) because other objects depend on it @@ -320,9 +330,13 @@ NOTICE: return type myvarchar is only a shell CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharout'; NOTICE: argument type myvarchar is only a shell +LINE 1: CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring + ^ CREATE FUNCTION myvarcharsend(myvarchar) RETURNS bytea LANGUAGE internal STABLE PARALLEL SAFE STRICT AS 'varcharsend'; NOTICE: argument type myvarchar is only a shell +LINE 1: CREATE FUNCTION myvarcharsend(myvarchar) RETURNS bytea + ^ CREATE FUNCTION myvarcharrecv(internal, oid, integer) RETURNS myvarchar LANGUAGE internal STABLE PARALLEL SAFE STRICT AS 'varcharrecv'; NOTICE: return type myvarchar is only a shell diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out index 61825ef7d4ee1..f551624afb3a3 100644 --- a/src/test/regress/expected/create_view.out +++ b/src/test/regress/expected/create_view.out @@ -824,6 +824,54 @@ View definition: FROM temp_view_test.tx1 tx1_1 WHERE tx1.y1 = tx1_1.f1)); +-- Test correct deparsing of ORDER BY when there is an output name conflict +create view aliased_order_by as +select x1 as x2, x2 as x1, x3 from tt1 + order by x2; -- this is interpreted per SQL92, so really ordering by x1 +\d+ aliased_order_by + View "testviewschm2.aliased_order_by" + Column | Type | Collation | Nullable | Default | Storage | Description +--------+---------+-----------+----------+---------+----------+------------- + x2 | integer | | | | plain | + x1 | integer | | | | plain | + x3 | text | | | | extended | +View definition: + SELECT x1 AS x2, + x2 AS x1, + x3 + FROM tt1 + ORDER BY tt1.x1; + +alter view aliased_order_by rename column x1 to x0; +\d+ aliased_order_by + View "testviewschm2.aliased_order_by" + Column | Type | Collation | Nullable | Default | Storage | Description +--------+---------+-----------+----------+---------+----------+------------- + x2 | integer | | | | plain | + x0 | integer | | | | plain | + x3 | text | | | | extended | +View definition: + SELECT x1 AS x2, + x2 AS x0, + x3 + FROM tt1 + ORDER BY x1; + +alter view aliased_order_by rename column x3 to x1; +\d+ aliased_order_by + View "testviewschm2.aliased_order_by" + Column | Type | Collation | Nullable | Default | Storage | Description +--------+---------+-----------+----------+---------+----------+------------- + x2 | integer | | | | plain | + x0 | integer | | | | plain | + x1 | text | | | | extended | +View definition: + SELECT x1 AS x2, + x2 AS x0, + x3 AS x1 + FROM tt1 + ORDER BY tt1.x1; + -- Test aliasing of joins create view view_of_joins as select * from @@ -2202,6 +2250,21 @@ select pg_get_viewdef('tt26v', true); FROM ( VALUES (1,2,3)) v(x, y, z); (1 row) +-- test restriction on non-system view expansion. +create table tt27v_tbl (a int); +create view tt27v as select a from tt27v_tbl; +set restrict_nonsystem_relation_kind to 'view'; +select a from tt27v where a > 0; -- Error +ERROR: access to non-system view "tt27v" is restricted +insert into tt27v values (1); -- Error +ERROR: access to non-system view "tt27v" is restricted +select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view. + viewname +---------- + tt27v +(1 row) + +reset restrict_nonsystem_relation_kind; -- clean up all the random objects we made above DROP SCHEMA temp_view_test CASCADE; NOTICE: drop cascades to 27 other objects @@ -2233,7 +2296,7 @@ drop cascades to view aliased_view_2 drop cascades to view aliased_view_3 drop cascades to view aliased_view_4 DROP SCHEMA testviewschm2 CASCADE; -NOTICE: drop cascades to 77 other objects +NOTICE: drop cascades to 80 other objects DETAIL: drop cascades to table t1 drop cascades to view temporal1 drop cascades to view temporal2 @@ -2260,6 +2323,7 @@ drop cascades to view mysecview9 drop cascades to view unspecified_types drop cascades to table tt1 drop cascades to table tx1 +drop cascades to view aliased_order_by drop cascades to view view_of_joins drop cascades to table tbl1a drop cascades to view view_of_joins_2a @@ -2311,3 +2375,5 @@ drop cascades to view tt23v drop cascades to view tt24v drop cascades to view tt25v drop cascades to view tt26v +drop cascades to table tt27v_tbl +drop cascades to view tt27v diff --git a/src/test/regress/expected/database.out b/src/test/regress/expected/database.out index 454db91ec090b..4cbdbdf84d0c5 100644 --- a/src/test/regress/expected/database.out +++ b/src/test/regress/expected/database.out @@ -12,4 +12,10 @@ WHERE datname = 'regression_utf8'; -- load catcache entry, if nothing else does ALTER DATABASE regression_utf8 RESET TABLESPACE; ROLLBACK; +CREATE ROLE regress_datdba_before; +CREATE ROLE regress_datdba_after; +ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; +REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; DROP DATABASE regression_utf8; +DROP ROLE regress_datdba_before; +DROP ROLE regress_datdba_after; diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out index f5949f3d174dd..dcab9e76f45de 100644 --- a/src/test/regress/expected/date.out +++ b/src/test/regress/expected/date.out @@ -94,17 +94,17 @@ SELECT date '1/8/1999'; ERROR: date/time field value out of range: "1/8/1999" LINE 1: SELECT date '1/8/1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1/18/1999'; ERROR: date/time field value out of range: "1/18/1999" LINE 1: SELECT date '1/18/1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '18/1/1999'; ERROR: date/time field value out of range: "18/1/1999" LINE 1: SELECT date '18/1/1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01/02/03'; date ------------ @@ -139,7 +139,7 @@ SELECT date 'January 8, 99 BC'; ERROR: date/time field value out of range: "January 8, 99 BC" LINE 1: SELECT date 'January 8, 99 BC'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '99-Jan-08'; date ------------ @@ -156,7 +156,7 @@ SELECT date '08-Jan-99'; ERROR: date/time field value out of range: "08-Jan-99" LINE 1: SELECT date '08-Jan-99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '08-Jan-1999'; date ------------ @@ -167,7 +167,7 @@ SELECT date 'Jan-08-99'; ERROR: date/time field value out of range: "Jan-08-99" LINE 1: SELECT date 'Jan-08-99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date 'Jan-08-1999'; date ------------ @@ -198,7 +198,7 @@ SELECT date '08 Jan 99'; ERROR: date/time field value out of range: "08 Jan 99" LINE 1: SELECT date '08 Jan 99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '08 Jan 1999'; date ------------ @@ -209,7 +209,7 @@ SELECT date 'Jan 08 99'; ERROR: date/time field value out of range: "Jan 08 99" LINE 1: SELECT date 'Jan 08 99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date 'Jan 08 1999'; date ------------ @@ -244,22 +244,22 @@ SELECT date '08-01-99'; ERROR: date/time field value out of range: "08-01-99" LINE 1: SELECT date '08-01-99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '08-01-1999'; ERROR: date/time field value out of range: "08-01-1999" LINE 1: SELECT date '08-01-1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01-08-99'; ERROR: date/time field value out of range: "01-08-99" LINE 1: SELECT date '01-08-99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01-08-1999'; ERROR: date/time field value out of range: "01-08-1999" LINE 1: SELECT date '01-08-1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '99-08-01'; date ------------ @@ -288,22 +288,22 @@ SELECT date '08 01 99'; ERROR: date/time field value out of range: "08 01 99" LINE 1: SELECT date '08 01 99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '08 01 1999'; ERROR: date/time field value out of range: "08 01 1999" LINE 1: SELECT date '08 01 1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01 08 99'; ERROR: date/time field value out of range: "01 08 99" LINE 1: SELECT date '01 08 99'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01 08 1999'; ERROR: date/time field value out of range: "01 08 1999" LINE 1: SELECT date '01 08 1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '99 08 01'; date ------------ @@ -345,7 +345,7 @@ SELECT date '1/18/1999'; ERROR: date/time field value out of range: "1/18/1999" LINE 1: SELECT date '1/18/1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '18/1/1999'; date ------------ @@ -392,7 +392,7 @@ SELECT date '99-Jan-08'; ERROR: date/time field value out of range: "99-Jan-08" LINE 1: SELECT date '99-Jan-08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-Jan-08'; date ------------ @@ -435,7 +435,7 @@ SELECT date '99 Jan 08'; ERROR: date/time field value out of range: "99 Jan 08" LINE 1: SELECT date '99 Jan 08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999 Jan 08'; date ------------ @@ -480,7 +480,7 @@ SELECT date '99-01-08'; ERROR: date/time field value out of range: "99-01-08" LINE 1: SELECT date '99-01-08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-01-08'; date ------------ @@ -515,7 +515,7 @@ SELECT date '99-08-01'; ERROR: date/time field value out of range: "99-08-01" LINE 1: SELECT date '99-08-01'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-08-01'; date ------------ @@ -526,7 +526,7 @@ SELECT date '99 01 08'; ERROR: date/time field value out of range: "99 01 08" LINE 1: SELECT date '99 01 08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999 01 08'; date ------------ @@ -561,7 +561,7 @@ SELECT date '99 08 01'; ERROR: date/time field value out of range: "99 08 01" LINE 1: SELECT date '99 08 01'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999 08 01'; date ------------ @@ -603,7 +603,7 @@ SELECT date '18/1/1999'; ERROR: date/time field value out of range: "18/1/1999" LINE 1: SELECT date '18/1/1999'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '01/02/03'; date ------------ @@ -644,7 +644,7 @@ SELECT date '99-Jan-08'; ERROR: date/time field value out of range: "99-Jan-08" LINE 1: SELECT date '99-Jan-08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-Jan-08'; date ------------ @@ -731,7 +731,7 @@ SELECT date '99-01-08'; ERROR: date/time field value out of range: "99-01-08" LINE 1: SELECT date '99-01-08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-01-08'; date ------------ @@ -766,7 +766,7 @@ SELECT date '99-08-01'; ERROR: date/time field value out of range: "99-08-01" LINE 1: SELECT date '99-08-01'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999-08-01'; date ------------ @@ -777,7 +777,7 @@ SELECT date '99 01 08'; ERROR: date/time field value out of range: "99 01 08" LINE 1: SELECT date '99 01 08'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999 01 08'; date ------------ @@ -812,7 +812,7 @@ SELECT date '99 08 01'; ERROR: date/time field value out of range: "99 08 01" LINE 1: SELECT date '99 08 01'; ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. SELECT date '1999 08 01'; date ------------ @@ -1295,7 +1295,7 @@ SELECT DATE_TRUNC('MILLENNIUM', TIMESTAMP '1970-03-20 04:30:00.00000'); -- 1001 SELECT DATE_TRUNC('MILLENNIUM', DATE '1970-03-20'); -- 1001-01-01 date_trunc ------------------------------ - Thu Jan 01 00:00:00 1001 PST + Thu Jan 01 00:00:00 1001 LMT (1 row) SELECT DATE_TRUNC('CENTURY', TIMESTAMP '1970-03-20 04:30:00.00000'); -- 1901 @@ -1319,13 +1319,13 @@ SELECT DATE_TRUNC('CENTURY', DATE '2004-08-10'); -- 2001-01-01 SELECT DATE_TRUNC('CENTURY', DATE '0002-02-04'); -- 0001-01-01 date_trunc ------------------------------ - Mon Jan 01 00:00:00 0001 PST + Mon Jan 01 00:00:00 0001 LMT (1 row) SELECT DATE_TRUNC('CENTURY', DATE '0055-08-10 BC'); -- 0100-01-01 BC date_trunc --------------------------------- - Tue Jan 01 00:00:00 0100 PST BC + Tue Jan 01 00:00:00 0100 LMT BC (1 row) SELECT DATE_TRUNC('DECADE', DATE '1993-12-25'); -- 1990-01-01 @@ -1337,13 +1337,13 @@ SELECT DATE_TRUNC('DECADE', DATE '1993-12-25'); -- 1990-01-01 SELECT DATE_TRUNC('DECADE', DATE '0004-12-25'); -- 0001-01-01 BC date_trunc --------------------------------- - Sat Jan 01 00:00:00 0001 PST BC + Sat Jan 01 00:00:00 0001 LMT BC (1 row) SELECT DATE_TRUNC('DECADE', DATE '0002-12-31 BC'); -- 0011-01-01 BC date_trunc --------------------------------- - Mon Jan 01 00:00:00 0011 PST BC + Mon Jan 01 00:00:00 0011 LMT BC (1 row) -- @@ -1528,6 +1528,8 @@ select make_date(2013, 13, 1); ERROR: date field value out of range: 2013-13-01 select make_date(2013, 11, -1); ERROR: date field value out of range: 2013-11--1 +SELECT make_date(-2147483648, 1, 1); +ERROR: date field value out of range: -2147483648-01-01 select make_time(10, 55, 100.1); ERROR: time field value out of range: 10:55:100.1 select make_time(24, 0, 2.1); diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out index f1121a87aa340..97c3bf54be554 100644 --- a/src/test/regress/expected/dbsize.out +++ b/src/test/regress/expected/dbsize.out @@ -79,6 +79,14 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM 11528652096115048448 | 10240 PB | -10240 PB (12 rows) +-- Ensure we get the expected results when passing the extremities of bigint +SELECT pg_size_pretty('-9223372036854775808'::bigint), + pg_size_pretty('9223372036854775807'::bigint); + pg_size_pretty | pg_size_pretty +----------------+---------------- + -8192 PB | 8192 PB +(1 row) + -- pg_size_bytes() tests SELECT size, pg_size_bytes(size) FROM (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '), diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out index 74d9ff2998d7a..75a078ada9e15 100644 --- a/src/test/regress/expected/dependency.out +++ b/src/test/regress/expected/dependency.out @@ -116,7 +116,7 @@ FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t'; RESET SESSION AUTHORIZATION; REASSIGN OWNED BY regress_dep_user1 TO regress_dep_user2; \dt deptest - List of relations + List of tables Schema | Name | Type | Owner --------+---------+-------+------------------- public | deptest | table | regress_dep_user2 diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index f65b66345ab57..ba6f05eeb7df6 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -15,6 +15,59 @@ NOTICE: drop cascades to type dependenttypetest -- this should fail because already gone drop domain domaindroptest cascade; ERROR: type "domaindroptest" does not exist +-- some error cases +create domain d_fail as no_such_type; +ERROR: type "no_such_type" does not exist +LINE 1: create domain d_fail as no_such_type; + ^ +create domain d_fail as int constraint cc REFERENCES this_table_not_exists(i); +ERROR: foreign key constraints not possible for domains +LINE 1: create domain d_fail as int constraint cc REFERENCES this_ta... + ^ +create domain d_fail as int4 not null no inherit; +ERROR: not-null constraints for domains cannot be marked NO INHERIT +LINE 1: create domain d_fail as int4 not null no inherit; + ^ +create domain d_fail as int4 not null null; +ERROR: conflicting NULL/NOT NULL constraints +LINE 1: create domain d_fail as int4 not null null; + ^ +create domain d_fail as int4 not null default 3 default 3; +ERROR: multiple default expressions +LINE 1: create domain d_fail as int4 not null default 3 default 3; + ^ +create domain d_fail int4 DEFAULT 3 + 'h'; +ERROR: invalid input syntax for type integer: "h" +LINE 1: create domain d_fail int4 DEFAULT 3 + 'h'; + ^ +create domain d_fail int4 collate "C"; +ERROR: collations are not supported by type integer +LINE 1: create domain d_fail int4 collate "C"; + ^ +create domain d_fail as anyelement; +ERROR: "anyelement" is not a valid base type for a domain +LINE 1: create domain d_fail as anyelement; + ^ +create domain d_fail as int4 unique; +ERROR: unique constraints not possible for domains +LINE 1: create domain d_fail as int4 unique; + ^ +create domain d_fail as int4 PRIMARY key; +ERROR: primary key constraints not possible for domains +LINE 1: create domain d_fail as int4 PRIMARY key; + ^ +create domain d_fail as int4 constraint cc generated by default as identity; +ERROR: specifying GENERATED not supported for domains +LINE 1: create domain d_fail as int4 constraint cc generated by defa... + ^ +create domain d_fail as int4 constraint cc check (values > 1) no inherit; +ERROR: check constraints for domains cannot be marked NO INHERIT +LINE 1: create domain d_fail as int4 constraint cc check (values > 1... + ^ +create domain d_fail as int4 constraint cc check (values > 1) deferrable; +ERROR: specifying constraint deferrability not supported for domains +LINE 1: ...n d_fail as int4 constraint cc check (values > 1) deferrable... + ^ -- Test domain input. -- Note: the point of checking both INSERT and COPY FROM is that INSERT -- exercises CoerceToDomain while COPY exercises domain_in. @@ -743,6 +796,20 @@ update domnotnull set col1 = null; -- fails ERROR: domain dnotnulltest does not allow null values alter domain dnotnulltest drop not null; update domnotnull set col1 = null; +update domnotnull set col1 = 5; +-- these constraints can also be added and removed by name +alter domain dnotnulltest add constraint dnotnulltest_notnull not null; +update domnotnull set col1 = null; -- fails +ERROR: domain dnotnulltest does not allow null values +select conname, pg_get_constraintdef(oid) from pg_constraint + where contypid = 'dnotnulltest'::regtype; + conname | pg_get_constraintdef +----------------------+---------------------- + dnotnulltest_notnull | NOT NULL +(1 row) + +alter domain dnotnulltest drop constraint dnotnulltest_notnull; +update domnotnull set col1 = null; drop domain dnotnulltest cascade; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to column col2 of table domnotnull @@ -1283,6 +1350,28 @@ select pg_basetype(1); -- expect NULL not error drop domain mytext cascade; NOTICE: drop cascades to type mytext_child_1 -- +-- Explicit enforceability specification not allowed +--- +CREATE DOMAIN constraint_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; +ERROR: specifying constraint enforceability not supported for domains +LINE 1: ...AS int CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; + ^ +CREATE DOMAIN constraint_not_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED; +ERROR: specifying constraint enforceability not supported for domains +LINE 1: ...S int CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORC... + ^ +CREATE DOMAIN constraint_enforced_dom AS int; +-- XXX misleading error messages +ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; +ERROR: CHECK constraints cannot be marked ENFORCED +LINE 1: ...om ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; + ^ +ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED; +ERROR: CHECK constraints cannot be marked NOT ENFORCED +LINE 1: ...m ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORC... + ^ +DROP DOMAIN constraint_enforced_dom; +-- -- Information schema -- SELECT * FROM information_schema.column_domain_usage diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out index 1d09c208bc903..4d9f36d0d3677 100644 --- a/src/test/regress/expected/enum.out +++ b/src/test/regress/expected/enum.out @@ -581,7 +581,7 @@ DETAIL: Key (id)=(red) is still referenced from table "enumtest_child". CREATE TYPE bogus AS ENUM('good', 'bad', 'ugly'); CREATE TABLE enumtest_bogus_child(parent bogus REFERENCES enumtest_parent); ERROR: foreign key constraint "enumtest_bogus_child_parent_fkey" cannot be implemented -DETAIL: Key columns "parent" and "id" are of incompatible types: bogus and rainbow. +DETAIL: Key columns "parent" of the referencing table and "id" of the referenced table are of incompatible types: bogus and rainbow. DROP TYPE bogus; -- check renaming a value ALTER TYPE rainbow RENAME VALUE 'red' TO 'crimson'; diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out index 126f7047fed3a..ad8ab294ff624 100644 --- a/src/test/regress/expected/equivclass.out +++ b/src/test/regress/expected/equivclass.out @@ -16,6 +16,8 @@ NOTICE: return type int8alias1 is only a shell create function int8alias1out(int8alias1) returns cstring strict immutable language internal as 'int8out'; NOTICE: argument type int8alias1 is only a shell +LINE 1: create function int8alias1out(int8alias1) returns cstring + ^ create type int8alias1 ( input = int8alias1in, output = int8alias1out, @@ -28,6 +30,8 @@ NOTICE: return type int8alias2 is only a shell create function int8alias2out(int8alias2) returns cstring strict immutable language internal as 'int8out'; NOTICE: argument type int8alias2 is only a shell +LINE 1: create function int8alias2out(int8alias2) returns cstring + ^ create type int8alias2 ( input = int8alias2in, output = int8alias2out, @@ -430,6 +434,36 @@ explain (costs off) Filter: ((unique1 IS NOT NULL) AND (unique2 IS NOT NULL)) (2 rows) +-- Test that broken ECs are processed correctly during self join removal. +-- Disable merge joins so that we don't get an error about missing commutator. +-- Test both orientations of the join clause, because only one of them breaks +-- the EC. +set enable_mergejoin to off; +explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff + join ec1 p on m.ff + n.ff = p.f1; + QUERY PLAN +--------------------------------------- + Nested Loop + Join Filter: ((n.ff + n.ff) = p.f1) + -> Seq Scan on ec0 n + -> Materialize + -> Seq Scan on ec1 p +(5 rows) + +explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff + join ec1 p on p.f1::int8 = (m.ff + n.ff)::int8alias1; + QUERY PLAN +--------------------------------------------------------------- + Nested Loop + Join Filter: ((p.f1)::bigint = ((n.ff + n.ff))::int8alias1) + -> Seq Scan on ec0 n + -> Materialize + -> Seq Scan on ec1 p +(5 rows) + +reset enable_mergejoin; -- this could be converted, but isn't at present explain (costs off) select * from tenk1 where unique1 = unique1 or unique2 = unique2; @@ -451,3 +485,51 @@ explain (costs off) -- this should not require a sort Filter: (f1 = 'foo'::name) (2 rows) +-- +-- test handling of merge/hash clauses that do not have valid commutators +-- +-- There are not (and should not be) any such operators built into Postgres +-- that are mergejoinable or hashable but have no commutators; so we leverage +-- the alias type 'int8alias1' created in this file to conduct the tests. +-- That's why this test is included here rather than in join.sql. +begin; +create table tbl_nocom(a int8, b int8alias1); +-- check that non-commutable merge clauses do not lead to error +set enable_hashjoin to off; +set enable_mergejoin to on; +explain (costs off) +select * from tbl_nocom t1 full join tbl_nocom t2 on t2.a = t1.b; + QUERY PLAN +-------------------------------------- + Merge Full Join + Merge Cond: (t2.a = t1.b) + -> Sort + Sort Key: t2.a + -> Seq Scan on tbl_nocom t2 + -> Sort + Sort Key: t1.b USING < + -> Seq Scan on tbl_nocom t1 +(8 rows) + +-- check that non-commutable hash clauses do not lead to error +alter operator = (int8, int8alias1) set (hashes); +alter operator family integer_ops using hash add + operator 1 = (int8, int8alias1); +create function hashint8alias1(int8alias1) returns int + strict immutable language internal as 'hashint8'; +alter operator family integer_ops using hash add + function 1 hashint8alias1(int8alias1); +set enable_hashjoin to on; +set enable_mergejoin to off; +explain (costs off) +select * from tbl_nocom t1 full join tbl_nocom t2 on t2.a = t1.b; + QUERY PLAN +-------------------------------------- + Hash Full Join + Hash Cond: (t2.a = t1.b) + -> Seq Scan on tbl_nocom t2 + -> Hash + -> Seq Scan on tbl_nocom t1 +(5 rows) + +abort; diff --git a/src/test/regress/expected/explain.out b/src/test/regress/expected/explain.out index 6585c6a69efe4..c53bf9c8aa3cc 100644 --- a/src/test/regress/expected/explain.out +++ b/src/test/regress/expected/explain.out @@ -60,27 +60,27 @@ select explain_filter('explain select * from int8_tbl i8'); Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (1 row) -select explain_filter('explain (analyze) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) +select explain_filter('explain (analyze, buffers off) select * from int8_tbl i8'); + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Planning Time: N.N ms Execution Time: N.N ms (3 rows) -select explain_filter('explain (analyze, verbose) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------------- - Seq Scan on public.int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) +select explain_filter('explain (analyze, buffers off, verbose) select * from int8_tbl i8'); + explain_filter +-------------------------------------------------------------------------------------------------------- + Seq Scan on public.int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Output: q1, q2 Planning Time: N.N ms Execution Time: N.N ms (4 rows) select explain_filter('explain (analyze, buffers, format text) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Planning Time: N.N ms Execution Time: N.N ms (3 rows) @@ -102,8 +102,9 @@ select explain_filter('explain (analyze, buffers, format xml) select * from int8 N + N.N + N.N + - N + + N.N + N + + false + N + N + N+ @@ -150,8 +151,9 @@ select explain_filter('explain (analyze, serialize, buffers, format yaml) select Plan Width: N + Actual Startup Time: N.N + Actual Total Time: N.N + - Actual Rows: N + + Actual Rows: N.N + Actual Loops: N + + Disabled: false + Shared Hit Blocks: N + Shared Read Blocks: N + Shared Dirtied Blocks: N + @@ -213,6 +215,7 @@ select explain_filter('explain (buffers, format json) select * from int8_tbl i8' "Total Cost": N.N, + "Plan Rows": N, + "Plan Width": N, + + "Disabled": false, + "Shared Hit Blocks": N, + "Shared Read Blocks": N, + "Shared Dirtied Blocks": N, + @@ -240,6 +243,42 @@ select explain_filter('explain (buffers, format json) select * from int8_tbl i8' ] (1 row) +-- Check expansion of window definitions +select explain_filter('explain verbose select sum(unique1) over w, sum(unique2) over (w order by hundred), sum(tenthous) over (w order by hundred) from tenk1 window w as (partition by ten)'); + explain_filter +------------------------------------------------------------------------------------------------------- + WindowAgg (cost=N.N..N.N rows=N width=N) + Output: sum(unique1) OVER w, (sum(unique2) OVER w1), (sum(tenthous) OVER w1), ten, hundred + Window: w AS (PARTITION BY tenk1.ten) + -> WindowAgg (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous, sum(unique2) OVER w1, sum(tenthous) OVER w1 + Window: w1 AS (PARTITION BY tenk1.ten ORDER BY tenk1.hundred) + -> Sort (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous + Sort Key: tenk1.ten, tenk1.hundred + -> Seq Scan on public.tenk1 (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous +(11 rows) + +select explain_filter('explain verbose select sum(unique1) over w1, sum(unique2) over (w1 order by hundred), sum(tenthous) over (w1 order by hundred rows 10 preceding) from tenk1 window w1 as (partition by ten)'); + explain_filter +--------------------------------------------------------------------------------------------------------- + WindowAgg (cost=N.N..N.N rows=N width=N) + Output: sum(unique1) OVER w1, (sum(unique2) OVER w2), (sum(tenthous) OVER w3), ten, hundred + Window: w1 AS (PARTITION BY tenk1.ten) + -> WindowAgg (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous, (sum(unique2) OVER w2), sum(tenthous) OVER w3 + Window: w3 AS (PARTITION BY tenk1.ten ORDER BY tenk1.hundred ROWS 'N'::bigint PRECEDING) + -> WindowAgg (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous, sum(unique2) OVER w2 + Window: w2 AS (PARTITION BY tenk1.ten ORDER BY tenk1.hundred) + -> Sort (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous + Sort Key: tenk1.ten, tenk1.hundred + -> Seq Scan on public.tenk1 (cost=N.N..N.N rows=N width=N) + Output: ten, hundred, unique1, unique2, tenthous +(14 rows) + -- Check output including I/O timings. These fields are conditional -- but always set in JSON format, so check them only in this case. set track_io_timing = on; @@ -260,8 +299,9 @@ select explain_filter('explain (analyze, buffers, format json) select * from int "Plan Width": N, + "Actual Startup Time": N.N, + "Actual Total Time": N.N, + - "Actual Rows": N, + + "Actual Rows": N.N, + "Actual Loops": N, + + "Disabled": false, + "Shared Hit Blocks": N, + "Shared Read Blocks": N, + "Shared Dirtied Blocks": N, + @@ -348,10 +388,10 @@ select explain_filter('explain (memory) select * from int8_tbl i8'); Memory: used=NkB allocated=NkB (2 rows) -select explain_filter('explain (memory, analyze) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) +select explain_filter('explain (memory, analyze, buffers off) select * from int8_tbl i8'); + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Memory: used=NkB allocated=NkB Planning Time: N.N ms Execution Time: N.N ms @@ -370,6 +410,7 @@ select explain_filter('explain (memory, summary, format yaml) select * from int8 Total Cost: N.N + Plan Rows: N + Plan Width: N + + Disabled: false + Planning: + Memory Used: N + Memory Allocated: N + @@ -393,10 +434,31 @@ select explain_filter('explain (memory, analyze, format json) select * from int8 "Plan Width": N, + "Actual Startup Time": N.N, + "Actual Total Time": N.N, + - "Actual Rows": N, + - "Actual Loops": N + + "Actual Rows": N.N, + + "Actual Loops": N, + + "Disabled": false, + + "Shared Hit Blocks": N, + + "Shared Read Blocks": N, + + "Shared Dirtied Blocks": N, + + "Shared Written Blocks": N, + + "Local Hit Blocks": N, + + "Local Read Blocks": N, + + "Local Dirtied Blocks": N, + + "Local Written Blocks": N, + + "Temp Read Blocks": N, + + "Temp Written Blocks": N + }, + "Planning": { + + "Shared Hit Blocks": N, + + "Shared Read Blocks": N, + + "Shared Dirtied Blocks": N, + + "Shared Written Blocks": N, + + "Local Hit Blocks": N, + + "Local Read Blocks": N, + + "Local Dirtied Blocks": N, + + "Local Written Blocks": N, + + "Temp Read Blocks": N, + + "Temp Written Blocks": N, + "Memory Used": N, + "Memory Allocated": N + }, + @@ -497,11 +559,12 @@ select jsonb_pretty( "string4" + ], + "Schema": "public", + + "Disabled": false, + "Node Type": "Seq Scan", + "Plan Rows": 0, + "Plan Width": 0, + "Total Cost": 0.0, + - "Actual Rows": 0, + + "Actual Rows": 0.0, + "Actual Loops": 0, + "Startup Cost": 0.0, + "Async Capable": false, + @@ -540,6 +603,7 @@ select jsonb_pretty( "stringu2", + "string4" + ], + + "Disabled": false, + "Sort Key": [ + "tenk1.tenthous" + ], + @@ -547,7 +611,7 @@ select jsonb_pretty( "Plan Rows": 0, + "Plan Width": 0, + "Total Cost": 0.0, + - "Actual Rows": 0, + + "Actual Rows": 0.0, + "Actual Loops": 0, + "Startup Cost": 0.0, + "Async Capable": false, + @@ -586,11 +650,12 @@ select jsonb_pretty( "stringu2", + "string4" + ], + + "Disabled": false, + "Node Type": "Gather Merge", + "Plan Rows": 0, + "Plan Width": 0, + "Total Cost": 0.0, + - "Actual Rows": 0, + + "Actual Rows": 0.0, + "Actual Loops": 0, + "Startup Cost": 0.0, + "Async Capable": false, + @@ -653,41 +718,99 @@ select explain_filter('explain (verbose) select * from int8_tbl i8'); Query Identifier: N (3 rows) +-- Test compute_query_id with utility statements containing plannable query +select explain_filter('explain (verbose) declare test_cur cursor for select * from int8_tbl'); + explain_filter +------------------------------------------------------------- + Seq Scan on public.int8_tbl (cost=N.N..N.N rows=N width=N) + Output: q1, q2 + Query Identifier: N +(3 rows) + +select explain_filter('explain (verbose) create table test_ctas as select 1'); + explain_filter +---------------------------------------- + Result (cost=N.N..N.N rows=N width=N) + Output: N + Query Identifier: N +(3 rows) + -- Test SERIALIZE option -select explain_filter('explain (analyze,serialize) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) +select explain_filter('explain (analyze,buffers off,serialize) select * from int8_tbl i8'); + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Planning Time: N.N ms Serialization: time=N.N ms output=NkB format=text Execution Time: N.N ms (4 rows) select explain_filter('explain (analyze,serialize text,buffers,timing off) select * from int8_tbl i8'); - explain_filter ---------------------------------------------------------------------------------- - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual rows=N loops=N) + explain_filter +----------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual rows=N.N loops=N) Planning Time: N.N ms Serialization: output=NkB format=text Execution Time: N.N ms (4 rows) select explain_filter('explain (analyze,serialize binary,buffers,timing) select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Planning Time: N.N ms Serialization: time=N.N ms output=NkB format=binary Execution Time: N.N ms (4 rows) -- this tests an edge case where we have no data to return -select explain_filter('explain (analyze,serialize) create temp table explain_temp as select * from int8_tbl i8'); - explain_filter ------------------------------------------------------------------------------------------------ - Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N loops=N) +select explain_filter('explain (analyze,buffers off,serialize) create temp table explain_temp as select * from int8_tbl i8'); + explain_filter +------------------------------------------------------------------------------------------------- + Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N) (actual time=N.N..N.N rows=N.N loops=N) Planning Time: N.N ms Serialization: time=N.N ms output=NkB format=text Execution Time: N.N ms (4 rows) +-- Test tuplestore storage usage in Window aggregate (memory case) +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over() from generate_series(1,10) a(n)'); + explain_filter +---------------------------------------------------------------------------------- + WindowAgg (actual time=N.N..N.N rows=N.N loops=N) + Window: w1 AS () + Storage: Memory Maximum Storage: NkB + -> Function Scan on generate_series a (actual time=N.N..N.N rows=N.N loops=N) + Planning Time: N.N ms + Execution Time: N.N ms +(6 rows) + +-- Test tuplestore storage usage in Window aggregate (disk case) +set work_mem to 64; +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over() from generate_series(1,2500) a(n)'); + explain_filter +---------------------------------------------------------------------------------- + WindowAgg (actual time=N.N..N.N rows=N.N loops=N) + Window: w1 AS () + Storage: Disk Maximum Storage: NkB + -> Function Scan on generate_series a (actual time=N.N..N.N rows=N.N loops=N) + Planning Time: N.N ms + Execution Time: N.N ms +(6 rows) + +-- Test tuplestore storage usage in Window aggregate (memory and disk case, final result is disk) +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over(partition by m) from (SELECT n < 3 as m, n from generate_series(1,2500) a(n))'); + explain_filter +---------------------------------------------------------------------------------------- + WindowAgg (actual time=N.N..N.N rows=N.N loops=N) + Window: w1 AS (PARTITION BY ((a.n < N))) + Storage: Disk Maximum Storage: NkB + -> Sort (actual time=N.N..N.N rows=N.N loops=N) + Sort Key: ((a.n < N)) + Sort Method: external merge Disk: NkB + -> Function Scan on generate_series a (actual time=N.N..N.N rows=N.N loops=N) + Planning Time: N.N ms + Execution Time: N.N ms +(9 rows) + +reset work_mem; diff --git a/src/test/regress/expected/expressions.out b/src/test/regress/expected/expressions.out index caeeb19674092..21c54fc1989c9 100644 --- a/src/test/regress/expected/expressions.out +++ b/src/test/regress/expected/expressions.out @@ -337,9 +337,13 @@ NOTICE: return type myint is only a shell create function myintout(myint) returns cstring strict immutable language internal as 'int4out'; NOTICE: argument type myint is only a shell +LINE 1: create function myintout(myint) returns cstring strict immut... + ^ create function myinthash(myint) returns integer strict immutable language internal as 'hashint4'; NOTICE: argument type myint is only a shell +LINE 1: create function myinthash(myint) returns integer strict immu... + ^ create type myint (input = myintin, output = myintout, like = int4); create cast (int4 as myint) without function; create cast (myint as int4) without function; diff --git a/src/test/regress/expected/fast_default.out b/src/test/regress/expected/fast_default.out index 59365dad964a9..ccbcdf8403fa9 100644 --- a/src/test/regress/expected/fast_default.out +++ b/src/test/regress/expected/fast_default.out @@ -58,6 +58,18 @@ ALTER TABLE has_volatile ADD col2 int DEFAULT 1; ALTER TABLE has_volatile ADD col3 timestamptz DEFAULT current_timestamp; ALTER TABLE has_volatile ADD col4 int DEFAULT (random() * 10000)::int; NOTICE: rewriting table has_volatile for reason 2 +-- virtual generated columns don't need a rewrite +ALTER TABLE has_volatile ADD col5 int GENERATED ALWAYS AS (tableoid::int + col2) VIRTUAL; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE float8; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE numeric; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE numeric; +-- here, we do need a rewrite +ALTER TABLE has_volatile ALTER COLUMN col1 SET DATA TYPE float8, + ADD COLUMN col6 float8 GENERATED ALWAYS AS (col1 * 4) VIRTUAL; +NOTICE: rewriting table has_volatile for reason 4 +-- stored generated columns need a rewrite +ALTER TABLE has_volatile ADD col7 int GENERATED ALWAYS AS (55) stored; +NOTICE: rewriting table has_volatile for reason 2 -- Test a large sample of different datatypes CREATE TABLE T(pk INT NOT NULL PRIMARY KEY, c_int INT DEFAULT 1); SELECT set('t'); @@ -245,6 +257,71 @@ SELECT comp(); (1 row) DROP TABLE T; +-- Test domains with default value for table rewrite. +CREATE DOMAIN domain1 AS int DEFAULT 11; -- constant +CREATE DOMAIN domain2 AS int DEFAULT random(min=>10, max=>100); -- volatile +CREATE DOMAIN domain3 AS text DEFAULT foo(4); -- stable +CREATE DOMAIN domain4 AS text[] + DEFAULT ('{"This", "is", "' || foo(4) || '","the", "real", "world"}')::TEXT[]; +CREATE TABLE t2 (a domain1); +INSERT INTO t2 VALUES (1),(2); +-- no table rewrite +ALTER TABLE t2 ADD COLUMN b domain1 default 3; +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + attnum | attname | atthasmissing | atthasdef | attmissingval +--------+---------+---------------+-----------+--------------- + 1 | a | f | f | + 2 | b | t | t | {3} +(2 rows) + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN c domain3 default left(random()::text,3); +NOTICE: rewriting table t2 for reason 2 +-- no table rewrite +ALTER TABLE t2 ADD COLUMN d domain4; +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + attnum | attname | atthasmissing | atthasdef | attmissingval +--------+---------+---------------+-----------+----------------------------------- + 1 | a | f | f | + 2 | b | f | t | + 3 | c | f | t | + 4 | d | t | f | {"{This,is,abcd,the,real,world}"} +(4 rows) + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN e domain2; +NOTICE: rewriting table t2 for reason 2 +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + attnum | attname | atthasmissing | atthasdef | attmissingval +--------+---------+---------------+-----------+--------------- + 1 | a | f | f | + 2 | b | f | t | + 3 | c | f | t | + 4 | d | f | f | + 5 | e | f | f | +(5 rows) + +SELECT a, b, length(c) = 3 as c_ok, d, e >= 10 as e_ok FROM t2; + a | b | c_ok | d | e_ok +---+---+------+-------------------------------+------ + 1 | 3 | t | {This,is,abcd,the,real,world} | t + 2 | 3 | t | {This,is,abcd,the,real,world} | t +(2 rows) + +DROP TABLE t2; +DROP DOMAIN domain1; +DROP DOMAIN domain2; +DROP DOMAIN domain3; +DROP DOMAIN domain4; DROP FUNCTION foo(INT); -- Fall back to full rewrite for volatile expressions CREATE TABLE T(pk INT NOT NULL PRIMARY KEY); diff --git a/src/test/regress/expected/float4-misrounded-input.out b/src/test/regress/expected/float4-misrounded-input.out index a4272316274f3..61c68a6c9fff5 100644 --- a/src/test/regress/expected/float4-misrounded-input.out +++ b/src/test/regress/expected/float4-misrounded-input.out @@ -308,14 +308,14 @@ SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; UPDATE FLOAT4_TBL SET f1 = FLOAT4_TBL.f1 * '-1' WHERE FLOAT4_TBL.f1 > '0.0'; -SELECT * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL ORDER BY 1; f1 ---------------- - 0 - -34.84 - -1004.3 -1.2345679e+20 + -1004.3 + -34.84 -1.2345679e-20 + 0 (5 rows) -- test edge-case coercions to integer @@ -490,6 +490,8 @@ NOTICE: return type xfloat4 is only a shell create function xfloat4out(xfloat4) returns cstring immutable strict language internal as 'int4out'; NOTICE: argument type xfloat4 is only a shell +LINE 1: create function xfloat4out(xfloat4) returns cstring immutabl... + ^ create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4); create cast (xfloat4 as float4) without function; create cast (float4 as xfloat4) without function; diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out index 65ee82caaeeb8..eaed1f2bfe71d 100644 --- a/src/test/regress/expected/float4.out +++ b/src/test/regress/expected/float4.out @@ -308,14 +308,14 @@ SELECT f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; UPDATE FLOAT4_TBL SET f1 = FLOAT4_TBL.f1 * '-1' WHERE FLOAT4_TBL.f1 > '0.0'; -SELECT * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL ORDER BY 1; f1 ---------------- - 0 - -34.84 - -1004.3 -1.2345679e+20 + -1004.3 + -34.84 -1.2345679e-20 + 0 (5 rows) -- test edge-case coercions to integer @@ -490,6 +490,8 @@ NOTICE: return type xfloat4 is only a shell create function xfloat4out(xfloat4) returns cstring immutable strict language internal as 'int4out'; NOTICE: argument type xfloat4 is only a shell +LINE 1: create function xfloat4out(xfloat4) returns cstring immutabl... + ^ create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4); create cast (xfloat4 as float4) without function; create cast (float4 as xfloat4) without function; diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out index 344d6b7d6d76d..9c519f1a1a1a5 100644 --- a/src/test/regress/expected/float8.out +++ b/src/test/regress/expected/float8.out @@ -648,14 +648,14 @@ SELECT exp(f.f1) from FLOAT8_TBL f; ERROR: value out of range: underflow SELECT f.f1 / '0.0' from FLOAT8_TBL f; ERROR: division by zero -SELECT * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL ORDER BY 1; f1 ----------------------- - 0 - -34.84 - -1004.3 -1.2345678901234e+200 + -1004.3 + -34.84 -1.2345678901234e-200 + 0 (5 rows) -- hyperbolic functions @@ -829,6 +829,63 @@ FROM (VALUES (float8 '-infinity'), NaN | NaN | NaN (22 rows) +RESET extra_float_digits; +-- gamma functions +-- we run these with extra_float_digits = -1, to get consistently rounded +-- results on all platforms. +SET extra_float_digits = -1; +SELECT x, + gamma(x), + lgamma(x) +FROM (VALUES (0.5), (1), (2), (3), (4), (5), + (float8 'infinity'), (float8 'nan')) AS t(x); + x | gamma | lgamma +----------+-----------------+------------------ + 0.5 | 1.7724538509055 | 0.5723649429247 + 1 | 1 | 0 + 2 | 1 | 0 + 3 | 2 | 0.69314718055995 + 4 | 6 | 1.7917594692281 + 5 | 24 | 3.1780538303479 + Infinity | Infinity | Infinity + NaN | NaN | NaN +(8 rows) + +-- test overflow/underflow handling +SELECT gamma(float8 '-infinity'); +ERROR: value out of range: overflow +SELECT lgamma(float8 '-infinity'); + lgamma +---------- + Infinity +(1 row) + +SELECT gamma(float8 '-1000.5'); +ERROR: value out of range: underflow +SELECT lgamma(float8 '-1000.5'); + lgamma +------------------ + -5914.4377011169 +(1 row) + +SELECT gamma(float8 '-1'); +ERROR: value out of range: overflow +SELECT lgamma(float8 '-1'); +ERROR: value out of range: overflow +SELECT gamma(float8 '0'); +ERROR: value out of range: overflow +SELECT lgamma(float8 '0'); +ERROR: value out of range: overflow +SELECT gamma(float8 '1000'); +ERROR: value out of range: overflow +SELECT lgamma(float8 '1000'); + lgamma +----------------- + 5905.2204232092 +(1 row) + +SELECT lgamma(float8 '1e308'); +ERROR: value out of range: overflow RESET extra_float_digits; -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); @@ -1022,6 +1079,12 @@ NOTICE: return type xfloat8 is only a shell create function xfloat8out(xfloat8) returns cstring immutable strict language internal as 'int8out'; NOTICE: argument type xfloat8 is only a shell +LINE 1: create function xfloat8out(xfloat8) returns cstring immutabl... + ^ +create type xfloat8 (input = xfloat8in, output = xfloat8out, like = no_such_type); +ERROR: type "no_such_type" does not exist +LINE 1: ...8 (input = xfloat8in, output = xfloat8out, like = no_such_ty... + ^ create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8); create cast (xfloat8 as float8) without function; create cast (float8 as xfloat8) without function; diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 6ed50fdcfa0bf..cce49e509abe4 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -742,6 +742,8 @@ COMMENT ON COLUMN ft1.c1 IS 'ft1.c1'; Check constraints: "ft1_c2_check" CHECK (c2 <> ''::text) "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date) +Not-null constraints: + "ft1_c1_not_null" NOT NULL "c1" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -864,6 +866,9 @@ ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 SET STORAGE PLAIN; Check constraints: "ft1_c2_check" CHECK (c2 <> ''::text) "ft1_c3_check" CHECK (c3 >= '01-01-1994'::date AND c3 <= '01-31-1994'::date) +Not-null constraints: + "ft1_c1_not_null" NOT NULL "c1" + "ft1_c6_not_null" NOT NULL "c6" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1409,6 +1414,8 @@ CREATE FOREIGN TABLE ft2 () INHERITS (fd_pt1) c1 | integer | | not null | | plain | | c2 | text | | | | extended | | c3 | date | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1418,6 +1425,8 @@ Child tables: ft2, FOREIGN c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" (inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1430,6 +1439,8 @@ DROP FOREIGN TABLE ft2; c1 | integer | | not null | | plain | | c2 | text | | | | extended | | c3 | date | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" CREATE FOREIGN TABLE ft2 ( c1 integer NOT NULL, @@ -1443,6 +1454,8 @@ CREATE FOREIGN TABLE ft2 ( c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1454,6 +1467,8 @@ ALTER FOREIGN TABLE ft2 INHERIT fd_pt1; c1 | integer | | not null | | plain | | c2 | text | | | | extended | | c3 | date | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1463,6 +1478,8 @@ Child tables: ft2, FOREIGN c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1484,6 +1501,8 @@ NOTICE: merging column "c3" with inherited definition c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1497,6 +1516,8 @@ Child tables: ct3, c1 | integer | | not null | | plain | | c2 | text | | | | extended | | c3 | date | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (inherited) Inherits: ft2 \d+ ft3 @@ -1506,6 +1527,8 @@ Inherits: ft2 c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "ft3_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 Inherits: ft2 @@ -1527,6 +1550,9 @@ ALTER TABLE fd_pt1 ADD COLUMN c8 integer; c6 | integer | | | | plain | | c7 | integer | | not null | | plain | | c8 | integer | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" + "fd_pt1_c7_not_null" NOT NULL "c7" Child tables: ft2, FOREIGN \d+ ft2 @@ -1541,6 +1567,9 @@ Child tables: ft2, FOREIGN c6 | integer | | | | | plain | | c7 | integer | | not null | | | plain | | c8 | integer | | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) + "fd_pt1_c7_not_null" NOT NULL "c7" (inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1559,6 +1588,9 @@ Child tables: ct3, c6 | integer | | | | plain | | c7 | integer | | not null | | plain | | c8 | integer | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (inherited) + "fd_pt1_c7_not_null" NOT NULL "c7" (inherited) Inherits: ft2 \d+ ft3 @@ -1573,6 +1605,9 @@ Inherits: ft2 c6 | integer | | | | | plain | | c7 | integer | | not null | | | plain | | c8 | integer | | | | | plain | | +Not-null constraints: + "ft3_c1_not_null" NOT NULL "c1" (local, inherited) + "fd_pt1_c7_not_null" NOT NULL "c7" (inherited) Server: s0 Inherits: ft2 @@ -1601,6 +1636,9 @@ ALTER TABLE fd_pt1 ALTER COLUMN c8 SET STORAGE EXTERNAL; c6 | integer | | not null | | plain | | c7 | integer | | | | plain | | c8 | text | | | | external | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" + "fd_pt1_c6_not_null" NOT NULL "c6" Child tables: ft2, FOREIGN \d+ ft2 @@ -1615,6 +1653,9 @@ Child tables: ft2, FOREIGN c6 | integer | | not null | | | plain | | c7 | integer | | | | | plain | | c8 | text | | | | | external | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) + "fd_pt1_c6_not_null" NOT NULL "c6" (inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1634,6 +1675,8 @@ ALTER TABLE fd_pt1 DROP COLUMN c8; c1 | integer | | not null | | plain | 10000 | c2 | text | | | | extended | | c3 | date | | | | plain | | +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1643,6 +1686,8 @@ Child tables: ft2, FOREIGN c1 | integer | | not null | | | plain | 10000 | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1657,11 +1702,12 @@ SELECT relname, conname, contype, conislocal, coninhcount, connoinherit FROM pg_class AS pc JOIN pg_constraint AS pgc ON (conrelid = pc.oid) WHERE pc.relname = 'fd_pt1' ORDER BY 1,2; - relname | conname | contype | conislocal | coninhcount | connoinherit ----------+------------+---------+------------+-------------+-------------- - fd_pt1 | fd_pt1chk1 | c | t | 0 | t - fd_pt1 | fd_pt1chk2 | c | t | 0 | f -(2 rows) + relname | conname | contype | conislocal | coninhcount | connoinherit +---------+--------------------+---------+------------+-------------+-------------- + fd_pt1 | fd_pt1_c1_not_null | n | t | 0 | f + fd_pt1 | fd_pt1chk1 | c | t | 0 | t + fd_pt1 | fd_pt1chk2 | c | t | 0 | f +(3 rows) -- child does not inherit NO INHERIT constraints \d+ fd_pt1 @@ -1674,6 +1720,8 @@ SELECT relname, conname, contype, conislocal, coninhcount, connoinherit Check constraints: "fd_pt1chk1" CHECK (c1 > 0) NO INHERIT "fd_pt1chk2" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1685,6 +1733,8 @@ Child tables: ft2, FOREIGN c3 | date | | | | | plain | | Check constraints: "fd_pt1chk2" CHECK (c2 <> ''::text) +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1721,6 +1771,8 @@ ALTER FOREIGN TABLE ft2 INHERIT fd_pt1; Check constraints: "fd_pt1chk1" CHECK (c1 > 0) NO INHERIT "fd_pt1chk2" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1732,6 +1784,8 @@ Child tables: ft2, FOREIGN c3 | date | | | | | plain | | Check constraints: "fd_pt1chk2" CHECK (c2 <> ''::text) +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1751,6 +1805,8 @@ ALTER TABLE fd_pt1 ADD CONSTRAINT fd_pt1chk3 CHECK (c2 <> '') NOT VALID; c3 | date | | | | plain | | Check constraints: "fd_pt1chk3" CHECK (c2 <> ''::text) NOT VALID +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1763,6 +1819,8 @@ Child tables: ft2, FOREIGN Check constraints: "fd_pt1chk2" CHECK (c2 <> ''::text) "fd_pt1chk3" CHECK (c2 <> ''::text) NOT VALID +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1778,6 +1836,8 @@ ALTER TABLE fd_pt1 VALIDATE CONSTRAINT fd_pt1chk3; c3 | date | | | | plain | | Check constraints: "fd_pt1chk3" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "c1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1790,6 +1850,8 @@ Child tables: ft2, FOREIGN Check constraints: "fd_pt1chk2" CHECK (c2 <> ''::text) "fd_pt1chk3" CHECK (c2 <> ''::text) +Not-null constraints: + "ft2_c1_not_null" NOT NULL "c1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1809,6 +1871,8 @@ ALTER TABLE fd_pt1 RENAME CONSTRAINT fd_pt1chk3 TO f2_check; f3 | date | | | | plain | | Check constraints: "f2_check" CHECK (f2 <> ''::text) +Not-null constraints: + "fd_pt1_c1_not_null" NOT NULL "f1" Child tables: ft2, FOREIGN \d+ ft2 @@ -1821,6 +1885,8 @@ Child tables: ft2, FOREIGN Check constraints: "f2_check" CHECK (f2 <> ''::text) "fd_pt1chk2" CHECK (f2 <> ''::text) +Not-null constraints: + "ft2_c1_not_null" NOT NULL "f1" (local, inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') Inherits: fd_pt1 @@ -1867,6 +1933,8 @@ CREATE FOREIGN TABLE fd_pt2_1 PARTITION OF fd_pt2 FOR VALUES IN (1) c2 | text | | | | extended | | c3 | date | | | | plain | | Partition key: LIST (c1) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN \d+ fd_pt2_1 @@ -1878,6 +1946,8 @@ Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN c3 | date | | | | | plain | | Partition of: fd_pt2 FOR VALUES IN (1) Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1)) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" (inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1897,6 +1967,8 @@ CREATE FOREIGN TABLE fd_pt2_1 ( c2 | text | | | | | extended | | c3 | date | | | | | plain | | c4 | character(1) | | | | | extended | | +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1912,6 +1984,8 @@ DROP FOREIGN TABLE fd_pt2_1; c2 | text | | | | extended | | c3 | date | | | | plain | | Partition key: LIST (c1) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" Number of partitions: 0 CREATE FOREIGN TABLE fd_pt2_1 ( @@ -1926,6 +2000,8 @@ CREATE FOREIGN TABLE fd_pt2_1 ( c1 | integer | | not null | | | plain | | c2 | text | | | | | extended | | c3 | date | | | | | plain | | +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1939,6 +2015,8 @@ ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); c2 | text | | | | extended | | c3 | date | | | | plain | | Partition key: LIST (c1) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN \d+ fd_pt2_1 @@ -1950,6 +2028,8 @@ Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN c3 | date | | | | | plain | | Partition of: fd_pt2 FOR VALUES IN (1) Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1)) +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" (inherited) Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1967,6 +2047,8 @@ ALTER TABLE fd_pt2_1 ADD CONSTRAINT p21chk CHECK (c2 <> ''); c2 | text | | | | extended | | c3 | date | | | | plain | | Partition key: LIST (c1) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" Partitions: fd_pt2_1 FOR VALUES IN (1), FOREIGN \d+ fd_pt2_1 @@ -1980,6 +2062,9 @@ Partition of: fd_pt2 FOR VALUES IN (1) Partition constraint: ((c1 IS NOT NULL) AND (c1 = 1)) Check constraints: "p21chk" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" (inherited) + "fd_pt2_1_c3_not_null" NOT NULL "c3" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') @@ -1997,6 +2082,9 @@ ALTER TABLE fd_pt2 ALTER c2 SET NOT NULL; c2 | text | | not null | | extended | | c3 | date | | | | plain | | Partition key: LIST (c1) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" + "fd_pt2_c2_not_null" NOT NULL "c2" Number of partitions: 0 \d+ fd_pt2_1 @@ -2008,11 +2096,14 @@ Number of partitions: 0 c3 | date | | not null | | | plain | | Check constraints: "p21chk" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" + "fd_pt2_1_c3_not_null" NOT NULL "c3" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); -- ERROR -ERROR: column "c2" in child table must be marked NOT NULL +ERROR: column "c2" in child table "fd_pt2_1" must be marked NOT NULL ALTER FOREIGN TABLE fd_pt2_1 ALTER c2 SET NOT NULL; ALTER TABLE fd_pt2 ATTACH PARTITION fd_pt2_1 FOR VALUES IN (1); ALTER TABLE fd_pt2 DETACH PARTITION fd_pt2_1; @@ -2027,6 +2118,9 @@ ALTER TABLE fd_pt2 ADD CONSTRAINT fd_pt2chk1 CHECK (c1 > 0); Partition key: LIST (c1) Check constraints: "fd_pt2chk1" CHECK (c1 > 0) +Not-null constraints: + "fd_pt2_c1_not_null" NOT NULL "c1" + "fd_pt2_c2_not_null" NOT NULL "c2" Number of partitions: 0 \d+ fd_pt2_1 @@ -2038,6 +2132,10 @@ Number of partitions: 0 c3 | date | | not null | | | plain | | Check constraints: "p21chk" CHECK (c2 <> ''::text) +Not-null constraints: + "fd_pt2_1_c1_not_null" NOT NULL "c1" + "fd_pt2_1_c2_not_null" NOT NULL "c2" + "fd_pt2_1_c3_not_null" NOT NULL "c3" Server: s0 FDW options: (delimiter ',', quote '"', "be quoted" 'value') diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 46764bd9e3b06..6a8f395934520 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -1,21 +1,49 @@ -- -- FOREIGN KEY -- --- MATCH FULL +-- NOT ENFORCED -- -- First test, check and cascade -- CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); -CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int ); --- Insert test data into PKTABLE +CREATE TABLE FKTABLE ( ftest1 int CONSTRAINT fktable_ftest1_fkey REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE NOT ENFORCED, + ftest2 int ); +-- Inserting into the foreign key table will not result in an error, even if +-- there is no matching key in the referenced table. +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); +-- Check FKTABLE +SELECT * FROM FKTABLE; + ftest1 | ftest2 +--------+-------- + 1 | 2 + 2 | 3 +(2 rows) + +-- Reverting it back to ENFORCED will result in failure because constraint validation will be triggered, +-- as it was previously in a valid state. +ALTER TABLE FKTABLE ALTER CONSTRAINT fktable_ftest1_fkey ENFORCED; +ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_ftest1_fkey" +DETAIL: Key (ftest1)=(1) is not present in table "pktable". +-- Insert referenced data that satisfies the constraint, then attempt to +-- change it. INSERT INTO PKTABLE VALUES (1, 'Test1'); INSERT INTO PKTABLE VALUES (2, 'Test2'); +ALTER TABLE FKTABLE ALTER CONSTRAINT fktable_ftest1_fkey ENFORCED; +-- Any further inserts will fail due to the enforcement. +INSERT INTO FKTABLE VALUES (3, 4); +ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_ftest1_fkey" +DETAIL: Key (ftest1)=(3) is not present in table "pktable". +-- +-- MATCH FULL +-- +-- First test, check and cascade +-- +-- Insert test data into PKTABLE INSERT INTO PKTABLE VALUES (3, 'Test3'); INSERT INTO PKTABLE VALUES (4, 'Test4'); INSERT INTO PKTABLE VALUES (5, 'Test5'); -- Insert successful rows into FK TABLE -INSERT INTO FKTABLE VALUES (1, 2); -INSERT INTO FKTABLE VALUES (2, 3); INSERT INTO FKTABLE VALUES (3, 4); INSERT INTO FKTABLE VALUES (NULL, 1); -- Insert a failed row into FK TABLE @@ -351,6 +379,43 @@ INSERT INTO FKTABLE VALUES (1, NULL); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE MATCH FULL; ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_ftest1_ftest2_fkey" DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. +-- Modifying other attributes of a constraint should not affect its enforceability, and vice versa +ALTER TABLE FKTABLE ADD CONSTRAINT fk_con FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE NOT VALID NOT ENFORCED; +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con DEFERRABLE INITIALLY DEFERRED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + condeferrable | condeferred | conenforced | convalidated +---------------+-------------+-------------+-------------- + t | t | f | f +(1 row) + +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con NOT ENFORCED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + condeferrable | condeferred | conenforced | convalidated +---------------+-------------+-------------+-------------- + t | t | f | f +(1 row) + +-- Enforceability also changes the validate state, as data validation will be +-- performed during this transformation. +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con ENFORCED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + condeferrable | condeferred | conenforced | convalidated +---------------+-------------+-------------+-------------- + t | t | t | t +(1 row) + +-- Can change enforceability and deferrability together +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con NOT ENFORCED NOT DEFERRABLE; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + condeferrable | condeferred | conenforced | convalidated +---------------+-------------+-------------+-------------- + f | f | f | f +(1 row) + DROP TABLE FKTABLE; DROP TABLE PKTABLE; -- MATCH SIMPLE @@ -772,7 +837,8 @@ CREATE TABLE FKTABLE ( fk_id_del_set_null int, fk_id_del_set_default int DEFAULT 0, FOREIGN KEY (tid, fk_id_del_set_null) REFERENCES PKTABLE ON DELETE SET NULL (fk_id_del_set_null), - FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default) + -- this tests handling of duplicate entries in SET DEFAULT column list + FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default, fk_id_del_set_default) ); SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = 'fktable'::regclass::oid ORDER BY oid; pg_get_constraintdef @@ -822,12 +888,12 @@ INSERT INTO PKTABLE VALUES(42); -- This next should fail, because int=inet does not exist CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable); ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- This should also fail for the same reason, but here we -- give the column name CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1)); ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- This should succeed, even though they are different types, -- because int=int8 exists and is a member of the integer opfamily CREATE TABLE FKTABLE (ftest1 int8 REFERENCES pktable); @@ -846,7 +912,7 @@ DROP TABLE FKTABLE; -- of the integer opfamily) CREATE TABLE FKTABLE (ftest1 numeric REFERENCES pktable); ERROR: foreign key constraint "fktable_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: numeric and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: numeric and integer. DROP TABLE PKTABLE; -- On the other hand, this should work because int implicitly promotes to -- numeric, and we allow promotion on the FK side @@ -869,23 +935,23 @@ CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); -- This should fail, because we just chose really odd types CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: cidr and integer. -- Again, so should this... CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: cidr and integer. -- This fails because we mixed up the column ordering CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable); ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest2" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- As does this... CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2)); ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest2" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- And again.. CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1)); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest2" are of incompatible types: integer and inet. +DETAIL: Key columns "ftest1" of the referencing table and "ptest2" of the referenced table are of incompatible types: integer and inet. -- This works... CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1)); DROP TABLE FKTABLE; @@ -906,17 +972,17 @@ DROP TABLE PKTABLE; CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, ptest4) REFERENCES pktable(ptest2, ptest1)); ERROR: foreign key constraint "pktable_ptest3_ptest4_fkey" cannot be implemented -DETAIL: Key columns "ptest3" and "ptest2" are of incompatible types: integer and inet. +DETAIL: Key columns "ptest3" of the referencing table and "ptest2" of the referenced table are of incompatible types: integer and inet. -- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, ptest3) REFERENCES pktable(ptest1, ptest2)); ERROR: foreign key constraint "pktable_ptest4_ptest3_fkey" cannot be implemented -DETAIL: Key columns "ptest4" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ptest4" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- Not this one either... Same as the last one except we didn't defined the columns being referenced. CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, ptest3) REFERENCES pktable); ERROR: foreign key constraint "pktable_ptest4_ptest3_fkey" cannot be implemented -DETAIL: Key columns "ptest4" and "ptest1" are of incompatible types: inet and integer. +DETAIL: Key columns "ptest4" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet and integer. -- -- Now some cases with inheritance -- Basic 2 table case: 1 column of matching types. @@ -1009,20 +1075,20 @@ create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_ -- just generally bad types (with and without column references on the referenced table) create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "base1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "base1" of the referenced table are of incompatible types: cidr and integer. create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1)); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "base1" are of incompatible types: cidr and integer. +DETAIL: Key columns "ftest1" of the referencing table and "base1" of the referenced table are of incompatible types: cidr and integer. -- let's mix up which columns reference which create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable); ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest2" and "base1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest2" of the referencing table and "base1" of the referenced table are of incompatible types: inet and integer. create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1)); ERROR: foreign key constraint "fktable_ftest2_ftest1_fkey" cannot be implemented -DETAIL: Key columns "ftest2" and "base1" are of incompatible types: inet and integer. +DETAIL: Key columns "ftest2" of the referencing table and "base1" of the referenced table are of incompatible types: inet and integer. create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1)); ERROR: foreign key constraint "fktable_ftest1_ftest2_fkey" cannot be implemented -DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: integer and inet. +DETAIL: Key columns "ftest1" of the referencing table and "ptest1" of the referenced table are of incompatible types: integer and inet. drop table pktable; drop table pktable_base; -- 2 columns (1 table), mismatched types @@ -1030,19 +1096,19 @@ create table pktable_base(base1 int not null, base2 int); create table pktable(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references pktable(base1, ptest1)) inherits (pktable_base); ERROR: foreign key constraint "pktable_base2_ptest2_fkey" cannot be implemented -DETAIL: Key columns "ptest2" and "ptest1" are of incompatible types: inet[] and inet. +DETAIL: Key columns "ptest2" of the referencing table and "ptest1" of the referenced table are of incompatible types: inet[] and inet. create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references pktable(ptest1, base1)) inherits (pktable_base); ERROR: foreign key constraint "pktable_base2_ptest2_fkey" cannot be implemented -DETAIL: Key columns "base2" and "ptest1" are of incompatible types: integer and inet. +DETAIL: Key columns "base2" of the referencing table and "ptest1" of the referenced table are of incompatible types: integer and inet. create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references pktable(base1, ptest1)) inherits (pktable_base); ERROR: foreign key constraint "pktable_ptest2_base2_fkey" cannot be implemented -DETAIL: Key columns "ptest2" and "base1" are of incompatible types: inet and integer. +DETAIL: Key columns "ptest2" of the referencing table and "base1" of the referenced table are of incompatible types: inet and integer. create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references pktable(base1, ptest1)) inherits (pktable_base); ERROR: foreign key constraint "pktable_ptest2_base2_fkey" cannot be implemented -DETAIL: Key columns "ptest2" and "base1" are of incompatible types: inet and integer. +DETAIL: Key columns "ptest2" of the referencing table and "base1" of the referenced table are of incompatible types: inet and integer. drop table pktable; ERROR: table "pktable" does not exist drop table pktable_base; @@ -1154,22 +1220,22 @@ CREATE TEMP TABLE fktable ( ALTER TABLE fktable ADD CONSTRAINT fk_2_3 FOREIGN KEY (x2) REFERENCES pktable(id3); ERROR: foreign key constraint "fk_2_3" cannot be implemented -DETAIL: Key columns "x2" and "id3" are of incompatible types: character varying and real. +DETAIL: Key columns "x2" of the referencing table and "id3" of the referenced table are of incompatible types: character varying and real. -- nor to int4 ALTER TABLE fktable ADD CONSTRAINT fk_2_1 FOREIGN KEY (x2) REFERENCES pktable(id1); ERROR: foreign key constraint "fk_2_1" cannot be implemented -DETAIL: Key columns "x2" and "id1" are of incompatible types: character varying and integer. +DETAIL: Key columns "x2" of the referencing table and "id1" of the referenced table are of incompatible types: character varying and integer. -- real does not promote to int4 ALTER TABLE fktable ADD CONSTRAINT fk_3_1 FOREIGN KEY (x3) REFERENCES pktable(id1); ERROR: foreign key constraint "fk_3_1" cannot be implemented -DETAIL: Key columns "x3" and "id1" are of incompatible types: real and integer. +DETAIL: Key columns "x3" of the referencing table and "id1" of the referenced table are of incompatible types: real and integer. -- int4 does not promote to text ALTER TABLE fktable ADD CONSTRAINT fk_1_2 FOREIGN KEY (x1) REFERENCES pktable(id2); ERROR: foreign key constraint "fk_1_2" cannot be implemented -DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying. +DETAIL: Key columns "x1" of the referencing table and "id2" of the referenced table are of incompatible types: integer and character varying. -- should succeed -- int4 promotes to real ALTER TABLE fktable ADD CONSTRAINT fk_1_3 @@ -1192,11 +1258,11 @@ FOREIGN KEY (x2,x5,x3) REFERENCES pktable(id2,id1,id3); ALTER TABLE fktable ADD CONSTRAINT fk_123_231 FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1); ERROR: foreign key constraint "fk_123_231" cannot be implemented -DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying. +DETAIL: Key columns "x1" of the referencing table and "id2" of the referenced table are of incompatible types: integer and character varying. ALTER TABLE fktable ADD CONSTRAINT fk_241_132 FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2); ERROR: foreign key constraint "fk_241_132" cannot be implemented -DETAIL: Key columns "x2" and "id1" are of incompatible types: character varying and integer. +DETAIL: Key columns "x2" of the referencing table and "id1" of the referenced table are of incompatible types: character varying and integer. DROP TABLE pktable, fktable; -- test a tricky case: we can elide firing the FK check trigger during -- an UPDATE if the UPDATE did not change the foreign key @@ -1276,13 +1342,34 @@ INSERT INTO fktable VALUES (0, 20); ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey" DETAIL: Key (fk)=(20) is not present in table "pktable". COMMIT; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT ENFORCED; +BEGIN; +-- doesn't match FK, but no error. +UPDATE pktable SET id = 10 WHERE id = 5; +-- doesn't match PK, but no error. +INSERT INTO fktable VALUES (0, 20); +ROLLBACK; -- try additional syntax ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE; --- illegal option +-- illegal options ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY DEFERRED; ERROR: constraint declared INITIALLY DEFERRED must be DEFERRABLE LINE 1: ...e ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY ... ^ +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT; +ERROR: constraint "fktable_fk_fkey" of relation "fktable" is not a not-null constraint +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; +ERROR: FOREIGN KEY constraints cannot be marked NOT VALID +LINE 1: ...ER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; + ^ +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey ENFORCED NOT ENFORCED; +ERROR: conflicting constraint properties +LINE 1: ...fktable ALTER CONSTRAINT fktable_fk_fkey ENFORCED NOT ENFORC... + ^ +CREATE TEMP TABLE fktable2 (fk int references pktable ENFORCED NOT ENFORCED); +ERROR: multiple ENFORCED/NOT ENFORCED clauses not allowed +LINE 1: ...ABLE fktable2 (fk int references pktable ENFORCED NOT ENFORC... + ^ -- test order of firing of FK triggers when several RI-induced changes need to -- be made to the same row. This was broken by subtransaction-related -- changes in 8.0. @@ -1439,11 +1526,11 @@ insert into pp values(11); update pp set f1=f1+1; insert into cc values(13); update pp set f1=f1+1; -- fail -ERROR: update or delete on table "pp" violates foreign key constraint "cc_f1_fkey" on table "cc" -DETAIL: Key (f1)=(13) is still referenced from table "cc". +ERROR: update or delete on table "pp" violates RESTRICT setting of foreign key constraint "cc_f1_fkey" on table "cc" +DETAIL: Key (f1)=(13) is referenced from table "cc". delete from pp where f1 = 13; -- fail -ERROR: update or delete on table "pp" violates foreign key constraint "cc_f1_fkey" on table "cc" -DETAIL: Key (f1)=(13) is still referenced from table "cc". +ERROR: update or delete on table "pp" violates RESTRICT setting of foreign key constraint "cc_f1_fkey" on table "cc" +DETAIL: Key (f1)=(13) is referenced from table "cc". drop table pp, cc; -- -- Test interaction of foreign-key optimization with rules (bug #14219) @@ -1580,10 +1667,14 @@ ALTER TABLE fk_partitioned_fk DROP COLUMN fdrop1; CREATE TABLE fk_partitioned_fk_1 (fdrop1 int, fdrop2 int, a int, fdrop3 int, b int); ALTER TABLE fk_partitioned_fk_1 DROP COLUMN fdrop1, DROP COLUMN fdrop2, DROP COLUMN fdrop3; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_1 FOR VALUES FROM (0,0) TO (1000,1000); -ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk ADD CONSTRAINT fk_partitioned_fk_a_b_fkey FOREIGN KEY (a, b) + REFERENCES fk_notpartitioned_pk NOT ENFORCED; CREATE TABLE fk_partitioned_fk_2 (b int, fdrop1 int, fdrop2 int, a int); ALTER TABLE fk_partitioned_fk_2 DROP COLUMN fdrop1, DROP COLUMN fdrop2; +ALTER TABLE fk_partitioned_fk_2 ADD CONSTRAINT fk_partitioned_fk_a_b_fkey FOREIGN KEY (a, b) + REFERENCES fk_notpartitioned_pk NOT ENFORCED; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey ENFORCED; CREATE TABLE fk_partitioned_fk_3 (fdrop1 int, fdrop2 int, fdrop3 int, fdrop4 int, b int, a int) PARTITION BY HASH (a); ALTER TABLE fk_partitioned_fk_3 DROP COLUMN fdrop1, DROP COLUMN fdrop2, @@ -1597,12 +1688,6 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_3 ALTER TABLE ONLY fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; ERROR: cannot use ONLY for foreign key on partitioned table "fk_partitioned_fk" referencing relation "fk_notpartitioned_pk" --- Adding a NOT VALID foreign key on a partitioned table referencing --- a non-partitioned table fails. -ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) - REFERENCES fk_notpartitioned_pk NOT VALID; -ERROR: cannot add NOT VALID foreign key on partitioned table "fk_partitioned_fk" referencing relation "fk_notpartitioned_pk" -DETAIL: This feature is not yet supported on partitioned tables. -- these inserts, targeting both the partition directly as well as the -- partitioned table, should all fail INSERT INTO fk_partitioned_fk (a,b) VALUES (500, 501); @@ -1665,6 +1750,67 @@ Indexes: Referenced by: TABLE "fk_partitioned_fk" CONSTRAINT "fk_partitioned_fk_a_b_fkey" FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) +-- Check the exsting FK trigger +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + conname | tgrel | tgname | tgtype +----------------------------+-----------------------+--------------------------+-------- + fk_partitioned_fk_a_b_fkey | fk_notpartitioned_pk | RI_ConstraintTrigger_a_N | 9 + fk_partitioned_fk_a_b_fkey | fk_notpartitioned_pk | RI_ConstraintTrigger_a_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_1 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_1 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_2 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_2 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_0 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_0 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_1 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_1 | RI_ConstraintTrigger_c_N | 17 +(14 rows) + +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey NOT ENFORCED; +-- No triggers +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + conname | tgrel | tgname | tgtype +---------+-------+--------+-------- +(0 rows) + +-- Changing it back to ENFORCED will recreate the necessary triggers. +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey ENFORCED; +-- Should be exactly the same number of triggers found as before +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + conname | tgrel | tgname | tgtype +----------------------------+-----------------------+--------------------------+-------- + fk_partitioned_fk_a_b_fkey | fk_notpartitioned_pk | RI_ConstraintTrigger_a_N | 9 + fk_partitioned_fk_a_b_fkey | fk_notpartitioned_pk | RI_ConstraintTrigger_a_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_1 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_1 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_2 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_2 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_0 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_0 | RI_ConstraintTrigger_c_N | 17 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_1 | RI_ConstraintTrigger_c_N | 5 + fk_partitioned_fk_a_b_fkey | fk_partitioned_fk_3_1 | RI_ConstraintTrigger_c_N | 17 +(14 rows) + ALTER TABLE fk_partitioned_fk DROP CONSTRAINT fk_partitioned_fk_a_b_fkey; -- done. DROP TABLE fk_notpartitioned_pk, fk_partitioned_fk; @@ -1680,6 +1826,147 @@ DELETE FROM fk_notpartitioned_pk WHERE a = 1; ERROR: update or delete on table "fk_notpartitioned_pk" violates foreign key constraint "fk_partitioned_fk_a_fkey" on table "fk_partitioned_fk" DETAIL: Key (a)=(1) is still referenced from table "fk_partitioned_fk". DROP TABLE fk_notpartitioned_pk, fk_partitioned_fk; +-- NOT VALID foreign keys on partitioned table +CREATE TABLE fk_notpartitioned_pk (a int, b int, PRIMARY KEY (a, b)); +CREATE TABLE fk_partitioned_fk (b int, a int) PARTITION BY RANGE (a, b); +ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; +-- Attaching a child table with the same valid foreign key constraint. +CREATE TABLE fk_partitioned_fk_1 (a int, b int); +ALTER TABLE fk_partitioned_fk_1 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_1 FOR VALUES FROM (0,0) TO (1000,1000); +-- Child constraint will remain valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + conname | convalidated | conrelid +------------------------------+--------------+--------------------- + fk_partitioned_fk_a_b_fkey | f | fk_partitioned_fk + fk_partitioned_fk_1_a_b_fkey | t | fk_partitioned_fk_1 +(2 rows) + +-- Validate the constraint +ALTER TABLE fk_partitioned_fk VALIDATE CONSTRAINT fk_partitioned_fk_a_b_fkey; +-- All constraints are now valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + conname | convalidated | conrelid +------------------------------+--------------+--------------------- + fk_partitioned_fk_a_b_fkey | t | fk_partitioned_fk + fk_partitioned_fk_1_a_b_fkey | t | fk_partitioned_fk_1 +(2 rows) + +-- Attaching a child with a NOT VALID constraint. +CREATE TABLE fk_partitioned_fk_2 (a int, b int); +INSERT INTO fk_partitioned_fk_2 VALUES(1000, 1000); -- doesn't exist in referenced table +ALTER TABLE fk_partitioned_fk_2 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; +-- It will fail because the attach operation implicitly validates the data. +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); +ERROR: insert or update on table "fk_partitioned_fk_2" violates foreign key constraint "fk_partitioned_fk_2_a_b_fkey" +DETAIL: Key (a, b)=(1000, 1000) is not present in table "fk_notpartitioned_pk". +-- Remove the invalid data and try again. +TRUNCATE fk_partitioned_fk_2; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); +-- The child constraint will also be valid. +SELECT conname, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_fk_2'::regclass ORDER BY oid::regclass::text; + conname | convalidated +------------------------------+-------------- + fk_partitioned_fk_2_a_b_fkey | t +(1 row) + +-- Test case where the child constraint is invalid, the grandchild constraint +-- is valid, and the validation for the grandchild should be skipped when a +-- valid constraint is applied to the top parent. +CREATE TABLE fk_partitioned_fk_3 (a int, b int) PARTITION BY RANGE (a, b); +ALTER TABLE fk_partitioned_fk_3 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; +CREATE TABLE fk_partitioned_fk_3_1 (a int, b int); +ALTER TABLE fk_partitioned_fk_3_1 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk_3 ATTACH PARTITION fk_partitioned_fk_3_1 FOR VALUES FROM (2000,2000) TO (3000,3000); +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_3 FOR VALUES FROM (2000,2000) TO (3000,3000); +-- All constraints are now valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + conname | convalidated | conrelid +--------------------------------+--------------+----------------------- + fk_partitioned_fk_a_b_fkey | t | fk_partitioned_fk + fk_partitioned_fk_1_a_b_fkey | t | fk_partitioned_fk_1 + fk_partitioned_fk_2_a_b_fkey | t | fk_partitioned_fk_2 + fk_partitioned_fk_3_a_b_fkey | t | fk_partitioned_fk_3 + fk_partitioned_fk_3_1_a_b_fkey | t | fk_partitioned_fk_3_1 +(5 rows) + +DROP TABLE fk_partitioned_fk, fk_notpartitioned_pk; +-- NOT VALID and NOT ENFORCED foreign key on a non-partitioned table +-- referencing a partitioned table +CREATE TABLE fk_partitioned_pk (a int, b int, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b); +CREATE TABLE fk_partitioned_pk_1 PARTITION OF fk_partitioned_pk FOR VALUES FROM (0,0) TO (1000,1000); +CREATE TABLE fk_partitioned_pk_2 PARTITION OF fk_partitioned_pk FOR VALUES FROM (1000,1000) TO (2000,2000); +CREATE TABLE fk_notpartitioned_fk (b int, a int); +INSERT INTO fk_partitioned_pk VALUES(100,100), (1000,1000); +INSERT INTO fk_notpartitioned_fk VALUES(100,100), (1000,1000); +ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey + FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID; +ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 + FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT ENFORCED; +-- All constraints will be invalid, and _fkey2 constraints will not be enforced. +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text; + conname | conenforced | convalidated +----------------------------------+-------------+-------------- + fk_notpartitioned_fk_a_b_fkey | t | f + fk_notpartitioned_fk_a_b_fkey_1 | t | f + fk_notpartitioned_fk_a_b_fkey_2 | t | f + fk_notpartitioned_fk_a_b_fkey2 | f | f + fk_notpartitioned_fk_a_b_fkey2_1 | f | f + fk_notpartitioned_fk_a_b_fkey2_2 | f | f +(6 rows) + +ALTER TABLE fk_notpartitioned_fk VALIDATE CONSTRAINT fk_notpartitioned_fk_a_b_fkey; +ALTER TABLE fk_notpartitioned_fk ALTER CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 ENFORCED; +-- All constraints are now valid and enforced. +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text; + conname | conenforced | convalidated +----------------------------------+-------------+-------------- + fk_notpartitioned_fk_a_b_fkey | t | t + fk_notpartitioned_fk_a_b_fkey_1 | t | t + fk_notpartitioned_fk_a_b_fkey_2 | t | t + fk_notpartitioned_fk_a_b_fkey2 | t | t + fk_notpartitioned_fk_a_b_fkey2_1 | t | t + fk_notpartitioned_fk_a_b_fkey2_2 | t | t +(6 rows) + +-- test a self-referential FK +ALTER TABLE fk_partitioned_pk ADD CONSTRAINT selffk FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID; +CREATE TABLE fk_partitioned_pk_3 PARTITION OF fk_partitioned_pk FOR VALUES FROM (2000,2000) TO (3000,3000) + PARTITION BY RANGE (a); +CREATE TABLE fk_partitioned_pk_3_1 PARTITION OF fk_partitioned_pk_3 FOR VALUES FROM (2000) TO (2100); +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_pk'::regclass AND contype = 'f' +ORDER BY oid::regclass::text; + conname | conenforced | convalidated +------------+-------------+-------------- + selffk | t | f + selffk_1 | t | f + selffk_2 | t | f + selffk_3 | t | f + selffk_3_1 | t | f +(5 rows) + +ALTER TABLE fk_partitioned_pk_2 VALIDATE CONSTRAINT selffk; +ALTER TABLE fk_partitioned_pk VALIDATE CONSTRAINT selffk; +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_pk'::regclass AND contype = 'f' +ORDER BY oid::regclass::text; + conname | conenforced | convalidated +------------+-------------+-------------- + selffk | t | t + selffk_1 | t | t + selffk_2 | t | t + selffk_3 | t | t + selffk_3_1 | t | t +(5 rows) + +DROP TABLE fk_notpartitioned_fk, fk_partitioned_pk; -- Test some other exotic foreign key features: MATCH SIMPLE, ON UPDATE/DELETE -- actions CREATE TABLE fk_notpartitioned_pk (a int, b int, primary key (a, b)); @@ -1868,6 +2155,43 @@ Partition of: fk_partitioned_fk FOR VALUES IN (1500, 1502) Foreign-key constraints: TABLE "fk_partitioned_fk" CONSTRAINT "fk_partitioned_fk_a_b_fkey" FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE +DROP TABLE fk_partitioned_fk_2; +CREATE TABLE fk_partitioned_fk_2 (b int, a int, + CONSTRAINT fk_part_con FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk ON UPDATE CASCADE ON DELETE CASCADE NOT ENFORCED); +-- fail -- cannot merge constraints with different enforceability. +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +ERROR: constraint "fk_partitioned_fk_a_b_fkey" enforceability conflicts with constraint "fk_part_con" on relation "fk_partitioned_fk_2" +-- If the constraint is modified to match the enforceability of the parent, it will work. +BEGIN; +-- change child constraint +ALTER TABLE fk_partitioned_fk_2 ALTER CONSTRAINT fk_part_con ENFORCED; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +\d fk_partitioned_fk_2 + Table "public.fk_partitioned_fk_2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + b | integer | | | + a | integer | | | +Partition of: fk_partitioned_fk FOR VALUES IN (1500, 1502) +Foreign-key constraints: + TABLE "fk_partitioned_fk" CONSTRAINT "fk_partitioned_fk_a_b_fkey" FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE + +ROLLBACK; +BEGIN; +-- or change parent constraint +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey NOT ENFORCED; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +\d fk_partitioned_fk_2 + Table "public.fk_partitioned_fk_2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + b | integer | | | + a | integer | | | +Partition of: fk_partitioned_fk FOR VALUES IN (1500, 1502) +Foreign-key constraints: + TABLE "fk_partitioned_fk" CONSTRAINT "fk_partitioned_fk_a_b_fkey" FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE NOT ENFORCED + +ROLLBACK; DROP TABLE fk_partitioned_fk_2; CREATE TABLE fk_partitioned_fk_4 (a int, b int, FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE) PARTITION BY RANGE (b, a); CREATE TABLE fk_partitioned_fk_4_1 PARTITION OF fk_partitioned_fk_4 FOR VALUES FROM (1,1) TO (100,100); @@ -1967,6 +2291,33 @@ INSERT INTO fk_notpartitioned_pk VALUES (1600, 601), (1600, 1601); ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1600); -- leave these tables around intentionally +-- Verify that attaching a table that's referenced by an existing FK +-- in the parent throws an error +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +ERROR: cannot attach table "fk_partitioned_pk_6" as a partition because it is referenced by foreign key "fk_partitioned_fk_6_a_fkey" +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; +-- Verify that attaching to a parent with two identical constraints work +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY); +CREATE TABLE fk_partitioned_fk_6 (a int, + FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6, + FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6 +) PARTITION BY LIST (a); +CREATE TABLE fk_partitioned_fk_6_1 PARTITION OF fk_partitioned_fk_6 FOR VALUES IN (1); +ALTER TABLE fk_partitioned_fk_6 DETACH PARTITION fk_partitioned_fk_6_1; +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_fk_6_1 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; +-- This case is similar to above, but the referenced relation is one level +-- lower in the hierarchy. This one fails in a different way as the above, +-- because we don't bother to protect against this case explicitly. If the +-- current error stops happening, we'll need to add a better protection. +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY) PARTITION BY list (a); +CREATE TABLE fk_partitioned_pk_61 PARTITION OF fk_partitioned_pk_6 FOR VALUES IN (1); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_61) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +ERROR: cannot ALTER TABLE "fk_partitioned_pk_61" because it is being used by active queries in this session +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; -- test the case when the referenced table is owned by a different user create role regress_other_partitioned_fk_owner; grant references on fk_notpartitioned_pk to regress_other_partitioned_fk_owner; @@ -2020,58 +2371,90 @@ CREATE TABLE part33_self_fk ( id_abc bigint ); ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); -SELECT cr.relname, co.conname, co.contype, co.convalidated, +-- verify that this constraint works +INSERT INTO parted_self_fk VALUES (1, NULL), (2, NULL), (3, NULL); +INSERT INTO parted_self_fk VALUES (10, 1), (11, 2), (12, 3) RETURNING tableoid::regclass; + tableoid +--------------- + part2_self_fk + part2_self_fk + part2_self_fk +(3 rows) + +INSERT INTO parted_self_fk VALUES (4, 5); -- error: referenced doesn't exist +ERROR: insert or update on table "part1_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey" +DETAIL: Key (id_abc)=(5) is not present in table "parted_self_fk". +DELETE FROM parted_self_fk WHERE id = 1 RETURNING *; -- error: reference remains +ERROR: update or delete on table "part1_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey_1" on table "parted_self_fk" +DETAIL: Key (id)=(1) is still referenced from table "parted_self_fk". +SELECT cr.relname, co.conname, co.convalidated, p.conname AS conparent, p.convalidated, cf.relname AS foreignrel FROM pg_constraint co JOIN pg_class cr ON cr.oid = co.conrelid LEFT JOIN pg_class cf ON cf.oid = co.confrelid LEFT JOIN pg_constraint p ON p.oid = co.conparentid -WHERE cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) -ORDER BY co.contype, cr.relname, co.conname, p.conname; - relname | conname | contype | convalidated | conparent | convalidated | foreignrel -----------------+----------------------------+---------+--------------+----------------------------+--------------+---------------- - part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk - part1_self_fk | part1_self_fk_pkey | p | t | parted_self_fk_pkey | t | - part2_self_fk | part2_self_fk_pkey | p | t | parted_self_fk_pkey | t | - part32_self_fk | part32_self_fk_pkey | p | t | part3_self_fk_pkey | t | - part33_self_fk | part33_self_fk_pkey | p | t | part3_self_fk_pkey | t | - part3_self_fk | part3_self_fk_pkey | p | t | parted_self_fk_pkey | t | - parted_self_fk | parted_self_fk_pkey | p | t | | | -(12 rows) +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; + relname | conname | convalidated | conparent | convalidated | foreignrel +----------------+--------------------------------+--------------+------------------------------+--------------+---------------- + part1_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part2_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part32_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part33_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part3_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey | t | | | parted_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_1 | t | parted_self_fk_id_abc_fkey | t | part1_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_2 | t | parted_self_fk_id_abc_fkey | t | part2_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_3 | t | parted_self_fk_id_abc_fkey | t | part3_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_3_1 | t | parted_self_fk_id_abc_fkey_3 | t | part33_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_4 | t | parted_self_fk_id_abc_fkey_3 | t | part32_self_fk +(11 rows) -- detach and re-attach multiple times just to ensure everything is kosher ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; +INSERT INTO part2_self_fk VALUES (16, 9); -- error: referenced doesn't exist +ERROR: insert or update on table "part2_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey" +DETAIL: Key (id_abc)=(9) is not present in table "parted_self_fk". +DELETE FROM parted_self_fk WHERE id = 2 RETURNING *; -- error: reference remains +ERROR: update or delete on table "part1_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey_5" on table "part2_self_fk" +DETAIL: Key (id)=(2) is still referenced from table "part2_self_fk". ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); +INSERT INTO parted_self_fk VALUES (16, 9); -- error: referenced doesn't exist +ERROR: insert or update on table "part2_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey" +DETAIL: Key (id_abc)=(9) is not present in table "parted_self_fk". +DELETE FROM parted_self_fk WHERE id = 3 RETURNING *; -- error: reference remains +ERROR: update or delete on table "part1_self_fk" violates foreign key constraint "parted_self_fk_id_abc_fkey_1" on table "parted_self_fk" +DETAIL: Key (id)=(3) is still referenced from table "parted_self_fk". ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); -SELECT cr.relname, co.conname, co.contype, co.convalidated, +ALTER TABLE parted_self_fk DETACH PARTITION part3_self_fk; +ALTER TABLE parted_self_fk ATTACH PARTITION part3_self_fk FOR VALUES FROM (30) TO (40); +ALTER TABLE part3_self_fk DETACH PARTITION part33_self_fk; +ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); +SELECT cr.relname, co.conname, co.convalidated, p.conname AS conparent, p.convalidated, cf.relname AS foreignrel FROM pg_constraint co JOIN pg_class cr ON cr.oid = co.conrelid LEFT JOIN pg_class cf ON cf.oid = co.confrelid LEFT JOIN pg_constraint p ON p.oid = co.conparentid -WHERE cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) -ORDER BY co.contype, cr.relname, co.conname, p.conname; - relname | conname | contype | convalidated | conparent | convalidated | foreignrel -----------------+----------------------------+---------+--------------+----------------------------+--------------+---------------- - part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk - part1_self_fk | part1_self_fk_pkey | p | t | parted_self_fk_pkey | t | - part2_self_fk | part2_self_fk_pkey | p | t | parted_self_fk_pkey | t | - part32_self_fk | part32_self_fk_pkey | p | t | part3_self_fk_pkey | t | - part33_self_fk | part33_self_fk_pkey | p | t | part3_self_fk_pkey | t | - part3_self_fk | part3_self_fk_pkey | p | t | parted_self_fk_pkey | t | - parted_self_fk | parted_self_fk_pkey | p | t | | | -(12 rows) +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; + relname | conname | convalidated | conparent | convalidated | foreignrel +----------------+--------------------------------+--------------+------------------------------+--------------+---------------- + part1_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part2_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part32_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part33_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + part3_self_fk | parted_self_fk_id_abc_fkey | t | parted_self_fk_id_abc_fkey | t | parted_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey | t | | | parted_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_1 | t | parted_self_fk_id_abc_fkey | t | part1_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_2 | t | parted_self_fk_id_abc_fkey | t | part2_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_3 | t | parted_self_fk_id_abc_fkey | t | part3_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_3_1 | t | parted_self_fk_id_abc_fkey_3 | t | part33_self_fk + parted_self_fk | parted_self_fk_id_abc_fkey_4 | t | parted_self_fk_id_abc_fkey_3 | t | part32_self_fk +(11 rows) -- Leave this table around, for pg_upgrade/pg_dump tests -- Test creating a constraint at the parent that already exists in partitions. @@ -2273,40 +2656,40 @@ INSERT into pk VALUES (1), (1000), (2000), (3000), (4000), (4500); INSERT into fk VALUES (1), (1000), (2000), (3000), (4000), (4500); -- should fail: referencing value present DELETE FROM pk WHERE a = 1; -ERROR: update or delete on table "pk1" violates foreign key constraint "fk_a_fkey1" on table "fk" +ERROR: update or delete on table "pk1" violates foreign key constraint "fk_a_fkey_1" on table "fk" DETAIL: Key (a)=(1) is still referenced from table "fk". DELETE FROM pk WHERE a = 1000; -ERROR: update or delete on table "pk2" violates foreign key constraint "fk_a_fkey2" on table "fk" +ERROR: update or delete on table "pk2" violates foreign key constraint "fk_a_fkey_2" on table "fk" DETAIL: Key (a)=(1000) is still referenced from table "fk". DELETE FROM pk WHERE a = 2000; -ERROR: update or delete on table "pk3" violates foreign key constraint "fk_a_fkey3" on table "fk" +ERROR: update or delete on table "pk3" violates foreign key constraint "fk_a_fkey_3" on table "fk" DETAIL: Key (a)=(2000) is still referenced from table "fk". DELETE FROM pk WHERE a = 3000; -ERROR: update or delete on table "pk4" violates foreign key constraint "fk_a_fkey4" on table "fk" +ERROR: update or delete on table "pk4" violates foreign key constraint "fk_a_fkey_4" on table "fk" DETAIL: Key (a)=(3000) is still referenced from table "fk". DELETE FROM pk WHERE a = 4000; -ERROR: update or delete on table "pk51" violates foreign key constraint "fk_a_fkey6" on table "fk" +ERROR: update or delete on table "pk51" violates foreign key constraint "fk_a_fkey_6" on table "fk" DETAIL: Key (a)=(4000) is still referenced from table "fk". DELETE FROM pk WHERE a = 4500; -ERROR: update or delete on table "pk52" violates foreign key constraint "fk_a_fkey7" on table "fk" +ERROR: update or delete on table "pk52" violates foreign key constraint "fk_a_fkey_7" on table "fk" DETAIL: Key (a)=(4500) is still referenced from table "fk". UPDATE pk SET a = 2 WHERE a = 1; -ERROR: update or delete on table "pk1" violates foreign key constraint "fk_a_fkey1" on table "fk" +ERROR: update or delete on table "pk1" violates foreign key constraint "fk_a_fkey_1" on table "fk" DETAIL: Key (a)=(1) is still referenced from table "fk". UPDATE pk SET a = 1002 WHERE a = 1000; -ERROR: update or delete on table "pk2" violates foreign key constraint "fk_a_fkey2" on table "fk" +ERROR: update or delete on table "pk2" violates foreign key constraint "fk_a_fkey_2" on table "fk" DETAIL: Key (a)=(1000) is still referenced from table "fk". UPDATE pk SET a = 2002 WHERE a = 2000; -ERROR: update or delete on table "pk3" violates foreign key constraint "fk_a_fkey3" on table "fk" +ERROR: update or delete on table "pk3" violates foreign key constraint "fk_a_fkey_3" on table "fk" DETAIL: Key (a)=(2000) is still referenced from table "fk". UPDATE pk SET a = 3002 WHERE a = 3000; -ERROR: update or delete on table "pk4" violates foreign key constraint "fk_a_fkey4" on table "fk" +ERROR: update or delete on table "pk4" violates foreign key constraint "fk_a_fkey_4" on table "fk" DETAIL: Key (a)=(3000) is still referenced from table "fk". UPDATE pk SET a = 4002 WHERE a = 4000; -ERROR: update or delete on table "pk51" violates foreign key constraint "fk_a_fkey6" on table "fk" +ERROR: update or delete on table "pk51" violates foreign key constraint "fk_a_fkey_6" on table "fk" DETAIL: Key (a)=(4000) is still referenced from table "fk". UPDATE pk SET a = 4502 WHERE a = 4500; -ERROR: update or delete on table "pk52" violates foreign key constraint "fk_a_fkey7" on table "fk" +ERROR: update or delete on table "pk52" violates foreign key constraint "fk_a_fkey_7" on table "fk" DETAIL: Key (a)=(4500) is still referenced from table "fk". -- now they should work DELETE FROM fk; @@ -2322,6 +2705,13 @@ UPDATE pk SET a = 4002 WHERE a = 4000; DELETE FROM pk WHERE a = 4002; UPDATE pk SET a = 4502 WHERE a = 4500; DELETE FROM pk WHERE a = 4502; +-- Also, detaching a partition that has the FK itself should work +-- https://postgr.es/m/CAAJ_b97GuPh6wQPbxQS-Zpy16Oh+0aMv-w64QcGrLhCOZZ6p+g@mail.gmail.com +CREATE TABLE ffk (a int, b int REFERENCES pk) PARTITION BY list (a); +CREATE TABLE ffk1 PARTITION OF ffk FOR VALUES IN (1); +ALTER TABLE ffk1 ADD FOREIGN KEY (a) REFERENCES pk; +ALTER TABLE ffk DETACH PARTITION ffk1; +DROP TABLE ffk, ffk1; CREATE SCHEMA fkpart4; SET search_path TO fkpart4; -- dropping/detaching PARTITIONs is prevented if that would break @@ -2338,19 +2728,19 @@ CREATE TABLE dropfk (a int REFERENCES droppk); INSERT into dropfk VALUES (1), (1000), (1500), (2000); -- these should all fail ALTER TABLE droppk DETACH PARTITION droppk_d; -ERROR: removing partition "droppk_d" violates foreign key constraint "dropfk_a_fkey5" +ERROR: removing partition "droppk_d" violates foreign key constraint "dropfk_a_fkey_5" DETAIL: Key (a)=(2000) is still referenced from table "dropfk". ALTER TABLE droppk2 DETACH PARTITION droppk2_d; -ERROR: removing partition "droppk2_d" violates foreign key constraint "dropfk_a_fkey4" +ERROR: removing partition "droppk2_d" violates foreign key constraint "dropfk_a_fkey_4" DETAIL: Key (a)=(1500) is still referenced from table "dropfk". ALTER TABLE droppk DETACH PARTITION droppk1; -ERROR: removing partition "droppk1" violates foreign key constraint "dropfk_a_fkey1" +ERROR: removing partition "droppk1" violates foreign key constraint "dropfk_a_fkey_1" DETAIL: Key (a)=(1) is still referenced from table "dropfk". ALTER TABLE droppk DETACH PARTITION droppk2; -ERROR: removing partition "droppk2" violates foreign key constraint "dropfk_a_fkey2" +ERROR: removing partition "droppk2" violates foreign key constraint "dropfk_a_fkey_2" DETAIL: Key (a)=(1000) is still referenced from table "dropfk". ALTER TABLE droppk2 DETACH PARTITION droppk21; -ERROR: removing partition "droppk21" violates foreign key constraint "dropfk_a_fkey3" +ERROR: removing partition "droppk21" violates foreign key constraint "dropfk_a_fkey_3" DETAIL: Key (a)=(1000) is still referenced from table "dropfk". -- dropping partitions is disallowed DROP TABLE droppk_d; @@ -2419,15 +2809,15 @@ SELECT pg_describe_object('pg_constraint'::regclass, oid, 0), confrelid::regclas FROM pg_catalog.pg_constraint WHERE conrelid IN (SELECT relid FROM pg_partition_tree('fk')) ORDER BY conrelid::regclass::text, conname; - pg_describe_object | confrelid | case -------------------------------------+-----------+----------------------------------- + pg_describe_object | confrelid | case +------------------------------------+-----------+------------------------------------ constraint fk_a_fkey on table fk | pk | TOP - constraint fk_a_fkey1 on table fk | pk1 | constraint fk_a_fkey on table fk - constraint fk_a_fkey2 on table fk | pk11 | constraint fk_a_fkey1 on table fk - constraint fk_a_fkey3 on table fk | pk2 | constraint fk_a_fkey on table fk - constraint fk_a_fkey4 on table fk | pk3 | constraint fk_a_fkey on table fk - constraint fk_a_fkey5 on table fk | pk31 | constraint fk_a_fkey4 on table fk - constraint fk_a_fkey6 on table fk | pk32 | constraint fk_a_fkey4 on table fk + constraint fk_a_fkey_1 on table fk | pk1 | constraint fk_a_fkey on table fk + constraint fk_a_fkey_2 on table fk | pk11 | constraint fk_a_fkey_1 on table fk + constraint fk_a_fkey_3 on table fk | pk2 | constraint fk_a_fkey on table fk + constraint fk_a_fkey_4 on table fk | pk3 | constraint fk_a_fkey on table fk + constraint fk_a_fkey_5 on table fk | pk31 | constraint fk_a_fkey_4 on table fk + constraint fk_a_fkey_6 on table fk | pk32 | constraint fk_a_fkey_4 on table fk constraint fk_a_fkey on table fk1 | pk | constraint fk_a_fkey on table fk constraint fk_a_fkey on table fk11 | pk | constraint fk_a_fkey on table fk1 constraint fk_a_fkey on table fk2 | pk | constraint fk_a_fkey on table fk @@ -2530,10 +2920,10 @@ CREATE TABLE pt1 PARTITION OF pt1_2 FOR VALUES IN (1); CREATE TABLE pt2 PARTITION OF pt1_2 FOR VALUES IN (2); CREATE TABLE ref(f1 int, f2 int, f3 int); ALTER TABLE ref ADD FOREIGN KEY(f1,f2) REFERENCES pt; -ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey1 +ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey_1 DEFERRABLE INITIALLY DEFERRED; -- fails -ERROR: cannot alter constraint "ref_f1_f2_fkey1" on relation "ref" -DETAIL: Constraint "ref_f1_f2_fkey1" is derived from constraint "ref_f1_f2_fkey" of relation "ref". +ERROR: cannot alter constraint "ref_f1_f2_fkey_1" on relation "ref" +DETAIL: Constraint "ref_f1_f2_fkey_1" is derived from constraint "ref_f1_f2_fkey" of relation "ref". HINT: You may alter the constraint it derives from instead. ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey DEFERRABLE INITIALLY DEFERRED; @@ -2635,11 +3025,11 @@ ALTER TABLE fk ADD FOREIGN KEY (a) REFERENCES pk ON UPDATE RESTRICT ON DELETE RE CREATE TABLE fk_d PARTITION OF fk DEFAULT; INSERT INTO fk VALUES (20), (30); DELETE FROM pk WHERE a = 20; -ERROR: update or delete on table "pk11" violates foreign key constraint "fk_a_fkey2" on table "fk" -DETAIL: Key (a)=(20) is still referenced from table "fk". +ERROR: update or delete on table "pk11" violates RESTRICT setting of foreign key constraint "fk_a_fkey_2" on table "fk" +DETAIL: Key (a)=(20) is referenced from table "fk". UPDATE pk SET a = 90 WHERE a = 30; -ERROR: update or delete on table "pk" violates foreign key constraint "fk_a_fkey" on table "fk" -DETAIL: Key (a)=(30) is still referenced from table "fk". +ERROR: update or delete on table "pk" violates RESTRICT setting of foreign key constraint "fk_a_fkey" on table "fk" +DETAIL: Key (a)=(30) is referenced from table "fk". SELECT tableoid::regclass, * FROM fk; tableoid | a ----------+---- @@ -2917,3 +3307,102 @@ DETAIL: drop cascades to table fkpart11.pk drop cascades to table fkpart11.fk_parted drop cascades to table fkpart11.fk_another drop cascades to function fkpart11.print_row() +-- When a table is attached as partition to a partitioned table that has +-- a foreign key to another partitioned table, it acquires a clone of the +-- FK. Upon detach, this clone is not removed, but instead becomes an +-- independent FK. If it then attaches to the partitioned table again, +-- the FK from the parent "takes over" ownership of the independent FK rather +-- than creating a separate one. +CREATE SCHEMA fkpart12 + CREATE TABLE fk_p ( id int, jd int, PRIMARY KEY(id, jd)) PARTITION BY list (id) + CREATE TABLE fk_p_1 PARTITION OF fk_p FOR VALUES IN (1) PARTITION BY list (jd) + CREATE TABLE fk_p_1_1 PARTITION OF fk_p_1 FOR VALUES IN (1) + CREATE TABLE fk_p_1_2 (x int, y int, jd int NOT NULL, id int NOT NULL) + CREATE TABLE fk_p_2 PARTITION OF fk_p FOR VALUES IN (2) PARTITION BY list (jd) + CREATE TABLE fk_p_2_1 PARTITION OF fk_p_2 FOR VALUES IN (1) + CREATE TABLE fk_p_2_2 PARTITION OF fk_p_2 FOR VALUES IN (2) + CREATE TABLE fk_r_1 ( p_jd int NOT NULL, x int, id int PRIMARY KEY, p_id int NOT NULL) + CREATE TABLE fk_r_2 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL) PARTITION BY list (id) + CREATE TABLE fk_r_2_1 PARTITION OF fk_r_2 FOR VALUES IN (2, 1) + CREATE TABLE fk_r ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL, + FOREIGN KEY (p_id, p_jd) REFERENCES fk_p (id, jd) + ) PARTITION BY list (id); +SET search_path TO fkpart12; +ALTER TABLE fk_p_1_2 DROP COLUMN x, DROP COLUMN y; +ALTER TABLE fk_p_1 ATTACH PARTITION fk_p_1_2 FOR VALUES IN (2); +ALTER TABLE fk_r_1 DROP COLUMN x; +INSERT INTO fk_p VALUES (1, 1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); +\d fk_r_2 + Partitioned table "fkpart12.fk_r_2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + id | integer | | not null | + p_id | integer | | not null | + p_jd | integer | | not null | +Partition of: fk_r FOR VALUES IN (2) +Partition key: LIST (id) +Indexes: + "fk_r_2_pkey" PRIMARY KEY, btree (id) +Foreign-key constraints: + TABLE "fk_r" CONSTRAINT "fk_r_p_id_p_jd_fkey" FOREIGN KEY (p_id, p_jd) REFERENCES fk_p(id, jd) +Number of partitions: 1 (Use \d+ to list them.) + +INSERT INTO fk_r VALUES (1, 1, 1); +INSERT INTO fk_r VALUES (2, 2, 1); +ERROR: insert or update on table "fk_r_2_1" violates foreign key constraint "fk_r_p_id_p_jd_fkey" +DETAIL: Key (p_id, p_jd)=(2, 1) is not present in table "fk_p". +ALTER TABLE fk_r DETACH PARTITION fk_r_1; +ALTER TABLE fk_r DETACH PARTITION fk_r_2; +\d fk_r_2 + Partitioned table "fkpart12.fk_r_2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + id | integer | | not null | + p_id | integer | | not null | + p_jd | integer | | not null | +Partition key: LIST (id) +Indexes: + "fk_r_2_pkey" PRIMARY KEY, btree (id) +Foreign-key constraints: + "fk_r_p_id_p_jd_fkey" FOREIGN KEY (p_id, p_jd) REFERENCES fk_p(id, jd) +Number of partitions: 1 (Use \d+ to list them.) + +INSERT INTO fk_r_1 (id, p_id, p_jd) VALUES (2, 1, 2); -- should fail +ERROR: insert or update on table "fk_r_1" violates foreign key constraint "fk_r_p_id_p_jd_fkey" +DETAIL: Key (p_id, p_jd)=(1, 2) is not present in table "fk_p". +DELETE FROM fk_p; -- should fail +ERROR: update or delete on table "fk_p_1_1" violates foreign key constraint "fk_r_p_id_p_jd_fkey_7" on table "fk_r_1" +DETAIL: Key (id, jd)=(1, 1) is still referenced from table "fk_r_1". +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); +\d fk_r_2 + Partitioned table "fkpart12.fk_r_2" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + id | integer | | not null | + p_id | integer | | not null | + p_jd | integer | | not null | +Partition of: fk_r FOR VALUES IN (2) +Partition key: LIST (id) +Indexes: + "fk_r_2_pkey" PRIMARY KEY, btree (id) +Foreign-key constraints: + TABLE "fk_r" CONSTRAINT "fk_r_p_id_p_jd_fkey" FOREIGN KEY (p_id, p_jd) REFERENCES fk_p(id, jd) +Number of partitions: 1 (Use \d+ to list them.) + +DELETE FROM fk_p; -- should fail +ERROR: update or delete on table "fk_p_1_1" violates foreign key constraint "fk_r_p_id_p_jd_fkey_2" on table "fk_r" +DETAIL: Key (id, jd)=(1, 1) is still referenced from table "fk_r". +-- these should all fail +ALTER TABLE fk_r_1 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; +ERROR: cannot drop inherited constraint "fk_r_p_id_p_jd_fkey" of relation "fk_r_1" +ALTER TABLE fk_r DROP CONSTRAINT fk_r_p_id_p_jd_fkey_1; +ERROR: cannot drop inherited constraint "fk_r_p_id_p_jd_fkey_1" of relation "fk_r" +ALTER TABLE fk_r_2 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; +ERROR: cannot drop inherited constraint "fk_r_p_id_p_jd_fkey" of relation "fk_r_2" +SET client_min_messages TO warning; +DROP SCHEMA fkpart12 CASCADE; +RESET client_min_messages; +RESET search_path; diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated_stored.out similarity index 84% rename from src/test/regress/expected/generated.out rename to src/test/regress/expected/generated_stored.out index 44058db7c1d51..16de30ab1910b 100644 --- a/src/test/regress/expected/generated.out +++ b/src/test/regress/expected/generated_stored.out @@ -1,12 +1,10 @@ --- sanity check of system catalog -SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's'); - attrelid | attname | attgenerated -----------+---------+-------------- -(0 rows) - +-- keep these tests aligned with generated_virtual.sql +CREATE SCHEMA generated_stored_tests; +GRANT USAGE ON SCHEMA generated_stored_tests TO PUBLIC; +SET search_path = generated_stored_tests; CREATE TABLE gtest0 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (55) STORED); CREATE TABLE gtest1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED); -SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_name LIKE 'gtest_' ORDER BY 1, 2; +SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_schema = 'generated_stored_tests' ORDER BY 1, 2; table_name | column_name | column_default | is_nullable | is_generated | generation_expression ------------+-------------+----------------+-------------+--------------+----------------------- gtest0 | a | | NO | NEVER | @@ -15,14 +13,14 @@ SELECT table_name, column_name, column_default, is_nullable, is_generated, gener gtest1 | b | | YES | ALWAYS | (a * 2) (4 rows) -SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage ORDER BY 1, 2, 3; +SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage WHERE table_schema = 'generated_stored_tests' ORDER BY 1, 2, 3; table_name | column_name | dependent_column ------------+-------------+------------------ gtest1 | a | b (1 row) \d gtest1 - Table "public.gtest1" + Table "generated_stored_tests.gtest1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | not null | @@ -125,6 +123,24 @@ SELECT * FROM gtest1 ORDER BY a; 4 | 8 (4 rows) +SELECT gtest1 FROM gtest1 ORDER BY a; -- whole-row reference + gtest1 +-------- + (1,2) + (2,4) + (3,6) + (4,8) +(4 rows) + +SELECT a, (SELECT gtest1.b) FROM gtest1 ORDER BY a; -- sublink + a | b +---+--- + 1 | 2 + 2 | 4 + 3 | 6 + 4 | 8 +(4 rows) + DELETE FROM gtest1 WHERE a >= 3; UPDATE gtest1 SET b = DEFAULT WHERE a = 1; UPDATE gtest1 SET b = 11 WHERE a = 1; -- error @@ -180,7 +196,12 @@ SELECT * FROM gtest1 ORDER BY a; 2 | 4 (2 rows) -UPDATE gtest1 SET a = 3 WHERE b = 4; +UPDATE gtest1 SET a = 3 WHERE b = 4 RETURNING old.*, new.*; + a | b | a | b +---+---+---+--- + 2 | 4 | 3 | 6 +(1 row) + SELECT * FROM gtest1 ORDER BY a; a | b ---+--- @@ -206,7 +227,14 @@ CREATE TABLE gtestm ( INSERT INTO gtestm VALUES (1, 5, 100); MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id WHEN MATCHED THEN UPDATE SET f1 = v.f1 - WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200); + WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200) + RETURNING merge_action(), old.*, new.*; + merge_action | id | f1 | f2 | f3 | f4 | id | f1 | f2 | f3 | f4 +--------------+----+----+-----+----+-----+----+----+-----+----+----- + UPDATE | 1 | 5 | 100 | 10 | 200 | 1 | 10 | 100 | 20 | 200 + INSERT | | | | | | 2 | 20 | 200 | 40 | 400 +(2 rows) + SELECT * FROM gtestm ORDER BY id; id | f1 | f2 | f3 | f4 ----+----+-----+----+----- @@ -214,6 +242,27 @@ SELECT * FROM gtestm ORDER BY id; 2 | 20 | 200 | 40 | 400 (2 rows) +DROP TABLE gtestm; +CREATE TABLE gtestm ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) STORED +); +INSERT INTO gtestm (a) SELECT g FROM generate_series(1, 10) g; +MERGE INTO gtestm t USING gtestm AS s ON 2 * t.a = s.b WHEN MATCHED THEN DELETE RETURNING *; + a | b | a | b +----+----+----+---- + 1 | 2 | 1 | 2 + 2 | 4 | 2 | 4 + 3 | 6 | 3 | 6 + 4 | 8 | 4 | 8 + 5 | 10 | 5 | 10 + 6 | 12 | 6 | 12 + 7 | 14 | 7 | 14 + 8 | 16 | 8 | 16 + 9 | 18 | 9 | 18 + 10 | 20 | 10 | 20 +(10 rows) + DROP TABLE gtestm; -- views CREATE VIEW gtest1v AS SELECT * FROM gtest1; @@ -270,7 +319,7 @@ SELECT * FROM gtest1_1; (0 rows) \d gtest1_1 - Table "public.gtest1_1" + Table "generated_stored_tests.gtest1_1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | not null | @@ -309,17 +358,38 @@ ERROR: column "b" inherits from generated column but specifies default CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS IDENTITY) INHERITS (gtest1); -- error NOTICE: merging column "b" with inherited definition ERROR: column "b" inherits from generated column but specifies identity +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) VIRTUAL) INHERITS (gtest1); -- error +NOTICE: merging column "b" with inherited definition +ERROR: column "b" inherits from generated column of different kind +DETAIL: Parent column is STORED, child column is VIRTUAL. CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) STORED) INHERITS (gtest1); -- ok, overrides parent NOTICE: merging column "b" with inherited definition \d+ gtestx - Table "public.gtestx" + Table "generated_stored_tests.gtestx" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description --------+---------+-----------+----------+-------------------------------------+---------+--------------+------------- a | integer | | not null | | plain | | b | integer | | | generated always as (a * 22) stored | plain | | x | integer | | | | plain | | +Not-null constraints: + "gtest1_a_not_null" NOT NULL "a" (inherited) Inherits: gtest1 +INSERT INTO gtestx (a, x) VALUES (11, 22); +SELECT * FROM gtest1; + a | b +----+----- + 3 | 6 + 4 | 8 + 11 | 242 +(3 rows) + +SELECT * FROM gtestx; + a | b | x +----+-----+---- + 11 | 242 | 22 +(1 row) + CREATE TABLE gtestxx_1 (a int NOT NULL, b int); ALTER TABLE gtestxx_1 INHERIT gtest1; -- error ERROR: column "b" in child table must be a generated column @@ -348,7 +418,7 @@ NOTICE: merging multiple inherited definitions of column "b" NOTICE: moving and merging column "b" with inherited definition DETAIL: User-specified column moved to the position of the inherited column. \d gtest1_y - Table "public.gtest1_y" + Table "generated_stored_tests.gtest1_y" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | not null | @@ -523,7 +593,7 @@ HINT: Use DROP ... CASCADE to drop the dependent objects too. ALTER TABLE gtest10 DROP COLUMN b CASCADE; -- drops c too NOTICE: drop cascades to column c of table gtest10 \d gtest10 - Table "public.gtest10" + Table "generated_stored_tests.gtest10" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- a | integer | | not null | @@ -535,18 +605,18 @@ ALTER TABLE gtest10a DROP COLUMN b; INSERT INTO gtest10a (a) VALUES (1); -- privileges CREATE USER regress_user11; -CREATE TABLE gtest11s (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); -INSERT INTO gtest11s VALUES (1, 10), (2, 20); -GRANT SELECT (a, c) ON gtest11s TO regress_user11; +CREATE TABLE gtest11 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); +INSERT INTO gtest11 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c) ON gtest11 TO regress_user11; CREATE FUNCTION gf1(a int) RETURNS int AS $$ SELECT a * 3 $$ IMMUTABLE LANGUAGE SQL; REVOKE ALL ON FUNCTION gf1(int) FROM PUBLIC; -CREATE TABLE gtest12s (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) STORED); -INSERT INTO gtest12s VALUES (1, 10), (2, 20); -GRANT SELECT (a, c) ON gtest12s TO regress_user11; +CREATE TABLE gtest12 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) STORED); +INSERT INTO gtest12 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c), INSERT ON gtest12 TO regress_user11; SET ROLE regress_user11; -SELECT a, b FROM gtest11s; -- not allowed -ERROR: permission denied for table gtest11s -SELECT a, c FROM gtest11s; -- allowed +SELECT a, b FROM gtest11; -- not allowed +ERROR: permission denied for table gtest11 +SELECT a, c FROM gtest11; -- allowed a | c ---+---- 1 | 20 @@ -555,7 +625,9 @@ SELECT a, c FROM gtest11s; -- allowed SELECT gf1(10); -- not allowed ERROR: permission denied for function gf1 -SELECT a, c FROM gtest12s; -- allowed +INSERT INTO gtest12 VALUES (3, 30), (4, 40); -- currently not allowed because of function permissions, should arguably be allowed +ERROR: permission denied for function gf1 +SELECT a, c FROM gtest12; -- allowed (does not actually invoke the function) a | c ---+---- 1 | 30 @@ -565,9 +637,9 @@ SELECT a, c FROM gtest12s; -- allowed RESET ROLE; DROP FUNCTION gf1(int); -- fail ERROR: cannot drop function gf1(integer) because other objects depend on it -DETAIL: column c of table gtest12s depends on function gf1(integer) +DETAIL: column c of table gtest12 depends on function gf1(integer) HINT: Use DROP ... CASCADE to drop the dependent objects too. -DROP TABLE gtest11s, gtest12s; +DROP TABLE gtest11, gtest12; DROP FUNCTION gf1(int); DROP USER regress_user11; -- check constraints @@ -584,12 +656,23 @@ INSERT INTO gtest20a (a) VALUES (10); INSERT INTO gtest20a (a) VALUES (30); ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row +-- table rewrite cases +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row +ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED); INSERT INTO gtest20b (a) VALUES (10); INSERT INTO gtest20b (a) VALUES (30); ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID; ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row ERROR: check constraint "chk" of relation "gtest20b" is violated by some row +-- check with whole-row reference +CREATE TABLE gtest20c (a int, b int GENERATED ALWAYS AS (a * 2) STORED); +ALTER TABLE gtest20c ADD CONSTRAINT whole_row_check CHECK (gtest20c IS NOT NULL); +INSERT INTO gtest20c VALUES (1); -- ok +INSERT INTO gtest20c VALUES (NULL); -- fails +ERROR: new row for relation "gtest20c" violates check constraint "whole_row_check" +DETAIL: Failing row contains (null, null). -- not-null constraints CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOT NULL); INSERT INTO gtest21a (a) VALUES (1); -- ok @@ -622,7 +705,7 @@ CREATE INDEX gtest22c_b_idx ON gtest22c (b); CREATE INDEX gtest22c_expr_idx ON gtest22c ((b * 3)); CREATE INDEX gtest22c_pred_idx ON gtest22c (a) WHERE b > 0; \d gtest22c - Table "public.gtest22c" + Table "generated_stored_tests.gtest22c" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | @@ -726,7 +809,7 @@ CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR ERROR: invalid ON DELETE action for foreign key constraint containing generated column CREATE TABLE gtest23b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x)); \d gtest23b - Table "public.gtest23b" + Table "generated_stored_tests.gtest23b" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | not null | @@ -759,6 +842,16 @@ CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * INSERT INTO gtest24 (a) VALUES (4); -- ok INSERT INTO gtest24 (a) VALUES (6); -- error ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" +CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); +CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) STORED); +INSERT INTO gtest24r (a) VALUES (4); -- ok +INSERT INTO gtest24r (a) VALUES (6); -- error +ERROR: value for domain gtestdomain1 violates check constraint "gtestdomain1_check" +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) STORED); +INSERT INTO gtest24nn (a) VALUES (4); -- ok +INSERT INTO gtest24nn (a) VALUES (NULL); -- error +ERROR: value for domain gtestdomainnn violates check constraint "gtestdomainnn_check" -- typed tables (currently not supported) CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); CREATE TABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) STORED); @@ -789,6 +882,11 @@ CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error ) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); ERROR: identity columns are not supported on partitions +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 GENERATED ALWAYS AS (f2 * 2) VIRTUAL -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +ERROR: column "f3" inherits from generated column of different kind +DETAIL: Parent column is STORED, child column is VIRTUAL. CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint); ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error ERROR: column "f3" in child table must be a generated column @@ -802,10 +900,15 @@ ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09 ERROR: table "gtest_child3" being attached contains an identity column "f3" DETAIL: The new partition may not contain an identity column. DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +ERROR: column "f3" inherits from generated column of different kind +DETAIL: Parent column is STORED, child column is VIRTUAL. +DROP TABLE gtest_child3; CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED); ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); \d gtest_child - Table "public.gtest_child" + Table "generated_stored_tests.gtest_child" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -814,7 +917,7 @@ ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09 Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') \d gtest_child2 - Table "public.gtest_child2" + Table "generated_stored_tests.gtest_child2" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+-------------------------------------- f1 | date | | not null | @@ -823,7 +926,7 @@ Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') \d gtest_child3 - Table "public.gtest_child3" + Table "generated_stored_tests.gtest_child3" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+-------------------------------------- f1 | date | | not null | @@ -842,6 +945,24 @@ SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; gtest_child2 | 08-15-2016 | 3 | 66 (3 rows) +SELECT tableoid::regclass, * FROM gtest_child ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +-------------+------------+----+---- + gtest_child | 07-15-2016 | 1 | 2 + gtest_child | 07-15-2016 | 2 | 4 +(2 rows) + +SELECT tableoid::regclass, * FROM gtest_child2 ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child2 | 08-15-2016 | 3 | 66 +(1 row) + +SELECT tableoid::regclass, * FROM gtest_child3 ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +----------+----+----+---- +(0 rows) + UPDATE gtest_parent SET f1 = f1 + 60 WHERE f2 = 1; SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; tableoid | f1 | f2 | f3 @@ -855,7 +976,7 @@ SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; ALTER TABLE ONLY gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 4); ALTER TABLE gtest_child ALTER COLUMN f3 SET EXPRESSION AS (f2 * 10); \d gtest_parent - Partitioned table "public.gtest_parent" + Partitioned table "generated_stored_tests.gtest_parent" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -865,7 +986,7 @@ Partition key: RANGE (f1) Number of partitions: 3 (Use \d+ to list them.) \d gtest_child - Table "public.gtest_child" + Table "generated_stored_tests.gtest_child" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+-------------------------------------- f1 | date | | not null | @@ -874,7 +995,7 @@ Number of partitions: 3 (Use \d+ to list them.) Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') \d gtest_child2 - Table "public.gtest_child2" + Table "generated_stored_tests.gtest_child2" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+-------------------------------------- f1 | date | | not null | @@ -883,7 +1004,7 @@ Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') \d gtest_child3 - Table "public.gtest_child3" + Table "generated_stored_tests.gtest_child3" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+-------------------------------------- f1 | date | | not null | @@ -902,7 +1023,7 @@ SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; -- alter generation expression of parent and all its children altogether ALTER TABLE gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 2); \d gtest_parent - Partitioned table "public.gtest_parent" + Partitioned table "generated_stored_tests.gtest_parent" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -912,7 +1033,7 @@ Partition key: RANGE (f1) Number of partitions: 3 (Use \d+ to list them.) \d gtest_child - Table "public.gtest_child" + Table "generated_stored_tests.gtest_child" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -921,7 +1042,7 @@ Number of partitions: 3 (Use \d+ to list them.) Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') \d gtest_child2 - Table "public.gtest_child2" + Table "generated_stored_tests.gtest_child2" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -930,7 +1051,7 @@ Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') \d gtest_child3 - Table "public.gtest_child3" + Table "generated_stored_tests.gtest_child3" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------- f1 | date | | not null | @@ -987,7 +1108,7 @@ SELECT * FROM gtest25 ORDER BY a; (2 rows) \d gtest25 - Table "public.gtest25" + Table "generated_stored_tests.gtest25" Column | Type | Collation | Nullable | Default --------+------------------+-----------+----------+------------------------------------------------------ a | integer | | not null | @@ -1011,7 +1132,7 @@ ERROR: cannot alter type of a column used by a generated column DETAIL: Column "a" is used by generated column "x". ALTER TABLE gtest27 ALTER COLUMN x TYPE numeric; \d gtest27 - Table "public.gtest27" + Table "generated_stored_tests.gtest27" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+-------------------------------------------- a | integer | | | @@ -1026,7 +1147,10 @@ SELECT * FROM gtest27; (2 rows) ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0; -- error -ERROR: generation expression for column "x" cannot be cast automatically to type boolean +ERROR: cannot specify USING when altering type of generated column +LINE 1: ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0... + ^ +DETAIL: Column "x" is a generated column. ALTER TABLE gtest27 ALTER COLUMN x DROP DEFAULT; -- error ERROR: column "x" of relation "gtest27" is a generated column HINT: Use ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION instead. @@ -1037,7 +1161,7 @@ ALTER TABLE gtest27 ALTER COLUMN b TYPE bigint, ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) STORED; \d gtest27 - Table "public.gtest27" + Table "generated_stored_tests.gtest27" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------------ a | bigint | | | @@ -1051,7 +1175,7 @@ ALTER TABLE gtest27 ERROR: cannot alter type of a column used by a generated column DETAIL: Column "a" is used by generated column "x". \d gtest27 - Table "public.gtest27" + Table "generated_stored_tests.gtest27" Column | Type | Collation | Nullable | Default --------+--------+-----------+----------+------------------------------------------ a | bigint | | | @@ -1079,7 +1203,7 @@ SELECT * FROM gtest29; (2 rows) \d gtest29 - Table "public.gtest29" + Table "generated_stored_tests.gtest29" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | @@ -1088,9 +1212,9 @@ SELECT * FROM gtest29; ALTER TABLE gtest29 ALTER COLUMN a SET EXPRESSION AS (a * 3); -- error ERROR: column "a" of relation "gtest29" is not a generated column ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION; -- error -ERROR: column "a" of relation "gtest29" is not a stored generated column +ERROR: column "a" of relation "gtest29" is not a generated column ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION IF EXISTS; -- notice -NOTICE: column "a" of relation "gtest29" is not a stored generated column, skipping +NOTICE: column "a" of relation "gtest29" is not a generated column, skipping -- Change the expression ALTER TABLE gtest29 ALTER COLUMN b SET EXPRESSION AS (a * 3); SELECT * FROM gtest29; @@ -1101,7 +1225,7 @@ SELECT * FROM gtest29; (2 rows) \d gtest29 - Table "public.gtest29" + Table "generated_stored_tests.gtest29" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | @@ -1120,7 +1244,7 @@ SELECT * FROM gtest29; (4 rows) \d gtest29 - Table "public.gtest29" + Table "generated_stored_tests.gtest29" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- a | integer | | | @@ -1129,7 +1253,7 @@ SELECT * FROM gtest29; -- check that dependencies between columns have also been removed ALTER TABLE gtest29 DROP COLUMN a; -- should not drop b \d gtest29 - Table "public.gtest29" + Table "generated_stored_tests.gtest29" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- b | integer | | | @@ -1142,7 +1266,7 @@ CREATE TABLE gtest30 ( CREATE TABLE gtest30_1 () INHERITS (gtest30); ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION; \d gtest30 - Table "public.gtest30" + Table "generated_stored_tests.gtest30" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- a | integer | | | @@ -1150,7 +1274,7 @@ ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION; Number of child tables: 1 (Use \d+ to list them.) \d gtest30_1 - Table "public.gtest30_1" + Table "generated_stored_tests.gtest30_1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- a | integer | | | @@ -1167,7 +1291,7 @@ CREATE TABLE gtest30_1 () INHERITS (gtest30); ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error ERROR: ALTER TABLE / DROP EXPRESSION must be applied to child tables too \d gtest30 - Table "public.gtest30" + Table "generated_stored_tests.gtest30" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | @@ -1175,7 +1299,7 @@ ERROR: ALTER TABLE / DROP EXPRESSION must be applied to child tables too Number of child tables: 1 (Use \d+ to list them.) \d gtest30_1 - Table "public.gtest30_1" + Table "generated_stored_tests.gtest30_1" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ a | integer | | | @@ -1184,6 +1308,18 @@ Inherits: gtest30 ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error ERROR: cannot drop generation expression from inherited column +-- composite type dependencies +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +ERROR: cannot alter table "gtest31_1" because column "gtest31_2.y" uses its row type +DROP TABLE gtest31_1, gtest31_2; +-- Check it for a partitioned table, too +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text) PARTITION BY LIST (a); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +ERROR: cannot alter table "gtest31_1" because column "gtest31_2.y" uses its row type +DROP TABLE gtest31_1, gtest31_2; -- triggers CREATE TABLE gtest26 ( a int PRIMARY KEY, @@ -1294,7 +1430,7 @@ UPDATE gtest26 SET a = 1 WHERE a = 0; NOTICE: OK DROP TRIGGER gtest11 ON gtest26; TRUNCATE gtest26; --- check that modifications of stored generated columns in triggers do +-- check that modifications of generated columns in triggers do -- not get propagated CREATE FUNCTION gtest_trigger_func4() RETURNS trigger LANGUAGE plpgsql @@ -1305,20 +1441,28 @@ BEGIN RETURN NEW; END; $$; -CREATE TRIGGER gtest12_01 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_01 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func(); -CREATE TRIGGER gtest12_02 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_02 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func4(); -CREATE TRIGGER gtest12_03 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_03 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func(); INSERT INTO gtest26 (a) VALUES (1); -UPDATE gtest26 SET a = 11 WHERE a = 1; -INFO: gtest12_01: BEFORE: old = (1,2) +INFO: gtest12_01: BEFORE: new = (1,) +INFO: gtest12_03: BEFORE: new = (10,300) +SELECT * FROM gtest26 ORDER BY a; + a | b +----+---- + 10 | 20 +(1 row) + +UPDATE gtest26 SET a = 11 WHERE a = 10; +INFO: gtest12_01: BEFORE: old = (10,20) INFO: gtest12_01: BEFORE: new = (11,) -INFO: gtest12_03: BEFORE: old = (1,2) +INFO: gtest12_03: BEFORE: old = (10,20) INFO: gtest12_03: BEFORE: new = (10,) SELECT * FROM gtest26 ORDER BY a; a | b @@ -1336,17 +1480,23 @@ CREATE TABLE gtest28a ( ALTER TABLE gtest28a DROP COLUMN a; CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); \d gtest28* - Table "public.gtest28a" + Table "generated_stored_tests.gtest28a" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ b | integer | | | c | integer | | | x | integer | | | generated always as (b * 2) stored - Table "public.gtest28b" + Table "generated_stored_tests.gtest28b" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+------------------------------------ b | integer | | | c | integer | | | x | integer | | | generated always as (b * 2) stored +-- sanity check of system catalog +SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's', 'v'); + attrelid | attname | attgenerated +----------+---------+-------------- +(0 rows) + diff --git a/src/test/regress/expected/generated_virtual.out b/src/test/regress/expected/generated_virtual.out new file mode 100644 index 0000000000000..6300e7c1d96e1 --- /dev/null +++ b/src/test/regress/expected/generated_virtual.out @@ -0,0 +1,1594 @@ +-- keep these tests aligned with generated_stored.sql +CREATE SCHEMA generated_virtual_tests; +GRANT USAGE ON SCHEMA generated_virtual_tests TO PUBLIC; +SET search_path = generated_virtual_tests; +CREATE TABLE gtest0 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (55) VIRTUAL); +CREATE TABLE gtest1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_schema = 'generated_virtual_tests' ORDER BY 1, 2; + table_name | column_name | column_default | is_nullable | is_generated | generation_expression +------------+-------------+----------------+-------------+--------------+----------------------- + gtest0 | a | | NO | NEVER | + gtest0 | b | | YES | ALWAYS | 55 + gtest1 | a | | NO | NEVER | + gtest1 | b | | YES | ALWAYS | (a * 2) +(4 rows) + +SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage WHERE table_schema = 'generated_virtual_tests' ORDER BY 1, 2, 3; + table_name | column_name | dependent_column +------------+-------------+------------------ + gtest1 | a | b +(1 row) + +\d gtest1 + Table "generated_virtual_tests.gtest1" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | not null | + b | integer | | | generated always as (a * 2) +Indexes: + "gtest1_pkey" PRIMARY KEY, btree (a) + +-- duplicate generated +CREATE TABLE gtest_err_1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL GENERATED ALWAYS AS (a * 3) VIRTUAL); +ERROR: multiple generation clauses specified for column "b" of table "gtest_err_1" +LINE 1: ...RY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL GENERATED ... + ^ +-- references to other generated columns, including self-references +CREATE TABLE gtest_err_2a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (b * 2) VIRTUAL); +ERROR: cannot use generated column "b" in column generation expression +LINE 1: ...2a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (b * 2) VIR... + ^ +DETAIL: A generated column cannot reference another generated column. +CREATE TABLE gtest_err_2b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL, c int GENERATED ALWAYS AS (b * 3) VIRTUAL); +ERROR: cannot use generated column "b" in column generation expression +LINE 1: ...YS AS (a * 2) VIRTUAL, c int GENERATED ALWAYS AS (b * 3) VIR... + ^ +DETAIL: A generated column cannot reference another generated column. +-- a whole-row var is a self-reference on steroids, so disallow that too +CREATE TABLE gtest_err_2c (a int PRIMARY KEY, + b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) VIRTUAL); +ERROR: cannot use whole-row variable in column generation expression +LINE 2: b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) VIRT... + ^ +DETAIL: This would cause the generated column to depend on its own value. +-- invalid reference +CREATE TABLE gtest_err_3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) VIRTUAL); +ERROR: column "c" does not exist +LINE 1: ..._3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) VIR... + ^ +-- generation expression must be immutable +CREATE TABLE gtest_err_4 (a int PRIMARY KEY, b double precision GENERATED ALWAYS AS (random()) VIRTUAL); +ERROR: generation expression is not immutable +-- ... but be sure that the immutability test is accurate +CREATE TABLE gtest2 (a int, b text GENERATED ALWAYS AS (a || ' sec') VIRTUAL); +DROP TABLE gtest2; +-- cannot have default/identity and generated +CREATE TABLE gtest_err_5a (a int PRIMARY KEY, b int DEFAULT 5 GENERATED ALWAYS AS (a * 2) VIRTUAL); +ERROR: both default and generation expression specified for column "b" of table "gtest_err_5a" +LINE 1: ... gtest_err_5a (a int PRIMARY KEY, b int DEFAULT 5 GENERATED ... + ^ +CREATE TABLE gtest_err_5b (a int PRIMARY KEY, b int GENERATED ALWAYS AS identity GENERATED ALWAYS AS (a * 2) VIRTUAL); +ERROR: both identity and generation expression specified for column "b" of table "gtest_err_5b" +LINE 1: ...t PRIMARY KEY, b int GENERATED ALWAYS AS identity GENERATED ... + ^ +-- reference to system column not allowed in generated column +-- (except tableoid, which we test below) +CREATE TABLE gtest_err_6a (a int PRIMARY KEY, b bool GENERATED ALWAYS AS (xmin <> 37) VIRTUAL); +ERROR: cannot use system column "xmin" in column generation expression +LINE 1: ...a (a int PRIMARY KEY, b bool GENERATED ALWAYS AS (xmin <> 37... + ^ +-- various prohibited constructs +CREATE TABLE gtest_err_7a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (avg(a)) VIRTUAL); +ERROR: aggregate functions are not allowed in column generation expressions +LINE 1: ...7a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (avg(a)) VI... + ^ +CREATE TABLE gtest_err_7b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (row_number() OVER (ORDER BY a)) VIRTUAL); +ERROR: window functions are not allowed in column generation expressions +LINE 1: ...7b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (row_number... + ^ +CREATE TABLE gtest_err_7c (a int PRIMARY KEY, b int GENERATED ALWAYS AS ((SELECT a)) VIRTUAL); +ERROR: cannot use subquery in column generation expression +LINE 1: ...7c (a int PRIMARY KEY, b int GENERATED ALWAYS AS ((SELECT a)... + ^ +CREATE TABLE gtest_err_7d (a int PRIMARY KEY, b int GENERATED ALWAYS AS (generate_series(1, a)) VIRTUAL); +ERROR: set-returning functions are not allowed in column generation expressions +LINE 1: ...7d (a int PRIMARY KEY, b int GENERATED ALWAYS AS (generate_s... + ^ +-- GENERATED BY DEFAULT not allowed +CREATE TABLE gtest_err_8 (a int PRIMARY KEY, b int GENERATED BY DEFAULT AS (a * 2) VIRTUAL); +ERROR: for a generated column, GENERATED ALWAYS must be specified +LINE 1: ...E gtest_err_8 (a int PRIMARY KEY, b int GENERATED BY DEFAULT... + ^ +INSERT INTO gtest1 VALUES (1); +INSERT INTO gtest1 VALUES (2, DEFAULT); -- ok +INSERT INTO gtest1 VALUES (3, 33); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1 VALUES (3, 33), (4, 44); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1 VALUES (3, DEFAULT), (4, 44); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1 VALUES (3, 33), (4, DEFAULT); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1 VALUES (3, DEFAULT), (4, DEFAULT); -- ok +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 1 | 2 + 2 | 4 + 3 | 6 + 4 | 8 +(4 rows) + +SELECT gtest1 FROM gtest1 ORDER BY a; -- whole-row reference + gtest1 +-------- + (1,2) + (2,4) + (3,6) + (4,8) +(4 rows) + +SELECT a, (SELECT gtest1.b) FROM gtest1 ORDER BY a; -- sublink + a | b +---+--- + 1 | 2 + 2 | 4 + 3 | 6 + 4 | 8 +(4 rows) + +DELETE FROM gtest1 WHERE a >= 3; +UPDATE gtest1 SET b = DEFAULT WHERE a = 1; +UPDATE gtest1 SET b = 11 WHERE a = 1; -- error +ERROR: column "b" can only be updated to DEFAULT +DETAIL: Column "b" is a generated column. +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 1 | 2 + 2 | 4 +(2 rows) + +SELECT a, b, b * 2 AS b2 FROM gtest1 ORDER BY a; + a | b | b2 +---+---+---- + 1 | 2 | 4 + 2 | 4 | 8 +(2 rows) + +SELECT a, b FROM gtest1 WHERE b = 4 ORDER BY a; + a | b +---+--- + 2 | 4 +(1 row) + +-- test that overflow error happens on read +INSERT INTO gtest1 VALUES (2000000000); +SELECT * FROM gtest1; +ERROR: integer out of range +DELETE FROM gtest1 WHERE a = 2000000000; +-- test with joins +CREATE TABLE gtestx (x int, y int); +INSERT INTO gtestx VALUES (11, 1), (22, 2), (33, 3); +SELECT * FROM gtestx, gtest1 WHERE gtestx.y = gtest1.a; + x | y | a | b +----+---+---+--- + 11 | 1 | 1 | 2 + 22 | 2 | 2 | 4 +(2 rows) + +DROP TABLE gtestx; +-- test UPDATE/DELETE quals +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 1 | 2 + 2 | 4 +(2 rows) + +UPDATE gtest1 SET a = 3 WHERE b = 4 RETURNING old.*, new.*; + a | b | a | b +---+---+---+--- + 2 | 4 | 3 | 6 +(1 row) + +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 1 | 2 + 3 | 6 +(2 rows) + +DELETE FROM gtest1 WHERE b = 2; +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 3 | 6 +(1 row) + +-- test MERGE +CREATE TABLE gtestm ( + id int PRIMARY KEY, + f1 int, + f2 int, + f3 int GENERATED ALWAYS AS (f1 * 2) VIRTUAL, + f4 int GENERATED ALWAYS AS (f2 * 2) VIRTUAL +); +INSERT INTO gtestm VALUES (1, 5, 100); +MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id + WHEN MATCHED THEN UPDATE SET f1 = v.f1 + WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200) + RETURNING merge_action(), old.*, new.*; + merge_action | id | f1 | f2 | f3 | f4 | id | f1 | f2 | f3 | f4 +--------------+----+----+-----+----+-----+----+----+-----+----+----- + UPDATE | 1 | 5 | 100 | 10 | 200 | 1 | 10 | 100 | 20 | 200 + INSERT | | | | | | 2 | 20 | 200 | 40 | 400 +(2 rows) + +SELECT * FROM gtestm ORDER BY id; + id | f1 | f2 | f3 | f4 +----+----+-----+----+----- + 1 | 10 | 100 | 20 | 200 + 2 | 20 | 200 | 40 | 400 +(2 rows) + +DROP TABLE gtestm; +CREATE TABLE gtestm ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +INSERT INTO gtestm (a) SELECT g FROM generate_series(1, 10) g; +MERGE INTO gtestm t USING gtestm AS s ON 2 * t.a = s.b WHEN MATCHED THEN DELETE RETURNING *; + a | b | a | b +----+----+----+---- + 1 | 2 | 1 | 2 + 2 | 4 | 2 | 4 + 3 | 6 | 3 | 6 + 4 | 8 | 4 | 8 + 5 | 10 | 5 | 10 + 6 | 12 | 6 | 12 + 7 | 14 | 7 | 14 + 8 | 16 | 8 | 16 + 9 | 18 | 9 | 18 + 10 | 20 | 10 | 20 +(10 rows) + +DROP TABLE gtestm; +-- views +CREATE VIEW gtest1v AS SELECT * FROM gtest1; +SELECT * FROM gtest1v; + a | b +---+--- + 3 | 6 +(1 row) + +INSERT INTO gtest1v VALUES (4, 8); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1v VALUES (5, DEFAULT); -- ok +INSERT INTO gtest1v VALUES (6, 66), (7, 77); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1v VALUES (6, DEFAULT), (7, 77); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1v VALUES (6, 66), (7, DEFAULT); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1v VALUES (6, DEFAULT), (7, DEFAULT); -- ok +ALTER VIEW gtest1v ALTER COLUMN b SET DEFAULT 100; +INSERT INTO gtest1v VALUES (8, DEFAULT); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +INSERT INTO gtest1v VALUES (8, DEFAULT), (9, DEFAULT); -- error +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +SELECT * FROM gtest1v; + a | b +---+---- + 3 | 6 + 5 | 10 + 6 | 12 + 7 | 14 +(4 rows) + +DELETE FROM gtest1v WHERE a >= 5; +DROP VIEW gtest1v; +-- CTEs +WITH foo AS (SELECT * FROM gtest1) SELECT * FROM foo; + a | b +---+--- + 3 | 6 +(1 row) + +-- inheritance +CREATE TABLE gtest1_1 () INHERITS (gtest1); +SELECT * FROM gtest1_1; + a | b +---+--- +(0 rows) + +\d gtest1_1 + Table "generated_virtual_tests.gtest1_1" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | not null | + b | integer | | | generated always as (a * 2) +Inherits: gtest1 + +INSERT INTO gtest1_1 VALUES (4); +SELECT * FROM gtest1_1; + a | b +---+--- + 4 | 8 +(1 row) + +SELECT * FROM gtest1; + a | b +---+--- + 3 | 6 + 4 | 8 +(2 rows) + +-- can't have generated column that is a child of normal column +CREATE TABLE gtest_normal (a int, b int); +CREATE TABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL) INHERITS (gtest_normal); -- error +NOTICE: merging column "a" with inherited definition +NOTICE: merging column "b" with inherited definition +ERROR: child column "b" specifies generation expression +HINT: A child table column cannot be generated unless its parent column is. +CREATE TABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest_normal_child INHERIT gtest_normal; -- error +ERROR: column "b" in child table must not be a generated column +DROP TABLE gtest_normal, gtest_normal_child; +-- test inheritance mismatches between parent and child +CREATE TABLE gtestx (x int, b int DEFAULT 10) INHERITS (gtest1); -- error +NOTICE: merging column "b" with inherited definition +ERROR: column "b" inherits from generated column but specifies default +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS IDENTITY) INHERITS (gtest1); -- error +NOTICE: merging column "b" with inherited definition +ERROR: column "b" inherits from generated column but specifies identity +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) STORED) INHERITS (gtest1); -- error +NOTICE: merging column "b" with inherited definition +ERROR: column "b" inherits from generated column of different kind +DETAIL: Parent column is VIRTUAL, child column is STORED. +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) VIRTUAL) INHERITS (gtest1); -- ok, overrides parent +NOTICE: merging column "b" with inherited definition +\d+ gtestx + Table "generated_virtual_tests.gtestx" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+------------------------------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | | generated always as (a * 22) | plain | | + x | integer | | | | plain | | +Not-null constraints: + "gtest1_a_not_null" NOT NULL "a" (inherited) +Inherits: gtest1 + +INSERT INTO gtestx (a, x) VALUES (11, 22); +SELECT * FROM gtest1; + a | b +----+---- + 3 | 6 + 4 | 8 + 11 | 22 +(3 rows) + +SELECT * FROM gtestx; + a | b | x +----+-----+---- + 11 | 242 | 22 +(1 row) + +CREATE TABLE gtestxx_1 (a int NOT NULL, b int); +ALTER TABLE gtestxx_1 INHERIT gtest1; -- error +ERROR: column "b" in child table must be a generated column +CREATE TABLE gtestxx_3 (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtestxx_3 INHERIT gtest1; -- ok +CREATE TABLE gtestxx_4 (b int GENERATED ALWAYS AS (a * 2) VIRTUAL, a int NOT NULL); +ALTER TABLE gtestxx_4 INHERIT gtest1; -- ok +-- test multiple inheritance mismatches +CREATE TABLE gtesty (x int, b int DEFAULT 55); +CREATE TABLE gtest1_y () INHERITS (gtest0, gtesty); -- error +NOTICE: merging multiple inherited definitions of column "b" +ERROR: inherited column "b" has a generation conflict +DROP TABLE gtesty; +CREATE TABLE gtesty (x int, b int); +CREATE TABLE gtest1_y () INHERITS (gtest1, gtesty); -- error +NOTICE: merging multiple inherited definitions of column "b" +ERROR: inherited column "b" has a generation conflict +DROP TABLE gtesty; +CREATE TABLE gtesty (x int, b int GENERATED ALWAYS AS (x * 22) VIRTUAL); +CREATE TABLE gtest1_y () INHERITS (gtest1, gtesty); -- error +NOTICE: merging multiple inherited definitions of column "b" +ERROR: column "b" inherits conflicting generation expressions +HINT: To resolve the conflict, specify a generation expression explicitly. +CREATE TABLE gtest1_y (b int GENERATED ALWAYS AS (x + 1) VIRTUAL) INHERITS (gtest1, gtesty); -- ok +NOTICE: merging multiple inherited definitions of column "b" +NOTICE: moving and merging column "b" with inherited definition +DETAIL: User-specified column moved to the position of the inherited column. +\d gtest1_y + Table "generated_virtual_tests.gtest1_y" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | not null | + b | integer | | | generated always as (x + 1) + x | integer | | | +Inherits: gtest1, + gtesty + +-- test correct handling of GENERATED column that's only in child +CREATE TABLE gtestp (f1 int); +CREATE TABLE gtestc (f2 int GENERATED ALWAYS AS (f1+1) VIRTUAL) INHERITS(gtestp); +INSERT INTO gtestc values(42); +TABLE gtestc; + f1 | f2 +----+---- + 42 | 43 +(1 row) + +UPDATE gtestp SET f1 = f1 * 10; +TABLE gtestc; + f1 | f2 +-----+----- + 420 | 421 +(1 row) + +DROP TABLE gtestp CASCADE; +NOTICE: drop cascades to table gtestc +-- test update +CREATE TABLE gtest3 (a int, b int GENERATED ALWAYS AS (a * 3) VIRTUAL); +INSERT INTO gtest3 (a) VALUES (1), (2), (3), (NULL); +SELECT * FROM gtest3 ORDER BY a; + a | b +---+--- + 1 | 3 + 2 | 6 + 3 | 9 + | +(4 rows) + +UPDATE gtest3 SET a = 22 WHERE a = 2; +SELECT * FROM gtest3 ORDER BY a; + a | b +----+---- + 1 | 3 + 3 | 9 + 22 | 66 + | +(4 rows) + +CREATE TABLE gtest3a (a text, b text GENERATED ALWAYS AS (a || '+' || a) VIRTUAL); +INSERT INTO gtest3a (a) VALUES ('a'), ('b'), ('c'), (NULL); +SELECT * FROM gtest3a ORDER BY a; + a | b +---+----- + a | a+a + b | b+b + c | c+c + | +(4 rows) + +UPDATE gtest3a SET a = 'bb' WHERE a = 'b'; +SELECT * FROM gtest3a ORDER BY a; + a | b +----+------- + a | a+a + bb | bb+bb + c | c+c + | +(4 rows) + +-- COPY +TRUNCATE gtest1; +INSERT INTO gtest1 (a) VALUES (1), (2); +COPY gtest1 TO stdout; +1 +2 +COPY gtest1 (a, b) TO stdout; +ERROR: column "b" is a generated column +DETAIL: Generated columns cannot be used in COPY. +COPY gtest1 FROM stdin; +COPY gtest1 (a, b) FROM stdin; +ERROR: column "b" is a generated column +DETAIL: Generated columns cannot be used in COPY. +SELECT * FROM gtest1 ORDER BY a; + a | b +---+--- + 1 | 2 + 2 | 4 + 3 | 6 + 4 | 8 +(4 rows) + +TRUNCATE gtest3; +INSERT INTO gtest3 (a) VALUES (1), (2); +COPY gtest3 TO stdout; +1 +2 +COPY gtest3 (a, b) TO stdout; +ERROR: column "b" is a generated column +DETAIL: Generated columns cannot be used in COPY. +COPY gtest3 FROM stdin; +COPY gtest3 (a, b) FROM stdin; +ERROR: column "b" is a generated column +DETAIL: Generated columns cannot be used in COPY. +SELECT * FROM gtest3 ORDER BY a; + a | b +---+---- + 1 | 3 + 2 | 6 + 3 | 9 + 4 | 12 +(4 rows) + +-- null values +CREATE TABLE gtest2 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (NULL) VIRTUAL); +INSERT INTO gtest2 VALUES (1); +SELECT * FROM gtest2; + a | b +---+--- + 1 | +(1 row) + +-- simple column reference for varlena types +CREATE TABLE gtest_varlena (a varchar, b varchar GENERATED ALWAYS AS (a) VIRTUAL); +INSERT INTO gtest_varlena (a) VALUES('01234567890123456789'); +INSERT INTO gtest_varlena (a) VALUES(NULL); +SELECT * FROM gtest_varlena ORDER BY a; + a | b +----------------------+---------------------- + 01234567890123456789 | 01234567890123456789 + | +(2 rows) + +DROP TABLE gtest_varlena; +-- composite types +CREATE TYPE double_int as (a int, b int); +CREATE TABLE gtest4 ( + a int, + b double_int GENERATED ALWAYS AS ((a * 2, a * 3)) VIRTUAL +); +INSERT INTO gtest4 VALUES (1), (6); +SELECT * FROM gtest4; + a | b +---+--------- + 1 | (2,3) + 6 | (12,18) +(2 rows) + +DROP TABLE gtest4; +DROP TYPE double_int; +-- using tableoid is allowed +CREATE TABLE gtest_tableoid ( + a int PRIMARY KEY, + b bool GENERATED ALWAYS AS (tableoid = 'gtest_tableoid'::regclass) VIRTUAL +); +INSERT INTO gtest_tableoid VALUES (1), (2); +ALTER TABLE gtest_tableoid ADD COLUMN + c regclass GENERATED ALWAYS AS (tableoid) VIRTUAL; +SELECT * FROM gtest_tableoid; + a | b | c +---+---+---------------- + 1 | t | gtest_tableoid + 2 | t | gtest_tableoid +(2 rows) + +-- drop column behavior +CREATE TABLE gtest10 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) VIRTUAL); +ALTER TABLE gtest10 DROP COLUMN b; -- fails +ERROR: cannot drop column b of table gtest10 because other objects depend on it +DETAIL: column c of table gtest10 depends on column b of table gtest10 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER TABLE gtest10 DROP COLUMN b CASCADE; -- drops c too +NOTICE: drop cascades to column c of table gtest10 +\d gtest10 + Table "generated_virtual_tests.gtest10" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+--------- + a | integer | | not null | +Indexes: + "gtest10_pkey" PRIMARY KEY, btree (a) + +CREATE TABLE gtest10a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest10a DROP COLUMN b; +INSERT INTO gtest10a (a) VALUES (1); +-- privileges +CREATE USER regress_user11; +CREATE TABLE gtest11 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) VIRTUAL); +INSERT INTO gtest11 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c) ON gtest11 TO regress_user11; +CREATE FUNCTION gf1(a int) RETURNS int AS $$ SELECT a * 3 $$ IMMUTABLE LANGUAGE SQL; +REVOKE ALL ON FUNCTION gf1(int) FROM PUBLIC; +CREATE TABLE gtest12 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) VIRTUAL); +INSERT INTO gtest12 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c), INSERT ON gtest12 TO regress_user11; +SET ROLE regress_user11; +SELECT a, b FROM gtest11; -- not allowed +ERROR: permission denied for table gtest11 +SELECT a, c FROM gtest11; -- allowed + a | c +---+---- + 1 | 20 + 2 | 40 +(2 rows) + +SELECT gf1(10); -- not allowed +ERROR: permission denied for function gf1 +INSERT INTO gtest12 VALUES (3, 30), (4, 40); -- allowed (does not actually invoke the function) +SELECT a, c FROM gtest12; -- currently not allowed because of function permissions, should arguably be allowed +ERROR: permission denied for function gf1 +RESET ROLE; +DROP FUNCTION gf1(int); -- fail +ERROR: cannot drop function gf1(integer) because other objects depend on it +DETAIL: column c of table gtest12 depends on function gf1(integer) +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE gtest11, gtest12; +DROP FUNCTION gf1(int); +DROP USER regress_user11; +-- check constraints +CREATE TABLE gtest20 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL CHECK (b < 50)); +INSERT INTO gtest20 (a) VALUES (10); -- ok +INSERT INTO gtest20 (a) VALUES (30); -- violates constraint +ERROR: new row for relation "gtest20" violates check constraint "gtest20_b_check" +DETAIL: Failing row contains (30, virtual). +ALTER TABLE gtest20 ALTER COLUMN b SET EXPRESSION AS (a * 100); -- violates constraint (currently not supported) +ERROR: ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables with check constraints +DETAIL: Column "b" of relation "gtest20" is a virtual generated column. +ALTER TABLE gtest20 ALTER COLUMN b SET EXPRESSION AS (a * 3); -- ok (currently not supported) +ERROR: ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables with check constraints +DETAIL: Column "b" of relation "gtest20" is a virtual generated column. +CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +INSERT INTO gtest20a (a) VALUES (10); +INSERT INTO gtest20a (a) VALUES (30); +ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row +ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row +-- table rewrite cases +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row +ERROR: check constraint "gtest20a_b_check" of relation "gtest20a" is violated by some row +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok +CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +INSERT INTO gtest20b (a) VALUES (10); +INSERT INTO gtest20b (a) VALUES (30); +ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID; +ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row +ERROR: check constraint "chk" of relation "gtest20b" is violated by some row +-- check with whole-row reference +CREATE TABLE gtest20c (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest20c ADD CONSTRAINT whole_row_check CHECK (gtest20c IS NOT NULL); +INSERT INTO gtest20c VALUES (1); -- ok +INSERT INTO gtest20c VALUES (NULL); -- fails +ERROR: new row for relation "gtest20c" violates check constraint "whole_row_check" +DETAIL: Failing row contains (null, virtual). +-- not-null constraints +CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL NOT NULL); +INSERT INTO gtest21a (a) VALUES (1); -- ok +INSERT INTO gtest21a (a) VALUES (0); -- violates constraint +ERROR: null value in column "b" of relation "gtest21a" violates not-null constraint +DETAIL: Failing row contains (0, virtual). +-- also check with table constraint syntax +CREATE TABLE gtest21ax (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL, CONSTRAINT cc NOT NULL b); +INSERT INTO gtest21ax (a) VALUES (0); -- violates constraint +ERROR: null value in column "b" of relation "gtest21ax" violates not-null constraint +DETAIL: Failing row contains (0, virtual). +INSERT INTO gtest21ax (a) VALUES (1); --ok +-- SET EXPRESSION supports not null constraint +ALTER TABLE gtest21ax ALTER COLUMN b SET EXPRESSION AS (nullif(a, 1)); --error +ERROR: column "b" of relation "gtest21ax" contains null values +DROP TABLE gtest21ax; +CREATE TABLE gtest21ax (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL); +ALTER TABLE gtest21ax ADD CONSTRAINT cc NOT NULL b; +INSERT INTO gtest21ax (a) VALUES (0); -- violates constraint +ERROR: null value in column "b" of relation "gtest21ax" violates not-null constraint +DETAIL: Failing row contains (0, virtual). +DROP TABLE gtest21ax; +CREATE TABLE gtest21b (a int, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL); +ALTER TABLE gtest21b ALTER COLUMN b SET NOT NULL; +INSERT INTO gtest21b (a) VALUES (1); -- ok +INSERT INTO gtest21b (a) VALUES (2), (0); -- violates constraint +ERROR: null value in column "b" of relation "gtest21b" violates not-null constraint +DETAIL: Failing row contains (0, virtual). +INSERT INTO gtest21b (a) VALUES (NULL); -- error +ERROR: null value in column "b" of relation "gtest21b" violates not-null constraint +DETAIL: Failing row contains (null, virtual). +ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL; +INSERT INTO gtest21b (a) VALUES (0); -- ok now +-- not-null constraint with partitioned table +CREATE TABLE gtestnn_parent ( + f1 int, + f2 bigint, + f3 bigint GENERATED ALWAYS AS (nullif(f1, 1) + nullif(f2, 10)) VIRTUAL NOT NULL +) PARTITION BY RANGE (f1); +CREATE TABLE gtestnn_child PARTITION OF gtestnn_parent FOR VALUES FROM (1) TO (5); +CREATE TABLE gtestnn_childdef PARTITION OF gtestnn_parent default; +-- check the error messages +INSERT INTO gtestnn_parent VALUES (2, 2, default), (3, 5, default), (14, 12, default); -- ok +INSERT INTO gtestnn_parent VALUES (1, 2, default); -- error +ERROR: null value in column "f3" of relation "gtestnn_child" violates not-null constraint +DETAIL: Failing row contains (1, 2, virtual). +INSERT INTO gtestnn_parent VALUES (2, 10, default); -- error +ERROR: null value in column "f3" of relation "gtestnn_child" violates not-null constraint +DETAIL: Failing row contains (2, 10, virtual). +ALTER TABLE gtestnn_parent ALTER COLUMN f3 SET EXPRESSION AS (nullif(f1, 2) + nullif(f2, 11)); -- error +ERROR: column "f3" of relation "gtestnn_child" contains null values +INSERT INTO gtestnn_parent VALUES (10, 11, default); -- ok +SELECT * FROM gtestnn_parent ORDER BY f1, f2, f3; + f1 | f2 | f3 +----+----+---- + 2 | 2 | 4 + 3 | 5 | 8 + 10 | 11 | 21 + 14 | 12 | 26 +(4 rows) + +-- test ALTER TABLE ADD COLUMN +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 14) + nullif(f2, 10)) VIRTUAL; -- error +ERROR: column "c" of relation "gtestnn_childdef" contains null values +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 13) + nullif(f2, 5)) VIRTUAL; -- error +ERROR: column "c" of relation "gtestnn_child" contains null values +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 4) + nullif(f2, 6)) VIRTUAL; -- ok +-- index constraints +CREATE TABLE gtest22a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a / 2) VIRTUAL UNIQUE); +ERROR: unique constraints on virtual generated columns are not supported +--INSERT INTO gtest22a VALUES (2); +--INSERT INTO gtest22a VALUES (3); +--INSERT INTO gtest22a VALUES (4); +CREATE TABLE gtest22b (a int, b int GENERATED ALWAYS AS (a / 2) VIRTUAL, PRIMARY KEY (a, b)); +ERROR: primary keys on virtual generated columns are not supported +--INSERT INTO gtest22b VALUES (2); +--INSERT INTO gtest22b VALUES (2); +-- indexes +CREATE TABLE gtest22c (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +--CREATE INDEX gtest22c_b_idx ON gtest22c (b); +--CREATE INDEX gtest22c_expr_idx ON gtest22c ((b * 3)); +--CREATE INDEX gtest22c_pred_idx ON gtest22c (a) WHERE b > 0; +--\d gtest22c +--INSERT INTO gtest22c VALUES (1), (2), (3); +--SET enable_seqscan TO off; +--SET enable_bitmapscan TO off; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 4; +--SELECT * FROM gtest22c WHERE b = 4; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 6; +--SELECT * FROM gtest22c WHERE b * 3 = 6; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--ALTER TABLE gtest22c ALTER COLUMN b SET EXPRESSION AS (a * 4); +--ANALYZE gtest22c; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 8; +--SELECT * FROM gtest22c WHERE b = 8; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 12; +--SELECT * FROM gtest22c WHERE b * 3 = 12; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--RESET enable_seqscan; +--RESET enable_bitmapscan; +-- foreign keys +CREATE TABLE gtest23a (x int PRIMARY KEY, y int); +--INSERT INTO gtest23a VALUES (1, 11), (2, 22), (3, 33); +CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x) ON UPDATE CASCADE); -- error +ERROR: invalid ON UPDATE action for foreign key constraint containing generated column +CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x) ON DELETE SET NULL); -- error +ERROR: invalid ON DELETE action for foreign key constraint containing generated column +CREATE TABLE gtest23b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x)); +ERROR: foreign key constraints on virtual generated columns are not supported +--\d gtest23b +--INSERT INTO gtest23b VALUES (1); -- ok +--INSERT INTO gtest23b VALUES (5); -- error +--ALTER TABLE gtest23b ALTER COLUMN b SET EXPRESSION AS (a * 5); -- error +--ALTER TABLE gtest23b ALTER COLUMN b SET EXPRESSION AS (a * 1); -- ok +--DROP TABLE gtest23b; +--DROP TABLE gtest23a; +CREATE TABLE gtest23p (x int, y int GENERATED ALWAYS AS (x * 2) VIRTUAL, PRIMARY KEY (y)); +ERROR: primary keys on virtual generated columns are not supported +--INSERT INTO gtest23p VALUES (1), (2), (3); +CREATE TABLE gtest23q (a int PRIMARY KEY, b int REFERENCES gtest23p (y)); +ERROR: relation "gtest23p" does not exist +--INSERT INTO gtest23q VALUES (1, 2); -- ok +--INSERT INTO gtest23q VALUES (2, 5); -- error +-- domains +CREATE DOMAIN gtestdomain1 AS int CHECK (VALUE < 10); +CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * 2) VIRTUAL); +ERROR: virtual generated column "b" cannot have a domain type +--INSERT INTO gtest24 (a) VALUES (4); -- ok +--INSERT INTO gtest24 (a) VALUES (6); -- error +CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); +CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) VIRTUAL); +ERROR: virtual generated column "b" cannot have a domain type +--INSERT INTO gtest24r (a) VALUES (4); -- ok +--INSERT INTO gtest24r (a) VALUES (6); -- error +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) VIRTUAL); +ERROR: virtual generated column "b" cannot have a domain type +--INSERT INTO gtest24nn (a) VALUES (4); -- ok +--INSERT INTO gtest24nn (a) VALUES (NULL); -- error +-- typed tables (currently not supported) +CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); +CREATE TABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) VIRTUAL); +ERROR: generated columns are not supported on typed tables +DROP TYPE gtest_type CASCADE; +-- partitioning cases +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint) PARTITION BY RANGE (f1); +CREATE TABLE gtest_child PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 2) VIRTUAL +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +ERROR: child column "f3" specifies generation expression +HINT: A child table column cannot be generated unless its parent column is. +CREATE TABLE gtest_child (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +ERROR: column "f3" in child table must not be a generated column +DROP TABLE gtest_parent, gtest_child; +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f1); +CREATE TABLE gtest_child PARTITION OF gtest_parent + FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- inherits gen expr +CREATE TABLE gtest_child2 PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 22) VIRTUAL -- overrides gen expr +) FOR VALUES FROM ('2016-08-01') TO ('2016-09-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 DEFAULT 42 -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +ERROR: column "f3" inherits from generated column but specifies default +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +ERROR: identity columns are not supported on partitions +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 GENERATED ALWAYS AS (f2 * 2) STORED -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +ERROR: column "f3" inherits from generated column of different kind +DETAIL: Parent column is VIRTUAL, child column is STORED. +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +ERROR: column "f3" in child table must be a generated column +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint DEFAULT 42); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +ERROR: column "f3" in child table must be a generated column +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +ERROR: table "gtest_child3" being attached contains an identity column "f3" +DETAIL: The new partition may not contain an identity column. +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +ERROR: column "f3" inherits from generated column of different kind +DETAIL: Parent column is VIRTUAL, child column is STORED. +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +\d gtest_child + Table "generated_virtual_tests.gtest_child" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 2) +Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') + +\d gtest_child2 + Table "generated_virtual_tests.gtest_child2" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------- + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 22) +Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') + +\d gtest_child3 + Table "generated_virtual_tests.gtest_child3" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------- + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 33) +Partition of: gtest_parent FOR VALUES FROM ('09-01-2016') TO ('10-01-2016') + +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 1); +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 2); +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-08-15', 3); +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child | 07-15-2016 | 1 | 2 + gtest_child | 07-15-2016 | 2 | 4 + gtest_child2 | 08-15-2016 | 3 | 6 +(3 rows) + +SELECT tableoid::regclass, * FROM gtest_child ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +-------------+------------+----+---- + gtest_child | 07-15-2016 | 1 | 2 + gtest_child | 07-15-2016 | 2 | 4 +(2 rows) + +SELECT tableoid::regclass, * FROM gtest_child2 ORDER BY 1, 2, 3; -- uses child's generation expression, not parent's + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child2 | 08-15-2016 | 3 | 66 +(1 row) + +SELECT tableoid::regclass, * FROM gtest_child3 ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +----------+----+----+---- +(0 rows) + +UPDATE gtest_parent SET f1 = f1 + 60 WHERE f2 = 1; +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child | 07-15-2016 | 2 | 4 + gtest_child2 | 08-15-2016 | 3 | 6 + gtest_child3 | 09-13-2016 | 1 | 2 +(3 rows) + +-- alter only parent's and one child's generation expression +ALTER TABLE ONLY gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 4); +ALTER TABLE gtest_child ALTER COLUMN f3 SET EXPRESSION AS (f2 * 10); +\d gtest_parent + Partitioned table "generated_virtual_tests.gtest_parent" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 4) +Partition key: RANGE (f1) +Number of partitions: 3 (Use \d+ to list them.) + +\d gtest_child + Table "generated_virtual_tests.gtest_child" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------- + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 10) +Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') + +\d gtest_child2 + Table "generated_virtual_tests.gtest_child2" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------- + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 22) +Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') + +\d gtest_child3 + Table "generated_virtual_tests.gtest_child3" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------- + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 33) +Partition of: gtest_parent FOR VALUES FROM ('09-01-2016') TO ('10-01-2016') + +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child | 07-15-2016 | 2 | 8 + gtest_child2 | 08-15-2016 | 3 | 12 + gtest_child3 | 09-13-2016 | 1 | 4 +(3 rows) + +-- alter generation expression of parent and all its children altogether +ALTER TABLE gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 2); +\d gtest_parent + Partitioned table "generated_virtual_tests.gtest_parent" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 2) +Partition key: RANGE (f1) +Number of partitions: 3 (Use \d+ to list them.) + +\d gtest_child + Table "generated_virtual_tests.gtest_child" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 2) +Partition of: gtest_parent FOR VALUES FROM ('07-01-2016') TO ('08-01-2016') + +\d gtest_child2 + Table "generated_virtual_tests.gtest_child2" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 2) +Partition of: gtest_parent FOR VALUES FROM ('08-01-2016') TO ('09-01-2016') + +\d gtest_child3 + Table "generated_virtual_tests.gtest_child3" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+------------------------------ + f1 | date | | not null | + f2 | bigint | | | + f3 | bigint | | | generated always as (f2 * 2) +Partition of: gtest_parent FOR VALUES FROM ('09-01-2016') TO ('10-01-2016') + +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + tableoid | f1 | f2 | f3 +--------------+------------+----+---- + gtest_child | 07-15-2016 | 2 | 4 + gtest_child2 | 08-15-2016 | 3 | 6 + gtest_child3 | 09-13-2016 | 1 | 2 +(3 rows) + +-- we leave these tables around for purposes of testing dump/reload/upgrade +-- generated columns in partition key (not allowed) +CREATE TABLE gtest_part_key (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f3); +ERROR: cannot use generated column in partition key +LINE 1: ...NERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f3); + ^ +DETAIL: Column "f3" is a generated column. +CREATE TABLE gtest_part_key (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE ((f3 * 3)); +ERROR: cannot use generated column in partition key +LINE 1: ...D ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE ((f3 * 3)); + ^ +DETAIL: Column "f3" is a generated column. +-- ALTER TABLE ... ADD COLUMN +CREATE TABLE gtest25 (a int PRIMARY KEY); +INSERT INTO gtest25 VALUES (3), (4); +ALTER TABLE gtest25 ADD COLUMN b int GENERATED ALWAYS AS (a * 2) VIRTUAL, ALTER COLUMN b SET EXPRESSION AS (a * 3); +SELECT * FROM gtest25 ORDER BY a; + a | b +---+---- + 3 | 9 + 4 | 12 +(2 rows) + +ALTER TABLE gtest25 ADD COLUMN x int GENERATED ALWAYS AS (b * 4) VIRTUAL; -- error +ERROR: cannot use generated column "b" in column generation expression +DETAIL: A generated column cannot reference another generated column. +ALTER TABLE gtest25 ADD COLUMN x int GENERATED ALWAYS AS (z * 4) VIRTUAL; -- error +ERROR: column "z" does not exist +ALTER TABLE gtest25 ADD COLUMN c int DEFAULT 42, + ADD COLUMN x int GENERATED ALWAYS AS (c * 4) VIRTUAL; +ALTER TABLE gtest25 ADD COLUMN d int DEFAULT 101; +ALTER TABLE gtest25 ALTER COLUMN d SET DATA TYPE float8, + ADD COLUMN y float8 GENERATED ALWAYS AS (d * 4) VIRTUAL; +SELECT * FROM gtest25 ORDER BY a; + a | b | c | x | d | y +---+----+----+-----+-----+----- + 3 | 9 | 42 | 168 | 101 | 404 + 4 | 12 | 42 | 168 | 101 | 404 +(2 rows) + +\d gtest25 + Table "generated_virtual_tests.gtest25" + Column | Type | Collation | Nullable | Default +--------+------------------+-----------+----------+----------------------------------------------- + a | integer | | not null | + b | integer | | | generated always as (a * 3) + c | integer | | | 42 + x | integer | | | generated always as (c * 4) + d | double precision | | | 101 + y | double precision | | | generated always as (d * 4::double precision) +Indexes: + "gtest25_pkey" PRIMARY KEY, btree (a) + +-- ALTER TABLE ... ALTER COLUMN +CREATE TABLE gtest27 ( + a int, + b int, + x int GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL +); +INSERT INTO gtest27 (a, b) VALUES (3, 7), (4, 11); +ALTER TABLE gtest27 ALTER COLUMN a TYPE text; -- error +ERROR: cannot alter type of a column used by a generated column +DETAIL: Column "a" is used by generated column "x". +ALTER TABLE gtest27 ALTER COLUMN x TYPE numeric; +\d gtest27 + Table "generated_virtual_tests.gtest27" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+------------------------------------- + a | integer | | | + b | integer | | | + x | numeric | | | generated always as (((a + b) * 2)) + +SELECT * FROM gtest27; + a | b | x +---+----+---- + 3 | 7 | 20 + 4 | 11 | 30 +(2 rows) + +ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0; -- error +ERROR: cannot specify USING when altering type of generated column +LINE 1: ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0... + ^ +DETAIL: Column "x" is a generated column. +ALTER TABLE gtest27 ALTER COLUMN x DROP DEFAULT; -- error +ERROR: column "x" of relation "gtest27" is a generated column +-- test not-null checking during table rewrite +INSERT INTO gtest27 (a, b) VALUES (NULL, NULL); +ALTER TABLE gtest27 + DROP COLUMN x, + ALTER COLUMN a TYPE bigint, + ALTER COLUMN b TYPE bigint, + ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL NOT NULL; -- error +ERROR: column "x" of relation "gtest27" contains null values +DELETE FROM gtest27 WHERE a IS NULL AND b IS NULL; +-- It's possible to alter the column types this way: +ALTER TABLE gtest27 + DROP COLUMN x, + ALTER COLUMN a TYPE bigint, + ALTER COLUMN b TYPE bigint, + ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL; +\d gtest27 + Table "generated_virtual_tests.gtest27" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+----------------------------------- + a | bigint | | | + b | bigint | | | + x | bigint | | | generated always as ((a + b) * 2) + +-- Ideally you could just do this, but not today (and should x change type?): +ALTER TABLE gtest27 + ALTER COLUMN a TYPE float8, + ALTER COLUMN b TYPE float8; -- error +ERROR: cannot alter type of a column used by a generated column +DETAIL: Column "a" is used by generated column "x". +\d gtest27 + Table "generated_virtual_tests.gtest27" + Column | Type | Collation | Nullable | Default +--------+--------+-----------+----------+----------------------------------- + a | bigint | | | + b | bigint | | | + x | bigint | | | generated always as ((a + b) * 2) + +SELECT * FROM gtest27; + a | b | x +---+----+---- + 3 | 7 | 20 + 4 | 11 | 30 +(2 rows) + +-- ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION +CREATE TABLE gtest29 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +INSERT INTO gtest29 (a) VALUES (3), (4); +SELECT * FROM gtest29; + a | b +---+--- + 3 | 6 + 4 | 8 +(2 rows) + +\d gtest29 + Table "generated_virtual_tests.gtest29" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 2) + +ALTER TABLE gtest29 ALTER COLUMN a SET EXPRESSION AS (a * 3); -- error +ERROR: column "a" of relation "gtest29" is not a generated column +ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION; -- error +ERROR: column "a" of relation "gtest29" is not a generated column +ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION IF EXISTS; -- notice +NOTICE: column "a" of relation "gtest29" is not a generated column, skipping +-- Change the expression +ALTER TABLE gtest29 ALTER COLUMN b SET EXPRESSION AS (a * 3); +SELECT * FROM gtest29; + a | b +---+---- + 3 | 9 + 4 | 12 +(2 rows) + +\d gtest29 + Table "generated_virtual_tests.gtest29" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 3) + +ALTER TABLE gtest29 ALTER COLUMN b DROP EXPRESSION; -- not supported +ERROR: ALTER TABLE / DROP EXPRESSION is not supported for virtual generated columns +DETAIL: Column "b" of relation "gtest29" is a virtual generated column. +INSERT INTO gtest29 (a) VALUES (5); +INSERT INTO gtest29 (a, b) VALUES (6, 66); +ERROR: cannot insert a non-DEFAULT value into column "b" +DETAIL: Column "b" is a generated column. +SELECT * FROM gtest29; + a | b +---+---- + 3 | 9 + 4 | 12 + 5 | 15 +(3 rows) + +\d gtest29 + Table "generated_virtual_tests.gtest29" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 3) + +-- check that dependencies between columns have also been removed +--ALTER TABLE gtest29 DROP COLUMN a; -- should not drop b +--\d gtest29 +-- with inheritance +CREATE TABLE gtest30 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +CREATE TABLE gtest30_1 () INHERITS (gtest30); +ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION; +ERROR: ALTER TABLE / DROP EXPRESSION is not supported for virtual generated columns +DETAIL: Column "b" of relation "gtest30" is a virtual generated column. +\d gtest30 + Table "generated_virtual_tests.gtest30" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 2) +Number of child tables: 1 (Use \d+ to list them.) + +\d gtest30_1 + Table "generated_virtual_tests.gtest30_1" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 2) +Inherits: gtest30 + +DROP TABLE gtest30 CASCADE; +NOTICE: drop cascades to table gtest30_1 +CREATE TABLE gtest30 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +CREATE TABLE gtest30_1 () INHERITS (gtest30); +ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error +ERROR: ALTER TABLE / DROP EXPRESSION must be applied to child tables too +\d gtest30 + Table "generated_virtual_tests.gtest30" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 2) +Number of child tables: 1 (Use \d+ to list them.) + +\d gtest30_1 + Table "generated_virtual_tests.gtest30_1" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + a | integer | | | + b | integer | | | generated always as (a * 2) +Inherits: gtest30 + +ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error +ERROR: cannot drop generation expression from inherited column +-- composite type dependencies +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') VIRTUAL, c text); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +ERROR: cannot alter table "gtest31_1" because column "gtest31_2.y" uses its row type +DROP TABLE gtest31_1, gtest31_2; +-- Check it for a partitioned table, too +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') VIRTUAL, c text) PARTITION BY LIST (a); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +ERROR: cannot alter table "gtest31_1" because column "gtest31_2.y" uses its row type +DROP TABLE gtest31_1, gtest31_2; +-- triggers +CREATE TABLE gtest26 ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +CREATE FUNCTION gtest_trigger_func() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + IF tg_op IN ('DELETE', 'UPDATE') THEN + RAISE INFO '%: %: old = %', TG_NAME, TG_WHEN, OLD; + END IF; + IF tg_op IN ('INSERT', 'UPDATE') THEN + RAISE INFO '%: %: new = %', TG_NAME, TG_WHEN, NEW; + END IF; + IF tg_op = 'DELETE' THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; +END +$$; +CREATE TRIGGER gtest1 BEFORE DELETE OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (OLD.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); +CREATE TRIGGER gtest2a BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.b < 0) -- error + EXECUTE PROCEDURE gtest_trigger_func(); +ERROR: BEFORE trigger's WHEN condition cannot reference NEW generated columns +LINE 3: WHEN (NEW.b < 0) -- error + ^ +DETAIL: Column "b" is a generated column. +CREATE TRIGGER gtest2b BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.* IS NOT NULL) -- error + EXECUTE PROCEDURE gtest_trigger_func(); +ERROR: BEFORE trigger's WHEN condition cannot reference NEW generated columns +LINE 3: WHEN (NEW.* IS NOT NULL) -- error + ^ +DETAIL: A whole-row reference is used and the table contains generated columns. +CREATE TRIGGER gtest2 BEFORE INSERT ON gtest26 + FOR EACH ROW + WHEN (NEW.a < 0) + EXECUTE PROCEDURE gtest_trigger_func(); +CREATE TRIGGER gtest3 AFTER DELETE OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (OLD.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); +CREATE TRIGGER gtest4 AFTER INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); +INSERT INTO gtest26 (a) VALUES (-2), (0), (3); +INFO: gtest2: BEFORE: new = (-2,) +INFO: gtest4: AFTER: new = (-2,) +SELECT * FROM gtest26 ORDER BY a; + a | b +----+---- + -2 | -4 + 0 | 0 + 3 | 6 +(3 rows) + +UPDATE gtest26 SET a = a * -2; +INFO: gtest1: BEFORE: old = (-2,) +INFO: gtest1: BEFORE: new = (4,) +INFO: gtest3: AFTER: old = (-2,) +INFO: gtest3: AFTER: new = (4,) +INFO: gtest4: AFTER: old = (3,) +INFO: gtest4: AFTER: new = (-6,) +SELECT * FROM gtest26 ORDER BY a; + a | b +----+----- + -6 | -12 + 0 | 0 + 4 | 8 +(3 rows) + +DELETE FROM gtest26 WHERE a = -6; +INFO: gtest1: BEFORE: old = (-6,) +INFO: gtest3: AFTER: old = (-6,) +SELECT * FROM gtest26 ORDER BY a; + a | b +---+--- + 0 | 0 + 4 | 8 +(2 rows) + +DROP TRIGGER gtest1 ON gtest26; +DROP TRIGGER gtest2 ON gtest26; +DROP TRIGGER gtest3 ON gtest26; +-- Check that an UPDATE of "a" fires the trigger for UPDATE OF b, per +-- SQL standard. +CREATE FUNCTION gtest_trigger_func3() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + RAISE NOTICE 'OK'; + RETURN NEW; +END +$$; +CREATE TRIGGER gtest11 BEFORE UPDATE OF b ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func3(); +UPDATE gtest26 SET a = 1 WHERE a = 0; +NOTICE: OK +DROP TRIGGER gtest11 ON gtest26; +TRUNCATE gtest26; +-- check that modifications of generated columns in triggers do +-- not get propagated +CREATE FUNCTION gtest_trigger_func4() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + NEW.a = 10; + NEW.b = 300; + RETURN NEW; +END; +$$; +CREATE TRIGGER gtest12_01 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func(); +CREATE TRIGGER gtest12_02 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func4(); +CREATE TRIGGER gtest12_03 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func(); +INSERT INTO gtest26 (a) VALUES (1); +INFO: gtest12_01: BEFORE: new = (1,) +INFO: gtest12_03: BEFORE: new = (10,) +SELECT * FROM gtest26 ORDER BY a; + a | b +----+---- + 10 | 20 +(1 row) + +UPDATE gtest26 SET a = 11 WHERE a = 10; +INFO: gtest12_01: BEFORE: old = (10,) +INFO: gtest12_01: BEFORE: new = (11,) +INFO: gtest12_03: BEFORE: old = (10,) +INFO: gtest12_03: BEFORE: new = (10,) +SELECT * FROM gtest26 ORDER BY a; + a | b +----+---- + 10 | 20 +(1 row) + +-- LIKE INCLUDING GENERATED and dropped column handling +CREATE TABLE gtest28a ( + a int, + b int, + c int, + x int GENERATED ALWAYS AS (b * 2) VIRTUAL +); +ALTER TABLE gtest28a DROP COLUMN a; +CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); +\d gtest28* + Table "generated_virtual_tests.gtest28a" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + b | integer | | | + c | integer | | | + x | integer | | | generated always as (b * 2) + + Table "generated_virtual_tests.gtest28b" + Column | Type | Collation | Nullable | Default +--------+---------+-----------+----------+----------------------------- + b | integer | | | + c | integer | | | + x | integer | | | generated always as (b * 2) + +-- sanity check of system catalog +SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's', 'v'); + attrelid | attname | attgenerated +----------+---------+-------------- +(0 rows) + +-- +-- test the expansion of virtual generated columns +-- +-- these tests are specific to generated_virtual.sql +-- +create table gtest32 ( + a int primary key, + b int generated always as (a * 2), + c int generated always as (10 + 10), + d int generated always as (coalesce(a, 100)) +); +insert into gtest32 values (1), (2); +analyze gtest32; +-- Ensure that nullingrel bits are propagated into the generation expressions +explain (costs off) +select sum(t2.b) over (partition by t2.a), + sum(t2.c) over (partition by t2.a), + sum(t2.d) over (partition by t2.a) +from gtest32 as t1 left join gtest32 as t2 on (t1.a = t2.a) +order by t1.a; + QUERY PLAN +------------------------------------------------------ + Sort + Sort Key: t1.a + -> WindowAgg + Window: w1 AS (PARTITION BY t2.a) + -> Sort + Sort Key: t2.a + -> Nested Loop Left Join + Join Filter: (t1.a = t2.a) + -> Seq Scan on gtest32 t1 + -> Materialize + -> Seq Scan on gtest32 t2 +(11 rows) + +select sum(t2.b) over (partition by t2.a), + sum(t2.c) over (partition by t2.a), + sum(t2.d) over (partition by t2.a) +from gtest32 as t1 left join gtest32 as t2 on (t1.a = t2.a) +order by t1.a; + sum | sum | sum +-----+-----+----- + 2 | 20 | 1 + 4 | 20 | 2 +(2 rows) + +-- Ensure that outer-join removal functions correctly after the propagation of nullingrel bits +explain (costs off) +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2; + QUERY PLAN +----------------------------------------- + Hash Left Join + Hash Cond: (t1.a = t2.a) + Filter: (COALESCE((t2.a * 2), 1) = 2) + -> Seq Scan on gtest32 t1 + -> Hash + -> Seq Scan on gtest32 t2 +(6 rows) + +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2; + a +--- + 1 +(1 row) + +explain (costs off) +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2 or t1.a is null; + QUERY PLAN +------------------------------------------------------------- + Hash Left Join + Hash Cond: (t1.a = t2.a) + Filter: ((COALESCE((t2.a * 2), 1) = 2) OR (t1.a IS NULL)) + -> Seq Scan on gtest32 t1 + -> Hash + -> Seq Scan on gtest32 t2 +(6 rows) + +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2 or t1.a is null; + a +--- + 1 +(1 row) + +-- Ensure that the generation expressions are wrapped into PHVs if needed +explain (verbose, costs off) +select t2.* from gtest32 t1 left join gtest32 t2 on false; + QUERY PLAN +------------------------------------------------------ + Nested Loop Left Join + Output: a, (a * 2), (20), (COALESCE(a, 100)) + Join Filter: false + -> Seq Scan on generated_virtual_tests.gtest32 t1 + Output: t1.a, t1.b, t1.c, t1.d + -> Result + Output: a, 20, COALESCE(a, 100) + One-Time Filter: false +(8 rows) + +select t2.* from gtest32 t1 left join gtest32 t2 on false; + a | b | c | d +---+---+---+--- + | | | + | | | +(2 rows) + +explain (verbose, costs off) +select * from gtest32 t group by grouping sets (a, b, c, d) having c = 20; + QUERY PLAN +----------------------------------------------------- + HashAggregate + Output: a, ((a * 2)), (20), (COALESCE(a, 100)) + Hash Key: t.a + Hash Key: (t.a * 2) + Hash Key: 20 + Hash Key: COALESCE(t.a, 100) + Filter: ((20) = 20) + -> Seq Scan on generated_virtual_tests.gtest32 t + Output: a, (a * 2), 20, COALESCE(a, 100) +(9 rows) + +select * from gtest32 t group by grouping sets (a, b, c, d) having c = 20; + a | b | c | d +---+---+----+--- + | | 20 | +(1 row) + +drop table gtest32; diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 0af464309ee97..118bc26d8cd24 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -187,16 +187,16 @@ from lateral execute_text_query_heap($$select string_agg((i, j)::text, ' ') from t_gin_test_tbl where $$ || query) res_heap; query | return by index | removed by recheck | match -------------------------------------------+-----------------+--------------------+------- - i @> '{}' | 7 | 0 | t - j @> '{}' | 6 | 0 | t - i @> '{}' and j @> '{}' | 4 | 0 | t - i @> '{1}' | 5 | 0 | t - i @> '{1}' and j @> '{}' | 3 | 0 | t - i @> '{1}' and i @> '{}' and j @> '{}' | 3 | 0 | t - j @> '{10}' | 4 | 0 | t - j @> '{10}' and i @> '{}' | 3 | 0 | t - j @> '{10}' and j @> '{}' and i @> '{}' | 3 | 0 | t - i @> '{1}' and j @> '{10}' | 2 | 0 | t + i @> '{}' | 7.00 | 0 | t + j @> '{}' | 6.00 | 0 | t + i @> '{}' and j @> '{}' | 4.00 | 0 | t + i @> '{1}' | 5.00 | 0 | t + i @> '{1}' and j @> '{}' | 3.00 | 0 | t + i @> '{1}' and i @> '{}' and j @> '{}' | 3.00 | 0 | t + j @> '{10}' | 4.00 | 0 | t + j @> '{10}' and i @> '{}' | 3.00 | 0 | t + j @> '{10}' and j @> '{}' and i @> '{}' | 3.00 | 0 | t + i @> '{1}' and j @> '{10}' | 2.00 | 0 | t (10 rows) reset enable_seqscan; diff --git a/src/test/regress/expected/groupingsets.out b/src/test/regress/expected/groupingsets.out index e1f06608104e9..35e4cb47ebed5 100644 --- a/src/test/regress/expected/groupingsets.out +++ b/src/test/regress/expected/groupingsets.out @@ -434,6 +434,35 @@ select x, not x as not_x, q2 from | | 4567890123456789 (5 rows) +select x, y + from (select four as x, four as y from tenk1) as t + group by grouping sets (x, y) + having y is null + order by 1, 2; + x | y +---+--- + 0 | + 1 | + 2 | + 3 | +(4 rows) + +select x, y || 'y' + from (select four as x, four as y from tenk1) as t + group by grouping sets (x, y) + order by 1, 2; + x | ?column? +---+---------- + 0 | + 1 | + 2 | + 3 | + | 0y + | 1y + | 2y + | 3y +(8 rows) + -- check qual push-down rules for a subquery with grouping sets explain (verbose, costs off) select * from ( @@ -442,19 +471,22 @@ select * from ( group by grouping sets(1, 2) ) ss where x = 1 and q1 = 123; - QUERY PLAN --------------------------------------------- + QUERY PLAN +-------------------------------------------------- Subquery Scan on ss Output: ss.x, ss.q1, ss.sum Filter: ((ss.x = 1) AND (ss.q1 = 123)) -> GroupAggregate Output: (1), i1.q1, sum(i1.q2) - Group Key: 1 + Group Key: (1) Sort Key: i1.q1 Group Key: i1.q1 - -> Seq Scan on public.int8_tbl i1 - Output: 1, i1.q1, i1.q2 -(10 rows) + -> Sort + Output: (1), i1.q1, i1.q2 + Sort Key: (1) + -> Seq Scan on public.int8_tbl i1 + Output: 1, i1.q1, i1.q2 +(13 rows) select * from ( select 1 as x, q1, sum(q2) @@ -736,15 +768,18 @@ select a, b, sum(v.x) -- Test reordering of grouping sets explain (costs off) select * from gstest1 group by grouping sets((a,b,v),(v)) order by v,b,a; - QUERY PLAN ------------------------------------------------------------------------------- - GroupAggregate - Group Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1 - Group Key: "*VALUES*".column3 - -> Sort - Sort Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1 - -> Values Scan on "*VALUES*" -(6 rows) + QUERY PLAN +------------------------------------------------------------------------------------ + Incremental Sort + Sort Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1 + Presorted Key: "*VALUES*".column3 + -> GroupAggregate + Group Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1 + Group Key: "*VALUES*".column3 + -> Sort + Sort Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1 + -> Values Scan on "*VALUES*" +(9 rows) -- Agg level check. This query should error out. select (select grouping(a,b) from gstest2) from gstest2 group by a,b; @@ -816,16 +851,18 @@ select a,count(*) from gstest2 group by rollup(a) having a is distinct from 1 or explain (costs off) select a,count(*) from gstest2 group by rollup(a) having a is distinct from 1 order by a; - QUERY PLAN ----------------------------------- - GroupAggregate - Group Key: a - Group Key: () - Filter: (a IS DISTINCT FROM 1) - -> Sort - Sort Key: a - -> Seq Scan on gstest2 -(7 rows) + QUERY PLAN +---------------------------------------- + Sort + Sort Key: a + -> GroupAggregate + Group Key: a + Group Key: () + Filter: (a IS DISTINCT FROM 1) + -> Sort + Sort Key: a + -> Seq Scan on gstest2 +(9 rows) select v.c, (select count(*) from gstest2 group by () having v.c) from (values (false),(true)) v(c) order by v.c; @@ -852,6 +889,27 @@ explain (costs off) -> Seq Scan on gstest2 (10 rows) +-- test pushdown of HAVING clause that does not reference any columns that are nullable by grouping sets +explain (costs off) +select a, b, count(*) from gstest2 group by grouping sets ((a, b), (a)) having a > 1 and b > 1; + QUERY PLAN +--------------------------------- + GroupAggregate + Group Key: a, b + Group Key: a + Filter: (b > 1) + -> Sort + Sort Key: a, b + -> Seq Scan on gstest2 + Filter: (a > 1) +(8 rows) + +select a, b, count(*) from gstest2 group by grouping sets ((a, b), (a)) having a > 1 and b > 1; + a | b | count +---+---+------- + 2 | 2 | 1 +(1 row) + -- HAVING with GROUPING queries select ten, grouping(ten) from onek group by grouping sets(ten) having grouping(ten) >= 0 @@ -1407,8 +1465,9 @@ explain (costs off) QUERY PLAN --------------------------------------------- Sort - Sort Key: (sum((sum(c))) OVER (?)), a, b + Sort Key: (sum((sum(c))) OVER w1), a, b -> WindowAgg + Window: w1 AS (ORDER BY a, b) -> Sort Sort Key: a, b -> MixedAggregate @@ -1417,7 +1476,7 @@ explain (costs off) Hash Key: b Group Key: () -> Seq Scan on gstest2 -(11 rows) +(12 rows) select a, b, sum(v.x) from (values (1),(2)) v(x), gstest_data(v.x) @@ -2150,4 +2209,276 @@ select (select grouping(v1)) from (values ((select 1))) v(v1) group by v1; 0 (1 row) +-- test handling of subqueries in grouping sets +create temp table gstest5(id integer primary key, v integer); +insert into gstest5 select i, i from generate_series(1,5)i; +explain (verbose, costs off) +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s +from gstest5 t1 +group by grouping sets(v, s) +order by case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end + nulls first; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: (GROUPING((SubPlan 1))), ((SubPlan 3)), (CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END), t1.v + Sort Key: (CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END) NULLS FIRST + -> HashAggregate + Output: GROUPING((SubPlan 1)), ((SubPlan 3)), CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END, t1.v + Hash Key: t1.v + Hash Key: (SubPlan 3) + -> Seq Scan on pg_temp.gstest5 t1 + Output: (SubPlan 3), t1.v, t1.id + SubPlan 3 + -> Bitmap Heap Scan on pg_temp.gstest5 t2 + Output: t1.v + Recheck Cond: (t2.id = t1.id) + -> Bitmap Index Scan on gstest5_pkey + Index Cond: (t2.id = t1.id) +(15 rows) + +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s +from gstest5 t1 +group by grouping sets(v, s) +order by case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end + nulls first; + grouping | s +----------+--- + 1 | + 1 | + 1 | + 1 | + 1 | + 0 | 1 + 0 | 2 + 0 | 3 + 0 | 4 + 0 | 5 +(10 rows) + +explain (verbose, costs off) +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s, + case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end as o +from gstest5 t1 +group by grouping sets(v, s) +order by o nulls first; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: (GROUPING((SubPlan 1))), ((SubPlan 3)), (CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END), t1.v + Sort Key: (CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END) NULLS FIRST + -> HashAggregate + Output: GROUPING((SubPlan 1)), ((SubPlan 3)), CASE WHEN (GROUPING((SubPlan 2)) = 0) THEN ((SubPlan 3)) ELSE NULL::integer END, t1.v + Hash Key: t1.v + Hash Key: (SubPlan 3) + -> Seq Scan on pg_temp.gstest5 t1 + Output: (SubPlan 3), t1.v, t1.id + SubPlan 3 + -> Bitmap Heap Scan on pg_temp.gstest5 t2 + Output: t1.v + Recheck Cond: (t2.id = t1.id) + -> Bitmap Index Scan on gstest5_pkey + Index Cond: (t2.id = t1.id) +(15 rows) + +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s, + case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end as o +from gstest5 t1 +group by grouping sets(v, s) +order by o nulls first; + grouping | s | o +----------+---+--- + 1 | | + 1 | | + 1 | | + 1 | | + 1 | | + 0 | 1 | 1 + 0 | 2 | 2 + 0 | 3 | 3 + 0 | 4 | 4 + 0 | 5 | 5 +(10 rows) + +-- test handling of expressions that should match lower target items +explain (costs off) +select a < b and b < 3 from (values (1, 2)) t(a, b) group by rollup(a < b and b < 3) having a < b and b < 3; + QUERY PLAN +----------------------------------- + MixedAggregate + Hash Key: ((1 < 2) AND (2 < 3)) + Group Key: () + Filter: (((1 < 2) AND (2 < 3))) + -> Result +(5 rows) + +select a < b and b < 3 from (values (1, 2)) t(a, b) group by rollup(a < b and b < 3) having a < b and b < 3; + ?column? +---------- + t +(1 row) + +explain (costs off) +select not a from (values(true)) t(a) group by rollup(not a) having not not a; + QUERY PLAN +------------------------------ + MixedAggregate + Hash Key: (NOT true) + Group Key: () + Filter: (NOT ((NOT true))) + -> Result +(5 rows) + +select not a from (values(true)) t(a) group by rollup(not a) having not not a; + ?column? +---------- + f +(1 row) + +-- test handling of expressions nullable by grouping sets +explain (costs off) +select distinct on (a, b) a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b; + QUERY PLAN +---------------------------------------------------------------- + Unique + -> Sort + Sort Key: "*VALUES*".column1, "*VALUES*".column2 + -> HashAggregate + Hash Key: "*VALUES*".column1, "*VALUES*".column2 + Hash Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + Filter: (column1 = column2) +(8 rows) + +select distinct on (a, b) a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b; + a | b +---+--- + 1 | 1 + 1 | + 2 | 2 + 2 | +(4 rows) + +explain (costs off) +select distinct on (a, b+1) a, b+1 +from (values (1, 0), (2, 1)) as t (a, b) where a = b+1 +group by grouping sets((a, b+1), (a)) +order by a, b+1; + QUERY PLAN +---------------------------------------------------------------------- + Unique + -> Sort + Sort Key: "*VALUES*".column1, (("*VALUES*".column2 + 1)) + -> HashAggregate + Hash Key: "*VALUES*".column1, ("*VALUES*".column2 + 1) + Hash Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + Filter: (column1 = (column2 + 1)) +(8 rows) + +select distinct on (a, b+1) a, b+1 +from (values (1, 0), (2, 1)) as t (a, b) where a = b+1 +group by grouping sets((a, b+1), (a)) +order by a, b+1; + a | ?column? +---+---------- + 1 | 1 + 1 | + 2 | 2 + 2 | +(4 rows) + +explain (costs off) +select a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b nulls first; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: "*VALUES*".column1, "*VALUES*".column2 NULLS FIRST + -> HashAggregate + Hash Key: "*VALUES*".column1, "*VALUES*".column2 + Hash Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + Filter: (column1 = column2) +(7 rows) + +select a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b nulls first; + a | b +---+--- + 1 | + 1 | 1 + 2 | + 2 | 2 +(4 rows) + +explain (costs off) +select 1 as one group by rollup(one) order by one nulls first; + QUERY PLAN +----------------------------- + Sort + Sort Key: (1) NULLS FIRST + -> MixedAggregate + Hash Key: 1 + Group Key: () + -> Result +(6 rows) + +select 1 as one group by rollup(one) order by one nulls first; + one +----- + + 1 +(2 rows) + +explain (costs off) +select a, b, row_number() over (order by a, b nulls first) +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)); + QUERY PLAN +-------------------------------------------------------------------------------------------- + WindowAgg + Window: w1 AS (ORDER BY "*VALUES*".column1, "*VALUES*".column2 ROWS UNBOUNDED PRECEDING) + -> Sort + Sort Key: "*VALUES*".column1, "*VALUES*".column2 NULLS FIRST + -> HashAggregate + Hash Key: "*VALUES*".column1, "*VALUES*".column2 + Hash Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + Filter: (column1 = column2) +(9 rows) + +select a, b, row_number() over (order by a, b nulls first) +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)); + a | b | row_number +---+---+------------ + 1 | | 1 + 1 | 1 | 2 + 2 | | 3 + 2 | 2 | 4 +(4 rows) + -- end diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out index 455b6d6c0ce54..7f9e29c765cf1 100644 --- a/src/test/regress/expected/guc.out +++ b/src/test/regress/expected/guc.out @@ -6,6 +6,10 @@ SHOW datestyle; Postgres, MDY (1 row) +-- Check output style of CamelCase enum options +SET intervalstyle to 'asd'; +ERROR: invalid value for parameter "IntervalStyle": "asd" +HINT: Available values: postgres, postgres_verbose, sql_standard, iso_8601. -- SET to some nondefault value SET vacuum_cost_delay TO 40; SET datestyle = 'ISO, YMD'; @@ -824,6 +828,27 @@ set default_with_oids to f; -- Should not allow to set it to true. set default_with_oids to t; ERROR: tables declared WITH OIDS are not supported +-- Test that disabling track_activities disables query ID reporting in +-- pg_stat_activity. +SET compute_query_id = on; +SET track_activities = on; +SELECT query_id IS NOT NULL AS qid_set FROM pg_stat_activity + WHERE pid = pg_backend_pid(); + qid_set +--------- + t +(1 row) + +SET track_activities = off; +SELECT query_id IS NOT NULL AS qid_set FROM pg_stat_activity + WHERE pid = pg_backend_pid(); + qid_set +--------- + f +(1 row) + +RESET track_activities; +RESET compute_query_id; -- Test GUC categories and flag patterns SELECT pg_settings_get_flags(NULL); pg_settings_get_flags diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out index 241713cc51e63..5ae93d8e8a515 100644 --- a/src/test/regress/expected/horology.out +++ b/src/test/regress/expected/horology.out @@ -1,11 +1,16 @@ -- -- HOROLOGY -- -SET DateStyle = 'Postgres, MDY'; -SHOW TimeZone; -- Many of these tests depend on the prevailing setting - TimeZone ----------- - PST8PDT +SHOW TimeZone; -- Many of these tests depend on the prevailing settings + TimeZone +--------------------- + America/Los_Angeles +(1 row) + +SHOW DateStyle; + DateStyle +--------------- + Postgres, MDY (1 row) -- @@ -100,7 +105,7 @@ SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'; ERROR: date/time field value out of range: "27/12/2001 04:05:06.789-08" LINE 1: SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'... ^ -HINT: Perhaps you need a different "datestyle" setting. +HINT: Perhaps you need a different "DateStyle" setting. set datestyle to dmy; SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'; timestamptz @@ -462,6 +467,15 @@ SELECT timestamp with time zone 'Y2001M12D27H04MM05S06.789-08'; ERROR: invalid input syntax for type timestamp with time zone: "Y2001M12D27H04MM05S06.789-08" LINE 1: SELECT timestamp with time zone 'Y2001M12D27H04MM05S06.789-0... ^ +-- More examples we used to accept and should not +SELECT timestamp with time zone 'J2452271 T X03456-08'; +ERROR: invalid input syntax for type timestamp with time zone: "J2452271 T X03456-08" +LINE 1: SELECT timestamp with time zone 'J2452271 T X03456-08'; + ^ +SELECT timestamp with time zone 'J2452271 T X03456.001e6-08'; +ERROR: invalid input syntax for type timestamp with time zone: "J2452271 T X03456.001e6-08" +LINE 1: SELECT timestamp with time zone 'J2452271 T X03456.001e6-08'... + ^ -- conflicting fields should throw errors SELECT date '1995-08-06 epoch'; ERROR: invalid input syntax for type date: "1995-08-06 epoch" @@ -1033,12 +1047,12 @@ SELECT d1 + interval '1 year' AS one_year FROM TIMESTAMPTZ_TBL; Sat Feb 14 17:32:01 1998 PST Sun Feb 15 17:32:01 1998 PST Mon Feb 16 17:32:01 1998 PST - Thu Feb 16 17:32:01 0096 PST BC - Sun Feb 16 17:32:01 0098 PST - Fri Feb 16 17:32:01 0598 PST - Wed Feb 16 17:32:01 1098 PST - Sun Feb 16 17:32:01 1698 PST - Fri Feb 16 17:32:01 1798 PST + Thu Feb 16 17:32:01 0096 LMT BC + Sun Feb 16 17:32:01 0098 LMT + Fri Feb 16 17:32:01 0598 LMT + Wed Feb 16 17:32:01 1098 LMT + Sun Feb 16 17:32:01 1698 LMT + Fri Feb 16 17:32:01 1798 LMT Wed Feb 16 17:32:01 1898 PST Mon Feb 16 17:32:01 1998 PST Sun Feb 16 17:32:01 2098 PST @@ -1104,12 +1118,12 @@ SELECT d1 - interval '1 year' AS one_year FROM TIMESTAMPTZ_TBL; Wed Feb 14 17:32:01 1996 PST Thu Feb 15 17:32:01 1996 PST Fri Feb 16 17:32:01 1996 PST - Mon Feb 16 17:32:01 0098 PST BC - Thu Feb 16 17:32:01 0096 PST - Tue Feb 16 17:32:01 0596 PST - Sun Feb 16 17:32:01 1096 PST - Thu Feb 16 17:32:01 1696 PST - Tue Feb 16 17:32:01 1796 PST + Mon Feb 16 17:32:01 0098 LMT BC + Thu Feb 16 17:32:01 0096 LMT + Tue Feb 16 17:32:01 0596 LMT + Sun Feb 16 17:32:01 1096 LMT + Thu Feb 16 17:32:01 1696 LMT + Tue Feb 16 17:32:01 1796 LMT Sun Feb 16 17:32:01 1896 PST Fri Feb 16 17:32:01 1996 PST Thu Feb 16 17:32:01 2096 PST @@ -2465,7 +2479,7 @@ SELECT '2020-10-05'::timestamptz > '2202020-10-05'::date as f; SELECT '4714-11-24 BC'::date::timestamptz; timestamptz --------------------------------- - Mon Nov 24 00:00:00 4714 PST BC + Mon Nov 24 00:00:00 4714 LMT BC (1 row) SET TimeZone = 'UTC-2'; @@ -3043,13 +3057,13 @@ RESET DateStyle; SELECT to_timestamp('0097/Feb/16 --> 08:14:30', 'YYYY/Mon/DD --> HH:MI:SS'); to_timestamp ------------------------------ - Sat Feb 16 08:14:30 0097 PST + Sat Feb 16 08:14:30 0097 LMT (1 row) SELECT to_timestamp('97/2/16 8:14:30', 'FMYYYY/FMMM/FMDD FMHH:FMMI:FMSS'); to_timestamp ------------------------------ - Sat Feb 16 08:14:30 0097 PST + Sat Feb 16 08:14:30 0097 LMT (1 row) SELECT to_timestamp('2011$03!18 23_38_15', 'YYYY-MM-DD HH24:MI:SS'); @@ -3086,7 +3100,7 @@ SELECT to_timestamp('My birthday-> Year: 1976, Month: May, Day: 16', SELECT to_timestamp('1,582nd VIII 21', 'Y,YYYth FMRM DD'); to_timestamp ------------------------------ - Sat Aug 21 00:00:00 1582 PST + Sat Aug 21 00:00:00 1582 LMT (1 row) SELECT to_timestamp('15 "text between quote marks" 98 54 45', @@ -3150,7 +3164,7 @@ SELECT to_timestamp('1997 AD 11 16', 'YYYY BC MM DD'); SELECT to_timestamp('1997 BC 11 16', 'YYYY BC MM DD'); to_timestamp --------------------------------- - Tue Nov 16 00:00:00 1997 PST BC + Tue Nov 16 00:00:00 1997 LMT BC (1 row) SELECT to_timestamp('1997 A.D. 11 16', 'YYYY B.C. MM DD'); @@ -3162,7 +3176,7 @@ SELECT to_timestamp('1997 A.D. 11 16', 'YYYY B.C. MM DD'); SELECT to_timestamp('1997 B.C. 11 16', 'YYYY B.C. MM DD'); to_timestamp --------------------------------- - Tue Nov 16 00:00:00 1997 PST BC + Tue Nov 16 00:00:00 1997 LMT BC (1 row) SELECT to_timestamp('9-1116', 'Y-MMDD'); @@ -3327,6 +3341,12 @@ SELECT to_timestamp('2011-12-18 11:38 MSK', 'YYYY-MM-DD HH12:MI TZ'); -- dyntz Sat Dec 17 23:38:00 2011 PST (1 row) +SELECT to_timestamp('2011-12-18 00:00 LMT', 'YYYY-MM-DD HH24:MI TZ'); -- dyntz + to_timestamp +------------------------------ + Sat Dec 17 23:52:58 2011 PST +(1 row) + SELECT to_timestamp('2011-12-18 11:38ESTFOO24', 'YYYY-MM-DD HH12:MITZFOOSS'); to_timestamp ------------------------------ @@ -3448,6 +3468,17 @@ SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; ERROR: date/time field value out of range: "2018-11-02 12:34:56.123456789" +SELECT i, to_timestamp('20181102123456123456', 'YYYYMMDDHH24MISSFF' || i) FROM generate_series(1, 6) i; + i | to_timestamp +---+------------------------------------- + 1 | Fri Nov 02 12:34:56.1 2018 PDT + 2 | Fri Nov 02 12:34:56.12 2018 PDT + 3 | Fri Nov 02 12:34:56.123 2018 PDT + 4 | Fri Nov 02 12:34:56.1235 2018 PDT + 5 | Fri Nov 02 12:34:56.12346 2018 PDT + 6 | Fri Nov 02 12:34:56.123456 2018 PDT +(6 rows) + SELECT to_date('1 4 1902', 'Q MM YYYY'); -- Q is ignored to_date ------------ @@ -3490,19 +3521,19 @@ SELECT to_date('-44-02-01 BC','YYYY-MM-DD BC'); SELECT to_timestamp('44-02-01 11:12:13 BC','YYYY-MM-DD HH24:MI:SS BC'); to_timestamp --------------------------------- - Fri Feb 01 11:12:13 0044 PST BC + Fri Feb 01 11:12:13 0044 LMT BC (1 row) SELECT to_timestamp('-44-02-01 11:12:13','YYYY-MM-DD HH24:MI:SS'); to_timestamp --------------------------------- - Fri Feb 01 11:12:13 0044 PST BC + Fri Feb 01 11:12:13 0044 LMT BC (1 row) SELECT to_timestamp('-44-02-01 11:12:13 BC','YYYY-MM-DD HH24:MI:SS BC'); to_timestamp ------------------------------ - Mon Feb 01 11:12:13 0044 PST + Mon Feb 01 11:12:13 0044 LMT (1 row) -- @@ -3738,6 +3769,14 @@ SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSSS'); -- ok SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSSS'); ERROR: date/time field value out of range: "2015-02-11 86400" +SELECT to_timestamp('1000000000,999', 'Y,YYY'); +ERROR: value for "Y,YYY" in source string is out of range +SELECT to_timestamp('0.-2147483648', 'SS.MS'); +ERROR: date/time field value out of range: "0.-2147483648" +SELECT to_timestamp('613566758', 'W'); +ERROR: date/time field value out of range: "613566758" +SELECT to_timestamp('2024 613566758 1', 'YYYY WW D'); +ERROR: date/time field value out of range: "2024 613566758 1" SELECT to_date('2016-13-10', 'YYYY-MM-DD'); ERROR: date/time field value out of range: "2016-13-10" SELECT to_date('2016-02-30', 'YYYY-MM-DD'); @@ -3778,6 +3817,14 @@ SELECT to_date('0000-02-01','YYYY-MM-DD'); -- allowed, though it shouldn't be 02-01-0001 BC (1 row) +SELECT to_date('100000000', 'CC'); +ERROR: date/time field value out of range: "100000000" +SELECT to_date('-100000000', 'CC'); +ERROR: date/time field value out of range: "-100000000" +SELECT to_date('-2147483648 01', 'CC YY'); +ERROR: date/time field value out of range: "-2147483648 01" +SELECT to_date('2147483647 01', 'CC YY'); +ERROR: date/time field value out of range: "2147483647 01" -- to_char's TZ format code produces zone abbrev if known SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ'); to_char diff --git a/src/test/regress/expected/identity.out b/src/test/regress/expected/identity.out index 3d554fe32767c..0398a19484f16 100644 --- a/src/test/regress/expected/identity.out +++ b/src/test/regress/expected/identity.out @@ -43,6 +43,8 @@ CREATE TABLE itest4 (a int, b text); ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- error, requires NOT NULL ERROR: column "a" of relation "itest4" must be declared NOT NULL before identity can be added ALTER TABLE itest4 ALTER COLUMN a SET NOT NULL; +ALTER TABLE itest4 ALTER COLUMN c ADD GENERATED ALWAYS AS IDENTITY; -- error, column c does not exist +ERROR: column "c" of relation "itest4" does not exist ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- ok ALTER TABLE itest4 ALTER COLUMN a DROP NOT NULL; -- error, disallowed ERROR: column "a" of relation "itest4" is an identity column @@ -578,6 +580,10 @@ TABLE itest8; f3 | integer | | not null | generated by default as identity | plain | | f4 | bigint | | not null | generated always as identity | plain | | f5 | bigint | | | | plain | | +Not-null constraints: + "itest8_f2_not_null" NOT NULL "f2" + "itest8_f3_not_null" NOT NULL "f3" + "itest8_f4_not_null" NOT NULL "f4" \d itest8_f2_seq Sequence "public.itest8_f2_seq" @@ -618,7 +624,7 @@ INSERT into pitest1_p1 (f1, f2) VALUES ('2016-07-3', 'from pitest1_p1'); CREATE TABLE pitest1_p2 (f3 bigint, f2 text, f1 date NOT NULL); INSERT INTO pitest1_p2 (f1, f2, f3) VALUES ('2016-08-2', 'before attaching', 100); ALTER TABLE pitest1 ATTACH PARTITION pitest1_p2 FOR VALUES FROM ('2016-08-01') TO ('2016-09-01'); -- requires NOT NULL constraint -ERROR: column "f3" in child table must be marked NOT NULL +ERROR: column "f3" in child table "pitest1_p2" must be marked NOT NULL ALTER TABLE pitest1_p2 ALTER COLUMN f3 SET NOT NULL; ALTER TABLE pitest1 ATTACH PARTITION pitest1_p2 FOR VALUES FROM ('2016-08-01') TO ('2016-09-01'); INSERT INTO pitest1_p2 (f1, f2) VALUES ('2016-08-3', 'from pitest1_p2'); @@ -905,3 +911,19 @@ SELECT * FROM itest16; DROP TABLE itest15; DROP TABLE itest16; +-- For testing of pg_dump and pg_upgrade, leave behind some identity +-- sequences whose logged-ness doesn't match their owning table's. +CREATE TABLE identity_dump_logged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_logged_a_seq SET UNLOGGED; +CREATE UNLOGGED TABLE identity_dump_unlogged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_unlogged_a_seq SET LOGGED; +SELECT relname, relpersistence FROM pg_class + WHERE relname ~ '^identity_dump_' ORDER BY 1; + relname | relpersistence +------------------------------+---------------- + identity_dump_logged | p + identity_dump_logged_a_seq | u + identity_dump_unlogged | u + identity_dump_unlogged_a_seq | p +(4 rows) + diff --git a/src/test/regress/expected/incremental_sort.out b/src/test/regress/expected/incremental_sort.out index 5fd54a10b1aaf..b00219643b9ad 100644 --- a/src/test/regress/expected/incremental_sort.out +++ b/src/test/regress/expected/incremental_sort.out @@ -39,7 +39,7 @@ declare line text; begin for line in - execute 'explain (analyze, costs off, summary off, timing off) ' || query + execute 'explain (analyze, costs off, summary off, timing off, buffers off) ' || query loop out_line := regexp_replace(line, '\d+kB', 'NNkB', 'g'); return next; @@ -55,7 +55,7 @@ declare element jsonb; matching_nodes jsonb := '[]'::jsonb; begin - execute 'explain (analyze, costs off, summary off, timing off, format ''json'') ' || query into strict elements; + execute 'explain (analyze, costs off, summary off, timing off, buffers off, format ''json'') ' || query into strict elements; while jsonb_array_length(elements) > 0 loop element := elements->0; elements := elements - 0; @@ -522,15 +522,15 @@ select * from (select * from t order by a) s order by a, b limit 55; select explain_analyze_without_memory('select * from (select * from t order by a) s order by a, b limit 55'); explain_analyze_without_memory --------------------------------------------------------------------------------------------------------------- - Limit (actual rows=55 loops=1) - -> Incremental Sort (actual rows=55 loops=1) + Limit (actual rows=55.00 loops=1) + -> Incremental Sort (actual rows=55.00 loops=1) Sort Key: t.a, t.b Presorted Key: t.a Full-sort Groups: 2 Sort Methods: top-N heapsort, quicksort Average Memory: NNkB Peak Memory: NNkB - -> Sort (actual rows=101 loops=1) + -> Sort (actual rows=101.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: NNkB - -> Seq Scan on t (actual rows=1000 loops=1) + -> Seq Scan on t (actual rows=1000.00 loops=1) (9 rows) select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from (select * from t order by a) s order by a, b limit 55')); @@ -538,12 +538,13 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from ------------------------------------------------- [ + { + + "Disabled": false, + "Sort Key": [ + "t.a", + "t.b" + ], + "Node Type": "Incremental Sort", + - "Actual Rows": 55, + + "Actual Rows": 55.00, + "Actual Loops": 1, + "Async Capable": false, + "Presorted Key": [ + @@ -708,9 +709,10 @@ explain (costs off) select * from t left join (select * from (select * from t or Sort Key: t_1.a, t_1.b Presorted Key: t_1.a -> Sort + Disabled: true Sort Key: t_1.a -> Seq Scan on t t_1 -(10 rows) +(11 rows) select * from t left join (select * from (select * from t order by a) v order by a, b) s on s.a = t.a where t.a in (1, 2); a | b | a | b @@ -724,16 +726,16 @@ rollback; select explain_analyze_without_memory('select * from (select * from t order by a) s order by a, b limit 70'); explain_analyze_without_memory ---------------------------------------------------------------------------------------------------------------- - Limit (actual rows=70 loops=1) - -> Incremental Sort (actual rows=70 loops=1) + Limit (actual rows=70.00 loops=1) + -> Incremental Sort (actual rows=70.00 loops=1) Sort Key: t.a, t.b Presorted Key: t.a Full-sort Groups: 1 Sort Method: quicksort Average Memory: NNkB Peak Memory: NNkB Pre-sorted Groups: 5 Sort Methods: top-N heapsort, quicksort Average Memory: NNkB Peak Memory: NNkB - -> Sort (actual rows=1000 loops=1) + -> Sort (actual rows=1000.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: NNkB - -> Seq Scan on t (actual rows=1000 loops=1) + -> Seq Scan on t (actual rows=1000.00 loops=1) (10 rows) select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from (select * from t order by a) s order by a, b limit 70')); @@ -741,12 +743,13 @@ select jsonb_pretty(explain_analyze_inc_sort_nodes_without_memory('select * from ------------------------------------------------- [ + { + + "Disabled": false, + "Sort Key": [ + "t.a", + "t.b" + ], + "Node Type": "Incremental Sort", + - "Actual Rows": 70, + + "Actual Rows": 70.00, + "Actual Loops": 1, + "Async Capable": false, + "Presorted Key": [ + @@ -1698,3 +1701,24 @@ explain (costs off) select a, b, a <-> point(5, 5) dist from point_table order b Order By: (a <-> '(5,5)'::point) (6 rows) +-- Ensure we get an incremental sort on the outer side of the mergejoin +explain (costs off) +select * from + (select * from tenk1 order by four) t1 join tenk1 t2 on t1.four = t2.four and t1.two = t2.two +order by t1.four, t1.two limit 1; + QUERY PLAN +----------------------------------------------------------------------- + Limit + -> Merge Join + Merge Cond: ((tenk1.four = t2.four) AND (tenk1.two = t2.two)) + -> Incremental Sort + Sort Key: tenk1.four, tenk1.two + Presorted Key: tenk1.four + -> Sort + Sort Key: tenk1.four + -> Seq Scan on tenk1 + -> Sort + Sort Key: t2.four, t2.two + -> Seq Scan on tenk1 t2 +(12 rows) + diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out index ea8b2454bf8cd..4e8fe49c8cfc3 100644 --- a/src/test/regress/expected/index_including.out +++ b/src/test/regress/expected/index_including.out @@ -113,7 +113,7 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary, i covering | 4 | 2 | t | t | 1 2 3 4 | 1978 1978 (1 row) -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid; +SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid AND contype = 'p'; pg_get_constraintdef | conname | conkey ---------------------------------------+----------+-------- PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | covering | {1,2} @@ -191,7 +191,7 @@ SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary, i tbl_pkey | 4 | 2 | t | t | 1 2 3 4 | 1978 1978 (1 row) -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid; +SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid AND contype = 'p'; pg_get_constraintdef | conname | conkey ---------------------------------------+----------+-------- PRIMARY KEY (c1, c2) INCLUDE (c3, c4) | tbl_pkey | {1,2} diff --git a/src/test/regress/expected/indexing.out b/src/test/regress/expected/indexing.out index f25723da92bdd..bcf1db11d731d 100644 --- a/src/test/regress/expected/indexing.out +++ b/src/test/regress/expected/indexing.out @@ -1117,15 +1117,27 @@ alter table idxpart attach partition idxpart3 for values from (20, 20) to (30, 3 select conname, contype, conrelid::regclass, conindid::regclass, conkey from pg_constraint where conrelid::regclass::text like 'idxpart%' order by conrelid::regclass::text, conname; - conname | contype | conrelid | conindid | conkey -----------------+---------+-----------+----------------+-------- - idxpart_pkey | p | idxpart | idxpart_pkey | {1,2} - idxpart1_pkey | p | idxpart1 | idxpart1_pkey | {1,2} - idxpart2_pkey | p | idxpart2 | idxpart2_pkey | {1,2} - idxpart21_pkey | p | idxpart21 | idxpart21_pkey | {1,2} - idxpart22_pkey | p | idxpart22 | idxpart22_pkey | {1,2} - idxpart3_pkey | p | idxpart3 | idxpart3_pkey | {2,1} -(6 rows) + conname | contype | conrelid | conindid | conkey +---------------------+---------+-----------+----------------+-------- + idxpart_a_not_null | n | idxpart | - | {1} + idxpart_b_not_null | n | idxpart | - | {2} + idxpart_pkey | p | idxpart | idxpart_pkey | {1,2} + idxpart1_pkey | p | idxpart1 | idxpart1_pkey | {1,2} + idxpart_a_not_null | n | idxpart1 | - | {1} + idxpart_b_not_null | n | idxpart1 | - | {2} + idxpart2_pkey | p | idxpart2 | idxpart2_pkey | {1,2} + idxpart_a_not_null | n | idxpart2 | - | {1} + idxpart_b_not_null | n | idxpart2 | - | {2} + idxpart21_pkey | p | idxpart21 | idxpart21_pkey | {1,2} + idxpart_a_not_null | n | idxpart21 | - | {1} + idxpart_b_not_null | n | idxpart21 | - | {2} + idxpart22_pkey | p | idxpart22 | idxpart22_pkey | {1,2} + idxpart_a_not_null | n | idxpart22 | - | {1} + idxpart_b_not_null | n | idxpart22 | - | {2} + idxpart3_a_not_null | n | idxpart3 | - | {2} + idxpart3_b_not_null | n | idxpart3 | - | {1} + idxpart3_pkey | p | idxpart3 | idxpart3_pkey | {2,1} +(18 rows) drop table idxpart; -- Verify that multi-layer partitioning honors the requirement that all @@ -1150,13 +1162,19 @@ create table idxpart2 partition of idxpart for values from (0) to (1000) partiti create table idxpart21 partition of idxpart2 for values from (0) to (1000); select conname, contype, conrelid::regclass, conindid::regclass, conkey from pg_constraint where conrelid::regclass::text like 'idxpart%' - order by conname; - conname | contype | conrelid | conindid | conkey -----------------+---------+-----------+----------------+-------- - idxpart21_pkey | p | idxpart21 | idxpart21_pkey | {1,2} - idxpart2_pkey | p | idxpart2 | idxpart2_pkey | {1,2} - idxpart_pkey | p | idxpart | idxpart_pkey | {1,2} -(3 rows) + order by conrelid::regclass::text, conname; + conname | contype | conrelid | conindid | conkey +--------------------+---------+-----------+----------------+-------- + idxpart_a_not_null | n | idxpart | - | {1} + idxpart_b_not_null | n | idxpart | - | {2} + idxpart_pkey | p | idxpart | idxpart_pkey | {1,2} + idxpart2_pkey | p | idxpart2 | idxpart2_pkey | {1,2} + idxpart_a_not_null | n | idxpart2 | - | {1} + idxpart_b_not_null | n | idxpart2 | - | {2} + idxpart21_pkey | p | idxpart21 | idxpart21_pkey | {1,2} + idxpart_a_not_null | n | idxpart21 | - | {1} + idxpart_b_not_null | n | idxpart21 | - | {2} +(9 rows) drop table idxpart; -- If a partitioned table has a unique/PK constraint, then it's not possible @@ -1259,14 +1277,10 @@ create table idxpart0 (like idxpart); alter table idxpart0 add unique (a); alter table idxpart attach partition idxpart0 default; alter table only idxpart add primary key (a); -- fail, no not-null constraint -ERROR: constraint must be added to child tables too -DETAIL: Column "a" of relation "idxpart0" is not already NOT NULL. -HINT: Do not specify the ONLY keyword. +ERROR: column "a" of table "idxpart0" is not marked NOT NULL alter table idxpart0 alter column a set not null; alter table only idxpart add primary key (a); -- now it works alter index idxpart_pkey attach partition idxpart0_a_key; -alter table idxpart0 alter column a drop not null; -- fail, pkey needs it -ERROR: column "a" is marked NOT NULL in parent table drop table idxpart; -- if a partition has a unique index without a constraint, does not attach -- automatically; creates a new index instead. @@ -1640,3 +1654,18 @@ select indexrelid::regclass, indisvalid, indisreplident, (3 rows) drop table parted_replica_tab; +-- test that indexing commands work with TOASTed values in pg_index +create table test_pg_index_toast_table (a int); +create or replace function test_pg_index_toast_func (a int, b int[]) + returns bool as $$ select true $$ language sql immutable; +select array_agg(n) b from generate_series(1, 10000) n \gset +create index concurrently test_pg_index_toast_index + on test_pg_index_toast_table (test_pg_index_toast_func(a, :'b')); +reindex index concurrently test_pg_index_toast_index; +drop index concurrently test_pg_index_toast_index; +create index test_pg_index_toast_index + on test_pg_index_toast_table (test_pg_index_toast_func(a, :'b')); +reindex index test_pg_index_toast_index; +drop index test_pg_index_toast_index; +drop function test_pg_index_toast_func; +drop table test_pg_index_toast_table; diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out index b6895d9ced07a..1705bff4dd3d1 100644 --- a/src/test/regress/expected/inet.out +++ b/src/test/regress/expected/inet.out @@ -88,31 +88,32 @@ SELECT i AS inet, host(i), text(i), family(i) FROM INET_TBL; ::4.3.2.1/24 | ::4.3.2.1 | ::4.3.2.1/24 | 6 (17 rows) -SELECT c AS cidr, abbrev(c) FROM INET_TBL; - cidr | abbrev ---------------------+-------------------- - 192.168.1.0/24 | 192.168.1/24 - 192.168.1.0/26 | 192.168.1.0/26 - 192.168.1.0/24 | 192.168.1/24 - 192.168.1.0/24 | 192.168.1/24 - 192.168.1.0/24 | 192.168.1/24 - 192.168.1.0/24 | 192.168.1/24 - 10.0.0.0/8 | 10/8 - 10.0.0.0/32 | 10.0.0.0/32 - 10.1.2.3/32 | 10.1.2.3/32 - 10.1.2.0/24 | 10.1.2/24 - 10.1.0.0/16 | 10.1/16 - 10.0.0.0/8 | 10/8 - 10.0.0.0/8 | 10/8 - 10.0.0.0/8 | 10/8 - 10:23::f1/128 | 10:23::f1/128 - 10:23::8000/113 | 10:23::8000/113 - ::ffff:1.2.3.4/128 | ::ffff:1.2.3.4/128 +SELECT c AS cidr, abbrev(c) AS "abbrev(cidr)", + i AS inet, abbrev(i) AS "abbrev(inet)" FROM INET_TBL; + cidr | abbrev(cidr) | inet | abbrev(inet) +--------------------+--------------------+------------------+------------------ + 192.168.1.0/24 | 192.168.1/24 | 192.168.1.226/24 | 192.168.1.226/24 + 192.168.1.0/26 | 192.168.1.0/26 | 192.168.1.226 | 192.168.1.226 + 192.168.1.0/24 | 192.168.1/24 | 192.168.1.0/24 | 192.168.1.0/24 + 192.168.1.0/24 | 192.168.1/24 | 192.168.1.0/25 | 192.168.1.0/25 + 192.168.1.0/24 | 192.168.1/24 | 192.168.1.255/24 | 192.168.1.255/24 + 192.168.1.0/24 | 192.168.1/24 | 192.168.1.255/25 | 192.168.1.255/25 + 10.0.0.0/8 | 10/8 | 10.1.2.3/8 | 10.1.2.3/8 + 10.0.0.0/32 | 10.0.0.0/32 | 10.1.2.3/8 | 10.1.2.3/8 + 10.1.2.3/32 | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3 + 10.1.2.0/24 | 10.1.2/24 | 10.1.2.3/24 | 10.1.2.3/24 + 10.1.0.0/16 | 10.1/16 | 10.1.2.3/16 | 10.1.2.3/16 + 10.0.0.0/8 | 10/8 | 10.1.2.3/8 | 10.1.2.3/8 + 10.0.0.0/8 | 10/8 | 11.1.2.3/8 | 11.1.2.3/8 + 10.0.0.0/8 | 10/8 | 9.1.2.3/8 | 9.1.2.3/8 + 10:23::f1/128 | 10:23::f1/128 | 10:23::f1/64 | 10:23::f1/64 + 10:23::8000/113 | 10:23::8000/113 | 10:23::ffff | 10:23::ffff + ::ffff:1.2.3.4/128 | ::ffff:1.2.3.4/128 | ::4.3.2.1/24 | ::4.3.2.1/24 (17 rows) -SELECT c AS cidr, broadcast(c), - i AS inet, broadcast(i) FROM INET_TBL; - cidr | broadcast | inet | broadcast +SELECT c AS cidr, broadcast(c) AS "broadcast(cidr)", + i AS inet, broadcast(i) AS "broadcast(inet)" FROM INET_TBL; + cidr | broadcast(cidr) | inet | broadcast(inet) --------------------+------------------+------------------+--------------------------------------- 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.226/24 | 192.168.1.255/24 192.168.1.0/26 | 192.168.1.63/26 | 192.168.1.226 | 192.168.1.226 @@ -190,6 +191,50 @@ SELECT c AS cidr, masklen(c) AS "masklen(cidr)", 10.0.0.0/8 | 8 | 9.1.2.3/8 | 8 (4 rows) +SELECT i AS inet, netmask(i) AS "netmask(inet)" FROM INET_TBL; + inet | netmask(inet) +------------------+----------------------------------------- + 192.168.1.226/24 | 255.255.255.0 + 192.168.1.226 | 255.255.255.255 + 192.168.1.0/24 | 255.255.255.0 + 192.168.1.0/25 | 255.255.255.128 + 192.168.1.255/24 | 255.255.255.0 + 192.168.1.255/25 | 255.255.255.128 + 10.1.2.3/8 | 255.0.0.0 + 10.1.2.3/8 | 255.0.0.0 + 10.1.2.3 | 255.255.255.255 + 10.1.2.3/24 | 255.255.255.0 + 10.1.2.3/16 | 255.255.0.0 + 10.1.2.3/8 | 255.0.0.0 + 11.1.2.3/8 | 255.0.0.0 + 9.1.2.3/8 | 255.0.0.0 + 10:23::f1/64 | ffff:ffff:ffff:ffff:: + 10:23::ffff | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + ::4.3.2.1/24 | ffff:ff00:: +(17 rows) + +SELECT i AS inet, hostmask(i) AS "hostmask(inet)" FROM INET_TBL; + inet | hostmask(inet) +------------------+------------------------------------ + 192.168.1.226/24 | 0.0.0.255 + 192.168.1.226 | 0.0.0.0 + 192.168.1.0/24 | 0.0.0.255 + 192.168.1.0/25 | 0.0.0.127 + 192.168.1.255/24 | 0.0.0.255 + 192.168.1.255/25 | 0.0.0.127 + 10.1.2.3/8 | 0.255.255.255 + 10.1.2.3/8 | 0.255.255.255 + 10.1.2.3 | 0.0.0.0 + 10.1.2.3/24 | 0.0.0.255 + 10.1.2.3/16 | 0.0.255.255 + 10.1.2.3/8 | 0.255.255.255 + 11.1.2.3/8 | 0.255.255.255 + 9.1.2.3/8 | 0.255.255.255 + 10:23::f1/64 | ::ffff:ffff:ffff:ffff + 10:23::ffff | :: + ::4.3.2.1/24 | 0:ff:ffff:ffff:ffff:ffff:ffff:ffff +(17 rows) + SELECT c AS cidr, i AS inet FROM INET_TBL WHERE c = i; cidr | inet @@ -238,29 +283,59 @@ SELECT max(c) AS max, min(c) AS min FROM INET_TBL; 10:23::8000/113 | 10.0.0.0/8 (1 row) --- check the conversion to/from text and set_netmask -SELECT set_masklen(inet(text(i)), 24) FROM INET_TBL; - set_masklen ------------------- - 192.168.1.226/24 - 192.168.1.226/24 - 192.168.1.0/24 - 192.168.1.0/24 - 192.168.1.255/24 - 192.168.1.255/24 - 10.1.2.3/24 - 10.1.2.3/24 - 10.1.2.3/24 - 10.1.2.3/24 - 10.1.2.3/24 - 10.1.2.3/24 - 11.1.2.3/24 - 9.1.2.3/24 - 10:23::f1/24 - 10:23::ffff/24 - ::4.3.2.1/24 +-- check the conversion to/from text and setting netmask +SELECT c AS cidr, set_masklen(cidr(text(c)), 24) AS "set_masklen(cidr)", + i AS inet, set_masklen(inet(text(i)), 24) AS "set_masklen(inet)" FROM INET_TBL; + cidr | set_masklen(cidr) | inet | set_masklen(inet) +--------------------+-------------------+------------------+------------------- + 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.226/24 | 192.168.1.226/24 + 192.168.1.0/26 | 192.168.1.0/24 | 192.168.1.226 | 192.168.1.226/24 + 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/24 + 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.0/25 | 192.168.1.0/24 + 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/24 | 192.168.1.255/24 + 192.168.1.0/24 | 192.168.1.0/24 | 192.168.1.255/25 | 192.168.1.255/24 + 10.0.0.0/8 | 10.0.0.0/24 | 10.1.2.3/8 | 10.1.2.3/24 + 10.0.0.0/32 | 10.0.0.0/24 | 10.1.2.3/8 | 10.1.2.3/24 + 10.1.2.3/32 | 10.1.2.0/24 | 10.1.2.3 | 10.1.2.3/24 + 10.1.2.0/24 | 10.1.2.0/24 | 10.1.2.3/24 | 10.1.2.3/24 + 10.1.0.0/16 | 10.1.0.0/24 | 10.1.2.3/16 | 10.1.2.3/24 + 10.0.0.0/8 | 10.0.0.0/24 | 10.1.2.3/8 | 10.1.2.3/24 + 10.0.0.0/8 | 10.0.0.0/24 | 11.1.2.3/8 | 11.1.2.3/24 + 10.0.0.0/8 | 10.0.0.0/24 | 9.1.2.3/8 | 9.1.2.3/24 + 10:23::f1/128 | 10::/24 | 10:23::f1/64 | 10:23::f1/24 + 10:23::8000/113 | 10::/24 | 10:23::ffff | 10:23::ffff/24 + ::ffff:1.2.3.4/128 | ::/24 | ::4.3.2.1/24 | ::4.3.2.1/24 +(17 rows) + +-- check that netmask is treated as maximum value when set to -1 +SELECT c AS cidr, set_masklen(cidr(text(c)), -1) AS "set_masklen(cidr)", + i AS inet, set_masklen(inet(text(i)), -1) AS "set_masklen(inet)" FROM INET_TBL; + cidr | set_masklen(cidr) | inet | set_masklen(inet) +--------------------+--------------------+------------------+------------------- + 192.168.1.0/24 | 192.168.1.0/32 | 192.168.1.226/24 | 192.168.1.226 + 192.168.1.0/26 | 192.168.1.0/32 | 192.168.1.226 | 192.168.1.226 + 192.168.1.0/24 | 192.168.1.0/32 | 192.168.1.0/24 | 192.168.1.0 + 192.168.1.0/24 | 192.168.1.0/32 | 192.168.1.0/25 | 192.168.1.0 + 192.168.1.0/24 | 192.168.1.0/32 | 192.168.1.255/24 | 192.168.1.255 + 192.168.1.0/24 | 192.168.1.0/32 | 192.168.1.255/25 | 192.168.1.255 + 10.0.0.0/8 | 10.0.0.0/32 | 10.1.2.3/8 | 10.1.2.3 + 10.0.0.0/32 | 10.0.0.0/32 | 10.1.2.3/8 | 10.1.2.3 + 10.1.2.3/32 | 10.1.2.3/32 | 10.1.2.3 | 10.1.2.3 + 10.1.2.0/24 | 10.1.2.0/32 | 10.1.2.3/24 | 10.1.2.3 + 10.1.0.0/16 | 10.1.0.0/32 | 10.1.2.3/16 | 10.1.2.3 + 10.0.0.0/8 | 10.0.0.0/32 | 10.1.2.3/8 | 10.1.2.3 + 10.0.0.0/8 | 10.0.0.0/32 | 11.1.2.3/8 | 11.1.2.3 + 10.0.0.0/8 | 10.0.0.0/32 | 9.1.2.3/8 | 9.1.2.3 + 10:23::f1/128 | 10:23::f1/128 | 10:23::f1/64 | 10:23::f1 + 10:23::8000/113 | 10:23::8000/128 | 10:23::ffff | 10:23::ffff + ::ffff:1.2.3.4/128 | ::ffff:1.2.3.4/128 | ::4.3.2.1/24 | ::4.3.2.1 (17 rows) +-- check that invalid netmask is rejected +SELECT set_masklen(inet(text(i)), 33) FROM INET_TBL; +ERROR: invalid mask length: 33 +SELECT set_masklen(cidr(text(c)), 33) FROM INET_TBL; +ERROR: invalid mask length: 33 -- check that btree index works correctly CREATE INDEX inet_idx1 ON inet_tbl(i); SET enable_seqscan TO off; diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index ad732134148ff..f9b0c415cfdcc 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -539,6 +539,9 @@ CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); INSERT INTO z VALUES (NULL, 'text'); -- should fail ERROR: null value in column "aa" of relation "z" violates not-null constraint DETAIL: Failing row contains (null, text). +-- ... but not UNIQUE. +CREATE TEMP TABLE z2 (b TEXT, UNIQUE(aa, b)) inherits (a); +INSERT INTO z2 VALUES (NULL, 'text'); -- should work -- Check inherited UPDATE with first child excluded create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit); create table some_tab_child () inherits(some_tab); @@ -1093,17 +1096,30 @@ CREATE TABLE inhta (); CREATE TABLE inhtb () INHERITS (inhta); CREATE TABLE inhtc () INHERITS (inhtb); CREATE TABLE inhtd () INHERITS (inhta, inhtb, inhtc); -ALTER TABLE inhta ADD COLUMN i int; +ALTER TABLE inhta ADD COLUMN i int, ADD COLUMN j bigint DEFAULT 1; NOTICE: merging definition of column "i" for child "inhtd" NOTICE: merging definition of column "i" for child "inhtd" +NOTICE: merging definition of column "j" for child "inhtd" +NOTICE: merging definition of column "j" for child "inhtd" \d+ inhta Table "public.inhta" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description --------+---------+-----------+----------+---------+---------+--------------+------------- i | integer | | | | plain | | + j | bigint | | | 1 | plain | | Child tables: inhtb, inhtd +\d+ inhtd + Table "public.inhtd" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + i | integer | | | | plain | | + j | bigint | | | 1 | plain | | +Inherits: inhta, + inhtb, + inhtc + DROP TABLE inhta, inhtb, inhtc, inhtd; -- Test for renaming in diamond inheritance CREATE TABLE inht2 (x int) INHERITS (inht1); @@ -1252,6 +1268,8 @@ Indexes: "test_primary_constraints_pkey" PRIMARY KEY, btree (id) Referenced by: TABLE "test_foreign_constraints" CONSTRAINT "test_foreign_constraints_id1_fkey" FOREIGN KEY (id1) REFERENCES test_primary_constraints(id) +Not-null constraints: + "test_primary_constraints_id_not_null" NOT NULL "id" \d+ test_foreign_constraints Table "public.test_foreign_constraints" @@ -1314,19 +1332,112 @@ NOTICE: merging constraint "inh_check_constraint1" with inherited definition alter table p1_c1 add constraint inh_check_constraint2 check (f1 < 10); alter table p1 add constraint inh_check_constraint2 check (f1 < 10); NOTICE: merging constraint "inh_check_constraint2" with inherited definition -select conrelid::regclass::text as relname, conname, conislocal, coninhcount +alter table p1 add constraint inh_check_constraint3 check (f1 > 0) not enforced; +alter table p1_c1 add constraint inh_check_constraint3 check (f1 > 0) not enforced; +NOTICE: merging constraint "inh_check_constraint3" with inherited definition +alter table p1_c1 add constraint inh_check_constraint4 check (f1 < 10) not enforced; +alter table p1 add constraint inh_check_constraint4 check (f1 < 10) not enforced; +NOTICE: merging constraint "inh_check_constraint4" with inherited definition +-- allowed to merge enforced constraint with parent's not enforced constraint +alter table p1_c1 add constraint inh_check_constraint5 check (f1 < 10) enforced; +alter table p1 add constraint inh_check_constraint5 check (f1 < 10) not enforced; +NOTICE: merging constraint "inh_check_constraint5" with inherited definition +alter table p1 add constraint inh_check_constraint6 check (f1 < 10) not enforced; +alter table p1_c1 add constraint inh_check_constraint6 check (f1 < 10) enforced; +NOTICE: merging constraint "inh_check_constraint6" with inherited definition +alter table p1_c1 add constraint inh_check_constraint9 check (f1 < 10) not valid enforced; +alter table p1 add constraint inh_check_constraint9 check (f1 < 10) not enforced; +NOTICE: merging constraint "inh_check_constraint9" with inherited definition +-- the not-valid state of the child constraint will be ignored here. +alter table p1 add constraint inh_check_constraint10 check (f1 < 10) not enforced; +alter table p1_c1 add constraint inh_check_constraint10 check (f1 < 10) not valid enforced; +NOTICE: merging constraint "inh_check_constraint10" with inherited definition +create table p1_c2(f1 int constraint inh_check_constraint4 check (f1 < 10)) inherits(p1); +NOTICE: merging column "f1" with inherited definition +NOTICE: merging constraint "inh_check_constraint4" with inherited definition +-- but reverse is not allowed +alter table p1_c1 add constraint inh_check_constraint7 check (f1 < 10) not enforced; +alter table p1 add constraint inh_check_constraint7 check (f1 < 10) enforced; +ERROR: constraint "inh_check_constraint7" conflicts with NOT ENFORCED constraint on relation "p1_c1" +alter table p1 add constraint inh_check_constraint8 check (f1 < 10) enforced; +alter table p1_c1 add constraint inh_check_constraint8 check (f1 < 10) not enforced; +ERROR: constraint "inh_check_constraint8" conflicts with NOT ENFORCED constraint on relation "p1_c1" +create table p1_fail(f1 int constraint inh_check_constraint2 check (f1 < 10) not enforced) inherits(p1); +NOTICE: merging column "f1" with inherited definition +ERROR: constraint "inh_check_constraint2" conflicts with NOT ENFORCED constraint on relation "p1_fail" +-- constraints with different enforceability can be merged by marking them as ENFORCED +create table p1_c3() inherits(p1, p1_c1); +NOTICE: merging multiple inherited definitions of column "f1" +-- but not allowed if the child constraint is explicitly asked to be NOT ENFORCED +create table p1_fail(f1 int constraint inh_check_constraint6 check (f1 < 10) not enforced) inherits(p1, p1_c1); +NOTICE: merging multiple inherited definitions of column "f1" +NOTICE: merging column "f1" with inherited definition +ERROR: constraint "inh_check_constraint6" conflicts with NOT ENFORCED constraint on relation "p1_fail" +select conrelid::regclass::text as relname, conname, conislocal, coninhcount, conenforced, convalidated from pg_constraint where conname like 'inh\_check\_constraint%' order by 1, 2; - relname | conname | conislocal | coninhcount ----------+-----------------------+------------+------------- - p1 | inh_check_constraint1 | t | 0 - p1 | inh_check_constraint2 | t | 0 - p1_c1 | inh_check_constraint1 | t | 1 - p1_c1 | inh_check_constraint2 | t | 1 -(4 rows) + relname | conname | conislocal | coninhcount | conenforced | convalidated +---------+------------------------+------------+-------------+-------------+-------------- + p1 | inh_check_constraint1 | t | 0 | t | t + p1 | inh_check_constraint10 | t | 0 | f | f + p1 | inh_check_constraint2 | t | 0 | t | t + p1 | inh_check_constraint3 | t | 0 | f | f + p1 | inh_check_constraint4 | t | 0 | f | f + p1 | inh_check_constraint5 | t | 0 | f | f + p1 | inh_check_constraint6 | t | 0 | f | f + p1 | inh_check_constraint8 | t | 0 | t | t + p1 | inh_check_constraint9 | t | 0 | f | f + p1_c1 | inh_check_constraint1 | t | 1 | t | t + p1_c1 | inh_check_constraint10 | t | 1 | t | t + p1_c1 | inh_check_constraint2 | t | 1 | t | t + p1_c1 | inh_check_constraint3 | t | 1 | f | f + p1_c1 | inh_check_constraint4 | t | 1 | f | f + p1_c1 | inh_check_constraint5 | t | 1 | t | t + p1_c1 | inh_check_constraint6 | t | 1 | t | t + p1_c1 | inh_check_constraint7 | t | 0 | f | f + p1_c1 | inh_check_constraint8 | f | 1 | t | t + p1_c1 | inh_check_constraint9 | t | 1 | t | f + p1_c2 | inh_check_constraint1 | f | 1 | t | t + p1_c2 | inh_check_constraint10 | f | 1 | f | f + p1_c2 | inh_check_constraint2 | f | 1 | t | t + p1_c2 | inh_check_constraint3 | f | 1 | f | f + p1_c2 | inh_check_constraint4 | t | 1 | t | t + p1_c2 | inh_check_constraint5 | f | 1 | f | f + p1_c2 | inh_check_constraint6 | f | 1 | f | f + p1_c2 | inh_check_constraint8 | f | 1 | t | t + p1_c2 | inh_check_constraint9 | f | 1 | f | f + p1_c3 | inh_check_constraint1 | f | 2 | t | t + p1_c3 | inh_check_constraint10 | f | 2 | t | t + p1_c3 | inh_check_constraint2 | f | 2 | t | t + p1_c3 | inh_check_constraint3 | f | 2 | f | f + p1_c3 | inh_check_constraint4 | f | 2 | f | f + p1_c3 | inh_check_constraint5 | f | 2 | t | t + p1_c3 | inh_check_constraint6 | f | 2 | t | t + p1_c3 | inh_check_constraint7 | f | 1 | f | f + p1_c3 | inh_check_constraint8 | f | 2 | t | t + p1_c3 | inh_check_constraint9 | f | 2 | t | t +(38 rows) +drop table p1 cascade; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table p1_c1 +drop cascades to table p1_c2 +drop cascades to table p1_c3 +-- +-- Similarly, check the merging of existing constraints; a parent constraint +-- marked as NOT ENFORCED can merge with an ENFORCED child constraint, but the +-- reverse is not allowed. +-- +create table p1(f1 int constraint p1_a_check check (f1 > 0) not enforced); +create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) enforced); +alter table p1_c1 inherit p1; drop table p1 cascade; NOTICE: drop cascades to table p1_c1 +create table p1(f1 int constraint p1_a_check check (f1 > 0) enforced); +create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) not enforced); +alter table p1_c1 inherit p1; +ERROR: constraint "p1_a_check" conflicts with NOT ENFORCED constraint on child table "p1_c1" +drop table p1, p1_c1; -- -- Test DROP behavior of multiply-defined CHECK constraints -- @@ -1623,10 +1734,11 @@ explain (verbose, costs off) select * from matest0 order by 1-id; Output: matest0_3.id, matest0_3.name, ((1 - matest0_3.id)) Sort Key: ((1 - matest0_3.id)) -> Seq Scan on public.matest2 matest0_3 + Disabled: true Output: matest0_3.id, matest0_3.name, (1 - matest0_3.id) -> Index Scan using matest3i on public.matest3 matest0_4 Output: matest0_4.id, matest0_4.name, (1 - matest0_4.id) -(13 rows) +(14 rows) select * from matest0 order by 1-id; id | name @@ -1677,6 +1789,36 @@ select min(1-id) from matest0; reset enable_seqscan; reset enable_parallel_append; +explain (verbose, costs off) -- bug #18652 +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; + QUERY PLAN +------------------------------------------------------------ + Result + Output: ((1 - t1.id)) + -> Merge Append + Sort Key: ((1 - t1.id)) + -> Index Scan using matest3i on public.matest3 t1 + Output: t1.id, (1 - t1.id) + -> Sort + Output: ((t2.id * 2)), ((1 - (t2.id * 2))) + Sort Key: ((1 - (t2.id * 2))) + -> Seq Scan on public.matest3 t2 + Output: (t2.id * 2), (1 - (t2.id * 2)) +(11 rows) + +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; + c +----- + -11 + -9 + -5 + -4 +(4 rows) + drop table matest0 cascade; NOTICE: drop cascades to 3 other objects DETAIL: drop cascades to table matest1 @@ -2023,6 +2165,743 @@ select * from cnullparent where f1 = 2; drop table cnullparent cascade; NOTICE: drop cascades to table cnullchild -- +-- Test inheritance of NOT NULL constraints +-- +create table pp1 (f1 int); +create table cc1 (f2 text, f3 int) inherits (pp1); +create table cc2 (f4 float) inherits (pp1,cc1); +NOTICE: merging multiple inherited definitions of column "f1" +create table cc3 () inherits (pp1,cc1,cc2); +NOTICE: merging multiple inherited definitions of column "f1" +NOTICE: merging multiple inherited definitions of column "f1" +NOTICE: merging multiple inherited definitions of column "f2" +NOTICE: merging multiple inherited definitions of column "f3" +alter table pp1 alter f1 set not null; +\d+ cc3 + Table "public.cc3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) +Inherits: pp1, + cc1, + cc2 + +alter table cc3 no inherit pp1; +alter table cc3 no inherit cc1; +alter table cc3 no inherit cc2; +\d+ cc3 + Table "public.cc3" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" + +drop table cc3; +-- named NOT NULL constraint +alter table cc1 add column a2 int constraint nn not null; +\d+ cc1 + Table "public.cc1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + a2 | integer | | not null | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) + "nn" NOT NULL "a2" +Inherits: pp1 +Child tables: cc2 + +\d+ cc2 + Table "public.cc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | + a2 | integer | | not null | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) + "nn" NOT NULL "a2" (inherited) +Inherits: pp1, + cc1 + +alter table pp1 alter column f1 set not null; +\d+ pp1 + Table "public.pp1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" +Child tables: cc1, + cc2 + +\d+ cc1 + Table "public.cc1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + a2 | integer | | not null | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) + "nn" NOT NULL "a2" +Inherits: pp1 +Child tables: cc2 + +\d+ cc2 + Table "public.cc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | + a2 | integer | | not null | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) + "nn" NOT NULL "a2" (inherited) +Inherits: pp1, + cc1 + +-- cannot create table with inconsistent NO INHERIT constraint +create table cc3 (a2 int not null no inherit) inherits (cc1); +NOTICE: moving and merging column "a2" with inherited definition +DETAIL: User-specified column moved to the position of the inherited column. +ERROR: cannot define not-null constraint on column "a2" with NO INHERIT +DETAIL: The column has an inherited not-null constraint. +-- change NO INHERIT status of inherited constraint: no dice, it's inherited +alter table cc2 add not null a2 no inherit; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "nn" on relation "cc2" +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +-- remove constraint from cc2: no dice, it's inherited +alter table cc2 alter column a2 drop not null; +ERROR: cannot drop inherited constraint "nn" of relation "cc2" +-- remove constraint from cc1, should succeed +alter table cc1 alter column a2 drop not null; +\d+ cc1 + Table "public.cc1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + a2 | integer | | | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) +Inherits: pp1 +Child tables: cc2 + +-- same for cc2 +alter table cc2 alter column f1 drop not null; +ERROR: cannot drop inherited constraint "pp1_f1_not_null" of relation "cc2" +\d+ cc2 + Table "public.cc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | + a2 | integer | | | | plain | | +Not-null constraints: + "pp1_f1_not_null" NOT NULL "f1" (inherited) +Inherits: pp1, + cc1 + +-- remove from cc1, should fail again +alter table cc1 alter column f1 drop not null; +ERROR: cannot drop inherited constraint "pp1_f1_not_null" of relation "cc1" +-- remove from pp1, should succeed +alter table pp1 alter column f1 drop not null; +\d+ pp1 + Table "public.pp1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | | | plain | | +Child tables: cc1, + cc2 + +alter table pp1 add primary key (f1); +-- Leave these tables around, for pg_upgrade testing +-- test that removing inheritance of NOT NULL NO INHERIT works correctly +create table inh_parent (f1 int not null no inherit, f2 int not null no inherit); +create table inh_child (f1 int not null no inherit, f2 int); +alter table inh_child inherit inh_parent; +alter table inh_child no inherit inh_parent; +\d+ inh_child + Table "public.inh_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | integer | | | | plain | | +Not-null constraints: + "inh_child_f1_not_null" NOT NULL "f1" NO INHERIT + +drop table inh_parent, inh_child; +-- test that inhcount is updated correctly through multiple inheritance +create table inh_pp1 (f1 int); +create table inh_cc1 (f2 text, f3 int) inherits (inh_pp1); +create table inh_cc2(f4 float) inherits(inh_pp1,inh_cc1); +NOTICE: merging multiple inherited definitions of column "f1" +alter table inh_pp1 alter column f1 set not null; +alter table inh_cc2 no inherit inh_pp1; +alter table inh_cc2 no inherit inh_cc1; +\d+ inh_cc2 + Table "public.inh_cc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | not null | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | +Not-null constraints: + "inh_pp1_f1_not_null" NOT NULL "f1" + +drop table inh_pp1, inh_cc1, inh_cc2; +create table inh_pp1 (f1 int not null); +create table inh_cc1 (f2 text, f3 int) inherits (inh_pp1); +create table inh_cc2(f4 float) inherits(inh_pp1,inh_cc1); +NOTICE: merging multiple inherited definitions of column "f1" +alter table inh_pp1 alter column f1 drop not null; +\d+ inh_cc2 + Table "public.inh_cc2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+------------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | | | plain | | + f2 | text | | | | extended | | + f3 | integer | | | | plain | | + f4 | double precision | | | | plain | | +Inherits: inh_pp1, + inh_cc1 + +drop table inh_pp1, inh_cc1, inh_cc2; +-- Test a not-null addition that must walk down the hierarchy +CREATE TABLE inh_parent (); +CREATE TABLE inh_child (i int) INHERITS (inh_parent); +CREATE TABLE inh_grandchild () INHERITS (inh_parent, inh_child); +ALTER TABLE inh_parent ADD COLUMN i int NOT NULL; +NOTICE: merging definition of column "i" for child "inh_child" +NOTICE: merging definition of column "i" for child "inh_grandchild" +drop table inh_parent, inh_child, inh_grandchild; +-- Test the same constraint name for different columns in different parents +create table inh_parent1(a int constraint nn not null); +create table inh_parent2(b int constraint nn not null); +create table inh_child1 () inherits (inh_parent1, inh_parent2); +\d+ inh_child1 + Table "public.inh_child1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "nn" NOT NULL "a" (inherited) + "inh_child1_b_not_null" NOT NULL "b" (inherited) +Inherits: inh_parent1, + inh_parent2 + +create table inh_child2 (constraint foo not null a) inherits (inh_parent1, inh_parent2); +alter table inh_child2 no inherit inh_parent2; +\d+ inh_child2 + Table "public.inh_child2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | not null | | plain | | +Not-null constraints: + "foo" NOT NULL "a" (local, inherited) + "nn" NOT NULL "b" +Inherits: inh_parent1 + +drop table inh_parent1, inh_parent2, inh_child1, inh_child2; +-- Test multiple parents with overlapping primary keys +create table inh_parent1(a int, b int, c int, primary key (a, b)); +create table inh_parent2(d int, e int, b int, primary key (d, b)); +create table inh_child() inherits (inh_parent1, inh_parent2); +NOTICE: merging multiple inherited definitions of column "b" +select conrelid::regclass, conname, contype, conkey, + coninhcount, conislocal, connoinherit + from pg_constraint where contype in ('n','p') and + conrelid::regclass::text in ('inh_child', 'inh_parent1', 'inh_parent2') + order by 1, 2; + conrelid | conname | contype | conkey | coninhcount | conislocal | connoinherit +-------------+------------------------+---------+--------+-------------+------------+-------------- + inh_parent1 | inh_parent1_a_not_null | n | {1} | 0 | t | f + inh_parent1 | inh_parent1_b_not_null | n | {2} | 0 | t | f + inh_parent1 | inh_parent1_pkey | p | {1,2} | 0 | t | t + inh_parent2 | inh_parent2_b_not_null | n | {3} | 0 | t | f + inh_parent2 | inh_parent2_d_not_null | n | {1} | 0 | t | f + inh_parent2 | inh_parent2_pkey | p | {1,3} | 0 | t | t + inh_child | inh_parent1_a_not_null | n | {1} | 1 | f | f + inh_child | inh_parent1_b_not_null | n | {2} | 2 | f | f + inh_child | inh_parent2_d_not_null | n | {4} | 1 | f | f +(9 rows) + +\d+ inh_child + Table "public.inh_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | + b | integer | | not null | | plain | | + c | integer | | | | plain | | + d | integer | | not null | | plain | | + e | integer | | | | plain | | +Not-null constraints: + "inh_parent1_a_not_null" NOT NULL "a" (inherited) + "inh_parent1_b_not_null" NOT NULL "b" (inherited) + "inh_parent2_d_not_null" NOT NULL "d" (inherited) +Inherits: inh_parent1, + inh_parent2 + +drop table inh_parent1, inh_parent2, inh_child; +-- NOT NULL NO INHERIT +create table inh_nn_parent(a int); +create table inh_nn_child() inherits (inh_nn_parent); +alter table inh_nn_parent add not null a no inherit; +create table inh_nn_child2() inherits (inh_nn_parent); +select conrelid::regclass, conname, contype, conkey, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text like 'inh\_nn\_%' + order by 2, 1; + conrelid | conname | contype | conkey | attname | coninhcount | conislocal | connoinherit +---------------+--------------------------+---------+--------+---------+-------------+------------+-------------- + inh_nn_parent | inh_nn_parent_a_not_null | n | {1} | a | 0 | t | t +(1 row) + +\d+ inh_nn* + Table "public.inh_nn_child" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Inherits: inh_nn_parent + + Table "public.inh_nn_child2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | | | plain | | +Inherits: inh_nn_parent + + Table "public.inh_nn_parent" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + a | integer | | not null | | plain | | +Not-null constraints: + "inh_nn_parent_a_not_null" NOT NULL "a" NO INHERIT +Child tables: inh_nn_child, + inh_nn_child2 + +drop table inh_nn_parent, inh_nn_child, inh_nn_child2; +CREATE TABLE inh_nn_parent (a int, NOT NULL a NO INHERIT); +CREATE TABLE inh_nn_child() INHERITS (inh_nn_parent); +ALTER TABLE inh_nn_parent ADD CONSTRAINT nna NOT NULL a; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "inh_nn_parent_a_not_null" on relation "inh_nn_parent" +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +ALTER TABLE inh_nn_parent ALTER a SET NOT NULL; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "inh_nn_parent_a_not_null" on relation "inh_nn_parent" +DROP TABLE inh_nn_parent cascade; +NOTICE: drop cascades to table inh_nn_child +-- Adding a PK at the top level of a hierarchy should cause all descendants +-- to be checked for nulls, even past a no-inherit constraint +CREATE TABLE inh_nn_lvl1 (a int); +CREATE TABLE inh_nn_lvl2 () INHERITS (inh_nn_lvl1); +CREATE TABLE inh_nn_lvl3 (CONSTRAINT foo NOT NULL a NO INHERIT) INHERITS (inh_nn_lvl2); +ALTER TABLE inh_nn_lvl1 ADD PRIMARY KEY (a); +ERROR: cannot change NO INHERIT status of NOT NULL constraint "foo" on relation "inh_nn_lvl3" +HINT: You might need to make the existing constraint inheritable using ALTER TABLE ... ALTER CONSTRAINT ... INHERIT. +DROP TABLE inh_nn_lvl1, inh_nn_lvl2, inh_nn_lvl3; +-- Disallow specifying conflicting NO INHERIT flags for the same constraint +CREATE TABLE inh_nn1 (a int primary key, b int, not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +CREATE TABLE inh_nn1 (a int not null); +CREATE TABLE inh_nn2 (a int not null no inherit) INHERITS (inh_nn1); +NOTICE: merging column "a" with inherited definition +ERROR: cannot define not-null constraint on column "a" with NO INHERIT +DETAIL: The column has an inherited not-null constraint. +CREATE TABLE inh_nn3 (a int not null, b int, not null a no inherit); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +CREATE TABLE inh_nn4 (a int not null no inherit, b int, not null a); +ERROR: conflicting NO INHERIT declaration for not-null constraint on column "a" +DROP TABLE IF EXISTS inh_nn1, inh_nn2, inh_nn3, inh_nn4; +NOTICE: table "inh_nn2" does not exist, skipping +NOTICE: table "inh_nn3" does not exist, skipping +NOTICE: table "inh_nn4" does not exist, skipping +-- +-- test inherit/deinherit +-- +create table inh_parent(f1 int); +create table inh_child1(f1 int not null); +create table inh_child2(f1 int); +-- inh_child1 should have not null constraint +alter table inh_child1 inherit inh_parent; +-- should fail, missing NOT NULL constraint +alter table inh_child2 inherit inh_child1; +ERROR: column "f1" in child table "inh_child2" must be marked NOT NULL +alter table inh_child2 alter column f1 set not null; +alter table inh_child2 inherit inh_child1; +-- add NOT NULL constraint recursively +alter table inh_parent alter column f1 set not null; +\d+ inh_parent + Table "public.inh_parent" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_parent_f1_not_null" NOT NULL "f1" +Child tables: inh_child1 + +\d+ inh_child1 + Table "public.inh_child1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_child1_f1_not_null" NOT NULL "f1" (local, inherited) +Inherits: inh_parent +Child tables: inh_child2 + +\d+ inh_child2 + Table "public.inh_child2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_child2_f1_not_null" NOT NULL "f1" (local, inherited) +Inherits: inh_child1 + +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent'::regclass, 'inh_child1'::regclass, 'inh_child2'::regclass) + order by 2, 1; + conrelid | conname | contype | coninhcount | conislocal +------------+------------------------+---------+-------------+------------ + inh_child1 | inh_child1_f1_not_null | n | 1 | t + inh_child2 | inh_child2_f1_not_null | n | 1 | t + inh_parent | inh_parent_f1_not_null | n | 0 | t +(3 rows) + +-- +-- test deinherit procedure +-- +-- deinherit inh_child1 +create table inh_child3 () inherits (inh_child1); +alter table inh_child1 no inherit inh_parent; +\d+ inh_parent + Table "public.inh_parent" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_parent_f1_not_null" NOT NULL "f1" + +\d+ inh_child1 + Table "public.inh_child1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_child1_f1_not_null" NOT NULL "f1" +Child tables: inh_child2, + inh_child3 + +\d+ inh_child2 + Table "public.inh_child2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + f1 | integer | | not null | | plain | | +Not-null constraints: + "inh_child2_f1_not_null" NOT NULL "f1" (local, inherited) +Inherits: inh_child1 + +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_parent', 'inh_child1', 'inh_child2', 'inh_child3') + order by 2, 1; + conrelid | conname | contype | coninhcount | conislocal +------------+------------------------+---------+-------------+------------ + inh_child1 | inh_child1_f1_not_null | n | 0 | t + inh_child3 | inh_child1_f1_not_null | n | 1 | f + inh_child2 | inh_child2_f1_not_null | n | 1 | t + inh_parent | inh_parent_f1_not_null | n | 0 | t +(4 rows) + +drop table inh_parent, inh_child1, inh_child2, inh_child3; +-- ALTER TABLE INHERIT ensures that the child has not-null constraints +create table inh_parent (a int not null); +create table inh_child (a int); +alter table inh_child inherit inh_parent; -- nope +ERROR: column "a" in child table "inh_child" must be marked NOT NULL +drop table inh_parent, inh_child; +-- Can't merge a NO INHERIT constraint with a normal one +create table inh_parent (a int not null); +create table inh_child (a int not null no inherit); +alter table inh_child inherit inh_parent; +ERROR: constraint "inh_child_a_not_null" conflicts with non-inherited constraint on child table "inh_child" +drop table inh_parent, inh_child; +-- don't interfere with other types of constraints +create table inh_parent (a int primary key); +create table inh_child (a int primary key) inherits (inh_parent); +NOTICE: merging column "a" with inherited definition +alter table inh_parent add constraint inh_parent_excl exclude ((1) with =); +alter table inh_parent add constraint inh_parent_uq unique (a); +alter table inh_parent add constraint inh_parent_fk foreign key (a) references inh_parent (a); +create table inh_child2 () inherits (inh_parent); +create table inh_child3 (like inh_parent); +alter table inh_child3 inherit inh_parent; +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint + where conrelid::regclass::text in ('inh_parent', 'inh_child', 'inh_child2', 'inh_child3') + order by 2, 1; + conrelid | conname | contype | coninhcount | conislocal +------------+-----------------------+---------+-------------+------------ + inh_child | inh_child_a_not_null | n | 1 | t + inh_child | inh_child_pkey | p | 0 | t + inh_parent | inh_parent_a_not_null | n | 0 | t + inh_child2 | inh_parent_a_not_null | n | 1 | f + inh_child3 | inh_parent_a_not_null | n | 1 | t + inh_parent | inh_parent_excl | x | 0 | t + inh_parent | inh_parent_fk | f | 0 | t + inh_parent | inh_parent_pkey | p | 0 | t + inh_parent | inh_parent_uq | u | 0 | t +(9 rows) + +drop table inh_parent, inh_child, inh_child2, inh_child3; +-- +-- test multi inheritance tree +-- +create table inh_parent(f1 int not null); +create table inh_child1() inherits(inh_parent); +create table inh_child2() inherits(inh_parent); +create table inh_child3() inherits(inh_child1, inh_child2); +NOTICE: merging multiple inherited definitions of column "f1" +-- show constraint info +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent'::regclass, 'inh_child1'::regclass, 'inh_child2'::regclass, 'inh_child3'::regclass) + order by 2, conrelid::regclass::text; + conrelid | conname | contype | coninhcount | conislocal +------------+------------------------+---------+-------------+------------ + inh_child1 | inh_parent_f1_not_null | n | 1 | f + inh_child2 | inh_parent_f1_not_null | n | 1 | f + inh_child3 | inh_parent_f1_not_null | n | 2 | f + inh_parent | inh_parent_f1_not_null | n | 0 | t +(4 rows) + +drop table inh_parent cascade; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table inh_child1 +drop cascades to table inh_child2 +drop cascades to table inh_child3 +-- test child table with inherited columns and +-- with explicitly specified not null constraints +create table inh_parent_1(f1 int); +create table inh_parent_2(f2 text); +create table inh_child(f1 int not null, f2 text not null) inherits(inh_parent_1, inh_parent_2); +NOTICE: merging column "f1" with inherited definition +NOTICE: merging column "f2" with inherited definition +-- show constraint info +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent_1'::regclass, 'inh_parent_2'::regclass, 'inh_child'::regclass) + order by 2, conrelid::regclass::text; + conrelid | conname | contype | coninhcount | conislocal +-----------+-----------------------+---------+-------------+------------ + inh_child | inh_child_f1_not_null | n | 0 | t + inh_child | inh_child_f2_not_null | n | 0 | t +(2 rows) + +-- also drops inh_child table +drop table inh_parent_1 cascade; +NOTICE: drop cascades to table inh_child +drop table inh_parent_2; +-- test multi layer inheritance tree +create table inh_p1(f1 int not null); +create table inh_p2(f1 int not null); +create table inh_p3(f2 int); +create table inh_p4(f1 int not null, f3 text not null); +create table inh_multiparent() inherits(inh_p1, inh_p2, inh_p3, inh_p4); +NOTICE: merging multiple inherited definitions of column "f1" +NOTICE: merging multiple inherited definitions of column "f1" +-- constraint on f1 should have three parents +select conrelid::regclass, contype, conname, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass in ('inh_p1', 'inh_p2', 'inh_p3', 'inh_p4', + 'inh_multiparent') + order by conrelid::regclass::text, conname; + conrelid | contype | conname | attname | coninhcount | conislocal +-----------------+---------+--------------------+---------+-------------+------------ + inh_multiparent | n | inh_p1_f1_not_null | f1 | 3 | f + inh_multiparent | n | inh_p4_f3_not_null | f3 | 1 | f + inh_p1 | n | inh_p1_f1_not_null | f1 | 0 | t + inh_p2 | n | inh_p2_f1_not_null | f1 | 0 | t + inh_p4 | n | inh_p4_f1_not_null | f1 | 0 | t + inh_p4 | n | inh_p4_f3_not_null | f3 | 0 | t +(6 rows) + +create table inh_multiparent2 (a int not null, f1 int) inherits(inh_p3, inh_multiparent); +NOTICE: merging multiple inherited definitions of column "f2" +NOTICE: merging column "f1" with inherited definition +select conrelid::regclass, contype, conname, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass in ('inh_p3', 'inh_multiparent', 'inh_multiparent2') + order by conrelid::regclass::text, conname; + conrelid | contype | conname | attname | coninhcount | conislocal +------------------+---------+-----------------------------+---------+-------------+------------ + inh_multiparent | n | inh_p1_f1_not_null | f1 | 3 | f + inh_multiparent | n | inh_p4_f3_not_null | f3 | 1 | f + inh_multiparent2 | n | inh_multiparent2_a_not_null | a | 0 | t + inh_multiparent2 | n | inh_p1_f1_not_null | f1 | 1 | f + inh_multiparent2 | n | inh_p4_f3_not_null | f3 | 1 | f +(5 rows) + +drop table inh_p1, inh_p2, inh_p3, inh_p4 cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table inh_multiparent +drop cascades to table inh_multiparent2 +-- +-- Test ALTER CONSTRAINT SET [NO] INHERIT +-- +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int, f1 int); +alter table inh_nn2 inherit inh_nn1; +create table inh_nn3 (f4 float) inherits (inh_nn2); +create table inh_nn4 (f5 int, f4 float, f2 text, f3 int, f1 int); +alter table inh_nn4 inherit inh_nn2, inherit inh_nn1, inherit inh_nn3; +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; + conrelid | conname | conkey | coninhcount | conislocal | connoinherit +----------+---------------------+--------+-------------+------------+-------------- + inh_nn1 | inh_nn1_f1_not_null | {1} | 0 | t | f + inh_nn2 | inh_nn1_f1_not_null | {3} | 1 | f | f + inh_nn3 | inh_nn1_f1_not_null | {3} | 1 | f | f + inh_nn4 | inh_nn1_f1_not_null | {5} | 3 | f | f +(4 rows) + +-- ALTER CONSTRAINT NO INHERIT should work on top-level constraints +alter table inh_nn1 alter constraint inh_nn1_f1_not_null no inherit; +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; + conrelid | conname | conkey | coninhcount | conislocal | connoinherit +----------+---------------------+--------+-------------+------------+-------------- + inh_nn1 | inh_nn1_f1_not_null | {1} | 0 | t | t + inh_nn2 | inh_nn1_f1_not_null | {3} | 0 | t | f + inh_nn3 | inh_nn1_f1_not_null | {3} | 1 | f | f + inh_nn4 | inh_nn1_f1_not_null | {5} | 2 | t | f +(4 rows) + +-- A constraint that's NO INHERIT can be dropped without damaging children +alter table inh_nn1 drop constraint inh_nn1_f1_not_null; +select conrelid::regclass, conname, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; + conrelid | conname | coninhcount | conislocal | connoinherit +----------+---------------------+-------------+------------+-------------- + inh_nn2 | inh_nn1_f1_not_null | 0 | t | f + inh_nn3 | inh_nn1_f1_not_null | 1 | f | f + inh_nn4 | inh_nn1_f1_not_null | 2 | t | f +(3 rows) + +drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4; +-- Test inherit constraint and make sure it validates. +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1); +insert into inh_nn2 values(NULL, 'sample', 1); +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +ERROR: column "f1" of relation "inh_nn2" contains null values +delete from inh_nn2; +create table inh_nn3 () inherits (inh_nn2); +create table inh_nn4 () inherits (inh_nn1, inh_nn2); +NOTICE: merging multiple inherited definitions of column "f1" +alter table inh_nn1 -- test multicommand alter table while at it + alter constraint inh_nn1_f1_not_null inherit, + alter constraint inh_nn1_f1_not_null no inherit; +select conrelid::regclass, conname, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; + conrelid | conname | coninhcount | conislocal | connoinherit +----------+---------------------+-------------+------------+-------------- + inh_nn1 | inh_nn1_f1_not_null | 0 | t | t + inh_nn2 | inh_nn1_f1_not_null | 0 | t | f + inh_nn3 | inh_nn1_f1_not_null | 1 | f | f + inh_nn4 | inh_nn1_f1_not_null | 1 | t | f +(4 rows) + +drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4; +-- Test not null inherit constraint which already exists on child table. +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1); +create table inh_nn3 (f4 float, constraint nn3_f1 not null f1 no inherit) inherits (inh_nn1, inh_nn2); +NOTICE: merging multiple inherited definitions of column "f1" +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') + order by 2, 1; + conrelid | conname | conkey | coninhcount | conislocal | connoinherit +----------+---------------------+--------+-------------+------------+-------------- + inh_nn1 | inh_nn1_f1_not_null | {1} | 0 | t | t + inh_nn3 | nn3_f1 | {1} | 0 | t | t +(2 rows) + +-- error: inh_nn3 has an incompatible NO INHERIT constraint +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +ERROR: cannot change NO INHERIT status of NOT NULL constraint "nn3_f1" on relation "inh_nn3" +alter table inh_nn3 alter constraint nn3_f1 inherit; +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; -- now it works +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') + order by 2, 1; + conrelid | conname | conkey | coninhcount | conislocal | connoinherit +----------+---------------------+--------+-------------+------------+-------------- + inh_nn1 | inh_nn1_f1_not_null | {1} | 0 | t | f + inh_nn2 | inh_nn1_f1_not_null | {1} | 1 | f | f + inh_nn3 | nn3_f1 | {1} | 2 | t | f +(3 rows) + +drop table inh_nn1, inh_nn2, inh_nn3; +-- Negative scenarios for alter constraint .. inherit. +create table inh_nn1 (f1 int check(f1 > 5) primary key references inh_nn1, f2 int not null); +-- constraints other than not-null are not supported +alter table inh_nn1 alter constraint inh_nn1_f1_check inherit; +ERROR: constraint "inh_nn1_f1_check" of relation "inh_nn1" is not a not-null constraint +alter table inh_nn1 alter constraint inh_nn1_pkey inherit; +ERROR: constraint "inh_nn1_pkey" of relation "inh_nn1" is not a not-null constraint +alter table inh_nn1 alter constraint inh_nn1_f1_fkey inherit; +ERROR: constraint "inh_nn1_f1_fkey" of relation "inh_nn1" is not a not-null constraint +-- try to drop a nonexistant constraint +alter table inh_nn1 alter constraint foo inherit; +ERROR: constraint "foo" of relation "inh_nn1" does not exist +-- Can't modify inheritability of inherited constraints +create table inh_nn2 () inherits (inh_nn1); +alter table inh_nn2 alter constraint inh_nn1_f2_not_null no inherit; +ERROR: cannot alter inherited constraint "inh_nn1_f2_not_null" on relation "inh_nn2" +drop table inh_nn1, inh_nn2; +-- -- Mixed ownership inheritance tree -- create role regress_alice; @@ -2945,3 +3824,33 @@ UPDATE errtst_parent SET partid = 30, data = data + 10 WHERE partid = 20; ERROR: no partition of relation "errtst_parent" found for row DETAIL: Partition key of the failing row contains (partid) = (30). DROP TABLE errtst_parent; +-- Check that we have the correct tuples estimate for an appendrel +create table tuplesest_parted (a int, b int, c float) partition by range(a); +create table tuplesest_parted1 partition of tuplesest_parted for values from (0) to (100); +create table tuplesest_parted2 partition of tuplesest_parted for values from (100) to (200); +create table tuplesest_tab (a int, b int); +insert into tuplesest_parted select i%200, i%300, i%400 from generate_series(1, 1000)i; +insert into tuplesest_tab select i, i from generate_series(1, 100)i; +analyze tuplesest_parted; +analyze tuplesest_tab; +explain (costs off) +select * from tuplesest_tab join + (select b from tuplesest_parted where c < 100 group by b) sub + on tuplesest_tab.a = sub.b; + QUERY PLAN +-------------------------------------------------------------------- + Hash Join + Hash Cond: (tuplesest_parted.b = tuplesest_tab.a) + -> HashAggregate + Group Key: tuplesest_parted.b + -> Append + -> Seq Scan on tuplesest_parted1 tuplesest_parted_1 + Filter: (c < '100'::double precision) + -> Seq Scan on tuplesest_parted2 tuplesest_parted_2 + Filter: (c < '100'::double precision) + -> Hash + -> Seq Scan on tuplesest_tab +(11 rows) + +drop table tuplesest_parted; +drop table tuplesest_tab; diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out index 5cb9cde0305aa..fdd0f6c8f258c 100644 --- a/src/test/regress/expected/insert_conflict.out +++ b/src/test/regress/expected/insert_conflict.out @@ -218,6 +218,7 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Async Capable": false, + "Relation Name": "insertconflicttest", + "Alias": "insertconflicttest", + + "Disabled": false, + "Conflict Resolution": "UPDATE", + "Conflict Arbiter Indexes": ["key_index"], + "Conflict Filter": "(insertconflicttest.fruit <> 'Lime'::text)",+ @@ -226,7 +227,8 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Node Type": "Result", + "Parent Relationship": "Outer", + "Parallel Aware": false, + - "Async Capable": false + + "Async Capable": false, + + "Disabled": false + } + ] + } + diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out index fddc09f6305a8..392f3bf655c2e 100644 --- a/src/test/regress/expected/int8.out +++ b/src/test/regress/expected/int8.out @@ -530,6 +530,16 @@ SELECT to_char(q2, 'MI9999999999999999') FROM INT8_TBL; -4567890123456789 (5 rows) +SELECT to_char(q2, '9999999999999999PL') FROM INT8_TBL; + to_char +-------------------- + 456+ + 4567890123456789+ + 123+ + 4567890123456789+ + -4567890123456789 +(5 rows) + SELECT to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; to_char ------------------- @@ -650,6 +660,46 @@ SELECT to_char(q2, '999999SG9999999999') FROM INT8_TBL; 456789-0123456789 (5 rows) +SELECT to_char(q2, 'FMRN') FROM INT8_TBL; + to_char +----------------- + CDLVI + ############### + CXXIII + ############### + ############### +(5 rows) + +SELECT to_char(1234, '9.99EEEE'); + to_char +----------- + 1.23e+03 +(1 row) + +SELECT to_char(1234::int8, '9.99eeee'); + to_char +----------- + 1.23e+03 +(1 row) + +SELECT to_char(-1234::int8, '9.99eeee'); + to_char +----------- + -1.23e+03 +(1 row) + +SELECT to_char(1234, '99999V99'); + to_char +---------- + 123400 +(1 row) + +SELECT to_char(1234::int8, '99999V99'); + to_char +---------- + 123400 +(1 row) + -- check min/max values and overflow behavior select '-9223372036854775808'::int8; int8 diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index 51ae010c7baba..a16e3ccdb2ee1 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -1834,6 +1834,7 @@ SELECT f1, EXTRACT(MINUTE FROM f1) AS MINUTE, EXTRACT(HOUR FROM f1) AS HOUR, EXTRACT(DAY FROM f1) AS DAY, + EXTRACT(WEEK FROM f1) AS WEEK, EXTRACT(MONTH FROM f1) AS MONTH, EXTRACT(QUARTER FROM f1) AS QUARTER, EXTRACT(YEAR FROM f1) AS YEAR, @@ -1842,20 +1843,52 @@ SELECT f1, EXTRACT(MILLENNIUM FROM f1) AS MILLENNIUM, EXTRACT(EPOCH FROM f1) AS EPOCH FROM INTERVAL_TBL; - f1 | microsecond | millisecond | second | minute | hour | day | month | quarter | year | decade | century | millennium | epoch --------------------------------+-------------+-------------+------------+--------+-----------+-----------+-------+---------+-----------+-----------+-----------+------------+------------------- - @ 1 min | 0 | 0.000 | 0.000000 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 60.000000 - @ 5 hours | 0 | 0.000 | 0.000000 | 0 | 5 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 18000.000000 - @ 10 days | 0 | 0.000 | 0.000000 | 0 | 0 | 10 | 0 | 1 | 0 | 0 | 0 | 0 | 864000.000000 - @ 34 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 34 | 3 | 0 | 0 | 1072958400.000000 - @ 3 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 3 | 2 | 0 | 0 | 0 | 0 | 7776000.000000 - @ 14 secs ago | -14000000 | -14000.000 | -14.000000 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -14.000000 - @ 1 day 2 hours 3 mins 4 secs | 4000000 | 4000.000 | 4.000000 | 3 | 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 93784.000000 - @ 6 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 1 | 6 | 0 | 0 | 0 | 189345600.000000 - @ 5 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 12960000.000000 - @ 5 mons 12 hours | 0 | 0.000 | 0.000000 | 0 | 12 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 13003200.000000 - infinity | | | | | Infinity | Infinity | | | Infinity | Infinity | Infinity | Infinity | Infinity - -infinity | | | | | -Infinity | -Infinity | | | -Infinity | -Infinity | -Infinity | -Infinity | -Infinity + f1 | microsecond | millisecond | second | minute | hour | day | week | month | quarter | year | decade | century | millennium | epoch +-------------------------------+-------------+-------------+------------+--------+-----------+-----------+------+-------+---------+-----------+-----------+-----------+------------+------------------- + @ 1 min | 0 | 0.000 | 0.000000 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 60.000000 + @ 5 hours | 0 | 0.000 | 0.000000 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 18000.000000 + @ 10 days | 0 | 0.000 | 0.000000 | 0 | 0 | 10 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 864000.000000 + @ 34 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 1 | 34 | 3 | 0 | 0 | 1072958400.000000 + @ 3 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 3 | 2 | 0 | 0 | 0 | 0 | 7776000.000000 + @ 14 secs ago | -14000000 | -14000.000 | -14.000000 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -14.000000 + @ 1 day 2 hours 3 mins 4 secs | 4000000 | 4000.000 | 4.000000 | 3 | 2 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 93784.000000 + @ 6 years | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 1 | 6 | 0 | 0 | 0 | 189345600.000000 + @ 5 mons | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 12960000.000000 + @ 5 mons 12 hours | 0 | 0.000 | 0.000000 | 0 | 12 | 0 | 0 | 5 | 2 | 0 | 0 | 0 | 0 | 13003200.000000 + infinity | | | | | Infinity | Infinity | | | | Infinity | Infinity | Infinity | Infinity | Infinity + -infinity | | | | | -Infinity | -Infinity | | | | -Infinity | -Infinity | -Infinity | -Infinity | -Infinity +(12 rows) + +SELECT -f1, + EXTRACT(MICROSECOND FROM -f1) AS MICROSECOND, + EXTRACT(MILLISECOND FROM -f1) AS MILLISECOND, + EXTRACT(SECOND FROM -f1) AS SECOND, + EXTRACT(MINUTE FROM -f1) AS MINUTE, + EXTRACT(HOUR FROM -f1) AS HOUR, + EXTRACT(DAY FROM -f1) AS DAY, + EXTRACT(WEEK FROM -f1) AS WEEK, + EXTRACT(MONTH FROM -f1) AS MONTH, + EXTRACT(QUARTER FROM -f1) AS QUARTER, + EXTRACT(YEAR FROM -f1) AS YEAR, + EXTRACT(DECADE FROM -f1) AS DECADE, + EXTRACT(CENTURY FROM -f1) AS CENTURY, + EXTRACT(MILLENNIUM FROM -f1) AS MILLENNIUM, + EXTRACT(EPOCH FROM -f1) AS EPOCH + FROM INTERVAL_TBL; + ?column? | microsecond | millisecond | second | minute | hour | day | week | month | quarter | year | decade | century | millennium | epoch +-----------------------------------+-------------+-------------+-----------+--------+-----------+-----------+------+-------+---------+-----------+-----------+-----------+------------+-------------------- + @ 1 min ago | 0 | 0.000 | 0.000000 | -1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -60.000000 + @ 5 hours ago | 0 | 0.000 | 0.000000 | 0 | -5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -18000.000000 + @ 10 days ago | 0 | 0.000 | 0.000000 | 0 | 0 | -10 | -1 | 0 | 1 | 0 | 0 | 0 | 0 | -864000.000000 + @ 34 years ago | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 0 | -1 | -34 | -3 | 0 | 0 | -1072958400.000000 + @ 3 mons ago | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | -3 | -2 | 0 | 0 | 0 | 0 | -7776000.000000 + @ 14 secs | 14000000 | 14000.000 | 14.000000 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 14.000000 + @ 1 day 2 hours 3 mins 4 secs ago | -4000000 | -4000.000 | -4.000000 | -3 | -2 | -1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | -93784.000000 + @ 6 years ago | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | 0 | -1 | -6 | 0 | 0 | 0 | -189345600.000000 + @ 5 mons ago | 0 | 0.000 | 0.000000 | 0 | 0 | 0 | 0 | -5 | -2 | 0 | 0 | 0 | 0 | -12960000.000000 + @ 5 mons 12 hours ago | 0 | 0.000 | 0.000000 | 0 | -12 | 0 | 0 | -5 | -2 | 0 | 0 | 0 | 0 | -13003200.000000 + -infinity | | | | | -Infinity | -Infinity | | | | -Infinity | -Infinity | -Infinity | -Infinity | -Infinity + infinity | | | | | Infinity | Infinity | | | | Infinity | Infinity | Infinity | Infinity | Infinity (12 rows) SELECT EXTRACT(FORTNIGHT FROM INTERVAL '2 days'); -- error @@ -2186,6 +2219,15 @@ SELECT i AS interval, date_trunc('hour', i) -infinity | -infinity (2 rows) +SELECT i AS interval, date_trunc('week', i) + FROM INFINITE_INTERVAL_TBL + WHERE NOT isfinite(i); +ERROR: unit "week" not supported for type interval +DETAIL: Months usually have fractional weeks. +SELECT i AS interval, date_trunc('ago', i) + FROM INFINITE_INTERVAL_TBL + WHERE NOT isfinite(i); +ERROR: unit "ago" not recognized for type interval SELECT i AS interval, justify_days(i), justify_hours(i), justify_interval(i) FROM INFINITE_INTERVAL_TBL WHERE NOT isfinite(i); diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 53f70d72ed64d..f35a0b18c37cb 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2358,6 +2358,61 @@ where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; ----+----+----------+---------- (0 rows) +-- +-- Test hash joins with multiple hash keys and subplans. +-- +-- First ensure we get a hash join with multiple hash keys. +explain (costs off) +select t1.unique1,t2.unique1 from tenk1 t1 +inner join tenk1 t2 on t1.two = t2.two + and t1.unique1 = (select min(unique1) from tenk1 + where t2.unique1=unique1) +where t1.unique1 < 10 and t2.unique1 < 10 +order by t1.unique1; + QUERY PLAN +---------------------------------------------------------------------------------------------------- + Sort + Sort Key: t1.unique1 + -> Hash Join + Hash Cond: ((t1.two = t2.two) AND (t1.unique1 = (SubPlan 2))) + -> Bitmap Heap Scan on tenk1 t1 + Recheck Cond: (unique1 < 10) + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 < 10) + -> Hash + -> Bitmap Heap Scan on tenk1 t2 + Recheck Cond: (unique1 < 10) + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 < 10) + SubPlan 2 + -> Result + InitPlan 1 + -> Limit + -> Index Only Scan using tenk1_unique1 on tenk1 + Index Cond: ((unique1 IS NOT NULL) AND (unique1 = t2.unique1)) +(19 rows) + +-- Ensure we get the expected result +select t1.unique1,t2.unique1 from tenk1 t1 +inner join tenk1 t2 on t1.two = t2.two + and t1.unique1 = (select min(unique1) from tenk1 + where t2.unique1=unique1) +where t1.unique1 < 10 and t2.unique1 < 10 +order by t1.unique1; + unique1 | unique1 +---------+--------- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + -- -- checks for correct handling of quals in multiway outer joins -- @@ -2518,10 +2573,11 @@ where t1.f1 = coalesce(t2.f1, 1); -> Materialize -> Seq Scan on int4_tbl t2 Filter: (f1 > 1) - -> Seq Scan on int4_tbl t3 + -> Materialize + -> Seq Scan on int4_tbl t3 -> Materialize -> Seq Scan on int4_tbl t4 -(13 rows) +(14 rows) explain (costs off) select * from int4_tbl t1 @@ -2980,6 +3036,45 @@ where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; reset enable_hashjoin; reset enable_nestloop; +-- +-- regression test for bug with hash-right-semi join +-- +create temp table tbl_rs(a int, b int); +insert into tbl_rs select i, i from generate_series(1,10)i; +analyze tbl_rs; +-- ensure we get a hash right semi join +explain (costs off) +select * from tbl_rs t1 join + lateral (select * from tbl_rs t2 where t2.a in + (select t1.a+t3.a from tbl_rs t3) and t2.a < 5) + on true; + QUERY PLAN +------------------------------------------- + Nested Loop + -> Seq Scan on tbl_rs t1 + -> Hash Right Semi Join + Hash Cond: ((t1.a + t3.a) = t2.a) + -> Seq Scan on tbl_rs t3 + -> Hash + -> Seq Scan on tbl_rs t2 + Filter: (a < 5) +(8 rows) + +-- and check we get the expected results +select * from tbl_rs t1 join + lateral (select * from tbl_rs t2 where t2.a in + (select t1.a+t3.a from tbl_rs t3) and t2.a < 5) + on true; + a | b | a | b +---+---+---+--- + 1 | 1 | 2 | 2 + 1 | 1 | 3 | 3 + 1 | 1 | 4 | 4 + 2 | 2 | 3 | 3 + 2 | 2 | 4 | 4 + 3 | 3 | 4 | 4 +(6 rows) + -- -- regression test for bug #13908 (hash join with skew tuples & nbatch increase) -- @@ -3127,6 +3222,21 @@ where b.unique2 is null; -> Index Only Scan using tenk1_unique2 on tenk1 b (5 rows) +-- +-- regression test for bogus RTE_GROUP entries +-- +explain (costs off) +select a.* from tenk1 a +where exists (select 1 from tenk1 b where a.unique1 = b.unique2 group by b.unique1); + QUERY PLAN +------------------------------------------------------------ + Hash Semi Join + Hash Cond: (a.unique1 = b.unique2) + -> Seq Scan on tenk1 a + -> Hash + -> Index Only Scan using tenk1_unique2 on tenk1 b +(5 rows) + -- -- regression test for proper handling of outer joins within antijoins -- @@ -3739,14 +3849,11 @@ where q1 = thousand or q2 = thousand; -> Seq Scan on q2 -> Bitmap Heap Scan on tenk1 Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand)) - -> BitmapOr - -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = q1.q1) - -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = q2.q2) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = ANY (ARRAY[q1.q1, q2.q2])) -> Hash -> Seq Scan on int4_tbl -(15 rows) +(12 rows) explain (costs off) select * from @@ -4278,15 +4385,62 @@ select * from tenk1 a join tenk1 b on Index Cond: (hundred = 4) -> Materialize -> Bitmap Heap Scan on tenk1 a - Recheck Cond: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7)) + Recheck Cond: ((unique1 = 1) OR ((unique2 = 3) OR (unique2 = 7))) + Filter: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7)) -> BitmapOr -> Bitmap Index Scan on tenk1_unique1 Index Cond: (unique1 = 1) -> Bitmap Index Scan on tenk1_unique2 - Index Cond: (unique2 = 3) + Index Cond: (unique2 = ANY ('{3,7}'::integer[])) +(18 rows) + +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 = 1 and b.unique1 = 2) or + ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4))) + -> Bitmap Heap Scan on tenk1 b + Recheck Cond: ((unique1 = 2) OR (hundred = 4)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 = 2) + -> Bitmap Index Scan on tenk1_hundred + Index Cond: (hundred = 4) + -> Materialize + -> Bitmap Heap Scan on tenk1 a + Recheck Cond: ((unique1 = 1) OR ((unique2 = 3) OR (unique2 = 7))) + Filter: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 = 1) -> Bitmap Index Scan on tenk1_unique2 - Index Cond: (unique2 = 7) -(19 rows) + Index Cond: (unique2 = ANY ('{3,7}'::integer[])) +(18 rows) + +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 < 20 or a.unique1 = 3 or a.unique1 = 1 and b.unique1 = 2) or + ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: ((a.unique1 < 20) OR (a.unique1 = 3) OR ((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4))) + -> Seq Scan on tenk1 b + -> Materialize + -> Bitmap Heap Scan on tenk1 a + Recheck Cond: ((unique1 < 20) OR ((unique1 = 3) OR (unique1 = 1)) OR ((unique2 = 3) OR (unique2 = 7))) + Filter: ((unique1 < 20) OR (unique1 = 3) OR (unique1 = 1) OR (unique2 = 3) OR (unique2 = 7)) + -> BitmapOr + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 < 20) + -> Bitmap Index Scan on tenk1_unique1 + Index Cond: (unique1 = ANY ('{3,1}'::integer[])) + -> Bitmap Index Scan on tenk1_unique2 + Index Cond: (unique2 = ANY ('{3,7}'::integer[])) +(14 rows) -- -- test placement of movable quals in a parameterized join tree @@ -5457,11 +5611,13 @@ CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int); CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int); CREATE TEMP TABLE c (id int PRIMARY KEY); CREATE TEMP TABLE d (a int, b int); +CREATE TEMP TABLE e (id1 int, id2 int, PRIMARY KEY(id1, id2)); INSERT INTO a VALUES (0, 0), (1, NULL); INSERT INTO b VALUES (0, 0), (1, NULL); INSERT INTO c VALUES (0), (1); INSERT INTO d VALUES (1,3), (2,2), (3,1); --- all three cases should be optimizable into a simple seqscan +INSERT INTO e VALUES (0,0), (2,2), (3,1); +-- all these cases should be optimizable into a simple seqscan explain (costs off) SELECT a.* FROM a LEFT JOIN b ON a.b_id = b.id; QUERY PLAN --------------- @@ -5482,6 +5638,14 @@ explain (costs off) Seq Scan on a (1 row) +explain (costs off) + SELECT a.* FROM a LEFT JOIN b ON a.id = b.id + LEFT JOIN e ON e.id1 = a.b_id AND b.c_id = e.id2; + QUERY PLAN +--------------- + Seq Scan on a +(1 row) + -- check optimization of outer join within another special join explain (costs off) select id from a where id in ( @@ -5802,6 +5966,27 @@ select c.id, ss.a from c -> Seq Scan on c (7 rows) +-- check the case when the placeholder relates to an outer join and its +-- inner in the press field but actually uses only the outer side of the join +explain (costs off) +SELECT q.val FROM b LEFT JOIN ( + SELECT (q1.z IS NOT NULL) AS val + FROM b LEFT JOIN ( + SELECT (t1.b_id IS NOT NULL) AS z FROM a t1 LEFT JOIN a t2 USING (id) + ) AS q1 + ON true +) AS q ON true; + QUERY PLAN +------------------------------------------ + Nested Loop Left Join + -> Seq Scan on b + -> Materialize + -> Nested Loop Left Join + -> Seq Scan on b b_1 + -> Materialize + -> Seq Scan on a t1 +(7 rows) + CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10); -- test join removals on a partitioned table @@ -6214,139 +6399,1247 @@ select * from (0 rows) -- --- Test hints given on incorrect column references are useful --- -select t1.uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion -ERROR: column t1.uunique1 does not exist -LINE 1: select t1.uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t1.unique1". -select t2.uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion -ERROR: column t2.uunique1 does not exist -LINE 1: select t2.uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t2.unique1". -select uunique1 from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once -ERROR: column "uunique1" does not exist -LINE 1: select uunique1 from - ^ -HINT: Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1". -select ctid from - tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, need qualification -ERROR: column "ctid" does not exist -LINE 1: select ctid from - ^ -DETAIL: There are columns named "ctid", but they are in tables that cannot be referenced from this part of the query. -HINT: Try using a table-qualified name. --- --- Take care to reference the correct RTE +-- test that semi- or inner self-joins on a unique column are removed -- -select atts.relid::regclass, s.* from pg_stats s join - pg_attribute a on s.attname = a.attname and s.tablename = - a.attrelid::regclass::text join (select unnest(indkey) attnum, - indexrelid from pg_index i) atts on atts.attnum = a.attnum where - schemaname != 'pg_catalog'; -ERROR: column atts.relid does not exist -LINE 1: select atts.relid::regclass, s.* from pg_stats s join - ^ --- Test bug in rangetable flattening -explain (verbose, costs off) -select 1 from - (select * from int8_tbl where q1 <> (select 42) offset 0) ss -where false; - QUERY PLAN --------------------------- - Result - Output: 1 - One-Time Filter: false -(3 rows) +-- enable only nestloop to get more predictable plans +set enable_hashjoin to off; +set enable_mergejoin to off; +create table sj (a int unique, b int, c int unique); +insert into sj values (1, null, 2), (null, 2, null), (2, 1, 1); +analyze sj; +-- Trivial self-join case. +explain (costs off) +select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; + QUERY PLAN +----------------------------------------------- + Seq Scan on sj q + Filter: ((a IS NOT NULL) AND (b = (a - 1))) +(2 rows) --- --- Test LATERAL --- -select unique2, x.* -from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; - unique2 | f1 ----------+---- - 9998 | 0 +select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; + a | b | c +---+---+--- + 2 | 1 | 1 (1 row) +-- Self-join removal performs after a subquery pull-up process and could remove +-- such kind of self-join too. Check this option. explain (costs off) - select unique2, x.* - from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; - QUERY PLAN -------------------------------------------------- - Nested Loop - -> Seq Scan on int4_tbl b - -> Index Scan using tenk1_unique1 on tenk1 a - Index Cond: (unique1 = b.f1) -(4 rows) +select * from sj p +where exists (select * from sj q + where q.a = p.a and q.b < 10); + QUERY PLAN +------------------------------------------ + Seq Scan on sj q + Filter: ((a IS NOT NULL) AND (b < 10)) +(2 rows) -select unique2, x.* -from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; - unique2 | f1 ----------+---- - 9998 | 0 +select * from sj p +where exists (select * from sj q + where q.a = p.a and q.b < 10); + a | b | c +---+---+--- + 2 | 1 | 1 (1 row) +-- Don't remove self-join for the case of equality of two different unique columns. explain (costs off) - select unique2, x.* - from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; - QUERY PLAN ------------------------------------------------ +select * from sj t1, sj t2 where t1.a = t2.c and t1.b is not null; + QUERY PLAN +--------------------------------------- Nested Loop - -> Seq Scan on int4_tbl x - -> Index Scan using tenk1_unique1 on tenk1 - Index Cond: (unique1 = x.f1) -(4 rows) + Join Filter: (t1.a = t2.c) + -> Seq Scan on sj t2 + -> Materialize + -> Seq Scan on sj t1 + Filter: (b IS NOT NULL) +(6 rows) +-- Ensure that relations with TABLESAMPLE clauses are not considered as +-- candidates to be removed explain (costs off) - select unique2, x.* - from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss; - QUERY PLAN ------------------------------------------------ +select * from sj t1 + join lateral + (select * from sj tablesample system(t1.b)) s + on t1.a = s.a; + QUERY PLAN +--------------------------------------- Nested Loop - -> Seq Scan on int4_tbl x - -> Index Scan using tenk1_unique1 on tenk1 - Index Cond: (unique1 = x.f1) -(4 rows) + -> Seq Scan on sj t1 + -> Memoize + Cache Key: t1.a, t1.b + Cache Mode: binary + -> Sample Scan on sj + Sampling: system (t1.b) + Filter: (t1.a = a) +(8 rows) -select unique2, x.* -from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; - unique2 | f1 ----------+------------- - 9998 | 0 - | 123456 - | -123456 - | 2147483647 - | -2147483647 -(5 rows) +-- Ensure that SJE does not form a self-referential lateral dependency +explain (costs off) +select * from sj t1 + left join lateral + (select t1.a as t1a, * from sj t2) s + on true +where t1.a = s.a; + QUERY PLAN +--------------------------- + Seq Scan on sj t2 + Filter: (a IS NOT NULL) +(2 rows) +-- Degenerated case. explain (costs off) - select unique2, x.* - from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; - QUERY PLAN ------------------------------------------------ - Nested Loop Left Join - -> Seq Scan on int4_tbl x - -> Index Scan using tenk1_unique1 on tenk1 - Index Cond: (unique1 = x.f1) -(4 rows) +select * from + (select a as x from sj where false) as q1, + (select a as y from sj where false) as q2 +where q1.x = q2.y; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) --- check scoping of lateral versus parent references --- the first of these should return int8_tbl.q2, the second int8_tbl.q1 -select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl; - q1 | q2 | r -------------------+-------------------+------------------- - 123 | 456 | 456 - 123 | 4567890123456789 | 4567890123456789 - 4567890123456789 | 123 | 123 - 4567890123456789 | 4567890123456789 | 4567890123456789 - 4567890123456789 | -4567890123456789 | -4567890123456789 -(5 rows) +-- We can't use a cross-EC generated self join qual because of current logic of +-- the generate_join_implied_equalities routine. +explain (costs off) +select * from sj t1, sj t2 where t1.a = t1.b and t1.b = t2.b and t2.b = t2.a; + QUERY PLAN +------------------------------ + Nested Loop + Join Filter: (t1.a = t2.b) + -> Seq Scan on sj t1 + Filter: (a = b) + -> Seq Scan on sj t2 + Filter: (b = a) +(6 rows) + +explain (costs off) +select * from sj t1, sj t2, sj t3 +where t1.a = t1.b and t1.b = t2.b and t2.b = t2.a and + t1.b = t3.b and t3.b = t3.a; + QUERY PLAN +------------------------------------ + Nested Loop + Join Filter: (t1.a = t3.b) + -> Nested Loop + Join Filter: (t1.a = t2.b) + -> Seq Scan on sj t1 + Filter: (a = b) + -> Seq Scan on sj t2 + Filter: (b = a) + -> Seq Scan on sj t3 + Filter: (b = a) +(10 rows) + +-- Double self-join removal. +-- Use a condition on "b + 1", not on "b", for the second join, so that +-- the equivalence class is different from the first one, and we can +-- test the non-ec code path. +explain (costs off) +select * +from sj t1 + join sj t2 on t1.a = t2.a and t1.b = t2.b + join sj t3 on t2.a = t3.a and t2.b + 1 = t3.b + 1; + QUERY PLAN +--------------------------------------------------------------------------- + Seq Scan on sj t3 + Filter: ((a IS NOT NULL) AND (b IS NOT NULL) AND ((b + 1) IS NOT NULL)) +(2 rows) + +-- subselect that references the removed relation +explain (costs off) +select t1.a, (select a from sj where a = t2.a and a = t1.a) +from sj t1, sj t2 +where t1.a = t2.a; + QUERY PLAN +------------------------------------------ + Seq Scan on sj t2 + Filter: (a IS NOT NULL) + SubPlan 1 + -> Result + One-Time Filter: (t2.a = t2.a) + -> Seq Scan on sj + Filter: (a = t2.a) +(7 rows) + +-- self-join under outer join +explain (costs off) +select * from sj x join sj y on x.a = y.a +left join int8_tbl z on x.a = z.q1; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + Join Filter: (y.a = z.q1) + -> Seq Scan on sj y + Filter: (a IS NOT NULL) + -> Materialize + -> Seq Scan on int8_tbl z +(6 rows) + +explain (costs off) +select * from sj x join sj y on x.a = y.a +left join int8_tbl z on y.a = z.q1; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + Join Filter: (y.a = z.q1) + -> Seq Scan on sj y + Filter: (a IS NOT NULL) + -> Materialize + -> Seq Scan on int8_tbl z +(6 rows) + +explain (costs off) +select * from ( + select t1.*, t2.a as ax from sj t1 join sj t2 + on (t1.a = t2.a and t1.c * t1.c = t2.c + 2 and t2.b is null) +) as q1 +left join + (select t3.* from sj t3, sj t4 where t3.c = t4.c) as q2 +on q1.ax = q2.a; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop Left Join + Join Filter: (t2.a = t4.a) + -> Seq Scan on sj t2 + Filter: ((b IS NULL) AND (a IS NOT NULL) AND ((c * c) = (c + 2))) + -> Seq Scan on sj t4 + Filter: (c IS NOT NULL) +(6 rows) + +-- Test that placeholders are updated correctly after join removal +explain (costs off) +select * from (values (1)) x +left join (select coalesce(y.q1, 1) from int8_tbl y + right join sj j1 inner join sj j2 on j1.a = j2.a + on true) z +on true; + QUERY PLAN +------------------------------------------ + Nested Loop Left Join + -> Result + -> Nested Loop Left Join + -> Seq Scan on sj j2 + Filter: (a IS NOT NULL) + -> Materialize + -> Seq Scan on int8_tbl y +(7 rows) + +-- Test that references to the removed rel in lateral subqueries are replaced +-- correctly after join removal +explain (verbose, costs off) +select t3.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select t1.a offset 0) t3 on true; + QUERY PLAN +------------------------------------ + Nested Loop + Output: (t2.a) + -> Seq Scan on public.sj t2 + Output: t2.a, t2.b, t2.c + Filter: (t2.a IS NOT NULL) + -> Result + Output: t2.a +(7 rows) + +explain (verbose, costs off) +select t3.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select * from (select t1.a offset 0) offset 0) t3 on true; + QUERY PLAN +------------------------------------ + Nested Loop + Output: (t2.a) + -> Seq Scan on public.sj t2 + Output: t2.a, t2.b, t2.c + Filter: (t2.a IS NOT NULL) + -> Result + Output: t2.a +(7 rows) + +explain (verbose, costs off) +select t4.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select t3.a from sj t3, (select t1.a) offset 0) t4 on true; + QUERY PLAN +------------------------------------ + Nested Loop + Output: t3.a + -> Seq Scan on public.sj t2 + Output: t2.a, t2.b, t2.c + Filter: (t2.a IS NOT NULL) + -> Seq Scan on public.sj t3 + Output: t3.a +(7 rows) + +-- Check updating of semi_rhs_exprs links from upper-level semi join to +-- the removing relation +explain (verbose, costs off) +select t1.a from sj t1 where t1.b in ( + select t2.b from sj t2 join sj t3 on t2.c=t3.c); + QUERY PLAN +------------------------------------------ + Nested Loop Semi Join + Output: t1.a + Join Filter: (t1.b = t3.b) + -> Seq Scan on public.sj t1 + Output: t1.a, t1.b, t1.c + -> Materialize + Output: t3.c, t3.b + -> Seq Scan on public.sj t3 + Output: t3.c, t3.b + Filter: (t3.c IS NOT NULL) +(10 rows) + +-- +-- SJE corner case: uniqueness of an inner is [partially] derived from +-- baserestrictinfo clauses. +-- XXX: We really should allow SJE for these corner cases? +-- +INSERT INTO sj VALUES (3, 1, 3); +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 3; + QUERY PLAN +------------------------------ + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j1 + Filter: (a = 2) + -> Seq Scan on sj j2 + Filter: (a = 3) +(6 rows) + +-- Return one row +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 3; + a | b | c | a | b | c +---+---+---+---+---+--- + 2 | 1 | 1 | 3 | 1 | 3 +(1 row) + +-- Remove SJ, define uniqueness by a constant +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 2; + QUERY PLAN +----------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND (a = 2)) +(2 rows) + +-- Return one row +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 2; + a | b | c | a | b | c +---+---+---+---+---+--- + 2 | 1 | 1 | 2 | 1 | 1 +(1 row) + +-- Remove SJ, define uniqueness by a constant expression +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND j1.a = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = j2.a; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND (a = (((EXTRACT(dow FROM CURRENT_TIMESTAMP(0)) / '15'::numeric) + '3'::numeric))::integer)) +(2 rows) + +-- Return one row +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND j1.a = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = j2.a; + a | b | c | a | b | c +---+---+---+---+---+--- + 3 | 1 | 3 | 3 | 1 | 3 +(1 row) + +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 1 AND j2.a = 1; + QUERY PLAN +----------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND (a = 1)) +(2 rows) + +-- Return no rows +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 1 AND j2.a = 1; + a | b | c | a | b | c +---+---+---+---+---+--- +(0 rows) + +-- Shuffle a clause. Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 1 = j1.a AND j2.a = 1; + QUERY PLAN +----------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND (a = 1)) +(2 rows) + +-- Return no rows +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 1 = j1.a AND j2.a = 1; + a | b | c | a | b | c +---+---+---+---+---+--- +(0 rows) + +-- SJE Corner case: a 'a.x=a.x' clause, have replaced with 'a.x IS NOT NULL' +-- after SJ elimination it shouldn't be a mergejoinable clause. +EXPLAIN (COSTS OFF) +SELECT t4.* +FROM (SELECT t1.*, t2.a AS a1 FROM sj t1, sj t2 WHERE t1.b = t2.b) AS t3 +JOIN sj t4 ON (t4.a = t3.a) WHERE t3.a1 = 42; + QUERY PLAN +--------------------------------- + Nested Loop + Join Filter: (t1.b = t2.b) + -> Seq Scan on sj t2 + Filter: (a = 42) + -> Seq Scan on sj t1 + Filter: (a IS NOT NULL) +(6 rows) + +SELECT t4.* +FROM (SELECT t1.*, t2.a AS a1 FROM sj t1, sj t2 WHERE t1.b = t2.b) AS t3 +JOIN sj t4 ON (t4.a = t3.a) WHERE t3.a1 = 42; + a | b | c +---+---+--- +(0 rows) + +-- Functional index +CREATE UNIQUE INDEX sj_fn_idx ON sj((a * a)); +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a*j1.a = 1 AND j2.a*j2.a = 1; + QUERY PLAN +----------------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND ((a * a) = 1)) +(2 rows) + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a*j1.a = 1 AND j2.a*j2.a = 2; + QUERY PLAN +------------------------------- + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j1 + Filter: ((a * a) = 1) + -> Seq Scan on sj j2 + Filter: ((a * a) = 2) +(6 rows) + +-- Restriction contains expressions in both sides, Remove SJ. +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.a) = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = (j2.a*j2.a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND ((a * a) = (((EXTRACT(dow FROM CURRENT_TIMESTAMP(0)) / '15'::numeric) + '3'::numeric))::integer)) +(2 rows) + +-- Empty set of rows should be returned +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.a) = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = (j2.a*j2.a); + a | b | c | a | b | c +---+---+---+---+---+--- +(0 rows) + +-- Restriction contains volatile function - disable SJE feature. +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.c/3) = (random()/3 + 3)::int + AND (random()/3 + 3)::int = (j2.a*j2.c/3); + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j1 + Filter: (((a * c) / 3) = (((random() / '3'::double precision) + '3'::double precision))::integer) + -> Seq Scan on sj j2 + Filter: ((((random() / '3'::double precision) + '3'::double precision))::integer = ((a * c) / 3)) +(6 rows) + +-- Return one row +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.c/3) = (random()/3 + 3)::int + AND (random()/3 + 3)::int = (j2.a*j2.c/3); + a | b | c | a | b | c +---+---+---+---+---+--- + 3 | 1 | 3 | 3 | 1 | 3 +(1 row) + +-- Multiple filters +CREATE UNIQUE INDEX sj_temp_idx1 ON sj(a,b,c); +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a = 2 AND j1.c = 3 AND j2.a = 2 AND 3 = j2.c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on sj j2 + Filter: ((b IS NOT NULL) AND (a = 2) AND (c = 3)) +(2 rows) + +-- Don't remove SJ +EXPLAIN (COSTS OFF) + SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND 2 = j1.a AND j1.c = 3 AND j2.a = 1 AND 3 = j2.c; + QUERY PLAN +--------------------------------------- + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j1 + Filter: ((2 = a) AND (c = 3)) + -> Seq Scan on sj j2 + Filter: ((c = 3) AND (a = 1)) +(6 rows) + +CREATE UNIQUE INDEX sj_temp_idx ON sj(a,b); +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2; + QUERY PLAN +------------------------------ + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j1 + Filter: (a = 2) + -> Seq Scan on sj j2 +(5 rows) + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 2 = j2.a; + QUERY PLAN +------------------------------ + Nested Loop + Join Filter: (j1.b = j2.b) + -> Seq Scan on sj j2 + Filter: (2 = a) + -> Seq Scan on sj j1 +(5 rows) + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND (j1.a = 1 OR j2.a = 1); + QUERY PLAN +--------------------------------------------------------------- + Nested Loop + Join Filter: ((j1.b = j2.b) AND ((j1.a = 1) OR (j2.a = 1))) + -> Seq Scan on sj j1 + -> Materialize + -> Seq Scan on sj j2 +(5 rows) + +DROP INDEX sj_fn_idx, sj_temp_idx1, sj_temp_idx; +-- Test that OR predicated are updated correctly after join removal +CREATE TABLE tab_with_flag ( id INT PRIMARY KEY, is_flag SMALLINT); +CREATE INDEX idx_test_is_flag ON tab_with_flag (is_flag); +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tab_with_flag +WHERE + (is_flag IS NULL OR is_flag = 0) + AND id IN (SELECT id FROM tab_with_flag WHERE id IN (2, 3)); + QUERY PLAN +----------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on tab_with_flag + Recheck Cond: (id = ANY ('{2,3}'::integer[])) + Filter: ((is_flag IS NULL) OR (is_flag = 0)) + -> Bitmap Index Scan on tab_with_flag_pkey + Index Cond: (id = ANY ('{2,3}'::integer[])) +(6 rows) + +DROP TABLE tab_with_flag; +-- HAVING clause +explain (costs off) +select p.b from sj p join sj q on p.a = q.a group by p.b having sum(p.a) = 1; + QUERY PLAN +--------------------------------- + HashAggregate + Group Key: q.b + Filter: (sum(q.a) = 1) + -> Seq Scan on sj q + Filter: (a IS NOT NULL) +(5 rows) + +-- update lateral references and range table entry reference +explain (verbose, costs off) +select 1 from (select x.* from sj x, sj y where x.a = y.a) q, + lateral generate_series(1, q.a) gs(i); + QUERY PLAN +------------------------------------------------------ + Nested Loop + Output: 1 + -> Seq Scan on public.sj y + Output: y.a, y.b, y.c + Filter: (y.a IS NOT NULL) + -> Function Scan on pg_catalog.generate_series gs + Output: gs.i + Function Call: generate_series(1, y.a) +(8 rows) + +explain (verbose, costs off) +select 1 from (select y.* from sj x, sj y where x.a = y.a) q, + lateral generate_series(1, q.a) gs(i); + QUERY PLAN +------------------------------------------------------ + Nested Loop + Output: 1 + -> Seq Scan on public.sj y + Output: y.a, y.b, y.c + Filter: (y.a IS NOT NULL) + -> Function Scan on pg_catalog.generate_series gs + Output: gs.i + Function Call: generate_series(1, y.a) +(8 rows) + +-- Test that a non-EC-derived join clause is processed correctly. Use an +-- outer join so that we can't form an EC. +explain (costs off) select * from sj p join sj q on p.a = q.a + left join sj r on p.a + q.a = r.a; + QUERY PLAN +------------------------------------ + Nested Loop Left Join + Join Filter: ((q.a + q.a) = r.a) + -> Seq Scan on sj q + Filter: (a IS NOT NULL) + -> Materialize + -> Seq Scan on sj r +(6 rows) + +-- FIXME this constant false filter doesn't look good. Should we merge +-- equivalence classes? +explain (costs off) +select * from sj p, sj q where p.a = q.a and p.b = 1 and q.b = 2; + QUERY PLAN +----------------------------------------------------- + Seq Scan on sj q + Filter: ((a IS NOT NULL) AND (b = 2) AND (b = 1)) +(2 rows) + +-- Check that attr_needed is updated correctly after self-join removal. In this +-- test, the join of j1 with j2 is removed. k1.b is required at either j1 or j2. +-- If this info is lost, join targetlist for (k1, k2) will not contain k1.b. +-- Use index scan for k1 so that we don't get 'b' from physical tlist used for +-- seqscan. Also disable reordering of joins because this test depends on a +-- particular join tree. +create table sk (a int, b int); +create index on sk(a); +set join_collapse_limit to 1; +set enable_seqscan to off; +explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j1.b = k1.b; + QUERY PLAN +----------------------------------------------------- + Nested Loop + Join Filter: (k1.b = j2.b) + -> Nested Loop + -> Index Scan using sk_a_idx on sk k1 + -> Index Only Scan using sk_a_idx on sk k2 + Index Cond: (a = k1.a) + -> Materialize + -> Index Scan using sj_a_key on sj j2 + Index Cond: (a IS NOT NULL) +(9 rows) + +explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j2.b = k1.b; + QUERY PLAN +----------------------------------------------------- + Nested Loop + Join Filter: (k1.b = j2.b) + -> Nested Loop + -> Index Scan using sk_a_idx on sk k1 + -> Index Only Scan using sk_a_idx on sk k2 + Index Cond: (a = k1.a) + -> Materialize + -> Index Scan using sj_a_key on sj j2 + Index Cond: (a IS NOT NULL) +(9 rows) + +reset join_collapse_limit; +reset enable_seqscan; +-- Check that clauses from the join filter list is not lost on the self-join removal +CREATE TABLE emp1 (id SERIAL PRIMARY KEY NOT NULL, code int); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM emp1 e1, emp1 e2 WHERE e1.id = e2.id AND e2.code <> e1.code; + QUERY PLAN +------------------------------------------ + Seq Scan on public.emp1 e2 + Output: e2.id, e2.code, e2.id, e2.code + Filter: (e2.code <> e2.code) +(3 rows) + +-- Shuffle self-joined relations. Only in the case of iterative deletion +-- attempts explains of these queries will be identical. +CREATE UNIQUE INDEX ON emp1((id*id)); +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c1.id=c2.id AND c1.id*c2.id=c3.id*c3.id; + QUERY PLAN +----------------------------------------- + Aggregate + -> Seq Scan on emp1 c3 + Filter: ((id * id) IS NOT NULL) +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c1.id=c3.id AND c1.id*c3.id=c2.id*c2.id; + QUERY PLAN +----------------------------------------- + Aggregate + -> Seq Scan on emp1 c3 + Filter: ((id * id) IS NOT NULL) +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c3.id=c2.id AND c3.id*c2.id=c1.id*c1.id; + QUERY PLAN +----------------------------------------- + Aggregate + -> Seq Scan on emp1 c3 + Filter: ((id * id) IS NOT NULL) +(3 rows) + +-- Check the usage of a parse tree by the set operations (bug #18170) +EXPLAIN (COSTS OFF) +SELECT c1.code FROM emp1 c1 LEFT JOIN emp1 c2 ON c1.id = c2.id +WHERE c2.id IS NOT NULL +EXCEPT ALL +SELECT c3.code FROM emp1 c3; + QUERY PLAN +--------------------------- + HashSetOp Except All + -> Seq Scan on emp1 c2 + -> Seq Scan on emp1 c3 +(3 rows) + +-- Check that SJE removes references from PHVs correctly +explain (costs off) +select * from emp1 t1 left join + (select coalesce(t3.code, 1) from emp1 t2 + left join (emp1 t3 join emp1 t4 on t3.id = t4.id) + on true) +on true; + QUERY PLAN +--------------------------------------------- + Nested Loop Left Join + -> Seq Scan on emp1 t1 + -> Materialize + -> Nested Loop Left Join + -> Seq Scan on emp1 t2 + -> Materialize + -> Seq Scan on emp1 t4 +(7 rows) + +-- Try PHV, which could potentially be removed completely by SJE, but that's +-- not implemented yet. +explain (verbose, costs off) +select 1 from emp1 t1 left join + ((select 1 as x, * from emp1 t2) s1 inner join + (select * from emp1 t3) s2 on s1.id = s2.id) + on true +where s1.x = 1; + QUERY PLAN +---------------------------------------- + Nested Loop + Output: 1 + -> Seq Scan on public.emp1 t1 + Output: t1.id, t1.code + -> Materialize + Output: t3.id + -> Seq Scan on public.emp1 t3 + Output: t3.id + Filter: (1 = 1) +(9 rows) + +-- Check that PHVs do not impose any constraints on removing self joins +explain (verbose, costs off) +select * from emp1 t1 join emp1 t2 on t1.id = t2.id left join + lateral (select t1.id as t1id, * from generate_series(1,1) t3) s on true; + QUERY PLAN +---------------------------------------------------------- + Nested Loop Left Join + Output: t2.id, t2.code, t2.id, t2.code, (t2.id), t3.t3 + -> Seq Scan on public.emp1 t2 + Output: t2.id, t2.code + -> Function Scan on pg_catalog.generate_series t3 + Output: t3.t3, t2.id + Function Call: generate_series(1, 1) +(7 rows) + +explain (verbose, costs off) +select * from generate_series(1,10) t1(id) left join + lateral (select t1.id as t1id, t2.id from emp1 t2 join emp1 t3 on t2.id = t3.id) +on true; + QUERY PLAN +------------------------------------------------------ + Nested Loop Left Join + Output: t1.id, (t1.id), t3.id + -> Function Scan on pg_catalog.generate_series t1 + Output: t1.id + Function Call: generate_series(1, 10) + -> Seq Scan on public.emp1 t3 + Output: t3.id, t1.id +(7 rows) + +-- This is a degenerate case of PHV usage: it is evaluated and needed inside +-- a baserel scan operation that the SJE removes. The PHV in this test should +-- be in the filter of parameterized Index Scan: the replace_nestloop_params() +-- code will detect if the placeholder list doesn't have a reference to this +-- parameter. +-- +-- NOTE: enable_hashjoin and enable_mergejoin must be disabled. +CREATE TABLE tbl_phv(x int, y int PRIMARY KEY); +CREATE INDEX tbl_phv_idx ON tbl_phv(x); +INSERT INTO tbl_phv (x, y) + SELECT gs, gs FROM generate_series(1,100) AS gs; +VACUUM ANALYZE tbl_phv; +EXPLAIN (COSTS OFF, VERBOSE) +SELECT 1 FROM tbl_phv t1 LEFT JOIN + (SELECT 1 extra, x, y FROM tbl_phv tl) t3 JOIN + (SELECT y FROM tbl_phv tr) t4 + ON t4.y = t3.y +ON true WHERE t3.extra IS NOT NULL AND t3.x = t1.x % 2; + QUERY PLAN +--------------------------------------------------------- + Nested Loop + Output: 1 + -> Seq Scan on public.tbl_phv t1 + Output: t1.x, t1.y + -> Index Scan using tbl_phv_idx on public.tbl_phv tr + Output: tr.x, tr.y + Index Cond: (tr.x = (t1.x % 2)) + Filter: (1 IS NOT NULL) +(8 rows) + +DROP TABLE IF EXISTS tbl_phv; +-- Check that SJE replaces join clauses involving the removed rel correctly +explain (costs off) +select * from emp1 t1 + inner join emp1 t2 on t1.id = t2.id + left join emp1 t3 on t1.id > 1 and t1.id < 2; + QUERY PLAN +---------------------------------------------- + Nested Loop Left Join + Join Filter: ((t2.id > 1) AND (t2.id < 2)) + -> Seq Scan on emp1 t2 + -> Materialize + -> Seq Scan on emp1 t3 +(5 rows) + +-- Check that SJE doesn't replace the target relation +EXPLAIN (COSTS OFF) +WITH t1 AS (SELECT * FROM emp1) +UPDATE emp1 SET code = t1.code + 1 FROM t1 +WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code; + QUERY PLAN +------------------------------------------------------- + Update on emp1 + -> Nested Loop + -> Seq Scan on emp1 + -> Index Scan using emp1_pkey on emp1 emp1_1 + Index Cond: (id = emp1.id) +(5 rows) + +-- Check that SJE correctly replaces relations in OR-clauses +EXPLAIN (COSTS OFF) +SELECT * FROM emp1 t1 + INNER JOIN emp1 t2 ON t1.id = t2.id + LEFT JOIN emp1 t3 ON t1.code = 1 AND (t2.code = t3.code OR t2.code = 1); + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop Left Join + Join Filter: ((t2.code = 1) AND ((t2.code = t3.code) OR (t2.code = 1))) + -> Seq Scan on emp1 t2 + -> Materialize + -> Seq Scan on emp1 t3 +(5 rows) + + INSERT INTO emp1 VALUES (1, 1), (2, 1); +WITH t1 AS (SELECT * FROM emp1) +UPDATE emp1 SET code = t1.code + 1 FROM t1 +WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code; + id | code | code +----+------+------ + 1 | 2 | 1 + 2 | 2 | 1 +(2 rows) + +TRUNCATE emp1; +EXPLAIN (COSTS OFF) +UPDATE sj sq SET b = 1 FROM sj as sz WHERE sq.a = sz.a; + QUERY PLAN +------------------------------------- + Update on sj sq + -> Nested Loop + Join Filter: (sq.a = sz.a) + -> Seq Scan on sj sq + -> Materialize + -> Seq Scan on sj sz +(6 rows) + +CREATE RULE sj_del_rule AS ON DELETE TO sj + DO INSTEAD + UPDATE sj SET a = 1 WHERE a = old.a; +EXPLAIN (COSTS OFF) DELETE FROM sj; + QUERY PLAN +-------------------------------------- + Update on sj sj_1 + -> Nested Loop + Join Filter: (sj.a = sj_1.a) + -> Seq Scan on sj sj_1 + -> Materialize + -> Seq Scan on sj +(6 rows) + +DROP RULE sj_del_rule ON sj CASCADE; +-- Check that SJE does not mistakenly omit qual clauses (bug #18187) +insert into emp1 values (1, 1); +explain (costs off) +select 1 from emp1 full join + (select * from emp1 t1 join + emp1 t2 join emp1 t3 on t2.id = t3.id + on true + where false) s on true +where false; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +select 1 from emp1 full join + (select * from emp1 t1 join + emp1 t2 join emp1 t3 on t2.id = t3.id + on true + where false) s on true +where false; + ?column? +---------- +(0 rows) + +-- Check that SJE does not mistakenly re-use knowledge of relation uniqueness +-- made with different set of quals +insert into emp1 values (2, 1); +explain (costs off) +select * from emp1 t1 where exists (select * from emp1 t2 + where t2.id = t1.code and t2.code > 0); + QUERY PLAN +--------------------------------------------- + Nested Loop + -> Seq Scan on emp1 t1 + -> Index Scan using emp1_pkey on emp1 t2 + Index Cond: (id = t1.code) + Filter: (code > 0) +(5 rows) + +select * from emp1 t1 where exists (select * from emp1 t2 + where t2.id = t1.code and t2.code > 0); + id | code +----+------ + 1 | 1 + 2 | 1 +(2 rows) + +-- We can remove the join even if we find the join can't duplicate rows and +-- the base quals of each side are different. In the following case we end up +-- moving quals over to s1 to make it so it can't match any rows. +create table sl(a int, b int, c int); +create unique index on sl(a, b); +vacuum analyze sl; +-- Both sides are unique, but base quals are different +explain (costs off) +select * from sl t1, sl t2 where t1.a = t2.a and t1.b = 1 and t2.b = 2; + QUERY PLAN +------------------------------ + Nested Loop + Join Filter: (t1.a = t2.a) + -> Seq Scan on sl t1 + Filter: (b = 1) + -> Seq Scan on sl t2 + Filter: (b = 2) +(6 rows) + +-- Check NullTest in baserestrictinfo list +explain (costs off) +select * from sl t1, sl t2 +where t1.a = t2.a and t1.b = 1 and t2.b = 2 + and t1.c IS NOT NULL and t2.c IS NOT NULL + and t2.b IS NOT NULL and t1.b IS NOT NULL + and t1.a IS NOT NULL and t2.a IS NOT NULL; + QUERY PLAN +--------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (t1.a = t2.a) + -> Seq Scan on sl t1 + Filter: ((c IS NOT NULL) AND (b IS NOT NULL) AND (a IS NOT NULL) AND (b = 1)) + -> Seq Scan on sl t2 + Filter: ((c IS NOT NULL) AND (b IS NOT NULL) AND (a IS NOT NULL) AND (b = 2)) +(6 rows) + +explain (verbose, costs off) +select * from sl t1, sl t2 +where t1.b = t2.b and t2.a = 3 and t1.a = 3 + and t1.c IS NOT NULL and t2.c IS NOT NULL + and t2.b IS NOT NULL and t1.b IS NOT NULL + and t1.a IS NOT NULL and t2.a IS NOT NULL; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Seq Scan on public.sl t2 + Output: t2.a, t2.b, t2.c, t2.a, t2.b, t2.c + Filter: ((t2.c IS NOT NULL) AND (t2.b IS NOT NULL) AND (t2.a IS NOT NULL) AND (t2.a = 3)) +(3 rows) + +-- Join qual isn't mergejoinable, but inner is unique. +EXPLAIN (COSTS OFF) +SELECT n2.a FROM sj n1, sj n2 WHERE n1.a <> n2.a AND n2.a = 1; + QUERY PLAN +------------------------------- + Nested Loop + Join Filter: (n1.a <> n2.a) + -> Seq Scan on sj n2 + Filter: (a = 1) + -> Seq Scan on sj n1 +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM +(SELECT n2.a FROM sj n1, sj n2 WHERE n1.a <> n2.a) q0, sl +WHERE q0.a = 1; + QUERY PLAN +------------------------------- + Nested Loop + Join Filter: (n1.a <> n2.a) + -> Nested Loop + -> Seq Scan on sl + -> Seq Scan on sj n2 + Filter: (a = 1) + -> Seq Scan on sj n1 +(7 rows) + +-- Check optimization disabling if it will violate special join conditions. +-- Two identical joined relations satisfies self join removal conditions but +-- stay in different special join infos. +CREATE TABLE sj_t1 (id serial, a int); +CREATE TABLE sj_t2 (id serial, a int); +CREATE TABLE sj_t3 (id serial, a int); +CREATE TABLE sj_t4 (id serial, a int); +CREATE UNIQUE INDEX ON sj_t3 USING btree (a,id); +CREATE UNIQUE INDEX ON sj_t2 USING btree (id); +EXPLAIN (COSTS OFF) +SELECT * FROM sj_t1 +JOIN ( + SELECT sj_t2.id AS id FROM sj_t2 + WHERE EXISTS + ( + SELECT TRUE FROM sj_t3,sj_t4 WHERE sj_t3.a = 1 AND sj_t3.id = sj_t2.id + ) + ) t2t3t4 +ON sj_t1.id = t2t3t4.id +JOIN ( + SELECT sj_t2.id AS id FROM sj_t2 + WHERE EXISTS + ( + SELECT TRUE FROM sj_t3,sj_t4 WHERE sj_t3.a = 1 AND sj_t3.id = sj_t2.id + ) + ) _t2t3t4 +ON sj_t1.id = _t2t3t4.id; + QUERY PLAN +------------------------------------------------------------------------------------- + Nested Loop + Join Filter: (sj_t3.id = sj_t1.id) + -> Nested Loop + Join Filter: (sj_t2.id = sj_t3.id) + -> Nested Loop Semi Join + -> Nested Loop + -> HashAggregate + Group Key: sj_t3.id + -> Nested Loop + -> Seq Scan on sj_t4 + -> Materialize + -> Bitmap Heap Scan on sj_t3 + Recheck Cond: (a = 1) + -> Bitmap Index Scan on sj_t3_a_id_idx + Index Cond: (a = 1) + -> Index Only Scan using sj_t2_id_idx on sj_t2 sj_t2_1 + Index Cond: (id = sj_t3.id) + -> Nested Loop + -> Index Only Scan using sj_t3_a_id_idx on sj_t3 sj_t3_1 + Index Cond: ((a = 1) AND (id = sj_t3.id)) + -> Seq Scan on sj_t4 sj_t4_1 + -> Index Only Scan using sj_t2_id_idx on sj_t2 + Index Cond: (id = sj_t2_1.id) + -> Seq Scan on sj_t1 +(24 rows) + +-- +-- Test RowMarks-related code +-- +-- Both sides have explicit LockRows marks +EXPLAIN (COSTS OFF) +SELECT a1.a FROM sj a1,sj a2 WHERE (a1.a=a2.a) FOR UPDATE; + QUERY PLAN +--------------------------------- + LockRows + -> Seq Scan on sj a2 + Filter: (a IS NOT NULL) +(3 rows) + +reset enable_hashjoin; +reset enable_mergejoin; +-- +-- Test hints given on incorrect column references are useful +-- +select t1.uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion +ERROR: column t1.uunique1 does not exist +LINE 1: select t1.uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t1.unique1". +select t2.uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion +ERROR: column t2.uunique1 does not exist +LINE 1: select t2.uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t2.unique1". +select uunique1 from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once +ERROR: column "uunique1" does not exist +LINE 1: select uunique1 from + ^ +HINT: Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1". +select ctid from + tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, need qualification +ERROR: column "ctid" does not exist +LINE 1: select ctid from + ^ +DETAIL: There are columns named "ctid", but they are in tables that cannot be referenced from this part of the query. +HINT: Try using a table-qualified name. +-- +-- Take care to reference the correct RTE +-- +select atts.relid::regclass, s.* from pg_stats s join + pg_attribute a on s.attname = a.attname and s.tablename = + a.attrelid::regclass::text join (select unnest(indkey) attnum, + indexrelid from pg_index i) atts on atts.attnum = a.attnum where + schemaname != 'pg_catalog'; +ERROR: column atts.relid does not exist +LINE 1: select atts.relid::regclass, s.* from pg_stats s join + ^ +-- Test bug in rangetable flattening +explain (verbose, costs off) +select 1 from + (select * from int8_tbl where q1 <> (select 42) offset 0) ss +where false; + QUERY PLAN +-------------------------- + Result + Output: 1 + One-Time Filter: false +(3 rows) + +-- +-- Test LATERAL +-- +select unique2, x.* +from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; + unique2 | f1 +---------+---- + 9998 | 0 +(1 row) + +explain (costs off) + select unique2, x.* + from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; + QUERY PLAN +------------------------------------------------- + Nested Loop + -> Seq Scan on int4_tbl b + -> Index Scan using tenk1_unique1 on tenk1 a + Index Cond: (unique1 = b.f1) +(4 rows) + +select unique2, x.* +from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; + unique2 | f1 +---------+---- + 9998 | 0 +(1 row) + +explain (costs off) + select unique2, x.* + from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; + QUERY PLAN +----------------------------------------------- + Nested Loop + -> Seq Scan on int4_tbl x + -> Index Scan using tenk1_unique1 on tenk1 + Index Cond: (unique1 = x.f1) +(4 rows) + +explain (costs off) + select unique2, x.* + from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss; + QUERY PLAN +----------------------------------------------- + Nested Loop + -> Seq Scan on int4_tbl x + -> Index Scan using tenk1_unique1 on tenk1 + Index Cond: (unique1 = x.f1) +(4 rows) + +select unique2, x.* +from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; + unique2 | f1 +---------+------------- + 9998 | 0 + | 123456 + | -123456 + | 2147483647 + | -2147483647 +(5 rows) + +explain (costs off) + select unique2, x.* + from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; + QUERY PLAN +----------------------------------------------- + Nested Loop Left Join + -> Seq Scan on int4_tbl x + -> Index Scan using tenk1_unique1 on tenk1 + Index Cond: (unique1 = x.f1) +(4 rows) + +-- check scoping of lateral versus parent references +-- the first of these should return int8_tbl.q2, the second int8_tbl.q1 +select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl; + q1 | q2 | r +------------------+-------------------+------------------- + 123 | 456 | 456 + 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | -4567890123456789 | -4567890123456789 +(5 rows) select *, (select r from (select q1 as q2) x, lateral (select q2 as r) y) from int8_tbl; q1 | q2 | r @@ -8001,12 +9294,13 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS --------------------------------------------------------- Nested Loop Anti Join -> Seq Scan on skip_fetch t1 + Disabled: true -> Materialize -> Bitmap Heap Scan on skip_fetch t2 Recheck Cond: (a = 1) -> Bitmap Index Scan on skip_fetch_a_idx Index Cond: (a = 1) -(7 rows) +(8 rows) SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL; a @@ -8015,3 +9309,101 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS RESET enable_indexonlyscan; RESET enable_seqscan; +-- Test BitmapHeapScan with a rescan releases resources correctly +SET enable_seqscan = off; +SET enable_indexscan = off; +CREATE TEMP TABLE rescan_bhs (a INT); +INSERT INTO rescan_bhs VALUES (1), (2); +CREATE INDEX ON rescan_bhs (a); +EXPLAIN (COSTS OFF) +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + Join Filter: (ANY (t1.a = (SubPlan 1).col1)) + -> Bitmap Heap Scan on rescan_bhs t1 + -> Bitmap Index Scan on rescan_bhs_a_idx + -> Materialize + -> Bitmap Heap Scan on rescan_bhs t2 + -> Bitmap Index Scan on rescan_bhs_a_idx + SubPlan 1 + -> Result + One-Time Filter: (t2.a > 1) + -> Bitmap Heap Scan on rescan_bhs t3 + -> Bitmap Index Scan on rescan_bhs_a_idx +(12 rows) + +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + a | a +---+--- + 1 | 2 + 2 | 2 +(2 rows) + +RESET enable_seqscan; +RESET enable_indexscan; +-- Test that we do not account for nullingrels when looking up statistics +CREATE TABLE group_tbl (a INT, b INT); +INSERT INTO group_tbl SELECT 1, 1; +CREATE STATISTICS group_tbl_stat (ndistinct) ON a, b FROM group_tbl; +ANALYZE group_tbl; +EXPLAIN (COSTS OFF) +SELECT 1 FROM group_tbl t1 + LEFT JOIN (SELECT a c1, COALESCE(a) c2 FROM group_tbl t2) s ON TRUE +GROUP BY s.c1, s.c2; + QUERY PLAN +-------------------------------------------- + Group + Group Key: t2.a, (COALESCE(t2.a)) + -> Sort + Sort Key: t2.a, (COALESCE(t2.a)) + -> Nested Loop Left Join + -> Seq Scan on group_tbl t1 + -> Seq Scan on group_tbl t2 +(7 rows) + +DROP TABLE group_tbl; +-- +-- Test for a nested loop join involving index scan, transforming OR-clauses +-- to SAOP. +-- +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + QUERY PLAN +----------------------------------------------------------------------------------------- + Aggregate + -> Nested Loop + -> Seq Scan on tenk1 t1 + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = ANY (ARRAY[t1.tenthous, t1.unique1, t1.unique2])) +(5 rows) + +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + count +------- + 20000 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); + QUERY PLAN +------------------------------------------------------------------------------ + Aggregate + -> Nested Loop Left Join + -> Seq Scan on onek t1 + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = ANY (ARRAY[t1.tenthous, t1.thousand])) +(5 rows) + +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); + count +------- + 19000 +(1 row) + diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index aa29bc597bde2..04b478cb468db 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -55,6 +55,54 @@ SELECT ('"'||repeat('.', 12)||'abc\n"')::json; -- OK, legal escapes "............abc\n" (1 row) +-- Test various lengths of strings to validate SIMD processing to escape +-- special chars in the JSON. +SELECT row_to_json(j)::jsonb FROM ( + SELECT left(E'abcdefghijklmnopqrstuv"\twxyz012345678', a) AS a + FROM generate_series(0,37) a +) j; + row_to_json +-------------------------------------------------- + {"a": ""} + {"a": "a"} + {"a": "ab"} + {"a": "abc"} + {"a": "abcd"} + {"a": "abcde"} + {"a": "abcdef"} + {"a": "abcdefg"} + {"a": "abcdefgh"} + {"a": "abcdefghi"} + {"a": "abcdefghij"} + {"a": "abcdefghijk"} + {"a": "abcdefghijkl"} + {"a": "abcdefghijklm"} + {"a": "abcdefghijklmn"} + {"a": "abcdefghijklmno"} + {"a": "abcdefghijklmnop"} + {"a": "abcdefghijklmnopq"} + {"a": "abcdefghijklmnopqr"} + {"a": "abcdefghijklmnopqrs"} + {"a": "abcdefghijklmnopqrst"} + {"a": "abcdefghijklmnopqrstu"} + {"a": "abcdefghijklmnopqrstuv"} + {"a": "abcdefghijklmnopqrstuv\""} + {"a": "abcdefghijklmnopqrstuv\"\t"} + {"a": "abcdefghijklmnopqrstuv\"\tw"} + {"a": "abcdefghijklmnopqrstuv\"\twx"} + {"a": "abcdefghijklmnopqrstuv\"\twxy"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz0"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz01"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz012"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz0123"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz01234"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz012345"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz0123456"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz01234567"} + {"a": "abcdefghijklmnopqrstuv\"\twxyz012345678"} +(38 rows) + -- see json_encoding test for input with unicode escapes -- Numbers. SELECT '1'::json; -- OK @@ -2282,6 +2330,9 @@ select json_object('{a,b,"","d e f"}','{1,2,3,"a b c"}'); {"a" : "1", "b" : "2", "" : "3", "d e f" : "a b c"} (1 row) +-- json_object_agg_unique requires unique keys +select json_object_agg_unique(mod(i,100), i) from generate_series(0, 199) i; +ERROR: duplicate JSON object key value: "0" -- json_to_record and json_to_recordset select * from json_to_record('{"a":1,"b":"foo","c":"bar"}') as x(a int, b text, d text); @@ -2453,6 +2504,56 @@ select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); {"a":{},"d":{}} (1 row) +-- json_strip_nulls (strip_in_arrays=true) +select json_strip_nulls(null, true); + json_strip_nulls +------------------ + +(1 row) + +select json_strip_nulls('1', true); + json_strip_nulls +------------------ + 1 +(1 row) + +select json_strip_nulls('"a string"', true); + json_strip_nulls +------------------ + "a string" +(1 row) + +select json_strip_nulls('null', true); + json_strip_nulls +------------------ + null +(1 row) + +select json_strip_nulls('[1,2,null,3,4]', true); + json_strip_nulls +------------------ + [1,2,3,4] +(1 row) + +select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + json_strip_nulls +------------------------------- + {"a":1,"c":[2,3],"d":{"e":4}} +(1 row) + +select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + json_strip_nulls +--------------------- + [1,{"a":1,"c":2},3] +(1 row) + +-- an empty object is not null and should not be stripped +select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + json_strip_nulls +------------------ + {"a":{},"d":{}} +(1 row) + -- json to tsvector select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json); to_tsvector diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index e66d7601899c8..5a1eb18aba29e 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -680,6 +680,12 @@ select '"foo"'::jsonb -> 'z'; (1 row) +select '[]'::jsonb -> -2147483648; + ?column? +---------- + +(1 row) + select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> null::text; ?column? ---------- @@ -746,6 +752,12 @@ select '"foo"'::jsonb ->> 'z'; (1 row) +select '[]'::jsonb ->> -2147483648; + ?column? +---------- + +(1 row) + -- equality and inequality SELECT '{"x":"y"}'::jsonb = '{"x":"y"}'::jsonb; ?column? @@ -4141,6 +4153,56 @@ select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); {"a": {}, "d": {}} (1 row) +-- jsonb_strip_nulls (strip_in_arrays=true) +select jsonb_strip_nulls(null, true); + jsonb_strip_nulls +------------------- + +(1 row) + +select jsonb_strip_nulls('1', true); + jsonb_strip_nulls +------------------- + 1 +(1 row) + +select jsonb_strip_nulls('"a string"', true); + jsonb_strip_nulls +------------------- + "a string" +(1 row) + +select jsonb_strip_nulls('null', true); + jsonb_strip_nulls +------------------- + null +(1 row) + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + jsonb_strip_nulls +------------------- + [1, 2, 3, 4] +(1 row) + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + jsonb_strip_nulls +-------------------------------------- + {"a": 1, "c": [2, 3], "d": {"e": 4}} +(1 row) + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + jsonb_strip_nulls +-------------------------- + [1, {"a": 1, "c": 2}, 3] +(1 row) + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + jsonb_strip_nulls +-------------------- + {"a": {}, "d": {}} +(1 row) + select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); jsonb_pretty ---------------------------- @@ -4575,6 +4637,12 @@ select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2, {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null} (1 row) +select jsonb_delete_path('{"a":[]}', '{"a",-2147483648}'); + jsonb_delete_path +------------------- + {"a": []} +(1 row) + select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{n}'; ?column? ---------------------------------------------------------- @@ -5599,6 +5667,12 @@ select 'true'::jsonb::bool; t (1 row) +select 'null'::jsonb::bool; + bool +------ + +(1 row) + select '[]'::jsonb::bool; ERROR: cannot cast jsonb array to type boolean select '1.0'::jsonb::float; @@ -5607,22 +5681,82 @@ select '1.0'::jsonb::float; 1 (1 row) +select 'null'::jsonb::float; + float8 +-------- + +(1 row) + select '[1.0]'::jsonb::float; ERROR: cannot cast jsonb array to type double precision +select '1.0'::jsonb::float4; + float4 +-------- + 1 +(1 row) + +select 'null'::jsonb::float4; + float4 +-------- + +(1 row) + +select '[1.0]'::jsonb::float4; +ERROR: cannot cast jsonb array to type real +select '12345'::jsonb::int2; + int2 +------- + 12345 +(1 row) + +select 'null'::jsonb::int2; + int2 +------ + +(1 row) + +select '"hello"'::jsonb::int2; +ERROR: cannot cast jsonb string to type smallint select '12345'::jsonb::int4; int4 ------- 12345 (1 row) +select 'null'::jsonb::int4; + int4 +------ + +(1 row) + select '"hello"'::jsonb::int4; ERROR: cannot cast jsonb string to type integer +select '12345'::jsonb::int8; + int8 +------- + 12345 +(1 row) + +select 'null'::jsonb::int8; + int8 +------ + +(1 row) + +select '"hello"'::jsonb::int8; +ERROR: cannot cast jsonb string to type bigint select '12345'::jsonb::numeric; numeric --------- 12345 (1 row) +select 'null'::jsonb::numeric; + numeric +--------- + +(1 row) + select '{}'::jsonb::numeric; ERROR: cannot cast jsonb object to type numeric select '12345.05'::jsonb::numeric; diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out index 7bb4eb1bc276e..4bcd4e91a2991 100644 --- a/src/test/regress/expected/jsonb_jsonpath.out +++ b/src/test/regress/expected/jsonb_jsonpath.out @@ -1906,7 +1906,7 @@ select jsonb_path_query('123', '$.bigint() * 2'); -- Test .boolean() select jsonb_path_query('null', '$.boolean()'); -ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +ERROR: jsonpath item method .boolean() can only be applied to a boolean, string, or numeric value select jsonb_path_query('null', '$.boolean()', silent => true); jsonb_path_query ------------------ @@ -1918,9 +1918,9 @@ select jsonb_path_query('[]', '$.boolean()'); (0 rows) select jsonb_path_query('[]', 'strict $.boolean()'); -ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +ERROR: jsonpath item method .boolean() can only be applied to a boolean, string, or numeric value select jsonb_path_query('{}', '$.boolean()'); -ERROR: jsonpath item method .boolean() can only be applied to a bool, string, or numeric value +ERROR: jsonpath item method .boolean() can only be applied to a boolean, string, or numeric value select jsonb_path_query('[]', 'strict $.boolean()', silent => true); jsonb_path_query ------------------ @@ -2568,7 +2568,7 @@ select jsonb_path_query('12.3', '$.number() * 2'); -- Test .string() select jsonb_path_query('null', '$.string()'); -ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +ERROR: jsonpath item method .string() can only be applied to a boolean, string, numeric, or datetime value select jsonb_path_query('null', '$.string()', silent => true); jsonb_path_query ------------------ @@ -2580,9 +2580,9 @@ select jsonb_path_query('[]', '$.string()'); (0 rows) select jsonb_path_query('[]', 'strict $.string()'); -ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +ERROR: jsonpath item method .string() can only be applied to a boolean, string, numeric, or datetime value select jsonb_path_query('{}', '$.string()'); -ERROR: jsonpath item method .string() can only be applied to a bool, string, numeric, or datetime value +ERROR: jsonpath item method .string() can only be applied to a boolean, string, numeric, or datetime value select jsonb_path_query('[]', 'strict $.string()', silent => true); jsonb_path_query ------------------ @@ -2636,15 +2636,6 @@ select jsonb_path_query('[2, true]', '$.string()'); "true" (2 rows) -select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -ERROR: cannot convert value from timestamptz to timestamp without time zone usage -HINT: Use *_tz() function for time zone support. -select jsonb_path_query_tz('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -- should work - jsonb_path_query_tz ----------------------------- - "Tue Aug 15 00:04:56 2023" -(1 row) - select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string()'); jsonb_path_query_array -------------------------- @@ -2657,6 +2648,81 @@ select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string().type()'); ["string", "string", "string"] (1 row) +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); +ERROR: cannot convert value from timestamptz to timestamp without time zone usage +HINT: Use *_tz() function for time zone support. +select jsonb_path_query_tz('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -- should work + jsonb_path_query_tz +----------------------- + "2023-08-15T00:04:56" +(1 row) + +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz().string()'); +ERROR: cannot convert value from timestamp to timestamptz without time zone usage +HINT: Use *_tz() function for time zone support. +select jsonb_path_query_tz('"2023-08-15 12:34:56"', '$.timestamp_tz().string()'); -- should work + jsonb_path_query_tz +----------------------------- + "2023-08-15T12:34:56-07:00" +(1 row) + +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp_tz().string()'); + jsonb_path_query +----------------------------- + "2023-08-15T12:34:56+05:30" +(1 row) + +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()'); + jsonb_path_query +----------------------- + "2023-08-15T12:34:56" +(1 row) + +select jsonb_path_query('"12:34:56 +5:30"', '$.time_tz().string()'); + jsonb_path_query +------------------ + "12:34:56+05:30" +(1 row) + +-- this timetz usage will absorb the UTC offset of the current timezone setting +begin; +set local timezone = 'UTC-10'; +select jsonb_path_query_tz('"12:34:56"', '$.time_tz().string()'); + jsonb_path_query_tz +--------------------- + "12:34:56+10:00" +(1 row) + +rollback; +select jsonb_path_query('"12:34:56"', '$.time().string()'); + jsonb_path_query +------------------ + "12:34:56" +(1 row) + +select jsonb_path_query('"2023-08-15"', '$.date().string()'); + jsonb_path_query +------------------ + "2023-08-15" +(1 row) + +-- .string() does not react to timezone or datestyle +begin; +set local timezone = 'UTC'; +set local datestyle = 'German'; +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp_tz().string()'); + jsonb_path_query +----------------------------- + "2023-08-15T12:34:56+05:30" +(1 row) + +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()'); + jsonb_path_query +----------------------- + "2023-08-15T12:34:56" +(1 row) + +rollback; -- Test .time() select jsonb_path_query('null', '$.time()'); ERROR: jsonpath item method .time() can only be applied to a string @@ -2964,7 +3030,7 @@ HINT: Use *_tz() function for time zone support. select jsonb_path_query_tz('"2023-08-15"', '$.timestamp_tz()'); -- should work jsonb_path_query_tz ----------------------------- - "2023-08-15T07:00:00+00:00" + "2023-08-15T00:00:00-07:00" (1 row) select jsonb_path_query('"12:34:56"', '$.timestamp_tz()'); @@ -3151,7 +3217,7 @@ HINT: Use *_tz() function for time zone support. select jsonb_path_query_tz('"2023-08-15 12:34:56"', '$.timestamp_tz()'); -- should work jsonb_path_query_tz ----------------------------- - "2023-08-15T02:34:56+00:00" + "2023-08-15T12:34:56+10:00" (1 row) select jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()'); diff --git a/src/test/regress/expected/limit.out b/src/test/regress/expected/limit.out index a2cd0f9f5b89e..e3bcc680653b3 100644 --- a/src/test/regress/expected/limit.out +++ b/src/test/regress/expected/limit.out @@ -624,11 +624,15 @@ SELECT thousand FROM onek WHERE thousand < 5 ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE SKIP LOCKED; ERROR: SKIP LOCKED and WITH TIES options cannot be used together +LINE 3: ORDER BY thousand FETCH FIRST 1 ROW WITH TIES FOR UPDATE S... + ^ -- should fail SELECT ''::text AS two, unique1, unique2, stringu1 FROM onek WHERE unique1 > 50 FETCH FIRST 2 ROW WITH TIES; ERROR: WITH TIES cannot be specified without ORDER BY clause +LINE 3: FETCH FIRST 2 ROW WITH TIES; + ^ -- test ruleutils CREATE VIEW limit_thousand_v_1 AS SELECT thousand FROM onek WHERE thousand < 995 ORDER BY thousand FETCH FIRST 5 ROWS WITH TIES OFFSET 10; @@ -643,7 +647,7 @@ View definition: WHERE thousand < 995 ORDER BY thousand OFFSET 10 - FETCH FIRST 5 ROWS WITH TIES; + FETCH FIRST (5) ROWS WITH TIES; CREATE VIEW limit_thousand_v_2 AS SELECT thousand FROM onek WHERE thousand < 995 ORDER BY thousand OFFSET 10 FETCH FIRST 5 ROWS ONLY; @@ -675,15 +679,29 @@ View definition: FROM onek WHERE thousand < 995 ORDER BY thousand - FETCH FIRST (NULL::integer + 1) ROWS WITH TIES; + FETCH FIRST ((NULL::integer + 1)) ROWS WITH TIES; CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS ONLY; + ORDER BY thousand FETCH FIRST (5::bigint) ROWS WITH TIES; \d+ limit_thousand_v_4 View "public.limit_thousand_v_4" Column | Type | Collation | Nullable | Default | Storage | Description ----------+---------+-----------+----------+---------+---------+------------- thousand | integer | | | | plain | +View definition: + SELECT thousand + FROM onek + WHERE thousand < 995 + ORDER BY thousand + FETCH FIRST (5::bigint) ROWS WITH TIES; + +CREATE VIEW limit_thousand_v_5 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS ONLY; +\d+ limit_thousand_v_5 + View "public.limit_thousand_v_5" + Column | Type | Collation | Nullable | Default | Storage | Description +----------+---------+-----------+----------+---------+---------+------------- + thousand | integer | | | | plain | View definition: SELECT thousand FROM onek diff --git a/src/test/regress/expected/maintain_every.out b/src/test/regress/expected/maintain_every.out new file mode 100644 index 0000000000000..dea1089c2499b --- /dev/null +++ b/src/test/regress/expected/maintain_every.out @@ -0,0 +1,33 @@ +-- Test maintenance commands that visit every eligible relation. Run as a +-- non-superuser, to skip other users' tables. +CREATE ROLE regress_maintain; +SET ROLE regress_maintain; +-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f +-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an +-- empty index. +CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts" +CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS; +CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent); +CREATE INDEX ON past_inh_db_parent ((1)); +ANALYZE past_inh_db_parent; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; + reltuples | relhassubclass +-----------+---------------- + 0 | t +(1 row) + +DROP TABLE past_inh_db_child; +SET client_min_messages = error; -- hide WARNINGs for other users' tables +ANALYZE; +RESET client_min_messages; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; + reltuples | relhassubclass +-----------+---------------- + 0 | f +(1 row) + +DROP TABLE past_inh_db_parent, past_inh_db_other; +RESET ROLE; +DROP ROLE regress_maintain; diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out index 038ab735176ea..54939ecc6b08a 100644 --- a/src/test/regress/expected/matview.out +++ b/src/test/regress/expected/matview.out @@ -624,19 +624,19 @@ GRANT ALL ON SCHEMA matview_schema TO public; SET SESSION AUTHORIZATION regress_matview_user; CREATE MATERIALIZED VIEW matview_schema.mv_withdata1 (a) AS SELECT generate_series(1, 10) WITH DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_schema.mv_withdata2 (a) AS SELECT generate_series(1, 10) WITH DATA; - QUERY PLAN --------------------------------------- - ProjectSet (actual rows=10 loops=1) - -> Result (actual rows=1 loops=1) + QUERY PLAN +----------------------------------------- + ProjectSet (actual rows=10.00 loops=1) + -> Result (actual rows=1.00 loops=1) (2 rows) REFRESH MATERIALIZED VIEW matview_schema.mv_withdata2; CREATE MATERIALIZED VIEW matview_schema.mv_nodata1 (a) AS SELECT generate_series(1, 10) WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_schema.mv_nodata2 (a) AS SELECT generate_series(1, 10) WITH NO DATA; QUERY PLAN @@ -669,11 +669,11 @@ ERROR: relation "matview_ine_tab" already exists CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok NOTICE: relation "matview_ine_tab" already exists, skipping -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0; -- error ERROR: relation "matview_ine_tab" already exists -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0; -- ok NOTICE: relation "matview_ine_tab" already exists, skipping @@ -681,11 +681,11 @@ NOTICE: relation "matview_ine_tab" already exists, skipping ------------ (0 rows) -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- error ERROR: relation "matview_ine_tab" already exists -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok NOTICE: relation "matview_ine_tab" already exists, skipping diff --git a/src/test/regress/expected/memoize.out b/src/test/regress/expected/memoize.out index 96906104d7ed3..38dfaf021c91d 100644 --- a/src/test/regress/expected/memoize.out +++ b/src/test/regress/expected/memoize.out @@ -10,7 +10,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', query) loop if hide_hitmiss = true then @@ -22,8 +22,9 @@ begin ln := regexp_replace(ln, 'Evictions: 0', 'Evictions: Zero'); ln := regexp_replace(ln, 'Evictions: \d+', 'Evictions: N'); ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N'); - ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N'); - ln := regexp_replace(ln, 'loops=\d+', 'loops=N'); + ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N'); + ln := regexp_replace(ln, 'loops=\d+', 'loops=N'); + ln := regexp_replace(ln, 'Index Searches: \d+', 'Index Searches: N'); return next ln; end loop; end; @@ -35,21 +36,22 @@ SELECT explain_memoize(' SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty WHERE t2.unique1 < 1000;', false); - explain_memoize -------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1000 loops=N) - -> Seq Scan on tenk1 t2 (actual rows=1000 loops=N) + explain_memoize +---------------------------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop (actual rows=1000.00 loops=N) + -> Seq Scan on tenk1 t2 (actual rows=1000.00 loops=N) Filter: (unique1 < 1000) Rows Removed by Filter: 9000 - -> Memoize (actual rows=1 loops=N) + -> Memoize (actual rows=1.00 loops=N) Cache Key: t2.twenty Cache Mode: logical Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N) + -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1.00 loops=N) Index Cond: (unique1 = t2.twenty) Heap Fetches: N -(12 rows) + Index Searches: N +(13 rows) -- And check we get the expected results. SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1 @@ -66,21 +68,22 @@ SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1, LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1 OFFSET 0) t2 WHERE t1.unique1 < 1000;', false); - explain_memoize -------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1000 loops=N) - -> Seq Scan on tenk1 t1 (actual rows=1000 loops=N) + explain_memoize +---------------------------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop (actual rows=1000.00 loops=N) + -> Seq Scan on tenk1 t1 (actual rows=1000.00 loops=N) Filter: (unique1 < 1000) Rows Removed by Filter: 9000 - -> Memoize (actual rows=1 loops=N) + -> Memoize (actual rows=1.00 loops=N) Cache Key: t1.twenty Cache Mode: binary Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=N) + -> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1.00 loops=N) Index Cond: (unique1 = t1.twenty) Heap Fetches: N -(12 rows) + Index Searches: N +(13 rows) -- And check we get the expected results. SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1, @@ -100,22 +103,24 @@ LATERAL ( ) t2 ON t1.two = t2.two WHERE t1.unique1 < 10;', false); - explain_memoize ----------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop Left Join (actual rows=20 loops=N) - -> Index Scan using tenk1_unique1 on tenk1 t1 (actual rows=10 loops=N) + explain_memoize +------------------------------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop Left Join (actual rows=20.00 loops=N) + -> Index Scan using tenk1_unique1 on tenk1 t1 (actual rows=10.00 loops=N) Index Cond: (unique1 < 10) - -> Memoize (actual rows=2 loops=N) + Index Searches: N + -> Memoize (actual rows=2.00 loops=N) Cache Key: t1.two Cache Mode: binary Hits: 8 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Subquery Scan on t2 (actual rows=2 loops=N) + -> Subquery Scan on t2 (actual rows=2.00 loops=N) Filter: (t1.two = t2.two) Rows Removed by Filter: 2 - -> Index Scan using tenk1_unique1 on tenk1 t2_1 (actual rows=4 loops=N) + -> Index Scan using tenk1_unique1 on tenk1 t2_1 (actual rows=4.00 loops=N) Index Cond: (unique1 < 4) -(13 rows) + Index Searches: N +(15 rows) -- And check we get the expected results. SELECT COUNT(*),AVG(t2.t1two) FROM tenk1 t1 LEFT JOIN @@ -134,22 +139,23 @@ SELECT explain_memoize(' SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN LATERAL (SELECT t1.two+1 AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false); - explain_memoize -------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1000 loops=N) - -> Seq Scan on tenk1 t1 (actual rows=1000 loops=N) + explain_memoize +---------------------------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop (actual rows=1000.00 loops=N) + -> Seq Scan on tenk1 t1 (actual rows=1000.00 loops=N) Filter: (unique1 < 1000) Rows Removed by Filter: 9000 - -> Memoize (actual rows=1 loops=N) + -> Memoize (actual rows=1.00 loops=N) Cache Key: (t1.two + 1) Cache Mode: binary Hits: 998 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=N) + -> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1.00 loops=N) Filter: ((t1.two + 1) = unique1) Rows Removed by Filter: 9999 Heap Fetches: N -(13 rows) + Index Searches: N +(14 rows) -- And check we get the expected results. SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN @@ -160,36 +166,6 @@ WHERE s.c1 = s.c2 AND t1.unique1 < 1000; 1000 | 9.5000000000000000 (1 row) --- Try with LATERAL references within PlaceHolderVars -SELECT explain_memoize(' -SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN -LATERAL (SELECT t1.two+t2.two AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE -WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false); - explain_memoize --------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1000 loops=N) - -> Seq Scan on tenk1 t1 (actual rows=1000 loops=N) - Filter: (unique1 < 1000) - Rows Removed by Filter: 9000 - -> Memoize (actual rows=1 loops=N) - Cache Key: t1.two - Cache Mode: binary - Hits: 998 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Seq Scan on tenk1 t2 (actual rows=1 loops=N) - Filter: ((t1.two + two) = unique1) - Rows Removed by Filter: 9999 -(12 rows) - --- And check we get the expected results. -SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN -LATERAL (SELECT t1.two+t2.two AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE -WHERE s.c1 = s.c2 AND t1.unique1 < 1000; - count | avg --------+-------------------- - 1000 | 9.0000000000000000 -(1 row) - -- Ensure we do not omit the cache keys from PlaceHolderVars SELECT explain_memoize(' SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN @@ -198,16 +174,16 @@ ON t1.two = s.two WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false); explain_memoize --------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1000 loops=N) - -> Seq Scan on tenk1 t1 (actual rows=1000 loops=N) + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop (actual rows=1000.00 loops=N) + -> Seq Scan on tenk1 t1 (actual rows=1000.00 loops=N) Filter: (unique1 < 1000) Rows Removed by Filter: 9000 - -> Memoize (actual rows=1 loops=N) + -> Memoize (actual rows=1.00 loops=N) Cache Key: t1.two, t1.twenty Cache Mode: binary Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Seq Scan on tenk1 t2 (actual rows=1 loops=N) + -> Seq Scan on tenk1 t2 (actual rows=1.00 loops=N) Filter: ((t1.twenty = unique1) AND (t1.two = two)) Rows Removed by Filter: 9999 (12 rows) @@ -237,19 +213,20 @@ VACUUM ANALYZE expr_key; SELECT explain_memoize(' SELECT * FROM expr_key t1 INNER JOIN expr_key t2 ON t1.x = t2.t::numeric AND t1.t::numeric = t2.x;', false); - explain_memoize -------------------------------------------------------------------------------------------- - Nested Loop (actual rows=80 loops=N) - -> Seq Scan on expr_key t1 (actual rows=40 loops=N) - -> Memoize (actual rows=2 loops=N) + explain_memoize +---------------------------------------------------------------------------------------------- + Nested Loop (actual rows=80.00 loops=N) + -> Seq Scan on expr_key t1 (actual rows=40.00 loops=N) + -> Memoize (actual rows=2.00 loops=N) Cache Key: t1.x, (t1.t)::numeric Cache Mode: logical Hits: 20 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using expr_key_idx_x_t on expr_key t2 (actual rows=2 loops=N) + -> Index Only Scan using expr_key_idx_x_t on expr_key t2 (actual rows=2.00 loops=N) Index Cond: (x = (t1.t)::numeric) Filter: (t1.x = (t)::numeric) Heap Fetches: N -(10 rows) + Index Searches: N +(11 rows) DROP TABLE expr_key; -- Reduce work_mem and hash_mem_multiplier so that we see some cache evictions @@ -262,21 +239,22 @@ SELECT explain_memoize(' SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.thousand WHERE t2.unique1 < 1200;', true); - explain_memoize -------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=N) - -> Nested Loop (actual rows=1200 loops=N) - -> Seq Scan on tenk1 t2 (actual rows=1200 loops=N) + explain_memoize +---------------------------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=N) + -> Nested Loop (actual rows=1200.00 loops=N) + -> Seq Scan on tenk1 t2 (actual rows=1200.00 loops=N) Filter: (unique1 < 1200) Rows Removed by Filter: 8800 - -> Memoize (actual rows=1 loops=N) + -> Memoize (actual rows=1.00 loops=N) Cache Key: t2.thousand Cache Mode: logical Hits: N Misses: N Evictions: N Overflows: 0 Memory Usage: NkB - -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N) + -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1.00 loops=N) Index Cond: (unique1 = t2.thousand) Heap Fetches: N -(12 rows) + Index Searches: N +(13 rows) CREATE TABLE flt (f float); CREATE INDEX flt_f_idx ON flt (f); @@ -286,36 +264,40 @@ SET enable_seqscan TO off; -- Ensure memoize operates in logical mode SELECT explain_memoize(' SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f = f2.f;', false); - explain_memoize -------------------------------------------------------------------------------- - Nested Loop (actual rows=4 loops=N) - -> Index Only Scan using flt_f_idx on flt f1 (actual rows=2 loops=N) + explain_memoize +---------------------------------------------------------------------------------- + Nested Loop (actual rows=4.00 loops=N) + -> Index Only Scan using flt_f_idx on flt f1 (actual rows=2.00 loops=N) Heap Fetches: N - -> Memoize (actual rows=2 loops=N) + Index Searches: N + -> Memoize (actual rows=2.00 loops=N) Cache Key: f1.f Cache Mode: logical Hits: 1 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using flt_f_idx on flt f2 (actual rows=2 loops=N) + -> Index Only Scan using flt_f_idx on flt f2 (actual rows=2.00 loops=N) Index Cond: (f = f1.f) Heap Fetches: N -(10 rows) + Index Searches: N +(12 rows) -- Ensure memoize operates in binary mode SELECT explain_memoize(' SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f >= f2.f;', false); - explain_memoize -------------------------------------------------------------------------------- - Nested Loop (actual rows=4 loops=N) - -> Index Only Scan using flt_f_idx on flt f1 (actual rows=2 loops=N) + explain_memoize +---------------------------------------------------------------------------------- + Nested Loop (actual rows=4.00 loops=N) + -> Index Only Scan using flt_f_idx on flt f1 (actual rows=2.00 loops=N) Heap Fetches: N - -> Memoize (actual rows=2 loops=N) + Index Searches: N + -> Memoize (actual rows=2.00 loops=N) Cache Key: f1.f Cache Mode: binary Hits: 0 Misses: 2 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using flt_f_idx on flt f2 (actual rows=2 loops=N) + -> Index Only Scan using flt_f_idx on flt f2 (actual rows=2.00 loops=N) Index Cond: (f <= f1.f) Heap Fetches: N -(10 rows) + Index Searches: N +(12 rows) DROP TABLE flt; -- Exercise Memoize in binary mode with a large fixed width type and a @@ -330,32 +312,36 @@ ANALYZE strtest; -- Ensure we get 3 hits and 3 misses SELECT explain_memoize(' SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false); - explain_memoize ----------------------------------------------------------------------------------- - Nested Loop (actual rows=24 loops=N) - -> Seq Scan on strtest s1 (actual rows=6 loops=N) - -> Memoize (actual rows=4 loops=N) + explain_memoize +------------------------------------------------------------------------------------- + Nested Loop (actual rows=24.00 loops=N) + -> Seq Scan on strtest s1 (actual rows=6.00 loops=N) + Disabled: true + -> Memoize (actual rows=4.00 loops=N) Cache Key: s1.n Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N) + -> Index Scan using strtest_n_idx on strtest s2 (actual rows=4.00 loops=N) Index Cond: (n <= s1.n) -(8 rows) + Index Searches: N +(10 rows) -- Ensure we get 3 hits and 3 misses SELECT explain_memoize(' SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false); - explain_memoize ----------------------------------------------------------------------------------- - Nested Loop (actual rows=24 loops=N) - -> Seq Scan on strtest s1 (actual rows=6 loops=N) - -> Memoize (actual rows=4 loops=N) + explain_memoize +------------------------------------------------------------------------------------- + Nested Loop (actual rows=24.00 loops=N) + -> Seq Scan on strtest s1 (actual rows=6.00 loops=N) + Disabled: true + -> Memoize (actual rows=4.00 loops=N) Cache Key: s1.t Cache Mode: binary Hits: 3 Misses: 3 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N) + -> Index Scan using strtest_t_idx on strtest s2 (actual rows=4.00 loops=N) Index Cond: (t <= s1.t) -(8 rows) + Index Searches: N +(10 rows) DROP TABLE strtest; -- Ensure memoize works with partitionwise join @@ -370,30 +356,34 @@ CREATE INDEX iprt_p2_a ON prt_p2 (a); ANALYZE prt; SELECT explain_memoize(' SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false); - explain_memoize ------------------------------------------------------------------------------------------- - Append (actual rows=32 loops=N) - -> Nested Loop (actual rows=16 loops=N) - -> Index Only Scan using iprt_p1_a on prt_p1 t1_1 (actual rows=4 loops=N) + explain_memoize +--------------------------------------------------------------------------------------------- + Append (actual rows=32.00 loops=N) + -> Nested Loop (actual rows=16.00 loops=N) + -> Index Only Scan using iprt_p1_a on prt_p1 t1_1 (actual rows=4.00 loops=N) Heap Fetches: N - -> Memoize (actual rows=4 loops=N) + Index Searches: N + -> Memoize (actual rows=4.00 loops=N) Cache Key: t1_1.a Cache Mode: logical Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using iprt_p1_a on prt_p1 t2_1 (actual rows=4 loops=N) + -> Index Only Scan using iprt_p1_a on prt_p1 t2_1 (actual rows=4.00 loops=N) Index Cond: (a = t1_1.a) Heap Fetches: N - -> Nested Loop (actual rows=16 loops=N) - -> Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4 loops=N) + Index Searches: N + -> Nested Loop (actual rows=16.00 loops=N) + -> Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4.00 loops=N) Heap Fetches: N - -> Memoize (actual rows=4 loops=N) + Index Searches: N + -> Memoize (actual rows=4.00 loops=N) Cache Key: t1_2.a Cache Mode: logical Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Index Only Scan using iprt_p2_a on prt_p2 t2_2 (actual rows=4 loops=N) + -> Index Only Scan using iprt_p2_a on prt_p2 t2_2 (actual rows=4.00 loops=N) Index Cond: (a = t1_2.a) Heap Fetches: N -(21 rows) + Index Searches: N +(25 rows) -- Ensure memoize works with parameterized union-all Append path SET enable_partitionwise_join TO off; @@ -401,23 +391,26 @@ SELECT explain_memoize(' SELECT * FROM prt_p1 t1 INNER JOIN (SELECT * FROM prt_p1 UNION ALL SELECT * FROM prt_p2) t2 ON t1.a = t2.a;', false); - explain_memoize -------------------------------------------------------------------------------------- - Nested Loop (actual rows=16 loops=N) - -> Index Only Scan using iprt_p1_a on prt_p1 t1 (actual rows=4 loops=N) + explain_memoize +---------------------------------------------------------------------------------------- + Nested Loop (actual rows=16.00 loops=N) + -> Index Only Scan using iprt_p1_a on prt_p1 t1 (actual rows=4.00 loops=N) Heap Fetches: N - -> Memoize (actual rows=4 loops=N) + Index Searches: N + -> Memoize (actual rows=4.00 loops=N) Cache Key: t1.a Cache Mode: logical Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB - -> Append (actual rows=4 loops=N) - -> Index Only Scan using iprt_p1_a on prt_p1 (actual rows=4 loops=N) + -> Append (actual rows=4.00 loops=N) + -> Index Only Scan using iprt_p1_a on prt_p1 (actual rows=4.00 loops=N) Index Cond: (a = t1.a) Heap Fetches: N - -> Index Only Scan using iprt_p2_a on prt_p2 (actual rows=0 loops=N) + Index Searches: N + -> Index Only Scan using iprt_p2_a on prt_p2 (actual rows=0.00 loops=N) Index Cond: (a = t1.a) Heap Fetches: N -(14 rows) + Index Searches: N +(17 rows) DROP TABLE prt; RESET enable_partitionwise_join; diff --git a/src/test/regress/expected/merge.out b/src/test/regress/expected/merge.out index 3d33259e8ffbb..cf2219df754fb 100644 --- a/src/test/regress/expected/merge.out +++ b/src/test/regress/expected/merge.out @@ -297,13 +297,13 @@ WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED BY TARGET THEN INSERT VALUES (s.sid, s.delta) -RETURNING merge_action(), t.*; - merge_action | tid | balance ---------------+-----+--------- - DELETE | 1 | 10 - DELETE | 2 | 20 - DELETE | 3 | 30 - INSERT | 4 | 40 +RETURNING merge_action(), old, new, t.*; + merge_action | old | new | tid | balance +--------------+--------+--------+-----+--------- + DELETE | (1,10) | | 1 | 10 + DELETE | (2,20) | | 2 | 20 + DELETE | (3,30) | | 3 | 30 + INSERT | | (4,40) | 4 | 40 (4 rows) SELECT * FROM target ORDER BY tid; @@ -994,7 +994,7 @@ WHEN NOT MATCHED BY SOURCE AND tid = 1 THEN UPDATE SET balance = 0 WHEN NOT MATCHED BY SOURCE THEN DELETE -RETURNING merge_action(), t.*; +RETURNING merge_action(), old, new, t.*; NOTICE: BEFORE INSERT STATEMENT trigger NOTICE: BEFORE UPDATE STATEMENT trigger NOTICE: BEFORE DELETE STATEMENT trigger @@ -1009,12 +1009,12 @@ NOTICE: AFTER UPDATE ROW trigger row: (1,10) -> (1,0) NOTICE: AFTER DELETE STATEMENT trigger NOTICE: AFTER UPDATE STATEMENT trigger NOTICE: AFTER INSERT STATEMENT trigger - merge_action | tid | balance ---------------+-----+--------- - UPDATE | 3 | 10 - INSERT | 4 | 40 - DELETE | 2 | 20 - UPDATE | 1 | 0 + merge_action | old | new | tid | balance +--------------+--------+--------+-----+--------- + UPDATE | (3,30) | (3,10) | 3 | 10 + INSERT | | (4,40) | 4 | 40 + DELETE | (2,20) | | 2 | 20 + UPDATE | (1,10) | (1,0) | 1 | 0 (4 rows) SELECT * FROM target ORDER BY tid; @@ -1436,17 +1436,19 @@ WHEN MATCHED AND tid < 2 THEN DELETE RETURNING (SELECT abbrev FROM merge_actions WHERE action = merge_action()) AS action, - t.*, + old.tid AS old_tid, old.balance AS old_balance, + new.tid AS new_tid, new.balance AS new_balance, + (SELECT new.balance - old.balance AS delta_balance), t.*, CASE merge_action() WHEN 'INSERT' THEN 'Inserted '||t WHEN 'UPDATE' THEN 'Added '||delta||' to balance' WHEN 'DELETE' THEN 'Removed '||t END AS description; - action | tid | balance | description ---------+-----+---------+--------------------- - del | 1 | 100 | Removed (1,100) - upd | 2 | 220 | Added 20 to balance - ins | 4 | 40 | Inserted (4,40) + action | old_tid | old_balance | new_tid | new_balance | delta_balance | tid | balance | description +--------+---------+-------------+---------+-------------+---------------+-----+---------+--------------------- + del | 1 | 100 | | | | 1 | 100 | Removed (1,100) + upd | 2 | 200 | 2 | 220 | 20 | 2 | 220 | Added 20 to balance + ins | | | 4 | 40 | | 4 | 40 | Inserted (4,40) (3 rows) ROLLBACK; @@ -1473,7 +1475,7 @@ WITH m AS ( INSERT (balance, tid) VALUES (balance + delta, sid) WHEN MATCHED AND tid < 2 THEN DELETE - RETURNING merge_action() AS action, t.*, + RETURNING merge_action() AS action, old AS old_data, new AS new_data, t.*, CASE merge_action() WHEN 'INSERT' THEN 'Inserted '||t WHEN 'UPDATE' THEN 'Added '||delta||' to balance' @@ -1487,14 +1489,14 @@ WITH m AS ( UPDATE SET last_change = description WHEN NOT MATCHED THEN INSERT VALUES (m.tid, description) - RETURNING action, merge_action() AS log_action, l.* + RETURNING m.*, merge_action() AS log_action, old AS old_log, new AS new_log, l.* ) SELECT * FROM m2; - action | log_action | tid | last_change ---------+------------+-----+--------------------- - DELETE | UPDATE | 1 | Removed (1,100) - UPDATE | INSERT | 2 | Added 20 to balance - INSERT | INSERT | 4 | Inserted (4,40) + action | old_data | new_data | tid | balance | description | log_action | old_log | new_log | tid | last_change +--------+----------+----------+-----+---------+---------------------+------------+----------------------+---------------------------+-----+--------------------- + DELETE | (1,100) | | 1 | 100 | Removed (1,100) | UPDATE | (1,"Original value") | (1,"Removed (1,100)") | 1 | Removed (1,100) + UPDATE | (2,200) | (2,220) | 2 | 220 | Added 20 to balance | INSERT | | (2,"Added 20 to balance") | 2 | Added 20 to balance + INSERT | | (4,40) | 4 | 40 | Inserted (4,40) | INSERT | | (4,"Inserted (4,40)") | 4 | Inserted (4,40) (3 rows) SELECT * FROM sq_target_merge_log ORDER BY tid; @@ -1518,11 +1520,11 @@ COPY ( INSERT (balance, tid) VALUES (balance + delta, sid) WHEN MATCHED AND tid < 2 THEN DELETE - RETURNING merge_action(), t.* + RETURNING merge_action(), old.*, new.* ) TO stdout; -DELETE 1 100 -UPDATE 2 220 -INSERT 4 40 +DELETE 1 100 \N \N +UPDATE 2 200 2 220 +INSERT \N \N 4 40 ROLLBACK; -- SQL function with MERGE ... RETURNING BEGIN; @@ -1621,7 +1623,7 @@ $$ DECLARE ln text; BEGIN FOR ln IN - EXECUTE 'explain (analyze, timing off, summary off, costs off) ' || + EXECUTE 'explain (analyze, timing off, summary off, costs off, buffers off) ' || query LOOP ln := regexp_replace(ln, '(Memory( Usage)?|Buckets|Batches): \S*', '\1: xxx', 'g'); @@ -1634,20 +1636,20 @@ SELECT explain_merge(' MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a WHEN MATCHED THEN UPDATE SET b = t.b + 1'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: updated=50 - -> Merge Join (actual rows=50 loops=1) + -> Merge Join (actual rows=50.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=50 loops=1) + -> Sort (actual rows=50.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=50 loops=1) - -> Sort (actual rows=100 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=50.00 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) (12 rows) -- only updates to selected tuples @@ -1655,20 +1657,20 @@ SELECT explain_merge(' MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a WHEN MATCHED AND t.a < 10 THEN UPDATE SET b = t.b + 1'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: updated=5 skipped=45 - -> Merge Join (actual rows=50 loops=1) + -> Merge Join (actual rows=50.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=50 loops=1) + -> Sort (actual rows=50.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=50 loops=1) - -> Sort (actual rows=100 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=50.00 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) (12 rows) -- updates + deletes @@ -1678,20 +1680,20 @@ WHEN MATCHED AND t.a < 10 THEN UPDATE SET b = t.b + 1 WHEN MATCHED AND t.a >= 10 AND t.a <= 20 THEN DELETE'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: updated=5 deleted=5 skipped=40 - -> Merge Join (actual rows=50 loops=1) + -> Merge Join (actual rows=50.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=50 loops=1) + -> Sort (actual rows=50.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=50 loops=1) - -> Sort (actual rows=100 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=50.00 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) (12 rows) -- only inserts @@ -1699,20 +1701,20 @@ SELECT explain_merge(' MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a WHEN NOT MATCHED AND s.a < 10 THEN INSERT VALUES (a, b)'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: inserted=4 skipped=96 - -> Merge Left Join (actual rows=100 loops=1) + -> Merge Left Join (actual rows=100.00 loops=1) Merge Cond: (s.a = t.a) - -> Sort (actual rows=100 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) - -> Sort (actual rows=45 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) + -> Sort (actual rows=45.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=45 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=45.00 loops=1) (12 rows) -- all three @@ -1724,20 +1726,20 @@ WHEN MATCHED AND t.a >= 30 AND t.a <= 40 THEN DELETE WHEN NOT MATCHED AND s.a < 20 THEN INSERT VALUES (a, b)'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: inserted=10 updated=9 deleted=5 skipped=76 - -> Merge Left Join (actual rows=100 loops=1) + -> Merge Left Join (actual rows=100.00 loops=1) Merge Cond: (s.a = t.a) - -> Sort (actual rows=100 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) - -> Sort (actual rows=49 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) + -> Sort (actual rows=49.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=49 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=49.00 loops=1) (12 rows) -- not matched by source @@ -1745,20 +1747,20 @@ SELECT explain_merge(' MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a WHEN NOT MATCHED BY SOURCE and t.a < 10 THEN DELETE'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: skipped=54 - -> Merge Left Join (actual rows=54 loops=1) + -> Merge Left Join (actual rows=54.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=54 loops=1) + -> Sort (actual rows=54.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=54 loops=1) - -> Sort (actual rows=100 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=54.00 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) (12 rows) -- not matched by source and target @@ -1768,20 +1770,20 @@ WHEN NOT MATCHED BY SOURCE AND t.a < 10 THEN DELETE WHEN NOT MATCHED BY TARGET AND s.a < 20 THEN INSERT VALUES (a, b)'); - explain_merge ----------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) + explain_merge +------------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) Tuples: skipped=100 - -> Merge Full Join (actual rows=100 loops=1) + -> Merge Full Join (actual rows=100.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=54 loops=1) + -> Sort (actual rows=54.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=54 loops=1) - -> Sort (actual rows=100 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=54.00 loops=1) + -> Sort (actual rows=100.00 loops=1) Sort Key: s.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_msource s (actual rows=100 loops=1) + -> Seq Scan on ex_msource s (actual rows=100.00 loops=1) (12 rows) -- nothing @@ -1789,15 +1791,15 @@ SELECT explain_merge(' MERGE INTO ex_mtarget t USING ex_msource s ON t.a = s.a AND t.a < -1000 WHEN MATCHED AND t.a < 10 THEN DO NOTHING'); - explain_merge --------------------------------------------------------------------- - Merge on ex_mtarget t (actual rows=0 loops=1) - -> Merge Join (actual rows=0 loops=1) + explain_merge +----------------------------------------------------------------------- + Merge on ex_mtarget t (actual rows=0.00 loops=1) + -> Merge Join (actual rows=0.00 loops=1) Merge Cond: (t.a = s.a) - -> Sort (actual rows=0 loops=1) + -> Sort (actual rows=0.00 loops=1) Sort Key: t.a Sort Method: quicksort Memory: xxx - -> Seq Scan on ex_mtarget t (actual rows=0 loops=1) + -> Seq Scan on ex_mtarget t (actual rows=0.00 loops=1) Filter: (a < '-1000'::integer) Rows Removed by Filter: 54 -> Sort (never executed) @@ -2039,10 +2041,10 @@ MERGE INTO pa_target t ON t.tid = s.sid AND t.tid = 1 WHEN MATCHED THEN UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' - RETURNING merge_action(), t.*; - merge_action | tid | balance | val ---------------+-----+---------+-------------------------- - UPDATE | 2 | 110 | initial updated by merge + RETURNING merge_action(), old, new, t.*; + merge_action | old | new | tid | balance | val +--------------+-----------------+------------------------------------+-----+---------+-------------------------- + UPDATE | (1,100,initial) | (2,110,"initial updated by merge") | 2 | 110 | initial updated by merge (1 row) SELECT * FROM pa_target ORDER BY tid; @@ -2058,6 +2060,23 @@ SELECT * FROM pa_target ORDER BY tid; 15 | 1500 | initial (8 rows) +ROLLBACK; +-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions +BEGIN; +TRUNCATE pa_target; +MERGE INTO pa_target t + USING (VALUES (10, 100)) AS s(sid, delta) + ON t.tid = s.sid + WHEN NOT MATCHED THEN + INSERT VALUES (1, 10, 'inserted by merge') + WHEN MATCHED THEN + DO NOTHING; +SELECT * FROM pa_target ORDER BY tid, val; + tid | balance | val +-----+---------+------------------- + 1 | 10 | inserted by merge +(1 row) + ROLLBACK; DROP TABLE pa_target CASCADE; -- The target table is partitioned in the same way, but this time by attaching @@ -2324,18 +2343,18 @@ MERGE INTO pa_target t UPDATE SET balance = balance + delta, val = val || ' updated by merge' WHEN NOT MATCHED THEN INSERT VALUES (slogts::timestamp, sid, delta, 'inserted by merge') - RETURNING merge_action(), t.*; - merge_action | logts | tid | balance | val ---------------+--------------------------+-----+---------+-------------------------- - UPDATE | Tue Jan 31 00:00:00 2017 | 1 | 110 | initial updated by merge - UPDATE | Tue Feb 28 00:00:00 2017 | 2 | 220 | initial updated by merge - INSERT | Sun Jan 15 00:00:00 2017 | 3 | 30 | inserted by merge - UPDATE | Tue Jan 31 00:00:00 2017 | 4 | 440 | initial updated by merge - UPDATE | Tue Feb 28 00:00:00 2017 | 5 | 550 | initial updated by merge - INSERT | Sun Jan 15 00:00:00 2017 | 6 | 60 | inserted by merge - UPDATE | Tue Jan 31 00:00:00 2017 | 7 | 770 | initial updated by merge - UPDATE | Tue Feb 28 00:00:00 2017 | 8 | 880 | initial updated by merge - INSERT | Sun Jan 15 00:00:00 2017 | 9 | 90 | inserted by merge + RETURNING merge_action(), old, new, t.*; + merge_action | old | new | logts | tid | balance | val +--------------+--------------------------------------------+---------------------------------------------------------------+--------------------------+-----+---------+-------------------------- + UPDATE | ("Tue Jan 31 00:00:00 2017",1,100,initial) | ("Tue Jan 31 00:00:00 2017",1,110,"initial updated by merge") | Tue Jan 31 00:00:00 2017 | 1 | 110 | initial updated by merge + UPDATE | ("Tue Feb 28 00:00:00 2017",2,200,initial) | ("Tue Feb 28 00:00:00 2017",2,220,"initial updated by merge") | Tue Feb 28 00:00:00 2017 | 2 | 220 | initial updated by merge + INSERT | | ("Sun Jan 15 00:00:00 2017",3,30,"inserted by merge") | Sun Jan 15 00:00:00 2017 | 3 | 30 | inserted by merge + UPDATE | ("Tue Jan 31 00:00:00 2017",4,400,initial) | ("Tue Jan 31 00:00:00 2017",4,440,"initial updated by merge") | Tue Jan 31 00:00:00 2017 | 4 | 440 | initial updated by merge + UPDATE | ("Tue Feb 28 00:00:00 2017",5,500,initial) | ("Tue Feb 28 00:00:00 2017",5,550,"initial updated by merge") | Tue Feb 28 00:00:00 2017 | 5 | 550 | initial updated by merge + INSERT | | ("Sun Jan 15 00:00:00 2017",6,60,"inserted by merge") | Sun Jan 15 00:00:00 2017 | 6 | 60 | inserted by merge + UPDATE | ("Tue Jan 31 00:00:00 2017",7,700,initial) | ("Tue Jan 31 00:00:00 2017",7,770,"initial updated by merge") | Tue Jan 31 00:00:00 2017 | 7 | 770 | initial updated by merge + UPDATE | ("Tue Feb 28 00:00:00 2017",8,800,initial) | ("Tue Feb 28 00:00:00 2017",8,880,"initial updated by merge") | Tue Feb 28 00:00:00 2017 | 8 | 880 | initial updated by merge + INSERT | | ("Sun Jan 15 00:00:00 2017",9,90,"inserted by merge") | Sun Jan 15 00:00:00 2017 | 9 | 90 | inserted by merge (9 rows) SELECT * FROM pa_target ORDER BY tid; @@ -2683,12 +2702,132 @@ SELECT * FROM new_measurement ORDER BY city_id, logdate; 1 | 01-17-2007 | | (2 rows) +-- MERGE into inheritance root table +DROP TRIGGER insert_measurement_trigger ON measurement; +ALTER TABLE measurement ADD CONSTRAINT mcheck CHECK (city_id = 0) NO INHERIT; +EXPLAIN (COSTS OFF) +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); + QUERY PLAN +-------------------------------------------------------------------------- + Merge on measurement m + Merge on measurement_y2007m01 m_1 + -> Nested Loop Left Join + -> Result + -> Seq Scan on measurement_y2007m01 m_1 + Filter: ((city_id = 1) AND (logdate = '01-17-2007'::date)) +(6 rows) + +BEGIN; +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; + city_id | logdate | peaktemp | unitsales +---------+------------+----------+----------- + 0 | 07-21-2005 | 25 | 35 + 0 | 01-17-2007 | 25 | 100 +(2 rows) + +ROLLBACK; +ALTER TABLE measurement ENABLE ROW LEVEL SECURITY; +ALTER TABLE measurement FORCE ROW LEVEL SECURITY; +CREATE POLICY measurement_p ON measurement USING (peaktemp IS NOT NULL); +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, NULL, 100); -- should fail +ERROR: new row violates row-level security policy for table "measurement" +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); -- ok +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; + city_id | logdate | peaktemp | unitsales +---------+------------+----------+----------- + 0 | 07-21-2005 | 25 | 35 + 0 | 01-17-2007 | 25 | 100 +(2 rows) + +MERGE INTO measurement m + USING (VALUES (1, '01-18-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 200) +RETURNING merge_action(), m.*; + merge_action | city_id | logdate | peaktemp | unitsales +--------------+---------+------------+----------+----------- + INSERT | 0 | 01-18-2007 | 25 | 200 +(1 row) + DROP TABLE measurement, new_measurement CASCADE; NOTICE: drop cascades to 3 other objects DETAIL: drop cascades to table measurement_y2006m02 drop cascades to table measurement_y2006m03 drop cascades to table measurement_y2007m01 DROP FUNCTION measurement_insert_trigger(); +-- +-- test non-strict join clause +-- +CREATE TABLE src (a int, b text); +INSERT INTO src VALUES (1, 'src row'); +CREATE TABLE tgt (a int, b text); +INSERT INTO tgt VALUES (NULL, 'tgt row'); +MERGE INTO tgt USING src ON tgt.a IS NOT DISTINCT FROM src.a + WHEN MATCHED THEN UPDATE SET a = src.a, b = src.b + WHEN NOT MATCHED BY SOURCE THEN DELETE + RETURNING merge_action(), src.*, tgt.*; + merge_action | a | b | a | b +--------------+---+---+---+--------- + DELETE | | | | tgt row +(1 row) + +SELECT * FROM tgt; + a | b +---+--- +(0 rows) + +DROP TABLE src, tgt; +-- +-- test for bug #18634 (wrong varnullingrels error) +-- +CREATE TABLE bug18634t (a int, b int, c text); +INSERT INTO bug18634t VALUES(1, 10, 'tgt1'), (2, 20, 'tgt2'); +CREATE VIEW bug18634v AS + SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t); +CREATE TABLE bug18634s (a int, b int, c text); +INSERT INTO bug18634s VALUES (1, 2, 'src1'); +MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a + WHEN MATCHED THEN UPDATE SET b = s.b + WHEN NOT MATCHED BY SOURCE THEN DELETE + RETURNING merge_action(), s.c, t.*; + merge_action | c | a | b | c +--------------+------+---+----+------ + UPDATE | src1 | 1 | 2 | tgt1 + DELETE | | 2 | 20 | tgt2 +(2 rows) + +SELECT * FROM bug18634t; + a | b | c +---+---+------ + 1 | 2 | tgt1 +(1 row) + +DROP TABLE bug18634t CASCADE; +NOTICE: drop cascades to view bug18634v +DROP TABLE bug18634s; -- prepare RESET SESSION AUTHORIZATION; -- try a system catalog diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out index 35fb72f302b57..c3b2b9d860343 100644 --- a/src/test/regress/expected/misc_functions.out +++ b/src/test/regress/expected/misc_functions.out @@ -22,7 +22,7 @@ BEGIN SET LOCAL jit = 0; FOR ln IN - EXECUTE format('explain (analyze %s, costs on, summary off, timing off) %s', + EXECUTE format('explain (analyze %s, costs on, summary off, timing off, buffers off) %s', analyze_str, query) LOOP IF hide_costs = true THEN @@ -412,6 +412,12 @@ select count(*) >= 0 as ok from pg_ls_archive_statusdir(); t (1 row) +select count(*) >= 0 as ok from pg_ls_summariesdir(); + ok +---- + t +(1 row) + -- pg_read_file() select length(pg_read_file('postmaster.pid')) > 20; ?column? @@ -641,27 +647,27 @@ SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g; SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '1 day') g(s);$$, true, true, false, true); - explain_mask_costs ------------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30 loops=1) + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30.00 loops=1) (1 row) -- As above but with generate_series_timestamp SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMP '2024-02-01', TIMESTAMP '2024-03-01', INTERVAL '1 day') g(s);$$, true, true, false, true); - explain_mask_costs ------------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30 loops=1) + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30.00 loops=1) (1 row) -- As above but with generate_series_timestamptz_at_zone() SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '1 day', 'UTC') g(s);$$, true, true, false, true); - explain_mask_costs ------------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30 loops=1) + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30.00 loops=1) (1 row) -- Ensure the estimated and actual row counts match when the range isn't @@ -669,27 +675,27 @@ true, true, false, true); SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '7 day') g(s);$$, true, true, false, true); - explain_mask_costs ----------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=5 width=N) (actual rows=5 loops=1) + explain_mask_costs +------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=5 width=N) (actual rows=5.00 loops=1) (1 row) -- Ensure the estimates match when step is decreasing SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMPTZ '2024-03-01', TIMESTAMPTZ '2024-02-01', INTERVAL '-1 day') g(s);$$, true, true, false, true); - explain_mask_costs ------------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30 loops=1) + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=30 width=N) (actual rows=30.00 loops=1) (1 row) -- Ensure an empty range estimates 1 row SELECT explain_mask_costs($$ SELECT * FROM generate_series(TIMESTAMPTZ '2024-03-01', TIMESTAMPTZ '2024-02-01', INTERVAL '1 day') g(s);$$, true, true, false, true); - explain_mask_costs ----------------------------------------------------------------------------------------- - Function Scan on generate_series g (cost=N..N rows=1 width=N) (actual rows=0 loops=1) + explain_mask_costs +------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=1 width=N) (actual rows=0.00 loops=1) (1 row) -- Ensure we get the default row estimate for infinity values @@ -706,6 +712,71 @@ false, true, false, true); -- the support function. SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '0 day') g(s); ERROR: step size cannot equal zero +-- +-- Test the SupportRequestRows support function for generate_series_numeric() +-- +-- Ensure the row estimate matches the actual rows +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0) g(s);$$, +true, true, false, true); + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=25 width=N) (actual rows=25.00 loops=1) +(1 row) + +-- As above but with non-default step +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0, 2.0) g(s);$$, +true, true, false, true); + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=13 width=N) (actual rows=13.00 loops=1) +(1 row) + +-- Ensure the estimates match when step is decreasing +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 1.0, -1.0) g(s);$$, +true, true, false, true); + explain_mask_costs +--------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=25 width=N) (actual rows=25.00 loops=1) +(1 row) + +-- Ensure an empty range estimates 1 row +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 1.0, 1.0) g(s);$$, +true, true, false, true); + explain_mask_costs +------------------------------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=1 width=N) (actual rows=0.00 loops=1) +(1 row) + +-- Ensure we get the default row estimate for error cases (infinity/NaN values +-- and zero step size) +SELECT explain_mask_costs($$ +SELECT * FROM generate_series('-infinity'::NUMERIC, 'infinity'::NUMERIC, 1.0) g(s);$$, +false, true, false, true); + explain_mask_costs +------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=1000 width=N) +(1 row) + +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0, 'NaN'::NUMERIC) g(s);$$, +false, true, false, true); + explain_mask_costs +------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=1000 width=N) +(1 row) + +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 2.0, 0.0) g(s);$$, +false, true, false, true); + explain_mask_costs +------------------------------------------------------------------- + Function Scan on generate_series g (cost=N..N rows=1000 width=N) +(1 row) + -- Test functions for control data SELECT count(*) > 0 AS ok FROM pg_control_checkpoint(); ok @@ -819,3 +890,31 @@ SELECT pg_column_toast_chunk_id(a) IS NULL, DROP TABLE test_chunk_id; DROP FUNCTION explain_mask_costs(text, bool, bool, bool, bool); +-- test stratnum translation support functions +SELECT gist_translate_cmptype_common(7); + gist_translate_cmptype_common +------------------------------- + 3 +(1 row) + +SELECT gist_translate_cmptype_common(3); + gist_translate_cmptype_common +------------------------------- + 18 +(1 row) + +-- relpath tests +CREATE FUNCTION test_relpath() + RETURNS void + AS :'regresslib' + LANGUAGE C; +SELECT test_relpath(); + test_relpath +-------------- + +(1 row) + +-- pg_replication_origin.roname limit +SELECT pg_replication_origin_create('regress_' || repeat('a', 505)); +ERROR: replication origin name is too long +DETAIL: Replication origin names must be no longer than 512 bytes. diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out index ad88cbd5c4c07..4ffc45a80187e 100644 --- a/src/test/regress/expected/misc_sanity.out +++ b/src/test/regress/expected/misc_sanity.out @@ -35,11 +35,18 @@ WHERE refclassid = 0 OR refobjid = 0 OR -- Look for system tables with varlena columns but no toast table. All -- system tables with toastable columns should have toast tables, with -- the following exceptions: --- 1. pg_class, pg_attribute, and pg_index, due to fear of recursive --- dependencies as toast tables depend on them. +-- 1. pg_class and pg_attribute, due to fear of recursive dependencies as +-- toast tables depend on them. -- 2. pg_largeobject and pg_largeobject_metadata. Large object catalogs -- and toast tables are mutually exclusive and large object data is handled -- as user data by pg_upgrade, which would cause failures. +-- 3. pg_authid, since its toast table cannot be accessed when it would be +-- needed, i.e., during authentication before we've selected a database. +-- 4. pg_replication_origin, since we want to be able to access that catalog +-- without setting up a snapshot. To make that safe, it needs to not have a +-- toast table, since toasted data cannot be fetched without a snapshot. As of +-- this writing, its only varlena column is roname, which we limit to 512 bytes +-- to avoid needing out-of-line storage. SELECT relname, attname, atttypid::regtype FROM pg_class c JOIN pg_attribute a ON c.oid = attrelid WHERE c.oid < 16384 AND @@ -53,13 +60,13 @@ ORDER BY 1, 2; pg_attribute | attfdwoptions | text[] pg_attribute | attmissingval | anyarray pg_attribute | attoptions | text[] + pg_authid | rolpassword | text pg_class | relacl | aclitem[] pg_class | reloptions | text[] pg_class | relpartbound | pg_node_tree - pg_index | indexprs | pg_node_tree - pg_index | indpred | pg_node_tree pg_largeobject | data | bytea pg_largeobject_metadata | lomacl | aclitem[] + pg_replication_origin | roname | text (11 rows) -- system catalogs without primary keys diff --git a/src/test/regress/expected/numa.out b/src/test/regress/expected/numa.out new file mode 100644 index 0000000000000..8af5dfeb9a5d3 --- /dev/null +++ b/src/test/regress/expected/numa.out @@ -0,0 +1,13 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +SELECT COUNT(*) = 0 AS ok FROM pg_shmem_allocations_numa; +\quit +\endif +-- switch to superuser +\c - +SELECT COUNT(*) >= 0 AS ok FROM pg_shmem_allocations_numa; + ok +---- + t +(1 row) + diff --git a/src/test/regress/expected/numa_1.out b/src/test/regress/expected/numa_1.out new file mode 100644 index 0000000000000..c90042fa7cce3 --- /dev/null +++ b/src/test/regress/expected/numa_1.out @@ -0,0 +1,5 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +SELECT COUNT(*) = 0 AS ok FROM pg_shmem_allocations_numa; +ERROR: libnuma initialization failed or NUMA is not supported on this platform +\quit diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index f30ac236f528d..072d76ce13173 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -1991,6 +1991,21 @@ SELECT to_char(val, '9.999EEEE') FROM num_data; -2.493e+07 (10 rows) +SELECT to_char(val, 'FMRN') FROM num_data; + to_char +----------------- + ############### + ############### + ############### + IV + ############### + ############### + ############### + ############### + ############### + ############### +(10 rows) + WITH v(val) AS (VALUES('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan')) SELECT val, @@ -2101,6 +2116,72 @@ SELECT to_char('12345678901'::float8, 'FM9999999999D9999900000000000000000'); ##########.#### (1 row) +SELECT to_char('100'::numeric, 'rn'); + to_char +----------------- + c +(1 row) + +SELECT to_char('1234'::numeric, 'rn'); + to_char +----------------- + mccxxxiv +(1 row) + +SELECT to_char('1235'::float4, 'rn'); + to_char +----------------- + mccxxxv +(1 row) + +SELECT to_char('1236'::float8, 'rn'); + to_char +----------------- + mccxxxvi +(1 row) + +SELECT to_char('1237'::float8, 'fmrn'); + to_char +----------- + mccxxxvii +(1 row) + +SELECT to_char('100e9'::numeric, 'RN'); + to_char +----------------- + ############### +(1 row) + +SELECT to_char('100e9'::float4, 'RN'); + to_char +----------------- + ############### +(1 row) + +SELECT to_char('100e9'::float8, 'RN'); + to_char +----------------- + ############### +(1 row) + +SELECT to_char(1234.56::numeric, '99999V99'); + to_char +---------- + 123456 +(1 row) + +SELECT to_char(1234.56::float4, '99999V99'); + to_char +---------- + 123456 +(1 row) + +SELECT to_char(1234.56::float8, '99999V99'); + to_char +---------- + 123456 +(1 row) + -- Check parsing of literal text in a format string SELECT to_char('100'::numeric, 'foo999'); to_char @@ -2297,6 +2378,90 @@ SELECT to_number('42nd', '99th'); 42 (1 row) +SELECT to_number('123456', '99999V99'); + to_number +------------------------- + 1234.560000000000000000 +(1 row) + +-- Test for correct conversion between numbers and Roman numerals +WITH rows AS + (SELECT i, to_char(i, 'RN') AS roman FROM generate_series(1, 3999) AS i) +SELECT + bool_and(to_number(roman, 'RN') = i) as valid +FROM rows; + valid +------- + t +(1 row) + +-- Some additional tests for RN input +SELECT to_number('CvIiI', 'rn'); + to_number +----------- + 108 +(1 row) + +SELECT to_number('MMXX ', 'RN'); + to_number +----------- + 2020 +(1 row) + +SELECT to_number(' XIV', ' RN'); + to_number +----------- + 14 +(1 row) + +SELECT to_number(' XIV ', ' RN'); + to_number +----------- + 14 +(1 row) + +SELECT to_number('M CC', 'RN'); + to_number +----------- + 1000 +(1 row) + +-- error cases +SELECT to_number('viv', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('DCCCD', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('XIXL', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('MCCM', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('MMMM', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('VV', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('IL', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('VIX', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('LXC', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('DCM', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('MMMDCM', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('CLXC', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('CM', 'MIRN'); +ERROR: "RN" is incompatible with other formats +DETAIL: "RN" may only be used together with "FM". +SELECT to_number('CM', 'RNRN'); +ERROR: cannot use "RN" twice +SELECT to_number('qiv', 'RN'); +ERROR: invalid Roman numeral +SELECT to_number('', 'RN'); +ERROR: invalid input syntax for type numeric: " " +SELECT to_number(' ', 'RN'); +ERROR: invalid Roman numeral RESET lc_numeric; -- -- Input syntax @@ -2691,6 +2856,24 @@ select div(12345678901234567890, 123) * 123 + 12345678901234567890 % 123; 12345678901234567890 (1 row) +select 8e9000 - div(8e18000 - 1, 9e9000 - 1) * 9; + ?column? +---------- + 8 +(1 row) + +select 7328412092 - div(53705623790171816464 - 1, 7328412092); + ?column? +---------- + 1 +(1 row) + +select div(539913372912345678, 539913372912345678); + div +----- + 1 +(1 row) + -- -- Test some corner cases for square root -- diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out index 717a237df9865..9e23166fed163 100644 --- a/src/test/regress/expected/numerology.out +++ b/src/test/regress/expected/numerology.out @@ -171,7 +171,7 @@ SELECT -0x8000000000000001; -- error cases SELECT 123abc; -ERROR: trailing junk after numeric literal at or near "123a" +ERROR: trailing junk after numeric literal at or near "123abc" LINE 1: SELECT 123abc; ^ SELECT 0x0o; @@ -322,7 +322,7 @@ ERROR: trailing junk after numeric literal at or near "100_" LINE 1: SELECT 100_; ^ SELECT 100__000; -ERROR: trailing junk after numeric literal at or near "100_" +ERROR: trailing junk after numeric literal at or near "100__000" LINE 1: SELECT 100__000; ^ SELECT _1_000.5; @@ -334,7 +334,7 @@ ERROR: trailing junk after numeric literal at or near "1_000_" LINE 1: SELECT 1_000_.5; ^ SELECT 1_000._5; -ERROR: trailing junk after numeric literal at or near "1_000._" +ERROR: trailing junk after numeric literal at or near "1_000._5" LINE 1: SELECT 1_000._5; ^ SELECT 1_000.5_; @@ -342,11 +342,11 @@ ERROR: trailing junk after numeric literal at or near "1_000.5_" LINE 1: SELECT 1_000.5_; ^ SELECT 1_000.5e_1; -ERROR: trailing junk after numeric literal at or near "1_000.5e" +ERROR: trailing junk after numeric literal at or near "1_000.5e_1" LINE 1: SELECT 1_000.5e_1; ^ PREPARE p1 AS SELECT $0_1; -ERROR: trailing junk after parameter at or near "$0_" +ERROR: trailing junk after parameter at or near "$0_1" LINE 1: PREPARE p1 AS SELECT $0_1; ^ -- diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 9d047b21b88ee..20bf9ea9cdf76 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -855,7 +855,6 @@ sha224(bytea) sha256(bytea) sha384(bytea) sha512(bytea) -gen_random_uuid() starts_with(text,text) macaddr8_eq(macaddr8,macaddr8) macaddr8_lt(macaddr8,macaddr8) @@ -874,6 +873,19 @@ xid8ne(xid8,xid8) xid8cmp(xid8,xid8) uuid_extract_timestamp(uuid) uuid_extract_version(uuid) +crc32(bytea) +crc32c(bytea) +bytea(smallint) +bytea(integer) +bytea(bigint) +bytea_larger(bytea,bytea) +bytea_smaller(bytea,bytea) +-- Check that functions without argument are not marked as leakproof. +SELECT p1.oid::regprocedure +FROM pg_proc p1 JOIN pg_namespace pn + ON pronamespace = pn.oid +WHERE nspname = 'pg_catalog' AND proleakproof AND pronargs = 0 +ORDER BY 1; -- restore normal output mode \a\t -- List of functions used by libpq's fe-lobj.c diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 53591a4f2d5be..d5368186caa9f 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -62,6 +62,45 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 450 | 0450 | 450 | 0450 (4 rows) +-- inner join with partially-redundant join clauses +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDER BY t1.a, t2.b; + QUERY PLAN +--------------------------------------------------------------- + Sort + Sort Key: t1.a + -> Append + -> Merge Join + Merge Cond: (t1_1.a = t2_1.a) + -> Index Scan using iprt1_p1_a on prt1_p1 t1_1 + -> Sort + Sort Key: t2_1.b + -> Seq Scan on prt2_p1 t2_1 + Filter: (a = b) + -> Hash Join + Hash Cond: (t1_2.a = t2_2.a) + -> Seq Scan on prt1_p2 t1_2 + -> Hash + -> Seq Scan on prt2_p2 t2_2 + Filter: (a = b) + -> Hash Join + Hash Cond: (t1_3.a = t2_3.a) + -> Seq Scan on prt1_p3 t1_3 + -> Hash + -> Seq Scan on prt2_p3 t2_3 + Filter: (a = b) +(22 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDER BY t1.a, t2.b; + a | c | b | c +----+------+----+------ + 0 | 0000 | 0 | 0000 + 6 | 0006 | 6 | 0006 + 12 | 0012 | 12 | 0012 + 18 | 0018 | 18 | 0018 + 24 | 0024 | 24 | 0024 +(5 rows) + -- left outer join, 3-way EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1 t1 @@ -674,6 +713,41 @@ SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) RESET enable_partitionwise_aggregate; RESET enable_hashjoin; +-- bug in freeing the SpecialJoinInfo of a child-join +EXPLAIN (COSTS OFF) +SELECT * FROM prt1 t1 JOIN prt1 t2 ON t1.a = t2.a WHERE t1.a IN (SELECT a FROM prt1 t3); + QUERY PLAN +-------------------------------------------------- + Append + -> Hash Semi Join + Hash Cond: (t1_1.a = t3_1.a) + -> Hash Join + Hash Cond: (t1_1.a = t2_1.a) + -> Seq Scan on prt1_p1 t1_1 + -> Hash + -> Seq Scan on prt1_p1 t2_1 + -> Hash + -> Seq Scan on prt1_p1 t3_1 + -> Hash Semi Join + Hash Cond: (t1_2.a = t3_2.a) + -> Hash Join + Hash Cond: (t1_2.a = t2_2.a) + -> Seq Scan on prt1_p2 t1_2 + -> Hash + -> Seq Scan on prt1_p2 t2_2 + -> Hash + -> Seq Scan on prt1_p2 t3_2 + -> Hash Semi Join + Hash Cond: (t1_3.a = t3_3.a) + -> Hash Join + Hash Cond: (t1_3.a = t2_3.a) + -> Seq Scan on prt1_p3 t1_3 + -> Hash + -> Seq Scan on prt1_p3 t2_3 + -> Hash + -> Seq Scan on prt1_p3 t3_3 +(28 rows) + -- -- partitioned by expression -- @@ -1803,6 +1877,55 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1 450 | 0002 | 450 | 0002 (4 rows) +-- inner join with partially-redundant join clauses +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDER BY t1.a, t2.b; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Sort Key: t1.a + -> Append + -> Hash Join + Hash Cond: ((t1_1.a = t2_1.a) AND ((t1_1.c)::text = (t2_1.c)::text)) + -> Seq Scan on prt1_l_p1 t1_1 + -> Hash + -> Seq Scan on prt2_l_p1 t2_1 + Filter: (a = b) + -> Hash Join + Hash Cond: ((t1_2.a = t2_2.a) AND ((t1_2.c)::text = (t2_2.c)::text)) + -> Seq Scan on prt1_l_p2_p1 t1_2 + -> Hash + -> Seq Scan on prt2_l_p2_p1 t2_2 + Filter: (a = b) + -> Hash Join + Hash Cond: ((t1_3.a = t2_3.a) AND ((t1_3.c)::text = (t2_3.c)::text)) + -> Seq Scan on prt1_l_p2_p2 t1_3 + -> Hash + -> Seq Scan on prt2_l_p2_p2 t2_3 + Filter: (a = b) + -> Hash Join + Hash Cond: ((t1_5.a = t2_5.a) AND ((t1_5.c)::text = (t2_5.c)::text)) + -> Append + -> Seq Scan on prt1_l_p3_p1 t1_5 + -> Seq Scan on prt1_l_p3_p2 t1_6 + -> Hash + -> Append + -> Seq Scan on prt2_l_p3_p1 t2_5 + Filter: (a = b) + -> Seq Scan on prt2_l_p3_p2 t2_6 + Filter: (a = b) +(32 rows) + +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDER BY t1.a, t2.b; + a | c | b | c +----+------+----+------ + 0 | 0000 | 0 | 0000 + 6 | 0002 | 6 | 0002 + 12 | 0000 | 12 | 0000 + 18 | 0002 | 18 | 0002 + 24 | 0000 | 24 | 0000 +(5 rows) + -- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0 ORDER BY t1.a, t2.b; @@ -5137,6 +5260,140 @@ SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DE Index Cond: (id = x_2.id) (11 rows) +EXPLAIN (COSTS OFF) -- Should use NestLoop with parameterised inner scan +SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) +ORDER BY x.id DESC LIMIT 2; + QUERY PLAN +-------------------------------------------------------------------------------- + Limit + -> Merge Append + Sort Key: x.id DESC + -> Nested Loop Left Join + -> Index Only Scan Backward using fract_t0_pkey on fract_t0 x_1 + -> Index Only Scan using fract_t0_pkey on fract_t0 y_1 + Index Cond: (id = x_1.id) + -> Nested Loop Left Join + -> Index Only Scan Backward using fract_t1_pkey on fract_t1 x_2 + -> Index Only Scan using fract_t1_pkey on fract_t1 y_2 + Index Cond: (id = x_2.id) +(11 rows) + +-- +-- Test Append's fractional paths +-- +CREATE INDEX pht1_c_idx ON pht1(c); +-- SeqScan might be the best choice if we need one single tuple +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Limit + -> Append + -> Nested Loop + Join Filter: (p1_1.c = p2_1.c) + -> Seq Scan on pht1_p1 p1_1 + -> Materialize + -> Seq Scan on pht1_p1 p2_1 + -> Nested Loop + Join Filter: (p1_2.c = p2_2.c) + -> Seq Scan on pht1_p2 p1_2 + -> Materialize + -> Seq Scan on pht1_p2 p2_2 + -> Nested Loop + Join Filter: (p1_3.c = p2_3.c) + -> Seq Scan on pht1_p3 p1_3 + -> Materialize + -> Seq Scan on pht1_p3 p2_3 +(17 rows) + +-- Increase number of tuples requested and an IndexScan will be chosen +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 100; + QUERY PLAN +------------------------------------------------------------------------ + Limit + -> Append + -> Nested Loop + -> Seq Scan on pht1_p1 p1_1 + -> Memoize + Cache Key: p1_1.c + Cache Mode: logical + -> Index Scan using pht1_p1_c_idx on pht1_p1 p2_1 + Index Cond: (c = p1_1.c) + -> Nested Loop + -> Seq Scan on pht1_p2 p1_2 + -> Memoize + Cache Key: p1_2.c + Cache Mode: logical + -> Index Scan using pht1_p2_c_idx on pht1_p2 p2_2 + Index Cond: (c = p1_2.c) + -> Nested Loop + -> Seq Scan on pht1_p3 p1_3 + -> Memoize + Cache Key: p1_3.c + Cache Mode: logical + -> Index Scan using pht1_p3_c_idx on pht1_p3 p2_3 + Index Cond: (c = p1_3.c) +(23 rows) + +-- If almost all the data should be fetched - prefer SeqScan +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 1000; + QUERY PLAN +-------------------------------------------------- + Limit + -> Append + -> Hash Join + Hash Cond: (p1_1.c = p2_1.c) + -> Seq Scan on pht1_p1 p1_1 + -> Hash + -> Seq Scan on pht1_p1 p2_1 + -> Hash Join + Hash Cond: (p1_2.c = p2_2.c) + -> Seq Scan on pht1_p2 p1_2 + -> Hash + -> Seq Scan on pht1_p2 p2_2 + -> Hash Join + Hash Cond: (p1_3.c = p2_3.c) + -> Seq Scan on pht1_p3 p1_3 + -> Hash + -> Seq Scan on pht1_p3 p2_3 +(17 rows) + +SET max_parallel_workers_per_gather = 1; +SET debug_parallel_query = on; +-- Partial paths should also be smart enough to employ limits +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 100; + QUERY PLAN +------------------------------------------------------------------------------ + Gather + Workers Planned: 1 + Single Copy: true + -> Limit + -> Append + -> Nested Loop + -> Seq Scan on pht1_p1 p1_1 + -> Memoize + Cache Key: p1_1.c + Cache Mode: logical + -> Index Scan using pht1_p1_c_idx on pht1_p1 p2_1 + Index Cond: (c = p1_1.c) + -> Nested Loop + -> Seq Scan on pht1_p2 p1_2 + -> Memoize + Cache Key: p1_2.c + Cache Mode: logical + -> Index Scan using pht1_p2_c_idx on pht1_p2 p2_2 + Index Cond: (c = p1_2.c) + -> Nested Loop + -> Seq Scan on pht1_p3 p1_3 + -> Memoize + Cache Key: p1_3.c + Cache Mode: logical + -> Index Scan using pht1_p3_c_idx on pht1_p3 p2_3 + Index Cond: (c = p1_3.c) +(26 rows) + +RESET debug_parallel_query; +-- Remove indexes from the partitioned table and its partitions +DROP INDEX pht1_c_idx CASCADE; -- cleanup DROP TABLE fract_t; RESET max_parallel_workers_per_gather; diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out deleted file mode 100644 index 59836e2d35e1e..0000000000000 --- a/src/test/regress/expected/partition_merge.out +++ /dev/null @@ -1,945 +0,0 @@ --- --- PARTITIONS_MERGE --- Tests for "ALTER TABLE ... MERGE PARTITIONS ..." command --- -CREATE SCHEMA partitions_merge_schema; -CREATE SCHEMA partitions_merge_schema2; -SET search_path = partitions_merge_schema, public; --- --- BY RANGE partitioning --- --- --- Test for error codes --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_dec2021 PARTITION OF sales_range FOR VALUES FROM ('2021-12-01') TO ('2021-12-31'); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr_1 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-04-15'); -CREATE TABLE sales_apr_2 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-15') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; --- ERROR: partition with name "sales_feb2022" is already used -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_feb2022) INTO sales_feb_mar_apr2022; -ERROR: partition with name "sales_feb2022" is already used -LINE 1: ...e MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_feb2... - ^ --- ERROR: "sales_apr2022" is not a table -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO sales_feb_mar_apr2022; -ERROR: "sales_apr2022" is not a table --- ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_jan2022" --- (space between sections sales_jan2022 and sales_mar2022) -ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022; -ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_jan2022" --- ERROR: lower bound of partition "sales_jan2022" conflicts with upper bound of previous partition "sales_dec2021" --- (space between sections sales_dec2021 and sales_jan2022) -ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022; -ERROR: lower bound of partition "sales_jan2022" conflicts with upper bound of previous partition "sales_dec2021" --- NO ERROR: test for custom partitions order, source partitions not in the search_path -SET search_path = partitions_merge_schema2, public; -ALTER TABLE partitions_merge_schema.sales_range MERGE PARTITIONS ( - partitions_merge_schema.sales_feb2022, - partitions_merge_schema.sales_mar2022, - partitions_merge_schema.sales_jan2022) INTO sales_jan_feb_mar2022; -SET search_path = partitions_merge_schema, public; -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr -------------------------------------------------+---------+------------------+-------------------------------------------------- - partitions_merge_schema2.sales_jan_feb_mar2022 | r | f | FOR VALUES FROM ('01-01-2022') TO ('04-01-2022') - sales_apr2022 | p | f | FOR VALUES FROM ('04-01-2022') TO ('05-01-2022') - sales_dec2021 | r | f | FOR VALUES FROM ('12-01-2021') TO ('12-31-2021') - sales_others | r | f | DEFAULT -(4 rows) - -DROP TABLE sales_range; --- --- Add rows into partitioned table, then merge partitions --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT pg_catalog.pg_get_partkeydef('sales_range'::regclass); - pg_get_partkeydef --------------------- - RANGE (sales_date) -(1 row) - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr ----------------+---------+------------------+-------------------------------------------------- - sales_apr2022 | r | f | FOR VALUES FROM ('04-01-2022') TO ('05-01-2022') - sales_feb2022 | r | f | FOR VALUES FROM ('02-01-2022') TO ('03-01-2022') - sales_jan2022 | r | f | FOR VALUES FROM ('01-01-2022') TO ('02-01-2022') - sales_mar2022 | r | f | FOR VALUES FROM ('03-01-2022') TO ('04-01-2022') - sales_others | r | f | DEFAULT -(5 rows) - --- check schema-qualified name of the new partition -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO partitions_merge_schema2.sales_feb_mar_apr2022; --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr -------------------------------------------------+---------+------------------+-------------------------------------------------- - partitions_merge_schema2.sales_feb_mar_apr2022 | r | f | FOR VALUES FROM ('02-01-2022') TO ('05-01-2022') - sales_jan2022 | r | f | FOR VALUES FROM ('01-01-2022') TO ('02-01-2022') - sales_others | r | f | DEFAULT -(3 rows) - -SELECT * FROM pg_indexes WHERE tablename = 'sales_feb_mar_apr2022' and schemaname = 'partitions_merge_schema2'; - schemaname | tablename | indexname | tablespace | indexdef ---------------------------+-----------------------+--------------------------------------+------------+------------------------------------------------------------------------------------------------------------------------------ - partitions_merge_schema2 | sales_feb_mar_apr2022 | sales_feb_mar_apr2022_sales_date_idx | | CREATE INDEX sales_feb_mar_apr2022_sales_date_idx ON partitions_merge_schema2.sales_feb_mar_apr2022 USING btree (sales_date) -(1 row) - -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_jan2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 -(3 rows) - -SELECT * FROM partitions_merge_schema2.sales_feb_mar_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(10 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 14 | Smith | 510 | 05-04-2022 -(1 row) - --- Use indexscan for testing indexes -SET enable_seqscan = OFF; -SELECT * FROM partitions_merge_schema2.sales_feb_mar_apr2022 where sales_date > '2022-01-01'; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 11 | Trump | 380 | 04-06-2022 - 5 | Deev | 250 | 04-07-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(10 rows) - -RESET enable_seqscan; -DROP TABLE sales_range; --- --- Merge some partitions into DEFAULT partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); --- Merge partitions (include DEFAULT partition) into partition with the same --- name -ALTER TABLE sales_range MERGE PARTITIONS - (sales_jan2022, sales_mar2022, partitions_merge_schema.sales_others) INTO sales_others; -select * from sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 14 | Smith | 510 | 05-04-2022 -(7 rows) - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr ----------------+---------+------------------+-------------------------------------------------- - sales_apr2022 | r | f | FOR VALUES FROM ('04-01-2022') TO ('05-01-2022') - sales_feb2022 | r | f | FOR VALUES FROM ('02-01-2022') TO ('03-01-2022') - sales_others | r | f | DEFAULT -(3 rows) - -DROP TABLE sales_range; --- --- Test for: --- * composite partition key; --- * GENERATED column; --- * column with DEFAULT value. --- -CREATE TABLE sales_date (salesperson_name VARCHAR(30), sales_year INT, sales_month INT, sales_day INT, - sales_date VARCHAR(10) GENERATED ALWAYS AS - (LPAD(sales_year::text, 4, '0') || '.' || LPAD(sales_month::text, 2, '0') || '.' || LPAD(sales_day::text, 2, '0')) STORED, - sales_department VARCHAR(30) DEFAULT 'Sales department') - PARTITION BY RANGE (sales_year, sales_month, sales_day); -CREATE TABLE sales_dec2022 PARTITION OF sales_date FOR VALUES FROM (2021, 12, 1) TO (2022, 1, 1); -CREATE TABLE sales_jan2022 PARTITION OF sales_date FOR VALUES FROM (2022, 1, 1) TO (2022, 2, 1); -CREATE TABLE sales_feb2022 PARTITION OF sales_date FOR VALUES FROM (2022, 2, 1) TO (2022, 3, 1); -CREATE TABLE sales_other PARTITION OF sales_date FOR VALUES FROM (2022, 3, 1) TO (MAXVALUE, MAXVALUE, MAXVALUE); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2021, 12, 7); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2021, 12, 8); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 1, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 2, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 1, 2); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 2, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 3, 3); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 3, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 5, 1); -SELECT * FROM sales_date; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(9 rows) - -SELECT * FROM sales_dec2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department -(2 rows) - -SELECT * FROM sales_jan2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department -(2 rows) - -SELECT * FROM sales_feb2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department -(2 rows) - -SELECT * FROM sales_other; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(3 rows) - -ALTER TABLE sales_date MERGE PARTITIONS (sales_jan2022, sales_feb2022) INTO sales_jan_feb2022; -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 1, 10); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 2, 10); -SELECT * FROM sales_date; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager1 | 2022 | 1 | 10 | 2022.01.10 | Sales department - Manager2 | 2022 | 2 | 10 | 2022.02.10 | Sales department - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(11 rows) - -SELECT * FROM sales_dec2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department -(2 rows) - -SELECT * FROM sales_jan_feb2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager1 | 2022 | 1 | 10 | 2022.01.10 | Sales department - Manager2 | 2022 | 2 | 10 | 2022.02.10 | Sales department -(6 rows) - -SELECT * FROM sales_other; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(3 rows) - -DROP TABLE sales_date; --- --- Test: merge partitions of partitioned table with triggers --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_20 PARTITION OF salespeople FOR VALUES FROM (10) TO (20); -CREATE TABLE salespeople20_30 PARTITION OF salespeople FOR VALUES FROM (20) TO (30); -CREATE TABLE salespeople30_40 PARTITION OF salespeople FOR VALUES FROM (30) TO (40); -INSERT INTO salespeople VALUES (1, 'Poirot'); -CREATE OR REPLACE FUNCTION after_insert_row_trigger() RETURNS trigger LANGUAGE 'plpgsql' AS $BODY$ -BEGIN - RAISE NOTICE 'trigger(%) called: action = %, when = %, level = %', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END; -$BODY$; -CREATE TRIGGER salespeople_after_insert_statement_trigger - AFTER INSERT - ON salespeople - FOR EACH STATEMENT - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); -CREATE TRIGGER salespeople_after_insert_row_trigger - AFTER INSERT - ON salespeople - FOR EACH ROW - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (10, 'May'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = STATEMENT --- 1 trigger should fire here (row): -INSERT INTO salespeople10_20 VALUES (19, 'Ivanov'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -ALTER TABLE salespeople MERGE PARTITIONS (salespeople10_20, salespeople20_30, salespeople30_40) INTO salespeople10_40; --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (20, 'Smirnoff'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = STATEMENT --- 1 trigger should fire here (row): -INSERT INTO salespeople10_40 VALUES (30, 'Ford'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -SELECT * FROM salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -SELECT * FROM salespeople10_40; - salesperson_id | salesperson_name -----------------+------------------ - 10 | May - 19 | Ivanov - 20 | Smirnoff - 30 | Ford -(4 rows) - -DROP TABLE salespeople; -DROP FUNCTION after_insert_row_trigger(); --- --- Test: merge partitions with deleted columns --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); --- Create partitions with some deleted columns: -CREATE TABLE salespeople10_20(d1 VARCHAR(30), salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)); -CREATE TABLE salespeople20_30(salesperson_id INT PRIMARY KEY, d2 INT, salesperson_name VARCHAR(30)); -CREATE TABLE salespeople30_40(salesperson_id INT PRIMARY KEY, d3 DATE, salesperson_name VARCHAR(30)); -INSERT INTO salespeople10_20 VALUES ('dummy value 1', 19, 'Ivanov'); -INSERT INTO salespeople20_30 VALUES (20, 101, 'Smirnoff'); -INSERT INTO salespeople30_40 VALUES (31, now(), 'Popov'); -ALTER TABLE salespeople10_20 DROP COLUMN d1; -ALTER TABLE salespeople20_30 DROP COLUMN d2; -ALTER TABLE salespeople30_40 DROP COLUMN d3; -ALTER TABLE salespeople ATTACH PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20); -ALTER TABLE salespeople ATTACH PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30); -ALTER TABLE salespeople ATTACH PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40); -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (30, 'Ford'); -ALTER TABLE salespeople MERGE PARTITIONS (salespeople10_20, salespeople20_30, salespeople30_40) INTO salespeople10_40; -select * from salespeople; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot - 19 | Ivanov - 10 | May - 20 | Smirnoff - 31 | Popov - 30 | Ford -(6 rows) - -select * from salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -select * from salespeople10_40; - salesperson_id | salesperson_name -----------------+------------------ - 19 | Ivanov - 10 | May - 20 | Smirnoff - 31 | Popov - 30 | Ford -(5 rows) - -DROP TABLE salespeople; --- --- Test: merge sub-partitions --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr2022_01_10 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-04-10'); -CREATE TABLE sales_apr2022_10_20 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-10') TO ('2022-04-20'); -CREATE TABLE sales_apr2022_20_30 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-20') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(4 rows) - -SELECT * FROM sales_apr2022_01_10; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(2 rows) - -SELECT * FROM sales_apr2022_10_20; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 4 | Ivanov | 750 | 04-13-2022 -(1 row) - -SELECT * FROM sales_apr2022_20_30; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 -(1 row) - -ALTER TABLE sales_apr2022 MERGE PARTITIONS (sales_apr2022_01_10, sales_apr2022_10_20, sales_apr2022_20_30) INTO sales_apr_all; -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(4 rows) - -SELECT * FROM sales_apr_all; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(4 rows) - -DROP TABLE sales_range; --- --- BY LIST partitioning --- --- --- Test: specific errors for BY LIST partitioning --- -CREATE TABLE sales_list -(salesperson_id INT GENERATED ALWAYS AS IDENTITY, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_west PARTITION OF sales_list FOR VALUES IN ('Lisbon', 'New York', 'Madrid'); -CREATE TABLE sales_east PARTITION OF sales_list FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'); -CREATE TABLE sales_central PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; -CREATE TABLE sales_list2 (LIKE sales_list) PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord2 PARTITION OF sales_list2 FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_others2 PARTITION OF sales_list2 DEFAULT; -CREATE TABLE sales_external (LIKE sales_list); -CREATE TABLE sales_external2 (vch VARCHAR(5)); --- ERROR: "sales_external" is not a partition -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external) INTO sales_all; -ERROR: "sales_external" is not a partition --- ERROR: "sales_external2" is not a partition -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external2) INTO sales_all; -ERROR: "sales_external2" is not a partition --- ERROR: relation "sales_nord2" is not a partition of relation "sales_list" -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_nord2, sales_east) INTO sales_all; -ERROR: relation "sales_nord2" is not a partition of relation "sales_list" -DROP TABLE sales_external2; -DROP TABLE sales_external; -DROP TABLE sales_list2; -DROP TABLE sales_list; --- --- Test: BY LIST partitioning, MERGE PARTITIONS with data --- -CREATE TABLE sales_list -(salesperson_id INT GENERATED ALWAYS AS IDENTITY, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE INDEX sales_list_salesperson_name_idx ON sales_list USING btree (salesperson_name); -CREATE INDEX sales_list_sales_state_idx ON sales_list USING btree (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_west PARTITION OF sales_list FOR VALUES IN ('Lisbon', 'New York', 'Madrid'); -CREATE TABLE sales_east PARTITION OF sales_list FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'); -CREATE TABLE sales_central PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Trump', 'Bejing', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smirnoff', 'New York', 500, '2022-03-03'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ford', 'St. Petersburg', 2000, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ivanov', 'Warsaw', 750, '2022-03-04'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Deev', 'Lisbon', 250, '2022-03-07'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Poirot', 'Berlin', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Helsinki', 1200, '2022-03-06'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Li', 'Vladivostok', 1150, '2022-03-09'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Helsinki', 1200, '2022-03-11'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Halder', 'Oslo', 800, '2022-03-02'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Muller', 'Madrid', 650, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smith', 'Kyiv', 350, '2022-03-10'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Gandi', 'Warsaw', 150, '2022-03-08'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Plato', 'Lisbon', 950, '2022-03-05'); --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_list'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr ----------------+---------+------------------+------------------------------------------------------ - sales_central | r | f | FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv') - sales_east | r | f | FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok') - sales_nord | r | f | FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki') - sales_west | r | f | FOR VALUES IN ('Lisbon', 'New York', 'Madrid') - sales_others | r | f | DEFAULT -(5 rows) - -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_central) INTO sales_all; --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_list'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | relkind | inhdetachpending | pg_get_expr ---------------+---------+------------------+-------------------------------------------------------------------------------------------------------------- - sales_all | r | f | FOR VALUES IN ('Lisbon', 'New York', 'Madrid', 'Bejing', 'Delhi', 'Vladivostok', 'Warsaw', 'Berlin', 'Kyiv') - sales_nord | r | f | FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki') - sales_others | r | f | DEFAULT -(3 rows) - -SELECT * FROM sales_list; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+----------------+--------------+------------ - 2 | Smirnoff | New York | 500 | 03-03-2022 - 5 | Deev | Lisbon | 250 | 03-07-2022 - 11 | Muller | Madrid | 650 | 03-05-2022 - 14 | Plato | Lisbon | 950 | 03-05-2022 - 1 | Trump | Bejing | 1000 | 03-01-2022 - 8 | Li | Vladivostok | 1150 | 03-09-2022 - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 6 | Poirot | Berlin | 1000 | 03-01-2022 - 12 | Smith | Kyiv | 350 | 03-10-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 - 3 | Ford | St. Petersburg | 2000 | 03-05-2022 - 7 | May | Helsinki | 1200 | 03-06-2022 - 9 | May | Helsinki | 1200 | 03-11-2022 - 10 | Halder | Oslo | 800 | 03-02-2022 -(14 rows) - -SELECT * FROM sales_nord; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+----------------+--------------+------------ - 3 | Ford | St. Petersburg | 2000 | 03-05-2022 - 7 | May | Helsinki | 1200 | 03-06-2022 - 9 | May | Helsinki | 1200 | 03-11-2022 - 10 | Halder | Oslo | 800 | 03-02-2022 -(4 rows) - -SELECT * FROM sales_all; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 2 | Smirnoff | New York | 500 | 03-03-2022 - 5 | Deev | Lisbon | 250 | 03-07-2022 - 11 | Muller | Madrid | 650 | 03-05-2022 - 14 | Plato | Lisbon | 950 | 03-05-2022 - 1 | Trump | Bejing | 1000 | 03-01-2022 - 8 | Li | Vladivostok | 1150 | 03-09-2022 - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 6 | Poirot | Berlin | 1000 | 03-01-2022 - 12 | Smith | Kyiv | 350 | 03-10-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(10 rows) - --- Use indexscan for testing indexes after merging partitions -SET enable_seqscan = OFF; -SELECT * FROM sales_all WHERE sales_state = 'Warsaw'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(2 rows) - -SELECT * FROM sales_list WHERE sales_state = 'Warsaw'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(2 rows) - -SELECT * FROM sales_list WHERE salesperson_name = 'Ivanov'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 -(1 row) - -RESET enable_seqscan; -DROP TABLE sales_list; --- --- Try to MERGE partitions of another table. --- -CREATE TABLE t1 (i int, a int, b int, c int) PARTITION BY RANGE (a, b); -CREATE TABLE t1p1 PARTITION OF t1 FOR VALUES FROM (1, 1) TO (1, 2); -CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t); -CREATE TABLE t2pa PARTITION OF t2 FOR VALUES FROM ('A') TO ('C'); -CREATE TABLE t3 (i int, t text); --- ERROR: relation "t1p1" is not a partition of relation "t2" -ALTER TABLE t2 MERGE PARTITIONS (t1p1, t2pa) INTO t2p; -ERROR: relation "t1p1" is not a partition of relation "t2" --- ERROR: "t3" is not a partition -ALTER TABLE t2 MERGE PARTITIONS (t2pa, t3) INTO t2p; -ERROR: "t3" is not a partition -DROP TABLE t3; -DROP TABLE t2; -DROP TABLE t1; --- --- Try to MERGE partitions of temporary table. --- -CREATE TEMP TABLE t (i int) PARTITION BY RANGE (i); -CREATE TEMP TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TEMP TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_1 | FOR VALUES FROM (0) TO (1) | t - tp_1_2 | FOR VALUES FROM (1) TO (2) | t -(2 rows) - -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; --- Partition should be temporary. -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_2 | FOR VALUES FROM (0) TO (2) | t -(1 row) - -DROP TABLE t; --- --- Check the partition index name if the partition name is the same as one --- of the merged partitions. --- -CREATE TABLE t (i int, PRIMARY KEY(i)) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -CREATE INDEX tidx ON t(i); -ALTER TABLE t MERGE PARTITIONS (tp_1_2, tp_0_1) INTO tp_1_2; --- Indexname values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'. --- Not-null constraint name should be 'tp_1_2_i_not_null'. -\d+ tp_1_2 - Table "partitions_merge_schema.tp_1_2" - Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ---------+---------+-----------+----------+---------+---------+--------------+------------- - i | integer | | not null | | plain | | -Partition of: t FOR VALUES FROM (0) TO (2) -Partition constraint: ((i IS NOT NULL) AND (i >= 0) AND (i < 2)) -Indexes: - "tp_1_2_pkey" PRIMARY KEY, btree (i) - "tp_1_2_i_idx" btree (i) - -DROP TABLE t; --- --- Try mixing permanent and temporary partitions. --- -SET search_path = partitions_merge_schema, pg_temp, public; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -SELECT c.oid::pg_catalog.regclass, c.relpersistence FROM pg_catalog.pg_class c WHERE c.oid = 't'::regclass; - oid | relpersistence ------+---------------- - t | p -(1 row) - -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_1 | FOR VALUES FROM (0) TO (1) | p - tp_1_2 | FOR VALUES FROM (1) TO (2) | p -(2 rows) - -SET search_path = pg_temp, partitions_merge_schema, public; --- Can't merge persistent partitions into a temporary partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ERROR: cannot create a temporary relation as partition of permanent relation "t" -SET search_path = partitions_merge_schema, public; --- Can't merge persistent partitions into a temporary partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO pg_temp.tp_0_2; -ERROR: cannot create a temporary relation as partition of permanent relation "t" -DROP TABLE t; -SET search_path = pg_temp, partitions_merge_schema, public; -BEGIN; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -SELECT c.oid::pg_catalog.regclass, c.relpersistence FROM pg_catalog.pg_class c WHERE c.oid = 't'::regclass; - oid | relpersistence ------+---------------- - t | t -(1 row) - -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_1 | FOR VALUES FROM (0) TO (1) | t - tp_1_2 | FOR VALUES FROM (1) TO (2) | t -(2 rows) - -SET search_path = partitions_merge_schema, pg_temp, public; --- Can't merge temporary partitions into a persistent partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ROLLBACK; --- Check the new partition inherits parent's tablespace -SET search_path = partitions_merge_schema, public; -CREATE TABLE t (i int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) - PARTITION BY RANGE (i) TABLESPACE regress_tblspace; -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -SELECT tablename, tablespace FROM pg_tables - WHERE tablename IN ('t', 'tp_0_2') AND schemaname = 'partitions_merge_schema' - ORDER BY tablename, tablespace; - tablename | tablespace ------------+------------------ - t | regress_tblspace - tp_0_2 | regress_tblspace -(2 rows) - -SELECT tablename, indexname, tablespace FROM pg_indexes - WHERE tablename IN ('t', 'tp_0_2') AND schemaname = 'partitions_merge_schema' - ORDER BY tablename, indexname, tablespace; - tablename | indexname | tablespace ------------+-------------+------------------ - t | t_pkey | regress_tblspace - tp_0_2 | tp_0_2_pkey | regress_tblspace -(2 rows) - -DROP TABLE t; --- Check the new partition inherits parent's table access method -SET search_path = partitions_merge_schema, public; -CREATE ACCESS METHOD partitions_merge_heap TYPE TABLE HANDLER heap_tableam_handler; -CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partitions_merge_heap; -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -SELECT c.relname, a.amname -FROM pg_class c JOIN pg_am a ON c.relam = a.oid -WHERE c.oid IN ('t'::regclass, 'tp_0_2'::regclass) -ORDER BY c.relname; - relname | amname ----------+----------------------- - t | partitions_merge_heap - tp_0_2 | partitions_merge_heap -(2 rows) - -DROP TABLE t; -DROP ACCESS METHOD partitions_merge_heap; --- Test permission checks. The user needs to own the parent table and all --- the merging partitions to do the merge. -CREATE ROLE regress_partition_merge_alice; -CREATE ROLE regress_partition_merge_bob; -GRANT ALL ON SCHEMA partitions_merge_schema TO regress_partition_merge_alice; -GRANT ALL ON SCHEMA partitions_merge_schema TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_alice; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ERROR: must be owner of table t -RESET SESSION AUTHORIZATION; -ALTER TABLE t OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ERROR: must be owner of table tp_0_1 -RESET SESSION AUTHORIZATION; -ALTER TABLE tp_0_1 OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ERROR: must be owner of table tp_1_2 -RESET SESSION AUTHORIZATION; -ALTER TABLE tp_1_2 OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -RESET SESSION AUTHORIZATION; -DROP TABLE t; -REVOKE ALL ON SCHEMA partitions_merge_schema FROM regress_partition_merge_alice; -REVOKE ALL ON SCHEMA partitions_merge_schema FROM regress_partition_merge_bob; -DROP ROLE regress_partition_merge_alice; -DROP ROLE regress_partition_merge_bob; -RESET search_path; --- -DROP SCHEMA partitions_merge_schema; -DROP SCHEMA partitions_merge_schema2; diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index 7a03b4e3607ab..d1966cd7d829f 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -11,7 +11,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', query) loop ln := regexp_replace(ln, 'Maximum Storage: \d+', 'Maximum Storage: N'); @@ -1893,6 +1893,35 @@ explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000; (2 rows) drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, iboolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2; +-- check that AlternativeSubPlan within a pruning expression gets cleaned up +create table asptab (id int primary key) partition by range (id); +create table asptab0 partition of asptab for values from (0) to (1); +create table asptab1 partition of asptab for values from (1) to (2); +explain (costs off) +select * from + (select exists (select 1 from int4_tbl tinner where f1 = touter.f1) as b + from int4_tbl touter) ss, + asptab +where asptab.id > ss.b::int; + QUERY PLAN +-------------------------------------------------------------------- + Nested Loop + -> Seq Scan on int4_tbl touter + -> Append + -> Index Only Scan using asptab0_pkey on asptab0 asptab_1 + Index Cond: (id > (EXISTS(SubPlan 3))::integer) + SubPlan 4 + -> Seq Scan on int4_tbl tinner_2 + -> Index Only Scan using asptab1_pkey on asptab1 asptab_2 + Index Cond: (id > (EXISTS(SubPlan 3))::integer) + SubPlan 3 + -> Seq Scan on int4_tbl tinner_1 + Filter: (f1 = touter.f1) + SubPlan 2 + -> Seq Scan on int4_tbl tinner +(14 rows) + +drop table asptab; -- -- Test Partition pruning for HASH partitioning -- @@ -2127,35 +2156,35 @@ create table ab_a3_b3 partition of ab_a3 for values in (3); set enable_indexonlyscan = off; prepare ab_q1 (int, int, int) as select * from ab where a between $1 and $2 and b <= $3; -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); - QUERY PLAN ---------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 2, 3); + QUERY PLAN +------------------------------------------------------------ + Append (actual rows=0.00 loops=1) Subplans Removed: 6 - -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a2_b3 ab_3 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b3 ab_3 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) (8 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); - QUERY PLAN ---------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (1, 2, 3); + QUERY PLAN +------------------------------------------------------------ + Append (actual rows=0.00 loops=1) Subplans Removed: 3 - -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) + -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a1_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a1_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1) + -> Seq Scan on ab_a1_b3 ab_3 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a2_b2 ab_5 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_5 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) - -> Seq Scan on ab_a2_b3 ab_6 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b3 ab_6 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b <= $3)) (14 rows) @@ -2163,29 +2192,29 @@ deallocate ab_q1; -- Runtime pruning after optimizer pruning prepare ab_q1 (int, int) as select a from ab where a between $1 and $2 and b < 3; -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2); - QUERY PLAN ---------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 2); + QUERY PLAN +------------------------------------------------------------ + Append (actual rows=0.00 loops=1) Subplans Removed: 4 - -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) - -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) (6 rows) -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); - QUERY PLAN ---------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 4); + QUERY PLAN +------------------------------------------------------------ + Append (actual rows=0.00 loops=1) Subplans Removed: 2 - -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) - -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) - -> Seq Scan on ab_a3_b1 ab_3 (actual rows=0 loops=1) + -> Seq Scan on ab_a3_b1 ab_3 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) - -> Seq Scan on ab_a3_b2 ab_4 (actual rows=0 loops=1) + -> Seq Scan on ab_a3_b2 ab_4 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < 3)) (10 rows) @@ -2193,16 +2222,16 @@ explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); -- different levels of partitioning. prepare ab_q2 (int, int) as select a from ab where a between $1 and $2 and b < (select 3); -explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q2 (2, 2); QUERY PLAN ----------------------------------------------------------------------- - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 6 InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Seq Scan on ab_a2_b1 ab_1 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1)) - -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1)) -> Seq Scan on ab_a2_b3 ab_3 (never executed) Filter: ((a >= $1) AND (a <= $2) AND (b < (InitPlan 1).col1)) @@ -2211,16 +2240,16 @@ explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); -- As above, but swap the PARAM_EXEC Param to the first partition level prepare ab_q3 (int, int) as select a from ab where b between $1 and $2 and a < (select 3); -explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q3 (2, 2); QUERY PLAN ----------------------------------------------------------------------- - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 6 InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Seq Scan on ab_a1_b2 ab_1 (actual rows=0 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Seq Scan on ab_a1_b2 ab_1 (actual rows=0.00 loops=1) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1)) - -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b2 ab_2 (actual rows=0.00 loops=1) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1)) -> Seq Scan on ab_a3_b2 ab_3 (never executed) Filter: ((b >= $1) AND (b <= $2) AND (a < (InitPlan 1).col1)) @@ -2273,45 +2302,45 @@ begin; -- Test run-time pruning using stable functions create function list_part_fn(int) returns int as $$ begin return $1; end;$$ language plpgsql stable; -- Ensure pruning works using a stable function containing no Vars -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); - QUERY PLAN ------------------------------------------------------------------- - Append (actual rows=1 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(1); + QUERY PLAN +--------------------------------------------------------------------- + Append (actual rows=1.00 loops=1) Subplans Removed: 3 - -> Seq Scan on list_part1 list_part_1 (actual rows=1 loops=1) + -> Seq Scan on list_part1 list_part_1 (actual rows=1.00 loops=1) Filter: (a = list_part_fn(1)) (4 rows) -- Ensure pruning does not take place when the function has a Var parameter -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); - QUERY PLAN ------------------------------------------------------------------- - Append (actual rows=4 loops=1) - -> Seq Scan on list_part1 list_part_1 (actual rows=1 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(a); + QUERY PLAN +--------------------------------------------------------------------- + Append (actual rows=4.00 loops=1) + -> Seq Scan on list_part1 list_part_1 (actual rows=1.00 loops=1) Filter: (a = list_part_fn(a)) - -> Seq Scan on list_part2 list_part_2 (actual rows=1 loops=1) + -> Seq Scan on list_part2 list_part_2 (actual rows=1.00 loops=1) Filter: (a = list_part_fn(a)) - -> Seq Scan on list_part3 list_part_3 (actual rows=1 loops=1) + -> Seq Scan on list_part3 list_part_3 (actual rows=1.00 loops=1) Filter: (a = list_part_fn(a)) - -> Seq Scan on list_part4 list_part_4 (actual rows=1 loops=1) + -> Seq Scan on list_part4 list_part_4 (actual rows=1.00 loops=1) Filter: (a = list_part_fn(a)) (9 rows) -- Ensure pruning does not take place when the expression contains a Var. -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; - QUERY PLAN ------------------------------------------------------------------- - Append (actual rows=0 loops=1) - -> Seq Scan on list_part1 list_part_1 (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(1) + a; + QUERY PLAN +--------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) + -> Seq Scan on list_part1 list_part_1 (actual rows=0.00 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 - -> Seq Scan on list_part2 list_part_2 (actual rows=0 loops=1) + -> Seq Scan on list_part2 list_part_2 (actual rows=0.00 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 - -> Seq Scan on list_part3 list_part_3 (actual rows=0 loops=1) + -> Seq Scan on list_part3 list_part_3 (actual rows=0.00 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 - -> Seq Scan on list_part4 list_part_4 (actual rows=0 loops=1) + -> Seq Scan on list_part4 list_part_4 (actual rows=0.00 loops=1) Filter: (a = (list_part_fn(1) + a)) Rows Removed by Filter: 1 (13 rows) @@ -2334,12 +2363,16 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', $1) loop ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N'); - ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N'); + ln := regexp_replace(ln, 'actual rows=\d+(?:\.\d+)? loops=\d+', 'actual rows=N loops=N'); ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N'); + perform regexp_matches(ln, 'Index Searches: \d+'); + if found then + continue; + end if; return next ln; end loop; end; @@ -2641,153 +2674,168 @@ reset parallel_tuple_cost; reset min_parallel_table_scan_size; reset max_parallel_workers_per_gather; -- Test run-time partition pruning with an initplan -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1 from lprt_a); - QUERY PLAN -------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Aggregate (actual rows=1 loops=1) - -> Seq Scan on lprt_a (actual rows=102 loops=1) + -> Aggregate (actual rows=1.00 loops=1) + -> Seq Scan on lprt_a (actual rows=102.00 loops=1) InitPlan 2 - -> Aggregate (actual rows=1 loops=1) - -> Seq Scan on lprt_a lprt_a_1 (actual rows=102 loops=1) + -> Aggregate (actual rows=1.00 loops=1) + -> Seq Scan on lprt_a lprt_a_1 (actual rows=102.00 loops=1) -> Bitmap Heap Scan on ab_a1_b1 ab_1 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a1_b1_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a1_b2 ab_2 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a1_b3 ab_3 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a2_b1 ab_4 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a2_b1_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a2_b2 ab_5 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a2_b2_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a2_b3 ab_6 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a2_b3_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a3_b1 ab_7 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a3_b1_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) - -> Bitmap Heap Scan on ab_a3_b2 ab_8 (actual rows=0 loops=1) + Index Searches: 0 + -> Bitmap Heap Scan on ab_a3_b2 ab_8 (actual rows=0.00 loops=1) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) - -> Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0.00 loops=1) Index Cond: (a = (InitPlan 1).col1) + Index Searches: 1 -> Bitmap Heap Scan on ab_a3_b3 ab_9 (never executed) Recheck Cond: (a = (InitPlan 1).col1) Filter: (b = (InitPlan 2).col1) -> Bitmap Index Scan on ab_a3_b3_a_idx (never executed) Index Cond: (a = (InitPlan 1).col1) -(52 rows) + Index Searches: 0 +(61 rows) -- Test run-time partition pruning with UNION ALL parents -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from (select * from ab where a = 1 union all select * from ab) ab where b = (select 1); - QUERY PLAN -------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Append (actual rows=0 loops=1) - -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Append (actual rows=0.00 loops=1) + -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) - -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0.00 loops=1) Index Cond: (a = 1) + Index Searches: 1 -> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) Index Cond: (a = 1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) Index Cond: (a = 1) - -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) + Index Searches: 0 + -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a1_b2 ab_2 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a1_b3 ab_3 (never executed) Filter: (b = (InitPlan 1).col1) - -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a2_b2 ab_5 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a2_b3 ab_6 (never executed) Filter: (b = (InitPlan 1).col1) - -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1) + -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a3_b2 ab_8 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a3_b3 ab_9 (never executed) Filter: (b = (InitPlan 1).col1) -(37 rows) +(40 rows) -- A case containing a UNION ALL with a non-partitioned child. -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from (select * from ab where a = 1 union all (values(10,5)) union all select * from ab) ab where b = (select 1); - QUERY PLAN -------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +---------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Append (actual rows=0 loops=1) - -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Append (actual rows=0.00 loops=1) + -> Bitmap Heap Scan on ab_a1_b1 ab_11 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) - -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0.00 loops=1) Index Cond: (a = 1) + Index Searches: 1 -> Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) -> Bitmap Index Scan on ab_a1_b2_a_idx (never executed) Index Cond: (a = 1) + Index Searches: 0 -> Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed) Recheck Cond: (a = 1) Filter: (b = (InitPlan 1).col1) -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) Index Cond: (a = 1) - -> Result (actual rows=0 loops=1) + Index Searches: 0 + -> Result (actual rows=0.00 loops=1) One-Time Filter: (5 = (InitPlan 1).col1) - -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) + -> Seq Scan on ab_a1_b1 ab_1 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a1_b2 ab_2 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a1_b3 ab_3 (never executed) Filter: (b = (InitPlan 1).col1) - -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0 loops=1) + -> Seq Scan on ab_a2_b1 ab_4 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a2_b2 ab_5 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a2_b3 ab_6 (never executed) Filter: (b = (InitPlan 1).col1) - -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0 loops=1) + -> Seq Scan on ab_a3_b1 ab_7 (actual rows=0.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a3_b2 ab_8 (never executed) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a3_b3 ab_9 (never executed) Filter: (b = (InitPlan 1).col1) -(39 rows) +(42 rows) -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning. create table xy_1 (x int, y int); @@ -2803,20 +2851,20 @@ union all select tableoid::regclass,a,b from ab ) ab where a = $1 and b = (select -10); -- Ensure the xy_1 subplan is not pruned. -explain (analyze, costs off, summary off, timing off) execute ab_q6(1); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q6(1); QUERY PLAN -------------------------------------------------------- - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 12 InitPlan 1 - -> Result (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) -> Seq Scan on ab_a1_b1 ab_1 (never executed) Filter: ((a = $1) AND (b = (InitPlan 1).col1)) -> Seq Scan on ab_a1_b2 ab_2 (never executed) Filter: ((a = $1) AND (b = (InitPlan 1).col1)) -> Seq Scan on ab_a1_b3 ab_3 (never executed) Filter: ((a = $1) AND (b = (InitPlan 1).col1)) - -> Seq Scan on xy_1 (actual rows=0 loops=1) + -> Seq Scan on xy_1 (actual rows=0.00 loops=1) Filter: ((x = $1) AND (y = (InitPlan 1).col1)) Rows Removed by Filter: 1 -> Seq Scan on ab_a1_b1 ab_4 (never executed) @@ -2846,46 +2894,52 @@ deallocate ab_q6; insert into ab values (1,2); select explain_analyze(' update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;'); - explain_analyze -------------------------------------------------------------------------------------------- - Update on ab_a1 (actual rows=0 loops=1) + explain_analyze +---------------------------------------------------------------------------------------------- + Update on ab_a1 (actual rows=0.00 loops=1) Update on ab_a1_b1 ab_a1_1 Update on ab_a1_b2 ab_a1_2 Update on ab_a1_b3 ab_a1_3 - -> Nested Loop (actual rows=1 loops=1) - -> Append (actual rows=1 loops=1) - -> Bitmap Heap Scan on ab_a1_b1 ab_a1_1 (actual rows=0 loops=1) + -> Nested Loop (actual rows=1.00 loops=1) + -> Append (actual rows=1.00 loops=1) + -> Bitmap Heap Scan on ab_a1_b1 ab_a1_1 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) - -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0.00 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b2 ab_a1_2 (actual rows=1 loops=1) + Index Searches: 1 + -> Bitmap Heap Scan on ab_a1_b2 ab_a1_2 (actual rows=1.00 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 - -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) + -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1.00 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1) + Index Searches: 1 + -> Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 - -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) + -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1.00 loops=1) Index Cond: (a = 1) - -> Materialize (actual rows=1 loops=1) + Index Searches: 1 + -> Materialize (actual rows=1.00 loops=1) Storage: Memory Maximum Storage: NkB - -> Append (actual rows=1 loops=1) - -> Bitmap Heap Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1) + -> Append (actual rows=1.00 loops=1) + -> Bitmap Heap Scan on ab_a1_b1 ab_1 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) - -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0.00 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b2 ab_2 (actual rows=1 loops=1) + Index Searches: 1 + -> Bitmap Heap Scan on ab_a1_b2 ab_2 (actual rows=1.00 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 - -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) + -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1.00 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1) + Index Searches: 1 + -> Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0.00 loops=1) Recheck Cond: (a = 1) Heap Blocks: exact=1 - -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) + -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1.00 loops=1) Index Cond: (a = 1) -(37 rows) + Index Searches: 1 +(43 rows) table ab; a | b @@ -2898,23 +2952,23 @@ truncate ab; insert into ab values (1, 1), (1, 2), (1, 3), (2, 1); select explain_analyze(' update ab_a1 set b = 3 from ab_a2 where ab_a2.b = (select 1);'); - explain_analyze ------------------------------------------------------------------------------- - Update on ab_a1 (actual rows=0 loops=1) + explain_analyze +--------------------------------------------------------------------------------- + Update on ab_a1 (actual rows=0.00 loops=1) Update on ab_a1_b1 ab_a1_1 Update on ab_a1_b2 ab_a1_2 Update on ab_a1_b3 ab_a1_3 InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Nested Loop (actual rows=3 loops=1) - -> Append (actual rows=3 loops=1) - -> Seq Scan on ab_a1_b1 ab_a1_1 (actual rows=1 loops=1) - -> Seq Scan on ab_a1_b2 ab_a1_2 (actual rows=1 loops=1) - -> Seq Scan on ab_a1_b3 ab_a1_3 (actual rows=1 loops=1) - -> Materialize (actual rows=1 loops=3) + -> Result (actual rows=1.00 loops=1) + -> Nested Loop (actual rows=3.00 loops=1) + -> Append (actual rows=3.00 loops=1) + -> Seq Scan on ab_a1_b1 ab_a1_1 (actual rows=1.00 loops=1) + -> Seq Scan on ab_a1_b2 ab_a1_2 (actual rows=1.00 loops=1) + -> Seq Scan on ab_a1_b3 ab_a1_3 (actual rows=1.00 loops=1) + -> Materialize (actual rows=1.00 loops=3) Storage: Memory Maximum Storage: NkB - -> Append (actual rows=1 loops=1) - -> Seq Scan on ab_a2_b1 ab_a2_1 (actual rows=1 loops=1) + -> Append (actual rows=1.00 loops=1) + -> Seq Scan on ab_a2_b1 ab_a2_1 (actual rows=1.00 loops=1) Filter: (b = (InitPlan 1).col1) -> Seq Scan on ab_a2_b2 ab_a2_2 (never executed) Filter: (b = (InitPlan 1).col1) @@ -2952,47 +3006,59 @@ create index tprt6_idx on tprt_6 (col1); insert into tprt values (10), (20), (501), (502), (505), (1001), (4500); set enable_hashjoin = off; set enable_mergejoin = off; -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 > tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- - Nested Loop (actual rows=6 loops=1) - -> Seq Scan on tbl1 (actual rows=2 loops=1) - -> Append (actual rows=3 loops=2) - -> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=2) + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop (actual rows=6.00 loops=1) + -> Seq Scan on tbl1 (actual rows=2.00 loops=1) + -> Append (actual rows=3.00 loops=2) + -> Index Scan using tprt1_idx on tprt_1 (actual rows=2.00 loops=2) Index Cond: (col1 < tbl1.col1) - -> Index Scan using tprt2_idx on tprt_2 (actual rows=2 loops=1) + Index Searches: 2 + -> Index Scan using tprt2_idx on tprt_2 (actual rows=2.00 loops=1) Index Cond: (col1 < tbl1.col1) + Index Searches: 1 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 < tbl1.col1) + Index Searches: 0 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 < tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 < tbl1.col1) + Index Searches: 0 -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 < tbl1.col1) -(15 rows) + Index Searches: 0 +(21 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- - Nested Loop (actual rows=2 loops=1) - -> Seq Scan on tbl1 (actual rows=2 loops=1) - -> Append (actual rows=1 loops=2) + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop (actual rows=2.00 loops=1) + -> Seq Scan on tbl1 (actual rows=2.00 loops=1) + -> Append (actual rows=1.00 loops=2) -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) - -> Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2) + Index Searches: 0 + -> Index Scan using tprt2_idx on tprt_2 (actual rows=1.00 loops=2) Index Cond: (col1 = tbl1.col1) + Index Searches: 2 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Index Searches: 0 +(21 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 > tprt.col1 @@ -3018,47 +3084,59 @@ order by tbl1.col1, tprt.col1; -- Multiple partitions insert into tbl1 values (1001), (1010), (1011); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- - Nested Loop (actual rows=23 loops=1) - -> Seq Scan on tbl1 (actual rows=5 loops=1) - -> Append (actual rows=5 loops=5) - -> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=5) + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop (actual rows=23.00 loops=1) + -> Seq Scan on tbl1 (actual rows=5.00 loops=1) + -> Append (actual rows=4.60 loops=5) + -> Index Scan using tprt1_idx on tprt_1 (actual rows=2.00 loops=5) Index Cond: (col1 < tbl1.col1) - -> Index Scan using tprt2_idx on tprt_2 (actual rows=3 loops=4) + Index Searches: 5 + -> Index Scan using tprt2_idx on tprt_2 (actual rows=2.75 loops=4) Index Cond: (col1 < tbl1.col1) - -> Index Scan using tprt3_idx on tprt_3 (actual rows=1 loops=2) + Index Searches: 4 + -> Index Scan using tprt3_idx on tprt_3 (actual rows=1.00 loops=2) Index Cond: (col1 < tbl1.col1) + Index Searches: 2 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 < tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 < tbl1.col1) + Index Searches: 0 -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 < tbl1.col1) -(15 rows) + Index Searches: 0 +(21 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- - Nested Loop (actual rows=3 loops=1) - -> Seq Scan on tbl1 (actual rows=5 loops=1) - -> Append (actual rows=1 loops=5) + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop (actual rows=3.00 loops=1) + -> Seq Scan on tbl1 (actual rows=5.00 loops=1) + -> Append (actual rows=0.60 loops=5) -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) - -> Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2) + Index Searches: 0 + -> Index Scan using tprt2_idx on tprt_2 (actual rows=1.00 loops=2) Index Cond: (col1 = tbl1.col1) - -> Index Scan using tprt3_idx on tprt_3 (actual rows=0 loops=3) + Index Searches: 2 + -> Index Scan using tprt3_idx on tprt_3 (actual rows=0.33 loops=3) Index Cond: (col1 = tbl1.col1) + Index Searches: 3 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Index Searches: 0 +(21 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 > tprt.col1 @@ -3103,26 +3181,32 @@ order by tbl1.col1, tprt.col1; -- Last partition delete from tbl1; insert into tbl1 values (4400); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 < tprt.col1; - QUERY PLAN --------------------------------------------------------------------------- - Nested Loop (actual rows=1 loops=1) - -> Seq Scan on tbl1 (actual rows=1 loops=1) - -> Append (actual rows=1 loops=1) + QUERY PLAN +----------------------------------------------------------------------------- + Nested Loop (actual rows=1.00 loops=1) + -> Seq Scan on tbl1 (actual rows=1.00 loops=1) + -> Append (actual rows=1.00 loops=1) -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 > tbl1.col1) + Index Searches: 0 -> Index Scan using tprt2_idx on tprt_2 (never executed) Index Cond: (col1 > tbl1.col1) + Index Searches: 0 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 > tbl1.col1) + Index Searches: 0 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 > tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 > tbl1.col1) - -> Index Scan using tprt6_idx on tprt_6 (actual rows=1 loops=1) + Index Searches: 0 + -> Index Scan using tprt6_idx on tprt_6 (actual rows=1.00 loops=1) Index Cond: (col1 > tbl1.col1) -(15 rows) + Index Searches: 1 +(21 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 < tprt.col1 @@ -3135,26 +3219,32 @@ order by tbl1.col1, tprt.col1; -- No matching partition delete from tbl1; insert into tbl1 values (10000); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; QUERY PLAN ------------------------------------------------------------------- - Nested Loop (actual rows=0 loops=1) - -> Seq Scan on tbl1 (actual rows=1 loops=1) - -> Append (actual rows=0 loops=1) + Nested Loop (actual rows=0.00 loops=1) + -> Seq Scan on tbl1 (actual rows=1.00 loops=1) + -> Append (actual rows=0.00 loops=1) -> Index Scan using tprt1_idx on tprt_1 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt2_idx on tprt_2 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt3_idx on tprt_3 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt4_idx on tprt_4 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt5_idx on tprt_5 (never executed) Index Cond: (col1 = tbl1.col1) + Index Searches: 0 -> Index Scan using tprt6_idx on tprt_6 (never executed) Index Cond: (col1 = tbl1.col1) -(15 rows) + Index Searches: 0 +(21 rows) select tbl1.col1, tprt.col1 from tbl1 inner join tprt on tbl1.col1 = tprt.col1 @@ -3175,10 +3265,10 @@ alter table part_cab attach partition part_abc_p1 for values in(3); prepare part_abc_q1 (int, int, int) as select * from part_abc where a = $1 and b = $2 and c = $3; -- Single partition should be scanned. -explain (analyze, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); - QUERY PLAN ----------------------------------------------------------- - Seq Scan on part_abc_p1 part_abc (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute part_abc_q1 (1, 2, 3); + QUERY PLAN +------------------------------------------------------------- + Seq Scan on part_abc_p1 part_abc (actual rows=0.00 loops=1) Filter: ((a = $1) AND (b = $2) AND (c = $3)) (2 rows) @@ -3200,29 +3290,29 @@ select * from listp where b = 1; -- partitions before finally detecting the correct set of 2nd level partitions -- which match the given parameter. prepare q1 (int,int) as select * from listp where b in ($1,$2); -explain (analyze, costs off, summary off, timing off) execute q1 (1,1); - QUERY PLAN -------------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,1); + QUERY PLAN +---------------------------------------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 1 - -> Seq Scan on listp_1_1 listp_1 (actual rows=0 loops=1) + -> Seq Scan on listp_1_1 listp_1 (actual rows=0.00 loops=1) Filter: (b = ANY (ARRAY[$1, $2])) (4 rows) -explain (analyze, costs off, summary off, timing off) execute q1 (2,2); - QUERY PLAN -------------------------------------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (2,2); + QUERY PLAN +---------------------------------------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 1 - -> Seq Scan on listp_2_1 listp_1 (actual rows=0 loops=1) + -> Seq Scan on listp_2_1 listp_1 (actual rows=0.00 loops=1) Filter: (b = ANY (ARRAY[$1, $2])) (4 rows) -- Try with no matching partitions. -explain (analyze, costs off, summary off, timing off) execute q1 (0,0); - QUERY PLAN --------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (0,0); + QUERY PLAN +----------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 2 (2 rows) @@ -3230,31 +3320,31 @@ deallocate q1; -- Test more complex cases where a not-equal condition further eliminates partitions. prepare q1 (int,int,int,int) as select * from listp where b in($1,$2) and $3 <> b and $4 <> b; -- Both partitions allowed by IN clause, but one disallowed by <> clause -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,0); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,2,2,0); QUERY PLAN ------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 1 - -> Seq Scan on listp_1_1 listp_1 (actual rows=0 loops=1) + -> Seq Scan on listp_1_1 listp_1 (actual rows=0.00 loops=1) Filter: ((b = ANY (ARRAY[$1, $2])) AND ($3 <> b) AND ($4 <> b)) (4 rows) -- Both partitions allowed by IN clause, then both excluded again by <> clauses. -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1); - QUERY PLAN --------------------------------- - Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,2,2,1); + QUERY PLAN +----------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 2 (2 rows) -- Ensure Params that evaluate to NULL properly prune away all partitions -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from listp where a = (select null::int); QUERY PLAN ------------------------------------------------------ - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Result (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) -> Seq Scan on listp_1_1 listp_1 (never executed) Filter: (a = (InitPlan 1).col1) -> Seq Scan on listp_2_1 listp_2 (never executed) @@ -3273,90 +3363,90 @@ create table stable_qual_pruning2 partition of stable_qual_pruning create table stable_qual_pruning3 partition of stable_qual_pruning for values from ('3000-02-01') to ('3000-03-01'); -- comparison against a stable value requires run-time pruning -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a < localtimestamp; - QUERY PLAN --------------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +----------------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 1 - -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0.00 loops=1) Filter: (a < LOCALTIMESTAMP) - -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_2 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_2 (actual rows=0.00 loops=1) Filter: (a < LOCALTIMESTAMP) (6 rows) -- timestamp < timestamptz comparison is only stable, not immutable -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a < '2000-02-01'::timestamptz; - QUERY PLAN --------------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +----------------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 2 - -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0.00 loops=1) Filter: (a < 'Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone) (4 rows) -- check ScalarArrayOp cases -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2010-02-01', '2020-01-01']::timestamp[]); - QUERY PLAN --------------------------------- - Result (actual rows=0 loops=1) + QUERY PLAN +----------------------------------- + Result (actual rows=0.00 loops=1) One-Time Filter: false (2 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', '2010-01-01']::timestamp[]); QUERY PLAN ---------------------------------------------------------------------------------------------------------------- - Seq Scan on stable_qual_pruning2 stable_qual_pruning (actual rows=0 loops=1) + Seq Scan on stable_qual_pruning2 stable_qual_pruning (actual rows=0.00 loops=1) Filter: (a = ANY ('{"Tue Feb 01 00:00:00 2000","Fri Jan 01 00:00:00 2010"}'::timestamp without time zone[])) (2 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', localtimestamp]::timestamp[]); QUERY PLAN ------------------------------------------------------------------------------------------------------------ - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 2 - -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_1 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_1 (actual rows=0.00 loops=1) Filter: (a = ANY (ARRAY['Tue Feb 01 00:00:00 2000'::timestamp without time zone, LOCALTIMESTAMP])) (4 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2010-02-01', '2020-01-01']::timestamptz[]); - QUERY PLAN --------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +----------------------------------- + Append (actual rows=0.00 loops=1) Subplans Removed: 3 (2 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', '2010-01-01']::timestamptz[]); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + Append (actual rows=0.00 loops=1) Subplans Removed: 2 - -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_1 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_1 (actual rows=0.00 loops=1) Filter: (a = ANY ('{"Tue Feb 01 00:00:00 2000 PST","Fri Jan 01 00:00:00 2010 PST"}'::timestamp with time zone[])) (4 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(null::timestamptz[]); - QUERY PLAN --------------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) - -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0 loops=1) + QUERY PLAN +----------------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) + -> Seq Scan on stable_qual_pruning1 stable_qual_pruning_1 (actual rows=0.00 loops=1) Filter: (a = ANY (NULL::timestamp with time zone[])) - -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_2 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning2 stable_qual_pruning_2 (actual rows=0.00 loops=1) Filter: (a = ANY (NULL::timestamp with time zone[])) - -> Seq Scan on stable_qual_pruning3 stable_qual_pruning_3 (actual rows=0 loops=1) + -> Seq Scan on stable_qual_pruning3 stable_qual_pruning_3 (actual rows=0.00 loops=1) Filter: (a = ANY (NULL::timestamp with time zone[])) (7 rows) @@ -3374,16 +3464,16 @@ create table mc3p1 partition of mc3p create table mc3p2 partition of mc3p for values from (2, minvalue, minvalue) to (3, maxvalue, maxvalue); insert into mc3p values (0, 1, 1), (1, 1, 1), (2, 1, 1); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from mc3p where a < 3 and abs(b) = 1; - QUERY PLAN --------------------------------------------------------- - Append (actual rows=3 loops=1) - -> Seq Scan on mc3p0 mc3p_1 (actual rows=1 loops=1) + QUERY PLAN +----------------------------------------------------------- + Append (actual rows=3.00 loops=1) + -> Seq Scan on mc3p0 mc3p_1 (actual rows=1.00 loops=1) Filter: ((a < 3) AND (abs(b) = 1)) - -> Seq Scan on mc3p1 mc3p_2 (actual rows=1 loops=1) + -> Seq Scan on mc3p1 mc3p_2 (actual rows=1.00 loops=1) Filter: ((a < 3) AND (abs(b) = 1)) - -> Seq Scan on mc3p2 mc3p_3 (actual rows=1 loops=1) + -> Seq Scan on mc3p2 mc3p_3 (actual rows=1.00 loops=1) Filter: ((a < 3) AND (abs(b) = 1)) (7 rows) @@ -3394,32 +3484,32 @@ select * from mc3p where a < 3 and abs(b) = 1; -- prepare ps1 as select * from mc3p where a = $1 and abs(b) < (select 3); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) execute ps1(1); QUERY PLAN ------------------------------------------------------------- - Append (actual rows=1 loops=1) + Append (actual rows=1.00 loops=1) Subplans Removed: 2 InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Seq Scan on mc3p1 mc3p_1 (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Seq Scan on mc3p1 mc3p_1 (actual rows=1.00 loops=1) Filter: ((a = $1) AND (abs(b) < (InitPlan 1).col1)) (6 rows) deallocate ps1; prepare ps2 as select * from mc3p where a <= $1 and abs(b) < (select 3); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) execute ps2(1); QUERY PLAN -------------------------------------------------------------- - Append (actual rows=2 loops=1) + Append (actual rows=2.00 loops=1) Subplans Removed: 1 InitPlan 1 - -> Result (actual rows=1 loops=1) - -> Seq Scan on mc3p0 mc3p_1 (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Seq Scan on mc3p0 mc3p_1 (actual rows=1.00 loops=1) Filter: ((a <= $1) AND (abs(b) < (InitPlan 1).col1)) - -> Seq Scan on mc3p1 mc3p_2 (actual rows=1 loops=1) + -> Seq Scan on mc3p1 mc3p_2 (actual rows=1.00 loops=1) Filter: ((a <= $1) AND (abs(b) < (InitPlan 1).col1)) (8 rows) @@ -3431,31 +3521,31 @@ insert into boolvalues values('t'),('f'); create table boolp (a bool) partition by list (a); create table boolp_t partition of boolp for values in('t'); create table boolp_f partition of boolp for values in('f'); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from boolp where a = (select value from boolvalues where value); - QUERY PLAN ------------------------------------------------------------ - Append (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Seq Scan on boolvalues (actual rows=1 loops=1) + -> Seq Scan on boolvalues (actual rows=1.00 loops=1) Filter: value Rows Removed by Filter: 1 -> Seq Scan on boolp_f boolp_1 (never executed) Filter: (a = (InitPlan 1).col1) - -> Seq Scan on boolp_t boolp_2 (actual rows=0 loops=1) + -> Seq Scan on boolp_t boolp_2 (actual rows=0.00 loops=1) Filter: (a = (InitPlan 1).col1) (9 rows) -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from boolp where a = (select value from boolvalues where not value); - QUERY PLAN ------------------------------------------------------------ - Append (actual rows=0 loops=1) + QUERY PLAN +-------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Seq Scan on boolvalues (actual rows=1 loops=1) + -> Seq Scan on boolvalues (actual rows=1.00 loops=1) Filter: (NOT value) Rows Removed by Filter: 1 - -> Seq Scan on boolp_f boolp_1 (actual rows=0 loops=1) + -> Seq Scan on boolp_f boolp_1 (actual rows=0.00 loops=1) Filter: (a = (InitPlan 1).col1) -> Seq Scan on boolp_t boolp_2 (never executed) Filter: (a = (InitPlan 1).col1) @@ -3475,19 +3565,21 @@ insert into ma_test select x,x from generate_series(0,29) t(x); create index on ma_test (b); analyze ma_test; prepare mt_q1 (int) as select a from ma_test where a >= $1 and a % 10 = 5 order by b; -explain (analyze, costs off, summary off, timing off) execute mt_q1(15); - QUERY PLAN ------------------------------------------------------------------------------------------ - Merge Append (actual rows=2 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(15); + QUERY PLAN +-------------------------------------------------------------------------------------------- + Merge Append (actual rows=2.00 loops=1) Sort Key: ma_test.b Subplans Removed: 1 - -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_1 (actual rows=1 loops=1) + -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_1 (actual rows=1.00 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 - -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_2 (actual rows=1 loops=1) + Index Searches: 1 + -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_2 (actual rows=1.00 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 -(9 rows) + Index Searches: 1 +(11 rows) execute mt_q1(15); a @@ -3496,16 +3588,17 @@ execute mt_q1(15); 25 (2 rows) -explain (analyze, costs off, summary off, timing off) execute mt_q1(25); - QUERY PLAN ------------------------------------------------------------------------------------------ - Merge Append (actual rows=1 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(25); + QUERY PLAN +-------------------------------------------------------------------------------------------- + Merge Append (actual rows=1.00 loops=1) Sort Key: ma_test.b Subplans Removed: 2 - -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_1 (actual rows=1 loops=1) + -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_1 (actual rows=1.00 loops=1) Filter: ((a >= $1) AND ((a % 10) = 5)) Rows Removed by Filter: 9 -(6 rows) + Index Searches: 1 +(7 rows) execute mt_q1(25); a @@ -3514,10 +3607,10 @@ execute mt_q1(25); (1 row) -- Ensure MergeAppend behaves correctly when no subplans match -explain (analyze, costs off, summary off, timing off) execute mt_q1(35); - QUERY PLAN --------------------------------------- - Merge Append (actual rows=0 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(35); + QUERY PLAN +----------------------------------------- + Merge Append (actual rows=0.00 loops=1) Sort Key: ma_test.b Subplans Removed: 3 (3 rows) @@ -3530,36 +3623,40 @@ execute mt_q1(35); deallocate mt_q1; prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1; -- Ensure output list looks sane when the MergeAppend has no subplans. -explain (analyze, verbose, costs off, summary off, timing off) execute mt_q2 (35); - QUERY PLAN --------------------------------------------- - Limit (actual rows=0 loops=1) +explain (analyze, verbose, costs off, summary off, timing off, buffers off) execute mt_q2 (35); + QUERY PLAN +----------------------------------------------- + Limit (actual rows=0.00 loops=1) Output: ma_test.a, ma_test.b - -> Merge Append (actual rows=0 loops=1) + -> Merge Append (actual rows=0.00 loops=1) Sort Key: ma_test.b Subplans Removed: 3 (5 rows) deallocate mt_q2; -- ensure initplan params properly prune partitions -explain (analyze, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; - QUERY PLAN ------------------------------------------------------------------------------------------------ - Merge Append (actual rows=20 loops=1) +explain (analyze, costs off, summary off, timing off, buffers off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; + QUERY PLAN +-------------------------------------------------------------------------------------------------- + Merge Append (actual rows=20.00 loops=1) Sort Key: ma_test.b InitPlan 2 - -> Result (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) InitPlan 1 - -> Limit (actual rows=1 loops=1) - -> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1 loops=1) + -> Limit (actual rows=1.00 loops=1) + -> Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1.00 loops=1) Index Cond: (b IS NOT NULL) + Index Searches: 1 -> Index Scan using ma_test_p1_b_idx on ma_test_p1 ma_test_1 (never executed) Filter: (a >= (InitPlan 2).col1) - -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_2 (actual rows=10 loops=1) + Index Searches: 0 + -> Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_2 (actual rows=10.00 loops=1) Filter: (a >= (InitPlan 2).col1) - -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_3 (actual rows=10 loops=1) + Index Searches: 1 + -> Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_3 (actual rows=10.00 loops=1) Filter: (a >= (InitPlan 2).col1) -(14 rows) + Index Searches: 1 +(18 rows) reset enable_seqscan; reset enable_sort; @@ -3992,11 +4089,11 @@ create table listp (a int, b int) partition by list (a); create table listp1 partition of listp for values in(1); create table listp2 partition of listp for values in(2) partition by list(b); create table listp2_10 partition of listp2 for values in (10); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from listp where a = (select 2) and b <> 10; - QUERY PLAN ---------------------------------------------------- - Seq Scan on listp1 listp (actual rows=0 loops=1) + QUERY PLAN +----------------------------------------------------- + Seq Scan on listp1 listp (actual rows=0.00 loops=1) Filter: ((b <> 10) AND (a = (InitPlan 1).col1)) InitPlan 1 -> Result (never executed) @@ -4117,26 +4214,30 @@ create table rangep_0_to_100_3 partition of rangep_0_to_100 for values in(3); create table rangep_100_to_200 partition of rangep for values from (100) to (200); create index on rangep (a); -- Ensure run-time pruning works on the nested Merge Append -explain (analyze on, costs off, timing off, summary off) +explain (analyze on, costs off, timing off, summary off, buffers off) select * from rangep where b IN((select 1),(select 2)) order by a; - QUERY PLAN ------------------------------------------------------------------------------------------------------------- - Append (actual rows=0 loops=1) + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Append (actual rows=0.00 loops=1) InitPlan 1 - -> Result (actual rows=1 loops=1) + -> Result (actual rows=1.00 loops=1) InitPlan 2 - -> Result (actual rows=1 loops=1) - -> Merge Append (actual rows=0 loops=1) + -> Result (actual rows=1.00 loops=1) + -> Merge Append (actual rows=0.00 loops=1) Sort Key: rangep_2.a - -> Index Scan using rangep_0_to_100_1_a_idx on rangep_0_to_100_1 rangep_2 (actual rows=0 loops=1) + -> Index Scan using rangep_0_to_100_1_a_idx on rangep_0_to_100_1 rangep_2 (actual rows=0.00 loops=1) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1])) - -> Index Scan using rangep_0_to_100_2_a_idx on rangep_0_to_100_2 rangep_3 (actual rows=0 loops=1) + Index Searches: 1 + -> Index Scan using rangep_0_to_100_2_a_idx on rangep_0_to_100_2 rangep_3 (actual rows=0.00 loops=1) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1])) + Index Searches: 1 -> Index Scan using rangep_0_to_100_3_a_idx on rangep_0_to_100_3 rangep_4 (never executed) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1])) - -> Index Scan using rangep_100_to_200_a_idx on rangep_100_to_200 rangep_5 (actual rows=0 loops=1) + Index Searches: 0 + -> Index Scan using rangep_100_to_200_a_idx on rangep_100_to_200 rangep_5 (actual rows=0.00 loops=1) Filter: (b = ANY (ARRAY[(InitPlan 1).col1, (InitPlan 2).col1])) -(15 rows) + Index Searches: 1 +(19 rows) reset enable_sort; drop table rangep; @@ -4440,3 +4541,263 @@ drop table hp_contradict_test; drop operator class part_test_int4_ops2 using hash; drop operator ===(int4, int4); drop function explain_analyze(text); +-- Runtime pruning on UPDATE using WITH CHECK OPTIONS and RETURNING +create table part_abc (a int, b text, c bool) partition by list (a); +create table part_abc_1 (b text, a int, c bool); +create table part_abc_2 (a int, c bool, b text); +alter table part_abc attach partition part_abc_1 for values in (1); +alter table part_abc attach partition part_abc_2 for values in (2); +insert into part_abc values (1, 'b', true); +insert into part_abc values (2, 'c', true); +create view part_abc_view as select * from part_abc where b <> 'a' with check option; +prepare update_part_abc_view as update part_abc_view set b = $2 where a = $1 returning *; +-- Only the unpruned partition should be shown in the list of relations to be +-- updated +explain (verbose, costs off) execute update_part_abc_view (1, 'd'); + QUERY PLAN +----------------------------------------------------------------------------- + Update on public.part_abc + Output: part_abc_1.a, part_abc_1.b, part_abc_1.c + Update on public.part_abc_1 + -> Append + Subplans Removed: 1 + -> Seq Scan on public.part_abc_1 + Output: $2, part_abc_1.tableoid, part_abc_1.ctid + Filter: ((part_abc_1.b <> 'a'::text) AND (part_abc_1.a = $1)) +(8 rows) + +execute update_part_abc_view (1, 'd'); + a | b | c +---+---+--- + 1 | d | t +(1 row) + +explain (verbose, costs off) execute update_part_abc_view (2, 'a'); + QUERY PLAN +----------------------------------------------------------------------------- + Update on public.part_abc + Output: part_abc_1.a, part_abc_1.b, part_abc_1.c + Update on public.part_abc_2 + -> Append + Subplans Removed: 1 + -> Seq Scan on public.part_abc_2 + Output: $2, part_abc_2.tableoid, part_abc_2.ctid + Filter: ((part_abc_2.b <> 'a'::text) AND (part_abc_2.a = $1)) +(8 rows) + +execute update_part_abc_view (2, 'a'); +ERROR: new row violates check option for view "part_abc_view" +DETAIL: Failing row contains (2, a, t). +-- All pruned. +explain (verbose, costs off) execute update_part_abc_view (3, 'a'); + QUERY PLAN +---------------------------------------------------- + Update on public.part_abc + Output: part_abc_1.a, part_abc_1.b, part_abc_1.c + -> Append + Subplans Removed: 2 +(4 rows) + +execute update_part_abc_view (3, 'a'); + a | b | c +---+---+--- +(0 rows) + +deallocate update_part_abc_view; +-- Runtime pruning on MERGE using a stable function +create function stable_one() returns int as $$ begin return 1; end; $$ language plpgsql stable; +explain (costs off) +merge into part_abc_view pt +using (select stable_one() as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; + QUERY PLAN +----------------------------------------------------------------------- + Merge on part_abc + Merge on part_abc_1 + -> Nested Loop + -> Append + Subplans Removed: 1 + -> Seq Scan on part_abc_1 + Filter: ((b <> 'a'::text) AND (a = stable_one())) + -> Materialize + -> Seq Scan on part_abc_1 pt1 + Filter: (a = stable_one()) +(10 rows) + +merge into part_abc_view pt +using (select stable_one() as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; + a +--- + 1 +(1 row) + +table part_abc_view; + a | b | c +---+---+--- + 2 | c | t +(1 row) + +-- All pruned. +explain (costs off) +merge into part_abc_view pt +using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; + QUERY PLAN +------------------------------------------------------ + Merge on part_abc + -> Nested Loop + -> Append + Subplans Removed: 2 + -> Materialize + -> Seq Scan on part_abc_1 pt1 + Filter: (a = (stable_one() + 2)) +(7 rows) + +merge into part_abc_view pt +using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; + a +--- +(0 rows) + +table part_abc_view; + a | b | c +---+---+--- + 2 | c | t +(1 row) + +-- MERGE ... INSERT when all pruned from MERGE source. +begin; +explain (costs off) +merge into part_abc_view pt +using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 +when not matched then insert values (1, 'd', false) returning pt.a; + QUERY PLAN +------------------------------------------------ + Merge on part_abc + -> Nested Loop Left Join + -> Seq Scan on part_abc_2 pt2 + Filter: ((stable_one() + 1) = a) + -> Materialize + -> Append + Subplans Removed: 2 +(7 rows) + +merge into part_abc_view pt +using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 +when not matched then insert values (1, 'd', false) returning pt.a; + a +--- + 1 +(1 row) + +table part_abc_view; + a | b | c +---+---+--- + 1 | d | f + 2 | c | t +(2 rows) + +rollback; +-- A case with multiple ModifyTable nodes. +begin; +create table part_abc_log (action text, a int, b text, c bool); +explain (costs off) +with t as ( + merge into part_abc_view pt + using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 + when not matched then insert values (1, 'd', false) returning merge_action(), pt.* +) +insert into part_abc_log select * from t returning *; + QUERY PLAN +-------------------------------------------------------- + Insert on part_abc_log + CTE t + -> Merge on part_abc + -> Nested Loop Left Join + -> Seq Scan on part_abc_2 pt2 + Filter: ((stable_one() + 1) = a) + -> Materialize + -> Append + Subplans Removed: 2 + -> CTE Scan on t +(10 rows) + +with t as ( + merge into part_abc_view pt + using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 + when not matched then insert values (1, 'd', false) returning merge_action(), pt.* +) +insert into part_abc_log select * from t returning *; + action | a | b | c +--------+---+---+--- + INSERT | 1 | d | f +(1 row) + +table part_abc_view; + a | b | c +---+---+--- + 1 | d | f + 2 | c | t +(2 rows) + +table part_abc_log; + action | a | b | c +--------+---+---+--- + INSERT | 1 | d | f +(1 row) + +rollback; +-- A case with nested MergeAppend with its own PartitionPruneInfo. +create index on part_abc (a); +alter table part_abc add d int; +create table part_abc_3 partition of part_abc for values in (3, 4) partition by range (d); +create table part_abc_3_1 partition of part_abc_3 for values from (minvalue) to (1); +create table part_abc_3_2 partition of part_abc_3 for values from (1) to (100); +create table part_abc_3_3 partition of part_abc_3 for values from (100) to (maxvalue); +explain (costs off) +select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d <= stable_one() +union all +select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d >= stable_one(); + QUERY PLAN +---------------------------------------------------------------------------------------------- + Append + -> Subquery Scan on "*SELECT* 1_1" + -> WindowAgg + Window: w1 AS (PARTITION BY part_abc.a ORDER BY part_abc.a) + -> Append + Subplans Removed: 1 + -> Index Scan using part_abc_2_a_idx on part_abc_2 part_abc_1 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d <= stable_one()) + -> Merge Append + Sort Key: part_abc_3.a + Subplans Removed: 1 + -> Index Scan using part_abc_3_1_a_idx on part_abc_3_1 part_abc_3 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d <= stable_one()) + -> Index Scan using part_abc_3_2_a_idx on part_abc_3_2 part_abc_4 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d <= stable_one()) + -> Subquery Scan on "*SELECT* 2" + -> WindowAgg + Window: w1 AS (PARTITION BY part_abc_5.a ORDER BY part_abc_5.a) + -> Append + Subplans Removed: 1 + -> Index Scan using part_abc_2_a_idx on part_abc_2 part_abc_6 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d >= stable_one()) + -> Merge Append + Sort Key: a + Subplans Removed: 1 + -> Index Scan using part_abc_3_2_a_idx on part_abc_3_2 part_abc_8 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d >= stable_one()) + -> Index Scan using part_abc_3_3_a_idx on part_abc_3_3 part_abc_9 + Index Cond: (a >= (stable_one() + 1)) + Filter: (d >= stable_one()) +(35 rows) + +drop view part_abc_view; +drop table part_abc; diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out deleted file mode 100644 index dc9a5130cccb9..0000000000000 --- a/src/test/regress/expected/partition_split.out +++ /dev/null @@ -1,1589 +0,0 @@ --- --- PARTITION_SPLIT --- Tests for "ALTER TABLE ... SPLIT PARTITION ..." command --- -CREATE SCHEMA partition_split_schema; -CREATE SCHEMA partition_split_schema2; -SET search_path = partition_split_schema, public; --- --- BY RANGE partitioning --- --- --- Test for error codes --- -CREATE TABLE sales_range (salesperson_id int, salesperson_name varchar(30), sales_amount int, sales_date date) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; --- ERROR: relation "sales_xxx" does not exist -ALTER TABLE sales_range SPLIT PARTITION sales_xxx INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: relation "sales_xxx" does not exist --- ERROR: relation "sales_jan2022" already exists -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: relation "sales_jan2022" already exists --- ERROR: invalid bound specification for a range partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES IN ('2022-05-01', '2022-06-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: invalid bound specification for a range partition -LINE 2: (PARTITION sales_jan2022 FOR VALUES IN ('2022-05-01', '202... - ^ --- ERROR: empty range bound specified for partition "sales_mar2022" -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-02-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: empty range bound specified for partition "sales_mar2022" -LINE 3: PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO... - ^ -DETAIL: Specified lower bound ('03-01-2022') is greater than or equal to upper bound ('02-01-2022'). ---ERROR: list of split partitions should contain at least two items -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-10-01')); -ERROR: list of new partitions should contain at least two items --- ERROR: lower bound of partition "sales_feb2022" is less than lower bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-01-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: lower bound of partition "sales_feb2022" is less than lower bound of split partition -LINE 2: (PARTITION sales_feb2022 FOR VALUES FROM ('2022-01-01') TO... - ^ --- ERROR: name "sales_feb_mar_apr2022" is already used --- (We can create partition with the same name as split partition, but can't create two partitions with the same name) -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb_mar_apr2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb_mar_apr2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: name "sales_feb_mar_apr2022" is already used -LINE 3: PARTITION sales_feb_mar_apr2022 FOR VALUES FROM ('2022-03... - ^ --- ERROR: name "sales_feb2022" is already used -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: name "sales_feb2022" is already used -LINE 3: PARTITION sales_feb2022 FOR VALUES FROM ('2022-03-01') TO... - ^ --- ERROR: "sales_feb_mar_apr2022" is not a partitioned table -ALTER TABLE sales_feb_mar_apr2022 SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: "sales_feb_mar_apr2022" is not a partitioned table --- ERROR: upper bound of partition "sales_apr2022" is greater than upper bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-06-01')); -ERROR: upper bound of partition "sales_apr2022" is greater than upper bound of split partition -LINE 4: ... sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-06-0... - ^ --- ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_feb2022" -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_feb2022" -LINE 3: PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO... - ^ --- Tests for spaces between partitions, them should be executed without DEFAULT partition -ALTER TABLE sales_range DETACH PARTITION sales_others; --- ERROR: lower bound of partition "sales_feb2022" is not equal to lower bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-02') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -ERROR: lower bound of partition "sales_feb2022" is not equal to lower bound of split partition -LINE 2: (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-02') TO... - ^ --- Check the source partition not in the search path -SET search_path = partition_split_schema2, public; -ALTER TABLE partition_split_schema.sales_range -SPLIT PARTITION partition_split_schema.sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -SET search_path = partition_split_schema, public; -\d+ sales_range - Partitioned table "partition_split_schema.sales_range" - Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -------------------+-----------------------+-----------+----------+---------+----------+--------------+------------- - salesperson_id | integer | | | | plain | | - salesperson_name | character varying(30) | | | | extended | | - sales_amount | integer | | | | plain | | - sales_date | date | | | | plain | | -Partition key: RANGE (sales_date) -Partitions: partition_split_schema2.sales_apr2022 FOR VALUES FROM ('04-01-2022') TO ('05-01-2022'), - partition_split_schema2.sales_feb2022 FOR VALUES FROM ('02-01-2022') TO ('03-01-2022'), - partition_split_schema2.sales_mar2022 FOR VALUES FROM ('03-01-2022') TO ('04-01-2022'), - sales_jan2022 FOR VALUES FROM ('01-01-2022') TO ('02-01-2022') - -DROP TABLE sales_range; -DROP TABLE sales_others; --- --- Add rows into partitioned table then split partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_jan2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 -(3 rows) - -SELECT * FROM sales_feb2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 -(3 rows) - -SELECT * FROM sales_mar2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 -(3 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(4 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 14 | Smith | 510 | 05-04-2022 -(1 row) - -DROP TABLE sales_range CASCADE; --- --- Add split partition, then add rows into partitioned table --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; --- Split partition, also check schema qualification of new partitions -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION partition_split_schema.sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION partition_split_schema2.sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -\d+ sales_range - Partitioned table "partition_split_schema.sales_range" - Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -------------------+-----------------------+-----------+----------+---------+----------+--------------+------------- - salesperson_id | integer | | | | plain | | - salesperson_name | character varying(30) | | | | extended | | - sales_amount | integer | | | | plain | | - sales_date | date | | | | plain | | -Partition key: RANGE (sales_date) -Partitions: partition_split_schema2.sales_mar2022 FOR VALUES FROM ('03-01-2022') TO ('04-01-2022'), - sales_apr2022 FOR VALUES FROM ('04-01-2022') TO ('05-01-2022'), - sales_feb2022 FOR VALUES FROM ('02-01-2022') TO ('03-01-2022'), - sales_jan2022 FOR VALUES FROM ('01-01-2022') TO ('02-01-2022'), - sales_others DEFAULT - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_jan2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 -(3 rows) - -SELECT * FROM sales_feb2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 -(3 rows) - -SELECT * FROM partition_split_schema2.sales_mar2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 -(3 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(4 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 14 | Smith | 510 | 05-04-2022 -(1 row) - -DROP TABLE sales_range CASCADE; --- --- Test for: --- * composite partition key; --- * GENERATED column; --- * column with DEFAULT value. --- -CREATE TABLE sales_date (salesperson_name VARCHAR(30), sales_year INT, sales_month INT, sales_day INT, - sales_date VARCHAR(10) GENERATED ALWAYS AS - (LPAD(sales_year::text, 4, '0') || '.' || LPAD(sales_month::text, 2, '0') || '.' || LPAD(sales_day::text, 2, '0')) STORED, - sales_department VARCHAR(30) DEFAULT 'Sales department') - PARTITION BY RANGE (sales_year, sales_month, sales_day); -CREATE TABLE sales_dec2022 PARTITION OF sales_date FOR VALUES FROM (2021, 12, 1) TO (2022, 1, 1); -CREATE TABLE sales_jan_feb2022 PARTITION OF sales_date FOR VALUES FROM (2022, 1, 1) TO (2022, 3, 1); -CREATE TABLE sales_other PARTITION OF sales_date FOR VALUES FROM (2022, 3, 1) TO (MAXVALUE, MAXVALUE, MAXVALUE); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2021, 12, 7); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2021, 12, 8); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 1, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 2, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 1, 2); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 2, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 3, 3); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 3, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 5, 1); -SELECT * FROM sales_date; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(9 rows) - -SELECT * FROM sales_dec2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department -(2 rows) - -SELECT * FROM sales_jan_feb2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department -(4 rows) - -SELECT * FROM sales_other; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(3 rows) - -ALTER TABLE sales_date SPLIT PARTITION sales_jan_feb2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM (2022, 1, 1) TO (2022, 2, 1), - PARTITION sales_feb2022 FOR VALUES FROM (2022, 2, 1) TO (2022, 3, 1)); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 1, 10); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 2, 10); -SELECT * FROM sales_date; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager1 | 2022 | 1 | 10 | 2022.01.10 | Sales department - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager2 | 2022 | 2 | 10 | 2022.02.10 | Sales department - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(11 rows) - -SELECT * FROM sales_dec2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2021 | 12 | 7 | 2021.12.07 | Sales department - Manager2 | 2021 | 12 | 8 | 2021.12.08 | Sales department -(2 rows) - -SELECT * FROM sales_jan2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager3 | 2022 | 1 | 1 | 2022.01.01 | Sales department - Manager2 | 2022 | 1 | 2 | 2022.01.02 | Sales department - Manager1 | 2022 | 1 | 10 | 2022.01.10 | Sales department -(3 rows) - -SELECT * FROM sales_feb2022; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 2 | 4 | 2022.02.04 | Sales department - Manager3 | 2022 | 2 | 1 | 2022.02.01 | Sales department - Manager2 | 2022 | 2 | 10 | 2022.02.10 | Sales department -(3 rows) - -SELECT * FROM sales_other; - salesperson_name | sales_year | sales_month | sales_day | sales_date | sales_department -------------------+------------+-------------+-----------+------------+------------------ - Manager1 | 2022 | 3 | 3 | 2022.03.03 | Sales department - Manager2 | 2022 | 3 | 4 | 2022.03.04 | Sales department - Manager3 | 2022 | 5 | 1 | 2022.05.01 | Sales department -(3 rows) - ---ERROR: relation "sales_jan_feb2022" does not exist -SELECT * FROM sales_jan_feb2022; -ERROR: relation "sales_jan_feb2022" does not exist -LINE 1: SELECT * FROM sales_jan_feb2022; - ^ -DROP TABLE sales_date CASCADE; --- --- Test: split DEFAULT partition; use an index on partition key; check index after split --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 6 | Poirot | 150 | 02-11-2022 - 7 | Li | 175 | 03-08-2022 - 8 | Ericsson | 185 | 02-23-2022 - 9 | Muller | 250 | 03-11-2022 - 11 | Trump | 380 | 04-06-2022 - 12 | Plato | 350 | 03-19-2022 - 14 | Smith | 510 | 05-04-2022 -(11 rows) - -SELECT * FROM pg_indexes WHERE tablename = 'sales_others' and schemaname = 'partition_split_schema' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------------------+--------------+-----------------------------+------------+---------------------------------------------------------------------------------------------------------- - partition_split_schema | sales_others | sales_others_sales_date_idx | | CREATE INDEX sales_others_sales_date_idx ON partition_split_schema.sales_others USING btree (sales_date) -(1 row) - -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'), - PARTITION sales_others DEFAULT); --- Use indexscan for testing indexes -SET enable_indexscan = ON; -SET enable_seqscan = OFF; -SELECT * FROM sales_feb2022 where sales_date > '2022-01-01'; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 -(3 rows) - -SELECT * FROM sales_mar2022 where sales_date > '2022-01-01'; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 -(3 rows) - -SELECT * FROM sales_apr2022 where sales_date > '2022-01-01'; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 11 | Trump | 380 | 04-06-2022 - 5 | Deev | 250 | 04-07-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(4 rows) - -SELECT * FROM sales_others where sales_date > '2022-01-01'; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 14 | Smith | 510 | 05-04-2022 -(1 row) - -SET enable_indexscan = ON; -SET enable_seqscan = ON; -SELECT * FROM pg_indexes WHERE tablename = 'sales_feb2022' and schemaname = 'partition_split_schema' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------------------+---------------+------------------------------+------------+------------------------------------------------------------------------------------------------------------ - partition_split_schema | sales_feb2022 | sales_feb2022_sales_date_idx | | CREATE INDEX sales_feb2022_sales_date_idx ON partition_split_schema.sales_feb2022 USING btree (sales_date) -(1 row) - -SELECT * FROM pg_indexes WHERE tablename = 'sales_mar2022' and schemaname = 'partition_split_schema' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------------------+---------------+------------------------------+------------+------------------------------------------------------------------------------------------------------------ - partition_split_schema | sales_mar2022 | sales_mar2022_sales_date_idx | | CREATE INDEX sales_mar2022_sales_date_idx ON partition_split_schema.sales_mar2022 USING btree (sales_date) -(1 row) - -SELECT * FROM pg_indexes WHERE tablename = 'sales_apr2022' and schemaname = 'partition_split_schema' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------------------+---------------+------------------------------+------------+------------------------------------------------------------------------------------------------------------ - partition_split_schema | sales_apr2022 | sales_apr2022_sales_date_idx | | CREATE INDEX sales_apr2022_sales_date_idx ON partition_split_schema.sales_apr2022 USING btree (sales_date) -(1 row) - -SELECT * FROM pg_indexes WHERE tablename = 'sales_others' and schemaname = 'partition_split_schema' ORDER BY indexname; - schemaname | tablename | indexname | tablespace | indexdef -------------------------+--------------+------------------------------+------------+----------------------------------------------------------------------------------------------------------- - partition_split_schema | sales_others | sales_others_sales_date_idx1 | | CREATE INDEX sales_others_sales_date_idx1 ON partition_split_schema.sales_others USING btree (sales_date) -(1 row) - -DROP TABLE sales_range CASCADE; --- --- Test: some cases for splitting DEFAULT partition (different bounds) --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date INT) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; --- sales_error intersects with sales_dec2022 (lower bound) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211230) TO (20220201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -LINE 3: PARTITION sales_error FOR VALUES FROM (20211230) TO (2022... - ^ --- sales_error intersects with sales_feb2022 (upper bound) --- ERROR: lower bound of partition "sales_feb2022" conflicts with upper bound of previous partition "sales_error" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20220101) TO (20220202), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -ERROR: lower bound of partition "sales_feb2022" conflicts with upper bound of previous partition "sales_error" -LINE 4: PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20... - ^ --- sales_error intersects with sales_dec2022 (inside bound) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211210) TO (20211220), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -LINE 3: PARTITION sales_error FOR VALUES FROM (20211210) TO (2021... - ^ --- sales_error intersects with sales_dec2022 (exactly the same bounds) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -LINE 3: PARTITION sales_error FOR VALUES FROM (20211201) TO (2022... - ^ --- ERROR: all partitions in the list should be DEFAULT because split partition is DEFAULT -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_jan2022 FOR VALUES FROM (20220101) TO (20220201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301)); -ERROR: one partition in the list should be DEFAULT because split partition is DEFAULT -LINE 2: (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20... - ^ --- no error: bounds of sales_noerror are between sales_dec2022 and sales_feb2022 -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_noerror FOR VALUES FROM (20220110) TO (20220120), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -DROP TABLE sales_range; -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date INT) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; --- no error: bounds of sales_noerror are equal to lower and upper bounds of sales_dec2022 and sales_feb2022 -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_noerror FOR VALUES FROM (20210101) TO (20210201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); -DROP TABLE sales_range; --- --- Test: split partition with CHECK and FOREIGN KEY CONSTRAINTs on partitioned table --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)); -INSERT INTO salespeople VALUES (1, 'Poirot'); -CREATE TABLE sales_range ( -salesperson_id INT REFERENCES salespeople(salesperson_id), -sales_amount INT CHECK (sales_amount > 1), -sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_feb_mar_apr2022'::regclass::oid ORDER BY conname; - pg_get_constraintdef | conname | conkey ----------------------------------------------------------------------+---------------------------------+-------- - CHECK ((sales_amount > 1)) | sales_range_sales_amount_check | {2} - FOREIGN KEY (salesperson_id) REFERENCES salespeople(salesperson_id) | sales_range_salesperson_id_fkey | {1} -(2 rows) - -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); --- We should see the same CONSTRAINTs as on sales_feb_mar_apr2022 partition -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_feb2022'::regclass::oid ORDER BY conname;; - pg_get_constraintdef | conname | conkey ----------------------------------------------------------------------+---------------------------------+-------- - CHECK ((sales_amount > 1)) | sales_range_sales_amount_check | {2} - FOREIGN KEY (salesperson_id) REFERENCES salespeople(salesperson_id) | sales_range_salesperson_id_fkey | {1} -(2 rows) - -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_mar2022'::regclass::oid ORDER BY conname;; - pg_get_constraintdef | conname | conkey ----------------------------------------------------------------------+---------------------------------+-------- - CHECK ((sales_amount > 1)) | sales_range_sales_amount_check | {2} - FOREIGN KEY (salesperson_id) REFERENCES salespeople(salesperson_id) | sales_range_salesperson_id_fkey | {1} -(2 rows) - -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_apr2022'::regclass::oid ORDER BY conname;; - pg_get_constraintdef | conname | conkey ----------------------------------------------------------------------+---------------------------------+-------- - CHECK ((sales_amount > 1)) | sales_range_sales_amount_check | {2} - FOREIGN KEY (salesperson_id) REFERENCES salespeople(salesperson_id) | sales_range_salesperson_id_fkey | {1} -(2 rows) - --- ERROR: new row for relation "sales_mar2022" violates check constraint "sales_range_sales_amount_check" -INSERT INTO sales_range VALUES (1, 0, '2022-03-11'); -ERROR: new row for relation "sales_mar2022" violates check constraint "sales_range_sales_amount_check" -DETAIL: Failing row contains (1, 0, 03-11-2022). --- ERROR: insert or update on table "sales_mar2022" violates foreign key constraint "sales_range_salesperson_id_fkey" -INSERT INTO sales_range VALUES (-1, 10, '2022-03-11'); -ERROR: insert or update on table "sales_mar2022" violates foreign key constraint "sales_range_salesperson_id_fkey" -DETAIL: Key (salesperson_id)=(-1) is not present in table "salespeople". --- ok -INSERT INTO sales_range VALUES (1, 10, '2022-03-11'); -DROP TABLE sales_range CASCADE; -DROP TABLE salespeople CASCADE; --- --- Test: split partition on partitioned table in case of existing FOREIGN KEY reference from another table --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE sales (salesperson_id INT REFERENCES salespeople(salesperson_id), sales_amount INT, sales_date DATE); -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_40 PARTITION OF salespeople FOR VALUES FROM (10) TO (40); -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (19, 'Ivanov'); -INSERT INTO salespeople VALUES (20, 'Smirnoff'); -INSERT INTO salespeople VALUES (30, 'Ford'); -INSERT INTO sales VALUES (1, 100, '2022-03-01'); -INSERT INTO sales VALUES (1, 110, '2022-03-02'); -INSERT INTO sales VALUES (10, 150, '2022-03-01'); -INSERT INTO sales VALUES (10, 90, '2022-03-03'); -INSERT INTO sales VALUES (19, 200, '2022-03-04'); -INSERT INTO sales VALUES (20, 50, '2022-03-12'); -INSERT INTO sales VALUES (20, 170, '2022-03-02'); -INSERT INTO sales VALUES (30, 30, '2022-03-04'); -SELECT * FROM salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -SELECT * FROM salespeople10_40; - salesperson_id | salesperson_name -----------------+------------------ - 10 | May - 19 | Ivanov - 20 | Smirnoff - 30 | Ford -(4 rows) - -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); -SELECT * FROM salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -SELECT * FROM salespeople10_20; - salesperson_id | salesperson_name -----------------+------------------ - 10 | May - 19 | Ivanov -(2 rows) - -SELECT * FROM salespeople20_30; - salesperson_id | salesperson_name -----------------+------------------ - 20 | Smirnoff -(1 row) - -SELECT * FROM salespeople30_40; - salesperson_id | salesperson_name -----------------+------------------ - 30 | Ford -(1 row) - --- ERROR: insert or update on table "sales" violates foreign key constraint "sales_salesperson_id_fkey" -INSERT INTO sales VALUES (40, 50, '2022-03-04'); -ERROR: insert or update on table "sales" violates foreign key constraint "sales_salesperson_id_fkey" -DETAIL: Key (salesperson_id)=(40) is not present in table "salespeople". --- ok -INSERT INTO sales VALUES (30, 50, '2022-03-04'); -DROP TABLE sales CASCADE; -DROP TABLE salespeople CASCADE; --- --- Test: split partition of partitioned table with triggers --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_40 PARTITION OF salespeople FOR VALUES FROM (10) TO (40); -INSERT INTO salespeople VALUES (1, 'Poirot'); -CREATE OR REPLACE FUNCTION after_insert_row_trigger() RETURNS trigger LANGUAGE 'plpgsql' AS $BODY$ -BEGIN - RAISE NOTICE 'trigger(%) called: action = %, when = %, level = %', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END; -$BODY$; -CREATE TRIGGER salespeople_after_insert_statement_trigger - AFTER INSERT - ON salespeople - FOR EACH STATEMENT - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); -CREATE TRIGGER salespeople_after_insert_row_trigger - AFTER INSERT - ON salespeople - FOR EACH ROW - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (10, 'May'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = STATEMENT --- 1 trigger should fire here (row): -INSERT INTO salespeople10_40 VALUES (19, 'Ivanov'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (20, 'Smirnoff'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = STATEMENT --- 1 trigger should fire here (row): -INSERT INTO salespeople30_40 VALUES (30, 'Ford'); -NOTICE: trigger(salespeople) called: action = INSERT, when = AFTER, level = ROW -SELECT * FROM salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -SELECT * FROM salespeople10_20; - salesperson_id | salesperson_name -----------------+------------------ - 10 | May - 19 | Ivanov -(2 rows) - -SELECT * FROM salespeople20_30; - salesperson_id | salesperson_name -----------------+------------------ - 20 | Smirnoff -(1 row) - -SELECT * FROM salespeople30_40; - salesperson_id | salesperson_name -----------------+------------------ - 30 | Ford -(1 row) - -DROP TABLE salespeople CASCADE; -DROP FUNCTION after_insert_row_trigger(); --- --- Test: split partition witch identity column --- If split partition column is identity column, columns of new partitions are identity columns too. --- -CREATE TABLE salespeople(salesperson_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE salespeople1_2 PARTITION OF salespeople FOR VALUES FROM (1) TO (2); --- Create new partition with identity column: -CREATE TABLE salespeople2_5(salesperson_id INT NOT NULL, salesperson_name VARCHAR(30)); -ALTER TABLE salespeople ATTACH PARTITION salespeople2_5 FOR VALUES FROM (2) TO (5); -INSERT INTO salespeople (salesperson_name) VALUES ('Poirot'); -INSERT INTO salespeople (salesperson_name) VALUES ('Ivanov'); -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople1_2'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - --- Split partition has identity column: -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople2_5'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -ALTER TABLE salespeople SPLIT PARTITION salespeople2_5 INTO - (PARTITION salespeople2_3 FOR VALUES FROM (2) TO (3), - PARTITION salespeople3_4 FOR VALUES FROM (3) TO (4), - PARTITION salespeople4_5 FOR VALUES FROM (4) TO (5)); -INSERT INTO salespeople (salesperson_name) VALUES ('May'); -INSERT INTO salespeople (salesperson_name) VALUES ('Ford'); -SELECT * FROM salespeople1_2; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -SELECT * FROM salespeople2_3; - salesperson_id | salesperson_name -----------------+------------------ - 2 | Ivanov -(1 row) - -SELECT * FROM salespeople3_4; - salesperson_id | salesperson_name -----------------+------------------ - 3 | May -(1 row) - -SELECT * FROM salespeople4_5; - salesperson_id | salesperson_name -----------------+------------------ - 4 | Ford -(1 row) - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople1_2'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - --- New partitions have identity-columns: -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople2_3'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople3_4'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople4_5'::regclass::oid ORDER BY attnum; - attname | attidentity | attgenerated -------------------+-------------+-------------- - salesperson_id | a | - salesperson_name | | -(2 rows) - -DROP TABLE salespeople CASCADE; --- --- Test: split partition with deleted columns --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); --- Create new partition with some deleted columns: -CREATE TABLE salespeople10_40(d1 VARCHAR(30), salesperson_id INT PRIMARY KEY, d2 INT, d3 DATE, salesperson_name VARCHAR(30)); -INSERT INTO salespeople10_40 VALUES ('dummy value 1', 19, 100, now(), 'Ivanov'); -INSERT INTO salespeople10_40 VALUES ('dummy value 2', 20, 101, now(), 'Smirnoff'); -ALTER TABLE salespeople10_40 DROP COLUMN d1; -ALTER TABLE salespeople10_40 DROP COLUMN d2; -ALTER TABLE salespeople10_40 DROP COLUMN d3; -ALTER TABLE salespeople ATTACH PARTITION salespeople10_40 FOR VALUES FROM (10) TO (40); -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (30, 'Ford'); -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); -select * from salespeople01_10; - salesperson_id | salesperson_name -----------------+------------------ - 1 | Poirot -(1 row) - -select * from salespeople10_20; - salesperson_id | salesperson_name -----------------+------------------ - 19 | Ivanov - 10 | May -(2 rows) - -select * from salespeople20_30; - salesperson_id | salesperson_name -----------------+------------------ - 20 | Smirnoff -(1 row) - -select * from salespeople30_40; - salesperson_id | salesperson_name -----------------+------------------ - 30 | Ford -(1 row) - -DROP TABLE salespeople CASCADE; --- --- Test: split sub-partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr_all PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(4 rows) - -ALTER TABLE sales_apr2022 SPLIT PARTITION sales_apr_all INTO - (PARTITION sales_apr2022_01_10 FOR VALUES FROM ('2022-04-01') TO ('2022-04-10'), - PARTITION sales_apr2022_10_20 FOR VALUES FROM ('2022-04-10') TO ('2022-04-20'), - PARTITION sales_apr2022_20_30 FOR VALUES FROM ('2022-04-20') TO ('2022-05-01')); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 4 | Ivanov | 750 | 04-13-2022 - 3 | Ford | 2000 | 04-30-2022 -(4 rows) - -SELECT * FROM sales_apr2022_01_10; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(2 rows) - -SELECT * FROM sales_apr2022_10_20; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 4 | Ivanov | 750 | 04-13-2022 -(1 row) - -SELECT * FROM sales_apr2022_20_30; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 -(1 row) - -DROP TABLE sales_range; --- --- BY LIST partitioning --- --- --- Test: specific errors for BY LIST partitioning --- -CREATE TABLE sales_list -(salesperson_id INT, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; --- ERROR: new partition "sales_east" would overlap with another (not split) partition "sales_nord" -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok', 'Helsinki'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); -ERROR: new partition "sales_east" would overlap with another (not split) partition "sales_nord" -LINE 3: ... FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok', 'Helsinki'... - ^ --- ERROR: new partition "sales_west" would overlap with another new partition "sales_central" -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Lisbon', 'Kyiv')); -ERROR: new partition "sales_west" would overlap with another new partition "sales_central" -LINE 2: (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York',... - ^ --- ERROR: new partition "sales_west" cannot have NULL value because split partition does not have -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid', NULL), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); -ERROR: new partition "sales_west" cannot have NULL value because split partition does not have -LINE 2: ...s_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid', NULL), - ^ -DROP TABLE sales_list; --- --- Test: two specific errors for BY LIST partitioning: --- * new partitions do not have NULL value, which split partition has. --- * new partitions do not have a value that split partition has. --- -CREATE TABLE sales_list -(salesperson_id INT, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Helsinki', 'St. Petersburg', 'Oslo'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok', NULL); --- ERROR: new partitions do not have value NULL but split partition does -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); -ERROR: new partitions do not have value NULL but split partition does --- ERROR: new partitions do not have value 'Kyiv' but split partition does -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', NULL)); -ERROR: new partitions do not have value 'Kyiv' but split partition does -DROP TABLE sales_list; --- --- Test: BY LIST partitioning, SPLIT PARTITION with data --- -CREATE TABLE sales_list -(salesperson_id SERIAL, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE INDEX sales_list_salesperson_name_idx ON sales_list USING btree (salesperson_name); -CREATE INDEX sales_list_sales_state_idx ON sales_list USING btree (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Helsinki', 'St. Petersburg', 'Oslo'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Trump', 'Bejing', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smirnoff', 'New York', 500, '2022-03-03'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ford', 'St. Petersburg', 2000, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ivanov', 'Warsaw', 750, '2022-03-04'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Deev', 'Lisbon', 250, '2022-03-07'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Poirot', 'Berlin', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Oslo', 1200, '2022-03-06'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Li', 'Vladivostok', 1150, '2022-03-09'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Oslo', 1200, '2022-03-11'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Halder', 'Helsinki', 800, '2022-03-02'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Muller', 'Madrid', 650, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smith', 'Kyiv', 350, '2022-03-10'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Gandi', 'Warsaw', 150, '2022-03-08'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Plato', 'Lisbon', 950, '2022-03-05'); -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); -SELECT * FROM sales_list; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+----------------+--------------+------------ - 1 | Trump | Bejing | 1000 | 03-01-2022 - 8 | Li | Vladivostok | 1150 | 03-09-2022 - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 6 | Poirot | Berlin | 1000 | 03-01-2022 - 12 | Smith | Kyiv | 350 | 03-10-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 - 3 | Ford | St. Petersburg | 2000 | 03-05-2022 - 7 | May | Oslo | 1200 | 03-06-2022 - 9 | May | Oslo | 1200 | 03-11-2022 - 10 | Halder | Helsinki | 800 | 03-02-2022 - 2 | Smirnoff | New York | 500 | 03-03-2022 - 5 | Deev | Lisbon | 250 | 03-07-2022 - 11 | Muller | Madrid | 650 | 03-05-2022 - 14 | Plato | Lisbon | 950 | 03-05-2022 -(14 rows) - -SELECT * FROM sales_west; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 2 | Smirnoff | New York | 500 | 03-03-2022 - 5 | Deev | Lisbon | 250 | 03-07-2022 - 11 | Muller | Madrid | 650 | 03-05-2022 - 14 | Plato | Lisbon | 950 | 03-05-2022 -(4 rows) - -SELECT * FROM sales_east; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 1 | Trump | Bejing | 1000 | 03-01-2022 - 8 | Li | Vladivostok | 1150 | 03-09-2022 -(2 rows) - -SELECT * FROM sales_nord; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+----------------+--------------+------------ - 3 | Ford | St. Petersburg | 2000 | 03-05-2022 - 7 | May | Oslo | 1200 | 03-06-2022 - 9 | May | Oslo | 1200 | 03-11-2022 - 10 | Halder | Helsinki | 800 | 03-02-2022 -(4 rows) - -SELECT * FROM sales_central; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 6 | Poirot | Berlin | 1000 | 03-01-2022 - 12 | Smith | Kyiv | 350 | 03-10-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(4 rows) - --- Use indexscan for testing indexes after splitting partition -SET enable_indexscan = ON; -SET enable_seqscan = OFF; -SELECT * FROM sales_central WHERE sales_state = 'Warsaw'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(2 rows) - -SELECT * FROM sales_list WHERE sales_state = 'Warsaw'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 - 13 | Gandi | Warsaw | 150 | 03-08-2022 -(2 rows) - -SELECT * FROM sales_list WHERE salesperson_name = 'Ivanov'; - salesperson_id | salesperson_name | sales_state | sales_amount | sales_date -----------------+------------------+-------------+--------------+------------ - 4 | Ivanov | Warsaw | 750 | 03-04-2022 -(1 row) - -SET enable_indexscan = ON; -SET enable_seqscan = ON; -DROP TABLE sales_list; --- --- Test for: --- * split DEFAULT partition to partitions with spaces between bounds; --- * random order of partitions in SPLIT PARTITION command. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-09'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-07'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_others DEFAULT, - PARTITION sales_mar2022_1decade FOR VALUES FROM ('2022-03-01') TO ('2022-03-10'), - PARTITION sales_jan2022_1decade FOR VALUES FROM ('2022-01-01') TO ('2022-01-10'), - PARTITION sales_feb2022_1decade FOR VALUES FROM ('2022-02-01') TO ('2022-02-10'), - PARTITION sales_apr2022_1decade FOR VALUES FROM ('2022-04-01') TO ('2022-04-10')); -SELECT * FROM sales_jan2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 13 | Gandi | 377 | 01-09-2022 -(1 row) - -SELECT * FROM sales_feb2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-09-2022 - 6 | Poirot | 150 | 02-07-2022 -(2 rows) - -SELECT * FROM sales_mar2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 -(1 row) - -SELECT * FROM sales_apr2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(2 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 8 | Ericsson | 185 | 02-23-2022 - 9 | Muller | 250 | 03-11-2022 - 10 | Halder | 350 | 01-28-2022 - 12 | Plato | 350 | 03-19-2022 - 14 | Smith | 510 | 05-04-2022 -(8 rows) - -DROP TABLE sales_range; --- --- Test for: --- * split non-DEFAULT partition to partitions with spaces between bounds; --- * random order of partitions in SPLIT PARTITION command. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_all PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-09'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-07'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -ALTER TABLE sales_range SPLIT PARTITION sales_all INTO - (PARTITION sales_mar2022_1decade FOR VALUES FROM ('2022-03-01') TO ('2022-03-10'), - PARTITION sales_jan2022_1decade FOR VALUES FROM ('2022-01-01') TO ('2022-01-10'), - PARTITION sales_feb2022_1decade FOR VALUES FROM ('2022-02-01') TO ('2022-02-10'), - PARTITION sales_apr2022_1decade FOR VALUES FROM ('2022-04-01') TO ('2022-04-10')); -SELECT * FROM sales_jan2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 13 | Gandi | 377 | 01-09-2022 -(1 row) - -SELECT * FROM sales_feb2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-09-2022 - 6 | Poirot | 150 | 02-07-2022 -(2 rows) - -SELECT * FROM sales_mar2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 -(1 row) - -SELECT * FROM sales_apr2022_1decade; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(2 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 14 | Smith | 510 | 05-04-2022 - 1 | May | 1000 | 01-31-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 8 | Ericsson | 185 | 02-23-2022 - 9 | Muller | 250 | 03-11-2022 - 10 | Halder | 350 | 01-28-2022 - 12 | Plato | 350 | 03-19-2022 -(8 rows) - -DROP TABLE sales_range; --- --- Test for split non-DEFAULT partition to DEFAULT partition + partitions --- with spaces between bounds. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_all PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -ALTER TABLE sales_range SPLIT PARTITION sales_all INTO - (PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_others DEFAULT); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); -SELECT * FROM sales_range; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 14 | Smith | 510 | 05-04-2022 -(14 rows) - -SELECT * FROM sales_jan2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 1 | May | 1000 | 01-31-2022 - 10 | Halder | 350 | 01-28-2022 - 13 | Gandi | 377 | 01-09-2022 -(3 rows) - -SELECT * FROM sales_feb2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 2 | Smirnoff | 500 | 02-10-2022 - 6 | Poirot | 150 | 02-11-2022 - 8 | Ericsson | 185 | 02-23-2022 -(3 rows) - -SELECT * FROM sales_apr2022; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 3 | Ford | 2000 | 04-30-2022 - 4 | Ivanov | 750 | 04-13-2022 - 5 | Deev | 250 | 04-07-2022 - 11 | Trump | 380 | 04-06-2022 -(4 rows) - -SELECT * FROM sales_others; - salesperson_id | salesperson_name | sales_amount | sales_date -----------------+------------------+--------------+------------ - 7 | Li | 175 | 03-08-2022 - 9 | Muller | 250 | 03-11-2022 - 12 | Plato | 350 | 03-19-2022 - 14 | Smith | 510 | 05-04-2022 -(4 rows) - -DROP TABLE sales_range; --- --- Try to SPLIT partition of another table. --- -CREATE TABLE t1(i int, t text) PARTITION BY LIST (t); -CREATE TABLE t1pa PARTITION OF t1 FOR VALUES IN ('A'); -CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t); --- ERROR: relation "t1pa" is not a partition of relation "t2" -ALTER TABLE t2 SPLIT PARTITION t1pa INTO - (PARTITION t2a FOR VALUES FROM ('A') TO ('B'), - PARTITION t2b FOR VALUES FROM ('B') TO ('C')); -ERROR: relation "t1pa" is not a partition of relation "t2" -DROP TABLE t2; -DROP TABLE t1; --- --- Try to SPLIT partition of temporary table. --- -CREATE TEMP TABLE t (i int) PARTITION BY RANGE (i); -CREATE TEMP TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_2 | FOR VALUES FROM (0) TO (2) | t -(1 row) - -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); --- Partitions should be temporary. -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - oid | pg_get_expr | relpersistence ---------+----------------------------+---------------- - tp_0_1 | FOR VALUES FROM (0) TO (1) | t - tp_1_2 | FOR VALUES FROM (1) TO (2) | t -(2 rows) - -DROP TABLE t; --- Check the new partitions inherit parent's tablespace -CREATE TABLE t (i int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) - PARTITION BY RANGE (i) TABLESPACE regress_tblspace; -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -SELECT tablename, tablespace FROM pg_tables - WHERE tablename IN ('t', 'tp_0_1', 'tp_1_2') AND schemaname = 'partition_split_schema' - ORDER BY tablename, tablespace; - tablename | tablespace ------------+------------------ - t | regress_tblspace - tp_0_1 | regress_tblspace - tp_1_2 | regress_tblspace -(3 rows) - -SELECT tablename, indexname, tablespace FROM pg_indexes - WHERE tablename IN ('t', 'tp_0_1', 'tp_1_2') AND schemaname = 'partition_split_schema' - ORDER BY tablename, indexname, tablespace; - tablename | indexname | tablespace ------------+-------------+------------------ - t | t_pkey | regress_tblspace - tp_0_1 | tp_0_1_pkey | regress_tblspace - tp_1_2 | tp_1_2_pkey | regress_tblspace -(3 rows) - -DROP TABLE t; --- Check new partitions inherits parent's table access method -CREATE ACCESS METHOD partition_split_heap TYPE TABLE HANDLER heap_tableam_handler; -CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partition_split_heap; -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -SELECT c.relname, a.amname -FROM pg_class c JOIN pg_am a ON c.relam = a.oid -WHERE c.oid IN ('t'::regclass, 'tp_0_1'::regclass, 'tp_1_2'::regclass) -ORDER BY c.relname; - relname | amname ----------+---------------------- - t | partition_split_heap - tp_0_1 | partition_split_heap - tp_1_2 | partition_split_heap -(3 rows) - -DROP TABLE t; -DROP ACCESS METHOD partition_split_heap; --- Test permission checks. The user needs to own the parent table and the --- the partition to split to do the split. -CREATE ROLE regress_partition_split_alice; -CREATE ROLE regress_partition_split_bob; -GRANT ALL ON SCHEMA partition_split_schema TO regress_partition_split_alice; -GRANT ALL ON SCHEMA partition_split_schema TO regress_partition_split_bob; -SET SESSION AUTHORIZATION regress_partition_split_alice; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -ERROR: must be owner of table t -RESET SESSION AUTHORIZATION; -ALTER TABLE t OWNER TO regress_partition_split_bob; -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -ERROR: must be owner of table tp_0_2 -RESET SESSION AUTHORIZATION; -ALTER TABLE tp_0_2 OWNER TO regress_partition_split_bob; -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -RESET SESSION AUTHORIZATION; -DROP TABLE t; -REVOKE ALL ON SCHEMA partition_split_schema FROM regress_partition_split_alice; -REVOKE ALL ON SCHEMA partition_split_schema FROM regress_partition_split_bob; -DROP ROLE regress_partition_split_alice; -DROP ROLE regress_partition_split_bob; --- Split partition of a temporary table when one of the partitions after --- split has the same name as the partition being split -CREATE TEMP TABLE t (a int) PARTITION BY RANGE (a); -CREATE TEMP TABLE tp_0 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0 INTO - (PARTITION tp_0 FOR VALUES FROM (0) TO (1), - PARTITION tp_1 FOR VALUES FROM (1) TO (2)); -DROP TABLE t; -RESET search_path; --- -DROP SCHEMA partition_split_schema; -DROP SCHEMA partition_split_schema2; diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out index 924d6e001d457..9bb3ab2818bfb 100644 --- a/src/test/regress/expected/password.out +++ b/src/test/regress/expected/password.out @@ -14,8 +14,14 @@ SET password_encryption = 'scram-sha-256'; -- ok SET password_encryption = 'md5'; CREATE ROLE regress_passwd1; ALTER ROLE regress_passwd1 PASSWORD 'role_pwd1'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. CREATE ROLE regress_passwd2; ALTER ROLE regress_passwd2 PASSWORD 'role_pwd2'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. SET password_encryption = 'scram-sha-256'; CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3'; CREATE ROLE regress_passwd4 PASSWORD NULL; @@ -57,14 +63,23 @@ ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2; SET password_encryption = 'md5'; -- encrypt with MD5 ALTER ROLE regress_passwd2 PASSWORD 'foo'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. -- already encrypted, use as they are ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo='; SET password_encryption = 'scram-sha-256'; -- create SCRAM secret ALTER ROLE regress_passwd4 PASSWORD 'foo'; -- already encrypted with MD5, use as it is CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. -- This looks like a valid SCRAM-SHA-256 secret, but it is not -- so it should be hashed with SCRAM-SHA-256. CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234'; @@ -127,6 +142,13 @@ SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassw regress_passwd_sha_len2 | t (3 rows) +-- Test that valid hashes that are too long are rejected +CREATE ROLE regress_passwd10 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; +ERROR: encrypted password is too long +DETAIL: Encrypted passwords must be no longer than 512 bytes. +ALTER ROLE regress_passwd9 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; +ERROR: encrypted password is too long +DETAIL: Encrypted passwords must be no longer than 512 bytes. DROP ROLE regress_passwd1; DROP ROLE regress_passwd2; DROP ROLE regress_passwd3; diff --git a/src/test/regress/expected/password_1.out b/src/test/regress/expected/password_1.out index 9d2cc94f3712a..8f613e976a6b8 100644 --- a/src/test/regress/expected/password_1.out +++ b/src/test/regress/expected/password_1.out @@ -61,12 +61,18 @@ ALTER ROLE regress_passwd2 PASSWORD 'foo'; ERROR: password encryption failed: unsupported -- already encrypted, use as they are ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo='; SET password_encryption = 'scram-sha-256'; -- create SCRAM secret ALTER ROLE regress_passwd4 PASSWORD 'foo'; -- already encrypted with MD5, use as it is CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. -- This looks like a valid SCRAM-SHA-256 secret, but it is not -- so it should be hashed with SCRAM-SHA-256. CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234'; @@ -100,6 +106,9 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+ CREATE ROLE regress_passwd_empty PASSWORD ''; NOTICE: empty string is not a valid password, clearing password ALTER ROLE regress_passwd_empty PASSWORD 'md585939a5ce845f1a1b620742e3c659e0a'; +WARNING: setting an MD5-encrypted password +DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +HINT: Refer to the PostgreSQL documentation for details about migrating to another password type. ALTER ROLE regress_passwd_empty PASSWORD 'SCRAM-SHA-256$4096:hpFyHTUsSWcR7O9P$LgZFIt6Oqdo27ZFKbZ2nV+vtnYM995pDh9ca6WSi120=:qVV5NeluNfUPkwm7Vqat25RjSPLkGeoZBQs6wVv+um4='; NOTICE: empty string is not a valid password, clearing password SELECT rolpassword FROM pg_authid WHERE rolname='regress_passwd_empty'; @@ -128,6 +137,13 @@ SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassw regress_passwd_sha_len2 | t (3 rows) +-- Test that valid hashes that are too long are rejected +CREATE ROLE regress_passwd10 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; +ERROR: encrypted password is too long +DETAIL: Encrypted passwords must be no longer than 512 bytes. +ALTER ROLE regress_passwd9 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; +ERROR: encrypted password is too long +DETAIL: Encrypted passwords must be no longer than 512 bytes. DROP ROLE regress_passwd1; DROP ROLE regress_passwd2; DROP ROLE regress_passwd3; diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 074af8f33a8e4..d8ce39dba3c16 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -2388,7 +2388,7 @@ begin end $$ language plpgsql; select namedparmcursor_test7(); ERROR: division by zero -CONTEXT: SQL expression "42/0 AS p1, 77 AS p2" +CONTEXT: PL/pgSQL expression "42/0 AS p1, 77 AS p2" PL/pgSQL function namedparmcursor_test7() line 6 at OPEN -- check that line comments work correctly within the argument list -- (this used to require a special hack in the code; it no longer does, @@ -2419,7 +2419,8 @@ declare p2 int4 := 1006; n int4; begin - open c1 (p1 := p1, p2 := p2, debug := 2); + -- use both supported syntaxes for named arguments + open c1 (p1 := p1, p2 => p2, debug => 2); fetch c1 into n; return n; end $$ language plpgsql; @@ -3487,7 +3488,8 @@ begin raise notice '% from %', r.i, c; end loop; -- again, to test if cursor was closed properly - for r in c(9,10) loop + -- (and while we're at it, test named-parameter notation) + for r in c(r2 := 10, r1 => 9) loop raise notice '% from %', r.i, c; end loop; -- and test a parameterless cursor @@ -3777,7 +3779,7 @@ end; $$ language plpgsql; select compos(); ERROR: returned record type does not match expected record type -DETAIL: Returned type unknown does not match expected type character varying in column 2. +DETAIL: Returned type unknown does not match expected type character varying in column "y" (position 2). CONTEXT: PL/pgSQL function compos() while casting return value to function's return type -- ... but this does create or replace function compos() returns compostype as $$ @@ -4563,11 +4565,11 @@ end $$; select fail(); ERROR: division by zero -CONTEXT: SQL expression "1/0" +CONTEXT: PL/pgSQL expression "1/0" PL/pgSQL function fail() line 3 at RETURN select fail(); ERROR: division by zero -CONTEXT: SQL expression "1/0" +CONTEXT: PL/pgSQL expression "1/0" PL/pgSQL function fail() line 3 at RETURN drop function fail(); -- Test handling of string literals. diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out index 7a9778e70fd1f..c01848f103ec8 100644 --- a/src/test/regress/expected/polygon.out +++ b/src/test/regress/expected/polygon.out @@ -286,10 +286,11 @@ FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200)) QUERY PLAN --------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (ORDER BY (p <-> '(123,456)'::point) ROWS UNBOUNDED PRECEDING) -> Index Scan using quad_poly_tbl_idx on quad_poly_tbl Index Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon) Order By: (p <-> '(123,456)'::point) -(4 rows) +(5 rows) CREATE TEMP TABLE quad_poly_tbl_ord_idx2 AS SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id diff --git a/src/test/regress/expected/polymorphism.out b/src/test/regress/expected/polymorphism.out index bf08e40ed8f8f..94eedfe375eea 100644 --- a/src/test/regress/expected/polymorphism.out +++ b/src/test/regress/expected/polymorphism.out @@ -1165,6 +1165,8 @@ create function dfunc(a int = 1, b int) returns int as $$ select $1 + $2; $$ language sql; ERROR: input parameters after one with a default value must also have defaults +LINE 1: create function dfunc(a int = 1, b int) returns int as $$ + ^ -- however, this should work: create function dfunc(a int = 1, out sum int, b int = 2) as $$ select $1 + $2; @@ -1270,6 +1272,8 @@ create function dfunc(out int = 20) returns int as $$ select 1; $$ language sql; ERROR: only input parameters can have default values +LINE 1: create function dfunc(out int = 20) returns int as $$ + ^ -- polymorphic parameter test create function dfunc(anyelement = 'World'::text) returns text as $$ select 'Hello, ' || $1::text; @@ -1567,12 +1571,20 @@ drop function dfunc(varchar, numeric); --fail, named parameters are not unique create function testpolym(a int, a int) returns int as $$ select 1;$$ language sql; ERROR: parameter name "a" used more than once +LINE 1: create function testpolym(a int, a int) returns int as $$ se... + ^ create function testpolym(int, out a int, out a int) returns int as $$ select 1;$$ language sql; ERROR: parameter name "a" used more than once +LINE 1: create function testpolym(int, out a int, out a int) returns... + ^ create function testpolym(out a int, inout a int) returns int as $$ select 1;$$ language sql; ERROR: parameter name "a" used more than once +LINE 1: create function testpolym(out a int, inout a int) returns in... + ^ create function testpolym(a int, inout a int) returns int as $$ select 1;$$ language sql; ERROR: parameter name "a" used more than once +LINE 1: create function testpolym(a int, inout a int) returns int as... + ^ -- valid create function testpolym(a int, out a int) returns int as $$ select $1;$$ language sql; select testpolym(37); diff --git a/src/test/regress/expected/predicate.out b/src/test/regress/expected/predicate.out index 6f1cc0d54cd3f..b79037748b7e6 100644 --- a/src/test/regress/expected/predicate.out +++ b/src/test/regress/expected/predicate.out @@ -97,55 +97,50 @@ SELECT * FROM pred_tab t WHERE t.b IS NULL OR t.c IS NULL; -- and b) its Var is not nullable by any outer joins EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL; - QUERY PLAN -------------------------------------------------- + LEFT JOIN pred_tab t2 ON t1.a IS NOT NULL; + QUERY PLAN +------------------------------------- Nested Loop Left Join -> Seq Scan on pred_tab t1 -> Materialize - -> Nested Loop Left Join - -> Seq Scan on pred_tab t2 - -> Materialize - -> Seq Scan on pred_tab t3 -(7 rows) + -> Seq Scan on pred_tab t2 +(4 rows) -- Ensure the IS_NOT_NULL qual is not ignored when columns are made nullable -- by an outer join EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON t1.a = 1 + FULL JOIN pred_tab t2 ON t1.a = t2.a LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL; QUERY PLAN ------------------------------------------- Nested Loop Left Join Join Filter: (t2.a IS NOT NULL) - -> Nested Loop Left Join - Join Filter: (t1.a = 1) - -> Seq Scan on pred_tab t1 - -> Materialize + -> Merge Full Join + Merge Cond: (t1.a = t2.a) + -> Sort + Sort Key: t1.a + -> Seq Scan on pred_tab t1 + -> Sort + Sort Key: t2.a -> Seq Scan on pred_tab t2 -> Materialize -> Seq Scan on pred_tab t3 -(9 rows) +(12 rows) -- Ensure the IS_NULL qual is reduced to constant-FALSE, since a) it's on a NOT -- NULL column, and b) its Var is not nullable by any outer joins EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NULL AND t2.b = 1; - QUERY PLAN ---------------------------------------------------- + LEFT JOIN pred_tab t2 ON t1.a IS NULL; + QUERY PLAN +-------------------------------- Nested Loop Left Join + Join Filter: false -> Seq Scan on pred_tab t1 - -> Materialize - -> Nested Loop Left Join - Join Filter: (false AND (t2.b = 1)) - -> Seq Scan on pred_tab t2 - -> Result - One-Time Filter: false -(8 rows) + -> Result + One-Time Filter: false +(5 rows) -- Ensure the IS_NULL qual is not reduced to constant-FALSE when the column is -- nullable by an outer join @@ -172,55 +167,50 @@ SELECT * FROM pred_tab t1 -- Ensure the OR clause is ignored when an OR branch is provably always true EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL OR t2.b = 1; - QUERY PLAN -------------------------------------------------- + LEFT JOIN pred_tab t2 ON t1.a IS NOT NULL OR t2.b = 1; + QUERY PLAN +------------------------------------- Nested Loop Left Join -> Seq Scan on pred_tab t1 -> Materialize - -> Nested Loop Left Join - -> Seq Scan on pred_tab t2 - -> Materialize - -> Seq Scan on pred_tab t3 -(7 rows) + -> Seq Scan on pred_tab t2 +(4 rows) -- Ensure the NullTest is not ignored when the column is nullable by an outer -- join EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON t1.a = 1 + FULL JOIN pred_tab t2 ON t1.a = t2.a LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL OR t2.b = 1; QUERY PLAN --------------------------------------------------- Nested Loop Left Join Join Filter: ((t2.a IS NOT NULL) OR (t2.b = 1)) - -> Nested Loop Left Join - Join Filter: (t1.a = 1) - -> Seq Scan on pred_tab t1 - -> Materialize + -> Merge Full Join + Merge Cond: (t1.a = t2.a) + -> Sort + Sort Key: t1.a + -> Seq Scan on pred_tab t1 + -> Sort + Sort Key: t2.a -> Seq Scan on pred_tab t2 -> Materialize -> Seq Scan on pred_tab t3 -(9 rows) +(12 rows) -- Ensure the OR clause is reduced to constant-FALSE when all OR branches are -- provably false EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON (t2.a IS NULL OR t2.c IS NULL) AND t2.b = 1; - QUERY PLAN ---------------------------------------------------- + LEFT JOIN pred_tab t2 ON (t1.a IS NULL OR t1.c IS NULL); + QUERY PLAN +-------------------------------- Nested Loop Left Join + Join Filter: false -> Seq Scan on pred_tab t1 - -> Materialize - -> Nested Loop Left Join - Join Filter: (false AND (t2.b = 1)) - -> Seq Scan on pred_tab t2 - -> Result - One-Time Filter: false -(8 rows) + -> Result + One-Time Filter: false +(5 rows) -- Ensure the OR clause is not reduced to constant-FALSE when a column is -- made nullable from an outer join @@ -290,3 +280,84 @@ SELECT * FROM pred_parent WHERE a IS NULL; (2 rows) DROP TABLE pred_parent, pred_child; +-- Validate we do not reduce a clone clause to a constant true or false +CREATE TABLE pred_tab (a int, b int); +CREATE TABLE pred_tab_notnull (a int, b int NOT NULL); +INSERT INTO pred_tab VALUES (1, 1); +INSERT INTO pred_tab VALUES (2, 2); +INSERT INTO pred_tab_notnull VALUES (2, 2); +INSERT INTO pred_tab_notnull VALUES (3, 3); +ANALYZE pred_tab; +ANALYZE pred_tab_notnull; +-- Ensure the IS_NOT_NULL qual is not reduced to constant true and removed +EXPLAIN (COSTS OFF) +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NOT NULL; + QUERY PLAN +--------------------------------------------------------------- + Nested Loop Left Join + -> Seq Scan on pred_tab t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: (t3.b IS NOT NULL) + -> Nested Loop Left Join + Join Filter: (t2.a = t3.a) + -> Seq Scan on pred_tab t2 + -> Materialize + -> Seq Scan on pred_tab_notnull t3 + -> Materialize + -> Seq Scan on pred_tab t4 +(12 rows) + +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NOT NULL; + a | b | a | b | a | b | a | b +---+---+---+---+---+---+---+--- + 1 | 1 | 1 | 1 | | | | + 1 | 1 | 2 | 2 | 2 | 2 | 1 | 1 + 1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 + 2 | 2 | 1 | 1 | | | | + 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 + 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 +(6 rows) + +-- Ensure the IS_NULL qual is not reduced to constant false +EXPLAIN (COSTS OFF) +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NULL AND t3.a IS NOT NULL; + QUERY PLAN +-------------------------------------------------------------------- + Nested Loop Left Join + -> Seq Scan on pred_tab t1 + -> Materialize + -> Nested Loop Left Join + Join Filter: ((t3.b IS NULL) AND (t3.a IS NOT NULL)) + -> Nested Loop Left Join + Join Filter: (t2.a = t3.a) + -> Seq Scan on pred_tab t2 + -> Materialize + -> Seq Scan on pred_tab_notnull t3 + -> Materialize + -> Seq Scan on pred_tab t4 +(12 rows) + +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NULL AND t3.a IS NOT NULL; + a | b | a | b | a | b | a | b +---+---+---+---+---+---+---+--- + 1 | 1 | 1 | 1 | | | | + 1 | 1 | 2 | 2 | 2 | 2 | | + 2 | 2 | 1 | 1 | | | | + 2 | 2 | 2 | 2 | 2 | 2 | | +(4 rows) + +DROP TABLE pred_tab; +DROP TABLE pred_tab_notnull; diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index fab0cc800fcdd..c25062c288f32 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -113,6 +113,36 @@ CREATE USER regress_priv_user2; CREATE USER regress_priv_user3; CREATE USER regress_priv_user4; CREATE USER regress_priv_user5; +-- DROP OWNED should also act on granted and granted-to roles +GRANT regress_priv_user1 TO regress_priv_user2; +GRANT regress_priv_user2 TO regress_priv_user3; +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; + roleid | member +--------------------+-------------------- + regress_priv_user1 | regress_priv_user2 + regress_priv_user2 | regress_priv_user3 +(2 rows) + +REASSIGN OWNED BY regress_priv_user2 TO regress_priv_user4; -- no effect +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; + roleid | member +--------------------+-------------------- + regress_priv_user1 | regress_priv_user2 + regress_priv_user2 | regress_priv_user3 +(2 rows) + +DROP OWNED BY regress_priv_user2; -- removes both grants +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; + roleid | member +--------+-------- +(0 rows) + GRANT pg_read_all_data TO regress_priv_user6; GRANT pg_write_all_data TO regress_priv_user7; GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION; @@ -141,6 +171,73 @@ SET ROLE pg_read_all_stats; -- fail, granted without SET option ERROR: permission denied to set role "pg_read_all_stats" RESET ROLE; RESET SESSION AUTHORIZATION; +-- test interaction of SET SESSION AUTHORIZATION and SET ROLE, +-- as well as propagation of these settings to parallel workers +GRANT regress_priv_user9 TO regress_priv_user8; +SET SESSION AUTHORIZATION regress_priv_user8; +SET ROLE regress_priv_user9; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +--------------------+--------------------+--------------------+-------------------- + regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9 +(1 row) + +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +--------------------+--------------------+--------------------+-------------------- + regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9 +(1 row) + +BEGIN; +SET SESSION AUTHORIZATION regress_priv_user10; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +---------------------+---------------------+---------------------+------ + regress_priv_user10 | regress_priv_user10 | regress_priv_user10 | none +(1 row) + +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +---------------------+---------------------+---------------------+------ + regress_priv_user10 | regress_priv_user10 | regress_priv_user10 | none +(1 row) + +ROLLBACK; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +--------------------+--------------------+--------------------+-------------------- + regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9 +(1 row) + +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + session_user | current_role | current_user | role +--------------------+--------------------+--------------------+-------------------- + regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9 +(1 row) + +RESET SESSION AUTHORIZATION; +-- session_user at this point is installation-dependent +SET debug_parallel_query = 0; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; + c_r_ok | c_u_ok | role +--------+--------+------ + t | t | none +(1 row) + +SET debug_parallel_query = 1; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; + c_r_ok | c_u_ok | role +--------+--------+------ + t | t | none +(1 row) + +RESET debug_parallel_query; REVOKE pg_read_all_settings FROM regress_priv_user8; DROP USER regress_priv_user10; DROP USER regress_priv_user9; @@ -149,6 +246,13 @@ CREATE GROUP regress_priv_group1; CREATE GROUP regress_priv_group2 WITH ADMIN regress_priv_user1 USER regress_priv_user2; ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4; GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1; +SET SESSION AUTHORIZATION regress_priv_user3; +ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- fail +ERROR: permission denied to alter role +DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may add or drop members. +ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; -- fail +ERROR: permission denied to alter role +DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may add or drop members. SET SESSION AUTHORIZATION regress_priv_user1; ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; NOTICE: role "regress_priv_user2" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user1" @@ -1422,15 +1526,6 @@ from (select oid from pg_roles where rolname = current_user) as t2; t (1 row) --- 'rule' privilege no longer exists, but for backwards compatibility --- has_table_privilege still recognizes the keyword and says FALSE -select has_table_privilege(current_user,t1.oid,'rule') -from (select oid from pg_class where relname = 'pg_authid') as t1; - has_table_privilege ---------------------- - f -(1 row) - select has_table_privilege(current_user,t1.oid,'references') from (select oid from pg_class where relname = 'pg_authid') as t1; has_table_privilege @@ -2077,10 +2172,160 @@ SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); 0 (1 row) +-- has_largeobject_privilege function +-- superuser +\c - +SELECT has_largeobject_privilege(1001, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1002, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1003, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1004, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1001, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1002, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1003, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1004, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +-- not-existing large object +SELECT has_largeobject_privilege(9999, 'SELECT'); -- NULL + has_largeobject_privilege +--------------------------- + +(1 row) + +-- non-superuser +SET SESSION AUTHORIZATION regress_priv_user2; +SELECT has_largeobject_privilege(1001, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1002, 'SELECT'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege(1003, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1004, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1001, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege(1003, 'UPDATE'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege(1004, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user3', 1001, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user3', 1003, 'SELECT'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'SELECT'); + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'UPDATE'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user3', 2001, 'UPDATE'); + has_largeobject_privilege +--------------------------- + t +(1 row) + -- compatibility mode in largeobject permission \c - SET lo_compat_privileges = false; -- default setting SET SESSION AUTHORIZATION regress_priv_user4; +SELECT has_largeobject_privilege(1002, 'SELECT'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied ERROR: permission denied for large object 1002 SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied @@ -2100,6 +2345,18 @@ ERROR: permission denied for function lo_import \c - SET lo_compat_privileges = true; -- compatibility mode SET SESSION AUTHORIZATION regress_priv_user4; +SELECT has_largeobject_privilege(1002, 'SELECT'); -- true + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- true + has_largeobject_privilege +--------------------------- + t +(1 row) + SELECT loread(lo_open(1002, x'40000'::int), 32); loread -------- @@ -2410,11 +2667,103 @@ SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2; COMMIT; +-- +-- Test for default privileges on large objects. This is done in a +-- separate, rollbacked, transaction to avoid any trouble with other +-- regression sessions. +-- +BEGIN; +SELECT lo_create(1007); + lo_create +----------- + 1007 +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'SELECT'); -- no + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'UPDATE'); -- no + has_largeobject_privilege +--------------------------- + f +(1 row) + +ALTER DEFAULT PRIVILEGES GRANT SELECT ON LARGE OBJECTS TO regress_priv_user2; +SELECT lo_create(1008); + lo_create +----------- + 1008 +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'SELECT'); -- yes + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user6', 1008, 'SELECT'); -- no + has_largeobject_privilege +--------------------------- + f +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'UPDATE'); -- no + has_largeobject_privilege +--------------------------- + f +(1 row) + +ALTER DEFAULT PRIVILEGES GRANT ALL ON LARGE OBJECTS TO regress_priv_user2; +SELECT lo_create(1009); + lo_create +----------- + 1009 +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1009, 'SELECT'); -- true + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1009, 'UPDATE'); -- true + has_largeobject_privilege +--------------------------- + t +(1 row) + +ALTER DEFAULT PRIVILEGES REVOKE UPDATE ON LARGE OBJECTS FROM regress_priv_user2; +SELECT lo_create(1010); + lo_create +----------- + 1010 +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1010, 'SELECT'); -- true + has_largeobject_privilege +--------------------------- + t +(1 row) + +SELECT has_largeobject_privilege('regress_priv_user2', 1010, 'UPDATE'); -- false + has_largeobject_privilege +--------------------------- + f +(1 row) + +ROLLBACK; +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON LARGE OBJECTS TO public; -- error +ERROR: cannot use IN SCHEMA clause when using GRANT/REVOKE ON LARGE OBJECTS +\c - -- Test for DROP OWNED BY with shared dependencies. This is done in a -- separate, rollbacked, transaction to avoid any trouble with other -- regression sessions. BEGIN; ALTER DEFAULT PRIVILEGES GRANT ALL ON FUNCTIONS TO regress_priv_user2; +ALTER DEFAULT PRIVILEGES GRANT ALL ON LARGE OBJECTS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON SEQUENCES TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO regress_priv_user2; @@ -2425,7 +2774,7 @@ SELECT count(*) FROM pg_shdepend classid = 'pg_default_acl'::regclass; count ------- - 5 + 6 (1 row) DROP OWNED BY regress_priv_user2, regress_priv_user2; @@ -2870,11 +3219,17 @@ REVOKE MAINTAIN ON lock_table FROM regress_locktable_user; -- clean up DROP TABLE lock_table; DROP USER regress_locktable_user; --- test to check privileges of system views pg_shmem_allocations and --- pg_backend_memory_contexts. +-- test to check privileges of system views pg_shmem_allocations, +-- pg_shmem_allocations_numa and pg_backend_memory_contexts. -- switch to superuser \c - CREATE ROLE regress_readallstats; +SELECT has_table_privilege('regress_readallstats','pg_aios','SELECT'); -- no + has_table_privilege +--------------------- + f +(1 row) + SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no has_table_privilege --------------------- @@ -2887,7 +3242,19 @@ SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT f (1 row) +SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations_numa','SELECT'); -- no + has_table_privilege +--------------------- + f +(1 row) + GRANT pg_read_all_stats TO regress_readallstats; +SELECT has_table_privilege('regress_readallstats','pg_aios','SELECT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- yes has_table_privilege --------------------- @@ -2900,8 +3267,20 @@ SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT t (1 row) +SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations_numa','SELECT'); -- yes + has_table_privilege +--------------------- + t +(1 row) + -- run query to ensure that functions within views can be executed SET ROLE regress_readallstats; +SELECT COUNT(*) >= 0 AS ok FROM pg_aios; + ok +---- + t +(1 row) + SELECT COUNT(*) >= 0 AS ok FROM pg_backend_memory_contexts; ok ---- @@ -3036,3 +3415,30 @@ DROP SCHEMA reindex_test; DROP ROLE regress_no_maintain; DROP ROLE regress_maintain; DROP ROLE regress_maintain_all; +-- grantor selection +CREATE ROLE regress_grantor1; +CREATE ROLE regress_grantor2 ROLE regress_grantor1; +CREATE ROLE regress_grantor3; +CREATE TABLE grantor_test1 (); +CREATE TABLE grantor_test2 (); +CREATE TABLE grantor_test3 (); +GRANT SELECT ON grantor_test2 TO regress_grantor1 WITH GRANT OPTION; +GRANT SELECT, UPDATE ON grantor_test3 TO regress_grantor2 WITH GRANT OPTION; +SET ROLE regress_grantor1; +GRANT SELECT, UPDATE ON grantor_test1 TO regress_grantor3; +ERROR: permission denied for table grantor_test1 +GRANT SELECT, UPDATE ON grantor_test2 TO regress_grantor3; +WARNING: not all privileges were granted for "grantor_test2" +GRANT SELECT, UPDATE ON grantor_test3 TO regress_grantor3; +RESET ROLE; +SELECT * FROM information_schema.table_privileges t + WHERE grantor LIKE 'regress_grantor%' ORDER BY ROW(t.*); + grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy +------------------+------------------+---------------+--------------+---------------+----------------+--------------+---------------- + regress_grantor1 | regress_grantor3 | regression | public | grantor_test2 | SELECT | NO | YES + regress_grantor2 | regress_grantor3 | regression | public | grantor_test3 | SELECT | NO | YES + regress_grantor2 | regress_grantor3 | regression | public | grantor_test3 | UPDATE | NO | NO +(3 rows) + +DROP TABLE grantor_test1, grantor_test2, grantor_test3; +DROP ROLE regress_grantor1, regress_grantor2, regress_grantor3; diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 3bbe4c5f974d6..cf48ae6d0c2ee 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -98,6 +98,81 @@ two | 2 1 | 2 (1 row) +-- \parse (extended query protocol) +\parse +\parse: missing required argument +SELECT 1 \parse '' +SELECT 2 \parse stmt1 +SELECT $1 \parse stmt2 +SELECT $1, $2 \parse stmt3 +-- \bind_named (extended query protocol) +\bind_named +\bind_named: missing required argument +\bind_named '' \g + ?column? +---------- + 1 +(1 row) + +\bind_named stmt1 \g + ?column? +---------- + 2 +(1 row) + +\bind_named stmt2 'foo' \g + ?column? +---------- + foo +(1 row) + +\bind_named stmt3 'foo' 'bar' \g + ?column? | ?column? +----------+---------- + foo | bar +(1 row) + +-- Repeated calls. The second call generates an error, cleaning up the +-- statement name set by the first call. +\bind_named stmt4 +\bind_named +\bind_named: missing required argument +\g +ERROR: there is no parameter $1 +LINE 1: SELECT $1, $2 + ^ +-- Last \bind_named wins +\bind_named stmt2 'foo' \bind_named stmt3 'foo2' 'bar2' \g + ?column? | ?column? +----------+---------- + foo2 | bar2 +(1 row) + +-- Multiple \g calls mean multiple executions +\bind_named stmt2 'foo3' \g \bind_named stmt3 'foo4' 'bar4' \g + ?column? +---------- + foo3 +(1 row) + + ?column? | ?column? +----------+---------- + foo4 | bar4 +(1 row) + +-- \close (extended query protocol) +\close +\close: missing required argument +\close '' +\close stmt2 +\close stmt2 +SELECT name, statement FROM pg_prepared_statements ORDER BY name; + name | statement +-------+---------------- + stmt1 | SELECT 2 + stmt3 | SELECT $1, $2 +(2 rows) + -- \bind (extended query protocol) SELECT 1 \bind \g ?column? @@ -117,6 +192,25 @@ SELECT $1, $2 \bind 'foo' 'bar' \g foo | bar (1 row) +-- last \bind wins +select $1::int as col \bind 'foo' \bind 2 \g + col +----- + 2 +(1 row) + +-- Multiple \g calls mean multiple executions +select $1::int as col \bind 1 \g \bind 2 \g + col +----- + 1 +(1 row) + + col +----- + 2 +(1 row) + -- errors -- parse error SELECT foo \bind \g @@ -129,6 +223,11 @@ ERROR: cannot insert multiple commands into a prepared statement -- bind error SELECT $1, $2 \bind 'foo' \g ERROR: bind message supplies 1 parameters, but prepared statement "" requires 2 +-- bind_named error +\bind_named stmt2 'baz' \g +ERROR: prepared statement "stmt2" does not exist +\bind_named stmt3 'baz' \g +ERROR: bind message supplies 1 parameters, but prepared statement "stmt3" requires 2 -- \gset select 10 as test01, 20 as test02, 'Hello' as test03 \gset pref01_ \echo :pref01_test01 :pref01_test02 :pref01_test03 @@ -2742,6 +2841,19 @@ Owned by: public.psql_serial_tab.id pg_catalog | exp | double precision | double precision | func pg_catalog | exp | numeric | numeric | func +\dfx exp +Schema | pg_catalog +Name | exp +Result data type | double precision +Argument data types | double precision +Type | func +--------------------+----------------- +Schema | pg_catalog +Name | exp +Result data type | numeric +Argument data types | numeric +Type | func + \pset tuples_only false \pset expanded on \d psql_serial_tab_id_seq @@ -2915,7 +3027,7 @@ Access method: heap (4 rows) \dt+ - List of relations + List of tables Schema | Name | Type | Owner | Persistence | Access method | Size | Description -----------------+---------------+-------+----------------------+-------------+---------------+---------+------------- tableam_display | tbl_heap | table | regress_display_role | permanent | heap | 0 bytes | @@ -2923,7 +3035,7 @@ Access method: heap (2 rows) \dm+ - List of relations + List of materialized views Schema | Name | Type | Owner | Persistence | Access method | Size | Description -----------------+--------------------+-------------------+----------------------+-------------+---------------+---------+------------- tableam_display | mat_view_heap_psql | materialized view | regress_display_role | permanent | heap_psql | 0 bytes | @@ -2931,7 +3043,7 @@ Access method: heap -- But not for views and sequences. \dv+ - List of relations + List of views Schema | Name | Type | Owner | Persistence | Size | Description -----------------+----------------+------+----------------------+-------------+---------+------------- tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | @@ -2948,6 +3060,49 @@ Access method: heap tableam_display | view_heap_psql | view | regress_display_role | permanent | 0 bytes | (4 rows) +-- \d with 'x' enables expanded mode, but only without a pattern +\d+x tbl_heap + Table "tableam_display.tbl_heap" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+----------------+-----------+----------+---------+----------+--------------+------------- + f1 | integer | | | | plain | | + f2 | character(100) | | | | extended | | + +\d+x +List of relations +-[ RECORD 1 ]--------------------- +Schema | tableam_display +Name | mat_view_heap_psql +Type | materialized view +Owner | regress_display_role +Persistence | permanent +Size | 0 bytes +Description | +-[ RECORD 2 ]--------------------- +Schema | tableam_display +Name | tbl_heap +Type | table +Owner | regress_display_role +Persistence | permanent +Size | 0 bytes +Description | +-[ RECORD 3 ]--------------------- +Schema | tableam_display +Name | tbl_heap_psql +Type | table +Owner | regress_display_role +Persistence | permanent +Size | 0 bytes +Description | +-[ RECORD 4 ]--------------------- +Schema | tableam_display +Name | view_heap_psql +Type | view +Owner | regress_display_role +Persistence | permanent +Size | 0 bytes +Description | + RESET ROLE; RESET search_path; DROP SCHEMA tableam_display CASCADE; @@ -4507,9 +4662,11 @@ bar 'bar' "bar" \pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" \a SELECT $1 \bind 1 \g + \bind_named stmt1 1 2 \g \C arg1 \c arg1 arg2 arg3 arg4 \cd arg1 + \close stmt1 \conninfo \copy arg1 arg2 arg3 arg4 arg5 arg6 \copyright @@ -4521,11 +4678,15 @@ bar 'bar' "bar" \echo arg1 arg2 arg3 arg4 arg5 \echo arg1 \encoding arg1 + \endpipeline \errverbose \f arg1 + \flush + \flushrequest \g arg1 \gx arg1 \gexec + \getresults SELECT 1 AS one \gset \h \? @@ -4538,16 +4699,20 @@ invalid command \lo \lo_list \o arg1 \p + SELECT 1 \parse \password arg1 \prompt arg1 arg2 \pset arg1 arg2 \q \reset \s arg1 + \sendpipeline \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \setenv arg1 arg2 \sf whole_line \sv whole_line + \startpipeline + \syncpipeline \t arg1 \T arg1 \timing arg1 @@ -5082,31 +5247,36 @@ List of access methods btree | integer_ops | smallint, integer, bigint (1 row) -\dAo+ btree float_ops - List of operators of operator families - AM | Operator family | Operator | Strategy | Purpose | Sort opfamily --------+-----------------+---------------------------------------+----------+---------+--------------- - btree | float_ops | <(double precision,double precision) | 1 | search | - btree | float_ops | <=(double precision,double precision) | 2 | search | - btree | float_ops | =(double precision,double precision) | 3 | search | - btree | float_ops | >=(double precision,double precision) | 4 | search | - btree | float_ops | >(double precision,double precision) | 5 | search | - btree | float_ops | <(real,real) | 1 | search | - btree | float_ops | <=(real,real) | 2 | search | - btree | float_ops | =(real,real) | 3 | search | - btree | float_ops | >=(real,real) | 4 | search | - btree | float_ops | >(real,real) | 5 | search | - btree | float_ops | <(double precision,real) | 1 | search | - btree | float_ops | <=(double precision,real) | 2 | search | - btree | float_ops | =(double precision,real) | 3 | search | - btree | float_ops | >=(double precision,real) | 4 | search | - btree | float_ops | >(double precision,real) | 5 | search | - btree | float_ops | <(real,double precision) | 1 | search | - btree | float_ops | <=(real,double precision) | 2 | search | - btree | float_ops | =(real,double precision) | 3 | search | - btree | float_ops | >=(real,double precision) | 4 | search | - btree | float_ops | >(real,double precision) | 5 | search | -(20 rows) +\dAo+ btree array_ops|float_ops + List of operators of operator families + AM | Operator family | Operator | Strategy | Purpose | Sort opfamily | Leakproof? +-------+-----------------+---------------------------------------+----------+---------+---------------+------------ + btree | array_ops | <(anyarray,anyarray) | 1 | search | | no + btree | array_ops | <=(anyarray,anyarray) | 2 | search | | no + btree | array_ops | =(anyarray,anyarray) | 3 | search | | no + btree | array_ops | >=(anyarray,anyarray) | 4 | search | | no + btree | array_ops | >(anyarray,anyarray) | 5 | search | | no + btree | float_ops | <(double precision,double precision) | 1 | search | | yes + btree | float_ops | <=(double precision,double precision) | 2 | search | | yes + btree | float_ops | =(double precision,double precision) | 3 | search | | yes + btree | float_ops | >=(double precision,double precision) | 4 | search | | yes + btree | float_ops | >(double precision,double precision) | 5 | search | | yes + btree | float_ops | <(real,real) | 1 | search | | yes + btree | float_ops | <=(real,real) | 2 | search | | yes + btree | float_ops | =(real,real) | 3 | search | | yes + btree | float_ops | >=(real,real) | 4 | search | | yes + btree | float_ops | >(real,real) | 5 | search | | yes + btree | float_ops | <(double precision,real) | 1 | search | | yes + btree | float_ops | <=(double precision,real) | 2 | search | | yes + btree | float_ops | =(double precision,real) | 3 | search | | yes + btree | float_ops | >=(double precision,real) | 4 | search | | yes + btree | float_ops | >(double precision,real) | 5 | search | | yes + btree | float_ops | <(real,double precision) | 1 | search | | yes + btree | float_ops | <=(real,double precision) | 2 | search | | yes + btree | float_ops | =(real,double precision) | 3 | search | | yes + btree | float_ops | >=(real,double precision) | 4 | search | | yes + btree | float_ops | >(real,double precision) | 5 | search | | yes +(25 rows) \dAo * pg_catalog.jsonb_path_ops List of operators of operator families @@ -5131,6 +5301,30 @@ List of access methods btree | float_ops | real | double precision | 3 | in_range(real,real,double precision,boolean,boolean) (8 rows) +\dApx+ btree time_ops +List of support functions of operator families +-[ RECORD 1 ]---------+--------------------------------------------------------------------------------- +AM | btree +Operator family | time_ops +Registered left type | time without time zone +Registered right type | time without time zone +Number | 1 +Function | time_cmp(time without time zone,time without time zone) +-[ RECORD 2 ]---------+--------------------------------------------------------------------------------- +AM | btree +Operator family | time_ops +Registered left type | time without time zone +Registered right type | time without time zone +Number | 4 +Function | btequalimage(oid) +-[ RECORD 3 ]---------+--------------------------------------------------------------------------------- +AM | btree +Operator family | time_ops +Registered left type | time without time zone +Registered right type | interval +Number | 3 +Function | in_range(time without time zone,time without time zone,interval,boolean,boolean) + \dAp * pg_catalog.uuid_ops List of support functions of operator families AM | Operator family | Registered left type | Registered right type | Number | Function @@ -5138,9 +5332,10 @@ List of access methods btree | uuid_ops | uuid | uuid | 1 | uuid_cmp btree | uuid_ops | uuid | uuid | 2 | uuid_sortsupport btree | uuid_ops | uuid | uuid | 4 | btequalimage + btree | uuid_ops | uuid | uuid | 6 | uuid_skipsupport hash | uuid_ops | uuid | uuid | 1 | uuid_hash hash | uuid_ops | uuid | uuid | 2 | uuid_hash_extended -(5 rows) +(6 rows) -- check \dconfig set work_mem = 10240; @@ -5286,12 +5481,12 @@ create function psql_df_plpgsql () as $$ begin return; end; $$; comment on function psql_df_plpgsql () is 'some comment'; \df+ psql_df_* - List of functions - Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Access privileges | Language | Internal name | Description ---------+------------------+------------------+---------------------+------+------------+----------+-------------------+----------+-------------------+----------+---------------+-------------- - public | psql_df_internal | double precision | double precision | func | immutable | safe | regress_psql_user | invoker | | internal | dsin | - public | psql_df_plpgsql | void | | func | volatile | unsafe | regress_psql_user | invoker | | plpgsql | | some comment - public | psql_df_sql | integer | x integer | func | volatile | unsafe | regress_psql_user | definer | | sql | | + List of functions + Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Leakproof? | Access privileges | Language | Internal name | Description +--------+------------------+------------------+---------------------+------+------------+----------+-------------------+----------+------------+-------------------+----------+---------------+-------------- + public | psql_df_internal | double precision | double precision | func | immutable | safe | regress_psql_user | invoker | no | | internal | dsin | + public | psql_df_plpgsql | void | | func | volatile | unsafe | regress_psql_user | invoker | no | | plpgsql | | some comment + public | psql_df_sql | integer | x integer | func | volatile | unsafe | regress_psql_user | definer | no | | sql | | (3 rows) rollback; @@ -6057,7 +6252,7 @@ List of access methods (0 rows) \dt "no.such.table.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6129,31 +6324,31 @@ List of access methods (0 rows) \di "no.such.index.relation" - List of relations + List of indexes Schema | Name | Type | Owner | Table --------+------+------+-------+------- (0 rows) \dm "no.such.materialized.view" - List of relations + List of materialized views Schema | Name | Type | Owner --------+------+------+------- (0 rows) \ds "no.such.relation" - List of relations + List of sequences Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dt "no.such.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dv "no.such.relation" - List of relations + List of views Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6248,9 +6443,9 @@ List of schemas (0 rows) \dRp "no.such.publication" - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root -------+-------+------------+---------+---------+---------+-----------+---------- + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +------+-------+------------+---------+---------+---------+-----------+-------------------+---------- (0 rows) \dRs "no.such.subscription" @@ -6266,9 +6461,9 @@ List of schemas (0 rows) \dx "no.such.installed.extension" - List of installed extensions - Name | Version | Schema | Description -------+---------+--------+------------- + List of installed extensions + Name | Version | Default version | Schema | Description +------+---------+-----------------+--------+------------- (0 rows) \dX "no.such.extended.statistics" @@ -6287,7 +6482,7 @@ List of schemas \dA "no.such.schema"."no.such.access.method" improper qualified name (too many dotted names): "no.such.schema"."no.such.access.method" \dt "no.such.schema"."no.such.table.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6339,31 +6534,31 @@ improper qualified name (too many dotted names): "no.such.schema"."no.such.table (0 rows) \di "no.such.schema"."no.such.index.relation" - List of relations + List of indexes Schema | Name | Type | Owner | Table --------+------+------+-------+------- (0 rows) \dm "no.such.schema"."no.such.materialized.view" - List of relations + List of materialized views Schema | Name | Type | Owner --------+------+------+------- (0 rows) \ds "no.such.schema"."no.such.relation" - List of relations + List of sequences Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dt "no.such.schema"."no.such.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dv "no.such.schema"."no.such.relation" - List of relations + List of views Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6454,7 +6649,7 @@ improper qualified name (too many dotted names): "no.such.schema"."no.such.insta improper qualified name (too many dotted names): "no.such.schema"."no.such.event.trigger" -- again, but with current database and dotted schema qualifications. \dt regression."no.such.schema"."no.such.table.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6490,31 +6685,31 @@ improper qualified name (too many dotted names): "no.such.schema"."no.such.event (0 rows) \di regression."no.such.schema"."no.such.index.relation" - List of relations + List of indexes Schema | Name | Type | Owner | Table --------+------+------+-------+------- (0 rows) \dm regression."no.such.schema"."no.such.materialized.view" - List of relations + List of materialized views Schema | Name | Type | Owner --------+------+------+------- (0 rows) \ds regression."no.such.schema"."no.such.relation" - List of relations + List of sequences Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dt regression."no.such.schema"."no.such.relation" - List of relations + List of tables Schema | Name | Type | Owner --------+------+------+------- (0 rows) \dv regression."no.such.schema"."no.such.relation" - List of relations + List of views Schema | Name | Type | Owner --------+------+------+------- (0 rows) @@ -6689,10 +6884,10 @@ REVOKE ALL ON DOMAIN regress_zeropriv_domain FROM CURRENT_USER, PUBLIC; CREATE PROCEDURE regress_zeropriv_proc() LANGUAGE sql AS ''; REVOKE ALL ON PROCEDURE regress_zeropriv_proc() FROM CURRENT_USER, PUBLIC; \df+ regress_zeropriv_proc - List of functions - Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Access privileges | Language | Internal name | Description ---------+-----------------------+------------------+---------------------+------+------------+----------+------------------------+----------+-------------------+----------+---------------+------------- - public | regress_zeropriv_proc | | | proc | volatile | unsafe | regress_zeropriv_owner | invoker | (none) | sql | | + List of functions + Schema | Name | Result data type | Argument data types | Type | Volatility | Parallel | Owner | Security | Leakproof? | Access privileges | Language | Internal name | Description +--------+-----------------------+------------------+---------------------+------+------------+----------+------------------------+----------+------------+-------------------+----------+---------------+------------- + public | regress_zeropriv_proc | | | proc | volatile | unsafe | regress_zeropriv_owner | invoker | no | (none) | sql | | (1 row) CREATE TABLE regress_zeropriv_tbl (a int); @@ -6724,5 +6919,15 @@ CREATE TABLE defprivs (a int); public | defprivs | table | (default) | | (1 row) +\zx defprivs +Access privileges +-[ RECORD 1 ]-----+---------- +Schema | public +Name | defprivs +Type | table +Access privileges | (default) +Column privileges | +Policies | + \pset null '' DROP TABLE defprivs; diff --git a/src/test/regress/expected/psql_pipeline.out b/src/test/regress/expected/psql_pipeline.out new file mode 100644 index 0000000000000..e78e6bfa0ad35 --- /dev/null +++ b/src/test/regress/expected/psql_pipeline.out @@ -0,0 +1,768 @@ +-- +-- Tests using psql pipelining +-- +CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); +-- Single query +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline + ?column? +---------- + val1 +(1 row) + +\startpipeline +SELECT 'val1'; +\endpipeline + ?column? +---------- + val1 +(1 row) + +-- Multiple queries +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT 'val4'; +SELECT 'val5', 'val6'; +\endpipeline + ?column? +---------- + val1 +(1 row) + + ?column? | ?column? +----------+---------- + val2 | val3 +(1 row) + + ?column? | ?column? +----------+---------- + val2 | val3 +(1 row) + + ?column? +---------- + val4 +(1 row) + + ?column? | ?column? +----------+---------- + val5 | val6 +(1 row) + +-- Multiple queries in single line, separated by semicolons +\startpipeline +SELECT 1; SELECT 2; SELECT 3 +; +\echo :PIPELINE_COMMAND_COUNT +3 +\endpipeline + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + + ?column? +---------- + 3 +(1 row) + +-- Test \flush +\startpipeline +\flush +SELECT $1 \bind 'val1' \sendpipeline +\flush +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +\flush +SELECT 'val4'; +SELECT 'val5', 'val6'; +\endpipeline + ?column? +---------- + val1 +(1 row) + + ?column? | ?column? +----------+---------- + val2 | val3 +(1 row) + + ?column? | ?column? +----------+---------- + val2 | val3 +(1 row) + + ?column? +---------- + val4 +(1 row) + + ?column? | ?column? +----------+---------- + val5 | val6 +(1 row) + +-- Send multiple syncs +\startpipeline +\echo :PIPELINE_COMMAND_COUNT +0 +\echo :PIPELINE_SYNC_COUNT +0 +\echo :PIPELINE_RESULT_COUNT +0 +SELECT $1 \bind 'val1' \sendpipeline +\syncpipeline +\syncpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +\syncpipeline +SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline +\echo :PIPELINE_COMMAND_COUNT +1 +\echo :PIPELINE_SYNC_COUNT +3 +\echo :PIPELINE_RESULT_COUNT +2 +SELECT 'val7'; +\syncpipeline +\syncpipeline +SELECT 'val8'; +\syncpipeline +SELECT 'val9'; +\echo :PIPELINE_COMMAND_COUNT +1 +\echo :PIPELINE_SYNC_COUNT +6 +\echo :PIPELINE_RESULT_COUNT +5 +\endpipeline + ?column? +---------- + val1 +(1 row) + + ?column? | ?column? +----------+---------- + val2 | val3 +(1 row) + + ?column? | ?column? +----------+---------- + val4 | val5 +(1 row) + + ?column? +---------- + val7 +(1 row) + + ?column? +---------- + val8 +(1 row) + + ?column? +---------- + val9 +(1 row) + +-- Query terminated with a semicolon replaces an unnamed prepared +-- statement. +\startpipeline +SELECT $1 \parse '' +SELECT 1; +\bind_named '' +\endpipeline + ?column? +---------- + 1 +(1 row) + +-- Extended query is appended to pipeline by a semicolon after a +-- newline. +\startpipeline +SELECT $1 \bind 1 +; +SELECT 2; +\endpipeline + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + +-- \startpipeline should not have any effect if already in a pipeline. +\startpipeline +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline + ?column? +---------- + val1 +(1 row) + +-- Convert an implicit transaction block to an explicit transaction block. +\startpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline +ROLLBACK \bind \sendpipeline +\endpipeline +-- Multiple explicit transactions +\startpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +COMMIT \bind \sendpipeline +\endpipeline +-- Use \parse and \bind_named +\startpipeline +SELECT $1 \parse '' +SELECT $1, $2 \parse '' +SELECT $2 \parse pipeline_1 +\bind_named '' 1 2 \sendpipeline +\bind_named pipeline_1 2 \sendpipeline +\endpipeline +ERROR: could not determine data type of parameter $1 +-- \getresults displays all results preceding a \flushrequest. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\flushrequest +\getresults + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + +\endpipeline +-- \getresults displays all results preceding a \syncpipeline. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\syncpipeline +\getresults + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + +\endpipeline +-- \getresults immediately returns if there is no result to fetch. +\startpipeline +\getresults +No pending results to get +SELECT $1 \bind 2 \sendpipeline +\getresults +No pending results to get +\flushrequest +\endpipeline + ?column? +---------- + 2 +(1 row) + +\getresults +No pending results to get +-- \getresults only fetches results preceding a \flushrequest. +\startpipeline +SELECT $1 \bind 2 \sendpipeline +\flushrequest +SELECT $1 \bind 2 \sendpipeline +\getresults + ?column? +---------- + 2 +(1 row) + +\endpipeline + ?column? +---------- + 2 +(1 row) + +-- \getresults only fetches results preceding a \syncpipeline. +\startpipeline +SELECT $1 \bind 2 \sendpipeline +\syncpipeline +SELECT $1 \bind 2 \sendpipeline +\getresults + ?column? +---------- + 2 +(1 row) + +\endpipeline + ?column? +---------- + 2 +(1 row) + +-- Use pipeline with chunked results for both \getresults and \endpipeline. +\startpipeline +\set FETCH_COUNT 10 +SELECT $1 \bind 2 \sendpipeline +\flushrequest +\getresults + ?column? +---------- + 2 +(1 row) + +SELECT $1 \bind 2 \sendpipeline +\endpipeline + ?column? +---------- + 2 +(1 row) + +\unset FETCH_COUNT +-- \getresults with specific number of requested results. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline +\echo :PIPELINE_SYNC_COUNT +0 +\syncpipeline +\echo :PIPELINE_SYNC_COUNT +1 +\echo :PIPELINE_RESULT_COUNT +3 +\getresults 1 + ?column? +---------- + 1 +(1 row) + +\echo :PIPELINE_RESULT_COUNT +2 +SELECT $1 \bind 4 \sendpipeline +\getresults 3 + ?column? +---------- + 2 +(1 row) + + ?column? +---------- + 3 +(1 row) + +\echo :PIPELINE_RESULT_COUNT +0 +\endpipeline + ?column? +---------- + 4 +(1 row) + +-- \syncpipeline count as one command to fetch for \getresults. +\startpipeline +\syncpipeline +\syncpipeline +SELECT $1 \bind 1 \sendpipeline +\flushrequest +\getresults 2 +\getresults 1 + ?column? +---------- + 1 +(1 row) + +\endpipeline +-- \getresults 0 should get all the results. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline +\syncpipeline +\getresults 0 + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + + ?column? +---------- + 3 +(1 row) + +\endpipeline +-- +-- Pipeline errors +-- +-- \endpipeline outside of pipeline should fail +\endpipeline +cannot send pipeline when not in pipeline mode +-- After an aborted pipeline, commands after a \syncpipeline should be +-- displayed. +\startpipeline +SELECT $1 \bind \sendpipeline +\syncpipeline +SELECT $1 \bind 1 \sendpipeline +\endpipeline +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 + ?column? +---------- + 1 +(1 row) + +-- For an incorrect number of parameters, the pipeline is aborted and +-- the following queries will not be executed. +\startpipeline +SELECT \bind 'val1' \sendpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline +ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0 +-- Using a semicolon with a parameter triggers an error and aborts +-- the pipeline. +\startpipeline +SELECT $1; +SELECT 1; +\endpipeline +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 +-- An explicit transaction with an error needs to be rollbacked after +-- the pipeline. +\startpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +\endpipeline +ERROR: duplicate key value violates unique constraint "psql_pipeline_pkey" +DETAIL: Key (a)=(1) already exists. +ROLLBACK; +-- \watch is not allowed in a pipeline. +\startpipeline +SELECT \bind \sendpipeline +\watch 1 +\watch not allowed in pipeline mode +\endpipeline +-- +(1 row) + +-- \gdesc should fail as synchronous commands are not allowed in a pipeline, +-- and the pipeline should still be usable. +\startpipeline +SELECT $1 \bind 1 \gdesc +synchronous command execution functions are not allowed in pipeline mode +SELECT $1 \bind 1 \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + +-- \gset is not allowed in a pipeline, pipeline should still be usable. +\startpipeline +SELECT $1 as i, $2 as j \parse '' +SELECT $1 as k, $2 as l \parse 'second' +\bind_named '' 1 2 \gset +\gset not allowed in pipeline mode +\bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j +\gset not allowed in pipeline mode +\bind_named '' 1 2 \sendpipeline +\endpipeline + i | j +---+--- + 1 | 2 +(1 row) + +-- \g and \gx are not allowed, pipeline should still be usable. +\startpipeline +SELECT $1 \bind 1 \g +\g not allowed in pipeline mode +SELECT $1 \bind 1 \g (format=unaligned tuples_only=on) +\g not allowed in pipeline mode +SELECT $1 \bind 1 \gx +\gx not allowed in pipeline mode +SELECT $1 \bind 1 \gx (format=unaligned tuples_only=on) +\gx not allowed in pipeline mode +\reset +SELECT $1 \bind 1 \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + +-- \g and \gx warnings should be emitted in an aborted pipeline, with +-- pipeline still usable. +\startpipeline +SELECT $1 \bind \sendpipeline +\flushrequest +\getresults +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 +SELECT $1 \bind 1 \g +\g not allowed in pipeline mode +SELECT $1 \bind 1 \gx +\gx not allowed in pipeline mode +\endpipeline +-- \sendpipeline is not allowed outside of a pipeline +\sendpipeline +\sendpipeline not allowed outside of pipeline mode +SELECT $1 \bind 1 \sendpipeline +\sendpipeline not allowed outside of pipeline mode +\reset +-- \sendpipeline is not allowed if not preceded by \bind or \bind_named +\startpipeline +\sendpipeline +\sendpipeline must be used after \bind or \bind_named +SELECT 1 \sendpipeline +\sendpipeline must be used after \bind or \bind_named +\endpipeline +-- \gexec is not allowed, pipeline should still be usable. +\startpipeline +SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' +\bind_named insert_stmt \gexec +\gexec not allowed in pipeline mode +\bind_named insert_stmt \sendpipeline +SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline +\endpipeline + ?column? +------------------------------------------------------------ + INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10) +(1 row) + + count +------- + 1 +(1 row) + +-- After an error, pipeline is aborted and requires \syncpipeline to be +-- reusable. +\startpipeline +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +\flushrequest +\getresults +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 +-- Pipeline is aborted. +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +-- Sync allows pipeline to recover. +\syncpipeline +\getresults +Pipeline aborted, command did not run +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +\flushrequest +\getresults + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 1 +(1 row) + +\endpipeline +-- In an aborted pipeline, \getresults 1 aborts commands one at a time. +\startpipeline +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\syncpipeline +\getresults 1 +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 +\getresults 1 +Pipeline aborted, command did not run +\getresults 1 +Pipeline aborted, command did not run +\getresults 1 +Pipeline aborted, command did not run +\getresults 1 +\endpipeline +-- Test chunked results with an aborted pipeline. +\startpipeline +\set FETCH_COUNT 10 +SELECT $1 \bind \sendpipeline +\flushrequest +\getresults +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 +SELECT $1 \bind \sendpipeline +\endpipeline +fetching results in chunked mode failed +Pipeline aborted, command did not run +\unset FETCH_COUNT +-- \getresults returns an error when an incorrect number is provided. +\startpipeline +\getresults -1 +\getresults: invalid number of requested results +\endpipeline +-- \getresults when there is no result should not impact the next +-- query executed. +\getresults 1 +No pending results to get +select 1; + ?column? +---------- + 1 +(1 row) + +-- Error messages accumulate and are repeated. +\startpipeline +SELECT 1 \bind \sendpipeline +\gdesc +synchronous command execution functions are not allowed in pipeline mode +\gdesc +synchronous command execution functions are not allowed in pipeline mode +synchronous command execution functions are not allowed in pipeline mode +\endpipeline + ?column? +---------- + 1 +(1 row) + +-- +-- Pipelines and transaction blocks +-- +-- SET LOCAL will issue a warning when modifying a GUC outside of a +-- transaction block. The change will still be valid as a pipeline +-- runs within an implicit transaction block. Sending a sync will +-- commit the implicit transaction block. The first command after a +-- sync will not be seen as belonging to a pipeline. +\startpipeline +SET LOCAL statement_timeout='1h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline +\syncpipeline +SHOW statement_timeout \bind \sendpipeline +SET LOCAL statement_timeout='2h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline +\endpipeline +WARNING: SET LOCAL can only be used in transaction blocks + statement_timeout +------------------- + 1h +(1 row) + + statement_timeout +------------------- + 0 +(1 row) + + statement_timeout +------------------- + 2h +(1 row) + +-- REINDEX CONCURRENTLY fails if not the first command in a pipeline. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + +ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block +-- REINDEX CONCURRENTLY works if it is the first command in a pipeline. +\startpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + ?column? +---------- + 2 +(1 row) + +-- Subtransactions are not allowed in a pipeline. +\startpipeline +SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +ROLLBACK TO SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline +ERROR: SAVEPOINT can only be used in transaction blocks +-- LOCK fails as the first command in a pipeline, as not seen in an +-- implicit transaction block. +\startpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline +ERROR: LOCK TABLE can only be used in transaction blocks +-- LOCK succeeds as it is not the first command in a pipeline, +-- seen in an implicit transaction block. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + 2 +(1 row) + +-- VACUUM works as the first command in a pipeline. +\startpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline +-- VACUUM fails when not the first command in a pipeline. +\startpipeline +SELECT 1 \bind \sendpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + +ERROR: VACUUM cannot run inside a transaction block +-- VACUUM works after a \syncpipeline. +\startpipeline +SELECT 1 \bind \sendpipeline +\syncpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline + ?column? +---------- + 1 +(1 row) + +-- Clean up +DROP TABLE psql_pipeline; diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 30b637113404f..4de96c04f9de4 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -17,7 +17,7 @@ SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p; (1 row) SET client_min_messages = 'ERROR'; -CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); +CREATE PUBLICATION testpub_ins_trunct WITH (publish = insert); RESET client_min_messages; ALTER PUBLICATION testpub_default SET (publish = update); -- error cases @@ -29,21 +29,27 @@ CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publis ERROR: conflicting or redundant options LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi... ^ +CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none); +ERROR: conflicting or redundant options +LINE 1: ...pub_xxx WITH (publish_generated_columns = stored, publish_ge... + ^ +CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo); +ERROR: publish_generated_columns requires a "none" or "stored" value \dRp - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------+--------------------------+------------+---------+---------+---------+-----------+---------- - testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f - testpub_default | regress_publication_user | f | f | t | f | f | f + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + testpub_default | regress_publication_user | f | f | t | f | f | none | f + testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f (2 rows) ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete'); \dRp - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------+--------------------------+------------+---------+---------+---------+-----------+---------- - testpib_ins_trunct | regress_publication_user | f | t | f | f | f | f - testpub_default | regress_publication_user | f | t | t | t | f | f + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + testpub_default | regress_publication_user | f | t | t | t | f | none | f + testpub_ins_trunct | regress_publication_user | f | t | f | f | f | none | f (2 rows) --- adding tables @@ -87,10 +93,10 @@ RESET client_min_messages; -- should be able to add schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_tbl1" Tables from schemas: @@ -99,20 +105,20 @@ Tables from schemas: -- should be able to drop schema from 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_tbl1" -- should be able to set schema to 'FOR TABLE' publication ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test; \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test" @@ -123,10 +129,10 @@ CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test; CREATE PUBLICATION testpub_for_tbl_schema FOR TABLES IN SCHEMA pub_test, TABLE pub_test.testpub_nopk; RESET client_min_messages; \dRp+ testpub_for_tbl_schema - Publication testpub_for_tbl_schema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_for_tbl_schema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test.testpub_nopk" Tables from schemas: @@ -144,10 +150,10 @@ LINE 1: ...CATION testpub_parsertst FOR TABLES IN SCHEMA foo, test.foo; -- should be able to add a table of the same schema to the schema publication ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk; \dRp+ testpub_forschema - Publication testpub_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test.testpub_nopk" Tables from schemas: @@ -156,10 +162,10 @@ Tables from schemas: -- should be able to drop the table ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk; \dRp+ testpub_forschema - Publication testpub_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test" @@ -170,10 +176,10 @@ ERROR: relation "testpub_nopk" is not part of the publication -- should be able to set table to schema publication ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk; \dRp+ testpub_forschema - Publication testpub_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test.testpub_nopk" @@ -193,12 +199,14 @@ Indexes: "testpub_tbl2_pkey" PRIMARY KEY, btree (id) Publications: "testpub_foralltables" +Not-null constraints: + "testpub_tbl2_id_not_null" NOT NULL "id" \dRp+ testpub_foralltables - Publication testpub_foralltables - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | t | t | t | f | f | f + Publication testpub_foralltables + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | t | t | t | f | f | none | f (1 row) DROP TABLE testpub_tbl2; @@ -210,19 +218,19 @@ CREATE PUBLICATION testpub3 FOR TABLE testpub_tbl3; CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl3; RESET client_min_messages; \dRp+ testpub3 - Publication testpub3 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub3 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_tbl3" "public.testpub_tbl3a" \dRp+ testpub4 - Publication testpub4 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub4 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_tbl3" @@ -243,10 +251,10 @@ UPDATE testpub_parted1 SET a = 1; -- only parent is listed as being in publication, not the partition ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted; \dRp+ testpub_forparted - Publication testpub_forparted - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_forparted + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_parted" @@ -261,10 +269,10 @@ ALTER TABLE testpub_parted DETACH PARTITION testpub_parted1; UPDATE testpub_parted1 SET a = 1; ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true); \dRp+ testpub_forparted - Publication testpub_forparted - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | t + Publication testpub_forparted + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | t Tables: "public.testpub_parted" @@ -293,10 +301,10 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub5 FOR TABLE testpub_rf_tbl1, testpub_rf_tbl2 WHERE (c <> 'test' AND d < 5) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl1" "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5)) @@ -309,10 +317,10 @@ Tables: ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 2000); \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl1" "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5)) @@ -328,10 +336,10 @@ Publications: ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2; \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl1" "public.testpub_rf_tbl3" WHERE ((e > 1000) AND (e < 2000)) @@ -339,10 +347,10 @@ Tables: -- remove testpub_rf_tbl1 and add testpub_rf_tbl3 again (another WHERE expression) ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500); \dRp+ testpub5 - Publication testpub5 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub5 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500)) @@ -375,10 +383,10 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax1 FOR TABLE testpub_rf_tbl1, ONLY testpub_rf_tbl3 WHERE (e < 999) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub_syntax1 - Publication testpub_syntax1 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub_syntax1 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl1" "public.testpub_rf_tbl3" WHERE (e < 999) @@ -388,10 +396,10 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_syntax2 FOR TABLE testpub_rf_tbl1, testpub_rf_schema1.testpub_rf_tbl5 WHERE (h < 999) WITH (publish = 'insert'); RESET client_min_messages; \dRp+ testpub_syntax2 - Publication testpub_syntax2 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | f | f + Publication testpub_syntax2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | f | none | f Tables: "public.testpub_rf_tbl1" "testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999) @@ -434,7 +442,7 @@ LINE 1: ...ICATION testpub6 FOR TABLE testpub_rf_tbl3 WHERE (e =#> 27); ^ DETAIL: User-defined operators are not allowed. -- fail - user-defined functions are not allowed -CREATE FUNCTION testpub_rf_func2() RETURNS integer AS $$ BEGIN RETURN 123; END; $$ LANGUAGE plpgsql; +CREATE FUNCTION testpub_rf_func2() RETURNS integer IMMUTABLE AS $$ BEGIN RETURN 123; END; $$ LANGUAGE plpgsql; ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl1 WHERE (a >= testpub_rf_func2()); ERROR: invalid publication WHERE expression LINE 1: ...ON testpub5 ADD TABLE testpub_rf_tbl1 WHERE (a >= testpub_rf... @@ -506,26 +514,42 @@ CREATE PUBLICATION testpub6 FOR TABLES IN SCHEMA testpub_rf_schema2; ALTER PUBLICATION testpub6 SET TABLES IN SCHEMA testpub_rf_schema2, TABLE testpub_rf_schema2.testpub_rf_tbl6 WHERE (i < 99); RESET client_min_messages; \dRp+ testpub6 - Publication testpub6 - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub6 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99) Tables from schemas: "testpub_rf_schema2" +-- fail - virtual generated column uses user-defined function +CREATE TABLE testpub_rf_tbl6 (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * testpub_rf_func2()) VIRTUAL); +CREATE PUBLICATION testpub7 FOR TABLE testpub_rf_tbl6 WHERE (y > 100); +ERROR: invalid publication WHERE expression +DETAIL: User-defined or built-in mutable functions are not allowed. +-- test that SET EXPRESSION is rejected, because it could affect a row filter +SET client_min_messages = 'ERROR'; +CREATE TABLE testpub_rf_tbl7 (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * 111) VIRTUAL); +CREATE PUBLICATION testpub8 FOR TABLE testpub_rf_tbl7 WHERE (y > 100); +ALTER TABLE testpub_rf_tbl7 ALTER COLUMN y SET EXPRESSION AS (x * testpub_rf_func2()); +ERROR: ALTER TABLE / SET EXPRESSION is not supported for virtual generated columns on tables that are part of a publication +DETAIL: Column "y" of relation "testpub_rf_tbl7" is a virtual generated column. +RESET client_min_messages; DROP TABLE testpub_rf_tbl1; DROP TABLE testpub_rf_tbl2; DROP TABLE testpub_rf_tbl3; DROP TABLE testpub_rf_tbl4; DROP TABLE testpub_rf_tbl5; +DROP TABLE testpub_rf_tbl6; DROP TABLE testpub_rf_schema1.testpub_rf_tbl5; DROP TABLE testpub_rf_schema2.testpub_rf_tbl6; DROP SCHEMA testpub_rf_schema1; DROP SCHEMA testpub_rf_schema2; DROP PUBLICATION testpub5; DROP PUBLICATION testpub6; +DROP PUBLICATION testpub8; +DROP TABLE testpub_rf_tbl7; DROP OPERATOR =#>(integer, integer); DROP FUNCTION testpub_rf_func1(integer, integer); DROP FUNCTION testpub_rf_func2(); @@ -664,6 +688,50 @@ DROP TABLE rf_tbl_abcd_pk; DROP TABLE rf_tbl_abcd_nopk; DROP TABLE rf_tbl_abcd_part_pk; -- ====================================================== +-- ====================================================== +-- Tests with generated column +SET client_min_messages = 'ERROR'; +-- stored +CREATE TABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) STORED NOT NULL); +CREATE UNIQUE INDEX testpub_gencol_idx ON testpub_gencol (b); +ALTER TABLE testpub_gencol REPLICA IDENTITY USING index testpub_gencol_idx; +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY index. +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +ERROR: cannot update table "testpub_gencol" +DETAIL: Replica identity must not contain unpublished generated columns. +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY. +ALTER TABLE testpub_gencol REPLICA IDENTITY FULL; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +ERROR: cannot update table "testpub_gencol" +DETAIL: Replica identity must not contain unpublished generated columns. +DROP PUBLICATION pub_gencol; +-- ok - generated column "b" is published explicitly +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored); +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +DROP PUBLICATION pub_gencol; +DROP TABLE testpub_gencol; +-- virtual +CREATE TABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) VIRTUAL); +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol; +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY. +ALTER TABLE testpub_gencol REPLICA IDENTITY FULL; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +ERROR: cannot update table "testpub_gencol" +DETAIL: Replica identity must not contain unpublished generated columns. +DROP PUBLICATION pub_gencol; +-- error - "stored" setting does not affect virtual column +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored); +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +ERROR: cannot update table "testpub_gencol" +DETAIL: Replica identity must not contain unpublished generated columns. +DROP PUBLICATION pub_gencol; +DROP TABLE testpub_gencol; +RESET client_min_messages; +-- ====================================================== -- fail - duplicate tables are not allowed if that table has any column lists SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_dups FOR TABLE testpub_tbl1 (a), testpub_tbl1 WITH (publish = 'insert'); @@ -677,7 +745,9 @@ CREATE PUBLICATION testpub_fortable FOR TABLE testpub_tbl1; CREATE PUBLICATION testpub_fortable_insert WITH (publish = 'insert'); RESET client_min_messages; CREATE TABLE testpub_tbl5 (a int PRIMARY KEY, b text, c text, - d int generated always as (a + length(b)) stored); + d int generated always as (a + length(b)) stored, + e int generated always as (a + length(b)) virtual +); -- error: column "x" does not exist ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, x); ERROR: column "x" of relation "testpub_tbl5" does not exist @@ -687,12 +757,16 @@ UPDATE testpub_tbl5 SET a = 1; ERROR: cannot update table "testpub_tbl5" DETAIL: Column list used by the publication does not cover the replica identity. ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; --- error: generated column "d" can't be in list -ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, d); -ERROR: cannot use generated column "d" in publication column list -- error: system attributes "ctid" not allowed in column list ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, ctid); ERROR: cannot use system column "ctid" in publication column list +ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl1 (id, ctid); +ERROR: cannot use system column "ctid" in publication column list +-- error: duplicates not allowed in column list +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, a); +ERROR: duplicate column "a" in publication column list +ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl5 (a, a); +ERROR: duplicate column "a" in publication column list -- ok ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, c); ALTER TABLE testpub_tbl5 DROP COLUMN c; -- no dice @@ -710,6 +784,12 @@ UPDATE testpub_tbl5 SET a = 1; ERROR: cannot update table "testpub_tbl5" DETAIL: Column list used by the publication does not cover the replica identity. ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; +-- ok: stored generated column "d" can be in the list too +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, d); +ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; +-- error: virtual generated column "e" can't be in list +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, e); +ERROR: cannot use virtual generated column "e" in publication column list -- error: change the replica identity to "b", and column list to (a, c) -- then update fails, because (a, c) does not cover replica identity ALTER TABLE testpub_tbl5 REPLICA IDENTITY USING INDEX testpub_tbl5_b_key; @@ -723,10 +803,10 @@ CREATE PUBLICATION testpub_table_ins WITH (publish = 'insert, truncate'); RESET client_min_messages; ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a); -- ok \dRp+ testpub_table_ins - Publication testpub_table_ins - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | f | f | t | f + Publication testpub_table_ins + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | f | f | t | none | f Tables: "public.testpub_tbl5" (a) @@ -764,6 +844,8 @@ Indexes: "testpub_tbl7_pkey" PRIMARY KEY, btree (a) Publications: "testpub_fortable" (a, b) +Not-null constraints: + "testpub_tbl7_a_not_null" NOT NULL "a" -- ok: the column list is the same, we should skip this table (or at least not fail) ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl7 (a, b); @@ -778,6 +860,8 @@ Indexes: "testpub_tbl7_pkey" PRIMARY KEY, btree (a) Publications: "testpub_fortable" (a, b) +Not-null constraints: + "testpub_tbl7_a_not_null" NOT NULL "a" -- ok: the column list changes, make sure the catalog gets updated ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl7 (a, c); @@ -792,6 +876,8 @@ Indexes: "testpub_tbl7_pkey" PRIMARY KEY, btree (a) Publications: "testpub_fortable" (a, c) +Not-null constraints: + "testpub_tbl7_a_not_null" NOT NULL "a" -- column list for partitioned tables has to cover replica identities for -- all child relations @@ -910,10 +996,10 @@ CREATE TABLE testpub_tbl_both_filters (a int, b int, c int, PRIMARY KEY (a,c)); ALTER TABLE testpub_tbl_both_filters REPLICA IDENTITY USING INDEX testpub_tbl_both_filters_pkey; ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c) WHERE (c != 1); \dRp+ testpub_both_filters - Publication testpub_both_filters - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_both_filters + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1) @@ -928,6 +1014,9 @@ Indexes: "testpub_tbl_both_filters_pkey" PRIMARY KEY, btree (a, c) REPLICA IDENTITY Publications: "testpub_both_filters" (a, c) WHERE (c <> 1) +Not-null constraints: + "testpub_tbl_both_filters_a_not_null" NOT NULL "a" + "testpub_tbl_both_filters_c_not_null" NOT NULL "c" DROP TABLE testpub_tbl_both_filters; DROP PUBLICATION testpub_both_filters; @@ -1118,10 +1207,10 @@ ERROR: relation "testpub_tbl1" is already member of publication "testpub_fortbl CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1; ERROR: publication "testpub_fortbl" already exists \dRp+ testpub_fortbl - Publication testpub_fortbl - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortbl + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test.testpub_nopk" "public.testpub_tbl1" @@ -1133,7 +1222,7 @@ DETAIL: This operation is not supported for views. ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1; ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1; ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk; -ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; +ALTER PUBLICATION testpub_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; \d+ pub_test.testpub_nopk Table "pub_test.testpub_nopk" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description @@ -1141,9 +1230,9 @@ ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tb foo | integer | | | | plain | | bar | integer | | | | plain | | Publications: - "testpib_ins_trunct" "testpub_default" "testpub_fortbl" + "testpub_ins_trunct" \d+ testpub_tbl1 Table "public.testpub_tbl1" @@ -1154,15 +1243,17 @@ Publications: Indexes: "testpub_tbl1_pkey" PRIMARY KEY, btree (id) Publications: - "testpib_ins_trunct" "testpub_default" "testpub_fortbl" + "testpub_ins_trunct" +Not-null constraints: + "testpub_tbl1_id_not_null" NOT NULL "id" \dRp+ testpub_default - Publication testpub_default - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | f | f + Publication testpub_default + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | f | none | f Tables: "pub_test.testpub_nopk" "public.testpub_tbl1" @@ -1180,8 +1271,10 @@ ERROR: relation "testpub_nopk" is not part of the publication Indexes: "testpub_tbl1_pkey" PRIMARY KEY, btree (id) Publications: - "testpib_ins_trunct" "testpub_fortbl" + "testpub_ins_trunct" +Not-null constraints: + "testpub_tbl1_id_not_null" NOT NULL "id" -- verify relation cache invalidation when a primary key is added using -- an existing index @@ -1240,10 +1333,10 @@ REVOKE CREATE ON DATABASE regression FROM regress_publication_user2; DROP TABLE testpub_parted; DROP TABLE testpub_tbl1; \dRp+ testpub_default - Publication testpub_default - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | f | f + Publication testpub_default + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | f | none | f (1 row) -- fail - must be owner of publication @@ -1253,20 +1346,20 @@ ERROR: must be owner of publication testpub_default RESET ROLE; ALTER PUBLICATION testpub_default RENAME TO testpub_foo; \dRp testpub_foo - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root --------------+--------------------------+------------+---------+---------+---------+-----------+---------- - testpub_foo | regress_publication_user | f | t | t | t | f | f + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +-------------+--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + testpub_foo | regress_publication_user | f | t | t | t | f | none | f (1 row) -- rename back to keep the rest simple ALTER PUBLICATION testpub_foo RENAME TO testpub_default; ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2; \dRp testpub_default - List of publications - Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ------------------+---------------------------+------------+---------+---------+---------+-----------+---------- - testpub_default | regress_publication_user2 | f | t | t | t | f | f + List of publications + Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +-----------------+---------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + testpub_default | regress_publication_user2 | f | t | t | t | f | none | f (1 row) -- adding schemas and tables @@ -1282,19 +1375,19 @@ CREATE TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"(id int); SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2, pub_test3; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1308,44 +1401,44 @@ CREATE PUBLICATION testpub6_forschema FOR TABLES IN SCHEMA "CURRENT_SCHEMA", CUR CREATE PUBLICATION testpub_fortable FOR TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"; RESET client_min_messages; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "public" \dRp+ testpub4_forschema - Publication testpub4_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub4_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "CURRENT_SCHEMA" \dRp+ testpub5_forschema - Publication testpub5_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub5_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "CURRENT_SCHEMA" "public" \dRp+ testpub6_forschema - Publication testpub6_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub6_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "CURRENT_SCHEMA" "public" \dRp+ testpub_fortable - Publication testpub_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "CURRENT_SCHEMA.CURRENT_SCHEMA" @@ -1379,10 +1472,10 @@ ERROR: schema "testpub_view" does not exist -- dropping the schema should reflect the change in publication DROP SCHEMA pub_test3; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1390,20 +1483,20 @@ Tables from schemas: -- renaming the schema should reflect the change in publication ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1_renamed" "pub_test2" ALTER SCHEMA pub_test1_renamed RENAME to pub_test1; \dRp+ testpub2_forschema - Publication testpub2_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub2_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1411,10 +1504,10 @@ Tables from schemas: -- alter publication add schema ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1423,10 +1516,10 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1435,10 +1528,10 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test1; ERROR: schema "pub_test1" is already member of publication "testpub1_forschema" \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1446,10 +1539,10 @@ Tables from schemas: -- alter publication drop schema ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" @@ -1457,10 +1550,10 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2; ERROR: tables from schema "pub_test2" are not part of the publication \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" @@ -1468,29 +1561,29 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" -- drop all schemas ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f (1 row) -- alter publication set multiple schema ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1499,10 +1592,10 @@ Tables from schemas: ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA non_existent_schema; ERROR: schema "non_existent_schema" does not exist \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" "pub_test2" @@ -1511,10 +1604,10 @@ Tables from schemas: -- removing the duplicate schemas ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1; \dRp+ testpub1_forschema - Publication testpub1_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub1_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" @@ -1593,18 +1686,18 @@ SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub3_forschema; RESET client_min_messages; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f (1 row) ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1; \dRp+ testpub3_forschema - Publication testpub3_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub3_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables from schemas: "pub_test1" @@ -1614,20 +1707,20 @@ CREATE PUBLICATION testpub_forschema_fortable FOR TABLES IN SCHEMA pub_test1, TA CREATE PUBLICATION testpub_fortable_forschema FOR TABLE pub_test2.tbl1, TABLES IN SCHEMA pub_test1; RESET client_min_messages; \dRp+ testpub_forschema_fortable - Publication testpub_forschema_fortable - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_forschema_fortable + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test2.tbl1" Tables from schemas: "pub_test1" \dRp+ testpub_fortable_forschema - Publication testpub_fortable_forschema - Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root ---------------------------+------------+---------+---------+---------+-----------+---------- - regress_publication_user | f | t | t | t | t | f + Publication testpub_fortable_forschema + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f Tables: "pub_test2.tbl1" Tables from schemas: @@ -1642,7 +1735,7 @@ LINE 1: CREATE PUBLICATION testpub_error FOR pub_test2.tbl1; DETAIL: One of TABLE or TABLES IN SCHEMA must be specified before a standalone table or schema name. DROP VIEW testpub_view; DROP PUBLICATION testpub_default; -DROP PUBLICATION testpib_ins_trunct; +DROP PUBLICATION testpub_ins_trunct; DROP PUBLICATION testpub_fortbl; DROP PUBLICATION testpub1_forschema; DROP PUBLICATION testpub2_forschema; @@ -1742,6 +1835,95 @@ DROP PUBLICATION pub; DROP TABLE sch1.tbl1; DROP SCHEMA sch1 cascade; DROP SCHEMA sch2 cascade; +-- ====================================================== +-- Test the 'publish_generated_columns' parameter with the following values: +-- 'stored', 'none', and the default (no value specified), which defaults to +-- 'stored'. +SET client_min_messages = 'ERROR'; +CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored); +\dRp+ pub1 + Publication pub1 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | t | t | t | t | t | stored | f +(1 row) + +CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns = none); +\dRp+ pub2 + Publication pub2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | t | t | t | t | t | none | f +(1 row) + +CREATE PUBLICATION pub3 FOR ALL TABLES WITH (publish_generated_columns); +\dRp+ pub3 + Publication pub3 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | t | t | t | t | t | stored | f +(1 row) + +DROP PUBLICATION pub1; +DROP PUBLICATION pub2; +DROP PUBLICATION pub3; +-- Test the 'publish_generated_columns' parameter as 'none' and 'stored' for +-- different scenarios with/without generated columns in column lists. +CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); +-- Generated columns in column list, when 'publish_generated_columns'='none' +CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns = none); +\dRp+ pub1 + Publication pub1 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f +Tables: + "public.gencols" (a, gen1) + +-- Generated columns in column list, when 'publish_generated_columns'='stored' +CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns = stored); +\dRp+ pub2 + Publication pub2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | stored | f +Tables: + "public.gencols" (a, gen1) + +-- Generated columns in column list, then set 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET (publish_generated_columns = none); +\dRp+ pub2 + Publication pub2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f +Tables: + "public.gencols" (a, gen1) + +-- Remove generated columns from column list, when 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET TABLE gencols(a); +\dRp+ pub2 + Publication pub2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f +Tables: + "public.gencols" (a) + +-- Add generated columns in column list, when 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1); +\dRp+ pub2 + Publication pub2 + Owner | All tables | Inserts | Updates | Deletes | Truncates | Generated columns | Via root +--------------------------+------------+---------+---------+---------+-----------+-------------------+---------- + regress_publication_user | f | t | t | t | t | none | f +Tables: + "public.gencols" (a, gen1) + +DROP PUBLICATION pub1; +DROP PUBLICATION pub2; +DROP TABLE gencols; +RESET client_min_messages; RESET SESSION AUTHORIZATION; DROP ROLE regress_publication_user, regress_publication_user2; DROP ROLE regress_publication_user_dummy; diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 397a8b35d6d5c..c21be83aa4aaf 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -1885,7 +1885,7 @@ select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text); select * from array_to_set(array['one', 'two']) as t(f1 point,f2 text); ERROR: return type mismatch in function declared to return record DETAIL: Final statement returns integer instead of point at column 1. -CONTEXT: SQL function "array_to_set" during startup +CONTEXT: SQL function "array_to_set" statement 1 -- with "strict", this function can't be inlined in FROM explain (verbose, costs off) select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text); diff --git a/src/test/regress/expected/replica_identity.out b/src/test/regress/expected/replica_identity.out index e9d7315a9c17d..b9b8dde018f08 100644 --- a/src/test/regress/expected/replica_identity.out +++ b/src/test/regress/expected/replica_identity.out @@ -174,6 +174,10 @@ Indexes: "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb) +Not-null constraints: + "test_replica_identity_id_not_null" NOT NULL "id" + "test_replica_identity_keya_not_null" NOT NULL "keya" + "test_replica_identity_keyb_not_null" NOT NULL "keyb" Replica Identity: FULL ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING; @@ -231,6 +235,9 @@ Indexes: -- used as replica identity. ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL; ERROR: column "id" is in index used as replica identity +-- but it's OK when the identity is FULL +ALTER TABLE test_replica_identity3 REPLICA IDENTITY FULL; +ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL; -- -- Test that replica identity can be set on an index that's not yet valid. -- (This matches the way pg_dump will try to dump a partitioned table.) @@ -253,6 +260,8 @@ ALTER TABLE ONLY test_replica_identity4_1 Partition key: LIST (id) Indexes: "test_replica_identity4_pkey" PRIMARY KEY, btree (id) INVALID REPLICA IDENTITY +Not-null constraints: + "test_replica_identity4_id_not_null" NOT NULL "id" Partitions: test_replica_identity4_1 FOR VALUES IN (1) ALTER INDEX test_replica_identity4_pkey @@ -265,11 +274,26 @@ ALTER INDEX test_replica_identity4_pkey Partition key: LIST (id) Indexes: "test_replica_identity4_pkey" PRIMARY KEY, btree (id) REPLICA IDENTITY +Not-null constraints: + "test_replica_identity4_id_not_null" NOT NULL "id" Partitions: test_replica_identity4_1 FOR VALUES IN (1) +-- Dropping the primary key is not allowed if that would leave the replica +-- identity as nullable +CREATE TABLE test_replica_identity5 (a int not null, b int, c int, + PRIMARY KEY (b, c)); +CREATE UNIQUE INDEX test_replica_identity5_a_b_key ON test_replica_identity5 (a, b); +ALTER TABLE test_replica_identity5 REPLICA IDENTITY USING INDEX test_replica_identity5_a_b_key; +ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey; +ALTER TABLE test_replica_identity5 ALTER b SET NOT NULL; +ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey; +ERROR: constraint "test_replica_identity5_pkey" of relation "test_replica_identity5" does not exist +ALTER TABLE test_replica_identity5 ALTER b DROP NOT NULL; +ERROR: column "b" is in index used as replica identity DROP TABLE test_replica_identity; DROP TABLE test_replica_identity2; DROP TABLE test_replica_identity3; DROP TABLE test_replica_identity4; +DROP TABLE test_replica_identity5; DROP TABLE test_replica_identity_othertable; DROP TABLE test_replica_identity_t3; diff --git a/src/test/regress/expected/returning.out b/src/test/regress/expected/returning.out index cb51bb86876db..341b689f76655 100644 --- a/src/test/regress/expected/returning.out +++ b/src/test/regress/expected/returning.out @@ -286,6 +286,63 @@ SELECT * FROM voo; 16 | zoo2 (2 rows) +-- Check use of a whole-row variable for an un-flattenable view +CREATE TEMP VIEW foo_v AS SELECT * FROM foo OFFSET 0; +UPDATE foo SET f2 = foo_v.f2 FROM foo_v WHERE foo_v.f1 = foo.f1 + RETURNING foo_v; + foo_v +----------------- + (2,more,42,141) + (16,zoo2,57,99) +(2 rows) + +SELECT * FROM foo; + f1 | f2 | f3 | f4 +----+------+----+----- + 2 | more | 42 | 141 + 16 | zoo2 | 57 | 99 +(2 rows) + +-- Check use of a whole-row variable for an inlined set-returning function +CREATE FUNCTION foo_f() RETURNS SETOF foo AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; + foo_f +----------------- + (2,more,42,141) + (16,zoo2,57,99) +(2 rows) + +SELECT * FROM foo; + f1 | f2 | f3 | f4 +----+------+----+----- + 2 | more | 42 | 141 + 16 | zoo2 | 57 | 99 +(2 rows) + +DROP FUNCTION foo_f(); +-- As above, but SRF is defined to return a composite type +CREATE TYPE foo_t AS (f1 int, f2 text, f3 int, f4 int8); +CREATE FUNCTION foo_f() RETURNS SETOF foo_t AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; + foo_f +----------------- + (2,more,42,141) + (16,zoo2,57,99) +(2 rows) + +SELECT * FROM foo; + f1 | f2 | f3 | f4 +----+------+----+----- + 2 | more | 42 | 141 + 16 | zoo2 | 57 | 99 +(2 rows) + +DROP FUNCTION foo_f(); +DROP TYPE foo_t; -- Try a join case CREATE TEMP TABLE joinme (f2j text, other int); INSERT INTO joinme VALUES('more', 12345); @@ -355,3 +412,577 @@ INSERT INTO foo AS bar DEFAULT VALUES RETURNING bar.f3; -- ok 42 (1 row) +-- +-- Test RETURNING OLD/NEW. +-- +-- Start with new data, to ensure predictable TIDs. +-- +TRUNCATE foo; +INSERT INTO foo VALUES (1, 'xxx', 10, 20), (2, 'more', 42, 141), (3, 'zoo2', 57, 99); +-- Error cases +INSERT INTO foo DEFAULT VALUES RETURNING WITH (nonsuch AS something) *; +ERROR: syntax error at or near "nonsuch" +LINE 1: INSERT INTO foo DEFAULT VALUES RETURNING WITH (nonsuch AS so... + ^ +INSERT INTO foo DEFAULT VALUES RETURNING WITH (new AS foo) *; +ERROR: table name "foo" specified more than once +LINE 1: INSERT INTO foo DEFAULT VALUES RETURNING WITH (new AS foo) *... + ^ +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS o, new AS n, old AS o) *; +ERROR: OLD cannot be specified multiple times +LINE 1: ...EFAULT VALUES RETURNING WITH (old AS o, new AS n, old AS o) ... + ^ +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS o, new AS n, new AS n) *; +ERROR: NEW cannot be specified multiple times +LINE 1: ...EFAULT VALUES RETURNING WITH (old AS o, new AS n, new AS n) ... + ^ +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS x, new AS x) *; +ERROR: table name "x" specified more than once +LINE 1: ...INTO foo DEFAULT VALUES RETURNING WITH (old AS x, new AS x) ... + ^ +-- INSERT has NEW, but not OLD +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (4) + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on pg_temp.foo + Output: (old.tableoid)::regclass, old.ctid, old.f1, old.f2, old.f3, old.f4, (new.tableoid)::regclass, new.ctid, new.f1, new.f2, new.f3, new.f4, foo.f1, foo.f2, foo.f3, foo.f4 + -> Result + Output: 4, NULL::text, 42, '99'::bigint +(4 rows) + +INSERT INTO foo VALUES (4) + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | f1 | f2 | f3 | f4 | tableoid | ctid | f1 | f2 | f3 | f4 | f1 | f2 | f3 | f4 +----------+------+----+----+----+----+----------+-------+----+----+----+----+----+----+----+---- + | | | | | | foo | (0,4) | 4 | | 42 | 99 | 4 | | 42 | 99 +(1 row) + +-- INSERT ... ON CONFLICT ... UPDATE has OLD and NEW +CREATE UNIQUE INDEX foo_f1_idx ON foo (f1); +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (4, 'conflict'), (5, 'ok') + ON CONFLICT (f1) DO UPDATE SET f2 = excluded.f2||'ed', f3 = -1 + RETURNING WITH (OLD AS o, NEW AS n) + o.tableoid::regclass, o.ctid, o.*, + n.tableoid::regclass, n.ctid, n.*, *; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------- + Insert on pg_temp.foo + Output: (o.tableoid)::regclass, o.ctid, o.f1, o.f2, o.f3, o.f4, (n.tableoid)::regclass, n.ctid, n.f1, n.f2, n.f3, n.f4, foo.f1, foo.f2, foo.f3, foo.f4 + Conflict Resolution: UPDATE + Conflict Arbiter Indexes: foo_f1_idx + -> Values Scan on "*VALUES*" + Output: "*VALUES*".column1, "*VALUES*".column2, 42, '99'::bigint +(6 rows) + +INSERT INTO foo VALUES (4, 'conflict'), (5, 'ok') + ON CONFLICT (f1) DO UPDATE SET f2 = excluded.f2||'ed', f3 = -1 + RETURNING WITH (OLD AS o, NEW AS n) + o.tableoid::regclass, o.ctid, o.*, + n.tableoid::regclass, n.ctid, n.*, *; + tableoid | ctid | f1 | f2 | f3 | f4 | tableoid | ctid | f1 | f2 | f3 | f4 | f1 | f2 | f3 | f4 +----------+-------+----+----+----+----+----------+-------+----+------------+----+----+----+------------+----+---- + foo | (0,4) | 4 | | 42 | 99 | foo | (0,5) | 4 | conflicted | -1 | 99 | 4 | conflicted | -1 | 99 + | | | | | | foo | (0,6) | 5 | ok | 42 | 99 | 5 | ok | 42 | 99 +(2 rows) + +-- UPDATE has OLD and NEW +EXPLAIN (verbose, costs off) +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, old, + new.tableoid::regclass, new.ctid, new.*, new, + old.f4::text||'->'||new.f4::text AS change; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on pg_temp.foo + Output: (old.tableoid)::regclass, old.ctid, old.f1, old.f2, old.f3, old.f4, old.*, (new.tableoid)::regclass, new.ctid, new.f1, new.f2, new.f3, new.f4, new.*, (((old.f4)::text || '->'::text) || (new.f4)::text) + Update on pg_temp.foo foo_1 + -> Result + Output: '100'::bigint, foo_1.tableoid, foo_1.ctid + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.tableoid, foo_1.ctid + Filter: (foo_1.f1 = 5) +(8 rows) + +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, old, + new.tableoid::regclass, new.ctid, new.*, new, + old.f4::text||'->'||new.f4::text AS change; + tableoid | ctid | f1 | f2 | f3 | f4 | old | tableoid | ctid | f1 | f2 | f3 | f4 | new | change +----------+-------+----+----+----+----+--------------+----------+-------+----+----+----+-----+---------------+--------- + foo | (0,6) | 5 | ok | 42 | 99 | (5,ok,42,99) | foo | (0,7) | 5 | ok | 42 | 100 | (5,ok,42,100) | 99->100 +(1 row) + +-- DELETE has OLD, but not NEW +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Delete on pg_temp.foo + Output: (old.tableoid)::regclass, old.ctid, old.f1, old.f2, old.f3, old.f4, (new.tableoid)::regclass, new.ctid, new.f1, new.f2, new.f3, new.f4, foo_1.f1, foo_1.f2, foo_1.f3, foo_1.f4 + Delete on pg_temp.foo foo_1 + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.tableoid, foo_1.ctid + Filter: (foo_1.f1 = 5) +(6 rows) + +DELETE FROM foo WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | f1 | f2 | f3 | f4 | tableoid | ctid | f1 | f2 | f3 | f4 | f1 | f2 | f3 | f4 +----------+-------+----+----+----+-----+----------+------+----+----+----+----+----+----+----+----- + foo | (0,7) | 5 | ok | 42 | 100 | | | | | | | 5 | ok | 42 | 100 +(1 row) + +-- RETURNING OLD and NEW from subquery +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (5, 'subquery test') + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + QUERY PLAN +--------------------------------------------------------------- + Insert on pg_temp.foo + Output: (SubPlan 1), (SubPlan 2) + -> Result + Output: 5, 'subquery test'::text, 42, '99'::bigint + SubPlan 1 + -> Aggregate + Output: max((old.f4 + x.x)) + -> Function Scan on pg_catalog.generate_series x + Output: x.x + Function Call: generate_series(1, 10) + SubPlan 2 + -> Aggregate + Output: max((new.f4 + x_1.x)) + -> Function Scan on pg_catalog.generate_series x_1 + Output: x_1.x + Function Call: generate_series(1, 10) +(16 rows) + +INSERT INTO foo VALUES (5, 'subquery test') + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + old_max | new_max +---------+--------- + | 109 +(1 row) + +EXPLAIN (verbose, costs off) +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING (SELECT old.f4 = new.f4), + (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + QUERY PLAN +--------------------------------------------------------------- + Update on pg_temp.foo + Output: (SubPlan 1), (SubPlan 2), (SubPlan 3) + Update on pg_temp.foo foo_1 + -> Result + Output: '100'::bigint, foo_1.tableoid, foo_1.ctid + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.tableoid, foo_1.ctid + Filter: (foo_1.f1 = 5) + SubPlan 1 + -> Result + Output: (old.f4 = new.f4) + SubPlan 2 + -> Aggregate + Output: max((old.f4 + x.x)) + -> Function Scan on pg_catalog.generate_series x + Output: x.x + Function Call: generate_series(1, 10) + SubPlan 3 + -> Aggregate + Output: max((new.f4 + x_1.x)) + -> Function Scan on pg_catalog.generate_series x_1 + Output: x_1.x + Function Call: generate_series(1, 10) +(23 rows) + +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING (SELECT old.f4 = new.f4), + (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + ?column? | old_max | new_max +----------+---------+--------- + f | 109 | 110 +(1 row) + +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 5 + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + QUERY PLAN +--------------------------------------------------------------- + Delete on pg_temp.foo + Output: (SubPlan 1), (SubPlan 2) + Delete on pg_temp.foo foo_1 + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.tableoid, foo_1.ctid + Filter: (foo_1.f1 = 5) + SubPlan 1 + -> Aggregate + Output: max((old.f4 + x.x)) + -> Function Scan on pg_catalog.generate_series x + Output: x.x + Function Call: generate_series(1, 10) + SubPlan 2 + -> Aggregate + Output: max((new.f4 + x_1.x)) + -> Function Scan on pg_catalog.generate_series x_1 + Output: x_1.x + Function Call: generate_series(1, 10) +(18 rows) + +DELETE FROM foo WHERE f1 = 5 + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + old_max | new_max +---------+--------- + 110 | +(1 row) + +-- DELETE turned into UPDATE by a rule has OLD and NEW +CREATE RULE foo_del_rule AS ON DELETE TO foo DO INSTEAD + UPDATE foo SET f2 = f2||' (deleted)', f3 = -1, f4 = -1 WHERE f1 = OLD.f1 + RETURNING *; +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 4 RETURNING old.*,new.*, *; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------- + Update on pg_temp.foo + Output: old.f1, old.f2, old.f3, old.f4, new.f1, new.f2, new.f3, new.f4, foo_2.f1, foo_2.f2, foo_2.f3, foo_2.f4 + Update on pg_temp.foo foo_2 + -> Nested Loop + Output: (foo_2.f2 || ' (deleted)'::text), '-1'::integer, '-1'::bigint, foo_1.ctid, foo_1.tableoid, foo_2.tableoid, foo_2.ctid + -> Seq Scan on pg_temp.foo foo_2 + Output: foo_2.f2, foo_2.f1, foo_2.tableoid, foo_2.ctid + Filter: (foo_2.f1 = 4) + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.ctid, foo_1.f1, foo_1.tableoid + Filter: (foo_1.f1 = 4) +(11 rows) + +DELETE FROM foo WHERE f1 = 4 RETURNING old.*,new.*, *; + f1 | f2 | f3 | f4 | f1 | f2 | f3 | f4 | f1 | f2 | f3 | f4 +----+------------+----+----+----+----------------------+----+----+----+----------------------+----+---- + 4 | conflicted | -1 | 99 | 4 | conflicted (deleted) | -1 | -1 | 4 | conflicted (deleted) | -1 | -1 +(1 row) + +-- UPDATE on view with rule +EXPLAIN (verbose, costs off) +UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on pg_temp.foo + Output: old.f1, old.f2, old.f3, old.f4, joinme.other, new.f1, new.f2, new.f3, new.f4, joinme.other, foo_1.f1, foo_1.f2, foo_1.f3, foo_1.f4, joinme.other, (new.f3 - old.f3) + Update on pg_temp.foo foo_1 + -> Hash Join + Output: foo_2.f1, (foo_2.f3 + 1), joinme.ctid, foo_2.ctid, joinme_1.ctid, joinme.other, foo_1.tableoid, foo_1.ctid, foo_2.tableoid + Hash Cond: (foo_1.f2 = joinme.f2j) + -> Hash Join + Output: foo_1.f2, foo_1.tableoid, foo_1.ctid, joinme_1.ctid, joinme_1.f2j + Hash Cond: (joinme_1.f2j = foo_1.f2) + -> Seq Scan on pg_temp.joinme joinme_1 + Output: joinme_1.ctid, joinme_1.f2j + -> Hash + Output: foo_1.f2, foo_1.tableoid, foo_1.ctid + -> Seq Scan on pg_temp.foo foo_1 + Output: foo_1.f2, foo_1.tableoid, foo_1.ctid + -> Hash + Output: joinme.ctid, joinme.other, joinme.f2j, foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid + -> Hash Join + Output: joinme.ctid, joinme.other, joinme.f2j, foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid + Hash Cond: (joinme.f2j = foo_2.f2) + -> Seq Scan on pg_temp.joinme + Output: joinme.ctid, joinme.other, joinme.f2j + -> Hash + Output: foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid + -> Seq Scan on pg_temp.foo foo_2 + Output: foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid + Filter: (foo_2.f3 = 57) +(27 rows) + +UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; + f1 | f2 | f3 | f4 | other | f1 | f2 | f3 | f4 | other | f1 | f2 | f3 | f4 | other | delta_f3 +----+------+----+----+-------+----+------+----+----+-------+----+------+----+----+-------+---------- + 3 | zoo2 | 57 | 99 | 54321 | 3 | zoo2 | 58 | 99 | 54321 | 3 | zoo2 | 58 | 99 | 54321 | 1 +(1 row) + +-- UPDATE on view with INSTEAD OF trigger +CREATE FUNCTION joinview_upd_trig_fn() RETURNS trigger +LANGUAGE plpgsql AS +$$ +BEGIN + RAISE NOTICE 'UPDATE: % -> %', old, new; + UPDATE foo SET f1 = new.f1, f3 = new.f3, f4 = new.f4 * 10 + FROM joinme WHERE f2 = f2j AND f2 = old.f2 + RETURNING new.f1, new.f4 INTO new.f1, new.f4; -- should fail + RETURN NEW; +END; +$$; +CREATE TRIGGER joinview_upd_trig INSTEAD OF UPDATE ON joinview + FOR EACH ROW EXECUTE FUNCTION joinview_upd_trig_fn(); +DROP RULE joinview_u ON joinview; +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; -- should fail +NOTICE: UPDATE: (3,zoo2,58,99,54321) -> (3,zoo2,59,7,54321) +ERROR: column reference "new.f1" is ambiguous +LINE 3: RETURNING new.f1, new.f4 + ^ +DETAIL: It could refer to either a PL/pgSQL variable or a table column. +QUERY: UPDATE foo SET f1 = new.f1, f3 = new.f3, f4 = new.f4 * 10 + FROM joinme WHERE f2 = f2j AND f2 = old.f2 + RETURNING new.f1, new.f4 +CONTEXT: PL/pgSQL function joinview_upd_trig_fn() line 4 at SQL statement +CREATE OR REPLACE FUNCTION joinview_upd_trig_fn() RETURNS trigger +LANGUAGE plpgsql AS +$$ +BEGIN + RAISE NOTICE 'UPDATE: % -> %', old, new; + UPDATE foo SET f1 = new.f1, f3 = new.f3, f4 = new.f4 * 10 + FROM joinme WHERE f2 = f2j AND f2 = old.f2 + RETURNING WITH (new AS n) new.f1, n.f4 INTO new.f1, new.f4; -- now ok + RETURN NEW; +END; +$$; +EXPLAIN (verbose, costs off) +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Update on pg_temp.joinview + Output: old.f1, old.f2, old.f3, old.f4, old.other, new.f1, new.f2, new.f3, new.f4, new.other, joinview.f1, joinview.f2, joinview.f3, joinview.f4, joinview.other, (new.f3 - old.f3) + -> Hash Join + Output: (foo.f3 + 1), '7'::bigint, ROW(foo.f1, foo.f2, foo.f3, foo.f4, joinme.other), foo.ctid, joinme.ctid, foo.tableoid + Hash Cond: (joinme.f2j = foo.f2) + -> Seq Scan on pg_temp.joinme + Output: joinme.other, joinme.ctid, joinme.f2j + -> Hash + Output: foo.f3, foo.f1, foo.f2, foo.f4, foo.ctid, foo.tableoid + -> Seq Scan on pg_temp.foo + Output: foo.f3, foo.f1, foo.f2, foo.f4, foo.ctid, foo.tableoid + Filter: (foo.f3 = 58) +(12 rows) + +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; -- should succeed +NOTICE: UPDATE: (3,zoo2,58,99,54321) -> (3,zoo2,59,7,54321) + f1 | f2 | f3 | f4 | other | f1 | f2 | f3 | f4 | other | f1 | f2 | f3 | f4 | other | delta_f3 +----+------+----+----+-------+----+------+----+----+-------+----+------+----+----+-------+---------- + 3 | zoo2 | 58 | 99 | 54321 | 3 | zoo2 | 59 | 70 | 54321 | 3 | zoo2 | 59 | 70 | 54321 | 1 +(1 row) + +-- Test wholerow & dropped column handling +ALTER TABLE foo DROP COLUMN f3 CASCADE; +NOTICE: drop cascades to 4 other objects +DETAIL: drop cascades to rule voo_i on view voo +drop cascades to view foo_v +drop cascades to view joinview +drop cascades to rule foo_del_rule on table foo +UPDATE foo SET f4 = f4 + 1 RETURNING old.f3; -- should fail +ERROR: column old.f3 does not exist +LINE 1: UPDATE foo SET f4 = f4 + 1 RETURNING old.f3; + ^ +UPDATE foo SET f4 = f4 + 1 RETURNING old, new; + old | new +-------------------------------+------------------------------ + (1,xxx,20) | (1,xxx,21) + (2,more,141) | (2,more,142) + (4,"conflicted (deleted)",-1) | (4,"conflicted (deleted)",0) + (3,zoo2,70) | (3,zoo2,71) +(4 rows) + +-- INSERT/DELETE on zero column table +CREATE TABLE zerocol(); +INSERT INTO zerocol SELECT RETURNING old.*, new.*, *; +ERROR: RETURNING must have at least one column +LINE 1: INSERT INTO zerocol SELECT RETURNING old.*, new.*, *; + ^ +INSERT INTO zerocol SELECT + RETURNING old.tableoid::regclass, old.ctid, + new.tableoid::regclass, new.ctid, ctid, *; + tableoid | ctid | tableoid | ctid | ctid +----------+------+----------+-------+------- + | | zerocol | (0,1) | (0,1) +(1 row) + +DELETE FROM zerocol + RETURNING old.tableoid::regclass, old.ctid, + new.tableoid::regclass, new.ctid, ctid, *; + tableoid | ctid | tableoid | ctid | ctid +----------+-------+----------+------+------- + zerocol | (0,1) | | | (0,1) +(1 row) + +DROP TABLE zerocol; +-- Test schema-qualified table name in RETURNING list +CREATE TABLE public.tt(a int, b int); +INSERT INTO public.tt VALUES (1, 10); +UPDATE public.tt SET b = b * 2 RETURNING a, b, old.b, new.b, tt.b, public.tt.b; + a | b | b | b | b | b +---+----+----+----+----+---- + 1 | 20 | 10 | 20 | 20 | 20 +(1 row) + +DROP TABLE public.tt; +-- Test cross-partition updates and attribute mapping +CREATE TABLE foo_parted (a int, b float8, c text) PARTITION BY LIST (a); +CREATE TABLE foo_part_s1 PARTITION OF foo_parted FOR VALUES IN (1); +CREATE TABLE foo_part_s2 PARTITION OF foo_parted FOR VALUES IN (2); +CREATE TABLE foo_part_d1 (c text, a int, b float8); +ALTER TABLE foo_parted ATTACH PARTITION foo_part_d1 FOR VALUES IN (3); +CREATE TABLE foo_part_d2 (b float8, c text, a int); +ALTER TABLE foo_parted ATTACH PARTITION foo_part_d2 FOR VALUES IN (4); +INSERT INTO foo_parted + VALUES (1, 17.1, 'P1'), (2, 17.2, 'P2'), (3, 17.3, 'P3'), (4, 17.4, 'P4') + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +----------+------+---+---+---+-------------+-------+---+------+----+---+------+---- + | | | | | foo_part_s1 | (0,1) | 1 | 17.1 | P1 | 1 | 17.1 | P1 + | | | | | foo_part_s2 | (0,1) | 2 | 17.2 | P2 | 2 | 17.2 | P2 + | | | | | foo_part_d1 | (0,1) | 3 | 17.3 | P3 | 3 | 17.3 | P3 + | | | | | foo_part_d2 | (0,1) | 4 | 17.4 | P4 | 4 | 17.4 | P4 +(4 rows) + +UPDATE foo_parted SET a = 2, b = b + 1, c = c || '->P2' WHERE a = 1 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +-------------+-------+---+------+----+-------------+-------+---+------+--------+---+------+-------- + foo_part_s1 | (0,1) | 1 | 17.1 | P1 | foo_part_s2 | (0,2) | 2 | 18.1 | P1->P2 | 2 | 18.1 | P1->P2 +(1 row) + +UPDATE foo_parted SET a = 1, b = b + 1, c = c || '->P1' WHERE a = 3 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +-------------+-------+---+------+----+-------------+-------+---+------+--------+---+------+-------- + foo_part_d1 | (0,1) | 3 | 17.3 | P3 | foo_part_s1 | (0,2) | 1 | 18.3 | P3->P1 | 1 | 18.3 | P3->P1 +(1 row) + +UPDATE foo_parted SET a = 3, b = b + 1, c = c || '->P3' WHERE a = 1 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +-------------+-------+---+------+--------+-------------+-------+---+------+------------+---+------+------------ + foo_part_s1 | (0,2) | 1 | 18.3 | P3->P1 | foo_part_d1 | (0,2) | 3 | 19.3 | P3->P1->P3 | 3 | 19.3 | P3->P1->P3 +(1 row) + +UPDATE foo_parted SET a = 4, b = b + 1, c = c || '->P4' WHERE a = 3 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +-------------+-------+---+------+------------+-------------+-------+---+------+----------------+---+------+---------------- + foo_part_d1 | (0,2) | 3 | 19.3 | P3->P1->P3 | foo_part_d2 | (0,2) | 4 | 20.3 | P3->P1->P3->P4 | 4 | 20.3 | P3->P1->P3->P4 +(1 row) + +-- cross-partition update that uses ReturningExpr nodes, without returning +-- old/new table values +CREATE VIEW foo_parted_v AS SELECT *, 'xxx' AS dummy FROM foo_parted; +UPDATE foo_parted_v SET a = 1, c = c || '->P1' WHERE a = 2 AND c = 'P2' + RETURNING 'P2:'||old.dummy, 'P1:'||new.dummy; + ?column? | ?column? +----------+---------- + P2:xxx | P1:xxx +(1 row) + +DELETE FROM foo_parted + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + tableoid | ctid | a | b | c | tableoid | ctid | a | b | c | a | b | c +-------------+-------+---+------+----------------+----------+------+---+---+---+---+------+---------------- + foo_part_s1 | (0,3) | 1 | 17.2 | P2->P1 | | | | | | 1 | 17.2 | P2->P1 + foo_part_s2 | (0,2) | 2 | 18.1 | P1->P2 | | | | | | 2 | 18.1 | P1->P2 + foo_part_d2 | (0,1) | 4 | 17.4 | P4 | | | | | | 4 | 17.4 | P4 + foo_part_d2 | (0,2) | 4 | 20.3 | P3->P1->P3->P4 | | | | | | 4 | 20.3 | P3->P1->P3->P4 +(4 rows) + +DROP TABLE foo_parted CASCADE; +NOTICE: drop cascades to view foo_parted_v +-- Test deparsing +CREATE FUNCTION foo_update() + RETURNS void + LANGUAGE sql +BEGIN ATOMIC + WITH u1 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING old.*, new.* + ), u2 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING WITH (OLD AS "old foo") "old foo".*, new.* + ), u3 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING WITH (NEW AS "new foo") old.*, "new foo".* + ) + UPDATE foo SET f1 = f1 + 1 + RETURNING WITH (OLD AS o, NEW AS n) + o.*, n.*, o, n, o.f1 = n.f1, o = n, + (SELECT o.f2 = n.f2), + (SELECT count(*) FROM foo WHERE foo.f1 = o.f4), + (SELECT count(*) FROM foo WHERE foo.f4 = n.f4), + (SELECT count(*) FROM foo WHERE foo = o), + (SELECT count(*) FROM foo WHERE foo = n); +END; +\sf foo_update +CREATE OR REPLACE FUNCTION public.foo_update() + RETURNS void + LANGUAGE sql +BEGIN ATOMIC + WITH u1 AS ( + UPDATE foo foo_1 SET f1 = (foo_1.f1 + 1) + RETURNING old.f1, + old.f2, + old.f4, + new.f1, + new.f2, + new.f4 + ), u2 AS ( + UPDATE foo foo_1 SET f1 = (foo_1.f1 + 1) + RETURNING WITH (OLD AS "old foo") "old foo".f1, + "old foo".f2, + "old foo".f4, + new.f1, + new.f2, + new.f4 + ), u3 AS ( + UPDATE foo foo_1 SET f1 = (foo_1.f1 + 1) + RETURNING WITH (NEW AS "new foo") old.f1, + old.f2, + old.f4, + "new foo".f1, + "new foo".f2, + "new foo".f4 + ) + UPDATE foo SET f1 = (foo.f1 + 1) + RETURNING WITH (OLD AS o, NEW AS n) o.f1, + o.f2, + o.f4, + n.f1, + n.f2, + n.f4, + o.*::foo AS o, + n.*::foo AS n, + (o.f1 = n.f1), + (o.* = n.*), + ( SELECT (o.f2 = n.f2)), + ( SELECT count(*) AS count + FROM foo foo_1 + WHERE (foo_1.f1 = o.f4)) AS count, + ( SELECT count(*) AS count + FROM foo foo_1 + WHERE (foo_1.f4 = n.f4)) AS count, + ( SELECT count(*) AS count + FROM foo foo_1 + WHERE (foo_1.* = o.*)) AS count, + ( SELECT count(*) AS count + FROM foo foo_1 + WHERE (foo_1.* = n.*)) AS count; +END +DROP FUNCTION foo_update; diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index 319190855bdb1..1c4e37d22493d 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -955,6 +955,8 @@ Policies: POLICY "pp1r" AS RESTRICTIVE TO regress_rls_dave USING ((cid < 55)) +Not-null constraints: + "part_document_dlevel_not_null" NOT NULL "dlevel" Partitions: part_document_fiction FOR VALUES FROM (11) TO (12), part_document_nonfiction FOR VALUES FROM (99) TO (100), part_document_satire FOR VALUES FROM (55) TO (56) @@ -4377,6 +4379,35 @@ ERROR: new row violates row-level security policy for table "r1" INSERT INTO r1 VALUES (10) ON CONFLICT ON CONSTRAINT r1_pkey DO UPDATE SET a = 30; ERROR: new row violates row-level security policy for table "r1" +DROP TABLE r1; +-- +-- Test policies using virtual generated columns +-- +SET SESSION AUTHORIZATION regress_rls_alice; +SET row_security = on; +CREATE TABLE r1 (a int, b int GENERATED ALWAYS AS (a * 10) VIRTUAL); +ALTER TABLE r1 ADD c int GENERATED ALWAYS AS (a * 100) VIRTUAL; +INSERT INTO r1 VALUES (1), (2), (4); +CREATE POLICY p0 ON r1 USING (b * 10 = c); +CREATE POLICY p1 ON r1 AS RESTRICTIVE USING (b > 10); +CREATE POLICY p2 ON r1 AS RESTRICTIVE USING ((SELECT c) < 400); +ALTER TABLE r1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE r1 FORCE ROW LEVEL SECURITY; +-- Should fail p1 +INSERT INTO r1 VALUES (0); +ERROR: new row violates row-level security policy "p1" for table "r1" +-- Should fail p2 +INSERT INTO r1 VALUES (4); +ERROR: new row violates row-level security policy "p2" for table "r1" +-- OK +INSERT INTO r1 VALUES (3); +SELECT * FROM r1; + a | b | c +---+----+----- + 2 | 20 | 200 + 3 | 30 | 300 +(2 rows) + DROP TABLE r1; -- Check dependency handling RESET SESSION AUTHORIZATION; @@ -4492,6 +4523,13 @@ SELECT * FROM rls_tbl WHERE a <<< 1000; --- (0 rows) +EXPLAIN (COSTS OFF) SELECT * FROM rls_tbl WHERE a <<< 1000 or a <<< 900; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + DROP OPERATOR <<< (int, int); DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; @@ -4554,9 +4592,160 @@ execute q; --------------+--- (0 rows) +-- make sure RLS dependencies in CTEs are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ with cte as (select * from rls_t) select * from cte $$; +prepare r as select current_user, * from rls_f(); +set role regress_rls_alice; +execute r; + current_user | c +-------------------+------------------ + regress_rls_alice | invisible to bob +(1 row) + +set role regress_rls_bob; +execute r; + current_user | c +--------------+--- +(0 rows) + +-- make sure RLS dependencies in subqueries are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select * from rls_t) _ $$; +prepare s as select current_user, * from rls_f(); +set role regress_rls_alice; +execute s; + current_user | c +-------------------+------------------ + regress_rls_alice | invisible to bob +(1 row) + +set role regress_rls_bob; +execute s; + current_user | c +--------------+--- +(0 rows) + +-- make sure RLS dependencies in sublinks are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select exists(select * from rls_t)::text $$; +prepare t as select current_user, * from rls_f(); +set role regress_rls_alice; +execute t; + current_user | c +-------------------+------ + regress_rls_alice | true +(1 row) + +set role regress_rls_bob; +execute t; + current_user | c +-----------------+------- + regress_rls_bob | false +(1 row) + +-- make sure RLS dependencies are handled when coercion projections are inserted +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select array_agg(c) as cs from rls_t) _ group by cs $$; +prepare u as select current_user, * from rls_f(); +set role regress_rls_alice; +execute u; + current_user | c +-------------------+---------------------- + regress_rls_alice | {"invisible to bob"} +(1 row) + +set role regress_rls_bob; +execute u; + current_user | c +-----------------+--- + regress_rls_bob | +(1 row) + +-- make sure RLS dependencies in security invoker views are handled +reset role; +create view rls_v with (security_invoker) as select * from rls_t; +grant select on rls_v to regress_rls_alice, regress_rls_bob; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from rls_v $$; +prepare v as select current_user, * from rls_f(); +set role regress_rls_alice; +execute v; + current_user | c +-------------------+------------------ + regress_rls_alice | invisible to bob +(1 row) + +set role regress_rls_bob; +execute v; + current_user | c +--------------+--- +(0 rows) + RESET ROLE; DROP FUNCTION rls_f(); +DROP VIEW rls_v; DROP TABLE rls_t; +-- Check that RLS changes invalidate SQL function plans +create table rls_t (c text); +create table test_t (c text); +insert into rls_t values ('a'), ('b'), ('c'), ('d'); +insert into test_t values ('a'), ('b'); +alter table rls_t enable row level security; +grant select on rls_t to regress_rls_alice; +grant select on test_t to regress_rls_alice; +create policy p1 on rls_t for select to regress_rls_alice + using (c = current_setting('rls_test.blah')); +-- Function changes row_security setting and so invalidates plan +create function rls_f(text) returns text +begin atomic + select set_config('rls_test.blah', $1, true) || set_config('row_security', 'false', true) || string_agg(c, ',' order by c) from rls_t; +end; +set plan_cache_mode to force_custom_plan; +-- Table owner bypasses RLS +select rls_f(c) from test_t order by rls_f; + rls_f +------------- + aoffa,b,c,d + boffa,b,c,d +(2 rows) + +-- For other users, changes in row_security setting +-- should lead to RLS error during query rewrite +set role regress_rls_alice; +select rls_f(c) from test_t order by rls_f; +ERROR: query would be affected by row-level security policy for table "rls_t" +CONTEXT: SQL function "rls_f" statement 1 +reset role; +set plan_cache_mode to force_generic_plan; +-- Table owner bypasses RLS, although cached plan will be invalidated +select rls_f(c) from test_t order by rls_f; + rls_f +------------- + aoffa,b,c,d + boffa,b,c,d +(2 rows) + +-- For other users, changes in row_security setting +-- should lead to plan invalidation and RLS error during query rewrite +set role regress_rls_alice; +select rls_f(c) from test_t order by rls_f; +ERROR: query would be affected by row-level security policy for table "rls_t" +CONTEXT: SQL function "rls_f" statement 1 +reset role; +reset plan_cache_mode; +reset rls_test.blah; +drop function rls_f(text); +drop table rls_t, test_t; -- -- Clean up objects -- diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out index b400b58f7633a..9168979a6206e 100644 --- a/src/test/regress/expected/rowtypes.out +++ b/src/test/regress/expected/rowtypes.out @@ -1300,6 +1300,60 @@ select pg_get_viewdef('composite_v', true); (1 row) drop view composite_v; +-- +-- Check cases where the composite comes from a proven-dummy rel (bug #18576) +-- +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss; + QUERY PLAN +------------------------------------------------------------------------ + Subquery Scan on ss + Output: (ss.a).x, (ss.a).n + -> ProjectSet + Output: information_schema._pg_expandarray('{1,2}'::integer[]) + -> Result +(5 rows) + +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss +where false; + QUERY PLAN +-------------------------- + Result + Output: (a).f1, (a).f2 + One-Time Filter: false +(3 rows) + +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t; + QUERY PLAN +----------------------------------- + CTE Scan on cte + Output: (cte.c).f1 + CTE cte + -> Result + Output: '(1,2)'::record +(5 rows) + +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t +where false; + QUERY PLAN +----------------------------------- + Result + Output: (cte.c).f1 + One-Time Filter: false + CTE cte + -> Result + Output: '(1,2)'::record +(6 rows) + -- -- Tests for component access / FieldSelect -- diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 52012806699aa..6cf828ca8d0dc 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1286,6 +1286,22 @@ drop table cchild; SELECT viewname, definition FROM pg_views WHERE schemaname = 'pg_catalog' ORDER BY viewname; +pg_aios| SELECT pid, + io_id, + io_generation, + state, + operation, + off, + length, + target, + handle_data_len, + raw_result, + result, + target_desc, + f_sync, + f_localmem, + f_buffered + FROM pg_get_aios() pg_get_aios(pid, io_id, io_generation, state, operation, off, length, target, handle_data_len, raw_result, result, target_desc, f_sync, f_localmem, f_buffered); pg_available_extension_versions| SELECT e.name, e.version, (x.extname IS NOT NULL) AS installed, @@ -1305,7 +1321,6 @@ pg_available_extensions| SELECT e.name, LEFT JOIN pg_extension x ON ((e.name = x.extname))); pg_backend_memory_contexts| SELECT name, ident, - parent, type, level, path, @@ -1314,7 +1329,7 @@ pg_backend_memory_contexts| SELECT name, free_bytes, free_chunks, used_bytes - FROM pg_get_backend_memory_contexts() pg_get_backend_memory_contexts(name, ident, parent, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes); + FROM pg_get_backend_memory_contexts() pg_get_backend_memory_contexts(name, ident, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes); pg_config| SELECT name, setting FROM pg_config() pg_config(name, setting); @@ -1475,12 +1490,13 @@ pg_replication_slots| SELECT l.slot_name, l.wal_status, l.safe_wal_size, l.two_phase, + l.two_phase_at, l.inactive_since, l.conflicting, l.invalidation_reason, l.failover, l.synced - FROM (pg_get_replication_slots() l(slot_name, plugin, slot_type, datoid, temporary, active, active_pid, xmin, catalog_xmin, restart_lsn, confirmed_flush_lsn, wal_status, safe_wal_size, two_phase, inactive_since, conflicting, invalidation_reason, failover, synced) + FROM (pg_get_replication_slots() l(slot_name, plugin, slot_type, datoid, temporary, active, active_pid, xmin, catalog_xmin, restart_lsn, confirmed_flush_lsn, wal_status, safe_wal_size, two_phase, two_phase_at, inactive_since, conflicting, invalidation_reason, failover, synced) LEFT JOIN pg_database d ON ((l.datoid = d.oid))); pg_roles| SELECT pg_authid.rolname, pg_authid.rolsuper, @@ -1741,6 +1757,10 @@ pg_shmem_allocations| SELECT name, size, allocated_size FROM pg_get_shmem_allocations() pg_get_shmem_allocations(name, off, size, allocated_size); +pg_shmem_allocations_numa| SELECT name, + numa_node, + size + FROM pg_get_shmem_allocations_numa() pg_get_shmem_allocations_numa(name, numa_node, size); pg_stat_activity| SELECT s.datid, d.datname, s.pid, @@ -1805,7 +1825,11 @@ pg_stat_all_tables| SELECT c.oid AS relid, pg_stat_get_vacuum_count(c.oid) AS vacuum_count, pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count, pg_stat_get_analyze_count(c.oid) AS analyze_count, - pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count + pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count, + pg_stat_get_total_vacuum_time(c.oid) AS total_vacuum_time, + pg_stat_get_total_autovacuum_time(c.oid) AS total_autovacuum_time, + pg_stat_get_total_analyze_time(c.oid) AS total_analyze_time, + pg_stat_get_total_autoanalyze_time(c.oid) AS total_autoanalyze_time FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) @@ -1825,12 +1849,14 @@ pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_buf_written_clean() AS buffers_cle pg_stat_get_bgwriter_stat_reset_time() AS stats_reset; pg_stat_checkpointer| SELECT pg_stat_get_checkpointer_num_timed() AS num_timed, pg_stat_get_checkpointer_num_requested() AS num_requested, + pg_stat_get_checkpointer_num_performed() AS num_done, pg_stat_get_checkpointer_restartpoints_timed() AS restartpoints_timed, pg_stat_get_checkpointer_restartpoints_requested() AS restartpoints_req, pg_stat_get_checkpointer_restartpoints_performed() AS restartpoints_done, pg_stat_get_checkpointer_write_time() AS write_time, pg_stat_get_checkpointer_sync_time() AS sync_time, pg_stat_get_checkpointer_buffers_written() AS buffers_written, + pg_stat_get_checkpointer_slru_written() AS slru_written, pg_stat_get_checkpointer_stat_reset_time() AS stats_reset; pg_stat_database| SELECT oid AS datid, datname, @@ -1862,6 +1888,8 @@ pg_stat_database| SELECT oid AS datid, pg_stat_get_db_sessions_abandoned(oid) AS sessions_abandoned, pg_stat_get_db_sessions_fatal(oid) AS sessions_fatal, pg_stat_get_db_sessions_killed(oid) AS sessions_killed, + pg_stat_get_db_parallel_workers_to_launch(oid) AS parallel_workers_to_launch, + pg_stat_get_db_parallel_workers_launched(oid) AS parallel_workers_launched, pg_stat_get_db_stat_reset_time(oid) AS stats_reset FROM ( SELECT 0 AS oid, NULL::name AS datname @@ -1889,21 +1917,23 @@ pg_stat_io| SELECT backend_type, object, context, reads, + read_bytes, read_time, writes, + write_bytes, write_time, writebacks, writeback_time, extends, + extend_bytes, extend_time, - op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset - FROM pg_stat_get_io() b(backend_type, object, context, reads, read_time, writes, write_time, writebacks, writeback_time, extends, extend_time, op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset); + FROM pg_stat_get_io() b(backend_type, object, context, reads, read_bytes, read_time, writes, write_bytes, write_time, writebacks, writeback_time, extends, extend_bytes, extend_time, hits, evictions, reuses, fsyncs, fsync_time, stats_reset); pg_stat_progress_analyze| SELECT s.pid, s.datid, d.datname, @@ -1923,7 +1953,8 @@ pg_stat_progress_analyze| SELECT s.pid, s.param5 AS ext_stats_computed, s.param6 AS child_tables_total, s.param7 AS child_tables_done, - (s.param8)::oid AS current_child_table_relid + (s.param8)::oid AS current_child_table_relid, + ((s.param9)::double precision / (1000000)::double precision) AS delay_time FROM (pg_stat_get_progress_info('ANALYZE'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) LEFT JOIN pg_database d ON ((s.datid = d.oid))); pg_stat_progress_basebackup| SELECT pid, @@ -2053,7 +2084,8 @@ pg_stat_progress_vacuum| SELECT s.pid, s.param7 AS dead_tuple_bytes, s.param8 AS num_dead_item_ids, s.param9 AS indexes_total, - s.param10 AS indexes_processed + s.param10 AS indexes_processed, + ((s.param11)::double precision / (1000000)::double precision) AS delay_time FROM (pg_stat_get_progress_info('VACUUM'::text) s(pid, datid, relid, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) LEFT JOIN pg_database d ON ((s.datid = d.oid))); pg_stat_recovery_prefetch| SELECT stats_reset, @@ -2140,9 +2172,16 @@ pg_stat_subscription_stats| SELECT ss.subid, s.subname, ss.apply_error_count, ss.sync_error_count, + ss.confl_insert_exists, + ss.confl_update_origin_differs, + ss.confl_update_exists, + ss.confl_update_missing, + ss.confl_delete_origin_differs, + ss.confl_delete_missing, + ss.confl_multiple_unique_conflicts, ss.stats_reset FROM pg_subscription s, - LATERAL pg_stat_get_subscription_stats(s.oid) ss(subid, apply_error_count, sync_error_count, stats_reset); + LATERAL pg_stat_get_subscription_stats(s.oid) ss(subid, apply_error_count, sync_error_count, confl_insert_exists, confl_update_origin_differs, confl_update_exists, confl_update_missing, confl_delete_origin_differs, confl_delete_missing, confl_multiple_unique_conflicts, stats_reset); pg_stat_sys_indexes| SELECT relid, indexrelid, schemaname, @@ -2179,7 +2218,11 @@ pg_stat_sys_tables| SELECT relid, vacuum_count, autovacuum_count, analyze_count, - autoanalyze_count + autoanalyze_count, + total_vacuum_time, + total_autovacuum_time, + total_analyze_time, + total_autoanalyze_time FROM pg_stat_all_tables WHERE ((schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (schemaname ~ '^pg_toast'::text)); pg_stat_user_functions| SELECT p.oid AS funcid, @@ -2227,19 +2270,19 @@ pg_stat_user_tables| SELECT relid, vacuum_count, autovacuum_count, analyze_count, - autoanalyze_count + autoanalyze_count, + total_vacuum_time, + total_autovacuum_time, + total_analyze_time, + total_autoanalyze_time FROM pg_stat_all_tables WHERE ((schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (schemaname !~ '^pg_toast'::text)); pg_stat_wal| SELECT wal_records, wal_fpi, wal_bytes, wal_buffers_full, - wal_write, - wal_sync, - wal_write_time, - wal_sync_time, stats_reset - FROM pg_stat_get_wal() w(wal_records, wal_fpi, wal_bytes, wal_buffers_full, wal_write, wal_sync, wal_write_time, wal_sync_time, stats_reset); + FROM pg_stat_get_wal() w(wal_records, wal_fpi, wal_bytes, wal_buffers_full, stats_reset); pg_stat_wal_receiver| SELECT pid, status, receive_start_lsn, @@ -2618,10 +2661,19 @@ pg_tables| SELECT n.nspname AS schemaname, LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 'p'::"char"])); -pg_timezone_abbrevs| SELECT abbrev, - utc_offset, - is_dst - FROM pg_timezone_abbrevs() pg_timezone_abbrevs(abbrev, utc_offset, is_dst); +pg_timezone_abbrevs| SELECT z.abbrev, + z.utc_offset, + z.is_dst + FROM pg_timezone_abbrevs_zone() z(abbrev, utc_offset, is_dst) +UNION ALL + SELECT a.abbrev, + a.utc_offset, + a.is_dst + FROM pg_timezone_abbrevs_abbrevs() a(abbrev, utc_offset, is_dst) + WHERE (NOT (EXISTS ( SELECT 1 + FROM pg_timezone_abbrevs_zone() z2(abbrev, utc_offset, is_dst) + WHERE (z2.abbrev = a.abbrev)))) + ORDER BY 1; pg_timezone_names| SELECT name, abbrev, utc_offset, @@ -3638,7 +3690,10 @@ MERGE INTO rule_merge1 t USING (SELECT 1 AS a) s -- test deparsing CREATE TABLE sf_target(id int, data text, filling int[]); CREATE FUNCTION merge_sf_test() - RETURNS TABLE(action text, a int, b text, id int, data text, filling int[]) + RETURNS TABLE(action text, a int, b text, + id int, data text, filling int[], + old_id int, old_data text, old_filling int[], + new_id int, new_data text, new_filling int[]) LANGUAGE sql BEGIN ATOMIC MERGE INTO sf_target t @@ -3677,11 +3732,12 @@ WHEN NOT MATCHED THEN INSERT (filling[1], id) VALUES (s.a, s.a) RETURNING - merge_action() AS action, *; + WITH (OLD AS o, NEW AS n) + merge_action() AS action, *, o.*, n.*; END; \sf merge_sf_test CREATE OR REPLACE FUNCTION public.merge_sf_test() - RETURNS TABLE(action text, a integer, b text, id integer, data text, filling integer[]) + RETURNS TABLE(action text, a integer, b text, id integer, data text, filling integer[], old_id integer, old_data text, old_filling integer[], new_id integer, new_data text, new_filling integer[]) LANGUAGE sql BEGIN ATOMIC MERGE INTO sf_target t @@ -3719,12 +3775,18 @@ BEGIN ATOMIC WHEN NOT MATCHED THEN INSERT (filling[1], id) VALUES (s.a, s.a) - RETURNING MERGE_ACTION() AS action, + RETURNING WITH (OLD AS o, NEW AS n) MERGE_ACTION() AS action, s.a, s.b, t.id, t.data, - t.filling; + t.filling, + o.id, + o.data, + o.filling, + n.id, + n.data, + n.filling; END CREATE FUNCTION merge_sf_test2() RETURNS void diff --git a/src/test/regress/expected/select.out b/src/test/regress/expected/select.out index 33a6dceb0e32b..bab0cc93ff5ec 100644 --- a/src/test/regress/expected/select.out +++ b/src/test/regress/expected/select.out @@ -757,14 +757,15 @@ select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; (1 row) -- actually run the query with an analyze to use the partial index -explain (costs off, analyze on, timing off, summary off) +explain (costs off, analyze on, timing off, summary off, buffers off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; - QUERY PLAN ------------------------------------------------------------------ - Index Scan using onek2_u2_prtl on onek2 (actual rows=1 loops=1) + QUERY PLAN +-------------------------------------------------------------------- + Index Scan using onek2_u2_prtl on onek2 (actual rows=1.00 loops=1) Index Cond: (unique2 = 11) Filter: (stringu1 = 'ATAAAA'::name) -(3 rows) + Index Searches: 1 +(4 rows) explain (costs off) select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; diff --git a/src/test/regress/expected/select_distinct.out b/src/test/regress/expected/select_distinct.out index 82b8e54f5f170..379ba0bc9fa5a 100644 --- a/src/test/regress/expected/select_distinct.out +++ b/src/test/regress/expected/select_distinct.out @@ -464,3 +464,135 @@ SELECT null IS NOT DISTINCT FROM null as "yes"; t (1 row) +-- +-- Test the planner's ability to reorder the distinctClause Pathkeys to match +-- the input path's ordering +-- +CREATE TABLE distinct_tbl (x int, y int); +INSERT INTO distinct_tbl SELECT i%10, i%10 FROM generate_series(1, 1000) AS i; +CREATE INDEX distinct_tbl_x_y_idx ON distinct_tbl (x, y); +ANALYZE distinct_tbl; +-- Produce results with sorting. +SET enable_hashagg TO OFF; +-- Ensure we avoid the need to re-sort by reordering the distinctClause +-- Pathkeys to match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl; + QUERY PLAN +------------------------------------------------------------------ + Unique + -> Index Only Scan using distinct_tbl_x_y_idx on distinct_tbl +(2 rows) + +SELECT DISTINCT y, x FROM distinct_tbl; + y | x +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Ensure we leverage incremental-sort by reordering the distinctClause +-- Pathkeys to partially match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM (SELECT * FROM distinct_tbl ORDER BY x) s; + QUERY PLAN +------------------------------------------------------------------------------ + Unique + -> Incremental Sort + Sort Key: s.x, s.y + Presorted Key: s.x + -> Subquery Scan on s + -> Index Only Scan using distinct_tbl_x_y_idx on distinct_tbl +(6 rows) + +SELECT DISTINCT y, x FROM (SELECT * FROM distinct_tbl ORDER BY x) s; + y | x +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Ensure we avoid the need to re-sort in partial distinct by reordering the +-- distinctClause Pathkeys to match the ordering of the input path +SET parallel_tuple_cost=0; +SET parallel_setup_cost=0; +SET min_parallel_table_scan_size=0; +SET min_parallel_index_scan_size=0; +SET max_parallel_workers_per_gather=2; +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl limit 10; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Limit + -> Unique + -> Gather Merge + Workers Planned: 1 + -> Unique + -> Parallel Index Only Scan using distinct_tbl_x_y_idx on distinct_tbl +(6 rows) + +SELECT DISTINCT y, x FROM distinct_tbl limit 10; + y | x +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +RESET max_parallel_workers_per_gather; +RESET min_parallel_index_scan_size; +RESET min_parallel_table_scan_size; +RESET parallel_setup_cost; +RESET parallel_tuple_cost; +-- Ensure we reorder the distinctClause Pathkeys to match the ordering of the +-- input path even if there is ORDER BY clause +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl ORDER BY y; + QUERY PLAN +------------------------------------------------------------------------ + Sort + Sort Key: y + -> Unique + -> Index Only Scan using distinct_tbl_x_y_idx on distinct_tbl +(4 rows) + +SELECT DISTINCT y, x FROM distinct_tbl ORDER BY y; + y | x +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +RESET enable_hashagg; +DROP TABLE distinct_tbl; diff --git a/src/test/regress/expected/select_distinct_on.out b/src/test/regress/expected/select_distinct_on.out index b2978c1114a09..75b1e7d300f0a 100644 --- a/src/test/regress/expected/select_distinct_on.out +++ b/src/test/regress/expected/select_distinct_on.out @@ -81,13 +81,12 @@ select distinct on (1) floor(random()) as r, f1 from int4_tbl order by 1,2; EXPLAIN (COSTS OFF) SELECT DISTINCT ON (four) four,two FROM tenk1 WHERE four = 0 ORDER BY 1; - QUERY PLAN ----------------------------------- - Result - -> Limit - -> Seq Scan on tenk1 - Filter: (four = 0) -(4 rows) + QUERY PLAN +---------------------------- + Limit + -> Seq Scan on tenk1 + Filter: (four = 0) +(3 rows) -- and check the result of the above query is correct SELECT DISTINCT ON (four) four,two @@ -115,11 +114,135 @@ SELECT DISTINCT ON (four) four,two EXPLAIN (COSTS OFF) SELECT DISTINCT ON (four) four,hundred FROM tenk1 WHERE four = 0 ORDER BY 1,2; - QUERY PLAN ------------------------------------------------------ - Result - -> Limit - -> Index Scan using tenk1_hundred on tenk1 - Filter: (four = 0) + QUERY PLAN +----------------------------------------------- + Limit + -> Index Scan using tenk1_hundred on tenk1 + Filter: (four = 0) +(3 rows) + +-- +-- Test the planner's ability to reorder the distinctClause Pathkeys to match +-- the input path's ordering +-- +CREATE TABLE distinct_on_tbl (x int, y int, z int); +INSERT INTO distinct_on_tbl SELECT i%10, i%10, i%10 FROM generate_series(1, 1000) AS i; +CREATE INDEX distinct_on_tbl_x_y_idx ON distinct_on_tbl (x, y); +ANALYZE distinct_on_tbl; +-- Produce results with sorting. +SET enable_hashagg TO OFF; +-- Ensure we avoid the need to re-sort by reordering the distinctClause +-- Pathkeys to match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl; + QUERY PLAN +------------------------------------------------------------------------ + Unique + -> Index Only Scan using distinct_on_tbl_x_y_idx on distinct_on_tbl +(2 rows) + +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl; + x | y +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Ensure we leverage incremental-sort by reordering the distinctClause +-- Pathkeys to partially match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM (SELECT * FROM distinct_on_tbl ORDER BY x) s; + QUERY PLAN +------------------------------------------------------------------------------------ + Unique + -> Incremental Sort + Sort Key: s.x, s.y + Presorted Key: s.x + -> Subquery Scan on s + -> Index Only Scan using distinct_on_tbl_x_y_idx on distinct_on_tbl +(6 rows) + +SELECT DISTINCT ON (y, x) x, y FROM (SELECT * FROM distinct_on_tbl ORDER BY x) s; + x | y +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Ensure we reorder the distinctClause Pathkeys to match the ordering of the +-- input path even if there is ORDER BY clause +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl ORDER BY y; + QUERY PLAN +------------------------------------------------------------------------------ + Sort + Sort Key: y + -> Unique + -> Index Only Scan using distinct_on_tbl_x_y_idx on distinct_on_tbl (4 rows) +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl ORDER BY y; + x | y +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +-- Ensure the resulting pathkey list matches the initial distinctClause Pathkeys +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM (select * from distinct_on_tbl order by x, z, y) s ORDER BY y, x, z; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Sort + Sort Key: s.y, s.x, s.z + -> Unique + -> Incremental Sort + Sort Key: s.x, s.y, s.z + Presorted Key: s.x + -> Subquery Scan on s + -> Sort + Sort Key: distinct_on_tbl.x, distinct_on_tbl.z, distinct_on_tbl.y + -> Seq Scan on distinct_on_tbl +(10 rows) + +SELECT DISTINCT ON (y, x) x, y FROM (select * from distinct_on_tbl order by x, z, y) s ORDER BY y, x, z; + x | y +---+--- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +RESET enable_hashagg; +DROP TABLE distinct_on_tbl; diff --git a/src/test/regress/expected/select_into.out b/src/test/regress/expected/select_into.out index b79fe9a1c0e28..d04ca2b1bf713 100644 --- a/src/test/regress/expected/select_into.out +++ b/src/test/regress/expected/select_into.out @@ -25,19 +25,19 @@ CREATE TABLE selinto_schema.tbl_withdata1 (a) AS SELECT generate_series(1,3) WITH DATA; INSERT INTO selinto_schema.tbl_withdata1 VALUES (4); ERROR: permission denied for table tbl_withdata1 -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_withdata2 (a) AS SELECT generate_series(1,3) WITH DATA; - QUERY PLAN --------------------------------------- - ProjectSet (actual rows=3 loops=1) - -> Result (actual rows=1 loops=1) + QUERY PLAN +----------------------------------------- + ProjectSet (actual rows=3.00 loops=1) + -> Result (actual rows=1.00 loops=1) (2 rows) -- WITH NO DATA, passes. CREATE TABLE selinto_schema.tbl_nodata1 (a) AS SELECT generate_series(1,3) WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_nodata2 (a) AS SELECT generate_series(1,3) WITH NO DATA; QUERY PLAN @@ -50,19 +50,19 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) PREPARE data_sel AS SELECT generate_series(1,3); CREATE TABLE selinto_schema.tbl_withdata3 (a) AS EXECUTE data_sel WITH DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_withdata4 (a) AS EXECUTE data_sel WITH DATA; - QUERY PLAN --------------------------------------- - ProjectSet (actual rows=3 loops=1) - -> Result (actual rows=1 loops=1) + QUERY PLAN +----------------------------------------- + ProjectSet (actual rows=3.00 loops=1) + -> Result (actual rows=1.00 loops=1) (2 rows) -- EXECUTE and WITH NO DATA, passes. CREATE TABLE selinto_schema.tbl_nodata3 (a) AS EXECUTE data_sel WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_nodata4 (a) AS EXECUTE data_sel WITH NO DATA; QUERY PLAN diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index 5a603f86b7366..0185ef661b135 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -1,6 +1,17 @@ -- -- PARALLEL -- +-- Save parallel worker stats, used for comparison at the end +select pg_stat_force_next_flush(); + pg_stat_force_next_flush +-------------------------- + +(1 row) + +select parallel_workers_to_launch as parallel_workers_to_launch_before, + parallel_workers_launched as parallel_workers_launched_before + from pg_stat_database + where datname = current_database() \gset create function sp_parallel_restricted(int) returns int as $$begin return $1; end$$ language plpgsql parallel restricted; begin; @@ -538,15 +549,18 @@ explain (costs off) ------------------------------------------------------------ Aggregate -> Nested Loop - -> Seq Scan on tenk2 - Filter: (thousand = 0) + -> Gather + Workers Planned: 4 + -> Parallel Seq Scan on tenk2 + Disabled: true + Filter: (thousand = 0) -> Gather Workers Planned: 4 -> Parallel Bitmap Heap Scan on tenk1 Recheck Cond: (hundred > 1) -> Bitmap Index Scan on tenk1_hundred Index Cond: (hundred > 1) -(10 rows) +(13 rows) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; count @@ -566,20 +580,20 @@ select count(*) from bmscantest where a>1; -- test accumulation of stats for parallel nodes reset enable_seqscan; alter table tenk2 set (parallel_workers = 0); -explain (analyze, timing off, summary off, costs off) +explain (analyze, timing off, summary off, costs off, buffers off) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; - QUERY PLAN --------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=1) - -> Nested Loop (actual rows=98000 loops=1) - -> Seq Scan on tenk2 (actual rows=10 loops=1) + QUERY PLAN +----------------------------------------------------------------------------- + Aggregate (actual rows=1.00 loops=1) + -> Nested Loop (actual rows=98000.00 loops=1) + -> Seq Scan on tenk2 (actual rows=10.00 loops=1) Filter: (thousand = 0) Rows Removed by Filter: 9990 - -> Gather (actual rows=9800 loops=10) + -> Gather (actual rows=9800.00 loops=10) Workers Planned: 4 Workers Launched: 4 - -> Parallel Seq Scan on tenk1 (actual rows=1960 loops=50) + -> Parallel Seq Scan on tenk1 (actual rows=1960.00 loops=50) Filter: (hundred > 1) Rows Removed by Filter: 40 (11 rows) @@ -592,7 +606,7 @@ $$ declare ln text; begin for ln in - explain (analyze, timing off, summary off, costs off) + explain (analyze, timing off, summary off, costs off, buffers off) select * from (select ten from tenk1 where ten < 100 order by ten) ss right join (values (1),(2),(3)) v(x) on true @@ -603,21 +617,21 @@ begin end; $$; select * from explain_parallel_sort_stats(); - explain_parallel_sort_stats --------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=30000 loops=1) - -> Values Scan on "*VALUES*" (actual rows=3 loops=1) - -> Gather Merge (actual rows=10000 loops=3) + explain_parallel_sort_stats +----------------------------------------------------------------------------- + Nested Loop Left Join (actual rows=30000.00 loops=1) + -> Values Scan on "*VALUES*" (actual rows=3.00 loops=1) + -> Gather Merge (actual rows=10000.00 loops=3) Workers Planned: 4 Workers Launched: 4 - -> Sort (actual rows=2000 loops=15) + -> Sort (actual rows=2000.00 loops=15) Sort Key: tenk1.ten Sort Method: quicksort Memory: xxx Worker 0: Sort Method: quicksort Memory: xxx Worker 1: Sort Method: quicksort Memory: xxx Worker 2: Sort Method: quicksort Memory: xxx Worker 3: Sort Method: quicksort Memory: xxx - -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=15) + -> Parallel Seq Scan on tenk1 (actual rows=2000.00 loops=15) Filter: (ten < 100) (14 rows) @@ -1116,9 +1130,10 @@ explain (costs off, verbose) Aggregate Output: count(*) -> Hash Right Semi Join - Hash Cond: ((b.unique1 = a.unique1) AND ((row_number() OVER (?)) = a.two)) + Hash Cond: ((b.unique1 = a.unique1) AND ((row_number() OVER w1) = a.two)) -> WindowAgg - Output: b.unique1, row_number() OVER (?) + Output: b.unique1, row_number() OVER w1 + Window: w1 AS (ROWS UNBOUNDED PRECEDING) -> Gather Output: b.unique1 Workers Planned: 4 @@ -1131,7 +1146,7 @@ explain (costs off, verbose) Workers Planned: 4 -> Parallel Seq Scan on public.tenk1 a Output: a.unique1, a.two -(18 rows) +(19 rows) -- LIMIT/OFFSET within sub-selects can't be pushed to workers. explain (costs off) @@ -1155,13 +1170,13 @@ explain (costs off) -- to increase the parallel query test coverage SAVEPOINT settings; SET LOCAL debug_parallel_query = 1; -EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1; - QUERY PLAN -------------------------------------------------------------- - Gather (actual rows=10000 loops=1) +EXPLAIN (analyze, timing off, summary off, costs off, buffers off) SELECT * FROM tenk1; + QUERY PLAN +---------------------------------------------------------------- + Gather (actual rows=10000.00 loops=1) Workers Planned: 4 Workers Launched: 4 - -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) + -> Parallel Seq Scan on tenk1 (actual rows=2000.00 loops=5) (4 rows) ROLLBACK TO SAVEPOINT settings; @@ -1329,3 +1344,94 @@ SELECT 1 FROM tenk1_vw_sec (9 rows) rollback; +-- test that a newly-created session role propagates to workers. +begin; +create role regress_parallel_worker; +set session authorization regress_parallel_worker; +select current_setting('session_authorization'); + current_setting +------------------------- + regress_parallel_worker +(1 row) + +set debug_parallel_query = 1; +select current_setting('session_authorization'); + current_setting +------------------------- + regress_parallel_worker +(1 row) + +rollback; +-- test that function option SET ROLE works in parallel workers. +create role regress_parallel_worker; +create function set_and_report_role() returns text as + $$ select current_setting('role') $$ language sql parallel safe + set role = regress_parallel_worker; +create function set_role_and_error(int) returns int as + $$ select 1 / $1 $$ language sql parallel safe + set role = regress_parallel_worker; +set debug_parallel_query = 0; +select set_and_report_role(); + set_and_report_role +------------------------- + regress_parallel_worker +(1 row) + +select set_role_and_error(0); +ERROR: division by zero +CONTEXT: SQL function "set_role_and_error" statement 1 +set debug_parallel_query = 1; +select set_and_report_role(); + set_and_report_role +------------------------- + regress_parallel_worker +(1 row) + +select set_role_and_error(0); +ERROR: division by zero +CONTEXT: SQL function "set_role_and_error" statement 1 +parallel worker +reset debug_parallel_query; +drop function set_and_report_role(); +drop function set_role_and_error(int); +drop role regress_parallel_worker; +-- don't freeze in ParallelFinish while holding an LWLock +BEGIN; +CREATE FUNCTION my_cmp (int4, int4) +RETURNS int LANGUAGE sql AS +$$ + SELECT + CASE WHEN $1 < $2 THEN -1 + WHEN $1 > $2 THEN 1 + ELSE 0 + END; +$$; +CREATE TABLE parallel_hang (i int4); +INSERT INTO parallel_hang + (SELECT * FROM generate_series(1, 400) gs); +CREATE OPERATOR CLASS int4_custom_ops FOR TYPE int4 USING btree AS + OPERATOR 1 < (int4, int4), OPERATOR 2 <= (int4, int4), + OPERATOR 3 = (int4, int4), OPERATOR 4 >= (int4, int4), + OPERATOR 5 > (int4, int4), FUNCTION 1 my_cmp(int4, int4); +CREATE UNIQUE INDEX parallel_hang_idx + ON parallel_hang + USING btree (i int4_custom_ops); +SET debug_parallel_query = on; +DELETE FROM parallel_hang WHERE 380 <= i AND i <= 420; +ROLLBACK; +-- Check parallel worker stats +select pg_stat_force_next_flush(); + pg_stat_force_next_flush +-------------------------- + +(1 row) + +select parallel_workers_to_launch > :'parallel_workers_to_launch_before' AS wrk_to_launch, + parallel_workers_launched > :'parallel_workers_launched_before' AS wrk_launched + from pg_stat_database + where datname = current_database(); + wrk_to_launch | wrk_launched +---------------+-------------- + t | t +(1 row) + diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out index 2b47b7796b108..15925d99c8a38 100644 --- a/src/test/regress/expected/sequence.out +++ b/src/test/regress/expected/sequence.out @@ -839,4 +839,11 @@ SELECT nextval('test_seq1'); 3 (1 row) +-- pg_get_sequence_data +SELECT * FROM pg_get_sequence_data('test_seq1'); + last_value | is_called +------------+----------- + 10 | t +(1 row) + DROP SEQUENCE test_seq1; diff --git a/src/test/regress/expected/sqljson.out b/src/test/regress/expected/sqljson.out index 4f91e2117ef94..625acf3019a38 100644 --- a/src/test/regress/expected/sqljson.out +++ b/src/test/regress/expected/sqljson.out @@ -272,7 +272,7 @@ SELECT pg_typeof(JSON_SERIALIZE(NULL)); -- only string types or bytea allowed SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING jsonb); -ERROR: cannot use RETURNING type jsonb in JSON_SERIALIZE() +ERROR: cannot use type jsonb in RETURNING clause of JSON_SERIALIZE() HINT: Try returning a string type or bytea. EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}'); QUERY PLAN @@ -337,6 +337,8 @@ LINE 1: SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING UTF8)... ^ SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING); ERROR: unrecognized JSON encoding: invalid_encoding +LINE 1: ...T JSON_OBJECT(RETURNING text FORMAT JSON ENCODING INVALID_EN... + ^ SELECT JSON_OBJECT(RETURNING bytea); json_object ------------- @@ -537,6 +539,8 @@ SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 ABSENT ON NULL); {"a" : "1", "c" : 2} (1 row) +SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, repeat('x', 1000): 1, 2: repeat('a', 100) WITH UNIQUE); +ERROR: duplicate JSON object key value: "2" SELECT JSON_OBJECT(1: 1, '1': NULL WITH UNIQUE); ERROR: duplicate JSON object key value: "1" SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE); @@ -569,6 +573,18 @@ SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WIT {"1": 1, "3": 1, "5": "a"} (1 row) +-- BUG: https://postgr.es/m/CADXhmgTJtJZK9A3Na_ry%2BXrq-ghjcejBRhcRMzWZvbd__QdgJA%40mail.gmail.com +-- datum_to_jsonb_internal() didn't catch keys that are casts instead of a simple scalar +CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral'); +CREATE FUNCTION mood_to_json(mood) RETURNS json AS $$ + SELECT to_json($1::text); +$$ LANGUAGE sql IMMUTABLE; +CREATE CAST (mood AS json) WITH FUNCTION mood_to_json(mood) AS IMPLICIT; +SELECT JSON_OBJECT('happy'::mood: '123'::jsonb); +ERROR: key value must be scalar, not array, composite, or json +DROP CAST (mood AS json); +DROP FUNCTION mood_to_json; +DROP TYPE mood; -- JSON_ARRAY() SELECT JSON_ARRAY(); json_array @@ -618,6 +634,8 @@ LINE 1: SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING UTF8); ^ SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING); ERROR: unrecognized JSON encoding: invalid_encoding +LINE 1: ...CT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING INVALID_EN... + ^ SELECT JSON_ARRAY(RETURNING bytea); json_array ------------ @@ -733,6 +751,12 @@ SELECT JSON_ARRAY(SELECT i FROM (VALUES (3), (1), (NULL), (2)) foo(i) ORDER BY i [1, 2, 3] (1 row) +SELECT JSON_ARRAY(WITH x AS (SELECT 1) VALUES (TRUE)); + json_array +------------ + [true] +(1 row) + -- Should fail SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i)); ERROR: subquery must return only one column @@ -815,22 +839,22 @@ SELECT FROM (VALUES (NULL), (3), (1), (NULL), (NULL), (5), (2), (4), (NULL)) foo(bar); -[ RECORD 1 ]--------------------+------------------------------------------------------------------------------------------------------------------------- -no_options | [1, 2, 3, 4, 5] -returning_jsonb | [1, 2, 3, 4, 5] -absent_on_null | [1, 2, 3, 4, 5] -absentonnull_returning_jsonb | [1, 2, 3, 4, 5] -null_on_null | [1, 2, 3, 4, 5, null, null, null, null] -nullonnull_returning_jsonb | [1, 2, 3, 4, 5, null, null, null, null] -row_no_options | [{"bar":1}, + - | {"bar":2}, + +no_options | [3, 1, 5, 2, 4] +returning_jsonb | [3, 1, 5, 2, 4] +absent_on_null | [3, 1, 5, 2, 4] +absentonnull_returning_jsonb | [3, 1, 5, 2, 4] +null_on_null | [null, 3, 1, null, null, 5, 2, 4, null] +nullonnull_returning_jsonb | [null, 3, 1, null, null, 5, 2, 4, null] +row_no_options | [{"bar":null}, + | {"bar":3}, + - | {"bar":4}, + - | {"bar":5}, + - | {"bar":null}, + + | {"bar":1}, + | {"bar":null}, + | {"bar":null}, + + | {"bar":5}, + + | {"bar":2}, + + | {"bar":4}, + | {"bar":null}] -row_returning_jsonb | [{"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 5}, {"bar": null}, {"bar": null}, {"bar": null}, {"bar": null}] +row_returning_jsonb | [{"bar": null}, {"bar": 3}, {"bar": 1}, {"bar": null}, {"bar": null}, {"bar": 5}, {"bar": 2}, {"bar": 4}, {"bar": null}] row_filtered_agg | [{"bar":3}, + | {"bar":4}, + | {"bar":5}] @@ -921,6 +945,9 @@ FROM (VALUES (1, 1), (0, NULL),(4, null), (5, null),(6, null),(2, 2)) foo(k, v); {"1": 1, "2": 2} (1 row) +SELECT JSON_OBJECTAGG(mod(i,100): (i)::text FORMAT JSON WITH UNIQUE) +FROM generate_series(0, 199) i; +ERROR: duplicate JSON object key value: "0" -- Test JSON_OBJECT deparsing EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json); @@ -1002,17 +1029,18 @@ FROM generate_series(1,5) i; EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) OVER (PARTITION BY i % 2) FROM generate_series(1,5) i; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- WindowAgg - Output: JSON_OBJECTAGG(i : (('111'::text || (i)::text))::bytea FORMAT JSON WITH UNIQUE KEYS RETURNING text) OVER (?), ((i % 2)) + Output: JSON_OBJECTAGG(i : (('111'::text || (i)::text))::bytea FORMAT JSON WITH UNIQUE KEYS RETURNING text) OVER w1, ((i % 2)) + Window: w1 AS (PARTITION BY ((i.i % 2))) -> Sort Output: ((i % 2)), i Sort Key: ((i.i % 2)) -> Function Scan on pg_catalog.generate_series i Output: (i % 2), i Function Call: generate_series(1, 5) -(8 rows) +(9 rows) CREATE VIEW json_objectagg_view AS SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) FILTER (WHERE i > 3) @@ -1038,17 +1066,18 @@ FROM generate_series(1,5) i; EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER (PARTITION BY i % 2) FROM generate_series(1,5) i; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- WindowAgg - Output: JSON_ARRAYAGG((('111'::text || (i)::text))::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER (?), ((i % 2)) + Output: JSON_ARRAYAGG((('111'::text || (i)::text))::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER w1, ((i % 2)) + Window: w1 AS (PARTITION BY ((i.i % 2))) -> Sort Output: ((i % 2)), i Sort Key: ((i.i % 2)) -> Function Scan on pg_catalog.generate_series i Output: (i % 2), i Function Call: generate_series(1, 5) -(8 rows) +(9 rows) CREATE VIEW json_arrayagg_view AS SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i > 3) @@ -1295,3 +1324,52 @@ SELECT JSON_SERIALIZE('123' RETURNING sqljson_char2); ERROR: value too long for type character(2) SELECT JSON_SERIALIZE('12' RETURNING sqljson_char2); ERROR: value for domain sqljson_char2 violates check constraint "sqljson_char2_check" +-- Bug #18657: JsonValueExpr.raw_expr was not initialized in ExecInitExprRec() +-- causing the Aggrefs contained in it to also not be initialized, which led +-- to a crash in ExecBuildAggTrans() as mentioned in the bug report: +-- https://postgr.es/m/18657-1b90ccce2b16bdb8@postgresql.org +CREATE FUNCTION volatile_one() RETURNS int AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql VOLATILE; +CREATE FUNCTION stable_one() RETURNS int AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql STABLE; +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': volatile_one() RETURNING text) FORMAT JSON); + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Aggregate + Output: JSON_OBJECT('a' : JSON_OBJECTAGG('b' : volatile_one() RETURNING text) FORMAT JSON RETURNING json) + -> Result +(3 rows) + +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': volatile_one() RETURNING text) FORMAT JSON); + json_object +--------------------- + {"a" : { "b" : 1 }} +(1 row) + +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': stable_one() RETURNING text) FORMAT JSON); + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Aggregate + Output: JSON_OBJECT('a' : JSON_OBJECTAGG('b' : stable_one() RETURNING text) FORMAT JSON RETURNING json) + -> Result +(3 rows) + +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': stable_one() RETURNING text) FORMAT JSON); + json_object +--------------------- + {"a" : { "b" : 1 }} +(1 row) + +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': 1 RETURNING text) FORMAT JSON); + QUERY PLAN +------------------------------------------------------------------------------------------------ + Aggregate + Output: JSON_OBJECT('a' : JSON_OBJECTAGG('b' : 1 RETURNING text) FORMAT JSON RETURNING json) + -> Result +(3 rows) + +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': 1 RETURNING text) FORMAT JSON); + json_object +--------------------- + {"a" : { "b" : 1 }} +(1 row) + +DROP FUNCTION volatile_one, stable_one; diff --git a/src/test/regress/expected/sqljson_jsontable.out b/src/test/regress/expected/sqljson_jsontable.out index fcad9cc02891a..458c5aaa5b068 100644 --- a/src/test/regress/expected/sqljson_jsontable.out +++ b/src/test/regress/expected/sqljson_jsontable.out @@ -175,7 +175,7 @@ FROM json_table_test vals [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 6 | f | 0 | | false [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 7 | f | 0 | | false [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 8 | f | 0 | | false - [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 9 | t | 0 | | true + [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 9 | t | 1 | 1 | true [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 10 | f | 0 | | false [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 11 | f | 0 | | false (14 rows) @@ -474,6 +474,7 @@ SELECT * FROM "Async Capable": false, + "Table Function Name": "json_table", + "Alias": "json_table_func", + + "Disabled": false, + "Output": ["id", "\"int\"", "text"], + "Table Function Call": "JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_0 PASSING 3 AS a, '\"foo\"'::jsonb AS \"b c\" COLUMNS (id FOR ORDINALITY, \"int\" integer PATH '$', text text PATH '$'))"+ } + @@ -489,7 +490,7 @@ DROP VIEW jsonb_table_view6; DROP DOMAIN jsonb_test_domain; -- JSON_TABLE: only one FOR ORDINALITY columns allowed SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (id FOR ORDINALITY, id2 FOR ORDINALITY, a int PATH '$.a' ERROR ON EMPTY)) jt; -ERROR: cannot use more than one FOR ORDINALITY column +ERROR: only one FOR ORDINALITY column is allowed LINE 1: ..._TABLE(jsonb '1', '$' COLUMNS (id FOR ORDINALITY, id2 FOR OR... ^ SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (id FOR ORDINALITY, a int PATH '$' ERROR ON EMPTY)) jt; @@ -549,28 +550,75 @@ SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'lax $.a' DEFAULT (1 row) -- JSON_TABLE: EXISTS PATH types -SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a')); +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a' ERROR ON ERROR)); -- ok; can cast to int4 a --- 0 (1 row) +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$' ERROR ON ERROR)); -- ok; can cast to int4 + a +--- + 1 +(1 row) + SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2 EXISTS PATH '$.a')); -ERROR: cannot cast behavior expression of type boolean to smallint +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: invalid input syntax for type smallint: "false" SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8 EXISTS PATH '$.a')); -ERROR: cannot cast behavior expression of type boolean to bigint +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: invalid input syntax for type bigint: "false" SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4 EXISTS PATH '$.a')); -ERROR: cannot cast behavior expression of type boolean to real -SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(5) EXISTS PATH '$.a')); +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: invalid input syntax for type real: "false" +-- Default FALSE (ON ERROR) doesn't fit char(3) +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a')); +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: value too long for type character(3) +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a' ERROR ON ERROR)); +ERROR: value too long for type character(3) +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(5) EXISTS PATH '$.a' ERROR ON ERROR)); a ------- false (1 row) SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXISTS PATH '$.a')); -ERROR: cannot cast behavior expression of type boolean to json + a +------- + false +(1 row) + SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EXISTS PATH '$.a')); -ERROR: cannot cast behavior expression of type boolean to jsonb + a +------- + false +(1 row) + +-- EXISTS PATH domain over int +CREATE DOMAIN dint4 AS int; +CREATE DOMAIN dint4_0 AS int CHECK (VALUE <> 0 ); +SELECT a, a::bool FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a dint4 EXISTS PATH '$.a' )); + a | a +---+--- + 0 | f +(1 row) + +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b')); +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: value for domain dint4_0 violates check constraint "dint4_0_check" +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' ERROR ON ERROR)); +ERROR: value for domain dint4_0 violates check constraint "dint4_0_check" +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' FALSE ON ERROR)); +ERROR: could not coerce ON ERROR expression (FALSE) to the RETURNING type +DETAIL: value for domain dint4_0 violates check constraint "dint4_0_check" +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' TRUE ON ERROR)); + a | a +---+--- + 1 | t +(1 row) + +DROP DOMAIN dint4, dint4_0; -- JSON_TABLE: WRAPPER/QUOTES clauses on scalar columns SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' KEEP QUOTES ON SCALAR STRING)); item @@ -662,8 +710,8 @@ LINE 1: SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || '... ^ -- JsonPathQuery() error message mentioning column name SELECT * FROM JSON_TABLE('{"a": [{"b": "1"}, {"b": "2"}]}', '$' COLUMNS (b json path '$.a[*].b' ERROR ON ERROR)); -ERROR: JSON path expression for column "b" should return single item without wrapper -HINT: Use WITH WRAPPER clause to wrap SQL/JSON items into array. +ERROR: JSON path expression for column "b" must return single item when no wrapper is requested +HINT: Use the WITH WRAPPER clause to wrap SQL/JSON items into an array. -- JSON_TABLE: nested paths -- Duplicate path names SELECT * FROM JSON_TABLE( @@ -1079,9 +1127,54 @@ SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int omit quotes true on error ERROR: invalid ON ERROR behavior for column "a" LINE 1: ...N_TABLE(jsonb '1', '$' COLUMNS (a int omit quotes true on er... ^ -DETAIL: Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for formatted columns. +DETAIL: Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for formatted columns. SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int exists empty object on error)); ERROR: invalid ON ERROR behavior for column "a" LINE 1: ...M JSON_TABLE(jsonb '1', '$' COLUMNS (a int exists empty obje... ^ DETAIL: Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in ON ERROR for EXISTS columns. +-- Test JSON_TABLE() column deparsing -- don't emit default ON ERROR / EMPTY +-- behavior +CREATE VIEW json_table_view8 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$')); +\sv json_table_view8; +CREATE OR REPLACE VIEW public.json_table_view8 AS + SELECT a + FROM JSON_TABLE( + '"a"'::text, '$' AS json_table_path_0 + COLUMNS ( + a text PATH '$' + ) + ) +CREATE VIEW json_table_view9 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); +\sv json_table_view9; +CREATE OR REPLACE VIEW public.json_table_view9 AS + SELECT a + FROM JSON_TABLE( + '"a"'::text, '$' AS json_table_path_0 + COLUMNS ( + a text PATH '$' + ) ERROR ON ERROR + ) +DROP VIEW json_table_view8, json_table_view9; +-- Test JSON_TABLE() deparsing -- don't emit default ON ERROR behavior +CREATE VIEW json_table_view8 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ON ERROR); +\sv json_table_view8; +CREATE OR REPLACE VIEW public.json_table_view8 AS + SELECT a + FROM JSON_TABLE( + '"a"'::text, '$' AS json_table_path_0 + COLUMNS ( + a text PATH '$' + ) + ) +CREATE VIEW json_table_view9 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ARRAY ON ERROR); +\sv json_table_view9; +CREATE OR REPLACE VIEW public.json_table_view9 AS + SELECT a + FROM JSON_TABLE( + '"a"'::text, '$' AS json_table_path_0 + COLUMNS ( + a text PATH '$' + ) + ) +DROP VIEW json_table_view8, json_table_view9; diff --git a/src/test/regress/expected/sqljson_queryfuncs.out b/src/test/regress/expected/sqljson_queryfuncs.out index bdadf4b788e64..5a35aeb7bba3a 100644 --- a/src/test/regress/expected/sqljson_queryfuncs.out +++ b/src/test/regress/expected/sqljson_queryfuncs.out @@ -344,7 +344,7 @@ SELECT JSON_VALUE(jsonb '[]', '$'); (1 row) SELECT JSON_VALUE(jsonb '[]', '$' ERROR ON ERROR); -ERROR: JSON path expression in JSON_VALUE should return single scalar item +ERROR: JSON path expression in JSON_VALUE must return single scalar item SELECT JSON_VALUE(jsonb '{}', '$'); json_value ------------ @@ -352,7 +352,7 @@ SELECT JSON_VALUE(jsonb '{}', '$'); (1 row) SELECT JSON_VALUE(jsonb '{}', '$' ERROR ON ERROR); -ERROR: JSON path expression in JSON_VALUE should return single scalar item +ERROR: JSON path expression in JSON_VALUE must return single scalar item SELECT JSON_VALUE(jsonb '1', '$.a'); json_value ------------ @@ -408,7 +408,7 @@ SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT '2' ON EMPTY DEFAULT '3' ON ERROR SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON EMPTY DEFAULT '3' ON ERROR); ERROR: no SQL/JSON item found for specified path SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' ERROR ON ERROR); -ERROR: JSON path expression in JSON_VALUE should return single scalar item +ERROR: JSON path expression in JSON_VALUE must return single scalar item SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' DEFAULT '0' ON ERROR); json_value ------------ @@ -541,11 +541,11 @@ SELECT JSON_VALUE(NULL::jsonb, '$'); (1 row) SELECT - JSON_QUERY(js, '$'), - JSON_QUERY(js, '$' WITHOUT WRAPPER), - JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER), - JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER), - JSON_QUERY(js, '$' WITH ARRAY WRAPPER) + JSON_QUERY(js, '$') AS "unspec", + JSON_QUERY(js, '$' WITHOUT WRAPPER) AS "without", + JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER) AS "with cond", + JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER) AS "with uncond", + JSON_QUERY(js, '$' WITH ARRAY WRAPPER) AS "with" FROM (VALUES (jsonb 'null'), @@ -555,12 +555,12 @@ FROM ('[1, null, "2"]'), ('{"a": 1, "b": [2]}') ) foo(js); - json_query | json_query | json_query | json_query | json_query + unspec | without | with cond | with uncond | with --------------------+--------------------+--------------------+----------------------+---------------------- - null | null | [null] | [null] | [null] - 12.3 | 12.3 | [12.3] | [12.3] | [12.3] - true | true | [true] | [true] | [true] - "aaa" | "aaa" | ["aaa"] | ["aaa"] | ["aaa"] + null | null | null | [null] | [null] + 12.3 | 12.3 | 12.3 | [12.3] | [12.3] + true | true | true | [true] | [true] + "aaa" | "aaa" | "aaa" | ["aaa"] | ["aaa"] [1, null, "2"] | [1, null, "2"] | [1, null, "2"] | [[1, null, "2"]] | [[1, null, "2"]] {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | [{"a": 1, "b": [2]}] | [{"a": 1, "b": [2]}] (6 rows) @@ -587,10 +587,10 @@ FROM --------------------+--------------------+---------------------+----------------------+---------------------- | | | | | | | | - null | null | [null] | [null] | [null] - 12.3 | 12.3 | [12.3] | [12.3] | [12.3] - true | true | [true] | [true] | [true] - "aaa" | "aaa" | ["aaa"] | ["aaa"] | ["aaa"] + null | null | null | [null] | [null] + 12.3 | 12.3 | 12.3 | [12.3] | [12.3] + true | true | true | [true] | [true] + "aaa" | "aaa" | "aaa" | ["aaa"] | ["aaa"] [1, 2, 3] | [1, 2, 3] | [1, 2, 3] | [[1, 2, 3]] | [[1, 2, 3]] {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | [{"a": 1, "b": [2]}] | [{"a": 1, "b": [2]}] | | [1, "2", null, [3]] | [1, "2", null, [3]] | [1, "2", null, [3]] @@ -662,7 +662,11 @@ SELECT JSON_QUERY(jsonb '"aaa"', '$.a' RETURNING char(2) OMIT QUOTES DEFAULT 'bb (1 row) SELECT JSON_QUERY(jsonb '"aaa"', '$.a' RETURNING char(2) OMIT QUOTES DEFAULT '"bb"'::jsonb ON EMPTY); -ERROR: value too long for type character(2) + json_query +------------ + bb +(1 row) + -- OMIT QUOTES behavior should not be specified when WITH WRAPPER used: -- Should fail SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES); @@ -677,7 +681,7 @@ LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER ... SELECT JSON_QUERY(jsonb '["1"]', '$[*]' WITH CONDITIONAL WRAPPER KEEP QUOTES); json_query ------------ - ["1"] + "1" (1 row) SELECT JSON_QUERY(jsonb '["1"]', '$[*]' WITH UNCONDITIONAL WRAPPER KEEP QUOTES); @@ -802,8 +806,8 @@ SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON ERROR); -- NULL ON EMPTY (1 row) SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' ERROR ON ERROR); -ERROR: JSON path expression in JSON_QUERY should return single item without wrapper -HINT: Use WITH WRAPPER clause to wrap SQL/JSON items into array. +ERROR: JSON path expression in JSON_QUERY must return single item when no wrapper is requested +HINT: Use the WITH WRAPPER clause to wrap SQL/JSON items into an array. SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' DEFAULT '"empty"' ON ERROR); json_query ------------ @@ -865,13 +869,17 @@ SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING bytea FORMAT JSON); (1 row) SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea EMPTY OBJECT ON ERROR); -ERROR: cannot cast behavior expression of type jsonb to bytea -LINE 1: ... JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea EMPTY OBJE... - ^ + json_query +------------ + \x7b7d +(1 row) + SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea FORMAT JSON EMPTY OBJECT ON ERROR); -ERROR: cannot cast behavior expression of type jsonb to bytea -LINE 1: ...jsonb '[1,2]', '$[*]' RETURNING bytea FORMAT JSON EMPTY OBJE... - ^ + json_query +------------ + \x7b7d +(1 row) + SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING json EMPTY OBJECT ON ERROR); json_query ------------ @@ -885,13 +893,11 @@ SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING jsonb EMPTY OBJECT ON ERROR); (1 row) SELECT JSON_QUERY(jsonb '[3,4]', '$[*]' RETURNING bigint[] EMPTY OBJECT ON ERROR); -ERROR: cannot cast behavior expression of type jsonb to bigint[] -LINE 1: ...ON_QUERY(jsonb '[3,4]', '$[*]' RETURNING bigint[] EMPTY OBJE... - ^ +ERROR: could not coerce ON ERROR expression (EMPTY OBJECT) to the RETURNING type +DETAIL: expected JSON array SELECT JSON_QUERY(jsonb '"[3,4]"', '$[*]' RETURNING bigint[] EMPTY OBJECT ON ERROR); -ERROR: cannot cast behavior expression of type jsonb to bigint[] -LINE 1: ..._QUERY(jsonb '"[3,4]"', '$[*]' RETURNING bigint[] EMPTY OBJE... - ^ +ERROR: could not coerce ON ERROR expression (EMPTY OBJECT) to the RETURNING type +DETAIL: expected JSON array -- Coercion fails with quotes on SELECT JSON_QUERY(jsonb '"123.1"', '$' RETURNING int2 error on error); ERROR: invalid input syntax for type smallint: ""123.1"" @@ -934,30 +940,30 @@ FROM x | y | list ---+---+-------------- 0 | 0 | [] - 0 | 1 | [1] + 0 | 1 | 1 0 | 2 | [1, 2] 0 | 3 | [1, 2, 3] 0 | 4 | [1, 2, 3, 4] 1 | 0 | [] - 1 | 1 | [1] + 1 | 1 | 1 1 | 2 | [1, 2] 1 | 3 | [1, 2, 3] 1 | 4 | [1, 2, 3, 4] 2 | 0 | [] 2 | 1 | [] - 2 | 2 | [2] + 2 | 2 | 2 2 | 3 | [2, 3] 2 | 4 | [2, 3, 4] 3 | 0 | [] 3 | 1 | [] 3 | 2 | [] - 3 | 3 | [3] + 3 | 3 | 3 3 | 4 | [3, 4] 4 | 0 | [] 4 | 1 | [] 4 | 2 | [] 4 | 3 | [] - 4 | 4 | [4] + 4 | 4 | 4 (25 rows) -- record type returning with quotes behavior. @@ -1078,11 +1084,11 @@ CREATE TABLE test_jsonb_constraints ( CONSTRAINT test_jsonb_constraint1 CHECK (js IS JSON) CONSTRAINT test_jsonb_constraint2 - CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS txt, array[1,2,3] as arr)) + CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS "TXT", array[1,2,3] as arr)) CONSTRAINT test_jsonb_constraint3 CHECK (JSON_VALUE(js::jsonb, '$.a' RETURNING int DEFAULT '12' ON EMPTY ERROR ON ERROR) > i) CONSTRAINT test_jsonb_constraint4 - CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < jsonb '[10]') + CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) = jsonb '[10]') CONSTRAINT test_jsonb_constraint5 CHECK (JSON_QUERY(js::jsonb, '$.a' RETURNING char(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > 'a' COLLATE "C") ); @@ -1095,9 +1101,9 @@ CREATE TABLE test_jsonb_constraints ( x | jsonb | | | JSON_QUERY('[1, 2]'::jsonb, '$[*]' RETURNING jsonb WITH UNCONDITIONAL WRAPPER KEEP QUOTES) Check constraints: "test_jsonb_constraint1" CHECK (js IS JSON) - "test_jsonb_constraint2" CHECK (JSON_EXISTS(js::jsonb, '$."a"' PASSING i + 5 AS int, i::text AS txt, ARRAY[1, 2, 3] AS arr)) + "test_jsonb_constraint2" CHECK (JSON_EXISTS(js::jsonb, '$."a"' PASSING i + 5 AS "int", i::text AS "TXT", ARRAY[1, 2, 3] AS arr)) "test_jsonb_constraint3" CHECK (JSON_VALUE(js::jsonb, '$."a"' RETURNING integer DEFAULT 12 ON EMPTY ERROR ON ERROR) > i) - "test_jsonb_constraint4" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER KEEP QUOTES EMPTY OBJECT ON ERROR) < '[10]'::jsonb) + "test_jsonb_constraint4" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER KEEP QUOTES EMPTY OBJECT ON ERROR) = '[10]'::jsonb) "test_jsonb_constraint5" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING character(5) WITHOUT WRAPPER OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C")) SELECT check_clause @@ -1107,10 +1113,10 @@ ORDER BY 1; check_clause ---------------------------------------------------------------------------------------------------------------------------------------- (JSON_QUERY((js)::jsonb, '$."a"' RETURNING character(5) WITHOUT WRAPPER OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C")) - (JSON_QUERY((js)::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER KEEP QUOTES EMPTY OBJECT ON ERROR) < '[10]'::jsonb) + (JSON_QUERY((js)::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER KEEP QUOTES EMPTY OBJECT ON ERROR) = '[10]'::jsonb) (JSON_VALUE((js)::jsonb, '$."a"' RETURNING integer DEFAULT 12 ON EMPTY ERROR ON ERROR) > i) (js IS JSON) - JSON_EXISTS((js)::jsonb, '$."a"' PASSING (i + 5) AS int, (i)::text AS txt, ARRAY[1, 2, 3] AS arr) + JSON_EXISTS((js)::jsonb, '$."a"' PASSING (i + 5) AS "int", (i)::text AS "TXT", ARRAY[1, 2, 3] AS arr) (5 rows) SELECT pg_get_expr(adbin, adrelid) @@ -1137,9 +1143,6 @@ DETAIL: Failing row contains ({"b": 1}, 1, [1, 2]). INSERT INTO test_jsonb_constraints VALUES ('{"a": 1}', 1); ERROR: new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint3" DETAIL: Failing row contains ({"a": 1}, 1, [1, 2]). -INSERT INTO test_jsonb_constraints VALUES ('{"a": 7}', 1); -ERROR: new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint5" -DETAIL: Failing row contains ({"a": 7}, 1, [1, 2]). INSERT INTO test_jsonb_constraints VALUES ('{"a": 10}', 1); ERROR: new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint4" DETAIL: Failing row contains ({"a": 10}, 1, [1, 2]). @@ -1363,6 +1366,20 @@ SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz); 1 (1 row) +SELECT JSON_QUERY(jsonb 'null', '$Xyz' PASSING 1 AS Xyz); +ERROR: could not find jsonpath variable "Xyz" +SELECT JSON_QUERY(jsonb 'null', '$Xyz' PASSING 1 AS "Xyz"); + json_query +------------ + 1 +(1 row) + +SELECT JSON_QUERY(jsonb 'null', '$"Xyz"' PASSING 1 AS "Xyz"); + json_query +------------ + 1 +(1 row) + -- Test ON ERROR / EMPTY value validity for the function; all fail. SELECT JSON_EXISTS(jsonb '1', '$' DEFAULT 1 ON ERROR); ERROR: invalid ON ERROR behavior @@ -1378,8 +1395,9 @@ SELECT JSON_QUERY(jsonb '1', '$' TRUE ON ERROR); ERROR: invalid ON ERROR behavior LINE 1: SELECT JSON_QUERY(jsonb '1', '$' TRUE ON ERROR); ^ -DETAIL: Only ERROR, NULL, EMPTY [ ARRAY ], EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for JSON_QUERY(). --- Test implicit coercion domain over fixed-legth type specified in RETURNING +DETAIL: Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in ON ERROR for JSON_QUERY(). +-- Test implicit coercion to a domain over fixed-length type specified in +-- RETURNING CREATE DOMAIN queryfuncs_char2 AS char(2); CREATE DOMAIN queryfuncs_char2_chk AS char(2) CHECK (VALUE NOT IN ('12')); SELECT JSON_QUERY(jsonb '123', '$' RETURNING queryfuncs_char2 ERROR ON ERROR); @@ -1415,3 +1433,34 @@ SELECT JSON_VALUE(jsonb '123', '$' RETURNING queryfuncs_char2_chk DEFAULT 1 ON E (1 row) DROP DOMAIN queryfuncs_char2, queryfuncs_char2_chk; +-- Test coercion to domain over another fixed-length type of the ON ERROR / +-- EMPTY expressions. Ask user to cast the DEFAULT expression explicitly if +-- automatic casting cannot be done, for example, from int to bit(2). +CREATE DOMAIN queryfuncs_d_varbit3 AS varbit(3) CHECK (VALUE <> '01'); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '111111' ON ERROR); +ERROR: bit string too long for type bit varying(3) +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '010' ON ERROR); + json_value +------------ + 010 +(1 row) + +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '01' ON ERROR); +ERROR: could not coerce ON ERROR expression (DEFAULT) to the RETURNING type +DETAIL: value for domain queryfuncs_d_varbit3 violates check constraint "queryfuncs_d_varbit3_check" +SELECT JSON_VALUE(jsonb '"111"', '$' RETURNING bit(2) ERROR ON ERROR); +ERROR: bit string length 3 does not match type bit(2) +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING bit(3) DEFAULT 1 ON ERROR); +ERROR: cannot cast behavior expression of type integer to bit +LINE 1: ...VALUE(jsonb '1234', '$' RETURNING bit(3) DEFAULT 1 ON ERROR... + ^ +HINT: You will need to explicitly cast the expression to type bit. +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING bit(3) DEFAULT 1::bit(3) ON ERROR); + json_value +------------ + 001 +(1 row) + +SELECT JSON_VALUE(jsonb '"111"', '$.a' RETURNING bit(3) DEFAULT '1111' ON EMPTY); +ERROR: bit string length 4 does not match type bit(3) +DROP DOMAIN queryfuncs_d_varbit3; diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out index 6e08898b18306..776f1ad0e5347 100644 --- a/src/test/regress/expected/stats.out +++ b/src/test/regress/expected/stats.out @@ -11,6 +11,92 @@ SHOW track_counts; -- must be on on (1 row) +-- List of backend types, contexts and objects tracked in pg_stat_io. +\a +SELECT backend_type, object, context FROM pg_stat_io + ORDER BY backend_type COLLATE "C", object COLLATE "C", context COLLATE "C"; +backend_type|object|context +autovacuum launcher|relation|bulkread +autovacuum launcher|relation|init +autovacuum launcher|relation|normal +autovacuum launcher|wal|init +autovacuum launcher|wal|normal +autovacuum worker|relation|bulkread +autovacuum worker|relation|init +autovacuum worker|relation|normal +autovacuum worker|relation|vacuum +autovacuum worker|wal|init +autovacuum worker|wal|normal +background worker|relation|bulkread +background worker|relation|bulkwrite +background worker|relation|init +background worker|relation|normal +background worker|relation|vacuum +background worker|temp relation|normal +background worker|wal|init +background worker|wal|normal +background writer|relation|init +background writer|relation|normal +background writer|wal|init +background writer|wal|normal +checkpointer|relation|init +checkpointer|relation|normal +checkpointer|wal|init +checkpointer|wal|normal +client backend|relation|bulkread +client backend|relation|bulkwrite +client backend|relation|init +client backend|relation|normal +client backend|relation|vacuum +client backend|temp relation|normal +client backend|wal|init +client backend|wal|normal +io worker|relation|bulkread +io worker|relation|bulkwrite +io worker|relation|init +io worker|relation|normal +io worker|relation|vacuum +io worker|temp relation|normal +io worker|wal|init +io worker|wal|normal +slotsync worker|relation|bulkread +slotsync worker|relation|bulkwrite +slotsync worker|relation|init +slotsync worker|relation|normal +slotsync worker|relation|vacuum +slotsync worker|temp relation|normal +slotsync worker|wal|init +slotsync worker|wal|normal +standalone backend|relation|bulkread +standalone backend|relation|bulkwrite +standalone backend|relation|init +standalone backend|relation|normal +standalone backend|relation|vacuum +standalone backend|wal|init +standalone backend|wal|normal +startup|relation|bulkread +startup|relation|bulkwrite +startup|relation|init +startup|relation|normal +startup|relation|vacuum +startup|wal|init +startup|wal|normal +walreceiver|wal|init +walreceiver|wal|normal +walsender|relation|bulkread +walsender|relation|bulkwrite +walsender|relation|init +walsender|relation|normal +walsender|relation|vacuum +walsender|temp relation|normal +walsender|wal|init +walsender|wal|normal +walsummarizer|wal|init +walsummarizer|wal|normal +walwriter|wal|init +walwriter|wal|normal +(79 rows) +\a -- ensure that both seqscan and indexscan plans are allowed SET enable_seqscan TO on; SET enable_indexscan TO on; @@ -830,8 +916,11 @@ SELECT sessions > :db_stat_sessions FROM pg_stat_database WHERE datname = (SELEC -- Test pg_stat_checkpointer checkpointer-related stats, together with pg_stat_wal SELECT num_requested AS rqst_ckpts_before FROM pg_stat_checkpointer \gset --- Test pg_stat_wal (and make a temp table so our temp schema exists) +-- Test pg_stat_wal SELECT wal_bytes AS wal_bytes_before FROM pg_stat_wal \gset +-- Test pg_stat_get_backend_wal() +SELECT wal_bytes AS backend_wal_bytes_before from pg_stat_get_backend_wal(pg_backend_pid()) \gset +-- Make a temp table so our temp schema exists CREATE TEMP TABLE test_stats_temp AS SELECT 17; DROP TABLE test_stats_temp; -- Checkpoint twice: The checkpointer reports stats after reporting completion @@ -851,6 +940,18 @@ SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal; t (1 row) +SELECT pg_stat_force_next_flush(); + pg_stat_force_next_flush +-------------------------- + +(1 row) + +SELECT wal_bytes > :backend_wal_bytes_before FROM pg_stat_get_backend_wal(pg_backend_pid()); + ?column? +---------- + t +(1 row) + -- Test pg_stat_get_backend_idset() and some allied functions. -- In particular, verify that their notion of backend ID matches -- our temp schema index. @@ -1120,7 +1221,7 @@ SELECT pg_stat_have_stats('bgwriter', 0, 0); -- unknown stats kinds error out SELECT pg_stat_have_stats('zaphod', 0, 0); ERROR: invalid statistics kind: "zaphod" --- db stats have objoid 0 +-- db stats have objid 0 SELECT pg_stat_have_stats('database', :dboid, 1); pg_stat_have_stats -------------------- @@ -1249,21 +1350,34 @@ SELECT pg_stat_get_subscription_stats(NULL); (1 row) --- Test that the following operations are tracked in pg_stat_io: +-- Test that the following operations are tracked in pg_stat_io and in +-- backend stats: -- - reads of target blocks into shared buffers -- - writes of shared buffers to permanent storage -- - extends of relations using shared buffers -- - fsyncs done to ensure the durability of data dirtying shared buffers -- - shared buffer hits +-- - WAL writes and fsyncs in IOContext IOCONTEXT_NORMAL -- There is no test for blocks evicted from shared buffers, because we cannot -- be sure of the state of shared buffers at the point the test is run. -- Create a regular table and insert some data to generate IOCONTEXT_NORMAL -- extends. +SELECT pid AS checkpointer_pid FROM pg_stat_activity + WHERE backend_type = 'checkpointer' \gset SELECT sum(extends) AS io_sum_shared_before_extends FROM pg_stat_io WHERE context = 'normal' AND object = 'relation' \gset +SELECT sum(extends) AS my_io_sum_shared_before_extends + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE context = 'normal' AND object = 'relation' \gset SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs FROM pg_stat_io WHERE object = 'relation' \gset io_sum_shared_before_ +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE object = 'relation' \gset my_io_sum_shared_before_ +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_io + WHERE context = 'normal' AND object = 'wal' \gset io_sum_wal_normal_before_ CREATE TABLE test_io_shared(a int); INSERT INTO test_io_shared SELECT i FROM generate_series(1,100)i; SELECT pg_stat_force_next_flush(); @@ -1280,8 +1394,17 @@ SELECT :io_sum_shared_after_extends > :io_sum_shared_before_extends; t (1 row) +SELECT sum(extends) AS my_io_sum_shared_after_extends + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE context = 'normal' AND object = 'relation' \gset +SELECT :my_io_sum_shared_after_extends > :my_io_sum_shared_before_extends; + ?column? +---------- + t +(1 row) + -- After a checkpoint, there should be some additional IOCONTEXT_NORMAL writes --- and fsyncs. +-- and fsyncs in the global stats (usually not for the backend). -- See comment above for rationale for two explicit CHECKPOINTs. CHECKPOINT; CHECKPOINT; @@ -1301,6 +1424,45 @@ SELECT current_setting('fsync') = 'off' t (1 row) +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE object = 'relation' \gset my_io_sum_shared_after_ +SELECT :my_io_sum_shared_after_writes >= :my_io_sum_shared_before_writes; + ?column? +---------- + t +(1 row) + +SELECT current_setting('fsync') = 'off' + OR :my_io_sum_shared_after_fsyncs >= :my_io_sum_shared_before_fsyncs; + ?column? +---------- + t +(1 row) + +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_io + WHERE context = 'normal' AND object = 'wal' \gset io_sum_wal_normal_after_ +SELECT current_setting('synchronous_commit') = 'on'; + ?column? +---------- + t +(1 row) + +SELECT :io_sum_wal_normal_after_writes > :io_sum_wal_normal_before_writes; + ?column? +---------- + t +(1 row) + +SELECT current_setting('fsync') = 'off' + OR current_setting('wal_sync_method') IN ('open_sync', 'open_datasync') + OR :io_sum_wal_normal_after_fsyncs > :io_sum_wal_normal_before_fsyncs; + ?column? +---------- + t +(1 row) + -- Change the tablespace so that the table is rewritten directly, then SELECT -- from it to cause it to be read back into shared buffers. SELECT sum(reads) AS io_sum_shared_before_reads @@ -1521,6 +1683,8 @@ SELECT pg_stat_have_stats('io', 0, 0); SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_pre_reset FROM pg_stat_io \gset +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset SELECT pg_stat_reset_shared('io'); pg_stat_reset_shared ---------------------- @@ -1535,6 +1699,47 @@ SELECT :io_stats_post_reset < :io_stats_pre_reset; t (1 row) +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_post_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset +-- pg_stat_reset_shared() did not reset backend IO stats +SELECT :my_io_stats_pre_reset <= :my_io_stats_post_reset; + ?column? +---------- + t +(1 row) + +-- but pg_stat_reset_backend_stats() does +SELECT pg_stat_reset_backend_stats(pg_backend_pid()); + pg_stat_reset_backend_stats +----------------------------- + +(1 row) + +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_post_backend_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset +SELECT :my_io_stats_pre_reset > :my_io_stats_post_backend_reset; + ?column? +---------- + t +(1 row) + +-- Check invalid input for pg_stat_get_backend_io() +SELECT pg_stat_get_backend_io(NULL); + pg_stat_get_backend_io +------------------------ +(0 rows) + +SELECT pg_stat_get_backend_io(0); + pg_stat_get_backend_io +------------------------ +(0 rows) + +-- Auxiliary processes return no data. +SELECT pg_stat_get_backend_io(:checkpointer_pid); + pg_stat_get_backend_io +------------------------ +(0 rows) + -- test BRIN index doesn't block HOT update CREATE TABLE brin_hot ( id integer PRIMARY KEY, @@ -1646,4 +1851,21 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2; DROP TABLE brin_hot_3; SET enable_seqscan = on; +-- Test that estimation of relation size works with tuples wider than the +-- relation fillfactor. We create a table with wide inline attributes and +-- low fillfactor, insert rows and then see how many rows EXPLAIN shows +-- before running analyze. We disable autovacuum so that it does not +-- interfere with the test. +CREATE TABLE table_fillfactor ( + n char(1000) +) with (fillfactor=10, autovacuum_enabled=off); +INSERT INTO table_fillfactor +SELECT 'x' FROM generate_series(1,1000); +SELECT * FROM check_estimated_rows('SELECT * FROM table_fillfactor'); + estimated | actual +-----------+-------- + 1000 | 1000 +(1 row) + +DROP TABLE table_fillfactor; -- End of Stats Test diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 8c4da95508408..6359e5fb689cb 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -66,6 +66,29 @@ ERROR: syntax error at or near "," LINE 1: CREATE STATISTICS tst ON (x, y) FROM ext_stats_test; ^ DROP TABLE ext_stats_test; +-- statistics on virtual generated column not allowed +CREATE TABLE ext_stats_test1 (x int, y int, z int GENERATED ALWAYS AS (x+y) VIRTUAL, w xid); +CREATE STATISTICS tst on z from ext_stats_test1; +ERROR: statistics creation on virtual generated columns is not supported +CREATE STATISTICS tst on (z) from ext_stats_test1; +ERROR: statistics creation on virtual generated columns is not supported +CREATE STATISTICS tst on (z+1) from ext_stats_test1; +ERROR: statistics creation on virtual generated columns is not supported +CREATE STATISTICS tst (ndistinct) ON z from ext_stats_test1; +ERROR: statistics creation on virtual generated columns is not supported +-- statistics on system column not allowed +CREATE STATISTICS tst on tableoid from ext_stats_test1; +ERROR: statistics creation on system columns is not supported +CREATE STATISTICS tst on (tableoid) from ext_stats_test1; +ERROR: statistics creation on system columns is not supported +CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test1; +ERROR: statistics creation on system columns is not supported +CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test1; +ERROR: statistics creation on system columns is not supported +-- statistics without a less-than operator not supported +CREATE STATISTICS tst (ndistinct) ON w from ext_stats_test1; +ERROR: column "w" cannot be used in statistics because its type xid has no default btree operator class +DROP TABLE ext_stats_test1; -- Ensure stats are dropped sanely, and test IF NOT EXISTS while at it CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER); CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1; @@ -3254,6 +3277,8 @@ CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied ERROR: permission denied for table priv_test_tbl +SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 OR b <<< 0; +ERROR: permission denied for table priv_test_tbl DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied ERROR: permission denied for table priv_test_tbl -- Grant access via a security barrier view, but hide all data @@ -3268,6 +3293,11 @@ SELECT * FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not l ---+--- (0 rows) +SELECT * FROM tststats.priv_test_view WHERE a <<< 0 OR b <<< 0; -- Should not leak + a | b +---+--- +(0 rows) + DELETE FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not leak -- Grant table access, but hide all data with RLS RESET SESSION AUTHORIZATION; @@ -3280,6 +3310,11 @@ SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not le ---+--- (0 rows) +SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 OR b <<< 0; + a | b +---+--- +(0 rows) + DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak -- privilege checks for pg_stats_ext and pg_stats_ext_exprs RESET SESSION AUTHORIZATION; @@ -3333,3 +3368,91 @@ NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to table tststats.priv_test_tbl drop cascades to view tststats.priv_test_view DROP USER regress_stats_user1; +CREATE TABLE grouping_unique (x integer); +INSERT INTO grouping_unique (x) SELECT gs FROM generate_series(1,1000) AS gs; +ANALYZE grouping_unique; +-- Optimiser treat GROUP-BY operator as an 'uniqueser' of the input +SELECT * FROM check_estimated_rows(' + SELECT * FROM generate_series(1, 1) t1 LEFT JOIN ( + SELECT x FROM grouping_unique t2 GROUP BY x) AS q1 + ON t1.t1 = q1.x; +'); + estimated | actual +-----------+-------- + 1 | 1 +(1 row) + +DROP TABLE grouping_unique; +-- +-- Extended statistics on sb_2 (x, y, z) improve a bucket size estimation, +-- and the optimizer may choose hash join. +-- +CREATE TABLE sb_1 AS + SELECT gs % 10 AS x, gs % 10 AS y, gs % 10 AS z + FROM generate_series(1, 1e4) AS gs; +CREATE TABLE sb_2 AS + SELECT gs % 49 AS x, gs % 51 AS y, gs % 73 AS z, 'abc' || gs AS payload + FROM generate_series(1, 1e4) AS gs; +ANALYZE sb_1, sb_2; +-- During hash join estimation, the number of distinct values on each column +-- is calculated. The optimizer selects the smallest number of distinct values +-- and the largest hash bucket size. The optimizer decides that the hash +-- bucket size is quite big because there are possibly many correlations. +EXPLAIN (COSTS OFF) -- Choose merge join +SELECT * FROM sb_1 a, sb_2 b WHERE a.x = b.x AND a.y = b.y AND a.z = b.z; + QUERY PLAN +------------------------------------------------------------- + Merge Join + Merge Cond: ((a.z = b.z) AND (a.x = b.x) AND (a.y = b.y)) + -> Sort + Sort Key: a.z, a.x, a.y + -> Seq Scan on sb_1 a + -> Sort + Sort Key: b.z, b.x, b.y + -> Seq Scan on sb_2 b +(8 rows) + +-- The ndistinct extended statistics on (x, y, z) provides more reliable value +-- of bucket size. +CREATE STATISTICS extstat_sb_2 (ndistinct) ON x, y, z FROM sb_2; +ANALYZE sb_2; +EXPLAIN (COSTS OFF) -- Choose hash join +SELECT * FROM sb_1 a, sb_2 b WHERE a.x = b.x AND a.y = b.y AND a.z = b.z; + QUERY PLAN +------------------------------------------------------------ + Hash Join + Hash Cond: ((a.x = b.x) AND (a.y = b.y) AND (a.z = b.z)) + -> Seq Scan on sb_1 a + -> Hash + -> Seq Scan on sb_2 b +(5 rows) + +-- Check that the Hash Join bucket size estimator detects equal clauses correctly. +SET enable_nestloop = 'off'; +SET enable_mergejoin = 'off'; +EXPLAIN (COSTS OFF) +SELECT FROM sb_1 LEFT JOIN sb_2 ON (sb_2.x=sb_1.x) AND (sb_1.x=sb_2.x); + QUERY PLAN +-------------------------------------------------------- + Hash Left Join + Hash Cond: ((sb_1.x = sb_2.x) AND (sb_1.x = sb_2.x)) + -> Seq Scan on sb_1 + -> Hash + -> Seq Scan on sb_2 +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT FROM sb_1 LEFT JOIN sb_2 + ON (sb_2.x=sb_1.x) AND (sb_1.x=sb_2.x) AND (sb_1.y=sb_2.y); + QUERY PLAN +------------------------------------------------------------------------------ + Hash Left Join + Hash Cond: ((sb_1.x = sb_2.x) AND (sb_1.y = sb_2.y) AND (sb_1.x = sb_2.x)) + -> Seq Scan on sb_1 + -> Hash + -> Seq Scan on sb_2 +(5 rows) + +RESET enable_nestloop; +RESET enable_mergejoin; +DROP TABLE sb_1, sb_2 CASCADE; diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out new file mode 100644 index 0000000000000..48d6392b4ad4f --- /dev/null +++ b/src/test/regress/expected/stats_import.out @@ -0,0 +1,1352 @@ +CREATE SCHEMA stats_import; +CREATE TYPE stats_import.complex_type AS ( + a integer, + b real, + c text, + d date, + e jsonb); +CREATE TABLE stats_import.test( + id INTEGER PRIMARY KEY, + name text, + comp stats_import.complex_type, + arange int4range, + tags text[] +) WITH (autovacuum_enabled = false); +SELECT + pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', 18::integer, + 'reltuples', 21::real, + 'relallvisible', 24::integer, + 'relallfrozen', 27::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +-- CREATE INDEX on a table with autovac disabled should not overwrite +-- stats +CREATE INDEX test_i ON stats_import.test(id); +SELECT relname, relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass +ORDER BY relname; + relname | relpages | reltuples | relallvisible | relallfrozen +---------+----------+-----------+---------------+-------------- + test | 18 | 21 | 24 | 27 +(1 row) + +SELECT pg_clear_relation_stats('stats_import', 'test'); + pg_clear_relation_stats +------------------------- + +(1 row) + +-- +-- relstats tests +-- +-- error: schemaname missing +SELECT pg_catalog.pg_restore_relation_stats( + 'relname', 'test', + 'relpages', 17::integer); +ERROR: "schemaname" cannot be NULL +-- error: relname missing +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relpages', 17::integer); +ERROR: "relname" cannot be NULL +--- error: schemaname is wrong type +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 3.6::float, + 'relname', 'test', + 'relpages', 17::integer); +WARNING: argument "schemaname" has type "double precision", expected type "text" +ERROR: "schemaname" cannot be NULL +--- error: relname is wrong type +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 0::oid, + 'relpages', 17::integer); +WARNING: argument "relname" has type "oid", expected type "text" +ERROR: "relname" cannot be NULL +-- error: relation not found +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'nope', + 'relpages', 17::integer); +ERROR: relation "stats_import.nope" does not exist +-- error: odd number of variadic arguments cannot be pairs +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relallvisible'); +ERROR: variadic arguments must be name/value pairs +HINT: Provide an even number of variadic arguments that can be divided into pairs. +-- error: argument name is NULL +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + NULL, '17'::integer); +ERROR: name at variadic position 5 is NULL +-- starting stats +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test_i'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 1 | 0 | 0 | 0 +(1 row) + +-- regular indexes have special case locking rules +BEGIN; +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test_i', + 'relpages', 18::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.test'::regclass AND + pid = pg_backend_pid() AND granted; + mode +-------------------------- + ShareUpdateExclusiveLock +(1 row) + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.test_i'::regclass AND + pid = pg_backend_pid() AND granted; + mode +----------------- + AccessShareLock +(1 row) + +COMMIT; +-- relpages may be -1 for partitioned tables +CREATE TABLE stats_import.part_parent ( i integer ) PARTITION BY RANGE(i); +CREATE TABLE stats_import.part_child_1 + PARTITION OF stats_import.part_parent + FOR VALUES FROM (0) TO (10) + WITH (autovacuum_enabled = false); +CREATE INDEX part_parent_i ON stats_import.part_parent(i); +ANALYZE stats_import.part_parent; +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent'::regclass; + relpages +---------- + -1 +(1 row) + +-- +-- Partitioned indexes aren't analyzed but it is possible to set +-- stats. The locking rules are different from normal indexes due to +-- the rules for in-place updates: both the partitioned table and the +-- partitioned index are locked in ShareUpdateExclusive mode. +-- +BEGIN; +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'part_parent_i', + 'relpages', 2::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.part_parent'::regclass AND + pid = pg_backend_pid() AND granted; + mode +-------------------------- + ShareUpdateExclusiveLock +(1 row) + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.part_parent_i'::regclass AND + pid = pg_backend_pid() AND granted; + mode +-------------------------- + ShareUpdateExclusiveLock +(1 row) + +COMMIT; +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent_i'::regclass; + relpages +---------- + 2 +(1 row) + +-- ok: set all relstats, with version, no bounds checking +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'version', 150000::integer, + 'relpages', '-17'::integer, + 'reltuples', 400::real, + 'relallvisible', 4::integer, + 'relallfrozen', 2::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + -17 | 400 | 4 | 2 +(1 row) + +-- ok: set just relpages, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', '16'::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 16 | 400 | 4 | 2 +(1 row) + +-- ok: set just reltuples, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'reltuples', '500'::real); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 16 | 500 | 4 | 2 +(1 row) + +-- ok: set just relallvisible, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relallvisible', 5::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 16 | 500 | 5 | 2 +(1 row) + +-- ok: just relallfrozen +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'version', 150000::integer, + 'relallfrozen', 3::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 16 | 500 | 5 | 3 +(1 row) + +-- warn: bad relpages type, rest updated +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', 'nope'::text, + 'reltuples', 400.0::real, + 'relallvisible', 4::integer, + 'relallfrozen', 3::integer); +WARNING: argument "relpages" has type "text", expected type "integer" + pg_restore_relation_stats +--------------------------- + f +(1 row) + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible | relallfrozen +----------+-----------+---------------+-------------- + 16 | 400 | 4 | 3 +(1 row) + +-- unrecognized argument name, rest ok +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', '171'::integer, + 'nope', 10::integer); +WARNING: unrecognized argument name: "nope" + pg_restore_relation_stats +--------------------------- + f +(1 row) + +SELECT relpages, reltuples, relallvisible +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible +----------+-----------+--------------- + 171 | 400 | 4 +(1 row) + +-- ok: clear stats +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'test'); + pg_clear_relation_stats +------------------------- + +(1 row) + +SELECT relpages, reltuples, relallvisible +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + relpages | reltuples | relallvisible +----------+-----------+--------------- + 0 | -1 | 0 +(1 row) + +-- invalid relkinds for statistics +CREATE SEQUENCE stats_import.testseq; +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'testseq'); +ERROR: cannot modify statistics for relation "testseq" +DETAIL: This operation is not supported for sequences. +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testseq'); +ERROR: cannot modify statistics for relation "testseq" +DETAIL: This operation is not supported for sequences. +CREATE VIEW stats_import.testview AS SELECT * FROM stats_import.test; +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testview'); +ERROR: cannot modify statistics for relation "testview" +DETAIL: This operation is not supported for views. +-- +-- attribute stats +-- +-- error: schemaname missing +SELECT pg_catalog.pg_restore_attribute_stats( + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: "schemaname" cannot be NULL +-- error: schema does not exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'nope', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: schema "nope" does not exist +-- error: relname missing +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: "relname" cannot be NULL +-- error: relname does not exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'nope', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: relation "stats_import.nope" does not exist +-- error: relname null +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', NULL, + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: "relname" cannot be NULL +-- error: NULL attname +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', NULL, + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: must specify either attname or attnum +-- error: attname doesn't exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'nope', + 'inherited', false::boolean, + 'null_frac', 0.1::real, + 'avg_width', 2::integer, + 'n_distinct', 0.3::real); +ERROR: column "nope" of relation "test" does not exist +-- error: both attname and attnum +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'attnum', 1::smallint, + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: cannot specify both attname and attnum +-- error: neither attname nor attnum +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: must specify either attname or attnum +-- error: attribute is system column +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'xmin', + 'inherited', false::boolean, + 'null_frac', 0.1::real); +ERROR: cannot modify statistics on system column "xmin" +-- error: inherited null +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', NULL::boolean, + 'null_frac', 0.1::real); +ERROR: "inherited" cannot be NULL +-- ok: just the fixed values, with version, no stakinds +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'version', 150000::integer, + 'null_frac', 0.2::real, + 'avg_width', 5::integer, + 'n_distinct', 0.6::real); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.2 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- +-- ok: restore by attnum, we normally reserve this for +-- indexes, but there is no reason it shouldn't work +-- for any stat-having relation. +-- +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attnum', 1::smallint, + 'inherited', false::boolean, + 'null_frac', 0.4::real); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.4 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- warn: unrecognized argument name, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.2::real, + 'nope', 0.5::real); +WARNING: unrecognized argument name: "nope" + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.2 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- warn: mcv / mcf null mismatch part 1, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.21::real, + 'most_common_freqs', '{0.1,0.2,0.3}'::real[] + ); +WARNING: "most_common_vals" must be specified when "most_common_freqs" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.21 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- warn: mcv / mcf null mismatch part 2, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.21::real, + 'most_common_vals', '{1,2,3}'::text + ); +WARNING: "most_common_freqs" must be specified when "most_common_vals" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.21 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- warn: mcf type mismatch, mcv-pair fails, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.22::real, + 'most_common_vals', '{2,1,3}'::text, + 'most_common_freqs', '{0.2,0.1}'::double precision[] + ); +WARNING: argument "most_common_freqs" has type "double precision[]", expected type "real[]" +WARNING: "most_common_freqs" must be specified when "most_common_vals" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.22 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- warn: mcv cast failure, mcv-pair fails, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.23::real, + 'most_common_vals', '{2,four,3}'::text, + 'most_common_freqs', '{0.3,0.25,0.05}'::real[] + ); +WARNING: invalid input syntax for type integer: "four" + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.23 | 5 | 0.6 | | | | | | | | | | +(1 row) + +-- ok: mcv+mcf +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'most_common_vals', '{2,1,3}'::text, + 'most_common_freqs', '{0.3,0.25,0.05}'::real[] + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.23 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | | | | | | | | +(1 row) + +-- warn: NULL in histogram array, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.24::real, + 'histogram_bounds', '{1,NULL,3,4}'::text + ); +WARNING: "histogram_bounds" array cannot contain NULL values + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.24 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | | | | | | | | +(1 row) + +-- ok: histogram_bounds +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'histogram_bounds', '{1,2,3,4}'::text + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.24 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | {1,2,3,4} | | | | | | | +(1 row) + +-- warn: elem_count_histogram null element, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.25::real, + 'elem_count_histogram', '{1,1,NULL,1,1,1,1,1}'::real[] + ); +WARNING: "elem_count_histogram" array cannot contain NULL values + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | tags | f | 0.25 | 0 | 0 | | | | | | | | | | +(1 row) + +-- ok: elem_count_histogram +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.26::real, + 'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}'::real[] + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+------------------+------------------------ + stats_import | test | tags | f | 0.26 | 0 | 0 | | | | | | | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} | | | +(1 row) + +-- warn: range stats on a scalar type, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.27::real, + 'range_empty_frac', 0.5::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); +WARNING: attribute "id" is not a range type +DETAIL: Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM. + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.27 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | {1,2,3,4} | | | | | | | +(1 row) + +-- warn: range_empty_frac range_length_hist null mismatch, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.28::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); +WARNING: "range_empty_frac" must be specified when "range_length_histogram" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | arange | f | 0.28 | 0 | 0 | | | | | | | | | | +(1 row) + +-- warn: range_empty_frac range_length_hist null mismatch part 2, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.29::real, + 'range_empty_frac', 0.5::real + ); +WARNING: "range_length_histogram" must be specified when "range_empty_frac" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | arange | f | 0.29 | 0 | 0 | | | | | | | | | | +(1 row) + +-- ok: range_empty_frac + range_length_hist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'range_empty_frac', 0.5::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | arange | f | 0.29 | 0 | 0 | | | | | | | | {399,499,Infinity} | 0.5 | +(1 row) + +-- warn: range bounds histogram on scalar, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.31::real, + 'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text + ); +WARNING: attribute "id" is not a range type +DETAIL: Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM. + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.31 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | {1,2,3,4} | | | | | | | +(1 row) + +-- ok: range_bounds_histogram +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+-------------------------------------- + stats_import | test | arange | f | 0.29 | 0 | 0 | | | | | | | | {399,499,Infinity} | 0.5 | {"[-1,1)","[0,4)","[1,4)","[1,100)"} +(1 row) + +-- warn: cannot set most_common_elems for range type, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.32::real, + 'most_common_elems', '{3,1}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); +WARNING: unable to determine element type of attribute "arange" +DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST. + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+-------------------------------------- + stats_import | test | arange | f | 0.32 | 0 | 0 | | | | | | | | {399,499,Infinity} | 0.5 | {"[-1,1)","[0,4)","[1,4)","[1,100)"} +(1 row) + +-- warn: scalars can't have mcelem, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.33::real, + 'most_common_elems', '{1,3}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); +WARNING: unable to determine element type of attribute "id" +DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST. + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.33 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | {1,2,3,4} | | | | | | | +(1 row) + +-- warn: mcelem / mcelem mismatch, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.34::real, + 'most_common_elems', '{one,two}'::text + ); +WARNING: "most_common_elem_freqs" must be specified when "most_common_elems" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+------------------+------------------------ + stats_import | test | tags | f | 0.34 | 0 | 0 | | | | | | | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} | | | +(1 row) + +-- warn: mcelem / mcelem null mismatch part 2, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.35::real, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3}'::real[] + ); +WARNING: "most_common_elems" must be specified when "most_common_elem_freqs" is specified + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+------------------+------------------------ + stats_import | test | tags | f | 0.35 | 0 | 0 | | | | | | | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} | | | +(1 row) + +-- ok: mcelem +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'most_common_elems', '{one,three}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+------------------+------------------------ + stats_import | test | tags | f | 0.35 | 0 | 0 | | | | | {one,three} | {0.3,0.2,0.2,0.3,0} | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} | | | +(1 row) + +-- warn: scalars can't have elem_count_histogram, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.36::real, + 'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1}'::real[] + ); +WARNING: unable to determine element type of attribute "id" +DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST. + pg_restore_attribute_stats +---------------------------- + f +(1 row) + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram | range_length_histogram | range_empty_frac | range_bounds_histogram +--------------+-----------+---------+-----------+-----------+-----------+------------+------------------+-------------------+------------------+-------------+-------------------+------------------------+----------------------+------------------------+------------------+------------------------ + stats_import | test | id | f | 0.36 | 5 | 0.6 | {2,1,3} | {0.3,0.25,0.05} | {1,2,3,4} | | | | | | | +(1 row) + +-- +-- Test the ability to exactly copy data from one table to an identical table, +-- correctly reconstructing the stakind order as well as the staopN and +-- stacollN values. Because oids are not stable across databases, we can only +-- test this when the source and destination are on the same database +-- instance. For that reason, we borrow and adapt a query found in fe_utils +-- and used by pg_dump/pg_upgrade. +-- +INSERT INTO stats_import.test +SELECT 1, 'one', (1, 1.1, 'ONE', '2001-01-01', '{ "xkey": "xval" }')::stats_import.complex_type, int4range(1,4), array['red','green'] +UNION ALL +SELECT 2, 'two', (2, 2.2, 'TWO', '2002-02-02', '[true, 4, "six"]')::stats_import.complex_type, int4range(1,4), array['blue','yellow'] +UNION ALL +SELECT 3, 'tre', (3, 3.3, 'TRE', '2003-03-03', NULL)::stats_import.complex_type, int4range(-1,1), array['"orange"', 'purple', 'cyan'] +UNION ALL +SELECT 4, 'four', NULL, int4range(0,100), NULL; +CREATE INDEX is_odd ON stats_import.test(((comp).a % 2 = 1)); +-- Generate statistics on table with data +ANALYZE stats_import.test; +CREATE TABLE stats_import.test_clone ( LIKE stats_import.test ) + WITH (autovacuum_enabled = false); +CREATE INDEX is_odd_clone ON stats_import.test_clone(((comp).a % 2 = 1)); +-- +-- Copy stats from test to test_clone, and is_odd to is_odd_clone +-- +SELECT s.schemaname, s.tablename, s.attname, s.inherited, r.* +FROM pg_catalog.pg_stats AS s +CROSS JOIN LATERAL + pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', s.tablename::text || '_clone', + 'attname', s.attname::text, + 'inherited', s.inherited, + 'version', 150000, + 'null_frac', s.null_frac, + 'avg_width', s.avg_width, + 'n_distinct', s.n_distinct, + 'most_common_vals', s.most_common_vals::text, + 'most_common_freqs', s.most_common_freqs, + 'histogram_bounds', s.histogram_bounds::text, + 'correlation', s.correlation, + 'most_common_elems', s.most_common_elems::text, + 'most_common_elem_freqs', s.most_common_elem_freqs, + 'elem_count_histogram', s.elem_count_histogram, + 'range_bounds_histogram', s.range_bounds_histogram::text, + 'range_empty_frac', s.range_empty_frac, + 'range_length_histogram', s.range_length_histogram::text) AS r +WHERE s.schemaname = 'stats_import' +AND s.tablename IN ('test', 'is_odd') +ORDER BY s.tablename, s.attname, s.inherited; + schemaname | tablename | attname | inherited | r +--------------+-----------+---------+-----------+--- + stats_import | is_odd | expr | f | t + stats_import | test | arange | f | t + stats_import | test | comp | f | t + stats_import | test | id | f | t + stats_import | test | name | f | t + stats_import | test | tags | f | t +(6 rows) + +SELECT c.relname, COUNT(*) AS num_stats +FROM pg_class AS c +JOIN pg_statistic s ON s.starelid = c.oid +WHERE c.relnamespace = 'stats_import'::regnamespace +AND c.relname IN ('test', 'test_clone', 'is_odd', 'is_odd_clone') +GROUP BY c.relname +ORDER BY c.relname; + relname | num_stats +--------------+----------- + is_odd | 1 + is_odd_clone | 1 + test | 5 + test_clone | 5 +(4 rows) + +-- check test minus test_clone +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test_clone'::regclass; + attname | stainherit | stanullfrac | stawidth | stadistinct | stakind1 | stakind2 | stakind3 | stakind4 | stakind5 | staop1 | staop2 | staop3 | staop4 | staop5 | stacoll1 | stacoll2 | stacoll3 | stacoll4 | stacoll5 | stanumbers1 | stanumbers2 | stanumbers3 | stanumbers4 | stanumbers5 | sv1 | sv2 | sv3 | sv4 | sv5 | direction +---------+------------+-------------+----------+-------------+----------+----------+----------+----------+----------+--------+--------+--------+--------+--------+----------+----------+----------+----------+----------+-------------+-------------+-------------+-------------+-------------+-----+-----+-----+-----+-----+----------- +(0 rows) + +-- check test_clone minus test +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test_clone'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test'::regclass; + attname | stainherit | stanullfrac | stawidth | stadistinct | stakind1 | stakind2 | stakind3 | stakind4 | stakind5 | staop1 | staop2 | staop3 | staop4 | staop5 | stacoll1 | stacoll2 | stacoll3 | stacoll4 | stacoll5 | stanumbers1 | stanumbers2 | stanumbers3 | stanumbers4 | stanumbers5 | sv1 | sv2 | sv3 | sv4 | sv5 | direction +---------+------------+-------------+----------+-------------+----------+----------+----------+----------+----------+--------+--------+--------+--------+--------+----------+----------+----------+----------+----------+-------------+-------------+-------------+-------------+-------------+-----+-----+-----+-----+-----+----------- +(0 rows) + +-- check is_odd minus is_odd_clone +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd_clone'::regclass; + attname | stainherit | stanullfrac | stawidth | stadistinct | stakind1 | stakind2 | stakind3 | stakind4 | stakind5 | staop1 | staop2 | staop3 | staop4 | staop5 | stacoll1 | stacoll2 | stacoll3 | stacoll4 | stacoll5 | stanumbers1 | stanumbers2 | stanumbers3 | stanumbers4 | stanumbers5 | sv1 | sv2 | sv3 | sv4 | sv5 | direction +---------+------------+-------------+----------+-------------+----------+----------+----------+----------+----------+--------+--------+--------+--------+--------+----------+----------+----------+----------+----------+-------------+-------------+-------------+-------------+-------------+-----+-----+-----+-----+-----+----------- +(0 rows) + +-- check is_odd_clone minus is_odd +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd_clone'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd'::regclass; + attname | stainherit | stanullfrac | stawidth | stadistinct | stakind1 | stakind2 | stakind3 | stakind4 | stakind5 | staop1 | staop2 | staop3 | staop4 | staop5 | stacoll1 | stacoll2 | stacoll3 | stacoll4 | stacoll5 | stanumbers1 | stanumbers2 | stanumbers3 | stanumbers4 | stanumbers5 | sv1 | sv2 | sv3 | sv4 | sv5 | direction +---------+------------+-------------+----------+-------------+----------+----------+----------+----------+----------+--------+--------+--------+--------+--------+----------+----------+----------+----------+----------+-------------+-------------+-------------+-------------+-------------+-----+-----+-----+-----+-----+----------- +(0 rows) + +-- attribute stats exist before a clear, but not after +SELECT COUNT(*) +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + count +------- + 1 +(1 row) + +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => false); + pg_clear_attribute_stats +-------------------------- + +(1 row) + +SELECT COUNT(*) +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + count +------- + 0 +(1 row) + +-- temp tables +CREATE TEMP TABLE stats_temp(i int); +SELECT pg_restore_relation_stats( + 'schemaname', 'pg_temp', + 'relname', 'stats_temp', + 'relpages', '-19'::integer, + 'reltuples', 401::real, + 'relallvisible', 5::integer, + 'relallfrozen', 3::integer); + pg_restore_relation_stats +--------------------------- + t +(1 row) + +SELECT relname, relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'pg_temp.stats_temp'::regclass +ORDER BY relname; + relname | relpages | reltuples | relallvisible | relallfrozen +------------+----------+-----------+---------------+-------------- + stats_temp | -19 | 401 | 5 | 3 +(1 row) + +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'pg_temp', + 'relname', 'stats_temp', + 'attname', 'i', + 'inherited', false::boolean, + 'null_frac', 0.0123::real + ); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT tablename, null_frac +FROM pg_stats +WHERE schemaname like 'pg_temp%' +AND tablename = 'stats_temp' +AND inherited = false +AND attname = 'i'; + tablename | null_frac +------------+----------- + stats_temp | 0.0123 +(1 row) + +DROP TABLE stats_temp; +DROP SCHEMA stats_import CASCADE; +NOTICE: drop cascades to 6 other objects +DETAIL: drop cascades to type stats_import.complex_type +drop cascades to table stats_import.test +drop cascades to table stats_import.part_parent +drop cascades to sequence stats_import.testseq +drop cascades to view stats_import.testview +drop cascades to table stats_import.test_clone diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index 52b69a107fb7a..788844abd20e3 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -236,6 +236,24 @@ SELECT E'De\\678dBeEf'::bytea; ERROR: invalid input syntax for type bytea LINE 1: SELECT E'De\\678dBeEf'::bytea; ^ +SELECT reverse(''::bytea); + reverse +--------- + \x +(1 row) + +SELECT reverse('\xaa'::bytea); + reverse +--------- + \xaa +(1 row) + +SELECT reverse('\xabcd'::bytea); + reverse +--------- + \xcdab +(1 row) + SET bytea_output TO escape; SELECT E'\\xDeAdBeEf'::bytea; bytea @@ -596,6 +614,73 @@ SELECT 'abcdefg' SIMILAR TO '_bcd%' ESCAPE NULL AS null; SELECT 'abcdefg' SIMILAR TO '_bcd#%' ESCAPE '##' AS error; ERROR: invalid escape string HINT: Escape string must be empty or one character. +-- Characters that should be left alone in character classes when a +-- SIMILAR TO regexp pattern is converted to POSIX style. +-- Underscore "_" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '_[_[:alpha:]_]_'; + QUERY PLAN +------------------------------------------------ + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:.[_[:alpha:]_].)$'::text) +(2 rows) + +-- Percentage "%" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '%[%[:alnum:]%]%'; + QUERY PLAN +-------------------------------------------------- + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:.*[%[:alnum:]%].*)$'::text) +(2 rows) + +-- Dot "." +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '.[.[:alnum:].].'; + QUERY PLAN +-------------------------------------------------- + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:\.[.[:alnum:].]\.)$'::text) +(2 rows) + +-- Dollar "$" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '$[$[:alnum:]$]$'; + QUERY PLAN +-------------------------------------------------- + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:\$[$[:alnum:]$]\$)$'::text) +(2 rows) + +-- Opening parenthesis "(" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '()[([:alnum:](]()'; + QUERY PLAN +------------------------------------------------------ + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:(?:)[([:alnum:](](?:))$'::text) +(2 rows) + +-- Caret "^" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '^[^[:alnum:]^[^^][[^^]][\^][[\^]]\^]^'; + QUERY PLAN +------------------------------------------------------------------------ + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:\^[^[:alnum:]^[^^][[^^]][\^][[\^]]\^]\^)$'::text) +(2 rows) + +-- Closing square bracket "]" at the beginning of character class +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[]%][^]%][^%]%'; + QUERY PLAN +------------------------------------------------ + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:[]%][^]%][^%].*)$'::text) +(2 rows) + +-- Closing square bracket effective after two carets at the beginning +-- of character class. +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[^^]^'; + QUERY PLAN +--------------------------------------- + Seq Scan on text_tbl + Filter: (f1 ~ '^(?:[^^]\^)$'::text) +(2 rows) + -- Test backslash escapes in regexp_replace's replacement string SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3'); regexp_replace @@ -1335,6 +1420,36 @@ SELECT POSITION('5' IN '1234567890') = '5' AS "5"; t (1 row) +SELECT POSITION('\x11'::bytea IN ''::bytea) = 0 AS "0"; + 0 +--- + t +(1 row) + +SELECT POSITION('\x33'::bytea IN '\x1122'::bytea) = 0 AS "0"; + 0 +--- + t +(1 row) + +SELECT POSITION(''::bytea IN '\x1122'::bytea) = 1 AS "1"; + 1 +--- + t +(1 row) + +SELECT POSITION('\x22'::bytea IN '\x1122'::bytea) = 2 AS "2"; + 2 +--- + t +(1 row) + +SELECT POSITION('\x5678'::bytea IN '\x1234567890'::bytea) = 3 AS "3"; + 3 +--- + t +(1 row) + -- T312 character overlay function SELECT OVERLAY('abcdef' PLACING '45' FROM 4) AS "abc45f"; abc45f @@ -2255,6 +2370,57 @@ SELECT sha512('The quick brown fox jumps over the lazy dog.'); \x91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed (1 row) +-- +-- CRC +-- +SELECT crc32(''); + crc32 +------- + 0 +(1 row) + +SELECT crc32('The quick brown fox jumps over the lazy dog.'); + crc32 +------------ + 1368401385 +(1 row) + +SELECT crc32c(''); + crc32c +-------- + 0 +(1 row) + +SELECT crc32c('The quick brown fox jumps over the lazy dog.'); + crc32c +----------- + 419469235 +(1 row) + +SELECT crc32c(repeat('A', 127)::bytea); + crc32c +----------- + 291820082 +(1 row) + +SELECT crc32c(repeat('A', 128)::bytea); + crc32c +----------- + 816091258 +(1 row) + +SELECT crc32c(repeat('A', 129)::bytea); + crc32c +------------ + 4213642571 +(1 row) + +SELECT crc32c(repeat('A', 800)::bytea); + crc32c +------------ + 3134039419 +(1 row) + -- -- encode/decode -- @@ -2331,6 +2497,108 @@ SELECT set_byte('\x1234567890abcdef00'::bytea, 7, 11); SELECT set_byte('\x1234567890abcdef00'::bytea, 99, 11); -- error ERROR: index 99 out of valid range, 0..8 +-- +-- conversions between bytea and integer types +-- +SELECT 0x1234::int2::bytea AS "\x1234", (-0x1234)::int2::bytea AS "\xedcc"; + \x1234 | \xedcc +--------+-------- + \x1234 | \xedcc +(1 row) + +SELECT 0x12345678::int4::bytea AS "\x12345678", (-0x12345678)::int4::bytea AS "\xedcba988"; + \x12345678 | \xedcba988 +------------+------------ + \x12345678 | \xedcba988 +(1 row) + +SELECT 0x1122334455667788::int8::bytea AS "\x1122334455667788", + (-0x1122334455667788)::int8::bytea AS "\xeeddccbbaa998878"; + \x1122334455667788 | \xeeddccbbaa998878 +--------------------+-------------------- + \x1122334455667788 | \xeeddccbbaa998878 +(1 row) + +SELECT ''::bytea::int2 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int2 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x1234'::bytea::int2 AS "4460"; + 4460 +------ + 4660 +(1 row) + +SELECT '\x123456'::bytea::int2; -- error +ERROR: smallint out of range +SELECT ''::bytea::int4 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int4 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x12345678'::bytea::int4 AS "305419896"; + 305419896 +----------- + 305419896 +(1 row) + +SELECT '\x123456789A'::bytea::int4; -- error +ERROR: integer out of range +SELECT ''::bytea::int8 AS "0"; + 0 +--- + 0 +(1 row) + +SELECT '\x12'::bytea::int8 AS "18"; + 18 +---- + 18 +(1 row) + +SELECT '\x1122334455667788'::bytea::int8 AS "1234605616436508552"; + 1234605616436508552 +--------------------- + 1234605616436508552 +(1 row) + +SELECT '\x112233445566778899'::bytea::int8; -- error +ERROR: bigint out of range +-- min/max integer values +SELECT '\x8000'::bytea::int2 AS "-32768", '\x7FFF'::bytea::int2 AS "32767"; + -32768 | 32767 +--------+------- + -32768 | 32767 +(1 row) + +SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\x7FFFFFFF'::bytea::int4 AS "2147483647"; + -2147483648 | 2147483647 +-------------+------------ + -2147483648 | 2147483647 +(1 row) + +SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808", + '\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807"; + -9223372036854775808 | 9223372036854775807 +----------------------+--------------------- + -9223372036854775808 | 9223372036854775807 +(1 row) + -- -- test behavior of escape_string_warning and standard_conforming_strings options -- diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out index 17d48b16857d0..1443e1d929296 100644 --- a/src/test/regress/expected/subscription.out +++ b/src/test/regress/expected/subscription.out @@ -119,7 +119,7 @@ HINT: To initiate replication, you must manually create the replication slot, e List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN ------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub4 | regress_subscription_user | f | {testpub} | f | off | d | f | none | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | none | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub4 SET (origin = any); @@ -127,7 +127,7 @@ ALTER SUBSCRIPTION regress_testsub4 SET (origin = any); List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN ------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub4 | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) DROP SUBSCRIPTION regress_testsub3; @@ -148,7 +148,7 @@ ERROR: invalid connection string syntax: missing "=" after "foobar" in connecti List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false); @@ -160,7 +160,7 @@ ALTER SUBSCRIPTION regress_testsub SET (run_as_owner = true); List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | off | d | f | any | f | t | f | off | dbname=regress_doesnotexist2 | 0/0 + regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | f | t | f | off | dbname=regress_doesnotexist2 | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub SET (password_required = true); @@ -179,7 +179,7 @@ ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345'); List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist2 | 0/12345 + regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist2 | 0/12345 (1 row) -- ok - with lsn = NONE @@ -191,7 +191,7 @@ ERROR: invalid WAL location (LSN): 0/0 List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist2 | 0/0 + regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist2 | 0/0 (1 row) BEGIN; @@ -226,7 +226,7 @@ HINT: Available values: local, remote_write, remote_apply, on, off. List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN ---------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+---------- - regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | off | d | f | any | t | f | f | local | dbname=regress_doesnotexist2 | 0/0 + regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | local | dbname=regress_doesnotexist2 | 0/0 (1 row) -- rename back to keep the rest simple @@ -258,7 +258,7 @@ HINT: To initiate replication, you must manually create the replication slot, e List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | t | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | t | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub SET (binary = false); @@ -267,7 +267,7 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) DROP SUBSCRIPTION regress_testsub; @@ -374,7 +374,7 @@ HINT: To initiate replication, you must manually create the replication slot, e List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | f | off | p | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | p | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) -- we can alter streaming when two_phase enabled @@ -412,7 +412,7 @@ HINT: To initiate replication, you must manually create the replication slot, e List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true); @@ -420,7 +420,7 @@ ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true); List of subscriptions Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit | Conninfo | Skip LSN -----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+---------- - regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | t | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 + regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | t | any | t | f | f | off | dbname=regress_doesnotexist | 0/0 (1 row) ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE); diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index 9eecdc1e92426..40d8056fcea40 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -1221,8 +1221,49 @@ where o.ten = 0; (1 row) -- --- Test rescan of a SetOp node +-- Test rescan of a hashed SetOp node -- +begin; +set local enable_sort = off; +explain (costs off) +select count(*) from + onek o cross join lateral ( + select * from onek i1 where i1.unique1 = o.unique1 + except + select * from onek i2 where i2.unique1 = o.unique2 + ) ss +where o.ten = 1; + QUERY PLAN +------------------------------------------------------------ + Aggregate + -> Nested Loop + -> Seq Scan on onek o + Filter: (ten = 1) + -> HashSetOp Except + -> Index Scan using onek_unique1 on onek i1 + Index Cond: (unique1 = o.unique1) + -> Index Scan using onek_unique1 on onek i2 + Index Cond: (unique1 = o.unique2) +(9 rows) + +select count(*) from + onek o cross join lateral ( + select * from onek i1 where i1.unique1 = o.unique1 + except + select * from onek i2 where i2.unique1 = o.unique2 + ) ss +where o.ten = 1; + count +------- + 100 +(1 row) + +rollback; +-- +-- Test rescan of a sorted SetOp node +-- +begin; +set local enable_hashagg = off; explain (costs off) select count(*) from onek o cross join lateral ( @@ -1231,21 +1272,21 @@ select count(*) from select * from onek i2 where i2.unique1 = o.unique2 ) ss where o.ten = 1; - QUERY PLAN ------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate -> Nested Loop -> Seq Scan on onek o Filter: (ten = 1) - -> Subquery Scan on ss - -> HashSetOp Except - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Index Scan using onek_unique1 on onek i1 - Index Cond: (unique1 = o.unique1) - -> Subquery Scan on "*SELECT* 2" - -> Index Scan using onek_unique1 on onek i2 - Index Cond: (unique1 = o.unique2) + -> SetOp Except + -> Sort + Sort Key: i1.unique1, i1.unique2, i1.two, i1.four, i1.ten, i1.twenty, i1.hundred, i1.thousand, i1.twothousand, i1.fivethous, i1.tenthous, i1.odd, i1.even, i1.stringu1, i1.stringu2, i1.string4 + -> Index Scan using onek_unique1 on onek i1 + Index Cond: (unique1 = o.unique1) + -> Sort + Sort Key: i2.unique1, i2.unique2, i2.two, i2.four, i2.ten, i2.twenty, i2.hundred, i2.thousand, i2.twothousand, i2.fivethous, i2.tenthous, i2.odd, i2.even, i2.stringu1, i2.stringu2, i2.string4 + -> Index Scan using onek_unique1 on onek i2 + Index Cond: (unique1 = o.unique2) (13 rows) select count(*) from @@ -1260,6 +1301,7 @@ where o.ten = 1; 100 (1 row) +rollback; -- -- Test rescan of a RecursiveUnion node -- @@ -1675,7 +1717,7 @@ $$ declare ln text; begin for ln in - explain (analyze, summary off, timing off, costs off) + explain (analyze, summary off, timing off, costs off, buffers off) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3 loop ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx'); @@ -1684,14 +1726,14 @@ begin end; $$; select * from explain_sq_limit(); - explain_sq_limit ----------------------------------------------------------------- - Limit (actual rows=3 loops=1) - -> Subquery Scan on x (actual rows=3 loops=1) - -> Sort (actual rows=3 loops=1) + explain_sq_limit +------------------------------------------------------------------- + Limit (actual rows=3.00 loops=1) + -> Subquery Scan on x (actual rows=3.00 loops=1) + -> Sort (actual rows=3.00 loops=1) Sort Key: sq_limit.c1, sq_limit.pk Sort Method: top-N heapsort Memory: xxx - -> Seq Scan on sq_limit (actual rows=8 loops=1) + -> Seq Scan on sq_limit (actual rows=8.00 loops=1) (6 rows) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3; @@ -1721,6 +1763,511 @@ fetch backward all in c1; (2 rows) commit; +-- +-- Verify that we correctly flatten cases involving a subquery output +-- expression that doesn't need to be wrapped in a PlaceHolderVar +-- +explain (costs off) +select tname, attname from ( +select relname::information_schema.sql_identifier as tname, * from + (select * from pg_class c) ss1) ss2 + right join pg_attribute a on a.attrelid = ss2.oid +where tname = 'tenk1' and attnum = 1; + QUERY PLAN +-------------------------------------------------------------------------- + Nested Loop + -> Index Scan using pg_class_relname_nsp_index on pg_class c + Index Cond: (relname = 'tenk1'::name) + -> Index Scan using pg_attribute_relid_attnum_index on pg_attribute a + Index Cond: ((attrelid = c.oid) AND (attnum = 1)) +(5 rows) + +select tname, attname from ( +select relname::information_schema.sql_identifier as tname, * from + (select * from pg_class c) ss1) ss2 + right join pg_attribute a on a.attrelid = ss2.oid +where tname = 'tenk1' and attnum = 1; + tname | attname +-------+--------- + tenk1 | unique1 +(1 row) + +-- Check behavior when there's a lateral reference in the output expression +explain (verbose, costs off) +select t1.ten, sum(x) from + tenk1 t1 left join lateral ( + select t1.ten + t2.ten as x, t2.fivethous from tenk1 t2 + ) ss on t1.unique1 = ss.fivethous +group by t1.ten +order by t1.ten; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: t1.ten, (sum((t1.ten + t2.ten))) + Sort Key: t1.ten + -> HashAggregate + Output: t1.ten, sum((t1.ten + t2.ten)) + Group Key: t1.ten + -> Hash Right Join + Output: t1.ten, t2.ten + Hash Cond: (t2.fivethous = t1.unique1) + -> Seq Scan on public.tenk1 t2 + Output: t2.unique1, t2.unique2, t2.two, t2.four, t2.ten, t2.twenty, t2.hundred, t2.thousand, t2.twothousand, t2.fivethous, t2.tenthous, t2.odd, t2.even, t2.stringu1, t2.stringu2, t2.string4 + -> Hash + Output: t1.ten, t1.unique1 + -> Seq Scan on public.tenk1 t1 + Output: t1.ten, t1.unique1 +(15 rows) + +select t1.ten, sum(x) from + tenk1 t1 left join lateral ( + select t1.ten + t2.ten as x, t2.fivethous from tenk1 t2 + ) ss on t1.unique1 = ss.fivethous +group by t1.ten +order by t1.ten; + ten | sum +-----+------- + 0 | 0 + 1 | 2000 + 2 | 4000 + 3 | 6000 + 4 | 8000 + 5 | 10000 + 6 | 12000 + 7 | 14000 + 8 | 16000 + 9 | 18000 +(10 rows) + +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+t3.q1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + QUERY PLAN +-------------------------------------------------------- + Sort + Output: t1.q1, ((t2.q1 + t3.q1)) + Sort Key: t1.q1, ((t2.q1 + t3.q1)) + -> Hash Left Join + Output: t1.q1, (t2.q1 + t3.q1) + Hash Cond: (t2.q2 = t3.q2) + -> Hash Left Join + Output: t1.q1, t2.q1, t2.q2 + Hash Cond: (t1.q2 = t2.q2) + -> Seq Scan on public.int8_tbl t1 + Output: t1.q1, t1.q2 + -> Hash + Output: t2.q1, t2.q2 + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Hash + Output: t3.q1, t3.q2 + -> Seq Scan on public.int8_tbl t3 + Output: t3.q1, t3.q2 +(19 rows) + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+t3.q1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + q1 | x +------------------+------------------ + 123 | 246 + 123 | 246 + 123 | 4567890123456912 + 123 | 4567890123456912 + 123 | 9135780246913578 + 4567890123456789 | 246 + 4567890123456789 | 4567890123456912 + 4567890123456789 | 4567890123456912 + 4567890123456789 | 9135780246913578 + 4567890123456789 | 9135780246913578 + 4567890123456789 | 9135780246913578 +(11 rows) + +-- strict expressions containing variables of rels under the same lowest +-- nulling outer join can escape being wrapped +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + QUERY PLAN +-------------------------------------------------------- + Sort + Output: t1.q1, ((t2.q1 + 1)) + Sort Key: t1.q1, ((t2.q1 + 1)) + -> Hash Right Join + Output: t1.q1, (t2.q1 + 1) + Hash Cond: (t2.q2 = t1.q2) + -> Hash Join + Output: t2.q1, t2.q2 + Hash Cond: (t2.q2 = t3.q2) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Hash + Output: t3.q2 + -> Seq Scan on public.int8_tbl t3 + Output: t3.q2 + -> Hash + Output: t1.q1, t1.q2 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q1, t1.q2 +(19 rows) + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + q1 | x +------------------+------------------ + 123 | 124 + 123 | 124 + 123 | 124 + 123 | 4567890123456790 + 123 | 4567890123456790 + 4567890123456789 | 124 + 4567890123456789 | 124 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 +(11 rows) + +-- otherwise we need to wrap the strict expressions +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + QUERY PLAN +-------------------------------------------------- + Sort + Output: t1.q1, ((t2.q1 + 1)) + Sort Key: t1.q1, ((t2.q1 + 1)) + -> Hash Right Join + Output: t1.q1, ((t2.q1 + 1)) + Hash Cond: (t2.q2 = t1.q2) + -> Nested Loop Left Join + Output: t2.q2, ((t2.q1 + 1)) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Seq Scan on public.int8_tbl t3 + Output: t3.q2, (t2.q1 + 1) + Filter: (t2.q2 = t3.q2) + -> Hash + Output: t1.q1, t1.q2 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q1, t1.q2 +(17 rows) + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + q1 | x +------------------+------------------ + 123 | 124 + 123 | 124 + 123 | 124 + 123 | 4567890123456790 + 123 | 4567890123456790 + 4567890123456789 | 124 + 4567890123456789 | 124 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 + 4567890123456789 | 4567890123456790 +(11 rows) + +-- lateral references for simple Vars can escape being wrapped if the +-- referenced rel is under the same lowest nulling outer join +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + QUERY PLAN +-------------------------------------------------------- + Sort + Output: t1.q1, t2.q2 + Sort Key: t1.q1, t2.q2 + -> Hash Right Join + Output: t1.q1, t2.q2 + Hash Cond: (t2.q1 = t1.q1) + -> Hash Join + Output: t2.q2, t2.q1 + Hash Cond: (t2.q2 = t3.q1) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Hash + Output: t3.q1 + -> Seq Scan on public.int8_tbl t3 + Output: t3.q1 + -> Hash + Output: t1.q1 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q1 +(19 rows) + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + q1 | x +------------------+------------------ + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 +(21 rows) + +-- otherwise we need to wrap the Vars +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + QUERY PLAN +-------------------------------------------------- + Sort + Output: t1.q1, (t2.q2) + Sort Key: t1.q1, (t2.q2) + -> Hash Right Join + Output: t1.q1, (t2.q2) + Hash Cond: (t2.q1 = t1.q1) + -> Nested Loop Left Join + Output: t2.q1, (t2.q2) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Seq Scan on public.int8_tbl t3 + Output: t3.q1, t2.q2 + Filter: (t2.q2 = t3.q1) + -> Hash + Output: t1.q1 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q1 +(17 rows) + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + q1 | x +------------------+------------------ + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | 4567890123456789 + 123 | + 123 | + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 + 4567890123456789 | + 4567890123456789 | + 4567890123456789 | +(26 rows) + +-- lateral references for PHVs can also escape being wrapped if the +-- referenced rel is under the same lowest nulling outer join +explain (verbose, costs off) +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 inner join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + QUERY PLAN +---------------------------------------------------------------- + Sort + Output: (COALESCE(t3.q1)), t4.q1, t4.q2 + Sort Key: (COALESCE(t3.q1)), t4.q1, t4.q2 + -> Hash Right Join + Output: (COALESCE(t3.q1)), t4.q1, t4.q2 + Hash Cond: (t4.q1 = t1.q2) + -> Hash Join + Output: (COALESCE(t3.q1)), t4.q1, t4.q2 + Hash Cond: (t2.q2 = t4.q1) + -> Hash Left Join + Output: t2.q2, (COALESCE(t3.q1)) + Hash Cond: (t2.q1 = t3.q2) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Hash + Output: t3.q2, (COALESCE(t3.q1)) + -> Seq Scan on public.int8_tbl t3 + Output: t3.q2, COALESCE(t3.q1) + -> Hash + Output: t4.q1, t4.q2 + -> Seq Scan on public.int8_tbl t4 + Output: t4.q1, t4.q2 + -> Hash + Output: t1.q2 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q2 +(26 rows) + +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 inner join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + y | q1 | q2 +------------------+------------------+------------------- + 123 | 123 | 456 + 123 | 123 | 4567890123456789 + 123 | 4567890123456789 | -4567890123456789 + 123 | 4567890123456789 | -4567890123456789 + 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 456 + 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + | | + | | +(24 rows) + +-- otherwise we need to wrap the PHVs +explain (verbose, costs off) +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 left join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + QUERY PLAN +---------------------------------------------------------------- + Sort + Output: ((COALESCE(t3.q1))), t4.q1, t4.q2 + Sort Key: ((COALESCE(t3.q1))), t4.q1, t4.q2 + -> Hash Right Join + Output: ((COALESCE(t3.q1))), t4.q1, t4.q2 + Hash Cond: (t4.q1 = t1.q2) + -> Nested Loop + Output: t4.q1, t4.q2, ((COALESCE(t3.q1))) + Join Filter: (t2.q2 = t4.q1) + -> Hash Left Join + Output: t2.q2, (COALESCE(t3.q1)) + Hash Cond: (t2.q1 = t3.q2) + -> Seq Scan on public.int8_tbl t2 + Output: t2.q1, t2.q2 + -> Hash + Output: t3.q2, (COALESCE(t3.q1)) + -> Seq Scan on public.int8_tbl t3 + Output: t3.q2, COALESCE(t3.q1) + -> Seq Scan on public.int8_tbl t4 + Output: t4.q1, t4.q2, (COALESCE(t3.q1)) + -> Hash + Output: t1.q2 + -> Seq Scan on public.int8_tbl t1 + Output: t1.q2 +(24 rows) + +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 left join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + y | q1 | q2 +------------------+------------------+------------------- + 123 | 123 | 456 + 123 | 123 | 4567890123456789 + 123 | 4567890123456789 | -4567890123456789 + 123 | 4567890123456789 | -4567890123456789 + 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 123 + 123 | 4567890123456789 | 4567890123456789 + 123 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 123 | 456 + 4567890123456789 | 123 | 4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | -4567890123456789 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + 4567890123456789 | 4567890123456789 | 4567890123456789 + | | + | | +(24 rows) + -- -- Tests for CTE inlining behavior -- @@ -2105,3 +2652,312 @@ ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd); Filter: (odd = b.odd) (16 rows) +-- +-- Test VALUES to ARRAY (VtA) transformation +-- +-- VtA transformation for joined VALUES is not supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek, (VALUES('RFAAAA'), ('VJAAAA')) AS v (i) + WHERE onek.stringu1 = v.i; + QUERY PLAN +------------------------------------------------------------- + Nested Loop + -> Values Scan on "*VALUES*" + -> Index Scan using onek_stringu1 on onek + Index Cond: (stringu1 = ("*VALUES*".column1)::text) +(4 rows) + +-- VtA transformation for a composite argument is not supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE (unique1,ten) IN (VALUES (1,1), (20,0), (99,9), (17,99)) + ORDER BY unique1; + QUERY PLAN +----------------------------------------------------------------- + Sort + Sort Key: onek.unique1 + -> Nested Loop + -> HashAggregate + Group Key: "*VALUES*".column1, "*VALUES*".column2 + -> Values Scan on "*VALUES*" + -> Index Scan using onek_unique1 on onek + Index Cond: (unique1 = "*VALUES*".column1) + Filter: ("*VALUES*".column2 = ten) +(9 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (VALUES(10000), (2), (389), (1000), (2000), (10029)) + ORDER BY unique1; + QUERY PLAN +---------------------------------------------------------------------------------------- + Sort + Sort Key: unique1 + -> Bitmap Heap Scan on onek + Recheck Cond: (unique1 = ANY ('{10000,2,389,1000,2000,10029}'::integer[])) + -> Bitmap Index Scan on onek_unique1 + Index Cond: (unique1 = ANY ('{10000,2,389,1000,2000,10029}'::integer[])) +(6 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (VALUES(1200), (1)); + QUERY PLAN +------------------------------------------------------------- + Bitmap Heap Scan on onek + Recheck Cond: (unique1 = ANY ('{1200,1}'::integer[])) + -> Bitmap Index Scan on onek_unique1 + Index Cond: (unique1 = ANY ('{1200,1}'::integer[])) +(4 rows) + +-- Recursive evaluation of constant queries is not yet supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (SELECT x * x FROM (VALUES(1200), (1)) AS x(x)); + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop + -> Unique + -> Sort + Sort Key: (("*VALUES*".column1 * "*VALUES*".column1)) + -> Values Scan on "*VALUES*" + -> Index Scan using onek_unique1 on onek + Index Cond: (unique1 = ("*VALUES*".column1 * "*VALUES*".column1)) +(7 rows) + +EXPLAIN (COSTS OFF) +SELECT unique1, stringu1 FROM onek WHERE stringu1::name IN (VALUES('RFAAAA'), ('VJAAAA')); + QUERY PLAN +------------------------------------------------------------------ + Bitmap Heap Scan on onek + Recheck Cond: (stringu1 = ANY ('{RFAAAA,VJAAAA}'::text[])) + -> Bitmap Index Scan on onek_stringu1 + Index Cond: (stringu1 = ANY ('{RFAAAA,VJAAAA}'::text[])) +(4 rows) + +EXPLAIN (COSTS OFF) +SELECT unique1, stringu1 FROM onek WHERE stringu1::text IN (VALUES('RFAAAA'), ('VJAAAA')); + QUERY PLAN +---------------------------------------------------------------- + Seq Scan on onek + Filter: ((stringu1)::text = ANY ('{RFAAAA,VJAAAA}'::text[])) +(2 rows) + +EXPLAIN (COSTS OFF) +SELECT * from onek WHERE unique1 in (VALUES(1200::bigint), (1)); + QUERY PLAN +------------------------------------------------------------ + Bitmap Heap Scan on onek + Recheck Cond: (unique1 = ANY ('{1200,1}'::bigint[])) + -> Bitmap Index Scan on onek_unique1 + Index Cond: (unique1 = ANY ('{1200,1}'::bigint[])) +(4 rows) + +-- VtA shouldn't depend on the side of the join probing with the VALUES expression. +EXPLAIN (COSTS OFF) +SELECT c.unique1,c.ten FROM tenk1 c JOIN onek a USING (ten) +WHERE a.ten IN (VALUES (1), (2)); + QUERY PLAN +-------------------------------------------------- + Hash Join + Hash Cond: (a.ten = c.ten) + -> Seq Scan on onek a + Filter: (ten = ANY ('{1,2}'::integer[])) + -> Hash + -> Seq Scan on tenk1 c +(6 rows) + +EXPLAIN (COSTS OFF) +SELECT c.unique1,c.ten FROM tenk1 c JOIN onek a USING (ten) +WHERE c.ten IN (VALUES (1), (2)); + QUERY PLAN +-------------------------------------------------- + Hash Join + Hash Cond: (c.ten = a.ten) + -> Seq Scan on tenk1 c + Filter: (ten = ANY ('{1,2}'::integer[])) + -> Hash + -> Seq Scan on onek a +(6 rows) + +-- Constant expressions are simplified +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE sin(two ) +four IN (VALUES (sin(0.5)), (2)); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Seq Scan on onek + Filter: ((sin((two)::double precision) + (four)::double precision) = ANY ('{0.479425538604203,2}'::double precision[])) +(2 rows) + +EXPLAIN (COSTS OFF) +-- VtA allows NULLs in the list +SELECT ten FROM onek WHERE sin(two)+four IN (VALUES (sin(0.5)), (NULL), (2)); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on onek + Filter: ((sin((two)::double precision) + (four)::double precision) = ANY ('{0.479425538604203,NULL,2}'::double precision[])) +(2 rows) + +-- VtA is supported for custom plans where params are substituted with +-- constants. VtA is not supported with generic plans where params prevent +-- us from building a constant array. +PREPARE test (int, numeric, text) AS + SELECT ten FROM onek WHERE sin(two) * four / ($3::real) IN (VALUES (sin($2)), (2), ($1)); +EXPLAIN (COSTS OFF) EXECUTE test(42, 3.14, '-1.5'); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on onek + Filter: (((sin((two)::double precision) * (four)::double precision) / '-1.5'::real) = ANY ('{0.0015926529164868282,2,42}'::double precision[])) +(2 rows) + +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, NULL); + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, '-1.5'); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on onek + Filter: (((sin((two)::double precision) * (four)::double precision) / '-1.5'::real) = ANY ('{0.0015926529164868282,2,NULL}'::double precision[])) +(2 rows) + +SET plan_cache_mode = 'force_generic_plan'; +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, '-1.5'); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Hash Semi Join + Hash Cond: (((sin((onek.two)::double precision) * (onek.four)::double precision) / ($3)::real) = "*VALUES*".column1) + -> Seq Scan on onek + -> Hash + -> Values Scan on "*VALUES*" +(5 rows) + +RESET plan_cache_mode; +-- VtA doesn't support LIMIT, OFFSET, and ORDER BY clauses +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) OFFSET 1); + QUERY PLAN +---------------------------------------------------- + Nested Loop + -> HashAggregate + Group Key: "*VALUES*".column1 + -> Limit + -> Values Scan on "*VALUES*" + -> Index Scan using onek_unique1 on onek + Index Cond: (unique1 = "*VALUES*".column1) +(7 rows) + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) ORDER BY 1); + QUERY PLAN +---------------------------------------------------- + Nested Loop + -> Unique + -> Sort + Sort Key: "*VALUES*".column1 + -> Sort + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Index Scan using onek_unique1 on onek + Index Cond: (unique1 = "*VALUES*".column1) +(9 rows) + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) LIMIT 1); + QUERY PLAN +---------------------------------------------------- + Nested Loop + -> HashAggregate + Group Key: "*VALUES*".column1 + -> Limit + -> Values Scan on "*VALUES*" + -> Index Scan using onek_unique1 on onek + Index Cond: (unique1 = "*VALUES*".column1) +(7 rows) + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t +WHERE unique1 IN (VALUES (0), ((2 IN (SELECT unique2 FROM onek c + WHERE c.unique2 = t.unique1))::integer)); + QUERY PLAN +------------------------------------------------------------ + Nested Loop Semi Join + -> Seq Scan on onek t + -> Values Scan on "*VALUES*" + Filter: (t.unique1 = column1) + SubPlan 1 + -> Index Only Scan using onek_unique2 on onek c + Index Cond: (unique2 = t.unique1) +(7 rows) + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t +WHERE unique1 IN (VALUES (0), ((2 IN (SELECT unique2 FROM onek c + WHERE c.unique2 IN (VALUES (sin(0.5)), (2))))::integer)); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Nested Loop + -> Unique + -> Sort + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + SubPlan 1 + -> Index Only Scan using onek_unique2 on onek c + Filter: ((unique2)::double precision = ANY ('{0.479425538604203,2}'::double precision[])) + -> Index Scan using onek_unique1 on onek t + Index Cond: (unique1 = "*VALUES*".column1) +(10 rows) + +-- VtA is not allowed with subqueries +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE unique1 IN (VALUES (0), ((2 IN + (SELECT (3)))::integer) +); + QUERY PLAN +---------------------------------------------------- + Nested Loop + -> Unique + -> Sort + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + SubPlan 1 + -> Result + -> Index Scan using onek_unique1 on onek t + Index Cond: (unique1 = "*VALUES*".column1) +(9 rows) + +-- VtA is not allowed with non-constant expressions +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE unique1 IN (VALUES (0), (unique2)); + QUERY PLAN +--------------------------------------- + Nested Loop Semi Join + -> Seq Scan on onek t + -> Values Scan on "*VALUES*" + Filter: (t.unique1 = column1) +(4 rows) + +EXPLAIN (COSTS OFF) +SELECT * FROM onek t1, lateral (SELECT * FROM onek t2 WHERE t2.ten IN (values (t1.ten), (1))); + QUERY PLAN +-------------------------------------------------- + Nested Loop + -> Seq Scan on onek t1 + -> Hash Semi Join + Hash Cond: (t2.ten = "*VALUES*".column1) + -> Seq Scan on onek t2 + -> Hash + -> Values Scan on "*VALUES*" +(7 rows) + +-- VtA causes the whole expression to be evaluated as a constant +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE 1.0::integer IN ((VALUES (1), (3))); + QUERY PLAN +-------------------- + Seq Scan on onek t +(1 row) + diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out index 84b3b64b49073..83228cfca293f 100644 --- a/src/test/regress/expected/sysviews.out +++ b/src/test/regress/expected/sysviews.out @@ -21,11 +21,11 @@ select count(*) >= 0 as ok from pg_available_extensions; -- The entire output of pg_backend_memory_contexts is not stable, -- we test only the existence and basic condition of TopMemoryContext. -select type, name, ident, parent, level, total_bytes >= free_bytes +select type, name, ident, level, total_bytes >= free_bytes from pg_backend_memory_contexts where level = 1; - type | name | ident | parent | level | ?column? -----------+------------------+-------+--------+-------+---------- - AllocSet | TopMemoryContext | | | 1 | t + type | name | ident | level | ?column? +----------+------------------+-------+-------+---------- + AllocSet | TopMemoryContext | | 1 | t (1 row) -- We can exercise some MemoryContext type stats functions. Most of the @@ -43,11 +43,11 @@ fetch 1 from cur; bbbbbbbbbb | 2 (1 row) -select type, name, parent, total_bytes > 0, total_nblocks, free_bytes > 0, free_chunks +select type, name, total_bytes > 0, total_nblocks, free_bytes > 0, free_chunks from pg_backend_memory_contexts where name = 'Caller tuples'; - type | name | parent | ?column? | total_nblocks | ?column? | free_chunks -------+---------------+----------------+----------+---------------+----------+------------- - Bump | Caller tuples | TupleSort sort | t | 2 | t | 0 + type | name | ?column? | total_nblocks | ?column? | free_chunks +------+---------------+----------+---------------+----------+------------- + Bump | Caller tuples | t | 2 | t | 0 (1 row) rollback; @@ -150,6 +150,7 @@ select name, setting from pg_settings where name like 'enable%'; --------------------------------+--------- enable_async_append | on enable_bitmapscan | on + enable_distinct_reordering | on enable_gathermerge | on enable_group_by_reordering | on enable_hashagg | on @@ -167,10 +168,11 @@ select name, setting from pg_settings where name like 'enable%'; enable_partitionwise_aggregate | off enable_partitionwise_join | off enable_presorted_aggregate | on + enable_self_join_elimination | on enable_seqscan | on enable_sort | on enable_tidscan | on -(22 rows) +(24 rows) -- There are always wait event descriptions for various types. InjectionPoint -- may be present or absent, depending on history since last postmaster start. @@ -222,3 +224,11 @@ select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs; t (1 row) +-- One specific case we can check without much fear of breakage +-- is the historical local-mean-time value used for America/Los_Angeles. +select * from pg_timezone_abbrevs where abbrev = 'LMT'; + abbrev | utc_offset | is_dst +--------+-------------------------------+-------- + LMT | @ 7 hours 52 mins 58 secs ago | f +(1 row) + diff --git a/src/test/regress/expected/tablespace.out b/src/test/regress/expected/tablespace.out index 9aabb85349741..a90e39e57382b 100644 --- a/src/test/regress/expected/tablespace.out +++ b/src/test/regress/expected/tablespace.out @@ -51,13 +51,13 @@ ERROR: cannot move system relation "pg_authid_rolname_index" REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_authid; ERROR: cannot reindex system catalogs concurrently -- toast relations, fail -REINDEX (TABLESPACE regress_tblspace) INDEX pg_toast.pg_toast_1260_index; -ERROR: cannot move system relation "pg_toast_1260_index" -REINDEX (TABLESPACE regress_tblspace) INDEX CONCURRENTLY pg_toast.pg_toast_1260_index; +REINDEX (TABLESPACE regress_tblspace) INDEX pg_toast.pg_toast_1262_index; +ERROR: cannot move system relation "pg_toast_1262_index" +REINDEX (TABLESPACE regress_tblspace) INDEX CONCURRENTLY pg_toast.pg_toast_1262_index; ERROR: cannot reindex system catalogs concurrently -REINDEX (TABLESPACE regress_tblspace) TABLE pg_toast.pg_toast_1260; -ERROR: cannot move system relation "pg_toast_1260_index" -REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_toast.pg_toast_1260; +REINDEX (TABLESPACE regress_tblspace) TABLE pg_toast.pg_toast_1262; +ERROR: cannot move system relation "pg_toast_1262_index" +REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_toast.pg_toast_1262; ERROR: cannot reindex system catalogs concurrently -- system catalog, fail REINDEX (TABLESPACE pg_global) TABLE pg_authid; @@ -927,6 +927,11 @@ ALTER INDEX testschema.part_a_idx SET TABLESPACE pg_default; -- Fail, not empty DROP TABLESPACE regress_tblspace; ERROR: tablespace "regress_tblspace" is not empty +-- Adequate cache initialization before GRANT +\c - +BEGIN; +GRANT ALL ON TABLESPACE regress_tblspace TO PUBLIC; +ROLLBACK; CREATE ROLE regress_tablespace_user1 login; CREATE ROLE regress_tablespace_user2 login; GRANT USAGE ON SCHEMA testschema TO regress_tablespace_user2; diff --git a/src/test/regress/expected/temp.out b/src/test/regress/expected/temp.out index 2a246a7e1231a..370361543b30c 100644 --- a/src/test/regress/expected/temp.out +++ b/src/test/regress/expected/temp.out @@ -410,3 +410,159 @@ SELECT current_schema() ~ 'pg_temp' AS is_temp_schema; PREPARE TRANSACTION 'twophase_search'; ERROR: cannot PREPARE a transaction that has operated on temporary objects +-- Tests to verify we recover correctly from exhausting buffer pins and +-- related matters. +-- use lower possible buffer limit to make the test cheaper +\c +SET temp_buffers = 100; +CREATE TEMPORARY TABLE test_temp(a int not null unique, b TEXT not null, cnt int not null); +INSERT INTO test_temp SELECT generate_series(1, 10000) as id, repeat('a', 200), 0; +-- should be at least 2x as large than temp_buffers +SELECT pg_relation_size('test_temp') / current_setting('block_size')::int8 > 200; + ?column? +---------- + t +(1 row) + +-- Don't want cursor names and plpgsql function lines in the error messages +\set VERBOSITY terse +/* helper function to create cursors for each page in [p_start, p_end] */ +CREATE FUNCTION test_temp_pin(p_start int, p_end int) +RETURNS void +LANGUAGE plpgsql +AS $f$ + DECLARE + cursorname text; + query text; + BEGIN + FOR i IN p_start..p_end LOOP + cursorname = 'c_'||i; + query = format($q$DECLARE %I CURSOR FOR SELECT ctid FROM test_temp WHERE ctid >= '( %s, 1)'::tid $q$, cursorname, i); + EXECUTE query; + EXECUTE 'FETCH NEXT FROM '||cursorname; + -- for test development + -- RAISE NOTICE '%: %', cursorname, query; + END LOOP; + END; +$f$; +-- Test overflow of temp table buffers is handled correctly +BEGIN; +-- should work, below max +SELECT test_temp_pin(0, 9); + test_temp_pin +--------------- + +(1 row) + +-- should fail, too many buffers pinned +SELECT test_temp_pin(10, 105); +ERROR: no empty local buffer available +ROLLBACK; +BEGIN; +-- have some working cursors to test after errors +SELECT test_temp_pin(0, 9); + test_temp_pin +--------------- + +(1 row) + +FETCH NEXT FROM c_3; + ctid +------- + (3,2) +(1 row) + +-- exhaust buffer pins in subtrans, check things work after +SAVEPOINT rescue_me; +SELECT test_temp_pin(10, 105); +ERROR: no empty local buffer available +ROLLBACK TO SAVEPOINT rescue_me; +-- pre-subtrans cursors continue to work +FETCH NEXT FROM c_3; + ctid +------- + (3,3) +(1 row) + +-- new cursors with pins can be created after subtrans rollback +SELECT test_temp_pin(10, 94); + test_temp_pin +--------------- + +(1 row) + +-- Check that read streams deal with lower number of pins available +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + count | max_a | min_a | max_cnt +-------+-------+-------+--------- + 10000 | 10000 | 1 | 0 +(1 row) + +ROLLBACK; +-- Check that temp tables with existing cursors can't be dropped. +BEGIN; +SELECT test_temp_pin(0, 1); + test_temp_pin +--------------- + +(1 row) + +DROP TABLE test_temp; +ERROR: cannot DROP TABLE "test_temp" because it is being used by active queries in this session +COMMIT; +-- Check that temp tables with existing cursors can't be dropped. +BEGIN; +SELECT test_temp_pin(0, 1); + test_temp_pin +--------------- + +(1 row) + +TRUNCATE test_temp; +ERROR: cannot TRUNCATE "test_temp" because it is being used by active queries in this session +COMMIT; +-- Check that temp tables that are dropped in transaction that's rolled back +-- preserve buffer contents +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + count | max_a | min_a | max_cnt +-------+-------+-------+--------- + 10000 | 10000 | 1 | 0 +(1 row) + +INSERT INTO test_temp(a, b, cnt) VALUES (-1, '', 0); +BEGIN; +INSERT INTO test_temp(a, b, cnt) VALUES (-2, '', 0); +DROP TABLE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + count | max_a | min_a | max_cnt +-------+-------+-------+--------- + 10001 | 10000 | -1 | 0 +(1 row) + +-- Check that temp table drop is transactional and preserves dirty +-- buffer contents +UPDATE test_temp SET cnt = cnt + 1 WHERE a = -1; +BEGIN; +DROP TABLE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + count | max_a | min_a | max_cnt +-------+-------+-------+--------- + 10001 | 10000 | -1 | 1 +(1 row) + +-- Check that temp table truncation is transactional and preserves dirty +-- buffer contents +UPDATE test_temp SET cnt = cnt + 1 WHERE a = -1; +BEGIN; +TRUNCATE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + count | max_a | min_a | max_cnt +-------+-------+-------+--------- + 10001 | 10000 | -1 | 2 +(1 row) + +-- cleanup +DROP FUNCTION test_temp_pin(int, int); diff --git a/src/test/regress/expected/test_setup.out b/src/test/regress/expected/test_setup.out index 3d0eeec996038..93a4c2691c191 100644 --- a/src/test/regress/expected/test_setup.out +++ b/src/test/regress/expected/test_setup.out @@ -205,10 +205,6 @@ CREATE FUNCTION binary_coercible(oid, oid) RETURNS bool AS :'regresslib', 'binary_coercible' LANGUAGE C STRICT STABLE PARALLEL SAFE; -CREATE FUNCTION ttdummy () - RETURNS trigger - AS :'regresslib' - LANGUAGE C; -- Use hand-rolled hash functions and operator classes to get predictable -- result on different machines. The hash function for int4 simply returns -- the sum of the values passed to it and the one for text returns the length diff --git a/src/test/regress/expected/tidscan.out b/src/test/regress/expected/tidscan.out index f133b5a4ac70f..e823bc91c5791 100644 --- a/src/test/regress/expected/tidscan.out +++ b/src/test/regress/expected/tidscan.out @@ -189,12 +189,12 @@ FETCH NEXT FROM c; (1 row) -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; - QUERY PLAN ---------------------------------------------------- - Update on tidscan (actual rows=1 loops=1) - -> Tid Scan on tidscan (actual rows=1 loops=1) + QUERY PLAN +------------------------------------------------------ + Update on tidscan (actual rows=1.00 loops=1) + -> Tid Scan on tidscan (actual rows=1.00 loops=1) TID Cond: CURRENT OF c (3 rows) @@ -205,12 +205,12 @@ FETCH NEXT FROM c; (1 row) -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; - QUERY PLAN ---------------------------------------------------- - Update on tidscan (actual rows=1 loops=1) - -> Tid Scan on tidscan (actual rows=1 loops=1) + QUERY PLAN +------------------------------------------------------ + Update on tidscan (actual rows=1.00 loops=1) + -> Tid Scan on tidscan (actual rows=1.00 loops=1) TID Cond: CURRENT OF c (3 rows) @@ -229,7 +229,7 @@ FETCH NEXT FROM c; (0 rows) -- should error out -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; ERROR: cursor "c" is not positioned on a row ROLLBACK; diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out index cf337da517ef2..6aaa19c8f4e46 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -591,6 +591,8 @@ SELECT date_trunc( 'week', timestamp '2004-02-29 15:44:17.71393' ) AS week_trunc Mon Feb 23 00:00:00 2004 (1 row) +SELECT date_trunc( 'ago', timestamp 'infinity' ) AS invalid_trunc; +ERROR: unit "ago" not recognized for type timestamp without time zone -- verify date_bin behaves the same as date_trunc for relevant intervals -- case 1: AD dates, origin < input SELECT @@ -2201,3 +2203,16 @@ select age(timestamp '-infinity', timestamp 'infinity'); select age(timestamp '-infinity', timestamp '-infinity'); ERROR: interval out of range +-- test timestamp near POSTGRES_EPOCH_JDATE +select timestamp '1999-12-31 24:00:00'; + timestamp +-------------------------- + Sat Jan 01 00:00:00 2000 +(1 row) + +select make_timestamp(1999, 12, 31, 24, 0, 0); + make_timestamp +-------------------------- + Sat Jan 01 00:00:00 2000 +(1 row) + diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out index bfb3825ff6cf0..2a69953ff25ed 100644 --- a/src/test/regress/expected/timestamptz.out +++ b/src/test/regress/expected/timestamptz.out @@ -176,6 +176,65 @@ SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST Fri Jan 10 07:32:01 205000 PST (1 row) +-- Recognize "LMT" as whatever it means in the current zone +SELECT 'Jan 01 00:00:00 1000 LMT'::timestamptz; + timestamptz +------------------------------ + Wed Jan 01 00:00:00 1000 LMT +(1 row) + +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; + timestamptz +------------------------------ + Sun Dec 31 23:52:58 2023 PST +(1 row) + +SET timezone = 'Europe/London'; +SELECT 'Jan 01 00:00:00 1000 LMT'::timestamptz; + timestamptz +------------------------------ + Wed Jan 01 00:00:00 1000 LMT +(1 row) + +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; + timestamptz +------------------------------ + Mon Jan 01 00:01:15 2024 GMT +(1 row) + +-- which might be nothing +SET timezone = 'UTC'; +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; -- fail +ERROR: invalid input syntax for type timestamp with time zone: "Jan 01 00:00:00 2024 LMT" +LINE 1: SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; + ^ +-- Another example of an abbrev that varies across zones +SELECT '1912-01-01 00:00 MMT'::timestamptz; -- from timezone_abbreviations + timestamptz +------------------------------ + Sun Dec 31 17:30:00 1911 UTC +(1 row) + +SET timezone = 'America/Montevideo'; +SELECT '1912-01-01 00:00'::timestamptz; + timestamptz +------------------------------ + Mon Jan 01 00:00:00 1912 MMT +(1 row) + +SELECT '1912-01-01 00:00 MMT'::timestamptz; + timestamptz +------------------------------ + Mon Jan 01 00:00:00 1912 MMT +(1 row) + +SELECT '1912-01-01 00:00 MMT'::timestamptz AT TIME ZONE 'UTC'; + timezone +-------------------------- + Mon Jan 01 03:44:51 1912 +(1 row) + +RESET timezone; -- Test non-error-throwing API SELECT pg_input_is_valid('now', 'timestamptz'); pg_input_is_valid @@ -330,12 +389,12 @@ SELECT d1 FROM TIMESTAMPTZ_TBL; Fri Feb 14 17:32:01 1997 PST Sat Feb 15 17:32:01 1997 PST Sun Feb 16 17:32:01 1997 PST - Tue Feb 16 17:32:01 0097 PST BC - Sat Feb 16 17:32:01 0097 PST - Thu Feb 16 17:32:01 0597 PST - Tue Feb 16 17:32:01 1097 PST - Sat Feb 16 17:32:01 1697 PST - Thu Feb 16 17:32:01 1797 PST + Tue Feb 16 17:32:01 0097 LMT BC + Sat Feb 16 17:32:01 0097 LMT + Thu Feb 16 17:32:01 0597 LMT + Tue Feb 16 17:32:01 1097 LMT + Sat Feb 16 17:32:01 1697 LMT + Thu Feb 16 17:32:01 1797 LMT Tue Feb 16 17:32:01 1897 PST Sun Feb 16 17:32:01 1997 PST Sat Feb 16 17:32:01 2097 PST @@ -359,19 +418,19 @@ SELECT d1 FROM TIMESTAMPTZ_TBL; SELECT '4714-11-24 00:00:00+00 BC'::timestamptz; timestamptz --------------------------------- - Sun Nov 23 16:00:00 4714 PST BC + Sun Nov 23 16:07:02 4714 LMT BC (1 row) SELECT '4714-11-23 16:00:00-08 BC'::timestamptz; timestamptz --------------------------------- - Sun Nov 23 16:00:00 4714 PST BC + Sun Nov 23 16:07:02 4714 LMT BC (1 row) SELECT 'Sun Nov 23 16:00:00 4714 PST BC'::timestamptz; timestamptz --------------------------------- - Sun Nov 23 16:00:00 4714 PST BC + Sun Nov 23 16:07:02 4714 LMT BC (1 row) SELECT '4714-11-23 23:59:59+00 BC'::timestamptz; -- out of range @@ -461,12 +520,12 @@ SELECT d1 FROM TIMESTAMPTZ_TBL --------------------------------- -infinity Wed Dec 31 16:00:00 1969 PST - Tue Feb 16 17:32:01 0097 PST BC - Sat Feb 16 17:32:01 0097 PST - Thu Feb 16 17:32:01 0597 PST - Tue Feb 16 17:32:01 1097 PST - Sat Feb 16 17:32:01 1697 PST - Thu Feb 16 17:32:01 1797 PST + Tue Feb 16 17:32:01 0097 LMT BC + Sat Feb 16 17:32:01 0097 LMT + Thu Feb 16 17:32:01 0597 LMT + Tue Feb 16 17:32:01 1097 LMT + Sat Feb 16 17:32:01 1697 LMT + Thu Feb 16 17:32:01 1797 LMT Tue Feb 16 17:32:01 1897 PST Wed Feb 28 17:32:01 1996 PST Thu Feb 29 17:32:01 1996 PST @@ -529,12 +588,12 @@ SELECT d1 FROM TIMESTAMPTZ_TBL Fri Feb 14 17:32:01 1997 PST Sat Feb 15 17:32:01 1997 PST Sun Feb 16 17:32:01 1997 PST - Tue Feb 16 17:32:01 0097 PST BC - Sat Feb 16 17:32:01 0097 PST - Thu Feb 16 17:32:01 0597 PST - Tue Feb 16 17:32:01 1097 PST - Sat Feb 16 17:32:01 1697 PST - Thu Feb 16 17:32:01 1797 PST + Tue Feb 16 17:32:01 0097 LMT BC + Sat Feb 16 17:32:01 0097 LMT + Thu Feb 16 17:32:01 0597 LMT + Tue Feb 16 17:32:01 1097 LMT + Sat Feb 16 17:32:01 1697 LMT + Thu Feb 16 17:32:01 1797 LMT Tue Feb 16 17:32:01 1897 PST Sun Feb 16 17:32:01 1997 PST Sat Feb 16 17:32:01 2097 PST @@ -561,12 +620,12 @@ SELECT d1 FROM TIMESTAMPTZ_TBL -infinity Wed Dec 31 16:00:00 1969 PST Thu Jan 02 00:00:00 1997 PST - Tue Feb 16 17:32:01 0097 PST BC - Sat Feb 16 17:32:01 0097 PST - Thu Feb 16 17:32:01 0597 PST - Tue Feb 16 17:32:01 1097 PST - Sat Feb 16 17:32:01 1697 PST - Thu Feb 16 17:32:01 1797 PST + Tue Feb 16 17:32:01 0097 LMT BC + Sat Feb 16 17:32:01 0097 LMT + Thu Feb 16 17:32:01 0597 LMT + Tue Feb 16 17:32:01 1097 LMT + Sat Feb 16 17:32:01 1697 LMT + Thu Feb 16 17:32:01 1797 LMT Tue Feb 16 17:32:01 1897 PST Wed Feb 28 17:32:01 1996 PST Thu Feb 29 17:32:01 1996 PST @@ -701,6 +760,8 @@ SELECT date_trunc( 'week', timestamp with time zone '2004-02-29 15:44:17.71393' Mon Feb 23 00:00:00 2004 PST (1 row) +SELECT date_trunc( 'ago', timestamp with time zone 'infinity' ) AS invalid_trunc; +ERROR: unit "ago" not recognized for type timestamp with time zone SELECT date_trunc('day', timestamp with time zone '2001-02-16 20:38:40+00', 'Australia/Sydney') as sydney_trunc; -- zone name sydney_trunc ------------------------------ @@ -719,6 +780,8 @@ SELECT date_trunc('day', timestamp with time zone '2001-02-16 20:38:40+00', 'VET Thu Feb 15 20:00:00 2001 PST (1 row) +SELECT date_trunc('ago', timestamp with time zone 'infinity', 'GMT') AS invalid_zone_trunc; +ERROR: unit "ago" not recognized for type timestamp with time zone -- verify date_bin behaves the same as date_trunc for relevant intervals SELECT str, @@ -920,12 +983,12 @@ SELECT d1 as timestamptz, Fri Feb 14 17:32:01 1997 PST | 1997 | 2 | 14 | 17 | 32 | 1 Sat Feb 15 17:32:01 1997 PST | 1997 | 2 | 15 | 17 | 32 | 1 Sun Feb 16 17:32:01 1997 PST | 1997 | 2 | 16 | 17 | 32 | 1 - Tue Feb 16 17:32:01 0097 PST BC | -97 | 2 | 16 | 17 | 32 | 1 - Sat Feb 16 17:32:01 0097 PST | 97 | 2 | 16 | 17 | 32 | 1 - Thu Feb 16 17:32:01 0597 PST | 597 | 2 | 16 | 17 | 32 | 1 - Tue Feb 16 17:32:01 1097 PST | 1097 | 2 | 16 | 17 | 32 | 1 - Sat Feb 16 17:32:01 1697 PST | 1697 | 2 | 16 | 17 | 32 | 1 - Thu Feb 16 17:32:01 1797 PST | 1797 | 2 | 16 | 17 | 32 | 1 + Tue Feb 16 17:32:01 0097 LMT BC | -97 | 2 | 16 | 17 | 32 | 1 + Sat Feb 16 17:32:01 0097 LMT | 97 | 2 | 16 | 17 | 32 | 1 + Thu Feb 16 17:32:01 0597 LMT | 597 | 2 | 16 | 17 | 32 | 1 + Tue Feb 16 17:32:01 1097 LMT | 1097 | 2 | 16 | 17 | 32 | 1 + Sat Feb 16 17:32:01 1697 LMT | 1697 | 2 | 16 | 17 | 32 | 1 + Thu Feb 16 17:32:01 1797 LMT | 1797 | 2 | 16 | 17 | 32 | 1 Tue Feb 16 17:32:01 1897 PST | 1897 | 2 | 16 | 17 | 32 | 1 Sun Feb 16 17:32:01 1997 PST | 1997 | 2 | 16 | 17 | 32 | 1 Sat Feb 16 17:32:01 2097 PST | 2097 | 2 | 16 | 17 | 32 | 1 @@ -994,12 +1057,12 @@ SELECT d1 as timestamptz, Fri Feb 14 17:32:01 1997 PST | 1 | 1000 | 1000000 Sat Feb 15 17:32:01 1997 PST | 1 | 1000 | 1000000 Sun Feb 16 17:32:01 1997 PST | 1 | 1000 | 1000000 - Tue Feb 16 17:32:01 0097 PST BC | 1 | 1000 | 1000000 - Sat Feb 16 17:32:01 0097 PST | 1 | 1000 | 1000000 - Thu Feb 16 17:32:01 0597 PST | 1 | 1000 | 1000000 - Tue Feb 16 17:32:01 1097 PST | 1 | 1000 | 1000000 - Sat Feb 16 17:32:01 1697 PST | 1 | 1000 | 1000000 - Thu Feb 16 17:32:01 1797 PST | 1 | 1000 | 1000000 + Tue Feb 16 17:32:01 0097 LMT BC | 1 | 1000 | 1000000 + Sat Feb 16 17:32:01 0097 LMT | 1 | 1000 | 1000000 + Thu Feb 16 17:32:01 0597 LMT | 1 | 1000 | 1000000 + Tue Feb 16 17:32:01 1097 LMT | 1 | 1000 | 1000000 + Sat Feb 16 17:32:01 1697 LMT | 1 | 1000 | 1000000 + Thu Feb 16 17:32:01 1797 LMT | 1 | 1000 | 1000000 Tue Feb 16 17:32:01 1897 PST | 1 | 1000 | 1000000 Sun Feb 16 17:32:01 1997 PST | 1 | 1000 | 1000000 Sat Feb 16 17:32:01 2097 PST | 1 | 1000 | 1000000 @@ -1069,12 +1132,12 @@ SELECT d1 as timestamptz, Fri Feb 14 17:32:01 1997 PST | 1997 | 7 | 5 | 5 | 45 Sat Feb 15 17:32:01 1997 PST | 1997 | 7 | 6 | 6 | 46 Sun Feb 16 17:32:01 1997 PST | 1997 | 7 | 7 | 0 | 47 - Tue Feb 16 17:32:01 0097 PST BC | -97 | 7 | 2 | 2 | 47 - Sat Feb 16 17:32:01 0097 PST | 97 | 7 | 6 | 6 | 47 - Thu Feb 16 17:32:01 0597 PST | 597 | 7 | 4 | 4 | 47 - Tue Feb 16 17:32:01 1097 PST | 1097 | 7 | 2 | 2 | 47 - Sat Feb 16 17:32:01 1697 PST | 1697 | 7 | 6 | 6 | 47 - Thu Feb 16 17:32:01 1797 PST | 1797 | 7 | 4 | 4 | 47 + Tue Feb 16 17:32:01 0097 LMT BC | -97 | 7 | 2 | 2 | 47 + Sat Feb 16 17:32:01 0097 LMT | 97 | 7 | 6 | 6 | 47 + Thu Feb 16 17:32:01 0597 LMT | 597 | 7 | 4 | 4 | 47 + Tue Feb 16 17:32:01 1097 LMT | 1097 | 7 | 2 | 2 | 47 + Sat Feb 16 17:32:01 1697 LMT | 1697 | 7 | 6 | 6 | 47 + Thu Feb 16 17:32:01 1797 LMT | 1797 | 7 | 4 | 4 | 47 Tue Feb 16 17:32:01 1897 PST | 1897 | 7 | 2 | 2 | 47 Sun Feb 16 17:32:01 1997 PST | 1997 | 7 | 7 | 0 | 47 Sat Feb 16 17:32:01 2097 PST | 2097 | 7 | 6 | 6 | 47 @@ -1146,12 +1209,12 @@ SELECT d1 as timestamptz, Fri Feb 14 17:32:01 1997 PST | 199 | 20 | 2 | 2450495 | 855970321 Sat Feb 15 17:32:01 1997 PST | 199 | 20 | 2 | 2450496 | 856056721 Sun Feb 16 17:32:01 1997 PST | 199 | 20 | 2 | 2450497 | 856143121 - Tue Feb 16 17:32:01 0097 PST BC | -10 | -1 | -1 | 1686043 | -65192682479 - Sat Feb 16 17:32:01 0097 PST | 9 | 1 | 1 | 1756537 | -59102000879 - Thu Feb 16 17:32:01 0597 PST | 59 | 6 | 1 | 1939158 | -43323546479 - Tue Feb 16 17:32:01 1097 PST | 109 | 11 | 2 | 2121779 | -27545092079 - Sat Feb 16 17:32:01 1697 PST | 169 | 17 | 2 | 2340925 | -8610877679 - Thu Feb 16 17:32:01 1797 PST | 179 | 18 | 2 | 2377449 | -5455204079 + Tue Feb 16 17:32:01 0097 LMT BC | -10 | -1 | -1 | 1686043 | -65192682901 + Sat Feb 16 17:32:01 0097 LMT | 9 | 1 | 1 | 1756537 | -59102001301 + Thu Feb 16 17:32:01 0597 LMT | 59 | 6 | 1 | 1939158 | -43323546901 + Tue Feb 16 17:32:01 1097 LMT | 109 | 11 | 2 | 2121779 | -27545092501 + Sat Feb 16 17:32:01 1697 LMT | 169 | 17 | 2 | 2340925 | -8610878101 + Thu Feb 16 17:32:01 1797 LMT | 179 | 18 | 2 | 2377449 | -5455204501 Tue Feb 16 17:32:01 1897 PST | 189 | 19 | 2 | 2413973 | -2299530479 Sun Feb 16 17:32:01 1997 PST | 199 | 20 | 2 | 2450497 | 856143121 Sat Feb 16 17:32:01 2097 PST | 209 | 21 | 3 | 2487022 | 4011903121 @@ -1221,12 +1284,12 @@ SELECT d1 as timestamptz, Fri Feb 14 17:32:01 1997 PST | -28800 | -8 | 0 Sat Feb 15 17:32:01 1997 PST | -28800 | -8 | 0 Sun Feb 16 17:32:01 1997 PST | -28800 | -8 | 0 - Tue Feb 16 17:32:01 0097 PST BC | -28800 | -8 | 0 - Sat Feb 16 17:32:01 0097 PST | -28800 | -8 | 0 - Thu Feb 16 17:32:01 0597 PST | -28800 | -8 | 0 - Tue Feb 16 17:32:01 1097 PST | -28800 | -8 | 0 - Sat Feb 16 17:32:01 1697 PST | -28800 | -8 | 0 - Thu Feb 16 17:32:01 1797 PST | -28800 | -8 | 0 + Tue Feb 16 17:32:01 0097 LMT BC | -28378 | -7 | -52 + Sat Feb 16 17:32:01 0097 LMT | -28378 | -7 | -52 + Thu Feb 16 17:32:01 0597 LMT | -28378 | -7 | -52 + Tue Feb 16 17:32:01 1097 LMT | -28378 | -7 | -52 + Sat Feb 16 17:32:01 1697 LMT | -28378 | -7 | -52 + Thu Feb 16 17:32:01 1797 LMT | -28378 | -7 | -52 Tue Feb 16 17:32:01 1897 PST | -28800 | -8 | 0 Sun Feb 16 17:32:01 1997 PST | -28800 | -8 | 0 Sat Feb 16 17:32:01 2097 PST | -28800 | -8 | 0 @@ -1300,12 +1363,12 @@ SELECT d1 as "timestamp", Fri Feb 14 17:32:01 1997 PST | 1000000 | 1000.000 | 1.000000 | 2450495 | 855970321.000000 Sat Feb 15 17:32:01 1997 PST | 1000000 | 1000.000 | 1.000000 | 2450496 | 856056721.000000 Sun Feb 16 17:32:01 1997 PST | 1000000 | 1000.000 | 1.000000 | 2450497 | 856143121.000000 - Tue Feb 16 17:32:01 0097 PST BC | 1000000 | 1000.000 | 1.000000 | 1686043 | -65192682479.000000 - Sat Feb 16 17:32:01 0097 PST | 1000000 | 1000.000 | 1.000000 | 1756537 | -59102000879.000000 - Thu Feb 16 17:32:01 0597 PST | 1000000 | 1000.000 | 1.000000 | 1939158 | -43323546479.000000 - Tue Feb 16 17:32:01 1097 PST | 1000000 | 1000.000 | 1.000000 | 2121779 | -27545092079.000000 - Sat Feb 16 17:32:01 1697 PST | 1000000 | 1000.000 | 1.000000 | 2340925 | -8610877679.000000 - Thu Feb 16 17:32:01 1797 PST | 1000000 | 1000.000 | 1.000000 | 2377449 | -5455204079.000000 + Tue Feb 16 17:32:01 0097 LMT BC | 1000000 | 1000.000 | 1.000000 | 1686043 | -65192682901.000000 + Sat Feb 16 17:32:01 0097 LMT | 1000000 | 1000.000 | 1.000000 | 1756537 | -59102001301.000000 + Thu Feb 16 17:32:01 0597 LMT | 1000000 | 1000.000 | 1.000000 | 1939158 | -43323546901.000000 + Tue Feb 16 17:32:01 1097 LMT | 1000000 | 1000.000 | 1.000000 | 2121779 | -27545092501.000000 + Sat Feb 16 17:32:01 1697 LMT | 1000000 | 1000.000 | 1.000000 | 2340925 | -8610878101.000000 + Thu Feb 16 17:32:01 1797 LMT | 1000000 | 1000.000 | 1.000000 | 2377449 | -5455204501.000000 Tue Feb 16 17:32:01 1897 PST | 1000000 | 1000.000 | 1.000000 | 2413973 | -2299530479.000000 Sun Feb 16 17:32:01 1997 PST | 1000000 | 1000.000 | 1.000000 | 2450497 | 856143121.000000 Sat Feb 16 17:32:01 2097 PST | 1000000 | 1000.000 | 1.000000 | 2487022 | 4011903121.000000 @@ -2304,7 +2367,7 @@ INSERT INTO TIMESTAMPTZ_TST VALUES(4, '1000000312 23:58:48 IST'); SELECT * FROM TIMESTAMPTZ_TST ORDER BY a; a | b ---+-------------------------------- - 1 | Wed Mar 12 13:58:48 1000 PST + 1 | Wed Mar 12 14:05:50 1000 LMT 2 | Sun Mar 12 14:58:48 10000 PDT 3 | Sun Mar 12 14:58:48 100000 PDT 3 | Sun Mar 12 14:58:48 10000 PDT @@ -2388,10 +2451,16 @@ SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UT Tue Dec 09 23:00:00 2014 (1 row) -SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC'; +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Asia/Singapore') AT TIME ZONE 'UTC'; + timezone +-------------------------- + Fri Dec 09 17:04:35 1881 +(1 row) + +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Pacific/Honolulu') AT TIME ZONE 'UTC'; timezone -------------------------- - Wed Dec 09 15:56:00 1846 + Sat Dec 10 10:31:26 1881 (1 row) SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Europe/Paris') AT TIME ZONE 'UTC'; @@ -2415,7 +2484,14 @@ SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'EDT'); Wed Dec 10 09:10:10 2008 EST (1 row) -SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT'); +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'FOO8BAR'); + make_timestamptz +------------------------------ + Wed Dec 10 13:10:10 2014 EST +(1 row) + +-- POSIX +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT,M3.2.0,M11.1.0'); make_timestamptz ------------------------------ Wed Dec 10 13:10:10 2014 EST @@ -3286,3 +3362,16 @@ SELECT age(timestamptz '-infinity', timestamptz 'infinity'); SELECT age(timestamptz '-infinity', timestamptz '-infinity'); ERROR: interval out of range +-- test timestamp near POSTGRES_EPOCH_JDATE +select timestamptz '1999-12-31 24:00:00'; + timestamptz +------------------------------ + Sat Jan 01 00:00:00 2000 PST +(1 row) + +select make_timestamptz(1999, 12, 31, 24, 0, 0); + make_timestamptz +------------------------------ + Sat Jan 01 00:00:00 2000 PST +(1 row) + diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index a044d6afe2712..2bf0e77d61ecb 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -4,147 +4,11 @@ -- directory paths and dlsuffix are passed to us in environment variables \getenv libdir PG_LIBDIR \getenv dlsuffix PG_DLSUFFIX -\set autoinclib :libdir '/autoinc' :dlsuffix -\set refintlib :libdir '/refint' :dlsuffix \set regresslib :libdir '/regress' :dlsuffix -CREATE FUNCTION autoinc () - RETURNS trigger - AS :'autoinclib' - LANGUAGE C; -CREATE FUNCTION check_primary_key () - RETURNS trigger - AS :'refintlib' - LANGUAGE C; -CREATE FUNCTION check_foreign_key () - RETURNS trigger - AS :'refintlib' - LANGUAGE C; CREATE FUNCTION trigger_return_old () RETURNS trigger AS :'regresslib' LANGUAGE C; -CREATE FUNCTION set_ttdummy (int4) - RETURNS int4 - AS :'regresslib' - LANGUAGE C STRICT; -create table pkeys (pkey1 int4 not null, pkey2 text not null); -create table fkeys (fkey1 int4, fkey2 text, fkey3 int); -create table fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); -create index fkeys_i on fkeys (fkey1, fkey2); -create index fkeys2_i on fkeys2 (fkey21, fkey22); -create index fkeys2p_i on fkeys2 (pkey23); -insert into pkeys values (10, '1'); -insert into pkeys values (20, '2'); -insert into pkeys values (30, '3'); -insert into pkeys values (40, '4'); -insert into pkeys values (50, '5'); -insert into pkeys values (60, '6'); -create unique index pkeys_i on pkeys (pkey1, pkey2); --- --- For fkeys: --- (fkey1, fkey2) --> pkeys (pkey1, pkey2) --- (fkey3) --> fkeys2 (pkey23) --- -create trigger check_fkeys_pkey_exist - before insert or update on fkeys - for each row - execute function - check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); -create trigger check_fkeys_pkey2_exist - before insert or update on fkeys - for each row - execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); --- --- For fkeys2: --- (fkey21, fkey22) --> pkeys (pkey1, pkey2) --- -create trigger check_fkeys2_pkey_exist - before insert or update on fkeys2 - for each row - execute procedure - check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2'); --- Test comments -COMMENT ON TRIGGER check_fkeys2_pkey_bad ON fkeys2 IS 'wrong'; -ERROR: trigger "check_fkeys2_pkey_bad" for table "fkeys2" does not exist -COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS 'right'; -COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS NULL; --- --- For pkeys: --- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: --- fkeys (fkey1, fkey2) and fkeys2 (fkey21, fkey22) --- -create trigger check_pkeys_fkey_cascade - before delete or update on pkeys - for each row - execute procedure - check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', - 'fkeys', 'fkey1', 'fkey2', 'fkeys2', 'fkey21', 'fkey22'); --- --- For fkeys2: --- ON DELETE/UPDATE (pkey23) RESTRICT: --- fkeys (fkey3) --- -create trigger check_fkeys2_fkey_restrict - before delete or update on fkeys2 - for each row - execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'fkeys', 'fkey3'); -insert into fkeys2 values (10, '1', 1); -insert into fkeys2 values (30, '3', 2); -insert into fkeys2 values (40, '4', 5); -insert into fkeys2 values (50, '5', 3); --- no key in pkeys -insert into fkeys2 values (70, '5', 3); -ERROR: tuple references non-existent key -DETAIL: Trigger "check_fkeys2_pkey_exist" found tuple referencing non-existent key in "pkeys". -insert into fkeys values (10, '1', 2); -insert into fkeys values (30, '3', 3); -insert into fkeys values (40, '4', 2); -insert into fkeys values (50, '5', 2); --- no key in pkeys -insert into fkeys values (70, '5', 1); -ERROR: tuple references non-existent key -DETAIL: Trigger "check_fkeys_pkey_exist" found tuple referencing non-existent key in "pkeys". --- no key in fkeys2 -insert into fkeys values (60, '6', 4); -ERROR: tuple references non-existent key -DETAIL: Trigger "check_fkeys_pkey2_exist" found tuple referencing non-existent key in "fkeys2". -delete from pkeys where pkey1 = 30 and pkey2 = '3'; -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted -ERROR: "check_fkeys2_fkey_restrict": tuple is referenced in "fkeys" -CONTEXT: SQL statement "delete from fkeys2 where fkey21 = $1 and fkey22 = $2 " -delete from pkeys where pkey1 = 40 and pkey2 = '4'; -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys2 are deleted -update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted -ERROR: "check_fkeys2_fkey_restrict": tuple is referenced in "fkeys" -CONTEXT: SQL statement "delete from fkeys2 where fkey21 = $1 and fkey22 = $2 " -update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys are deleted -NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys2 are deleted -SELECT trigger_name, event_manipulation, event_object_schema, event_object_table, - action_order, action_condition, action_orientation, action_timing, - action_reference_old_table, action_reference_new_table - FROM information_schema.triggers - WHERE event_object_table in ('pkeys', 'fkeys', 'fkeys2') - ORDER BY trigger_name COLLATE "C", 2; - trigger_name | event_manipulation | event_object_schema | event_object_table | action_order | action_condition | action_orientation | action_timing | action_reference_old_table | action_reference_new_table -----------------------------+--------------------+---------------------+--------------------+--------------+------------------+--------------------+---------------+----------------------------+---------------------------- - check_fkeys2_fkey_restrict | DELETE | public | fkeys2 | 1 | | ROW | BEFORE | | - check_fkeys2_fkey_restrict | UPDATE | public | fkeys2 | 1 | | ROW | BEFORE | | - check_fkeys2_pkey_exist | INSERT | public | fkeys2 | 1 | | ROW | BEFORE | | - check_fkeys2_pkey_exist | UPDATE | public | fkeys2 | 2 | | ROW | BEFORE | | - check_fkeys_pkey2_exist | INSERT | public | fkeys | 1 | | ROW | BEFORE | | - check_fkeys_pkey2_exist | UPDATE | public | fkeys | 1 | | ROW | BEFORE | | - check_fkeys_pkey_exist | INSERT | public | fkeys | 2 | | ROW | BEFORE | | - check_fkeys_pkey_exist | UPDATE | public | fkeys | 2 | | ROW | BEFORE | | - check_pkeys_fkey_cascade | DELETE | public | pkeys | 1 | | ROW | BEFORE | | - check_pkeys_fkey_cascade | UPDATE | public | pkeys | 1 | | ROW | BEFORE | | -(10 rows) - -DROP TABLE pkeys; -DROP TABLE fkeys; -DROP TABLE fkeys2; -- Check behavior when trigger returns unmodified trigtuple create table trigtest (f1 int, f2 text); create trigger trigger_return_old @@ -295,143 +159,6 @@ select * from trigtest; (1 row) drop table trigtest; -create sequence ttdummy_seq increment 10 start 0 minvalue 0; -create table tttest ( - price_id int4, - price_val int4, - price_on int4, - price_off int4 default 999999 -); -create trigger ttdummy - before delete or update on tttest - for each row - execute procedure - ttdummy (price_on, price_off); -create trigger ttserial - before insert or update on tttest - for each row - execute procedure - autoinc (price_on, ttdummy_seq); -insert into tttest values (1, 1, null); -insert into tttest values (2, 2, null); -insert into tttest values (3, 3, 0); -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 2 | 2 | 20 | 999999 - 3 | 3 | 30 | 999999 -(3 rows) - -delete from tttest where price_id = 2; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 3 | 3 | 30 | 999999 - 2 | 2 | 20 | 40 -(3 rows) - --- what do we see ? --- get current prices -select * from tttest where price_off = 999999; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 3 | 3 | 30 | 999999 -(2 rows) - --- change price for price_id == 3 -update tttest set price_val = 30 where price_id = 3; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 2 | 2 | 20 | 40 - 3 | 30 | 50 | 999999 - 3 | 3 | 30 | 50 -(4 rows) - --- now we want to change pric_id in ALL tuples --- this gets us not what we need -update tttest set price_id = 5 where price_id = 3; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 2 | 2 | 20 | 40 - 3 | 3 | 30 | 50 - 5 | 30 | 60 | 999999 - 3 | 30 | 50 | 60 -(5 rows) - --- restore data as before last update: -select set_ttdummy(0); - set_ttdummy -------------- - 1 -(1 row) - -delete from tttest where price_id = 5; -update tttest set price_off = 999999 where price_val = 30; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 2 | 2 | 20 | 40 - 3 | 3 | 30 | 50 - 3 | 30 | 50 | 999999 -(4 rows) - --- and try change price_id now! -update tttest set price_id = 5 where price_id = 3; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 1 | 1 | 10 | 999999 - 2 | 2 | 20 | 40 - 5 | 3 | 30 | 50 - 5 | 30 | 50 | 999999 -(4 rows) - --- isn't it what we need ? -select set_ttdummy(1); - set_ttdummy -------------- - 0 -(1 row) - --- we want to correct some "date" -update tttest set price_on = -1 where price_id = 1; -ERROR: ttdummy (tttest): you cannot change price_on and/or price_off columns (use set_ttdummy) --- but this doesn't work --- try in this way -select set_ttdummy(0); - set_ttdummy -------------- - 1 -(1 row) - -update tttest set price_on = -1 where price_id = 1; -select * from tttest; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 2 | 2 | 20 | 40 - 5 | 3 | 30 | 50 - 5 | 30 | 50 | 999999 - 1 | 1 | -1 | 999999 -(4 rows) - --- isn't it what we need ? --- get price for price_id == 5 as it was @ "date" 35 -select * from tttest where price_on <= 35 and price_off > 35 and price_id = 5; - price_id | price_val | price_on | price_off -----------+-----------+----------+----------- - 5 | 3 | 30 | 50 -(1 row) - -drop table tttest; -drop sequence ttdummy_seq; -- -- tests for per-statement triggers -- @@ -494,6 +221,11 @@ SELECT * FROM main_table ORDER BY a, b; | (8 rows) +-- Test comments +COMMENT ON TRIGGER no_such_trigger ON main_table IS 'wrong'; +ERROR: trigger "no_such_trigger" for table "main_table" does not exist +COMMENT ON TRIGGER before_ins_stmt_trig ON main_table IS 'right'; +COMMENT ON TRIGGER before_ins_stmt_trig ON main_table IS NULL; -- -- test triggers with WHEN clause -- @@ -2796,11 +2528,13 @@ select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname, ---------+-------------------------+------------------------+----------- child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | O child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | O + child1 | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_del" | O + child1 | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_upd" | O parent | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | O parent | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | O parent | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_del" | O parent | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_upd" | O -(6 rows) +(8 rows) alter table parent disable trigger all; select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname, @@ -2811,11 +2545,13 @@ select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname, ---------+-------------------------+------------------------+----------- child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | D child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | D + child1 | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_del" | D + child1 | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_upd" | D parent | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | D parent | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | D parent | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_del" | D parent | RI_ConstraintTrigger_a_ | "RI_FKey_noaction_upd" | D -(6 rows) +(8 rows) drop table parent, child1; -- Verify that firing state propagates correctly on creation, too @@ -3074,6 +2810,55 @@ drop trigger child_row_trig on child; alter table parent attach partition child for values in ('AAA'); drop table child, parent; -- +-- Verify access of transition tables with UPDATE triggers and tuples +-- moved across partitions. +-- +create or replace function dump_update_new() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, new table = %', TG_NAME, + (select string_agg(new_table::text, ', ' order by a) from new_table); + return null; + end; +$$; +create or replace function dump_update_old() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, old table = %', TG_NAME, + (select string_agg(old_table::text, ', ' order by a) from old_table); + return null; + end; +$$; +create table trans_tab_parent (a text) partition by list (a); +create table trans_tab_child1 partition of trans_tab_parent for values in ('AAA1', 'AAA2'); +create table trans_tab_child2 partition of trans_tab_parent for values in ('BBB1', 'BBB2'); +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_update_old(); +create trigger trans_tab_parent_insert_trig + after insert on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_insert(); +create trigger trans_tab_parent_delete_trig + after delete on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_delete(); +insert into trans_tab_parent values ('AAA1'), ('BBB1'); +NOTICE: trigger = trans_tab_parent_insert_trig, new table = (AAA1), (BBB1) +-- should not trigger access to new table when moving across partitions. +update trans_tab_parent set a = 'BBB2' where a = 'AAA1'; +NOTICE: trigger = trans_tab_parent_update_trig, old table = (AAA1) +drop trigger trans_tab_parent_update_trig on trans_tab_parent; +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_update_new(); +-- should not trigger access to old table when moving across partitions. +update trans_tab_parent set a = 'AAA2' where a = 'BBB1'; +NOTICE: trigger = trans_tab_parent_update_trig, new table = (AAA2) +delete from trans_tab_parent; +NOTICE: trigger = trans_tab_parent_delete_trig, old table = (AAA2), (BBB2) +-- clean up +drop table trans_tab_parent, trans_tab_child1, trans_tab_child2; +drop function dump_update_new, dump_update_old; +-- -- Verify behavior of statement triggers on (non-partition) -- inheritance hierarchy with transition tables; similar to the -- partition case, except there is no rerouting on insertion and child @@ -3315,6 +3100,26 @@ create trigger my_table_col_update_trig ERROR: transition tables cannot be specified for triggers with column lists drop table my_table; -- +-- Verify that transition tables can't be used in, eg, a view. +-- +create table my_table (a int); +create function make_bogus_matview() returns trigger as +$$ begin + create materialized view transition_test_mv as select * from new_table; + return new; +end $$ +language plpgsql; +create trigger make_bogus_matview + after insert on my_table + referencing new table as new_table + for each statement execute function make_bogus_matview(); +insert into my_table values (42); -- error +ERROR: transition table "new_table" cannot be referenced in a persistent object +CONTEXT: SQL statement "create materialized view transition_test_mv as select * from new_table" +PL/pgSQL function make_bogus_matview() line 2 at SQL statement +drop table my_table; +drop function make_bogus_matview(); +-- -- Test firing of triggers with transition tables by foreign key cascades -- create table refd_table (a int primary key, b text); @@ -3728,3 +3533,70 @@ Inherits: parent drop table parent, child; drop function f(); +-- Test who runs deferred trigger functions +-- setup +create role regress_caller; +create role regress_fn_owner; +create function whoami() returns trigger language plpgsql +as $$ +begin + raise notice 'I am %', current_user; + return null; +end; +$$; +alter function whoami() owner to regress_fn_owner; +create table defer_trig (id integer); +grant insert on defer_trig to public; +create constraint trigger whoami after insert on defer_trig + deferrable initially deferred + for each row + execute function whoami(); +-- deferred triggers must run as the user that queued the trigger +begin; +set role regress_caller; +insert into defer_trig values (1); +reset role; +set role regress_fn_owner; +insert into defer_trig values (2); +reset role; +commit; +NOTICE: I am regress_caller +NOTICE: I am regress_fn_owner +-- security definer functions override the user who queued the trigger +alter function whoami() security definer; +begin; +set role regress_caller; +insert into defer_trig values (3); +reset role; +commit; +NOTICE: I am regress_fn_owner +alter function whoami() security invoker; +-- make sure the current user is restored after error +create or replace function whoami() returns trigger language plpgsql +as $$ +begin + raise notice 'I am %', current_user; + perform 1 / 0; + return null; +end; +$$; +begin; +set role regress_caller; +insert into defer_trig values (4); +reset role; +commit; -- error expected +NOTICE: I am regress_caller +ERROR: division by zero +CONTEXT: SQL statement "SELECT 1 / 0" +PL/pgSQL function whoami() line 4 at PERFORM +select current_user = session_user; + ?column? +---------- + t +(1 row) + +-- clean up +drop table defer_trig; +drop function whoami(); +drop role regress_fn_owner; +drop role regress_caller; diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index 88d8f6c32d665..dd0c52ab08b50 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -11,6 +11,10 @@ -- that is OID or REGPROC fields that are not zero and do not match some -- row in the linked-to table. However, if we want to enforce that a link -- field can't be 0, we have to check it here. +-- directory paths and dlsuffix are passed to us in environment variables +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX +\set regresslib :libdir '/regress' :dlsuffix -- **************** pg_type **************** -- Look for illegal values in pg_type fields. SELECT t1.oid, t1.typname @@ -550,8 +554,7 @@ WHERE pc.relkind IN ('r', 't', 'm') and SELECT a1.attrelid, a1.attname FROM pg_attribute as a1 WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR - a1.attcacheoff != -1 OR a1.attinhcount < 0 OR - (a1.attinhcount = 0 AND NOT a1.attislocal); + a1.attinhcount < 0 OR (a1.attinhcount = 0 AND NOT a1.attislocal); attrelid | attname ----------+--------- (0 rows) @@ -588,6 +591,21 @@ WHERE a1.atttypid = t1.oid AND ----------+---------+-----+--------- (0 rows) +-- Look for IsCatalogTextUniqueIndexOid() omissions. +CREATE FUNCTION is_catalog_text_unique_index_oid(oid) RETURNS bool + AS :'regresslib', 'is_catalog_text_unique_index_oid' + LANGUAGE C STRICT; +SELECT indexrelid::regclass +FROM pg_index +WHERE (is_catalog_text_unique_index_oid(indexrelid) <> + (indisunique AND + indexrelid < 16384 AND + EXISTS (SELECT 1 FROM pg_attribute + WHERE attrelid = indexrelid AND atttypid = 'text'::regtype))); + indexrelid +------------ +(0 rows) + -- **************** pg_range **************** -- Look for illegal values in pg_range fields. SELECT r.rngtypid, r.rngsubtype diff --git a/src/test/regress/expected/typed_table.out b/src/test/regress/expected/typed_table.out index b6fbda3f21786..885f085e15421 100644 --- a/src/test/regress/expected/typed_table.out +++ b/src/test/regress/expected/typed_table.out @@ -1,5 +1,7 @@ CREATE TABLE ttable1 OF nothing; ERROR: type "nothing" does not exist +LINE 1: CREATE TABLE ttable1 OF nothing; + ^ CREATE TYPE person_type AS (id int, name text); CREATE TABLE persons OF person_type; CREATE TABLE IF NOT EXISTS persons OF person_type; @@ -36,6 +38,8 @@ ALTER TABLE persons RENAME COLUMN id TO num; ERROR: cannot rename column of typed table ALTER TABLE persons ALTER COLUMN name TYPE varchar; ERROR: cannot alter column type of typed table +LINE 1: ALTER TABLE persons ALTER COLUMN name TYPE varchar; + ^ CREATE TABLE stuff (id int); ALTER TABLE persons INHERIT stuff; ERROR: cannot change inheritance of typed table diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out index 0fd0e1c38b3d7..96962817ed45a 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -370,17 +370,13 @@ select count(*) from explain (costs off) select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; - QUERY PLAN ------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------ Aggregate - -> Subquery Scan on ss - -> HashSetOp Intersect - -> Append - -> Subquery Scan on "*SELECT* 2" - -> Seq Scan on tenk1 - -> Subquery Scan on "*SELECT* 1" - -> Index Only Scan using tenk1_unique1 on tenk1 tenk1_1 -(8 rows) + -> HashSetOp Intersect + -> Seq Scan on tenk1 + -> Index Only Scan using tenk1_unique1 on tenk1 tenk1_1 +(4 rows) select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; @@ -389,18 +385,17 @@ select count(*) from 5000 (1 row) +-- this query will prefer a sorted setop unless we force it. +set enable_indexscan to off; explain (costs off) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +--------------------------------- HashSetOp Except - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Index Only Scan using tenk1_unique1 on tenk1 - -> Subquery Scan on "*SELECT* 2" - -> Index Only Scan using tenk1_unique2 on tenk1 tenk1_1 - Filter: (unique2 <> 10) -(7 rows) + -> Seq Scan on tenk1 + -> Seq Scan on tenk1 tenk1_1 + Filter: (unique2 <> 10) +(4 rows) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; unique1 @@ -408,6 +403,35 @@ select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 10 (1 row) +reset enable_indexscan; +-- the hashed implementation is sensitive to child plans' tuple slot types +explain (costs off) +select * from int8_tbl intersect select q2, q1 from int8_tbl order by 1, 2; + QUERY PLAN +--------------------------------------------- + Sort + Sort Key: int8_tbl.q1, int8_tbl.q2 + -> HashSetOp Intersect + -> Seq Scan on int8_tbl + -> Seq Scan on int8_tbl int8_tbl_1 +(5 rows) + +select * from int8_tbl intersect select q2, q1 from int8_tbl order by 1, 2; + q1 | q2 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(3 rows) + +select q2, q1 from int8_tbl intersect select * from int8_tbl order by 1, 2; + q2 | q1 +------------------+------------------ + 123 | 4567890123456789 + 4567890123456789 | 123 + 4567890123456789 | 4567890123456789 +(3 rows) + set enable_hashagg to off; explain (costs off) select count(*) from @@ -434,19 +458,15 @@ select count(*) from explain (costs off) select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; - QUERY PLAN ------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------ Aggregate - -> Subquery Scan on ss - -> SetOp Intersect - -> Sort - Sort Key: "*SELECT* 2".fivethous - -> Append - -> Subquery Scan on "*SELECT* 2" - -> Seq Scan on tenk1 - -> Subquery Scan on "*SELECT* 1" - -> Index Only Scan using tenk1_unique1 on tenk1 tenk1_1 -(10 rows) + -> SetOp Intersect + -> Sort + Sort Key: tenk1.fivethous + -> Seq Scan on tenk1 + -> Index Only Scan using tenk1_unique1 on tenk1 tenk1_1 +(6 rows) select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; @@ -457,18 +477,13 @@ select count(*) from explain (costs off) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; - QUERY PLAN ------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------ SetOp Except - -> Sort - Sort Key: "*SELECT* 1".unique1 - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Index Only Scan using tenk1_unique1 on tenk1 - -> Subquery Scan on "*SELECT* 2" - -> Index Only Scan using tenk1_unique2 on tenk1 tenk1_1 - Filter: (unique2 <> 10) -(9 rows) + -> Index Only Scan using tenk1_unique1 on tenk1 + -> Index Only Scan using tenk1_unique2 on tenk1 tenk1_1 + Filter: (unique2 <> 10) +(4 rows) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; unique1 @@ -476,6 +491,20 @@ select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 10 (1 row) +explain (costs off) +select f1 from int4_tbl union all + (select unique1 from tenk1 union select unique2 from tenk1); + QUERY PLAN +------------------------------------------------------------------------ + Append + -> Seq Scan on int4_tbl + -> Unique + -> Merge Append + Sort Key: tenk1.unique1 + -> Index Only Scan using tenk1_unique1 on tenk1 + -> Index Only Scan using tenk1_unique2 on tenk1 tenk1_1 +(7 rows) + reset enable_hashagg; -- non-hashable type set enable_hashagg to on; @@ -528,15 +557,12 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (va explain (costs off) select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x); - QUERY PLAN ------------------------------------------------ + QUERY PLAN +----------------------------------- HashSetOp Intersect - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(6 rows) + -> Values Scan on "*VALUES*" + -> Values Scan on "*VALUES*_1" +(3 rows) select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x); x @@ -546,15 +572,12 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from explain (costs off) select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x); - QUERY PLAN ------------------------------------------------ + QUERY PLAN +----------------------------------- HashSetOp Except - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(6 rows) + -> Values Scan on "*VALUES*" + -> Values Scan on "*VALUES*_1" +(3 rows) select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x); x @@ -606,17 +629,16 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) union select x from (va explain (costs off) select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Intersect -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from (values (array[1, 2]), (array[1, 4])) _(x); x @@ -626,17 +648,16 @@ select x from (values (array[1, 2]), (array[1, 3])) _(x) intersect select x from explain (costs off) select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Except -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (array[1, 2]), (array[1, 3])) _(x) except select x from (values (array[1, 2]), (array[1, 4])) _(x); x @@ -669,17 +690,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values explain (costs off) select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Intersect -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x); x @@ -689,17 +709,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (va explain (costs off) select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Except -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x); x @@ -777,17 +796,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) union select x from (values explain (costs off) select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Intersect -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (values (row(1, 2)), (row(1, 4))) _(x); x @@ -797,17 +815,16 @@ select x from (values (row(1, 2)), (row(1, 3))) _(x) intersect select x from (va explain (costs off) select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x); - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +----------------------------------------- SetOp Except -> Sort - Sort Key: "*SELECT* 1".x - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Values Scan on "*VALUES*" - -> Subquery Scan on "*SELECT* 2" - -> Values Scan on "*VALUES*_1" -(8 rows) + Sort Key: "*VALUES*".column1 + -> Values Scan on "*VALUES*" + -> Sort + Sort Key: "*VALUES*_1".column1 + -> Values Scan on "*VALUES*_1" +(7 rows) select x from (values (row(1, 2)), (row(1, 3))) _(x) except select x from (values (row(1, 2)), (row(1, 4))) _(x); x @@ -822,11 +839,12 @@ explain (costs off) select '123'::xid union select '123'::xid; QUERY PLAN --------------------------- HashAggregate + Disabled: true Group Key: ('123'::xid) -> Append -> Result -> Result -(5 rows) +(6 rows) reset enable_hashagg; -- @@ -969,15 +987,12 @@ set enable_sort = false; -- no means to disable Unique. explain (costs off) select from generate_series(1,5) intersect select from generate_series(1,3); - QUERY PLAN ----------------------------------------------------------------------- - HashSetOp Intersect - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Function Scan on generate_series - -> Subquery Scan on "*SELECT* 2" - -> Function Scan on generate_series generate_series_1 -(6 rows) + QUERY PLAN +---------------------------------------------------------- + SetOp Intersect + -> Function Scan on generate_series + -> Function Scan on generate_series generate_series_1 +(3 rows) select from generate_series(1,5) union all select from generate_series(1,3); -- @@ -1014,15 +1029,12 @@ select from generate_series(1,5) union select from generate_series(1,3); explain (costs off) select from generate_series(1,5) intersect select from generate_series(1,3); - QUERY PLAN ----------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------- SetOp Intersect - -> Append - -> Subquery Scan on "*SELECT* 1" - -> Function Scan on generate_series - -> Subquery Scan on "*SELECT* 2" - -> Function Scan on generate_series generate_series_1 -(6 rows) + -> Function Scan on generate_series + -> Function Scan on generate_series generate_series_1 +(3 rows) select from generate_series(1,5) union select from generate_series(1,3); -- @@ -1460,18 +1472,17 @@ select t1.unique1 from tenk1 t1 inner join tenk2 t2 on t1.tenthous = t2.tenthous and t2.thousand = 0 union all (values(1)) limit 1; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------- Limit -> Append -> Nested Loop - Join Filter: (t1.tenthous = t2.tenthous) - -> Seq Scan on tenk1 t1 - -> Materialize - -> Seq Scan on tenk2 t2 - Filter: (thousand = 0) + -> Seq Scan on tenk2 t2 + Filter: (thousand = 0) + -> Index Scan using tenk1_thous_tenthous on tenk1 t1 + Index Cond: (tenthous = t2.tenthous) -> Result -(9 rows) +(8 rows) -- Ensure there is no problem if cheapest_startup_path is NULL explain (costs off) diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out index 420769a40c9df..095df0a670c24 100644 --- a/src/test/regress/expected/updatable_views.out +++ b/src/test/regress/expected/updatable_views.out @@ -437,7 +437,8 @@ NOTICE: drop cascades to view ro_view19 -- simple updatable view CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0; +CREATE VIEW rw_view1 AS + SELECT *, 'Const' AS c, (SELECT concat('b: ', b)) AS d FROM base_tbl WHERE a>0; SELECT table_name, is_insertable_into FROM information_schema.tables WHERE table_name = 'rw_view1'; @@ -462,7 +463,9 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view1 | a | YES rw_view1 | b | YES -(2 rows) + rw_view1 | c | NO + rw_view1 | d | NO +(4 rows) INSERT INTO rw_view1 VALUES (3, 'Row 3'); INSERT INTO rw_view1 (a) VALUES (4); @@ -479,20 +482,22 @@ SELECT * FROM base_tbl; 5 | Unspecified (6 rows) +SET jit_above_cost = 0; MERGE INTO rw_view1 t USING (VALUES (0, 'ROW 0'), (1, 'ROW 1'), (2, 'ROW 2'), (3, 'ROW 3')) AS v(a,b) ON t.a = v.a WHEN MATCHED AND t.a <= 1 THEN UPDATE SET b = v.b WHEN MATCHED THEN DELETE WHEN NOT MATCHED AND a > 0 THEN INSERT (a) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; - merge_action | a | b | a | b ---------------+---+-------+---+------------- - UPDATE | 1 | ROW 1 | 1 | ROW 1 - DELETE | 3 | ROW 3 | 3 | Row 3 - INSERT | 2 | ROW 2 | 2 | Unspecified + RETURNING merge_action(), v.*, old, new, old.*, new.*, t.*; + merge_action | a | b | old | new | a | b | c | d | a | b | c | d | a | b | c | d +--------------+---+-------+------------------------------+----------------------------------------+---+-------+-------+----------+---+-------------+-------+----------------+---+-------------+-------+---------------- + UPDATE | 1 | ROW 1 | (1,"Row 1",Const,"b: Row 1") | (1,"ROW 1",Const,"b: ROW 1") | 1 | Row 1 | Const | b: Row 1 | 1 | ROW 1 | Const | b: ROW 1 | 1 | ROW 1 | Const | b: ROW 1 + DELETE | 3 | ROW 3 | (3,"Row 3",Const,"b: Row 3") | | 3 | Row 3 | Const | b: Row 3 | | | | | 3 | Row 3 | Const | b: Row 3 + INSERT | 2 | ROW 2 | | (2,Unspecified,Const,"b: Unspecified") | | | | | 2 | Unspecified | Const | b: Unspecified | 2 | Unspecified | Const | b: Unspecified (3 rows) +SET jit_above_cost TO DEFAULT; SELECT * FROM base_tbl ORDER BY a; a | b ----+------------- @@ -511,13 +516,13 @@ MERGE INTO rw_view1 t WHEN MATCHED THEN DELETE WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED AND a > 0 THEN INSERT (a) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; - merge_action | a | b | a | b ---------------+---+----+---+------------- - UPDATE | 1 | R1 | 1 | R1 - DELETE | | | 5 | Unspecified - DELETE | 2 | R2 | 2 | Unspecified - INSERT | 3 | R3 | 3 | Unspecified + RETURNING merge_action(), v.*, old, new, old.*, new.*, t.*; + merge_action | a | b | old | new | a | b | c | d | a | b | c | d | a | b | c | d +--------------+---+----+----------------------------------------+----------------------------------------+---+-------------+-------+----------------+---+-------------+-------+----------------+---+-------------+-------+---------------- + UPDATE | 1 | R1 | (1,"ROW 1",Const,"b: ROW 1") | (1,R1,Const,"b: R1") | 1 | ROW 1 | Const | b: ROW 1 | 1 | R1 | Const | b: R1 | 1 | R1 | Const | b: R1 + DELETE | | | (5,Unspecified,Const,"b: Unspecified") | | 5 | Unspecified | Const | b: Unspecified | | | | | 5 | Unspecified | Const | b: Unspecified + DELETE | 2 | R2 | (2,Unspecified,Const,"b: Unspecified") | | 2 | Unspecified | Const | b: Unspecified | | | | | 2 | Unspecified | Const | b: Unspecified + INSERT | 3 | R3 | | (3,Unspecified,Const,"b: Unspecified") | | | | | 3 | Unspecified | Const | b: Unspecified | 3 | Unspecified | Const | b: Unspecified (4 rows) SELECT * FROM base_tbl ORDER BY a; @@ -634,8 +639,10 @@ DROP TABLE base_tbl_hist; -- view on top of view CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl WHERE a>0; -CREATE VIEW rw_view2 AS SELECT aa AS aaa, bb AS bbb FROM rw_view1 WHERE aa<10; +CREATE VIEW rw_view1 AS + SELECT b AS bb, a AS aa, 'Const1' AS c FROM base_tbl WHERE a>0; +CREATE VIEW rw_view2 AS + SELECT aa AS aaa, bb AS bbb, c AS c1, 'Const2' AS c2 FROM rw_view1 WHERE aa<10; SELECT table_name, is_insertable_into FROM information_schema.tables WHERE table_name = 'rw_view2'; @@ -660,27 +667,29 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view2 | aaa | YES rw_view2 | bbb | YES -(2 rows) + rw_view2 | c1 | NO + rw_view2 | c2 | NO +(4 rows) INSERT INTO rw_view2 VALUES (3, 'Row 3'); INSERT INTO rw_view2 (aaa) VALUES (4); SELECT * FROM rw_view2; - aaa | bbb ------+------------- - 1 | Row 1 - 2 | Row 2 - 3 | Row 3 - 4 | Unspecified + aaa | bbb | c1 | c2 +-----+-------------+--------+-------- + 1 | Row 1 | Const1 | Const2 + 2 | Row 2 | Const1 | Const2 + 3 | Row 3 | Const1 | Const2 + 4 | Unspecified | Const1 | Const2 (4 rows) UPDATE rw_view2 SET bbb='Row 4' WHERE aaa=4; DELETE FROM rw_view2 WHERE aaa=2; SELECT * FROM rw_view2; - aaa | bbb ------+------- - 1 | Row 1 - 3 | Row 3 - 4 | Row 4 + aaa | bbb | c1 | c2 +-----+-------+--------+-------- + 1 | Row 1 | Const1 | Const2 + 3 | Row 3 | Const1 | Const2 + 4 | Row 4 | Const1 | Const2 (3 rows) MERGE INTO rw_view2 t @@ -688,20 +697,20 @@ MERGE INTO rw_view2 t WHEN MATCHED AND aaa = 3 THEN DELETE WHEN MATCHED THEN UPDATE SET bbb = v.b WHEN NOT MATCHED THEN INSERT (aaa) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; - merge_action | a | b | aaa | bbb ---------------+---+----+-----+------------- - DELETE | 3 | R3 | 3 | Row 3 - UPDATE | 4 | R4 | 4 | R4 - INSERT | 5 | R5 | 5 | Unspecified + RETURNING merge_action(), v.*, (SELECT old), (SELECT (SELECT new)), t.*; + merge_action | a | b | old | new | aaa | bbb | c1 | c2 +--------------+---+----+---------------------------+-------------------------------+-----+-------------+--------+-------- + DELETE | 3 | R3 | (3,"Row 3",Const1,Const2) | | 3 | Row 3 | Const1 | Const2 + UPDATE | 4 | R4 | (4,"Row 4",Const1,Const2) | (4,R4,Const1,Const2) | 4 | R4 | Const1 | Const2 + INSERT | 5 | R5 | | (5,Unspecified,Const1,Const2) | 5 | Unspecified | Const1 | Const2 (3 rows) SELECT * FROM rw_view2 ORDER BY aaa; - aaa | bbb ------+------------- - 1 | Row 1 - 4 | R4 - 5 | Unspecified + aaa | bbb | c1 | c2 +-----+-------------+--------+-------- + 1 | Row 1 | Const1 | Const2 + 4 | R4 | Const1 | Const2 + 5 | Unspecified | Const1 | Const2 (3 rows) MERGE INTO rw_view2 t @@ -710,21 +719,21 @@ MERGE INTO rw_view2 t WHEN MATCHED THEN UPDATE SET bbb = v.b WHEN NOT MATCHED THEN INSERT (aaa) VALUES (v.a) WHEN NOT MATCHED BY SOURCE THEN UPDATE SET bbb = 'Not matched by source' - RETURNING merge_action(), v.*, t.*; - merge_action | a | b | aaa | bbb ---------------+---+----+-----+----------------------- - UPDATE | | | 1 | Not matched by source - DELETE | 4 | r4 | 4 | R4 - UPDATE | 5 | r5 | 5 | r5 - INSERT | 6 | r6 | 6 | Unspecified + RETURNING merge_action(), v.*, old, (SELECT new FROM (VALUES ((SELECT new)))), t.*; + merge_action | a | b | old | new | aaa | bbb | c1 | c2 +--------------+---+----+-------------------------------+-------------------------------------------+-----+-----------------------+--------+-------- + UPDATE | | | (1,"Row 1",Const1,Const2) | (1,"Not matched by source",Const1,Const2) | 1 | Not matched by source | Const1 | Const2 + DELETE | 4 | r4 | (4,R4,Const1,Const2) | | 4 | R4 | Const1 | Const2 + UPDATE | 5 | r5 | (5,Unspecified,Const1,Const2) | (5,r5,Const1,Const2) | 5 | r5 | Const1 | Const2 + INSERT | 6 | r6 | | (6,Unspecified,Const1,Const2) | 6 | Unspecified | Const1 | Const2 (4 rows) SELECT * FROM rw_view2 ORDER BY aaa; - aaa | bbb ------+----------------------- - 1 | Not matched by source - 5 | r5 - 6 | Unspecified + aaa | bbb | c1 | c2 +-----+-----------------------+--------+-------- + 1 | Not matched by source | Const1 | Const2 + 5 | r5 | Const1 | Const2 + 6 | Unspecified | Const1 | Const2 (3 rows) EXPLAIN (costs off) UPDATE rw_view2 SET aaa=5 WHERE aaa=4; @@ -886,16 +895,25 @@ SELECT table_name, column_name, is_updatable rw_view2 | b | YES (4 rows) -INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *; - a | b ----+------- - 3 | Row 3 +INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING old.*, new.*; + a | b | a | b +---+---+---+------- + | | 3 | Row 3 (1 row) -UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *; - a | b ----+----------- - 3 | Row three +UPDATE rw_view2 SET b='R3' WHERE a=3 RETURNING old.*, new.*; -- rule returns NEW + a | b | a | b +---+----+---+---- + 3 | R3 | 3 | R3 +(1 row) + +DROP RULE rw_view1_upd_rule ON rw_view1; +CREATE RULE rw_view1_upd_rule AS ON UPDATE TO rw_view1 + DO INSTEAD UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a RETURNING *; +UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING old.*, new.*; + a | b | a | b +---+----+---+----------- + 3 | R3 | 3 | Row three (1 row) SELECT * FROM rw_view2; @@ -906,10 +924,10 @@ SELECT * FROM rw_view2; 3 | Row three (3 rows) -DELETE FROM rw_view2 WHERE a=3 RETURNING *; - a | b ----+----------- - 3 | Row three +DELETE FROM rw_view2 WHERE a=3 RETURNING old.*, new.*; + a | b | a | b +---+-----------+---+--- + 3 | Row three | | (1 row) SELECT * FROM rw_view2; @@ -960,8 +978,10 @@ drop cascades to view rw_view2 -- view on top of view with triggers CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers -CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a<10; +CREATE VIEW rw_view1 AS + SELECT *, 'Const1' AS c1 FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers +CREATE VIEW rw_view2 AS + SELECT *, 'Const2' AS c2 FROM rw_view1 WHERE a<10; SELECT table_name, is_insertable_into FROM information_schema.tables WHERE table_name LIKE 'rw_view%' @@ -992,9 +1012,12 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view1 | a | NO rw_view1 | b | NO + rw_view1 | c1 | NO rw_view2 | a | NO rw_view2 | b | NO -(4 rows) + rw_view2 | c1 | NO + rw_view2 | c2 | NO +(7 rows) CREATE FUNCTION rw_view1_trig_fn() RETURNS trigger AS @@ -1002,9 +1025,11 @@ $$ BEGIN IF TG_OP = 'INSERT' THEN INSERT INTO base_tbl VALUES (NEW.a, NEW.b); + NEW.c1 = 'Trigger Const1'; RETURN NEW; ELSIF TG_OP = 'UPDATE' THEN UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a; + NEW.c1 = 'Trigger Const1'; RETURN NEW; ELSIF TG_OP = 'DELETE' THEN DELETE FROM base_tbl WHERE a=OLD.a; @@ -1045,9 +1070,12 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view1 | a | NO rw_view1 | b | NO + rw_view1 | c1 | NO rw_view2 | a | NO rw_view2 | b | NO -(4 rows) + rw_view2 | c1 | NO + rw_view2 | c2 | NO +(7 rows) CREATE TRIGGER rw_view1_upd_trig INSTEAD OF UPDATE ON rw_view1 FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn(); @@ -1081,9 +1109,12 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view1 | a | NO rw_view1 | b | NO + rw_view1 | c1 | NO rw_view2 | a | NO rw_view2 | b | NO -(4 rows) + rw_view2 | c1 | NO + rw_view2 | c2 | NO +(7 rows) CREATE TRIGGER rw_view1_del_trig INSTEAD OF DELETE ON rw_view1 FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn(); @@ -1117,41 +1148,44 @@ SELECT table_name, column_name, is_updatable ------------+-------------+-------------- rw_view1 | a | NO rw_view1 | b | NO + rw_view1 | c1 | NO rw_view2 | a | NO rw_view2 | b | NO -(4 rows) + rw_view2 | c1 | NO + rw_view2 | c2 | NO +(7 rows) -INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *; - a | b ----+------- - 3 | Row 3 +INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING old.*, new.*; + a | b | c1 | c2 | a | b | c1 | c2 +---+---+----+----+---+-------+----------------+-------- + | | | | 3 | Row 3 | Trigger Const1 | Const2 (1 row) -UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *; - a | b ----+----------- - 3 | Row three +UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING old.*, new.*; + a | b | c1 | c2 | a | b | c1 | c2 +---+-------+--------+--------+---+-----------+----------------+-------- + 3 | Row 3 | Const1 | Const2 | 3 | Row three | Trigger Const1 | Const2 (1 row) SELECT * FROM rw_view2; - a | b ----+----------- - 1 | Row 1 - 2 | Row 2 - 3 | Row three + a | b | c1 | c2 +---+-----------+--------+-------- + 1 | Row 1 | Const1 | Const2 + 2 | Row 2 | Const1 | Const2 + 3 | Row three | Const1 | Const2 (3 rows) -DELETE FROM rw_view2 WHERE a=3 RETURNING *; - a | b ----+----------- - 3 | Row three +DELETE FROM rw_view2 WHERE a=3 RETURNING old.*, new.*; + a | b | c1 | c2 | a | b | c1 | c2 +---+-----------+--------+--------+---+---+----+---- + 3 | Row three | Const1 | Const2 | | | | (1 row) SELECT * FROM rw_view2; - a | b ----+------- - 1 | Row 1 - 2 | Row 2 + a | b | c1 | c2 +---+-------+--------+-------- + 1 | Row 1 | Const1 | Const2 + 2 | Row 2 | Const1 | Const2 (2 rows) MERGE INTO rw_view2 t @@ -1159,12 +1193,12 @@ MERGE INTO rw_view2 t WHEN MATCHED AND t.a <= 1 THEN DELETE WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b) - RETURNING merge_action(), s.*, t.*; - merge_action | a | b | a | b ---------------+---+----+---+------- - DELETE | 1 | R1 | 1 | Row 1 - UPDATE | 2 | R2 | 2 | R2 - INSERT | 3 | R3 | 3 | R3 + RETURNING merge_action(), s.*, old, new, t.*; + merge_action | a | b | old | new | a | b | c1 | c2 +--------------+---+----+---------------------------+--------------------------------+---+-------+----------------+-------- + DELETE | 1 | R1 | (1,"Row 1",Const1,Const2) | | 1 | Row 1 | Const1 | Const2 + UPDATE | 2 | R2 | (2,"Row 2",Const1,Const2) | (2,R2,"Trigger Const1",Const2) | 2 | R2 | Trigger Const1 | Const2 + INSERT | 3 | R3 | | (3,R3,"Trigger Const1",Const2) | 3 | R3 | Trigger Const1 | Const2 (3 rows) SELECT * FROM base_tbl ORDER BY a; @@ -1182,12 +1216,12 @@ MERGE INTO rw_view2 t WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b) WHEN NOT MATCHED BY SOURCE THEN UPDATE SET b = 'Not matched by source' - RETURNING merge_action(), s.*, t.*; - merge_action | a | b | a | b ---------------+---+----+---+----------------------- - UPDATE | 2 | r2 | 2 | r2 - UPDATE | | | 3 | Not matched by source - INSERT | 1 | r1 | 1 | r1 + RETURNING merge_action(), s.*, old, new, t.*; + merge_action | a | b | old | new | a | b | c1 | c2 +--------------+---+----+----------------------+-----------------------------------------------------+---+-----------------------+----------------+-------- + UPDATE | 2 | r2 | (2,R2,Const1,Const2) | (2,r2,"Trigger Const1",Const2) | 2 | r2 | Trigger Const1 | Const2 + UPDATE | | | (3,R3,Const1,Const2) | (3,"Not matched by source","Trigger Const1",Const2) | 3 | Not matched by source | Trigger Const1 | Const2 + INSERT | 1 | r1 | | (1,r1,"Trigger Const1",Const2) | 1 | r1 | Trigger Const1 | Const2 (3 rows) SELECT * FROM base_tbl ORDER BY a; @@ -1279,7 +1313,7 @@ MERGE INTO rw_view2 t WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); -- should fail ERROR: cannot merge into view "rw_view2" -DETAIL: MERGE is not supported for views with INSTEAD OF triggers for some actions, but not others. +DETAIL: MERGE is not supported for views with INSTEAD OF triggers for some actions but not all. HINT: To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers. MERGE INTO rw_view2 t USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index 6026e15ed3197..95392003b86ed 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -10,6 +10,11 @@ CREATE TABLE guid2 guid_field UUID, text_field TEXT DEFAULT(now()) ); +CREATE TABLE guid3 +( + id SERIAL, + guid_field UUID +); -- inserting invalid data tests -- too long INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F'); @@ -129,6 +134,37 @@ CREATE INDEX guid1_btree ON guid1 USING BTREE (guid_field); CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field); -- unique index test CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field); +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111' OR + guid_field <> '3f3e3c3b-3a30-3938-3736-353433a2313e'; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------ + Aggregate + -> Seq Scan on guid1 + Filter: ((guid_field <> '11111111-1111-1111-1111-111111111111'::uuid) OR (guid_field <> '3f3e3c3b-3a30-3938-3736-353433a2313e'::uuid)) +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222' OR + guid_field <= '11111111111111111111111111111111' OR + guid_field <= '3f3e3c3b-3a30-3938-3736-353433a2313e'; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + -> Seq Scan on guid1 + Filter: ((guid_field <= '22222222-2222-2222-2222-222222222222'::uuid) OR (guid_field <= '11111111-1111-1111-1111-111111111111'::uuid) OR (guid_field <= '3f3e3c3b-3a30-3938-3736-353433a2313e'::uuid)) +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field = '3f3e3c3b-3a30-3938-3736-353433a2313e' OR + guid_field = '11111111111111111111111111111111'; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------- + Aggregate + -> Seq Scan on guid1 + Filter: ((guid_field = '3f3e3c3b-3a30-3938-3736-353433a2313e'::uuid) OR (guid_field = '11111111-1111-1111-1111-111111111111'::uuid)) +(3 rows) + -- should fail INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); ERROR: duplicate key value violates unique constraint "guid1_unique_btree" @@ -168,6 +204,50 @@ SELECT count(DISTINCT guid_field) FROM guid1; 2 (1 row) +-- test of uuidv4() alias +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (uuidv4()); +INSERT INTO guid1 (guid_field) VALUES (uuidv4()); +SELECT count(DISTINCT guid_field) FROM guid1; + count +------- + 2 +(1 row) + +-- generation test for v7 +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (uuidv7()); +INSERT INTO guid1 (guid_field) VALUES (uuidv7()); +INSERT INTO guid1 (guid_field) VALUES (uuidv7(INTERVAL '1 day')); +SELECT count(DISTINCT guid_field) FROM guid1; + count +------- + 3 +(1 row) + +-- test sortability of v7 +INSERT INTO guid3 (guid_field) SELECT uuidv7() FROM generate_series(1, 10); +SELECT array_agg(id ORDER BY guid_field) FROM guid3; + array_agg +------------------------ + {1,2,3,4,5,6,7,8,9,10} +(1 row) + +-- Check the timestamp offsets for v7. +-- +-- generate UUIDv7 values with timestamps ranging from 1970 (the Unix epoch year) +-- to 10888 (one year before the maximum possible year), and then verify that +-- the extracted timestamps from these UUIDv7 values have not overflowed. +WITH uuidts AS ( + SELECT y, ts as ts, lag(ts) OVER (ORDER BY y) AS prev_ts + FROM (SELECT y, uuid_extract_timestamp(uuidv7((y || ' years')::interval)) AS ts + FROM generate_series(1970 - extract(year from now())::int, 10888 - extract(year from now())::int) y) +) +SELECT y, ts, prev_ts FROM uuidts WHERE ts < prev_ts; + y | ts | prev_ts +---+----+--------- +(0 rows) + -- extract functions -- version SELECT uuid_extract_version('11111111-1111-5111-8111-111111111111'); -- 5 @@ -188,8 +268,26 @@ SELECT uuid_extract_version('11111111-1111-1111-1111-111111111111'); -- null (1 row) +SELECT uuid_extract_version(uuidv4()); -- 4 + uuid_extract_version +---------------------- + 4 +(1 row) + +SELECT uuid_extract_version(uuidv7()); -- 7 + uuid_extract_version +---------------------- + 7 +(1 row) + -- timestamp -SELECT uuid_extract_timestamp('C232AB00-9414-11EC-B3C8-9F6BDECED846') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 4122bis test vector +SELECT uuid_extract_timestamp('C232AB00-9414-11EC-B3C8-9F6BDECED846') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 9562 test vector for v1 + ?column? +---------- + t +(1 row) + +SELECT uuid_extract_timestamp('017F22E2-79B0-7CC3-98C4-DC0C0C07398F') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 9562 test vector for v7 ?column? ---------- t @@ -208,4 +306,4 @@ SELECT uuid_extract_timestamp('11111111-1111-1111-1111-111111111111'); -- null (1 row) -- clean up -DROP TABLE guid1, guid2 CASCADE; +DROP TABLE guid1, guid2, guid3 CASCADE; diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 2eba7128876f2..0abcc99989e07 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -148,6 +148,10 @@ CREATE INDEX brin_pvactst ON pvactst USING brin (i); CREATE INDEX gin_pvactst ON pvactst USING gin (a); CREATE INDEX gist_pvactst ON pvactst USING gist (p); CREATE INDEX spgist_pvactst ON pvactst USING spgist (p); +CREATE TABLE pvactst2 (i INT) WITH (autovacuum_enabled = off); +INSERT INTO pvactst2 SELECT generate_series(1, 1000); +CREATE INDEX ON pvactst2 (i); +CREATE INDEX ON pvactst2 (i); -- VACUUM invokes parallel index cleanup SET min_parallel_index_scan_size to 0; VACUUM (PARALLEL 2) pvactst; @@ -167,6 +171,13 @@ VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel ERROR: parallel option requires a value between 0 and 1024 LINE 1: VACUUM (PARALLEL) pvactst; ^ +-- Test parallel vacuum using the minimum maintenance_work_mem with and without +-- dead tuples. +SET maintenance_work_mem TO 64; +VACUUM (PARALLEL 2) pvactst2; +DELETE FROM pvactst2 WHERE i < 1000; +VACUUM (PARALLEL 2) pvactst2; +RESET maintenance_work_mem; -- Test different combinations of parallel and full options for temporary tables CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY); CREATE INDEX tmp_idx1 ON tmp (a); @@ -175,6 +186,7 @@ WARNING: disabling parallel option of vacuum on "tmp" --- cannot vacuum tempora VACUUM (PARALLEL 0, FULL TRUE) tmp; -- can specify parallel disabled (even though that's implied by FULL) RESET min_parallel_index_scan_size; DROP TABLE pvactst; +DROP TABLE pvactst2; -- INDEX_CLEANUP option CREATE TABLE no_index_cleanup (i INT PRIMARY KEY, t TEXT); -- Use uncompressed data stored in toast. @@ -224,6 +236,7 @@ SELECT pg_relation_size('vac_truncate_test') > 0; t (1 row) +SET vacuum_truncate = false; VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') = 0; ?column? @@ -232,6 +245,32 @@ SELECT pg_relation_size('vac_truncate_test') = 0; (1 row) VACUUM (TRUNCATE FALSE, FULL TRUE) vac_truncate_test; +ALTER TABLE vac_truncate_test RESET (vacuum_truncate); +INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); +ERROR: null value in column "i" of relation "vac_truncate_test" violates not-null constraint +DETAIL: Failing row contains (null, null). +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; + ?column? +---------- + t +(1 row) + +RESET vacuum_truncate; +VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; + ?column? +---------- + t +(1 row) + +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') = 0; + ?column? +---------- + t +(1 row) + DROP TABLE vac_truncate_test; -- partitioned table CREATE TABLE vacparted (a int, b char) PARTITION BY LIST (a); @@ -291,6 +330,98 @@ ANALYZE vactst, vactst; BEGIN; -- ANALYZE behaves differently inside a transaction block ANALYZE vactst, vactst; COMMIT; +-- +-- Tests for ANALYZE ONLY / VACUUM ONLY on partitioned tables +-- +CREATE TABLE only_parted (a int, b text) PARTITION BY LIST (a); +CREATE TABLE only_parted1 PARTITION OF only_parted FOR VALUES IN (1); +INSERT INTO only_parted VALUES (1, 'a'); +-- Ensure only the partitioned table is analyzed +ANALYZE ONLY only_parted; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +--------------+----------+---------- + only_parted | t | f + only_parted1 | f | f +(2 rows) + +-- Ensure partitioned table and the partitions are analyzed +ANALYZE only_parted; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +--------------+----------+---------- + only_parted | t | f + only_parted1 | t | f +(2 rows) + +DROP TABLE only_parted; +-- VACUUM ONLY on a partitioned table does nothing, ensure we get a warning. +VACUUM ONLY vacparted; +WARNING: VACUUM ONLY of partitioned table "vacparted" has no effect +-- Try ANALYZE ONLY with a column list +ANALYZE ONLY vacparted(a,b); +-- +-- Tests for VACUUM ONLY / ANALYZE ONLY on inheritance tables +-- +CREATE TABLE only_inh_parent (a int primary key, b TEXT); +CREATE TABLE only_inh_child () INHERITS (only_inh_parent); +INSERT INTO only_inh_child(a,b) VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc'); +-- Ensure only parent is analyzed +ANALYZE ONLY only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +-----------------+----------+---------- + only_inh_child | f | f + only_inh_parent | t | f +(2 rows) + +-- Ensure the parent and child are analyzed +ANALYZE only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +-----------------+----------+---------- + only_inh_child | t | f + only_inh_parent | t | f +(2 rows) + +-- Ensure only the parent is vacuumed +VACUUM ONLY only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +-----------------+----------+---------- + only_inh_child | t | f + only_inh_parent | t | t +(2 rows) + +-- Ensure parent and child are vacuumed +VACUUM only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + relname | analyzed | vacuumed +-----------------+----------+---------- + only_inh_child | t | t + only_inh_parent | t | t +(2 rows) + +DROP TABLE only_inh_parent CASCADE; +NOTICE: drop cascades to table only_inh_child -- parenthesized syntax for ANALYZE ANALYZE (VERBOSE) does_not_exist; ERROR: relation "does_not_exist" does not exist diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out index 8b447aa01e59f..b86b668f433d0 100644 --- a/src/test/regress/expected/window.out +++ b/src/test/regress/expected/window.out @@ -652,10 +652,11 @@ select first_value(max(x)) over (), y QUERY PLAN --------------------------------------------- WindowAgg + Window: w1 AS () -> HashAggregate Group Key: (tenk1.ten + tenk1.four) -> Seq Scan on tenk1 -(4 rows) +(5 rows) -- window functions returning pass-by-ref values from different rows select x, lag(x, 1) over (order by x), lead(x, 3) over (order by x) @@ -3537,14 +3538,15 @@ explain (costs off) select f1, sum(f1) over (partition by f1 order by f2 range between 1 preceding and 1 following) from t1 where f1 = f2; - QUERY PLAN ---------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (PARTITION BY f1 ORDER BY f2 RANGE BETWEEN '1'::bigint PRECEDING AND '1'::bigint FOLLOWING) -> Sort Sort Key: f1 -> Seq Scan on t1 Filter: (f1 = f2) -(5 rows) +(6 rows) select f1, sum(f1) over (partition by f1 order by f2 range between 1 preceding and 1 following) @@ -3583,14 +3585,15 @@ explain (costs off) select f1, sum(f1) over (partition by f1 order by f2 groups between 1 preceding and 1 following) from t1 where f1 = f2; - QUERY PLAN ---------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (PARTITION BY f1 ORDER BY f2 GROUPS BETWEEN '1'::bigint PRECEDING AND '1'::bigint FOLLOWING) -> Sort Sort Key: f1 -> Seq Scan on t1 Filter: (f1 = f2) -(5 rows) +(6 rows) select f1, sum(f1) over (partition by f1 order by f2 groups between 1 preceding and 1 following) @@ -3711,13 +3714,14 @@ SELECT cume_dist() OVER (PARTITION BY depname ORDER BY enroll_date RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) cd FROM empsalary; - QUERY PLAN ----------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------- WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY enroll_date ROWS UNBOUNDED PRECEDING) -> Sort Sort Key: depname, enroll_date -> Seq Scan on empsalary -(4 rows) +(5 rows) -- Ensure WindowFuncs which cannot support their WindowClause's frameOptions -- being changed are untouched @@ -3731,18 +3735,20 @@ SELECT count(*) OVER (PARTITION BY depname ORDER BY enroll_date RANGE BETWEEN CURRENT ROW AND CURRENT ROW) cnt FROM empsalary; - QUERY PLAN ------------------------------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- WindowAgg - Output: empno, depname, (row_number() OVER (?)), (rank() OVER (?)), count(*) OVER (?), enroll_date + Output: empno, depname, (row_number() OVER w1), (rank() OVER w1), count(*) OVER w2, enroll_date + Window: w2 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date RANGE BETWEEN CURRENT ROW AND CURRENT ROW) -> WindowAgg - Output: depname, enroll_date, empno, row_number() OVER (?), rank() OVER (?) + Output: depname, enroll_date, empno, row_number() OVER w1, rank() OVER w1 + Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING) -> Sort Output: depname, enroll_date, empno Sort Key: empsalary.depname, empsalary.enroll_date -> Seq Scan on pg_temp.empsalary Output: depname, enroll_date, empno -(9 rows) +(11 rows) -- Ensure the above query gives us the expected results SELECT @@ -3777,16 +3783,18 @@ SELECT * FROM min(salary) OVER (PARTITION BY depname || 'A', depname) depminsalary FROM empsalary) emp WHERE depname = 'sales'; - QUERY PLAN --------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------- Subquery Scan on emp -> WindowAgg + Window: w2 AS () -> WindowAgg + Window: w1 AS (PARTITION BY (((empsalary.depname)::text || 'A'::text))) -> Sort Sort Key: (((empsalary.depname)::text || 'A'::text)) -> Seq Scan on empsalary Filter: ((depname)::text = 'sales'::text) -(7 rows) +(9 rows) -- pushdown is unsafe because there's a PARTITION BY clause without depname: EXPLAIN (COSTS OFF) @@ -3796,18 +3804,20 @@ SELECT * FROM min(salary) OVER (PARTITION BY depname) depminsalary FROM empsalary) emp WHERE depname = 'sales'; - QUERY PLAN -------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------- Subquery Scan on emp Filter: ((emp.depname)::text = 'sales'::text) -> WindowAgg + Window: w2 AS (PARTITION BY empsalary.enroll_date) -> Sort Sort Key: empsalary.enroll_date -> WindowAgg + Window: w1 AS (PARTITION BY empsalary.depname) -> Sort Sort Key: empsalary.depname -> Seq Scan on empsalary -(9 rows) +(11 rows) -- Test window function run conditions are properly pushed down into the -- WindowAgg @@ -3817,14 +3827,15 @@ SELECT * FROM row_number() OVER (ORDER BY empno) rn FROM empsalary) emp WHERE rn < 3; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------- WindowAgg - Run Condition: (row_number() OVER (?) < 3) + Window: w1 AS (ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING) + Run Condition: (row_number() OVER w1 < 3) -> Sort Sort Key: empsalary.empno -> Seq Scan on empsalary -(5 rows) +(6 rows) -- The following 3 statements should result the same result. SELECT * FROM @@ -3868,14 +3879,15 @@ SELECT * FROM rank() OVER (ORDER BY salary DESC) r FROM empsalary) emp WHERE r <= 3; - QUERY PLAN ------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------- WindowAgg - Run Condition: (rank() OVER (?) <= 3) + Window: w1 AS (ORDER BY empsalary.salary ROWS UNBOUNDED PRECEDING) + Run Condition: (rank() OVER w1 <= 3) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(5 rows) +(6 rows) SELECT * FROM (SELECT empno, @@ -3898,16 +3910,17 @@ SELECT * FROM dense_rank() OVER (ORDER BY salary DESC) dr FROM empsalary) emp WHERE dr = 1; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------- Subquery Scan on emp Filter: (emp.dr = 1) -> WindowAgg - Run Condition: (dense_rank() OVER (?) <= 1) + Window: w1 AS (ORDER BY empsalary.salary ROWS UNBOUNDED PRECEDING) + Run Condition: (dense_rank() OVER w1 <= 1) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(7 rows) +(8 rows) SELECT * FROM (SELECT empno, @@ -3928,14 +3941,15 @@ SELECT * FROM count(*) OVER (ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; - QUERY PLAN -------------------------------------------- + QUERY PLAN +--------------------------------------------- WindowAgg - Run Condition: (count(*) OVER (?) <= 3) + Window: w1 AS (ORDER BY empsalary.salary) + Run Condition: (count(*) OVER w1 <= 3) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(5 rows) +(6 rows) SELECT * FROM (SELECT empno, @@ -3957,14 +3971,15 @@ SELECT * FROM count(empno) OVER (ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------- WindowAgg - Run Condition: (count(empsalary.empno) OVER (?) <= 3) + Window: w1 AS (ORDER BY empsalary.salary) + Run Condition: (count(empsalary.empno) OVER w1 <= 3) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(5 rows) +(6 rows) SELECT * FROM (SELECT empno, @@ -3986,14 +4001,15 @@ SELECT * FROM count(*) OVER (ORDER BY salary DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) c FROM empsalary) emp WHERE c >= 3; - QUERY PLAN -------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------- WindowAgg - Run Condition: (count(*) OVER (?) >= 3) + Window: w1 AS (ORDER BY empsalary.salary ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + Run Condition: (count(*) OVER w1 >= 3) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(5 rows) +(6 rows) EXPLAIN (COSTS OFF) SELECT * FROM @@ -4002,12 +4018,13 @@ SELECT * FROM count(*) OVER () c FROM empsalary) emp WHERE 11 <= c; - QUERY PLAN --------------------------------------------- + QUERY PLAN +------------------------------------------- WindowAgg - Run Condition: (11 <= count(*) OVER (?)) + Window: w1 AS () + Run Condition: (11 <= count(*) OVER w1) -> Seq Scan on empsalary -(3 rows) +(4 rows) EXPLAIN (COSTS OFF) SELECT * FROM @@ -4017,16 +4034,17 @@ SELECT * FROM dense_rank() OVER (ORDER BY salary DESC) dr FROM empsalary) emp WHERE dr = 1; - QUERY PLAN ------------------------------------------------------ + QUERY PLAN +---------------------------------------------------- Subquery Scan on emp Filter: (emp.dr = 1) -> WindowAgg - Run Condition: (dense_rank() OVER (?) <= 1) + Window: w1 AS (ORDER BY empsalary.salary) + Run Condition: (dense_rank() OVER w1 <= 1) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(7 rows) +(8 rows) -- Ensure we get a run condition when there's a PARTITION BY clause EXPLAIN (COSTS OFF) @@ -4036,14 +4054,15 @@ SELECT * FROM row_number() OVER (PARTITION BY depname ORDER BY empno) rn FROM empsalary) emp WHERE rn < 3; - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------- WindowAgg - Run Condition: (row_number() OVER (?) < 3) + Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING) + Run Condition: (row_number() OVER w1 < 3) -> Sort Sort Key: empsalary.depname, empsalary.empno -> Seq Scan on empsalary -(5 rows) +(6 rows) -- and ensure we get the correct results from the above plan SELECT * FROM @@ -4071,15 +4090,16 @@ SELECT empno, depname FROM row_number() OVER (PARTITION BY depname ORDER BY empno) rn FROM empsalary) emp WHERE rn < 3; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------- Subquery Scan on emp -> WindowAgg - Run Condition: (row_number() OVER (?) < 3) + Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING) + Run Condition: (row_number() OVER w1 < 3) -> Sort Sort Key: empsalary.depname, empsalary.empno -> Seq Scan on empsalary -(6 rows) +(7 rows) -- likewise with count(empno) instead of row_number() EXPLAIN (COSTS OFF) @@ -4090,14 +4110,15 @@ SELECT * FROM count(empno) OVER (PARTITION BY depname ORDER BY salary DESC) c FROM empsalary) emp WHERE c <= 3; - QUERY PLAN ------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------- WindowAgg - Run Condition: (count(empsalary.empno) OVER (?) <= 3) + Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.salary) + Run Condition: (count(empsalary.empno) OVER w1 <= 3) -> Sort Sort Key: empsalary.depname, empsalary.salary DESC -> Seq Scan on empsalary -(5 rows) +(6 rows) -- and again, check the results are what we expect. SELECT * FROM @@ -4129,12 +4150,23 @@ SELECT * FROM count(empno) OVER () c FROM empsalary) emp WHERE c = 1; - QUERY PLAN --------------------------------------------------------- + QUERY PLAN +------------------------------------------------------- WindowAgg - Run Condition: (count(empsalary.empno) OVER (?) = 1) + Window: w1 AS () + Run Condition: (count(empsalary.empno) OVER w1 = 1) -> Seq Scan on empsalary -(3 rows) +(4 rows) + +-- Try another case with a WindowFunc with a byref return type +SELECT * FROM + (SELECT row_number() OVER (PARTITION BY salary) AS rn, + lead(depname) OVER (PARTITION BY salary) || ' Department' AS n_dep + FROM empsalary) emp +WHERE rn < 1; + rn | n_dep +----+------- +(0 rows) -- Some more complex cases with multiple window clauses EXPLAIN (COSTS OFF) @@ -4147,23 +4179,26 @@ SELECT * FROM ntile(2) OVER (PARTITION BY depname) nt -- w2 FROM empsalary ) e WHERE rn <= 1 AND c1 <= 3 AND nt < 2; - QUERY PLAN ------------------------------------------------------------------------------------------------ + QUERY PLAN +-------------------------------------------------------------------------------------------------------- Subquery Scan on e -> WindowAgg - Filter: (((row_number() OVER (?)) <= 1) AND ((ntile(2) OVER (?)) < 2)) - Run Condition: (count(empsalary.salary) OVER (?) <= 3) + Window: w3 AS (PARTITION BY (((empsalary.depname)::text || ''::text))) + Run Condition: (count(empsalary.salary) OVER w3 <= 3) + Filter: (((row_number() OVER w2) <= 1) AND ((ntile(2) OVER w2) < 2)) -> Sort Sort Key: (((empsalary.depname)::text || ''::text)) -> WindowAgg - Run Condition: ((row_number() OVER (?) <= 1) AND (ntile(2) OVER (?) < 2)) + Window: w2 AS (PARTITION BY empsalary.depname) + Run Condition: ((row_number() OVER w2 <= 1) AND (ntile(2) OVER w2 < 2)) -> Sort Sort Key: empsalary.depname -> WindowAgg + Window: w1 AS (PARTITION BY ((''::text || (empsalary.depname)::text))) -> Sort Sort Key: ((''::text || (empsalary.depname)::text)) -> Seq Scan on empsalary -(14 rows) +(17 rows) -- Ensure we correctly filter out all of the run conditions from each window SELECT * FROM @@ -4189,12 +4224,13 @@ SELECT 1 FROM FROM empsalary e1 LEFT JOIN empsalary e2 ON TRUE WHERE e1.empno = e2.empno) s WHERE s.c = 1; - QUERY PLAN ---------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------- Subquery Scan on s Filter: (s.c = 1) -> WindowAgg - Run Condition: (ntile(e2.salary) OVER (?) <= 1) + Window: w1 AS (PARTITION BY e1.depname ROWS UNBOUNDED PRECEDING) + Run Condition: (ntile(e2.salary) OVER w1 <= 1) -> Sort Sort Key: e1.depname -> Merge Join @@ -4205,7 +4241,7 @@ WHERE s.c = 1; -> Sort Sort Key: e2.empno -> Seq Scan on empsalary e2 -(14 rows) +(15 rows) -- Ensure the run condition optimization is used in cases where the WindowFunc -- has a Var from another query level @@ -4214,16 +4250,17 @@ SELECT 1 FROM (SELECT ntile(s1.x) OVER () AS c FROM (SELECT (SELECT 1) AS x) AS s1) s WHERE s.c = 1; - QUERY PLAN ------------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------- Subquery Scan on s Filter: (s.c = 1) -> WindowAgg - Run Condition: (ntile((InitPlan 1).col1) OVER (?) <= 1) + Window: w1 AS (ROWS UNBOUNDED PRECEDING) + Run Condition: (ntile((InitPlan 1).col1) OVER w1 <= 1) InitPlan 1 -> Result -> Result -(7 rows) +(8 rows) -- Tests to ensure we don't push down the run condition when it's not valid to -- do so. @@ -4236,15 +4273,16 @@ SELECT * FROM count(*) OVER (ORDER BY salary DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) c FROM empsalary) emp WHERE c <= 3; - QUERY PLAN ------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------------------------------- Subquery Scan on emp Filter: (emp.c <= 3) -> WindowAgg + Window: w1 AS (ORDER BY empsalary.salary ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) -> Sort Sort Key: empsalary.salary DESC -> Seq Scan on empsalary -(6 rows) +(7 rows) -- Ensure we don't push down when the window function's monotonic properties -- don't match that of the clauses. @@ -4255,15 +4293,16 @@ SELECT * FROM count(*) OVER (ORDER BY salary) c FROM empsalary) emp WHERE 3 <= c; - QUERY PLAN ------------------------------------------- + QUERY PLAN +--------------------------------------------------- Subquery Scan on emp Filter: (3 <= emp.c) -> WindowAgg + Window: w1 AS (ORDER BY empsalary.salary) -> Sort Sort Key: empsalary.salary -> Seq Scan on empsalary -(6 rows) +(7 rows) -- Ensure we don't use a run condition when there's a volatile function in the -- WindowFunc @@ -4274,15 +4313,16 @@ SELECT * FROM count(random()) OVER (ORDER BY empno DESC) c FROM empsalary) emp WHERE c = 1; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +-------------------------------------------------- Subquery Scan on emp Filter: (emp.c = 1) -> WindowAgg + Window: w1 AS (ORDER BY empsalary.empno) -> Sort Sort Key: empsalary.empno DESC -> Seq Scan on empsalary -(6 rows) +(7 rows) -- Ensure we don't use a run condition when the WindowFunc contains subplans EXPLAIN (COSTS OFF) @@ -4292,17 +4332,18 @@ SELECT * FROM count((SELECT 1)) OVER (ORDER BY empno DESC) c FROM empsalary) emp WHERE c = 1; - QUERY PLAN ----------------------------------------------- + QUERY PLAN +-------------------------------------------------- Subquery Scan on emp Filter: (emp.c = 1) -> WindowAgg + Window: w1 AS (ORDER BY empsalary.empno) InitPlan 1 -> Result -> Sort Sort Key: empsalary.empno DESC -> Seq Scan on empsalary -(8 rows) +(9 rows) -- Test Sort node collapsing EXPLAIN (COSTS OFF) @@ -4312,16 +4353,18 @@ SELECT * FROM min(salary) OVER (PARTITION BY depname, empno order by enroll_date) depminsalary FROM empsalary) emp WHERE depname = 'sales'; - QUERY PLAN ----------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------- Subquery Scan on emp -> WindowAgg + Window: w2 AS (ORDER BY empsalary.empno) -> WindowAgg + Window: w1 AS (PARTITION BY empsalary.empno ORDER BY empsalary.enroll_date) -> Sort Sort Key: empsalary.empno, empsalary.enroll_date -> Seq Scan on empsalary Filter: ((depname)::text = 'sales'::text) -(7 rows) +(9 rows) -- Ensure that the evaluation order of the WindowAggs results in the WindowAgg -- with the same sort order that's required by the ORDER BY is evaluated last. @@ -4333,17 +4376,19 @@ SELECT empno, min(salary) OVER (PARTITION BY depname order by enroll_date) depminsalary FROM empsalary ORDER BY depname, empno; - QUERY PLAN ----------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------- WindowAgg + Window: w2 AS (PARTITION BY depname ORDER BY empno) -> Incremental Sort Sort Key: depname, empno Presorted Key: depname -> WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY enroll_date) -> Sort Sort Key: depname, enroll_date -> Seq Scan on empsalary -(8 rows) +(10 rows) -- As above, but with an adjusted ORDER BY to ensure the above plan didn't -- perform only 2 sorts by accident. @@ -4355,17 +4400,19 @@ SELECT empno, min(salary) OVER (PARTITION BY depname order by enroll_date) depminsalary FROM empsalary ORDER BY depname, enroll_date; - QUERY PLAN ------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------- WindowAgg + Window: w2 AS (PARTITION BY depname ORDER BY enroll_date) -> Incremental Sort Sort Key: depname, enroll_date Presorted Key: depname -> WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY empno) -> Sort Sort Key: depname, empno -> Seq Scan on empsalary -(8 rows) +(10 rows) SET enable_hashagg TO off; -- Ensure we don't get a sort for both DISTINCT and ORDER BY. We expect the @@ -4379,21 +4426,23 @@ SELECT DISTINCT min(salary) OVER (PARTITION BY depname order by enroll_date) depminsalary FROM empsalary ORDER BY depname, enroll_date; - QUERY PLAN ------------------------------------------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------------------------------------------- Unique -> Incremental Sort - Sort Key: depname, enroll_date, empno, (sum(salary) OVER (?)), (min(salary) OVER (?)) + Sort Key: depname, enroll_date, empno, (sum(salary) OVER w1), (min(salary) OVER w2) Presorted Key: depname, enroll_date -> WindowAgg + Window: w2 AS (PARTITION BY depname ORDER BY enroll_date) -> Incremental Sort Sort Key: depname, enroll_date Presorted Key: depname -> WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY empno) -> Sort Sort Key: depname, empno -> Seq Scan on empsalary -(12 rows) +(14 rows) -- As above but adjust the ORDER BY clause to help ensure the plan with the -- minimum amount of sorting wasn't a fluke. @@ -4406,21 +4455,23 @@ SELECT DISTINCT min(salary) OVER (PARTITION BY depname order by enroll_date) depminsalary FROM empsalary ORDER BY depname, empno; - QUERY PLAN ------------------------------------------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------------------------------------------- Unique -> Incremental Sort - Sort Key: depname, empno, enroll_date, (sum(salary) OVER (?)), (min(salary) OVER (?)) + Sort Key: depname, empno, enroll_date, (sum(salary) OVER w2), (min(salary) OVER w1) Presorted Key: depname, empno -> WindowAgg + Window: w2 AS (PARTITION BY depname ORDER BY empno) -> Incremental Sort Sort Key: depname, empno Presorted Key: depname -> WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY enroll_date) -> Sort Sort Key: depname, enroll_date -> Seq Scan on empsalary -(12 rows) +(14 rows) RESET enable_hashagg; -- Test Sort node reordering @@ -4429,14 +4480,16 @@ SELECT lead(1) OVER (PARTITION BY depname ORDER BY salary, enroll_date), lag(1) OVER (PARTITION BY depname ORDER BY salary,enroll_date,empno) FROM empsalary; - QUERY PLAN -------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------- WindowAgg + Window: w2 AS (PARTITION BY depname ORDER BY salary, enroll_date) -> WindowAgg + Window: w1 AS (PARTITION BY depname ORDER BY salary, enroll_date, empno) -> Sort Sort Key: depname, salary, enroll_date, empno -> Seq Scan on empsalary -(5 rows) +(7 rows) -- Test incremental sorting EXPLAIN (COSTS OFF) @@ -4449,19 +4502,21 @@ SELECT * FROM row_number() OVER (PARTITION BY depname ORDER BY enroll_date DESC) AS last_emp FROM empsalary) emp WHERE first_emp = 1 OR last_emp = 1; - QUERY PLAN ------------------------------------------------------------------------------------ + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- Subquery Scan on emp Filter: ((emp.first_emp = 1) OR (emp.last_emp = 1)) -> WindowAgg + Window: w2 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING) -> Incremental Sort Sort Key: empsalary.depname, empsalary.enroll_date Presorted Key: empsalary.depname -> WindowAgg + Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING) -> Sort Sort Key: empsalary.depname, empsalary.enroll_date DESC -> Seq Scan on empsalary -(10 rows) +(12 rows) SELECT * FROM (SELECT depname, @@ -5289,11 +5344,12 @@ LIMIT 1; -------------------------------------------------------------------------- Limit -> WindowAgg + Window: w1 AS (ORDER BY t1.unique1) -> Nested Loop -> Index Only Scan using tenk1_unique1 on tenk1 t1 -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 Index Cond: (tenthous = t1.unique1) -(6 rows) +(7 rows) -- Ensure we get a cheap total plan. Lack of ORDER BY in the WindowClause -- means that all rows must be read from the join, so a cheap startup plan @@ -5307,13 +5363,14 @@ LIMIT 1; ------------------------------------------------------------------- Limit -> WindowAgg + Window: w1 AS () -> Hash Join Hash Cond: (t1.unique1 = t2.tenthous) -> Index Only Scan using tenk1_unique1 on tenk1 t1 -> Hash -> Seq Scan on tenk1 t2 Filter: (two = 1) -(8 rows) +(9 rows) -- Ensure we get a cheap total plan. This time use UNBOUNDED FOLLOWING, which -- needs to read all join rows to output the first WindowAgg row. @@ -5321,17 +5378,18 @@ EXPLAIN (COSTS OFF) SELECT COUNT(*) OVER (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous LIMIT 1; - QUERY PLAN --------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------ Limit -> WindowAgg + Window: w1 AS (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) -> Merge Join Merge Cond: (t1.unique1 = t2.tenthous) -> Index Only Scan using tenk1_unique1 on tenk1 t1 -> Sort Sort Key: t2.tenthous -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 -(8 rows) +(9 rows) -- Ensure we get a cheap total plan. This time use 10000 FOLLOWING so we need -- to read all join rows. @@ -5339,17 +5397,18 @@ EXPLAIN (COSTS OFF) SELECT COUNT(*) OVER (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND 10000 FOLLOWING) FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous LIMIT 1; - QUERY PLAN --------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------ Limit -> WindowAgg + Window: w1 AS (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND '10000'::bigint FOLLOWING) -> Merge Join Merge Cond: (t1.unique1 = t2.tenthous) -> Index Only Scan using tenk1_unique1 on tenk1 t1 -> Sort Sort Key: t2.tenthous -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 -(8 rows) +(9 rows) -- Tests for problems with failure to walk or mutate expressions -- within window frame clauses. @@ -5374,14 +5433,15 @@ AS $$ WINDOW w AS (ORDER BY s ROWS BETWEEN CURRENT ROW AND GROUP_SIZE FOLLOWING) $$ LANGUAGE SQL STABLE; EXPLAIN (costs off) SELECT * FROM pg_temp.f(2); - QUERY PLAN ------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------- Subquery Scan on f -> WindowAgg + Window: w AS (ORDER BY s.s ROWS BETWEEN CURRENT ROW AND '2'::bigint FOLLOWING) -> Sort Sort Key: s.s -> Function Scan on generate_series s -(5 rows) +(6 rows) SELECT * FROM pg_temp.f(2); f diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out index 08cfa5463fbcc..26c8850514007 100644 --- a/src/test/regress/expected/with.out +++ b/src/test/regress/expected/with.out @@ -329,6 +329,26 @@ SELECT * FROM subdepartment ORDER BY name; 1 | 0 | A (1 row) +-- exercise the deduplication code of a UNION with mixed input slot types +WITH RECURSIVE subdepartment AS +( + -- select all columns to prevent projection + SELECT id, parent_department, name FROM department WHERE name = 'A' + UNION + -- joins do projection + SELECT d.id, d.parent_department, d.name FROM department AS d + INNER JOIN subdepartment AS sd ON d.parent_department = sd.id +) +SELECT * FROM subdepartment ORDER BY name; + id | parent_department | name +----+-------------------+------ + 1 | 0 | A + 2 | 1 | B + 3 | 2 | C + 4 | 2 | D + 6 | 4 | F +(5 rows) + -- inside subqueries SELECT count(*) FROM ( WITH RECURSIVE t(n) AS ( @@ -636,6 +656,21 @@ SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON 16 | {3,7,11,16} | (16,"{3,7,11,16}") (16 rows) +CREATE TEMP TABLE duplicates (a INT NOT NULL); +INSERT INTO duplicates VALUES(1), (1); +-- Try out a recursive UNION case where the non-recursive part's table slot +-- uses TTSOpsBufferHeapTuple and contains duplicate rows. +WITH RECURSIVE cte (a) as ( + SELECT a FROM duplicates + UNION + SELECT a FROM cte +) +SELECT a FROM cte; + a +--- + 1 +(1 row) + -- test that column statistics from a materialized CTE are available -- to upper planner (otherwise, we'd get a stupider plan) explain (costs off) @@ -2069,6 +2104,14 @@ WITH RECURSIVE x(n) AS ( ERROR: ORDER BY in a recursive query is not implemented LINE 3: ORDER BY (SELECT n FROM x)) ^ +-- and this +WITH RECURSIVE x(n) AS ( + WITH sub_cte AS (SELECT * FROM x) + DELETE FROM graph RETURNING f) + SELECT * FROM x; +ERROR: recursive query "x" must not contain data-modifying statements +LINE 1: WITH RECURSIVE x(n) AS ( + ^ CREATE TEMPORARY TABLE y (a INTEGER); INSERT INTO y SELECT generate_series(1, 10); -- LEFT JOIN diff --git a/src/test/regress/expected/without_overlaps.out b/src/test/regress/expected/without_overlaps.out new file mode 100644 index 0000000000000..ea607bed0a412 --- /dev/null +++ b/src/test/regress/expected/without_overlaps.out @@ -0,0 +1,2500 @@ +-- Tests for WITHOUT OVERLAPS. +-- +-- We leave behind several tables to test pg_dump etc: +-- temporal_rng, temporal_rng2, +-- temporal_fk_rng2rng. +SET datestyle TO ISO, YMD; +-- +-- test input parser +-- +-- PK with no columns just WITHOUT OVERLAPS: +CREATE TABLE temporal_rng ( + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (valid_at WITHOUT OVERLAPS) +); +ERROR: constraint using WITHOUT OVERLAPS needs at least two columns +-- PK with a range column/PERIOD that isn't there: +CREATE TABLE temporal_rng ( + id INTEGER, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ERROR: column "valid_at" named in key does not exist +LINE 3: CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHO... + ^ +-- PK with a non-range column: +CREATE TABLE temporal_rng ( + id int4range, + valid_at TEXT, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ERROR: column "valid_at" in WITHOUT OVERLAPS is not a range or multirange type +LINE 4: CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHO... + ^ +-- PK with one column plus a range: +CREATE TABLE temporal_rng ( + -- Since we can't depend on having btree_gist here, + -- use an int4range instead of an int. + -- (The rangetypes regression test uses the same trick.) + id int4range, + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng + Table "public.temporal_rng" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + pg_get_constraintdef +--------------------------------------------- + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + pg_get_indexdef +------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_rng_pk ON temporal_rng USING gist (id, valid_at) +(1 row) + +-- PK from LIKE: +CREATE TABLE temporal_rng2 (LIKE temporal_rng INCLUDING ALL); +\d temporal_rng2 + Table "public.temporal_rng2" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng2_pkey" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) + +DROP TABLE temporal_rng2; +-- no PK from INHERITS: +CREATE TABLE temporal_rng2 () INHERITS (temporal_rng); +\d temporal_rng2 + Table "public.temporal_rng2" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Inherits: temporal_rng + +DROP TABLE temporal_rng2; +DROP TABLE temporal_rng; +-- PK in inheriting table: +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +CREATE TABLE temporal_rng2 ( + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) INHERITS (temporal_rng); +\d temporal_rng2 + Table "public.temporal_rng2" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Inherits: temporal_rng + +DROP TABLE temporal_rng CASCADE; +NOTICE: drop cascades to table temporal_rng2 +-- Add PK to already inheriting table: +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +CREATE TABLE temporal_rng2 () INHERITS (temporal_rng); +ALTER TABLE temporal_rng2 + ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +\d temporal_rng2 + Table "public.temporal_rng2" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Inherits: temporal_rng + +DROP TABLE temporal_rng2; +DROP TABLE temporal_rng; +-- PK with two columns plus a range: +CREATE TABLE temporal_rng2 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng2 + Table "public.temporal_rng2" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id1 | int4range | | not null | + id2 | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng2_pk" PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng2_pk'; + pg_get_constraintdef +--------------------------------------------------- + PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng2_pk'; + pg_get_indexdef +--------------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_rng2_pk ON temporal_rng2 USING gist (id1, id2, valid_at) +(1 row) + +-- PK with a custom range type: +CREATE TYPE textrange2 AS range (subtype=text, collation="C"); +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at textrange2, + CONSTRAINT temporal_rng3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_pk; +DROP TABLE temporal_rng3; +DROP TYPE textrange2; +-- PK with one column plus a multirange: +CREATE TABLE temporal_mltrng ( + id int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_mltrng + Table "public.temporal_mltrng" + Column | Type | Collation | Nullable | Default +----------+----------------+-----------+----------+--------- + id | int4range | | not null | + valid_at | datemultirange | | not null | +Indexes: + "temporal_mltrng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk'; + pg_get_constraintdef +--------------------------------------------- + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk'; + pg_get_indexdef +------------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_mltrng_pk ON temporal_mltrng USING gist (id, valid_at) +(1 row) + +-- PK with two columns plus a multirange: +CREATE TABLE temporal_mltrng2 ( + id1 int4range, + id2 int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_mltrng2 + Table "public.temporal_mltrng2" + Column | Type | Collation | Nullable | Default +----------+----------------+-----------+----------+--------- + id1 | int4range | | not null | + id2 | int4range | | not null | + valid_at | datemultirange | | not null | +Indexes: + "temporal_mltrng2_pk" PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk'; + pg_get_constraintdef +--------------------------------------------------- + PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk'; + pg_get_indexdef +--------------------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_mltrng2_pk ON temporal_mltrng2 USING gist (id1, id2, valid_at) +(1 row) + +-- UNIQUE with no columns just WITHOUT OVERLAPS: +CREATE TABLE temporal_rng3 ( + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (valid_at WITHOUT OVERLAPS) +); +ERROR: constraint using WITHOUT OVERLAPS needs at least two columns +-- UNIQUE with a range column/PERIOD that isn't there: +CREATE TABLE temporal_rng3 ( + id INTEGER, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +ERROR: column "valid_at" named in key does not exist +LINE 3: CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT O... + ^ +-- UNIQUE with a non-range column: +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at TEXT, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +ERROR: column "valid_at" in WITHOUT OVERLAPS is not a range or multirange type +LINE 4: CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT O... + ^ +-- UNIQUE with one column plus a range: +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng3 + Table "public.temporal_rng3" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | | + valid_at | daterange | | | +Indexes: + "temporal_rng3_uq" UNIQUE (id, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; + pg_get_constraintdef +---------------------------------------- + UNIQUE (id, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; + pg_get_indexdef +--------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_rng3_uq ON temporal_rng3 USING gist (id, valid_at) +(1 row) + +DROP TABLE temporal_rng3; +-- UNIQUE with two columns plus a range: +CREATE TABLE temporal_rng3 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng3 + Table "public.temporal_rng3" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id1 | int4range | | | + id2 | int4range | | | + valid_at | daterange | | | +Indexes: + "temporal_rng3_uq" UNIQUE (id1, id2, valid_at WITHOUT OVERLAPS) + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; + pg_get_constraintdef +---------------------------------------------- + UNIQUE (id1, id2, valid_at WITHOUT OVERLAPS) +(1 row) + +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; + pg_get_indexdef +--------------------------------------------------------------------------------------- + CREATE UNIQUE INDEX temporal_rng3_uq ON temporal_rng3 USING gist (id1, id2, valid_at) +(1 row) + +DROP TABLE temporal_rng3; +-- UNIQUE with a custom range type: +CREATE TYPE textrange2 AS range (subtype=text, collation="C"); +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at textrange2, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq; +DROP TABLE temporal_rng3; +DROP TYPE textrange2; +-- +-- test ALTER TABLE ADD CONSTRAINT +-- +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +ALTER TABLE temporal_rng + ADD CONSTRAINT temporal_rng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +-- PK with USING INDEX (not possible): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE INDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_pk + PRIMARY KEY USING INDEX idx_temporal3_uq; +ERROR: "idx_temporal3_uq" is not a unique index +LINE 2: ADD CONSTRAINT temporal3_pk + ^ +DETAIL: Cannot create a primary key or unique constraint using such an index. +DROP TABLE temporal3; +-- UNIQUE with USING INDEX (not possible): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE INDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_uq + UNIQUE USING INDEX idx_temporal3_uq; +ERROR: "idx_temporal3_uq" is not a unique index +LINE 2: ADD CONSTRAINT temporal3_uq + ^ +DETAIL: Cannot create a primary key or unique constraint using such an index. +DROP TABLE temporal3; +-- UNIQUE with USING [UNIQUE] INDEX (possible but not a temporal constraint): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE UNIQUE INDEX idx_temporal3_uq ON temporal3 (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_uq + UNIQUE USING INDEX idx_temporal3_uq; +NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "idx_temporal3_uq" to "temporal3_uq" +DROP TABLE temporal3; +-- Add range column and the PK at the same time +CREATE TABLE temporal3 ( + id int4range +); +ALTER TABLE temporal3 + ADD COLUMN valid_at daterange, + ADD CONSTRAINT temporal3_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DROP TABLE temporal3; +-- Add range column and UNIQUE constraint at the same time +CREATE TABLE temporal3 ( + id int4range +); +ALTER TABLE temporal3 + ADD COLUMN valid_at daterange, + ADD CONSTRAINT temporal3_uq + UNIQUE (id, valid_at WITHOUT OVERLAPS); +DROP TABLE temporal3; +-- +-- range PK: test with existing rows +-- +ALTER TABLE temporal_rng DROP CONSTRAINT temporal_rng_pk; +-- okay: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_rng DROP CONSTRAINT temporal_rng_pk; +-- should fail: +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); + ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ERROR: could not create exclusion constraint "temporal_rng_pk" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-02,2018-02-03)) conflicts with key (id, valid_at)=([1,2), [2018-01-01,2018-01-05)). +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', 'empty'); + ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng" +ROLLBACK; +ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_rng; +-- +-- range PK: test inserts +-- +-- okay: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +-- should fail: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); +ERROR: conflicting key value violates exclusion constraint "temporal_rng_pk" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-01,2018-01-05)) conflicts with existing key (id, valid_at)=([1,2), [2018-01-02,2018-02-03)). +INSERT INTO temporal_rng (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +ERROR: null value in column "id" of relation "temporal_rng" violates not-null constraint +DETAIL: Failing row contains (null, [2018-01-01,2018-01-05)). +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', NULL); +ERROR: null value in column "valid_at" of relation "temporal_rng" violates not-null constraint +DETAIL: Failing row contains ([3,4), null). +-- rejects empty: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', 'empty'); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng" +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2018-01-02,2018-02-03) + [1,2) | [2018-03-03,2018-04-04) + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) +(4 rows) + +-- +-- range PK: test updates +-- +-- update the scalar part +UPDATE temporal_rng +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the range part +UPDATE temporal_rng +SET valid_at = '[2020-01-01,2021-01-01)' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_rng +SET id = '[21,22)', + valid_at = '[2018-01-02,2018-02-03)' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +---------+------------------------- + [1,2) | [2018-03-03,2018-04-04) + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) + [21,22) | [2018-01-02,2018-02-03) +(4 rows) + +-- should fail: +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = daterange('2018-03-05', '2018-05-05') +WHERE id = '[21,22)'; +ERROR: conflicting key value violates exclusion constraint "temporal_rng_pk" +DETAIL: Key (id, valid_at)=([1,2), [2018-03-05,2018-05-05)) conflicts with existing key (id, valid_at)=([1,2), [2018-03-03,2018-04-04)). +-- set the scalar part to NULL +UPDATE temporal_rng +SET id = NULL, + valid_at = daterange('2018-03-05', '2018-05-05') +WHERE id = '[21,22)'; +ERROR: null value in column "id" of relation "temporal_rng" violates not-null constraint +DETAIL: Failing row contains (null, [2018-03-05,2018-05-05)). +-- set the range part to NULL +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = NULL +WHERE id = '[21,22)'; +ERROR: null value in column "valid_at" of relation "temporal_rng" violates not-null constraint +DETAIL: Failing row contains ([1,2), null). +-- rejects empty: +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = 'empty' +WHERE id = '[21,22)'; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng" +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +---------+------------------------- + [1,2) | [2018-03-03,2018-04-04) + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) + [21,22) | [2018-01-02,2018-02-03) +(4 rows) + +-- +-- range UQ: test with existing rows +-- +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at daterange +); +-- okay: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +INSERT INTO temporal_rng3 (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', NULL); +ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq; +-- should fail: +BEGIN; + INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); + ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ERROR: could not create exclusion constraint "temporal_rng3_uq" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-02,2018-02-03)) conflicts with key (id, valid_at)=([1,2), [2018-01-01,2018-01-05)). +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', 'empty'); + ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng3" +ROLLBACK; +ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_rng3; +-- +-- range UQ: test inserts +-- +-- okay: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +INSERT INTO temporal_rng3 (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', NULL); +-- should fail: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); +ERROR: conflicting key value violates exclusion constraint "temporal_rng3_uq" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-01,2018-01-05)) conflicts with existing key (id, valid_at)=([1,2), [2018-01-02,2018-02-03)). +-- rejects empty: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', 'empty'); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng3" +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2018-01-02,2018-02-03) + [1,2) | [2018-03-03,2018-04-04) + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) + [3,4) | + | [2018-01-01,2018-01-05) +(6 rows) + +-- +-- range UQ: test updates +-- +-- update the scalar part +UPDATE temporal_rng3 +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the range part +UPDATE temporal_rng3 +SET valid_at = '[2020-01-01,2021-01-01)' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_rng3 +SET id = '[21,22)', + valid_at = '[2018-01-02,2018-02-03)' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +-- set the scalar part to NULL +UPDATE temporal_rng3 +SET id = NULL, + valid_at = daterange('2020-01-01', '2021-01-01') +WHERE id = '[21,22)'; +-- set the range part to NULL +UPDATE temporal_rng3 +SET id = '[1,2)', + valid_at = NULL +WHERE id IS NULL AND valid_at @> '2020-06-01'::date; +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2018-03-03,2018-04-04) + [1,2) | + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) + [3,4) | + | [2018-01-01,2018-01-05) +(6 rows) + +-- should fail: +UPDATE temporal_rng3 +SET valid_at = daterange('2018-03-01', '2018-05-05') +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: conflicting key value violates exclusion constraint "temporal_rng3_uq" +DETAIL: Key (id, valid_at)=([1,2), [2018-03-01,2018-05-05)) conflicts with existing key (id, valid_at)=([1,2), [2018-03-03,2018-04-04)). +-- rejects empty: +UPDATE temporal_rng3 +SET valid_at = 'empty' +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng3" +-- still rejects empty when scalar part is NULL: +UPDATE temporal_rng3 +SET id = NULL, + valid_at = 'empty' +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_rng3" +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2018-03-03,2018-04-04) + [1,2) | + [2,3) | [2018-01-01,2018-01-05) + [3,4) | [2018-01-01,) + [3,4) | + | [2018-01-01,2018-01-05) +(6 rows) + +DROP TABLE temporal_rng3; +-- +-- multirange PK: test with existing rows +-- +ALTER TABLE temporal_mltrng DROP CONSTRAINT temporal_mltrng_pk; +-- okay: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_mltrng DROP CONSTRAINT temporal_mltrng_pk; +-- should fail: +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); + ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ERROR: could not create exclusion constraint "temporal_mltrng_pk" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-02,2018-02-03)}) conflicts with key (id, valid_at)=([1,2), {[2018-01-01,2018-01-05)}). +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', '{}'); + ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng" +ROLLBACK; +ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_mltrng; +-- +-- multirange PK: test inserts +-- +-- okay: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +-- should fail: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +ERROR: conflicting key value violates exclusion constraint "temporal_mltrng_pk" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-01,2018-01-05)}) conflicts with existing key (id, valid_at)=([1,2), {[2018-01-02,2018-02-03)}). +INSERT INTO temporal_mltrng (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +ERROR: null value in column "id" of relation "temporal_mltrng" violates not-null constraint +DETAIL: Failing row contains (null, {[2018-01-01,2018-01-05)}). +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', NULL); +ERROR: null value in column "valid_at" of relation "temporal_mltrng" violates not-null constraint +DETAIL: Failing row contains ([3,4), null). +-- rejects empty: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', '{}'); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng" +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2018-01-02,2018-02-03)} + [1,2) | {[2018-03-03,2018-04-04)} + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} +(4 rows) + +-- +-- multirange PK: test updates +-- +-- update the scalar part +UPDATE temporal_mltrng +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the multirange part +UPDATE temporal_mltrng +SET valid_at = '{[2020-01-01,2021-01-01)}' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_mltrng +SET id = '[21,22)', + valid_at = '{[2018-01-02,2018-02-03)}' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +---------+--------------------------- + [1,2) | {[2018-03-03,2018-04-04)} + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} + [21,22) | {[2018-01-02,2018-02-03)} +(4 rows) + +-- should fail: +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) +WHERE id = '[21,22)'; +ERROR: conflicting key value violates exclusion constraint "temporal_mltrng_pk" +DETAIL: Key (id, valid_at)=([1,2), {[2018-03-05,2018-05-05)}) conflicts with existing key (id, valid_at)=([1,2), {[2018-03-03,2018-04-04)}). +-- set the scalar part to NULL +UPDATE temporal_mltrng +SET id = NULL, + valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) +WHERE id = '[21,22)'; +ERROR: null value in column "id" of relation "temporal_mltrng" violates not-null constraint +DETAIL: Failing row contains (null, {[2018-03-05,2018-05-05)}). +-- set the multirange part to NULL +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = NULL +WHERE id = '[21,22)'; +ERROR: null value in column "valid_at" of relation "temporal_mltrng" violates not-null constraint +DETAIL: Failing row contains ([1,2), null). +-- rejects empty: +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = '{}' +WHERE id = '[21,22)'; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng" +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +---------+--------------------------- + [1,2) | {[2018-03-03,2018-04-04)} + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} + [21,22) | {[2018-01-02,2018-02-03)} +(4 rows) + +-- +-- multirange UQ: test with existing rows +-- +CREATE TABLE temporal_mltrng3 ( + id int4range, + valid_at datemultirange +); +-- okay: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', NULL); +ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_mltrng3 DROP CONSTRAINT temporal_mltrng3_uq; +-- should fail: +BEGIN; + INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); + ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ERROR: could not create exclusion constraint "temporal_mltrng3_uq" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-02,2018-02-03)}) conflicts with key (id, valid_at)=([1,2), {[2018-01-01,2018-01-05)}). +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', '{}'); + ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng3" +ROLLBACK; +ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_mltrng3; +-- +-- multirange UQ: test inserts +-- +-- okay: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', NULL); +-- should fail: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +ERROR: conflicting key value violates exclusion constraint "temporal_mltrng3_uq" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-01,2018-01-05)}) conflicts with existing key (id, valid_at)=([1,2), {[2018-01-02,2018-02-03)}). +-- rejects empty: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', '{}'); +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng3" +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2018-01-02,2018-02-03)} + [1,2) | {[2018-03-03,2018-04-04)} + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} + [3,4) | + | {[2018-01-01,2018-01-05)} +(6 rows) + +-- +-- multirange UQ: test updates +-- +-- update the scalar part +UPDATE temporal_mltrng3 +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the multirange part +UPDATE temporal_mltrng3 +SET valid_at = '{[2020-01-01,2021-01-01)}' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_mltrng3 +SET id = '[21,22)', + valid_at = '{[2018-01-02,2018-02-03)}' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +-- set the scalar part to NULL +UPDATE temporal_mltrng3 +SET id = NULL, + valid_at = datemultirange(daterange('2020-01-01', '2021-01-01')) +WHERE id = '[21,22)'; +-- set the multirange part to NULL +UPDATE temporal_mltrng3 +SET id = '[1,2)', + valid_at = NULL +WHERE id IS NULL AND valid_at @> '2020-06-01'::date; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2018-03-03,2018-04-04)} + [1,2) | + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} + [3,4) | + | {[2018-01-01,2018-01-05)} +(6 rows) + +-- should fail: +UPDATE temporal_mltrng3 +SET valid_at = datemultirange(daterange('2018-03-01', '2018-05-05')) +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: conflicting key value violates exclusion constraint "temporal_mltrng3_uq" +DETAIL: Key (id, valid_at)=([1,2), {[2018-03-01,2018-05-05)}) conflicts with existing key (id, valid_at)=([1,2), {[2018-03-03,2018-04-04)}). +-- rejects empty: +UPDATE temporal_mltrng3 +SET valid_at = '{}' +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng3" +-- still rejects empty when scalar part is NULL: +UPDATE temporal_mltrng3 +SET id = NULL, + valid_at = '{}' +WHERE id = '[1,2)' AND valid_at IS NULL; +ERROR: empty WITHOUT OVERLAPS value found in column "valid_at" in relation "temporal_mltrng3" +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2018-03-03,2018-04-04)} + [1,2) | + [2,3) | {[2018-01-01,2018-01-05)} + [3,4) | {[2018-01-01,)} + [3,4) | + | {[2018-01-01,2018-01-05)} +(6 rows) + +DROP TABLE temporal_mltrng3; +-- +-- test a range with both a PK and a UNIQUE constraint +-- +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + id2 int8range, + name TEXT, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal3_uniq UNIQUE (id2, valid_at WITHOUT OVERLAPS) +); +INSERT INTO temporal3 (id, valid_at, id2, name) + VALUES + ('[1,2)', daterange('2000-01-01', '2010-01-01'), '[7,8)', 'foo'), + ('[2,3)', daterange('2000-01-01', '2010-01-01'), '[9,10)', 'bar') +; +DROP TABLE temporal3; +-- +-- test changing the PK's dependencies +-- +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal3 ALTER COLUMN valid_at DROP NOT NULL; +ERROR: column "valid_at" is in a primary key +ALTER TABLE temporal3 ALTER COLUMN valid_at TYPE tstzrange USING tstzrange(lower(valid_at), upper(valid_at)); +ALTER TABLE temporal3 RENAME COLUMN valid_at TO valid_thru; +ALTER TABLE temporal3 DROP COLUMN valid_thru; +DROP TABLE temporal3; +-- +-- test PARTITION BY for ranges +-- +-- temporal PRIMARY KEY: +CREATE TABLE temporal_partitioned ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned FOR VALUES IN ('[1,2)', '[2,3)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned FOR VALUES IN ('[3,4)', '[4,5)'); +INSERT INTO temporal_partitioned (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[3,4)', daterange('2000-01-01', '2010-01-01'), 'three'); +SELECT * FROM temporal_partitioned ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------- + [1,2) | [2000-01-01,2000-02-01) | one + [1,2) | [2000-02-01,2000-03-01) | one + [3,4) | [2000-01-01,2010-01-01) | three +(3 rows) + +SELECT * FROM tp1 ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------ + [1,2) | [2000-01-01,2000-02-01) | one + [1,2) | [2000-02-01,2000-03-01) | one +(2 rows) + +SELECT * FROM tp2 ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------- + [3,4) | [2000-01-01,2010-01-01) | three +(1 row) + +DROP TABLE temporal_partitioned; +-- temporal UNIQUE: +CREATE TABLE temporal_partitioned ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned FOR VALUES IN ('[1,2)', '[2,3)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned FOR VALUES IN ('[3,4)', '[4,5)'); +INSERT INTO temporal_partitioned (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[3,4)', daterange('2000-01-01', '2010-01-01'), 'three'); +SELECT * FROM temporal_partitioned ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------- + [1,2) | [2000-01-01,2000-02-01) | one + [1,2) | [2000-02-01,2000-03-01) | one + [3,4) | [2000-01-01,2010-01-01) | three +(3 rows) + +SELECT * FROM tp1 ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------ + [1,2) | [2000-01-01,2000-02-01) | one + [1,2) | [2000-02-01,2000-03-01) | one +(2 rows) + +SELECT * FROM tp2 ORDER BY id, valid_at; + id | valid_at | name +-------+-------------------------+------- + [3,4) | [2000-01-01,2010-01-01) | three +(1 row) + +DROP TABLE temporal_partitioned; +-- ALTER TABLE REPLICA IDENTITY +\d temporal_rng + Table "public.temporal_rng" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) + +ALTER TABLE temporal_rng REPLICA IDENTITY USING INDEX temporal_rng_pk; +\d temporal_rng + Table "public.temporal_rng" + Column | Type | Collation | Nullable | Default +----------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | +Indexes: + "temporal_rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) REPLICA IDENTITY + +-- +-- ON CONFLICT: ranges +-- +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) + [1,2) | [2010-01-01,2020-01-01) + [2,3) | [2005-01-01,2006-01-01) +(3 rows) + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) + [1,2) | [2010-01-01,2020-01-01) + [2,3) | [2005-01-01,2006-01-01) +(3 rows) + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +SELECT * FROM temporal_rng ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +-- with a UNIQUE constraint: +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +SELECT * FROM temporal3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) + [1,2) | [2010-01-01,2020-01-01) + [2,3) | [2005-01-01,2006-01-01) +(3 rows) + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +SELECT * FROM temporal3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) + [1,2) | [2010-01-01,2020-01-01) + [2,3) | [2005-01-01,2006-01-01) +(3 rows) + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +SELECT * FROM temporal3 ORDER BY id, valid_at; + id | valid_at +-------+------------------------- + [1,2) | [2000-01-01,2010-01-01) +(1 row) + +DROP TABLE temporal3; +-- +-- ON CONFLICT: multiranges +-- +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} + [1,2) | {[2010-01-01,2020-01-01)} + [2,3) | {[2005-01-01,2006-01-01)} +(3 rows) + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} + [1,2) | {[2010-01-01,2020-01-01)} + [2,3) | {[2005-01-01,2006-01-01)} +(3 rows) + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +-- with a UNIQUE constraint: +CREATE TABLE temporal_mltrng3 ( + id int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} + [1,2) | {[2010-01-01,2020-01-01)} + [2,3) | {[2005-01-01,2006-01-01)} +(3 rows) + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} + [1,2) | {[2010-01-01,2020-01-01)} + [2,3) | {[2005-01-01,2006-01-01)} +(3 rows) + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + id | valid_at +-------+--------------------------- + [1,2) | {[2000-01-01,2010-01-01)} +(1 row) + +DROP TABLE temporal_mltrng3; +-- +-- test FK dependencies +-- +-- can't drop a range referenced by an FK, unless with CASCADE +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal3 (id, PERIOD valid_at) +); +ALTER TABLE temporal3 DROP COLUMN valid_at; +ERROR: cannot drop column valid_at of table temporal3 because other objects depend on it +DETAIL: constraint temporal_fk_rng2rng_fk on table temporal_fk_rng2rng depends on column valid_at of table temporal3 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER TABLE temporal3 DROP COLUMN valid_at CASCADE; +NOTICE: drop cascades to constraint temporal_fk_rng2rng_fk on table temporal_fk_rng2rng +DROP TABLE temporal_fk_rng2rng; +DROP TABLE temporal3; +-- +-- test FOREIGN KEY, range references range +-- +-- test table setup +DROP TABLE temporal_rng; +CREATE TABLE temporal_rng (id int4range, valid_at daterange); +ALTER TABLE temporal_rng + ADD CONSTRAINT temporal_rng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +-- Can't create a FK with a mismatched range type +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at int4range, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk2 PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk2 FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +ERROR: foreign key constraint "temporal_fk_rng2rng_fk2" cannot be implemented +DETAIL: Key columns "valid_at" of the referencing table and "valid_at" of the referenced table are of incompatible types: int4range and daterange. +-- works: PERIOD for both referenced and referencing +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +DROP TABLE temporal_fk_rng2rng; +-- with mismatched PERIOD columns: +-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) +-- REFERENCES part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, valid_at) +); +ERROR: foreign key uses PERIOD on the referencing table but not the referenced table +-- (parent_id, valid_at) REFERENCES (id, valid_at) +-- both should specify PERIOD: +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng (id, valid_at) +); +ERROR: foreign key must use PERIOD when referencing a primary using WITHOUT OVERLAPS +-- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- (parent_id, valid_at) REFERENCES [implicit] +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- (parent_id, PERIOD valid_at) REFERENCES (id) +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id) +); +ERROR: foreign key uses PERIOD on the referencing table but not the referenced table +-- (parent_id) REFERENCES (id, PERIOD valid_at) +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- with inferred PK on the referenced table: +-- (parent_id, PERIOD valid_at) REFERENCES [implicit] +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng +); +DROP TABLE temporal_fk_rng2rng; +-- (parent_id) REFERENCES [implicit] +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_rng +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- should fail because of duplicate referenced columns: +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_rng (id, PERIOD id) +); +ERROR: foreign key referenced-columns list must not contain duplicates +-- Two scalar columns +DROP TABLE temporal_rng2; +CREATE TABLE temporal_rng2 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +CREATE TABLE temporal_fk2_rng2rng ( + id int4range, + valid_at daterange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk2_rng2rng_fk FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at) +); +\d temporal_fk2_rng2rng + Table "public.temporal_fk2_rng2rng" + Column | Type | Collation | Nullable | Default +------------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | + parent_id1 | int4range | | | + parent_id2 | int4range | | | +Indexes: + "temporal_fk2_rng2rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Foreign-key constraints: + "temporal_fk2_rng2rng_fk" FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_rng2(id1, id2, PERIOD valid_at) + +DROP TABLE temporal_fk2_rng2rng; +-- +-- test ALTER TABLE ADD CONSTRAINT +-- +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at); +-- Two scalar columns: +CREATE TABLE temporal_fk2_rng2rng ( + id int4range, + valid_at daterange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk2_rng2rng + ADD CONSTRAINT temporal_fk2_rng2rng_fk + FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at); +\d temporal_fk2_rng2rng + Table "public.temporal_fk2_rng2rng" + Column | Type | Collation | Nullable | Default +------------+-----------+-----------+----------+--------- + id | int4range | | not null | + valid_at | daterange | | not null | + parent_id1 | int4range | | | + parent_id2 | int4range | | | +Indexes: + "temporal_fk2_rng2rng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Foreign-key constraints: + "temporal_fk2_rng2rng_fk" FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_rng2(id1, id2, PERIOD valid_at) + +-- with inferred PK on the referenced table, and wrong column type: +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk, + ALTER COLUMN valid_at TYPE tsrange USING tsrange(lower(valid_at), upper(valid_at)); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +ERROR: foreign key constraint "temporal_fk_rng2rng_fk" cannot be implemented +DETAIL: Key columns "valid_at" of the referencing table and "valid_at" of the referenced table are of incompatible types: tsrange and daterange. +ALTER TABLE temporal_fk_rng2rng + ALTER COLUMN valid_at TYPE daterange USING daterange(lower(valid_at)::date, upper(valid_at)::date); +-- with inferred PK on the referenced table: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +-- should fail because of duplicate referenced columns: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk2 + FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_rng (id, PERIOD id); +ERROR: foreign key referenced-columns list must not contain duplicates +-- +-- test with rows already +-- +DELETE FROM temporal_fk_rng2rng; +DELETE FROM temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[1,2)', daterange('2018-01-02', '2018-02-03')), + ('[1,2)', daterange('2018-03-03', '2018-04-04')), + ('[2,3)', daterange('2018-01-01', '2018-01-05')), + ('[3,4)', daterange('2018-01-01', NULL)); +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-01'), '[1,2)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); +-- should fail: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), [2018-01-02,2018-04-01)) is not present in table "temporal_rng". +-- okay again: +DELETE FROM temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +-- +-- test pg_get_constraintdef +-- +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_rng2rng_fk'; + pg_get_constraintdef +--------------------------------------------------------------------------------------- + FOREIGN KEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng(id, PERIOD valid_at) +(1 row) + +-- +-- test FK referencing inserts +-- +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-01'), '[1,2)'); +-- should fail: +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), [2018-01-02,2018-04-01)) is not present in table "temporal_rng". +-- now it should work: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-02-03', '2018-03-03')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); +-- +-- test FK referencing updates +-- +-- slide the edge across a referenced transition: +UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-02-20') WHERE id = '[1,2)'; +-- should fail: +UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-05-01') WHERE id = '[1,2)'; +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), [2018-01-02,2018-05-01)) is not present in table "temporal_rng". +UPDATE temporal_fk_rng2rng SET parent_id = '[8,9)' WHERE id = '[1,2)'; +ERROR: insert or update on table "temporal_fk_rng2rng" violates foreign key constraint "temporal_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([8,9), [2018-01-02,2018-02-20)) is not present in table "temporal_rng". +-- ALTER FK DEFERRABLE +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); + INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + DELETE FROM temporal_rng WHERE id = '[5,6)'; --should not fail yet. +COMMIT; -- should fail here. +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- +-- test FK referenced updates NO ACTION +-- +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON UPDATE NO ACTION; +-- a PK update that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'; +-- a PK update that succeeds even though the numeric id is referenced because the range isn't: +DELETE FROM temporal_rng WHERE id = '[5,6)'; +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) + VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +UPDATE temporal_rng SET valid_at = daterange('2016-02-01', '2016-03-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- A PK update sliding the edge between two referenced rows: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[6,7)', daterange('2018-01-01', '2018-02-01')), + ('[6,7)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[4,5)', daterange('2018-01-15', '2018-02-15'), '[6,7)'); +UPDATE temporal_rng + SET valid_at = CASE WHEN lower(valid_at) = '2018-01-01' THEN daterange('2018-01-01', '2018-01-05') + WHEN lower(valid_at) = '2018-02-01' THEN daterange('2018-01-05', '2018-03-01') END + WHERE id = '[6,7)'; +-- a PK update shrinking the referenced range but still valid: +-- There are two references: one fulfilled by the first pk row, +-- the other fulfilled by both pk rows combined. +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[1,2)', daterange('2018-01-01', '2018-03-01')), + ('[1,2)', daterange('2018-03-01', '2018-06-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[1,2)', daterange('2018-01-15', '2018-02-01'), '[1,2)'), + ('[2,3)', daterange('2018-01-15', '2018-05-01'), '[1,2)'); +UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update growing the referenced range is fine: +UPDATE temporal_rng SET valid_at = daterange('2018-01-01', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-25'::date; +-- a PK update shrinking the referenced range and changing the id invalidates the whole range (error): +UPDATE temporal_rng SET id = '[2,3)', valid_at = daterange('2018-01-15', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-01,2018-03-01)) is still referenced from table "temporal_fk_rng2rng". +-- a PK update changing only the id invalidates the whole range (error): +UPDATE temporal_rng SET id = '[2,3)' + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([1,2), [2018-01-01,2018-03-01)) is still referenced from table "temporal_fk_rng2rng". +-- a PK update that loses time from both ends, but is still valid: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[2,3)', daterange('2018-01-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[5,6)', daterange('2018-01-15', '2018-02-01'), '[2,3)'); +UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-02-15') + WHERE id = '[2,3)'; +-- a PK update that fails because both are referenced: +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- a PK update that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +COMMIT; +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- changing the scalar part fails: +UPDATE temporal_rng SET id = '[7,8)' + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- then delete the objecting FK record and the same PK update succeeds: +DELETE FROM temporal_fk_rng2rng WHERE id = '[3,4)'; +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +-- +-- test FK referenced updates RESTRICT +-- +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON UPDATE RESTRICT; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- test FK referenced deletes NO ACTION +-- +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +-- a PK delete that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +DELETE FROM temporal_rng WHERE id = '[5,6)'; +-- a PK delete that succeeds even though the numeric id is referenced because the range isn't: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- a PK delete that fails because both are referenced: +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- a PK delete that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +COMMIT; +ERROR: update or delete on table "temporal_rng" violates foreign key constraint "temporal_fk_rng2rng_fk" on table "temporal_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_fk_rng2rng". +-- then delete the objecting FK record and the same PK delete succeeds: +DELETE FROM temporal_fk_rng2rng WHERE id = '[3,4)'; +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +-- +-- test FK referenced deletes RESTRICT +-- +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE RESTRICT; +ERROR: unsupported ON DELETE action for foreign key constraint using PERIOD +-- +-- test ON UPDATE/DELETE options +-- +-- test FK referenced updates CASCADE +INSERT INTO temporal_rng (id, valid_at) VALUES ('[6,7)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[4,5)', daterange('2018-01-01', '2021-01-01'), '[6,7)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE CASCADE ON UPDATE CASCADE; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- test FK referenced updates SET NULL +INSERT INTO temporal_rng (id, valid_at) VALUES ('[9,10)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[6,7)', daterange('2018-01-01', '2021-01-01'), '[9,10)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE SET NULL ON UPDATE SET NULL; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- test FK referenced updates SET DEFAULT +INSERT INTO temporal_rng (id, valid_at) VALUES ('[-1,-1]', daterange(null, null)); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[12,13)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[8,9)', daterange('2018-01-01', '2021-01-01'), '[12,13)'); +ALTER TABLE temporal_fk_rng2rng + ALTER COLUMN parent_id SET DEFAULT '[-1,-1]', + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- test FOREIGN KEY, multirange references multirange +-- +-- test table setup +DROP TABLE temporal_mltrng; +CREATE TABLE temporal_mltrng ( id int4range, valid_at datemultirange); +ALTER TABLE temporal_mltrng + ADD CONSTRAINT temporal_mltrng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +-- Can't create a FK with a mismatched multirange type +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at int4multirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk2 PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk2 FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +ERROR: foreign key constraint "temporal_fk_mltrng2mltrng_fk2" cannot be implemented +DETAIL: Key columns "valid_at" of the referencing table and "valid_at" of the referenced table are of incompatible types: int4multirange and datemultirange. +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +DROP TABLE temporal_fk_mltrng2mltrng; +-- with mismatched PERIOD columns: +-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) +-- REFERENCES part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, valid_at) +); +ERROR: foreign key uses PERIOD on the referencing table but not the referenced table +-- (parent_id, valid_at) REFERENCES (id, valid_at) +-- both should specify PERIOD: +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng (id, valid_at) +); +ERROR: foreign key must use PERIOD when referencing a primary using WITHOUT OVERLAPS +-- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- (parent_id, valid_at) REFERENCES [implicit] +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- (parent_id, PERIOD valid_at) REFERENCES (id) +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id) +); +ERROR: foreign key uses PERIOD on the referencing table but not the referenced table +-- (parent_id) REFERENCES (id, PERIOD valid_at) +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- with inferred PK on the referenced table: +-- (parent_id, PERIOD valid_at) REFERENCES [implicit] +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng +); +DROP TABLE temporal_fk_mltrng2mltrng; +-- (parent_id) REFERENCES [implicit] +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_mltrng +); +ERROR: foreign key uses PERIOD on the referenced table but not the referencing table +-- should fail because of duplicate referenced columns: +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_mltrng (id, PERIOD id) +); +ERROR: foreign key referenced-columns list must not contain duplicates +-- Two scalar columns +DROP TABLE temporal_mltrng2; +CREATE TABLE temporal_mltrng2 ( + id1 int4range, + id2 int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +CREATE TABLE temporal_fk2_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk2_mltrng2mltrng_fk FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at) +); +\d temporal_fk2_mltrng2mltrng + Table "public.temporal_fk2_mltrng2mltrng" + Column | Type | Collation | Nullable | Default +------------+----------------+-----------+----------+--------- + id | int4range | | not null | + valid_at | datemultirange | | not null | + parent_id1 | int4range | | | + parent_id2 | int4range | | | +Indexes: + "temporal_fk2_mltrng2mltrng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Foreign-key constraints: + "temporal_fk2_mltrng2mltrng_fk" FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_mltrng2(id1, id2, PERIOD valid_at) + +DROP TABLE temporal_fk2_mltrng2mltrng; +-- +-- test ALTER TABLE ADD CONSTRAINT +-- +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +-- Two scalar columns: +CREATE TABLE temporal_fk2_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk2_mltrng2mltrng + ADD CONSTRAINT temporal_fk2_mltrng2mltrng_fk + FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at); +\d temporal_fk2_mltrng2mltrng + Table "public.temporal_fk2_mltrng2mltrng" + Column | Type | Collation | Nullable | Default +------------+----------------+-----------+----------+--------- + id | int4range | | not null | + valid_at | datemultirange | | not null | + parent_id1 | int4range | | | + parent_id2 | int4range | | | +Indexes: + "temporal_fk2_mltrng2mltrng_pk" PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +Foreign-key constraints: + "temporal_fk2_mltrng2mltrng_fk" FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_mltrng2(id1, id2, PERIOD valid_at) + +-- should fail because of duplicate referenced columns: +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk2 + FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_mltrng (id, PERIOD id); +ERROR: foreign key referenced-columns list must not contain duplicates +-- +-- test with rows already +-- +DELETE FROM temporal_fk_mltrng2mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))), + ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))), + ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))), + ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-01')), '[1,2)'); +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); +-- should fail: +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +ERROR: insert or update on table "temporal_fk_mltrng2mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), {[2018-01-02,2018-04-01)}) is not present in table "temporal_mltrng". +-- okay again: +DELETE FROM temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +-- +-- test pg_get_constraintdef +-- +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_mltrng2mltrng_fk'; + pg_get_constraintdef +------------------------------------------------------------------------------------------ + FOREIGN KEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng(id, PERIOD valid_at) +(1 row) + +-- +-- test FK referencing inserts +-- +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-01')), '[1,2)'); +-- should fail: +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); +ERROR: insert or update on table "temporal_fk_mltrng2mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), {[2018-01-02,2018-04-01)}) is not present in table "temporal_mltrng". +-- now it should work: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-02-03', '2018-03-03'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); +-- +-- test FK referencing updates +-- +-- slide the edge across a referenced transition: +UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-02-20')) WHERE id = '[1,2)'; +-- should fail: +UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-05-01')) WHERE id = '[1,2)'; +ERROR: insert or update on table "temporal_fk_mltrng2mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), {[2018-01-02,2018-05-01)}) is not present in table "temporal_mltrng". +UPDATE temporal_fk_mltrng2mltrng SET parent_id = '[8,9)' WHERE id = '[1,2)'; +ERROR: insert or update on table "temporal_fk_mltrng2mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([8,9), {[2018-01-02,2018-02-20)}) is not present in table "temporal_mltrng". +-- ALTER FK DEFERRABLE +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); + INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + DELETE FROM temporal_mltrng WHERE id = '[5,6)'; --should not fail yet. +COMMIT; -- should fail here. +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- +-- test FK referenced updates NO ACTION +-- +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) + ON UPDATE NO ACTION; +-- a PK update that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'; +-- a PK update that succeeds even though the numeric id is referenced because the range isn't: +DELETE FROM temporal_mltrng WHERE id = '[5,6)'; +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- A PK update sliding the edge between two referenced rows: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[6,7)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[6,7)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[4,5)', datemultirange(daterange('2018-01-15', '2018-02-15')), '[6,7)'); +UPDATE temporal_mltrng + SET valid_at = CASE WHEN lower(valid_at) = '2018-01-01' THEN datemultirange(daterange('2018-01-01', '2018-01-05')) + WHEN lower(valid_at) = '2018-02-01' THEN datemultirange(daterange('2018-01-05', '2018-03-01')) END + WHERE id = '[6,7)'; +-- a PK update shrinking the referenced multirange but still valid: +-- There are two references: one fulfilled by the first pk row, +-- the other fulfilled by both pk rows combined. +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[1,2)', datemultirange(daterange('2018-01-01', '2018-03-01'))), + ('[1,2)', datemultirange(daterange('2018-03-01', '2018-06-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[1,2)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[1,2)'), + ('[2,3)', datemultirange(daterange('2018-01-15', '2018-05-01')), '[1,2)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update growing the referenced multirange is fine: +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-25'::date; +-- a PK update shrinking the referenced multirange and changing the id invalidates the whole multirange (error): +UPDATE temporal_mltrng SET id = '[2,3)', valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-01,2018-03-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- a PK update changing only the id invalidates the whole multirange (error): +UPDATE temporal_mltrng SET id = '[2,3)' + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([1,2), {[2018-01-01,2018-03-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- a PK update that loses time from both ends, but is still valid: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[2,3)', datemultirange(daterange('2018-01-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[5,6)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[2,3)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-02-15')) + WHERE id = '[2,3)'; +-- a PK update that fails because both are referenced: +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- a PK update that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +COMMIT; +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- changing the scalar part fails: +UPDATE temporal_mltrng SET id = '[7,8)' + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- +-- test FK referenced updates RESTRICT +-- +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) + ON UPDATE RESTRICT; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- test FK referenced deletes NO ACTION +-- +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +-- a PK delete that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +DELETE FROM temporal_mltrng WHERE id = '[5,6)'; +-- a PK delete that succeeds even though the numeric id is referenced because the range isn't: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- a PK delete that fails because both are referenced: +DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- a PK delete that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +COMMIT; +ERROR: update or delete on table "temporal_mltrng" violates foreign key constraint "temporal_fk_mltrng2mltrng_fk" on table "temporal_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_fk_mltrng2mltrng". +-- +-- FK between partitioned tables: ranges +-- +CREATE TABLE temporal_partitioned_rng ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 partition OF temporal_partitioned_rng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); +CREATE TABLE tp2 partition OF temporal_partitioned_rng FOR VALUES IN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)'); +INSERT INTO temporal_partitioned_rng (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[2,3)', daterange('2000-01-01', '2010-01-01'), 'two'); +CREATE TABLE temporal_partitioned_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_partitioned_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_partitioned_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng (id, PERIOD valid_at) +) PARTITION BY LIST (id); +CREATE TABLE tfkp1 partition OF temporal_partitioned_fk_rng2rng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); +CREATE TABLE tfkp2 partition OF temporal_partitioned_fk_rng2rng FOR VALUES IN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)'); +-- +-- partitioned FK referencing inserts +-- +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-15'), '[1,2)'), + ('[1,2)', daterange('2001-01-01', '2002-01-01'), '[2,3)'), + ('[2,3)', daterange('2000-01-01', '2000-02-15'), '[1,2)'); +-- should fail: +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2010-01-01', '2010-02-15'), '[1,2)'); +ERROR: insert or update on table "tfkp1" violates foreign key constraint "temporal_partitioned_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), [2010-01-01,2010-02-15)) is not present in table "temporal_partitioned_rng". +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2000-01-01', '2000-02-15'), '[3,4)'); +ERROR: insert or update on table "tfkp1" violates foreign key constraint "temporal_partitioned_fk_rng2rng_fk" +DETAIL: Key (parent_id, valid_at)=([3,4), [2000-01-01,2000-02-15)) is not present in table "temporal_partitioned_rng". +-- +-- partitioned FK referencing updates +-- +UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-02-13') WHERE id = '[2,3)'; +-- move a row from the first partition to the second +UPDATE temporal_partitioned_fk_rng2rng SET id = '[4,5)' WHERE id = '[1,2)'; +-- move a row from the second partition to the first +UPDATE temporal_partitioned_fk_rng2rng SET id = '[1,2)' WHERE id = '[4,5)'; +-- should fail: +UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-04-01') WHERE id = '[1,2)'; +ERROR: conflicting key value violates exclusion constraint "tfkp1_pkey" +DETAIL: Key (id, valid_at)=([1,2), [2000-01-01,2000-04-01)) conflicts with existing key (id, valid_at)=([1,2), [2000-01-01,2000-04-01)). +-- +-- partitioned FK referenced updates NO ACTION +-- +TRUNCATE temporal_partitioned_rng, temporal_partitioned_fk_rng2rng; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2016-01-01', '2016-02-01')); +UPDATE temporal_partitioned_rng SET valid_at = daterange('2018-01-01', '2018-02-01') WHERE id = '[5,6)'; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-02-01', '2016-03-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- should fail: +UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +ERROR: update or delete on table "tp1" violates foreign key constraint "temporal_partitioned_fk_rng2rng_fk_1" on table "temporal_partitioned_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_partitioned_fk_rng2rng". +-- +-- partitioned FK referenced deletes NO ACTION +-- +TRUNCATE temporal_partitioned_rng, temporal_partitioned_fk_rng2rng; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +DELETE FROM temporal_partitioned_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- should fail: +DELETE FROM temporal_partitioned_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +ERROR: update or delete on table "tp1" violates foreign key constraint "temporal_partitioned_fk_rng2rng_fk_1" on table "temporal_partitioned_fk_rng2rng" +DETAIL: Key (id, valid_at)=([5,6), [2018-01-01,2018-02-01)) is still referenced from table "temporal_partitioned_fk_rng2rng". +-- +-- partitioned FK referenced updates CASCADE +-- +ALTER TABLE temporal_partitioned_fk_rng2rng + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE CASCADE ON UPDATE CASCADE; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes CASCADE +-- +-- +-- partitioned FK referenced updates SET NULL +-- +ALTER TABLE temporal_partitioned_fk_rng2rng + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE SET NULL ON UPDATE SET NULL; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes SET NULL +-- +-- +-- partitioned FK referenced updates SET DEFAULT +-- +ALTER TABLE temporal_partitioned_fk_rng2rng + ALTER COLUMN parent_id SET DEFAULT '[-1,-1]', + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes SET DEFAULT +-- +DROP TABLE temporal_partitioned_fk_rng2rng; +DROP TABLE temporal_partitioned_rng; +-- +-- FK between partitioned tables: multiranges +-- +CREATE TABLE temporal_partitioned_mltrng ( + id int4range, + valid_at datemultirange, + name text, + CONSTRAINT temporal_paritioned_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned_mltrng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)', '[13,14)', '[15,16)', '[17,18)', '[19,20)', '[21,22)', '[23,24)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned_mltrng FOR VALUES IN ('[0,1)', '[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)', '[14,15)', '[16,17)', '[18,19)', '[20,21)', '[22,23)', '[24,25)'); +INSERT INTO temporal_partitioned_mltrng (id, valid_at, name) VALUES + ('[1,2)', datemultirange(daterange('2000-01-01', '2000-02-01')), 'one'), + ('[1,2)', datemultirange(daterange('2000-02-01', '2000-03-01')), 'one'), + ('[2,3)', datemultirange(daterange('2000-01-01', '2010-01-01')), 'two'); +CREATE TABLE temporal_partitioned_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng (id, PERIOD valid_at) +) PARTITION BY LIST (id); +CREATE TABLE tfkp1 PARTITION OF temporal_partitioned_fk_mltrng2mltrng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)', '[13,14)', '[15,16)', '[17,18)', '[19,20)', '[21,22)', '[23,24)'); +CREATE TABLE tfkp2 PARTITION OF temporal_partitioned_fk_mltrng2mltrng FOR VALUES IN ('[0,1)', '[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)', '[14,15)', '[16,17)', '[18,19)', '[20,21)', '[22,23)', '[24,25)'); +-- +-- partitioned FK referencing inserts +-- +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[1,2)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[1,2)'), + ('[1,2)', datemultirange(daterange('2001-01-01', '2002-01-01')), '[2,3)'), + ('[2,3)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[1,2)'); +-- should fail: +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2010-01-01', '2010-02-15')), '[1,2)'); +ERROR: insert or update on table "tfkp1" violates foreign key constraint "temporal_partitioned_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([1,2), {[2010-01-01,2010-02-15)}) is not present in table "temporal_partitioned_mltrng". +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[3,4)'); +ERROR: insert or update on table "tfkp1" violates foreign key constraint "temporal_partitioned_fk_mltrng2mltrng_fk" +DETAIL: Key (parent_id, valid_at)=([3,4), {[2000-01-01,2000-02-15)}) is not present in table "temporal_partitioned_mltrng". +-- +-- partitioned FK referencing updates +-- +UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-02-13')) WHERE id = '[2,3)'; +-- move a row from the first partition to the second +UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[4,5)' WHERE id = '[1,2)'; +-- move a row from the second partition to the first +UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[1,2)' WHERE id = '[4,5)'; +-- should fail: +UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-04-01')) WHERE id = '[1,2)'; +ERROR: conflicting key value violates exclusion constraint "tfkp1_pkey" +DETAIL: Key (id, valid_at)=([1,2), {[2000-01-01,2000-04-01)}) conflicts with existing key (id, valid_at)=([1,2), {[2000-01-01,2000-04-01)}). +-- +-- partitioned FK referenced updates NO ACTION +-- +TRUNCATE temporal_partitioned_mltrng, temporal_partitioned_fk_mltrng2mltrng; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2016-01-01', '2016-02-01'))); +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')) WHERE id = '[5,6)'; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- should fail: +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +ERROR: update or delete on table "tp1" violates foreign key constraint "temporal_partitioned_fk_mltrng2mltrng_fk_2" on table "temporal_partitioned_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_partitioned_fk_mltrng2mltrng". +-- +-- partitioned FK referenced deletes NO ACTION +-- +TRUNCATE temporal_partitioned_mltrng, temporal_partitioned_fk_mltrng2mltrng; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +DELETE FROM temporal_partitioned_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- should fail: +DELETE FROM temporal_partitioned_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +ERROR: update or delete on table "tp1" violates foreign key constraint "temporal_partitioned_fk_mltrng2mltrng_fk_2" on table "temporal_partitioned_fk_mltrng2mltrng" +DETAIL: Key (id, valid_at)=([5,6), {[2018-01-01,2018-02-01)}) is still referenced from table "temporal_partitioned_fk_mltrng2mltrng". +-- +-- partitioned FK referenced updates CASCADE +-- +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE CASCADE ON UPDATE CASCADE; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes CASCADE +-- +-- +-- partitioned FK referenced updates SET NULL +-- +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE SET NULL ON UPDATE SET NULL; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes SET NULL +-- +-- +-- partitioned FK referenced updates SET DEFAULT +-- +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + ALTER COLUMN parent_id SET DEFAULT '[0,1)', + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; +ERROR: unsupported ON UPDATE action for foreign key constraint using PERIOD +-- +-- partitioned FK referenced deletes SET DEFAULT +-- +DROP TABLE temporal_partitioned_fk_mltrng2mltrng; +DROP TABLE temporal_partitioned_mltrng; +RESET datestyle; diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 93a79cda8fd4e..103a22a3b1d3c 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -485,8 +485,7 @@ SELECT xmlserialize(DOCUMENT '42' AS text + 42+ + - + - + (1 row) SELECT xmlserialize(CONTENT '42' AS text INDENT); @@ -546,8 +545,7 @@ SELECT xmlserialize(DOCUMENT '42text node< 42 + text node73+ + - + - + (1 row) SELECT xmlserialize(CONTENT '42text node73' AS text INDENT); @@ -601,8 +599,7 @@ SELECT xmlserialize(DOCUMENT ' + 73 + + - + - + (1 row) SELECT xmlserialize(CONTENT '73' AS text INDENT); @@ -620,8 +617,7 @@ SELECT xmlserialize(DOCUMENT '' AS text INDENT); xmlserialize -------------- + - + - + (1 row) SELECT xmlserialize(CONTENT '' AS text INDENT); @@ -638,8 +634,7 @@ SELECT xmlserialize(DOCUMENT '' AS text INDENT); -------------- + + - + - + (1 row) SELECT xmlserialize(CONTENT '' AS text INDENT); @@ -663,6 +658,24 @@ SELECT xmlserialize(CONTENT '42' AS text t (1 row) +-- indent xml strings containing blank nodes +SELECT xmlserialize(DOCUMENT ' ' AS text INDENT); + xmlserialize +-------------- + + + + + +(1 row) + +SELECT xmlserialize(CONTENT 'text node ' AS text INDENT); + xmlserialize +-------------- + text node + + + + + + +(1 row) + SELECT xml 'bar' IS DOCUMENT; ?column? ---------- @@ -809,21 +822,25 @@ CREATE VIEW xmlview6 AS SELECT xmlpi(name foo, 'bar'); CREATE VIEW xmlview7 AS SELECT xmlroot(xml '', version no value, standalone yes); CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10)); CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text); +CREATE VIEW xmlview10 AS SELECT xmlserialize(document '42' AS text indent); +CREATE VIEW xmlview11 AS SELECT xmlserialize(document '42' AS character varying no indent); SELECT table_name, view_definition FROM information_schema.views WHERE table_name LIKE 'xmlview%' ORDER BY 1; - table_name | view_definition -------------+------------------------------------------------------------------------------------------------------------ + table_name | view_definition +------------+--------------------------------------------------------------------------------------------------------------------------------------- xmlview1 | SELECT xmlcomment('test'::text) AS xmlcomment; + xmlview10 | SELECT XMLSERIALIZE(DOCUMENT '42'::xml AS text INDENT) AS "xmlserialize"; + xmlview11 | SELECT (XMLSERIALIZE(DOCUMENT '42'::xml AS character varying NO INDENT))::character varying AS "xmlserialize"; xmlview2 | SELECT XMLCONCAT('hello'::xml, 'you'::xml) AS "xmlconcat"; xmlview3 | SELECT XMLELEMENT(NAME element, XMLATTRIBUTES(1 AS ":one:", 'deuce' AS two), 'content&') AS "xmlelement"; - xmlview4 | SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement" + + xmlview4 | SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement" + | FROM emp; xmlview5 | SELECT XMLPARSE(CONTENT 'x'::text STRIP WHITESPACE) AS "xmlparse"; xmlview6 | SELECT XMLPI(NAME foo, 'bar'::text) AS "xmlpi"; xmlview7 | SELECT XMLROOT(''::xml, VERSION NO VALUE, STANDALONE YES) AS "xmlroot"; - xmlview8 | SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10)))::character(10) AS "xmlserialize"; - xmlview9 | SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text) AS "xmlserialize"; -(9 rows) + xmlview8 | SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10) NO INDENT))::character(10) AS "xmlserialize"; + xmlview9 | SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text NO INDENT) AS "xmlserialize"; +(11 rows) -- Text XPath expressions evaluation SELECT xpath('/value', data) FROM xmltest; @@ -1356,6 +1373,10 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1; -- errors SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2); ERROR: XMLTABLE function has 1 columns available but 2 columns specified +SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1); +ERROR: option name "__pg__is_not_null" cannot be used in XMLTABLE +LINE 1: ...MLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_n... + ^ -- XMLNAMESPACES tests SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), '/zz:rows/zz:row' @@ -1366,16 +1387,20 @@ SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), 10 (1 row) -CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), - '/zz:rows/zz:row' +CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS "Zz"), + '/Zz:rows/Zz:row' PASSING '10' - COLUMNS a int PATH 'zz:a'); + COLUMNS a int PATH 'Zz:a'); SELECT * FROM xmltableview2; a ---- 10 (1 row) +\sv xmltableview2 +CREATE OR REPLACE VIEW public.xmltableview2 AS + SELECT a + FROM XMLTABLE(XMLNAMESPACES ('http://x.y'::text AS "Zz"), ('/Zz:rows/Zz:row'::text) PASSING ('10'::xml) COLUMNS a integer PATH ('Zz:a'::text)) SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'), '/rows/row' PASSING '10' @@ -1564,6 +1589,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1575,6 +1601,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1584,6 +1611,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" + diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index 9323b84ae21d2..73c411118a390 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -443,6 +443,17 @@ ERROR: unsupported XML feature LINE 1: SELECT xmlserialize(CONTENT '42<... ^ DETAIL: This functionality requires the server to be built with libxml support. +-- indent xml strings containing blank nodes +SELECT xmlserialize(DOCUMENT ' ' AS text INDENT); +ERROR: unsupported XML feature +LINE 1: SELECT xmlserialize(DOCUMENT ' '... + ^ +DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmlserialize(CONTENT 'text node ' AS text INDENT); +ERROR: unsupported XML feature +LINE 1: SELECT xmlserialize(CONTENT 'text node ... + ^ +DETAIL: This functionality requires the server to be built with libxml support. SELECT xml 'bar' IS DOCUMENT; ERROR: unsupported XML feature LINE 1: SELECT xml 'bar' IS DOCUMENT; @@ -572,6 +583,16 @@ ERROR: unsupported XML feature LINE 1: ...EATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as ... ^ DETAIL: This functionality requires the server to be built with libxml support. +CREATE VIEW xmlview10 AS SELECT xmlserialize(document '42' AS text indent); +ERROR: unsupported XML feature +LINE 1: ...TE VIEW xmlview10 AS SELECT xmlserialize(document '42' AS character varying no indent); +ERROR: unsupported XML feature +LINE 1: ...TE VIEW xmlview11 AS SELECT xmlserialize(document '10' - COLUMNS a int PATH 'zz:a'); + COLUMNS a int PATH 'Zz:a'); ERROR: unsupported XML feature LINE 3: PASSING '10' @@ -1198,6 +1225,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1209,6 +1237,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1218,6 +1247,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" + diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out index f956322c69384..a85d95358d901 100644 --- a/src/test/regress/expected/xml_2.out +++ b/src/test/regress/expected/xml_2.out @@ -471,8 +471,7 @@ SELECT xmlserialize(DOCUMENT '42' AS text + 42+ + - + - + (1 row) SELECT xmlserialize(CONTENT '42' AS text INDENT); @@ -532,8 +531,7 @@ SELECT xmlserialize(DOCUMENT '42text node< 42 + text node73+ + - + - + (1 row) SELECT xmlserialize(CONTENT '42text node73' AS text INDENT); @@ -587,8 +585,7 @@ SELECT xmlserialize(DOCUMENT ' + 73 + + - + - + (1 row) SELECT xmlserialize(CONTENT '73' AS text INDENT); @@ -606,8 +603,7 @@ SELECT xmlserialize(DOCUMENT '' AS text INDENT); xmlserialize -------------- + - + - + (1 row) SELECT xmlserialize(CONTENT '' AS text INDENT); @@ -624,8 +620,7 @@ SELECT xmlserialize(DOCUMENT '' AS text INDENT); -------------- + + - + - + (1 row) SELECT xmlserialize(CONTENT '' AS text INDENT); @@ -649,6 +644,24 @@ SELECT xmlserialize(CONTENT '42' AS text t (1 row) +-- indent xml strings containing blank nodes +SELECT xmlserialize(DOCUMENT ' ' AS text INDENT); + xmlserialize +-------------- + + + + + +(1 row) + +SELECT xmlserialize(CONTENT 'text node ' AS text INDENT); + xmlserialize +-------------- + text node + + + + + + +(1 row) + SELECT xml 'bar' IS DOCUMENT; ?column? ---------- @@ -795,21 +808,25 @@ CREATE VIEW xmlview6 AS SELECT xmlpi(name foo, 'bar'); CREATE VIEW xmlview7 AS SELECT xmlroot(xml '', version no value, standalone yes); CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10)); CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text); +CREATE VIEW xmlview10 AS SELECT xmlserialize(document '42' AS text indent); +CREATE VIEW xmlview11 AS SELECT xmlserialize(document '42' AS character varying no indent); SELECT table_name, view_definition FROM information_schema.views WHERE table_name LIKE 'xmlview%' ORDER BY 1; - table_name | view_definition -------------+------------------------------------------------------------------------------------------------------------ + table_name | view_definition +------------+--------------------------------------------------------------------------------------------------------------------------------------- xmlview1 | SELECT xmlcomment('test'::text) AS xmlcomment; + xmlview10 | SELECT XMLSERIALIZE(DOCUMENT '42'::xml AS text INDENT) AS "xmlserialize"; + xmlview11 | SELECT (XMLSERIALIZE(DOCUMENT '42'::xml AS character varying NO INDENT))::character varying AS "xmlserialize"; xmlview2 | SELECT XMLCONCAT('hello'::xml, 'you'::xml) AS "xmlconcat"; xmlview3 | SELECT XMLELEMENT(NAME element, XMLATTRIBUTES(1 AS ":one:", 'deuce' AS two), 'content&') AS "xmlelement"; - xmlview4 | SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement" + + xmlview4 | SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement" + | FROM emp; xmlview5 | SELECT XMLPARSE(CONTENT 'x'::text STRIP WHITESPACE) AS "xmlparse"; xmlview6 | SELECT XMLPI(NAME foo, 'bar'::text) AS "xmlpi"; xmlview7 | SELECT XMLROOT(''::xml, VERSION NO VALUE, STANDALONE YES) AS "xmlroot"; - xmlview8 | SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10)))::character(10) AS "xmlserialize"; - xmlview9 | SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text) AS "xmlserialize"; -(9 rows) + xmlview8 | SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10) NO INDENT))::character(10) AS "xmlserialize"; + xmlview9 | SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text NO INDENT) AS "xmlserialize"; +(11 rows) -- Text XPath expressions evaluation SELECT xpath('/value', data) FROM xmltest; @@ -1342,6 +1359,10 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1; -- errors SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2); ERROR: XMLTABLE function has 1 columns available but 2 columns specified +SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1); +ERROR: option name "__pg__is_not_null" cannot be used in XMLTABLE +LINE 1: ...MLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_n... + ^ -- XMLNAMESPACES tests SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), '/zz:rows/zz:row' @@ -1352,16 +1373,20 @@ SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), 10 (1 row) -CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), - '/zz:rows/zz:row' +CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS "Zz"), + '/Zz:rows/Zz:row' PASSING '10' - COLUMNS a int PATH 'zz:a'); + COLUMNS a int PATH 'Zz:a'); SELECT * FROM xmltableview2; a ---- 10 (1 row) +\sv xmltableview2 +CREATE OR REPLACE VIEW public.xmltableview2 AS + SELECT a + FROM XMLTABLE(XMLNAMESPACES ('http://x.y'::text AS "Zz"), ('/Zz:rows/Zz:row'::text) PASSING ('10'::xml) COLUMNS a integer PATH ('Zz:a'::text)) SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'), '/rows/row' PASSING '10' @@ -1550,6 +1575,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Parallel Aware": false, + "Async Capable": false, + "Join Type": "Inner", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Inner Unique": false, + "Plans": [ + @@ -1561,6 +1587,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Relation Name": "xmldata", + "Schema": "public", + "Alias": "xmldata", + + "Disabled": false, + "Output": ["xmldata.data"] + }, + { + @@ -1570,6 +1597,7 @@ SELECT f.* FROM xmldata, LATERAL xmltable('/ROWS/ROW[COUNTRY_NAME="Japan" or COU "Async Capable": false, + "Table Function Name": "xmltable", + "Alias": "f", + + "Disabled": false, + "Output": ["f.\"COUNTRY_NAME\"", "f.\"REGION_ID\""], + "Table Function Call": "XMLTABLE(('/ROWS/ROW[COUNTRY_NAME=\"Japan\" or COUNTRY_NAME=\"India\"]'::text) PASSING (xmldata.data) COLUMNS \"COUNTRY_NAME\" text, \"REGION_ID\" integer)",+ "Filter": "(f.\"COUNTRY_NAME\" = 'Japan'::text)" + diff --git a/src/test/regress/meson.build b/src/test/regress/meson.build index 5a9be73531e9c..1da9e9462a9af 100644 --- a/src/test/regress/meson.build +++ b/src/test/regress/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # also used by isolationtester and ecpg tests pg_regress_c = files('pg_regress.c') @@ -43,23 +43,6 @@ regress_module = shared_module('regress', ) test_install_libs += regress_module -# Get some extra C modules from contrib/spi but mark them as not to be -# installed. -# FIXME: avoid the duplication. - -autoinc_regress = shared_module('autoinc', - ['../../../contrib/spi/autoinc.c'], - kwargs: pg_test_mod_args, -) -test_install_libs += autoinc_regress - -refint_regress = shared_module('refint', - ['../../../contrib/spi/refint.c'], - c_args: refint_cflags, - kwargs: pg_test_mod_args, -) -test_install_libs += refint_regress - tests += { 'name': 'regress', diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 2429ec2bbaab0..a424be2a6bf0f 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -28,7 +28,7 @@ test: strings md5 numerology point lseg line box path polygon circle date time t # geometry depends on point, lseg, line, box, path, polygon, circle # horology depends on date, time, timetz, timestamp, timestamptz, interval # ---------- -test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database +test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import # ---------- # Load huge amounts of data @@ -36,7 +36,7 @@ test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comment # execute two copy tests in parallel, to check that copy itself # is concurrent safe. # ---------- -test: copy copyselect copydml insert insert_conflict +test: copy copyselect copydml copyencoding insert insert_conflict # ---------- # More groups of parallel tests @@ -66,7 +66,7 @@ test: select_into select_distinct select_distinct_on select_implicit select_havi # ---------- # Another group of parallel tests # ---------- -test: brin gin gist spgist privileges init_privs security_label collate matview lock replica_identity rowsecurity object_address tablesample groupingsets drop_operator password identity generated join_hash +test: brin gin gist spgist privileges init_privs security_label collate matview lock replica_identity rowsecurity object_address tablesample groupingsets drop_operator password identity generated_stored join_hash # ---------- # Additional BRIN tests @@ -78,10 +78,10 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other -test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 +test: rules psql psql_crosstab psql_pipeline amutils stats_ext collate.linux.utf8 collate.windows.win1252 # ---------- # Run these alone so they don't run out of parallel workers @@ -91,6 +91,10 @@ test: select_parallel test: write_parallel test: vacuum_parallel +# Run this alone, because concurrent DROP TABLE would make non-superuser +# "ANALYZE;" fail with "relation with OID $n does not exist". +test: maintain_every + # no relation related tests can be put in this group test: publication subscription @@ -108,7 +112,7 @@ test: json jsonb json_encoding jsonpath jsonpath_encoding jsonb_jsonpath sqljson # ---------- # Another group of parallel tests # with depends on create_misc -# NB: temp.sql does a reconnect which transiently uses 2 connections, +# NB: temp.sql does reconnects which transiently use 2 connections, # so keep this parallel group to at most 19 tests # ---------- test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml @@ -119,7 +123,7 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion tr # The stats test resets stats, so nothing else needing stats access can be in # this group. # ---------- -test: partition_merge partition_split partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain compression memoize stats predicate +test: partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain compression memoize stats predicate numa # event_trigger depends on create_am and cannot run concurrently with # any test that runs DDL diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 69a0caffa4738..5d85dcc62f0a5 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -8,7 +8,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/test/regress/pg_regress.c @@ -28,7 +28,6 @@ #include "common/logging.h" #include "common/restricted_token.h" -#include "common/string.h" #include "common/username.h" #include "getopt_long.h" #include "lib/stringinfo.h" @@ -233,14 +232,17 @@ free_stringlist(_stringlist **listhead) static void split_to_stringlist(const char *s, const char *delim, _stringlist **listhead) { - char *sc = pg_strdup(s); char *token; + char *sc; + char *tofree; + + tofree = sc = pg_strdup(s); while ((token = strsep(&sc, delim))) { add_stringlist_item(listhead, token); } - free(sc); + free(tofree); } /* @@ -516,11 +518,15 @@ make_temp_sockdir(void) * Remove the directory before dying to the usual signals. Omit SIGQUIT, * preserving it as a quick, untidy exit. */ - pqsignal(SIGHUP, signal_remove_temp); pqsignal(SIGINT, signal_remove_temp); - pqsignal(SIGPIPE, signal_remove_temp); pqsignal(SIGTERM, signal_remove_temp); + /* the following are not valid on Windows */ +#ifndef WIN32 + pqsignal(SIGHUP, signal_remove_temp); + pqsignal(SIGPIPE, signal_remove_temp); +#endif + return temp_sockdir; } @@ -776,7 +782,7 @@ initialize_environment(void) /* * Set timezone and datestyle for datetime-related tests */ - setenv("PGTZ", "PST8PDT", 1); + setenv("PGTZ", "America/Los_Angeles", 1); setenv("PGDATESTYLE", "Postgres, MDY", 1); /* @@ -1329,7 +1335,7 @@ make_directory(const char *dir) } /* - * In: filename.ext, Return: filename_i.ext, where 0 < i <= 9 + * In: filename.ext, Return: filename_i.ext, where 0 <= i <= 9 */ static char * get_alternative_expectfile(const char *expectfile, int i) diff --git a/src/test/regress/pg_regress.h b/src/test/regress/pg_regress.h index 5b636ca300926..13d5ba25ebbc7 100644 --- a/src/test/regress/pg_regress.h +++ b/src/test/regress/pg_regress.h @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * pg_regress.h --- regression test driver * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/test/regress/pg_regress.h @@ -18,8 +18,6 @@ #define INVALID_PID INVALID_HANDLE_VALUE #endif -struct StringInfoData; /* avoid including stringinfo.h here */ - /* simple list of strings */ typedef struct _stringlist { diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c index 8aeed97be1a75..072d1cbc62d08 100644 --- a/src/test/regress/pg_regress_main.c +++ b/src/test/regress/pg_regress_main.c @@ -8,7 +8,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/test/regress/pg_regress_main.c diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index 45a6ad3c49ee5..3dbba06902405 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -6,7 +6,7 @@ * * This code is released under the terms of the PostgreSQL License. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/test/regress/regress.c @@ -21,8 +21,7 @@ #include "access/detoast.h" #include "access/htup_details.h" -#include "access/transam.h" -#include "access/xact.h" +#include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" @@ -38,6 +37,7 @@ #include "optimizer/plancat.h" #include "parser/parse_coerce.h" #include "port/atomics.h" +#include "postmaster/postmaster.h" /* for MAX_BACKENDS */ #include "storage/spin.h" #include "utils/array.h" #include "utils/builtins.h" @@ -80,7 +80,10 @@ static void regress_lseg_construct(LSEG *lseg, Point *pt1, Point *pt2); -PG_MODULE_MAGIC; +PG_MODULE_MAGIC_EXT( + .name = "regress", + .version = PG_VERSION +); /* return the point where two paths intersect, or NULL if no intersection. */ @@ -264,227 +267,6 @@ trigger_return_old(PG_FUNCTION_ARGS) return PointerGetDatum(tuple); } -#define TTDUMMY_INFINITY 999999 - -static SPIPlanPtr splan = NULL; -static bool ttoff = false; - -PG_FUNCTION_INFO_V1(ttdummy); - -Datum -ttdummy(PG_FUNCTION_ARGS) -{ - TriggerData *trigdata = (TriggerData *) fcinfo->context; - Trigger *trigger; /* to get trigger name */ - char **args; /* arguments */ - int attnum[2]; /* fnumbers of start/stop columns */ - Datum oldon, - oldoff; - Datum newon, - newoff; - Datum *cvals; /* column values */ - char *cnulls; /* column nulls */ - char *relname; /* triggered relation name */ - Relation rel; /* triggered relation */ - HeapTuple trigtuple; - HeapTuple newtuple = NULL; - HeapTuple rettuple; - TupleDesc tupdesc; /* tuple description */ - int natts; /* # of attributes */ - bool isnull; /* to know is some column NULL or not */ - int ret; - int i; - - if (!CALLED_AS_TRIGGER(fcinfo)) - elog(ERROR, "ttdummy: not fired by trigger manager"); - if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) - elog(ERROR, "ttdummy: must be fired for row"); - if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event)) - elog(ERROR, "ttdummy: must be fired before event"); - if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) - elog(ERROR, "ttdummy: cannot process INSERT event"); - if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) - newtuple = trigdata->tg_newtuple; - - trigtuple = trigdata->tg_trigtuple; - - rel = trigdata->tg_relation; - relname = SPI_getrelname(rel); - - /* check if TT is OFF for this relation */ - if (ttoff) /* OFF - nothing to do */ - { - pfree(relname); - return PointerGetDatum((newtuple != NULL) ? newtuple : trigtuple); - } - - trigger = trigdata->tg_trigger; - - if (trigger->tgnargs != 2) - elog(ERROR, "ttdummy (%s): invalid (!= 2) number of arguments %d", - relname, trigger->tgnargs); - - args = trigger->tgargs; - tupdesc = rel->rd_att; - natts = tupdesc->natts; - - for (i = 0; i < 2; i++) - { - attnum[i] = SPI_fnumber(tupdesc, args[i]); - if (attnum[i] <= 0) - elog(ERROR, "ttdummy (%s): there is no attribute %s", - relname, args[i]); - if (SPI_gettypeid(tupdesc, attnum[i]) != INT4OID) - elog(ERROR, "ttdummy (%s): attribute %s must be of integer type", - relname, args[i]); - } - - oldon = SPI_getbinval(trigtuple, tupdesc, attnum[0], &isnull); - if (isnull) - elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[0]); - - oldoff = SPI_getbinval(trigtuple, tupdesc, attnum[1], &isnull); - if (isnull) - elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[1]); - - if (newtuple != NULL) /* UPDATE */ - { - newon = SPI_getbinval(newtuple, tupdesc, attnum[0], &isnull); - if (isnull) - elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[0]); - newoff = SPI_getbinval(newtuple, tupdesc, attnum[1], &isnull); - if (isnull) - elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[1]); - - if (oldon != newon || oldoff != newoff) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("ttdummy (%s): you cannot change %s and/or %s columns (use set_ttdummy)", - relname, args[0], args[1]))); - - if (newoff != TTDUMMY_INFINITY) - { - pfree(relname); /* allocated in upper executor context */ - return PointerGetDatum(NULL); - } - } - else if (oldoff != TTDUMMY_INFINITY) /* DELETE */ - { - pfree(relname); - return PointerGetDatum(NULL); - } - - newoff = DirectFunctionCall1(nextval, CStringGetTextDatum("ttdummy_seq")); - /* nextval now returns int64; coerce down to int32 */ - newoff = Int32GetDatum((int32) DatumGetInt64(newoff)); - - /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - elog(ERROR, "ttdummy (%s): SPI_connect returned %d", relname, ret); - - /* Fetch tuple values and nulls */ - cvals = (Datum *) palloc(natts * sizeof(Datum)); - cnulls = (char *) palloc(natts * sizeof(char)); - for (i = 0; i < natts; i++) - { - cvals[i] = SPI_getbinval((newtuple != NULL) ? newtuple : trigtuple, - tupdesc, i + 1, &isnull); - cnulls[i] = (isnull) ? 'n' : ' '; - } - - /* change date column(s) */ - if (newtuple) /* UPDATE */ - { - cvals[attnum[0] - 1] = newoff; /* start_date eq current date */ - cnulls[attnum[0] - 1] = ' '; - cvals[attnum[1] - 1] = TTDUMMY_INFINITY; /* stop_date eq INFINITY */ - cnulls[attnum[1] - 1] = ' '; - } - else - /* DELETE */ - { - cvals[attnum[1] - 1] = newoff; /* stop_date eq current date */ - cnulls[attnum[1] - 1] = ' '; - } - - /* if there is no plan ... */ - if (splan == NULL) - { - SPIPlanPtr pplan; - Oid *ctypes; - char *query; - - /* allocate space in preparation */ - ctypes = (Oid *) palloc(natts * sizeof(Oid)); - query = (char *) palloc(100 + 16 * natts); - - /* - * Construct query: INSERT INTO _relation_ VALUES ($1, ...) - */ - sprintf(query, "INSERT INTO %s VALUES (", relname); - for (i = 1; i <= natts; i++) - { - sprintf(query + strlen(query), "$%d%s", - i, (i < natts) ? ", " : ")"); - ctypes[i - 1] = SPI_gettypeid(tupdesc, i); - } - - /* Prepare plan for query */ - pplan = SPI_prepare(query, natts, ctypes); - if (pplan == NULL) - elog(ERROR, "ttdummy (%s): SPI_prepare returned %s", relname, SPI_result_code_string(SPI_result)); - - if (SPI_keepplan(pplan)) - elog(ERROR, "ttdummy (%s): SPI_keepplan failed", relname); - - splan = pplan; - } - - ret = SPI_execp(splan, cvals, cnulls, 0); - - if (ret < 0) - elog(ERROR, "ttdummy (%s): SPI_execp returned %d", relname, ret); - - /* Tuple to return to upper Executor ... */ - if (newtuple) /* UPDATE */ - rettuple = SPI_modifytuple(rel, trigtuple, 1, &(attnum[1]), &newoff, NULL); - else /* DELETE */ - rettuple = trigtuple; - - SPI_finish(); /* don't forget say Bye to SPI mgr */ - - pfree(relname); - - return PointerGetDatum(rettuple); -} - -PG_FUNCTION_INFO_V1(set_ttdummy); - -Datum -set_ttdummy(PG_FUNCTION_ARGS) -{ - int32 on = PG_GETARG_INT32(0); - - if (ttoff) /* OFF currently */ - { - if (on == 0) - PG_RETURN_INT32(0); - - /* turn ON */ - ttoff = false; - PG_RETURN_INT32(0); - } - - /* ON currently */ - if (on != 0) - PG_RETURN_INT32(1); - - /* turn OFF */ - ttoff = true; - - PG_RETURN_INT32(1); -} - /* * Type int44 has no real-world use, but the regression tests use it @@ -645,6 +427,31 @@ make_tuple_indirect(PG_FUNCTION_ARGS) PG_RETURN_POINTER(newtup->t_data); } +PG_FUNCTION_INFO_V1(get_environ); + +Datum +get_environ(PG_FUNCTION_ARGS) +{ +#if !defined(WIN32) || defined(_MSC_VER) + extern char **environ; +#endif + int nvals = 0; + ArrayType *result; + Datum *env; + + for (char **s = environ; *s; s++) + nvals++; + + env = palloc(nvals * sizeof(Datum)); + + for (int i = 0; i < nvals; i++) + env[i] = CStringGetTextDatum(environ[i]); + + result = construct_array_builtin(env, nvals, TEXTOID); + + PG_RETURN_POINTER(result); +} + PG_FUNCTION_INFO_V1(regress_setenv); Datum @@ -887,91 +694,7 @@ test_spinlock(void) if (memcmp(struct_w_lock.data_after, "ef12", 4) != 0) elog(ERROR, "padding after spinlock modified"); } - - /* - * Ensure that allocating more than INT32_MAX emulated spinlocks works. - * That's interesting because the spinlock emulation uses a 32bit integer - * to map spinlocks onto semaphores. There've been bugs... - */ -#ifndef HAVE_SPINLOCKS - { - /* - * Initialize enough spinlocks to advance counter close to wraparound. - * It's too expensive to perform acquire/release for each, as those - * may be syscalls when the spinlock emulation is used (and even just - * atomic TAS would be expensive). - */ - for (uint32 i = 0; i < INT32_MAX - 100000; i++) - { - slock_t lock; - - SpinLockInit(&lock); - } - - for (uint32 i = 0; i < 200000; i++) - { - slock_t lock; - - SpinLockInit(&lock); - - SpinLockAcquire(&lock); - SpinLockRelease(&lock); - SpinLockAcquire(&lock); - SpinLockRelease(&lock); - } - } -#endif -} - -/* - * Verify that performing atomic ops inside a spinlock isn't a - * problem. Realistically that's only going to be a problem when both - * --disable-spinlocks and --disable-atomics are used, but it's cheap enough - * to just always test. - * - * The test works by initializing enough atomics that we'd conflict if there - * were an overlap between a spinlock and an atomic by holding a spinlock - * while manipulating more than NUM_SPINLOCK_SEMAPHORES atomics. - * - * NUM_TEST_ATOMICS doesn't really need to be more than - * NUM_SPINLOCK_SEMAPHORES, but it seems better to test a bit more - * extensively. - */ -static void -test_atomic_spin_nest(void) -{ - slock_t lock; -#define NUM_TEST_ATOMICS (NUM_SPINLOCK_SEMAPHORES + NUM_ATOMICS_SEMAPHORES + 27) - pg_atomic_uint32 atomics32[NUM_TEST_ATOMICS]; - pg_atomic_uint64 atomics64[NUM_TEST_ATOMICS]; - - SpinLockInit(&lock); - - for (int i = 0; i < NUM_TEST_ATOMICS; i++) - { - pg_atomic_init_u32(&atomics32[i], 0); - pg_atomic_init_u64(&atomics64[i], 0); - } - - /* just so it's not all zeroes */ - for (int i = 0; i < NUM_TEST_ATOMICS; i++) - { - EXPECT_EQ_U32(pg_atomic_fetch_add_u32(&atomics32[i], i), 0); - EXPECT_EQ_U64(pg_atomic_fetch_add_u64(&atomics64[i], i), 0); - } - - /* test whether we can do atomic op with lock held */ - SpinLockAcquire(&lock); - for (int i = 0; i < NUM_TEST_ATOMICS; i++) - { - EXPECT_EQ_U32(pg_atomic_fetch_sub_u32(&atomics32[i], i), i); - EXPECT_EQ_U32(pg_atomic_read_u32(&atomics32[i]), 0); - EXPECT_EQ_U64(pg_atomic_fetch_sub_u64(&atomics64[i], i), i); - EXPECT_EQ_U64(pg_atomic_read_u64(&atomics64[i]), 0); - } - SpinLockRelease(&lock); } -#undef NUM_TEST_ATOMICS PG_FUNCTION_INFO_V1(test_atomic_ops); Datum @@ -989,8 +712,6 @@ test_atomic_ops(PG_FUNCTION_ARGS) */ test_spinlock(); - test_atomic_spin_nest(); - PG_RETURN_BOOL(true); } @@ -1002,6 +723,13 @@ test_fdw_handler(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +PG_FUNCTION_INFO_V1(is_catalog_text_unique_index_oid); +Datum +is_catalog_text_unique_index_oid(PG_FUNCTION_ARGS) +{ + return IsCatalogTextUniqueIndexOid(PG_GETARG_OID(0)); +} + PG_FUNCTION_INFO_V1(test_support_func); Datum test_support_func(PG_FUNCTION_ARGS) @@ -1082,6 +810,56 @@ test_opclass_options_func(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +/* one-time tests for encoding infrastructure */ +PG_FUNCTION_INFO_V1(test_enc_setup); +Datum +test_enc_setup(PG_FUNCTION_ARGS) +{ + /* Test pg_encoding_set_invalid() */ + for (int i = 0; i < _PG_LAST_ENCODING_; i++) + { + char buf[2], + bigbuf[16]; + int len, + mblen, + valid; + + if (pg_encoding_max_length(i) == 1) + continue; + pg_encoding_set_invalid(i, buf); + len = strnlen(buf, 2); + if (len != 2) + elog(WARNING, + "official invalid string for encoding \"%s\" has length %d", + pg_enc2name_tbl[i].name, len); + mblen = pg_encoding_mblen(i, buf); + if (mblen != 2) + elog(WARNING, + "official invalid string for encoding \"%s\" has mblen %d", + pg_enc2name_tbl[i].name, mblen); + valid = pg_encoding_verifymbstr(i, buf, len); + if (valid != 0) + elog(WARNING, + "official invalid string for encoding \"%s\" has valid prefix of length %d", + pg_enc2name_tbl[i].name, valid); + valid = pg_encoding_verifymbstr(i, buf, 1); + if (valid != 0) + elog(WARNING, + "first byte of official invalid string for encoding \"%s\" has valid prefix of length %d", + pg_enc2name_tbl[i].name, valid); + memset(bigbuf, ' ', sizeof(bigbuf)); + bigbuf[0] = buf[0]; + bigbuf[1] = buf[1]; + valid = pg_encoding_verifymbstr(i, bigbuf, sizeof(bigbuf)); + if (valid != 0) + elog(WARNING, + "trailing data changed official invalid string for encoding \"%s\" to have valid prefix of length %d", + pg_enc2name_tbl[i].name, valid); + } + + PG_RETURN_VOID(); +} + /* * Call an encoding conversion or verification function. * @@ -1222,3 +1000,31 @@ binary_coercible(PG_FUNCTION_ARGS) PG_RETURN_BOOL(IsBinaryCoercible(srctype, targettype)); } + +/* + * Sanity checks for functions in relpath.h + */ +PG_FUNCTION_INFO_V1(test_relpath); +Datum +test_relpath(PG_FUNCTION_ARGS) +{ + RelPathStr rpath; + + /* + * Verify that PROCNUMBER_CHARS and MAX_BACKENDS stay in sync. + * Unfortunately I don't know how to express that in a way suitable for a + * static assert. + */ + if ((int) ceil(log10(MAX_BACKENDS)) != PROCNUMBER_CHARS) + elog(WARNING, "mismatch between MAX_BACKENDS and PROCNUMBER_CHARS"); + + /* verify that the max-length relpath is generated ok */ + rpath = GetRelationPath(OID_MAX, OID_MAX, OID_MAX, MAX_BACKENDS - 1, + INIT_FORKNUM); + + if (strlen(rpath.str) != REL_PATH_STR_MAXLEN) + elog(WARNING, "maximum length relpath is if length %zu instead of %zu", + strlen(rpath.str), REL_PATH_STR_MAXLEN); + + PG_RETURN_VOID(); +} diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index ca6d1bcfb7fa7..277b4b198ccc4 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -507,6 +507,38 @@ create temp table p_t1_2 partition of p_t1 for values in(2); -- Ensure we can remove non-PK columns for partitioned tables. explain (costs off) select * from p_t1 group by a,b,c,d; +create unique index t2_z_uidx on t2(z); + +-- Ensure we don't remove any columns from the GROUP BY for a unique +-- index on a NULLable column. +explain (costs off) select y,z from t2 group by y,z; + +-- Make the column NOT NULL and ensure we remove the redundant column +alter table t2 alter column z set not null; +explain (costs off) select y,z from t2 group by y,z; + +-- When there are multiple supporting unique indexes and the GROUP BY contains +-- columns to cover all of those, ensure we pick the index with the least +-- number of columns so that we can remove more columns from the GROUP BY. +explain (costs off) select x,y,z from t2 group by x,y,z; + +-- As above but try ordering the columns differently to ensure we get the +-- same result. +explain (costs off) select x,y,z from t2 group by z,x,y; + +-- Ensure we don't use a partial index as proof of functional dependency +drop index t2_z_uidx; +create index t2_z_uidx on t2 (z) where z > 0; +explain (costs off) select y,z from t2 group by y,z; + +-- A unique index defined as NULLS NOT DISTINCT does not need a supporting NOT +-- NULL constraint on the indexed columns. Ensure the redundant columns are +-- removed from the GROUP BY for such a table. +drop index t2_z_uidx; +alter table t2 alter column z drop not null; +create unique index t2_z_uidx on t2(z) nulls not distinct; +explain (costs off) select y,z from t2 group by y,z; + drop table t1 cascade; drop table t2; drop table t3; @@ -601,6 +633,25 @@ explain (costs off) select sum(two order by two) from tenk1; reset enable_presorted_aggregate; +-- +-- Test cases with FILTER clause +-- + +-- Ensure we presort when the aggregate contains plain Vars +explain (costs off) +select sum(two order by two) filter (where two > 1) from tenk1; + +-- Ensure we presort for RelabelType'd Vars +explain (costs off) +select string_agg(distinct f1, ',') filter (where length(f1) > 1) +from varchar_tbl; + +-- Ensure we don't presort when the aggregate's argument contains an +-- explicit cast. +explain (costs off) +select string_agg(distinct f1::varchar(2), ',') filter (where length(f1) > 1) +from varchar_tbl; + -- -- Test combinations of DISTINCT and/or ORDER BY -- @@ -747,7 +798,7 @@ select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok --- string_agg bytea tests +-- string_agg, min, max bytea tests create table bytea_test_table(v bytea); select string_agg(v, '') from bytea_test_table; @@ -762,6 +813,15 @@ select string_agg(v, '') from bytea_test_table; select string_agg(v, NULL) from bytea_test_table; select string_agg(v, decode('ee', 'hex')) from bytea_test_table; +select min(v) from bytea_test_table; +select max(v) from bytea_test_table; + +insert into bytea_test_table values(decode('ffff','hex')); +insert into bytea_test_table values(decode('aaaa','hex')); + +select min(v) from bytea_test_table; +select max(v) from bytea_test_table; + drop table bytea_test_table; -- Test parallel string_agg and array_agg @@ -811,11 +871,16 @@ select * from v_pagg_test order by y; -- Ensure parallel aggregation is actually being used. explain (costs off) select * from v_pagg_test order by y; -set max_parallel_workers_per_gather = 0; - -- Ensure results are the same without parallel aggregation. +set max_parallel_workers_per_gather = 0; select * from v_pagg_test order by y; +-- Check that we don't fail on anonymous record types. +set max_parallel_workers_per_gather = 2; +explain (costs off) +select array_dims(array_agg(s)) from (select * from pagg_test) s; +select array_dims(array_agg(s)) from (select * from pagg_test) s; + -- Clean up reset max_parallel_workers_per_gather; reset bytea_output; @@ -1223,13 +1288,13 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM (SELECT * FROM btg ORDER BY x, y, w, z) AS q1 GROUP BY w, x, z, y; --- Utilize the ordering of merge join to avoid a full Sort operation +-- Utilize the ordering of merge join to avoid a Sort operation SET enable_hashjoin = off; SET enable_nestloop = off; EXPLAIN (COSTS OFF) SELECT count(*) - FROM btg t1 JOIN btg t2 ON t1.z = t2.z AND t1.w = t2.w AND t1.x = t2.x - GROUP BY t1.x, t1.y, t1.z, t1.w; + FROM btg t1 JOIN btg t2 ON t1.w = t2.w AND t1.x = t2.x AND t1.z = t2.z + GROUP BY t1.w, t1.z, t1.x; RESET enable_nestloop; RESET enable_hashjoin; diff --git a/src/test/regress/sql/alter_generic.sql b/src/test/regress/sql/alter_generic.sql index de58d268d310c..5e20dc63337c9 100644 --- a/src/test/regress/sql/alter_generic.sql +++ b/src/test/regress/sql/alter_generic.sql @@ -310,7 +310,7 @@ ALTER OPERATOR FAMILY alt_opf4 USING btree ADD OPERATOR 6 < (int4, int2); -- ope ALTER OPERATOR FAMILY alt_opf4 USING btree ADD OPERATOR 0 < (int4, int2); -- operator number should be between 1 and 5 ALTER OPERATOR FAMILY alt_opf4 USING btree ADD OPERATOR 1 < ; -- operator without argument types ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 0 btint42cmp(int4, int2); -- invalid options parsing function -ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 6 btint42cmp(int4, int2); -- function number should be between 1 and 5 +ALTER OPERATOR FAMILY alt_opf4 USING btree ADD FUNCTION 7 btint42cmp(int4, int2); -- function number should be between 1 and 6 ALTER OPERATOR FAMILY alt_opf4 USING btree ADD STORAGE invalid_storage; -- Ensure STORAGE is not a part of ALTER OPERATOR FAMILY DROP OPERATOR FAMILY alt_opf4 USING btree; @@ -444,6 +444,9 @@ ALTER OPERATOR FAMILY alt_opf18 USING btree ADD -- Should fail. Not allowed to have cross-type equalimage function. ALTER OPERATOR FAMILY alt_opf18 USING btree ADD FUNCTION 4 (int4, int2) btequalimage(oid); +-- Should fail. Not allowed to have cross-type skip support function. +ALTER OPERATOR FAMILY alt_opf18 USING btree + ADD FUNCTION 6 (int4, int2) btint4skipsupport(internal); ALTER OPERATOR FAMILY alt_opf18 USING btree DROP FUNCTION 2 (int4, int4); DROP OPERATOR FAMILY alt_opf18 USING btree; diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 28cabc49e9fe0..5ce9d1e429f81 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -387,10 +387,12 @@ ALTER TABLE attmp3 validate constraint attmpconstr; -- Try a non-verified CHECK constraint ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds +ALTER TABLE attmp3 ADD CONSTRAINT b_greater_than_ten_not_enforced CHECK (b > 10) NOT ENFORCED; -- succeeds ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails DELETE FROM attmp3 WHERE NOT b > 10; ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds +ALTER TABLE attmp3 VALIDATE CONSTRAINT b_greater_than_ten_not_enforced; -- fail -- Test inherited NOT VALID CHECK constraints select * from attmp3; @@ -908,6 +910,20 @@ alter table atacc1 add constraint atacc1_constr_b_valid check(test_b is not null alter table atacc1 alter test_b set not null, alter test_a set not null; drop table atacc1; +-- not null not valid with partitions +CREATE TABLE atnnparted (id int, col1 int) PARTITION BY LIST (id); +ALTER TABLE atnnparted ADD CONSTRAINT dummy_constr NOT NULL id NOT VALID; +CREATE TABLE atnnpart1 (col1 int, id int); +ALTER TABLE atnnpart1 ADD CONSTRAINT another_constr NOT NULL id; +ALTER TABLE atnnpart1 ADD PRIMARY KEY (id); +ALTER TABLE atnnparted ATTACH PARTITION atnnpart1 FOR VALUES IN ('1'); +\d+ atnnpart* +BEGIN; +ALTER TABLE atnnparted VALIDATE CONSTRAINT dummy_constr; +\d+ atnnpart* +ROLLBACK; +-- leave a table in this state for the pg_upgrade test + -- test inheritance create table parent (a int); create table child (b varchar(255)) inherits (parent); @@ -920,14 +936,6 @@ insert into parent values (NULL); insert into child (a, b) values (NULL, 'foo'); alter table only parent alter a set not null; alter table child alter a set not null; -delete from parent; -alter table only parent alter a set not null; -insert into parent values (NULL); -alter table child alter a set not null; -insert into child (a, b) values (NULL, 'foo'); -delete from child; -alter table child alter a set not null; -insert into child (a, b) values (NULL, 'foo'); drop table child; drop table parent; @@ -1196,6 +1204,11 @@ alter table renameColumn add column w int; -- this should fail alter table only renameColumn add column x int; +-- this should work +alter table renameColumn add column x int check (x > 0) not enforced; + +-- this should fail +alter table renameColumn add column y int check (x > 0) not enforced enforced; -- Test corner cases in dropping of inherited columns @@ -1496,8 +1509,6 @@ select conname, obj_description(oid, 'pg_constraint') as desc alter table at_partitioned alter column name type varchar(127); --- Note: these tests currently show the wrong behavior for comments :-( - select relname, c.oid = oldoid as orig_oid, case relfilenode @@ -1799,6 +1810,8 @@ select * from my_locks order by 1; rollback; begin; +create function ttdummy () returns trigger language plpgsql as +$$ begin return new; end $$; create trigger ttdummy before delete or update on alterlock for each row @@ -2127,6 +2140,7 @@ DROP TABLE tt9; -- Check that comments on constraints and indexes are not lost at ALTER TABLE. CREATE TABLE comment_test ( id int, + constraint id_notnull_constraint not null id, positive_col int CHECK (positive_col > 0), indexed_col int, CONSTRAINT comment_test_pk PRIMARY KEY (id)); @@ -2136,6 +2150,7 @@ COMMENT ON COLUMN comment_test.id IS 'Column ''id'' on comment_test'; COMMENT ON INDEX comment_test_index IS 'Simple index on comment_test'; COMMENT ON CONSTRAINT comment_test_positive_col_check ON comment_test IS 'CHECK constraint on comment_test.positive_col'; COMMENT ON CONSTRAINT comment_test_pk ON comment_test IS 'PRIMARY KEY constraint of comment_test'; +COMMENT ON CONSTRAINT id_notnull_constraint ON comment_test IS 'NOT NULL constraint of comment_test'; COMMENT ON INDEX comment_test_pk IS 'Index backing the PRIMARY KEY of comment_test'; SELECT col_description('comment_test'::regclass, 1) as comment; @@ -2153,6 +2168,11 @@ ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE text; ALTER TABLE comment_test ALTER COLUMN positive_col SET DATA TYPE int; ALTER TABLE comment_test ALTER COLUMN positive_col SET DATA TYPE bigint; +-- Some error cases. +ALTER TABLE comment_test ALTER COLUMN xmin SET DATA TYPE x; +ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE x; +ALTER TABLE comment_test ALTER COLUMN id SET DATA TYPE int COLLATE "C"; + -- Check that the comments are intact. SELECT col_description('comment_test'::regclass, 1) as comment; SELECT indexrelid::regclass::text as index, obj_description(indexrelid, 'pg_class') as comment FROM pg_index where indrelid = 'comment_test'::regclass ORDER BY 1, 2; @@ -2349,6 +2369,9 @@ CREATE TABLE atnotnull1 (); ALTER TABLE atnotnull1 ADD COLUMN a INT, ALTER a SET NOT NULL; +ALTER TABLE atnotnull1 + ADD COLUMN b INT, + ADD NOT NULL b; ALTER TABLE atnotnull1 ADD COLUMN c INT, ADD PRIMARY KEY (c); @@ -2489,6 +2512,14 @@ ALTER TABLE list_parted ATTACH PARTITION part_1 FOR VALUES IN (1); SELECT attislocal, attinhcount FROM pg_attribute WHERE attrelid = 'part_1'::regclass AND attnum > 0; SELECT conislocal, coninhcount FROM pg_constraint WHERE conrelid = 'part_1'::regclass AND conname = 'check_a'; +-- check that NOT NULL NO INHERIT cannot be merged to a normal NOT NULL +CREATE TABLE part_fail (a int NOT NULL NO INHERIT, + b char(2) COLLATE "C", + CONSTRAINT check_a CHECK (a > 0) +); +ALTER TABLE list_parted ATTACH PARTITION part_fail FOR VALUES IN (2); +DROP TABLE part_fail; + -- check that the new partition won't overlap with an existing partition CREATE TABLE fail_part (LIKE part_1 INCLUDING CONSTRAINTS); ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1); @@ -2742,6 +2773,8 @@ DROP TABLE fail_part; -- check that the table is partitioned at all CREATE TABLE regular_table (a int); ALTER TABLE regular_table DETACH PARTITION any_name; +ALTER TABLE regular_table DETACH PARTITION any_name CONCURRENTLY; +ALTER TABLE regular_table DETACH PARTITION any_name FINALIZE; DROP TABLE regular_table; -- check that the partition being detached exists at all @@ -2813,22 +2846,23 @@ ALTER TABLE part_2 DROP COLUMN b; ALTER TABLE part_2 RENAME COLUMN b to c; ALTER TABLE part_2 ALTER COLUMN b TYPE text; --- cannot add/drop NOT NULL or check constraints to *only* the parent, when +-- cannot add NOT NULL or check constraints to *only* the parent, when -- partitions exist ALTER TABLE ONLY list_parted2 ALTER b SET NOT NULL; ALTER TABLE ONLY list_parted2 ADD CONSTRAINT check_b CHECK (b <> 'zz'); +-- dropping them is ok though ALTER TABLE list_parted2 ALTER b SET NOT NULL; ALTER TABLE ONLY list_parted2 ALTER b DROP NOT NULL; ALTER TABLE list_parted2 ADD CONSTRAINT check_b CHECK (b <> 'zz'); ALTER TABLE ONLY list_parted2 DROP CONSTRAINT check_b; +-- ... and the partitions should still have both +\d+ part_2 -- It's alright though, if no partitions are yet created CREATE TABLE parted_no_parts (a int) PARTITION BY LIST (a); ALTER TABLE ONLY parted_no_parts ALTER a SET NOT NULL; ALTER TABLE ONLY parted_no_parts ADD CONSTRAINT check_a CHECK (a > 0); -ALTER TABLE ONLY parted_no_parts ALTER a DROP NOT NULL; -ALTER TABLE ONLY parted_no_parts DROP CONSTRAINT check_a; DROP TABLE parted_no_parts; -- cannot drop inherited NOT NULL or check constraints from partition @@ -2836,6 +2870,12 @@ ALTER TABLE list_parted2 ALTER b SET NOT NULL, ADD CONSTRAINT check_a2 CHECK (a ALTER TABLE part_2 ALTER b DROP NOT NULL; ALTER TABLE part_2 DROP CONSTRAINT check_a2; +-- can't drop NOT NULL from under an invalid PK +CREATE TABLE list_parted3 (a int NOT NULL) PARTITION BY LIST (a); +CREATE TABLE list_parted3_1 PARTITION OF list_parted3 FOR VALUES IN (1); +ALTER TABLE ONLY list_parted3 ADD PRIMARY KEY (a); +ALTER TABLE ONLY list_parted3 DROP CONSTRAINT list_parted3_a_not_null; + -- Doesn't make sense to add NO INHERIT constraints on partitioned tables ALTER TABLE list_parted2 add constraint check_b2 check (b <> 'zz') NO INHERIT; @@ -2856,7 +2896,7 @@ ALTER TABLE list_parted DROP COLUMN b; SELECT * FROM list_parted; -- cleanup -DROP TABLE list_parted, list_parted2, range_parted; +DROP TABLE list_parted, list_parted2, range_parted, list_parted3; DROP TABLE fail_def_part; DROP TABLE hash_parted; diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 47058dfde5092..47d62c1d38d28 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -713,6 +713,28 @@ select array_replace(array['AB',NULL,'CDE'],NULL,'12'); select array(select array[i,i/2] from generate_series(1,5) i); select array(select array['Hello', i::text] from generate_series(9,11) i); +-- int2vector and oidvector should be treated as scalar types for this purpose +select pg_typeof(array(select '11 22 33'::int2vector from generate_series(1,5))); +select array(select '11 22 33'::int2vector from generate_series(1,5)); +select unnest(array(select '11 22 33'::int2vector from generate_series(1,5))); +select pg_typeof(array(select '11 22 33'::oidvector from generate_series(1,5))); +select array(select '11 22 33'::oidvector from generate_series(1,5)); +select unnest(array(select '11 22 33'::oidvector from generate_series(1,5))); + +-- array[] should do the same +select pg_typeof(array['11 22 33'::int2vector]); +select array['11 22 33'::int2vector]; +select pg_typeof(unnest(array['11 22 33'::int2vector])); +select unnest(array['11 22 33'::int2vector]); +select pg_typeof(unnest('11 22 33'::int2vector)); +select unnest('11 22 33'::int2vector); +select pg_typeof(array['11 22 33'::oidvector]); +select array['11 22 33'::oidvector]; +select pg_typeof(unnest(array['11 22 33'::oidvector])); +select unnest(array['11 22 33'::oidvector]); +select pg_typeof(unnest('11 22 33'::oidvector)); +select unnest('11 22 33'::oidvector); + -- Insert/update on a column that is array of composite create temp table t1 (f1 int8_tbl[]); @@ -827,3 +849,46 @@ SELECT array_dims(array_sample('[-1:2][2:3]={{1,2},{3,NULL},{5,6},{7,8}}'::int[] SELECT array_dims(array_sample('{{{1,2},{3,NULL}},{{5,6},{7,8}},{{9,10},{11,12}}}'::int[], 2)); SELECT array_sample('{1,2,3,4,5,6}'::int[], -1); -- fail SELECT array_sample('{1,2,3,4,5,6}'::int[], 7); --fail + +-- array_reverse +SELECT array_reverse('{}'::int[]); +SELECT array_reverse('{1}'::int[]); +SELECT array_reverse('{1,2}'::int[]); +SELECT array_reverse('{1,2,3,NULL,4,5,6}'::int[]); +SELECT array_reverse('{{1,2},{3,4},{5,6},{7,8}}'::int[]); + +-- array_sort +SELECT array_sort('{}'::int[]); +SELECT array_sort('{1}'::int[]); +SELECT array_sort('{1,3,5,2,4,6}'::int[]); +SELECT array_sort('{1.1,3.3,5.5,2.2,4.4,6.6}'::numeric[]); +SELECT array_sort('{foo,bar,CCC,Abc,bbc}'::text[] COLLATE "C"); +SELECT array_sort('{foo,bar,null,CCC,Abc,bbc}'::text[] COLLATE "C"); +SELECT array_sort(ARRAY(SELECT '1 4'::int2vector UNION ALL SELECT '1 2'::int2vector)); + +-- array_sort with order specified +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true); +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false); + +-- array_sort with order and nullsfirst flag specified +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true, true); +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], true, false); +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false, true); +SELECT array_sort('{1.1,3.3,5.5,2.2,null,4.4,6.6}'::float8[], false, false); + +-- multidimensional array tests +SELECT array_sort('{{1}}'::int[]); +SELECT array_sort(ARRAY[[2,4],[2,1],[6,5]]); +SELECT array_sort('{{"1 2","3 4"}, {"1 -2","-1 4"}}'::int2vector[]); + +-- no ordering operator tests +SELECT array_sort('{1}'::xid[]); -- no error because no sort is required +SELECT array_sort('{1,2,3}'::xid[]); +SELECT array_sort('{{1,2,3},{2,3,4}}'::xid[]); + +-- bounds preservation tests +SELECT array_sort(a) FROM (VALUES ('[10:12][20:21]={{1,2},{10,20},{3,4}}'::int[])) v(a); +SELECT array_sort(a) FROM (VALUES ('[-1:0]={7,1}'::int[])) v(a); +SELECT array_sort(a) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); +SELECT array_sort(a [-1:0]) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); +SELECT array_sort(a [-1:0][20:20]) FROM (VALUES ('[-2:0][20:21]={{1,2},{10,20},{1,-4}}'::int[])) v(a); diff --git a/src/test/regress/sql/bitmapops.sql b/src/test/regress/sql/bitmapops.sql index 498f4721b5130..1b175f6ff9667 100644 --- a/src/test/regress/sql/bitmapops.sql +++ b/src/test/regress/sql/bitmapops.sql @@ -12,7 +12,7 @@ -- That allows us to test all the different combinations of -- lossy and non-lossy pages with the minimum amount of data -CREATE TABLE bmscantest (a int, b int, t text); +CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false); INSERT INTO bmscantest SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' @@ -29,8 +29,14 @@ set enable_seqscan=false; -- Lower work_mem to trigger use of lossy bitmaps set work_mem = 64; +-- Test bitmap-and without the skip fetch optimization. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + +-- Test that we return correct results when using the skip fetch optimization +-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling +-- the optimization. +VACUUM (FREEZE) bmscantest; --- Test bitmap-and. SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; -- Test bitmap-or. diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql index 695cfad4bea3a..7ea97f47c8d0e 100644 --- a/src/test/regress/sql/brin.sql +++ b/src/test/regress/sql/brin.sql @@ -510,6 +510,17 @@ SELECT * FROM brintest_3 WHERE b < '0'; DROP TABLE brintest_3; RESET enable_seqscan; +-- test parallel build with immutable function. +CREATE TABLE brintest_expr (n int); +CREATE FUNCTION brintest_func() RETURNS int LANGUAGE sql IMMUTABLE RETURN 0; +BEGIN; +SET LOCAL min_parallel_table_scan_size = 0; +SET LOCAL max_parallel_maintenance_workers = 4; +CREATE INDEX brintest_expr_idx ON brintest_expr USING brin (brintest_func()); +COMMIT; +DROP TABLE brintest_expr; +DROP FUNCTION brintest_func(); + -- test an unlogged table, mostly to get coverage of brinbuildempty CREATE UNLOGGED TABLE brintest_unlogged (n numrange); CREATE INDEX brinidx_unlogged ON brintest_unlogged USING brin (n); diff --git a/src/test/regress/sql/brin_multi.sql b/src/test/regress/sql/brin_multi.sql index 55349b4e1fd12..dda9fb73e0c08 100644 --- a/src/test/regress/sql/brin_multi.sql +++ b/src/test/regress/sql/brin_multi.sql @@ -619,7 +619,7 @@ CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_ SET enable_seqscan = off; -- make sure the ranges were built correctly and 2023-01-01 eliminates all -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; DROP TABLE brin_date_test; @@ -636,10 +636,10 @@ CREATE INDEX ON brin_timestamp_test USING brin (a timestamp_minmax_multi_ops) WI SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_timestamp_test WHERE a = '2023-01-01'::timestamp; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_timestamp_test WHERE a = '1900-01-01'::timestamp; DROP TABLE brin_timestamp_test; @@ -655,10 +655,10 @@ CREATE INDEX ON brin_date_test USING brin (a date_minmax_multi_ops) WITH (pages_ SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '2023-01-01'::date; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_date_test WHERE a = '1900-01-01'::date; DROP TABLE brin_date_test; @@ -676,10 +676,10 @@ CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '30 years'::interval; DROP TABLE brin_interval_test; @@ -695,10 +695,10 @@ CREATE INDEX ON brin_interval_test USING brin (a interval_minmax_multi_ops) WITH SET enable_seqscan = off; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '-30 years'::interval; -EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF) +EXPLAIN (ANALYZE, TIMING OFF, COSTS OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM brin_interval_test WHERE a = '30 years'::interval; DROP TABLE brin_interval_test; diff --git a/src/test/regress/sql/btree_index.sql b/src/test/regress/sql/btree_index.sql index 0d2a33f37053c..68c61dbc7d19c 100644 --- a/src/test/regress/sql/btree_index.sql +++ b/src/test/regress/sql/btree_index.sql @@ -110,6 +110,85 @@ SELECT b.* FROM bt_f8_heap b WHERE b.seqno = '4500'::float8; +-- +-- Add coverage of RowCompare quals whose row omits a column ("proargtypes") +-- that's after the first column, but before the final column. The scan's +-- initial positioning strategy must become >= here (it's not the > strategy, +-- since the absence of "proargtypes" makes that tighter constraint unsafe). +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) > ('abs', 0) +ORDER BY proname, proargtypes, pronamespace LIMIT 1; + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) > ('abs', 0) +ORDER BY proname, proargtypes, pronamespace LIMIT 1; + +-- +-- Similar to the previous test case, but this time it's a backwards scan +-- using a < RowCompare. Must use the <= strategy (and not the < strategy). +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) < ('abs', 1_000_000) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1; + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE (proname, pronamespace) < ('abs', 1_000_000) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC LIMIT 1; + +-- +-- Add coverage for RowCompare quals whose rhs row has a NULL that ends scan +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL) +ORDER BY proname, proargtypes, pronamespace; + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) < ('abs', NULL) +ORDER BY proname, proargtypes, pronamespace; + +-- +-- Add coverage for backwards scan RowCompare quals whose rhs row has a NULL +-- that ends scan +-- +explain (costs off) +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC; + +SELECT proname, proargtypes, pronamespace + FROM pg_proc + WHERE proname = 'abs' AND (proname, proargtypes) > ('abs', NULL) +ORDER BY proname DESC, proargtypes DESC, pronamespace DESC; + +-- +-- Add coverage for recheck of > key following array advancement on previous +-- (left sibling) page that used a high key whose attribute value corresponding +-- to the > key was -inf (due to being truncated when the high key was created). +-- +-- XXX This relies on the assumption that tenk1_thous_tenthous has a truncated +-- high key "(183, -inf)" on the first page that we'll scan. The test will only +-- provide useful coverage when the default 8K BLCKSZ is in use. +-- +explain (costs off) +SELECT thousand, tenthous + FROM tenk1 + WHERE thousand IN (182, 183) AND tenthous > 7550; + +SELECT thousand, tenthous + FROM tenk1 + WHERE thousand IN (182, 183) AND tenthous > 7550; + -- -- Add coverage for optimization of backwards scan index descents -- @@ -248,6 +327,27 @@ alter table btree_tall_tbl alter COLUMN t set storage plain; create index btree_tall_idx on btree_tall_tbl (t, id) with (fillfactor = 10); insert into btree_tall_tbl select g, repeat('x', 250) from generate_series(1, 130) g; +insert into btree_tall_tbl select g, NULL +from generate_series(50, 60) g; + +-- +-- Test for skip scan with type that lacks skip support (text) +-- +set enable_seqscan to false; +set enable_bitmapscan to false; + +-- Forwards scan +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t, id; +explain (costs off) +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t, id; + +-- Backwards scan +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t DESC, id DESC; +explain (costs off) +SELECT id FROM btree_tall_tbl WHERE id = 55 ORDER BY t DESC, id DESC; + +reset enable_seqscan; +reset enable_bitmapscan; -- -- Test for multilevel page deletion @@ -272,6 +372,17 @@ INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,1000) i; -- Test unsupported btree opclass parameters create index on btree_tall_tbl (id int4_ops(foo=1)); +-- test parallel build with immutable function. +CREATE TABLE btree_test_expr (n int); +CREATE FUNCTION btree_test_func() RETURNS int LANGUAGE sql IMMUTABLE RETURN 0; +BEGIN; +SET LOCAL min_parallel_table_scan_size = 0; +SET LOCAL max_parallel_maintenance_workers = 4; +CREATE INDEX btree_test_expr_idx ON btree_test_expr USING btree (btree_test_func()); +COMMIT; +DROP TABLE btree_test_expr; +DROP FUNCTION btree_test_func(); + -- Test case of ALTER INDEX with abuse of column names for indexes. -- This grammar is not officially supported, but the parser allows it. CREATE INDEX btree_tall_idx2 ON btree_tall_tbl (id); diff --git a/src/test/regress/sql/case.sql b/src/test/regress/sql/case.sql index 83fe43be6b84f..388d4c6f52835 100644 --- a/src/test/regress/sql/case.sql +++ b/src/test/regress/sql/case.sql @@ -242,6 +242,11 @@ SELECT CASE make_ad(1,2) WHEN array[1,2]::arrdomain THEN 'right' END; +-- While we're here, also test handling of a NULLIF arg that is a read/write +-- object (bug #18722) + +SELECT NULLIF(make_ad(1,2), array[2,3]::arrdomain); + ROLLBACK; -- Test interaction of CASE with ArrayCoerceExpr (bug #15471) diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql index 80f28a97d785b..dbc190227d022 100644 --- a/src/test/regress/sql/collate.icu.utf8.sql +++ b/src/test/regress/sql/collate.icu.utf8.sql @@ -116,6 +116,11 @@ SELECT a, lower(x COLLATE "C"), lower(y COLLATE "C") FROM collate_test10; SELECT a, x, y FROM collate_test10 ORDER BY lower(y), a; +SELECT lower('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "en-x-icu"); +SELECT casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "en-x-icu"); +SELECT lower('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "tr-x-icu"); +SELECT casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' COLLATE "tr-x-icu"); + -- LIKE/ILIKE SELECT * FROM collate_test1 WHERE b LIKE 'abc'; @@ -514,13 +519,36 @@ CREATE COLLATION testcoll_rulesx (provider = icu, locale = '', rules = '!!wrong! CREATE COLLATION ctest_det (provider = icu, locale = '', deterministic = true); CREATE COLLATION ctest_nondet (provider = icu, locale = '', deterministic = false); +SELECT 'abc' LIKE 'abc' COLLATE ctest_det; +SELECT 'abc' LIKE 'a\bc' COLLATE ctest_det; + +SELECT 'abc' LIKE 'abc' COLLATE ctest_nondet; +SELECT 'abc' LIKE 'a\bc' COLLATE ctest_nondet; + CREATE TABLE test6 (a int, b text); -- same string in different normal forms -INSERT INTO test6 VALUES (1, U&'\00E4bc'); -INSERT INTO test6 VALUES (2, U&'\0061\0308bc'); +INSERT INTO test6 VALUES (1, U&'zy\00E4bc'); +INSERT INTO test6 VALUES (2, U&'zy\0061\0308bc'); SELECT * FROM test6; -SELECT * FROM test6 WHERE b = 'äbc' COLLATE ctest_det; -SELECT * FROM test6 WHERE b = 'äbc' COLLATE ctest_nondet; +SELECT * FROM test6 WHERE b = 'zyäbc' COLLATE ctest_det; +SELECT * FROM test6 WHERE b = 'zyäbc' COLLATE ctest_nondet; + +SELECT strpos(b COLLATE ctest_det, 'bc') FROM test6; +SELECT strpos(b COLLATE ctest_nondet, 'bc') FROM test6; + +SELECT replace(b COLLATE ctest_det, U&'\00E4b', 'X') FROM test6; +SELECT replace(b COLLATE ctest_nondet, U&'\00E4b', 'X') FROM test6; + +SELECT a, split_part(b COLLATE ctest_det, U&'\00E4b', 2) FROM test6; +SELECT a, split_part(b COLLATE ctest_nondet, U&'\00E4b', 2) FROM test6; +SELECT a, split_part(b COLLATE ctest_det, U&'\00E4b', -1) FROM test6; +SELECT a, split_part(b COLLATE ctest_nondet, U&'\00E4b', -1) FROM test6; + +SELECT a, string_to_array(b COLLATE ctest_det, U&'\00E4b') FROM test6; +SELECT a, string_to_array(b COLLATE ctest_nondet, U&'\00E4b') FROM test6; + +SELECT * FROM test6 WHERE b LIKE 'zyäbc' COLLATE ctest_det; +SELECT * FROM test6 WHERE b LIKE 'zyäbc' COLLATE ctest_nondet; -- same with arrays CREATE TABLE test6a (a int, b text[]); @@ -536,6 +564,10 @@ CREATE COLLATION case_insensitive (provider = icu, locale = '@colStrength=second SELECT 'abc' <= 'ABC' COLLATE case_sensitive, 'abc' >= 'ABC' COLLATE case_sensitive; SELECT 'abc' <= 'ABC' COLLATE case_insensitive, 'abc' >= 'ABC' COLLATE case_insensitive; +-- tests with array_sort +SELECT array_sort('{a,B}'::text[] COLLATE case_insensitive); +SELECT array_sort('{a,B}'::text[] COLLATE "C"); + -- test language tags CREATE COLLATION lt_insensitive (provider = icu, locale = 'en-u-ks-level1', deterministic = false); SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; @@ -637,14 +669,14 @@ SELECT string_to_array('ABCDEFGHI'::char(9) COLLATE case_insensitive, NULL, 'b') -- This tests the issue described in match_pattern_prefix(). In the -- absence of that check, the case_insensitive tests below would -- return no rows where they should logically return one. -CREATE TABLE test4c (x text COLLATE "C"); +CREATE TABLE test4c (x text COLLATE case_insensitive); INSERT INTO test4c VALUES ('abc'); CREATE INDEX ON test4c (x); SET enable_seqscan = off; SELECT x FROM test4c WHERE x LIKE 'ABC' COLLATE case_sensitive; -- ok, no rows SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_sensitive; -- ok, no rows -SELECT x FROM test4c WHERE x LIKE 'ABC' COLLATE case_insensitive; -- error -SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_insensitive; -- error +SELECT x FROM test4c WHERE x LIKE 'ABC' COLLATE case_insensitive; -- ok +SELECT x FROM test4c WHERE x LIKE 'ABC%' COLLATE case_insensitive; -- ok RESET enable_seqscan; -- Unicode special case: different variants of Greek lower case sigma. @@ -687,39 +719,92 @@ SELECT * FROM test4 WHERE b = 'cote' COLLATE ignore_accents; SELECT * FROM test4 WHERE b = 'Cote' COLLATE ignore_accents; -- still case-sensitive SELECT * FROM test4 WHERE b = 'Cote' COLLATE case_insensitive; --- foreign keys (should use collation of primary key) - --- PK is case-sensitive, FK is case-insensitive +CREATE TABLE test4nfd (a int, b text); +INSERT INTO test4nfd VALUES (1, 'cote'), (2, 'côte'), (3, 'coté'), (4, 'côté'); +UPDATE test4nfd SET b = normalize(b, nfd); + +-- This shows why replace should be greedy. Otherwise, in the NFD +-- case, the match would stop before the decomposed accents, which +-- would leave the accents in the results. +SELECT a, b, replace(b COLLATE ignore_accents, 'co', 'ma') FROM test4; +SELECT a, b, replace(b COLLATE ignore_accents, 'co', 'ma') FROM test4nfd; + +-- This is a tricky one. A naive implementation would first test +-- \00E4 matches \0061, which is true under ignore_accents, but then +-- the rest of the string won't match anymore. Therefore, the +-- algorithm has to test whether the rest of the string matches, and +-- if not try matching \00E4 against a longer substring like +-- \0061\0308, which will then work out. +SELECT U&'\0061\0308bc' LIKE U&'\00E4_c' COLLATE ignore_accents; +-- and in reverse: +SELECT U&'\00E4bc' LIKE U&'\0061\0308_c' COLLATE ignore_accents; +-- inner % matches b: +SELECT U&'\0061\0308bc' LIKE U&'\00E4%c' COLLATE ignore_accents; +-- inner %% matches b then zero: +SELECT U&'\0061\0308bc' LIKE U&'\00E4%%c' COLLATE ignore_accents; +-- inner %% matches b then zero: +SELECT U&'cb\0061\0308' LIKE U&'c%%\00E4' COLLATE ignore_accents; +-- trailing _ matches two codepoints that form one grapheme: +SELECT U&'cb\0061\0308' LIKE U&'cb_' COLLATE ignore_accents; +-- trailing __ matches two codepoints that form one grapheme: +SELECT U&'cb\0061\0308' LIKE U&'cb__' COLLATE ignore_accents; +-- leading % matches zero: +SELECT U&'\0061\0308bc' LIKE U&'%\00E4bc' COLLATE ignore_accents; +-- leading % matches zero (with later %): +SELECT U&'\0061\0308bc' LIKE U&'%\00E4%c' COLLATE ignore_accents; +-- trailing % matches zero: +SELECT U&'\0061\0308bc' LIKE U&'\00E4bc%' COLLATE ignore_accents; +-- trailing % matches zero (with previous %): +SELECT U&'\0061\0308bc' LIKE U&'\00E4%c%' COLLATE ignore_accents; +-- _ versus two codepoints that form one grapheme: +SELECT U&'\0061\0308bc' LIKE U&'_bc' COLLATE ignore_accents; +-- (actually this matches because) +SELECT U&'\0308bc' = 'bc' COLLATE ignore_accents; +-- __ matches two codepoints that form one grapheme: +SELECT U&'\0061\0308bc' LIKE U&'__bc' COLLATE ignore_accents; +-- _ matches one codepoint that forms half a grapheme: +SELECT U&'\0061\0308bc' LIKE U&'_\0308bc' COLLATE ignore_accents; +-- doesn't match because \00e4 doesn't match only \0308 +SELECT U&'\0061\0308bc' LIKE U&'_\00e4bc' COLLATE ignore_accents; +-- escape character at end of pattern +SELECT 'foox' LIKE 'foo\' COLLATE ignore_accents; + +-- foreign keys (mixing different nondeterministic collations not allowed) CREATE TABLE test10pk (x text COLLATE case_sensitive PRIMARY KEY); -INSERT INTO test10pk VALUES ('abc'), ('def'), ('ghi'); -CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -INSERT INTO test10fk VALUES ('abc'); -- ok -INSERT INTO test10fk VALUES ('ABC'); -- error -INSERT INTO test10fk VALUES ('xyz'); -- error -SELECT * FROM test10pk; -SELECT * FROM test10fk; --- restrict update even though the values are "equal" in the FK table -UPDATE test10fk SET x = 'ABC' WHERE x = 'abc'; -- error -SELECT * FROM test10fk; -DELETE FROM test10pk WHERE x = 'abc'; -SELECT * FROM test10pk; -SELECT * FROM test10fk; - --- PK is case-insensitive, FK is case-sensitive +CREATE TABLE test10fk (x text COLLATE case_insensitive REFERENCES test10pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -- error + CREATE TABLE test11pk (x text COLLATE case_insensitive PRIMARY KEY); -INSERT INTO test11pk VALUES ('abc'), ('def'), ('ghi'); -CREATE TABLE test11fk (x text COLLATE case_sensitive REFERENCES test11pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -INSERT INTO test11fk VALUES ('abc'); -- ok -INSERT INTO test11fk VALUES ('ABC'); -- ok -INSERT INTO test11fk VALUES ('xyz'); -- error -SELECT * FROM test11pk; -SELECT * FROM test11fk; --- cascade update even though the values are "equal" in the PK table -UPDATE test11pk SET x = 'ABC' WHERE x = 'abc'; -SELECT * FROM test11fk; -DELETE FROM test11pk WHERE x = 'abc'; -SELECT * FROM test11pk; -SELECT * FROM test11fk; +CREATE TABLE test11fk (x text COLLATE case_sensitive REFERENCES test11pk (x) ON UPDATE CASCADE ON DELETE CASCADE); -- error + +-- foreign key actions +-- Some of the behaviors are most easily visible with a +-- case-insensitive collation. +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE NO ACTION); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- ok +SELECT * FROM test12pk; +SELECT * FROM test12fk; -- no updates here +DROP TABLE test12pk, test12fk; + +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE RESTRICT); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- restrict violation +SELECT * FROM test12pk; +SELECT * FROM test12fk; +DROP TABLE test12pk, test12fk; + +CREATE TABLE test12pk (x text COLLATE case_insensitive PRIMARY KEY); +CREATE TABLE test12fk (a int, b text COLLATE case_insensitive REFERENCES test12pk (x) ON UPDATE CASCADE); +INSERT INTO test12pk VALUES ('abc'); +INSERT INTO test12fk VALUES (1, 'abc'), (2, 'ABC'); +UPDATE test12pk SET x = 'ABC' WHERE x = 'abc'; -- ok +SELECT * FROM test12pk; +SELECT * FROM test12fk; -- was updated +DROP TABLE test12pk, test12fk; -- partitioning CREATE TABLE test20 (a int, b text COLLATE case_insensitive) PARTITION BY LIST (b); @@ -796,6 +881,122 @@ INSERT INTO test33 VALUES (2, 'DEF'); -- they end up in the same partition (but it's platform-dependent which one) SELECT (SELECT count(*) FROM test33_0) <> (SELECT count(*) FROM test33_1); +-- +-- Bug #18568 +-- +-- Partitionwise aggregate (full or partial) should not be used when a +-- partition key's collation doesn't match that of the GROUP BY column it is +-- matched with. +SET max_parallel_workers_per_gather TO 0; +SET enable_incremental_sort TO off; + +CREATE TABLE pagg_tab3 (a text, c text collate case_insensitive) PARTITION BY LIST(c collate "C"); +CREATE TABLE pagg_tab3_p1 PARTITION OF pagg_tab3 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab3_p2 PARTITION OF pagg_tab3 FOR VALUES IN ('B', 'A'); +INSERT INTO pagg_tab3 SELECT i % 4 + 1, substr('abAB', (i % 4) + 1 , 1) FROM generate_series(0, 19) i; +ANALYZE pagg_tab3; + +SET enable_partitionwise_aggregate TO false; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + +-- No "full" partitionwise aggregation allowed, though "partial" is allowed. +SET enable_partitionwise_aggregate TO true; +EXPLAIN (COSTS OFF) +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; +SELECT upper(c collate case_insensitive), count(c) FROM pagg_tab3 GROUP BY c collate case_insensitive ORDER BY 1; + +-- OK to use full partitionwise aggregate after changing the GROUP BY column's +-- collation to be the same as that of the partition key. +EXPLAIN (COSTS OFF) +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; +SELECT c collate "C", count(c) FROM pagg_tab3 GROUP BY c collate "C" ORDER BY 1; + +-- Partitionwise join should not be allowed too when the collation used by the +-- join keys doesn't match the partition key collation. +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +SET enable_partitionwise_join TO true; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +-- OK when the join clause uses the same collation as the partition key. +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; +SELECT t1.c COLLATE "C", count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab3 t2 ON t1.c = t2.c COLLATE "C" GROUP BY t1.c COLLATE "C" ORDER BY t1.c COLLATE "C"; + +-- Few other cases where the joined partition keys are matched via equivalence +-- class, not a join restriction clause. + +-- Collations of joined columns match, but the partition keys collation is different +SET enable_partitionwise_join TO true; +CREATE TABLE pagg_tab4 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (b collate "C"); +CREATE TABLE pagg_tab4_p1 PARTITION OF pagg_tab4 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab4_p2 PARTITION OF pagg_tab4 FOR VALUES IN ('B', 'A'); +INSERT INTO pagg_tab4 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 11) i; +ANALYZE pagg_tab4; + +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab4 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab3 t1 JOIN pagg_tab4 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +-- OK when the partition key collation is same as that of the join columns +CREATE TABLE pagg_tab5 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (c collate case_insensitive); +CREATE TABLE pagg_tab5_p1 PARTITION OF pagg_tab5 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab5_p2 PARTITION OF pagg_tab5 FOR VALUES IN ('c', 'd'); +INSERT INTO pagg_tab5 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +INSERT INTO pagg_tab5 (b, c) SELECT substr('cdCD', (i % 4) + 1 , 1), substr('cdCD', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +ANALYZE pagg_tab5; + +CREATE TABLE pagg_tab6 (c text collate case_insensitive, b text collate case_insensitive) PARTITION BY LIST (b collate case_insensitive); +CREATE TABLE pagg_tab6_p1 PARTITION OF pagg_tab6 FOR VALUES IN ('a', 'b'); +CREATE TABLE pagg_tab6_p2 PARTITION OF pagg_tab6 FOR VALUES IN ('c', 'd'); +INSERT INTO pagg_tab6 (b, c) SELECT substr('abAB', (i % 4) + 1 , 1), substr('abAB', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +INSERT INTO pagg_tab6 (b, c) SELECT substr('cdCD', (i % 4) + 1 , 1), substr('cdCD', (i % 2) + 1 , 1) FROM generate_series(0, 5) i; +ANALYZE pagg_tab6; + +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +SET enable_partitionwise_join TO false; +EXPLAIN (COSTS OFF) +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; +SELECT t1.c, count(t2.c) FROM pagg_tab5 t1 JOIN pagg_tab6 t2 ON t1.c = t2.c AND t1.c = t2.b GROUP BY 1 ORDER BY t1.c COLLATE "C"; + +DROP TABLE pagg_tab3; +DROP TABLE pagg_tab4; +DROP TABLE pagg_tab5; +DROP TABLE pagg_tab6; + +RESET enable_partitionwise_aggregate; +RESET max_parallel_workers_per_gather; +RESET enable_incremental_sort; + +-- virtual generated columns +CREATE TABLE t5 ( + a int, + b text collate "C", + c text collate "C" GENERATED ALWAYS AS (b COLLATE case_insensitive) +); +INSERT INTO t5 (a, b) values (1, 'D1'), (2, 'D2'), (3, 'd1'); +-- Collation of c should be the one defined for the column ("C"), not +-- the one of the generation expression. (Note that we cannot just +-- test with, say, using COLLATION FOR, because the collation of +-- function calls is already determined in the parser before +-- rewriting.) +SELECT * FROM t5 ORDER BY c ASC, a ASC; + -- cleanup RESET search_path; diff --git a/src/test/regress/sql/collate.utf8.sql b/src/test/regress/sql/collate.utf8.sql index 1f5f9ef491d03..d6d14220ab342 100644 --- a/src/test/regress/sql/collate.utf8.sql +++ b/src/test/regress/sql/collate.utf8.sql @@ -11,6 +11,21 @@ SELECT getdatabaseencoding() <> 'UTF8' AS skip_test \gset SET client_encoding TO UTF8; +-- +-- Test builtin "C" +-- +CREATE COLLATION regress_builtin_c ( + provider = builtin, locale = 'C'); + +-- non-ASCII characters are unchanged +SELECT LOWER(U&'\00C1' COLLATE regress_builtin_c) = U&'\00C1'; +SELECT UPPER(U&'\00E1' COLLATE regress_builtin_c) = U&'\00E1'; + +-- non-ASCII characters are not alphabetic +SELECT U&'\00C1\00E1' !~ '[[:alpha:]]' COLLATE regress_builtin_c; + +DROP COLLATION regress_builtin_c; + -- -- Test PG_C_UTF8 -- @@ -30,6 +45,7 @@ INSERT INTO test_pg_c_utf8 VALUES ('abc DEF 123abc'), ('ábc sßs ßss DÉF'), ('DŽxxDŽ džxxDž Džxxdž'), + (U&'Λλ 1a \FF11a'), ('ȺȺȺ'), ('ⱥⱥⱥ'), ('ⱥȺ'); @@ -65,3 +81,70 @@ SELECT 'xAb' ~* '[W-Y]' COLLATE PG_C_UTF8; SELECT 'xAb' !~* '[c-d]' COLLATE PG_C_UTF8; SELECT 'Δ' ~* '[γ-λ]' COLLATE PG_C_UTF8; SELECT 'δ' ~* '[Γ-Λ]' COLLATE PG_C_UTF8; -- same as above with cases reversed + +-- case folding +select casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' collate PG_C_UTF8); + +-- +-- Test PG_UNICODE_FAST +-- + +CREATE COLLATION regress_pg_unicode_fast ( + provider = builtin, locale = 'unicode'); -- fails +CREATE COLLATION regress_pg_unicode_fast ( + provider = builtin, locale = 'PG_UNICODE_FAST'); + +CREATE TABLE test_pg_unicode_fast ( + t TEXT COLLATE PG_UNICODE_FAST +); +INSERT INTO test_pg_unicode_fast VALUES + ('abc DEF 123abc'), + ('ábc sßs ßss DÉF'), + ('DŽxxDŽ džxxDž Džxxdž'), + (U&'Λλ 1a \FF11a'), + ('ȺȺȺ'), + ('ⱥⱥⱥ'), + ('ⱥȺ'); + +SELECT + t, lower(t), initcap(t), upper(t), + length(convert_to(t, 'UTF8')) AS t_bytes, + length(convert_to(lower(t), 'UTF8')) AS lower_t_bytes, + length(convert_to(initcap(t), 'UTF8')) AS initcap_t_bytes, + length(convert_to(upper(t), 'UTF8')) AS upper_t_bytes + FROM test_pg_unicode_fast; + +DROP TABLE test_pg_unicode_fast; + +-- test Final_Sigma +SELECT lower('ΑΣ' COLLATE PG_UNICODE_FAST); -- 0391 03A3 +SELECT lower('ΑΣ0' COLLATE PG_UNICODE_FAST); -- 0391 03A3 0030 +SELECT lower('ἈΣ̓' COLLATE PG_UNICODE_FAST); -- 0391 0343 03A3 0343 +SELECT lower('ᾼΣͅ' COLLATE PG_UNICODE_FAST); -- 0391 0345 03A3 0345 + +-- test !Final_Sigma +SELECT lower('Σ' COLLATE PG_UNICODE_FAST); -- 03A3 +SELECT lower('0Σ' COLLATE PG_UNICODE_FAST); -- 0030 03A3 +SELECT lower('ΑΣΑ' COLLATE PG_UNICODE_FAST); -- 0391 03A3 0391 +SELECT lower('ἈΣ̓Α' COLLATE PG_UNICODE_FAST); -- 0391 0343 03A3 0343 0391 +SELECT lower('ᾼΣͅΑ' COLLATE PG_UNICODE_FAST); -- 0391 0345 03A3 0345 0391 + +-- properties + +SELECT 'xyz' ~ '[[:alnum:]]' COLLATE PG_UNICODE_FAST; +SELECT 'xyz' !~ '[[:upper:]]' COLLATE PG_UNICODE_FAST; +SELECT '@' !~ '[[:alnum:]]' COLLATE PG_UNICODE_FAST; +SELECT '=' !~ '[[:punct:]]' COLLATE PG_UNICODE_FAST; -- symbols are not punctuation +SELECT 'a8a' ~ '[[:digit:]]' COLLATE PG_UNICODE_FAST; +SELECT '൧' ~ '\d' COLLATE PG_UNICODE_FAST; + +-- case mapping + +SELECT 'xYz' ~* 'XyZ' COLLATE PG_UNICODE_FAST; +SELECT 'xAb' ~* '[W-Y]' COLLATE PG_UNICODE_FAST; +SELECT 'xAb' !~* '[c-d]' COLLATE PG_UNICODE_FAST; +SELECT 'Δ' ~* '[γ-λ]' COLLATE PG_UNICODE_FAST; +SELECT 'δ' ~* '[Γ-Λ]' COLLATE PG_UNICODE_FAST; -- same as above with cases reversed + +-- case folding +select casefold('AbCd 123 #$% ıiIİ ẞ ß DŽDždž Σσς' collate PG_UNICODE_FAST); diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql index e3e3bea70911b..337baab7ced93 100644 --- a/src/test/regress/sql/constraints.sql +++ b/src/test/regress/sql/constraints.sql @@ -6,6 +6,7 @@ -- - PRIMARY KEY clauses -- - UNIQUE clauses -- - EXCLUDE clauses +-- - NOT NULL clauses -- -- directory paths are passed to us in environment variables @@ -66,6 +67,18 @@ INSERT INTO CHECK_TBL VALUES (1); SELECT * FROM CHECK_TBL; +CREATE TABLE NE_CHECK_TBL (x int, + CONSTRAINT CHECK_CON CHECK (x > 3) NOT ENFORCED); + +INSERT INTO NE_CHECK_TBL VALUES (5); +INSERT INTO NE_CHECK_TBL VALUES (4); +INSERT INTO NE_CHECK_TBL VALUES (3); +INSERT INTO NE_CHECK_TBL VALUES (2); +INSERT INTO NE_CHECK_TBL VALUES (6); +INSERT INTO NE_CHECK_TBL VALUES (1); + +SELECT * FROM NE_CHECK_TBL; + CREATE SEQUENCE CHECK_SEQ; CREATE TABLE CHECK2_TBL (x int, y text, z int, @@ -91,7 +104,8 @@ CREATE TABLE INSERT_TBL (x INT DEFAULT nextval('insert_seq'), y TEXT DEFAULT '-NULL-', z INT DEFAULT -1 * currval('insert_seq'), CONSTRAINT INSERT_TBL_CON CHECK (x >= 3 AND y <> 'check failed' AND x < 8), - CHECK (x + z = 0)); + CHECK (x + z = 0) ENFORCED, /* no change it is a default */ + CONSTRAINT NE_INSERT_TBL_CON CHECK (x + z = 1) NOT ENFORCED); INSERT INTO INSERT_TBL(x,z) VALUES (2, -2); @@ -517,6 +531,12 @@ COMMIT; SELECT * FROM unique_tbl; +-- enforceability cannot be specified or set for unique constraint +CREATE TABLE UNIQUE_EN_TBL(i int UNIQUE ENFORCED); +CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED); +ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED; +ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORCED; + DROP TABLE unique_tbl; -- @@ -597,6 +617,391 @@ ALTER TABLE deferred_excl ADD EXCLUDE (f1 WITH =); DROP TABLE deferred_excl; +-- verify constraints created for NOT NULL clauses +CREATE TABLE notnull_tbl1 (a INTEGER NOT NULL NOT NULL); +\d+ notnull_tbl1 +-- no-op +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; +\d+ notnull_tbl1 +-- duplicate name +ALTER TABLE notnull_tbl1 ADD COLUMN b INT CONSTRAINT notnull_tbl1_a_not_null NOT NULL; +-- DROP NOT NULL gets rid of both the attnotnull flag and the constraint itself +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +\d+ notnull_tbl1 +-- SET NOT NULL puts both back +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +\d+ notnull_tbl1 +-- Doing it twice doesn't create a redundant constraint +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +select conname, contype, conkey from pg_constraint where conrelid = 'notnull_tbl1'::regclass; +-- Using the "table constraint" syntax also works +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +ALTER TABLE notnull_tbl1 ADD CONSTRAINT foobar NOT NULL a; +\d+ notnull_tbl1 +DROP TABLE notnull_tbl1; + +-- Verify that constraint names and NO INHERIT are properly considered when +-- multiple constraint are specified, either explicitly or via SERIAL/PK/etc, +-- and that conflicting cases are rejected. Mind that table constraints +-- handle this separately from column constraints. +create table notnull_tbl1 (a int primary key constraint foo not null); +\d+ notnull_tbl1 +create table notnull_tbl2 (a serial, constraint foo not null a); +\d+ notnull_tbl2 +create table notnull_tbl3 (constraint foo not null a, a int generated by default as identity); +\d+ notnull_tbl3 +create table notnull_tbl4 (a int not null constraint foo not null); +\d+ notnull_tbl4 +create table notnull_tbl5 (a int constraint foo not null constraint foo not null); +\d+ notnull_tbl5 +create table notnull_tbl6 (like notnull_tbl1, constraint foo not null a); +\d+ notnull_tbl6 +drop table notnull_tbl2, notnull_tbl3, notnull_tbl4, notnull_tbl5, notnull_tbl6; + +-- error cases: +create table notnull_tbl_fail (a serial constraint foo not null constraint bar not null); +create table notnull_tbl_fail (a serial constraint foo not null no inherit constraint foo not null); +create table notnull_tbl_fail (a int constraint foo not null, constraint foo not null a no inherit); +create table notnull_tbl_fail (a serial constraint foo not null, constraint bar not null a); +create table notnull_tbl_fail (a serial, constraint foo not null a, constraint bar not null a); +create table notnull_tbl_fail (a serial, constraint foo not null a no inherit); +create table notnull_tbl_fail (a serial not null no inherit); +create table notnull_tbl_fail (like notnull_tbl1, constraint foo2 not null a); +create table notnull_tbl_fail (a int primary key constraint foo not null no inherit); +create table notnull_tbl_fail (a int not null no inherit primary key); +create table notnull_tbl_fail (a int primary key, not null a no inherit); +create table notnull_tbl_fail (a int, primary key(a), not null a no inherit); +create table notnull_tbl_fail (a int generated by default as identity, constraint foo not null a no inherit); +create table notnull_tbl_fail (a int generated by default as identity not null no inherit); + +drop table notnull_tbl1; + +-- NOT NULL NO INHERIT +CREATE TABLE ATACC1 (a int, NOT NULL a NO INHERIT); +CREATE TABLE ATACC2 () INHERITS (ATACC1); +\d+ ATACC2 +DROP TABLE ATACC1, ATACC2; +CREATE TABLE ATACC1 (a int); +ALTER TABLE ATACC1 ADD NOT NULL a NO INHERIT; +CREATE TABLE ATACC2 () INHERITS (ATACC1); +\d+ ATACC2 +DROP TABLE ATACC1, ATACC2; +CREATE TABLE ATACC1 (a int); +CREATE TABLE ATACC2 () INHERITS (ATACC1); +ALTER TABLE ATACC1 ADD NOT NULL a NO INHERIT; +\d+ ATACC2 +CREATE TABLE ATACC3 (PRIMARY KEY (a)) INHERITS (ATACC1); +\d+ ATACC3 +DROP TABLE ATACC1, ATACC2, ATACC3; + +-- NOT NULL NO INHERIT is not possible on partitioned tables +CREATE TABLE ATACC1 (a int NOT NULL NO INHERIT) PARTITION BY LIST (a); +CREATE TABLE ATACC1 (a int, NOT NULL a NO INHERIT) PARTITION BY LIST (a); + +-- it's not possible to override a no-inherit constraint with an inheritable one +CREATE TABLE ATACC2 (a int, CONSTRAINT a_is_not_null NOT NULL a NO INHERIT); +CREATE TABLE ATACC1 (a int); +CREATE TABLE ATACC3 (a int) INHERITS (ATACC2); +ALTER TABLE ATACC2 INHERIT ATACC1; +-- can't override +ALTER TABLE ATACC1 ADD CONSTRAINT ditto NOT NULL a; +-- dropping the NO INHERIT constraint allows this to work +ALTER TABLE ATACC2 DROP CONSTRAINT a_is_not_null; +ALTER TABLE ATACC1 ADD CONSTRAINT ditto NOT NULL a; +\d+ ATACC3 +DROP TABLE ATACC1, ATACC2, ATACC3; + +-- Can't have two constraints with the same name +CREATE TABLE notnull_tbl2 (a INTEGER CONSTRAINT blah NOT NULL, b INTEGER CONSTRAINT blah NOT NULL); + +-- can't drop not-null in primary key +CREATE TABLE notnull_tbl2 (a INTEGER PRIMARY KEY); +ALTER TABLE notnull_tbl2 ALTER a DROP NOT NULL; +DROP TABLE notnull_tbl2; + +CREATE TABLE notnull_tbl3 (a INTEGER NOT NULL, CHECK (a IS NOT NULL)); +ALTER TABLE notnull_tbl3 ALTER A DROP NOT NULL; +ALTER TABLE notnull_tbl3 ADD b int, ADD CONSTRAINT pk PRIMARY KEY (a, b); +\d notnull_tbl3 +ALTER TABLE notnull_tbl3 DROP CONSTRAINT pk; +\d notnull_tbl3 + +-- Primary keys cause not-null constraints to be created. +CREATE TABLE cnn_pk (a int, b int); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +ALTER TABLE cnn_pk ADD CONSTRAINT cnn_primarykey PRIMARY KEY (b); +\d+ cnn_pk* +ALTER TABLE cnn_pk DROP CONSTRAINT cnn_primarykey; +\d+ cnn_pk* +DROP TABLE cnn_pk, cnn_pk_child; + +-- As above, but create the primary key ahead of time +CREATE TABLE cnn_pk (a int, b int, CONSTRAINT cnn_primarykey PRIMARY KEY (b)); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +\d+ cnn_pk* +ALTER TABLE cnn_pk DROP CONSTRAINT cnn_primarykey; +\d+ cnn_pk* +DROP TABLE cnn_pk, cnn_pk_child; + +-- As above, but create the primary key using a UNIQUE index +CREATE TABLE cnn_pk (a int, b int); +CREATE UNIQUE INDEX cnn_uq ON cnn_pk (b); +CREATE TABLE cnn_pk_child () INHERITS (cnn_pk); +ALTER TABLE cnn_pk ADD CONSTRAINT cnn_primarykey PRIMARY KEY USING INDEX cnn_uq; +\d+ cnn_pk* +DROP TABLE cnn_pk, cnn_pk_child; + +-- Unique constraints don't give raise to not-null constraints, however. +create table cnn_uq (a int); +alter table cnn_uq add unique (a); +\d+ cnn_uq +drop table cnn_uq; +create table cnn_uq (a int); +create unique index cnn_uq_idx on cnn_uq (a); +alter table cnn_uq add unique using index cnn_uq_idx; +\d+ cnn_uq + +-- can't create a primary key on a noinherit not-null +create table cnn_pk (a int not null no inherit); +alter table cnn_pk add primary key (a); +drop table cnn_pk; + +-- Ensure partitions are scanned for null values when adding a PK +create table cnn2_parted(a int) partition by list (a); +create table cnn_part1 partition of cnn2_parted for values in (1, null); +insert into cnn_part1 values (null); +alter table cnn2_parted add primary key (a); +drop table cnn2_parted; + +-- columns in regular and LIKE inheritance should be marked not-nullable +-- for primary keys, even if those are deferred +CREATE TABLE notnull_tbl4 (a INTEGER PRIMARY KEY INITIALLY DEFERRED); +CREATE TABLE notnull_tbl4_lk (LIKE notnull_tbl4); +CREATE TABLE notnull_tbl4_lk2 (LIKE notnull_tbl4 INCLUDING INDEXES); +CREATE TABLE notnull_tbl4_lk3 (LIKE notnull_tbl4 INCLUDING INDEXES, NOT NULL a); +ALTER TABLE notnull_tbl4_lk3 RENAME CONSTRAINT notnull_tbl4_a_not_null TO a_nn; +CREATE TABLE notnull_tbl4_cld () INHERITS (notnull_tbl4); +CREATE TABLE notnull_tbl4_cld2 (PRIMARY KEY (a) DEFERRABLE) INHERITS (notnull_tbl4); +CREATE TABLE notnull_tbl4_cld3 (PRIMARY KEY (a) DEFERRABLE, CONSTRAINT a_nn NOT NULL a) INHERITS (notnull_tbl4); +\d+ notnull_tbl4 +\d+ notnull_tbl4_lk +\d+ notnull_tbl4_lk2 +\d+ notnull_tbl4_lk3 +\d+ notnull_tbl4_cld +\d+ notnull_tbl4_cld2 +\d+ notnull_tbl4_cld3 +-- leave these tables around for pg_upgrade testing + +-- It's possible to remove a constraint from parents without affecting children +CREATE TABLE notnull_tbl5 (a int CONSTRAINT ann NOT NULL, + b int CONSTRAINT bnn NOT NULL); +CREATE TABLE notnull_tbl5_child () INHERITS (notnull_tbl5); +ALTER TABLE ONLY notnull_tbl5 DROP CONSTRAINT ann; +ALTER TABLE ONLY notnull_tbl5 ALTER b DROP NOT NULL; +\d+ notnull_tbl5_child +CREATE TABLE notnull_tbl6 (a int CONSTRAINT ann NOT NULL, + b int CONSTRAINT bnn NOT NULL, check (a > 0)) PARTITION BY LIST (a); +CREATE TABLE notnull_tbl6_1 PARTITION OF notnull_tbl6 FOR VALUES IN (1); +ALTER TABLE ONLY notnull_tbl6 DROP CONSTRAINT ann; +ALTER TABLE ONLY notnull_tbl6 ALTER b DROP NOT NULL; +\d+ notnull_tbl6_1 + + +-- NOT NULL NOT VALID +PREPARE get_nnconstraint_info(regclass[]) AS +SELECT conrelid::regclass as tabname, conname, convalidated, conislocal, coninhcount +FROM pg_constraint +WHERE conrelid = ANY($1) +ORDER BY conrelid::regclass::text COLLATE "C", conname; + +CREATE TABLE notnull_tbl1 (a int, b int); +INSERT INTO notnull_tbl1 VALUES (NULL, 1), (300, 3); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; -- error +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a NOT VALID; -- ok +-- even an invalid not-null forbids new nulls +INSERT INTO notnull_tbl1 VALUES (NULL, 4); +\d+ notnull_tbl1 + +-- If we have an invalid constraint, we can't have another +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn1 NOT NULL a NOT VALID NO INHERIT; +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a; + +-- cannot add primary key on a column with an invalid not-null +ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a); + +-- ALTER column SET NOT NULL validates an invalid constraint (but this fails +-- because of rows with null values) +ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL; +\d+ notnull_tbl1 + +-- Creating a derived table using LIKE gets the constraint, but it's valid +CREATE TABLE notnull_tbl1_copy (LIKE notnull_tbl1); +EXECUTE get_nnconstraint_info('{notnull_tbl1_copy}'); + +-- An inheritance child table gets the constraint, but it's valid +CREATE TABLE notnull_tbl1_child (a int, b int) INHERITS (notnull_tbl1); +EXECUTE get_nnconstraint_info('{notnull_tbl1_child, notnull_tbl1}'); + +-- Also try inheritance added after table creation +CREATE TABLE notnull_tbl1_child2 (c int, b int, a int); +ALTER TABLE notnull_tbl1_child2 INHERIT notnull_tbl1; -- nope +ALTER TABLE notnull_tbl1_child2 ADD NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1_child2 INHERIT notnull_tbl1; +EXECUTE get_nnconstraint_info('{notnull_tbl1_child2}'); + +--table rewrite won't validate invalid constraint +ALTER TABLE notnull_tbl1 ADD column d float8 default random(); + +-- VALIDATE CONSTRAINT scans the table +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- error, nulls exist +UPDATE notnull_tbl1 SET a = 100 WHERE b = 1; +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- now ok +EXECUTE get_nnconstraint_info('{notnull_tbl1}'); + +--- now we can add primary key +ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a); +DROP TABLE notnull_tbl1, notnull_tbl1_child, notnull_tbl1_child2; + +-- dropping an invalid constraint is possible +CREATE TABLE notnull_tbl1 (a int, b int); +ALTER TABLE notnull_tbl1 ADD NOT NULL a NOT VALID, + ADD NOT NULL b NOT VALID; +ALTER TABLE notnull_tbl1 ALTER a DROP NOT NULL; +ALTER TABLE notnull_tbl1 DROP CONSTRAINT notnull_tbl1_b_not_null; +DROP TABLE notnull_tbl1; + +-- ALTER .. NO INHERIT works for invalid constraints +CREATE TABLE notnull_tbl1 (a int); +CREATE TABLE notnull_tbl1_chld () INHERITS (notnull_tbl1); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nntbl1_a NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1 ALTER CONSTRAINT nntbl1_a NO INHERIT; + +-- DROP CONSTRAINT recurses correctly on invalid constraints +ALTER TABLE notnull_tbl1 ALTER CONSTRAINT nntbl1_a INHERIT; +ALTER TABLE notnull_tbl1 DROP CONSTRAINT nntbl1_a; +DROP TABLE notnull_tbl1, notnull_tbl1_chld; + +-- if a parent has a valid not null constraint then a child table cannot +-- have an invalid one +CREATE TABLE notnull_tbl1 (a int); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn_parent NOT NULL a not valid; +CREATE TABLE notnull_chld0 (a int, CONSTRAINT nn_chld0 NOT NULL a); +ALTER TABLE notnull_tbl1 INHERIT notnull_chld0; --error + +ALTER TABLE notnull_chld0 DROP CONSTRAINT nn_chld0; +ALTER TABLE notnull_chld0 ADD CONSTRAINT nn_chld0 NOT NULL a not valid; +ALTER TABLE notnull_tbl1 INHERIT notnull_chld0; --now ok + +-- parents and child not-null will all be validated. +ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn_parent; +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_chld0}'); +DROP TABLE notnull_tbl1, notnull_chld0; + +-- Test invalid not null on inheritance table. +CREATE TABLE notnull_inhparent (i int); +CREATE TABLE notnull_inhchild (i int) INHERITS (notnull_inhparent); +CREATE TABLE notnull_inhgrand () INHERITS (notnull_inhparent, notnull_inhchild); +ALTER TABLE notnull_inhparent ADD CONSTRAINT nn NOT NULL i NOT VALID; +ALTER TABLE notnull_inhchild ADD CONSTRAINT nn1 NOT NULL i; -- error +EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); +ALTER TABLE notnull_inhparent ALTER i SET NOT NULL; -- ok +EXECUTE get_nnconstraint_info('{notnull_inhparent, notnull_inhchild, notnull_inhgrand}'); +DROP TABLE notnull_inhparent, notnull_inhchild, notnull_inhgrand; + +-- Verify NOT NULL VALID/NOT VALID with partition table. +DROP TABLE notnull_tbl1; +CREATE TABLE notnull_tbl1 (a int, b int) PARTITION BY LIST (a); +ALTER TABLE notnull_tbl1 ADD CONSTRAINT notnull_con NOT NULL a NOT VALID; --ok +CREATE TABLE notnull_tbl1_1 PARTITION OF notnull_tbl1 FOR VALUES IN (1,2); +CREATE TABLE notnull_tbl1_2(a int, CONSTRAINT nn2 NOT NULL a, b int); +ALTER TABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_2 FOR VALUES IN (3,4); + +CREATE TABLE notnull_tbl1_3(a int, b int); +INSERT INTO notnull_tbl1_3 values(NULL,1); +ALTER TABLE notnull_tbl1_3 add CONSTRAINT nn3 NOT NULL a NOT VALID; +ALTER TABLE notnull_tbl1 ATTACH PARTITION notnull_tbl1_3 FOR VALUES IN (NULL,5); + +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_tbl1_1, notnull_tbl1_2, notnull_tbl1_3}'); +ALTER TABLE notnull_tbl1 ALTER COLUMN a SET NOT NULL; --error, notnull_tbl1_3 have null values +ALTER TABLE notnull_tbl1_3 VALIDATE CONSTRAINT nn3; --error + +TRUNCATE notnull_tbl1; +ALTER TABLE notnull_tbl1 ALTER COLUMN a SET NOT NULL; --OK + +EXECUTE get_nnconstraint_info('{notnull_tbl1, notnull_tbl1_1, notnull_tbl1_2, notnull_tbl1_3}'); +DROP TABLE notnull_tbl1; + +-- partitioned table have not-null, then the partitions can not be NOT NULL NOT VALID. +CREATE TABLE pp_nn (a int, b int, NOT NULL a) PARTITION BY LIST (a); +CREATE TABLE pp_nn_1(a int, b int); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn1 NOT NULL a NOT VALID; +ALTER TABLE pp_nn ATTACH PARTITION pp_nn_1 FOR VALUES IN (NULL,5); --error +ALTER TABLE pp_nn_1 VALIDATE CONSTRAINT nn1; +ALTER TABLE pp_nn ATTACH PARTITION pp_nn_1 FOR VALUES IN (NULL,5); --ok +DROP TABLE pp_nn; + +-- Try a partition with an invalid constraint and create a PK on the parent. +CREATE TABLE pp_nn (a int) PARTITION BY HASH (a); +CREATE TABLE pp_nn_1 PARTITION OF pp_nn FOR VALUES WITH (MODULUS 2, REMAINDER 0); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn NOT NULL a NOT VALID; +ALTER TABLE ONLY pp_nn ADD PRIMARY KEY (a); +DROP TABLE pp_nn; + +-- same as above, but the constraint is NO INHERIT +CREATE TABLE pp_nn (a int) PARTITION BY HASH (a); +CREATE TABLE pp_nn_1 PARTITION OF pp_nn FOR VALUES WITH (MODULUS 2, REMAINDER 0); +ALTER TABLE pp_nn_1 ADD CONSTRAINT nn NOT NULL a NO INHERIT; +ALTER TABLE ONLY pp_nn ADD PRIMARY KEY (a); +DROP TABLE pp_nn; + +-- Create table with NOT NULL INVALID constraint, for pg_upgrade. +CREATE TABLE notnull_tbl1_upg (a int, b int); +INSERT INTO notnull_tbl1_upg VALUES (NULL, 1), (NULL, 2), (300, 3); +ALTER TABLE notnull_tbl1_upg ADD CONSTRAINT nn NOT NULL a NOT VALID; +-- Inherit test for pg_upgrade +CREATE TABLE notnull_parent_upg (a int); +CREATE TABLE notnull_child_upg () INHERITS (notnull_parent_upg); +ALTER TABLE notnull_child_upg ADD CONSTRAINT nn NOT NULL a; +ALTER TABLE notnull_parent_upg ADD CONSTRAINT nn NOT NULL a NOT VALID; +SELECT conrelid::regclass, contype, convalidated, conislocal +FROM pg_catalog.pg_constraint +WHERE conrelid in ('notnull_parent_upg'::regclass, 'notnull_child_upg'::regclass) +ORDER BY 1; + +-- Partition table test, for pg_upgrade +CREATE TABLE notnull_part1_upg (a int, b int) PARTITION BY LIST (a); +ALTER TABLE notnull_part1_upg ADD CONSTRAINT notnull_con NOT NULL a NOT VALID; --ok +CREATE TABLE notnull_part1_1_upg PARTITION OF notnull_part1_upg FOR VALUES IN (1,2); +CREATE TABLE notnull_part1_2_upg (a int, CONSTRAINT nn2 NOT NULL a, b int); +ALTER TABLE notnull_part1_upg ATTACH PARTITION notnull_part1_2_upg FOR VALUES IN (3,4); +CREATE TABLE notnull_part1_3_upg (a int, b int); +INSERT INTO notnull_part1_3_upg values(NULL,1); +ALTER TABLE notnull_part1_3_upg add CONSTRAINT nn3 NOT NULL a NOT VALID; +ALTER TABLE notnull_part1_upg ATTACH PARTITION notnull_part1_3_upg FOR VALUES IN (NULL,5); +EXECUTE get_nnconstraint_info('{notnull_part1_upg, notnull_part1_1_upg, notnull_part1_2_upg, notnull_part1_3_upg}'); + +-- Inheritance test tables for pg_upgrade +create table constr_parent (a int); +create table constr_child (a int) inherits (constr_parent); +alter table constr_parent add not null a not valid; +alter table constr_child validate constraint constr_parent_a_not_null; +EXECUTE get_nnconstraint_info('{constr_parent, constr_child}'); + +create table constr_parent2 (a int); +create table constr_child2 () inherits (constr_parent2); +alter table constr_parent2 add not null a not valid; +alter table constr_child2 validate constraint constr_parent2_a_not_null; +EXECUTE get_nnconstraint_info('{constr_parent2, constr_child2}'); + +create table constr_parent3 (a int not null); +create table constr_child3 () inherits (constr_parent2, constr_parent3); +EXECUTE get_nnconstraint_info('{constr_parent3, constr_child3}'); + +DEALLOCATE get_nnconstraint_info; + +-- end NOT NULL NOT VALID + + -- Comments -- Setup a low-level role to enforce non-superuser checks. CREATE ROLE regress_constraint_comments; diff --git a/src/test/regress/sql/conversion.sql b/src/test/regress/sql/conversion.sql index 9a65fca91fbd5..a80d62367a20a 100644 --- a/src/test/regress/sql/conversion.sql +++ b/src/test/regress/sql/conversion.sql @@ -8,6 +8,11 @@ \set regresslib :libdir '/regress' :dlsuffix +CREATE FUNCTION test_enc_setup() RETURNS void + AS :'regresslib', 'test_enc_setup' + LANGUAGE C STRICT; +SELECT FROM test_enc_setup(); + CREATE FUNCTION test_enc_conversion(bytea, name, name, bool, validlen OUT int, result OUT bytea) AS :'regresslib', 'test_enc_conversion' LANGUAGE C STRICT; @@ -295,11 +300,14 @@ insert into gb18030_inputs values ('\x666f6f84309c38', 'valid, translates to UTF-8 by mapping function'), ('\x666f6f84309c', 'incomplete char '), ('\x666f6f84309c0a', 'incomplete char, followed by newline '), + ('\x666f6f84', 'incomplete char at end'), ('\x666f6f84309c3800', 'invalid, NUL byte'), ('\x666f6f84309c0038', 'invalid, NUL byte'); --- Test GB18030 verification -select description, inbytes, (test_conv(inbytes, 'gb18030', 'gb18030')).* from gb18030_inputs; +-- Test GB18030 verification. Round-trip through text so the backing of the +-- bytea values is palloc, not shared_buffers. This lets Valgrind detect +-- reads past the end. +select description, inbytes, (test_conv(inbytes::text::bytea, 'gb18030', 'gb18030')).* from gb18030_inputs; -- Test conversions from GB18030 select description, inbytes, (test_conv(inbytes, 'gb18030', 'utf8')).* from gb18030_inputs; diff --git a/src/test/regress/sql/copy.sql b/src/test/regress/sql/copy.sql index e2dd24cb3519b..f0b88a23db853 100644 --- a/src/test/regress/sql/copy.sql +++ b/src/test/regress/sql/copy.sql @@ -38,6 +38,34 @@ copy copytest2 from :'filename' csv quote '''' escape E'\\'; select * from copytest except select * from copytest2; +--- test unquoted \. as data inside CSV +-- do not use copy out to export the data, as it would quote \. +\o :filename +\qecho line1 +\qecho '\\.' +\qecho line2 +\o +-- get the data back in with copy +truncate copytest2; +copy copytest2(test) from :'filename' csv; +select test from copytest2 order by test collate "C"; + +-- in text mode, \. must be alone on its line +truncate copytest2; +copy copytest2(test) from stdin; +line1 +line2 +foo\. +line3 +\. +copy copytest2(test) from stdin; +line4 +line5 +\.foo +line6 +\. +select test from copytest2; + -- test header line feature @@ -165,7 +193,8 @@ begin bytes_processed > 0 as has_bytes_processed, bytes_total > 0 as has_bytes_total, tuples_processed, - tuples_excluded + tuples_excluded, + tuples_skipped from pg_stat_progress_copy where pid = pg_backend_pid()) select into report (to_jsonb(r)) as value @@ -194,6 +223,13 @@ truncate tab_progress_reporting; copy tab_progress_reporting from :'filename' where (salary < 2000); +-- Generate COPY FROM report with PIPE, with some skipped tuples. +copy tab_progress_reporting from stdin(on_error ignore); +sharon x (15,12) x sam +sharon 25 (15,12) 1000 sam +sharon y (15,12) x sam +\. + drop trigger check_after_tab_progress_reporting on tab_progress_reporting; drop function notice_after_tab_progress_reporting(); drop table tab_progress_reporting; @@ -320,3 +356,22 @@ COPY parted_si(id, data) FROM :'filename'; SELECT tableoid::regclass, id % 2 = 0 is_even, count(*) from parted_si GROUP BY 1, 2 ORDER BY 1; DROP TABLE parted_si; + +-- ensure COPY FREEZE errors for foreign tables +begin; +create foreign data wrapper copytest_wrapper; +create server copytest_server foreign data wrapper copytest_wrapper; +create foreign table copytest_foreign_table (a int) server copytest_server; +copy copytest_foreign_table from stdin (freeze); +1 +\. +rollback; + +-- Tests for COPY TO with materialized views. +-- COPY TO should fail for an unpopulated materialized view +-- but succeed for a populated one. +CREATE MATERIALIZED VIEW copytest_mv AS SELECT 1 AS id WITH NO DATA; +COPY copytest_mv(id) TO stdout WITH (header); +REFRESH MATERIALIZED VIEW copytest_mv; +COPY copytest_mv(id) TO stdout WITH (header); +DROP MATERIALIZED VIEW copytest_mv; diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql index 8b14962194710..45273557ce040 100644 --- a/src/test/regress/sql/copy2.sql +++ b/src/test/regress/sql/copy2.sql @@ -70,18 +70,26 @@ COPY x from stdin (on_error ignore, on_error ignore); COPY x from stdin (log_verbosity default, log_verbosity verbose); -- incorrect options -COPY x to stdin (format BINARY, delimiter ','); -COPY x to stdin (format BINARY, null 'x'); +COPY x from stdin (format BINARY, delimiter ','); +COPY x from stdin (format BINARY, null 'x'); COPY x from stdin (format BINARY, on_error ignore); COPY x from stdin (on_error unsupported); -COPY x to stdin (format TEXT, force_quote(a)); +COPY x from stdin (format TEXT, force_quote(a)); +COPY x from stdin (format TEXT, force_quote *); COPY x from stdin (format CSV, force_quote(a)); -COPY x to stdout (format TEXT, force_not_null(a)); -COPY x to stdin (format CSV, force_not_null(a)); -COPY x to stdout (format TEXT, force_null(a)); -COPY x to stdin (format CSV, force_null(a)); -COPY x to stdin (format BINARY, on_error unsupported); -COPY x to stdout (log_verbosity unsupported); +COPY x from stdin (format CSV, force_quote *); +COPY x from stdin (format TEXT, force_not_null(a)); +COPY x from stdin (format TEXT, force_not_null *); +COPY x to stdout (format CSV, force_not_null(a)); +COPY x to stdout (format CSV, force_not_null *); +COPY x from stdin (format TEXT, force_null(a)); +COPY x from stdin (format TEXT, force_null *); +COPY x to stdout (format CSV, force_null(a)); +COPY x to stdout (format CSV, force_null *); +COPY x to stdout (format BINARY, on_error unsupported); +COPY x from stdin (log_verbosity unsupported); +COPY x from stdin with (reject_limit 1); +COPY x from stdin with (on_error ignore, reject_limit 0); -- too many columns in column list: should fail COPY x (a, b, c, d, e, d, c) from stdin; @@ -533,6 +541,10 @@ COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity verbose); 1 {1} 1 'foo' 2 {2} 2 \N \. +COPY check_ign_err2 FROM STDIN WITH (on_error ignore, log_verbosity silent); +3 {3} 3 'bar' +4 {4} 4 \N +\. -- reset context choice \set SHOW_CONTEXT errors @@ -557,6 +569,25 @@ COPY check_ign_err FROM STDIN WITH (on_error ignore); 1 {1} 3 abc \. +-- tests for reject_limit option +COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 3); +6 {6} 6 +a {7} 7 +8 {8} 8888888888 +9 {a, 9} 9 + +10 {10} 10 +\. + +COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 4); +6 {6} 6 +a {7} 7 +8 {8} 8888888888 +9 {a, 9} 9 + +10 {10} 10 +\. + -- clean up DROP TABLE forcetest; DROP TABLE vistest; diff --git a/src/test/regress/sql/copydml.sql b/src/test/regress/sql/copydml.sql index 4578342253b62..b7eeb0eed8150 100644 --- a/src/test/regress/sql/copydml.sql +++ b/src/test/regress/sql/copydml.sql @@ -66,6 +66,10 @@ create rule qqq as on delete to copydml_test where old.t <> 'f' do instead inser copy (delete from copydml_test) to stdout; drop rule qqq on copydml_test; +create rule qqq as on insert to copydml_test do instead notify copydml_test; +copy (insert into copydml_test default values) to stdout; +drop rule qqq on copydml_test; + -- triggers create function qqq_trig() returns trigger as $$ begin diff --git a/src/test/regress/sql/copyencoding.sql b/src/test/regress/sql/copyencoding.sql new file mode 100644 index 0000000000000..4e96a4d6505cf --- /dev/null +++ b/src/test/regress/sql/copyencoding.sql @@ -0,0 +1,53 @@ +-- +-- Test cases for encoding with COPY commands +-- + +-- skip test if not UTF8 server encoding +SELECT getdatabaseencoding() <> 'UTF8' + AS skip_test \gset +\if :skip_test +\quit +\endif + +-- directory paths are passed to us in environment variables +\getenv abs_builddir PG_ABS_BUILDDIR + +\set utf8_csv :abs_builddir '/results/copyencoding_utf8.csv' + +CREATE TABLE copy_encoding_tab (t text); + +-- Valid cases + +-- Use ENCODING option +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv, ENCODING 'UTF8'); +-- Read UTF8 data as LATIN1: no error +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv, ENCODING 'LATIN1'); + +-- Use client_encoding +SET client_encoding TO UTF8; +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv); +-- Read UTF8 data as LATIN1: no error +SET client_encoding TO LATIN1; +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv); +RESET client_encoding; + +-- Invalid cases + +-- Use ENCODING explicitly +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv, ENCODING 'UTF8'); +-- Read UTF8 data as EUC_JP: no error +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv, ENCODING 'EUC_JP'); + +-- Use client_encoding +SET client_encoding TO UTF8; +-- U+3042 HIRAGANA LETTER A +COPY (SELECT E'\u3042') TO :'utf8_csv' WITH (FORMAT csv); +-- Read UTF8 data as EUC_JP: no error +SET client_encoding TO EUC_JP; +COPY copy_encoding_tab FROM :'utf8_csv' WITH (FORMAT csv); +RESET client_encoding; + +DROP TABLE copy_encoding_tab; diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/create_am.sql index 825aed325e563..754fe0c694bc5 100644 --- a/src/test/regress/sql/create_am.sql +++ b/src/test/regress/sql/create_am.sql @@ -217,6 +217,16 @@ ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2; DROP MATERIALIZED VIEW heapmv; DROP TABLE heaptable; +-- Partitioned table with USING +CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2; +SELECT pg_describe_object(classid, objid, objsubid) AS obj, + pg_describe_object(refclassid, refobjid, refobjsubid) as refobj + FROM pg_depend, pg_am + WHERE pg_depend.refclassid = 'pg_am'::regclass + AND pg_am.oid = pg_depend.refobjid + AND pg_depend.objid = 'am_partitioned'::regclass; +DROP TABLE am_partitioned; + -- Partition hierarchies with access methods BEGIN; SET LOCAL default_table_access_method = 'heap'; diff --git a/src/test/regress/sql/create_function_sql.sql b/src/test/regress/sql/create_function_sql.sql index 89e9af3a49933..6d1c102d78082 100644 --- a/src/test/regress/sql/create_function_sql.sql +++ b/src/test/regress/sql/create_function_sql.sql @@ -328,6 +328,15 @@ CREATE OR REPLACE PROCEDURE functest1(a int) LANGUAGE SQL AS 'SELECT $1'; DROP FUNCTION functest1(a int); +-- early shutdown of set-returning functions + +CREATE FUNCTION functest_srf0() RETURNS SETOF int +LANGUAGE SQL +AS $$ SELECT i FROM generate_series(1, 100) i $$; + +SELECT functest_srf0() LIMIT 5; + + -- inlining of set-returning functions CREATE TABLE functest3 (a int); @@ -385,6 +394,31 @@ CREATE FUNCTION voidtest5(a int) RETURNS SETOF VOID LANGUAGE SQL AS $$ SELECT generate_series(1, a) $$ STABLE; SELECT * FROM voidtest5(3); +-- DDL within a SQL function can now affect later statements in the function; +-- though that doesn't work if check_function_bodies is on. + +SET check_function_bodies TO off; + +CREATE FUNCTION create_and_insert() RETURNS VOID LANGUAGE sql AS $$ + create table ddl_test (f1 int); + insert into ddl_test values (1.2); +$$; + +SELECT create_and_insert(); + +TABLE ddl_test; + +CREATE FUNCTION alter_and_insert() RETURNS VOID LANGUAGE sql AS $$ + alter table ddl_test alter column f1 type numeric; + insert into ddl_test values (1.2); +$$; + +SELECT alter_and_insert(); + +TABLE ddl_test; + +RESET check_function_bodies; + -- Regression tests for bugs: -- Check that arguments that are R/W expanded datums aren't corrupted by @@ -415,6 +449,16 @@ CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL AS 'a', 'b'; +CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL + AS ''; + +-- make sure empty-body case is handled at execution time, too +SET check_function_bodies = off; +CREATE FUNCTION test1 (anyelement) RETURNS anyarray LANGUAGE SQL + AS ''; +SELECT test1(0); +RESET check_function_bodies; + -- Cleanup DROP SCHEMA temp_func_test CASCADE; DROP USER regress_unpriv_user; diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index e296891cab806..e21ff426519b0 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -372,6 +372,12 @@ CREATE INDEX hash_tuplesort_idx ON tenk1 USING hash (stringu1 name_ops) WITH (fi EXPLAIN (COSTS OFF) SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA'; SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA'; +-- OR-clauses shouldn't be transformed into SAOP because hash indexes don't +-- support SAOP scans. +SET enable_seqscan = off; +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 WHERE stringu1 = 'TVAAAA' OR stringu1 = 'TVAAAB'; +RESET enable_seqscan; DROP INDEX hash_tuplesort_idx; RESET maintenance_work_mem; @@ -644,7 +650,9 @@ DROP TABLE syscol_table; -- CREATE TABLE onek_with_null AS SELECT unique1, unique2 FROM onek; -INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL); +INSERT INTO onek_with_null(unique1, unique2) +VALUES (NULL, -1), (NULL, 2_147_483_647), (NULL, NULL), + (100, NULL), (500, NULL); CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1); SET enable_seqscan = OFF; @@ -657,6 +665,7 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; DROP INDEX onek_nulltest; @@ -669,6 +678,7 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NUL SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IN (-1, 0, 1); +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; DROP INDEX onek_nulltest; @@ -680,6 +690,7 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; DROP INDEX onek_nulltest; @@ -691,6 +702,7 @@ SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; +SELECT unique1, unique2 FROM onek_with_null WHERE unique1 = 500 ORDER BY unique2 DESC, unique1 DESC LIMIT 1; DROP INDEX onek_nulltest; @@ -710,9 +722,9 @@ SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= 0 ORDER BY unique2 LIMIT 2; SELECT unique1, unique2 FROM onek_with_null - ORDER BY unique2 DESC LIMIT 2; + ORDER BY unique2 DESC LIMIT 5; SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 - ORDER BY unique2 DESC LIMIT 2; + ORDER BY unique2 DESC LIMIT 3; SELECT unique1, unique2 FROM onek_with_null WHERE unique2 < 999 ORDER BY unique2 DESC LIMIT 2; @@ -726,18 +738,110 @@ DROP TABLE onek_with_null; -- Check bitmap index path planning -- +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous = 0); +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous = 0); + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = (SELECT 1 + 2) OR tenthous = 42); +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = (SELECT 1 + 2) OR tenthous = 42); + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42 OR tenthous IS NULL); + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous::int2 = 3::int8 OR tenthous = 42::int8); + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous::int2 = 3::int8 OR tenthous::int2 = 42::int8); + + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::int2 OR tenthous = 3::int8 OR tenthous = 42::int8); + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + EXPLAIN (COSTS OFF) SELECT * FROM tenk1 WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); SELECT * FROM tenk1 WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1::numeric OR tenthous = 3::int4 OR tenthous = 42::numeric); + +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 + WHERE tenthous = 1::numeric OR tenthous = 3::int4 OR tenthous = 42::numeric; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + EXPLAIN (COSTS OFF) SELECT count(*) FROM tenk1 WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); SELECT count(*) FROM tenk1 WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand < 42 OR thousand < 99 OR 43 > thousand OR 42 > thousand); +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand < 42 OR thousand < 99 OR 43 > thousand OR 42 > thousand); + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3) OR thousand = 41; +SELECT count(*) FROM tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3) OR thousand = 41; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99 OR tenthous < 2) OR thousand = 41; +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99 OR tenthous < 2) OR thousand = 41; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 41 OR thousand = 99 AND tenthous = 2); +SELECT count(*) FROM tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 41 OR thousand = 99 AND tenthous = 2); + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1, tenk2 + WHERE tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk1.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1, tenk2 + WHERE tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 JOIN tenk2 ON + tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 LEFT JOIN tenk2 ON + tenk1.hundred = 42 AND (tenk2.thousand = 42 OR tenk2.thousand = 41 OR tenk2.tenthous = 2) AND + tenk2.hundred = tenk1.hundred; -- -- Check behavior with duplicate index column contents -- @@ -754,7 +858,8 @@ SELECT count(*) FROM dupindexcols WHERE f1 BETWEEN 'WA' AND 'ZZZ' and id < 1000 and f1 ~<~ 'YX'; -- --- Check that index scans with =ANY indexquals return rows in index order +-- Check that index scans with SAOP array and/or skip array indexquals +-- return rows in index order -- explain (costs off) @@ -766,7 +871,7 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1,42,7) ORDER BY unique1; --- Non-required array scan key on "tenthous": +-- Skip array on "thousand", SAOP array on "tenthous": explain (costs off) SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) @@ -776,7 +881,7 @@ SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) ORDER BY thousand; --- Non-required array scan key on "tenthous", backward scan: +-- Skip array on "thousand", SAOP array on "tenthous", backward scan: explain (costs off) SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) @@ -786,6 +891,15 @@ SELECT thousand, tenthous FROM tenk1 WHERE thousand < 2 AND tenthous IN (1001,3000) ORDER BY thousand DESC, tenthous DESC; +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > 995 and tenthous in (998, 999) +ORDER BY thousand desc; + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > 995 and tenthous in (998, 999) +ORDER BY thousand desc; + -- -- Check elimination of redundant and contradictory index quals -- @@ -799,6 +913,21 @@ SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY(' SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY('{33, 44}'::bigint[]); +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 = ANY(NULL); + +SELECT unique1 FROM tenk1 WHERE unique1 = ANY(NULL); + +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{NULL,NULL,NULL}'); + +SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{NULL,NULL,NULL}'); + +explain (costs off) +SELECT unique1 FROM tenk1 WHERE unique1 IS NULL AND unique1 IS NULL; + +SELECT unique1 FROM tenk1 WHERE unique1 IS NULL AND unique1 IS NULL; + explain (costs off) SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 1; @@ -839,6 +968,41 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint; +explain (costs off) +SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5); + +SELECT unique1 FROM tenk1 WHERE (thousand, tenthous) > (NULL, 5); + +-- Skip array redundancy (pair of redundant low_compare inequalities) +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 and thousand >= 0 AND tenthous = 3000 +ORDER BY thousand; + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 and thousand >= 0 AND tenthous = 3000 +ORDER BY thousand; + +-- Skip array redundancy (pair of redundant high_compare inequalities) +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand < 3 and thousand <= 2 AND tenthous = 1001 +ORDER BY thousand; + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand < 3 and thousand <= 2 AND tenthous = 1001 +ORDER BY thousand; + +-- Skip array preprocessing increments "thousand > -1" to "thousand >= 0" +explain (costs off) +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 AND tenthous IN (1001,3000) +ORDER BY thousand limit 2; + +SELECT thousand, tenthous FROM tenk1 +WHERE thousand > -1 AND tenthous IN (1001,3000) +ORDER BY thousand limit 2; + -- -- Check elimination of constant-NULL subexpressions -- @@ -1126,9 +1290,9 @@ REINDEX TABLE CONCURRENTLY concur_reindex_tab; COMMIT; REINDEX TABLE CONCURRENTLY pg_class; -- no catalog relation REINDEX INDEX CONCURRENTLY pg_class_oid_index; -- no catalog index --- These are the toast table and index of pg_authid. -REINDEX TABLE CONCURRENTLY pg_toast.pg_toast_1260; -- no catalog toast table -REINDEX INDEX CONCURRENTLY pg_toast.pg_toast_1260_index; -- no catalog toast index +-- These are the toast table and index of pg_database. +REINDEX TABLE CONCURRENTLY pg_toast.pg_toast_1262; -- no catalog toast table +REINDEX INDEX CONCURRENTLY pg_toast.pg_toast_1262_index; -- no catalog toast index REINDEX SYSTEM CONCURRENTLY postgres; -- not allowed for SYSTEM REINDEX (CONCURRENTLY) SYSTEM postgres; -- ditto REINDEX (CONCURRENTLY) SYSTEM; -- ditto @@ -1252,6 +1416,41 @@ SELECT b.relname, ORDER BY 1; DROP TABLE concur_temp_tab_1, concur_temp_tab_2, reindex_temp_before; +-- No OR-clause groupings should happen, and there should be no clause +-- permutations in the filtering conditions we could see in the EXPLAIN. +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 WHERE unique1 < 1 OR hundred < 2; + +-- OR clauses in the 'unique1' column are grouped, so clause permutation +-- occurs. W e can see it in the 'Recheck Cond': the second clause involving +-- the 'unique1' column goes just after the first one. +EXPLAIN (COSTS OFF) +SELECT * FROM tenk1 WHERE unique1 < 1 OR unique1 < 3 OR hundred < 2; + +-- Check bitmap scan can consider similar OR arguments separately without +-- grouping them into SAOP. +CREATE TABLE bitmap_split_or (a int NOT NULL, b int NOT NULL, c int NOT NULL); +INSERT INTO bitmap_split_or (SELECT 1, 1, i FROM generate_series(1, 1000) i); +INSERT INTO bitmap_split_or (select i, 2, 2 FROM generate_series(1, 1000) i); +VACUUM ANALYZE bitmap_split_or; +CREATE INDEX t_b_partial_1_idx ON bitmap_split_or (b) WHERE a = 1; +CREATE INDEX t_b_partial_2_idx ON bitmap_split_or (b) WHERE a = 2; +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or WHERE (a = 1 OR a = 2) AND b = 2; +DROP INDEX t_b_partial_1_idx; +DROP INDEX t_b_partial_2_idx; +CREATE INDEX t_a_b_idx ON bitmap_split_or (a, b); +CREATE INDEX t_b_c_idx ON bitmap_split_or (b, c); +CREATE STATISTICS t_a_b_stat (mcv) ON a, b FROM bitmap_split_or; +CREATE STATISTICS t_b_c_stat (mcv) ON b, c FROM bitmap_split_or; +ANALYZE bitmap_split_or; +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or t1, bitmap_split_or t2 +WHERE t1.a = t2.b OR t1.a = 2; +EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or WHERE a = 1 AND (b = 1 OR b = 2) AND c = 2; +DROP TABLE bitmap_split_or; + -- -- REINDEX SCHEMA -- @@ -1305,8 +1504,8 @@ REINDEX SCHEMA schema_to_reindex; RESET ROLE; GRANT USAGE ON SCHEMA pg_toast TO regress_reindexuser; SET SESSION ROLE regress_reindexuser; -REINDEX TABLE pg_toast.pg_toast_1260; -REINDEX INDEX pg_toast.pg_toast_1260_index; +REINDEX TABLE pg_toast.pg_toast_1262; +REINDEX INDEX pg_toast.pg_toast_1262_index; -- Clean up RESET ROLE; diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 1fd4cbfa7ef0d..37a227148e9c2 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -30,6 +30,12 @@ CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK DROP TABLE unlogged1, public.unlogged2; +CREATE UNLOGGED TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- fail +CREATE TABLE unlogged1 (a int) PARTITION BY RANGE (a); -- ok +ALTER TABLE unlogged1 SET LOGGED; -- fails +ALTER TABLE unlogged1 SET UNLOGGED; -- fails +DROP TABLE unlogged1; + CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r'; diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql index 04008a027b8d9..6e21722aaeb95 100644 --- a/src/test/regress/sql/create_table_like.sql +++ b/src/test/regress/sql/create_table_like.sql @@ -51,7 +51,7 @@ INSERT INTO test_like_id_3 (b) VALUES ('b3'); SELECT * FROM test_like_id_3; -- identity was copied and applied DROP TABLE test_like_id_1, test_like_id_2, test_like_id_3; -CREATE TABLE test_like_gen_1 (a int, b int GENERATED ALWAYS AS (a * 2) STORED); +CREATE TABLE test_like_gen_1 (a int, b int GENERATED ALWAYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (a * 3) VIRTUAL); \d test_like_gen_1 INSERT INTO test_like_gen_1 (a) VALUES (1); SELECT * FROM test_like_gen_1; @@ -128,7 +128,8 @@ CREATE TABLE inhz (x text REFERENCES inhz, LIKE inhx INCLUDING INDEXES); DROP TABLE inhz; -- including storage and comments -CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text); +CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) ENFORCED PRIMARY KEY, + b text CHECK (length(b) > 100) NOT ENFORCED); CREATE INDEX ctlt1_b_key ON ctlt1 (b); CREATE INDEX ctlt1_fnidx ON ctlt1 ((a || b)); CREATE STATISTICS ctlt1_a_b_stat ON a,b FROM ctlt1; @@ -194,9 +195,10 @@ ROLLBACK; DROP TABLE ctlt1, ctlt2, ctlt3, ctlt4, ctlt12_storage, ctlt12_comments, ctlt1_inh, ctlt13_inh, ctlt13_like, ctlt_all, ctla, ctlb CASCADE; -- LIKE must respect NO INHERIT property of constraints -CREATE TABLE noinh_con_copy (a int CHECK (a > 0) NO INHERIT); +CREATE TABLE noinh_con_copy (a int CHECK (a > 0) NO INHERIT, b int not null, + c int not null no inherit); CREATE TABLE noinh_con_copy1 (LIKE noinh_con_copy INCLUDING CONSTRAINTS); -\d noinh_con_copy1 +\d+ noinh_con_copy1 -- fail, as partitioned tables don't allow NO INHERIT constraints CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL) @@ -223,3 +225,45 @@ DROP SEQUENCE ctlseq1; DROP TYPE ctlty1; DROP VIEW ctlv1; DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12; + +-- +-- CREATE FOREIGN TABLE LIKE +-- +CREATE FOREIGN DATA WRAPPER ctl_dummy; +CREATE SERVER ctl_s0 FOREIGN DATA WRAPPER ctl_dummy; + +CREATE TABLE ctl_table(a int PRIMARY KEY, + b varchar COMPRESSION pglz, + c int GENERATED ALWAYS AS (a * 2) STORED, + d bigint GENERATED ALWAYS AS IDENTITY, + e int DEFAULT 1); + +CREATE INDEX ctl_table_a_key ON ctl_table(a); +COMMENT ON COLUMN ctl_table.b IS 'Column b'; +CREATE STATISTICS ctl_table_stat ON a,b FROM ctl_table; +ALTER TABLE ctl_table ADD CONSTRAINT foo CHECK (b = 'text'); +ALTER TABLE ctl_table ALTER COLUMN b SET STORAGE MAIN; + +\d+ ctl_table + +-- Test EXCLUDING ALL +CREATE FOREIGN TABLE ctl_foreign_table1(LIKE ctl_table EXCLUDING ALL) SERVER ctl_s0; +\d+ ctl_foreign_table1 +-- \d+ does not report the value of attcompression for a foreign table, so +-- check separately. +SELECT attname, attcompression FROM pg_attribute + WHERE attrelid = 'ctl_foreign_table1'::regclass and attnum > 0 ORDER BY attnum; + +-- Test INCLUDING ALL +-- INDEXES, IDENTITY, COMPRESSION, STORAGE are not copied. +CREATE FOREIGN TABLE ctl_foreign_table2(LIKE ctl_table INCLUDING ALL) SERVER ctl_s0; +\d+ ctl_foreign_table2 +-- \d+ does not report the value of attcompression for a foreign table, so +-- check separately. +SELECT attname, attcompression FROM pg_attribute + WHERE attrelid = 'ctl_foreign_table2'::regclass and attnum > 0 ORDER BY attnum; + +DROP TABLE ctl_table; +DROP FOREIGN TABLE ctl_foreign_table1; +DROP FOREIGN TABLE ctl_foreign_table2; +DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE; diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql index 8838a40f7abbe..ae6841308b9b6 100644 --- a/src/test/regress/sql/create_view.sql +++ b/src/test/regress/sql/create_view.sql @@ -373,6 +373,22 @@ ALTER TABLE tmp1 RENAME TO tx1; \d+ aliased_view_3 \d+ aliased_view_4 +-- Test correct deparsing of ORDER BY when there is an output name conflict + +create view aliased_order_by as +select x1 as x2, x2 as x1, x3 from tt1 + order by x2; -- this is interpreted per SQL92, so really ordering by x1 + +\d+ aliased_order_by + +alter view aliased_order_by rename column x1 to x0; + +\d+ aliased_order_by + +alter view aliased_order_by rename column x3 to x1; + +\d+ aliased_order_by + -- Test aliasing of joins create view view_of_joins as @@ -813,6 +829,15 @@ select x + y + z as c1, from (values(1,2,3)) v(x,y,z); select pg_get_viewdef('tt26v', true); +-- test restriction on non-system view expansion. +create table tt27v_tbl (a int); +create view tt27v as select a from tt27v_tbl; +set restrict_nonsystem_relation_kind to 'view'; +select a from tt27v where a > 0; -- Error +insert into tt27v values (1); -- Error +select viewname from pg_views where viewname = 'tt27v'; -- Ok to access a system view. +reset restrict_nonsystem_relation_kind; + -- clean up all the random objects we made above DROP SCHEMA temp_view_test CASCADE; DROP SCHEMA testviewschm2 CASCADE; diff --git a/src/test/regress/sql/database.sql b/src/test/regress/sql/database.sql index 0367c0e37ab1f..46ad2634781ea 100644 --- a/src/test/regress/sql/database.sql +++ b/src/test/regress/sql/database.sql @@ -14,4 +14,11 @@ WHERE datname = 'regression_utf8'; ALTER DATABASE regression_utf8 RESET TABLESPACE; ROLLBACK; +CREATE ROLE regress_datdba_before; +CREATE ROLE regress_datdba_after; +ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; +REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; + DROP DATABASE regression_utf8; +DROP ROLE regress_datdba_before; +DROP ROLE regress_datdba_after; diff --git a/src/test/regress/sql/date.sql b/src/test/regress/sql/date.sql index 1c58ff6966dbb..805aec706cc06 100644 --- a/src/test/regress/sql/date.sql +++ b/src/test/regress/sql/date.sql @@ -371,5 +371,6 @@ select make_date(0, 7, 15); select make_date(2013, 2, 30); select make_date(2013, 13, 1); select make_date(2013, 11, -1); +SELECT make_date(-2147483648, 1, 1); select make_time(10, 55, 100.1); select make_time(24, 0, 2.1); diff --git a/src/test/regress/sql/dbsize.sql b/src/test/regress/sql/dbsize.sql index b34cf33385ebd..38b9444400768 100644 --- a/src/test/regress/sql/dbsize.sql +++ b/src/test/regress/sql/dbsize.sql @@ -27,6 +27,10 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM (11258449312612351::numeric), (11258449312612352::numeric), (11528652096115048447::numeric), (11528652096115048448::numeric)) x(size); +-- Ensure we get the expected results when passing the extremities of bigint +SELECT pg_size_pretty('-9223372036854775808'::bigint), + pg_size_pretty('9223372036854775807'::bigint); + -- pg_size_bytes() tests SELECT size, pg_size_bytes(size) FROM (VALUES ('1'), ('123bytes'), ('256 B'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '), diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index b5a70ee8be701..b752a63ab5f69 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -16,6 +16,20 @@ drop domain domaindroptest cascade; -- this should fail because already gone drop domain domaindroptest cascade; +-- some error cases +create domain d_fail as no_such_type; +create domain d_fail as int constraint cc REFERENCES this_table_not_exists(i); +create domain d_fail as int4 not null no inherit; +create domain d_fail as int4 not null null; +create domain d_fail as int4 not null default 3 default 3; +create domain d_fail int4 DEFAULT 3 + 'h'; +create domain d_fail int4 collate "C"; +create domain d_fail as anyelement; +create domain d_fail as int4 unique; +create domain d_fail as int4 PRIMARY key; +create domain d_fail as int4 constraint cc generated by default as identity; +create domain d_fail as int4 constraint cc check (values > 1) no inherit; +create domain d_fail as int4 constraint cc check (values > 1) deferrable; -- Test domain input. @@ -429,6 +443,17 @@ alter domain dnotnulltest drop not null; update domnotnull set col1 = null; +update domnotnull set col1 = 5; + +-- these constraints can also be added and removed by name +alter domain dnotnulltest add constraint dnotnulltest_notnull not null; +update domnotnull set col1 = null; -- fails +select conname, pg_get_constraintdef(oid) from pg_constraint + where contypid = 'dnotnulltest'::regtype; + +alter domain dnotnulltest drop constraint dnotnulltest_notnull; +update domnotnull set col1 = null; + drop domain dnotnulltest cascade; -- Test ALTER DOMAIN .. DEFAULT .. @@ -855,6 +880,16 @@ select pg_basetype(1); -- expect NULL not error drop domain mytext cascade; +-- +-- Explicit enforceability specification not allowed +--- +CREATE DOMAIN constraint_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; +CREATE DOMAIN constraint_not_enforced_dom AS int CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED; +CREATE DOMAIN constraint_enforced_dom AS int; +-- XXX misleading error messages +ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) ENFORCED; +ALTER DOMAIN constraint_enforced_dom ADD CONSTRAINT the_constraint CHECK (value > 0) NOT ENFORCED; +DROP DOMAIN constraint_enforced_dom; -- -- Information schema diff --git a/src/test/regress/sql/equivclass.sql b/src/test/regress/sql/equivclass.sql index 247b0a3105576..7fc2159349b6c 100644 --- a/src/test/regress/sql/equivclass.sql +++ b/src/test/regress/sql/equivclass.sql @@ -259,6 +259,22 @@ drop user regress_user_ectest; explain (costs off) select * from tenk1 where unique1 = unique1 and unique2 = unique2; +-- Test that broken ECs are processed correctly during self join removal. +-- Disable merge joins so that we don't get an error about missing commutator. +-- Test both orientations of the join clause, because only one of them breaks +-- the EC. +set enable_mergejoin to off; + +explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff + join ec1 p on m.ff + n.ff = p.f1; + +explain (costs off) + select * from ec0 m join ec0 n on m.ff = n.ff + join ec1 p on p.f1::int8 = (m.ff + n.ff)::int8alias1; + +reset enable_mergejoin; + -- this could be converted, but isn't at present explain (costs off) select * from tenk1 where unique1 = unique1 or unique2 = unique2; @@ -269,3 +285,37 @@ create temp view overview as select f1::information_schema.sql_identifier as sqli, f2 from undername; explain (costs off) -- this should not require a sort select * from overview where sqli = 'foo' order by sqli; + +-- +-- test handling of merge/hash clauses that do not have valid commutators +-- + +-- There are not (and should not be) any such operators built into Postgres +-- that are mergejoinable or hashable but have no commutators; so we leverage +-- the alias type 'int8alias1' created in this file to conduct the tests. +-- That's why this test is included here rather than in join.sql. + +begin; + +create table tbl_nocom(a int8, b int8alias1); + +-- check that non-commutable merge clauses do not lead to error +set enable_hashjoin to off; +set enable_mergejoin to on; +explain (costs off) +select * from tbl_nocom t1 full join tbl_nocom t2 on t2.a = t1.b; + +-- check that non-commutable hash clauses do not lead to error +alter operator = (int8, int8alias1) set (hashes); +alter operator family integer_ops using hash add + operator 1 = (int8, int8alias1); +create function hashint8alias1(int8alias1) returns int + strict immutable language internal as 'hashint8'; +alter operator family integer_ops using hash add + function 1 hashint8alias1(int8alias1); +set enable_hashjoin to on; +set enable_mergejoin to off; +explain (costs off) +select * from tbl_nocom t1 full join tbl_nocom t2 on t2.a = t1.b; + +abort; diff --git a/src/test/regress/sql/explain.sql b/src/test/regress/sql/explain.sql index c7055f850c557..7842d25ded3fe 100644 --- a/src/test/regress/sql/explain.sql +++ b/src/test/regress/sql/explain.sql @@ -62,14 +62,19 @@ set track_io_timing = off; -- Simple cases select explain_filter('explain select * from int8_tbl i8'); -select explain_filter('explain (analyze) select * from int8_tbl i8'); -select explain_filter('explain (analyze, verbose) select * from int8_tbl i8'); +select explain_filter('explain (analyze, buffers off) select * from int8_tbl i8'); +select explain_filter('explain (analyze, buffers off, verbose) select * from int8_tbl i8'); select explain_filter('explain (analyze, buffers, format text) select * from int8_tbl i8'); select explain_filter('explain (analyze, buffers, format xml) select * from int8_tbl i8'); select explain_filter('explain (analyze, serialize, buffers, format yaml) select * from int8_tbl i8'); select explain_filter('explain (buffers, format text) select * from int8_tbl i8'); select explain_filter('explain (buffers, format json) select * from int8_tbl i8'); +-- Check expansion of window definitions + +select explain_filter('explain verbose select sum(unique1) over w, sum(unique2) over (w order by hundred), sum(tenthous) over (w order by hundred) from tenk1 window w as (partition by ten)'); +select explain_filter('explain verbose select sum(unique1) over w1, sum(unique2) over (w1 order by hundred), sum(tenthous) over (w1 order by hundred rows 10 preceding) from tenk1 window w1 as (partition by ten)'); + -- Check output including I/O timings. These fields are conditional -- but always set in JSON format, so check them only in this case. set track_io_timing = on; @@ -96,7 +101,7 @@ select explain_filter('explain (analyze, generic_plan) select unique1 from tenk1 -- MEMORY option select explain_filter('explain (memory) select * from int8_tbl i8'); -select explain_filter('explain (memory, analyze) select * from int8_tbl i8'); +select explain_filter('explain (memory, analyze, buffers off) select * from int8_tbl i8'); select explain_filter('explain (memory, summary, format yaml) select * from int8_tbl i8'); select explain_filter('explain (memory, analyze, format json) select * from int8_tbl i8'); prepare int8_query as select * from int8_tbl i8; @@ -163,9 +168,22 @@ select explain_filter('explain (verbose) select * from t1 where pg_temp.mysin(f1 set compute_query_id = on; select explain_filter('explain (verbose) select * from int8_tbl i8'); +-- Test compute_query_id with utility statements containing plannable query +select explain_filter('explain (verbose) declare test_cur cursor for select * from int8_tbl'); +select explain_filter('explain (verbose) create table test_ctas as select 1'); + -- Test SERIALIZE option -select explain_filter('explain (analyze,serialize) select * from int8_tbl i8'); +select explain_filter('explain (analyze,buffers off,serialize) select * from int8_tbl i8'); select explain_filter('explain (analyze,serialize text,buffers,timing off) select * from int8_tbl i8'); select explain_filter('explain (analyze,serialize binary,buffers,timing) select * from int8_tbl i8'); -- this tests an edge case where we have no data to return -select explain_filter('explain (analyze,serialize) create temp table explain_temp as select * from int8_tbl i8'); +select explain_filter('explain (analyze,buffers off,serialize) create temp table explain_temp as select * from int8_tbl i8'); + +-- Test tuplestore storage usage in Window aggregate (memory case) +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over() from generate_series(1,10) a(n)'); +-- Test tuplestore storage usage in Window aggregate (disk case) +set work_mem to 64; +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over() from generate_series(1,2500) a(n)'); +-- Test tuplestore storage usage in Window aggregate (memory and disk case, final result is disk) +select explain_filter('explain (analyze,buffers off,costs off) select sum(n) over(partition by m) from (SELECT n < 3 as m, n from generate_series(1,2500) a(n))'); +reset work_mem; diff --git a/src/test/regress/sql/fast_default.sql b/src/test/regress/sql/fast_default.sql index dc9df78a35d5d..068dd0bc8aad0 100644 --- a/src/test/regress/sql/fast_default.sql +++ b/src/test/regress/sql/fast_default.sql @@ -66,6 +66,17 @@ ALTER TABLE has_volatile ADD col2 int DEFAULT 1; ALTER TABLE has_volatile ADD col3 timestamptz DEFAULT current_timestamp; ALTER TABLE has_volatile ADD col4 int DEFAULT (random() * 10000)::int; +-- virtual generated columns don't need a rewrite +ALTER TABLE has_volatile ADD col5 int GENERATED ALWAYS AS (tableoid::int + col2) VIRTUAL; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE float8; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE numeric; +ALTER TABLE has_volatile ALTER COLUMN col5 TYPE numeric; +-- here, we do need a rewrite +ALTER TABLE has_volatile ALTER COLUMN col1 SET DATA TYPE float8, + ADD COLUMN col6 float8 GENERATED ALWAYS AS (col1 * 4) VIRTUAL; +-- stored generated columns need a rewrite +ALTER TABLE has_volatile ADD col7 int GENERATED ALWAYS AS (55) stored; + -- Test a large sample of different datatypes @@ -237,6 +248,50 @@ SELECT comp(); DROP TABLE T; +-- Test domains with default value for table rewrite. +CREATE DOMAIN domain1 AS int DEFAULT 11; -- constant +CREATE DOMAIN domain2 AS int DEFAULT random(min=>10, max=>100); -- volatile +CREATE DOMAIN domain3 AS text DEFAULT foo(4); -- stable +CREATE DOMAIN domain4 AS text[] + DEFAULT ('{"This", "is", "' || foo(4) || '","the", "real", "world"}')::TEXT[]; + +CREATE TABLE t2 (a domain1); +INSERT INTO t2 VALUES (1),(2); + +-- no table rewrite +ALTER TABLE t2 ADD COLUMN b domain1 default 3; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN c domain3 default left(random()::text,3); + +-- no table rewrite +ALTER TABLE t2 ADD COLUMN d domain4; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +-- table rewrite should happen +ALTER TABLE t2 ADD COLUMN e domain2; + +SELECT attnum, attname, atthasmissing, atthasdef, attmissingval +FROM pg_attribute +WHERE attnum > 0 AND attrelid = 't2'::regclass +ORDER BY attnum; + +SELECT a, b, length(c) = 3 as c_ok, d, e >= 10 as e_ok FROM t2; + +DROP TABLE t2; +DROP DOMAIN domain1; +DROP DOMAIN domain2; +DROP DOMAIN domain3; +DROP DOMAIN domain4; DROP FUNCTION foo(INT); -- Fall back to full rewrite for volatile expressions diff --git a/src/test/regress/sql/float4.sql b/src/test/regress/sql/float4.sql index 8fb12368c39b1..44418a64002ed 100644 --- a/src/test/regress/sql/float4.sql +++ b/src/test/regress/sql/float4.sql @@ -98,7 +98,7 @@ UPDATE FLOAT4_TBL SET f1 = FLOAT4_TBL.f1 * '-1' WHERE FLOAT4_TBL.f1 > '0.0'; -SELECT * FROM FLOAT4_TBL; +SELECT * FROM FLOAT4_TBL ORDER BY 1; -- test edge-case coercions to integer SELECT '32767.4'::float4::int2; diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql index 98e9926c9e054..0ef271f27020e 100644 --- a/src/test/regress/sql/float8.sql +++ b/src/test/regress/sql/float8.sql @@ -197,7 +197,7 @@ SELECT exp(f.f1) from FLOAT8_TBL f; SELECT f.f1 / '0.0' from FLOAT8_TBL f; -SELECT * FROM FLOAT8_TBL; +SELECT * FROM FLOAT8_TBL ORDER BY 1; -- hyperbolic functions -- we run these with extra_float_digits = 0 too, since different platforms @@ -245,6 +245,29 @@ FROM (VALUES (float8 '-infinity'), RESET extra_float_digits; +-- gamma functions +-- we run these with extra_float_digits = -1, to get consistently rounded +-- results on all platforms. +SET extra_float_digits = -1; +SELECT x, + gamma(x), + lgamma(x) +FROM (VALUES (0.5), (1), (2), (3), (4), (5), + (float8 'infinity'), (float8 'nan')) AS t(x); +-- test overflow/underflow handling +SELECT gamma(float8 '-infinity'); +SELECT lgamma(float8 '-infinity'); +SELECT gamma(float8 '-1000.5'); +SELECT lgamma(float8 '-1000.5'); +SELECT gamma(float8 '-1'); +SELECT lgamma(float8 '-1'); +SELECT gamma(float8 '0'); +SELECT lgamma(float8 '0'); +SELECT gamma(float8 '1000'); +SELECT lgamma(float8 '1000'); +SELECT lgamma(float8 '1e308'); +RESET extra_float_digits; + -- test for over- and underflow INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); @@ -328,6 +351,7 @@ create function xfloat8in(cstring) returns xfloat8 immutable strict language internal as 'int8in'; create function xfloat8out(xfloat8) returns cstring immutable strict language internal as 'int8out'; +create type xfloat8 (input = xfloat8in, output = xfloat8out, like = no_such_type); create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8); create cast (xfloat8 as float8) without function; create cast (float8 as xfloat8) without function; diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql index f5e093899974e..cfcecb4e911ad 100644 --- a/src/test/regress/sql/foreign_key.sql +++ b/src/test/regress/sql/foreign_key.sql @@ -2,23 +2,46 @@ -- FOREIGN KEY -- --- MATCH FULL +-- NOT ENFORCED -- -- First test, check and cascade -- CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); -CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int ); +CREATE TABLE FKTABLE ( ftest1 int CONSTRAINT fktable_ftest1_fkey REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE NOT ENFORCED, + ftest2 int ); --- Insert test data into PKTABLE +-- Inserting into the foreign key table will not result in an error, even if +-- there is no matching key in the referenced table. +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); + +-- Check FKTABLE +SELECT * FROM FKTABLE; + +-- Reverting it back to ENFORCED will result in failure because constraint validation will be triggered, +-- as it was previously in a valid state. +ALTER TABLE FKTABLE ALTER CONSTRAINT fktable_ftest1_fkey ENFORCED; + +-- Insert referenced data that satisfies the constraint, then attempt to +-- change it. INSERT INTO PKTABLE VALUES (1, 'Test1'); INSERT INTO PKTABLE VALUES (2, 'Test2'); +ALTER TABLE FKTABLE ALTER CONSTRAINT fktable_ftest1_fkey ENFORCED; + +-- Any further inserts will fail due to the enforcement. +INSERT INTO FKTABLE VALUES (3, 4); + +-- +-- MATCH FULL +-- +-- First test, check and cascade +-- +-- Insert test data into PKTABLE INSERT INTO PKTABLE VALUES (3, 'Test3'); INSERT INTO PKTABLE VALUES (4, 'Test4'); INSERT INTO PKTABLE VALUES (5, 'Test5'); -- Insert successful rows into FK TABLE -INSERT INTO FKTABLE VALUES (1, 2); -INSERT INTO FKTABLE VALUES (2, 3); INSERT INTO FKTABLE VALUES (3, 4); INSERT INTO FKTABLE VALUES (NULL, 1); @@ -230,6 +253,27 @@ INSERT INTO FKTABLE VALUES (1, NULL); ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE MATCH FULL; +-- Modifying other attributes of a constraint should not affect its enforceability, and vice versa +ALTER TABLE FKTABLE ADD CONSTRAINT fk_con FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE NOT VALID NOT ENFORCED; +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con DEFERRABLE INITIALLY DEFERRED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con NOT ENFORCED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + +-- Enforceability also changes the validate state, as data validation will be +-- performed during this transformation. +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con ENFORCED; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + +-- Can change enforceability and deferrability together +ALTER TABLE FKTABLE ALTER CONSTRAINT fk_con NOT ENFORCED NOT DEFERRABLE; +SELECT condeferrable, condeferred, conenforced, convalidated +FROM pg_constraint WHERE conname = 'fk_con'; + DROP TABLE FKTABLE; DROP TABLE PKTABLE; @@ -473,7 +517,8 @@ CREATE TABLE FKTABLE ( fk_id_del_set_null int, fk_id_del_set_default int DEFAULT 0, FOREIGN KEY (tid, fk_id_del_set_null) REFERENCES PKTABLE ON DELETE SET NULL (fk_id_del_set_null), - FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default) + -- this tests handling of duplicate entries in SET DEFAULT column list + FOREIGN KEY (tid, fk_id_del_set_default) REFERENCES PKTABLE ON DELETE SET DEFAULT (fk_id_del_set_default, fk_id_del_set_default) ); SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = 'fktable'::regclass::oid ORDER BY oid; @@ -968,10 +1013,25 @@ INSERT INTO fktable VALUES (0, 20); COMMIT; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT ENFORCED; + +BEGIN; + +-- doesn't match FK, but no error. +UPDATE pktable SET id = 10 WHERE id = 5; +-- doesn't match PK, but no error. +INSERT INTO fktable VALUES (0, 20); + +ROLLBACK; + -- try additional syntax ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE; --- illegal option +-- illegal options ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; +ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey ENFORCED NOT ENFORCED; +CREATE TEMP TABLE fktable2 (fk int references pktable ENFORCED NOT ENFORCED); -- test order of firing of FK triggers when several RI-induced changes need to -- be made to the same row. This was broken by subtransaction-related @@ -1182,11 +1242,14 @@ ALTER TABLE fk_partitioned_fk DROP COLUMN fdrop1; CREATE TABLE fk_partitioned_fk_1 (fdrop1 int, fdrop2 int, a int, fdrop3 int, b int); ALTER TABLE fk_partitioned_fk_1 DROP COLUMN fdrop1, DROP COLUMN fdrop2, DROP COLUMN fdrop3; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_1 FOR VALUES FROM (0,0) TO (1000,1000); -ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk ADD CONSTRAINT fk_partitioned_fk_a_b_fkey FOREIGN KEY (a, b) + REFERENCES fk_notpartitioned_pk NOT ENFORCED; CREATE TABLE fk_partitioned_fk_2 (b int, fdrop1 int, fdrop2 int, a int); ALTER TABLE fk_partitioned_fk_2 DROP COLUMN fdrop1, DROP COLUMN fdrop2; +ALTER TABLE fk_partitioned_fk_2 ADD CONSTRAINT fk_partitioned_fk_a_b_fkey FOREIGN KEY (a, b) + REFERENCES fk_notpartitioned_pk NOT ENFORCED; ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); - +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey ENFORCED; CREATE TABLE fk_partitioned_fk_3 (fdrop1 int, fdrop2 int, fdrop3 int, fdrop4 int, b int, a int) PARTITION BY HASH (a); ALTER TABLE fk_partitioned_fk_3 DROP COLUMN fdrop1, DROP COLUMN fdrop2, @@ -1200,10 +1263,6 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_3 -- a non-partitioned table fails. ALTER TABLE ONLY fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; --- Adding a NOT VALID foreign key on a partitioned table referencing --- a non-partitioned table fails. -ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) - REFERENCES fk_notpartitioned_pk NOT VALID; -- these inserts, targeting both the partition directly as well as the -- partitioned table, should all fail @@ -1236,6 +1295,32 @@ UPDATE fk_notpartitioned_pk SET b = 1502 WHERE a = 1500; UPDATE fk_notpartitioned_pk SET b = 2504 WHERE a = 2500; -- check psql behavior \d fk_notpartitioned_pk + +-- Check the exsting FK trigger +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey NOT ENFORCED; +-- No triggers +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + +-- Changing it back to ENFORCED will recreate the necessary triggers. +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey ENFORCED; + +-- Should be exactly the same number of triggers found as before +SELECT conname, tgrelid::regclass as tgrel, regexp_replace(tgname, '[0-9]+', 'N') as tgname, tgtype +FROM pg_trigger t JOIN pg_constraint c ON (t.tgconstraint = c.oid) +WHERE tgrelid IN (SELECT relid FROM pg_partition_tree('fk_partitioned_fk'::regclass) + UNION ALL SELECT 'fk_notpartitioned_pk'::regclass) +ORDER BY tgrelid, tgtype; + ALTER TABLE fk_partitioned_fk DROP CONSTRAINT fk_partitioned_fk_a_b_fkey; -- done. DROP TABLE fk_notpartitioned_pk, fk_partitioned_fk; @@ -1251,6 +1336,99 @@ ALTER TABLE fk_notpartitioned_pk ALTER COLUMN a TYPE bigint; DELETE FROM fk_notpartitioned_pk WHERE a = 1; DROP TABLE fk_notpartitioned_pk, fk_partitioned_fk; +-- NOT VALID foreign keys on partitioned table +CREATE TABLE fk_notpartitioned_pk (a int, b int, PRIMARY KEY (a, b)); +CREATE TABLE fk_partitioned_fk (b int, a int) PARTITION BY RANGE (a, b); +ALTER TABLE fk_partitioned_fk ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; + +-- Attaching a child table with the same valid foreign key constraint. +CREATE TABLE fk_partitioned_fk_1 (a int, b int); +ALTER TABLE fk_partitioned_fk_1 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_1 FOR VALUES FROM (0,0) TO (1000,1000); + +-- Child constraint will remain valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + +-- Validate the constraint +ALTER TABLE fk_partitioned_fk VALIDATE CONSTRAINT fk_partitioned_fk_a_b_fkey; + +-- All constraints are now valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + +-- Attaching a child with a NOT VALID constraint. +CREATE TABLE fk_partitioned_fk_2 (a int, b int); +INSERT INTO fk_partitioned_fk_2 VALUES(1000, 1000); -- doesn't exist in referenced table +ALTER TABLE fk_partitioned_fk_2 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; + +-- It will fail because the attach operation implicitly validates the data. +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); + +-- Remove the invalid data and try again. +TRUNCATE fk_partitioned_fk_2; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES FROM (1000,1000) TO (2000,2000); + +-- The child constraint will also be valid. +SELECT conname, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_fk_2'::regclass ORDER BY oid::regclass::text; + +-- Test case where the child constraint is invalid, the grandchild constraint +-- is valid, and the validation for the grandchild should be skipped when a +-- valid constraint is applied to the top parent. +CREATE TABLE fk_partitioned_fk_3 (a int, b int) PARTITION BY RANGE (a, b); +ALTER TABLE fk_partitioned_fk_3 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk NOT VALID; +CREATE TABLE fk_partitioned_fk_3_1 (a int, b int); +ALTER TABLE fk_partitioned_fk_3_1 ADD FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk; +ALTER TABLE fk_partitioned_fk_3 ATTACH PARTITION fk_partitioned_fk_3_1 FOR VALUES FROM (2000,2000) TO (3000,3000); +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_3 FOR VALUES FROM (2000,2000) TO (3000,3000); + +-- All constraints are now valid. +SELECT conname, convalidated, conrelid::regclass FROM pg_constraint +WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass::text; + +DROP TABLE fk_partitioned_fk, fk_notpartitioned_pk; + +-- NOT VALID and NOT ENFORCED foreign key on a non-partitioned table +-- referencing a partitioned table +CREATE TABLE fk_partitioned_pk (a int, b int, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b); +CREATE TABLE fk_partitioned_pk_1 PARTITION OF fk_partitioned_pk FOR VALUES FROM (0,0) TO (1000,1000); +CREATE TABLE fk_partitioned_pk_2 PARTITION OF fk_partitioned_pk FOR VALUES FROM (1000,1000) TO (2000,2000); +CREATE TABLE fk_notpartitioned_fk (b int, a int); +INSERT INTO fk_partitioned_pk VALUES(100,100), (1000,1000); +INSERT INTO fk_notpartitioned_fk VALUES(100,100), (1000,1000); +ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey + FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID; +ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 + FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT ENFORCED; + +-- All constraints will be invalid, and _fkey2 constraints will not be enforced. +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text; + +ALTER TABLE fk_notpartitioned_fk VALIDATE CONSTRAINT fk_notpartitioned_fk_a_b_fkey; +ALTER TABLE fk_notpartitioned_fk ALTER CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 ENFORCED; + +-- All constraints are now valid and enforced. +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text; + +-- test a self-referential FK +ALTER TABLE fk_partitioned_pk ADD CONSTRAINT selffk FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID; +CREATE TABLE fk_partitioned_pk_3 PARTITION OF fk_partitioned_pk FOR VALUES FROM (2000,2000) TO (3000,3000) + PARTITION BY RANGE (a); +CREATE TABLE fk_partitioned_pk_3_1 PARTITION OF fk_partitioned_pk_3 FOR VALUES FROM (2000) TO (2100); +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_pk'::regclass AND contype = 'f' +ORDER BY oid::regclass::text; +ALTER TABLE fk_partitioned_pk_2 VALIDATE CONSTRAINT selffk; +ALTER TABLE fk_partitioned_pk VALIDATE CONSTRAINT selffk; +SELECT conname, conenforced, convalidated FROM pg_constraint +WHERE conrelid = 'fk_partitioned_pk'::regclass AND contype = 'f' +ORDER BY oid::regclass::text; + +DROP TABLE fk_notpartitioned_fk, fk_partitioned_pk; + -- Test some other exotic foreign key features: MATCH SIMPLE, ON UPDATE/DELETE -- actions CREATE TABLE fk_notpartitioned_pk (a int, b int, primary key (a, b)); @@ -1372,6 +1550,25 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN \d fk_partitioned_fk_2 DROP TABLE fk_partitioned_fk_2; +CREATE TABLE fk_partitioned_fk_2 (b int, a int, + CONSTRAINT fk_part_con FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk ON UPDATE CASCADE ON DELETE CASCADE NOT ENFORCED); +-- fail -- cannot merge constraints with different enforceability. +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +-- If the constraint is modified to match the enforceability of the parent, it will work. +BEGIN; +-- change child constraint +ALTER TABLE fk_partitioned_fk_2 ALTER CONSTRAINT fk_part_con ENFORCED; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +\d fk_partitioned_fk_2 +ROLLBACK; +BEGIN; +-- or change parent constraint +ALTER TABLE fk_partitioned_fk ALTER CONSTRAINT fk_partitioned_fk_a_b_fkey NOT ENFORCED; +ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 FOR VALUES IN (1500,1502); +\d fk_partitioned_fk_2 +ROLLBACK; +DROP TABLE fk_partitioned_fk_2; + CREATE TABLE fk_partitioned_fk_4 (a int, b int, FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE CASCADE ON DELETE CASCADE) PARTITION BY RANGE (b, a); CREATE TABLE fk_partitioned_fk_4_1 PARTITION OF fk_partitioned_fk_4 FOR VALUES FROM (1,1) TO (100,100); CREATE TABLE fk_partitioned_fk_4_2 (a int, b int, FOREIGN KEY (a, b) REFERENCES fk_notpartitioned_pk(a, b) ON UPDATE SET NULL); @@ -1417,6 +1614,34 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2 -- leave these tables around intentionally +-- Verify that attaching a table that's referenced by an existing FK +-- in the parent throws an error +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; + +-- Verify that attaching to a parent with two identical constraints work +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY); +CREATE TABLE fk_partitioned_fk_6 (a int, + FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6, + FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6 +) PARTITION BY LIST (a); +CREATE TABLE fk_partitioned_fk_6_1 PARTITION OF fk_partitioned_fk_6 FOR VALUES IN (1); +ALTER TABLE fk_partitioned_fk_6 DETACH PARTITION fk_partitioned_fk_6_1; +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_fk_6_1 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; + +-- This case is similar to above, but the referenced relation is one level +-- lower in the hierarchy. This one fails in a different way as the above, +-- because we don't bother to protect against this case explicitly. If the +-- current error stops happening, we'll need to add a better protection. +CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY) PARTITION BY list (a); +CREATE TABLE fk_partitioned_pk_61 PARTITION OF fk_partitioned_pk_6 FOR VALUES IN (1); +CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_61) PARTITION BY LIST (a); +ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1); +DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6; + -- test the case when the referenced table is owned by a different user create role regress_other_partitioned_fk_owner; grant references on fk_notpartitioned_pk to regress_other_partitioned_fk_owner; @@ -1470,29 +1695,52 @@ CREATE TABLE part33_self_fk ( ); ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); -SELECT cr.relname, co.conname, co.contype, co.convalidated, +-- verify that this constraint works +INSERT INTO parted_self_fk VALUES (1, NULL), (2, NULL), (3, NULL); +INSERT INTO parted_self_fk VALUES (10, 1), (11, 2), (12, 3) RETURNING tableoid::regclass; + +INSERT INTO parted_self_fk VALUES (4, 5); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 1 RETURNING *; -- error: reference remains + +SELECT cr.relname, co.conname, co.convalidated, p.conname AS conparent, p.convalidated, cf.relname AS foreignrel FROM pg_constraint co JOIN pg_class cr ON cr.oid = co.conrelid LEFT JOIN pg_class cf ON cf.oid = co.confrelid LEFT JOIN pg_constraint p ON p.oid = co.conparentid -WHERE cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) -ORDER BY co.contype, cr.relname, co.conname, p.conname; +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; -- detach and re-attach multiple times just to ensure everything is kosher ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; + +INSERT INTO part2_self_fk VALUES (16, 9); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 2 RETURNING *; -- error: reference remains + ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); + +INSERT INTO parted_self_fk VALUES (16, 9); -- error: referenced doesn't exist +DELETE FROM parted_self_fk WHERE id = 3 RETURNING *; -- error: reference remains + ALTER TABLE parted_self_fk DETACH PARTITION part2_self_fk; ALTER TABLE parted_self_fk ATTACH PARTITION part2_self_fk FOR VALUES FROM (10) TO (20); -SELECT cr.relname, co.conname, co.contype, co.convalidated, +ALTER TABLE parted_self_fk DETACH PARTITION part3_self_fk; +ALTER TABLE parted_self_fk ATTACH PARTITION part3_self_fk FOR VALUES FROM (30) TO (40); + +ALTER TABLE part3_self_fk DETACH PARTITION part33_self_fk; +ALTER TABLE part3_self_fk ATTACH PARTITION part33_self_fk FOR VALUES FROM (30) TO (40); + +SELECT cr.relname, co.conname, co.convalidated, p.conname AS conparent, p.convalidated, cf.relname AS foreignrel FROM pg_constraint co JOIN pg_class cr ON cr.oid = co.conrelid LEFT JOIN pg_class cf ON cf.oid = co.confrelid LEFT JOIN pg_constraint p ON p.oid = co.conparentid -WHERE cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) -ORDER BY co.contype, cr.relname, co.conname, p.conname; +WHERE co.contype = 'f' AND + cr.oid IN (SELECT relid FROM pg_partition_tree('parted_self_fk')) +ORDER BY cr.relname, co.conname, p.conname; -- Leave this table around, for pg_upgrade/pg_dump tests @@ -1655,6 +1903,14 @@ DELETE FROM pk WHERE a = 4002; UPDATE pk SET a = 4502 WHERE a = 4500; DELETE FROM pk WHERE a = 4502; +-- Also, detaching a partition that has the FK itself should work +-- https://postgr.es/m/CAAJ_b97GuPh6wQPbxQS-Zpy16Oh+0aMv-w64QcGrLhCOZZ6p+g@mail.gmail.com +CREATE TABLE ffk (a int, b int REFERENCES pk) PARTITION BY list (a); +CREATE TABLE ffk1 PARTITION OF ffk FOR VALUES IN (1); +ALTER TABLE ffk1 ADD FOREIGN KEY (a) REFERENCES pk; +ALTER TABLE ffk DETACH PARTITION ffk1; +DROP TABLE ffk, ffk1; + CREATE SCHEMA fkpart4; SET search_path TO fkpart4; -- dropping/detaching PARTITIONs is prevented if that would break @@ -1806,7 +2062,7 @@ CREATE TABLE pt1 PARTITION OF pt1_2 FOR VALUES IN (1); CREATE TABLE pt2 PARTITION OF pt1_2 FOR VALUES IN (2); CREATE TABLE ref(f1 int, f2 int, f3 int); ALTER TABLE ref ADD FOREIGN KEY(f1,f2) REFERENCES pt; -ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey1 +ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey_1 DEFERRABLE INITIALLY DEFERRED; -- fails ALTER TABLE ref ALTER CONSTRAINT ref_f1_f2_fkey DEFERRABLE INITIALLY DEFERRED; @@ -2069,3 +2325,64 @@ UPDATE fkpart11.pk SET a = 3 WHERE a = 4; UPDATE fkpart11.pk SET a = 1 WHERE a = 2; DROP SCHEMA fkpart11 CASCADE; + +-- When a table is attached as partition to a partitioned table that has +-- a foreign key to another partitioned table, it acquires a clone of the +-- FK. Upon detach, this clone is not removed, but instead becomes an +-- independent FK. If it then attaches to the partitioned table again, +-- the FK from the parent "takes over" ownership of the independent FK rather +-- than creating a separate one. +CREATE SCHEMA fkpart12 + CREATE TABLE fk_p ( id int, jd int, PRIMARY KEY(id, jd)) PARTITION BY list (id) + CREATE TABLE fk_p_1 PARTITION OF fk_p FOR VALUES IN (1) PARTITION BY list (jd) + CREATE TABLE fk_p_1_1 PARTITION OF fk_p_1 FOR VALUES IN (1) + CREATE TABLE fk_p_1_2 (x int, y int, jd int NOT NULL, id int NOT NULL) + CREATE TABLE fk_p_2 PARTITION OF fk_p FOR VALUES IN (2) PARTITION BY list (jd) + CREATE TABLE fk_p_2_1 PARTITION OF fk_p_2 FOR VALUES IN (1) + CREATE TABLE fk_p_2_2 PARTITION OF fk_p_2 FOR VALUES IN (2) + CREATE TABLE fk_r_1 ( p_jd int NOT NULL, x int, id int PRIMARY KEY, p_id int NOT NULL) + CREATE TABLE fk_r_2 ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL) PARTITION BY list (id) + CREATE TABLE fk_r_2_1 PARTITION OF fk_r_2 FOR VALUES IN (2, 1) + CREATE TABLE fk_r ( id int PRIMARY KEY, p_id int NOT NULL, p_jd int NOT NULL, + FOREIGN KEY (p_id, p_jd) REFERENCES fk_p (id, jd) + ) PARTITION BY list (id); +SET search_path TO fkpart12; + +ALTER TABLE fk_p_1_2 DROP COLUMN x, DROP COLUMN y; +ALTER TABLE fk_p_1 ATTACH PARTITION fk_p_1_2 FOR VALUES IN (2); +ALTER TABLE fk_r_1 DROP COLUMN x; + +INSERT INTO fk_p VALUES (1, 1); + +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); + +\d fk_r_2 + +INSERT INTO fk_r VALUES (1, 1, 1); +INSERT INTO fk_r VALUES (2, 2, 1); + +ALTER TABLE fk_r DETACH PARTITION fk_r_1; +ALTER TABLE fk_r DETACH PARTITION fk_r_2; + +\d fk_r_2 + +INSERT INTO fk_r_1 (id, p_id, p_jd) VALUES (2, 1, 2); -- should fail +DELETE FROM fk_p; -- should fail + +ALTER TABLE fk_r ATTACH PARTITION fk_r_1 FOR VALUES IN (1); +ALTER TABLE fk_r ATTACH PARTITION fk_r_2 FOR VALUES IN (2); + +\d fk_r_2 + +DELETE FROM fk_p; -- should fail + +-- these should all fail +ALTER TABLE fk_r_1 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; +ALTER TABLE fk_r DROP CONSTRAINT fk_r_p_id_p_jd_fkey_1; +ALTER TABLE fk_r_2 DROP CONSTRAINT fk_r_p_id_p_jd_fkey; + +SET client_min_messages TO warning; +DROP SCHEMA fkpart12 CASCADE; +RESET client_min_messages; +RESET search_path; diff --git a/src/test/regress/sql/generated.sql b/src/test/regress/sql/generated_stored.sql similarity index 84% rename from src/test/regress/sql/generated.sql rename to src/test/regress/sql/generated_stored.sql index cb55d77821f21..4ec155f2da989 100644 --- a/src/test/regress/sql/generated.sql +++ b/src/test/regress/sql/generated_stored.sql @@ -1,13 +1,16 @@ --- sanity check of system catalog -SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's'); +-- keep these tests aligned with generated_virtual.sql + +CREATE SCHEMA generated_stored_tests; +GRANT USAGE ON SCHEMA generated_stored_tests TO PUBLIC; +SET search_path = generated_stored_tests; CREATE TABLE gtest0 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (55) STORED); CREATE TABLE gtest1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED); -SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_name LIKE 'gtest_' ORDER BY 1, 2; +SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_schema = 'generated_stored_tests' ORDER BY 1, 2; -SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage ORDER BY 1, 2, 3; +SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage WHERE table_schema = 'generated_stored_tests' ORDER BY 1, 2, 3; \d gtest1 @@ -56,6 +59,8 @@ INSERT INTO gtest1 VALUES (3, 33), (4, DEFAULT); -- error INSERT INTO gtest1 VALUES (3, DEFAULT), (4, DEFAULT); -- ok SELECT * FROM gtest1 ORDER BY a; +SELECT gtest1 FROM gtest1 ORDER BY a; -- whole-row reference +SELECT a, (SELECT gtest1.b) FROM gtest1 ORDER BY a; -- sublink DELETE FROM gtest1 WHERE a >= 3; UPDATE gtest1 SET b = DEFAULT WHERE a = 1; @@ -79,7 +84,7 @@ DROP TABLE gtestx; -- test UPDATE/DELETE quals SELECT * FROM gtest1 ORDER BY a; -UPDATE gtest1 SET a = 3 WHERE b = 4; +UPDATE gtest1 SET a = 3 WHERE b = 4 RETURNING old.*, new.*; SELECT * FROM gtest1 ORDER BY a; DELETE FROM gtest1 WHERE b = 2; SELECT * FROM gtest1 ORDER BY a; @@ -95,10 +100,19 @@ CREATE TABLE gtestm ( INSERT INTO gtestm VALUES (1, 5, 100); MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id WHEN MATCHED THEN UPDATE SET f1 = v.f1 - WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200); + WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200) + RETURNING merge_action(), old.*, new.*; SELECT * FROM gtestm ORDER BY id; DROP TABLE gtestm; +CREATE TABLE gtestm ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) STORED +); +INSERT INTO gtestm (a) SELECT g FROM generate_series(1, 10) g; +MERGE INTO gtestm t USING gtestm AS s ON 2 * t.a = s.b WHEN MATCHED THEN DELETE RETURNING *; +DROP TABLE gtestm; + -- views CREATE VIEW gtest1v AS SELECT * FROM gtest1; SELECT * FROM gtest1v; @@ -138,8 +152,12 @@ DROP TABLE gtest_normal, gtest_normal_child; -- test inheritance mismatches between parent and child CREATE TABLE gtestx (x int, b int DEFAULT 10) INHERITS (gtest1); -- error CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS IDENTITY) INHERITS (gtest1); -- error +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) VIRTUAL) INHERITS (gtest1); -- error CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) STORED) INHERITS (gtest1); -- ok, overrides parent \d+ gtestx +INSERT INTO gtestx (a, x) VALUES (11, 22); +SELECT * FROM gtest1; +SELECT * FROM gtestx; CREATE TABLE gtestxx_1 (a int NOT NULL, b int); ALTER TABLE gtestxx_1 INHERIT gtest1; -- error @@ -265,26 +283,27 @@ INSERT INTO gtest10a (a) VALUES (1); -- privileges CREATE USER regress_user11; -CREATE TABLE gtest11s (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); -INSERT INTO gtest11s VALUES (1, 10), (2, 20); -GRANT SELECT (a, c) ON gtest11s TO regress_user11; +CREATE TABLE gtest11 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); +INSERT INTO gtest11 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c) ON gtest11 TO regress_user11; CREATE FUNCTION gf1(a int) RETURNS int AS $$ SELECT a * 3 $$ IMMUTABLE LANGUAGE SQL; REVOKE ALL ON FUNCTION gf1(int) FROM PUBLIC; -CREATE TABLE gtest12s (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) STORED); -INSERT INTO gtest12s VALUES (1, 10), (2, 20); -GRANT SELECT (a, c) ON gtest12s TO regress_user11; +CREATE TABLE gtest12 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) STORED); +INSERT INTO gtest12 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c), INSERT ON gtest12 TO regress_user11; SET ROLE regress_user11; -SELECT a, b FROM gtest11s; -- not allowed -SELECT a, c FROM gtest11s; -- allowed +SELECT a, b FROM gtest11; -- not allowed +SELECT a, c FROM gtest11; -- allowed SELECT gf1(10); -- not allowed -SELECT a, c FROM gtest12s; -- allowed +INSERT INTO gtest12 VALUES (3, 30), (4, 40); -- currently not allowed because of function permissions, should arguably be allowed +SELECT a, c FROM gtest12; -- allowed (does not actually invoke the function) RESET ROLE; DROP FUNCTION gf1(int); -- fail -DROP TABLE gtest11s, gtest12s; +DROP TABLE gtest11, gtest12; DROP FUNCTION gf1(int); DROP USER regress_user11; @@ -300,6 +319,9 @@ CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STOR INSERT INTO gtest20a (a) VALUES (10); INSERT INTO gtest20a (a) VALUES (30); ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row +-- table rewrite cases +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED); INSERT INTO gtest20b (a) VALUES (10); @@ -307,6 +329,12 @@ INSERT INTO gtest20b (a) VALUES (30); ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID; ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row +-- check with whole-row reference +CREATE TABLE gtest20c (a int, b int GENERATED ALWAYS AS (a * 2) STORED); +ALTER TABLE gtest20c ADD CONSTRAINT whole_row_check CHECK (gtest20c IS NOT NULL); +INSERT INTO gtest20c VALUES (1); -- ok +INSERT INTO gtest20c VALUES (NULL); -- fails + -- not-null constraints CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOT NULL); INSERT INTO gtest21a (a) VALUES (1); -- ok @@ -386,6 +414,15 @@ CREATE DOMAIN gtestdomain1 AS int CHECK (VALUE < 10); CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * 2) STORED); INSERT INTO gtest24 (a) VALUES (4); -- ok INSERT INTO gtest24 (a) VALUES (6); -- error +CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); +CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) STORED); +INSERT INTO gtest24r (a) VALUES (4); -- ok +INSERT INTO gtest24r (a) VALUES (6); -- error + +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) STORED); +INSERT INTO gtest24nn (a) VALUES (4); -- ok +INSERT INTO gtest24nn (a) VALUES (NULL); -- error -- typed tables (currently not supported) CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); @@ -413,6 +450,9 @@ CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error ) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 GENERATED ALWAYS AS (f2 * 2) VIRTUAL -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint); ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error DROP TABLE gtest_child3; @@ -422,6 +462,9 @@ DROP TABLE gtest_child3; CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY); ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +DROP TABLE gtest_child3; CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED); ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); \d gtest_child @@ -431,6 +474,9 @@ INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 1); INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 2); INSERT INTO gtest_parent (f1, f2) VALUES ('2016-08-15', 3); SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; +SELECT tableoid::regclass, * FROM gtest_child ORDER BY 1, 2, 3; +SELECT tableoid::regclass, * FROM gtest_child2 ORDER BY 1, 2, 3; +SELECT tableoid::regclass, * FROM gtest_child3 ORDER BY 1, 2, 3; UPDATE gtest_parent SET f1 = f1 + 60 WHERE f2 = 1; SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; @@ -545,6 +591,18 @@ ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error \d gtest30_1 ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error +-- composite type dependencies +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +DROP TABLE gtest31_1, gtest31_2; + +-- Check it for a partitioned table, too +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text) PARTITION BY LIST (a); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +DROP TABLE gtest31_1, gtest31_2; + -- triggers CREATE TABLE gtest26 ( a int PRIMARY KEY, @@ -630,7 +688,7 @@ UPDATE gtest26 SET a = 1 WHERE a = 0; DROP TRIGGER gtest11 ON gtest26; TRUNCATE gtest26; --- check that modifications of stored generated columns in triggers do +-- check that modifications of generated columns in triggers do -- not get propagated CREATE FUNCTION gtest_trigger_func4() RETURNS trigger LANGUAGE plpgsql @@ -642,20 +700,21 @@ BEGIN END; $$; -CREATE TRIGGER gtest12_01 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_01 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func(); -CREATE TRIGGER gtest12_02 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_02 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func4(); -CREATE TRIGGER gtest12_03 BEFORE UPDATE ON gtest26 +CREATE TRIGGER gtest12_03 BEFORE INSERT OR UPDATE ON gtest26 FOR EACH ROW EXECUTE PROCEDURE gtest_trigger_func(); INSERT INTO gtest26 (a) VALUES (1); -UPDATE gtest26 SET a = 11 WHERE a = 1; +SELECT * FROM gtest26 ORDER BY a; +UPDATE gtest26 SET a = 11 WHERE a = 10; SELECT * FROM gtest26 ORDER BY a; -- LIKE INCLUDING GENERATED and dropped column handling @@ -671,3 +730,7 @@ ALTER TABLE gtest28a DROP COLUMN a; CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); \d gtest28* + + +-- sanity check of system catalog +SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's', 'v'); diff --git a/src/test/regress/sql/generated_virtual.sql b/src/test/regress/sql/generated_virtual.sql new file mode 100644 index 0000000000000..b4eedeee2fb27 --- /dev/null +++ b/src/test/regress/sql/generated_virtual.sql @@ -0,0 +1,835 @@ +-- keep these tests aligned with generated_stored.sql + + +CREATE SCHEMA generated_virtual_tests; +GRANT USAGE ON SCHEMA generated_virtual_tests TO PUBLIC; +SET search_path = generated_virtual_tests; + +CREATE TABLE gtest0 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (55) VIRTUAL); +CREATE TABLE gtest1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); + +SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_schema = 'generated_virtual_tests' ORDER BY 1, 2; + +SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage WHERE table_schema = 'generated_virtual_tests' ORDER BY 1, 2, 3; + +\d gtest1 + +-- duplicate generated +CREATE TABLE gtest_err_1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL GENERATED ALWAYS AS (a * 3) VIRTUAL); + +-- references to other generated columns, including self-references +CREATE TABLE gtest_err_2a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (b * 2) VIRTUAL); +CREATE TABLE gtest_err_2b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL, c int GENERATED ALWAYS AS (b * 3) VIRTUAL); +-- a whole-row var is a self-reference on steroids, so disallow that too +CREATE TABLE gtest_err_2c (a int PRIMARY KEY, + b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) VIRTUAL); + +-- invalid reference +CREATE TABLE gtest_err_3 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (c * 2) VIRTUAL); + +-- generation expression must be immutable +CREATE TABLE gtest_err_4 (a int PRIMARY KEY, b double precision GENERATED ALWAYS AS (random()) VIRTUAL); +-- ... but be sure that the immutability test is accurate +CREATE TABLE gtest2 (a int, b text GENERATED ALWAYS AS (a || ' sec') VIRTUAL); +DROP TABLE gtest2; + +-- cannot have default/identity and generated +CREATE TABLE gtest_err_5a (a int PRIMARY KEY, b int DEFAULT 5 GENERATED ALWAYS AS (a * 2) VIRTUAL); +CREATE TABLE gtest_err_5b (a int PRIMARY KEY, b int GENERATED ALWAYS AS identity GENERATED ALWAYS AS (a * 2) VIRTUAL); + +-- reference to system column not allowed in generated column +-- (except tableoid, which we test below) +CREATE TABLE gtest_err_6a (a int PRIMARY KEY, b bool GENERATED ALWAYS AS (xmin <> 37) VIRTUAL); + +-- various prohibited constructs +CREATE TABLE gtest_err_7a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (avg(a)) VIRTUAL); +CREATE TABLE gtest_err_7b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (row_number() OVER (ORDER BY a)) VIRTUAL); +CREATE TABLE gtest_err_7c (a int PRIMARY KEY, b int GENERATED ALWAYS AS ((SELECT a)) VIRTUAL); +CREATE TABLE gtest_err_7d (a int PRIMARY KEY, b int GENERATED ALWAYS AS (generate_series(1, a)) VIRTUAL); + +-- GENERATED BY DEFAULT not allowed +CREATE TABLE gtest_err_8 (a int PRIMARY KEY, b int GENERATED BY DEFAULT AS (a * 2) VIRTUAL); + +INSERT INTO gtest1 VALUES (1); +INSERT INTO gtest1 VALUES (2, DEFAULT); -- ok +INSERT INTO gtest1 VALUES (3, 33); -- error +INSERT INTO gtest1 VALUES (3, 33), (4, 44); -- error +INSERT INTO gtest1 VALUES (3, DEFAULT), (4, 44); -- error +INSERT INTO gtest1 VALUES (3, 33), (4, DEFAULT); -- error +INSERT INTO gtest1 VALUES (3, DEFAULT), (4, DEFAULT); -- ok + +SELECT * FROM gtest1 ORDER BY a; +SELECT gtest1 FROM gtest1 ORDER BY a; -- whole-row reference +SELECT a, (SELECT gtest1.b) FROM gtest1 ORDER BY a; -- sublink +DELETE FROM gtest1 WHERE a >= 3; + +UPDATE gtest1 SET b = DEFAULT WHERE a = 1; +UPDATE gtest1 SET b = 11 WHERE a = 1; -- error + +SELECT * FROM gtest1 ORDER BY a; + +SELECT a, b, b * 2 AS b2 FROM gtest1 ORDER BY a; +SELECT a, b FROM gtest1 WHERE b = 4 ORDER BY a; + +-- test that overflow error happens on read +INSERT INTO gtest1 VALUES (2000000000); +SELECT * FROM gtest1; +DELETE FROM gtest1 WHERE a = 2000000000; + +-- test with joins +CREATE TABLE gtestx (x int, y int); +INSERT INTO gtestx VALUES (11, 1), (22, 2), (33, 3); +SELECT * FROM gtestx, gtest1 WHERE gtestx.y = gtest1.a; +DROP TABLE gtestx; + +-- test UPDATE/DELETE quals +SELECT * FROM gtest1 ORDER BY a; +UPDATE gtest1 SET a = 3 WHERE b = 4 RETURNING old.*, new.*; +SELECT * FROM gtest1 ORDER BY a; +DELETE FROM gtest1 WHERE b = 2; +SELECT * FROM gtest1 ORDER BY a; + +-- test MERGE +CREATE TABLE gtestm ( + id int PRIMARY KEY, + f1 int, + f2 int, + f3 int GENERATED ALWAYS AS (f1 * 2) VIRTUAL, + f4 int GENERATED ALWAYS AS (f2 * 2) VIRTUAL +); +INSERT INTO gtestm VALUES (1, 5, 100); +MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id + WHEN MATCHED THEN UPDATE SET f1 = v.f1 + WHEN NOT MATCHED THEN INSERT VALUES (v.id, v.f1, 200) + RETURNING merge_action(), old.*, new.*; +SELECT * FROM gtestm ORDER BY id; +DROP TABLE gtestm; + +CREATE TABLE gtestm ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +INSERT INTO gtestm (a) SELECT g FROM generate_series(1, 10) g; +MERGE INTO gtestm t USING gtestm AS s ON 2 * t.a = s.b WHEN MATCHED THEN DELETE RETURNING *; +DROP TABLE gtestm; + +-- views +CREATE VIEW gtest1v AS SELECT * FROM gtest1; +SELECT * FROM gtest1v; +INSERT INTO gtest1v VALUES (4, 8); -- error +INSERT INTO gtest1v VALUES (5, DEFAULT); -- ok +INSERT INTO gtest1v VALUES (6, 66), (7, 77); -- error +INSERT INTO gtest1v VALUES (6, DEFAULT), (7, 77); -- error +INSERT INTO gtest1v VALUES (6, 66), (7, DEFAULT); -- error +INSERT INTO gtest1v VALUES (6, DEFAULT), (7, DEFAULT); -- ok + +ALTER VIEW gtest1v ALTER COLUMN b SET DEFAULT 100; +INSERT INTO gtest1v VALUES (8, DEFAULT); -- error +INSERT INTO gtest1v VALUES (8, DEFAULT), (9, DEFAULT); -- error + +SELECT * FROM gtest1v; +DELETE FROM gtest1v WHERE a >= 5; +DROP VIEW gtest1v; + +-- CTEs +WITH foo AS (SELECT * FROM gtest1) SELECT * FROM foo; + +-- inheritance +CREATE TABLE gtest1_1 () INHERITS (gtest1); +SELECT * FROM gtest1_1; +\d gtest1_1 +INSERT INTO gtest1_1 VALUES (4); +SELECT * FROM gtest1_1; +SELECT * FROM gtest1; + +-- can't have generated column that is a child of normal column +CREATE TABLE gtest_normal (a int, b int); +CREATE TABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL) INHERITS (gtest_normal); -- error +CREATE TABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest_normal_child INHERIT gtest_normal; -- error +DROP TABLE gtest_normal, gtest_normal_child; + +-- test inheritance mismatches between parent and child +CREATE TABLE gtestx (x int, b int DEFAULT 10) INHERITS (gtest1); -- error +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS IDENTITY) INHERITS (gtest1); -- error +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) STORED) INHERITS (gtest1); -- error +CREATE TABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) VIRTUAL) INHERITS (gtest1); -- ok, overrides parent +\d+ gtestx +INSERT INTO gtestx (a, x) VALUES (11, 22); +SELECT * FROM gtest1; +SELECT * FROM gtestx; + +CREATE TABLE gtestxx_1 (a int NOT NULL, b int); +ALTER TABLE gtestxx_1 INHERIT gtest1; -- error +CREATE TABLE gtestxx_3 (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtestxx_3 INHERIT gtest1; -- ok +CREATE TABLE gtestxx_4 (b int GENERATED ALWAYS AS (a * 2) VIRTUAL, a int NOT NULL); +ALTER TABLE gtestxx_4 INHERIT gtest1; -- ok + +-- test multiple inheritance mismatches +CREATE TABLE gtesty (x int, b int DEFAULT 55); +CREATE TABLE gtest1_y () INHERITS (gtest0, gtesty); -- error +DROP TABLE gtesty; + +CREATE TABLE gtesty (x int, b int); +CREATE TABLE gtest1_y () INHERITS (gtest1, gtesty); -- error +DROP TABLE gtesty; + +CREATE TABLE gtesty (x int, b int GENERATED ALWAYS AS (x * 22) VIRTUAL); +CREATE TABLE gtest1_y () INHERITS (gtest1, gtesty); -- error +CREATE TABLE gtest1_y (b int GENERATED ALWAYS AS (x + 1) VIRTUAL) INHERITS (gtest1, gtesty); -- ok +\d gtest1_y + +-- test correct handling of GENERATED column that's only in child +CREATE TABLE gtestp (f1 int); +CREATE TABLE gtestc (f2 int GENERATED ALWAYS AS (f1+1) VIRTUAL) INHERITS(gtestp); +INSERT INTO gtestc values(42); +TABLE gtestc; +UPDATE gtestp SET f1 = f1 * 10; +TABLE gtestc; +DROP TABLE gtestp CASCADE; + +-- test update +CREATE TABLE gtest3 (a int, b int GENERATED ALWAYS AS (a * 3) VIRTUAL); +INSERT INTO gtest3 (a) VALUES (1), (2), (3), (NULL); +SELECT * FROM gtest3 ORDER BY a; +UPDATE gtest3 SET a = 22 WHERE a = 2; +SELECT * FROM gtest3 ORDER BY a; + +CREATE TABLE gtest3a (a text, b text GENERATED ALWAYS AS (a || '+' || a) VIRTUAL); +INSERT INTO gtest3a (a) VALUES ('a'), ('b'), ('c'), (NULL); +SELECT * FROM gtest3a ORDER BY a; +UPDATE gtest3a SET a = 'bb' WHERE a = 'b'; +SELECT * FROM gtest3a ORDER BY a; + +-- COPY +TRUNCATE gtest1; +INSERT INTO gtest1 (a) VALUES (1), (2); + +COPY gtest1 TO stdout; + +COPY gtest1 (a, b) TO stdout; + +COPY gtest1 FROM stdin; +3 +4 +\. + +COPY gtest1 (a, b) FROM stdin; + +SELECT * FROM gtest1 ORDER BY a; + +TRUNCATE gtest3; +INSERT INTO gtest3 (a) VALUES (1), (2); + +COPY gtest3 TO stdout; + +COPY gtest3 (a, b) TO stdout; + +COPY gtest3 FROM stdin; +3 +4 +\. + +COPY gtest3 (a, b) FROM stdin; + +SELECT * FROM gtest3 ORDER BY a; + +-- null values +CREATE TABLE gtest2 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (NULL) VIRTUAL); +INSERT INTO gtest2 VALUES (1); +SELECT * FROM gtest2; + +-- simple column reference for varlena types +CREATE TABLE gtest_varlena (a varchar, b varchar GENERATED ALWAYS AS (a) VIRTUAL); +INSERT INTO gtest_varlena (a) VALUES('01234567890123456789'); +INSERT INTO gtest_varlena (a) VALUES(NULL); +SELECT * FROM gtest_varlena ORDER BY a; +DROP TABLE gtest_varlena; + +-- composite types +CREATE TYPE double_int as (a int, b int); +CREATE TABLE gtest4 ( + a int, + b double_int GENERATED ALWAYS AS ((a * 2, a * 3)) VIRTUAL +); +INSERT INTO gtest4 VALUES (1), (6); +SELECT * FROM gtest4; + +DROP TABLE gtest4; +DROP TYPE double_int; + +-- using tableoid is allowed +CREATE TABLE gtest_tableoid ( + a int PRIMARY KEY, + b bool GENERATED ALWAYS AS (tableoid = 'gtest_tableoid'::regclass) VIRTUAL +); +INSERT INTO gtest_tableoid VALUES (1), (2); +ALTER TABLE gtest_tableoid ADD COLUMN + c regclass GENERATED ALWAYS AS (tableoid) VIRTUAL; +SELECT * FROM gtest_tableoid; + +-- drop column behavior +CREATE TABLE gtest10 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) VIRTUAL); +ALTER TABLE gtest10 DROP COLUMN b; -- fails +ALTER TABLE gtest10 DROP COLUMN b CASCADE; -- drops c too + +\d gtest10 + +CREATE TABLE gtest10a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest10a DROP COLUMN b; +INSERT INTO gtest10a (a) VALUES (1); + +-- privileges +CREATE USER regress_user11; + +CREATE TABLE gtest11 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (b * 2) VIRTUAL); +INSERT INTO gtest11 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c) ON gtest11 TO regress_user11; + +CREATE FUNCTION gf1(a int) RETURNS int AS $$ SELECT a * 3 $$ IMMUTABLE LANGUAGE SQL; +REVOKE ALL ON FUNCTION gf1(int) FROM PUBLIC; + +CREATE TABLE gtest12 (a int PRIMARY KEY, b int, c int GENERATED ALWAYS AS (gf1(b)) VIRTUAL); +INSERT INTO gtest12 VALUES (1, 10), (2, 20); +GRANT SELECT (a, c), INSERT ON gtest12 TO regress_user11; + +SET ROLE regress_user11; +SELECT a, b FROM gtest11; -- not allowed +SELECT a, c FROM gtest11; -- allowed +SELECT gf1(10); -- not allowed +INSERT INTO gtest12 VALUES (3, 30), (4, 40); -- allowed (does not actually invoke the function) +SELECT a, c FROM gtest12; -- currently not allowed because of function permissions, should arguably be allowed +RESET ROLE; + +DROP FUNCTION gf1(int); -- fail +DROP TABLE gtest11, gtest12; +DROP FUNCTION gf1(int); +DROP USER regress_user11; + +-- check constraints +CREATE TABLE gtest20 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL CHECK (b < 50)); +INSERT INTO gtest20 (a) VALUES (10); -- ok +INSERT INTO gtest20 (a) VALUES (30); -- violates constraint + +ALTER TABLE gtest20 ALTER COLUMN b SET EXPRESSION AS (a * 100); -- violates constraint (currently not supported) +ALTER TABLE gtest20 ALTER COLUMN b SET EXPRESSION AS (a * 3); -- ok (currently not supported) + +CREATE TABLE gtest20a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +INSERT INTO gtest20a (a) VALUES (10); +INSERT INTO gtest20a (a) VALUES (30); +ALTER TABLE gtest20a ADD CHECK (b < 50); -- fails on existing row +-- table rewrite cases +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 50); -- fails on existing row +ALTER TABLE gtest20a ADD COLUMN c float8 DEFAULT random() CHECK (b < 61); -- ok + +CREATE TABLE gtest20b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +INSERT INTO gtest20b (a) VALUES (10); +INSERT INTO gtest20b (a) VALUES (30); +ALTER TABLE gtest20b ADD CONSTRAINT chk CHECK (b < 50) NOT VALID; +ALTER TABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row + +-- check with whole-row reference +CREATE TABLE gtest20c (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +ALTER TABLE gtest20c ADD CONSTRAINT whole_row_check CHECK (gtest20c IS NOT NULL); +INSERT INTO gtest20c VALUES (1); -- ok +INSERT INTO gtest20c VALUES (NULL); -- fails + +-- not-null constraints +CREATE TABLE gtest21a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL NOT NULL); +INSERT INTO gtest21a (a) VALUES (1); -- ok +INSERT INTO gtest21a (a) VALUES (0); -- violates constraint + +-- also check with table constraint syntax +CREATE TABLE gtest21ax (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL, CONSTRAINT cc NOT NULL b); +INSERT INTO gtest21ax (a) VALUES (0); -- violates constraint +INSERT INTO gtest21ax (a) VALUES (1); --ok +-- SET EXPRESSION supports not null constraint +ALTER TABLE gtest21ax ALTER COLUMN b SET EXPRESSION AS (nullif(a, 1)); --error +DROP TABLE gtest21ax; + +CREATE TABLE gtest21ax (a int PRIMARY KEY, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL); +ALTER TABLE gtest21ax ADD CONSTRAINT cc NOT NULL b; +INSERT INTO gtest21ax (a) VALUES (0); -- violates constraint +DROP TABLE gtest21ax; + +CREATE TABLE gtest21b (a int, b int GENERATED ALWAYS AS (nullif(a, 0)) VIRTUAL); +ALTER TABLE gtest21b ALTER COLUMN b SET NOT NULL; +INSERT INTO gtest21b (a) VALUES (1); -- ok +INSERT INTO gtest21b (a) VALUES (2), (0); -- violates constraint +INSERT INTO gtest21b (a) VALUES (NULL); -- error +ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL; +INSERT INTO gtest21b (a) VALUES (0); -- ok now + +-- not-null constraint with partitioned table +CREATE TABLE gtestnn_parent ( + f1 int, + f2 bigint, + f3 bigint GENERATED ALWAYS AS (nullif(f1, 1) + nullif(f2, 10)) VIRTUAL NOT NULL +) PARTITION BY RANGE (f1); +CREATE TABLE gtestnn_child PARTITION OF gtestnn_parent FOR VALUES FROM (1) TO (5); +CREATE TABLE gtestnn_childdef PARTITION OF gtestnn_parent default; +-- check the error messages +INSERT INTO gtestnn_parent VALUES (2, 2, default), (3, 5, default), (14, 12, default); -- ok +INSERT INTO gtestnn_parent VALUES (1, 2, default); -- error +INSERT INTO gtestnn_parent VALUES (2, 10, default); -- error +ALTER TABLE gtestnn_parent ALTER COLUMN f3 SET EXPRESSION AS (nullif(f1, 2) + nullif(f2, 11)); -- error +INSERT INTO gtestnn_parent VALUES (10, 11, default); -- ok +SELECT * FROM gtestnn_parent ORDER BY f1, f2, f3; +-- test ALTER TABLE ADD COLUMN +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 14) + nullif(f2, 10)) VIRTUAL; -- error +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 13) + nullif(f2, 5)) VIRTUAL; -- error +ALTER TABLE gtestnn_parent ADD COLUMN c int NOT NULL GENERATED ALWAYS AS (nullif(f1, 4) + nullif(f2, 6)) VIRTUAL; -- ok + +-- index constraints +CREATE TABLE gtest22a (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a / 2) VIRTUAL UNIQUE); +--INSERT INTO gtest22a VALUES (2); +--INSERT INTO gtest22a VALUES (3); +--INSERT INTO gtest22a VALUES (4); +CREATE TABLE gtest22b (a int, b int GENERATED ALWAYS AS (a / 2) VIRTUAL, PRIMARY KEY (a, b)); +--INSERT INTO gtest22b VALUES (2); +--INSERT INTO gtest22b VALUES (2); + +-- indexes +CREATE TABLE gtest22c (a int, b int GENERATED ALWAYS AS (a * 2) VIRTUAL); +--CREATE INDEX gtest22c_b_idx ON gtest22c (b); +--CREATE INDEX gtest22c_expr_idx ON gtest22c ((b * 3)); +--CREATE INDEX gtest22c_pred_idx ON gtest22c (a) WHERE b > 0; +--\d gtest22c + +--INSERT INTO gtest22c VALUES (1), (2), (3); +--SET enable_seqscan TO off; +--SET enable_bitmapscan TO off; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 4; +--SELECT * FROM gtest22c WHERE b = 4; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 6; +--SELECT * FROM gtest22c WHERE b * 3 = 6; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--SELECT * FROM gtest22c WHERE a = 1 AND b > 0; + +--ALTER TABLE gtest22c ALTER COLUMN b SET EXPRESSION AS (a * 4); +--ANALYZE gtest22c; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 8; +--SELECT * FROM gtest22c WHERE b = 8; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 12; +--SELECT * FROM gtest22c WHERE b * 3 = 12; +--EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--SELECT * FROM gtest22c WHERE a = 1 AND b > 0; +--RESET enable_seqscan; +--RESET enable_bitmapscan; + +-- foreign keys +CREATE TABLE gtest23a (x int PRIMARY KEY, y int); +--INSERT INTO gtest23a VALUES (1, 11), (2, 22), (3, 33); + +CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x) ON UPDATE CASCADE); -- error +CREATE TABLE gtest23x (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x) ON DELETE SET NULL); -- error + +CREATE TABLE gtest23b (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) VIRTUAL REFERENCES gtest23a (x)); +--\d gtest23b + +--INSERT INTO gtest23b VALUES (1); -- ok +--INSERT INTO gtest23b VALUES (5); -- error +--ALTER TABLE gtest23b ALTER COLUMN b SET EXPRESSION AS (a * 5); -- error +--ALTER TABLE gtest23b ALTER COLUMN b SET EXPRESSION AS (a * 1); -- ok + +--DROP TABLE gtest23b; +--DROP TABLE gtest23a; + +CREATE TABLE gtest23p (x int, y int GENERATED ALWAYS AS (x * 2) VIRTUAL, PRIMARY KEY (y)); +--INSERT INTO gtest23p VALUES (1), (2), (3); + +CREATE TABLE gtest23q (a int PRIMARY KEY, b int REFERENCES gtest23p (y)); +--INSERT INTO gtest23q VALUES (1, 2); -- ok +--INSERT INTO gtest23q VALUES (2, 5); -- error + +-- domains +CREATE DOMAIN gtestdomain1 AS int CHECK (VALUE < 10); +CREATE TABLE gtest24 (a int PRIMARY KEY, b gtestdomain1 GENERATED ALWAYS AS (a * 2) VIRTUAL); +--INSERT INTO gtest24 (a) VALUES (4); -- ok +--INSERT INTO gtest24 (a) VALUES (6); -- error +CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); +CREATE TABLE gtest24r (a int PRIMARY KEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) VIRTUAL); +--INSERT INTO gtest24r (a) VALUES (4); -- ok +--INSERT INTO gtest24r (a) VALUES (6); -- error + +CREATE DOMAIN gtestdomainnn AS int CHECK (VALUE IS NOT NULL); +CREATE TABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) VIRTUAL); +--INSERT INTO gtest24nn (a) VALUES (4); -- ok +--INSERT INTO gtest24nn (a) VALUES (NULL); -- error + +-- typed tables (currently not supported) +CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); +CREATE TABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) VIRTUAL); +DROP TYPE gtest_type CASCADE; + +-- partitioning cases +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint) PARTITION BY RANGE (f1); +CREATE TABLE gtest_child PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 2) VIRTUAL +) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +CREATE TABLE gtest_child (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- error +DROP TABLE gtest_parent, gtest_child; + +CREATE TABLE gtest_parent (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f1); +CREATE TABLE gtest_child PARTITION OF gtest_parent + FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); -- inherits gen expr +CREATE TABLE gtest_child2 PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 22) VIRTUAL -- overrides gen expr +) FOR VALUES FROM ('2016-08-01') TO ('2016-09-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 DEFAULT 42 -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +CREATE TABLE gtest_child3 PARTITION OF gtest_parent ( + f3 GENERATED ALWAYS AS (f2 * 2) STORED -- error +) FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint DEFAULT 42); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); -- error +DROP TABLE gtest_child3; +CREATE TABLE gtest_child3 (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) VIRTUAL); +ALTER TABLE gtest_parent ATTACH PARTITION gtest_child3 FOR VALUES FROM ('2016-09-01') TO ('2016-10-01'); +\d gtest_child +\d gtest_child2 +\d gtest_child3 +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 1); +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-07-15', 2); +INSERT INTO gtest_parent (f1, f2) VALUES ('2016-08-15', 3); +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; +SELECT tableoid::regclass, * FROM gtest_child ORDER BY 1, 2, 3; +SELECT tableoid::regclass, * FROM gtest_child2 ORDER BY 1, 2, 3; -- uses child's generation expression, not parent's +SELECT tableoid::regclass, * FROM gtest_child3 ORDER BY 1, 2, 3; +UPDATE gtest_parent SET f1 = f1 + 60 WHERE f2 = 1; +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + +-- alter only parent's and one child's generation expression +ALTER TABLE ONLY gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 4); +ALTER TABLE gtest_child ALTER COLUMN f3 SET EXPRESSION AS (f2 * 10); +\d gtest_parent +\d gtest_child +\d gtest_child2 +\d gtest_child3 +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; + +-- alter generation expression of parent and all its children altogether +ALTER TABLE gtest_parent ALTER COLUMN f3 SET EXPRESSION AS (f2 * 2); +\d gtest_parent +\d gtest_child +\d gtest_child2 +\d gtest_child3 +SELECT tableoid::regclass, * FROM gtest_parent ORDER BY 1, 2, 3; +-- we leave these tables around for purposes of testing dump/reload/upgrade + +-- generated columns in partition key (not allowed) +CREATE TABLE gtest_part_key (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE (f3); +CREATE TABLE gtest_part_key (f1 date NOT NULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) VIRTUAL) PARTITION BY RANGE ((f3 * 3)); + +-- ALTER TABLE ... ADD COLUMN +CREATE TABLE gtest25 (a int PRIMARY KEY); +INSERT INTO gtest25 VALUES (3), (4); +ALTER TABLE gtest25 ADD COLUMN b int GENERATED ALWAYS AS (a * 2) VIRTUAL, ALTER COLUMN b SET EXPRESSION AS (a * 3); +SELECT * FROM gtest25 ORDER BY a; +ALTER TABLE gtest25 ADD COLUMN x int GENERATED ALWAYS AS (b * 4) VIRTUAL; -- error +ALTER TABLE gtest25 ADD COLUMN x int GENERATED ALWAYS AS (z * 4) VIRTUAL; -- error +ALTER TABLE gtest25 ADD COLUMN c int DEFAULT 42, + ADD COLUMN x int GENERATED ALWAYS AS (c * 4) VIRTUAL; +ALTER TABLE gtest25 ADD COLUMN d int DEFAULT 101; +ALTER TABLE gtest25 ALTER COLUMN d SET DATA TYPE float8, + ADD COLUMN y float8 GENERATED ALWAYS AS (d * 4) VIRTUAL; +SELECT * FROM gtest25 ORDER BY a; +\d gtest25 + +-- ALTER TABLE ... ALTER COLUMN +CREATE TABLE gtest27 ( + a int, + b int, + x int GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL +); +INSERT INTO gtest27 (a, b) VALUES (3, 7), (4, 11); +ALTER TABLE gtest27 ALTER COLUMN a TYPE text; -- error +ALTER TABLE gtest27 ALTER COLUMN x TYPE numeric; +\d gtest27 +SELECT * FROM gtest27; +ALTER TABLE gtest27 ALTER COLUMN x TYPE boolean USING x <> 0; -- error +ALTER TABLE gtest27 ALTER COLUMN x DROP DEFAULT; -- error +-- test not-null checking during table rewrite +INSERT INTO gtest27 (a, b) VALUES (NULL, NULL); +ALTER TABLE gtest27 + DROP COLUMN x, + ALTER COLUMN a TYPE bigint, + ALTER COLUMN b TYPE bigint, + ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL NOT NULL; -- error +DELETE FROM gtest27 WHERE a IS NULL AND b IS NULL; +-- It's possible to alter the column types this way: +ALTER TABLE gtest27 + DROP COLUMN x, + ALTER COLUMN a TYPE bigint, + ALTER COLUMN b TYPE bigint, + ADD COLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) VIRTUAL; +\d gtest27 +-- Ideally you could just do this, but not today (and should x change type?): +ALTER TABLE gtest27 + ALTER COLUMN a TYPE float8, + ALTER COLUMN b TYPE float8; -- error +\d gtest27 +SELECT * FROM gtest27; + +-- ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION +CREATE TABLE gtest29 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +INSERT INTO gtest29 (a) VALUES (3), (4); +SELECT * FROM gtest29; +\d gtest29 +ALTER TABLE gtest29 ALTER COLUMN a SET EXPRESSION AS (a * 3); -- error +ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION; -- error +ALTER TABLE gtest29 ALTER COLUMN a DROP EXPRESSION IF EXISTS; -- notice + +-- Change the expression +ALTER TABLE gtest29 ALTER COLUMN b SET EXPRESSION AS (a * 3); +SELECT * FROM gtest29; +\d gtest29 + +ALTER TABLE gtest29 ALTER COLUMN b DROP EXPRESSION; -- not supported +INSERT INTO gtest29 (a) VALUES (5); +INSERT INTO gtest29 (a, b) VALUES (6, 66); +SELECT * FROM gtest29; +\d gtest29 + +-- check that dependencies between columns have also been removed +--ALTER TABLE gtest29 DROP COLUMN a; -- should not drop b +--\d gtest29 + +-- with inheritance +CREATE TABLE gtest30 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +CREATE TABLE gtest30_1 () INHERITS (gtest30); +ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION; +\d gtest30 +\d gtest30_1 +DROP TABLE gtest30 CASCADE; +CREATE TABLE gtest30 ( + a int, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); +CREATE TABLE gtest30_1 () INHERITS (gtest30); +ALTER TABLE ONLY gtest30 ALTER COLUMN b DROP EXPRESSION; -- error +\d gtest30 +\d gtest30_1 +ALTER TABLE gtest30_1 ALTER COLUMN b DROP EXPRESSION; -- error + +-- composite type dependencies +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') VIRTUAL, c text); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +DROP TABLE gtest31_1, gtest31_2; + +-- Check it for a partitioned table, too +CREATE TABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') VIRTUAL, c text) PARTITION BY LIST (a); +CREATE TABLE gtest31_2 (x int, y gtest31_1); +ALTER TABLE gtest31_1 ALTER COLUMN b TYPE varchar; -- fails +DROP TABLE gtest31_1, gtest31_2; + +-- triggers +CREATE TABLE gtest26 ( + a int PRIMARY KEY, + b int GENERATED ALWAYS AS (a * 2) VIRTUAL +); + +CREATE FUNCTION gtest_trigger_func() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + IF tg_op IN ('DELETE', 'UPDATE') THEN + RAISE INFO '%: %: old = %', TG_NAME, TG_WHEN, OLD; + END IF; + IF tg_op IN ('INSERT', 'UPDATE') THEN + RAISE INFO '%: %: new = %', TG_NAME, TG_WHEN, NEW; + END IF; + IF tg_op = 'DELETE' THEN + RETURN OLD; + ELSE + RETURN NEW; + END IF; +END +$$; + +CREATE TRIGGER gtest1 BEFORE DELETE OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (OLD.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest2a BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.b < 0) -- error + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest2b BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.* IS NOT NULL) -- error + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest2 BEFORE INSERT ON gtest26 + FOR EACH ROW + WHEN (NEW.a < 0) + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest3 AFTER DELETE OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (OLD.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest4 AFTER INSERT OR UPDATE ON gtest26 + FOR EACH ROW + WHEN (NEW.b < 0) -- ok + EXECUTE PROCEDURE gtest_trigger_func(); + +INSERT INTO gtest26 (a) VALUES (-2), (0), (3); +SELECT * FROM gtest26 ORDER BY a; +UPDATE gtest26 SET a = a * -2; +SELECT * FROM gtest26 ORDER BY a; +DELETE FROM gtest26 WHERE a = -6; +SELECT * FROM gtest26 ORDER BY a; + +DROP TRIGGER gtest1 ON gtest26; +DROP TRIGGER gtest2 ON gtest26; +DROP TRIGGER gtest3 ON gtest26; + +-- Check that an UPDATE of "a" fires the trigger for UPDATE OF b, per +-- SQL standard. +CREATE FUNCTION gtest_trigger_func3() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + RAISE NOTICE 'OK'; + RETURN NEW; +END +$$; + +CREATE TRIGGER gtest11 BEFORE UPDATE OF b ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func3(); + +UPDATE gtest26 SET a = 1 WHERE a = 0; + +DROP TRIGGER gtest11 ON gtest26; +TRUNCATE gtest26; + +-- check that modifications of generated columns in triggers do +-- not get propagated +CREATE FUNCTION gtest_trigger_func4() RETURNS trigger + LANGUAGE plpgsql +AS $$ +BEGIN + NEW.a = 10; + NEW.b = 300; + RETURN NEW; +END; +$$; + +CREATE TRIGGER gtest12_01 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func(); + +CREATE TRIGGER gtest12_02 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func4(); + +CREATE TRIGGER gtest12_03 BEFORE INSERT OR UPDATE ON gtest26 + FOR EACH ROW + EXECUTE PROCEDURE gtest_trigger_func(); + +INSERT INTO gtest26 (a) VALUES (1); +SELECT * FROM gtest26 ORDER BY a; +UPDATE gtest26 SET a = 11 WHERE a = 10; +SELECT * FROM gtest26 ORDER BY a; + +-- LIKE INCLUDING GENERATED and dropped column handling +CREATE TABLE gtest28a ( + a int, + b int, + c int, + x int GENERATED ALWAYS AS (b * 2) VIRTUAL +); + +ALTER TABLE gtest28a DROP COLUMN a; + +CREATE TABLE gtest28b (LIKE gtest28a INCLUDING GENERATED); + +\d gtest28* + + +-- sanity check of system catalog +SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOT IN ('', 's', 'v'); + + +-- +-- test the expansion of virtual generated columns +-- +-- these tests are specific to generated_virtual.sql +-- + +create table gtest32 ( + a int primary key, + b int generated always as (a * 2), + c int generated always as (10 + 10), + d int generated always as (coalesce(a, 100)) +); + +insert into gtest32 values (1), (2); +analyze gtest32; + +-- Ensure that nullingrel bits are propagated into the generation expressions +explain (costs off) +select sum(t2.b) over (partition by t2.a), + sum(t2.c) over (partition by t2.a), + sum(t2.d) over (partition by t2.a) +from gtest32 as t1 left join gtest32 as t2 on (t1.a = t2.a) +order by t1.a; + +select sum(t2.b) over (partition by t2.a), + sum(t2.c) over (partition by t2.a), + sum(t2.d) over (partition by t2.a) +from gtest32 as t1 left join gtest32 as t2 on (t1.a = t2.a) +order by t1.a; + +-- Ensure that outer-join removal functions correctly after the propagation of nullingrel bits +explain (costs off) +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2; + +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2; + +explain (costs off) +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2 or t1.a is null; + +select t1.a from gtest32 t1 left join gtest32 t2 on t1.a = t2.a +where coalesce(t2.b, 1) = 2 or t1.a is null; + +-- Ensure that the generation expressions are wrapped into PHVs if needed +explain (verbose, costs off) +select t2.* from gtest32 t1 left join gtest32 t2 on false; +select t2.* from gtest32 t1 left join gtest32 t2 on false; + +explain (verbose, costs off) +select * from gtest32 t group by grouping sets (a, b, c, d) having c = 20; +select * from gtest32 t group by grouping sets (a, b, c, d) having c = 20; + +drop table gtest32; diff --git a/src/test/regress/sql/groupingsets.sql b/src/test/regress/sql/groupingsets.sql index 90ba27257a9ee..38d3cdd0fd89a 100644 --- a/src/test/regress/sql/groupingsets.sql +++ b/src/test/regress/sql/groupingsets.sql @@ -172,6 +172,17 @@ select x, not x as not_x, q2 from group by grouping sets(x, q2) order by x, q2; +select x, y + from (select four as x, four as y from tenk1) as t + group by grouping sets (x, y) + having y is null + order by 1, 2; + +select x, y || 'y' + from (select four as x, four as y from tenk1) as t + group by grouping sets (x, y) + order by 1, 2; + -- check qual push-down rules for a subquery with grouping sets explain (verbose, costs off) select * from ( @@ -279,6 +290,11 @@ explain (costs off) select v.c, (select count(*) from gstest2 group by () having v.c) from (values (false),(true)) v(c) order by v.c; +-- test pushdown of HAVING clause that does not reference any columns that are nullable by grouping sets +explain (costs off) +select a, b, count(*) from gstest2 group by grouping sets ((a, b), (a)) having a > 1 and b > 1; +select a, b, count(*) from gstest2 group by grouping sets ((a, b), (a)) having a > 1 and b > 1; + -- HAVING with GROUPING queries select ten, grouping(ten) from onek group by grouping sets(ten) having grouping(ten) >= 0 @@ -589,4 +605,102 @@ explain (costs off) select (select grouping(v1)) from (values ((select 1))) v(v1) group by v1; select (select grouping(v1)) from (values ((select 1))) v(v1) group by v1; +-- test handling of subqueries in grouping sets +create temp table gstest5(id integer primary key, v integer); +insert into gstest5 select i, i from generate_series(1,5)i; + +explain (verbose, costs off) +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s +from gstest5 t1 +group by grouping sets(v, s) +order by case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end + nulls first; + +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s +from gstest5 t1 +group by grouping sets(v, s) +order by case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end + nulls first; + +explain (verbose, costs off) +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s, + case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end as o +from gstest5 t1 +group by grouping sets(v, s) +order by o nulls first; + +select grouping((select t1.v from gstest5 t2 where id = t1.id)), + (select t1.v from gstest5 t2 where id = t1.id) as s, + case when grouping((select t1.v from gstest5 t2 where id = t1.id)) = 0 + then (select t1.v from gstest5 t2 where id = t1.id) + else null end as o +from gstest5 t1 +group by grouping sets(v, s) +order by o nulls first; + +-- test handling of expressions that should match lower target items +explain (costs off) +select a < b and b < 3 from (values (1, 2)) t(a, b) group by rollup(a < b and b < 3) having a < b and b < 3; +select a < b and b < 3 from (values (1, 2)) t(a, b) group by rollup(a < b and b < 3) having a < b and b < 3; + +explain (costs off) +select not a from (values(true)) t(a) group by rollup(not a) having not not a; +select not a from (values(true)) t(a) group by rollup(not a) having not not a; + +-- test handling of expressions nullable by grouping sets +explain (costs off) +select distinct on (a, b) a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b; + +select distinct on (a, b) a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b; + +explain (costs off) +select distinct on (a, b+1) a, b+1 +from (values (1, 0), (2, 1)) as t (a, b) where a = b+1 +group by grouping sets((a, b+1), (a)) +order by a, b+1; + +select distinct on (a, b+1) a, b+1 +from (values (1, 0), (2, 1)) as t (a, b) where a = b+1 +group by grouping sets((a, b+1), (a)) +order by a, b+1; + +explain (costs off) +select a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b nulls first; + +select a, b +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)) +order by a, b nulls first; + +explain (costs off) +select 1 as one group by rollup(one) order by one nulls first; +select 1 as one group by rollup(one) order by one nulls first; + +explain (costs off) +select a, b, row_number() over (order by a, b nulls first) +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)); + +select a, b, row_number() over (order by a, b nulls first) +from (values (1, 1), (2, 2)) as t (a, b) where a = b +group by grouping sets((a, b), (a)); + -- end diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql index dc79761955d0c..f65f84a26320a 100644 --- a/src/test/regress/sql/guc.sql +++ b/src/test/regress/sql/guc.sql @@ -2,6 +2,9 @@ -- we can't rely on any specific default value of vacuum_cost_delay SHOW datestyle; +-- Check output style of CamelCase enum options +SET intervalstyle to 'asd'; + -- SET to some nondefault value SET vacuum_cost_delay TO 40; SET datestyle = 'ISO, YMD'; @@ -319,6 +322,18 @@ set default_with_oids to f; -- Should not allow to set it to true. set default_with_oids to t; +-- Test that disabling track_activities disables query ID reporting in +-- pg_stat_activity. +SET compute_query_id = on; +SET track_activities = on; +SELECT query_id IS NOT NULL AS qid_set FROM pg_stat_activity + WHERE pid = pg_backend_pid(); +SET track_activities = off; +SELECT query_id IS NOT NULL AS qid_set FROM pg_stat_activity + WHERE pid = pg_backend_pid(); +RESET track_activities; +RESET compute_query_id; + -- Test GUC categories and flag patterns SELECT pg_settings_get_flags(NULL); SELECT pg_settings_get_flags('does_not_exist'); diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql index e5cf12ff63d33..8978249a5dc1e 100644 --- a/src/test/regress/sql/horology.sql +++ b/src/test/regress/sql/horology.sql @@ -1,9 +1,9 @@ -- -- HOROLOGY -- -SET DateStyle = 'Postgres, MDY'; -SHOW TimeZone; -- Many of these tests depend on the prevailing setting +SHOW TimeZone; -- Many of these tests depend on the prevailing settings +SHOW DateStyle; -- -- Test various input formats @@ -102,6 +102,10 @@ SELECT date 'J J 1520447'; SELECT timestamp with time zone 'Y2001M12D27H04M05S06.789+08'; SELECT timestamp with time zone 'Y2001M12D27H04MM05S06.789-08'; +-- More examples we used to accept and should not +SELECT timestamp with time zone 'J2452271 T X03456-08'; +SELECT timestamp with time zone 'J2452271 T X03456.001e6-08'; + -- conflicting fields should throw errors SELECT date '1995-08-06 epoch'; SELECT date '1995-08-06 infinity'; @@ -538,6 +542,7 @@ SELECT to_timestamp('2011-12-18 11:38 EST', 'YYYY-MM-DD HH12:MI TZ'); SELECT to_timestamp('2011-12-18 11:38 -05', 'YYYY-MM-DD HH12:MI TZ'); SELECT to_timestamp('2011-12-18 11:38 +01:30', 'YYYY-MM-DD HH12:MI TZ'); SELECT to_timestamp('2011-12-18 11:38 MSK', 'YYYY-MM-DD HH12:MI TZ'); -- dyntz +SELECT to_timestamp('2011-12-18 00:00 LMT', 'YYYY-MM-DD HH24:MI TZ'); -- dyntz SELECT to_timestamp('2011-12-18 11:38ESTFOO24', 'YYYY-MM-DD HH12:MITZFOOSS'); SELECT to_timestamp('2011-12-18 11:38-05FOO24', 'YYYY-MM-DD HH12:MITZFOOSS'); SELECT to_timestamp('2011-12-18 11:38 JUNK', 'YYYY-MM-DD HH12:MI TZ'); -- error @@ -558,6 +563,7 @@ SELECT i, to_timestamp('2018-11-02 12:34:56.1234', 'YYYY-MM-DD HH24:MI:SS.FF' || SELECT i, to_timestamp('2018-11-02 12:34:56.12345', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i; +SELECT i, to_timestamp('20181102123456123456', 'YYYYMMDDHH24MISSFF' || i) FROM generate_series(1, 6) i; SELECT to_date('1 4 1902', 'Q MM YYYY'); -- Q is ignored SELECT to_date('3 4 21 01', 'W MM CC YY'); @@ -650,6 +656,10 @@ SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSS'); -- ok SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSS'); SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSSS'); -- ok SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSSS'); +SELECT to_timestamp('1000000000,999', 'Y,YYY'); +SELECT to_timestamp('0.-2147483648', 'SS.MS'); +SELECT to_timestamp('613566758', 'W'); +SELECT to_timestamp('2024 613566758 1', 'YYYY WW D'); SELECT to_date('2016-13-10', 'YYYY-MM-DD'); SELECT to_date('2016-02-30', 'YYYY-MM-DD'); SELECT to_date('2016-02-29', 'YYYY-MM-DD'); -- ok @@ -660,6 +670,10 @@ SELECT to_date('2016 365', 'YYYY DDD'); -- ok SELECT to_date('2016 366', 'YYYY DDD'); -- ok SELECT to_date('2016 367', 'YYYY DDD'); SELECT to_date('0000-02-01','YYYY-MM-DD'); -- allowed, though it shouldn't be +SELECT to_date('100000000', 'CC'); +SELECT to_date('-100000000', 'CC'); +SELECT to_date('-2147483648 01', 'CC YY'); +SELECT to_date('2147483647 01', 'CC YY'); -- to_char's TZ format code produces zone abbrev if known SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ'); diff --git a/src/test/regress/sql/identity.sql b/src/test/regress/sql/identity.sql index 84c43a19a31af..45992a3d894ba 100644 --- a/src/test/regress/sql/identity.sql +++ b/src/test/regress/sql/identity.sql @@ -19,6 +19,7 @@ SELECT pg_get_serial_sequence('itest1', 'a'); CREATE TABLE itest4 (a int, b text); ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- error, requires NOT NULL ALTER TABLE itest4 ALTER COLUMN a SET NOT NULL; +ALTER TABLE itest4 ALTER COLUMN c ADD GENERATED ALWAYS AS IDENTITY; -- error, column c does not exist ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- ok ALTER TABLE itest4 ALTER COLUMN a DROP NOT NULL; -- error, disallowed ALTER TABLE itest4 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY; -- error, already set @@ -528,3 +529,12 @@ SELECT * FROM itest15; SELECT * FROM itest16; DROP TABLE itest15; DROP TABLE itest16; + +-- For testing of pg_dump and pg_upgrade, leave behind some identity +-- sequences whose logged-ness doesn't match their owning table's. +CREATE TABLE identity_dump_logged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_logged_a_seq SET UNLOGGED; +CREATE UNLOGGED TABLE identity_dump_unlogged (a INT GENERATED ALWAYS AS IDENTITY); +ALTER SEQUENCE identity_dump_unlogged_a_seq SET LOGGED; +SELECT relname, relpersistence FROM pg_class + WHERE relname ~ '^identity_dump_' ORDER BY 1; diff --git a/src/test/regress/sql/incremental_sort.sql b/src/test/regress/sql/incremental_sort.sql index ab471bdfffc12..f1f8fae56549a 100644 --- a/src/test/regress/sql/incremental_sort.sql +++ b/src/test/regress/sql/incremental_sort.sql @@ -21,7 +21,7 @@ declare line text; begin for line in - execute 'explain (analyze, costs off, summary off, timing off) ' || query + execute 'explain (analyze, costs off, summary off, timing off, buffers off) ' || query loop out_line := regexp_replace(line, '\d+kB', 'NNkB', 'g'); return next; @@ -38,7 +38,7 @@ declare element jsonb; matching_nodes jsonb := '[]'::jsonb; begin - execute 'explain (analyze, costs off, summary off, timing off, format ''json'') ' || query into strict elements; + execute 'explain (analyze, costs off, summary off, timing off, buffers off, format ''json'') ' || query into strict elements; while jsonb_array_length(elements) > 0 loop element := elements->0; elements := elements - 0; @@ -292,3 +292,9 @@ create index point_table_a_idx on point_table using gist(a); -- Ensure we get an incremental sort plan for both of the following queries explain (costs off) select a, b, a <-> point(5, 5) dist from point_table order by dist, b limit 1; explain (costs off) select a, b, a <-> point(5, 5) dist from point_table order by dist, b desc limit 1; + +-- Ensure we get an incremental sort on the outer side of the mergejoin +explain (costs off) +select * from + (select * from tenk1 order by four) t1 join tenk1 t2 on t1.four = t2.four and t1.two = t2.two +order by t1.four, t1.two limit 1; diff --git a/src/test/regress/sql/index_including.sql b/src/test/regress/sql/index_including.sql index 11c95974ec97c..43bb6ea585258 100644 --- a/src/test/regress/sql/index_including.sql +++ b/src/test/regress/sql/index_including.sql @@ -68,7 +68,7 @@ DROP TABLE tbl; CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box, CONSTRAINT covering PRIMARY KEY(c1,c2) INCLUDE(c3,c4)); SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary, indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid; -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid; +SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid AND contype = 'p'; -- ensure that constraint works INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; @@ -95,7 +95,7 @@ DROP TABLE tbl; CREATE TABLE tbl (c1 int,c2 int, c3 int, c4 box, PRIMARY KEY(c1,c2) INCLUDE(c3,c4)); SELECT indexrelid::regclass, indnatts, indnkeyatts, indisunique, indisprimary, indkey, indclass FROM pg_index WHERE indrelid = 'tbl'::regclass::oid; -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid; +SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'tbl'::regclass::oid AND contype = 'p'; -- ensure that constraint works INSERT INTO tbl SELECT 1, 2, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; INSERT INTO tbl SELECT 1, NULL, 3*x, box('4,4,4,4') FROM generate_series(1,10) AS x; diff --git a/src/test/regress/sql/indexing.sql b/src/test/regress/sql/indexing.sql index 5f1f4b80c95cf..b5cb01c2d7097 100644 --- a/src/test/regress/sql/indexing.sql +++ b/src/test/regress/sql/indexing.sql @@ -592,7 +592,7 @@ create table idxpart2 partition of idxpart for values from (0) to (1000) partiti create table idxpart21 partition of idxpart2 for values from (0) to (1000); select conname, contype, conrelid::regclass, conindid::regclass, conkey from pg_constraint where conrelid::regclass::text like 'idxpart%' - order by conname; + order by conrelid::regclass::text, conname; drop table idxpart; -- If a partitioned table has a unique/PK constraint, then it's not possible @@ -671,7 +671,6 @@ alter table only idxpart add primary key (a); -- fail, no not-null constraint alter table idxpart0 alter column a set not null; alter table only idxpart add primary key (a); -- now it works alter index idxpart_pkey attach partition idxpart0_a_key; -alter table idxpart0 alter column a drop not null; -- fail, pkey needs it drop table idxpart; -- if a partition has a unique index without a constraint, does not attach @@ -919,3 +918,19 @@ select indexrelid::regclass, indisvalid, indisreplident, where indexrelid::regclass::text like 'parted_replica%' order by indexrelid::regclass::text collate "C"; drop table parted_replica_tab; + +-- test that indexing commands work with TOASTed values in pg_index +create table test_pg_index_toast_table (a int); +create or replace function test_pg_index_toast_func (a int, b int[]) + returns bool as $$ select true $$ language sql immutable; +select array_agg(n) b from generate_series(1, 10000) n \gset +create index concurrently test_pg_index_toast_index + on test_pg_index_toast_table (test_pg_index_toast_func(a, :'b')); +reindex index concurrently test_pg_index_toast_index; +drop index concurrently test_pg_index_toast_index; +create index test_pg_index_toast_index + on test_pg_index_toast_table (test_pg_index_toast_func(a, :'b')); +reindex index test_pg_index_toast_index; +drop index test_pg_index_toast_index; +drop function test_pg_index_toast_func; +drop table test_pg_index_toast_table; diff --git a/src/test/regress/sql/inet.sql b/src/test/regress/sql/inet.sql index 3910eac3bc4a9..8f276856df902 100644 --- a/src/test/regress/sql/inet.sql +++ b/src/test/regress/sql/inet.sql @@ -34,9 +34,10 @@ SELECT c AS cidr, i AS inet FROM INET_TBL; -- now test some support functions SELECT i AS inet, host(i), text(i), family(i) FROM INET_TBL; -SELECT c AS cidr, abbrev(c) FROM INET_TBL; -SELECT c AS cidr, broadcast(c), - i AS inet, broadcast(i) FROM INET_TBL; +SELECT c AS cidr, abbrev(c) AS "abbrev(cidr)", + i AS inet, abbrev(i) AS "abbrev(inet)" FROM INET_TBL; +SELECT c AS cidr, broadcast(c) AS "broadcast(cidr)", + i AS inet, broadcast(i) AS "broadcast(inet)" FROM INET_TBL; SELECT c AS cidr, network(c) AS "network(cidr)", i AS inet, network(i) AS "network(inet)" FROM INET_TBL; SELECT c AS cidr, masklen(c) AS "masklen(cidr)", @@ -46,6 +47,9 @@ SELECT c AS cidr, masklen(c) AS "masklen(cidr)", i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL WHERE masklen(c) <= 8; +SELECT i AS inet, netmask(i) AS "netmask(inet)" FROM INET_TBL; +SELECT i AS inet, hostmask(i) AS "hostmask(inet)" FROM INET_TBL; + SELECT c AS cidr, i AS inet FROM INET_TBL WHERE c = i; @@ -60,8 +64,15 @@ SELECT i, c, SELECT max(i) AS max, min(i) AS min FROM INET_TBL; SELECT max(c) AS max, min(c) AS min FROM INET_TBL; --- check the conversion to/from text and set_netmask -SELECT set_masklen(inet(text(i)), 24) FROM INET_TBL; +-- check the conversion to/from text and setting netmask +SELECT c AS cidr, set_masklen(cidr(text(c)), 24) AS "set_masklen(cidr)", + i AS inet, set_masklen(inet(text(i)), 24) AS "set_masklen(inet)" FROM INET_TBL; +-- check that netmask is treated as maximum value when set to -1 +SELECT c AS cidr, set_masklen(cidr(text(c)), -1) AS "set_masklen(cidr)", + i AS inet, set_masklen(inet(text(i)), -1) AS "set_masklen(inet)" FROM INET_TBL; +-- check that invalid netmask is rejected +SELECT set_masklen(inet(text(i)), 33) FROM INET_TBL; +SELECT set_masklen(cidr(text(c)), 33) FROM INET_TBL; -- check that btree index works correctly CREATE INDEX inet_idx1 ON inet_tbl(i); diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index e3bcfdb181e6c..699e8ac09c88e 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -96,6 +96,9 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid; -- Confirm PRIMARY KEY adds NOT NULL constraint to child table CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); INSERT INTO z VALUES (NULL, 'text'); -- should fail +-- ... but not UNIQUE. +CREATE TEMP TABLE z2 (b TEXT, UNIQUE(aa, b)) inherits (a); +INSERT INTO z2 VALUES (NULL, 'text'); -- should work -- Check inherited UPDATE with first child excluded create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit); @@ -377,8 +380,9 @@ CREATE TABLE inhta (); CREATE TABLE inhtb () INHERITS (inhta); CREATE TABLE inhtc () INHERITS (inhtb); CREATE TABLE inhtd () INHERITS (inhta, inhtb, inhtc); -ALTER TABLE inhta ADD COLUMN i int; +ALTER TABLE inhta ADD COLUMN i int, ADD COLUMN j bigint DEFAULT 1; \d+ inhta +\d+ inhtd DROP TABLE inhta, inhtb, inhtc, inhtd; -- Test for renaming in diamond inheritance @@ -465,12 +469,64 @@ alter table p1_c1 add constraint inh_check_constraint1 check (f1 > 0); alter table p1_c1 add constraint inh_check_constraint2 check (f1 < 10); alter table p1 add constraint inh_check_constraint2 check (f1 < 10); -select conrelid::regclass::text as relname, conname, conislocal, coninhcount +alter table p1 add constraint inh_check_constraint3 check (f1 > 0) not enforced; +alter table p1_c1 add constraint inh_check_constraint3 check (f1 > 0) not enforced; + +alter table p1_c1 add constraint inh_check_constraint4 check (f1 < 10) not enforced; +alter table p1 add constraint inh_check_constraint4 check (f1 < 10) not enforced; + +-- allowed to merge enforced constraint with parent's not enforced constraint +alter table p1_c1 add constraint inh_check_constraint5 check (f1 < 10) enforced; +alter table p1 add constraint inh_check_constraint5 check (f1 < 10) not enforced; + +alter table p1 add constraint inh_check_constraint6 check (f1 < 10) not enforced; +alter table p1_c1 add constraint inh_check_constraint6 check (f1 < 10) enforced; + +alter table p1_c1 add constraint inh_check_constraint9 check (f1 < 10) not valid enforced; +alter table p1 add constraint inh_check_constraint9 check (f1 < 10) not enforced; + +-- the not-valid state of the child constraint will be ignored here. +alter table p1 add constraint inh_check_constraint10 check (f1 < 10) not enforced; +alter table p1_c1 add constraint inh_check_constraint10 check (f1 < 10) not valid enforced; + +create table p1_c2(f1 int constraint inh_check_constraint4 check (f1 < 10)) inherits(p1); + +-- but reverse is not allowed +alter table p1_c1 add constraint inh_check_constraint7 check (f1 < 10) not enforced; +alter table p1 add constraint inh_check_constraint7 check (f1 < 10) enforced; + +alter table p1 add constraint inh_check_constraint8 check (f1 < 10) enforced; +alter table p1_c1 add constraint inh_check_constraint8 check (f1 < 10) not enforced; + +create table p1_fail(f1 int constraint inh_check_constraint2 check (f1 < 10) not enforced) inherits(p1); + +-- constraints with different enforceability can be merged by marking them as ENFORCED +create table p1_c3() inherits(p1, p1_c1); + +-- but not allowed if the child constraint is explicitly asked to be NOT ENFORCED +create table p1_fail(f1 int constraint inh_check_constraint6 check (f1 < 10) not enforced) inherits(p1, p1_c1); + +select conrelid::regclass::text as relname, conname, conislocal, coninhcount, conenforced, convalidated from pg_constraint where conname like 'inh\_check\_constraint%' order by 1, 2; drop table p1 cascade; +-- +-- Similarly, check the merging of existing constraints; a parent constraint +-- marked as NOT ENFORCED can merge with an ENFORCED child constraint, but the +-- reverse is not allowed. +-- +create table p1(f1 int constraint p1_a_check check (f1 > 0) not enforced); +create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) enforced); +alter table p1_c1 inherit p1; +drop table p1 cascade; + +create table p1(f1 int constraint p1_a_check check (f1 > 0) enforced); +create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) not enforced); +alter table p1_c1 inherit p1; +drop table p1, p1_c1; + -- -- Test DROP behavior of multiply-defined CHECK constraints -- @@ -601,6 +657,14 @@ select min(1-id) from matest0; reset enable_seqscan; reset enable_parallel_append; +explain (verbose, costs off) -- bug #18652 +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; +select 1 - id as c from +(select id from matest3 t1 union all select id * 2 from matest3 t2) ss +order by c; + drop table matest0 cascade; -- @@ -759,6 +823,358 @@ select * from cnullparent; select * from cnullparent where f1 = 2; drop table cnullparent cascade; +-- +-- Test inheritance of NOT NULL constraints +-- +create table pp1 (f1 int); +create table cc1 (f2 text, f3 int) inherits (pp1); +create table cc2 (f4 float) inherits (pp1,cc1); +create table cc3 () inherits (pp1,cc1,cc2); +alter table pp1 alter f1 set not null; +\d+ cc3 +alter table cc3 no inherit pp1; +alter table cc3 no inherit cc1; +alter table cc3 no inherit cc2; +\d+ cc3 +drop table cc3; + +-- named NOT NULL constraint +alter table cc1 add column a2 int constraint nn not null; +\d+ cc1 +\d+ cc2 +alter table pp1 alter column f1 set not null; +\d+ pp1 +\d+ cc1 +\d+ cc2 + +-- cannot create table with inconsistent NO INHERIT constraint +create table cc3 (a2 int not null no inherit) inherits (cc1); + +-- change NO INHERIT status of inherited constraint: no dice, it's inherited +alter table cc2 add not null a2 no inherit; + +-- remove constraint from cc2: no dice, it's inherited +alter table cc2 alter column a2 drop not null; + +-- remove constraint from cc1, should succeed +alter table cc1 alter column a2 drop not null; +\d+ cc1 + +-- same for cc2 +alter table cc2 alter column f1 drop not null; +\d+ cc2 + +-- remove from cc1, should fail again +alter table cc1 alter column f1 drop not null; + +-- remove from pp1, should succeed +alter table pp1 alter column f1 drop not null; +\d+ pp1 + +alter table pp1 add primary key (f1); +-- Leave these tables around, for pg_upgrade testing + +-- test that removing inheritance of NOT NULL NO INHERIT works correctly +create table inh_parent (f1 int not null no inherit, f2 int not null no inherit); +create table inh_child (f1 int not null no inherit, f2 int); +alter table inh_child inherit inh_parent; +alter table inh_child no inherit inh_parent; +\d+ inh_child +drop table inh_parent, inh_child; + +-- test that inhcount is updated correctly through multiple inheritance +create table inh_pp1 (f1 int); +create table inh_cc1 (f2 text, f3 int) inherits (inh_pp1); +create table inh_cc2(f4 float) inherits(inh_pp1,inh_cc1); +alter table inh_pp1 alter column f1 set not null; +alter table inh_cc2 no inherit inh_pp1; +alter table inh_cc2 no inherit inh_cc1; +\d+ inh_cc2 +drop table inh_pp1, inh_cc1, inh_cc2; + +create table inh_pp1 (f1 int not null); +create table inh_cc1 (f2 text, f3 int) inherits (inh_pp1); +create table inh_cc2(f4 float) inherits(inh_pp1,inh_cc1); +alter table inh_pp1 alter column f1 drop not null; +\d+ inh_cc2 +drop table inh_pp1, inh_cc1, inh_cc2; + + +-- Test a not-null addition that must walk down the hierarchy +CREATE TABLE inh_parent (); +CREATE TABLE inh_child (i int) INHERITS (inh_parent); +CREATE TABLE inh_grandchild () INHERITS (inh_parent, inh_child); +ALTER TABLE inh_parent ADD COLUMN i int NOT NULL; +drop table inh_parent, inh_child, inh_grandchild; + +-- Test the same constraint name for different columns in different parents +create table inh_parent1(a int constraint nn not null); +create table inh_parent2(b int constraint nn not null); +create table inh_child1 () inherits (inh_parent1, inh_parent2); +\d+ inh_child1 + +create table inh_child2 (constraint foo not null a) inherits (inh_parent1, inh_parent2); +alter table inh_child2 no inherit inh_parent2; +\d+ inh_child2 + +drop table inh_parent1, inh_parent2, inh_child1, inh_child2; + +-- Test multiple parents with overlapping primary keys +create table inh_parent1(a int, b int, c int, primary key (a, b)); +create table inh_parent2(d int, e int, b int, primary key (d, b)); +create table inh_child() inherits (inh_parent1, inh_parent2); +select conrelid::regclass, conname, contype, conkey, + coninhcount, conislocal, connoinherit + from pg_constraint where contype in ('n','p') and + conrelid::regclass::text in ('inh_child', 'inh_parent1', 'inh_parent2') + order by 1, 2; +\d+ inh_child +drop table inh_parent1, inh_parent2, inh_child; + +-- NOT NULL NO INHERIT +create table inh_nn_parent(a int); +create table inh_nn_child() inherits (inh_nn_parent); +alter table inh_nn_parent add not null a no inherit; +create table inh_nn_child2() inherits (inh_nn_parent); +select conrelid::regclass, conname, contype, conkey, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text like 'inh\_nn\_%' + order by 2, 1; +\d+ inh_nn* +drop table inh_nn_parent, inh_nn_child, inh_nn_child2; + +CREATE TABLE inh_nn_parent (a int, NOT NULL a NO INHERIT); +CREATE TABLE inh_nn_child() INHERITS (inh_nn_parent); +ALTER TABLE inh_nn_parent ADD CONSTRAINT nna NOT NULL a; +ALTER TABLE inh_nn_parent ALTER a SET NOT NULL; +DROP TABLE inh_nn_parent cascade; + +-- Adding a PK at the top level of a hierarchy should cause all descendants +-- to be checked for nulls, even past a no-inherit constraint +CREATE TABLE inh_nn_lvl1 (a int); +CREATE TABLE inh_nn_lvl2 () INHERITS (inh_nn_lvl1); +CREATE TABLE inh_nn_lvl3 (CONSTRAINT foo NOT NULL a NO INHERIT) INHERITS (inh_nn_lvl2); +ALTER TABLE inh_nn_lvl1 ADD PRIMARY KEY (a); +DROP TABLE inh_nn_lvl1, inh_nn_lvl2, inh_nn_lvl3; + +-- Disallow specifying conflicting NO INHERIT flags for the same constraint +CREATE TABLE inh_nn1 (a int primary key, b int, not null a no inherit); +CREATE TABLE inh_nn1 (a int not null); +CREATE TABLE inh_nn2 (a int not null no inherit) INHERITS (inh_nn1); +CREATE TABLE inh_nn3 (a int not null, b int, not null a no inherit); +CREATE TABLE inh_nn4 (a int not null no inherit, b int, not null a); +DROP TABLE IF EXISTS inh_nn1, inh_nn2, inh_nn3, inh_nn4; + +-- +-- test inherit/deinherit +-- +create table inh_parent(f1 int); +create table inh_child1(f1 int not null); +create table inh_child2(f1 int); + +-- inh_child1 should have not null constraint +alter table inh_child1 inherit inh_parent; + +-- should fail, missing NOT NULL constraint +alter table inh_child2 inherit inh_child1; + +alter table inh_child2 alter column f1 set not null; +alter table inh_child2 inherit inh_child1; + +-- add NOT NULL constraint recursively +alter table inh_parent alter column f1 set not null; + +\d+ inh_parent +\d+ inh_child1 +\d+ inh_child2 + +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent'::regclass, 'inh_child1'::regclass, 'inh_child2'::regclass) + order by 2, 1; + +-- +-- test deinherit procedure +-- + +-- deinherit inh_child1 +create table inh_child3 () inherits (inh_child1); +alter table inh_child1 no inherit inh_parent; +\d+ inh_parent +\d+ inh_child1 +\d+ inh_child2 +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_parent', 'inh_child1', 'inh_child2', 'inh_child3') + order by 2, 1; +drop table inh_parent, inh_child1, inh_child2, inh_child3; + +-- ALTER TABLE INHERIT ensures that the child has not-null constraints +create table inh_parent (a int not null); +create table inh_child (a int); +alter table inh_child inherit inh_parent; -- nope +drop table inh_parent, inh_child; + +-- Can't merge a NO INHERIT constraint with a normal one +create table inh_parent (a int not null); +create table inh_child (a int not null no inherit); +alter table inh_child inherit inh_parent; +drop table inh_parent, inh_child; + +-- don't interfere with other types of constraints +create table inh_parent (a int primary key); +create table inh_child (a int primary key) inherits (inh_parent); +alter table inh_parent add constraint inh_parent_excl exclude ((1) with =); +alter table inh_parent add constraint inh_parent_uq unique (a); +alter table inh_parent add constraint inh_parent_fk foreign key (a) references inh_parent (a); +create table inh_child2 () inherits (inh_parent); +create table inh_child3 (like inh_parent); +alter table inh_child3 inherit inh_parent; +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint + where conrelid::regclass::text in ('inh_parent', 'inh_child', 'inh_child2', 'inh_child3') + order by 2, 1; + +drop table inh_parent, inh_child, inh_child2, inh_child3; + +-- +-- test multi inheritance tree +-- +create table inh_parent(f1 int not null); +create table inh_child1() inherits(inh_parent); +create table inh_child2() inherits(inh_parent); +create table inh_child3() inherits(inh_child1, inh_child2); + +-- show constraint info +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent'::regclass, 'inh_child1'::regclass, 'inh_child2'::regclass, 'inh_child3'::regclass) + order by 2, conrelid::regclass::text; + +drop table inh_parent cascade; + +-- test child table with inherited columns and +-- with explicitly specified not null constraints +create table inh_parent_1(f1 int); +create table inh_parent_2(f2 text); +create table inh_child(f1 int not null, f2 text not null) inherits(inh_parent_1, inh_parent_2); + +-- show constraint info +select conrelid::regclass, conname, contype, coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid in ('inh_parent_1'::regclass, 'inh_parent_2'::regclass, 'inh_child'::regclass) + order by 2, conrelid::regclass::text; + +-- also drops inh_child table +drop table inh_parent_1 cascade; +drop table inh_parent_2; + +-- test multi layer inheritance tree +create table inh_p1(f1 int not null); +create table inh_p2(f1 int not null); +create table inh_p3(f2 int); +create table inh_p4(f1 int not null, f3 text not null); + +create table inh_multiparent() inherits(inh_p1, inh_p2, inh_p3, inh_p4); + +-- constraint on f1 should have three parents +select conrelid::regclass, contype, conname, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass in ('inh_p1', 'inh_p2', 'inh_p3', 'inh_p4', + 'inh_multiparent') + order by conrelid::regclass::text, conname; + +create table inh_multiparent2 (a int not null, f1 int) inherits(inh_p3, inh_multiparent); +select conrelid::regclass, contype, conname, + (select attname from pg_attribute where attrelid = conrelid and attnum = conkey[1]), + coninhcount, conislocal + from pg_constraint where contype = 'n' and + conrelid::regclass in ('inh_p3', 'inh_multiparent', 'inh_multiparent2') + order by conrelid::regclass::text, conname; + +drop table inh_p1, inh_p2, inh_p3, inh_p4 cascade; + +-- +-- Test ALTER CONSTRAINT SET [NO] INHERIT +-- +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int, f1 int); +alter table inh_nn2 inherit inh_nn1; +create table inh_nn3 (f4 float) inherits (inh_nn2); +create table inh_nn4 (f5 int, f4 float, f2 text, f3 int, f1 int); +alter table inh_nn4 inherit inh_nn2, inherit inh_nn1, inherit inh_nn3; +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; +-- ALTER CONSTRAINT NO INHERIT should work on top-level constraints +alter table inh_nn1 alter constraint inh_nn1_f1_not_null no inherit; +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; +-- A constraint that's NO INHERIT can be dropped without damaging children +alter table inh_nn1 drop constraint inh_nn1_f1_not_null; +select conrelid::regclass, conname, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; +drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4; + +-- Test inherit constraint and make sure it validates. +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1); +insert into inh_nn2 values(NULL, 'sample', 1); +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +delete from inh_nn2; +create table inh_nn3 () inherits (inh_nn2); +create table inh_nn4 () inherits (inh_nn1, inh_nn2); +alter table inh_nn1 -- test multicommand alter table while at it + alter constraint inh_nn1_f1_not_null inherit, + alter constraint inh_nn1_f1_not_null no inherit; +select conrelid::regclass, conname, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3', 'inh_nn4') + order by 2, 1; +drop table inh_nn1, inh_nn2, inh_nn3, inh_nn4; + +-- Test not null inherit constraint which already exists on child table. +create table inh_nn1 (f1 int not null no inherit); +create table inh_nn2 (f2 text, f3 int) inherits (inh_nn1); +create table inh_nn3 (f4 float, constraint nn3_f1 not null f1 no inherit) inherits (inh_nn1, inh_nn2); +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') + order by 2, 1; +-- error: inh_nn3 has an incompatible NO INHERIT constraint +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; +alter table inh_nn3 alter constraint nn3_f1 inherit; +alter table inh_nn1 alter constraint inh_nn1_f1_not_null inherit; -- now it works +select conrelid::regclass, conname, conkey, coninhcount, conislocal, connoinherit + from pg_constraint where contype = 'n' and + conrelid::regclass::text in ('inh_nn1', 'inh_nn2', 'inh_nn3') + order by 2, 1; +drop table inh_nn1, inh_nn2, inh_nn3; + +-- Negative scenarios for alter constraint .. inherit. +create table inh_nn1 (f1 int check(f1 > 5) primary key references inh_nn1, f2 int not null); +-- constraints other than not-null are not supported +alter table inh_nn1 alter constraint inh_nn1_f1_check inherit; +alter table inh_nn1 alter constraint inh_nn1_pkey inherit; +alter table inh_nn1 alter constraint inh_nn1_f1_fkey inherit; +-- try to drop a nonexistant constraint +alter table inh_nn1 alter constraint foo inherit; +-- Can't modify inheritability of inherited constraints +create table inh_nn2 () inherits (inh_nn1); +alter table inh_nn2 alter constraint inh_nn1_f2_not_null no inherit; + +drop table inh_nn1, inh_nn2; + -- -- Mixed ownership inheritance tree -- @@ -1152,3 +1568,24 @@ UPDATE errtst_parent SET partid = 0, data = data + 10 WHERE partid = 20; UPDATE errtst_parent SET partid = 30, data = data + 10 WHERE partid = 20; DROP TABLE errtst_parent; + +-- Check that we have the correct tuples estimate for an appendrel +create table tuplesest_parted (a int, b int, c float) partition by range(a); +create table tuplesest_parted1 partition of tuplesest_parted for values from (0) to (100); +create table tuplesest_parted2 partition of tuplesest_parted for values from (100) to (200); + +create table tuplesest_tab (a int, b int); + +insert into tuplesest_parted select i%200, i%300, i%400 from generate_series(1, 1000)i; +insert into tuplesest_tab select i, i from generate_series(1, 100)i; + +analyze tuplesest_parted; +analyze tuplesest_tab; + +explain (costs off) +select * from tuplesest_tab join + (select b from tuplesest_parted where c < 100 group by b) sub + on tuplesest_tab.a = sub.b; + +drop table tuplesest_parted; +drop table tuplesest_tab; diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql index fffb28906a1e6..53359f06ade97 100644 --- a/src/test/regress/sql/int8.sql +++ b/src/test/regress/sql/int8.sql @@ -110,6 +110,7 @@ SELECT to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S999999999 FROM INT8_TBL; SELECT to_char(q2, 'MI9999999999999999') FROM INT8_TBL; +SELECT to_char(q2, '9999999999999999PL') FROM INT8_TBL; SELECT to_char(q2, 'FMS9999999999999999') FROM INT8_TBL; SELECT to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL; SELECT to_char(q2, 'SG9999999999999999th') FROM INT8_TBL; @@ -122,6 +123,13 @@ SELECT to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL; SELECT to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL; SELECT to_char(q2, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; SELECT to_char(q2, '999999SG9999999999') FROM INT8_TBL; +SELECT to_char(q2, 'FMRN') FROM INT8_TBL; + +SELECT to_char(1234, '9.99EEEE'); +SELECT to_char(1234::int8, '9.99eeee'); +SELECT to_char(-1234::int8, '9.99eeee'); +SELECT to_char(1234, '99999V99'); +SELECT to_char(1234::int8, '99999V99'); -- check min/max values and overflow behavior diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql index fbf6e064d66bd..43bc793925ee5 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -592,6 +592,7 @@ SELECT f1, EXTRACT(MINUTE FROM f1) AS MINUTE, EXTRACT(HOUR FROM f1) AS HOUR, EXTRACT(DAY FROM f1) AS DAY, + EXTRACT(WEEK FROM f1) AS WEEK, EXTRACT(MONTH FROM f1) AS MONTH, EXTRACT(QUARTER FROM f1) AS QUARTER, EXTRACT(YEAR FROM f1) AS YEAR, @@ -601,6 +602,23 @@ SELECT f1, EXTRACT(EPOCH FROM f1) AS EPOCH FROM INTERVAL_TBL; +SELECT -f1, + EXTRACT(MICROSECOND FROM -f1) AS MICROSECOND, + EXTRACT(MILLISECOND FROM -f1) AS MILLISECOND, + EXTRACT(SECOND FROM -f1) AS SECOND, + EXTRACT(MINUTE FROM -f1) AS MINUTE, + EXTRACT(HOUR FROM -f1) AS HOUR, + EXTRACT(DAY FROM -f1) AS DAY, + EXTRACT(WEEK FROM -f1) AS WEEK, + EXTRACT(MONTH FROM -f1) AS MONTH, + EXTRACT(QUARTER FROM -f1) AS QUARTER, + EXTRACT(YEAR FROM -f1) AS YEAR, + EXTRACT(DECADE FROM -f1) AS DECADE, + EXTRACT(CENTURY FROM -f1) AS CENTURY, + EXTRACT(MILLENNIUM FROM -f1) AS MILLENNIUM, + EXTRACT(EPOCH FROM -f1) AS EPOCH + FROM INTERVAL_TBL; + SELECT EXTRACT(FORTNIGHT FROM INTERVAL '2 days'); -- error SELECT EXTRACT(TIMEZONE FROM INTERVAL '2 days'); -- error @@ -758,6 +776,14 @@ SELECT i AS interval, date_trunc('hour', i) FROM INFINITE_INTERVAL_TBL WHERE NOT isfinite(i); +SELECT i AS interval, date_trunc('week', i) + FROM INFINITE_INTERVAL_TBL + WHERE NOT isfinite(i); + +SELECT i AS interval, date_trunc('ago', i) + FROM INFINITE_INTERVAL_TBL + WHERE NOT isfinite(i); + SELECT i AS interval, justify_days(i), justify_hours(i), justify_interval(i) FROM INFINITE_INTERVAL_TBL WHERE NOT isfinite(i); diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index d81ff63be5374..cc5128add4df0 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -441,6 +441,27 @@ select a.f1, b.f1, t.thousand, t.tenthous from (select sum(f1) as f1 from int4_tbl i4b) b where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; +-- +-- Test hash joins with multiple hash keys and subplans. +-- + +-- First ensure we get a hash join with multiple hash keys. +explain (costs off) +select t1.unique1,t2.unique1 from tenk1 t1 +inner join tenk1 t2 on t1.two = t2.two + and t1.unique1 = (select min(unique1) from tenk1 + where t2.unique1=unique1) +where t1.unique1 < 10 and t2.unique1 < 10 +order by t1.unique1; + +-- Ensure we get the expected result +select t1.unique1,t2.unique1 from tenk1 t1 +inner join tenk1 t2 on t1.two = t2.two + and t1.unique1 = (select min(unique1) from tenk1 + where t2.unique1=unique1) +where t1.unique1 < 10 and t2.unique1 < 10 +order by t1.unique1; + -- -- checks for correct handling of quals in multiway outer joins -- @@ -717,6 +738,27 @@ where not exists (select 1 from tbl_ra t2 where t2.b = t1.a) and t1.b < 2; reset enable_hashjoin; reset enable_nestloop; +-- +-- regression test for bug with hash-right-semi join +-- + +create temp table tbl_rs(a int, b int); +insert into tbl_rs select i, i from generate_series(1,10)i; +analyze tbl_rs; + +-- ensure we get a hash right semi join +explain (costs off) +select * from tbl_rs t1 join + lateral (select * from tbl_rs t2 where t2.a in + (select t1.a+t3.a from tbl_rs t3) and t2.a < 5) + on true; + +-- and check we get the expected results +select * from tbl_rs t1 join + lateral (select * from tbl_rs t2 where t2.a in + (select t1.a+t3.a from tbl_rs t3) and t2.a < 5) + on true; + -- -- regression test for bug #13908 (hash join with skew tuples & nbatch increase) -- @@ -797,6 +839,14 @@ explain (costs off) select a.* from tenk1 a left join tenk1 b on a.unique1 = b.unique2 where b.unique2 is null; +-- +-- regression test for bogus RTE_GROUP entries +-- + +explain (costs off) +select a.* from tenk1 a +where exists (select 1 from tenk1 b where a.unique1 = b.unique2 group by b.unique1); + -- -- regression test for proper handling of outer joins within antijoins -- @@ -1433,6 +1483,15 @@ select * from tenk1 a join tenk1 b on (a.unique1 = 1 and b.unique1 = 2) or ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 = 1 and b.unique1 = 2) or + ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); +explain (costs off) +select * from tenk1 a join tenk1 b on + (a.unique1 < 20 or a.unique1 = 3 or a.unique1 = 1 and b.unique1 = 2) or + ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); + -- -- test placement of movable quals in a parameterized join tree -- @@ -1952,17 +2011,22 @@ CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int); CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int); CREATE TEMP TABLE c (id int PRIMARY KEY); CREATE TEMP TABLE d (a int, b int); +CREATE TEMP TABLE e (id1 int, id2 int, PRIMARY KEY(id1, id2)); INSERT INTO a VALUES (0, 0), (1, NULL); INSERT INTO b VALUES (0, 0), (1, NULL); INSERT INTO c VALUES (0), (1); INSERT INTO d VALUES (1,3), (2,2), (3,1); +INSERT INTO e VALUES (0,0), (2,2), (3,1); --- all three cases should be optimizable into a simple seqscan +-- all these cases should be optimizable into a simple seqscan explain (costs off) SELECT a.* FROM a LEFT JOIN b ON a.b_id = b.id; explain (costs off) SELECT b.* FROM b LEFT JOIN c ON b.c_id = c.id; explain (costs off) SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id) ON (a.b_id = b.id); +explain (costs off) + SELECT a.* FROM a LEFT JOIN b ON a.id = b.id + LEFT JOIN e ON e.id1 = a.b_id AND b.c_id = e.id2; -- check optimization of outer join within another special join explain (costs off) @@ -2111,6 +2175,17 @@ select c.id, ss.a from c left join (select d.a from onerow, d left join b on d.a = b.id) ss on c.id = ss.a; +-- check the case when the placeholder relates to an outer join and its +-- inner in the press field but actually uses only the outer side of the join +explain (costs off) +SELECT q.val FROM b LEFT JOIN ( + SELECT (q1.z IS NOT NULL) AS val + FROM b LEFT JOIN ( + SELECT (t1.b_id IS NOT NULL) AS z FROM a t1 LEFT JOIN a t2 USING (id) + ) AS q1 + ON true +) AS q ON true; + CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10); @@ -2345,6 +2420,516 @@ select * from select * from int8_tbl x join (int4_tbl x cross join int4_tbl y(ff)) j on q1 = f1; -- ok +-- +-- test that semi- or inner self-joins on a unique column are removed +-- + +-- enable only nestloop to get more predictable plans +set enable_hashjoin to off; +set enable_mergejoin to off; + +create table sj (a int unique, b int, c int unique); +insert into sj values (1, null, 2), (null, 2, null), (2, 1, 1); +analyze sj; + +-- Trivial self-join case. +explain (costs off) +select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; +select p.* from sj p, sj q where q.a = p.a and q.b = q.a - 1; + +-- Self-join removal performs after a subquery pull-up process and could remove +-- such kind of self-join too. Check this option. +explain (costs off) +select * from sj p +where exists (select * from sj q + where q.a = p.a and q.b < 10); +select * from sj p +where exists (select * from sj q + where q.a = p.a and q.b < 10); + +-- Don't remove self-join for the case of equality of two different unique columns. +explain (costs off) +select * from sj t1, sj t2 where t1.a = t2.c and t1.b is not null; + +-- Ensure that relations with TABLESAMPLE clauses are not considered as +-- candidates to be removed +explain (costs off) +select * from sj t1 + join lateral + (select * from sj tablesample system(t1.b)) s + on t1.a = s.a; + +-- Ensure that SJE does not form a self-referential lateral dependency +explain (costs off) +select * from sj t1 + left join lateral + (select t1.a as t1a, * from sj t2) s + on true +where t1.a = s.a; + +-- Degenerated case. +explain (costs off) +select * from + (select a as x from sj where false) as q1, + (select a as y from sj where false) as q2 +where q1.x = q2.y; + +-- We can't use a cross-EC generated self join qual because of current logic of +-- the generate_join_implied_equalities routine. +explain (costs off) +select * from sj t1, sj t2 where t1.a = t1.b and t1.b = t2.b and t2.b = t2.a; +explain (costs off) +select * from sj t1, sj t2, sj t3 +where t1.a = t1.b and t1.b = t2.b and t2.b = t2.a and + t1.b = t3.b and t3.b = t3.a; + +-- Double self-join removal. +-- Use a condition on "b + 1", not on "b", for the second join, so that +-- the equivalence class is different from the first one, and we can +-- test the non-ec code path. +explain (costs off) +select * +from sj t1 + join sj t2 on t1.a = t2.a and t1.b = t2.b + join sj t3 on t2.a = t3.a and t2.b + 1 = t3.b + 1; + +-- subselect that references the removed relation +explain (costs off) +select t1.a, (select a from sj where a = t2.a and a = t1.a) +from sj t1, sj t2 +where t1.a = t2.a; + +-- self-join under outer join +explain (costs off) +select * from sj x join sj y on x.a = y.a +left join int8_tbl z on x.a = z.q1; + +explain (costs off) +select * from sj x join sj y on x.a = y.a +left join int8_tbl z on y.a = z.q1; + +explain (costs off) +select * from ( + select t1.*, t2.a as ax from sj t1 join sj t2 + on (t1.a = t2.a and t1.c * t1.c = t2.c + 2 and t2.b is null) +) as q1 +left join + (select t3.* from sj t3, sj t4 where t3.c = t4.c) as q2 +on q1.ax = q2.a; + +-- Test that placeholders are updated correctly after join removal +explain (costs off) +select * from (values (1)) x +left join (select coalesce(y.q1, 1) from int8_tbl y + right join sj j1 inner join sj j2 on j1.a = j2.a + on true) z +on true; + +-- Test that references to the removed rel in lateral subqueries are replaced +-- correctly after join removal +explain (verbose, costs off) +select t3.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select t1.a offset 0) t3 on true; + +explain (verbose, costs off) +select t3.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select * from (select t1.a offset 0) offset 0) t3 on true; + +explain (verbose, costs off) +select t4.a from sj t1 + join sj t2 on t1.a = t2.a + join lateral (select t3.a from sj t3, (select t1.a) offset 0) t4 on true; + +-- Check updating of semi_rhs_exprs links from upper-level semi join to +-- the removing relation +explain (verbose, costs off) +select t1.a from sj t1 where t1.b in ( + select t2.b from sj t2 join sj t3 on t2.c=t3.c); + +-- +-- SJE corner case: uniqueness of an inner is [partially] derived from +-- baserestrictinfo clauses. +-- XXX: We really should allow SJE for these corner cases? +-- + +INSERT INTO sj VALUES (3, 1, 3); + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 3; +-- Return one row +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 3; + +-- Remove SJ, define uniqueness by a constant +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 2; +-- Return one row +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2 AND j2.a = 2; + +-- Remove SJ, define uniqueness by a constant expression +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND j1.a = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = j2.a; +-- Return one row +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND j1.a = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = j2.a; + +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 1 AND j2.a = 1; +-- Return no rows +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 1 AND j2.a = 1; + +-- Shuffle a clause. Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 1 = j1.a AND j2.a = 1; +-- Return no rows +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 1 = j1.a AND j2.a = 1; + +-- SJE Corner case: a 'a.x=a.x' clause, have replaced with 'a.x IS NOT NULL' +-- after SJ elimination it shouldn't be a mergejoinable clause. +EXPLAIN (COSTS OFF) +SELECT t4.* +FROM (SELECT t1.*, t2.a AS a1 FROM sj t1, sj t2 WHERE t1.b = t2.b) AS t3 +JOIN sj t4 ON (t4.a = t3.a) WHERE t3.a1 = 42; +SELECT t4.* +FROM (SELECT t1.*, t2.a AS a1 FROM sj t1, sj t2 WHERE t1.b = t2.b) AS t3 +JOIN sj t4 ON (t4.a = t3.a) WHERE t3.a1 = 42; + +-- Functional index +CREATE UNIQUE INDEX sj_fn_idx ON sj((a * a)); + +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a*j1.a = 1 AND j2.a*j2.a = 1; +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a*j1.a = 1 AND j2.a*j2.a = 2; + +-- Restriction contains expressions in both sides, Remove SJ. +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.a) = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = (j2.a*j2.a); +-- Empty set of rows should be returned +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.a) = (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int + AND (EXTRACT(DOW FROM current_timestamp(0))/15 + 3)::int = (j2.a*j2.a); + +-- Restriction contains volatile function - disable SJE feature. +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.c/3) = (random()/3 + 3)::int + AND (random()/3 + 3)::int = (j2.a*j2.c/3); +-- Return one row +SELECT * FROM sj j1, sj j2 +WHERE j1.b = j2.b + AND (j1.a*j1.c/3) = (random()/3 + 3)::int + AND (random()/3 + 3)::int = (j2.a*j2.c/3); + +-- Multiple filters +CREATE UNIQUE INDEX sj_temp_idx1 ON sj(a,b,c); + +-- Remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND j1.a = 2 AND j1.c = 3 AND j2.a = 2 AND 3 = j2.c; + +-- Don't remove SJ +EXPLAIN (COSTS OFF) + SELECT * FROM sj j1, sj j2 + WHERE j1.b = j2.b AND 2 = j1.a AND j1.c = 3 AND j2.a = 1 AND 3 = j2.c; + +CREATE UNIQUE INDEX sj_temp_idx ON sj(a,b); + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND j1.a = 2; + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND 2 = j2.a; + +-- Don't remove SJ +EXPLAIN (COSTS OFF) +SELECT * FROM sj j1, sj j2 WHERE j1.b = j2.b AND (j1.a = 1 OR j2.a = 1); + +DROP INDEX sj_fn_idx, sj_temp_idx1, sj_temp_idx; + +-- Test that OR predicated are updated correctly after join removal +CREATE TABLE tab_with_flag ( id INT PRIMARY KEY, is_flag SMALLINT); +CREATE INDEX idx_test_is_flag ON tab_with_flag (is_flag); + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tab_with_flag +WHERE + (is_flag IS NULL OR is_flag = 0) + AND id IN (SELECT id FROM tab_with_flag WHERE id IN (2, 3)); +DROP TABLE tab_with_flag; + +-- HAVING clause +explain (costs off) +select p.b from sj p join sj q on p.a = q.a group by p.b having sum(p.a) = 1; + +-- update lateral references and range table entry reference +explain (verbose, costs off) +select 1 from (select x.* from sj x, sj y where x.a = y.a) q, + lateral generate_series(1, q.a) gs(i); + +explain (verbose, costs off) +select 1 from (select y.* from sj x, sj y where x.a = y.a) q, + lateral generate_series(1, q.a) gs(i); + +-- Test that a non-EC-derived join clause is processed correctly. Use an +-- outer join so that we can't form an EC. +explain (costs off) select * from sj p join sj q on p.a = q.a + left join sj r on p.a + q.a = r.a; + +-- FIXME this constant false filter doesn't look good. Should we merge +-- equivalence classes? +explain (costs off) +select * from sj p, sj q where p.a = q.a and p.b = 1 and q.b = 2; + +-- Check that attr_needed is updated correctly after self-join removal. In this +-- test, the join of j1 with j2 is removed. k1.b is required at either j1 or j2. +-- If this info is lost, join targetlist for (k1, k2) will not contain k1.b. +-- Use index scan for k1 so that we don't get 'b' from physical tlist used for +-- seqscan. Also disable reordering of joins because this test depends on a +-- particular join tree. +create table sk (a int, b int); +create index on sk(a); +set join_collapse_limit to 1; +set enable_seqscan to off; +explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j1.b = k1.b; +explain (costs off) select 1 from + (sk k1 join sk k2 on k1.a = k2.a) + join (sj j1 join sj j2 on j1.a = j2.a) on j2.b = k1.b; +reset join_collapse_limit; +reset enable_seqscan; + +-- Check that clauses from the join filter list is not lost on the self-join removal +CREATE TABLE emp1 (id SERIAL PRIMARY KEY NOT NULL, code int); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT * FROM emp1 e1, emp1 e2 WHERE e1.id = e2.id AND e2.code <> e1.code; + +-- Shuffle self-joined relations. Only in the case of iterative deletion +-- attempts explains of these queries will be identical. +CREATE UNIQUE INDEX ON emp1((id*id)); + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c1.id=c2.id AND c1.id*c2.id=c3.id*c3.id; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c1.id=c3.id AND c1.id*c3.id=c2.id*c2.id; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM emp1 c1, emp1 c2, emp1 c3 +WHERE c3.id=c2.id AND c3.id*c2.id=c1.id*c1.id; + +-- Check the usage of a parse tree by the set operations (bug #18170) +EXPLAIN (COSTS OFF) +SELECT c1.code FROM emp1 c1 LEFT JOIN emp1 c2 ON c1.id = c2.id +WHERE c2.id IS NOT NULL +EXCEPT ALL +SELECT c3.code FROM emp1 c3; + +-- Check that SJE removes references from PHVs correctly +explain (costs off) +select * from emp1 t1 left join + (select coalesce(t3.code, 1) from emp1 t2 + left join (emp1 t3 join emp1 t4 on t3.id = t4.id) + on true) +on true; + +-- Try PHV, which could potentially be removed completely by SJE, but that's +-- not implemented yet. +explain (verbose, costs off) +select 1 from emp1 t1 left join + ((select 1 as x, * from emp1 t2) s1 inner join + (select * from emp1 t3) s2 on s1.id = s2.id) + on true +where s1.x = 1; + +-- Check that PHVs do not impose any constraints on removing self joins +explain (verbose, costs off) +select * from emp1 t1 join emp1 t2 on t1.id = t2.id left join + lateral (select t1.id as t1id, * from generate_series(1,1) t3) s on true; + +explain (verbose, costs off) +select * from generate_series(1,10) t1(id) left join + lateral (select t1.id as t1id, t2.id from emp1 t2 join emp1 t3 on t2.id = t3.id) +on true; + +-- This is a degenerate case of PHV usage: it is evaluated and needed inside +-- a baserel scan operation that the SJE removes. The PHV in this test should +-- be in the filter of parameterized Index Scan: the replace_nestloop_params() +-- code will detect if the placeholder list doesn't have a reference to this +-- parameter. +-- +-- NOTE: enable_hashjoin and enable_mergejoin must be disabled. +CREATE TABLE tbl_phv(x int, y int PRIMARY KEY); +CREATE INDEX tbl_phv_idx ON tbl_phv(x); +INSERT INTO tbl_phv (x, y) + SELECT gs, gs FROM generate_series(1,100) AS gs; +VACUUM ANALYZE tbl_phv; +EXPLAIN (COSTS OFF, VERBOSE) +SELECT 1 FROM tbl_phv t1 LEFT JOIN + (SELECT 1 extra, x, y FROM tbl_phv tl) t3 JOIN + (SELECT y FROM tbl_phv tr) t4 + ON t4.y = t3.y +ON true WHERE t3.extra IS NOT NULL AND t3.x = t1.x % 2; +DROP TABLE IF EXISTS tbl_phv; + +-- Check that SJE replaces join clauses involving the removed rel correctly +explain (costs off) +select * from emp1 t1 + inner join emp1 t2 on t1.id = t2.id + left join emp1 t3 on t1.id > 1 and t1.id < 2; + +-- Check that SJE doesn't replace the target relation +EXPLAIN (COSTS OFF) +WITH t1 AS (SELECT * FROM emp1) +UPDATE emp1 SET code = t1.code + 1 FROM t1 +WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code; + +-- Check that SJE correctly replaces relations in OR-clauses +EXPLAIN (COSTS OFF) +SELECT * FROM emp1 t1 + INNER JOIN emp1 t2 ON t1.id = t2.id + LEFT JOIN emp1 t3 ON t1.code = 1 AND (t2.code = t3.code OR t2.code = 1); + + INSERT INTO emp1 VALUES (1, 1), (2, 1); + +WITH t1 AS (SELECT * FROM emp1) +UPDATE emp1 SET code = t1.code + 1 FROM t1 +WHERE t1.id = emp1.id RETURNING emp1.id, emp1.code, t1.code; + +TRUNCATE emp1; + +EXPLAIN (COSTS OFF) +UPDATE sj sq SET b = 1 FROM sj as sz WHERE sq.a = sz.a; + +CREATE RULE sj_del_rule AS ON DELETE TO sj + DO INSTEAD + UPDATE sj SET a = 1 WHERE a = old.a; +EXPLAIN (COSTS OFF) DELETE FROM sj; +DROP RULE sj_del_rule ON sj CASCADE; + +-- Check that SJE does not mistakenly omit qual clauses (bug #18187) +insert into emp1 values (1, 1); +explain (costs off) +select 1 from emp1 full join + (select * from emp1 t1 join + emp1 t2 join emp1 t3 on t2.id = t3.id + on true + where false) s on true +where false; +select 1 from emp1 full join + (select * from emp1 t1 join + emp1 t2 join emp1 t3 on t2.id = t3.id + on true + where false) s on true +where false; + +-- Check that SJE does not mistakenly re-use knowledge of relation uniqueness +-- made with different set of quals +insert into emp1 values (2, 1); +explain (costs off) +select * from emp1 t1 where exists (select * from emp1 t2 + where t2.id = t1.code and t2.code > 0); +select * from emp1 t1 where exists (select * from emp1 t2 + where t2.id = t1.code and t2.code > 0); + +-- We can remove the join even if we find the join can't duplicate rows and +-- the base quals of each side are different. In the following case we end up +-- moving quals over to s1 to make it so it can't match any rows. +create table sl(a int, b int, c int); +create unique index on sl(a, b); +vacuum analyze sl; + +-- Both sides are unique, but base quals are different +explain (costs off) +select * from sl t1, sl t2 where t1.a = t2.a and t1.b = 1 and t2.b = 2; + +-- Check NullTest in baserestrictinfo list +explain (costs off) +select * from sl t1, sl t2 +where t1.a = t2.a and t1.b = 1 and t2.b = 2 + and t1.c IS NOT NULL and t2.c IS NOT NULL + and t2.b IS NOT NULL and t1.b IS NOT NULL + and t1.a IS NOT NULL and t2.a IS NOT NULL; +explain (verbose, costs off) +select * from sl t1, sl t2 +where t1.b = t2.b and t2.a = 3 and t1.a = 3 + and t1.c IS NOT NULL and t2.c IS NOT NULL + and t2.b IS NOT NULL and t1.b IS NOT NULL + and t1.a IS NOT NULL and t2.a IS NOT NULL; + +-- Join qual isn't mergejoinable, but inner is unique. +EXPLAIN (COSTS OFF) +SELECT n2.a FROM sj n1, sj n2 WHERE n1.a <> n2.a AND n2.a = 1; + +EXPLAIN (COSTS OFF) +SELECT * FROM +(SELECT n2.a FROM sj n1, sj n2 WHERE n1.a <> n2.a) q0, sl +WHERE q0.a = 1; + +-- Check optimization disabling if it will violate special join conditions. +-- Two identical joined relations satisfies self join removal conditions but +-- stay in different special join infos. +CREATE TABLE sj_t1 (id serial, a int); +CREATE TABLE sj_t2 (id serial, a int); +CREATE TABLE sj_t3 (id serial, a int); +CREATE TABLE sj_t4 (id serial, a int); + +CREATE UNIQUE INDEX ON sj_t3 USING btree (a,id); +CREATE UNIQUE INDEX ON sj_t2 USING btree (id); + +EXPLAIN (COSTS OFF) +SELECT * FROM sj_t1 +JOIN ( + SELECT sj_t2.id AS id FROM sj_t2 + WHERE EXISTS + ( + SELECT TRUE FROM sj_t3,sj_t4 WHERE sj_t3.a = 1 AND sj_t3.id = sj_t2.id + ) + ) t2t3t4 +ON sj_t1.id = t2t3t4.id +JOIN ( + SELECT sj_t2.id AS id FROM sj_t2 + WHERE EXISTS + ( + SELECT TRUE FROM sj_t3,sj_t4 WHERE sj_t3.a = 1 AND sj_t3.id = sj_t2.id + ) + ) _t2t3t4 +ON sj_t1.id = _t2t3t4.id; + +-- +-- Test RowMarks-related code +-- + +-- Both sides have explicit LockRows marks +EXPLAIN (COSTS OFF) +SELECT a1.a FROM sj a1,sj a2 WHERE (a1.a=a2.a) FOR UPDATE; + +reset enable_hashjoin; +reset enable_mergejoin; + -- -- Test hints given on incorrect column references are useful -- @@ -2952,3 +3537,49 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS RESET enable_indexonlyscan; RESET enable_seqscan; +-- Test BitmapHeapScan with a rescan releases resources correctly +SET enable_seqscan = off; +SET enable_indexscan = off; + +CREATE TEMP TABLE rescan_bhs (a INT); +INSERT INTO rescan_bhs VALUES (1), (2); +CREATE INDEX ON rescan_bhs (a); + +EXPLAIN (COSTS OFF) +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + +RESET enable_seqscan; +RESET enable_indexscan; + +-- Test that we do not account for nullingrels when looking up statistics +CREATE TABLE group_tbl (a INT, b INT); +INSERT INTO group_tbl SELECT 1, 1; +CREATE STATISTICS group_tbl_stat (ndistinct) ON a, b FROM group_tbl; +ANALYZE group_tbl; + +EXPLAIN (COSTS OFF) +SELECT 1 FROM group_tbl t1 + LEFT JOIN (SELECT a c1, COALESCE(a) c2 FROM group_tbl t2) s ON TRUE +GROUP BY s.c1, s.c2; + +DROP TABLE group_tbl; + +-- +-- Test for a nested loop join involving index scan, transforming OR-clauses +-- to SAOP. +-- + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index ec57dfe707077..e9800b21ffed6 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -12,6 +12,13 @@ SELECT '"\v"'::json; -- ERROR, not a valid JSON escape SELECT ('"'||repeat('.', 12)||'abc"')::json; -- OK SELECT ('"'||repeat('.', 12)||'abc\n"')::json; -- OK, legal escapes +-- Test various lengths of strings to validate SIMD processing to escape +-- special chars in the JSON. +SELECT row_to_json(j)::jsonb FROM ( + SELECT left(E'abcdefghijklmnopqrstuv"\twxyz012345678', a) AS a + FROM generate_series(0,37) a +) j; + -- see json_encoding test for input with unicode escapes -- Numbers. @@ -748,6 +755,8 @@ select json_object('{a,b,NULL,"d e f"}','{1,2,3,"a b c"}'); select json_object('{a,b,"","d e f"}','{1,2,3,"a b c"}'); +-- json_object_agg_unique requires unique keys +select json_object_agg_unique(mod(i,100), i) from generate_series(0, 199) i; -- json_to_record and json_to_recordset @@ -805,6 +814,25 @@ select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]'); -- an empty object is not null and should not be stripped select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); +-- json_strip_nulls (strip_in_arrays=true) + +select json_strip_nulls(null, true); + +select json_strip_nulls('1', true); + +select json_strip_nulls('"a string"', true); + +select json_strip_nulls('null', true); + +select json_strip_nulls('[1,2,null,3,4]', true); + +select json_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + +select json_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + +-- an empty object is not null and should not be stripped +select json_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); + -- json to tsvector select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::json); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 97bc2242a1333..57c11acddfee6 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -204,6 +204,7 @@ select '[{"b": "c"}, {"b": "cc"}]'::jsonb -> 'z'; select '{"a": "c", "b": null}'::jsonb -> 'b'; select '"foo"'::jsonb -> 1; select '"foo"'::jsonb -> 'z'; +select '[]'::jsonb -> -2147483648; select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> null::text; select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> null::int; @@ -216,6 +217,7 @@ select '[{"b": "c"}, {"b": "cc"}]'::jsonb ->> 'z'; select '{"a": "c", "b": null}'::jsonb ->> 'b'; select '"foo"'::jsonb ->> 1; select '"foo"'::jsonb ->> 'z'; +select '[]'::jsonb ->> -2147483648; -- equality and inequality SELECT '{"x":"y"}'::jsonb = '{"x":"y"}'::jsonb; @@ -1100,6 +1102,24 @@ select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]'); -- an empty object is not null and should not be stripped select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }'); +-- jsonb_strip_nulls (strip_in_arrays=true) + +select jsonb_strip_nulls(null, true); + +select jsonb_strip_nulls('1', true); + +select jsonb_strip_nulls('"a string"', true); + +select jsonb_strip_nulls('null', true); + +select jsonb_strip_nulls('[1,2,null,3,4]', true); + +select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}', true); + +select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]', true); + +-- an empty object is not null and should not be stripped +select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }', true); select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}'); select jsonb_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]'); @@ -1185,6 +1205,7 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{n}'); select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{b,-1}'); select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{d,1,0}'); +select jsonb_delete_path('{"a":[]}', '{"a",-2147483648}'); select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{n}'; select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1}'; @@ -1537,12 +1558,25 @@ select ts_headline('[]'::jsonb, tsquery('aaa & bbb')); -- casts select 'true'::jsonb::bool; +select 'null'::jsonb::bool; select '[]'::jsonb::bool; select '1.0'::jsonb::float; +select 'null'::jsonb::float; select '[1.0]'::jsonb::float; +select '1.0'::jsonb::float4; +select 'null'::jsonb::float4; +select '[1.0]'::jsonb::float4; +select '12345'::jsonb::int2; +select 'null'::jsonb::int2; +select '"hello"'::jsonb::int2; select '12345'::jsonb::int4; +select 'null'::jsonb::int4; select '"hello"'::jsonb::int4; +select '12345'::jsonb::int8; +select 'null'::jsonb::int8; +select '"hello"'::jsonb::int8; select '12345'::jsonb::numeric; +select 'null'::jsonb::numeric; select '{}'::jsonb::numeric; select '12345.05'::jsonb::numeric; select '12345.05'::jsonb::float4; diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql index 17f9d038c0aa9..3e8929a5269bc 100644 --- a/src/test/regress/sql/jsonb_jsonpath.sql +++ b/src/test/regress/sql/jsonb_jsonpath.sql @@ -598,10 +598,30 @@ select jsonb_path_query('1234', '$.string()'); select jsonb_path_query('true', '$.string()'); select jsonb_path_query('1234', '$.string().type()'); select jsonb_path_query('[2, true]', '$.string()'); -select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -select jsonb_path_query_tz('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -- should work select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string()'); select jsonb_path_query_array('[1.23, "yes", false]', '$[*].string().type()'); +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); +select jsonb_path_query_tz('"2023-08-15 12:34:56 +5:30"', '$.timestamp().string()'); -- should work +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp_tz().string()'); +select jsonb_path_query_tz('"2023-08-15 12:34:56"', '$.timestamp_tz().string()'); -- should work +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp_tz().string()'); +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()'); +select jsonb_path_query('"12:34:56 +5:30"', '$.time_tz().string()'); +-- this timetz usage will absorb the UTC offset of the current timezone setting +begin; +set local timezone = 'UTC-10'; +select jsonb_path_query_tz('"12:34:56"', '$.time_tz().string()'); +rollback; +select jsonb_path_query('"12:34:56"', '$.time().string()'); +select jsonb_path_query('"2023-08-15"', '$.date().string()'); + +-- .string() does not react to timezone or datestyle +begin; +set local timezone = 'UTC'; +set local datestyle = 'German'; +select jsonb_path_query('"2023-08-15 12:34:56 +5:30"', '$.timestamp_tz().string()'); +select jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp().string()'); +rollback; -- Test .time() select jsonb_path_query('null', '$.time()'); diff --git a/src/test/regress/sql/limit.sql b/src/test/regress/sql/limit.sql index 6f0cda9870155..603910fe6d11c 100644 --- a/src/test/regress/sql/limit.sql +++ b/src/test/regress/sql/limit.sql @@ -196,6 +196,9 @@ CREATE VIEW limit_thousand_v_3 AS SELECT thousand FROM onek WHERE thousand < 995 ORDER BY thousand FETCH FIRST (NULL+1) ROWS WITH TIES; \d+ limit_thousand_v_3 CREATE VIEW limit_thousand_v_4 AS SELECT thousand FROM onek WHERE thousand < 995 - ORDER BY thousand FETCH FIRST NULL ROWS ONLY; + ORDER BY thousand FETCH FIRST (5::bigint) ROWS WITH TIES; \d+ limit_thousand_v_4 +CREATE VIEW limit_thousand_v_5 AS SELECT thousand FROM onek WHERE thousand < 995 + ORDER BY thousand FETCH FIRST NULL ROWS ONLY; +\d+ limit_thousand_v_5 -- leave these views diff --git a/src/test/regress/sql/maintain_every.sql b/src/test/regress/sql/maintain_every.sql new file mode 100644 index 0000000000000..263e97272d596 --- /dev/null +++ b/src/test/regress/sql/maintain_every.sql @@ -0,0 +1,26 @@ +-- Test maintenance commands that visit every eligible relation. Run as a +-- non-superuser, to skip other users' tables. + +CREATE ROLE regress_maintain; +SET ROLE regress_maintain; + +-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f +-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an +-- empty index. +CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts" +CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS; +CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent); +CREATE INDEX ON past_inh_db_parent ((1)); +ANALYZE past_inh_db_parent; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; +DROP TABLE past_inh_db_child; +SET client_min_messages = error; -- hide WARNINGs for other users' tables +ANALYZE; +RESET client_min_messages; +SELECT reltuples, relhassubclass + FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass; +DROP TABLE past_inh_db_parent, past_inh_db_other; + +RESET ROLE; +DROP ROLE regress_maintain; diff --git a/src/test/regress/sql/matview.sql b/src/test/regress/sql/matview.sql index b74ee305e0f6f..6704eeae2df84 100644 --- a/src/test/regress/sql/matview.sql +++ b/src/test/regress/sql/matview.sql @@ -274,13 +274,13 @@ GRANT ALL ON SCHEMA matview_schema TO public; SET SESSION AUTHORIZATION regress_matview_user; CREATE MATERIALIZED VIEW matview_schema.mv_withdata1 (a) AS SELECT generate_series(1, 10) WITH DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_schema.mv_withdata2 (a) AS SELECT generate_series(1, 10) WITH DATA; REFRESH MATERIALIZED VIEW matview_schema.mv_withdata2; CREATE MATERIALIZED VIEW matview_schema.mv_nodata1 (a) AS SELECT generate_series(1, 10) WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_schema.mv_nodata2 (a) AS SELECT generate_series(1, 10) WITH NO DATA; REFRESH MATERIALIZED VIEW matview_schema.mv_nodata2; @@ -301,16 +301,16 @@ CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- error CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0; -- error -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0; -- ok -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- error -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS SELECT 1 / 0 WITH NO DATA; -- ok DROP MATERIALIZED VIEW matview_ine_tab; diff --git a/src/test/regress/sql/memoize.sql b/src/test/regress/sql/memoize.sql index 059bec5f4f73e..c0d47fa875ad9 100644 --- a/src/test/regress/sql/memoize.sql +++ b/src/test/regress/sql/memoize.sql @@ -11,7 +11,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', query) loop if hide_hitmiss = true then @@ -23,8 +23,9 @@ begin ln := regexp_replace(ln, 'Evictions: 0', 'Evictions: Zero'); ln := regexp_replace(ln, 'Evictions: \d+', 'Evictions: N'); ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N'); - ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N'); - ln := regexp_replace(ln, 'loops=\d+', 'loops=N'); + ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N'); + ln := regexp_replace(ln, 'loops=\d+', 'loops=N'); + ln := regexp_replace(ln, 'Index Searches: \d+', 'Index Searches: N'); return next ln; end loop; end; @@ -85,17 +86,6 @@ SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN LATERAL (SELECT t1.two+1 AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE WHERE s.c1 = s.c2 AND t1.unique1 < 1000; --- Try with LATERAL references within PlaceHolderVars -SELECT explain_memoize(' -SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN -LATERAL (SELECT t1.two+t2.two AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE -WHERE s.c1 = s.c2 AND t1.unique1 < 1000;', false); - --- And check we get the expected results. -SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN -LATERAL (SELECT t1.two+t2.two AS c1, t2.unique1 AS c2 FROM tenk1 t2) s ON TRUE -WHERE s.c1 = s.c2 AND t1.unique1 < 1000; - -- Ensure we do not omit the cache keys from PlaceHolderVars SELECT explain_memoize(' SELECT COUNT(*), AVG(t1.twenty) FROM tenk1 t1 LEFT JOIN diff --git a/src/test/regress/sql/merge.sql b/src/test/regress/sql/merge.sql index 92163ec9fe0d5..2660b19f2389f 100644 --- a/src/test/regress/sql/merge.sql +++ b/src/test/regress/sql/merge.sql @@ -235,7 +235,7 @@ WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED BY TARGET THEN INSERT VALUES (s.sid, s.delta) -RETURNING merge_action(), t.*; +RETURNING merge_action(), old, new, t.*; SELECT * FROM target ORDER BY tid; ROLLBACK; @@ -677,7 +677,7 @@ WHEN NOT MATCHED BY SOURCE AND tid = 1 THEN UPDATE SET balance = 0 WHEN NOT MATCHED BY SOURCE THEN DELETE -RETURNING merge_action(), t.*; +RETURNING merge_action(), old, new, t.*; SELECT * FROM target ORDER BY tid; ROLLBACK; @@ -930,7 +930,9 @@ WHEN MATCHED AND tid < 2 THEN DELETE RETURNING (SELECT abbrev FROM merge_actions WHERE action = merge_action()) AS action, - t.*, + old.tid AS old_tid, old.balance AS old_balance, + new.tid AS new_tid, new.balance AS new_balance, + (SELECT new.balance - old.balance AS delta_balance), t.*, CASE merge_action() WHEN 'INSERT' THEN 'Inserted '||t WHEN 'UPDATE' THEN 'Added '||delta||' to balance' @@ -956,7 +958,7 @@ WITH m AS ( INSERT (balance, tid) VALUES (balance + delta, sid) WHEN MATCHED AND tid < 2 THEN DELETE - RETURNING merge_action() AS action, t.*, + RETURNING merge_action() AS action, old AS old_data, new AS new_data, t.*, CASE merge_action() WHEN 'INSERT' THEN 'Inserted '||t WHEN 'UPDATE' THEN 'Added '||delta||' to balance' @@ -970,7 +972,7 @@ WITH m AS ( UPDATE SET last_change = description WHEN NOT MATCHED THEN INSERT VALUES (m.tid, description) - RETURNING action, merge_action() AS log_action, l.* + RETURNING m.*, merge_action() AS log_action, old AS old_log, new AS new_log, l.* ) SELECT * FROM m2; SELECT * FROM sq_target_merge_log ORDER BY tid; @@ -988,7 +990,7 @@ COPY ( INSERT (balance, tid) VALUES (balance + delta, sid) WHEN MATCHED AND tid < 2 THEN DELETE - RETURNING merge_action(), t.* + RETURNING merge_action(), old.*, new.* ) TO stdout; ROLLBACK; @@ -1072,7 +1074,7 @@ $$ DECLARE ln text; BEGIN FOR ln IN - EXECUTE 'explain (analyze, timing off, summary off, costs off) ' || + EXECUTE 'explain (analyze, timing off, summary off, costs off, buffers off) ' || query LOOP ln := regexp_replace(ln, '(Memory( Usage)?|Buckets|Batches): \S*', '\1: xxx', 'g'); @@ -1265,10 +1267,23 @@ MERGE INTO pa_target t ON t.tid = s.sid AND t.tid = 1 WHEN MATCHED THEN UPDATE SET tid = tid + 1, balance = balance + delta, val = val || ' updated by merge' - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; SELECT * FROM pa_target ORDER BY tid; ROLLBACK; +-- bug #18871: ExecInitPartitionInfo()'s handling of DO NOTHING actions +BEGIN; +TRUNCATE pa_target; +MERGE INTO pa_target t + USING (VALUES (10, 100)) AS s(sid, delta) + ON t.tid = s.sid + WHEN NOT MATCHED THEN + INSERT VALUES (1, 10, 'inserted by merge') + WHEN MATCHED THEN + DO NOTHING; +SELECT * FROM pa_target ORDER BY tid, val; +ROLLBACK; + DROP TABLE pa_target CASCADE; -- The target table is partitioned in the same way, but this time by attaching @@ -1456,7 +1471,7 @@ MERGE INTO pa_target t UPDATE SET balance = balance + delta, val = val || ' updated by merge' WHEN NOT MATCHED THEN INSERT VALUES (slogts::timestamp, sid, delta, 'inserted by merge') - RETURNING merge_action(), t.*; + RETURNING merge_action(), old, new, t.*; SELECT * FROM pa_target ORDER BY tid; ROLLBACK; @@ -1707,9 +1722,97 @@ WHEN MATCHED THEN DELETE; SELECT * FROM new_measurement ORDER BY city_id, logdate; +-- MERGE into inheritance root table +DROP TRIGGER insert_measurement_trigger ON measurement; +ALTER TABLE measurement ADD CONSTRAINT mcheck CHECK (city_id = 0) NO INHERIT; + +EXPLAIN (COSTS OFF) +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); + +BEGIN; +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; +ROLLBACK; + +ALTER TABLE measurement ENABLE ROW LEVEL SECURITY; +ALTER TABLE measurement FORCE ROW LEVEL SECURITY; +CREATE POLICY measurement_p ON measurement USING (peaktemp IS NOT NULL); + +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, NULL, 100); -- should fail + +MERGE INTO measurement m + USING (VALUES (1, '01-17-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 100); -- ok +SELECT * FROM ONLY measurement ORDER BY city_id, logdate; + +MERGE INTO measurement m + USING (VALUES (1, '01-18-2007'::date)) nm(city_id, logdate) ON + (m.city_id = nm.city_id and m.logdate=nm.logdate) +WHEN NOT MATCHED THEN INSERT + (city_id, logdate, peaktemp, unitsales) + VALUES (city_id - 1, logdate, 25, 200) +RETURNING merge_action(), m.*; + DROP TABLE measurement, new_measurement CASCADE; DROP FUNCTION measurement_insert_trigger(); +-- +-- test non-strict join clause +-- +CREATE TABLE src (a int, b text); +INSERT INTO src VALUES (1, 'src row'); + +CREATE TABLE tgt (a int, b text); +INSERT INTO tgt VALUES (NULL, 'tgt row'); + +MERGE INTO tgt USING src ON tgt.a IS NOT DISTINCT FROM src.a + WHEN MATCHED THEN UPDATE SET a = src.a, b = src.b + WHEN NOT MATCHED BY SOURCE THEN DELETE + RETURNING merge_action(), src.*, tgt.*; + +SELECT * FROM tgt; + +DROP TABLE src, tgt; + +-- +-- test for bug #18634 (wrong varnullingrels error) +-- +CREATE TABLE bug18634t (a int, b int, c text); +INSERT INTO bug18634t VALUES(1, 10, 'tgt1'), (2, 20, 'tgt2'); +CREATE VIEW bug18634v AS + SELECT * FROM bug18634t WHERE EXISTS (SELECT 1 FROM bug18634t); + +CREATE TABLE bug18634s (a int, b int, c text); +INSERT INTO bug18634s VALUES (1, 2, 'src1'); + +MERGE INTO bug18634v t USING bug18634s s ON s.a = t.a + WHEN MATCHED THEN UPDATE SET b = s.b + WHEN NOT MATCHED BY SOURCE THEN DELETE + RETURNING merge_action(), s.c, t.*; + +SELECT * FROM bug18634t; + +DROP TABLE bug18634t CASCADE; +DROP TABLE bug18634s; + -- prepare RESET SESSION AUTHORIZATION; diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql index e570783453cd0..23792c4132a10 100644 --- a/src/test/regress/sql/misc_functions.sql +++ b/src/test/regress/sql/misc_functions.sql @@ -24,7 +24,7 @@ BEGIN SET LOCAL jit = 0; FOR ln IN - EXECUTE format('explain (analyze %s, costs on, summary off, timing off) %s', + EXECUTE format('explain (analyze %s, costs on, summary off, timing off, buffers off) %s', analyze_str, query) LOOP IF hide_costs = true THEN @@ -163,6 +163,7 @@ select (w).size = :segsize as ok from (select pg_ls_waldir() w) ss where length((w).name) = 24 limit 1; select count(*) >= 0 as ok from pg_ls_archive_statusdir(); +select count(*) >= 0 as ok from pg_ls_summariesdir(); -- pg_read_file() select length(pg_read_file('postmaster.pid')) > 20; @@ -310,6 +311,44 @@ false, true, false, true); -- the support function. SELECT * FROM generate_series(TIMESTAMPTZ '2024-02-01', TIMESTAMPTZ '2024-03-01', INTERVAL '0 day') g(s); +-- +-- Test the SupportRequestRows support function for generate_series_numeric() +-- + +-- Ensure the row estimate matches the actual rows +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0) g(s);$$, +true, true, false, true); + +-- As above but with non-default step +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0, 2.0) g(s);$$, +true, true, false, true); + +-- Ensure the estimates match when step is decreasing +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 1.0, -1.0) g(s);$$, +true, true, false, true); + +-- Ensure an empty range estimates 1 row +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 1.0, 1.0) g(s);$$, +true, true, false, true); + +-- Ensure we get the default row estimate for error cases (infinity/NaN values +-- and zero step size) +SELECT explain_mask_costs($$ +SELECT * FROM generate_series('-infinity'::NUMERIC, 'infinity'::NUMERIC, 1.0) g(s);$$, +false, true, false, true); + +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(1.0, 25.0, 'NaN'::NUMERIC) g(s);$$, +false, true, false, true); + +SELECT explain_mask_costs($$ +SELECT * FROM generate_series(25.0, 2.0, 0.0) g(s);$$, +false, true, false, true); + -- Test functions for control data SELECT count(*) > 0 AS ok FROM pg_control_checkpoint(); SELECT count(*) > 0 AS ok FROM pg_control_init(); @@ -360,3 +399,18 @@ SELECT pg_column_toast_chunk_id(a) IS NULL, FROM test_chunk_id; DROP TABLE test_chunk_id; DROP FUNCTION explain_mask_costs(text, bool, bool, bool, bool); + +-- test stratnum translation support functions +SELECT gist_translate_cmptype_common(7); +SELECT gist_translate_cmptype_common(3); + + +-- relpath tests +CREATE FUNCTION test_relpath() + RETURNS void + AS :'regresslib' + LANGUAGE C; +SELECT test_relpath(); + +-- pg_replication_origin.roname limit +SELECT pg_replication_origin_create('regress_' || repeat('a', 505)); diff --git a/src/test/regress/sql/misc_sanity.sql b/src/test/regress/sql/misc_sanity.sql index cda760bd5ef99..e861614ea7184 100644 --- a/src/test/regress/sql/misc_sanity.sql +++ b/src/test/regress/sql/misc_sanity.sql @@ -38,11 +38,18 @@ WHERE refclassid = 0 OR refobjid = 0 OR -- Look for system tables with varlena columns but no toast table. All -- system tables with toastable columns should have toast tables, with -- the following exceptions: --- 1. pg_class, pg_attribute, and pg_index, due to fear of recursive --- dependencies as toast tables depend on them. +-- 1. pg_class and pg_attribute, due to fear of recursive dependencies as +-- toast tables depend on them. -- 2. pg_largeobject and pg_largeobject_metadata. Large object catalogs -- and toast tables are mutually exclusive and large object data is handled -- as user data by pg_upgrade, which would cause failures. +-- 3. pg_authid, since its toast table cannot be accessed when it would be +-- needed, i.e., during authentication before we've selected a database. +-- 4. pg_replication_origin, since we want to be able to access that catalog +-- without setting up a snapshot. To make that safe, it needs to not have a +-- toast table, since toasted data cannot be fetched without a snapshot. As of +-- this writing, its only varlena column is roname, which we limit to 512 bytes +-- to avoid needing out-of-line storage. SELECT relname, attname, atttypid::regtype FROM pg_class c JOIN pg_attribute a ON c.oid = attrelid diff --git a/src/test/regress/sql/numa.sql b/src/test/regress/sql/numa.sql new file mode 100644 index 0000000000000..324481c33b75d --- /dev/null +++ b/src/test/regress/sql/numa.sql @@ -0,0 +1,10 @@ +SELECT NOT(pg_numa_available()) AS skip_test \gset +\if :skip_test +SELECT COUNT(*) = 0 AS ok FROM pg_shmem_allocations_numa; +\quit +\endif + +-- switch to superuser +\c - + +SELECT COUNT(*) >= 0 AS ok FROM pg_shmem_allocations_numa; diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql index c86395209ab0c..b98ae27df5691 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -996,6 +996,7 @@ SELECT to_char(val, E'99999 "text" 9999 "9999" 999 "\\"text between quote marks\ SELECT to_char(val, '999999SG9999999999') FROM num_data; SELECT to_char(val, 'FM9999999999999999.999999999999999') FROM num_data; SELECT to_char(val, '9.999EEEE') FROM num_data; +SELECT to_char(val, 'FMRN') FROM num_data; WITH v(val) AS (VALUES('0'::numeric),('-4.2'),('4.2e9'),('1.2e-5'),('inf'),('-inf'),('nan')) @@ -1033,6 +1034,19 @@ SELECT to_char('100'::numeric, 'FM999.'); SELECT to_char('100'::numeric, 'FM999'); SELECT to_char('12345678901'::float8, 'FM9999999999D9999900000000000000000'); +SELECT to_char('100'::numeric, 'rn'); +SELECT to_char('1234'::numeric, 'rn'); +SELECT to_char('1235'::float4, 'rn'); +SELECT to_char('1236'::float8, 'rn'); +SELECT to_char('1237'::float8, 'fmrn'); +SELECT to_char('100e9'::numeric, 'RN'); +SELECT to_char('100e9'::float4, 'RN'); +SELECT to_char('100e9'::float8, 'RN'); + +SELECT to_char(1234.56::numeric, '99999V99'); +SELECT to_char(1234.56::float4, '99999V99'); +SELECT to_char(1234.56::float8, '99999V99'); + -- Check parsing of literal text in a format string SELECT to_char('100'::numeric, 'foo999'); SELECT to_char('100'::numeric, 'f\oo999'); @@ -1070,6 +1084,40 @@ SELECT to_number('$1,234.56','L99,999.99'); SELECT to_number('1234.56','L99,999.99'); SELECT to_number('1,234.56','L99,999.99'); SELECT to_number('42nd', '99th'); +SELECT to_number('123456', '99999V99'); + +-- Test for correct conversion between numbers and Roman numerals +WITH rows AS + (SELECT i, to_char(i, 'RN') AS roman FROM generate_series(1, 3999) AS i) +SELECT + bool_and(to_number(roman, 'RN') = i) as valid +FROM rows; + +-- Some additional tests for RN input +SELECT to_number('CvIiI', 'rn'); +SELECT to_number('MMXX ', 'RN'); +SELECT to_number(' XIV', ' RN'); +SELECT to_number(' XIV ', ' RN'); +SELECT to_number('M CC', 'RN'); +-- error cases +SELECT to_number('viv', 'RN'); +SELECT to_number('DCCCD', 'RN'); +SELECT to_number('XIXL', 'RN'); +SELECT to_number('MCCM', 'RN'); +SELECT to_number('MMMM', 'RN'); +SELECT to_number('VV', 'RN'); +SELECT to_number('IL', 'RN'); +SELECT to_number('VIX', 'RN'); +SELECT to_number('LXC', 'RN'); +SELECT to_number('DCM', 'RN'); +SELECT to_number('MMMDCM', 'RN'); +SELECT to_number('CLXC', 'RN'); +SELECT to_number('CM', 'MIRN'); +SELECT to_number('CM', 'RNRN'); +SELECT to_number('qiv', 'RN'); +SELECT to_number('', 'RN'); +SELECT to_number(' ', 'RN'); + RESET lc_numeric; -- @@ -1210,6 +1258,9 @@ select 12345678901234567890 % 123; select 12345678901234567890 / 123; select div(12345678901234567890, 123); select div(12345678901234567890, 123) * 123 + 12345678901234567890 % 123; +select 8e9000 - div(8e18000 - 1, 9e9000 - 1) * 9; +select 7328412092 - div(53705623790171816464 - 1, 7328412092); +select div(539913372912345678, 539913372912345678); -- -- Test some corner cases for square root diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 2fe7b6dcc4986..2fb3a85287816 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -399,6 +399,13 @@ FROM pg_proc p1 JOIN pg_namespace pn WHERE nspname = 'pg_catalog' AND proleakproof ORDER BY 1; +-- Check that functions without argument are not marked as leakproof. +SELECT p1.oid::regprocedure +FROM pg_proc p1 JOIN pg_namespace pn + ON pronamespace = pn.oid +WHERE nspname = 'pg_catalog' AND proleakproof AND pronargs = 0 +ORDER BY 1; + -- restore normal output mode \a\t diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql index 128ce8376e609..30f15ee9acb5a 100644 --- a/src/test/regress/sql/partition_join.sql +++ b/src/test/regress/sql/partition_join.sql @@ -34,6 +34,11 @@ EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; +-- inner join with partially-redundant join clauses +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDER BY t1.a, t2.b; + -- left outer join, 3-way EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1 t1 @@ -138,6 +143,10 @@ SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) RESET enable_partitionwise_aggregate; RESET enable_hashjoin; +-- bug in freeing the SpecialJoinInfo of a child-join +EXPLAIN (COSTS OFF) +SELECT * FROM prt1 t1 JOIN prt1 t2 ON t1.a = t2.a WHERE t1.a IN (SELECT a FROM prt1 t3); + -- -- partitioned by expression -- @@ -386,6 +395,11 @@ EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b; +-- inner join with partially-redundant join clauses +EXPLAIN (COSTS OFF) +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDER BY t1.a, t2.b; +SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDER BY t1.a, t2.b; + -- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFT JOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0 ORDER BY t1.a, t2.b; @@ -1210,6 +1224,30 @@ SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id AS EXPLAIN (COSTS OFF) SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DESC LIMIT 10; +EXPLAIN (COSTS OFF) -- Should use NestLoop with parameterised inner scan +SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) +ORDER BY x.id DESC LIMIT 2; + +-- +-- Test Append's fractional paths +-- + +CREATE INDEX pht1_c_idx ON pht1(c); +-- SeqScan might be the best choice if we need one single tuple +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 1; +-- Increase number of tuples requested and an IndexScan will be chosen +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 100; +-- If almost all the data should be fetched - prefer SeqScan +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 1000; + +SET max_parallel_workers_per_gather = 1; +SET debug_parallel_query = on; +-- Partial paths should also be smart enough to employ limits +EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT 100; +RESET debug_parallel_query; + +-- Remove indexes from the partitioned table and its partitions +DROP INDEX pht1_c_idx CASCADE; -- cleanup DROP TABLE fract_t; diff --git a/src/test/regress/sql/partition_merge.sql b/src/test/regress/sql/partition_merge.sql deleted file mode 100644 index bede819af942e..0000000000000 --- a/src/test/regress/sql/partition_merge.sql +++ /dev/null @@ -1,609 +0,0 @@ --- --- PARTITIONS_MERGE --- Tests for "ALTER TABLE ... MERGE PARTITIONS ..." command --- - -CREATE SCHEMA partitions_merge_schema; -CREATE SCHEMA partitions_merge_schema2; -SET search_path = partitions_merge_schema, public; - --- --- BY RANGE partitioning --- - --- --- Test for error codes --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_dec2021 PARTITION OF sales_range FOR VALUES FROM ('2021-12-01') TO ('2021-12-31'); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); - -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr_1 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-04-15'); -CREATE TABLE sales_apr_2 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-15') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); - -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - --- ERROR: partition with name "sales_feb2022" is already used -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_feb2022) INTO sales_feb_mar_apr2022; --- ERROR: "sales_apr2022" is not a table -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO sales_feb_mar_apr2022; --- ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_jan2022" --- (space between sections sales_jan2022 and sales_mar2022) -ALTER TABLE sales_range MERGE PARTITIONS (sales_jan2022, sales_mar2022) INTO sales_jan_mar2022; --- ERROR: lower bound of partition "sales_jan2022" conflicts with upper bound of previous partition "sales_dec2021" --- (space between sections sales_dec2021 and sales_jan2022) -ALTER TABLE sales_range MERGE PARTITIONS (sales_dec2021, sales_jan2022, sales_feb2022) INTO sales_dec_jan_feb2022; - --- NO ERROR: test for custom partitions order, source partitions not in the search_path -SET search_path = partitions_merge_schema2, public; -ALTER TABLE partitions_merge_schema.sales_range MERGE PARTITIONS ( - partitions_merge_schema.sales_feb2022, - partitions_merge_schema.sales_mar2022, - partitions_merge_schema.sales_jan2022) INTO sales_jan_feb_mar2022; -SET search_path = partitions_merge_schema, public; - -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -DROP TABLE sales_range; - --- --- Add rows into partitioned table, then merge partitions --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT pg_catalog.pg_get_partkeydef('sales_range'::regclass); - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - --- check schema-qualified name of the new partition -ALTER TABLE sales_range MERGE PARTITIONS (sales_feb2022, sales_mar2022, sales_apr2022) INTO partitions_merge_schema2.sales_feb_mar_apr2022; - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -SELECT * FROM pg_indexes WHERE tablename = 'sales_feb_mar_apr2022' and schemaname = 'partitions_merge_schema2'; - -SELECT * FROM sales_range; -SELECT * FROM sales_jan2022; -SELECT * FROM partitions_merge_schema2.sales_feb_mar_apr2022; -SELECT * FROM sales_others; - --- Use indexscan for testing indexes -SET enable_seqscan = OFF; - -SELECT * FROM partitions_merge_schema2.sales_feb_mar_apr2022 where sales_date > '2022-01-01'; - -RESET enable_seqscan; - -DROP TABLE sales_range; - --- --- Merge some partitions into DEFAULT partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); -CREATE TABLE sales_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - --- Merge partitions (include DEFAULT partition) into partition with the same --- name -ALTER TABLE sales_range MERGE PARTITIONS - (sales_jan2022, sales_mar2022, partitions_merge_schema.sales_others) INTO sales_others; - -select * from sales_others; - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_range'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -DROP TABLE sales_range; - --- --- Test for: --- * composite partition key; --- * GENERATED column; --- * column with DEFAULT value. --- -CREATE TABLE sales_date (salesperson_name VARCHAR(30), sales_year INT, sales_month INT, sales_day INT, - sales_date VARCHAR(10) GENERATED ALWAYS AS - (LPAD(sales_year::text, 4, '0') || '.' || LPAD(sales_month::text, 2, '0') || '.' || LPAD(sales_day::text, 2, '0')) STORED, - sales_department VARCHAR(30) DEFAULT 'Sales department') - PARTITION BY RANGE (sales_year, sales_month, sales_day); - -CREATE TABLE sales_dec2022 PARTITION OF sales_date FOR VALUES FROM (2021, 12, 1) TO (2022, 1, 1); -CREATE TABLE sales_jan2022 PARTITION OF sales_date FOR VALUES FROM (2022, 1, 1) TO (2022, 2, 1); -CREATE TABLE sales_feb2022 PARTITION OF sales_date FOR VALUES FROM (2022, 2, 1) TO (2022, 3, 1); -CREATE TABLE sales_other PARTITION OF sales_date FOR VALUES FROM (2022, 3, 1) TO (MAXVALUE, MAXVALUE, MAXVALUE); - -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2021, 12, 7); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2021, 12, 8); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 1, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 2, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 1, 2); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 2, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 3, 3); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 3, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 5, 1); - -SELECT * FROM sales_date; -SELECT * FROM sales_dec2022; -SELECT * FROM sales_jan2022; -SELECT * FROM sales_feb2022; -SELECT * FROM sales_other; - -ALTER TABLE sales_date MERGE PARTITIONS (sales_jan2022, sales_feb2022) INTO sales_jan_feb2022; - -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 1, 10); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 2, 10); - -SELECT * FROM sales_date; -SELECT * FROM sales_dec2022; -SELECT * FROM sales_jan_feb2022; -SELECT * FROM sales_other; - -DROP TABLE sales_date; - --- --- Test: merge partitions of partitioned table with triggers --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); - -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_20 PARTITION OF salespeople FOR VALUES FROM (10) TO (20); -CREATE TABLE salespeople20_30 PARTITION OF salespeople FOR VALUES FROM (20) TO (30); -CREATE TABLE salespeople30_40 PARTITION OF salespeople FOR VALUES FROM (30) TO (40); - -INSERT INTO salespeople VALUES (1, 'Poirot'); - -CREATE OR REPLACE FUNCTION after_insert_row_trigger() RETURNS trigger LANGUAGE 'plpgsql' AS $BODY$ -BEGIN - RAISE NOTICE 'trigger(%) called: action = %, when = %, level = %', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END; -$BODY$; - -CREATE TRIGGER salespeople_after_insert_statement_trigger - AFTER INSERT - ON salespeople - FOR EACH STATEMENT - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); - -CREATE TRIGGER salespeople_after_insert_row_trigger - AFTER INSERT - ON salespeople - FOR EACH ROW - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); - --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (10, 'May'); --- 1 trigger should fire here (row): -INSERT INTO salespeople10_20 VALUES (19, 'Ivanov'); - -ALTER TABLE salespeople MERGE PARTITIONS (salespeople10_20, salespeople20_30, salespeople30_40) INTO salespeople10_40; - --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (20, 'Smirnoff'); --- 1 trigger should fire here (row): -INSERT INTO salespeople10_40 VALUES (30, 'Ford'); - -SELECT * FROM salespeople01_10; -SELECT * FROM salespeople10_40; - -DROP TABLE salespeople; -DROP FUNCTION after_insert_row_trigger(); - --- --- Test: merge partitions with deleted columns --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); - -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); --- Create partitions with some deleted columns: -CREATE TABLE salespeople10_20(d1 VARCHAR(30), salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)); -CREATE TABLE salespeople20_30(salesperson_id INT PRIMARY KEY, d2 INT, salesperson_name VARCHAR(30)); -CREATE TABLE salespeople30_40(salesperson_id INT PRIMARY KEY, d3 DATE, salesperson_name VARCHAR(30)); - -INSERT INTO salespeople10_20 VALUES ('dummy value 1', 19, 'Ivanov'); -INSERT INTO salespeople20_30 VALUES (20, 101, 'Smirnoff'); -INSERT INTO salespeople30_40 VALUES (31, now(), 'Popov'); - -ALTER TABLE salespeople10_20 DROP COLUMN d1; -ALTER TABLE salespeople20_30 DROP COLUMN d2; -ALTER TABLE salespeople30_40 DROP COLUMN d3; - -ALTER TABLE salespeople ATTACH PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20); -ALTER TABLE salespeople ATTACH PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30); -ALTER TABLE salespeople ATTACH PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40); - -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (30, 'Ford'); - -ALTER TABLE salespeople MERGE PARTITIONS (salespeople10_20, salespeople20_30, salespeople30_40) INTO salespeople10_40; - -select * from salespeople; -select * from salespeople01_10; -select * from salespeople10_40; - -DROP TABLE salespeople; - --- --- Test: merge sub-partitions --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); - -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr2022_01_10 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-04-10'); -CREATE TABLE sales_apr2022_10_20 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-10') TO ('2022-04-20'); -CREATE TABLE sales_apr2022_20_30 PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-20') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); - -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT * FROM sales_range; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_apr2022_01_10; -SELECT * FROM sales_apr2022_10_20; -SELECT * FROM sales_apr2022_20_30; - -ALTER TABLE sales_apr2022 MERGE PARTITIONS (sales_apr2022_01_10, sales_apr2022_10_20, sales_apr2022_20_30) INTO sales_apr_all; - -SELECT * FROM sales_range; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_apr_all; - -DROP TABLE sales_range; - --- --- BY LIST partitioning --- - --- --- Test: specific errors for BY LIST partitioning --- -CREATE TABLE sales_list -(salesperson_id INT GENERATED ALWAYS AS IDENTITY, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_west PARTITION OF sales_list FOR VALUES IN ('Lisbon', 'New York', 'Madrid'); -CREATE TABLE sales_east PARTITION OF sales_list FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'); -CREATE TABLE sales_central PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; - - -CREATE TABLE sales_list2 (LIKE sales_list) PARTITION BY LIST (sales_state); -CREATE TABLE sales_nord2 PARTITION OF sales_list2 FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_others2 PARTITION OF sales_list2 DEFAULT; - - -CREATE TABLE sales_external (LIKE sales_list); -CREATE TABLE sales_external2 (vch VARCHAR(5)); - --- ERROR: "sales_external" is not a partition -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external) INTO sales_all; --- ERROR: "sales_external2" is not a partition -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_external2) INTO sales_all; --- ERROR: relation "sales_nord2" is not a partition of relation "sales_list" -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_nord2, sales_east) INTO sales_all; - -DROP TABLE sales_external2; -DROP TABLE sales_external; -DROP TABLE sales_list2; -DROP TABLE sales_list; - --- --- Test: BY LIST partitioning, MERGE PARTITIONS with data --- -CREATE TABLE sales_list -(salesperson_id INT GENERATED ALWAYS AS IDENTITY, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); - -CREATE INDEX sales_list_salesperson_name_idx ON sales_list USING btree (salesperson_name); -CREATE INDEX sales_list_sales_state_idx ON sales_list USING btree (sales_state); - -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_west PARTITION OF sales_list FOR VALUES IN ('Lisbon', 'New York', 'Madrid'); -CREATE TABLE sales_east PARTITION OF sales_list FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'); -CREATE TABLE sales_central PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; - -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Trump', 'Bejing', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smirnoff', 'New York', 500, '2022-03-03'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ford', 'St. Petersburg', 2000, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ivanov', 'Warsaw', 750, '2022-03-04'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Deev', 'Lisbon', 250, '2022-03-07'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Poirot', 'Berlin', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Helsinki', 1200, '2022-03-06'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Li', 'Vladivostok', 1150, '2022-03-09'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Helsinki', 1200, '2022-03-11'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Halder', 'Oslo', 800, '2022-03-02'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Muller', 'Madrid', 650, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smith', 'Kyiv', 350, '2022-03-10'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Gandi', 'Warsaw', 150, '2022-03-08'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Plato', 'Lisbon', 950, '2022-03-05'); - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_list'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -ALTER TABLE sales_list MERGE PARTITIONS (sales_west, sales_east, sales_central) INTO sales_all; - --- show partitions with conditions: -SELECT c.oid::pg_catalog.regclass, c.relkind, inhdetachpending, pg_catalog.pg_get_expr(c.relpartbound, c.oid) - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 'sales_list'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -SELECT * FROM sales_list; -SELECT * FROM sales_nord; -SELECT * FROM sales_all; - --- Use indexscan for testing indexes after merging partitions -SET enable_seqscan = OFF; - -SELECT * FROM sales_all WHERE sales_state = 'Warsaw'; -SELECT * FROM sales_list WHERE sales_state = 'Warsaw'; -SELECT * FROM sales_list WHERE salesperson_name = 'Ivanov'; - -RESET enable_seqscan; - -DROP TABLE sales_list; - --- --- Try to MERGE partitions of another table. --- -CREATE TABLE t1 (i int, a int, b int, c int) PARTITION BY RANGE (a, b); -CREATE TABLE t1p1 PARTITION OF t1 FOR VALUES FROM (1, 1) TO (1, 2); -CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t); -CREATE TABLE t2pa PARTITION OF t2 FOR VALUES FROM ('A') TO ('C'); -CREATE TABLE t3 (i int, t text); - --- ERROR: relation "t1p1" is not a partition of relation "t2" -ALTER TABLE t2 MERGE PARTITIONS (t1p1, t2pa) INTO t2p; --- ERROR: "t3" is not a partition -ALTER TABLE t2 MERGE PARTITIONS (t2pa, t3) INTO t2p; - -DROP TABLE t3; -DROP TABLE t2; -DROP TABLE t1; - --- --- Try to MERGE partitions of temporary table. --- -CREATE TEMP TABLE t (i int) PARTITION BY RANGE (i); -CREATE TEMP TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TEMP TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); - -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; - --- Partition should be temporary. -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -DROP TABLE t; - --- --- Check the partition index name if the partition name is the same as one --- of the merged partitions. --- -CREATE TABLE t (i int, PRIMARY KEY(i)) PARTITION BY RANGE (i); - -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); - -CREATE INDEX tidx ON t(i); -ALTER TABLE t MERGE PARTITIONS (tp_1_2, tp_0_1) INTO tp_1_2; - --- Indexname values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'. --- Not-null constraint name should be 'tp_1_2_i_not_null'. -\d+ tp_1_2 - -DROP TABLE t; - --- --- Try mixing permanent and temporary partitions. --- -SET search_path = partitions_merge_schema, pg_temp, public; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); - -SELECT c.oid::pg_catalog.regclass, c.relpersistence FROM pg_catalog.pg_class c WHERE c.oid = 't'::regclass; -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -SET search_path = pg_temp, partitions_merge_schema, public; - --- Can't merge persistent partitions into a temporary partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; - -SET search_path = partitions_merge_schema, public; - --- Can't merge persistent partitions into a temporary partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO pg_temp.tp_0_2; -DROP TABLE t; - -SET search_path = pg_temp, partitions_merge_schema, public; - -BEGIN; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); - -SELECT c.oid::pg_catalog.regclass, c.relpersistence FROM pg_catalog.pg_class c WHERE c.oid = 't'::regclass; -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -SET search_path = partitions_merge_schema, pg_temp, public; - --- Can't merge temporary partitions into a persistent partition -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -ROLLBACK; - --- Check the new partition inherits parent's tablespace -SET search_path = partitions_merge_schema, public; -CREATE TABLE t (i int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) - PARTITION BY RANGE (i) TABLESPACE regress_tblspace; -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -SELECT tablename, tablespace FROM pg_tables - WHERE tablename IN ('t', 'tp_0_2') AND schemaname = 'partitions_merge_schema' - ORDER BY tablename, tablespace; -SELECT tablename, indexname, tablespace FROM pg_indexes - WHERE tablename IN ('t', 'tp_0_2') AND schemaname = 'partitions_merge_schema' - ORDER BY tablename, indexname, tablespace; -DROP TABLE t; - --- Check the new partition inherits parent's table access method -SET search_path = partitions_merge_schema, public; -CREATE ACCESS METHOD partitions_merge_heap TYPE TABLE HANDLER heap_tableam_handler; -CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partitions_merge_heap; -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -SELECT c.relname, a.amname -FROM pg_class c JOIN pg_am a ON c.relam = a.oid -WHERE c.oid IN ('t'::regclass, 'tp_0_2'::regclass) -ORDER BY c.relname; -DROP TABLE t; -DROP ACCESS METHOD partitions_merge_heap; - --- Test permission checks. The user needs to own the parent table and all --- the merging partitions to do the merge. -CREATE ROLE regress_partition_merge_alice; -CREATE ROLE regress_partition_merge_bob; -GRANT ALL ON SCHEMA partitions_merge_schema TO regress_partition_merge_alice; -GRANT ALL ON SCHEMA partitions_merge_schema TO regress_partition_merge_bob; - -SET SESSION AUTHORIZATION regress_partition_merge_alice; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); -CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); - -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -RESET SESSION AUTHORIZATION; - -ALTER TABLE t OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -RESET SESSION AUTHORIZATION; - -ALTER TABLE tp_0_1 OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -RESET SESSION AUTHORIZATION; - -ALTER TABLE tp_1_2 OWNER TO regress_partition_merge_bob; -SET SESSION AUTHORIZATION regress_partition_merge_bob; -ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; -RESET SESSION AUTHORIZATION; - -DROP TABLE t; -REVOKE ALL ON SCHEMA partitions_merge_schema FROM regress_partition_merge_alice; -REVOKE ALL ON SCHEMA partitions_merge_schema FROM regress_partition_merge_bob; -DROP ROLE regress_partition_merge_alice; -DROP ROLE regress_partition_merge_bob; - -RESET search_path; - --- -DROP SCHEMA partitions_merge_schema; -DROP SCHEMA partitions_merge_schema2; diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index 442428d937cb6..d93c0c03babad 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -12,7 +12,7 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', query) loop ln := regexp_replace(ln, 'Maximum Storage: \d+', 'Maximum Storage: N'); @@ -388,6 +388,21 @@ explain (costs off) select * from rparted_by_int2 where a > 100_000_000_000_000; drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, iboolpart, boolrangep, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2; +-- check that AlternativeSubPlan within a pruning expression gets cleaned up + +create table asptab (id int primary key) partition by range (id); +create table asptab0 partition of asptab for values from (0) to (1); +create table asptab1 partition of asptab for values from (1) to (2); + +explain (costs off) +select * from + (select exists (select 1 from int4_tbl tinner where f1 = touter.f1) as b + from int4_tbl touter) ss, + asptab +where asptab.id > ss.b::int; + +drop table asptab; + -- -- Test Partition pruning for HASH partitioning -- @@ -465,8 +480,8 @@ set enable_indexonlyscan = off; prepare ab_q1 (int, int, int) as select * from ab where a between $1 and $2 and b <= $3; -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2, 3); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (1, 2, 3); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 2, 3); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (1, 2, 3); deallocate ab_q1; @@ -474,21 +489,21 @@ deallocate ab_q1; prepare ab_q1 (int, int) as select a from ab where a between $1 and $2 and b < 3; -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 2); -explain (analyze, costs off, summary off, timing off) execute ab_q1 (2, 4); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 2); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q1 (2, 4); -- Ensure a mix of PARAM_EXTERN and PARAM_EXEC Params work together at -- different levels of partitioning. prepare ab_q2 (int, int) as select a from ab where a between $1 and $2 and b < (select 3); -explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q2 (2, 2); -- As above, but swap the PARAM_EXEC Param to the first partition level prepare ab_q3 (int, int) as select a from ab where b between $1 and $2 and a < (select 3); -explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q3 (2, 2); -- -- Test runtime pruning with hash partitioned tables @@ -538,13 +553,13 @@ begin; create function list_part_fn(int) returns int as $$ begin return $1; end;$$ language plpgsql stable; -- Ensure pruning works using a stable function containing no Vars -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1); +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(1); -- Ensure pruning does not take place when the function has a Var parameter -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(a); +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(a); -- Ensure pruning does not take place when the expression contains a Var. -explain (analyze, costs off, summary off, timing off) select * from list_part where a = list_part_fn(1) + a; +explain (analyze, costs off, summary off, timing off, buffers off) select * from list_part where a = list_part_fn(1) + a; rollback; @@ -567,12 +582,16 @@ declare ln text; begin for ln in - execute format('explain (analyze, costs off, summary off, timing off) %s', + execute format('explain (analyze, costs off, summary off, timing off, buffers off) %s', $1) loop ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N'); - ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N'); + ln := regexp_replace(ln, 'actual rows=\d+(?:\.\d+)? loops=\d+', 'actual rows=N loops=N'); ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N'); + perform regexp_matches(ln, 'Index Searches: \d+'); + if found then + continue; + end if; return next ln; end loop; end; @@ -650,15 +669,15 @@ reset min_parallel_table_scan_size; reset max_parallel_workers_per_gather; -- Test run-time partition pruning with an initplan -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1 from lprt_a); -- Test run-time partition pruning with UNION ALL parents -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from (select * from ab where a = 1 union all select * from ab) ab where b = (select 1); -- A case containing a UNION ALL with a non-partitioned child. -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from (select * from ab where a = 1 union all (values(10,5)) union all select * from ab) ab where b = (select 1); -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning. @@ -678,7 +697,7 @@ union all ) ab where a = $1 and b = (select -10); -- Ensure the xy_1 subplan is not pruned. -explain (analyze, costs off, summary off, timing off) execute ab_q6(1); +explain (analyze, costs off, summary off, timing off, buffers off) execute ab_q6(1); -- Ensure we see just the xy_1 row. execute ab_q6(100); @@ -733,10 +752,10 @@ insert into tprt values (10), (20), (501), (502), (505), (1001), (4500); set enable_hashjoin = off; set enable_mergejoin = off; -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 > tprt.col1; -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -749,10 +768,10 @@ order by tbl1.col1, tprt.col1; -- Multiple partitions insert into tbl1 values (1001), (1010), (1011); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1; -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -766,7 +785,7 @@ order by tbl1.col1, tprt.col1; -- Last partition delete from tbl1; insert into tbl1 values (4400); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 < tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -776,7 +795,7 @@ order by tbl1.col1, tprt.col1; -- No matching partition delete from tbl1; insert into tbl1 values (10000); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from tbl1 join tprt on tbl1.col1 = tprt.col1; select tbl1.col1, tprt.col1 from tbl1 @@ -799,7 +818,7 @@ prepare part_abc_q1 (int, int, int) as select * from part_abc where a = $1 and b = $2 and c = $3; -- Single partition should be scanned. -explain (analyze, costs off, summary off, timing off) execute part_abc_q1 (1, 2, 3); +explain (analyze, costs off, summary off, timing off, buffers off) execute part_abc_q1 (1, 2, 3); deallocate part_abc_q1; @@ -819,12 +838,12 @@ select * from listp where b = 1; -- which match the given parameter. prepare q1 (int,int) as select * from listp where b in ($1,$2); -explain (analyze, costs off, summary off, timing off) execute q1 (1,1); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,1); -explain (analyze, costs off, summary off, timing off) execute q1 (2,2); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (2,2); -- Try with no matching partitions. -explain (analyze, costs off, summary off, timing off) execute q1 (0,0); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (0,0); deallocate q1; @@ -832,13 +851,13 @@ deallocate q1; prepare q1 (int,int,int,int) as select * from listp where b in($1,$2) and $3 <> b and $4 <> b; -- Both partitions allowed by IN clause, but one disallowed by <> clause -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,0); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,2,2,0); -- Both partitions allowed by IN clause, then both excluded again by <> clauses. -explain (analyze, costs off, summary off, timing off) execute q1 (1,2,2,1); +explain (analyze, costs off, summary off, timing off, buffers off) execute q1 (1,2,2,1); -- Ensure Params that evaluate to NULL properly prune away all partitions -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from listp where a = (select null::int); drop table listp; @@ -855,30 +874,30 @@ create table stable_qual_pruning3 partition of stable_qual_pruning for values from ('3000-02-01') to ('3000-03-01'); -- comparison against a stable value requires run-time pruning -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a < localtimestamp; -- timestamp < timestamptz comparison is only stable, not immutable -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a < '2000-02-01'::timestamptz; -- check ScalarArrayOp cases -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2010-02-01', '2020-01-01']::timestamp[]); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', '2010-01-01']::timestamp[]); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', localtimestamp]::timestamp[]); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2010-02-01', '2020-01-01']::timestamptz[]); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(array['2000-02-01', '2010-01-01']::timestamptz[]); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from stable_qual_pruning where a = any(null::timestamptz[]); @@ -898,7 +917,7 @@ create table mc3p2 partition of mc3p for values from (2, minvalue, minvalue) to (3, maxvalue, maxvalue); insert into mc3p values (0, 1, 1), (1, 1, 1), (2, 1, 1); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from mc3p where a < 3 and abs(b) = 1; -- @@ -908,12 +927,12 @@ select * from mc3p where a < 3 and abs(b) = 1; -- prepare ps1 as select * from mc3p where a = $1 and abs(b) < (select 3); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) execute ps1(1); deallocate ps1; prepare ps2 as select * from mc3p where a <= $1 and abs(b) < (select 3); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) execute ps2(1); deallocate ps2; @@ -927,10 +946,10 @@ create table boolp (a bool) partition by list (a); create table boolp_t partition of boolp for values in('t'); create table boolp_f partition of boolp for values in('f'); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from boolp where a = (select value from boolvalues where value); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from boolp where a = (select value from boolvalues where not value); drop table boolp; @@ -950,12 +969,12 @@ create index on ma_test (b); analyze ma_test; prepare mt_q1 (int) as select a from ma_test where a >= $1 and a % 10 = 5 order by b; -explain (analyze, costs off, summary off, timing off) execute mt_q1(15); +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(15); execute mt_q1(15); -explain (analyze, costs off, summary off, timing off) execute mt_q1(25); +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(25); execute mt_q1(25); -- Ensure MergeAppend behaves correctly when no subplans match -explain (analyze, costs off, summary off, timing off) execute mt_q1(35); +explain (analyze, costs off, summary off, timing off, buffers off) execute mt_q1(35); execute mt_q1(35); deallocate mt_q1; @@ -963,12 +982,12 @@ deallocate mt_q1; prepare mt_q2 (int) as select * from ma_test where a >= $1 order by b limit 1; -- Ensure output list looks sane when the MergeAppend has no subplans. -explain (analyze, verbose, costs off, summary off, timing off) execute mt_q2 (35); +explain (analyze, verbose, costs off, summary off, timing off, buffers off) execute mt_q2 (35); deallocate mt_q2; -- ensure initplan params properly prune partitions -explain (analyze, costs off, summary off, timing off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; +explain (analyze, costs off, summary off, timing off, buffers off) select * from ma_test where a >= (select min(b) from ma_test_p2) order by b; reset enable_seqscan; reset enable_sort; @@ -1148,7 +1167,7 @@ create table listp1 partition of listp for values in(1); create table listp2 partition of listp for values in(2) partition by list(b); create table listp2_10 partition of listp2 for values in (10); -explain (analyze, costs off, summary off, timing off) +explain (analyze, costs off, summary off, timing off, buffers off) select * from listp where a = (select 2) and b <> 10; -- @@ -1216,7 +1235,7 @@ create table rangep_100_to_200 partition of rangep for values from (100) to (200 create index on rangep (a); -- Ensure run-time pruning works on the nested Merge Append -explain (analyze on, costs off, timing off, summary off) +explain (analyze on, costs off, timing off, summary off, buffers off) select * from rangep where b IN((select 1),(select 2)) order by a; reset enable_sort; drop table rangep; @@ -1339,3 +1358,92 @@ drop operator class part_test_int4_ops2 using hash; drop operator ===(int4, int4); drop function explain_analyze(text); + +-- Runtime pruning on UPDATE using WITH CHECK OPTIONS and RETURNING +create table part_abc (a int, b text, c bool) partition by list (a); +create table part_abc_1 (b text, a int, c bool); +create table part_abc_2 (a int, c bool, b text); +alter table part_abc attach partition part_abc_1 for values in (1); +alter table part_abc attach partition part_abc_2 for values in (2); +insert into part_abc values (1, 'b', true); +insert into part_abc values (2, 'c', true); +create view part_abc_view as select * from part_abc where b <> 'a' with check option; +prepare update_part_abc_view as update part_abc_view set b = $2 where a = $1 returning *; +-- Only the unpruned partition should be shown in the list of relations to be +-- updated +explain (verbose, costs off) execute update_part_abc_view (1, 'd'); +execute update_part_abc_view (1, 'd'); +explain (verbose, costs off) execute update_part_abc_view (2, 'a'); +execute update_part_abc_view (2, 'a'); +-- All pruned. +explain (verbose, costs off) execute update_part_abc_view (3, 'a'); +execute update_part_abc_view (3, 'a'); +deallocate update_part_abc_view; + +-- Runtime pruning on MERGE using a stable function +create function stable_one() returns int as $$ begin return 1; end; $$ language plpgsql stable; +explain (costs off) +merge into part_abc_view pt +using (select stable_one() as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; +merge into part_abc_view pt +using (select stable_one() as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; +table part_abc_view; + +-- All pruned. +explain (costs off) +merge into part_abc_view pt +using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; +merge into part_abc_view pt +using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (q.pid = pt1.a) on pt.a = pt1.a +when matched then delete returning pt.a; +table part_abc_view; + +-- MERGE ... INSERT when all pruned from MERGE source. +begin; +explain (costs off) +merge into part_abc_view pt +using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 +when not matched then insert values (1, 'd', false) returning pt.a; +merge into part_abc_view pt +using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 +when not matched then insert values (1, 'd', false) returning pt.a; +table part_abc_view; +rollback; + +-- A case with multiple ModifyTable nodes. +begin; +create table part_abc_log (action text, a int, b text, c bool); +explain (costs off) +with t as ( + merge into part_abc_view pt + using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 + when not matched then insert values (1, 'd', false) returning merge_action(), pt.* +) +insert into part_abc_log select * from t returning *; +with t as ( + merge into part_abc_view pt + using (select stable_one() + 1 as pid) as q join part_abc_2 pt2 on (q.pid = pt2.a) on pt.a = stable_one() + 2 + when not matched then insert values (1, 'd', false) returning merge_action(), pt.* +) +insert into part_abc_log select * from t returning *; +table part_abc_view; +table part_abc_log; +rollback; + +-- A case with nested MergeAppend with its own PartitionPruneInfo. +create index on part_abc (a); +alter table part_abc add d int; +create table part_abc_3 partition of part_abc for values in (3, 4) partition by range (d); +create table part_abc_3_1 partition of part_abc_3 for values from (minvalue) to (1); +create table part_abc_3_2 partition of part_abc_3 for values from (1) to (100); +create table part_abc_3_3 partition of part_abc_3 for values from (100) to (maxvalue); +explain (costs off) +select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d <= stable_one() +union all +select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d >= stable_one(); + +drop view part_abc_view; +drop table part_abc; diff --git a/src/test/regress/sql/partition_split.sql b/src/test/regress/sql/partition_split.sql deleted file mode 100644 index ef5ea07f7400b..0000000000000 --- a/src/test/regress/sql/partition_split.sql +++ /dev/null @@ -1,962 +0,0 @@ --- --- PARTITION_SPLIT --- Tests for "ALTER TABLE ... SPLIT PARTITION ..." command --- - -CREATE SCHEMA partition_split_schema; -CREATE SCHEMA partition_split_schema2; -SET search_path = partition_split_schema, public; - --- --- BY RANGE partitioning --- - --- --- Test for error codes --- -CREATE TABLE sales_range (salesperson_id int, salesperson_name varchar(30), sales_amount int, sales_date date) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - --- ERROR: relation "sales_xxx" does not exist -ALTER TABLE sales_range SPLIT PARTITION sales_xxx INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: relation "sales_jan2022" already exists -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: invalid bound specification for a range partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES IN ('2022-05-01', '2022-06-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: empty range bound specified for partition "sales_mar2022" -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-02-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - ---ERROR: list of split partitions should contain at least two items -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-10-01')); - --- ERROR: lower bound of partition "sales_feb2022" is less than lower bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-01-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: name "sales_feb_mar_apr2022" is already used --- (We can create partition with the same name as split partition, but can't create two partitions with the same name) -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb_mar_apr2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb_mar_apr2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: name "sales_feb2022" is already used -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: "sales_feb_mar_apr2022" is not a partitioned table -ALTER TABLE sales_feb_mar_apr2022 SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- ERROR: upper bound of partition "sales_apr2022" is greater than upper bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-06-01')); - --- ERROR: lower bound of partition "sales_mar2022" conflicts with upper bound of previous partition "sales_feb2022" -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-02-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- Tests for spaces between partitions, them should be executed without DEFAULT partition -ALTER TABLE sales_range DETACH PARTITION sales_others; - --- ERROR: lower bound of partition "sales_feb2022" is not equal to lower bound of split partition -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-02') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- Check the source partition not in the search path -SET search_path = partition_split_schema2, public; -ALTER TABLE partition_split_schema.sales_range -SPLIT PARTITION partition_split_schema.sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -SET search_path = partition_split_schema, public; -\d+ sales_range - -DROP TABLE sales_range; -DROP TABLE sales_others; - --- --- Add rows into partitioned table then split partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - -SELECT * FROM sales_range; -SELECT * FROM sales_jan2022; -SELECT * FROM sales_feb2022; -SELECT * FROM sales_mar2022; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_others; - -DROP TABLE sales_range CASCADE; - --- --- Add split partition, then add rows into partitioned table --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - --- Split partition, also check schema qualification of new partitions -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION partition_split_schema.sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION partition_split_schema2.sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); -\d+ sales_range - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT * FROM sales_range; -SELECT * FROM sales_jan2022; -SELECT * FROM sales_feb2022; -SELECT * FROM partition_split_schema2.sales_mar2022; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_others; - -DROP TABLE sales_range CASCADE; - --- --- Test for: --- * composite partition key; --- * GENERATED column; --- * column with DEFAULT value. --- -CREATE TABLE sales_date (salesperson_name VARCHAR(30), sales_year INT, sales_month INT, sales_day INT, - sales_date VARCHAR(10) GENERATED ALWAYS AS - (LPAD(sales_year::text, 4, '0') || '.' || LPAD(sales_month::text, 2, '0') || '.' || LPAD(sales_day::text, 2, '0')) STORED, - sales_department VARCHAR(30) DEFAULT 'Sales department') - PARTITION BY RANGE (sales_year, sales_month, sales_day); - -CREATE TABLE sales_dec2022 PARTITION OF sales_date FOR VALUES FROM (2021, 12, 1) TO (2022, 1, 1); -CREATE TABLE sales_jan_feb2022 PARTITION OF sales_date FOR VALUES FROM (2022, 1, 1) TO (2022, 3, 1); -CREATE TABLE sales_other PARTITION OF sales_date FOR VALUES FROM (2022, 3, 1) TO (MAXVALUE, MAXVALUE, MAXVALUE); - -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2021, 12, 7); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2021, 12, 8); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 1, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 2, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 1, 2); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 2, 1); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 3, 3); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 3, 4); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager3', 2022, 5, 1); - -SELECT * FROM sales_date; -SELECT * FROM sales_dec2022; -SELECT * FROM sales_jan_feb2022; -SELECT * FROM sales_other; - -ALTER TABLE sales_date SPLIT PARTITION sales_jan_feb2022 INTO - (PARTITION sales_jan2022 FOR VALUES FROM (2022, 1, 1) TO (2022, 2, 1), - PARTITION sales_feb2022 FOR VALUES FROM (2022, 2, 1) TO (2022, 3, 1)); - -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager1', 2022, 1, 10); -INSERT INTO sales_date(salesperson_name, sales_year, sales_month, sales_day) VALUES ('Manager2', 2022, 2, 10); - -SELECT * FROM sales_date; -SELECT * FROM sales_dec2022; -SELECT * FROM sales_jan2022; -SELECT * FROM sales_feb2022; -SELECT * FROM sales_other; - ---ERROR: relation "sales_jan_feb2022" does not exist -SELECT * FROM sales_jan_feb2022; - -DROP TABLE sales_date CASCADE; - --- --- Test: split DEFAULT partition; use an index on partition key; check index after split --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT * FROM sales_others; -SELECT * FROM pg_indexes WHERE tablename = 'sales_others' and schemaname = 'partition_split_schema' ORDER BY indexname; - -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'), - PARTITION sales_others DEFAULT); - --- Use indexscan for testing indexes -SET enable_indexscan = ON; -SET enable_seqscan = OFF; - -SELECT * FROM sales_feb2022 where sales_date > '2022-01-01'; -SELECT * FROM sales_mar2022 where sales_date > '2022-01-01'; -SELECT * FROM sales_apr2022 where sales_date > '2022-01-01'; -SELECT * FROM sales_others where sales_date > '2022-01-01'; - -SET enable_indexscan = ON; -SET enable_seqscan = ON; - -SELECT * FROM pg_indexes WHERE tablename = 'sales_feb2022' and schemaname = 'partition_split_schema' ORDER BY indexname; -SELECT * FROM pg_indexes WHERE tablename = 'sales_mar2022' and schemaname = 'partition_split_schema' ORDER BY indexname; -SELECT * FROM pg_indexes WHERE tablename = 'sales_apr2022' and schemaname = 'partition_split_schema' ORDER BY indexname; -SELECT * FROM pg_indexes WHERE tablename = 'sales_others' and schemaname = 'partition_split_schema' ORDER BY indexname; - -DROP TABLE sales_range CASCADE; - --- --- Test: some cases for splitting DEFAULT partition (different bounds) --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date INT) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - --- sales_error intersects with sales_dec2022 (lower bound) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211230) TO (20220201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - --- sales_error intersects with sales_feb2022 (upper bound) --- ERROR: lower bound of partition "sales_feb2022" conflicts with upper bound of previous partition "sales_error" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20220101) TO (20220202), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - --- sales_error intersects with sales_dec2022 (inside bound) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211210) TO (20211220), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - --- sales_error intersects with sales_dec2022 (exactly the same bounds) --- ERROR: lower bound of partition "sales_error" conflicts with upper bound of previous partition "sales_dec2022" -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_error FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - --- ERROR: all partitions in the list should be DEFAULT because split partition is DEFAULT -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_jan2022 FOR VALUES FROM (20220101) TO (20220201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301)); - --- no error: bounds of sales_noerror are between sales_dec2022 and sales_feb2022 -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_noerror FOR VALUES FROM (20220110) TO (20220120), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - -DROP TABLE sales_range; - -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date INT) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - --- no error: bounds of sales_noerror are equal to lower and upper bounds of sales_dec2022 and sales_feb2022 -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_dec2022 FOR VALUES FROM (20211201) TO (20220101), - PARTITION sales_noerror FOR VALUES FROM (20210101) TO (20210201), - PARTITION sales_feb2022 FOR VALUES FROM (20220201) TO (20220301), - PARTITION sales_others DEFAULT); - -DROP TABLE sales_range; - --- --- Test: split partition with CHECK and FOREIGN KEY CONSTRAINTs on partitioned table --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)); -INSERT INTO salespeople VALUES (1, 'Poirot'); - -CREATE TABLE sales_range ( -salesperson_id INT REFERENCES salespeople(salesperson_id), -sales_amount INT CHECK (sales_amount > 1), -sales_date DATE) PARTITION BY RANGE (sales_date); - -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb_mar_apr2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_feb_mar_apr2022'::regclass::oid ORDER BY conname; - -ALTER TABLE sales_range SPLIT PARTITION sales_feb_mar_apr2022 INTO - (PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_mar2022 FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'), - PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01')); - --- We should see the same CONSTRAINTs as on sales_feb_mar_apr2022 partition -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_feb2022'::regclass::oid ORDER BY conname;; -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_mar2022'::regclass::oid ORDER BY conname;; -SELECT pg_get_constraintdef(oid), conname, conkey FROM pg_constraint WHERE conrelid = 'sales_apr2022'::regclass::oid ORDER BY conname;; - --- ERROR: new row for relation "sales_mar2022" violates check constraint "sales_range_sales_amount_check" -INSERT INTO sales_range VALUES (1, 0, '2022-03-11'); --- ERROR: insert or update on table "sales_mar2022" violates foreign key constraint "sales_range_salesperson_id_fkey" -INSERT INTO sales_range VALUES (-1, 10, '2022-03-11'); --- ok -INSERT INTO sales_range VALUES (1, 10, '2022-03-11'); - -DROP TABLE sales_range CASCADE; -DROP TABLE salespeople CASCADE; - --- --- Test: split partition on partitioned table in case of existing FOREIGN KEY reference from another table --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); -CREATE TABLE sales (salesperson_id INT REFERENCES salespeople(salesperson_id), sales_amount INT, sales_date DATE); - -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_40 PARTITION OF salespeople FOR VALUES FROM (10) TO (40); - -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (19, 'Ivanov'); -INSERT INTO salespeople VALUES (20, 'Smirnoff'); -INSERT INTO salespeople VALUES (30, 'Ford'); - -INSERT INTO sales VALUES (1, 100, '2022-03-01'); -INSERT INTO sales VALUES (1, 110, '2022-03-02'); -INSERT INTO sales VALUES (10, 150, '2022-03-01'); -INSERT INTO sales VALUES (10, 90, '2022-03-03'); -INSERT INTO sales VALUES (19, 200, '2022-03-04'); -INSERT INTO sales VALUES (20, 50, '2022-03-12'); -INSERT INTO sales VALUES (20, 170, '2022-03-02'); -INSERT INTO sales VALUES (30, 30, '2022-03-04'); - -SELECT * FROM salespeople01_10; -SELECT * FROM salespeople10_40; - -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); - -SELECT * FROM salespeople01_10; -SELECT * FROM salespeople10_20; -SELECT * FROM salespeople20_30; -SELECT * FROM salespeople30_40; - --- ERROR: insert or update on table "sales" violates foreign key constraint "sales_salesperson_id_fkey" -INSERT INTO sales VALUES (40, 50, '2022-03-04'); --- ok -INSERT INTO sales VALUES (30, 50, '2022-03-04'); - -DROP TABLE sales CASCADE; -DROP TABLE salespeople CASCADE; - --- --- Test: split partition of partitioned table with triggers --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); - -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); -CREATE TABLE salespeople10_40 PARTITION OF salespeople FOR VALUES FROM (10) TO (40); - -INSERT INTO salespeople VALUES (1, 'Poirot'); - -CREATE OR REPLACE FUNCTION after_insert_row_trigger() RETURNS trigger LANGUAGE 'plpgsql' AS $BODY$ -BEGIN - RAISE NOTICE 'trigger(%) called: action = %, when = %, level = %', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; - RETURN NULL; -END; -$BODY$; - -CREATE TRIGGER salespeople_after_insert_statement_trigger - AFTER INSERT - ON salespeople - FOR EACH STATEMENT - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); - -CREATE TRIGGER salespeople_after_insert_row_trigger - AFTER INSERT - ON salespeople - FOR EACH ROW - EXECUTE PROCEDURE after_insert_row_trigger('salespeople'); - --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (10, 'May'); --- 1 trigger should fire here (row): -INSERT INTO salespeople10_40 VALUES (19, 'Ivanov'); - -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); - --- 2 triggers should fire here (row + statement): -INSERT INTO salespeople VALUES (20, 'Smirnoff'); --- 1 trigger should fire here (row): -INSERT INTO salespeople30_40 VALUES (30, 'Ford'); - -SELECT * FROM salespeople01_10; -SELECT * FROM salespeople10_20; -SELECT * FROM salespeople20_30; -SELECT * FROM salespeople30_40; - -DROP TABLE salespeople CASCADE; -DROP FUNCTION after_insert_row_trigger(); - --- --- Test: split partition witch identity column --- If split partition column is identity column, columns of new partitions are identity columns too. --- -CREATE TABLE salespeople(salesperson_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); - -CREATE TABLE salespeople1_2 PARTITION OF salespeople FOR VALUES FROM (1) TO (2); --- Create new partition with identity column: -CREATE TABLE salespeople2_5(salesperson_id INT NOT NULL, salesperson_name VARCHAR(30)); -ALTER TABLE salespeople ATTACH PARTITION salespeople2_5 FOR VALUES FROM (2) TO (5); - -INSERT INTO salespeople (salesperson_name) VALUES ('Poirot'); -INSERT INTO salespeople (salesperson_name) VALUES ('Ivanov'); - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople'::regclass::oid ORDER BY attnum; -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople1_2'::regclass::oid ORDER BY attnum; --- Split partition has identity column: -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople2_5'::regclass::oid ORDER BY attnum; - -ALTER TABLE salespeople SPLIT PARTITION salespeople2_5 INTO - (PARTITION salespeople2_3 FOR VALUES FROM (2) TO (3), - PARTITION salespeople3_4 FOR VALUES FROM (3) TO (4), - PARTITION salespeople4_5 FOR VALUES FROM (4) TO (5)); - -INSERT INTO salespeople (salesperson_name) VALUES ('May'); -INSERT INTO salespeople (salesperson_name) VALUES ('Ford'); - -SELECT * FROM salespeople1_2; -SELECT * FROM salespeople2_3; -SELECT * FROM salespeople3_4; -SELECT * FROM salespeople4_5; - -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople'::regclass::oid ORDER BY attnum; -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople1_2'::regclass::oid ORDER BY attnum; --- New partitions have identity-columns: -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople2_3'::regclass::oid ORDER BY attnum; -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople3_4'::regclass::oid ORDER BY attnum; -SELECT attname, attidentity, attgenerated FROM pg_attribute WHERE attnum > 0 AND attrelid = 'salespeople4_5'::regclass::oid ORDER BY attnum; - -DROP TABLE salespeople CASCADE; - --- --- Test: split partition with deleted columns --- -CREATE TABLE salespeople(salesperson_id INT PRIMARY KEY, salesperson_name VARCHAR(30)) PARTITION BY RANGE (salesperson_id); - -CREATE TABLE salespeople01_10 PARTITION OF salespeople FOR VALUES FROM (1) TO (10); --- Create new partition with some deleted columns: -CREATE TABLE salespeople10_40(d1 VARCHAR(30), salesperson_id INT PRIMARY KEY, d2 INT, d3 DATE, salesperson_name VARCHAR(30)); - -INSERT INTO salespeople10_40 VALUES ('dummy value 1', 19, 100, now(), 'Ivanov'); -INSERT INTO salespeople10_40 VALUES ('dummy value 2', 20, 101, now(), 'Smirnoff'); - -ALTER TABLE salespeople10_40 DROP COLUMN d1; -ALTER TABLE salespeople10_40 DROP COLUMN d2; -ALTER TABLE salespeople10_40 DROP COLUMN d3; - -ALTER TABLE salespeople ATTACH PARTITION salespeople10_40 FOR VALUES FROM (10) TO (40); - -INSERT INTO salespeople VALUES (1, 'Poirot'); -INSERT INTO salespeople VALUES (10, 'May'); -INSERT INTO salespeople VALUES (30, 'Ford'); - -ALTER TABLE salespeople SPLIT PARTITION salespeople10_40 INTO - (PARTITION salespeople10_20 FOR VALUES FROM (10) TO (20), - PARTITION salespeople20_30 FOR VALUES FROM (20) TO (30), - PARTITION salespeople30_40 FOR VALUES FROM (30) TO (40)); - -select * from salespeople01_10; -select * from salespeople10_20; -select * from salespeople20_30; -select * from salespeople30_40; - -DROP TABLE salespeople CASCADE; - --- --- Test: split sub-partition --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_feb2022 PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'); -CREATE TABLE sales_mar2022 PARTITION OF sales_range FOR VALUES FROM ('2022-03-01') TO ('2022-04-01'); - -CREATE TABLE sales_apr2022 (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_apr_all PARTITION OF sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); -ALTER TABLE sales_range ATTACH PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'); - -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -CREATE INDEX sales_range_sales_date_idx ON sales_range USING btree (sales_date); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT * FROM sales_range; -SELECT * FROM sales_apr2022; - -ALTER TABLE sales_apr2022 SPLIT PARTITION sales_apr_all INTO - (PARTITION sales_apr2022_01_10 FOR VALUES FROM ('2022-04-01') TO ('2022-04-10'), - PARTITION sales_apr2022_10_20 FOR VALUES FROM ('2022-04-10') TO ('2022-04-20'), - PARTITION sales_apr2022_20_30 FOR VALUES FROM ('2022-04-20') TO ('2022-05-01')); - -SELECT * FROM sales_range; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_apr2022_01_10; -SELECT * FROM sales_apr2022_10_20; -SELECT * FROM sales_apr2022_20_30; - -DROP TABLE sales_range; - --- --- BY LIST partitioning --- - --- --- Test: specific errors for BY LIST partitioning --- -CREATE TABLE sales_list -(salesperson_id INT, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); - -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Oslo', 'St. Petersburg', 'Helsinki'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; - --- ERROR: new partition "sales_east" would overlap with another (not split) partition "sales_nord" -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok', 'Helsinki'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); - --- ERROR: new partition "sales_west" would overlap with another new partition "sales_central" -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Lisbon', 'Kyiv')); - --- ERROR: new partition "sales_west" cannot have NULL value because split partition does not have -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid', NULL), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); - -DROP TABLE sales_list; - --- --- Test: two specific errors for BY LIST partitioning: --- * new partitions do not have NULL value, which split partition has. --- * new partitions do not have a value that split partition has. --- -CREATE TABLE sales_list -(salesperson_id INT, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); - -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Helsinki', 'St. Petersburg', 'Oslo'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok', NULL); - --- ERROR: new partitions do not have value NULL but split partition does -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); - --- ERROR: new partitions do not have value 'Kyiv' but split partition does -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', NULL)); - -DROP TABLE sales_list; - --- --- Test: BY LIST partitioning, SPLIT PARTITION with data --- -CREATE TABLE sales_list -(salesperson_id SERIAL, - salesperson_name VARCHAR(30), - sales_state VARCHAR(20), - sales_amount INT, - sales_date DATE) -PARTITION BY LIST (sales_state); - -CREATE INDEX sales_list_salesperson_name_idx ON sales_list USING btree (salesperson_name); -CREATE INDEX sales_list_sales_state_idx ON sales_list USING btree (sales_state); - -CREATE TABLE sales_nord PARTITION OF sales_list FOR VALUES IN ('Helsinki', 'St. Petersburg', 'Oslo'); -CREATE TABLE sales_all PARTITION OF sales_list FOR VALUES IN ('Warsaw', 'Lisbon', 'New York', 'Madrid', 'Bejing', 'Berlin', 'Delhi', 'Kyiv', 'Vladivostok'); -CREATE TABLE sales_others PARTITION OF sales_list DEFAULT; - -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Trump', 'Bejing', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smirnoff', 'New York', 500, '2022-03-03'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ford', 'St. Petersburg', 2000, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Ivanov', 'Warsaw', 750, '2022-03-04'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Deev', 'Lisbon', 250, '2022-03-07'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Poirot', 'Berlin', 1000, '2022-03-01'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Oslo', 1200, '2022-03-06'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Li', 'Vladivostok', 1150, '2022-03-09'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('May', 'Oslo', 1200, '2022-03-11'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Halder', 'Helsinki', 800, '2022-03-02'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Muller', 'Madrid', 650, '2022-03-05'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Smith', 'Kyiv', 350, '2022-03-10'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Gandi', 'Warsaw', 150, '2022-03-08'); -INSERT INTO sales_list (salesperson_name, sales_state, sales_amount, sales_date) VALUES ('Plato', 'Lisbon', 950, '2022-03-05'); - -ALTER TABLE sales_list SPLIT PARTITION sales_all INTO - (PARTITION sales_west FOR VALUES IN ('Lisbon', 'New York', 'Madrid'), - PARTITION sales_east FOR VALUES IN ('Bejing', 'Delhi', 'Vladivostok'), - PARTITION sales_central FOR VALUES IN ('Warsaw', 'Berlin', 'Kyiv')); - -SELECT * FROM sales_list; -SELECT * FROM sales_west; -SELECT * FROM sales_east; -SELECT * FROM sales_nord; -SELECT * FROM sales_central; - --- Use indexscan for testing indexes after splitting partition -SET enable_indexscan = ON; -SET enable_seqscan = OFF; - -SELECT * FROM sales_central WHERE sales_state = 'Warsaw'; -SELECT * FROM sales_list WHERE sales_state = 'Warsaw'; -SELECT * FROM sales_list WHERE salesperson_name = 'Ivanov'; - -SET enable_indexscan = ON; -SET enable_seqscan = ON; - -DROP TABLE sales_list; - --- --- Test for: --- * split DEFAULT partition to partitions with spaces between bounds; --- * random order of partitions in SPLIT PARTITION command. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-09'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-07'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -ALTER TABLE sales_range SPLIT PARTITION sales_others INTO - (PARTITION sales_others DEFAULT, - PARTITION sales_mar2022_1decade FOR VALUES FROM ('2022-03-01') TO ('2022-03-10'), - PARTITION sales_jan2022_1decade FOR VALUES FROM ('2022-01-01') TO ('2022-01-10'), - PARTITION sales_feb2022_1decade FOR VALUES FROM ('2022-02-01') TO ('2022-02-10'), - PARTITION sales_apr2022_1decade FOR VALUES FROM ('2022-04-01') TO ('2022-04-10')); - -SELECT * FROM sales_jan2022_1decade; -SELECT * FROM sales_feb2022_1decade; -SELECT * FROM sales_mar2022_1decade; -SELECT * FROM sales_apr2022_1decade; -SELECT * FROM sales_others; - -DROP TABLE sales_range; - --- --- Test for: --- * split non-DEFAULT partition to partitions with spaces between bounds; --- * random order of partitions in SPLIT PARTITION command. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_all PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-05-01'); -CREATE TABLE sales_others PARTITION OF sales_range DEFAULT; - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-09'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-07'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -ALTER TABLE sales_range SPLIT PARTITION sales_all INTO - (PARTITION sales_mar2022_1decade FOR VALUES FROM ('2022-03-01') TO ('2022-03-10'), - PARTITION sales_jan2022_1decade FOR VALUES FROM ('2022-01-01') TO ('2022-01-10'), - PARTITION sales_feb2022_1decade FOR VALUES FROM ('2022-02-01') TO ('2022-02-10'), - PARTITION sales_apr2022_1decade FOR VALUES FROM ('2022-04-01') TO ('2022-04-10')); - -SELECT * FROM sales_jan2022_1decade; -SELECT * FROM sales_feb2022_1decade; -SELECT * FROM sales_mar2022_1decade; -SELECT * FROM sales_apr2022_1decade; -SELECT * FROM sales_others; - -DROP TABLE sales_range; - --- --- Test for split non-DEFAULT partition to DEFAULT partition + partitions --- with spaces between bounds. --- -CREATE TABLE sales_range (salesperson_id INT, salesperson_name VARCHAR(30), sales_amount INT, sales_date DATE) PARTITION BY RANGE (sales_date); -CREATE TABLE sales_jan2022 PARTITION OF sales_range FOR VALUES FROM ('2022-01-01') TO ('2022-02-01'); -CREATE TABLE sales_all PARTITION OF sales_range FOR VALUES FROM ('2022-02-01') TO ('2022-05-01'); - -INSERT INTO sales_range VALUES (1, 'May', 1000, '2022-01-31'); -INSERT INTO sales_range VALUES (2, 'Smirnoff', 500, '2022-02-10'); -INSERT INTO sales_range VALUES (3, 'Ford', 2000, '2022-04-30'); -INSERT INTO sales_range VALUES (4, 'Ivanov', 750, '2022-04-13'); -INSERT INTO sales_range VALUES (5, 'Deev', 250, '2022-04-07'); -INSERT INTO sales_range VALUES (6, 'Poirot', 150, '2022-02-11'); -INSERT INTO sales_range VALUES (7, 'Li', 175, '2022-03-08'); -INSERT INTO sales_range VALUES (8, 'Ericsson', 185, '2022-02-23'); -INSERT INTO sales_range VALUES (9, 'Muller', 250, '2022-03-11'); -INSERT INTO sales_range VALUES (10, 'Halder', 350, '2022-01-28'); -INSERT INTO sales_range VALUES (11, 'Trump', 380, '2022-04-06'); -INSERT INTO sales_range VALUES (12, 'Plato', 350, '2022-03-19'); -INSERT INTO sales_range VALUES (13, 'Gandi', 377, '2022-01-09'); - -ALTER TABLE sales_range SPLIT PARTITION sales_all INTO - (PARTITION sales_apr2022 FOR VALUES FROM ('2022-04-01') TO ('2022-05-01'), - PARTITION sales_feb2022 FOR VALUES FROM ('2022-02-01') TO ('2022-03-01'), - PARTITION sales_others DEFAULT); - -INSERT INTO sales_range VALUES (14, 'Smith', 510, '2022-05-04'); - -SELECT * FROM sales_range; -SELECT * FROM sales_jan2022; -SELECT * FROM sales_feb2022; -SELECT * FROM sales_apr2022; -SELECT * FROM sales_others; - -DROP TABLE sales_range; - --- --- Try to SPLIT partition of another table. --- -CREATE TABLE t1(i int, t text) PARTITION BY LIST (t); -CREATE TABLE t1pa PARTITION OF t1 FOR VALUES IN ('A'); -CREATE TABLE t2 (i int, t text) PARTITION BY RANGE (t); - --- ERROR: relation "t1pa" is not a partition of relation "t2" -ALTER TABLE t2 SPLIT PARTITION t1pa INTO - (PARTITION t2a FOR VALUES FROM ('A') TO ('B'), - PARTITION t2b FOR VALUES FROM ('B') TO ('C')); - -DROP TABLE t2; -DROP TABLE t1; - --- --- Try to SPLIT partition of temporary table. --- -CREATE TEMP TABLE t (i int) PARTITION BY RANGE (i); -CREATE TEMP TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); - -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); - --- Partitions should be temporary. -SELECT c.oid::pg_catalog.regclass, pg_catalog.pg_get_expr(c.relpartbound, c.oid), c.relpersistence - FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i - WHERE c.oid = i.inhrelid AND i.inhparent = 't'::regclass - ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT', c.oid::pg_catalog.regclass::pg_catalog.text; - -DROP TABLE t; - --- Check the new partitions inherit parent's tablespace -CREATE TABLE t (i int PRIMARY KEY USING INDEX TABLESPACE regress_tblspace) - PARTITION BY RANGE (i) TABLESPACE regress_tblspace; -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -SELECT tablename, tablespace FROM pg_tables - WHERE tablename IN ('t', 'tp_0_1', 'tp_1_2') AND schemaname = 'partition_split_schema' - ORDER BY tablename, tablespace; -SELECT tablename, indexname, tablespace FROM pg_indexes - WHERE tablename IN ('t', 'tp_0_1', 'tp_1_2') AND schemaname = 'partition_split_schema' - ORDER BY tablename, indexname, tablespace; -DROP TABLE t; - --- Check new partitions inherits parent's table access method -CREATE ACCESS METHOD partition_split_heap TYPE TABLE HANDLER heap_tableam_handler; -CREATE TABLE t (i int) PARTITION BY RANGE (i) USING partition_split_heap; -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -SELECT c.relname, a.amname -FROM pg_class c JOIN pg_am a ON c.relam = a.oid -WHERE c.oid IN ('t'::regclass, 'tp_0_1'::regclass, 'tp_1_2'::regclass) -ORDER BY c.relname; -DROP TABLE t; -DROP ACCESS METHOD partition_split_heap; - --- Test permission checks. The user needs to own the parent table and the --- the partition to split to do the split. -CREATE ROLE regress_partition_split_alice; -CREATE ROLE regress_partition_split_bob; -GRANT ALL ON SCHEMA partition_split_schema TO regress_partition_split_alice; -GRANT ALL ON SCHEMA partition_split_schema TO regress_partition_split_bob; - -SET SESSION AUTHORIZATION regress_partition_split_alice; -CREATE TABLE t (i int) PARTITION BY RANGE (i); -CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); - -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -RESET SESSION AUTHORIZATION; - -ALTER TABLE t OWNER TO regress_partition_split_bob; -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -RESET SESSION AUTHORIZATION; - -ALTER TABLE tp_0_2 OWNER TO regress_partition_split_bob; -SET SESSION AUTHORIZATION regress_partition_split_bob; -ALTER TABLE t SPLIT PARTITION tp_0_2 INTO - (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), - PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); -RESET SESSION AUTHORIZATION; - -DROP TABLE t; -REVOKE ALL ON SCHEMA partition_split_schema FROM regress_partition_split_alice; -REVOKE ALL ON SCHEMA partition_split_schema FROM regress_partition_split_bob; -DROP ROLE regress_partition_split_alice; -DROP ROLE regress_partition_split_bob; - --- Split partition of a temporary table when one of the partitions after --- split has the same name as the partition being split -CREATE TEMP TABLE t (a int) PARTITION BY RANGE (a); -CREATE TEMP TABLE tp_0 PARTITION OF t FOR VALUES FROM (0) TO (2); -ALTER TABLE t SPLIT PARTITION tp_0 INTO - (PARTITION tp_0 FOR VALUES FROM (0) TO (1), - PARTITION tp_1 FOR VALUES FROM (1) TO (2)); -DROP TABLE t; - -RESET search_path; - --- -DROP SCHEMA partition_split_schema; -DROP SCHEMA partition_split_schema2; diff --git a/src/test/regress/sql/password.sql b/src/test/regress/sql/password.sql index bb82aa4aa244b..e7a98045450c1 100644 --- a/src/test/regress/sql/password.sql +++ b/src/test/regress/sql/password.sql @@ -95,6 +95,10 @@ SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassw WHERE rolname LIKE 'regress_passwd_sha_len%' ORDER BY rolname; +-- Test that valid hashes that are too long are rejected +CREATE ROLE regress_passwd10 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; +ALTER ROLE regress_passwd9 PASSWORD 'SCRAM-SHA-256$000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004096:wNFxNSk1hAXBkgub8py3bg==$65zC6E+R0U7tiYTC9+Wtq4Thw6gUDj3eDCINij8TflU=:rC1I7tcVugrHEY2DT0iPjGyjM4aJxkMM9n8WBxtUtHU='; + DROP ROLE regress_passwd1; DROP ROLE regress_passwd2; DROP ROLE regress_passwd3; diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 18c91572ae140..d413d995d17e0 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -2072,7 +2072,8 @@ declare p2 int4 := 1006; n int4; begin - open c1 (p1 := p1, p2 := p2, debug := 2); + -- use both supported syntaxes for named arguments + open c1 (p1 := p1, p2 => p2, debug => 2); fetch c1 into n; return n; end $$ language plpgsql; @@ -2934,7 +2935,8 @@ begin raise notice '% from %', r.i, c; end loop; -- again, to test if cursor was closed properly - for r in c(9,10) loop + -- (and while we're at it, test named-parameter notation) + for r in c(r2 := 10, r1 => 9) loop raise notice '% from %', r.i, c; end loop; -- and test a parameterless cursor diff --git a/src/test/regress/sql/predicate.sql b/src/test/regress/sql/predicate.sql index 63f6a7786f369..9dcb81b1bc52f 100644 --- a/src/test/regress/sql/predicate.sql +++ b/src/test/regress/sql/predicate.sql @@ -64,22 +64,20 @@ SELECT * FROM pred_tab t WHERE t.b IS NULL OR t.c IS NULL; -- and b) its Var is not nullable by any outer joins EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL; + LEFT JOIN pred_tab t2 ON t1.a IS NOT NULL; -- Ensure the IS_NOT_NULL qual is not ignored when columns are made nullable -- by an outer join EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON t1.a = 1 + FULL JOIN pred_tab t2 ON t1.a = t2.a LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL; -- Ensure the IS_NULL qual is reduced to constant-FALSE, since a) it's on a NOT -- NULL column, and b) its Var is not nullable by any outer joins EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NULL AND t2.b = 1; + LEFT JOIN pred_tab t2 ON t1.a IS NULL; -- Ensure the IS_NULL qual is not reduced to constant-FALSE when the column is -- nullable by an outer join @@ -95,22 +93,20 @@ SELECT * FROM pred_tab t1 -- Ensure the OR clause is ignored when an OR branch is provably always true EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL OR t2.b = 1; + LEFT JOIN pred_tab t2 ON t1.a IS NOT NULL OR t2.b = 1; -- Ensure the NullTest is not ignored when the column is nullable by an outer -- join EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON t1.a = 1 + FULL JOIN pred_tab t2 ON t1.a = t2.a LEFT JOIN pred_tab t3 ON t2.a IS NOT NULL OR t2.b = 1; -- Ensure the OR clause is reduced to constant-FALSE when all OR branches are -- provably false EXPLAIN (COSTS OFF) SELECT * FROM pred_tab t1 - LEFT JOIN pred_tab t2 ON TRUE - LEFT JOIN pred_tab t3 ON (t2.a IS NULL OR t2.c IS NULL) AND t2.b = 1; + LEFT JOIN pred_tab t2 ON (t1.a IS NULL OR t1.c IS NULL); -- Ensure the OR clause is not reduced to constant-FALSE when a column is -- made nullable from an outer join @@ -147,3 +143,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM pred_parent WHERE a IS NULL; DROP TABLE pred_parent, pred_child; + +-- Validate we do not reduce a clone clause to a constant true or false +CREATE TABLE pred_tab (a int, b int); +CREATE TABLE pred_tab_notnull (a int, b int NOT NULL); + +INSERT INTO pred_tab VALUES (1, 1); +INSERT INTO pred_tab VALUES (2, 2); + +INSERT INTO pred_tab_notnull VALUES (2, 2); +INSERT INTO pred_tab_notnull VALUES (3, 3); + +ANALYZE pred_tab; +ANALYZE pred_tab_notnull; + +-- Ensure the IS_NOT_NULL qual is not reduced to constant true and removed +EXPLAIN (COSTS OFF) +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NOT NULL; + +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NOT NULL; + +-- Ensure the IS_NULL qual is not reduced to constant false +EXPLAIN (COSTS OFF) +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NULL AND t3.a IS NOT NULL; + +SELECT * FROM pred_tab t1 + LEFT JOIN pred_tab t2 ON TRUE + LEFT JOIN pred_tab_notnull t3 ON t2.a = t3.a + LEFT JOIN pred_tab t4 ON t3.b IS NULL AND t3.a IS NOT NULL; + +DROP TABLE pred_tab; +DROP TABLE pred_tab_notnull; diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index ae338e8cc8ea6..f337aa67c13f2 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -90,6 +90,21 @@ CREATE USER regress_priv_user3; CREATE USER regress_priv_user4; CREATE USER regress_priv_user5; +-- DROP OWNED should also act on granted and granted-to roles +GRANT regress_priv_user1 TO regress_priv_user2; +GRANT regress_priv_user2 TO regress_priv_user3; +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; +REASSIGN OWNED BY regress_priv_user2 TO regress_priv_user4; -- no effect +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; +DROP OWNED BY regress_priv_user2; -- removes both grants +SELECT roleid::regrole, member::regrole FROM pg_auth_members + WHERE roleid IN ('regress_priv_user1'::regrole,'regress_priv_user2'::regrole) + ORDER BY roleid::regrole::text; + GRANT pg_read_all_data TO regress_priv_user6; GRANT pg_write_all_data TO regress_priv_user7; GRANT pg_read_all_settings TO regress_priv_user8 WITH ADMIN OPTION; @@ -124,6 +139,39 @@ SET ROLE pg_read_all_stats; -- fail, granted without SET option RESET ROLE; RESET SESSION AUTHORIZATION; + +-- test interaction of SET SESSION AUTHORIZATION and SET ROLE, +-- as well as propagation of these settings to parallel workers +GRANT regress_priv_user9 TO regress_priv_user8; + +SET SESSION AUTHORIZATION regress_priv_user8; +SET ROLE regress_priv_user9; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + +BEGIN; +SET SESSION AUTHORIZATION regress_priv_user10; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; +ROLLBACK; +SET debug_parallel_query = 0; +SELECT session_user, current_role, current_user, current_setting('role') as role; +SET debug_parallel_query = 1; +SELECT session_user, current_role, current_user, current_setting('role') as role; + +RESET SESSION AUTHORIZATION; +-- session_user at this point is installation-dependent +SET debug_parallel_query = 0; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; +SET debug_parallel_query = 1; +SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role; + +RESET debug_parallel_query; + REVOKE pg_read_all_settings FROM regress_priv_user8; DROP USER regress_priv_user10; @@ -136,6 +184,9 @@ CREATE GROUP regress_priv_group2 WITH ADMIN regress_priv_user1 USER regress_priv ALTER GROUP regress_priv_group1 ADD USER regress_priv_user4; GRANT regress_priv_group2 TO regress_priv_user2 GRANTED BY regress_priv_user1; +SET SESSION AUTHORIZATION regress_priv_user3; +ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- fail +ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; -- fail SET SESSION AUTHORIZATION regress_priv_user1; ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- duplicate @@ -1004,10 +1055,6 @@ from (select oid from pg_roles where rolname = current_user) as t2; select has_table_privilege(t2.oid,'pg_authid','delete') from (select oid from pg_roles where rolname = current_user) as t2; --- 'rule' privilege no longer exists, but for backwards compatibility --- has_table_privilege still recognizes the keyword and says FALSE -select has_table_privilege(current_user,t1.oid,'rule') -from (select oid from pg_class where relname = 'pg_authid') as t1; select has_table_privilege(current_user,t1.oid,'references') from (select oid from pg_class where relname = 'pg_authid') as t1; @@ -1328,11 +1375,50 @@ SELECT loread(lo_open(1005, x'40000'::int), 32); SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); +-- has_largeobject_privilege function + +-- superuser +\c - +SELECT has_largeobject_privilege(1001, 'SELECT'); +SELECT has_largeobject_privilege(1002, 'SELECT'); +SELECT has_largeobject_privilege(1003, 'SELECT'); +SELECT has_largeobject_privilege(1004, 'SELECT'); + +SELECT has_largeobject_privilege(1001, 'UPDATE'); +SELECT has_largeobject_privilege(1002, 'UPDATE'); +SELECT has_largeobject_privilege(1003, 'UPDATE'); +SELECT has_largeobject_privilege(1004, 'UPDATE'); + +-- not-existing large object +SELECT has_largeobject_privilege(9999, 'SELECT'); -- NULL + +-- non-superuser +SET SESSION AUTHORIZATION regress_priv_user2; +SELECT has_largeobject_privilege(1001, 'SELECT'); +SELECT has_largeobject_privilege(1002, 'SELECT'); -- false +SELECT has_largeobject_privilege(1003, 'SELECT'); +SELECT has_largeobject_privilege(1004, 'SELECT'); + +SELECT has_largeobject_privilege(1001, 'UPDATE'); +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false +SELECT has_largeobject_privilege(1003, 'UPDATE'); -- false +SELECT has_largeobject_privilege(1004, 'UPDATE'); + +SELECT has_largeobject_privilege('regress_priv_user3', 1001, 'SELECT'); +SELECT has_largeobject_privilege('regress_priv_user3', 1003, 'SELECT'); -- false +SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'SELECT'); + +SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'UPDATE'); -- false +SELECT has_largeobject_privilege('regress_priv_user3', 2001, 'UPDATE'); + -- compatibility mode in largeobject permission \c - SET lo_compat_privileges = false; -- default setting SET SESSION AUTHORIZATION regress_priv_user4; +SELECT has_largeobject_privilege(1002, 'SELECT'); -- false +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false + SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied @@ -1346,6 +1432,9 @@ SELECT lo_import('/dev/null', 2003); -- to be denied SET lo_compat_privileges = true; -- compatibility mode SET SESSION AUTHORIZATION regress_priv_user4; +SELECT has_largeobject_privilege(1002, 'SELECT'); -- true +SELECT has_largeobject_privilege(1002, 'UPDATE'); -- true + SELECT loread(lo_open(1002, x'40000'::int), 32); SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); @@ -1497,11 +1586,47 @@ ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2; COMMIT; +-- +-- Test for default privileges on large objects. This is done in a +-- separate, rollbacked, transaction to avoid any trouble with other +-- regression sessions. +-- + +BEGIN; + +SELECT lo_create(1007); +SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'SELECT'); -- no +SELECT has_largeobject_privilege('regress_priv_user2', 1007, 'UPDATE'); -- no + +ALTER DEFAULT PRIVILEGES GRANT SELECT ON LARGE OBJECTS TO regress_priv_user2; + +SELECT lo_create(1008); +SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'SELECT'); -- yes +SELECT has_largeobject_privilege('regress_priv_user6', 1008, 'SELECT'); -- no +SELECT has_largeobject_privilege('regress_priv_user2', 1008, 'UPDATE'); -- no + +ALTER DEFAULT PRIVILEGES GRANT ALL ON LARGE OBJECTS TO regress_priv_user2; +SELECT lo_create(1009); +SELECT has_largeobject_privilege('regress_priv_user2', 1009, 'SELECT'); -- true +SELECT has_largeobject_privilege('regress_priv_user2', 1009, 'UPDATE'); -- true + +ALTER DEFAULT PRIVILEGES REVOKE UPDATE ON LARGE OBJECTS FROM regress_priv_user2; +SELECT lo_create(1010); +SELECT has_largeobject_privilege('regress_priv_user2', 1010, 'SELECT'); -- true +SELECT has_largeobject_privilege('regress_priv_user2', 1010, 'UPDATE'); -- false + +ROLLBACK; + +ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON LARGE OBJECTS TO public; -- error + +\c - + -- Test for DROP OWNED BY with shared dependencies. This is done in a -- separate, rollbacked, transaction to avoid any trouble with other -- regression sessions. BEGIN; ALTER DEFAULT PRIVILEGES GRANT ALL ON FUNCTIONS TO regress_priv_user2; +ALTER DEFAULT PRIVILEGES GRANT ALL ON LARGE OBJECTS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON SEQUENCES TO regress_priv_user2; ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO regress_priv_user2; @@ -1822,24 +1947,29 @@ REVOKE MAINTAIN ON lock_table FROM regress_locktable_user; DROP TABLE lock_table; DROP USER regress_locktable_user; --- test to check privileges of system views pg_shmem_allocations and --- pg_backend_memory_contexts. +-- test to check privileges of system views pg_shmem_allocations, +-- pg_shmem_allocations_numa and pg_backend_memory_contexts. -- switch to superuser \c - CREATE ROLE regress_readallstats; +SELECT has_table_privilege('regress_readallstats','pg_aios','SELECT'); -- no SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- no +SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations_numa','SELECT'); -- no GRANT pg_read_all_stats TO regress_readallstats; +SELECT has_table_privilege('regress_readallstats','pg_aios','SELECT'); -- yes SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- yes SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- yes +SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations_numa','SELECT'); -- yes -- run query to ensure that functions within views can be executed SET ROLE regress_readallstats; +SELECT COUNT(*) >= 0 AS ok FROM pg_aios; SELECT COUNT(*) >= 0 AS ok FROM pg_backend_memory_contexts; SELECT COUNT(*) >= 0 AS ok FROM pg_shmem_allocations; RESET ROLE; @@ -1953,3 +2083,25 @@ DROP SCHEMA reindex_test; DROP ROLE regress_no_maintain; DROP ROLE regress_maintain; DROP ROLE regress_maintain_all; + +-- grantor selection +CREATE ROLE regress_grantor1; +CREATE ROLE regress_grantor2 ROLE regress_grantor1; +CREATE ROLE regress_grantor3; +CREATE TABLE grantor_test1 (); +CREATE TABLE grantor_test2 (); +CREATE TABLE grantor_test3 (); +GRANT SELECT ON grantor_test2 TO regress_grantor1 WITH GRANT OPTION; +GRANT SELECT, UPDATE ON grantor_test3 TO regress_grantor2 WITH GRANT OPTION; + +SET ROLE regress_grantor1; +GRANT SELECT, UPDATE ON grantor_test1 TO regress_grantor3; +GRANT SELECT, UPDATE ON grantor_test2 TO regress_grantor3; +GRANT SELECT, UPDATE ON grantor_test3 TO regress_grantor3; +RESET ROLE; + +SELECT * FROM information_schema.table_privileges t + WHERE grantor LIKE 'regress_grantor%' ORDER BY ROW(t.*); + +DROP TABLE grantor_test1, grantor_test2, grantor_test3; +DROP ROLE regress_grantor1, regress_grantor2, regress_grantor3; diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index 3b3c6f6e2944d..1a8a83462f022 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -45,12 +45,46 @@ SELECT 1 as one, 2 as two \g (format=csv csv_fieldsep='\t') SELECT 1 as one, 2 as two \gx (title='foo bar') \g --- \bind (extended query protocol) +-- \parse (extended query protocol) +\parse +SELECT 1 \parse '' +SELECT 2 \parse stmt1 +SELECT $1 \parse stmt2 +SELECT $1, $2 \parse stmt3 + +-- \bind_named (extended query protocol) +\bind_named +\bind_named '' \g +\bind_named stmt1 \g +\bind_named stmt2 'foo' \g +\bind_named stmt3 'foo' 'bar' \g +-- Repeated calls. The second call generates an error, cleaning up the +-- statement name set by the first call. +\bind_named stmt4 +\bind_named +\g +-- Last \bind_named wins +\bind_named stmt2 'foo' \bind_named stmt3 'foo2' 'bar2' \g +-- Multiple \g calls mean multiple executions +\bind_named stmt2 'foo3' \g \bind_named stmt3 'foo4' 'bar4' \g + +-- \close (extended query protocol) +\close +\close '' +\close stmt2 +\close stmt2 +SELECT name, statement FROM pg_prepared_statements ORDER BY name; +-- \bind (extended query protocol) SELECT 1 \bind \g SELECT $1 \bind 'foo' \g SELECT $1, $2 \bind 'foo' 'bar' \g +-- last \bind wins +select $1::int as col \bind 'foo' \bind 2 \g +-- Multiple \g calls mean multiple executions +select $1::int as col \bind 1 \g \bind 2 \g + -- errors -- parse error SELECT foo \bind \g @@ -58,6 +92,9 @@ SELECT foo \bind \g SELECT 1 \; SELECT 2 \bind \g -- bind error SELECT $1, $2 \bind 'foo' \g +-- bind_named error +\bind_named stmt2 'baz' \g +\bind_named stmt3 'baz' \g -- \gset @@ -461,6 +498,7 @@ create table psql_serial_tab (id serial); \d psql_serial_tab_id_seq \pset tuples_only true \df exp +\dfx exp \pset tuples_only false \pset expanded on \d psql_serial_tab_id_seq @@ -523,6 +561,9 @@ CREATE MATERIALIZED VIEW mat_view_heap_psql USING heap_psql AS SELECT f1 from tb \dv+ \set HIDE_TABLEAM on \d+ +-- \d with 'x' enables expanded mode, but only without a pattern +\d+x tbl_heap +\d+x RESET ROLE; RESET search_path; DROP SCHEMA tableam_display CASCADE; @@ -990,9 +1031,11 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; \pset fieldsep | `nosuchcommand` :foo :'foo' :"foo" \a SELECT $1 \bind 1 \g + \bind_named stmt1 1 2 \g \C arg1 \c arg1 arg2 arg3 arg4 \cd arg1 + \close stmt1 \conninfo \copy arg1 arg2 arg3 arg4 arg5 arg6 \copyright @@ -1004,11 +1047,15 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; \echo arg1 arg2 arg3 arg4 arg5 \echo arg1 \encoding arg1 + \endpipeline \errverbose \f arg1 + \flush + \flushrequest \g arg1 \gx arg1 \gexec + \getresults SELECT 1 AS one \gset \h \? @@ -1020,16 +1067,20 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; \lo_list \o arg1 \p + SELECT 1 \parse \password arg1 \prompt arg1 arg2 \pset arg1 arg2 \q \reset \s arg1 + \sendpipeline \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \setenv arg1 arg2 \sf whole_line \sv whole_line + \startpipeline + \syncpipeline \t arg1 \T arg1 \timing arg1 @@ -1266,9 +1317,10 @@ drop role regress_partitioning_role; \dAc brin pg*.oid* \dAf spgist \dAf btree int4 -\dAo+ btree float_ops +\dAo+ btree array_ops|float_ops \dAo * pg_catalog.jsonb_path_ops \dAp+ btree float_ops +\dApx+ btree time_ops \dAp * pg_catalog.uuid_ops -- check \dconfig @@ -1887,5 +1939,6 @@ ROLLBACK; CREATE TABLE defprivs (a int); \pset null '(default)' \z defprivs +\zx defprivs \pset null '' DROP TABLE defprivs; diff --git a/src/test/regress/sql/psql_pipeline.sql b/src/test/regress/sql/psql_pipeline.sql new file mode 100644 index 0000000000000..5945eca1ef76c --- /dev/null +++ b/src/test/regress/sql/psql_pipeline.sql @@ -0,0 +1,442 @@ +-- +-- Tests using psql pipelining +-- + +CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); + +-- Single query +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline +\startpipeline +SELECT 'val1'; +\endpipeline + +-- Multiple queries +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT 'val4'; +SELECT 'val5', 'val6'; +\endpipeline + +-- Multiple queries in single line, separated by semicolons +\startpipeline +SELECT 1; SELECT 2; SELECT 3 +; +\echo :PIPELINE_COMMAND_COUNT +\endpipeline + +-- Test \flush +\startpipeline +\flush +SELECT $1 \bind 'val1' \sendpipeline +\flush +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +\flush +SELECT 'val4'; +SELECT 'val5', 'val6'; +\endpipeline + +-- Send multiple syncs +\startpipeline +\echo :PIPELINE_COMMAND_COUNT +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT +SELECT $1 \bind 'val1' \sendpipeline +\syncpipeline +\syncpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +\syncpipeline +SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline +\echo :PIPELINE_COMMAND_COUNT +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT +SELECT 'val7'; +\syncpipeline +\syncpipeline +SELECT 'val8'; +\syncpipeline +SELECT 'val9'; +\echo :PIPELINE_COMMAND_COUNT +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT +\endpipeline + +-- Query terminated with a semicolon replaces an unnamed prepared +-- statement. +\startpipeline +SELECT $1 \parse '' +SELECT 1; +\bind_named '' +\endpipeline + +-- Extended query is appended to pipeline by a semicolon after a +-- newline. +\startpipeline +SELECT $1 \bind 1 +; +SELECT 2; +\endpipeline + +-- \startpipeline should not have any effect if already in a pipeline. +\startpipeline +\startpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline + +-- Convert an implicit transaction block to an explicit transaction block. +\startpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline +ROLLBACK \bind \sendpipeline +\endpipeline + +-- Multiple explicit transactions +\startpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +COMMIT \bind \sendpipeline +\endpipeline + +-- Use \parse and \bind_named +\startpipeline +SELECT $1 \parse '' +SELECT $1, $2 \parse '' +SELECT $2 \parse pipeline_1 +\bind_named '' 1 2 \sendpipeline +\bind_named pipeline_1 2 \sendpipeline +\endpipeline + +-- \getresults displays all results preceding a \flushrequest. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\flushrequest +\getresults +\endpipeline + +-- \getresults displays all results preceding a \syncpipeline. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\syncpipeline +\getresults +\endpipeline + +-- \getresults immediately returns if there is no result to fetch. +\startpipeline +\getresults +SELECT $1 \bind 2 \sendpipeline +\getresults +\flushrequest +\endpipeline +\getresults + +-- \getresults only fetches results preceding a \flushrequest. +\startpipeline +SELECT $1 \bind 2 \sendpipeline +\flushrequest +SELECT $1 \bind 2 \sendpipeline +\getresults +\endpipeline + +-- \getresults only fetches results preceding a \syncpipeline. +\startpipeline +SELECT $1 \bind 2 \sendpipeline +\syncpipeline +SELECT $1 \bind 2 \sendpipeline +\getresults +\endpipeline + +-- Use pipeline with chunked results for both \getresults and \endpipeline. +\startpipeline +\set FETCH_COUNT 10 +SELECT $1 \bind 2 \sendpipeline +\flushrequest +\getresults +SELECT $1 \bind 2 \sendpipeline +\endpipeline +\unset FETCH_COUNT + +-- \getresults with specific number of requested results. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline +\echo :PIPELINE_SYNC_COUNT +\syncpipeline +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT +\getresults 1 +\echo :PIPELINE_RESULT_COUNT +SELECT $1 \bind 4 \sendpipeline +\getresults 3 +\echo :PIPELINE_RESULT_COUNT +\endpipeline + +-- \syncpipeline count as one command to fetch for \getresults. +\startpipeline +\syncpipeline +\syncpipeline +SELECT $1 \bind 1 \sendpipeline +\flushrequest +\getresults 2 +\getresults 1 +\endpipeline + +-- \getresults 0 should get all the results. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline +\syncpipeline +\getresults 0 +\endpipeline + +-- +-- Pipeline errors +-- + +-- \endpipeline outside of pipeline should fail +\endpipeline + +-- After an aborted pipeline, commands after a \syncpipeline should be +-- displayed. +\startpipeline +SELECT $1 \bind \sendpipeline +\syncpipeline +SELECT $1 \bind 1 \sendpipeline +\endpipeline + +-- For an incorrect number of parameters, the pipeline is aborted and +-- the following queries will not be executed. +\startpipeline +SELECT \bind 'val1' \sendpipeline +SELECT $1 \bind 'val1' \sendpipeline +\endpipeline + +-- Using a semicolon with a parameter triggers an error and aborts +-- the pipeline. +\startpipeline +SELECT $1; +SELECT 1; +\endpipeline + +-- An explicit transaction with an error needs to be rollbacked after +-- the pipeline. +\startpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +\endpipeline +ROLLBACK; + +-- \watch is not allowed in a pipeline. +\startpipeline +SELECT \bind \sendpipeline +\watch 1 +\endpipeline + +-- \gdesc should fail as synchronous commands are not allowed in a pipeline, +-- and the pipeline should still be usable. +\startpipeline +SELECT $1 \bind 1 \gdesc +SELECT $1 \bind 1 \sendpipeline +\endpipeline + +-- \gset is not allowed in a pipeline, pipeline should still be usable. +\startpipeline +SELECT $1 as i, $2 as j \parse '' +SELECT $1 as k, $2 as l \parse 'second' +\bind_named '' 1 2 \gset +\bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j +\bind_named '' 1 2 \sendpipeline +\endpipeline + +-- \g and \gx are not allowed, pipeline should still be usable. +\startpipeline +SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \g (format=unaligned tuples_only=on) +SELECT $1 \bind 1 \gx +SELECT $1 \bind 1 \gx (format=unaligned tuples_only=on) +\reset +SELECT $1 \bind 1 \sendpipeline +\endpipeline + +-- \g and \gx warnings should be emitted in an aborted pipeline, with +-- pipeline still usable. +\startpipeline +SELECT $1 \bind \sendpipeline +\flushrequest +\getresults +SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \gx +\endpipeline + +-- \sendpipeline is not allowed outside of a pipeline +\sendpipeline +SELECT $1 \bind 1 \sendpipeline +\reset + +-- \sendpipeline is not allowed if not preceded by \bind or \bind_named +\startpipeline +\sendpipeline +SELECT 1 \sendpipeline +\endpipeline + +-- \gexec is not allowed, pipeline should still be usable. +\startpipeline +SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' +\bind_named insert_stmt \gexec +\bind_named insert_stmt \sendpipeline +SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline +\endpipeline + +-- After an error, pipeline is aborted and requires \syncpipeline to be +-- reusable. +\startpipeline +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +\flushrequest +\getresults +-- Pipeline is aborted. +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +-- Sync allows pipeline to recover. +\syncpipeline +\getresults +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\close a +\flushrequest +\getresults +\endpipeline + +-- In an aborted pipeline, \getresults 1 aborts commands one at a time. +\startpipeline +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \parse a +\bind_named a 1 \sendpipeline +\syncpipeline +\getresults 1 +\getresults 1 +\getresults 1 +\getresults 1 +\getresults 1 +\endpipeline + +-- Test chunked results with an aborted pipeline. +\startpipeline +\set FETCH_COUNT 10 +SELECT $1 \bind \sendpipeline +\flushrequest +\getresults +SELECT $1 \bind \sendpipeline +\endpipeline +\unset FETCH_COUNT + +-- \getresults returns an error when an incorrect number is provided. +\startpipeline +\getresults -1 +\endpipeline + +-- \getresults when there is no result should not impact the next +-- query executed. +\getresults 1 +select 1; + +-- Error messages accumulate and are repeated. +\startpipeline +SELECT 1 \bind \sendpipeline +\gdesc +\gdesc +\endpipeline + +-- +-- Pipelines and transaction blocks +-- + +-- SET LOCAL will issue a warning when modifying a GUC outside of a +-- transaction block. The change will still be valid as a pipeline +-- runs within an implicit transaction block. Sending a sync will +-- commit the implicit transaction block. The first command after a +-- sync will not be seen as belonging to a pipeline. +\startpipeline +SET LOCAL statement_timeout='1h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline +\syncpipeline +SHOW statement_timeout \bind \sendpipeline +SET LOCAL statement_timeout='2h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline +\endpipeline + +-- REINDEX CONCURRENTLY fails if not the first command in a pipeline. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + +-- REINDEX CONCURRENTLY works if it is the first command in a pipeline. +\startpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + +-- Subtransactions are not allowed in a pipeline. +\startpipeline +SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +ROLLBACK TO SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + +-- LOCK fails as the first command in a pipeline, as not seen in an +-- implicit transaction block. +\startpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + +-- LOCK succeeds as it is not the first command in a pipeline, +-- seen in an implicit transaction block. +\startpipeline +SELECT $1 \bind 1 \sendpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline +\endpipeline + +-- VACUUM works as the first command in a pipeline. +\startpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline + +-- VACUUM fails when not the first command in a pipeline. +\startpipeline +SELECT 1 \bind \sendpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline + +-- VACUUM works after a \syncpipeline. +\startpipeline +SELECT 1 \bind \sendpipeline +\syncpipeline +VACUUM psql_pipeline \bind \sendpipeline +\endpipeline + +-- Clean up +DROP TABLE psql_pipeline; diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql index 479d4f3264472..68001de4000fd 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -15,7 +15,7 @@ COMMENT ON PUBLICATION testpub_default IS 'test publication'; SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p; SET client_min_messages = 'ERROR'; -CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert); +CREATE PUBLICATION testpub_ins_trunct WITH (publish = insert); RESET client_min_messages; ALTER PUBLICATION testpub_default SET (publish = update); @@ -24,6 +24,8 @@ ALTER PUBLICATION testpub_default SET (publish = update); CREATE PUBLICATION testpub_xxx WITH (foo); CREATE PUBLICATION testpub_xxx WITH (publish = 'cluster, vacuum'); CREATE PUBLICATION testpub_xxx WITH (publish_via_partition_root = 'true', publish_via_partition_root = '0'); +CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = stored, publish_generated_columns = none); +CREATE PUBLICATION testpub_xxx WITH (publish_generated_columns = foo); \dRp @@ -212,7 +214,7 @@ CREATE FUNCTION testpub_rf_func1(integer, integer) RETURNS boolean AS $$ SELECT CREATE OPERATOR =#> (PROCEDURE = testpub_rf_func1, LEFTARG = integer, RIGHTARG = integer); CREATE PUBLICATION testpub6 FOR TABLE testpub_rf_tbl3 WHERE (e =#> 27); -- fail - user-defined functions are not allowed -CREATE FUNCTION testpub_rf_func2() RETURNS integer AS $$ BEGIN RETURN 123; END; $$ LANGUAGE plpgsql; +CREATE FUNCTION testpub_rf_func2() RETURNS integer IMMUTABLE AS $$ BEGIN RETURN 123; END; $$ LANGUAGE plpgsql; ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl1 WHERE (a >= testpub_rf_func2()); -- fail - non-immutable functions are not allowed. random() is volatile. ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl1 WHERE (a < random()); @@ -259,18 +261,30 @@ CREATE PUBLICATION testpub6 FOR TABLES IN SCHEMA testpub_rf_schema2; ALTER PUBLICATION testpub6 SET TABLES IN SCHEMA testpub_rf_schema2, TABLE testpub_rf_schema2.testpub_rf_tbl6 WHERE (i < 99); RESET client_min_messages; \dRp+ testpub6 +-- fail - virtual generated column uses user-defined function +CREATE TABLE testpub_rf_tbl6 (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * testpub_rf_func2()) VIRTUAL); +CREATE PUBLICATION testpub7 FOR TABLE testpub_rf_tbl6 WHERE (y > 100); +-- test that SET EXPRESSION is rejected, because it could affect a row filter +SET client_min_messages = 'ERROR'; +CREATE TABLE testpub_rf_tbl7 (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * 111) VIRTUAL); +CREATE PUBLICATION testpub8 FOR TABLE testpub_rf_tbl7 WHERE (y > 100); +ALTER TABLE testpub_rf_tbl7 ALTER COLUMN y SET EXPRESSION AS (x * testpub_rf_func2()); +RESET client_min_messages; DROP TABLE testpub_rf_tbl1; DROP TABLE testpub_rf_tbl2; DROP TABLE testpub_rf_tbl3; DROP TABLE testpub_rf_tbl4; DROP TABLE testpub_rf_tbl5; +DROP TABLE testpub_rf_tbl6; DROP TABLE testpub_rf_schema1.testpub_rf_tbl5; DROP TABLE testpub_rf_schema2.testpub_rf_tbl6; DROP SCHEMA testpub_rf_schema1; DROP SCHEMA testpub_rf_schema2; DROP PUBLICATION testpub5; DROP PUBLICATION testpub6; +DROP PUBLICATION testpub8; +DROP TABLE testpub_rf_tbl7; DROP OPERATOR =#>(integer, integer); DROP FUNCTION testpub_rf_func1(integer, integer); DROP FUNCTION testpub_rf_func2(); @@ -394,6 +408,54 @@ DROP TABLE rf_tbl_abcd_nopk; DROP TABLE rf_tbl_abcd_part_pk; -- ====================================================== +-- ====================================================== +-- Tests with generated column +SET client_min_messages = 'ERROR'; + +-- stored +CREATE TABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) STORED NOT NULL); +CREATE UNIQUE INDEX testpub_gencol_idx ON testpub_gencol (b); +ALTER TABLE testpub_gencol REPLICA IDENTITY USING index testpub_gencol_idx; + +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY index. +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; + +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY. +ALTER TABLE testpub_gencol REPLICA IDENTITY FULL; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +DROP PUBLICATION pub_gencol; + +-- ok - generated column "b" is published explicitly +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored); +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +DROP PUBLICATION pub_gencol; + +DROP TABLE testpub_gencol; + +-- virtual +CREATE TABLE testpub_gencol (a INT, b INT GENERATED ALWAYS AS (a + 1) VIRTUAL); + +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol; + +-- error - generated column "b" must be published explicitly as it is +-- part of the REPLICA IDENTITY. +ALTER TABLE testpub_gencol REPLICA IDENTITY FULL; +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +DROP PUBLICATION pub_gencol; + +-- error - "stored" setting does not affect virtual column +CREATE PUBLICATION pub_gencol FOR TABLE testpub_gencol with (publish_generated_columns = stored); +UPDATE testpub_gencol SET a = 100 WHERE a = 1; +DROP PUBLICATION pub_gencol; + +DROP TABLE testpub_gencol; + +RESET client_min_messages; +-- ====================================================== + -- fail - duplicate tables are not allowed if that table has any column lists SET client_min_messages = 'ERROR'; CREATE PUBLICATION testpub_dups FOR TABLE testpub_tbl1 (a), testpub_tbl1 WITH (publish = 'insert'); @@ -406,17 +468,21 @@ CREATE PUBLICATION testpub_fortable FOR TABLE testpub_tbl1; CREATE PUBLICATION testpub_fortable_insert WITH (publish = 'insert'); RESET client_min_messages; CREATE TABLE testpub_tbl5 (a int PRIMARY KEY, b text, c text, - d int generated always as (a + length(b)) stored); + d int generated always as (a + length(b)) stored, + e int generated always as (a + length(b)) virtual +); -- error: column "x" does not exist ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, x); -- error: replica identity "a" not included in the column list ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (b, c); UPDATE testpub_tbl5 SET a = 1; ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; --- error: generated column "d" can't be in list -ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, d); -- error: system attributes "ctid" not allowed in column list ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, ctid); +ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl1 (id, ctid); +-- error: duplicates not allowed in column list +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, a); +ALTER PUBLICATION testpub_fortable SET TABLE testpub_tbl5 (a, a); -- ok ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, c); ALTER TABLE testpub_tbl5 DROP COLUMN c; -- no dice @@ -431,6 +497,12 @@ ALTER TABLE testpub_tbl5 REPLICA IDENTITY USING INDEX testpub_tbl5_b_key; UPDATE testpub_tbl5 SET a = 1; ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; +-- ok: stored generated column "d" can be in the list too +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, d); +ALTER PUBLICATION testpub_fortable DROP TABLE testpub_tbl5; +-- error: virtual generated column "e" can't be in list +ALTER PUBLICATION testpub_fortable ADD TABLE testpub_tbl5 (a, e); + -- error: change the replica identity to "b", and column list to (a, c) -- then update fails, because (a, c) does not cover replica identity ALTER TABLE testpub_tbl5 REPLICA IDENTITY USING INDEX testpub_tbl5_b_key; @@ -760,7 +832,7 @@ ALTER PUBLICATION testpub_default ADD TABLE testpub_tbl1; ALTER PUBLICATION testpub_default SET TABLE testpub_tbl1; ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_nopk; -ALTER PUBLICATION testpib_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; +ALTER PUBLICATION testpub_ins_trunct ADD TABLE pub_test.testpub_nopk, testpub_tbl1; \d+ pub_test.testpub_nopk \d+ testpub_tbl1 @@ -1039,7 +1111,7 @@ CREATE PUBLICATION testpub_error FOR pub_test2.tbl1; DROP VIEW testpub_view; DROP PUBLICATION testpub_default; -DROP PUBLICATION testpib_ins_trunct; +DROP PUBLICATION testpub_ins_trunct; DROP PUBLICATION testpub_fortbl; DROP PUBLICATION testpub1_forschema; DROP PUBLICATION testpub2_forschema; @@ -1105,7 +1177,52 @@ DROP PUBLICATION pub; DROP TABLE sch1.tbl1; DROP SCHEMA sch1 cascade; DROP SCHEMA sch2 cascade; +-- ====================================================== + +-- Test the 'publish_generated_columns' parameter with the following values: +-- 'stored', 'none', and the default (no value specified), which defaults to +-- 'stored'. +SET client_min_messages = 'ERROR'; +CREATE PUBLICATION pub1 FOR ALL TABLES WITH (publish_generated_columns = stored); +\dRp+ pub1 +CREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish_generated_columns = none); +\dRp+ pub2 +CREATE PUBLICATION pub3 FOR ALL TABLES WITH (publish_generated_columns); +\dRp+ pub3 + +DROP PUBLICATION pub1; +DROP PUBLICATION pub2; +DROP PUBLICATION pub3; +-- Test the 'publish_generated_columns' parameter as 'none' and 'stored' for +-- different scenarios with/without generated columns in column lists. +CREATE TABLE gencols (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); + +-- Generated columns in column list, when 'publish_generated_columns'='none' +CREATE PUBLICATION pub1 FOR table gencols(a, gen1) WITH (publish_generated_columns = none); +\dRp+ pub1 + +-- Generated columns in column list, when 'publish_generated_columns'='stored' +CREATE PUBLICATION pub2 FOR table gencols(a, gen1) WITH (publish_generated_columns = stored); +\dRp+ pub2 + +-- Generated columns in column list, then set 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET (publish_generated_columns = none); +\dRp+ pub2 + +-- Remove generated columns from column list, when 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET TABLE gencols(a); +\dRp+ pub2 + +-- Add generated columns in column list, when 'publish_generated_columns'='none' +ALTER PUBLICATION pub2 SET TABLE gencols(a, gen1); +\dRp+ pub2 + +DROP PUBLICATION pub1; +DROP PUBLICATION pub2; +DROP TABLE gencols; + +RESET client_min_messages; RESET SESSION AUTHORIZATION; DROP ROLE regress_publication_user, regress_publication_user2; DROP ROLE regress_publication_user_dummy; diff --git a/src/test/regress/sql/replica_identity.sql b/src/test/regress/sql/replica_identity.sql index 039cca25e8c34..30daec05b7134 100644 --- a/src/test/regress/sql/replica_identity.sql +++ b/src/test/regress/sql/replica_identity.sql @@ -100,6 +100,9 @@ ALTER TABLE test_replica_identity3 ALTER COLUMN id TYPE bigint; -- ALTER TABLE DROP NOT NULL is not allowed for columns part of an index -- used as replica identity. ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL; +-- but it's OK when the identity is FULL +ALTER TABLE test_replica_identity3 REPLICA IDENTITY FULL; +ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL; -- -- Test that replica identity can be set on an index that's not yet valid. @@ -120,9 +123,21 @@ ALTER INDEX test_replica_identity4_pkey ATTACH PARTITION test_replica_identity4_1_pkey; \d+ test_replica_identity4 +-- Dropping the primary key is not allowed if that would leave the replica +-- identity as nullable +CREATE TABLE test_replica_identity5 (a int not null, b int, c int, + PRIMARY KEY (b, c)); +CREATE UNIQUE INDEX test_replica_identity5_a_b_key ON test_replica_identity5 (a, b); +ALTER TABLE test_replica_identity5 REPLICA IDENTITY USING INDEX test_replica_identity5_a_b_key; +ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey; +ALTER TABLE test_replica_identity5 ALTER b SET NOT NULL; +ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey; +ALTER TABLE test_replica_identity5 ALTER b DROP NOT NULL; + DROP TABLE test_replica_identity; DROP TABLE test_replica_identity2; DROP TABLE test_replica_identity3; DROP TABLE test_replica_identity4; +DROP TABLE test_replica_identity5; DROP TABLE test_replica_identity_othertable; DROP TABLE test_replica_identity_t3; diff --git a/src/test/regress/sql/returning.sql b/src/test/regress/sql/returning.sql index a460f82fb7c84..cc99cb53f63c4 100644 --- a/src/test/regress/sql/returning.sql +++ b/src/test/regress/sql/returning.sql @@ -132,6 +132,30 @@ DELETE FROM foo WHERE f2 = 'zit' RETURNING *; SELECT * FROM foo; SELECT * FROM voo; +-- Check use of a whole-row variable for an un-flattenable view +CREATE TEMP VIEW foo_v AS SELECT * FROM foo OFFSET 0; +UPDATE foo SET f2 = foo_v.f2 FROM foo_v WHERE foo_v.f1 = foo.f1 + RETURNING foo_v; +SELECT * FROM foo; + +-- Check use of a whole-row variable for an inlined set-returning function +CREATE FUNCTION foo_f() RETURNS SETOF foo AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; +SELECT * FROM foo; +DROP FUNCTION foo_f(); + +-- As above, but SRF is defined to return a composite type +CREATE TYPE foo_t AS (f1 int, f2 text, f3 int, f4 int8); +CREATE FUNCTION foo_f() RETURNS SETOF foo_t AS + $$ SELECT * FROM foo OFFSET 0 $$ LANGUAGE sql STABLE; +UPDATE foo SET f2 = foo_f.f2 FROM foo_f() WHERE foo_f.f1 = foo.f1 + RETURNING foo_f; +SELECT * FROM foo; +DROP FUNCTION foo_f(); +DROP TYPE foo_t; + -- Try a join case CREATE TEMP TABLE joinme (f2j text, other int); @@ -160,3 +184,227 @@ INSERT INTO foo AS bar DEFAULT VALUES RETURNING *; -- ok INSERT INTO foo AS bar DEFAULT VALUES RETURNING foo.*; -- fails, wrong name INSERT INTO foo AS bar DEFAULT VALUES RETURNING bar.*; -- ok INSERT INTO foo AS bar DEFAULT VALUES RETURNING bar.f3; -- ok + +-- +-- Test RETURNING OLD/NEW. +-- +-- Start with new data, to ensure predictable TIDs. +-- +TRUNCATE foo; +INSERT INTO foo VALUES (1, 'xxx', 10, 20), (2, 'more', 42, 141), (3, 'zoo2', 57, 99); + +-- Error cases +INSERT INTO foo DEFAULT VALUES RETURNING WITH (nonsuch AS something) *; +INSERT INTO foo DEFAULT VALUES RETURNING WITH (new AS foo) *; +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS o, new AS n, old AS o) *; +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS o, new AS n, new AS n) *; +INSERT INTO foo DEFAULT VALUES RETURNING WITH (old AS x, new AS x) *; + +-- INSERT has NEW, but not OLD +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (4) + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; +INSERT INTO foo VALUES (4) + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +-- INSERT ... ON CONFLICT ... UPDATE has OLD and NEW +CREATE UNIQUE INDEX foo_f1_idx ON foo (f1); +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (4, 'conflict'), (5, 'ok') + ON CONFLICT (f1) DO UPDATE SET f2 = excluded.f2||'ed', f3 = -1 + RETURNING WITH (OLD AS o, NEW AS n) + o.tableoid::regclass, o.ctid, o.*, + n.tableoid::regclass, n.ctid, n.*, *; +INSERT INTO foo VALUES (4, 'conflict'), (5, 'ok') + ON CONFLICT (f1) DO UPDATE SET f2 = excluded.f2||'ed', f3 = -1 + RETURNING WITH (OLD AS o, NEW AS n) + o.tableoid::regclass, o.ctid, o.*, + n.tableoid::regclass, n.ctid, n.*, *; + +-- UPDATE has OLD and NEW +EXPLAIN (verbose, costs off) +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, old, + new.tableoid::regclass, new.ctid, new.*, new, + old.f4::text||'->'||new.f4::text AS change; +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, old, + new.tableoid::regclass, new.ctid, new.*, new, + old.f4::text||'->'||new.f4::text AS change; + +-- DELETE has OLD, but not NEW +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; +DELETE FROM foo WHERE f1 = 5 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +-- RETURNING OLD and NEW from subquery +EXPLAIN (verbose, costs off) +INSERT INTO foo VALUES (5, 'subquery test') + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; +INSERT INTO foo VALUES (5, 'subquery test') + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + +EXPLAIN (verbose, costs off) +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING (SELECT old.f4 = new.f4), + (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; +UPDATE foo SET f4 = 100 WHERE f1 = 5 + RETURNING (SELECT old.f4 = new.f4), + (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 5 + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; +DELETE FROM foo WHERE f1 = 5 + RETURNING (SELECT max(old.f4 + x) FROM generate_series(1, 10) x) old_max, + (SELECT max(new.f4 + x) FROM generate_series(1, 10) x) new_max; + +-- DELETE turned into UPDATE by a rule has OLD and NEW +CREATE RULE foo_del_rule AS ON DELETE TO foo DO INSTEAD + UPDATE foo SET f2 = f2||' (deleted)', f3 = -1, f4 = -1 WHERE f1 = OLD.f1 + RETURNING *; +EXPLAIN (verbose, costs off) +DELETE FROM foo WHERE f1 = 4 RETURNING old.*,new.*, *; +DELETE FROM foo WHERE f1 = 4 RETURNING old.*,new.*, *; + +-- UPDATE on view with rule +EXPLAIN (verbose, costs off) +UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; +UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; + +-- UPDATE on view with INSTEAD OF trigger +CREATE FUNCTION joinview_upd_trig_fn() RETURNS trigger +LANGUAGE plpgsql AS +$$ +BEGIN + RAISE NOTICE 'UPDATE: % -> %', old, new; + UPDATE foo SET f1 = new.f1, f3 = new.f3, f4 = new.f4 * 10 + FROM joinme WHERE f2 = f2j AND f2 = old.f2 + RETURNING new.f1, new.f4 INTO new.f1, new.f4; -- should fail + RETURN NEW; +END; +$$; +CREATE TRIGGER joinview_upd_trig INSTEAD OF UPDATE ON joinview + FOR EACH ROW EXECUTE FUNCTION joinview_upd_trig_fn(); +DROP RULE joinview_u ON joinview; +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; -- should fail + +CREATE OR REPLACE FUNCTION joinview_upd_trig_fn() RETURNS trigger +LANGUAGE plpgsql AS +$$ +BEGIN + RAISE NOTICE 'UPDATE: % -> %', old, new; + UPDATE foo SET f1 = new.f1, f3 = new.f3, f4 = new.f4 * 10 + FROM joinme WHERE f2 = f2j AND f2 = old.f2 + RETURNING WITH (new AS n) new.f1, n.f4 INTO new.f1, new.f4; -- now ok + RETURN NEW; +END; +$$; +EXPLAIN (verbose, costs off) +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; +UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 + RETURNING old.*, new.*, *, new.f3 - old.f3 AS delta_f3; -- should succeed + +-- Test wholerow & dropped column handling +ALTER TABLE foo DROP COLUMN f3 CASCADE; +UPDATE foo SET f4 = f4 + 1 RETURNING old.f3; -- should fail +UPDATE foo SET f4 = f4 + 1 RETURNING old, new; + +-- INSERT/DELETE on zero column table +CREATE TABLE zerocol(); +INSERT INTO zerocol SELECT RETURNING old.*, new.*, *; +INSERT INTO zerocol SELECT + RETURNING old.tableoid::regclass, old.ctid, + new.tableoid::regclass, new.ctid, ctid, *; +DELETE FROM zerocol + RETURNING old.tableoid::regclass, old.ctid, + new.tableoid::regclass, new.ctid, ctid, *; +DROP TABLE zerocol; + +-- Test schema-qualified table name in RETURNING list +CREATE TABLE public.tt(a int, b int); +INSERT INTO public.tt VALUES (1, 10); +UPDATE public.tt SET b = b * 2 RETURNING a, b, old.b, new.b, tt.b, public.tt.b; +DROP TABLE public.tt; + +-- Test cross-partition updates and attribute mapping +CREATE TABLE foo_parted (a int, b float8, c text) PARTITION BY LIST (a); +CREATE TABLE foo_part_s1 PARTITION OF foo_parted FOR VALUES IN (1); +CREATE TABLE foo_part_s2 PARTITION OF foo_parted FOR VALUES IN (2); +CREATE TABLE foo_part_d1 (c text, a int, b float8); +ALTER TABLE foo_parted ATTACH PARTITION foo_part_d1 FOR VALUES IN (3); +CREATE TABLE foo_part_d2 (b float8, c text, a int); +ALTER TABLE foo_parted ATTACH PARTITION foo_part_d2 FOR VALUES IN (4); + +INSERT INTO foo_parted + VALUES (1, 17.1, 'P1'), (2, 17.2, 'P2'), (3, 17.3, 'P3'), (4, 17.4, 'P4') + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +UPDATE foo_parted SET a = 2, b = b + 1, c = c || '->P2' WHERE a = 1 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +UPDATE foo_parted SET a = 1, b = b + 1, c = c || '->P1' WHERE a = 3 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +UPDATE foo_parted SET a = 3, b = b + 1, c = c || '->P3' WHERE a = 1 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +UPDATE foo_parted SET a = 4, b = b + 1, c = c || '->P4' WHERE a = 3 + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +-- cross-partition update that uses ReturningExpr nodes, without returning +-- old/new table values +CREATE VIEW foo_parted_v AS SELECT *, 'xxx' AS dummy FROM foo_parted; +UPDATE foo_parted_v SET a = 1, c = c || '->P1' WHERE a = 2 AND c = 'P2' + RETURNING 'P2:'||old.dummy, 'P1:'||new.dummy; + +DELETE FROM foo_parted + RETURNING old.tableoid::regclass, old.ctid, old.*, + new.tableoid::regclass, new.ctid, new.*, *; + +DROP TABLE foo_parted CASCADE; + +-- Test deparsing +CREATE FUNCTION foo_update() + RETURNS void + LANGUAGE sql +BEGIN ATOMIC + WITH u1 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING old.*, new.* + ), u2 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING WITH (OLD AS "old foo") "old foo".*, new.* + ), u3 AS ( + UPDATE foo SET f1 = f1 + 1 RETURNING WITH (NEW AS "new foo") old.*, "new foo".* + ) + UPDATE foo SET f1 = f1 + 1 + RETURNING WITH (OLD AS o, NEW AS n) + o.*, n.*, o, n, o.f1 = n.f1, o = n, + (SELECT o.f2 = n.f2), + (SELECT count(*) FROM foo WHERE foo.f1 = o.f4), + (SELECT count(*) FROM foo WHERE foo.f4 = n.f4), + (SELECT count(*) FROM foo WHERE foo = o), + (SELECT count(*) FROM foo WHERE foo = n); +END; + +\sf foo_update +DROP FUNCTION foo_update; diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql index 3011d71b12be5..9da967a9ef2f5 100644 --- a/src/test/regress/sql/rowsecurity.sql +++ b/src/test/regress/sql/rowsecurity.sql @@ -2072,6 +2072,33 @@ INSERT INTO r1 VALUES (10) DROP TABLE r1; +-- +-- Test policies using virtual generated columns +-- +SET SESSION AUTHORIZATION regress_rls_alice; +SET row_security = on; +CREATE TABLE r1 (a int, b int GENERATED ALWAYS AS (a * 10) VIRTUAL); +ALTER TABLE r1 ADD c int GENERATED ALWAYS AS (a * 100) VIRTUAL; +INSERT INTO r1 VALUES (1), (2), (4); + +CREATE POLICY p0 ON r1 USING (b * 10 = c); +CREATE POLICY p1 ON r1 AS RESTRICTIVE USING (b > 10); +CREATE POLICY p2 ON r1 AS RESTRICTIVE USING ((SELECT c) < 400); +ALTER TABLE r1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE r1 FORCE ROW LEVEL SECURITY; + +-- Should fail p1 +INSERT INTO r1 VALUES (0); + +-- Should fail p2 +INSERT INTO r1 VALUES (4); + +-- OK +INSERT INTO r1 VALUES (3); +SELECT * FROM r1; + +DROP TABLE r1; + -- Check dependency handling RESET SESSION AUTHORIZATION; CREATE TABLE dep1 (c1 int); @@ -2177,6 +2204,7 @@ CREATE FUNCTION op_leak(int, int) RETURNS bool CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); SELECT * FROM rls_tbl WHERE a <<< 1000; +EXPLAIN (COSTS OFF) SELECT * FROM rls_tbl WHERE a <<< 1000 or a <<< 900; DROP OPERATOR <<< (int, int); DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; @@ -2217,10 +2245,112 @@ execute q; set role regress_rls_bob; execute q; +-- make sure RLS dependencies in CTEs are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ with cte as (select * from rls_t) select * from cte $$; +prepare r as select current_user, * from rls_f(); +set role regress_rls_alice; +execute r; +set role regress_rls_bob; +execute r; + +-- make sure RLS dependencies in subqueries are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select * from rls_t) _ $$; +prepare s as select current_user, * from rls_f(); +set role regress_rls_alice; +execute s; +set role regress_rls_bob; +execute s; + +-- make sure RLS dependencies in sublinks are handled +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select exists(select * from rls_t)::text $$; +prepare t as select current_user, * from rls_f(); +set role regress_rls_alice; +execute t; +set role regress_rls_bob; +execute t; + +-- make sure RLS dependencies are handled when coercion projections are inserted +reset role; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from (select array_agg(c) as cs from rls_t) _ group by cs $$; +prepare u as select current_user, * from rls_f(); +set role regress_rls_alice; +execute u; +set role regress_rls_bob; +execute u; + +-- make sure RLS dependencies in security invoker views are handled +reset role; +create view rls_v with (security_invoker) as select * from rls_t; +grant select on rls_v to regress_rls_alice, regress_rls_bob; +create or replace function rls_f() returns setof rls_t + stable language sql + as $$ select * from rls_v $$; +prepare v as select current_user, * from rls_f(); +set role regress_rls_alice; +execute v; +set role regress_rls_bob; +execute v; + RESET ROLE; DROP FUNCTION rls_f(); +DROP VIEW rls_v; DROP TABLE rls_t; +-- Check that RLS changes invalidate SQL function plans +create table rls_t (c text); +create table test_t (c text); +insert into rls_t values ('a'), ('b'), ('c'), ('d'); +insert into test_t values ('a'), ('b'); +alter table rls_t enable row level security; +grant select on rls_t to regress_rls_alice; +grant select on test_t to regress_rls_alice; +create policy p1 on rls_t for select to regress_rls_alice + using (c = current_setting('rls_test.blah')); + +-- Function changes row_security setting and so invalidates plan +create function rls_f(text) returns text +begin atomic + select set_config('rls_test.blah', $1, true) || set_config('row_security', 'false', true) || string_agg(c, ',' order by c) from rls_t; +end; + +set plan_cache_mode to force_custom_plan; + +-- Table owner bypasses RLS +select rls_f(c) from test_t order by rls_f; + +-- For other users, changes in row_security setting +-- should lead to RLS error during query rewrite +set role regress_rls_alice; +select rls_f(c) from test_t order by rls_f; +reset role; + +set plan_cache_mode to force_generic_plan; + +-- Table owner bypasses RLS, although cached plan will be invalidated +select rls_f(c) from test_t order by rls_f; + +-- For other users, changes in row_security setting +-- should lead to plan invalidation and RLS error during query rewrite +set role regress_rls_alice; +select rls_f(c) from test_t order by rls_f; +reset role; + +reset plan_cache_mode; +reset rls_test.blah; +drop function rls_f(text); +drop table rls_t, test_t; + -- -- Clean up objects -- diff --git a/src/test/regress/sql/rowtypes.sql b/src/test/regress/sql/rowtypes.sql index fd47dc9e0f674..174b062144a2d 100644 --- a/src/test/regress/sql/rowtypes.sql +++ b/src/test/regress/sql/rowtypes.sql @@ -520,6 +520,27 @@ where (select * from (select c as c1) s select pg_get_viewdef('composite_v', true); drop view composite_v; +-- +-- Check cases where the composite comes from a proven-dummy rel (bug #18576) +-- +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss; +explain (verbose, costs off) +select (ss.a).x, (ss.a).n from + (select information_schema._pg_expandarray(array[1,2]) AS a) ss +where false; + +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t; +explain (verbose, costs off) +with cte(c) as materialized (select row(1, 2)), + cte2(c) as (select * from cte) +select (c).f1 from cte2 as t +where false; + -- -- Tests for component access / FieldSelect -- diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index 4a5fa50585573..fdd3ff1d161c1 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -1294,7 +1294,10 @@ MERGE INTO rule_merge1 t USING (SELECT 1 AS a) s CREATE TABLE sf_target(id int, data text, filling int[]); CREATE FUNCTION merge_sf_test() - RETURNS TABLE(action text, a int, b text, id int, data text, filling int[]) + RETURNS TABLE(action text, a int, b text, + id int, data text, filling int[], + old_id int, old_data text, old_filling int[], + new_id int, new_data text, new_filling int[]) LANGUAGE sql BEGIN ATOMIC MERGE INTO sf_target t @@ -1333,7 +1336,8 @@ WHEN NOT MATCHED THEN INSERT (filling[1], id) VALUES (s.a, s.a) RETURNING - merge_action() AS action, *; + WITH (OLD AS o, NEW AS n) + merge_action() AS action, *, o.*, n.*; END; \sf merge_sf_test diff --git a/src/test/regress/sql/select.sql b/src/test/regress/sql/select.sql index 019f1e767398d..1d1bf2b9310aa 100644 --- a/src/test/regress/sql/select.sql +++ b/src/test/regress/sql/select.sql @@ -196,7 +196,7 @@ explain (costs off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; -- actually run the query with an analyze to use the partial index -explain (costs off, analyze on, timing off, summary off) +explain (costs off, analyze on, timing off, summary off, buffers off) select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; explain (costs off) select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA'; diff --git a/src/test/regress/sql/select_distinct.sql b/src/test/regress/sql/select_distinct.sql index da92c197aba5c..50ac7dde396c6 100644 --- a/src/test/regress/sql/select_distinct.sql +++ b/src/test/regress/sql/select_distinct.sql @@ -221,3 +221,56 @@ SELECT 1 IS NOT DISTINCT FROM 2 as "no"; SELECT 2 IS NOT DISTINCT FROM 2 as "yes"; SELECT 2 IS NOT DISTINCT FROM null as "no"; SELECT null IS NOT DISTINCT FROM null as "yes"; + +-- +-- Test the planner's ability to reorder the distinctClause Pathkeys to match +-- the input path's ordering +-- + +CREATE TABLE distinct_tbl (x int, y int); +INSERT INTO distinct_tbl SELECT i%10, i%10 FROM generate_series(1, 1000) AS i; +CREATE INDEX distinct_tbl_x_y_idx ON distinct_tbl (x, y); +ANALYZE distinct_tbl; + +-- Produce results with sorting. +SET enable_hashagg TO OFF; + +-- Ensure we avoid the need to re-sort by reordering the distinctClause +-- Pathkeys to match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl; +SELECT DISTINCT y, x FROM distinct_tbl; + +-- Ensure we leverage incremental-sort by reordering the distinctClause +-- Pathkeys to partially match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM (SELECT * FROM distinct_tbl ORDER BY x) s; +SELECT DISTINCT y, x FROM (SELECT * FROM distinct_tbl ORDER BY x) s; + +-- Ensure we avoid the need to re-sort in partial distinct by reordering the +-- distinctClause Pathkeys to match the ordering of the input path +SET parallel_tuple_cost=0; +SET parallel_setup_cost=0; +SET min_parallel_table_scan_size=0; +SET min_parallel_index_scan_size=0; +SET max_parallel_workers_per_gather=2; + +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl limit 10; +SELECT DISTINCT y, x FROM distinct_tbl limit 10; + +RESET max_parallel_workers_per_gather; +RESET min_parallel_index_scan_size; +RESET min_parallel_table_scan_size; +RESET parallel_setup_cost; +RESET parallel_tuple_cost; + +-- Ensure we reorder the distinctClause Pathkeys to match the ordering of the +-- input path even if there is ORDER BY clause +EXPLAIN (COSTS OFF) +SELECT DISTINCT y, x FROM distinct_tbl ORDER BY y; +SELECT DISTINCT y, x FROM distinct_tbl ORDER BY y; + +RESET enable_hashagg; + +DROP TABLE distinct_tbl; diff --git a/src/test/regress/sql/select_distinct_on.sql b/src/test/regress/sql/select_distinct_on.sql index 261e6140feb15..8680749e49add 100644 --- a/src/test/regress/sql/select_distinct_on.sql +++ b/src/test/regress/sql/select_distinct_on.sql @@ -42,3 +42,43 @@ SELECT DISTINCT ON (four) four,two EXPLAIN (COSTS OFF) SELECT DISTINCT ON (four) four,hundred FROM tenk1 WHERE four = 0 ORDER BY 1,2; + +-- +-- Test the planner's ability to reorder the distinctClause Pathkeys to match +-- the input path's ordering +-- + +CREATE TABLE distinct_on_tbl (x int, y int, z int); +INSERT INTO distinct_on_tbl SELECT i%10, i%10, i%10 FROM generate_series(1, 1000) AS i; +CREATE INDEX distinct_on_tbl_x_y_idx ON distinct_on_tbl (x, y); +ANALYZE distinct_on_tbl; + +-- Produce results with sorting. +SET enable_hashagg TO OFF; + +-- Ensure we avoid the need to re-sort by reordering the distinctClause +-- Pathkeys to match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl; +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl; + +-- Ensure we leverage incremental-sort by reordering the distinctClause +-- Pathkeys to partially match the ordering of the input path +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM (SELECT * FROM distinct_on_tbl ORDER BY x) s; +SELECT DISTINCT ON (y, x) x, y FROM (SELECT * FROM distinct_on_tbl ORDER BY x) s; + +-- Ensure we reorder the distinctClause Pathkeys to match the ordering of the +-- input path even if there is ORDER BY clause +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl ORDER BY y; +SELECT DISTINCT ON (y, x) x, y FROM distinct_on_tbl ORDER BY y; + +-- Ensure the resulting pathkey list matches the initial distinctClause Pathkeys +EXPLAIN (COSTS OFF) +SELECT DISTINCT ON (y, x) x, y FROM (select * from distinct_on_tbl order by x, z, y) s ORDER BY y, x, z; +SELECT DISTINCT ON (y, x) x, y FROM (select * from distinct_on_tbl order by x, z, y) s ORDER BY y, x, z; + +RESET enable_hashagg; + +DROP TABLE distinct_on_tbl; diff --git a/src/test/regress/sql/select_into.sql b/src/test/regress/sql/select_into.sql index 689c448cc20f2..f71e3940e0adf 100644 --- a/src/test/regress/sql/select_into.sql +++ b/src/test/regress/sql/select_into.sql @@ -30,26 +30,26 @@ SET SESSION AUTHORIZATION regress_selinto_user; CREATE TABLE selinto_schema.tbl_withdata1 (a) AS SELECT generate_series(1,3) WITH DATA; INSERT INTO selinto_schema.tbl_withdata1 VALUES (4); -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_withdata2 (a) AS SELECT generate_series(1,3) WITH DATA; -- WITH NO DATA, passes. CREATE TABLE selinto_schema.tbl_nodata1 (a) AS SELECT generate_series(1,3) WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_nodata2 (a) AS SELECT generate_series(1,3) WITH NO DATA; -- EXECUTE and WITH DATA, passes. PREPARE data_sel AS SELECT generate_series(1,3); CREATE TABLE selinto_schema.tbl_withdata3 (a) AS EXECUTE data_sel WITH DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_withdata4 (a) AS EXECUTE data_sel WITH DATA; -- EXECUTE and WITH NO DATA, passes. CREATE TABLE selinto_schema.tbl_nodata3 (a) AS EXECUTE data_sel WITH NO DATA; -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) CREATE TABLE selinto_schema.tbl_nodata4 (a) AS EXECUTE data_sel WITH NO DATA; RESET SESSION AUTHORIZATION; diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql index c7df8f775cee9..71a75bc86ea76 100644 --- a/src/test/regress/sql/select_parallel.sql +++ b/src/test/regress/sql/select_parallel.sql @@ -2,6 +2,13 @@ -- PARALLEL -- +-- Save parallel worker stats, used for comparison at the end +select pg_stat_force_next_flush(); +select parallel_workers_to_launch as parallel_workers_to_launch_before, + parallel_workers_launched as parallel_workers_launched_before + from pg_stat_database + where datname = current_database() \gset + create function sp_parallel_restricted(int) returns int as $$begin return $1; end$$ language plpgsql parallel restricted; @@ -223,7 +230,7 @@ select count(*) from bmscantest where a>1; -- test accumulation of stats for parallel nodes reset enable_seqscan; alter table tenk2 set (parallel_workers = 0); -explain (analyze, timing off, summary off, costs off) +explain (analyze, timing off, summary off, costs off, buffers off) select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0; alter table tenk2 reset (parallel_workers); @@ -235,7 +242,7 @@ $$ declare ln text; begin for ln in - explain (analyze, timing off, summary off, costs off) + explain (analyze, timing off, summary off, costs off, buffers off) select * from (select ten from tenk1 where ten < 100 order by ten) ss right join (values (1),(2),(3)) v(x) on true @@ -443,7 +450,7 @@ explain (costs off) -- to increase the parallel query test coverage SAVEPOINT settings; SET LOCAL debug_parallel_query = 1; -EXPLAIN (analyze, timing off, summary off, costs off) SELECT * FROM tenk1; +EXPLAIN (analyze, timing off, summary off, costs off, buffers off) SELECT * FROM tenk1; ROLLBACK TO SAVEPOINT settings; -- provoke error in worker @@ -511,3 +518,73 @@ SELECT 1 FROM tenk1_vw_sec WHERE (SELECT sum(f1) FROM int4_tbl WHERE f1 < unique1) < 100; rollback; + +-- test that a newly-created session role propagates to workers. +begin; +create role regress_parallel_worker; +set session authorization regress_parallel_worker; +select current_setting('session_authorization'); +set debug_parallel_query = 1; +select current_setting('session_authorization'); +rollback; + +-- test that function option SET ROLE works in parallel workers. +create role regress_parallel_worker; + +create function set_and_report_role() returns text as + $$ select current_setting('role') $$ language sql parallel safe + set role = regress_parallel_worker; + +create function set_role_and_error(int) returns int as + $$ select 1 / $1 $$ language sql parallel safe + set role = regress_parallel_worker; + +set debug_parallel_query = 0; +select set_and_report_role(); +select set_role_and_error(0); +set debug_parallel_query = 1; +select set_and_report_role(); +select set_role_and_error(0); +reset debug_parallel_query; + +drop function set_and_report_role(); +drop function set_role_and_error(int); +drop role regress_parallel_worker; + +-- don't freeze in ParallelFinish while holding an LWLock +BEGIN; + +CREATE FUNCTION my_cmp (int4, int4) +RETURNS int LANGUAGE sql AS +$$ + SELECT + CASE WHEN $1 < $2 THEN -1 + WHEN $1 > $2 THEN 1 + ELSE 0 + END; +$$; + +CREATE TABLE parallel_hang (i int4); +INSERT INTO parallel_hang + (SELECT * FROM generate_series(1, 400) gs); + +CREATE OPERATOR CLASS int4_custom_ops FOR TYPE int4 USING btree AS + OPERATOR 1 < (int4, int4), OPERATOR 2 <= (int4, int4), + OPERATOR 3 = (int4, int4), OPERATOR 4 >= (int4, int4), + OPERATOR 5 > (int4, int4), FUNCTION 1 my_cmp(int4, int4); + +CREATE UNIQUE INDEX parallel_hang_idx + ON parallel_hang + USING btree (i int4_custom_ops); + +SET debug_parallel_query = on; +DELETE FROM parallel_hang WHERE 380 <= i AND i <= 420; + +ROLLBACK; + +-- Check parallel worker stats +select pg_stat_force_next_flush(); +select parallel_workers_to_launch > :'parallel_workers_to_launch_before' AS wrk_to_launch, + parallel_workers_launched > :'parallel_workers_launched_before' AS wrk_launched + from pg_stat_database + where datname = current_database(); diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql index 674f5f1f66818..2c220b60749ea 100644 --- a/src/test/regress/sql/sequence.sql +++ b/src/test/regress/sql/sequence.sql @@ -413,4 +413,7 @@ SELECT nextval('test_seq1'); SELECT nextval('test_seq1'); SELECT nextval('test_seq1'); +-- pg_get_sequence_data +SELECT * FROM pg_get_sequence_data('test_seq1'); + DROP SEQUENCE test_seq1; diff --git a/src/test/regress/sql/sqljson.sql b/src/test/regress/sql/sqljson.sql index bb2487e86495d..343d344d2707f 100644 --- a/src/test/regress/sql/sqljson.sql +++ b/src/test/regress/sql/sqljson.sql @@ -138,6 +138,8 @@ SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2); SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 NULL ON NULL); SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 ABSENT ON NULL); +SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, repeat('x', 1000): 1, 2: repeat('a', 100) WITH UNIQUE); + SELECT JSON_OBJECT(1: 1, '1': NULL WITH UNIQUE); SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE); SELECT JSON_OBJECT(1: 1, '1': NULL NULL ON NULL WITH UNIQUE RETURNING jsonb); @@ -150,6 +152,17 @@ SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE RETURNING SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE RETURNING jsonb); SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WITH UNIQUE RETURNING jsonb); +-- BUG: https://postgr.es/m/CADXhmgTJtJZK9A3Na_ry%2BXrq-ghjcejBRhcRMzWZvbd__QdgJA%40mail.gmail.com +-- datum_to_jsonb_internal() didn't catch keys that are casts instead of a simple scalar +CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral'); +CREATE FUNCTION mood_to_json(mood) RETURNS json AS $$ + SELECT to_json($1::text); +$$ LANGUAGE sql IMMUTABLE; +CREATE CAST (mood AS json) WITH FUNCTION mood_to_json(mood) AS IMPLICIT; +SELECT JSON_OBJECT('happy'::mood: '123'::jsonb); +DROP CAST (mood AS json); +DROP FUNCTION mood_to_json; +DROP TYPE mood; -- JSON_ARRAY() SELECT JSON_ARRAY(); @@ -186,6 +199,8 @@ SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL) --SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL); --SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL RETURNING jsonb); SELECT JSON_ARRAY(SELECT i FROM (VALUES (3), (1), (NULL), (2)) foo(i) ORDER BY i); +SELECT JSON_ARRAY(WITH x AS (SELECT 1) VALUES (TRUE)); + -- Should fail SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i)); SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i)); @@ -283,6 +298,9 @@ FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v); SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS RETURNING jsonb) FROM (VALUES (1, 1), (0, NULL),(4, null), (5, null),(6, null),(2, 2)) foo(k, v); +SELECT JSON_OBJECTAGG(mod(i,100): (i)::text FORMAT JSON WITH UNIQUE) +FROM generate_series(0, 199) i; + -- Test JSON_OBJECT deparsing EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json); @@ -475,3 +493,17 @@ SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING v CREATE DOMAIN sqljson_char2 AS char(2) CHECK (VALUE NOT IN ('12')); SELECT JSON_SERIALIZE('123' RETURNING sqljson_char2); SELECT JSON_SERIALIZE('12' RETURNING sqljson_char2); + +-- Bug #18657: JsonValueExpr.raw_expr was not initialized in ExecInitExprRec() +-- causing the Aggrefs contained in it to also not be initialized, which led +-- to a crash in ExecBuildAggTrans() as mentioned in the bug report: +-- https://postgr.es/m/18657-1b90ccce2b16bdb8@postgresql.org +CREATE FUNCTION volatile_one() RETURNS int AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql VOLATILE; +CREATE FUNCTION stable_one() RETURNS int AS $$ BEGIN RETURN 1; END; $$ LANGUAGE plpgsql STABLE; +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': volatile_one() RETURNING text) FORMAT JSON); +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': volatile_one() RETURNING text) FORMAT JSON); +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': stable_one() RETURNING text) FORMAT JSON); +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': stable_one() RETURNING text) FORMAT JSON); +EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': 1 RETURNING text) FORMAT JSON); +SELECT JSON_OBJECT('a': JSON_OBJECTAGG('b': 1 RETURNING text) FORMAT JSON); +DROP FUNCTION volatile_one, stable_one; diff --git a/src/test/regress/sql/sqljson_jsontable.sql b/src/test/regress/sql/sqljson_jsontable.sql index 4594e5b0138f9..154eea79c768a 100644 --- a/src/test/regress/sql/sqljson_jsontable.sql +++ b/src/test/regress/sql/sqljson_jsontable.sql @@ -262,14 +262,28 @@ SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'strict $.a' DEFAU SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'lax $.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt; -- JSON_TABLE: EXISTS PATH types -SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a')); +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a' ERROR ON ERROR)); -- ok; can cast to int4 +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$' ERROR ON ERROR)); -- ok; can cast to int4 SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2 EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8 EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4 EXISTS PATH '$.a')); -SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(5) EXISTS PATH '$.a')); +-- Default FALSE (ON ERROR) doesn't fit char(3) +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a')); +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a' ERROR ON ERROR)); +SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(5) EXISTS PATH '$.a' ERROR ON ERROR)); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXISTS PATH '$.a')); SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EXISTS PATH '$.a')); +-- EXISTS PATH domain over int +CREATE DOMAIN dint4 AS int; +CREATE DOMAIN dint4_0 AS int CHECK (VALUE <> 0 ); +SELECT a, a::bool FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a dint4 EXISTS PATH '$.a' )); +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b')); +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' ERROR ON ERROR)); +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' FALSE ON ERROR)); +SELECT a, a::bool FROM JSON_TABLE(jsonb '{"a":1}', '$' COLUMNS (a dint4_0 EXISTS PATH '$.b' TRUE ON ERROR)); +DROP DOMAIN dint4, dint4_0; + -- JSON_TABLE: WRAPPER/QUOTES clauses on scalar columns SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' KEEP QUOTES ON SCALAR STRING)); SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text PATH '$' OMIT QUOTES ON SCALAR STRING)); @@ -528,3 +542,22 @@ SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int) NULL ON ERROR); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int true on empty)); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int omit quotes true on error)); SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int exists empty object on error)); + +-- Test JSON_TABLE() column deparsing -- don't emit default ON ERROR / EMPTY +-- behavior +CREATE VIEW json_table_view8 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$')); +\sv json_table_view8; + +CREATE VIEW json_table_view9 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') ERROR ON ERROR); +\sv json_table_view9; + +DROP VIEW json_table_view8, json_table_view9; + +-- Test JSON_TABLE() deparsing -- don't emit default ON ERROR behavior +CREATE VIEW json_table_view8 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ON ERROR); +\sv json_table_view8; + +CREATE VIEW json_table_view9 AS SELECT * from JSON_TABLE('"a"', '$' COLUMNS (a text PATH '$') EMPTY ARRAY ON ERROR); +\sv json_table_view9; + +DROP VIEW json_table_view8, json_table_view9; diff --git a/src/test/regress/sql/sqljson_queryfuncs.sql b/src/test/regress/sql/sqljson_queryfuncs.sql index e9005d3d4eb0d..8d7b225b61217 100644 --- a/src/test/regress/sql/sqljson_queryfuncs.sql +++ b/src/test/regress/sql/sqljson_queryfuncs.sql @@ -146,11 +146,11 @@ select json_value('{"a": "1.234"}', '$.a' returning int error on error); SELECT JSON_VALUE(NULL::jsonb, '$'); SELECT - JSON_QUERY(js, '$'), - JSON_QUERY(js, '$' WITHOUT WRAPPER), - JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER), - JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER), - JSON_QUERY(js, '$' WITH ARRAY WRAPPER) + JSON_QUERY(js, '$') AS "unspec", + JSON_QUERY(js, '$' WITHOUT WRAPPER) AS "without", + JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER) AS "with cond", + JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER) AS "with uncond", + JSON_QUERY(js, '$' WITH ARRAY WRAPPER) AS "with" FROM (VALUES (jsonb 'null'), @@ -327,11 +327,11 @@ CREATE TABLE test_jsonb_constraints ( CONSTRAINT test_jsonb_constraint1 CHECK (js IS JSON) CONSTRAINT test_jsonb_constraint2 - CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS txt, array[1,2,3] as arr)) + CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS "TXT", array[1,2,3] as arr)) CONSTRAINT test_jsonb_constraint3 CHECK (JSON_VALUE(js::jsonb, '$.a' RETURNING int DEFAULT '12' ON EMPTY ERROR ON ERROR) > i) CONSTRAINT test_jsonb_constraint4 - CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < jsonb '[10]') + CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) = jsonb '[10]') CONSTRAINT test_jsonb_constraint5 CHECK (JSON_QUERY(js::jsonb, '$.a' RETURNING char(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > 'a' COLLATE "C") ); @@ -353,7 +353,6 @@ INSERT INTO test_jsonb_constraints VALUES ('1', 1); INSERT INTO test_jsonb_constraints VALUES ('[]'); INSERT INTO test_jsonb_constraints VALUES ('{"b": 1}', 1); INSERT INTO test_jsonb_constraints VALUES ('{"a": 1}', 1); -INSERT INTO test_jsonb_constraints VALUES ('{"a": 7}', 1); INSERT INTO test_jsonb_constraints VALUES ('{"a": 10}', 1); DROP TABLE test_jsonb_constraints; @@ -466,13 +465,17 @@ SELECT json_value('"aaa"', path RETURNING json) FROM jsonpaths; SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xy); SELECT JSON_QUERY(jsonb 'null', '$xy' PASSING 1 AS xyz); SELECT JSON_QUERY(jsonb 'null', '$xyz' PASSING 1 AS xyz); +SELECT JSON_QUERY(jsonb 'null', '$Xyz' PASSING 1 AS Xyz); +SELECT JSON_QUERY(jsonb 'null', '$Xyz' PASSING 1 AS "Xyz"); +SELECT JSON_QUERY(jsonb 'null', '$"Xyz"' PASSING 1 AS "Xyz"); -- Test ON ERROR / EMPTY value validity for the function; all fail. SELECT JSON_EXISTS(jsonb '1', '$' DEFAULT 1 ON ERROR); SELECT JSON_VALUE(jsonb '1', '$' EMPTY ON ERROR); SELECT JSON_QUERY(jsonb '1', '$' TRUE ON ERROR); --- Test implicit coercion domain over fixed-legth type specified in RETURNING +-- Test implicit coercion to a domain over fixed-length type specified in +-- RETURNING CREATE DOMAIN queryfuncs_char2 AS char(2); CREATE DOMAIN queryfuncs_char2_chk AS char(2) CHECK (VALUE NOT IN ('12')); SELECT JSON_QUERY(jsonb '123', '$' RETURNING queryfuncs_char2 ERROR ON ERROR); @@ -484,3 +487,16 @@ SELECT JSON_VALUE(jsonb '123', '$' RETURNING queryfuncs_char2 DEFAULT 1 ON ERROR SELECT JSON_VALUE(jsonb '123', '$' RETURNING queryfuncs_char2_chk ERROR ON ERROR); SELECT JSON_VALUE(jsonb '123', '$' RETURNING queryfuncs_char2_chk DEFAULT 1 ON ERROR); DROP DOMAIN queryfuncs_char2, queryfuncs_char2_chk; + +-- Test coercion to domain over another fixed-length type of the ON ERROR / +-- EMPTY expressions. Ask user to cast the DEFAULT expression explicitly if +-- automatic casting cannot be done, for example, from int to bit(2). +CREATE DOMAIN queryfuncs_d_varbit3 AS varbit(3) CHECK (VALUE <> '01'); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '111111' ON ERROR); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '010' ON ERROR); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING queryfuncs_d_varbit3 DEFAULT '01' ON ERROR); +SELECT JSON_VALUE(jsonb '"111"', '$' RETURNING bit(2) ERROR ON ERROR); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING bit(3) DEFAULT 1 ON ERROR); +SELECT JSON_VALUE(jsonb '1234', '$' RETURNING bit(3) DEFAULT 1::bit(3) ON ERROR); +SELECT JSON_VALUE(jsonb '"111"', '$.a' RETURNING bit(3) DEFAULT '1111' ON EMPTY); +DROP DOMAIN queryfuncs_d_varbit3; diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql index d8ac0d06f484d..232ab8db8fa8b 100644 --- a/src/test/regress/sql/stats.sql +++ b/src/test/regress/sql/stats.sql @@ -8,6 +8,12 @@ -- conditio sine qua non SHOW track_counts; -- must be on +-- List of backend types, contexts and objects tracked in pg_stat_io. +\a +SELECT backend_type, object, context FROM pg_stat_io + ORDER BY backend_type COLLATE "C", object COLLATE "C", context COLLATE "C"; +\a + -- ensure that both seqscan and indexscan plans are allowed SET enable_seqscan TO on; SET enable_indexscan TO on; @@ -420,9 +426,13 @@ SELECT sessions > :db_stat_sessions FROM pg_stat_database WHERE datname = (SELEC -- Test pg_stat_checkpointer checkpointer-related stats, together with pg_stat_wal SELECT num_requested AS rqst_ckpts_before FROM pg_stat_checkpointer \gset --- Test pg_stat_wal (and make a temp table so our temp schema exists) +-- Test pg_stat_wal SELECT wal_bytes AS wal_bytes_before FROM pg_stat_wal \gset +-- Test pg_stat_get_backend_wal() +SELECT wal_bytes AS backend_wal_bytes_before from pg_stat_get_backend_wal(pg_backend_pid()) \gset + +-- Make a temp table so our temp schema exists CREATE TEMP TABLE test_stats_temp AS SELECT 17; DROP TABLE test_stats_temp; @@ -435,6 +445,9 @@ CHECKPOINT; SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer; SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal; +SELECT pg_stat_force_next_flush(); +SELECT wal_bytes > :backend_wal_bytes_before FROM pg_stat_get_backend_wal(pg_backend_pid()); + -- Test pg_stat_get_backend_idset() and some allied functions. -- In particular, verify that their notion of backend ID matches -- our temp schema index. @@ -542,7 +555,7 @@ ROLLBACK; SELECT pg_stat_have_stats('bgwriter', 0, 0); -- unknown stats kinds error out SELECT pg_stat_have_stats('zaphod', 0, 0); --- db stats have objoid 0 +-- db stats have objid 0 SELECT pg_stat_have_stats('database', :dboid, 1); SELECT pg_stat_have_stats('database', :dboid, 0); @@ -595,32 +608,49 @@ SELECT pg_stat_get_replication_slot(NULL); SELECT pg_stat_get_subscription_stats(NULL); --- Test that the following operations are tracked in pg_stat_io: +-- Test that the following operations are tracked in pg_stat_io and in +-- backend stats: -- - reads of target blocks into shared buffers -- - writes of shared buffers to permanent storage -- - extends of relations using shared buffers -- - fsyncs done to ensure the durability of data dirtying shared buffers -- - shared buffer hits +-- - WAL writes and fsyncs in IOContext IOCONTEXT_NORMAL -- There is no test for blocks evicted from shared buffers, because we cannot -- be sure of the state of shared buffers at the point the test is run. -- Create a regular table and insert some data to generate IOCONTEXT_NORMAL -- extends. +SELECT pid AS checkpointer_pid FROM pg_stat_activity + WHERE backend_type = 'checkpointer' \gset SELECT sum(extends) AS io_sum_shared_before_extends FROM pg_stat_io WHERE context = 'normal' AND object = 'relation' \gset +SELECT sum(extends) AS my_io_sum_shared_before_extends + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE context = 'normal' AND object = 'relation' \gset SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs FROM pg_stat_io WHERE object = 'relation' \gset io_sum_shared_before_ +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE object = 'relation' \gset my_io_sum_shared_before_ +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_io + WHERE context = 'normal' AND object = 'wal' \gset io_sum_wal_normal_before_ CREATE TABLE test_io_shared(a int); INSERT INTO test_io_shared SELECT i FROM generate_series(1,100)i; SELECT pg_stat_force_next_flush(); SELECT sum(extends) AS io_sum_shared_after_extends FROM pg_stat_io WHERE context = 'normal' AND object = 'relation' \gset SELECT :io_sum_shared_after_extends > :io_sum_shared_before_extends; +SELECT sum(extends) AS my_io_sum_shared_after_extends + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE context = 'normal' AND object = 'relation' \gset +SELECT :my_io_sum_shared_after_extends > :my_io_sum_shared_before_extends; -- After a checkpoint, there should be some additional IOCONTEXT_NORMAL writes --- and fsyncs. +-- and fsyncs in the global stats (usually not for the backend). -- See comment above for rationale for two explicit CHECKPOINTs. CHECKPOINT; CHECKPOINT; @@ -630,6 +660,20 @@ SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs SELECT :io_sum_shared_after_writes > :io_sum_shared_before_writes; SELECT current_setting('fsync') = 'off' OR :io_sum_shared_after_fsyncs > :io_sum_shared_before_fsyncs; +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_get_backend_io(pg_backend_pid()) + WHERE object = 'relation' \gset my_io_sum_shared_after_ +SELECT :my_io_sum_shared_after_writes >= :my_io_sum_shared_before_writes; +SELECT current_setting('fsync') = 'off' + OR :my_io_sum_shared_after_fsyncs >= :my_io_sum_shared_before_fsyncs; +SELECT sum(writes) AS writes, sum(fsyncs) AS fsyncs + FROM pg_stat_io + WHERE context = 'normal' AND object = 'wal' \gset io_sum_wal_normal_after_ +SELECT current_setting('synchronous_commit') = 'on'; +SELECT :io_sum_wal_normal_after_writes > :io_sum_wal_normal_before_writes; +SELECT current_setting('fsync') = 'off' + OR current_setting('wal_sync_method') IN ('open_sync', 'open_datasync') + OR :io_sum_wal_normal_after_fsyncs > :io_sum_wal_normal_before_fsyncs; -- Change the tablespace so that the table is rewritten directly, then SELECT -- from it to cause it to be read back into shared buffers. @@ -762,11 +806,27 @@ SELECT :io_sum_bulkwrite_strategy_extends_after > :io_sum_bulkwrite_strategy_ext SELECT pg_stat_have_stats('io', 0, 0); SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_pre_reset FROM pg_stat_io \gset +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset SELECT pg_stat_reset_shared('io'); SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_post_reset FROM pg_stat_io \gset SELECT :io_stats_post_reset < :io_stats_pre_reset; - +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_post_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset +-- pg_stat_reset_shared() did not reset backend IO stats +SELECT :my_io_stats_pre_reset <= :my_io_stats_post_reset; +-- but pg_stat_reset_backend_stats() does +SELECT pg_stat_reset_backend_stats(pg_backend_pid()); +SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_post_backend_reset + FROM pg_stat_get_backend_io(pg_backend_pid()) \gset +SELECT :my_io_stats_pre_reset > :my_io_stats_post_backend_reset; + +-- Check invalid input for pg_stat_get_backend_io() +SELECT pg_stat_get_backend_io(NULL); +SELECT pg_stat_get_backend_io(0); +-- Auxiliary processes return no data. +SELECT pg_stat_get_backend_io(:checkpointer_pid); -- test BRIN index doesn't block HOT update CREATE TABLE brin_hot ( @@ -849,4 +909,20 @@ DROP TABLE brin_hot_3; SET enable_seqscan = on; +-- Test that estimation of relation size works with tuples wider than the +-- relation fillfactor. We create a table with wide inline attributes and +-- low fillfactor, insert rows and then see how many rows EXPLAIN shows +-- before running analyze. We disable autovacuum so that it does not +-- interfere with the test. +CREATE TABLE table_fillfactor ( + n char(1000) +) with (fillfactor=10, autovacuum_enabled=off); + +INSERT INTO table_fillfactor +SELECT 'x' FROM generate_series(1,1000); + +SELECT * FROM check_estimated_rows('SELECT * FROM table_fillfactor'); + +DROP TABLE table_fillfactor; + -- End of Stats Test diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index 0c08a6cc42e89..da4f2fe9c938f 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -45,6 +45,20 @@ CREATE STATISTICS tst ON (y) FROM ext_stats_test; -- single column reference CREATE STATISTICS tst ON y + z FROM ext_stats_test; -- missing parentheses CREATE STATISTICS tst ON (x, y) FROM ext_stats_test; -- tuple expression DROP TABLE ext_stats_test; +-- statistics on virtual generated column not allowed +CREATE TABLE ext_stats_test1 (x int, y int, z int GENERATED ALWAYS AS (x+y) VIRTUAL, w xid); +CREATE STATISTICS tst on z from ext_stats_test1; +CREATE STATISTICS tst on (z) from ext_stats_test1; +CREATE STATISTICS tst on (z+1) from ext_stats_test1; +CREATE STATISTICS tst (ndistinct) ON z from ext_stats_test1; +-- statistics on system column not allowed +CREATE STATISTICS tst on tableoid from ext_stats_test1; +CREATE STATISTICS tst on (tableoid) from ext_stats_test1; +CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test1; +CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test1; +-- statistics without a less-than operator not supported +CREATE STATISTICS tst (ndistinct) ON w from ext_stats_test1; +DROP TABLE ext_stats_test1; -- Ensure stats are dropped sanely, and test IF NOT EXISTS while at it CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER); @@ -1634,6 +1648,7 @@ CREATE FUNCTION op_leak(int, int) RETURNS bool CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied +SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 OR b <<< 0; DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied -- Grant access via a security barrier view, but hide all data @@ -1645,6 +1660,7 @@ GRANT SELECT, DELETE ON tststats.priv_test_view TO regress_stats_user1; -- Should now have access via the view, but see nothing and leak nothing SET SESSION AUTHORIZATION regress_stats_user1; SELECT * FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not leak +SELECT * FROM tststats.priv_test_view WHERE a <<< 0 OR b <<< 0; -- Should not leak DELETE FROM tststats.priv_test_view WHERE a <<< 0 AND b <<< 0; -- Should not leak -- Grant table access, but hide all data with RLS @@ -1655,6 +1671,7 @@ GRANT SELECT, DELETE ON tststats.priv_test_tbl TO regress_stats_user1; -- Should now have direct table access, but see nothing and leak nothing SET SESSION AUTHORIZATION regress_stats_user1; SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak +SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 OR b <<< 0; DELETE FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Should not leak -- privilege checks for pg_stats_ext and pg_stats_ext_exprs @@ -1690,3 +1707,55 @@ RESET SESSION AUTHORIZATION; DROP TABLE stats_ext_tbl; DROP SCHEMA tststats CASCADE; DROP USER regress_stats_user1; + +CREATE TABLE grouping_unique (x integer); +INSERT INTO grouping_unique (x) SELECT gs FROM generate_series(1,1000) AS gs; +ANALYZE grouping_unique; + +-- Optimiser treat GROUP-BY operator as an 'uniqueser' of the input +SELECT * FROM check_estimated_rows(' + SELECT * FROM generate_series(1, 1) t1 LEFT JOIN ( + SELECT x FROM grouping_unique t2 GROUP BY x) AS q1 + ON t1.t1 = q1.x; +'); +DROP TABLE grouping_unique; + +-- +-- Extended statistics on sb_2 (x, y, z) improve a bucket size estimation, +-- and the optimizer may choose hash join. +-- +CREATE TABLE sb_1 AS + SELECT gs % 10 AS x, gs % 10 AS y, gs % 10 AS z + FROM generate_series(1, 1e4) AS gs; +CREATE TABLE sb_2 AS + SELECT gs % 49 AS x, gs % 51 AS y, gs % 73 AS z, 'abc' || gs AS payload + FROM generate_series(1, 1e4) AS gs; +ANALYZE sb_1, sb_2; + +-- During hash join estimation, the number of distinct values on each column +-- is calculated. The optimizer selects the smallest number of distinct values +-- and the largest hash bucket size. The optimizer decides that the hash +-- bucket size is quite big because there are possibly many correlations. +EXPLAIN (COSTS OFF) -- Choose merge join +SELECT * FROM sb_1 a, sb_2 b WHERE a.x = b.x AND a.y = b.y AND a.z = b.z; + +-- The ndistinct extended statistics on (x, y, z) provides more reliable value +-- of bucket size. +CREATE STATISTICS extstat_sb_2 (ndistinct) ON x, y, z FROM sb_2; +ANALYZE sb_2; + +EXPLAIN (COSTS OFF) -- Choose hash join +SELECT * FROM sb_1 a, sb_2 b WHERE a.x = b.x AND a.y = b.y AND a.z = b.z; + +-- Check that the Hash Join bucket size estimator detects equal clauses correctly. +SET enable_nestloop = 'off'; +SET enable_mergejoin = 'off'; +EXPLAIN (COSTS OFF) +SELECT FROM sb_1 LEFT JOIN sb_2 ON (sb_2.x=sb_1.x) AND (sb_1.x=sb_2.x); +EXPLAIN (COSTS OFF) +SELECT FROM sb_1 LEFT JOIN sb_2 + ON (sb_2.x=sb_1.x) AND (sb_1.x=sb_2.x) AND (sb_1.y=sb_2.y); +RESET enable_nestloop; +RESET enable_mergejoin; + +DROP TABLE sb_1, sb_2 CASCADE; diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql new file mode 100644 index 0000000000000..d140733a75028 --- /dev/null +++ b/src/test/regress/sql/stats_import.sql @@ -0,0 +1,973 @@ +CREATE SCHEMA stats_import; + +CREATE TYPE stats_import.complex_type AS ( + a integer, + b real, + c text, + d date, + e jsonb); + +CREATE TABLE stats_import.test( + id INTEGER PRIMARY KEY, + name text, + comp stats_import.complex_type, + arange int4range, + tags text[] +) WITH (autovacuum_enabled = false); + +SELECT + pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', 18::integer, + 'reltuples', 21::real, + 'relallvisible', 24::integer, + 'relallfrozen', 27::integer); + +-- CREATE INDEX on a table with autovac disabled should not overwrite +-- stats +CREATE INDEX test_i ON stats_import.test(id); + +SELECT relname, relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass +ORDER BY relname; + +SELECT pg_clear_relation_stats('stats_import', 'test'); + +-- +-- relstats tests +-- + +-- error: schemaname missing +SELECT pg_catalog.pg_restore_relation_stats( + 'relname', 'test', + 'relpages', 17::integer); + +-- error: relname missing +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relpages', 17::integer); + +--- error: schemaname is wrong type +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 3.6::float, + 'relname', 'test', + 'relpages', 17::integer); + +--- error: relname is wrong type +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 0::oid, + 'relpages', 17::integer); + +-- error: relation not found +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'nope', + 'relpages', 17::integer); + +-- error: odd number of variadic arguments cannot be pairs +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relallvisible'); + +-- error: argument name is NULL +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + NULL, '17'::integer); + +-- starting stats +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test_i'::regclass; + +-- regular indexes have special case locking rules +BEGIN; +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test_i', + 'relpages', 18::integer); + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.test'::regclass AND + pid = pg_backend_pid() AND granted; + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.test_i'::regclass AND + pid = pg_backend_pid() AND granted; + +COMMIT; + +-- relpages may be -1 for partitioned tables +CREATE TABLE stats_import.part_parent ( i integer ) PARTITION BY RANGE(i); +CREATE TABLE stats_import.part_child_1 + PARTITION OF stats_import.part_parent + FOR VALUES FROM (0) TO (10) + WITH (autovacuum_enabled = false); + +CREATE INDEX part_parent_i ON stats_import.part_parent(i); + +ANALYZE stats_import.part_parent; + +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent'::regclass; + +-- +-- Partitioned indexes aren't analyzed but it is possible to set +-- stats. The locking rules are different from normal indexes due to +-- the rules for in-place updates: both the partitioned table and the +-- partitioned index are locked in ShareUpdateExclusive mode. +-- +BEGIN; + +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'part_parent_i', + 'relpages', 2::integer); + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.part_parent'::regclass AND + pid = pg_backend_pid() AND granted; + +SELECT mode FROM pg_locks +WHERE relation = 'stats_import.part_parent_i'::regclass AND + pid = pg_backend_pid() AND granted; + +COMMIT; + +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent_i'::regclass; + +-- ok: set all relstats, with version, no bounds checking +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'version', 150000::integer, + 'relpages', '-17'::integer, + 'reltuples', 400::real, + 'relallvisible', 4::integer, + 'relallfrozen', 2::integer); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- ok: set just relpages, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', '16'::integer); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- ok: set just reltuples, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'reltuples', '500'::real); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- ok: set just relallvisible, rest stay same +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relallvisible', 5::integer); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- ok: just relallfrozen +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'version', 150000::integer, + 'relallfrozen', 3::integer); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- warn: bad relpages type, rest updated +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', 'nope'::text, + 'reltuples', 400.0::real, + 'relallvisible', 4::integer, + 'relallfrozen', 3::integer); + +SELECT relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- unrecognized argument name, rest ok +SELECT pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'relpages', '171'::integer, + 'nope', 10::integer); + +SELECT relpages, reltuples, relallvisible +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- ok: clear stats +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'test'); + +SELECT relpages, reltuples, relallvisible +FROM pg_class +WHERE oid = 'stats_import.test'::regclass; + +-- invalid relkinds for statistics +CREATE SEQUENCE stats_import.testseq; + +SELECT pg_catalog.pg_restore_relation_stats( + 'schemaname', 'stats_import', + 'relname', 'testseq'); + +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testseq'); + +CREATE VIEW stats_import.testview AS SELECT * FROM stats_import.test; + +SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testview'); + +-- +-- attribute stats +-- + +-- error: schemaname missing +SELECT pg_catalog.pg_restore_attribute_stats( + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: schema does not exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'nope', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: relname missing +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: relname does not exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'nope', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: relname null +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', NULL, + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: NULL attname +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', NULL, + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: attname doesn't exist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'nope', + 'inherited', false::boolean, + 'null_frac', 0.1::real, + 'avg_width', 2::integer, + 'n_distinct', 0.3::real); + +-- error: both attname and attnum +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'attnum', 1::smallint, + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: neither attname nor attnum +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: attribute is system column +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'xmin', + 'inherited', false::boolean, + 'null_frac', 0.1::real); + +-- error: inherited null +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', NULL::boolean, + 'null_frac', 0.1::real); + +-- ok: just the fixed values, with version, no stakinds +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'version', 150000::integer, + 'null_frac', 0.2::real, + 'avg_width', 5::integer, + 'n_distinct', 0.6::real); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- +-- ok: restore by attnum, we normally reserve this for +-- indexes, but there is no reason it shouldn't work +-- for any stat-having relation. +-- +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attnum', 1::smallint, + 'inherited', false::boolean, + 'null_frac', 0.4::real); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: unrecognized argument name, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.2::real, + 'nope', 0.5::real); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: mcv / mcf null mismatch part 1, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.21::real, + 'most_common_freqs', '{0.1,0.2,0.3}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: mcv / mcf null mismatch part 2, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.21::real, + 'most_common_vals', '{1,2,3}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: mcf type mismatch, mcv-pair fails, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.22::real, + 'most_common_vals', '{2,1,3}'::text, + 'most_common_freqs', '{0.2,0.1}'::double precision[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: mcv cast failure, mcv-pair fails, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.23::real, + 'most_common_vals', '{2,four,3}'::text, + 'most_common_freqs', '{0.3,0.25,0.05}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- ok: mcv+mcf +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'most_common_vals', '{2,1,3}'::text, + 'most_common_freqs', '{0.3,0.25,0.05}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: NULL in histogram array, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.24::real, + 'histogram_bounds', '{1,NULL,3,4}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- ok: histogram_bounds +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'histogram_bounds', '{1,2,3,4}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: elem_count_histogram null element, rest get set +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.25::real, + 'elem_count_histogram', '{1,1,NULL,1,1,1,1,1}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + +-- ok: elem_count_histogram +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.26::real, + 'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + +-- warn: range stats on a scalar type, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.27::real, + 'range_empty_frac', 0.5::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: range_empty_frac range_length_hist null mismatch, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.28::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- warn: range_empty_frac range_length_hist null mismatch part 2, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.29::real, + 'range_empty_frac', 0.5::real + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- ok: range_empty_frac + range_length_hist +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'range_empty_frac', 0.5::real, + 'range_length_histogram', '{399,499,Infinity}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- warn: range bounds histogram on scalar, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.31::real, + 'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- ok: range_bounds_histogram +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- warn: cannot set most_common_elems for range type, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.32::real, + 'most_common_elems', '{3,1}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- warn: scalars can't have mcelem, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.33::real, + 'most_common_elems', '{1,3}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- warn: mcelem / mcelem mismatch, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.34::real, + 'most_common_elems', '{one,two}'::text + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + +-- warn: mcelem / mcelem null mismatch part 2, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'null_frac', 0.35::real, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + +-- ok: mcelem +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'tags', + 'inherited', false::boolean, + 'most_common_elems', '{one,three}'::text, + 'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'tags'; + +-- warn: scalars can't have elem_count_histogram, rest ok +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'id', + 'inherited', false::boolean, + 'null_frac', 0.36::real, + 'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1}'::real[] + ); + +SELECT * +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'id'; + +-- +-- Test the ability to exactly copy data from one table to an identical table, +-- correctly reconstructing the stakind order as well as the staopN and +-- stacollN values. Because oids are not stable across databases, we can only +-- test this when the source and destination are on the same database +-- instance. For that reason, we borrow and adapt a query found in fe_utils +-- and used by pg_dump/pg_upgrade. +-- +INSERT INTO stats_import.test +SELECT 1, 'one', (1, 1.1, 'ONE', '2001-01-01', '{ "xkey": "xval" }')::stats_import.complex_type, int4range(1,4), array['red','green'] +UNION ALL +SELECT 2, 'two', (2, 2.2, 'TWO', '2002-02-02', '[true, 4, "six"]')::stats_import.complex_type, int4range(1,4), array['blue','yellow'] +UNION ALL +SELECT 3, 'tre', (3, 3.3, 'TRE', '2003-03-03', NULL)::stats_import.complex_type, int4range(-1,1), array['"orange"', 'purple', 'cyan'] +UNION ALL +SELECT 4, 'four', NULL, int4range(0,100), NULL; + +CREATE INDEX is_odd ON stats_import.test(((comp).a % 2 = 1)); + +-- Generate statistics on table with data +ANALYZE stats_import.test; + +CREATE TABLE stats_import.test_clone ( LIKE stats_import.test ) + WITH (autovacuum_enabled = false); + +CREATE INDEX is_odd_clone ON stats_import.test_clone(((comp).a % 2 = 1)); + +-- +-- Copy stats from test to test_clone, and is_odd to is_odd_clone +-- +SELECT s.schemaname, s.tablename, s.attname, s.inherited, r.* +FROM pg_catalog.pg_stats AS s +CROSS JOIN LATERAL + pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', s.tablename::text || '_clone', + 'attname', s.attname::text, + 'inherited', s.inherited, + 'version', 150000, + 'null_frac', s.null_frac, + 'avg_width', s.avg_width, + 'n_distinct', s.n_distinct, + 'most_common_vals', s.most_common_vals::text, + 'most_common_freqs', s.most_common_freqs, + 'histogram_bounds', s.histogram_bounds::text, + 'correlation', s.correlation, + 'most_common_elems', s.most_common_elems::text, + 'most_common_elem_freqs', s.most_common_elem_freqs, + 'elem_count_histogram', s.elem_count_histogram, + 'range_bounds_histogram', s.range_bounds_histogram::text, + 'range_empty_frac', s.range_empty_frac, + 'range_length_histogram', s.range_length_histogram::text) AS r +WHERE s.schemaname = 'stats_import' +AND s.tablename IN ('test', 'is_odd') +ORDER BY s.tablename, s.attname, s.inherited; + +SELECT c.relname, COUNT(*) AS num_stats +FROM pg_class AS c +JOIN pg_statistic s ON s.starelid = c.oid +WHERE c.relnamespace = 'stats_import'::regnamespace +AND c.relname IN ('test', 'test_clone', 'is_odd', 'is_odd_clone') +GROUP BY c.relname +ORDER BY c.relname; + +-- check test minus test_clone +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test_clone'::regclass; + +-- check test_clone minus test +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test_clone'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'test_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.test'::regclass; + +-- check is_odd minus is_odd_clone +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd_clone'::regclass; + +-- check is_odd_clone minus is_odd +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd_clone'::regclass +EXCEPT +SELECT + a.attname, s.stainherit, s.stanullfrac, s.stawidth, s.stadistinct, + s.stakind1, s.stakind2, s.stakind3, s.stakind4, s.stakind5, + s.staop1, s.staop2, s.staop3, s.staop4, s.staop5, + s.stacoll1, s.stacoll2, s.stacoll3, s.stacoll4, s.stacoll5, + s.stanumbers1, s.stanumbers2, s.stanumbers3, s.stanumbers4, s.stanumbers5, + s.stavalues1::text AS sv1, s.stavalues2::text AS sv2, + s.stavalues3::text AS sv3, s.stavalues4::text AS sv4, + s.stavalues5::text AS sv5, 'is_odd_clone' AS direction +FROM pg_statistic s +JOIN pg_attribute a ON a.attrelid = s.starelid AND a.attnum = s.staattnum +WHERE s.starelid = 'stats_import.is_odd'::regclass; + +-- attribute stats exist before a clear, but not after +SELECT COUNT(*) +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => false); + +SELECT COUNT(*) +FROM pg_stats +WHERE schemaname = 'stats_import' +AND tablename = 'test' +AND inherited = false +AND attname = 'arange'; + +-- temp tables +CREATE TEMP TABLE stats_temp(i int); +SELECT pg_restore_relation_stats( + 'schemaname', 'pg_temp', + 'relname', 'stats_temp', + 'relpages', '-19'::integer, + 'reltuples', 401::real, + 'relallvisible', 5::integer, + 'relallfrozen', 3::integer); + +SELECT relname, relpages, reltuples, relallvisible, relallfrozen +FROM pg_class +WHERE oid = 'pg_temp.stats_temp'::regclass +ORDER BY relname; + +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'pg_temp', + 'relname', 'stats_temp', + 'attname', 'i', + 'inherited', false::boolean, + 'null_frac', 0.0123::real + ); + +SELECT tablename, null_frac +FROM pg_stats +WHERE schemaname like 'pg_temp%' +AND tablename = 'stats_temp' +AND inherited = false +AND attname = 'i'; +DROP TABLE stats_temp; +DROP SCHEMA stats_import CASCADE; diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index 395967899290b..2577a42987de7 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -77,6 +77,10 @@ SELECT E'De\123dBeEf'::bytea; SELECT E'De\\123dBeEf'::bytea; SELECT E'De\\678dBeEf'::bytea; +SELECT reverse(''::bytea); +SELECT reverse('\xaa'::bytea); +SELECT reverse('\xabcd'::bytea); + SET bytea_output TO escape; SELECT E'\\xDeAdBeEf'::bytea; SELECT E'\\x De Ad Be Ef '::bytea; @@ -193,6 +197,26 @@ SELECT 'abcd\efg' SIMILAR TO '_bcd\%' ESCAPE '' AS true; SELECT 'abcdefg' SIMILAR TO '_bcd%' ESCAPE NULL AS null; SELECT 'abcdefg' SIMILAR TO '_bcd#%' ESCAPE '##' AS error; +-- Characters that should be left alone in character classes when a +-- SIMILAR TO regexp pattern is converted to POSIX style. +-- Underscore "_" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '_[_[:alpha:]_]_'; +-- Percentage "%" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '%[%[:alnum:]%]%'; +-- Dot "." +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '.[.[:alnum:].].'; +-- Dollar "$" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '$[$[:alnum:]$]$'; +-- Opening parenthesis "(" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '()[([:alnum:](]()'; +-- Caret "^" +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '^[^[:alnum:]^[^^][[^^]][\^][[\^]]\^]^'; +-- Closing square bracket "]" at the beginning of character class +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[]%][^]%][^%]%'; +-- Closing square bracket effective after two carets at the beginning +-- of character class. +EXPLAIN (COSTS OFF) SELECT * FROM TEXT_TBL WHERE f1 SIMILAR TO '[^^]^'; + -- Test backslash escapes in regexp_replace's replacement string SELECT regexp_replace('1112223333', E'(\\d{3})(\\d{3})(\\d{4})', E'(\\1) \\2-\\3'); SELECT regexp_replace('foobarrbazz', E'(.)\\1', E'X\\&Y', 'g'); @@ -363,6 +387,12 @@ SELECT POSITION('4' IN '1234567890') = '4' AS "4"; SELECT POSITION('5' IN '1234567890') = '5' AS "5"; +SELECT POSITION('\x11'::bytea IN ''::bytea) = 0 AS "0"; +SELECT POSITION('\x33'::bytea IN '\x1122'::bytea) = 0 AS "0"; +SELECT POSITION(''::bytea IN '\x1122'::bytea) = 1 AS "1"; +SELECT POSITION('\x22'::bytea IN '\x1122'::bytea) = 2 AS "2"; +SELECT POSITION('\x5678'::bytea IN '\x1234567890'::bytea) = 3 AS "3"; + -- T312 character overlay function SELECT OVERLAY('abcdef' PLACING '45' FROM 4) AS "abc45f"; @@ -719,6 +749,20 @@ SELECT sha384('The quick brown fox jumps over the lazy dog.'); SELECT sha512(''); SELECT sha512('The quick brown fox jumps over the lazy dog.'); +-- +-- CRC +-- +SELECT crc32(''); +SELECT crc32('The quick brown fox jumps over the lazy dog.'); + +SELECT crc32c(''); +SELECT crc32c('The quick brown fox jumps over the lazy dog.'); + +SELECT crc32c(repeat('A', 127)::bytea); +SELECT crc32c(repeat('A', 128)::bytea); +SELECT crc32c(repeat('A', 129)::bytea); +SELECT crc32c(repeat('A', 800)::bytea); + -- -- encode/decode -- @@ -742,6 +786,35 @@ SELECT get_byte('\x1234567890abcdef00'::bytea, 99); -- error SELECT set_byte('\x1234567890abcdef00'::bytea, 7, 11); SELECT set_byte('\x1234567890abcdef00'::bytea, 99, 11); -- error +-- +-- conversions between bytea and integer types +-- +SELECT 0x1234::int2::bytea AS "\x1234", (-0x1234)::int2::bytea AS "\xedcc"; +SELECT 0x12345678::int4::bytea AS "\x12345678", (-0x12345678)::int4::bytea AS "\xedcba988"; +SELECT 0x1122334455667788::int8::bytea AS "\x1122334455667788", + (-0x1122334455667788)::int8::bytea AS "\xeeddccbbaa998878"; + +SELECT ''::bytea::int2 AS "0"; +SELECT '\x12'::bytea::int2 AS "18"; +SELECT '\x1234'::bytea::int2 AS "4460"; +SELECT '\x123456'::bytea::int2; -- error + +SELECT ''::bytea::int4 AS "0"; +SELECT '\x12'::bytea::int4 AS "18"; +SELECT '\x12345678'::bytea::int4 AS "305419896"; +SELECT '\x123456789A'::bytea::int4; -- error + +SELECT ''::bytea::int8 AS "0"; +SELECT '\x12'::bytea::int8 AS "18"; +SELECT '\x1122334455667788'::bytea::int8 AS "1234605616436508552"; +SELECT '\x112233445566778899'::bytea::int8; -- error + +-- min/max integer values +SELECT '\x8000'::bytea::int2 AS "-32768", '\x7FFF'::bytea::int2 AS "32767"; +SELECT '\x80000000'::bytea::int4 AS "-2147483648", '\x7FFFFFFF'::bytea::int4 AS "2147483647"; +SELECT '\x8000000000000000'::bytea::int8 AS "-9223372036854775808", + '\x7FFFFFFFFFFFFFFF'::bytea::int8 AS "9223372036854775807"; + -- -- test behavior of escape_string_warning and standard_conforming_strings options -- diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index 75a9b718b2f29..fec38ef85a6a6 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -638,8 +638,36 @@ select sum(ss.tst::int) from where o.ten = 0; -- --- Test rescan of a SetOp node +-- Test rescan of a hashed SetOp node -- +begin; +set local enable_sort = off; + +explain (costs off) +select count(*) from + onek o cross join lateral ( + select * from onek i1 where i1.unique1 = o.unique1 + except + select * from onek i2 where i2.unique1 = o.unique2 + ) ss +where o.ten = 1; + +select count(*) from + onek o cross join lateral ( + select * from onek i1 where i1.unique1 = o.unique1 + except + select * from onek i2 where i2.unique1 = o.unique2 + ) ss +where o.ten = 1; + +rollback; + +-- +-- Test rescan of a sorted SetOp node +-- +begin; +set local enable_hashagg = off; + explain (costs off) select count(*) from onek o cross join lateral ( @@ -657,6 +685,8 @@ select count(*) from ) ss where o.ten = 1; +rollback; + -- -- Test rescan of a RecursiveUnion node -- @@ -857,7 +887,7 @@ $$ declare ln text; begin for ln in - explain (analyze, summary off, timing off, costs off) + explain (analyze, summary off, timing off, costs off, buffers off) select * from (select pk,c2 from sq_limit order by c1,pk) as x limit 3 loop ln := regexp_replace(ln, 'Memory: \S*', 'Memory: xxx'); @@ -890,6 +920,158 @@ fetch backward all in c1; commit; +-- +-- Verify that we correctly flatten cases involving a subquery output +-- expression that doesn't need to be wrapped in a PlaceHolderVar +-- + +explain (costs off) +select tname, attname from ( +select relname::information_schema.sql_identifier as tname, * from + (select * from pg_class c) ss1) ss2 + right join pg_attribute a on a.attrelid = ss2.oid +where tname = 'tenk1' and attnum = 1; + +select tname, attname from ( +select relname::information_schema.sql_identifier as tname, * from + (select * from pg_class c) ss1) ss2 + right join pg_attribute a on a.attrelid = ss2.oid +where tname = 'tenk1' and attnum = 1; + +-- Check behavior when there's a lateral reference in the output expression +explain (verbose, costs off) +select t1.ten, sum(x) from + tenk1 t1 left join lateral ( + select t1.ten + t2.ten as x, t2.fivethous from tenk1 t2 + ) ss on t1.unique1 = ss.fivethous +group by t1.ten +order by t1.ten; + +select t1.ten, sum(x) from + tenk1 t1 left join lateral ( + select t1.ten + t2.ten as x, t2.fivethous from tenk1 t2 + ) ss on t1.unique1 = ss.fivethous +group by t1.ten +order by t1.ten; + +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+t3.q1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+t3.q1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +-- strict expressions containing variables of rels under the same lowest +-- nulling outer join can escape being wrapped +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +-- otherwise we need to wrap the strict expressions +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q1+1 as x, * from int8_tbl t3) t3 on t2.q2 = t3.q2) + on t1.q2 = t2.q2 +order by 1, 2; + +-- lateral references for simple Vars can escape being wrapped if the +-- referenced rel is under the same lowest nulling outer join +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 inner join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + +-- otherwise we need to wrap the Vars +explain (verbose, costs off) +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + +select t1.q1, x from + int8_tbl t1 left join + (int8_tbl t2 left join + lateral (select t2.q2 as x, * from int8_tbl t3) ss on t2.q2 = ss.q1) + on t1.q1 = t2.q1 +order by 1, 2; + +-- lateral references for PHVs can also escape being wrapped if the +-- referenced rel is under the same lowest nulling outer join +explain (verbose, costs off) +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 inner join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 inner join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + +-- otherwise we need to wrap the PHVs +explain (verbose, costs off) +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 left join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + +select ss2.* from + int8_tbl t1 left join + (int8_tbl t2 left join + (select coalesce(q1) as x, * from int8_tbl t3) ss1 on t2.q1 = ss1.q2 left join + lateral (select ss1.x as y, * from int8_tbl t4) ss2 on t2.q2 = ss2.q1) + on t1.q2 = ss2.q1 +order by 1, 2, 3; + -- -- Tests for CTE inlining behavior -- @@ -1020,3 +1202,103 @@ WHERE a.thousand < 750; explain (costs off) SELECT * FROM tenk1 A LEFT JOIN tenk2 B ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd); + +-- +-- Test VALUES to ARRAY (VtA) transformation +-- + +-- VtA transformation for joined VALUES is not supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek, (VALUES('RFAAAA'), ('VJAAAA')) AS v (i) + WHERE onek.stringu1 = v.i; + +-- VtA transformation for a composite argument is not supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE (unique1,ten) IN (VALUES (1,1), (20,0), (99,9), (17,99)) + ORDER BY unique1; + +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (VALUES(10000), (2), (389), (1000), (2000), (10029)) + ORDER BY unique1; + +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (VALUES(1200), (1)); + +-- Recursive evaluation of constant queries is not yet supported +EXPLAIN (COSTS OFF) +SELECT * FROM onek + WHERE unique1 IN (SELECT x * x FROM (VALUES(1200), (1)) AS x(x)); + +EXPLAIN (COSTS OFF) +SELECT unique1, stringu1 FROM onek WHERE stringu1::name IN (VALUES('RFAAAA'), ('VJAAAA')); + +EXPLAIN (COSTS OFF) +SELECT unique1, stringu1 FROM onek WHERE stringu1::text IN (VALUES('RFAAAA'), ('VJAAAA')); + +EXPLAIN (COSTS OFF) +SELECT * from onek WHERE unique1 in (VALUES(1200::bigint), (1)); + +-- VtA shouldn't depend on the side of the join probing with the VALUES expression. +EXPLAIN (COSTS OFF) +SELECT c.unique1,c.ten FROM tenk1 c JOIN onek a USING (ten) +WHERE a.ten IN (VALUES (1), (2)); +EXPLAIN (COSTS OFF) +SELECT c.unique1,c.ten FROM tenk1 c JOIN onek a USING (ten) +WHERE c.ten IN (VALUES (1), (2)); + +-- Constant expressions are simplified +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE sin(two ) +four IN (VALUES (sin(0.5)), (2)); +EXPLAIN (COSTS OFF) + +-- VtA allows NULLs in the list +SELECT ten FROM onek WHERE sin(two)+four IN (VALUES (sin(0.5)), (NULL), (2)); + +-- VtA is supported for custom plans where params are substituted with +-- constants. VtA is not supported with generic plans where params prevent +-- us from building a constant array. +PREPARE test (int, numeric, text) AS + SELECT ten FROM onek WHERE sin(two) * four / ($3::real) IN (VALUES (sin($2)), (2), ($1)); +EXPLAIN (COSTS OFF) EXECUTE test(42, 3.14, '-1.5'); +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, NULL); +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, '-1.5'); +SET plan_cache_mode = 'force_generic_plan'; +EXPLAIN (COSTS OFF) EXECUTE test(NULL, 3.14, '-1.5'); +RESET plan_cache_mode; + +-- VtA doesn't support LIMIT, OFFSET, and ORDER BY clauses +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) OFFSET 1); +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) ORDER BY 1); +EXPLAIN (COSTS OFF) +SELECT ten FROM onek WHERE unique1 IN (VALUES (1), (2) LIMIT 1); + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t +WHERE unique1 IN (VALUES (0), ((2 IN (SELECT unique2 FROM onek c + WHERE c.unique2 = t.unique1))::integer)); + +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t +WHERE unique1 IN (VALUES (0), ((2 IN (SELECT unique2 FROM onek c + WHERE c.unique2 IN (VALUES (sin(0.5)), (2))))::integer)); + +-- VtA is not allowed with subqueries +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE unique1 IN (VALUES (0), ((2 IN + (SELECT (3)))::integer) +); + +-- VtA is not allowed with non-constant expressions +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE unique1 IN (VALUES (0), (unique2)); +EXPLAIN (COSTS OFF) +SELECT * FROM onek t1, lateral (SELECT * FROM onek t2 WHERE t2.ten IN (values (t1.ten), (1))); + +-- VtA causes the whole expression to be evaluated as a constant +EXPLAIN (COSTS OFF) +SELECT ten FROM onek t WHERE 1.0::integer IN ((VALUES (1), (3))); diff --git a/src/test/regress/sql/sysviews.sql b/src/test/regress/sql/sysviews.sql index 15e2a9e741729..66179f026b379 100644 --- a/src/test/regress/sql/sysviews.sql +++ b/src/test/regress/sql/sysviews.sql @@ -14,7 +14,7 @@ select count(*) >= 0 as ok from pg_available_extensions; -- The entire output of pg_backend_memory_contexts is not stable, -- we test only the existence and basic condition of TopMemoryContext. -select type, name, ident, parent, level, total_bytes >= free_bytes +select type, name, ident, level, total_bytes >= free_bytes from pg_backend_memory_contexts where level = 1; -- We can exercise some MemoryContext type stats functions. Most of the @@ -28,7 +28,7 @@ declare cur cursor for select left(a,10), b from (values(repeat('a', 512 * 1024),1),(repeat('b', 512),2)) v(a,b) order by v.a desc; fetch 1 from cur; -select type, name, parent, total_bytes > 0, total_nblocks, free_bytes > 0, free_chunks +select type, name, total_bytes > 0, total_nblocks, free_bytes > 0, free_chunks from pg_backend_memory_contexts where name = 'Caller tuples'; rollback; @@ -98,3 +98,6 @@ set timezone_abbreviations = 'Australia'; select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs; set timezone_abbreviations = 'India'; select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs; +-- One specific case we can check without much fear of breakage +-- is the historical local-mean-time value used for America/Los_Angeles. +select * from pg_timezone_abbrevs where abbrev = 'LMT'; diff --git a/src/test/regress/sql/tablespace.sql b/src/test/regress/sql/tablespace.sql index d274d9615efa7..dfe3db096e28d 100644 --- a/src/test/regress/sql/tablespace.sql +++ b/src/test/regress/sql/tablespace.sql @@ -40,10 +40,10 @@ REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_am; REINDEX (TABLESPACE regress_tblspace) TABLE pg_authid; REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_authid; -- toast relations, fail -REINDEX (TABLESPACE regress_tblspace) INDEX pg_toast.pg_toast_1260_index; -REINDEX (TABLESPACE regress_tblspace) INDEX CONCURRENTLY pg_toast.pg_toast_1260_index; -REINDEX (TABLESPACE regress_tblspace) TABLE pg_toast.pg_toast_1260; -REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_toast.pg_toast_1260; +REINDEX (TABLESPACE regress_tblspace) INDEX pg_toast.pg_toast_1262_index; +REINDEX (TABLESPACE regress_tblspace) INDEX CONCURRENTLY pg_toast.pg_toast_1262_index; +REINDEX (TABLESPACE regress_tblspace) TABLE pg_toast.pg_toast_1262; +REINDEX (TABLESPACE regress_tblspace) TABLE CONCURRENTLY pg_toast.pg_toast_1262; -- system catalog, fail REINDEX (TABLESPACE pg_global) TABLE pg_authid; REINDEX (TABLESPACE pg_global) TABLE CONCURRENTLY pg_authid; @@ -396,6 +396,12 @@ ALTER INDEX testschema.part_a_idx SET TABLESPACE pg_default; -- Fail, not empty DROP TABLESPACE regress_tblspace; +-- Adequate cache initialization before GRANT +\c - +BEGIN; +GRANT ALL ON TABLESPACE regress_tblspace TO PUBLIC; +ROLLBACK; + CREATE ROLE regress_tablespace_user1 login; CREATE ROLE regress_tablespace_user2 login; GRANT USAGE ON SCHEMA testschema TO regress_tablespace_user2; diff --git a/src/test/regress/sql/temp.sql b/src/test/regress/sql/temp.sql index 2a487a1ef7f43..d50472ddced89 100644 --- a/src/test/regress/sql/temp.sql +++ b/src/test/regress/sql/temp.sql @@ -311,3 +311,110 @@ SET search_path TO 'pg_temp'; BEGIN; SELECT current_schema() ~ 'pg_temp' AS is_temp_schema; PREPARE TRANSACTION 'twophase_search'; + + +-- Tests to verify we recover correctly from exhausting buffer pins and +-- related matters. + +-- use lower possible buffer limit to make the test cheaper +\c +SET temp_buffers = 100; + +CREATE TEMPORARY TABLE test_temp(a int not null unique, b TEXT not null, cnt int not null); +INSERT INTO test_temp SELECT generate_series(1, 10000) as id, repeat('a', 200), 0; +-- should be at least 2x as large than temp_buffers +SELECT pg_relation_size('test_temp') / current_setting('block_size')::int8 > 200; + +-- Don't want cursor names and plpgsql function lines in the error messages +\set VERBOSITY terse + +/* helper function to create cursors for each page in [p_start, p_end] */ +CREATE FUNCTION test_temp_pin(p_start int, p_end int) +RETURNS void +LANGUAGE plpgsql +AS $f$ + DECLARE + cursorname text; + query text; + BEGIN + FOR i IN p_start..p_end LOOP + cursorname = 'c_'||i; + query = format($q$DECLARE %I CURSOR FOR SELECT ctid FROM test_temp WHERE ctid >= '( %s, 1)'::tid $q$, cursorname, i); + EXECUTE query; + EXECUTE 'FETCH NEXT FROM '||cursorname; + -- for test development + -- RAISE NOTICE '%: %', cursorname, query; + END LOOP; + END; +$f$; + + +-- Test overflow of temp table buffers is handled correctly +BEGIN; +-- should work, below max +SELECT test_temp_pin(0, 9); +-- should fail, too many buffers pinned +SELECT test_temp_pin(10, 105); +ROLLBACK; + +BEGIN; +-- have some working cursors to test after errors +SELECT test_temp_pin(0, 9); +FETCH NEXT FROM c_3; +-- exhaust buffer pins in subtrans, check things work after +SAVEPOINT rescue_me; +SELECT test_temp_pin(10, 105); +ROLLBACK TO SAVEPOINT rescue_me; +-- pre-subtrans cursors continue to work +FETCH NEXT FROM c_3; + +-- new cursors with pins can be created after subtrans rollback +SELECT test_temp_pin(10, 94); + +-- Check that read streams deal with lower number of pins available +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + +ROLLBACK; + + +-- Check that temp tables with existing cursors can't be dropped. +BEGIN; +SELECT test_temp_pin(0, 1); +DROP TABLE test_temp; +COMMIT; + +-- Check that temp tables with existing cursors can't be dropped. +BEGIN; +SELECT test_temp_pin(0, 1); +TRUNCATE test_temp; +COMMIT; + +-- Check that temp tables that are dropped in transaction that's rolled back +-- preserve buffer contents +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; +INSERT INTO test_temp(a, b, cnt) VALUES (-1, '', 0); +BEGIN; +INSERT INTO test_temp(a, b, cnt) VALUES (-2, '', 0); +DROP TABLE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + +-- Check that temp table drop is transactional and preserves dirty +-- buffer contents +UPDATE test_temp SET cnt = cnt + 1 WHERE a = -1; +BEGIN; +DROP TABLE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + +-- Check that temp table truncation is transactional and preserves dirty +-- buffer contents +UPDATE test_temp SET cnt = cnt + 1 WHERE a = -1; +BEGIN; +TRUNCATE test_temp; +ROLLBACK; +SELECT count(*), max(a) max_a, min(a) min_a, max(cnt) max_cnt FROM test_temp; + + +-- cleanup +DROP FUNCTION test_temp_pin(int, int); diff --git a/src/test/regress/sql/test_setup.sql b/src/test/regress/sql/test_setup.sql index 06b0e2121f895..5854399a02803 100644 --- a/src/test/regress/sql/test_setup.sql +++ b/src/test/regress/sql/test_setup.sql @@ -252,11 +252,6 @@ CREATE FUNCTION binary_coercible(oid, oid) AS :'regresslib', 'binary_coercible' LANGUAGE C STRICT STABLE PARALLEL SAFE; -CREATE FUNCTION ttdummy () - RETURNS trigger - AS :'regresslib' - LANGUAGE C; - -- Use hand-rolled hash functions and operator classes to get predictable -- result on different machines. The hash function for int4 simply returns -- the sum of the values passed to it and the one for text returns the length diff --git a/src/test/regress/sql/tidscan.sql b/src/test/regress/sql/tidscan.sql index 313e0fb9b679a..1b82d5f1a53e0 100644 --- a/src/test/regress/sql/tidscan.sql +++ b/src/test/regress/sql/tidscan.sql @@ -68,17 +68,17 @@ DECLARE c CURSOR FOR SELECT ctid, * FROM tidscan; FETCH NEXT FROM c; -- skip one row FETCH NEXT FROM c; -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; FETCH NEXT FROM c; -- perform update -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; SELECT * FROM tidscan; -- position cursor past any rows FETCH NEXT FROM c; -- should error out -EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; ROLLBACK; diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql index 820ef7752ac7c..55f80530ea05e 100644 --- a/src/test/regress/sql/timestamp.sql +++ b/src/test/regress/sql/timestamp.sql @@ -176,6 +176,8 @@ SELECT d1 - timestamp without time zone '1997-01-02' AS diff SELECT date_trunc( 'week', timestamp '2004-02-29 15:44:17.71393' ) AS week_trunc; +SELECT date_trunc( 'ago', timestamp 'infinity' ) AS invalid_trunc; + -- verify date_bin behaves the same as date_trunc for relevant intervals -- case 1: AD dates, origin < input @@ -424,3 +426,7 @@ select age(timestamp 'infinity', timestamp 'infinity'); select age(timestamp 'infinity', timestamp '-infinity'); select age(timestamp '-infinity', timestamp 'infinity'); select age(timestamp '-infinity', timestamp '-infinity'); + +-- test timestamp near POSTGRES_EPOCH_JDATE +select timestamp '1999-12-31 24:00:00'; +select make_timestamp(1999, 12, 31, 24, 0, 0); diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql index ccfd90d6467ae..caca3123f13f6 100644 --- a/src/test/regress/sql/timestamptz.sql +++ b/src/test/regress/sql/timestamptz.sql @@ -109,6 +109,23 @@ SELECT '20500110 173201 Europe/Helsinki'::timestamptz; -- non-DST SELECT '205000-07-10 17:32:01 Europe/Helsinki'::timestamptz; -- DST SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST +-- Recognize "LMT" as whatever it means in the current zone +SELECT 'Jan 01 00:00:00 1000 LMT'::timestamptz; +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; +SET timezone = 'Europe/London'; +SELECT 'Jan 01 00:00:00 1000 LMT'::timestamptz; +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; +-- which might be nothing +SET timezone = 'UTC'; +SELECT 'Jan 01 00:00:00 2024 LMT'::timestamptz; -- fail +-- Another example of an abbrev that varies across zones +SELECT '1912-01-01 00:00 MMT'::timestamptz; -- from timezone_abbreviations +SET timezone = 'America/Montevideo'; +SELECT '1912-01-01 00:00'::timestamptz; +SELECT '1912-01-01 00:00 MMT'::timestamptz; +SELECT '1912-01-01 00:00 MMT'::timestamptz AT TIME ZONE 'UTC'; +RESET timezone; + -- Test non-error-throwing API SELECT pg_input_is_valid('now', 'timestamptz'); SELECT pg_input_is_valid('garbage', 'timestamptz'); @@ -200,10 +217,14 @@ SELECT d1 - timestamp with time zone '1997-01-02' AS diff FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01'; SELECT date_trunc( 'week', timestamp with time zone '2004-02-29 15:44:17.71393' ) AS week_trunc; +SELECT date_trunc( 'ago', timestamp with time zone 'infinity' ) AS invalid_trunc; SELECT date_trunc('day', timestamp with time zone '2001-02-16 20:38:40+00', 'Australia/Sydney') as sydney_trunc; -- zone name SELECT date_trunc('day', timestamp with time zone '2001-02-16 20:38:40+00', 'GMT') as gmt_trunc; -- fixed-offset abbreviation SELECT date_trunc('day', timestamp with time zone '2001-02-16 20:38:40+00', 'VET') as vet_trunc; -- variable-offset abbreviation +SELECT date_trunc('ago', timestamp with time zone 'infinity', 'GMT') AS invalid_zone_trunc; + + -- verify date_bin behaves the same as date_trunc for relevant intervals SELECT @@ -442,14 +463,18 @@ SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2') = '1973-07-15 08:15:5 -- full timezone names SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') = timestamptz '2014-12-10 00:00:00 Europe/Prague'; SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UTC'; -SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC'; +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Asia/Singapore') AT TIME ZONE 'UTC'; +SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Pacific/Honolulu') AT TIME ZONE 'UTC'; SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Europe/Paris') AT TIME ZONE 'UTC'; SELECT make_timestamptz(1910, 12, 24, 0, 0, 0, 'Nehwon/Lankhmar'); -- abbreviations SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'EST'); SELECT make_timestamptz(2008, 12, 10, 10, 10, 10, 'EDT'); -SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT'); +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'FOO8BAR'); + +-- POSIX +SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT,M3.2.0,M11.1.0'); RESET TimeZone; @@ -668,3 +693,7 @@ SELECT age(timestamptz 'infinity', timestamptz 'infinity'); SELECT age(timestamptz 'infinity', timestamptz '-infinity'); SELECT age(timestamptz '-infinity', timestamptz 'infinity'); SELECT age(timestamptz '-infinity', timestamptz '-infinity'); + +-- test timestamp near POSTGRES_EPOCH_JDATE +select timestamptz '1999-12-31 24:00:00'; +select make_timestamptz(1999, 12, 31, 24, 0, 0); diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 51610788b212a..9ffd318385ff6 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -6,135 +6,13 @@ \getenv libdir PG_LIBDIR \getenv dlsuffix PG_DLSUFFIX -\set autoinclib :libdir '/autoinc' :dlsuffix -\set refintlib :libdir '/refint' :dlsuffix \set regresslib :libdir '/regress' :dlsuffix -CREATE FUNCTION autoinc () - RETURNS trigger - AS :'autoinclib' - LANGUAGE C; - -CREATE FUNCTION check_primary_key () - RETURNS trigger - AS :'refintlib' - LANGUAGE C; - -CREATE FUNCTION check_foreign_key () - RETURNS trigger - AS :'refintlib' - LANGUAGE C; - CREATE FUNCTION trigger_return_old () RETURNS trigger AS :'regresslib' LANGUAGE C; -CREATE FUNCTION set_ttdummy (int4) - RETURNS int4 - AS :'regresslib' - LANGUAGE C STRICT; - -create table pkeys (pkey1 int4 not null, pkey2 text not null); -create table fkeys (fkey1 int4, fkey2 text, fkey3 int); -create table fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); - -create index fkeys_i on fkeys (fkey1, fkey2); -create index fkeys2_i on fkeys2 (fkey21, fkey22); -create index fkeys2p_i on fkeys2 (pkey23); - -insert into pkeys values (10, '1'); -insert into pkeys values (20, '2'); -insert into pkeys values (30, '3'); -insert into pkeys values (40, '4'); -insert into pkeys values (50, '5'); -insert into pkeys values (60, '6'); -create unique index pkeys_i on pkeys (pkey1, pkey2); - --- --- For fkeys: --- (fkey1, fkey2) --> pkeys (pkey1, pkey2) --- (fkey3) --> fkeys2 (pkey23) --- -create trigger check_fkeys_pkey_exist - before insert or update on fkeys - for each row - execute function - check_primary_key ('fkey1', 'fkey2', 'pkeys', 'pkey1', 'pkey2'); - -create trigger check_fkeys_pkey2_exist - before insert or update on fkeys - for each row - execute function check_primary_key ('fkey3', 'fkeys2', 'pkey23'); - --- --- For fkeys2: --- (fkey21, fkey22) --> pkeys (pkey1, pkey2) --- -create trigger check_fkeys2_pkey_exist - before insert or update on fkeys2 - for each row - execute procedure - check_primary_key ('fkey21', 'fkey22', 'pkeys', 'pkey1', 'pkey2'); - --- Test comments -COMMENT ON TRIGGER check_fkeys2_pkey_bad ON fkeys2 IS 'wrong'; -COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS 'right'; -COMMENT ON TRIGGER check_fkeys2_pkey_exist ON fkeys2 IS NULL; - --- --- For pkeys: --- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: --- fkeys (fkey1, fkey2) and fkeys2 (fkey21, fkey22) --- -create trigger check_pkeys_fkey_cascade - before delete or update on pkeys - for each row - execute procedure - check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', - 'fkeys', 'fkey1', 'fkey2', 'fkeys2', 'fkey21', 'fkey22'); - --- --- For fkeys2: --- ON DELETE/UPDATE (pkey23) RESTRICT: --- fkeys (fkey3) --- -create trigger check_fkeys2_fkey_restrict - before delete or update on fkeys2 - for each row - execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'fkeys', 'fkey3'); - -insert into fkeys2 values (10, '1', 1); -insert into fkeys2 values (30, '3', 2); -insert into fkeys2 values (40, '4', 5); -insert into fkeys2 values (50, '5', 3); --- no key in pkeys -insert into fkeys2 values (70, '5', 3); - -insert into fkeys values (10, '1', 2); -insert into fkeys values (30, '3', 3); -insert into fkeys values (40, '4', 2); -insert into fkeys values (50, '5', 2); --- no key in pkeys -insert into fkeys values (70, '5', 1); --- no key in fkeys2 -insert into fkeys values (60, '6', 4); - -delete from pkeys where pkey1 = 30 and pkey2 = '3'; -delete from pkeys where pkey1 = 40 and pkey2 = '4'; -update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; -update pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; - -SELECT trigger_name, event_manipulation, event_object_schema, event_object_table, - action_order, action_condition, action_orientation, action_timing, - action_reference_old_table, action_reference_new_table - FROM information_schema.triggers - WHERE event_object_table in ('pkeys', 'fkeys', 'fkeys2') - ORDER BY trigger_name COLLATE "C", 2; - -DROP TABLE pkeys; -DROP TABLE fkeys; -DROP TABLE fkeys2; -- Check behavior when trigger returns unmodified trigtuple create table trigtest (f1 int, f2 text); @@ -214,77 +92,6 @@ select * from trigtest; drop table trigtest; -create sequence ttdummy_seq increment 10 start 0 minvalue 0; - -create table tttest ( - price_id int4, - price_val int4, - price_on int4, - price_off int4 default 999999 -); - -create trigger ttdummy - before delete or update on tttest - for each row - execute procedure - ttdummy (price_on, price_off); - -create trigger ttserial - before insert or update on tttest - for each row - execute procedure - autoinc (price_on, ttdummy_seq); - -insert into tttest values (1, 1, null); -insert into tttest values (2, 2, null); -insert into tttest values (3, 3, 0); - -select * from tttest; -delete from tttest where price_id = 2; -select * from tttest; --- what do we see ? - --- get current prices -select * from tttest where price_off = 999999; - --- change price for price_id == 3 -update tttest set price_val = 30 where price_id = 3; -select * from tttest; - --- now we want to change pric_id in ALL tuples --- this gets us not what we need -update tttest set price_id = 5 where price_id = 3; -select * from tttest; - --- restore data as before last update: -select set_ttdummy(0); -delete from tttest where price_id = 5; -update tttest set price_off = 999999 where price_val = 30; -select * from tttest; - --- and try change price_id now! -update tttest set price_id = 5 where price_id = 3; -select * from tttest; --- isn't it what we need ? - -select set_ttdummy(1); - --- we want to correct some "date" -update tttest set price_on = -1 where price_id = 1; --- but this doesn't work - --- try in this way -select set_ttdummy(0); -update tttest set price_on = -1 where price_id = 1; -select * from tttest; --- isn't it what we need ? - --- get price for price_id == 5 as it was @ "date" 35 -select * from tttest where price_on <= 35 and price_off > 35 and price_id = 5; - -drop table tttest; -drop sequence ttdummy_seq; - -- -- tests for per-statement triggers -- @@ -346,6 +153,11 @@ COPY main_table (a, b) FROM stdin; SELECT * FROM main_table ORDER BY a, b; +-- Test comments +COMMENT ON TRIGGER no_such_trigger ON main_table IS 'wrong'; +COMMENT ON TRIGGER before_ins_stmt_trig ON main_table IS 'right'; +COMMENT ON TRIGGER before_ins_stmt_trig ON main_table IS NULL; + -- -- test triggers with WHEN clause -- @@ -2187,6 +1999,52 @@ alter table parent attach partition child for values in ('AAA'); drop table child, parent; +-- +-- Verify access of transition tables with UPDATE triggers and tuples +-- moved across partitions. +-- +create or replace function dump_update_new() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, new table = %', TG_NAME, + (select string_agg(new_table::text, ', ' order by a) from new_table); + return null; + end; +$$; +create or replace function dump_update_old() returns trigger language plpgsql as +$$ + begin + raise notice 'trigger = %, old table = %', TG_NAME, + (select string_agg(old_table::text, ', ' order by a) from old_table); + return null; + end; +$$; +create table trans_tab_parent (a text) partition by list (a); +create table trans_tab_child1 partition of trans_tab_parent for values in ('AAA1', 'AAA2'); +create table trans_tab_child2 partition of trans_tab_parent for values in ('BBB1', 'BBB2'); +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_update_old(); +create trigger trans_tab_parent_insert_trig + after insert on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_insert(); +create trigger trans_tab_parent_delete_trig + after delete on trans_tab_parent referencing old table as old_table + for each statement execute procedure dump_delete(); +insert into trans_tab_parent values ('AAA1'), ('BBB1'); +-- should not trigger access to new table when moving across partitions. +update trans_tab_parent set a = 'BBB2' where a = 'AAA1'; +drop trigger trans_tab_parent_update_trig on trans_tab_parent; +create trigger trans_tab_parent_update_trig + after update on trans_tab_parent referencing new table as new_table + for each statement execute procedure dump_update_new(); +-- should not trigger access to old table when moving across partitions. +update trans_tab_parent set a = 'AAA2' where a = 'BBB1'; +delete from trans_tab_parent; +-- clean up +drop table trans_tab_parent, trans_tab_child1, trans_tab_child2; +drop function dump_update_new, dump_update_old; + -- -- Verify behavior of statement triggers on (non-partition) -- inheritance hierarchy with transition tables; similar to the @@ -2434,6 +2292,25 @@ create trigger my_table_col_update_trig drop table my_table; +-- +-- Verify that transition tables can't be used in, eg, a view. +-- + +create table my_table (a int); +create function make_bogus_matview() returns trigger as +$$ begin + create materialized view transition_test_mv as select * from new_table; + return new; +end $$ +language plpgsql; +create trigger make_bogus_matview + after insert on my_table + referencing new table as new_table + for each statement execute function make_bogus_matview(); +insert into my_table values (42); -- error +drop table my_table; +drop function make_bogus_matview(); + -- -- Test firing of triggers with transition tables by foreign key cascades -- @@ -2820,3 +2697,66 @@ alter trigger parenttrig on parent rename to anothertrig; drop table parent, child; drop function f(); + +-- Test who runs deferred trigger functions + +-- setup +create role regress_caller; +create role regress_fn_owner; +create function whoami() returns trigger language plpgsql +as $$ +begin + raise notice 'I am %', current_user; + return null; +end; +$$; +alter function whoami() owner to regress_fn_owner; + +create table defer_trig (id integer); +grant insert on defer_trig to public; +create constraint trigger whoami after insert on defer_trig + deferrable initially deferred + for each row + execute function whoami(); + +-- deferred triggers must run as the user that queued the trigger +begin; +set role regress_caller; +insert into defer_trig values (1); +reset role; +set role regress_fn_owner; +insert into defer_trig values (2); +reset role; +commit; + +-- security definer functions override the user who queued the trigger +alter function whoami() security definer; +begin; +set role regress_caller; +insert into defer_trig values (3); +reset role; +commit; +alter function whoami() security invoker; + +-- make sure the current user is restored after error +create or replace function whoami() returns trigger language plpgsql +as $$ +begin + raise notice 'I am %', current_user; + perform 1 / 0; + return null; +end; +$$; + +begin; +set role regress_caller; +insert into defer_trig values (4); +reset role; +commit; -- error expected +select current_user = session_user; + +-- clean up +drop table defer_trig; +drop function whoami(); +drop role regress_fn_owner; +drop role regress_caller; diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index e88d6cbe49d16..c94dd83d3061c 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -12,6 +12,12 @@ -- row in the linked-to table. However, if we want to enforce that a link -- field can't be 0, we have to check it here. +-- directory paths and dlsuffix are passed to us in environment variables +\getenv libdir PG_LIBDIR +\getenv dlsuffix PG_DLSUFFIX + +\set regresslib :libdir '/regress' :dlsuffix + -- **************** pg_type **************** -- Look for illegal values in pg_type fields. @@ -397,8 +403,7 @@ WHERE pc.relkind IN ('r', 't', 'm') and SELECT a1.attrelid, a1.attname FROM pg_attribute as a1 WHERE a1.attrelid = 0 OR a1.atttypid = 0 OR a1.attnum = 0 OR - a1.attcacheoff != -1 OR a1.attinhcount < 0 OR - (a1.attinhcount = 0 AND NOT a1.attislocal); + a1.attinhcount < 0 OR (a1.attinhcount = 0 AND NOT a1.attislocal); -- Cross-check attnum against parent relation @@ -426,6 +431,20 @@ WHERE a1.atttypid = t1.oid AND a1.attbyval != t1.typbyval OR (a1.attstorage != t1.typstorage AND a1.attstorage != 'p')); +-- Look for IsCatalogTextUniqueIndexOid() omissions. + +CREATE FUNCTION is_catalog_text_unique_index_oid(oid) RETURNS bool + AS :'regresslib', 'is_catalog_text_unique_index_oid' + LANGUAGE C STRICT; + +SELECT indexrelid::regclass +FROM pg_index +WHERE (is_catalog_text_unique_index_oid(indexrelid) <> + (indisunique AND + indexrelid < 16384 AND + EXISTS (SELECT 1 FROM pg_attribute + WHERE attrelid = indexrelid AND atttypid = 'text'::regtype))); + -- **************** pg_range **************** -- Look for illegal values in pg_range fields. diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql index f8826514e42a6..13700a6bfc4e9 100644 --- a/src/test/regress/sql/union.sql +++ b/src/test/regress/sql/union.sql @@ -134,10 +134,21 @@ select count(*) from select count(*) from ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; +-- this query will prefer a sorted setop unless we force it. +set enable_indexscan to off; + explain (costs off) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; +reset enable_indexscan; + +-- the hashed implementation is sensitive to child plans' tuple slot types +explain (costs off) +select * from int8_tbl intersect select q2, q1 from int8_tbl order by 1, 2; +select * from int8_tbl intersect select q2, q1 from int8_tbl order by 1, 2; +select q2, q1 from int8_tbl intersect select * from int8_tbl order by 1, 2; + set enable_hashagg to off; explain (costs off) @@ -156,6 +167,10 @@ explain (costs off) select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; +explain (costs off) +select f1 from int4_tbl union all + (select unique1 from tenk1 union select unique2 from tenk1); + reset enable_hashagg; -- non-hashable type diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql index 93b693ae83761..c071fffc11639 100644 --- a/src/test/regress/sql/updatable_views.sql +++ b/src/test/regress/sql/updatable_views.sql @@ -154,7 +154,8 @@ DROP SEQUENCE uv_seq CASCADE; CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0; +CREATE VIEW rw_view1 AS + SELECT *, 'Const' AS c, (SELECT concat('b: ', b)) AS d FROM base_tbl WHERE a>0; SELECT table_name, is_insertable_into FROM information_schema.tables @@ -175,13 +176,18 @@ UPDATE rw_view1 SET a=5 WHERE a=4; DELETE FROM rw_view1 WHERE b='Row 2'; SELECT * FROM base_tbl; +SET jit_above_cost = 0; + MERGE INTO rw_view1 t USING (VALUES (0, 'ROW 0'), (1, 'ROW 1'), (2, 'ROW 2'), (3, 'ROW 3')) AS v(a,b) ON t.a = v.a WHEN MATCHED AND t.a <= 1 THEN UPDATE SET b = v.b WHEN MATCHED THEN DELETE WHEN NOT MATCHED AND a > 0 THEN INSERT (a) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; + RETURNING merge_action(), v.*, old, new, old.*, new.*, t.*; + +SET jit_above_cost TO DEFAULT; + SELECT * FROM base_tbl ORDER BY a; MERGE INTO rw_view1 t @@ -191,7 +197,7 @@ MERGE INTO rw_view1 t WHEN MATCHED THEN DELETE WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED AND a > 0 THEN INSERT (a) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; + RETURNING merge_action(), v.*, old, new, old.*, new.*, t.*; SELECT * FROM base_tbl ORDER BY a; EXPLAIN (costs off) UPDATE rw_view1 SET a=6 WHERE a=5; @@ -240,8 +246,10 @@ DROP TABLE base_tbl_hist; CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl WHERE a>0; -CREATE VIEW rw_view2 AS SELECT aa AS aaa, bb AS bbb FROM rw_view1 WHERE aa<10; +CREATE VIEW rw_view1 AS + SELECT b AS bb, a AS aa, 'Const1' AS c FROM base_tbl WHERE a>0; +CREATE VIEW rw_view2 AS + SELECT aa AS aaa, bb AS bbb, c AS c1, 'Const2' AS c2 FROM rw_view1 WHERE aa<10; SELECT table_name, is_insertable_into FROM information_schema.tables @@ -268,7 +276,7 @@ MERGE INTO rw_view2 t WHEN MATCHED AND aaa = 3 THEN DELETE WHEN MATCHED THEN UPDATE SET bbb = v.b WHEN NOT MATCHED THEN INSERT (aaa) VALUES (v.a) - RETURNING merge_action(), v.*, t.*; + RETURNING merge_action(), v.*, (SELECT old), (SELECT (SELECT new)), t.*; SELECT * FROM rw_view2 ORDER BY aaa; MERGE INTO rw_view2 t @@ -277,7 +285,7 @@ MERGE INTO rw_view2 t WHEN MATCHED THEN UPDATE SET bbb = v.b WHEN NOT MATCHED THEN INSERT (aaa) VALUES (v.a) WHEN NOT MATCHED BY SOURCE THEN UPDATE SET bbb = 'Not matched by source' - RETURNING merge_action(), v.*, t.*; + RETURNING merge_action(), v.*, old, (SELECT new FROM (VALUES ((SELECT new)))), t.*; SELECT * FROM rw_view2 ORDER BY aaa; EXPLAIN (costs off) UPDATE rw_view2 SET aaa=5 WHERE aaa=4; @@ -362,10 +370,14 @@ SELECT table_name, column_name, is_updatable WHERE table_name LIKE 'rw_view%' ORDER BY table_name, ordinal_position; -INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *; -UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *; +INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING old.*, new.*; +UPDATE rw_view2 SET b='R3' WHERE a=3 RETURNING old.*, new.*; -- rule returns NEW +DROP RULE rw_view1_upd_rule ON rw_view1; +CREATE RULE rw_view1_upd_rule AS ON UPDATE TO rw_view1 + DO INSTEAD UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a RETURNING *; +UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING old.*, new.*; SELECT * FROM rw_view2; -DELETE FROM rw_view2 WHERE a=3 RETURNING *; +DELETE FROM rw_view2 WHERE a=3 RETURNING old.*, new.*; SELECT * FROM rw_view2; MERGE INTO rw_view2 t USING (VALUES (3, 'Row 3')) AS v(a,b) ON t.a = v.a @@ -381,8 +393,10 @@ DROP TABLE base_tbl CASCADE; CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers -CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a<10; +CREATE VIEW rw_view1 AS + SELECT *, 'Const1' AS c1 FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers +CREATE VIEW rw_view2 AS + SELECT *, 'Const2' AS c2 FROM rw_view1 WHERE a<10; SELECT table_name, is_insertable_into FROM information_schema.tables @@ -407,9 +421,11 @@ $$ BEGIN IF TG_OP = 'INSERT' THEN INSERT INTO base_tbl VALUES (NEW.a, NEW.b); + NEW.c1 = 'Trigger Const1'; RETURN NEW; ELSIF TG_OP = 'UPDATE' THEN UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a; + NEW.c1 = 'Trigger Const1'; RETURN NEW; ELSIF TG_OP = 'DELETE' THEN DELETE FROM base_tbl WHERE a=OLD.a; @@ -479,10 +495,10 @@ SELECT table_name, column_name, is_updatable WHERE table_name LIKE 'rw_view%' ORDER BY table_name, ordinal_position; -INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *; -UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *; +INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING old.*, new.*; +UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING old.*, new.*; SELECT * FROM rw_view2; -DELETE FROM rw_view2 WHERE a=3 RETURNING *; +DELETE FROM rw_view2 WHERE a=3 RETURNING old.*, new.*; SELECT * FROM rw_view2; MERGE INTO rw_view2 t @@ -490,7 +506,7 @@ MERGE INTO rw_view2 t WHEN MATCHED AND t.a <= 1 THEN DELETE WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b) - RETURNING merge_action(), s.*, t.*; + RETURNING merge_action(), s.*, old, new, t.*; SELECT * FROM base_tbl ORDER BY a; MERGE INTO rw_view2 t @@ -498,7 +514,7 @@ MERGE INTO rw_view2 t WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b) WHEN NOT MATCHED BY SOURCE THEN UPDATE SET b = 'Not matched by source' - RETURNING merge_action(), s.*, t.*; + RETURNING merge_action(), s.*, old, new, t.*; SELECT * FROM base_tbl ORDER BY a; EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2; diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql index c88f6d087a716..465153a03415c 100644 --- a/src/test/regress/sql/uuid.sql +++ b/src/test/regress/sql/uuid.sql @@ -10,6 +10,11 @@ CREATE TABLE guid2 guid_field UUID, text_field TEXT DEFAULT(now()) ); +CREATE TABLE guid3 +( + id SERIAL, + guid_field UUID +); -- inserting invalid data tests -- too long @@ -63,6 +68,18 @@ CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field); -- unique index test CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field); + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111' OR + guid_field <> '3f3e3c3b-3a30-3938-3736-353433a2313e'; +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222' OR + guid_field <= '11111111111111111111111111111111' OR + guid_field <= '3f3e3c3b-3a30-3938-3736-353433a2313e'; +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM guid1 WHERE guid_field = '3f3e3c3b-3a30-3938-3736-353433a2313e' OR + guid_field = '11111111111111111111111111111111'; + -- should fail INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); @@ -85,6 +102,34 @@ INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); INSERT INTO guid1 (guid_field) VALUES (gen_random_uuid()); SELECT count(DISTINCT guid_field) FROM guid1; +-- test of uuidv4() alias +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (uuidv4()); +INSERT INTO guid1 (guid_field) VALUES (uuidv4()); +SELECT count(DISTINCT guid_field) FROM guid1; + +-- generation test for v7 +TRUNCATE guid1; +INSERT INTO guid1 (guid_field) VALUES (uuidv7()); +INSERT INTO guid1 (guid_field) VALUES (uuidv7()); +INSERT INTO guid1 (guid_field) VALUES (uuidv7(INTERVAL '1 day')); +SELECT count(DISTINCT guid_field) FROM guid1; + +-- test sortability of v7 +INSERT INTO guid3 (guid_field) SELECT uuidv7() FROM generate_series(1, 10); +SELECT array_agg(id ORDER BY guid_field) FROM guid3; + +-- Check the timestamp offsets for v7. +-- +-- generate UUIDv7 values with timestamps ranging from 1970 (the Unix epoch year) +-- to 10888 (one year before the maximum possible year), and then verify that +-- the extracted timestamps from these UUIDv7 values have not overflowed. +WITH uuidts AS ( + SELECT y, ts as ts, lag(ts) OVER (ORDER BY y) AS prev_ts + FROM (SELECT y, uuid_extract_timestamp(uuidv7((y || ' years')::interval)) AS ts + FROM generate_series(1970 - extract(year from now())::int, 10888 - extract(year from now())::int) y) +) +SELECT y, ts, prev_ts FROM uuidts WHERE ts < prev_ts; -- extract functions @@ -92,12 +137,15 @@ SELECT count(DISTINCT guid_field) FROM guid1; SELECT uuid_extract_version('11111111-1111-5111-8111-111111111111'); -- 5 SELECT uuid_extract_version(gen_random_uuid()); -- 4 SELECT uuid_extract_version('11111111-1111-1111-1111-111111111111'); -- null +SELECT uuid_extract_version(uuidv4()); -- 4 +SELECT uuid_extract_version(uuidv7()); -- 7 -- timestamp -SELECT uuid_extract_timestamp('C232AB00-9414-11EC-B3C8-9F6BDECED846') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 4122bis test vector +SELECT uuid_extract_timestamp('C232AB00-9414-11EC-B3C8-9F6BDECED846') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 9562 test vector for v1 +SELECT uuid_extract_timestamp('017F22E2-79B0-7CC3-98C4-DC0C0C07398F') = 'Tuesday, February 22, 2022 2:22:22.00 PM GMT+05:00'; -- RFC 9562 test vector for v7 SELECT uuid_extract_timestamp(gen_random_uuid()); -- null SELECT uuid_extract_timestamp('11111111-1111-1111-1111-111111111111'); -- null -- clean up -DROP TABLE guid1, guid2 CASCADE; +DROP TABLE guid1, guid2, guid3 CASCADE; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 548cd7accace4..a72bdb5b619d9 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -113,6 +113,10 @@ CREATE INDEX brin_pvactst ON pvactst USING brin (i); CREATE INDEX gin_pvactst ON pvactst USING gin (a); CREATE INDEX gist_pvactst ON pvactst USING gist (p); CREATE INDEX spgist_pvactst ON pvactst USING spgist (p); +CREATE TABLE pvactst2 (i INT) WITH (autovacuum_enabled = off); +INSERT INTO pvactst2 SELECT generate_series(1, 1000); +CREATE INDEX ON pvactst2 (i); +CREATE INDEX ON pvactst2 (i); -- VACUUM invokes parallel index cleanup SET min_parallel_index_scan_size to 0; @@ -130,6 +134,14 @@ VACUUM (PARALLEL 2, INDEX_CLEANUP FALSE) pvactst; VACUUM (PARALLEL 2, FULL TRUE) pvactst; -- error, cannot use both PARALLEL and FULL VACUUM (PARALLEL) pvactst; -- error, cannot use PARALLEL option without parallel degree +-- Test parallel vacuum using the minimum maintenance_work_mem with and without +-- dead tuples. +SET maintenance_work_mem TO 64; +VACUUM (PARALLEL 2) pvactst2; +DELETE FROM pvactst2 WHERE i < 1000; +VACUUM (PARALLEL 2) pvactst2; +RESET maintenance_work_mem; + -- Test different combinations of parallel and full options for temporary tables CREATE TEMPORARY TABLE tmp (a int PRIMARY KEY); CREATE INDEX tmp_idx1 ON tmp (a); @@ -137,6 +149,7 @@ VACUUM (PARALLEL 1, FULL FALSE) tmp; -- parallel vacuum disabled for temp tables VACUUM (PARALLEL 0, FULL TRUE) tmp; -- can specify parallel disabled (even though that's implied by FULL) RESET min_parallel_index_scan_size; DROP TABLE pvactst; +DROP TABLE pvactst2; -- INDEX_CLEANUP option CREATE TABLE no_index_cleanup (i INT PRIMARY KEY, t TEXT); @@ -181,9 +194,19 @@ CREATE TEMP TABLE vac_truncate_test(i INT NOT NULL, j text) INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') > 0; +SET vacuum_truncate = false; VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; SELECT pg_relation_size('vac_truncate_test') = 0; VACUUM (TRUNCATE FALSE, FULL TRUE) vac_truncate_test; +ALTER TABLE vac_truncate_test RESET (vacuum_truncate); +INSERT INTO vac_truncate_test VALUES (1, NULL), (NULL, NULL); +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; +RESET vacuum_truncate; +VACUUM (TRUNCATE FALSE, DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') > 0; +VACUUM (DISABLE_PAGE_SKIPPING) vac_truncate_test; +SELECT pg_relation_size('vac_truncate_test') = 0; DROP TABLE vac_truncate_test; -- partitioned table @@ -233,6 +256,72 @@ BEGIN; -- ANALYZE behaves differently inside a transaction block ANALYZE vactst, vactst; COMMIT; +-- +-- Tests for ANALYZE ONLY / VACUUM ONLY on partitioned tables +-- +CREATE TABLE only_parted (a int, b text) PARTITION BY LIST (a); +CREATE TABLE only_parted1 PARTITION OF only_parted FOR VALUES IN (1); +INSERT INTO only_parted VALUES (1, 'a'); + +-- Ensure only the partitioned table is analyzed +ANALYZE ONLY only_parted; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass) + ORDER BY relname; + +-- Ensure partitioned table and the partitions are analyzed +ANALYZE only_parted; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_parted'::regclass, 'only_parted1'::regclass) + ORDER BY relname; + +DROP TABLE only_parted; + +-- VACUUM ONLY on a partitioned table does nothing, ensure we get a warning. +VACUUM ONLY vacparted; + +-- Try ANALYZE ONLY with a column list +ANALYZE ONLY vacparted(a,b); + +-- +-- Tests for VACUUM ONLY / ANALYZE ONLY on inheritance tables +-- +CREATE TABLE only_inh_parent (a int primary key, b TEXT); +CREATE TABLE only_inh_child () INHERITS (only_inh_parent); +INSERT INTO only_inh_child(a,b) VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc'); + +-- Ensure only parent is analyzed +ANALYZE ONLY only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + +-- Ensure the parent and child are analyzed +ANALYZE only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + +-- Ensure only the parent is vacuumed +VACUUM ONLY only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + +-- Ensure parent and child are vacuumed +VACUUM only_inh_parent; +SELECT relname, last_analyze IS NOT NULL AS analyzed, last_vacuum IS NOT NULL AS vacuumed + FROM pg_stat_user_tables + WHERE relid IN ('only_inh_parent'::regclass, 'only_inh_child'::regclass) + ORDER BY relname; + +DROP TABLE only_inh_parent CASCADE; + -- parenthesized syntax for ANALYZE ANALYZE (VERBOSE) does_not_exist; ANALYZE (nonexistent-arg) does_not_exist; diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql index 6de5493b05bb2..02f105f070e8b 100644 --- a/src/test/regress/sql/window.sql +++ b/src/test/regress/sql/window.sql @@ -1345,6 +1345,13 @@ SELECT * FROM FROM empsalary) emp WHERE c = 1; +-- Try another case with a WindowFunc with a byref return type +SELECT * FROM + (SELECT row_number() OVER (PARTITION BY salary) AS rn, + lead(depname) OVER (PARTITION BY salary) || ' Department' AS n_dep + FROM empsalary) emp +WHERE rn < 1; + -- Some more complex cases with multiple window clauses EXPLAIN (COSTS OFF) SELECT * FROM diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql index 8f6e6c0b40567..b1cae1612904b 100644 --- a/src/test/regress/sql/with.sql +++ b/src/test/regress/sql/with.sql @@ -216,6 +216,20 @@ WITH RECURSIVE subdepartment AS ) SELECT * FROM subdepartment ORDER BY name; +-- exercise the deduplication code of a UNION with mixed input slot types +WITH RECURSIVE subdepartment AS +( + -- select all columns to prevent projection + SELECT id, parent_department, name FROM department WHERE name = 'A' + + UNION + + -- joins do projection + SELECT d.id, d.parent_department, d.name FROM department AS d + INNER JOIN subdepartment AS sd ON d.parent_department = sd.id +) +SELECT * FROM subdepartment ORDER BY name; + -- inside subqueries SELECT count(*) FROM ( WITH RECURSIVE t(n) AS ( @@ -347,6 +361,18 @@ UNION ALL SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON (t1.id=t2.id); +CREATE TEMP TABLE duplicates (a INT NOT NULL); +INSERT INTO duplicates VALUES(1), (1); + +-- Try out a recursive UNION case where the non-recursive part's table slot +-- uses TTSOpsBufferHeapTuple and contains duplicate rows. +WITH RECURSIVE cte (a) as ( + SELECT a FROM duplicates + UNION + SELECT a FROM cte +) +SELECT a FROM cte; + -- test that column statistics from a materialized CTE are available -- to upper planner (otherwise, we'd get a stupider plan) explain (costs off) @@ -937,6 +963,13 @@ WITH RECURSIVE x(n) AS ( ORDER BY (SELECT n FROM x)) SELECT * FROM x; +-- and this +WITH RECURSIVE x(n) AS ( + WITH sub_cte AS (SELECT * FROM x) + DELETE FROM graph RETURNING f) + SELECT * FROM x; + + CREATE TEMPORARY TABLE y (a INTEGER); INSERT INTO y SELECT generate_series(1, 10); diff --git a/src/test/regress/sql/without_overlaps.sql b/src/test/regress/sql/without_overlaps.sql new file mode 100644 index 0000000000000..4aaca242bbece --- /dev/null +++ b/src/test/regress/sql/without_overlaps.sql @@ -0,0 +1,2024 @@ +-- Tests for WITHOUT OVERLAPS. +-- +-- We leave behind several tables to test pg_dump etc: +-- temporal_rng, temporal_rng2, +-- temporal_fk_rng2rng. + +SET datestyle TO ISO, YMD; + +-- +-- test input parser +-- + +-- PK with no columns just WITHOUT OVERLAPS: + +CREATE TABLE temporal_rng ( + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (valid_at WITHOUT OVERLAPS) +); + +-- PK with a range column/PERIOD that isn't there: + +CREATE TABLE temporal_rng ( + id INTEGER, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); + +-- PK with a non-range column: + +CREATE TABLE temporal_rng ( + id int4range, + valid_at TEXT, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); + +-- PK with one column plus a range: + +CREATE TABLE temporal_rng ( + -- Since we can't depend on having btree_gist here, + -- use an int4range instead of an int. + -- (The rangetypes regression test uses the same trick.) + id int4range, + valid_at daterange, + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; + +-- PK from LIKE: +CREATE TABLE temporal_rng2 (LIKE temporal_rng INCLUDING ALL); +\d temporal_rng2 +DROP TABLE temporal_rng2; + +-- no PK from INHERITS: +CREATE TABLE temporal_rng2 () INHERITS (temporal_rng); +\d temporal_rng2 +DROP TABLE temporal_rng2; +DROP TABLE temporal_rng; + +-- PK in inheriting table: +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +CREATE TABLE temporal_rng2 ( + CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) INHERITS (temporal_rng); +\d temporal_rng2 +DROP TABLE temporal_rng CASCADE; + +-- Add PK to already inheriting table: +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +CREATE TABLE temporal_rng2 () INHERITS (temporal_rng); +ALTER TABLE temporal_rng2 + ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +\d temporal_rng2 +DROP TABLE temporal_rng2; +DROP TABLE temporal_rng; + +-- PK with two columns plus a range: +CREATE TABLE temporal_rng2 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng2 +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng2_pk'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng2_pk'; + +-- PK with a custom range type: +CREATE TYPE textrange2 AS range (subtype=text, collation="C"); +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at textrange2, + CONSTRAINT temporal_rng3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_pk; +DROP TABLE temporal_rng3; +DROP TYPE textrange2; + +-- PK with one column plus a multirange: +CREATE TABLE temporal_mltrng ( + id int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_mltrng +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk'; + +-- PK with two columns plus a multirange: +CREATE TABLE temporal_mltrng2 ( + id1 int4range, + id2 int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_mltrng2 +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk'; + +-- UNIQUE with no columns just WITHOUT OVERLAPS: + +CREATE TABLE temporal_rng3 ( + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (valid_at WITHOUT OVERLAPS) +); + +-- UNIQUE with a range column/PERIOD that isn't there: + +CREATE TABLE temporal_rng3 ( + id INTEGER, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); + +-- UNIQUE with a non-range column: + +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at TEXT, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); + +-- UNIQUE with one column plus a range: + +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng3 +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; +DROP TABLE temporal_rng3; + +-- UNIQUE with two columns plus a range: +CREATE TABLE temporal_rng3 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng3_uq UNIQUE (id1, id2, valid_at WITHOUT OVERLAPS) +); +\d temporal_rng3 +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; +SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; +DROP TABLE temporal_rng3; + +-- UNIQUE with a custom range type: +CREATE TYPE textrange2 AS range (subtype=text, collation="C"); +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at textrange2, + CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq; +DROP TABLE temporal_rng3; +DROP TYPE textrange2; + +-- +-- test ALTER TABLE ADD CONSTRAINT +-- + +CREATE TABLE temporal_rng ( + id int4range, + valid_at daterange +); +ALTER TABLE temporal_rng + ADD CONSTRAINT temporal_rng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); + +-- PK with USING INDEX (not possible): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE INDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_pk + PRIMARY KEY USING INDEX idx_temporal3_uq; +DROP TABLE temporal3; + +-- UNIQUE with USING INDEX (not possible): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE INDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_uq + UNIQUE USING INDEX idx_temporal3_uq; +DROP TABLE temporal3; + +-- UNIQUE with USING [UNIQUE] INDEX (possible but not a temporal constraint): +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange +); +CREATE UNIQUE INDEX idx_temporal3_uq ON temporal3 (id, valid_at); +ALTER TABLE temporal3 + ADD CONSTRAINT temporal3_uq + UNIQUE USING INDEX idx_temporal3_uq; +DROP TABLE temporal3; + +-- Add range column and the PK at the same time +CREATE TABLE temporal3 ( + id int4range +); +ALTER TABLE temporal3 + ADD COLUMN valid_at daterange, + ADD CONSTRAINT temporal3_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DROP TABLE temporal3; + +-- Add range column and UNIQUE constraint at the same time +CREATE TABLE temporal3 ( + id int4range +); +ALTER TABLE temporal3 + ADD COLUMN valid_at daterange, + ADD CONSTRAINT temporal3_uq + UNIQUE (id, valid_at WITHOUT OVERLAPS); +DROP TABLE temporal3; + +-- +-- range PK: test with existing rows +-- + +ALTER TABLE temporal_rng DROP CONSTRAINT temporal_rng_pk; + +-- okay: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_rng DROP CONSTRAINT temporal_rng_pk; + +-- should fail: +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); + ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', 'empty'); + ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +ALTER TABLE temporal_rng ADD CONSTRAINT temporal_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_rng; + +-- +-- range PK: test inserts +-- + +-- okay: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); + +-- should fail: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', NULL); +-- rejects empty: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[3,4)', 'empty'); +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +-- +-- range PK: test updates +-- + +-- update the scalar part +UPDATE temporal_rng +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the range part +UPDATE temporal_rng +SET valid_at = '[2020-01-01,2021-01-01)' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_rng +SET id = '[21,22)', + valid_at = '[2018-01-02,2018-02-03)' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +SELECT * FROM temporal_rng ORDER BY id, valid_at; +-- should fail: +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = daterange('2018-03-05', '2018-05-05') +WHERE id = '[21,22)'; +-- set the scalar part to NULL +UPDATE temporal_rng +SET id = NULL, + valid_at = daterange('2018-03-05', '2018-05-05') +WHERE id = '[21,22)'; +-- set the range part to NULL +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = NULL +WHERE id = '[21,22)'; +-- rejects empty: +UPDATE temporal_rng +SET id = '[1,2)', + valid_at = 'empty' +WHERE id = '[21,22)'; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +-- +-- range UQ: test with existing rows +-- + +CREATE TABLE temporal_rng3 ( + id int4range, + valid_at daterange +); + +-- okay: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +INSERT INTO temporal_rng3 (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', NULL); +ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_rng3 DROP CONSTRAINT temporal_rng3_uq; + +-- should fail: +BEGIN; + INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); + ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', 'empty'); + ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +ALTER TABLE temporal_rng3 ADD CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_rng3; + +-- +-- range UQ: test inserts +-- + +-- okay: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-03')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-03-03', '2018-04-04')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[2,3)', daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', daterange('2018-01-01', NULL)); +INSERT INTO temporal_rng3 (id, valid_at) VALUES (NULL, daterange('2018-01-01', '2018-01-05')); +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', NULL); + +-- should fail: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[1,2)', daterange('2018-01-01', '2018-01-05')); +-- rejects empty: +INSERT INTO temporal_rng3 (id, valid_at) VALUES ('[3,4)', 'empty'); +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; + +-- +-- range UQ: test updates +-- + +-- update the scalar part +UPDATE temporal_rng3 +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the range part +UPDATE temporal_rng3 +SET valid_at = '[2020-01-01,2021-01-01)' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_rng3 +SET id = '[21,22)', + valid_at = '[2018-01-02,2018-02-03)' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +-- set the scalar part to NULL +UPDATE temporal_rng3 +SET id = NULL, + valid_at = daterange('2020-01-01', '2021-01-01') +WHERE id = '[21,22)'; +-- set the range part to NULL +UPDATE temporal_rng3 +SET id = '[1,2)', + valid_at = NULL +WHERE id IS NULL AND valid_at @> '2020-06-01'::date; +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; +-- should fail: +UPDATE temporal_rng3 +SET valid_at = daterange('2018-03-01', '2018-05-05') +WHERE id = '[1,2)' AND valid_at IS NULL; +-- rejects empty: +UPDATE temporal_rng3 +SET valid_at = 'empty' +WHERE id = '[1,2)' AND valid_at IS NULL; +-- still rejects empty when scalar part is NULL: +UPDATE temporal_rng3 +SET id = NULL, + valid_at = 'empty' +WHERE id = '[1,2)' AND valid_at IS NULL; +SELECT * FROM temporal_rng3 ORDER BY id, valid_at; +DROP TABLE temporal_rng3; + +-- +-- multirange PK: test with existing rows +-- + +ALTER TABLE temporal_mltrng DROP CONSTRAINT temporal_mltrng_pk; + +-- okay: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_mltrng DROP CONSTRAINT temporal_mltrng_pk; + +-- should fail: +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); + ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', '{}'); + ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +ALTER TABLE temporal_mltrng ADD CONSTRAINT temporal_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_mltrng; + +-- +-- multirange PK: test inserts +-- + +-- okay: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); + +-- should fail: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', NULL); +-- rejects empty: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[3,4)', '{}'); +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +-- +-- multirange PK: test updates +-- + +-- update the scalar part +UPDATE temporal_mltrng +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the multirange part +UPDATE temporal_mltrng +SET valid_at = '{[2020-01-01,2021-01-01)}' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_mltrng +SET id = '[21,22)', + valid_at = '{[2018-01-02,2018-02-03)}' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; +-- should fail: +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) +WHERE id = '[21,22)'; +-- set the scalar part to NULL +UPDATE temporal_mltrng +SET id = NULL, + valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) +WHERE id = '[21,22)'; +-- set the multirange part to NULL +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = NULL +WHERE id = '[21,22)'; +-- rejects empty: +UPDATE temporal_mltrng +SET id = '[1,2)', + valid_at = '{}' +WHERE id = '[21,22)'; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +-- +-- multirange UQ: test with existing rows +-- + +CREATE TABLE temporal_mltrng3 ( + id int4range, + valid_at datemultirange +); + +-- okay: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', NULL); +ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ALTER TABLE temporal_mltrng3 DROP CONSTRAINT temporal_mltrng3_uq; + +-- should fail: +BEGIN; + INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); + ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +-- rejects empty: +BEGIN; + INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', '{}'); + ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +ROLLBACK; +ALTER TABLE temporal_mltrng3 ADD CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); +DELETE FROM temporal_mltrng3; + +-- +-- multirange UQ: test inserts +-- + +-- okay: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES (NULL, datemultirange(daterange('2018-01-01', '2018-01-05'))); +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', NULL); + +-- should fail: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-01-01', '2018-01-05'))); +-- rejects empty: +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[3,4)', '{}'); +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +-- +-- multirange UQ: test updates +-- + +-- update the scalar part +UPDATE temporal_mltrng3 +SET id = '[11,12)' +WHERE id = '[1,2)' +AND valid_at @> '2018-01-15'::date; +-- update the multirange part +UPDATE temporal_mltrng3 +SET valid_at = '{[2020-01-01,2021-01-01)}' +WHERE id = '[11,12)' +AND valid_at @> '2018-01-15'::date; +-- update both at once +UPDATE temporal_mltrng3 +SET id = '[21,22)', + valid_at = '{[2018-01-02,2018-02-03)}' +WHERE id = '[11,12)' +AND valid_at @> '2020-01-15'::date; +-- set the scalar part to NULL +UPDATE temporal_mltrng3 +SET id = NULL, + valid_at = datemultirange(daterange('2020-01-01', '2021-01-01')) +WHERE id = '[21,22)'; +-- set the multirange part to NULL +UPDATE temporal_mltrng3 +SET id = '[1,2)', + valid_at = NULL +WHERE id IS NULL AND valid_at @> '2020-06-01'::date; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; +-- should fail: +UPDATE temporal_mltrng3 +SET valid_at = datemultirange(daterange('2018-03-01', '2018-05-05')) +WHERE id = '[1,2)' AND valid_at IS NULL; +-- rejects empty: +UPDATE temporal_mltrng3 +SET valid_at = '{}' +WHERE id = '[1,2)' AND valid_at IS NULL; +-- still rejects empty when scalar part is NULL: +UPDATE temporal_mltrng3 +SET id = NULL, + valid_at = '{}' +WHERE id = '[1,2)' AND valid_at IS NULL; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; +DROP TABLE temporal_mltrng3; + +-- +-- test a range with both a PK and a UNIQUE constraint +-- + +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + id2 int8range, + name TEXT, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal3_uniq UNIQUE (id2, valid_at WITHOUT OVERLAPS) +); +INSERT INTO temporal3 (id, valid_at, id2, name) + VALUES + ('[1,2)', daterange('2000-01-01', '2010-01-01'), '[7,8)', 'foo'), + ('[2,3)', daterange('2000-01-01', '2010-01-01'), '[9,10)', 'bar') +; +DROP TABLE temporal3; + +-- +-- test changing the PK's dependencies +-- + +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); + +ALTER TABLE temporal3 ALTER COLUMN valid_at DROP NOT NULL; +ALTER TABLE temporal3 ALTER COLUMN valid_at TYPE tstzrange USING tstzrange(lower(valid_at), upper(valid_at)); +ALTER TABLE temporal3 RENAME COLUMN valid_at TO valid_thru; +ALTER TABLE temporal3 DROP COLUMN valid_thru; +DROP TABLE temporal3; + +-- +-- test PARTITION BY for ranges +-- + +-- temporal PRIMARY KEY: +CREATE TABLE temporal_partitioned ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned FOR VALUES IN ('[1,2)', '[2,3)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned FOR VALUES IN ('[3,4)', '[4,5)'); +INSERT INTO temporal_partitioned (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[3,4)', daterange('2000-01-01', '2010-01-01'), 'three'); +SELECT * FROM temporal_partitioned ORDER BY id, valid_at; +SELECT * FROM tp1 ORDER BY id, valid_at; +SELECT * FROM tp2 ORDER BY id, valid_at; +DROP TABLE temporal_partitioned; + +-- temporal UNIQUE: +CREATE TABLE temporal_partitioned ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned FOR VALUES IN ('[1,2)', '[2,3)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned FOR VALUES IN ('[3,4)', '[4,5)'); +INSERT INTO temporal_partitioned (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[3,4)', daterange('2000-01-01', '2010-01-01'), 'three'); +SELECT * FROM temporal_partitioned ORDER BY id, valid_at; +SELECT * FROM tp1 ORDER BY id, valid_at; +SELECT * FROM tp2 ORDER BY id, valid_at; +DROP TABLE temporal_partitioned; + +-- ALTER TABLE REPLICA IDENTITY +\d temporal_rng +ALTER TABLE temporal_rng REPLICA IDENTITY USING INDEX temporal_rng_pk; +\d temporal_rng + +-- +-- ON CONFLICT: ranges +-- + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +TRUNCATE temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_rng ORDER BY id, valid_at; + +-- with a UNIQUE constraint: + +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; +SELECT * FROM temporal3 ORDER BY id, valid_at; + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; +SELECT * FROM temporal3 ORDER BY id, valid_at; + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING; +SELECT * FROM temporal3 ORDER BY id, valid_at; + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal3 ORDER BY id, valid_at; + +TRUNCATE temporal3; +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); +-- with a conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal3 ORDER BY id, valid_at; + +DROP TABLE temporal3; + +-- +-- ON CONFLICT: multiranges +-- + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO NOTHING; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng_pk DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_mltrng ORDER BY id, valid_at; + +-- with a UNIQUE constraint: + +CREATE TABLE temporal_mltrng3 ( + id int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS) +); +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO NOTHING; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +TRUNCATE temporal_mltrng3; +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); +-- with a conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[2,3)'; +-- id matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[3,4)'; +-- date matches but no conflict +INSERT INTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ON CONSTRAINT temporal_mltrng3_uq DO UPDATE SET id = EXCLUDED.id + '[4,5)'; +SELECT * FROM temporal_mltrng3 ORDER BY id, valid_at; + +DROP TABLE temporal_mltrng3; + +-- +-- test FK dependencies +-- + +-- can't drop a range referenced by an FK, unless with CASCADE +CREATE TABLE temporal3 ( + id int4range, + valid_at daterange, + CONSTRAINT temporal3_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal3 (id, PERIOD valid_at) +); +ALTER TABLE temporal3 DROP COLUMN valid_at; +ALTER TABLE temporal3 DROP COLUMN valid_at CASCADE; +DROP TABLE temporal_fk_rng2rng; +DROP TABLE temporal3; + +-- +-- test FOREIGN KEY, range references range +-- + +-- test table setup +DROP TABLE temporal_rng; +CREATE TABLE temporal_rng (id int4range, valid_at daterange); +ALTER TABLE temporal_rng + ADD CONSTRAINT temporal_rng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); + +-- Can't create a FK with a mismatched range type +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at int4range, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk2 PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk2 FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); + +-- works: PERIOD for both referenced and referencing +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +DROP TABLE temporal_fk_rng2rng; + +-- with mismatched PERIOD columns: + +-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) +-- REFERENCES part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, valid_at) +); +-- (parent_id, valid_at) REFERENCES (id, valid_at) +-- both should specify PERIOD: +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng (id, valid_at) +); +-- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +-- (parent_id, valid_at) REFERENCES [implicit] +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_rng +); +-- (parent_id, PERIOD valid_at) REFERENCES (id) +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id) +); +-- (parent_id) REFERENCES (id, PERIOD valid_at) +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_rng (id, PERIOD valid_at) +); +-- with inferred PK on the referenced table: +-- (parent_id, PERIOD valid_at) REFERENCES [implicit] +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng +); +DROP TABLE temporal_fk_rng2rng; +-- (parent_id) REFERENCES [implicit] +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_rng +); + +-- should fail because of duplicate referenced columns: +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_rng (id, PERIOD id) +); + +-- Two scalar columns +DROP TABLE temporal_rng2; +CREATE TABLE temporal_rng2 ( + id1 int4range, + id2 int4range, + valid_at daterange, + CONSTRAINT temporal_rng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); + +CREATE TABLE temporal_fk2_rng2rng ( + id int4range, + valid_at daterange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk2_rng2rng_fk FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at) +); +\d temporal_fk2_rng2rng +DROP TABLE temporal_fk2_rng2rng; + +-- +-- test ALTER TABLE ADD CONSTRAINT +-- + +CREATE TABLE temporal_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng (id, PERIOD valid_at); +-- Two scalar columns: +CREATE TABLE temporal_fk2_rng2rng ( + id int4range, + valid_at daterange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk2_rng2rng + ADD CONSTRAINT temporal_fk2_rng2rng_fk + FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at); +\d temporal_fk2_rng2rng + +-- with inferred PK on the referenced table, and wrong column type: +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk, + ALTER COLUMN valid_at TYPE tsrange USING tsrange(lower(valid_at), upper(valid_at)); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +ALTER TABLE temporal_fk_rng2rng + ALTER COLUMN valid_at TYPE daterange USING daterange(lower(valid_at)::date, upper(valid_at)::date); + +-- with inferred PK on the referenced table: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; + +-- should fail because of duplicate referenced columns: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk2 + FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_rng (id, PERIOD id); + +-- +-- test with rows already +-- + +DELETE FROM temporal_fk_rng2rng; +DELETE FROM temporal_rng; +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[1,2)', daterange('2018-01-02', '2018-02-03')), + ('[1,2)', daterange('2018-03-03', '2018-04-04')), + ('[2,3)', daterange('2018-01-01', '2018-01-05')), + ('[3,4)', daterange('2018-01-01', NULL)); + +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-01'), '[1,2)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); +-- should fail: +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +-- okay again: +DELETE FROM temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; + +-- +-- test pg_get_constraintdef +-- + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_rng2rng_fk'; + +-- +-- test FK referencing inserts +-- + +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[1,2)', daterange('2018-01-02', '2018-02-01'), '[1,2)'); +-- should fail: +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); +-- now it should work: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2018-02-03', '2018-03-03')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[2,3)', daterange('2018-01-02', '2018-04-01'), '[1,2)'); + +-- +-- test FK referencing updates +-- + +-- slide the edge across a referenced transition: +UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-02-20') WHERE id = '[1,2)'; +-- should fail: +UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-05-01') WHERE id = '[1,2)'; +UPDATE temporal_fk_rng2rng SET parent_id = '[8,9)' WHERE id = '[1,2)'; + +-- ALTER FK DEFERRABLE + +BEGIN; + INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); + INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + + DELETE FROM temporal_rng WHERE id = '[5,6)'; --should not fail yet. +COMMIT; -- should fail here. + +-- +-- test FK referenced updates NO ACTION +-- + +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON UPDATE NO ACTION; +-- a PK update that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'; +-- a PK update that succeeds even though the numeric id is referenced because the range isn't: +DELETE FROM temporal_rng WHERE id = '[5,6)'; +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) + VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +UPDATE temporal_rng SET valid_at = daterange('2016-02-01', '2016-03-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- A PK update sliding the edge between two referenced rows: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[6,7)', daterange('2018-01-01', '2018-02-01')), + ('[6,7)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[4,5)', daterange('2018-01-15', '2018-02-15'), '[6,7)'); +UPDATE temporal_rng + SET valid_at = CASE WHEN lower(valid_at) = '2018-01-01' THEN daterange('2018-01-01', '2018-01-05') + WHEN lower(valid_at) = '2018-02-01' THEN daterange('2018-01-05', '2018-03-01') END + WHERE id = '[6,7)'; +-- a PK update shrinking the referenced range but still valid: +-- There are two references: one fulfilled by the first pk row, +-- the other fulfilled by both pk rows combined. +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[1,2)', daterange('2018-01-01', '2018-03-01')), + ('[1,2)', daterange('2018-03-01', '2018-06-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[1,2)', daterange('2018-01-15', '2018-02-01'), '[1,2)'), + ('[2,3)', daterange('2018-01-15', '2018-05-01'), '[1,2)'); +UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update growing the referenced range is fine: +UPDATE temporal_rng SET valid_at = daterange('2018-01-01', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-25'::date; +-- a PK update shrinking the referenced range and changing the id invalidates the whole range (error): +UPDATE temporal_rng SET id = '[2,3)', valid_at = daterange('2018-01-15', '2018-03-01') + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update changing only the id invalidates the whole range (error): +UPDATE temporal_rng SET id = '[2,3)' + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update that loses time from both ends, but is still valid: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[2,3)', daterange('2018-01-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[5,6)', daterange('2018-01-15', '2018-02-01'), '[2,3)'); +UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-02-15') + WHERE id = '[2,3)'; +-- a PK update that fails because both are referenced: +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +-- a PK update that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + + UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +COMMIT; +-- changing the scalar part fails: +UPDATE temporal_rng SET id = '[7,8)' + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +-- then delete the objecting FK record and the same PK update succeeds: +DELETE FROM temporal_fk_rng2rng WHERE id = '[3,4)'; +UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); + +-- +-- test FK referenced updates RESTRICT +-- + +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON UPDATE RESTRICT; + +-- +-- test FK referenced deletes NO ACTION +-- + +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng; +-- a PK delete that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +DELETE FROM temporal_rng WHERE id = '[5,6)'; +-- a PK delete that succeeds even though the numeric id is referenced because the range isn't: +INSERT INTO temporal_rng (id, valid_at) VALUES + ('[5,6)', daterange('2018-01-01', '2018-02-01')), + ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- a PK delete that fails because both are referenced: +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +-- a PK delete that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_rng2rng + ALTER CONSTRAINT temporal_fk_rng2rng_fk + DEFERRABLE INITIALLY DEFERRED; + + DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); +COMMIT; +-- then delete the objecting FK record and the same PK delete succeeds: +DELETE FROM temporal_fk_rng2rng WHERE id = '[3,4)'; +DELETE FROM temporal_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); + +-- +-- test FK referenced deletes RESTRICT +-- + +TRUNCATE temporal_rng, temporal_fk_rng2rng; +ALTER TABLE temporal_fk_rng2rng + DROP CONSTRAINT temporal_fk_rng2rng_fk; +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE RESTRICT; + +-- +-- test ON UPDATE/DELETE options +-- + +-- test FK referenced updates CASCADE +INSERT INTO temporal_rng (id, valid_at) VALUES ('[6,7)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[4,5)', daterange('2018-01-01', '2021-01-01'), '[6,7)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE CASCADE ON UPDATE CASCADE; + +-- test FK referenced updates SET NULL +INSERT INTO temporal_rng (id, valid_at) VALUES ('[9,10)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[6,7)', daterange('2018-01-01', '2021-01-01'), '[9,10)'); +ALTER TABLE temporal_fk_rng2rng + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE SET NULL ON UPDATE SET NULL; + +-- test FK referenced updates SET DEFAULT +INSERT INTO temporal_rng (id, valid_at) VALUES ('[-1,-1]', daterange(null, null)); +INSERT INTO temporal_rng (id, valid_at) VALUES ('[12,13)', daterange('2018-01-01', '2021-01-01')); +INSERT INTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[8,9)', daterange('2018-01-01', '2021-01-01'), '[12,13)'); +ALTER TABLE temporal_fk_rng2rng + ALTER COLUMN parent_id SET DEFAULT '[-1,-1]', + ADD CONSTRAINT temporal_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_rng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; + +-- +-- test FOREIGN KEY, multirange references multirange +-- + +-- test table setup +DROP TABLE temporal_mltrng; +CREATE TABLE temporal_mltrng ( id int4range, valid_at datemultirange); +ALTER TABLE temporal_mltrng + ADD CONSTRAINT temporal_mltrng_pk + PRIMARY KEY (id, valid_at WITHOUT OVERLAPS); + +-- Can't create a FK with a mismatched multirange type +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at int4multirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk2 PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk2 FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); + +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +DROP TABLE temporal_fk_mltrng2mltrng; + +-- with mismatched PERIOD columns: + +-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) +-- REFERENCES part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, valid_at) +); +-- (parent_id, valid_at) REFERENCES (id, valid_at) +-- both should specify PERIOD: +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng (id, valid_at) +); +-- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +-- (parent_id, valid_at) REFERENCES [implicit] +-- FOREIGN KEY part should specify PERIOD +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, valid_at) + REFERENCES temporal_mltrng +); +-- (parent_id, PERIOD valid_at) REFERENCES (id) +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id) +); +-- (parent_id) REFERENCES (id, PERIOD valid_at) +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_mltrng (id, PERIOD valid_at) +); +-- with inferred PK on the referenced table: +-- (parent_id, PERIOD valid_at) REFERENCES [implicit] +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng +); +DROP TABLE temporal_fk_mltrng2mltrng; +-- (parent_id) REFERENCES [implicit] +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id) + REFERENCES temporal_mltrng +); + +-- should fail because of duplicate referenced columns: +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_mltrng (id, PERIOD id) +); + +-- Two scalar columns +DROP TABLE temporal_mltrng2; +CREATE TABLE temporal_mltrng2 ( + id1 int4range, + id2 int4range, + valid_at datemultirange, + CONSTRAINT temporal_mltrng2_pk PRIMARY KEY (id1, id2, valid_at WITHOUT OVERLAPS) +); + +CREATE TABLE temporal_fk2_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_fk2_mltrng2mltrng_fk FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at) +); +\d temporal_fk2_mltrng2mltrng +DROP TABLE temporal_fk2_mltrng2mltrng; + +-- +-- test ALTER TABLE ADD CONSTRAINT +-- + +CREATE TABLE temporal_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); + +-- Two scalar columns: +CREATE TABLE temporal_fk2_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id1 int4range, + parent_id2 int4range, + CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +); + +ALTER TABLE temporal_fk2_mltrng2mltrng + ADD CONSTRAINT temporal_fk2_mltrng2mltrng_fk + FOREIGN KEY (parent_id1, parent_id2, PERIOD valid_at) + REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at); +\d temporal_fk2_mltrng2mltrng + +-- should fail because of duplicate referenced columns: +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk2 + FOREIGN KEY (parent_id, PERIOD parent_id) + REFERENCES temporal_mltrng (id, PERIOD id); + +-- +-- test with rows already +-- + +DELETE FROM temporal_fk_mltrng2mltrng; +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-03'))), + ('[1,2)', datemultirange(daterange('2018-03-03', '2018-04-04'))), + ('[2,3)', datemultirange(daterange('2018-01-01', '2018-01-05'))), + ('[3,4)', datemultirange(daterange('2018-01-01', NULL))); + +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-01')), '[1,2)'); +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); +-- should fail: +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +-- okay again: +DELETE FROM temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); + +-- +-- test pg_get_constraintdef +-- + +SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_fk_mltrng2mltrng_fk'; + +-- +-- test FK referencing inserts +-- + +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[1,2)', datemultirange(daterange('2018-01-02', '2018-02-01')), '[1,2)'); +-- should fail: +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); +-- now it should work: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2018-02-03', '2018-03-03'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[2,3)', datemultirange(daterange('2018-01-02', '2018-04-01')), '[1,2)'); + +-- +-- test FK referencing updates +-- + +-- slide the edge across a referenced transition: +UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-02-20')) WHERE id = '[1,2)'; +-- should fail: +UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-05-01')) WHERE id = '[1,2)'; +UPDATE temporal_fk_mltrng2mltrng SET parent_id = '[8,9)' WHERE id = '[1,2)'; + +-- ALTER FK DEFERRABLE + +BEGIN; + INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); + INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + + DELETE FROM temporal_mltrng WHERE id = '[5,6)'; --should not fail yet. +COMMIT; -- should fail here. + +-- +-- test FK referenced updates NO ACTION +-- + +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) + ON UPDATE NO ACTION; +-- a PK update that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'; +-- a PK update that succeeds even though the numeric id is referenced because the range isn't: +DELETE FROM temporal_mltrng WHERE id = '[5,6)'; +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- A PK update sliding the edge between two referenced rows: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[6,7)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[6,7)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[4,5)', datemultirange(daterange('2018-01-15', '2018-02-15')), '[6,7)'); +UPDATE temporal_mltrng + SET valid_at = CASE WHEN lower(valid_at) = '2018-01-01' THEN datemultirange(daterange('2018-01-01', '2018-01-05')) + WHEN lower(valid_at) = '2018-02-01' THEN datemultirange(daterange('2018-01-05', '2018-03-01')) END + WHERE id = '[6,7)'; +-- a PK update shrinking the referenced multirange but still valid: +-- There are two references: one fulfilled by the first pk row, +-- the other fulfilled by both pk rows combined. +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[1,2)', datemultirange(daterange('2018-01-01', '2018-03-01'))), + ('[1,2)', datemultirange(daterange('2018-03-01', '2018-06-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[1,2)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[1,2)'), + ('[2,3)', datemultirange(daterange('2018-01-15', '2018-05-01')), '[1,2)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update growing the referenced multirange is fine: +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-25'::date; +-- a PK update shrinking the referenced multirange and changing the id invalidates the whole multirange (error): +UPDATE temporal_mltrng SET id = '[2,3)', valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update changing only the id invalidates the whole multirange (error): +UPDATE temporal_mltrng SET id = '[2,3)' + WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; +-- a PK update that loses time from both ends, but is still valid: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[2,3)', datemultirange(daterange('2018-01-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[5,6)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[2,3)'); +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-02-15')) + WHERE id = '[2,3)'; +-- a PK update that fails because both are referenced: +UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +-- a PK update that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + + UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +COMMIT; +-- changing the scalar part fails: +UPDATE temporal_mltrng SET id = '[7,8)' + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); + +-- +-- test FK referenced updates RESTRICT +-- + +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + DROP CONSTRAINT temporal_fk_mltrng2mltrng_fk; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at) + ON UPDATE RESTRICT; + +-- +-- test FK referenced deletes NO ACTION +-- + +TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; +ALTER TABLE temporal_fk_mltrng2mltrng + ADD CONSTRAINT temporal_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_mltrng (id, PERIOD valid_at); +-- a PK delete that succeeds because the numeric id isn't referenced: +INSERT INTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +DELETE FROM temporal_mltrng WHERE id = '[5,6)'; +-- a PK delete that succeeds even though the numeric id is referenced because the range isn't: +INSERT INTO temporal_mltrng (id, valid_at) VALUES + ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))), + ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- a PK delete that fails because both are referenced: +DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +-- a PK delete that fails because both are referenced, but not 'til commit: +BEGIN; + ALTER TABLE temporal_fk_mltrng2mltrng + ALTER CONSTRAINT temporal_fk_mltrng2mltrng_fk + DEFERRABLE INITIALLY DEFERRED; + + DELETE FROM temporal_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); +COMMIT; + +-- +-- FK between partitioned tables: ranges +-- + +CREATE TABLE temporal_partitioned_rng ( + id int4range, + valid_at daterange, + name text, + CONSTRAINT temporal_paritioned_rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 partition OF temporal_partitioned_rng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); +CREATE TABLE tp2 partition OF temporal_partitioned_rng FOR VALUES IN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)'); +INSERT INTO temporal_partitioned_rng (id, valid_at, name) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'), + ('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'), + ('[2,3)', daterange('2000-01-01', '2010-01-01'), 'two'); + +CREATE TABLE temporal_partitioned_fk_rng2rng ( + id int4range, + valid_at daterange, + parent_id int4range, + CONSTRAINT temporal_partitioned_fk_rng2rng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_partitioned_fk_rng2rng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng (id, PERIOD valid_at) +) PARTITION BY LIST (id); +CREATE TABLE tfkp1 partition OF temporal_partitioned_fk_rng2rng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); +CREATE TABLE tfkp2 partition OF temporal_partitioned_fk_rng2rng FOR VALUES IN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)'); + +-- +-- partitioned FK referencing inserts +-- + +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[1,2)', daterange('2000-01-01', '2000-02-15'), '[1,2)'), + ('[1,2)', daterange('2001-01-01', '2002-01-01'), '[2,3)'), + ('[2,3)', daterange('2000-01-01', '2000-02-15'), '[1,2)'); +-- should fail: +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2010-01-01', '2010-02-15'), '[1,2)'); +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES + ('[3,4)', daterange('2000-01-01', '2000-02-15'), '[3,4)'); + +-- +-- partitioned FK referencing updates +-- + +UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-02-13') WHERE id = '[2,3)'; +-- move a row from the first partition to the second +UPDATE temporal_partitioned_fk_rng2rng SET id = '[4,5)' WHERE id = '[1,2)'; +-- move a row from the second partition to the first +UPDATE temporal_partitioned_fk_rng2rng SET id = '[1,2)' WHERE id = '[4,5)'; +-- should fail: +UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-04-01') WHERE id = '[1,2)'; + +-- +-- partitioned FK referenced updates NO ACTION +-- + +TRUNCATE temporal_partitioned_rng, temporal_partitioned_fk_rng2rng; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2016-01-01', '2016-02-01')); +UPDATE temporal_partitioned_rng SET valid_at = daterange('2018-01-01', '2018-02-01') WHERE id = '[5,6)'; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-02-01', '2016-03-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- should fail: +UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-01-01', '2016-02-01') + WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); + +-- +-- partitioned FK referenced deletes NO ACTION +-- + +TRUNCATE temporal_partitioned_rng, temporal_partitioned_fk_rng2rng; +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); +INSERT INTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-02-01', '2018-03-01')); +INSERT INTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); +DELETE FROM temporal_partitioned_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-02-01', '2018-03-01'); +-- should fail: +DELETE FROM temporal_partitioned_rng WHERE id = '[5,6)' AND valid_at = daterange('2018-01-01', '2018-02-01'); + +-- +-- partitioned FK referenced updates CASCADE +-- + +ALTER TABLE temporal_partitioned_fk_rng2rng + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE CASCADE ON UPDATE CASCADE; + +-- +-- partitioned FK referenced deletes CASCADE +-- + +-- +-- partitioned FK referenced updates SET NULL +-- + +ALTER TABLE temporal_partitioned_fk_rng2rng + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE SET NULL ON UPDATE SET NULL; + +-- +-- partitioned FK referenced deletes SET NULL +-- + +-- +-- partitioned FK referenced updates SET DEFAULT +-- + +ALTER TABLE temporal_partitioned_fk_rng2rng + ALTER COLUMN parent_id SET DEFAULT '[-1,-1]', + DROP CONSTRAINT temporal_partitioned_fk_rng2rng_fk, + ADD CONSTRAINT temporal_partitioned_fk_rng2rng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_rng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; + +-- +-- partitioned FK referenced deletes SET DEFAULT +-- + +DROP TABLE temporal_partitioned_fk_rng2rng; +DROP TABLE temporal_partitioned_rng; + +-- +-- FK between partitioned tables: multiranges +-- + +CREATE TABLE temporal_partitioned_mltrng ( + id int4range, + valid_at datemultirange, + name text, + CONSTRAINT temporal_paritioned_mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS) +) PARTITION BY LIST (id); +CREATE TABLE tp1 PARTITION OF temporal_partitioned_mltrng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)', '[13,14)', '[15,16)', '[17,18)', '[19,20)', '[21,22)', '[23,24)'); +CREATE TABLE tp2 PARTITION OF temporal_partitioned_mltrng FOR VALUES IN ('[0,1)', '[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)', '[14,15)', '[16,17)', '[18,19)', '[20,21)', '[22,23)', '[24,25)'); +INSERT INTO temporal_partitioned_mltrng (id, valid_at, name) VALUES + ('[1,2)', datemultirange(daterange('2000-01-01', '2000-02-01')), 'one'), + ('[1,2)', datemultirange(daterange('2000-02-01', '2000-03-01')), 'one'), + ('[2,3)', datemultirange(daterange('2000-01-01', '2010-01-01')), 'two'); + +CREATE TABLE temporal_partitioned_fk_mltrng2mltrng ( + id int4range, + valid_at datemultirange, + parent_id int4range, + CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_pk PRIMARY KEY (id, valid_at WITHOUT OVERLAPS), + CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng (id, PERIOD valid_at) +) PARTITION BY LIST (id); +CREATE TABLE tfkp1 PARTITION OF temporal_partitioned_fk_mltrng2mltrng FOR VALUES IN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)', '[13,14)', '[15,16)', '[17,18)', '[19,20)', '[21,22)', '[23,24)'); +CREATE TABLE tfkp2 PARTITION OF temporal_partitioned_fk_mltrng2mltrng FOR VALUES IN ('[0,1)', '[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)', '[14,15)', '[16,17)', '[18,19)', '[20,21)', '[22,23)', '[24,25)'); + +-- +-- partitioned FK referencing inserts +-- + +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[1,2)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[1,2)'), + ('[1,2)', datemultirange(daterange('2001-01-01', '2002-01-01')), '[2,3)'), + ('[2,3)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[1,2)'); +-- should fail: +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2010-01-01', '2010-02-15')), '[1,2)'); +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES + ('[3,4)', datemultirange(daterange('2000-01-01', '2000-02-15')), '[3,4)'); + +-- +-- partitioned FK referencing updates +-- + +UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-02-13')) WHERE id = '[2,3)'; +-- move a row from the first partition to the second +UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[4,5)' WHERE id = '[1,2)'; +-- move a row from the second partition to the first +UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[1,2)' WHERE id = '[4,5)'; +-- should fail: +UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-04-01')) WHERE id = '[1,2)'; + +-- +-- partitioned FK referenced updates NO ACTION +-- + +TRUNCATE temporal_partitioned_mltrng, temporal_partitioned_fk_mltrng2mltrng; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2016-01-01', '2016-02-01'))); +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')) WHERE id = '[5,6)'; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- should fail: +UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) + WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); + +-- +-- partitioned FK referenced deletes NO ACTION +-- + +TRUNCATE temporal_partitioned_mltrng, temporal_partitioned_fk_mltrng2mltrng; +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); +INSERT INTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); +INSERT INTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); +DELETE FROM temporal_partitioned_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); +-- should fail: +DELETE FROM temporal_partitioned_mltrng WHERE id = '[5,6)' AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); + +-- +-- partitioned FK referenced updates CASCADE +-- + +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE CASCADE ON UPDATE CASCADE; + +-- +-- partitioned FK referenced deletes CASCADE +-- + +-- +-- partitioned FK referenced updates SET NULL +-- + +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE SET NULL ON UPDATE SET NULL; + +-- +-- partitioned FK referenced deletes SET NULL +-- + +-- +-- partitioned FK referenced updates SET DEFAULT +-- + +ALTER TABLE temporal_partitioned_fk_mltrng2mltrng + ALTER COLUMN parent_id SET DEFAULT '[0,1)', + DROP CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk, + ADD CONSTRAINT temporal_partitioned_fk_mltrng2mltrng_fk + FOREIGN KEY (parent_id, PERIOD valid_at) + REFERENCES temporal_partitioned_mltrng + ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; + +-- +-- partitioned FK referenced deletes SET DEFAULT +-- + +DROP TABLE temporal_partitioned_fk_mltrng2mltrng; +DROP TABLE temporal_partitioned_mltrng; + +RESET datestyle; diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index 953bac09e45f9..0ea4f508837cf 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -168,6 +168,9 @@ SELECT xmlserialize(CONTENT '' AS text INDENT); -- 'no indent' = not using 'no indent' SELECT xmlserialize(DOCUMENT '42' AS text) = xmlserialize(DOCUMENT '42' AS text NO INDENT); SELECT xmlserialize(CONTENT '42' AS text) = xmlserialize(CONTENT '42' AS text NO INDENT); +-- indent xml strings containing blank nodes +SELECT xmlserialize(DOCUMENT ' ' AS text INDENT); +SELECT xmlserialize(CONTENT 'text node ' AS text INDENT); SELECT xml 'bar' IS DOCUMENT; SELECT xml 'barfoo' IS DOCUMENT; @@ -216,6 +219,8 @@ CREATE VIEW xmlview6 AS SELECT xmlpi(name foo, 'bar'); CREATE VIEW xmlview7 AS SELECT xmlroot(xml '', version no value, standalone yes); CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10)); CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text); +CREATE VIEW xmlview10 AS SELECT xmlserialize(document '42' AS text indent); +CREATE VIEW xmlview11 AS SELECT xmlserialize(document '42' AS character varying no indent); SELECT table_name, view_definition FROM information_schema.views WHERE table_name LIKE 'xmlview%' ORDER BY 1; @@ -430,19 +435,23 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1; -- errors SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2); +SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1); + -- XMLNAMESPACES tests SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), '/zz:rows/zz:row' PASSING '10' COLUMNS a int PATH 'zz:a'); -CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz), - '/zz:rows/zz:row' +CREATE VIEW xmltableview2 AS SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS "Zz"), + '/Zz:rows/Zz:row' PASSING '10' - COLUMNS a int PATH 'zz:a'); + COLUMNS a int PATH 'Zz:a'); SELECT * FROM xmltableview2; +\sv xmltableview2 + SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'), '/rows/row' PASSING '10' diff --git a/src/test/ssl/Makefile b/src/test/ssl/Makefile index 6441a8047b1d0..e8a1639db2d3d 100644 --- a/src/test/ssl/Makefile +++ b/src/test/ssl/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/test/ssl # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/ssl/Makefile diff --git a/src/test/ssl/meson.build b/src/test/ssl/meson.build index b3c5503f79219..cf8b2b9303a0c 100644 --- a/src/test/ssl/meson.build +++ b/src/test/ssl/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tests += { 'name': 'ssl', diff --git a/src/test/ssl/sslfiles.mk b/src/test/ssl/sslfiles.mk index 88c93ec18d544..23aaad0c76671 100644 --- a/src/test/ssl/sslfiles.mk +++ b/src/test/ssl/sslfiles.mk @@ -9,7 +9,7 @@ # The main Makefile in this directory defers to this helper file when # building the sslfiles-related targets. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/test/ssl/sslfiles.mk diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl index b8773270235ae..2cb4d0ffd4199 100644 --- a/src/test/ssl/t/001_ssltests.pl +++ b/src/test/ssl/t/001_ssltests.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -17,7 +17,7 @@ { plan skip_all => 'OpenSSL not supported by this build'; } -elsif (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) { plan skip_all => 'Potentially unsafe test SSL not enabled in PG_TEST_EXTRA'; @@ -35,10 +35,8 @@ sub switch_server_cert $ssl_server->switch_server_cert(@_); } -# Determine whether this build uses OpenSSL or LibreSSL. As a heuristic, the -# HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. (Nor for OpenSSL -# 1.0.1, but that's old enough that accommodating it isn't worth the cost.) -my $libressl = not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1"); +# Determine whether this build uses OpenSSL or LibreSSL. +my $libressl = $ssl_server->is_libressl; #### Some configuration @@ -61,6 +59,8 @@ sub switch_server_cert note "setting up data directory"; my $node = PostgreSQL::Test::Cluster->new('primary'); $node->init; +# Needed to allow connect_fails to inspect postmaster log: +$node->append_conf('postgresql.conf', "log_min_messages = debug2"); # PGHOST is enforced here to set up the node, subsequent connections # will use a dedicated connection string. @@ -117,6 +117,18 @@ sub switch_server_cert $result = $node->restart(fail_ok => 1); is($result, 1, 'restart succeeds with correct SSL protocol bounds'); +# Test parsing colon-separated groups. Resetting to a default value to clear +# the error is fine since the call to switch_server_cert in the client side +# tests will overwrite ssl_groups with a known set of groups. +$node->append_conf('sslconfig.conf', qq{ssl_groups='bad:value'}); +my $log_size = -s $node->logfile; +$result = $node->restart(fail_ok => 1); +is($result, 0, 'restart fails with incorrect groups'); +ok($node->log_contains(qr/no SSL error reported/) == 0, + 'error message translated'); +$node->append_conf('ssl_config.conf', qq{ssl_groups='prime256v1'}); +$result = $node->restart(fail_ok => 1); + ### Run client-side tests. ### ### Test that libpq accepts/rejects the connection correctly, depending @@ -136,6 +148,33 @@ sub switch_server_cert $common_connstr = "$default_ssl_connstr user=ssltestuser dbname=trustdb hostaddr=$SERVERHOSTADDR host=common-name.pg-ssltest.test"; +SKIP: +{ + skip "Keylogging is not supported with LibreSSL", 5 if $libressl; + + my $tempdir = PostgreSQL::Test::Utils::tempdir; + my @status; + + # Properly escape backslashes in the path + $tempdir =~ s/\\/\\\\/g; + + # Connect should work with a given sslkeylogfile + $node->connect_ok( + "$common_connstr sslrootcert=ssl/root+server_ca.crt sslkeylogfile=$tempdir/key.txt sslmode=require", + "connect with server root cert and sslkeylogfile=$tempdir/key.txt"); + + # Verify the key file exists + ok(-f "$tempdir/key.txt", "keylog file exists at: $tempdir/key.txt"); + + # Skip permission checks on Windows/Cygwin + skip "Permissions check not enforced on Windows", 2 + if ($windows_os || $Config::Config{osname} eq 'cygwin'); + + ok( (@status = stat("$tempdir/key.txt")), + "keylog file exists and returned status"); + ok(@status && !($status[2] & 0006), "keylog file is not world readable"); +} + # The server should not accept non-SSL connections. $node->connect_fails( "$common_connstr sslmode=disable", @@ -532,12 +571,14 @@ sub switch_server_cert # pg_stat_ssl command_like( [ - 'psql', '-X', - '-A', '-F', - ',', '-P', - 'null=_null_', '-d', - "$common_connstr sslrootcert=invalid", '-c', - "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" + 'psql', + '--no-psqlrc', + '--no-align', + '--field-separator' => ',', + '--pset', => 'null=_null_', + '--dbname' => "$common_connstr sslrootcert=invalid", + '--command' => + "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" ], qr{^pid,ssl,version,cipher,bits,client_dn,client_serial,issuer_dn\r?\n ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,_null_,_null_,_null_\r?$}mx, @@ -731,17 +772,15 @@ sub switch_server_cert command_like( [ 'psql', - '-X', - '-A', - '-F', - ',', - '-P', - 'null=_null_', - '-d', - "$common_connstr user=ssltestuser sslcert=ssl/client.crt " + '--no-psqlrc', + '--no-align', + '--field-separator' => ',', + '--pset' => 'null=_null_', + '--dbname' => + "$common_connstr user=ssltestuser sslcert=ssl/client.crt " . sslkey('client.key'), - '-c', - "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" + '--command' => + "SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid()" ], qr{^pid,ssl,version,cipher,bits,client_dn,client_serial,issuer_dn\r?\n ^\d+,t,TLSv[\d.]+,[\w-]+,\d+,/?CN=ssltestuser,$serialno,/?\QCN=Test CA for PostgreSQL SSL regression test client certs\E\r?$}mx, @@ -769,10 +808,8 @@ sub switch_server_cert expected_stderr => qr/certificate authentication failed for user "anotheruser"/, # certificate authentication should be logged even on failure - # temporarily(?) skip this check due to timing issue - # log_like => - # [qr/connection authenticated: identity="CN=ssltestuser" method=cert/], -); + log_like => + [qr/connection authenticated: identity="CN=ssltestuser" method=cert/],); # revoked client cert $node->connect_fails( @@ -780,11 +817,10 @@ sub switch_server_cert . sslkey('client-revoked.key'), "certificate authorization fails with revoked client cert", expected_stderr => qr|SSL error: ssl[a-z0-9/]* alert certificate revoked|, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 0: certificate revoked}, - # qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number 2315134995201656577, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, - # ], + log_like => [ + qr{Client certificate verification failed at depth 0: certificate revoked}, + qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ], # revoked certificates should not authenticate the user log_unlike => [qr/connection authenticated:/],); @@ -834,24 +870,20 @@ sub switch_server_cert $common_connstr . " " . "sslmode=require sslcert=ssl/client.crt", "intermediate client certificate is missing", expected_stderr => qr/SSL error: tlsv1 alert unknown ca/, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 0: unable to get local issuer certificate}, - # qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number 2315134995201656576, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, - # ] -); + log_like => [ + qr{Client certificate verification failed at depth 0: unable to get local issuer certificate}, + qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ]); $node->connect_fails( "$common_connstr sslmode=require sslcert=ssl/client-long.crt " . sslkey('client-long.key'), "logged client certificate Subjects are truncated if they're too long", expected_stderr => qr/SSL error: tlsv1 alert unknown ca/, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 0: unable to get local issuer certificate}, - # qr{Failed certificate data \(unverified\): subject "\.\.\./CN=ssl-123456789012345678901234567890123456789012345678901234567890", serial number 2315418733629425152, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, - # ] -); + log_like => [ + qr{Client certificate verification failed at depth 0: unable to get local issuer certificate}, + qr{Failed certificate data \(unverified\): subject "\.\.\./CN=ssl-123456789012345678901234567890123456789012345678901234567890", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ]); # Use an invalid cafile here so that the next test won't be able to verify the # client CA. @@ -866,12 +898,14 @@ sub switch_server_cert "$common_connstr sslmode=require sslcert=ssl/client+client_ca.crt", "intermediate client certificate is untrusted", expected_stderr => qr/SSL error: tlsv1 alert unknown ca/, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 1: unable to get local issuer certificate}, - # qr{Failed certificate data \(unverified\): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number 2315134995201656577, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite"}, - # ] -); + log_like => [ + qr{Client certificate verification failed at depth 1: unable to get local issuer certificate}, + # As of 5/2025, LibreSSL reports a different cert as being at fault; + # it's wrong, but seems to be their bug not ours + !$libressl + ? qr{Failed certificate data \(unverified\): subject "/CN=Test CA for PostgreSQL SSL regression test client certs", serial number \d+, issuer "/CN=Test root CA for PostgreSQL SSL regression test suite"} + : qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ]); # test server-side CRL directory switch_server_cert( @@ -885,12 +919,10 @@ sub switch_server_cert . sslkey('client-revoked.key'), "certificate authorization fails with revoked client cert with server-side CRL directory", expected_stderr => qr|SSL error: ssl[a-z0-9/]* alert certificate revoked|, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 0: certificate revoked}, - # qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number 2315134995201656577, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, - # ] -); + log_like => [ + qr{Client certificate verification failed at depth 0: certificate revoked}, + qr{Failed certificate data \(unverified\): subject "/CN=ssltestuser", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ]); # revoked client cert, non-ASCII subject $node->connect_fails( @@ -898,11 +930,9 @@ sub switch_server_cert . sslkey('client-revoked-utf8.key'), "certificate authorization fails with revoked UTF-8 client cert with server-side CRL directory", expected_stderr => qr|SSL error: ssl[a-z0-9/]* alert certificate revoked|, - # temporarily(?) skip this check due to timing issue - # log_like => [ - # qr{Client certificate verification failed at depth 0: certificate revoked}, - # qr{Failed certificate data \(unverified\): subject "/CN=\\xce\\x9f\\xce\\xb4\\xcf\\x85\\xcf\\x83\\xcf\\x83\\xce\\xad\\xce\\xb1\\xcf\\x82", serial number 2315420958437414144, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, - # ] -); + log_like => [ + qr{Client certificate verification failed at depth 0: certificate revoked}, + qr{Failed certificate data \(unverified\): subject "/CN=\\xce\\x9f\\xce\\xb4\\xcf\\x85\\xcf\\x83\\xcf\\x83\\xce\\xad\\xce\\xb1\\xcf\\x82", serial number \d+, issuer "/CN=Test CA for PostgreSQL SSL regression test client certs"}, + ]); done_testing(); diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl index dd9322412434f..60b60b286570b 100644 --- a/src/test/ssl/t/002_scram.pl +++ b/src/test/ssl/t/002_scram.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test SCRAM authentication and TLS channel binding types @@ -20,7 +20,7 @@ { plan skip_all => 'OpenSSL not supported by this build'; } -elsif (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) { plan skip_all => 'Potentially unsafe test SSL not enabled in PG_TEST_EXTRA'; @@ -44,11 +44,17 @@ sub switch_server_cert # This is the pattern to use in pg_hba.conf to match incoming connections. my $SERVERHOSTCIDR = '127.0.0.1/32'; +# Determine whether this build uses OpenSSL or LibreSSL. +my $libressl = $ssl_server->is_libressl; + # Determine whether build supports detection of hash algorithms for # RSA-PSS certificates. my $supports_rsapss_certs = check_pg_config("#define HAVE_X509_GET_SIGNATURE_INFO 1"); +# As of 5/2025, LibreSSL doesn't actually work for RSA-PSS certificates. +$supports_rsapss_certs = 0 if $libressl; + # Allocation of base connection string shared among multiple tests. my $common_connstr; @@ -71,8 +77,8 @@ sub switch_server_cert $ssl_server->configure_test_server_for_ssl( $node, $SERVERHOSTADDR, $SERVERHOSTCIDR, "scram-sha-256", - 'password' => "pass", - 'password_enc' => "scram-sha-256"); + password => "pass", + password_enc => "scram-sha-256"); switch_server_cert($node, certfile => 'server-cn-only'); $ENV{PGPASSWORD} = "pass"; $common_connstr = diff --git a/src/test/ssl/t/003_sslinfo.pl b/src/test/ssl/t/003_sslinfo.pl index 2ae5724846b1d..3c756489cdf5e 100644 --- a/src/test/ssl/t/003_sslinfo.pl +++ b/src/test/ssl/t/003_sslinfo.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -18,7 +18,7 @@ { plan skip_all => 'OpenSSL not supported by this build'; } -elsif (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) +if (!$ENV{PG_TEST_EXTRA} || $ENV{PG_TEST_EXTRA} !~ /\bssl\b/) { plan skip_all => 'Potentially unsafe test SSL not enabled in PG_TEST_EXTRA'; @@ -186,9 +186,8 @@ sub switch_server_cert $result = $node->safe_psql( "trustdb", "SELECT ssl_client_cert_present();", - connstr => "$common_connstr dbname=trustdb $c->{'opts'}"); - is($result, $c->{'present'}, - "ssl_client_cert_present() for $c->{'opts'}"); + connstr => "$common_connstr dbname=trustdb $c->{opts}"); + is($result, $c->{present}, "ssl_client_cert_present() for $c->{opts}"); } done_testing(); diff --git a/src/test/ssl/t/SSL/Backend/OpenSSL.pm b/src/test/ssl/t/SSL/Backend/OpenSSL.pm index 410b4b1a3f5a8..4159addb700c1 100644 --- a/src/test/ssl/t/SSL/Backend/OpenSSL.pm +++ b/src/test/ssl/t/SSL/Backend/OpenSSL.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod @@ -26,6 +26,7 @@ package SSL::Backend::OpenSSL; use strict; use warnings FATAL => 'all'; +use PostgreSQL::Test::Utils; use File::Basename; use File::Copy; @@ -205,6 +206,23 @@ sub get_library return $self->{_library}; } +=pod + +=item $backend->library_is_libressl() + +Detect whether the SSL library is LibreSSL. + +=cut + +sub library_is_libressl +{ + my ($self) = @_; + + # The HAVE_SSL_CTX_SET_CERT_CB macro isn't defined for LibreSSL. + # We may eventually need a less-bogus heuristic. + return not check_pg_config("#define HAVE_SSL_CTX_SET_CERT_CB 1"); +} + # Internal method for copying a set of files, taking into account wildcards sub _copy_files { diff --git a/src/test/ssl/t/SSL/Server.pm b/src/test/ssl/t/SSL/Server.pm index 021eec74abff0..96f0f201e9c0b 100644 --- a/src/test/ssl/t/SSL/Server.pm +++ b/src/test/ssl/t/SSL/Server.pm @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group =pod @@ -197,17 +197,18 @@ sub configure_test_server_for_ssl } # enable logging etc. - open my $conf, '>>', "$pgdata/postgresql.conf" or die $!; - print $conf "fsync=off\n"; - print $conf "log_connections=on\n"; - print $conf "log_hostname=on\n"; - print $conf "listen_addresses='$serverhost'\n"; - print $conf "log_statement=all\n"; + $node->append_conf( + 'postgresql.conf', <append_conf('postgresql.conf', "include 'sslconfig.conf'"); # SSL configuration will be placed here open my $sslconf, '>', "$pgdata/sslconfig.conf" or die $!; @@ -243,6 +244,23 @@ sub ssl_library =pod +=item $server->is_libressl() + +Detect whether the currently used SSL backend is LibreSSL. +(Ideally we'd not need this hack, but presently we do.) + +=cut + +sub is_libressl +{ + my $self = shift; + my $backend = $self->{backend}; + + return $backend->library_is_libressl(); +} + +=pod + =item switch_server_cert(params) Change the configuration to use the given set of certificate, key, ca and @@ -296,13 +314,17 @@ sub switch_server_cert my %params = @_; my $pgdata = $node->data_dir; - open my $sslconf, '>', "$pgdata/sslconfig.conf" or die $!; - print $sslconf "ssl=on\n"; - print $sslconf $backend->set_server_cert(\%params); - print $sslconf "ssl_passphrase_command='" - . $params{passphrase_cmd} . "'\n" + ok(unlink($node->data_dir . '/sslconfig.conf')); + $node->append_conf('sslconfig.conf', "ssl=on"); + $node->append_conf('sslconfig.conf', $backend->set_server_cert(\%params)); + # use lists of ECDH curves and cipher suites for syntax testing + $node->append_conf('sslconfig.conf', 'ssl_groups=X25519:prime256v1:secp521r1'); + $node->append_conf('sslconfig.conf', + 'ssl_tls13_ciphers=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256'); + + $node->append_conf('sslconfig.conf', + "ssl_passphrase_command='" . $params{passphrase_cmd} . "'") if defined $params{passphrase_cmd}; - close $sslconf; return if (defined($params{restart}) && $params{restart} eq 'no'); @@ -321,35 +343,32 @@ sub _configure_hba_for_ssl # but seems best to keep it as narrow as possible for security reasons. # # When connecting to certdb, also check the client certificate. - open my $hba, '>', "$pgdata/pg_hba.conf" or die $!; - print $hba - "# TYPE DATABASE USER ADDRESS METHOD OPTIONS\n"; - print $hba - "hostssl trustdb md5testuser $servercidr md5\n"; - print $hba - "hostssl trustdb all $servercidr $authmethod\n"; - print $hba - "hostssl verifydb ssltestuser $servercidr $authmethod clientcert=verify-full\n"; - print $hba - "hostssl verifydb anotheruser $servercidr $authmethod clientcert=verify-full\n"; - print $hba - "hostssl verifydb yetanotheruser $servercidr $authmethod clientcert=verify-ca\n"; - print $hba - "hostssl certdb all $servercidr cert\n"; - print $hba - "hostssl certdb_dn all $servercidr cert clientname=DN map=dn\n", - "hostssl certdb_dn_re all $servercidr cert clientname=DN map=dnre\n", - "hostssl certdb_cn all $servercidr cert clientname=CN map=cn\n"; - close $hba; + ok(unlink($node->data_dir . '/pg_hba.conf')); + $node->append_conf( + 'pg_hba.conf', <", "$pgdata/pg_ident.conf" or die $!; - print $map - "# MAPNAME SYSTEM-USERNAME PG-USERNAME\n", - "dn \"CN=ssltestuser-dn,OU=Testing,OU=Engineering,O=PGDG\" ssltestuser\n", - "dnre \"/^.*OU=Testing,.*\$\" ssltestuser\n", - "cn ssltestuser-dn ssltestuser\n"; - + ok(unlink($node->data_dir . '/pg_ident.conf')); + $node->append_conf( + 'pg_ident.conf', <wait_for_subscription_sync($node_publisher, 'tap_sub'); +# Reset IO statistics, for the WAL sender check with pg_stat_io. +$node_publisher->safe_psql('postgres', "SELECT pg_stat_reset_shared('io')"); + my $result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab_notrep"); is($result, qq(0), 'check non-replicated table is empty on subscriber'); @@ -184,6 +187,19 @@ $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab_no_col"); is($result, qq(2), 'check replicated changes for table having no columns'); +# Wait for the logical WAL sender to update its IO statistics. This is +# done before the next restart, which would force a flush of its stats, and +# far enough from the reset done above to not impact the run time. +$node_publisher->poll_query_until( + 'postgres', + qq[SELECT sum(reads) > 0 + FROM pg_catalog.pg_stat_io + WHERE backend_type = 'walsender' + AND object = 'wal'] + ) + or die + "Timed out while waiting for the walsender to update its IO statistics"; + # insert some duplicate rows $node_publisher->safe_psql('postgres', "INSERT INTO tab_full SELECT generate_series(1,10)"); @@ -331,13 +347,8 @@ 2|baz), 'update works with REPLICA IDENTITY FULL and a primary key'); -# Check that subscriber handles cases where update/delete target tuple -# is missing. We have to look for the DEBUG1 log messages about that, -# so temporarily bump up the log verbosity. -$node_subscriber->append_conf('postgresql.conf', "log_min_messages = debug1"); -$node_subscriber->reload; - $node_subscriber->safe_psql('postgres', "DELETE FROM tab_full_pk"); +$node_subscriber->safe_psql('postgres', "DELETE FROM tab_full WHERE a = 25"); # Note that the current location of the log file is not grabbed immediately # after reloading the configuration, but after sending one SQL command to @@ -346,16 +357,21 @@ $node_publisher->safe_psql('postgres', "UPDATE tab_full_pk SET b = 'quux' WHERE a = 1"); +$node_publisher->safe_psql('postgres', + "UPDATE tab_full SET a = a + 1 WHERE a = 25"); $node_publisher->safe_psql('postgres', "DELETE FROM tab_full_pk WHERE a = 2"); $node_publisher->wait_for_catchup('tap_sub'); my $logfile = slurp_file($node_subscriber->logfile, $log_location); ok( $logfile =~ - qr/logical replication did not find row to be updated in replication target relation "tab_full_pk"/, + qr/conflict detected on relation "public.tab_full_pk": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(1, quux\); replica identity \(a\)=\(1\)/m, + 'update target row is missing'); +ok( $logfile =~ + qr/conflict detected on relation "public.tab_full": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(26\); replica identity full \(25\)/m, 'update target row is missing'); ok( $logfile =~ - qr/logical replication did not find row to be deleted in replication target relation "tab_full_pk"/, + qr/conflict detected on relation "public.tab_full_pk": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(2\)/m, 'delete target row is missing'); $node_subscriber->append_conf('postgresql.conf', @@ -517,7 +533,7 @@ $result = $node_subscriber->safe_psql('postgres', "SELECT count(*), min(a), max(a) FROM tab_full"); -is($result, qq(21|0|100), 'check replicated insert after alter publication'); +is($result, qq(19|0|100), 'check replicated insert after alter publication'); # check restart on rename $oldpid = $node_publisher->safe_psql('postgres', diff --git a/src/test/subscription/t/002_types.pl b/src/test/subscription/t/002_types.pl index 08186e5246c48..75beb594c58d4 100644 --- a/src/test/subscription/t/002_types.pl +++ b/src/test/subscription/t/002_types.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This tests that more complex datatypes are replicated correctly # by logical replication diff --git a/src/test/subscription/t/003_constraints.pl b/src/test/subscription/t/003_constraints.pl index 4f115eeaa3368..e333263d604f5 100644 --- a/src/test/subscription/t/003_constraints.pl +++ b/src/test/subscription/t/003_constraints.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # This test checks that constraints work on subscriber use strict; diff --git a/src/test/subscription/t/004_sync.pl b/src/test/subscription/t/004_sync.pl index a2d9462395ac7..d5eac05a3b309 100644 --- a/src/test/subscription/t/004_sync.pl +++ b/src/test/subscription/t/004_sync.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for logical replication table syncing use strict; diff --git a/src/test/subscription/t/005_encoding.pl b/src/test/subscription/t/005_encoding.pl index 38e3e0f0bce43..f74a22995d95c 100644 --- a/src/test/subscription/t/005_encoding.pl +++ b/src/test/subscription/t/005_encoding.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test replication between databases with different encodings use strict; diff --git a/src/test/subscription/t/006_rewrite.pl b/src/test/subscription/t/006_rewrite.pl index af464c306dd47..651447e0bc581 100644 --- a/src/test/subscription/t/006_rewrite.pl +++ b/src/test/subscription/t/006_rewrite.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test logical replication behavior with heap rewrites use strict; diff --git a/src/test/subscription/t/007_ddl.pl b/src/test/subscription/t/007_ddl.pl index 7ab51d6343dda..7d12bcbddb687 100644 --- a/src/test/subscription/t/007_ddl.pl +++ b/src/test/subscription/t/007_ddl.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test some logical replication DDL behavior use strict; @@ -69,6 +69,93 @@ "Alter subscription set publication throws warning for non-existent publication" ); +# Cleanup +$node_publisher->safe_psql('postgres', qq[ + DROP PUBLICATION mypub; + SELECT pg_drop_replication_slot('mysub'); +]); +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION mysub1"); + +# +# Test ALTER PUBLICATION RENAME command during the replication +# + +# Test function for swapping name of publications +sub test_swap +{ + my ($table_name, $pubname, $appname) = @_; + + # Confirms tuples can be replicated + $node_publisher->safe_psql('postgres', "INSERT INTO $table_name VALUES (1);"); + $node_publisher->wait_for_catchup($appname); + my $result = + $node_subscriber->safe_psql('postgres', "SELECT a FROM $table_name"); + is($result, qq(1), 'check replication worked well before renaming a publication'); + + # Swap the name of publications; $pubname <-> pub_empty + $node_publisher->safe_psql('postgres', qq[ + ALTER PUBLICATION $pubname RENAME TO tap_pub_tmp; + ALTER PUBLICATION pub_empty RENAME TO $pubname; + ALTER PUBLICATION tap_pub_tmp RENAME TO pub_empty; + ]); + + # Insert the data again + $node_publisher->safe_psql('postgres', "INSERT INTO $table_name VALUES (2);"); + $node_publisher->wait_for_catchup($appname); + + # Confirms the second tuple won't be replicated because $pubname does not + # contains relations anymore. + $result = + $node_subscriber->safe_psql('postgres', "SELECT a FROM $table_name ORDER BY a"); + is($result, qq(1), + 'check the tuple inserted after the RENAME was not replicated'); + + # Restore the name of publications because it can be called several times + $node_publisher->safe_psql('postgres', qq[ + ALTER PUBLICATION $pubname RENAME TO tap_pub_tmp; + ALTER PUBLICATION pub_empty RENAME TO $pubname; + ALTER PUBLICATION tap_pub_tmp RENAME TO pub_empty; + ]); +} + +# Create another table +$ddl = "CREATE TABLE test2 (a int, b text);"; +$node_publisher->safe_psql('postgres', $ddl); +$node_subscriber->safe_psql('postgres', $ddl); + +# Create publications and a subscription +$node_publisher->safe_psql('postgres', qq[ + CREATE PUBLICATION pub_empty; + CREATE PUBLICATION pub_for_tab FOR TABLE test1; + CREATE PUBLICATION pub_for_all_tables FOR ALL TABLES; +]); +$node_subscriber->safe_psql('postgres', + "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr' PUBLICATION pub_for_tab" +); +$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub'); + +# Confirms RENAME command works well for a publication +test_swap('test1', 'pub_for_tab', 'tap_sub'); + +# Switches a publication which includes all tables +$node_subscriber->safe_psql('postgres', + "ALTER SUBSCRIPTION tap_sub SET PUBLICATION pub_for_all_tables;" +); +$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub'); + +# Confirms RENAME command works well for ALL TABLES publication +test_swap('test2', 'pub_for_all_tables', 'tap_sub'); + +# Cleanup +$node_publisher->safe_psql('postgres', qq[ + DROP PUBLICATION pub_empty, pub_for_tab, pub_for_all_tables; + DROP TABLE test1, test2; +]); +$node_subscriber->safe_psql('postgres', qq[ + DROP SUBSCRIPTION tap_sub; + DROP TABLE test1, test2; +]); + $node_subscriber->stop; $node_publisher->stop; diff --git a/src/test/subscription/t/008_diff_schema.pl b/src/test/subscription/t/008_diff_schema.pl index cf04f85584aad..d0d24f0eb96d0 100644 --- a/src/test/subscription/t/008_diff_schema.pl +++ b/src/test/subscription/t/008_diff_schema.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test behavior with different schema on subscriber use strict; @@ -118,6 +118,21 @@ qq(1|1|1), 'check replicated inserts on subscriber'); +# Test if the expected error is reported when the subscriber table is missing +# columns which were specified on the publisher table. +$node_publisher->safe_psql('postgres', + "CREATE TABLE test_tab3 (a int, b int, c int)"); +$node_subscriber->safe_psql('postgres', "CREATE TABLE test_tab3 (a int)"); + +my $offset = -s $node_subscriber->logfile; + +$node_subscriber->safe_psql('postgres', + "ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION"); + +$node_subscriber->wait_for_log( + qr/ERROR: ( [A-Z0-9]+:)? logical replication target relation "public.test_tab3" is missing replicated columns: "b", "c"/, + $offset); + $node_subscriber->stop; $node_publisher->stop; diff --git a/src/test/subscription/t/009_matviews.pl b/src/test/subscription/t/009_matviews.pl index 40f65d4f5d918..9316fd1bb6d95 100644 --- a/src/test/subscription/t/009_matviews.pl +++ b/src/test/subscription/t/009_matviews.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test materialized views behavior use strict; diff --git a/src/test/subscription/t/010_truncate.pl b/src/test/subscription/t/010_truncate.pl index e41e1a8db7f26..3d16c2a800de9 100644 --- a/src/test/subscription/t/010_truncate.pl +++ b/src/test/subscription/t/010_truncate.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test TRUNCATE use strict; diff --git a/src/test/subscription/t/011_generated.pl b/src/test/subscription/t/011_generated.pl index 8b2e5f4708eb2..c7a4c52e4f2a9 100644 --- a/src/test/subscription/t/011_generated.pl +++ b/src/test/subscription/t/011_generated.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test generated columns use strict; @@ -21,11 +21,11 @@ my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; $node_publisher->safe_psql('postgres', - "CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED)" + "CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (a * 3) VIRTUAL)" ); $node_subscriber->safe_psql('postgres', - "CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 22) STORED, c int)" + "CREATE TABLE tab1 (a int PRIMARY KEY, b int GENERATED ALWAYS AS (a * 22) STORED, c int GENERATED ALWAYS AS (a * 33) VIRTUAL, d int)" ); # data for initial sync @@ -42,10 +42,11 @@ # Wait for initial sync of all subscriptions $node_subscriber->wait_for_subscription_sync; -my $result = $node_subscriber->safe_psql('postgres', "SELECT a, b FROM tab1"); -is( $result, qq(1|22 -2|44 -3|66), 'generated columns initial sync'); +my $result = + $node_subscriber->safe_psql('postgres', "SELECT a, b, c FROM tab1"); +is( $result, qq(1|22|33 +2|44|66 +3|66|99), 'generated columns initial sync'); # data to replicate @@ -56,11 +57,11 @@ $node_publisher->wait_for_catchup('sub1'); $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1"); -is( $result, qq(1|22| -2|44| -3|66| -4|88| -6|132|), 'generated columns replicated'); +is( $result, qq(1|22|33| +2|44|66| +3|66|99| +4|88|132| +6|132|198|), 'generated columns replicated'); # try it with a subscriber-side trigger @@ -69,7 +70,7 @@ CREATE FUNCTION tab1_trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN - NEW.c := NEW.a + 10; + NEW.d := NEW.a + 10; RETURN NEW; END $$; @@ -88,12 +89,285 @@ BEGIN $result = $node_subscriber->safe_psql('postgres', "SELECT * FROM tab1 ORDER BY 1"); -is( $result, qq(1|22| -2|44| -3|66| -4|88| -6|132| -8|176|18 -9|198|19), 'generated columns replicated with trigger'); +is( $result, qq(1|22|33| +2|44|66| +3|66|99| +4|88|132| +6|132|198| +8|176|264|18 +9|198|297|19), 'generated columns replicated with trigger'); + +# cleanup +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); +$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); + +# ============================================================================= +# Exercise logical replication of a generated column to a subscriber side +# regular column. This is done both when the publication parameter +# 'publish_generated_columns' is set to 'none' (to confirm existing default +# behavior), and is set to 'stored' (to confirm replication occurs). +# +# The test environment is set up as follows: +# +# - Publication pub1 on the 'postgres' database. +# pub1 has publish_generated_columns as 'none'. +# +# - Publication pub2 on the 'postgres' database. +# pub2 has publish_generated_columns as 'stored'. +# +# - Subscription sub1 on the 'postgres' database for publication pub1. +# +# - Subscription sub2 on the 'test_pgc_true' database for publication pub2. +# ============================================================================= + +$node_subscriber->safe_psql('postgres', "CREATE DATABASE test_pgc_true"); + +# -------------------------------------------------- +# Test Case: Generated to regular column replication +# Publisher table has generated column 'b'. +# Subscriber table has regular column 'b'. +# -------------------------------------------------- + +# Create table and publications. Insert data to verify initial sync. +$node_publisher->safe_psql( + 'postgres', qq( + CREATE TABLE tab_gen_to_nogen (a int, b int GENERATED ALWAYS AS (a * 2) STORED); + INSERT INTO tab_gen_to_nogen (a) VALUES (1), (2), (3); + CREATE PUBLICATION regress_pub1_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = none); + CREATE PUBLICATION regress_pub2_gen_to_nogen FOR TABLE tab_gen_to_nogen WITH (publish_generated_columns = stored); +)); + +# Create the table and subscription in the 'postgres' database. +$node_subscriber->safe_psql( + 'postgres', qq( + CREATE TABLE tab_gen_to_nogen (a int, b int); + CREATE SUBSCRIPTION regress_sub1_gen_to_nogen CONNECTION '$publisher_connstr' PUBLICATION regress_pub1_gen_to_nogen WITH (copy_data = true); +)); + +# Create the table and subscription in the 'test_pgc_true' database. +$node_subscriber->safe_psql( + 'test_pgc_true', qq( + CREATE TABLE tab_gen_to_nogen (a int, b int); + CREATE SUBSCRIPTION regress_sub2_gen_to_nogen CONNECTION '$publisher_connstr' PUBLICATION regress_pub2_gen_to_nogen WITH (copy_data = true); +)); + +# Wait for the initial synchronization of both subscriptions. +$node_subscriber->wait_for_subscription_sync($node_publisher, + 'regress_sub1_gen_to_nogen', 'postgres'); +$node_subscriber->wait_for_subscription_sync($node_publisher, + 'regress_sub2_gen_to_nogen', 'test_pgc_true'); + +# Verify that generated column data is not copied during the initial +# synchronization when publish_generated_columns is set to 'none'. +$result = $node_subscriber->safe_psql('postgres', + "SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); +is( $result, qq(1| +2| +3|), 'tab_gen_to_nogen initial sync, when publish_generated_columns=none'); + +# Verify that generated column data is copied during the initial synchronization +# when publish_generated_columns is set to 'stored'. +$result = $node_subscriber->safe_psql('test_pgc_true', + "SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); +is( $result, qq(1|2 +2|4 +3|6), + 'tab_gen_to_nogen initial sync, when publish_generated_columns=stored'); + +# Insert data to verify incremental replication. +$node_publisher->safe_psql('postgres', + "INSERT INTO tab_gen_to_nogen VALUES (4), (5)"); + +# Verify that the generated column data is not replicated during incremental +# replication when publish_generated_columns is set to 'none'. +$node_publisher->wait_for_catchup('regress_sub1_gen_to_nogen'); +$result = $node_subscriber->safe_psql('postgres', + "SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); +is( $result, qq(1| +2| +3| +4| +5|), + 'tab_gen_to_nogen incremental replication, when publish_generated_columns=none' +); + +# Verify that generated column data is replicated during incremental +# synchronization when publish_generated_columns is set to 'stored'. +$node_publisher->wait_for_catchup('regress_sub2_gen_to_nogen'); +$result = $node_subscriber->safe_psql('test_pgc_true', + "SELECT a, b FROM tab_gen_to_nogen ORDER BY a"); +is( $result, qq(1|2 +2|4 +3|6 +4|8 +5|10), + 'tab_gen_to_nogen incremental replication, when publish_generated_columns=stored' +); + +# cleanup +$node_subscriber->safe_psql('postgres', + "DROP SUBSCRIPTION regress_sub1_gen_to_nogen"); +$node_subscriber->safe_psql('test_pgc_true', + "DROP SUBSCRIPTION regress_sub2_gen_to_nogen"); +$node_publisher->safe_psql( + 'postgres', qq( + DROP PUBLICATION regress_pub1_gen_to_nogen; + DROP PUBLICATION regress_pub2_gen_to_nogen; +)); +$node_subscriber->safe_psql('test_pgc_true', "DROP table tab_gen_to_nogen"); +$node_subscriber->safe_psql('postgres', "DROP DATABASE test_pgc_true"); + +# ============================================================================= +# The following test cases demonstrate how publication column lists interact +# with the publication parameter 'publish_generated_columns'. +# +# Test: Column lists take precedence, so generated columns in a column list +# will be replicated even when publish_generated_columns is 'none'. +# +# Test: When there is a column list, only those generated columns named in the +# column list will be replicated even when publish_generated_columns is +# 'stored'. +# ============================================================================= + +# -------------------------------------------------- +# Test Case: Publisher replicates the column list, including generated columns, +# even when the publish_generated_columns option is set to 'none'. +# -------------------------------------------------- + +# Create table and publication. Insert data to verify initial sync. +$node_publisher->safe_psql( + 'postgres', qq( + CREATE TABLE tab2 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED); + INSERT INTO tab2 (a) VALUES (1), (2); + CREATE PUBLICATION pub1 FOR table tab2(gen1) WITH (publish_generated_columns=none); +)); + +# Create table and subscription. +$node_subscriber->safe_psql( + 'postgres', qq( + CREATE TABLE tab2 (a int, gen1 int); + CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1 WITH (copy_data = true); +)); + +# Wait for initial sync. +$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1'); + +# Initial sync test when publish_generated_columns is 'none'. +# Verify 'gen1' is replicated regardless of the 'none' parameter value. +$result = + $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1"); +is( $result, qq(|2 +|4), + 'tab2 initial sync, when publish_generated_columns=none'); + +# Insert data to verify incremental replication. +$node_publisher->safe_psql('postgres', "INSERT INTO tab2 VALUES (3), (4)"); + +# Incremental replication test when publish_generated_columns is 'none'. +# Verify 'gen1' is replicated regardless of the 'none' parameter value. +$node_publisher->wait_for_catchup('sub1'); +$result = + $node_subscriber->safe_psql('postgres', "SELECT * FROM tab2 ORDER BY gen1"); +is( $result, qq(|2 +|4 +|6 +|8), + 'tab2 incremental replication, when publish_generated_columns=none'); + +# cleanup +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); +$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); + +# -------------------------------------------------- +# Test Case: Even when publish_generated_columns is set to 'stored', the +# publisher only publishes the data of columns specified in the column list, +# skipping other generated and non-generated columns. +# -------------------------------------------------- + +# Create table and publication. Insert data to verify initial sync. +$node_publisher->safe_psql( + 'postgres', qq( + CREATE TABLE tab3 (a int, gen1 int GENERATED ALWAYS AS (a * 2) STORED, gen2 int GENERATED ALWAYS AS (a * 2) STORED); + INSERT INTO tab3 (a) VALUES (1), (2); + CREATE PUBLICATION pub1 FOR table tab3(gen1) WITH (publish_generated_columns=stored); +)); + +# Create table and subscription. +$node_subscriber->safe_psql( + 'postgres', qq( + CREATE TABLE tab3 (a int, gen1 int, gen2 int); + CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1 WITH (copy_data = true); +)); + +# Wait for initial sync. +$node_subscriber->wait_for_subscription_sync($node_publisher, 'sub1'); + +# Initial sync test when publish_generated_columns is 'stored'. +# Verify only 'gen1' is replicated regardless of the 'stored' parameter value. +$result = + $node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1"); +is( $result, qq(|2| +|4|), + 'tab3 initial sync, when publish_generated_columns=stored'); + +# Insert data to verify incremental replication. +$node_publisher->safe_psql('postgres', "INSERT INTO tab3 VALUES (3), (4)"); + +# Incremental replication test when publish_generated_columns is 'stored'. +# Verify only 'gen1' is replicated regardless of the 'stored' parameter value. +$node_publisher->wait_for_catchup('sub1'); +$result = + $node_subscriber->safe_psql('postgres', "SELECT * FROM tab3 ORDER BY gen1"); +is( $result, qq(|2| +|4| +|6| +|8|), + 'tab3 incremental replication, when publish_generated_columns=stored'); + +# cleanup +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); +$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); + +# ============================================================================= +# The following test verifies the expected error when replicating to a +# generated subscriber column. Test the following combinations: +# - regular -> generated +# - generated -> generated +# ============================================================================= + +# -------------------------------------------------- +# A "regular -> generated" or "generated -> generated" replication fails, +# reporting an error that the generated column on the subscriber side cannot +# be replicated. +# +# Test Case: regular -> generated and generated -> generated +# Publisher table has regular column 'c2' and generated column 'c3'. +# Subscriber table has generated columns 'c2' and 'c3'. +# -------------------------------------------------- + +# Create table and publication. Insert data into the table. +$node_publisher->safe_psql( + 'postgres', qq( + CREATE TABLE t1(c1 int, c2 int, c3 int GENERATED ALWAYS AS (c1 * 2) STORED); + CREATE PUBLICATION pub1 for table t1(c1, c2, c3); + INSERT INTO t1 VALUES (1); +)); + +# Create table and subscription. +$node_subscriber->safe_psql( + 'postgres', qq( + CREATE TABLE t1(c1 int, c2 int GENERATED ALWAYS AS (c1 + 2) STORED, c3 int GENERATED ALWAYS AS (c1 + 2) STORED); + CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1; +)); + +# Verify that an error occurs. +my $offset = -s $node_subscriber->logfile; +$node_subscriber->wait_for_log( + qr/ERROR: ( [A-Z0-9]+:)? logical replication target relation "public.t1" has incompatible generated columns: "c2", "c3"/, + $offset); + +# cleanup +$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); +$node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); done_testing(); diff --git a/src/test/subscription/t/012_collation.pl b/src/test/subscription/t/012_collation.pl index fbfee3504c327..0f2076471e878 100644 --- a/src/test/subscription/t/012_collation.pl +++ b/src/test/subscription/t/012_collation.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test collations, in particular nondeterministic ones # (only works with ICU) diff --git a/src/test/subscription/t/013_partition.pl b/src/test/subscription/t/013_partition.pl index 29580525a97d8..61b0cb4aa1ac1 100644 --- a/src/test/subscription/t/013_partition.pl +++ b/src/test/subscription/t/013_partition.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test logical replication with partitioned tables use strict; @@ -49,6 +49,10 @@ $node_subscriber1->safe_psql('postgres', "CREATE TABLE tab1 (c text, a int PRIMARY KEY, b text) PARTITION BY LIST (a)" ); +# make a BRIN index to test aminsertcleanup logic in subscriber +$node_subscriber1->safe_psql('postgres', + "CREATE INDEX tab1_c_brin_idx ON tab1 USING brin (c)" +); $node_subscriber1->safe_psql('postgres', "CREATE TABLE tab1_1 (b text, c text DEFAULT 'sub1_tab1', a int NOT NULL)" ); @@ -343,13 +347,6 @@ BEGIN $node_subscriber2->safe_psql('postgres', "SELECT a FROM tab1 ORDER BY 1"); is($result, qq(), 'truncate of tab1 replicated'); -# Check that subscriber handles cases where update/delete target tuple -# is missing. We have to look for the DEBUG1 log messages about that, -# so temporarily bump up the log verbosity. -$node_subscriber1->append_conf('postgresql.conf', - "log_min_messages = debug1"); -$node_subscriber1->reload; - $node_publisher->safe_psql('postgres', "INSERT INTO tab1 VALUES (1, 'foo'), (4, 'bar'), (10, 'baz')"); @@ -372,22 +369,18 @@ BEGIN my $logfile = slurp_file($node_subscriber1->logfile(), $log_location); ok( $logfile =~ - qr/logical replication did not find row to be updated in replication target relation's partition "tab1_2_2"/, + qr/conflict detected on relation "public.tab1_2_2": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(null, 4, quux\); replica identity \(a\)=\(4\)/, 'update target row is missing in tab1_2_2'); ok( $logfile =~ - qr/logical replication did not find row to be deleted in replication target relation "tab1_1"/, + qr/conflict detected on relation "public.tab1_1": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(1\)/, 'delete target row is missing in tab1_1'); ok( $logfile =~ - qr/logical replication did not find row to be deleted in replication target relation "tab1_2_2"/, + qr/conflict detected on relation "public.tab1_2_2": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(4\)/, 'delete target row is missing in tab1_2_2'); ok( $logfile =~ - qr/logical replication did not find row to be deleted in replication target relation "tab1_def"/, + qr/conflict detected on relation "public.tab1_def": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(10\)/, 'delete target row is missing in tab1_def'); -$node_subscriber1->append_conf('postgresql.conf', - "log_min_messages = warning"); -$node_subscriber1->reload; - # Tests for replication using root table identity and schema # publisher @@ -773,13 +766,6 @@ BEGIN pub_tab2|5|zzz xxx_c|6|aaa), 'inserts into tab2 replicated'); -# Check that subscriber handles cases where update/delete target tuple -# is missing. We have to look for the DEBUG1 log messages about that, -# so temporarily bump up the log verbosity. -$node_subscriber1->append_conf('postgresql.conf', - "log_min_messages = debug1"); -$node_subscriber1->reload; - $node_subscriber1->safe_psql('postgres', "DELETE FROM tab2"); # Note that the current location of the log file is not grabbed immediately @@ -796,15 +782,34 @@ BEGIN $logfile = slurp_file($node_subscriber1->logfile(), $log_location); ok( $logfile =~ - qr/logical replication did not find row to be updated in replication target relation's partition "tab2_1"/, + qr/conflict detected on relation "public.tab2_1": conflict=update_missing.*\n.*DETAIL:.* Could not find the row to be updated.*\n.*Remote tuple \(pub_tab2, quux, 5\); replica identity \(a\)=\(5\)/, 'update target row is missing in tab2_1'); ok( $logfile =~ - qr/logical replication did not find row to be deleted in replication target relation "tab2_1"/, + qr/conflict detected on relation "public.tab2_1": conflict=delete_missing.*\n.*DETAIL:.* Could not find the row to be deleted.*\n.*Replica identity \(a\)=\(1\)/, 'delete target row is missing in tab2_1'); +# Enable the track_commit_timestamp to detect the conflict when attempting +# to update a row that was previously modified by a different origin. +$node_subscriber1->append_conf('postgresql.conf', + 'track_commit_timestamp = on'); +$node_subscriber1->restart; + +$node_subscriber1->safe_psql('postgres', + "INSERT INTO tab2 VALUES (3, 'yyy')"); +$node_publisher->safe_psql('postgres', + "UPDATE tab2 SET b = 'quux' WHERE a = 3"); + +$node_publisher->wait_for_catchup('sub_viaroot'); + +$logfile = slurp_file($node_subscriber1->logfile(), $log_location); +ok( $logfile =~ + qr/conflict detected on relation "public.tab2_1": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified locally in transaction [0-9]+ at .*\n.*Existing local tuple \(yyy, null, 3\); remote tuple \(pub_tab2, quux, 3\); replica identity \(a\)=\(3\)/, + 'updating a tuple that was modified by a different origin'); + +# The remaining tests no longer test conflict detection. $node_subscriber1->append_conf('postgresql.conf', - "log_min_messages = warning"); -$node_subscriber1->reload; + 'track_commit_timestamp = off'); +$node_subscriber1->restart; # Test that replication continues to work correctly after altering the # partition of a partitioned target table. diff --git a/src/test/subscription/t/014_binary.pl b/src/test/subscription/t/014_binary.pl index a7598f12fb82c..1efa822bc392c 100644 --- a/src/test/subscription/t/014_binary.pl +++ b/src/test/subscription/t/014_binary.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Binary mode logical replication test diff --git a/src/test/subscription/t/015_stream.pl b/src/test/subscription/t/015_stream.pl index 5b9956681d63d..03135b1cd6e1a 100644 --- a/src/test/subscription/t/015_stream.pl +++ b/src/test/subscription/t/015_stream.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test streaming of simple large transaction use strict; diff --git a/src/test/subscription/t/016_stream_subxact.pl b/src/test/subscription/t/016_stream_subxact.pl index edcf17aef380d..16b6653b4d063 100644 --- a/src/test/subscription/t/016_stream_subxact.pl +++ b/src/test/subscription/t/016_stream_subxact.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test streaming of transaction containing subtransactions use strict; diff --git a/src/test/subscription/t/017_stream_ddl.pl b/src/test/subscription/t/017_stream_ddl.pl index e6571b26380ab..77913701f0126 100644 --- a/src/test/subscription/t/017_stream_ddl.pl +++ b/src/test/subscription/t/017_stream_ddl.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test streaming of large transaction with DDL and subtransactions # diff --git a/src/test/subscription/t/018_stream_subxact_abort.pl b/src/test/subscription/t/018_stream_subxact_abort.pl index e38050b9e6ff9..3c0cc3536dc28 100644 --- a/src/test/subscription/t/018_stream_subxact_abort.pl +++ b/src/test/subscription/t/018_stream_subxact_abort.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test streaming of transaction containing multiple subtransactions and rollbacks use strict; diff --git a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl index 84c0e5ca9ef0f..8952c11c14c95 100644 --- a/src/test/subscription/t/019_stream_subxact_ddl_abort.pl +++ b/src/test/subscription/t/019_stream_subxact_ddl_abort.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test streaming of transaction with subtransactions, DDLs, DMLs, and # rollbacks diff --git a/src/test/subscription/t/020_messages.pl b/src/test/subscription/t/020_messages.pl index 9736cb95b48dc..03bda94971aeb 100644 --- a/src/test/subscription/t/020_messages.pl +++ b/src/test/subscription/t/020_messages.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests that logical decoding messages use strict; diff --git a/src/test/subscription/t/021_twophase.pl b/src/test/subscription/t/021_twophase.pl index a47d3b7dd6e15..b8e4242d1f121 100644 --- a/src/test/subscription/t/021_twophase.pl +++ b/src/test/subscription/t/021_twophase.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # logical replication of 2PC test use strict; @@ -23,7 +23,7 @@ my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber'); $node_subscriber->init; $node_subscriber->append_conf('postgresql.conf', - qq(max_prepared_transactions = 10)); + qq(max_prepared_transactions = 0)); $node_subscriber->start; # Create some pre-existing content on publisher @@ -67,12 +67,24 @@ # then COMMIT PREPARED ############################### +# Save the log location, to see the failure of the application +my $log_location = -s $node_subscriber->logfile; + $node_publisher->safe_psql( 'postgres', " BEGIN; INSERT INTO tab_full VALUES (11); PREPARE TRANSACTION 'test_prepared_tab_full';"); +# Confirm the ERROR is reported because max_prepared_transactions is zero +$node_subscriber->wait_for_log( + qr/ERROR: ( [A-Z0-9]+:)? prepared transactions are disabled/); + +# Set max_prepared_transactions to correct value to resume the replication +$node_subscriber->append_conf('postgresql.conf', + qq(max_prepared_transactions = 10)); +$node_subscriber->restart; + $node_publisher->wait_for_catchup($appname); # check that transaction is in prepared state on subscriber @@ -361,7 +373,14 @@ $node_publisher->safe_psql('postgres', "SELECT count(*) FROM tab_copy;"); is($result, qq(6), 'publisher inserted data'); +# Wait for both subscribers to catchup $node_publisher->wait_for_catchup($appname_copy); +$node_publisher->wait_for_catchup($appname); + +# Make sure there are no prepared transactions on the subscriber +$result = $node_subscriber->safe_psql('postgres', + "SELECT count(*) FROM pg_prepared_xacts;"); +is($result, qq(0), 'should be no prepared transactions on subscriber'); $result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM tab_copy;"); @@ -385,7 +404,7 @@ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION tap_sub_copy DISABLE;"); $node_subscriber->poll_query_until('postgres', - "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication worker'" + "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication apply worker'" ); $node_subscriber->safe_psql( 'postgres', " @@ -434,7 +453,7 @@ $node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION tap_sub_copy DISABLE;"); $node_subscriber->poll_query_until('postgres', - "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication worker'" + "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication apply worker'" ); $node_subscriber->safe_psql( 'postgres', " diff --git a/src/test/subscription/t/022_twophase_cascade.pl b/src/test/subscription/t/022_twophase_cascade.pl index 1acc79f17e5b0..06148a85039b8 100644 --- a/src/test/subscription/t/022_twophase_cascade.pl +++ b/src/test/subscription/t/022_twophase_cascade.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test cascading logical replication of 2PC. # @@ -88,7 +88,7 @@ CREATE SUBSCRIPTION tap_sub_B CONNECTION '$node_A_connstr application_name=$appname_B' PUBLICATION tap_pub_A - WITH (two_phase = on)"); + WITH (two_phase = on, streaming = off)"); # node_B (pub) -> node_C (sub) my $node_B_connstr = $node_B->connstr . ' dbname=postgres'; @@ -100,7 +100,7 @@ CREATE SUBSCRIPTION tap_sub_C CONNECTION '$node_B_connstr application_name=$appname_C' PUBLICATION tap_pub_B - WITH (two_phase = on)"); + WITH (two_phase = on, streaming = off)"); # Wait for subscribers to finish initialization $node_A->wait_for_catchup($appname_B); diff --git a/src/test/subscription/t/023_twophase_stream.pl b/src/test/subscription/t/023_twophase_stream.pl index 23c762e8adf7a..e01347ca69950 100644 --- a/src/test/subscription/t/023_twophase_stream.pl +++ b/src/test/subscription/t/023_twophase_stream.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test logical replication of 2PC with streaming. use strict; diff --git a/src/test/subscription/t/024_add_drop_pub.pl b/src/test/subscription/t/024_add_drop_pub.pl index c0d7ffcb6b8d5..e995d8b383901 100644 --- a/src/test/subscription/t/024_add_drop_pub.pl +++ b/src/test/subscription/t/024_add_drop_pub.pl @@ -1,7 +1,9 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group -# This test checks behaviour of ALTER SUBSCRIPTION ... ADD/DROP PUBLICATION +# This test checks behaviour of ALTER SUBSCRIPTION ... ADD/DROP PUBLICATION and +# ensures that creating a publication associated with a subscription at a later +# point of time does not break logical replication. use strict; use warnings FATAL => 'all'; use PostgreSQL::Test::Cluster; @@ -80,6 +82,57 @@ "SELECT count(*), min(a), max(a) FROM tab_1"); is($result, qq(20|1|10), 'check initial data is copied to subscriber'); +# Ensure that setting a missing publication to the subscription does not +# disrupt existing logical replication. Instead, it should log a warning +# while allowing replication to continue. Additionally, verify that replication +# resumes after the missing publication is created for the publication table. + +# Create table on publisher and subscriber +$node_publisher->safe_psql('postgres', "CREATE TABLE tab_3 (a int)"); +$node_subscriber->safe_psql('postgres', "CREATE TABLE tab_3 (a int)"); + +my $oldpid = $node_publisher->safe_psql('postgres', + "SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';" +); + +# Set the subscription with a missing publication +$node_subscriber->safe_psql('postgres', + "ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_3"); + +# Wait for the walsender to restart after altering the subscription +$node_publisher->poll_query_until('postgres', + "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';" + ) + or die + "Timed out while waiting for apply worker to restart after altering the subscription"; + +my $offset = -s $node_publisher->logfile; + +$node_publisher->safe_psql('postgres',"INSERT INTO tab_3 values(1)"); + +# Verify that a warning is logged. +$node_publisher->wait_for_log( + qr/WARNING: ( [A-Z0-9]+:)? skipped loading publication: tap_pub_3/, $offset); + +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION tap_pub_3 FOR TABLE tab_3"); + +$node_subscriber->safe_psql('postgres', + "ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION"); + +$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub'); + +$node_publisher->safe_psql('postgres', "INSERT INTO tab_3 values(2)"); + +$node_publisher->wait_for_catchup('tap_sub'); + +# Verify that the insert operation gets replicated to subscriber after +# publication is created. +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM tab_3"); +is($result, qq(1 +2), 'check that the incremental data is replicated after the publication is created'); + # shutdown $node_subscriber->stop('fast'); $node_publisher->stop('fast'); diff --git a/src/test/subscription/t/025_rep_changes_for_schema.pl b/src/test/subscription/t/025_rep_changes_for_schema.pl index 2258fe96b1b81..0d074ccda1367 100644 --- a/src/test/subscription/t/025_rep_changes_for_schema.pl +++ b/src/test/subscription/t/025_rep_changes_for_schema.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Logical replication tests for schema publications use strict; diff --git a/src/test/subscription/t/026_stats.pl b/src/test/subscription/t/026_stats.pl index fb3e5629b3c43..00a1c2fcd48c3 100644 --- a/src/test/subscription/t/026_stats.pl +++ b/src/test/subscription/t/026_stats.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for subscription stats. use strict; @@ -30,6 +30,7 @@ sub create_sub_pub_w_errors qq[ BEGIN; CREATE TABLE $table_name(a int); + ALTER TABLE $table_name REPLICA IDENTITY FULL; INSERT INTO $table_name VALUES (1); COMMIT; ]); @@ -91,20 +92,36 @@ sub create_sub_pub_w_errors # subscriber due to violation of the unique constraint on test table. $node_publisher->safe_psql($db, qq(INSERT INTO $table_name VALUES (1))); - # Wait for the apply error to be reported. + # Wait for the subscriber to report both an apply error and an + # insert_exists conflict. $node_subscriber->poll_query_until( $db, qq[ - SELECT apply_error_count > 0 + SELECT apply_error_count > 0 AND confl_insert_exists > 0 FROM pg_stat_subscription_stats WHERE subname = '$sub_name' ]) or die - qq(Timed out while waiting for apply error for subscription '$sub_name'); + qq(Timed out while waiting for apply error and insert_exists conflict for subscription '$sub_name'); # Truncate test table so that apply worker can continue. $node_subscriber->safe_psql($db, qq(TRUNCATE $table_name)); + # Delete data from the test table on the publisher. This delete operation + # should be skipped on the subscriber since the table is already empty. + $node_publisher->safe_psql($db, qq(DELETE FROM $table_name;)); + + # Wait for the subscriber to report a delete_missing conflict. + $node_subscriber->poll_query_until( + $db, + qq[ + SELECT confl_delete_missing > 0 + FROM pg_stat_subscription_stats + WHERE subname = '$sub_name' + ]) + or die + qq(Timed out while waiting for delete_missing conflict for subscription '$sub_name'); + return ($pub_name, $sub_name); } @@ -123,17 +140,19 @@ sub create_sub_pub_w_errors create_sub_pub_w_errors($node_publisher, $node_subscriber, $db, $table1_name); -# Apply and Sync errors are > 0 and reset timestamp is NULL +# Apply errors, sync errors, and conflicts are > 0 and stats_reset timestamp is NULL is( $node_subscriber->safe_psql( $db, qq(SELECT apply_error_count > 0, sync_error_count > 0, + confl_insert_exists > 0, + confl_delete_missing > 0, stats_reset IS NULL FROM pg_stat_subscription_stats WHERE subname = '$sub1_name') ), - qq(t|t|t), - qq(Check that apply errors and sync errors are both > 0 and stats_reset is NULL for subscription '$sub1_name'.) + qq(t|t|t|t|t), + qq(Check that apply errors, sync errors, and conflicts are > 0 and stats_reset is NULL for subscription '$sub1_name'.) ); # Reset a single subscription @@ -141,17 +160,19 @@ sub create_sub_pub_w_errors qq(SELECT pg_stat_reset_subscription_stats((SELECT subid FROM pg_stat_subscription_stats WHERE subname = '$sub1_name'))) ); -# Apply and Sync errors are 0 and stats reset is not NULL +# Apply errors, sync errors, and conflicts are 0 and stats_reset timestamp is not NULL is( $node_subscriber->safe_psql( $db, qq(SELECT apply_error_count = 0, sync_error_count = 0, + confl_insert_exists = 0, + confl_delete_missing = 0, stats_reset IS NOT NULL FROM pg_stat_subscription_stats WHERE subname = '$sub1_name') ), - qq(t|t|t), - qq(Confirm that apply errors and sync errors are both 0 and stats_reset is not NULL after reset for subscription '$sub1_name'.) + qq(t|t|t|t|t), + qq(Confirm that apply errors, sync errors, and conflicts are 0 and stats_reset is not NULL after reset for subscription '$sub1_name'.) ); # Get reset timestamp @@ -181,46 +202,52 @@ sub create_sub_pub_w_errors create_sub_pub_w_errors($node_publisher, $node_subscriber, $db, $table2_name); -# Apply and Sync errors are > 0 and reset timestamp is NULL +# Apply errors, sync errors, and conflicts are > 0 and stats_reset timestamp is NULL is( $node_subscriber->safe_psql( $db, qq(SELECT apply_error_count > 0, sync_error_count > 0, + confl_insert_exists > 0, + confl_delete_missing > 0, stats_reset IS NULL FROM pg_stat_subscription_stats WHERE subname = '$sub2_name') ), - qq(t|t|t), - qq(Confirm that apply errors and sync errors are both > 0 and stats_reset is NULL for sub '$sub2_name'.) + qq(t|t|t|t|t), + qq(Confirm that apply errors, sync errors, and conflicts are > 0 and stats_reset is NULL for sub '$sub2_name'.) ); # Reset all subscriptions $node_subscriber->safe_psql($db, qq(SELECT pg_stat_reset_subscription_stats(NULL))); -# Apply and Sync errors are 0 and stats reset is not NULL +# Apply errors, sync errors, and conflicts are 0 and stats_reset timestamp is not NULL is( $node_subscriber->safe_psql( $db, qq(SELECT apply_error_count = 0, sync_error_count = 0, + confl_insert_exists = 0, + confl_delete_missing = 0, stats_reset IS NOT NULL FROM pg_stat_subscription_stats WHERE subname = '$sub1_name') ), - qq(t|t|t), - qq(Confirm that apply errors and sync errors are both 0 and stats_reset is not NULL for sub '$sub1_name' after reset.) + qq(t|t|t|t|t), + qq(Confirm that apply errors, sync errors, and conflicts are 0 and stats_reset is not NULL for sub '$sub1_name' after reset.) ); is( $node_subscriber->safe_psql( $db, qq(SELECT apply_error_count = 0, sync_error_count = 0, + confl_insert_exists = 0, + confl_delete_missing = 0, stats_reset IS NOT NULL FROM pg_stat_subscription_stats WHERE subname = '$sub2_name') ), - qq(t|t|t), - qq(Confirm that apply errors and sync errors are both 0 and stats_reset is not NULL for sub '$sub2_name' after reset.) + qq(t|t|t|t|t), + qq(Confirm that apply errors, sync errors, and conflicts are 0 and stats_reset is not NULL for sub '$sub2_name' after reset.) ); $reset_time1 = $node_subscriber->safe_psql($db, diff --git a/src/test/subscription/t/027_nosuperuser.pl b/src/test/subscription/t/027_nosuperuser.pl index a4d7da36636ba..36af1c16e7f51 100644 --- a/src/test/subscription/t/027_nosuperuser.pl +++ b/src/test/subscription/t/027_nosuperuser.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test that logical replication respects permissions use strict; diff --git a/src/test/subscription/t/028_row_filter.pl b/src/test/subscription/t/028_row_filter.pl index 2acd36d7a6f22..e2c8367005355 100644 --- a/src/test/subscription/t/028_row_filter.pl +++ b/src/test/subscription/t/028_row_filter.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test logical replication behavior with row filtering use strict; @@ -240,6 +240,9 @@ $node_publisher->safe_psql('postgres', "CREATE TABLE tab_rowfilter_child_sync PARTITION OF tab_rowfilter_parent_sync FOR VALUES FROM (1) TO (20)" ); +$node_publisher->safe_psql('postgres', + "CREATE TABLE tab_rowfilter_virtual (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * 2) VIRTUAL)" +); # setup structure on subscriber $node_subscriber->safe_psql('postgres', @@ -294,6 +297,9 @@ "CREATE TABLE tab_rowfilter_parent_sync (a int)"); $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_rowfilter_child_sync (a int)"); +$node_subscriber->safe_psql('postgres', + "CREATE TABLE tab_rowfilter_virtual (id int PRIMARY KEY, x int, y int GENERATED ALWAYS AS (x * 2) VIRTUAL)" +); # setup logical replication $node_publisher->safe_psql('postgres', @@ -359,6 +365,11 @@ "CREATE PUBLICATION tap_pub_child_sync FOR TABLE tab_rowfilter_child_sync WHERE (a < 15)" ); +# publication using virtual generated column in row filter expression +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION tap_pub_virtual FOR TABLE tab_rowfilter_virtual WHERE (y > 10)" +); + # # The following INSERTs are executed before the CREATE SUBSCRIPTION, so these # SQL commands are for testing the initial data copy using logical replication. @@ -407,8 +418,12 @@ "INSERT INTO tab_rowfilter_child(a, b) VALUES(0,'0'),(30,'30'),(40,'40')" ); +$node_publisher->safe_psql('postgres', + "INSERT INTO tab_rowfilter_virtual (id, x) VALUES (1, 2), (2, 4), (3, 6)" +); + $node_subscriber->safe_psql('postgres', - "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub_1, tap_pub_2, tap_pub_3, tap_pub_4a, tap_pub_4b, tap_pub_5a, tap_pub_5b, tap_pub_toast, tap_pub_inherits, tap_pub_viaroot_2, tap_pub_viaroot_1, tap_pub_parent_sync, tap_pub_child_sync" + "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub_1, tap_pub_2, tap_pub_3, tap_pub_4a, tap_pub_4b, tap_pub_5a, tap_pub_5b, tap_pub_toast, tap_pub_inherits, tap_pub_viaroot_2, tap_pub_viaroot_1, tap_pub_parent_sync, tap_pub_child_sync, tap_pub_virtual" ); # wait for initial table synchronization to finish @@ -550,6 +565,16 @@ "SELECT a FROM tab_rowfilter_child_sync ORDER BY 1"); is($result, qq(), 'check initial data copy from tab_rowfilter_child_sync'); +# Check expected replicated rows for tab_rowfilter_virtual +# tap_pub_virtual filter is: (y > 10), where y is generated as (x * 2) +# - INSERT (1, 2) NO, 2 * 2 <= 10 +# - INSERT (2, 4) NO, 4 * 2 <= 10 +# - INSERT (3, 6) YES, 6 * 2 > 10 +$result = $node_subscriber->safe_psql('postgres', + "SELECT id, x FROM tab_rowfilter_virtual ORDER BY id"); +is($result, qq(3|6), + 'check initial data copy from table tab_rowfilter_virtual'); + # The following commands are executed after CREATE SUBSCRIPTION, so these SQL # commands are for testing normal logical replication behavior. # @@ -582,6 +607,8 @@ "INSERT INTO tab_rowfilter_child (a, b) VALUES (13, '13'), (17, '17')"); $node_publisher->safe_psql('postgres', "INSERT INTO tab_rowfilter_viaroot_part (a) VALUES (14), (15), (16)"); +$node_publisher->safe_psql('postgres', + "INSERT INTO tab_rowfilter_virtual (id, x) VALUES (4, 3), (5, 7)"); $node_publisher->wait_for_catchup($appname); @@ -725,6 +752,15 @@ 'check replicated rows to tab_rowfilter_inherited and tab_rowfilter_child' ); +# Check expected replicated rows for tab_rowfilter_virtual +# tap_pub_virtual filter is: (y > 10), where y is generated as (x * 2) +# - INSERT (4, 3) NO, 3 * 2 <= 10 +# - INSERT (5, 7) YES, 7 * 2 > 10 +$result = $node_subscriber->safe_psql('postgres', + "SELECT id, x FROM tab_rowfilter_virtual ORDER BY id"); +is( $result, qq(3|6 +5|7), 'check replicated rows to tab_rowfilter_virtual'); + # UPDATE the non-toasted column for table tab_rowfilter_toast $node_publisher->safe_psql('postgres', "UPDATE tab_rowfilter_toast SET b = '1'"); diff --git a/src/test/subscription/t/029_on_error.pl b/src/test/subscription/t/029_on_error.pl index 0ab57a4b5b0e4..243662e1240c8 100644 --- a/src/test/subscription/t/029_on_error.pl +++ b/src/test/subscription/t/029_on_error.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for disable_on_error and SKIP transaction features. use strict; @@ -30,7 +30,7 @@ sub test_skip_lsn # ERROR with its CONTEXT when retrieving this information. my $contents = slurp_file($node_subscriber->logfile, $offset); $contents =~ - qr/duplicate key value violates unique constraint "tbl_pkey".*\n.*DETAIL:.*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+\/[[:xdigit:]]+)/m + qr/conflict detected on relation "public.tbl".*\n.*DETAIL:.* Key already exists in unique index "tbl_pkey", modified by .*origin.* transaction \d+ at .*\n.*Key \(i\)=\(\d+\); existing local tuple .*; remote tuple .*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+\/[[:xdigit:]]+)/m or die "could not get error-LSN"; my $lsn = $1; @@ -83,6 +83,7 @@ sub test_skip_lsn 'postgresql.conf', qq[ max_prepared_transactions = 10 +track_commit_timestamp = on ]); $node_subscriber->start; @@ -93,6 +94,7 @@ sub test_skip_lsn 'postgres', qq[ CREATE TABLE tbl (i INT, t BYTEA); +ALTER TABLE tbl REPLICA IDENTITY FULL; INSERT INTO tbl VALUES (1, NULL); ]); $node_subscriber->safe_psql( @@ -144,13 +146,14 @@ sub test_skip_lsn test_skip_lsn($node_publisher, $node_subscriber, "(2, NULL)", "2", "test skipping transaction"); -# Test for PREPARE and COMMIT PREPARED. Insert the same data to tbl and -# PREPARE the transaction, raising an error. Then skip the transaction. +# Test for PREPARE and COMMIT PREPARED. Update the data and PREPARE the +# transaction, raising an error on the subscriber due to violation of the +# unique constraint on tbl. Then skip the transaction. $node_publisher->safe_psql( 'postgres', qq[ BEGIN; -INSERT INTO tbl VALUES (1, NULL); +UPDATE tbl SET i = 2; PREPARE TRANSACTION 'gtx'; COMMIT PREPARED 'gtx'; ]); diff --git a/src/test/subscription/t/030_origin.pl b/src/test/subscription/t/030_origin.pl index 056561f00841c..5b82848e5e6d3 100644 --- a/src/test/subscription/t/030_origin.pl +++ b/src/test/subscription/t/030_origin.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test the CREATE SUBSCRIPTION 'origin' parameter and its interaction with # 'copy_data' parameter. @@ -27,9 +27,14 @@ my $node_A = PostgreSQL::Test::Cluster->new('node_A'); $node_A->init(allows_streaming => 'logical'); $node_A->start; + # node_B my $node_B = PostgreSQL::Test::Cluster->new('node_B'); $node_B->init(allows_streaming => 'logical'); + +# Enable the track_commit_timestamp to detect the conflict when attempting to +# update a row that was previously modified by a different origin. +$node_B->append_conf('postgresql.conf', 'track_commit_timestamp = on'); $node_B->start; # Create table on node_A @@ -139,6 +144,48 @@ 'Remote data originating from another node (not the publisher) is not replicated when origin parameter is none' ); +############################################################################### +# Check that the conflict can be detected when attempting to update or +# delete a row that was previously modified by a different source. +############################################################################### + +$node_B->safe_psql('postgres', "DELETE FROM tab;"); + +$node_A->safe_psql('postgres', "INSERT INTO tab VALUES (32);"); + +$node_A->wait_for_catchup($subname_BA); +$node_B->wait_for_catchup($subname_AB); + +$result = $node_B->safe_psql('postgres', "SELECT * FROM tab ORDER BY 1;"); +is($result, qq(32), 'The node_A data replicated to node_B'); + +# The update should update the row on node B that was inserted by node A. +$node_C->safe_psql('postgres', "UPDATE tab SET a = 33 WHERE a = 32;"); + +$node_B->wait_for_log( + qr/conflict detected on relation "public.tab": conflict=update_origin_differs.*\n.*DETAIL:.* Updating the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local tuple \(32\); remote tuple \(33\); replica identity \(a\)=\(32\)/ +); + +$node_B->safe_psql('postgres', "DELETE FROM tab;"); +$node_A->safe_psql('postgres', "INSERT INTO tab VALUES (33);"); + +$node_A->wait_for_catchup($subname_BA); +$node_B->wait_for_catchup($subname_AB); + +$result = $node_B->safe_psql('postgres', "SELECT * FROM tab ORDER BY 1;"); +is($result, qq(33), 'The node_A data replicated to node_B'); + +# The delete should remove the row on node B that was inserted by node A. +$node_C->safe_psql('postgres', "DELETE FROM tab WHERE a = 33;"); + +$node_B->wait_for_log( + qr/conflict detected on relation "public.tab": conflict=delete_origin_differs.*\n.*DETAIL:.* Deleting the row that was modified by a different origin ".*" in transaction [0-9]+ at .*\n.*Existing local tuple \(33\); replica identity \(a\)=\(33\)/ +); + +# The remaining tests no longer test conflict detection. +$node_B->append_conf('postgresql.conf', 'track_commit_timestamp = off'); +$node_B->restart; + ############################################################################### # Specifying origin = NONE indicates that the publisher should only replicate the # changes that are generated locally from node_B, but in this case since the @@ -204,9 +251,123 @@ $node_B->wait_for_catchup($subname_AB2); # clear the operations done by this test -$node_A->safe_psql('postgres', "DROP TABLE tab_new"); -$node_B->safe_psql('postgres', "DROP TABLE tab_new"); -$node_A->safe_psql('postgres', "DROP SUBSCRIPTION $subname_AB2"); +$node_A->safe_psql( + 'postgres', qq( +DROP TABLE tab_new; +DROP SUBSCRIPTION $subname_AB2; +DROP SUBSCRIPTION $subname_AB; +DROP PUBLICATION tap_pub_A; +)); +$node_B->safe_psql( + 'postgres', qq( +DROP TABLE tab_new; +DROP SUBSCRIPTION $subname_BA; +DROP PUBLICATION tap_pub_B; +)); + +############################################################################### +# Specifying origin = NONE and copy_data = on must raise WARNING if we subscribe +# to a partitioned table and this table contains any remotely originated data. +# +# node_B +# __________________________ +# | tab_main | --------------> node_C (tab_main) +# |__________________________| +# | tab_part1 | tab_part2 | <-------------- node_A (tab_part2) +# |____________|_____________| +# | tab_part2_1 | +# |_____________| +# +# node_B +# __________________________ +# | tab_main | +# |__________________________| +# | tab_part1 | tab_part2 | <-------------- node_A (tab_part2) +# |____________|_____________| +# | tab_part2_1 | --------------> node_C (tab_part2_1) +# |_____________| +############################################################################### + +# create a table on node A which will act as a source for a partition on node B +$node_A->safe_psql( + 'postgres', qq( +CREATE TABLE tab_part2(a int); +CREATE PUBLICATION tap_pub_A FOR TABLE tab_part2; +)); + +# create a partition table on node B +$node_B->safe_psql( + 'postgres', qq( +CREATE TABLE tab_main(a int) PARTITION BY RANGE(a); +CREATE TABLE tab_part1 PARTITION OF tab_main FOR VALUES FROM (0) TO (5); +CREATE TABLE tab_part2(a int) PARTITION BY RANGE(a); +CREATE TABLE tab_part2_1 PARTITION OF tab_part2 FOR VALUES FROM (5) TO (10); +ALTER TABLE tab_main ATTACH PARTITION tab_part2 FOR VALUES FROM (5) to (10); +CREATE SUBSCRIPTION tap_sub_A_B CONNECTION '$node_A_connstr' PUBLICATION tap_pub_A; +)); + +# create a table on node C +$node_C->safe_psql( + 'postgres', qq( +CREATE TABLE tab_main(a int); +CREATE TABLE tab_part2_1(a int); +)); + +# create a logical replication setup between node B and node C with +# subscription on node C having origin = NONE and copy_data = on +$node_B->safe_psql( + 'postgres', qq( +CREATE PUBLICATION tap_pub_B FOR TABLE tab_main WITH (publish_via_partition_root); +CREATE PUBLICATION tap_pub_B_2 FOR TABLE tab_part2_1; +)); + +($result, $stdout, $stderr) = $node_C->psql( + 'postgres', " + CREATE SUBSCRIPTION tap_sub_B_C CONNECTION '$node_B_connstr' PUBLICATION tap_pub_B WITH (origin = none, copy_data = on); +"); + +# A warning must be logged as a partition 'tab_part2' in node B is subscribed to +# node A so partition 'tab_part2' can have remotely originated data +like( + $stderr, + qr/WARNING: ( [A-Z0-9]+:)? subscription "tap_sub_b_c" requested copy_data with origin = NONE but might copy data that had a different origin/, + "Create subscription with origin = none and copy_data when the publisher's partition is subscribing from different origin" +); +$node_C->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_B_C"); + +($result, $stdout, $stderr) = $node_C->psql( + 'postgres', " + CREATE SUBSCRIPTION tap_sub_B_C CONNECTION '$node_B_connstr' PUBLICATION tap_pub_B_2 WITH (origin = none, copy_data = on); +"); + +# A warning must be logged as ancestor of table 'tab_part2_1' in node B is +# subscribed to node A so table 'tab_part2_1' can have remotely originated +# data +like( + $stderr, + qr/WARNING: ( [A-Z0-9]+:)? subscription "tap_sub_b_c" requested copy_data with origin = NONE but might copy data that had a different origin/, + "Create subscription with origin = none and copy_data when the publisher's ancestor is subscribing from different origin" +); + +# clear the operations done by this test +$node_C->safe_psql( + 'postgres', qq( +DROP SUBSCRIPTION tap_sub_B_C; +DROP TABLE tab_main; +DROP TABLE tab_part2_1; +)); +$node_B->safe_psql( + 'postgres', qq( +DROP SUBSCRIPTION tap_sub_A_B; +DROP PUBLICATION tap_pub_B; +DROP PUBLICATION tap_pub_B_2; +DROP TABLE tab_main; +)); +$node_A->safe_psql( + 'postgres', qq( +DROP PUBLICATION tap_pub_A; +DROP TABLE tab_part2; +)); # shutdown $node_B->stop('fast'); diff --git a/src/test/subscription/t/031_column_list.pl b/src/test/subscription/t/031_column_list.pl index 9a97fa5020313..e859bcdf4eb8a 100644 --- a/src/test/subscription/t/031_column_list.pl +++ b/src/test/subscription/t/031_column_list.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Test partial-column publication of tables use strict; @@ -1202,13 +1202,14 @@ is( $result, qq(t t), 'check the number of columns in the old tuple'); -# TEST: Generated and dropped columns are not considered for the column list. -# So, the publication having a column list except for those columns and a -# publication without any column (aka all columns as part of the columns +# TEST: Dropped columns are not considered for the column list, and generated +# columns are not replicated if they are not explicitly included in the column +# list. So, the publication having a column list except for those columns and a +# publication without any column list (aka all columns as part of the columns # list) are considered to have the same column list. $node_publisher->safe_psql( 'postgres', qq( - CREATE TABLE test_mix_4 (a int PRIMARY KEY, b int, c int, d int GENERATED ALWAYS AS (a + 1) STORED); + CREATE TABLE test_mix_4 (a int PRIMARY KEY, b int, c int, d int GENERATED ALWAYS AS (a + 1) STORED, e int GENERATED ALWAYS AS (a + 2) VIRTUAL); ALTER TABLE test_mix_4 DROP COLUMN c; CREATE PUBLICATION pub_mix_7 FOR TABLE test_mix_4 (a, b); diff --git a/src/test/subscription/t/032_subscribe_use_index.pl b/src/test/subscription/t/032_subscribe_use_index.pl index cc999e33c3ac7..834c9ad53375f 100644 --- a/src/test/subscription/t/032_subscribe_use_index.pl +++ b/src/test/subscription/t/032_subscribe_use_index.pl @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # Test logical replication behavior with subscriber using available index use strict; diff --git a/src/test/subscription/t/033_run_as_table_owner.pl b/src/test/subscription/t/033_run_as_table_owner.pl index b129fc3c38edb..c6d690009c9ef 100644 --- a/src/test/subscription/t/033_run_as_table_owner.pl +++ b/src/test/subscription/t/033_run_as_table_owner.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Test that logical replication respects permissions use strict; diff --git a/src/test/subscription/t/034_temporal.pl b/src/test/subscription/t/034_temporal.pl new file mode 100644 index 0000000000000..6bbf65672790e --- /dev/null +++ b/src/test/subscription/t/034_temporal.pl @@ -0,0 +1,631 @@ + +# Copyright (c) 2024-2025, PostgreSQL Global Development Group + +# Logical replication tests for temporal tables +# +# A table can use a temporal PRIMARY KEY or UNIQUE index as its REPLICA IDENTITY. +# This is a GiST index (not B-tree) and its last element uses WITHOUT OVERLAPS. +# That element restricts other rows with overlaps semantics instead of equality, +# but it is always at least as restrictive as a normal non-null unique index. +# Therefore we can still apply logical decoding messages to the subscriber. +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# setup + +my $node_publisher = PostgreSQL::Test::Cluster->new('publisher'); +$node_publisher->init(allows_streaming => 'logical'); +$node_publisher->start; + +my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber'); +$node_subscriber->init; +$node_subscriber->start; + +my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; + +my ($result, $stdout, $stderr); + +sub create_tables() +{ + # create tables on publisher + + $node_publisher->safe_psql('postgres', + "CREATE TABLE temporal_no_key (id int4range, valid_at daterange, a text)" + ); + + $node_publisher->safe_psql('postgres', + "CREATE TABLE temporal_pk (id int4range, valid_at daterange, a text, PRIMARY KEY (id, valid_at WITHOUT OVERLAPS))" + ); + + $node_publisher->safe_psql('postgres', + "CREATE TABLE temporal_unique (id int4range, valid_at daterange, a text, UNIQUE (id, valid_at WITHOUT OVERLAPS))" + ); + + # create tables on subscriber + + $node_subscriber->safe_psql('postgres', + "CREATE TABLE temporal_no_key (id int4range, valid_at daterange, a text)" + ); + + $node_subscriber->safe_psql('postgres', + "CREATE TABLE temporal_pk (id int4range, valid_at daterange, a text, PRIMARY KEY (id, valid_at WITHOUT OVERLAPS))" + ); + + $node_subscriber->safe_psql('postgres', + "CREATE TABLE temporal_unique (id int4range, valid_at daterange, a text, UNIQUE (id, valid_at WITHOUT OVERLAPS))" + ); +} + +sub drop_everything() +{ + $node_publisher->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_no_key"); + $node_publisher->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_pk"); + $node_publisher->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_unique"); + $node_publisher->safe_psql('postgres', "DROP PUBLICATION pub1"); + $node_subscriber->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_no_key"); + $node_subscriber->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_pk"); + $node_subscriber->safe_psql('postgres', + "DROP TABLE IF EXISTS temporal_unique"); + $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION sub1"); +} + +# ################################# +# Test with REPLICA IDENTITY DEFAULT: +# ################################# + +create_tables(); + +# sync initial data: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION pub1 FOR ALL TABLES"); +$node_subscriber->safe_psql('postgres', + "CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1" +); +$node_subscriber->wait_for_subscription_sync; + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_no_key DEFAULT'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is($result, qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_pk DEFAULT'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_unique DEFAULT'); + +# replicate with no key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "UPDATE temporal_no_key SET a = 'b' WHERE id = '[2,3)'"); +is( $stderr, + qq(psql::1: ERROR: cannot update table "temporal_no_key" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't UPDATE temporal_no_key DEFAULT"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "DELETE FROM temporal_no_key WHERE id = '[3,4)'"); +is( $stderr, + qq(psql::1: ERROR: cannot delete from table "temporal_no_key" because it does not have a replica identity and publishes deletes +HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't DELETE temporal_no_key DEFAULT"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|a +[3,4)|[2000-01-01,2010-01-01)|a +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_no_key DEFAULT'); + +# replicate with a primary key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_pk SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_pk WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_pk DEFAULT'); + +# replicate with a unique key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "UPDATE temporal_unique SET a = 'b' WHERE id = '[2,3)'"); +is( $stderr, + qq(psql::1: ERROR: cannot update table "temporal_unique" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't UPDATE temporal_unique DEFAULT"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "DELETE FROM temporal_unique WHERE id = '[3,4)'"); +is( $stderr, + qq(psql::1: ERROR: cannot delete from table "temporal_unique" because it does not have a replica identity and publishes deletes +HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't DELETE temporal_unique DEFAULT"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|a +[3,4)|[2000-01-01,2010-01-01)|a +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_unique DEFAULT'); + +# cleanup + +drop_everything(); + + +# ################################# +# Test with REPLICA IDENTITY FULL: +# ################################# + +create_tables(); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_no_key REPLICA IDENTITY FULL"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY FULL"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY FULL"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_no_key REPLICA IDENTITY FULL"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY FULL"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY FULL"); + +# sync initial data: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION pub1 FOR ALL TABLES"); +$node_subscriber->safe_psql('postgres', + "CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1" +); +$node_subscriber->wait_for_subscription_sync; + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_no_key FULL'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is($result, qq{[1,2)|[2000-01-01,2010-01-01)|a}, 'synced temporal_pk FULL'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_unique FULL'); + +# replicate with no key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_no_key SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_no_key WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_no_key FULL'); + +# replicate with a primary key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_pk SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_pk WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_pk FULL'); + +# replicate with a unique key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_unique SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_unique WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_unique FULL'); + +# cleanup + +drop_everything(); + + +# ################################# +# Test with REPLICA IDENTITY USING INDEX +# ################################# + +# create tables on publisher + +$node_publisher->safe_psql('postgres', + "CREATE TABLE temporal_pk (id int4range, valid_at daterange, a text, PRIMARY KEY (id, valid_at WITHOUT OVERLAPS))" +); +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY USING INDEX temporal_pk_pkey"); + +$node_publisher->safe_psql('postgres', + "CREATE TABLE temporal_unique (id int4range NOT NULL, valid_at daterange NOT NULL, a text, UNIQUE (id, valid_at WITHOUT OVERLAPS))" +); +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY USING INDEX temporal_unique_id_valid_at_key" +); + +# create tables on subscriber + +$node_subscriber->safe_psql('postgres', + "CREATE TABLE temporal_pk (id int4range, valid_at daterange, a text, PRIMARY KEY (id, valid_at WITHOUT OVERLAPS))" +); +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY USING INDEX temporal_pk_pkey"); + +$node_subscriber->safe_psql('postgres', + "CREATE TABLE temporal_unique (id int4range NOT NULL, valid_at daterange NOT NULL, a text, UNIQUE (id, valid_at WITHOUT OVERLAPS))" +); +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY USING INDEX temporal_unique_id_valid_at_key" +); + +# sync initial data: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION pub1 FOR ALL TABLES"); +$node_subscriber->safe_psql('postgres', + "CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1" +); +$node_subscriber->wait_for_subscription_sync; + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_pk USING INDEX'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_unique USING INDEX'); + +# replicate with a primary key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_pk SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_pk WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_pk USING INDEX'); + +# replicate with a unique key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "UPDATE temporal_unique SET a = 'b' WHERE id = '[2,3)'"); + +$node_publisher->safe_psql('postgres', + "DELETE FROM temporal_unique WHERE id = '[3,4)'"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|b +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_unique USING INDEX'); + +# cleanup + +drop_everything(); + + +# ################################# +# Test with REPLICA IDENTITY NOTHING +# ################################# + +create_tables(); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_no_key REPLICA IDENTITY NOTHING"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY NOTHING"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY NOTHING"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_no_key REPLICA IDENTITY NOTHING"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_pk REPLICA IDENTITY NOTHING"); + +$node_subscriber->safe_psql('postgres', + "ALTER TABLE temporal_unique REPLICA IDENTITY NOTHING"); + +# sync initial data: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[1,2)', '[2000-01-01,2010-01-01)', 'a')"); + +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION pub1 FOR ALL TABLES"); +$node_subscriber->safe_psql('postgres', + "CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr' PUBLICATION pub1" +); +$node_subscriber->wait_for_subscription_sync; + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_no_key NOTHING'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is($result, qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_pk NOTHING'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, + qq{[1,2)|[2000-01-01,2010-01-01)|a}, + 'synced temporal_unique NOTHING'); + +# replicate with no key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_no_key (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "UPDATE temporal_no_key SET a = 'b' WHERE id = '[2,3)'"); +is( $stderr, + qq(psql::1: ERROR: cannot update table "temporal_no_key" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't UPDATE temporal_no_key NOTHING"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "DELETE FROM temporal_no_key WHERE id = '[3,4)'"); +is( $stderr, + qq(psql::1: ERROR: cannot delete from table "temporal_no_key" because it does not have a replica identity and publishes deletes +HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't DELETE temporal_no_key NOTHING"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_no_key ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|a +[3,4)|[2000-01-01,2010-01-01)|a +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_no_key NOTHING'); + +# replicate with a primary key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_pk (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "UPDATE temporal_pk SET a = 'b' WHERE id = '[2,3)'"); +is( $stderr, + qq(psql::1: ERROR: cannot update table "temporal_pk" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't UPDATE temporal_pk NOTHING"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "DELETE FROM temporal_pk WHERE id = '[3,4)'"); +is( $stderr, + qq(psql::1: ERROR: cannot delete from table "temporal_pk" because it does not have a replica identity and publishes deletes +HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't DELETE temporal_pk NOTHING"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_pk ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|a +[3,4)|[2000-01-01,2010-01-01)|a +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_pk NOTHING'); + +# replicate with a unique key: + +$node_publisher->safe_psql( + 'postgres', + "INSERT INTO temporal_unique (id, valid_at, a) + VALUES ('[2,3)', '[2000-01-01,2010-01-01)', 'a'), + ('[3,4)', '[2000-01-01,2010-01-01)', 'a'), + ('[4,5)', '[2000-01-01,2010-01-01)', 'a')"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "UPDATE temporal_unique SET a = 'b' WHERE id = '[2,3)'"); +is( $stderr, + qq(psql::1: ERROR: cannot update table "temporal_unique" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't UPDATE temporal_unique NOTHING"); + +($result, $stdout, $stderr) = $node_publisher->psql('postgres', + "DELETE FROM temporal_unique WHERE id = '[3,4)'"); +is( $stderr, + qq(psql::1: ERROR: cannot delete from table "temporal_unique" because it does not have a replica identity and publishes deletes +HINT: To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.), + "can't DELETE temporal_unique NOTHING"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = $node_subscriber->safe_psql('postgres', + "SELECT * FROM temporal_unique ORDER BY id, valid_at"); +is( $result, qq{[1,2)|[2000-01-01,2010-01-01)|a +[2,3)|[2000-01-01,2010-01-01)|a +[3,4)|[2000-01-01,2010-01-01)|a +[4,5)|[2000-01-01,2010-01-01)|a}, 'replicated temporal_unique NOTHING'); + +# cleanup + +drop_everything(); + +done_testing(); diff --git a/src/test/subscription/t/035_conflicts.pl b/src/test/subscription/t/035_conflicts.pl new file mode 100644 index 0000000000000..2a7a8239a2966 --- /dev/null +++ b/src/test/subscription/t/035_conflicts.pl @@ -0,0 +1,148 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group + +# Test the conflict detection of conflict type 'multiple_unique_conflicts'. +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +############################### +# Setup +############################### + +# Create a publisher node +my $node_publisher = PostgreSQL::Test::Cluster->new('publisher'); +$node_publisher->init(allows_streaming => 'logical'); +$node_publisher->start; + +# Create a subscriber node +my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber'); +$node_subscriber->init; +$node_subscriber->start; + +# Create a table on publisher +$node_publisher->safe_psql('postgres', + "CREATE TABLE conf_tab (a int PRIMARY KEY, b int UNIQUE, c int UNIQUE);"); + +$node_publisher->safe_psql('postgres', + "CREATE TABLE conf_tab_2 (a int PRIMARY KEY, b int UNIQUE, c int UNIQUE);"); + +# Create same table on subscriber +$node_subscriber->safe_psql('postgres', + "CREATE TABLE conf_tab (a int PRIMARY key, b int UNIQUE, c int UNIQUE);"); + +$node_subscriber->safe_psql( + 'postgres', qq[ + CREATE TABLE conf_tab_2 (a int PRIMARY KEY, b int, c int, unique(a,b)) PARTITION BY RANGE (a); + CREATE TABLE conf_tab_2_p1 PARTITION OF conf_tab_2 FOR VALUES FROM (MINVALUE) TO (100); +]); + +# Setup logical replication +my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; +$node_publisher->safe_psql('postgres', + "CREATE PUBLICATION pub_tab FOR TABLE conf_tab, conf_tab_2"); + +# Create the subscription +my $appname = 'sub_tab'; +$node_subscriber->safe_psql( + 'postgres', + "CREATE SUBSCRIPTION sub_tab + CONNECTION '$publisher_connstr application_name=$appname' + PUBLICATION pub_tab;"); + +# Wait for initial table sync to finish +$node_subscriber->wait_for_subscription_sync($node_publisher, $appname); + +################################################## +# INSERT data on Pub and Sub +################################################## + +# Insert data in the publisher table +$node_publisher->safe_psql('postgres', + "INSERT INTO conf_tab VALUES (1,1,1);"); + +# Insert data in the subscriber table +$node_subscriber->safe_psql('postgres', + "INSERT INTO conf_tab VALUES (2,2,2), (3,3,3), (4,4,4);"); + +################################################## +# Test multiple_unique_conflicts due to INSERT +################################################## +my $log_offset = -s $node_subscriber->logfile; + +$node_publisher->safe_psql('postgres', + "INSERT INTO conf_tab VALUES (2,3,4);"); + +# Confirm that this causes an error on the subscriber +$node_subscriber->wait_for_log( + qr/conflict detected on relation \"public.conf_tab\": conflict=multiple_unique_conflicts.* +.*Key already exists in unique index \"conf_tab_pkey\".* +.*Key \(a\)=\(2\); existing local tuple \(2, 2, 2\); remote tuple \(2, 3, 4\).* +.*Key already exists in unique index \"conf_tab_b_key\".* +.*Key \(b\)=\(3\); existing local tuple \(3, 3, 3\); remote tuple \(2, 3, 4\).* +.*Key already exists in unique index \"conf_tab_c_key\".* +.*Key \(c\)=\(4\); existing local tuple \(4, 4, 4\); remote tuple \(2, 3, 4\)./, + $log_offset); + +pass('multiple_unique_conflicts detected during insert'); + +# Truncate table to get rid of the error +$node_subscriber->safe_psql('postgres', "TRUNCATE conf_tab;"); + +################################################## +# Test multiple_unique_conflicts due to UPDATE +################################################## +$log_offset = -s $node_subscriber->logfile; + +# Insert data in the publisher table +$node_publisher->safe_psql('postgres', + "INSERT INTO conf_tab VALUES (5,5,5);"); + +# Insert data in the subscriber table +$node_subscriber->safe_psql('postgres', + "INSERT INTO conf_tab VALUES (6,6,6), (7,7,7), (8,8,8);"); + +$node_publisher->safe_psql('postgres', + "UPDATE conf_tab set a=6, b=7, c=8 where a=5;"); + +# Confirm that this causes an error on the subscriber +$node_subscriber->wait_for_log( + qr/conflict detected on relation \"public.conf_tab\": conflict=multiple_unique_conflicts.* +.*Key already exists in unique index \"conf_tab_pkey\".* +.*Key \(a\)=\(6\); existing local tuple \(6, 6, 6\); remote tuple \(6, 7, 8\).* +.*Key already exists in unique index \"conf_tab_b_key\".* +.*Key \(b\)=\(7\); existing local tuple \(7, 7, 7\); remote tuple \(6, 7, 8\).* +.*Key already exists in unique index \"conf_tab_c_key\".* +.*Key \(c\)=\(8\); existing local tuple \(8, 8, 8\); remote tuple \(6, 7, 8\)./, + $log_offset); + +pass('multiple_unique_conflicts detected during update'); + +# Truncate table to get rid of the error +$node_subscriber->safe_psql('postgres', "TRUNCATE conf_tab;"); + + +################################################## +# Test multiple_unique_conflicts due to INSERT on a leaf partition +################################################## + +# Insert data in the subscriber table +$node_subscriber->safe_psql('postgres', + "INSERT INTO conf_tab_2 VALUES (55,2,3);"); + +# Insert data in the publisher table +$node_publisher->safe_psql('postgres', + "INSERT INTO conf_tab_2 VALUES (55,2,3);"); + +$node_subscriber->wait_for_log( + qr/conflict detected on relation \"public.conf_tab_2_p1\": conflict=multiple_unique_conflicts.* +.*Key already exists in unique index \"conf_tab_2_p1_pkey\".* +.*Key \(a\)=\(55\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\).* +.*Key already exists in unique index \"conf_tab_2_p1_a_b_key\".* +.*Key \(a, b\)=\(55, 2\); existing local tuple \(55, 2, 3\); remote tuple \(55, 2, 3\)./, + $log_offset); + +pass('multiple_unique_conflicts detected on a leaf partition during insert'); + +done_testing(); diff --git a/src/test/subscription/t/100_bugs.pl b/src/test/subscription/t/100_bugs.pl index cb36ca7b16b62..5e3577011833b 100644 --- a/src/test/subscription/t/100_bugs.pl +++ b/src/test/subscription/t/100_bugs.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # Tests for various bugs found over time use strict; @@ -377,8 +377,8 @@ $node_publisher->stop('fast'); $node_subscriber->stop('fast'); -# The bug was that when the REPLICA IDENTITY FULL is used with dropped or -# generated columns, we fail to apply updates and deletes +# The bug was that when the REPLICA IDENTITY FULL is used with dropped +# we fail to apply updates and deletes $node_publisher->rotate_logfile(); $node_publisher->start(); @@ -389,18 +389,14 @@ 'postgres', qq( CREATE TABLE dropped_cols (a int, b_drop int, c int); ALTER TABLE dropped_cols REPLICA IDENTITY FULL; - CREATE TABLE generated_cols (a int, b_gen int GENERATED ALWAYS AS (5 * a) STORED, c int); - ALTER TABLE generated_cols REPLICA IDENTITY FULL; - CREATE PUBLICATION pub_dropped_cols FOR TABLE dropped_cols, generated_cols; + CREATE PUBLICATION pub_dropped_cols FOR TABLE dropped_cols; -- some initial data INSERT INTO dropped_cols VALUES (1, 1, 1); - INSERT INTO generated_cols (a, c) VALUES (1, 1); )); $node_subscriber->safe_psql( 'postgres', qq( CREATE TABLE dropped_cols (a int, b_drop int, c int); - CREATE TABLE generated_cols (a int, b_gen int GENERATED ALWAYS AS (5 * a) STORED, c int); )); $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; @@ -421,7 +417,6 @@ $node_publisher->safe_psql( 'postgres', qq( UPDATE dropped_cols SET a = 100; - UPDATE generated_cols SET a = 100; )); $node_publisher->wait_for_catchup('sub_dropped_cols'); @@ -430,11 +425,6 @@ qq(1), 'replication with RI FULL and dropped columns'); -is( $node_subscriber->safe_psql( - 'postgres', "SELECT count(*) FROM generated_cols WHERE a = 100"), - qq(1), - 'replication with RI FULL and generated columns'); - $node_publisher->stop('fast'); $node_subscriber->stop('fast'); @@ -487,6 +477,101 @@ is( $result, qq(2|f 3|t), 'check replicated update on subscriber'); +# Test create and immediate drop of replication slot via replication commands +# (this exposed a memory-management bug in v18) +my $publisher_host = $node_publisher->host; +my $publisher_port = $node_publisher->port; +my $connstr_db = + "host=$publisher_host port=$publisher_port replication=database dbname=postgres"; + +is( $node_publisher->psql( + 'postgres', + qq[ + CREATE_REPLICATION_SLOT test_slot LOGICAL pgoutput (SNAPSHOT export); + DROP_REPLICATION_SLOT test_slot; + ], + timeout => $PostgreSQL::Test::Utils::timeout_default, + extra_params => [ '-d', $connstr_db ]), + 0, + 'create and immediate drop of replication slot'); + +$node_publisher->stop('fast'); +$node_subscriber->stop('fast'); + +# The bug was that when an ERROR was caught and handled by a (PL/pgSQL) +# function, the apply worker reset the replication origin but continued +# processing subsequent changes. So, we fail to update the replication origin +# during further apply operations. This can lead to the apply worker requesting +# the changes that have been applied again after restarting. + +$node_publisher->rotate_logfile(); +$node_publisher->start(); + +$node_subscriber->rotate_logfile(); +$node_subscriber->start(); + +# Set up a publication with a table +$node_publisher->safe_psql( + 'postgres', qq( + CREATE TABLE t1 (a int); + CREATE PUBLICATION regress_pub FOR TABLE t1; +)); + +# Set up a subscription which subscribes the publication +$node_subscriber->safe_psql( + 'postgres', qq( + CREATE TABLE t1 (a int); + CREATE SUBSCRIPTION regress_sub CONNECTION '$publisher_connstr' PUBLICATION regress_pub; +)); + +$node_subscriber->wait_for_subscription_sync($node_publisher, 'regress_sub'); + +# Create an AFTER INSERT trigger on the table that raises and subsequently +# handles an exception. Subsequent insertions will trigger this exception, +# causing the apply worker to invoke its error callback with an ERROR. However, +# since the error is caught within the trigger, the apply worker will continue +# processing changes. +$node_subscriber->safe_psql( + 'postgres', q{ +CREATE FUNCTION handle_exception_trigger() +RETURNS TRIGGER AS $$ +BEGIN + BEGIN + -- Raise an exception + RAISE EXCEPTION 'This is a test exception'; + EXCEPTION + WHEN OTHERS THEN + RETURN NEW; + END; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER silent_exception_trigger +AFTER INSERT OR UPDATE ON t1 +FOR EACH ROW +EXECUTE FUNCTION handle_exception_trigger(); + +ALTER TABLE t1 ENABLE ALWAYS TRIGGER silent_exception_trigger; +}); + +# Obtain current remote_lsn value to check its advancement later +my $remote_lsn = $node_subscriber->safe_psql('postgres', + "SELECT remote_lsn FROM pg_replication_origin_status os, pg_subscription s WHERE os.external_id = 'pg_' || s.oid AND s.subname = 'regress_sub'" +); + +# Insert a tuple to replicate changes +$node_publisher->safe_psql('postgres', "INSERT INTO t1 VALUES (1);"); +$node_publisher->wait_for_catchup('regress_sub'); + +# Confirms the origin can be advanced +$result = $node_subscriber->safe_psql('postgres', + "SELECT remote_lsn > '$remote_lsn' FROM pg_replication_origin_status os, pg_subscription s WHERE os.external_id = 'pg_' || s.oid AND s.subname = 'regress_sub'" +); +is($result, 't', + 'remote_lsn has advanced for apply worker raising an exception'); + $node_publisher->stop('fast'); $node_subscriber->stop('fast'); diff --git a/src/timezone/data/tzdata.zi b/src/timezone/data/tzdata.zi index be1c408592027..a7fb52f1968f3 100644 --- a/src/timezone/data/tzdata.zi +++ b/src/timezone/data/tzdata.zi @@ -1,4 +1,4 @@ -# version 2024a +# version 2025b # This zic input file is in the public domain. R d 1916 o - Jun 14 23s 1 S R d 1916 1919 - O Su>=1 23s 0 - @@ -721,12 +721,16 @@ R P 2085 o - Ap 21 2 0 - R P 2085 o - Jun 9 2 1 S R P 2086 o - Ap 13 2 0 - R P 2086 o - May 25 2 1 S -R PH 1936 o - N 1 0 1 D -R PH 1937 o - F 1 0 0 S -R PH 1954 o - Ap 12 0 1 D -R PH 1954 o - Jul 1 0 0 S -R PH 1978 o - Mar 22 0 1 D -R PH 1978 o - S 21 0 0 S +R PH 1936 o - O 31 24 1 D +R PH 1937 o - Ja 15 24 0 S +R PH 1941 o - D 15 24 1 D +R PH 1945 o - N 30 24 0 S +R PH 1954 o - Ap 11 24 1 D +R PH 1954 o - Jun 4 24 0 S +R PH 1977 o - Mar 27 24 1 D +R PH 1977 o - S 21 24 0 S +R PH 1990 o - May 21 0 1 D +R PH 1990 o - Jul 28 24 0 S R S 1920 1923 - Ap Su>=15 2 1 S R S 1920 1923 - O Su>=1 2 0 - R S 1962 o - Ap 29 2 1 S @@ -1324,14 +1328,10 @@ R O 1961 1964 - May lastSu 1s 1 S R O 1962 1964 - S lastSu 1s 0 - R p 1916 o - Jun 17 23 1 S R p 1916 o - N 1 1 0 - -R p 1917 o - F 28 23s 1 S -R p 1917 1921 - O 14 23s 0 - -R p 1918 o - Mar 1 23s 1 S -R p 1919 o - F 28 23s 1 S -R p 1920 o - F 29 23s 1 S -R p 1921 o - F 28 23s 1 S +R p 1917 1921 - Mar 1 0 1 S +R p 1917 1921 - O 14 24 0 - R p 1924 o - Ap 16 23s 1 S -R p 1924 o - O 14 23s 0 - +R p 1924 o - O 4 23s 0 - R p 1926 o - Ap 17 23s 1 S R p 1926 1929 - O Sa>=1 23s 0 - R p 1927 o - Ap 9 23s 1 S @@ -1349,8 +1349,9 @@ R p 1938 o - Mar 26 23s 1 S R p 1939 o - Ap 15 23s 1 S R p 1939 o - N 18 23s 0 - R p 1940 o - F 24 23s 1 S -R p 1940 1941 - O 5 23s 0 - +R p 1940 o - O 7 23s 0 - R p 1941 o - Ap 5 23s 1 S +R p 1941 o - O 5 23s 0 - R p 1942 1945 - Mar Sa>=8 23s 1 S R p 1942 o - Ap 25 22s 2 M R p 1942 o - Au 15 22s 1 S @@ -1360,16 +1361,16 @@ R p 1943 1945 - Au Sa>=25 22s 1 S R p 1944 1945 - Ap Sa>=21 22s 2 M R p 1946 o - Ap Sa>=1 23s 1 S R p 1946 o - O Sa>=1 23s 0 - -R p 1947 1965 - Ap Su>=1 2s 1 S +R p 1947 1966 - Ap Su>=1 2s 1 S R p 1947 1965 - O Su>=1 2s 0 - -R p 1977 o - Mar 27 0s 1 S -R p 1977 o - S 25 0s 0 - -R p 1978 1979 - Ap Su>=1 0s 1 S -R p 1978 o - O 1 0s 0 - -R p 1979 1982 - S lastSu 1s 0 - -R p 1980 o - Mar lastSu 0s 1 S -R p 1981 1982 - Mar lastSu 1s 1 S -R p 1983 o - Mar lastSu 2s 1 S +R p 1976 o - S lastSu 1 0 - +R p 1977 o - Mar lastSu 0s 1 S +R p 1977 o - S lastSu 0s 0 - +R p 1978 1980 - Ap Su>=1 1s 1 S +R p 1978 o - O 1 1s 0 - +R p 1979 1980 - S lastSu 1s 0 - +R p 1981 1986 - Mar lastSu 0s 1 S +R p 1981 1985 - S lastSu 0s 0 - R z 1932 o - May 21 0s 1 S R z 1932 1939 - O Su>=1 0s 0 - R z 1933 1939 - Ap Su>=2 0s 1 S @@ -1728,7 +1729,7 @@ R Y 1972 2006 - O lastSu 2 0 S R Y 1987 2006 - Ap Su>=1 2 1 D R Yu 1965 o - Ap lastSu 0 2 DD R Yu 1965 o - O lastSu 2 0 S -R m 1931 o - May 1 23 1 D +R m 1931 o - Ap 30 0 1 D R m 1931 o - O 1 0 0 S R m 1939 o - F 5 0 1 D R m 1939 o - Jun 25 0 0 S @@ -2022,9 +2023,9 @@ R y 2002 2004 - Ap Su>=1 0 0 - R y 2002 2003 - S Su>=1 0 1 - R y 2004 2009 - O Su>=15 0 1 - R y 2005 2009 - Mar Su>=8 0 0 - -R y 2010 ma - O Su>=1 0 1 - +R y 2010 2024 - O Su>=1 0 1 - R y 2010 2012 - Ap Su>=8 0 0 - -R y 2013 ma - Mar Su>=22 0 0 - +R y 2013 2024 - Mar Su>=22 0 0 - R PE 1938 o - Ja 1 0 1 - R PE 1938 o - Ap 1 0 0 - R PE 1938 1939 - S lastSu 0 1 - @@ -2096,15 +2097,15 @@ Z Africa/Algiers 0:12:12 - LMT 1891 Mar 16 0 d WE%sT 1981 May 1 - CET Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u --1 - -01 1975 +-1 - %z 1975 0 - GMT Z Africa/Cairo 2:5:9 - LMT 1900 O 2 K EE%sT Z Africa/Casablanca -0:30:20 - LMT 1913 O 26 -0 M +00/+01 1984 Mar 16 -1 - +01 1986 -0 M +00/+01 2018 O 28 3 -1 M +01/+00 +0 M %z 1984 Mar 16 +1 - %z 1986 +0 M %z 2018 O 28 3 +1 M %z Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u 0 - WET 1918 May 6 23 0 1 WEST 1918 O 7 23 @@ -2115,9 +2116,9 @@ Z Africa/Ceuta -0:21:16 - LMT 1901 Ja 1 0u 1 - CET 1986 1 E CE%sT Z Africa/El_Aaiun -0:52:48 - LMT 1934 --1 - -01 1976 Ap 14 -0 M +00/+01 2018 O 28 3 -1 M +01/+00 +-1 - %z 1976 Ap 14 +0 M %z 2018 O 28 3 +1 M %z Z Africa/Johannesburg 1:52 - LMT 1892 F 8 1:30 - SAST 1903 Mar 2 SA SAST @@ -2132,19 +2133,19 @@ Z Africa/Khartoum 2:10:8 - LMT 1931 Z Africa/Lagos 0:13:35 - LMT 1905 Jul 0 - GMT 1908 Jul 0:13:35 - LMT 1914 -0:30 - +0030 1919 S +0:30 - %z 1919 S 1 - WAT -Z Africa/Maputo 2:10:20 - LMT 1903 Mar +Z Africa/Maputo 2:10:18 - LMT 1909 2 - CAT Z Africa/Monrovia -0:43:8 - LMT 1882 -0:43:8 - MMT 1919 Mar -0:44:30 - MMT 1972 Ja 7 0 - GMT Z Africa/Nairobi 2:27:16 - LMT 1908 May -2:30 - +0230 1928 Jun 30 24 +2:30 - %z 1928 Jun 30 24 3 - EAT 1930 Ja 4 24 -2:30 - +0230 1936 D 31 24 -2:45 - +0245 1942 Jul 31 24 +2:30 - %z 1936 D 31 24 +2:45 - %z 1942 Jul 31 24 3 - EAT Z Africa/Ndjamena 1:0:12 - LMT 1912 1 - WAT 1979 O 14 @@ -2168,7 +2169,7 @@ Z Africa/Tunis 0:40:44 - LMT 1881 May 12 0:9:21 - PMT 1911 Mar 11 1 n CE%sT Z Africa/Windhoek 1:8:24 - LMT 1892 F 8 -1:30 - +0130 1903 Mar +1:30 - %z 1903 Mar 2 - SAST 1942 S 20 2 2 1 SAST 1943 Mar 21 2 2 - SAST 1990 Mar 21 @@ -2191,167 +2192,167 @@ Z America/Anchorage 14:0:24 - LMT 1867 O 19 14:31:37 -9 u Y%sT 1983 N 30 -9 u AK%sT Z America/Araguaina -3:12:48 - LMT 1914 --3 B -03/-02 1990 S 17 --3 - -03 1995 S 14 --3 B -03/-02 2003 S 24 --3 - -03 2012 O 21 --3 B -03/-02 2013 S --3 - -03 +-3 B %z 1990 S 17 +-3 - %z 1995 S 14 +-3 B %z 2003 S 24 +-3 - %z 2012 O 21 +-3 B %z 2013 S +-3 - %z Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 A -03/-02 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 A %z Z America/Argentina/Catamarca -4:23:8 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar 3 --4 - -04 1991 O 20 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 Jun --4 - -04 2004 Jun 20 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar 3 +-4 - %z 1991 O 20 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 Jun +-4 - %z 2004 Jun 20 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/Cordoba -4:16:48 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar 3 --4 - -04 1991 O 20 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 A -03/-02 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar 3 +-4 - %z 1991 O 20 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 A %z Z America/Argentina/Jujuy -4:21:12 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1990 Mar 4 --4 - -04 1990 O 28 --4 1 -03 1991 Mar 17 --4 - -04 1991 O 6 --3 1 -02 1992 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1990 Mar 4 +-4 - %z 1990 O 28 +-4 1 %z 1991 Mar 17 +-4 - %z 1991 O 6 +-3 1 %z 1992 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/La_Rioja -4:27:24 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar --4 - -04 1991 May 7 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 Jun --4 - -04 2004 Jun 20 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar +-4 - %z 1991 May 7 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 Jun +-4 - %z 2004 Jun 20 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/Mendoza -4:35:16 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1990 Mar 4 --4 - -04 1990 O 15 --4 1 -03 1991 Mar --4 - -04 1991 O 15 --4 1 -03 1992 Mar --4 - -04 1992 O 18 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 May 23 --4 - -04 2004 S 26 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1990 Mar 4 +-4 - %z 1990 O 15 +-4 1 %z 1991 Mar +-4 - %z 1991 O 15 +-4 1 %z 1992 Mar +-4 - %z 1992 O 18 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 May 23 +-4 - %z 2004 S 26 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 Jun --4 - -04 2004 Jun 20 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 Jun +-4 - %z 2004 Jun 20 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/Salta -4:21:40 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar 3 --4 - -04 1991 O 20 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar 3 +-4 - %z 1991 O 20 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/San_Juan -4:34:4 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar --4 - -04 1991 May 7 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 May 31 --4 - -04 2004 Jul 25 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar +-4 - %z 1991 May 7 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 May 31 +-4 - %z 2004 Jul 25 +-3 A %z 2008 O 18 +-3 - %z Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1990 --3 1 -02 1990 Mar 14 --4 - -04 1990 O 15 --4 1 -03 1991 Mar --4 - -04 1991 Jun --3 - -03 1999 O 3 --4 1 -03 2000 Mar 3 --3 - -03 2004 May 31 --4 - -04 2004 Jul 25 --3 A -03/-02 2008 Ja 21 --4 Sa -04/-03 2009 O 11 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1990 +-3 1 %z 1990 Mar 14 +-4 - %z 1990 O 15 +-4 1 %z 1991 Mar +-4 - %z 1991 Jun +-3 - %z 1999 O 3 +-4 1 %z 2000 Mar 3 +-3 - %z 2004 May 31 +-4 - %z 2004 Jul 25 +-3 A %z 2008 Ja 21 +-4 Sa %z 2009 O 11 +-3 - %z Z America/Argentina/Tucuman -4:20:52 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1991 Mar 3 --4 - -04 1991 O 20 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 Jun --4 - -04 2004 Jun 13 --3 A -03/-02 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1991 Mar 3 +-4 - %z 1991 O 20 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 Jun +-4 - %z 2004 Jun 13 +-3 A %z Z America/Argentina/Ushuaia -4:33:12 - LMT 1894 O 31 -4:16:48 - CMT 1920 May --4 - -04 1930 D --4 A -04/-03 1969 O 5 --3 A -03/-02 1999 O 3 --4 A -04/-03 2000 Mar 3 --3 - -03 2004 May 30 --4 - -04 2004 Jun 20 --3 A -03/-02 2008 O 18 --3 - -03 +-4 - %z 1930 D +-4 A %z 1969 O 5 +-3 A %z 1999 O 3 +-4 A %z 2000 Mar 3 +-3 - %z 2004 May 30 +-4 - %z 2004 Jun 20 +-3 A %z 2008 O 18 +-3 - %z Z America/Asuncion -3:50:40 - LMT 1890 -3:50:40 - AMT 1931 O 10 --4 - -04 1972 O --3 - -03 1974 Ap --4 y -04/-03 +-4 - %z 1972 O +-3 - %z 1974 Ap +-4 y %z 2024 O 15 +-3 - %z Z America/Bahia -2:34:4 - LMT 1914 --3 B -03/-02 2003 S 24 --3 - -03 2011 O 16 --3 B -03/-02 2012 O 21 --3 - -03 +-3 B %z 2003 S 24 +-3 - %z 2011 O 16 +-3 B %z 2012 O 21 +-3 - %z Z America/Bahia_Banderas -7:1 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1942 Ap 24 --7 - MST 1949 Ja 14 --8 - PST 1970 +-7 - MST 1970 -7 m M%sT 2010 Ap 4 2 -6 m C%sT Z America/Barbados -3:58:29 - LMT 1911 Au 28 @@ -2359,18 +2360,18 @@ Z America/Barbados -3:58:29 - LMT 1911 Au 28 -4 BB AST/-0330 1945 -4 BB A%sT Z America/Belem -3:13:56 - LMT 1914 --3 B -03/-02 1988 S 12 --3 - -03 +-3 B %z 1988 S 12 +-3 - %z Z America/Belize -5:52:48 - LMT 1912 Ap -6 BZ %s Z America/Boa_Vista -4:2:40 - LMT 1914 --4 B -04/-03 1988 S 12 --4 - -04 1999 S 30 --4 B -04/-03 2000 O 15 --4 - -04 +-4 B %z 1988 S 12 +-4 - %z 1999 S 30 +-4 B %z 2000 O 15 +-4 - %z Z America/Bogota -4:56:16 - LMT 1884 Mar 13 -4:56:16 - BMT 1914 N 23 --5 CO -05/-04 +-5 CO %z Z America/Boise -7:44:49 - LMT 1883 N 18 20u -8 u P%sT 1923 May 13 2 -7 u M%sT 1974 @@ -2383,21 +2384,23 @@ Z America/Cambridge_Bay 0 - -00 1920 -6 - CST 2001 Ap 1 3 -7 C M%sT Z America/Campo_Grande -3:38:28 - LMT 1914 --4 B -04/-03 +-4 B %z Z America/Cancun -5:47:4 - LMT 1922 Ja 1 6u --6 - CST 1981 D 23 +-6 - CST 1981 D 26 2 +-5 - EST 1983 Ja 4 +-6 m C%sT 1997 O 26 2 -5 m E%sT 1998 Au 2 2 -6 m C%sT 2015 F 1 2 -5 - EST Z America/Caracas -4:27:44 - LMT 1890 -4:27:40 - CMT 1912 F 12 --4:30 - -0430 1965 --4 - -04 2007 D 9 3 --4:30 - -0430 2016 May 1 2:30 --4 - -04 +-4:30 - %z 1965 +-4 - %z 2007 D 9 3 +-4:30 - %z 2016 May 1 2:30 +-4 - %z Z America/Cayenne -3:29:20 - LMT 1911 Jul --4 - -04 1967 O --3 - -03 +-4 - %z 1967 O +-3 - %z Z America/Chicago -5:50:36 - LMT 1883 N 18 18u -6 u C%sT 1920 -6 Ch C%sT 1936 Mar 1 2 @@ -2407,7 +2410,7 @@ Z America/Chicago -5:50:36 - LMT 1883 N 18 18u -6 Ch C%sT 1967 -6 u C%sT Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1996 @@ -2416,7 +2419,7 @@ Z America/Chihuahua -7:4:20 - LMT 1922 Ja 1 7u -7 m M%sT 2022 O 30 2 -6 - CST Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1996 @@ -2429,13 +2432,27 @@ Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u Z America/Costa_Rica -5:36:13 - LMT 1890 -5:36:13 - SJMT 1921 Ja 15 -6 CR C%sT +Z America/Coyhaique -4:48:16 - LMT 1890 +-4:42:45 - SMT 1910 Ja 10 +-5 - %z 1916 Jul +-4:42:45 - SMT 1918 S 10 +-4 - %z 1919 Jul +-4:42:45 - SMT 1927 S +-5 x %z 1932 S +-4 - %z 1942 Jun +-5 - %z 1942 Au +-4 - %z 1946 Au 28 24 +-5 1 %z 1947 Mar 31 24 +-5 - %z 1947 May 21 23 +-4 x %z 2025 Mar 20 +-3 - %z Z America/Cuiaba -3:44:20 - LMT 1914 --4 B -04/-03 2003 S 24 --4 - -04 2004 O --4 B -04/-03 +-4 B %z 2003 S 24 +-4 - %z 2004 O +-4 B %z Z America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28 --3 - -03 1980 Ap 6 2 --3 E -03/-02 1996 +-3 - %z 1980 Ap 6 2 +-3 E %z 1996 0 - GMT Z America/Dawson -9:17:40 - LMT 1900 Au 20 -9 Y Y%sT 1965 @@ -2467,12 +2484,12 @@ Z America/Edmonton -7:33:52 - LMT 1906 S -7 Ed M%sT 1987 -7 C M%sT Z America/Eirunepe -4:39:28 - LMT 1914 --5 B -05/-04 1988 S 12 --5 - -05 1993 S 28 --5 B -05/-04 1994 S 22 --5 - -05 2008 Jun 24 --4 - -04 2013 N 10 --5 - -05 +-5 B %z 1988 S 12 +-5 - %z 1993 S 28 +-5 B %z 1994 S 22 +-5 - %z 2008 Jun 24 +-4 - %z 2013 N 10 +-5 - %z Z America/El_Salvador -5:56:48 - LMT 1921 -6 SV C%sT Z America/Fort_Nelson -8:10:47 - LMT 1884 @@ -2482,12 +2499,12 @@ Z America/Fort_Nelson -8:10:47 - LMT 1884 -8 C P%sT 2015 Mar 8 2 -7 - MST Z America/Fortaleza -2:34 - LMT 1914 --3 B -03/-02 1990 S 17 --3 - -03 1999 S 30 --3 B -03/-02 2000 O 22 --3 - -03 2001 S 13 --3 B -03/-02 2002 O --3 - -03 +-3 B %z 1990 S 17 +-3 - %z 1999 S 30 +-3 B %z 2000 O 22 +-3 - %z 2001 S 13 +-3 B %z 2002 O +-3 - %z Z America/Glace_Bay -3:59:48 - LMT 1902 Jun 15 -4 C A%sT 1953 -4 H A%sT 1954 @@ -2514,12 +2531,12 @@ Z America/Guatemala -6:2:4 - LMT 1918 O 5 -6 GT C%sT Z America/Guayaquil -5:19:20 - LMT 1890 -5:14 - QMT 1931 --5 EC -05/-04 +-5 EC %z Z America/Guyana -3:52:39 - LMT 1911 Au --4 - -04 1915 Mar --3:45 - -0345 1975 Au --3 - -03 1992 Mar 29 1 --4 - -04 +-4 - %z 1915 Mar +-3:45 - %z 1975 Au +-3 - %z 1992 Mar 29 1 +-4 - %z Z America/Halifax -4:14:24 - LMT 1902 Jun 15 -4 H A%sT 1918 -4 C A%sT 1919 @@ -2531,12 +2548,11 @@ Z America/Havana -5:29:28 - LMT 1890 -5:29:36 - HMT 1925 Jul 19 12 -5 Q C%sT Z America/Hermosillo -7:23:52 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1942 Ap 24 --7 - MST 1949 Ja 14 --8 - PST 1970 +-7 - MST 1996 -7 m M%sT 1999 -7 - MST Z America/Indiana/Indianapolis -5:44:38 - LMT 1883 N 18 18u @@ -2644,23 +2660,23 @@ Z America/Kentucky/Monticello -5:39:24 - LMT 1883 N 18 18u Z America/La_Paz -4:32:36 - LMT 1890 -4:32:36 - CMT 1931 O 15 -4:32:36 1 BST 1932 Mar 21 --4 - -04 +-4 - %z Z America/Lima -5:8:12 - LMT 1890 -5:8:36 - LMT 1908 Jul 28 --5 PE -05/-04 +-5 PE %z Z America/Los_Angeles -7:52:58 - LMT 1883 N 18 20u -8 u P%sT 1946 -8 CA P%sT 1967 -8 u P%sT Z America/Maceio -2:22:52 - LMT 1914 --3 B -03/-02 1990 S 17 --3 - -03 1995 O 13 --3 B -03/-02 1996 S 4 --3 - -03 1999 S 30 --3 B -03/-02 2000 O 22 --3 - -03 2001 S 13 --3 B -03/-02 2002 O --3 - -03 +-3 B %z 1990 S 17 +-3 - %z 1995 O 13 +-3 B %z 1996 S 4 +-3 - %z 1999 S 30 +-3 B %z 2000 O 22 +-3 - %z 2001 S 13 +-3 B %z 2002 O +-3 - %z Z America/Managua -5:45:8 - LMT 1890 -5:45:12 - MMT 1934 Jun 23 -6 - CST 1973 May @@ -2671,10 +2687,10 @@ Z America/Managua -5:45:8 - LMT 1890 -5 - EST 1997 -6 NI C%sT Z America/Manaus -4:0:4 - LMT 1914 --4 B -04/-03 1988 S 12 --4 - -04 1993 S 28 --4 B -04/-03 1994 S 22 --4 - -04 +-4 B %z 1988 S 12 +-4 - %z 1993 S 28 +-4 B %z 1994 S 22 +-4 - %z Z America/Martinique -4:4:20 - LMT 1890 -4:4:20 - FFMT 1911 May -4 - AST 1980 Ap 6 @@ -2686,12 +2702,11 @@ Z America/Matamoros -6:30 - LMT 1922 Ja 1 6u -6 m C%sT 2010 -6 u C%sT Z America/Mazatlan -7:5:40 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1942 Ap 24 --7 - MST 1949 Ja 14 --8 - PST 1970 +-7 - MST 1970 -7 m M%sT Z America/Menominee -5:50:27 - LMT 1885 S 18 12 -6 u C%sT 1946 @@ -2699,8 +2714,8 @@ Z America/Menominee -5:50:27 - LMT 1885 S 18 12 -5 - EST 1973 Ap 29 2 -6 u C%sT Z America/Merida -5:58:28 - LMT 1922 Ja 1 6u --6 - CST 1981 D 23 --5 - EST 1982 D 2 +-6 - CST 1981 D 26 2 +-5 - EST 1982 N 2 2 -6 m C%sT Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55 -8:46:18 - LMT 1900 Au 20 12 @@ -2713,7 +2728,7 @@ Z America/Metlakatla 15:13:42 - LMT 1867 O 19 15:44:55 -8 - PST 2019 Ja 20 2 -9 u AK%sT Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 m C%sT 2001 S 30 2 @@ -2721,8 +2736,8 @@ Z America/Mexico_City -6:36:36 - LMT 1922 Ja 1 7u -6 m C%sT Z America/Miquelon -3:44:40 - LMT 1911 Jun 15 -4 - AST 1980 May --3 - -03 1987 --3 C -03/-02 +-3 - %z 1987 +-3 C %z Z America/Moncton -4:19:8 - LMT 1883 D 9 -5 - EST 1902 Jun 15 -4 C A%sT 1933 @@ -2733,20 +2748,23 @@ Z America/Moncton -4:19:8 - LMT 1883 D 9 -4 o A%sT 2007 -4 C A%sT Z America/Monterrey -6:41:16 - LMT 1922 Ja 1 6u +-7 - MST 1927 Jun 10 +-6 - CST 1930 N 15 +-7 m M%sT 1932 Ap -6 - CST 1988 -6 u C%sT 1989 -6 m C%sT Z America/Montevideo -3:44:51 - LMT 1908 Jun 10 -3:44:51 - MMT 1920 May --4 - -04 1923 O --3:30 U -0330/-03 1942 D 14 --3 U -03/-0230 1960 --3 U -03/-02 1968 --3 U -03/-0230 1970 --3 U -03/-02 1974 --3 U -03/-0130 1974 Mar 10 --3 U -03/-0230 1974 D 22 --3 U -03/-02 +-4 - %z 1923 O +-3:30 U %z 1942 D 14 +-3 U %z 1960 +-3 U %z 1968 +-3 U %z 1970 +-3 U %z 1974 +-3 U %z 1974 Mar 10 +-3 U %z 1974 D 22 +-3 U %z Z America/New_York -4:56:2 - LMT 1883 N 18 17u -5 u E%sT 1920 -5 NY E%sT 1942 @@ -2763,12 +2781,12 @@ Z America/Nome 12:58:22 - LMT 1867 O 19 13:29:35 -9 u Y%sT 1983 N 30 -9 u AK%sT Z America/Noronha -2:9:40 - LMT 1914 --2 B -02/-01 1990 S 17 --2 - -02 1999 S 30 --2 B -02/-01 2000 O 15 --2 - -02 2001 S 13 --2 B -02/-01 2002 O --2 - -02 +-2 B %z 1990 S 17 +-2 - %z 1999 S 30 +-2 B %z 2000 O 15 +-2 - %z 2001 S 13 +-2 B %z 2002 O +-2 - %z Z America/North_Dakota/Beulah -6:47:7 - LMT 1883 N 18 19u -7 u M%sT 2010 N 7 2 -6 u C%sT @@ -2779,12 +2797,12 @@ Z America/North_Dakota/New_Salem -6:45:39 - LMT 1883 N 18 19u -7 u M%sT 2003 O 26 2 -6 u C%sT Z America/Nuuk -3:26:56 - LMT 1916 Jul 28 --3 - -03 1980 Ap 6 2 --3 E -03/-02 2023 Mar 26 1u --2 - -02 2023 O 29 1u --2 E -02/-01 +-3 - %z 1980 Ap 6 2 +-3 E %z 2023 Mar 26 1u +-2 - %z 2023 O 29 1u +-2 E %z Z America/Ojinaga -6:57:40 - LMT 1922 Ja 1 7u --7 - MST 1927 Jun 10 23 +-7 - MST 1927 Jun 10 -6 - CST 1930 N 15 -7 m M%sT 1932 Ap -6 - CST 1996 @@ -2800,8 +2818,8 @@ Z America/Panama -5:18:8 - LMT 1890 Z America/Paramaribo -3:40:40 - LMT 1911 -3:40:52 - PMT 1935 -3:40:36 - PMT 1945 O --3:30 - -0330 1984 O --3 - -03 +-3:30 - %z 1984 O +-3 - %z Z America/Phoenix -7:28:18 - LMT 1883 N 18 19u -7 u M%sT 1944 Ja 1 0:1 -7 - MST 1944 Ap 1 0:1 @@ -2813,37 +2831,37 @@ Z America/Port-au-Prince -4:49:20 - LMT 1890 -4:49 - PPMT 1917 Ja 24 12 -5 HT E%sT Z America/Porto_Velho -4:15:36 - LMT 1914 --4 B -04/-03 1988 S 12 --4 - -04 +-4 B %z 1988 S 12 +-4 - %z Z America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12 -4 - AST 1942 May 3 -4 u A%sT 1946 -4 - AST Z America/Punta_Arenas -4:43:40 - LMT 1890 -4:42:45 - SMT 1910 Ja 10 --5 - -05 1916 Jul +-5 - %z 1916 Jul -4:42:45 - SMT 1918 S 10 --4 - -04 1919 Jul +-4 - %z 1919 Jul -4:42:45 - SMT 1927 S --5 x -05/-04 1932 S --4 - -04 1942 Jun --5 - -05 1942 Au --4 - -04 1946 Au 28 24 --5 1 -04 1947 Mar 31 24 --5 - -05 1947 May 21 23 --4 x -04/-03 2016 D 4 --3 - -03 +-5 x %z 1932 S +-4 - %z 1942 Jun +-5 - %z 1942 Au +-4 - %z 1946 Au 28 24 +-5 1 %z 1947 Mar 31 24 +-5 - %z 1947 May 21 23 +-4 x %z 2016 D 4 +-3 - %z Z America/Rankin_Inlet 0 - -00 1957 -6 Y C%sT 2000 O 29 2 -5 - EST 2001 Ap 1 3 -6 C C%sT Z America/Recife -2:19:36 - LMT 1914 --3 B -03/-02 1990 S 17 --3 - -03 1999 S 30 --3 B -03/-02 2000 O 15 --3 - -03 2001 S 13 --3 B -03/-02 2002 O --3 - -03 +-3 B %z 1990 S 17 +-3 - %z 1999 S 30 +-3 B %z 2000 O 15 +-3 - %z 2001 S 13 +-3 B %z 2002 O +-3 - %z Z America/Regina -6:58:36 - LMT 1905 S -7 r M%sT 1960 Ap lastSu 2 -6 - CST @@ -2854,28 +2872,28 @@ Z America/Resolute 0 - -00 1947 Au 31 -5 - EST 2007 Mar 11 3 -6 C C%sT Z America/Rio_Branco -4:31:12 - LMT 1914 --5 B -05/-04 1988 S 12 --5 - -05 2008 Jun 24 --4 - -04 2013 N 10 --5 - -05 +-5 B %z 1988 S 12 +-5 - %z 2008 Jun 24 +-4 - %z 2013 N 10 +-5 - %z Z America/Santarem -3:38:48 - LMT 1914 --4 B -04/-03 1988 S 12 --4 - -04 2008 Jun 24 --3 - -03 +-4 B %z 1988 S 12 +-4 - %z 2008 Jun 24 +-3 - %z Z America/Santiago -4:42:45 - LMT 1890 -4:42:45 - SMT 1910 Ja 10 --5 - -05 1916 Jul +-5 - %z 1916 Jul -4:42:45 - SMT 1918 S 10 --4 - -04 1919 Jul +-4 - %z 1919 Jul -4:42:45 - SMT 1927 S --5 x -05/-04 1932 S --4 - -04 1942 Jun --5 - -05 1942 Au --4 - -04 1946 Jul 14 24 --4 1 -03 1946 Au 28 24 --5 1 -04 1947 Mar 31 24 --5 - -05 1947 May 21 23 --4 x -04/-03 +-5 x %z 1932 S +-4 - %z 1942 Jun +-5 - %z 1942 Au +-4 - %z 1946 Jul 14 24 +-4 1 %z 1946 Au 28 24 +-5 1 %z 1947 Mar 31 24 +-5 - %z 1947 May 21 23 +-4 x %z Z America/Santo_Domingo -4:39:36 - LMT 1890 -4:40 - SDMT 1933 Ap 1 12 -5 DO %s 1974 O 27 @@ -2883,14 +2901,14 @@ Z America/Santo_Domingo -4:39:36 - LMT 1890 -5 u E%sT 2000 D 3 1 -4 - AST Z America/Sao_Paulo -3:6:28 - LMT 1914 --3 B -03/-02 1963 O 23 --3 1 -02 1964 --3 B -03/-02 +-3 B %z 1963 O 23 +-3 1 %z 1964 +-3 B %z Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 --2 - -02 1980 Ap 6 2 --2 c -02/-01 1981 Mar 29 --1 E -01/+00 2024 Mar 31 --2 E -02/-01 +-2 - %z 1980 Ap 6 2 +-2 c %z 1981 Mar 29 +-1 E %z 2024 Mar 31 +-2 E %z Z America/Sitka 14:58:47 - LMT 1867 O 19 15:30 -9:1:13 - LMT 1900 Au 20 12 -8 - PST 1942 @@ -2918,15 +2936,21 @@ Z America/Thule -4:35:8 - LMT 1916 Jul 28 -4 Th A%sT Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 7u -7 - MST 1924 --8 - PST 1927 Jun 10 23 +-8 - PST 1927 Jun 10 -7 - MST 1930 N 15 -8 - PST 1931 Ap -8 1 PDT 1931 S 30 -8 - PST 1942 Ap 24 -8 1 PWT 1945 Au 14 23u --8 1 PPT 1945 N 12 +-8 1 PPT 1945 N 15 -8 - PST 1948 Ap 5 -8 1 PDT 1949 Ja 14 +-8 - PST 1950 May +-8 1 PDT 1950 S 24 +-8 - PST 1951 Ap 29 2 +-8 1 PDT 1951 S 30 2 +-8 - PST 1952 Ap 27 2 +-8 1 PDT 1952 S 28 2 -8 - PST 1954 -8 CA P%sT 1961 -8 - PST 1976 @@ -2961,31 +2985,31 @@ Z America/Yakutat 14:41:5 - LMT 1867 O 19 15:12:18 -9 u Y%sT 1983 N 30 -9 u AK%sT Z Antarctica/Casey 0 - -00 1969 -8 - +08 2009 O 18 2 -11 - +11 2010 Mar 5 2 -8 - +08 2011 O 28 2 -11 - +11 2012 F 21 17u -8 - +08 2016 O 22 -11 - +11 2018 Mar 11 4 -8 - +08 2018 O 7 4 -11 - +11 2019 Mar 17 3 -8 - +08 2019 O 4 3 -11 - +11 2020 Mar 8 3 -8 - +08 2020 O 4 0:1 -11 - +11 2021 Mar 14 -8 - +08 2021 O 3 0:1 -11 - +11 2022 Mar 13 -8 - +08 2022 O 2 0:1 -11 - +11 2023 Mar 9 3 -8 - +08 +8 - %z 2009 O 18 2 +11 - %z 2010 Mar 5 2 +8 - %z 2011 O 28 2 +11 - %z 2012 F 21 17u +8 - %z 2016 O 22 +11 - %z 2018 Mar 11 4 +8 - %z 2018 O 7 4 +11 - %z 2019 Mar 17 3 +8 - %z 2019 O 4 3 +11 - %z 2020 Mar 8 3 +8 - %z 2020 O 4 0:1 +11 - %z 2021 Mar 14 +8 - %z 2021 O 3 0:1 +11 - %z 2022 Mar 13 +8 - %z 2022 O 2 0:1 +11 - %z 2023 Mar 9 3 +8 - %z Z Antarctica/Davis 0 - -00 1957 Ja 13 -7 - +07 1964 N +7 - %z 1964 N 0 - -00 1969 F -7 - +07 2009 O 18 2 -5 - +05 2010 Mar 10 20u -7 - +07 2011 O 28 2 -5 - +05 2012 F 21 20u -7 - +07 +7 - %z 2009 O 18 2 +5 - %z 2010 Mar 10 20u +7 - %z 2011 O 28 2 +5 - %z 2012 F 21 20u +7 - %z Z Antarctica/Macquarie 0 - -00 1899 N 10 - AEST 1916 O 1 2 10 1 AEDT 1917 F @@ -2996,151 +3020,146 @@ Z Antarctica/Macquarie 0 - -00 1899 N 10 1 AEDT 2011 10 AT AE%sT Z Antarctica/Mawson 0 - -00 1954 F 13 -6 - +06 2009 O 18 2 -5 - +05 +6 - %z 2009 O 18 2 +5 - %z Z Antarctica/Palmer 0 - -00 1965 --4 A -04/-03 1969 O 5 --3 A -03/-02 1982 May --4 x -04/-03 2016 D 4 --3 - -03 +-4 A %z 1969 O 5 +-3 A %z 1982 May +-4 x %z 2016 D 4 +-3 - %z Z Antarctica/Rothera 0 - -00 1976 D --3 - -03 +-3 - %z Z Antarctica/Troll 0 - -00 2005 F 12 0 Tr %s Z Antarctica/Vostok 0 - -00 1957 D 16 -7 - +07 1994 F +7 - %z 1994 F 0 - -00 1994 N -7 - +07 2023 D 18 2 -5 - +05 +7 - %z 2023 D 18 2 +5 - %z Z Asia/Almaty 5:7:48 - LMT 1924 May 2 -5 - +05 1930 Jun 21 -6 R +06/+07 1991 Mar 31 2s -5 R +05/+06 1992 Ja 19 2s -6 R +06/+07 2004 O 31 2s -6 - +06 2024 Mar -5 - +05 +5 - %z 1930 Jun 21 +6 R %z 1991 Mar 31 2s +5 R %z 1992 Ja 19 2s +6 R %z 2004 O 31 2s +6 - %z 2024 Mar +5 - %z Z Asia/Amman 2:23:44 - LMT 1931 2 J EE%sT 2022 O 28 0s -3 - +03 +3 - %z Z Asia/Anadyr 11:49:56 - LMT 1924 May 2 -12 - +12 1930 Jun 21 -13 R +13/+14 1982 Ap 1 0s -12 R +12/+13 1991 Mar 31 2s -11 R +11/+12 1992 Ja 19 2s -12 R +12/+13 2010 Mar 28 2s -11 R +11/+12 2011 Mar 27 2s -12 - +12 +12 - %z 1930 Jun 21 +13 R %z 1982 Ap 1 0s +12 R %z 1991 Mar 31 2s +11 R %z 1992 Ja 19 2s +12 R %z 2010 Mar 28 2s +11 R %z 2011 Mar 27 2s +12 - %z Z Asia/Aqtau 3:21:4 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 - +05 1981 O -6 - +06 1982 Ap -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 1994 S 25 2s -4 R +04/+05 2004 O 31 2s -5 - +05 +4 - %z 1930 Jun 21 +5 - %z 1981 O +6 - %z 1982 Ap +5 R %z 1991 Mar 31 2s +4 R %z 1992 Ja 19 2s +5 R %z 1994 S 25 2s +4 R %z 2004 O 31 2s +5 - %z Z Asia/Aqtobe 3:48:40 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 - +05 1981 Ap -5 1 +06 1981 O -6 - +06 1982 Ap -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 2004 O 31 2s -5 - +05 +4 - %z 1930 Jun 21 +5 - %z 1981 Ap +5 1 %z 1981 O +6 - %z 1982 Ap +5 R %z 1991 Mar 31 2s +4 R %z 1992 Ja 19 2s +5 R %z 2004 O 31 2s +5 - %z Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 R +05/+06 1991 Mar 31 2 -4 R +04/+05 1992 Ja 19 2 -5 - +05 +4 - %z 1930 Jun 21 +5 R %z 1991 Mar 31 2 +4 R %z 1992 Ja 19 2 +5 - %z Z Asia/Atyrau 3:27:44 - LMT 1924 May 2 -3 - +03 1930 Jun 21 -5 - +05 1981 O -6 - +06 1982 Ap -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 1999 Mar 28 2s -4 R +04/+05 2004 O 31 2s -5 - +05 +3 - %z 1930 Jun 21 +5 - %z 1981 O +6 - %z 1982 Ap +5 R %z 1991 Mar 31 2s +4 R %z 1992 Ja 19 2s +5 R %z 1999 Mar 28 2s +4 R %z 2004 O 31 2s +5 - %z Z Asia/Baghdad 2:57:40 - LMT 1890 2:57:36 - BMT 1918 -3 - +03 1982 May -3 IQ +03/+04 +3 - %z 1982 May +3 IQ %z Z Asia/Baku 3:19:24 - LMT 1924 May 2 -3 - +03 1957 Mar -4 R +04/+05 1991 Mar 31 2s -3 R +03/+04 1992 S lastSu 2s -4 - +04 1996 -4 E +04/+05 1997 -4 AZ +04/+05 +3 - %z 1957 Mar +4 R %z 1991 Mar 31 2s +3 R %z 1992 S lastSu 2s +4 - %z 1996 +4 E %z 1997 +4 AZ %z Z Asia/Bangkok 6:42:4 - LMT 1880 6:42:4 - BMT 1920 Ap -7 - +07 +7 - %z Z Asia/Barnaul 5:35 - LMT 1919 D 10 -6 - +06 1930 Jun 21 -7 R +07/+08 1991 Mar 31 2s -6 R +06/+07 1992 Ja 19 2s -7 R +07/+08 1995 May 28 -6 R +06/+07 2011 Mar 27 2s -7 - +07 2014 O 26 2s -6 - +06 2016 Mar 27 2s -7 - +07 +6 - %z 1930 Jun 21 +7 R %z 1991 Mar 31 2s +6 R %z 1992 Ja 19 2s +7 R %z 1995 May 28 +6 R %z 2011 Mar 27 2s +7 - %z 2014 O 26 2s +6 - %z 2016 Mar 27 2s +7 - %z Z Asia/Beirut 2:22 - LMT 1880 2 l EE%sT Z Asia/Bishkek 4:58:24 - LMT 1924 May 2 -5 - +05 1930 Jun 21 -6 R +06/+07 1991 Mar 31 2s -5 R +05/+06 1991 Au 31 2 -5 KG +05/+06 2005 Au 12 -6 - +06 +5 - %z 1930 Jun 21 +6 R %z 1991 Mar 31 2s +5 R %z 1991 Au 31 2 +5 KG %z 2005 Au 12 +6 - %z Z Asia/Chita 7:33:52 - LMT 1919 D 15 -8 - +08 1930 Jun 21 -9 R +09/+10 1991 Mar 31 2s -8 R +08/+09 1992 Ja 19 2s -9 R +09/+10 2011 Mar 27 2s -10 - +10 2014 O 26 2s -8 - +08 2016 Mar 27 2 -9 - +09 -Z Asia/Choibalsan 7:38 - LMT 1905 Au -7 - +07 1978 -8 - +08 1983 Ap -9 X +09/+10 2008 Mar 31 -8 X +08/+09 +8 - %z 1930 Jun 21 +9 R %z 1991 Mar 31 2s +8 R %z 1992 Ja 19 2s +9 R %z 2011 Mar 27 2s +10 - %z 2014 O 26 2s +8 - %z 2016 Mar 27 2 +9 - %z Z Asia/Colombo 5:19:24 - LMT 1880 5:19:32 - MMT 1906 -5:30 - +0530 1942 Ja 5 -5:30 0:30 +06 1942 S -5:30 1 +0630 1945 O 16 2 -5:30 - +0530 1996 May 25 -6:30 - +0630 1996 O 26 0:30 -6 - +06 2006 Ap 15 0:30 -5:30 - +0530 +5:30 - %z 1942 Ja 5 +5:30 0:30 %z 1942 S +5:30 1 %z 1945 O 16 2 +5:30 - %z 1996 May 25 +6:30 - %z 1996 O 26 0:30 +6 - %z 2006 Ap 15 0:30 +5:30 - %z Z Asia/Damascus 2:25:12 - LMT 1920 2 S EE%sT 2022 O 28 -3 - +03 +3 - %z Z Asia/Dhaka 6:1:40 - LMT 1890 5:53:20 - HMT 1941 O -6:30 - +0630 1942 May 15 -5:30 - +0530 1942 S -6:30 - +0630 1951 S 30 -6 - +06 2009 -6 BD +06/+07 -Z Asia/Dili 8:22:20 - LMT 1912 -8 - +08 1942 F 21 23 -9 - +09 1976 May 3 -8 - +08 2000 S 17 -9 - +09 +6:30 - %z 1942 May 15 +5:30 - %z 1942 S +6:30 - %z 1951 S 30 +6 - %z 2009 +6 BD %z +Z Asia/Dili 8:22:20 - LMT 1911 D 31 16u +8 - %z 1942 F 21 23 +9 - %z 1976 May 3 +8 - %z 2000 S 17 +9 - %z Z Asia/Dubai 3:41:12 - LMT 1920 -4 - +04 +4 - %z Z Asia/Dushanbe 4:35:12 - LMT 1924 May 2 -5 - +05 1930 Jun 21 -6 R +06/+07 1991 Mar 31 2s -5 1 +06 1991 S 9 2s -5 - +05 +5 - %z 1930 Jun 21 +6 R %z 1991 Mar 31 2s +5 1 %z 1991 S 9 2s +5 - %z Z Asia/Famagusta 2:15:48 - LMT 1921 N 14 2 CY EE%sT 1998 S 2 E EE%sT 2016 S 8 -3 - +03 2017 O 29 1u +3 - %z 2017 O 29 1u 2 E EE%sT Z Asia/Gaza 2:17:52 - LMT 1900 O 2 Z EET/EEST 1948 May 15 @@ -3162,14 +3181,14 @@ Z Asia/Hebron 2:20:23 - LMT 1900 O 2 P EE%sT Z Asia/Ho_Chi_Minh 7:6:30 - LMT 1906 Jul 7:6:30 - PLMT 1911 May -7 - +07 1942 D 31 23 -8 - +08 1945 Mar 14 23 -9 - +09 1945 S 1 24 -7 - +07 1947 Ap -8 - +08 1955 Jul 1 1 -7 - +07 1959 D 31 23 -8 - +08 1975 Jun 13 -7 - +07 +7 - %z 1942 D 31 23 +8 - %z 1945 Mar 14 23 +9 - %z 1945 S 1 24 +7 - %z 1947 Ap +8 - %z 1955 Jul 1 1 +7 - %z 1959 D 31 23 +8 - %z 1975 Jun 13 +7 - %z Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u 8 - HKT 1941 Jun 15 3 8 1 HKST 1941 O 1 4 @@ -3177,145 +3196,145 @@ Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 29 17u 9 - JST 1945 N 18 2 8 HK HK%sT Z Asia/Hovd 6:6:36 - LMT 1905 Au -6 - +06 1978 -7 X +07/+08 +6 - %z 1978 +7 X %z Z Asia/Irkutsk 6:57:5 - LMT 1880 6:57:5 - IMT 1920 Ja 25 -7 - +07 1930 Jun 21 -8 R +08/+09 1991 Mar 31 2s -7 R +07/+08 1992 Ja 19 2s -8 R +08/+09 2011 Mar 27 2s -9 - +09 2014 O 26 2s -8 - +08 +7 - %z 1930 Jun 21 +8 R %z 1991 Mar 31 2s +7 R %z 1992 Ja 19 2s +8 R %z 2011 Mar 27 2s +9 - %z 2014 O 26 2s +8 - %z Z Asia/Jakarta 7:7:12 - LMT 1867 Au 10 7:7:12 - BMT 1923 D 31 16:40u -7:20 - +0720 1932 N -7:30 - +0730 1942 Mar 23 -9 - +09 1945 S 23 -7:30 - +0730 1948 May -8 - +08 1950 May -7:30 - +0730 1964 +7:20 - %z 1932 N +7:30 - %z 1942 Mar 23 +9 - %z 1945 S 23 +7:30 - %z 1948 May +8 - %z 1950 May +7:30 - %z 1964 7 - WIB Z Asia/Jayapura 9:22:48 - LMT 1932 N -9 - +09 1944 S -9:30 - +0930 1964 +9 - %z 1944 S +9:30 - %z 1964 9 - WIT Z Asia/Jerusalem 2:20:54 - LMT 1880 2:20:40 - JMT 1918 2 Z I%sT Z Asia/Kabul 4:36:48 - LMT 1890 -4 - +04 1945 -4:30 - +0430 +4 - %z 1945 +4:30 - %z Z Asia/Kamchatka 10:34:36 - LMT 1922 N 10 -11 - +11 1930 Jun 21 -12 R +12/+13 1991 Mar 31 2s -11 R +11/+12 1992 Ja 19 2s -12 R +12/+13 2010 Mar 28 2s -11 R +11/+12 2011 Mar 27 2s -12 - +12 +11 - %z 1930 Jun 21 +12 R %z 1991 Mar 31 2s +11 R %z 1992 Ja 19 2s +12 R %z 2010 Mar 28 2s +11 R %z 2011 Mar 27 2s +12 - %z Z Asia/Karachi 4:28:12 - LMT 1907 -5:30 - +0530 1942 S -5:30 1 +0630 1945 O 15 -5:30 - +0530 1951 S 30 -5 - +05 1971 Mar 26 +5:30 - %z 1942 S +5:30 1 %z 1945 O 15 +5:30 - %z 1951 S 30 +5 - %z 1971 Mar 26 5 PK PK%sT Z Asia/Kathmandu 5:41:16 - LMT 1920 -5:30 - +0530 1986 -5:45 - +0545 +5:30 - %z 1986 +5:45 - %z Z Asia/Khandyga 9:2:13 - LMT 1919 D 15 -8 - +08 1930 Jun 21 -9 R +09/+10 1991 Mar 31 2s -8 R +08/+09 1992 Ja 19 2s -9 R +09/+10 2004 -10 R +10/+11 2011 Mar 27 2s -11 - +11 2011 S 13 0s -10 - +10 2014 O 26 2s -9 - +09 +8 - %z 1930 Jun 21 +9 R %z 1991 Mar 31 2s +8 R %z 1992 Ja 19 2s +9 R %z 2004 +10 R %z 2011 Mar 27 2s +11 - %z 2011 S 13 0s +10 - %z 2014 O 26 2s +9 - %z Z Asia/Kolkata 5:53:28 - LMT 1854 Jun 28 5:53:20 - HMT 1870 5:21:10 - MMT 1906 5:30 - IST 1941 O -5:30 1 +0630 1942 May 15 +5:30 1 %z 1942 May 15 5:30 - IST 1942 S -5:30 1 +0630 1945 O 15 +5:30 1 %z 1945 O 15 5:30 - IST Z Asia/Krasnoyarsk 6:11:26 - LMT 1920 Ja 6 -6 - +06 1930 Jun 21 -7 R +07/+08 1991 Mar 31 2s -6 R +06/+07 1992 Ja 19 2s -7 R +07/+08 2011 Mar 27 2s -8 - +08 2014 O 26 2s -7 - +07 +6 - %z 1930 Jun 21 +7 R %z 1991 Mar 31 2s +6 R %z 1992 Ja 19 2s +7 R %z 2011 Mar 27 2s +8 - %z 2014 O 26 2s +7 - %z Z Asia/Kuching 7:21:20 - LMT 1926 Mar -7:30 - +0730 1933 -8 NB +08/+0820 1942 F 16 -9 - +09 1945 S 12 -8 - +08 +7:30 - %z 1933 +8 NB %z 1942 F 16 +9 - %z 1945 S 12 +8 - %z Z Asia/Macau 7:34:10 - LMT 1904 O 30 8 - CST 1941 D 21 23 -9 _ +09/+10 1945 S 30 24 +9 _ %z 1945 S 30 24 8 _ C%sT Z Asia/Magadan 10:3:12 - LMT 1924 May 2 -10 - +10 1930 Jun 21 -11 R +11/+12 1991 Mar 31 2s -10 R +10/+11 1992 Ja 19 2s -11 R +11/+12 2011 Mar 27 2s -12 - +12 2014 O 26 2s -10 - +10 2016 Ap 24 2s -11 - +11 +10 - %z 1930 Jun 21 +11 R %z 1991 Mar 31 2s +10 R %z 1992 Ja 19 2s +11 R %z 2011 Mar 27 2s +12 - %z 2014 O 26 2s +10 - %z 2016 Ap 24 2s +11 - %z Z Asia/Makassar 7:57:36 - LMT 1920 7:57:36 - MMT 1932 N -8 - +08 1942 F 9 -9 - +09 1945 S 23 +8 - %z 1942 F 9 +9 - %z 1945 S 23 8 - WITA -Z Asia/Manila -15:56 - LMT 1844 D 31 -8:4 - LMT 1899 May 11 -8 PH P%sT 1942 May -9 - JST 1944 N +Z Asia/Manila -15:56:8 - LMT 1844 D 31 +8:3:52 - LMT 1899 S 6 4u +8 PH P%sT 1942 F 11 24 +9 - JST 1945 Mar 4 8 PH P%sT Z Asia/Nicosia 2:13:28 - LMT 1921 N 14 2 CY EE%sT 1998 S 2 E EE%sT Z Asia/Novokuznetsk 5:48:48 - LMT 1924 May -6 - +06 1930 Jun 21 -7 R +07/+08 1991 Mar 31 2s -6 R +06/+07 1992 Ja 19 2s -7 R +07/+08 2010 Mar 28 2s -6 R +06/+07 2011 Mar 27 2s -7 - +07 +6 - %z 1930 Jun 21 +7 R %z 1991 Mar 31 2s +6 R %z 1992 Ja 19 2s +7 R %z 2010 Mar 28 2s +6 R %z 2011 Mar 27 2s +7 - %z Z Asia/Novosibirsk 5:31:40 - LMT 1919 D 14 6 -6 - +06 1930 Jun 21 -7 R +07/+08 1991 Mar 31 2s -6 R +06/+07 1992 Ja 19 2s -7 R +07/+08 1993 May 23 -6 R +06/+07 2011 Mar 27 2s -7 - +07 2014 O 26 2s -6 - +06 2016 Jul 24 2s -7 - +07 +6 - %z 1930 Jun 21 +7 R %z 1991 Mar 31 2s +6 R %z 1992 Ja 19 2s +7 R %z 1993 May 23 +6 R %z 2011 Mar 27 2s +7 - %z 2014 O 26 2s +6 - %z 2016 Jul 24 2s +7 - %z Z Asia/Omsk 4:53:30 - LMT 1919 N 14 -5 - +05 1930 Jun 21 -6 R +06/+07 1991 Mar 31 2s -5 R +05/+06 1992 Ja 19 2s -6 R +06/+07 2011 Mar 27 2s -7 - +07 2014 O 26 2s -6 - +06 +5 - %z 1930 Jun 21 +6 R %z 1991 Mar 31 2s +5 R %z 1992 Ja 19 2s +6 R %z 2011 Mar 27 2s +7 - %z 2014 O 26 2s +6 - %z Z Asia/Oral 3:25:24 - LMT 1924 May 2 -3 - +03 1930 Jun 21 -5 - +05 1981 Ap -5 1 +06 1981 O -6 - +06 1982 Ap -5 R +05/+06 1989 Mar 26 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 1992 Mar 29 2s -4 R +04/+05 2004 O 31 2s -5 - +05 +3 - %z 1930 Jun 21 +5 - %z 1981 Ap +5 1 %z 1981 O +6 - %z 1982 Ap +5 R %z 1989 Mar 26 2s +4 R %z 1992 Ja 19 2s +5 R %z 1992 Mar 29 2s +4 R %z 2004 O 31 2s +5 - %z Z Asia/Pontianak 7:17:20 - LMT 1908 May 7:17:20 - PMT 1932 N -7:30 - +0730 1942 Ja 29 -9 - +09 1945 S 23 -7:30 - +0730 1948 May -8 - +08 1950 May -7:30 - +0730 1964 +7:30 - %z 1942 Ja 29 +9 - %z 1945 S 23 +7:30 - %z 1948 May +8 - %z 1950 May +7:30 - %z 1964 8 - WITA 1988 7 - WIB Z Asia/Pyongyang 8:23 - LMT 1908 Ap @@ -3325,48 +3344,48 @@ Z Asia/Pyongyang 8:23 - LMT 1908 Ap 8:30 - KST 2018 May 4 23:30 9 - KST Z Asia/Qatar 3:26:8 - LMT 1920 -4 - +04 1972 Jun -3 - +03 +4 - %z 1972 Jun +3 - %z Z Asia/Qostanay 4:14:28 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 - +05 1981 Ap -5 1 +06 1981 O -6 - +06 1982 Ap -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 2004 O 31 2s -6 - +06 2024 Mar -5 - +05 +4 - %z 1930 Jun 21 +5 - %z 1981 Ap +5 1 %z 1981 O +6 - %z 1982 Ap +5 R %z 1991 Mar 31 2s +4 R %z 1992 Ja 19 2s +5 R %z 2004 O 31 2s +6 - %z 2024 Mar +5 - %z Z Asia/Qyzylorda 4:21:52 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 - +05 1981 Ap -5 1 +06 1981 O -6 - +06 1982 Ap -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1991 S 29 2s -5 R +05/+06 1992 Ja 19 2s -6 R +06/+07 1992 Mar 29 2s -5 R +05/+06 2004 O 31 2s -6 - +06 2018 D 21 -5 - +05 +4 - %z 1930 Jun 21 +5 - %z 1981 Ap +5 1 %z 1981 O +6 - %z 1982 Ap +5 R %z 1991 Mar 31 2s +4 R %z 1991 S 29 2s +5 R %z 1992 Ja 19 2s +6 R %z 1992 Mar 29 2s +5 R %z 2004 O 31 2s +6 - %z 2018 D 21 +5 - %z Z Asia/Riyadh 3:6:52 - LMT 1947 Mar 14 -3 - +03 +3 - %z Z Asia/Sakhalin 9:30:48 - LMT 1905 Au 23 -9 - +09 1945 Au 25 -11 R +11/+12 1991 Mar 31 2s -10 R +10/+11 1992 Ja 19 2s -11 R +11/+12 1997 Mar lastSu 2s -10 R +10/+11 2011 Mar 27 2s -11 - +11 2014 O 26 2s -10 - +10 2016 Mar 27 2s -11 - +11 +9 - %z 1945 Au 25 +11 R %z 1991 Mar 31 2s +10 R %z 1992 Ja 19 2s +11 R %z 1997 Mar lastSu 2s +10 R %z 2011 Mar 27 2s +11 - %z 2014 O 26 2s +10 - %z 2016 Mar 27 2s +11 - %z Z Asia/Samarkand 4:27:53 - LMT 1924 May 2 -4 - +04 1930 Jun 21 -5 - +05 1981 Ap -5 1 +06 1981 O -6 - +06 1982 Ap -5 R +05/+06 1992 -5 - +05 +4 - %z 1930 Jun 21 +5 - %z 1981 Ap +5 1 %z 1981 O +6 - %z 1982 Ap +5 R %z 1992 +5 - %z Z Asia/Seoul 8:27:52 - LMT 1908 Ap 8:30 - KST 1912 9 - JST 1945 S 8 @@ -3378,161 +3397,147 @@ Z Asia/Shanghai 8:5:43 - LMT 1901 8 CN C%sT Z Asia/Singapore 6:55:25 - LMT 1901 6:55:25 - SMT 1905 Jun -7 - +07 1933 -7 0:20 +0720 1936 -7:20 - +0720 1941 S -7:30 - +0730 1942 F 16 -9 - +09 1945 S 12 -7:30 - +0730 1981 D 31 16u -8 - +08 +7 - %z 1933 +7 0:20 %z 1936 +7:20 - %z 1941 S +7:30 - %z 1942 F 16 +9 - %z 1945 S 12 +7:30 - %z 1981 D 31 16u +8 - %z Z Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2 -10 - +10 1930 Jun 21 -11 R +11/+12 1991 Mar 31 2s -10 R +10/+11 1992 Ja 19 2s -11 R +11/+12 2011 Mar 27 2s -12 - +12 2014 O 26 2s -11 - +11 +10 - %z 1930 Jun 21 +11 R %z 1991 Mar 31 2s +10 R %z 1992 Ja 19 2s +11 R %z 2011 Mar 27 2s +12 - %z 2014 O 26 2s +11 - %z Z Asia/Taipei 8:6 - LMT 1896 8 - CST 1937 O 9 - JST 1945 S 21 1 8 f C%sT Z Asia/Tashkent 4:37:11 - LMT 1924 May 2 -5 - +05 1930 Jun 21 -6 R +06/+07 1991 Mar 31 2 -5 R +05/+06 1992 -5 - +05 +5 - %z 1930 Jun 21 +6 R %z 1991 Mar 31 2 +5 R %z 1992 +5 - %z Z Asia/Tbilisi 2:59:11 - LMT 1880 2:59:11 - TBMT 1924 May 2 -3 - +03 1957 Mar -4 R +04/+05 1991 Mar 31 2s -3 R +03/+04 1992 -3 e +03/+04 1994 S lastSu -4 e +04/+05 1996 O lastSu -4 1 +05 1997 Mar lastSu -4 e +04/+05 2004 Jun 27 -3 R +03/+04 2005 Mar lastSu 2 -4 - +04 +3 - %z 1957 Mar +4 R %z 1991 Mar 31 2s +3 R %z 1992 +3 e %z 1994 S lastSu +4 e %z 1996 O lastSu +4 1 %z 1997 Mar lastSu +4 e %z 2004 Jun 27 +3 R %z 2005 Mar lastSu 2 +4 - %z Z Asia/Tehran 3:25:44 - LMT 1916 3:25:44 - TMT 1935 Jun 13 -3:30 i +0330/+0430 1977 O 20 24 -4 i +04/+05 1979 -3:30 i +0330/+0430 +3:30 i %z 1977 O 20 24 +4 i %z 1978 N 10 24 +3:30 i %z Z Asia/Thimphu 5:58:36 - LMT 1947 Au 15 -5:30 - +0530 1987 O -6 - +06 +5:30 - %z 1987 O +6 - %z Z Asia/Tokyo 9:18:59 - LMT 1887 D 31 15u 9 JP J%sT Z Asia/Tomsk 5:39:51 - LMT 1919 D 22 -6 - +06 1930 Jun 21 -7 R +07/+08 1991 Mar 31 2s -6 R +06/+07 1992 Ja 19 2s -7 R +07/+08 2002 May 1 3 -6 R +06/+07 2011 Mar 27 2s -7 - +07 2014 O 26 2s -6 - +06 2016 May 29 2s -7 - +07 +6 - %z 1930 Jun 21 +7 R %z 1991 Mar 31 2s +6 R %z 1992 Ja 19 2s +7 R %z 2002 May 1 3 +6 R %z 2011 Mar 27 2s +7 - %z 2014 O 26 2s +6 - %z 2016 May 29 2s +7 - %z Z Asia/Ulaanbaatar 7:7:32 - LMT 1905 Au -7 - +07 1978 -8 X +08/+09 +7 - %z 1978 +8 X %z Z Asia/Urumqi 5:50:20 - LMT 1928 -6 - +06 +6 - %z Z Asia/Ust-Nera 9:32:54 - LMT 1919 D 15 -8 - +08 1930 Jun 21 -9 R +09/+10 1981 Ap -11 R +11/+12 1991 Mar 31 2s -10 R +10/+11 1992 Ja 19 2s -11 R +11/+12 2011 Mar 27 2s -12 - +12 2011 S 13 0s -11 - +11 2014 O 26 2s -10 - +10 +8 - %z 1930 Jun 21 +9 R %z 1981 Ap +11 R %z 1991 Mar 31 2s +10 R %z 1992 Ja 19 2s +11 R %z 2011 Mar 27 2s +12 - %z 2011 S 13 0s +11 - %z 2014 O 26 2s +10 - %z Z Asia/Vladivostok 8:47:31 - LMT 1922 N 15 -9 - +09 1930 Jun 21 -10 R +10/+11 1991 Mar 31 2s -9 R +09/+10 1992 Ja 19 2s -10 R +10/+11 2011 Mar 27 2s -11 - +11 2014 O 26 2s -10 - +10 +9 - %z 1930 Jun 21 +10 R %z 1991 Mar 31 2s +9 R %z 1992 Ja 19 2s +10 R %z 2011 Mar 27 2s +11 - %z 2014 O 26 2s +10 - %z Z Asia/Yakutsk 8:38:58 - LMT 1919 D 15 -8 - +08 1930 Jun 21 -9 R +09/+10 1991 Mar 31 2s -8 R +08/+09 1992 Ja 19 2s -9 R +09/+10 2011 Mar 27 2s -10 - +10 2014 O 26 2s -9 - +09 +8 - %z 1930 Jun 21 +9 R %z 1991 Mar 31 2s +8 R %z 1992 Ja 19 2s +9 R %z 2011 Mar 27 2s +10 - %z 2014 O 26 2s +9 - %z Z Asia/Yangon 6:24:47 - LMT 1880 6:24:47 - RMT 1920 -6:30 - +0630 1942 May -9 - +09 1945 May 3 -6:30 - +0630 +6:30 - %z 1942 May +9 - %z 1945 May 3 +6:30 - %z Z Asia/Yekaterinburg 4:2:33 - LMT 1916 Jul 3 3:45:5 - PMT 1919 Jul 15 4 -4 - +04 1930 Jun 21 -5 R +05/+06 1991 Mar 31 2s -4 R +04/+05 1992 Ja 19 2s -5 R +05/+06 2011 Mar 27 2s -6 - +06 2014 O 26 2s -5 - +05 +4 - %z 1930 Jun 21 +5 R %z 1991 Mar 31 2s +4 R %z 1992 Ja 19 2s +5 R %z 2011 Mar 27 2s +6 - %z 2014 O 26 2s +5 - %z Z Asia/Yerevan 2:58 - LMT 1924 May 2 -3 - +03 1957 Mar -4 R +04/+05 1991 Mar 31 2s -3 R +03/+04 1995 S 24 2s -4 - +04 1997 -4 R +04/+05 2011 -4 AM +04/+05 +3 - %z 1957 Mar +4 R %z 1991 Mar 31 2s +3 R %z 1995 S 24 2s +4 - %z 1997 +4 R %z 2011 +4 AM %z Z Atlantic/Azores -1:42:40 - LMT 1884 -1:54:32 - HMT 1912 Ja 1 2u --2 p -02/-01 1942 Ap 25 22s --2 p +00 1942 Au 15 22s --2 p -02/-01 1943 Ap 17 22s --2 p +00 1943 Au 28 22s --2 p -02/-01 1944 Ap 22 22s --2 p +00 1944 Au 26 22s --2 p -02/-01 1945 Ap 21 22s --2 p +00 1945 Au 25 22s --2 p -02/-01 1966 Ap 3 2 --1 p -01/+00 1983 S 25 1s --1 W- -01/+00 1992 S 27 1s -0 E WE%sT 1993 Mar 28 1u --1 E -01/+00 +-2 p %z 1966 O 2 2s +-1 - %z 1982 Mar 28 0s +-1 p %z 1986 +-1 E %z 1992 D 27 1s +0 E WE%sT 1993 Jun 17 1u +-1 E %z Z Atlantic/Bermuda -4:19:18 - LMT 1890 -4:19:18 Be BMT/BST 1930 Ja 1 2 -4 Be A%sT 1974 Ap 28 2 -4 C A%sT 1976 -4 u A%sT Z Atlantic/Canary -1:1:36 - LMT 1922 Mar --1 - -01 1946 S 30 1 +-1 - %z 1946 S 30 1 0 - WET 1980 Ap 6 0s 0 1 WEST 1980 S 28 1u 0 E WE%sT Z Atlantic/Cape_Verde -1:34:4 - LMT 1912 Ja 1 2u --2 - -02 1942 S --2 1 -01 1945 O 15 --2 - -02 1975 N 25 2 --1 - -01 +-2 - %z 1942 S +-2 1 %z 1945 O 15 +-2 - %z 1975 N 25 2 +-1 - %z Z Atlantic/Faroe -0:27:4 - LMT 1908 Ja 11 0 - WET 1981 0 E WE%sT Z Atlantic/Madeira -1:7:36 - LMT 1884 -1:7:36 - FMT 1912 Ja 1 1u --1 p -01/+00 1942 Ap 25 22s --1 p +01 1942 Au 15 22s --1 p -01/+00 1943 Ap 17 22s --1 p +01 1943 Au 28 22s --1 p -01/+00 1944 Ap 22 22s --1 p +01 1944 Au 26 22s --1 p -01/+00 1945 Ap 21 22s --1 p +01 1945 Au 25 22s --1 p -01/+00 1966 Ap 3 2 -0 p WE%sT 1983 S 25 1s +-1 p %z 1966 O 2 2s +0 - WET 1982 Ap 4 +0 p WE%sT 1986 Jul 31 0 E WE%sT Z Atlantic/South_Georgia -2:26:8 - LMT 1890 --2 - -02 +-2 - %z Z Atlantic/Stanley -3:51:24 - LMT 1890 -3:51:24 - SMT 1912 Mar 12 --4 FK -04/-03 1983 May --3 FK -03/-02 1985 S 15 --4 FK -04/-03 2010 S 5 2 --3 - -03 +-4 FK %z 1983 May +-3 FK %z 1985 S 15 +-4 FK %z 2010 S 5 2 +-3 - %z Z Australia/Adelaide 9:14:20 - LMT 1895 F 9 - ACST 1899 May 9:30 AU AC%sT 1971 @@ -3550,8 +3555,8 @@ Z Australia/Darwin 8:43:20 - LMT 1895 F 9 - ACST 1899 May 9:30 AU AC%sT Z Australia/Eucla 8:35:28 - LMT 1895 D -8:45 AU +0845/+0945 1943 Jul -8:45 AW +0845/+0945 +8:45 AU %z 1943 Jul +8:45 AW %z Z Australia/Hobart 9:49:16 - LMT 1895 S 10 AT AE%sT 1919 O 24 10 AU AE%sT 1967 @@ -3562,8 +3567,8 @@ Z Australia/Lindeman 9:55:56 - LMT 1895 10 Ho AE%sT Z Australia/Lord_Howe 10:36:20 - LMT 1895 F 10 - AEST 1981 Mar -10:30 LH +1030/+1130 1985 Jul -10:30 LH +1030/+11 +10:30 LH %z 1985 Jul +10:30 LH %z Z Australia/Melbourne 9:39:52 - LMT 1895 F 10 AU AE%sT 1971 10 AV AE%sT @@ -3573,52 +3578,47 @@ Z Australia/Perth 7:43:24 - LMT 1895 D Z Australia/Sydney 10:4:52 - LMT 1895 F 10 AU AE%sT 1971 10 AN AE%sT -Z CET 1 c CE%sT -Z CST6CDT -6 u C%sT -Z EET 2 E EE%sT -Z EST -5 - EST -Z EST5EDT -5 u E%sT Z Etc/GMT 0 - GMT -Z Etc/GMT+1 -1 - -01 -Z Etc/GMT+10 -10 - -10 -Z Etc/GMT+11 -11 - -11 -Z Etc/GMT+12 -12 - -12 -Z Etc/GMT+2 -2 - -02 -Z Etc/GMT+3 -3 - -03 -Z Etc/GMT+4 -4 - -04 -Z Etc/GMT+5 -5 - -05 -Z Etc/GMT+6 -6 - -06 -Z Etc/GMT+7 -7 - -07 -Z Etc/GMT+8 -8 - -08 -Z Etc/GMT+9 -9 - -09 -Z Etc/GMT-1 1 - +01 -Z Etc/GMT-10 10 - +10 -Z Etc/GMT-11 11 - +11 -Z Etc/GMT-12 12 - +12 -Z Etc/GMT-13 13 - +13 -Z Etc/GMT-14 14 - +14 -Z Etc/GMT-2 2 - +02 -Z Etc/GMT-3 3 - +03 -Z Etc/GMT-4 4 - +04 -Z Etc/GMT-5 5 - +05 -Z Etc/GMT-6 6 - +06 -Z Etc/GMT-7 7 - +07 -Z Etc/GMT-8 8 - +08 -Z Etc/GMT-9 9 - +09 +Z Etc/GMT+1 -1 - %z +Z Etc/GMT+10 -10 - %z +Z Etc/GMT+11 -11 - %z +Z Etc/GMT+12 -12 - %z +Z Etc/GMT+2 -2 - %z +Z Etc/GMT+3 -3 - %z +Z Etc/GMT+4 -4 - %z +Z Etc/GMT+5 -5 - %z +Z Etc/GMT+6 -6 - %z +Z Etc/GMT+7 -7 - %z +Z Etc/GMT+8 -8 - %z +Z Etc/GMT+9 -9 - %z +Z Etc/GMT-1 1 - %z +Z Etc/GMT-10 10 - %z +Z Etc/GMT-11 11 - %z +Z Etc/GMT-12 12 - %z +Z Etc/GMT-13 13 - %z +Z Etc/GMT-14 14 - %z +Z Etc/GMT-2 2 - %z +Z Etc/GMT-3 3 - %z +Z Etc/GMT-4 4 - %z +Z Etc/GMT-5 5 - %z +Z Etc/GMT-6 6 - %z +Z Etc/GMT-7 7 - %z +Z Etc/GMT-8 8 - %z +Z Etc/GMT-9 9 - %z Z Etc/UTC 0 - UTC Z Europe/Andorra 0:6:4 - LMT 1901 0 - WET 1946 S 30 1 - CET 1985 Mar 31 2 1 E CE%sT Z Europe/Astrakhan 3:12:12 - LMT 1924 May -3 - +03 1930 Jun 21 -4 R +04/+05 1989 Mar 26 2s -3 R +03/+04 1991 Mar 31 2s -4 - +04 1992 Mar 29 2s -3 R +03/+04 2011 Mar 27 2s -4 - +04 2014 O 26 2s -3 - +03 2016 Mar 27 2s -4 - +04 +3 - %z 1930 Jun 21 +4 R %z 1989 Mar 26 2s +3 R %z 1991 Mar 31 2s +4 - %z 1992 Mar 29 2s +3 R %z 2011 Mar 27 2s +4 - %z 2014 O 26 2s +3 - %z 2016 Mar 27 2s +4 - %z Z Europe/Athens 1:34:52 - LMT 1895 S 14 1:34:52 - AMT 1916 Jul 28 0:1 2 g EE%sT 1941 Ap 30 @@ -3691,7 +3691,7 @@ Z Europe/Helsinki 1:39:49 - LMT 1878 May 31 Z Europe/Istanbul 1:55:52 - LMT 1880 1:56:56 - IMT 1910 O 2 T EE%sT 1978 Jun 29 -3 T +03/+04 1984 N 1 2 +3 T %z 1984 N 1 2 2 T EE%sT 2007 2 E EE%sT 2011 Mar 27 1u 2 - EET 2011 Mar 28 1u @@ -3700,19 +3700,19 @@ Z Europe/Istanbul 1:55:52 - LMT 1880 2 E EE%sT 2015 O 25 1u 2 1 EEST 2015 N 8 1u 2 E EE%sT 2016 S 7 -3 - +03 +3 - %z Z Europe/Kaliningrad 1:22 - LMT 1893 Ap 1 c CE%sT 1945 Ap 10 2 O EE%sT 1946 Ap 7 3 R MSK/MSD 1989 Mar 26 2s 2 R EE%sT 2011 Mar 27 2s -3 - +03 2014 O 26 2s +3 - %z 2014 O 26 2s 2 - EET Z Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0u -3 - +03 1930 Jun 21 -4 R +04/+05 1989 Mar 26 2s +3 - %z 1930 Jun 21 +4 R %z 1989 Mar 26 2s 3 R MSK/MSD 1991 Mar 31 2s -4 - +04 1992 Mar 29 2s +4 - %z 1992 Mar 29 2s 3 R MSK/MSD 2011 Mar 27 2s 4 - MSK 2014 O 26 2s 3 - MSK @@ -3727,10 +3727,10 @@ Z Europe/Kyiv 2:2:4 - LMT 1880 2 E EE%sT Z Europe/Lisbon -0:36:45 - LMT 1884 -0:36:45 - LMT 1912 Ja 1 0u -0 p WE%sT 1966 Ap 3 2 +0 p WE%sT 1966 O 2 2s 1 - CET 1976 S 26 1 -0 p WE%sT 1983 S 25 1s -0 W- WE%sT 1992 S 27 1s +0 p WE%sT 1986 +0 E WE%sT 1992 S 27 1u 1 E CE%sT 1996 Mar 31 1u 0 E WE%sT Z Europe/London -0:1:15 - LMT 1847 D @@ -3754,7 +3754,7 @@ Z Europe/Minsk 1:50:16 - LMT 1880 3 R MSK/MSD 1990 3 - MSK 1991 Mar 31 2s 2 R EE%sT 2011 Mar 27 2s -3 - +03 +3 - %z Z Europe/Moscow 2:30:17 - LMT 1880 2:30:17 - MMT 1916 Jul 3 2:31:19 R %s 1919 Jul 1 0u @@ -3802,24 +3802,24 @@ Z Europe/Rome 0:49:56 - LMT 1866 D 12 1 I CE%sT 1980 1 E CE%sT Z Europe/Samara 3:20:20 - LMT 1919 Jul 1 0u -3 - +03 1930 Jun 21 -4 - +04 1935 Ja 27 -4 R +04/+05 1989 Mar 26 2s -3 R +03/+04 1991 Mar 31 2s -2 R +02/+03 1991 S 29 2s -3 - +03 1991 O 20 3 -4 R +04/+05 2010 Mar 28 2s -3 R +03/+04 2011 Mar 27 2s -4 - +04 +3 - %z 1930 Jun 21 +4 - %z 1935 Ja 27 +4 R %z 1989 Mar 26 2s +3 R %z 1991 Mar 31 2s +2 R %z 1991 S 29 2s +3 - %z 1991 O 20 3 +4 R %z 2010 Mar 28 2s +3 R %z 2011 Mar 27 2s +4 - %z Z Europe/Saratov 3:4:18 - LMT 1919 Jul 1 0u -3 - +03 1930 Jun 21 -4 R +04/+05 1988 Mar 27 2s -3 R +03/+04 1991 Mar 31 2s -4 - +04 1992 Mar 29 2s -3 R +03/+04 2011 Mar 27 2s -4 - +04 2014 O 26 2s -3 - +03 2016 D 4 2s -4 - +04 +3 - %z 1930 Jun 21 +4 R %z 1988 Mar 27 2s +3 R %z 1991 Mar 31 2s +4 - %z 1992 Mar 29 2s +3 R %z 2011 Mar 27 2s +4 - %z 2014 O 26 2s +3 - %z 2016 D 4 2s +4 - %z Z Europe/Simferopol 2:16:24 - LMT 1880 2:16 - SMT 1924 May 2 2 - EET 1930 Jun 21 @@ -3863,14 +3863,14 @@ Z Europe/Tirane 1:19:20 - LMT 1914 1 q CE%sT 1984 Jul 1 E CE%sT Z Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0u -3 - +03 1930 Jun 21 -4 R +04/+05 1989 Mar 26 2s -3 R +03/+04 1991 Mar 31 2s -2 R +02/+03 1992 Ja 19 2s -3 R +03/+04 2011 Mar 27 2s -4 - +04 2014 O 26 2s -3 - +03 2016 Mar 27 2s -4 - +04 +3 - %z 1930 Jun 21 +4 R %z 1989 Mar 26 2s +3 R %z 1991 Mar 31 2s +2 R %z 1992 Ja 19 2s +3 R %z 2011 Mar 27 2s +4 - %z 2014 O 26 2s +3 - %z 2016 Mar 27 2s +4 - %z Z Europe/Vienna 1:5:21 - LMT 1893 Ap 1 c CE%sT 1920 1 a CE%sT 1940 Ap 1 2s @@ -3895,15 +3895,15 @@ Z Europe/Vilnius 1:41:16 - LMT 1880 2 - EET 2003 2 E EE%sT Z Europe/Volgograd 2:57:40 - LMT 1920 Ja 3 -3 - +03 1930 Jun 21 -4 - +04 1961 N 11 -4 R +04/+05 1988 Mar 27 2s +3 - %z 1930 Jun 21 +4 - %z 1961 N 11 +4 R %z 1988 Mar 27 2s 3 R MSK/MSD 1991 Mar 31 2s -4 - +04 1992 Mar 29 2s +4 - %z 1992 Mar 29 2s 3 R MSK/MSD 2011 Mar 27 2s 4 - MSK 2014 O 26 2s 3 - MSK 2018 O 28 2s -4 - +04 2020 D 27 2s +4 - %z 2020 D 27 2s 3 - MSK Z Europe/Warsaw 1:24 - LMT 1880 1:24 - WMT 1915 Au 5 @@ -3919,58 +3919,53 @@ Z Europe/Zurich 0:34:8 - LMT 1853 Jul 16 1 CH CE%sT 1981 1 E CE%sT Z Factory 0 - -00 -Z HST -10 - HST Z Indian/Chagos 4:49:40 - LMT 1907 -5 - +05 1996 -6 - +06 +5 - %z 1996 +6 - %z Z Indian/Maldives 4:54 - LMT 1880 4:54 - MMT 1960 -5 - +05 +5 - %z Z Indian/Mauritius 3:50 - LMT 1907 -4 MU +04/+05 -Z MET 1 c ME%sT -Z MST -7 - MST -Z MST7MDT -7 u M%sT -Z PST8PDT -8 u P%sT +4 MU %z Z Pacific/Apia 12:33:4 - LMT 1892 Jul 5 -11:26:56 - LMT 1911 --11:30 - -1130 1950 --11 WS -11/-10 2011 D 29 24 -13 WS +13/+14 +-11:30 - %z 1950 +-11 WS %z 2011 D 29 24 +13 WS %z Z Pacific/Auckland 11:39:4 - LMT 1868 N 2 11:30 NZ NZ%sT 1946 12 NZ NZ%sT Z Pacific/Bougainville 10:22:16 - LMT 1880 9:48:32 - PMMT 1895 -10 - +10 1942 Jul -9 - +09 1945 Au 21 -10 - +10 2014 D 28 2 -11 - +11 +10 - %z 1942 Jul +9 - %z 1945 Au 21 +10 - %z 2014 D 28 2 +11 - %z Z Pacific/Chatham 12:13:48 - LMT 1868 N 2 -12:15 - +1215 1946 -12:45 k +1245/+1345 +12:15 - %z 1946 +12:45 k %z Z Pacific/Easter -7:17:28 - LMT 1890 -7:17:28 - EMT 1932 S --7 x -07/-06 1982 Mar 14 3u --6 x -06/-05 +-7 x %z 1982 Mar 14 3u +-6 x %z Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13 -11 VU +11/+12 +11 VU %z Z Pacific/Fakaofo -11:24:56 - LMT 1901 --11 - -11 2011 D 30 -13 - +13 +-11 - %z 2011 D 30 +13 - %z Z Pacific/Fiji 11:55:44 - LMT 1915 O 26 -12 FJ +12/+13 +12 FJ %z Z Pacific/Galapagos -5:58:24 - LMT 1931 --5 - -05 1986 --6 EC -06/-05 +-5 - %z 1986 +-6 EC %z Z Pacific/Gambier -8:59:48 - LMT 1912 O --9 - -09 +-9 - %z Z Pacific/Guadalcanal 10:39:48 - LMT 1912 O -11 - +11 +11 - %z Z Pacific/Guam -14:21 - LMT 1844 D 31 9:39 - LMT 1901 10 - GST 1941 D 10 -9 - +09 1944 Jul 31 +9 - %z 1944 Jul 31 10 Gu G%sT 2000 D 23 10 - ChST Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12 @@ -3979,74 +3974,73 @@ Z Pacific/Honolulu -10:31:26 - LMT 1896 Ja 13 12 -10:30 u H%sT 1947 Jun 8 2 -10 - HST Z Pacific/Kanton 0 - -00 1937 Au 31 --12 - -12 1979 O --11 - -11 1994 D 31 -13 - +13 +-12 - %z 1979 O +-11 - %z 1994 D 31 +13 - %z Z Pacific/Kiritimati -10:29:20 - LMT 1901 --10:40 - -1040 1979 O --10 - -10 1994 D 31 -14 - +14 +-10:40 - %z 1979 O +-10 - %z 1994 D 31 +14 - %z Z Pacific/Kosrae -13:8:4 - LMT 1844 D 31 10:51:56 - LMT 1901 -11 - +11 1914 O -9 - +09 1919 F -11 - +11 1937 -10 - +10 1941 Ap -9 - +09 1945 Au -11 - +11 1969 O -12 - +12 1999 -11 - +11 +11 - %z 1914 O +9 - %z 1919 F +11 - %z 1937 +10 - %z 1941 Ap +9 - %z 1945 Au +11 - %z 1969 O +12 - %z 1999 +11 - %z Z Pacific/Kwajalein 11:9:20 - LMT 1901 -11 - +11 1937 -10 - +10 1941 Ap -9 - +09 1944 F 6 -11 - +11 1969 O --12 - -12 1993 Au 20 24 -12 - +12 +11 - %z 1937 +10 - %z 1941 Ap +9 - %z 1944 F 6 +11 - %z 1969 O +-12 - %z 1993 Au 20 24 +12 - %z Z Pacific/Marquesas -9:18 - LMT 1912 O --9:30 - -0930 +-9:30 - %z Z Pacific/Nauru 11:7:40 - LMT 1921 Ja 15 -11:30 - +1130 1942 Au 29 -9 - +09 1945 S 8 -11:30 - +1130 1979 F 10 2 -12 - +12 +11:30 - %z 1942 Au 29 +9 - %z 1945 S 8 +11:30 - %z 1979 F 10 2 +12 - %z Z Pacific/Niue -11:19:40 - LMT 1952 O 16 --11:20 - -1120 1964 Jul --11 - -11 +-11:20 - %z 1964 Jul +-11 - %z Z Pacific/Norfolk 11:11:52 - LMT 1901 -11:12 - +1112 1951 -11:30 - +1130 1974 O 27 2s -11:30 1 +1230 1975 Mar 2 2s -11:30 - +1130 2015 O 4 2s -11 - +11 2019 Jul -11 AN +11/+12 +11:12 - %z 1951 +11:30 - %z 1974 O 27 2s +11:30 1 %z 1975 Mar 2 2s +11:30 - %z 2015 O 4 2s +11 - %z 2019 Jul +11 AN %z Z Pacific/Noumea 11:5:48 - LMT 1912 Ja 13 -11 NC +11/+12 +11 NC %z Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5 -11:22:48 - LMT 1911 -11 - SST Z Pacific/Palau -15:2:4 - LMT 1844 D 31 8:57:56 - LMT 1901 -9 - +09 +9 - %z Z Pacific/Pitcairn -8:40:20 - LMT 1901 --8:30 - -0830 1998 Ap 27 --8 - -08 +-8:30 - %z 1998 Ap 27 +-8 - %z Z Pacific/Port_Moresby 9:48:40 - LMT 1880 9:48:32 - PMMT 1895 -10 - +10 +10 - %z Z Pacific/Rarotonga 13:20:56 - LMT 1899 D 26 -10:39:4 - LMT 1952 O 16 --10:30 - -1030 1978 N 12 --10 CK -10/-0930 +-10:30 - %z 1978 N 12 +-10 CK %z Z Pacific/Tahiti -9:58:16 - LMT 1912 O --10 - -10 +-10 - %z Z Pacific/Tarawa 11:32:4 - LMT 1901 -12 - +12 +12 - %z Z Pacific/Tongatapu 12:19:12 - LMT 1945 S 10 -12:20 - +1220 1961 -13 - +13 1999 -13 TO +13/+14 -Z WET 0 E WE%sT +12:20 - %z 1961 +13 - %z 1999 +13 TO %z L Etc/GMT GMT L Australia/Sydney Australia/ACT L Australia/Lord_Howe Australia/LHI @@ -4062,6 +4056,8 @@ L America/Rio_Branco Brazil/Acre L America/Noronha Brazil/DeNoronha L America/Sao_Paulo Brazil/East L America/Manaus Brazil/West +L Europe/Brussels CET +L America/Chicago CST6CDT L America/Halifax Canada/Atlantic L America/Winnipeg Canada/Central L America/Toronto Canada/Eastern @@ -4073,6 +4069,9 @@ L America/Whitehorse Canada/Yukon L America/Santiago Chile/Continental L Pacific/Easter Chile/EasterIsland L America/Havana Cuba +L Europe/Athens EET +L America/Panama EST +L America/New_York EST5EDT L Africa/Cairo Egypt L Europe/Dublin Eire L Etc/GMT Etc/GMT+0 @@ -4096,6 +4095,9 @@ L America/Jamaica Jamaica L Asia/Tokyo Japan L Pacific/Kwajalein Kwajalein L Africa/Tripoli Libya +L Europe/Brussels MET +L America/Phoenix MST +L America/Denver MST7MDT L America/Tijuana Mexico/BajaNorte L America/Mazatlan Mexico/BajaSur L America/Mexico_City Mexico/General @@ -4259,6 +4261,7 @@ L America/Denver America/Shiprock L America/Toronto America/Thunder_Bay L America/Edmonton America/Yellowknife L Pacific/Auckland Antarctica/South_Pole +L Asia/Ulaanbaatar Asia/Choibalsan L Asia/Shanghai Asia/Chongqing L Asia/Shanghai Asia/Harbin L Asia/Urumqi Asia/Kashgar @@ -4273,6 +4276,7 @@ L Europe/Kyiv Europe/Zaporozhye L Pacific/Kanton Pacific/Enderbury L Pacific/Honolulu Pacific/Johnston L Pacific/Port_Moresby Pacific/Yap +L Europe/Lisbon WET L Africa/Nairobi Africa/Asmera L America/Nuuk America/Godthab L Asia/Ashgabat Asia/Ashkhabad @@ -4290,5 +4294,7 @@ L Asia/Ulaanbaatar Asia/Ulan_Bator L Atlantic/Faroe Atlantic/Faeroe L Europe/Kyiv Europe/Kiev L Asia/Nicosia Europe/Nicosia +L Pacific/Honolulu HST +L America/Los_Angeles PST8PDT L Pacific/Guadalcanal Pacific/Ponape L Pacific/Port_Moresby Pacific/Truk diff --git a/src/timezone/known_abbrevs.txt b/src/timezone/known_abbrevs.txt index d03fe0af1316a..efdf9092b160a 100644 --- a/src/timezone/known_abbrevs.txt +++ b/src/timezone/known_abbrevs.txt @@ -80,8 +80,6 @@ IST 7200 JST 32400 KST 32400 MDT -21600 D -MEST 7200 D -MET 3600 MSK 10800 MST -25200 NDT -9000 D diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index 0bc160ea7d79f..8eb02ef14691c 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -1624,15 +1624,8 @@ pg_next_dst_boundary(const pg_time_t *timep, sp = &tz->state; if (sp->timecnt == 0) { - /* non-DST zone, use lowest-numbered standard type */ - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) - { - i = 0; - break; - } - ttisp = &sp->ttis[i]; + /* non-DST zone, use the defaulttype */ + ttisp = &sp->ttis[sp->defaulttype]; *before_gmtoff = ttisp->tt_utoff; *before_isdst = ttisp->tt_isdst; return 0; @@ -1692,15 +1685,8 @@ pg_next_dst_boundary(const pg_time_t *timep, } if (t < sp->ats[0]) { - /* For "before", use lowest-numbered standard type */ - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) - { - i = 0; - break; - } - ttisp = &sp->ttis[i]; + /* For "before", use the defaulttype */ + ttisp = &sp->ttis[sp->defaulttype]; *before_gmtoff = ttisp->tt_utoff; *before_isdst = ttisp->tt_isdst; *boundary = sp->ats[0]; @@ -1793,7 +1779,9 @@ pg_interpret_timezone_abbrev(const char *abbrev, * abbreviation should get us what we want, since extrapolation would just * be repeating the newest or oldest meanings. * - * Use binary search to locate the first transition > cutoff time. + * Use binary search to locate the first transition > cutoff time. (Note + * that sp->timecnt could be zero, in which case this loop does nothing + * and only the defaulttype entry will be checked.) */ { int lo = 0; @@ -1827,7 +1815,19 @@ pg_interpret_timezone_abbrev(const char *abbrev, } /* - * Not there, so scan forwards to find the first one after. + * Not found yet; check the defaulttype, which is notionally the era + * before any of the entries in sp->types[]. + */ + ttisp = &sp->ttis[sp->defaulttype]; + if (ttisp->tt_desigidx == abbrind) + { + *gmtoff = ttisp->tt_utoff; + *isdst = ttisp->tt_isdst; + return true; + } + + /* + * Not there, so scan forwards to find the first one after the cutoff. */ for (i = cutoff; i < sp->timecnt; i++) { @@ -1843,6 +1843,120 @@ pg_interpret_timezone_abbrev(const char *abbrev, return false; /* hm, not actually used in any interval? */ } +/* + * Detect whether a timezone abbreviation is defined within the given zone. + * + * This is similar to pg_interpret_timezone_abbrev() but is not concerned + * with a specific point in time. We want to know if the abbreviation is + * known at all, and if so whether it has one meaning or several. + * + * Returns true if the abbreviation is known, false if not. + * If the abbreviation is known and has a single meaning (only one value + * of gmtoff/isdst), sets *isfixed = true and sets *gmtoff and *isdst. + * If there are multiple meanings, sets *isfixed = false. + * + * Note: abbrev is matched case-sensitively; it should be all-upper-case. + */ +bool +pg_timezone_abbrev_is_known(const char *abbrev, + bool *isfixed, + long int *gmtoff, + int *isdst, + const pg_tz *tz) +{ + bool result = false; + const struct state *sp = &tz->state; + const char *abbrs; + int abbrind; + + /* + * Locate the abbreviation in the zone's abbreviation list. We assume + * there are not duplicates in the list. + */ + abbrs = sp->chars; + abbrind = 0; + while (abbrind < sp->charcnt) + { + if (strcmp(abbrev, abbrs + abbrind) == 0) + break; + while (abbrs[abbrind] != '\0') + abbrind++; + abbrind++; + } + if (abbrind >= sp->charcnt) + return false; /* definitely not there */ + + /* + * Scan the ttinfo array to find uses of the abbreviation. + */ + for (int i = 0; i < sp->typecnt; i++) + { + const struct ttinfo *ttisp = &sp->ttis[i]; + + if (ttisp->tt_desigidx == abbrind) + { + if (!result) + { + /* First usage */ + *isfixed = true; /* for the moment */ + *gmtoff = ttisp->tt_utoff; + *isdst = ttisp->tt_isdst; + result = true; + } + else + { + /* Second or later usage, does it match? */ + if (*gmtoff != ttisp->tt_utoff || + *isdst != ttisp->tt_isdst) + { + *isfixed = false; + break; /* no point in looking further */ + } + } + } + } + + return result; +} + +/* + * Iteratively fetch all the abbreviations used in the given time zone. + * + * *indx is a state counter that the caller must initialize to zero + * before the first call, and not touch between calls. + * + * Returns the next known abbreviation, or NULL if there are no more. + * + * Note: the caller typically applies pg_interpret_timezone_abbrev() + * to each result. While that nominally results in O(N^2) time spent + * searching the sp->chars[] array, we don't expect any zone to have + * enough abbreviations to make that meaningful. + */ +const char * +pg_get_next_timezone_abbrev(int *indx, + const pg_tz *tz) +{ + const char *result; + const struct state *sp = &tz->state; + const char *abbrs; + int abbrind; + + /* If we're still in range, the result is the current abbrev. */ + abbrs = sp->chars; + abbrind = *indx; + if (abbrind < 0 || abbrind >= sp->charcnt) + return NULL; + result = abbrs + abbrind; + + /* Advance *indx past this abbrev and its trailing null. */ + while (abbrs[abbrind] != '\0') + abbrind++; + abbrind++; + *indx = abbrind; + + return result; +} + /* * If the given timezone uses only one GMT offset, store that offset * into *gmtoff and return true, else return false. diff --git a/src/timezone/meson.build b/src/timezone/meson.build index 391150ba885df..ad9f6f6b8addb 100644 --- a/src/timezone/meson.build +++ b/src/timezone/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group # files to build into backend timezone_sources = files( diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index ce36023fb4166..671b4d76237d5 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -3,7 +3,7 @@ * pgtz.c * Timezone Library Integration Functions * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/timezone/pgtz.c diff --git a/src/timezone/pgtz.h b/src/timezone/pgtz.h index 8be88fad7d4bd..8caac631cab82 100644 --- a/src/timezone/pgtz.h +++ b/src/timezone/pgtz.h @@ -6,7 +6,7 @@ * Note: this file contains only definitions that are private to the * timezone library. Public definitions are in pgtime.h. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * IDENTIFICATION * src/timezone/pgtz.h diff --git a/src/timezone/tznames/Default b/src/timezone/tznames/Default index 563a125353b07..5e692423b5a60 100644 --- a/src/timezone/tznames/Default +++ b/src/timezone/tznames/Default @@ -551,12 +551,10 @@ EETDST 10800 D # East-Egypt Summertime FET 10800 # Further-eastern European Time (obsolete) # (Europe/Kaliningrad) # (Europe/Minsk) -MEST 7200 D # Middle Europe Summer Time - # (MET) +MEST 7200 D # Middle Europe Summer Time (obsolete) MESZ 7200 D # Mitteleuropaeische Sommerzeit (German) # (attested in IANA comments though not their code) -MET 3600 # Middle Europe Time - # (MET) +MET 3600 # Middle Europe Time (obsolete) METDST 7200 D # Middle Europe Summer Time (not in IANA database) MEZ 3600 # Mitteleuropaeische Zeit (German) # (attested in IANA comments though not their code) diff --git a/src/timezone/tznames/Europe.txt b/src/timezone/tznames/Europe.txt index 2e762b90700f6..7a7a8340456c4 100644 --- a/src/timezone/tznames/Europe.txt +++ b/src/timezone/tznames/Europe.txt @@ -183,12 +183,10 @@ GMT 0 # Greenwich Mean Time # - IST: Israel Standard Time (Asia) IST 3600 # Irish Standard Time # (Europe/Dublin) -MEST 7200 D # Middle Europe Summer Time - # (MET) +MEST 7200 D # Middle Europe Summer Time (obsolete) MESZ 7200 D # Mitteleuropaeische Sommerzeit (German) # (attested in IANA comments though not their code) -MET 3600 # Middle Europe Time - # (MET) +MET 3600 # Middle Europe Time (obsolete) METDST 7200 D # Middle Europe Summer Time (not in IANA database) MEZ 3600 # Mitteleuropaeische Zeit (German) # (attested in IANA comments though not their code) diff --git a/src/timezone/tznames/meson.build b/src/timezone/tznames/meson.build index f4fb1316bca92..10a26b397ab0b 100644 --- a/src/timezone/tznames/meson.build +++ b/src/timezone/tznames/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group tznames = files( 'Africa.txt', diff --git a/src/timezone/zic.c b/src/timezone/zic.c index d605c721ecf70..3b70b8881805f 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -117,11 +117,11 @@ extern int link(const char *target, const char *linkname); (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname)) #endif -static void memory_exhausted(const char *msg) pg_attribute_noreturn(); +pg_noreturn static void memory_exhausted(const char *msg); static void verror(const char *string, va_list args) pg_attribute_printf(1, 0); static void error(const char *string,...) pg_attribute_printf(1, 2); static void warning(const char *string,...) pg_attribute_printf(1, 2); -static void usage(FILE *stream, int status) pg_attribute_noreturn(); +pg_noreturn static void usage(FILE *stream, int status); static void addtt(zic_t starttime, int type); static int addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut); diff --git a/src/tools/PerfectHash.pm b/src/tools/PerfectHash.pm index 448c5ed3ac833..b8dcfe25e2a82 100644 --- a/src/tools/PerfectHash.pm +++ b/src/tools/PerfectHash.pm @@ -20,7 +20,7 @@ # not in the set. # # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/tools/PerfectHash.pm diff --git a/src/tools/RELEASE_CHANGES b/src/tools/RELEASE_CHANGES index 0f30f85ec71fa..c0d75c213beae 100644 --- a/src/tools/RELEASE_CHANGES +++ b/src/tools/RELEASE_CHANGES @@ -10,6 +10,7 @@ For All Releases (major, minor, beta, RC) o update doc/src/sgml/release-NN.sgml in relevant branches o run spellchecker on result o add SGML markup + o run src/tools/add_commit_links.pl * Update timezone data to match latest IANA timezone database and new Windows releases, if any (see src/timezone/README) @@ -88,6 +89,9 @@ Starting a New Development Cycle * Typically, we do pgindent and perltidy runs just before branching, as well as before beta (complete steps from src/tools/pgindent/README) +* It's also advisable to check that copyright years are up-to-date + (run src/tools/copyright.pl, commit any changes it finds) + * Create a branch in git for maintenance of the previous release o on master branch, do: git pull # be sure you have the latest "master" diff --git a/src/tools/add_commit_links.pl b/src/tools/add_commit_links.pl new file mode 100755 index 0000000000000..710a649203209 --- /dev/null +++ b/src/tools/add_commit_links.pl @@ -0,0 +1,134 @@ +#! /usr/bin/perl + +################################################################# +# add_commit_links.pl -- add commit links to the release notes +# +# Copyright (c) 2024-2025, PostgreSQL Global Development Group +# +# src/tools/add_commit_links.pl +################################################################# + +# +# This script adds commit links to the release notes. +# +# Usage: cd to top of source tree and issue +# src/tools/add_commit_links.pl release_notes_file +# +# The script can add links for release note items that lack them, and update +# those that have them. The script is sensitive to the release note file being +# in a specific format: +# +# * File name contains the major version number preceded by a dash +# and followed by a period +# * Commit text is generated by src/tools/git_changelog +# * SGML comments around commit text start in the first column +# * The commit item title ends with an attribution that ends with +# a closing parentheses +# * previously added URL link text is unmodified +# * a "" follows the commit item title +# +# The major version number is used to select the commit hash for minor +# releases. An error will be generated if valid commits are found but +# no proper location for the commit links is found. + +use strict; +use warnings FATAL => 'all'; + +sub process_file +{ + my $file = shift; + + my $in_comment = 0; + my $prev_line_ended_with_paren = 0; + my $prev_leading_space = ''; + my $lineno = 0; + + my @hashes = (); + + my $tmpfile = $file . '.tmp'; + + # Get major version number from the file name. + $file =~ m/-(\d+)\./; + my $major_version = $1; + + open(my $fh, '<', $file) || die "could not open file $file: $!\n"; + open(my $tfh, '>', $tmpfile) || die "could not open file $tmpfile: $!\n"; + + while (<$fh>) + { + $lineno++; + + $in_comment = 1 if (m/^/); + } + + close($fh); + close($tfh); + + rename($tmpfile, $file) || die "could not rename %s to %s: $!\n", + $tmpfile, + $file; + + return; +} + +if (@ARGV == 0) +{ + printf(STDERR "Usage: %s release_notes_file [...]\n", $0); + exit(1); +} + +for my $file (@ARGV) +{ + process_file($file); +} diff --git a/src/tools/check_bison_recursion.pl b/src/tools/check_bison_recursion.pl index f217f931d0b2d..6dea3a21779a9 100755 --- a/src/tools/check_bison_recursion.pl +++ b/src/tools/check_bison_recursion.pl @@ -16,7 +16,7 @@ # To use: run bison with the -v switch, then feed the produced y.output # file to this script. # -# Copyright (c) 2011-2024, PostgreSQL Global Development Group +# Copyright (c) 2011-2025, PostgreSQL Global Development Group # # src/tools/check_bison_recursion.pl ################################################################# diff --git a/src/tools/ci/README b/src/tools/ci/README index 30ddd200c9669..12c1e7c308fa9 100644 --- a/src/tools/ci/README +++ b/src/tools/ci/README @@ -61,7 +61,7 @@ Controlling CI via commit messages The behavior of CI can be controlled by special content in commit messages. Currently the following controls are available: -- ci-os-only: {(freebsd|linux|macos|windows|mingw)} +- ci-os-only: {(freebsd|linux|macos|mingw|netbsd|openbsd|windows)} Only runs CI on operating systems specified. This can be useful when addressing portability issues affecting only a subset of platforms. diff --git a/src/tools/ci/ci_macports_packages.sh b/src/tools/ci/ci_macports_packages.sh index 71248bd22b04e..63e97b37c7863 100755 --- a/src/tools/ci/ci_macports_packages.sh +++ b/src/tools/ci/ci_macports_packages.sh @@ -19,7 +19,7 @@ echo "macOS major version: $macos_major_version" # Scan the available MacPorts releases to find one that matches the running # macOS release. macports_release_list_url="https://api.github.com/repos/macports/macports-base/releases" -macports_version_pattern="2\.9\.3" +macports_version_pattern="2\.10\.1" macports_url="$( curl -s $macports_release_list_url | grep "\"https://github.com/macports/macports-base/releases/download/v$macports_version_pattern/MacPorts-$macports_version_pattern-$macos_major_version-[A-Za-z]*\.pkg\"" | sed 's/.*: "//;s/".*//' | head -1 )" echo "MacPorts package URL: $macports_url" @@ -59,11 +59,18 @@ if [ -n "$(port -q installed installed)" ] ; then sudo port unsetrequested installed fi -# if setting all the required packages as requested fails, we need -# to install at least one of them -if ! sudo port setrequested $packages > /dev/null 2>&1 ; then - echo not all required packages installed, doing so now +# If setting all the required packages as requested fails, we need +# to install at least one of them. Need to do so one-by-one as +# port setrequested only reports failures for the first package. +echo "checking if all required packages are installed" +for package in $packages ; do + if ! sudo port setrequested $package > /dev/null 2>&1 ; then update_cached_image=1 + fi +done +echo "done" +if [ "$update_cached_image" -eq 1 ]; then + echo not all required packages installed, doing so now # to keep the image small, we deleted the ports tree from the image... sudo port selfupdate # XXX likely we'll need some other way to force an upgrade at some diff --git a/src/tools/ci/cores_backtrace.sh b/src/tools/ci/cores_backtrace.sh index 28d3cecfc6709..5460741525814 100755 --- a/src/tools/ci/cores_backtrace.sh +++ b/src/tools/ci/cores_backtrace.sh @@ -9,7 +9,7 @@ os=$1 directory=$2 case $os in - freebsd|linux|macos) + freebsd|linux|macos|netbsd|openbsd) ;; *) echo "unsupported operating system ${os}" @@ -26,7 +26,7 @@ for corefile in $(find "$directory" -type f) ; do echo -e '\n\n' fi - if [ "$os" = 'macos' ]; then + if [ "$os" = 'macos' ] || [ "$os" = 'openbsd' ]; then lldb -c $corefile --batch -o 'thread backtrace all' -o 'quit' else auxv=$(gdb --quiet --core ${corefile} --batch -ex 'info auxv' 2>/dev/null) @@ -37,6 +37,8 @@ for corefile in $(find "$directory" -type f) ; do if [ "$os" = 'freebsd' ]; then binary=$(echo "$auxv" | grep AT_EXECPATH | perl -pe "s/^.*\"(.*)\"\$/\$1/g") + elif [ "$os" = 'netbsd' ]; then + binary=$(echo "$auxv" | grep AT_SUN_EXECNAME | perl -pe "s/^.*\"(.*)\"\$/\$1/g") elif [ "$os" = 'linux' ]; then binary=$(echo "$auxv" | grep AT_EXECFN | perl -pe "s/^.*\"(.*)\"\$/\$1/g") else diff --git a/src/tools/ci/gcp_freebsd_repartition.sh b/src/tools/ci/gcp_freebsd_repartition.sh deleted file mode 100755 index 3adb8fb88eccf..0000000000000 --- a/src/tools/ci/gcp_freebsd_repartition.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -set -e -set -x - -# fix backup partition table after resize -gpart recover da0 -gpart show da0 - -# delete and re-add swap partition with expanded size -swapoff -a -gpart delete -i 3 da0 -gpart add -t freebsd-swap -l swapfs -a 4096 da0 -gpart show da0 -swapon -a - -# create a file system on a memory disk backed by swap, to minimize I/O -mdconfig -a -t swap -s20g -u md1 -newfs -b 8192 -U /dev/md1 - -# migrate working directory -du -hs $CIRRUS_WORKING_DIR -mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig -mkdir $CIRRUS_WORKING_DIR -mount -o noatime /dev/md1 $CIRRUS_WORKING_DIR -cp -a $CIRRUS_WORKING_DIR.orig/ $CIRRUS_WORKING_DIR/ diff --git a/src/tools/ci/gcp_ram_disk.sh b/src/tools/ci/gcp_ram_disk.sh new file mode 100755 index 0000000000000..d48634512ac28 --- /dev/null +++ b/src/tools/ci/gcp_ram_disk.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# Move working directory into a RAM disk for better performance. + +set -e +set -x + +mv $CIRRUS_WORKING_DIR $CIRRUS_WORKING_DIR.orig +mkdir $CIRRUS_WORKING_DIR + +case "`uname`" in + FreeBSD|NetBSD) + mount -t tmpfs tmpfs $CIRRUS_WORKING_DIR + ;; + OpenBSD) + umount /dev/sd0j # unused /usr/obj partition + printf "m j\n\n\nswap\nw\nq\n" | disklabel -E sd0 + swapon /dev/sd0j + mount -t mfs -o rw,noatime,nodev,-s=8000000 swap $CIRRUS_WORKING_DIR + ;; +esac + +cp -a $CIRRUS_WORKING_DIR.orig/. $CIRRUS_WORKING_DIR/ diff --git a/src/tools/ci/pg_ci_base.conf b/src/tools/ci/pg_ci_base.conf index d8faa9c26c179..9cec5c2910d80 100644 --- a/src/tools/ci/pg_ci_base.conf +++ b/src/tools/ci/pg_ci_base.conf @@ -8,7 +8,7 @@ max_prepared_transactions = 10 # Settings that make logs more useful log_autovacuum_min_duration = 0 log_checkpoints = true -log_connections = true +log_connections = all log_disconnections = true log_line_prefix = '%m [%p][%b] %q[%a][%v:%x] ' log_lock_waits = true diff --git a/src/tools/copyright.pl b/src/tools/copyright.pl index 804537f26a4ea..0d2bf7b486df6 100755 --- a/src/tools/copyright.pl +++ b/src/tools/copyright.pl @@ -2,7 +2,7 @@ ################################################################# # copyright.pl -- update copyright notices throughout the source tree, idempotently. # -# Copyright (c) 2011-2024, PostgreSQL Global Development Group +# Copyright (c) 2011-2025, PostgreSQL Global Development Group # # src/tools/copyright.pl # diff --git a/src/tools/fix-old-flex-code.pl b/src/tools/fix-old-flex-code.pl deleted file mode 100644 index a37a1f3d52256..0000000000000 --- a/src/tools/fix-old-flex-code.pl +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/perl -#---------------------------------------------------------------------- -# -# fix-old-flex-code.pl -# -# flex versions before 2.5.36, with certain option combinations, produce -# code that causes an "unused variable" warning. That's annoying, so -# let's suppress it by inserting a dummy reference to the variable. -# (That's exactly what 2.5.36 and later do ...) -# -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group -# Portions Copyright (c) 1994, Regents of the University of California -# -# src/tools/fix-old-flex-code.pl -# -#---------------------------------------------------------------------- - -use strict; -use warnings FATAL => 'all'; - -# Get command line argument. -usage() if $#ARGV != 0; -my $filename = shift; - -# Suck in the whole file. -local $/ = undef; -my $cfile; -open($cfile, '<', $filename) || die "opening $filename for reading: $!"; -my $ccode = <$cfile>; -close($cfile); - -# No need to do anything if it's not flex 2.5.x for x < 36. -exit 0 if $ccode !~ m/^#define YY_FLEX_MAJOR_VERSION 2$/m; -exit 0 if $ccode !~ m/^#define YY_FLEX_MINOR_VERSION 5$/m; -exit 0 if $ccode !~ m/^#define YY_FLEX_SUBMINOR_VERSION (\d+)$/m; -exit 0 if $1 >= 36; - -# Apply the desired patch. -$ccode =~ - s|(struct yyguts_t \* yyg = \(struct yyguts_t\*\)yyscanner; /\* This var may be unused depending upon options. \*/ -.*?) - return yy_is_jam \? 0 : yy_current_state; -|$1 - (void) yyg; - return yy_is_jam ? 0 : yy_current_state; -|s; - -# Write the modified file back out. -open($cfile, '>', $filename) || die "opening $filename for writing: $!"; -print $cfile $ccode; -close($cfile); - -exit 0; - - -sub usage -{ - die <. -EOM -} diff --git a/src/tools/gen_export.pl b/src/tools/gen_export.pl index d9fdaaaf6d0f5..86a7742b36981 100644 --- a/src/tools/gen_export.pl +++ b/src/tools/gen_export.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2024, PostgreSQL Global Development Group +# Copyright (c) 2024-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/tools/gen_keywordlist.pl b/src/tools/gen_keywordlist.pl index 1b3bc2e9b47e9..6ec83ff33f9a9 100644 --- a/src/tools/gen_keywordlist.pl +++ b/src/tools/gen_keywordlist.pl @@ -21,7 +21,7 @@ # Note that case folding works correctly only for all-ASCII keywords! # # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/tools/gen_keywordlist.pl @@ -71,7 +71,7 @@ * %s.h * List of keywords represented as a ScanKeywordList. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES diff --git a/src/tools/generate_editorconfig.py b/src/tools/generate_editorconfig.py new file mode 100755 index 0000000000000..0ce54f7292ade --- /dev/null +++ b/src/tools/generate_editorconfig.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +import os + + +def cd_to_repo_root(): + abspath = os.path.abspath(__file__) + dname = os.path.join(os.path.dirname(abspath), "..", "..") + os.chdir(dname) + + +# Space based indentation levels are not tracked in .gitattributes, so +# we hardcode them here for the relevant filetypes. +space_based_indent_sizes = { + "*.py": 4, + "*.sgml": 1, + "*.xsl": 1, + "*.xml": 2, +} + + +def main(): + cd_to_repo_root() + + with open(".gitattributes", "r") as f: + lines = f.read().splitlines() + + new_contents = """root = true + +[*] +indent_size = tab +""" + + for line in lines: + if line.startswith("#") or len(line) == 0: + continue + name, git_rules = line.split() + if git_rules == "-whitespace": + rules = [ + "indent_style = unset", + "indent_size = unset", + "trim_trailing_whitespace = unset", + "insert_final_newline = unset", + ] + elif git_rules.startswith("whitespace="): + git_whitespace_rules = git_rules.replace("whitespace=", "").split(",") + rules = [] + if "-blank-at-eol" in git_whitespace_rules: + rules += ["trim_trailing_whitespace = unset"] + else: + rules += ["trim_trailing_whitespace = true"] + + if "-blank-at-eof" in git_whitespace_rules: + rules += ["insert_final_newline = unset"] + else: + rules += ["insert_final_newline = true"] + + if "tab-in-indent" in git_whitespace_rules: + rules += ["indent_style = space"] + elif "indent-with-non-tab" in git_whitespace_rules: + rules += ["indent_style = tab"] + elif name in ["*.pl", "*.pm"]: + # We want editors to use tabs for indenting Perl + # files, but we cannot add it such a rule to + # .gitattributes, because certain lines are still + # indented with spaces (e.g. SYNOPSIS blocks). So we + # hardcode the rule here. + + rules += ["indent_style = tab"] + else: + rules += ["indent_style = unset"] + + tab_width = "unset" + for rule in git_whitespace_rules: + if rule.startswith("tabwidth="): + tab_width = rule.replace("tabwidth=", "") + rules += [f"tab_width = {tab_width}"] + + if name in space_based_indent_sizes: + indent_size = space_based_indent_sizes[name] + rules += [f"indent_size = {indent_size}"] + + else: + continue + + rules = "\n".join(rules) + new_contents += f"\n[{name}]\n{rules}\n" + + with open(".editorconfig", "w") as f: + f.write(new_contents) + + +if __name__ == "__main__": + main() diff --git a/src/tools/git_changelog b/src/tools/git_changelog index bfd17718bc76d..b8bd874f20858 100755 --- a/src/tools/git_changelog +++ b/src/tools/git_changelog @@ -1,6 +1,6 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group # # src/tools/git_changelog diff --git a/src/tools/ifaddrs/Makefile b/src/tools/ifaddrs/Makefile index e49547bb6ac72..1cb01a8211f2a 100644 --- a/src/tools/ifaddrs/Makefile +++ b/src/tools/ifaddrs/Makefile @@ -2,7 +2,7 @@ # # Makefile for src/tools/ifaddrs # -# Copyright (c) 2003-2024, PostgreSQL Global Development Group +# Copyright (c) 2003-2025, PostgreSQL Global Development Group # # src/tools/ifaddrs/Makefile # diff --git a/src/tools/mark_pgdllimport.pl b/src/tools/mark_pgdllimport.pl index b838aeeb43192..d276250fdb3c1 100755 --- a/src/tools/mark_pgdllimport.pl +++ b/src/tools/mark_pgdllimport.pl @@ -15,7 +15,7 @@ # script modifies before committing. This script uses as arguments # a list of the header files to scan for the markings. # -# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # src/tools/mark_pgdllimport.pl diff --git a/src/tools/msvc_gendef.pl b/src/tools/msvc_gendef.pl index 97346cc8929bf..868aad51b09ca 100644 --- a/src/tools/msvc_gendef.pl +++ b/src/tools/msvc_gendef.pl @@ -1,5 +1,5 @@ -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index d922013e40bb5..1d6aa76df9474 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -2,7 +2,7 @@ # # src/tools/pg_bsd_indent/Makefile # -# Copyright (c) 2017-2024, PostgreSQL Global Development Group +# Copyright (c) 2017-2025, PostgreSQL Global Development Group # #------------------------------------------------------------------------- @@ -25,6 +25,8 @@ OBJS = \ parse.o \ pr_comment.o +$(OBJS): CFLAGS += $(PERMIT_MISSING_VARIABLE_DECLARATIONS) + all: pg_bsd_indent pg_bsd_indent: $(OBJS) | submake-libpgport diff --git a/src/tools/pg_bsd_indent/err.h b/src/tools/pg_bsd_indent/err.h index a3e8f97825572..1083462088e2b 100644 --- a/src/tools/pg_bsd_indent/err.h +++ b/src/tools/pg_bsd_indent/err.h @@ -37,9 +37,9 @@ * This is cut down to just the minimum that we need to build indent. */ -void err(int, const char *, ...) - pg_attribute_noreturn() pg_attribute_printf(2, 3); -void errx(int, const char *, ...) - pg_attribute_noreturn() pg_attribute_printf(2, 3); +pg_noreturn void err(int, const char *, ...) + pg_attribute_printf(2, 3); +pg_noreturn void errx(int, const char *, ...) + pg_attribute_printf(2, 3); #endif /* !_ERR_H_ */ diff --git a/src/tools/pg_bsd_indent/meson.build b/src/tools/pg_bsd_indent/meson.build index 4387c47740ea6..9909ee46581f7 100644 --- a/src/tools/pg_bsd_indent/meson.build +++ b/src/tools/pg_bsd_indent/meson.build @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2024, PostgreSQL Global Development Group +# Copyright (c) 2022-2025, PostgreSQL Global Development Group pg_bsd_indent_sources = files( 'args.c', @@ -18,6 +18,7 @@ endif pg_bsd_indent = executable('pg_bsd_indent', pg_bsd_indent_sources, + c_args: cflags_no_missing_var_decls, dependencies: [frontend_code], include_directories: include_directories('.'), kwargs: default_bin_args + { diff --git a/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl index 9e23ab96161bc..bd70c916d9beb 100644 --- a/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl +++ b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl @@ -1,7 +1,7 @@ # pg_bsd_indent: some simple tests # The test cases come from FreeBSD upstream, but this test scaffolding is ours. -# Copyright (c) 2017-2024, PostgreSQL Global Development Group +# Copyright (c) 2017-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; @@ -26,8 +26,8 @@ # Any diffs in the generated files will be accumulated here. my $diffs_file = "test.diffs"; -# options used with diff -my @diffopts = ("-upd"); +# options used with diff (see pg_regress.c's pretty_diff_opts) +my @diffopts = ("-U3"); push(@diffopts, "--strip-trailing-cr") if $windows_os; # Copy support files to current dir, so *.pro files don't need to know path. @@ -49,8 +49,9 @@ ], "pg_bsd_indent succeeds on $test"); # check result matches, adding any diff to $diffs_file - my $result = run_log([ 'diff', @diffopts, "$test_src.stdout", "$test.out" ], - '>>', $diffs_file); + my $result = + run_log([ 'diff', @diffopts, "$test_src.stdout", "$test.out" ], + '>>' => $diffs_file); ok($result, "pg_bsd_indent output matches for $test"); } diff --git a/src/tools/pgflex b/src/tools/pgflex index baabe2df1c8eb..3986b06874e75 100755 --- a/src/tools/pgflex +++ b/src/tools/pgflex @@ -4,7 +4,6 @@ # Wrapper around flex that: # - ensures lex.backup is created in a private directory # - can error out if lex.backup is created (--no-backup) -# - can fix warnings (--fix-warnings) # - works around concurrency issues with win_flex.exe: # https://github.com/lexxmark/winflexbison/issues/86 @@ -28,8 +27,6 @@ parser.add_argument('-o', dest='output_file', type=abspath, required=True, parser.add_argument('-i', dest='input_file', type=abspath, help='input file') -parser.add_argument('--fix-warnings', action='store_true', - help='whether to fix warnings in generated file') parser.add_argument('--no-backup', action='store_true', help='whether no_backup is enabled or not') @@ -72,14 +69,4 @@ if args.no_backup: sys.exit('Scanner requires backup; see lex.backup.') os.remove('lex.backup') -# fix warnings -if args.fix_warnings: - fix_warning_script = os.path.join(args.srcdir, - 'src/tools/fix-old-flex-code.pl') - - command = [args.perl, fix_warning_script, args.output_file] - sp = subprocess.run(command) - if sp.returncode != 0: - sys.exit(sp.returncode) - sys.exit(0) diff --git a/src/tools/pginclude/README b/src/tools/pginclude/README index a685940da952c..2f8fe6b78baa5 100644 --- a/src/tools/pginclude/README +++ b/src/tools/pginclude/README @@ -1,66 +1,45 @@ src/tools/pginclude/README -NOTE: headerscheck and headerscheck --cplusplus are in current use, -and any problems they find should generally get fixed. The other -scripts in this directory have not been used in some time, and have -issues. pgrminclude in particular has a history of creating more -problems than it fixes. Be very wary of applying their results -blindly. +This directory contains some scripts and information for managing +header files and includes in PostgreSQL source code. -pginclude -========= +include-what-you-use +==================== -These utilities help clean up #include file usage. They should be run -in this order so that the include files have the proper includes before -the C files are tested. +include-what-you-use (IWYU) () is a +tool for finding missing or superfluous includes in C source files. -pgfixinclude change #include's to <> or "" +With a compilation database (compile_commands.json, produced by +meson), it can be run like this, over the whole source tree: -pgcompinclude [-v] - report which #include files can not compile on their own + iwyu_tool.py -p build . -pgrminclude [-v] - remove extra #include's +(this will likely be very noisy) or for individual files: -pgcheckdefines - check for #ifdef tests on symbols defined in files that - weren't included --- this is a necessary sanity check on - pgrminclude + iwyu_tool.py -p build src/bin/psql/startup.c -pgdefine create macro calls for all defines in the file (used by - the above routines) +Various other invocation options are available. -It is also a good idea to sort the pg-specific include files in -alphabetic order. This is best done with a text editor. Typical usage -order would be: +It is recommended to use at least version 0.23. Earlier versions give +advice that is incompatible with the compiler warning option +-Wmissing-variable-declarations. - pgfixinclude - sort include references - run multiple times: - pgcompinclude - pgrminclude /src/include - pgrminclude / - pgcheckdefines +clangd (the language server) can automatically give IWYU-style advice; +see . -There is a complexity when modifying /src/include. If include file 1 -includes file 2, and file 2 includes file 3, then when file 1 is -processed, it needs only file 2, not file 3. However, if later, include -file 2 is processed, and file 3 is not needed by file 2 and is removed, -file 1 might then need to include file 3. For this reason, the -pgcompinclude and pgrminclude /src/include steps must be run several -times until all includes compile cleanly. +The source code contains some "IWYU pragma" comments to tell IWYU +about some PostgreSQL include file conventions (such as that a header +such as "postgres.h" should always be included, even if it doesn't +contribute any symbols used by the particular source file) and to +silence a few warnings that are difficult to fix. See + +for documentation about those. -Also, tests should be done with configure settings of --enable-cassert -and EXEC_BACKEND on and off. It is also wise to test a WIN32 compile. - -Another tools that does a similar task is at: - - http://code.google.com/p/include-what-you-use/ - -An include file visualizer script is available at: - - http://archives.postgresql.org/pgsql-hackers/2011-09/msg00311.php +Of course, any include changes suggested by this or other tools should +be checked and verified carefully. Note that some includes are only +used on some platforms or with some compilation options, so blindly +following the produced advice is not recommended. headerscheck diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck index 436e2b92a334d..9e86d0493621e 100755 --- a/src/tools/pginclude/headerscheck +++ b/src/tools/pginclude/headerscheck @@ -13,7 +13,7 @@ # No output if everything is OK, else compiler errors. # # src/tools/pginclude/headerscheck -# Copyright (c) 2009-2024, PostgreSQL Global Development Group +# Copyright (c) 2009-2025, PostgreSQL Global Development Group # option to check for C++ compatibility if [ "$1" = "--cplusplus" ]; then @@ -138,6 +138,12 @@ do test "$f" = src/pl/tcl/pltclerrcodes.h && continue # Also not meant to be included standalone. + test "$f" = contrib/isn/EAN13.h && continue + test "$f" = contrib/isn/ISBN.h && continue + test "$f" = contrib/isn/ISMN.h && continue + test "$f" = contrib/isn/ISSN.h && continue + test "$f" = contrib/isn/UPC.h && continue + test "$f" = src/include/common/unicode_nonspacing_table.h && continue test "$f" = src/include/common/unicode_east_asian_fw_table.h && continue @@ -162,6 +168,9 @@ do # This produces a "no previous prototype" warning. ! $cplusplus && test "$f" = src/include/storage/checksum_impl.h && continue + # SectionMemoryManager.h is C++ + test "$f" = src/include/jit/SectionMemoryManager.h && continue + # ppport.h is not under our control, so we can't make it standalone. test "$f" = src/pl/plperl/ppport.h && continue diff --git a/src/tools/pginclude/pgcheckdefines b/src/tools/pginclude/pgcheckdefines deleted file mode 100755 index 096bbbe876798..0000000000000 --- a/src/tools/pginclude/pgcheckdefines +++ /dev/null @@ -1,305 +0,0 @@ -#! /usr/bin/perl - -# Copyright (c) 2021-2024, PostgreSQL Global Development Group - -# -# This script looks for symbols that are referenced in #ifdef or defined() -# tests without having #include'd the file that defines them. Since this -# situation won't necessarily lead to any compiler message, it seems worth -# having an automated check for it. In particular, use this to audit the -# results of pgrminclude! -# -# Usage: configure and build a PG source tree (non-VPATH), then start this -# script at the top level. It's best to enable as many configure options -# as you can, especially --enable-cassert which is known to affect include -# requirements. NB: you MUST use gcc, unless you have another compiler that -# can be persuaded to spit out the names of referenced include files. -# -# The results are necessarily platform-dependent, so use care in interpreting -# them. We try to process all .c files, even those not intended for the -# current platform, so there will be some phony failures. -# -# src/tools/pginclude/pgcheckdefines -# - -use strict; -use warnings FATAL => 'all'; - -use Cwd; -use File::Basename; - -my $topdir = cwd(); - -# Programs to use -my $FIND = "find"; -my $MAKE = "make"; - -# -# Build arrays of all the .c and .h files in the tree -# -# We ignore .h files under src/include/port/, since only the one exposed as -# src/include/port.h is interesting. (XXX Windows ports have additional -# files there?) Ditto for .h files in src/backend/port/ subdirectories. -# Including these .h files would clutter the list of define'd symbols and -# cause a lot of false-positive results. -# -my (@cfiles, @hfiles); - -open my $pipe, '-|', "$FIND * -type f -name '*.c'" - or die "can't fork: $!"; -while (<$pipe>) -{ - chomp; - push @cfiles, $_; -} -close $pipe or die "$FIND failed: $!"; - -open $pipe, '-|', "$FIND * -type f -name '*.h'" - or die "can't fork: $!"; -while (<$pipe>) -{ - chomp; - push @hfiles, $_ - unless m|^src/include/port/| - || m|^src/backend/port/\w+/|; -} -close $pipe or die "$FIND failed: $!"; - -# -# For each .h file, extract all the symbols it #define's, and add them to -# a hash table. To cover the possibility of multiple .h files defining -# the same symbol, we make each hash entry a hash of filenames. -# -my %defines; - -foreach my $hfile (@hfiles) -{ - open my $fh, '<', $hfile - or die "can't open $hfile: $!"; - while (<$fh>) - { - if (m/^\s*#\s*define\s+(\w+)/) - { - $defines{$1}{$hfile} = 1; - } - } - close $fh; -} - -# -# For each file (both .h and .c), run the compiler to get a list of what -# files it #include's. Then extract all the symbols it tests for defined-ness, -# and check each one against the previously built hashtable. -# -foreach my $file (@hfiles, @cfiles) -{ - my ($fname, $fpath) = fileparse($file); - chdir $fpath or die "can't chdir to $fpath: $!"; - - # - # Ask 'make' to parse the makefile so we can get the correct flags to - # use. CPPFLAGS in particular varies for each subdirectory. If we are - # processing a .h file, we might be in a subdirectory that has no - # Makefile, in which case we have to fake it. Note that there seems - # no easy way to prevent make from recursing into subdirectories and - # hence printing multiple definitions --- we keep the last one, which - # should come from the current Makefile. - # - my $MAKECMD; - - if (-f "Makefile" || -f "GNUmakefile") - { - $MAKECMD = "$MAKE -qp"; - } - else - { - my $subdir = $fpath; - chop $subdir; - my $top_builddir = ".."; - my $tmp = $fpath; - while (($tmp = dirname($tmp)) ne '.') - { - $top_builddir = $top_builddir . "/.."; - } - $MAKECMD = - "$MAKE -qp 'subdir=$subdir' 'top_builddir=$top_builddir' -f '$top_builddir/src/Makefile.global'"; - } - - my ($CPPFLAGS, $CFLAGS, $CFLAGS_SL, $PTHREAD_CFLAGS, $CC); - - open $pipe, '-|', "$MAKECMD" - or die "can't fork: $!"; - while (<$pipe>) - { - if (m/^CPPFLAGS :?= (.*)/) - { - $CPPFLAGS = $1; - } - elsif (m/^CFLAGS :?= (.*)/) - { - $CFLAGS = $1; - } - elsif (m/^CFLAGS_SL :?= (.*)/) - { - $CFLAGS_SL = $1; - } - elsif (m/^PTHREAD_CFLAGS :?= (.*)/) - { - $PTHREAD_CFLAGS = $1; - } - elsif (m/^CC :?= (.*)/) - { - $CC = $1; - } - } - - # If make exits with status 1, it's not an error, it just means make - # thinks some files may not be up-to-date. Only complain on status 2. - close PIPE; - die "$MAKE failed in $fpath\n" if $? != 0 && $? != 256; - - # Expand out stuff that might be referenced in CFLAGS - $CFLAGS =~ s/\$\(CFLAGS_SL\)/$CFLAGS_SL/; - $CFLAGS =~ s/\$\(PTHREAD_CFLAGS\)/$PTHREAD_CFLAGS/; - - # - # Run the compiler (which had better be gcc) to get the inclusions. - # "gcc -H" reports inclusions on stderr as "... filename" where the - # number of dots varies according to nesting depth. - # - my @includes = (); - my $COMPILE = "$CC $CPPFLAGS $CFLAGS -H -E $fname"; - open $pipe, '-|', "$COMPILE 2>&1 >/dev/null" - or die "can't fork: $!"; - while (<$pipe>) - { - if (m/^\.+ (.*)/) - { - my $include = $1; - - # Ignore system headers (absolute paths); but complain if a - # .c file includes a system header before any PG header. - if ($include =~ m|^/|) - { - warn "$file includes $include before any Postgres inclusion\n" - if $#includes == -1 && $file =~ m/\.c$/; - next; - } - - # Strip any "./" (assume this appears only at front) - $include =~ s|^\./||; - - # Make path relative to top of tree - my $ipath = $fpath; - while ($include =~ s|^\.\./||) - { - $ipath = dirname($ipath) . "/"; - } - $ipath =~ s|^\./||; - push @includes, $ipath . $include; - } - else - { - warn "$CC: $_"; - } - } - - # The compiler might fail, particularly if we are checking a file that's - # not supposed to be compiled at all on the current platform, so don't - # quit on nonzero status. - close PIPE or warn "$COMPILE failed in $fpath\n"; - - # - # Scan the file to find #ifdef, #ifndef, and #if defined() constructs - # We assume #ifdef isn't continued across lines, and that defined(foo) - # isn't split across lines either - # - open my $fh, '<', $fname - or die "can't open $file: $!"; - my $inif = 0; - while (<$fh>) - { - my $line = $_; - if ($line =~ m/^\s*#\s*ifdef\s+(\w+)/) - { - checkit($file, $1, @includes); - } - if ($line =~ m/^\s*#\s*ifndef\s+(\w+)/) - { - checkit($file, $1, @includes); - } - if ($line =~ m/^\s*#\s*if\s+/) - { - $inif = 1; - } - if ($inif) - { - while ($line =~ s/\bdefined(\s+|\s*\(\s*)(\w+)//) - { - checkit($file, $2, @includes); - } - if (!($line =~ m/\\$/)) - { - $inif = 0; - } - } - } - close $fh; - - chdir $topdir or die "can't chdir to $topdir: $!"; -} - -exit 0; - -# Check an is-defined reference -sub checkit -{ - my ($file, $symbol, @includes) = @_; - - # Ignore if symbol isn't defined in any PG include files - if (!defined $defines{$symbol}) - { - return; - } - - # - # Try to match source(s) of symbol to the inclusions of the current file - # (including itself). We consider it OK if any one matches. - # - # Note: these tests aren't bulletproof; in theory the inclusion might - # occur after the use of the symbol. Given our normal file layout, - # however, the risk is minimal. - # - foreach my $deffile (keys %{ $defines{$symbol} }) - { - return if $deffile eq $file; - foreach my $reffile (@includes) - { - return if $deffile eq $reffile; - } - } - - # - # If current file is a .h file, it's OK for it to assume that one of the - # base headers (postgres.h or postgres_fe.h) has been included. - # - if ($file =~ m/\.h$/) - { - foreach my $deffile (keys %{ $defines{$symbol} }) - { - return if $deffile eq 'src/include/c.h'; - return if $deffile eq 'src/include/postgres.h'; - return if $deffile eq 'src/include/postgres_fe.h'; - return if $deffile eq 'src/include/pg_config.h'; - return if $deffile eq 'src/include/pg_config_manual.h'; - } - } - - # - my @places = keys %{ $defines{$symbol} }; - print "$file references $symbol, defined in @places\n"; - - # print "includes: @includes\n"; - - return; -} diff --git a/src/tools/pginclude/pgcompinclude b/src/tools/pginclude/pgcompinclude deleted file mode 100755 index 12169db9f6443..0000000000000 --- a/src/tools/pginclude/pgcompinclude +++ /dev/null @@ -1,47 +0,0 @@ -: -# report which #include files can not compile on their own -# takes -v option to display compile failure message and line numbers -# src/tools/pginclude/pgcompinclude - -: ${CC:=cc} -: ${PGSRC:=src} - -if ! pgdefine -then echo "pgdefine must be in your PATH" 1>&2 - exit 1 -fi - -trap "rm -f /tmp/$$.c /tmp/$$.o /tmp/$$ /tmp/$$a" 0 1 2 3 15 -find . \( -name .git -a -prune \) -o -name '*.h' -type f -print | while read FILE -do - sed 's/->[a-zA-Z0-9_\.]*//g' "$FILE" >/tmp/$$a - echo "#include \"postgres.h\"" >/tmp/$$.c - - # suppress fcinfo errors - echo "struct {Datum arg[1];} *fcinfo;" >>/tmp/$$.c - - echo "#include \"/tmp/$$a\"" >>/tmp/$$.c - - echo "Datum include_test(void);" >>/tmp/$$.c - echo "Datum include_test() {" >>/tmp/$$.c - - pgdefine "$FILE" >>/tmp/$$.c - - echo "return (Datum)0;" >>/tmp/$$.c - echo "}" >>/tmp/$$.c - - # Use -O1 to get warnings only generated by optimization, - # but -O2 is too slow. - $CC -fsyntax-only -Werror -Wall -Wmissing-prototypes \ - -Wmissing-declarations -I$PGSRC/include -I$PGSRC/backend \ - -I$PGSRC/interfaces/libpq -I`dirname $FILE` $CFLAGS -O1 -c /tmp/$$.c \ - -o /tmp/$$.o >/tmp/$$ 2>&1 - if [ "$?" -ne 0 ] - then echo "$FILE" - if [ "$1" = "-v" ] - then cat /tmp/$$ - nl /tmp/$$.c - echo - fi - fi -done diff --git a/src/tools/pginclude/pgdefine b/src/tools/pginclude/pgdefine deleted file mode 100755 index 242d035a778f1..0000000000000 --- a/src/tools/pginclude/pgdefine +++ /dev/null @@ -1,25 +0,0 @@ -: -# create macro calls for all defines in the file - -# src/tools/pginclude/pgdefine - -trap "rm -f /tmp/$$" 0 1 2 3 15 -for FILE -do - cat "$FILE" | grep "^#define" >/tmp/$$ - cat /tmp/$$ | sed -n 's/^#define[ ][ ]*\([a-zA-Z0-9_]*\)[ ][ ]*[^ ].*\\\\$/\1;/p' - cat /tmp/$$ | sed -n 's/^#define[ ][ ]*\([a-zA-Z0-9_]*\)[ ][ ]*[^ ].*[^\\\\]$/(void)\1;/p' - - ( - cat /tmp/$$ | sed -n 's/^#define[ ][ ]*\([a-zA-Z0-9_]*([^)]*)\).*\\\\$/\1;/p' - cat /tmp/$$ | sed -n 's/^#define[ ][ ]*\([a-zA-Z0-9_]*([^)]*)\).*[^\\\\]$/(=void)\1;/p' - ) | - sed 's/([a-zA-Z0-9_ ][a-zA-Z0-9_ ]*)/(0)/g' | - sed 's/([a-zA-Z0-9_ ]*,/(0,/g' | - sed 's/,[a-zA-Z0-9_ ]*,/,0,/g' | - sed 's/,[a-zA-Z0-9_ ]*)/,0)/g' | - # do not cast 'return' macros as (void) - sed 's/(=void)\(.*return\)/\1/g' | - sed 's/(=void)\(.*RETURN\)/\1/g' | - sed 's/(=void)/(void)/g' -done diff --git a/src/tools/pginclude/pgfixinclude b/src/tools/pginclude/pgfixinclude deleted file mode 100755 index 6721566495c9f..0000000000000 --- a/src/tools/pginclude/pgfixinclude +++ /dev/null @@ -1,21 +0,0 @@ -: -# change #include's to <> or "" -# src/tools/pginclude/pgfixinclude - -trap "rm -f /tmp/$$.c /tmp/$$.o /tmp/$$ /tmp/$$a /tmp/$$b" 0 1 2 3 15 -find . \( -name .git -a -prune \) -o -type f -name '*.[chyls]' -print | -while read FILE -do - cat "$FILE" | grep "^#include" | - sed 's/^#include[ ]*[<"]\([^>"]*\).*$/\1/g' | - while read INCLUDE - do - if [ -s /usr/include/"$INCLUDE" ] - then cat "$FILE" | - sed 's;^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]$;#include <'"$INCLUDE"'>;g' >/tmp/$$ - else cat "$FILE" | - sed 's;^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]$;#include "'"$INCLUDE"'";g' >/tmp/$$ - fi - cat /tmp/$$ > "$FILE" - done -done diff --git a/src/tools/pginclude/pgrminclude b/src/tools/pginclude/pgrminclude deleted file mode 100755 index 7cbd2e7c9cab1..0000000000000 --- a/src/tools/pginclude/pgrminclude +++ /dev/null @@ -1,149 +0,0 @@ -: -# remove extra #include's - -# pgcompinclude must be run before and after pgrminclude. It must be -# run before because we don't want include dependencies to leak into -# the C program files, and after because removal of includes from headers -# can cause new include unfulfilled dependencies. -# -# Limitations: 2011-09-24 -# -# Pgrminclude, when processing header files, can cause includes to be -# removed that require the addition of new illogical header files. -# This is dependent on what order the header files are processed. -# Manual review of header files now needed to satisfy pgcompinclude is -# required. -# -# C program files that have #ifdef blocks that contain code that cannot -# be compiled on the platform from which pgrminclude is run cannot be -# processed, and are skipped. - -: ${CC:=cc} -: ${PGSRC:=src} - -if ! pgdefine -then echo "pgdefine must be in your PATH" 1>&2 - exit 1 -fi - -trap "rm -f /tmp/$$.c /tmp/$$.o /tmp/$$ /tmp/$$a /tmp/$$b" 0 1 2 3 15 - -if [ "$1" = "-v" ] -then VERBOSE="Y" -else VERBOSE="" -fi - -verbose_output() { - if [ "$VERBOSE" ] - then cat /tmp/$$ - cat /tmp/$$b - nl /tmp/$$.c - fi -} - -process_includes_in_file() { - # loop through all includes mentioned in the file - cat "$FILE" | - grep "^#include\>" | - grep -v '/\* *pgrminclude *ignore *\*/' | - sed 's/^#include[ ]*[<"]\([^>"]*\).*$/\1/g' | - grep -v 'parser/kwlist\.h' | - grep -v '\.c$' | - while read INCLUDE - do if [ "$VERBOSE" ] - then echo "checking $FILE $INCLUDE" - fi - compile_file - done -} - -compile_file() { - [ "$INCLUDE" -a -s /usr/include/"$INCLUDE" ] && continue - [ "$INCLUDE" = "postgres.h" ] && continue - [ "$INCLUDE" = "postgres_fe.h" ] && continue - [ "$INCLUDE" = "pg_config.h" ] && continue - [ "$INCLUDE" = "c.h" ] && continue - # Stringify macros will expand undefined identifiers, so skip files that use it - egrep -q '\<(CppAsString2?|CppConcat)\>' "$FILE" && continue - - # preserve configure-specific includes - # these includes are surrounded by #ifdef's - grep -B1 '^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]' "$FILE" | - egrep -q '^#if|^#else|^#elif' && continue - grep -A1 '^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]' "$FILE" | - egrep -q '^#else|^#elif|^#endif' && continue - - # Remove all #if and #ifdef blocks because the blocks - # might contain code that is not compiled on this platform. - cat "$FILE" | - grep -v "^#if" | - grep -v "^#else" | - grep -v "^#elif" | - grep -v "^#endif" | - # with #if blocks gone, now undef #defines to avoid redefine - # warning and failure - sed 's/#define[ ][ ]*\([A-Za-z0-9_]*\).*$/#undef \1\n&/' >/tmp/$$a - - # set up initial file contents - grep -v '^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]' \ - /tmp/$$a >/tmp/$$b - - if [ "$IS_INCLUDE" = "Y" ] - then echo "#include \"postgres.h\"" >/tmp/$$.c - # suppress fcinfo errors - echo "struct {Datum arg[1];} *fcinfo;" >>/tmp/$$.c - else >/tmp/$$.c - fi - - echo "#include \"/tmp/$$b\"" >>/tmp/$$.c - - if [ "$IS_INCLUDE" = "Y" ] - then echo "Datum include_test(void);" >>/tmp/$$.c - echo "Datum include_test() {" >>/tmp/$$.c - pgdefine "$FILE" >>/tmp/$$.c - echo "return (Datum)0;" >>/tmp/$$.c - echo "}" >>/tmp/$$.c - fi - - # Use -O1 to get warnings only generated by optimization, - # but -O2 is too slow. - $CC -fsyntax-only -Werror -Wall -Wmissing-prototypes \ - -Wmissing-declarations -I$PGSRC/include -I$PGSRC/backend \ - -I$PGSRC/interfaces/libpq -I`dirname $FILE` $CFLAGS -O1 -c /tmp/$$.c \ - -o /tmp/$$.o >/tmp/$$ 2>&1 - if [ "$?" -eq 0 ] - then [ "$INCLUDE" -o "$VERBOSE" ] && echo "$FILE $INCLUDE" - grep -v '^#include[ ][ ]*[<"]'"$INCLUDE"'[>"]' \ - "$FILE" >/tmp/$$b - mv /tmp/$$b "$FILE" - return 0 - else return 1 - fi -} - -# Process include files first because they can affect the compilation -# of *.c files. -(find . \( -name .git -a -prune \) -o -type f -name '*.h' -print | sort; - find . \( -name .git -a -prune \) -o -type f -name '*.c' -print | sort) | -grep -v '/postgres.h$' | -grep -v '/postgres_fe.h$' | -grep -v '/pg_config.h$' | -grep -v '\./c.h$' | -while read FILE -do - if [ `expr $FILE : '.*\.h$'` -ne 0 ] - then IS_INCLUDE="Y" - else IS_INCLUDE="N" - fi - - # Can we compile the file with all existing includes? - INCLUDE="" - compile_file - # If the file can't be compiled on its own, there is no sense - # trying to remove the include files. - if [ "$?" -ne 0 ] - then echo "cannot compile $FILE with existing includes" - verbose_output - else process_includes_in_file - fi -done diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index 99e57f93bbcde..4976a373f9e53 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -4,8 +4,9 @@ src/include/storage/s_lock\.h$ src/include/port/atomics/ # -# This contains C++ constructs that confuse pgindent. +# These contain C++ constructs that confuse pgindent. src/include/jit/llvmjit\.h$ +src/include/jit/SectionMemoryManager\.h$ # # These are generated files with incomplete code fragments that # confuse pgindent. diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent index 77c8118e5d797..b7d718089248e 100755 --- a/src/tools/pgindent/pgindent +++ b/src/tools/pgindent/pgindent @@ -1,13 +1,20 @@ #!/usr/bin/perl -# Copyright (c) 2021-2024, PostgreSQL Global Development Group +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Program to maintain uniform layout style in our C code. +# Exit codes: +# 0 -- all OK +# 1 -- error invoking pgindent, nothing done +# 2 -- --check mode and at least one file requires changes +# 3 -- pg_bsd_indent failed on at least one file use strict; use warnings FATAL => 'all'; use Cwd qw(abs_path getcwd); use File::Find; -use File::Spec qw(devnull); +use File::Spec; use File::Temp; use IO::Handle; use Getopt::Long; @@ -66,11 +73,14 @@ if ($sourcedir) # might make them so. For the moment we just hardwire a list of names # to add and a list of names to exclude; eventually this may need to be # easier to configure. Note that the typedefs need trailing newlines. -my @additional = ("bool\n"); +my @additional = map { "$_\n" } qw( + bool regex_t regmatch_t regoff +); my %excluded = map { +"$_\n" => 1 } qw( - ANY FD_SET U abs allocfunc boolean date digit ilist interval iterator other - pointer printfunc reference string timestamp type wrap + FD_SET LookupSet boolean date duration + element_type inquiry iterator other + pointer reference rep string timestamp type wrap ); # globals @@ -175,7 +185,7 @@ sub process_exclude while (my $line = <$eh>) { chomp $line; - next if $line =~ m/^#/; + next if $line =~ m/^#/ || $line eq ""; my $rgx = qr!$line!; @files = grep { $_ !~ /$rgx/ } @files if $rgx; } @@ -235,6 +245,14 @@ sub pre_indent # Protect wrapping in CATALOG() $source =~ s!^(CATALOG\(.*)$!/*$1*/!gm; + # Treat a CURL_IGNORE_DEPRECATION() as braces for the purposes of + # indentation. (The recursive regex comes from the perlre documentation; it + # matches balanced parentheses as group $1 and the contents as group $2.) + my $curlopen = '{ /* CURL_IGNORE_DEPRECATION */'; + my $curlclose = '} /* CURL_IGNORE_DEPRECATION */'; + $source =~ + s!^[ \t]+CURL_IGNORE_DEPRECATION(\(((?:(?>[^()]+)|(?1))*)\))!$curlopen$2$curlclose!gms; + return $source; } @@ -249,6 +267,12 @@ sub post_indent $source =~ s!^/\* Open extern "C" \*/$!{!gm; $source =~ s!^/\* Close extern "C" \*/$!}!gm; + # Restore the CURL_IGNORE_DEPRECATION() macro, keeping in mind that our + # markers may have been re-indented. + $source =~ + s!{[ \t]+/\* CURL_IGNORE_DEPRECATION \*/!CURL_IGNORE_DEPRECATION(!gm; + $source =~ s!}[ \t]+/\* CURL_IGNORE_DEPRECATION \*/!)!gm; + ## Comments # Undo change of dash-protected block comments @@ -408,6 +432,7 @@ foreach my $source_filename (@files) if ($source eq "") { print STDERR "Failure in $source_filename: " . $error_message . "\n"; + $status = 3; next; } @@ -428,7 +453,7 @@ foreach my $source_filename (@files) if ($check) { - $status = 2; + $status ||= 2; last unless $diff; } } diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index b4d7f9217cec4..32d6e718adca0 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -6,6 +6,7 @@ ASN1_INTEGER ASN1_OBJECT ASN1_OCTET_STRING ASN1_STRING +ATAlterConstraint AV A_ArrayExpr A_Const @@ -54,6 +55,9 @@ AggStrategy AggTransInfo Aggref AggregateInstrumentation +AioWorkerControl +AioWorkerSlot +AioWorkerSubmissionQueue AlenState Alias AllocBlock @@ -150,6 +154,7 @@ ArrayIOData ArrayIterator ArrayMapState ArrayMetaState +ArraySortCachedInfo ArraySubWorkspace ArrayToken ArrayType @@ -168,6 +173,7 @@ AttrNumber AttributeOpts AuthRequest AuthToken +AutoPrewarmReadStreamData AutoPrewarmSharedState AutoVacOpts AutoVacuumShmemStruct @@ -189,6 +195,7 @@ BOOLEAN BOX BTArrayKeyInfo BTBuildState +BTCallbackState BTCycleId BTDedupInterval BTDedupState @@ -214,7 +221,6 @@ BTScanInsertData BTScanKeyPreproc BTScanOpaque BTScanOpaqueData -BTScanPos BTScanPosData BTScanPosItem BTShared @@ -230,11 +236,11 @@ BTWriteState BUF_MEM BYTE BY_HANDLE_FILE_INFORMATION -Backend BackendParameters BackendStartupData BackendState BackendType +BackendTypeMask BackgroundWorker BackgroundWorkerArray BackgroundWorkerHandle @@ -262,6 +268,7 @@ BitmapAndPath BitmapAndState BitmapHeapPath BitmapHeapScan +BitmapHeapScanDesc BitmapHeapScanInstrumentation BitmapHeapScanState BitmapIndexScan @@ -275,6 +282,7 @@ BlockId BlockIdData BlockInfoRecord BlockNumber +BlockRangeReadStreamPrivate BlockRefTable BlockRefTableBuffer BlockRefTableChunk @@ -331,6 +339,8 @@ BufFile Buffer BufferAccessStrategy BufferAccessStrategyType +BufferCacheNumaContext +BufferCacheNumaRec BufferCachePagesContext BufferCachePagesRec BufferDesc @@ -368,8 +378,19 @@ CState CTECycleClause CTEMaterialize CTESearchClause +CURL +CURLM +CURLMcode +CURLMsg +CURLcode +CURLoption CV CachedExpression +CachedFunction +CachedFunctionCompileCallback +CachedFunctionDeleteCallback +CachedFunctionHashEntry +CachedFunctionHashKey CachedPlan CachedPlanSource CallContext @@ -382,6 +403,7 @@ CaseTestExpr CaseWhen Cash CastInfo +CatCInProgress CatCList CatCTup CatCache @@ -389,6 +411,7 @@ CatCacheHeader CatalogId CatalogIdMapEntry CatalogIndexState +ChangeVarNodes_callback ChangeVarNodes_context CheckPoint CheckPointStmt @@ -453,7 +476,9 @@ CommitTimestampEntry CommitTimestampShared CommonEntry CommonTableExpr +CompactAttribute CompareScalarsContext +CompareType CompiledExprState CompositeIOData CompositeTypeStmt @@ -467,12 +492,15 @@ ConditionVariableMinimallyPadded ConditionalStack ConfigData ConfigVariable +ConflictTupleInfo +ConflictType ConnCacheEntry ConnCacheKey ConnParams ConnStatusType ConnType ConnectionStateEnum +ConnectionTiming ConsiderSplitContext Const ConstrCheck @@ -490,6 +518,7 @@ ConvertRowtypeExpr CookedConstraint CopyDest CopyFormatOptions +CopyFromRoutine CopyFromState CopyFromStateData CopyHeaderChoice @@ -501,6 +530,7 @@ CopyMultiInsertInfo CopyOnErrorChoice CopySource CopyStmt +CopyToRoutine CopyToState CopyToStateData Cost @@ -587,6 +617,7 @@ DatumTupleFields DbInfo DbInfoArr DbLocaleInfo +DbOidName DeClonePtrType DeadLockState DeallocateStmt @@ -598,6 +629,7 @@ DefElem DefElemAction DefaultACLInfo DefineStmt +DefnDumperPtr DeleteStmt DependencyGenerator DependencyGeneratorData @@ -617,6 +649,7 @@ DirectoryMethodFile DisableTimeoutParams DiscardMode DiscardStmt +DispatchOption DistanceValue DistinctExpr DoState @@ -646,7 +679,8 @@ DumpableObjectType DumpableObjectWithAcl DynamicFileList DynamicZoneAbbrev -EC_KEY +ECDerivesEntry +ECDerivesKey EDGE ENGINE EOM_flatten_into_method @@ -683,6 +717,7 @@ EphemeralNamedRelationMetadata EphemeralNamedRelationMetadataData EquivalenceClass EquivalenceMember +EquivalenceMemberIterator ErrorContextCallback ErrorData ErrorSaveContext @@ -727,10 +762,12 @@ ExpandedRange ExpandedRecordFieldInfo ExpandedRecordHeader ExplainDirectModify_function +ExplainExtensionOption ExplainForeignModify_function ExplainForeignScan_function ExplainFormat ExplainOneQuery_hook_type +ExplainOptionHandler ExplainSerializeOption ExplainState ExplainStmt @@ -758,6 +795,7 @@ FDWCollateState FD_SET FILE FILETIME +FPI FSMAddress FSMPage FSMPageData @@ -1001,6 +1039,7 @@ GenerationBlock GenerationContext GenerationPointer GenericCosts +GenericXLogPageData GenericXLogState GeqoPrivateData GetForeignJoinPaths_function @@ -1017,11 +1056,14 @@ GinBtreeData GinBtreeDataLeafInsertData GinBtreeEntryInsertData GinBtreeStack +GinBuffer +GinBuildShared GinBuildState GinChkVal GinEntries GinEntryAccumulator GinIndexStat +GinLeader GinMetaPageData GinNullCategory GinOptions @@ -1029,14 +1071,18 @@ GinPageOpaque GinPageOpaqueData GinPlaceToPageRC GinPostingList +GinPostingTreeScanItem GinQualCounts GinScanEntry +GinScanItem GinScanKey GinScanOpaque GinScanOpaqueData +GinSegmentInfo GinState GinStatsData GinTernaryValue +GinTuple GinTupleCollector GinVacuumState GistBuildMode @@ -1144,8 +1190,10 @@ HeadlineJsonState HeadlineParsedText HeadlineWordEntry HeapCheckContext +HeapCheckReadStreamData HeapPageFreeze HeapScanDesc +HeapScanDescData HeapTuple HeapTupleData HeapTupleFields @@ -1205,6 +1253,7 @@ IndexClause IndexClauseSet IndexDeleteCounts IndexDeletePrefetchState +IndexDoCheckCallback IndexElem IndexFetchHeapData IndexFetchTableData @@ -1218,6 +1267,7 @@ IndexPath IndexRuntimeKeyInfo IndexScan IndexScanDesc +IndexScanInstrumentation IndexScanState IndexStateFlagsAction IndexStmt @@ -1234,13 +1284,14 @@ InheritableSocket InitSampleScan_function InitializeDSMForeignScan_function InitializeWorkerForeignScan_function +InjIoErrorState InjectionPointCacheEntry InjectionPointCallback InjectionPointCondition InjectionPointConditionType InjectionPointEntry -InjectionPointsCtl InjectionPointSharedState +InjectionPointsCtl InlineCodeBlock InsertStmt Instrumentation @@ -1255,7 +1306,9 @@ Interval IntervalAggState IntoClause InvalMessageArray +InvalidationInfo InvalidationMsgsGroup +IoMethodOps IpcMemoryId IpcMemoryKey IpcMemoryState @@ -1444,8 +1497,7 @@ LLVMOrcResourceTrackerRef LLVMOrcSymbolStringPoolRef LLVMOrcThreadSafeContextRef LLVMOrcThreadSafeModuleRef -LLVMPassManagerBuilderRef -LLVMPassManagerRef +LLVMPassBuilderOptionsRef LLVMTargetMachineRef LLVMTargetRef LLVMTypeRef @@ -1515,6 +1567,7 @@ LoadStmt LocalBufferLookupEnt LocalPgBackendStatus LocalTransactionId +Location LocationIndex LocationLen LockAcquireResult @@ -1584,6 +1637,7 @@ LogicalSlotInfo LogicalSlotInfoArr LogicalTape LogicalTapeSet +LookupSet LsnReadQueue LsnReadQueueNextFun LsnReadQueueNextStatus @@ -1608,6 +1662,7 @@ ManyTestResourceKind Material MaterialPath MaterialState +MdPathStr MdfdVec Memoize MemoizeEntry @@ -1622,6 +1677,7 @@ MemoryContextCallback MemoryContextCallbackFunction MemoryContextCounters MemoryContextData +MemoryContextId MemoryContextMethodID MemoryContextMethods MemoryStatsPrintFunc @@ -1714,6 +1770,8 @@ NumericDigit NumericSortSupport NumericSumAccum NumericVar +OAuthValidatorCallbacks +OAuthValidatorModuleInit OM_uint32 OP OSAPerGroupState @@ -1749,11 +1807,11 @@ OnConflictAction OnConflictClause OnConflictExpr OnConflictSetState -OpBtreeInterpretation OpClassCacheEnt OpExpr OpFamilyMember OpFamilyOpFuncGroup +OpIndexInterpretation OpclassInfo Operator OperatorElement @@ -1763,6 +1821,7 @@ OprCacheKey OprInfo OprProofCacheEntry OprProofCacheKey +OrArgIndexMatch OuterJoinClauseInfo OutputPluginCallbacks OutputPluginOptions @@ -1779,6 +1838,7 @@ PGAlignedBlock PGAlignedXLogBlock PGAsyncStatusType PGCALL2 +PGCRYPTO_SHA_t PGChecksummablePage PGContextVisibility PGEvent @@ -1821,6 +1881,7 @@ PGVerbosity PG_Locale_Strategy PG_Lock_Status PG_init_t +PGauthData PGcancel PGcancelConn PGcmdQueueEntry @@ -1828,7 +1889,9 @@ PGconn PGdataValue PGlobjfuncs PGnotify +PGoauthBearerRequest PGpipelineStatus +PGpromptOAuthDevice PGresAttDesc PGresAttValue PGresParamDesc @@ -1847,7 +1910,6 @@ PLpgSQL_exception PLpgSQL_exception_block PLpgSQL_execstate PLpgSQL_expr -PLpgSQL_func_hashkey PLpgSQL_function PLpgSQL_getdiag_kind PLpgSQL_if_elsif @@ -1862,6 +1924,7 @@ PLpgSQL_rec PLpgSQL_recfield PLpgSQL_resolve_option PLpgSQL_row +PLpgSQL_rwopt PLpgSQL_stmt PLpgSQL_stmt_assert PLpgSQL_stmt_assign @@ -1927,6 +1990,8 @@ PLyTransformToOb PLyTupleToOb PLyUnicode_FromStringAndSize_t PLy_elog_impl_t +PMChild +PMChildPool PMINIDUMP_CALLBACK_INFORMATION PMINIDUMP_EXCEPTION_INFORMATION PMINIDUMP_USER_STREAM_INFORMATION @@ -1938,6 +2003,7 @@ PQArgBlock PQEnvironmentOption PQExpBuffer PQExpBufferData +PQauthDataHook_type PQcommMethods PQconninfoOption PQnoticeProcessor @@ -1957,6 +2023,7 @@ PSQL_COMP_CASE PSQL_ECHO PSQL_ECHO_HIDDEN PSQL_ERROR_ROLLBACK +PSQL_SEND_MODE PTEntryArray PTIterationArray PTOKEN_PRIVILEGES @@ -2090,6 +2157,27 @@ Permutation PermutationStep PermutationStepBlocker PermutationStepBlockerType +PgAioBackend +PgAioCtl +PgAioHandle +PgAioHandleCallbackComplete +PgAioHandleCallbackID +PgAioHandleCallbackReport +PgAioHandleCallbackStage +PgAioHandleCallbacks +PgAioHandleCallbacksEntry +PgAioHandleFlags +PgAioHandleState +PgAioOp +PgAioOpData +PgAioResult +PgAioResultStatus +PgAioReturn +PgAioTargetData +PgAioTargetID +PgAioTargetInfo +PgAioUringContext +PgAioWaitRef PgArchData PgBackendGSSStatus PgBackendSSLStatus @@ -2113,6 +2201,7 @@ PgFdwSamplingMethod PgFdwScanState PgIfAddrCallback PgStatShared_Archiver +PgStatShared_Backend PgStatShared_BgWriter PgStatShared_Checkpointer PgStatShared_Common @@ -2120,12 +2209,16 @@ PgStatShared_Database PgStatShared_Function PgStatShared_HashEntry PgStatShared_IO +PgStatShared_InjectionPoint +PgStatShared_InjectionPointFixed PgStatShared_Relation PgStatShared_ReplSlot PgStatShared_SLRU PgStatShared_Subscription PgStatShared_Wal PgStat_ArchiverStats +PgStat_Backend +PgStat_BackendPending PgStat_BackendSubEntry PgStat_BgWriterStats PgStat_BktypeIO @@ -2138,18 +2231,18 @@ PgStat_FunctionCallUsage PgStat_FunctionCounts PgStat_HashKey PgStat_IO -PgStat_Kind PgStat_KindInfo PgStat_LocalState PgStat_PendingDroppedStatsItem PgStat_PendingIO -PgStat_PendingWalStats PgStat_SLRUStats PgStat_ShmemControl PgStat_Snapshot PgStat_SnapshotEntry PgStat_StatDBEntry PgStat_StatFuncEntry +PgStat_StatInjEntry +PgStat_StatInjFixedEntry PgStat_StatReplSlotEntry PgStat_StatSubEntry PgStat_StatTabEntry @@ -2157,9 +2250,11 @@ PgStat_SubXactStatus PgStat_TableCounts PgStat_TableStatus PgStat_TableXactStatus +PgStat_WalCounters PgStat_WalStats PgXmlErrorContext PgXmlStrictness +Pg_abi_values Pg_finfo_record Pg_magic_struct PipeProtoChunk @@ -2191,6 +2286,7 @@ PortalHashEnt PortalStatus PortalStrategy PostParseColumnRefHook +PostRewriteHook PostgresPollingStatusType PostingItem PreParseColumnRefHook @@ -2255,18 +2351,19 @@ PublicationPartOpt PublicationRelInfo PublicationSchemaInfo PublicationTable +PublishGencolsType PullFilter PullFilterOps PushFilter PushFilterOps PushFunction PyCFunction -PyMappingMethods PyMethodDef PyModuleDef PyObject -PySequenceMethods PyTypeObject +PyType_Slot +PyType_Spec Py_ssize_t QPRS_STATE QTN2QTState @@ -2371,12 +2468,16 @@ RelFileLocator RelFileLocatorBackend RelFileNumber RelIdCacheEnt +RelIdToTypeIdCacheEntry RelInfo RelInfoArr RelMapFile RelMapping RelOptInfo RelOptKind +RelPathStr +RelStatsInfo +RelSyncCallbackFunction RelToCheck RelToCluster RelabelType @@ -2430,6 +2531,7 @@ RepOriginId ReparameterizeForeignPathByChild_function ReplaceVarsFromTargetList_context ReplaceVarsNoMatchOption +ReplaceWrapOption ReplicaIdentityStmt ReplicationKind ReplicationSlot @@ -2459,6 +2561,10 @@ ResultRelInfo ResultState ReturnSetInfo ReturnStmt +ReturningClause +ReturningExpr +ReturningOption +ReturningOptionKind RevmapContents RevokeRoleGrantAction RewriteMappingDataEntry @@ -2475,7 +2581,6 @@ RoleSpecType RoleStmtType RollupData RowCompareExpr -RowCompareType RowExpr RowIdentityVarInfo RowMarkClause @@ -2524,6 +2629,7 @@ SPPageDesc SQLDropObject SQLFunctionCache SQLFunctionCachePtr +SQLFunctionHashEntry SQLFunctionParseInfo SQLFunctionParseInfoPtr SQLValueFunction @@ -2535,6 +2641,7 @@ STARTUPINFO STRLEN SV SYNCHRONIZATION_BARRIER +SYSTEM_INFO SampleScan SampleScanGetSampleSize_function SampleScanState @@ -2566,12 +2673,15 @@ SeenRelsEntry SelectLimit SelectStmt Selectivity +SelfJoinCandidate SemTPadded SemiAntiJoinFactors SeqScan SeqScanState SeqTable SeqTableData +SeqType +SequenceItem SerCommitSeqNo SerialControl SerialIOData @@ -2597,11 +2707,14 @@ SetOpCmd SetOpPath SetOpState SetOpStatePerGroup +SetOpStatePerGroupData +SetOpStatePerInput SetOpStrategy SetOperation SetOperationStmt SetQuantifier SetToDefault +SetVarReturningType_context SetupWorkerPtrType ShDependObjectInfo SharedAggInfo @@ -2613,8 +2726,10 @@ SharedExecutorInstrumentation SharedFileSet SharedHashInfo SharedIncrementalSortInfo +SharedIndexScanInstrumentation SharedInvalCatalogMsg SharedInvalCatcacheMsg +SharedInvalRelSyncMsg SharedInvalRelcacheMsg SharedInvalRelmapMsg SharedInvalSmgrMsg @@ -2651,12 +2766,14 @@ SimpleStats SimpleStringList SimpleStringListCell SingleBoundSortItem -SinglePartitionSpec Size SkipPages +SkipSupport +SkipSupportIncDec SlabBlock SlabContext SlabSlot +SlotInvalidationCauseMap SlotNumber SlotSyncCtxStruct SlruCtl @@ -2716,7 +2833,6 @@ SpinDelayStatus SplitInterval SplitLR SplitPageLayout -SplitPartitionContext SplitPoint SplitTextOutputData SplitVar @@ -2774,6 +2890,7 @@ SubscriptionRelState SummarizerReadLocalXLogPrivate SupportRequestCost SupportRequestIndexCondition +SupportRequestModifyInPlace SupportRequestOptimizeWindowClause SupportRequestRows SupportRequestSelectivity @@ -2799,10 +2916,12 @@ TAR_MEMBER TBMIterateResult TBMIteratingState TBMIterator +TBMPrivateIterator TBMSharedIterator TBMSharedIteratorState TBMStatus TBlockState +TCPattern TIDBitmap TM_FailureData TM_IndexDelete @@ -2876,6 +2995,7 @@ TarMethodData TarMethodFile TargetEntry TclExceptionNameMap +Tcl_CmdInfo Tcl_DString Tcl_FileProc Tcl_HashEntry @@ -2883,6 +3003,7 @@ Tcl_HashTable Tcl_Interp Tcl_NotifierProcs Tcl_Obj +Tcl_Size Tcl_Time TempNamespaceStatus TestDSMRegistryStruct @@ -3008,6 +3129,7 @@ TypeCat TypeFuncClass TypeInfo TypeName +TzAbbrevCache U32 U8 UChar @@ -3027,12 +3149,19 @@ UnicodeNormalizationQC Unique UniquePath UniquePathMethod +UniqueRelInfo UniqueState UnlistenStmt UnresolvedTup UnresolvedTupData UpdateContext UpdateStmt +UpgradeTask +UpgradeTaskProcessCB +UpgradeTaskReport +UpgradeTaskSlot +UpgradeTaskSlotState +UpgradeTaskStep UploadManifestCmd UpperRelationKind UpperUniquePath @@ -3051,12 +3180,18 @@ VacuumRelation VacuumStmt ValidIOData ValidateIndexState +ValidatorModuleResult +ValidatorModuleState +ValidatorShutdownCB +ValidatorStartupCB +ValidatorValidateCB ValuesScan ValuesScanState Var VarBit VarChar VarParamState +VarReturningType VarString VarStringSortSupport Variable @@ -3254,9 +3389,9 @@ _resultmap _stringlist access_vector_t acquireLocksOnSubLinks_context +addFkConstraintSides add_nulling_relids_context adjust_appendrel_attrs_context -allocfunc amadjustmembers_function ambeginscan_function ambuild_function @@ -3268,6 +3403,7 @@ amcostestimate_function amendscan_function amestimateparallelscan_function amgetbitmap_function +amgettreeheight_function amgettuple_function aminitparallelscan_function aminsert_function @@ -3278,11 +3414,27 @@ amparallelrescan_function amproperty_function amrescan_function amrestrpos_function +amtranslate_cmptype_function +amtranslate_strategy_function amvacuumcleanup_function amvalidate_function array_iter array_unnest_fctx assign_collations_context +astreamer +astreamer_archive_context +astreamer_extractor +astreamer_gzip_decompressor +astreamer_gzip_writer +astreamer_lz4_frame +astreamer_member +astreamer_ops +astreamer_plain_writer +astreamer_recovery_injector +astreamer_tar_archiver +astreamer_tar_parser +astreamer_verify +astreamer_zstd_frame auth_password_hook_typ autovac_table av_relation @@ -3309,19 +3461,6 @@ bbsink_shell bbsink_state bbsink_throttle bbsink_zstd -bbstreamer -bbstreamer_archive_context -bbstreamer_extractor -bbstreamer_gzip_decompressor -bbstreamer_gzip_writer -bbstreamer_lz4_frame -bbstreamer_member -bbstreamer_ops -bbstreamer_plain_writer -bbstreamer_recovery_injector -bbstreamer_tar_archiver -bbstreamer_tar_parser -bbstreamer_zstd_frame bgworker_main_type bh_node_type binaryheap @@ -3350,17 +3489,24 @@ check_function_callback check_network_data check_object_relabel_type check_password_hook_type -check_ungrouped_columns_context child_process_kind chr cmpEntriesArg codes_t collation_cache_entry +collation_cache_hash color colormaprange compare_context config_handle config_var_value +conn_errorMessage_func +conn_oauth_client_id_func +conn_oauth_client_secret_func +conn_oauth_discovery_uri_func +conn_oauth_issuer_id_func +conn_oauth_scope_func +conn_sasl_state_func contain_aggs_of_level_context contain_placeholder_references_context convert_testexpr_context @@ -3371,11 +3517,15 @@ core_yy_extra_type core_yyscan_t corrupt_items cost_qual_eval_context +count_param_references_context cp_hash_func create_upper_paths_hook_type createdb_failure_params crosstab_HashEnt crosstab_cat_desc +curl_infotype +curl_socket_t +curl_version_info_data datapagemap_iterator_t datapagemap_t dateKEY @@ -3387,9 +3537,8 @@ deparse_columns deparse_context deparse_expr_cxt deparse_namespace -destructor +derives_hash dev_t -digit disassembledLeaf dlist_head dlist_iter @@ -3427,21 +3576,27 @@ dsm_handle dsm_op dsm_segment dsm_segment_detach_callback +duration eLogType ean13 eary ec_matches_callback_type ec_member_foreign_arg ec_member_matches_arg +element_type emit_log_hook_type eval_const_expressions_context exec_thread_arg execution_state exit_function explain_get_index_name_hook_type +explain_per_node_hook_type +explain_per_plan_hook_type +explain_validate_options_hook_type f_smgr fasthash_state fd_set +fe_oauth_state fe_scram_state fe_scram_state_enum fetch_range_request @@ -3455,6 +3610,7 @@ fill_string_relopt finalize_primnode_context find_dependent_phvs_context find_expr_references_context +fireRIRonSubLink_context fix_join_expr_context fix_scan_expr_context fix_upper_expr_context @@ -3519,7 +3675,6 @@ gss_key_value_set_desc gss_name_t gtrgm_consistent_cache gzFile -hashfunc hbaPort heap_page_items_state help_handler @@ -3541,17 +3696,21 @@ init_function inline_cte_walker_context inline_error_callback_arg ino_t +inquiry instr_time int128 int16 int16KEY +int16_t int2vector int32 int32KEY int32_t int64 int64KEY +int64_t int8 +int8_t int8x16_t internalPQconninfoOption intptr_t @@ -3575,16 +3734,20 @@ json_manifest_version_callback json_ofield_action json_scalar_action json_struct_action +keepwal_entry +keepwal_hash keyEntryData key_t lclContext lclTocEntry leafSegmentInfo leaf_item +libpq_gettext_func libpq_source line_t lineno_t list_sort_comparator +loc_chunk local_relopt local_relopts local_source @@ -3636,10 +3799,12 @@ mxact mxtruncinfo needs_fmgr_hook_type network_sortsupport_state +nl_item nodeitem normal_rand_fctx nsphash_hash ntile_context +nullingrel_info numeric object_access_hook_type object_access_hook_type_str @@ -3652,6 +3817,7 @@ openssl_tls_init_hook_typ ossl_EVP_cipher_func other output_type +overexplain_options pagetable_hash pagetable_iterator pairingheap @@ -3661,6 +3827,9 @@ pam_handle_t parallel_worker_main_type parse_error_callback_arg partition_method_t +pe_test_config +pe_test_escape_func +pe_test_vector pendingPosition pending_label pgParameterStatus @@ -3668,7 +3837,6 @@ pg_atomic_flag pg_atomic_uint32 pg_atomic_uint64 pg_be_sasl_mech -pg_case_map pg_category_range pg_checksum_context pg_checksum_raw_context @@ -3692,7 +3860,6 @@ pg_funcptr_t pg_gssinfo pg_hmac_ctx pg_hmac_errno -pg_int64 pg_local_to_utf_combined pg_locale_t pg_mb_radix_tree @@ -3710,6 +3877,7 @@ pg_sha256_ctx pg_sha384_ctx pg_sha512_ctx pg_snapshot +pg_special_case pg_stack_base_t pg_time_t pg_time_usec_t @@ -3760,7 +3928,8 @@ plperl_query_entry plpgsql_CastExprHashEntry plpgsql_CastHashEntry plpgsql_CastHashKey -plpgsql_HashEnt +plpgsql_expr_walker_callback +plpgsql_stmt_walker_callback pltcl_call_state pltcl_interp_desc pltcl_proc_desc @@ -3783,7 +3952,6 @@ printTextLineFormat printTextLineWrap printTextRule printXheaderWidthType -printfunc priv_map process_file_callback_t process_sublinks_context @@ -3823,12 +3991,9 @@ reduce_outer_joins_pass1_state reduce_outer_joins_pass2_state reference regex_arc_t -regex_t regexp regexp_matches_ctx registered_buffer -regmatch_t -regoff_t regproc relopt_bool relopt_enum @@ -3847,6 +4012,7 @@ remoteConnHashEnt remoteDep remove_nulling_relids_context rendezvousHashEntry +rep replace_rte_variables_callback replace_rte_variables_context report_error_fn @@ -3865,12 +4031,16 @@ rt_node_class_test_elem rt_radix_tree saophash_hash save_buffer +save_locale_t scram_state scram_state_enum +script_error_callback_arg security_class_t sem_t sepgsql_context_info_t sequence_magic +set_conn_altsock_func +set_conn_oauth_token_func set_join_pathlist_hook_type set_rel_pathlist_hook_type shared_ts_iter @@ -3937,10 +4107,12 @@ stream_stop_callback string substitute_actual_parameters_context substitute_actual_srf_parameters_context +substitute_grouped_columns_context substitute_phv_relids_context subxids_array_status symbol tablespaceinfo +tar_file td_entry teSection temp_tablespaces_extra @@ -3989,6 +4161,7 @@ uint32_t uint32x4_t uint64 uint64_t +uint64x2_t uint8 uint8_t uint8x16_t @@ -4140,6 +4313,7 @@ xmlGenericErrorFunc xmlNodePtr xmlNodeSetPtr xmlParserCtxtPtr +xmlParserErrors xmlParserInputPtr xmlSaveCtxt xmlSaveCtxtPtr diff --git a/src/tools/testint128.c b/src/tools/testint128.c index 4613ef0a50d45..a25631e277d2e 100644 --- a/src/tools/testint128.c +++ b/src/tools/testint128.c @@ -6,7 +6,7 @@ * This is a standalone test program that compares the behavior of an * implementation in int128.h to an (assumed correct) int128 native type. * - * Copyright (c) 2017-2024, PostgreSQL Global Development Group + * Copyright (c) 2017-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/tools/testwrap b/src/tools/testwrap index 9a270beb72d2a..02f1951ad7e94 100755 --- a/src/tools/testwrap +++ b/src/tools/testwrap @@ -13,6 +13,7 @@ parser.add_argument('--basedir', help='base directory of test', type=str) parser.add_argument('--testgroup', help='test group', type=str) parser.add_argument('--testname', help='test name', type=str) parser.add_argument('--skip', help='skip test (with reason)', type=str) +parser.add_argument('--pg-test-extra', help='extra tests', type=str) parser.add_argument('test_command', nargs='*') args = parser.parse_args() @@ -41,6 +42,15 @@ env_dict = {**os.environ, 'TESTDATADIR': os.path.join(testdir, 'data'), 'TESTLOGDIR': os.path.join(testdir, 'log')} + +# The configuration time value of PG_TEST_EXTRA is supplied via argument +# --pg-test-extra. But it can be overridden by environment variable +# PG_TEST_EXTRA at the time of running a test. Hence use value from arguments +# only if PG_TEST_EXTRA is not set in the test environment, which already +# contains all the environment variables at the time of running the test. +if "PG_TEST_EXTRA" not in env_dict and args.pg_test_extra: + env_dict["PG_TEST_EXTRA"] = args.pg_test_extra + sp = subprocess.Popen(args.test_command, env=env_dict, stdout=subprocess.PIPE) # Meson categorizes a passing TODO test point as bad # (https://github.com/mesonbuild/meson/issues/13183). Remove the TODO @@ -51,6 +61,7 @@ for line in sp.stdout: if line.startswith(b'ok '): line = line.replace(b' # TODO ', b' # testwrap-overridden-TODO ', 1) sys.stdout.buffer.write(line) + sys.stdout.flush() returncode = sp.wait() if returncode == 0: diff --git a/src/tools/version_stamp.pl b/src/tools/version_stamp.pl index 3743ece299633..c3509474d83b2 100755 --- a/src/tools/version_stamp.pl +++ b/src/tools/version_stamp.pl @@ -3,7 +3,7 @@ ################################################################# # version_stamp.pl -- update version stamps throughout the source tree # -# Copyright (c) 2008-2024, PostgreSQL Global Development Group +# Copyright (c) 2008-2025, PostgreSQL Global Development Group # # src/tools/version_stamp.pl ################################################################# diff --git a/src/tools/win32tzlist.pl b/src/tools/win32tzlist.pl index 17d45b957058c..706b1f78f80b6 100755 --- a/src/tools/win32tzlist.pl +++ b/src/tools/win32tzlist.pl @@ -2,7 +2,7 @@ # # win32tzlist.pl -- compare Windows timezone information # -# Copyright (c) 2008-2024, PostgreSQL Global Development Group +# Copyright (c) 2008-2025, PostgreSQL Global Development Group # # src/tools/win32tzlist.pl ################################################################# diff --git a/src/tutorial/advanced.source b/src/tutorial/advanced.source index 0c68b3344c359..f46fced1a5f32 100644 --- a/src/tutorial/advanced.source +++ b/src/tutorial/advanced.source @@ -10,6 +10,55 @@ -- --------------------------------------------------------------------------- +----------------------------- +-- Window Functions +----------------------------- + +-- a sample table +CREATE TABLE empsalary ( + depname text, + empno bigint, + salary int, + enroll_date date +); + +INSERT INTO empsalary VALUES +('develop', 10, 5200, '2007-08-01'), +('sales', 1, 5000, '2006-10-01'), +('personnel', 5, 3500, '2007-12-10'), +('sales', 4, 4800, '2007-08-08'), +('personnel', 2, 3900, '2006-12-23'), +('develop', 7, 4200, '2008-01-01'), +('develop', 9, 4500, '2008-01-01'), +('sales', 3, 4800, '2007-08-01'), +('develop', 8, 6000, '2006-10-01'), +('develop', 11, 5200, '2007-08-15'); + +SELECT depname, empno, salary, avg(salary) OVER (PARTITION BY depname) + FROM empsalary; + +SELECT depname, empno, salary, + row_number() OVER (PARTITION BY depname ORDER BY salary DESC) +FROM empsalary; + +SELECT salary, sum(salary) OVER () FROM empsalary; + +SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary; + +SELECT depname, empno, salary, enroll_date +FROM + (SELECT depname, empno, salary, enroll_date, + row_number() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos + FROM empsalary + ) AS ss +WHERE pos < 3; + +SELECT sum(salary) OVER w, avg(salary) OVER w + FROM empsalary + WINDOW w AS (PARTITION BY depname ORDER BY salary DESC); + +DROP TABLE empsalary; + ----------------------------- -- Inheritance: -- A table can inherit from zero or more tables. A query can reference diff --git a/src/tutorial/complex.source b/src/tutorial/complex.source index 8dcff724d45f3..7ae0359dcd91d 100644 --- a/src/tutorial/complex.source +++ b/src/tutorial/complex.source @@ -5,7 +5,7 @@ -- use this new type. -- -- --- Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +-- Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group -- Portions Copyright (c) 1994, Regents of the University of California -- -- src/tutorial/complex.source diff --git a/src/tutorial/funcs.c b/src/tutorial/funcs.c index f597777a1ffad..4a61177567c2b 100644 --- a/src/tutorial/funcs.c +++ b/src/tutorial/funcs.c @@ -11,6 +11,7 @@ #include "postgres.h" /* general Postgres declarations */ #include "executor/executor.h" /* for GetAttributeByName() */ +#include "utils/fmgrprotos.h" /* for text_starts_with() */ #include "utils/geo_decls.h" /* for point type */ PG_MODULE_MAGIC; @@ -102,6 +103,25 @@ concat_text(PG_FUNCTION_ARGS) PG_RETURN_TEXT_P(new_text); } +/* A wrapper around starts_with(text, text) */ + +PG_FUNCTION_INFO_V1(t_starts_with); + +Datum +t_starts_with(PG_FUNCTION_ARGS) +{ + text *t1 = PG_GETARG_TEXT_PP(0); + text *t2 = PG_GETARG_TEXT_PP(1); + Oid collid = PG_GET_COLLATION(); + bool result; + + result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with, + collid, + PointerGetDatum(t1), + PointerGetDatum(t2))); + PG_RETURN_BOOL(result); +} + /* Composite types */ PG_FUNCTION_INFO_V1(c_overpaid); diff --git a/src/tutorial/funcs.source b/src/tutorial/funcs.source index 542b5c81ec951..eb56153754220 100644 --- a/src/tutorial/funcs.source +++ b/src/tutorial/funcs.source @@ -123,16 +123,25 @@ SELECT * FROM EMP; ----------------------------- CREATE FUNCTION add_one(integer) RETURNS integer - AS '_OBJWD_/funcs' LANGUAGE C; + AS '_OBJWD_/funcs' LANGUAGE C STRICT; + +CREATE FUNCTION add_one(double precision) RETURNS double precision + AS '_OBJWD_/funcs' LANGUAGE C STRICT; CREATE FUNCTION makepoint(point, point) RETURNS point - AS '_OBJWD_/funcs' LANGUAGE C; + AS '_OBJWD_/funcs' LANGUAGE C STRICT; CREATE FUNCTION copytext(text) RETURNS text - AS '_OBJWD_/funcs' LANGUAGE C; + AS '_OBJWD_/funcs' LANGUAGE C STRICT; + +CREATE FUNCTION concat_text(text, text) RETURNS text + AS '_OBJWD_/funcs' LANGUAGE C STRICT; + +CREATE FUNCTION t_starts_with(text, text) RETURNS boolean + AS '_OBJWD_/funcs' LANGUAGE C STRICT; CREATE FUNCTION c_overpaid(EMP, integer) RETURNS boolean - AS '_OBJWD_/funcs' LANGUAGE C; + AS '_OBJWD_/funcs' LANGUAGE C STRICT; SELECT add_one(3) AS four; @@ -140,6 +149,8 @@ SELECT makepoint('(1,2)'::point, '(3,4)'::point ) AS newpoint; SELECT copytext('hello world!'); +SELECT t_starts_with('foobar', 'foo'); + SELECT name, c_overpaid(EMP, 1500) AS overpaid FROM EMP WHERE name = 'Bill' or name = 'Sam'; @@ -147,10 +158,13 @@ WHERE name = 'Bill' or name = 'Sam'; -- remove functions that were created in this file DROP FUNCTION c_overpaid(EMP, integer); +DROP FUNCTION t_starts_with(text, text); +DROP FUNCTION concat_text(text, text); DROP FUNCTION copytext(text); DROP FUNCTION makepoint(point, point); +DROP FUNCTION add_one(double precision); DROP FUNCTION add_one(integer); ---DROP FUNCTION clean_EMP(); +DROP FUNCTION clean_EMP(); DROP FUNCTION high_pay(); DROP FUNCTION new_emp(); DROP FUNCTION add_em(integer, integer); diff --git a/src/tutorial/syscat.source b/src/tutorial/syscat.source index 44d8602c72d09..21ee574fd9eae 100644 --- a/src/tutorial/syscat.source +++ b/src/tutorial/syscat.source @@ -4,7 +4,7 @@ -- sample queries to the system catalogs -- -- --- Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +-- Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group -- Portions Copyright (c) 1994, Regents of the University of California -- -- src/tutorial/syscat.source